From d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb Mon Sep 17 00:00:00 2001 From: Apple Date: Fri, 24 Oct 2014 20:43:47 +0000 Subject: [PATCH] Security-57031.1.35.tar.gz --- .call | 40 + ...mpty.c => .com.apple.timemachine.supported | 0 CircleJoinRequested/Applicant.h | 29 + CircleJoinRequested/Applicant.m | 79 + CircleJoinRequested/CircleJoinRequested.1 | 79 + CircleJoinRequested/CircleJoinRequested.m | 771 + CircleJoinRequested/Info.plist | 28 + CircleJoinRequested/NSArray+map.h | 15 + CircleJoinRequested/NSArray+map.m | 24 + .../NSDate+TimeIntervalDescription.h | 13 + .../NSDate+TimeIntervalDescription.m | 46 + CircleJoinRequested/PersistantState.h | 25 + CircleJoinRequested/PersistantState.m | 90 + CircleJoinRequested/Readme.txt | 0 ...m.apple.security.CircleJoinRequested.plist | 37 + CircleJoinRequested/entitlements.plist | 16 + .../CloudKeychainProxy-Info.plist | 6 +- CloudKeychainProxy/CloudKeychainProxy.1 | 79 + .../cloudkeychain.entitlements.plist | 24 - ...om.apple.security.cloudkeychainproxy.plist | 16 +- Default-568h@2x.png | Bin 0 -> 18594 bytes .../CloudKeychain.icns | Bin 159530 -> 0 bytes Keychain Circle Notification/KNAppDelegate.h | 22 - .../KNPersistantState.h | 23 - .../NSArray+mapWithBlock.h | 15 - .../NSArray+mapWithBlock.m | 24 - .../NSDictionary+compactDescription.h | 14 - .../NSDictionary+compactDescription.m | 52 - .../NSSet+compactDescription.h | 13 - .../NSSet+compactDescription.m | 26 - .../NSString+compactDescription.h | 13 - .../NSString+compactDescription.m | 30 - Keychain Circle Notification/main.m | 14 - Keychain/AppDelegate.h | 15 + Keychain/AppDelegate.m | 46 + Keychain/CircleStatusView.h | 25 + Keychain/CircleStatusView.m | 75 + Keychain/Default-568h@2x.png | Bin 0 -> 18594 bytes Keychain/Default.png | Bin 0 -> 6540 bytes Keychain/Default@2x.png | Bin 0 -> 16107 bytes Keychain/DeviceItemCell.h | 14 + Keychain/DeviceItemCell.m | 32 + Keychain/DeviceTableViewController.h | 20 + Keychain/DeviceTableViewController.m | 180 + Keychain/DeviceViewController.h | 13 + Keychain/DeviceViewController.m | 38 + Keychain/EditItemViewController.h | 22 + Keychain/EditItemViewController.m | 94 + Keychain/FirstViewController.h | 13 + Keychain/FirstViewController.m | 29 + Keychain/KCAItemDetailViewController.h | 22 + Keychain/KCAItemDetailViewController.m | 65 + Keychain/KCATableViewController.h | 26 + Keychain/KCATableViewController.m | 313 + Keychain/KDAppDelegate.h | 33 - Keychain/KDAppDelegate.m | 83 - Keychain/KDCirclePeer.h | 19 - Keychain/KDCirclePeer.m | 42 - Keychain/KDSecCircle.h | 35 - Keychain/KDSecItems.h | 18 - Keychain/Keychain-Entitlements.plist | 17 + Keychain/Keychain-Info.plist | 60 +- Keychain/KeychainItemCell.h | 23 + Keychain/KeychainItemCell.m | 49 + Keychain/KeychainKeys.png | Bin 0 -> 15193 bytes Keychain/MyKeychain.h | 26 + Keychain/MyKeychain.m | 347 + Keychain/NewPasswordViewController.h | 20 + Keychain/NewPasswordViewController.m | 62 + Keychain/PeerListCell.h | 16 + Keychain/PeerListCell.m | 34 + Keychain/SyncViewController.h | 34 + Keychain/SyncViewController.m | 241 + Keychain/ToolsViewController.h | 25 + Keychain/ToolsViewController.m | 180 + Keychain/first.png | Bin 0 -> 253 bytes Keychain/first@2x.png | Bin 0 -> 402 bytes Keychain/main.m | 10 +- Keychain/second.png | Bin 0 -> 128 bytes Keychain/second@2x.png | Bin 0 -> 130 bytes Keychain/utilities.c | 54 + Keychain/utilities.h | 34 + ...KeychainSyncAccountNotification-Info.plist | 28 + ...KeychainSyncAccountNotification-Prefix.pch | 7 + .../KeychainSyncAccountNotification.h | 15 + .../KeychainSyncAccountNotification.m | 80 + .../en.lproj/InfoPlist.strings | 0 Keychain_114x114.png | Bin 0 -> 17059 bytes Keychain_144x144.png | Bin 0 -> 22702 bytes Keychain_57x57.png | Bin 0 -> 8097 bytes Keychain_72x72.png | Bin 0 -> 10006 bytes .../OTAPKIAssetTool-entitlements.plist | 10 + OTAPKIAssetTool/OTAServiceApp.h | 46 + OTAPKIAssetTool/OTAServiceApp.m | 1384 ++ OTAPKIAssetTool/OTAServicemain.m | 47 + .../com.apple.OTAPKIAssetTool.plist | 37 + README | 47 +- README.genanchors | 14 + README.keychain | 32 + SecureObjectSync-Info.plist | 24 + SecureObjectSync.exp | 1 + Security-Info.plist | 24 + Security.exp-in | 173 + Security.xcodeproj/project.pbxproj | 11841 ++++++++++------ .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 140968 -> 0 bytes .../xcshareddata/xcschemes/Debug.xcscheme | 622 + .../xcschemes/ProtectedCloudStorage.xcscheme | 59 + .../xcshareddata/xcschemes/Release.xcscheme | 504 + .../xcshareddata/xcschemes/SyncTest.xcscheme | 86 + .../xcshareddata/xcschemes/SyncTest2.xcscheme | 86 + .../xcschemes/codesigntester.xcscheme | 84 + .../xcschemes/libsecurityd.xcscheme | 63 + .../xcshareddata/xcschemes/secdtests.xcscheme | 77 +- .../xcshareddata/xcschemes/security.xcscheme | 99 + .../xcshareddata/xcschemes/securityd.xcscheme | 81 + .../xcshareddata/xcschemes/sslEcdsa.xcscheme | 81 + .../xcshareddata/xcschemes/sslServer.xcscheme | 81 + .../xcshareddata/xcschemes/sslViewer.xcscheme | 81 + .../xcschemes/xcschememanagement.plist | 104 - APPLE_LICENSE => Security/APPLE_LICENSE | 0 Security/Breadcrumb/README | 99 + Security/Breadcrumb/SecBreadcrumb.c | 335 + Security/Breadcrumb/SecBreadcrumb.h | 61 + Security/Breadcrumb/bc-10-knife-on-bread.c | 88 + Security/Breadcrumb/breadcrumb_regressions.h | 7 + .../CloudKeychainProxy-Info.plist | 30 + .../cloudkeychain.entitlements.plist | 0 ...om.apple.security.cloudkeychainproxy.plist | 57 + .../en.lproj/InfoPlist.strings | 0 .../KNAppDelegate.h | 38 + .../KNAppDelegate.m | 53 +- .../KNPersistantState.h | 39 + .../KNPersistantState.m | 30 +- .../Keychain Circle Notification-Info.plist | 4 +- .../Keychain Circle Notification-Prefix.pch | 0 .../NSArray+mapWithBlock.h | 31 + .../NSArray+mapWithBlock.m | 40 + .../NSDictionary+compactDescription.h | 30 + .../NSDictionary+compactDescription.m | 68 + .../NSSet+compactDescription.h | 29 + .../NSSet+compactDescription.m | 42 + .../NSString+compactDescription.h | 29 + .../NSString+compactDescription.m | 46 + ...ecurity.keychain-circle-notification.plist | 7 +- .../en.lproj/Credits.rtf | 0 .../en.lproj/InfoPlist.strings | 0 .../en.lproj/Localizable.strings | Bin .../en.lproj/MainMenu.xib | 0 .../entitlments.plist | 0 Security/Keychain Circle Notification/main.m | 30 + {Keychain => Security/Keychain}/Icon.icns | Bin Security/Keychain/KDAppDelegate.h | 49 + Security/Keychain/KDAppDelegate.m | 99 + Security/Keychain/KDCirclePeer.h | 35 + Security/Keychain/KDCirclePeer.m | 58 + Security/Keychain/KDSecCircle.h | 51 + {Keychain => Security/Keychain}/KDSecCircle.m | 42 +- Security/Keychain/KDSecItems.h | 34 + {Keychain => Security/Keychain}/KDSecItems.m | 30 +- Security/Keychain/Keychain-Info.plist | 32 + .../Keychain}/Keychain-Prefix.pch | 0 .../Keychain}/en.lproj/Credits.rtf | 0 .../Keychain}/en.lproj/InfoPlist.strings | 0 .../Keychain}/en.lproj/MainMenu.xib | 0 Security/Keychain/main.m | 30 + Security/README | 29 + Security/Security.xcodeproj/project.pbxproj | 6513 +++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Security.xcscheme | 0 .../xcschemes/Security_executables.xcscheme | 0 .../xcschemes/Security_frameworks.xcscheme | 0 .../xcshareddata/xcschemes/World.xcscheme | 3 +- .../xcshareddata/xcschemes/authd.xcscheme | 0 .../xcschemes/copyHeaders.xcscheme | 0 .../xcshareddata/xcschemes/secd.xcscheme | 0 .../xcshareddata/xcschemes/secdtests.xcscheme | 128 + Security/asl/com.apple.securityd | 28 + Security/authd/Info.plist | 31 + {authd => Security/authd}/agent.c | 6 +- {authd => Security/authd}/agent.h | 2 +- {authd => Security/authd}/authd_private.h | 2 +- {authd => Security/authd}/authdb.c | 5 +- {authd => Security/authd}/authdb.h | 2 +- {authd => Security/authd}/authitems.c | 2 +- {authd => Security/authd}/authitems.h | 2 +- {authd => Security/authd}/authorization.plist | 200 +- {authd => Security/authd}/authtoken.c | 2 +- {authd => Security/authd}/authtoken.h | 2 +- {authd => Security/authd}/authtypes.h | 2 +- {authd => Security/authd}/authutilities.c | 2 +- {authd => Security/authd}/authutilities.h | 2 +- {authd => Security/authd}/ccaudit.c | 2 +- Security/authd/ccaudit.h | 26 + {authd => Security/authd}/com.apple.authd | 2 +- {authd => Security/authd}/com.apple.authd.sb | 0 {authd => Security/authd}/connection.c | 2 +- Security/authd/connection.h | 38 + {authd => Security/authd}/crc.c | 2 +- {authd => Security/authd}/crc.h | 2 +- {authd => Security/authd}/credential.c | 2 +- Security/authd/credential.h | 54 + Security/authd/debugging.c | 75 + Security/authd/debugging.h | 41 + .../authd}/en.lproj/InfoPlist.strings | 0 {authd => Security/authd}/engine.c | 124 +- {authd => Security/authd}/engine.h | 2 +- Security/authd/main.c | 208 + {authd => Security/authd}/mechanism.c | 2 +- {authd => Security/authd}/mechanism.h | 2 +- Security/authd/object.c | 5 + {authd => Security/authd}/object.h | 2 +- {authd => Security/authd}/process.c | 4 +- Security/authd/process.h | 102 + {authd => Security/authd}/rule.c | 2 +- {authd => Security/authd}/rule.h | 2 +- .../authd}/security.auth-Prefix.pch | 0 Security/authd/server.c | 1169 ++ Security/authd/server.h | 80 + {authd => Security/authd}/session.c | 2 +- Security/authd/session.h | 60 + .../cloud_keychain_diagnose-Prefix.pch | 0 .../codesign_tests}/FatDynamicValidation.c | 2 +- .../codesign_tests}/validation.sh | 0 Security/config/base.xcconfig | 14 + {config => Security/config}/command.xcconfig | 2 +- {config => Security/config}/debug.xcconfig | 0 .../config}/executable.xcconfig | 2 +- {config => Security/config}/lib.xcconfig | 0 {config => Security/config}/release.xcconfig | 0 {config => Security/config}/security.xcconfig | 2 +- {config => Security/config}/test.xcconfig | 0 {doc => Security/doc}/ACLsInCDSA.cwk | Bin {doc => Security/doc}/APIStrategy.cwk | Bin .../doc}/AccessControlArchitecture.cwk | Bin {doc => Security/doc}/AppleCL_Spec.doc | Bin {doc => Security/doc}/AppleCSP.doc | Bin {doc => Security/doc}/AppleTP_Spec.doc | Bin .../doc}/Apple_OID_Assignments.rtf | 0 .../doc}/ArchitectureOverview.cwk | Bin Security/doc/C++Utilities.cwk | 1019 ++ {doc => Security/doc}/DebuggingAids.cwk | Bin {doc => Security/doc}/HowToWriteA_CSP.cwk | Bin {doc => Security/doc}/HowToWriteA_Plugin.cwk | Bin {doc => Security/doc}/SecuritySupport.doc | Bin .../doc}/Supported_CSP_Algorithms.doc | Bin {doc => Security/doc}/cwk_styles | Bin {include => Security/include}/security_asn1 | 0 .../include}/security_cdsa_client | 0 .../include}/security_cdsa_plugin | 0 .../include}/security_cdsa_utilities | 0 .../include}/security_cdsa_utils | 0 .../include}/security_codesigning | 0 .../include}/security_comcryption | 0 .../include}/security_cryptkit | 0 {include => Security/include}/security_filedb | 0 .../include}/security_keychain | 0 {include => Security/include}/security_ocspd | 0 {include => Security/include}/security_pkcs12 | 0 {include => Security/include}/security_smime | 0 .../include}/security_utilities | 0 .../include}/securityd_client | 0 {lib => Security/lib}/FDEPrefs.plist | 0 {lib => Security/lib}/Info-Security.plist | 2 +- {lib => Security/lib}/Security.order | 0 {lib => Security/lib}/TimeStampingPrefs.plist | 0 {lib => Security/lib}/copy_pieces.mk | 2 +- {lib => Security/lib}/dummy.cpp | 0 .../lib}/en.lproj/FDELocalizable.strings | 0 .../lib}/en.lproj/InfoPlist.strings | Bin .../en.lproj/authorization.buttons.strings | 4 + .../en.lproj/authorization.prompts.strings | 8 +- {lib => Security/lib}/framework.sb | 0 Security/lib/generateErrStrings.pl | 343 + .../lib}/plugins/csparser-Info.plist | 2 +- {lib => Security/lib}/plugins/csparser.cpp | 2 +- {lib => Security/lib}/plugins/csparser.exp | 2 +- {lib => Security/lib}/security.exp-in | 62 +- .../Info-security_apple_csp.plist | 0 .../libsecurity_apple_csp}/README | 0 .../libsecurity_apple_csp}/TODO | 0 .../docs/libsecurity_apple_csp.plist | 0 .../docs/libsecurity_apple_csp.txt | 0 .../libsecurity_apple_csp}/lib/AppleCSP.cpp | 2 +- .../libsecurity_apple_csp}/lib/AppleCSP.h | 2 +- .../lib/AppleCSPBuiltin.cpp | 2 +- .../lib/AppleCSPContext.cpp | 2 +- .../lib/AppleCSPContext.h | 2 +- .../lib/AppleCSPKeys.cpp | 2 +- .../libsecurity_apple_csp}/lib/AppleCSPKeys.h | 2 +- .../lib/AppleCSPPlugin.cpp | 2 +- .../lib/AppleCSPSession.h | 2 +- .../lib/AppleCSPUtils.cpp | 2 +- .../lib/AppleCSPUtils.h | 2 +- .../libsecurity_apple_csp}/lib/BinaryKey.h | 2 +- .../lib/BlockCryptor.cpp | 3 +- .../libsecurity_apple_csp}/lib/BlockCryptor.h | 3 +- .../lib/CryptKitSpace.h | 3 +- .../libsecurity_apple_csp}/lib/DH_csp.cpp | 2 +- .../libsecurity_apple_csp}/lib/DH_csp.h | 2 +- .../lib/DH_exchange.cpp | 2 +- .../libsecurity_apple_csp}/lib/DH_exchange.h | 2 +- .../libsecurity_apple_csp}/lib/DH_keys.cpp | 2 +- .../libsecurity_apple_csp}/lib/DH_keys.h | 2 +- .../libsecurity_apple_csp}/lib/DH_utils.cpp | 2 +- .../libsecurity_apple_csp}/lib/DH_utils.h | 2 +- .../lib/DigestContext.cpp | 2 +- .../lib/DigestContext.h | 2 +- .../lib/FEEAsymmetricContext.cpp | 3 +- .../lib/FEEAsymmetricContext.h | 3 +- .../lib/FEECSPUtils.cpp | 3 +- .../libsecurity_apple_csp}/lib/FEECSPUtils.h | 3 +- .../libsecurity_apple_csp}/lib/FEEKeys.cpp | 3 +- .../libsecurity_apple_csp}/lib/FEEKeys.h | 3 +- .../lib/FEESignatureObject.cpp | 3 +- .../lib/FEESignatureObject.h | 2 +- .../libsecurity_apple_csp}/lib/HMACSHA1.c | 5 +- .../libsecurity_apple_csp}/lib/HMACSHA1.h | 5 +- .../libsecurity_apple_csp}/lib/MD2Object.cpp | 2 +- .../libsecurity_apple_csp}/lib/MD2Object.h | 2 +- .../libsecurity_apple_csp}/lib/MacContext.cpp | 2 +- .../libsecurity_apple_csp}/lib/MacContext.h | 2 +- .../libsecurity_apple_csp}/lib/NullCryptor.h | 3 +- .../lib/RSA_DSA_csp.cpp | 2 +- .../libsecurity_apple_csp}/lib/RSA_DSA_csp.h | 2 +- .../lib/RSA_DSA_keys.cpp | 2 +- .../libsecurity_apple_csp}/lib/RSA_DSA_keys.h | 2 +- .../lib/RSA_DSA_signature.cpp | 2 +- .../lib/RSA_DSA_signature.h | 2 +- .../lib/RSA_DSA_utils.cpp | 2 +- .../lib/RSA_DSA_utils.h | 2 +- .../lib/RSA_asymmetric.cpp | 2 +- .../lib/RSA_asymmetric.h | 2 +- .../libsecurity_apple_csp}/lib/RawSigner.h | 2 +- .../lib/SHA1_MD5_Object.cpp | 3 +- .../lib/SHA1_MD5_Object.h | 3 +- .../lib/SHA2_Object.cpp | 4 +- .../libsecurity_apple_csp}/lib/SHA2_Object.h | 3 +- .../lib/SignatureContext.cpp | 2 +- .../lib/SignatureContext.h | 2 +- .../lib/YarrowConnection.cpp | 2 +- .../lib/YarrowConnection.h | 2 +- .../libsecurity_apple_csp}/lib/aesCommon.h | 2 +- .../libsecurity_apple_csp}/lib/aescsp.cpp | 3 +- .../libsecurity_apple_csp}/lib/aescspi.h | 2 +- .../libsecurity_apple_csp}/lib/algmaker.cpp | 2 +- .../libsecurity_apple_csp}/lib/ascContext.cpp | 24 +- .../libsecurity_apple_csp/lib/ascContext.h | 78 + .../libsecurity_apple_csp/lib/ascFactory.h | 53 + .../libsecurity_apple_csp}/lib/bfContext.cpp | 3 +- .../libsecurity_apple_csp}/lib/bfContext.h | 3 +- .../libsecurity_apple_csp}/lib/boxes-ref.c | 2 +- .../libsecurity_apple_csp/lib/boxes-ref.h | 51 + .../lib/bsafeAsymmetric.cpp | 2 +- .../lib/bsafeContext.cpp | 2 +- .../lib/bsafeKeyGen.cpp | 2 +- .../libsecurity_apple_csp}/lib/bsafePKCS1.cpp | 2 +- .../libsecurity_apple_csp}/lib/bsafePKCS1.h | 2 +- .../lib/bsafeSymmetric.cpp | 2 +- .../libsecurity_apple_csp}/lib/bsafecsp.h | 2 +- .../libsecurity_apple_csp}/lib/bsafecspi.h | 2 +- .../libsecurity_apple_csp}/lib/bsobjects.h | 2 +- .../lib/castContext.cpp | 2 +- .../libsecurity_apple_csp}/lib/castContext.h | 3 +- .../lib/cryptkitcsp.cpp | 2 +- .../libsecurity_apple_csp}/lib/cryptkitcsp.h | 2 +- .../libsecurity_apple_csp}/lib/cspdebugging.c | 5 +- .../libsecurity_apple_csp}/lib/cspdebugging.h | 5 +- .../libsecurity_apple_csp}/lib/cssmplugin.exp | 0 .../libsecurity_apple_csp}/lib/deriveKey.cpp | 5 +- .../libsecurity_apple_csp}/lib/desContext.cpp | 3 +- .../libsecurity_apple_csp}/lib/desContext.h | 3 +- .../lib/gladmanContext.cpp | 3 +- .../lib/gladmanContext.h | 2 +- .../libsecurity_apple_csp}/lib/memory.cpp | 2 +- .../lib/miscAlgFactory.cpp | 3 +- .../lib/miscAlgFactory.h | 3 +- .../lib/miscalgorithms.cpp | 2 +- .../lib/opensshCoding.cpp | 3 +- .../lib/opensshCoding.h | 3 +- .../lib/opensshWrap.cpp | 3 +- .../libsecurity_apple_csp/lib/pbkdDigest.cpp | 84 + .../libsecurity_apple_csp/lib/pbkdDigest.h | 83 + Security/libsecurity_apple_csp/lib/pbkdf2.c | 99 + Security/libsecurity_apple_csp/lib/pbkdf2.h | 78 + .../lib/pkcs12Derive.cpp | 3 +- .../libsecurity_apple_csp}/lib/pkcs12Derive.h | 3 +- .../libsecurity_apple_csp}/lib/pkcs8.cpp | 2 +- .../libsecurity_apple_csp}/lib/pkcs8.h | 2 +- .../libsecurity_apple_csp}/lib/rc2Context.cpp | 3 +- .../libsecurity_apple_csp}/lib/rc2Context.h | 3 +- .../libsecurity_apple_csp}/lib/rc4Context.cpp | 3 +- .../libsecurity_apple_csp}/lib/rc4Context.h | 3 +- .../libsecurity_apple_csp}/lib/rc5Context.cpp | 3 +- .../libsecurity_apple_csp}/lib/rc5Context.h | 3 +- .../lib/rijndael-alg-ref.c | 619 + .../lib/rijndael-alg-ref.h | 82 + .../libsecurity_apple_csp/lib/rijndaelApi.c | 276 + .../libsecurity_apple_csp/lib/rijndaelApi.h | 119 + .../lib/vRijndael-alg-ref.c | 5 +- .../libsecurity_apple_csp}/lib/wrapKey.cpp | 2 +- .../libsecurity_apple_csp}/lib/wrapKeyCms.cpp | 2 +- .../project.pbxproj | 0 .../mds/csp_capabilities.mdsinfo | 0 .../mds/csp_capabilities_common.mds | 0 .../mds/csp_common.mdsinfo | 0 .../mds/csp_primary.mdsinfo | 0 .../libsecurity_apple_csp}/open_ssl/LICENSE | 0 .../open_ssl/bf/COPYRIGHT | 0 .../libsecurity_apple_csp}/open_ssl/bf/README | 0 .../open_ssl/bf/bf_ecb.c | 0 .../open_ssl/bf/bf_enc.c | 0 .../open_ssl/bf/bf_locl.h | 0 .../open_ssl/bf/bf_pi.h | 0 .../open_ssl/bf/bf_skey.c | 0 .../open_ssl/bio/bio_lib.c | 2 +- .../open_ssl/bio/bss_file.c | 2 +- .../open_ssl/bn/bn_add.c | 2 +- .../open_ssl/bn/bn_asm.c | 2 +- .../open_ssl/bn/bn_blind.c | 2 +- .../open_ssl/bn/bn_ctx.c | 2 +- .../open_ssl/bn/bn_div.c | 2 +- .../open_ssl/bn/bn_err.c | 2 +- .../open_ssl/bn/bn_exp.c | 0 .../open_ssl/bn/bn_exp2.c | 2 +- .../open_ssl/bn/bn_gcd.c | 2 +- .../open_ssl/bn/bn_lcl.h | 0 .../open_ssl/bn/bn_lib.c | 2 +- .../open_ssl/bn/bn_mont.c | 2 +- .../open_ssl/bn/bn_mpi.c | 2 +- .../open_ssl/bn/bn_mul.c | 2 +- .../open_ssl/bn/bn_prime.c | 2 +- .../open_ssl/bn/bn_prime.h | 2 +- .../open_ssl/bn/bn_print.c | 2 +- .../open_ssl/bn/bn_rand.c | 0 .../open_ssl/bn/bn_recp.c | 2 +- .../open_ssl/bn/bn_shift.c | 2 +- .../open_ssl/bn/bn_sqr.c | 2 +- .../open_ssl/bn/bn_word.c | 2 +- .../open_ssl/bn/bnspeed.c | 2 +- .../open_ssl/bn/bntest.c | 2 +- .../open_ssl/bn/divtest.c | 2 +- .../libsecurity_apple_csp}/open_ssl/bn/exp.c | 2 +- .../open_ssl/bn/expspeed.c | 2 +- .../open_ssl/bn/exptest.c | 2 +- .../open_ssl/bn/vms-helper.c | 2 +- .../open_ssl/buffer/buf_err.c | 2 +- .../open_ssl/buffer/buffer.c | 2 +- .../open_ssl/cryptlib.c | 2 +- .../open_ssl/cryptlib.h | 2 +- .../open_ssl/dh/dh_check.c | 2 +- .../open_ssl/dh/dh_err.c | 2 +- .../open_ssl/dh/dh_gen.c | 2 +- .../open_ssl/dh/dh_key.c | 2 +- .../open_ssl/dh/dh_lib.c | 2 +- .../open_ssl/dsa/dsa_asn1.c | 2 +- .../open_ssl/dsa/dsa_err.c | 2 +- .../open_ssl/dsa/dsa_gen.c | 2 +- .../open_ssl/dsa/dsa_key.c | 2 +- .../open_ssl/dsa/dsa_lib.c | 2 +- .../open_ssl/dsa/dsa_ossl.c | 2 +- .../open_ssl/dsa/dsa_sign.c | 2 +- .../open_ssl/dsa/dsa_vrf.c | 2 +- .../libsecurity_apple_csp}/open_ssl/err/err.c | 2 +- .../open_ssl/err/err_prn.c | 2 +- .../libsecurity_apple_csp}/open_ssl/ex_data.c | 2 +- .../open_ssl/lhash/lhash.c | 2 +- .../libsecurity_apple_csp}/open_ssl/mem.c | 2 +- .../open_ssl/misc/rc2_cbc.c | 2 +- .../open_ssl/misc/rc2_locl.h | 2 +- .../open_ssl/misc/rc2_skey.c | 2 +- .../open_ssl/misc/rc5_enc.c | 2 +- .../open_ssl/misc/rc5_locl.h | 2 +- .../open_ssl/misc/rc5_skey.c | 2 +- .../open_ssl/openssl/asn1.h | 2 +- .../open_ssl/openssl/bio.h | 2 +- .../open_ssl/openssl/blowfish.h | 0 .../open_ssl/openssl/bn.h | 2 +- .../open_ssl/openssl/buffer.h | 2 +- .../open_ssl/openssl/cast.h | 0 .../open_ssl/openssl/crypto.h | 2 +- .../open_ssl/openssl/dh.h | 2 +- .../open_ssl/openssl/dsa.h | 2 +- .../open_ssl/openssl/e_os.h | 2 +- .../open_ssl/openssl/e_os2.h | 2 +- .../open_ssl/openssl/err.h | 2 +- .../open_ssl/openssl/evp.h | 2 +- .../open_ssl/openssl/lhash.h | 2 +- .../open_ssl/openssl/objects.h | 2 +- .../open_ssl/openssl/openssl_pkcs7.h | 2 +- .../open_ssl/openssl/opensslconf.h | 4 +- .../open_ssl/openssl/opensslv.h | 2 +- .../open_ssl/openssl/rand.h | 2 +- .../open_ssl/openssl/rc2.h | 2 +- .../open_ssl/openssl/rc5.h | 2 +- .../open_ssl/openssl/rsa.h | 2 +- .../open_ssl/openssl/safestack.h | 2 +- .../open_ssl/openssl/stack.h | 2 +- .../open_ssl/openssl/x509.h | 2 +- .../open_ssl/openssl/x509_vfy.h | 2 +- .../open_ssl/opensslUtils/opensslAsn1.cpp | 2 +- .../open_ssl/opensslUtils/opensslAsn1.h | 2 +- .../open_ssl/opensslUtils/opensslUtils.cpp | 2 +- .../open_ssl/opensslUtils/opensslUtils.h | 2 +- .../open_ssl/rsa/rsa_chk.c | 2 +- .../open_ssl/rsa/rsa_eay.c | 2 +- .../open_ssl/rsa/rsa_err.c | 2 +- .../open_ssl/rsa/rsa_gen.c | 2 +- .../open_ssl/rsa/rsa_lib.c | 2 +- .../open_ssl/rsa/rsa_none.c | 2 +- .../open_ssl/rsa/rsa_null.c | 2 +- .../open_ssl/rsa/rsa_pk1.c | 2 +- .../open_ssl/rsa/rsa_saos.c | 2 +- .../open_ssl/rsa/rsa_sign.c | 2 +- .../open_ssl/rsa/rsa_ssl.c | 2 +- .../open_ssl/stack/stack.c | 2 +- .../libsecurity_apple_csp}/tests/t-dsa.cpp | 2 +- .../libsecurity_apple_csp}/tests/t-rsa.cpp | 2 +- .../libsecurity_apple_csp}/tests/t.cpp | 2 +- .../Info-security_apple_cspdl.plist | 0 .../lib/AppleCSPDLBuiltin.cpp | 2 +- .../lib/AppleCSPDLPlugin.cpp | 2 +- .../lib/CSPDLDatabase.cpp | 2 +- .../lib/CSPDLDatabase.h | 2 +- .../lib/CSPDLPlugin.cpp | 2 +- .../lib/CSPDLPlugin.h | 2 +- .../lib/SSCSPDLSession.cpp | 2 +- .../lib/SSCSPDLSession.h | 2 +- .../lib/SSCSPSession.cpp | 2 +- .../lib/SSCSPSession.h | 2 +- .../lib/SSContext.cpp | 2 +- .../libsecurity_apple_cspdl}/lib/SSContext.h | 2 +- .../lib/SSDLSession.cpp | 169 +- .../lib/SSDLSession.h | 2 +- .../lib/SSDatabase.cpp | 2 +- .../libsecurity_apple_cspdl}/lib/SSDatabase.h | 2 +- .../lib/SSFactory.cpp | 2 +- .../libsecurity_apple_cspdl}/lib/SSFactory.h | 2 +- .../libsecurity_apple_cspdl}/lib/SSKey.cpp | 2 +- .../libsecurity_apple_cspdl}/lib/SSKey.h | 2 +- .../project.pbxproj | 0 .../mds/cspdl_common.mdsinfo | 0 .../mds/cspdl_csp_capabilities.mdsinfo | 0 .../mds/cspdl_csp_primary.mdsinfo | 0 .../mds/cspdl_dl_primary.mdsinfo | 0 .../Info-security_apple_file_dl.plist | 0 .../libsecurity_apple_file_dl}/TODO | 0 .../libsecurity_apple_file_dl}/doc/FORMAT | 0 .../libsecurity_apple_file_dl}/doc/ISSUES | 0 .../lib/AppleDLBuiltin.cpp | 2 +- .../lib/AppleDLPlugin.cpp | 2 +- .../lib/AppleFileDL.cpp | 2 +- .../lib/AppleFileDL.h | 2 +- .../project.pbxproj | 0 .../mds/dl_common.mdsinfo | 0 .../mds/dl_primary.mdsinfo | 0 .../Info-plugin_apple_x509_cl.plist | 0 .../Info-security_apple_x509_cl.plist | 0 .../libsecurity_apple_x509_cl}/TODO | 0 .../lib/AppleX509CL.cpp | 2 +- .../lib/AppleX509CL.h | 2 +- .../lib/AppleX509CLBuiltin.cpp | 2 +- .../lib/AppleX509CLPlugin.cpp | 2 +- .../lib/AppleX509CLSession.cpp | 2 +- .../lib/AppleX509CLSession.h | 2 +- .../lib/CLCachedEntry.cpp | 5 +- .../lib/CLCachedEntry.h | 5 +- .../lib/CLCertExtensions.cpp | 2 +- .../lib/CLCertExtensions.h | 2 +- .../lib/CLCrlExtensions.cpp | 2 +- .../lib/CLCrlExtensions.h | 5 +- .../lib/CLFieldsCommon.cpp | 2 +- .../lib/CLFieldsCommon.h | 2 +- .../lib/CSPAttacher.cpp | 2 +- .../lib/CSPAttacher.h | 2 +- .../lib/CertFields.cpp | 5 +- .../lib/CrlFields.cpp | 5 +- .../lib/DecodedCert.cpp | 5 +- .../lib/DecodedCert.h | 5 +- .../lib/DecodedCrl.cpp | 3 +- .../lib/DecodedCrl.h | 3 +- .../lib/DecodedExtensions.cpp | 2 +- .../lib/DecodedExtensions.h | 2 +- .../lib/DecodedItem.cpp | 2 +- .../lib/DecodedItem.h | 2 +- .../lib/LockedMap.h | 5 +- .../lib/Session_CRL.cpp | 2 +- .../lib/Session_CSR.cpp | 2 +- .../lib/Session_Cert.cpp | 2 +- .../lib/Session_Crypto.cpp | 5 +- .../lib/clNameUtils.cpp | 2 +- .../lib/clNameUtils.h | 2 +- .../lib/clNssUtils.cpp | 2 +- .../lib/clNssUtils.h | 2 +- .../lib/cldebugging.h | 2 +- .../project.pbxproj | 0 .../mds/cl_common.mdsinfo | 0 .../mds/cl_primary.mdsinfo | 0 .../Info-security_apple_x509_tp.plist | 0 .../lib/AppleTP.cpp | 2 +- .../libsecurity_apple_x509_tp}/lib/AppleTP.h | 2 +- .../lib/AppleTPSession.cpp | 2 +- .../lib/AppleTPSession.h | 3 +- .../lib/AppleX509TPBuiltin.cpp | 2 +- .../lib/AppleX509TPPlugin.cpp | 2 +- .../lib/TPCertInfo.cpp | 68 +- .../lib/TPCertInfo.h | 2 +- .../lib/TPCrlInfo.cpp | 3 +- .../lib/TPCrlInfo.h | 3 +- .../lib/TPDatabase.cpp | 217 +- .../lib/TPDatabase.h | 3 +- .../lib/TPNetwork.cpp | 2 +- .../lib/TPNetwork.h | 3 +- .../lib/certGroupUtils.cpp | 79 +- .../lib/certGroupUtils.h | 20 +- .../libsecurity_apple_x509_tp/lib/cuEnc64.c | 587 + .../libsecurity_apple_x509_tp/lib/cuEnc64.h | 77 + .../lib/ocspRequest.cpp | 214 + .../lib/ocspRequest.h | 83 + .../lib/tpCertGroup.cpp | 6 +- .../lib/tpCredRequest.cpp | 3 +- .../lib/tpCrlVerify.cpp | 2 +- .../lib/tpCrlVerify.h | 3 +- .../lib/tpOcspCache.cpp | 2 +- .../lib/tpOcspCache.h | 2 +- .../lib/tpOcspCertVfy.cpp | 2 +- .../lib/tpOcspCertVfy.h | 2 +- .../lib/tpOcspVerify.cpp | 2 +- .../lib/tpOcspVerify.h | 2 +- .../lib/tpPolicies.cpp | 130 +- .../lib/tpPolicies.h | 3 +- .../libsecurity_apple_x509_tp}/lib/tpTime.c | 3 +- .../libsecurity_apple_x509_tp}/lib/tpTime.h | 3 +- .../lib/tpdebugging.h | 2 +- .../project.pbxproj | 0 .../mds/tp_common.mdsinfo | 0 .../mds/tp_policyOids.mdsinfo | 0 .../mds/tp_primary.mdsinfo | 0 .../libsecurity_asn1}/APPLE_LICENSE | 0 .../libsecurity_asn1}/CHANGES.Apple | 0 .../Info-security_asn1.plist | 0 .../libsecurity_asn1}/Makefile | 0 .../MozillaPublicLicense1.1.html | 0 .../libsecurity_asn1}/Security | 0 .../libsecurity_asn1}/asn1/README | 0 .../libsecurity_asn1}/asn1/appleoids.asn | 0 .../libsecurity_asn1}/asn1/asn-useful.asn1 | 0 .../libsecurity_asn1}/asn1/pkcs1.asn1 | 0 .../libsecurity_asn1}/asn1/pkcs10.asn | 0 .../libsecurity_asn1}/asn1/pkcs1oids.asn | 0 .../libsecurity_asn1}/asn1/pkcs5.asn1 | 0 .../libsecurity_asn1}/asn1/pkcs7.asn | 0 .../libsecurity_asn1}/asn1/pkcs8.asn | 0 .../libsecurity_asn1}/asn1/pkcs9oids.asn | 0 .../libsecurity_asn1}/asn1/rfc3161.asn1 | 0 .../libsecurity_asn1}/asn1/sm_cms.asn | 0 .../libsecurity_asn1}/asn1/sm_ess.asn | 0 .../libsecurity_asn1}/asn1/sm_vdatypes.asn | 0 .../libsecurity_asn1}/asn1/sm_x411mtsas.asn | 0 .../libsecurity_asn1}/asn1/sm_x411ub.asn | 0 .../libsecurity_asn1}/asn1/sm_x501if.asn | 0 .../libsecurity_asn1}/asn1/sm_x501ud.asn | 0 .../libsecurity_asn1}/asn1/sm_x509af.asn | 0 .../libsecurity_asn1}/asn1/sm_x509ce.asn | 0 .../libsecurity_asn1}/asn1/sm_x509cmn.asn | 0 .../libsecurity_asn1}/asn1/sm_x520sa.asn | 0 .../libsecurity_asn1/config/base.xcconfig | 10 + .../libsecurity_asn1}/config/debug.xcconfig | 0 Security/libsecurity_asn1/config/lib.xcconfig | 39 + .../libsecurity_asn1}/config/release.xcconfig | 0 .../docs/libsecurity_asn1.plist | 0 .../docs/libsecurity_asn1.txt | 0 .../libsecurity_asn1}/lib/SecAsn1Coder.c | 2 +- .../libsecurity_asn1}/lib/SecAsn1Coder.h | 2 +- .../libsecurity_asn1}/lib/SecAsn1Templates.c | 2 +- .../libsecurity_asn1}/lib/SecAsn1Templates.h | 2 +- .../libsecurity_asn1}/lib/SecAsn1Types.h | 0 Security/libsecurity_asn1/lib/SecNssCoder.cpp | 194 + Security/libsecurity_asn1/lib/SecNssCoder.h | 161 + .../libsecurity_asn1}/lib/X509Templates.c | 2 +- .../libsecurity_asn1}/lib/X509Templates.h | 2 +- .../libsecurity_asn1}/lib/asn1Templates.h | 2 +- .../lib/certExtensionTemplates.c | 2 +- .../lib/certExtensionTemplates.h | 2 +- .../libsecurity_asn1}/lib/csrTemplates.c | 2 +- .../libsecurity_asn1}/lib/csrTemplates.h | 2 +- .../libsecurity_asn1}/lib/keyTemplates.c | 2 +- .../libsecurity_asn1}/lib/keyTemplates.h | 2 +- .../libsecurity_asn1}/lib/nameTemplates.c | 12 +- .../libsecurity_asn1}/lib/nameTemplates.h | 2 +- .../libsecurity_asn1}/lib/nsprPortX.c | 2 +- .../libsecurity_asn1}/lib/nssUtils.c | 2 +- .../libsecurity_asn1}/lib/nssUtils.h | 2 +- .../libsecurity_asn1}/lib/nssilckt.h | 0 .../libsecurity_asn1}/lib/nssilock.h | 0 .../libsecurity_asn1}/lib/nsslocks.h | 0 .../libsecurity_asn1}/lib/ocspTemplates.c | 2 +- .../libsecurity_asn1}/lib/ocspTemplates.h | 2 +- Security/libsecurity_asn1/lib/oidsalg.c | 501 + .../libsecurity_asn1}/lib/oidsalg.h | 9 +- .../libsecurity_asn1}/lib/oidsattr.c | 10 +- .../libsecurity_asn1}/lib/oidsattr.h | 2 +- Security/libsecurity_asn1/lib/oidsbase.h | 356 + .../libsecurity_asn1}/lib/oidsocsp.c | 2 +- .../libsecurity_asn1}/lib/oidsocsp.h | 2 +- .../libsecurity_asn1}/lib/osKeyTemplates.c | 2 +- .../libsecurity_asn1}/lib/osKeyTemplates.h | 2 +- .../libsecurity_asn1}/lib/pkcs12Templates.c | 2 +- .../libsecurity_asn1/lib/pkcs12Templates.h | 284 + .../libsecurity_asn1}/lib/pkcs7Templates.c | 2 +- .../libsecurity_asn1/lib/pkcs7Templates.h | 165 + .../libsecurity_asn1}/lib/plarena.c | 2 +- .../libsecurity_asn1}/lib/plarena.h | 0 .../libsecurity_asn1}/lib/plarenas.h | 0 .../libsecurity_asn1}/lib/plstr.h | 0 .../libsecurity_asn1}/lib/prbit.h | 0 .../libsecurity_asn1}/lib/prcpucfg.h | 0 .../libsecurity_asn1}/lib/prcvar.h | 0 .../libsecurity_asn1}/lib/prenv.h | 0 .../libsecurity_asn1}/lib/prerr.h | 0 .../libsecurity_asn1}/lib/prerror.h | 0 .../libsecurity_asn1}/lib/prinit.h | 0 .../libsecurity_asn1}/lib/prinrval.h | 0 .../libsecurity_asn1}/lib/prlock.h | 0 .../libsecurity_asn1}/lib/prlog.h | 0 .../libsecurity_asn1}/lib/prlong.h | 0 .../libsecurity_asn1}/lib/prmem.h | 0 .../libsecurity_asn1}/lib/prmon.h | 0 .../libsecurity_asn1}/lib/protypes.h | 0 .../libsecurity_asn1}/lib/prthread.h | 0 .../libsecurity_asn1}/lib/prtime.h | 0 .../libsecurity_asn1}/lib/prtypes.h | 0 .../libsecurity_asn1}/lib/prvrsion.h | 0 .../libsecurity_asn1}/lib/secErrorStr.c | 2 +- .../libsecurity_asn1}/lib/secasn1.h | 0 .../libsecurity_asn1}/lib/secasn1d.c | 20 +- .../libsecurity_asn1}/lib/secasn1e.c | 7 + .../libsecurity_asn1}/lib/secasn1t.h | 0 .../libsecurity_asn1}/lib/secasn1u.c | 0 .../libsecurity_asn1}/lib/seccomon.h | 0 .../libsecurity_asn1}/lib/secerr.h | 0 .../libsecurity_asn1}/lib/secport.c | 0 .../libsecurity_asn1}/lib/secport.h | 0 .../libsecurity_asn1}/lib/security_asn1.exp | 0 .../project.pbxproj | 477 + .../libsecurity_asn1}/security_asn1 | 0 .../libsecurity_authorization}/APPLE_LICENSE | 0 .../Info-security_authorization.plist | 0 .../lib/AuthSession.h | 2 +- .../lib/Authorization.c | 2 +- .../lib/Authorization.cpp | 2 +- .../lib/Authorization.h | 2 +- .../lib/AuthorizationDB.h | 2 +- .../lib/AuthorizationPlugin.h | 2 +- .../lib/AuthorizationPriv.h | 2 +- .../lib/AuthorizationTags.h | 2 +- .../lib/AuthorizationTagsPriv.h | 2 +- .../libsecurity_authorization}/lib/privPort.h | 2 +- .../lib/security_authorization.exp | 2 +- .../lib/trampolineClient.cpp | 2 +- .../lib/trampolineServer.cpp | 2 +- .../project.pbxproj | 0 .../Info-security_cdsa_client.plist | 0 .../libsecurity_cdsa_client}/lib/DLDBList.cpp | 2 +- .../libsecurity_cdsa_client}/lib/DLDBList.h | 2 +- .../lib/aclclient.cpp | 2 +- .../libsecurity_cdsa_client}/lib/aclclient.h | 2 +- .../libsecurity_cdsa_client}/lib/clclient.cpp | 2 +- .../libsecurity_cdsa_client}/lib/clclient.h | 2 +- .../lib/cryptoclient.cpp | 2 +- .../lib/cryptoclient.h | 2 +- .../lib/cspclient.cpp | 2 +- .../libsecurity_cdsa_client}/lib/cspclient.h | 2 +- .../lib/cssmclient.cpp | 2 +- .../libsecurity_cdsa_client}/lib/cssmclient.h | 2 +- .../lib/dl_standard.cpp | 2 +- .../lib/dl_standard.h | 2 +- .../libsecurity_cdsa_client}/lib/dlclient.cpp | 7 +- .../libsecurity_cdsa_client}/lib/dlclient.h | 2 +- .../lib/dlclientpriv.cpp | 2 +- .../lib/dliterators.cpp | 2 +- .../lib/dliterators.h | 2 +- .../libsecurity_cdsa_client}/lib/dlquery.cpp | 2 +- .../libsecurity_cdsa_client}/lib/dlquery.h | 2 +- .../libsecurity_cdsa_client}/lib/genkey.cpp | 2 +- .../libsecurity_cdsa_client}/lib/genkey.h | 2 +- .../lib/keychainacl.cpp | 2 +- .../lib/keychainacl.h | 2 +- .../lib/keyclient.cpp | 2 +- .../libsecurity_cdsa_client}/lib/keyclient.h | 2 +- .../lib/macclient.cpp | 2 +- .../libsecurity_cdsa_client}/lib/macclient.h | 2 +- .../lib/mds_standard.cpp | 2 +- .../lib/mds_standard.h | 2 +- .../lib/mdsclient.cpp | 2 +- .../libsecurity_cdsa_client}/lib/mdsclient.h | 2 +- .../lib/multidldb.cpp | 2 +- .../libsecurity_cdsa_client}/lib/multidldb.h | 2 +- .../lib/securestorage.cpp | 2 +- .../lib/securestorage.h | 2 +- .../lib/signclient.cpp | 2 +- .../libsecurity_cdsa_client}/lib/signclient.h | 2 +- .../libsecurity_cdsa_client}/lib/tpclient.cpp | 2 +- .../libsecurity_cdsa_client}/lib/tpclient.h | 2 +- .../libsecurity_cdsa_client}/lib/wrapkey.cpp | 2 +- .../libsecurity_cdsa_client}/lib/wrapkey.h | 2 +- .../project.pbxproj | 0 .../Info-security_cdsa_plugin.plist | 0 .../libsecurity_cdsa_plugin}/lib/ACsession.h | 2 +- .../libsecurity_cdsa_plugin}/lib/CLsession.h | 2 +- .../lib/CSPsession.cpp | 2 +- .../libsecurity_cdsa_plugin}/lib/CSPsession.h | 2 +- .../lib/DLsession.cpp | 2 +- .../libsecurity_cdsa_plugin}/lib/DLsession.h | 2 +- .../libsecurity_cdsa_plugin}/lib/Database.cpp | 2 +- .../libsecurity_cdsa_plugin}/lib/Database.h | 2 +- .../lib/DatabaseSession.cpp | 2 +- .../lib/DatabaseSession.h | 2 +- .../lib/DbContext.cpp | 2 +- .../libsecurity_cdsa_plugin}/lib/DbContext.h | 2 +- .../libsecurity_cdsa_plugin}/lib/TPsession.h | 2 +- .../libsecurity_cdsa_plugin}/lib/c++plugin.h | 2 +- .../lib/csputilities.cpp | 2 +- .../lib/cssmplugin.cpp | 2 +- .../libsecurity_cdsa_plugin}/lib/cssmplugin.h | 2 +- .../lib/generator.cfg | 0 .../libsecurity_cdsa_plugin}/lib/generator.mk | 0 .../libsecurity_cdsa_plugin}/lib/generator.pl | 0 .../lib/pluginsession.cpp | 2 +- .../lib/pluginsession.h | 2 +- .../libsecurity_cdsa_plugin}/lib/pluginspi.h | 2 +- .../project.pbxproj | 0 .../libsecurity_cdsa_utilities}/APPLE_LICENSE | 0 .../Info-security_cdsa_utilities.plist | 0 .../lib/AuthorizationData.cpp | 2 +- .../lib/AuthorizationData.h | 2 +- .../lib/AuthorizationWalkers.h | 2 +- .../lib/KeySchema.h | 2 +- .../lib/KeySchema.m4 | 2 +- .../libsecurity_cdsa_utilities}/lib/Schema.h | 2 +- .../libsecurity_cdsa_utilities}/lib/Schema.m4 | 7 +- .../lib/acl_any.cpp | 2 +- .../libsecurity_cdsa_utilities}/lib/acl_any.h | 2 +- .../lib/acl_codesigning.cpp | 2 +- .../lib/acl_codesigning.h | 2 +- .../lib/acl_comment.cpp | 2 +- .../lib/acl_comment.h | 2 +- .../lib/acl_password.cpp | 2 +- .../lib/acl_password.h | 2 +- .../lib/acl_preauth.cpp | 2 +- .../lib/acl_preauth.h | 2 +- .../lib/acl_process.cpp | 2 +- .../lib/acl_process.h | 2 +- .../lib/acl_prompted.cpp | 2 +- .../lib/acl_prompted.h | 2 +- .../lib/acl_protectedpw.cpp | 2 +- .../lib/acl_protectedpw.h | 2 +- .../lib/acl_secret.cpp | 2 +- .../lib/acl_secret.h | 2 +- .../lib/acl_threshold.cpp | 2 +- .../lib/acl_threshold.h | 2 +- .../lib/aclsubject.cpp | 2 +- .../lib/aclsubject.h | 2 +- .../lib/callback.cpp | 2 +- .../lib/callback.h | 2 +- .../lib/constdata.cpp | 2 +- .../lib/constdata.h | 2 +- .../lib/context.cpp | 2 +- .../libsecurity_cdsa_utilities}/lib/context.h | 27 +- .../lib/cssmacl.cpp | 2 +- .../libsecurity_cdsa_utilities}/lib/cssmacl.h | 2 +- .../lib/cssmaclpod.cpp | 2 +- .../lib/cssmaclpod.h | 2 +- .../lib/cssmalloc.cpp | 2 +- .../lib/cssmalloc.h | 2 +- .../lib/cssmbridge.h | 2 +- .../lib/cssmcert.cpp | 2 +- .../lib/cssmcert.h | 2 +- .../lib/cssmcred.cpp | 2 +- .../lib/cssmcred.h | 2 +- .../lib/cssmdata.cpp | 2 +- .../lib/cssmdata.h | 3 +- .../lib/cssmdates.cpp | 2 +- .../lib/cssmdates.h | 2 +- .../lib/cssmdb.cpp | 6 +- .../libsecurity_cdsa_utilities}/lib/cssmdb.h | 2 +- .../lib/cssmdbname.cpp | 2 +- .../lib/cssmdbname.h | 2 +- .../lib/cssmendian.cpp | 2 +- .../lib/cssmendian.h | 2 +- .../lib/cssmerrors.cpp | 2 +- .../lib/cssmerrors.h | 2 +- .../lib/cssmkey.cpp | 2 +- .../libsecurity_cdsa_utilities}/lib/cssmkey.h | 2 +- .../lib/cssmlist.cpp | 2 +- .../lib/cssmlist.h | 2 +- .../lib/cssmpods.cpp | 2 +- .../lib/cssmpods.h | 2 +- .../lib/cssmtrust.cpp | 2 +- .../lib/cssmtrust.h | 2 +- .../lib/cssmwalkers.cpp | 2 +- .../lib/cssmwalkers.h | 2 +- .../libsecurity_cdsa_utilities}/lib/db++.cpp | 2 +- .../libsecurity_cdsa_utilities}/lib/db++.h | 2 +- .../lib/digestobject.h | 2 +- .../lib/generator.mk | 0 .../lib/generator.pl | 0 .../lib/handleobject.cpp | 2 +- .../lib/handleobject.h | 2 +- .../lib/handletemplates.cpp | 2 +- .../lib/handletemplates.h | 2 +- .../lib/handletemplates_defs.h | 2 +- .../lib/objectacl.cpp | 2 +- .../lib/objectacl.h | 2 +- .../lib/osxverifier.cpp | 2 +- .../lib/osxverifier.h | 2 +- .../lib/u32handleobject.cpp | 2 +- .../lib/u32handleobject.h | 2 +- .../lib/uniformrandom.cpp | 2 +- .../lib/uniformrandom.h | 2 +- .../lib/walkers.cpp | 2 +- .../libsecurity_cdsa_utilities}/lib/walkers.h | 2 +- .../project.pbxproj | 0 .../Info-security_cdsa_utils.plist | 0 .../lib/cuCdsaUtils.cpp | 2 +- .../libsecurity_cdsa_utils}/lib/cuCdsaUtils.h | 2 +- .../libsecurity_cdsa_utils}/lib/cuDbUtils.cpp | 2 +- .../libsecurity_cdsa_utils}/lib/cuDbUtils.h | 2 +- Security/libsecurity_cdsa_utils/lib/cuEnc64.c | 392 + Security/libsecurity_cdsa_utils/lib/cuEnc64.h | 67 + .../libsecurity_cdsa_utils}/lib/cuFileIo.c | 2 +- .../libsecurity_cdsa_utils}/lib/cuFileIo.h | 2 +- .../lib/cuOidParser.cpp | 2 +- .../libsecurity_cdsa_utils}/lib/cuOidParser.h | 2 +- .../libsecurity_cdsa_utils}/lib/cuPem.cpp | 2 +- .../libsecurity_cdsa_utils}/lib/cuPem.h | 2 +- .../lib/cuPrintCert.cpp | 2 +- .../libsecurity_cdsa_utils}/lib/cuPrintCert.h | 2 +- .../libsecurity_cdsa_utils}/lib/cuTimeStr.cpp | 2 +- .../libsecurity_cdsa_utils}/lib/cuTimeStr.h | 2 +- .../project.pbxproj | 0 .../libsecurity_checkpw}/APPLE_LICENSE | 0 .../Info-security_checkpw.plist | 0 .../libsecurity_checkpw}/checkpw.pam | 0 .../libsecurity_checkpw}/lib/checkpw.c | 2 +- .../libsecurity_checkpw}/lib/checkpw.h | 2 +- .../lib/security_checkpw.exp | 0 .../project.pbxproj | 0 .../libsecurity_checkpw}/test/perf-checkpw.c | 0 .../libsecurity_checkpw}/test/test-checkpw.c | 0 .../libsecurity_cms}/APPLE_LICENSE | 0 .../libsecurity_cms}/Info-security_cms.plist | 0 .../libsecurity_cms}/lib/CMSDecoder.cpp | 20 +- .../libsecurity_cms}/lib/CMSDecoder.h | 19 +- .../libsecurity_cms}/lib/CMSEncoder.cpp | 17 +- .../libsecurity_cms}/lib/CMSEncoder.h | 9 +- .../libsecurity_cms}/lib/CMSPrivate.h | 2 +- .../libsecurity_cms}/lib/CMSUtils.cpp | 3 +- .../libsecurity_cms}/lib/CMSUtils.h | 2 +- .../libsecurity_cms}/lib/security_cms.exp | 4 + .../libsecurity_cms.xcodeproj/project.pbxproj | 0 .../libsecurity_codesigning}/APPLE_LICENSE | 0 .../CodeSigningHelper-Info.plist | 0 .../com.apple.CodeSigningHelper.sb | 0 .../CodeSigningHelper/main.c | 194 + .../Info-security_codesigning.plist | 0 .../libsecurity_codesigning}/antlr2/AUTHORS | 0 .../libsecurity_codesigning}/antlr2/ChangeLog | 0 .../antlr2/LICENSE.txt | 0 .../antlr2/Makefile.in | 0 .../libsecurity_codesigning}/antlr2/README | 0 .../libsecurity_codesigning}/antlr2/TODO | 0 .../libsecurity_codesigning}/antlr2/antlr.jar | Bin .../antlr2/antlr/ANTLRException.hpp | 0 .../antlr2/antlr/ANTLRUtil.hpp | 0 .../antlr2/antlr/AST.hpp | 0 .../antlr2/antlr/ASTArray.hpp | 0 .../antlr2/antlr/ASTFactory.hpp | 0 .../antlr2/antlr/ASTNULLType.hpp | 0 .../antlr2/antlr/ASTPair.hpp | 0 .../antlr2/antlr/ASTRefCount.hpp | 0 .../antlr2/antlr/BaseAST.hpp | 0 .../antlr2/antlr/BitSet.hpp | 0 .../antlr2/antlr/CharBuffer.hpp | 0 .../antlr2/antlr/CharInputBuffer.hpp | 0 .../antlr2/antlr/CharScanner.hpp | 0 .../antlr2/antlr/CharStreamException.hpp | 0 .../antlr2/antlr/CharStreamIOException.hpp | 0 .../antlr2/antlr/CircularQueue.hpp | 0 .../antlr2/antlr/CommonAST.hpp | 0 .../antlr/CommonASTWithHiddenTokens.hpp | 0 .../antlr2/antlr/CommonHiddenStreamToken.hpp | 0 .../antlr2/antlr/CommonToken.hpp | 0 .../antlr2/antlr/IOException.hpp | 0 .../antlr2/antlr/InputBuffer.hpp | 0 .../antlr2/antlr/LLkParser.hpp | 0 .../antlr2/antlr/LexerSharedInputState.hpp | 0 .../antlr2/antlr/Makefile.in | 0 .../antlr2/antlr/MismatchedCharException.hpp | 0 .../antlr2/antlr/MismatchedTokenException.hpp | 0 .../antlr2/antlr/NoViableAltException.hpp | 0 .../antlr/NoViableAltForCharException.hpp | 0 .../antlr2/antlr/Parser.hpp | 0 .../antlr2/antlr/ParserSharedInputState.hpp | 0 .../antlr2/antlr/RecognitionException.hpp | 0 .../antlr2/antlr/RefCount.hpp | 0 .../antlr2/antlr/SemanticException.hpp | 0 .../antlr2/antlr/String.hpp | 0 .../antlr2/antlr/Token.hpp | 0 .../antlr2/antlr/TokenBuffer.hpp | 0 .../antlr2/antlr/TokenRefCount.hpp | 0 .../antlr2/antlr/TokenStream.hpp | 0 .../antlr2/antlr/TokenStreamBasicFilter.hpp | 0 .../antlr2/antlr/TokenStreamException.hpp | 0 .../antlr/TokenStreamHiddenTokenFilter.hpp | 0 .../antlr2/antlr/TokenStreamIOException.hpp | 0 .../antlr/TokenStreamRecognitionException.hpp | 0 .../antlr/TokenStreamRetryException.hpp | 0 .../antlr2/antlr/TokenStreamRewriteEngine.hpp | 0 .../antlr2/antlr/TokenStreamSelector.hpp | 0 .../antlr2/antlr/TokenWithIndex.hpp | 0 .../antlr2/antlr/TreeParser.hpp | 0 .../antlr/TreeParserSharedInputState.hpp | 0 .../antlr2/antlr/config.hpp | 0 .../antlr2/contrib/bcb4/README | 0 .../antlr2/contrib/bcb4/antlr.bpr | 0 .../antlr2/contrib/bcb4/antlr.cpp | 0 .../antlr2/doxygen.cfg | 0 .../antlr2/libsecurity_codesigning.plist | 0 .../antlr2/libsecurity_codesigning.txt | 0 .../antlr2/scripts/cr_stripper.sh | 0 .../antlr2/scripts/make_change_log.tcl | 0 .../antlr2/src/ANTLRUtil.cpp | 0 .../antlr2/src/ASTFactory.cpp | 0 .../antlr2/src/ASTNULLType.cpp | 0 .../antlr2/src/ASTRefCount.cpp | 0 .../antlr2/src/BaseAST.cpp | 0 .../antlr2/src/BitSet.cpp | 0 .../antlr2/src/CharBuffer.cpp | 0 .../antlr2/src/CharScanner.cpp | 0 .../antlr2/src/CommonAST.cpp | 0 .../antlr2/src/CommonASTWithHiddenTokens.cpp | 0 .../antlr2/src/CommonHiddenStreamToken.cpp | 0 .../antlr2/src/CommonToken.cpp | 0 .../antlr2/src/InputBuffer.cpp | 0 .../antlr2/src/LLkParser.cpp | 0 .../antlr2/src/Makefile.in | 0 .../antlr2/src/MismatchedCharException.cpp | 0 .../antlr2/src/MismatchedTokenException.cpp | 0 .../antlr2/src/NoViableAltException.cpp | 0 .../src/NoViableAltForCharException.cpp | 0 .../antlr2/src/Parser.cpp | 0 .../antlr2/src/RecognitionException.cpp | 0 .../antlr2/src/String.cpp | 0 .../antlr2/src/Token.cpp | 0 .../antlr2/src/TokenBuffer.cpp | 0 .../antlr2/src/TokenRefCount.cpp | 0 .../antlr2/src/TokenStreamBasicFilter.cpp | 0 .../src/TokenStreamHiddenTokenFilter.cpp | 0 .../antlr2/src/TokenStreamRewriteEngine.cpp | 0 .../antlr2/src/TokenStreamSelector.cpp | 0 .../antlr2/src/TreeParser.cpp | 0 .../antlr2/src/dll.cpp | 0 .../dtrace/codesign-watch.d | 0 .../libsecurity_codesigning}/dtrace/reqint.d | 0 .../dtrace/sp-watch.d | 0 .../gke/com.apple.gkreport.plist | 0 .../libsecurity_codesigning}/gke/gkclear | 0 .../libsecurity_codesigning}/gke/gkgenerate | 0 .../libsecurity_codesigning}/gke/gkhandmake | 0 .../libsecurity_codesigning}/gke/gklist | 0 .../libsecurity_codesigning}/gke/gkmerge | 0 .../libsecurity_codesigning}/gke/gkrecord | 0 .../libsecurity_codesigning}/gke/gkreport | 2 +- .../libsecurity_codesigning}/gke/gkunpack.cpp | 0 .../libsecurity_codesigning}/lib/CSCommon.h | 14 +- .../lib/CSCommonPriv.h | 2 +- .../libsecurity_codesigning}/lib/Code.cpp | 3 +- .../libsecurity_codesigning}/lib/Code.h | 2 +- .../lib/CodeSigner.cpp | 3 +- .../libsecurity_codesigning}/lib/CodeSigner.h | 2 +- .../lib/CodeSigning.h | 2 +- .../lib/RequirementKeywords.h | 0 .../lib/RequirementLexer.cpp | 0 .../lib/RequirementLexer.hpp | 0 .../lib/RequirementParser.cpp | 0 .../lib/RequirementParser.hpp | 0 .../lib/RequirementParserTokenTypes.hpp | 0 .../lib/RequirementParserTokenTypes.txt | 0 .../lib/Requirements.cpp | 2 +- .../lib/Requirements.h | 2 +- .../lib/SecAssessment.cpp | 31 +- .../lib/SecAssessment.h | 10 +- .../libsecurity_codesigning}/lib/SecCode.cpp | 2 +- .../libsecurity_codesigning}/lib/SecCode.h | 2 +- .../lib/SecCodeHost.cpp | 2 +- .../lib/SecCodeHost.h | 2 +- .../lib/SecCodeHostLib.c | 2 +- .../lib/SecCodeHostLib.h | 2 +- .../lib/SecCodePriv.h | 2 +- .../lib/SecCodeSigner.cpp | 6 +- .../lib/SecCodeSigner.h | 2 +- .../lib/SecIntegrity.cpp | 2 +- .../lib/SecIntegrity.h | 2 +- .../lib/SecIntegrityLib.c | 2 +- .../lib/SecIntegrityLib.h | 2 +- .../lib/SecRequirement.cpp | 2 +- .../lib/SecRequirement.h | 2 +- .../lib/SecRequirementPriv.h | 2 +- .../lib/SecStaticCode.cpp | 31 +- .../lib/SecStaticCode.h | 3 +- .../lib/SecStaticCodePriv.h | 16 +- .../libsecurity_codesigning/lib/SecTask.c | 292 + .../libsecurity_codesigning/lib/SecTask.h | 103 + .../lib/SecTaskPriv.h | 0 .../lib/StaticCode.cpp | 154 +- .../libsecurity_codesigning}/lib/StaticCode.h | 33 +- .../lib/antlrplugin.cpp | 2 +- .../lib/antlrplugin.h | 2 +- .../lib/bundlediskrep.cpp | 4 +- .../lib/bundlediskrep.h | 4 +- .../lib/cdbuilder.cpp | 2 +- .../libsecurity_codesigning}/lib/cdbuilder.h | 2 +- .../lib/codedirectory.cpp | 2 +- .../lib/codedirectory.h | 2 +- .../libsecurity_codesigning}/lib/cs.cpp | 2 +- .../libsecurity_codesigning}/lib/cs.h | 5 +- .../libsecurity_codesigning}/lib/cscdefs.c | 0 .../libsecurity_codesigning}/lib/cscdefs.h | 0 .../lib/csdatabase.cpp | 2 +- .../libsecurity_codesigning}/lib/csdatabase.h | 2 +- .../libsecurity_codesigning}/lib/cserror.cpp | 2 +- .../libsecurity_codesigning}/lib/cserror.h | 2 +- .../lib/csgeneric.cpp | 2 +- .../libsecurity_codesigning}/lib/csgeneric.h | 2 +- .../libsecurity_codesigning}/lib/cskernel.cpp | 2 +- .../libsecurity_codesigning}/lib/cskernel.h | 2 +- .../lib/csprocess.cpp | 2 +- .../libsecurity_codesigning}/lib/csprocess.h | 2 +- .../lib/csutilities.cpp | 2 +- .../lib/csutilities.h | 2 +- .../lib/detachedrep.cpp | 2 +- .../lib/detachedrep.h | 2 +- .../lib/dirscanner.cpp | 0 .../libsecurity_codesigning}/lib/dirscanner.h | 0 .../libsecurity_codesigning}/lib/diskrep.cpp | 5 +- .../libsecurity_codesigning}/lib/diskrep.h | 10 +- .../libsecurity_codesigning}/lib/drmaker.cpp | 0 .../libsecurity_codesigning}/lib/drmaker.h | 0 .../lib/filediskrep.cpp | 2 +- .../lib/filediskrep.h | 2 +- .../libsecurity_codesigning/lib/gkoverride.m | 168 + .../lib/kerneldiskrep.cpp | 2 +- .../lib/kerneldiskrep.h | 2 +- .../libsecurity_codesigning}/lib/machorep.cpp | 6 +- .../libsecurity_codesigning}/lib/machorep.h | 2 +- .../lib/opaquewhitelist.cpp | 307 + .../lib/opaquewhitelist.h | 6 +- .../lib/piddiskrep.cpp | 17 +- .../libsecurity_codesigning}/lib/piddiskrep.h | 6 +- .../libsecurity_codesigning}/lib/policydb.cpp | 33 +- .../libsecurity_codesigning}/lib/policydb.h | 10 +- .../lib/policyengine.cpp | 45 +- .../lib/policyengine.h | 2 +- .../lib/quarantine++.cpp | 2 +- .../lib/quarantine++.h | 2 +- .../lib/reqdumper.cpp | 2 +- .../libsecurity_codesigning}/lib/reqdumper.h | 2 +- .../lib/reqinterp.cpp | 2 +- .../libsecurity_codesigning}/lib/reqinterp.h | 2 +- .../libsecurity_codesigning}/lib/reqmaker.cpp | 2 +- .../libsecurity_codesigning}/lib/reqmaker.h | 2 +- .../lib/reqparser.cpp | 2 +- .../libsecurity_codesigning}/lib/reqparser.h | 2 +- .../lib/reqreader.cpp | 2 +- .../libsecurity_codesigning}/lib/reqreader.h | 2 +- .../lib/requirement.cpp | 0 .../lib/requirement.h | 0 .../lib/resources.cpp | 11 +- .../libsecurity_codesigning}/lib/resources.h | 2 +- .../lib/security_codesigning.d | 2 + .../lib/security_codesigning.exp | 2 +- .../libsecurity_codesigning}/lib/sigblob.cpp | 2 +- .../libsecurity_codesigning}/lib/sigblob.h | 2 +- .../libsecurity_codesigning}/lib/signer.cpp | 19 +- .../libsecurity_codesigning}/lib/signer.h | 4 +- .../lib/signerutils.cpp | 2 +- .../lib/signerutils.h | 2 +- .../lib/singlediskrep.cpp | 6 +- .../lib/singlediskrep.h | 4 +- .../libsecurity_codesigning}/lib/slcrep.cpp | 2 +- .../libsecurity_codesigning}/lib/slcrep.h | 2 +- .../lib/syspolicy.sql | 0 .../libsecurity_codesigning}/lib/xar++.cpp | 2 +- .../libsecurity_codesigning}/lib/xar++.h | 2 +- .../lib/xpcengine.cpp | 36 +- .../libsecurity_codesigning}/lib/xpcengine.h | 2 +- .../project.pbxproj | 2172 +++ .../libsecurity_codesigning}/req/cfm.ireqs | 0 .../req/ppc-host.ireq | 0 .../requirements.grammar | 0 .../Info-security_comcryption.plist | 0 .../libsecurity_comcryption}/lib/comDebug.h | 2 +- .../lib/comcryptPriv.c | 39 +- .../lib/comcryptPriv.h | 37 +- .../lib/comcryption.c | 48 +- .../lib/comcryption.h | 36 +- .../project.pbxproj | 0 .../Info-security_cryptkit.plist | 0 .../libsecurity_cryptkit}/ckutils/Makefile | 0 .../ckutils/Makefile.common | 0 .../ckutils/atomTime/Makefile | 0 .../ckutils/atomTime/atomTime.c | 0 .../ckutils/badsig/Makefile | 0 .../ckutils/badsig/badsig.c | 475 + .../ckutils/blobtest/Makefile | 0 .../ckutils/blobtest/blobtest.c | 28 +- .../ckutils/cfileTest/Makefile | 0 .../ckutils/cfileTest/cfileTest.c | 32 +- .../ckutils/ckutilsPlatform.h | 0 .../ckutils/giantAsmBench/Makefile | 0 .../ckutils/giantAsmBench/giantAsmBench.c | 28 +- .../ckutils/giantBench/Makefile | 0 .../ckutils/giantBench/giantBench.c | 28 +- .../ckutils/giantDvt/Makefile | 0 .../ckutils/giantDvt/giantDvt.c | 28 +- .../ckutils/sigTime/Makefile | 0 .../ckutils/sigTime/sigTime.cpp | 0 .../libsecurity_cryptkit}/lib/ByteRep.txt | 0 .../libsecurity_cryptkit}/lib/CipherFileDES.c | 10 +- .../libsecurity_cryptkit}/lib/CipherFileDES.h | 8 +- .../lib/CipherFileFEED.c | 10 +- .../lib/CipherFileFEED.h | 8 +- .../lib/CipherFileTypes.h | 8 +- .../libsecurity_cryptkit}/lib/Crypt.h | 10 +- .../libsecurity_cryptkit}/lib/CryptKit.def | 0 .../libsecurity_cryptkit}/lib/CryptKit.h | 6 +- .../lib/CryptKitAsn1.cpp | 0 .../libsecurity_cryptkit}/lib/CryptKitAsn1.h | 0 .../libsecurity_cryptkit}/lib/CryptKitDER.cpp | 3 +- .../libsecurity_cryptkit}/lib/CryptKitDER.h | 23 +- .../libsecurity_cryptkit/lib/CryptKitSA.h | 23 + .../lib/CurveParamDocs/FEEDaffine.nb | 0 .../lib/CurveParamDocs/FEEDsansY.nb | 0 .../lib/CurveParamDocs/README | 0 .../lib/CurveParamDocs/curvegen.c | 0 .../lib/CurveParamDocs/curverecords.nb | 0 .../lib/CurveParamDocs/disc.h | 0 .../lib/CurveParamDocs/ellproj.c | 0 .../lib/CurveParamDocs/ellproj.h | 0 .../lib/CurveParamDocs/factor.c | 0 .../lib/CurveParamDocs/fmodule.c | 0 .../lib/CurveParamDocs/fmodule.h | 0 .../lib/CurveParamDocs/giants.c | 0 .../lib/CurveParamDocs/giants.h | 0 .../lib/CurveParamDocs/schoof.c | 0 .../lib/CurveParamDocs/schoofs.c | 0 .../lib/CurveParamDocs/tools.c | 0 .../lib/CurveParamDocs/tools.h | 0 .../libsecurity_cryptkit}/lib/ECDSA_Profile.h | 9 +- .../lib/ECDSA_Verify_Prefix.h | 0 .../lib/HmacSha1Legacy.c | 5 +- .../lib/HmacSha1Legacy.h | 5 +- .../libsecurity_cryptkit}/lib/Mathematica.FEE | 0 .../libsecurity_cryptkit}/lib/NSCipherFile.h | 8 +- .../libsecurity_cryptkit}/lib/NSCipherFile.m | 8 +- .../libsecurity_cryptkit}/lib/NSCryptors.h | 6 +- .../libsecurity_cryptkit}/lib/NSDESCryptor.h | 6 +- .../libsecurity_cryptkit}/lib/NSDESCryptor.m | 10 +- .../lib/NSFEEPublicKey.h | 8 +- .../lib/NSFEEPublicKey.m | 10 +- .../lib/NSFEEPublicKeyPrivate.h | 36 + .../libsecurity_cryptkit}/lib/NSMD5Hash.h | 8 +- .../libsecurity_cryptkit}/lib/NSMD5Hash.m | 8 +- .../lib/NSRandomNumberGenerator.h | 8 +- .../lib/NSRandomNumberGenerator.m | 8 +- Security/libsecurity_cryptkit/lib/README | 221 + .../libsecurity_cryptkit}/lib/TOP_README | 2 +- .../libsecurity_cryptkit}/lib/buildSrcTree | 0 .../libsecurity_cryptkit}/lib/byteRep.c | 14 +- .../libsecurity_cryptkit}/lib/byteRep.h | 10 +- .../libsecurity_cryptkit}/lib/changes | 0 .../libsecurity_cryptkit}/lib/ckDES.c | 15 +- .../libsecurity_cryptkit}/lib/ckDES.h | 12 +- .../libsecurity_cryptkit}/lib/ckMD5.c | 10 +- .../libsecurity_cryptkit}/lib/ckMD5.h | 8 +- .../libsecurity_cryptkit}/lib/ckSHA1.c | 8 +- .../libsecurity_cryptkit}/lib/ckSHA1.h | 8 +- .../libsecurity_cryptkit}/lib/ckSHA1_priv.c | 8 +- .../libsecurity_cryptkit}/lib/ckSHA1_priv.h | 8 +- .../libsecurity_cryptkit}/lib/ckconfig.h | 9 +- .../libsecurity_cryptkit}/lib/ckutilities.c | 20 +- .../libsecurity_cryptkit}/lib/ckutilities.h | 8 +- .../lib/curveParamData.h | 0 .../lib/curveParamDataOld.h | 0 .../libsecurity_cryptkit}/lib/curveParams.c | 22 +- .../libsecurity_cryptkit}/lib/curveParams.h | 16 +- .../libsecurity_cryptkit}/lib/elliptic.c | 37 +- .../libsecurity_cryptkit}/lib/elliptic.h | 8 +- .../lib/ellipticMeasure.h | 9 +- .../libsecurity_cryptkit}/lib/ellipticProj.c | 9 +- .../libsecurity_cryptkit}/lib/ellipticProj.h | 8 +- .../libsecurity_cryptkit}/lib/enc64.c | 10 +- .../libsecurity_cryptkit}/lib/enc64.h | 8 +- .../libsecurity_cryptkit}/lib/engineNSA127.c | 15 +- .../libsecurity_cryptkit}/lib/falloc.c | 10 +- .../libsecurity_cryptkit}/lib/falloc.h | 8 +- .../libsecurity_cryptkit}/lib/feeCipherFile.c | 10 +- .../libsecurity_cryptkit}/lib/feeCipherFile.h | 8 +- .../lib/feeCipherFileAtom.c | 10 +- .../libsecurity_cryptkit}/lib/feeDES.c | 12 +- .../libsecurity_cryptkit}/lib/feeDES.h | 8 +- .../libsecurity_cryptkit}/lib/feeDebug.h | 9 +- .../lib/feeDigitalSignature.c | 12 +- .../lib/feeDigitalSignature.h | 8 +- .../libsecurity_cryptkit}/lib/feeECDSA.c | 11 +- .../libsecurity_cryptkit}/lib/feeECDSA.h | 8 +- .../libsecurity_cryptkit}/lib/feeFEED.c | 16 +- .../libsecurity_cryptkit}/lib/feeFEED.h | 8 +- .../libsecurity_cryptkit}/lib/feeFEEDExp.c | 18 +- .../libsecurity_cryptkit}/lib/feeFEEDExp.h | 8 +- .../libsecurity_cryptkit}/lib/feeFunctions.h | 10 +- .../libsecurity_cryptkit}/lib/feeHash.c | 8 +- .../libsecurity_cryptkit}/lib/feeHash.h | 8 +- .../libsecurity_cryptkit}/lib/feePublicKey.c | 26 +- .../libsecurity_cryptkit}/lib/feePublicKey.h | 12 +- .../lib/feePublicKeyPrivate.h | 8 +- .../libsecurity_cryptkit}/lib/feeRandom.c | 12 +- .../libsecurity_cryptkit}/lib/feeRandom.h | 8 +- .../libsecurity_cryptkit}/lib/feeTypes.h | 14 +- .../libsecurity_cryptkit}/lib/giantFFT.c | 9 +- .../libsecurity_cryptkit}/lib/giantIntegers.c | 40 +- .../libsecurity_cryptkit}/lib/giantIntegers.h | 11 +- .../lib/giantPortCommon.h | 8 +- .../lib/giantPort_Generic.h | 8 +- .../libsecurity_cryptkit}/lib/giantPort_PPC.c | 8 +- .../libsecurity_cryptkit}/lib/giantPort_PPC.h | 8 +- .../lib/giantPort_PPC_Gnu.h | 0 .../lib/giantPort_PPC_Gnu.s | 24 +- .../lib/giantPort_i486.h | 8 +- .../lib/giantPort_i486.s | 8 +- .../libsecurity_cryptkit}/lib/mutils.h | 8 +- .../libsecurity_cryptkit}/lib/mutils.m | 8 +- .../libsecurity_cryptkit}/lib/platform.c | 8 +- .../libsecurity_cryptkit}/lib/platform.h | 8 +- .../libsecurity_cryptkit}/lib/unixMakefile | 0 .../project.pbxproj | 0 .../libsecurity_cssm}/APPLE_LICENSE | 0 .../Info-security_cssm.plist | 0 .../libsecurity_cssm}/lib/attachfactory.cpp | 2 +- .../libsecurity_cssm}/lib/attachfactory.h | 2 +- .../libsecurity_cssm}/lib/attachment.cpp | 2 +- .../libsecurity_cssm}/lib/attachment.h | 2 +- .../libsecurity_cssm/lib/certextensions.h | 640 + .../libsecurity_cssm}/lib/cspattachment.cpp | 2 +- .../libsecurity_cssm}/lib/cspattachment.h | 2 +- .../libsecurity_cssm}/lib/cssm.cpp | 2 +- .../libsecurity_cssm}/lib/cssm.h | 2 +- .../libsecurity_cssm}/lib/cssmaci.h | 2 +- .../libsecurity_cssm}/lib/cssmapi.h | 2 +- Security/libsecurity_cssm/lib/cssmapple.h | 1160 ++ .../libsecurity_cssm}/lib/cssmapplePriv.h | 2 +- .../libsecurity_cssm}/lib/cssmcli.h | 2 +- .../libsecurity_cssm}/lib/cssmconfig.h | 2 +- .../libsecurity_cssm}/lib/cssmcontext.cpp | 2 +- .../libsecurity_cssm}/lib/cssmcontext.h | 2 +- .../libsecurity_cssm}/lib/cssmcspi.h | 2 +- .../libsecurity_cssm}/lib/cssmdli.h | 2 +- .../libsecurity_cssm}/lib/cssmerr.h | 2 +- .../libsecurity_cssm}/lib/cssmint.h | 2 +- .../libsecurity_cssm}/lib/cssmkrapi.h | 2 +- .../libsecurity_cssm}/lib/cssmkrspi.h | 2 +- .../libsecurity_cssm}/lib/cssmmds.cpp | 2 +- .../libsecurity_cssm}/lib/cssmmds.h | 2 +- .../libsecurity_cssm}/lib/cssmspi.h | 2 +- .../libsecurity_cssm}/lib/cssmtpi.h | 2 +- .../libsecurity_cssm}/lib/cssmtype.h | 4 +- .../libsecurity_cssm}/lib/eisl.h | 4 +- .../libsecurity_cssm}/lib/emmspi.h | 2 +- .../libsecurity_cssm}/lib/emmtype.h | 2 +- .../libsecurity_cssm}/lib/generator.cfg | 0 .../libsecurity_cssm}/lib/generator.mk | 2 +- .../libsecurity_cssm}/lib/generator.pl | 3 +- .../libsecurity_cssm}/lib/guids.cpp | 2 +- .../libsecurity_cssm}/lib/manager.cpp | 2 +- .../libsecurity_cssm}/lib/manager.h | 2 +- .../libsecurity_cssm}/lib/modload_plugin.cpp | 2 +- .../libsecurity_cssm}/lib/modload_plugin.h | 2 +- .../libsecurity_cssm}/lib/modload_static.cpp | 2 +- .../libsecurity_cssm}/lib/modload_static.h | 2 +- .../libsecurity_cssm}/lib/modloader.cpp | 2 +- .../libsecurity_cssm}/lib/modloader.h | 2 +- .../libsecurity_cssm}/lib/module.cpp | 2 +- .../libsecurity_cssm}/lib/module.h | 2 +- Security/libsecurity_cssm/lib/oidsalg.c | 158 + Security/libsecurity_cssm/lib/oidsbase.h | 517 + .../libsecurity_cssm}/lib/oidscert.cpp | 21 +- .../libsecurity_cssm}/lib/oidscert.h | 10 +- .../libsecurity_cssm}/lib/oidscrl.cpp | 4 +- .../libsecurity_cssm}/lib/oidscrl.h | 2 +- .../libsecurity_cssm}/lib/security_cssm.exp | 2 +- Security/libsecurity_cssm/lib/transition.cpp | 519 + .../libsecurity_cssm}/lib/x509defs.h | 2 +- .../project.pbxproj | 0 .../libsecurity_cssm}/mds/cssm.mdsinfo | 0 .../Info-security_filedb.plist | 0 .../libsecurity_filedb}/lib/AppleDatabase.cpp | 159 +- .../libsecurity_filedb}/lib/AppleDatabase.h | 2 +- .../libsecurity_filedb}/lib/AtomicFile.cpp | 2 +- .../libsecurity_filedb}/lib/AtomicFile.h | 2 +- .../libsecurity_filedb}/lib/DbIndex.cpp | 2 +- .../libsecurity_filedb}/lib/DbIndex.h | 2 +- .../libsecurity_filedb}/lib/DbQuery.cpp | 2 +- .../libsecurity_filedb}/lib/DbQuery.h | 2 +- .../libsecurity_filedb}/lib/DbValue.cpp | 2 +- .../libsecurity_filedb}/lib/DbValue.h | 2 +- .../libsecurity_filedb}/lib/MetaAttribute.cpp | 2 +- .../libsecurity_filedb}/lib/MetaAttribute.h | 2 +- .../libsecurity_filedb}/lib/MetaRecord.cpp | 2 +- .../libsecurity_filedb}/lib/MetaRecord.h | 2 +- .../lib/OverUnderflowCheck.h | 0 .../lib/ReadWriteSection.cpp | 0 .../lib/ReadWriteSection.h | 2 +- .../lib/SelectionPredicate.cpp | 2 +- .../lib/SelectionPredicate.h | 2 +- .../project.pbxproj | 0 .../libsecurity_keychain}/APPLE_LICENSE | 0 .../Info-security_keychain.plist | 0 .../libsecurity_keychain}/Security | 0 .../libsecurity_keychain}/lib/ACL.cpp | 2 +- .../libsecurity_keychain}/lib/ACL.h | 2 +- .../libsecurity_keychain}/lib/Access.cpp | 2 +- .../libsecurity_keychain}/lib/Access.h | 2 +- .../lib/AppleBaselineEscrowCertificates.h | 178 + .../libsecurity_keychain}/lib/CCallbackMgr.cp | 2 +- .../libsecurity_keychain}/lib/CCallbackMgr.h | 2 +- .../libsecurity_keychain}/lib/Certificate.cpp | 8 +- .../libsecurity_keychain}/lib/Certificate.h | 8 +- .../lib/CertificateRequest.cpp | 2 +- .../lib/CertificateRequest.h | 2 +- .../lib/CertificateValues.cpp | 8 +- .../lib/CertificateValues.h | 8 +- .../lib/DLDBListCFPref.cpp | 11 +- .../lib/DLDBListCFPref.h | 2 +- .../lib/DynamicDLDBList.cpp | 2 +- .../lib/DynamicDLDBList.h | 2 +- .../lib/ExtendedAttribute.cpp | 3 +- .../lib/ExtendedAttribute.h | 3 +- .../libsecurity_keychain}/lib/Globals.cpp | 2 +- .../libsecurity_keychain}/lib/Globals.h | 2 +- .../libsecurity_keychain}/lib/Identity.cpp | 2 +- .../libsecurity_keychain}/lib/Identity.h | 2 +- .../lib/IdentityCursor.cpp | 2 +- .../lib/IdentityCursor.h | 2 +- .../libsecurity_keychain}/lib/Item.cpp | 8 +- .../libsecurity_keychain}/lib/Item.h | 8 +- .../libsecurity_keychain}/lib/KCCursor.cpp | 2 +- .../libsecurity_keychain}/lib/KCCursor.h | 2 +- .../lib/KCEventNotifier.cpp | 2 +- .../lib/KCEventNotifier.h | 2 +- .../libsecurity_keychain}/lib/KCExceptions.h | 2 +- .../libsecurity_keychain}/lib/KCUtilities.cpp | 2 +- .../libsecurity_keychain}/lib/KCUtilities.h | 2 +- .../libsecurity_keychain}/lib/KeyItem.cpp | 11 +- .../libsecurity_keychain}/lib/KeyItem.h | 2 +- .../libsecurity_keychain}/lib/Keychains.cpp | 6 +- .../libsecurity_keychain}/lib/Keychains.h | 2 +- .../lib/MacOSErrorStrings.h | 2 +- .../libsecurity_keychain}/lib/Password.cpp | 2 +- .../libsecurity_keychain}/lib/Password.h | 2 +- .../libsecurity_keychain}/lib/Policies.cpp | 8 +- .../libsecurity_keychain}/lib/Policies.h | 8 +- .../lib/PolicyCursor.cpp | 8 +- .../libsecurity_keychain}/lib/PolicyCursor.h | 8 +- .../libsecurity_keychain}/lib/PrimaryKey.cpp | 2 +- .../libsecurity_keychain}/lib/PrimaryKey.h | 2 +- .../libsecurity_keychain}/lib/SecACL.cpp | 2 +- .../libsecurity_keychain}/lib/SecACL.h | 2 +- .../libsecurity_keychain}/lib/SecAccess.cpp | 8 +- .../libsecurity_keychain}/lib/SecAccess.h | 2 +- .../libsecurity_keychain}/lib/SecAccessPriv.h | 2 +- .../libsecurity_keychain}/lib/SecAsn1TypesP.h | 0 .../libsecurity_keychain}/lib/SecBase.cpp | 2 +- Security/libsecurity_keychain/lib/SecBase.h | 648 + .../libsecurity_keychain}/lib/SecBase64P.c | 0 .../libsecurity_keychain}/lib/SecBase64P.h | 0 .../libsecurity_keychain}/lib/SecBaseP.h | 2 +- .../libsecurity_keychain/lib/SecBasePriv.h | 92 + .../libsecurity_keychain}/lib/SecBridge.h | 2 +- .../libsecurity_keychain}/lib/SecCFTypes.cpp | 2 +- .../libsecurity_keychain}/lib/SecCFTypes.h | 2 +- .../lib/SecCertificate.cpp | 134 +- .../libsecurity_keychain/lib/SecCertificate.h | 466 + .../lib/SecCertificateBundle.cpp | 2 +- .../lib/SecCertificateBundle.h | 2 +- .../lib/SecCertificateInternalP.h | 8 +- .../lib/SecCertificateOIDs.h | 2 +- .../lib/SecCertificateP.c | 8 +- .../lib/SecCertificateP.h | 8 +- .../lib/SecCertificatePriv.h | 257 + .../lib/SecCertificatePrivP.h | 8 +- .../lib/SecCertificateRequest.cpp | 2 +- .../lib/SecCertificateRequest.h | 191 + .../libsecurity_keychain}/lib/SecExport.cpp | 2 +- .../lib/SecExternalRep.cpp | 13 +- .../lib/SecExternalRep.h | 2 +- .../lib/SecFDERecoveryAsymmetricCrypto.cpp | 2 +- .../lib/SecFDERecoveryAsymmetricCrypto.h | 2 +- .../libsecurity_keychain}/lib/SecFrameworkP.c | 2 +- .../libsecurity_keychain}/lib/SecFrameworkP.h | 2 +- .../libsecurity_keychain}/lib/SecIdentity.cpp | 8 +- .../libsecurity_keychain/lib/SecIdentity.h | 198 + .../lib/SecIdentityPriv.h | 152 + .../lib/SecIdentitySearch.cpp | 2 +- .../lib/SecIdentitySearch.h | 2 +- .../lib/SecIdentitySearchPriv.h | 2 +- .../libsecurity_keychain}/lib/SecImport.cpp | 8 +- .../lib/SecImportExport.c | 335 + .../lib/SecImportExport.h | 681 + .../lib/SecImportExportAgg.cpp | 2 +- .../lib/SecImportExportAgg.h | 2 +- .../lib/SecImportExportCrypto.cpp | 171 +- .../lib/SecImportExportCrypto.h | 2 +- .../lib/SecImportExportOpenSSH.cpp | 3 +- .../lib/SecImportExportOpenSSH.h | 3 +- .../lib/SecImportExportPem.cpp | 2 +- .../lib/SecImportExportPem.h | 2 +- .../lib/SecImportExportPkcs8.cpp | 2 +- .../lib/SecImportExportPkcs8.h | 2 +- .../lib/SecImportExportUtils.cpp | 13 +- .../lib/SecImportExportUtils.h | 2 +- .../libsecurity_keychain/lib/SecInternal.h | 67 + .../libsecurity_keychain}/lib/SecInternalP.h | 8 +- .../libsecurity_keychain}/lib/SecItem.cpp | 166 +- Security/libsecurity_keychain/lib/SecItem.h | 1113 ++ .../lib/SecItemConstants.c | 233 + .../libsecurity_keychain/lib/SecItemPriv.h | 301 + .../libsecurity_keychain}/lib/SecKey.cpp | 103 +- Security/libsecurity_keychain/lib/SecKey.h | 604 + .../libsecurity_keychain/lib/SecKeyPriv.h | 392 + .../libsecurity_keychain}/lib/SecKeychain.cpp | 152 +- .../libsecurity_keychain}/lib/SecKeychain.h | 4 +- .../lib/SecKeychainAddIToolsPassword.cpp | 2 +- .../lib/SecKeychainItem.cpp | 8 +- .../lib/SecKeychainItem.h | 8 +- .../lib/SecKeychainItemExtendedAttributes.cpp | 2 +- .../lib/SecKeychainItemExtendedAttributes.h | 2 +- .../lib/SecKeychainItemPriv.h | 2 +- .../lib/SecKeychainPriv.h | 128 + .../lib/SecKeychainSearch.cpp | 2 +- .../lib/SecKeychainSearch.h | 2 +- .../lib/SecKeychainSearchPriv.h | 2 +- .../lib/SecNetscapeTemplates.cpp | 2 +- .../lib/SecNetscapeTemplates.h | 2 +- .../libsecurity_keychain}/lib/SecPassword.cpp | 2 +- .../libsecurity_keychain}/lib/SecPassword.h | 2 +- .../lib/SecPkcs8Templates.cpp | 2 +- .../lib/SecPkcs8Templates.h | 2 +- .../libsecurity_keychain/lib/SecPolicy.cpp | 453 + Security/libsecurity_keychain/lib/SecPolicy.h | 408 + .../libsecurity_keychain/lib/SecPolicyPriv.h | 147 + .../lib/SecPolicySearch.cpp | 2 +- .../lib/SecPolicySearch.h | 2 +- .../libsecurity_keychain}/lib/SecRSAKeyP.h | 2 +- .../libsecurity_keychain}/lib/SecRandom.c | 2 +- Security/libsecurity_keychain/lib/SecRandom.h | 66 + .../libsecurity_keychain}/lib/SecRandomP.h | 2 +- .../lib/SecRecoveryPassword.c | 2 +- .../lib/SecRecoveryPassword.h | 2 +- .../libsecurity_keychain}/lib/SecTrust.cpp | 8 +- Security/libsecurity_keychain/lib/SecTrust.h | 686 + .../libsecurity_keychain/lib/SecTrustPriv.h | 175 + .../lib/SecTrustSettings.cpp | 25 +- .../lib/SecTrustSettings.h | 321 + .../lib/SecTrustSettingsPriv.h | 143 + .../lib/SecTrustedApplication.cpp | 11 +- .../lib/SecTrustedApplication.h | 8 +- .../lib/SecTrustedApplicationPriv.h | 2 +- .../lib/SecWrappedKeys.cpp | 2 +- Security/libsecurity_keychain/lib/Security.h | 103 + .../lib/StorageManager.cpp | 52 +- .../lib/StorageManager.h | 2 +- .../libsecurity_keychain}/lib/Trust.cpp | 17 +- .../libsecurity_keychain}/lib/Trust.h | 8 +- .../lib/TrustAdditions.cpp | 8 +- .../lib/TrustAdditions.h | 8 +- .../libsecurity_keychain}/lib/TrustItem.cpp | 2 +- .../libsecurity_keychain}/lib/TrustItem.h | 2 +- .../lib/TrustKeychains.h | 2 +- .../lib/TrustRevocation.cpp | 31 +- .../lib/TrustSettings.cpp | 3 +- .../libsecurity_keychain}/lib/TrustSettings.h | 2 +- .../lib/TrustSettingsSchema.h | 2 +- .../lib/TrustSettingsUtils.cpp | 3 +- .../lib/TrustSettingsUtils.h | 2 +- .../libsecurity_keychain}/lib/TrustStore.cpp | 8 +- .../libsecurity_keychain}/lib/TrustStore.h | 2 +- .../lib/TrustedApplication.cpp | 8 +- .../lib/TrustedApplication.h | 8 +- .../lib/UnlockReferralItem.cpp | 2 +- .../lib/UnlockReferralItem.h | 2 +- .../lib/certextensionsP.h | 2 +- .../lib/cssmdatetime.cpp | 2 +- .../libsecurity_keychain}/lib/cssmdatetime.h | 2 +- .../lib/defaultcreds.cpp | 2 +- .../libsecurity_keychain}/lib/defaultcreds.h | 2 +- .../lib/generateErrStrings.pl | 98 + .../lib/security_keychain.exp | 15 +- .../lib/tsaDERUtilities.c | 2 +- .../lib/tsaDERUtilities.h | 2 +- .../libsecurity_keychain}/libDER/README.txt | 0 .../Tests/AppleMobilePersonalizedTicket.h | 25 +- .../libDER/Tests/DER_Ticket.c | 25 +- .../libDER/Tests/DER_Ticket.h | 96 + .../certsCrls/EndCertificateCP.01.01.crt | Bin .../libDER/Tests/certsCrls/Test_CRL_CA1.crl | Bin .../Tests/certsCrls/Test_CRL_CA1.crl.pem | 0 .../Tests/certsCrls/TrustAnchorCP.01.01.crt | Bin .../certsCrls/TrustAnchorCRLCP.01.01.crl | Bin .../libDER/Tests/certsCrls/apple_v3.000.cer | Bin .../libDER/Tests/certsCrls/apple_v3.001.cer | Bin .../libDER/Tests/certsCrls/entrust_v3.100.cer | Bin .../libDER/Tests/certsCrls/entrust_v3.101.cer | Bin .../libDER/Tests/certsCrls/keybank_v3.100.cer | Bin .../libDER/Tests/certsCrls/keybank_v3.101.cer | Bin .../libDER/Tests/certsCrls/keybank_v3.102.cer | Bin .../libDER/Tests/parseCert.c | 2 +- .../libDER/Tests/parseCrl.c | 2 +- .../libDER/Tests/parseTicket.c | 0 .../libDER/config/base.xcconfig | 16 + .../libDER/config/debug.xcconfig | 0 .../libDER/config/lib.xcconfig | 0 .../libDER/config/release.xcconfig | 0 .../libDER/libDER.xcodeproj/project.pbxproj | 756 + .../libDER/libDER/DER_CertCrl.c | 25 +- .../libDER/libDER/DER_CertCrl.h | 25 +- .../libDER/libDER/DER_Decode.c | 2 +- .../libDER/libDER/DER_Decode.h | 2 +- .../libDER/libDER/DER_Digest.c | 25 +- .../libDER/libDER/DER_Digest.h | 95 + .../libDER/libDER/DER_Encode.c | 27 +- .../libDER/libDER/DER_Encode.h | 124 + .../libDER/libDER/DER_Keys.c | 25 +- .../libDER/libDER/DER_Keys.h | 125 + .../libDER/libDER/asn1Types.h | 112 + .../libDER/libDER/libDER.h | 86 + .../libDER/libDER/libDER_config.h | 113 + .../libDER/libDER/oids.c | 147 +- .../libsecurity_keychain/libDER/libDER/oids.h | 137 + .../libDER/libDERUtils/fileIo.c | 85 + .../libDER/libDERUtils/fileIo.h | 29 + .../libDER/libDERUtils/libDERUtils.c | 57 + .../libDER/libDERUtils/libDERUtils.h | 50 + .../libDER/libDERUtils/printFields.c | 25 +- .../libDER/libDERUtils/printFields.h | 78 + .../project.pbxproj | 1319 ++ .../plist/iToolsTrustedApps.plist | 0 .../regressions/kc-40-seckey.c | 124 +- .../regressions/kc-41-sececkey.c | 33 +- .../regressions/kc-42-trust-revocation.c | 390 + .../regressions/keychain_regressions.h | 1 + .../regressions/si-33-keychain-backup.c | 107 + .../xpc-tsa/XPCTimeStampingService-Info.plist | 0 .../libsecurity_keychain}/xpc-tsa/main-tsa.m | 2 +- .../xpc-tsa/timestampclient.h | 2 +- .../xpc-tsa/timestampclient.m | 2 +- .../xpc/XPCKeychainSandboxCheck-Info.plist | 0 Security/libsecurity_keychain/xpc/main.c | 422 + .../libsecurity_manifest}/APPLE_LICENSE | 0 .../Info-security_manifest.plist | 0 .../lib/AppleManifest.cpp | 2 +- .../libsecurity_manifest}/lib/AppleManifest.h | 2 +- .../libsecurity_manifest}/lib/Download.cpp | 2 +- .../libsecurity_manifest}/lib/Download.h | 2 +- .../libsecurity_manifest}/lib/Manifest.cpp | 2 +- .../libsecurity_manifest}/lib/Manifest.h | 2 +- .../lib/ManifestInternal.cpp | 2 +- .../lib/ManifestInternal.h | 2 +- .../lib/ManifestSigner.cpp | 2 +- .../lib/ManifestSigner.h | 2 +- .../libsecurity_manifest}/lib/SecManifest.cpp | 2 +- .../libsecurity_manifest}/lib/SecManifest.h | 2 +- .../lib/SecureDownload.cpp | 2 +- .../lib/SecureDownload.h | 2 +- .../lib/SecureDownloadInternal.c | 0 .../lib/SecureDownloadInternal.h | 0 .../lib/security_manifest.exp | 2 +- .../project.pbxproj | 0 .../libsecurity_mds}/Info-security_mds.plist | 0 .../libsecurity_mds}/README | 0 .../libsecurity_mds}/lib/MDSAttrParser.cpp | 4 +- .../libsecurity_mds}/lib/MDSAttrParser.h | 4 +- .../libsecurity_mds}/lib/MDSAttrStrings.cpp | 4 +- .../libsecurity_mds}/lib/MDSAttrStrings.h | 4 +- .../libsecurity_mds}/lib/MDSAttrUtils.cpp | 4 +- .../libsecurity_mds}/lib/MDSAttrUtils.h | 4 +- .../libsecurity_mds}/lib/MDSDatabase.cpp | 2 +- .../libsecurity_mds}/lib/MDSDatabase.h | 2 +- .../libsecurity_mds}/lib/MDSDictionary.cpp | 4 +- .../libsecurity_mds}/lib/MDSDictionary.h | 4 +- .../libsecurity_mds}/lib/MDSModule.cpp | 2 +- .../libsecurity_mds}/lib/MDSModule.h | 2 +- .../libsecurity_mds}/lib/MDSPrefs.cpp | 2 +- .../libsecurity_mds}/lib/MDSPrefs.h | 2 +- Security/libsecurity_mds/lib/MDSSchema.cpp | 823 ++ Security/libsecurity_mds/lib/MDSSchema.h | 107 + .../libsecurity_mds}/lib/MDSSession.cpp | 2 +- .../libsecurity_mds}/lib/MDSSession.h | 2 +- .../libsecurity_mds}/lib/mds.h | 4 +- .../libsecurity_mds}/lib/mds_schema.h | 4 +- .../libsecurity_mds}/lib/mdsapi.cpp | 4 +- .../libsecurity_mds}/lib/mdspriv.h | 2 +- .../libsecurity_mds}/lib/security_mds.exp | 0 .../libsecurity_mds.xcodeproj/project.pbxproj | 0 .../Info-security_ocspd.plist | 0 .../libsecurity_ocspd}/client/ocspdClient.cpp | 23 +- .../libsecurity_ocspd}/client/ocspdClient.h | 23 +- .../common/ocspExtensions.cpp | 2 +- .../common/ocspExtensions.h | 2 +- .../common/ocspResponse.cpp | 2 +- .../libsecurity_ocspd}/common/ocspResponse.h | 2 +- .../libsecurity_ocspd}/common/ocspdClient.h | 0 .../common/ocspdDbSchema.cpp | 2 +- .../libsecurity_ocspd}/common/ocspdDbSchema.h | 2 +- .../libsecurity_ocspd}/common/ocspdDebug.h | 2 +- .../libsecurity_ocspd/common/ocspdTypes.h | 42 + .../libsecurity_ocspd}/common/ocspdUtils.cpp | 23 +- .../libsecurity_ocspd/common/ocspdUtils.h | 99 + .../project.pbxproj | 0 Security/libsecurity_ocspd/mig/mig.mk | 47 + .../libsecurity_ocspd}/mig/ocspd.defs | 0 .../libsecurity_pkcs12}/APPLE_LICENSE | 0 .../Info-security_pkcs12.plist | 0 .../libsecurity_pkcs12}/lib/SecPkcs12.cpp | 2 +- .../libsecurity_pkcs12}/lib/SecPkcs12.h | 2 +- .../lib/pkcs12BagAttrs.cpp | 2 +- .../libsecurity_pkcs12}/lib/pkcs12BagAttrs.h | 2 +- .../libsecurity_pkcs12}/lib/pkcs12Coder.cpp | 2 +- .../libsecurity_pkcs12}/lib/pkcs12Coder.h | 2 +- .../libsecurity_pkcs12}/lib/pkcs12Crypto.cpp | 2 +- .../libsecurity_pkcs12}/lib/pkcs12Crypto.h | 2 +- .../libsecurity_pkcs12}/lib/pkcs12Debug.h | 2 +- .../libsecurity_pkcs12}/lib/pkcs12Decode.cpp | 2 +- .../libsecurity_pkcs12}/lib/pkcs12Encode.cpp | 2 +- .../lib/pkcs12Keychain.cpp | 2 +- .../libsecurity_pkcs12}/lib/pkcs12SafeBag.cpp | 2 +- .../libsecurity_pkcs12}/lib/pkcs12SafeBag.h | 2 +- .../lib/pkcs12Templates.cpp | 8 +- .../libsecurity_pkcs12/lib/pkcs12Templates.h | 286 + .../libsecurity_pkcs12/lib/pkcs12Utils.cpp | 832 ++ Security/libsecurity_pkcs12/lib/pkcs12Utils.h | 186 + .../lib/pkcs7Templates.cpp | 2 +- .../libsecurity_pkcs12/lib/pkcs7Templates.h | 167 + .../libsecurity_pkcs12}/lib/pkcsoids.cpp | 2 +- .../libsecurity_pkcs12}/lib/pkcsoids.h | 2 +- .../project.pbxproj | 0 .../libsecurity_sd_cspdl}/APPLE_LICENSE | 0 .../Info-security_sd_cspdl.plist | 0 .../lib/SDCSPDLBuiltin.cpp | 2 +- .../lib/SDCSPDLDatabase.cpp | 2 +- .../lib/SDCSPDLDatabase.h | 2 +- .../lib/SDCSPDLPlugin.cpp | 2 +- .../libsecurity_sd_cspdl}/lib/SDCSPDLPlugin.h | 2 +- .../lib/SDCSPDLSession.cpp | 2 +- .../lib/SDCSPDLSession.h | 2 +- .../lib/SDCSPSession.cpp | 2 +- .../libsecurity_sd_cspdl}/lib/SDCSPSession.h | 2 +- .../libsecurity_sd_cspdl}/lib/SDContext.cpp | 2 +- .../libsecurity_sd_cspdl}/lib/SDContext.h | 2 +- .../libsecurity_sd_cspdl}/lib/SDDLSession.cpp | 2 +- .../libsecurity_sd_cspdl}/lib/SDDLSession.h | 2 +- .../libsecurity_sd_cspdl}/lib/SDFactory.cpp | 2 +- .../libsecurity_sd_cspdl}/lib/SDFactory.h | 2 +- .../libsecurity_sd_cspdl}/lib/SDKey.cpp | 2 +- .../libsecurity_sd_cspdl}/lib/SDKey.h | 2 +- .../project.pbxproj | 0 .../mds/sd_cspdl_common.mdsinfo | 0 .../libsecurity_smime}/APPLE_LICENSE | 0 .../Info-security_smime.plist | 0 Security/libsecurity_smime/TODO | 9 + .../docs/libsecurity_smime.plist | 0 .../docs/libsecurity_smime.txt | 0 Security/libsecurity_smime/lib/SecCMS.c | 140 + Security/libsecurity_smime/lib/SecCMS.h | 43 + Security/libsecurity_smime/lib/SecCmsBase.h | 511 + .../libsecurity_smime/lib/SecCmsContentInfo.h | 212 + .../libsecurity_smime/lib/SecCmsDecoder.h | 143 + .../lib/SecCmsDigestContext.h | 78 + .../lib/SecCmsDigestedData.h | 77 + .../libsecurity_smime/lib/SecCmsEncoder.h | 129 + .../lib/SecCmsEncryptedData.h | 76 + .../lib/SecCmsEnvelopedData.h | 80 + .../libsecurity_smime/lib/SecCmsMessage.h | 163 + .../lib/SecCmsRecipientInfo.h | 81 + .../libsecurity_smime/lib/SecCmsSignedData.h | 197 + .../libsecurity_smime/lib/SecCmsSignerInfo.h | 263 + Security/libsecurity_smime/lib/SecSMIME.h | 56 + Security/libsecurity_smime/lib/SecSMIMEPriv.h | 170 + Security/libsecurity_smime/lib/cert.c | 828 ++ Security/libsecurity_smime/lib/cert.h | 132 + Security/libsecurity_smime/lib/cmsarray.c | 214 + Security/libsecurity_smime/lib/cmsasn1.c | 599 + Security/libsecurity_smime/lib/cmsattr.c | 450 + Security/libsecurity_smime/lib/cmscinfo.c | 420 + Security/libsecurity_smime/lib/cmscipher.c | 1199 ++ Security/libsecurity_smime/lib/cmsdecode.c | 728 + Security/libsecurity_smime/lib/cmsdigdata.c | 229 + Security/libsecurity_smime/lib/cmsdigest.c | 280 + Security/libsecurity_smime/lib/cmsencdata.c | 294 + Security/libsecurity_smime/lib/cmsencode.c | 785 + Security/libsecurity_smime/lib/cmsenvdata.c | 440 + Security/libsecurity_smime/lib/cmslocal.h | 346 + Security/libsecurity_smime/lib/cmsmessage.c | 362 + Security/libsecurity_smime/lib/cmspriv.h | 510 + Security/libsecurity_smime/lib/cmspubkey.c | 1449 ++ Security/libsecurity_smime/lib/cmsrecinfo.c | 704 + Security/libsecurity_smime/lib/cmsreclist.c | 237 + Security/libsecurity_smime/lib/cmsreclist.h | 57 + Security/libsecurity_smime/lib/cmssigdata.c | 1192 ++ Security/libsecurity_smime/lib/cmssiginfo.c | 1429 ++ Security/libsecurity_smime/lib/cmstpriv.h | 502 + Security/libsecurity_smime/lib/cmsutil.c | 412 + Security/libsecurity_smime/lib/cryptohi.c | 552 + Security/libsecurity_smime/lib/cryptohi.h | 143 + Security/libsecurity_smime/lib/plhash.c | 538 + Security/libsecurity_smime/lib/plhash.h | 164 + Security/libsecurity_smime/lib/secalgid.c | 172 + .../libsecurity_smime}/lib/secitem.c | 0 .../libsecurity_smime}/lib/secitem.h | 0 Security/libsecurity_smime/lib/secoid.c | 1490 ++ Security/libsecurity_smime/lib/secoid.h | 118 + Security/libsecurity_smime/lib/secoidt.h | 61 + .../libsecurity_smime/lib/security_smime.exp | 133 + .../libsecurity_smime}/lib/siginfoUtils.cpp | 2 +- Security/libsecurity_smime/lib/smimeutil.c | 802 ++ Security/libsecurity_smime/lib/testcms | 43 + .../libsecurity_smime}/lib/tsaSupport.c | 25 +- .../libsecurity_smime}/lib/tsaSupport.h | 2 +- .../libsecurity_smime}/lib/tsaSupportPriv.h | 3 +- .../libsecurity_smime}/lib/tsaTemplates.c | 21 +- .../libsecurity_smime}/lib/tsaTemplates.h | 2 +- .../project.pbxproj | 648 + .../regressions/smime-cms-test.c | 524 + .../regressions/smime_regressions.h | 29 + .../libsecurity_ssl}/Info-security_ssl.plist | 0 .../libsecurity_ssl}/README | 0 .../libsecurity_ssl}/Security | 0 Security/libsecurity_ssl/config/base.xcconfig | 16 + .../libsecurity_ssl}/config/debug.xcconfig | 0 .../libsecurity_ssl}/config/kext.xcconfig | 0 Security/libsecurity_ssl/config/lib.xcconfig | 30 + .../libsecurity_ssl}/config/release.xcconfig | 0 .../libsecurity_ssl/config/tests.xcconfig | 31 + .../libsecurity_ssl}/dtlsEcho/README | 0 .../dtlsEcho/dtlsEchoClient.c | 27 +- .../dtlsEcho/dtlsEchoServer.c | 27 +- .../libsecurity_ssl}/lib/CipherSuite.h | 8 +- .../libsecurity_ssl}/lib/ModuleAttacher.h | 0 .../libsecurity_ssl/lib/SSLRecordInternal.c | 418 + .../libsecurity_ssl/lib/SSLRecordInternal.h | 73 + .../libsecurity_ssl}/lib/SecureTransport.h | 15 +- .../lib/SecureTransportPriv.h | 59 +- .../libsecurity_ssl}/lib/appleCdsa.h | 8 +- .../libsecurity_ssl}/lib/appleSession.c | 14 +- .../libsecurity_ssl}/lib/appleSession.h | 10 +- .../libsecurity_ssl}/lib/cipherSpecs.c | 8 +- .../libsecurity_ssl}/lib/cipherSpecs.h | 8 +- .../libsecurity_ssl}/lib/cryptType.h | 8 +- Security/libsecurity_ssl/lib/secCrypto.c | 77 + .../lib/securetransport++.cpp | 2 +- .../libsecurity_ssl}/lib/securetransport++.h | 0 .../libsecurity_ssl}/lib/security_ssl.exp | 1 + .../libsecurity_ssl}/lib/ssl.h | 8 +- .../libsecurity_ssl}/lib/sslAlertMessage.h | 8 +- .../libsecurity_ssl}/lib/sslBER.c | 8 +- .../libsecurity_ssl}/lib/sslBER.h | 8 +- .../libsecurity_ssl}/lib/sslBuildFlags.h | 8 +- Security/libsecurity_ssl/lib/sslCipherSpecs.c | 529 + .../libsecurity_ssl}/lib/sslCipherSpecs.h | 8 +- .../libsecurity_ssl}/lib/sslContext.c | 749 +- Security/libsecurity_ssl/lib/sslContext.h | 286 + Security/libsecurity_ssl/lib/sslCrypto.c | 569 + Security/libsecurity_ssl/lib/sslCrypto.h | 83 + .../libsecurity_ssl}/lib/sslDebug.h | 8 +- .../libsecurity_ssl}/lib/sslDigests.c | 8 +- .../libsecurity_ssl}/lib/sslDigests.h | 8 +- .../libsecurity_ssl}/lib/sslHandshake.h | 15 +- Security/libsecurity_ssl/lib/sslKeychain.c | 236 + Security/libsecurity_ssl/lib/sslKeychain.h | 53 + .../libsecurity_ssl}/lib/sslMemory.c | 8 +- .../libsecurity_ssl}/lib/sslMemory.h | 8 +- .../libsecurity_ssl}/lib/sslNullCipher.c | 8 +- .../libsecurity_ssl}/lib/sslPriv.h | 8 +- .../libsecurity_ssl}/lib/sslRand.c | 8 +- .../libsecurity_ssl}/lib/sslRand.h | 8 +- Security/libsecurity_ssl/lib/sslRecord.c | 126 + .../libsecurity_ssl}/lib/sslRecord.h | 8 +- .../libsecurity_ssl}/lib/sslSession.c | 22 +- .../libsecurity_ssl}/lib/sslSession.h | 8 +- Security/libsecurity_ssl/lib/sslTransport.c | 450 + .../libsecurity_ssl}/lib/sslTypes.h | 29 +- .../libsecurity_ssl}/lib/sslUtils.c | 8 +- .../libsecurity_ssl}/lib/sslUtils.h | 8 +- .../libsecurity_ssl}/lib/symCipher.c | 8 +- .../libsecurity_ssl}/lib/symCipher.h | 8 +- .../libsecurity_ssl}/lib/symCipherParams.c | 8 +- Security/libsecurity_ssl/lib/tlsCallbacks.c | 231 + Security/libsecurity_ssl/lib/tlsCallbacks.h | 32 + .../libsecurity_ssl}/lib/tls_digest.c | 8 +- .../libsecurity_ssl}/lib/tls_digest.h | 8 +- .../libsecurity_ssl}/lib/tls_hashhmac.c | 8 +- .../libsecurity_ssl}/lib/tls_hashhmac.h | 8 +- .../libsecurity_ssl}/lib/tls_hmac.c | 8 +- .../libsecurity_ssl}/lib/tls_hmac.h | 8 +- .../libsecurity_ssl/lib/tls_record_internal.h | 81 + .../libsecurity_ssl}/lib/tls_ssl.h | 8 +- .../libsecurity_ssl.xcodeproj/project.pbxproj | 938 ++ .../regressions/ClientCert_ecc_ecc.h | 0 .../regressions/ClientCert_ecc_rsa.h | 0 .../regressions/ClientCert_rsa_ecc.h | 0 .../regressions/ClientCert_rsa_rsa.h | 0 .../regressions/ClientKey_ecc.h | 0 .../regressions/ClientKey_rsa.h | 0 .../SECG_ecc-secp256r1-client_cert.h | 0 .../SECG_ecc-secp256r1-client_key.h | 0 .../SECG_ecc_rsa-secp256r1-client_cert.h | 0 .../SECG_ecc_rsa-secp256r1-client_key.h | 0 .../libsecurity_ssl}/regressions/cert-1.h | 0 .../libsecurity_ssl}/regressions/gencerts.sh | 0 .../libsecurity_ssl}/regressions/identity-1.h | 0 .../libsecurity_ssl}/regressions/privkey-1.h | 0 .../regressions/ssl-39-echo.c | 2 +- .../regressions/ssl-40-clientauth.c | 4 +- .../regressions/ssl-41-clientauth.c | 10 +- .../regressions/ssl-42-ciphers.c | 240 +- .../regressions/ssl-43-ciphers.c | 64 +- .../regressions/ssl-44-crashes.c | 42 +- .../regressions/ssl-45-tls12.c | 34 +- .../ssl-46-SSLGetSupportedCiphers.c | 30 +- .../regressions/ssl-47-falsestart.c | 36 +- .../regressions/ssl-48-split.c | 357 + .../libsecurity_ssl/regressions/ssl-49-sni.c | 273 + .../regressions/ssl-50-server.c | 266 + .../regressions/ssl-51-state.c | 503 + .../libsecurity_ssl/regressions/ssl-utils.c | 276 + .../libsecurity_ssl/regressions/ssl-utils.h | 38 + .../regressions/ssl_regressions.h | 31 + .../libsecurity_ssl}/security_ssl | 0 Security/libsecurity_ssl/sslViewer/fileIo.c | 116 + Security/libsecurity_ssl/sslViewer/fileIo.h | 44 + Security/libsecurity_ssl/sslViewer/ioSock.c | 502 + Security/libsecurity_ssl/sslViewer/ioSock.h | 110 + .../libsecurity_ssl}/sslViewer/printCert.c | 8 +- .../libsecurity_ssl}/sslViewer/printCert.h | 8 +- .../libsecurity_ssl/sslViewer/sslAppUtils.cpp | 1650 +++ .../libsecurity_ssl/sslViewer/sslAppUtils.h | 167 + .../libsecurity_ssl}/sslViewer/sslServer.1 | 0 .../libsecurity_ssl/sslViewer/sslServer.cpp | 1061 ++ .../libsecurity_ssl}/sslViewer/sslViewer.1 | 0 .../libsecurity_ssl}/sslViewer/sslViewer.cpp | 2 +- .../sslViewer.xcodeproj/project.pbxproj | 0 .../libsecurity_transform}/100-sha2.m | 27 +- .../libsecurity_transform.Default.xcconfig | 0 .../libsecurity_transform_Deployment.xcconfig | 0 ...libsecurity_transform_Development.xcconfig | 0 .../libsecurity_transform_core.xcconfig | 0 .../security_transform_Default.xcconfig | 0 .../security_transform_Deployment.xcconfig | 0 .../security_transform_Development.xcconfig | 0 .../Info-security_transform.plist | 0 .../libsecurity_transform}/NSData+HexString.h | 2 +- .../libsecurity_transform}/NSData+HexString.m | 4 +- Security/libsecurity_transform/custom.h | 32 + .../libsecurity_transform}/custom.mm | 145 +- .../lib/CEncryptDecrypt.c | 0 .../lib/CoreFoundationBasics.cpp | 0 .../lib/CoreFoundationBasics.h | 0 .../libsecurity_transform}/lib/Digest.cpp | 0 .../libsecurity_transform}/lib/Digest.h | 0 .../libsecurity_transform}/lib/Digest_block.c | 25 +- .../libsecurity_transform/lib/Digest_block.h | 24 + .../lib/EncodeDecodeTransforms.c | 29 +- .../lib/EncryptTransform.cpp | 232 +- .../lib/EncryptTransform.h | 2 +- .../lib/EncryptTransformUtilities.cpp | 2 +- .../lib/EncryptTransformUtilities.h | 2 +- .../lib/GroupTransform.cpp | 2 +- .../lib/GroupTransform.h | 0 .../libsecurity_transform}/lib/LinkedList.cpp | 0 .../libsecurity_transform}/lib/LinkedList.h | 0 .../libsecurity_transform}/lib/Monitor.cpp | 0 .../libsecurity_transform}/lib/Monitor.h | 0 .../lib/NullTransform.cpp | 0 .../lib/NullTransform.h | 0 .../lib/SecCollectTransform.cpp | 2 +- .../lib/SecCollectTransform.h | 2 +- .../lib/SecCustomTransform.cpp | 27 +- .../lib/SecCustomTransform.h | 11 +- .../lib/SecDecodeTransform.h | 2 +- .../lib/SecDigestTransform.cpp | 0 .../lib/SecDigestTransform.h | 2 +- .../lib/SecEncodeTransform.h | 2 +- .../lib/SecEncryptTransform.cpp | 2 +- .../lib/SecEncryptTransform.h | 16 +- .../lib/SecExternalSourceTransform.cpp | 56 + .../lib/SecExternalSourceTransform.h | 2 +- .../lib/SecGroupTransform.cpp | 51 + .../lib/SecGroupTransform.h | 0 .../lib/SecMaskGenerationFunctionTransform.c | 32 +- .../lib/SecMaskGenerationFunctionTransform.h | 0 .../lib/SecNullTransform.cpp | 0 .../lib/SecNullTransform.h | 0 .../lib/SecReadTransform.h | 0 .../lib/SecSignVerifyTransform.c | 25 +- .../lib/SecSignVerifyTransform.h | 2 +- .../lib/SecTransform.cpp | 184 +- .../libsecurity_transform}/lib/SecTransform.h | 2 +- .../lib/SecTransformInternal.h | 0 .../lib/SecTransformReadTransform.cpp | 0 .../lib/SecTransformReadTransform.h | 2 +- .../lib/SecTransformValidator.h | 2 +- .../lib/SingleShotSource.cpp | 0 .../lib/SingleShotSource.h | 0 .../libsecurity_transform}/lib/Source.cpp | 0 .../libsecurity_transform}/lib/Source.h | 0 .../lib/StreamSource.cpp | 0 .../libsecurity_transform}/lib/StreamSource.h | 0 .../libsecurity_transform}/lib/Transform.cpp | 2 +- .../libsecurity_transform}/lib/Transform.h | 0 .../lib/TransformFactory.cpp | 0 .../lib/TransformFactory.h | 0 .../libsecurity_transform}/lib/Utilities.cpp | 23 + .../libsecurity_transform}/lib/Utilities.h | 0 .../libsecurity_transform}/lib/c++utils.cpp | 0 .../libsecurity_transform}/lib/c++utils.h | 0 .../libsecurity_transform}/lib/misc.c | 27 +- Security/libsecurity_transform/lib/misc.h | 51 + .../lib/security_transform.exp | 0 .../project.pbxproj | 869 ++ .../misc/base32alpha2vals | 0 .../libsecurity_transform/misc/speed-test.h | 32 + .../libsecurity_transform/misc/speed-test.mm | 108 + .../unit-tests-Info.plist | 0 .../libsecurity_utilities}/APPLE_LICENSE | 0 .../Info-security_utilities.plist | 0 .../libsecurity_utilities}/lib/adornments.cpp | 2 +- .../libsecurity_utilities}/lib/adornments.h | 2 +- .../libsecurity_utilities}/lib/alloc.cpp | 2 +- .../libsecurity_utilities}/lib/alloc.h | 2 +- .../libsecurity_utilities}/lib/blob.cpp | 2 +- .../libsecurity_utilities}/lib/blob.h | 2 +- .../libsecurity_utilities}/lib/bufferfifo.cpp | 2 +- .../libsecurity_utilities}/lib/bufferfifo.h | 2 +- .../libsecurity_utilities}/lib/buffers.cpp | 2 +- .../libsecurity_utilities}/lib/buffers.h | 2 +- .../libsecurity_utilities}/lib/ccaudit.cpp | 2 +- Security/libsecurity_utilities/lib/ccaudit.h | 189 + .../libsecurity_utilities}/lib/cfclass.cpp | 2 +- .../libsecurity_utilities}/lib/cfclass.h | 2 +- .../libsecurity_utilities}/lib/cfmach++.cpp | 2 +- .../libsecurity_utilities}/lib/cfmach++.h | 2 +- .../libsecurity_utilities}/lib/cfmunge.cpp | 2 +- .../libsecurity_utilities}/lib/cfmunge.h | 2 +- .../lib/cfutilities.cpp | 20 +- .../libsecurity_utilities}/lib/cfutilities.h | 2 +- .../lib/coderepository.cpp | 2 +- .../lib/coderepository.h | 2 +- .../libsecurity_utilities}/lib/crc.c | 0 .../libsecurity_utilities}/lib/crc.h | 0 .../libsecurity_utilities}/lib/daemon.cpp | 2 +- .../libsecurity_utilities}/lib/daemon.h | 2 +- .../libsecurity_utilities}/lib/debugging.cpp | 2 +- .../libsecurity_utilities/lib/debugging.h | 129 + .../lib/debugging_internal.cpp | 2 +- .../lib/debugging_internal.h | 61 + .../libsecurity_utilities}/lib/debugsupport.h | 2 +- .../libsecurity_utilities}/lib/devrandom.cpp | 2 +- .../libsecurity_utilities}/lib/devrandom.h | 2 +- .../libsecurity_utilities}/lib/dtrace.mk | 0 .../lib/dyld_cache_format.h | 2 +- .../libsecurity_utilities}/lib/dyldcache.cpp | 2 +- .../libsecurity_utilities}/lib/dyldcache.h | 2 +- .../libsecurity_utilities}/lib/endian.cpp | 2 +- .../libsecurity_utilities}/lib/endian.h | 2 +- .../libsecurity_utilities}/lib/errors.cpp | 2 +- .../libsecurity_utilities}/lib/errors.h | 2 +- .../libsecurity_utilities}/lib/exports | 0 .../libsecurity_utilities}/lib/fdmover.cpp | 2 +- .../libsecurity_utilities}/lib/fdmover.h | 2 +- .../libsecurity_utilities}/lib/fdsel.cpp | 2 +- .../libsecurity_utilities}/lib/fdsel.h | 2 +- .../libsecurity_utilities}/lib/globalizer.cpp | 2 +- .../libsecurity_utilities}/lib/globalizer.h | 2 +- .../libsecurity_utilities}/lib/hashing.cpp | 2 +- .../libsecurity_utilities}/lib/hashing.h | 2 +- .../libsecurity_utilities}/lib/headermap.cpp | 2 +- .../libsecurity_utilities}/lib/headermap.h | 2 +- .../libsecurity_utilities}/lib/hosts.cpp | 2 +- .../libsecurity_utilities}/lib/hosts.h | 2 +- .../libsecurity_utilities}/lib/inetreply.cpp | 2 +- .../libsecurity_utilities}/lib/inetreply.h | 2 +- .../libsecurity_utilities}/lib/iodevices.cpp | 2 +- .../libsecurity_utilities}/lib/iodevices.h | 2 +- .../libsecurity_utilities}/lib/ip++.cpp | 2 +- .../libsecurity_utilities}/lib/ip++.h | 2 +- .../libsecurity_utilities}/lib/kq++.cpp | 2 +- .../libsecurity_utilities}/lib/kq++.h | 2 +- .../libsecurity_utilities}/lib/ktracecodes.h | 2 +- .../libsecurity_utilities}/lib/logging.cpp | 2 +- .../libsecurity_utilities}/lib/logging.h | 2 +- .../libsecurity_utilities}/lib/mach++.cpp | 2 +- .../libsecurity_utilities}/lib/mach++.h | 2 +- .../libsecurity_utilities}/lib/mach_notify.c | 2 +- .../libsecurity_utilities}/lib/mach_notify.h | 2 +- .../libsecurity_utilities}/lib/macho++.cpp | 10 +- .../libsecurity_utilities}/lib/macho++.h | 8 +- .../lib/machrunloopserver.cpp | 2 +- .../lib/machrunloopserver.h | 2 +- .../libsecurity_utilities}/lib/machserver.cpp | 2 +- .../libsecurity_utilities}/lib/machserver.h | 2 +- .../libsecurity_utilities}/lib/memstreams.h | 2 +- .../libsecurity_utilities}/lib/memutils.h | 2 +- .../libsecurity_utilities}/lib/muscle++.cpp | 2 +- .../libsecurity_utilities}/lib/muscle++.h | 2 +- .../libsecurity_utilities}/lib/osxcode.cpp | 2 +- .../libsecurity_utilities}/lib/osxcode.h | 2 +- .../libsecurity_utilities}/lib/pcsc++.cpp | 4 +- .../libsecurity_utilities}/lib/pcsc++.h | 2 +- .../libsecurity_utilities}/lib/powerwatch.cpp | 2 +- .../libsecurity_utilities}/lib/powerwatch.h | 2 +- .../libsecurity_utilities}/lib/refcount.h | 3 +- .../lib/seccfobject.cpp | 2 +- .../libsecurity_utilities}/lib/seccfobject.h | 2 +- .../lib/security_utilities.d | 0 .../lib/security_utilities.h | 2 +- .../libsecurity_utilities}/lib/selector.cpp | 2 +- .../libsecurity_utilities}/lib/selector.h | 2 +- .../lib/simpleprefs.cpp | 2 +- .../libsecurity_utilities}/lib/simpleprefs.h | 2 +- .../libsecurity_utilities}/lib/socks++.cpp | 2 +- .../libsecurity_utilities}/lib/socks++.h | 2 +- .../libsecurity_utilities}/lib/socks++4.cpp | 2 +- .../libsecurity_utilities}/lib/socks++4.h | 2 +- .../libsecurity_utilities}/lib/socks++5.cpp | 2 +- .../libsecurity_utilities}/lib/socks++5.h | 2 +- .../libsecurity_utilities}/lib/sqlite++.cpp | 2 +- .../libsecurity_utilities}/lib/sqlite++.h | 2 +- .../libsecurity_utilities}/lib/streams.cpp | 2 +- .../libsecurity_utilities}/lib/streams.h | 2 +- .../libsecurity_utilities}/lib/superblob.cpp | 0 .../libsecurity_utilities}/lib/superblob.h | 0 .../libsecurity_utilities}/lib/threading.cpp | 2 +- .../libsecurity_utilities}/lib/threading.h | 2 +- .../lib/threading_internal.h | 2 +- .../libsecurity_utilities}/lib/timeflow.cpp | 2 +- .../libsecurity_utilities}/lib/timeflow.h | 2 +- .../libsecurity_utilities}/lib/tqueue.cpp | 2 +- .../libsecurity_utilities}/lib/tqueue.h | 2 +- .../lib/trackingallocator.cpp | 2 +- .../lib/trackingallocator.h | 2 +- .../lib/transactions.cpp | 2 +- .../libsecurity_utilities}/lib/transactions.h | 2 +- .../libsecurity_utilities}/lib/typedvalue.cpp | 2 +- .../libsecurity_utilities}/lib/typedvalue.h | 2 +- .../libsecurity_utilities}/lib/unix++.cpp | 3 +- .../libsecurity_utilities}/lib/unix++.h | 2 +- .../libsecurity_utilities}/lib/unixchild.cpp | 2 +- .../libsecurity_utilities}/lib/unixchild.h | 2 +- .../libsecurity_utilities}/lib/url.cpp | 2 +- .../libsecurity_utilities}/lib/url.h | 2 +- .../libsecurity_utilities}/lib/utilities.cpp | 2 +- .../libsecurity_utilities/lib/utilities.h | 315 + .../lib/utility_config.h | 2 +- .../libsecurity_utilities}/lib/vproc++.cpp | 2 +- .../libsecurity_utilities}/lib/vproc++.h | 2 +- .../project.pbxproj | 0 Security/libsecurityd/APPLE_LICENSE | 335 + .../libsecurityd}/Info-securityd_client.plist | 0 .../libsecurityd}/Info-securityd_server.plist | 0 .../libsecurityd}/lib/SharedMemoryClient.cpp | 0 .../libsecurityd}/lib/SharedMemoryClient.h | 0 .../libsecurityd/lib/SharedMemoryCommon.h | 43 + .../libsecurityd}/lib/dictionary.cpp | 2 +- .../libsecurityd}/lib/dictionary.h | 8 +- .../libsecurityd}/lib/eventlistener.cpp | 2 +- .../libsecurityd}/lib/eventlistener.h | 2 +- .../libsecurityd}/lib/handletypes.h | 2 +- .../libsecurityd}/lib/sec_xdr.c | 2 +- .../libsecurityd}/lib/sec_xdr.h | 2 +- .../libsecurityd}/lib/sec_xdr_array.c | 2 +- .../libsecurityd}/lib/sec_xdr_reference.c | 2 +- .../libsecurityd}/lib/sec_xdr_sizeof.c | 2 +- .../libsecurityd}/lib/sec_xdrmem.c | 2 +- .../libsecurityd}/lib/ss_types.h | 2 +- .../libsecurityd}/lib/ssblob.cpp | 2 +- .../libsecurityd}/lib/ssblob.h | 2 +- .../libsecurityd}/lib/ssclient.cpp | 2 +- .../libsecurityd}/lib/ssclient.h | 2 +- .../libsecurityd}/lib/sscommon.h | 2 +- .../libsecurityd}/lib/ssnotify.h | 2 +- .../libsecurityd}/lib/sstransit.cpp | 2 +- .../libsecurityd}/lib/sstransit.h | 2 +- Security/libsecurityd/lib/transition.cpp | 1066 ++ .../libsecurityd}/lib/ucsp_types.h | 2 +- .../libsecurityd}/lib/xdr_auth.c | 2 +- .../libsecurityd}/lib/xdr_auth.h | 2 +- .../libsecurityd}/lib/xdr_cssm.c | 2 +- .../libsecurityd}/lib/xdr_cssm.h | 2 +- .../libsecurityd}/lib/xdr_dldb.cpp | 2 +- .../libsecurityd}/lib/xdr_dldb.h | 2 +- .../libsecurityd.xcodeproj/project.pbxproj | 0 .../libsecurityd}/mig/cshosting.defs | 2 +- Security/libsecurityd/mig/mig.mk | 67 + .../libsecurityd}/mig/ss_types.defs | 2 +- .../libsecurityd}/mig/ucsp.defs | 2 +- .../libsecurityd}/mig/ucspNotify.defs | 2 +- {regressions => Security/regressions}/README | 0 .../regressions}/inc/IPC/Run3.pm | 0 .../regressions}/inc/MyHarness.pm | 0 .../regressions.xcodeproj/project.pbxproj | 351 + Security/regressions/t/security.pl | 68 + .../regressions}/test/test-00-test.c | 3 +- .../regressions}/test/test_regressions.h | 0 .../regressions}/test/testcert.c | 13 +- .../regressions}/test/testcert.h | 9 +- Security/regressions/test/testcpp.h | 83 + Security/regressions/test/testenv.c | 345 + Security/regressions/test/testenv.h | 42 + .../regressions}/test/testlist_begin.h | 0 .../regressions}/test/testlist_end.h | 0 Security/regressions/test/testmore.c | 350 + Security/regressions/test/testmore.h | 213 + Security/regressions/test/testpolicy.h | 35 + .../regressions}/test/testpolicy.m | 54 +- .../CloudKeychainProxy/CloudKeychainProxy.1 | 0 .../sec}/SOSCircle/CKBridge/CKClient.c | 2 +- .../sec}/SOSCircle/CKBridge/CKClient.h | 2 +- .../CKBridge/SOSCloudKeychainClient.c | 682 + .../CKBridge/SOSCloudKeychainClient.h | 122 + .../CKBridge/SOSCloudKeychainConstants.c | 24 +- .../CKBridge/SOSCloudKeychainConstants.h | 29 +- .../SOSCircle/CKBridge/SOSCloudTransport.c | 2 +- .../SOSCircle/CKBridge/SOSCloudTransport.h | 2 +- .../CloudKeychainProxy/CKDKVSProxy.h | 119 + .../CloudKeychainProxy/CKDKVSProxy.m | 1058 ++ .../CloudKeychainProxy/CKDPersistentState.h | 2 +- .../CloudKeychainProxy/CKDPersistentState.m | 2 +- .../CloudKeychainProxy/CKDUserInteraction.h | 8 +- .../CloudKeychainProxy/CKDUserInteraction.m | 8 +- .../SOSCircle/CloudKeychainProxy/ckdmain.m | 4 +- .../cloudkeychain.entitlements.plist | 19 + .../CloudKeychainProxy/cloudkeychainproxy.m | 465 + .../en.lproj/InfoPlist.strings | 2 + .../scripts/PhoneTerms2.applescript | 126 + .../scripts/PhoneTerms2.scpt | Bin .../scripts/install_on_devices | 11 + .../CloudKeychainProxy/scripts/kcstatus | 6 + .../CloudKeychainProxy/scripts/sosbuildroot | 1 + .../CloudKeychainProxy/scripts/soscopy | 0 .../CloudKeychainProxy/scripts/soscopysshkeys | 0 .../CloudKeychainProxy/scripts/sosinstallroot | 0 .../CloudKeychainProxy/scripts/sosreset | 0 .../CloudKeychainProxy/scripts/tweak | 131 + Security/sec/SOSCircle/Empty.c | 0 .../SOSCircle/Regressions/CKDKeyValueStore.h | 94 + .../SOSCircle/Regressions/CKDKeyValueStore.m | 8 +- .../Regressions/SOSCircle_regressions.h | 19 +- .../Regressions/SOSRegressionUtilities.c | 52 +- .../Regressions/SOSRegressionUtilities.h | 7 +- .../SOSCircle/Regressions/SOSTestDataSource.c | 507 + .../SOSCircle/Regressions/SOSTestDataSource.h | 61 + .../sec/SOSCircle/Regressions/SOSTestDevice.c | 379 + .../sec/SOSCircle/Regressions/SOSTestDevice.h | 63 + .../SOSCircle/Regressions/sc-103-syncupdate.c | 41 +- .../Regressions/sc-130-resignationticket.c | 32 +- .../SOSCircle/Regressions/sc-131-transport.c | 48 + .../SOSCircle/Regressions/sc-20-keynames.c | 29 +- .../SOSCircle/Regressions/sc-30-peerinfo.c | 124 + .../Regressions/sc-31-peerinfo-simplefuzz.c | 83 + .../sec/SOSCircle/Regressions/sc-40-circle.c | 117 + .../SOSCircle/Regressions/sc-41-cloudcircle.c | 64 + .../Regressions/sc-42-circlegencount.c | 67 + .../Regressions/sc-45-digestvector.c | 157 + .../sec/SOSCircle/Regressions/sc-50-message.c | 261 + .../Regressions/sc-51-persistentEC.c | 4 +- .../sec/SOSCircle/Regressions/sc-60-peer.c | 157 + .../sec}/SOSCircle/Regressions/sc-70-engine.c | 71 +- .../Regressions/sc-75-circle-engine.c | 296 + .../SOSCircle/Regressions/sc-90-ckdclient.c | 35 +- .../SOSCircle/Regressions/sc-95-ckd2client.c | 30 +- .../sec}/SOSCircle/Regressions/sc-kvstool.m | 34 +- Security/sec/SOSCircle/SOSARCDefines.h | 65 + .../SOSCircle/SecureObjectSync/SOSAccount.c | 1026 ++ .../SOSCircle/SecureObjectSync/SOSAccount.h | 214 + .../SecureObjectSync/SOSAccountCircles.c | 170 + .../SOSAccountCloudParameters.c | 85 + .../SecureObjectSync/SOSAccountCredentials.c | 266 + .../SecureObjectSync/SOSAccountDer.c | 153 + .../SecureObjectSync/SOSAccountFullPeerInfo.c | 186 + .../SecureObjectSync/SOSAccountPeers.c | 176 + .../SecureObjectSync/SOSAccountPersistence.c | 709 + .../SecureObjectSync/SOSAccountPriv.h | 293 + .../SecureObjectSync/SOSAccountUpdate.c | 479 + .../SOSCircle/SecureObjectSync/SOSCircle.c | 1261 ++ .../SOSCircle/SecureObjectSync/SOSCircle.h | 57 +- .../SecureObjectSync/SOSCloudCircle.c | 556 + .../SecureObjectSync/SOSCloudCircle.h | 80 +- .../SecureObjectSync/SOSCloudCircleInternal.h | 54 + .../sec/SOSCircle/SecureObjectSync/SOSCoder.c | 552 + .../sec/SOSCircle/SecureObjectSync/SOSCoder.h | 72 + .../SecureObjectSync/SOSDataSource.h | 228 + .../SecureObjectSync/SOSDigestVector.c | 379 + .../SecureObjectSync/SOSDigestVector.h | 96 + .../SOSCircle/SecureObjectSync/SOSEngine.c | 1087 ++ .../SOSCircle/SecureObjectSync/SOSEngine.h | 102 + .../SecureObjectSync/SOSExports.exp-in | 17 +- .../SecureObjectSync/SOSFullPeerInfo.c | 42 +- .../SecureObjectSync/SOSFullPeerInfo.h | 76 + .../SOSCircle/SecureObjectSync/SOSInternal.c | 51 +- .../SOSCircle/SecureObjectSync/SOSInternal.h | 106 + .../SOSCircle/SecureObjectSync/SOSKVSKeys.c | 233 + .../SOSCircle/SecureObjectSync/SOSKVSKeys.h | 50 + .../SOSCircle/SecureObjectSync/SOSManifest.c | 228 + .../SOSCircle/SecureObjectSync/SOSManifest.h | 101 + .../SOSCircle/SecureObjectSync/SOSMessage.c | 1183 ++ .../SOSCircle/SecureObjectSync/SOSMessage.h | 137 + .../sec/SOSCircle/SecureObjectSync/SOSPeer.c | 498 + .../sec/SOSCircle/SecureObjectSync/SOSPeer.h | 112 + .../SOSCircle/SecureObjectSync/SOSPeerCoder.c | 160 + .../SOSCircle/SecureObjectSync/SOSPeerCoder.h | 23 + .../SOSCircle/SecureObjectSync/SOSPeerInfo.c | 261 +- .../SOSCircle/SecureObjectSync/SOSPeerInfo.h | 139 + .../SecureObjectSync/SOSPeerInfoCollections.c | 245 + .../SecureObjectSync/SOSPeerInfoCollections.h | 64 + .../SecureObjectSync/SOSPeerInfoInternal.h | 33 + .../SOSCircle/SecureObjectSync/SOSTransport.c | 437 + .../SOSCircle/SecureObjectSync/SOSTransport.h | 26 + .../SecureObjectSync/SOSTransportCircle.c | 76 + .../SecureObjectSync/SOSTransportCircle.h | 45 + .../SecureObjectSync/SOSTransportCircleKVS.c | 249 + .../SecureObjectSync/SOSTransportCircleKVS.h | 19 + .../SecureObjectSync/SOSTransportCoder.c | 221 + .../SecureObjectSync/SOSTransportCoder.h | 19 + .../SOSTransportKeyParameter.c | 62 + .../SOSTransportKeyParameter.h | 34 + .../SOSTransportKeyParameterKVS.c | 89 + .../SOSTransportKeyParameterKVS.h | 16 + .../SecureObjectSync/SOSTransportMessage.c | 172 + .../SecureObjectSync/SOSTransportMessage.h | 51 + .../SecureObjectSync/SOSTransportMessageKVS.c | 249 + .../SecureObjectSync/SOSTransportMessageKVS.h | 28 + .../SecureObjectSync/SOSUserKeygen.c | 30 +- .../SecureObjectSync/SOSUserKeygen.h | 35 + Security/sec/SOSCircle/Tool/SOSCommands.h | 52 + Security/sec/SOSCircle/Tool/keychain_sync.c | 579 + Security/sec/SOSCircle/osxshim.c | 65 + .../AppleBaselineEscrowCertificates.h | 178 + .../sec}/Security/AuthorizationStatus.h | 0 .../Regressions/Security_regressions.h | 99 + .../Regressions/crypto/pbkdf2-00-hmac-sha1.c | 2 +- .../Regressions/crypto/spbkdf-00-hmac-sha1.c | 2 +- .../Regressions/otr/otr-00-identity.c | 25 +- .../Regressions/otr/otr-30-negotiation.c | 67 +- .../sec/Security/Regressions/otr/otr-otrdh.c | 61 + .../Security/Regressions/otr/otr-packetdata.c | 283 + .../Regressions/secitem/si-00-find-nothing.c | 2 +- .../Security/Regressions/secitem/si-05-add.c | 25 +- .../Regressions/secitem/si-10-find-internet.c | 2 +- .../Regressions/secitem/si-11-update-data.c | 2 +- .../Regressions/secitem/si-12-item-stress.c | 32 +- .../Regressions/secitem/si-14-dateparse.c | 32 +- .../Regressions/secitem/si-15-certificate.c | 2 +- .../secitem/si-16-ec-certificate.c | 27 +- .../secitem/si-20-sectrust-activation.c | 2 +- .../Regressions/secitem/si-20-sectrust.c | 902 ++ .../Regressions/secitem/si-21-sectrust-asr.c | 2 +- .../Regressions/secitem/si-22-sectrust-iap.c | 9 +- .../secitem/si-23-sectrust-ocsp-wwdr.c | 2 +- .../Regressions/secitem/si-23-sectrust-ocsp.c | 54 +- .../secitem/si-24-sectrust-appleid.c | 2 +- .../si-24-sectrust-digicert-malaysia.c | 2 +- .../secitem/si-24-sectrust-diginotar.c | 2 +- .../Regressions/secitem/si-24-sectrust-itms.c | 9 +- .../secitem/si-24-sectrust-mobileasset.c | 2 +- .../Regressions/secitem/si-24-sectrust-nist.c | 2 +- .../secitem/si-24-sectrust-otatasking.c | 2 +- .../secitem/si-24-sectrust-shoebox.c | 53 +- .../secitem/si-25-sectrust-ipsec-eap.c | 17 +- .../secitem/si-26-applicationsigning.c | 2 +- .../secitem/si-27-sectrust-exceptions.c | 4 +- .../secitem/si-28-sectrustsettings.c | 2 +- .../secitem/si-29-sectrust-codesigning.c | 2 +- .../secitem/si-30-keychain-upgrade.c | 27 +- .../Regressions/secitem/si-31-keychain-bad.c | 25 +- .../secitem/si-31-keychain-unreadable.c | 104 + .../secitem/si-33-keychain-backup.c | 523 + .../Regressions/secitem/si-40-seckey-custom.c | 253 + .../Regressions/secitem/si-40-seckey.c | 31 +- .../Regressions/secitem/si-41-sececkey.c | 391 + .../Regressions/secitem/si-42-identity.c | 25 +- .../Regressions/secitem/si-43-persistent.c | 2 +- .../Regressions/secitem/si-50-secrandom.c | 49 + .../Security/Regressions/secitem/si-60-cms.c | 27 +- .../Regressions/secitem/si-61-pkcs12.c | 25 +- .../Security/Regressions/secitem/si-62-csr.c | 27 +- .../Security/Regressions/secitem/si-63-scep.c | 40 +- .../Security/Regressions/secitem/si-63-scep.h | 0 .../secitem/si-63-scep/getcacert-mdes.h | 0 .../secitem/si-63-scep/getcacert-mdesqa.h | 0 .../Regressions/secitem/si-64-ossl-cms.c | 27 +- .../attached_no_data_signed_data.h | 0 .../si-64-ossl-cms/attached_signed_data.h | 0 .../secitem/si-64-ossl-cms/detached_content.h | 0 .../si-64-ossl-cms/detached_signed_data.h | 0 .../secitem/si-64-ossl-cms/privkey.h | 0 .../secitem/si-64-ossl-cms/signer.h | 0 .../secitem/si-65-cms-cert-policy.c | 25 +- .../Regressions/secitem/si-66-smime.c | 28 +- .../secitem/si-66-smime/signed-receipt.h | 0 .../secitem/si-67-sectrust-blacklist.c | 147 + .../Global Trustee.cer.h | 0 .../UTN-USERFirst-Hardware.cer.h | 0 .../addons.mozilla.org.cer.h | 0 .../login.live.com.cer.h | 0 .../login.skype.com.cer.h | 0 .../login.yahoo.com.1.cer.h | 0 .../login.yahoo.com.2.cer.h | 0 .../login.yahoo.com.cer.h | 0 .../mail.google.com.cer.h | 0 .../www.google.com.cer.h | 0 .../secitem/si-68-secmatchissuer.c | 24 +- .../Regressions/secitem/si-69-keydesc.c | 36 +- .../secitem/si-70-sectrust-unified.c | 369 + .../secitem/si-71-mobile-store-policy.c | 575 + .../Regressions/secitem/si-72-syncableitems.c | 24 +- .../secitem/si-73-secpasswordgenerate.c | 93 +- .../Regressions/secitem/si-74-OTAPKISigner.c | 29 +- .../secitem/si-75-AppleIDRecordSigning.c | 32 +- .../secitem/si-76-shared-credentials.c | 163 + .../Regressions/secitem/si-78-query-attrs.c | 128 + .../secitem/si-79-smp-cert-policy.c | 410 + .../Regressions/secitem/si-80-empty-data.c | 59 + .../secitem/si-81-item-acl-stress.c | 287 + .../secitem/si-81-sectrust-server-auth.c | 557 + .../secitem/si_77_SecAccessControl.c | 247 + .../sec}/Security/Regressions/vmdh/vmdh-40.c | 2 +- .../Regressions/vmdh/vmdh-41-example.c | 6 +- .../Regressions/vmdh/vmdh-42-example2.c | 4 +- Security/sec/Security/SecAccessControl.c | 313 + Security/sec/Security/SecAccessControl.h | 64 + .../Security/SecAccessControlExports.exp-in | 28 + Security/sec/Security/SecAccessControlPriv.h | 128 + Security/sec/Security/SecBase.h | 112 + {sec => Security/sec}/Security/SecBase64.c | 0 {sec => Security/sec}/Security/SecBase64.h | 0 Security/sec/Security/SecBasePriv.h | 125 + Security/sec/Security/SecCMS.c | 696 + Security/sec/Security/SecCMS.h | 173 + .../sec}/Security/SecCertificate.c | 195 +- Security/sec/Security/SecCertificate.h | 87 + .../sec}/Security/SecCertificateInternal.h | 8 +- .../sec}/Security/SecCertificatePath.c | 35 +- .../sec}/Security/SecCertificatePath.h | 2 +- Security/sec/Security/SecCertificatePriv.h | 201 + .../sec}/Security/SecCertificateRequest.c | 100 +- Security/sec/Security/SecCertificateRequest.h | 135 + Security/sec/Security/SecDH.c | 380 + {sec => Security/sec}/Security/SecDH.h | 21 +- Security/sec/Security/SecECKey.c | 848 ++ {sec => Security/sec}/Security/SecECKey.h | 17 +- Security/sec/Security/SecECKeyPriv.h | 43 + .../sec}/Security/SecExports.exp-in | 67 +- {sec => Security/sec}/Security/SecFramework.c | 73 +- {sec => Security/sec}/Security/SecFramework.h | 2 +- .../sec}/Security/SecFrameworkStrings.h | 33 +- Security/sec/Security/SecIdentity.c | 106 + Security/sec/Security/SecIdentity.h | 75 + Security/sec/Security/SecIdentityPriv.h | 48 + Security/sec/Security/SecImportExport.c | 172 + Security/sec/Security/SecImportExport.h | 94 + Security/sec/Security/SecInternal.h | 76 + {sec => Security/sec}/Security/SecItem.c | 295 +- Security/sec/Security/SecItem.h | 1006 ++ Security/sec/Security/SecItemConstants.c | 224 + .../sec}/Security/SecItemInternal.h | 8 +- Security/sec/Security/SecItemPriv.h | 349 + {sec => Security/sec}/Security/SecKey.c | 110 +- Security/sec/Security/SecKey.h | 296 + .../sec}/Security/SecKeyInternal.h | 10 +- Security/sec/Security/SecKeyPriv.h | 341 + Security/sec/Security/SecLogging.c | 53 + Security/sec/Security/SecLogging.h | 18 + Security/sec/Security/SecOTR.h | 91 + Security/sec/Security/SecOTRDHKey.c | 371 + Security/sec/Security/SecOTRDHKey.h | 66 + Security/sec/Security/SecOTRErrors.h | 43 + .../sec}/Security/SecOTRFullIdentity.c | 25 +- .../sec}/Security/SecOTRIdentityPriv.h | 27 +- {sec => Security/sec}/Security/SecOTRMath.c | 67 +- Security/sec/Security/SecOTRMath.h | 81 + Security/sec/Security/SecOTRPacketData.c | 26 + .../sec}/Security/SecOTRPacketData.h | 110 +- .../sec}/Security/SecOTRPackets.c | 43 +- Security/sec/Security/SecOTRPackets.h | 50 + .../sec}/Security/SecOTRPublicIdentity.c | 60 +- Security/sec/Security/SecOTRSession.c | 1030 ++ Security/sec/Security/SecOTRSession.h | 133 + .../sec}/Security/SecOTRSessionAKE.c | 54 +- Security/sec/Security/SecOTRSessionPriv.h | 107 + {sec => Security/sec}/Security/SecOTRUtils.c | 53 +- Security/sec/Security/SecOnOSX.h | 44 + {sec => Security/sec}/Security/SecPBKDF.c | 2 +- {sec => Security/sec}/Security/SecPBKDF.h | 2 +- .../sec}/Security/SecPasswordGenerate.c | 270 +- .../sec}/Security/SecPasswordGenerate.h | 23 +- {sec => Security/sec}/Security/SecPolicy.c | 382 +- Security/sec/Security/SecPolicy.h | 391 + Security/sec/Security/SecPolicyCerts.h | 74 + .../sec}/Security/SecPolicyInternal.h | 8 +- Security/sec/Security/SecPolicyPriv.h | 439 + {sec => Security/sec}/Security/SecRSAKey.c | 14 +- {sec => Security/sec}/Security/SecRSAKey.h | 2 +- .../sec}/Security/SecRSAKeyPriv.h | 2 +- Security/sec/Security/SecRandom.h | 61 + {sec => Security/sec}/Security/SecSCEP.c | 81 +- {sec => Security/sec}/Security/SecSCEP.h | 3 +- .../sec/Security/SecServerEncryptionSupport.c | 355 + .../sec/Security/SecServerEncryptionSupport.h | 26 + Security/sec/Security/SecSharedCredential.c | 298 + Security/sec/Security/SecSharedCredential.h | 107 + {sec => Security/sec}/Security/SecTrust.c | 131 +- Security/sec/Security/SecTrust.h | 681 + Security/sec/Security/SecTrustPriv.h | 229 + .../sec}/Security/SecTrustSettings.c | 32 +- Security/sec/Security/SecTrustSettings.h | 247 + Security/sec/Security/SecTrustSettingsPriv.h | 218 + .../sec}/Security/SecTrustStore.c | 6 +- .../sec}/Security/SecTrustStore.h | 2 +- Security/sec/Security/Security.h | 35 + {sec => Security/sec}/Security/SecuritydXPC.c | 76 +- Security/sec/Security/SecuritydXPC.h | 54 + .../sec}/Security/Tool/SecurityCommands.h | 16 +- .../Security/Tool/add_internet_password.c | 30 +- Security/sec/Security/Tool/codesign.c | 427 + Security/sec/Security/Tool/keychain_add.c | 130 + .../sec}/Security/Tool/keychain_backup.c | 8 +- Security/sec/Security/Tool/keychain_find.c | 556 + Security/sec/Security/Tool/keychain_util.c | 341 + Security/sec/Security/Tool/keychain_util.h | 33 + Security/sec/Security/Tool/log_control.c | 172 + .../sec}/Security/Tool/pkcs12_util.c | 8 +- {sec => Security/sec}/Security/Tool/scep.c | 67 +- .../sec}/Security/Tool/show_certificates.c | 85 +- {sec => Security/sec}/Security/Tool/spc.c | 97 +- Security/sec/Security/certextensions.h | 546 + Security/sec/Security/cssmapple.h | 76 + Security/sec/Security/keychain_find.h | 53 + {sec => Security/sec}/Security/p12import.c | 21 +- {sec => Security/sec}/Security/p12import.h | 2 +- {sec => Security/sec}/Security/p12pbegen.c | 2 +- {sec => Security/sec}/Security/p12pbegen.h | 2 +- Security/sec/Security/pbkdf2.c | 104 + Security/sec/Security/pbkdf2.h | 77 + .../sec/Security/so_01_serverencryption.c | 137 + Security/sec/Security/vmdh.c | 77 + Security/sec/Security/vmdh.h | 77 + .../sec}/SecurityTool/SecurityTool.c | 2 +- .../sec}/SecurityTool/SecurityTool.h | 2 +- Security/sec/SecurityTool/builtin_commands.h | 37 + Security/sec/SecurityTool/digest_calc.c | 102 + .../sec}/SecurityTool/entitlements.plist | 0 Security/sec/SecurityTool/leaks.c | 109 + Security/sec/SecurityTool/leaks.h | 37 + .../sec}/SecurityTool/print_cert.c | 3 +- .../sec}/SecurityTool/print_cert.h | 3 +- {sec => Security/sec}/SecurityTool/security.1 | 0 Security/sec/SecurityTool/tool_errors.h | 76 + .../com.apple.security.swcagent.plist | 38 + Security/sec/SharedWebCredential/swcagent.m | 802 ++ .../sec/SharedWebCredential/swcagent_client.c | 310 + .../sec/SharedWebCredential/swcagent_client.h | 112 + Security/sec/config/base.xcconfig | 49 + {sec => Security/sec}/config/debug.xcconfig | 0 .../sec}/config/lib-arc-only.xcconfig | 0 Security/sec/config/lib.xcconfig | 34 + {sec => Security/sec}/config/release.xcconfig | 0 {sec => Security/sec}/ipc/client.c | 30 +- Security/sec/ipc/com.apple.secd.plist | 40 + Security/sec/ipc/com.apple.securityd.plist | 40 + Security/sec/ipc/securityd_client.h | 252 + Security/sec/ipc/server.c | 933 ++ Security/sec/sec.xcodeproj/project.pbxproj | 3010 ++++ .../sec}/securityd/OTATrustUtilities.c | 369 +- .../sec}/securityd/OTATrustUtilities.h | 18 +- .../securityd/Regressions/SOSAccountTesting.h | 455 + .../Regressions/SOSTransportTestTransports.c | 733 + .../Regressions/SOSTransportTestTransports.h | 41 + .../Regressions/SecdTestKeychainUtilities.c | 59 + .../Regressions/SecdTestKeychainUtilities.h | 33 + .../Regressions/ios6_1_keychain_2_db.h | 10586 ++++++++++++++ .../securityd/Regressions/sd-10-policytree.c | 2 +- .../securityd/Regressions/secd-01-items.c | 33 +- .../secd-02-upgrade-while-locked.c | 36 +- .../Regressions/secd-03-corrupted-items.c | 30 +- .../Regressions/secd-04-corrupted-items.c | 30 +- .../Regressions/secd-05-corrupted-items.c | 30 +- .../Regressions/secd-30-keychain-upgrade.c | 25 +- .../Regressions/secd-31-keychain-bad.c | 25 +- .../Regressions/secd-31-keychain-unreadable.c | 96 + .../securityd/Regressions/secd-50-account.c | 118 + .../Regressions/secd-51-account-inflate.c | 96 +- .../Regressions/secd-52-account-changed.c | 205 + .../Regressions/secd-55-account-circle.c | 309 + .../secd-55-account-incompatibility.c | 239 + .../Regressions/secd-56-account-apply.c | 299 + .../Regressions/secd-57-account-leave.c | 255 + .../Regressions/secd-58-password-change.c | 227 + .../Regressions/secd-59-account-cleanup.c | 187 + .../secd-60-account-cloud-identity.c | 165 + ...d-61-account-leave-not-in-kansas-anymore.c | 209 + .../Regressions/secd-70-engine-corrupt.c | 253 + .../securityd/Regressions/secd-70-engine.c | 510 + .../Regressions/secd-70-otr-remote.c | 184 + .../securityd/Regressions/secd_regressions.h | 48 + .../Regressions/securityd_regressions.h | 7 + Security/sec/securityd/SOSCloudCircleServer.c | 1190 ++ Security/sec/securityd/SOSCloudCircleServer.h | 121 + .../sec}/securityd/SecCAIssuerCache.c | 9 +- .../sec}/securityd/SecCAIssuerCache.h | 9 +- .../sec}/securityd/SecCAIssuerRequest.c | 11 +- Security/sec/securityd/SecCAIssuerRequest.h | 30 + {sec => Security/sec}/securityd/SecDbItem.c | 352 +- Security/sec/securityd/SecDbItem.h | 234 + Security/sec/securityd/SecDbKeychainItem.c | 982 ++ Security/sec/securityd/SecDbKeychainItem.h | 50 + Security/sec/securityd/SecDbQuery.c | 842 ++ Security/sec/securityd/SecDbQuery.h | 163 + Security/sec/securityd/SecItemDataSource.c | 640 + Security/sec/securityd/SecItemDataSource.h | 51 + Security/sec/securityd/SecItemDb.c | 1210 ++ Security/sec/securityd/SecItemDb.h | 131 + Security/sec/securityd/SecItemSchema.c | 299 + Security/sec/securityd/SecItemSchema.h | 59 + Security/sec/securityd/SecItemServer.c | 1885 +++ Security/sec/securityd/SecItemServer.h | 85 + Security/sec/securityd/SecKeybagSupport.c | 277 + Security/sec/securityd/SecKeybagSupport.h | 97 + Security/sec/securityd/SecLogSettingsServer.c | 35 + Security/sec/securityd/SecLogSettingsServer.h | 19 + .../sec}/securityd/SecOCSPCache.c | 13 +- .../sec}/securityd/SecOCSPCache.h | 9 +- .../sec}/securityd/SecOCSPRequest.c | 8 +- .../sec}/securityd/SecOCSPRequest.h | 8 +- .../sec}/securityd/SecOCSPResponse.c | 76 +- .../sec}/securityd/SecOCSPResponse.h | 8 +- Security/sec/securityd/SecOTRRemote.c | 101 + Security/sec/securityd/SecOTRRemote.h | 34 + .../sec}/securityd/SecPolicyServer.c | 152 +- .../sec}/securityd/SecPolicyServer.h | 10 +- .../sec}/securityd/SecTrustServer.c | 14 +- .../sec}/securityd/SecTrustServer.h | 9 +- .../sec}/securityd/SecTrustStoreServer.c | 10 +- .../sec}/securityd/SecTrustStoreServer.h | 8 +- {sec => Security/sec}/securityd/asynchttp.c | 23 +- {sec => Security/sec}/securityd/asynchttp.h | 8 +- Security/sec/securityd/entitlements.plist | 18 + Security/sec/securityd/iCloudTrace.c | 536 + Security/sec/securityd/iCloudTrace.h | 45 + {sec => Security/sec}/securityd/policytree.c | 8 +- {sec => Security/sec}/securityd/policytree.h | 8 +- Security/sec/securityd/spi.c | 109 + Security/sec/securityd/spi.h | 40 + Security/secdtests/main.c | 52 + Security/secdtests/testlist.h | 4 + .../SecurityTests-Entitlements.plist | 0 Security/sectests/main.c | 47 + Security/sectests/test/testenv.c | 264 + Security/sectests/testlist.h | 6 + Security/security2/security2.1 | 28 + Security/security2/security_tool_commands.c | 44 + Security/security2/sub_commands.h | 28 + {tlsnke => Security/tlsnke}/loadkext.sh | 0 .../tlsnke/tlsnke.xcodeproj/project.pbxproj | 611 + .../contents.xcworkspacedata | 0 .../xcshareddata/xcschemes/Device.xcscheme | 5 +- .../xcshareddata/xcschemes/Host.xcscheme | 5 +- .../xcshareddata/xcschemes/tlsnke.xcscheme | 5 +- .../xcschemes/tlsnketest.xcscheme | 5 +- .../tlsnke/tlsnke/en.lproj/InfoPlist.strings | 2 + .../tlsnke}/tlsnke/tlsnke-Info.plist | 0 .../tlsnke}/tlsnke/tlsnke-Prefix.pch | 0 {tlsnke => Security/tlsnke}/tlsnke/tlsnke.c | 30 +- Security/tlsnke/tlsnke/tlsnke.h | 104 + .../tlsnke}/tlsnketest/cert-1.h | 0 .../tlsnke}/tlsnketest/dtls_client.c | 33 +- .../tlsnke}/tlsnketest/identity-1.h | 0 Security/tlsnke/tlsnketest/main.c | 295 + .../tlsnke}/tlsnketest/privkey-1.h | 0 Security/tlsnke/tlsnketest/ssl-utils.c | 123 + Security/tlsnke/tlsnketest/ssl-utils.h | 34 + .../tlsnke}/tlsnketest/st_test.c | 32 +- .../tlsnke}/tlsnketest/tlssocket.c | 40 +- Security/tlsnke/tlsnketest/tlssocket.h | 59 + .../utilities/Regressions/su-05-cfwrappers.c | 114 + .../utilities/Regressions/su-07-debugging.c | 223 + .../Regressions/su-10-cfstring-der.c | 106 + .../utilities}/Regressions/su-11-cfdata-der.c | 30 +- .../Regressions/su-12-cfboolean-der.c | 102 + .../Regressions/su-13-cfnumber-der.c | 30 +- .../Regressions/su-14-cfarray-der.c | 30 +- .../Regressions/su-15-cfdictionary-der.c | 30 +- .../utilities}/Regressions/su-16-cfdate-der.c | 35 +- .../utilities}/Regressions/su-40-secdb.c | 31 +- .../Regressions/su-41-secdb-stress.c | 41 +- .../Regressions/utilities_regressions.h | 2 + Security/utilities/SecLogging.mobileconfig | 53 + .../SecurityTool/not_on_this_platorm.c | 30 + Security/utilities/SecurityTool/readline.c | 279 + Security/utilities/SecurityTool/readline.h | 57 + .../SecurityTool/security_tool_commands.h | 44 + .../security_tool_commands_table.h | 45 + Security/utilities/config/lib.xcconfig | 2 + .../utilities}/src/SecAKSWrappers.c | 8 +- Security/utilities/src/SecAKSWrappers.h | 121 + Security/utilities/src/SecCFError.c | 124 + Security/utilities/src/SecCFError.h | 62 + Security/utilities/src/SecCFRelease.h | 57 + Security/utilities/src/SecCFWrappers.c | 99 + Security/utilities/src/SecCFWrappers.h | 807 ++ .../utilities}/src/SecCertificateTrace.c | 43 +- .../utilities}/src/SecCertificateTrace.h | 8 +- {utilities => Security/utilities}/src/SecDb.c | 90 +- Security/utilities/src/SecDb.h | 157 + Security/utilities/src/SecDispatchRelease.h | 74 + .../utilities}/src/SecFileLocations.c | 8 +- .../utilities}/src/SecFileLocations.h | 8 +- Security/utilities/src/SecIOFormat.h | 103 + Security/utilities/src/SecMeta.h | 203 + Security/utilities/src/SecXPCError.c | 83 + Security/utilities/src/SecXPCError.h | 49 + Security/utilities/src/array_size.h | 30 + .../utilities}/src/cloud_keychain_diagnose.c | 36 +- Security/utilities/src/comparison.c | 35 + Security/utilities/src/comparison.h | 33 + Security/utilities/src/debugging.c | 556 + Security/utilities/src/debugging.h | 148 + Security/utilities/src/debugging_test.h | 32 + Security/utilities/src/der_array.c | 91 + Security/utilities/src/der_boolean.c | 70 + Security/utilities/src/der_data.c | 103 + Security/utilities/src/der_date.c | 400 + Security/utilities/src/der_date.h | 43 + .../utilities}/src/der_dictionary.c | 37 +- Security/utilities/src/der_null.c | 66 + .../utilities}/src/der_number.c | 30 +- .../utilities}/src/der_plist.c | 30 +- Security/utilities/src/der_plist.h | 53 + Security/utilities/src/der_plist_internal.c | 34 + .../utilities}/src/der_plist_internal.h | 33 +- Security/utilities/src/der_string.c | 94 + Security/utilities/src/fileIo.c | 100 + Security/utilities/src/fileIo.h | 26 + Security/utilities/src/iCloudKeychainTrace.c | 459 + Security/utilities/src/iCloudKeychainTrace.h | 54 + Security/utilities/src/iOSforOSX-SecAttr.c | 47 + Security/utilities/src/iOSforOSX-SecRandom.c | 29 + Security/utilities/src/iOSforOSX.c | 83 + Security/utilities/src/iOSforOSX.h | 50 + Security/utilities/src/simulate_crash.c | 53 + Security/utilities/src/sqlutils.h | 53 + {utilities => Security/utilities}/utilities | 0 .../utilities.xcodeproj/project.pbxproj | 572 + ...tegration Certification Authority Cert.crt | Bin 0 -> 1051 bytes ...416543643077536561487847634e4d6f773d3d.crt | Bin 0 -> 1543 bytes .../AppleID-certs/AppleRootCertificate.crt | Bin 0 -> 1215 bytes .../AppleID-certs/Invalid-asset_signing.crt | Bin 0 -> 1009 bytes SecurityTests/AppleID-certs/iPhoneCACert.crt | Bin 0 -> 1015 bytes SecurityTests/CreateCerts.sh | 86 + .../DigiNotarCA2007RootCertificate.crt | Bin 0 -> 1422 bytes .../DigiNotar_Root_CA_G2-RootCertificate.crt | Bin 0 -> 1428 bytes SecurityTests/DigiNotar/Expectations.plist | 8 + ...rtiID_Enterprise_Certificate_Authority.crt | Bin 0 -> 1558 bytes ...r_PKIoverheid_CA_Organisatie_-_G2-Cert.crt | Bin 0 -> 1696 bytes .../DigiNotar/Invalid-asterisk.google.com.crt | Bin 0 -> 1324 bytes ...Invalid-diginotarpkioverheidcaoverheid.crt | Bin 0 -> 1151 bytes ...rpkioverheidcaoverheidenbedrijven-Cert.crt | Bin 0 -> 1164 bytes ...omnyacc-denhelder.nl-diginotar.cyberca.crt | Bin 0 -> 1364 bytes .../Invalid-webmail.portofamsterdam.nl.crt | Bin 0 -> 1437 bytes ...ebmail.terneuzen.nl-diginotar-services.crt | Bin 0 -> 1354 bytes ...stre.com-diginotal.extended.validation.crt | Bin 0 -> 1375 bytes ...ingservices.nl-diginotar-services-1024.crt | Bin 0 -> 951 bytes ...e_van_Defensie_Certificatie_Autoriteit.crt | Bin 0 -> 1262 bytes ...an_Defensie_Certificatie_Autoriteit_G2.crt | Bin 0 -> 1783 bytes .../diginotar-public-ca-2025-Cert.crt | Bin 0 -> 1543 bytes ...rvices-1024-entrust-secure-server-Cert.crt | Bin 0 -> 977 bytes ...diginotar-services-diginotar-root-Cert.crt | Bin 0 -> 1541 bytes ...diginotar.cyberca-gte.global.root-Cert.crt | Bin 0 -> 1374 bytes ...nded.validation-diginotar.root.ca-Cert.crt | Bin 0 -> 1542 bytes ...tar.root.ca-entrust-secure-server-Cert.crt | Bin 0 -> 1356 bytes ...aatdernederlandenorganisatieca-g2-Cert.crt | Bin 0 -> 1594 bytes .../staatdernederlandenoverheidca-Cert.crt | Bin 0 -> 1158 bytes ...Digisign-Server-ID-Enrich-Entrust-Cert.crt | Bin 0 -> 1234 bytes ...igisign-Server-ID-Enrich-GTETrust-Cert.crt | Bin 0 -> 975 bytes .../Invalid-webmail.jaring.my.crt | Bin 0 -> 849 bytes .../Invalid-www.cybersecurity.my.crt | Bin 0 -> 786 bytes .../Invalid-asset_signing.crt | Bin 0 -> 1009 bytes .../OTATasking-certs/task_signing.crt | Bin 0 -> 1000 bytes SecurityTests/PKITS.pdf | Bin 0 -> 1267741 bytes SecurityTests/PostSecurityTests.sh | 17 + SecurityTests/PreSecurityTests.sh | 59 + SecurityTests/SecurityDevTests-Info.plist | 26 + .../SecurityTests-Entitlements.plist | 42 + SecurityTests/SecurityTests-Info.plist | 26 + SecurityTests/StartTLSServers.sh | 73 + SecurityTests/StopTLSServers.sh | 14 + SecurityTests/clxutils/ChangeLog | 40 + SecurityTests/clxutils/Makefile | 92 + SecurityTests/clxutils/Makefile.cdsa | 165 + SecurityTests/clxutils/Makefile.lib | 113 + .../clxutils/NISCC/TLS_SSL/CoveringLetter.pdf | 3314 +++++ SecurityTests/clxutils/NISCC/TLS_SSL/Makefile | 39 + .../clxutils/NISCC/TLS_SSL/README.txt | 214 + .../clxutils/NISCC/TLS_SSL/SSL_TLS.pdf | Bin 0 -> 110436 bytes .../NISCC/TLS_SSL/certDecode/Makefile | 44 + .../NISCC/TLS_SSL/certDecode/certDecode.cpp | 163 + .../clxutils/NISCC/TLS_SSL/dmitchNotes | 121 + .../NISCC/TLS_SSL/nisccCertVerify/Makefile | 44 + .../nisccCertVerify/nisccCertVerify.cpp | 194 + .../NISCC/TLS_SSL/nisccSimpleClient/Makefile | 182 + .../nisccSimpleClient/nisccSimpleClient.cpp | 177 + .../clxutils/NISCC/TLS_SSL/nisccSslTest | 43 + .../NISCC/TLS_SSL/skipThisNisccCert/Makefile | 44 + .../skipThisNisccCert/skipThisNisccCert.cpp | 104 + .../NISCC/TLS_SSL/testcases/client.crt | Bin 0 -> 509 bytes .../NISCC/TLS_SSL/testcases/client_crt.pem | 13 + .../NISCC/TLS_SSL/testcases/client_key.der | Bin 0 -> 609 bytes .../NISCC/TLS_SSL/testcases/client_key.pem | 15 + .../NISCC/TLS_SSL/testcases/readme.txt | 46 + .../NISCC/TLS_SSL/testcases/rootca.crt | Bin 0 -> 525 bytes .../NISCC/TLS_SSL/testcases/rootca_crt.pem | 13 + .../NISCC/TLS_SSL/testcases/rootca_key.pem | 15 + .../NISCC/TLS_SSL/testcases/server.crt | Bin 0 -> 509 bytes .../NISCC/TLS_SSL/testcases/server_crt.pem | 13 + .../NISCC/TLS_SSL/testcases/server_key.pem | 15 + SecurityTests/clxutils/README | 253 + SecurityTests/clxutils/anchorTest/Makefile | 59 + .../clxutils/anchorTest/anchorSourceTest | 75 + .../clxutils/anchorTest/anchorTest.cpp | 1125 ++ .../clxutils/anchorTest/buildCertKeychains | 56 + .../clxutils/anchorTest/intermedSourceTest | 84 + .../clxutils/anchorTest/intermedTest | 128 + SecurityTests/clxutils/caVerify/Makefile | 55 + SecurityTests/clxutils/caVerify/caVerify.cpp | 648 + SecurityTests/clxutils/certChain/Makefile | 53 + SecurityTests/clxutils/certChain/README | 39 + .../clxutils/certChain/amazon_v3.100.cer | Bin 0 -> 945 bytes .../clxutils/certChain/certChain.cpp | 234 + .../clxutils/certChain/keybank_v3.100.cer | Bin 0 -> 1039 bytes .../clxutils/certChain/keybank_v3.101.cer | Bin 0 -> 906 bytes SecurityTests/clxutils/certInCrl/Makefile | 54 + .../clxutils/certInCrl/certInCrl.cpp | 90 + SecurityTests/clxutils/certLabelTest/Makefile | 48 + .../clxutils/certLabelTest/certLabelTest.cpp | 426 + .../clxutils/certSerialEncodeTest/Makefile | 54 + .../certSerialEncodeTest.cpp | 358 + SecurityTests/clxutils/certTime/Makefile | 54 + SecurityTests/clxutils/certTime/anchor_0 | Bin 0 -> 510 bytes SecurityTests/clxutils/certTime/anchor_34 | Bin 0 -> 1111 bytes SecurityTests/clxutils/certTime/anchor_44 | Bin 0 -> 1130 bytes SecurityTests/clxutils/certTime/anchor_76 | Bin 0 -> 1492 bytes SecurityTests/clxutils/certTime/anchor_80 | Bin 0 -> 890 bytes SecurityTests/clxutils/certTime/anchor_9 | Bin 0 -> 1053 bytes SecurityTests/clxutils/certTime/certTime.cpp | 618 + .../clxutils/certTime/extenCooker.cpp | 811 ++ SecurityTests/clxutils/certTime/extenCooker.h | 162 + SecurityTests/clxutils/certTime/runTime | 23 + SecurityTests/clxutils/certcrl/Makefile | 59 + SecurityTests/clxutils/certcrl/README.doc | Bin 0 -> 50688 bytes SecurityTests/clxutils/certcrl/certcrl.cpp | 443 + SecurityTests/clxutils/certcrl/script.cpp | 923 ++ SecurityTests/clxutils/certcrl/script.h | 51 + .../testSubjects/AppleCerts/AppleCerts.scr | 34 + .../AppleCerts/AppleDevelopment.pem | 30 + .../AppleCerts/AppleQuickTime.pem | 94 + .../testSubjects/AppleCerts/AppleROOTCA.pem | 28 + .../testSubjects/AppleCerts/AppleSWUPDATE.pem | 24 + .../AppleCerts/AppleSecUpdate.pem | 95 + .../testSubjects/AppleCerts/AppleSherlock.pem | 94 + .../AppleCerts/AppleSignUpdate.pem | 95 + .../AppleCerts/AppleSoftUpdate.pem | 30 + .../AppleCodeSigning/AppleCodeSigning.scr | 83 + .../AppleCodeSigning/CodeSignTest.keychain | Bin 0 -> 88764 bytes .../testSubjects/AppleCodeSigning/csCA.cer | Bin 0 -> 546 bytes .../AppleCodeSigning/csCaBadEKU.cer | Bin 0 -> 559 bytes .../AppleCodeSigning/csCaBadPLC.cer | Bin 0 -> 567 bytes .../AppleCodeSigning/csCaNoBC.cer | Bin 0 -> 545 bytes .../AppleCodeSigning/csCaNoEKU.cer | Bin 0 -> 541 bytes .../AppleCodeSigning/csCaNoPLC.cer | Bin 0 -> 563 bytes .../AppleCodeSigning/csDevLeaf.cer | Bin 0 -> 556 bytes .../testSubjects/AppleCodeSigning/csLeaf.cer | Bin 0 -> 543 bytes .../AppleCodeSigning/csLeafBadEKU.cer | Bin 0 -> 546 bytes .../AppleCodeSigning/csLeafBadEKUinInt.cer | Bin 0 -> 579 bytes .../AppleCodeSigning/csLeafBadPLCinInt.cer | Bin 0 -> 579 bytes .../AppleCodeSigning/csLeafNoBcInInt.cer | Bin 0 -> 575 bytes .../AppleCodeSigning/csLeafNoEKU.cer | Bin 0 -> 528 bytes .../AppleCodeSigning/csLeafNoEKUinInt.cer | Bin 0 -> 577 bytes .../AppleCodeSigning/csLeafNoPLCinInt.cer | Bin 0 -> 577 bytes .../AppleCodeSigning/csLeafShortPath.cer | Bin 0 -> 540 bytes .../testSubjects/AppleCodeSigning/csRoot.cer | Bin 0 -> 523 bytes .../CodePkgSigning/BadCodeSignLeaf.cer | Bin 0 -> 550 bytes .../CodePkgSigning/CodePkgSigning.scr | 54 + .../CodePkgSigning/CodeSignLeaf.cer | Bin 0 -> 545 bytes .../CodePkgSigning/CodeSignRoot.cer | Bin 0 -> 523 bytes .../testSubjects/CodePkgSigning/NoEKULeaf.cer | Bin 0 -> 522 bytes .../testSubjects/GarthCRL/.gdb_history | 18 + .../GarthCRL/CNTMTT68S21G224G.cer | Bin 0 -> 1602 bytes .../GarthCRL/InfoCamereFirmaQualificata.cer | Bin 0 -> 1351 bytes .../testSubjects/GarthCRL/InfoCamereRoot.cer | Bin 0 -> 1364 bytes .../certcrl/testSubjects/GarthCRL/crl.scr | 19 + .../certcrl/testSubjects/GarthCRL/fetched.crl | Bin 0 -> 259495 bytes .../certcrl/testSubjects/NSS_ECC/ECCCA.cer | Bin 0 -> 386 bytes .../certcrl/testSubjects/NSS_ECC/ECCp192.cer | Bin 0 -> 382 bytes .../certcrl/testSubjects/NSS_ECC/ECCp224.cer | Bin 0 -> 388 bytes .../certcrl/testSubjects/NSS_ECC/ECCp256.cer | Bin 0 -> 398 bytes .../certcrl/testSubjects/NSS_ECC/ECCp384.cer | Bin 0 -> 427 bytes .../certcrl/testSubjects/NSS_ECC/ECCp521.cer | Bin 0 -> 465 bytes .../NSS_ECC/End_P256_Specified_SHA1.cer | Bin 0 -> 574 bytes .../NSS_ECC/End_P256_Specified_SHA256.cer | Bin 0 -> 589 bytes .../NSS_ECC/End_P256_combined_SHA256.cer | Bin 0 -> 557 bytes .../NSS_ECC/End_P256_combined_SHA512.cer | Bin 0 -> 557 bytes .../NSS_ECC/End_P384_Specified_SHA256.cer | Bin 0 -> 668 bytes .../NSS_ECC/End_P384_Specified_SHA384.cer | Bin 0 -> 669 bytes .../NSS_ECC/End_P384_combined_SHA1.cer | Bin 0 -> 628 bytes .../NSS_ECC/End_P384_combined_SHA256.cer | Bin 0 -> 636 bytes .../NSS_ECC/End_P521_Specified_SHA1.cer | Bin 0 -> 749 bytes .../NSS_ECC/End_P521_combined_SHA1.cer | Bin 0 -> 725 bytes .../NSS_ECC/End_P521_combined_SHA512.cer | Bin 0 -> 733 bytes .../certcrl/testSubjects/NSS_ECC/RootP256.cer | Bin 0 -> 539 bytes .../certcrl/testSubjects/NSS_ECC/msEcc.scr | 83 + .../certcrl/testSubjects/NSS_ECC/nssecc.scr | 41 + .../testSubjects/NSS_ECC/opensslEcc.scr | 46 + .../testSubjects/NSS_ECC/secp256r1ca.cer | Bin 0 -> 825 bytes .../NSS_ECC/secp256r1server-secp256r1ca.cer | Bin 0 -> 578 bytes .../testSubjects/NSS_ECC/secp384r1ca.cer | Bin 0 -> 887 bytes .../NSS_ECC/secp384r1server-secp384r1ca.cer | Bin 0 -> 640 bytes .../testSubjects/NSS_ECC/secp521r1ca.cer | Bin 0 -> 962 bytes .../NSS_ECC/secp521r1server-secp521r1ca.cer | Bin 0 -> 714 bytes .../X509tests/Certificate Path.pdf | Bin 0 -> 729713 bytes .../testSubjects/X509tests/makeCertScr | 22 + .../certcrl/testSubjects/X509tests/runCertScr | 11 + .../test1/End Certificate CP.01.01.crt | Bin 0 -> 650 bytes .../X509tests/test1/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test1/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test10/End Certificate CP.03.02.crt | Bin 0 -> 650 bytes .../test10/Intermediate CRL CP.03.02.crl | Bin 0 -> 335 bytes .../Intermediate Certificate CP.03.02.crt | Bin 0 -> 665 bytes .../test10/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test10/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test11/End Certificate CP.03.03.crt | Bin 0 -> 650 bytes .../test11/Intermediate CRL CP.03.03.crl | Bin 0 -> 335 bytes .../Intermediate Certificate CP.03.03.crt | Bin 0 -> 665 bytes .../test11/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test11/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test12/End Certificate CP.03.04.crt | Bin 0 -> 652 bytes .../test12/Intermediate CRL CP.03.04.crl | Bin 0 -> 335 bytes .../Intermediate Certificate CP.03.04.crt | Bin 0 -> 665 bytes .../test12/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test12/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test13/End Certificate CP.04.01.crt | Bin 0 -> 650 bytes .../test13/Intermediate CRL CP.04.01.crl | Bin 0 -> 335 bytes .../Intermediate Certificate CP.04.01.crt | Bin 0 -> 665 bytes .../test13/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test13/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test14/End Certificate CP.04.02.crt | Bin 0 -> 650 bytes .../test14/Intermediate CRL CP.04.02.crl | Bin 0 -> 335 bytes .../Intermediate Certificate CP.04.02.crt | Bin 0 -> 665 bytes .../test14/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test14/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test15/End Certificate CP.04.03.crt | Bin 0 -> 654 bytes .../test15/Intermediate CRL CP.04.03.crl | Bin 0 -> 341 bytes .../Intermediate Certificate CP.04.03.crt | Bin 0 -> 671 bytes .../test15/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test15/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test16/End Certificate CP.04.04.crt | Bin 0 -> 657 bytes .../test16/Intermediate CRL CP.04.04.crl | Bin 0 -> 337 bytes .../Intermediate Certificate CP.04.04.crt | Bin 0 -> 667 bytes .../test16/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test16/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test17/End Certificate CP.04.05.crt | Bin 0 -> 652 bytes .../test17/Intermediate CRL CP.04.05.crl | Bin 0 -> 337 bytes .../Intermediate Certificate CP.04.05.crt | Bin 0 -> 667 bytes .../test17/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test17/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test18/End Certificate CP.04.06.crt | Bin 0 -> 650 bytes .../test18/Intermediate CRL CP.04.06.crl | Bin 0 -> 335 bytes .../Intermediate Certificate CP.04.06.crt | Bin 0 -> 665 bytes .../test18/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test18/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test19/End Certificate CP.05.01.crt | Bin 0 -> 650 bytes .../Intermediate Certificate CP.05.01.crt | Bin 0 -> 665 bytes .../test19/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test19/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test2/End Certificate CP.01.02.crt | Bin 0 -> 650 bytes .../test2/Intermediate CRL CP.01.02.crl | Bin 0 -> 335 bytes .../Intermediate Certificate CP.01.02.crt | Bin 0 -> 665 bytes .../X509tests/test2/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test2/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test20/End Certificate CP.06.01.crt | Bin 0 -> 650 bytes .../test20/Intermediate CRL CP.06.01.crl | Bin 0 -> 335 bytes .../Intermediate Certificate CP.06.01.crt | Bin 0 -> 665 bytes .../test20/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test20/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test21/End Certificate CP.06.02.crt | Bin 0 -> 650 bytes .../test21/Intermediate CRL CP.06.02.crl | Bin 0 -> 371 bytes .../Intermediate Certificate CP.06.02.crt | Bin 0 -> 665 bytes .../test21/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test21/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test22/End Certificate IC.01.01.crt | Bin 0 -> 650 bytes .../test22/Intermediate CRL IC.01.01.crl | Bin 0 -> 335 bytes .../Intermediate Certificate IC.01.01.crt | Bin 0 -> 648 bytes .../test22/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test22/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test23/End Certificate IC.02.01.crt | Bin 0 -> 650 bytes .../test23/Intermediate CRL IC.02.01.crl | Bin 0 -> 335 bytes .../Intermediate Certificate IC.02.01.crt | Bin 0 -> 662 bytes .../test23/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test23/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test24/End Certificate IC.02.02.crt | Bin 0 -> 650 bytes .../test24/Intermediate CRL IC.02.02.crl | Bin 0 -> 335 bytes .../Intermediate Certificate IC.02.02.crt | Bin 0 -> 665 bytes .../test24/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test24/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test25/End Certificate IC.02.03.crt | Bin 0 -> 650 bytes .../test25/Intermediate CRL IC.02.03.crl | Bin 0 -> 335 bytes .../Intermediate Certificate IC.02.03.crt | Bin 0 -> 659 bytes .../test25/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test25/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test26/End Certificate IC.02.04.crt | Bin 0 -> 650 bytes .../test26/Intermediate CRL IC.02.04.crl | Bin 0 -> 335 bytes .../Intermediate Certificate IC.02.04.crt | Bin 0 -> 662 bytes .../test26/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test26/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test27/End Certificate IC.04.01.crt | Bin 0 -> 650 bytes .../test27/Intermediate CRL IC.04.01.crl | Bin 0 -> 335 bytes .../Intermediate Certificate IC.04.01.crt | Bin 0 -> 659 bytes .../test27/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test27/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test28/End Certificate IC.05.01.crt | Bin 0 -> 650 bytes .../test28/Intermediate CRL IC.05.01.crl | Bin 0 -> 335 bytes .../Intermediate Certificate IC.05.01.crt | Bin 0 -> 665 bytes .../test28/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test28/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test29/End Certificate IC.05.02.crt | Bin 0 -> 650 bytes .../test29/Intermediate CRL IC.05.02.crl | Bin 0 -> 335 bytes .../Intermediate Certificate IC.05.02.crt | Bin 0 -> 662 bytes .../test29/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test29/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test3/End Certificate CP.01.03.crt | Bin 0 -> 650 bytes .../test3/Intermediate CRL CP.01.03.crl | Bin 0 -> 335 bytes .../Intermediate Certificate CP.01.03.crt | Bin 0 -> 665 bytes .../X509tests/test3/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test3/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test30/End Certificate IC.05.03.crt | Bin 0 -> 650 bytes .../test30/Intermediate CRL IC.05.03.crl | Bin 0 -> 335 bytes .../Intermediate Certificate IC.05.03.crt | Bin 0 -> 662 bytes .../test30/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test30/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test31/End Certificate IC.06.01.crt | Bin 0 -> 650 bytes .../test31/Intermediate CRL IC.06.01.crl | Bin 0 -> 335 bytes .../Intermediate Certificate IC.06.01.crt | Bin 0 -> 665 bytes .../test31/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test31/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test32/End Certificate IC.06.02.crt | Bin 0 -> 650 bytes .../test32/Intermediate CRL IC.06.02.crl | Bin 0 -> 335 bytes .../Intermediate Certificate IC.06.02.crt | Bin 0 -> 662 bytes .../test32/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test32/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test33/End Certificate IC.06.03.crt | Bin 0 -> 650 bytes .../test33/Intermediate CRL IC.06.03.crl | Bin 0 -> 335 bytes .../Intermediate Certificate IC.06.03.crt | Bin 0 -> 662 bytes .../test33/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test33/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test34/End Certificate PP.01.01.crt | Bin 0 -> 650 bytes .../test34/Intermediate CRL PP.01.01.crl | Bin 0 -> 335 bytes .../Intermediate Certificate PP.01.01.crt | Bin 0 -> 665 bytes .../test34/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test34/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test35/End Certificate PP.01.02.crt | Bin 0 -> 626 bytes .../test35/Intermediate CRL PP.01.02.crl | Bin 0 -> 335 bytes .../Intermediate Certificate PP.01.02.crt | Bin 0 -> 641 bytes .../test35/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test35/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test36/End Certificate PP.01.03.crt | Bin 0 -> 650 bytes .../test36/Intermediate CRL 1 PP.01.03.crl | Bin 0 -> 335 bytes .../test36/Intermediate CRL 2 PP.01.03.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 PP.01.03.crt | Bin 0 -> 665 bytes .../Intermediate Certificate 2 PP.01.03.crt | Bin 0 -> 665 bytes .../test36/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test36/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test37/End Certificate PP.01.04.crt | Bin 0 -> 650 bytes .../test37/Intermediate CRL 1 PP.01.04.crl | Bin 0 -> 335 bytes .../test37/Intermediate CRL 2 PP.01.04.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 PP.01.04.crt | Bin 0 -> 665 bytes .../Intermediate Certificate 2 PP.01.04.crt | Bin 0 -> 665 bytes .../test37/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test37/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test38/End Certificate PP.01.05.crt | Bin 0 -> 650 bytes .../test38/Intermediate CRL 1 PP.01.05.crl | Bin 0 -> 335 bytes .../test38/Intermediate CRL 2 PP.01.05.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 PP.01.05.crt | Bin 0 -> 665 bytes .../Intermediate Certificate 2 PP.01.05.crt | Bin 0 -> 665 bytes .../test38/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test38/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test39/End Certificate PP.01.06.crt | Bin 0 -> 665 bytes .../test39/Intermediate CRL 1 PP.01.06.crl | Bin 0 -> 335 bytes .../test39/Intermediate CRL 2 PP.01.06.crl | Bin 0 -> 335 bytes .../test39/Intermediate CRL 3 PP.01.06.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 PP.01.06.crt | Bin 0 -> 706 bytes .../Intermediate Certificate 2 PP.01.06.crt | Bin 0 -> 691 bytes .../Intermediate Certificate 3 PP.01.06.crt | Bin 0 -> 678 bytes .../test39/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test39/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test4/End Certificate CP.02.01.crt | Bin 0 -> 650 bytes .../test4/Intermediate CRL 1 CP.02.01.crl | Bin 0 -> 335 bytes .../test4/Intermediate CRL 2 CP.02.01.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 CP.02.01.crt | Bin 0 -> 665 bytes .../Intermediate Certificate 2 CP.02.01.crt | Bin 0 -> 665 bytes .../X509tests/test4/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test4/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test40/End Certificate PP.01.07.crt | Bin 0 -> 665 bytes .../test40/Intermediate CRL 1 PP.01.07.crl | Bin 0 -> 335 bytes .../test40/Intermediate CRL 2 PP.01.07.crl | Bin 0 -> 335 bytes .../test40/Intermediate CRL 3 PP.01.07.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 PP.01.07.crt | Bin 0 -> 691 bytes .../Intermediate Certificate 2 PP.01.07.crt | Bin 0 -> 678 bytes .../Intermediate Certificate 3 PP.01.07.crt | Bin 0 -> 665 bytes .../test40/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test40/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test41/End Certificate PP.01.08.crt | Bin 0 -> 665 bytes .../test41/Intermediate CRL 1 PP.01.08.crl | Bin 0 -> 335 bytes .../test41/Intermediate CRL 2 PP.01.08.crl | Bin 0 -> 335 bytes .../test41/Intermediate CRL 3 PP.01.08.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 PP.01.08.crt | Bin 0 -> 678 bytes .../Intermediate Certificate 2 PP.01.08.crt | Bin 0 -> 665 bytes .../Intermediate Certificate 3 PP.01.08.crt | Bin 0 -> 665 bytes .../test41/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test41/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test42/End Certificate PP.01.09.crt | Bin 0 -> 650 bytes .../test42/Intermediate CRL 1 PP.01.09.crl | Bin 0 -> 335 bytes .../test42/Intermediate CRL 2 PP.01.09.crl | Bin 0 -> 335 bytes .../test42/Intermediate CRL 3 PP.01.09.crl | Bin 0 -> 335 bytes .../test42/Intermediate CRL 4 PP.01.09.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 PP.01.09.crt | Bin 0 -> 691 bytes .../Intermediate Certificate 2 PP.01.09.crt | Bin 0 -> 678 bytes .../Intermediate Certificate 3 PP.01.09.crt | Bin 0 -> 665 bytes .../Intermediate Certificate 4 PP.01.09.crt | Bin 0 -> 665 bytes .../test42/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test42/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test43/End Certificate PP.06.01.crt | Bin 0 -> 626 bytes .../test43/Intermediate CRL 1 PP.06.01.crl | Bin 0 -> 335 bytes .../test43/Intermediate CRL 2 PP.06.01.crl | Bin 0 -> 335 bytes .../test43/Intermediate CRL 3 PP.06.01.crl | Bin 0 -> 335 bytes .../test43/Intermediate CRL 4 PP.06.01.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 PP.06.01.crt | Bin 0 -> 679 bytes .../Intermediate Certificate 2 PP.06.01.crt | Bin 0 -> 665 bytes .../Intermediate Certificate 3 PP.06.01.crt | Bin 0 -> 665 bytes .../Intermediate Certificate 4 PP.06.01.crt | Bin 0 -> 665 bytes .../test43/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test43/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test44/End Certificate PP.06.02.crt | Bin 0 -> 626 bytes .../test44/Intermediate CRL 1 PP.06.02.crl | Bin 0 -> 335 bytes .../test44/Intermediate CRL 2 PP.06.02.crl | Bin 0 -> 335 bytes .../test44/Intermediate CRL 3 PP.06.02.crl | Bin 0 -> 335 bytes .../test44/Intermediate CRL 4 PP.06.02.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 PP.06.02.crt | Bin 0 -> 679 bytes .../Intermediate Certificate 2 PP.06.02.crt | Bin 0 -> 665 bytes .../Intermediate Certificate 3 PP.06.02.crt | Bin 0 -> 665 bytes .../Intermediate Certificate 4 PP.06.02.crt | Bin 0 -> 665 bytes .../test44/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test44/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test45/End Certificate PP.06.03.crt | Bin 0 -> 626 bytes .../test45/Intermediate CRL 1 PP.06.03.crl | Bin 0 -> 335 bytes .../test45/Intermediate CRL 2 PP.06.03.crl | Bin 0 -> 335 bytes .../test45/Intermediate CRL 3 PP.06.03.crl | Bin 0 -> 335 bytes .../test45/Intermediate CRL 4 PP.06.03.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 PP.06.03.crt | Bin 0 -> 679 bytes .../Intermediate Certificate 2 PP.06.03.crt | Bin 0 -> 665 bytes .../Intermediate Certificate 3 PP.06.03.crt | Bin 0 -> 665 bytes .../Intermediate Certificate 4 PP.06.03.crt | Bin 0 -> 665 bytes .../test45/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test45/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test46/End Certificate PP.06.04.crt | Bin 0 -> 650 bytes .../test46/Intermediate CRL 1 PP.06.04.crl | Bin 0 -> 335 bytes .../test46/Intermediate CRL 2 PP.06.04.crl | Bin 0 -> 335 bytes .../test46/Intermediate CRL 3 PP.06.04.crl | Bin 0 -> 335 bytes .../test46/Intermediate CRL 4 PP.06.04.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 PP.06.04.crt | Bin 0 -> 679 bytes .../Intermediate Certificate 2 PP.06.04.crt | Bin 0 -> 665 bytes .../Intermediate Certificate 3 PP.06.04.crt | Bin 0 -> 665 bytes .../Intermediate Certificate 4 PP.06.04.crt | Bin 0 -> 665 bytes .../test46/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test46/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test47/End Certificate PP.06.05.crt | Bin 0 -> 626 bytes .../test47/Intermediate CRL 1 PP.06.05.crl | Bin 0 -> 335 bytes .../test47/Intermediate CRL 2 PP.06.05.crl | Bin 0 -> 335 bytes .../test47/Intermediate CRL 3 PP.06.05.crl | Bin 0 -> 335 bytes .../test47/Intermediate CRL 4 PP.06.05.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 PP.06.05.crt | Bin 0 -> 679 bytes .../Intermediate Certificate 2 PP.06.05.crt | Bin 0 -> 679 bytes .../Intermediate Certificate 3 PP.06.05.crt | Bin 0 -> 679 bytes .../Intermediate Certificate 4 PP.06.05.crt | Bin 0 -> 665 bytes .../test47/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test47/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test48/End Certificate PP.08.01.crt | Bin 0 -> 650 bytes .../test48/Intermediate CRL PP.08.01.crl | Bin 0 -> 335 bytes .../Intermediate Certificate PP.08.01.crt | Bin 0 -> 665 bytes .../test48/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test48/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test49/End Certificate PP.08.02.crt | Bin 0 -> 663 bytes .../test49/Intermediate CRL PP.08.02.crl | Bin 0 -> 335 bytes .../Intermediate Certificate PP.08.02.crt | Bin 0 -> 678 bytes .../test49/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test49/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test5/End Certificate CP.02.02.crt | Bin 0 -> 650 bytes .../test5/Intermediate CRL CP.02.02.crl | Bin 0 -> 335 bytes .../Intermediate Certificate CP.02.02.crt | Bin 0 -> 665 bytes .../X509tests/test5/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test5/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test50/End Certificate PP.08.03.crt | Bin 0 -> 645 bytes .../test50/Intermediate CRL PP.08.03.crl | Bin 0 -> 335 bytes .../Intermediate Certificate PP.08.03.crt | Bin 0 -> 660 bytes .../test50/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test50/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test51/End Certificate PP.08.04.crt | Bin 0 -> 651 bytes .../test51/Intermediate CRL PP.08.04.crl | Bin 0 -> 335 bytes .../Intermediate Certificate PP.08.04.crt | Bin 0 -> 666 bytes .../test51/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test51/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test52/End Certificate PP.08.05.crt | Bin 0 -> 651 bytes .../test52/Intermediate CRL PP.08.05.crl | Bin 0 -> 335 bytes .../Intermediate Certificate PP.08.05.crt | Bin 0 -> 666 bytes .../test52/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test52/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test53/End Certificate PP.08.06.crt | Bin 0 -> 677 bytes .../test53/Intermediate CRL PP.08.06.crl | Bin 0 -> 335 bytes .../Intermediate Certificate PP.08.06.crt | Bin 0 -> 692 bytes .../test53/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test53/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test54/End Certificate PL.01.01.crt | Bin 0 -> 651 bytes .../test54/Intermediate CRL 1 PL.01.01.crl | Bin 0 -> 335 bytes .../test54/Intermediate CRL 2 PL.01.01.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 PL.01.01.crt | Bin 0 -> 669 bytes .../Intermediate Certificate 2 PL.01.01.crt | Bin 0 -> 666 bytes .../test54/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test54/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test55/End Certificate PL.01.02.crt | Bin 0 -> 666 bytes .../test55/Intermediate CRL 1 PL.01.02.crl | Bin 0 -> 335 bytes .../test55/Intermediate CRL 2 PL.01.02.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 PL.01.02.crt | Bin 0 -> 669 bytes .../Intermediate Certificate 2 PL.01.02.crt | Bin 0 -> 666 bytes .../test55/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test55/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test56/End Certificate PL.01.03.crt | Bin 0 -> 651 bytes .../test56/Intermediate CRL PL.01.03.crl | Bin 0 -> 335 bytes .../Intermediate Certificate PL.01.03.crt | Bin 0 -> 669 bytes .../test56/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test56/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test57/End Certificate PL.01.04.crt | Bin 0 -> 666 bytes .../test57/Intermediate CRL PL.01.04.crl | Bin 0 -> 335 bytes .../Intermediate Certificate PL.01.04.crt | Bin 0 -> 669 bytes .../test57/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test57/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test58/End Certificate PL.01.05.crt | Bin 0 -> 651 bytes .../test58/Intermediate CRL 1 PL.01.05.crl | Bin 0 -> 335 bytes .../test58/Intermediate CRL 2 PL.01.05.crl | Bin 0 -> 335 bytes .../test58/Intermediate CRL 3 PL.01.05.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 PL.01.05.crt | Bin 0 -> 669 bytes .../Intermediate Certificate 2 PL.01.05.crt | Bin 0 -> 669 bytes .../Intermediate Certificate 3 PL.01.05.crt | Bin 0 -> 669 bytes .../test58/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test58/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test59/End Certificate PL.01.06.crt | Bin 0 -> 666 bytes .../test59/Intermediate CRL 1 PL.01.06.crl | Bin 0 -> 335 bytes .../test59/Intermediate CRL 2 PL.01.06.crl | Bin 0 -> 335 bytes .../test59/Intermediate CRL 3 PL.01.06.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 PL.01.06.crt | Bin 0 -> 669 bytes .../Intermediate Certificate 2 PL.01.06.crt | Bin 0 -> 669 bytes .../Intermediate Certificate 3 PL.01.06.crt | Bin 0 -> 669 bytes .../test59/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test59/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test6/End Certificate CP.02.03.crt | Bin 0 -> 650 bytes .../test6/Intermediate CRL CP.02.03.crl | Bin 0 -> 335 bytes .../Intermediate Certificate CP.02.03.crt | Bin 0 -> 665 bytes .../X509tests/test6/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test6/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test60/End Certificate PL.01.07.crt | Bin 0 -> 651 bytes .../test60/Intermediate CRL 1 PL.01.07.crl | Bin 0 -> 335 bytes .../test60/Intermediate CRL 2 PL.01.07.crl | Bin 0 -> 335 bytes .../test60/Intermediate CRL 3 PL.01.07.crl | Bin 0 -> 335 bytes .../test60/Intermediate CRL 4 PL.01.07.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 PL.01.07.crt | Bin 0 -> 669 bytes .../Intermediate Certificate 2 PL.01.07.crt | Bin 0 -> 669 bytes .../Intermediate Certificate 3 PL.01.07.crt | Bin 0 -> 669 bytes .../Intermediate Certificate 4 PL.01.07.crt | Bin 0 -> 666 bytes .../test60/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test60/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test61/End Certificate PL.01.08.crt | Bin 0 -> 666 bytes .../test61/Intermediate CRL 1 PL.01.08.crl | Bin 0 -> 335 bytes .../test61/Intermediate CRL 2 PL.01.08.crl | Bin 0 -> 335 bytes .../test61/Intermediate CRL 3 PL.01.08.crl | Bin 0 -> 335 bytes .../test61/Intermediate CRL 4 PL.01.08.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 PL.01.08.crt | Bin 0 -> 669 bytes .../Intermediate Certificate 2 PL.01.08.crt | Bin 0 -> 669 bytes .../Intermediate Certificate 3 PL.01.08.crt | Bin 0 -> 669 bytes .../Intermediate Certificate 4 PL.01.08.crt | Bin 0 -> 666 bytes .../test61/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test61/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test62/End Certificate PL.01.09.crt | Bin 0 -> 651 bytes .../test62/Intermediate CRL 1 PL.01.09.crl | Bin 0 -> 335 bytes .../test62/Intermediate CRL 2 PL.01.09.crl | Bin 0 -> 335 bytes .../test62/Intermediate CRL 3 PL.01.09.crl | Bin 0 -> 335 bytes .../test62/Intermediate CRL 4 PL.01.09.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 PL.01.09.crt | Bin 0 -> 669 bytes .../Intermediate Certificate 2 PL.01.09.crt | Bin 0 -> 669 bytes .../Intermediate Certificate 3 PL.01.09.crt | Bin 0 -> 669 bytes .../Intermediate Certificate 4 PL.01.09.crt | Bin 0 -> 666 bytes .../test62/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test62/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test63/End Certificate PL.01.10.crt | Bin 0 -> 666 bytes .../test63/Intermediate CRL 1 PL.01.10.crl | Bin 0 -> 335 bytes .../test63/Intermediate CRL 2 PL.01.10.crl | Bin 0 -> 335 bytes .../test63/Intermediate CRL 3 PL.01.10.crl | Bin 0 -> 335 bytes .../test63/Intermediate CRL 4 PL.01.10.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 PL.01.10.crt | Bin 0 -> 669 bytes .../Intermediate Certificate 2 PL.01.10.crt | Bin 0 -> 669 bytes .../Intermediate Certificate 3 PL.01.10.crt | Bin 0 -> 669 bytes .../Intermediate Certificate 4 PL.01.10.crt | Bin 0 -> 666 bytes .../test63/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test63/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test64/End Certificate RL.02.01.crt | Bin 0 -> 651 bytes .../test64/Intermediate CRL RL.02.01.crl | Bin 0 -> 335 bytes .../Intermediate Certificate RL.02.01.crt | Bin 0 -> 666 bytes .../test64/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test64/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test65/End Certificate RL.03.01.crt | Bin 0 -> 651 bytes .../test65/Intermediate CRL RL.03.01.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 RL.03.01.crt | Bin 0 -> 666 bytes .../Intermediate Certificate 2 RL.03.01.crt | Bin 0 -> 666 bytes .../test65/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test65/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test66/End Certificate RL.03.02.crt | Bin 0 -> 651 bytes .../test66/Intermediate CRL RL.03.02.crl | Bin 0 -> 372 bytes .../Intermediate Certificate RL.03.02.crt | Bin 0 -> 666 bytes .../test66/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test66/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test67/End Certificate RL.03.03.crt | Bin 0 -> 651 bytes .../test67/Intermediate CRL 1 RL.03.03.crl | Bin 0 -> 372 bytes .../test67/Intermediate CRL 2 RL.03.03.crl | Bin 0 -> 335 bytes .../Intermediate Certificate RL.03.03.crt | Bin 0 -> 666 bytes .../test67/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test67/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test68/End Certificate RL.05.01.crt | Bin 0 -> 651 bytes .../test68/Intermediate CRL 1 RL.05.01.crl | Bin 0 -> 393 bytes .../test68/Intermediate CRL 2 RL.05.01.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 RL.05.01.crt | Bin 0 -> 666 bytes .../Intermediate Certificate 2 RL.05.01.crt | Bin 0 -> 666 bytes .../test68/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test68/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test69/End Certificate RL.05.02.crt | Bin 0 -> 651 bytes .../test69/Intermediate CRL RL.05.02.crl | Bin 0 -> 393 bytes .../Intermediate Certificate RL.05.02.crt | Bin 0 -> 666 bytes .../test69/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test69/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test7/End Certificate CP.02.04.crt | Bin 0 -> 650 bytes .../test7/Intermediate CRL CP.02.04.crl | Bin 0 -> 335 bytes .../Intermediate Certificate CP.02.04.crt | Bin 0 -> 665 bytes .../X509tests/test7/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test7/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test70/End Certificate RL.06.01.crt | Bin 0 -> 651 bytes .../test70/Intermediate CRL 1 RL.06.01.crl | Bin 0 -> 393 bytes .../test70/Intermediate CRL 2 RL.06.01.crl | Bin 0 -> 335 bytes .../Intermediate Certificate 1 RL.06.01.crt | Bin 0 -> 666 bytes .../Intermediate Certificate 2 RL.06.01.crt | Bin 0 -> 666 bytes .../test70/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test70/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test71/End Certificate RL.06.02.crt | Bin 0 -> 651 bytes .../test71/Intermediate CRL RL.06.02.crl | Bin 0 -> 393 bytes .../Intermediate Certificate RL.06.02.crt | Bin 0 -> 666 bytes .../test71/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test71/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test72/End Certificate RL.07.01.crt | Bin 0 -> 651 bytes .../test72/Intermediate CRL RL.07.01.crl | Bin 0 -> 335 bytes .../Intermediate Certificate RL.07.01.crt | Bin 0 -> 666 bytes .../test72/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test72/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test73/End Certificate RL.07.02.crt | Bin 0 -> 651 bytes .../test73/Intermediate CRL RL.07.02.crl | Bin 0 -> 335 bytes .../Intermediate Certificate RL.07.02.crt | Bin 0 -> 666 bytes .../test73/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test73/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test74/End Certificate RL.07.03.crt | Bin 0 -> 651 bytes .../test74/Intermediate CRL RL.07.03.crl | Bin 0 -> 337 bytes .../Intermediate Certificate RL.07.03.crt | Bin 0 -> 666 bytes .../test74/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test74/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test75/End Certificate RL.08.01.crt | Bin 0 -> 651 bytes .../test75/Intermediate CRL RL.08.01.crl | Bin 0 -> 350 bytes .../Intermediate Certificate RL.08.01.crt | Bin 0 -> 666 bytes .../test75/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test75/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test76/End Certificate RL.09.01.crt | Bin 0 -> 651 bytes .../test76/Intermediate CRL RL.09.01.crl | Bin 0 -> 352 bytes .../Intermediate Certificate RL.09.01.crt | Bin 0 -> 666 bytes .../test76/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test76/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test8/End Certificate CP.02.05.crt | Bin 0 -> 652 bytes .../test8/Intermediate CRL CP.02.05.crl | Bin 0 -> 335 bytes .../Intermediate Certificate CP.02.05.crt | Bin 0 -> 665 bytes .../X509tests/test8/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test8/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../test9/End Certificate CP.03.01.crt | Bin 0 -> 650 bytes .../test9/Intermediate CRL CP.03.01.crl | Bin 0 -> 335 bytes .../Intermediate Certificate CP.03.01.crt | Bin 0 -> 665 bytes .../X509tests/test9/Trust Anchor CP.01.01.crt | Bin 0 -> 624 bytes .../test9/Trust Anchor CRL CP.01.01.crl | Bin 0 -> 371 bytes .../testSubjects/X509tests/x509tests.scr | 969 ++ .../anchorAndDb/amazon_v3.100.cer | Bin 0 -> 945 bytes .../testSubjects/anchorAndDb/anchorAndDb.scr | 79 + .../testSubjects/anchorAndDb/dbWithLeaf.db | Bin 0 -> 24060 bytes .../testSubjects/anchorAndDb/dbWithRoot.db | Bin 0 -> 23736 bytes .../testSubjects/anchorAndDb/root_1.cer | Bin 0 -> 568 bytes .../testSubjects/bmpSslHost/bmpSslHost.scr | 19 + .../testSubjects/bmpSslHost/loopStone.scr | 63 + .../bmpSslHost/stone.tees_v3.100.cer | Bin 0 -> 894 bytes .../bmpSslHost/stone.tees_v3.101.cer | Bin 0 -> 1051 bytes .../bmpSslHost/stone.tees_v3.102.cer | Bin 0 -> 1011 bytes .../testSubjects/crlFromSsl/amazon_v3.100.cer | Bin 0 -> 1274 bytes .../testSubjects/crlFromSsl/amazon_v3.101.cer | Bin 0 -> 1584 bytes .../testSubjects/crlFromSsl/apple_v3.100.cer | Bin 0 -> 1746 bytes .../testSubjects/crlFromSsl/apple_v3.101.cer | Bin 0 -> 1570 bytes .../crlFromSsl/cduniverse_v3.100.cer | Bin 0 -> 1344 bytes .../crlFromSsl/cduniverse_v3.101.cer | Bin 0 -> 1184 bytes .../testSubjects/crlFromSsl/crlssl.scr | 130 + .../crlFromSsl/entrust_v3.100.cer | Bin 0 -> 1165 bytes .../crlFromSsl/entrust_v3.101.cer | Bin 0 -> 1270 bytes .../crlFromSsl/firstamlink_v3.100.cer | Bin 0 -> 1647 bytes .../crlFromSsl/keybank_v3.100.cer | Bin 0 -> 1278 bytes .../crlFromSsl/keybank_v3.101.cer | Bin 0 -> 1584 bytes .../crlFromSsl/keybank_v3.102.cer | Bin 0 -> 774 bytes .../crlFromSsl/netfile.state.co_v3.100.cer | Bin 0 -> 1462 bytes .../crlFromSsl/netfile.state.co_v3.101.cer | Bin 0 -> 1581 bytes .../crlFromSsl/netfile.state.co_v3.102.cer | Bin 0 -> 1236 bytes .../certcrl/testSubjects/crlFromSsl/one.scr | 18 + .../crlFromSsl/proteron_v3.100.cer | Bin 0 -> 842 bytes .../crlFromSsl/puretec_v3.100.cer | Bin 0 -> 769 bytes .../crlFromSsl/secauth_v3.100.cer | Bin 0 -> 845 bytes .../crlFromSsl/secauth_v3.101.cer | Bin 0 -> 807 bytes .../crlFromSsl/verisign_v3.100.cer | Bin 0 -> 1788 bytes .../crlFromSsl/verisign_v3.101.cer | Bin 0 -> 1570 bytes .../crlFromSsl/verisign_v3.102.cer | Bin 0 -> 1226 bytes .../crlFromSsl/wellsfargo_v3.100.cer | Bin 0 -> 1147 bytes .../crlFromSsl/wellsfargo_v3.101.cer | Bin 0 -> 903 bytes .../testSubjects/crlFromSsl/xdss_v3.100.cer | Bin 0 -> 1222 bytes .../testSubjects/crlFromSsl/xdss_v3.101.cer | Bin 0 -> 903 bytes .../certcrl/testSubjects/crlTime/crl.crl | Bin 0 -> 282 bytes .../testSubjects/crlTime/crlTestLeaf.cer | Bin 0 -> 503 bytes .../testSubjects/crlTime/crlTestRoot.cer | Bin 0 -> 517 bytes .../certcrl/testSubjects/crlTime/crlTime.scr | 128 + .../testSubjects/crossSigned/SOA1-SOA2.pem | 30 + .../testSubjects/crossSigned/SOA2-SOA1.pem | 30 + .../testSubjects/crossSigned/crossSigned.scr | 44 + .../testSubjects/crossSigned/crossSigned1.db | Bin 0 -> 24768 bytes .../crossSigned/crossSignedBoth.db | Bin 0 -> 27292 bytes .../certcrl/testSubjects/emptyCert/CA.cer | Bin 0 -> 523 bytes .../testSubjects/emptyCert/emptyCert.cer | 0 .../testSubjects/emptyCert/emptyCert.scr | 51 + .../certcrl/testSubjects/emptyCert/leaf.cer | Bin 0 -> 523 bytes .../certcrl/testSubjects/emptyCert/root.cer | Bin 0 -> 525 bytes .../certcrl/testSubjects/emptySubject/ca.pem | 10 + .../emptySubject/emptySubject.scr | 21 + .../testSubjects/emptySubject/user.pem | 39 + .../testSubjects/expiredAppleCA/.gdb_history | 12 + .../expiredAppleCA/AppleDevRoot.pem | 34 + .../expiredAppleCA/NewDevCAIntermdiate.pem | 108 + .../OriginalDevCAIntermediate.pem | 34 + .../expiredAppleCA/appleDevCAs.keychain | Bin 0 -> 28012 bytes .../expiredAppleCA/dmitchtread.cer | Bin 0 -> 1483 bytes .../testSubjects/expiredAppleCA/expiredCA.scr | 112 + .../testSubjects/expiredAppleCA/one.scr | 35 + .../expiredCerts/bothCAs.keychain | Bin 0 -> 24188 bytes .../testSubjects/expiredCerts/ecExpiredCA.cer | Bin 0 -> 463 bytes .../expiredCerts/ecExpiredLeaf.cer | Bin 0 -> 463 bytes .../expiredCerts/ecExpiredRoot.cer | Bin 0 -> 465 bytes .../testSubjects/expiredCerts/ecGoodCA.cer | Bin 0 -> 463 bytes .../testSubjects/expiredCerts/ecGoodLeaf.cer | Bin 0 -> 463 bytes .../testSubjects/expiredCerts/ecGoodRoot.cer | Bin 0 -> 465 bytes .../expiredCerts/expiredCA.keychain | Bin 0 -> 23216 bytes .../expiredCerts/expiredCerts.scr | 147 + .../expiredCerts/expiredRoot.keychain | Bin 0 -> 23232 bytes .../testSubjects/expiredCerts/goodCA.keychain | Bin 0 -> 23216 bytes .../expiredCerts/goodRoot.keychain | Bin 0 -> 23232 bytes .../certcrl/testSubjects/expiredCerts/one.scr | 25 + .../expiredRoot/applestore_v3.100.cer | Bin 0 -> 1746 bytes .../expiredRoot/applestore_v3.101.cer | Bin 0 -> 1570 bytes .../testSubjects/expiredRoot/expiredRoot.scr | 79 + .../testSubjects/expiredRoot/iproj_v3.102.cer | Bin 0 -> 565 bytes .../certcrl/testSubjects/gipCps/gipCps.scr | 28 + .../certcrl/testSubjects/gipCps/gipCps0.cer | Bin 0 -> 690 bytes .../testSubjects/hostNameDot/hostNameDot.scr | 65 + .../hostNameDot/hostNameDotCommonName.cer | Bin 0 -> 564 bytes .../hostNameDot/hostNameDotCommonNameDot.cer | Bin 0 -> 562 bytes .../hostNameDot/hostNameDotRoot.cer | Bin 0 -> 503 bytes .../hostNameDot/hostNameDotSubjAltName.cer | Bin 0 -> 571 bytes .../hostNameDot/hostNameDotSubjAltNameDot.cer | Bin 0 -> 569 bytes .../testSubjects/implicitAnchor/CA.cer | Bin 0 -> 523 bytes .../implicitAnchor/implicitAnchor.scr | 35 + .../testSubjects/implicitAnchor/leaf.cer | Bin 0 -> 523 bytes .../testSubjects/implicitAnchor/root.cer | Bin 0 -> 525 bytes .../certcrl/testSubjects/ipSec/VPNTrialCA.cer | Bin 0 -> 1156 bytes .../certcrl/testSubjects/ipSec/ipSec.scr | 17 + .../ipSec/vpn-gateway.vpntrial.com.cer | Bin 0 -> 1452 bytes .../certcrl/testSubjects/localTime/badCert_1 | Bin 0 -> 749 bytes .../certcrl/testSubjects/localTime/badCert_2 | Bin 0 -> 749 bytes .../certcrl/testSubjects/localTime/badCert_3 | Bin 0 -> 805 bytes .../certcrl/testSubjects/localTime/badCert_4 | Bin 0 -> 751 bytes .../testSubjects/localTime/localTime.scr | 37 + .../miscPolicies/miscPolicies.scr | 23 + .../miscPolicies/miscPoliciesRoot.cer | Bin 0 -> 499 bytes .../testSubjects/miscPolicies/noEKU.cer | Bin 0 -> 488 bytes .../miscPolicies/resourceSignLeaf.cer | Bin 0 -> 522 bytes .../miscPolicies/rfc3280CodeSigningLeaf.cer | Bin 0 -> 526 bytes .../netFetch/JITC_Class3Mail_CA.crt | Bin 0 -> 1055 bytes .../netFetch/JITC_Class3_root_CA.cer | Bin 0 -> 637 bytes .../testSubjects/netFetch/c3MailCaCrl.db | Bin 0 -> 45988 bytes .../certcrl/testSubjects/netFetch/ghoo.cer | Bin 0 -> 1134 bytes .../certcrl/testSubjects/netFetch/net.scr | 80 + .../ocspFromSsl/amazon_v3.100.cer | Bin 0 -> 1274 bytes .../ocspFromSsl/amazon_v3.101.cer | Bin 0 -> 1584 bytes .../testSubjects/ocspFromSsl/apple_v3.100.cer | Bin 0 -> 1746 bytes .../testSubjects/ocspFromSsl/apple_v3.101.cer | Bin 0 -> 1570 bytes .../ocspFromSsl/cduniverse_v3.100.cer | Bin 0 -> 1344 bytes .../ocspFromSsl/cduniverse_v3.101.cer | Bin 0 -> 1184 bytes .../ocspFromSsl/certum_v3.100.cer | Bin 0 -> 1562 bytes .../ocspFromSsl/certum_v3.101.cer | Bin 0 -> 1081 bytes .../ocspFromSsl/certum_v3.102.cer | Bin 0 -> 784 bytes .../ocspFromSsl/keybank_v3.100.cer | Bin 0 -> 1278 bytes .../ocspFromSsl/keybank_v3.101.cer | Bin 0 -> 1584 bytes .../ocspFromSsl/keybank_v3.102.cer | Bin 0 -> 774 bytes .../testSubjects/ocspFromSsl/ocspssl.scr | 137 + .../testSubjects/ocspFromSsl/ocspsslNew.scr | 144 + .../certcrl/testSubjects/ocspFromSsl/one.scr | 19 + .../ocspFromSsl/proteron_v3.100.cer | Bin 0 -> 842 bytes .../ocspFromSsl/secauth_v3.100.cer | Bin 0 -> 845 bytes .../ocspFromSsl/secauth_v3.101.cer | Bin 0 -> 807 bytes .../ocspFromSsl/thawte_v3.100.cer | Bin 0 -> 827 bytes .../ocspFromSsl/thawte_v3.101.cer | Bin 0 -> 807 bytes .../ocspFromSsl/verisign_v3.100.cer | Bin 0 -> 1788 bytes .../ocspFromSsl/verisign_v3.101.cer | Bin 0 -> 1570 bytes .../ocspFromSsl/verisign_v3.102.cer | Bin 0 -> 1226 bytes .../ocspFromSsl/wellsfargo_v3.100.cer | Bin 0 -> 1147 bytes .../ocspFromSsl/wellsfargo_v3.101.cer | Bin 0 -> 903 bytes .../testSubjects/ocspFromSsl/xdss_v3.100.cer | Bin 0 -> 1222 bytes .../testSubjects/ocspFromSsl/xdss_v3.101.cer | Bin 0 -> 903 bytes .../ocsp_openvalidation/Root_CA1.crt | Bin 0 -> 1235 bytes .../ocsp_openvalidation/Root_CA2.crt | Bin 0 -> 1285 bytes .../ocsp_openvalidation/Server_CA1.crt | Bin 0 -> 1113 bytes .../ocsp_openvalidation/Server_CA2.crt | Bin 0 -> 1177 bytes .../ocsp_openvalidation/User_CA1.crt | Bin 0 -> 1126 bytes .../ocsp_openvalidation/User_CA2.crt | Bin 0 -> 1160 bytes .../testSubjects/ocsp_openvalidation/ocsp.scr | 123 + .../testSubjects/ocsp_openvalidation/one.scr | 23 + .../ocsp_openvalidation/one_CA2.scr | 19 + .../testSubjects/parasiticKeys/.gdb_history | 7 + .../parasiticKeys/derCerts/eepkint1.der | Bin 0 -> 1468 bytes .../parasiticKeys/derCerts/eepkint1.key.der | Bin 0 -> 140 bytes .../parasiticKeys/derCerts/pkint8k.der | Bin 0 -> 2488 bytes .../parasiticKeys/derCerts/pkint8k.key.der | Bin 0 -> 2061 bytes .../parasiticKeys/derCerts/uee8k.der | Bin 0 -> 2718 bytes .../testSubjects/parasiticKeys/eepkint1.pem | 33 + .../testSubjects/parasiticKeys/eepkint2.pem | 54 + .../testSubjects/parasiticKeys/intca.pem | 36 + .../testSubjects/parasiticKeys/parasite.scr | 68 + .../parasiticKeys/parasiteEnableLargeKeys.scr | 71 + .../parasiticKeys/parasiteErrDetect.scr | 70 + .../testSubjects/parasiticKeys/pkint16k.pem | 97 + .../testSubjects/parasiticKeys/pkint8k.pem | 54 + .../testSubjects/parasiticKeys/pkuser.pem | 15 + .../testSubjects/parasiticKeys/prsa16k.pem | 238 + .../testSubjects/parasiticKeys/prsa8k.pem | 121 + .../testSubjects/parasiticKeys/root.pem | 15 + .../testSubjects/parasiticKeys/shintca.pem | 19 + .../testSubjects/parasiticKeys/shroot.pem | 15 + .../testSubjects/parasiticKeys/ssRootCert.der | Bin 0 -> 1767 bytes .../testSubjects/parasiticKeys/ssSubjCert.der | Bin 0 -> 1745 bytes .../testSubjects/parasiticKeys/tee16k.pem | 102 + .../testSubjects/parasiticKeys/tee8k.pem | 59 + .../testSubjects/parasiticKeys/uee16k.pem | 102 + .../testSubjects/parasiticKeys/uee8k.pem | 59 + .../certcrl/testSubjects/pkinitPolicy/CA.cer | Bin 0 -> 495 bytes .../testSubjects/pkinitPolicy/noBC.cer | Bin 0 -> 480 bytes .../testSubjects/pkinitPolicy/noCA.cer | Bin 0 -> 501 bytes .../pkinitPolicy/pkinitPolicy.scr | 38 + .../testSubjects/qualCertStatment/ICA3.cer | Bin 0 -> 1703 bytes .../qualCertStatment/Netlock1.der | Bin 0 -> 2047 bytes .../qualCertStatment/badStatementId.cer | Bin 0 -> 515 bytes .../qualCertStatment/qualCertStatement.scr | 32 + .../resourceSigning/intermediate.cer | Bin 0 -> 508 bytes .../testSubjects/resourceSigning/leaf.cer | Bin 0 -> 540 bytes .../resourceSigning/leafBadEKU.cer | Bin 0 -> 558 bytes .../resourceSigning/leafBadKU.cer | Bin 0 -> 550 bytes .../resourceSigning/leafNoEKU.cer | Bin 0 -> 536 bytes .../resourceSigning/resourceSigning.scr | 51 + .../testSubjects/resourceSigning/root.cer | Bin 0 -> 466 bytes .../serverGatedCrypto/alandsbanken_v3.100.cer | Bin 0 -> 1276 bytes .../serverGatedCrypto/alandsbanken_v3.101.cer | Bin 0 -> 903 bytes .../serverGatedCrypto/luottokunta_v3.100.cer | Bin 0 -> 1432 bytes .../serverGatedCrypto/luottokunta_v3.101.cer | Bin 0 -> 903 bytes .../testSubjects/serverGatedCrypto/sgc.scr | 26 + .../smime/AliceDSSSignByCarlNoInherit.cer | Bin 0 -> 738 bytes .../testSubjects/smime/AliceRSASignByCarl.cer | Bin 0 -> 518 bytes .../testSubjects/smime/BobDHEncryptByCarl.cer | Bin 0 -> 870 bytes .../testSubjects/smime/BobRSASignByCarl.cer | Bin 0 -> 516 bytes .../testSubjects/smime/CarlDSSCRLEmpty.crl | Bin 0 -> 111 bytes .../testSubjects/smime/CarlDSSCRLForAll.crl | Bin 0 -> 219 bytes .../testSubjects/smime/CarlDSSCRLForCarl.crl | Bin 0 -> 134 bytes .../testSubjects/smime/CarlDSSSelf.cer | Bin 0 -> 671 bytes .../testSubjects/smime/CarlRSACRLEmpty.crl | Bin 0 -> 202 bytes .../testSubjects/smime/CarlRSACRLForAll.crl | Bin 0 -> 311 bytes .../testSubjects/smime/CarlRSACRLForCarl.crl | Bin 0 -> 239 bytes .../testSubjects/smime/CarlRSASelf.cer | Bin 0 -> 495 bytes .../smime/DianeDHEncryptByCarl.cer | Bin 0 -> 873 bytes .../smime/DianeDSSSignByCarlInherit.cer | Bin 0 -> 446 bytes .../testSubjects/smime/DianeRSASignByCarl.cer | Bin 0 -> 526 bytes .../smime/EricaDHEncryptByCarl.cer | Bin 0 -> 749 bytes .../certcrl/testSubjects/smime/certsParsed | 320 + .../certcrl/testSubjects/smime/crlsParsed | 89 + .../certcrl/testSubjects/smime/smime.scr | 436 + .../testSubjects/trustSettings/buildAndTest | 39 + .../testSubjects/trustSettings/crl.crl | Bin 0 -> 282 bytes .../trustSettings/crlTestLeaf.cer | Bin 0 -> 503 bytes .../trustSettings/crlTestRoot.cer | Bin 0 -> 517 bytes .../testSubjects/trustSettings/csCA.cer | Bin 0 -> 546 bytes .../testSubjects/trustSettings/csLeaf.cer | Bin 0 -> 543 bytes .../trustSettings/csLeafShortPath.cer | Bin 0 -> 540 bytes .../testSubjects/trustSettings/csRoot.cer | Bin 0 -> 523 bytes .../testSubjects/trustSettings/debugRoot.cer | Bin 0 -> 487 bytes .../trustSettings/dmitchAppleThawte.cer | Bin 0 -> 721 bytes .../trustSettings/emptyTrustSettings.plist | 10 + .../testSubjects/trustSettings/localhost.cer | Bin 0 -> 486 bytes .../trustSettings/makeTrustSettings | 51 + .../testSubjects/trustSettings/one.scr | 57 + .../testSubjects/trustSettings/thawteCA.cer | Bin 0 -> 835 bytes .../trustSettings/trustSettings.scr | 176 + .../trustSettings/trustSettingsTest.keychain | Bin 0 -> 30020 bytes .../trustSettings/userTrustSettings.plist | 172 + SecurityTests/clxutils/certsFromDb/Makefile | 54 + .../clxutils/certsFromDb/certsFromDb.cpp | 210 + SecurityTests/clxutils/cgConstruct/Makefile | 55 + .../clxutils/cgConstruct/cgConstruct.cpp | 565 + SecurityTests/clxutils/cgVerify/Makefile | 54 + SecurityTests/clxutils/cgVerify/cgVerify.cpp | 724 + .../clxutils/cgVerify/dsaParam512.der | Bin 0 -> 160 bytes .../clxutils/cgVerifyParsed/Makefile | 54 + .../cgVerifyParsed/cgVerifyParsed.cpp | 699 + .../clxutils/cgVerifyParsed/dsaParam512.der | Bin 0 -> 160 bytes .../cgVerifyParsed/tpVerifyParsed.cpp | 178 + .../clxutils/cgVerifyParsed/tpVerifyParsed.h | 33 + .../clxutils/clAppUtils/BlobList.cpp | 92 + SecurityTests/clxutils/clAppUtils/BlobList.h | 30 + .../clxutils/clAppUtils/CertBuilderApp.cpp | 376 + .../clxutils/clAppUtils/CertBuilderApp.h | 65 + .../clxutils/clAppUtils/CertParser.cpp | 248 + .../clxutils/clAppUtils/CertParser.h | 105 + SecurityTests/clxutils/clAppUtils/Makefile | 62 + .../clxutils/clAppUtils/certVerify.cpp | 692 + .../clxutils/clAppUtils/certVerify.h | 148 + SecurityTests/clxutils/clAppUtils/clutils.c | 192 + SecurityTests/clxutils/clAppUtils/clutils.h | 31 + .../clxutils/clAppUtils/crlUtils.cpp | 318 + SecurityTests/clxutils/clAppUtils/crlUtils.h | 28 + .../clxutils/clAppUtils/identPicker.cpp | 331 + .../clxutils/clAppUtils/identPicker.h | 91 + SecurityTests/clxutils/clAppUtils/ioSock.c | 480 + SecurityTests/clxutils/clAppUtils/ioSock.h | 88 + .../clxutils/clAppUtils/keyPicker.cpp | 365 + SecurityTests/clxutils/clAppUtils/keyPicker.h | 62 + .../clxutils/clAppUtils/printCertName.cpp | 186 + .../clxutils/clAppUtils/printCertName.h | 27 + .../clxutils/clAppUtils/ringBufferIo.cpp | 330 + .../clxutils/clAppUtils/ringBufferIo.h | 101 + .../clxutils/clAppUtils/sslAppUtils.cpp | 1653 +++ .../clxutils/clAppUtils/sslAppUtils.h | 159 + .../clxutils/clAppUtils/sslClient.cpp | 212 + .../clAppUtils/sslRingBufferThreads.cpp | 304 + .../clAppUtils/sslRingBufferThreads.h | 67 + .../clxutils/clAppUtils/sslServe.cpp | 380 + .../clxutils/clAppUtils/sslThreading.h | 174 + SecurityTests/clxutils/clAppUtils/timeStr.cpp | 290 + SecurityTests/clxutils/clAppUtils/timeStr.h | 65 + SecurityTests/clxutils/clAppUtils/tpUtils.cpp | 1215 ++ SecurityTests/clxutils/clAppUtils/tpUtils.h | 181 + SecurityTests/clxutils/clTool/Makefile | 54 + SecurityTests/clxutils/clTool/clTool.cpp | 312 + SecurityTests/clxutils/cltpdvt | 294 + SecurityTests/clxutils/cltpdvt_usage | 10 + .../clxutils/clxutils.pbproj/project.pbxproj | 70 + SecurityTests/clxutils/cmsTime/Makefile | 58 + SecurityTests/clxutils/cmsTime/cmsTime.cpp | 156 + SecurityTests/clxutils/cmsTime/noRoot.p7 | Bin 0 -> 2521 bytes SecurityTests/clxutils/cmsTime/withRoot.p7 | Bin 0 -> 6648 bytes SecurityTests/clxutils/cmstool/Makefile | 48 + SecurityTests/clxutils/cmstool/cmstool.cpp | 1220 ++ .../clxutils/cmstool/testSubjects/ptext1.txt | 772 + .../clxutils/cmstool/testSubjects/signed1.cms | Bin 0 -> 23230 bytes .../clxutils/cmstool/testSubjects/vfyCms | 27 + SecurityTests/clxutils/crlTool/Makefile | 54 + SecurityTests/clxutils/crlTool/crlNetwork.cpp | 253 + SecurityTests/clxutils/crlTool/crlNetwork.h | 30 + SecurityTests/clxutils/crlTool/crlTool.cpp | 232 + SecurityTests/clxutils/dotMacArchive/Makefile | 50 + .../clxutils/dotMacArchive/dotMacArchive.cpp | 546 + .../clxutils/dotMacArchive/dotMacTpAttach.cpp | 91 + .../clxutils/dotMacArchive/dotMacTpAttach.h | 48 + .../clxutils/dotMacArchive/identSearch.cpp | 132 + .../clxutils/dotMacArchive/identSearch.h | 53 + SecurityTests/clxutils/dotMacRequest/Makefile | 54 + SecurityTests/clxutils/dotMacRequest/README | 23 + .../clxutils/dotMacRequest/dotMacRequest.cpp | 624 + SecurityTests/clxutils/dotMacTool/MDS | 6 + SecurityTests/clxutils/dotMacTool/Makefile | 59 + SecurityTests/clxutils/dotMacTool/README | 107 + .../clxutils/dotMacTool/dotMacTool.cpp | 728 + .../clxutils/dotMacTool/keyPicker.cpp | 38 + SecurityTests/clxutils/dotMacTool/keyPicker.h | 48 + SecurityTests/clxutils/dumpasn1.cfg | 3634 +++++ SecurityTests/clxutils/extenGrab/Makefile | 54 + .../clxutils/extenGrab/extenGrab.cpp | 124 + SecurityTests/clxutils/extenTest/Makefile | 54 + .../clxutils/extenTest/extenTest.cpp | 1546 ++ SecurityTests/clxutils/extenTestTp/Makefile | 54 + .../clxutils/extenTestTp/extenTestTp.cpp | 1430 ++ .../clxutils/extendAttrTest/Makefile | 53 + .../clxutils/extendAttrTest/amazon_v3.100.cer | Bin 0 -> 945 bytes .../extendAttrTest/extendAttrTest.cpp | 526 + .../clxutils/extendAttrTest/rsakey_priv.der | Bin 0 -> 319 bytes .../clxutils/extendAttrTest/rsakey_pub.der | Bin 0 -> 94 bytes .../clxutils/extendAttrTool/Makefile | 53 + .../extendAttrTool/extendAttrTool.cpp | 459 + .../extendAttrTool/singleItemPicker.cpp | 233 + .../extendAttrTool/singleItemPicker.h | 55 + .../clxutils/extractCertFields/Makefile | 54 + .../extractCertFields/extractCertFields.cpp | 211 + SecurityTests/clxutils/findCert/Makefile | 50 + SecurityTests/clxutils/findCert/asnUtils.cpp | 262 + SecurityTests/clxutils/findCert/asnUtils.h | 77 + SecurityTests/clxutils/findCert/findCert.cpp | 144 + SecurityTests/clxutils/idPref/Makefile | 48 + SecurityTests/clxutils/idPref/idPref.cpp | 118 + SecurityTests/clxutils/idTool/Makefile | 54 + SecurityTests/clxutils/idTool/idTool.cpp | 439 + .../clxutils/importExport/amazon_v3.100.pem | 22 + .../clxutils/importExport/cdnow_v300.pem | 20 + .../clxutils/importExport/dhParams_512.der | Bin 0 -> 84 bytes .../clxutils/importExport/dsaParamOpenssl.pem | 6 + .../clxutils/importExport/dsaParams_512.der | Bin 0 -> 160 bytes .../clxutils/importExport/exportOpensslTool | 103 + .../clxutils/importExport/exportPkcs8Tool | 104 + .../clxutils/importExport/impExpOpensslEcdsa | 78 + .../importExport/impExpOpensslEcdsaTool | 136 + .../clxutils/importExport/importExport | 117 + .../clxutils/importExport/importExportAgg | 192 + .../importExport/importExportECDSA_P12 | 84 + .../importExport/importExportECDSA_P12_Tool | 95 + .../clxutils/importExport/importExportKeyTool | 112 + .../clxutils/importExport/importExportOpenssh | 219 + .../importExport/importExportOpensshTool | 344 + .../importExport/importExportOpensslWrap | 207 + .../clxutils/importExport/importExportPkcs12 | 193 + .../clxutils/importExport/importExportPkcs7 | 135 + .../clxutils/importExport/importExportPkcs8 | 210 + .../importExport/importExportPkcs8Tool | 71 + .../clxutils/importExport/importExportRawKey | 258 + .../clxutils/importExport/localcert.pem | 12 + .../clxutils/importExport/secp256r1ca.p12 | Bin 0 -> 1425 bytes .../clxutils/importExport/secp384r1ca.p12 | Bin 0 -> 1529 bytes .../clxutils/importExport/secp521r1ca.p12 | Bin 0 -> 1667 bytes .../clxutils/importExport/setupCommon | 60 + .../clxutils/importExport/somePlainText | 1 + SecurityTests/clxutils/kcExport/Makefile | 48 + SecurityTests/clxutils/kcExport/kcExport.cpp | 392 + SecurityTests/clxutils/kcImport/Makefile | 48 + SecurityTests/clxutils/kcImport/kcImport.cpp | 600 + SecurityTests/clxutils/kcTime/Makefile | 49 + .../clxutils/kcTime/SecureServer.509.cer | Bin 0 -> 568 bytes .../clxutils/kcTime/amazon_v3.100.cer | Bin 0 -> 599 bytes SecurityTests/clxutils/kcTime/kcTime.cpp | 504 + SecurityTests/clxutils/kcTime/test1.p12 | Bin 0 -> 2846 bytes SecurityTests/clxutils/kcTool/Makefile | 54 + SecurityTests/clxutils/kcTool/kcTool.cpp | 297 + SecurityTests/clxutils/keyFromCert/Makefile | 54 + .../clxutils/keyFromCert/keyFromCert.cpp | 77 + SecurityTests/clxutils/krbtool/Makefile | 50 + SecurityTests/clxutils/krbtool/asnUtils.cpp | 262 + SecurityTests/clxutils/krbtool/asnUtils.h | 77 + .../clxutils/krbtool/identPicker.cpp | 542 + SecurityTests/clxutils/krbtool/identPicker.h | 66 + SecurityTests/clxutils/krbtool/krbtool.cpp | 313 + SecurityTests/clxutils/make.ssl | 10 + .../clxutils/makeCertPolicy/Makefile | 54 + .../makeCertPolicy/makeCertPolicy.cpp | 202 + SecurityTests/clxutils/makeCrl/Makefile | 54 + SecurityTests/clxutils/makeCrl/makeCrl.cpp | 328 + .../clxutils/makeCrl/testFiles/crl.crl | Bin 0 -> 282 bytes .../makeCrl/testFiles/crlKeychain.keychain | Bin 0 -> 29836 bytes .../makeCrl/testFiles/crlTestLeaf.cer | Bin 0 -> 503 bytes .../makeCrl/testFiles/crlTestRoot.cer | Bin 0 -> 517 bytes .../clxutils/makeCrl/testFiles/crlTime.scr | 127 + .../makeCrl/testFiles/crlTimeTiger.scr | 128 + .../clxutils/makeCrl/testFiles/notes | 27 + .../clxutils/makeExpiredCerts/Makefile | 48 + .../makeExpiredCerts/makeExpiredCerts.cpp | 309 + SecurityTests/clxutils/newCmsTool/Makefile | 48 + .../clxutils/newCmsTool/blobs/GTE_SGC.cer | Bin 0 -> 745 bytes .../clxutils/newCmsTool/blobs/certs.p7 | Bin 0 -> 802 bytes .../clxutils/newCmsTool/blobs/certsOnly.p7 | Bin 0 -> 1509 bytes .../newCmsTool/blobs/cmsEcdsaHandsoff | 83 + .../newCmsTool/blobs/cmsEcdsaRoot.cer | Bin 0 -> 433 bytes .../clxutils/newCmsTool/blobs/cmsKeychain | Bin 0 -> 37900 bytes .../clxutils/newCmsTool/blobs/cmsRoot.cer | Bin 0 -> 491 bytes .../clxutils/newCmsTool/blobs/cmstest | 506 + .../clxutils/newCmsTool/blobs/cmstestHandsoff | 77 + .../clxutils/newCmsTool/blobs/cmstestUsage | 11 + .../clxutils/newCmsTool/blobs/dmitchIChat.cer | Bin 0 -> 707 bytes .../blobs/ecdsaCmsKeychain.keychain | Bin 0 -> 33044 bytes .../clxutils/newCmsTool/blobs/env.p7 | Bin 0 -> 649 bytes .../clxutils/newCmsTool/blobs/env_two.p7 | Bin 0 -> 1051 bytes SecurityTests/clxutils/newCmsTool/blobs/ptext | 5 + .../clxutils/newCmsTool/blobs/sign.p7 | Bin 0 -> 2208 bytes .../clxutils/newCmsTool/blobs/sign2.p7 | Bin 0 -> 3817 bytes .../clxutils/newCmsTool/blobs/signEnv.p7 | Bin 0 -> 2658 bytes .../clxutils/newCmsTool/blobs/signEnv_auth.p7 | Bin 0 -> 2658 bytes .../newCmsTool/blobs/signEnv_certs.p7 | Bin 0 -> 4122 bytes .../newCmsTool/blobs/signEnv_twoSign.p7 | Bin 0 -> 4642 bytes .../blobs/signEnv_twoSign_twoRecip.p7 | Bin 0 -> 5044 bytes .../clxutils/newCmsTool/blobs/sign_auth.p7 | Bin 0 -> 2206 bytes .../clxutils/newCmsTool/blobs/sign_certs.p7 | Bin 0 -> 3669 bytes .../clxutils/newCmsTool/blobs/sign_det.p7 | Bin 0 -> 2018 bytes .../clxutils/newCmsTool/blobs/sign_nocerts.p7 | Bin 0 -> 663 bytes .../newCmsTool/blobs/sign_only_certs.p7 | Bin 0 -> 1509 bytes .../clxutils/newCmsTool/blobs/sign_signer.p7 | Bin 0 -> 1381 bytes .../clxutils/newCmsTool/blobs/sign_two.p7 | Bin 0 -> 4192 bytes .../newCmsTool/blobs/sign_withroot.p7 | Bin 0 -> 3033 bytes .../clxutils/newCmsTool/newCmsTool.cpp | 1658 +++ SecurityTests/clxutils/ocspTool/Makefile | 53 + .../clxutils/ocspTool/findOcspUrl.cpp | 61 + SecurityTests/clxutils/ocspTool/findOcspUrl.h | 42 + .../clxutils/ocspTool/ocspNetwork.cpp | 187 + SecurityTests/clxutils/ocspTool/ocspNetwork.h | 49 + .../clxutils/ocspTool/ocspRequest.cpp | 196 + SecurityTests/clxutils/ocspTool/ocspRequest.h | 84 + SecurityTests/clxutils/ocspTool/ocspTool.cpp | 1254 ++ SecurityTests/clxutils/ocspTool/ocspUtils.cpp | 50 + SecurityTests/clxutils/ocspTool/ocspUtils.h | 29 + SecurityTests/clxutils/ocspdTool/Makefile | 53 + .../clxutils/ocspdTool/ocspdTool.cpp | 485 + SecurityTests/clxutils/p12/Makefile | 52 + SecurityTests/clxutils/p12/SecNssCoder.cpp | 191 + SecurityTests/clxutils/p12/SecNssCoder.h | 161 + SecurityTests/clxutils/p12/p12.cpp | 153 + SecurityTests/clxutils/p12/p12.h | 52 + SecurityTests/clxutils/p12/p12Crypto.cpp | 307 + SecurityTests/clxutils/p12/p12Crypto.h | 101 + SecurityTests/clxutils/p12/p12Decode.cpp | 416 + SecurityTests/clxutils/p12/p12Encode.cpp | 67 + SecurityTests/clxutils/p12/p12GetPassKey.cpp | 132 + SecurityTests/clxutils/p12/p12GetPassKey.h | 30 + .../clxutils/p12/p12ImportExport.cpp | 472 + SecurityTests/clxutils/p12/p12Parse.cpp | 919 ++ SecurityTests/clxutils/p12/p12pbe.cpp | 325 + SecurityTests/clxutils/p12/p12pbe.h | 59 + SecurityTests/clxutils/p12/pkcs12Parsed.cpp | 93 + SecurityTests/clxutils/p12/pkcs12Parsed.h | 92 + SecurityTests/clxutils/p12Parse/Makefile | 57 + SecurityTests/clxutils/p12Parse/main.cpp | 50 + SecurityTests/clxutils/p12Parse/p12Crypto.cpp | 322 + SecurityTests/clxutils/p12Parse/p12Crypto.h | 101 + SecurityTests/clxutils/p12Parse/p12Parse.cpp | 922 ++ SecurityTests/clxutils/p12Parse/p12Parse.h | 21 + .../clxutils/p12Parse/pkcs12Parsed.cpp | 93 + .../clxutils/p12Parse/pkcs12Parsed.h | 92 + .../clxutils/p12Parse/pkcs12Utils.cpp | 322 + SecurityTests/clxutils/p12Parse/pkcs12Utils.h | 45 + SecurityTests/clxutils/p12Reencode/Makefile | 54 + SecurityTests/clxutils/p12Reencode/doReencode | 22 + .../clxutils/p12Reencode/p12Reencode.cpp | 395 + SecurityTests/clxutils/p12Reencode/test1.p12 | Bin 0 -> 2846 bytes SecurityTests/clxutils/p12Reencode/test10.p12 | Bin 0 -> 3934 bytes SecurityTests/clxutils/p12Reencode/test11.p12 | Bin 0 -> 3934 bytes SecurityTests/clxutils/p12Reencode/test12.p12 | Bin 0 -> 3942 bytes SecurityTests/clxutils/p12Reencode/test13.p12 | Bin 0 -> 3934 bytes SecurityTests/clxutils/p12Reencode/test14.p12 | Bin 0 -> 3934 bytes SecurityTests/clxutils/p12Reencode/test15.p12 | Bin 0 -> 3950 bytes SecurityTests/clxutils/p12Reencode/test16.p12 | Bin 0 -> 3950 bytes SecurityTests/clxutils/p12Reencode/test17.p12 | Bin 0 -> 3942 bytes SecurityTests/clxutils/p12Reencode/test18.p12 | Bin 0 -> 3934 bytes SecurityTests/clxutils/p12Reencode/test19.p12 | Bin 0 -> 3558 bytes SecurityTests/clxutils/parseCert/Makefile | 54 + .../clxutils/parseCert/parseCert.cpp | 60 + SecurityTests/clxutils/parseCrl/Makefile | 54 + SecurityTests/clxutils/parseCrl/parseCrl.cpp | 64 + SecurityTests/clxutils/pemtool/Makefile | 54 + SecurityTests/clxutils/pemtool/pemtool.c | 108 + .../KeychainAccessSystemRoot.cer | Bin 0 -> 494 bytes .../rootStoreTool/KeychainAccessUserRoot.cer | Bin 0 -> 490 bytes SecurityTests/clxutils/rootStoreTool/Makefile | 59 + .../rootStoreTool/SMIME_SystemRoot.cer | Bin 0 -> 482 bytes .../clxutils/rootStoreTool/SMIME_UserRoot.cer | Bin 0 -> 478 bytes .../clxutils/rootStoreTool/SSL_SystemRoot.cer | Bin 0 -> 478 bytes .../clxutils/rootStoreTool/SSL_UserRoot.cer | Bin 0 -> 474 bytes .../rootStoreTool/UnrestrictedSystemRoot.cer | Bin 0 -> 496 bytes .../rootStoreTool/UnrestrictedUserRoot.cer | Bin 0 -> 492 bytes .../clxutils/rootStoreTool/addTestRoots | 21 + .../clxutils/rootStoreTool/addTestRootsSec | 21 + .../clxutils/rootStoreTool/buildSysAnchors | 45 + .../rootStoreTool/parseTrustedRootList.cpp | 297 + .../rootStoreTool/parseTrustedRootList.h | 46 + .../clxutils/rootStoreTool/rootStoreTool.cpp | 932 ++ .../clxutils/rootStoreTool/rootUtils.cpp | 378 + .../clxutils/rootStoreTool/rootUtils.h | 104 + .../clxutils/rootStoreTool/threeRoots.pem | 38 + SecurityTests/clxutils/secTime/Makefile | 58 + .../clxutils/secTime/SecureServer.509.cer | Bin 0 -> 568 bytes SecurityTests/clxutils/secTime/ThawteCA.cer | Bin 0 -> 835 bytes SecurityTests/clxutils/secTime/ThawteRoot.cer | Bin 0 -> 817 bytes .../clxutils/secTime/amazon_v3.100.cer | Bin 0 -> 945 bytes .../clxutils/secTime/dmitchThawte.cer | Bin 0 -> 721 bytes .../clxutils/secTime/firstamlink.cer | Bin 0 -> 805 bytes SecurityTests/clxutils/secTime/secTime.cpp | 739 + .../clxutils/secToolVerify/AppleQuickTime.pem | 94 + .../clxutils/secToolVerify/AppleSWUPDATE.pem | 107 + .../clxutils/secToolVerify/VPNTrialCA.cer | Bin 0 -> 1156 bytes .../clxutils/secToolVerify/amazon_v3.100.cer | Bin 0 -> 945 bytes .../secToolVerify/applestore_v3.100.cer | Bin 0 -> 1158 bytes .../secToolVerify/applestore_v3.101.cer | Bin 0 -> 903 bytes .../secToolVerify/dmitchThawte2005.cer | Bin 0 -> 721 bytes .../secToolVerify/dmitchThawte2007.cer | Bin 0 -> 734 bytes .../clxutils/secToolVerify/iproj_v3.102.cer | Bin 0 -> 565 bytes .../clxutils/secToolVerify/secToolVerify | 154 + .../clxutils/secToolVerify/serverbasic.crt | Bin 0 -> 791 bytes .../vpn-gateway.vpntrial.com.cer | Bin 0 -> 1452 bytes SecurityTests/clxutils/secTrustTime/Makefile | 58 + .../clxutils/secTrustTime/keybank_v3.100.cer | Bin 0 -> 1121 bytes .../clxutils/secTrustTime/keybank_v3.101.cer | Bin 0 -> 903 bytes .../clxutils/secTrustTime/keybank_v3.102.cer | Bin 0 -> 576 bytes SecurityTests/clxutils/secTrustTime/runTests | 33 + .../clxutils/secTrustTime/secTrustTime.cpp | 378 + SecurityTests/clxutils/signerAndSubj/Makefile | 54 + .../clxutils/signerAndSubj/signerAndSubj.cpp | 717 + .../clxutils/signerAndSubjSsl/Makefile | 54 + .../clxutils/signerAndSubjSsl/doTest | 215 + .../signerAndSubjSsl/signerAndSubjSsl.cpp | 412 + .../clxutils/signerAndSubjTp/Makefile | 54 + .../clxutils/signerAndSubjTp/makeSmimeCert | 38 + .../signerAndSubjTp/signerAndSubjTp.cpp | 959 ++ .../clxutils/simpleUrlAccess/Makefile | 44 + .../simpleUrlAccess/simpleUrlAccess.c | 185 + SecurityTests/clxutils/smimePolicy/Makefile | 58 + .../clxutils/smimePolicy/smimePolicy.cpp | 1246 ++ SecurityTests/clxutils/sslAlert/Makefile | 55 + SecurityTests/clxutils/sslAlert/README | 1 + SecurityTests/clxutils/sslAlert/sslAlert.cpp | 439 + SecurityTests/clxutils/sslAuth/Makefile | 55 + SecurityTests/clxutils/sslAuth/sslAuth.cpp | 384 + SecurityTests/clxutils/sslBench/Makefile | 53 + SecurityTests/clxutils/sslBench/sslBench.cpp | 440 + SecurityTests/clxutils/sslCipher/Makefile | 55 + .../clxutils/sslCipher/sslCipher.cpp | 561 + SecurityTests/clxutils/sslEAP/Makefile | 53 + .../clxutils/sslEAP/ringBufferThreads.cpp | 359 + .../clxutils/sslEAP/ringBufferThreads.h | 80 + SecurityTests/clxutils/sslEAP/sslEAP.cpp | 246 + SecurityTests/clxutils/sslEcdsa/Makefile | 60 + .../sslEcdsa/ecc-secp256r1-client.pfx | Bin 0 -> 1036 bytes .../clxutils/sslEcdsa/ecdsa.keychain | Bin 0 -> 24940 bytes SecurityTests/clxutils/sslEcdsa/sslEcdsa.cpp | 631 + .../clxutils/sslHandshakeTimeRB/Makefile | 53 + .../sslHandshakeTimeRB/sslHandshakeTimeRB.cpp | 274 + .../clxutils/sslHdshakeTime/Makefile | 53 + .../sslHdshakeTime/sslHdshakeTime.cpp | 479 + SecurityTests/clxutils/sslProt/Makefile | 55 + SecurityTests/clxutils/sslProt/dhParams1024.h | 24 + SecurityTests/clxutils/sslProt/dhParams512.h | 14 + SecurityTests/clxutils/sslProt/sslProt.cpp | 1061 ++ SecurityTests/clxutils/sslScripts/AlexTest | 80 + SecurityTests/clxutils/sslScripts/authClient | 72 + SecurityTests/clxutils/sslScripts/authDoncio | 47 + SecurityTests/clxutils/sslScripts/authExtern | 80 + SecurityTests/clxutils/sslScripts/authServe | 62 + .../clxutils/sslScripts/cynicRoot.cer | Bin 0 -> 2391 bytes .../clxutils/sslScripts/dhParams_1024.der | Bin 0 -> 151 bytes .../clxutils/sslScripts/dhParams_512.der | Bin 0 -> 84 bytes .../clxutils/sslScripts/doncioRoot.cer | Bin 0 -> 750 bytes SecurityTests/clxutils/sslScripts/doprompt | 25 + .../clxutils/sslScripts/dsaCertToolInput | 14 + .../clxutils/sslScripts/makeLocalCert | 72 + .../clxutils/sslScripts/openssl/doprompt | 2 + .../sslScripts/openssl/makeOpensslCert | 101 + .../sslScripts/openssl/opensslReqInput | 10 + .../clxutils/sslScripts/openssl/opensslTest | 49 + .../sslScripts/openssl/osdsaparam.der | 6 + .../clxutils/sslScripts/openssl/runServeView | 41 + SecurityTests/clxutils/sslScripts/protClient | 146 + SecurityTests/clxutils/sslScripts/protServe | 89 + .../clxutils/sslScripts/removeLocalCerts | 24 + .../clxutils/sslScripts/runProtClient | 60 + SecurityTests/clxutils/sslScripts/setTrustAll | 10 + .../clxutils/sslScripts/simplePrompt | 2 + .../clxutils/sslScripts/sslExtendUse.scr | 58 + SecurityTests/clxutils/sslScripts/sslKcSetup | 59 + SecurityTests/clxutils/sslScripts/ssldvt | 109 + .../clxutils/sslScripts/ssldvtCertErr | 2 + SecurityTests/clxutils/sslScripts/ssldvtUsage | 1 + SecurityTests/clxutils/sslScripts/test1.p12 | Bin 0 -> 2846 bytes SecurityTests/clxutils/sslScripts/trustAll | 14 + .../clxutils/sslScripts/verisignCA.cer | Bin 0 -> 906 bytes SecurityTests/clxutils/sslServer/Makefile | 53 + .../clxutils/sslServer/sslServer.cpp | 1060 ++ SecurityTests/clxutils/sslSession/Makefile | 57 + .../clxutils/sslSession/sslSession.cpp | 293 + SecurityTests/clxutils/sslSubjName/Makefile | 62 + .../clxutils/sslSubjName/sslSubjName.cpp | 595 + SecurityTests/clxutils/sslThroughput/Makefile | 53 + .../clxutils/sslThroughput/runSslThroughput | 27 + .../clxutils/sslThroughput/sslThroughput.cpp | 283 + SecurityTests/clxutils/sslViewer/Makefile | 53 + .../clxutils/sslViewer/SSLViewer.cpp | 1799 +++ SecurityTests/clxutils/sslViewer/SSL_Sites | 306 + SecurityTests/clxutils/sslViewer/pingSslSites | 37 + SecurityTests/clxutils/sslViewer/verifyPing | 144 + SecurityTests/clxutils/sysIdTool/Makefile | 48 + .../clxutils/sysIdTool/sysIdTool.cpp | 187 + SecurityTests/clxutils/threadTest/Makefile | 66 + .../clxutils/threadTest/amazon_v3.100.cer | Bin 0 -> 1274 bytes .../clxutils/threadTest/amazon_v3.101.cer | Bin 0 -> 1584 bytes SecurityTests/clxutils/threadTest/attach.cpp | 270 + .../clxutils/threadTest/cduniverse_v3.100.cer | Bin 0 -> 1344 bytes .../clxutils/threadTest/cgConstructThr.cpp | 390 + .../clxutils/threadTest/cgVerifyThr.cpp | 453 + .../clxutils/threadTest/copyRoots.cpp | 46 + SecurityTests/clxutils/threadTest/cspRand.cpp | 63 + .../clxutils/threadTest/cssmErrStr.cpp | 61 + .../clxutils/threadTest/dbOpenClose.cpp | 76 + .../clxutils/threadTest/derDecode.cpp | 131 + SecurityTests/clxutils/threadTest/desTest.cpp | 296 + .../clxutils/threadTest/digestClient.cpp | 59 + .../clxutils/threadTest/getCachedFields.cpp | 231 + .../clxutils/threadTest/getFields.cpp | 200 + SecurityTests/clxutils/threadTest/ioSockThr.c | 335 + SecurityTests/clxutils/threadTest/ioSockThr.h | 76 + .../clxutils/threadTest/kcStatus.cpp | 84 + .../clxutils/threadTest/mdsLookupThr.cpp | 173 + .../threadTest/mypage.apple_v3.100.cer | Bin 0 -> 1102 bytes SecurityTests/clxutils/threadTest/rsaSign.cpp | 325 + .../clxutils/threadTest/secTrustEval.cpp | 135 + .../clxutils/threadTest/serverpremium.crt | Bin 0 -> 811 bytes .../clxutils/threadTest/signVerify.cpp | 118 + SecurityTests/clxutils/threadTest/sslPing.cpp | 407 + .../clxutils/threadTest/sslThrash.cpp | 265 + .../clxutils/threadTest/symTestThr.cpp | 150 + SecurityTests/clxutils/threadTest/t_stdlib.c | 53 + .../clxutils/threadTest/testParams.h | 90 + SecurityTests/clxutils/threadTest/testutil.c | 175 + SecurityTests/clxutils/threadTest/testutil.h | 19 + .../clxutils/threadTest/threadTest.cpp | 496 + .../clxutils/threadTest/timeThread.cpp | 99 + .../clxutils/threadTest/trustSettings.cpp | 101 + SecurityTests/clxutils/trustAnchors/Makefile | 53 + .../clxutils/trustAnchors/trustAnchors.c | 529 + SecurityTests/clxutils/trustApps/Makefile | 53 + .../clxutils/trustApps/trustApps.cpp | 153 + SecurityTests/clxutils/unBER/Makefile | 58 + SecurityTests/clxutils/unBER/unBER.cpp | 448 + SecurityTests/clxutils/updateCert | 42 + SecurityTests/clxutils/updateCerts | 35 + SecurityTests/clxutils/urlPageGrab/Makefile | 53 + .../clxutils/urlPageGrab/cfSimpleGet.cpp | 126 + .../clxutils/urlPageGrab/cfSimpleGet.h | 14 + SecurityTests/clxutils/urlPageGrab/grabPages | 38 + SecurityTests/clxutils/urlPageGrab/pltGrab | 91 + .../clxutils/urlPageGrab/speedo_html.tar | Bin 0 -> 5488640 bytes .../clxutils/urlPageGrab/urlPageGrab.cpp | 491 + SecurityTests/clxutils/userTrustTest/Makefile | 58 + .../clxutils/userTrustTest/amazon_v3.100.cer | Bin 0 -> 945 bytes .../clxutils/userTrustTest/userTrustTest.cpp | 244 + SecurityTests/clxutils/vfyCacCert/Makefile | 39 + SecurityTests/clxutils/vfyCacCert/README | 37 + .../clxutils/vfyCacCert/certs/cac_c7_cert.crt | Bin 0 -> 1027 bytes .../vfyCacCert/certs/cac_signing_cert.crt | Bin 0 -> 1134 bytes .../clxutils/vfyCacCert/certs/joe2.ID.cer | Bin 0 -> 962 bytes .../vfyCacCert/certs/joe2.encrypt.cer | Bin 0 -> 1004 bytes .../clxutils/vfyCacCert/certs/joe2.sign.cer | Bin 0 -> 1072 bytes SecurityTests/clxutils/vfyCacCert/vfyAllCerts | 9 + .../clxutils/vfyCacCert/vfyCacCert.cpp | 494 + SecurityTests/clxutils/vfyCert/Makefile | 54 + SecurityTests/clxutils/vfyCert/vfyCert.c | 68 + SecurityTests/clxutils/vfyCertChain/Makefile | 54 + .../clxutils/vfyCertChain/vfyCertChain.cpp | 426 + SecurityTests/cspxutils/ChangeLog | 28 + SecurityTests/cspxutils/EXAMPLES_README | 33 + SecurityTests/cspxutils/Makefile | 96 + SecurityTests/cspxutils/Makefile.cdsa | 152 + SecurityTests/cspxutils/Makefile.lib | 119 + SecurityTests/cspxutils/Makefile.template | 62 + SecurityTests/cspxutils/README | 239 + SecurityTests/cspxutils/acltool/Makefile | 51 + SecurityTests/cspxutils/acltool/aclUtils.cpp | 509 + SecurityTests/cspxutils/acltool/aclUtils.h | 54 + SecurityTests/cspxutils/acltool/acltool.cpp | 327 + SecurityTests/cspxutils/aesVect/Makefile | 57 + SecurityTests/cspxutils/aesVect/aesVect.c | 179 + SecurityTests/cspxutils/aesVect/ecb_vk.hdr | 13 + SecurityTests/cspxutils/aesVect/ecb_vk.txt | 2334 +++ SecurityTests/cspxutils/aesVect/ecb_vt.hdr | 13 + SecurityTests/cspxutils/aesVect/ecb_vt.txt | 1566 ++ SecurityTests/cspxutils/aesVect/enDecrypt.h | 47 + .../cspxutils/aesVect/enDecryptCsp.c | 84 + .../cspxutils/aesVect/enDecryptRef.c | 56 + .../cspxutils/aesVect/enDecryptTest.c | 42 + SecurityTests/cspxutils/aesVect/makeVectors | 31 + SecurityTests/cspxutils/aesVect/rijndael.c | 427 + SecurityTests/cspxutils/aesVect/std_defs.h | 151 + SecurityTests/cspxutils/aesVect/testVectors | 27 + SecurityTests/cspxutils/ascTool/Makefile | 55 + SecurityTests/cspxutils/ascTool/ascTool.cpp | 291 + SecurityTests/cspxutils/asymCompat/Makefile | 56 + .../cspxutils/asymCompat/asymCompat.c | 826 ++ SecurityTests/cspxutils/asymPerform/Makefile | 56 + .../cspxutils/asymPerform/asymPerform.c | 266 + SecurityTests/cspxutils/asymTest/Makefile | 55 + SecurityTests/cspxutils/asymTest/asymTest.c | 870 ++ SecurityTests/cspxutils/attachLeak/Makefile | 54 + .../cspxutils/attachLeak/attachLeak.c | 185 + SecurityTests/cspxutils/badattr/Makefile | 55 + SecurityTests/cspxutils/badattr/badattr.c | 1417 ++ SecurityTests/cspxutils/badmac/Makefile | 54 + SecurityTests/cspxutils/badmac/badmac.c | 400 + SecurityTests/cspxutils/badsig/Makefile | 54 + SecurityTests/cspxutils/badsig/badsig.c | 820 ++ SecurityTests/cspxutils/buildExample | 32 + SecurityTests/cspxutils/ccCtxSize/Makefile | 57 + SecurityTests/cspxutils/ccCtxSize/ccCtxSize.c | 62 + SecurityTests/cspxutils/ccHmacClone/Makefile | 60 + .../cspxutils/ccHmacClone/ccHmacClone.cpp | 422 + SecurityTests/cspxutils/ccHmacCompat/Makefile | 59 + .../cspxutils/ccHmacCompat/ccHmacCompat.c | 421 + SecurityTests/cspxutils/ccOneShot/Makefile | 59 + .../cspxutils/ccOneShot/ccOneShot.cpp | 243 + .../cspxutils/ccOpensslCompat/Makefile | 55 + .../ccOpensslCompat/ccOpensslCompat.cpp | 188 + .../cspxutils/ccOpensslCompat/digestCommon.h | 197 + .../ccOpensslCompat/digestCommonCrypto.cpp | 7 + .../ccOpensslCompat/digestCommonExtern.h | 39 + .../ccOpensslCompat/digestOpenssl.cpp | 14 + SecurityTests/cspxutils/ccPerform/Makefile | 56 + .../cspxutils/ccPerform/ccPerform.cpp | 240 + SecurityTests/cspxutils/ccSymCompat/Makefile | 56 + .../cspxutils/ccSymCompat/ccSymCompat.c | 1016 ++ SecurityTests/cspxutils/ccSymTest/Makefile | 56 + .../cspxutils/ccSymTest/ccSymTest.cpp | 777 + SecurityTests/cspxutils/ccdvt | 29 + SecurityTests/cspxutils/ccmake | 46 + .../cspxutils/clearPubKeyTest/Makefile | 56 + .../clearPubKeyTest/clearPubKeyTest.cpp | 395 + SecurityTests/cspxutils/contextReuse/Makefile | 55 + .../cspxutils/contextReuse/contextReuse.cpp | 739 + SecurityTests/cspxutils/cputimeCal/Makefile | 55 + .../cspxutils/cputimeCal/cputimeCal.cpp | 36 + SecurityTests/cspxutils/cryptTool/Makefile | 55 + SecurityTests/cspxutils/cryptTool/README | 55 + SecurityTests/cspxutils/cryptTool/cryptTool.c | 415 + SecurityTests/cspxutils/cryptTool/runCrypt | 27 + SecurityTests/cspxutils/cspdvt | 185 + SecurityTests/cspxutils/cspdvt_usage | 7 + .../cspxutils.pbproj/project.pbxproj | 71 + SecurityTests/cspxutils/dbTool/Makefile | 55 + SecurityTests/cspxutils/dbTool/dbAttrs.cpp | 444 + SecurityTests/cspxutils/dbTool/dbAttrs.h | 52 + SecurityTests/cspxutils/dbTool/dbCert.cpp | 508 + SecurityTests/cspxutils/dbTool/dbCert.h | 48 + SecurityTests/cspxutils/dbTool/dbTool.cpp | 747 + SecurityTests/cspxutils/dbVerifyKey/Makefile | 55 + .../cspxutils/dbVerifyKey/dbVerifyKey.cpp | 222 + SecurityTests/cspxutils/dhFulltest/Makefile | 55 + .../cspxutils/dhFulltest/dhFulltest.cpp | 711 + .../cspxutils/dhFulltest/dhParams_512.der | Bin 0 -> 84 bytes SecurityTests/cspxutils/dhTest/Makefile | 61 + SecurityTests/cspxutils/dhTest/README | 63 + .../cspxutils/dhTest/dhParams_512.der | Bin 0 -> 84 bytes SecurityTests/cspxutils/dhTest/dhTest.cpp | 468 + SecurityTests/cspxutils/dsaPartial/Makefile | 55 + .../cspxutils/dsaPartial/dsaParam512_1.der | Bin 0 -> 160 bytes .../cspxutils/dsaPartial/dsaParam512_2.der | Bin 0 -> 160 bytes .../cspxutils/dsaPartial/dsaPartial.cpp | 724 + SecurityTests/cspxutils/ecdhTest/Makefile | 59 + SecurityTests/cspxutils/ecdhTest/ecdhTest.cpp | 451 + SecurityTests/cspxutils/feeCurve | 62 + SecurityTests/cspxutils/feedvt | 22 + .../cspxutils/genErrorStrings/Makefile | 35 + .../cspxutils/genErrorStrings/fileIo.c | 89 + .../cspxutils/genErrorStrings/fileIo.h | 20 + .../genErrorStrings/genErrorStrings.cpp | 211 + .../cspxutils/genErrorStrings/genStrings | 33 + SecurityTests/cspxutils/genKeyPair/Makefile | 55 + .../cspxutils/genKeyPair/genKeyPair.cpp | 238 + SecurityTests/cspxutils/hashClone/Makefile | 55 + SecurityTests/cspxutils/hashClone/hashClone.c | 354 + SecurityTests/cspxutils/hashCompat/Makefile | 56 + .../cspxutils/hashCompat/hashCompat.c | 321 + SecurityTests/cspxutils/hashTest/Makefile | 54 + SecurityTests/cspxutils/hashTest/hashTest.c | 397 + SecurityTests/cspxutils/hashTime/MD5.c | 366 + SecurityTests/cspxutils/hashTime/MD5.h | 63 + SecurityTests/cspxutils/hashTime/Makefile | 56 + SecurityTests/cspxutils/hashTime/SHA1.c | 176 + SecurityTests/cspxutils/hashTime/SHA1.h | 76 + SecurityTests/cspxutils/hashTime/SHA1_priv.c | 311 + SecurityTests/cspxutils/hashTime/SHA1_priv.h | 54 + SecurityTests/cspxutils/hashTime/hashTime.cpp | 723 + .../cspxutils/hashTimeLibCrypt/Makefile | 55 + .../hashTimeLibCrypt/hashTimeLibCrypt.cpp | 272 + .../cspxutils/hashTimeLibCrypt/pbkdDigest.cpp | 72 + .../cspxutils/hashTimeLibCrypt/pbkdDigest.h | 78 + SecurityTests/cspxutils/hashTimeSA/MD5.c | 367 + SecurityTests/cspxutils/hashTimeSA/MD5.h | 63 + SecurityTests/cspxutils/hashTimeSA/Makefile | 42 + SecurityTests/cspxutils/hashTimeSA/SHA1.c | 176 + SecurityTests/cspxutils/hashTimeSA/SHA1.h | 76 + .../cspxutils/hashTimeSA/SHA1_priv.c | 313 + .../cspxutils/hashTimeSA/SHA1_priv.h | 54 + .../cspxutils/hashTimeSA/hashTimeSA.cpp | 420 + SecurityTests/cspxutils/keyDate/Makefile | 57 + SecurityTests/cspxutils/keyDate/keyDate.cpp | 1415 ++ SecurityTests/cspxutils/keyHash/Makefile | 54 + SecurityTests/cspxutils/keyHash/keyHash.c | 249 + SecurityTests/cspxutils/keyHashAsym/Makefile | 61 + .../cspxutils/keyHashAsym/dhParams_512.der | Bin 0 -> 84 bytes .../cspxutils/keyHashAsym/dsaParams_512.der | Bin 0 -> 160 bytes .../cspxutils/keyHashAsym/keyHashAsym.c | 547 + SecurityTests/cspxutils/keySizePref/Makefile | 37 + .../cspxutils/keySizePref/keySizePref.cpp | 140 + SecurityTests/cspxutils/keyStore/Makefile | 55 + SecurityTests/cspxutils/keyStore/keyStore.c | 816 ++ SecurityTests/cspxutils/keyStoreLeak/Makefile | 55 + .../cspxutils/keyStoreLeak/keyStoreLeak.c | 477 + SecurityTests/cspxutils/macCompat/Makefile | 55 + SecurityTests/cspxutils/macCompat/macCompat.c | 651 + SecurityTests/cspxutils/macTest/Makefile | 54 + SecurityTests/cspxutils/macTest/macTest.c | 175 + SecurityTests/cspxutils/mdsLookup/Makefile | 54 + .../cspxutils/mdsLookup/mdsLookup.cpp | 528 + SecurityTests/cspxutils/mdsdump/MDSSchema.cpp | 680 + SecurityTests/cspxutils/mdsdump/MDSSchema.h | 101 + SecurityTests/cspxutils/mdsdump/Makefile | 54 + SecurityTests/cspxutils/mdsdump/mdsdump.cpp | 558 + SecurityTests/cspxutils/miniWrap/Makefile | 54 + SecurityTests/cspxutils/miniWrap/miniWrap.c | 809 ++ SecurityTests/cspxutils/pbeTest/Makefile | 54 + SecurityTests/cspxutils/pbeTest/pbeTest.c | 1270 ++ SecurityTests/cspxutils/perform/Makefile | 55 + SecurityTests/cspxutils/perform/aesPerform | 22 + SecurityTests/cspxutils/perform/doPerform | 31 + SecurityTests/cspxutils/perform/perform.cpp | 339 + SecurityTests/cspxutils/performRaw/Makefile | 55 + .../cspxutils/performRaw/aesPerformRaw | 22 + .../cspxutils/performRaw/doPerformRaw | 32 + .../cspxutils/performRaw/performRaw.cpp | 329 + SecurityTests/cspxutils/performSuite | 72 + SecurityTests/cspxutils/pubKeyTool/Makefile | 57 + .../cspxutils/pubKeyTool/derive_pub.der | Bin 0 -> 140 bytes .../cspxutils/pubKeyTool/pubKeyTool.cpp | 672 + .../cspxutils/pubKeyTool/rsa_priv.der | Bin 0 -> 635 bytes .../cspxutils/pubKeyTool/rsa_pub.der | Bin 0 -> 140 bytes SecurityTests/cspxutils/randTest/Makefile | 54 + SecurityTests/cspxutils/randTest/randTest.c | 219 + SecurityTests/cspxutils/rawRsaSig/Makefile | 55 + SecurityTests/cspxutils/rawRsaSig/rawRsaSig.c | 323 + SecurityTests/cspxutils/rawSig/Makefile | 55 + SecurityTests/cspxutils/rawSig/rawSig.c | 477 + SecurityTests/cspxutils/rsatool/Makefile | 55 + SecurityTests/cspxutils/rsatool/README | 127 + SecurityTests/cspxutils/rsatool/rsatool.c | 1182 ++ SecurityTests/cspxutils/sha2Time/Makefile | 55 + SecurityTests/cspxutils/sha2Time/sha2Time.cpp | 126 + SecurityTests/cspxutils/sha2Vectors/Makefile | 49 + .../cspxutils/sha2Vectors/sha2Vectors.cpp | 361 + .../cspxutils/sha2VectorsCdsa/Makefile | 55 + .../sha2VectorsCdsa/sha2VectorsCdsa.cpp | 431 + SecurityTests/cspxutils/sigPerform/Makefile | 56 + .../cspxutils/sigPerform/sigPerform.c | 261 + SecurityTests/cspxutils/sigtest/Makefile | 55 + SecurityTests/cspxutils/sigtest/sigtest.c | 486 + SecurityTests/cspxutils/sshKey/Makefile | 56 + SecurityTests/cspxutils/sshKey/sshKey.cpp | 1461 ++ SecurityTests/cspxutils/ssl2Padding/Makefile | 55 + .../cspxutils/ssl2Padding/ssl2Padding.cpp | 394 + SecurityTests/cspxutils/symCompat/Makefile | 55 + SecurityTests/cspxutils/symCompat/symCompat.c | 1010 ++ SecurityTests/cspxutils/symDelta/Makefile | 54 + SecurityTests/cspxutils/symDelta/symDelta.c | 853 ++ SecurityTests/cspxutils/symReference/Makefile | 55 + .../symReference/blobs/G4/ctext_3DES | Bin 0 -> 264 bytes .../cspxutils/symReference/blobs/G4/ctext_AES | Bin 0 -> 272 bytes .../symReference/blobs/G4/ctext_AES192 | Bin 0 -> 264 bytes .../symReference/blobs/G4/ctext_AES256 | Bin 0 -> 288 bytes .../cspxutils/symReference/blobs/G4/ctext_ASC | Bin 0 -> 282 bytes .../symReference/blobs/G4/ctext_Blowfish | Bin 0 -> 264 bytes .../symReference/blobs/G4/ctext_CAST | 3 + .../cspxutils/symReference/blobs/G4/ctext_DES | Bin 0 -> 264 bytes .../cspxutils/symReference/blobs/G4/ctext_RC2 | Bin 0 -> 264 bytes .../cspxutils/symReference/blobs/G4/ctext_RC4 | 3 + .../cspxutils/symReference/blobs/G4/ctext_RC5 | Bin 0 -> 264 bytes .../cspxutils/symReference/blobs/G4/iv_3DES | 1 + .../cspxutils/symReference/blobs/G4/iv_AES | 1 + .../cspxutils/symReference/blobs/G4/iv_AES192 | 1 + .../cspxutils/symReference/blobs/G4/iv_AES256 | 1 + .../symReference/blobs/G4/iv_Blowfish | 1 + .../cspxutils/symReference/blobs/G4/iv_CAST | 1 + .../cspxutils/symReference/blobs/G4/iv_DES | 1 + .../cspxutils/symReference/blobs/G4/iv_RC2 | 1 + .../cspxutils/symReference/blobs/G4/iv_RC5 | 1 + .../cspxutils/symReference/blobs/G4/key_3DES | Bin 0 -> 24 bytes .../cspxutils/symReference/blobs/G4/key_AES | 1 + .../symReference/blobs/G4/key_AES192 | 1 + .../symReference/blobs/G4/key_AES256 | 1 + .../cspxutils/symReference/blobs/G4/key_ASC | 1 + .../symReference/blobs/G4/key_Blowfish | 1 + .../cspxutils/symReference/blobs/G4/key_CAST | 1 + .../cspxutils/symReference/blobs/G4/key_DES | 1 + .../cspxutils/symReference/blobs/G4/key_RC2 | 1 + .../cspxutils/symReference/blobs/G4/key_RC4 | 1 + .../cspxutils/symReference/blobs/G4/key_RC5 | 1 + .../symReference/blobs/G4/ptext_3DES | 2 + .../cspxutils/symReference/blobs/G4/ptext_AES | Bin 0 -> 256 bytes .../symReference/blobs/G4/ptext_AES192 | Bin 0 -> 256 bytes .../symReference/blobs/G4/ptext_AES256 | Bin 0 -> 256 bytes .../cspxutils/symReference/blobs/G4/ptext_ASC | 3 + .../symReference/blobs/G4/ptext_Blowfish | 1 + .../symReference/blobs/G4/ptext_CAST | Bin 0 -> 256 bytes .../cspxutils/symReference/blobs/G4/ptext_DES | Bin 0 -> 256 bytes .../cspxutils/symReference/blobs/G4/ptext_RC2 | Bin 0 -> 256 bytes .../cspxutils/symReference/blobs/G4/ptext_RC4 | Bin 0 -> 256 bytes .../cspxutils/symReference/blobs/G4/ptext_RC5 | Bin 0 -> 256 bytes .../cspxutils/symReference/symReference.cpp | 464 + SecurityTests/cspxutils/symTest/Makefile | 55 + SecurityTests/cspxutils/symTest/symTest.c | 771 + SecurityTests/cspxutils/testall | 67 + SecurityTests/cspxutils/utilLib/Makefile | 59 + SecurityTests/cspxutils/utilLib/boxes-ref.h | 85 + SecurityTests/cspxutils/utilLib/bsafeUtils.c | 1009 ++ SecurityTests/cspxutils/utilLib/bsafeUtils.h | 109 + SecurityTests/cspxutils/utilLib/common.c | 624 + SecurityTests/cspxutils/utilLib/common.h | 155 + SecurityTests/cspxutils/utilLib/commonCpp.cpp | 160 + SecurityTests/cspxutils/utilLib/cputime.c | 81 + SecurityTests/cspxutils/utilLib/cputime.h | 89 + .../cspxutils/utilLib/cspdlTesting.h | 100 + SecurityTests/cspxutils/utilLib/cspwrap.c | 3279 +++++ SecurityTests/cspxutils/utilLib/cspwrap.h | 454 + .../cspxutils/utilLib/cssmErrorStrings.h | 532 + SecurityTests/cspxutils/utilLib/fileIo.c | 128 + SecurityTests/cspxutils/utilLib/fileIo.h | 20 + .../cspxutils/utilLib/nssAppUtils.cpp | 90 + SecurityTests/cspxutils/utilLib/nssAppUtils.h | 41 + .../cspxutils/utilLib/rijndael-alg-ref.c | 373 + .../cspxutils/utilLib/rijndael-alg-ref.h | 53 + SecurityTests/cspxutils/utilLib/rijndaelApi.c | 357 + SecurityTests/cspxutils/utilLib/rijndaelApi.h | 108 + .../cspxutils/utilLib/ssleayUtils.cpp | 266 + SecurityTests/cspxutils/utilLib/ssleayUtils.h | 54 + SecurityTests/cspxutils/utilLib/t_stdlib.c | 59 + SecurityTests/cspxutils/wrap/Makefile | 55 + SecurityTests/cspxutils/wrap/wrap.c | 249 + SecurityTests/cspxutils/wrapTest/Makefile | 54 + SecurityTests/cspxutils/wrapTest/wrapTest.c | 1077 ++ .../AppleRootCertificate.crt | Bin 0 -> 1215 bytes .../Invalid-task_signing.crt | Bin 0 -> 1000 bytes .../mobileasset-certs/asset_signing.crt | Bin 0 -> 1009 bytes .../mobileasset-certs/iPhoneCACert.crt | Bin 0 -> 1015 bytes .../AllCertificatesNoPoliciesTest2EE.crt | Bin 0 -> 898 bytes .../AllCertificatesSamePoliciesTest10EE.crt | Bin 0 -> 941 bytes .../AllCertificatesSamePoliciesTest13EE.crt | Bin 0 -> 958 bytes .../AllCertificatesanyPolicyTest11EE.crt | Bin 0 -> 914 bytes .../nist-certs/AnyPolicyTest14EE.crt | Bin 0 -> 903 bytes .../nist-certs/BadCRLIssuerNameCACert.crt | Bin 0 -> 911 bytes .../nist-certs/BadCRLSignatureCACert.crt | Bin 0 -> 909 bytes SecurityTests/nist-certs/BadSignedCACert.crt | Bin 0 -> 902 bytes .../nist-certs/BadnotAfterDateCACert.crt | Bin 0 -> 909 bytes .../nist-certs/BadnotBeforeDateCACert.crt | Bin 0 -> 910 bytes .../BasicSelfIssuedCRLSigningKeyCACert.crt | Bin 0 -> 925 bytes .../BasicSelfIssuedNewKeyCACert.crt | Bin 0 -> 917 bytes .../BasicSelfIssuedNewKeyOldWithNewCACert.crt | Bin 0 -> 933 bytes .../BasicSelfIssuedOldKeyCACert.crt | Bin 0 -> 917 bytes .../BasicSelfIssuedOldKeyNewWithOldCACert.crt | Bin 0 -> 1067 bytes .../CPSPointerQualifierTest20EE.crt | Bin 0 -> 1011 bytes SecurityTests/nist-certs/DSACACert.crt | Bin 0 -> 1045 bytes .../DSAParametersInheritedCACert.crt | Bin 0 -> 546 bytes .../nist-certs/DifferentPoliciesTest12EE.crt | Bin 0 -> 914 bytes .../nist-certs/DifferentPoliciesTest3EE.crt | Bin 0 -> 916 bytes .../nist-certs/DifferentPoliciesTest4EE.crt | Bin 0 -> 909 bytes .../nist-certs/DifferentPoliciesTest5EE.crt | Bin 0 -> 917 bytes .../nist-certs/DifferentPoliciesTest7EE.crt | Bin 0 -> 943 bytes .../nist-certs/DifferentPoliciesTest8EE.crt | Bin 0 -> 941 bytes .../nist-certs/DifferentPoliciesTest9EE.crt | Bin 0 -> 931 bytes SecurityTests/nist-certs/Expectations.plist | 141 + .../GeneralizedTimeCRLnextUpdateCACert.crt | Bin 0 -> 920 bytes SecurityTests/nist-certs/GoodCACert.crt | Bin 0 -> 896 bytes SecurityTests/nist-certs/GoodsubCACert.crt | Bin 0 -> 910 bytes .../GoodsubCAPanyPolicyMapping1to2CACert.crt | Bin 0 -> 968 bytes ...nvalidBasicSelfIssuedNewWithOldTest5EE.crt | Bin 0 -> 947 bytes ...nvalidBasicSelfIssuedOldWithNewTest2EE.crt | Bin 0 -> 947 bytes .../nist-certs/InvalidCASignatureTest2EE.crt | Bin 0 -> 899 bytes .../InvalidCAnotAfterDateTest5EE.crt | Bin 0 -> 925 bytes .../InvalidCAnotBeforeDateTest1EE.crt | Bin 0 -> 927 bytes .../InvalidDNSnameConstraintsTest31EE.crt | Bin 0 -> 981 bytes .../InvalidDNSnameConstraintsTest33EE.crt | Bin 0 -> 970 bytes .../InvalidDNSnameConstraintsTest38EE.crt | Bin 0 -> 969 bytes ...alidDNandRFC822nameConstraintsTest28EE.crt | Bin 0 -> 1049 bytes ...alidDNandRFC822nameConstraintsTest29EE.crt | Bin 0 -> 1051 bytes .../InvalidDNnameConstraintsTest10EE.crt | Bin 0 -> 986 bytes .../InvalidDNnameConstraintsTest12EE.crt | Bin 0 -> 991 bytes .../InvalidDNnameConstraintsTest13EE.crt | Bin 0 -> 991 bytes .../InvalidDNnameConstraintsTest15EE.crt | Bin 0 -> 962 bytes .../InvalidDNnameConstraintsTest16EE.crt | Bin 0 -> 962 bytes .../InvalidDNnameConstraintsTest17EE.crt | Bin 0 -> 962 bytes .../InvalidDNnameConstraintsTest20EE.crt | Bin 0 -> 904 bytes .../InvalidDNnameConstraintsTest2EE.crt | Bin 0 -> 957 bytes .../InvalidDNnameConstraintsTest3EE.crt | Bin 0 -> 1113 bytes .../InvalidDNnameConstraintsTest7EE.crt | Bin 0 -> 957 bytes .../InvalidDNnameConstraintsTest8EE.crt | Bin 0 -> 957 bytes .../InvalidDNnameConstraintsTest9EE.crt | Bin 0 -> 957 bytes .../nist-certs/InvalidDSASignatureTest6EE.crt | Bin 0 -> 851 bytes .../nist-certs/InvalidEESignatureTest3EE.crt | Bin 0 -> 893 bytes .../InvalidEEnotAfterDateTest6EE.crt | Bin 0 -> 912 bytes .../InvalidEEnotBeforeDateTest2EE.crt | Bin 0 -> 913 bytes .../InvalidLongSerialNumberTest18EE.crt | Bin 0 -> 948 bytes .../InvalidMappingFromanyPolicyTest7EE.crt | Bin 0 -> 936 bytes .../InvalidMappingToanyPolicyTest8EE.crt | Bin 0 -> 926 bytes .../InvalidMissingbasicConstraintsTest1EE.crt | Bin 0 -> 940 bytes .../InvalidNameChainingOrderTest2EE.crt | Bin 0 -> 999 bytes .../nist-certs/InvalidNameChainingTest1EE.crt | Bin 0 -> 914 bytes .../InvalidNegativeSerialNumberTest15EE.crt | Bin 0 -> 937 bytes .../InvalidPolicyMappingTest10EE.crt | Bin 0 -> 938 bytes .../InvalidPolicyMappingTest2EE.crt | Bin 0 -> 918 bytes .../InvalidPolicyMappingTest4EE.crt | Bin 0 -> 928 bytes .../InvalidRFC822nameConstraintsTest22EE.crt | Bin 0 -> 982 bytes .../InvalidRFC822nameConstraintsTest24EE.crt | Bin 0 -> 993 bytes .../InvalidRFC822nameConstraintsTest26EE.crt | Bin 0 -> 982 bytes ...alidSelfIssuedinhibitAnyPolicyTest10EE.crt | Bin 0 -> 919 bytes ...validSelfIssuedinhibitAnyPolicyTest8EE.crt | Bin 0 -> 944 bytes ...SelfIssuedinhibitPolicyMappingTest10EE.crt | Bin 0 -> 952 bytes ...SelfIssuedinhibitPolicyMappingTest11EE.crt | Bin 0 -> 952 bytes ...dSelfIssuedinhibitPolicyMappingTest8EE.crt | Bin 0 -> 954 bytes ...dSelfIssuedinhibitPolicyMappingTest9EE.crt | Bin 0 -> 954 bytes ...lidSelfIssuedpathLenConstraintTest16EE.crt | Bin 0 -> 944 bytes ...SelfIssuedrequireExplicitPolicyTest7EE.crt | Bin 0 -> 925 bytes ...SelfIssuedrequireExplicitPolicyTest8EE.crt | Bin 0 -> 925 bytes .../InvalidURInameConstraintsTest35EE.crt | Bin 0 -> 987 bytes .../InvalidURInameConstraintsTest37EE.crt | Bin 0 -> 987 bytes ...ownCriticalCertificateExtensionTest2EE.crt | Bin 0 -> 954 bytes .../nist-certs/InvalidcAFalseTest2EE.crt | Bin 0 -> 934 bytes .../nist-certs/InvalidcAFalseTest3EE.crt | Bin 0 -> 938 bytes .../nist-certs/InvalidcRLIssuerTest27EE.crt | Bin 0 -> 999 bytes .../nist-certs/InvalidcRLIssuerTest31EE.crt | Bin 0 -> 1136 bytes .../nist-certs/InvalidcRLIssuerTest32EE.crt | Bin 0 -> 1136 bytes .../nist-certs/InvalidcRLIssuerTest34EE.crt | Bin 0 -> 1044 bytes .../nist-certs/InvalidcRLIssuerTest35EE.crt | Bin 0 -> 1128 bytes .../InvalidinhibitAnyPolicyTest1EE.crt | Bin 0 -> 919 bytes .../InvalidinhibitAnyPolicyTest4EE.crt | Bin 0 -> 923 bytes .../InvalidinhibitAnyPolicyTest5EE.crt | Bin 0 -> 925 bytes .../InvalidinhibitAnyPolicyTest6EE.crt | Bin 0 -> 926 bytes .../InvalidinhibitPolicyMappingTest1EE.crt | Bin 0 -> 950 bytes .../InvalidinhibitPolicyMappingTest3EE.crt | Bin 0 -> 943 bytes .../InvalidinhibitPolicyMappingTest5EE.crt | Bin 0 -> 942 bytes .../InvalidinhibitPolicyMappingTest6EE.crt | Bin 0 -> 947 bytes ...lidkeyUsageCriticalcRLSignFalseTest4EE.crt | Bin 0 -> 954 bytes ...eyUsageCriticalkeyCertSignFalseTest1EE.crt | Bin 0 -> 962 bytes ...keyUsageNotCriticalcRLSignFalseTest5EE.crt | Bin 0 -> 962 bytes ...sageNotCriticalkeyCertSignFalseTest2EE.crt | Bin 0 -> 963 bytes ...alidonlyContainsAttributeCertsTest14EE.crt | Bin 0 -> 945 bytes .../InvalidonlyContainsCACertsTest12EE.crt | Bin 0 -> 931 bytes .../InvalidonlyContainsUserCertsTest11EE.crt | Bin 0 -> 952 bytes .../InvalidonlySomeReasonsTest15EE.crt | Bin 0 -> 924 bytes .../InvalidonlySomeReasonsTest16EE.crt | Bin 0 -> 924 bytes .../InvalidonlySomeReasonsTest17EE.crt | Bin 0 -> 924 bytes .../InvalidonlySomeReasonsTest20EE.crt | Bin 0 -> 1153 bytes .../InvalidonlySomeReasonsTest21EE.crt | Bin 0 -> 1153 bytes .../InvalidpathLenConstraintTest10EE.crt | Bin 0 -> 953 bytes .../InvalidpathLenConstraintTest11EE.crt | Bin 0 -> 940 bytes .../InvalidpathLenConstraintTest12EE.crt | Bin 0 -> 957 bytes .../InvalidpathLenConstraintTest5EE.crt | Bin 0 -> 930 bytes .../InvalidpathLenConstraintTest6EE.crt | Bin 0 -> 947 bytes .../InvalidpathLenConstraintTest9EE.crt | Bin 0 -> 935 bytes ...Invalidpre2000UTCEEnotAfterDateTest7EE.crt | Bin 0 -> 926 bytes .../InvalidrequireExplicitPolicyTest3EE.crt | Bin 0 -> 919 bytes .../InvalidrequireExplicitPolicyTest5EE.crt | Bin 0 -> 925 bytes .../nist-certs/LongSerialNumberCACert.crt | Bin 0 -> 910 bytes .../nist-certs/Mapping1to2CACert.crt | Bin 0 -> 960 bytes .../nist-certs/MappingFromanyPolicyCACert.crt | Bin 0 -> 961 bytes .../nist-certs/MappingToanyPolicyCACert.crt | Bin 0 -> 965 bytes .../MissingbasicConstraintsCACert.crt | Bin 0 -> 899 bytes .../nist-certs/NameOrderingCACert.crt | Bin 0 -> 980 bytes .../nist-certs/NegativeSerialNumberCACert.crt | Bin 0 -> 914 bytes SecurityTests/nist-certs/NoCRLCACert.crt | Bin 0 -> 898 bytes SecurityTests/nist-certs/NoPoliciesCACert.crt | Bin 0 -> 878 bytes .../NoissuingDistributionPointCACert.crt | Bin 0 -> 919 bytes .../nist-certs/OldCRLnextUpdateCACert.crt | Bin 0 -> 910 bytes .../nist-certs/OverlappingPoliciesTest6EE.crt | Bin 0 -> 948 bytes .../nist-certs/P12Mapping1to3CACert.crt | Bin 0 -> 978 bytes .../nist-certs/P12Mapping1to3subCACert.crt | Bin 0 -> 1000 bytes .../nist-certs/P12Mapping1to3subsubCACert.crt | Bin 0 -> 980 bytes .../nist-certs/P1Mapping1to234CACert.crt | Bin 0 -> 1017 bytes .../nist-certs/P1Mapping1to234subCACert.crt | Bin 0 -> 1002 bytes .../P1anyPolicyMapping1to2CACert.crt | Bin 0 -> 1329 bytes .../PanyPolicyMapping1to2CACert.crt | Bin 0 -> 965 bytes .../nist-certs/PoliciesP1234CACert.crt | Bin 0 -> 964 bytes .../nist-certs/PoliciesP1234subCAP123Cert.crt | Bin 0 -> 948 bytes .../PoliciesP1234subsubCAP123P12Cert.crt | Bin 0 -> 947 bytes .../nist-certs/PoliciesP123CACert.crt | Bin 0 -> 949 bytes .../nist-certs/PoliciesP123subCAP12Cert.crt | Bin 0 -> 931 bytes .../PoliciesP123subsubCAP12P1Cert.crt | Bin 0 -> 926 bytes .../PoliciesP123subsubCAP12P2Cert.crt | Bin 0 -> 926 bytes .../PoliciesP123subsubsubCAP12P2P1Cert.crt | Bin 0 -> 936 bytes .../nist-certs/PoliciesP12CACert.crt | Bin 0 -> 934 bytes .../nist-certs/PoliciesP12subCAP1Cert.crt | Bin 0 -> 912 bytes .../PoliciesP12subsubCAP1P2Cert.crt | Bin 0 -> 922 bytes .../nist-certs/PoliciesP2subCA2Cert.crt | Bin 0 -> 918 bytes .../nist-certs/PoliciesP2subCACert.crt | Bin 0 -> 901 bytes SecurityTests/nist-certs/PoliciesP3CACert.crt | Bin 0 -> 919 bytes .../RFC3280MandatoryAttributeTypesCACert.crt | Bin 0 -> 980 bytes .../RFC3280OptionalAttributeTypesCACert.crt | Bin 0 -> 992 bytes SecurityTests/nist-certs/RevokedsubCACert.crt | Bin 0 -> 897 bytes ...rfromPrintableStringtoUTF8StringCACert.crt | Bin 0 -> 935 bytes ...CertificateandCRLKeysCA2CRLSigningCert.crt | Bin 0 -> 909 bytes ...eandCRLKeysCA2CertificateSigningCACert.crt | Bin 0 -> 926 bytes ...cateandCRLKeysCertificateSigningCACert.crt | Bin 0 -> 926 bytes .../nist-certs/TrustAnchorRootCertificate.crt | Bin 0 -> 843 bytes SecurityTests/nist-certs/TwoCRLsCACert.crt | Bin 0 -> 900 bytes SecurityTests/nist-certs/UIDCACert.crt | Bin 0 -> 900 bytes .../UTF8StringCaseInsensitiveMatchCACert.crt | Bin 0 -> 925 bytes .../UTF8StringEncodedNamesCACert.crt | Bin 0 -> 902 bytes .../UnknownCRLEntryExtensionCACert.crt | Bin 0 -> 919 bytes .../nist-certs/UnknownCRLExtensionCACert.crt | Bin 0 -> 913 bytes .../UserNoticeQualifierTest15EE.crt | Bin 0 -> 1026 bytes .../UserNoticeQualifierTest16EE.crt | Bin 0 -> 1145 bytes .../UserNoticeQualifierTest17EE.crt | Bin 0 -> 1014 bytes .../UserNoticeQualifierTest18EE.crt | Bin 0 -> 1240 bytes .../UserNoticeQualifierTest19EE.crt | Bin 0 -> 1263 bytes .../ValidBasicSelfIssuedNewWithOldTest3EE.crt | Bin 0 -> 945 bytes .../ValidBasicSelfIssuedNewWithOldTest4EE.crt | Bin 0 -> 945 bytes .../ValidBasicSelfIssuedOldWithNewTest1EE.crt | Bin 0 -> 945 bytes .../ValidCertificatePathTest1EE.crt | Bin 0 -> 893 bytes .../ValidDNSnameConstraintsTest30EE.crt | Bin 0 -> 976 bytes .../ValidDNSnameConstraintsTest32EE.crt | Bin 0 -> 976 bytes ...alidDNandRFC822nameConstraintsTest27EE.crt | Bin 0 -> 1044 bytes .../ValidDNnameConstraintsTest11EE.crt | Bin 0 -> 985 bytes .../ValidDNnameConstraintsTest14EE.crt | Bin 0 -> 926 bytes .../ValidDNnameConstraintsTest18EE.crt | Bin 0 -> 932 bytes .../ValidDNnameConstraintsTest19EE.crt | Bin 0 -> 957 bytes .../ValidDNnameConstraintsTest1EE.crt | Bin 0 -> 956 bytes .../ValidDNnameConstraintsTest4EE.crt | Bin 0 -> 1016 bytes .../ValidDNnameConstraintsTest5EE.crt | Bin 0 -> 1109 bytes .../ValidDNnameConstraintsTest6EE.crt | Bin 0 -> 956 bytes .../ValidDSAParameterInheritanceTest5EE.crt | Bin 0 -> 574 bytes .../nist-certs/ValidDSASignaturesTest4EE.crt | Bin 0 -> 835 bytes ...alidGeneralizedTimenotAfterDateTest8EE.crt | Bin 0 -> 925 bytes ...lidGeneralizedTimenotBeforeDateTest4EE.crt | Bin 0 -> 926 bytes .../ValidLongSerialNumberTest16EE.crt | Bin 0 -> 946 bytes .../ValidLongSerialNumberTest17EE.crt | Bin 0 -> 946 bytes ...ValidNameChainingCapitalizationTest5EE.crt | Bin 0 -> 922 bytes .../ValidNameChainingWhitespaceTest3EE.crt | Bin 0 -> 923 bytes .../ValidNameChainingWhitespaceTest4EE.crt | Bin 0 -> 924 bytes .../nist-certs/ValidNameUIDsTest6EE.crt | Bin 0 -> 901 bytes .../ValidNegativeSerialNumberTest14EE.crt | Bin 0 -> 936 bytes .../nist-certs/ValidPolicyMappingTest11EE.crt | Bin 0 -> 936 bytes .../nist-certs/ValidPolicyMappingTest12EE.crt | Bin 0 -> 1339 bytes .../nist-certs/ValidPolicyMappingTest13EE.crt | Bin 0 -> 929 bytes .../nist-certs/ValidPolicyMappingTest14EE.crt | Bin 0 -> 929 bytes .../nist-certs/ValidPolicyMappingTest1EE.crt | Bin 0 -> 916 bytes .../nist-certs/ValidPolicyMappingTest3EE.crt | Bin 0 -> 926 bytes .../nist-certs/ValidPolicyMappingTest5EE.crt | Bin 0 -> 924 bytes .../nist-certs/ValidPolicyMappingTest6EE.crt | Bin 0 -> 924 bytes .../nist-certs/ValidPolicyMappingTest9EE.crt | Bin 0 -> 927 bytes ...dRFC3280MandatoryAttributeTypesTest7EE.crt | Bin 0 -> 1011 bytes ...idRFC3280OptionalAttributeTypesTest8EE.crt | Bin 0 -> 1022 bytes .../ValidRFC822nameConstraintsTest21EE.crt | Bin 0 -> 991 bytes .../ValidRFC822nameConstraintsTest23EE.crt | Bin 0 -> 980 bytes .../ValidRFC822nameConstraintsTest25EE.crt | Bin 0 -> 991 bytes ...romPrintableStringtoUTF8StringTest10EE.crt | Bin 0 -> 965 bytes ...ValidSelfIssuedinhibitAnyPolicyTest7EE.crt | Bin 0 -> 939 bytes ...ValidSelfIssuedinhibitAnyPolicyTest9EE.crt | Bin 0 -> 939 bytes ...dSelfIssuedinhibitPolicyMappingTest7EE.crt | Bin 0 -> 949 bytes ...lidSelfIssuedpathLenConstraintTest15EE.crt | Bin 0 -> 938 bytes ...lidSelfIssuedpathLenConstraintTest17EE.crt | Bin 0 -> 941 bytes ...SelfIssuedrequireExplicitPolicyTest6EE.crt | Bin 0 -> 945 bytes .../ValidURInameConstraintsTest34EE.crt | Bin 0 -> 994 bytes .../ValidURInameConstraintsTest36EE.crt | Bin 0 -> 997 bytes ...UTF8StringCaseInsensitiveMatchTest11EE.crt | Bin 0 -> 962 bytes .../ValidUTF8StringEncodedNamesTest9EE.crt | Bin 0 -> 924 bytes ...NotCriticalCertificateExtensionTest1EE.crt | Bin 0 -> 952 bytes ...alidbasicConstraintsNotCriticalTest4EE.crt | Bin 0 -> 948 bytes .../nist-certs/ValidcRLIssuerTest28EE.crt | Bin 0 -> 1156 bytes .../nist-certs/ValidcRLIssuerTest29EE.crt | Bin 0 -> 1065 bytes .../nist-certs/ValidcRLIssuerTest30EE.crt | Bin 0 -> 1156 bytes .../nist-certs/ValidcRLIssuerTest33EE.crt | Bin 0 -> 1134 bytes .../ValidinhibitAnyPolicyTest2EE.crt | Bin 0 -> 931 bytes .../ValidinhibitPolicyMappingTest2EE.crt | Bin 0 -> 938 bytes .../ValidinhibitPolicyMappingTest4EE.crt | Bin 0 -> 941 bytes .../ValidkeyUsageNotCriticalTest3EE.crt | Bin 0 -> 932 bytes .../ValidonlyContainsCACertsTest13EE.crt | Bin 0 -> 946 bytes .../ValidonlySomeReasonsTest18EE.crt | Bin 0 -> 1035 bytes .../ValidonlySomeReasonsTest19EE.crt | Bin 0 -> 1151 bytes .../ValidpathLenConstraintTest13EE.crt | Bin 0 -> 938 bytes .../ValidpathLenConstraintTest14EE.crt | Bin 0 -> 955 bytes .../ValidpathLenConstraintTest7EE.crt | Bin 0 -> 925 bytes .../ValidpathLenConstraintTest8EE.crt | Bin 0 -> 942 bytes .../Validpre2000UTCnotBeforeDateTest3EE.crt | Bin 0 -> 920 bytes .../ValidrequireExplicitPolicyTest1EE.crt | Bin 0 -> 918 bytes .../ValidrequireExplicitPolicyTest2EE.crt | Bin 0 -> 917 bytes .../ValidrequireExplicitPolicyTest4EE.crt | Bin 0 -> 942 bytes SecurityTests/nist-certs/WrongCRLCACert.crt | Bin 0 -> 901 bytes SecurityTests/nist-certs/anyPolicyCACert.crt | Bin 0 -> 911 bytes .../basicConstraintsCriticalcAFalseCACert.crt | Bin 0 -> 923 bytes .../basicConstraintsNotCriticalCACert.crt | Bin 0 -> 918 bytes ...sicConstraintsNotCriticalcAFalseCACert.crt | Bin 0 -> 924 bytes SecurityTests/nist-certs/deltaCRLCA1Cert.crt | Bin 0 -> 901 bytes SecurityTests/nist-certs/deltaCRLCA2Cert.crt | Bin 0 -> 901 bytes SecurityTests/nist-certs/deltaCRLCA3Cert.crt | Bin 0 -> 901 bytes .../deltaCRLIndicatorNoBaseCACert.crt | Bin 0 -> 917 bytes .../nist-certs/distributionPoint1CACert.crt | Bin 0 -> 910 bytes .../nist-certs/distributionPoint2CACert.crt | Bin 0 -> 910 bytes .../nist-certs/indirectCRLCA1Cert.crt | Bin 0 -> 904 bytes .../nist-certs/indirectCRLCA2Cert.crt | Bin 0 -> 904 bytes .../nist-certs/indirectCRLCA3Cert.crt | Bin 0 -> 904 bytes .../indirectCRLCA3cRLIssuerCert.crt | Bin 0 -> 1010 bytes .../nist-certs/indirectCRLCA4Cert.crt | Bin 0 -> 904 bytes .../indirectCRLCA4cRLIssuerCert.crt | Bin 0 -> 1144 bytes .../nist-certs/indirectCRLCA5Cert.crt | Bin 0 -> 904 bytes .../nist-certs/indirectCRLCA6Cert.crt | Bin 0 -> 904 bytes .../nist-certs/inhibitAnyPolicy0CACert.crt | Bin 0 -> 940 bytes .../nist-certs/inhibitAnyPolicy1CACert.crt | Bin 0 -> 940 bytes .../inhibitAnyPolicy1SelfIssuedCACert.crt | Bin 0 -> 917 bytes .../inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt | Bin 0 -> 919 bytes .../inhibitAnyPolicy1subCA1Cert.crt | Bin 0 -> 915 bytes .../inhibitAnyPolicy1subCA2Cert.crt | Bin 0 -> 915 bytes .../inhibitAnyPolicy1subCAIAP5Cert.crt | Bin 0 -> 941 bytes .../inhibitAnyPolicy1subsubCA2Cert.crt | Bin 0 -> 922 bytes .../nist-certs/inhibitAnyPolicy5CACert.crt | Bin 0 -> 940 bytes .../nist-certs/inhibitAnyPolicy5subCACert.crt | Bin 0 -> 937 bytes .../inhibitAnyPolicy5subsubCACert.crt | Bin 0 -> 926 bytes .../nist-certs/inhibitAnyPolicyTest3EE.crt | Bin 0 -> 921 bytes .../inhibitPolicyMapping0CACert.crt | Bin 0 -> 935 bytes .../inhibitPolicyMapping0subCACert.crt | Bin 0 -> 970 bytes .../inhibitPolicyMapping1P12CACert.crt | Bin 0 -> 953 bytes .../inhibitPolicyMapping1P12subCACert.crt | Bin 0 -> 1018 bytes .../inhibitPolicyMapping1P12subCAIPM5Cert.crt | Bin 0 -> 973 bytes .../inhibitPolicyMapping1P12subsubCACert.crt | Bin 0 -> 998 bytes ...hibitPolicyMapping1P12subsubCAIPM5Cert.crt | Bin 0 -> 1006 bytes .../inhibitPolicyMapping1P1CACert.crt | Bin 0 -> 938 bytes ...nhibitPolicyMapping1P1SelfIssuedCACert.crt | Bin 0 -> 931 bytes ...bitPolicyMapping1P1SelfIssuedsubCACert.crt | Bin 0 -> 979 bytes .../inhibitPolicyMapping1P1subCACert.crt | Bin 0 -> 976 bytes .../inhibitPolicyMapping1P1subsubCACert.crt | Bin 0 -> 982 bytes .../inhibitPolicyMapping5CACert.crt | Bin 0 -> 935 bytes .../inhibitPolicyMapping5subCACert.crt | Bin 0 -> 947 bytes .../inhibitPolicyMapping5subsubCACert.crt | Bin 0 -> 934 bytes .../inhibitPolicyMapping5subsubsubCACert.crt | Bin 0 -> 982 bytes .../keyUsageCriticalcRLSignFalseCACert.crt | Bin 0 -> 923 bytes ...keyUsageCriticalkeyCertSignFalseCACert.crt | Bin 0 -> 927 bytes .../nist-certs/keyUsageNotCriticalCACert.crt | Bin 0 -> 910 bytes .../keyUsageNotCriticalcRLSignFalseCACert.crt | Bin 0 -> 924 bytes ...UsageNotCriticalkeyCertSignFalseCACert.crt | Bin 0 -> 928 bytes .../nist-certs/nameConstraintsDN1CACert.crt | Bin 0 -> 1009 bytes .../nameConstraintsDN1SelfIssuedCACert.crt | Bin 0 -> 921 bytes .../nameConstraintsDN1subCA1Cert.crt | Bin 0 -> 1079 bytes .../nameConstraintsDN1subCA2Cert.crt | Bin 0 -> 1051 bytes .../nameConstraintsDN1subCA3Cert.crt | Bin 0 -> 995 bytes .../nist-certs/nameConstraintsDN2CACert.crt | Bin 0 -> 1095 bytes .../nist-certs/nameConstraintsDN3CACert.crt | Bin 0 -> 1008 bytes .../nameConstraintsDN3subCA1Cert.crt | Bin 0 -> 1022 bytes .../nameConstraintsDN3subCA2Cert.crt | Bin 0 -> 995 bytes .../nist-certs/nameConstraintsDN4CACert.crt | Bin 0 -> 1093 bytes .../nist-certs/nameConstraintsDN5CACert.crt | Bin 0 -> 1123 bytes .../nist-certs/nameConstraintsDNS1CACert.crt | Bin 0 -> 954 bytes .../nist-certs/nameConstraintsDNS2CACert.crt | Bin 0 -> 957 bytes .../nameConstraintsRFC822CA1Cert.crt | Bin 0 -> 958 bytes .../nameConstraintsRFC822CA2Cert.crt | Bin 0 -> 957 bytes .../nameConstraintsRFC822CA3Cert.crt | Bin 0 -> 957 bytes .../nist-certs/nameConstraintsURI1CACert.crt | Bin 0 -> 955 bytes .../nist-certs/nameConstraintsURI2CACert.crt | Bin 0 -> 957 bytes .../onlyContainsAttributeCertsCACert.crt | Bin 0 -> 918 bytes .../nist-certs/onlyContainsCACertsCACert.crt | Bin 0 -> 911 bytes .../onlyContainsUserCertsCACert.crt | Bin 0 -> 913 bytes .../nist-certs/onlySomeReasonsCA1Cert.crt | Bin 0 -> 908 bytes .../nist-certs/onlySomeReasonsCA2Cert.crt | Bin 0 -> 908 bytes .../nist-certs/onlySomeReasonsCA3Cert.crt | Bin 0 -> 908 bytes .../nist-certs/onlySomeReasonsCA4Cert.crt | Bin 0 -> 908 bytes .../nist-certs/pathLenConstraint0CACert.crt | Bin 0 -> 913 bytes .../pathLenConstraint0SelfIssuedCACert.crt | Bin 0 -> 919 bytes .../pathLenConstraint0subCA2Cert.crt | Bin 0 -> 923 bytes .../pathLenConstraint0subCACert.crt | Bin 0 -> 922 bytes .../nist-certs/pathLenConstraint1CACert.crt | Bin 0 -> 913 bytes .../pathLenConstraint1SelfIssuedCACert.crt | Bin 0 -> 919 bytes .../pathLenConstraint1SelfIssuedsubCACert.crt | Bin 0 -> 925 bytes .../pathLenConstraint1subCACert.crt | Bin 0 -> 922 bytes .../nist-certs/pathLenConstraint6CACert.crt | Bin 0 -> 913 bytes .../pathLenConstraint6subCA0Cert.crt | Bin 0 -> 926 bytes .../pathLenConstraint6subCA1Cert.crt | Bin 0 -> 926 bytes .../pathLenConstraint6subCA4Cert.crt | Bin 0 -> 926 bytes .../pathLenConstraint6subsubCA00Cert.crt | Bin 0 -> 934 bytes .../pathLenConstraint6subsubCA11Cert.crt | Bin 0 -> 934 bytes .../pathLenConstraint6subsubCA41Cert.crt | Bin 0 -> 934 bytes .../pathLenConstraint6subsubsubCA11XCert.crt | Bin 0 -> 939 bytes .../pathLenConstraint6subsubsubCA41XCert.crt | Bin 0 -> 939 bytes .../nist-certs/pre2000CRLnextUpdateCACert.crt | Bin 0 -> 914 bytes .../requireExplicitPolicy0CACert.crt | Bin 0 -> 933 bytes .../requireExplicitPolicy0subCACert.crt | Bin 0 -> 930 bytes .../requireExplicitPolicy0subsubCACert.crt | Bin 0 -> 936 bytes .../requireExplicitPolicy0subsubsubCACert.crt | Bin 0 -> 942 bytes .../requireExplicitPolicy10CACert.crt | Bin 0 -> 934 bytes .../requireExplicitPolicy10subCACert.crt | Bin 0 -> 932 bytes .../requireExplicitPolicy10subsubCACert.crt | Bin 0 -> 938 bytes ...requireExplicitPolicy10subsubsubCACert.crt | Bin 0 -> 944 bytes .../requireExplicitPolicy2CACert.crt | Bin 0 -> 933 bytes ...requireExplicitPolicy2SelfIssuedCACert.crt | Bin 0 -> 927 bytes ...uireExplicitPolicy2SelfIssuedsubCACert.crt | Bin 0 -> 933 bytes .../requireExplicitPolicy2subCACert.crt | Bin 0 -> 930 bytes .../requireExplicitPolicy4CACert.crt | Bin 0 -> 933 bytes .../requireExplicitPolicy4subCACert.crt | Bin 0 -> 930 bytes .../requireExplicitPolicy4subsubCACert.crt | Bin 0 -> 936 bytes .../requireExplicitPolicy4subsubsubCACert.crt | Bin 0 -> 942 bytes .../requireExplicitPolicy5CACert.crt | Bin 0 -> 933 bytes .../requireExplicitPolicy5subCACert.crt | Bin 0 -> 930 bytes .../requireExplicitPolicy5subsubCACert.crt | Bin 0 -> 936 bytes .../requireExplicitPolicy5subsubsubCACert.crt | Bin 0 -> 942 bytes .../requireExplicitPolicy7CACert.crt | Bin 0 -> 933 bytes .../requireExplicitPolicy7subCARE2Cert.crt | Bin 0 -> 952 bytes ...quireExplicitPolicy7subsubCARE2RE4Cert.crt | Bin 0 -> 964 bytes ...reExplicitPolicy7subsubsubCARE2RE4Cert.crt | Bin 0 -> 954 bytes SecurityTests/regressions/Makefile | 190 + SecurityTests/regressions/README | 220 + .../auth/auth-01-immediate-agent.c | 41 + .../regressions/auth/auth-02-aewp-basic.c | 40 + .../auth/auth-SessionCreate-01-basic.c | 34 + .../regressions/dl/dl-10-create-delete.c | 285 + .../regressions/dl/dl-11-create-relation.c | 269 + SecurityTests/regressions/dl/dl-12-modify.c | 687 + SecurityTests/regressions/inc/MyHarness.pm | 29 + SecurityTests/regressions/inc/Test.pm | 955 ++ SecurityTests/regressions/inc/Test/Builder.pm | 1873 +++ .../regressions/inc/Test/Builder/Module.pm | 185 + .../regressions/inc/Test/Builder/Tester.pm | 646 + .../inc/Test/Builder/Tester/Color.pm | 50 + SecurityTests/regressions/inc/Test/Harness.pm | 1169 ++ .../regressions/inc/Test/Harness/Assert.pm | 64 + .../regressions/inc/Test/Harness/Iterator.pm | 70 + .../regressions/inc/Test/Harness/Point.pm | 143 + .../regressions/inc/Test/Harness/Results.pm | 182 + .../regressions/inc/Test/Harness/Straps.pm | 648 + .../regressions/inc/Test/Harness/TAP.pod | 492 + .../regressions/inc/Test/Harness/Util.pm | 133 + SecurityTests/regressions/inc/Test/More.pm | 1569 ++ SecurityTests/regressions/inc/Test/Simple.pm | 230 + .../regressions/inc/Test/Tutorial.pod | 603 + .../regressions/kc/kc-05-retain-release.c | 36 + .../regressions/kc/kc-10-unlock-noui.c | 37 + .../regressions/kc/kc-11-unlock-referral.c | 64 + SecurityTests/regressions/kc/kc-12-status.c | 138 + .../regressions/kc/kc-15-item-add-generic.c | 57 + .../kc/kc-16-item-add-certificate.c | 227 + .../regressions/kc/kc-17-item-find-key.c | 101 + .../regressions/kc/kc-18-item-find-internet.c | 114 + .../regressions/kc/kc-19-item-copy-internet.c | 112 + .../regressions/kc/kc-20-item-change-label.m | 327 + .../regressions/kc/kc-21-item-use-callback.c | 102 + .../regressions/kc/kc-22-key-symmetric.c | 133 + .../regressions/kc/kc-23-item-notify.c | 83 + SecurityTests/regressions/kc/kc-23-notify.c | 99 + SecurityTests/regressions/kc/kc-24-login.c | 95 + .../regressions/kc/kc-25-bulk-notify.c | 90 + SecurityTests/regressions/kc/kc-26-is-valid.c | 59 + SecurityTests/regressions/kc/kc-30-trust.c | 25 + .../regressions/kc/kc-40-item-change-label2.m | 351 + .../regressions/kc/kc-46-dl-add-certificate.c | 247 + .../regressions/kc/kc-50-iPhone-emulation.c | 325 + SecurityTests/regressions/kc/kc-50-thread.c | 78 + .../regressions/kc/kc-51-testSecItemFind.c | 3359 +++++ .../regressions/kc/kc-52-testCFEqualAndHash.c | 73 + SecurityTests/regressions/t/40kc-list.t | 13 + SecurityTests/regressions/t/40kc-unlock.t | 27 + .../regressions/t/41kc-unlock-referral.t | 37 + SecurityTests/regressions/t/IPC/Run3.pm | 666 + SecurityTests/regressions/t/security.pl | 66 + SecurityTests/regressions/test/00testtest.c | 45 + SecurityTests/regressions/test/testcpp.h | 83 + SecurityTests/regressions/test/testcssm.c | 68 + SecurityTests/regressions/test/testcssm.h | 30 + SecurityTests/regressions/test/testenv.c | 87 + SecurityTests/regressions/test/testenv.h | 40 + .../regressions/test/testeventqueue.c | 95 + .../regressions/test/testeventqueue.h | 25 + SecurityTests/regressions/test/testleaks.c | 188 + SecurityTests/regressions/test/testleaks.h | 59 + SecurityTests/regressions/test/testmore.c | 274 + SecurityTests/regressions/test/testmore.h | 172 + SecurityTests/regressions/test/testsecevent.c | 171 + SecurityTests/regressions/test/testsecevent.h | 38 + SecurityTests/regressions/ut/ut-00-errors.cpp | 18 + .../regressions/ut/ut-01-devrandom.cpp | 23 + .../Apple TEST RootCertificate.crt | Bin 0 -> 1244 bytes ...Relations Certification Authority Cert.crt | Bin 0 -> 1063 bytes ...ions Certification Authority TEST Cert.crt | Bin 0 -> 1068 bytes .../shoebox-certs/AppleRootCertificate.crt | Bin 0 -> 1215 bytes .../Invalid.com.apple.testcard.crt | Bin 0 -> 1524 bytes SecurityTests/test-certs/CACert.ecc.pem | 11 + SecurityTests/test-certs/CACert.rsa.pem | 14 + SecurityTests/test-certs/CAKey.ecc.pem | 5 + SecurityTests/test-certs/CAKey.rsa.pem | 16 + .../test-certs/ClientCert.ecc.ecc.pem | 9 + .../test-certs/ClientCert.ecc.rsa.pem | 10 + .../test-certs/ClientCert.rsa.ecc.pem | 11 + .../test-certs/ClientCert.rsa.rsa.pem | 12 + SecurityTests/test-certs/ClientKey.ecc.pem | 25 + SecurityTests/test-certs/ClientKey.rsa.pem | 16 + SecurityTests/test-certs/ClientReq.ecc.pem | 7 + SecurityTests/test-certs/ClientReq.rsa.pem | 10 + .../test-certs/SECG_ecc-secp256r1-client.pem | 27 + .../SECG_ecc_rsa-secp256r1-client.pem | 28 + .../test-certs/ServerCert.ecc.ecc.pem | 9 + .../test-certs/ServerCert.ecc.rsa.pem | 10 + .../test-certs/ServerCert.rsa.ecc.pem | 10 + .../test-certs/ServerCert.rsa.rsa.pem | 12 + SecurityTests/test-certs/ServerKey.ecc.pem | 25 + SecurityTests/test-certs/ServerKey.rsa.pem | 16 + SecurityTests/test-certs/ServerReq.ecc.pem | 7 + SecurityTests/test-certs/ServerReq.rsa.pem | 10 + SecurityTests/test-certs/ecparam.pem | 3 + .../English.lproj/InfoPlist.strings | 5 + SecurityTests/testKeychainAPI/run.sh | 12 + .../testKeychainAPI/testKeychainAPI | Bin 0 -> 71104 bytes .../testKeychainAPI.pbproj/project.pbxproj | 1871 +++ .../testKeychainAPI/KCAPI_CString.cpp | 445 + .../testKeychainAPI/KCAPI_CString.h | 213 + .../testKeychainAPI/KCAPI_Cert.cpp | 88 + .../testKeychainAPI/KCAPI_Cert.h | 51 + .../testKeychainAPI/KCAPI_Item.cpp | 512 + .../testKeychainAPI/KCAPI_Item.h | 298 + .../testKeychainAPI/KCAPI_Keychain.cpp | 784 + .../testKeychainAPI/KCAPI_Keychain.h | 463 + .../testKeychainAPI/KCAPI_Manager.cpp | 64 + .../testKeychainAPI/KCAPI_Manager.h | 52 + .../testKeychainAPI/KCAPI_Password.cpp | 372 + .../testKeychainAPI/KCAPI_Password.h | 176 + .../testKeychainAPI/KCOperation.cpp | 211 + .../testKeychainAPI/KCOperation.h | 259 + .../testKeychainAPI/KCOperationID.cpp | 124 + .../testKeychainAPI/KCOperationID.h | 159 + .../testKeychainAPI/KCParamUtility.cpp | 1 + .../testKeychainAPI/KCParamUtility.h | 649 + .../testKeychainAPI/testKeychainAPI/Radar.cpp | 116 + .../testKeychainAPI/testKeychainAPI/Radar.h | 48 + .../testKeychainAPI/scripts/cleanup | 7 + .../testKeychainAPI/scripts/error_scripts | 166 + .../scripts/error_sub_cases_scripts | 494 + .../testKeychainAPI/scripts/script0000 | 19 + .../testKeychainAPI/scripts/script0001 | 69 + .../testKeychainAPI/scripts/script0001.001 | 15 + .../testKeychainAPI/scripts/script0002 | 69 + .../testKeychainAPI/scripts/script0002.000 | 65 + .../testKeychainAPI/scripts/script0003 | 69 + .../testKeychainAPI/scripts/script0003.000 | 70 + .../testKeychainAPI/scripts/script0004 | 69 + .../testKeychainAPI/scripts/script0004.000 | 70 + .../testKeychainAPI/scripts/script0005 | 77 + .../testKeychainAPI/scripts/script0005.000 | 61 + .../testKeychainAPI/scripts/script0006 | 80 + .../testKeychainAPI/scripts/script0006.000 | 69 + .../testKeychainAPI/scripts/script0007 | 82 + .../testKeychainAPI/scripts/script0007.000 | 69 + .../testKeychainAPI/scripts/script0008 | 94 + .../testKeychainAPI/scripts/script0008.000 | 57 + .../testKeychainAPI/scripts/script0009 | 50 + .../testKeychainAPI/scripts/script0010 | 87 + .../testKeychainAPI/scripts/script0010.000 | 66 + .../testKeychainAPI/scripts/script0011 | 189 + .../testKeychainAPI/scripts/script0011.001 | 130 + .../testKeychainAPI/scripts/script0011.002 | 27 + .../testKeychainAPI/scripts/script0011.003 | 122 + .../testKeychainAPI/scripts/script0012 | 60 + .../testKeychainAPI/scripts/script0012.000 | 45 + .../testKeychainAPI/scripts/script0012.001 | 17 + .../testKeychainAPI/scripts/script0013 | 79 + .../testKeychainAPI/scripts/script0013.000 | 30 + .../testKeychainAPI/scripts/script0014 | 80 + .../testKeychainAPI/scripts/script0014.000 | 49 + .../testKeychainAPI/scripts/script0015 | 92 + .../testKeychainAPI/scripts/script0015.000 | 59 + .../testKeychainAPI/scripts/script0016 | 86 + .../testKeychainAPI/scripts/script0016.000 | 53 + .../testKeychainAPI/scripts/script0017 | 82 + .../testKeychainAPI/scripts/script0018 | 32 + .../testKeychainAPI/scripts/script0019 | 60 + .../testKeychainAPI/scripts/script0020 | 44 + .../testKeychainAPI/scripts/script0021 | 41 + .../testKeychainAPI/scripts/script0022 | 170 + .../testKeychainAPI/scripts/script0023 | 43 + .../testKeychainAPI/scripts/script0024 | 33 + .../testKeychainAPI/scripts/script0025 | 59 + .../testKeychainAPI/scripts/script0026 | 68 + .../testKeychainAPI/scripts/script0026.000 | 44 + .../testKeychainAPI/scripts/script0026.001 | 54 + .../testKeychainAPI/scripts/script0026.002 | 42 + .../testKeychainAPI/scripts/script0027 | 68 + .../testKeychainAPI/scripts/script0027.000 | 64 + .../testKeychainAPI/scripts/script0027.001 | 55 + .../testKeychainAPI/scripts/script0027.002 | 43 + .../testKeychainAPI/scripts/script0028 | 68 + .../testKeychainAPI/scripts/script0028.000 | 63 + .../testKeychainAPI/scripts/script0028.001 | 54 + .../testKeychainAPI/scripts/script0028.002 | 42 + .../testKeychainAPI/scripts/script0029 | 73 + .../testKeychainAPI/scripts/script0029.000 | 63 + .../testKeychainAPI/scripts/script0030 | 73 + .../testKeychainAPI/scripts/script0030.000 | 63 + .../testKeychainAPI/scripts/script0031 | 73 + .../testKeychainAPI/scripts/script0031.000 | 63 + .../testKeychainAPI/scripts/script0032 | 23 + .../testKeychainAPI/scripts/script0033 | 64 + .../testKeychainAPI/scripts/script0034 | 65 + .../testKeychainAPI/scripts/script0035 | 98 + .../testKeychainAPI/scripts/script0036 | 35 + .../testKeychainAPI/testKeychainAPI.cpp | 476 + .../testKeychainAPI/testKeychainAPI.h | 68 + .../testKeychainAPI_user_manual.cwk | Bin 0 -> 115775 bytes SecurityTests/testclient/attributes.cpp | 78 + SecurityTests/testclient/attributes.h | 76 + SecurityTests/testclient/csptests.cpp | 210 + SecurityTests/testclient/csptests.h | 9 + SecurityTests/testclient/dltests.cpp | 804 ++ SecurityTests/testclient/dltests.h | 11 + SecurityTests/testclient/testclient.cpp | 132 + .../testclient.pbproj/project.pbxproj | 372 + SecurityTests/testlist.h | 8 + SecurityTests/testmain.c | 47 + SecurityTests/xdr_rpc/Makefile.xdr_test | 36 + .../AclOwnerPrototype_getOwner.decoded | 63 + .../xdr_rpc/Reference/transition.cpp | 1244 ++ .../xdr_rpc/TestData/AclEntryInfo_getAcl | Bin 0 -> 1072 bytes .../xdr_rpc/TestData/AclEntryInput_changeAcl | Bin 0 -> 404 bytes .../TestData/AclOwnerPrototype_getOwner | Bin 0 -> 231 bytes .../xdr_rpc/TestData/Context_decrypt | Bin 0 -> 536 bytes .../xdr_rpc/TestData/Query_findFirst | Bin 0 -> 1144 bytes .../xdr_rpc/securityd_data_saver.cpp | 205 + SecurityTests/xdr_rpc/securityd_data_saver.h | 208 + SecurityTests/xdr_rpc/xdr_test.cpp | 2676 ++++ SecurityTool/APPLE_LICENSE | 335 + .../SecurityTool.xcodeproj/project.pbxproj | 513 + SecurityTool/access_utils.c | 203 + SecurityTool/access_utils.h | 46 + SecurityTool/authz.c | 723 + SecurityTool/authz.h | 32 + SecurityTool/cmsutil.c | 1595 +++ SecurityTool/cmsutil.h | 39 + SecurityTool/config/debug.xcconfig | 3 + SecurityTool/config/project.xcconfig | 25 + SecurityTool/config/release.xcconfig | 3 + SecurityTool/createFVMaster.c | 790 ++ SecurityTool/createFVMaster.h | 39 + SecurityTool/db_commands.cpp | 210 + SecurityTool/db_commands.h | 39 + SecurityTool/display_error_code.c | 54 + SecurityTool/display_error_code.h | 39 + SecurityTool/entitlements.plist | 19 + SecurityTool/identity_find.c | 531 + SecurityTool/identity_find.h | 47 + SecurityTool/identity_prefs.c | 277 + SecurityTool/identity_prefs.h | 44 + SecurityTool/key_create.c | 619 + SecurityTool/key_create.h | 41 + SecurityTool/keychain_add.c | 898 ++ SecurityTool/keychain_add.h | 43 + SecurityTool/keychain_create.c | 180 + SecurityTool/keychain_create.h | 39 + SecurityTool/keychain_delete.c | 160 + SecurityTool/keychain_delete.h | 41 + SecurityTool/keychain_export.c | 441 + SecurityTool/keychain_export.h | 39 + SecurityTool/keychain_find.c | 1341 ++ SecurityTool/keychain_find.h | 83 + SecurityTool/keychain_import.c | 484 + SecurityTool/keychain_import.h | 39 + SecurityTool/keychain_list.c | 459 + SecurityTool/keychain_list.h | 43 + SecurityTool/keychain_lock.c | 118 + SecurityTool/keychain_lock.h | 39 + SecurityTool/keychain_recode.c | 151 + SecurityTool/keychain_recode.h | 39 + SecurityTool/keychain_set_settings.c | 269 + SecurityTool/keychain_set_settings.h | 40 + SecurityTool/keychain_show_info.c | 99 + SecurityTool/keychain_show_info.h | 39 + SecurityTool/keychain_unlock.c | 131 + SecurityTool/keychain_unlock.h | 39 + SecurityTool/keychain_utilities.c | 961 ++ SecurityTool/keychain_utilities.h | 67 + SecurityTool/leaks.c | 110 + SecurityTool/leaks.h | 39 + SecurityTool/mds_install.cpp | 50 + SecurityTool/mds_install.h | 39 + SecurityTool/readline.c | 150 + SecurityTool/readline.h | 49 + SecurityTool/security.1 | 1418 ++ SecurityTool/security.c | 967 ++ SecurityTool/security.h | 49 + SecurityTool/security_tool_commands.c | 43 + SecurityTool/srCdsaUtils.cpp | 525 + SecurityTool/srCdsaUtils.h | 131 + SecurityTool/sub_commands.h | 29 + SecurityTool/trust_settings_impexp.c | 139 + SecurityTool/trust_settings_impexp.h | 40 + SecurityTool/trusted_cert_add.c | 626 + SecurityTool/trusted_cert_add.h | 40 + SecurityTool/trusted_cert_dump.c | 265 + SecurityTool/trusted_cert_dump.h | 39 + SecurityTool/trusted_cert_utils.c | 446 + SecurityTool/trusted_cert_utils.h | 74 + SecurityTool/user_trust_enable.cpp | 114 + SecurityTool/user_trust_enable.h | 39 + SecurityTool/verify_cert.c | 328 + SecurityTool/verify_cert.h | 39 + .../Base.lproj/Main_iPad.storyboard | 30 + .../Base.lproj/Main_iPhone.storyboard | 30 + .../RemoteCFUserNotificationTest-Info.plist | 56 + .../RemoteCFUserNotificationTest-Prefix.pch | 10 + .../SWCAppDelegate.h | 14 + .../SWCAppDelegate.m | 48 + .../SWCViewController.h | 13 + .../SWCViewController.m | 428 + .../SharedWebCredentialViewService-Info.plist | 55 + .../SharedWebCredentialViewService-Prefix.pch | 10 + .../en.lproj/InfoPlist.strings | 2 + .../entitlements.plist | 10 + SharedWebCredentialViewService/main.m | 17 + SyncTest/KCATableViewController.xib | 160 + SyncTest/spiralsink114.png | Bin 0 -> 24752 bytes SyncTest/spiralsink57.png | Bin 0 -> 7978 bytes TODO | 265 + WHITEPAPER | 146 + asl/com.apple.securityd | 8 +- authd/Info.plist | 31 - authd/ccaudit.h | 26 - authd/connection.h | 38 - authd/credential.h | 54 - authd/debugging.c | 75 - authd/debugging.h | 41 - authd/main.c | 208 - authd/object.c | 5 - authd/process.h | 102 - authd/server.c | 1169 -- authd/server.h | 80 - authd/session.h | 60 - .../PKITrustData/AppleESCertificates.plist | Bin 0 -> 2086 bytes .../AssetData/PKITrustData/AssetVersion.plist | 8 + .../AssetData/PKITrustData/Blocked.plist | Bin 0 -> 435 bytes .../AssetData/PKITrustData/EVRoots.plist | Bin 0 -> 3448 bytes .../PKITrustData/GrayListedKeys.plist | Bin 0 -> 381 bytes .../AssetData/PKITrustData/certsIndex.data | Bin 0 -> 5352 bytes .../AssetData/PKITrustData/certsTable.data | Bin 0 -> 242192 bytes .../AssetData/PKITrustData/manifest.data | Bin 0 -> 495 bytes .../SecurityCertificatesAssets/Info.plist | 25 + .../BuildOSXRootKeychain/X509Anchors | Bin 0 -> 282984 bytes .../BuildOSXRootKeychain/buildRootKeychain.rb | 628 + .../BuildOSXRootKeychain/certsha1hashtmp | Bin 0 -> 100 bytes .../BuildOSXRootKeychain/evroot.config | 462 + .../BuildiOSAsset/BuildAsset.rb | 222 + .../BuildiOSAsset/BuildPListFiles.rb | 63 + .../CertificateTool.xcodeproj/project.pbxproj | 653 + .../contents.xcworkspacedata | 7 + .../AppleBaselineEscrowCertificates.h | 1 + .../CertificateTool/AssetVersion.plist | 8 + .../CertificateTool-Prefix.pch | 7 + .../CertificateTool/CertificateToolApp.h | 59 + .../CertificateTool/CertificateToolApp.m | 795 ++ .../CertificateTool/DataConversion.h | 53 + .../CertificateTool/DataConversion.m | 103 + .../CertificateTool/Info.plist | 25 + .../CertificateTool/PSAssetConstants.c | 19 + .../CertificateTool/PSAssetConstants.h | 33 + .../CertificateTool/CertificateTool/PSCert.h | 30 + .../CertificateTool/CertificateTool/PSCert.m | 204 + .../CertificateTool/PSCertData.h | 25 + .../CertificateTool/PSCertData.m | 144 + .../CertificateTool/PSCertKey.h | 21 + .../CertificateTool/PSCertKey.m | 45 + .../CertificateTool/PSCertRecord.h | 20 + .../CertificateTool/PSCertRecord.m | 54 + .../CertificateTool/CertificateTool/PSCerts.h | 22 + .../CertificateTool/CertificateTool/PSCerts.m | 81 + .../CertificateTool/PSUtilities.h | 28 + .../CertificateTool/PSUtilities.m | 382 + .../CertificateTool/ValidateAsset.c | 409 + .../CertificateTool/ValidateAsset.h | 14 + .../CertificateTool/CertificateTool/main.m | 78 + certificates/EVRoots/evroot.config | 462 + certificates/assetData/Info.plist | 27 + certificates/certs/AppleDEVID.cer | Bin 0 -> 1032 bytes certificates/certs/DODCA_13.cer | Bin 0 -> 1080 bytes certificates/certs/DODCA_14.cer | Bin 0 -> 1080 bytes certificates/certs/DODCA_15.cer | Bin 0 -> 1072 bytes certificates/certs/DODCA_16.cer | Bin 0 -> 1072 bytes certificates/certs/DODCA_17.cer | Bin 0 -> 1072 bytes certificates/certs/DODCA_18.cer | Bin 0 -> 1072 bytes certificates/certs/DODCA_19.cer | Bin 0 -> 1348 bytes certificates/certs/DODCA_20.cer | Bin 0 -> 1348 bytes certificates/certs/DODCA_25.der | Bin 0 -> 1421 bytes certificates/certs/DODCA_26.der | Bin 0 -> 1421 bytes certificates/certs/DODCA_27.cer | Bin 0 -> 1360 bytes certificates/certs/DODCA_28.cer | Bin 0 -> 1360 bytes certificates/certs/DODCA_29.cer | Bin 0 -> 1360 bytes certificates/certs/DODCA_30.cer | Bin 0 -> 1360 bytes certificates/certs/DODEMAILCA_13.cer | Bin 0 -> 1086 bytes certificates/certs/DODEMAILCA_14.cer | Bin 0 -> 1086 bytes certificates/certs/DODEMAILCA_15.cer | Bin 0 -> 1078 bytes certificates/certs/DODEMAILCA_16.cer | Bin 0 -> 1078 bytes certificates/certs/DODEMAILCA_17.cer | Bin 0 -> 1078 bytes certificates/certs/DODEMAILCA_18.cer | Bin 0 -> 1078 bytes certificates/certs/DODEMAILCA_19.cer | Bin 0 -> 1354 bytes certificates/certs/DODEMAILCA_20.cer | Bin 0 -> 1354 bytes certificates/certs/DODEMAILCA_21.cer | Bin 0 -> 1427 bytes certificates/certs/DODEMAILCA_22.cer | Bin 0 -> 1427 bytes certificates/certs/DODEMAILCA_23.cer | Bin 0 -> 1427 bytes certificates/certs/DODEMAILCA_24.cer | Bin 0 -> 1427 bytes certificates/certs/DODEMAILCA_25.der | Bin 0 -> 1427 bytes certificates/certs/DODEMAILCA_26.der | Bin 0 -> 1427 bytes certificates/certs/DODEMAILCA_27.cer | Bin 0 -> 1366 bytes certificates/certs/DODEMAILCA_28.cer | Bin 0 -> 1366 bytes certificates/certs/DODEMAILCA_29.cer | Bin 0 -> 1366 bytes certificates/certs/DODEMAILCA_30.cer | Bin 0 -> 1366 bytes certificates/certs/DODINTERMEDIATECA-2.cer | Bin 0 -> 1360 bytes certificates/certs/DODINTERMEDIATECA_1.cer | Bin 0 -> 1360 bytes certificates/certs/DOD_CA-11.cer | Bin 0 -> 1080 bytes certificates/certs/DOD_CA-12.cer | Bin 0 -> 1080 bytes certificates/certs/DOD_CLASS_3_CA-10.cer | Bin 0 -> 1050 bytes certificates/certs/DOD_CLASS_3_CA-5.cer | Bin 0 -> 1049 bytes certificates/certs/DOD_CLASS_3_CA-6.cer | Bin 0 -> 1049 bytes certificates/certs/DOD_CLASS_3_CA-7.cer | Bin 0 -> 1049 bytes certificates/certs/DOD_CLASS_3_CA-8.cer | Bin 0 -> 1049 bytes certificates/certs/DOD_CLASS_3_CA-9.cer | Bin 0 -> 1049 bytes .../certs/DOD_CLASS_3_EMAIL_CA-10.cer | Bin 0 -> 1056 bytes certificates/certs/DOD_CLASS_3_EMAIL_CA-5.cer | Bin 0 -> 1055 bytes certificates/certs/DOD_CLASS_3_EMAIL_CA-6.cer | Bin 0 -> 1055 bytes certificates/certs/DOD_CLASS_3_EMAIL_CA-7.cer | Bin 0 -> 1055 bytes certificates/certs/DOD_CLASS_3_EMAIL_CA-8.cer | Bin 0 -> 1055 bytes certificates/certs/DOD_CLASS_3_EMAIL_CA-9.cer | Bin 0 -> 1055 bytes certificates/certs/DOD_EMAIL_CA-11.cer | Bin 0 -> 1086 bytes certificates/certs/DOD_EMAIL_CA-12.cer | Bin 0 -> 1086 bytes certificates/certs/DoDCA21.cer | Bin 0 -> 1421 bytes certificates/certs/DoDCA22.cer | Bin 0 -> 1421 bytes certificates/certs/DoDCA23.cer | Bin 0 -> 1421 bytes certificates/certs/DoDCA24.cer | Bin 0 -> 1421 bytes .../certs/GeoTrust_True_Credentials_CA_2.cer | Bin 0 -> 699 bytes certificates/certs/IDENTRUSTECA1.cer | Bin 0 -> 1069 bytes certificates/certs/IDENTRUSTECA2.cer | Bin 0 -> 1434 bytes certificates/certs/IDENTRUSTECA3.cer | Bin 0 -> 1399 bytes certificates/certs/ORCECA2.cer | Bin 0 -> 1037 bytes .../certs/ORCECAFOREIGNNATIONALSCA1.cer | Bin 0 -> 1059 bytes certificates/certs/ORCECAHW3.cer | Bin 0 -> 1431 bytes certificates/certs/ORCECAHW4.cer | Bin 0 -> 1396 bytes certificates/certs/ORCECASW3.cer | Bin 0 -> 1431 bytes certificates/certs/ORCECASW4.cer | Bin 0 -> 1396 bytes certificates/certs/ORC_ECA.cer | Bin 0 -> 1074 bytes certificates/certs/Thawte_Code_Signing_CA.cer | Bin 0 -> 850 bytes certificates/certs/Thawte_SGC_CA.der.cer | Bin 0 -> 807 bytes .../certs/Thawte_SSL_Domain_CA_der.cer | Bin 0 -> 823 bytes certificates/certs/VERISIGNCLIENTECA-G2.cer | Bin 0 -> 1520 bytes ...LIENTEXTERNALCERTIFICATIONAUTHORITY_G3.cer | Bin 0 -> 1481 bytes ...gnClientExternalCertificationAuthority.cer | Bin 0 -> 1176 bytes certificates/certs/VeriSign_TSA_CA.crt | Bin 0 -> 977 bytes certificates/certs/VisaNet.crt | Bin 0 -> 1096 bytes certificates/certs/acClasse0_0.cer | Bin 0 -> 711 bytes certificates/certs/acClasse0_1.cer | Bin 0 -> 783 bytes certificates/certs/acClasse1_0.cer | Bin 0 -> 782 bytes certificates/certs/acClasse1_1.cer | Bin 0 -> 711 bytes certificates/certs/acClasse2_0.cer | Bin 0 -> 782 bytes certificates/certs/acClasse2_1.cer | Bin 0 -> 712 bytes certificates/certs/acClasse3_0.cer | Bin 0 -> 783 bytes certificates/certs/acClasse3_1.cer | Bin 0 -> 711 bytes certificates/certs/acClasse4.cer | Bin 0 -> 794 bytes certificates/certs/acClasse5.cer | Bin 0 -> 774 bytes certificates/certs/acCps2_2.cer | Bin 0 -> 685 bytes certificates/certs/belgiumrs.crt | Bin 0 -> 1023 bytes certificates/certs/e-Visa.crt | Bin 0 -> 1097 bytes certificates/certs/gipCps0.cer | Bin 0 -> 690 bytes .../DigiNotar Extended Validation CA.cer | Bin 0 -> 1542 bytes ...iNotar PKIoverheid CA Organisatie - G2.cer | Bin 0 -> 1696 bytes .../distrusted/DigiNotar Qualified CA.cer | Bin 0 -> 1541 bytes .../distrusted/DigiNotar Services 1024 CA.cer | Bin 0 -> 1403 bytes .../distrusted/DigiNotar Services CA.cer | Bin 0 -> 1541 bytes .../distrusted/DigiNotarRootCA2007.crt | Bin 0 -> 1422 bytes certificates/distrusted/DigiNotarRootCAG2.cer | Bin 0 -> 1428 bytes .../distrusted/DigiNotar_PKIoverheid_CA.cer | Bin 0 -> 1164 bytes certificates/distrusted/EASEE-gas CA.cer | Bin 0 -> 1497 bytes ... van Advocaten - Dutch Bar Association.cer | Bin 0 -> 1560 bytes certificates/distrusted/TRIALOrgCA.cer | Bin 0 -> 1605 bytes ...tar_PKIoverheid_Organisatie_TEST_CA_G2.cer | Bin 0 -> 1734 bytes certificates/distrusted/TU Delft CA.cer | Bin 0 -> 1517 bytes .../BuildAsset/BuildAsset-Prefix.pch | 7 + .../ota_cert_tool/BuildAsset/BuildAsset.1 | 79 + certificates/ota_cert_tool/BuildAsset/main.m | 14 + .../ota_cert_tool/Scripts/BuildAsset.rb | 39 + .../ota_cert_tool/Scripts/BuildPlistFiles.rb | 35 + certificates/ota_cert_tool/Scripts/File.rb | 141 + .../SecuritydAssertHelper/Readme.txt | 0 .../SecuritydAssertHelper.1 | 79 + .../SecuritydAssertHelper.m | 39 + .../ota_cert_tool/TestValidator/Readme.txt | 0 .../TestValidator/Resources/EVRoots.plist | 309 + .../TestValidator/Resources/Manifest.plist | 20 + .../TestValidator/Resources/certs.plist | 97 + .../TestValidator/Resources/distrusted.plist | 22 + .../TestValidator/Resources/revoked.plist | 18 + .../TestValidator/Resources/roots.plist | 193 + .../TestValidator/TestValidator.1 | 79 + .../TestValidator/TestValidator.m | 30 + .../assertValidation-Prefix.pch | 7 + .../project.pbxproj | 904 ++ .../contents.xcworkspacedata | 7 + .../ios_ota_cert_tool/CommonBaseXX.c | 9 + .../ios_ota_cert_tool/CommonBaseXX.h | 273 + .../ios_ota_cert_tool/CommonBuffering.c | 114 + .../ios_ota_cert_tool/CommonBufferingPriv.h | 63 + .../ios_ota_cert_tool/Info.plist | 27 + .../ota_cert_tool/ios_ota_cert_tool/PSCert.h | 22 + .../ota_cert_tool/ios_ota_cert_tool/PSCert.m | 37 + .../ios_ota_cert_tool/PSCertKey.h | 21 + .../ios_ota_cert_tool/PSCertKey.m | 47 + .../ota_cert_tool/ios_ota_cert_tool/PSCerts.h | 23 + .../ota_cert_tool/ios_ota_cert_tool/PSCerts.m | 86 + .../ios_ota_cert_tool/PSIOSCertToolApp.h | 51 + .../ios_ota_cert_tool/PSIOSCertToolApp.m | 503 + .../ios_ota_cert_tool/PSUtilities.h | 28 + .../ios_ota_cert_tool/PSUtilities.m | 333 + .../ios_ota_cert_tool/ValidateAsset.c | 508 + .../ios_ota_cert_tool/ValidateAsset.h | 16 + .../ios_ota_cert_tool/ccMemory.h | 71 + .../ios_ota_cert_tool-Prefix.pch | 7 + .../ios_ota_cert_tool/ios_ota_cert_tool.1 | 79 + .../ota_cert_tool/ios_ota_cert_tool/main.m | 71 + certificates/removed/AOLTimeWarner1.der | Bin 0 -> 1002 bytes certificates/removed/AOLTimeWarner2.der | Bin 0 -> 1514 bytes certificates/removed/EntrustRootCA1024.crt | Bin 0 -> 1244 bytes .../removed/Equifax_Secure_eBusiness_CA-2.cer | Bin 0 -> 804 bytes .../removed/JCSSecureSignRootCA11.cer | Bin 0 -> 881 bytes certificates/removed/ValiCertClass1PVA.cer | Bin 0 -> 747 bytes certificates/removed/ValiCertClass2PVA.cer | Bin 0 -> 747 bytes certificates/removed/ValiCertClass3PVA.cer | Bin 0 -> 747 bytes certificates/removed/persbasi.crt | Bin 0 -> 805 bytes certificates/removed/persprem.crt | Bin 0 -> 813 bytes certificates/revoked/*.EGO.GOV.TR.cer | Bin 0 -> 1345 bytes certificates/revoked/*.google.com.cer | Bin 0 -> 1459 bytes certificates/revoked/*.mail.me.com.cer | Bin 0 -> 1314 bytes .../revoked/DigiNotar Public CA 2025.cer | Bin 0 -> 1543 bytes certificates/revoked/DigiNotar092006.cer | Bin 0 -> 1340 bytes certificates/revoked/DigiNotar092706.cer | Bin 0 -> 1340 bytes certificates/revoked/DigiNotar100406.cer | Bin 0 -> 1374 bytes certificates/revoked/DigiNotarRootCA1.cer | Bin 0 -> 1356 bytes certificates/revoked/DigiNotarRootCA2.cer | Bin 0 -> 1356 bytes .../revoked/DigiNotarServices1024CA.cer | Bin 0 -> 977 bytes ...Digisign-Server-ID-Enrich-Entrust-Cert.cer | Bin 0 -> 1234 bytes ...igisign-Server-ID-Enrich-GTETrust-Cert.cer | Bin 0 -> 975 bytes certificates/revoked/Micros CA 2.cer | Bin 0 -> 1095 bytes ...ave Organization Issuing CA, Level 2 2.cer | Bin 0 -> 1190 bytes .../revoked/e-islem.kktcmerkezbankasi.org.cer | Bin 0 -> 1012 bytes certificates/roots/00_BCA.cer | Bin 0 -> 1134 bytes certificates/roots/2048CA.cer | Bin 0 -> 1120 bytes certificates/roots/A-Trust-Qual-01.cer | Bin 0 -> 1111 bytes certificates/roots/A-Trust-Qual-02a.crt | Bin 0 -> 975 bytes certificates/roots/A-Trust-nQual-01.cer | Bin 0 -> 865 bytes certificates/roots/A-Trust-nQual-03.cer | Bin 0 -> 979 bytes certificates/roots/APCAroot.der | Bin 0 -> 932 bytes .../roots/Actalis Authentication Root CA.cer | Bin 0 -> 1471 bytes .../roots/AddTrust Class 1 CA Root.crt | Bin 0 -> 1052 bytes .../roots/AddTrust External CA Root.crt | Bin 0 -> 1082 bytes .../roots/AddTrust Public CA Root.crt | Bin 0 -> 1049 bytes .../roots/AddTrust Qualified CA Root.crt | Bin 0 -> 1058 bytes certificates/roots/AffirmTrust-Commercial.der | Bin 0 -> 848 bytes certificates/roots/AffirmTrust-Networking.der | Bin 0 -> 848 bytes .../roots/AffirmTrust-Premium-ECC.der | Bin 0 -> 514 bytes certificates/roots/AffirmTrust-Premium.der | Bin 0 -> 1354 bytes certificates/roots/AmericaOnline1.der | Bin 0 -> 936 bytes certificates/roots/AmericaOnline2.der | Bin 0 -> 1448 bytes certificates/roots/AppCAG2.cer | Bin 0 -> 932 bytes certificates/roots/Apple Root CA - G2.cer | Bin 0 -> 1430 bytes certificates/roots/Apple Root CA - G3.cer | Bin 0 -> 583 bytes certificates/roots/AppleDEVID.cer | Bin 0 -> 1032 bytes certificates/roots/AppleIncRoot042506.cer | Bin 0 -> 1215 bytes certificates/roots/AppleROOTCA.der | Bin 0 -> 1470 bytes ...rtificacion Raiz del Estado Venezolano.cer | Bin 0 -> 2463 bytes certificates/roots/BIT-Admin-Root-CA.crt | Bin 0 -> 1369 bytes certificates/roots/BIT-AdminCA-CD-T01.crt | Bin 0 -> 1105 bytes certificates/roots/BTCTRT.cer | Bin 0 -> 891 bytes .../roots/Buypass Class 2 Root CA.cer | Bin 0 -> 1373 bytes .../roots/Buypass Class 3 Root CA.cer | Bin 0 -> 1373 bytes certificates/roots/BuypassClass2CA1.cer | Bin 0 -> 855 bytes certificates/roots/BuypassClass3CA1.cer | Bin 0 -> 855 bytes certificates/roots/C1_PCA_G3v2.509 | Bin 0 -> 1054 bytes certificates/roots/C2_PCA_G3v2.509 | Bin 0 -> 1053 bytes certificates/roots/C3_PCA_G3v2.509 | Bin 0 -> 1054 bytes certificates/roots/C4_PCA_G3v2.509 | Bin 0 -> 1054 bytes certificates/roots/CA Disig Root R1.cer | Bin 0 -> 1389 bytes certificates/roots/CA Disig Root R2.cer | Bin 0 -> 1389 bytes certificates/roots/CNNICEVRoot.der | Bin 0 -> 1019 bytes .../roots/COMODOCertificationAuthority.crt | Bin 0 -> 1057 bytes certificates/roots/Certigna.cer | Bin 0 -> 940 bytes certificates/roots/Certinomis - Root CA.cer | Bin 0 -> 1430 bytes certificates/roots/Certinomis-May2013.der | Bin 0 -> 1440 bytes .../roots/Certum Trusted Network CA 2.cer | Bin 0 -> 1495 bytes certificates/roots/Chunghwa-ROOTeCA.der | Bin 0 -> 1460 bytes certificates/roots/Class1_PCA_G2_v2.509 | Bin 0 -> 774 bytes certificates/roots/Class2_PCA_G2_v2.509 | Bin 0 -> 775 bytes certificates/roots/Class3_PCA_G2_v2.509 | Bin 0 -> 774 bytes certificates/roots/Class4_PCA_G2_v2.509 | Bin 0 -> 774 bytes certificates/roots/ComSign-CA.der | Bin 0 -> 919 bytes certificates/roots/ComSign-Global.der | Bin 0 -> 1541 bytes certificates/roots/ComSign-Secured.der | Bin 0 -> 943 bytes .../roots/Comodo_AAA_Certificate_Services.cer | Bin 0 -> 1078 bytes .../Comodo_Secure_Certificate_Services.cer | Bin 0 -> 1091 bytes .../Comodo_Trusted_Certificate_Services.cer | Bin 0 -> 1095 bytes .../roots/D-TRUST_Root_Class_3_CA_2_2009.cer | Bin 0 -> 1079 bytes .../D-TRUST_Root_Class_3_CA_2_EV_2009.cer | Bin 0 -> 1095 bytes certificates/roots/DST Root CA X4.cer | Bin 0 -> 831 bytes .../roots/Deutsche_Telekom_Root_CA_2.der | Bin 0 -> 931 bytes .../roots/DigiCertAssuredIDRootCA.crt | Bin 0 -> 955 bytes .../roots/DigiCertAssuredIDRootG2.der | Bin 0 -> 922 bytes .../roots/DigiCertAssuredIDRootG3.der | Bin 0 -> 586 bytes certificates/roots/DigiCertGlobalRootCA.crt | Bin 0 -> 947 bytes certificates/roots/DigiCertGlobalRootG2.der | Bin 0 -> 914 bytes certificates/roots/DigiCertGlobalRootG3.der | Bin 0 -> 579 bytes .../roots/DigiCertHighAssuranceEVRootCA.crt | Bin 0 -> 969 bytes certificates/roots/DigiCertTrustedRootG4.der | Bin 0 -> 1428 bytes certificates/roots/DoDCLASS3RootCA.cer | Bin 0 -> 619 bytes certificates/roots/DoDRootCA2.der | Bin 0 -> 884 bytes certificates/roots/E-Tugra.der | Bin 0 -> 1615 bytes certificates/roots/EBG_KOKSM.cer | Bin 0 -> 1515 bytes certificates/roots/ECARootCA.der | Bin 0 -> 668 bytes certificates/roots/EchoworxRootCA2.cer | Bin 0 -> 1259 bytes certificates/roots/EntrustEVRoot.crt | Bin 0 -> 1173 bytes certificates/roots/EntrustRoot-EC1.der | Bin 0 -> 765 bytes certificates/roots/EntrustRoot-G2.der | Bin 0 -> 1090 bytes .../roots/Equifax_Secure_Certificate_Auth | Bin 0 -> 804 bytes .../roots/Equifax_Secure_Global_eBusiness | Bin 0 -> 660 bytes .../roots/Equifax_Secure_eBusiness_CA-1.cer | Bin 0 -> 646 bytes certificates/roots/Estonia-Juur-SK.cer | Bin 0 -> 1258 bytes certificates/roots/FBCA-commonpolicy2.cer | Bin 0 -> 933 bytes certificates/roots/FederalCommonPolicyCA.cer | Bin 0 -> 1124 bytes .../roots/Firmaprofesional-CIF-A62634068.der | Bin 0 -> 1560 bytes certificates/roots/GD-Class2-root.crt | Bin 0 -> 1028 bytes certificates/roots/GTEGB18.cer | Bin 0 -> 606 bytes ...t Primary Certification Authority - G2.cer | Bin 0 -> 690 bytes ...t Primary Certification Authority - G3.cer | Bin 0 -> 1026 bytes certificates/roots/GeoTrust_Global_CA.cer | Bin 0 -> 856 bytes certificates/roots/GlobalSign-Root-R3.der | Bin 0 -> 867 bytes .../roots/GlobalSign-RootCA-2028exp.cer | Bin 0 -> 889 bytes certificates/roots/GlobalSignRoot-R4.cer | Bin 0 -> 485 bytes certificates/roots/GlobalSignRoot-R5.cer | Bin 0 -> 546 bytes certificates/roots/GlobalSignRootCA-R2.cer | Bin 0 -> 958 bytes .../GoDaddyRootCertificateAuthorityG2.der | Bin 0 -> 969 bytes .../roots/HKPost-smartid_rt.cacert.crt | Bin 0 -> 820 bytes certificates/roots/HaricaRootCA2011.der | Bin 0 -> 1077 bytes certificates/roots/ICA-20090901.der | Bin 0 -> 1314 bytes certificates/roots/IdenTrust_Root_X3.der | Bin 0 -> 846 bytes certificates/roots/IdenTrust_Root_X6.der | Bin 0 -> 1037 bytes certificates/roots/Izenpe-RAIZ2007.crt | Bin 0 -> 1524 bytes certificates/roots/Izenpe-ca_raiz2003.crt | Bin 0 -> 1123 bytes certificates/roots/Izenpe.com.cer | Bin 0 -> 1525 bytes .../roots/JapanMinistryIAC-ApplicationCA2.der | Bin 0 -> 1019 bytes certificates/roots/KIR-SZAFIR-Trusted.der | Bin 0 -> 885 bytes certificates/roots/KMD-CA-KPerson.crt | Bin 0 -> 890 bytes certificates/roots/KMD-CA-Server.crt | Bin 0 -> 862 bytes certificates/roots/MPHPT_CA.cer | Bin 0 -> 952 bytes .../roots/Microsec e-Szigno Root CA 2009.cer | Bin 0 -> 1038 bytes certificates/roots/NetLockAranyClassGoldF.cer | Bin 0 -> 1049 bytes certificates/roots/NetworkSolutionsEVRoot.crt | Bin 0 -> 1002 bytes certificates/roots/PCA1ss_v4.509 | Bin 0 -> 577 bytes certificates/roots/PCA2ss_v4.509 | Bin 0 -> 576 bytes certificates/roots/PCA3ss_v4.509 | Bin 0 -> 576 bytes certificates/roots/Poland-Certum-CTNCA.der | Bin 0 -> 959 bytes certificates/roots/ROOT-CHAMBERS.crt | Bin 0 -> 1217 bytes certificates/roots/ROOT-CHAMBERSIGN.crt | Bin 0 -> 1225 bytes certificates/roots/RSA_Root_CA.der | Bin 0 -> 869 bytes certificates/roots/SCRoot1ca.cer | Bin 0 -> 862 bytes certificates/roots/SECOM-EVRoot1ca.cer | Bin 0 -> 897 bytes certificates/roots/SECOM-RootCA2.cer | Bin 0 -> 891 bytes certificates/roots/SF-Class2-root.crt | Bin 0 -> 1043 bytes .../SKEE_Certification_Centre_Root_CA.crt | Bin 0 -> 1031 bytes certificates/roots/SoneraClass1.crt | Bin 0 -> 804 bytes certificates/roots/SoneraClass2.crt | Bin 0 -> 804 bytes .../Staat der Nederlanden EV Root CA.cer | Bin 0 -> 1396 bytes .../StarfieldRootCertificateAuthorityG2.der | Bin 0 -> 993 bytes ...ieldServicesRootCertificateAuthorityG2.der | Bin 0 -> 1011 bytes certificates/roots/StartCom May 2013 G2.der | Bin 0 -> 1383 bytes certificates/roots/SwissSign-Gold_G2.der | Bin 0 -> 1470 bytes certificates/roots/SwissSign-Platinum_G2.der | Bin 0 -> 1477 bytes certificates/roots/SwissSign-Silver_G2.der | Bin 0 -> 1473 bytes certificates/roots/Swisscom Root CA 2.cer | Bin 0 -> 1501 bytes certificates/roots/Swisscom Root EV CA 2.cer | Bin 0 -> 1508 bytes ...c Primary Certification Authority - G4.cer | Bin 0 -> 684 bytes ...c Primary Certification Authority - G6.cer | Bin 0 -> 1018 bytes ...c Primary Certification Authority - G4.cer | Bin 0 -> 684 bytes ...c Primary Certification Authority - G6.cer | Bin 0 -> 1018 bytes ...c Primary Certification Authority - G4.cer | Bin 0 -> 683 bytes ...c Primary Certification Authority - G6.cer | Bin 0 -> 1530 bytes .../roots/T-TeleSec GlobalRoot Class 2.cer | Bin 0 -> 967 bytes .../roots/T-TeleSec GlobalRoot Class 3.cer | Bin 0 -> 967 bytes certificates/roots/TDC_ocesca.cer | Bin 0 -> 1309 bytes certificates/roots/TDC_rootca.cer | Bin 0 -> 1071 bytes .../roots/TRUST2408 OCES Primary CA.cer | Bin 0 -> 1568 bytes certificates/roots/TWCARootCA-4096.der | Bin 0 -> 1349 bytes certificates/roots/Taiwan-GRCA2.der | Bin 0 -> 1359 bytes certificates/roots/TeliaSoneraRootCAv1.der | Bin 0 -> 1340 bytes .../roots/Thawte_Personal_Basic_CA.cer | Bin 0 -> 820 bytes .../roots/Thawte_Personal_Freemail_CA.cer | Bin 0 -> 832 bytes .../roots/Thawte_Personal_Premium_CA.cer | Bin 0 -> 828 bytes .../roots/Thawte_Premium_Server_CA.cer | Bin 0 -> 826 bytes certificates/roots/Thawte_Server_CA.cer | Bin 0 -> 806 bytes certificates/roots/Thawte_Timestamping_CA.cer | Bin 0 -> 692 bytes certificates/roots/TrustisFPSRootCA.der | Bin 0 -> 875 bytes certificates/roots/Trustwave-SGCA.der | Bin 0 -> 960 bytes certificates/roots/Trustwave-STCA.der | Bin 0 -> 956 bytes certificates/roots/TubitakSurum3.cer | Bin 0 -> 1307 bytes certificates/roots/UCAGlobalRoot.cer | Bin 0 -> 1430 bytes certificates/roots/UCARoot.cer | Bin 0 -> 904 bytes .../UTN-USERFirst-ClientAuthentication.der | Bin 0 -> 1190 bytes certificates/roots/UTN-USERFirst-Hardware.crt | Bin 0 -> 1144 bytes .../UTN-USERFirst-NetworkApplication.der | Bin 0 -> 1128 bytes certificates/roots/UTN-USERFirst-Object.crt | Bin 0 -> 1130 bytes certificates/roots/UTN_DATACorp_SGC.cer | Bin 0 -> 1122 bytes certificates/roots/Unizeto-CertumCA.cer | Bin 0 -> 784 bytes .../roots/VASLatvijasPasts-SSI-RCA.crt | Bin 0 -> 1965 bytes ...c Primary Certification Authority - G4.cer | Bin 0 -> 904 bytes ...Universal Root Certification Authority.cer | Bin 0 -> 1213 bytes .../roots/VeriSignC3PublicPrimaryCA-G5.cer | Bin 0 -> 1239 bytes .../roots/VerisignSHA1_1024_PCA1_G1.cer | Bin 0 -> 576 bytes .../roots/VerisignSHA1_1024_PCA2_G1.cer | Bin 0 -> 576 bytes .../roots/VerisignSHA1_1024_PCA3_G1.cer | Bin 0 -> 576 bytes .../Visa Information Delivery Root CA.cer | Bin 0 -> 1021 bytes certificates/roots/Visa eCommerce Root.cer | Bin 0 -> 934 bytes certificates/roots/WISeKey-owgrgaca.cer | Bin 0 -> 1013 bytes certificates/roots/WellsSecurePRCA.der | Bin 0 -> 1217 bytes certificates/roots/XGCA.crt | Bin 0 -> 1076 bytes certificates/roots/ac-racine.der | Bin 0 -> 887 bytes .../roots/ac_offline_raiz_certicamara.crt | Bin 0 -> 1642 bytes certificates/roots/belgiumrca.crt | Bin 0 -> 920 bytes certificates/roots/belgiumrca2.crt | Bin 0 -> 914 bytes certificates/roots/certSIGN ROOT CA.cer | Bin 0 -> 828 bytes certificates/roots/certplus_class2.der | Bin 0 -> 918 bytes certificates/roots/cisco-ca2048.der | Bin 0 -> 839 bytes certificates/roots/cnnicroot.cer | Bin 0 -> 857 bytes certificates/roots/disig-root-1.der | Bin 0 -> 1043 bytes certificates/roots/entrust2048.der | Bin 0 -> 1070 bytes certificates/roots/expressz.cer | Bin 0 -> 1363 bytes certificates/roots/geotrust-primary-ca.crt | Bin 0 -> 896 bytes certificates/roots/globalSignRoot.cer | Bin 0 -> 889 bytes certificates/roots/kisa-root-rsa-3280.der | Bin 0 -> 887 bytes certificates/roots/kisa-root-wrsa.der | Bin 0 -> 1366 bytes certificates/roots/kozjegyzoi.cer | Bin 0 -> 1665 bytes .../roots/netlockQA-01-minositett.cer | Bin 0 -> 1749 bytes certificates/roots/persfree.crt | Bin 0 -> 817 bytes certificates/roots/popFinnVrkrootc.der | Bin 0 -> 1054 bytes certificates/roots/qvrca.crt | Bin 0 -> 1492 bytes certificates/roots/qvrca2.crt | Bin 0 -> 1467 bytes certificates/roots/qvrca3.crt | Bin 0 -> 1697 bytes certificates/roots/root_chambers-2008.der | Bin 0 -> 1875 bytes certificates/roots/root_chambersign-2008.der | Bin 0 -> 1869 bytes certificates/roots/serverbasic.crt | Bin 0 -> 791 bytes certificates/roots/serverpremium.crt | Bin 0 -> 811 bytes .../roots/staatDerNederlandenRootCA-G2.crt | Bin 0 -> 1486 bytes .../roots/staatdernederlandenrootca.cer | Bin 0 -> 958 bytes certificates/roots/startcom-sfsca.der | Bin 0 -> 1997 bytes certificates/roots/startcomSHA2.der | Bin 0 -> 1931 bytes certificates/roots/swisscom-sdcs-root.crt | Bin 0 -> 1501 bytes certificates/roots/swisssign.der | Bin 0 -> 953 bytes certificates/roots/tc_Universal_CA-I.cer | Bin 0 -> 993 bytes certificates/roots/tc_Universal_CA-II.cer | Bin 0 -> 1507 bytes certificates/roots/tc_class_2_ii.cer | Bin 0 -> 1198 bytes certificates/roots/tc_class_3_ii.cer | Bin 0 -> 1198 bytes certificates/roots/tc_class_4_ii.cer | Bin 0 -> 954 bytes .../roots/thawte Primary Root CA - G3.cer | Bin 0 -> 1070 bytes certificates/roots/thawte-primary-root-ca.crt | Bin 0 -> 1060 bytes .../roots/thawte_Primary_Root_CA_G2_ECC.cer | Bin 0 -> 652 bytes certificates/roots/trustCenter-root-5.der | Bin 0 -> 997 bytes certificates/roots/turktrust-root1.cer | Bin 0 -> 1023 bytes certificates/roots/turktrust-root2.cer | Bin 0 -> 1088 bytes certificates/roots/turktrust-root3.cer | Bin 0 -> 1089 bytes certificates/roots/twca-root-1.der | Bin 0 -> 895 bytes certificates/roots/uzleti.cer | Bin 0 -> 1359 bytes codesign_wrapper/MISBase.h | 44 + codesign_wrapper/MISEntitlement.c | 100 + codesign_wrapper/MISEntitlement.h | 23 + codesign_wrapper/Makefile | 31 + codesign_wrapper/check_entitlements.c | 400 + codesign_wrapper/codesign.c | 276 + codesign_wrapper/codesign.h | 42 + codesign_wrapper/codesign_wrapper.c | 1019 ++ codesign_wrapper/codesign_wrapper.h | 87 + config/base.xcconfig | 15 - doc/C++Utilities.cwk | Bin 132909 -> 0 bytes evroots.h | 2370 ++++ .../com.apple.icloudKeychainStats.plist | 19 + iCloudStat/main.c | 260 + iCloudStats/com.apple.iCloudStats.plist | 21 - iCloudStats/iCloudStats.1 | 79 - iCloudStats/main.c | 274 - include/security_agent_client | 1 - lib/generateErrStrings.pl | 343 - libsecurity_apple_csp/lib/ascContext.h | 60 - libsecurity_apple_csp/lib/ascFactory.h | 34 - libsecurity_apple_csp/lib/boxes-ref.h | 51 - libsecurity_apple_csp/lib/pbkdDigest.cpp | 84 - libsecurity_apple_csp/lib/pbkdDigest.h | 83 - libsecurity_apple_csp/lib/pbkdf2.c | 100 - libsecurity_apple_csp/lib/pbkdf2.h | 79 - libsecurity_apple_csp/lib/rijndael-alg-ref.c | 620 - libsecurity_apple_csp/lib/rijndael-alg-ref.h | 82 - libsecurity_apple_csp/lib/rijndaelApi.c | 276 - libsecurity_apple_csp/lib/rijndaelApi.h | 119 - .../xcschemes/xcschememanagement.plist | 19 - .../xcschemes/xcschememanagement.plist | 14 - .../xcschemes/xcschememanagement.plist | 14 - .../xcschemes/xcschememanagement.plist | 19 - libsecurity_apple_x509_tp/lib/cuEnc64.c | 587 - libsecurity_apple_x509_tp/lib/cuEnc64.h | 77 - libsecurity_apple_x509_tp/lib/ocspRequest.cpp | 214 - libsecurity_apple_x509_tp/lib/ocspRequest.h | 83 - .../xcschemes/xcschememanagement.plist | 14 - libsecurity_asn1/config/base.xcconfig | 16 - libsecurity_asn1/config/lib.xcconfig | 33 - libsecurity_asn1/lib/SecNssCoder.cpp | 194 - libsecurity_asn1/lib/SecNssCoder.h | 161 - libsecurity_asn1/lib/oidsalg.c | 497 - libsecurity_asn1/lib/oidsbase.h | 356 - libsecurity_asn1/lib/pkcs12Templates.h | 284 - libsecurity_asn1/lib/pkcs7Templates.h | 165 - .../project.pbxproj | 473 - .../xcschemes/xcschememanagement.plist | 14 - .../xcschemes/xcschememanagement.plist | 14 - .../xcschemes/xcschememanagement.plist | 14 - .../xcschemes/xcschememanagement.plist | 19 - .../xcschemes/xcschememanagement.plist | 19 - libsecurity_cdsa_utils/lib/cuEnc64.c | 392 - libsecurity_cdsa_utils/lib/cuEnc64.h | 67 - .../xcschemes/xcschememanagement.plist | 14 - .../xcschemes/xcschememanagement.plist | 24 - .../xcschemes/xcschememanagement.plist | 14 - .../CodeSigningHelper/main.c | 194 - libsecurity_codesigning/lib/SecTask.c | 292 - libsecurity_codesigning/lib/SecTask.h | 103 - libsecurity_codesigning/lib/cfmdiskrep.cpp | 224 - libsecurity_codesigning/lib/cfmdiskrep.h | 112 - .../lib/opaquewhitelist.cpp | 250 - .../project.pbxproj | 2043 --- .../xcschemes/xcschememanagement.plist | 54 - .../xcschemes/xcschememanagement.plist | 14 - libsecurity_cryptkit/ckutils/badsig/badsig.c | 461 - libsecurity_cryptkit/lib/CryptKitSA.h | 23 - .../lib/NSFEEPublicKeyPrivate.h | 36 - libsecurity_cryptkit/lib/README | 221 - .../xcschemes/xcschememanagement.plist | 24 - libsecurity_cssm/lib/certextensions.h | 640 - libsecurity_cssm/lib/cssmapple.h | 1158 -- libsecurity_cssm/lib/oidsalg.c | 158 - libsecurity_cssm/lib/oidsbase.h | 497 - libsecurity_cssm/lib/transition.cpp | 519 - .../xcschemes/xcschememanagement.plist | 14 - .../xcschemes/xcschememanagement.plist | 14 - libsecurity_keychain/lib/SecBase.h | 642 - libsecurity_keychain/lib/SecBasePriv.h | 91 - libsecurity_keychain/lib/SecCertificate.h | 466 - libsecurity_keychain/lib/SecCertificatePriv.h | 254 - .../lib/SecCertificateRequest.h | 191 - libsecurity_keychain/lib/SecIdentity.h | 198 - libsecurity_keychain/lib/SecIdentityPriv.h | 152 - libsecurity_keychain/lib/SecImportExport.c | 335 - libsecurity_keychain/lib/SecImportExport.h | 675 - libsecurity_keychain/lib/SecInternal.h | 67 - libsecurity_keychain/lib/SecItem.h | 1093 -- libsecurity_keychain/lib/SecItemConstants.c | 232 - libsecurity_keychain/lib/SecItemPriv.h | 296 - libsecurity_keychain/lib/SecKey.h | 588 - libsecurity_keychain/lib/SecKeyPriv.h | 445 - libsecurity_keychain/lib/SecKeychainPriv.h | 93 - libsecurity_keychain/lib/SecPolicy.cpp | 356 - libsecurity_keychain/lib/SecPolicy.h | 408 - libsecurity_keychain/lib/SecPolicyPriv.h | 94 - libsecurity_keychain/lib/SecRandom.h | 66 - libsecurity_keychain/lib/SecTrust.h | 686 - libsecurity_keychain/lib/SecTrustPriv.h | 175 - libsecurity_keychain/lib/SecTrustSettings.h | 321 - .../lib/SecTrustSettingsPriv.h | 143 - libsecurity_keychain/lib/Security.h | 102 - .../lib/generateErrStrings.pl | 98 - .../libDER/Tests/DER_Ticket.h | 81 - .../libDER/config/base.xcconfig | 14 - .../libDER/libDER.xcodeproj/project.pbxproj | 752 - .../xcschemes/xcschememanagement.plist | 39 - .../libDER/libDER/DER_Digest.h | 74 - .../libDER/libDER/DER_Encode.h | 103 - libsecurity_keychain/libDER/libDER/DER_Keys.h | 104 - .../libDER/libDER/asn1Types.h | 91 - libsecurity_keychain/libDER/libDER/libDER.h | 65 - .../libDER/libDER/libDER_config.h | 92 - libsecurity_keychain/libDER/libDER/oids.h | 112 - .../libDER/libDERUtils/fileIo.c | 85 - .../libDER/libDERUtils/fileIo.h | 29 - .../libDER/libDERUtils/libDERUtils.c | 36 - .../libDER/libDERUtils/libDERUtils.h | 29 - .../libDER/libDERUtils/printFields.h | 57 - .../project.pbxproj | 1315 -- .../xcschemes/xcschememanagement.plist | 29 - .../regressions/si-33-keychain-backup.c | 91 - libsecurity_keychain/xpc/main.c | 422 - .../xcschemes/xcschememanagement.plist | 14 - libsecurity_mds/lib/MDSSchema.cpp | 823 -- libsecurity_mds/lib/MDSSchema.h | 107 - .../xcschemes/xcschememanagement.plist | 14 - libsecurity_ocspd/common/ocspdTypes.h | 41 - libsecurity_ocspd/common/ocspdUtils.h | 98 - .../xcschemes/xcschememanagement.plist | 19 - libsecurity_ocspd/mig/mig.mk | 45 - libsecurity_pkcs12/lib/pkcs12Templates.h | 286 - libsecurity_pkcs12/lib/pkcs12Utils.cpp | 832 -- libsecurity_pkcs12/lib/pkcs12Utils.h | 186 - libsecurity_pkcs12/lib/pkcs7Templates.h | 167 - .../xcschemes/xcschememanagement.plist | 14 - .../xcschemes/xcschememanagement.plist | 14 - libsecurity_smime/APPLE_LICENSE | 680 +- libsecurity_smime/Security | 1 + libsecurity_smime/lib/SecAsn1Item.c | 306 + libsecurity_smime/lib/SecAsn1Item.h | 117 + libsecurity_smime/lib/SecCmsBase.h | 64 +- libsecurity_smime/lib/SecCmsContentInfo.h | 33 +- libsecurity_smime/lib/SecCmsDecoder.h | 15 +- libsecurity_smime/lib/SecCmsDigestContext.h | 15 +- libsecurity_smime/lib/SecCmsDigestedData.h | 4 +- libsecurity_smime/lib/SecCmsEncoder.h | 23 +- libsecurity_smime/lib/SecCmsEncryptedData.h | 4 +- libsecurity_smime/lib/SecCmsEnvelopedData.h | 13 +- libsecurity_smime/lib/SecCmsMessage.h | 17 +- libsecurity_smime/lib/SecCmsRecipientInfo.h | 22 +- libsecurity_smime/lib/SecCmsSignedData.h | 33 +- libsecurity_smime/lib/SecCmsSignerInfo.h | 62 +- libsecurity_smime/lib/SecSMIME.h | 4 +- libsecurity_smime/lib/SecSMIMEPriv.h | 21 +- libsecurity_smime/lib/cert.c | 258 +- libsecurity_smime/lib/cert.h | 34 +- libsecurity_smime/lib/cmsarray.c | 1 + libsecurity_smime/lib/cmsasn1.c | 20 +- libsecurity_smime/lib/cmsattr.c | 29 +- libsecurity_smime/lib/cmscinfo.c | 182 +- libsecurity_smime/lib/cmscipher.c | 192 +- libsecurity_smime/lib/cmsdecode.c | 83 +- libsecurity_smime/lib/cmsdigdata.c | 28 +- libsecurity_smime/lib/cmsdigest.c | 241 +- libsecurity_smime/lib/cmsencdata.c | 27 +- libsecurity_smime/lib/cmsencode.c | 121 +- libsecurity_smime/lib/cmsenvdata.c | 48 +- libsecurity_smime/lib/cmslocal.h | 56 +- libsecurity_smime/lib/cmsmessage.c | 95 +- libsecurity_smime/lib/cmspriv.h | 106 +- libsecurity_smime/lib/cmspubkey.c | 928 +- libsecurity_smime/lib/cmsrecinfo.c | 240 +- libsecurity_smime/lib/cmsreclist.c | 15 +- libsecurity_smime/lib/cmsreclist.h | 2 +- libsecurity_smime/lib/cmssigdata.c | 515 +- libsecurity_smime/lib/cmssiginfo.c | 740 +- libsecurity_smime/lib/cmstpriv.h | 127 +- libsecurity_smime/lib/cmsutil.c | 105 +- libsecurity_smime/lib/crypto-embedded.c | 384 + libsecurity_smime/lib/cryptohi.c | 80 +- libsecurity_smime/lib/cryptohi.h | 21 +- libsecurity_smime/lib/plhash.c | 2 +- libsecurity_smime/lib/plhash.h | 4 +- libsecurity_smime/lib/secalgid.c | 10 +- libsecurity_smime/lib/secoid.c | 448 +- libsecurity_smime/lib/secoid.h | 12 +- libsecurity_smime/lib/secoidt.h | 8 +- libsecurity_smime/lib/security_smime.exp | 25 +- libsecurity_smime/lib/smimeutil.c | 93 +- .../project.pbxproj | 630 +- .../xcschemes/xcschememanagement.plist | 24 - libsecurity_smime/security_smime | 1 + libsecurity_ssl/config/base.xcconfig | 14 - libsecurity_ssl/config/lib.xcconfig | 30 - libsecurity_ssl/config/tests.xcconfig | 25 - libsecurity_ssl/lib/ModuleAttacher.c | 159 - libsecurity_ssl/lib/SSLRecordInternal.c | 706 - libsecurity_ssl/lib/SSLRecordInternal.h | 57 - libsecurity_ssl/lib/appleCdsa.c | 2147 --- libsecurity_ssl/lib/ssl3Callouts.c | 362 - libsecurity_ssl/lib/ssl3RecordCallouts.c | 440 - libsecurity_ssl/lib/sslAlertMessage.c | 412 - libsecurity_ssl/lib/sslCert.c | 788 - libsecurity_ssl/lib/sslChangeCipher.c | 121 - libsecurity_ssl/lib/sslCipherSpecs.c | 661 - libsecurity_ssl/lib/sslContext.h | 433 - libsecurity_ssl/lib/sslCrypto.c | 1269 -- libsecurity_ssl/lib/sslCrypto.h | 232 - libsecurity_ssl/lib/sslHandshake.c | 1383 -- libsecurity_ssl/lib/sslHandshakeFinish.c | 159 - libsecurity_ssl/lib/sslHandshakeHello.c | 1030 -- libsecurity_ssl/lib/sslKeyExchange.c | 1968 --- libsecurity_ssl/lib/sslKeychain.c | 489 - libsecurity_ssl/lib/sslKeychain.h | 74 - libsecurity_ssl/lib/sslRecord.c | 166 - libsecurity_ssl/lib/sslTransport.c | 603 - libsecurity_ssl/lib/tls1Callouts.c | 584 - libsecurity_ssl/lib/tls1RecordCallouts.c | 234 - libsecurity_ssl/lib/tls_record.h | 158 - .../libsecurity_ssl.xcodeproj/project.pbxproj | 1002 -- .../xcschemes/xcschememanagement.plist | 39 - libsecurity_ssl/regressions/ssl-utils.c | 259 - libsecurity_ssl/regressions/ssl-utils.h | 22 - libsecurity_ssl/regressions/ssl_regressions.h | 25 - libsecurity_ssl/sslViewer/fileIo.c | 116 - libsecurity_ssl/sslViewer/fileIo.h | 44 - libsecurity_ssl/sslViewer/ioSock.c | 502 - libsecurity_ssl/sslViewer/ioSock.h | 110 - libsecurity_ssl/sslViewer/sslAppUtils.cpp | 1647 --- libsecurity_ssl/sslViewer/sslAppUtils.h | 163 - libsecurity_ssl/sslViewer/sslServer.cpp | 1062 -- libsecurity_transform/custom.h | 16 - libsecurity_transform/lib/Digest_block.h | 9 - .../lib/SecExternalSourceTransform.cpp | 41 - .../lib/SecGroupTransform.cpp | 36 - libsecurity_transform/lib/misc.h | 36 - .../project.pbxproj | 875 -- .../xcschemes/xcschememanagement.plist | 29 - libsecurity_transform/misc/speed-test.h | 16 - libsecurity_transform/misc/speed-test.mm | 92 - libsecurity_utilities/lib/ccaudit.h | 189 - libsecurity_utilities/lib/debugging.h | 129 - .../lib/debugging_internal.h | 45 - libsecurity_utilities/lib/utilities.h | 315 - .../xcschemes/xcschememanagement.plist | 19 - libsecurityd/lib/SharedMemoryCommon.h | 20 - libsecurityd/lib/transition.cpp | 1066 -- .../xcschemes/xcschememanagement.plist | 34 - libsecurityd/mig/mig.mk | 61 - ntlm/NtlmGenerator.c | 726 + ntlm/NtlmGenerator.h | 132 + ntlm/ntlmBlobPriv.c | 499 + ntlm/ntlmBlobPriv.h | 286 + refs.txt | 0 .../regressions.xcodeproj/project.pbxproj | 341 - regressions/t/security.pl | 68 - regressions/test/run_tests.sh | 33 - regressions/test/testcpp.h | 83 - regressions/test/testenv.c | 291 - regressions/test/testenv.h | 41 - regressions/test/testmore.c | 347 - regressions/test/testmore.h | 201 - regressions/test/testpolicy.h | 19 - resources/AppleESCertificates.plist | Bin 0 -> 2086 bytes resources/AssetVersion.plist | 8 + resources/Blocked.plist | Bin 0 -> 435 bytes resources/EVRoots.plist | Bin 0 -> 3448 bytes resources/English.lproj/Certificate.strings | Bin 0 -> 22712 bytes resources/English.lproj/CloudKeychain.strings | Bin 0 -> 6498 bytes resources/English.lproj/OID.strings | Bin 0 -> 211564 bytes .../SharedWebCredentials.strings | Bin 0 -> 4982 bytes resources/GrayListedKeys.plist | Bin 0 -> 381 bytes resources/certsIndex.data | Bin 0 -> 5352 bytes resources/certsTable.data | Bin 0 -> 242192 bytes sbr | 25 + .../CKBridge/SOSCloudKeychainClient.c | 757 - .../CKBridge/SOSCloudKeychainClient.h | 136 - .../CloudKeychainProxy/CKDKVSProxy.h | 95 - .../CloudKeychainProxy/CKDKVSProxy.m | 869 -- .../CloudKeychainProxy/cloudkeychainproxy.m | 461 - .../CloudKeychainProxy/scripts/sosbuildroot | 31 - .../CloudKeychainProxy/scripts/sshauser | 69 - sec/SOSCircle/Regressions/CKDKeyValueStore.h | 78 - sec/SOSCircle/Regressions/SOSTestDataSource.c | 382 - sec/SOSCircle/Regressions/SOSTestDataSource.h | 34 - sec/SOSCircle/Regressions/SOSTestTransport.c | 48 - sec/SOSCircle/Regressions/SOSTestTransport.h | 24 - .../Regressions/sc-100-devicecircle.c | 565 - .../Regressions/sc-101-accountsync.c | 574 - .../Regressions/sc-102-cfusernotification.c | 100 - .../Regressions/sc-120-cloudcircle.c | 391 - sec/SOSCircle/Regressions/sc-30-peerinfo.c | 108 - sec/SOSCircle/Regressions/sc-40-circle.c | 101 - sec/SOSCircle/Regressions/sc-41-cloudcircle.c | 48 - sec/SOSCircle/Regressions/sc-60-peer.c | 147 - .../Regressions/sc-75-circle-engine.c | 223 - sec/SOSCircle/SOSARCDefines.h | 49 - .../Imported/SOSCloudCircleServer.h | 1 - .../SecureObjectSync/Imported/SecItemServer.h | 1 - .../SecureObjectSync/Imported/SecuritydXPC.h | 1 - .../Imported/securityd_client.h | 1 - sec/SOSCircle/SecureObjectSync/Imported/spi.h | 1 - sec/SOSCircle/SecureObjectSync/SOSAccount.c | 3191 ----- sec/SOSCircle/SecureObjectSync/SOSAccount.h | 224 - sec/SOSCircle/SecureObjectSync/SOSCircle.c | 1172 -- .../SecureObjectSync/SOSCloudCircle.c | 425 - .../SecureObjectSync/SOSCloudCircleInternal.h | 31 - sec/SOSCircle/SecureObjectSync/SOSCoder.c | 495 - sec/SOSCircle/SecureObjectSync/SOSCoder.h | 41 - sec/SOSCircle/SecureObjectSync/SOSEngine.c | 932 -- sec/SOSCircle/SecureObjectSync/SOSEngine.h | 83 - .../SecureObjectSync/SOSFullPeerInfo.h | 60 - sec/SOSCircle/SecureObjectSync/SOSInternal.h | 87 - sec/SOSCircle/SecureObjectSync/SOSPeer.c | 517 - sec/SOSCircle/SecureObjectSync/SOSPeer.h | 77 - sec/SOSCircle/SecureObjectSync/SOSPeerInfo.h | 127 - .../SecureObjectSync/SOSPeerInfoInternal.h | 16 - sec/SOSCircle/SecureObjectSync/SOSTransport.c | 329 - sec/SOSCircle/SecureObjectSync/SOSTransport.h | 103 - sec/SOSCircle/SecureObjectSync/SOSUserKey.c | 80 - sec/SOSCircle/SecureObjectSync/SOSUserKey.h | 18 - .../SecureObjectSync/SOSUserKeygen.h | 19 - sec/SOSCircle/Tool/SOSCommands.h | 32 - sec/SOSCircle/Tool/keychain_sync.c | 459 - sec/SOSCircle/osxshim.c | 30 - .../AppleBaselineEscrowCertificates.h | 94 - .../Regressions/Security_regressions.h | 75 - sec/Security/Regressions/otr/otr-otrdh.c | 45 - sec/Security/Regressions/otr/otr-packetdata.c | 185 - .../Regressions/secitem/si-20-sectrust.c | 861 -- .../secitem/si-31-keychain-unreadable.c | 89 - .../secitem/si-33-keychain-backup.c | 481 - .../Regressions/secitem/si-40-seckey-custom.c | 152 - .../Regressions/secitem/si-41-sececkey.c | 283 - .../Regressions/secitem/si-50-secrandom.c | 34 - .../secitem/si-67-sectrust-blacklist.c | 81 - .../secitem/si-70-sectrust-unified.c | 250 - .../secitem/si-71-mobile-store-policy.c | 424 - sec/Security/SecBase.h | 105 - sec/Security/SecBasePriv.h | 125 - sec/Security/SecCMS.c | 696 - sec/Security/SecCMS.h | 173 - sec/Security/SecCertificate.h | 87 - sec/Security/SecCertificatePriv.h | 198 - sec/Security/SecCertificateRequest.h | 128 - sec/Security/SecDH.c | 302 - sec/Security/SecECKey.c | 665 - sec/Security/SecIdentity.c | 136 - sec/Security/SecIdentity.h | 75 - sec/Security/SecIdentityPriv.h | 48 - sec/Security/SecImportExport.c | 172 - sec/Security/SecImportExport.h | 94 - sec/Security/SecInternal.h | 76 - sec/Security/SecItem.h | 973 -- sec/Security/SecItemConstants.c | 216 - sec/Security/SecItemPriv.h | 341 - sec/Security/SecKey.h | 296 - sec/Security/SecKeyPriv.h | 295 - sec/Security/SecOTR.h | 76 - sec/Security/SecOTRDHKey.c | 309 - sec/Security/SecOTRDHKey.h | 46 - sec/Security/SecOTRErrors.h | 27 - sec/Security/SecOTRMath.h | 65 - sec/Security/SecOTRMathPrivate.h | 121 - sec/Security/SecOTRPacketData.c | 10 - sec/Security/SecOTRPackets.h | 31 - sec/Security/SecOTRSession.c | 777 - sec/Security/SecOTRSession.h | 112 - sec/Security/SecOTRSessionPriv.h | 92 - sec/Security/SecOnOSX.h | 28 - sec/Security/SecPolicy.h | 391 - sec/Security/SecPolicyPriv.h | 378 - sec/Security/SecRandom.h | 61 - sec/Security/SecTrust.h | 681 - sec/Security/SecTrustPriv.h | 229 - sec/Security/SecTrustSettings.h | 247 - sec/Security/SecTrustSettingsPriv.h | 218 - sec/Security/Security.h | 33 - sec/Security/SecuritydXPC.h | 38 - sec/Security/Tool/codesign.c | 424 - sec/Security/Tool/keychain_add.c | 128 - sec/Security/Tool/keychain_find.c | 572 - sec/Security/certextensions.h | 546 - sec/Security/cssmapple.h | 76 - sec/Security/keychain_find.h | 53 - sec/Security/pbkdf2.c | 105 - sec/Security/pbkdf2.h | 78 - sec/Security/vmdh.c | 62 - sec/Security/vmdh.h | 62 - sec/SecurityTool/builtin_commands.h | 21 - sec/SecurityTool/digest_calc.c | 78 - sec/SecurityTool/leaks.c | 109 - sec/SecurityTool/leaks.h | 37 - sec/SecurityTool/tool_errors.h | 60 - sec/config/base.xcconfig | 47 - sec/config/lib.xcconfig | 32 - sec/ipc/com.apple.secd.plist | 47 - sec/ipc/com.apple.securityd.plist | 38 - sec/ipc/securityd_client.h | 209 - sec/ipc/server.c | 769 - sec/sec.xcodeproj/project.pbxproj | 2504 ---- .../xcschemes/xcschememanagement.plist | 89 - sec/securityd/Regressions/SOSAccountTesting.h | 254 - .../Regressions/SecdTestKeychainUtilities.c | 45 - .../Regressions/SecdTestKeychainUtilities.h | 17 - .../Regressions/brighton_keychain_2_db.h | 10586 -------------- sec/securityd/Regressions/sd-70-engine.c | 383 - .../Regressions/secd-31-keychain-unreadable.c | 81 - sec/securityd/Regressions/secd-50-account.c | 99 - .../Regressions/secd-52-account-changed.c | 179 - .../Regressions/secd-55-account-circle.c | 300 - .../secd-55-account-incompatibility.c | 197 - .../Regressions/secd-56-account-apply.c | 223 - .../Regressions/secd-57-account-leave.c | 238 - .../Regressions/secd-58-password-change.c | 198 - .../Regressions/secd-59-account-cleanup.c | 180 - .../secd-60-account-cloud-identity.c | 151 - ...d-61-account-leave-not-in-kansas-anymore.c | 194 - sec/securityd/Regressions/secd_regressions.h | 31 - .../Regressions/securityd_regressions.h | 12 - sec/securityd/SOSCloudCircleServer.c | 1000 -- sec/securityd/SOSCloudCircleServer.h | 85 - sec/securityd/SecCAIssuerRequest.h | 15 - sec/securityd/SecDbItem.h | 404 - sec/securityd/SecItemServer.c | 4446 ------ sec/securityd/SecItemServer.h | 71 - sec/securityd/entitlements.plist | 12 - sec/securityd/spi.c | 75 - sec/securityd/spi.h | 40 - secdtests/main.c | 28 +- secdtests/secdtests-entitlements.plist | 40 + secdtests/testlist.h | 6 +- sectask/SecEntitlements.h | 101 + sectask/SecTask.c | 303 + sectask/SecTask.h | 112 + sectask/regressions/sectask-10-sectask.c | 198 + sectask/regressions/sectask_ipc.defs | 33 + sectask/regressions/sectask_regressions.h | 9 + sectests/main.c | 32 - sectests/test/testenv.c | 264 - sectests/testlist.h | 3 - security2/security2.1 | 79 - security2/security_tool_commands.c | 28 - security2/sub_commands.h | 12 - securityd/APPLE_LICENSE | 367 + securityd/config/debug.xcconfig | 3 + securityd/config/project.xcconfig | 25 + securityd/config/release.xcconfig | 3 + securityd/doc/BLOBFORMAT | 63 + securityd/doc/securityd.1 | 36 + securityd/dtrace/dtrace.mk | 2 + securityd/dtrace/securityd-watch.d | 415 + securityd/etc/CodeEquivalenceCandidates | 74 + securityd/etc/com.apple.securityd.plist | 31 + securityd/etc/startup.mk | 55 + .../Info-security_agent_client.plist | 5 + .../Info-security_agent_server.plist | 5 + .../libsecurity_agent/lib/agentclient.cpp | 597 + securityd/libsecurity_agent/lib/agentclient.h | 220 + securityd/libsecurity_agent/lib/sa_types.h | 70 + .../libsecurity_agent/lib/secagent_types.h | 53 + securityd/libsecurity_agent/lib/utils.c | 26 + securityd/libsecurity_agent/lib/utils.h | 26 + .../project.pbxproj | 513 + securityd/libsecurity_agent/mig/mig.mk | 39 + securityd/libsecurity_agent/mig/sa_reply.defs | 54 + .../libsecurity_agent/mig/sa_request.defs | 70 + .../libsecurity_agent/security_agent_client | 1 + securityd/mig/mig.mk | 47 + securityd/mig/self.defs | 43 + securityd/security_agent_client | 1 + securityd/security_agent_server | 1 + securityd/securityd.xcodeproj/project.pbxproj | 1187 ++ .../contents.xcworkspacedata | 7 + .../KeyStore/AppleKeyStoreEvents.h | 9 + .../KeyStore/KeyStore-Info.plist | 28 + .../KeyStore/KeyStoreEvents.c | 54 + .../project.pbxproj | 634 + .../com.apple.securityd_service.plist | 17 + .../com.apple.securitydservice.sb | 31 + .../securityd_service/main.c | 1080 ++ .../securityd_service/securityd_service.h | 31 + .../securityd_service_client.c | 237 + .../securityd_service_client.h | 46 + .../securityd_service/service.entitlements | 14 + .../securitydservicectrl/main.c | 114 + securityd/src/AuthorizationDBPlist.cpp | 416 + securityd/src/AuthorizationDBPlist.h | 83 + securityd/src/AuthorizationEngine.cpp | 366 + securityd/src/AuthorizationEngine.h | 103 + securityd/src/AuthorizationMechEval.cpp | 304 + securityd/src/AuthorizationMechEval.h | 69 + securityd/src/AuthorizationRule.cpp | 1117 ++ securityd/src/AuthorizationRule.h | 160 + securityd/src/SharedMemoryServer.cpp | 169 + securityd/src/SharedMemoryServer.h | 39 + securityd/src/acl_keychain.cpp | 327 + securityd/src/acl_keychain.h | 81 + securityd/src/acls.cpp | 303 + securityd/src/acls.h | 155 + securityd/src/agentquery.cpp | 1575 ++ securityd/src/agentquery.h | 341 + securityd/src/auditevents.cpp | 72 + securityd/src/auditevents.h | 50 + securityd/src/authhost.cpp | 216 + securityd/src/authhost.h | 57 + securityd/src/authority.cpp | 319 + securityd/src/authority.h | 132 + securityd/src/ccaudit_extensions.cpp | 441 + securityd/src/ccaudit_extensions.h | 253 + securityd/src/child.cpp | 137 + securityd/src/child.h | 77 + securityd/src/clientid.cpp | 220 + securityd/src/clientid.h | 84 + securityd/src/codesigdb.cpp | 549 + securityd/src/codesigdb.h | 111 + securityd/src/connection.cpp | 180 + securityd/src/connection.h | 108 + securityd/src/credential.cpp | 211 + securityd/src/credential.h | 104 + securityd/src/csproxy.cpp | 531 + securityd/src/csproxy.h | 131 + securityd/src/database.cpp | 283 + securityd/src/database.h | 238 + securityd/src/dbcrypto.cpp | 542 + securityd/src/dbcrypto.h | 93 + securityd/src/dtrace.h | 48 + securityd/src/entropy.cpp | 224 + securityd/src/entropy.h | 65 + securityd/src/kcdatabase.cpp | 1501 ++ securityd/src/kcdatabase.h | 264 + securityd/src/kckey.cpp | 228 + securityd/src/kckey.h | 90 + securityd/src/key.cpp | 36 + securityd/src/key.h | 80 + securityd/src/localdatabase.cpp | 280 + securityd/src/localdatabase.h | 103 + securityd/src/localkey.cpp | 194 + securityd/src/localkey.h | 117 + securityd/src/main.cpp | 354 + securityd/src/notifications.cpp | 211 + securityd/src/notifications.h | 140 + securityd/src/pcscmonitor.cpp | 232 + securityd/src/pcscmonitor.h | 96 + securityd/src/process.cpp | 258 + securityd/src/process.h | 136 + securityd/src/reader.cpp | 154 + securityd/src/reader.h | 79 + securityd/src/securityd.d | 131 + securityd/src/securityd.exp | 0 securityd/src/securityd.order | 912 ++ securityd/src/server.cpp | 567 + securityd/src/server.h | 239 + securityd/src/session.cpp | 689 + securityd/src/session.h | 226 + securityd/src/structure.cpp | 191 + securityd/src/structure.h | 259 + securityd/src/tempdatabase.cpp | 178 + securityd/src/tempdatabase.h | 66 + securityd/src/token.cpp | 512 + securityd/src/token.h | 134 + securityd/src/tokenaccess.cpp | 63 + securityd/src/tokenaccess.h | 87 + securityd/src/tokenacl.cpp | 193 + securityd/src/tokenacl.h | 72 + securityd/src/tokencache.cpp | 264 + securityd/src/tokencache.h | 116 + securityd/src/tokend.cpp | 201 + securityd/src/tokend.h | 122 + securityd/src/tokendatabase.cpp | 837 ++ securityd/src/tokendatabase.h | 245 + securityd/src/tokenkey.cpp | 129 + securityd/src/tokenkey.h | 65 + securityd/src/transition.cpp | 1597 +++ securityd/tests/AZNTest.cpp | 81 + securityd/tests/auth.plist | 19 + securityd/tests/exectest.cpp | 120 + securityd/tests/testacls.cpp | 409 + securityd/tests/testauth.cpp | 132 + securityd/tests/testblobs.cpp | 288 + securityd/tests/testclient.cpp | 287 + securityd/tests/testclient.h | 75 + securityd/tests/testcrypto.cpp | 190 + securityd/tests/testutils.cpp | 246 + securityd/tests/testutils.h | 96 + spiralsink114.png | Bin 0 -> 24752 bytes spiralsink57.png | Bin 0 -> 7978 bytes sslViewer/SSLViewer.cpp | 1627 +++ sslViewer/SSL_Sites | 306 + sslViewer/ecc-secp256r1-client.pfx | Bin 0 -> 1036 bytes sslViewer/ioSock.c | 481 + sslViewer/ioSock.h | 89 + sslViewer/pingSslSites | 37 + sslViewer/sslAppUtils.cpp | 1616 +++ sslViewer/sslAppUtils.h | 166 + sslViewer/sslClient.cpp | 196 + sslViewer/sslEcdsa.cpp | 646 + sslViewer/sslServe.cpp | 288 + sslViewer/sslServer-entitlements.plist | 11 + sslViewer/sslServer.cpp | 1065 ++ sslViewer/sslThreading.h | 169 + sslViewer/sslViewer-entitlements.plist | 11 + sslViewer/verifyPing | 143 + tlsnke/tlsnke.xcodeproj/project.pbxproj | 593 - .../xcdebugger/Breakpoints.xcbkptlist | 5 - tlsnke/tlsnke/tlsnke.h | 88 - tlsnke/tlsnketest/main.c | 279 - tlsnke/tlsnketest/ssl-utils.c | 107 - tlsnke/tlsnketest/ssl-utils.h | 18 - tlsnke/tlsnketest/tlssocket.h | 43 - utilities/Regressions/su-10-cfstring-der.c | 90 - utilities/Regressions/su-12-cfboolean-der.c | 86 - utilities/SecurityTool/not_on_this_platorm.c | 14 - utilities/SecurityTool/readline.c | 257 - utilities/SecurityTool/readline.h | 54 - .../SecurityTool/security_tool_commands.h | 28 - .../security_tool_commands_table.h | 29 - utilities/src/SecAKSWrappers.h | 105 - utilities/src/SecCFCanonicalHashes.c | 120 - utilities/src/SecCFCanonicalHashes.h | 20 - utilities/src/SecCFError.c | 106 - utilities/src/SecCFError.h | 46 - utilities/src/SecCFRelease.h | 34 - utilities/src/SecCFWrappers.c | 71 - utilities/src/SecCFWrappers.h | 585 - utilities/src/SecDb.h | 117 - utilities/src/SecDispatchRelease.h | 58 - utilities/src/SecIOFormat.h | 50 - utilities/src/SecXPCError.c | 67 - utilities/src/SecXPCError.h | 33 - utilities/src/array_size.h | 14 - utilities/src/comparison.c | 19 - utilities/src/comparison.h | 17 - utilities/src/debugging.c | 294 - utilities/src/debugging.h | 124 - utilities/src/der_array.c | 75 - utilities/src/der_boolean.c | 54 - utilities/src/der_data.c | 87 - utilities/src/der_date.c | 406 - utilities/src/der_date.h | 27 - utilities/src/der_null.c | 50 - utilities/src/der_plist.h | 39 - utilities/src/der_plist_internal.c | 18 - utilities/src/der_string.c | 78 - utilities/src/fileIo.c | 100 - utilities/src/fileIo.h | 26 - utilities/src/iCloudKeychainTrace.c | 195 - utilities/src/iCloudKeychainTrace.h | 42 - utilities/src/iOSforOSX-SecAttr.c | 27 - utilities/src/iOSforOSX-SecRandom.c | 13 - utilities/src/iOSforOSX.c | 67 - utilities/src/iOSforOSX.h | 34 - utilities/src/sqlutils.h | 37 - utilities/utilities.xcodeproj/project.pbxproj | 546 - 6163 files changed, 450098 insertions(+), 126580 deletions(-) create mode 100644 .call rename sec/SOSCircle/Empty.c => .com.apple.timemachine.supported (100%) create mode 100644 CircleJoinRequested/Applicant.h create mode 100644 CircleJoinRequested/Applicant.m create mode 100644 CircleJoinRequested/CircleJoinRequested.1 create mode 100644 CircleJoinRequested/CircleJoinRequested.m create mode 100644 CircleJoinRequested/Info.plist create mode 100644 CircleJoinRequested/NSArray+map.h create mode 100644 CircleJoinRequested/NSArray+map.m create mode 100644 CircleJoinRequested/NSDate+TimeIntervalDescription.h create mode 100644 CircleJoinRequested/NSDate+TimeIntervalDescription.m create mode 100644 CircleJoinRequested/PersistantState.h create mode 100644 CircleJoinRequested/PersistantState.m create mode 100644 CircleJoinRequested/Readme.txt create mode 100644 CircleJoinRequested/com.apple.security.CircleJoinRequested.plist create mode 100644 CircleJoinRequested/entitlements.plist create mode 100644 CloudKeychainProxy/CloudKeychainProxy.1 delete mode 100644 CloudKeychainProxy/cloudkeychain.entitlements.plist create mode 100644 Default-568h@2x.png delete mode 100644 Keychain Circle Notification/CloudKeychain.icns delete mode 100644 Keychain Circle Notification/KNAppDelegate.h delete mode 100644 Keychain Circle Notification/KNPersistantState.h delete mode 100644 Keychain Circle Notification/NSArray+mapWithBlock.h delete mode 100644 Keychain Circle Notification/NSArray+mapWithBlock.m delete mode 100644 Keychain Circle Notification/NSDictionary+compactDescription.h delete mode 100644 Keychain Circle Notification/NSDictionary+compactDescription.m delete mode 100644 Keychain Circle Notification/NSSet+compactDescription.h delete mode 100644 Keychain Circle Notification/NSSet+compactDescription.m delete mode 100644 Keychain Circle Notification/NSString+compactDescription.h delete mode 100644 Keychain Circle Notification/NSString+compactDescription.m delete mode 100644 Keychain Circle Notification/main.m create mode 100644 Keychain/AppDelegate.h create mode 100644 Keychain/AppDelegate.m create mode 100644 Keychain/CircleStatusView.h create mode 100644 Keychain/CircleStatusView.m create mode 100644 Keychain/Default-568h@2x.png create mode 100644 Keychain/Default.png create mode 100644 Keychain/Default@2x.png create mode 100644 Keychain/DeviceItemCell.h create mode 100644 Keychain/DeviceItemCell.m create mode 100644 Keychain/DeviceTableViewController.h create mode 100644 Keychain/DeviceTableViewController.m create mode 100644 Keychain/DeviceViewController.h create mode 100644 Keychain/DeviceViewController.m create mode 100644 Keychain/EditItemViewController.h create mode 100644 Keychain/EditItemViewController.m create mode 100644 Keychain/FirstViewController.h create mode 100644 Keychain/FirstViewController.m create mode 100644 Keychain/KCAItemDetailViewController.h create mode 100644 Keychain/KCAItemDetailViewController.m create mode 100644 Keychain/KCATableViewController.h create mode 100644 Keychain/KCATableViewController.m delete mode 100644 Keychain/KDAppDelegate.h delete mode 100644 Keychain/KDAppDelegate.m delete mode 100644 Keychain/KDCirclePeer.h delete mode 100644 Keychain/KDCirclePeer.m delete mode 100644 Keychain/KDSecCircle.h delete mode 100644 Keychain/KDSecItems.h create mode 100644 Keychain/Keychain-Entitlements.plist create mode 100644 Keychain/KeychainItemCell.h create mode 100644 Keychain/KeychainItemCell.m create mode 100644 Keychain/KeychainKeys.png create mode 100644 Keychain/MyKeychain.h create mode 100644 Keychain/MyKeychain.m create mode 100644 Keychain/NewPasswordViewController.h create mode 100644 Keychain/NewPasswordViewController.m create mode 100644 Keychain/PeerListCell.h create mode 100644 Keychain/PeerListCell.m create mode 100644 Keychain/SyncViewController.h create mode 100644 Keychain/SyncViewController.m create mode 100644 Keychain/ToolsViewController.h create mode 100644 Keychain/ToolsViewController.m create mode 100644 Keychain/first.png create mode 100644 Keychain/first@2x.png create mode 100644 Keychain/second.png create mode 100644 Keychain/second@2x.png create mode 100644 Keychain/utilities.c create mode 100644 Keychain/utilities.h create mode 100644 KeychainSyncAccountNotification/KeychainSyncAccountNotification-Info.plist create mode 100644 KeychainSyncAccountNotification/KeychainSyncAccountNotification-Prefix.pch create mode 100644 KeychainSyncAccountNotification/KeychainSyncAccountNotification.h create mode 100644 KeychainSyncAccountNotification/KeychainSyncAccountNotification.m rename {Keychain Circle Notification => KeychainSyncAccountNotification}/en.lproj/InfoPlist.strings (100%) create mode 100644 Keychain_114x114.png create mode 100644 Keychain_144x144.png create mode 100644 Keychain_57x57.png create mode 100644 Keychain_72x72.png create mode 100644 OTAPKIAssetTool/OTAPKIAssetTool-entitlements.plist create mode 100644 OTAPKIAssetTool/OTAServiceApp.h create mode 100644 OTAPKIAssetTool/OTAServiceApp.m create mode 100644 OTAPKIAssetTool/OTAServicemain.m create mode 100644 OTAPKIAssetTool/com.apple.OTAPKIAssetTool.plist create mode 100644 README.genanchors create mode 100644 README.keychain create mode 100644 SecureObjectSync-Info.plist create mode 100644 SecureObjectSync.exp create mode 100644 Security-Info.plist create mode 100644 Security.exp-in create mode 100644 Security.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 Security.xcodeproj/project.xcworkspace/xcuserdata/jkauth.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 Security.xcodeproj/xcshareddata/xcschemes/Debug.xcscheme create mode 100644 Security.xcodeproj/xcshareddata/xcschemes/ProtectedCloudStorage.xcscheme create mode 100644 Security.xcodeproj/xcshareddata/xcschemes/Release.xcscheme create mode 100644 Security.xcodeproj/xcshareddata/xcschemes/SyncTest.xcscheme create mode 100644 Security.xcodeproj/xcshareddata/xcschemes/SyncTest2.xcscheme create mode 100644 Security.xcodeproj/xcshareddata/xcschemes/codesigntester.xcscheme create mode 100644 Security.xcodeproj/xcshareddata/xcschemes/libsecurityd.xcscheme create mode 100644 Security.xcodeproj/xcshareddata/xcschemes/security.xcscheme create mode 100644 Security.xcodeproj/xcshareddata/xcschemes/securityd.xcscheme create mode 100644 Security.xcodeproj/xcshareddata/xcschemes/sslEcdsa.xcscheme create mode 100644 Security.xcodeproj/xcshareddata/xcschemes/sslServer.xcscheme create mode 100644 Security.xcodeproj/xcshareddata/xcschemes/sslViewer.xcscheme delete mode 100644 Security.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist rename APPLE_LICENSE => Security/APPLE_LICENSE (100%) create mode 100644 Security/Breadcrumb/README create mode 100644 Security/Breadcrumb/SecBreadcrumb.c create mode 100644 Security/Breadcrumb/SecBreadcrumb.h create mode 100644 Security/Breadcrumb/bc-10-knife-on-bread.c create mode 100644 Security/Breadcrumb/breadcrumb_regressions.h create mode 100644 Security/CloudKeychainProxy/CloudKeychainProxy-Info.plist rename {sec/SOSCircle => Security}/CloudKeychainProxy/cloudkeychain.entitlements.plist (100%) create mode 100644 Security/CloudKeychainProxy/com.apple.security.cloudkeychainproxy.plist rename {Keychain => Security/CloudKeychainProxy}/en.lproj/InfoPlist.strings (100%) create mode 100644 Security/Keychain Circle Notification/KNAppDelegate.h rename {Keychain Circle Notification => Security/Keychain Circle Notification}/KNAppDelegate.m (86%) create mode 100644 Security/Keychain Circle Notification/KNPersistantState.h rename {Keychain Circle Notification => Security/Keychain Circle Notification}/KNPersistantState.m (75%) rename {Keychain Circle Notification => Security/Keychain Circle Notification}/Keychain Circle Notification-Info.plist (91%) rename {Keychain Circle Notification => Security/Keychain Circle Notification}/Keychain Circle Notification-Prefix.pch (100%) create mode 100644 Security/Keychain Circle Notification/NSArray+mapWithBlock.h create mode 100644 Security/Keychain Circle Notification/NSArray+mapWithBlock.m create mode 100644 Security/Keychain Circle Notification/NSDictionary+compactDescription.h create mode 100644 Security/Keychain Circle Notification/NSDictionary+compactDescription.m create mode 100644 Security/Keychain Circle Notification/NSSet+compactDescription.h create mode 100644 Security/Keychain Circle Notification/NSSet+compactDescription.m create mode 100644 Security/Keychain Circle Notification/NSString+compactDescription.h create mode 100644 Security/Keychain Circle Notification/NSString+compactDescription.m rename {Keychain Circle Notification => Security/Keychain Circle Notification}/com.apple.security.keychain-circle-notification.plist (86%) rename {Keychain Circle Notification => Security/Keychain Circle Notification}/en.lproj/Credits.rtf (100%) rename {authd => Security/Keychain Circle Notification}/en.lproj/InfoPlist.strings (100%) rename {Keychain Circle Notification => Security/Keychain Circle Notification}/en.lproj/Localizable.strings (100%) rename {Keychain Circle Notification => Security/Keychain Circle Notification}/en.lproj/MainMenu.xib (100%) rename {Keychain Circle Notification => Security/Keychain Circle Notification}/entitlments.plist (100%) create mode 100644 Security/Keychain Circle Notification/main.m rename {Keychain => Security/Keychain}/Icon.icns (100%) create mode 100644 Security/Keychain/KDAppDelegate.h create mode 100644 Security/Keychain/KDAppDelegate.m create mode 100644 Security/Keychain/KDCirclePeer.h create mode 100644 Security/Keychain/KDCirclePeer.m create mode 100644 Security/Keychain/KDSecCircle.h rename {Keychain => Security/Keychain}/KDSecCircle.m (81%) create mode 100644 Security/Keychain/KDSecItems.h rename {Keychain => Security/Keychain}/KDSecItems.m (76%) create mode 100644 Security/Keychain/Keychain-Info.plist rename {Keychain => Security/Keychain}/Keychain-Prefix.pch (100%) rename {Keychain => Security/Keychain}/en.lproj/Credits.rtf (100%) rename {sec/SOSCircle/CloudKeychainProxy => Security/Keychain}/en.lproj/InfoPlist.strings (100%) rename {Keychain => Security/Keychain}/en.lproj/MainMenu.xib (100%) create mode 100644 Security/Keychain/main.m create mode 100644 Security/README create mode 100644 Security/Security.xcodeproj/project.pbxproj create mode 100644 Security/Security.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Security/Security.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings rename {Security.xcodeproj => Security/Security.xcodeproj}/xcshareddata/xcschemes/Security.xcscheme (100%) rename {Security.xcodeproj => Security/Security.xcodeproj}/xcshareddata/xcschemes/Security_executables.xcscheme (100%) rename {Security.xcodeproj => Security/Security.xcodeproj}/xcshareddata/xcschemes/Security_frameworks.xcscheme (100%) rename {Security.xcodeproj => Security/Security.xcodeproj}/xcshareddata/xcschemes/World.xcscheme (96%) rename {Security.xcodeproj => Security/Security.xcodeproj}/xcshareddata/xcschemes/authd.xcscheme (100%) rename {Security.xcodeproj => Security/Security.xcodeproj}/xcshareddata/xcschemes/copyHeaders.xcscheme (100%) rename {Security.xcodeproj => Security/Security.xcodeproj}/xcshareddata/xcschemes/secd.xcscheme (100%) create mode 100644 Security/Security.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme create mode 100644 Security/asl/com.apple.securityd create mode 100644 Security/authd/Info.plist rename {authd => Security/authd}/agent.c (98%) rename {authd => Security/authd}/agent.h (97%) rename {authd => Security/authd}/authd_private.h (98%) rename {authd => Security/authd}/authdb.c (99%) rename {authd => Security/authd}/authdb.h (96%) rename {authd => Security/authd}/authitems.c (99%) rename {authd => Security/authd}/authitems.h (98%) rename {authd => Security/authd}/authorization.plist (91%) rename {authd => Security/authd}/authtoken.c (99%) rename {authd => Security/authd}/authtoken.h (97%) rename {authd => Security/authd}/authtypes.h (94%) rename {authd => Security/authd}/authutilities.c (99%) rename {authd => Security/authd}/authutilities.h (93%) rename {authd => Security/authd}/ccaudit.c (99%) create mode 100644 Security/authd/ccaudit.h rename {authd => Security/authd}/com.apple.authd (80%) rename {authd => Security/authd}/com.apple.authd.sb (100%) rename {authd => Security/authd}/connection.c (97%) create mode 100644 Security/authd/connection.h rename {authd => Security/authd}/crc.c (99%) rename {authd => Security/authd}/crc.h (93%) rename {authd => Security/authd}/credential.c (99%) create mode 100644 Security/authd/credential.h create mode 100644 Security/authd/debugging.c create mode 100644 Security/authd/debugging.h rename {tlsnke/tlsnke => Security/authd}/en.lproj/InfoPlist.strings (100%) rename {authd => Security/authd}/engine.c (93%) rename {authd => Security/authd}/engine.h (93%) create mode 100644 Security/authd/main.c rename {authd => Security/authd}/mechanism.c (99%) rename {authd => Security/authd}/mechanism.h (95%) create mode 100644 Security/authd/object.c rename {authd => Security/authd}/object.h (92%) rename {authd => Security/authd}/process.c (99%) create mode 100644 Security/authd/process.h rename {authd => Security/authd}/rule.c (99%) rename {authd => Security/authd}/rule.h (98%) rename {authd => Security/authd}/security.auth-Prefix.pch (100%) create mode 100644 Security/authd/server.c create mode 100644 Security/authd/server.h rename {authd => Security/authd}/session.c (98%) create mode 100644 Security/authd/session.h rename {cloud_keychain_diagnose => Security/cloud_keychain_diagnose}/cloud_keychain_diagnose-Prefix.pch (100%) rename {codesign_tests => Security/codesign_tests}/FatDynamicValidation.c (94%) rename {codesign_tests => Security/codesign_tests}/validation.sh (100%) create mode 100644 Security/config/base.xcconfig rename {config => Security/config}/command.xcconfig (89%) rename {config => Security/config}/debug.xcconfig (100%) rename {config => Security/config}/executable.xcconfig (76%) rename {config => Security/config}/lib.xcconfig (100%) rename {config => Security/config}/release.xcconfig (100%) rename {config => Security/config}/security.xcconfig (95%) rename {config => Security/config}/test.xcconfig (100%) rename {doc => Security/doc}/ACLsInCDSA.cwk (100%) rename {doc => Security/doc}/APIStrategy.cwk (100%) rename {doc => Security/doc}/AccessControlArchitecture.cwk (100%) rename {doc => Security/doc}/AppleCL_Spec.doc (100%) rename {doc => Security/doc}/AppleCSP.doc (100%) rename {doc => Security/doc}/AppleTP_Spec.doc (100%) rename {doc => Security/doc}/Apple_OID_Assignments.rtf (100%) rename {doc => Security/doc}/ArchitectureOverview.cwk (100%) create mode 100644 Security/doc/C++Utilities.cwk rename {doc => Security/doc}/DebuggingAids.cwk (100%) rename {doc => Security/doc}/HowToWriteA_CSP.cwk (100%) rename {doc => Security/doc}/HowToWriteA_Plugin.cwk (100%) rename {doc => Security/doc}/SecuritySupport.doc (100%) rename {doc => Security/doc}/Supported_CSP_Algorithms.doc (100%) rename {doc => Security/doc}/cwk_styles (100%) rename {include => Security/include}/security_asn1 (100%) rename {include => Security/include}/security_cdsa_client (100%) rename {include => Security/include}/security_cdsa_plugin (100%) rename {include => Security/include}/security_cdsa_utilities (100%) rename {include => Security/include}/security_cdsa_utils (100%) rename {include => Security/include}/security_codesigning (100%) rename {include => Security/include}/security_comcryption (100%) rename {include => Security/include}/security_cryptkit (100%) rename {include => Security/include}/security_filedb (100%) rename {include => Security/include}/security_keychain (100%) rename {include => Security/include}/security_ocspd (100%) rename {include => Security/include}/security_pkcs12 (100%) rename {include => Security/include}/security_smime (100%) rename {include => Security/include}/security_utilities (100%) rename {include => Security/include}/securityd_client (100%) rename {lib => Security/lib}/FDEPrefs.plist (100%) rename {lib => Security/lib}/Info-Security.plist (93%) rename {lib => Security/lib}/Security.order (100%) rename {lib => Security/lib}/TimeStampingPrefs.plist (100%) rename {lib => Security/lib}/copy_pieces.mk (96%) rename {lib => Security/lib}/dummy.cpp (100%) rename {lib => Security/lib}/en.lproj/FDELocalizable.strings (100%) rename {lib => Security/lib}/en.lproj/InfoPlist.strings (100%) rename {lib => Security/lib}/en.lproj/authorization.buttons.strings (96%) rename {lib => Security/lib}/en.lproj/authorization.prompts.strings (95%) rename {lib => Security/lib}/framework.sb (100%) create mode 100644 Security/lib/generateErrStrings.pl rename {lib => Security/lib}/plugins/csparser-Info.plist (94%) rename {lib => Security/lib}/plugins/csparser.cpp (94%) rename {lib => Security/lib}/plugins/csparser.exp (93%) rename {lib => Security/lib}/security.exp-in (97%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/Info-security_apple_csp.plist (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/README (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/TODO (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/docs/libsecurity_apple_csp.plist (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/docs/libsecurity_apple_csp.txt (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/AppleCSP.cpp (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/AppleCSP.h (97%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/AppleCSPBuiltin.cpp (94%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/AppleCSPContext.cpp (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/AppleCSPContext.h (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/AppleCSPKeys.cpp (97%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/AppleCSPKeys.h (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/AppleCSPPlugin.cpp (94%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/AppleCSPSession.h (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/AppleCSPUtils.cpp (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/AppleCSPUtils.h (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/BinaryKey.h (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/BlockCryptor.cpp (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/BlockCryptor.h (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/CryptKitSpace.h (91%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/DH_csp.cpp (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/DH_csp.h (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/DH_exchange.cpp (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/DH_exchange.h (94%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/DH_keys.cpp (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/DH_keys.h (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/DH_utils.cpp (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/DH_utils.h (97%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/DigestContext.cpp (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/DigestContext.h (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/FEEAsymmetricContext.cpp (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/FEEAsymmetricContext.h (97%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/FEECSPUtils.cpp (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/FEECSPUtils.h (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/FEEKeys.cpp (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/FEEKeys.h (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/FEESignatureObject.cpp (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/FEESignatureObject.h (97%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/HMACSHA1.c (87%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/HMACSHA1.h (89%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/MD2Object.cpp (95%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/MD2Object.h (94%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/MacContext.cpp (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/MacContext.h (97%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/NullCryptor.h (95%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/RSA_DSA_csp.cpp (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/RSA_DSA_csp.h (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/RSA_DSA_keys.cpp (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/RSA_DSA_keys.h (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/RSA_DSA_signature.cpp (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/RSA_DSA_signature.h (97%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/RSA_DSA_utils.cpp (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/RSA_DSA_utils.h (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/RSA_asymmetric.cpp (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/RSA_asymmetric.h (97%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/RawSigner.h (97%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/SHA1_MD5_Object.cpp (95%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/SHA1_MD5_Object.h (95%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/SHA2_Object.cpp (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/SHA2_Object.h (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/SignatureContext.cpp (97%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/SignatureContext.h (97%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/YarrowConnection.cpp (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/YarrowConnection.h (95%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/aesCommon.h (95%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/aescsp.cpp (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/aescspi.h (97%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/algmaker.cpp (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/ascContext.cpp (89%) create mode 100644 Security/libsecurity_apple_csp/lib/ascContext.h create mode 100644 Security/libsecurity_apple_csp/lib/ascFactory.h rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/bfContext.cpp (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/bfContext.h (95%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/boxes-ref.c (99%) create mode 100644 Security/libsecurity_apple_csp/lib/boxes-ref.h rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/bsafeAsymmetric.cpp (97%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/bsafeContext.cpp (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/bsafeKeyGen.cpp (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/bsafePKCS1.cpp (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/bsafePKCS1.h (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/bsafeSymmetric.cpp (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/bsafecsp.h (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/bsafecspi.h (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/bsobjects.h (97%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/castContext.cpp (97%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/castContext.h (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/cryptkitcsp.cpp (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/cryptkitcsp.h (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/cspdebugging.c (92%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/cspdebugging.h (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/cssmplugin.exp (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/deriveKey.cpp (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/desContext.cpp (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/desContext.h (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/gladmanContext.cpp (97%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/gladmanContext.h (97%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/memory.cpp (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/miscAlgFactory.cpp (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/miscAlgFactory.h (93%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/miscalgorithms.cpp (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/opensshCoding.cpp (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/opensshCoding.h (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/opensshWrap.cpp (99%) create mode 100644 Security/libsecurity_apple_csp/lib/pbkdDigest.cpp create mode 100644 Security/libsecurity_apple_csp/lib/pbkdDigest.h create mode 100644 Security/libsecurity_apple_csp/lib/pbkdf2.c create mode 100644 Security/libsecurity_apple_csp/lib/pbkdf2.h rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/pkcs12Derive.cpp (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/pkcs12Derive.h (93%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/pkcs8.cpp (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/pkcs8.h (95%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/rc2Context.cpp (97%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/rc2Context.h (94%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/rc4Context.cpp (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/rc4Context.h (94%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/rc5Context.cpp (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/rc5Context.h (94%) create mode 100644 Security/libsecurity_apple_csp/lib/rijndael-alg-ref.c create mode 100644 Security/libsecurity_apple_csp/lib/rijndael-alg-ref.h create mode 100644 Security/libsecurity_apple_csp/lib/rijndaelApi.c create mode 100644 Security/libsecurity_apple_csp/lib/rijndaelApi.h rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/vRijndael-alg-ref.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/wrapKey.cpp (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/lib/wrapKeyCms.cpp (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/libsecurity_apple_csp.xcodeproj/project.pbxproj (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/mds/csp_capabilities.mdsinfo (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/mds/csp_capabilities_common.mds (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/mds/csp_common.mdsinfo (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/mds/csp_primary.mdsinfo (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/LICENSE (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bf/COPYRIGHT (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bf/README (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bf/bf_ecb.c (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bf/bf_enc.c (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bf/bf_locl.h (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bf/bf_pi.h (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bf/bf_skey.c (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bio/bio_lib.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bio/bss_file.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_add.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_asm.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_blind.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_ctx.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_div.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_err.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_exp.c (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_exp2.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_gcd.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_lcl.h (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_lib.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_mont.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_mpi.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_mul.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_prime.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_prime.h (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_print.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_rand.c (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_recp.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_shift.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_sqr.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bn_word.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bnspeed.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/bntest.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/divtest.c (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/exp.c (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/expspeed.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/exptest.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/bn/vms-helper.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/buffer/buf_err.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/buffer/buffer.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/cryptlib.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/cryptlib.h (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/dh/dh_check.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/dh/dh_err.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/dh/dh_gen.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/dh/dh_key.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/dh/dh_lib.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/dsa/dsa_asn1.c (97%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/dsa/dsa_err.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/dsa/dsa_gen.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/dsa/dsa_key.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/dsa/dsa_lib.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/dsa/dsa_ossl.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/dsa/dsa_sign.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/dsa/dsa_vrf.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/err/err.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/err/err_prn.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/ex_data.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/lhash/lhash.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/mem.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/misc/rc2_cbc.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/misc/rc2_locl.h (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/misc/rc2_skey.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/misc/rc5_enc.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/misc/rc5_locl.h (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/misc/rc5_skey.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/asn1.h (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/bio.h (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/blowfish.h (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/bn.h (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/buffer.h (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/cast.h (100%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/crypto.h (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/dh.h (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/dsa.h (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/e_os.h (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/e_os2.h (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/err.h (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/evp.h (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/lhash.h (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/objects.h (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/openssl_pkcs7.h (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/opensslconf.h (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/opensslv.h (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/rand.h (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/rc2.h (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/rc5.h (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/rsa.h (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/safestack.h (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/stack.h (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/x509.h (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/openssl/x509_vfy.h (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/opensslUtils/opensslAsn1.cpp (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/opensslUtils/opensslAsn1.h (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/opensslUtils/opensslUtils.cpp (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/opensslUtils/opensslUtils.h (96%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/rsa/rsa_chk.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/rsa/rsa_eay.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/rsa/rsa_err.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/rsa/rsa_gen.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/rsa/rsa_lib.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/rsa/rsa_none.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/rsa/rsa_null.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/rsa/rsa_pk1.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/rsa/rsa_saos.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/rsa/rsa_sign.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/rsa/rsa_ssl.c (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/open_ssl/stack/stack.c (99%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/tests/t-dsa.cpp (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/tests/t-rsa.cpp (98%) rename {libsecurity_apple_csp => Security/libsecurity_apple_csp}/tests/t.cpp (98%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/Info-security_apple_cspdl.plist (100%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/lib/AppleCSPDLBuiltin.cpp (94%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/lib/AppleCSPDLPlugin.cpp (94%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/lib/CSPDLDatabase.cpp (95%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/lib/CSPDLDatabase.h (95%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/lib/CSPDLPlugin.cpp (96%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/lib/CSPDLPlugin.h (96%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/lib/SSCSPDLSession.cpp (98%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/lib/SSCSPDLSession.h (96%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/lib/SSCSPSession.cpp (99%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/lib/SSCSPSession.h (98%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/lib/SSContext.cpp (99%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/lib/SSContext.h (98%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/lib/SSDLSession.cpp (98%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/lib/SSDLSession.h (99%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/lib/SSDatabase.cpp (99%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/lib/SSDatabase.h (98%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/lib/SSFactory.cpp (97%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/lib/SSFactory.h (95%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/lib/SSKey.cpp (99%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/lib/SSKey.h (97%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/libsecurity_apple_cspdl.xcodeproj/project.pbxproj (100%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/mds/cspdl_common.mdsinfo (100%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/mds/cspdl_csp_capabilities.mdsinfo (100%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/mds/cspdl_csp_primary.mdsinfo (100%) rename {libsecurity_apple_cspdl => Security/libsecurity_apple_cspdl}/mds/cspdl_dl_primary.mdsinfo (100%) rename {libsecurity_apple_file_dl => Security/libsecurity_apple_file_dl}/Info-security_apple_file_dl.plist (100%) rename {libsecurity_apple_file_dl => Security/libsecurity_apple_file_dl}/TODO (100%) rename {libsecurity_apple_file_dl => Security/libsecurity_apple_file_dl}/doc/FORMAT (100%) rename {libsecurity_apple_file_dl => Security/libsecurity_apple_file_dl}/doc/ISSUES (100%) rename {libsecurity_apple_file_dl => Security/libsecurity_apple_file_dl}/lib/AppleDLBuiltin.cpp (94%) rename {libsecurity_apple_file_dl => Security/libsecurity_apple_file_dl}/lib/AppleDLPlugin.cpp (94%) rename {libsecurity_apple_file_dl => Security/libsecurity_apple_file_dl}/lib/AppleFileDL.cpp (97%) rename {libsecurity_apple_file_dl => Security/libsecurity_apple_file_dl}/lib/AppleFileDL.h (96%) rename {libsecurity_apple_file_dl => Security/libsecurity_apple_file_dl}/libsecurity_apple_file_dl.xcodeproj/project.pbxproj (100%) rename {libsecurity_apple_file_dl => Security/libsecurity_apple_file_dl}/mds/dl_common.mdsinfo (100%) rename {libsecurity_apple_file_dl => Security/libsecurity_apple_file_dl}/mds/dl_primary.mdsinfo (100%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/Info-plugin_apple_x509_cl.plist (100%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/Info-security_apple_x509_cl.plist (100%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/TODO (100%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/AppleX509CL.cpp (96%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/AppleX509CL.h (95%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/AppleX509CLBuiltin.cpp (94%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/AppleX509CLPlugin.cpp (94%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/AppleX509CLSession.cpp (97%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/AppleX509CLSession.h (99%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/CLCachedEntry.cpp (91%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/CLCachedEntry.h (96%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/CLCertExtensions.cpp (99%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/CLCertExtensions.h (97%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/CLCrlExtensions.cpp (98%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/CLCrlExtensions.h (90%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/CLFieldsCommon.cpp (99%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/CLFieldsCommon.h (98%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/CSPAttacher.cpp (98%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/CSPAttacher.h (95%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/CertFields.cpp (99%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/CrlFields.cpp (99%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/DecodedCert.cpp (98%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/DecodedCert.h (95%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/DecodedCrl.cpp (96%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/DecodedCrl.h (96%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/DecodedExtensions.cpp (99%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/DecodedExtensions.h (98%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/DecodedItem.cpp (97%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/DecodedItem.h (99%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/LockedMap.h (93%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/Session_CRL.cpp (99%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/Session_CSR.cpp (99%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/Session_Cert.cpp (99%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/Session_Crypto.cpp (98%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/clNameUtils.cpp (99%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/clNameUtils.h (98%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/clNssUtils.cpp (99%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/clNssUtils.h (99%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/lib/cldebugging.h (95%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/libsecurity_apple_x509_cl.xcodeproj/project.pbxproj (100%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/mds/cl_common.mdsinfo (100%) rename {libsecurity_apple_x509_cl => Security/libsecurity_apple_x509_cl}/mds/cl_primary.mdsinfo (100%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/Info-security_apple_x509_tp.plist (100%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/AppleTP.cpp (96%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/AppleTP.h (95%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/AppleTPSession.cpp (99%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/AppleTPSession.h (98%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/AppleX509TPBuiltin.cpp (94%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/AppleX509TPPlugin.cpp (94%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/TPCertInfo.cpp (97%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/TPCertInfo.h (99%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/TPCrlInfo.cpp (99%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/TPCrlInfo.h (98%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/TPDatabase.cpp (77%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/TPDatabase.h (95%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/TPNetwork.cpp (99%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/TPNetwork.h (95%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/certGroupUtils.cpp (87%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/certGroupUtils.h (89%) create mode 100644 Security/libsecurity_apple_x509_tp/lib/cuEnc64.c create mode 100644 Security/libsecurity_apple_x509_tp/lib/cuEnc64.h create mode 100644 Security/libsecurity_apple_x509_tp/lib/ocspRequest.cpp create mode 100644 Security/libsecurity_apple_x509_tp/lib/ocspRequest.h rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/tpCertGroup.cpp (99%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/tpCredRequest.cpp (99%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/tpCrlVerify.cpp (99%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/tpCrlVerify.h (97%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/tpOcspCache.cpp (99%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/tpOcspCache.h (96%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/tpOcspCertVfy.cpp (99%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/tpOcspCertVfy.h (96%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/tpOcspVerify.cpp (99%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/tpOcspVerify.h (95%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/tpPolicies.cpp (95%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/tpPolicies.h (96%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/tpTime.c (98%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/tpTime.h (96%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/lib/tpdebugging.h (97%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/libsecurity_apple_x509_tp.xcodeproj/project.pbxproj (100%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/mds/tp_common.mdsinfo (100%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/mds/tp_policyOids.mdsinfo (100%) rename {libsecurity_apple_x509_tp => Security/libsecurity_apple_x509_tp}/mds/tp_primary.mdsinfo (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/APPLE_LICENSE (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/CHANGES.Apple (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/Info-security_asn1.plist (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/Makefile (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/MozillaPublicLicense1.1.html (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/Security (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/README (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/appleoids.asn (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/asn-useful.asn1 (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/pkcs1.asn1 (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/pkcs10.asn (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/pkcs1oids.asn (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/pkcs5.asn1 (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/pkcs7.asn (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/pkcs8.asn (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/pkcs9oids.asn (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/rfc3161.asn1 (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/sm_cms.asn (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/sm_ess.asn (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/sm_vdatypes.asn (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/sm_x411mtsas.asn (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/sm_x411ub.asn (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/sm_x501if.asn (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/sm_x501ud.asn (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/sm_x509af.asn (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/sm_x509ce.asn (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/sm_x509cmn.asn (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/asn1/sm_x520sa.asn (100%) create mode 100644 Security/libsecurity_asn1/config/base.xcconfig rename {libsecurity_asn1 => Security/libsecurity_asn1}/config/debug.xcconfig (100%) create mode 100644 Security/libsecurity_asn1/config/lib.xcconfig rename {libsecurity_asn1 => Security/libsecurity_asn1}/config/release.xcconfig (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/docs/libsecurity_asn1.plist (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/docs/libsecurity_asn1.txt (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/SecAsn1Coder.c (98%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/SecAsn1Coder.h (98%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/SecAsn1Templates.c (99%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/SecAsn1Templates.h (98%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/SecAsn1Types.h (100%) create mode 100644 Security/libsecurity_asn1/lib/SecNssCoder.cpp create mode 100644 Security/libsecurity_asn1/lib/SecNssCoder.h rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/X509Templates.c (98%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/X509Templates.h (98%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/asn1Templates.h (94%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/certExtensionTemplates.c (99%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/certExtensionTemplates.h (99%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/csrTemplates.c (97%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/csrTemplates.h (96%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/keyTemplates.c (99%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/keyTemplates.h (99%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/nameTemplates.c (95%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/nameTemplates.h (98%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/nsprPortX.c (98%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/nssUtils.c (95%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/nssUtils.h (95%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/nssilckt.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/nssilock.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/nsslocks.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/ocspTemplates.c (99%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/ocspTemplates.h (99%) create mode 100644 Security/libsecurity_asn1/lib/oidsalg.c rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/oidsalg.h (98%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/oidsattr.c (98%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/oidsattr.h (99%) create mode 100644 Security/libsecurity_asn1/lib/oidsbase.h rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/oidsocsp.c (96%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/oidsocsp.h (95%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/osKeyTemplates.c (98%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/osKeyTemplates.h (98%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/pkcs12Templates.c (99%) create mode 100644 Security/libsecurity_asn1/lib/pkcs12Templates.h rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/pkcs7Templates.c (98%) create mode 100644 Security/libsecurity_asn1/lib/pkcs7Templates.h rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/plarena.c (99%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/plarena.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/plarenas.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/plstr.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/prbit.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/prcpucfg.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/prcvar.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/prenv.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/prerr.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/prerror.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/prinit.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/prinrval.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/prlock.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/prlog.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/prlong.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/prmem.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/prmon.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/protypes.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/prthread.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/prtime.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/prtypes.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/prvrsion.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/secErrorStr.c (98%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/secasn1.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/secasn1d.c (99%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/secasn1e.c (99%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/secasn1t.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/secasn1u.c (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/seccomon.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/secerr.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/secport.c (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/secport.h (100%) rename {libsecurity_asn1 => Security/libsecurity_asn1}/lib/security_asn1.exp (100%) create mode 100644 Security/libsecurity_asn1/libsecurity_asn1.xcodeproj/project.pbxproj rename {libsecurity_asn1 => Security/libsecurity_asn1}/security_asn1 (100%) rename {libsecurity_authorization => Security/libsecurity_authorization}/APPLE_LICENSE (100%) rename {libsecurity_authorization => Security/libsecurity_authorization}/Info-security_authorization.plist (100%) rename {libsecurity_authorization => Security/libsecurity_authorization}/lib/AuthSession.h (99%) rename {libsecurity_authorization => Security/libsecurity_authorization}/lib/Authorization.c (99%) rename {libsecurity_authorization => Security/libsecurity_authorization}/lib/Authorization.cpp (99%) rename {libsecurity_authorization => Security/libsecurity_authorization}/lib/Authorization.h (99%) rename {libsecurity_authorization => Security/libsecurity_authorization}/lib/AuthorizationDB.h (98%) rename {libsecurity_authorization => Security/libsecurity_authorization}/lib/AuthorizationPlugin.h (99%) rename {libsecurity_authorization => Security/libsecurity_authorization}/lib/AuthorizationPriv.h (99%) rename {libsecurity_authorization => Security/libsecurity_authorization}/lib/AuthorizationTags.h (98%) rename {libsecurity_authorization => Security/libsecurity_authorization}/lib/AuthorizationTagsPriv.h (99%) rename {libsecurity_authorization => Security/libsecurity_authorization}/lib/privPort.h (95%) rename {libsecurity_authorization => Security/libsecurity_authorization}/lib/security_authorization.exp (95%) rename {libsecurity_authorization => Security/libsecurity_authorization}/lib/trampolineClient.cpp (99%) rename {libsecurity_authorization => Security/libsecurity_authorization}/lib/trampolineServer.cpp (96%) rename {libsecurity_authorization => Security/libsecurity_authorization}/libsecurity_authorization.xcodeproj/project.pbxproj (100%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/Info-security_cdsa_client.plist (100%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/DLDBList.cpp (96%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/DLDBList.h (97%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/aclclient.cpp (99%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/aclclient.h (98%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/clclient.cpp (95%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/clclient.h (96%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/cryptoclient.cpp (97%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/cryptoclient.h (97%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/cspclient.cpp (98%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/cspclient.h (99%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/cssmclient.cpp (99%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/cssmclient.h (99%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/dl_standard.cpp (98%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/dl_standard.h (98%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/dlclient.cpp (99%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/dlclient.h (99%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/dlclientpriv.cpp (95%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/dliterators.cpp (98%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/dliterators.h (99%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/dlquery.cpp (98%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/dlquery.h (98%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/genkey.cpp (97%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/genkey.h (97%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/keychainacl.cpp (98%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/keychainacl.h (97%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/keyclient.cpp (97%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/keyclient.h (98%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/macclient.cpp (96%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/macclient.h (97%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/mds_standard.cpp (99%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/mds_standard.h (98%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/mdsclient.cpp (98%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/mdsclient.h (98%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/multidldb.cpp (98%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/multidldb.h (97%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/securestorage.cpp (99%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/securestorage.h (99%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/signclient.cpp (96%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/signclient.h (97%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/tpclient.cpp (97%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/tpclient.h (97%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/wrapkey.cpp (98%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/lib/wrapkey.h (98%) rename {libsecurity_cdsa_client => Security/libsecurity_cdsa_client}/libsecurity_cdsa_client.xcodeproj/project.pbxproj (100%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/Info-security_cdsa_plugin.plist (100%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/ACsession.h (96%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/CLsession.h (96%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/CSPsession.cpp (99%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/CSPsession.h (99%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/DLsession.cpp (97%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/DLsession.h (96%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/Database.cpp (99%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/Database.h (99%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/DatabaseSession.cpp (99%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/DatabaseSession.h (98%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/DbContext.cpp (95%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/DbContext.h (97%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/TPsession.h (96%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/c++plugin.h (95%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/csputilities.cpp (98%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/cssmplugin.cpp (98%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/cssmplugin.h (98%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/generator.cfg (100%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/generator.mk (100%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/generator.pl (100%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/pluginsession.cpp (97%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/pluginsession.h (98%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/lib/pluginspi.h (98%) rename {libsecurity_cdsa_plugin => Security/libsecurity_cdsa_plugin}/libsecurity_cdsa_plugin.xcodeproj/project.pbxproj (100%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/APPLE_LICENSE (100%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/Info-security_cdsa_utilities.plist (100%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/AuthorizationData.cpp (99%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/AuthorizationData.h (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/AuthorizationWalkers.h (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/KeySchema.h (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/KeySchema.m4 (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/Schema.h (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/Schema.m4 (99%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/acl_any.cpp (96%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/acl_any.h (96%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/acl_codesigning.cpp (99%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/acl_codesigning.h (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/acl_comment.cpp (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/acl_comment.h (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/acl_password.cpp (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/acl_password.h (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/acl_preauth.cpp (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/acl_preauth.h (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/acl_process.cpp (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/acl_process.h (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/acl_prompted.cpp (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/acl_prompted.h (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/acl_protectedpw.cpp (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/acl_protectedpw.h (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/acl_secret.cpp (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/acl_secret.h (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/acl_threshold.cpp (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/acl_threshold.h (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/aclsubject.cpp (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/aclsubject.h (99%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/callback.cpp (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/callback.h (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/constdata.cpp (95%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/constdata.h (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/context.cpp (99%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/context.h (93%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmacl.cpp (94%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmacl.h (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmaclpod.cpp (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmaclpod.h (99%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmalloc.cpp (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmalloc.h (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmbridge.h (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmcert.cpp (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmcert.h (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmcred.cpp (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmcred.h (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmdata.cpp (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmdata.h (99%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmdates.cpp (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmdates.h (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmdb.cpp (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmdb.h (99%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmdbname.cpp (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmdbname.h (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmendian.cpp (96%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmendian.h (95%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmerrors.cpp (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmerrors.h (96%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmkey.cpp (96%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmkey.h (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmlist.cpp (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmlist.h (99%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmpods.cpp (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmpods.h (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmtrust.cpp (95%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmtrust.h (99%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmwalkers.cpp (94%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/cssmwalkers.h (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/db++.cpp (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/db++.h (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/digestobject.h (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/generator.mk (100%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/generator.pl (100%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/handleobject.cpp (94%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/handleobject.h (95%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/handletemplates.cpp (95%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/handletemplates.h (99%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/handletemplates_defs.h (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/objectacl.cpp (99%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/objectacl.h (99%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/osxverifier.cpp (98%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/osxverifier.h (97%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/u32handleobject.cpp (94%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/u32handleobject.h (95%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/uniformrandom.cpp (94%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/uniformrandom.h (96%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/walkers.cpp (95%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/lib/walkers.h (99%) rename {libsecurity_cdsa_utilities => Security/libsecurity_cdsa_utilities}/libsecurity_cdsa_utilities.xcodeproj/project.pbxproj (100%) rename {libsecurity_cdsa_utils => Security/libsecurity_cdsa_utils}/Info-security_cdsa_utils.plist (100%) rename {libsecurity_cdsa_utils => Security/libsecurity_cdsa_utils}/lib/cuCdsaUtils.cpp (99%) rename {libsecurity_cdsa_utils => Security/libsecurity_cdsa_utils}/lib/cuCdsaUtils.h (98%) rename {libsecurity_cdsa_utils => Security/libsecurity_cdsa_utils}/lib/cuDbUtils.cpp (99%) rename {libsecurity_cdsa_utils => Security/libsecurity_cdsa_utils}/lib/cuDbUtils.h (96%) create mode 100644 Security/libsecurity_cdsa_utils/lib/cuEnc64.c create mode 100644 Security/libsecurity_cdsa_utils/lib/cuEnc64.h rename {libsecurity_cdsa_utils => Security/libsecurity_cdsa_utils}/lib/cuFileIo.c (96%) rename {libsecurity_cdsa_utils => Security/libsecurity_cdsa_utils}/lib/cuFileIo.h (94%) rename {libsecurity_cdsa_utils => Security/libsecurity_cdsa_utils}/lib/cuOidParser.cpp (99%) rename {libsecurity_cdsa_utils => Security/libsecurity_cdsa_utils}/lib/cuOidParser.h (96%) rename {libsecurity_cdsa_utils => Security/libsecurity_cdsa_utils}/lib/cuPem.cpp (98%) rename {libsecurity_cdsa_utils => Security/libsecurity_cdsa_utils}/lib/cuPem.h (95%) rename {libsecurity_cdsa_utils => Security/libsecurity_cdsa_utils}/lib/cuPrintCert.cpp (99%) rename {libsecurity_cdsa_utils => Security/libsecurity_cdsa_utils}/lib/cuPrintCert.h (96%) rename {libsecurity_cdsa_utils => Security/libsecurity_cdsa_utils}/lib/cuTimeStr.cpp (98%) rename {libsecurity_cdsa_utils => Security/libsecurity_cdsa_utils}/lib/cuTimeStr.h (96%) rename {libsecurity_cdsa_utils => Security/libsecurity_cdsa_utils}/libsecurity_cdsa_utils.xcodeproj/project.pbxproj (100%) rename {libsecurity_checkpw => Security/libsecurity_checkpw}/APPLE_LICENSE (100%) rename {libsecurity_checkpw => Security/libsecurity_checkpw}/Info-security_checkpw.plist (100%) rename {libsecurity_checkpw => Security/libsecurity_checkpw}/checkpw.pam (100%) rename {libsecurity_checkpw => Security/libsecurity_checkpw}/lib/checkpw.c (97%) rename {libsecurity_checkpw => Security/libsecurity_checkpw}/lib/checkpw.h (96%) rename {libsecurity_checkpw => Security/libsecurity_checkpw}/lib/security_checkpw.exp (100%) rename {libsecurity_checkpw => Security/libsecurity_checkpw}/libsecurity_checkpw.xcodeproj/project.pbxproj (100%) rename {libsecurity_checkpw => Security/libsecurity_checkpw}/test/perf-checkpw.c (100%) rename {libsecurity_checkpw => Security/libsecurity_checkpw}/test/test-checkpw.c (100%) rename {libsecurity_cms => Security/libsecurity_cms}/APPLE_LICENSE (100%) rename {libsecurity_cms => Security/libsecurity_cms}/Info-security_cms.plist (100%) rename {libsecurity_cms => Security/libsecurity_cms}/lib/CMSDecoder.cpp (98%) rename {libsecurity_cms => Security/libsecurity_cms}/lib/CMSDecoder.h (93%) rename {libsecurity_cms => Security/libsecurity_cms}/lib/CMSEncoder.cpp (98%) rename {libsecurity_cms => Security/libsecurity_cms}/lib/CMSEncoder.h (97%) rename {libsecurity_cms => Security/libsecurity_cms}/lib/CMSPrivate.h (98%) rename {libsecurity_cms => Security/libsecurity_cms}/lib/CMSUtils.cpp (97%) rename {libsecurity_cms => Security/libsecurity_cms}/lib/CMSUtils.h (97%) rename {libsecurity_cms => Security/libsecurity_cms}/lib/security_cms.exp (93%) rename {libsecurity_cms => Security/libsecurity_cms}/libsecurity_cms.xcodeproj/project.pbxproj (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/APPLE_LICENSE (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/CodeSigningHelper/CodeSigningHelper-Info.plist (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/CodeSigningHelper/com.apple.CodeSigningHelper.sb (100%) create mode 100644 Security/libsecurity_codesigning/CodeSigningHelper/main.c rename {libsecurity_codesigning => Security/libsecurity_codesigning}/Info-security_codesigning.plist (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/AUTHORS (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/ChangeLog (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/LICENSE.txt (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/Makefile.in (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/README (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/TODO (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr.jar (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/ANTLRException.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/ANTLRUtil.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/AST.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/ASTArray.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/ASTFactory.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/ASTNULLType.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/ASTPair.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/ASTRefCount.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/BaseAST.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/BitSet.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/CharBuffer.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/CharInputBuffer.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/CharScanner.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/CharStreamException.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/CharStreamIOException.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/CircularQueue.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/CommonAST.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/CommonASTWithHiddenTokens.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/CommonHiddenStreamToken.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/CommonToken.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/IOException.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/InputBuffer.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/LLkParser.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/LexerSharedInputState.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/Makefile.in (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/MismatchedCharException.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/MismatchedTokenException.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/NoViableAltException.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/NoViableAltForCharException.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/Parser.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/ParserSharedInputState.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/RecognitionException.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/RefCount.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/SemanticException.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/String.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/Token.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/TokenBuffer.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/TokenRefCount.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/TokenStream.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/TokenStreamBasicFilter.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/TokenStreamException.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/TokenStreamHiddenTokenFilter.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/TokenStreamIOException.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/TokenStreamRecognitionException.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/TokenStreamRetryException.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/TokenStreamRewriteEngine.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/TokenStreamSelector.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/TokenWithIndex.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/TreeParser.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/TreeParserSharedInputState.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/antlr/config.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/contrib/bcb4/README (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/contrib/bcb4/antlr.bpr (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/contrib/bcb4/antlr.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/doxygen.cfg (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/libsecurity_codesigning.plist (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/libsecurity_codesigning.txt (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/scripts/cr_stripper.sh (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/scripts/make_change_log.tcl (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/ANTLRUtil.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/ASTFactory.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/ASTNULLType.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/ASTRefCount.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/BaseAST.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/BitSet.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/CharBuffer.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/CharScanner.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/CommonAST.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/CommonASTWithHiddenTokens.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/CommonHiddenStreamToken.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/CommonToken.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/InputBuffer.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/LLkParser.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/Makefile.in (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/MismatchedCharException.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/MismatchedTokenException.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/NoViableAltException.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/NoViableAltForCharException.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/Parser.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/RecognitionException.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/String.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/Token.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/TokenBuffer.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/TokenRefCount.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/TokenStreamBasicFilter.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/TokenStreamHiddenTokenFilter.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/TokenStreamRewriteEngine.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/TokenStreamSelector.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/TreeParser.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/antlr2/src/dll.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/dtrace/codesign-watch.d (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/dtrace/reqint.d (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/dtrace/sp-watch.d (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/gke/com.apple.gkreport.plist (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/gke/gkclear (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/gke/gkgenerate (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/gke/gkhandmake (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/gke/gklist (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/gke/gkmerge (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/gke/gkrecord (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/gke/gkreport (79%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/gke/gkunpack.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/CSCommon.h (95%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/CSCommonPriv.h (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/Code.cpp (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/Code.h (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/CodeSigner.cpp (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/CodeSigner.h (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/CodeSigning.h (95%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/RequirementKeywords.h (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/RequirementLexer.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/RequirementLexer.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/RequirementParser.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/RequirementParser.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/RequirementParserTokenTypes.hpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/RequirementParserTokenTypes.txt (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/Requirements.cpp (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/Requirements.h (96%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecAssessment.cpp (95%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecAssessment.h (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecCode.cpp (99%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecCode.h (99%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecCodeHost.cpp (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecCodeHost.h (99%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecCodeHostLib.c (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecCodeHostLib.h (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecCodePriv.h (99%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecCodeSigner.cpp (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecCodeSigner.h (99%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecIntegrity.cpp (94%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecIntegrity.h (96%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecIntegrityLib.c (94%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecIntegrityLib.h (96%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecRequirement.cpp (99%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecRequirement.h (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecRequirementPriv.h (99%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecStaticCode.cpp (92%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecStaticCode.h (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecStaticCodePriv.h (81%) create mode 100644 Security/libsecurity_codesigning/lib/SecTask.c create mode 100644 Security/libsecurity_codesigning/lib/SecTask.h rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/SecTaskPriv.h (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/StaticCode.cpp (90%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/StaticCode.h (90%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/antlrplugin.cpp (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/antlrplugin.h (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/bundlediskrep.cpp (99%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/bundlediskrep.h (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/cdbuilder.cpp (99%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/cdbuilder.h (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/codedirectory.cpp (99%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/codedirectory.h (99%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/cs.cpp (96%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/cs.h (96%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/cscdefs.c (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/cscdefs.h (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/csdatabase.cpp (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/csdatabase.h (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/cserror.cpp (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/cserror.h (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/csgeneric.cpp (99%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/csgeneric.h (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/cskernel.cpp (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/cskernel.h (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/csprocess.cpp (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/csprocess.h (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/csutilities.cpp (99%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/csutilities.h (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/detachedrep.cpp (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/detachedrep.h (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/dirscanner.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/dirscanner.h (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/diskrep.cpp (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/diskrep.h (95%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/drmaker.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/drmaker.h (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/filediskrep.cpp (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/filediskrep.h (97%) create mode 100644 Security/libsecurity_codesigning/lib/gkoverride.m rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/kerneldiskrep.cpp (96%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/kerneldiskrep.h (96%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/machorep.cpp (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/machorep.h (98%) create mode 100644 Security/libsecurity_codesigning/lib/opaquewhitelist.cpp rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/opaquewhitelist.h (91%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/piddiskrep.cpp (92%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/piddiskrep.h (94%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/policydb.cpp (92%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/policydb.h (94%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/policyengine.cpp (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/policyengine.h (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/quarantine++.cpp (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/quarantine++.h (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/reqdumper.cpp (99%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/reqdumper.h (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/reqinterp.cpp (99%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/reqinterp.h (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/reqmaker.cpp (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/reqmaker.h (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/reqparser.cpp (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/reqparser.h (96%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/reqreader.cpp (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/reqreader.h (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/requirement.cpp (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/requirement.h (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/resources.cpp (96%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/resources.h (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/security_codesigning.d (99%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/security_codesigning.exp (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/sigblob.cpp (96%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/sigblob.h (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/signer.cpp (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/signer.h (96%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/signerutils.cpp (99%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/signerutils.h (99%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/singlediskrep.cpp (96%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/singlediskrep.h (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/slcrep.cpp (98%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/slcrep.h (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/syspolicy.sql (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/xar++.cpp (97%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/xar++.h (96%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/xpcengine.cpp (82%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/lib/xpcengine.h (96%) create mode 100644 Security/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj rename {libsecurity_codesigning => Security/libsecurity_codesigning}/req/cfm.ireqs (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/req/ppc-host.ireq (100%) rename {libsecurity_codesigning => Security/libsecurity_codesigning}/requirements.grammar (100%) rename {libsecurity_comcryption => Security/libsecurity_comcryption}/Info-security_comcryption.plist (100%) rename {libsecurity_comcryption => Security/libsecurity_comcryption}/lib/comDebug.h (99%) rename {libsecurity_comcryption => Security/libsecurity_comcryption}/lib/comcryptPriv.c (90%) rename {libsecurity_comcryption => Security/libsecurity_comcryption}/lib/comcryptPriv.h (92%) rename {libsecurity_comcryption => Security/libsecurity_comcryption}/lib/comcryption.c (97%) rename {libsecurity_comcryption => Security/libsecurity_comcryption}/lib/comcryption.h (81%) rename {libsecurity_comcryption => Security/libsecurity_comcryption}/libsecurity_comcryption.xcodeproj/project.pbxproj (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/Info-security_cryptkit.plist (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/ckutils/Makefile (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/ckutils/Makefile.common (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/ckutils/atomTime/Makefile (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/ckutils/atomTime/atomTime.c (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/ckutils/badsig/Makefile (100%) create mode 100644 Security/libsecurity_cryptkit/ckutils/badsig/badsig.c rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/ckutils/blobtest/Makefile (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/ckutils/blobtest/blobtest.c (87%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/ckutils/cfileTest/Makefile (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/ckutils/cfileTest/cfileTest.c (92%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/ckutils/ckutilsPlatform.h (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/ckutils/giantAsmBench/Makefile (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/ckutils/giantAsmBench/giantAsmBench.c (83%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/ckutils/giantBench/Makefile (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/ckutils/giantBench/giantBench.c (83%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/ckutils/giantDvt/Makefile (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/ckutils/giantDvt/giantDvt.c (92%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/ckutils/sigTime/Makefile (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/ckutils/sigTime/sigTime.cpp (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/ByteRep.txt (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CipherFileDES.c (97%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CipherFileDES.h (87%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CipherFileFEED.c (96%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CipherFileFEED.h (87%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CipherFileTypes.h (88%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/Crypt.h (83%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CryptKit.def (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CryptKit.h (80%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CryptKitAsn1.cpp (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CryptKitAsn1.h (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CryptKitDER.cpp (99%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CryptKitDER.h (82%) create mode 100644 Security/libsecurity_cryptkit/lib/CryptKitSA.h rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CurveParamDocs/FEEDaffine.nb (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CurveParamDocs/FEEDsansY.nb (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CurveParamDocs/README (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CurveParamDocs/curvegen.c (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CurveParamDocs/curverecords.nb (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CurveParamDocs/disc.h (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CurveParamDocs/ellproj.c (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CurveParamDocs/ellproj.h (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CurveParamDocs/factor.c (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CurveParamDocs/fmodule.c (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CurveParamDocs/fmodule.h (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CurveParamDocs/giants.c (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CurveParamDocs/giants.h (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CurveParamDocs/schoof.c (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CurveParamDocs/schoofs.c (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CurveParamDocs/tools.c (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/CurveParamDocs/tools.h (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/ECDSA_Profile.h (86%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/ECDSA_Verify_Prefix.h (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/HmacSha1Legacy.c (96%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/HmacSha1Legacy.h (92%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/Mathematica.FEE (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/NSCipherFile.h (93%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/NSCipherFile.m (96%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/NSCryptors.h (90%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/NSDESCryptor.h (81%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/NSDESCryptor.m (90%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/NSFEEPublicKey.h (88%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/NSFEEPublicKey.m (97%) create mode 100644 Security/libsecurity_cryptkit/lib/NSFEEPublicKeyPrivate.h rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/NSMD5Hash.h (75%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/NSMD5Hash.m (84%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/NSRandomNumberGenerator.h (76%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/NSRandomNumberGenerator.m (85%) create mode 100644 Security/libsecurity_cryptkit/lib/README rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/TOP_README (95%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/buildSrcTree (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/byteRep.c (96%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/byteRep.h (87%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/changes (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/ckDES.c (97%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/ckDES.h (84%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/ckMD5.c (97%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/ckMD5.h (87%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/ckSHA1.c (94%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/ckSHA1.h (84%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/ckSHA1_priv.c (97%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/ckSHA1_priv.h (84%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/ckconfig.h (91%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/ckutilities.c (95%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/ckutilities.h (80%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/curveParamData.h (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/curveParamDataOld.h (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/curveParams.c (98%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/curveParams.h (93%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/elliptic.c (97%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/elliptic.h (93%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/ellipticMeasure.h (85%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/ellipticProj.c (97%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/ellipticProj.h (88%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/enc64.c (97%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/enc64.h (86%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/engineNSA127.c (96%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/falloc.c (88%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/falloc.h (82%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feeCipherFile.c (95%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feeCipherFile.h (95%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feeCipherFileAtom.c (97%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feeDES.c (97%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feeDES.h (92%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feeDebug.h (93%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feeDigitalSignature.c (97%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feeDigitalSignature.h (91%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feeECDSA.c (97%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feeECDSA.h (88%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feeFEED.c (98%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feeFEED.h (93%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feeFEEDExp.c (97%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feeFEEDExp.h (93%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feeFunctions.h (82%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feeHash.c (89%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feeHash.h (86%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feePublicKey.c (98%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feePublicKey.h (96%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feePublicKeyPrivate.h (79%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feeRandom.c (93%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feeRandom.h (81%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/feeTypes.h (93%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/giantFFT.c (97%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/giantIntegers.c (97%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/giantIntegers.h (93%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/giantPortCommon.h (82%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/giantPort_Generic.h (93%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/giantPort_PPC.c (95%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/giantPort_PPC.h (91%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/giantPort_PPC_Gnu.h (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/giantPort_PPC_Gnu.s (86%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/giantPort_i486.h (92%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/giantPort_i486.s (92%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/mutils.h (76%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/mutils.m (81%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/platform.c (93%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/platform.h (86%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/lib/unixMakefile (100%) rename {libsecurity_cryptkit => Security/libsecurity_cryptkit}/libsecurity_cryptkit.xcodeproj/project.pbxproj (100%) rename {libsecurity_cssm => Security/libsecurity_cssm}/APPLE_LICENSE (100%) rename {libsecurity_cssm => Security/libsecurity_cssm}/Info-security_cssm.plist (100%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/attachfactory.cpp (98%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/attachfactory.h (97%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/attachment.cpp (99%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/attachment.h (98%) create mode 100644 Security/libsecurity_cssm/lib/certextensions.h rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cspattachment.cpp (94%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cspattachment.h (95%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cssm.cpp (99%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cssm.h (94%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cssmaci.h (96%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cssmapi.h (99%) create mode 100644 Security/libsecurity_cssm/lib/cssmapple.h rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cssmapplePriv.h (98%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cssmcli.h (99%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cssmconfig.h (96%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cssmcontext.cpp (99%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cssmcontext.h (98%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cssmcspi.h (99%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cssmdli.h (98%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cssmerr.h (99%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cssmint.h (97%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cssmkrapi.h (99%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cssmkrspi.h (98%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cssmmds.cpp (95%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cssmmds.h (96%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cssmspi.h (98%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cssmtpi.h (99%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/cssmtype.h (99%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/eisl.h (99%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/emmspi.h (98%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/emmtype.h (96%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/generator.cfg (100%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/generator.mk (95%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/generator.pl (98%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/guids.cpp (98%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/manager.cpp (99%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/manager.h (98%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/modload_plugin.cpp (98%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/modload_plugin.h (96%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/modload_static.cpp (97%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/modload_static.h (96%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/modloader.cpp (98%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/modloader.h (97%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/module.cpp (98%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/module.h (97%) create mode 100644 Security/libsecurity_cssm/lib/oidsalg.c create mode 100644 Security/libsecurity_cssm/lib/oidsbase.h rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/oidscert.cpp (97%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/oidscert.h (97%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/oidscrl.cpp (98%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/oidscrl.h (98%) rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/security_cssm.exp (99%) create mode 100644 Security/libsecurity_cssm/lib/transition.cpp rename {libsecurity_cssm => Security/libsecurity_cssm}/lib/x509defs.h (99%) rename {libsecurity_cssm => Security/libsecurity_cssm}/libsecurity_cssm.xcodeproj/project.pbxproj (100%) rename {libsecurity_cssm => Security/libsecurity_cssm}/mds/cssm.mdsinfo (100%) rename {libsecurity_filedb => Security/libsecurity_filedb}/Info-security_filedb.plist (100%) rename {libsecurity_filedb => Security/libsecurity_filedb}/lib/AppleDatabase.cpp (99%) rename {libsecurity_filedb => Security/libsecurity_filedb}/lib/AppleDatabase.h (99%) rename {libsecurity_filedb => Security/libsecurity_filedb}/lib/AtomicFile.cpp (99%) rename {libsecurity_filedb => Security/libsecurity_filedb}/lib/AtomicFile.h (98%) rename {libsecurity_filedb => Security/libsecurity_filedb}/lib/DbIndex.cpp (99%) rename {libsecurity_filedb => Security/libsecurity_filedb}/lib/DbIndex.h (98%) rename {libsecurity_filedb => Security/libsecurity_filedb}/lib/DbQuery.cpp (93%) rename {libsecurity_filedb => Security/libsecurity_filedb}/lib/DbQuery.h (94%) rename {libsecurity_filedb => Security/libsecurity_filedb}/lib/DbValue.cpp (99%) rename {libsecurity_filedb => Security/libsecurity_filedb}/lib/DbValue.h (98%) rename {libsecurity_filedb => Security/libsecurity_filedb}/lib/MetaAttribute.cpp (98%) rename {libsecurity_filedb => Security/libsecurity_filedb}/lib/MetaAttribute.h (98%) rename {libsecurity_filedb => Security/libsecurity_filedb}/lib/MetaRecord.cpp (99%) rename {libsecurity_filedb => Security/libsecurity_filedb}/lib/MetaRecord.h (98%) rename {libsecurity_filedb => Security/libsecurity_filedb}/lib/OverUnderflowCheck.h (100%) rename {libsecurity_filedb => Security/libsecurity_filedb}/lib/ReadWriteSection.cpp (100%) rename {libsecurity_filedb => Security/libsecurity_filedb}/lib/ReadWriteSection.h (98%) rename {libsecurity_filedb => Security/libsecurity_filedb}/lib/SelectionPredicate.cpp (96%) rename {libsecurity_filedb => Security/libsecurity_filedb}/lib/SelectionPredicate.h (95%) rename {libsecurity_filedb => Security/libsecurity_filedb}/libsecurity_filedb.xcodeproj/project.pbxproj (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/APPLE_LICENSE (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/Info-security_keychain.plist (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/Security (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/ACL.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/ACL.h (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/Access.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/Access.h (98%) create mode 100644 Security/libsecurity_keychain/lib/AppleBaselineEscrowCertificates.h rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/CCallbackMgr.cp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/CCallbackMgr.h (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/Certificate.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/Certificate.h (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/CertificateRequest.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/CertificateRequest.h (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/CertificateValues.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/CertificateValues.h (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/DLDBListCFPref.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/DLDBListCFPref.h (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/DynamicDLDBList.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/DynamicDLDBList.h (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/ExtendedAttribute.cpp (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/ExtendedAttribute.h (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/Globals.cpp (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/Globals.h (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/Identity.cpp (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/Identity.h (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/IdentityCursor.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/IdentityCursor.h (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/Item.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/Item.h (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/KCCursor.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/KCCursor.h (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/KCEventNotifier.cpp (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/KCEventNotifier.h (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/KCExceptions.h (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/KCUtilities.cpp (94%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/KCUtilities.h (94%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/KeyItem.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/KeyItem.h (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/Keychains.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/Keychains.h (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/MacOSErrorStrings.h (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/Password.cpp (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/Password.h (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/Policies.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/Policies.h (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/PolicyCursor.cpp (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/PolicyCursor.h (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/PrimaryKey.cpp (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/PrimaryKey.h (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecACL.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecACL.h (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecAccess.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecAccess.h (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecAccessPriv.h (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecAsn1TypesP.h (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecBase.cpp (99%) create mode 100644 Security/libsecurity_keychain/lib/SecBase.h rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecBase64P.c (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecBase64P.h (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecBaseP.h (97%) create mode 100644 Security/libsecurity_keychain/lib/SecBasePriv.h rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecBridge.h (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecCFTypes.cpp (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecCFTypes.h (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecCertificate.cpp (83%) create mode 100644 Security/libsecurity_keychain/lib/SecCertificate.h rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecCertificateBundle.cpp (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecCertificateBundle.h (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecCertificateInternalP.h (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecCertificateOIDs.h (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecCertificateP.c (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecCertificateP.h (98%) create mode 100644 Security/libsecurity_keychain/lib/SecCertificatePriv.h rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecCertificatePrivP.h (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecCertificateRequest.cpp (98%) create mode 100644 Security/libsecurity_keychain/lib/SecCertificateRequest.h rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecExport.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecExternalRep.cpp (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecExternalRep.h (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecFDERecoveryAsymmetricCrypto.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecFDERecoveryAsymmetricCrypto.h (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecFrameworkP.c (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecFrameworkP.h (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecIdentity.cpp (99%) create mode 100644 Security/libsecurity_keychain/lib/SecIdentity.h create mode 100644 Security/libsecurity_keychain/lib/SecIdentityPriv.h rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecIdentitySearch.cpp (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecIdentitySearch.h (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecIdentitySearchPriv.h (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecImport.cpp (99%) create mode 100644 Security/libsecurity_keychain/lib/SecImportExport.c create mode 100644 Security/libsecurity_keychain/lib/SecImportExport.h rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecImportExportAgg.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecImportExportAgg.h (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecImportExportCrypto.cpp (92%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecImportExportCrypto.h (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecImportExportOpenSSH.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecImportExportOpenSSH.h (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecImportExportPem.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecImportExportPem.h (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecImportExportPkcs8.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecImportExportPkcs8.h (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecImportExportUtils.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecImportExportUtils.h (99%) create mode 100644 Security/libsecurity_keychain/lib/SecInternal.h rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecInternalP.h (95%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecItem.cpp (97%) create mode 100644 Security/libsecurity_keychain/lib/SecItem.h create mode 100644 Security/libsecurity_keychain/lib/SecItemConstants.c create mode 100644 Security/libsecurity_keychain/lib/SecItemPriv.h rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecKey.cpp (97%) create mode 100644 Security/libsecurity_keychain/lib/SecKey.h create mode 100644 Security/libsecurity_keychain/lib/SecKeyPriv.h rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecKeychain.cpp (84%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecKeychain.h (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecKeychainAddIToolsPassword.cpp (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecKeychainItem.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecKeychainItem.h (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecKeychainItemExtendedAttributes.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecKeychainItemExtendedAttributes.h (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecKeychainItemPriv.h (99%) create mode 100644 Security/libsecurity_keychain/lib/SecKeychainPriv.h rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecKeychainSearch.cpp (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecKeychainSearch.h (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecKeychainSearchPriv.h (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecNetscapeTemplates.cpp (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecNetscapeTemplates.h (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecPassword.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecPassword.h (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecPkcs8Templates.cpp (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecPkcs8Templates.h (98%) create mode 100644 Security/libsecurity_keychain/lib/SecPolicy.cpp create mode 100644 Security/libsecurity_keychain/lib/SecPolicy.h create mode 100644 Security/libsecurity_keychain/lib/SecPolicyPriv.h rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecPolicySearch.cpp (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecPolicySearch.h (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecRSAKeyP.h (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecRandom.c (97%) create mode 100644 Security/libsecurity_keychain/lib/SecRandom.h rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecRandomP.h (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecRecoveryPassword.c (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecRecoveryPassword.h (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecTrust.cpp (99%) create mode 100644 Security/libsecurity_keychain/lib/SecTrust.h create mode 100644 Security/libsecurity_keychain/lib/SecTrustPriv.h rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecTrustSettings.cpp (97%) create mode 100644 Security/libsecurity_keychain/lib/SecTrustSettings.h create mode 100644 Security/libsecurity_keychain/lib/SecTrustSettingsPriv.h rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecTrustedApplication.cpp (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecTrustedApplication.h (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecTrustedApplicationPriv.h (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/SecWrappedKeys.cpp (99%) create mode 100644 Security/libsecurity_keychain/lib/Security.h rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/StorageManager.cpp (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/StorageManager.h (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/Trust.cpp (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/Trust.h (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/TrustAdditions.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/TrustAdditions.h (95%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/TrustItem.cpp (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/TrustItem.h (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/TrustKeychains.h (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/TrustRevocation.cpp (95%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/TrustSettings.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/TrustSettings.h (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/TrustSettingsSchema.h (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/TrustSettingsUtils.cpp (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/TrustSettingsUtils.h (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/TrustStore.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/TrustStore.h (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/TrustedApplication.cpp (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/TrustedApplication.h (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/UnlockReferralItem.cpp (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/UnlockReferralItem.h (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/certextensionsP.h (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/cssmdatetime.cpp (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/cssmdatetime.h (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/defaultcreds.cpp (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/defaultcreds.h (97%) create mode 100644 Security/libsecurity_keychain/lib/generateErrStrings.pl rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/security_keychain.exp (97%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/tsaDERUtilities.c (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/lib/tsaDERUtilities.h (95%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/README.txt (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/Tests/AppleMobilePersonalizedTicket.h (86%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/Tests/DER_Ticket.c (85%) create mode 100644 Security/libsecurity_keychain/libDER/Tests/DER_Ticket.h rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/Tests/certsCrls/EndCertificateCP.01.01.crt (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/Tests/certsCrls/Test_CRL_CA1.crl (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/Tests/certsCrls/Test_CRL_CA1.crl.pem (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/Tests/certsCrls/TrustAnchorCP.01.01.crt (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/Tests/certsCrls/TrustAnchorCRLCP.01.01.crl (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/Tests/certsCrls/apple_v3.000.cer (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/Tests/certsCrls/apple_v3.001.cer (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/Tests/certsCrls/entrust_v3.100.cer (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/Tests/certsCrls/entrust_v3.101.cer (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/Tests/certsCrls/keybank_v3.100.cer (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/Tests/certsCrls/keybank_v3.101.cer (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/Tests/certsCrls/keybank_v3.102.cer (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/Tests/parseCert.c (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/Tests/parseCrl.c (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/Tests/parseTicket.c (100%) create mode 100644 Security/libsecurity_keychain/libDER/config/base.xcconfig rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/config/debug.xcconfig (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/config/lib.xcconfig (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/config/release.xcconfig (100%) create mode 100644 Security/libsecurity_keychain/libDER/libDER.xcodeproj/project.pbxproj rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/libDER/DER_CertCrl.c (90%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/libDER/DER_CertCrl.h (87%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/libDER/DER_Decode.c (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/libDER/DER_Decode.h (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/libDER/DER_Digest.c (82%) create mode 100644 Security/libsecurity_keychain/libDER/libDER/DER_Digest.h rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/libDER/DER_Encode.c (88%) create mode 100644 Security/libsecurity_keychain/libDER/libDER/DER_Encode.h rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/libDER/DER_Keys.c (80%) create mode 100644 Security/libsecurity_keychain/libDER/libDER/DER_Keys.h create mode 100644 Security/libsecurity_keychain/libDER/libDER/asn1Types.h create mode 100644 Security/libsecurity_keychain/libDER/libDER/libDER.h create mode 100644 Security/libsecurity_keychain/libDER/libDER/libDER_config.h rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/libDER/oids.c (81%) create mode 100644 Security/libsecurity_keychain/libDER/libDER/oids.h create mode 100644 Security/libsecurity_keychain/libDER/libDERUtils/fileIo.c create mode 100644 Security/libsecurity_keychain/libDER/libDERUtils/fileIo.h create mode 100644 Security/libsecurity_keychain/libDER/libDERUtils/libDERUtils.c create mode 100644 Security/libsecurity_keychain/libDER/libDERUtils/libDERUtils.h rename {libsecurity_keychain => Security/libsecurity_keychain}/libDER/libDERUtils/printFields.c (87%) create mode 100644 Security/libsecurity_keychain/libDER/libDERUtils/printFields.h create mode 100644 Security/libsecurity_keychain/libsecurity_keychain.xcodeproj/project.pbxproj rename {libsecurity_keychain => Security/libsecurity_keychain}/plist/iToolsTrustedApps.plist (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/regressions/kc-40-seckey.c (80%) rename {libsecurity_keychain => Security/libsecurity_keychain}/regressions/kc-41-sececkey.c (91%) create mode 100644 Security/libsecurity_keychain/regressions/kc-42-trust-revocation.c rename {libsecurity_keychain => Security/libsecurity_keychain}/regressions/keychain_regressions.h (87%) create mode 100644 Security/libsecurity_keychain/regressions/si-33-keychain-backup.c rename {libsecurity_keychain => Security/libsecurity_keychain}/xpc-tsa/XPCTimeStampingService-Info.plist (100%) rename {libsecurity_keychain => Security/libsecurity_keychain}/xpc-tsa/main-tsa.m (99%) rename {libsecurity_keychain => Security/libsecurity_keychain}/xpc-tsa/timestampclient.h (96%) rename {libsecurity_keychain => Security/libsecurity_keychain}/xpc-tsa/timestampclient.m (98%) rename {libsecurity_keychain => Security/libsecurity_keychain}/xpc/XPCKeychainSandboxCheck-Info.plist (100%) create mode 100644 Security/libsecurity_keychain/xpc/main.c rename {libsecurity_manifest => Security/libsecurity_manifest}/APPLE_LICENSE (100%) rename {libsecurity_manifest => Security/libsecurity_manifest}/Info-security_manifest.plist (100%) rename {libsecurity_manifest => Security/libsecurity_manifest}/lib/AppleManifest.cpp (99%) rename {libsecurity_manifest => Security/libsecurity_manifest}/lib/AppleManifest.h (97%) rename {libsecurity_manifest => Security/libsecurity_manifest}/lib/Download.cpp (99%) rename {libsecurity_manifest => Security/libsecurity_manifest}/lib/Download.h (97%) rename {libsecurity_manifest => Security/libsecurity_manifest}/lib/Manifest.cpp (95%) rename {libsecurity_manifest => Security/libsecurity_manifest}/lib/Manifest.h (96%) rename {libsecurity_manifest => Security/libsecurity_manifest}/lib/ManifestInternal.cpp (99%) rename {libsecurity_manifest => Security/libsecurity_manifest}/lib/ManifestInternal.h (99%) rename {libsecurity_manifest => Security/libsecurity_manifest}/lib/ManifestSigner.cpp (93%) rename {libsecurity_manifest => Security/libsecurity_manifest}/lib/ManifestSigner.h (95%) rename {libsecurity_manifest => Security/libsecurity_manifest}/lib/SecManifest.cpp (98%) rename {libsecurity_manifest => Security/libsecurity_manifest}/lib/SecManifest.h (99%) rename {libsecurity_manifest => Security/libsecurity_manifest}/lib/SecureDownload.cpp (98%) rename {libsecurity_manifest => Security/libsecurity_manifest}/lib/SecureDownload.h (99%) rename {libsecurity_manifest => Security/libsecurity_manifest}/lib/SecureDownloadInternal.c (100%) rename {libsecurity_manifest => Security/libsecurity_manifest}/lib/SecureDownloadInternal.h (100%) rename {libsecurity_manifest => Security/libsecurity_manifest}/lib/security_manifest.exp (95%) rename {libsecurity_manifest => Security/libsecurity_manifest}/libsecurity_manifest.xcodeproj/project.pbxproj (100%) rename {libsecurity_mds => Security/libsecurity_mds}/Info-security_mds.plist (100%) rename {libsecurity_mds => Security/libsecurity_mds}/README (100%) rename {libsecurity_mds => Security/libsecurity_mds}/lib/MDSAttrParser.cpp (99%) rename {libsecurity_mds => Security/libsecurity_mds}/lib/MDSAttrParser.h (97%) rename {libsecurity_mds => Security/libsecurity_mds}/lib/MDSAttrStrings.cpp (99%) rename {libsecurity_mds => Security/libsecurity_mds}/lib/MDSAttrStrings.h (97%) rename {libsecurity_mds => Security/libsecurity_mds}/lib/MDSAttrUtils.cpp (98%) rename {libsecurity_mds => Security/libsecurity_mds}/lib/MDSAttrUtils.h (96%) rename {libsecurity_mds => Security/libsecurity_mds}/lib/MDSDatabase.cpp (99%) rename {libsecurity_mds => Security/libsecurity_mds}/lib/MDSDatabase.h (98%) rename {libsecurity_mds => Security/libsecurity_mds}/lib/MDSDictionary.cpp (99%) rename {libsecurity_mds => Security/libsecurity_mds}/lib/MDSDictionary.h (96%) rename {libsecurity_mds => Security/libsecurity_mds}/lib/MDSModule.cpp (98%) rename {libsecurity_mds => Security/libsecurity_mds}/lib/MDSModule.h (96%) rename {libsecurity_mds => Security/libsecurity_mds}/lib/MDSPrefs.cpp (98%) rename {libsecurity_mds => Security/libsecurity_mds}/lib/MDSPrefs.h (95%) create mode 100644 Security/libsecurity_mds/lib/MDSSchema.cpp create mode 100644 Security/libsecurity_mds/lib/MDSSchema.h rename {libsecurity_mds => Security/libsecurity_mds}/lib/MDSSession.cpp (99%) rename {libsecurity_mds => Security/libsecurity_mds}/lib/MDSSession.h (98%) rename {libsecurity_mds => Security/libsecurity_mds}/lib/mds.h (97%) rename {libsecurity_mds => Security/libsecurity_mds}/lib/mds_schema.h (98%) rename {libsecurity_mds => Security/libsecurity_mds}/lib/mdsapi.cpp (98%) rename {libsecurity_mds => Security/libsecurity_mds}/lib/mdspriv.h (95%) rename {libsecurity_mds => Security/libsecurity_mds}/lib/security_mds.exp (100%) rename {libsecurity_mds => Security/libsecurity_mds}/libsecurity_mds.xcodeproj/project.pbxproj (100%) rename {libsecurity_ocspd => Security/libsecurity_ocspd}/Info-security_ocspd.plist (100%) rename {libsecurity_ocspd => Security/libsecurity_ocspd}/client/ocspdClient.cpp (93%) rename {libsecurity_ocspd => Security/libsecurity_ocspd}/client/ocspdClient.h (84%) rename {libsecurity_ocspd => Security/libsecurity_ocspd}/common/ocspExtensions.cpp (98%) rename {libsecurity_ocspd => Security/libsecurity_ocspd}/common/ocspExtensions.h (98%) rename {libsecurity_ocspd => Security/libsecurity_ocspd}/common/ocspResponse.cpp (99%) rename {libsecurity_ocspd => Security/libsecurity_ocspd}/common/ocspResponse.h (99%) rename {libsecurity_ocspd => Security/libsecurity_ocspd}/common/ocspdClient.h (100%) rename {libsecurity_ocspd => Security/libsecurity_ocspd}/common/ocspdDbSchema.cpp (96%) rename {libsecurity_ocspd => Security/libsecurity_ocspd}/common/ocspdDbSchema.h (98%) rename {libsecurity_ocspd => Security/libsecurity_ocspd}/common/ocspdDebug.h (97%) create mode 100644 Security/libsecurity_ocspd/common/ocspdTypes.h rename {libsecurity_ocspd => Security/libsecurity_ocspd}/common/ocspdUtils.cpp (89%) create mode 100644 Security/libsecurity_ocspd/common/ocspdUtils.h rename {libsecurity_ocspd => Security/libsecurity_ocspd}/libsecurity_ocspd.xcodeproj/project.pbxproj (100%) create mode 100644 Security/libsecurity_ocspd/mig/mig.mk rename {libsecurity_ocspd => Security/libsecurity_ocspd}/mig/ocspd.defs (100%) rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/APPLE_LICENSE (100%) rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/Info-security_pkcs12.plist (100%) rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/lib/SecPkcs12.cpp (99%) rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/lib/SecPkcs12.h (99%) rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/lib/pkcs12BagAttrs.cpp (98%) rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/lib/pkcs12BagAttrs.h (98%) rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/lib/pkcs12Coder.cpp (99%) rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/lib/pkcs12Coder.h (99%) rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/lib/pkcs12Crypto.cpp (99%) rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/lib/pkcs12Crypto.h (98%) rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/lib/pkcs12Debug.h (96%) rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/lib/pkcs12Decode.cpp (99%) rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/lib/pkcs12Encode.cpp (99%) rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/lib/pkcs12Keychain.cpp (99%) rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/lib/pkcs12SafeBag.cpp (99%) rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/lib/pkcs12SafeBag.h (99%) rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/lib/pkcs12Templates.cpp (97%) create mode 100644 Security/libsecurity_pkcs12/lib/pkcs12Templates.h create mode 100644 Security/libsecurity_pkcs12/lib/pkcs12Utils.cpp create mode 100644 Security/libsecurity_pkcs12/lib/pkcs12Utils.h rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/lib/pkcs7Templates.cpp (98%) create mode 100644 Security/libsecurity_pkcs12/lib/pkcs7Templates.h rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/lib/pkcsoids.cpp (94%) rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/lib/pkcsoids.h (94%) rename {libsecurity_pkcs12 => Security/libsecurity_pkcs12}/libsecurity_pkcs12.xcodeproj/project.pbxproj (100%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/APPLE_LICENSE (100%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/Info-security_sd_cspdl.plist (100%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/lib/SDCSPDLBuiltin.cpp (94%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/lib/SDCSPDLDatabase.cpp (95%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/lib/SDCSPDLDatabase.h (95%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/lib/SDCSPDLPlugin.cpp (97%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/lib/SDCSPDLPlugin.h (97%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/lib/SDCSPDLSession.cpp (97%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/lib/SDCSPDLSession.h (95%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/lib/SDCSPSession.cpp (99%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/lib/SDCSPSession.h (98%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/lib/SDContext.cpp (99%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/lib/SDContext.h (98%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/lib/SDDLSession.cpp (99%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/lib/SDDLSession.h (99%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/lib/SDFactory.cpp (97%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/lib/SDFactory.h (95%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/lib/SDKey.cpp (99%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/lib/SDKey.h (97%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/libsecurity_sd_cspdl.xcodeproj/project.pbxproj (100%) rename {libsecurity_sd_cspdl => Security/libsecurity_sd_cspdl}/mds/sd_cspdl_common.mdsinfo (100%) rename {libsecurity_utilities => Security/libsecurity_smime}/APPLE_LICENSE (100%) rename {libsecurity_smime => Security/libsecurity_smime}/Info-security_smime.plist (100%) create mode 100644 Security/libsecurity_smime/TODO rename {libsecurity_smime => Security/libsecurity_smime}/docs/libsecurity_smime.plist (100%) rename {libsecurity_smime => Security/libsecurity_smime}/docs/libsecurity_smime.txt (100%) create mode 100644 Security/libsecurity_smime/lib/SecCMS.c create mode 100644 Security/libsecurity_smime/lib/SecCMS.h create mode 100644 Security/libsecurity_smime/lib/SecCmsBase.h create mode 100644 Security/libsecurity_smime/lib/SecCmsContentInfo.h create mode 100644 Security/libsecurity_smime/lib/SecCmsDecoder.h create mode 100644 Security/libsecurity_smime/lib/SecCmsDigestContext.h create mode 100644 Security/libsecurity_smime/lib/SecCmsDigestedData.h create mode 100644 Security/libsecurity_smime/lib/SecCmsEncoder.h create mode 100644 Security/libsecurity_smime/lib/SecCmsEncryptedData.h create mode 100644 Security/libsecurity_smime/lib/SecCmsEnvelopedData.h create mode 100644 Security/libsecurity_smime/lib/SecCmsMessage.h create mode 100644 Security/libsecurity_smime/lib/SecCmsRecipientInfo.h create mode 100644 Security/libsecurity_smime/lib/SecCmsSignedData.h create mode 100644 Security/libsecurity_smime/lib/SecCmsSignerInfo.h create mode 100644 Security/libsecurity_smime/lib/SecSMIME.h create mode 100644 Security/libsecurity_smime/lib/SecSMIMEPriv.h create mode 100644 Security/libsecurity_smime/lib/cert.c create mode 100644 Security/libsecurity_smime/lib/cert.h create mode 100644 Security/libsecurity_smime/lib/cmsarray.c create mode 100644 Security/libsecurity_smime/lib/cmsasn1.c create mode 100644 Security/libsecurity_smime/lib/cmsattr.c create mode 100644 Security/libsecurity_smime/lib/cmscinfo.c create mode 100644 Security/libsecurity_smime/lib/cmscipher.c create mode 100644 Security/libsecurity_smime/lib/cmsdecode.c create mode 100644 Security/libsecurity_smime/lib/cmsdigdata.c create mode 100644 Security/libsecurity_smime/lib/cmsdigest.c create mode 100644 Security/libsecurity_smime/lib/cmsencdata.c create mode 100644 Security/libsecurity_smime/lib/cmsencode.c create mode 100644 Security/libsecurity_smime/lib/cmsenvdata.c create mode 100644 Security/libsecurity_smime/lib/cmslocal.h create mode 100644 Security/libsecurity_smime/lib/cmsmessage.c create mode 100644 Security/libsecurity_smime/lib/cmspriv.h create mode 100644 Security/libsecurity_smime/lib/cmspubkey.c create mode 100644 Security/libsecurity_smime/lib/cmsrecinfo.c create mode 100644 Security/libsecurity_smime/lib/cmsreclist.c create mode 100644 Security/libsecurity_smime/lib/cmsreclist.h create mode 100644 Security/libsecurity_smime/lib/cmssigdata.c create mode 100644 Security/libsecurity_smime/lib/cmssiginfo.c create mode 100644 Security/libsecurity_smime/lib/cmstpriv.h create mode 100644 Security/libsecurity_smime/lib/cmsutil.c create mode 100644 Security/libsecurity_smime/lib/cryptohi.c create mode 100644 Security/libsecurity_smime/lib/cryptohi.h create mode 100644 Security/libsecurity_smime/lib/plhash.c create mode 100644 Security/libsecurity_smime/lib/plhash.h create mode 100644 Security/libsecurity_smime/lib/secalgid.c rename {libsecurity_smime => Security/libsecurity_smime}/lib/secitem.c (100%) rename {libsecurity_smime => Security/libsecurity_smime}/lib/secitem.h (100%) create mode 100644 Security/libsecurity_smime/lib/secoid.c create mode 100644 Security/libsecurity_smime/lib/secoid.h create mode 100644 Security/libsecurity_smime/lib/secoidt.h create mode 100644 Security/libsecurity_smime/lib/security_smime.exp rename {libsecurity_smime => Security/libsecurity_smime}/lib/siginfoUtils.cpp (97%) create mode 100644 Security/libsecurity_smime/lib/smimeutil.c create mode 100755 Security/libsecurity_smime/lib/testcms rename {libsecurity_smime => Security/libsecurity_smime}/lib/tsaSupport.c (98%) rename {libsecurity_smime => Security/libsecurity_smime}/lib/tsaSupport.h (96%) rename {libsecurity_smime => Security/libsecurity_smime}/lib/tsaSupportPriv.h (90%) rename {libsecurity_smime => Security/libsecurity_smime}/lib/tsaTemplates.c (96%) rename {libsecurity_smime => Security/libsecurity_smime}/lib/tsaTemplates.h (98%) create mode 100644 Security/libsecurity_smime/libsecurity_smime.xcodeproj/project.pbxproj create mode 100644 Security/libsecurity_smime/regressions/smime-cms-test.c create mode 100644 Security/libsecurity_smime/regressions/smime_regressions.h rename {libsecurity_ssl => Security/libsecurity_ssl}/Info-security_ssl.plist (100%) rename {libsecurity_ssl => Security/libsecurity_ssl}/README (100%) rename {libsecurity_ssl => Security/libsecurity_ssl}/Security (100%) create mode 100644 Security/libsecurity_ssl/config/base.xcconfig rename {libsecurity_ssl => Security/libsecurity_ssl}/config/debug.xcconfig (100%) rename {libsecurity_ssl => Security/libsecurity_ssl}/config/kext.xcconfig (100%) create mode 100644 Security/libsecurity_ssl/config/lib.xcconfig rename {libsecurity_ssl => Security/libsecurity_ssl}/config/release.xcconfig (100%) create mode 100644 Security/libsecurity_ssl/config/tests.xcconfig rename {libsecurity_ssl => Security/libsecurity_ssl}/dtlsEcho/README (100%) rename {libsecurity_ssl => Security/libsecurity_ssl}/dtlsEcho/dtlsEchoClient.c (86%) rename {libsecurity_ssl => Security/libsecurity_ssl}/dtlsEcho/dtlsEchoServer.c (87%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/CipherSuite.h (99%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/ModuleAttacher.h (100%) create mode 100644 Security/libsecurity_ssl/lib/SSLRecordInternal.c create mode 100644 Security/libsecurity_ssl/lib/SSLRecordInternal.h rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/SecureTransport.h (99%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/SecureTransportPriv.h (93%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/appleCdsa.h (98%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/appleSession.c (98%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/appleSession.h (91%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/cipherSpecs.c (99%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/cipherSpecs.h (97%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/cryptType.h (95%) create mode 100644 Security/libsecurity_ssl/lib/secCrypto.c rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/securetransport++.cpp (99%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/securetransport++.h (100%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/security_ssl.exp (99%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/ssl.h (93%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslAlertMessage.h (96%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslBER.c (99%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslBER.h (96%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslBuildFlags.h (96%) create mode 100644 Security/libsecurity_ssl/lib/sslCipherSpecs.c rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslCipherSpecs.h (94%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslContext.c (81%) create mode 100644 Security/libsecurity_ssl/lib/sslContext.h create mode 100644 Security/libsecurity_ssl/lib/sslCrypto.c create mode 100644 Security/libsecurity_ssl/lib/sslCrypto.h rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslDebug.h (97%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslDigests.c (96%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslDigests.h (93%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslHandshake.h (94%) create mode 100644 Security/libsecurity_ssl/lib/sslKeychain.c create mode 100644 Security/libsecurity_ssl/lib/sslKeychain.h rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslMemory.c (98%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslMemory.h (95%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslNullCipher.c (94%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslPriv.h (93%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslRand.c (95%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslRand.h (91%) create mode 100644 Security/libsecurity_ssl/lib/sslRecord.c rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslRecord.h (93%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslSession.c (95%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslSession.h (94%) create mode 100644 Security/libsecurity_ssl/lib/sslTransport.c rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslTypes.h (89%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslUtils.c (97%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/sslUtils.h (95%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/symCipher.c (99%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/symCipher.h (98%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/symCipherParams.c (96%) create mode 100644 Security/libsecurity_ssl/lib/tlsCallbacks.c create mode 100644 Security/libsecurity_ssl/lib/tlsCallbacks.h rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/tls_digest.c (99%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/tls_digest.h (96%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/tls_hashhmac.c (93%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/tls_hashhmac.h (95%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/tls_hmac.c (98%) rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/tls_hmac.h (96%) create mode 100644 Security/libsecurity_ssl/lib/tls_record_internal.h rename {libsecurity_ssl => Security/libsecurity_ssl}/lib/tls_ssl.h (96%) create mode 100644 Security/libsecurity_ssl/libsecurity_ssl.xcodeproj/project.pbxproj rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/ClientCert_ecc_ecc.h (100%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/ClientCert_ecc_rsa.h (100%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/ClientCert_rsa_ecc.h (100%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/ClientCert_rsa_rsa.h (100%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/ClientKey_ecc.h (100%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/ClientKey_rsa.h (100%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/SECG_ecc-secp256r1-client_cert.h (100%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/SECG_ecc-secp256r1-client_key.h (100%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/SECG_ecc_rsa-secp256r1-client_cert.h (100%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/SECG_ecc_rsa-secp256r1-client_key.h (100%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/cert-1.h (100%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/gencerts.sh (100%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/identity-1.h (100%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/privkey-1.h (100%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/ssl-39-echo.c (99%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/ssl-40-clientauth.c (99%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/ssl-41-clientauth.c (98%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/ssl-42-ciphers.c (76%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/ssl-43-ciphers.c (92%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/ssl-44-crashes.c (83%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/ssl-45-tls12.c (88%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/ssl-46-SSLGetSupportedCiphers.c (91%) rename {libsecurity_ssl => Security/libsecurity_ssl}/regressions/ssl-47-falsestart.c (88%) create mode 100644 Security/libsecurity_ssl/regressions/ssl-48-split.c create mode 100644 Security/libsecurity_ssl/regressions/ssl-49-sni.c create mode 100644 Security/libsecurity_ssl/regressions/ssl-50-server.c create mode 100644 Security/libsecurity_ssl/regressions/ssl-51-state.c create mode 100644 Security/libsecurity_ssl/regressions/ssl-utils.c create mode 100644 Security/libsecurity_ssl/regressions/ssl-utils.h create mode 100644 Security/libsecurity_ssl/regressions/ssl_regressions.h rename {libsecurity_ssl => Security/libsecurity_ssl}/security_ssl (100%) create mode 100644 Security/libsecurity_ssl/sslViewer/fileIo.c create mode 100644 Security/libsecurity_ssl/sslViewer/fileIo.h create mode 100644 Security/libsecurity_ssl/sslViewer/ioSock.c create mode 100644 Security/libsecurity_ssl/sslViewer/ioSock.h rename {libsecurity_ssl => Security/libsecurity_ssl}/sslViewer/printCert.c (98%) rename {libsecurity_ssl => Security/libsecurity_ssl}/sslViewer/printCert.h (94%) create mode 100644 Security/libsecurity_ssl/sslViewer/sslAppUtils.cpp create mode 100644 Security/libsecurity_ssl/sslViewer/sslAppUtils.h rename {libsecurity_ssl => Security/libsecurity_ssl}/sslViewer/sslServer.1 (100%) create mode 100644 Security/libsecurity_ssl/sslViewer/sslServer.cpp rename {libsecurity_ssl => Security/libsecurity_ssl}/sslViewer/sslViewer.1 (100%) rename {libsecurity_ssl => Security/libsecurity_ssl}/sslViewer/sslViewer.cpp (99%) rename {libsecurity_ssl => Security/libsecurity_ssl}/sslViewer/sslViewer.xcodeproj/project.pbxproj (100%) rename {libsecurity_transform => Security/libsecurity_transform}/100-sha2.m (89%) rename {libsecurity_transform => Security/libsecurity_transform}/Configurations/libsecurity_transform.Default.xcconfig (100%) rename {libsecurity_transform => Security/libsecurity_transform}/Configurations/libsecurity_transform_Deployment.xcconfig (100%) rename {libsecurity_transform => Security/libsecurity_transform}/Configurations/libsecurity_transform_Development.xcconfig (100%) rename {libsecurity_transform => Security/libsecurity_transform}/Configurations/libsecurity_transform_core.xcconfig (100%) rename {libsecurity_transform => Security/libsecurity_transform}/Configurations/security_transform_Default.xcconfig (100%) rename {libsecurity_transform => Security/libsecurity_transform}/Configurations/security_transform_Deployment.xcconfig (100%) rename {libsecurity_transform => Security/libsecurity_transform}/Configurations/security_transform_Development.xcconfig (100%) rename {libsecurity_transform => Security/libsecurity_transform}/Info-security_transform.plist (100%) rename {libsecurity_transform => Security/libsecurity_transform}/NSData+HexString.h (75%) rename {libsecurity_transform => Security/libsecurity_transform}/NSData+HexString.m (88%) create mode 100644 Security/libsecurity_transform/custom.h rename {libsecurity_transform => Security/libsecurity_transform}/custom.mm (97%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/CEncryptDecrypt.c (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/CoreFoundationBasics.cpp (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/CoreFoundationBasics.h (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/Digest.cpp (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/Digest.h (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/Digest_block.c (77%) create mode 100644 Security/libsecurity_transform/lib/Digest_block.h rename {libsecurity_transform => Security/libsecurity_transform}/lib/EncodeDecodeTransforms.c (96%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/EncryptTransform.cpp (96%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/EncryptTransform.h (98%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/EncryptTransformUtilities.cpp (98%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/EncryptTransformUtilities.h (98%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/GroupTransform.cpp (99%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/GroupTransform.h (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/LinkedList.cpp (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/LinkedList.h (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/Monitor.cpp (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/Monitor.h (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/NullTransform.cpp (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/NullTransform.h (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecCollectTransform.cpp (99%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecCollectTransform.h (96%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecCustomTransform.cpp (97%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecCustomTransform.h (99%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecDecodeTransform.h (97%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecDigestTransform.cpp (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecDigestTransform.h (98%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecEncodeTransform.h (98%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecEncryptTransform.cpp (98%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecEncryptTransform.h (90%) create mode 100644 Security/libsecurity_transform/lib/SecExternalSourceTransform.cpp rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecExternalSourceTransform.h (97%) create mode 100644 Security/libsecurity_transform/lib/SecGroupTransform.cpp rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecGroupTransform.h (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecMaskGenerationFunctionTransform.c (88%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecMaskGenerationFunctionTransform.h (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecNullTransform.cpp (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecNullTransform.h (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecReadTransform.h (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecSignVerifyTransform.c (96%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecSignVerifyTransform.h (98%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecTransform.cpp (94%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecTransform.h (99%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecTransformInternal.h (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecTransformReadTransform.cpp (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecTransformReadTransform.h (97%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SecTransformValidator.h (96%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SingleShotSource.cpp (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/SingleShotSource.h (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/Source.cpp (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/Source.h (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/StreamSource.cpp (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/StreamSource.h (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/Transform.cpp (99%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/Transform.h (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/TransformFactory.cpp (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/TransformFactory.h (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/Utilities.cpp (75%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/Utilities.h (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/c++utils.cpp (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/c++utils.h (100%) rename {libsecurity_transform => Security/libsecurity_transform}/lib/misc.c (81%) create mode 100644 Security/libsecurity_transform/lib/misc.h rename {libsecurity_transform => Security/libsecurity_transform}/lib/security_transform.exp (100%) create mode 100644 Security/libsecurity_transform/libsecurity_transform.xcodeproj/project.pbxproj rename {libsecurity_transform => Security/libsecurity_transform}/misc/base32alpha2vals (100%) create mode 100644 Security/libsecurity_transform/misc/speed-test.h create mode 100644 Security/libsecurity_transform/misc/speed-test.mm rename {libsecurity_transform => Security/libsecurity_transform}/unit-tests-Info.plist (100%) rename {libsecurityd => Security/libsecurity_utilities}/APPLE_LICENSE (100%) rename {libsecurity_utilities => Security/libsecurity_utilities}/Info-security_utilities.plist (100%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/adornments.cpp (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/adornments.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/alloc.cpp (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/alloc.h (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/blob.cpp (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/blob.h (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/bufferfifo.cpp (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/bufferfifo.h (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/buffers.cpp (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/buffers.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/ccaudit.cpp (98%) create mode 100644 Security/libsecurity_utilities/lib/ccaudit.h rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/cfclass.cpp (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/cfclass.h (96%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/cfmach++.cpp (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/cfmach++.h (96%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/cfmunge.cpp (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/cfmunge.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/cfutilities.cpp (93%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/cfutilities.h (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/coderepository.cpp (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/coderepository.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/crc.c (100%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/crc.h (100%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/daemon.cpp (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/daemon.h (95%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/debugging.cpp (99%) create mode 100644 Security/libsecurity_utilities/lib/debugging.h rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/debugging_internal.cpp (96%) create mode 100644 Security/libsecurity_utilities/lib/debugging_internal.h rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/debugsupport.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/devrandom.cpp (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/devrandom.h (96%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/dtrace.mk (100%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/dyld_cache_format.h (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/dyldcache.cpp (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/dyldcache.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/endian.cpp (94%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/endian.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/errors.cpp (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/errors.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/exports (100%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/fdmover.cpp (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/fdmover.h (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/fdsel.cpp (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/fdsel.h (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/globalizer.cpp (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/globalizer.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/hashing.cpp (95%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/hashing.h (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/headermap.cpp (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/headermap.h (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/hosts.cpp (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/hosts.h (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/inetreply.cpp (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/inetreply.h (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/iodevices.cpp (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/iodevices.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/ip++.cpp (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/ip++.h (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/kq++.cpp (96%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/kq++.h (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/ktracecodes.h (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/logging.cpp (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/logging.h (95%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/mach++.cpp (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/mach++.h (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/mach_notify.c (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/mach_notify.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/macho++.cpp (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/macho++.h (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/machrunloopserver.cpp (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/machrunloopserver.h (96%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/machserver.cpp (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/machserver.h (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/memstreams.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/memutils.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/muscle++.cpp (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/muscle++.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/osxcode.cpp (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/osxcode.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/pcsc++.cpp (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/pcsc++.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/powerwatch.cpp (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/powerwatch.h (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/refcount.h (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/seccfobject.cpp (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/seccfobject.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/security_utilities.d (100%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/security_utilities.h (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/selector.cpp (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/selector.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/simpleprefs.cpp (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/simpleprefs.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/socks++.cpp (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/socks++.h (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/socks++4.cpp (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/socks++4.h (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/socks++5.cpp (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/socks++5.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/sqlite++.cpp (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/sqlite++.h (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/streams.cpp (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/streams.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/superblob.cpp (100%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/superblob.h (100%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/threading.cpp (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/threading.h (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/threading_internal.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/timeflow.cpp (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/timeflow.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/tqueue.cpp (94%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/tqueue.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/trackingallocator.cpp (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/trackingallocator.h (96%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/transactions.cpp (95%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/transactions.h (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/typedvalue.cpp (94%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/typedvalue.h (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/unix++.cpp (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/unix++.h (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/unixchild.cpp (99%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/unixchild.h (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/url.cpp (98%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/url.h (96%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/utilities.cpp (98%) create mode 100644 Security/libsecurity_utilities/lib/utilities.h rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/utility_config.h (97%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/vproc++.cpp (95%) rename {libsecurity_utilities => Security/libsecurity_utilities}/lib/vproc++.h (96%) rename {libsecurity_utilities => Security/libsecurity_utilities}/libsecurity_utilities.xcodeproj/project.pbxproj (100%) create mode 100644 Security/libsecurityd/APPLE_LICENSE rename {libsecurityd => Security/libsecurityd}/Info-securityd_client.plist (100%) rename {libsecurityd => Security/libsecurityd}/Info-securityd_server.plist (100%) rename {libsecurityd => Security/libsecurityd}/lib/SharedMemoryClient.cpp (100%) rename {libsecurityd => Security/libsecurityd}/lib/SharedMemoryClient.h (100%) create mode 100644 Security/libsecurityd/lib/SharedMemoryCommon.h rename {libsecurityd => Security/libsecurityd}/lib/dictionary.cpp (99%) rename {libsecurityd => Security/libsecurityd}/lib/dictionary.h (96%) rename {libsecurityd => Security/libsecurityd}/lib/eventlistener.cpp (98%) rename {libsecurityd => Security/libsecurityd}/lib/eventlistener.h (96%) rename {libsecurityd => Security/libsecurityd}/lib/handletypes.h (97%) rename {libsecurityd => Security/libsecurityd}/lib/sec_xdr.c (99%) rename {libsecurityd => Security/libsecurityd}/lib/sec_xdr.h (97%) rename {libsecurityd => Security/libsecurityd}/lib/sec_xdr_array.c (98%) rename {libsecurityd => Security/libsecurityd}/lib/sec_xdr_reference.c (98%) rename {libsecurityd => Security/libsecurityd}/lib/sec_xdr_sizeof.c (98%) rename {libsecurityd => Security/libsecurityd}/lib/sec_xdrmem.c (99%) rename {libsecurityd => Security/libsecurityd}/lib/ss_types.h (97%) rename {libsecurityd => Security/libsecurityd}/lib/ssblob.cpp (96%) rename {libsecurityd => Security/libsecurityd}/lib/ssblob.h (98%) rename {libsecurityd => Security/libsecurityd}/lib/ssclient.cpp (99%) rename {libsecurityd => Security/libsecurityd}/lib/ssclient.h (99%) rename {libsecurityd => Security/libsecurityd}/lib/sscommon.h (97%) rename {libsecurityd => Security/libsecurityd}/lib/ssnotify.h (98%) rename {libsecurityd => Security/libsecurityd}/lib/sstransit.cpp (98%) rename {libsecurityd => Security/libsecurityd}/lib/sstransit.h (98%) create mode 100644 Security/libsecurityd/lib/transition.cpp rename {libsecurityd => Security/libsecurityd}/lib/ucsp_types.h (95%) rename {libsecurityd => Security/libsecurityd}/lib/xdr_auth.c (97%) rename {libsecurityd => Security/libsecurityd}/lib/xdr_auth.h (95%) rename {libsecurityd => Security/libsecurityd}/lib/xdr_cssm.c (99%) rename {libsecurityd => Security/libsecurityd}/lib/xdr_cssm.h (99%) rename {libsecurityd => Security/libsecurityd}/lib/xdr_dldb.cpp (96%) rename {libsecurityd => Security/libsecurityd}/lib/xdr_dldb.h (97%) rename {libsecurityd => Security/libsecurityd}/libsecurityd.xcodeproj/project.pbxproj (100%) rename {libsecurityd => Security/libsecurityd}/mig/cshosting.defs (97%) create mode 100644 Security/libsecurityd/mig/mig.mk rename {libsecurityd => Security/libsecurityd}/mig/ss_types.defs (98%) rename {libsecurityd => Security/libsecurityd}/mig/ucsp.defs (99%) rename {libsecurityd => Security/libsecurityd}/mig/ucspNotify.defs (96%) rename {regressions => Security/regressions}/README (100%) rename {regressions => Security/regressions}/inc/IPC/Run3.pm (100%) rename {regressions => Security/regressions}/inc/MyHarness.pm (100%) create mode 100644 Security/regressions/regressions.xcodeproj/project.pbxproj create mode 100755 Security/regressions/t/security.pl rename {regressions => Security/regressions}/test/test-00-test.c (90%) rename {regressions => Security/regressions}/test/test_regressions.h (100%) rename {regressions => Security/regressions}/test/testcert.c (96%) rename {regressions => Security/regressions}/test/testcert.h (94%) create mode 100644 Security/regressions/test/testcpp.h create mode 100644 Security/regressions/test/testenv.c create mode 100644 Security/regressions/test/testenv.h rename {regressions => Security/regressions}/test/testlist_begin.h (100%) rename {regressions => Security/regressions}/test/testlist_end.h (100%) create mode 100644 Security/regressions/test/testmore.c create mode 100644 Security/regressions/test/testmore.h create mode 100644 Security/regressions/test/testpolicy.h rename {regressions => Security/regressions}/test/testpolicy.m (82%) rename {sec => Security/sec}/CloudKeychainProxy/CloudKeychainProxy.1 (100%) rename {sec => Security/sec}/SOSCircle/CKBridge/CKClient.c (99%) rename {sec => Security/sec}/SOSCircle/CKBridge/CKClient.h (97%) create mode 100644 Security/sec/SOSCircle/CKBridge/SOSCloudKeychainClient.c create mode 100644 Security/sec/SOSCircle/CKBridge/SOSCloudKeychainClient.h rename {sec => Security/sec}/SOSCircle/CKBridge/SOSCloudKeychainConstants.c (85%) rename {sec => Security/sec}/SOSCircle/CKBridge/SOSCloudKeychainConstants.h (80%) rename {sec => Security/sec}/SOSCircle/CKBridge/SOSCloudTransport.c (99%) rename {sec => Security/sec}/SOSCircle/CKBridge/SOSCloudTransport.h (97%) create mode 100644 Security/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.h create mode 100644 Security/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.m rename {sec => Security/sec}/SOSCircle/CloudKeychainProxy/CKDPersistentState.h (95%) rename {sec => Security/sec}/SOSCircle/CloudKeychainProxy/CKDPersistentState.m (98%) rename {sec => Security/sec}/SOSCircle/CloudKeychainProxy/CKDUserInteraction.h (94%) rename {sec => Security/sec}/SOSCircle/CloudKeychainProxy/CKDUserInteraction.m (98%) rename {sec => Security/sec}/SOSCircle/CloudKeychainProxy/ckdmain.m (92%) create mode 100644 Security/sec/SOSCircle/CloudKeychainProxy/cloudkeychain.entitlements.plist create mode 100644 Security/sec/SOSCircle/CloudKeychainProxy/cloudkeychainproxy.m create mode 100644 Security/sec/SOSCircle/CloudKeychainProxy/en.lproj/InfoPlist.strings create mode 100644 Security/sec/SOSCircle/CloudKeychainProxy/scripts/PhoneTerms2.applescript rename {sec => Security/sec}/SOSCircle/CloudKeychainProxy/scripts/PhoneTerms2.scpt (100%) rename {sec => Security/sec}/SOSCircle/CloudKeychainProxy/scripts/install_on_devices (75%) create mode 100644 Security/sec/SOSCircle/CloudKeychainProxy/scripts/kcstatus create mode 100755 Security/sec/SOSCircle/CloudKeychainProxy/scripts/sosbuildroot rename {sec => Security/sec}/SOSCircle/CloudKeychainProxy/scripts/soscopy (100%) rename {sec => Security/sec}/SOSCircle/CloudKeychainProxy/scripts/soscopysshkeys (100%) rename {sec => Security/sec}/SOSCircle/CloudKeychainProxy/scripts/sosinstallroot (100%) rename {sec => Security/sec}/SOSCircle/CloudKeychainProxy/scripts/sosreset (100%) create mode 100755 Security/sec/SOSCircle/CloudKeychainProxy/scripts/tweak create mode 100644 Security/sec/SOSCircle/Empty.c create mode 100644 Security/sec/SOSCircle/Regressions/CKDKeyValueStore.h rename {sec => Security/sec}/SOSCircle/Regressions/CKDKeyValueStore.m (99%) rename {sec => Security/sec}/SOSCircle/Regressions/SOSCircle_regressions.h (76%) rename {sec => Security/sec}/SOSCircle/Regressions/SOSRegressionUtilities.c (89%) rename {sec => Security/sec}/SOSCircle/Regressions/SOSRegressionUtilities.h (89%) create mode 100644 Security/sec/SOSCircle/Regressions/SOSTestDataSource.c create mode 100644 Security/sec/SOSCircle/Regressions/SOSTestDataSource.h create mode 100644 Security/sec/SOSCircle/Regressions/SOSTestDevice.c create mode 100644 Security/sec/SOSCircle/Regressions/SOSTestDevice.h rename {sec => Security/sec}/SOSCircle/Regressions/sc-103-syncupdate.c (82%) rename {sec => Security/sec}/SOSCircle/Regressions/sc-130-resignationticket.c (77%) create mode 100644 Security/sec/SOSCircle/Regressions/sc-131-transport.c rename {sec => Security/sec}/SOSCircle/Regressions/sc-20-keynames.c (79%) create mode 100644 Security/sec/SOSCircle/Regressions/sc-30-peerinfo.c create mode 100644 Security/sec/SOSCircle/Regressions/sc-31-peerinfo-simplefuzz.c create mode 100644 Security/sec/SOSCircle/Regressions/sc-40-circle.c create mode 100644 Security/sec/SOSCircle/Regressions/sc-41-cloudcircle.c create mode 100644 Security/sec/SOSCircle/Regressions/sc-42-circlegencount.c create mode 100644 Security/sec/SOSCircle/Regressions/sc-45-digestvector.c create mode 100644 Security/sec/SOSCircle/Regressions/sc-50-message.c rename {sec => Security/sec}/SOSCircle/Regressions/sc-51-persistentEC.c (95%) create mode 100644 Security/sec/SOSCircle/Regressions/sc-60-peer.c rename {sec => Security/sec}/SOSCircle/Regressions/sc-70-engine.c (90%) create mode 100644 Security/sec/SOSCircle/Regressions/sc-75-circle-engine.c rename {sec => Security/sec}/SOSCircle/Regressions/sc-90-ckdclient.c (85%) rename {sec => Security/sec}/SOSCircle/Regressions/sc-95-ckd2client.c (82%) rename {sec => Security/sec}/SOSCircle/Regressions/sc-kvstool.m (90%) create mode 100644 Security/sec/SOSCircle/SOSARCDefines.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSAccount.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSAccount.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSAccountCircles.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSAccountCloudParameters.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSAccountCredentials.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSAccountDer.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSAccountFullPeerInfo.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSAccountPeers.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSAccountPersistence.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSAccountPriv.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSAccountUpdate.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSCircle.c rename {sec => Security/sec}/SOSCircle/SecureObjectSync/SOSCircle.h (77%) create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.c rename {sec => Security/sec}/SOSCircle/SecureObjectSync/SOSCloudCircle.h (78%) create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSCloudCircleInternal.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSCoder.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSCoder.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSDataSource.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSDigestVector.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSDigestVector.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSEngine.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSEngine.h rename {sec => Security/sec}/SOSCircle/SecureObjectSync/SOSExports.exp-in (76%) rename {sec => Security/sec}/SOSCircle/SecureObjectSync/SOSFullPeerInfo.c (88%) create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.h rename {sec => Security/sec}/SOSCircle/SecureObjectSync/SOSInternal.c (77%) create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSInternal.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSKVSKeys.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSKVSKeys.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSManifest.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSManifest.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSMessage.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSMessage.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSPeer.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSPeer.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.h rename {sec => Security/sec}/SOSCircle/SecureObjectSync/SOSPeerInfo.c (82%) create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSPeerInfo.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSPeerInfoCollections.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSPeerInfoCollections.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSPeerInfoInternal.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSTransport.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSTransport.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSTransportCircle.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSTransportCircle.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSTransportCircleKVS.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSTransportCircleKVS.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSTransportCoder.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSTransportCoder.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSTransportKeyParameter.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSTransportKeyParameter.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSTransportKeyParameterKVS.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSTransportKeyParameterKVS.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSTransportMessage.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSTransportMessage.h create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSTransportMessageKVS.c create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSTransportMessageKVS.h rename {sec => Security/sec}/SOSCircle/SecureObjectSync/SOSUserKeygen.c (91%) create mode 100644 Security/sec/SOSCircle/SecureObjectSync/SOSUserKeygen.h create mode 100644 Security/sec/SOSCircle/Tool/SOSCommands.h create mode 100644 Security/sec/SOSCircle/Tool/keychain_sync.c create mode 100644 Security/sec/SOSCircle/osxshim.c create mode 100644 Security/sec/Security/AppleBaselineEscrowCertificates.h rename {sec => Security/sec}/Security/AuthorizationStatus.h (100%) create mode 100644 Security/sec/Security/Regressions/Security_regressions.h rename {sec => Security/sec}/Security/Regressions/crypto/pbkdf2-00-hmac-sha1.c (98%) rename {sec => Security/sec}/Security/Regressions/crypto/spbkdf-00-hmac-sha1.c (99%) rename {sec => Security/sec}/Security/Regressions/otr/otr-00-identity.c (89%) rename {sec => Security/sec}/Security/Regressions/otr/otr-30-negotiation.c (80%) create mode 100644 Security/sec/Security/Regressions/otr/otr-otrdh.c create mode 100644 Security/sec/Security/Regressions/otr/otr-packetdata.c rename {sec => Security/sec}/Security/Regressions/secitem/si-00-find-nothing.c (92%) rename {sec => Security/sec}/Security/Regressions/secitem/si-05-add.c (93%) rename {sec => Security/sec}/Security/Regressions/secitem/si-10-find-internet.c (98%) rename {sec => Security/sec}/Security/Regressions/secitem/si-11-update-data.c (97%) rename {sec => Security/sec}/Security/Regressions/secitem/si-12-item-stress.c (94%) rename {sec => Security/sec}/Security/Regressions/secitem/si-14-dateparse.c (85%) rename {sec => Security/sec}/Security/Regressions/secitem/si-15-certificate.c (99%) rename {sec => Security/sec}/Security/Regressions/secitem/si-16-ec-certificate.c (98%) rename {sec => Security/sec}/Security/Regressions/secitem/si-20-sectrust-activation.c (99%) create mode 100644 Security/sec/Security/Regressions/secitem/si-20-sectrust.c rename {sec => Security/sec}/Security/Regressions/secitem/si-21-sectrust-asr.c (99%) rename {sec => Security/sec}/Security/Regressions/secitem/si-22-sectrust-iap.c (98%) rename {sec => Security/sec}/Security/Regressions/secitem/si-23-sectrust-ocsp-wwdr.c (99%) rename {sec => Security/sec}/Security/Regressions/secitem/si-23-sectrust-ocsp.c (97%) rename {sec => Security/sec}/Security/Regressions/secitem/si-24-sectrust-appleid.c (88%) rename {sec => Security/sec}/Security/Regressions/secitem/si-24-sectrust-digicert-malaysia.c (89%) rename {sec => Security/sec}/Security/Regressions/secitem/si-24-sectrust-diginotar.c (91%) rename {sec => Security/sec}/Security/Regressions/secitem/si-24-sectrust-itms.c (99%) rename {sec => Security/sec}/Security/Regressions/secitem/si-24-sectrust-mobileasset.c (88%) rename {sec => Security/sec}/Security/Regressions/secitem/si-24-sectrust-nist.c (88%) rename {sec => Security/sec}/Security/Regressions/secitem/si-24-sectrust-otatasking.c (88%) rename {sec => Security/sec}/Security/Regressions/secitem/si-24-sectrust-shoebox.c (97%) rename {sec => Security/sec}/Security/Regressions/secitem/si-25-sectrust-ipsec-eap.c (98%) rename {sec => Security/sec}/Security/Regressions/secitem/si-26-applicationsigning.c (99%) rename {sec => Security/sec}/Security/Regressions/secitem/si-27-sectrust-exceptions.c (99%) rename {sec => Security/sec}/Security/Regressions/secitem/si-28-sectrustsettings.c (99%) rename {sec => Security/sec}/Security/Regressions/secitem/si-29-sectrust-codesigning.c (99%) rename {sec => Security/sec}/Security/Regressions/secitem/si-30-keychain-upgrade.c (87%) rename {sec => Security/sec}/Security/Regressions/secitem/si-31-keychain-bad.c (77%) create mode 100644 Security/sec/Security/Regressions/secitem/si-31-keychain-unreadable.c create mode 100644 Security/sec/Security/Regressions/secitem/si-33-keychain-backup.c create mode 100644 Security/sec/Security/Regressions/secitem/si-40-seckey-custom.c rename {sec => Security/sec}/Security/Regressions/secitem/si-40-seckey.c (93%) create mode 100644 Security/sec/Security/Regressions/secitem/si-41-sececkey.c rename {sec => Security/sec}/Security/Regressions/secitem/si-42-identity.c (97%) rename {sec => Security/sec}/Security/Regressions/secitem/si-43-persistent.c (98%) create mode 100644 Security/sec/Security/Regressions/secitem/si-50-secrandom.c rename {sec => Security/sec}/Security/Regressions/secitem/si-60-cms.c (99%) rename {sec => Security/sec}/Security/Regressions/secitem/si-61-pkcs12.c (97%) rename {sec => Security/sec}/Security/Regressions/secitem/si-62-csr.c (91%) rename {sec => Security/sec}/Security/Regressions/secitem/si-63-scep.c (98%) rename {sec => Security/sec}/Security/Regressions/secitem/si-63-scep.h (100%) rename {sec => Security/sec}/Security/Regressions/secitem/si-63-scep/getcacert-mdes.h (100%) rename {sec => Security/sec}/Security/Regressions/secitem/si-63-scep/getcacert-mdesqa.h (100%) rename {sec => Security/sec}/Security/Regressions/secitem/si-64-ossl-cms.c (85%) rename {sec => Security/sec}/Security/Regressions/secitem/si-64-ossl-cms/attached_no_data_signed_data.h (100%) rename {sec => Security/sec}/Security/Regressions/secitem/si-64-ossl-cms/attached_signed_data.h (100%) rename {sec => Security/sec}/Security/Regressions/secitem/si-64-ossl-cms/detached_content.h (100%) rename {sec => Security/sec}/Security/Regressions/secitem/si-64-ossl-cms/detached_signed_data.h (100%) rename {sec => Security/sec}/Security/Regressions/secitem/si-64-ossl-cms/privkey.h (100%) rename {sec => Security/sec}/Security/Regressions/secitem/si-64-ossl-cms/signer.h (100%) rename {sec => Security/sec}/Security/Regressions/secitem/si-65-cms-cert-policy.c (94%) rename {sec => Security/sec}/Security/Regressions/secitem/si-66-smime.c (99%) rename {sec => Security/sec}/Security/Regressions/secitem/si-66-smime/signed-receipt.h (100%) create mode 100644 Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist.c rename {sec => Security/sec}/Security/Regressions/secitem/si-67-sectrust-blacklist/Global Trustee.cer.h (100%) rename {sec => Security/sec}/Security/Regressions/secitem/si-67-sectrust-blacklist/UTN-USERFirst-Hardware.cer.h (100%) rename {sec => Security/sec}/Security/Regressions/secitem/si-67-sectrust-blacklist/addons.mozilla.org.cer.h (100%) rename {sec => Security/sec}/Security/Regressions/secitem/si-67-sectrust-blacklist/login.live.com.cer.h (100%) rename {sec => Security/sec}/Security/Regressions/secitem/si-67-sectrust-blacklist/login.skype.com.cer.h (100%) rename {sec => Security/sec}/Security/Regressions/secitem/si-67-sectrust-blacklist/login.yahoo.com.1.cer.h (100%) rename {sec => Security/sec}/Security/Regressions/secitem/si-67-sectrust-blacklist/login.yahoo.com.2.cer.h (100%) rename {sec => Security/sec}/Security/Regressions/secitem/si-67-sectrust-blacklist/login.yahoo.com.cer.h (100%) rename {sec => Security/sec}/Security/Regressions/secitem/si-67-sectrust-blacklist/mail.google.com.cer.h (100%) rename {sec => Security/sec}/Security/Regressions/secitem/si-67-sectrust-blacklist/www.google.com.cer.h (100%) rename {sec => Security/sec}/Security/Regressions/secitem/si-68-secmatchissuer.c (89%) rename {sec => Security/sec}/Security/Regressions/secitem/si-69-keydesc.c (79%) create mode 100644 Security/sec/Security/Regressions/secitem/si-70-sectrust-unified.c create mode 100644 Security/sec/Security/Regressions/secitem/si-71-mobile-store-policy.c rename {sec => Security/sec}/Security/Regressions/secitem/si-72-syncableitems.c (84%) rename {sec => Security/sec}/Security/Regressions/secitem/si-73-secpasswordgenerate.c (93%) rename {sec => Security/sec}/Security/Regressions/secitem/si-74-OTAPKISigner.c (98%) rename {sec => Security/sec}/Security/Regressions/secitem/si-75-AppleIDRecordSigning.c (94%) create mode 100644 Security/sec/Security/Regressions/secitem/si-76-shared-credentials.c create mode 100644 Security/sec/Security/Regressions/secitem/si-78-query-attrs.c create mode 100644 Security/sec/Security/Regressions/secitem/si-79-smp-cert-policy.c create mode 100644 Security/sec/Security/Regressions/secitem/si-80-empty-data.c create mode 100644 Security/sec/Security/Regressions/secitem/si-81-item-acl-stress.c create mode 100644 Security/sec/Security/Regressions/secitem/si-81-sectrust-server-auth.c create mode 100644 Security/sec/Security/Regressions/secitem/si_77_SecAccessControl.c rename {sec => Security/sec}/Security/Regressions/vmdh/vmdh-40.c (96%) rename {sec => Security/sec}/Security/Regressions/vmdh/vmdh-41-example.c (96%) rename {sec => Security/sec}/Security/Regressions/vmdh/vmdh-42-example2.c (97%) create mode 100644 Security/sec/Security/SecAccessControl.c create mode 100644 Security/sec/Security/SecAccessControl.h create mode 100644 Security/sec/Security/SecAccessControlExports.exp-in create mode 100644 Security/sec/Security/SecAccessControlPriv.h create mode 100644 Security/sec/Security/SecBase.h rename {sec => Security/sec}/Security/SecBase64.c (100%) rename {sec => Security/sec}/Security/SecBase64.h (100%) create mode 100644 Security/sec/Security/SecBasePriv.h create mode 100644 Security/sec/Security/SecCMS.c create mode 100644 Security/sec/Security/SecCMS.h rename {sec => Security/sec}/Security/SecCertificate.c (98%) create mode 100644 Security/sec/Security/SecCertificate.h rename {sec => Security/sec}/Security/SecCertificateInternal.h (99%) rename {sec => Security/sec}/Security/SecCertificatePath.c (93%) rename {sec => Security/sec}/Security/SecCertificatePath.h (98%) create mode 100644 Security/sec/Security/SecCertificatePriv.h rename {sec => Security/sec}/Security/SecCertificateRequest.c (95%) create mode 100644 Security/sec/Security/SecCertificateRequest.h create mode 100644 Security/sec/Security/SecDH.c rename {sec => Security/sec}/Security/SecDH.h (91%) create mode 100644 Security/sec/Security/SecECKey.c rename {sec => Security/sec}/Security/SecECKey.h (92%) create mode 100644 Security/sec/Security/SecECKeyPriv.h rename {sec => Security/sec}/Security/SecExports.exp-in (92%) rename {sec => Security/sec}/Security/SecFramework.c (80%) rename {sec => Security/sec}/Security/SecFramework.h (96%) rename {sec => Security/sec}/Security/SecFrameworkStrings.h (92%) create mode 100644 Security/sec/Security/SecIdentity.c create mode 100644 Security/sec/Security/SecIdentity.h create mode 100644 Security/sec/Security/SecIdentityPriv.h create mode 100644 Security/sec/Security/SecImportExport.c create mode 100644 Security/sec/Security/SecImportExport.h create mode 100644 Security/sec/Security/SecInternal.h rename {sec => Security/sec}/Security/SecItem.c (80%) create mode 100644 Security/sec/Security/SecItem.h create mode 100644 Security/sec/Security/SecItemConstants.c rename {sec => Security/sec}/Security/SecItemInternal.h (81%) create mode 100644 Security/sec/Security/SecItemPriv.h rename {sec => Security/sec}/Security/SecKey.c (94%) create mode 100644 Security/sec/Security/SecKey.h rename {sec => Security/sec}/Security/SecKeyInternal.h (91%) create mode 100644 Security/sec/Security/SecKeyPriv.h create mode 100644 Security/sec/Security/SecLogging.c create mode 100644 Security/sec/Security/SecLogging.h create mode 100644 Security/sec/Security/SecOTR.h create mode 100644 Security/sec/Security/SecOTRDHKey.c create mode 100644 Security/sec/Security/SecOTRDHKey.h create mode 100644 Security/sec/Security/SecOTRErrors.h rename {sec => Security/sec}/Security/SecOTRFullIdentity.c (94%) rename {sec => Security/sec}/Security/SecOTRIdentityPriv.h (75%) rename {sec => Security/sec}/Security/SecOTRMath.c (79%) create mode 100644 Security/sec/Security/SecOTRMath.h create mode 100644 Security/sec/Security/SecOTRPacketData.c rename {sec => Security/sec}/Security/SecOTRPacketData.h (82%) rename {sec => Security/sec}/Security/SecOTRPackets.c (89%) create mode 100644 Security/sec/Security/SecOTRPackets.h rename {sec => Security/sec}/Security/SecOTRPublicIdentity.c (83%) create mode 100644 Security/sec/Security/SecOTRSession.c create mode 100644 Security/sec/Security/SecOTRSession.h rename {sec => Security/sec}/Security/SecOTRSessionAKE.c (91%) create mode 100644 Security/sec/Security/SecOTRSessionPriv.h rename {sec => Security/sec}/Security/SecOTRUtils.c (79%) create mode 100644 Security/sec/Security/SecOnOSX.h rename {sec => Security/sec}/Security/SecPBKDF.c (96%) rename {sec => Security/sec}/Security/SecPBKDF.h (97%) rename {sec => Security/sec}/Security/SecPasswordGenerate.c (88%) rename {sec => Security/sec}/Security/SecPasswordGenerate.h (87%) rename {sec => Security/sec}/Security/SecPolicy.c (88%) create mode 100644 Security/sec/Security/SecPolicy.h create mode 100644 Security/sec/Security/SecPolicyCerts.h rename {sec => Security/sec}/Security/SecPolicyInternal.h (98%) create mode 100644 Security/sec/Security/SecPolicyPriv.h rename {sec => Security/sec}/Security/SecRSAKey.c (99%) rename {sec => Security/sec}/Security/SecRSAKey.h (96%) rename {sec => Security/sec}/Security/SecRSAKeyPriv.h (95%) create mode 100644 Security/sec/Security/SecRandom.h rename {sec => Security/sec}/Security/SecSCEP.c (94%) rename {sec => Security/sec}/Security/SecSCEP.h (98%) create mode 100644 Security/sec/Security/SecServerEncryptionSupport.c create mode 100644 Security/sec/Security/SecServerEncryptionSupport.h create mode 100644 Security/sec/Security/SecSharedCredential.c create mode 100644 Security/sec/Security/SecSharedCredential.h rename {sec => Security/sec}/Security/SecTrust.c (96%) create mode 100644 Security/sec/Security/SecTrust.h create mode 100644 Security/sec/Security/SecTrustPriv.h rename {sec => Security/sec}/Security/SecTrustSettings.c (94%) create mode 100644 Security/sec/Security/SecTrustSettings.h create mode 100644 Security/sec/Security/SecTrustSettingsPriv.h rename {sec => Security/sec}/Security/SecTrustStore.c (97%) rename {sec => Security/sec}/Security/SecTrustStore.h (96%) create mode 100644 Security/sec/Security/Security.h rename {sec => Security/sec}/Security/SecuritydXPC.c (77%) create mode 100644 Security/sec/Security/SecuritydXPC.h rename {sec => Security/sec}/Security/Tool/SecurityCommands.h (90%) rename {sec => Security/sec}/Security/Tool/add_internet_password.c (83%) create mode 100644 Security/sec/Security/Tool/codesign.c create mode 100644 Security/sec/Security/Tool/keychain_add.c rename {sec => Security/sec}/Security/Tool/keychain_backup.c (98%) create mode 100644 Security/sec/Security/Tool/keychain_find.c create mode 100644 Security/sec/Security/Tool/keychain_util.c create mode 100644 Security/sec/Security/Tool/keychain_util.h create mode 100644 Security/sec/Security/Tool/log_control.c rename {sec => Security/sec}/Security/Tool/pkcs12_util.c (99%) rename {sec => Security/sec}/Security/Tool/scep.c (91%) rename {sec => Security/sec}/Security/Tool/show_certificates.c (77%) rename {sec => Security/sec}/Security/Tool/spc.c (93%) create mode 100644 Security/sec/Security/certextensions.h create mode 100644 Security/sec/Security/cssmapple.h create mode 100644 Security/sec/Security/keychain_find.h rename {sec => Security/sec}/Security/p12import.c (97%) rename {sec => Security/sec}/Security/p12import.h (94%) rename {sec => Security/sec}/Security/p12pbegen.c (99%) rename {sec => Security/sec}/Security/p12pbegen.h (94%) create mode 100644 Security/sec/Security/pbkdf2.c create mode 100644 Security/sec/Security/pbkdf2.h create mode 100644 Security/sec/Security/so_01_serverencryption.c create mode 100644 Security/sec/Security/vmdh.c create mode 100644 Security/sec/Security/vmdh.h rename {sec => Security/sec}/SecurityTool/SecurityTool.c (99%) rename {sec => Security/sec}/SecurityTool/SecurityTool.h (96%) create mode 100644 Security/sec/SecurityTool/builtin_commands.h create mode 100644 Security/sec/SecurityTool/digest_calc.c rename {sec => Security/sec}/SecurityTool/entitlements.plist (100%) create mode 100644 Security/sec/SecurityTool/leaks.c create mode 100644 Security/sec/SecurityTool/leaks.h rename {sec => Security/sec}/SecurityTool/print_cert.c (98%) rename {sec => Security/sec}/SecurityTool/print_cert.h (92%) rename {sec => Security/sec}/SecurityTool/security.1 (100%) create mode 100644 Security/sec/SecurityTool/tool_errors.h create mode 100644 Security/sec/SharedWebCredential/com.apple.security.swcagent.plist create mode 100644 Security/sec/SharedWebCredential/swcagent.m create mode 100644 Security/sec/SharedWebCredential/swcagent_client.c create mode 100644 Security/sec/SharedWebCredential/swcagent_client.h create mode 100644 Security/sec/config/base.xcconfig rename {sec => Security/sec}/config/debug.xcconfig (100%) rename {sec => Security/sec}/config/lib-arc-only.xcconfig (100%) create mode 100644 Security/sec/config/lib.xcconfig rename {sec => Security/sec}/config/release.xcconfig (100%) rename {sec => Security/sec}/ipc/client.c (90%) create mode 100644 Security/sec/ipc/com.apple.secd.plist create mode 100644 Security/sec/ipc/com.apple.securityd.plist create mode 100755 Security/sec/ipc/securityd_client.h create mode 100644 Security/sec/ipc/server.c create mode 100644 Security/sec/sec.xcodeproj/project.pbxproj rename {sec => Security/sec}/securityd/OTATrustUtilities.c (84%) rename {sec => Security/sec}/securityd/OTATrustUtilities.h (87%) create mode 100644 Security/sec/securityd/Regressions/SOSAccountTesting.h create mode 100644 Security/sec/securityd/Regressions/SOSTransportTestTransports.c create mode 100644 Security/sec/securityd/Regressions/SOSTransportTestTransports.h create mode 100644 Security/sec/securityd/Regressions/SecdTestKeychainUtilities.c create mode 100644 Security/sec/securityd/Regressions/SecdTestKeychainUtilities.h create mode 100644 Security/sec/securityd/Regressions/ios6_1_keychain_2_db.h rename {sec => Security/sec}/securityd/Regressions/sd-10-policytree.c (97%) rename {sec => Security/sec}/securityd/Regressions/secd-01-items.c (80%) rename {sec => Security/sec}/securityd/Regressions/secd-02-upgrade-while-locked.c (79%) rename {sec => Security/sec}/securityd/Regressions/secd-03-corrupted-items.c (81%) rename {sec => Security/sec}/securityd/Regressions/secd-04-corrupted-items.c (82%) rename {sec => Security/sec}/securityd/Regressions/secd-05-corrupted-items.c (81%) rename {sec => Security/sec}/securityd/Regressions/secd-30-keychain-upgrade.c (87%) rename {sec => Security/sec}/securityd/Regressions/secd-31-keychain-bad.c (78%) create mode 100644 Security/sec/securityd/Regressions/secd-31-keychain-unreadable.c create mode 100644 Security/sec/securityd/Regressions/secd-50-account.c rename {sec => Security/sec}/securityd/Regressions/secd-51-account-inflate.c (77%) create mode 100644 Security/sec/securityd/Regressions/secd-52-account-changed.c create mode 100644 Security/sec/securityd/Regressions/secd-55-account-circle.c create mode 100644 Security/sec/securityd/Regressions/secd-55-account-incompatibility.c create mode 100644 Security/sec/securityd/Regressions/secd-56-account-apply.c create mode 100644 Security/sec/securityd/Regressions/secd-57-account-leave.c create mode 100644 Security/sec/securityd/Regressions/secd-58-password-change.c create mode 100644 Security/sec/securityd/Regressions/secd-59-account-cleanup.c create mode 100644 Security/sec/securityd/Regressions/secd-60-account-cloud-identity.c create mode 100644 Security/sec/securityd/Regressions/secd-61-account-leave-not-in-kansas-anymore.c create mode 100644 Security/sec/securityd/Regressions/secd-70-engine-corrupt.c create mode 100644 Security/sec/securityd/Regressions/secd-70-engine.c create mode 100644 Security/sec/securityd/Regressions/secd-70-otr-remote.c create mode 100644 Security/sec/securityd/Regressions/secd_regressions.h create mode 100644 Security/sec/securityd/Regressions/securityd_regressions.h create mode 100644 Security/sec/securityd/SOSCloudCircleServer.c create mode 100644 Security/sec/securityd/SOSCloudCircleServer.h rename {sec => Security/sec}/securityd/SecCAIssuerCache.c (99%) rename {sec => Security/sec}/securityd/SecCAIssuerCache.h (94%) rename {sec => Security/sec}/securityd/SecCAIssuerRequest.c (97%) create mode 100644 Security/sec/securityd/SecCAIssuerRequest.h rename {sec => Security/sec}/securityd/SecDbItem.c (80%) create mode 100644 Security/sec/securityd/SecDbItem.h create mode 100644 Security/sec/securityd/SecDbKeychainItem.c create mode 100644 Security/sec/securityd/SecDbKeychainItem.h create mode 100644 Security/sec/securityd/SecDbQuery.c create mode 100644 Security/sec/securityd/SecDbQuery.h create mode 100644 Security/sec/securityd/SecItemDataSource.c create mode 100644 Security/sec/securityd/SecItemDataSource.h create mode 100644 Security/sec/securityd/SecItemDb.c create mode 100644 Security/sec/securityd/SecItemDb.h create mode 100644 Security/sec/securityd/SecItemSchema.c create mode 100644 Security/sec/securityd/SecItemSchema.h create mode 100644 Security/sec/securityd/SecItemServer.c create mode 100644 Security/sec/securityd/SecItemServer.h create mode 100644 Security/sec/securityd/SecKeybagSupport.c create mode 100644 Security/sec/securityd/SecKeybagSupport.h create mode 100644 Security/sec/securityd/SecLogSettingsServer.c create mode 100644 Security/sec/securityd/SecLogSettingsServer.h rename {sec => Security/sec}/securityd/SecOCSPCache.c (98%) rename {sec => Security/sec}/securityd/SecOCSPCache.h (98%) rename {sec => Security/sec}/securityd/SecOCSPRequest.c (98%) rename {sec => Security/sec}/securityd/SecOCSPRequest.h (96%) rename {sec => Security/sec}/securityd/SecOCSPResponse.c (94%) rename {sec => Security/sec}/securityd/SecOCSPResponse.h (98%) create mode 100644 Security/sec/securityd/SecOTRRemote.c create mode 100644 Security/sec/securityd/SecOTRRemote.h rename {sec => Security/sec}/securityd/SecPolicyServer.c (96%) rename {sec => Security/sec}/securityd/SecPolicyServer.h (97%) rename {sec => Security/sec}/securityd/SecTrustServer.c (99%) rename {sec => Security/sec}/securityd/SecTrustServer.h (97%) rename {sec => Security/sec}/securityd/SecTrustStoreServer.c (99%) rename {sec => Security/sec}/securityd/SecTrustStoreServer.h (95%) rename {sec => Security/sec}/securityd/asynchttp.c (96%) rename {sec => Security/sec}/securityd/asynchttp.h (96%) create mode 100644 Security/sec/securityd/entitlements.plist create mode 100644 Security/sec/securityd/iCloudTrace.c create mode 100644 Security/sec/securityd/iCloudTrace.h rename {sec => Security/sec}/securityd/policytree.c (99%) rename {sec => Security/sec}/securityd/policytree.h (97%) create mode 100644 Security/sec/securityd/spi.c create mode 100644 Security/sec/securityd/spi.h create mode 100644 Security/secdtests/main.c create mode 100644 Security/secdtests/testlist.h rename {sectests => Security/sectests}/SecurityTests-Entitlements.plist (100%) create mode 100644 Security/sectests/main.c create mode 100644 Security/sectests/test/testenv.c create mode 100644 Security/sectests/testlist.h create mode 100644 Security/security2/security2.1 create mode 100644 Security/security2/security_tool_commands.c create mode 100644 Security/security2/sub_commands.h rename {tlsnke => Security/tlsnke}/loadkext.sh (100%) create mode 100644 Security/tlsnke/tlsnke.xcodeproj/project.pbxproj rename {tlsnke => Security/tlsnke}/tlsnke.xcodeproj/project.xcworkspace/contents.xcworkspacedata (100%) rename {tlsnke => Security/tlsnke}/tlsnke.xcodeproj/xcshareddata/xcschemes/Device.xcscheme (96%) rename {tlsnke => Security/tlsnke}/tlsnke.xcodeproj/xcshareddata/xcschemes/Host.xcscheme (96%) rename {tlsnke => Security/tlsnke}/tlsnke.xcodeproj/xcshareddata/xcschemes/tlsnke.xcscheme (94%) rename {tlsnke => Security/tlsnke}/tlsnke.xcodeproj/xcshareddata/xcschemes/tlsnketest.xcscheme (96%) create mode 100644 Security/tlsnke/tlsnke/en.lproj/InfoPlist.strings rename {tlsnke => Security/tlsnke}/tlsnke/tlsnke-Info.plist (100%) rename {tlsnke => Security/tlsnke}/tlsnke/tlsnke-Prefix.pch (100%) rename {tlsnke => Security/tlsnke}/tlsnke/tlsnke.c (97%) create mode 100644 Security/tlsnke/tlsnke/tlsnke.h rename {tlsnke => Security/tlsnke}/tlsnketest/cert-1.h (100%) rename {tlsnke => Security/tlsnke}/tlsnketest/dtls_client.c (84%) rename {tlsnke => Security/tlsnke}/tlsnketest/identity-1.h (100%) create mode 100644 Security/tlsnke/tlsnketest/main.c rename {tlsnke => Security/tlsnke}/tlsnketest/privkey-1.h (100%) create mode 100644 Security/tlsnke/tlsnketest/ssl-utils.c create mode 100644 Security/tlsnke/tlsnketest/ssl-utils.h rename {tlsnke => Security/tlsnke}/tlsnketest/st_test.c (96%) rename {tlsnke => Security/tlsnke}/tlsnketest/tlssocket.c (86%) create mode 100644 Security/tlsnke/tlsnketest/tlssocket.h create mode 100644 Security/utilities/Regressions/su-05-cfwrappers.c create mode 100644 Security/utilities/Regressions/su-07-debugging.c create mode 100644 Security/utilities/Regressions/su-10-cfstring-der.c rename {utilities => Security/utilities}/Regressions/su-11-cfdata-der.c (88%) create mode 100644 Security/utilities/Regressions/su-12-cfboolean-der.c rename {utilities => Security/utilities}/Regressions/su-13-cfnumber-der.c (77%) rename {utilities => Security/utilities}/Regressions/su-14-cfarray-der.c (77%) rename {utilities => Security/utilities}/Regressions/su-15-cfdictionary-der.c (86%) rename {utilities => Security/utilities}/Regressions/su-16-cfdate-der.c (87%) rename {utilities => Security/utilities}/Regressions/su-40-secdb.c (87%) rename {utilities => Security/utilities}/Regressions/su-41-secdb-stress.c (86%) rename {utilities => Security/utilities}/Regressions/utilities_regressions.h (88%) create mode 100644 Security/utilities/SecLogging.mobileconfig create mode 100644 Security/utilities/SecurityTool/not_on_this_platorm.c create mode 100644 Security/utilities/SecurityTool/readline.c create mode 100644 Security/utilities/SecurityTool/readline.h create mode 100644 Security/utilities/SecurityTool/security_tool_commands.h create mode 100644 Security/utilities/SecurityTool/security_tool_commands_table.h create mode 100644 Security/utilities/config/lib.xcconfig rename {utilities => Security/utilities}/src/SecAKSWrappers.c (97%) create mode 100644 Security/utilities/src/SecAKSWrappers.h create mode 100644 Security/utilities/src/SecCFError.c create mode 100644 Security/utilities/src/SecCFError.h create mode 100644 Security/utilities/src/SecCFRelease.h create mode 100644 Security/utilities/src/SecCFWrappers.c create mode 100644 Security/utilities/src/SecCFWrappers.h rename {utilities => Security/utilities}/src/SecCertificateTrace.c (93%) rename {utilities => Security/utilities}/src/SecCertificateTrace.h (95%) rename {utilities => Security/utilities}/src/SecDb.c (92%) create mode 100644 Security/utilities/src/SecDb.h create mode 100644 Security/utilities/src/SecDispatchRelease.h rename {utilities => Security/utilities}/src/SecFileLocations.c (99%) rename {utilities => Security/utilities}/src/SecFileLocations.h (95%) create mode 100644 Security/utilities/src/SecIOFormat.h create mode 100644 Security/utilities/src/SecMeta.h create mode 100644 Security/utilities/src/SecXPCError.c create mode 100644 Security/utilities/src/SecXPCError.h create mode 100644 Security/utilities/src/array_size.h rename {utilities => Security/utilities}/src/cloud_keychain_diagnose.c (97%) create mode 100644 Security/utilities/src/comparison.c create mode 100644 Security/utilities/src/comparison.h create mode 100644 Security/utilities/src/debugging.c create mode 100644 Security/utilities/src/debugging.h create mode 100644 Security/utilities/src/debugging_test.h create mode 100644 Security/utilities/src/der_array.c create mode 100644 Security/utilities/src/der_boolean.c create mode 100644 Security/utilities/src/der_data.c create mode 100644 Security/utilities/src/der_date.c create mode 100644 Security/utilities/src/der_date.h rename {utilities => Security/utilities}/src/der_dictionary.c (85%) create mode 100644 Security/utilities/src/der_null.c rename {utilities => Security/utilities}/src/der_number.c (77%) rename {utilities => Security/utilities}/src/der_plist.c (82%) create mode 100644 Security/utilities/src/der_plist.h create mode 100644 Security/utilities/src/der_plist_internal.c rename {utilities => Security/utilities}/src/der_plist_internal.h (79%) create mode 100644 Security/utilities/src/der_string.c create mode 100644 Security/utilities/src/fileIo.c create mode 100644 Security/utilities/src/fileIo.h create mode 100644 Security/utilities/src/iCloudKeychainTrace.c create mode 100644 Security/utilities/src/iCloudKeychainTrace.h create mode 100644 Security/utilities/src/iOSforOSX-SecAttr.c create mode 100644 Security/utilities/src/iOSforOSX-SecRandom.c create mode 100644 Security/utilities/src/iOSforOSX.c create mode 100644 Security/utilities/src/iOSforOSX.h create mode 100644 Security/utilities/src/simulate_crash.c create mode 100644 Security/utilities/src/sqlutils.h rename {utilities => Security/utilities}/utilities (100%) create mode 100644 Security/utilities/utilities.xcodeproj/project.pbxproj create mode 100644 SecurityTests/AppleID-certs/Apple Application Integration Certification Authority Cert.crt create mode 100644 SecurityTests/AppleID-certs/Apple Production ShareServices-7130767241416543643077536561487847634e4d6f773d3d.crt create mode 100644 SecurityTests/AppleID-certs/AppleRootCertificate.crt create mode 100644 SecurityTests/AppleID-certs/Invalid-asset_signing.crt create mode 100644 SecurityTests/AppleID-certs/iPhoneCACert.crt create mode 100644 SecurityTests/CreateCerts.sh create mode 100644 SecurityTests/DigiNotar/DigiNotarCA2007RootCertificate.crt create mode 100644 SecurityTests/DigiNotar/DigiNotar_Root_CA_G2-RootCertificate.crt create mode 100644 SecurityTests/DigiNotar/Expectations.plist create mode 100644 SecurityTests/DigiNotar/Invalid-CertiID_Enterprise_Certificate_Authority.crt create mode 100644 SecurityTests/DigiNotar/Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt create mode 100644 SecurityTests/DigiNotar/Invalid-asterisk.google.com.crt create mode 100644 SecurityTests/DigiNotar/Invalid-diginotarpkioverheidcaoverheid.crt create mode 100644 SecurityTests/DigiNotar/Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt create mode 100644 SecurityTests/DigiNotar/Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt create mode 100644 SecurityTests/DigiNotar/Invalid-webmail.portofamsterdam.nl.crt create mode 100644 SecurityTests/DigiNotar/Invalid-webmail.terneuzen.nl-diginotar-services.crt create mode 100644 SecurityTests/DigiNotar/Invalid-www.maestre.com-diginotal.extended.validation.crt create mode 100644 SecurityTests/DigiNotar/Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt create mode 100644 SecurityTests/DigiNotar/Ministerie_van_Defensie_Certificatie_Autoriteit.crt create mode 100644 SecurityTests/DigiNotar/Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt create mode 100644 SecurityTests/DigiNotar/diginotar-public-ca-2025-Cert.crt create mode 100644 SecurityTests/DigiNotar/diginotar-services-1024-entrust-secure-server-Cert.crt create mode 100644 SecurityTests/DigiNotar/diginotar-services-diginotar-root-Cert.crt create mode 100644 SecurityTests/DigiNotar/diginotar.cyberca-gte.global.root-Cert.crt create mode 100644 SecurityTests/DigiNotar/diginotar.extended.validation-diginotar.root.ca-Cert.crt create mode 100644 SecurityTests/DigiNotar/diginotar.root.ca-entrust-secure-server-Cert.crt create mode 100644 SecurityTests/DigiNotar/staatdernederlandenorganisatieca-g2-Cert.crt create mode 100644 SecurityTests/DigiNotar/staatdernederlandenoverheidca-Cert.crt create mode 100644 SecurityTests/DigicertMalaysia/Digisign-Server-ID-Enrich-Entrust-Cert.crt create mode 100644 SecurityTests/DigicertMalaysia/Digisign-Server-ID-Enrich-GTETrust-Cert.crt create mode 100644 SecurityTests/DigicertMalaysia/Invalid-webmail.jaring.my.crt create mode 100644 SecurityTests/DigicertMalaysia/Invalid-www.cybersecurity.my.crt create mode 100644 SecurityTests/OTATasking-certs/Invalid-asset_signing.crt create mode 100644 SecurityTests/OTATasking-certs/task_signing.crt create mode 100644 SecurityTests/PKITS.pdf create mode 100644 SecurityTests/PostSecurityTests.sh create mode 100644 SecurityTests/PreSecurityTests.sh create mode 100644 SecurityTests/SecurityDevTests-Info.plist create mode 100644 SecurityTests/SecurityTests-Entitlements.plist create mode 100644 SecurityTests/SecurityTests-Info.plist create mode 100644 SecurityTests/StartTLSServers.sh create mode 100644 SecurityTests/StopTLSServers.sh create mode 100644 SecurityTests/clxutils/ChangeLog create mode 100644 SecurityTests/clxutils/Makefile create mode 100644 SecurityTests/clxutils/Makefile.cdsa create mode 100644 SecurityTests/clxutils/Makefile.lib create mode 100755 SecurityTests/clxutils/NISCC/TLS_SSL/CoveringLetter.pdf create mode 100644 SecurityTests/clxutils/NISCC/TLS_SSL/Makefile create mode 100644 SecurityTests/clxutils/NISCC/TLS_SSL/README.txt create mode 100755 SecurityTests/clxutils/NISCC/TLS_SSL/SSL_TLS.pdf create mode 100644 SecurityTests/clxutils/NISCC/TLS_SSL/certDecode/Makefile create mode 100644 SecurityTests/clxutils/NISCC/TLS_SSL/certDecode/certDecode.cpp create mode 100644 SecurityTests/clxutils/NISCC/TLS_SSL/dmitchNotes create mode 100644 SecurityTests/clxutils/NISCC/TLS_SSL/nisccCertVerify/Makefile create mode 100644 SecurityTests/clxutils/NISCC/TLS_SSL/nisccCertVerify/nisccCertVerify.cpp create mode 100644 SecurityTests/clxutils/NISCC/TLS_SSL/nisccSimpleClient/Makefile create mode 100644 SecurityTests/clxutils/NISCC/TLS_SSL/nisccSimpleClient/nisccSimpleClient.cpp create mode 100755 SecurityTests/clxutils/NISCC/TLS_SSL/nisccSslTest create mode 100644 SecurityTests/clxutils/NISCC/TLS_SSL/skipThisNisccCert/Makefile create mode 100644 SecurityTests/clxutils/NISCC/TLS_SSL/skipThisNisccCert/skipThisNisccCert.cpp create mode 100755 SecurityTests/clxutils/NISCC/TLS_SSL/testcases/client.crt create mode 100755 SecurityTests/clxutils/NISCC/TLS_SSL/testcases/client_crt.pem create mode 100644 SecurityTests/clxutils/NISCC/TLS_SSL/testcases/client_key.der create mode 100755 SecurityTests/clxutils/NISCC/TLS_SSL/testcases/client_key.pem create mode 100755 SecurityTests/clxutils/NISCC/TLS_SSL/testcases/readme.txt create mode 100755 SecurityTests/clxutils/NISCC/TLS_SSL/testcases/rootca.crt create mode 100755 SecurityTests/clxutils/NISCC/TLS_SSL/testcases/rootca_crt.pem create mode 100755 SecurityTests/clxutils/NISCC/TLS_SSL/testcases/rootca_key.pem create mode 100755 SecurityTests/clxutils/NISCC/TLS_SSL/testcases/server.crt create mode 100755 SecurityTests/clxutils/NISCC/TLS_SSL/testcases/server_crt.pem create mode 100755 SecurityTests/clxutils/NISCC/TLS_SSL/testcases/server_key.pem create mode 100644 SecurityTests/clxutils/README create mode 100644 SecurityTests/clxutils/anchorTest/Makefile create mode 100755 SecurityTests/clxutils/anchorTest/anchorSourceTest create mode 100644 SecurityTests/clxutils/anchorTest/anchorTest.cpp create mode 100755 SecurityTests/clxutils/anchorTest/buildCertKeychains create mode 100755 SecurityTests/clxutils/anchorTest/intermedSourceTest create mode 100755 SecurityTests/clxutils/anchorTest/intermedTest create mode 100644 SecurityTests/clxutils/caVerify/Makefile create mode 100644 SecurityTests/clxutils/caVerify/caVerify.cpp create mode 100755 SecurityTests/clxutils/certChain/Makefile create mode 100644 SecurityTests/clxutils/certChain/README create mode 100644 SecurityTests/clxutils/certChain/amazon_v3.100.cer create mode 100644 SecurityTests/clxutils/certChain/certChain.cpp create mode 100644 SecurityTests/clxutils/certChain/keybank_v3.100.cer create mode 100644 SecurityTests/clxutils/certChain/keybank_v3.101.cer create mode 100644 SecurityTests/clxutils/certInCrl/Makefile create mode 100644 SecurityTests/clxutils/certInCrl/certInCrl.cpp create mode 100644 SecurityTests/clxutils/certLabelTest/Makefile create mode 100644 SecurityTests/clxutils/certLabelTest/certLabelTest.cpp create mode 100644 SecurityTests/clxutils/certSerialEncodeTest/Makefile create mode 100644 SecurityTests/clxutils/certSerialEncodeTest/certSerialEncodeTest.cpp create mode 100644 SecurityTests/clxutils/certTime/Makefile create mode 100644 SecurityTests/clxutils/certTime/anchor_0 create mode 100644 SecurityTests/clxutils/certTime/anchor_34 create mode 100644 SecurityTests/clxutils/certTime/anchor_44 create mode 100644 SecurityTests/clxutils/certTime/anchor_76 create mode 100644 SecurityTests/clxutils/certTime/anchor_80 create mode 100644 SecurityTests/clxutils/certTime/anchor_9 create mode 100644 SecurityTests/clxutils/certTime/certTime.cpp create mode 100644 SecurityTests/clxutils/certTime/extenCooker.cpp create mode 100644 SecurityTests/clxutils/certTime/extenCooker.h create mode 100755 SecurityTests/clxutils/certTime/runTime create mode 100644 SecurityTests/clxutils/certcrl/Makefile create mode 100644 SecurityTests/clxutils/certcrl/README.doc create mode 100644 SecurityTests/clxutils/certcrl/certcrl.cpp create mode 100644 SecurityTests/clxutils/certcrl/script.cpp create mode 100644 SecurityTests/clxutils/certcrl/script.h create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleCerts.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleDevelopment.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleQuickTime.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleROOTCA.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleSWUPDATE.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleSecUpdate.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleSherlock.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleSignUpdate.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleSoftUpdate.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/AppleCodeSigning.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/CodeSignTest.keychain create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csCA.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csCaBadEKU.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csCaBadPLC.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csCaNoBC.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csCaNoEKU.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csCaNoPLC.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csDevLeaf.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csLeaf.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csLeafBadEKU.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csLeafBadEKUinInt.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csLeafBadPLCinInt.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csLeafNoBcInInt.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csLeafNoEKU.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csLeafNoEKUinInt.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csLeafNoPLCinInt.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csLeafShortPath.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csRoot.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/CodePkgSigning/BadCodeSignLeaf.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/CodePkgSigning/CodePkgSigning.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/CodePkgSigning/CodeSignLeaf.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/CodePkgSigning/CodeSignRoot.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/CodePkgSigning/NoEKULeaf.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/GarthCRL/.gdb_history create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/GarthCRL/CNTMTT68S21G224G.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/GarthCRL/InfoCamereFirmaQualificata.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/GarthCRL/InfoCamereRoot.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/GarthCRL/crl.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/GarthCRL/fetched.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/ECCCA.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/ECCp192.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/ECCp224.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/ECCp256.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/ECCp384.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/ECCp521.cer create mode 100755 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P256_Specified_SHA1.cer create mode 100755 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P256_Specified_SHA256.cer create mode 100755 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P256_combined_SHA256.cer create mode 100755 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P256_combined_SHA512.cer create mode 100755 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P384_Specified_SHA256.cer create mode 100755 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P384_Specified_SHA384.cer create mode 100755 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P384_combined_SHA1.cer create mode 100755 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P384_combined_SHA256.cer create mode 100755 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P521_Specified_SHA1.cer create mode 100755 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P521_combined_SHA1.cer create mode 100755 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P521_combined_SHA512.cer create mode 100755 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/RootP256.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/msEcc.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/nssecc.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/opensslEcc.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/secp256r1ca.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/secp256r1server-secp256r1ca.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/secp384r1ca.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/secp384r1server-secp384r1ca.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/secp521r1ca.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/secp521r1server-secp521r1ca.cer create mode 100755 SecurityTests/clxutils/certcrl/testSubjects/X509tests/Certificate Path.pdf create mode 100755 SecurityTests/clxutils/certcrl/testSubjects/X509tests/makeCertScr create mode 100755 SecurityTests/clxutils/certcrl/testSubjects/X509tests/runCertScr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test1/End Certificate CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test1/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test1/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test10/End Certificate CP.03.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test10/Intermediate CRL CP.03.02.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test10/Intermediate Certificate CP.03.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test10/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test10/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test11/End Certificate CP.03.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test11/Intermediate CRL CP.03.03.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test11/Intermediate Certificate CP.03.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test11/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test11/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test12/End Certificate CP.03.04.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test12/Intermediate CRL CP.03.04.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test12/Intermediate Certificate CP.03.04.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test12/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test12/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test13/End Certificate CP.04.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test13/Intermediate CRL CP.04.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test13/Intermediate Certificate CP.04.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test13/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test13/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test14/End Certificate CP.04.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test14/Intermediate CRL CP.04.02.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test14/Intermediate Certificate CP.04.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test14/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test14/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test15/End Certificate CP.04.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test15/Intermediate CRL CP.04.03.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test15/Intermediate Certificate CP.04.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test15/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test15/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test16/End Certificate CP.04.04.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test16/Intermediate CRL CP.04.04.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test16/Intermediate Certificate CP.04.04.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test16/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test16/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test17/End Certificate CP.04.05.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test17/Intermediate CRL CP.04.05.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test17/Intermediate Certificate CP.04.05.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test17/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test17/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test18/End Certificate CP.04.06.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test18/Intermediate CRL CP.04.06.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test18/Intermediate Certificate CP.04.06.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test18/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test18/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test19/End Certificate CP.05.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test19/Intermediate Certificate CP.05.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test19/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test19/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test2/End Certificate CP.01.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test2/Intermediate CRL CP.01.02.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test2/Intermediate Certificate CP.01.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test2/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test2/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test20/End Certificate CP.06.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test20/Intermediate CRL CP.06.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test20/Intermediate Certificate CP.06.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test20/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test20/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test21/End Certificate CP.06.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test21/Intermediate CRL CP.06.02.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test21/Intermediate Certificate CP.06.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test21/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test21/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test22/End Certificate IC.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test22/Intermediate CRL IC.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test22/Intermediate Certificate IC.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test22/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test22/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test23/End Certificate IC.02.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test23/Intermediate CRL IC.02.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test23/Intermediate Certificate IC.02.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test23/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test23/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test24/End Certificate IC.02.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test24/Intermediate CRL IC.02.02.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test24/Intermediate Certificate IC.02.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test24/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test24/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test25/End Certificate IC.02.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test25/Intermediate CRL IC.02.03.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test25/Intermediate Certificate IC.02.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test25/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test25/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test26/End Certificate IC.02.04.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test26/Intermediate CRL IC.02.04.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test26/Intermediate Certificate IC.02.04.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test26/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test26/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test27/End Certificate IC.04.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test27/Intermediate CRL IC.04.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test27/Intermediate Certificate IC.04.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test27/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test27/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test28/End Certificate IC.05.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test28/Intermediate CRL IC.05.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test28/Intermediate Certificate IC.05.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test28/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test28/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test29/End Certificate IC.05.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test29/Intermediate CRL IC.05.02.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test29/Intermediate Certificate IC.05.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test29/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test29/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test3/End Certificate CP.01.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test3/Intermediate CRL CP.01.03.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test3/Intermediate Certificate CP.01.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test3/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test3/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test30/End Certificate IC.05.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test30/Intermediate CRL IC.05.03.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test30/Intermediate Certificate IC.05.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test30/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test30/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test31/End Certificate IC.06.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test31/Intermediate CRL IC.06.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test31/Intermediate Certificate IC.06.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test31/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test31/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test32/End Certificate IC.06.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test32/Intermediate CRL IC.06.02.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test32/Intermediate Certificate IC.06.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test32/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test32/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test33/End Certificate IC.06.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test33/Intermediate CRL IC.06.03.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test33/Intermediate Certificate IC.06.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test33/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test33/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test34/End Certificate PP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test34/Intermediate CRL PP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test34/Intermediate Certificate PP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test34/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test34/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test35/End Certificate PP.01.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test35/Intermediate CRL PP.01.02.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test35/Intermediate Certificate PP.01.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test35/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test35/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test36/End Certificate PP.01.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test36/Intermediate CRL 1 PP.01.03.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test36/Intermediate CRL 2 PP.01.03.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test36/Intermediate Certificate 1 PP.01.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test36/Intermediate Certificate 2 PP.01.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test36/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test36/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test37/End Certificate PP.01.04.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test37/Intermediate CRL 1 PP.01.04.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test37/Intermediate CRL 2 PP.01.04.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test37/Intermediate Certificate 1 PP.01.04.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test37/Intermediate Certificate 2 PP.01.04.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test37/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test37/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test38/End Certificate PP.01.05.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test38/Intermediate CRL 1 PP.01.05.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test38/Intermediate CRL 2 PP.01.05.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test38/Intermediate Certificate 1 PP.01.05.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test38/Intermediate Certificate 2 PP.01.05.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test38/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test38/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/End Certificate PP.01.06.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/Intermediate CRL 1 PP.01.06.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/Intermediate CRL 2 PP.01.06.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/Intermediate CRL 3 PP.01.06.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/Intermediate Certificate 1 PP.01.06.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/Intermediate Certificate 2 PP.01.06.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/Intermediate Certificate 3 PP.01.06.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test4/End Certificate CP.02.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test4/Intermediate CRL 1 CP.02.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test4/Intermediate CRL 2 CP.02.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test4/Intermediate Certificate 1 CP.02.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test4/Intermediate Certificate 2 CP.02.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test4/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test4/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/End Certificate PP.01.07.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/Intermediate CRL 1 PP.01.07.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/Intermediate CRL 2 PP.01.07.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/Intermediate CRL 3 PP.01.07.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/Intermediate Certificate 1 PP.01.07.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/Intermediate Certificate 2 PP.01.07.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/Intermediate Certificate 3 PP.01.07.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test41/End Certificate PP.01.08.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test41/Intermediate CRL 1 PP.01.08.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test41/Intermediate CRL 2 PP.01.08.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test41/Intermediate CRL 3 PP.01.08.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test41/Intermediate Certificate 1 PP.01.08.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test41/Intermediate Certificate 2 PP.01.08.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test41/Intermediate Certificate 3 PP.01.08.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test41/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test41/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/End Certificate PP.01.09.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/Intermediate CRL 1 PP.01.09.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/Intermediate CRL 2 PP.01.09.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/Intermediate CRL 3 PP.01.09.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/Intermediate CRL 4 PP.01.09.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/Intermediate Certificate 1 PP.01.09.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/Intermediate Certificate 2 PP.01.09.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/Intermediate Certificate 3 PP.01.09.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/Intermediate Certificate 4 PP.01.09.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/End Certificate PP.06.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Intermediate CRL 1 PP.06.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Intermediate CRL 2 PP.06.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Intermediate CRL 3 PP.06.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Intermediate CRL 4 PP.06.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Intermediate Certificate 1 PP.06.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Intermediate Certificate 2 PP.06.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Intermediate Certificate 3 PP.06.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Intermediate Certificate 4 PP.06.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/End Certificate PP.06.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/Intermediate CRL 1 PP.06.02.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/Intermediate CRL 2 PP.06.02.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/Intermediate CRL 3 PP.06.02.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/Intermediate CRL 4 PP.06.02.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/Intermediate Certificate 1 PP.06.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/Intermediate Certificate 2 PP.06.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/Intermediate Certificate 3 PP.06.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/Intermediate Certificate 4 PP.06.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/End Certificate PP.06.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Intermediate CRL 1 PP.06.03.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Intermediate CRL 2 PP.06.03.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Intermediate CRL 3 PP.06.03.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Intermediate CRL 4 PP.06.03.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Intermediate Certificate 1 PP.06.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Intermediate Certificate 2 PP.06.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Intermediate Certificate 3 PP.06.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Intermediate Certificate 4 PP.06.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/End Certificate PP.06.04.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Intermediate CRL 1 PP.06.04.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Intermediate CRL 2 PP.06.04.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Intermediate CRL 3 PP.06.04.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Intermediate CRL 4 PP.06.04.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Intermediate Certificate 1 PP.06.04.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Intermediate Certificate 2 PP.06.04.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Intermediate Certificate 3 PP.06.04.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Intermediate Certificate 4 PP.06.04.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test47/End Certificate PP.06.05.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test47/Intermediate CRL 1 PP.06.05.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test47/Intermediate CRL 2 PP.06.05.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test47/Intermediate CRL 3 PP.06.05.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test47/Intermediate CRL 4 PP.06.05.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test47/Intermediate Certificate 1 PP.06.05.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test47/Intermediate Certificate 2 PP.06.05.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test47/Intermediate Certificate 3 PP.06.05.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test47/Intermediate Certificate 4 PP.06.05.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test47/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test47/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test48/End Certificate PP.08.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test48/Intermediate CRL PP.08.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test48/Intermediate Certificate PP.08.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test48/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test48/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test49/End Certificate PP.08.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test49/Intermediate CRL PP.08.02.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test49/Intermediate Certificate PP.08.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test49/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test49/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test5/End Certificate CP.02.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test5/Intermediate CRL CP.02.02.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test5/Intermediate Certificate CP.02.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test5/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test5/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test50/End Certificate PP.08.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test50/Intermediate CRL PP.08.03.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test50/Intermediate Certificate PP.08.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test50/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test50/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test51/End Certificate PP.08.04.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test51/Intermediate CRL PP.08.04.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test51/Intermediate Certificate PP.08.04.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test51/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test51/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test52/End Certificate PP.08.05.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test52/Intermediate CRL PP.08.05.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test52/Intermediate Certificate PP.08.05.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test52/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test52/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test53/End Certificate PP.08.06.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test53/Intermediate CRL PP.08.06.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test53/Intermediate Certificate PP.08.06.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test53/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test53/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test54/End Certificate PL.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test54/Intermediate CRL 1 PL.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test54/Intermediate CRL 2 PL.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test54/Intermediate Certificate 1 PL.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test54/Intermediate Certificate 2 PL.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test54/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test54/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test55/End Certificate PL.01.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test55/Intermediate CRL 1 PL.01.02.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test55/Intermediate CRL 2 PL.01.02.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test55/Intermediate Certificate 1 PL.01.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test55/Intermediate Certificate 2 PL.01.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test55/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test55/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test56/End Certificate PL.01.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test56/Intermediate CRL PL.01.03.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test56/Intermediate Certificate PL.01.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test56/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test56/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test57/End Certificate PL.01.04.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test57/Intermediate CRL PL.01.04.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test57/Intermediate Certificate PL.01.04.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test57/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test57/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/End Certificate PL.01.05.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/Intermediate CRL 1 PL.01.05.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/Intermediate CRL 2 PL.01.05.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/Intermediate CRL 3 PL.01.05.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/Intermediate Certificate 1 PL.01.05.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/Intermediate Certificate 2 PL.01.05.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/Intermediate Certificate 3 PL.01.05.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/End Certificate PL.01.06.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/Intermediate CRL 1 PL.01.06.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/Intermediate CRL 2 PL.01.06.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/Intermediate CRL 3 PL.01.06.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/Intermediate Certificate 1 PL.01.06.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/Intermediate Certificate 2 PL.01.06.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/Intermediate Certificate 3 PL.01.06.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test6/End Certificate CP.02.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test6/Intermediate CRL CP.02.03.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test6/Intermediate Certificate CP.02.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test6/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test6/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/End Certificate PL.01.07.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate CRL 1 PL.01.07.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate CRL 2 PL.01.07.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate CRL 3 PL.01.07.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate CRL 4 PL.01.07.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate Certificate 1 PL.01.07.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate Certificate 2 PL.01.07.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate Certificate 3 PL.01.07.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate Certificate 4 PL.01.07.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/End Certificate PL.01.08.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/Intermediate CRL 1 PL.01.08.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/Intermediate CRL 2 PL.01.08.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/Intermediate CRL 3 PL.01.08.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/Intermediate CRL 4 PL.01.08.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/Intermediate Certificate 1 PL.01.08.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/Intermediate Certificate 2 PL.01.08.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/Intermediate Certificate 3 PL.01.08.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/Intermediate Certificate 4 PL.01.08.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/End Certificate PL.01.09.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/Intermediate CRL 1 PL.01.09.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/Intermediate CRL 2 PL.01.09.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/Intermediate CRL 3 PL.01.09.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/Intermediate CRL 4 PL.01.09.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/Intermediate Certificate 1 PL.01.09.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/Intermediate Certificate 2 PL.01.09.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/Intermediate Certificate 3 PL.01.09.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/Intermediate Certificate 4 PL.01.09.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/End Certificate PL.01.10.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/Intermediate CRL 1 PL.01.10.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/Intermediate CRL 2 PL.01.10.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/Intermediate CRL 3 PL.01.10.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/Intermediate CRL 4 PL.01.10.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/Intermediate Certificate 1 PL.01.10.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/Intermediate Certificate 2 PL.01.10.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/Intermediate Certificate 3 PL.01.10.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/Intermediate Certificate 4 PL.01.10.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test64/End Certificate RL.02.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test64/Intermediate CRL RL.02.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test64/Intermediate Certificate RL.02.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test64/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test64/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test65/End Certificate RL.03.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test65/Intermediate CRL RL.03.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test65/Intermediate Certificate 1 RL.03.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test65/Intermediate Certificate 2 RL.03.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test65/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test65/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test66/End Certificate RL.03.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test66/Intermediate CRL RL.03.02.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test66/Intermediate Certificate RL.03.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test66/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test66/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test67/End Certificate RL.03.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test67/Intermediate CRL 1 RL.03.03.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test67/Intermediate CRL 2 RL.03.03.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test67/Intermediate Certificate RL.03.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test67/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test67/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test68/End Certificate RL.05.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test68/Intermediate CRL 1 RL.05.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test68/Intermediate CRL 2 RL.05.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test68/Intermediate Certificate 1 RL.05.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test68/Intermediate Certificate 2 RL.05.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test68/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test68/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test69/End Certificate RL.05.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test69/Intermediate CRL RL.05.02.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test69/Intermediate Certificate RL.05.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test69/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test69/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test7/End Certificate CP.02.04.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test7/Intermediate CRL CP.02.04.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test7/Intermediate Certificate CP.02.04.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test7/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test7/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test70/End Certificate RL.06.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test70/Intermediate CRL 1 RL.06.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test70/Intermediate CRL 2 RL.06.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test70/Intermediate Certificate 1 RL.06.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test70/Intermediate Certificate 2 RL.06.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test70/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test70/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test71/End Certificate RL.06.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test71/Intermediate CRL RL.06.02.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test71/Intermediate Certificate RL.06.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test71/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test71/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test72/End Certificate RL.07.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test72/Intermediate CRL RL.07.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test72/Intermediate Certificate RL.07.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test72/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test72/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test73/End Certificate RL.07.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test73/Intermediate CRL RL.07.02.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test73/Intermediate Certificate RL.07.02.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test73/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test73/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test74/End Certificate RL.07.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test74/Intermediate CRL RL.07.03.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test74/Intermediate Certificate RL.07.03.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test74/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test74/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test75/End Certificate RL.08.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test75/Intermediate CRL RL.08.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test75/Intermediate Certificate RL.08.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test75/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test75/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test76/End Certificate RL.09.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test76/Intermediate CRL RL.09.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test76/Intermediate Certificate RL.09.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test76/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test76/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test8/End Certificate CP.02.05.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test8/Intermediate CRL CP.02.05.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test8/Intermediate Certificate CP.02.05.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test8/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test8/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test9/End Certificate CP.03.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test9/Intermediate CRL CP.03.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test9/Intermediate Certificate CP.03.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test9/Trust Anchor CP.01.01.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/test9/Trust Anchor CRL CP.01.01.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/X509tests/x509tests.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/anchorAndDb/amazon_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/anchorAndDb/anchorAndDb.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/anchorAndDb/dbWithLeaf.db create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/anchorAndDb/dbWithRoot.db create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/anchorAndDb/root_1.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/bmpSslHost/bmpSslHost.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/bmpSslHost/loopStone.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/bmpSslHost/stone.tees_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/bmpSslHost/stone.tees_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/bmpSslHost/stone.tees_v3.102.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/amazon_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/amazon_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/apple_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/apple_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/cduniverse_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/cduniverse_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/crlssl.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/entrust_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/entrust_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/firstamlink_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/keybank_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/keybank_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/keybank_v3.102.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/netfile.state.co_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/netfile.state.co_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/netfile.state.co_v3.102.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/one.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/proteron_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/puretec_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/secauth_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/secauth_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/verisign_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/verisign_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/verisign_v3.102.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/wellsfargo_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/wellsfargo_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/xdss_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/xdss_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlTime/crl.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlTime/crlTestLeaf.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlTime/crlTestRoot.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crlTime/crlTime.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crossSigned/SOA1-SOA2.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crossSigned/SOA2-SOA1.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crossSigned/crossSigned.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crossSigned/crossSigned1.db create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/crossSigned/crossSignedBoth.db create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/emptyCert/CA.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/emptyCert/emptyCert.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/emptyCert/emptyCert.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/emptyCert/leaf.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/emptyCert/root.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/emptySubject/ca.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/emptySubject/emptySubject.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/emptySubject/user.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/.gdb_history create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/AppleDevRoot.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/NewDevCAIntermdiate.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/OriginalDevCAIntermediate.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/appleDevCAs.keychain create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/dmitchtread.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/expiredCA.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/one.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/bothCAs.keychain create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/ecExpiredCA.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/ecExpiredLeaf.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/ecExpiredRoot.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/ecGoodCA.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/ecGoodLeaf.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/ecGoodRoot.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/expiredCA.keychain create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/expiredCerts.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/expiredRoot.keychain create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/goodCA.keychain create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/goodRoot.keychain create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/one.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredRoot/applestore_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredRoot/applestore_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredRoot/expiredRoot.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/expiredRoot/iproj_v3.102.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/gipCps/gipCps.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/gipCps/gipCps0.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/hostNameDot/hostNameDot.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/hostNameDot/hostNameDotCommonName.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/hostNameDot/hostNameDotCommonNameDot.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/hostNameDot/hostNameDotRoot.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/hostNameDot/hostNameDotSubjAltName.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/hostNameDot/hostNameDotSubjAltNameDot.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/implicitAnchor/CA.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/implicitAnchor/implicitAnchor.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/implicitAnchor/leaf.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/implicitAnchor/root.cer create mode 100755 SecurityTests/clxutils/certcrl/testSubjects/ipSec/VPNTrialCA.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ipSec/ipSec.scr create mode 100755 SecurityTests/clxutils/certcrl/testSubjects/ipSec/vpn-gateway.vpntrial.com.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/localTime/badCert_1 create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/localTime/badCert_2 create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/localTime/badCert_3 create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/localTime/badCert_4 create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/localTime/localTime.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/miscPolicies/miscPolicies.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/miscPolicies/miscPoliciesRoot.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/miscPolicies/noEKU.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/miscPolicies/resourceSignLeaf.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/miscPolicies/rfc3280CodeSigningLeaf.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/netFetch/JITC_Class3Mail_CA.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/netFetch/JITC_Class3_root_CA.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/netFetch/c3MailCaCrl.db create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/netFetch/ghoo.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/netFetch/net.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/amazon_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/amazon_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/apple_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/apple_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/cduniverse_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/cduniverse_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/certum_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/certum_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/certum_v3.102.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/keybank_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/keybank_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/keybank_v3.102.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/ocspssl.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/ocspsslNew.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/one.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/proteron_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/secauth_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/secauth_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/thawte_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/thawte_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/verisign_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/verisign_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/verisign_v3.102.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/wellsfargo_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/wellsfargo_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/xdss_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/xdss_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocsp_openvalidation/Root_CA1.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocsp_openvalidation/Root_CA2.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocsp_openvalidation/Server_CA1.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocsp_openvalidation/Server_CA2.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocsp_openvalidation/User_CA1.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocsp_openvalidation/User_CA2.crt create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocsp_openvalidation/ocsp.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocsp_openvalidation/one.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/ocsp_openvalidation/one_CA2.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/.gdb_history create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/derCerts/eepkint1.der create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/derCerts/eepkint1.key.der create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/derCerts/pkint8k.der create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/derCerts/pkint8k.key.der create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/derCerts/uee8k.der create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/eepkint1.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/eepkint2.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/intca.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/parasite.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/parasiteEnableLargeKeys.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/parasiteErrDetect.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/pkint16k.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/pkint8k.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/pkuser.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/prsa16k.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/prsa8k.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/root.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/shintca.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/shroot.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/ssRootCert.der create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/ssSubjCert.der create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/tee16k.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/tee8k.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/uee16k.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/uee8k.pem create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/pkinitPolicy/CA.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/pkinitPolicy/noBC.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/pkinitPolicy/noCA.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/pkinitPolicy/pkinitPolicy.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/qualCertStatment/ICA3.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/qualCertStatment/Netlock1.der create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/qualCertStatment/badStatementId.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/qualCertStatment/qualCertStatement.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/intermediate.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/leaf.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/leafBadEKU.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/leafBadKU.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/leafNoEKU.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/resourceSigning.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/root.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/serverGatedCrypto/alandsbanken_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/serverGatedCrypto/alandsbanken_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/serverGatedCrypto/luottokunta_v3.100.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/serverGatedCrypto/luottokunta_v3.101.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/serverGatedCrypto/sgc.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/smime/AliceDSSSignByCarlNoInherit.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/smime/AliceRSASignByCarl.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/smime/BobDHEncryptByCarl.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/smime/BobRSASignByCarl.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/smime/CarlDSSCRLEmpty.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/smime/CarlDSSCRLForAll.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/smime/CarlDSSCRLForCarl.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/smime/CarlDSSSelf.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/smime/CarlRSACRLEmpty.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/smime/CarlRSACRLForAll.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/smime/CarlRSACRLForCarl.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/smime/CarlRSASelf.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/smime/DianeDHEncryptByCarl.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/smime/DianeDSSSignByCarlInherit.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/smime/DianeRSASignByCarl.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/smime/EricaDHEncryptByCarl.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/smime/certsParsed create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/smime/crlsParsed create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/smime/smime.scr create mode 100755 SecurityTests/clxutils/certcrl/testSubjects/trustSettings/buildAndTest create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/trustSettings/crl.crl create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/trustSettings/crlTestLeaf.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/trustSettings/crlTestRoot.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/trustSettings/csCA.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/trustSettings/csLeaf.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/trustSettings/csLeafShortPath.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/trustSettings/csRoot.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/trustSettings/debugRoot.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/trustSettings/dmitchAppleThawte.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/trustSettings/emptyTrustSettings.plist create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/trustSettings/localhost.cer create mode 100755 SecurityTests/clxutils/certcrl/testSubjects/trustSettings/makeTrustSettings create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/trustSettings/one.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/trustSettings/thawteCA.cer create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/trustSettings/trustSettings.scr create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/trustSettings/trustSettingsTest.keychain create mode 100644 SecurityTests/clxutils/certcrl/testSubjects/trustSettings/userTrustSettings.plist create mode 100644 SecurityTests/clxutils/certsFromDb/Makefile create mode 100644 SecurityTests/clxutils/certsFromDb/certsFromDb.cpp create mode 100644 SecurityTests/clxutils/cgConstruct/Makefile create mode 100644 SecurityTests/clxutils/cgConstruct/cgConstruct.cpp create mode 100644 SecurityTests/clxutils/cgVerify/Makefile create mode 100644 SecurityTests/clxutils/cgVerify/cgVerify.cpp create mode 100644 SecurityTests/clxutils/cgVerify/dsaParam512.der create mode 100644 SecurityTests/clxutils/cgVerifyParsed/Makefile create mode 100644 SecurityTests/clxutils/cgVerifyParsed/cgVerifyParsed.cpp create mode 100644 SecurityTests/clxutils/cgVerifyParsed/dsaParam512.der create mode 100644 SecurityTests/clxutils/cgVerifyParsed/tpVerifyParsed.cpp create mode 100644 SecurityTests/clxutils/cgVerifyParsed/tpVerifyParsed.h create mode 100644 SecurityTests/clxutils/clAppUtils/BlobList.cpp create mode 100644 SecurityTests/clxutils/clAppUtils/BlobList.h create mode 100644 SecurityTests/clxutils/clAppUtils/CertBuilderApp.cpp create mode 100644 SecurityTests/clxutils/clAppUtils/CertBuilderApp.h create mode 100644 SecurityTests/clxutils/clAppUtils/CertParser.cpp create mode 100644 SecurityTests/clxutils/clAppUtils/CertParser.h create mode 100644 SecurityTests/clxutils/clAppUtils/Makefile create mode 100644 SecurityTests/clxutils/clAppUtils/certVerify.cpp create mode 100644 SecurityTests/clxutils/clAppUtils/certVerify.h create mode 100644 SecurityTests/clxutils/clAppUtils/clutils.c create mode 100644 SecurityTests/clxutils/clAppUtils/clutils.h create mode 100644 SecurityTests/clxutils/clAppUtils/crlUtils.cpp create mode 100644 SecurityTests/clxutils/clAppUtils/crlUtils.h create mode 100644 SecurityTests/clxutils/clAppUtils/identPicker.cpp create mode 100644 SecurityTests/clxutils/clAppUtils/identPicker.h create mode 100644 SecurityTests/clxutils/clAppUtils/ioSock.c create mode 100644 SecurityTests/clxutils/clAppUtils/ioSock.h create mode 100644 SecurityTests/clxutils/clAppUtils/keyPicker.cpp create mode 100644 SecurityTests/clxutils/clAppUtils/keyPicker.h create mode 100644 SecurityTests/clxutils/clAppUtils/printCertName.cpp create mode 100644 SecurityTests/clxutils/clAppUtils/printCertName.h create mode 100644 SecurityTests/clxutils/clAppUtils/ringBufferIo.cpp create mode 100644 SecurityTests/clxutils/clAppUtils/ringBufferIo.h create mode 100644 SecurityTests/clxutils/clAppUtils/sslAppUtils.cpp create mode 100644 SecurityTests/clxutils/clAppUtils/sslAppUtils.h create mode 100644 SecurityTests/clxutils/clAppUtils/sslClient.cpp create mode 100644 SecurityTests/clxutils/clAppUtils/sslRingBufferThreads.cpp create mode 100644 SecurityTests/clxutils/clAppUtils/sslRingBufferThreads.h create mode 100644 SecurityTests/clxutils/clAppUtils/sslServe.cpp create mode 100644 SecurityTests/clxutils/clAppUtils/sslThreading.h create mode 100644 SecurityTests/clxutils/clAppUtils/timeStr.cpp create mode 100644 SecurityTests/clxutils/clAppUtils/timeStr.h create mode 100644 SecurityTests/clxutils/clAppUtils/tpUtils.cpp create mode 100644 SecurityTests/clxutils/clAppUtils/tpUtils.h create mode 100644 SecurityTests/clxutils/clTool/Makefile create mode 100644 SecurityTests/clxutils/clTool/clTool.cpp create mode 100755 SecurityTests/clxutils/cltpdvt create mode 100644 SecurityTests/clxutils/cltpdvt_usage create mode 100644 SecurityTests/clxutils/clxutils.pbproj/project.pbxproj create mode 100644 SecurityTests/clxutils/cmsTime/Makefile create mode 100644 SecurityTests/clxutils/cmsTime/cmsTime.cpp create mode 100644 SecurityTests/clxutils/cmsTime/noRoot.p7 create mode 100644 SecurityTests/clxutils/cmsTime/withRoot.p7 create mode 100644 SecurityTests/clxutils/cmstool/Makefile create mode 100644 SecurityTests/clxutils/cmstool/cmstool.cpp create mode 100644 SecurityTests/clxutils/cmstool/testSubjects/ptext1.txt create mode 100644 SecurityTests/clxutils/cmstool/testSubjects/signed1.cms create mode 100755 SecurityTests/clxutils/cmstool/testSubjects/vfyCms create mode 100644 SecurityTests/clxutils/crlTool/Makefile create mode 100644 SecurityTests/clxutils/crlTool/crlNetwork.cpp create mode 100644 SecurityTests/clxutils/crlTool/crlNetwork.h create mode 100644 SecurityTests/clxutils/crlTool/crlTool.cpp create mode 100644 SecurityTests/clxutils/dotMacArchive/Makefile create mode 100644 SecurityTests/clxutils/dotMacArchive/dotMacArchive.cpp create mode 100644 SecurityTests/clxutils/dotMacArchive/dotMacTpAttach.cpp create mode 100644 SecurityTests/clxutils/dotMacArchive/dotMacTpAttach.h create mode 100644 SecurityTests/clxutils/dotMacArchive/identSearch.cpp create mode 100644 SecurityTests/clxutils/dotMacArchive/identSearch.h create mode 100644 SecurityTests/clxutils/dotMacRequest/Makefile create mode 100644 SecurityTests/clxutils/dotMacRequest/README create mode 100644 SecurityTests/clxutils/dotMacRequest/dotMacRequest.cpp create mode 100644 SecurityTests/clxutils/dotMacTool/MDS create mode 100644 SecurityTests/clxutils/dotMacTool/Makefile create mode 100644 SecurityTests/clxutils/dotMacTool/README create mode 100644 SecurityTests/clxutils/dotMacTool/dotMacTool.cpp create mode 100644 SecurityTests/clxutils/dotMacTool/keyPicker.cpp create mode 100644 SecurityTests/clxutils/dotMacTool/keyPicker.h create mode 100644 SecurityTests/clxutils/dumpasn1.cfg create mode 100644 SecurityTests/clxutils/extenGrab/Makefile create mode 100644 SecurityTests/clxutils/extenGrab/extenGrab.cpp create mode 100644 SecurityTests/clxutils/extenTest/Makefile create mode 100644 SecurityTests/clxutils/extenTest/extenTest.cpp create mode 100644 SecurityTests/clxutils/extenTestTp/Makefile create mode 100644 SecurityTests/clxutils/extenTestTp/extenTestTp.cpp create mode 100644 SecurityTests/clxutils/extendAttrTest/Makefile create mode 100644 SecurityTests/clxutils/extendAttrTest/amazon_v3.100.cer create mode 100644 SecurityTests/clxutils/extendAttrTest/extendAttrTest.cpp create mode 100644 SecurityTests/clxutils/extendAttrTest/rsakey_priv.der create mode 100644 SecurityTests/clxutils/extendAttrTest/rsakey_pub.der create mode 100644 SecurityTests/clxutils/extendAttrTool/Makefile create mode 100644 SecurityTests/clxutils/extendAttrTool/extendAttrTool.cpp create mode 100644 SecurityTests/clxutils/extendAttrTool/singleItemPicker.cpp create mode 100644 SecurityTests/clxutils/extendAttrTool/singleItemPicker.h create mode 100644 SecurityTests/clxutils/extractCertFields/Makefile create mode 100644 SecurityTests/clxutils/extractCertFields/extractCertFields.cpp create mode 100644 SecurityTests/clxutils/findCert/Makefile create mode 100644 SecurityTests/clxutils/findCert/asnUtils.cpp create mode 100644 SecurityTests/clxutils/findCert/asnUtils.h create mode 100644 SecurityTests/clxutils/findCert/findCert.cpp create mode 100644 SecurityTests/clxutils/idPref/Makefile create mode 100644 SecurityTests/clxutils/idPref/idPref.cpp create mode 100644 SecurityTests/clxutils/idTool/Makefile create mode 100644 SecurityTests/clxutils/idTool/idTool.cpp create mode 100644 SecurityTests/clxutils/importExport/amazon_v3.100.pem create mode 100644 SecurityTests/clxutils/importExport/cdnow_v300.pem create mode 100644 SecurityTests/clxutils/importExport/dhParams_512.der create mode 100644 SecurityTests/clxutils/importExport/dsaParamOpenssl.pem create mode 100644 SecurityTests/clxutils/importExport/dsaParams_512.der create mode 100755 SecurityTests/clxutils/importExport/exportOpensslTool create mode 100755 SecurityTests/clxutils/importExport/exportPkcs8Tool create mode 100755 SecurityTests/clxutils/importExport/impExpOpensslEcdsa create mode 100755 SecurityTests/clxutils/importExport/impExpOpensslEcdsaTool create mode 100755 SecurityTests/clxutils/importExport/importExport create mode 100755 SecurityTests/clxutils/importExport/importExportAgg create mode 100755 SecurityTests/clxutils/importExport/importExportECDSA_P12 create mode 100755 SecurityTests/clxutils/importExport/importExportECDSA_P12_Tool create mode 100755 SecurityTests/clxutils/importExport/importExportKeyTool create mode 100755 SecurityTests/clxutils/importExport/importExportOpenssh create mode 100755 SecurityTests/clxutils/importExport/importExportOpensshTool create mode 100755 SecurityTests/clxutils/importExport/importExportOpensslWrap create mode 100755 SecurityTests/clxutils/importExport/importExportPkcs12 create mode 100755 SecurityTests/clxutils/importExport/importExportPkcs7 create mode 100755 SecurityTests/clxutils/importExport/importExportPkcs8 create mode 100755 SecurityTests/clxutils/importExport/importExportPkcs8Tool create mode 100755 SecurityTests/clxutils/importExport/importExportRawKey create mode 100644 SecurityTests/clxutils/importExport/localcert.pem create mode 100644 SecurityTests/clxutils/importExport/secp256r1ca.p12 create mode 100644 SecurityTests/clxutils/importExport/secp384r1ca.p12 create mode 100644 SecurityTests/clxutils/importExport/secp521r1ca.p12 create mode 100644 SecurityTests/clxutils/importExport/setupCommon create mode 100644 SecurityTests/clxutils/importExport/somePlainText create mode 100644 SecurityTests/clxutils/kcExport/Makefile create mode 100644 SecurityTests/clxutils/kcExport/kcExport.cpp create mode 100644 SecurityTests/clxutils/kcImport/Makefile create mode 100644 SecurityTests/clxutils/kcImport/kcImport.cpp create mode 100644 SecurityTests/clxutils/kcTime/Makefile create mode 100644 SecurityTests/clxutils/kcTime/SecureServer.509.cer create mode 100644 SecurityTests/clxutils/kcTime/amazon_v3.100.cer create mode 100644 SecurityTests/clxutils/kcTime/kcTime.cpp create mode 100644 SecurityTests/clxutils/kcTime/test1.p12 create mode 100644 SecurityTests/clxutils/kcTool/Makefile create mode 100644 SecurityTests/clxutils/kcTool/kcTool.cpp create mode 100644 SecurityTests/clxutils/keyFromCert/Makefile create mode 100644 SecurityTests/clxutils/keyFromCert/keyFromCert.cpp create mode 100644 SecurityTests/clxutils/krbtool/Makefile create mode 100644 SecurityTests/clxutils/krbtool/asnUtils.cpp create mode 100644 SecurityTests/clxutils/krbtool/asnUtils.h create mode 100644 SecurityTests/clxutils/krbtool/identPicker.cpp create mode 100644 SecurityTests/clxutils/krbtool/identPicker.h create mode 100644 SecurityTests/clxutils/krbtool/krbtool.cpp create mode 100644 SecurityTests/clxutils/make.ssl create mode 100644 SecurityTests/clxutils/makeCertPolicy/Makefile create mode 100644 SecurityTests/clxutils/makeCertPolicy/makeCertPolicy.cpp create mode 100644 SecurityTests/clxutils/makeCrl/Makefile create mode 100644 SecurityTests/clxutils/makeCrl/makeCrl.cpp create mode 100644 SecurityTests/clxutils/makeCrl/testFiles/crl.crl create mode 100644 SecurityTests/clxutils/makeCrl/testFiles/crlKeychain.keychain create mode 100644 SecurityTests/clxutils/makeCrl/testFiles/crlTestLeaf.cer create mode 100644 SecurityTests/clxutils/makeCrl/testFiles/crlTestRoot.cer create mode 100644 SecurityTests/clxutils/makeCrl/testFiles/crlTime.scr create mode 100644 SecurityTests/clxutils/makeCrl/testFiles/crlTimeTiger.scr create mode 100644 SecurityTests/clxutils/makeCrl/testFiles/notes create mode 100644 SecurityTests/clxutils/makeExpiredCerts/Makefile create mode 100644 SecurityTests/clxutils/makeExpiredCerts/makeExpiredCerts.cpp create mode 100644 SecurityTests/clxutils/newCmsTool/Makefile create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/GTE_SGC.cer create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/certs.p7 create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/certsOnly.p7 create mode 100755 SecurityTests/clxutils/newCmsTool/blobs/cmsEcdsaHandsoff create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/cmsEcdsaRoot.cer create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/cmsKeychain create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/cmsRoot.cer create mode 100755 SecurityTests/clxutils/newCmsTool/blobs/cmstest create mode 100755 SecurityTests/clxutils/newCmsTool/blobs/cmstestHandsoff create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/cmstestUsage create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/dmitchIChat.cer create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/ecdsaCmsKeychain.keychain create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/env.p7 create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/env_two.p7 create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/ptext create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/sign.p7 create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/sign2.p7 create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/signEnv.p7 create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/signEnv_auth.p7 create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/signEnv_certs.p7 create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/signEnv_twoSign.p7 create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/signEnv_twoSign_twoRecip.p7 create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/sign_auth.p7 create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/sign_certs.p7 create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/sign_det.p7 create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/sign_nocerts.p7 create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/sign_only_certs.p7 create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/sign_signer.p7 create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/sign_two.p7 create mode 100644 SecurityTests/clxutils/newCmsTool/blobs/sign_withroot.p7 create mode 100644 SecurityTests/clxutils/newCmsTool/newCmsTool.cpp create mode 100644 SecurityTests/clxutils/ocspTool/Makefile create mode 100644 SecurityTests/clxutils/ocspTool/findOcspUrl.cpp create mode 100644 SecurityTests/clxutils/ocspTool/findOcspUrl.h create mode 100644 SecurityTests/clxutils/ocspTool/ocspNetwork.cpp create mode 100644 SecurityTests/clxutils/ocspTool/ocspNetwork.h create mode 100644 SecurityTests/clxutils/ocspTool/ocspRequest.cpp create mode 100644 SecurityTests/clxutils/ocspTool/ocspRequest.h create mode 100644 SecurityTests/clxutils/ocspTool/ocspTool.cpp create mode 100644 SecurityTests/clxutils/ocspTool/ocspUtils.cpp create mode 100644 SecurityTests/clxutils/ocspTool/ocspUtils.h create mode 100644 SecurityTests/clxutils/ocspdTool/Makefile create mode 100644 SecurityTests/clxutils/ocspdTool/ocspdTool.cpp create mode 100644 SecurityTests/clxutils/p12/Makefile create mode 100644 SecurityTests/clxutils/p12/SecNssCoder.cpp create mode 100644 SecurityTests/clxutils/p12/SecNssCoder.h create mode 100644 SecurityTests/clxutils/p12/p12.cpp create mode 100644 SecurityTests/clxutils/p12/p12.h create mode 100644 SecurityTests/clxutils/p12/p12Crypto.cpp create mode 100644 SecurityTests/clxutils/p12/p12Crypto.h create mode 100644 SecurityTests/clxutils/p12/p12Decode.cpp create mode 100644 SecurityTests/clxutils/p12/p12Encode.cpp create mode 100644 SecurityTests/clxutils/p12/p12GetPassKey.cpp create mode 100644 SecurityTests/clxutils/p12/p12GetPassKey.h create mode 100644 SecurityTests/clxutils/p12/p12ImportExport.cpp create mode 100644 SecurityTests/clxutils/p12/p12Parse.cpp create mode 100644 SecurityTests/clxutils/p12/p12pbe.cpp create mode 100644 SecurityTests/clxutils/p12/p12pbe.h create mode 100644 SecurityTests/clxutils/p12/pkcs12Parsed.cpp create mode 100644 SecurityTests/clxutils/p12/pkcs12Parsed.h create mode 100644 SecurityTests/clxutils/p12Parse/Makefile create mode 100644 SecurityTests/clxutils/p12Parse/main.cpp create mode 100644 SecurityTests/clxutils/p12Parse/p12Crypto.cpp create mode 100644 SecurityTests/clxutils/p12Parse/p12Crypto.h create mode 100644 SecurityTests/clxutils/p12Parse/p12Parse.cpp create mode 100644 SecurityTests/clxutils/p12Parse/p12Parse.h create mode 100644 SecurityTests/clxutils/p12Parse/pkcs12Parsed.cpp create mode 100644 SecurityTests/clxutils/p12Parse/pkcs12Parsed.h create mode 100644 SecurityTests/clxutils/p12Parse/pkcs12Utils.cpp create mode 100644 SecurityTests/clxutils/p12Parse/pkcs12Utils.h create mode 100644 SecurityTests/clxutils/p12Reencode/Makefile create mode 100755 SecurityTests/clxutils/p12Reencode/doReencode create mode 100644 SecurityTests/clxutils/p12Reencode/p12Reencode.cpp create mode 100644 SecurityTests/clxutils/p12Reencode/test1.p12 create mode 100644 SecurityTests/clxutils/p12Reencode/test10.p12 create mode 100644 SecurityTests/clxutils/p12Reencode/test11.p12 create mode 100644 SecurityTests/clxutils/p12Reencode/test12.p12 create mode 100644 SecurityTests/clxutils/p12Reencode/test13.p12 create mode 100644 SecurityTests/clxutils/p12Reencode/test14.p12 create mode 100644 SecurityTests/clxutils/p12Reencode/test15.p12 create mode 100644 SecurityTests/clxutils/p12Reencode/test16.p12 create mode 100644 SecurityTests/clxutils/p12Reencode/test17.p12 create mode 100644 SecurityTests/clxutils/p12Reencode/test18.p12 create mode 100644 SecurityTests/clxutils/p12Reencode/test19.p12 create mode 100644 SecurityTests/clxutils/parseCert/Makefile create mode 100644 SecurityTests/clxutils/parseCert/parseCert.cpp create mode 100644 SecurityTests/clxutils/parseCrl/Makefile create mode 100644 SecurityTests/clxutils/parseCrl/parseCrl.cpp create mode 100644 SecurityTests/clxutils/pemtool/Makefile create mode 100644 SecurityTests/clxutils/pemtool/pemtool.c create mode 100644 SecurityTests/clxutils/rootStoreTool/KeychainAccessSystemRoot.cer create mode 100644 SecurityTests/clxutils/rootStoreTool/KeychainAccessUserRoot.cer create mode 100644 SecurityTests/clxutils/rootStoreTool/Makefile create mode 100644 SecurityTests/clxutils/rootStoreTool/SMIME_SystemRoot.cer create mode 100644 SecurityTests/clxutils/rootStoreTool/SMIME_UserRoot.cer create mode 100644 SecurityTests/clxutils/rootStoreTool/SSL_SystemRoot.cer create mode 100644 SecurityTests/clxutils/rootStoreTool/SSL_UserRoot.cer create mode 100644 SecurityTests/clxutils/rootStoreTool/UnrestrictedSystemRoot.cer create mode 100644 SecurityTests/clxutils/rootStoreTool/UnrestrictedUserRoot.cer create mode 100755 SecurityTests/clxutils/rootStoreTool/addTestRoots create mode 100755 SecurityTests/clxutils/rootStoreTool/addTestRootsSec create mode 100755 SecurityTests/clxutils/rootStoreTool/buildSysAnchors create mode 100644 SecurityTests/clxutils/rootStoreTool/parseTrustedRootList.cpp create mode 100644 SecurityTests/clxutils/rootStoreTool/parseTrustedRootList.h create mode 100644 SecurityTests/clxutils/rootStoreTool/rootStoreTool.cpp create mode 100644 SecurityTests/clxutils/rootStoreTool/rootUtils.cpp create mode 100644 SecurityTests/clxutils/rootStoreTool/rootUtils.h create mode 100644 SecurityTests/clxutils/rootStoreTool/threeRoots.pem create mode 100644 SecurityTests/clxutils/secTime/Makefile create mode 100644 SecurityTests/clxutils/secTime/SecureServer.509.cer create mode 100644 SecurityTests/clxutils/secTime/ThawteCA.cer create mode 100644 SecurityTests/clxutils/secTime/ThawteRoot.cer create mode 100644 SecurityTests/clxutils/secTime/amazon_v3.100.cer create mode 100644 SecurityTests/clxutils/secTime/dmitchThawte.cer create mode 100644 SecurityTests/clxutils/secTime/firstamlink.cer create mode 100644 SecurityTests/clxutils/secTime/secTime.cpp create mode 100644 SecurityTests/clxutils/secToolVerify/AppleQuickTime.pem create mode 100644 SecurityTests/clxutils/secToolVerify/AppleSWUPDATE.pem create mode 100644 SecurityTests/clxutils/secToolVerify/VPNTrialCA.cer create mode 100644 SecurityTests/clxutils/secToolVerify/amazon_v3.100.cer create mode 100644 SecurityTests/clxutils/secToolVerify/applestore_v3.100.cer create mode 100644 SecurityTests/clxutils/secToolVerify/applestore_v3.101.cer create mode 100644 SecurityTests/clxutils/secToolVerify/dmitchThawte2005.cer create mode 100644 SecurityTests/clxutils/secToolVerify/dmitchThawte2007.cer create mode 100644 SecurityTests/clxutils/secToolVerify/iproj_v3.102.cer create mode 100755 SecurityTests/clxutils/secToolVerify/secToolVerify create mode 100644 SecurityTests/clxutils/secToolVerify/serverbasic.crt create mode 100644 SecurityTests/clxutils/secToolVerify/vpn-gateway.vpntrial.com.cer create mode 100644 SecurityTests/clxutils/secTrustTime/Makefile create mode 100644 SecurityTests/clxutils/secTrustTime/keybank_v3.100.cer create mode 100644 SecurityTests/clxutils/secTrustTime/keybank_v3.101.cer create mode 100644 SecurityTests/clxutils/secTrustTime/keybank_v3.102.cer create mode 100755 SecurityTests/clxutils/secTrustTime/runTests create mode 100644 SecurityTests/clxutils/secTrustTime/secTrustTime.cpp create mode 100644 SecurityTests/clxutils/signerAndSubj/Makefile create mode 100644 SecurityTests/clxutils/signerAndSubj/signerAndSubj.cpp create mode 100644 SecurityTests/clxutils/signerAndSubjSsl/Makefile create mode 100755 SecurityTests/clxutils/signerAndSubjSsl/doTest create mode 100644 SecurityTests/clxutils/signerAndSubjSsl/signerAndSubjSsl.cpp create mode 100644 SecurityTests/clxutils/signerAndSubjTp/Makefile create mode 100755 SecurityTests/clxutils/signerAndSubjTp/makeSmimeCert create mode 100644 SecurityTests/clxutils/signerAndSubjTp/signerAndSubjTp.cpp create mode 100644 SecurityTests/clxutils/simpleUrlAccess/Makefile create mode 100644 SecurityTests/clxutils/simpleUrlAccess/simpleUrlAccess.c create mode 100644 SecurityTests/clxutils/smimePolicy/Makefile create mode 100644 SecurityTests/clxutils/smimePolicy/smimePolicy.cpp create mode 100644 SecurityTests/clxutils/sslAlert/Makefile create mode 100644 SecurityTests/clxutils/sslAlert/README create mode 100644 SecurityTests/clxutils/sslAlert/sslAlert.cpp create mode 100644 SecurityTests/clxutils/sslAuth/Makefile create mode 100644 SecurityTests/clxutils/sslAuth/sslAuth.cpp create mode 100644 SecurityTests/clxutils/sslBench/Makefile create mode 100644 SecurityTests/clxutils/sslBench/sslBench.cpp create mode 100644 SecurityTests/clxutils/sslCipher/Makefile create mode 100644 SecurityTests/clxutils/sslCipher/sslCipher.cpp create mode 100644 SecurityTests/clxutils/sslEAP/Makefile create mode 100644 SecurityTests/clxutils/sslEAP/ringBufferThreads.cpp create mode 100644 SecurityTests/clxutils/sslEAP/ringBufferThreads.h create mode 100644 SecurityTests/clxutils/sslEAP/sslEAP.cpp create mode 100644 SecurityTests/clxutils/sslEcdsa/Makefile create mode 100644 SecurityTests/clxutils/sslEcdsa/ecc-secp256r1-client.pfx create mode 100644 SecurityTests/clxutils/sslEcdsa/ecdsa.keychain create mode 100644 SecurityTests/clxutils/sslEcdsa/sslEcdsa.cpp create mode 100644 SecurityTests/clxutils/sslHandshakeTimeRB/Makefile create mode 100644 SecurityTests/clxutils/sslHandshakeTimeRB/sslHandshakeTimeRB.cpp create mode 100644 SecurityTests/clxutils/sslHdshakeTime/Makefile create mode 100644 SecurityTests/clxutils/sslHdshakeTime/sslHdshakeTime.cpp create mode 100644 SecurityTests/clxutils/sslProt/Makefile create mode 100644 SecurityTests/clxutils/sslProt/dhParams1024.h create mode 100644 SecurityTests/clxutils/sslProt/dhParams512.h create mode 100644 SecurityTests/clxutils/sslProt/sslProt.cpp create mode 100755 SecurityTests/clxutils/sslScripts/AlexTest create mode 100755 SecurityTests/clxutils/sslScripts/authClient create mode 100755 SecurityTests/clxutils/sslScripts/authDoncio create mode 100755 SecurityTests/clxutils/sslScripts/authExtern create mode 100755 SecurityTests/clxutils/sslScripts/authServe create mode 100644 SecurityTests/clxutils/sslScripts/cynicRoot.cer create mode 100644 SecurityTests/clxutils/sslScripts/dhParams_1024.der create mode 100644 SecurityTests/clxutils/sslScripts/dhParams_512.der create mode 100644 SecurityTests/clxutils/sslScripts/doncioRoot.cer create mode 100755 SecurityTests/clxutils/sslScripts/doprompt create mode 100644 SecurityTests/clxutils/sslScripts/dsaCertToolInput create mode 100755 SecurityTests/clxutils/sslScripts/makeLocalCert create mode 100755 SecurityTests/clxutils/sslScripts/openssl/doprompt create mode 100755 SecurityTests/clxutils/sslScripts/openssl/makeOpensslCert create mode 100644 SecurityTests/clxutils/sslScripts/openssl/opensslReqInput create mode 100755 SecurityTests/clxutils/sslScripts/openssl/opensslTest create mode 100644 SecurityTests/clxutils/sslScripts/openssl/osdsaparam.der create mode 100755 SecurityTests/clxutils/sslScripts/openssl/runServeView create mode 100755 SecurityTests/clxutils/sslScripts/protClient create mode 100755 SecurityTests/clxutils/sslScripts/protServe create mode 100755 SecurityTests/clxutils/sslScripts/removeLocalCerts create mode 100755 SecurityTests/clxutils/sslScripts/runProtClient create mode 100755 SecurityTests/clxutils/sslScripts/setTrustAll create mode 100755 SecurityTests/clxutils/sslScripts/simplePrompt create mode 100644 SecurityTests/clxutils/sslScripts/sslExtendUse.scr create mode 100644 SecurityTests/clxutils/sslScripts/sslKcSetup create mode 100755 SecurityTests/clxutils/sslScripts/ssldvt create mode 100644 SecurityTests/clxutils/sslScripts/ssldvtCertErr create mode 100644 SecurityTests/clxutils/sslScripts/ssldvtUsage create mode 100644 SecurityTests/clxutils/sslScripts/test1.p12 create mode 100755 SecurityTests/clxutils/sslScripts/trustAll create mode 100644 SecurityTests/clxutils/sslScripts/verisignCA.cer create mode 100644 SecurityTests/clxutils/sslServer/Makefile create mode 100644 SecurityTests/clxutils/sslServer/sslServer.cpp create mode 100644 SecurityTests/clxutils/sslSession/Makefile create mode 100644 SecurityTests/clxutils/sslSession/sslSession.cpp create mode 100644 SecurityTests/clxutils/sslSubjName/Makefile create mode 100644 SecurityTests/clxutils/sslSubjName/sslSubjName.cpp create mode 100644 SecurityTests/clxutils/sslThroughput/Makefile create mode 100755 SecurityTests/clxutils/sslThroughput/runSslThroughput create mode 100644 SecurityTests/clxutils/sslThroughput/sslThroughput.cpp create mode 100644 SecurityTests/clxutils/sslViewer/Makefile create mode 100644 SecurityTests/clxutils/sslViewer/SSLViewer.cpp create mode 100644 SecurityTests/clxutils/sslViewer/SSL_Sites create mode 100755 SecurityTests/clxutils/sslViewer/pingSslSites create mode 100755 SecurityTests/clxutils/sslViewer/verifyPing create mode 100644 SecurityTests/clxutils/sysIdTool/Makefile create mode 100644 SecurityTests/clxutils/sysIdTool/sysIdTool.cpp create mode 100644 SecurityTests/clxutils/threadTest/Makefile create mode 100644 SecurityTests/clxutils/threadTest/amazon_v3.100.cer create mode 100644 SecurityTests/clxutils/threadTest/amazon_v3.101.cer create mode 100644 SecurityTests/clxutils/threadTest/attach.cpp create mode 100644 SecurityTests/clxutils/threadTest/cduniverse_v3.100.cer create mode 100644 SecurityTests/clxutils/threadTest/cgConstructThr.cpp create mode 100644 SecurityTests/clxutils/threadTest/cgVerifyThr.cpp create mode 100644 SecurityTests/clxutils/threadTest/copyRoots.cpp create mode 100644 SecurityTests/clxutils/threadTest/cspRand.cpp create mode 100644 SecurityTests/clxutils/threadTest/cssmErrStr.cpp create mode 100644 SecurityTests/clxutils/threadTest/dbOpenClose.cpp create mode 100644 SecurityTests/clxutils/threadTest/derDecode.cpp create mode 100644 SecurityTests/clxutils/threadTest/desTest.cpp create mode 100644 SecurityTests/clxutils/threadTest/digestClient.cpp create mode 100644 SecurityTests/clxutils/threadTest/getCachedFields.cpp create mode 100644 SecurityTests/clxutils/threadTest/getFields.cpp create mode 100644 SecurityTests/clxutils/threadTest/ioSockThr.c create mode 100644 SecurityTests/clxutils/threadTest/ioSockThr.h create mode 100644 SecurityTests/clxutils/threadTest/kcStatus.cpp create mode 100644 SecurityTests/clxutils/threadTest/mdsLookupThr.cpp create mode 100644 SecurityTests/clxutils/threadTest/mypage.apple_v3.100.cer create mode 100644 SecurityTests/clxutils/threadTest/rsaSign.cpp create mode 100644 SecurityTests/clxutils/threadTest/secTrustEval.cpp create mode 100644 SecurityTests/clxutils/threadTest/serverpremium.crt create mode 100644 SecurityTests/clxutils/threadTest/signVerify.cpp create mode 100644 SecurityTests/clxutils/threadTest/sslPing.cpp create mode 100644 SecurityTests/clxutils/threadTest/sslThrash.cpp create mode 100644 SecurityTests/clxutils/threadTest/symTestThr.cpp create mode 100644 SecurityTests/clxutils/threadTest/t_stdlib.c create mode 100644 SecurityTests/clxutils/threadTest/testParams.h create mode 100644 SecurityTests/clxutils/threadTest/testutil.c create mode 100644 SecurityTests/clxutils/threadTest/testutil.h create mode 100644 SecurityTests/clxutils/threadTest/threadTest.cpp create mode 100644 SecurityTests/clxutils/threadTest/timeThread.cpp create mode 100644 SecurityTests/clxutils/threadTest/trustSettings.cpp create mode 100644 SecurityTests/clxutils/trustAnchors/Makefile create mode 100644 SecurityTests/clxutils/trustAnchors/trustAnchors.c create mode 100644 SecurityTests/clxutils/trustApps/Makefile create mode 100644 SecurityTests/clxutils/trustApps/trustApps.cpp create mode 100644 SecurityTests/clxutils/unBER/Makefile create mode 100644 SecurityTests/clxutils/unBER/unBER.cpp create mode 100755 SecurityTests/clxutils/updateCert create mode 100755 SecurityTests/clxutils/updateCerts create mode 100644 SecurityTests/clxutils/urlPageGrab/Makefile create mode 100644 SecurityTests/clxutils/urlPageGrab/cfSimpleGet.cpp create mode 100644 SecurityTests/clxutils/urlPageGrab/cfSimpleGet.h create mode 100755 SecurityTests/clxutils/urlPageGrab/grabPages create mode 100755 SecurityTests/clxutils/urlPageGrab/pltGrab create mode 100644 SecurityTests/clxutils/urlPageGrab/speedo_html.tar create mode 100644 SecurityTests/clxutils/urlPageGrab/urlPageGrab.cpp create mode 100644 SecurityTests/clxutils/userTrustTest/Makefile create mode 100644 SecurityTests/clxutils/userTrustTest/amazon_v3.100.cer create mode 100644 SecurityTests/clxutils/userTrustTest/userTrustTest.cpp create mode 100755 SecurityTests/clxutils/vfyCacCert/Makefile create mode 100644 SecurityTests/clxutils/vfyCacCert/README create mode 100644 SecurityTests/clxutils/vfyCacCert/certs/cac_c7_cert.crt create mode 100644 SecurityTests/clxutils/vfyCacCert/certs/cac_signing_cert.crt create mode 100644 SecurityTests/clxutils/vfyCacCert/certs/joe2.ID.cer create mode 100644 SecurityTests/clxutils/vfyCacCert/certs/joe2.encrypt.cer create mode 100644 SecurityTests/clxutils/vfyCacCert/certs/joe2.sign.cer create mode 100755 SecurityTests/clxutils/vfyCacCert/vfyAllCerts create mode 100644 SecurityTests/clxutils/vfyCacCert/vfyCacCert.cpp create mode 100644 SecurityTests/clxutils/vfyCert/Makefile create mode 100644 SecurityTests/clxutils/vfyCert/vfyCert.c create mode 100644 SecurityTests/clxutils/vfyCertChain/Makefile create mode 100644 SecurityTests/clxutils/vfyCertChain/vfyCertChain.cpp create mode 100644 SecurityTests/cspxutils/ChangeLog create mode 100644 SecurityTests/cspxutils/EXAMPLES_README create mode 100644 SecurityTests/cspxutils/Makefile create mode 100644 SecurityTests/cspxutils/Makefile.cdsa create mode 100644 SecurityTests/cspxutils/Makefile.lib create mode 100644 SecurityTests/cspxutils/Makefile.template create mode 100644 SecurityTests/cspxutils/README create mode 100644 SecurityTests/cspxutils/acltool/Makefile create mode 100644 SecurityTests/cspxutils/acltool/aclUtils.cpp create mode 100644 SecurityTests/cspxutils/acltool/aclUtils.h create mode 100644 SecurityTests/cspxutils/acltool/acltool.cpp create mode 100644 SecurityTests/cspxutils/aesVect/Makefile create mode 100644 SecurityTests/cspxutils/aesVect/aesVect.c create mode 100644 SecurityTests/cspxutils/aesVect/ecb_vk.hdr create mode 100644 SecurityTests/cspxutils/aesVect/ecb_vk.txt create mode 100644 SecurityTests/cspxutils/aesVect/ecb_vt.hdr create mode 100644 SecurityTests/cspxutils/aesVect/ecb_vt.txt create mode 100644 SecurityTests/cspxutils/aesVect/enDecrypt.h create mode 100644 SecurityTests/cspxutils/aesVect/enDecryptCsp.c create mode 100644 SecurityTests/cspxutils/aesVect/enDecryptRef.c create mode 100644 SecurityTests/cspxutils/aesVect/enDecryptTest.c create mode 100755 SecurityTests/cspxutils/aesVect/makeVectors create mode 100644 SecurityTests/cspxutils/aesVect/rijndael.c create mode 100644 SecurityTests/cspxutils/aesVect/std_defs.h create mode 100755 SecurityTests/cspxutils/aesVect/testVectors create mode 100644 SecurityTests/cspxutils/ascTool/Makefile create mode 100644 SecurityTests/cspxutils/ascTool/ascTool.cpp create mode 100644 SecurityTests/cspxutils/asymCompat/Makefile create mode 100644 SecurityTests/cspxutils/asymCompat/asymCompat.c create mode 100644 SecurityTests/cspxutils/asymPerform/Makefile create mode 100644 SecurityTests/cspxutils/asymPerform/asymPerform.c create mode 100644 SecurityTests/cspxutils/asymTest/Makefile create mode 100644 SecurityTests/cspxutils/asymTest/asymTest.c create mode 100644 SecurityTests/cspxutils/attachLeak/Makefile create mode 100644 SecurityTests/cspxutils/attachLeak/attachLeak.c create mode 100644 SecurityTests/cspxutils/badattr/Makefile create mode 100644 SecurityTests/cspxutils/badattr/badattr.c create mode 100644 SecurityTests/cspxutils/badmac/Makefile create mode 100644 SecurityTests/cspxutils/badmac/badmac.c create mode 100644 SecurityTests/cspxutils/badsig/Makefile create mode 100644 SecurityTests/cspxutils/badsig/badsig.c create mode 100755 SecurityTests/cspxutils/buildExample create mode 100644 SecurityTests/cspxutils/ccCtxSize/Makefile create mode 100644 SecurityTests/cspxutils/ccCtxSize/ccCtxSize.c create mode 100644 SecurityTests/cspxutils/ccHmacClone/Makefile create mode 100644 SecurityTests/cspxutils/ccHmacClone/ccHmacClone.cpp create mode 100644 SecurityTests/cspxutils/ccHmacCompat/Makefile create mode 100644 SecurityTests/cspxutils/ccHmacCompat/ccHmacCompat.c create mode 100644 SecurityTests/cspxutils/ccOneShot/Makefile create mode 100644 SecurityTests/cspxutils/ccOneShot/ccOneShot.cpp create mode 100644 SecurityTests/cspxutils/ccOpensslCompat/Makefile create mode 100644 SecurityTests/cspxutils/ccOpensslCompat/ccOpensslCompat.cpp create mode 100644 SecurityTests/cspxutils/ccOpensslCompat/digestCommon.h create mode 100644 SecurityTests/cspxutils/ccOpensslCompat/digestCommonCrypto.cpp create mode 100644 SecurityTests/cspxutils/ccOpensslCompat/digestCommonExtern.h create mode 100644 SecurityTests/cspxutils/ccOpensslCompat/digestOpenssl.cpp create mode 100644 SecurityTests/cspxutils/ccPerform/Makefile create mode 100644 SecurityTests/cspxutils/ccPerform/ccPerform.cpp create mode 100644 SecurityTests/cspxutils/ccSymCompat/Makefile create mode 100644 SecurityTests/cspxutils/ccSymCompat/ccSymCompat.c create mode 100644 SecurityTests/cspxutils/ccSymTest/Makefile create mode 100644 SecurityTests/cspxutils/ccSymTest/ccSymTest.cpp create mode 100755 SecurityTests/cspxutils/ccdvt create mode 100755 SecurityTests/cspxutils/ccmake create mode 100644 SecurityTests/cspxutils/clearPubKeyTest/Makefile create mode 100644 SecurityTests/cspxutils/clearPubKeyTest/clearPubKeyTest.cpp create mode 100644 SecurityTests/cspxutils/contextReuse/Makefile create mode 100644 SecurityTests/cspxutils/contextReuse/contextReuse.cpp create mode 100644 SecurityTests/cspxutils/cputimeCal/Makefile create mode 100644 SecurityTests/cspxutils/cputimeCal/cputimeCal.cpp create mode 100644 SecurityTests/cspxutils/cryptTool/Makefile create mode 100644 SecurityTests/cspxutils/cryptTool/README create mode 100644 SecurityTests/cspxutils/cryptTool/cryptTool.c create mode 100755 SecurityTests/cspxutils/cryptTool/runCrypt create mode 100755 SecurityTests/cspxutils/cspdvt create mode 100644 SecurityTests/cspxutils/cspdvt_usage create mode 100644 SecurityTests/cspxutils/cspxutils.pbproj/project.pbxproj create mode 100644 SecurityTests/cspxutils/dbTool/Makefile create mode 100644 SecurityTests/cspxutils/dbTool/dbAttrs.cpp create mode 100644 SecurityTests/cspxutils/dbTool/dbAttrs.h create mode 100644 SecurityTests/cspxutils/dbTool/dbCert.cpp create mode 100644 SecurityTests/cspxutils/dbTool/dbCert.h create mode 100644 SecurityTests/cspxutils/dbTool/dbTool.cpp create mode 100644 SecurityTests/cspxutils/dbVerifyKey/Makefile create mode 100644 SecurityTests/cspxutils/dbVerifyKey/dbVerifyKey.cpp create mode 100644 SecurityTests/cspxutils/dhFulltest/Makefile create mode 100644 SecurityTests/cspxutils/dhFulltest/dhFulltest.cpp create mode 100644 SecurityTests/cspxutils/dhFulltest/dhParams_512.der create mode 100644 SecurityTests/cspxutils/dhTest/Makefile create mode 100644 SecurityTests/cspxutils/dhTest/README create mode 100644 SecurityTests/cspxutils/dhTest/dhParams_512.der create mode 100644 SecurityTests/cspxutils/dhTest/dhTest.cpp create mode 100644 SecurityTests/cspxutils/dsaPartial/Makefile create mode 100644 SecurityTests/cspxutils/dsaPartial/dsaParam512_1.der create mode 100644 SecurityTests/cspxutils/dsaPartial/dsaParam512_2.der create mode 100644 SecurityTests/cspxutils/dsaPartial/dsaPartial.cpp create mode 100644 SecurityTests/cspxutils/ecdhTest/Makefile create mode 100644 SecurityTests/cspxutils/ecdhTest/ecdhTest.cpp create mode 100755 SecurityTests/cspxutils/feeCurve create mode 100755 SecurityTests/cspxutils/feedvt create mode 100644 SecurityTests/cspxutils/genErrorStrings/Makefile create mode 100644 SecurityTests/cspxutils/genErrorStrings/fileIo.c create mode 100644 SecurityTests/cspxutils/genErrorStrings/fileIo.h create mode 100644 SecurityTests/cspxutils/genErrorStrings/genErrorStrings.cpp create mode 100755 SecurityTests/cspxutils/genErrorStrings/genStrings create mode 100644 SecurityTests/cspxutils/genKeyPair/Makefile create mode 100644 SecurityTests/cspxutils/genKeyPair/genKeyPair.cpp create mode 100644 SecurityTests/cspxutils/hashClone/Makefile create mode 100644 SecurityTests/cspxutils/hashClone/hashClone.c create mode 100644 SecurityTests/cspxutils/hashCompat/Makefile create mode 100644 SecurityTests/cspxutils/hashCompat/hashCompat.c create mode 100644 SecurityTests/cspxutils/hashTest/Makefile create mode 100644 SecurityTests/cspxutils/hashTest/hashTest.c create mode 100644 SecurityTests/cspxutils/hashTime/MD5.c create mode 100644 SecurityTests/cspxutils/hashTime/MD5.h create mode 100644 SecurityTests/cspxutils/hashTime/Makefile create mode 100644 SecurityTests/cspxutils/hashTime/SHA1.c create mode 100644 SecurityTests/cspxutils/hashTime/SHA1.h create mode 100644 SecurityTests/cspxutils/hashTime/SHA1_priv.c create mode 100644 SecurityTests/cspxutils/hashTime/SHA1_priv.h create mode 100644 SecurityTests/cspxutils/hashTime/hashTime.cpp create mode 100644 SecurityTests/cspxutils/hashTimeLibCrypt/Makefile create mode 100644 SecurityTests/cspxutils/hashTimeLibCrypt/hashTimeLibCrypt.cpp create mode 100644 SecurityTests/cspxutils/hashTimeLibCrypt/pbkdDigest.cpp create mode 100644 SecurityTests/cspxutils/hashTimeLibCrypt/pbkdDigest.h create mode 100644 SecurityTests/cspxutils/hashTimeSA/MD5.c create mode 100644 SecurityTests/cspxutils/hashTimeSA/MD5.h create mode 100644 SecurityTests/cspxutils/hashTimeSA/Makefile create mode 100644 SecurityTests/cspxutils/hashTimeSA/SHA1.c create mode 100644 SecurityTests/cspxutils/hashTimeSA/SHA1.h create mode 100644 SecurityTests/cspxutils/hashTimeSA/SHA1_priv.c create mode 100644 SecurityTests/cspxutils/hashTimeSA/SHA1_priv.h create mode 100644 SecurityTests/cspxutils/hashTimeSA/hashTimeSA.cpp create mode 100644 SecurityTests/cspxutils/keyDate/Makefile create mode 100644 SecurityTests/cspxutils/keyDate/keyDate.cpp create mode 100644 SecurityTests/cspxutils/keyHash/Makefile create mode 100644 SecurityTests/cspxutils/keyHash/keyHash.c create mode 100644 SecurityTests/cspxutils/keyHashAsym/Makefile create mode 100644 SecurityTests/cspxutils/keyHashAsym/dhParams_512.der create mode 100644 SecurityTests/cspxutils/keyHashAsym/dsaParams_512.der create mode 100644 SecurityTests/cspxutils/keyHashAsym/keyHashAsym.c create mode 100644 SecurityTests/cspxutils/keySizePref/Makefile create mode 100644 SecurityTests/cspxutils/keySizePref/keySizePref.cpp create mode 100755 SecurityTests/cspxutils/keyStore/Makefile create mode 100644 SecurityTests/cspxutils/keyStore/keyStore.c create mode 100755 SecurityTests/cspxutils/keyStoreLeak/Makefile create mode 100644 SecurityTests/cspxutils/keyStoreLeak/keyStoreLeak.c create mode 100644 SecurityTests/cspxutils/macCompat/Makefile create mode 100644 SecurityTests/cspxutils/macCompat/macCompat.c create mode 100644 SecurityTests/cspxutils/macTest/Makefile create mode 100644 SecurityTests/cspxutils/macTest/macTest.c create mode 100644 SecurityTests/cspxutils/mdsLookup/Makefile create mode 100644 SecurityTests/cspxutils/mdsLookup/mdsLookup.cpp create mode 100644 SecurityTests/cspxutils/mdsdump/MDSSchema.cpp create mode 100644 SecurityTests/cspxutils/mdsdump/MDSSchema.h create mode 100644 SecurityTests/cspxutils/mdsdump/Makefile create mode 100644 SecurityTests/cspxutils/mdsdump/mdsdump.cpp create mode 100644 SecurityTests/cspxutils/miniWrap/Makefile create mode 100644 SecurityTests/cspxutils/miniWrap/miniWrap.c create mode 100644 SecurityTests/cspxutils/pbeTest/Makefile create mode 100644 SecurityTests/cspxutils/pbeTest/pbeTest.c create mode 100644 SecurityTests/cspxutils/perform/Makefile create mode 100755 SecurityTests/cspxutils/perform/aesPerform create mode 100755 SecurityTests/cspxutils/perform/doPerform create mode 100644 SecurityTests/cspxutils/perform/perform.cpp create mode 100644 SecurityTests/cspxutils/performRaw/Makefile create mode 100755 SecurityTests/cspxutils/performRaw/aesPerformRaw create mode 100755 SecurityTests/cspxutils/performRaw/doPerformRaw create mode 100644 SecurityTests/cspxutils/performRaw/performRaw.cpp create mode 100755 SecurityTests/cspxutils/performSuite create mode 100644 SecurityTests/cspxutils/pubKeyTool/Makefile create mode 100644 SecurityTests/cspxutils/pubKeyTool/derive_pub.der create mode 100644 SecurityTests/cspxutils/pubKeyTool/pubKeyTool.cpp create mode 100644 SecurityTests/cspxutils/pubKeyTool/rsa_priv.der create mode 100644 SecurityTests/cspxutils/pubKeyTool/rsa_pub.der create mode 100644 SecurityTests/cspxutils/randTest/Makefile create mode 100644 SecurityTests/cspxutils/randTest/randTest.c create mode 100644 SecurityTests/cspxutils/rawRsaSig/Makefile create mode 100644 SecurityTests/cspxutils/rawRsaSig/rawRsaSig.c create mode 100755 SecurityTests/cspxutils/rawSig/Makefile create mode 100755 SecurityTests/cspxutils/rawSig/rawSig.c create mode 100644 SecurityTests/cspxutils/rsatool/Makefile create mode 100644 SecurityTests/cspxutils/rsatool/README create mode 100644 SecurityTests/cspxutils/rsatool/rsatool.c create mode 100644 SecurityTests/cspxutils/sha2Time/Makefile create mode 100644 SecurityTests/cspxutils/sha2Time/sha2Time.cpp create mode 100644 SecurityTests/cspxutils/sha2Vectors/Makefile create mode 100644 SecurityTests/cspxutils/sha2Vectors/sha2Vectors.cpp create mode 100644 SecurityTests/cspxutils/sha2VectorsCdsa/Makefile create mode 100644 SecurityTests/cspxutils/sha2VectorsCdsa/sha2VectorsCdsa.cpp create mode 100644 SecurityTests/cspxutils/sigPerform/Makefile create mode 100644 SecurityTests/cspxutils/sigPerform/sigPerform.c create mode 100644 SecurityTests/cspxutils/sigtest/Makefile create mode 100644 SecurityTests/cspxutils/sigtest/sigtest.c create mode 100644 SecurityTests/cspxutils/sshKey/Makefile create mode 100644 SecurityTests/cspxutils/sshKey/sshKey.cpp create mode 100644 SecurityTests/cspxutils/ssl2Padding/Makefile create mode 100644 SecurityTests/cspxutils/ssl2Padding/ssl2Padding.cpp create mode 100644 SecurityTests/cspxutils/symCompat/Makefile create mode 100644 SecurityTests/cspxutils/symCompat/symCompat.c create mode 100644 SecurityTests/cspxutils/symDelta/Makefile create mode 100644 SecurityTests/cspxutils/symDelta/symDelta.c create mode 100644 SecurityTests/cspxutils/symReference/Makefile create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ctext_3DES create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ctext_AES create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ctext_AES192 create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ctext_AES256 create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ctext_ASC create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ctext_Blowfish create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ctext_CAST create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ctext_DES create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ctext_RC2 create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ctext_RC4 create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ctext_RC5 create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/iv_3DES create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/iv_AES create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/iv_AES192 create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/iv_AES256 create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/iv_Blowfish create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/iv_CAST create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/iv_DES create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/iv_RC2 create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/iv_RC5 create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/key_3DES create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/key_AES create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/key_AES192 create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/key_AES256 create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/key_ASC create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/key_Blowfish create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/key_CAST create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/key_DES create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/key_RC2 create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/key_RC4 create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/key_RC5 create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ptext_3DES create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ptext_AES create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ptext_AES192 create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ptext_AES256 create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ptext_ASC create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ptext_Blowfish create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ptext_CAST create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ptext_DES create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ptext_RC2 create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ptext_RC4 create mode 100644 SecurityTests/cspxutils/symReference/blobs/G4/ptext_RC5 create mode 100644 SecurityTests/cspxutils/symReference/symReference.cpp create mode 100644 SecurityTests/cspxutils/symTest/Makefile create mode 100644 SecurityTests/cspxutils/symTest/symTest.c create mode 100755 SecurityTests/cspxutils/testall create mode 100644 SecurityTests/cspxutils/utilLib/Makefile create mode 100644 SecurityTests/cspxutils/utilLib/boxes-ref.h create mode 100644 SecurityTests/cspxutils/utilLib/bsafeUtils.c create mode 100644 SecurityTests/cspxutils/utilLib/bsafeUtils.h create mode 100644 SecurityTests/cspxutils/utilLib/common.c create mode 100644 SecurityTests/cspxutils/utilLib/common.h create mode 100644 SecurityTests/cspxutils/utilLib/commonCpp.cpp create mode 100644 SecurityTests/cspxutils/utilLib/cputime.c create mode 100644 SecurityTests/cspxutils/utilLib/cputime.h create mode 100755 SecurityTests/cspxutils/utilLib/cspdlTesting.h create mode 100644 SecurityTests/cspxutils/utilLib/cspwrap.c create mode 100644 SecurityTests/cspxutils/utilLib/cspwrap.h create mode 100644 SecurityTests/cspxutils/utilLib/cssmErrorStrings.h create mode 100644 SecurityTests/cspxutils/utilLib/fileIo.c create mode 100644 SecurityTests/cspxutils/utilLib/fileIo.h create mode 100644 SecurityTests/cspxutils/utilLib/nssAppUtils.cpp create mode 100644 SecurityTests/cspxutils/utilLib/nssAppUtils.h create mode 100644 SecurityTests/cspxutils/utilLib/rijndael-alg-ref.c create mode 100644 SecurityTests/cspxutils/utilLib/rijndael-alg-ref.h create mode 100644 SecurityTests/cspxutils/utilLib/rijndaelApi.c create mode 100644 SecurityTests/cspxutils/utilLib/rijndaelApi.h create mode 100644 SecurityTests/cspxutils/utilLib/ssleayUtils.cpp create mode 100644 SecurityTests/cspxutils/utilLib/ssleayUtils.h create mode 100644 SecurityTests/cspxutils/utilLib/t_stdlib.c create mode 100644 SecurityTests/cspxutils/wrap/Makefile create mode 100644 SecurityTests/cspxutils/wrap/wrap.c create mode 100644 SecurityTests/cspxutils/wrapTest/Makefile create mode 100644 SecurityTests/cspxutils/wrapTest/wrapTest.c create mode 100644 SecurityTests/mobileasset-certs/AppleRootCertificate.crt create mode 100644 SecurityTests/mobileasset-certs/Invalid-task_signing.crt create mode 100644 SecurityTests/mobileasset-certs/asset_signing.crt create mode 100644 SecurityTests/mobileasset-certs/iPhoneCACert.crt create mode 100644 SecurityTests/nist-certs/AllCertificatesNoPoliciesTest2EE.crt create mode 100644 SecurityTests/nist-certs/AllCertificatesSamePoliciesTest10EE.crt create mode 100644 SecurityTests/nist-certs/AllCertificatesSamePoliciesTest13EE.crt create mode 100644 SecurityTests/nist-certs/AllCertificatesanyPolicyTest11EE.crt create mode 100644 SecurityTests/nist-certs/AnyPolicyTest14EE.crt create mode 100644 SecurityTests/nist-certs/BadCRLIssuerNameCACert.crt create mode 100644 SecurityTests/nist-certs/BadCRLSignatureCACert.crt create mode 100644 SecurityTests/nist-certs/BadSignedCACert.crt create mode 100644 SecurityTests/nist-certs/BadnotAfterDateCACert.crt create mode 100644 SecurityTests/nist-certs/BadnotBeforeDateCACert.crt create mode 100644 SecurityTests/nist-certs/BasicSelfIssuedCRLSigningKeyCACert.crt create mode 100644 SecurityTests/nist-certs/BasicSelfIssuedNewKeyCACert.crt create mode 100644 SecurityTests/nist-certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt create mode 100644 SecurityTests/nist-certs/BasicSelfIssuedOldKeyCACert.crt create mode 100644 SecurityTests/nist-certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt create mode 100644 SecurityTests/nist-certs/CPSPointerQualifierTest20EE.crt create mode 100644 SecurityTests/nist-certs/DSACACert.crt create mode 100644 SecurityTests/nist-certs/DSAParametersInheritedCACert.crt create mode 100644 SecurityTests/nist-certs/DifferentPoliciesTest12EE.crt create mode 100644 SecurityTests/nist-certs/DifferentPoliciesTest3EE.crt create mode 100644 SecurityTests/nist-certs/DifferentPoliciesTest4EE.crt create mode 100644 SecurityTests/nist-certs/DifferentPoliciesTest5EE.crt create mode 100644 SecurityTests/nist-certs/DifferentPoliciesTest7EE.crt create mode 100644 SecurityTests/nist-certs/DifferentPoliciesTest8EE.crt create mode 100644 SecurityTests/nist-certs/DifferentPoliciesTest9EE.crt create mode 100644 SecurityTests/nist-certs/Expectations.plist create mode 100644 SecurityTests/nist-certs/GeneralizedTimeCRLnextUpdateCACert.crt create mode 100644 SecurityTests/nist-certs/GoodCACert.crt create mode 100644 SecurityTests/nist-certs/GoodsubCACert.crt create mode 100644 SecurityTests/nist-certs/GoodsubCAPanyPolicyMapping1to2CACert.crt create mode 100644 SecurityTests/nist-certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt create mode 100644 SecurityTests/nist-certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt create mode 100644 SecurityTests/nist-certs/InvalidCASignatureTest2EE.crt create mode 100644 SecurityTests/nist-certs/InvalidCAnotAfterDateTest5EE.crt create mode 100644 SecurityTests/nist-certs/InvalidCAnotBeforeDateTest1EE.crt create mode 100644 SecurityTests/nist-certs/InvalidDNSnameConstraintsTest31EE.crt create mode 100644 SecurityTests/nist-certs/InvalidDNSnameConstraintsTest33EE.crt create mode 100644 SecurityTests/nist-certs/InvalidDNSnameConstraintsTest38EE.crt create mode 100644 SecurityTests/nist-certs/InvalidDNandRFC822nameConstraintsTest28EE.crt create mode 100644 SecurityTests/nist-certs/InvalidDNandRFC822nameConstraintsTest29EE.crt create mode 100644 SecurityTests/nist-certs/InvalidDNnameConstraintsTest10EE.crt create mode 100644 SecurityTests/nist-certs/InvalidDNnameConstraintsTest12EE.crt create mode 100644 SecurityTests/nist-certs/InvalidDNnameConstraintsTest13EE.crt create mode 100644 SecurityTests/nist-certs/InvalidDNnameConstraintsTest15EE.crt create mode 100644 SecurityTests/nist-certs/InvalidDNnameConstraintsTest16EE.crt create mode 100644 SecurityTests/nist-certs/InvalidDNnameConstraintsTest17EE.crt create mode 100644 SecurityTests/nist-certs/InvalidDNnameConstraintsTest20EE.crt create mode 100644 SecurityTests/nist-certs/InvalidDNnameConstraintsTest2EE.crt create mode 100644 SecurityTests/nist-certs/InvalidDNnameConstraintsTest3EE.crt create mode 100644 SecurityTests/nist-certs/InvalidDNnameConstraintsTest7EE.crt create mode 100644 SecurityTests/nist-certs/InvalidDNnameConstraintsTest8EE.crt create mode 100644 SecurityTests/nist-certs/InvalidDNnameConstraintsTest9EE.crt create mode 100644 SecurityTests/nist-certs/InvalidDSASignatureTest6EE.crt create mode 100644 SecurityTests/nist-certs/InvalidEESignatureTest3EE.crt create mode 100644 SecurityTests/nist-certs/InvalidEEnotAfterDateTest6EE.crt create mode 100644 SecurityTests/nist-certs/InvalidEEnotBeforeDateTest2EE.crt create mode 100644 SecurityTests/nist-certs/InvalidLongSerialNumberTest18EE.crt create mode 100644 SecurityTests/nist-certs/InvalidMappingFromanyPolicyTest7EE.crt create mode 100644 SecurityTests/nist-certs/InvalidMappingToanyPolicyTest8EE.crt create mode 100644 SecurityTests/nist-certs/InvalidMissingbasicConstraintsTest1EE.crt create mode 100644 SecurityTests/nist-certs/InvalidNameChainingOrderTest2EE.crt create mode 100644 SecurityTests/nist-certs/InvalidNameChainingTest1EE.crt create mode 100644 SecurityTests/nist-certs/InvalidNegativeSerialNumberTest15EE.crt create mode 100644 SecurityTests/nist-certs/InvalidPolicyMappingTest10EE.crt create mode 100644 SecurityTests/nist-certs/InvalidPolicyMappingTest2EE.crt create mode 100644 SecurityTests/nist-certs/InvalidPolicyMappingTest4EE.crt create mode 100644 SecurityTests/nist-certs/InvalidRFC822nameConstraintsTest22EE.crt create mode 100644 SecurityTests/nist-certs/InvalidRFC822nameConstraintsTest24EE.crt create mode 100644 SecurityTests/nist-certs/InvalidRFC822nameConstraintsTest26EE.crt create mode 100644 SecurityTests/nist-certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt create mode 100644 SecurityTests/nist-certs/InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt create mode 100644 SecurityTests/nist-certs/InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt create mode 100644 SecurityTests/nist-certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt create mode 100644 SecurityTests/nist-certs/InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt create mode 100644 SecurityTests/nist-certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt create mode 100644 SecurityTests/nist-certs/InvalidSelfIssuedpathLenConstraintTest16EE.crt create mode 100644 SecurityTests/nist-certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt create mode 100644 SecurityTests/nist-certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt create mode 100644 SecurityTests/nist-certs/InvalidURInameConstraintsTest35EE.crt create mode 100644 SecurityTests/nist-certs/InvalidURInameConstraintsTest37EE.crt create mode 100644 SecurityTests/nist-certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt create mode 100644 SecurityTests/nist-certs/InvalidcAFalseTest2EE.crt create mode 100644 SecurityTests/nist-certs/InvalidcAFalseTest3EE.crt create mode 100644 SecurityTests/nist-certs/InvalidcRLIssuerTest27EE.crt create mode 100644 SecurityTests/nist-certs/InvalidcRLIssuerTest31EE.crt create mode 100644 SecurityTests/nist-certs/InvalidcRLIssuerTest32EE.crt create mode 100644 SecurityTests/nist-certs/InvalidcRLIssuerTest34EE.crt create mode 100644 SecurityTests/nist-certs/InvalidcRLIssuerTest35EE.crt create mode 100644 SecurityTests/nist-certs/InvalidinhibitAnyPolicyTest1EE.crt create mode 100644 SecurityTests/nist-certs/InvalidinhibitAnyPolicyTest4EE.crt create mode 100644 SecurityTests/nist-certs/InvalidinhibitAnyPolicyTest5EE.crt create mode 100644 SecurityTests/nist-certs/InvalidinhibitAnyPolicyTest6EE.crt create mode 100644 SecurityTests/nist-certs/InvalidinhibitPolicyMappingTest1EE.crt create mode 100644 SecurityTests/nist-certs/InvalidinhibitPolicyMappingTest3EE.crt create mode 100644 SecurityTests/nist-certs/InvalidinhibitPolicyMappingTest5EE.crt create mode 100644 SecurityTests/nist-certs/InvalidinhibitPolicyMappingTest6EE.crt create mode 100644 SecurityTests/nist-certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt create mode 100644 SecurityTests/nist-certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt create mode 100644 SecurityTests/nist-certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt create mode 100644 SecurityTests/nist-certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt create mode 100644 SecurityTests/nist-certs/InvalidonlyContainsAttributeCertsTest14EE.crt create mode 100644 SecurityTests/nist-certs/InvalidonlyContainsCACertsTest12EE.crt create mode 100644 SecurityTests/nist-certs/InvalidonlyContainsUserCertsTest11EE.crt create mode 100644 SecurityTests/nist-certs/InvalidonlySomeReasonsTest15EE.crt create mode 100644 SecurityTests/nist-certs/InvalidonlySomeReasonsTest16EE.crt create mode 100644 SecurityTests/nist-certs/InvalidonlySomeReasonsTest17EE.crt create mode 100644 SecurityTests/nist-certs/InvalidonlySomeReasonsTest20EE.crt create mode 100644 SecurityTests/nist-certs/InvalidonlySomeReasonsTest21EE.crt create mode 100644 SecurityTests/nist-certs/InvalidpathLenConstraintTest10EE.crt create mode 100644 SecurityTests/nist-certs/InvalidpathLenConstraintTest11EE.crt create mode 100644 SecurityTests/nist-certs/InvalidpathLenConstraintTest12EE.crt create mode 100644 SecurityTests/nist-certs/InvalidpathLenConstraintTest5EE.crt create mode 100644 SecurityTests/nist-certs/InvalidpathLenConstraintTest6EE.crt create mode 100644 SecurityTests/nist-certs/InvalidpathLenConstraintTest9EE.crt create mode 100644 SecurityTests/nist-certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt create mode 100644 SecurityTests/nist-certs/InvalidrequireExplicitPolicyTest3EE.crt create mode 100644 SecurityTests/nist-certs/InvalidrequireExplicitPolicyTest5EE.crt create mode 100644 SecurityTests/nist-certs/LongSerialNumberCACert.crt create mode 100644 SecurityTests/nist-certs/Mapping1to2CACert.crt create mode 100644 SecurityTests/nist-certs/MappingFromanyPolicyCACert.crt create mode 100644 SecurityTests/nist-certs/MappingToanyPolicyCACert.crt create mode 100644 SecurityTests/nist-certs/MissingbasicConstraintsCACert.crt create mode 100644 SecurityTests/nist-certs/NameOrderingCACert.crt create mode 100644 SecurityTests/nist-certs/NegativeSerialNumberCACert.crt create mode 100644 SecurityTests/nist-certs/NoCRLCACert.crt create mode 100644 SecurityTests/nist-certs/NoPoliciesCACert.crt create mode 100644 SecurityTests/nist-certs/NoissuingDistributionPointCACert.crt create mode 100644 SecurityTests/nist-certs/OldCRLnextUpdateCACert.crt create mode 100644 SecurityTests/nist-certs/OverlappingPoliciesTest6EE.crt create mode 100644 SecurityTests/nist-certs/P12Mapping1to3CACert.crt create mode 100644 SecurityTests/nist-certs/P12Mapping1to3subCACert.crt create mode 100644 SecurityTests/nist-certs/P12Mapping1to3subsubCACert.crt create mode 100644 SecurityTests/nist-certs/P1Mapping1to234CACert.crt create mode 100644 SecurityTests/nist-certs/P1Mapping1to234subCACert.crt create mode 100644 SecurityTests/nist-certs/P1anyPolicyMapping1to2CACert.crt create mode 100644 SecurityTests/nist-certs/PanyPolicyMapping1to2CACert.crt create mode 100644 SecurityTests/nist-certs/PoliciesP1234CACert.crt create mode 100644 SecurityTests/nist-certs/PoliciesP1234subCAP123Cert.crt create mode 100644 SecurityTests/nist-certs/PoliciesP1234subsubCAP123P12Cert.crt create mode 100644 SecurityTests/nist-certs/PoliciesP123CACert.crt create mode 100644 SecurityTests/nist-certs/PoliciesP123subCAP12Cert.crt create mode 100644 SecurityTests/nist-certs/PoliciesP123subsubCAP12P1Cert.crt create mode 100644 SecurityTests/nist-certs/PoliciesP123subsubCAP12P2Cert.crt create mode 100644 SecurityTests/nist-certs/PoliciesP123subsubsubCAP12P2P1Cert.crt create mode 100644 SecurityTests/nist-certs/PoliciesP12CACert.crt create mode 100644 SecurityTests/nist-certs/PoliciesP12subCAP1Cert.crt create mode 100644 SecurityTests/nist-certs/PoliciesP12subsubCAP1P2Cert.crt create mode 100644 SecurityTests/nist-certs/PoliciesP2subCA2Cert.crt create mode 100644 SecurityTests/nist-certs/PoliciesP2subCACert.crt create mode 100644 SecurityTests/nist-certs/PoliciesP3CACert.crt create mode 100644 SecurityTests/nist-certs/RFC3280MandatoryAttributeTypesCACert.crt create mode 100644 SecurityTests/nist-certs/RFC3280OptionalAttributeTypesCACert.crt create mode 100644 SecurityTests/nist-certs/RevokedsubCACert.crt create mode 100644 SecurityTests/nist-certs/RolloverfromPrintableStringtoUTF8StringCACert.crt create mode 100644 SecurityTests/nist-certs/SeparateCertificateandCRLKeysCA2CRLSigningCert.crt create mode 100644 SecurityTests/nist-certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt create mode 100644 SecurityTests/nist-certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt create mode 100644 SecurityTests/nist-certs/TrustAnchorRootCertificate.crt create mode 100644 SecurityTests/nist-certs/TwoCRLsCACert.crt create mode 100644 SecurityTests/nist-certs/UIDCACert.crt create mode 100644 SecurityTests/nist-certs/UTF8StringCaseInsensitiveMatchCACert.crt create mode 100644 SecurityTests/nist-certs/UTF8StringEncodedNamesCACert.crt create mode 100644 SecurityTests/nist-certs/UnknownCRLEntryExtensionCACert.crt create mode 100644 SecurityTests/nist-certs/UnknownCRLExtensionCACert.crt create mode 100644 SecurityTests/nist-certs/UserNoticeQualifierTest15EE.crt create mode 100644 SecurityTests/nist-certs/UserNoticeQualifierTest16EE.crt create mode 100644 SecurityTests/nist-certs/UserNoticeQualifierTest17EE.crt create mode 100644 SecurityTests/nist-certs/UserNoticeQualifierTest18EE.crt create mode 100644 SecurityTests/nist-certs/UserNoticeQualifierTest19EE.crt create mode 100644 SecurityTests/nist-certs/ValidBasicSelfIssuedNewWithOldTest3EE.crt create mode 100644 SecurityTests/nist-certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt create mode 100644 SecurityTests/nist-certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt create mode 100644 SecurityTests/nist-certs/ValidCertificatePathTest1EE.crt create mode 100644 SecurityTests/nist-certs/ValidDNSnameConstraintsTest30EE.crt create mode 100644 SecurityTests/nist-certs/ValidDNSnameConstraintsTest32EE.crt create mode 100644 SecurityTests/nist-certs/ValidDNandRFC822nameConstraintsTest27EE.crt create mode 100644 SecurityTests/nist-certs/ValidDNnameConstraintsTest11EE.crt create mode 100644 SecurityTests/nist-certs/ValidDNnameConstraintsTest14EE.crt create mode 100644 SecurityTests/nist-certs/ValidDNnameConstraintsTest18EE.crt create mode 100644 SecurityTests/nist-certs/ValidDNnameConstraintsTest19EE.crt create mode 100644 SecurityTests/nist-certs/ValidDNnameConstraintsTest1EE.crt create mode 100644 SecurityTests/nist-certs/ValidDNnameConstraintsTest4EE.crt create mode 100644 SecurityTests/nist-certs/ValidDNnameConstraintsTest5EE.crt create mode 100644 SecurityTests/nist-certs/ValidDNnameConstraintsTest6EE.crt create mode 100644 SecurityTests/nist-certs/ValidDSAParameterInheritanceTest5EE.crt create mode 100644 SecurityTests/nist-certs/ValidDSASignaturesTest4EE.crt create mode 100644 SecurityTests/nist-certs/ValidGeneralizedTimenotAfterDateTest8EE.crt create mode 100644 SecurityTests/nist-certs/ValidGeneralizedTimenotBeforeDateTest4EE.crt create mode 100644 SecurityTests/nist-certs/ValidLongSerialNumberTest16EE.crt create mode 100644 SecurityTests/nist-certs/ValidLongSerialNumberTest17EE.crt create mode 100644 SecurityTests/nist-certs/ValidNameChainingCapitalizationTest5EE.crt create mode 100644 SecurityTests/nist-certs/ValidNameChainingWhitespaceTest3EE.crt create mode 100644 SecurityTests/nist-certs/ValidNameChainingWhitespaceTest4EE.crt create mode 100644 SecurityTests/nist-certs/ValidNameUIDsTest6EE.crt create mode 100644 SecurityTests/nist-certs/ValidNegativeSerialNumberTest14EE.crt create mode 100644 SecurityTests/nist-certs/ValidPolicyMappingTest11EE.crt create mode 100644 SecurityTests/nist-certs/ValidPolicyMappingTest12EE.crt create mode 100644 SecurityTests/nist-certs/ValidPolicyMappingTest13EE.crt create mode 100644 SecurityTests/nist-certs/ValidPolicyMappingTest14EE.crt create mode 100644 SecurityTests/nist-certs/ValidPolicyMappingTest1EE.crt create mode 100644 SecurityTests/nist-certs/ValidPolicyMappingTest3EE.crt create mode 100644 SecurityTests/nist-certs/ValidPolicyMappingTest5EE.crt create mode 100644 SecurityTests/nist-certs/ValidPolicyMappingTest6EE.crt create mode 100644 SecurityTests/nist-certs/ValidPolicyMappingTest9EE.crt create mode 100644 SecurityTests/nist-certs/ValidRFC3280MandatoryAttributeTypesTest7EE.crt create mode 100644 SecurityTests/nist-certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt create mode 100644 SecurityTests/nist-certs/ValidRFC822nameConstraintsTest21EE.crt create mode 100644 SecurityTests/nist-certs/ValidRFC822nameConstraintsTest23EE.crt create mode 100644 SecurityTests/nist-certs/ValidRFC822nameConstraintsTest25EE.crt create mode 100644 SecurityTests/nist-certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt create mode 100644 SecurityTests/nist-certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt create mode 100644 SecurityTests/nist-certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt create mode 100644 SecurityTests/nist-certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt create mode 100644 SecurityTests/nist-certs/ValidSelfIssuedpathLenConstraintTest15EE.crt create mode 100644 SecurityTests/nist-certs/ValidSelfIssuedpathLenConstraintTest17EE.crt create mode 100644 SecurityTests/nist-certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt create mode 100644 SecurityTests/nist-certs/ValidURInameConstraintsTest34EE.crt create mode 100644 SecurityTests/nist-certs/ValidURInameConstraintsTest36EE.crt create mode 100644 SecurityTests/nist-certs/ValidUTF8StringCaseInsensitiveMatchTest11EE.crt create mode 100644 SecurityTests/nist-certs/ValidUTF8StringEncodedNamesTest9EE.crt create mode 100644 SecurityTests/nist-certs/ValidUnknownNotCriticalCertificateExtensionTest1EE.crt create mode 100644 SecurityTests/nist-certs/ValidbasicConstraintsNotCriticalTest4EE.crt create mode 100644 SecurityTests/nist-certs/ValidcRLIssuerTest28EE.crt create mode 100644 SecurityTests/nist-certs/ValidcRLIssuerTest29EE.crt create mode 100644 SecurityTests/nist-certs/ValidcRLIssuerTest30EE.crt create mode 100644 SecurityTests/nist-certs/ValidcRLIssuerTest33EE.crt create mode 100644 SecurityTests/nist-certs/ValidinhibitAnyPolicyTest2EE.crt create mode 100644 SecurityTests/nist-certs/ValidinhibitPolicyMappingTest2EE.crt create mode 100644 SecurityTests/nist-certs/ValidinhibitPolicyMappingTest4EE.crt create mode 100644 SecurityTests/nist-certs/ValidkeyUsageNotCriticalTest3EE.crt create mode 100644 SecurityTests/nist-certs/ValidonlyContainsCACertsTest13EE.crt create mode 100644 SecurityTests/nist-certs/ValidonlySomeReasonsTest18EE.crt create mode 100644 SecurityTests/nist-certs/ValidonlySomeReasonsTest19EE.crt create mode 100644 SecurityTests/nist-certs/ValidpathLenConstraintTest13EE.crt create mode 100644 SecurityTests/nist-certs/ValidpathLenConstraintTest14EE.crt create mode 100644 SecurityTests/nist-certs/ValidpathLenConstraintTest7EE.crt create mode 100644 SecurityTests/nist-certs/ValidpathLenConstraintTest8EE.crt create mode 100644 SecurityTests/nist-certs/Validpre2000UTCnotBeforeDateTest3EE.crt create mode 100644 SecurityTests/nist-certs/ValidrequireExplicitPolicyTest1EE.crt create mode 100644 SecurityTests/nist-certs/ValidrequireExplicitPolicyTest2EE.crt create mode 100644 SecurityTests/nist-certs/ValidrequireExplicitPolicyTest4EE.crt create mode 100644 SecurityTests/nist-certs/WrongCRLCACert.crt create mode 100644 SecurityTests/nist-certs/anyPolicyCACert.crt create mode 100644 SecurityTests/nist-certs/basicConstraintsCriticalcAFalseCACert.crt create mode 100644 SecurityTests/nist-certs/basicConstraintsNotCriticalCACert.crt create mode 100644 SecurityTests/nist-certs/basicConstraintsNotCriticalcAFalseCACert.crt create mode 100644 SecurityTests/nist-certs/deltaCRLCA1Cert.crt create mode 100644 SecurityTests/nist-certs/deltaCRLCA2Cert.crt create mode 100644 SecurityTests/nist-certs/deltaCRLCA3Cert.crt create mode 100644 SecurityTests/nist-certs/deltaCRLIndicatorNoBaseCACert.crt create mode 100644 SecurityTests/nist-certs/distributionPoint1CACert.crt create mode 100644 SecurityTests/nist-certs/distributionPoint2CACert.crt create mode 100644 SecurityTests/nist-certs/indirectCRLCA1Cert.crt create mode 100644 SecurityTests/nist-certs/indirectCRLCA2Cert.crt create mode 100644 SecurityTests/nist-certs/indirectCRLCA3Cert.crt create mode 100644 SecurityTests/nist-certs/indirectCRLCA3cRLIssuerCert.crt create mode 100644 SecurityTests/nist-certs/indirectCRLCA4Cert.crt create mode 100644 SecurityTests/nist-certs/indirectCRLCA4cRLIssuerCert.crt create mode 100644 SecurityTests/nist-certs/indirectCRLCA5Cert.crt create mode 100644 SecurityTests/nist-certs/indirectCRLCA6Cert.crt create mode 100644 SecurityTests/nist-certs/inhibitAnyPolicy0CACert.crt create mode 100644 SecurityTests/nist-certs/inhibitAnyPolicy1CACert.crt create mode 100644 SecurityTests/nist-certs/inhibitAnyPolicy1SelfIssuedCACert.crt create mode 100644 SecurityTests/nist-certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt create mode 100644 SecurityTests/nist-certs/inhibitAnyPolicy1subCA1Cert.crt create mode 100644 SecurityTests/nist-certs/inhibitAnyPolicy1subCA2Cert.crt create mode 100644 SecurityTests/nist-certs/inhibitAnyPolicy1subCAIAP5Cert.crt create mode 100644 SecurityTests/nist-certs/inhibitAnyPolicy1subsubCA2Cert.crt create mode 100644 SecurityTests/nist-certs/inhibitAnyPolicy5CACert.crt create mode 100644 SecurityTests/nist-certs/inhibitAnyPolicy5subCACert.crt create mode 100644 SecurityTests/nist-certs/inhibitAnyPolicy5subsubCACert.crt create mode 100644 SecurityTests/nist-certs/inhibitAnyPolicyTest3EE.crt create mode 100644 SecurityTests/nist-certs/inhibitPolicyMapping0CACert.crt create mode 100644 SecurityTests/nist-certs/inhibitPolicyMapping0subCACert.crt create mode 100644 SecurityTests/nist-certs/inhibitPolicyMapping1P12CACert.crt create mode 100644 SecurityTests/nist-certs/inhibitPolicyMapping1P12subCACert.crt create mode 100644 SecurityTests/nist-certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt create mode 100644 SecurityTests/nist-certs/inhibitPolicyMapping1P12subsubCACert.crt create mode 100644 SecurityTests/nist-certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt create mode 100644 SecurityTests/nist-certs/inhibitPolicyMapping1P1CACert.crt create mode 100644 SecurityTests/nist-certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt create mode 100644 SecurityTests/nist-certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt create mode 100644 SecurityTests/nist-certs/inhibitPolicyMapping1P1subCACert.crt create mode 100644 SecurityTests/nist-certs/inhibitPolicyMapping1P1subsubCACert.crt create mode 100644 SecurityTests/nist-certs/inhibitPolicyMapping5CACert.crt create mode 100644 SecurityTests/nist-certs/inhibitPolicyMapping5subCACert.crt create mode 100644 SecurityTests/nist-certs/inhibitPolicyMapping5subsubCACert.crt create mode 100644 SecurityTests/nist-certs/inhibitPolicyMapping5subsubsubCACert.crt create mode 100644 SecurityTests/nist-certs/keyUsageCriticalcRLSignFalseCACert.crt create mode 100644 SecurityTests/nist-certs/keyUsageCriticalkeyCertSignFalseCACert.crt create mode 100644 SecurityTests/nist-certs/keyUsageNotCriticalCACert.crt create mode 100644 SecurityTests/nist-certs/keyUsageNotCriticalcRLSignFalseCACert.crt create mode 100644 SecurityTests/nist-certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt create mode 100644 SecurityTests/nist-certs/nameConstraintsDN1CACert.crt create mode 100644 SecurityTests/nist-certs/nameConstraintsDN1SelfIssuedCACert.crt create mode 100644 SecurityTests/nist-certs/nameConstraintsDN1subCA1Cert.crt create mode 100644 SecurityTests/nist-certs/nameConstraintsDN1subCA2Cert.crt create mode 100644 SecurityTests/nist-certs/nameConstraintsDN1subCA3Cert.crt create mode 100644 SecurityTests/nist-certs/nameConstraintsDN2CACert.crt create mode 100644 SecurityTests/nist-certs/nameConstraintsDN3CACert.crt create mode 100644 SecurityTests/nist-certs/nameConstraintsDN3subCA1Cert.crt create mode 100644 SecurityTests/nist-certs/nameConstraintsDN3subCA2Cert.crt create mode 100644 SecurityTests/nist-certs/nameConstraintsDN4CACert.crt create mode 100644 SecurityTests/nist-certs/nameConstraintsDN5CACert.crt create mode 100644 SecurityTests/nist-certs/nameConstraintsDNS1CACert.crt create mode 100644 SecurityTests/nist-certs/nameConstraintsDNS2CACert.crt create mode 100644 SecurityTests/nist-certs/nameConstraintsRFC822CA1Cert.crt create mode 100644 SecurityTests/nist-certs/nameConstraintsRFC822CA2Cert.crt create mode 100644 SecurityTests/nist-certs/nameConstraintsRFC822CA3Cert.crt create mode 100644 SecurityTests/nist-certs/nameConstraintsURI1CACert.crt create mode 100644 SecurityTests/nist-certs/nameConstraintsURI2CACert.crt create mode 100644 SecurityTests/nist-certs/onlyContainsAttributeCertsCACert.crt create mode 100644 SecurityTests/nist-certs/onlyContainsCACertsCACert.crt create mode 100644 SecurityTests/nist-certs/onlyContainsUserCertsCACert.crt create mode 100644 SecurityTests/nist-certs/onlySomeReasonsCA1Cert.crt create mode 100644 SecurityTests/nist-certs/onlySomeReasonsCA2Cert.crt create mode 100644 SecurityTests/nist-certs/onlySomeReasonsCA3Cert.crt create mode 100644 SecurityTests/nist-certs/onlySomeReasonsCA4Cert.crt create mode 100644 SecurityTests/nist-certs/pathLenConstraint0CACert.crt create mode 100644 SecurityTests/nist-certs/pathLenConstraint0SelfIssuedCACert.crt create mode 100644 SecurityTests/nist-certs/pathLenConstraint0subCA2Cert.crt create mode 100644 SecurityTests/nist-certs/pathLenConstraint0subCACert.crt create mode 100644 SecurityTests/nist-certs/pathLenConstraint1CACert.crt create mode 100644 SecurityTests/nist-certs/pathLenConstraint1SelfIssuedCACert.crt create mode 100644 SecurityTests/nist-certs/pathLenConstraint1SelfIssuedsubCACert.crt create mode 100644 SecurityTests/nist-certs/pathLenConstraint1subCACert.crt create mode 100644 SecurityTests/nist-certs/pathLenConstraint6CACert.crt create mode 100644 SecurityTests/nist-certs/pathLenConstraint6subCA0Cert.crt create mode 100644 SecurityTests/nist-certs/pathLenConstraint6subCA1Cert.crt create mode 100644 SecurityTests/nist-certs/pathLenConstraint6subCA4Cert.crt create mode 100644 SecurityTests/nist-certs/pathLenConstraint6subsubCA00Cert.crt create mode 100644 SecurityTests/nist-certs/pathLenConstraint6subsubCA11Cert.crt create mode 100644 SecurityTests/nist-certs/pathLenConstraint6subsubCA41Cert.crt create mode 100644 SecurityTests/nist-certs/pathLenConstraint6subsubsubCA11XCert.crt create mode 100644 SecurityTests/nist-certs/pathLenConstraint6subsubsubCA41XCert.crt create mode 100644 SecurityTests/nist-certs/pre2000CRLnextUpdateCACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy0CACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy0subCACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy0subsubCACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy0subsubsubCACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy10CACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy10subCACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy10subsubCACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy10subsubsubCACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy2CACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy2SelfIssuedCACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy2SelfIssuedsubCACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy2subCACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy4CACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy4subCACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy4subsubCACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy4subsubsubCACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy5CACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy5subCACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy5subsubCACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy5subsubsubCACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy7CACert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy7subCARE2Cert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt create mode 100644 SecurityTests/nist-certs/requireExplicitPolicy7subsubsubCARE2RE4Cert.crt create mode 100644 SecurityTests/regressions/Makefile create mode 100644 SecurityTests/regressions/README create mode 100644 SecurityTests/regressions/auth/auth-01-immediate-agent.c create mode 100644 SecurityTests/regressions/auth/auth-02-aewp-basic.c create mode 100644 SecurityTests/regressions/auth/auth-SessionCreate-01-basic.c create mode 100644 SecurityTests/regressions/dl/dl-10-create-delete.c create mode 100644 SecurityTests/regressions/dl/dl-11-create-relation.c create mode 100644 SecurityTests/regressions/dl/dl-12-modify.c create mode 100644 SecurityTests/regressions/inc/MyHarness.pm create mode 100644 SecurityTests/regressions/inc/Test.pm create mode 100644 SecurityTests/regressions/inc/Test/Builder.pm create mode 100644 SecurityTests/regressions/inc/Test/Builder/Module.pm create mode 100644 SecurityTests/regressions/inc/Test/Builder/Tester.pm create mode 100644 SecurityTests/regressions/inc/Test/Builder/Tester/Color.pm create mode 100644 SecurityTests/regressions/inc/Test/Harness.pm create mode 100644 SecurityTests/regressions/inc/Test/Harness/Assert.pm create mode 100644 SecurityTests/regressions/inc/Test/Harness/Iterator.pm create mode 100644 SecurityTests/regressions/inc/Test/Harness/Point.pm create mode 100644 SecurityTests/regressions/inc/Test/Harness/Results.pm create mode 100644 SecurityTests/regressions/inc/Test/Harness/Straps.pm create mode 100644 SecurityTests/regressions/inc/Test/Harness/TAP.pod create mode 100644 SecurityTests/regressions/inc/Test/Harness/Util.pm create mode 100644 SecurityTests/regressions/inc/Test/More.pm create mode 100644 SecurityTests/regressions/inc/Test/Simple.pm create mode 100644 SecurityTests/regressions/inc/Test/Tutorial.pod create mode 100755 SecurityTests/regressions/kc/kc-05-retain-release.c create mode 100755 SecurityTests/regressions/kc/kc-10-unlock-noui.c create mode 100755 SecurityTests/regressions/kc/kc-11-unlock-referral.c create mode 100755 SecurityTests/regressions/kc/kc-12-status.c create mode 100755 SecurityTests/regressions/kc/kc-15-item-add-generic.c create mode 100644 SecurityTests/regressions/kc/kc-16-item-add-certificate.c create mode 100755 SecurityTests/regressions/kc/kc-17-item-find-key.c create mode 100755 SecurityTests/regressions/kc/kc-18-item-find-internet.c create mode 100755 SecurityTests/regressions/kc/kc-19-item-copy-internet.c create mode 100755 SecurityTests/regressions/kc/kc-20-item-change-label.m create mode 100644 SecurityTests/regressions/kc/kc-21-item-use-callback.c create mode 100755 SecurityTests/regressions/kc/kc-22-key-symmetric.c create mode 100755 SecurityTests/regressions/kc/kc-23-item-notify.c create mode 100755 SecurityTests/regressions/kc/kc-23-notify.c create mode 100755 SecurityTests/regressions/kc/kc-24-login.c create mode 100755 SecurityTests/regressions/kc/kc-25-bulk-notify.c create mode 100755 SecurityTests/regressions/kc/kc-26-is-valid.c create mode 100755 SecurityTests/regressions/kc/kc-30-trust.c create mode 100755 SecurityTests/regressions/kc/kc-40-item-change-label2.m create mode 100644 SecurityTests/regressions/kc/kc-46-dl-add-certificate.c create mode 100644 SecurityTests/regressions/kc/kc-50-iPhone-emulation.c create mode 100644 SecurityTests/regressions/kc/kc-50-thread.c create mode 100644 SecurityTests/regressions/kc/kc-51-testSecItemFind.c create mode 100644 SecurityTests/regressions/kc/kc-52-testCFEqualAndHash.c create mode 100755 SecurityTests/regressions/t/40kc-list.t create mode 100755 SecurityTests/regressions/t/40kc-unlock.t create mode 100755 SecurityTests/regressions/t/41kc-unlock-referral.t create mode 100644 SecurityTests/regressions/t/IPC/Run3.pm create mode 100755 SecurityTests/regressions/t/security.pl create mode 100644 SecurityTests/regressions/test/00testtest.c create mode 100644 SecurityTests/regressions/test/testcpp.h create mode 100644 SecurityTests/regressions/test/testcssm.c create mode 100644 SecurityTests/regressions/test/testcssm.h create mode 100644 SecurityTests/regressions/test/testenv.c create mode 100644 SecurityTests/regressions/test/testenv.h create mode 100644 SecurityTests/regressions/test/testeventqueue.c create mode 100644 SecurityTests/regressions/test/testeventqueue.h create mode 100644 SecurityTests/regressions/test/testleaks.c create mode 100644 SecurityTests/regressions/test/testleaks.h create mode 100644 SecurityTests/regressions/test/testmore.c create mode 100644 SecurityTests/regressions/test/testmore.h create mode 100644 SecurityTests/regressions/test/testsecevent.c create mode 100644 SecurityTests/regressions/test/testsecevent.h create mode 100755 SecurityTests/regressions/ut/ut-00-errors.cpp create mode 100755 SecurityTests/regressions/ut/ut-01-devrandom.cpp create mode 100644 SecurityTests/shoebox-certs/Apple TEST RootCertificate.crt create mode 100644 SecurityTests/shoebox-certs/Apple Worldwide Developer Relations Certification Authority Cert.crt create mode 100644 SecurityTests/shoebox-certs/Apple Worldwide Developer Relations Certification Authority TEST Cert.crt create mode 100644 SecurityTests/shoebox-certs/AppleRootCertificate.crt create mode 100644 SecurityTests/shoebox-certs/Invalid.com.apple.testcard.crt create mode 100644 SecurityTests/test-certs/CACert.ecc.pem create mode 100644 SecurityTests/test-certs/CACert.rsa.pem create mode 100644 SecurityTests/test-certs/CAKey.ecc.pem create mode 100644 SecurityTests/test-certs/CAKey.rsa.pem create mode 100644 SecurityTests/test-certs/ClientCert.ecc.ecc.pem create mode 100644 SecurityTests/test-certs/ClientCert.ecc.rsa.pem create mode 100644 SecurityTests/test-certs/ClientCert.rsa.ecc.pem create mode 100644 SecurityTests/test-certs/ClientCert.rsa.rsa.pem create mode 100644 SecurityTests/test-certs/ClientKey.ecc.pem create mode 100644 SecurityTests/test-certs/ClientKey.rsa.pem create mode 100644 SecurityTests/test-certs/ClientReq.ecc.pem create mode 100644 SecurityTests/test-certs/ClientReq.rsa.pem create mode 100644 SecurityTests/test-certs/SECG_ecc-secp256r1-client.pem create mode 100644 SecurityTests/test-certs/SECG_ecc_rsa-secp256r1-client.pem create mode 100644 SecurityTests/test-certs/ServerCert.ecc.ecc.pem create mode 100644 SecurityTests/test-certs/ServerCert.ecc.rsa.pem create mode 100644 SecurityTests/test-certs/ServerCert.rsa.ecc.pem create mode 100644 SecurityTests/test-certs/ServerCert.rsa.rsa.pem create mode 100644 SecurityTests/test-certs/ServerKey.ecc.pem create mode 100644 SecurityTests/test-certs/ServerKey.rsa.pem create mode 100644 SecurityTests/test-certs/ServerReq.ecc.pem create mode 100644 SecurityTests/test-certs/ServerReq.rsa.pem create mode 100644 SecurityTests/test-certs/ecparam.pem create mode 100644 SecurityTests/testKeychainAPI/English.lproj/InfoPlist.strings create mode 100755 SecurityTests/testKeychainAPI/run.sh create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI.cwp/testKeychainAPI/testKeychainAPI create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI.pbproj/project.pbxproj create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_CString.cpp create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_CString.h create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Cert.cpp create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Cert.h create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Item.cpp create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Item.h create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Keychain.cpp create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Keychain.h create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Manager.cpp create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Manager.h create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Password.cpp create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Password.h create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/KCOperation.cpp create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/KCOperation.h create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/KCOperationID.cpp create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/KCOperationID.h create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/KCParamUtility.cpp create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/KCParamUtility.h create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/Radar.cpp create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/Radar.h create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/cleanup create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/error_scripts create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/error_sub_cases_scripts create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0000 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0001 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0001.001 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0002 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0002.000 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0003 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0003.000 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0004 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0004.000 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0005 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0005.000 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0006 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0006.000 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0007 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0007.000 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0008 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0008.000 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0009 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0010 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0010.000 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0011 create mode 100755 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0011.001 create mode 100755 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0011.002 create mode 100755 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0011.003 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0012 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0012.000 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0012.001 create mode 100755 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0013 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0013.000 create mode 100755 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0014 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0014.000 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0015 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0015.000 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0016 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0016.000 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0017 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0018 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0019 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0020 create mode 100755 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0021 create mode 100755 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0022 create mode 100755 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0023 create mode 100755 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0024 create mode 100755 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0025 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0026 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0026.000 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0026.001 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0026.002 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0027 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0027.000 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0027.001 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0027.002 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0028 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0028.000 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0028.001 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0028.002 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0029 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0029.000 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0030 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0030.000 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0031 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0031.000 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0032 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0033 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0034 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0035 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0036 create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/testKeychainAPI.cpp create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI/testKeychainAPI.h create mode 100644 SecurityTests/testKeychainAPI/testKeychainAPI_user_manual.cwk create mode 100644 SecurityTests/testclient/attributes.cpp create mode 100644 SecurityTests/testclient/attributes.h create mode 100644 SecurityTests/testclient/csptests.cpp create mode 100644 SecurityTests/testclient/csptests.h create mode 100644 SecurityTests/testclient/dltests.cpp create mode 100644 SecurityTests/testclient/dltests.h create mode 100644 SecurityTests/testclient/testclient.cpp create mode 100644 SecurityTests/testclient/testclient.pbproj/project.pbxproj create mode 100644 SecurityTests/testlist.h create mode 100644 SecurityTests/testmain.c create mode 100644 SecurityTests/xdr_rpc/Makefile.xdr_test create mode 100644 SecurityTests/xdr_rpc/Reference/AclOwnerPrototype_getOwner.decoded create mode 100644 SecurityTests/xdr_rpc/Reference/transition.cpp create mode 100644 SecurityTests/xdr_rpc/TestData/AclEntryInfo_getAcl create mode 100644 SecurityTests/xdr_rpc/TestData/AclEntryInput_changeAcl create mode 100644 SecurityTests/xdr_rpc/TestData/AclOwnerPrototype_getOwner create mode 100644 SecurityTests/xdr_rpc/TestData/Context_decrypt create mode 100644 SecurityTests/xdr_rpc/TestData/Query_findFirst create mode 100644 SecurityTests/xdr_rpc/securityd_data_saver.cpp create mode 100644 SecurityTests/xdr_rpc/securityd_data_saver.h create mode 100644 SecurityTests/xdr_rpc/xdr_test.cpp create mode 100644 SecurityTool/APPLE_LICENSE create mode 100644 SecurityTool/SecurityTool.xcodeproj/project.pbxproj create mode 100644 SecurityTool/access_utils.c create mode 100644 SecurityTool/access_utils.h create mode 100644 SecurityTool/authz.c create mode 100644 SecurityTool/authz.h create mode 100644 SecurityTool/cmsutil.c create mode 100644 SecurityTool/cmsutil.h create mode 100644 SecurityTool/config/debug.xcconfig create mode 100644 SecurityTool/config/project.xcconfig create mode 100644 SecurityTool/config/release.xcconfig create mode 100644 SecurityTool/createFVMaster.c create mode 100644 SecurityTool/createFVMaster.h create mode 100644 SecurityTool/db_commands.cpp create mode 100644 SecurityTool/db_commands.h create mode 100644 SecurityTool/display_error_code.c create mode 100644 SecurityTool/display_error_code.h create mode 100644 SecurityTool/entitlements.plist create mode 100644 SecurityTool/identity_find.c create mode 100644 SecurityTool/identity_find.h create mode 100644 SecurityTool/identity_prefs.c create mode 100644 SecurityTool/identity_prefs.h create mode 100644 SecurityTool/key_create.c create mode 100644 SecurityTool/key_create.h create mode 100644 SecurityTool/keychain_add.c create mode 100644 SecurityTool/keychain_add.h create mode 100644 SecurityTool/keychain_create.c create mode 100644 SecurityTool/keychain_create.h create mode 100644 SecurityTool/keychain_delete.c create mode 100644 SecurityTool/keychain_delete.h create mode 100644 SecurityTool/keychain_export.c create mode 100644 SecurityTool/keychain_export.h create mode 100644 SecurityTool/keychain_find.c create mode 100644 SecurityTool/keychain_find.h create mode 100644 SecurityTool/keychain_import.c create mode 100644 SecurityTool/keychain_import.h create mode 100644 SecurityTool/keychain_list.c create mode 100644 SecurityTool/keychain_list.h create mode 100644 SecurityTool/keychain_lock.c create mode 100644 SecurityTool/keychain_lock.h create mode 100644 SecurityTool/keychain_recode.c create mode 100644 SecurityTool/keychain_recode.h create mode 100644 SecurityTool/keychain_set_settings.c create mode 100644 SecurityTool/keychain_set_settings.h create mode 100644 SecurityTool/keychain_show_info.c create mode 100644 SecurityTool/keychain_show_info.h create mode 100644 SecurityTool/keychain_unlock.c create mode 100644 SecurityTool/keychain_unlock.h create mode 100644 SecurityTool/keychain_utilities.c create mode 100644 SecurityTool/keychain_utilities.h create mode 100644 SecurityTool/leaks.c create mode 100644 SecurityTool/leaks.h create mode 100644 SecurityTool/mds_install.cpp create mode 100644 SecurityTool/mds_install.h create mode 100644 SecurityTool/readline.c create mode 100644 SecurityTool/readline.h create mode 100644 SecurityTool/security.1 create mode 100644 SecurityTool/security.c create mode 100644 SecurityTool/security.h create mode 100644 SecurityTool/security_tool_commands.c create mode 100644 SecurityTool/srCdsaUtils.cpp create mode 100644 SecurityTool/srCdsaUtils.h create mode 100644 SecurityTool/sub_commands.h create mode 100644 SecurityTool/trust_settings_impexp.c create mode 100644 SecurityTool/trust_settings_impexp.h create mode 100644 SecurityTool/trusted_cert_add.c create mode 100644 SecurityTool/trusted_cert_add.h create mode 100644 SecurityTool/trusted_cert_dump.c create mode 100644 SecurityTool/trusted_cert_dump.h create mode 100644 SecurityTool/trusted_cert_utils.c create mode 100644 SecurityTool/trusted_cert_utils.h create mode 100644 SecurityTool/user_trust_enable.cpp create mode 100644 SecurityTool/user_trust_enable.h create mode 100644 SecurityTool/verify_cert.c create mode 100644 SecurityTool/verify_cert.h create mode 100755 SharedWebCredentialViewService/Base.lproj/Main_iPad.storyboard create mode 100755 SharedWebCredentialViewService/Base.lproj/Main_iPhone.storyboard create mode 100755 SharedWebCredentialViewService/RemoteCFUserNotificationTest-Info.plist create mode 100755 SharedWebCredentialViewService/RemoteCFUserNotificationTest-Prefix.pch create mode 100755 SharedWebCredentialViewService/SWCAppDelegate.h create mode 100755 SharedWebCredentialViewService/SWCAppDelegate.m create mode 100755 SharedWebCredentialViewService/SWCViewController.h create mode 100755 SharedWebCredentialViewService/SWCViewController.m create mode 100644 SharedWebCredentialViewService/SharedWebCredentialViewService-Info.plist create mode 100644 SharedWebCredentialViewService/SharedWebCredentialViewService-Prefix.pch create mode 100755 SharedWebCredentialViewService/en.lproj/InfoPlist.strings create mode 100755 SharedWebCredentialViewService/entitlements.plist create mode 100755 SharedWebCredentialViewService/main.m create mode 100644 SyncTest/KCATableViewController.xib create mode 100644 SyncTest/spiralsink114.png create mode 100644 SyncTest/spiralsink57.png create mode 100644 TODO create mode 100644 WHITEPAPER delete mode 100644 authd/Info.plist delete mode 100644 authd/ccaudit.h delete mode 100644 authd/connection.h delete mode 100644 authd/credential.h delete mode 100644 authd/debugging.c delete mode 100644 authd/debugging.h delete mode 100644 authd/main.c delete mode 100644 authd/object.c delete mode 100644 authd/process.h delete mode 100644 authd/server.c delete mode 100644 authd/server.h delete mode 100644 authd/session.h create mode 100644 certificates/CertificateTool/Asset/SecurityCertificatesAssets/AssetData/PKITrustData/AppleESCertificates.plist create mode 100644 certificates/CertificateTool/Asset/SecurityCertificatesAssets/AssetData/PKITrustData/AssetVersion.plist create mode 100644 certificates/CertificateTool/Asset/SecurityCertificatesAssets/AssetData/PKITrustData/Blocked.plist create mode 100644 certificates/CertificateTool/Asset/SecurityCertificatesAssets/AssetData/PKITrustData/EVRoots.plist create mode 100644 certificates/CertificateTool/Asset/SecurityCertificatesAssets/AssetData/PKITrustData/GrayListedKeys.plist create mode 100644 certificates/CertificateTool/Asset/SecurityCertificatesAssets/AssetData/PKITrustData/certsIndex.data create mode 100644 certificates/CertificateTool/Asset/SecurityCertificatesAssets/AssetData/PKITrustData/certsTable.data create mode 100644 certificates/CertificateTool/Asset/SecurityCertificatesAssets/AssetData/PKITrustData/manifest.data create mode 100644 certificates/CertificateTool/Asset/SecurityCertificatesAssets/Info.plist create mode 100644 certificates/CertificateTool/BuildOSXRootKeychain/X509Anchors create mode 100644 certificates/CertificateTool/BuildOSXRootKeychain/buildRootKeychain.rb create mode 100644 certificates/CertificateTool/BuildOSXRootKeychain/certsha1hashtmp create mode 100755 certificates/CertificateTool/BuildOSXRootKeychain/evroot.config create mode 100644 certificates/CertificateTool/BuildiOSAsset/BuildAsset.rb create mode 100644 certificates/CertificateTool/BuildiOSAsset/BuildPListFiles.rb create mode 100644 certificates/CertificateTool/CertificateTool.xcodeproj/project.pbxproj create mode 100644 certificates/CertificateTool/CertificateTool.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 120000 certificates/CertificateTool/CertificateTool/AppleBaselineEscrowCertificates.h create mode 100644 certificates/CertificateTool/CertificateTool/AssetVersion.plist create mode 100644 certificates/CertificateTool/CertificateTool/CertificateTool-Prefix.pch create mode 100644 certificates/CertificateTool/CertificateTool/CertificateToolApp.h create mode 100644 certificates/CertificateTool/CertificateTool/CertificateToolApp.m create mode 100644 certificates/CertificateTool/CertificateTool/DataConversion.h create mode 100644 certificates/CertificateTool/CertificateTool/DataConversion.m create mode 100644 certificates/CertificateTool/CertificateTool/Info.plist create mode 100644 certificates/CertificateTool/CertificateTool/PSAssetConstants.c create mode 100644 certificates/CertificateTool/CertificateTool/PSAssetConstants.h create mode 100644 certificates/CertificateTool/CertificateTool/PSCert.h create mode 100644 certificates/CertificateTool/CertificateTool/PSCert.m create mode 100644 certificates/CertificateTool/CertificateTool/PSCertData.h create mode 100644 certificates/CertificateTool/CertificateTool/PSCertData.m create mode 100644 certificates/CertificateTool/CertificateTool/PSCertKey.h create mode 100644 certificates/CertificateTool/CertificateTool/PSCertKey.m create mode 100644 certificates/CertificateTool/CertificateTool/PSCertRecord.h create mode 100644 certificates/CertificateTool/CertificateTool/PSCertRecord.m create mode 100644 certificates/CertificateTool/CertificateTool/PSCerts.h create mode 100644 certificates/CertificateTool/CertificateTool/PSCerts.m create mode 100644 certificates/CertificateTool/CertificateTool/PSUtilities.h create mode 100644 certificates/CertificateTool/CertificateTool/PSUtilities.m create mode 100644 certificates/CertificateTool/CertificateTool/ValidateAsset.c create mode 100644 certificates/CertificateTool/CertificateTool/ValidateAsset.h create mode 100644 certificates/CertificateTool/CertificateTool/main.m create mode 100755 certificates/EVRoots/evroot.config create mode 100644 certificates/assetData/Info.plist create mode 100644 certificates/certs/AppleDEVID.cer create mode 100644 certificates/certs/DODCA_13.cer create mode 100644 certificates/certs/DODCA_14.cer create mode 100644 certificates/certs/DODCA_15.cer create mode 100644 certificates/certs/DODCA_16.cer create mode 100644 certificates/certs/DODCA_17.cer create mode 100644 certificates/certs/DODCA_18.cer create mode 100644 certificates/certs/DODCA_19.cer create mode 100644 certificates/certs/DODCA_20.cer create mode 100644 certificates/certs/DODCA_25.der create mode 100644 certificates/certs/DODCA_26.der create mode 100644 certificates/certs/DODCA_27.cer create mode 100644 certificates/certs/DODCA_28.cer create mode 100644 certificates/certs/DODCA_29.cer create mode 100644 certificates/certs/DODCA_30.cer create mode 100644 certificates/certs/DODEMAILCA_13.cer create mode 100644 certificates/certs/DODEMAILCA_14.cer create mode 100644 certificates/certs/DODEMAILCA_15.cer create mode 100644 certificates/certs/DODEMAILCA_16.cer create mode 100644 certificates/certs/DODEMAILCA_17.cer create mode 100644 certificates/certs/DODEMAILCA_18.cer create mode 100644 certificates/certs/DODEMAILCA_19.cer create mode 100644 certificates/certs/DODEMAILCA_20.cer create mode 100644 certificates/certs/DODEMAILCA_21.cer create mode 100644 certificates/certs/DODEMAILCA_22.cer create mode 100644 certificates/certs/DODEMAILCA_23.cer create mode 100644 certificates/certs/DODEMAILCA_24.cer create mode 100644 certificates/certs/DODEMAILCA_25.der create mode 100644 certificates/certs/DODEMAILCA_26.der create mode 100644 certificates/certs/DODEMAILCA_27.cer create mode 100644 certificates/certs/DODEMAILCA_28.cer create mode 100644 certificates/certs/DODEMAILCA_29.cer create mode 100644 certificates/certs/DODEMAILCA_30.cer create mode 100644 certificates/certs/DODINTERMEDIATECA-2.cer create mode 100644 certificates/certs/DODINTERMEDIATECA_1.cer create mode 100644 certificates/certs/DOD_CA-11.cer create mode 100644 certificates/certs/DOD_CA-12.cer create mode 100644 certificates/certs/DOD_CLASS_3_CA-10.cer create mode 100644 certificates/certs/DOD_CLASS_3_CA-5.cer create mode 100644 certificates/certs/DOD_CLASS_3_CA-6.cer create mode 100644 certificates/certs/DOD_CLASS_3_CA-7.cer create mode 100644 certificates/certs/DOD_CLASS_3_CA-8.cer create mode 100644 certificates/certs/DOD_CLASS_3_CA-9.cer create mode 100644 certificates/certs/DOD_CLASS_3_EMAIL_CA-10.cer create mode 100644 certificates/certs/DOD_CLASS_3_EMAIL_CA-5.cer create mode 100644 certificates/certs/DOD_CLASS_3_EMAIL_CA-6.cer create mode 100644 certificates/certs/DOD_CLASS_3_EMAIL_CA-7.cer create mode 100644 certificates/certs/DOD_CLASS_3_EMAIL_CA-8.cer create mode 100644 certificates/certs/DOD_CLASS_3_EMAIL_CA-9.cer create mode 100644 certificates/certs/DOD_EMAIL_CA-11.cer create mode 100644 certificates/certs/DOD_EMAIL_CA-12.cer create mode 100644 certificates/certs/DoDCA21.cer create mode 100644 certificates/certs/DoDCA22.cer create mode 100644 certificates/certs/DoDCA23.cer create mode 100644 certificates/certs/DoDCA24.cer create mode 100644 certificates/certs/GeoTrust_True_Credentials_CA_2.cer create mode 100644 certificates/certs/IDENTRUSTECA1.cer create mode 100644 certificates/certs/IDENTRUSTECA2.cer create mode 100644 certificates/certs/IDENTRUSTECA3.cer create mode 100644 certificates/certs/ORCECA2.cer create mode 100644 certificates/certs/ORCECAFOREIGNNATIONALSCA1.cer create mode 100644 certificates/certs/ORCECAHW3.cer create mode 100644 certificates/certs/ORCECAHW4.cer create mode 100644 certificates/certs/ORCECASW3.cer create mode 100644 certificates/certs/ORCECASW4.cer create mode 100644 certificates/certs/ORC_ECA.cer create mode 100755 certificates/certs/Thawte_Code_Signing_CA.cer create mode 100644 certificates/certs/Thawte_SGC_CA.der.cer create mode 100644 certificates/certs/Thawte_SSL_Domain_CA_der.cer create mode 100644 certificates/certs/VERISIGNCLIENTECA-G2.cer create mode 100644 certificates/certs/VERISIGNCLIENTEXTERNALCERTIFICATIONAUTHORITY_G3.cer create mode 100644 certificates/certs/VeriSignClientExternalCertificationAuthority.cer create mode 100755 certificates/certs/VeriSign_TSA_CA.crt create mode 100644 certificates/certs/VisaNet.crt create mode 100644 certificates/certs/acClasse0_0.cer create mode 100644 certificates/certs/acClasse0_1.cer create mode 100644 certificates/certs/acClasse1_0.cer create mode 100644 certificates/certs/acClasse1_1.cer create mode 100644 certificates/certs/acClasse2_0.cer create mode 100644 certificates/certs/acClasse2_1.cer create mode 100644 certificates/certs/acClasse3_0.cer create mode 100644 certificates/certs/acClasse3_1.cer create mode 100644 certificates/certs/acClasse4.cer create mode 100644 certificates/certs/acClasse5.cer create mode 100644 certificates/certs/acCps2_2.cer create mode 100644 certificates/certs/belgiumrs.crt create mode 100644 certificates/certs/e-Visa.crt create mode 100644 certificates/certs/gipCps0.cer create mode 100644 certificates/distrusted/DigiNotar Extended Validation CA.cer create mode 100644 certificates/distrusted/DigiNotar PKIoverheid CA Organisatie - G2.cer create mode 100644 certificates/distrusted/DigiNotar Qualified CA.cer create mode 100644 certificates/distrusted/DigiNotar Services 1024 CA.cer create mode 100644 certificates/distrusted/DigiNotar Services CA.cer create mode 100644 certificates/distrusted/DigiNotarRootCA2007.crt create mode 100644 certificates/distrusted/DigiNotarRootCAG2.cer create mode 100644 certificates/distrusted/DigiNotar_PKIoverheid_CA.cer create mode 100644 certificates/distrusted/EASEE-gas CA.cer create mode 100644 certificates/distrusted/Nederlandse Orde van Advocaten - Dutch Bar Association.cer create mode 100644 certificates/distrusted/TRIALOrgCA.cer create mode 100644 certificates/distrusted/TRIAL_DigiNotar_PKIoverheid_Organisatie_TEST_CA_G2.cer create mode 100644 certificates/distrusted/TU Delft CA.cer create mode 100644 certificates/ota_cert_tool/BuildAsset/BuildAsset-Prefix.pch create mode 100644 certificates/ota_cert_tool/BuildAsset/BuildAsset.1 create mode 100644 certificates/ota_cert_tool/BuildAsset/main.m create mode 100644 certificates/ota_cert_tool/Scripts/BuildAsset.rb create mode 100644 certificates/ota_cert_tool/Scripts/BuildPlistFiles.rb create mode 100644 certificates/ota_cert_tool/Scripts/File.rb create mode 100644 certificates/ota_cert_tool/SecuritydAssertHelper/Readme.txt create mode 100644 certificates/ota_cert_tool/SecuritydAssertHelper/SecuritydAssertHelper.1 create mode 100644 certificates/ota_cert_tool/SecuritydAssertHelper/SecuritydAssertHelper.m create mode 100644 certificates/ota_cert_tool/TestValidator/Readme.txt create mode 100644 certificates/ota_cert_tool/TestValidator/Resources/EVRoots.plist create mode 100644 certificates/ota_cert_tool/TestValidator/Resources/Manifest.plist create mode 100644 certificates/ota_cert_tool/TestValidator/Resources/certs.plist create mode 100644 certificates/ota_cert_tool/TestValidator/Resources/distrusted.plist create mode 100644 certificates/ota_cert_tool/TestValidator/Resources/revoked.plist create mode 100644 certificates/ota_cert_tool/TestValidator/Resources/roots.plist create mode 100644 certificates/ota_cert_tool/TestValidator/TestValidator.1 create mode 100644 certificates/ota_cert_tool/TestValidator/TestValidator.m create mode 100644 certificates/ota_cert_tool/assertValidation/assertValidation-Prefix.pch create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool.xcodeproj/project.pbxproj create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/CommonBaseXX.c create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/CommonBaseXX.h create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/CommonBuffering.c create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/CommonBufferingPriv.h create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/Info.plist create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/PSCert.h create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/PSCert.m create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/PSCertKey.h create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/PSCertKey.m create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/PSCerts.h create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/PSCerts.m create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/PSIOSCertToolApp.h create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/PSIOSCertToolApp.m create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/PSUtilities.h create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/PSUtilities.m create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/ValidateAsset.c create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/ValidateAsset.h create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/ccMemory.h create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/ios_ota_cert_tool-Prefix.pch create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/ios_ota_cert_tool.1 create mode 100644 certificates/ota_cert_tool/ios_ota_cert_tool/main.m create mode 100644 certificates/removed/AOLTimeWarner1.der create mode 100644 certificates/removed/AOLTimeWarner2.der create mode 100644 certificates/removed/EntrustRootCA1024.crt create mode 100644 certificates/removed/Equifax_Secure_eBusiness_CA-2.cer create mode 100644 certificates/removed/JCSSecureSignRootCA11.cer create mode 100644 certificates/removed/ValiCertClass1PVA.cer create mode 100644 certificates/removed/ValiCertClass2PVA.cer create mode 100644 certificates/removed/ValiCertClass3PVA.cer create mode 100644 certificates/removed/persbasi.crt create mode 100644 certificates/removed/persprem.crt create mode 100644 certificates/revoked/*.EGO.GOV.TR.cer create mode 100644 certificates/revoked/*.google.com.cer create mode 100644 certificates/revoked/*.mail.me.com.cer create mode 100644 certificates/revoked/DigiNotar Public CA 2025.cer create mode 100644 certificates/revoked/DigiNotar092006.cer create mode 100644 certificates/revoked/DigiNotar092706.cer create mode 100644 certificates/revoked/DigiNotar100406.cer create mode 100644 certificates/revoked/DigiNotarRootCA1.cer create mode 100644 certificates/revoked/DigiNotarRootCA2.cer create mode 100644 certificates/revoked/DigiNotarServices1024CA.cer create mode 100644 certificates/revoked/Digisign-Server-ID-Enrich-Entrust-Cert.cer create mode 100644 certificates/revoked/Digisign-Server-ID-Enrich-GTETrust-Cert.cer create mode 100644 certificates/revoked/Micros CA 2.cer create mode 100644 certificates/revoked/Trustwave Organization Issuing CA, Level 2 2.cer create mode 100644 certificates/revoked/e-islem.kktcmerkezbankasi.org.cer create mode 100644 certificates/roots/00_BCA.cer create mode 100644 certificates/roots/2048CA.cer create mode 100644 certificates/roots/A-Trust-Qual-01.cer create mode 100644 certificates/roots/A-Trust-Qual-02a.crt create mode 100644 certificates/roots/A-Trust-nQual-01.cer create mode 100644 certificates/roots/A-Trust-nQual-03.cer create mode 100644 certificates/roots/APCAroot.der create mode 100644 certificates/roots/Actalis Authentication Root CA.cer create mode 100644 certificates/roots/AddTrust Class 1 CA Root.crt create mode 100644 certificates/roots/AddTrust External CA Root.crt create mode 100644 certificates/roots/AddTrust Public CA Root.crt create mode 100644 certificates/roots/AddTrust Qualified CA Root.crt create mode 100644 certificates/roots/AffirmTrust-Commercial.der create mode 100644 certificates/roots/AffirmTrust-Networking.der create mode 100644 certificates/roots/AffirmTrust-Premium-ECC.der create mode 100644 certificates/roots/AffirmTrust-Premium.der create mode 100644 certificates/roots/AmericaOnline1.der create mode 100644 certificates/roots/AmericaOnline2.der create mode 100644 certificates/roots/AppCAG2.cer create mode 100644 certificates/roots/Apple Root CA - G2.cer create mode 100644 certificates/roots/Apple Root CA - G3.cer create mode 100644 certificates/roots/AppleDEVID.cer create mode 100644 certificates/roots/AppleIncRoot042506.cer create mode 100644 certificates/roots/AppleROOTCA.der create mode 100644 certificates/roots/Autoridad de Certificacion Raiz del Estado Venezolano.cer create mode 100644 certificates/roots/BIT-Admin-Root-CA.crt create mode 100644 certificates/roots/BIT-AdminCA-CD-T01.crt create mode 100644 certificates/roots/BTCTRT.cer create mode 100644 certificates/roots/Buypass Class 2 Root CA.cer create mode 100644 certificates/roots/Buypass Class 3 Root CA.cer create mode 100755 certificates/roots/BuypassClass2CA1.cer create mode 100755 certificates/roots/BuypassClass3CA1.cer create mode 100644 certificates/roots/C1_PCA_G3v2.509 create mode 100644 certificates/roots/C2_PCA_G3v2.509 create mode 100644 certificates/roots/C3_PCA_G3v2.509 create mode 100644 certificates/roots/C4_PCA_G3v2.509 create mode 100644 certificates/roots/CA Disig Root R1.cer create mode 100644 certificates/roots/CA Disig Root R2.cer create mode 100644 certificates/roots/CNNICEVRoot.der create mode 100644 certificates/roots/COMODOCertificationAuthority.crt create mode 100644 certificates/roots/Certigna.cer create mode 100644 certificates/roots/Certinomis - Root CA.cer create mode 100644 certificates/roots/Certinomis-May2013.der create mode 100644 certificates/roots/Certum Trusted Network CA 2.cer create mode 100644 certificates/roots/Chunghwa-ROOTeCA.der create mode 100644 certificates/roots/Class1_PCA_G2_v2.509 create mode 100644 certificates/roots/Class2_PCA_G2_v2.509 create mode 100644 certificates/roots/Class3_PCA_G2_v2.509 create mode 100644 certificates/roots/Class4_PCA_G2_v2.509 create mode 100644 certificates/roots/ComSign-CA.der create mode 100644 certificates/roots/ComSign-Global.der create mode 100644 certificates/roots/ComSign-Secured.der create mode 100644 certificates/roots/Comodo_AAA_Certificate_Services.cer create mode 100644 certificates/roots/Comodo_Secure_Certificate_Services.cer create mode 100644 certificates/roots/Comodo_Trusted_Certificate_Services.cer create mode 100644 certificates/roots/D-TRUST_Root_Class_3_CA_2_2009.cer create mode 100644 certificates/roots/D-TRUST_Root_Class_3_CA_2_EV_2009.cer create mode 100644 certificates/roots/DST Root CA X4.cer create mode 100644 certificates/roots/Deutsche_Telekom_Root_CA_2.der create mode 100644 certificates/roots/DigiCertAssuredIDRootCA.crt create mode 100644 certificates/roots/DigiCertAssuredIDRootG2.der create mode 100644 certificates/roots/DigiCertAssuredIDRootG3.der create mode 100644 certificates/roots/DigiCertGlobalRootCA.crt create mode 100644 certificates/roots/DigiCertGlobalRootG2.der create mode 100644 certificates/roots/DigiCertGlobalRootG3.der create mode 100644 certificates/roots/DigiCertHighAssuranceEVRootCA.crt create mode 100644 certificates/roots/DigiCertTrustedRootG4.der create mode 100644 certificates/roots/DoDCLASS3RootCA.cer create mode 100644 certificates/roots/DoDRootCA2.der create mode 100644 certificates/roots/E-Tugra.der create mode 100644 certificates/roots/EBG_KOKSM.cer create mode 100644 certificates/roots/ECARootCA.der create mode 100644 certificates/roots/EchoworxRootCA2.cer create mode 100644 certificates/roots/EntrustEVRoot.crt create mode 100644 certificates/roots/EntrustRoot-EC1.der create mode 100644 certificates/roots/EntrustRoot-G2.der create mode 100644 certificates/roots/Equifax_Secure_Certificate_Auth create mode 100644 certificates/roots/Equifax_Secure_Global_eBusiness create mode 100644 certificates/roots/Equifax_Secure_eBusiness_CA-1.cer create mode 100644 certificates/roots/Estonia-Juur-SK.cer create mode 100755 certificates/roots/FBCA-commonpolicy2.cer create mode 100644 certificates/roots/FederalCommonPolicyCA.cer create mode 100644 certificates/roots/Firmaprofesional-CIF-A62634068.der create mode 100644 certificates/roots/GD-Class2-root.crt create mode 100644 certificates/roots/GTEGB18.cer create mode 100644 certificates/roots/GeoTrust Primary Certification Authority - G2.cer create mode 100644 certificates/roots/GeoTrust Primary Certification Authority - G3.cer create mode 100644 certificates/roots/GeoTrust_Global_CA.cer create mode 100644 certificates/roots/GlobalSign-Root-R3.der create mode 100644 certificates/roots/GlobalSign-RootCA-2028exp.cer create mode 100644 certificates/roots/GlobalSignRoot-R4.cer create mode 100644 certificates/roots/GlobalSignRoot-R5.cer create mode 100644 certificates/roots/GlobalSignRootCA-R2.cer create mode 100644 certificates/roots/GoDaddyRootCertificateAuthorityG2.der create mode 100644 certificates/roots/HKPost-smartid_rt.cacert.crt create mode 100644 certificates/roots/HaricaRootCA2011.der create mode 100644 certificates/roots/ICA-20090901.der create mode 100644 certificates/roots/IdenTrust_Root_X3.der create mode 100644 certificates/roots/IdenTrust_Root_X6.der create mode 100644 certificates/roots/Izenpe-RAIZ2007.crt create mode 100644 certificates/roots/Izenpe-ca_raiz2003.crt create mode 100644 certificates/roots/Izenpe.com.cer create mode 100644 certificates/roots/JapanMinistryIAC-ApplicationCA2.der create mode 100644 certificates/roots/KIR-SZAFIR-Trusted.der create mode 100644 certificates/roots/KMD-CA-KPerson.crt create mode 100644 certificates/roots/KMD-CA-Server.crt create mode 100644 certificates/roots/MPHPT_CA.cer create mode 100644 certificates/roots/Microsec e-Szigno Root CA 2009.cer create mode 100644 certificates/roots/NetLockAranyClassGoldF.cer create mode 100644 certificates/roots/NetworkSolutionsEVRoot.crt create mode 100644 certificates/roots/PCA1ss_v4.509 create mode 100644 certificates/roots/PCA2ss_v4.509 create mode 100644 certificates/roots/PCA3ss_v4.509 create mode 100644 certificates/roots/Poland-Certum-CTNCA.der create mode 100644 certificates/roots/ROOT-CHAMBERS.crt create mode 100644 certificates/roots/ROOT-CHAMBERSIGN.crt create mode 100644 certificates/roots/RSA_Root_CA.der create mode 100644 certificates/roots/SCRoot1ca.cer create mode 100644 certificates/roots/SECOM-EVRoot1ca.cer create mode 100644 certificates/roots/SECOM-RootCA2.cer create mode 100644 certificates/roots/SF-Class2-root.crt create mode 100644 certificates/roots/SKEE_Certification_Centre_Root_CA.crt create mode 100644 certificates/roots/SoneraClass1.crt create mode 100644 certificates/roots/SoneraClass2.crt create mode 100644 certificates/roots/Staat der Nederlanden EV Root CA.cer create mode 100644 certificates/roots/StarfieldRootCertificateAuthorityG2.der create mode 100644 certificates/roots/StarfieldServicesRootCertificateAuthorityG2.der create mode 100644 certificates/roots/StartCom May 2013 G2.der create mode 100644 certificates/roots/SwissSign-Gold_G2.der create mode 100644 certificates/roots/SwissSign-Platinum_G2.der create mode 100644 certificates/roots/SwissSign-Silver_G2.der create mode 100644 certificates/roots/Swisscom Root CA 2.cer create mode 100644 certificates/roots/Swisscom Root EV CA 2.cer create mode 100644 certificates/roots/Symantec Class 1 Public Primary Certification Authority - G4.cer create mode 100644 certificates/roots/Symantec Class 1 Public Primary Certification Authority - G6.cer create mode 100644 certificates/roots/Symantec Class 2 Public Primary Certification Authority - G4.cer create mode 100644 certificates/roots/Symantec Class 2 Public Primary Certification Authority - G6.cer create mode 100644 certificates/roots/Symantec Class 3 Public Primary Certification Authority - G4.cer create mode 100644 certificates/roots/Symantec Class 3 Public Primary Certification Authority - G6.cer create mode 100644 certificates/roots/T-TeleSec GlobalRoot Class 2.cer create mode 100644 certificates/roots/T-TeleSec GlobalRoot Class 3.cer create mode 100644 certificates/roots/TDC_ocesca.cer create mode 100644 certificates/roots/TDC_rootca.cer create mode 100644 certificates/roots/TRUST2408 OCES Primary CA.cer create mode 100644 certificates/roots/TWCARootCA-4096.der create mode 100644 certificates/roots/Taiwan-GRCA2.der create mode 100644 certificates/roots/TeliaSoneraRootCAv1.der create mode 100755 certificates/roots/Thawte_Personal_Basic_CA.cer create mode 100755 certificates/roots/Thawte_Personal_Freemail_CA.cer create mode 100755 certificates/roots/Thawte_Personal_Premium_CA.cer create mode 100755 certificates/roots/Thawte_Premium_Server_CA.cer create mode 100755 certificates/roots/Thawte_Server_CA.cer create mode 100755 certificates/roots/Thawte_Timestamping_CA.cer create mode 100644 certificates/roots/TrustisFPSRootCA.der create mode 100644 certificates/roots/Trustwave-SGCA.der create mode 100644 certificates/roots/Trustwave-STCA.der create mode 100644 certificates/roots/TubitakSurum3.cer create mode 100644 certificates/roots/UCAGlobalRoot.cer create mode 100644 certificates/roots/UCARoot.cer create mode 100644 certificates/roots/UTN-USERFirst-ClientAuthentication.der create mode 100644 certificates/roots/UTN-USERFirst-Hardware.crt create mode 100644 certificates/roots/UTN-USERFirst-NetworkApplication.der create mode 100644 certificates/roots/UTN-USERFirst-Object.crt create mode 100644 certificates/roots/UTN_DATACorp_SGC.cer create mode 100644 certificates/roots/Unizeto-CertumCA.cer create mode 100644 certificates/roots/VASLatvijasPasts-SSI-RCA.crt create mode 100644 certificates/roots/VeriSign Class 3 Public Primary Certification Authority - G4.cer create mode 100644 certificates/roots/VeriSign Universal Root Certification Authority.cer create mode 100644 certificates/roots/VeriSignC3PublicPrimaryCA-G5.cer create mode 100644 certificates/roots/VerisignSHA1_1024_PCA1_G1.cer create mode 100644 certificates/roots/VerisignSHA1_1024_PCA2_G1.cer create mode 100644 certificates/roots/VerisignSHA1_1024_PCA3_G1.cer create mode 100644 certificates/roots/Visa Information Delivery Root CA.cer create mode 100644 certificates/roots/Visa eCommerce Root.cer create mode 100644 certificates/roots/WISeKey-owgrgaca.cer create mode 100644 certificates/roots/WellsSecurePRCA.der create mode 100644 certificates/roots/XGCA.crt create mode 100644 certificates/roots/ac-racine.der create mode 100644 certificates/roots/ac_offline_raiz_certicamara.crt create mode 100644 certificates/roots/belgiumrca.crt create mode 100644 certificates/roots/belgiumrca2.crt create mode 100644 certificates/roots/certSIGN ROOT CA.cer create mode 100644 certificates/roots/certplus_class2.der create mode 100644 certificates/roots/cisco-ca2048.der create mode 100755 certificates/roots/cnnicroot.cer create mode 100644 certificates/roots/disig-root-1.der create mode 100644 certificates/roots/entrust2048.der create mode 100644 certificates/roots/expressz.cer create mode 100644 certificates/roots/geotrust-primary-ca.crt create mode 100644 certificates/roots/globalSignRoot.cer create mode 100644 certificates/roots/kisa-root-rsa-3280.der create mode 100644 certificates/roots/kisa-root-wrsa.der create mode 100644 certificates/roots/kozjegyzoi.cer create mode 100644 certificates/roots/netlockQA-01-minositett.cer create mode 100644 certificates/roots/persfree.crt create mode 100644 certificates/roots/popFinnVrkrootc.der create mode 100644 certificates/roots/qvrca.crt create mode 100644 certificates/roots/qvrca2.crt create mode 100644 certificates/roots/qvrca3.crt create mode 100644 certificates/roots/root_chambers-2008.der create mode 100644 certificates/roots/root_chambersign-2008.der create mode 100644 certificates/roots/serverbasic.crt create mode 100644 certificates/roots/serverpremium.crt create mode 100644 certificates/roots/staatDerNederlandenRootCA-G2.crt create mode 100644 certificates/roots/staatdernederlandenrootca.cer create mode 100644 certificates/roots/startcom-sfsca.der create mode 100644 certificates/roots/startcomSHA2.der create mode 100644 certificates/roots/swisscom-sdcs-root.crt create mode 100644 certificates/roots/swisssign.der create mode 100644 certificates/roots/tc_Universal_CA-I.cer create mode 100644 certificates/roots/tc_Universal_CA-II.cer create mode 100644 certificates/roots/tc_class_2_ii.cer create mode 100644 certificates/roots/tc_class_3_ii.cer create mode 100644 certificates/roots/tc_class_4_ii.cer create mode 100644 certificates/roots/thawte Primary Root CA - G3.cer create mode 100644 certificates/roots/thawte-primary-root-ca.crt create mode 100755 certificates/roots/thawte_Primary_Root_CA_G2_ECC.cer create mode 100644 certificates/roots/trustCenter-root-5.der create mode 100644 certificates/roots/turktrust-root1.cer create mode 100644 certificates/roots/turktrust-root2.cer create mode 100644 certificates/roots/turktrust-root3.cer create mode 100644 certificates/roots/twca-root-1.der create mode 100644 certificates/roots/uzleti.cer create mode 100644 codesign_wrapper/MISBase.h create mode 100644 codesign_wrapper/MISEntitlement.c create mode 100644 codesign_wrapper/MISEntitlement.h create mode 100644 codesign_wrapper/Makefile create mode 100644 codesign_wrapper/check_entitlements.c create mode 100644 codesign_wrapper/codesign.c create mode 100644 codesign_wrapper/codesign.h create mode 100644 codesign_wrapper/codesign_wrapper.c create mode 100644 codesign_wrapper/codesign_wrapper.h delete mode 100644 config/base.xcconfig delete mode 100644 doc/C++Utilities.cwk create mode 100644 evroots.h create mode 100644 iCloudStat/com.apple.icloudKeychainStats.plist create mode 100644 iCloudStat/main.c delete mode 100644 iCloudStats/com.apple.iCloudStats.plist delete mode 100644 iCloudStats/iCloudStats.1 delete mode 100644 iCloudStats/main.c delete mode 120000 include/security_agent_client delete mode 100644 lib/generateErrStrings.pl delete mode 100644 libsecurity_apple_csp/lib/ascContext.h delete mode 100644 libsecurity_apple_csp/lib/ascFactory.h delete mode 100644 libsecurity_apple_csp/lib/boxes-ref.h delete mode 100644 libsecurity_apple_csp/lib/pbkdDigest.cpp delete mode 100644 libsecurity_apple_csp/lib/pbkdDigest.h delete mode 100644 libsecurity_apple_csp/lib/pbkdf2.c delete mode 100644 libsecurity_apple_csp/lib/pbkdf2.h delete mode 100644 libsecurity_apple_csp/lib/rijndael-alg-ref.c delete mode 100644 libsecurity_apple_csp/lib/rijndael-alg-ref.h delete mode 100644 libsecurity_apple_csp/lib/rijndaelApi.c delete mode 100644 libsecurity_apple_csp/lib/rijndaelApi.h delete mode 100644 libsecurity_apple_csp/libsecurity_apple_csp.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_apple_cspdl/libsecurity_apple_cspdl.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_apple_file_dl/libsecurity_apple_file_dl.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_apple_x509_cl/libsecurity_apple_x509_cl.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_apple_x509_tp/lib/cuEnc64.c delete mode 100644 libsecurity_apple_x509_tp/lib/cuEnc64.h delete mode 100644 libsecurity_apple_x509_tp/lib/ocspRequest.cpp delete mode 100644 libsecurity_apple_x509_tp/lib/ocspRequest.h delete mode 100644 libsecurity_apple_x509_tp/libsecurity_apple_x509_tp.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_asn1/config/base.xcconfig delete mode 100644 libsecurity_asn1/config/lib.xcconfig delete mode 100644 libsecurity_asn1/lib/SecNssCoder.cpp delete mode 100644 libsecurity_asn1/lib/SecNssCoder.h delete mode 100644 libsecurity_asn1/lib/oidsalg.c delete mode 100644 libsecurity_asn1/lib/oidsbase.h delete mode 100644 libsecurity_asn1/lib/pkcs12Templates.h delete mode 100644 libsecurity_asn1/lib/pkcs7Templates.h delete mode 100644 libsecurity_asn1/libsecurity_asn1.xcodeproj/project.pbxproj delete mode 100644 libsecurity_asn1/libsecurity_asn1.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_authorization/libsecurity_authorization.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_cdsa_client/libsecurity_cdsa_client.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_cdsa_utilities/libsecurity_cdsa_utilities.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_cdsa_utils/lib/cuEnc64.c delete mode 100644 libsecurity_cdsa_utils/lib/cuEnc64.h delete mode 100644 libsecurity_cdsa_utils/libsecurity_cdsa_utils.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_checkpw/libsecurity_checkpw.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_cms/libsecurity_cms.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_codesigning/CodeSigningHelper/main.c delete mode 100644 libsecurity_codesigning/lib/SecTask.c delete mode 100644 libsecurity_codesigning/lib/SecTask.h delete mode 100644 libsecurity_codesigning/lib/cfmdiskrep.cpp delete mode 100644 libsecurity_codesigning/lib/cfmdiskrep.h delete mode 100644 libsecurity_codesigning/lib/opaquewhitelist.cpp delete mode 100644 libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj delete mode 100644 libsecurity_codesigning/libsecurity_codesigning.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_comcryption/libsecurity_comcryption.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_cryptkit/ckutils/badsig/badsig.c delete mode 100644 libsecurity_cryptkit/lib/CryptKitSA.h delete mode 100644 libsecurity_cryptkit/lib/NSFEEPublicKeyPrivate.h delete mode 100644 libsecurity_cryptkit/lib/README delete mode 100644 libsecurity_cryptkit/libsecurity_cryptkit.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_cssm/lib/certextensions.h delete mode 100644 libsecurity_cssm/lib/cssmapple.h delete mode 100644 libsecurity_cssm/lib/oidsalg.c delete mode 100644 libsecurity_cssm/lib/oidsbase.h delete mode 100644 libsecurity_cssm/lib/transition.cpp delete mode 100644 libsecurity_cssm/libsecurity_cssm.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_filedb/libsecurity_filedb.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_keychain/lib/SecBase.h delete mode 100644 libsecurity_keychain/lib/SecBasePriv.h delete mode 100644 libsecurity_keychain/lib/SecCertificate.h delete mode 100644 libsecurity_keychain/lib/SecCertificatePriv.h delete mode 100644 libsecurity_keychain/lib/SecCertificateRequest.h delete mode 100644 libsecurity_keychain/lib/SecIdentity.h delete mode 100644 libsecurity_keychain/lib/SecIdentityPriv.h delete mode 100644 libsecurity_keychain/lib/SecImportExport.c delete mode 100644 libsecurity_keychain/lib/SecImportExport.h delete mode 100644 libsecurity_keychain/lib/SecInternal.h delete mode 100644 libsecurity_keychain/lib/SecItem.h delete mode 100644 libsecurity_keychain/lib/SecItemConstants.c delete mode 100644 libsecurity_keychain/lib/SecItemPriv.h delete mode 100644 libsecurity_keychain/lib/SecKey.h delete mode 100644 libsecurity_keychain/lib/SecKeyPriv.h delete mode 100644 libsecurity_keychain/lib/SecKeychainPriv.h delete mode 100644 libsecurity_keychain/lib/SecPolicy.cpp delete mode 100644 libsecurity_keychain/lib/SecPolicy.h delete mode 100644 libsecurity_keychain/lib/SecPolicyPriv.h delete mode 100644 libsecurity_keychain/lib/SecRandom.h delete mode 100644 libsecurity_keychain/lib/SecTrust.h delete mode 100644 libsecurity_keychain/lib/SecTrustPriv.h delete mode 100644 libsecurity_keychain/lib/SecTrustSettings.h delete mode 100644 libsecurity_keychain/lib/SecTrustSettingsPriv.h delete mode 100644 libsecurity_keychain/lib/Security.h delete mode 100644 libsecurity_keychain/lib/generateErrStrings.pl delete mode 100644 libsecurity_keychain/libDER/Tests/DER_Ticket.h delete mode 100644 libsecurity_keychain/libDER/config/base.xcconfig delete mode 100644 libsecurity_keychain/libDER/libDER.xcodeproj/project.pbxproj delete mode 100644 libsecurity_keychain/libDER/libDER.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_keychain/libDER/libDER/DER_Digest.h delete mode 100644 libsecurity_keychain/libDER/libDER/DER_Encode.h delete mode 100644 libsecurity_keychain/libDER/libDER/DER_Keys.h delete mode 100644 libsecurity_keychain/libDER/libDER/asn1Types.h delete mode 100644 libsecurity_keychain/libDER/libDER/libDER.h delete mode 100644 libsecurity_keychain/libDER/libDER/libDER_config.h delete mode 100644 libsecurity_keychain/libDER/libDER/oids.h delete mode 100644 libsecurity_keychain/libDER/libDERUtils/fileIo.c delete mode 100644 libsecurity_keychain/libDER/libDERUtils/fileIo.h delete mode 100644 libsecurity_keychain/libDER/libDERUtils/libDERUtils.c delete mode 100644 libsecurity_keychain/libDER/libDERUtils/libDERUtils.h delete mode 100644 libsecurity_keychain/libDER/libDERUtils/printFields.h delete mode 100644 libsecurity_keychain/libsecurity_keychain.xcodeproj/project.pbxproj delete mode 100644 libsecurity_keychain/libsecurity_keychain.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_keychain/regressions/si-33-keychain-backup.c delete mode 100644 libsecurity_keychain/xpc/main.c delete mode 100644 libsecurity_manifest/libsecurity_manifest.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_mds/lib/MDSSchema.cpp delete mode 100644 libsecurity_mds/lib/MDSSchema.h delete mode 100644 libsecurity_mds/libsecurity_mds.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_ocspd/common/ocspdTypes.h delete mode 100644 libsecurity_ocspd/common/ocspdUtils.h delete mode 100644 libsecurity_ocspd/libsecurity_ocspd.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_ocspd/mig/mig.mk delete mode 100644 libsecurity_pkcs12/lib/pkcs12Templates.h delete mode 100644 libsecurity_pkcs12/lib/pkcs12Utils.cpp delete mode 100644 libsecurity_pkcs12/lib/pkcs12Utils.h delete mode 100644 libsecurity_pkcs12/lib/pkcs7Templates.h delete mode 100644 libsecurity_pkcs12/libsecurity_pkcs12.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_sd_cspdl/libsecurity_sd_cspdl.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist create mode 120000 libsecurity_smime/Security create mode 100644 libsecurity_smime/lib/SecAsn1Item.c create mode 100644 libsecurity_smime/lib/SecAsn1Item.h create mode 100644 libsecurity_smime/lib/crypto-embedded.c delete mode 100644 libsecurity_smime/libsecurity_smime.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist create mode 120000 libsecurity_smime/security_smime delete mode 100644 libsecurity_ssl/config/base.xcconfig delete mode 100644 libsecurity_ssl/config/lib.xcconfig delete mode 100644 libsecurity_ssl/config/tests.xcconfig delete mode 100644 libsecurity_ssl/lib/ModuleAttacher.c delete mode 100644 libsecurity_ssl/lib/SSLRecordInternal.c delete mode 100644 libsecurity_ssl/lib/SSLRecordInternal.h delete mode 100644 libsecurity_ssl/lib/appleCdsa.c delete mode 100644 libsecurity_ssl/lib/ssl3Callouts.c delete mode 100644 libsecurity_ssl/lib/ssl3RecordCallouts.c delete mode 100644 libsecurity_ssl/lib/sslAlertMessage.c delete mode 100644 libsecurity_ssl/lib/sslCert.c delete mode 100644 libsecurity_ssl/lib/sslChangeCipher.c delete mode 100644 libsecurity_ssl/lib/sslCipherSpecs.c delete mode 100644 libsecurity_ssl/lib/sslContext.h delete mode 100644 libsecurity_ssl/lib/sslCrypto.c delete mode 100644 libsecurity_ssl/lib/sslCrypto.h delete mode 100644 libsecurity_ssl/lib/sslHandshake.c delete mode 100644 libsecurity_ssl/lib/sslHandshakeFinish.c delete mode 100644 libsecurity_ssl/lib/sslHandshakeHello.c delete mode 100644 libsecurity_ssl/lib/sslKeyExchange.c delete mode 100644 libsecurity_ssl/lib/sslKeychain.c delete mode 100644 libsecurity_ssl/lib/sslKeychain.h delete mode 100644 libsecurity_ssl/lib/sslRecord.c delete mode 100644 libsecurity_ssl/lib/sslTransport.c delete mode 100644 libsecurity_ssl/lib/tls1Callouts.c delete mode 100644 libsecurity_ssl/lib/tls1RecordCallouts.c delete mode 100644 libsecurity_ssl/lib/tls_record.h delete mode 100644 libsecurity_ssl/libsecurity_ssl.xcodeproj/project.pbxproj delete mode 100644 libsecurity_ssl/libsecurity_ssl.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_ssl/regressions/ssl-utils.c delete mode 100644 libsecurity_ssl/regressions/ssl-utils.h delete mode 100644 libsecurity_ssl/regressions/ssl_regressions.h delete mode 100644 libsecurity_ssl/sslViewer/fileIo.c delete mode 100644 libsecurity_ssl/sslViewer/fileIo.h delete mode 100644 libsecurity_ssl/sslViewer/ioSock.c delete mode 100644 libsecurity_ssl/sslViewer/ioSock.h delete mode 100644 libsecurity_ssl/sslViewer/sslAppUtils.cpp delete mode 100644 libsecurity_ssl/sslViewer/sslAppUtils.h delete mode 100644 libsecurity_ssl/sslViewer/sslServer.cpp delete mode 100644 libsecurity_transform/custom.h delete mode 100644 libsecurity_transform/lib/Digest_block.h delete mode 100644 libsecurity_transform/lib/SecExternalSourceTransform.cpp delete mode 100644 libsecurity_transform/lib/SecGroupTransform.cpp delete mode 100644 libsecurity_transform/lib/misc.h delete mode 100644 libsecurity_transform/libsecurity_transform.xcodeproj/project.pbxproj delete mode 100644 libsecurity_transform/libsecurity_transform.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurity_transform/misc/speed-test.h delete mode 100644 libsecurity_transform/misc/speed-test.mm delete mode 100644 libsecurity_utilities/lib/ccaudit.h delete mode 100644 libsecurity_utilities/lib/debugging.h delete mode 100644 libsecurity_utilities/lib/debugging_internal.h delete mode 100644 libsecurity_utilities/lib/utilities.h delete mode 100644 libsecurity_utilities/libsecurity_utilities.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurityd/lib/SharedMemoryCommon.h delete mode 100644 libsecurityd/lib/transition.cpp delete mode 100644 libsecurityd/libsecurityd.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 libsecurityd/mig/mig.mk create mode 100644 ntlm/NtlmGenerator.c create mode 100644 ntlm/NtlmGenerator.h create mode 100644 ntlm/ntlmBlobPriv.c create mode 100644 ntlm/ntlmBlobPriv.h create mode 100644 refs.txt delete mode 100644 regressions/regressions.xcodeproj/project.pbxproj delete mode 100755 regressions/t/security.pl delete mode 100755 regressions/test/run_tests.sh delete mode 100644 regressions/test/testcpp.h delete mode 100644 regressions/test/testenv.c delete mode 100644 regressions/test/testenv.h delete mode 100644 regressions/test/testmore.c delete mode 100644 regressions/test/testmore.h delete mode 100644 regressions/test/testpolicy.h create mode 100644 resources/AppleESCertificates.plist create mode 100644 resources/AssetVersion.plist create mode 100644 resources/Blocked.plist create mode 100644 resources/EVRoots.plist create mode 100644 resources/English.lproj/Certificate.strings create mode 100644 resources/English.lproj/CloudKeychain.strings create mode 100644 resources/English.lproj/OID.strings create mode 100644 resources/English.lproj/SharedWebCredentials.strings create mode 100644 resources/GrayListedKeys.plist create mode 100644 resources/certsIndex.data create mode 100644 resources/certsTable.data create mode 100755 sbr delete mode 100644 sec/SOSCircle/CKBridge/SOSCloudKeychainClient.c delete mode 100644 sec/SOSCircle/CKBridge/SOSCloudKeychainClient.h delete mode 100644 sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.h delete mode 100644 sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.m delete mode 100644 sec/SOSCircle/CloudKeychainProxy/cloudkeychainproxy.m delete mode 100755 sec/SOSCircle/CloudKeychainProxy/scripts/sosbuildroot delete mode 100755 sec/SOSCircle/CloudKeychainProxy/scripts/sshauser delete mode 100644 sec/SOSCircle/Regressions/CKDKeyValueStore.h delete mode 100644 sec/SOSCircle/Regressions/SOSTestDataSource.c delete mode 100644 sec/SOSCircle/Regressions/SOSTestDataSource.h delete mode 100644 sec/SOSCircle/Regressions/SOSTestTransport.c delete mode 100644 sec/SOSCircle/Regressions/SOSTestTransport.h delete mode 100644 sec/SOSCircle/Regressions/sc-100-devicecircle.c delete mode 100644 sec/SOSCircle/Regressions/sc-101-accountsync.c delete mode 100644 sec/SOSCircle/Regressions/sc-102-cfusernotification.c delete mode 100644 sec/SOSCircle/Regressions/sc-120-cloudcircle.c delete mode 100644 sec/SOSCircle/Regressions/sc-30-peerinfo.c delete mode 100644 sec/SOSCircle/Regressions/sc-40-circle.c delete mode 100644 sec/SOSCircle/Regressions/sc-41-cloudcircle.c delete mode 100644 sec/SOSCircle/Regressions/sc-60-peer.c delete mode 100644 sec/SOSCircle/Regressions/sc-75-circle-engine.c delete mode 100644 sec/SOSCircle/SOSARCDefines.h delete mode 120000 sec/SOSCircle/SecureObjectSync/Imported/SOSCloudCircleServer.h delete mode 120000 sec/SOSCircle/SecureObjectSync/Imported/SecItemServer.h delete mode 120000 sec/SOSCircle/SecureObjectSync/Imported/SecuritydXPC.h delete mode 120000 sec/SOSCircle/SecureObjectSync/Imported/securityd_client.h delete mode 120000 sec/SOSCircle/SecureObjectSync/Imported/spi.h delete mode 100644 sec/SOSCircle/SecureObjectSync/SOSAccount.c delete mode 100644 sec/SOSCircle/SecureObjectSync/SOSAccount.h delete mode 100644 sec/SOSCircle/SecureObjectSync/SOSCircle.c delete mode 100644 sec/SOSCircle/SecureObjectSync/SOSCloudCircle.c delete mode 100644 sec/SOSCircle/SecureObjectSync/SOSCloudCircleInternal.h delete mode 100644 sec/SOSCircle/SecureObjectSync/SOSCoder.c delete mode 100644 sec/SOSCircle/SecureObjectSync/SOSCoder.h delete mode 100644 sec/SOSCircle/SecureObjectSync/SOSEngine.c delete mode 100644 sec/SOSCircle/SecureObjectSync/SOSEngine.h delete mode 100644 sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.h delete mode 100644 sec/SOSCircle/SecureObjectSync/SOSInternal.h delete mode 100644 sec/SOSCircle/SecureObjectSync/SOSPeer.c delete mode 100644 sec/SOSCircle/SecureObjectSync/SOSPeer.h delete mode 100644 sec/SOSCircle/SecureObjectSync/SOSPeerInfo.h delete mode 100644 sec/SOSCircle/SecureObjectSync/SOSPeerInfoInternal.h delete mode 100644 sec/SOSCircle/SecureObjectSync/SOSTransport.c delete mode 100644 sec/SOSCircle/SecureObjectSync/SOSTransport.h delete mode 100644 sec/SOSCircle/SecureObjectSync/SOSUserKey.c delete mode 100644 sec/SOSCircle/SecureObjectSync/SOSUserKey.h delete mode 100644 sec/SOSCircle/SecureObjectSync/SOSUserKeygen.h delete mode 100644 sec/SOSCircle/Tool/SOSCommands.h delete mode 100644 sec/SOSCircle/Tool/keychain_sync.c delete mode 100644 sec/SOSCircle/osxshim.c delete mode 100644 sec/Security/AppleBaselineEscrowCertificates.h delete mode 100644 sec/Security/Regressions/Security_regressions.h delete mode 100644 sec/Security/Regressions/otr/otr-otrdh.c delete mode 100644 sec/Security/Regressions/otr/otr-packetdata.c delete mode 100644 sec/Security/Regressions/secitem/si-20-sectrust.c delete mode 100644 sec/Security/Regressions/secitem/si-31-keychain-unreadable.c delete mode 100644 sec/Security/Regressions/secitem/si-33-keychain-backup.c delete mode 100644 sec/Security/Regressions/secitem/si-40-seckey-custom.c delete mode 100644 sec/Security/Regressions/secitem/si-41-sececkey.c delete mode 100644 sec/Security/Regressions/secitem/si-50-secrandom.c delete mode 100644 sec/Security/Regressions/secitem/si-67-sectrust-blacklist.c delete mode 100644 sec/Security/Regressions/secitem/si-70-sectrust-unified.c delete mode 100644 sec/Security/Regressions/secitem/si-71-mobile-store-policy.c delete mode 100644 sec/Security/SecBase.h delete mode 100644 sec/Security/SecBasePriv.h delete mode 100644 sec/Security/SecCMS.c delete mode 100644 sec/Security/SecCMS.h delete mode 100644 sec/Security/SecCertificate.h delete mode 100644 sec/Security/SecCertificatePriv.h delete mode 100644 sec/Security/SecCertificateRequest.h delete mode 100644 sec/Security/SecDH.c delete mode 100644 sec/Security/SecECKey.c delete mode 100644 sec/Security/SecIdentity.c delete mode 100644 sec/Security/SecIdentity.h delete mode 100644 sec/Security/SecIdentityPriv.h delete mode 100644 sec/Security/SecImportExport.c delete mode 100644 sec/Security/SecImportExport.h delete mode 100644 sec/Security/SecInternal.h delete mode 100644 sec/Security/SecItem.h delete mode 100644 sec/Security/SecItemConstants.c delete mode 100644 sec/Security/SecItemPriv.h delete mode 100644 sec/Security/SecKey.h delete mode 100644 sec/Security/SecKeyPriv.h delete mode 100644 sec/Security/SecOTR.h delete mode 100644 sec/Security/SecOTRDHKey.c delete mode 100644 sec/Security/SecOTRDHKey.h delete mode 100644 sec/Security/SecOTRErrors.h delete mode 100644 sec/Security/SecOTRMath.h delete mode 100644 sec/Security/SecOTRMathPrivate.h delete mode 100644 sec/Security/SecOTRPacketData.c delete mode 100644 sec/Security/SecOTRPackets.h delete mode 100644 sec/Security/SecOTRSession.c delete mode 100644 sec/Security/SecOTRSession.h delete mode 100644 sec/Security/SecOTRSessionPriv.h delete mode 100644 sec/Security/SecOnOSX.h delete mode 100644 sec/Security/SecPolicy.h delete mode 100644 sec/Security/SecPolicyPriv.h delete mode 100644 sec/Security/SecRandom.h delete mode 100644 sec/Security/SecTrust.h delete mode 100644 sec/Security/SecTrustPriv.h delete mode 100644 sec/Security/SecTrustSettings.h delete mode 100644 sec/Security/SecTrustSettingsPriv.h delete mode 100644 sec/Security/Security.h delete mode 100644 sec/Security/SecuritydXPC.h delete mode 100644 sec/Security/Tool/codesign.c delete mode 100644 sec/Security/Tool/keychain_add.c delete mode 100644 sec/Security/Tool/keychain_find.c delete mode 100644 sec/Security/certextensions.h delete mode 100644 sec/Security/cssmapple.h delete mode 100644 sec/Security/keychain_find.h delete mode 100644 sec/Security/pbkdf2.c delete mode 100644 sec/Security/pbkdf2.h delete mode 100644 sec/Security/vmdh.c delete mode 100644 sec/Security/vmdh.h delete mode 100644 sec/SecurityTool/builtin_commands.h delete mode 100644 sec/SecurityTool/digest_calc.c delete mode 100644 sec/SecurityTool/leaks.c delete mode 100644 sec/SecurityTool/leaks.h delete mode 100644 sec/SecurityTool/tool_errors.h delete mode 100644 sec/config/base.xcconfig delete mode 100644 sec/config/lib.xcconfig delete mode 100644 sec/ipc/com.apple.secd.plist delete mode 100644 sec/ipc/com.apple.securityd.plist delete mode 100755 sec/ipc/securityd_client.h delete mode 100644 sec/ipc/server.c delete mode 100644 sec/sec.xcodeproj/project.pbxproj delete mode 100644 sec/sec.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 sec/securityd/Regressions/SOSAccountTesting.h delete mode 100644 sec/securityd/Regressions/SecdTestKeychainUtilities.c delete mode 100644 sec/securityd/Regressions/SecdTestKeychainUtilities.h delete mode 100644 sec/securityd/Regressions/brighton_keychain_2_db.h delete mode 100644 sec/securityd/Regressions/sd-70-engine.c delete mode 100644 sec/securityd/Regressions/secd-31-keychain-unreadable.c delete mode 100644 sec/securityd/Regressions/secd-50-account.c delete mode 100644 sec/securityd/Regressions/secd-52-account-changed.c delete mode 100644 sec/securityd/Regressions/secd-55-account-circle.c delete mode 100644 sec/securityd/Regressions/secd-55-account-incompatibility.c delete mode 100644 sec/securityd/Regressions/secd-56-account-apply.c delete mode 100644 sec/securityd/Regressions/secd-57-account-leave.c delete mode 100644 sec/securityd/Regressions/secd-58-password-change.c delete mode 100644 sec/securityd/Regressions/secd-59-account-cleanup.c delete mode 100644 sec/securityd/Regressions/secd-60-account-cloud-identity.c delete mode 100644 sec/securityd/Regressions/secd-61-account-leave-not-in-kansas-anymore.c delete mode 100644 sec/securityd/Regressions/secd_regressions.h delete mode 100644 sec/securityd/Regressions/securityd_regressions.h delete mode 100644 sec/securityd/SOSCloudCircleServer.c delete mode 100644 sec/securityd/SOSCloudCircleServer.h delete mode 100644 sec/securityd/SecCAIssuerRequest.h delete mode 100644 sec/securityd/SecDbItem.h delete mode 100644 sec/securityd/SecItemServer.c delete mode 100644 sec/securityd/SecItemServer.h delete mode 100644 sec/securityd/entitlements.plist delete mode 100644 sec/securityd/spi.c delete mode 100644 sec/securityd/spi.h create mode 100644 secdtests/secdtests-entitlements.plist create mode 100644 sectask/SecEntitlements.h create mode 100644 sectask/SecTask.c create mode 100644 sectask/SecTask.h create mode 100644 sectask/regressions/sectask-10-sectask.c create mode 100644 sectask/regressions/sectask_ipc.defs create mode 100644 sectask/regressions/sectask_regressions.h delete mode 100644 sectests/main.c delete mode 100644 sectests/test/testenv.c delete mode 100644 sectests/testlist.h delete mode 100644 security2/security2.1 delete mode 100644 security2/security_tool_commands.c delete mode 100644 security2/sub_commands.h create mode 100644 securityd/APPLE_LICENSE create mode 100644 securityd/config/debug.xcconfig create mode 100644 securityd/config/project.xcconfig create mode 100644 securityd/config/release.xcconfig create mode 100644 securityd/doc/BLOBFORMAT create mode 100644 securityd/doc/securityd.1 create mode 100644 securityd/dtrace/dtrace.mk create mode 100755 securityd/dtrace/securityd-watch.d create mode 100644 securityd/etc/CodeEquivalenceCandidates create mode 100644 securityd/etc/com.apple.securityd.plist create mode 100644 securityd/etc/startup.mk create mode 100644 securityd/libsecurity_agent/Info-security_agent_client.plist create mode 100644 securityd/libsecurity_agent/Info-security_agent_server.plist create mode 100644 securityd/libsecurity_agent/lib/agentclient.cpp create mode 100644 securityd/libsecurity_agent/lib/agentclient.h create mode 100644 securityd/libsecurity_agent/lib/sa_types.h create mode 100644 securityd/libsecurity_agent/lib/secagent_types.h create mode 100644 securityd/libsecurity_agent/lib/utils.c create mode 100644 securityd/libsecurity_agent/lib/utils.h create mode 100644 securityd/libsecurity_agent/libsecurity_agent.xcodeproj/project.pbxproj create mode 100644 securityd/libsecurity_agent/mig/mig.mk create mode 100644 securityd/libsecurity_agent/mig/sa_reply.defs create mode 100644 securityd/libsecurity_agent/mig/sa_request.defs create mode 120000 securityd/libsecurity_agent/security_agent_client create mode 100644 securityd/mig/mig.mk create mode 100644 securityd/mig/self.defs create mode 120000 securityd/security_agent_client create mode 120000 securityd/security_agent_server create mode 100644 securityd/securityd.xcodeproj/project.pbxproj create mode 100644 securityd/securityd.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 securityd/securityd_service/KeyStore/AppleKeyStoreEvents.h create mode 100644 securityd/securityd_service/KeyStore/KeyStore-Info.plist create mode 100644 securityd/securityd_service/KeyStore/KeyStoreEvents.c create mode 100644 securityd/securityd_service/securityd_service.xcodeproj/project.pbxproj create mode 100644 securityd/securityd_service/securityd_service/com.apple.securityd_service.plist create mode 100644 securityd/securityd_service/securityd_service/com.apple.securitydservice.sb create mode 100644 securityd/securityd_service/securityd_service/main.c create mode 100644 securityd/securityd_service/securityd_service/securityd_service.h create mode 100644 securityd/securityd_service/securityd_service/securityd_service_client.c create mode 100644 securityd/securityd_service/securityd_service/securityd_service_client.h create mode 100644 securityd/securityd_service/securityd_service/service.entitlements create mode 100644 securityd/securityd_service/securitydservicectrl/main.c create mode 100644 securityd/src/AuthorizationDBPlist.cpp create mode 100644 securityd/src/AuthorizationDBPlist.h create mode 100644 securityd/src/AuthorizationEngine.cpp create mode 100644 securityd/src/AuthorizationEngine.h create mode 100644 securityd/src/AuthorizationMechEval.cpp create mode 100644 securityd/src/AuthorizationMechEval.h create mode 100644 securityd/src/AuthorizationRule.cpp create mode 100644 securityd/src/AuthorizationRule.h create mode 100644 securityd/src/SharedMemoryServer.cpp create mode 100644 securityd/src/SharedMemoryServer.h create mode 100644 securityd/src/acl_keychain.cpp create mode 100644 securityd/src/acl_keychain.h create mode 100644 securityd/src/acls.cpp create mode 100644 securityd/src/acls.h create mode 100644 securityd/src/agentquery.cpp create mode 100644 securityd/src/agentquery.h create mode 100644 securityd/src/auditevents.cpp create mode 100644 securityd/src/auditevents.h create mode 100644 securityd/src/authhost.cpp create mode 100644 securityd/src/authhost.h create mode 100644 securityd/src/authority.cpp create mode 100644 securityd/src/authority.h create mode 100644 securityd/src/ccaudit_extensions.cpp create mode 100644 securityd/src/ccaudit_extensions.h create mode 100644 securityd/src/child.cpp create mode 100644 securityd/src/child.h create mode 100644 securityd/src/clientid.cpp create mode 100644 securityd/src/clientid.h create mode 100644 securityd/src/codesigdb.cpp create mode 100644 securityd/src/codesigdb.h create mode 100644 securityd/src/connection.cpp create mode 100644 securityd/src/connection.h create mode 100644 securityd/src/credential.cpp create mode 100644 securityd/src/credential.h create mode 100644 securityd/src/csproxy.cpp create mode 100644 securityd/src/csproxy.h create mode 100644 securityd/src/database.cpp create mode 100644 securityd/src/database.h create mode 100644 securityd/src/dbcrypto.cpp create mode 100644 securityd/src/dbcrypto.h create mode 100644 securityd/src/dtrace.h create mode 100644 securityd/src/entropy.cpp create mode 100644 securityd/src/entropy.h create mode 100644 securityd/src/kcdatabase.cpp create mode 100644 securityd/src/kcdatabase.h create mode 100644 securityd/src/kckey.cpp create mode 100644 securityd/src/kckey.h create mode 100644 securityd/src/key.cpp create mode 100644 securityd/src/key.h create mode 100644 securityd/src/localdatabase.cpp create mode 100644 securityd/src/localdatabase.h create mode 100644 securityd/src/localkey.cpp create mode 100644 securityd/src/localkey.h create mode 100644 securityd/src/main.cpp create mode 100644 securityd/src/notifications.cpp create mode 100644 securityd/src/notifications.h create mode 100644 securityd/src/pcscmonitor.cpp create mode 100644 securityd/src/pcscmonitor.h create mode 100644 securityd/src/process.cpp create mode 100644 securityd/src/process.h create mode 100644 securityd/src/reader.cpp create mode 100644 securityd/src/reader.h create mode 100644 securityd/src/securityd.d create mode 100644 securityd/src/securityd.exp create mode 100644 securityd/src/securityd.order create mode 100644 securityd/src/server.cpp create mode 100644 securityd/src/server.h create mode 100644 securityd/src/session.cpp create mode 100644 securityd/src/session.h create mode 100644 securityd/src/structure.cpp create mode 100644 securityd/src/structure.h create mode 100644 securityd/src/tempdatabase.cpp create mode 100644 securityd/src/tempdatabase.h create mode 100644 securityd/src/token.cpp create mode 100644 securityd/src/token.h create mode 100644 securityd/src/tokenaccess.cpp create mode 100644 securityd/src/tokenaccess.h create mode 100644 securityd/src/tokenacl.cpp create mode 100644 securityd/src/tokenacl.h create mode 100644 securityd/src/tokencache.cpp create mode 100644 securityd/src/tokencache.h create mode 100644 securityd/src/tokend.cpp create mode 100644 securityd/src/tokend.h create mode 100644 securityd/src/tokendatabase.cpp create mode 100644 securityd/src/tokendatabase.h create mode 100644 securityd/src/tokenkey.cpp create mode 100644 securityd/src/tokenkey.h create mode 100644 securityd/src/transition.cpp create mode 100644 securityd/tests/AZNTest.cpp create mode 100644 securityd/tests/auth.plist create mode 100644 securityd/tests/exectest.cpp create mode 100644 securityd/tests/testacls.cpp create mode 100644 securityd/tests/testauth.cpp create mode 100644 securityd/tests/testblobs.cpp create mode 100644 securityd/tests/testclient.cpp create mode 100644 securityd/tests/testclient.h create mode 100644 securityd/tests/testcrypto.cpp create mode 100644 securityd/tests/testutils.cpp create mode 100644 securityd/tests/testutils.h create mode 100644 spiralsink114.png create mode 100644 spiralsink57.png create mode 100644 sslViewer/SSLViewer.cpp create mode 100644 sslViewer/SSL_Sites create mode 100644 sslViewer/ecc-secp256r1-client.pfx create mode 100644 sslViewer/ioSock.c create mode 100644 sslViewer/ioSock.h create mode 100755 sslViewer/pingSslSites create mode 100644 sslViewer/sslAppUtils.cpp create mode 100644 sslViewer/sslAppUtils.h create mode 100644 sslViewer/sslClient.cpp create mode 100644 sslViewer/sslEcdsa.cpp create mode 100644 sslViewer/sslServe.cpp create mode 100644 sslViewer/sslServer-entitlements.plist create mode 100644 sslViewer/sslServer.cpp create mode 100644 sslViewer/sslThreading.h create mode 100644 sslViewer/sslViewer-entitlements.plist create mode 100755 sslViewer/verifyPing delete mode 100644 tlsnke/tlsnke.xcodeproj/project.pbxproj delete mode 100644 tlsnke/tlsnke.xcodeproj/xcuserdata/fabrice.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist delete mode 100644 tlsnke/tlsnke/tlsnke.h delete mode 100644 tlsnke/tlsnketest/main.c delete mode 100644 tlsnke/tlsnketest/ssl-utils.c delete mode 100644 tlsnke/tlsnketest/ssl-utils.h delete mode 100644 tlsnke/tlsnketest/tlssocket.h delete mode 100644 utilities/Regressions/su-10-cfstring-der.c delete mode 100644 utilities/Regressions/su-12-cfboolean-der.c delete mode 100644 utilities/SecurityTool/not_on_this_platorm.c delete mode 100644 utilities/SecurityTool/readline.c delete mode 100644 utilities/SecurityTool/readline.h delete mode 100644 utilities/SecurityTool/security_tool_commands.h delete mode 100644 utilities/SecurityTool/security_tool_commands_table.h delete mode 100644 utilities/src/SecAKSWrappers.h delete mode 100644 utilities/src/SecCFCanonicalHashes.c delete mode 100644 utilities/src/SecCFCanonicalHashes.h delete mode 100644 utilities/src/SecCFError.c delete mode 100644 utilities/src/SecCFError.h delete mode 100644 utilities/src/SecCFRelease.h delete mode 100644 utilities/src/SecCFWrappers.c delete mode 100644 utilities/src/SecCFWrappers.h delete mode 100644 utilities/src/SecDb.h delete mode 100644 utilities/src/SecDispatchRelease.h delete mode 100644 utilities/src/SecIOFormat.h delete mode 100644 utilities/src/SecXPCError.c delete mode 100644 utilities/src/SecXPCError.h delete mode 100644 utilities/src/array_size.h delete mode 100644 utilities/src/comparison.c delete mode 100644 utilities/src/comparison.h delete mode 100644 utilities/src/debugging.c delete mode 100644 utilities/src/debugging.h delete mode 100644 utilities/src/der_array.c delete mode 100644 utilities/src/der_boolean.c delete mode 100644 utilities/src/der_data.c delete mode 100644 utilities/src/der_date.c delete mode 100644 utilities/src/der_date.h delete mode 100644 utilities/src/der_null.c delete mode 100644 utilities/src/der_plist.h delete mode 100644 utilities/src/der_plist_internal.c delete mode 100644 utilities/src/der_string.c delete mode 100644 utilities/src/fileIo.c delete mode 100644 utilities/src/fileIo.h delete mode 100644 utilities/src/iCloudKeychainTrace.c delete mode 100644 utilities/src/iCloudKeychainTrace.h delete mode 100644 utilities/src/iOSforOSX-SecAttr.c delete mode 100644 utilities/src/iOSforOSX-SecRandom.c delete mode 100644 utilities/src/iOSforOSX.c delete mode 100644 utilities/src/iOSforOSX.h delete mode 100644 utilities/src/sqlutils.h delete mode 100644 utilities/utilities.xcodeproj/project.pbxproj diff --git a/.call b/.call new file mode 100644 index 00000000..6cc86973 --- /dev/null +++ b/.call @@ -0,0 +1,40 @@ +# +# call configuration file +# + +# ============================================================================= +# Some Xcode defaults +# + +configuration = Debug-Emulator +DSTROOT = /tmp/Security.dst + +# ============================================================================= +# Commands +# + +build + xcodebuild -configuration Debug-Emulator -target Security + +build_deployment + xcodebuild -configuration Release-Emulator -target Security + +clean + xcodebuild clean -configuration Debug-Emulator -target Security + +install + rm -rf /tmp/Security.sym + export RC_JASPER=YES && xcodebuild install -configuration Debug-Emulator -target Security DSTROOT=$DSTROOT + +install_deployment + rm -rf /tmp/Security.sym + export RC_JASPER=YES && xcodebuild install -configuration Release-Emulator -target Security DSTROOT=$DSTROOT SYMROOT=/tmp/Security.sym + +update up + svn $< + +commit com ci + svn $< + +# ============================================================================= +# end diff --git a/sec/SOSCircle/Empty.c b/.com.apple.timemachine.supported similarity index 100% rename from sec/SOSCircle/Empty.c rename to .com.apple.timemachine.supported diff --git a/CircleJoinRequested/Applicant.h b/CircleJoinRequested/Applicant.h new file mode 100644 index 00000000..f7c76bff --- /dev/null +++ b/CircleJoinRequested/Applicant.h @@ -0,0 +1,29 @@ +// +// Applicant.h +// Security +// +// Created by J Osborne on 3/7/13. +// Copyright (c) 2013 Apple Inc. All Rights Reserved. +// + +#import +#include "SecureObjectSync/SOSPeerInfo.h" + +typedef enum { + ApplicantWaiting, + ApplicantOnScreen, + ApplicantRejected, + ApplicantAccepted, +} ApplicantUIState; + +@interface Applicant : NSObject +@property (readwrite) ApplicantUIState applicantUIState; +@property (readonly) NSString *applicantUIStateName; +@property (readwrite) SOSPeerInfoRef rawPeerInfo; +@property (readonly) NSString *name; +@property (readonly) NSString *idString; +@property (readonly) NSString *deviceType; +-(id)initWithPeerInfo:(SOSPeerInfoRef) peerInfo; +-(NSString *)description; +-(void)dealloc; +@end diff --git a/CircleJoinRequested/Applicant.m b/CircleJoinRequested/Applicant.m new file mode 100644 index 00000000..f996d3a8 --- /dev/null +++ b/CircleJoinRequested/Applicant.m @@ -0,0 +1,79 @@ +// +// Applicant.m +// Security +// +// Created by J Osborne on 3/7/13. +// Copyright (c) 2013 Apple Inc. All Rights Reserved. +// + +#import "Applicant.h" +#include + +@implementation Applicant + +-(id)initWithPeerInfo:(SOSPeerInfoRef)peerInfo +{ + self = [super init]; + if (!self) { + return self; + } + + self.rawPeerInfo = CFRetainSafe(peerInfo); + self.applicantUIState = ApplicantWaiting; + + return self; +} + +-(NSString*)idString +{ + return (__bridge NSString *)(SOSPeerInfoGetPeerID(self.rawPeerInfo)); +} + +-(NSString *)name +{ + return (__bridge NSString *)(SOSPeerInfoGetPeerName(self.rawPeerInfo)); +} + +-(void)dealloc +{ + if (self.rawPeerInfo) { + CFRelease(self.rawPeerInfo); + } +} + +-(NSString *)description +{ + return [NSString stringWithFormat:@"%@=%@", self.rawPeerInfo, self.applicantUIStateName]; +} + +-(NSString *)deviceType +{ + return (__bridge NSString *)(SOSPeerInfoGetPeerDeviceType(self.rawPeerInfo)); +} + +-(NSString *)applicantUIStateName +{ + switch (self.applicantUIState) { + case ApplicantWaiting: + return @"Waiting"; + break; + + case ApplicantOnScreen: + return @"OnScreen"; + break; + + case ApplicantRejected: + return @"Rejected"; + break; + + case ApplicantAccepted: + return @"Accepted"; + break; + + default: + return [NSString stringWithFormat:@"UnknownState#%d", self.applicantUIState]; + break; + } +} + +@end diff --git a/CircleJoinRequested/CircleJoinRequested.1 b/CircleJoinRequested/CircleJoinRequested.1 new file mode 100644 index 00000000..40da368b --- /dev/null +++ b/CircleJoinRequested/CircleJoinRequested.1 @@ -0,0 +1,79 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. +.\"See Also: +.\"man mdoc.samples for a complete listing of options +.\"man mdoc for the short list of editing options +.\"/usr/share/misc/mdoc.template +.Dd 3/12/13 \" DATE +.Dt CircleJoinRequested 1 \" Program name and manual section number +.Os Darwin +.Sh NAME \" Section Header - required - don't modify +.Nm CircleJoinRequested, +.\" The following lines are read in generating the apropos(man -k) database. Use only key +.\" words here as the database is built based on the words here and in the .ND line. +.Nm Other_name_for_same_program(), +.Nm Yet another name for the same program. +.\" Use .Nm macro to designate other names for the documented program. +.Nd This line parsed for whatis database. +.Sh SYNOPSIS \" Section Header - required - don't modify +.Nm +.Op Fl abcd \" [-abcd] +.Op Fl a Ar path \" [-a path] +.Op Ar file \" [file] +.Op Ar \" [file ...] +.Ar arg0 \" Underlined argument - use .Ar anywhere to underline +arg2 ... \" Arguments +.Sh DESCRIPTION \" Section Header - required - don't modify +Use the .Nm macro to refer to your program throughout the man page like such: +.Nm +Underlining is accomplished with the .Ar macro like this: +.Ar underlined text . +.Pp \" Inserts a space +A list of items with descriptions: +.Bl -tag -width -indent \" Begins a tagged list +.It item a \" Each item preceded by .It macro +Description of item a +.It item b +Description of item b +.El \" Ends the list +.Pp +A list of flags and their descriptions: +.Bl -tag -width -indent \" Differs from above in tag removed +.It Fl a \"-a flag as a list item +Description of -a flag +.It Fl b +Description of -b flag +.El \" Ends the list +.Pp +.\" .Sh ENVIRONMENT \" May not be needed +.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 +.\" .It Ev ENV_VAR_1 +.\" Description of ENV_VAR_1 +.\" .It Ev ENV_VAR_2 +.\" Description of ENV_VAR_2 +.\" .El +.Sh FILES \" File used or created by the topic of the man page +.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact +.It Pa /usr/share/file_name +FILE_1 description +.It Pa /Users/joeuser/Library/really_long_file_name +FILE_2 description +.El \" Ends the list +.\" .Sh DIAGNOSTICS \" May not be needed +.\" .Bl -diag +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .El +.Sh SEE ALSO +.\" List links in ascending order by section, alphabetically within a section. +.\" Please do not reference files that do not exist without filing a bug report +.Xr a 1 , +.Xr b 1 , +.Xr c 1 , +.Xr a 2 , +.Xr b 2 , +.Xr a 3 , +.Xr b 3 +.\" .Sh BUGS \" Document known, unremedied bugs +.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file diff --git a/CircleJoinRequested/CircleJoinRequested.m b/CircleJoinRequested/CircleJoinRequested.m new file mode 100644 index 00000000..e00c7bc5 --- /dev/null +++ b/CircleJoinRequested/CircleJoinRequested.m @@ -0,0 +1,771 @@ +// +// CircleJoinRequested.m +// CircleJoinRequested +// +// Created by J Osborne on 3/5/13. +// Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. +// +#import +#import +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnewline-eof" +#import +#pragma clang diagnostic pop +#import +#import +#import +#include +#include "SecureObjectSync/SOSCloudCircle.h" +#include "SecureObjectSync/SOSPeerInfo.h" +#import +#import +#include +#include +#import "Applicant.h" +#import "NSArray+map.h" +#import +#import +#import +#import "PersistantState.h" +#include +#include +#import "NSDate+TimeIntervalDescription.h" +#include +#include +#include +#import +#import +#import +#import + +// As long as we are logging the failure use exit code of zero to make launchd happy +#define EXIT_LOGGED_FAILURE(code) xpc_transaction_end(); exit(0) + +const char *kLaunchLaterXPCName = "com.apple.security.CircleJoinRequestedTick"; +CFRunLoopSourceRef currentAlertSource = NULL; +CFUserNotificationRef currentAlert = NULL; +bool currentAlertIsForApplicants = true; +bool currentAlertIsForKickOut = false; +NSMutableDictionary *applicants = nil; +volatile NSString *debugState = @"main?"; +dispatch_block_t doOnceInMainBlockChain = NULL; + +NSString *castleKeychainUrl = @"prefs:root=CASTLE&path=Keychain/ADVANCED"; + +#if 0 +// For use with: __attribute__((cleanup(CFReleaseSafeIndirect))) CFType auto_var; +static void CFReleaseSafeIndirect(void *o_) +{ + void **o = o_; + if (o && *o) { + CFRelease(*o); + } +} +#endif + +static void doOnceInMain(dispatch_block_t block) +{ + if (doOnceInMainBlockChain) { + doOnceInMainBlockChain = ^{ + doOnceInMainBlockChain(); + block(); + }; + } else { + doOnceInMainBlockChain = block; + } +} + +static NSString *appleIDAccountName() +{ + ACAccountStore *accountStore = [[ACAccountStore alloc] init]; + ACAccount *primaryAppleAccount = [accountStore aa_primaryAppleAccount]; + return primaryAppleAccount.username; +} + +static CFOptionFlags flagsForAsk(Applicant *applicant) +{ + return kCFUserNotificationPlainAlertLevel|CFUserNotificationSecureTextField(0); +} + +// NOTE: gives precedence to OnScreen +static Applicant *firstApplicantWaitingOrOnScreen() +{ + Applicant *waiting = nil; + for (Applicant *applicant in [applicants objectEnumerator]) { + if (applicant.applicantUIState == ApplicantOnScreen) { + return applicant; + } else if (applicant.applicantUIState == ApplicantWaiting) { + waiting = applicant; + } + } + + return waiting; +} + +static NSMutableArray *applicantsInState(ApplicantUIState state) +{ + NSMutableArray *results = [NSMutableArray new]; + for (Applicant *applicant in [applicants objectEnumerator]) { + if (applicant.applicantUIState == state) { + [results addObject:applicant]; + } + } + + return results; +} + +static BOOL processRequests(CFErrorRef *error) +{ + bool ok = true; + NSMutableArray *toAccept = [[applicantsInState(ApplicantAccepted) mapWithBlock:^id(id obj) { + return (id)[obj rawPeerInfo]; + }] mutableCopy]; + NSMutableArray *toReject = [[applicantsInState(ApplicantRejected) mapWithBlock:^id(id obj) { + return (id)[obj rawPeerInfo]; + }] mutableCopy]; + + NSLog(@"Process accept: %@", toAccept); + NSLog(@"Process reject: %@", toReject); + + if ([toAccept count]) { + ok = ok && SOSCCAcceptApplicants((__bridge CFArrayRef)(toAccept), error); + } + if ([toReject count]) { + ok = ok && SOSCCRejectApplicants((__bridge CFArrayRef)(toReject), error); + } + + return ok; +} + +static void cancelCurrentAlert(bool stopRunLoop) +{ + if (currentAlertSource) { + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), currentAlertSource, kCFRunLoopDefaultMode); + CFRelease(currentAlertSource); + currentAlertSource = NULL; + } + if (currentAlert) { + CFUserNotificationCancel(currentAlert); + CFRelease(currentAlert); + currentAlert = NULL; + } + if (stopRunLoop) { + CFRunLoopStop(CFRunLoopGetCurrent()); + } + currentAlertIsForKickOut = currentAlertIsForApplicants = false; +} + +static void askAboutAll(bool passwordFailure); + +static void applicantChoice(CFUserNotificationRef userNotification, CFOptionFlags responseFlags) +{ + ApplicantUIState choice; + + if (kCFUserNotificationAlternateResponse == responseFlags) { + choice = ApplicantRejected; + } else if (kCFUserNotificationDefaultResponse == responseFlags) { + choice = ApplicantAccepted; + } else { + NSLog(@"Unexpected response %lu", responseFlags); + choice = ApplicantRejected; + } + + BOOL processed = NO; + CFErrorRef error = NULL; + + NSArray *onScreen = applicantsInState(ApplicantOnScreen); + + [onScreen enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + Applicant* applicant = (Applicant*) obj; + + applicant.applicantUIState = choice; + }]; + + if (choice == ApplicantRejected) { + // If this device has ever set up the public key this should work without the password... + processed = processRequests(&error); + if (processed) { + NSLog(@"Didn't need password to process %@", onScreen); + cancelCurrentAlert(true); + return; + } else { + // ...however if the public key gets lost we should "just" fall through to the validate + // password path. + NSLog(@"Couldn't process reject without password (e=%@) for %@ (will try with password next)", error, onScreen); + } + } + + NSString *password = (__bridge NSString *)(CFUserNotificationGetResponseValue(userNotification, kCFUserNotificationTextFieldValuesKey, 0)); + if (!password) { + NSLog(@"No password given, retry"); + askAboutAll(true); + return; + } + const char *passwordUTF8 = [password UTF8String]; + NSData *passwordBytes = [NSData dataWithBytes:passwordUTF8 length:strlen(passwordUTF8)]; + + // Sometimes securityd crashes between the SOSCCRegisterUserCredentials and the processRequests, + // (which results in a process error -- I think this is 13355140); as a workaround we retry + // failure a few times before we give up. + for (int try = 0; try < 5 && !processed; try++) { + if (!SOSCCTryUserCredentials(CFSTR(""), (__bridge CFDataRef)(passwordBytes), &error)) { + NSLog(@"Try user credentials failed %@", error); + if ((error==NULL) || (CFEqual(kSOSErrorDomain, CFErrorGetDomain(error)) && kSOSErrorWrongPassword == CFErrorGetCode(error))) { + NSLog(@"Calling askAboutAll again..."); + + [onScreen enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + Applicant* applicant = (Applicant*) obj; + + applicant.applicantUIState = ApplicantWaiting; + }]; + askAboutAll(true); + return; + } + EXIT_LOGGED_FAILURE(EX_DATAERR); + } + + processed = processRequests(&error); + if (!processed) { + NSLog(@"Can't processRequests: %@ for %@", error, onScreen); + } + } + if (processed && firstApplicantWaitingOrOnScreen()) { + cancelCurrentAlert(false); + askAboutAll(false); + } else { + cancelCurrentAlert(true); + } +} + +static void passwordFailurePrompt() +{ + //CFBridgingRelease + NSString *pwIncorrect = [NSString stringWithFormat:(NSString *)CFBridgingRelease(SecCopyCKString(SEC_CK_PASSWORD_INCORRECT)), appleIDAccountName()]; + NSString *tryAgain = CFBridgingRelease(SecCopyCKString(SEC_CK_TRY_AGAIN)); + NSDictionary *noteAttributes = @{ + (id)kCFUserNotificationAlertHeaderKey: pwIncorrect, + (id)kCFUserNotificationDefaultButtonTitleKey: tryAgain, + // TopMost gets us onto the lock screen + (id)kCFUserNotificationAlertTopMostKey: (id)kCFBooleanTrue, + (__bridge id)SBUserNotificationDontDismissOnUnlock: @YES, + (__bridge id)SBUserNotificationDismissOnLock: @NO, + }; + CFOptionFlags flags = kCFUserNotificationPlainAlertLevel; + SInt32 err; + CFUserNotificationRef note = CFUserNotificationCreate(NULL, 0.0, flags, &err, (__bridge CFDictionaryRef)noteAttributes); + CFUserNotificationReceiveResponse(note, 0.0, &flags); + CFRelease(note); +} + +static NSDictionary *createNote(Applicant *applicantToAskAbout) { + if(!applicantToAskAbout) return NULL; + NSString *appName = applicantToAskAbout.name; + if(!appName) return NULL; + NSString *devType = applicantToAskAbout.deviceType; + if(!devType) return NULL; + return @{ + (id)kCFUserNotificationAlertHeaderKey: [NSString stringWithFormat:(__bridge_transfer NSString*)SecCopyCKString(SEC_CK_JOIN_TITLE), appName], + (id)kCFUserNotificationAlertMessageKey: [NSString stringWithFormat:(__bridge_transfer NSString*)SecCopyCKString(SEC_CK_JOIN_PROMPT), appleIDAccountName(), devType], + (id)kCFUserNotificationDefaultButtonTitleKey: (__bridge_transfer NSString*)SecCopyCKString(SEC_CK_ALLOW), + (id)kCFUserNotificationAlternateButtonTitleKey: (__bridge_transfer NSString*)SecCopyCKString(SEC_CK_DONT_ALLOW), + (id)kCFUserNotificationTextFieldTitlesKey: (__bridge_transfer NSString*)SecCopyCKString(SEC_CK_ICLOUD_PASSWORD), + // TopMost gets us onto the lock screen + (id)kCFUserNotificationAlertTopMostKey: (id)kCFBooleanTrue, + (__bridge_transfer id)SBUserNotificationDontDismissOnUnlock: @YES, + (__bridge_transfer id)SBUserNotificationDismissOnLock: @NO, + }; +} + +static void askAboutAll(bool passwordFailure) +{ + if ([[MCProfileConnection sharedConnection] effectiveBoolValueForSetting: MCFeatureAccountModificationAllowed] == MCRestrictedBoolExplicitNo) { + NSLog(@"Account modifications not allowed."); + return; + } + + if (passwordFailure) { + passwordFailurePrompt(); + } + + if ((passwordFailure || !currentAlertIsForApplicants) && currentAlert) { + if (!currentAlertIsForApplicants) { + CFUserNotificationCancel(currentAlert); + } + // after password failure we need to remove the existing alert and supporting objects + // because we can't reuse them. + CFRelease(currentAlert); + currentAlert = NULL; + if (currentAlertSource) { + CFRelease(currentAlertSource); + currentAlertSource = NULL; + } + } + currentAlertIsForApplicants = true; + + Applicant *applicantToAskAbout = firstApplicantWaitingOrOnScreen(); + NSLog(@"Asking about: %@ (of: %@)", applicantToAskAbout, applicants); + + NSDictionary *noteAttributes = createNote(applicantToAskAbout); + if(!noteAttributes) { + NSLog(@"NULL data for %@", applicantToAskAbout); + cancelCurrentAlert(true); + return; + } + + CFOptionFlags flags = flagsForAsk(applicantToAskAbout); + + if (currentAlert) { + SInt32 err = CFUserNotificationUpdate(currentAlert, 0, flags, (__bridge CFDictionaryRef)noteAttributes); + if (err) { + NSLog(@"CFUserNotificationUpdate err=%d", (int)err); + EXIT_LOGGED_FAILURE(EX_SOFTWARE); + } + } else { + SInt32 err = 0; + currentAlert = CFUserNotificationCreate(NULL, 0.0, flags, &err, (__bridge CFDictionaryRef)(noteAttributes)); + if (err) { + NSLog(@"Can't make notification for %@ err=%x", applicantToAskAbout, (int)err); + EXIT_LOGGED_FAILURE(EX_SOFTWARE); + } + + currentAlertSource = CFUserNotificationCreateRunLoopSource(NULL, currentAlert, applicantChoice, 0); + CFRunLoopAddSource(CFRunLoopGetCurrent(), currentAlertSource, kCFRunLoopDefaultMode); + } + + applicantToAskAbout.applicantUIState = ApplicantOnScreen; +} + +static void scheduleActivity(int alertInterval) +{ + xpc_object_t options = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(options, XPC_ACTIVITY_DELAY, alertInterval); + xpc_dictionary_set_uint64(options, XPC_ACTIVITY_GRACE_PERIOD, XPC_ACTIVITY_INTERVAL_1_MIN); + xpc_dictionary_set_bool(options, XPC_ACTIVITY_REPEATING, false); + xpc_dictionary_set_bool(options, XPC_ACTIVITY_ALLOW_BATTERY, true); + xpc_dictionary_set_string(options, XPC_ACTIVITY_PRIORITY, XPC_ACTIVITY_PRIORITY_UTILITY); + + xpc_activity_register(kLaunchLaterXPCName, options, ^(xpc_activity_t activity) { + NSLog(@"activity handler fired"); + }); +} + +static void reminderChoice(CFUserNotificationRef userNotification, CFOptionFlags responseFlags) +{ + if (kCFUserNotificationAlternateResponse == responseFlags || kCFUserNotificationDefaultResponse == responseFlags) { + PersistantState *state = [PersistantState loadFromStorage]; + NSDate *nowish = [NSDate new]; + state.pendingApplicationReminder = [nowish dateByAddingTimeInterval: state.pendingApplicationReminderAlertInterval]; + scheduleActivity(state.pendingApplicationReminderAlertInterval); + [state writeToStorage]; + if (kCFUserNotificationAlternateResponse == responseFlags) { + BOOL ok = [[LSApplicationWorkspace defaultWorkspace] openSensitiveURL:[NSURL URLWithString:castleKeychainUrl] withOptions:nil]; + NSLog(@"ok=%d opening %@", ok, [NSURL URLWithString:castleKeychainUrl]); + } + } + + cancelCurrentAlert(true); +} + + +static NSString* getLocalizedDeviceClass(void) { + NSString *deviceType = NULL; + switch (MGGetSInt32Answer(kMGQDeviceClassNumber, MGDeviceClassInvalid)) { + case MGDeviceClassiPhone: + deviceType = (__bridge NSString*)SecCopyCKString(SEC_CK_THIS_IPHONE); + break; + case MGDeviceClassiPod: + deviceType = (__bridge NSString*)SecCopyCKString(SEC_CK_THIS_IPOD); + break; + case MGDeviceClassiPad: + deviceType = (__bridge NSString*)SecCopyCKString(SEC_CK_THIS_IPAD); + break; + default: + deviceType = (__bridge NSString*)SecCopyCKString(SEC_CK_THIS_DEVICE); + break; + } + return deviceType; +} + +static bool iCloudResetAvailable() +{ + SecureBackup *backupd = [SecureBackup new]; + NSDictionary *backupdResults; + NSError *error = [backupd getAccountInfoWithInfo:nil results:&backupdResults]; + NSLog(@"SecureBackup e=%@ r=%@", error, backupdResults); + return (nil == error && [backupdResults[kSecureBackupIsEnabledKey] isEqualToNumber:@YES]); +} + +static void postApplicationReminderAlert(NSDate *nowish, PersistantState *state, unsigned int alertInterval) +{ + + NSString *deviceType = getLocalizedDeviceClass(); + + bool has_iCSC = iCloudResetAvailable(); + + NSString *alertMessage = [NSString stringWithFormat:(__bridge NSString*)SecCopyCKString(has_iCSC ? SEC_CK_ARS1_BODY : SEC_CK_ARS0_BODY), deviceType]; + if (state.defaultPendingApplicationReminderAlertInterval != state.pendingApplicationReminderAlertInterval) { + alertMessage = [NSString stringWithFormat:@"%@ 〖debug interval %u; wait time %@〗", + alertMessage, + state.pendingApplicationReminderAlertInterval, + [nowish copyDescriptionOfIntervalSince:state.applcationDate]]; + } + + NSDictionary *pendingAttributes = @{ + (id)kCFUserNotificationAlertHeaderKey: (__bridge NSString*)SecCopyCKString(has_iCSC ? SEC_CK_ARS1_TITLE : SEC_CK_ARS0_TITLE), + (id)kCFUserNotificationAlertMessageKey: alertMessage, + (id)kCFUserNotificationDefaultButtonTitleKey: (__bridge NSString*)SecCopyCKString(SEC_CK_AR_APPROVE_OTHER), + (id)kCFUserNotificationAlternateButtonTitleKey: has_iCSC ? (__bridge NSString*)SecCopyCKString(SEC_CK_AR_USE_CODE) : @"", + (id)kCFUserNotificationAlertTopMostKey: (id)kCFBooleanTrue, + (__bridge id)SBUserNotificationHideButtonsInAwayView: @YES, + (__bridge id)SBUserNotificationDontDismissOnUnlock: @YES, + (__bridge id)SBUserNotificationDismissOnLock: @NO, + (__bridge id)SBUserNotificationOneButtonPerLine: @YES, + }; + SInt32 err = 0; + currentAlert = CFUserNotificationCreate(NULL, 0.0, kCFUserNotificationPlainAlertLevel, &err, (__bridge CFDictionaryRef)(pendingAttributes)); + + if (err) { + NSLog(@"Can't make pending notification err=%x", (int)err); + } else { + currentAlertIsForApplicants = false; + currentAlertSource = CFUserNotificationCreateRunLoopSource(NULL, currentAlert, reminderChoice, 0); + CFRunLoopAddSource(CFRunLoopGetCurrent(), currentAlertSource, kCFRunLoopDefaultMode); + } +} + +static void kickOutChoice(CFUserNotificationRef userNotification, CFOptionFlags responseFlags) +{ + NSLog(@"kOC %@ %lu", userNotification, responseFlags); + if (kCFUserNotificationAlternateResponse == responseFlags) { + // We need to let things unwind to main for the new state to get saved + doOnceInMain(^{ + BOOL ok = [[LSApplicationWorkspace defaultWorkspace] openSensitiveURL:[NSURL URLWithString:castleKeychainUrl] withOptions:nil]; + NSLog(@"ok=%d opening %@", ok, [NSURL URLWithString:castleKeychainUrl]); + }); + } + cancelCurrentAlert(true); +} + +static void postKickedOutAlert(enum DepartureReason reason) +{ + NSString *deviceType = getLocalizedDeviceClass(); + NSString *message = nil; + debugState = @"pKOA A"; + bool ok_to_use_code = iCloudResetAvailable(); + debugState = @"pKOA B"; + + switch (reason) { + case kSOSNeverLeftCircle: + // Was: SEC_CK_CR_BODY_NEVER_LEFT + return; + break; + + case kSOSWithdrewMembership: + // Was: SEC_CK_CR_BODY_WITHDREW + // "... if you turn off a switch you have some idea why the light is off" - Murf + return; + break; + + case kSOSMembershipRevoked: + message = [NSString stringWithFormat:(__bridge NSString*)SecCopyCKString(SEC_CK_CR_BODY_REVOKED), deviceType]; + break; + + case kSOSLeftUntrustedCircle: + message = [NSString stringWithFormat:(__bridge NSString*)SecCopyCKString(SEC_CK_CR_BODY_LEFT_UNTRUSTED), deviceType]; + ok_to_use_code = false; + break; + + case kSOSNeverAppliedToCircle: + // We didn't get kicked out, we were never here. This should only happen if we changed iCloud accounts + // (and we had sync on in the previous one, and never had it on in the new one). As this is explicit + // user action alot of thd "Light switch" argument (above) applies. + return; + break; + + default: + message = [NSString stringWithFormat:(__bridge NSString*)SecCopyCKString(SEC_CK_CR_BODY_UNKNOWN), deviceType]; + ok_to_use_code = false; + syslog(LOG_ERR, "Unknown DepartureReason %d", reason); + break; + } + + NSDictionary *kickedAttributes = @{ + (id)kCFUserNotificationAlertHeaderKey: (__bridge NSString*)SecCopyCKString(SEC_CK_CR_TITLE), + (id)kCFUserNotificationAlertMessageKey: message, + (id)kCFUserNotificationDefaultButtonTitleKey: (__bridge NSString*)SecCopyCKString(SEC_CK_CR_OK), + (id)kCFUserNotificationAlternateButtonTitleKey: ok_to_use_code ? (__bridge NSString*)SecCopyCKString(SEC_CK_CR_USE_CODE) + : @"", + (id)kCFUserNotificationAlertTopMostKey: (id)kCFBooleanTrue, + (__bridge id)SBUserNotificationHideButtonsInAwayView: @YES, + (__bridge id)SBUserNotificationDontDismissOnUnlock: @YES, + (__bridge id)SBUserNotificationDismissOnLock: @NO, + (__bridge id)SBUserNotificationOneButtonPerLine: @YES, + }; + SInt32 err = 0; + + if (currentAlertIsForKickOut) { + debugState = @"pKOA C"; + NSLog(@"Updating existing alert %@ with %@", currentAlert, kickedAttributes); + CFUserNotificationUpdate(currentAlert, 0, kCFUserNotificationPlainAlertLevel, (__bridge CFDictionaryRef)(kickedAttributes)); + } else { + debugState = @"pKOA D"; + + CFUserNotificationRef note = CFUserNotificationCreate(NULL, 0.0, kCFUserNotificationPlainAlertLevel, &err, (__bridge CFDictionaryRef)(kickedAttributes)); + if (err) { + NSLog(@"Can't make kicked out notification err=%x", (int)err); + } else { + currentAlertIsForApplicants = false; + currentAlertIsForKickOut = true; + + currentAlert = note; + NSLog(@"New ko alert %@ a=%@", currentAlert, kickedAttributes); + currentAlertSource = CFUserNotificationCreateRunLoopSource(NULL, currentAlert, kickOutChoice, 0); + CFRunLoopAddSource(CFRunLoopGetCurrent(), currentAlertSource, kCFRunLoopDefaultMode); + int backupStateChangeToken; + notify_register_dispatch("com.apple.EscrowSecurityAlert.reset", &backupStateChangeToken, dispatch_get_main_queue(), ^(int token) { + if (currentAlert == note) { + NSLog(@"Backup state might have changed (dS=%@)", debugState); + postKickedOutAlert(reason); + } else { + NSLog(@"Backup state may have changed, but we don't care anymore (dS=%@)", debugState); + } + }); + debugState = @"pKOA E"; + CFRunLoopRun(); + debugState = @"pKOA F"; + notify_cancel(backupStateChangeToken); + } + } + debugState = @"pKOA Z"; +} + +static bool processEvents() +{ + debugState = @"processEvents A"; + CFErrorRef error = NULL; + CFErrorRef departError = NULL; + SOSCCStatus circleStatus = SOSCCThisDeviceIsInCircle(&error); + NSDate *nowish = [NSDate date]; + PersistantState *state = [PersistantState loadFromStorage]; + enum DepartureReason departureReason = SOSCCGetLastDepartureReason(&departError); + NSLog(@"CircleStatus %d -> %d{%d} (s=%p)", state.lastCircleStatus, circleStatus, departureReason, state); + + NSTimeInterval timeUntilApplicationAlert = [state.pendingApplicationReminder timeIntervalSinceDate:nowish]; + + NSLog(@"Time until pendingApplicationReminder (%@) %f", [state.pendingApplicationReminder debugDescription], timeUntilApplicationAlert); + + if (circleStatus == kSOSCCRequestPending && timeUntilApplicationAlert <= 0) { + debugState = @"reminderAlert"; + postApplicationReminderAlert(nowish, state, state.pendingApplicationReminderAlertInterval); + } else if (circleStatus == kSOSCCRequestPending) { + scheduleActivity(ceil(timeUntilApplicationAlert)); + } + + if (((circleStatus == kSOSCCNotInCircle || circleStatus == kSOSCCCircleAbsent) && state.lastCircleStatus == kSOSCCInCircle) || state.debugShowLeftReason || (circleStatus == kSOSCCNotInCircle && state.lastCircleStatus == kSOSCCCircleAbsent && state.absentCircleWithNoReason)) { + debugState = @"processEvents B"; + // Use to be in the circle, now we aren't. We ought to tell the user why. + + if (state.debugShowLeftReason) { + NSLog(@"debugShowLeftReason is %@", state.debugShowLeftReason); + departureReason = [state.debugShowLeftReason intValue]; + state.debugShowLeftReason = nil; + departError = NULL; + [state writeToStorage]; + } + + if (kSOSDepartureReasonError != departureReason) { + if (circleStatus == kSOSCCCircleAbsent && departureReason == kSOSNeverLeftCircle) { + // We don't yet know why the circle has vanished, remember our current ignorance + state.absentCircleWithNoReason = YES; + } else { + state.absentCircleWithNoReason = NO; + } + NSLog(@"Depature reason %d", departureReason); + postKickedOutAlert(departureReason); + NSLog(@"pKOA returned (cS %d lCS %d)", circleStatus, state.lastCircleStatus); + } else { + NSLog(@"Can't get last depature reason: %@", departError); + } + } + + debugState = @"processEvents C"; + + if (circleStatus != state.lastCircleStatus) { + SOSCCStatus lastCircleStatus = state.lastCircleStatus; + state.lastCircleStatus = circleStatus; + + if (lastCircleStatus != kSOSCCRequestPending && circleStatus == kSOSCCRequestPending) { + state.applcationDate = nowish; + state.pendingApplicationReminder = [nowish dateByAddingTimeInterval: state.pendingApplicationReminderAlertInterval]; + scheduleActivity(state.pendingApplicationReminderAlertInterval); + } + if (lastCircleStatus == kSOSCCRequestPending && circleStatus != kSOSCCRequestPending) { + NSLog(@"Pending request completed"); + state.applcationDate = [NSDate distantPast]; + state.pendingApplicationReminder = [NSDate distantFuture]; + } + + [state writeToStorage]; + } + + if (circleStatus != kSOSCCInCircle) { + if (circleStatus == kSOSCCRequestPending && currentAlert) { + int notifyToken = 0; + CFUserNotificationRef postedAlert = currentAlert; + + debugState = @"processEvents D1"; + notify_register_dispatch(kSOSCCCircleChangedNotification, ¬ifyToken, dispatch_get_main_queue(), ^(int token) { + if (postedAlert != currentAlert) { + NSLog(@"-- CC after original alert gone (currentAlertIsForApplicants %d, pA %p, cA %p -- %@)", currentAlertIsForApplicants ? 1:0, postedAlert, currentAlert, currentAlert); + notify_cancel(token); + } else { + CFErrorRef localError = NULL; + SOSCCStatus newCircleStatus = SOSCCThisDeviceIsInCircle(&localError); + if (newCircleStatus != kSOSCCRequestPending) { + if (newCircleStatus == kSOSCCError) + NSLog(@"No longer pending (nCS=%d, alert=%@) error: %@", newCircleStatus, currentAlert, localError); + else + NSLog(@"No longer pending (nCS=%d, alert=%@)", newCircleStatus, currentAlert); + cancelCurrentAlert(true); + } else { + NSLog(@"Still pending..."); + } + } + }); + debugState = @"processEvents D2"; + NSLog(@"NOTE: currentAlertIsForApplicants %d, token %d", currentAlertIsForApplicants ? 1:0, notifyToken); + CFRunLoopRun(); + return true; + } + debugState = @"processEvents D3"; + NSLog(@"SOSCCThisDeviceIsInCircle status %d, not checking applicants", circleStatus); + return false; + } + + debugState = @"processEvents E"; + applicants = [NSMutableDictionary new]; + for (id applicantInfo in (__bridge_transfer NSArray *)(SOSCCCopyApplicantPeerInfo(&error))) { + Applicant *applicant = [[Applicant alloc] initWithPeerInfo:(__bridge SOSPeerInfoRef)(applicantInfo)]; + applicants[applicant.idString] = applicant; + } + + int notify_token = -42; + debugState = @"processEvents F"; + int notify_register_status = notify_register_dispatch(kSOSCCCircleChangedNotification, ¬ify_token, dispatch_get_main_queue(), ^(int token) { + NSLog(@"Notified: %s", kSOSCCCircleChangedNotification); + CFErrorRef circleStatusError = NULL; + + bool needsUpdate = false; + CFErrorRef copyPeerError = NULL; + NSMutableSet *newIds = [NSMutableSet new]; + for (id applicantInfo in (__bridge_transfer NSArray *)(SOSCCCopyApplicantPeerInfo(©PeerError))) { + Applicant *newApplicant = [[Applicant alloc] initWithPeerInfo:(__bridge SOSPeerInfoRef)(applicantInfo)]; + [newIds addObject:newApplicant.idString]; + Applicant *existingApplicant = applicants[newApplicant.idString]; + if (existingApplicant) { + switch (existingApplicant.applicantUIState) { + case ApplicantWaiting: + applicants[newApplicant.idString] = newApplicant; + break; + + case ApplicantOnScreen: + newApplicant.applicantUIState = ApplicantOnScreen; + applicants[newApplicant.idString] = newApplicant; + break; + + default: + NSLog(@"Update to %@ >> %@ with pending order, should work out Ok though", existingApplicant, newApplicant); + break; + } + } else { + needsUpdate = true; + applicants[newApplicant.idString] = newApplicant; + } + } + if (copyPeerError) { + NSLog(@"Could not update peer info array: %@", copyPeerError); + return; + } + + NSMutableArray *idsToRemoveFromApplicants = [NSMutableArray new]; + for (NSString *exisitngId in [applicants keyEnumerator]) { + if (![newIds containsObject:exisitngId]) { + [idsToRemoveFromApplicants addObject:exisitngId]; + needsUpdate = true; + } + } + [applicants removeObjectsForKeys:idsToRemoveFromApplicants]; + + if (newIds.count == 0) { + NSLog(@"All applicants were handled elsewhere"); + cancelCurrentAlert(true); + } + SOSCCStatus currentCircleStatus = SOSCCThisDeviceIsInCircle(&circleStatusError); + if (kSOSCCInCircle != currentCircleStatus) { + NSLog(@"Left circle (%d), not handing remaining %lu applicants", currentCircleStatus, (unsigned long)newIds.count); + cancelCurrentAlert(true); + } + if (needsUpdate) { + askAboutAll(false); + } else { + NSLog(@"needsUpdate false, not updating alert"); + } + }); + NSLog(@"ACC token %d, status %d", notify_token, notify_register_status); + debugState = @"processEvents F2"; + + if (applicants.count == 0) { + NSLog(@"No applicants"); + } else { + debugState = @"processEvents F3"; + askAboutAll(false); + debugState = @"processEvents F4"; + if (currentAlert) { + debugState = @"processEvents F5"; + CFRunLoopRun(); + } + } + + debugState = @"processEvents F6"; + notify_cancel(notify_token); + debugState = @"processEvents DONE"; + + return false; +} + +int main (int argc, const char * argv[]) +{ + @autoreleasepool { + xpc_transaction_begin(); + + // NOTE: DISPATCH_QUEUE_PRIORITY_LOW will not actually manage to drain events + // in a lot of cases (like circleStatus != kSOSCCInCircle) + xpc_set_event_stream_handler("com.apple.notifyd.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(xpc_object_t object) { + char *event_description = xpc_copy_description(object); + NSLog(@"notifyd event: %s\nAlert (%p) %s %s\ndebugState: %@", event_description, currentAlert, currentAlertIsForApplicants ? "for applicants" : "!applicants", currentAlertIsForKickOut ? "KO" : "!KO", debugState); + free(event_description); + }); + + xpc_activity_register(kLaunchLaterXPCName, XPC_ACTIVITY_CHECK_IN, ^(xpc_activity_t activity) { + }); + + + int falseInARow = 0; + while (falseInARow < 2) { + if (processEvents()) { + falseInARow = 0; + } else { + falseInARow++; + } + cancelCurrentAlert(false); + if (doOnceInMainBlockChain) { + doOnceInMainBlockChain(); + doOnceInMainBlockChain = NULL; + } + } + } + + NSLog(@"Done"); + xpc_transaction_end(); + return(0); +} diff --git a/CircleJoinRequested/Info.plist b/CircleJoinRequested/Info.plist new file mode 100644 index 00000000..cb617beb --- /dev/null +++ b/CircleJoinRequested/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleAllowMixedLocalizations + + CFBundleDevelopmentRegion + English + CFBundleExecutable + CircleJoinRequested + CFBundleIconFile + + CFBundleIdentifier + com.apple.security.CircleJoinRequested + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + CircleJoinRequested + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/CircleJoinRequested/NSArray+map.h b/CircleJoinRequested/NSArray+map.h new file mode 100644 index 00000000..281959c4 --- /dev/null +++ b/CircleJoinRequested/NSArray+map.h @@ -0,0 +1,15 @@ +// +// NSArray+map.h +// Security +// +// Created by J Osborne on 3/8/13. +// Copyright (c) 2013 Apple Inc. All Rights Reserved. +// + +#import + +typedef id (^mapBlock)(id obj); + +@interface NSArray (map) +-(NSArray*)mapWithBlock:(mapBlock)block; +@end diff --git a/CircleJoinRequested/NSArray+map.m b/CircleJoinRequested/NSArray+map.m new file mode 100644 index 00000000..68069ef8 --- /dev/null +++ b/CircleJoinRequested/NSArray+map.m @@ -0,0 +1,24 @@ +// +// NSArray+map.m +// Security +// +// Created by J Osborne on 3/8/13. +// Copyright (c) 2013 Apple Inc. All Rights Reserved. +// + +#import "NSArray+map.h" + +@implementation NSArray (map) + +-(NSArray*)mapWithBlock:(mapBlock)block +{ + NSMutableArray *results = [[NSMutableArray alloc] initWithCapacity:self.count]; + + for (id obj in self) { + [results addObject:block(obj)]; + } + + return [results copy]; +} + +@end diff --git a/CircleJoinRequested/NSDate+TimeIntervalDescription.h b/CircleJoinRequested/NSDate+TimeIntervalDescription.h new file mode 100644 index 00000000..551fa2e8 --- /dev/null +++ b/CircleJoinRequested/NSDate+TimeIntervalDescription.h @@ -0,0 +1,13 @@ +// +// NSDate+TimeIntervalDescription.h +// Security +// +// Created by J Osborne on 7/17/13. +// +// + +#import + +@interface NSDate (TimeIntervalDescription) + -(NSString *)copyDescriptionOfIntervalSince:(NSDate*)originalDate; +@end diff --git a/CircleJoinRequested/NSDate+TimeIntervalDescription.m b/CircleJoinRequested/NSDate+TimeIntervalDescription.m new file mode 100644 index 00000000..aad74451 --- /dev/null +++ b/CircleJoinRequested/NSDate+TimeIntervalDescription.m @@ -0,0 +1,46 @@ +// +// NSDate+TimeIntervalDescription.m +// Security +// +// Created by J Osborne on 7/17/13. +// +// + +#import "NSDate+TimeIntervalDescription.h" +#include +#import +#import + +@implementation NSDate (TimeIntervalDescription) + +-(NSString*)copyDescriptionOfIntervalSince:(NSDate *)originalDate +{ + // This is really expected to be "1 day", "N days" in production, but for testing we + // use very small intervals, and we may as well have that work out. + + NSTimeInterval seconds = [self timeIntervalSinceDate:originalDate]; + if (seconds <= 0) { + return (__bridge_transfer NSString*)SecCopyCKString(SEC_CK_TID_FUTURE); + } + if (seconds == 0) { + return (__bridge_transfer NSString*)SecCopyCKString(SEC_CK_TID_NOW); + } + if (seconds < 1) { + return (__bridge_transfer NSString*)SecCopyCKString(SEC_CK_TID_SUBSECOND); + } + if (seconds < 120) { + return [NSString stringWithFormat:@"%d %@", (int)seconds, (__bridge_transfer NSString*)SecCopyCKString(SEC_CK_TID_SECONDS)]; + } + if (seconds < 2*60*60) { + return [NSString stringWithFormat:@"%d %@", (int)seconds/60, (__bridge_transfer NSString*)SecCopyCKString(SEC_CK_TID_MINUTES)]; + } + if (seconds < 60*60*24) { + return [NSString stringWithFormat:@"%d %@", (int)seconds/(60*60), (__bridge_transfer NSString*)SecCopyCKString(SEC_CK_TID_HOURS)]; + } + + double days = nearbyint(seconds/(60*60*24)); + // XXX "day" vs. "days" + return [NSString stringWithFormat:@"%.0f %@", days, (days == 1) ? (__bridge_transfer NSString*)SecCopyCKString(SEC_CK_TID_DAY) : (__bridge_transfer NSString*)SecCopyCKString(SEC_CK_TID_DAYS)]; +} + +@end diff --git a/CircleJoinRequested/PersistantState.h b/CircleJoinRequested/PersistantState.h new file mode 100644 index 00000000..0915fcb7 --- /dev/null +++ b/CircleJoinRequested/PersistantState.h @@ -0,0 +1,25 @@ +// +// PersistantState.h +// Security +// +// Created by J Osborne on 7/11/13. +// +// + +#import +#include "SecureObjectSync/SOSCloudCircle.h" +#include "SecureObjectSync/SOSPeerInfo.h" + +@interface PersistantState : NSObject ++(instancetype)loadFromStorage; +-(unsigned int)defaultPendingApplicationReminderAlertInterval; +-(void)writeToStorage; + +@property SOSCCStatus lastCircleStatus; +@property NSDate *lastWritten; +@property NSDate *pendingApplicationReminder; +@property unsigned int pendingApplicationReminderAlertInterval; +@property NSDate *applcationDate; +@property NSNumber *debugShowLeftReason; +@property BOOL absentCircleWithNoReason; +@end diff --git a/CircleJoinRequested/PersistantState.m b/CircleJoinRequested/PersistantState.m new file mode 100644 index 00000000..733e3c08 --- /dev/null +++ b/CircleJoinRequested/PersistantState.m @@ -0,0 +1,90 @@ +// +// PersistantState.m +// Security +// +// Created by J Osborne on 7/11/13. +// +// + +#import "PersistantState.h" +#import + +@interface PersistantState() +-(NSURL*)urlForStorage; +@end + +@implementation PersistantState + +-(NSURL*)urlForStorage +{ + return [NSURL fileURLWithPath:@"/var/mobile/Library/Preferences/com.apple.security.CircleJoinRequested.plist" isDirectory:NO]; +} + +-(unsigned int)defaultPendingApplicationReminderAlertInterval +{ + return 60 * 60 * 24 * 2; +} + ++(instancetype)loadFromStorage +{ + PersistantState *state = [[PersistantState alloc] init]; + if (!state) { + return state; + } + + NSError *error = nil; + id plist = @{@"lastWritten": [NSDate distantPast]}; + + NSData *stateData = [NSData dataWithContentsOfURL:[state urlForStorage] options:0 error:&error]; + if (!stateData) { + NSLog(@"Can't read state data (p=%@, err=%@)", [state urlForStorage], error); + } else { + NSPropertyListFormat format; + id plistTmp = [NSPropertyListSerialization propertyListWithData:stateData options: NSPropertyListMutableContainersAndLeaves format:&format error:&error]; + + if (plistTmp == nil) { + NSLog(@"Can't deserialize %@, e=%@", stateData, error); + } else { + plist = plistTmp; + } + } + + state.lastCircleStatus = plist[@"lastCircleStatus"] ? [plist[@"lastCircleStatus"] intValue] : kSOSCCCircleAbsent; + state.lastWritten = plist[@"lastWritten"]; + state.pendingApplicationReminder = plist[@"pendingApplicationReminder"] ? plist[@"pendingApplicationReminder"] : [NSDate distantFuture]; + state.applcationDate = plist[@"applcationDate"] ? plist[@"applcationDate"] : [NSDate distantPast]; + state.debugShowLeftReason = plist[@"debugShowLeftReason"]; + state.pendingApplicationReminderAlertInterval = plist[@"pendingApplicationReminderAlertInterval"] ? [plist[@"pendingApplicationReminderAlertInterval"] unsignedIntValue] : [state defaultPendingApplicationReminderAlertInterval]; + state.absentCircleWithNoReason = plist[@"absentCircleWithNoReason"] ? [plist[@"absentCircleWithNoReason"] intValue] : NO; + + return state; +} + +-(void)writeToStorage +{ + NSDictionary *plist = @{@"lastCircleStatus": [NSNumber numberWithInt:self.lastCircleStatus], + @"lastWritten": [NSDate date], + @"pendingApplicationReminder": self.pendingApplicationReminder ? self.pendingApplicationReminder : [NSDate distantFuture], + @"applcationDate": self.applcationDate ? self.applcationDate : [NSDate distantPast], + @"pendingApplicationReminderAlertInterval": [NSNumber numberWithUnsignedInt:self.pendingApplicationReminderAlertInterval], + @"absentCircleWithNoReason": [NSNumber numberWithBool:self.absentCircleWithNoReason] + }; + if (self.debugShowLeftReason) { + NSMutableDictionary *tmp = [plist mutableCopy]; + tmp[@"debugShowLeftReason"] = self.debugShowLeftReason; + plist =[tmp copy]; + } + NSLog(@"writeToStorage plist=%@", plist); + + NSError *error = nil; + NSData *stateData = [NSPropertyListSerialization dataWithPropertyList:plist format:NSPropertyListXMLFormat_v1_0 options:kCFPropertyListImmutable error:&error]; + if (!stateData) { + NSLog(@"Can't serialize %@: %@", plist, error); + return; + } + if (![stateData writeToURL:[self urlForStorage] options:NSDataWritingAtomic error:&error]) { + NSLog(@"Can't write to %@, error=%@", [self urlForStorage], error); + } +} + +@end diff --git a/CircleJoinRequested/Readme.txt b/CircleJoinRequested/Readme.txt new file mode 100644 index 00000000..e69de29b diff --git a/CircleJoinRequested/com.apple.security.CircleJoinRequested.plist b/CircleJoinRequested/com.apple.security.CircleJoinRequested.plist new file mode 100644 index 00000000..10ce645e --- /dev/null +++ b/CircleJoinRequested/com.apple.security.CircleJoinRequested.plist @@ -0,0 +1,37 @@ + + + + + UserName + mobile + Label + com.apple.security.CircleJoinRequested + enabletransactions + + ProgramArguments + + /System/Library/Frameworks/Security.framework/CircleJoinRequested/CircleJoinRequested + + LaunchEvents + + com.apple.notifyd.matching + + com.apple.mobile.keybagd.first_unlock + + Notification + com.apple.mobile.keybagd.first_unlock + + TICK + + Notification + com.apple.security.tick + + kSOSCCCircleChangedNotification + + Notification + com.apple.security.secureobjectsync.circlechanged + + + + + diff --git a/CircleJoinRequested/entitlements.plist b/CircleJoinRequested/entitlements.plist new file mode 100644 index 00000000..489658ce --- /dev/null +++ b/CircleJoinRequested/entitlements.plist @@ -0,0 +1,16 @@ + + + + + com.apple.private.accounts.allaccounts + + application-identifier + CircleJoinRequested + keychain-cloud-circle + + com.apple.springboard.opensensitiveurl + + com.apple.securebackupd.access + + + diff --git a/CloudKeychainProxy/CloudKeychainProxy-Info.plist b/CloudKeychainProxy/CloudKeychainProxy-Info.plist index 116d48a1..132f0435 100644 --- a/CloudKeychainProxy/CloudKeychainProxy-Info.plist +++ b/CloudKeychainProxy/CloudKeychainProxy-Info.plist @@ -17,12 +17,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.0 + 10.0 CFBundleSignature ???? CFBundleVersion - 55471.14.18 - NSHumanReadableCopyright - Copyright © 2013 Apple, Inc. All rights reserved. + ${CURRENT_PROJECT_VERSION} diff --git a/CloudKeychainProxy/CloudKeychainProxy.1 b/CloudKeychainProxy/CloudKeychainProxy.1 new file mode 100644 index 00000000..e2565fb7 --- /dev/null +++ b/CloudKeychainProxy/CloudKeychainProxy.1 @@ -0,0 +1,79 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. +.\"See Also: +.\"man mdoc.samples for a complete listing of options +.\"man mdoc for the short list of editing options +.\"/usr/share/misc/mdoc.template +.Dd 1/15/13 \" DATE +.Dt CloudKeychainProxy 1 \" Program name and manual section number +.Os Darwin +.Sh NAME \" Section Header - required - don't modify +.Nm CloudKeychainProxy, +.\" The following lines are read in generating the apropos(man -k) database. Use only key +.\" words here as the database is built based on the words here and in the .ND line. +.Nm Other_name_for_same_program(), +.Nm Yet another name for the same program. +.\" Use .Nm macro to designate other names for the documented program. +.Nd This line parsed for whatis database. +.Sh SYNOPSIS \" Section Header - required - don't modify +.Nm +.Op Fl abcd \" [-abcd] +.Op Fl a Ar path \" [-a path] +.Op Ar file \" [file] +.Op Ar \" [file ...] +.Ar arg0 \" Underlined argument - use .Ar anywhere to underline +arg2 ... \" Arguments +.Sh DESCRIPTION \" Section Header - required - don't modify +Use the .Nm macro to refer to your program throughout the man page like such: +.Nm +Underlining is accomplished with the .Ar macro like this: +.Ar underlined text . +.Pp \" Inserts a space +A list of items with descriptions: +.Bl -tag -width -indent \" Begins a tagged list +.It item a \" Each item preceded by .It macro +Description of item a +.It item b +Description of item b +.El \" Ends the list +.Pp +A list of flags and their descriptions: +.Bl -tag -width -indent \" Differs from above in tag removed +.It Fl a \"-a flag as a list item +Description of -a flag +.It Fl b +Description of -b flag +.El \" Ends the list +.Pp +.\" .Sh ENVIRONMENT \" May not be needed +.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 +.\" .It Ev ENV_VAR_1 +.\" Description of ENV_VAR_1 +.\" .It Ev ENV_VAR_2 +.\" Description of ENV_VAR_2 +.\" .El +.Sh FILES \" File used or created by the topic of the man page +.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact +.It Pa /usr/share/file_name +FILE_1 description +.It Pa /Users/joeuser/Library/really_long_file_name +FILE_2 description +.El \" Ends the list +.\" .Sh DIAGNOSTICS \" May not be needed +.\" .Bl -diag +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .El +.Sh SEE ALSO +.\" List links in ascending order by section, alphabetically within a section. +.\" Please do not reference files that do not exist without filing a bug report +.Xr a 1 , +.Xr b 1 , +.Xr c 1 , +.Xr a 2 , +.Xr b 2 , +.Xr a 3 , +.Xr b 3 +.\" .Sh BUGS \" Document known, unremedied bugs +.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file diff --git a/CloudKeychainProxy/cloudkeychain.entitlements.plist b/CloudKeychainProxy/cloudkeychain.entitlements.plist deleted file mode 100644 index f09dd1b8..00000000 --- a/CloudKeychainProxy/cloudkeychain.entitlements.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - keychain-sync-updates - - application-identifier - com.apple.security.cloudkeychainproxy3 - sync-keychain - - keychain-access-groups - - sync - * - - com.apple.developer.ubiquity-container-identifiers - - com.apple.security.cloudkeychainproxy3 - com.apple.security.cloudkeychain - - com.apple.developer.ubiquity-kvstore-identifier - com.apple.security.cloudkeychainproxy3 - - diff --git a/CloudKeychainProxy/com.apple.security.cloudkeychainproxy.plist b/CloudKeychainProxy/com.apple.security.cloudkeychainproxy.plist index d23581fb..b0347db0 100644 --- a/CloudKeychainProxy/com.apple.security.cloudkeychainproxy.plist +++ b/CloudKeychainProxy/com.apple.security.cloudkeychainproxy.plist @@ -2,11 +2,11 @@ - LimitLoadToSessionType - Background + EnablePressuredExit + ProgramArguments - /System/Library/Frameworks/Security.framework/Versions/A/Resources/CloudKeychainProxy.bundle/Contents/MacOS/CloudKeychainProxy + /System/Library/Frameworks/Security.framework/CloudKeychainProxy.bundle/CloudKeychainProxy MachServices @@ -15,10 +15,10 @@ RunAtLoad - KeepAlive - + enabletransactions + Program - /System/Library/Frameworks/Security.framework/Versions/A/Resources/CloudKeychainProxy.bundle/Contents/MacOS/CloudKeychainProxy + /System/Library/Frameworks/Security.framework/CloudKeychainProxy.bundle/CloudKeychainProxy Label com.apple.security.cloudkeychainproxy3 EnvironmentVariables @@ -32,10 +32,10 @@ com.apple.notifyd.matching - com.apple.keystore.lockstatus + com.apple.mobile.keybagd.lock_status Notification - com.apple.keystore.lockstatus + com.apple.mobile.keybagd.lock_status com.apple.security.cloudkeychainproxy.kvstorechange3 diff --git a/Default-568h@2x.png b/Default-568h@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0891b7aabfcf3422423b109c8beed2bab838c607 GIT binary patch literal 18594 zcmeI4X;f257Jx&9fS`ixvS;&$x8J@slQFSel)6zJN=?13FB7H(lQjRkSy8x_-S~tvu2gzn1oS+dLcF#eqtq$ z%tf9TTvX?`)R@}3uBI;jzS-=ZR-Td&MHaS&;!0?Ni*#$#`n*~CcQK)Q9vAQ~TUpnI!j)a2biYK^R)M~A5wUDZhx?ULMX z3x1P&qt=trOY6P2U67L=m=U?F|5#Uj(eCueNTZaHs_ceWiHeET+j+tp3Jt9g(ekqP z2WOvfR{qV+9r+o4J5?qK>7;;^+I7tGv-i)es$X_D=EoKF+S?zsyj^oRFElP}c}JT< zd8SUs-?O?}2YD#ngKbnHgzHBcboxK_2r9l(?eNCl-pEzkJm}fY?WC*jnS?VBE4EpY zO$fEejz6fU;W2Kl>JeQBZBl-%Irg`obSlg*@4QB;Dd1H7^Oi5wvt4d{RZ!8Og?^aE z)k0$1g+V3fd(gdQ3d&q2q-FL*uy#}|bc^=VhFsl0jBgUGJ+-s3U8MK9A!YJJMxpci z5hJ%|{DwV48fZn0{n5l$N_KcSb#NKE4plB`9I6Zt=Z!~-zw0{9tg$L&Ju1F0X)Cy8 zKF;(&lJ>x)Jw(=;p~sF(Sd9VWGwFE2rnyS9!f^DZ8+aCLq zQ};>lcJ1GDLqjm6Hd>|Eabno@P`~Bn(~6^aD_#yoEH(a?Nm1S<;S+hSxI5d16^<1lEM3NPFi zkqPrpL)+ zgnseFikg`gJVBha1&7C4;O6>h=dt~`ND+;Zd?W(4v2JIb7Pt>Td42%M-Ju-XAH#Pns762L}K3 zDhvsRqN0Ni(1UrishD2YvV?4*h2iFj$+&N||Fn$4n|^NSU+o?~jq`0jVQt8T9l{7b zXiwwODFh2V!Q6sqP9S>WH$oOf$N~=d0-bqTlD61!=`&0eAP-F>XN?*|gtOXX{ zQVTWyYo4ZK0GAw!GHf|pz9`D;-bbb*5LBX*{bnz|+)$@&P9|ORM2o?95{;ejvo&r- zq8cBhTN6nn)7~W>54U)%-F_-b?YKdfk5I8MHcuzBD5)!;yv#Z&R&^y=@=>VTIMy#r zX&U<=BsPkdqcMe<_}2+>H%XKyrr5ZR8_KVe>ZqYN z^=^~TFD};;rHJ$U;{~w^hYojl4hRI@SH$^K{YEo=sg)WY87r!*7blQK&qnpDo0`Vn zkl)9u9g=mCh&ZCJS(L4yN3k0kQ zuvg$h2KEEk51T+O0JQ+r0`R>g{jvqM0Mr6d3qUOZwE!?PI7HY@CE|dr sfw?Q;rAv?G4&^^8-z_>&sWXMxvD*gPOU4CBe-*@OtE+wfmVJNyHv)PfH~;_u literal 0 HcmV?d00001 diff --git a/Keychain Circle Notification/CloudKeychain.icns b/Keychain Circle Notification/CloudKeychain.icns deleted file mode 100644 index 97fe7c7875a561d94dceebdef5f6bd784bbef6c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 159530 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�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 -#import -#import "KNPersistantState.h" - -@class KDSecCircle; - -@interface KNAppDelegate : NSObject - -@property (assign) IBOutlet NSWindow *window; -@property (retain) KDSecCircle *circle; -@property (retain) NSMutableSet *viewedIds; -@property (retain) KNPersistantState *state; - -@end diff --git a/Keychain Circle Notification/KNPersistantState.h b/Keychain Circle Notification/KNPersistantState.h deleted file mode 100644 index ad842485..00000000 --- a/Keychain Circle Notification/KNPersistantState.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// KNPersistantState.h -// Security -// -// Created by J Osborne on 7/28/13. -// -// - -#import -#include "SecureObjectSync/SOSCloudCircle.h" -#include "SecureObjectSync/SOSPeerInfo.h" - -@interface KNPersistantState : NSObject -+(instancetype)loadFromStorage; --(void)writeToStorage; - -@property SOSCCStatus lastCircleStatus; -@property NSNumber *debugLeftReason; -@property NSNumber *pendingApplicationReminderInterval; -@property NSDate *pendingApplicationReminder; -@property NSDate *applcationDate; -@property NSDate *lastWritten; -@end diff --git a/Keychain Circle Notification/NSArray+mapWithBlock.h b/Keychain Circle Notification/NSArray+mapWithBlock.h deleted file mode 100644 index 03d342ba..00000000 --- a/Keychain Circle Notification/NSArray+mapWithBlock.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// NSArray+mapWithBlock.h -// Security -// -// Created by J Osborne on 2/26/13. -// -// - -#import - -typedef id (^mapBlock)(id obj); - -@interface NSArray (mapWithBlock) --(NSArray*)mapWithBlock:(mapBlock)block; -@end diff --git a/Keychain Circle Notification/NSArray+mapWithBlock.m b/Keychain Circle Notification/NSArray+mapWithBlock.m deleted file mode 100644 index 0ec2e6d1..00000000 --- a/Keychain Circle Notification/NSArray+mapWithBlock.m +++ /dev/null @@ -1,24 +0,0 @@ -// -// NSArray+mapWithBlock.m -// Security -// -// Created by J Osborne on 2/26/13. -// -// - -#import "NSArray+mapWithBlock.h" - -@implementation NSArray (mapWithBlock) - --(NSArray*)mapWithBlock:(mapBlock)block -{ - NSMutableArray *mapped = [[NSMutableArray alloc] initWithCapacity:self.count]; - - for (id obj in self) { - [mapped addObject:block(obj)]; - } - - return [mapped copy]; -} - -@end diff --git a/Keychain Circle Notification/NSDictionary+compactDescription.h b/Keychain Circle Notification/NSDictionary+compactDescription.h deleted file mode 100644 index 1cd252d4..00000000 --- a/Keychain Circle Notification/NSDictionary+compactDescription.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// NSDictionary+compactDescription.h -// KeychainMigrator -// -// Created by J Osborne on 2/19/13. -// -// - -#import - -@interface NSDictionary (compactDescription) --(NSString*)compactDescription; --(NSString*)compactDescriptionWithoutItemData; -@end diff --git a/Keychain Circle Notification/NSDictionary+compactDescription.m b/Keychain Circle Notification/NSDictionary+compactDescription.m deleted file mode 100644 index 9b47d51a..00000000 --- a/Keychain Circle Notification/NSDictionary+compactDescription.m +++ /dev/null @@ -1,52 +0,0 @@ -// -// NSDictionary+compactDescription.m -// KeychainMigrator -// -// Created by J Osborne on 2/19/13. -// -// - -#import "NSDictionary+compactDescription.h" -#import "NSString+compactDescription.h" - -@implementation NSDictionary (compactDescription) - --(NSString*)compactDescription -{ - NSMutableArray *results = [NSMutableArray new]; - for (NSString *k in self) { - id v = self[k]; - if ([v respondsToSelector:@selector(compactDescription)]) { - v = [v compactDescription]; - } else { - v = [v description]; - } - - [results addObject:[NSString stringWithFormat:@"%@=%@", [k compactDescription], v]]; - } - return [NSString stringWithFormat:@"{%@}", [results componentsJoinedByString:@", "]]; -} - --(NSString*)compactDescriptionWithoutItemData; -{ - NSMutableArray *results = [NSMutableArray new]; - for (NSString *k in self) { - if ([k isEqualToString:kSecValueData]) { - [results addObject:[NSString stringWithFormat:@"%@=", [k compactDescription]]]; - continue; - } - - id v = self[k]; - if ([v respondsToSelector:@selector(compactDescription)]) { - v = [v compactDescription]; - } else { - v = [v description]; - } - - [results addObject:[NSString stringWithFormat:@"%@=%@", [k compactDescription], v]]; - } - return [NSString stringWithFormat:@"{%@}", [results componentsJoinedByString:@", "]]; - -} - -@end diff --git a/Keychain Circle Notification/NSSet+compactDescription.h b/Keychain Circle Notification/NSSet+compactDescription.h deleted file mode 100644 index 851dab02..00000000 --- a/Keychain Circle Notification/NSSet+compactDescription.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// NSSet+compactDescription.h -// KeychainMigrator -// -// Created by J Osborne on 3/21/13. -// -// - -#import - -@interface NSSet (compactDescription) --(NSString*)compactDescription; -@end diff --git a/Keychain Circle Notification/NSSet+compactDescription.m b/Keychain Circle Notification/NSSet+compactDescription.m deleted file mode 100644 index 2c521f7d..00000000 --- a/Keychain Circle Notification/NSSet+compactDescription.m +++ /dev/null @@ -1,26 +0,0 @@ -// -// NSSet+compactDescription.m -// KeychainMigrator -// -// Created by J Osborne on 3/21/13. -// -// - -#import "NSSet+compactDescription.h" - -@implementation NSSet (compactDescription) - --(NSString*)compactDescription -{ - NSMutableArray *results = [NSMutableArray new]; - for (id v in self) { - if ([v respondsToSelector:@selector(compactDescription)]) { - [results addObject:[v compactDescription]]; - } else { - [results addObject:[v description]]; - } - } - return [NSString stringWithFormat:@"[%@]", [results componentsJoinedByString:@", "]]; -} - -@end diff --git a/Keychain Circle Notification/NSString+compactDescription.h b/Keychain Circle Notification/NSString+compactDescription.h deleted file mode 100644 index d810558b..00000000 --- a/Keychain Circle Notification/NSString+compactDescription.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// NSString+compactDescription.h -// KeychainMigrator -// -// Created by J Osborne on 2/19/13. -// -// - -#import - -@interface NSString (compactDescription) --(NSString*)compactDescription; -@end diff --git a/Keychain Circle Notification/NSString+compactDescription.m b/Keychain Circle Notification/NSString+compactDescription.m deleted file mode 100644 index 52b242df..00000000 --- a/Keychain Circle Notification/NSString+compactDescription.m +++ /dev/null @@ -1,30 +0,0 @@ -// -// NSString+compactDescription.m -// KeychainMigrator -// -// Created by J Osborne on 2/19/13. -// -// - -#import "NSString+compactDescription.h" - -@implementation NSString (compactDescription) - --(NSString*)compactDescription -{ - static NSCharacterSet *forceQuotes = nil; - static dispatch_once_t setup; - dispatch_once(&setup, ^{ - forceQuotes = [NSCharacterSet characterSetWithCharactersInString:@"\"' \t\n\r="]; - }); - - if ([self rangeOfCharacterFromSet:forceQuotes].location != NSNotFound) { - NSString *escaped = [self stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; - escaped = [escaped stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; - return [NSString stringWithFormat:@"\"%@\"", escaped]; - } else { - return self; - } -} - -@end diff --git a/Keychain Circle Notification/main.m b/Keychain Circle Notification/main.m deleted file mode 100644 index a6473303..00000000 --- a/Keychain Circle Notification/main.m +++ /dev/null @@ -1,14 +0,0 @@ -// -// main.m -// Keychain Circle Notification -// -// Created by J Osborne on 2/21/13. -// -// - -#import - -int main(int argc, char *argv[]) -{ - return NSApplicationMain(argc, (const char **)argv); -} diff --git a/Keychain/AppDelegate.h b/Keychain/AppDelegate.h new file mode 100644 index 00000000..899f8345 --- /dev/null +++ b/Keychain/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// Keychain +// +// Created by john on 10/22/12. +// +// + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + +@end diff --git a/Keychain/AppDelegate.m b/Keychain/AppDelegate.m new file mode 100644 index 00000000..037005d0 --- /dev/null +++ b/Keychain/AppDelegate.m @@ -0,0 +1,46 @@ +// +// AppDelegate.m +// Keychain +// +// Created by john on 10/22/12. +// +// + +#import "AppDelegate.h" + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application +{ + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application +{ + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application +{ + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/Keychain/CircleStatusView.h b/Keychain/CircleStatusView.h new file mode 100644 index 00000000..602002ee --- /dev/null +++ b/Keychain/CircleStatusView.h @@ -0,0 +1,25 @@ +// +// CircleStatusView.h +// Security +// +// Created by John Hurley on 12/5/12. +// +// + +#import + +@interface CircleStatusView : UIView +{ +} +@property (weak, nonatomic) UIColor *color; + +@end + +@interface ItemStatusView : UIView +{ +} +@property (weak, nonatomic) UIColor *color; + +@end + + diff --git a/Keychain/CircleStatusView.m b/Keychain/CircleStatusView.m new file mode 100644 index 00000000..ca2691e0 --- /dev/null +++ b/Keychain/CircleStatusView.m @@ -0,0 +1,75 @@ +// +// CircleStatusView.m +// Security +// +// Created by John Hurley on 12/5/12. +// +// + +#import "CircleStatusView.h" + +@implementation CircleStatusView + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + _color = [UIColor redColor]; +// NSLog(@"Frame: w: %f, h: %f", self.frame.size.width, self.frame.size.height); + } + return self; +} + +/* +// Only override drawRect: if you perform custom drawing. +// An empty implementation adversely affects performance during animation. +- (void)drawRect:(CGRect)rect +{ + // Drawing code +} +*/ + +- (void)drawRect:(CGRect)rect +{ + CGContextRef context= UIGraphicsGetCurrentContext(); + +// NSLog(@"Frame: w: %f, h: %f", self.frame.size.width, self.frame.size.height); + if (!_color) + _color= [UIColor redColor]; + CGContextSetFillColorWithColor(context, _color.CGColor); + CGContextSetAlpha(context, 0.95); + CGContextFillEllipseInRect(context, CGRectMake(0,0,self.frame.size.width,self.frame.size.height)); + + CGContextSetStrokeColorWithColor(context, _color.CGColor); + CGContextStrokeEllipseInRect(context, CGRectMake(0,0,self.frame.size.width,self.frame.size.height)); +} + +@end + +@implementation ItemStatusView + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + _color = [UIColor blueColor]; + } + return self; +} + +- (void)drawRect:(CGRect)rect +{ + CGContextRef context= UIGraphicsGetCurrentContext(); + + // NSLog(@"Frame: w: %f, h: %f", self.frame.size.width, self.frame.size.height); + if (!_color) + _color= [UIColor blueColor]; + CGContextSetFillColorWithColor(context, _color.CGColor); + CGContextSetAlpha(context, 0.95); + CGContextFillEllipseInRect(context, CGRectMake(0,0,self.frame.size.width,self.frame.size.height)); + + CGContextSetStrokeColorWithColor(context, _color.CGColor); + CGContextStrokeEllipseInRect(context, CGRectMake(0,0,self.frame.size.width,self.frame.size.height)); +} + +@end diff --git a/Keychain/Default-568h@2x.png b/Keychain/Default-568h@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0891b7aabfcf3422423b109c8beed2bab838c607 GIT binary patch literal 18594 zcmeI4X;f257Jx&9fS`ixvS;&$x8J@slQFSel)6zJN=?13FB7H(lQjRkSy8x_-S~tvu2gzn1oS+dLcF#eqtq$ z%tf9TTvX?`)R@}3uBI;jzS-=ZR-Td&MHaS&;!0?Ni*#$#`n*~CcQK)Q9vAQ~TUpnI!j)a2biYK^R)M~A5wUDZhx?ULMX z3x1P&qt=trOY6P2U67L=m=U?F|5#Uj(eCueNTZaHs_ceWiHeET+j+tp3Jt9g(ekqP z2WOvfR{qV+9r+o4J5?qK>7;;^+I7tGv-i)es$X_D=EoKF+S?zsyj^oRFElP}c}JT< zd8SUs-?O?}2YD#ngKbnHgzHBcboxK_2r9l(?eNCl-pEzkJm}fY?WC*jnS?VBE4EpY zO$fEejz6fU;W2Kl>JeQBZBl-%Irg`obSlg*@4QB;Dd1H7^Oi5wvt4d{RZ!8Og?^aE z)k0$1g+V3fd(gdQ3d&q2q-FL*uy#}|bc^=VhFsl0jBgUGJ+-s3U8MK9A!YJJMxpci z5hJ%|{DwV48fZn0{n5l$N_KcSb#NKE4plB`9I6Zt=Z!~-zw0{9tg$L&Ju1F0X)Cy8 zKF;(&lJ>x)Jw(=;p~sF(Sd9VWGwFE2rnyS9!f^DZ8+aCLq zQ};>lcJ1GDLqjm6Hd>|Eabno@P`~Bn(~6^aD_#yoEH(a?Nm1S<;S+hSxI5d16^<1lEM3NPFi zkqPrpL)+ zgnseFikg`gJVBha1&7C4;O6>h=dt~`ND+;Zd?W(4v2JIb7Pt>Td42%M-Ju-XAH#Pns762L}K3 zDhvsRqN0Ni(1UrishD2YvV?4*h2iFj$+&N||Fn$4n|^NSU+o?~jq`0jVQt8T9l{7b zXiwwODFh2V!Q6sqP9S>WH$oOf$N~=d0-bqTlD61!=`&0eAP-F>XN?*|gtOXX{ zQVTWyYo4ZK0GAw!GHf|pz9`D;-bbb*5LBX*{bnz|+)$@&P9|ORM2o?95{;ejvo&r- zq8cBhTN6nn)7~W>54U)%-F_-b?YKdfk5I8MHcuzBD5)!;yv#Z&R&^y=@=>VTIMy#r zX&U<=BsPkdqcMe<_}2+>H%XKyrr5ZR8_KVe>ZqYN z^=^~TFD};;rHJ$U;{~w^hYojl4hRI@SH$^K{YEo=sg)WY87r!*7blQK&qnpDo0`Vn zkl)9u9g=mCh&ZCJS(L4yN3k0kQ zuvg$h2KEEk51T+O0JQ+r0`R>g{jvqM0Mr6d3qUOZwE!?PI7HY@CE|dr sfw?Q;rAv?G4&^^8-z_>&sWXMxvD*gPOU4CBe-*@OtE+wfmVJNyHv)PfH~;_u literal 0 HcmV?d00001 diff --git a/Keychain/Default.png b/Keychain/Default.png new file mode 100644 index 0000000000000000000000000000000000000000..4c8ca6f693f96d511e9113c0eb59eec552354e42 GIT binary patch literal 6540 zcmeAS@N?(olHy`uVBq!ia0y~yU~~ZD2OMlbkt;o0To@QwR5G2N13aCb6#|O#(=u~X z85k@CTSM>X-wqM6>&y>YB4)1;;ojbLbbV-W^iFB1wa3^zCog^LCAReC4K0-?R_2{6 zrP*)4+_uWUy3w5N52M3PW_}MFMP9a~>YLvVZ1D_k*IMQ2QT^fwzoOb(*3gH$%aYWC zkHmcab=va2<#X%jakpJ;<1@F;k__#bwtC&%^D0v(FBh9K&$sK+<}2RJS609D)17$w ztdQP8(eLM8Ka}m_IQ@3wyMKP)l=oM4-?`YS_*P?4V_ORLPxsj&7Ju#kH;>6^Kp?T7~ zl+q?{UOOqV==?+d{=)5s|M~T1mwtH@+Z^$G&eEO9JNP^AX@3jZ*J*!!>lc|1-W%fA z@AOQpXZ_Lt>rxFXrGp*zLPiW@uo_c7C{As>j zWeX)wi+LTp_)@KYZCX{j;H?|1yXT4DnlS(Fr8gyP5|uaX_gLvaW0ScZdnG7o+u{T6 zFI-%d{ls*WuCDa5UJ@|RXv&ejZe}*BMkiWY51&pnRPw(hlykSzvj6e%mYz-GdvzBD zF10?szF_~!jS=?2HyQuPCvARXAe}C}WP|yQ*>5~~=*Nxq8+HHW1~FMDRCP^TcacKuk$ z(U#REVv)D!PhJ*ecH-ELFUrfyV&*)Z)>UCOuS?yd^L@Afk>ihynYPc{^CRwu+JHX+#$@YsC4c|l0tGigsn@jy) zXD($Ouk>H+V(Mr6NQT0S9BFM~V6nkj;1OBOz`zY;a|<&v%$g$sEJPk;hD4M^`1)8S z=jZArrsOB3>Q&?x097+E*i={nnYpPYi3%0DIeEoa6}C!X6;?ntNLXJ<0j#7X+g2&U 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 literal 0 HcmV?d00001 diff --git a/Keychain/DeviceItemCell.h b/Keychain/DeviceItemCell.h new file mode 100644 index 00000000..5da86533 --- /dev/null +++ b/Keychain/DeviceItemCell.h @@ -0,0 +1,14 @@ +// +// DeviceItemCell.h +// Security +// +// + +#import + +@interface DeviceItemCell : UITableViewCell +@property (weak, nonatomic) IBOutlet UILabel *itemDeviceName; +@property (weak, nonatomic) IBOutlet UILabel *itemPeerID; +@property (weak, nonatomic) IBOutlet UILabel *itemDeviceStatus; + +@end diff --git a/Keychain/DeviceItemCell.m b/Keychain/DeviceItemCell.m new file mode 100644 index 00000000..d6b96821 --- /dev/null +++ b/Keychain/DeviceItemCell.m @@ -0,0 +1,32 @@ +// +// DeviceItemCell.m +// Security +// +// + +#import "DeviceItemCell.h" + +@implementation DeviceItemCell + +- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier +{ + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; + if (self) { + // Initialization code + } + return self; +} + +- (void)setSelected:(BOOL)selected animated:(BOOL)animated +{ + [super setSelected:selected animated:animated]; + + // Configure the view for the selected state +} + ++ (NSString *)reuseIdentifier +{ + return @"DeviceItemCellIdentifier"; +} + +@end diff --git a/Keychain/DeviceTableViewController.h b/Keychain/DeviceTableViewController.h new file mode 100644 index 00000000..e92b1d18 --- /dev/null +++ b/Keychain/DeviceTableViewController.h @@ -0,0 +1,20 @@ +// +// KCATableViewController.h +// Security +// +// Created by John Hurley on 10/22/12. +// +// + +#import + +@class DeviceItemCell; + +@interface DeviceTableViewController : UITableViewController +//@property (assign, nonatomic) IBOutlet KeychainItemCell *kcitemCell; +@property (strong, nonatomic) NSArray *kcItemStatuses; +@property (strong, nonatomic) NSArray *kcItemNames; + +- (NSArray *)getItems; + +@end diff --git a/Keychain/DeviceTableViewController.m b/Keychain/DeviceTableViewController.m new file mode 100644 index 00000000..bca1ac09 --- /dev/null +++ b/Keychain/DeviceTableViewController.m @@ -0,0 +1,180 @@ +// +// DeviceTableViewController.m +// Security +// +// + + +#import "DeviceTableViewController.h" +#import "DeviceItemCell.h" + +static NSString *redCircle = @"🔴"; +static NSString *blueCircle = @"🔵"; + +enum +{ + KCA_ITEM_STATUS_ID = 300, + KCA_ITEM_NAME_ID = 301, + KCA_ITEM_ACCT_ID = 302, +}; + +@interface DeviceTableViewController () + +@end + +@implementation DeviceTableViewController + +- (id)initWithStyle:(UITableViewStyle)style +{ + NSLog(@"DeviceTableViewController: initWithStyle"); + if (self = [super initWithStyle:style]) + { + // Custom initialization + // [self.tableView registerClass:(Class)[KeychainItemCell class] forCellReuseIdentifier:(NSString *)@"kciCell"]; + + _kcItemStatuses = [[NSArray alloc] initWithObjects:@"",redCircle, blueCircle,@"",@"",blueCircle,nil]; + _kcItemNames = [[NSArray alloc] initWithObjects:@"Facebook",@"iCloud", @"WSJ",@"Twitter",@"NYTimes",@"Wells Fargo", nil]; + // self.navigationItem.rightBarButtonItem = self.editButtonItem; + } + return self; +} + +#if 0 +- (void)viewDidLoad +{ + NSLog(@"DeviceTableViewController: viewDidLoad"); + [super viewDidLoad]; + + // Uncomment the following line to preserve selection between presentations. + // self.clearsSelectionOnViewWillAppear = NO; + _kcItemStatuses = [[NSArray alloc] initWithObjects:@"",redCircle, blueCircle,@"",@"",nil]; + _kcItemNames = [[NSArray alloc] initWithObjects:@"Facebook",@"iCloud", @"WSJ",@"Twitter",@"NYTimes",nil]; + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + self.navigationItem.rightBarButtonItem = self.editButtonItem; +} +#endif + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender +{ + if ([[segue identifier] isEqualToString:@"ItemDetail"]) + { +#if 0 + KCAItemDetailViewController *detailViewController = [segue destinationViewController]; + NSIndexPath *myIndexPath = [self.tableView indexPathForSelectedRow]; + int row = [myIndexPath row]; + //TODO - horribly inefficient ! + NSArray *items = [self getItems]; + detailViewController.itemDetailModel = [items objectAtIndex: row]; +#endif + } +} + +// MARK: - Table view data source + +- (NSArray *)getItems +{ + NSArray *allItems = NULL;//(NSArray *)[[MyKeychain sharedInstance] fetchDictionaryAll]; + return allItems; +} + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +{ + // Return the number of sections. + NSLog(@"numberOfSectionsInTableView"); + return 1; //TODO +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + // Return the number of rows in the section. + + // SOSCircleCountPeers(circle) + SOSCircleCountApplicants(circle) + + static bool dumpedit = false; + + if (!dumpedit) + { + NSMutableDictionary *allItems = NULL;//[[MyKeychain sharedInstance] fetchDictionaryAll]; + NSLog(@"numberOfRowsInSection: items: %lu", (unsigned long)[allItems count]); + + dumpedit = true; + } + //TODO +#if _USE_TEST_DATA +return _kcItemStatuses.count; +#else + NSInteger count = [[self getItems] count]; + NSLog(@"numberOfRowsInSection: %ld", (long)count); + return count; +#endif + + return 1; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ +#if 1 + NSLog(@"cellForRowAtIndexPath %@", indexPath); + +//- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0); // newer dequeue method guarantees a cell is returned and resized properly, assuming identifier is registered + +// KeychainItemCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + +// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:KCAItemCellIdentifier forIndexPath:(NSIndexPath *)indexPath]; + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"deviceTableCell" forIndexPath:(NSIndexPath *)indexPath]; + if (cell == nil) + { + NSLog(@"cellForRowAtIndexPath : cell was nil"); + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"deviceTableCell"]; + } + + // Configure the cell... + + NSUInteger row = [indexPath row]; + +#if _USE_TEST_DATA + UILabel *statusLabel = (UILabel *)[cell viewWithTag:KCA_ITEM_STATUS_ID]; + statusLabel.text = [_kcItemStatuses objectAtIndex: row]; + UILabel *nameLabel = (UILabel *)[cell viewWithTag:KCA_ITEM_NAME_ID]; + nameLabel.text = [_kcItemNames objectAtIndex: row]; +#else + NSArray *items = [self getItems]; + NSDictionary *theItem = [items objectAtIndex: row]; + UILabel *statusLabel = (UILabel *)[cell viewWithTag:KCA_ITEM_STATUS_ID]; + statusLabel.text = [_kcItemStatuses objectAtIndex: row]; + UILabel *nameLabel = (UILabel *)[cell viewWithTag:KCA_ITEM_NAME_ID]; + nameLabel.text = [theItem objectForKey: (__bridge id)(kSecAttrService)]; + UILabel *accountLabel = (UILabel *)[cell viewWithTag:KCA_ITEM_ACCT_ID]; + accountLabel.text = [theItem objectForKey: (__bridge id)(kSecAttrAccount)]; +#endif + +/* + WHY DOESNT THIS WORK !!! + cell.itemAccount.text = + cell.itemStatus.text = + cell.itemName.text = [_kcItemNames objectAtIndex: [indexPath row]]; +*/ + return cell; +#else + static NSString *CellIdentifier = @"DeviceCell"; + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; + } + + // Configure the cell... +// cell.textLabel.text = @"1234"; + cell.textLabel.text = self.objects[indexPath.row]; +#endif + return cell; +} + + +@end diff --git a/Keychain/DeviceViewController.h b/Keychain/DeviceViewController.h new file mode 100644 index 00000000..08f85e66 --- /dev/null +++ b/Keychain/DeviceViewController.h @@ -0,0 +1,13 @@ +// +// DeviceViewController.h +// Security +// +// Created by john on 11/18/12. +// +// + +#import + +@interface DeviceViewController : UIViewController + +@end diff --git a/Keychain/DeviceViewController.m b/Keychain/DeviceViewController.m new file mode 100644 index 00000000..e893ed50 --- /dev/null +++ b/Keychain/DeviceViewController.m @@ -0,0 +1,38 @@ +// +// DeviceViewController.m +// Security +// +// Created by john on 11/18/12. +// +// + +#import "DeviceViewController.h" + +@interface DeviceViewController () + +@end + +@implementation DeviceViewController + +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + // Custom initialization + } + return self; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +@end diff --git a/Keychain/EditItemViewController.h b/Keychain/EditItemViewController.h new file mode 100644 index 00000000..19204f96 --- /dev/null +++ b/Keychain/EditItemViewController.h @@ -0,0 +1,22 @@ +// +// EditItemViewController.h +// Security +// +// Created by john on 10/24/12. +// +// + +#import + +@interface EditItemViewController : UIViewController +{ + dispatch_group_t dgroup; + dispatch_queue_t xpc_queue; +} +@property (strong, nonatomic) NSDictionary *itemDetailModel; + +@property (weak, nonatomic) IBOutlet UITextField *itemName; +@property (weak, nonatomic) IBOutlet UITextField *itemAccount; +@property (weak, nonatomic) IBOutlet UITextField *itemPassword; + +@end diff --git a/Keychain/EditItemViewController.m b/Keychain/EditItemViewController.m new file mode 100644 index 00000000..6b743d17 --- /dev/null +++ b/Keychain/EditItemViewController.m @@ -0,0 +1,94 @@ +// +// EditItemViewController.m +// Security +// +// Created by john on 10/24/12. +// +// + +#import "EditItemViewController.h" +#import "MyKeychain.h" +//#import +//#import +#import +#import +#include "utilities.h" + +static const CFStringRef kAddItemKeyY = CFSTR("AddItem"); + + +@interface EditItemViewController () + +@end + +@implementation EditItemViewController + +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + // Custom initialization + } + return self; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + // Do any additional setup after loading the view. + NSLog(@"_itemDetailModel: %@", _itemDetailModel); + + dgroup = dispatch_group_create(); + xpc_queue = dispatch_queue_create("EditItemViewController", DISPATCH_QUEUE_CONCURRENT); + _itemName.text = [_itemDetailModel objectForKey:(__bridge id)(kSecAttrService)]; + _itemAccount.text = [_itemDetailModel objectForKey:(__bridge id)(kSecAttrAccount)]; +// _itemPassword.text = @"TODO";//[_itemDetailModel objectForKey:(__bridge id)(kSecValueData)]; + NSData *pwdData = [_itemDetailModel objectForKey:(__bridge id)(kSecValueData)]; + if (pwdData) + { + NSString *pwd = [[NSString alloc] initWithData:pwdData encoding:NSUTF8StringEncoding]; + _itemPassword.text = pwd; + } + else + _itemPassword.text = @""; + +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (void)postToCloud:(NSDictionary *)kcitem +{ + CFErrorRef error = NULL; + testPutObjectInCloud(kAddItemKeyY, (__bridge CFTypeRef)(kcitem), &error, dgroup, xpc_queue); + NSLog(@"NOT IMPLEMENTED: Sent new item to cloud: %@", kcitem); +} + +- (IBAction)handlePasswordEditDone:(id)sender +{ + NSLog(@"handlePasswordEditDone"); + + NSMutableDictionary *newItem = [NSMutableDictionary dictionaryWithCapacity:0]; + [newItem setObject:[_itemPassword text] forKey:kItemPasswordKey]; + [newItem setObject:[_itemAccount text] forKey:kItemAccountKey]; + [newItem setObject:[_itemName text] forKey:kItemNameKey]; + + [[MyKeychain sharedInstance] setItem:newItem]; + [self postToCloud:newItem]; +} + + +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender +{ + NSLog(@"prepareForSegue EditDone"); + if ([[segue identifier] isEqualToString:@"EditDone"]) + { + NSLog(@"seque EditDone"); + [self handlePasswordEditDone:NULL]; + } +} + +@end diff --git a/Keychain/FirstViewController.h b/Keychain/FirstViewController.h new file mode 100644 index 00000000..03af16ff --- /dev/null +++ b/Keychain/FirstViewController.h @@ -0,0 +1,13 @@ +// +// FirstViewController.h +// Keychain +// +// Created by john on 10/22/12. +// +// + +#import + +@interface FirstViewController : UIViewController + +@end diff --git a/Keychain/FirstViewController.m b/Keychain/FirstViewController.m new file mode 100644 index 00000000..dbe940ee --- /dev/null +++ b/Keychain/FirstViewController.m @@ -0,0 +1,29 @@ +// +// FirstViewController.m +// Keychain +// +// Created by john on 10/22/12. +// +// + +#import "FirstViewController.h" + +@interface FirstViewController () + +@end + +@implementation FirstViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + // Do any additional setup after loading the view, typically from a nib. +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +@end diff --git a/Keychain/KCAItemDetailViewController.h b/Keychain/KCAItemDetailViewController.h new file mode 100644 index 00000000..fc007a56 --- /dev/null +++ b/Keychain/KCAItemDetailViewController.h @@ -0,0 +1,22 @@ +// +// KCAItemDetailViewController.h +// Security +// +// Created by John Hurley on 10/24/12. +// +// + +#import + +@interface KCAItemDetailViewController : UIViewController +{ + +} +@property (weak, nonatomic) NSDictionary *itemDetailModel; +@property (weak, nonatomic) IBOutlet UITextField *itemName; +@property (weak, nonatomic) IBOutlet UITextField *itemAccount; +@property (weak, nonatomic) IBOutlet UITextField *itemPassword; +@property (weak, nonatomic) IBOutlet UITextField *itemCreated; +@property (weak, nonatomic) IBOutlet UITextField *itemModified; + +@end diff --git a/Keychain/KCAItemDetailViewController.m b/Keychain/KCAItemDetailViewController.m new file mode 100644 index 00000000..e93c50d5 --- /dev/null +++ b/Keychain/KCAItemDetailViewController.m @@ -0,0 +1,65 @@ +// +// KCAItemDetailViewController.m +// Security +// +// Created by John Hurley on 10/24/12. +// +// + +#import "KCAItemDetailViewController.h" +#import "EditItemViewController.h" + +@interface KCAItemDetailViewController () + +@end + +@implementation KCAItemDetailViewController + +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + // Custom initialization + } + return self; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + // Do any additional setup after loading the view. + +// NSLog(@"_itemDetailModel: %@", _itemDetailModel); + _itemName.text = [_itemDetailModel objectForKey:(__bridge id)(kSecAttrService)]; + _itemAccount.text = [_itemDetailModel objectForKey:(__bridge id)(kSecAttrAccount)]; + + NSData *pwdData = [_itemDetailModel objectForKey:(__bridge id)(kSecValueData)]; + if (pwdData) + { + NSString *pwd = [[NSString alloc] initWithData:pwdData encoding:NSUTF8StringEncoding]; + _itemPassword.text = pwd; + } + else + _itemPassword.text = @""; + + _itemCreated.text = [[_itemDetailModel objectForKey:(__bridge id)(kSecAttrCreationDate)] description]; + _itemModified.text = [[_itemDetailModel objectForKey:(__bridge id)(kSecAttrModificationDate)] description]; +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender +{ + if ([[segue identifier] isEqualToString:@"ItemEdit"]) + { + NSLog(@"Preparing seque to EditItemViewController: %@", _itemDetailModel); + EditItemViewController *editItemViewController = [segue destinationViewController]; + editItemViewController.itemDetailModel = [NSDictionary dictionaryWithDictionary:_itemDetailModel]; + } +} + +@end diff --git a/Keychain/KCATableViewController.h b/Keychain/KCATableViewController.h new file mode 100644 index 00000000..79d5f9d6 --- /dev/null +++ b/Keychain/KCATableViewController.h @@ -0,0 +1,26 @@ +// +// KCATableViewController.h +// Security +// +// Created by John Hurley on 10/22/12. +// +// + +#import + +@class KeychainItemCell; + +@interface KCATableViewController : UITableViewController +{ + int notificationToken; + bool hasUnlockedRecently; +} +//@property (assign, nonatomic) IBOutlet KeychainItemCell *kcitemCell; +@property (strong, nonatomic) NSArray *kcItemStatuses; +@property (strong, nonatomic) NSArray *kcItemNames; +@property (strong, nonatomic) NSTimer *lockTimer; +@property (strong, nonatomic) NSTimer *recentTimer; + +- (NSArray *)getItems; + +@end diff --git a/Keychain/KCATableViewController.m b/Keychain/KCATableViewController.m new file mode 100644 index 00000000..78b3bfbd --- /dev/null +++ b/Keychain/KCATableViewController.m @@ -0,0 +1,313 @@ +// +// KCATableViewController.m +// Security +// +// Created by John Hurley on 10/22/12. +// +// + +/* + Sample: + + (lldb) po allItems + (NSMutableDictionary *) $3 = 0x0855f200 <__NSCFArray 0x855f200>( + { + acct = "Keychain Sync Test Account"; + agrp = test; + cdat = "2012-10-04 21:59:46 +0000"; + gena = <4b657963 6861696e 2053796e 63205465 73742050 61737377 6f726420 44617461>; + mdat = "2012-10-08 21:02:39 +0000"; + pdmn = ak; + svce = "Keychain Sync Test Service"; + }, + { + acct = ""; + agrp = test; + cdat = "2012-10-22 21:08:14 +0000"; + gena = <4b657963 6861696e 2053796e 63205465 73742050 61737377 6f726420 44617461>; + mdat = "2012-10-22 21:08:14 +0000"; + pdmn = ak; + svce = ""; + }, + { + acct = iacct; + agrp = test; + cdat = "2012-10-22 21:08:29 +0000"; + gena = <4b657963 6861696e 2053796e 63205465 73742050 61737377 6f726420 44617461>; + mdat = "2012-10-22 21:08:29 +0000"; + pdmn = ak; + svce = iname; + }, + { + acct = bar; + agrp = test; + cdat = "2012-10-23 16:57:03 +0000"; + gena = <4b657963 6861696e 2053796e 63205465 73742050 61737377 6f726420 44617461>; + mdat = "2012-10-23 16:57:03 +0000"; + pdmn = ak; + svce = baz; + }, + { + acct = foo9; + agrp = test; + cdat = "2012-10-24 22:11:54 +0000"; + gena = <4b657963 6861696e 2053796e 63205465 73742050 61737377 6f726420 44617461>; + mdat = "2012-10-24 22:11:54 +0000"; + pdmn = ak; + svce = passfoo9; + } + ) +*/ + +#import "KCATableViewController.h" +#import "KeychainItemCell.h" +#import "MyKeychain.h" +#import "KCAItemDetailViewController.h" +#import +#import +#import +#import +#if TARGET_OS_EMBEDDED +#import +#endif + + +@interface KCATableViewController () +@end + +@implementation KCATableViewController + +- (void)viewDidLoad +{ + NSLog(@"KCATableViewController: viewDidLoad"); + [super viewDidLoad]; + + _lockTimer = [NSTimer timerWithTimeInterval:15.0 target:self selector:@selector(stopLockTimer:) userInfo:nil repeats:YES]; + [[NSRunLoop currentRunLoop] addTimer: _lockTimer forMode: NSDefaultRunLoopMode]; + + notify_register_dispatch(kSecServerKeychainChangedNotification, ¬ificationToken, dispatch_get_main_queue(), + ^ (int token __unused) + { + NSLog(@"Received %s", kSecServerKeychainChangedNotification); + [self.tableView reloadData]; + }); +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender +{ + // Invoked immediately prior to initiating a segue. Return NO to prevent the segue from firing. The default implementation returns YES. + if (hasUnlockedRecently) + return YES; + if ([identifier isEqualToString:@"ItemDetail"]) + return [self askForPassword]; + return YES; +} + +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender +{ + if ([[segue identifier] isEqualToString:@"ItemDetail"]) + { + KCAItemDetailViewController *detailViewController = [segue destinationViewController]; + NSIndexPath *myIndexPath = [self.tableView indexPathForSelectedRow]; + CFIndex row = [myIndexPath row]; + //TODO - horribly inefficient ! + NSArray *items = [self getItems]; + detailViewController.itemDetailModel = [items objectAtIndex: row]; + } +} + +// MARK: - Table view data source + +- (NSArray *)getItems +{ + // Each array element is a dictionary. If svce is present, compare + NSArray *allItems = (NSArray *)[[MyKeychain sharedInstance] fetchDictionaryAll]; + + return [allItems sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { + NSString *service1 = obj1[(__bridge id)(kSecAttrService)]; + NSString *service2 = obj2[(__bridge id)(kSecAttrService)]; + return [service1 compare:service2]; + }]; + + return allItems; +} + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +{ + // Return the number of sections. + return 1; //TODO +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + // Return the number of rows in the section. + NSInteger count = [[self getItems] count]; +// NSLog(@"numberOfRowsInSection: %d", count); + self.navigationController.navigationBar.topItem.title = [NSString stringWithFormat:@"All Items (%ld)", (long)count]; + +// NSLog(@"Items: %@", [self getItems]); + return count; +} + +- (BOOL)itemUpdatedRecently:(NSDictionary *)item +{ + const NSTimeInterval recent = 15.0; // within the last 15 seconds + NSDate *modDate = [item[(__bridge id)kSecAttrModificationDate] dateByAddingTimeInterval:recent]; + NSDate *now = [NSDate dateWithTimeIntervalSinceNow:0]; + +// NSLog(@"Mod date: %@, now: %@", modDate, now); + return [modDate compare:now] == NSOrderedDescending; // i.e. modDate+15s > now +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + KeychainItemCell *cell = [tableView dequeueReusableCellWithIdentifier:@"kcTableCell" forIndexPath:(NSIndexPath *)indexPath]; + if (cell == nil) + { + NSLog(@"cellForRowAtIndexPath : cell was nil"); + cell = [[KeychainItemCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"kcTableCell"]; + } + + // Configure the cell... + + NSUInteger row = [indexPath row]; + + NSArray *items = [self getItems]; + NSDictionary *theItem = [items objectAtIndex: row]; + + NSString *svce = [theItem objectForKey: (__bridge id)(kSecAttrService)]; + NSString *acct = [theItem objectForKey: (__bridge id)(kSecAttrAccount)]; + + + if ([self itemUpdatedRecently:theItem]) + [cell startCellFlasher]; +/* else + cell.itemStatus.text = @""; +*/ + cell.itemName.text = (svce && [svce length]) ? svce : @"<>"; + cell.itemAccount.text = (acct && [acct length])? acct : @"<>"; + + [cell.itemAccount setTextColor:[UIColor grayColor]]; + + return cell; +} + +- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath +{ + OSStatus status; + NSUInteger row = [indexPath row]; + + NSArray *items = [self getItems]; + NSDictionary *item = [items objectAtIndex: row]; + NSMutableDictionary *query = [NSMutableDictionary dictionaryWithDictionary:item]; + + [query removeObjectForKey:(__bridge id)kSecValueData]; + [query removeObjectForKey:(__bridge id)kSecAttrCreationDate]; + [query removeObjectForKey:(__bridge id)kSecAttrModificationDate]; + [query removeObjectForKey:(__bridge id)kSecAttrGeneric]; + [query removeObjectForKey:@"tomb"]; + query[(__bridge id)(kSecClass)] = (__bridge id)(kSecClassGenericPassword); + +// NSLog(@"Item: %@", item); +// NSLog(@"Query: %@", query); + status = SecItemDelete((__bridge CFDictionaryRef)query); + if (status) + NSLog(@"Error from SecItemDelete: %d", (int)status); + else + [self.tableView reloadData]; +} + +// MARK: Ask for PIN + +- (void)startLockTimer +{ + NSLog(@"startLockTimer"); + hasUnlockedRecently = true; + [_lockTimer setFireDate:[NSDate dateWithTimeIntervalSinceNow:60.0]]; +} + +- (void)stopLockTimer:(NSTimer *)timer +{ +// NSLog(@"stopLockTimer"); + // Call when we hit home button +// [_lockTimer invalidate]; + hasUnlockedRecently = false; +} + +- (BOOL)unlockDeviceWithPasscode:(NSString *)passcode +{ +#if TARGET_OS_EMBEDDED + int status = kMobileKeyBagError; + NSData *passcodeData = [passcode dataUsingEncoding:NSUTF8StringEncoding]; + if (MKBGetDeviceLockState(NULL) != kMobileKeyBagDisabled) + status = MKBUnlockDevice((__bridge CFDataRef)passcodeData, NULL); + else + status = kMobileKeyBagSuccess; + + // #define kMobileKeyBagDeviceLockedError (-2) + + if (status != kMobileKeyBagSuccess) + { + NSLog(@"Could not unlock device. Error: %d", status); + return NO; + } +#endif + [self startLockTimer]; + return YES; +} + +#define NO_AUTOCAPITALIZATION 0 +#define NO_AUTOCORRECTION 1 + +- (BOOL)askForPassword +{ + // Return YES if authenticated + CFUserNotificationRef dialog_alert = 0; + SInt32 err; + NSMutableDictionary *nd = [NSMutableDictionary dictionaryWithCapacity:0]; + CFOptionFlags flags = kCFUserNotificationCautionAlertLevel | kCFUserNotificationNoDefaultButtonFlag; + NSString *passcode; + + // Header and buttons + nd[(NSString *)kCFUserNotificationAlertHeaderKey] = @"Unlock"; + nd[(NSString *)kCFUserNotificationAlertMessageKey] = @"To view details"; + nd[(NSString *)kCFUserNotificationDefaultButtonTitleKey] = @"OK"; + nd[(NSString *)kCFUserNotificationAlternateButtonTitleKey] = @"Cancel"; + nd[(__bridge __strong id)(SBUserNotificationGroupsTextFields)] = (__bridge id)(kCFBooleanTrue); + nd[(NSString *)kCFUserNotificationTextFieldTitlesKey] = @[@"Passcode"]; + nd[(__bridge NSString *)SBUserNotificationTextAutocapitalizationType] = @[ @(NO_AUTOCAPITALIZATION) ]; + nd[(__bridge NSString *)SBUserNotificationTextAutocapitalizationType] = @[ @(NO_AUTOCORRECTION) ]; + + flags = kCFUserNotificationPlainAlertLevel | CFUserNotificationSecureTextField(0); + + dialog_alert = CFUserNotificationCreate(NULL, 0, flags, &err, (__bridge CFMutableDictionaryRef)nd); + if (!dialog_alert) + return NO; + + CFUserNotificationReceiveResponse(dialog_alert, 0, &flags); + // the 2 lower bits of the response flags will give the button pressed + // 0 --> default + // 1 --> alternate + if (flags & kCFUserNotificationCancelResponse) { // user cancelled + if (dialog_alert) + CFRelease(dialog_alert); + return NO; + } + + // user clicked OK + passcode = CFBridgingRelease(CFUserNotificationGetResponseValue(dialog_alert, kCFUserNotificationTextFieldValuesKey, 0)); + // test using MKBUnlockDevice +// NSLog(@"PIN: %@", passcode); // TODO: REMOVE THIS!!!! + + if (dialog_alert) + CFRelease(dialog_alert); + return [self unlockDeviceWithPasscode:passcode]; +} + +@end diff --git a/Keychain/KDAppDelegate.h b/Keychain/KDAppDelegate.h deleted file mode 100644 index 6e40385d..00000000 --- a/Keychain/KDAppDelegate.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// KDAppDelegate.h -// Keychain -// -// Created by J Osborne on 2/13/13. -// -// - -#import -#import "KDSecItems.h" -#import "KDSecCircle.h" - -@interface KDAppDelegate : NSObject - -@property (assign) IBOutlet NSWindow *window; -@property (assign) IBOutlet NSTableView *itemTable; -@property (assign) IBOutlet NSTextFieldCell *itemTableTitle; -@property (retain) id itemDataSource; - -@property (assign) IBOutlet NSButton *enableKeychainSyncing; -@property (assign) IBOutlet NSTextFieldCell *circleStatusCell; -@property (assign) IBOutlet NSTextFieldCell *peerCountCell; -@property (assign) IBOutlet NSTextView *peerTextList; -@property (assign) IBOutlet NSTextFieldCell *applicantCountCell; -@property (assign) IBOutlet NSTextView *applicantTextList; -@property (assign) IBOutlet NSProgressIndicator *syncSpinner; - -@property (retain) KDSecCircle *circle; - -@property (retain) NSMutableArray *stuffNotToLeak; - --(IBAction)enableKeychainSyncingClicked:(id)sender; -@end diff --git a/Keychain/KDAppDelegate.m b/Keychain/KDAppDelegate.m deleted file mode 100644 index 1d3b81f7..00000000 --- a/Keychain/KDAppDelegate.m +++ /dev/null @@ -1,83 +0,0 @@ -// -// KDAppDelegate.m -// Keychain -// -// Created by J Osborne on 2/13/13. -// -// - -#import "KDAppDelegate.h" -#import "KDCirclePeer.h" -#import "NSArray+mapWithBlock.h" -#include - -#define kSecServerKeychainChangedNotification "com.apple.security.keychainchanged" - -@implementation KDAppDelegate - -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification -{ - self.stuffNotToLeak = [NSMutableArray new]; - [self.stuffNotToLeak addObject:[[NSNotificationCenter defaultCenter] addObserverForName:kKDSecItemsUpdated object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { - self.itemTableTitle.title = [NSString stringWithFormat:@"All Items (%ld)", (long)[self.itemDataSource numberOfRowsInTableView:self.itemTable]]; - }]]; - - [self.syncSpinner setUsesThreadedAnimation:YES]; - [self.syncSpinner startAnimation:nil]; - - self.itemDataSource = [[KDSecItems alloc] init]; - self.itemTable.dataSource = self.itemDataSource; - - int notificationToken; - uint32_t rc = notify_register_dispatch(kSecServerKeychainChangedNotification, ¬ificationToken, dispatch_get_main_queue(), ^(int token __unused) { - NSLog(@"Received %s", kSecServerKeychainChangedNotification); - [(KDSecItems*)self.itemDataSource loadItems]; - [self.itemTable reloadData]; - }); - NSAssert(rc == 0, @"Can't register for %s", kSecServerKeychainChangedNotification); - - self.circle = [KDSecCircle new]; - [self.circle addChangeCallback:^{ - self.circleStatusCell.stringValue = self.circle.status; - - [self setCheckbox]; - - self.peerCountCell.objectValue = @(self.circle.peers.count); - NSString *peerNames = [[self.circle.peers mapWithBlock:^id(id obj) { - return ((KDCirclePeer*)obj).name; - }] componentsJoinedByString:@"\n"]; - [self.peerTextList.textStorage replaceCharactersInRange:NSMakeRange(0, [self.peerTextList.textStorage length]) withString:peerNames]; - - self.applicantCountCell.objectValue = @(self.circle.applicants.count); - NSString *applicantNames = [[self.circle.applicants mapWithBlock:^id(id obj) { - return ((KDCirclePeer*)obj).name; - }] componentsJoinedByString:@"\n"]; - [self.applicantTextList.textStorage replaceCharactersInRange:NSMakeRange(0, [self.applicantTextList.textStorage length]) withString:applicantNames]; - - [self.syncSpinner stopAnimation:nil]; - }]; -} - --(void)setCheckbox -{ - if (self.circle.isInCircle) { - [self.enableKeychainSyncing setState:NSOnState]; - } else if (self.circle.isOutOfCircle) { - [self.enableKeychainSyncing setState:NSOffState]; - } else { - [self.enableKeychainSyncing setState:NSMixedState]; - } -} - --(IBAction)enableKeychainSyncingClicked:(id)sender -{ - [self.syncSpinner startAnimation:sender]; - if (self.circle.isOutOfCircle) { - [self.circle enableSync]; - } else { - [self.circle disableSync]; - } - [self setCheckbox]; -} - -@end diff --git a/Keychain/KDCirclePeer.h b/Keychain/KDCirclePeer.h deleted file mode 100644 index 45416f97..00000000 --- a/Keychain/KDCirclePeer.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// KDCirclePeer.h -// Security -// -// Created by J Osborne on 2/25/13. -// -// - -#import - -@interface KDCirclePeer : NSObject - -@property (readonly) NSString *name; -@property (readonly) NSString *idString; -@property (readonly) id peerObject; - --(id)initWithPeerObject:(id)peerObject; - -@end diff --git a/Keychain/KDCirclePeer.m b/Keychain/KDCirclePeer.m deleted file mode 100644 index 695af370..00000000 --- a/Keychain/KDCirclePeer.m +++ /dev/null @@ -1,42 +0,0 @@ -// -// KDCirclePeer.m -// Security -// -// Created by J Osborne on 2/25/13. -// -// - -#import "KDCirclePeer.h" -#include "SecureObjectSync/SOSCloudCircle.h" -#include "SecureObjectSync/SOSPeerInfo.h" - -@interface KDCirclePeer () - -@property (readwrite) NSString *name; -@property (readwrite) NSString *idString; -@property (readwrite) id peerObject; - -@end - -@implementation KDCirclePeer - --(id)initWithPeerObject:(id)peerObject -{ - self = [super init]; - if (!self) { - return self; - } - - self.peerObject = peerObject; - self.name = (__bridge NSString *)(SOSPeerInfoGetPeerName((__bridge SOSPeerInfoRef)peerObject)); - self.idString = (__bridge NSString *)(SOSPeerInfoGetPeerID((__bridge SOSPeerInfoRef)peerObject)); - - return self; -} - --(NSString*)description -{ - return [NSString stringWithFormat:@"[peer n='%@' id='%@' o=%@]", self.name, self.idString, self.peerObject]; -} - -@end diff --git a/Keychain/KDSecCircle.h b/Keychain/KDSecCircle.h deleted file mode 100644 index 35455a31..00000000 --- a/Keychain/KDSecCircle.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// KDSecCircle.h -// Security -// -// Created by J Osborne on 2/20/13. -// -// - -#import "SecureObjectSync/SOSCloudCircle.h" -#import - -@interface KDSecCircle : NSObject - -@property (readonly) BOOL isInCircle; -@property (readonly) BOOL isOutOfCircle; - -@property (readonly) SOSCCStatus rawStatus; - -@property (readonly) NSString *status; -@property (readonly) NSError *error; - -// Both of these are arrays of KDCircelPeer objects -@property (readonly) NSArray *peers; -@property (readonly) NSArray *applicants; - --(void)addChangeCallback:(dispatch_block_t)callback; --(id)init; - -// these are "try to", and may (most likely will) not complete by the time they return --(void)enableSync; --(void)disableSync; --(void)rejectApplicantId:(NSString*)applicantId; --(void)acceptApplicantId:(NSString*)applicantId; - -@end diff --git a/Keychain/KDSecItems.h b/Keychain/KDSecItems.h deleted file mode 100644 index 72a6c71d..00000000 --- a/Keychain/KDSecItems.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// KDSecItems.h -// Security -// -// Created by J Osborne on 2/14/13. -// -// - -#import - -extern NSString *kKDSecItemsUpdated; - -@interface KDSecItems : NSObject --(NSInteger)numberOfRowsInTableView:(NSTableView*)t; -- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex; - --(void)loadItems; -@end diff --git a/Keychain/Keychain-Entitlements.plist b/Keychain/Keychain-Entitlements.plist new file mode 100644 index 00000000..2de764bf --- /dev/null +++ b/Keychain/Keychain-Entitlements.plist @@ -0,0 +1,17 @@ + + + + + com.apple.keystore.device + + keychain-cloud-circle + + application-identifier + Keychain + keychain-access-groups + + Keychain + * + + + diff --git a/Keychain/Keychain-Info.plist b/Keychain/Keychain-Info.plist index 94b28a95..98556e5b 100644 --- a/Keychain/Keychain-Info.plist +++ b/Keychain/Keychain-Info.plist @@ -4,10 +4,23 @@ CFBundleDevelopmentRegion en + CFBundleDisplayName + ${PRODUCT_NAME} CFBundleExecutable ${EXECUTABLE_NAME} - CFBundleIconFile - Icon.icns + CFBundleIcons + + CFBundlePrimaryIcon + + CFBundleIconFiles + + Keychain_57x57.png + Keychain_114x114.png + Keychain_72x72.png + Keychain_144x144.png + + + CFBundleIdentifier com.apple.security.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion @@ -17,16 +30,43 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0 + 10.0 CFBundleSignature ???? CFBundleVersion - 55471.14.18 - LSMinimumSystemVersion - ${MACOSX_DEPLOYMENT_TARGET} - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication + ${CURRENT_PROJECT_VERSION} + LSRequiresIPhoneOS + + UIMainStoryboardFile + MainStoryboard_iPhone + UIMainStoryboardFile~ipad + MainStoryboard_iPhone + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarTintParameters + + UINavigationBar + + Style + UIBarStyleDefault + Translucent + + + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + diff --git a/Keychain/KeychainItemCell.h b/Keychain/KeychainItemCell.h new file mode 100644 index 00000000..0c64c0d7 --- /dev/null +++ b/Keychain/KeychainItemCell.h @@ -0,0 +1,23 @@ +// +// KeychainItemCell.h +// Security +// +// Created by John Hurley on 10/22/12. +// +// + +#import +#import "CircleStatusView.h" + +@interface KeychainItemCell : UITableViewCell +{ + uint32_t flashCounter; + NSTimer *flashTimer; +} +@property (weak, nonatomic) IBOutlet ItemStatusView *itemStatus; +@property (weak, nonatomic) IBOutlet UILabel *itemName; +@property (weak, nonatomic) IBOutlet UILabel *itemAccount; + +- (void)startCellFlasher; + +@end diff --git a/Keychain/KeychainItemCell.m b/Keychain/KeychainItemCell.m new file mode 100644 index 00000000..60cb2684 --- /dev/null +++ b/Keychain/KeychainItemCell.m @@ -0,0 +1,49 @@ +// +// KeychainItemCell.m +// Security +// +// Created by John Hurley on 10/22/12. +// +// + +#import "KeychainItemCell.h" +#import + +@implementation KeychainItemCell + +- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier +{ + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; + if (self) { + // Initialization code + } + return self; +} + +- (void)setSelected:(BOOL)selected animated:(BOOL)animated +{ + [super setSelected:selected animated:animated]; + + // Configure the view for the selected state +} + ++ (NSString *)reuseIdentifier +{ + return @"KeychainItemCellIdentifier"; +} + +- (void)startCellFlasher +{ + CABasicAnimation *theAnimation = NULL; + + theAnimation=[CABasicAnimation animationWithKeyPath:@"opacity"]; + theAnimation.duration=0.75; + theAnimation.repeatCount=6; //HUGE_VALF; + theAnimation.autoreverses=YES; + theAnimation.fromValue=[NSNumber numberWithFloat:0.0]; + theAnimation.toValue=[NSNumber numberWithFloat:1.0]; + theAnimation.removedOnCompletion = TRUE; + [_itemStatus.layer addAnimation:theAnimation forKey:@"animateOpacity"]; +} + +@end diff --git a/Keychain/KeychainKeys.png b/Keychain/KeychainKeys.png new file mode 100644 index 0000000000000000000000000000000000000000..9622f56b74cc7df5b459fcbce6f11e92cb64c8cd GIT binary patch literal 15193 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 + +extern const NSString *kItemPasswordKey; +extern const NSString *kItemAccountKey; +extern const NSString *kItemNameKey; + +@interface MyKeychain : NSObject ++ (MyKeychain *) sharedInstance; +- (void) setPassword: (NSString *) password; +- (NSString *) fetchPassword; +- (void)setItem:(NSDictionary *)newItem; +- (NSMutableArray *) fetchDictionaryWithQuery:(NSMutableDictionary *)query; +- (NSMutableArray *) fetchDictionaryAll; + +- (void)setPasswordFull:(NSString *)account service:(NSString *)service password:(NSString *) thePassword; +- (void)clearAllKeychainItems; + +@end diff --git a/Keychain/MyKeychain.m b/Keychain/MyKeychain.m new file mode 100644 index 00000000..347a2bc1 --- /dev/null +++ b/Keychain/MyKeychain.m @@ -0,0 +1,347 @@ +// +// MyKeychain.m +// KCSync +// +// Created by John Hurley on 10/3/12. +// Copyright (c) 2012 john. All rights reserved. +// + +#import "MyKeychain.h" +#import +#import +#import + +const NSString *kItemPasswordKey = @"ItemPasswordKey"; +const NSString *kItemAccountKey = @"ItemAccountKey"; +const NSString *kItemNameKey = @"ItemNameKey"; + +#define KCSCOPE "mykeychain" + +// secdebug(KCSCOPE, + +@implementation MyKeychain + +static MyKeychain *sharedInstance = nil; + ++ (MyKeychain *) sharedInstance +{ + if (!sharedInstance) + sharedInstance = [[self alloc] init]; + + return sharedInstance; +} + +// Translate status messages into return strings +- (NSString *) fetchStatus : (OSStatus) status +{ + switch (status) + { + case 0: + return(@"Success!"); + case errSecNotAvailable: + return(@"No trust results are available.!"); + case errSecItemNotFound: + return(@"The item cannot be found."); + case errSecParam: + return(@"Parameter error."); + case errSecAllocate: + return(@"Memory allocation error. Failed to allocate memory."); + case errSecInteractionNotAllowed: + return(@"User interaction is not allowed."); + case errSecUnimplemented: + return(@"Function is not implemented"); + case errSecDuplicateItem: + return(@"The item already exists."); + case errSecDecode: + return(@"Unable to decode the provided data."); + + default: + return([NSString stringWithFormat:@"Function returned: %ld", (long)status]); + break; + } + return @"can't happen..."; +} + +#define ACCOUNT @"Keychain Sync Test Account" +#define SERVICE @"Keychain Sync Test Service" +#define PWKEY @"Keychain Sync Test Password Data" + +// Return a base dictionary +- (NSMutableDictionary *) baseDictionary +{ + NSMutableDictionary *md = [[NSMutableDictionary alloc] init]; + + // Password identification keys + NSData *identifier = [PWKEY dataUsingEncoding:NSUTF8StringEncoding]; + [md setObject:identifier forKey:(__bridge id)kSecAttrGeneric]; + [md setObject:ACCOUNT forKey:(__bridge id)kSecAttrAccount]; + [md setObject:SERVICE forKey:(__bridge id)kSecAttrService]; + [md setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; + [md setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecAttrSynchronizable]; + + return md; +} + +// Return a keychain-style dictionary populated with the password +- (NSMutableDictionary *) buildDictForPassword:(NSString *) password +{ + NSMutableDictionary *passwordDict = [self baseDictionary]; + + // Add the password + NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; + [passwordDict setObject:passwordData forKey:(__bridge id)kSecValueData]; // password + + return passwordDict; +} + +// Build a search query based +- (NSMutableDictionary *) buildSearchQuery +{ + NSMutableDictionary *genericPasswordQuery = [self baseDictionary]; + + // Add the search constraints + [genericPasswordQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; + [genericPasswordQuery setObject:(__bridge id)kCFBooleanTrue + forKey:(__bridge id)kSecReturnAttributes]; + [genericPasswordQuery setObject:(__bridge id)kCFBooleanTrue + forKey:(__bridge id)kSecReturnData]; + + return genericPasswordQuery; +} + +// retrieve data dictionary from the keychain +- (NSMutableArray *) fetchDictionaryWithQuery:(NSMutableDictionary *)query +{ + NSMutableDictionary *genericPasswordQuery = query; + +// secerror("Query: %@", query); + CFTypeRef cfresult = nil; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)genericPasswordQuery, &cfresult); + +// secerror( "FETCH: %s\n", [[self fetchStatus:status] UTF8String]); + + if (status == errSecItemNotFound) + return NULL; + + if (CFGetTypeID(cfresult) == CFArrayGetTypeID()) + { + NSMutableArray *result = [NSMutableArray arrayWithCapacity:0]; + [result addObjectsFromArray:CFBridgingRelease(cfresult)]; + return result; + } + + // If it is a single result, embed it in an array because callers expect it + if (CFGetTypeID(cfresult) == CFDictionaryGetTypeID()) + return [NSMutableArray arrayWithObject:CFBridgingRelease(cfresult)]; + + return NULL; +} + +- (NSMutableArray *)fetchDictionary +{ + return [self fetchDictionaryWithQuery:[self buildSearchQuery]]; +} + +// create a new keychain entry +- (BOOL) createKeychainValue:(NSString *) password +{ + NSMutableDictionary *md = [self buildDictForPassword:password]; + OSStatus status = SecItemAdd((__bridge CFDictionaryRef)md, NULL); + + secerror( "CREATE: %s\n", [[self fetchStatus:status] UTF8String]); + + if (status == errSecSuccess) return YES; else return NO; +} + +// remove a keychain entry +- (void) clearKeychain +{ + NSMutableDictionary *genericPasswordQuery = [self baseDictionary]; + + OSStatus status = SecItemDelete((__bridge CFDictionaryRef) genericPasswordQuery); + secerror( "DELETE: %s\n", [[self fetchStatus:status] UTF8String]); +} + +// update a keychain entry +- (BOOL) updateKeychainValue:(NSString *)password +{ + NSMutableDictionary *genericPasswordQuery = [self baseDictionary]; + + NSMutableDictionary *attributesToUpdate = [[NSMutableDictionary alloc] init]; + NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; + [attributesToUpdate setObject:passwordData forKey:(__bridge id)kSecValueData]; + + OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)genericPasswordQuery, (__bridge CFDictionaryRef)attributesToUpdate); + secerror( "UPDATE: %s\n", [[self fetchStatus:status] UTF8String]); + + if (status == 0) return YES; else return NO; +} + +// fetch a keychain value +- (NSString *) fetchPassword +{ + NSMutableArray *allItems = [self fetchDictionary]; + if (!allItems) + return NULL; + + // This is used for a single item, so take first item in array + NSData *passData = [allItems[0] objectForKey:(__bridge id)kSecValueData]; + if (passData) + return [[NSString alloc] initWithData:passData encoding:NSUTF8StringEncoding]; + + return NULL; +} + +- (void)setPassword: (NSString *) thePassword +{ + if (![self createKeychainValue:thePassword]) + [self updateKeychainValue:thePassword]; +} + +- (void)setItem:(NSDictionary *)newItem +{ + OSStatus status = errSecSuccess; + NSMutableDictionary *passwordDict = [self baseDictionary]; + + // Add the password + NSData *passwordData = [[newItem objectForKey:kItemPasswordKey] dataUsingEncoding:NSUTF8StringEncoding]; + [passwordDict setObject:passwordData forKey:(__bridge id)kSecValueData]; // password + + [passwordDict setObject:[newItem objectForKey:kItemAccountKey] forKey:(__bridge id)kSecAttrAccount]; + [passwordDict setObject:[newItem objectForKey:kItemNameKey] forKey:(__bridge id)kSecAttrService]; + + // Try to add first; if error, then try to update + status = SecItemAdd((__bridge CFDictionaryRef)passwordDict, NULL); + secerror( "SecItemAdd result: %@ (%ld)", [self fetchStatus:status], (long)status); + NSLog(@"SecItemAdd result: %@ (%ld)", [self fetchStatus:status], (long)status); + + if (status) + { + // Try update + // We only want to update the password data, so delete the other keys + +// NSArray *keysToRemove = [NSArray arrayWithObjects:kItemAccountKey, kItemNameKey, nil]; + [passwordDict removeObjectsForKeys:@[(__bridge id)kSecValueData]]; + + NSDictionary *itemsToUpdate = @{ (__bridge id)kSecValueData : passwordData }; +// [genericPasswordQuery setObject:[newItem objectForKey:kItemAccountKey] forKey:(__bridge id)kSecAttrAccount]; +// [genericPasswordQuery setObject:[newItem objectForKey:kItemNameKey] forKey:(__bridge id)kSecAttrService]; + status = SecItemUpdate((__bridge CFDictionaryRef)passwordDict, (__bridge CFDictionaryRef)(itemsToUpdate)); + secerror( "SecItemUpdate result: %@ (%ld)", [self fetchStatus:status], (long)status); + NSLog(@"SecItemUpdate result: %@ (%ld)", [self fetchStatus:status], (long)status); + } +} + +- (NSMutableArray *)fetchDictionaryAll +{ + NSMutableDictionary *query = [[NSMutableDictionary alloc] init]; + [query setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; + [query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecAttrSynchronizable]; + + // Add the search constraints + [query setObject:(__bridge id)kSecMatchLimitAll forKey:(__bridge id)kSecMatchLimit]; + [query setObject:(__bridge id)kCFBooleanTrue + forKey:(__bridge id)kSecReturnAttributes]; + [query setObject:(__bridge id)kCFBooleanTrue + forKey:(__bridge id)kSecReturnData]; + + NSMutableArray *genericItems = [self fetchDictionaryWithQuery:query]; + + // Now look for internet items + [query setObject:(__bridge id)kSecClassInternetPassword forKey:(__bridge id)kSecClass]; + NSMutableArray *internetItems = [self fetchDictionaryWithQuery:query]; + if (internetItems) + [genericItems addObjectsFromArray:internetItems]; + return genericItems; +} + +// MARK: ----- Full routines ----- + +// Return a base dictionary +- (NSMutableDictionary *) baseDictionaryFull:(NSString *)account service:(NSString *)service +{ + NSMutableDictionary *md = [[NSMutableDictionary alloc] init]; + + // Password identification keys + NSData *identifier = [PWKEY dataUsingEncoding:NSUTF8StringEncoding]; + [md setObject:identifier forKey:(__bridge id)kSecAttrGeneric]; + [md setObject:account forKey:(__bridge id)kSecAttrAccount]; + [md setObject:service forKey:(__bridge id)kSecAttrService]; + [md setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; + [md setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecAttrSynchronizable]; + +// return [md autorelease]; + return md; +} + +- (BOOL) createKeychainValueFull:(NSString *)account service:(NSString *)service password:(NSString *)password +{ + NSMutableDictionary *md = [self buildDictForPasswordFull:account service:service password:password]; + OSStatus status = SecItemAdd((__bridge CFDictionaryRef)md, NULL); + secerror( "CREATE: %s\n", [[self fetchStatus:status] UTF8String]); + + if (status == errSecSuccess) return YES; else return NO; +} + +- (BOOL) updateKeychainValueFull:(NSString *)account service:(NSString *)service password:(NSString *)password +{ + NSMutableDictionary *genericPasswordQuery = [self baseDictionaryFull:account service:service]; + + NSMutableDictionary *attributesToUpdate = [[NSMutableDictionary alloc] init]; + NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; + [attributesToUpdate setObject:passwordData forKey:(__bridge id)kSecValueData]; + + OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)genericPasswordQuery, (__bridge CFDictionaryRef)attributesToUpdate); + secerror( "UPDATE: %s\n", [[self fetchStatus:status] UTF8String]); + + if (status == 0) return YES; else return NO; +} + +- (void)setPasswordFull:(NSString *)account service:(NSString *)service password:(NSString *) thePassword +{ + secerror( "setPasswordFull account: %@, service: %@, password: %@", account, service, thePassword); + if (![self createKeychainValueFull:account service:service password:thePassword]) + [self updateKeychainValueFull:account service:service password:thePassword]; +} + +// Return a keychain-style dictionary populated with the password +- (NSMutableDictionary *) buildDictForPasswordFull:(NSString *)account service:(NSString *)service password:(NSString *)password +{ + NSMutableDictionary *passwordDict = [self baseDictionaryFull:account service:service]; + + // Add the password + NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; + [passwordDict setObject:passwordData forKey:(__bridge id)kSecValueData]; // password + + return passwordDict; +} + +- (void)clearAllKeychainItems +{ + CFIndex ix, top; + OSStatus status = errSecSuccess; + + NSArray *allItems = (NSArray *)[[MyKeychain sharedInstance] fetchDictionaryAll]; + top = [allItems count]; + secerror( "Deleting %ld items", (long)top); + + for (ix=0; ix + +@interface NewPasswordViewController : UIViewController +{ + dispatch_group_t dgroup; + dispatch_queue_t xpc_queue; +} +@property (weak, nonatomic) IBOutlet UITextField *itemName; +@property (weak, nonatomic) IBOutlet UITextField *itemAccount; +@property (weak, nonatomic) IBOutlet UITextField *itemPassword; + +@end diff --git a/Keychain/NewPasswordViewController.m b/Keychain/NewPasswordViewController.m new file mode 100644 index 00000000..28e6376e --- /dev/null +++ b/Keychain/NewPasswordViewController.m @@ -0,0 +1,62 @@ +// +// NewPasswordViewController.m +// Security +// +// Created by john on 10/24/12. +// +// + +#import "NewPasswordViewController.h" +#import "MyKeychain.h" +//#import +#import +#import +#include "utilities.h" + +static const CFStringRef kAddItemKeyX = CFSTR("AddItem"); + + +@interface NewPasswordViewController () + +@end + +@implementation NewPasswordViewController + +- (void)viewDidLoad +{ + NSLog(@"NewPasswordViewController:viewDidLoad"); + [super viewDidLoad]; + + dgroup = dispatch_group_create(); + xpc_queue = dispatch_queue_create("NewPasswordViewController", DISPATCH_QUEUE_CONCURRENT); + // Uncomment the following line to preserve selection between presentations. + // self.clearsSelectionOnViewWillAppear = NO; + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem; +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (void)postToCloud:(NSDictionary *)kcitem +{ + CFErrorRef error = NULL; + testPutObjectInCloud(kAddItemKeyX, (__bridge CFTypeRef)(kcitem), &error, dgroup, xpc_queue); + NSLog(@"Sent new item to cloud: %@", kcitem); +} + +- (IBAction)handleNewPasswordDone:(id)sender +{ + // [self performSegueWithIdentifier: @"SegueToScene1" sender: self]; + NSLog(@"NewPasswordViewController:handleAddButton"); + + [[MyKeychain sharedInstance] setPasswordFull:[_itemAccount text] service:[_itemName text] password:[_itemPassword text]]; + + [self performSegueWithIdentifier:@"AllItemsSegue" sender:self]; +} + +@end diff --git a/Keychain/PeerListCell.h b/Keychain/PeerListCell.h new file mode 100644 index 00000000..2eb5b15e --- /dev/null +++ b/Keychain/PeerListCell.h @@ -0,0 +1,16 @@ +// +// PeerListCell.h +// Security +// +// Created by Mitch Adler on 12/4/12. +// +// + +#import + +@interface PeerListCell : UITableViewCell + +@property (weak, nonatomic) IBOutlet UILabel *peerName; +@property (weak, nonatomic) IBOutlet UILabel *peerCircle; + +@end diff --git a/Keychain/PeerListCell.m b/Keychain/PeerListCell.m new file mode 100644 index 00000000..bfbf7dbd --- /dev/null +++ b/Keychain/PeerListCell.m @@ -0,0 +1,34 @@ +// +// PeerListCell.m +// Security +// +// Created by Mitch Adler on 12/4/12. +// +// + +#import "PeerListCell.h" + +@implementation PeerListCell + +- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier +{ + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; + if (self) { + // Initialization code + } + return self; +} + +- (void)setSelected:(BOOL)selected animated:(BOOL)animated +{ + [super setSelected:selected animated:animated]; + + // Configure the view for the selected state +} + ++ (NSString *)reuseIdentifier +{ + return @"PeerTableCell"; +} + +@end diff --git a/Keychain/SyncViewController.h b/Keychain/SyncViewController.h new file mode 100644 index 00000000..3bbaa14f --- /dev/null +++ b/Keychain/SyncViewController.h @@ -0,0 +1,34 @@ +// +// SyncViewController.h +// Keychain +// +// Created by john on 10/22/12. +// + +#import +#import +#import "CircleStatusView.h" + +@interface SyncViewController : UIViewController { + int notificationToken; + int notificationCount; +} +@property (weak, nonatomic) IBOutlet UILabel *statusMessage; +@property (weak, nonatomic) IBOutlet UISwitch *syncingEnabled; +@property (weak, nonatomic) IBOutlet UIProgressView *circleProgress; +@property (weak, nonatomic) IBOutlet UILabel *circleStatus; +@property (weak, nonatomic) IBOutlet UILabel *updateCount; +@property (weak, nonatomic) IBOutlet UILabel *peerCount; +@property (weak, nonatomic) IBOutlet UILabel *applicantCount; +@property (weak, nonatomic) IBOutlet UITableView *peerList; +@property (weak, nonatomic) IBOutlet UITableView *applicantList; +@property (weak, nonatomic) IBOutlet UILabel *stateChanged; +@property (weak, nonatomic) IBOutlet UIButton *acceptButton; +@property (weak, nonatomic) IBOutlet CircleStatusView *stateChangedC; + +- (void)flashChangeLight; +- (void)setStatus:(NSString *)message; +- (void)updateSyncingEnabledSwitch; ++ (void)requestToJoinCircle; + +@end diff --git a/Keychain/SyncViewController.m b/Keychain/SyncViewController.m new file mode 100644 index 00000000..bdbe5578 --- /dev/null +++ b/Keychain/SyncViewController.m @@ -0,0 +1,241 @@ +// +// SyncViewController.m +// Keychain +// +// Created by john on 10/22/12. +// +// + +#import "SyncViewController.h" +#import "MyKeychain.h" + +#import +#import +#import +#import +#import + +#import +#import + +#import +#import +#import +#import +#import "PeerListCell.h" +#import + +__unused static const uint64_t maxTimeToWaitInSeconds = 30ull * NSEC_PER_SEC; + +@interface SyncViewController () +@end + +@implementation SyncViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + // Do any additional setup after loading the view, typically from a nib. + [self setStatus:@"Idle…"]; + [self updateSyncingEnabledSwitch]; + + notify_register_dispatch(kSOSCCCircleChangedNotification, ¬ificationToken, + dispatch_get_main_queue(), + ^(int tokenx __unused) { + notificationCount++; + [self setStatus:@"Got circle changed notification."]; + [self flashChangeLight]; + [self updateSyncingEnabledSwitch]; + [self updateMemberCounts]; + [_peerList reloadData]; + [_applicantList reloadData]; + }); + [_acceptButton setEnabled:NO]; + + [self updateStatusCircleColor]; + +// _stateChangedC.color = [UIColor redColor]; +// [_stateChangedC setNeedsDisplay]; +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (void)updateSyncingEnabledSwitch +{ + // Set the visual state of switch based on membership in circle + CFErrorRef error = NULL; + SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(&error); + BOOL switchIsOn = (ccstatus == kSOSCCInCircle || ccstatus == kSOSCCRequestPending); + [_syncingEnabled setOn:switchIsOn animated:NO]; + + CFStringRef circleStatusStr = SOSCCGetStatusDescription(ccstatus); + [_circleStatus setText:CFBridgingRelease(circleStatusStr)]; + [_updateCount setText:[NSString stringWithFormat:@"%d", notificationCount]]; + + // TODO: Maybe update spinny for pending?!? + + NSLog(@"ccstatus: %@ (%d), error: %@", SOSCCGetStatusDescription(ccstatus), ccstatus, error); +} + +- (void)updateStatusCircleColor +{ + switch (SOSCCThisDeviceIsInCircle(NULL)) + { + case kSOSCCInCircle: + _stateChangedC.color = [UIColor greenColor]; + break; + case kSOSCCRequestPending: + _stateChangedC.color = [UIColor yellowColor]; + break; + default: + _stateChangedC.color = [UIColor redColor]; + break; + } + [_stateChangedC setNeedsDisplay]; +} + +- (void)updateMemberCounts +{ + CFArrayRef foundApplicants = SOSCCCopyApplicantPeerInfo(NULL); + CFIndex applicantCount = foundApplicants ? CFArrayGetCount(foundApplicants) : -1; + [_applicantCount setText:[NSString stringWithFormat:@"%ld", (long)applicantCount]]; + + CFArrayRef foundPeers = SOSCCCopyPeerPeerInfo(NULL); + CFIndex peerCount = foundPeers ? CFArrayGetCount(foundPeers) : -1; + [_peerCount setText:[NSString stringWithFormat:@"%ld", (long)peerCount]]; + + [_acceptButton setEnabled:(applicantCount > 0)? YES: NO]; + + [self updateStatusCircleColor]; + + CFReleaseSafe(foundApplicants); + CFReleaseSafe(foundPeers); +} + ++ (void)requestToJoinCircle +{ + // Set the visual state of switch based on membership in circle + bool bx = true; + CFErrorRef error = NULL; + SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(&error); + + switch (ccstatus) { + case kSOSCCCircleAbsent: + bx = SOSCCResetToOffering(&error); + break; + case kSOSCCNotInCircle: + bx = SOSCCRequestToJoinCircle(&error); + break; + default: + NSLog(@"Request to join circle with bad status: %@ (%d)", SOSCCGetStatusDescription(ccstatus), ccstatus); + break; + } + if (!bx) + NSLog(@"requestToJoinCircle Error: %@", error); +} + +- (IBAction)acceptAllApplicants:(id)sender +{ + CFArrayRef applicants = SOSCCCopyApplicantPeerInfo(NULL); + if (applicants) { + SOSCCAcceptApplicants(applicants, NULL); + CFRelease(applicants); + } +} + +- (IBAction)handleEnableSyncing:(id)sender +{ + dispatch_queue_t workq = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + if ([sender isOn]) // i.e. we are trying to turn on syncing + { + dispatch_async(workq, ^ { + NSLog(@"Keychain syncing is being turned ON"); + [[self class] requestToJoinCircle]; + }); + } + else + { + dispatch_async(workq, ^ { + NSLog(@"Keychain syncing is being turned OFF"); + CFErrorRef error = NULL; + bool bx = SOSCCRemoveThisDeviceFromCircle(&error); + if (!bx) + NSLog(@"SOSCCRemoveThisDeviceFromCircle: %@", error); + }); + } +} + +- (void)flashChangeLight +{ + CABasicAnimation *theAnimation = NULL; + + theAnimation=[CABasicAnimation animationWithKeyPath:@"opacity"]; + theAnimation.duration=0.75; + theAnimation.repeatCount=5; //HUGE_VALF; + theAnimation.autoreverses=YES; + theAnimation.fromValue=[NSNumber numberWithFloat:1.0]; + theAnimation.toValue=[NSNumber numberWithFloat:0.0]; + [_stateChangedC.layer addAnimation:theAnimation forKey:@"animateOpacity"]; +} + +- (void)setStatus:(NSString *)message +{ + NSLog(@"%@", message); + _statusMessage.text = message; +} + +// +// MARK: Table view handling +// +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + PeerListCell *cell = [tableView dequeueReusableCellWithIdentifier:@"PeerTableCell" forIndexPath:(NSIndexPath *)indexPath]; + if (cell == nil) + { + NSLog(@"cellForRowAtIndexPath : cell was nil"); + cell = [[PeerListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"PeerTableCell"]; + } + + NSArray *list = NULL; + NSArray *hilighted = NULL; + if (tableView == _peerList) { + list = (__bridge_transfer NSArray*)SOSCCCopyPeerPeerInfo(NULL); + hilighted = (__bridge_transfer NSArray*)SOSCCCopyConcurringPeerPeerInfo(NULL); + } else { + list = (__bridge_transfer NSArray*)SOSCCCopyApplicantPeerInfo(NULL); + } + + if (list) { + cell.peerCircle.text = @"A"; + SOSPeerInfoRef pi = (__bridge SOSPeerInfoRef) list[[indexPath row]]; + if (pi) { + cell.peerName.text = (__bridge NSString*) SOSPeerInfoGetPeerName(pi); + if ([hilighted containsObject: (__bridge id)pi]) + cell.peerName.textColor = [UIColor greenColor]; + } + } else { + cell.peerName.text = @"Null List"; + } + + return cell; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + NSArray* list = nil; + + if (tableView == _peerList) { + list = (__bridge_transfer NSArray*) SOSCCCopyPeerPeerInfo(NULL); + } else { + list = (__bridge_transfer NSArray*) SOSCCCopyApplicantPeerInfo(NULL); + } + + return [list count]; +} + +@end + diff --git a/Keychain/ToolsViewController.h b/Keychain/ToolsViewController.h new file mode 100644 index 00000000..68ec78a7 --- /dev/null +++ b/Keychain/ToolsViewController.h @@ -0,0 +1,25 @@ +// +// ToolsViewController.h +// Keychain +// +// Created by john on 10/22/12. +// +// + +#import +#import + +@interface ToolsViewController : UIViewController { + int notificationToken; + int notificationCount; +} +@property (weak, nonatomic) IBOutlet UIButton *autopopulateButton; +@property (weak, nonatomic) IBOutlet UIButton *clearButton; +@property (weak, nonatomic) IBOutlet UIButton *clearKVS; +@property (weak, nonatomic) IBOutlet UIButton *buttonC; +@property (weak, nonatomic) IBOutlet UILabel *kvsCleared; +@property (weak, nonatomic) IBOutlet UILabel *statusMessage; + +- (void)setStatus:(NSString *)message; + +@end diff --git a/Keychain/ToolsViewController.m b/Keychain/ToolsViewController.m new file mode 100644 index 00000000..48db7f45 --- /dev/null +++ b/Keychain/ToolsViewController.m @@ -0,0 +1,180 @@ +// +// ToolsViewController.m +// Keychain +// +// Created by john on 10/22/12. +// +// + +#import "ToolsViewController.h" +#import "MyKeychain.h" + +#include +#include +#include +#include +#include +//#include + +#include +#include + +#import +#include +#include +#include +//#import "PeerListCell.h" + +static const uint64_t maxTimeToWaitInSeconds = 30ull * NSEC_PER_SEC; + +static bool testClearAll(void *sender) +{ + __block bool result = false; + dispatch_queue_t processQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0); + dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds); + + SOSCloudKeychainClearAll(processQueue, ^(CFDictionaryRef returnedValues, CFErrorRef error) + { + result = true; +// secerror("SOSCloudKeychainClearAll returned: %@", error); + dispatch_async(dispatch_get_main_queue(), + ^{ + NSLog(@"Updating because of notification"); + }); + + dispatch_semaphore_signal(waitSemaphore); + }); + + dispatch_semaphore_wait(waitSemaphore, finishTime); +//ARC dispatch_release(waitSemaphore); +// secerror("SOSCloudKeychainClearAll exit"); + return result; +} + +static void apply_block_1(const void *value, void *context) +{ + return ((__bridge void (^)(const void *value))context)(value); +} + +static inline void CFArrayForEach(CFArrayRef array, void (^operation)(const void *value)) { + CFArrayApplyFunction(array, CFRangeMake(0, CFArrayGetCount(array)), apply_block_1, (__bridge void *)(operation)); +} + +static void dumpCircleInfo() +{ + CFErrorRef error = NULL; + CFArrayRef applicantPeerInfos = NULL; + CFArrayRef peerInfos = NULL; + int idx; + + NSArray *ccmsgs = @[@"Error", @"InCircle", @"NotInCircle", @"RequestPending", @"CircleAbsent" ]; + + SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(&error); + NSLog(@"ccstatus: %d, error: %@", ccstatus, error); + idx = ccstatus-kSOSCCError; + if (0<=idx && idx<(int)[ccmsgs count]) + NSLog(@"ccstatus: %d (%@)", ccstatus, ccmsgs[idx]); + + // Now look at current applicants + applicantPeerInfos = SOSCCCopyApplicantPeerInfo(&error); + if (applicantPeerInfos) + { + NSLog(@"Applicants: %ld, error: %@", (long)CFArrayGetCount(applicantPeerInfos), error); + CFArrayForEach(applicantPeerInfos, ^(const void *value) { + SOSPeerInfoRef peer = (SOSPeerInfoRef)value; + CFStringRef peerName = SOSPeerInfoGetPeerName(peer); + NSLog(@"Applicant: %@", peerName); + }); + } + else + NSLog(@"No applicants, error: %@", error); + + + peerInfos = SOSCCCopyPeerPeerInfo(&error); + if (peerInfos) + { + NSLog(@"Peers: %ld, error: %@", (long)CFArrayGetCount(peerInfos), error); + CFArrayForEach(peerInfos, ^(const void *value) { + SOSPeerInfoRef peer = (SOSPeerInfoRef)value; + CFStringRef peerName = SOSPeerInfoGetPeerName(peer); + NSLog(@"Peer: %@", peerName); + }); + } + else + NSLog(@"No peers, error: %@", error); +} + + +@interface ToolsViewController () +@end + +@implementation ToolsViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + // Do any additional setup after loading the view, typically from a nib. + [self setStatus:@"Idle…"]; +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (void)addPasswordItem:(NSString *)account service:(NSString *)service password:(NSString *) thePassword +{ + [[MyKeychain sharedInstance] setPasswordFull:account service:service password:thePassword]; +} + +- (IBAction)handleAutoPopulate:(id)sender +{ + [self addPasswordItem:@"12345678" service:@"Evernote" password:@"fiord42/sate"]; + [self addPasswordItem:@"acct2433" service:@"SwissBank" password:@"nerd0)sorely"]; + [self addPasswordItem:@"QR49BZQ77" service:@"Wells Fargo" password:@"per1}bargirl"]; + [self addPasswordItem:@"03991993-9291" service:@"Bank of America" password:@"dabs35\angst"]; + [self addPasswordItem:@"followme" service:@"Twitter" password:@"mica86[board"]; + [self addPasswordItem:@"j18373@apple.com" service:@"Mail" password:@"macro13:VIII"]; + [self addPasswordItem:@"j18373" service:@"Facebook" password:@"vow5:karakul"]; + [self addPasswordItem:@"lonely22" service:@"G+Circles" password:@"vclub17'earls"]; + [self addPasswordItem:@"yoyo9182" service:@"Skype" password:@"Andy137#FAQs"]; + [self addPasswordItem:@"terminator3828" service:@"Blizzard" password:@"David95?hive"]; +} + +- (IBAction)handleClearKeychain:(id)sender +{ + NSLog(@"Clear All Keychain Items"); + [[MyKeychain sharedInstance] clearAllKeychainItems]; +} + +- (IBAction)handleClearKVS:(id)sender +{ + testClearAll((__bridge void *)(self)); +} + +- (IBAction)resetToEmpty:(id)sender +{ + SOSCCResetToEmpty(NULL); +} + +- (IBAction)handleDumpButton:(id)sender +{ + dumpCircleInfo(); +} + +- (IBAction)handleSync:(id)sender +{ + //SOSCCSyncWithAllPeers(); +} + +//bool +- (void)setStatus:(NSString *)message +{ + NSLog(@"%@", message); + _statusMessage.text = message; +} + +@end + diff --git a/Keychain/first.png b/Keychain/first.png new file mode 100644 index 0000000000000000000000000000000000000000..9300ee2cd85a05d8ab3d300acc09c13829ccb5ce GIT binary patch literal 253 zcmeAS@N?(olHy`uVBq!ia0vp^av;pY3?xs=ZJr3EI14-?iy0WWg+Z8+Vb&Z8prA^C zPl)UP|NntZ{NT8nT`EuocS(?6FasltZ*a@vB{%Q?+`Lrc8c;aH)5S4F;&O7r0@i?& zF{WoZ52n7mx3~H`AG5@C!zy!*9MOhPk>$<~3{&!XpXRp}%-pr`k1SV$-RV4u0*22w zAO2x6m@j;8KEt!(gFm@9e7bmb^TL_!dGfoeFWl{ZC|~k_Q9HX^MW7%9gZ;w7yrcIE Q^gxdFboFyt=akR{03BgY=Kufz literal 0 HcmV?d00001 diff --git a/Keychain/first@2x.png b/Keychain/first@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..374d78edd0e6d5db42b559bac2178edef037836a GIT binary patch literal 402 zcmeAS@N?(olHy`uVBq!ia0vp^HXzKw3=&b&bO2JE1s;*b3=CqbAk63)r1AkM=o;V? z;`;ype;|`WAeXrOCC~`5k|4ie21X_}K5=6c-?FCezLl$1U%LPN&9|Skp6V+DRb2FR zaSZV|{&t!t-(dwFhRxG9n7sM-Ke&3WQnRdOsQ#H+mQQxR%?IsgO#P;KeOB}J^*^WW zn#~dKvU&5>v!Xi!?i?%bXW@96u%f$_t!&|)uPtiNz4qKLWW4uxyKc$GyAh0z>RHi? zo?JOMgIVbMn$=FHmxgAuNz8E5cj=S)s26y^Y2l`4C#9y^`hQy?Q&Hsb^vq;qt?+p< z^QXJs7i0CAq7^vN;PmIOHOU=OL1sKI$sT45u8YIXzI2ur>+O#&*(9nR{qE3ar?Lw% i{+gxlr%3V4d&E5TcJ?AMtKADhA?WGq=d#Wzp$Pymd53oZ literal 0 HcmV?d00001 diff --git a/Keychain/main.m b/Keychain/main.m index a56dff25..c60e1380 100644 --- a/Keychain/main.m +++ b/Keychain/main.m @@ -2,13 +2,17 @@ // main.m // Keychain // -// Created by J Osborne on 2/13/13. +// Created by john on 10/22/12. // // -#import +#import + +#import "AppDelegate.h" int main(int argc, char *argv[]) { - return NSApplicationMain(argc, (const char **)argv); + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } } diff --git a/Keychain/second.png b/Keychain/second.png new file mode 100644 index 0000000000000000000000000000000000000000..1100b487f2ca4f4b885625ba575c842c210fb73c GIT binary patch literal 128 zcmeAS@N?(olHy`uVBq!ia0vp^av;pe3?v!<**pYNoCO|{#S9GG!XV7ZFl&wkP>?Oa zC&cyt|NlT{=%LGXAk`&7e!&b5&u*jvIl`VUjv*Y^lM@bb&-nj;xnQF>1H+`lD#BN) SrXB@KGkCiCxvXFVdQ&MBb@0K*?3>;M1& literal 0 HcmV?d00001 diff --git a/Keychain/utilities.c b/Keychain/utilities.c new file mode 100644 index 00000000..03764479 --- /dev/null +++ b/Keychain/utilities.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 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@ + */ + +// +// utilities.c +// + +#include +#include + +#include +#include "utilities.h" + +bool testPutObjectInCloud(CFStringRef key, CFTypeRef object, CFErrorRef *error, dispatch_group_t dgroup, dispatch_queue_t processQueue) +{ + //FIXME: The error set in the block is never returned here. + secerror("testPutObjectInCloud: key: %@, %@", key, object); + CFDictionaryRef objects = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, key, object, NULL); + if (objects) + { + dispatch_group_enter(dgroup); + SOSCloudKeychainPutObjectsInCloud(objects, processQueue, ^ (CFDictionaryRef returnedValues, CFErrorRef error2) + { + secerror("testPutObjectInCloud returned: %@", returnedValues); + if (error2) + { + secerror("testPutObjectInCloud returned: %@", error2); + } + dispatch_group_leave(dgroup); + }); + CFRelease(objects); + } + return true; // Never returns an error +} diff --git a/Keychain/utilities.h b/Keychain/utilities.h new file mode 100644 index 00000000..677b06bb --- /dev/null +++ b/Keychain/utilities.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2012-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@ + */ + +// +// utilities.h +// + +#ifndef __KEYCHAIN_UTILITIES_H__ +#define __KEYCHAIN_UTILITIES_H__ + +bool testPutObjectInCloud(CFStringRef key, CFTypeRef object, CFErrorRef *error, dispatch_group_t dgroup, dispatch_queue_t processQueue); + +#endif /* __KEYCHAIN_UTILITIES_H__ */ + diff --git a/KeychainSyncAccountNotification/KeychainSyncAccountNotification-Info.plist b/KeychainSyncAccountNotification/KeychainSyncAccountNotification-Info.plist new file mode 100644 index 00000000..9806922e --- /dev/null +++ b/KeychainSyncAccountNotification/KeychainSyncAccountNotification-Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.apple.security.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 10.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + KeychainSyncAccountNotification + + diff --git a/KeychainSyncAccountNotification/KeychainSyncAccountNotification-Prefix.pch b/KeychainSyncAccountNotification/KeychainSyncAccountNotification-Prefix.pch new file mode 100644 index 00000000..e4c16b64 --- /dev/null +++ b/KeychainSyncAccountNotification/KeychainSyncAccountNotification-Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'KeychainSyncAccountNotification' target in the 'KeychainSyncAccountNotification' project +// + +#ifdef __OBJC__ + #import +#endif diff --git a/KeychainSyncAccountNotification/KeychainSyncAccountNotification.h b/KeychainSyncAccountNotification/KeychainSyncAccountNotification.h new file mode 100644 index 00000000..81560c93 --- /dev/null +++ b/KeychainSyncAccountNotification/KeychainSyncAccountNotification.h @@ -0,0 +1,15 @@ +// +// KeychainSyncAccountNotification.h +// Security +// +// Created by keith on 5/2/13. +// +// + +#import +#import +#import + +@interface KeychainSyncAccountNotification : NSObject + +@end diff --git a/KeychainSyncAccountNotification/KeychainSyncAccountNotification.m b/KeychainSyncAccountNotification/KeychainSyncAccountNotification.m new file mode 100644 index 00000000..c00eed74 --- /dev/null +++ b/KeychainSyncAccountNotification/KeychainSyncAccountNotification.m @@ -0,0 +1,80 @@ +// +// KeychainSyncAccountNotification.m +// Security +// +// Created by keith on 5/2/13. +// +// + +#import "KeychainSyncAccountNotification.h" +#import +#import +#import +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnewline-eof" +#import +#pragma clang diagnostic pop +#import +#import +#import +#import + +@implementation KeychainSyncAccountNotification + +- (BOOL)account:(ACAccount *)account willChangeWithType:(ACAccountChangeType)changeType inStore:(ACDAccountStore *)store oldAccount:(ACAccount *)oldAccount { + if ((changeType == kACAccountChangeTypeDeleted) && [oldAccount.accountType.identifier isEqualToString:ACAccountTypeIdentifierAppleAccount]) { + if ([account aa_isPrimaryAccount]) { + + CFErrorRef removalError = NULL; + + ACLogDebug(@"Performing SOS circle credential removal for account %@: %@", oldAccount.identifier, oldAccount.username); + + if (!SOSCCRemoveThisDeviceFromCircle(&removalError)) { + ACLogError(@"Account %@ could not leave the SOS circle: %@", oldAccount.identifier, removalError); + } + } else { + ACLogDebug(@"NOT performing SOS circle credential removal for secondary account %@: %@", account.identifier, account.username); + } + } + + return YES; +} + +- (void)account:(ACAccount *)account didChangeWithType:(ACAccountChangeType)changeType inStore:(ACDAccountStore *)store oldAccount:(ACAccount *)oldAccount { + if ((changeType == kACAccountChangeTypeAdded || changeType == kACAccountChangeTypeModified) && [account.accountType.identifier isEqualToString:ACAccountTypeIdentifierAppleAccount]) { + if ([account aa_isPrimaryAccount]) { + NSError *errObject; + ACAccountCredential *accountCred = [store credentialForAccount:account error:&errObject]; + if (accountCred != NULL) { + CFErrorRef authenticateError = NULL; + if (accountCred.password != NULL) { + const char *accountPassword = [accountCred.password cStringUsingEncoding:NSUTF8StringEncoding]; + CFDataRef passwordData = CFDataCreate(kCFAllocatorDefault, (const uint8_t *)accountPassword, strlen(accountPassword)); + if (NULL != passwordData) { + ACLogDebug(@"Performing SOS circle credential set for account %@: %@", account.identifier, account.username); + if (!SOSCCSetUserCredentials((__bridge CFStringRef)(account.username), passwordData, &authenticateError)) { + ACLogError(@"Unable to set SOS circle credentials for account %@: %@", account.identifier, authenticateError); + if (NULL != authenticateError) { + CFRelease(authenticateError); + } + } + CFRelease(passwordData); + } + } else { + if (!SOSCCCanAuthenticate(&authenticateError)) { + ACLogError(@"Account %@ did not present a password and we could not authenticate the SOS circle: %@", account.identifier, authenticateError); + if (NULL != authenticateError) { + CFRelease(authenticateError); + } + } + } + } else { + ACLogError(@"Account %@ did not present a credential for SOS circle: %@", account.identifier, errObject); + } + } else { + ACLogDebug(@"NOT performing SOS circle credential set for secondary account %@: %@", account.identifier, account.username); + } + } +} + +@end diff --git a/Keychain Circle Notification/en.lproj/InfoPlist.strings b/KeychainSyncAccountNotification/en.lproj/InfoPlist.strings similarity index 100% rename from Keychain Circle Notification/en.lproj/InfoPlist.strings rename to KeychainSyncAccountNotification/en.lproj/InfoPlist.strings diff --git a/Keychain_114x114.png b/Keychain_114x114.png new file mode 100644 index 0000000000000000000000000000000000000000..0955e18ea245c3b04c5ed90180dc003fd90cb906 GIT binary patch literal 17059 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 literal 0 HcmV?d00001 diff --git a/Keychain_144x144.png b/Keychain_144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..8d0c7dd514f9464a673568baea5f704368559973 GIT binary patch literal 22702 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 QzyJUM07*qoM6N<$f}bU~-2eap literal 0 HcmV?d00001 diff --git a/Keychain_57x57.png b/Keychain_57x57.png new file mode 100644 index 0000000000000000000000000000000000000000..2eedfa0bdd94f5b7eb7b8b3d2b1ccd19f2cacdbe GIT binary patch literal 8097 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 literal 0 HcmV?d00001 diff --git a/Keychain_72x72.png b/Keychain_72x72.png new file mode 100644 index 0000000000000000000000000000000000000000..ad12ceb07baf8421d355c05144ad4024887b890e GIT binary patch literal 10006 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 + + + + com.apple.private.assets.accessible-asset-types + + com.apple.MobileAsset.PKITrustServices.PKITrustData + + + diff --git a/OTAPKIAssetTool/OTAServiceApp.h b/OTAPKIAssetTool/OTAServiceApp.h new file mode 100644 index 00000000..7ad689ef --- /dev/null +++ b/OTAPKIAssetTool/OTAServiceApp.h @@ -0,0 +1,46 @@ +// +// OTAServiceApp.h +// Security +// +// Created by local on 2/11/13. +// +// + +#import +#import + + + +@interface OTAServiceApp : NSObject +{ + NSArray* _file_list; + NSString* _manifest_file_name; + NSString* _asset_version_file_name; + NSNumber* _current_asset_version; + NSNumber* _next_asset_version; + NSString* _current_asset_directory; + NSString* _assets_directory; + NSFileManager* _fileManager; + uid_t _uid; /* user uid */ + gid_t _gid; + CFTimeInterval _asset_query_retry_interval; + bool _verbose; +} + +@property (readonly) NSArray* file_list; +@property (readonly) NSString* manifest_file_name; +@property (readonly) NSString* asset_version_file_name; +@property (readonly) NSNumber* current_asset_version; +@property (readonly) NSNumber* next_asset_version; +@property (readonly) NSString* current_asset_directory; +@property (readonly) NSString* assets_directory; +@property (readonly) NSFileManager* fileManager; +@property (readonly) uid_t uid; +@property (readonly) gid_t gid; + + +- (id)init:(int)argc withArguments:(const char**)argv; + +- (void)checkInWithActivity; + +@end diff --git a/OTAPKIAssetTool/OTAServiceApp.m b/OTAPKIAssetTool/OTAServiceApp.m new file mode 100644 index 00000000..e6259879 --- /dev/null +++ b/OTAPKIAssetTool/OTAServiceApp.m @@ -0,0 +1,1384 @@ +// +// OTAServiceApp.m +// Security +// +// Created by local on 2/11/13. +// +// + + +#import "OTAServiceApp.h" + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#if !TARGET_IPHONE_SIMULATOR +#import +#endif + +#import +#import +#import +#import +#import +#import +#import +#import + +#define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) { CFRelease(_cf); } } +#define CFReleaseNull(CF) { CFTypeRef _cf = (CF); if (_cf) { (CF) = NULL; CFRelease(_cf); } } + +//#define VERBOSE_LOGGING 1 + +#if VERBOSE_LOGGING + +static void OTAPKI_LOG(const char* sz, ...) +{ + va_list va; + va_start(va, sz); + + FILE* fp = fopen("/tmp/OTAPKITool.log", "a"); + if (NULL != fp) + { + vfprintf(fp, sz, va); + fclose(fp); + } + va_end(va); +} + +#else + +#define OTAPKI_LOG(sz, ...) + +#endif + +//#define NEW_LOCATION 1 + + + +/* ========================================================================== + The following are a set of string constants used by this program. + + kBaseAssetDirectoryPath - This is the full path on the device that + will contain the Assets directory. This + directory was chosen because it is owned + by securityd + + kkManifestFileName - The file name of the manifest file for the + OTA PKI trust asset + + kAssetVersionFileName - The file name of the plist file in the asset + that contains the version number of this + OTA PKI trust asset. It is a plist that is a + dictionary with a single key with a single + key value pair that has the version number + of the asset. This is used to ensure against + anti-replay. + + kBlockKeyFileName - The file name of the asset file that contains + blocked keys. Any certificate with these keys + will be marked as not being trusted. + + kGrayListedKeysFileName - The file name of the asset file that contains + gray listed keys. If a chain has any of these + keys, than the chain will still be approved but + an entry will be added to the details dictionary + noting that the key was gray listed + + + kEVRootsFileName - The file name of the asset file that contains + the list of EV OIDS and their corresponding + certificates. This file sets which certs will + be considered to be EV. + + 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. + + kCertsTableFileName - The file name of the asset file that contains + all of the anchor certificates. The + kCertsIndexFileName file is used to find the + correct offset in this file to retrieve a + specific anchor certificate. + + kVersionNumberKey - The dictionary key for the kAssetVersionFileName + file to get the version number + + kVersionDirectoryNamePrefix - + The directory name prefix for all of the + asset directorys + + kPKITrustDataAssetType - The asset identifier of the OTA PKI asset + + +========================================================================== */ + +#if NEW_LOCATION +static const NSString* kBaseAssetDirectoryPath = @"/var/OTAPKI"; +#else +static const NSString* kBaseAssetDirectoryPath = @"/var/Keychains"; +#endif + +static const NSString* kManifestFileName = @"manifest.data"; +static const NSString* kAssetVersionFileName = @"AssetVersion.plist"; +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* kCertsIndexFileName = @"certsIndex.data"; +static const NSString* kCertsTableFileName = @"certsTable.data"; +static const NSString* kVersionNumberKey = @"VersionNumber"; +static const NSString* kAssetDirectoryName = @"Assets"; +static const NSString* kAssetDirectoryUser = @"_securityd"; +static const NSString* kAssetDirectoryGroup = @"wheel"; +#if NEW_LOCATION +static const unsigned long kAssetDirectoryPermission = S_IRWXU | S_IRWXG | S_IRWXO; +#else +static const unsigned long kAssetDirectoryPermission = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; +#endif +static const NSString* kVersionDirectoryNamePrefix = @"Version_"; +static const NSString* kPKITrustDataAssetType =@"com.apple.MobileAsset.PKITrustServices.PKITrustData"; + +const char *kOTAPKIAssetToolActivity = "com.apple.OTAPKIAssetTool.asset-check"; + +static const UInt8 kApplePKISettingsRootCACert[] = { + 0x30, 0x82, 0x07, 0xca, 0x30, 0x82, 0x05, 0xb2, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x4e, + 0xa1, 0x31, 0xe7, 0xca, 0x50, 0xb8, 0x97, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x30, 0x81, 0x84, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, + 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, + 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x1e, 0x17, + 0x0d, 0x31, 0x33, 0x30, 0x36, 0x32, 0x34, 0x32, 0x33, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x17, 0x0d, + 0x34, 0x33, 0x30, 0x36, 0x31, 0x37, 0x32, 0x33, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x30, 0x81, 0x84, + 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x65, + 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, + 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, + 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, + 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, + 0x02, 0x82, 0x02, 0x01, 0x00, 0xce, 0x15, 0xf7, 0x6f, 0xd8, 0x42, 0x0c, 0x6f, 0x45, 0xb4, 0x04, + 0x59, 0x24, 0xcb, 0x70, 0x88, 0x84, 0x77, 0xa1, 0x91, 0x54, 0xf4, 0x87, 0x61, 0xb3, 0xd3, 0xfc, + 0xbe, 0xb6, 0x05, 0x3c, 0xb9, 0xb7, 0x7d, 0x7c, 0xbc, 0x0b, 0xe8, 0x87, 0x07, 0xcf, 0x20, 0xbe, + 0xaa, 0xeb, 0x24, 0xc5, 0xe4, 0x5c, 0xcd, 0xcb, 0x89, 0x9f, 0x7a, 0xea, 0xb4, 0x5d, 0x3b, 0x29, + 0x6c, 0xba, 0x4d, 0x15, 0xfb, 0x59, 0xd0, 0x5a, 0xea, 0x41, 0x4e, 0x0d, 0x1d, 0xf7, 0x66, 0x77, + 0xa2, 0x96, 0x56, 0xed, 0xd1, 0x16, 0x7b, 0xea, 0xf5, 0x60, 0xdf, 0x32, 0x9c, 0xa9, 0xfd, 0xbf, + 0xb8, 0x34, 0x6f, 0x57, 0x17, 0xe6, 0x04, 0x37, 0x71, 0x07, 0xc0, 0xe9, 0x0f, 0x3c, 0xed, 0x4f, + 0x31, 0x87, 0x05, 0xa4, 0xed, 0xab, 0xac, 0xd6, 0x50, 0x05, 0x5b, 0xca, 0xd3, 0xf9, 0xd6, 0xaa, + 0xaa, 0x88, 0x57, 0x66, 0xf6, 0x6d, 0x8d, 0x4b, 0x71, 0x29, 0xd4, 0x3d, 0x1d, 0xbc, 0x82, 0x6e, + 0x81, 0xe9, 0x19, 0xf5, 0xe1, 0x12, 0x9f, 0x47, 0xdb, 0x5c, 0xed, 0x88, 0xba, 0x51, 0xe7, 0x3a, + 0xa0, 0x77, 0x2d, 0xe6, 0xcc, 0xb4, 0x34, 0xdf, 0xad, 0xbd, 0x7b, 0xf8, 0xa7, 0x79, 0x51, 0x2d, + 0xe6, 0xc2, 0xee, 0xd2, 0x96, 0xfa, 0x60, 0x60, 0x32, 0x40, 0x41, 0x37, 0x12, 0xeb, 0x63, 0x99, + 0x3d, 0xf3, 0x21, 0xbe, 0xdf, 0xa1, 0x77, 0xe6, 0x81, 0xa9, 0x99, 0x0c, 0x4b, 0x43, 0x0c, 0x05, + 0x6a, 0x6b, 0x8f, 0x05, 0x02, 0xd9, 0x43, 0xab, 0x72, 0x76, 0xca, 0xa7, 0x75, 0x63, 0x85, 0xe3, + 0xa5, 0x5c, 0xc0, 0xd6, 0xd4, 0x1c, 0xeb, 0xac, 0x2c, 0x9a, 0x15, 0x6b, 0x4e, 0x99, 0x74, 0x7d, + 0xd2, 0x69, 0x9f, 0xa8, 0xf7, 0x65, 0xde, 0xeb, 0x36, 0x85, 0xd5, 0x7e, 0x4a, 0x7a, 0x8a, 0xeb, + 0x7c, 0xcd, 0x43, 0x9e, 0x05, 0xdb, 0x34, 0xc3, 0x69, 0xbd, 0xc2, 0xe7, 0xfb, 0xa0, 0x43, 0xb3, + 0xd7, 0x15, 0x28, 0x8a, 0x91, 0xce, 0xd7, 0xa7, 0xa4, 0xcc, 0xf4, 0x1b, 0x37, 0x33, 0x76, 0xc4, + 0x58, 0xb9, 0x2d, 0x89, 0xe2, 0xb6, 0x2c, 0x56, 0x10, 0x96, 0xcc, 0xa6, 0x07, 0x79, 0x11, 0x7d, + 0x26, 0xd2, 0x85, 0x22, 0x19, 0x20, 0xb7, 0xef, 0xc3, 0xd9, 0x4e, 0x18, 0xf3, 0xaa, 0x05, 0xce, + 0x87, 0x99, 0xde, 0x76, 0x90, 0x08, 0x74, 0xac, 0x61, 0x31, 0xf8, 0x51, 0xa0, 0xc9, 0x70, 0xfc, + 0xb9, 0x22, 0xfe, 0xd2, 0x0d, 0xc8, 0x49, 0x64, 0x00, 0xe4, 0xf1, 0x53, 0xfd, 0xa1, 0xe6, 0xff, + 0x8e, 0xd6, 0xde, 0x9e, 0xcc, 0x3d, 0x37, 0x3a, 0x10, 0x62, 0x59, 0xb2, 0x34, 0x8a, 0x1d, 0xf7, + 0x9e, 0xa0, 0xbb, 0xf4, 0x53, 0xd9, 0xb8, 0x18, 0x88, 0x12, 0x5c, 0x92, 0x0d, 0xc9, 0x94, 0x7f, + 0x24, 0xb9, 0x9f, 0xda, 0x07, 0xb6, 0x79, 0x77, 0x09, 0xa3, 0x29, 0x3a, 0x70, 0x63, 0x3b, 0x22, + 0x42, 0x14, 0xd0, 0xf9, 0x7b, 0x90, 0x52, 0x2b, 0x3f, 0x7f, 0xb7, 0x41, 0x20, 0x0d, 0x7e, 0x70, + 0xd7, 0x88, 0x36, 0xa2, 0xe9, 0x81, 0x77, 0xf4, 0xb0, 0x15, 0x43, 0x9c, 0x5f, 0x4d, 0x3e, 0x4f, + 0x83, 0x79, 0x06, 0x73, 0x7a, 0xe7, 0xcb, 0x79, 0x1d, 0xec, 0xa3, 0xce, 0x93, 0x5c, 0x68, 0xbf, + 0x5a, 0xe6, 0x4c, 0x23, 0x86, 0x41, 0x7f, 0xb4, 0xfc, 0xd0, 0x2c, 0x1b, 0x64, 0x39, 0x64, 0xb7, + 0xd2, 0x1d, 0xd0, 0x2d, 0x16, 0x77, 0xfe, 0x4d, 0xad, 0xf0, 0x4f, 0x38, 0xb3, 0xf9, 0x5a, 0xee, + 0x0e, 0x1d, 0xb6, 0xf9, 0x3f, 0xba, 0x77, 0x5a, 0x20, 0xd2, 0x74, 0x1a, 0x4b, 0x5a, 0xaf, 0x62, + 0xb5, 0xd3, 0xef, 0x37, 0x49, 0xfe, 0x1e, 0xcd, 0xb5, 0xba, 0xb5, 0xa6, 0x46, 0x7b, 0x38, 0x63, + 0x62, 0x3c, 0x18, 0x7d, 0x57, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x02, 0x3c, 0x30, 0x82, + 0x02, 0x38, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x35, 0x07, 0x82, + 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f, 0x61, 0xb6, + 0x1c, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, + 0x01, 0xff, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x35, + 0x07, 0x82, 0xfe, 0x0e, 0x8f, 0xf5, 0xa0, 0x7c, 0x2e, 0xf9, 0x65, 0x7b, 0xa8, 0x48, 0xe8, 0x8f, + 0x61, 0xb6, 0x1c, 0x30, 0x82, 0x01, 0xd3, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x82, 0x01, 0xca, + 0x30, 0x82, 0x01, 0xc6, 0x30, 0x82, 0x01, 0xc2, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, + 0x64, 0x05, 0x01, 0x30, 0x82, 0x01, 0xb3, 0x30, 0x82, 0x01, 0x78, 0x06, 0x08, 0x2b, 0x06, 0x01, + 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x82, 0x01, 0x6a, 0x1e, 0x82, 0x01, 0x66, 0x00, 0x52, 0x00, + 0x65, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, + 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, + 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, + 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, + 0x6e, 0x00, 0x79, 0x00, 0x20, 0x00, 0x70, 0x00, 0x61, 0x00, 0x72, 0x00, 0x74, 0x00, 0x79, 0x00, + 0x20, 0x00, 0x61, 0x00, 0x73, 0x00, 0x73, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00, + 0x20, 0x00, 0x61, 0x00, 0x63, 0x00, 0x63, 0x00, 0x65, 0x00, 0x70, 0x00, 0x74, 0x00, 0x61, 0x00, + 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00, + 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, 0x00, + 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x62, 0x00, + 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, + 0x61, 0x00, 0x72, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6d, 0x00, + 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, + 0x6e, 0x00, 0x64, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, 0x00, + 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x2c, 0x00, + 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, + 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x6c, 0x00, + 0x69, 0x00, 0x63, 0x00, 0x79, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, + 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, + 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x70, 0x00, 0x72, 0x00, + 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, + 0x74, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, + 0x73, 0x00, 0x2e, 0x30, 0x35, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, + 0x29, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x61, 0x70, 0x70, 0x6c, + 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, + 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x6f, 0x8a, + 0xb7, 0x35, 0x73, 0x5a, 0xc5, 0x34, 0xf7, 0x8c, 0xf0, 0xd1, 0x4a, 0x17, 0x52, 0x1c, 0x70, 0xf0, + 0xe0, 0x53, 0xb4, 0x16, 0xde, 0x81, 0xda, 0x2a, 0xa4, 0xf9, 0x5b, 0x0e, 0xa6, 0x17, 0x86, 0x52, + 0xc6, 0x70, 0x73, 0xf3, 0x3f, 0x1c, 0x87, 0x94, 0xdd, 0xfe, 0x02, 0x0b, 0x85, 0xc9, 0xb9, 0xcf, + 0x15, 0x91, 0x05, 0x2e, 0x7e, 0xeb, 0xe6, 0xce, 0x0e, 0x4e, 0xd1, 0xf7, 0xe2, 0xd7, 0xf4, 0x60, + 0xd2, 0xfc, 0x1d, 0xbf, 0xad, 0x61, 0x28, 0xf8, 0x53, 0x31, 0xb3, 0x92, 0xef, 0xa4, 0x05, 0x34, + 0x97, 0x57, 0x97, 0x56, 0x3b, 0x12, 0x20, 0x2d, 0x88, 0x76, 0x81, 0x0e, 0x77, 0x85, 0xf1, 0x37, + 0xc6, 0x19, 0x8b, 0x23, 0xc2, 0x42, 0x55, 0x40, 0xc9, 0x91, 0x5c, 0x78, 0xc5, 0xe6, 0x77, 0xfe, + 0x72, 0x5f, 0xb2, 0x2c, 0x00, 0xf2, 0xe6, 0x8c, 0xcc, 0x02, 0x49, 0xd9, 0x78, 0x20, 0xae, 0xbd, + 0x75, 0x61, 0x6a, 0xaa, 0xc5, 0x71, 0x3e, 0x5d, 0x02, 0xdf, 0xd2, 0x91, 0x5c, 0x0a, 0x85, 0xc9, + 0x59, 0x7d, 0x4e, 0x89, 0x21, 0x59, 0x59, 0xe3, 0xc7, 0xdc, 0xff, 0x1e, 0x62, 0x1e, 0xb9, 0x62, + 0x2c, 0x34, 0x49, 0x15, 0xd9, 0xdf, 0x47, 0x99, 0x39, 0xcc, 0x1a, 0x01, 0xc0, 0xda, 0x48, 0x44, + 0xd4, 0x8b, 0xd3, 0x17, 0x7e, 0x39, 0xf9, 0x00, 0xe1, 0x2a, 0x46, 0xaa, 0x14, 0x22, 0xa1, 0x38, + 0x09, 0x0b, 0xb7, 0x0c, 0x88, 0xa5, 0x73, 0xfd, 0xc4, 0x6b, 0xee, 0x07, 0xb4, 0x1b, 0xb3, 0x4a, + 0xab, 0xae, 0xf6, 0xe7, 0x04, 0x61, 0x4b, 0x34, 0x7a, 0xe4, 0xff, 0xf9, 0x30, 0x28, 0x61, 0x92, + 0x52, 0x58, 0x10, 0x15, 0x3a, 0x9f, 0x0a, 0xaf, 0x15, 0x29, 0x6c, 0x67, 0xc4, 0xb4, 0xcf, 0xe6, + 0xf9, 0x46, 0x68, 0xe2, 0x2a, 0x97, 0x29, 0x16, 0xed, 0x1a, 0x9b, 0x9a, 0x45, 0x70, 0x3c, 0xf2, + 0xdf, 0x29, 0x20, 0x9e, 0x33, 0x4b, 0x5b, 0x8d, 0xf6, 0x19, 0xec, 0x4b, 0xae, 0x1a, 0x2f, 0x53, + 0x03, 0x9a, 0xfd, 0x68, 0x39, 0x58, 0xf7, 0x2e, 0x07, 0x9c, 0xf1, 0x3c, 0x1b, 0x47, 0x43, 0x19, + 0x81, 0x0e, 0x0a, 0xbb, 0x84, 0xa0, 0xda, 0x87, 0xbc, 0x8a, 0x2a, 0xb7, 0x9c, 0xe1, 0xf9, 0xeb, + 0x37, 0xb0, 0x11, 0x20, 0x7e, 0x4c, 0x11, 0x2e, 0x54, 0x30, 0xce, 0xaf, 0x63, 0xed, 0x6a, 0x63, + 0x1f, 0x1e, 0x61, 0x62, 0x04, 0xf3, 0x3a, 0x5f, 0x26, 0x6c, 0x5c, 0xd7, 0xba, 0x4f, 0xf2, 0x61, + 0x26, 0x29, 0x99, 0xea, 0x61, 0x84, 0x0d, 0x68, 0xa2, 0x5d, 0x9b, 0x5c, 0xe7, 0x86, 0x1d, 0xef, + 0xf4, 0x6f, 0x3b, 0x6c, 0x67, 0xf0, 0x70, 0xe9, 0xc5, 0xdc, 0x0a, 0x9d, 0x0f, 0xdc, 0xcc, 0x0e, + 0x7b, 0xf8, 0xc4, 0xee, 0x64, 0xe4, 0xd9, 0x3f, 0x14, 0xae, 0x8f, 0xc8, 0x18, 0x4d, 0xa1, 0xe4, + 0x40, 0x2c, 0xe9, 0x13, 0xc6, 0xc1, 0xe0, 0xb9, 0x13, 0xbe, 0xd9, 0x93, 0x66, 0x56, 0x35, 0x5c, + 0xc1, 0x38, 0x7d, 0xa1, 0xbb, 0x87, 0xa5, 0x90, 0x33, 0x4f, 0xea, 0xb6, 0x37, 0x19, 0x61, 0x81, + 0x40, 0xba, 0xd7, 0x07, 0x69, 0x05, 0x15, 0x96, 0xe9, 0xde, 0x4f, 0x8a, 0x2b, 0x99, 0x5a, 0x17, + 0x3f, 0x9f, 0xcf, 0x86, 0xf5, 0x37, 0x0a, 0xa1, 0x0e, 0x25, 0x65, 0x2d, 0x52, 0xce, 0x87, 0x10, + 0x0f, 0x25, 0xc2, 0x1e, 0x0f, 0x71, 0x93, 0xb5, 0xc0, 0xb3, 0xb4, 0xd1, 0x65, 0xa8, 0xb4, 0xf6, + 0xa5, 0x71, 0xad, 0x45, 0xdb, 0xdf, 0xec, 0xe3, 0x2a, 0x7e, 0x99, 0x96, 0x5a, 0x5d, 0x69, 0xfa, + 0xdb, 0x13, 0x39, 0xb8, 0xf5, 0x58, 0xbb, 0x87, 0x69, 0x8d, 0x2c, 0x6d, 0x39, 0xff, 0x26, 0xce, + 0x2c, 0xa8, 0x5a, 0x7e, 0x4b, 0x3f, 0xed, 0xac, 0x5f, 0xf0, 0xef, 0x48, 0xd3, 0xf8 +}; + + +static const UInt8 kAppleTestPKISettingsRootCACert[] = { + 0x30, 0x82, 0x05, 0xd7, 0x30, 0x82, 0x03, 0xbf, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x26, + 0xfe, 0xf8, 0xda, 0x41, 0xf3, 0x61, 0x90, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x30, 0x79, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0c, 0x24, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, + 0x54, 0x45, 0x53, 0x54, 0x49, 0x4e, 0x47, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, + 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x34, 0x32, 0x32, 0x32, 0x30, 0x33, 0x31, 0x34, + 0x36, 0x5a, 0x17, 0x0d, 0x34, 0x33, 0x30, 0x34, 0x31, 0x35, 0x32, 0x30, 0x33, 0x31, 0x34, 0x36, + 0x5a, 0x30, 0x79, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x24, 0x41, 0x70, + 0x70, 0x6c, 0x65, 0x20, 0x50, 0x4b, 0x49, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, + 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x54, 0x45, 0x53, 0x54, 0x49, + 0x4e, 0x47, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, + 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 0x02, 0x22, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0x84, 0xbe, 0xc2, + 0x69, 0x9b, 0xec, 0xd5, 0xde, 0x72, 0xf0, 0x4f, 0x78, 0x81, 0x10, 0xa9, 0x56, 0x59, 0x77, 0x9c, + 0x46, 0x95, 0xd7, 0xb7, 0x0b, 0x77, 0x73, 0x02, 0xce, 0xf8, 0xaa, 0x32, 0x89, 0xee, 0xbe, 0xaa, + 0x40, 0x53, 0xf9, 0x2d, 0x96, 0x08, 0xcd, 0x2a, 0xa4, 0x61, 0xd4, 0xfd, 0x7d, 0x67, 0x2a, 0x35, + 0xc1, 0xfc, 0x43, 0xa4, 0x9c, 0xd0, 0xbd, 0xcd, 0x82, 0x27, 0xed, 0xa1, 0x1c, 0x2d, 0x9a, 0x62, + 0xd5, 0x99, 0xbd, 0x74, 0xaa, 0xf3, 0xce, 0x78, 0xc6, 0x47, 0x07, 0x43, 0x04, 0x5b, 0xbc, 0x27, + 0x5e, 0x26, 0x3e, 0x77, 0x90, 0x69, 0x7a, 0xf6, 0xe0, 0x8e, 0xaa, 0xdf, 0x96, 0x12, 0x2c, 0xb2, + 0x8b, 0xb9, 0x7e, 0x17, 0xfe, 0xde, 0x99, 0x67, 0x9b, 0x50, 0x13, 0x5c, 0x8d, 0x15, 0x26, 0x0a, + 0x9f, 0x08, 0x2f, 0x3f, 0x7c, 0x01, 0x2c, 0x3e, 0xa1, 0xba, 0xb1, 0x25, 0x33, 0xe5, 0xd9, 0x39, + 0x37, 0xde, 0x06, 0x3a, 0x63, 0x48, 0xa0, 0x9d, 0x3b, 0xa5, 0x72, 0x46, 0xfb, 0x6e, 0xa2, 0xd4, + 0x74, 0xe6, 0xf1, 0xc1, 0x69, 0xc8, 0x31, 0xff, 0x58, 0x84, 0x3a, 0xc2, 0x6b, 0x9a, 0x0d, 0x19, + 0x76, 0xe4, 0xd4, 0x4d, 0x85, 0xbc, 0x84, 0xf0, 0x07, 0x75, 0x66, 0x5f, 0xd7, 0xea, 0xab, 0x9e, + 0x46, 0xf2, 0x8a, 0x29, 0xab, 0x73, 0x57, 0xaf, 0x95, 0x4f, 0xc7, 0xf3, 0x3b, 0x55, 0xb4, 0x26, + 0x57, 0x68, 0xe9, 0x5a, 0x34, 0xbb, 0xa9, 0x39, 0xb3, 0x57, 0x5f, 0x25, 0x93, 0xd6, 0x34, 0xb7, + 0xd1, 0xc4, 0xd7, 0x70, 0xed, 0x30, 0xdb, 0x21, 0xc1, 0xcc, 0xdf, 0xed, 0xec, 0x37, 0xc5, 0xdc, + 0x0b, 0xc9, 0x85, 0x46, 0x26, 0xa7, 0x51, 0xc8, 0xdd, 0xe6, 0x47, 0xfc, 0x37, 0xd6, 0x73, 0x6f, + 0x91, 0x3d, 0xef, 0xd8, 0xa4, 0xa5, 0x08, 0x32, 0x8c, 0xae, 0x8f, 0x57, 0xf7, 0x99, 0x48, 0xef, + 0x81, 0x44, 0xac, 0x80, 0x42, 0x57, 0x9f, 0x64, 0x77, 0x40, 0x2a, 0xec, 0x03, 0x21, 0x79, 0x01, + 0x0b, 0x87, 0xc3, 0x9d, 0x22, 0xc9, 0xc0, 0x69, 0xe0, 0x34, 0xff, 0x73, 0xdd, 0x1e, 0x1b, 0x0c, + 0xe0, 0x68, 0xf0, 0x8c, 0x7a, 0x4b, 0xcd, 0x1d, 0x3f, 0x38, 0x2d, 0xe8, 0x9b, 0x91, 0xa6, 0xfe, + 0xa8, 0x8b, 0x45, 0x1c, 0xdf, 0xaf, 0x49, 0x34, 0x48, 0x17, 0x02, 0x28, 0xdb, 0xe0, 0x6e, 0x74, + 0x34, 0xea, 0xac, 0x6b, 0x00, 0x45, 0x89, 0xa9, 0xb5, 0x63, 0xbd, 0x2f, 0xe0, 0x58, 0x2e, 0xd3, + 0xc2, 0x74, 0xa2, 0x37, 0x37, 0x62, 0xf6, 0x76, 0x1b, 0x3f, 0xfb, 0x98, 0x64, 0x13, 0xd6, 0x8c, + 0xa0, 0x0c, 0xbc, 0x54, 0x00, 0xe0, 0xf8, 0x63, 0x17, 0x22, 0x44, 0x36, 0xe0, 0x28, 0xa0, 0x7d, + 0x50, 0x9e, 0x50, 0x94, 0xea, 0xd7, 0x62, 0xab, 0x6d, 0x7a, 0x19, 0xa4, 0xa2, 0x74, 0x79, 0x5d, + 0x15, 0x85, 0x21, 0xfe, 0x9a, 0x35, 0x76, 0x40, 0x78, 0x01, 0xe3, 0x46, 0x2f, 0x6f, 0x2d, 0x0a, + 0x1d, 0xac, 0x2e, 0x23, 0xec, 0xb8, 0x48, 0x74, 0xbc, 0xee, 0x29, 0x72, 0xb6, 0xe7, 0x52, 0x8c, + 0xd4, 0x1a, 0x00, 0x34, 0x75, 0x1c, 0x4b, 0x83, 0x50, 0xbb, 0x57, 0x21, 0x9b, 0xd8, 0xb4, 0x75, + 0xf3, 0x98, 0x8a, 0x9b, 0x45, 0xa8, 0x61, 0x50, 0x10, 0xb4, 0xec, 0x91, 0x2e, 0xe7, 0xf2, 0xb8, + 0xb9, 0x62, 0x70, 0xc2, 0x93, 0xe7, 0xd9, 0xf1, 0x02, 0x27, 0xd7, 0xec, 0xde, 0x5b, 0x42, 0xa1, + 0x26, 0x37, 0x41, 0x32, 0x65, 0x11, 0x63, 0x38, 0xbb, 0x6f, 0x23, 0x7a, 0xa0, 0xb7, 0x24, 0xeb, + 0xa8, 0x38, 0x8b, 0xa7, 0x73, 0xe2, 0xc8, 0x30, 0x56, 0x73, 0x6f, 0x17, 0x6e, 0x1a, 0xe5, 0x32, + 0xff, 0xd6, 0xa2, 0x08, 0x7b, 0x6a, 0x23, 0x33, 0x9f, 0x10, 0x05, 0x71, 0xdd, 0x02, 0x03, 0x01, + 0x00, 0x01, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, + 0x14, 0xd2, 0xa5, 0x3b, 0xf2, 0x5d, 0xfd, 0x1f, 0x25, 0xda, 0xfb, 0x06, 0xfb, 0x59, 0x99, 0xc4, + 0xac, 0xc4, 0x0b, 0xac, 0x64, 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, 0xd2, 0xa5, 0x3b, 0xf2, 0x5d, 0xfd, 0x1f, 0x25, 0xda, 0xfb, 0x06, 0xfb, 0x59, + 0x99, 0xc4, 0xac, 0xc4, 0x0b, 0xac, 0x64, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, + 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x71, 0x10, 0x3c, 0x89, 0xd5, + 0xc0, 0x00, 0xdc, 0x36, 0x1d, 0x93, 0xaa, 0xab, 0x4a, 0xb6, 0xfa, 0xa8, 0x5b, 0x89, 0x1c, 0xb3, + 0x4a, 0x04, 0x2e, 0xb3, 0x25, 0x0f, 0x12, 0x07, 0x29, 0x70, 0x3d, 0x34, 0xd1, 0xdd, 0x7e, 0x30, + 0xfd, 0xf5, 0xfa, 0x94, 0xf4, 0xcb, 0xdb, 0xac, 0x1b, 0xed, 0xe5, 0x11, 0x4a, 0xc8, 0xab, 0x26, + 0xe2, 0x41, 0xcb, 0xa5, 0x74, 0x4b, 0xe1, 0xd2, 0xf3, 0x83, 0x1c, 0x7a, 0xcb, 0x29, 0xd9, 0xd2, + 0xa6, 0x9d, 0x08, 0x95, 0x73, 0x63, 0xe2, 0x9c, 0xeb, 0xa5, 0x82, 0x8b, 0x6c, 0xf4, 0x64, 0x98, + 0x03, 0x53, 0x91, 0x35, 0x04, 0x89, 0x25, 0xa0, 0x1f, 0xdc, 0x42, 0xf7, 0x59, 0x44, 0x63, 0x75, + 0xe6, 0x49, 0x10, 0x66, 0x0f, 0x08, 0x07, 0x39, 0xc4, 0x3e, 0x1f, 0xba, 0x30, 0x42, 0xf8, 0x7a, + 0xc8, 0xbe, 0x6f, 0xdb, 0xec, 0x16, 0xb2, 0x76, 0x84, 0x2c, 0x6e, 0x20, 0xd1, 0xbd, 0xd5, 0x90, + 0x22, 0x0a, 0x90, 0x5c, 0x70, 0x47, 0xc9, 0x2d, 0xe3, 0x77, 0x74, 0xfd, 0xbb, 0x85, 0x1a, 0xd8, + 0x5c, 0x38, 0x94, 0x4c, 0x83, 0x28, 0x23, 0xa5, 0x4f, 0x55, 0x5f, 0xe3, 0x42, 0x80, 0x10, 0xd4, + 0xa5, 0x8d, 0xcf, 0x8b, 0x53, 0x69, 0x6d, 0xc5, 0x37, 0xd2, 0xfa, 0xbb, 0xc0, 0x5a, 0xab, 0x6f, + 0x71, 0x37, 0x92, 0xd4, 0x90, 0xef, 0x5d, 0xf1, 0xc3, 0xb8, 0x64, 0x08, 0xd3, 0xba, 0x36, 0x69, + 0x2b, 0x00, 0xed, 0xad, 0x36, 0x21, 0x38, 0xdf, 0x4a, 0xc6, 0x44, 0xc4, 0x6b, 0xd8, 0xb0, 0x7f, + 0x67, 0x05, 0xaa, 0x6f, 0x9e, 0x8a, 0xf1, 0x81, 0x95, 0x99, 0xb9, 0x56, 0xf4, 0x73, 0xa7, 0xb4, + 0x19, 0xb9, 0x4b, 0xb8, 0x1d, 0x10, 0xa5, 0x88, 0x7c, 0x39, 0xa3, 0x85, 0xe7, 0xba, 0x65, 0x86, + 0xca, 0xf7, 0x0e, 0xe0, 0x0d, 0x73, 0x3f, 0xea, 0x98, 0x88, 0x58, 0x73, 0xfa, 0x68, 0x5b, 0xaa, + 0x8c, 0xfd, 0x3e, 0x22, 0x3e, 0x92, 0xc7, 0xe2, 0x77, 0x14, 0x81, 0xe6, 0xd9, 0xdc, 0xc1, 0xe9, + 0xc0, 0x06, 0x57, 0xb4, 0xca, 0xb6, 0x14, 0x15, 0x16, 0x80, 0x7e, 0xc5, 0x11, 0xa4, 0x05, 0x66, + 0xad, 0x1d, 0xa3, 0xb6, 0xab, 0x2a, 0xbe, 0xd0, 0x52, 0x4e, 0x9e, 0x84, 0x61, 0x6b, 0xf4, 0x34, + 0x23, 0x94, 0x24, 0xc6, 0xc8, 0xb0, 0x94, 0x22, 0x4c, 0x3b, 0xac, 0x85, 0xe3, 0xd4, 0xf7, 0x38, + 0xe5, 0x9a, 0x76, 0xb3, 0x1b, 0xf0, 0xbc, 0x78, 0xc6, 0x6f, 0x11, 0xb3, 0x1a, 0x5c, 0x4f, 0x07, + 0x52, 0x06, 0x92, 0x7a, 0x25, 0x86, 0x91, 0x71, 0x8a, 0xf4, 0x03, 0xce, 0x19, 0x0d, 0xfc, 0xde, + 0x8f, 0xc9, 0x4e, 0x84, 0xf1, 0x17, 0x18, 0x6f, 0x37, 0x56, 0xb9, 0x76, 0x7e, 0x8f, 0xca, 0xde, + 0xd4, 0x1b, 0x2d, 0x8d, 0xcf, 0x12, 0x9f, 0xf9, 0xb9, 0x8b, 0x82, 0x8f, 0x4d, 0xb7, 0x63, 0x26, + 0x8d, 0xda, 0x35, 0x94, 0x18, 0xf9, 0x55, 0xca, 0x39, 0x09, 0xe9, 0x62, 0xe1, 0x00, 0xd8, 0x67, + 0xed, 0x5e, 0x84, 0xc2, 0xe5, 0x8e, 0x46, 0x57, 0xa4, 0xa7, 0x17, 0x70, 0xcf, 0x6d, 0xdf, 0x43, + 0x64, 0x2b, 0x36, 0xe6, 0xf3, 0xc1, 0x4c, 0x7a, 0x7e, 0x9e, 0x47, 0xc4, 0x14, 0x82, 0xbe, 0x94, + 0x73, 0x54, 0xd0, 0x2c, 0xc2, 0x31, 0xc6, 0xd5, 0xc3, 0xd7, 0xa9, 0xef, 0x11, 0x24, 0x2f, 0xd0, + 0x5b, 0xb8, 0x6a, 0x8e, 0x3c, 0xb7, 0x4b, 0x00, 0x9b, 0xc1, 0xca, 0x00, 0x6f, 0xd4, 0x73, 0x93, + 0x2e, 0x39, 0x37, 0x2a, 0x73, 0x44, 0x9b, 0x1b, 0x05, 0x1a, 0x7c, 0x2f, 0xc9, 0x2b, 0x37, 0xf3, + 0xcd, 0x8c, 0x4e, 0xc2, 0x7a, 0x6e, 0xd9, 0xd4, 0xf1, 0x8d, 0x6d, 0x07, 0x4b, 0xb5, 0x09, 0xb9, + 0x48, 0x55, 0xac, 0xc6, 0x7e, 0xbc, 0xc6, 0x76, 0xeb, 0x5f, 0x0f + +}; + +static NSDictionary* VerifyMessage(CFDataRef message, SecPolicyRef policy, CFDataRef cert_data) +{ + NSDictionary* result = nil; + + SecTrustRef trustRef = NULL; + CFDataRef payload = NULL; + CFArrayRef anchors = NULL; + OSStatus status = noErr; + SecCertificateRef aCertRef = NULL; + SecTrustResultType trust_result = kSecTrustResultRecoverableTrustFailure; + + if (NULL == message || NULL == policy || NULL == cert_data) + { + goto out; + } + + status = SecCMSVerifyCopyDataAndAttributes(message, NULL, policy, &trustRef, &payload, NULL); + if (noErr != status || NULL == trustRef || NULL == payload) + { + goto out; + } + + aCertRef = SecCertificateCreateWithData(NULL, cert_data); + if (NULL == aCertRef) + { + goto out; + } + + anchors = CFArrayCreate(kCFAllocatorDefault, (const void **)&aCertRef, 1, &kCFTypeArrayCallBacks); + if (NULL == anchors) + { + goto out; + } + + status = SecTrustSetAnchorCertificates(trustRef, anchors); + if (noErr != status) + { + goto out; + } + + status = SecTrustEvaluate(trustRef, &trust_result); + + if (noErr != status) + { + goto out; + } + + if (trust_result == kSecTrustResultUnspecified) + { + // Life is good and we got back the expected result. + + NSData* property_list_data = CFBridgingRelease(payload); + + NSPropertyListFormat format; + NSError* error = nil; + result = [NSPropertyListSerialization propertyListWithData:property_list_data options:0 format:&format error:&error]; + if (nil != error) + { + result = nil; + } + } + +out: + CFReleaseSafe(aCertRef) + CFReleaseSafe(anchors); + return result; +} + +/* ========================================================================== + Private Methods for the OTAServiceApp class + ========================================================================== */ +@interface OTAServiceApp (PrivateMethods) +- (void)processAssets:(NSArray*)assets; +- (BOOL)checkAssetVersions:(NSString *)assetDir; +- (BOOL)validateAsset:(NSString *)assetDir; +- (BOOL)validateDirectory:(NSString *)assetDir withFiles:(NSArray *)file_names; +- (NSDictionary *)decodeManifest:(NSData *)manifest_file_data; +- (BOOL)checkFileHash:(NSString *)file_path hash:(NSData *)hash; +- (BOOL)installAssetFiles:(NSString *)assetDir; +- (NSString*)getCurrentAssetDirectory; + +@end + +@implementation OTAServiceApp + +@synthesize file_list = _file_list; +@synthesize manifest_file_name = _manifest_file_name; +@synthesize asset_version_file_name = _asset_version_file_name; +@synthesize current_asset_version = _current_asset_version; +@synthesize next_asset_version = _next_asset_version; +@synthesize fileManager = _fileManager; +@synthesize current_asset_directory = _current_asset_directory; +@synthesize assets_directory = _assets_directory; + +/* -------------------------------------------------------------------------- + OTAServiceApp init:withArguments: + + Initialize a new instance of the OTAServiceApp class + -------------------------------------------------------------------------- */ +- (id)init:(int)argc withArguments:(const char**)argv +{ + if ((self = [super init])) + { + _fileManager = [NSFileManager defaultManager]; + + _manifest_file_name = (NSString *)kManifestFileName; + _asset_version_file_name = (NSString *)kAssetVersionFileName; + _file_list = [NSArray arrayWithObjects:kBlockKeyFileName, kGrayListedKeysFileName, + kEVRootsFileName, kCertsIndexFileName, kCertsTableFileName, + kManifestFileName, kAssetVersionFileName, kAppleESCertificatesName, nil]; + + _current_asset_version = nil; + _next_asset_version = nil; + _assets_directory = nil; + _current_asset_directory = [self getCurrentAssetDirectory]; + + /* Default interval is one hour */ + _asset_query_retry_interval = 60.0 * 60; + _verbose = false; + + int ch; + while ((ch = getopt(argc, (char * const *)argv, "d:v")) != -1 ) + { + switch (ch) + { + case 'd': + { + char *endptr = NULL; + errno = 0; + CFTimeInterval interval = strtod(optarg, &endptr); + if ((interval == 0 && endptr == optarg) || errno == ERANGE) { + syslog(LOG_ERR, "invalid argument '%s', ignoring", optarg); + } else { + syslog(LOG_NOTICE, "Setting query retry interval to %f seconds", interval); + _asset_query_retry_interval = (CFTimeInterval)interval; + } + } + break; + case 'v': + syslog(LOG_NOTICE, "Enabling verbose logging"); + _verbose = true; + break; + default: + break; + } + } + + struct stat info; +#if NEW_LOCATION + if (stat([kBaseAssetDirectoryPath UTF8String], &info)) + { + OTAPKI_LOG("OTAServiceApp.init:withArguments: stat of %s failed\n", [kBaseAssetDirectoryPath UTF8String]); + + if (mkdir([kBaseAssetDirectoryPath UTF8String], kAssetDirectoryPermission)) + { + OTAPKI_LOG("OTAServiceApp.init:withArguments: mkdir of %s failed\n", [kBaseAssetDirectoryPath UTF8String]); + } + else + { + if (stat([kBaseAssetDirectoryPath UTF8String], &info)) + { + OTAPKI_LOG("OTAServiceApp.init:withArguments: second stat of %s failed\n", [kBaseAssetDirectoryPath UTF8String]); + } + } + } +#else + stat([kBaseAssetDirectoryPath UTF8String], &info); + + _uid = info.st_uid; + _gid = info.st_gid; +#endif + + } + + return self; +} + +#if !TARGET_IPHONE_SIMULATOR + +- (void)registerBackgroundTaskAgentJobWithDelay:(CFTimeInterval)delay +{ + /* + * ELEs are very important, so allow asset queries on any network type and + * construct the job so that it will fire as soon as possible, unless we are + * scheduling a retry after a failure. + */ + xpc_object_t job = xpc_dictionary_create(NULL, NULL, 0); + if (delay != 0) + { + xpc_dictionary_set_double(job, kBackgroundTaskAgentJobWindowStartTime, CFAbsoluteTimeGetCurrent() + delay); + } + xpc_dictionary_set_double(job, kBackgroundTaskAgentJobWindowEndTime, CFAbsoluteTimeGetCurrent() + BACKGROUND_TASK_AGENT_JOB_WINDOW_MAX_TIME_FROM_NOW_SEC); + xpc_dictionary_set_bool(job, kBackgroundTaskAgentNetworkRequired, true); + xpc_dictionary_set_bool(job, kBackgroundTaskAgentCellularAllowed, true); + xpc_dictionary_set_bool(job, kBackgroundTaskAgentAllowedDuringRoaming, true); + xpc_dictionary_set_bool(job, kBackgroundTaskAgentPowerOptLevel, kBackgroundTaskAgentPowerDontCare); + + if (_verbose) + { + char *desc = xpc_copy_description(job); + syslog(LOG_NOTICE, "Adding BTA job %s", desc); + free(desc); + } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + BackgroundTaskAgentAddJob(kOTAPKIAssetToolActivity, job); +#pragma GCC diagnostic pop +} + +#endif + +/* -------------------------------------------------------------------------- + OTAServiceApp checkInWithActivity + + Check in with the XPC activity configured in OTAPKIAssetTool's launchd + plist. This activity will launch OTAPKIAssetTool every three days (with + some leeway decided by the system). At that time, we schedule a + BackgroundTaskAgent job to be notified immediately when the network is + available so we can perform an asset query. + -------------------------------------------------------------------------- */ +- (void)checkInWithActivity +{ +#if !TARGET_IPHONE_SIMULATOR +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + BackgroundTaskAgentInit("com.apple.OTAPKIAssetTool", dispatch_get_main_queue(), ^(const char *job_name, xpc_object_t job) + { + /* + * We're doing real work at this point, so open a transaction so + * that the system (hopefully) won't kill us while we're busy + */ + xpc_transaction_begin(); + + if (_verbose) + { + syslog(LOG_NOTICE, "BackgroundTaskAgent job %s fired", job_name); + } + + int64_t job_status = xpc_dictionary_get_int64(job, kBackgroundTaskAgentJobStatus); + if (job_status == kBackgroundTaskAgentJobRequestError) + { + syslog(LOG_ERR, "Failed to create BTA job -- malformed job?"); + } + else if (job_status == kBackgroundTaskAgentJobSatisfied) + { + if (_verbose) + { + syslog(LOG_NOTICE, "BTA job %s is satisfied -- performing asset query", job_name); + } + bool shouldReschedule = false; + if ([self run:&shouldReschedule] || !shouldReschedule) + { + if (_verbose) + { + syslog(LOG_NOTICE, "Unscheduling BTA job"); + } + BackgroundTaskAgentRemoveJob(kOTAPKIAssetToolActivity); + } + else + { + syslog(LOG_NOTICE, "Asset query failed due to network error. Re-scheduling BTA job for another attempt in %f seconds.", _asset_query_retry_interval); + [self registerBackgroundTaskAgentJobWithDelay:_asset_query_retry_interval]; + } + } + else if (job_status == kBackgroundTaskAgentJobUnsatisfied) + { + /* + * We will receive this if the job expires before we get to do our + * work. We still want to check for new assets as soon as possible, + * so reschedule the job. + */ + if (xpc_dictionary_get_bool(job, kBackgroundTaskAgentJobExpired)) + { + [self registerBackgroundTaskAgentJobWithDelay:0]; + } + } + + xpc_transaction_end(); + }); +#pragma GCC diagnostic pop +#endif + + xpc_activity_register(kOTAPKIAssetToolActivity, XPC_ACTIVITY_CHECK_IN, ^(xpc_activity_t activity) + { + xpc_activity_state_t state = xpc_activity_get_state(activity); + + if (_verbose) + { + xpc_object_t criteria = xpc_activity_copy_criteria(activity); + + if (criteria != NULL) + { + char *desc = xpc_copy_description(criteria); + syslog(LOG_NOTICE, "Criteria for XPC activity %s: %s", kOTAPKIAssetToolActivity, desc); + free(desc); + } + else + { + syslog(LOG_NOTICE, "No critera for XPC activity %s", kOTAPKIAssetToolActivity); + } + } + + if (state == XPC_ACTIVITY_STATE_CHECK_IN) + { + /* + * The activity is already configured in the launchd plist, so there + * is nothing to do here + */ + if (_verbose) + { + syslog(LOG_NOTICE, "Activity %s in check in state", kOTAPKIAssetToolActivity); + } + } + else if (state == XPC_ACTIVITY_STATE_RUN) + { +#if !TARGET_IPHONE_SIMULATOR +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + xpc_object_t job = BackgroundTaskAgentCopyJob(kOTAPKIAssetToolActivity); +#pragma GCC diagnostic pop + if (job == NULL) + { + syslog(LOG_NOTICE, "Activity %s in run state. Scheduling BTA job for earliest network availability.", kOTAPKIAssetToolActivity); + [self registerBackgroundTaskAgentJobWithDelay:0]; + } + else if (_verbose) + { + syslog(LOG_NOTICE, "Already have a BTA job registered. Ignoring activity."); + } +#else + /* + * BackgroundTaskAgent doesn't exist on the iOS simulator, so we + * just directly try to find and download new assets. + */ + xpc_transaction_begin(); + bool shouldReschedule = false; + if (![self run:&shouldReschedule]) { + syslog(LOG_NOTICE, "Asset query failed%s.", shouldReschedule ? " due to network issue" : ""); + } + xpc_transaction_end(); +#endif + } + }); +} + +/* -------------------------------------------------------------------------- + OTAServiceApp run + + Run this program and leave. This program will currently run every 3 days, + with some leeway based on network availability. That will provide the + longest time from publisihing a change in the PKI trust setting asset and + having that asset be consumed by a device. + + The program simnply ask the mobile asset daemon if there are any assets + to be processed with the PKITrustDataAssetType. If not this program + will just complete and will be re-run in 3 days. If there is an asset to + process then the asset will be process and then the program will complete. + + Returns false if the operation failed. On return, shouldReschedule is set + to true if the operation failed due to a network error and the caller + should reschedule this operation at a more opportune time. + -------------------------------------------------------------------------- */ +- (bool)run:(bool *)shouldReschedule +{ + @autoreleasepool + { + if (shouldReschedule != NULL) { + *shouldReschedule = false; + } + + syslog(LOG_NOTICE, "OTAPKIAssetTool running"); + if (![[MCProfileConnection sharedConnection] isOTAPKIUpdatesAllowed]) + { + syslog(LOG_NOTICE, "OTAPKIAssetTool: OTAPKI updates are not allowed."); + return false; + } + + ASAssetQuery *assetQuery = [[ASAssetQuery alloc] initWithAssetType:(NSString *)kPKITrustDataAssetType]; + if (assetQuery == nil) + { + syslog(LOG_NOTICE, "OTAPKIAssetTool: Could not create the asset query."); + return false; + } + + // Get the asset synchronously + NSError *error = nil; + NSArray *foundAssets = [assetQuery runQueryAndReturnError:&error]; + if (nil != foundAssets) + { + [self processAssets:foundAssets]; + } + else + { + syslog(LOG_NOTICE, "OTAPKIAssetTool: No assets returned from query: %s", [[error description] UTF8String]); + + NSArray *networkErrorCodes = @[ @(ASErrorNetwork), @(ASErrorNetworkNoConnection), @(ASErrorNetworkTimedOut), @(ASErrorNetworkUnexpectedResponse) ]; + if ([[error domain] isEqualToString:ASErrorDomain] && [networkErrorCodes containsObject:@([error code])]) + { + syslog(LOG_NOTICE, "OTAPKIAssetTool: Query failed due to network error."); + if (shouldReschedule != NULL) { + *shouldReschedule = true; + } + } + return false; + } + + return true; + } +} + +/* -------------------------------------------------------------------------- + OTAServiceApp processAssets: + + If when run is called asset(s) are found they will be processed here. + -------------------------------------------------------------------------- */ +- (void)processAssets:(NSArray*)assets +{ + if (nil == assets) + { + return; + } + + NSError* error = nil; + ASAsset* asset = nil; + int asset_version = 0; + + for (asset in assets) + { + NSDictionary* asset_attributes = asset.attributes; + + NSNumber* contentVersion = [asset_attributes objectForKey:@"ContentVersion"]; + OTAPKI_LOG("In processAssets: about to check the ContentVersion\n"); + if (nil != contentVersion) + { + asset_version = [contentVersion intValue]; + int current_asset_version_number = (nil != _current_asset_version) ? [_current_asset_version intValue] : 0; + + if (asset_version <= current_asset_version_number) + { + syslog(LOG_NOTICE, "OTAPKIAssetTool: content version %d is too small. Current asset version id %d", + asset_version, current_asset_version_number); + + OTAPKI_LOG("In processAssets: content version is too small: current asset version is %d\nContent version is %d\n", + current_asset_version_number, asset_version); + asset = nil; + continue; + } + } + + if (nil == asset) + { + syslog(LOG_NOTICE, "OTAPKIAssetTool: no suitable asset found"); + return; + } + + + // Check to see if the asset needs to be downloaded + if (asset.state == ASAssetStateNotPresent) + { + __block dispatch_semaphore_t sem = dispatch_semaphore_create(0); + + [asset setProgressHandler:^(NSDictionary *state, NSError *anError) + { + if (error != nil) + { + // An error occured. Signal the semaphore to bail + dispatch_semaphore_signal(sem); + } + else if ([[state objectForKey:@"Operation"] isEqualToString:(NSString *) @"OperationCompleted"]) + { + // The download is complete. Signal the semaphore + dispatch_semaphore_signal(sem); + } + }]; + + NSNumber* yesValue = [NSNumber numberWithBool:YES]; + const id keys[] = {ASDownloadOptionAllow3G, ASDownloadOptionAllow4G, ASDownloadOptionPriority, ASDownloadOptionAllowBatteryPower}; + const id values[] = {yesValue, yesValue, ASDownloadPriorityHigh, yesValue}; + + NSDictionary* options = [NSDictionary dictionaryWithObjects:values forKeys:keys count:(sizeof (keys) / sizeof(keys[0]))]; + + [asset beginDownloadWithOptions:options]; + dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); + } + + // Check to see if the asset is now available for processing + if ([asset state] == ASAssetStateInstalled) + { + // Get the asset data directory + NSString* assetDir = [[[asset localURL] URLByAppendingPathComponent:@"PKITrustData"] path]; + if (nil != assetDir) + { + // validate the asset. + OTAPKI_LOG("In processAssets: about to validateAsset\n"); + if ([self validateAsset:assetDir]) + { + OTAPKI_LOG("In processAssets: asset validated installing\n"); + // The asset is valid so install the files + [self installAssetFiles:assetDir]; + + // Signal securityd to idle-exit at it's next opportunity + OTAPKI_LOG("In processAssets: notifying securityd\n"); + int didUpdate = 0; + (void)SecTrustOTAPKIGetUpdatedAsset(&didUpdate); + syslog(LOG_NOTICE, "OTAPKIAssetTool: installed new asset %d", asset_version); + } + else + { + syslog(LOG_NOTICE, "OTAPKIAssetTool: Asset %d did not validate", asset_version); + } + + // regaurdless if the asset is valid. Now that it is + // installed, it needs to be purged to ensure that + // we can retrieve a new updated asset. + [asset purgeAndReturnError:&error]; + } + else + { + syslog(LOG_NOTICE, "OTAPKIAssetTool: Asset directory %s not found", [assetDir UTF8String]); + } + } + } +} + +/* -------------------------------------------------------------------------- + OTAServiceApp checkAssetVersions: + + If when run is called asset(s) are found they will be processed here. + -------------------------------------------------------------------------- */ +- (BOOL)checkAssetVersions:(NSString *)assetDir +{ + BOOL result = NO; + + OTAPKI_LOG("Entering checkAssetVersions\n"); + + if (nil == assetDir || nil == self.current_asset_version) + { + OTAPKI_LOG("checkAssetVersions: parameter error\n"); + return result; + } + + // first get the new version number from the downloaded asset + NSString* next_asset_version_path = [assetDir stringByAppendingPathComponent:self.asset_version_file_name]; + if (![self.fileManager fileExistsAtPath:next_asset_version_path]) + { + // The asset is missing the AssertVersion.plist + // This is an invalid asset + OTAPKI_LOG("checkAssetVersions: could not file asseet version file %s\n", [self.asset_version_file_name UTF8String]); + return result; + } + + NSError* error = nil; + NSInputStream* input_stream = [NSInputStream inputStreamWithFileAtPath:next_asset_version_path]; + [input_stream open]; + NSDictionary* asset_dict = [NSPropertyListSerialization propertyListWithStream:input_stream options:0 format:nil error:&error]; + [input_stream close]; + + if (nil != error) + { + OTAPKI_LOG("checkAssetVersions: error reading asset version file: %s\n", [[error localizedDescription] UTF8String]); + return result; + } + + _next_asset_version = [asset_dict objectForKey:kVersionNumberKey]; + if (nil == _next_asset_version) + { + OTAPKI_LOG("asset_dict did not have a entry with a key of kVersionNumberKey\n"); + return result; + } + + // Check the current asset version against the new asset version. The new asset version MUST be larger than the + // current asset version + NSInteger current_asset_version_value = [self.current_asset_version integerValue]; + NSInteger next_asset_version_value = [self.next_asset_version integerValue]; + + if (next_asset_version_value <= current_asset_version_value) + { + OTAPKI_LOG("heckAssetVersions: assert version too small. current_asset_version_value = %d next_asset_version_value = %d\n", + current_asset_version_value, next_asset_version_value); + return result; + } + + return YES; +} + + +/* -------------------------------------------------------------------------- + OTAServiceApp validateAsset: + + Decode the manifest and verify the file hashes + -------------------------------------------------------------------------- */ +- (BOOL)validateAsset:(NSString *)assetDir +{ + BOOL result = NO; + + OTAPKI_LOG("Enterning validateAsset\n"); + + if (![self validateDirectory:assetDir withFiles:self.file_list]) + { + OTAPKI_LOG("validateAsset param\n"); + return result; + } + + NSString* manifest_file_path = [assetDir stringByAppendingPathComponent:self.manifest_file_name]; + NSError* error = nil; + NSData* manifest_file_data = [NSData dataWithContentsOfFile:manifest_file_path options:0 error:&error]; + if (nil != error) + { + OTAPKI_LOG("validateAsset: could not read manifest file. error = %s\n", [[error localizedDescription] UTF8String]); + return result; + } + + NSDictionary* manifest_data = [self decodeManifest:manifest_file_data]; + if (nil == manifest_data) + { + OTAPKI_LOG("validateAsset: decodeManifest failed!\n"); + return result; + } + + NSString* full_file_path = nil; + NSData* hash = nil; + for (NSString* file_name in self.file_list) + { + if ([file_name isEqualToString:self.manifest_file_name]) + { + continue; + } + + hash = [manifest_data objectForKey:file_name]; + if (nil == hash) + { + OTAPKI_LOG("validateAsset: could not get hash for file %s\n", [file_name UTF8String]); + return result; + } + + full_file_path = [assetDir stringByAppendingPathComponent:file_name]; + if (![self checkFileHash:full_file_path hash:hash]) + { + OTAPKI_LOG("validateAsset: hash for file %s does not match\n", [file_name UTF8String]); + return result; + } + } + + result = [self checkAssetVersions:assetDir]; + return result; +} + +/* -------------------------------------------------------------------------- + OTAServiceApp validateDirectory:withFiles: + + Ensure that a given directory has the files listed in the files_names + parameter + -------------------------------------------------------------------------- */ +- (BOOL)validateDirectory:(NSString *)assetDir withFiles:(NSArray *)file_names +{ + BOOL result = NO; + OTAPKI_LOG("Enterning validateDirectory\n"); + + if (nil == assetDir || nil == file_names) + { + OTAPKI_LOG("validateDirectory param error\n"); + return result; + } + NSError* error = nil; + NSArray* dir_items = [self.fileManager contentsOfDirectoryAtPath:assetDir error:&error]; + if (nil != error) + { + OTAPKI_LOG("validateDirectory: Error calling contentsOfDirectoryAtPath: error = %s\n", [[error localizedDescription] UTF8String]); + return result; + } + + for (NSString* file_name in file_names) + { + if (![dir_items containsObject:file_name]) + { + OTAPKI_LOG("validateDirectory: missing file %s\n", [file_name UTF8String]); + return result; + } + } + + return YES; +} + +/* -------------------------------------------------------------------------- + OTAServiceApp decodeManifest: + + Ensure that the asset manifest blob has it CMS signature verified + -------------------------------------------------------------------------- */ +- (NSDictionary *)decodeManifest:(NSData *)manifest_file_data +{ + NSDictionary* result = nil; + CFDataRef cert_data = NULL; + CFDataRef message = NULL; + SecPolicyRef policy = NULL; + CFBooleanRef mgResult = NULL; + + OTAPKI_LOG("Enterning decodeManifest\n"); + + if (nil == manifest_file_data) + { + OTAPKI_LOG("decodeManifest: parameter error\n"); + goto out; + } + + message = CFBridgingRetain(manifest_file_data); + + policy = SecPolicyCreateOTAPKISigner(); + if (NULL == policy) + { + OTAPKI_LOG("decodeManifest: could not get the SecPolicyCreateOTAPKISigner policyRef\n"); + goto out; + } + + cert_data = CFDataCreate(kCFAllocatorDefault, kApplePKISettingsRootCACert, sizeof(kApplePKISettingsRootCACert)); + if (NULL == cert_data) + { + OTAPKI_LOG("decodeManifest: could not kApplePKISettingsRootCACert data\n"); + goto out; + } + + result = VerifyMessage(message, policy, cert_data); + + if (NULL != result) + { + OTAPKI_LOG("decodeManifest: SecPolicyCreateOTAPKISigner success!\n"); + goto out; + } + + OTAPKI_LOG("decodeManifest: SecPolicyCreateOTAPKISigner failed! Checking to see if this is an internal build\n"); + + // The first attempt did not work so check to see if this is running on an internal build. + if (!MGIsQuestionValid(kMGQAppleInternalInstallCapability)) + { + OTAPKI_LOG("decodeManifest: kMGQAppleInternalInstallCapability had an error\n"); + goto out; + } + + mgResult = MGCopyAnswer(kMGQAppleInternalInstallCapability, NULL); + + if (NULL == mgResult || !CFEqual(mgResult, kCFBooleanTrue)) + { + OTAPKI_LOG("decodeManifest: Not an internal build"); + goto out; + } + + OTAPKI_LOG("decodeManifest: This is an internal build\n"); + + CFReleaseNull(policy); + CFReleaseNull(cert_data); + + policy = SecPolicyCreateTestOTAPKISigner(); + if (NULL == policy) + { + OTAPKI_LOG("decodeManifest: could not SecPolicyCreateTestOTAPKISigner policyRef\n"); + goto out; + } + + cert_data = CFDataCreate(kCFAllocatorDefault, kAppleTestPKISettingsRootCACert, sizeof(kAppleTestPKISettingsRootCACert)); + if (NULL == cert_data) + { + OTAPKI_LOG("decodeManifest: could not kAppleTestPKISettingsRootCACert data\n"); + goto out; + } + + result = VerifyMessage(message, policy, cert_data); + +out: + + CFReleaseSafe(mgResult); + CFReleaseSafe(message); + CFReleaseSafe(policy); + CFReleaseSafe(cert_data); + return result; +} + +/* -------------------------------------------------------------------------- + OTAServiceApp checkFileHash:hash: + + Ensure that the given asset file's hash is the same as in the manifest + -------------------------------------------------------------------------- */ +- (BOOL)checkFileHash:(NSString *)file_path hash:(NSData *)hash +{ + BOOL result = NO; + if (nil == file_path || nil == hash) + { + return result; + } + + NSError* error = nil; + NSData* file_data = [NSData dataWithContentsOfFile:file_path options:0 error:&error]; + if (nil != error) + { + return result; + } + + UInt8 buffer[CC_SHA256_DIGEST_LENGTH]; + memset(buffer, 0, CC_SHA256_DIGEST_LENGTH); + CC_SHA256([file_data bytes], (CC_LONG)[file_data length], buffer); + NSData* file_hash_data = [NSData dataWithBytesNoCopy:buffer length:CC_SHA256_DIGEST_LENGTH freeWhenDone:NO]; + + result = [hash isEqualToData:file_hash_data]; + + return result; +} + +/* -------------------------------------------------------------------------- + OTAServiceApp installAssetFiles: + + Copy over the files into the /var/Keychains/Assets directory. + -------------------------------------------------------------------------- */ +- (BOOL)installAssetFiles:(NSString *)assetDir +{ + BOOL result = NO; + + OTAPKI_LOG("Entering installAssetFiles\n"); + + if (nil == assetDir) + { + OTAPKI_LOG("installAssetFiles: parameter error\n"); + return result; + } + + if (nil == self.assets_directory) + { + OTAPKI_LOG("installAssetFiles: no assets directory\n"); + return result; + } + + // Create a temp directory to hold the new asset files. + NSString* tempDir = [self.assets_directory stringByAppendingPathComponent:@"TempAssetDir"]; + NSError* error = nil; + +#if NEW_LOCATION + id values[] = {[NSNumber numberWithUnsignedLong: kAssetDirectoryPermission]}; + id keys[] = {NSFilePosixPermissions}; + + NSDictionary* attributes = [NSDictionary dictionaryWithObjects:values forKeys:keys count:1]; +#else + struct passwd *user_info = getpwnam([kAssetDirectoryUser UTF8String]); + struct group *group_info = getgrnam([kAssetDirectoryGroup UTF8String]); + NSNumber* uid_num = [NSNumber numberWithUnsignedInt: user_info->pw_uid]; + NSNumber* gid_num = [NSNumber numberWithUnsignedInt: group_info->gr_gid]; + + id values[] = {uid_num, gid_num, [NSNumber numberWithUnsignedLong: kAssetDirectoryPermission]}; + id keys[] = {NSFileOwnerAccountID, NSFileGroupOwnerAccountID, NSFilePosixPermissions}; + + NSDictionary* attributes = [NSDictionary dictionaryWithObjects:values forKeys:keys count:3]; +#endif + + + if (![self.fileManager createDirectoryAtPath:tempDir withIntermediateDirectories:YES + attributes:attributes error:&error]) + { + OTAPKI_LOG("installAssetFiles: could not create directory %s\n", [tempDir UTF8String]); + return result; + } + +#ifndef NEW_LOCATION + // Copy all of the asset files to the newly created directory + for (NSString* file_name in self.file_list) + { + NSString* download_assert_path = [assetDir stringByAppendingPathComponent:file_name]; + NSString* asset_path = [tempDir stringByAppendingPathComponent:file_name]; + if ([self.fileManager copyItemAtPath:download_assert_path toPath:asset_path error:&error]) + { + chown([asset_path UTF8String], self.uid, self.gid); + } + else + { + [self.fileManager removeItemAtPath:tempDir error:nil]; + return result; + } + } +#endif // !NEW_LOCATION + + + // Now that all of the files have been copied to the temp directory make a single call + // to rename (move) the temp directory to be the correct version directory. This rename + // allow for reducing a race conditions between this asset code and securityd. + NSInteger new_version_value = [self.next_asset_version integerValue]; + NSString* new_version_dir_name = [NSString stringWithFormat:@"%@%ld", kVersionDirectoryNamePrefix, (long)new_version_value]; + NSString* new_version_dir_path = [self.assets_directory stringByAppendingPathComponent:new_version_dir_name]; + if (![self.fileManager moveItemAtPath:tempDir toPath:new_version_dir_path error:&error]) + { + OTAPKI_LOG("installAssetFiles: could not move path %s\n", [tempDir UTF8String]); + [self.fileManager removeItemAtPath:tempDir error:nil]; + return result; + } + + result = YES; + return result; +} + +/* -------------------------------------------------------------------------- + OTAServiceApp getCurrentAssetDirectory: + + Looks through the /var/Keychains/Assets directory to find latest asset + version directory. If no assets have been downloaded then nil is returned + and the current asset version is set to 0 + -------------------------------------------------------------------------- */ +- (NSString*)getCurrentAssetDirectory +{ + NSString* result = nil; + BOOL isDir = NO; + + OTAPKI_LOG("In getCurrentAssetDirectory\n"); + OTAPKI_LOG("getCurrentAssetDirectory: checking to see if %s exists\n", [kBaseAssetDirectoryPath UTF8String]); + + // Check to see if the base directory is there + if (![self.fileManager fileExistsAtPath:(NSString *)kBaseAssetDirectoryPath isDirectory:&isDir] || !isDir) + { + OTAPKI_LOG("getCurrentAssetDirectory: %s does not exists\n", [kBaseAssetDirectoryPath UTF8String]); + // This might be fatal + return result; + } + + NSError* error = nil; + NSInteger version_number = 0; + NSInteger current_version_number = 0; + int aVerNum = 0; + OSStatus err = noErr; + + _assets_directory = [kBaseAssetDirectoryPath stringByAppendingPathComponent:(NSString *)kAssetDirectoryName]; + + OTAPKI_LOG("getCurrentAssetDirectory: %s does exists\n", [self.assets_directory UTF8String]); + + if ([self.fileManager fileExistsAtPath:self.assets_directory isDirectory:&isDir] && isDir) + { + OTAPKI_LOG("getCurrentAssetDirectory: %s does exists\n", [self.assets_directory UTF8String]); + NSDirectoryEnumerator* dirEnum = [self.fileManager enumeratorAtPath:self.assets_directory]; + [dirEnum skipDescendents]; + + for (NSString* file in dirEnum) + { + if ([file hasPrefix:(NSString *)kVersionDirectoryNamePrefix]) + { + NSString* version_str = [file substringFromIndex:[kVersionDirectoryNamePrefix length]]; + NSInteger aVersion_number = [version_str integerValue]; + if (aVersion_number > version_number) + { + version_number = aVersion_number; + } + } + } + } + else + { +#if NEW_LOCATION + id values[] = {[NSNumber numberWithUnsignedLong: kAssetDirectoryPermission]}; + id keys[] = {NSFilePosixPermissions}; + + NSDictionary* attributes = [NSDictionary dictionaryWithObjects:values forKeys:keys count:1]; +#else + + struct passwd *user_info = getpwnam([kAssetDirectoryUser UTF8String]); + struct group *group_info = getgrnam([kAssetDirectoryGroup UTF8String]); + NSNumber* uid_num = [NSNumber numberWithUnsignedInt: user_info->pw_uid]; + NSNumber* gid_num = [NSNumber numberWithUnsignedInt: group_info->gr_gid]; + + id values[] = {uid_num, gid_num, [NSNumber numberWithUnsignedLong: kAssetDirectoryPermission]}; + id keys[] = {NSFileOwnerAccountID, NSFileGroupOwnerAccountID, NSFilePosixPermissions}; + NSDictionary* attributes = [NSDictionary dictionaryWithObjects:values forKeys:keys count:3]; +#endif + OTAPKI_LOG("getCurrentAssetDirectory: %s does NOT exists\n", [self.assets_directory UTF8String]); + OTAPKI_LOG("getCurrentAssetDirectory: creating %s\n", [self.assets_directory UTF8String]); + + if (![self.fileManager createDirectoryAtPath:self.assets_directory withIntermediateDirectories:YES + attributes:attributes error:&error]) + { + OTAPKI_LOG("getCurrentAssetDirectory: failed to create %s\n", [self.assets_directory UTF8String]); + return result; + } + + } + + err = SecTrustGetOTAPKIAssetVersionNumber(&aVerNum); + if (errSecSuccess == err && aVerNum > 0) + { + current_version_number = aVerNum; + } + + if (version_number < current_version_number) + { + OTAPKI_LOG("The largest OTA version number is smaller than the current version number. This means the system has a newer asset\n"); + version_number = current_version_number; + } + else + { + OTAPKI_LOG("The largest OTA version number is equal to the current version number. The OTA asset is newer than the system asset\n"); + NSString* version_dir_name = [NSString stringWithFormat:@"%@%ld", kVersionDirectoryNamePrefix, (long)version_number]; + result = [self.assets_directory stringByAppendingPathComponent:version_dir_name]; + } + + OTAPKI_LOG("getCurrentAssetDirectory: setting version number to %d\n", version_number); + _current_asset_version = [NSNumber numberWithInteger:version_number]; + return result; +} + +@end diff --git a/OTAPKIAssetTool/OTAServicemain.m b/OTAPKIAssetTool/OTAServicemain.m new file mode 100644 index 00000000..432c01e6 --- /dev/null +++ b/OTAPKIAssetTool/OTAServicemain.m @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* ========================================================================== + main for the OTAService for iOS securityd + ========================================================================== */ + +#import +#import +#import "OTAServiceApp.h" + +int main(int argc, const char * argv[]) +{ + // OTAServiceApp + @autoreleasepool + { + OTAServiceApp* ota_service_application = [[OTAServiceApp alloc] init:argc withArguments:argv]; + [ota_service_application checkInWithActivity]; + + /* Spin a runloop so events can be delivered */ + CFRunLoopRun(); + } + return 0; +} + + + diff --git a/OTAPKIAssetTool/com.apple.OTAPKIAssetTool.plist b/OTAPKIAssetTool/com.apple.OTAPKIAssetTool.plist new file mode 100644 index 00000000..cf161728 --- /dev/null +++ b/OTAPKIAssetTool/com.apple.OTAPKIAssetTool.plist @@ -0,0 +1,37 @@ + + + + + EnablePressuredExit + + EnableTransactions + + POSIXSpawnType + Adaptive + Label + com.apple.OTAPKIAssetTool + ProgramArguments + + /usr/libexec/OTAPKIAssetTool + + Umask + 18 + UserName + _securityd + LaunchEvents + + com.apple.xpc.activity + + com.apple.OTAPKIAssetTool.asset-check + + Priority + Utility + Interval + 259200 + GracePeriod + 3600 + + + + + diff --git a/README b/README index cfdcee72..6338ba12 100644 --- a/README +++ b/README @@ -1,29 +1,38 @@ -This code contains a Darwin version of CDSA along with many other security libraries. +Update June 17, 2014 -Information about CDSA may be obtained from the OpenGroup web site at: +Here lie the iOS and OS X versions of Security, including securityd and SecurityTool for OS X. - http://www.opengroup.org/pubs/catalog/c914.htm +----------- -Further information regarding the security of the MacOSX product is available at: - http://www.apple.com/support/security/ + Projects in Security + Last update Dec 1 2005 -Developers wishing to know more about developing their products in a manner consistent with MacOS security should view: - http://developer.apple.com/macos/security.html +Standalone crypto libs +---------------------- +libCert/ + Library to parse and verify X509 certificates. Uses libgRSA, + libDER, libMD5, and libSHA1. -To build this project in a Darwin environment (as opposed to building in-house -at Apple), use the Darwin buildstyle. If you're building with Xcode, select -"Darwin" from the "Active Build Style" popup. If you're building from the command -line, specify the build style like so: +libDER/ + DER decoding library, ROM_capable, no malloc. -% xcodebuild -buildstyle Darwin install +libGiants/ + General purpose ROM-capable giantIntegers package. No malloc. + Performs unsigned arithmetic ONLY as of Nov. 28 2005. + +libgRSA/ + Full ROM-capable RSA package based on libGiants. + Provided to Mike Smith and Chris Aycock 8/23/05. + Converted to unsigned libGiants circa 11/30/05. -This build style is necessitated by the fact that the CSP built at (and -shipped by) Apple includes some algorithms which are proprietary to Apple; -the source code for these algorithms is not open source. Selecting the -Darwin build style allows the Security project (and also the CSP, in -the libsecurity_apple_csp project, which also must be built with the -Darwin build style) to be built from the Darwin open source tree without -requiring the source for these algorithms. +libScripts/ + Scripts to build and test all of these libraries. + +==== + +To regenerate strings file run: +genstrings -o resources/English.lproj -s SecString sec/Security/SecFrameworkStrings.h +in the top level dir. diff --git a/README.genanchors b/README.genanchors new file mode 100644 index 00000000..191278ee --- /dev/null +++ b/README.genanchors @@ -0,0 +1,14 @@ +# Build the genanchors target against the Base SDK. + +# Run the following commands: + +rm -rf resources/roots +svn export svn+ssh://src.apple.com/svn/security/tla/trunk/security_certificates/roots resources/roots +svn cat svn+ssh://src.apple.com/svn/security/tla/trunk/security_certificates/buildEVRoots | awk ' +BEGIN {s = 0} +/# ------------------------------------------------------------------------------/ { s = 1 } +/EOF/ {s = 0} +{ if(s == 1) { print }}' > resources/evroot.config +~/build/Debug/genanchors -a resources/roots -e resources/evroot.config -a resources/roots > evroots.h + +#Then commit the new evroots.h and evroot.config diff --git a/README.keychain b/README.keychain new file mode 100644 index 00000000..d153a7fb --- /dev/null +++ b/README.keychain @@ -0,0 +1,32 @@ +Starting in 4.0 the keychain will be using content protection + +We will define 4 new classes for the keychain: + +Ak = non_exportable, uid_protection|pin_protection +Ck = wrap_on_lock|unwrap_on_lock|non_exportable, uid_protection|pin_protection +Dk = non_exportable, uid_protection +Ek = wrap_on_lock|unwrap_on_lock|non_exportable, uid_protection|pin_protection + +A new attribute will be added to all keychain items allowing a caller +to specify the content protection level. +Caller will have a choice or class Ak, Ck, Dk or Ek protection for the +items data. + +Consider whether or not to allow SecItemUpdate to change the protection class. + +Backup will no longer directly backup the keychain file, instead a new +SecKeychainMigrate() SPI will be added which takes a keybag and a password and +returns a keychain blob in which class A and C items are protected by the +provided keybags A and C keys, and the class E key protected items will not +migrate. + +Restore will pass the keychain file from an old backup or keychain blob +returned by the new SPI and the backup keybag and password to securityd so +items can be migrated back into the system keychain db. Class E items in the +backup set will only get restored if they are decryptable (restore is to same +device) otherwise they are discarded during the restore. + + +Implementors notes: +Migrate will take a db file needing to be upgraded or a keychain blob +needing to be migrated into the system security domain. diff --git a/SecureObjectSync-Info.plist b/SecureObjectSync-Info.plist new file mode 100644 index 00000000..f98af0c4 --- /dev/null +++ b/SecureObjectSync-Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.apple.${EXECUTABLE_NAME} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${EXECUTABLE_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + AAPL + CFBundleVersion + 1 + + diff --git a/SecureObjectSync.exp b/SecureObjectSync.exp new file mode 100644 index 00000000..796cb21e --- /dev/null +++ b/SecureObjectSync.exp @@ -0,0 +1 @@ +_SecSyncCCDeriveUserIDFromEntropy diff --git a/Security-Info.plist b/Security-Info.plist new file mode 100644 index 00000000..4bc200ce --- /dev/null +++ b/Security-Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.apple.${EXECUTABLE_NAME} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${EXECUTABLE_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 10.0 + CFBundleSignature + AAPL + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + + diff --git a/Security.exp-in b/Security.exp-in new file mode 100644 index 00000000..7b024929 --- /dev/null +++ b/Security.exp-in @@ -0,0 +1,173 @@ +#include + +#include "Security/SecExports.exp-in" +#include "Security/SecAccessControlExports.exp-in" +#include "SecureObjectSync/SOSExports.exp-in" + +_CSSMOID_MD5WithRSA +_CSSMOID_SHA1 +_CSSMOID_SHA1WithRSA +_CSSMOID_SHA256WithRSA +_CSSMOID_SHA384WithRSA +_CSSMOID_ECDSA_WithSHA1 +_CSSMOID_PKCS5_HMAC_SHA1 +_DEROidCompare +_NtlmCreateClientRequest +_NtlmCreateClientResponse +_NtlmGeneratePasswordHashes +_NtlmGeneratorCreate +_NtlmGeneratorRelease +_NtlmGetNegotiatedVersion +_OID_PKIX_OCSP_BASIC +_SSLAddDistinguishedName +_SSLClose +_SSLContextGetTypeID +_SSLCopyDistinguishedNames +_SSLCopyPeerTrust +_SSLCreateContext +_SSLCreateContextWithRecordFuncs +_SSLGetAllowAnonymousCiphers +_SSLGetBufferedReadSize +_SSLGetCertificate +_SSLGetCipherSizes +_SSLGetClientCertificateState +_SSLGetClientSideAuthenticate +_SSLGetConnection +_SSLGetDatagramWriteSize +_SSLGetEnabledCiphers +_SSLGetEncryptionCertificate +_SSLGetMaxDatagramRecordSize +_SSLGetNegotiatedCipher +_SSLGetNegotiatedCurve +_SSLGetNegotiatedProtocolVersion +_SSLGetNumberEnabledCiphers +_SSLGetNumberOfSignatureAlgorithms +_SSLGetNumberSupportedCiphers +_SSLGetPeerDomainName +_SSLGetPeerDomainNameLength +_SSLGetPeerID +_SSLGetPeerSecTrust +_SSLGetProtocolVersionMax +_SSLGetProtocolVersionMin +_SSLGetPSKIdentity +_SSLGetResumableSessionInfo +_SSLGetSessionState +_SSLGetSignatureAlgorithms +_SSLGetSupportedCiphers +_SSLHandshake +_SSLInternalClientRandom +_SSLInternalMasterSecret +_SSLInternalServerRandom +_SSLInternalSetMasterSecretFunction +_SSLInternalSetSessionTicket +_SSLInternal_PRF +_SSLRead +_SSLSetNPNData +_SSLSetNPNFunc +_SSLGetNPNData +_SSLSetAllowAnonymousCiphers +_SSLSetCertificate +_SSLSetClientSideAuthenticate +_SSLSetConnection +_SSLSetDatagramHelloCookie +_SSLSetECDSACurves +_SSLSetEnabledCiphers +_SSLSetEncryptionCertificate +_SSLSetIOFuncs +_SSLSetMaxDatagramRecordSize +_SSLSetProtocolVersionMax +_SSLSetProtocolVersionMin +_SSLSetPSKIdentity +_SSLSetPSKSharedSecret +_SSLSetRecordContext +_SSLSetSessionOption +_SSLGetSessionOption +_SSLSetPeerDomainName +_SSLSetPeerID +_SSLSetSessionCacheTimeout +_SSLWrite + +/* Those are deprecated */ +__SSLCopyPeerCertificates +__SSLDisposeContext +__SSLGetAllowsAnyRoot +__SSLGetAllowsExpiredCerts +__SSLGetAllowsExpiredRoots +__SSLGetDiffieHellmanParams +__SSLGetEnableCertVerify +__SSLGetProtocolVersion +__SSLGetProtocolVersionEnabled +__SSLGetRsaBlinding +__SSLNewContext +__SSLNewDatagramContext +__SSLSetAllowsAnyRoot +__SSLSetAllowsExpiredCerts +__SSLSetAllowsExpiredRoots +__SSLSetDiffieHellmanParams +__SSLSetEnableCertVerify +__SSLSetProtocolVersion +__SSLSetProtocolVersionEnabled +__SSLSetRsaBlinding +__SSLSetTrustedRoots + +/* Workaround for radar://9392483 */ +/* _SSLCopyPeerCertificates */ +/* _SSLDisposeContext */ +/* _SSLNewContext */ +/* _SSLSetEnableCertVerify */ +/* _SSLSetAllowsAnyRoot */ +/* _SSLSetAllowsExpiredRoots */ +/* _SSLSetProtocolVersionEnabled */ +/* end workaround */ +_SecASN1PrintableString +_SecAbsoluteTimeFromDateContent +_SecASN1UTF8String +_SecAccessGroupsGetCurrent +_SecAsn1CoderCreate +_SecAsn1CoderRelease +_SecAsn1DecodeData +_SecAsn1EncodeItem +_SecAsn1OidCompare +_SecDERItemCopyOIDDecimalRepresentation +_SecDigestCreate +_SecFrameworkCopyResourceContents +_SecFrameworkCopyResourceURL +_SecPKCS12Import +_SecRandomCopyBytes +_SecSHA1DigestCreate +_SecTaskCopySigningIdentifier +_SecTaskCopyValueForEntitlement +_SecTaskCopyValuesForEntitlements +_SecTaskCreateFromSelf +_SecTaskCreateWithAuditToken +_SecTaskGetTypeID +__NtlmCreateClientResponse +_kSecAsn1OCSPBasicResponseTemplate +_kSecAsn1OCSPCertStatusRevokedTemplate +_kSecAsn1OCSPResponderIDAsKeyTemplate +_kSecAsn1OCSPResponderIDAsNameTemplate +_kSecAsn1OCSPResponseDataTemplate +_kSecAsn1OCSPResponseTemplate +_kSecAsn1OCSPSignedRequestTemplate +_kSecCSRBasicContraintsPathLen +_kSecCSRChallengePassword +_kSecOidCommonName +_kSecOidCountryName +_kSecOidLocalityName +_kSecOidOrganization +_kSecOidOrganizationalUnit +_kSecOidStateProvinceName +_kSecRandomDefault + +_oidAnyExtendedKeyUsage +_oidAnyPolicy +_vmdh_create +_vmdh_destroy +_vmdh_encrypt_password +_vmdh_generate_key + +_SecSMIMEFindBulkAlgForRecipients + +//Localization +_SecFrameworkCopyLocalizedString + diff --git a/Security.xcodeproj/project.pbxproj b/Security.xcodeproj/project.pbxproj index 04caee63..ac141335 100644 --- a/Security.xcodeproj/project.pbxproj +++ b/Security.xcodeproj/project.pbxproj @@ -7,461 +7,1402 @@ objects = { /* Begin PBXAggregateTarget section */ - 0C6C642915D5ADB500BC68CD /* Security_kexts */ = { + 05EF68AF1949149C007958C3 /* Security_temporary_UI */ = { isa = PBXAggregateTarget; - buildConfigurationList = 0C6C642A15D5ADB500BC68CD /* Build configuration list for PBXAggregateTarget "Security_kexts" */; + buildConfigurationList = 05EF68B01949149C007958C3 /* Build configuration list for PBXAggregateTarget "Security_temporary_UI" */; buildPhases = ( ); dependencies = ( - 0C6C643015D5AE4C00BC68CD /* PBXTargetDependency */, - 0C6C642E15D5ADC900BC68CD /* PBXTargetDependency */, + 05EF68B4194914C2007958C3 /* PBXTargetDependency */, + ); + name = Security_temporary_UI; + productName = Security_temporary_UI; + }; + 05EF68B519491512007958C3 /* Security_frameworks */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 05EF68B619491512007958C3 /* Build configuration list for PBXAggregateTarget "Security_frameworks" */; + buildPhases = ( + ); + dependencies = ( + 05EF68BA19491577007958C3 /* PBXTargetDependency */, + ); + name = Security_frameworks; + productName = Security_framework; + }; + 05EF68BB194915A5007958C3 /* Security_executables */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 05EF68BC194915A5007958C3 /* Build configuration list for PBXAggregateTarget "Security_executables" */; + buildPhases = ( + ); + dependencies = ( + 05EF68CA1949167B007958C3 /* PBXTargetDependency */, + 05EF68C81949166E007958C3 /* PBXTargetDependency */, + 05EF68C0194915B6007958C3 /* PBXTargetDependency */, + ); + name = Security_executables; + productName = Security_executables; + }; + 05EF68C1194915FB007958C3 /* Security_kexts */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 05EF68C2194915FB007958C3 /* Build configuration list for PBXAggregateTarget "Security_kexts" */; + buildPhases = ( + ); + dependencies = ( + 05EF68C61949160C007958C3 /* PBXTargetDependency */, ); name = Security_kexts; productName = Security_kexts; }; - 182BB598146FE295000BF1F3 /* World */ = { + 0C6799F912F7C37C00712919 /* dtlsTests */ = { isa = PBXAggregateTarget; - buildConfigurationList = 182BB599146FE295000BF1F3 /* Build configuration list for PBXAggregateTarget "World" */; + buildConfigurationList = 0C679A0412F7C3AE00712919 /* Build configuration list for PBXAggregateTarget "dtlsTests" */; buildPhases = ( - 18F2360315CB30EC00060520 /* ShellScript */, ); dependencies = ( - 186F779914E5A06500434E1F /* PBXTargetDependency */, - 186F779B14E5A06800434E1F /* PBXTargetDependency */, - 0CFE4BA7167943EF0077AE4F /* PBXTargetDependency */, + 0CCA42F715C8A820002AEC4C /* PBXTargetDependency */, + 0CCA42F515C8A815002AEC4C /* PBXTargetDependency */, ); - name = World; - productName = SecurityFramework; + name = dtlsTests; + productName = dtlsTests; }; - 186F778814E59FB200434E1F /* Security_frameworks */ = { + 0C7CFA2E14E1BA4800DF9D95 /* phase1_ios */ = { isa = PBXAggregateTarget; - buildConfigurationList = 186F778914E59FB200434E1F /* Build configuration list for PBXAggregateTarget "Security_frameworks" */; + buildConfigurationList = 0C7CFA2F14E1BA4800DF9D95 /* Build configuration list for PBXAggregateTarget "phase1_ios" */; buildPhases = ( ); dependencies = ( - 186F779714E5A04200434E1F /* PBXTargetDependency */, - 186F779514E5A01C00434E1F /* PBXTargetDependency */, - 186F779314E5A01700434E1F /* PBXTargetDependency */, + 0C7CFA3714E1BAEC00DF9D95 /* PBXTargetDependency */, + 0C7CFA3514E1BA7000DF9D95 /* PBXTargetDependency */, ); - name = Security_frameworks; - productName = Framework; + name = phase1_ios; + productName = kernel; }; - 186F778C14E59FDA00434E1F /* Security_executables */ = { + 4C541F840F250BF500E508AE /* phase2 */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 4C541FA30F250C8C00E508AE /* Build configuration list for PBXAggregateTarget "phase2" */; + buildPhases = ( + ); + dependencies = ( + 72D41316175D13E40052A8ED /* PBXTargetDependency */, + 4C541F8C0F250C0400E508AE /* PBXTargetDependency */, + 4C541F8E0F250C0900E508AE /* PBXTargetDependency */, + 4C541F920F250C1300E508AE /* PBXTargetDependency */, + 4C541F900F250C0E00E508AE /* PBXTargetDependency */, + 4C9DE9EF1181ACA000CF5C27 /* PBXTargetDependency */, + 0C664AB41759270C0092D3D9 /* PBXTargetDependency */, + 0C99B740131C984900584CF4 /* PBXTargetDependency */, + 0CC827F2138712B100BD99B7 /* PBXTargetDependency */, + 0CD72A5A16D55BF100A4B8A3 /* PBXTargetDependency */, + 52D82BF616A627100078DFE5 /* PBXTargetDependency */, + 5DDD0BEE16D6748900D6C0D6 /* PBXTargetDependency */, + 4C52D0EE16EFCD720079966E /* PBXTargetDependency */, + BE197F631911742900BA91D1 /* PBXTargetDependency */, + BE4AC9B418B8020400B84964 /* PBXTargetDependency */, + 5346481B17331ED800FE9172 /* PBXTargetDependency */, + ); + name = phase2; + productName = phase2; + }; + 4C541F950F250C3000E508AE /* phase1 */ = { isa = PBXAggregateTarget; - buildConfigurationList = 186F778D14E59FDA00434E1F /* Build configuration list for PBXAggregateTarget "Security_executables" */; + buildConfigurationList = 4C541FA20F250C8C00E508AE /* Build configuration list for PBXAggregateTarget "phase1" */; buildPhases = ( ); dependencies = ( - 721680B3179B4C6C00406BB4 /* PBXTargetDependency */, - 37A7CEDA197DBA8700926CE8 /* PBXTargetDependency */, - 722CF218175D602F00BCE0A5 /* PBXTargetDependency */, - 521470291697842500DF0DB3 /* PBXTargetDependency */, - 18F235FF15CA100300060520 /* PBXTargetDependency */, - 186F779114E5A00F00434E1F /* PBXTargetDependency */, - 0CCEBDBA16C303D8001BD7F6 /* PBXTargetDependency */, - 0CFC55E315DDB86500BEC89E /* PBXTargetDependency */, - C2432A2515C726B50096DB5B /* PBXTargetDependency */, - 4CB23B90169F59D8003A0131 /* PBXTargetDependency */, - EBB9FFE01682E71F00FF9774 /* PBXTargetDependency */, + 4C541F9D0F250C3500E508AE /* PBXTargetDependency */, ); - name = Security_executables; - productName = Other; + name = phase1; + productName = phase1; }; - 4CE4729E16D833FD009070D1 /* Security_temporary_UI */ = { + 4C91273D0ADBF46200AF202E /* world */ = { isa = PBXAggregateTarget; - buildConfigurationList = 4CE472C716D833FE009070D1 /* Build configuration list for PBXAggregateTarget "Security_temporary_UI" */; + buildConfigurationList = 4C91274A0ADBF4A100AF202E /* Build configuration list for PBXAggregateTarget "world" */; buildPhases = ( ); dependencies = ( - 4C797BC916D83A3100C7B586 /* PBXTargetDependency */, - 4C797BF116D83A3800C7B586 /* PBXTargetDependency */, + 4C541F9F0F250C4F00E508AE /* PBXTargetDependency */, + 4C541FA10F250C5200E508AE /* PBXTargetDependency */, ); - name = Security_temporary_UI; - productName = "Security_ temporary_UI"; + name = world; + productName = world; + }; + E75533E01651D8A900D2B847 /* CKd-only */ = { + isa = PBXAggregateTarget; + buildConfigurationList = E75533F51651D8A900D2B847 /* Build configuration list for PBXAggregateTarget "CKd-only" */; + buildPhases = ( + ); + dependencies = ( + E7B01BA81664294D000485F1 /* PBXTargetDependency */, + E7F0FC171651DA5E002BEC2D /* PBXTargetDependency */, + ); + name = "CKd-only"; + productName = phase2; }; /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ - 0C10987616CAAE8200803B8F /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1831329914EB2C6D00F0BCAC /* libASN1.a */; }; - 0C4EAE4C1766864F00773425 /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18752C1D16F2837A004E2799 /* libaks.a */; }; - 0C4EAE761766875E00773425 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFD14CF429600B05E7F /* IOKit.framework */; }; - 0C4EAE7717668DDF00773425 /* libsecdRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C4EAE721766865000773425 /* libsecdRegressions.a */; }; - 0C4F055E15C9E51A00F9DFD5 /* sslTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C4F055D15C9E51A00F9DFD5 /* sslTypes.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 0C6C632A15D1989900BC68CD /* libsecurity_ssl_regressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C6D77CF15C8B66000BB4405 /* libsecurity_ssl_regressions.a */; }; - 0C6C633015D19FF500BC68CD /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; - 0C6D0065177B54CB0095D167 /* com.apple.securityd in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0C6D0064177B54C60095D167 /* com.apple.securityd */; }; - 0CAA7AB516C9A72A00A32C6D /* libsecurity_keychain_regressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CBD50B316C325F000713B6C /* libsecurity_keychain_regressions.a */; }; - 0CBD50DC16C32C8D00713B6C /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894015FFECF3008CE3E3 /* libutilities.a */; }; - 0CC3351C16C1ED8000399E53 /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18D4053B14CE2C1600A2BE4E /* libsecurity.a */; }; - 0CC3351E16C1ED8000399E53 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1831329A14EB2C6D00F0BCAC /* libDER.a */; }; - 0CC3351F16C1ED8000399E53 /* libSecItemShimOSX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 186CDD1E14CA11C700AF9171 /* libSecItemShimOSX.a */; }; - 0CC3352016C1ED8000399E53 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894015FFECF3008CE3E3 /* libutilities.a */; }; - 0CC3352116C1ED8000399E53 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF42B8F159E674D00ACACE1 /* Foundation.framework */; }; - 0CC3352216C1ED8000399E53 /* libcorecrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8313C814F5A26500DF7FDC /* libcorecrypto.dylib */; }; - 0CC3352316C1ED8000399E53 /* libSOSRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1288EC15FFE9D7008CE3E3 /* libSOSRegressions.a */; }; - 0CC3352416C1ED8000399E53 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; - 0CC3352616C1ED8000399E53 /* libsecipc_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270F6014CF655B00B05E7F /* libsecipc_client.a */; }; - 0CC3352716C1ED8000399E53 /* libSecureObjectSync.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1288EA15FFE9D7008CE3E3 /* libSecureObjectSync.a */; }; - 0CC3355A16C1EEE700399E53 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CC3355716C1EEE700399E53 /* main.c */; }; - 0CC3356316C1EFBE00399E53 /* libregressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CC3356016C1EF5D00399E53 /* libregressions.a */; }; - 0CCEBDB116C2CFC1001BD7F6 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C6C630E15D193C800BC68CD /* main.c */; }; - 0CCEBDB416C2D026001BD7F6 /* libregressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CC3356016C1EF5D00399E53 /* libregressions.a */; }; - 0CCEBDB616C2E431001BD7F6 /* libsecurityd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270C7D14CE573D00B05E7F /* libsecurityd.a */; }; - 0CCEBDB716C2E6B0001BD7F6 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFB14CF427800B05E7F /* CFNetwork.framework */; }; - 0CCEBDB816C2E6CE001BD7F6 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5AD146FEF43000BF1F3 /* libsqlite3.dylib */; }; - 0CCEBDBB16C30924001BD7F6 /* libutilitiesRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894215FFECF3008CE3E3 /* libutilitiesRegressions.a */; }; - 18270EE814CF294500B05E7F /* libsecurityd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270C7D14CE573D00B05E7F /* libsecurityd.a */; }; - 18270EF614CF334A00B05E7F /* server.c in Sources */ = {isa = PBXBuildFile; fileRef = 18270EF314CF333400B05E7F /* server.c */; }; - 18270EF814CF424900B05E7F /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; - 18270EF914CF425100B05E7F /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5B9146FF0BE000BF1F3 /* libbsm.dylib */; }; - 18270EFA14CF426200B05E7F /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5AD146FEF43000BF1F3 /* libsqlite3.dylib */; }; - 18270EFC14CF427800B05E7F /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFB14CF427800B05E7F /* CFNetwork.framework */; }; - 18270EFE14CF429600B05E7F /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFD14CF429600B05E7F /* IOKit.framework */; }; - 18270F0014CF42CA00B05E7F /* libcorecrypto.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFF14CF42CA00B05E7F /* libcorecrypto.a */; }; - 18270F6114CF656E00B05E7F /* libsecipc_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270F6014CF655B00B05E7F /* libsecipc_client.a */; }; - 182A191115D09AFF006AB103 /* connection.c in Sources */ = {isa = PBXBuildFile; fileRef = 182A191015D09AFF006AB103 /* connection.c */; }; - 182BB22A146F068B000BF1F3 /* iToolsTrustedApps.plist in Resources */ = {isa = PBXBuildFile; fileRef = 182BB229146F068B000BF1F3 /* iToolsTrustedApps.plist */; }; - 182BB3C5146F1DCB000BF1F3 /* sd_cspdl_common.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 182BB3C4146F1DCB000BF1F3 /* sd_cspdl_common.mdsinfo */; }; - 182BB41B146F2533000BF1F3 /* libsecurity_apple_csp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B5C6146DE6C8007E536C /* libsecurity_apple_csp.a */; }; - 182BB41C146F2533000BF1F3 /* libsecurity_apple_cspdl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B5D2146DE6CE007E536C /* libsecurity_apple_cspdl.a */; }; - 182BB41D146F2533000BF1F3 /* libsecurity_apple_file_dl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B5DE146DE6D7007E536C /* libsecurity_apple_file_dl.a */; }; - 182BB41E146F2533000BF1F3 /* libsecurity_apple_x509_cl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B5EB146DE6E8007E536C /* libsecurity_apple_x509_cl.a */; }; - 182BB41F146F2533000BF1F3 /* libsecurity_apple_x509_tp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B5F9146DE6FD007E536C /* libsecurity_apple_x509_tp.a */; }; - 182BB421146F2533000BF1F3 /* libsecurity_authorization.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B612146DE70A007E536C /* libsecurity_authorization.a */; }; - 182BB422146F2533000BF1F3 /* libsecurity_cdsa_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B61E146DE715007E536C /* libsecurity_cdsa_client.a */; }; - 182BB423146F2533000BF1F3 /* libsecurity_cdsa_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B55A146DE227007E536C /* libsecurity_cdsa_utilities.a */; }; - 182BB424146F2533000BF1F3 /* libsecurity_checkpw.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B644146DE748007E536C /* libsecurity_checkpw.a */; }; - 182BB425146F2533000BF1F3 /* libsecurity_cms.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B654146DE750007E536C /* libsecurity_cms.a */; }; - 182BB426146F2533000BF1F3 /* libsecurity_codesigning.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B666146DE757007E536C /* libsecurity_codesigning.a */; }; - 182BB428146F2533000BF1F3 /* libsecurity_cryptkit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B684146DE76F007E536C /* libsecurity_cryptkit.a */; }; - 182BB429146F2533000BF1F3 /* libsecurity_filedb.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B69D146DE797007E536C /* libsecurity_filedb.a */; }; - 182BB42A146F2533000BF1F3 /* libsecurity_keychain.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B6B3146DE7A0007E536C /* libsecurity_keychain.a */; }; - 182BB42B146F2533000BF1F3 /* libsecurity_ocspd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B6E9146DE7E8007E536C /* libsecurity_ocspd.a */; }; - 182BB42C146F2533000BF1F3 /* libsecurity_pkcs12.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B6F5146DE7EF007E536C /* libsecurity_pkcs12.a */; }; - 182BB42D146F2533000BF1F3 /* libsecurity_transform.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B739146DE845007E536C /* libsecurity_transform.a */; }; - 182BB42E146F2533000BF1F3 /* libsecurityd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 184461B1146E9D3300B12992 /* libsecurityd_client.a */; }; - 182BB4E1146F2591000BF1F3 /* libsecurity_manifest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B6D0146DE7D7007E536C /* libsecurity_manifest.a */; }; - 182BB4E2146F2591000BF1F3 /* libsecurity_mds.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B6DC146DE7E0007E536C /* libsecurity_mds.a */; }; - 182BB4E3146F2591000BF1F3 /* libsecurity_sd_cspdl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B701146DE7F7007E536C /* libsecurity_sd_cspdl.a */; }; - 182BB4E4146F2591000BF1F3 /* libsecurity_smime.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B71C146DE825007E536C /* libsecurity_smime.a */; }; - 182BB4E5146F2591000BF1F3 /* libsecurity_ssl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B728146DE839007E536C /* libsecurity_ssl.a */; }; - 182BB55F146F4544000BF1F3 /* FDEPrefs.plist in Resources */ = {isa = PBXBuildFile; fileRef = 182BB55C146F4544000BF1F3 /* FDEPrefs.plist */; }; - 182BB57F146F51A5000BF1F3 /* csparser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 182BB557146F4510000BF1F3 /* csparser.cpp */; }; - 182BB589146FE013000BF1F3 /* libsecurity_codesigning.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B666146DE757007E536C /* libsecurity_codesigning.a */; }; - 182BB590146FE125000BF1F3 /* libsecurity_cdsa_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B55A146DE227007E536C /* libsecurity_cdsa_utilities.a */; }; - 182BB591146FE12F000BF1F3 /* libsecurity_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B538146DDBE5007E536C /* libsecurity_utilities.a */; }; - 182BB592146FE1D7000BF1F3 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; - 182BB5AA146FEE50000BF1F3 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; - 182BB5AC146FEF15000BF1F3 /* libpam.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5AB146FEF14000BF1F3 /* libpam.dylib */; }; - 182BB5AE146FEF43000BF1F3 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5AD146FEF43000BF1F3 /* libsqlite3.dylib */; }; - 182BB5B2146FF039000BF1F3 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5B1146FF039000BF1F3 /* libz.dylib */; }; - 182BB5B4146FF04C000BF1F3 /* libxar.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5B3146FF04C000BF1F3 /* libxar.dylib */; }; - 182BB5B6146FF090000BF1F3 /* libauto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5B5146FF08F000BF1F3 /* libauto.dylib */; }; - 182BB5B8146FF0A2000BF1F3 /* libobjc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5B7146FF0A1000BF1F3 /* libobjc.dylib */; }; - 182BB5BA146FF0BF000BF1F3 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5B9146FF0BE000BF1F3 /* libbsm.dylib */; }; - 182BB5BB146FF62F000BF1F3 /* libsecurity_comcryption.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B676146DE75E007E536C /* libsecurity_comcryption.a */; }; - 1831329B14EB2C6D00F0BCAC /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1831329914EB2C6D00F0BCAC /* libASN1.a */; }; - 1831329C14EB2C6D00F0BCAC /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1831329A14EB2C6D00F0BCAC /* libDER.a */; }; - 18363C1417026084002D5C1C /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFD14CF429600B05E7F /* IOKit.framework */; }; - 1844605F146DE93E00B12992 /* csp_capabilities.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 1844605B146DE93E00B12992 /* csp_capabilities.mdsinfo */; }; - 18446060146DE93E00B12992 /* csp_capabilities_common.mds in Resources */ = {isa = PBXBuildFile; fileRef = 1844605C146DE93E00B12992 /* csp_capabilities_common.mds */; }; - 18446061146DE93E00B12992 /* csp_common.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 1844605D146DE93E00B12992 /* csp_common.mdsinfo */; }; - 18446062146DE93E00B12992 /* csp_primary.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 1844605E146DE93E00B12992 /* csp_primary.mdsinfo */; }; - 18446083146DF58B00B12992 /* libsecurity_cdsa_plugin.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B62B146DE720007E536C /* libsecurity_cdsa_plugin.a */; }; - 184460C7146E7B1E00B12992 /* cspdl_common.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 184460C3146E7B1E00B12992 /* cspdl_common.mdsinfo */; }; - 184460C8146E7B1E00B12992 /* cspdl_csp_capabilities.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 184460C4146E7B1E00B12992 /* cspdl_csp_capabilities.mdsinfo */; }; - 184460C9146E7B1E00B12992 /* cspdl_csp_primary.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 184460C5146E7B1E00B12992 /* cspdl_csp_primary.mdsinfo */; }; - 184460CA146E7B1E00B12992 /* cspdl_dl_primary.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 184460C6146E7B1E00B12992 /* cspdl_dl_primary.mdsinfo */; }; - 184460E3146E806700B12992 /* dl_common.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 184460E1146E806700B12992 /* dl_common.mdsinfo */; }; - 184460E4146E806700B12992 /* dl_primary.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 184460E2146E806700B12992 /* dl_primary.mdsinfo */; }; - 18446105146E82C800B12992 /* cl_common.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 18446103146E82C800B12992 /* cl_common.mdsinfo */; }; - 18446106146E82C800B12992 /* cl_primary.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 18446104146E82C800B12992 /* cl_primary.mdsinfo */; }; - 18446115146E85A300B12992 /* tp_common.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 18446112146E85A300B12992 /* tp_common.mdsinfo */; }; - 18446116146E85A300B12992 /* tp_policyOids.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 18446113146E85A300B12992 /* tp_policyOids.mdsinfo */; }; - 18446117146E85A300B12992 /* tp_primary.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 18446114146E85A300B12992 /* tp_primary.mdsinfo */; }; - 18500F9B14708D0E006F9AB4 /* SecDebugErrorMessages.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18500F9A14708D0E006F9AB4 /* SecDebugErrorMessages.strings */; }; - 18500FA114708F19006F9AB4 /* SecErrorMessages.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18500F9F14708F19006F9AB4 /* SecErrorMessages.strings */; }; - 1879B4AA146DCA18007E536C /* cssm.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 1879B4A9146DCA18007E536C /* cssm.mdsinfo */; }; - 1879B546146DE192007E536C /* libsecurity_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B538146DDBE5007E536C /* libsecurity_utilities.a */; }; - 1879B570146DE2E6007E536C /* libsecurity_cdsa_utils.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B54F146DE212007E536C /* libsecurity_cdsa_utils.a */; }; - 1879B571146DE2FF007E536C /* libsecurity_cssm.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B565146DE244007E536C /* libsecurity_cssm.a */; }; - 187A05B1170393FF0038C158 /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18752C1D16F2837A004E2799 /* libaks.a */; }; - 187D6B9315D435BD00E27494 /* authorization.buttons.strings in Resources */ = {isa = PBXBuildFile; fileRef = 187D6B8F15D4359F00E27494 /* authorization.buttons.strings */; }; - 187D6B9415D435C700E27494 /* authorization.prompts.strings in Resources */ = {isa = PBXBuildFile; fileRef = 187D6B9115D4359F00E27494 /* authorization.prompts.strings */; }; - 187D6B9715D438AD00E27494 /* authorization.plist in Copy authorization.plist */ = {isa = PBXBuildFile; fileRef = 187D6B9515D436BF00E27494 /* authorization.plist */; }; - 187D6B9815D4476D00E27494 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFD14CF429600B05E7F /* IOKit.framework */; }; - 1885B45214D9AB8100519375 /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1885B3F914D8D9B100519375 /* libASN1.a */; }; - 188AD8DC1471FE3E0081C619 /* FDELocalizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 188AD8D81471FE3D0081C619 /* FDELocalizable.strings */; }; - 188AD8DD1471FE3E0081C619 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 188AD8DA1471FE3D0081C619 /* InfoPlist.strings */; }; - 189757871700CF4C00672567 /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18752C1D16F2837A004E2799 /* libaks.a */; }; - 18A5493315EFD3690059E6DC /* dummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18A5493115EFD2F40059E6DC /* dummy.cpp */; }; - 18AD56A414CDE7BE008233F2 /* libSecItemShimOSX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 186CDD1E14CA11C700AF9171 /* libSecItemShimOSX.a */; }; - 18B647EC14D9F20500F538BF /* oidsalg.h in Headers */ = {isa = PBXBuildFile; fileRef = 18B647E814D9EB6300F538BF /* oidsalg.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18B647ED14D9F20F00F538BF /* oidsattr.h in Headers */ = {isa = PBXBuildFile; fileRef = 18B647EA14D9EE4300F538BF /* oidsattr.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18BBC7361471F5A300F2B224 /* SecExternalSourceTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 18BBC7351471F5A300F2B224 /* SecExternalSourceTransform.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18BEB19A14CF7F8100C8BD36 /* com.apple.secd.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 18BEB19614CF74C100C8BD36 /* com.apple.secd.plist */; }; - 18CD682717272EBC005345FB /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18752C1D16F2837A004E2799 /* libaks.a */; }; - 18CD684E17272EE2005345FB /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFD14CF429600B05E7F /* IOKit.framework */; }; - 18CFEE8915DEE2C600E3F2A3 /* com.apple.authd.sb in Copy sandbox profile */ = {isa = PBXBuildFile; fileRef = 18CFEE8715DEE25200E3F2A3 /* com.apple.authd.sb */; }; - 18D6803B16B768F700DF6D2E /* com.apple.authd in Copy asl module */ = {isa = PBXBuildFile; fileRef = 18D6803916B768D500DF6D2E /* com.apple.authd */; }; - 18F2352115C9FA3C00060520 /* agent.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F234F915C9FA3B00060520 /* agent.c */; }; - 18F2352215C9FA3C00060520 /* authdb.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F234FB15C9FA3B00060520 /* authdb.c */; }; - 18F2352315C9FA3C00060520 /* authitems.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F234FD15C9FA3B00060520 /* authitems.c */; }; - 18F2352415C9FA3C00060520 /* authtoken.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F234FF15C9FA3B00060520 /* authtoken.c */; }; - 18F2352515C9FA3C00060520 /* authutilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2350215C9FA3B00060520 /* authutilities.c */; }; - 18F2352615C9FA3C00060520 /* ccaudit.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2350415C9FA3B00060520 /* ccaudit.c */; }; - 18F2352715C9FA3C00060520 /* crc.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2350615C9FA3B00060520 /* crc.c */; }; - 18F2352815C9FA3C00060520 /* credential.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2350815C9FA3B00060520 /* credential.c */; }; - 18F2352915C9FA3C00060520 /* debugging.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2350A15C9FA3B00060520 /* debugging.c */; }; - 18F2352B15C9FA3C00060520 /* engine.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2350F15C9FA3B00060520 /* engine.c */; }; - 18F2352C15C9FA3C00060520 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2351115C9FA3B00060520 /* main.c */; }; - 18F2352D15C9FA3C00060520 /* mechanism.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2351215C9FA3B00060520 /* mechanism.c */; }; - 18F2352E15C9FA3C00060520 /* object.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2351415C9FA3C00060520 /* object.c */; }; - 18F2352F15C9FA3C00060520 /* process.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2351615C9FA3C00060520 /* process.c */; }; - 18F2353015C9FA3C00060520 /* rule.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2351815C9FA3C00060520 /* rule.c */; }; - 18F2353215C9FA3C00060520 /* server.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2351D15C9FA3C00060520 /* server.c */; }; - 18F2353315C9FA3C00060520 /* session.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2351F15C9FA3C00060520 /* session.c */; }; - 18F2353515C9FDB700060520 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; - 18F2353615C9FDD200060520 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF42BB515A3947F00ACACE1 /* Security.framework */; }; - 18F2353715C9FDE400060520 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5B9146FF0BE000BF1F3 /* libbsm.dylib */; }; - 18F2353815C9FDEF00060520 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5AD146FEF43000BF1F3 /* libsqlite3.dylib */; }; - 18F2360115CAF41200060520 /* libsecurity_codesigning.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F2360015CAF41100060520 /* libsecurity_codesigning.a */; }; - 18FE68021471A42900A2CBE3 /* SecDigestTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3A3146F1BEC000BF1F3 /* SecDigestTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68031471A42900A2CBE3 /* SecReadTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3A4146F1BEC000BF1F3 /* SecReadTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68041471A42900A2CBE3 /* SecTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3A5146F1BEC000BF1F3 /* SecTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68051471A42900A2CBE3 /* SecCustomTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3A6146F1BEC000BF1F3 /* SecCustomTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68061471A42900A2CBE3 /* SecDecodeTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3A7146F1BEC000BF1F3 /* SecDecodeTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68071471A42900A2CBE3 /* SecEncodeTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3A8146F1BEC000BF1F3 /* SecEncodeTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68081471A42900A2CBE3 /* SecEncryptTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3A9146F1BEC000BF1F3 /* SecEncryptTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68091471A42900A2CBE3 /* SecSignVerifyTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3AA146F1BEC000BF1F3 /* SecSignVerifyTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE680A1471A42900A2CBE3 /* SecTransformReadTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3AB146F1BEC000BF1F3 /* SecTransformReadTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE680B1471A42900A2CBE3 /* CipherSuite.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB36E146F13B4000BF1F3 /* CipherSuite.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE680C1471A42900A2CBE3 /* SecureTransport.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB36F146F13B4000BF1F3 /* SecureTransport.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE680D1471A42900A2CBE3 /* mds.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB356146F1198000BF1F3 /* mds.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE680E1471A42900A2CBE3 /* mds_schema.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB357146F1198000BF1F3 /* mds_schema.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE680F1471A42900A2CBE3 /* SecureDownload.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB315146F0E7E000BF1F3 /* SecureDownload.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68101471A42900A2CBE3 /* SecAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB187146EAD4C000BF1F3 /* SecAccess.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68111471A42900A2CBE3 /* SecACL.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB188146EAD4C000BF1F3 /* SecACL.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68121471A42900A2CBE3 /* SecBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB189146EAD4C000BF1F3 /* SecBase.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68131471A42900A2CBE3 /* SecCertificate.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB18A146EAD4C000BF1F3 /* SecCertificate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68141471A42900A2CBE3 /* SecIdentity.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB18B146EAD4C000BF1F3 /* SecIdentity.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68151471A42900A2CBE3 /* SecIdentitySearch.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB18C146EAD4C000BF1F3 /* SecIdentitySearch.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68161471A42900A2CBE3 /* SecItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB18D146EAD4C000BF1F3 /* SecItem.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68171471A42900A2CBE3 /* SecKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB18E146EAD4C000BF1F3 /* SecKey.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68181471A42900A2CBE3 /* SecKeychain.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB18F146EAD4C000BF1F3 /* SecKeychain.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68191471A42900A2CBE3 /* SecKeychainItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB190146EAD4C000BF1F3 /* SecKeychainItem.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE681A1471A42900A2CBE3 /* SecKeychainSearch.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB191146EAD4C000BF1F3 /* SecKeychainSearch.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE681B1471A42900A2CBE3 /* SecPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB192146EAD4C000BF1F3 /* SecPolicy.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE681C1471A42900A2CBE3 /* SecPolicySearch.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB193146EAD4C000BF1F3 /* SecPolicySearch.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE681D1471A42900A2CBE3 /* SecTrust.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB194146EAD4C000BF1F3 /* SecTrust.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE681E1471A42900A2CBE3 /* SecTrustedApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB195146EAD4C000BF1F3 /* SecTrustedApplication.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE681F1471A42900A2CBE3 /* Security.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB196146EAD4C000BF1F3 /* Security.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68201471A42900A2CBE3 /* SecImportExport.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB197146EAD4C000BF1F3 /* SecImportExport.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68211471A42900A2CBE3 /* SecTrustSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB198146EAD4C000BF1F3 /* SecTrustSettings.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68221471A42900A2CBE3 /* SecCertificateOIDs.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB199146EAD4C000BF1F3 /* SecCertificateOIDs.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68231471A42900A2CBE3 /* SecRandom.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB19A146EAD4C000BF1F3 /* SecRandom.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68241471A42900A2CBE3 /* SecTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844617E146E9A8500B12992 /* SecTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68251471A42900A2CBE3 /* CodeSigning.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844617F146E9A8500B12992 /* CodeSigning.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68261471A42900A2CBE3 /* CSCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446180146E9A8500B12992 /* CSCommon.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68271471A42900A2CBE3 /* SecCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446181146E9A8500B12992 /* SecCode.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68281471A42900A2CBE3 /* SecStaticCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446182146E9A8500B12992 /* SecStaticCode.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68291471A42900A2CBE3 /* SecRequirement.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446183146E9A8500B12992 /* SecRequirement.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE682A1471A42900A2CBE3 /* SecCodeHost.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446184146E9A8500B12992 /* SecCodeHost.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE682B1471A42900A2CBE3 /* CMSDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446170146E982800B12992 /* CMSDecoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE682C1471A42900A2CBE3 /* CMSEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446171146E982800B12992 /* CMSEncoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE682D1471A42900A2CBE3 /* AuthorizationTags.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446144146E923200B12992 /* AuthorizationTags.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE682E1471A42900A2CBE3 /* AuthSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446145146E923200B12992 /* AuthSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE682F1471A42900A2CBE3 /* Authorization.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446146146E923200B12992 /* Authorization.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68301471A42900A2CBE3 /* AuthorizationDB.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446147146E923200B12992 /* AuthorizationDB.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68311471A42900A2CBE3 /* AuthorizationPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446148146E923200B12992 /* AuthorizationPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68321471A42900A2CBE3 /* SecAsn1Coder.h in Headers */ = {isa = PBXBuildFile; fileRef = 184460AB146DFCC100B12992 /* SecAsn1Coder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68331471A42900A2CBE3 /* SecAsn1Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 184460AC146DFCC100B12992 /* SecAsn1Templates.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68341471A42900A2CBE3 /* SecAsn1Types.h in Headers */ = {isa = PBXBuildFile; fileRef = 184460AD146DFCC100B12992 /* SecAsn1Types.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68351471A42900A2CBE3 /* certextensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4AD146DCA84007E536C /* certextensions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68361471A42900A2CBE3 /* cssm.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4AE146DCA84007E536C /* cssm.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68371471A42900A2CBE3 /* cssmaci.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4AF146DCA84007E536C /* cssmaci.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68381471A42900A2CBE3 /* cssmapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4B0146DCA84007E536C /* cssmapi.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68391471A42900A2CBE3 /* cssmapple.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4B1146DCA84007E536C /* cssmapple.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE683A1471A42900A2CBE3 /* cssmcli.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4B2146DCA84007E536C /* cssmcli.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE683B1471A42900A2CBE3 /* cssmconfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4B3146DCA84007E536C /* cssmconfig.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE683C1471A42900A2CBE3 /* cssmcspi.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4B4146DCA84007E536C /* cssmcspi.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE683D1471A42900A2CBE3 /* cssmdli.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4B5146DCA84007E536C /* cssmdli.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE683E1471A42900A2CBE3 /* cssmerr.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4B6146DCA84007E536C /* cssmerr.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE683F1471A42900A2CBE3 /* cssmkrapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4B7146DCA84007E536C /* cssmkrapi.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68401471A42900A2CBE3 /* cssmkrspi.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4B8146DCA84007E536C /* cssmkrspi.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68411471A42900A2CBE3 /* cssmspi.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4B9146DCA84007E536C /* cssmspi.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68421471A42900A2CBE3 /* cssmtpi.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4BA146DCA84007E536C /* cssmtpi.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68431471A42900A2CBE3 /* cssmtype.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4BB146DCA84007E536C /* cssmtype.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68441471A42900A2CBE3 /* eisl.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4BC146DCA84007E536C /* eisl.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68451471A42900A2CBE3 /* emmspi.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4BD146DCA84007E536C /* emmspi.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68461471A42900A2CBE3 /* emmtype.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4BE146DCA84007E536C /* emmtype.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE68491471A42900A2CBE3 /* oidsbase.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4C1146DCA84007E536C /* oidsbase.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE684A1471A42900A2CBE3 /* oidscert.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4C2146DCA84007E536C /* oidscert.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE684B1471A42900A2CBE3 /* oidscrl.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4C3146DCA84007E536C /* oidscrl.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE684C1471A42900A2CBE3 /* x509defs.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4C4146DCA84007E536C /* x509defs.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18FE684D1471A46600A2CBE3 /* asn1Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 184460A1146DFCB700B12992 /* asn1Templates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE684E1471A46600A2CBE3 /* AuthorizationPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844614F146E923B00B12992 /* AuthorizationPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE684F1471A46600A2CBE3 /* AuthorizationTagsPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844614E146E923B00B12992 /* AuthorizationTagsPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68501471A46600A2CBE3 /* certExtensionTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844609A146DFCB700B12992 /* certExtensionTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68511471A46600A2CBE3 /* checkpw.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446168146E95D700B12992 /* checkpw.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68521471A46600A2CBE3 /* CMSPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446174146E982D00B12992 /* CMSPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68531471A46600A2CBE3 /* CSCommonPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844618C146E9A8F00B12992 /* CSCommonPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68541471A46600A2CBE3 /* csrTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844609B146DFCB700B12992 /* csrTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68551471A46600A2CBE3 /* cssmapplePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4AB146DCA4A007E536C /* cssmapplePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68561471A46600A2CBE3 /* keyTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 184460A0146DFCB700B12992 /* keyTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68571471A46600A2CBE3 /* mdspriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB35A146F11A1000BF1F3 /* mdspriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68581471A46600A2CBE3 /* nameTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844609D146DFCB700B12992 /* nameTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68591471A46600A2CBE3 /* ocspTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844609C146DFCB700B12992 /* ocspTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE685A1471A46600A2CBE3 /* osKeyTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844609F146DFCB700B12992 /* osKeyTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE685B1471A46600A2CBE3 /* SecAccessPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1B2146EAD5D000BF1F3 /* SecAccessPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE685C1471A46600A2CBE3 /* secasn1t.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446099146DFCB700B12992 /* secasn1t.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE685D1471A46600A2CBE3 /* SecAssessment.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446194146E9A8F00B12992 /* SecAssessment.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE685E1471A46600A2CBE3 /* SecBasePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1B3146EAD5D000BF1F3 /* SecBasePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE685F1471A46600A2CBE3 /* SecCertificateBundle.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1B4146EAD5D000BF1F3 /* SecCertificateBundle.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68611471A46600A2CBE3 /* SecCertificatePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1B5146EAD5D000BF1F3 /* SecCertificatePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68621471A46600A2CBE3 /* SecCertificateRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1B6146EAD5D000BF1F3 /* SecCertificateRequest.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68631471A46600A2CBE3 /* SecCmsBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB383146F14D2000BF1F3 /* SecCmsBase.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68641471A46600A2CBE3 /* SecCmsContentInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB384146F14D2000BF1F3 /* SecCmsContentInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68651471A46600A2CBE3 /* SecCmsDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB385146F14D2000BF1F3 /* SecCmsDecoder.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68661471A46600A2CBE3 /* SecCmsDigestContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB386146F14D2000BF1F3 /* SecCmsDigestContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68671471A46600A2CBE3 /* SecCmsDigestedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB387146F14D2000BF1F3 /* SecCmsDigestedData.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68681471A46600A2CBE3 /* SecCmsEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB388146F14D2000BF1F3 /* SecCmsEncoder.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68691471A46600A2CBE3 /* SecCmsEncryptedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB389146F14D2000BF1F3 /* SecCmsEncryptedData.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE686A1471A46600A2CBE3 /* SecCmsEnvelopedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB38A146F14D2000BF1F3 /* SecCmsEnvelopedData.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE686B1471A46600A2CBE3 /* SecCmsMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB38B146F14D2000BF1F3 /* SecCmsMessage.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE686C1471A46600A2CBE3 /* SecCmsRecipientInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB38C146F14D2000BF1F3 /* SecCmsRecipientInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE686D1471A46600A2CBE3 /* SecCmsSignedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB38D146F14D2000BF1F3 /* SecCmsSignedData.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE686E1471A46600A2CBE3 /* SecCmsSignerInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB38E146F14D2000BF1F3 /* SecCmsSignerInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE686F1471A46600A2CBE3 /* SecCodeHostLib.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446193146E9A8F00B12992 /* SecCodeHostLib.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68701471A46600A2CBE3 /* SecCodePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844618D146E9A8F00B12992 /* SecCodePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68711471A46600A2CBE3 /* SecCodeSigner.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446190146E9A8F00B12992 /* SecCodeSigner.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68721471A46600A2CBE3 /* SecFDERecoveryAsymmetricCrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1AF146EAD5D000BF1F3 /* SecFDERecoveryAsymmetricCrypto.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68731471A46600A2CBE3 /* SecIdentityPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1B7146EAD5D000BF1F3 /* SecIdentityPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68741471A46600A2CBE3 /* SecIdentitySearchPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1C4146EAD5D000BF1F3 /* SecIdentitySearchPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68751471A46600A2CBE3 /* SecIntegrity.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446191146E9A8F00B12992 /* SecIntegrity.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68761471A46600A2CBE3 /* SecIntegrityLib.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446192146E9A8F00B12992 /* SecIntegrityLib.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68771471A46600A2CBE3 /* SecItemPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1CA146EAD5D000BF1F3 /* SecItemPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68781471A46600A2CBE3 /* SecKeychainItemExtendedAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1CB146EAD5D000BF1F3 /* SecKeychainItemExtendedAttributes.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68791471A46600A2CBE3 /* SecKeychainItemPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1B8146EAD5D000BF1F3 /* SecKeychainItemPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE687A1471A46600A2CBE3 /* SecKeychainPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1B9146EAD5D000BF1F3 /* SecKeychainPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE687B1471A46700A2CBE3 /* SecKeychainSearchPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1C5146EAD5D000BF1F3 /* SecKeychainSearchPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE687C1471A46700A2CBE3 /* SecKeyPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1BA146EAD5D000BF1F3 /* SecKeyPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE687D1471A46700A2CBE3 /* SecManifest.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB317146F0E94000BF1F3 /* SecManifest.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE687E1471A46700A2CBE3 /* SecNullTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3B6146F1BF9000BF1F3 /* SecNullTransform.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE687F1471A46700A2CBE3 /* SecPassword.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1B0146EAD5D000BF1F3 /* SecPassword.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68801471A46700A2CBE3 /* SecPolicyPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1BB146EAD5D000BF1F3 /* SecPolicyPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68811471A46700A2CBE3 /* SecRandomP.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1CF146EAD5D000BF1F3 /* SecRandomP.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68821471A46700A2CBE3 /* SecRecoveryPassword.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1CE146EAD5D000BF1F3 /* SecRecoveryPassword.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68831471A46700A2CBE3 /* SecRequirementPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844618F146E9A8F00B12992 /* SecRequirementPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68841471A46700A2CBE3 /* SecSMIME.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB38F146F14D2000BF1F3 /* SecSMIME.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68851471A46700A2CBE3 /* SecStaticCodePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844618E146E9A8F00B12992 /* SecStaticCodePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68861471A46700A2CBE3 /* SecTransformInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3B7146F1BF9000BF1F3 /* SecTransformInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68871471A46700A2CBE3 /* SecTrustedApplicationPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1BC146EAD5D000BF1F3 /* SecTrustedApplicationPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68881471A46700A2CBE3 /* SecTrustPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1BD146EAD5D000BF1F3 /* SecTrustPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE68891471A46700A2CBE3 /* SecTrustSettingsPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1C6146EAD5D000BF1F3 /* SecTrustSettingsPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE688A1471A46700A2CBE3 /* SecureDownloadInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB318146F0E94000BF1F3 /* SecureDownloadInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE688B1471A46700A2CBE3 /* SecureTransportPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB372146F13BB000BF1F3 /* SecureTransportPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE688C1471A46700A2CBE3 /* TrustSettingsSchema.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1C8146EAD5D000BF1F3 /* TrustSettingsSchema.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 18FE688D1471A46700A2CBE3 /* X509Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844609E146DFCB700B12992 /* X509Templates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 37A7CEAE197DB8FA00926CE8 /* FatDynamicValidation.c in Sources */ = {isa = PBXBuildFile; fileRef = 37A7CEAD197DB8FA00926CE8 /* FatDynamicValidation.c */; }; - 37A7CEDD197DCEE500926CE8 /* validation.sh in CopyFiles */ = {isa = PBXBuildFile; fileRef = 37A7CEDB197DCDD700926CE8 /* validation.sh */; }; - 395E7CEE16C64EA500CD82A4 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 395E7CED16C64EA500CD82A4 /* SystemConfiguration.framework */; }; - 39BFB04516D304DE0022564B /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 395E7CED16C64EA500CD82A4 /* SystemConfiguration.framework */; }; - 4A5C1790161A9DFB00ABF784 /* authd_private.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 18F2351A15C9FA3C00060520 /* authd_private.h */; }; - 4AD6F6F91651D2A600DB4CE6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF42B8F159E674D00ACACE1 /* Foundation.framework */; }; - 4C01DF14164C3E7C006798CD /* libSecureObjectSync.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1288EA15FFE9D7008CE3E3 /* libSecureObjectSync.a */; }; - 4C2505B716D2DF9F002CE025 /* Icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 4C2505B616D2DF9F002CE025 /* Icon.icns */; }; - 4C328D301778EC4F0015EED1 /* AOSUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C328D2F1778EC4F0015EED1 /* AOSUI.framework */; }; - 4C49390D16E51ACE00CE110C /* com.apple.security.keychain-circle-notification.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4C49390C16E51ACE00CE110C /* com.apple.security.keychain-circle-notification.plist */; }; - 4C49390F16E51FC700CE110C /* com.apple.security.keychain-circle-notification.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C49390C16E51ACE00CE110C /* com.apple.security.keychain-circle-notification.plist */; }; - 4C5DD46A17A5E5D000696A79 /* KNPersistantState.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C5DD44317A5E31900696A79 /* KNPersistantState.m */; }; - 4C5DD46C17A5F67300696A79 /* AppleSystemInfo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C5DD46B17A5F67300696A79 /* AppleSystemInfo.framework */; }; - 4C7D453D17BEE69B00DDD88F /* NSString+compactDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C7D453C17BEE69B00DDD88F /* NSString+compactDescription.m */; }; - 4C7D456817BEED0400DDD88F /* NSDictionary+compactDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C7D456517BEE6B700DDD88F /* NSDictionary+compactDescription.m */; }; - 4C7D456917BEED1400DDD88F /* NSSet+compactDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C7D456717BEE6B700DDD88F /* NSSet+compactDescription.m */; }; - 4C7D8765160A74C400D041E3 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894015FFECF3008CE3E3 /* libutilities.a */; }; - 4C8313C914F5A26500DF7FDC /* libcorecrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8313C814F5A26500DF7FDC /* libcorecrypto.dylib */; }; - 4C85DEDA16DBD5BF00ED8D47 /* KDCirclePeer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C85DED916DBD5BF00ED8D47 /* KDCirclePeer.m */; }; - 4C85DEDB16DBD5BF00ED8D47 /* KDCirclePeer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C85DED916DBD5BF00ED8D47 /* KDCirclePeer.m */; }; - 4C8D8651177A752D0019A804 /* libsecipc_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270F6014CF655B00B05E7F /* libsecipc_client.a */; }; - 4C96F76016D5462F00D3B39D /* KDSecCircle.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C96F73916D5372C00D3B39D /* KDSecCircle.m */; }; - 4C96F76216D54C9600D3B39D /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C96F76116D54C9600D3B39D /* CoreFoundation.framework */; }; - 4C96F7C216D6DF8400D3B39D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5214700716977CB800DF0DB3 /* Cocoa.framework */; }; - 4C96F7C816D6DF8400D3B39D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4C96F7C616D6DF8400D3B39D /* InfoPlist.strings */; }; - 4C96F7CA16D6DF8400D3B39D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C96F7C916D6DF8400D3B39D /* main.m */; }; - 4C96F7CE16D6DF8400D3B39D /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 4C96F7CC16D6DF8400D3B39D /* Credits.rtf */; }; - 4C96F7D116D6DF8400D3B39D /* KNAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C96F7D016D6DF8400D3B39D /* KNAppDelegate.m */; }; - 4C96F7D416D6DF8400D3B39D /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C96F7D216D6DF8400D3B39D /* MainMenu.xib */; }; - 4C97761E17BEB23E0002BFE4 /* AOSAccounts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C97761D17BEB23E0002BFE4 /* AOSAccounts.framework */; }; - 4CAEACCC16D6FBF600263776 /* KDSecCircle.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C96F73916D5372C00D3B39D /* KDSecCircle.m */; }; - 4CAEACCD16D6FC7600263776 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF42BB515A3947F00ACACE1 /* Security.framework */; }; - 4CB23B47169F5873003A0131 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; - 4CB23B4C169F5873003A0131 /* security2.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB23B4B169F5873003A0131 /* security2.1 */; }; - 4CB23B81169F58DE003A0131 /* security_tool_commands.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CB23B80169F58DE003A0131 /* security_tool_commands.c */; }; - 4CB23B89169F5990003A0131 /* libSecurityTool.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB23B76169F5873003A0131 /* libSecurityTool.a */; }; - 4CB23B8A169F599A003A0131 /* libSecurityCommands.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB23B78169F5873003A0131 /* libSecurityCommands.a */; }; - 4CB23B8B169F599A003A0131 /* libSOSCommands.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB23B7A169F5873003A0131 /* libSOSCommands.a */; }; - 4CB23B8C169F59AD003A0131 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894015FFECF3008CE3E3 /* libutilities.a */; }; - 4CB86AF0167A6FF300F46643 /* SOSCircle.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB86AE6167A6FF200F46643 /* SOSCircle.h */; }; - 4CB86AF1167A6FF300F46643 /* SOSCloudCircle.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB86AE7167A6FF200F46643 /* SOSCloudCircle.h */; }; - 4CB86AF2167A6FF300F46643 /* SOSCloudCircleInternal.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB86AE8167A6FF200F46643 /* SOSCloudCircleInternal.h */; }; - 4CB86AF3167A6FF300F46643 /* SOSEngine.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB86AE9167A6FF200F46643 /* SOSEngine.h */; }; - 4CB86AF4167A6FF300F46643 /* SOSFullPeerInfo.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB86AEA167A6FF300F46643 /* SOSFullPeerInfo.h */; }; - 4CB86AF5167A6FF300F46643 /* SOSInternal.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB86AEB167A6FF300F46643 /* SOSInternal.h */; }; - 4CB86AF6167A6FF300F46643 /* SOSPeer.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB86AEC167A6FF300F46643 /* SOSPeer.h */; }; - 4CB86AF7167A6FF300F46643 /* SOSPeerInfo.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB86AED167A6FF300F46643 /* SOSPeerInfo.h */; }; - 4CB86AF8167A6FF300F46643 /* SOSTransport.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB86AEE167A6FF300F46643 /* SOSTransport.h */; }; - 4CB86AFB167A8F2200F46643 /* SOSAccount.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB86AFA167A8F2200F46643 /* SOSAccount.h */; }; - 4CC7A7B416CC2A85003E10C1 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5214700716977CB800DF0DB3 /* Cocoa.framework */; }; - 4CC7A7BA16CC2A85003E10C1 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4CC7A7B816CC2A85003E10C1 /* InfoPlist.strings */; }; - 4CC7A7BC16CC2A85003E10C1 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7A7BB16CC2A85003E10C1 /* main.m */; }; - 4CC7A7C016CC2A85003E10C1 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 4CC7A7BE16CC2A85003E10C1 /* Credits.rtf */; }; - 4CC7A7C316CC2A85003E10C1 /* KDAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7A7C216CC2A85003E10C1 /* KDAppDelegate.m */; }; - 4CC7A7C616CC2A85003E10C1 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4CC7A7C416CC2A85003E10C1 /* MainMenu.xib */; }; - 4CC7A7F316CC2B0A003E10C1 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CC7A7F216CC2B0A003E10C1 /* Security.framework */; }; - 4CC7A7F616CD99E2003E10C1 /* KDSecItems.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7A7F516CD95D3003E10C1 /* KDSecItems.m */; }; - 4CC8DEA416DC1AC800462517 /* libSecOtrOSX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1288F215FFE9D7008CE3E3 /* libSecOtrOSX.a */; }; - 4CD1980D16DD3BDF00A9E8FD /* NSArray+mapWithBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CD1980C16DD3BDF00A9E8FD /* NSArray+mapWithBlock.m */; }; - 4CD1980E16DD3BDF00A9E8FD /* NSArray+mapWithBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CD1980C16DD3BDF00A9E8FD /* NSArray+mapWithBlock.m */; }; - 4CFE1CB916DD4B9C0026E900 /* CloudKeychain.icns in Resources */ = {isa = PBXBuildFile; fileRef = 4CFE1CB816DD4B9C0026E900 /* CloudKeychain.icns */; }; - 5208BF4F16A0993C0062DDC5 /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18D4053B14CE2C1600A2BE4E /* libsecurity.a */; }; - 5208C0D716A0C96F0062DDC5 /* libSecureObjectSync.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1288EA15FFE9D7008CE3E3 /* libSecureObjectSync.a */; }; - 52146FDB1697673900DF0DB3 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894015FFECF3008CE3E3 /* libutilities.a */; }; - 5214701216977CB800DF0DB3 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5214701016977CB800DF0DB3 /* InfoPlist.strings */; }; - 5214701D16977D9500DF0DB3 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894015FFECF3008CE3E3 /* libutilities.a */; }; - 5214701E16977DA700DF0DB3 /* libCloudKeychainProxy.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C01DE32164C3793006798CD /* libCloudKeychainProxy.a */; }; - 5214702216977E7D00DF0DB3 /* CloudKeychainProxy-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5214700F16977CB800DF0DB3 /* CloudKeychainProxy-Info.plist */; }; - 521470261697800500DF0DB3 /* com.apple.security.cloudkeychainproxy.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5214702516977FEC00DF0DB3 /* com.apple.security.cloudkeychainproxy.plist */; }; - 5214702A1697855800DF0DB3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5214700C16977CB800DF0DB3 /* Foundation.framework */; }; - 5241C60D16DC1BA100DB5C6F /* libSecOtrOSX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1288F215FFE9D7008CE3E3 /* libSecOtrOSX.a */; }; - 52669053169D181900ED8231 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF42BB515A3947F00ACACE1 /* Security.framework */; }; - 529E948C169E29450000AC9B /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18FE67EA1471A3AA00A2CBE3 /* Security.framework */; }; - 529E948D169E29470000AC9B /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18FE67EA1471A3AA00A2CBE3 /* Security.framework */; }; - 52AEA489153C778C005AFC59 /* tsaSupportPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 52AEA484153C7581005AFC59 /* tsaSupportPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 52B006C015238F76005D4556 /* TimeStampingPrefs.plist in Resources */ = {isa = PBXBuildFile; fileRef = 52B006BF15238F76005D4556 /* TimeStampingPrefs.plist */; }; - 52B5A9C21519330300664F11 /* tsaSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B5A9C01519330300664F11 /* tsaSupport.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 52B5A9C31519330300664F11 /* tsaTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B5A9C11519330300664F11 /* tsaTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 52C3D236169B56860091D9D3 /* ckdmain.m in Sources */ = {isa = PBXBuildFile; fileRef = 52C3D235169B56860091D9D3 /* ckdmain.m */; }; - 52CD052316A0E24900218387 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF42BB515A3947F00ACACE1 /* Security.framework */; }; - 52CD052416A0E2A000218387 /* libcorecrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8313C814F5A26500DF7FDC /* libcorecrypto.dylib */; }; - 532847791785076B009118DC /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5328475117850741009118DC /* Localizable.strings */; }; - 721680A6179B40F600406BB4 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72756C9E175D566800F52070 /* CoreFoundation.framework */; }; - 721680A9179B40F600406BB4 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 721680A8179B40F600406BB4 /* main.c */; }; - 721680AF179B4C3200406BB4 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1807384B146D0D4E00F05C24 /* Security.framework */; }; - 721680BE179B509900406BB4 /* com.apple.iCloudStats.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 721680BD179B4F9100406BB4 /* com.apple.iCloudStats.plist */; }; - 72756C31175D48C100F52070 /* cloud_keychain_diagnose.c in Sources */ = {isa = PBXBuildFile; fileRef = 72756C30175D48C100F52070 /* cloud_keychain_diagnose.c */; }; - 72CC327B175D6E0A00217455 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72756C9E175D566800F52070 /* CoreFoundation.framework */; }; - 72CC327C175D6E1800217455 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 722CF215175D5E5000BCE0A5 /* Security.framework */; }; - AAF3DCCB1666D03300376593 /* libsecurity_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F235F715CA0D9D00060520 /* libsecurity_utilities.a */; }; - BE8C5F0A16F7CE450074CF86 /* framework.sb in Resources */ = {isa = PBXBuildFile; fileRef = BE8C5F0916F7CE450074CF86 /* framework.sb */; }; - BEC3A76816F79497003E5634 /* SecTaskPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = BEC3A76716F79497003E5634 /* SecTaskPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - C288A0891505796F00E773B7 /* libOpenScriptingUtil.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = C288A0881505795D00E773B7 /* libOpenScriptingUtil.dylib */; settings = {ATTRIBUTES = (Weak, ); }; }; - CDDE9D1E1729E2E60013B0E8 /* SecPasswordGenerate.h in Headers */ = {isa = PBXBuildFile; fileRef = CDDE9D1C1729DF250013B0E8 /* SecPasswordGenerate.h */; settings = {ATTRIBUTES = (Private, ); }; }; - E778BFBC17176DDE00302C14 /* security.exp-in in Sources */ = {isa = PBXBuildFile; fileRef = 182BB562146F4C73000BF1F3 /* security.exp-in */; }; + 0C0BDB32175685B000BC1A7E /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C0BDB31175685B000BC1A7E /* main.c */; }; + 0C0BDB851756A4B900BC1A7E /* libsecdRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C0BDB821756A1D700BC1A7E /* libsecdRegressions.a */; }; + 0C0BDB861756A4C100BC1A7E /* libsecurityd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F7F66514D77DF700F88A12 /* libsecurityd.a */; }; + 0C0BDB871756A4FA00BC1A7E /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2FEC5115755D710008BE39 /* libutilities.a */; }; + 0C0BDB881756A51000BC1A7E /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB740680A4749C800D641BB /* libsqlite3.dylib */; }; + 0C0BDB891756A56A00BC1A7E /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F7F66314D77DF700F88A12 /* libsecurity.a */; }; + 0C0BDB8A1756A5D500BC1A7E /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8786AD0B03E05E00BB77D4 /* libDER.a */; }; + 0C0BDB8B1756A5D900BC1A7E /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 795CA9860D38269B00BAE6A2 /* libASN1.a */; }; + 0C0BDB8C1756A5F500BC1A7E /* libregressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E710C708133192EA00F85568 /* libregressions.a */; }; + 0C0BDB8D1756A66100BC1A7E /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF730310EF9CDE300E17471 /* CFNetwork.framework */; }; + 0C0BDB8E1756A69A00BC1A7E /* libSecureObjectSync.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60888B155C943D00A0904F /* libSecureObjectSync.a */; }; + 0C0BDB8F1756A6D500BC1A7E /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D690911652E06A0079537A /* libMobileGestalt.dylib */; }; + 0C0BDB901756A80100BC1A7E /* libsecipc_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F7F66914D77DF700F88A12 /* libsecipc_client.a */; }; + 0C0BDB911756A8A400BC1A7E /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; + 0C0BDB921756A8AA00BC1A7E /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60F1C409BE27E300B4040C /* CoreFoundation.framework */; }; + 0C0BDB931756A8C900BC1A7E /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; + 0C150099161D01D700181E9D /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8786AD0B03E05E00BB77D4 /* libDER.a */; }; + 0C15009A161D01F400181E9D /* libCMS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 79BDD39F0D60D5F9000D84D3 /* libCMS.a */; }; + 0C15009B161D020000181E9D /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 795CA9860D38269B00BAE6A2 /* libASN1.a */; }; + 0C3145571496B8FB00427C0B /* SecureTransport.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C3145551496B8FB00427C0B /* SecureTransport.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0C3145581496B8FB00427C0B /* SecureTransportPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C3145561496B8FB00427C0B /* SecureTransportPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0C59B55417677C3E00617746 /* com.apple.securityd in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0C59B54517677A9900617746 /* com.apple.securityd */; }; + 0C5D2EEB167FEAAC0077501D /* SecAsn1Coder.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C5D2EEA167FEAAC0077501D /* SecAsn1Coder.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0C5D2EED167FEEC90077501D /* secasn1t.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C5D2EEC167FEEC90077501D /* secasn1t.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0C5D2EEF167FF0560077501D /* SecAsn1Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C5D2EEE167FF0560077501D /* SecAsn1Templates.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0C5D2EF1167FF1FC0077501D /* oidsalg.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C5D2EF0167FF1FC0077501D /* oidsalg.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0C78F1CC16A5E1BF00654E08 /* sectask-10-sectask.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C78F1CA16A5E1BF00654E08 /* sectask-10-sectask.c */; }; + 0C78F1CD16A5E1BF00654E08 /* sectask-10-sectask.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C78F1CA16A5E1BF00654E08 /* sectask-10-sectask.c */; }; + 0C78F1CE16A5E1BF00654E08 /* sectask_ipc.defs in Sources */ = {isa = PBXBuildFile; fileRef = 0C78F1CB16A5E1BF00654E08 /* sectask_ipc.defs */; settings = {ATTRIBUTES = (Client, Server, ); }; }; + 0C78F1CF16A5E1BF00654E08 /* sectask_ipc.defs in Sources */ = {isa = PBXBuildFile; fileRef = 0C78F1CB16A5E1BF00654E08 /* sectask_ipc.defs */; settings = {ATTRIBUTES = (Client, Server, ); }; }; + 0C78F1D016A5E3EB00654E08 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 107227350D91FE89003CF14F /* libbsm.dylib */; }; + 0CA31A4814BB5CDB00BD348C /* CipherSuite.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CA31A4614BB5C9100BD348C /* CipherSuite.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0CA31A7514BB6C2500BD348C /* sslTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CA31A7314BB6C2500BD348C /* sslTypes.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0CC827F51387137900BD99B7 /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 798B7FD40D3D7B5400AC1D04 /* libASN1.a */; }; + 0CC82948138716F400BD99B7 /* libregressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CC82947138716F400BD99B7 /* libregressions.a */; }; + 0CCA408015C745B9002AEC4C /* libsecurity_ssl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCA406A15C73CA1002AEC4C /* libsecurity_ssl.a */; }; + 0CCA418715C89FBB002AEC4C /* libsecurity_ssl_regressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCA418415C89ECD002AEC4C /* libsecurity_ssl_regressions.a */; }; + 0CCA418815C89FC4002AEC4C /* libsecurity_ssl_regressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CCA418415C89ECD002AEC4C /* libsecurity_ssl_regressions.a */; }; + 0CD72A5D16D5769A00A4B8A3 /* utilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CD72A5B16D5769A00A4B8A3 /* utilities.c */; }; + 107226D30D91DB32003CF14F /* SecTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 107226D10D91DB32003CF14F /* SecTask.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18F7F66E14D77E9700F88A12 /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F7F66314D77DF700F88A12 /* libsecurity.a */; }; + 18F7F66F14D77EA400F88A12 /* libsecipc_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F7F66914D77DF700F88A12 /* libsecipc_client.a */; }; + 18F7F67214D77ED000F88A12 /* libsecurityd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F7F66514D77DF700F88A12 /* libsecurityd.a */; }; + 18F7F67514D77EF400F88A12 /* libsecurityd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F7F66514D77DF700F88A12 /* libsecurityd.a */; }; + 18F7F67814D77F0600F88A12 /* libsecurityd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F7F66514D77DF700F88A12 /* libsecurityd.a */; }; + 18F7F67914D77F4400F88A12 /* NtlmGenerator.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C999BA10AB5F0BB0010451D /* NtlmGenerator.c */; }; + 18F7F67A14D77F4400F88A12 /* ntlmBlobPriv.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C999BA30AB5F0BB0010451D /* ntlmBlobPriv.c */; }; + 18F7F67C14D77F5000F88A12 /* SecTask.c in Sources */ = {isa = PBXBuildFile; fileRef = 107226D00D91DB32003CF14F /* SecTask.c */; }; + 443381ED18A3D83100215606 /* SecAccessControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 443381D918A3D81400215606 /* SecAccessControl.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 443381EE18A3D83A00215606 /* SecAccessControlPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 443381DA18A3D81400215606 /* SecAccessControlPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4ACED92D15A10A320060775A /* libSecurityRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E79D9CD5159BEA78000834EC /* libSecurityRegressions.a */; }; + 4AF7000015AFB73800B9D400 /* SecOTRIdentityPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AF7FFF615AFB73800B9D400 /* SecOTRIdentityPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4AF7000115AFB73800B9D400 /* SecOTRMath.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AF7FFF715AFB73800B9D400 /* SecOTRMath.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4AF7000315AFB73800B9D400 /* SecOTRPacketData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AF7FFF915AFB73800B9D400 /* SecOTRPacketData.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4AF7000415AFB73800B9D400 /* SecOTRPackets.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AF7FFFA15AFB73800B9D400 /* SecOTRPackets.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4AF7000515AFB73800B9D400 /* SecOTRSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AF7FFFB15AFB73800B9D400 /* SecOTRSession.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4AF7000615AFB73800B9D400 /* SecOTRSessionPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AF7FFFC15AFB73800B9D400 /* SecOTRSessionPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4AF7FFFD15AFB73800B9D400 /* SecOTR.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AF7FFF315AFB73800B9D400 /* SecOTR.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4AF7FFFE15AFB73800B9D400 /* SecOTRDHKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AF7FFF415AFB73800B9D400 /* SecOTRDHKey.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4AF7FFFF15AFB73800B9D400 /* SecOTRErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AF7FFF515AFB73800B9D400 /* SecOTRErrors.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4C0B906E0ACCBD240077CD03 /* SecFramework.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0B906C0ACCBD240077CD03 /* SecFramework.h */; }; + 4C0CC642174C580200CC799A /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; + 4C12828D0BB4957D00985BB0 /* SecTrustSettingsPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C12828C0BB4957D00985BB0 /* SecTrustSettingsPriv.h */; }; + 4C198F220ACDB4BF00AAB142 /* Certificate.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4C198F1D0ACDB4BF00AAB142 /* Certificate.strings */; }; + 4C198F230ACDB4BF00AAB142 /* OID.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4C198F1F0ACDB4BF00AAB142 /* OID.strings */; }; + 4C1ADEAA1615175500E4A8AF /* libSecureObjectSync.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60888B155C943D00A0904F /* libSecureObjectSync.a */; }; + 4C1B442D0BB9CAF900461B82 /* SecTrustStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C1B442C0BB9CAF900461B82 /* SecTrustStore.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4C2215220F3A612C00835155 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB740680A4749C800D641BB /* libsqlite3.dylib */; }; + 4C2318BD0A48B5AD00792B82 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60F1C409BE27E300B4040C /* CoreFoundation.framework */; }; + 4C2F81D50BF121D2003C4F77 /* SecRandom.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C2F81D40BF121D2003C4F77 /* SecRandom.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C2FEC5215755D8C0008BE39 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2FEC5115755D710008BE39 /* libutilities.a */; }; + 4C2FEC5315755DAB0008BE39 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2FEC5115755D710008BE39 /* libutilities.a */; }; + 4C2FEC5415755DCD0008BE39 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2FEC5115755D710008BE39 /* libutilities.a */; }; + 4C2FEC5515755DE50008BE39 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2FEC5115755D710008BE39 /* libutilities.a */; }; + 4C2FEC5615755DF40008BE39 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2FEC5115755D710008BE39 /* libutilities.a */; }; + 4C2FEC5715755E040008BE39 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2FEC5115755D710008BE39 /* libutilities.a */; }; + 4C2FEC5A15755E2A0008BE39 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2FEC5115755D710008BE39 /* libutilities.a */; }; + 4C2FEC5B15755E2F0008BE39 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2FEC5115755D710008BE39 /* libutilities.a */; }; + 4C2FEC5D157571DD0008BE39 /* libSOSRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60888D155C943D00A0904F /* libSOSRegressions.a */; }; + 4C2FEC5E157571E30008BE39 /* libSOSRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60888D155C943D00A0904F /* libSOSRegressions.a */; }; + 4C2FEC66157588770008BE39 /* libSecureObjectSync.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60888B155C943D00A0904F /* libSecureObjectSync.a */; }; + 4C2FEC671575887D0008BE39 /* libSecureObjectSync.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60888B155C943D00A0904F /* libSecureObjectSync.a */; }; + 4C32C1030A4976BF002891BD /* certextensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C28BCD60986EBCB0020C665 /* certextensions.h */; }; + 4C32C1240A4976BF002891BD /* SecBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C696B3709BFA94F000CBC75 /* SecBase.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C32C1250A4976BF002891BD /* SecCertificate.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C8FD03D099D5C91006867B6 /* SecCertificate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C32C1260A4976BF002891BD /* SecTrust.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C8FD03E099D5C91006867B6 /* SecTrust.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C32C1680A4976D5002891BD /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60F1C409BE27E300B4040C /* CoreFoundation.framework */; }; + 4C32C1990A497A0C002891BD /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; + 4C32C1A60A497A21002891BD /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; + 4C3CECF31416E25C00947741 /* DigiNotar_Root_CA_G2-RootCertificate.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECF21416E20400947741 /* DigiNotar_Root_CA_G2-RootCertificate.crt */; }; + 4C3CECF41416E2EC00947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEA1416DB2200947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */; }; + 4C3CECF51416E2FA00947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEB1416DB2200947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt */; }; + 4C3CECF61416E31A00947741 /* Invalid-diginotarpkioverheidcaoverheid.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEC1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheid.crt */; }; + 4C3CECF81416E33500947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECED1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt */; }; + 4C3CECF91416E34F00947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEE1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt */; }; + 4C3CECFA1416E34F00947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEF1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt */; }; + 4C3CECFB1416E34F00947741 /* staatdernederlandenorganisatieca-g2-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECF01416DB2200947741 /* staatdernederlandenorganisatieca-g2-Cert.crt */; }; + 4C3CECFC1416E34F00947741 /* staatdernederlandenoverheidca-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECF11416DB2200947741 /* staatdernederlandenoverheidca-Cert.crt */; }; + 4C3CECFD1416E35400947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEA1416DB2200947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */; }; + 4C3CECFE1416E35400947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEB1416DB2200947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt */; }; + 4C3CECFF1416E35400947741 /* Invalid-diginotarpkioverheidcaoverheid.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEC1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheid.crt */; }; + 4C3CED001416E35400947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECED1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt */; }; + 4C3CED011416E35400947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEE1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt */; }; + 4C3CED021416E35400947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEF1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt */; }; + 4C3CED031416E35400947741 /* staatdernederlandenorganisatieca-g2-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECF01416DB2200947741 /* staatdernederlandenorganisatieca-g2-Cert.crt */; }; + 4C3CED041416E35400947741 /* staatdernederlandenoverheidca-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECF11416DB2200947741 /* staatdernederlandenoverheidca-Cert.crt */; }; + 4C3CED051416E35A00947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEA1416DB2200947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */; }; + 4C3DD6B0179755560093F9D8 /* NSDate+TimeIntervalDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C3DD6AF179755560093F9D8 /* NSDate+TimeIntervalDescription.m */; }; + 4C3DD6BD179760280093F9D8 /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D690911652E06A0079537A /* libMobileGestalt.dylib */; }; + 4C4296320BB0A68200491999 /* SecTrustSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C4296300BB0A68200491999 /* SecTrustSettings.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4C494C570F4F884800CDCBFE /* EVRoots.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4C494C560F4F884800CDCBFE /* EVRoots.plist */; }; + 4C50AD0C1410679000EE92DE /* Invalid-asterisk.google.com.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFD1410671D00EE92DE /* Invalid-asterisk.google.com.crt */; }; + 4C50AD0D1410679000EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFE1410671D00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */; }; + 4C50AD0E1410679000EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFF1410671D00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */; }; + 4C50AD0F1410679000EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD001410671D00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt */; }; + 4C50AD101410679000EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD011410671D00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */; }; + 4C50AD111410679000EE92DE /* diginotar-public-ca-2025-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD021410671D00EE92DE /* diginotar-public-ca-2025-Cert.crt */; }; + 4C50AD121410679000EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD031410671D00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt */; }; + 4C50AD131410679000EE92DE /* diginotar-services-diginotar-root-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD041410671D00EE92DE /* diginotar-services-diginotar-root-Cert.crt */; }; + 4C50AD141410679000EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD051410671D00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt */; }; + 4C50AD151410679000EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD061410671D00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */; }; + 4C50AD181410679900EE92DE /* Invalid-asterisk.google.com.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFD1410671D00EE92DE /* Invalid-asterisk.google.com.crt */; }; + 4C50AD191410679900EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFE1410671D00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */; }; + 4C50AD1A1410679900EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFF1410671D00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */; }; + 4C50AD1B1410679900EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD001410671D00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt */; }; + 4C50AD1C1410679900EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD011410671D00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */; }; + 4C50AD1D1410679900EE92DE /* diginotar-public-ca-2025-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD021410671D00EE92DE /* diginotar-public-ca-2025-Cert.crt */; }; + 4C50AD1E1410679900EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD031410671D00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt */; }; + 4C50AD1F1410679900EE92DE /* diginotar-services-diginotar-root-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD041410671D00EE92DE /* diginotar-services-diginotar-root-Cert.crt */; }; + 4C50AD201410679900EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD051410671D00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt */; }; + 4C50AD211410679900EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD061410671D00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */; }; + 4C50AD221410679900EE92DE /* diginotar.root.ca-entrust-secure-server-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD071410671D00EE92DE /* diginotar.root.ca-entrust-secure-server-Cert.crt */; }; + 4C50AD23141067A100EE92DE /* DigiNotarCA2007RootCertificate.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFC1410671D00EE92DE /* DigiNotarCA2007RootCertificate.crt */; }; + 4C50AD24141067A100EE92DE /* Invalid-asterisk.google.com.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFD1410671D00EE92DE /* Invalid-asterisk.google.com.crt */; }; + 4C50AD25141067A100EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFE1410671D00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */; }; + 4C50AD26141067A100EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFF1410671D00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */; }; + 4C50AD27141067A100EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD001410671D00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt */; }; + 4C50AD28141067A100EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD011410671D00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */; }; + 4C50AD29141067A100EE92DE /* diginotar-public-ca-2025-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD021410671D00EE92DE /* diginotar-public-ca-2025-Cert.crt */; }; + 4C50AD2A141067A100EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD031410671D00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt */; }; + 4C50AD2B141067A100EE92DE /* diginotar-services-diginotar-root-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD041410671D00EE92DE /* diginotar-services-diginotar-root-Cert.crt */; }; + 4C50AD2C141067A100EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD051410671D00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt */; }; + 4C50AD2D141067A100EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD061410671D00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */; }; + 4C50AD30141068C100EE92DE /* Expectations.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD2F1410689300EE92DE /* Expectations.plist */; }; + 4C50AD3914106A4E00EE92DE /* Invalid-asterisk.google.com.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFD1410671D00EE92DE /* Invalid-asterisk.google.com.crt */; }; + 4C50AD3A14106A4E00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFE1410671D00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */; }; + 4C50AD3B14106A4E00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFF1410671D00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */; }; + 4C50AD3C14106A4E00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD001410671D00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt */; }; + 4C50AD3D14106A4E00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD011410671D00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */; }; + 4C50AD3E14106A4E00EE92DE /* diginotar-public-ca-2025-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD021410671D00EE92DE /* diginotar-public-ca-2025-Cert.crt */; }; + 4C50AD3F14106A4E00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD031410671D00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt */; }; + 4C50AD4014106A4E00EE92DE /* diginotar-services-diginotar-root-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD041410671D00EE92DE /* diginotar-services-diginotar-root-Cert.crt */; }; + 4C50AD4114106A4E00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD051410671D00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt */; }; + 4C50AD4214106A4E00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD061410671D00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */; }; + 4C50AD4614106A5000EE92DE /* Invalid-asterisk.google.com.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFD1410671D00EE92DE /* Invalid-asterisk.google.com.crt */; }; + 4C50AD4714106A5000EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFE1410671D00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */; }; + 4C50AD4814106A5000EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFF1410671D00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */; }; + 4C50AD4914106A5000EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD001410671D00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt */; }; + 4C50AD4A14106A5000EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD011410671D00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */; }; + 4C50AD4B14106A5000EE92DE /* diginotar-public-ca-2025-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD021410671D00EE92DE /* diginotar-public-ca-2025-Cert.crt */; }; + 4C50AD4C14106A5000EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD031410671D00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt */; }; + 4C50AD4D14106A5000EE92DE /* diginotar-services-diginotar-root-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD041410671D00EE92DE /* diginotar-services-diginotar-root-Cert.crt */; }; + 4C50AD4E14106A5000EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD051410671D00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt */; }; + 4C50AD4F14106A5000EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD061410671D00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */; }; + 4C50AD5014106A5000EE92DE /* diginotar.root.ca-entrust-secure-server-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD071410671D00EE92DE /* diginotar.root.ca-entrust-secure-server-Cert.crt */; }; + 4C50AD5114106A5400EE92DE /* Expectations.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD2F1410689300EE92DE /* Expectations.plist */; }; + 4C50AD5214106A5400EE92DE /* DigiNotarCA2007RootCertificate.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFC1410671D00EE92DE /* DigiNotarCA2007RootCertificate.crt */; }; + 4C50AD5314106A5400EE92DE /* Invalid-asterisk.google.com.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFD1410671D00EE92DE /* Invalid-asterisk.google.com.crt */; }; + 4C50AD5414106A5400EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFE1410671D00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */; }; + 4C50AD5514106A5400EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50ACFF1410671D00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */; }; + 4C50AD5614106A5400EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD001410671D00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt */; }; + 4C50AD5714106A5400EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD011410671D00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */; }; + 4C50AD5814106A5400EE92DE /* diginotar-public-ca-2025-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD021410671D00EE92DE /* diginotar-public-ca-2025-Cert.crt */; }; + 4C50AD5914106A5400EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD031410671D00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt */; }; + 4C50AD5A14106A5400EE92DE /* diginotar-services-diginotar-root-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD041410671D00EE92DE /* diginotar-services-diginotar-root-Cert.crt */; }; + 4C50AD5B14106A5400EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD051410671D00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt */; }; + 4C50AD5C14106A5400EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C50AD061410671D00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */; }; + 4C52D0B516EFC61E0079966E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + 4C52D0BA16EFC61E0079966E /* CircleJoinRequested.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C52D0B916EFC61E0079966E /* CircleJoinRequested.m */; }; + 4C52D0E716EFCCA20079966E /* Applicant.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C52D0E316EFCCA20079966E /* Applicant.m */; }; + 4C52D0E816EFCCA30079966E /* NSArray+map.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C52D0E616EFCCA20079966E /* NSArray+map.m */; }; + 4C52D0E916EFCCF80079966E /* com.apple.security.CircleJoinRequested.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C52D0E416EFCCA20079966E /* com.apple.security.CircleJoinRequested.plist */; }; + 4C52D0EB16EFCD150079966E /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60F1C409BE27E300B4040C /* CoreFoundation.framework */; }; + 4C52D0EC16EFCD300079966E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D82BD316A5EADA0078DFE5 /* Security.framework */; }; + 4C6416D50BB34F00001C83FD /* SecPolicyPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6416D40BB34F00001C83FD /* SecPolicyPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4C6416F10BB357D5001C83FD /* SecInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6416F00BB357D5001C83FD /* SecInternal.h */; }; + 4C64E01C0B8FBC71009B306C /* SecIdentity.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CAC87D60B8F82720009C9FC /* SecIdentity.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C64E01D0B8FBC7E009B306C /* Security.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64E00B0B8FBBF3009B306C /* Security.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C70664C0DDDFED9004DA56B /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 107227350D91FE89003CF14F /* libbsm.dylib */; }; + 4C7072860AC9EA4F007CC205 /* SecKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7072840AC9EA4E007CC205 /* SecKey.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C7072D40AC9ED5A007CC205 /* SecKeyPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7072D30AC9ED5A007CC205 /* SecKeyPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4C7073CA0ACB2BAD007CC205 /* SecRSAKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7073C80ACB2BAD007CC205 /* SecRSAKey.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4C711D6713AFCD0900FE865D /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8786D90B03E1BC00BB77D4 /* libDER.a */; }; + 4C711D6913AFCD0900FE865D /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 798B7FD40D3D7B5400AC1D04 /* libASN1.a */; }; + 4C711D6C13AFCD0900FE865D /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB740680A4749C800D641BB /* libsqlite3.dylib */; }; + 4C711D6D13AFCD0900FE865D /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; + 4C711D6E13AFCD0900FE865D /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60F1C409BE27E300B4040C /* CoreFoundation.framework */; }; + 4C711D6F13AFCD0900FE865D /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF730310EF9CDE300E17471 /* CFNetwork.framework */; }; + 4C711D7013AFCD0900FE865D /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; + 4C711D7113AFCD0900FE865D /* libregressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CC82947138716F400BD99B7 /* libregressions.a */; }; + 4C7391790B01745000C4CBFA /* vmdh.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7391770B01745000C4CBFA /* vmdh.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4C7416040F1D71A2008E0E4D /* SecSCEP.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7416020F1D71A2008E0E4D /* SecSCEP.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4C7608B30AC34A8100980096 /* SecCertificatePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7608B10AC34A8100980096 /* SecCertificatePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4C7913251799A5CC00A9633E /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C7913241799A5CB00A9633E /* MobileCoreServices.framework */; }; + 4C7CE5700DC7DC6600AE53FC /* SecEntitlements.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7CE56E0DC7DB0A00AE53FC /* SecEntitlements.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4C84DA551720698900AEE225 /* AppleAccount.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C84DA541720698900AEE225 /* AppleAccount.framework */; }; + 4C87F3A80D611C26000E7104 /* SecTrustPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C87F3A70D611C26000E7104 /* SecTrustPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4C8A38C917B93DF10001B4C0 /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */; }; + 4C8B91C61416EB8B00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C8B91C51416EB6A00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt */; }; + 4C8B91C71416EBA400A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C8B91C51416EB6A00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt */; }; + 4C8B91C81416EBB500A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C8B91C51416EB6A00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt */; }; + 4C8B91C91416ED7E00A254E2 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEA1416DB2200947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */; }; + 4C8B91CA1416ED7E00A254E2 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEB1416DB2200947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt */; }; + 4C8B91CB1416ED7E00A254E2 /* Invalid-diginotarpkioverheidcaoverheid.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEC1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheid.crt */; }; + 4C8B91CC1416ED7E00A254E2 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECED1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt */; }; + 4C8B91CD1416ED7E00A254E2 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEE1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt */; }; + 4C8B91CE1416ED7E00A254E2 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEF1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt */; }; + 4C8B91CF1416ED7E00A254E2 /* staatdernederlandenorganisatieca-g2-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECF01416DB2200947741 /* staatdernederlandenorganisatieca-g2-Cert.crt */; }; + 4C8B91D01416ED7E00A254E2 /* staatdernederlandenoverheidca-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECF11416DB2200947741 /* staatdernederlandenoverheidca-Cert.crt */; }; + 4C8B91D11416ED7E00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C8B91C51416EB6A00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt */; }; + 4C8B91D21416ED8E00A254E2 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEA1416DB2200947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */; }; + 4C8B91D31416ED8E00A254E2 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEB1416DB2200947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt */; }; + 4C8B91D41416ED8E00A254E2 /* Invalid-diginotarpkioverheidcaoverheid.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEC1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheid.crt */; }; + 4C8B91D51416ED8E00A254E2 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECED1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt */; }; + 4C8B91D61416ED8E00A254E2 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEE1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt */; }; + 4C8B91D71416ED8E00A254E2 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEF1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt */; }; + 4C8B91D81416ED8E00A254E2 /* staatdernederlandenorganisatieca-g2-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECF01416DB2200947741 /* staatdernederlandenorganisatieca-g2-Cert.crt */; }; + 4C8B91D91416ED8E00A254E2 /* staatdernederlandenoverheidca-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECF11416DB2200947741 /* staatdernederlandenoverheidca-Cert.crt */; }; + 4C8B91DA1416ED8E00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C8B91C51416EB6A00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt */; }; + 4C8B91DB1416ED9400A254E2 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECEA1416DB2200947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */; }; + 4C8B91E31416ED9400A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C8B91C51416EB6A00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt */; }; + 4C8B91E41416ED9A00A254E2 /* DigiNotar_Root_CA_G2-RootCertificate.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C3CECF21416E20400947741 /* DigiNotar_Root_CA_G2-RootCertificate.crt */; }; + 4C999BA60AB5F0BB0010451D /* NtlmGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C999BA20AB5F0BB0010451D /* NtlmGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4C999BA80AB5F0BB0010451D /* ntlmBlobPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C999BA40AB5F0BB0010451D /* ntlmBlobPriv.h */; }; + 4C9DE9E31181AC8300CF5C27 /* sslEcdsa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9DE9E21181AC8300CF5C27 /* sslEcdsa.cpp */; }; + 4C9DEA451181B34C00CF5C27 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; + 4C9DEA6C1181B35700CF5C27 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60F1C409BE27E300B4040C /* CoreFoundation.framework */; }; + 4C9DEAA71181B37500CF5C27 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF730310EF9CDE300E17471 /* CFNetwork.framework */; }; + 4C9DEAAD1181B39300CF5C27 /* ioSock.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CE5A65809C79E0600D27A3F /* ioSock.c */; }; + 4C9DEAB11181B39800CF5C27 /* sslAppUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE5A65A09C79E0600D27A3F /* sslAppUtils.cpp */; }; + 4CAE95AA0F3D6DF20075278E /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF730310EF9CDE300E17471 /* CFNetwork.framework */; }; + 4CAE95D80F3D6DFC0075278E /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF730310EF9CDE300E17471 /* CFNetwork.framework */; }; + 4CAE95DC0F3D6E020075278E /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF730310EF9CDE300E17471 /* CFNetwork.framework */; }; + 4CAF66190F3A6FCD0064A534 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; + 4CAF67AC0F3A70220064A534 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; + 4CBA0E880BB33C0000E72B55 /* SecPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CBA0E860BB33C0000E72B55 /* SecPolicy.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4CC3D29D178F698D0070FCC4 /* PersistantState.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC3D290178F310C0070FCC4 /* PersistantState.m */; }; + 4CC92B1C15A3BF2F00C6D578 /* testmain.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92B1B15A3BF2F00C6D578 /* testmain.c */; }; + 4CC92B1D15A3BF2F00C6D578 /* testmain.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92B1B15A3BF2F00C6D578 /* testmain.c */; }; + 4CC92B2615A3C6FE00C6D578 /* libSecurityRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E79D9CD5159BEA78000834EC /* libSecurityRegressions.a */; }; + 4CC92B2715A3C73E00C6D578 /* libsecuritydRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CC92B1A15A3BF1E00C6D578 /* libsecuritydRegressions.a */; }; + 4CC92B3115A3C99600C6D578 /* libsecuritydRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CC92B1A15A3BF1E00C6D578 /* libsecuritydRegressions.a */; }; + 4CCE0ADA0D41797400DDBB21 /* SecIdentityPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCE0AD90D41797400DDBB21 /* SecIdentityPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4CCE0ADE0D4179E500DDBB21 /* SecBasePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0208F80D3C154200BFE54E /* SecBasePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4CD3BA621106FF4D00BE8B75 /* SecECKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CD3BA601106FF4D00BE8B75 /* SecECKey.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4CE39035169F87BB00026468 /* libSecurityTool.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E7104A06169E038F00DB0045 /* libSecurityTool.a */; }; + 4CE39045169F87E500026468 /* libSecurityTool.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E7104A06169E038F00DB0045 /* libSecurityTool.a */; }; + 4CE5A55B09C7970A00D27A3F /* SSLViewer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE5A55709C7970A00D27A3F /* SSLViewer.cpp */; }; + 4CE5A60E09C79DF200D27A3F /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60F1C409BE27E300B4040C /* CoreFoundation.framework */; }; + 4CE5A66009C79E0600D27A3F /* ioSock.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CE5A65809C79E0600D27A3F /* ioSock.c */; }; + 4CE5A66109C79E0600D27A3F /* sslAppUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE5A65A09C79E0600D27A3F /* sslAppUtils.cpp */; }; + 4CEF4CA80C5551FE00062475 /* SecCertificateInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CEF4CA70C5551FE00062475 /* SecCertificateInternal.h */; }; + 4CF0484C0A5D988F00268236 /* SecItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF0484A0A5D988F00268236 /* SecItem.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4CF048800A5F016300268236 /* SecItemPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF0487F0A5F016300268236 /* SecItemPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4CF41D0C0BBB4022005F3248 /* SecCertificatePath.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF41D0A0BBB4022005F3248 /* SecCertificatePath.h */; }; + 4CF4C19D171E0EA600877419 /* Accounts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF4C19C171E0EA600877419 /* Accounts.framework */; }; + 4CF730320EF9CDE300E17471 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF730310EF9CDE300E17471 /* CFNetwork.framework */; }; + 4CFBF6100D5A951100969BBE /* SecPolicyInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CFBF5F10D5A92E100969BBE /* SecPolicyInternal.h */; }; + 5208F4BD1670027400A49DDA /* SyncViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5208F4BC1670027400A49DDA /* SyncViewController.m */; }; + 5208F4BE1670027400A49DDA /* SyncViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5208F4BC1670027400A49DDA /* SyncViewController.m */; }; + 5208F4CF16702D8800A49DDA /* CircleStatusView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5208F4CE16702D8800A49DDA /* CircleStatusView.m */; }; + 5208F4D016702D8800A49DDA /* CircleStatusView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5208F4CE16702D8800A49DDA /* CircleStatusView.m */; }; + 52222CC1167BDAE100EDD09C /* SpringBoardServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52222CC0167BDAE100EDD09C /* SpringBoardServices.framework */; }; + 52222CD0167BDAEC00EDD09C /* SpringBoardServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52222CC0167BDAE100EDD09C /* SpringBoardServices.framework */; }; + 5223A7E316560CE400804179 /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D690911652E06A0079537A /* libMobileGestalt.dylib */; }; + 5223A7E416560CFB00804179 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60F1C409BE27E300B4040C /* CoreFoundation.framework */; }; + 5233635818CA9B2600333A5C /* libsecurityd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F7F66514D77DF700F88A12 /* libsecurityd.a */; }; + 5233636318CA9B3C00333A5C /* libSecureObjectSync.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60888B155C943D00A0904F /* libSecureObjectSync.a */; }; + 5233636418CA9B8900333A5C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; + 5262A64216AA01910038AFC1 /* Keychain_57x57.png in Resources */ = {isa = PBXBuildFile; fileRef = 527435A916A9E6D1001A96FF /* Keychain_57x57.png */; }; + 5264FB4E163674B50005D258 /* MyKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 5264FB4D163674B50005D258 /* MyKeychain.m */; }; + 5264FB4F163674C00005D258 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 520C98E7162485CA00A7C80B /* QuartzCore.framework */; }; + 5264FB50163674CF0005D258 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52B35B051623753000B97D06 /* Security.framework */; }; + 5264FB52163675310005D258 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2FEC5115755D710008BE39 /* libutilities.a */; }; + 52704B7E1638F4EB007FEBB0 /* KeychainKeys.png in Resources */ = {isa = PBXBuildFile; fileRef = 52704B7D1638F4EB007FEBB0 /* KeychainKeys.png */; }; + 52704B811638F610007FEBB0 /* NewPasswordViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52704B801638F610007FEBB0 /* NewPasswordViewController.m */; }; + 52704B84163905EE007FEBB0 /* EditItemViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52704B83163905EE007FEBB0 /* EditItemViewController.m */; }; + 52704B881639193F007FEBB0 /* Keychain-Entitlements.plist in Resources */ = {isa = PBXBuildFile; fileRef = 52704B871639193F007FEBB0 /* Keychain-Entitlements.plist */; }; + 527435AC16A9E6DB001A96FF /* Keychain_114x114.png in Resources */ = {isa = PBXBuildFile; fileRef = 527435AB16A9E6DB001A96FF /* Keychain_114x114.png */; }; + 527435AE16A9E6E5001A96FF /* Keychain_72x72.png in Resources */ = {isa = PBXBuildFile; fileRef = 527435AD16A9E6E5001A96FF /* Keychain_72x72.png */; }; + 527435B016A9E6EA001A96FF /* Keychain_144x144.png in Resources */ = {isa = PBXBuildFile; fileRef = 527435AF16A9E6E9001A96FF /* Keychain_144x144.png */; }; + 5296CB4E1655B8F5009912AF /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D690911652E06A0079537A /* libMobileGestalt.dylib */; }; + 5296CB4F1655B92F009912AF /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D690911652E06A0079537A /* libMobileGestalt.dylib */; }; + 5296CB501655B990009912AF /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D690911652E06A0079537A /* libMobileGestalt.dylib */; }; + 5296CB511655B9A3009912AF /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D690911652E06A0079537A /* libMobileGestalt.dylib */; }; + 5296CB521655B9B5009912AF /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D690911652E06A0079537A /* libMobileGestalt.dylib */; }; + 5296CBAA1656A7AC009912AF /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB740680A4749C800D641BB /* libsqlite3.dylib */; }; + 5296CBAB1656A7E2009912AF /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; + 5296CBAC1656A7E9009912AF /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF730310EF9CDE300E17471 /* CFNetwork.framework */; }; + 529990541661BA2600C297A2 /* DeviceTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 529990531661BA2600C297A2 /* DeviceTableViewController.m */; }; + 529990571661BADF00C297A2 /* DeviceItemCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 529990561661BADF00C297A2 /* DeviceItemCell.m */; }; + 52A23EDC161DEC3800E271E0 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 52A23EDB161DEC3700E271E0 /* Default-568h@2x.png */; }; + 52A23EDD161DEC3F00E271E0 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 52A23EDB161DEC3700E271E0 /* Default-568h@2x.png */; }; + 52CD69FB16384C2000961848 /* KCAItemDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52CD69FA16384C2000961848 /* KCAItemDetailViewController.m */; }; + 52D82BDF16A621F70078DFE5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + 52D82BE516A621F70078DFE5 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 52D82BE316A621F70078DFE5 /* InfoPlist.strings */; }; + 52D82BEE16A622370078DFE5 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D82BD316A5EADA0078DFE5 /* Security.framework */; }; + 52D82BEF16A622470078DFE5 /* libCloudKeychainProxy.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 52849FAE164462E7005CDF23 /* libCloudKeychainProxy.a */; }; + 52D82BF016A622570078DFE5 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2FEC5115755D710008BE39 /* libutilities.a */; }; + 52D82BF416A622E60078DFE5 /* com.apple.security.cloudkeychainproxy.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 52222D2C16A5CBCC00EDD09C /* com.apple.security.cloudkeychainproxy.plist */; }; + 52D82BF816A6283F0078DFE5 /* ckdmain.m in Sources */ = {isa = PBXBuildFile; fileRef = 52D82BF716A6283F0078DFE5 /* ckdmain.m */; }; + 52DE816B1636347500F49F0C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE411314471B000DE34E /* UIKit.framework */; }; + 52DE816C1636347500F49F0C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + 52DE816D1636347500F49F0C /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE451314471B000DE34E /* CoreGraphics.framework */; }; + 52DE81751636347500F49F0C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 52DE81741636347500F49F0C /* main.m */; }; + 52DE81791636347600F49F0C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 52DE81781636347600F49F0C /* AppDelegate.m */; }; + 52DE817B1636347600F49F0C /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 52DE817A1636347600F49F0C /* Default.png */; }; + 52DE817D1636347600F49F0C /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 52DE817C1636347600F49F0C /* Default@2x.png */; }; + 52DE817F1636347600F49F0C /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 52DE817E1636347600F49F0C /* Default-568h@2x.png */; }; + 52DE81881636347600F49F0C /* FirstViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52DE81871636347600F49F0C /* FirstViewController.m */; }; + 52DE818A1636347600F49F0C /* first.png in Resources */ = {isa = PBXBuildFile; fileRef = 52DE81891636347600F49F0C /* first.png */; }; + 52DE818C1636347600F49F0C /* first@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 52DE818B1636347600F49F0C /* first@2x.png */; }; + 52DE818F1636347600F49F0C /* ToolsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52DE818E1636347600F49F0C /* ToolsViewController.m */; }; + 52DE81911636347600F49F0C /* second.png in Resources */ = {isa = PBXBuildFile; fileRef = 52DE81901636347600F49F0C /* second.png */; }; + 52DE81931636347600F49F0C /* second@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 52DE81921636347600F49F0C /* second@2x.png */; }; + 52DE819C163636B900F49F0C /* KCATableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52DE819B163636B900F49F0C /* KCATableViewController.m */; }; + 52DE819F16363C1A00F49F0C /* KeychainItemCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 52DE819E16363C1A00F49F0C /* KeychainItemCell.m */; }; + 52F63A201659F04E0076D2DE /* DeviceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52F63A1F1659F04E0076D2DE /* DeviceViewController.m */; }; + 5328C0521738903F00708984 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; + 533B5D4F177CD63100995334 /* SpringBoardServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52222CC0167BDAE100EDD09C /* SpringBoardServices.framework */; }; + 5346480217331E1200FE9172 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + 5346480817331E1200FE9172 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5346480617331E1200FE9172 /* InfoPlist.strings */; }; + 5346481E173322BD00FE9172 /* KeychainSyncAccountNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = 5346481D173322BD00FE9172 /* KeychainSyncAccountNotification.m */; }; + 5346481F17332F9C00FE9172 /* Accounts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF4C19C171E0EA600877419 /* Accounts.framework */; }; + 53C0E1FF177FB48A00F8A018 /* CloudKeychain.strings in Resources */ = {isa = PBXBuildFile; fileRef = 53C0E1F1177FAC2C00F8A018 /* CloudKeychain.strings */; }; + 5D83979D160259EE0075998F /* Invalid.com.apple.testcard.crt in Resources */ = {isa = PBXBuildFile; fileRef = 5D83979C160259EE0075998F /* Invalid.com.apple.testcard.crt */; }; + 5D83979E16025A720075998F /* Invalid.com.apple.testcard.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5D83979C160259EE0075998F /* Invalid.com.apple.testcard.crt */; }; + 5DDD0BEC16D6747700D6C0D6 /* com.apple.OTAPKIAssetTool.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5DDD0BDD16D6740E00D6C0D6 /* com.apple.OTAPKIAssetTool.plist */; }; + 7200D76F177B9999009BB396 /* ManagedConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72C3EC2D1705F24E0040C87C /* ManagedConfiguration.framework */; }; + 721146D7177A80CF005B5871 /* AppleESCertificates.plist in Resources */ = {isa = PBXBuildFile; fileRef = 721146CA177A80C3005B5871 /* AppleESCertificates.plist */; }; + 7245AD2A16E80211009096D8 /* AssetVersion.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7245AD1D16E801BB009096D8 /* AssetVersion.plist */; }; + 728B56A216D59979008FA3AB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + 72979BE3175D095900BE8FD6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + 72979BF0175D0B2D00BE8FD6 /* cloud_keychain_diagnose.c in Sources */ = {isa = PBXBuildFile; fileRef = 72979BEF175D0B2D00BE8FD6 /* cloud_keychain_diagnose.c */; }; + 72979BF1175D0B5900BE8FD6 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; + 72979BF2175D0D4F00BE8FD6 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; + 72C3EC2E1705F24E0040C87C /* ManagedConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72C3EC2D1705F24E0040C87C /* ManagedConfiguration.framework */; }; + 72CD2BBE16D59AE30064EEE1 /* OTAServiceApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 72CD2BBB16D59AE30064EEE1 /* OTAServiceApp.m */; }; + 72CD2BBF16D59AE30064EEE1 /* OTAServicemain.m in Sources */ = {isa = PBXBuildFile; fileRef = 72CD2BBD16D59AE30064EEE1 /* OTAServicemain.m */; }; + 72CD2BCD16D59AF30064EEE1 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; + 72CD2BCE16D59B010064EEE1 /* MobileAsset.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7273402816CAFB3C0096622A /* MobileAsset.framework */; }; + 72DCB35016C4371E009213D4 /* Blocked.plist in Resources */ = {isa = PBXBuildFile; fileRef = 72E2DBF316BC476E00E7B236 /* Blocked.plist */; }; + 72DCB35116C4371E009213D4 /* certsIndex.data in Resources */ = {isa = PBXBuildFile; fileRef = 72E2DBF416BC476E00E7B236 /* certsIndex.data */; }; + 72DCB35216C4371E009213D4 /* certsTable.data in Resources */ = {isa = PBXBuildFile; fileRef = 72E2DBF516BC476E00E7B236 /* certsTable.data */; }; + 72DF9EFE178360230054641E /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D690911652E06A0079537A /* libMobileGestalt.dylib */; }; + 72F06A9B16D431AA003C8D56 /* GrayListedKeys.plist in Resources */ = {isa = PBXBuildFile; fileRef = 72F06A8D16D4315B003C8D56 /* GrayListedKeys.plist */; }; + 78F92F11195128D70023B54B /* SecECKeyPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 78F92F10195128D70023B54B /* SecECKeyPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 7901791812D51F7200CA4D44 /* SecCmsBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 7901790E12D51F7200CA4D44 /* SecCmsBase.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 7901791912D51F7200CA4D44 /* SecCmsContentInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 7901790F12D51F7200CA4D44 /* SecCmsContentInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 7901791A12D51F7200CA4D44 /* SecCmsDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 7901791012D51F7200CA4D44 /* SecCmsDecoder.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 7901791B12D51F7200CA4D44 /* SecCmsDigestContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 7901791112D51F7200CA4D44 /* SecCmsDigestContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 7901791C12D51F7200CA4D44 /* SecCmsEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 7901791212D51F7200CA4D44 /* SecCmsEncoder.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 7901791D12D51F7200CA4D44 /* SecCmsEnvelopedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 7901791312D51F7200CA4D44 /* SecCmsEnvelopedData.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 7901791E12D51F7200CA4D44 /* SecCmsMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = 7901791412D51F7200CA4D44 /* SecCmsMessage.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 7901791F12D51F7200CA4D44 /* SecCmsRecipientInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 7901791512D51F7200CA4D44 /* SecCmsRecipientInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 7901792012D51F7200CA4D44 /* SecCmsSignedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 7901791612D51F7200CA4D44 /* SecCmsSignedData.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 7901792112D51F7200CA4D44 /* SecCmsSignerInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 7901791712D51F7200CA4D44 /* SecCmsSignerInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 7901792912D51FFC00CA4D44 /* SecAsn1Types.h in Headers */ = {isa = PBXBuildFile; fileRef = 7901792812D51FFC00CA4D44 /* SecAsn1Types.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 790850F70CA88AE10083CC4D /* securityd_client.h in Headers */ = {isa = PBXBuildFile; fileRef = 790850820CA87CF00083CC4D /* securityd_client.h */; }; + 790850F80CA88AE10083CC4D /* securityd_ipc_types.h in Headers */ = {isa = PBXBuildFile; fileRef = 790850830CA87CF00083CC4D /* securityd_ipc_types.h */; }; + 790851D40CA9B19D0083CC4D /* server.c in Sources */ = {isa = PBXBuildFile; fileRef = 790850840CA87CF00083CC4D /* server.c */; }; + 790851EE0CA9B3410083CC4D /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; + 790851EF0CA9B3410083CC4D /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60F1C409BE27E300B4040C /* CoreFoundation.framework */; }; + 7913B2020D172B3900601FE9 /* ioSock.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CE5A65809C79E0600D27A3F /* ioSock.c */; }; + 7913B2030D172B3900601FE9 /* sslAppUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE5A65A09C79E0600D27A3F /* sslAppUtils.cpp */; }; + 7913B2050D172B3900601FE9 /* sslServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7913B1DF0D17280500601FE9 /* sslServer.cpp */; }; + 7913B2080D172B3900601FE9 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; + 7913B2090D172B3900601FE9 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60F1C409BE27E300B4040C /* CoreFoundation.framework */; }; + 791766DE0DD0162C00F3B974 /* SecCertificateRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 791766DD0DD0162C00F3B974 /* SecCertificateRequest.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 7930B058134A2D97007062F8 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB740680A4749C800D641BB /* libsqlite3.dylib */; }; + 7930B06A134A4864007062F8 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; + 7940D4130C3ACF9000FDB5D8 /* SecDH.h in Headers */ = {isa = PBXBuildFile; fileRef = 7940D4110C3ACF9000FDB5D8 /* SecDH.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 7947431A146213DC00D638A3 /* Invalid-www.cybersecurity.my.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 794743191462137C00D638A3 /* Invalid-www.cybersecurity.my.crt */; }; + 7947431B146213EF00D638A3 /* Invalid-www.cybersecurity.my.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 794743191462137C00D638A3 /* Invalid-www.cybersecurity.my.crt */; }; + 7947431D1462151400D638A3 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7947431C146214E500D638A3 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt */; }; + 7947431E1462151E00D638A3 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7947431C146214E500D638A3 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt */; }; + 795CA9CE0D38435E00BAE6A2 /* p12pbegen.h in Headers */ = {isa = PBXBuildFile; fileRef = 795CA9CC0D38435E00BAE6A2 /* p12pbegen.h */; }; + 79679E29146202A800CF997F /* Digisign-Server-ID-Enrich-Entrust-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 79679E251462028800CF997F /* Digisign-Server-ID-Enrich-Entrust-Cert.crt */; }; + 79679E2A146202A800CF997F /* Invalid-webmail.jaring.my.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 79679E261462028800CF997F /* Invalid-webmail.jaring.my.crt */; }; + 79679E2C146202CB00CF997F /* Digisign-Server-ID-Enrich-Entrust-Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 79679E251462028800CF997F /* Digisign-Server-ID-Enrich-Entrust-Cert.crt */; }; + 79679E2D146202CB00CF997F /* Invalid-webmail.jaring.my.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 79679E261462028800CF997F /* Invalid-webmail.jaring.my.crt */; }; + 79863B710CADCEAB00818B0D /* com.apple.securityd.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 79863B700CADCEAB00818B0D /* com.apple.securityd.plist */; }; + 79863B960CADD21700818B0D /* securityd_server.h in Headers */ = {isa = PBXBuildFile; fileRef = 79863B940CADD21700818B0D /* securityd_server.h */; }; + 79BDD3C20D60DB84000D84D3 /* SecCMS.h in Headers */ = {isa = PBXBuildFile; fileRef = 79BDD3C00D60DB84000D84D3 /* SecCMS.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 79C0C675134A6E2D00A51BCB /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; + 79C0C6BC134A96C100A51BCB /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF730310EF9CDE300E17471 /* CFNetwork.framework */; }; + 79DCEA61134A280F007F57DC /* codesign_wrapper.c in Sources */ = {isa = PBXBuildFile; fileRef = 79DCEA5E134A280F007F57DC /* codesign_wrapper.c */; }; + 79DCEA62134A280F007F57DC /* codesign.c in Sources */ = {isa = PBXBuildFile; fileRef = 79DCEA5F134A280F007F57DC /* codesign.c */; }; + 79DCEA63134A280F007F57DC /* MISEntitlement.c in Sources */ = {isa = PBXBuildFile; fileRef = 79DCEA60134A280F007F57DC /* MISEntitlement.c */; }; + 79DCEA87134A2A1B007F57DC /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8786AD0B03E05E00BB77D4 /* libDER.a */; }; + 79DCEA8B134A2A1B007F57DC /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60F1C409BE27E300B4040C /* CoreFoundation.framework */; }; + 79E0D705143E55DB0010CE0E /* Apple Application Integration Certification Authority Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 79E0D702143E558B0010CE0E /* Apple Application Integration Certification Authority Cert.crt */; }; + 79E0D706143E55DB0010CE0E /* Apple Production ShareServices-7130767241416543643077536561487847634e4d6f773d3d.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 79E0D703143E558B0010CE0E /* Apple Production ShareServices-7130767241416543643077536561487847634e4d6f773d3d.crt */; }; + 79E0D707143E55DB0010CE0E /* AppleRootCertificate.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 79E0D704143E558B0010CE0E /* AppleRootCertificate.crt */; }; + 79E0D709143E56010010CE0E /* Apple Application Integration Certification Authority Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 79E0D702143E558B0010CE0E /* Apple Application Integration Certification Authority Cert.crt */; }; + 79E0D70A143E56010010CE0E /* Apple Production ShareServices-7130767241416543643077536561487847634e4d6f773d3d.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 79E0D703143E558B0010CE0E /* Apple Production ShareServices-7130767241416543643077536561487847634e4d6f773d3d.crt */; }; + 79E0D70B143E56010010CE0E /* AppleRootCertificate.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 79E0D704143E558B0010CE0E /* AppleRootCertificate.crt */; }; + 79E0D7A8143E672A0010CE0E /* Invalid-asset_signing.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 79E0D7A6143E671C0010CE0E /* Invalid-asset_signing.crt */; }; + 79E0D7A9143E673B0010CE0E /* Invalid-asset_signing.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 79E0D7A6143E671C0010CE0E /* Invalid-asset_signing.crt */; }; + 79E0D7AC143E68CF0010CE0E /* iPhoneCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 79E0D7AA143E68BF0010CE0E /* iPhoneCACert.crt */; }; + 79E0D7AD143E68D70010CE0E /* iPhoneCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 79E0D7AA143E68BF0010CE0E /* iPhoneCACert.crt */; }; + 79EF5B6E0D3D6A31009F5270 /* SecImportExport.h in Headers */ = {isa = PBXBuildFile; fileRef = 79EF5B6C0D3D6A31009F5270 /* SecImportExport.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 79EF5B730D3D6AFE009F5270 /* p12import.h in Headers */ = {isa = PBXBuildFile; fileRef = 79EF5B720D3D6AFE009F5270 /* p12import.h */; }; + 8E02FA6B1107BE460043545E /* pbkdf2.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E02FA691107BE460043545E /* pbkdf2.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 8ED6F6CA110904E300D2B368 /* SecPBKDF.h in Headers */ = {isa = PBXBuildFile; fileRef = 8ED6F6C8110904E300D2B368 /* SecPBKDF.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B9499C24139DC391004F4EDE /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8786D90B03E1BC00BB77D4 /* libDER.a */; }; + BE061FE11899ECEE00C739F6 /* SecSharedCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = BE061FE01899ECEE00C739F6 /* SecSharedCredential.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BE197F2C19116FD100BA91D1 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BE197F2A19116FD100BA91D1 /* InfoPlist.strings */; }; + BE197F2E19116FD100BA91D1 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = BE197F2D19116FD100BA91D1 /* main.m */; }; + BE197F3219116FD100BA91D1 /* SWCAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = BE197F3119116FD100BA91D1 /* SWCAppDelegate.m */; }; + BE197F5B1911723E00BA91D1 /* SpringBoardUIServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE197F5A1911723E00BA91D1 /* SpringBoardUIServices.framework */; }; + BE197F5C1911724900BA91D1 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE411314471B000DE34E /* UIKit.framework */; }; + BE197F5E191173A800BA91D1 /* SWCViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BE197F5D191173A800BA91D1 /* SWCViewController.m */; }; + BE197F61191173F200BA91D1 /* entitlements.plist in Resources */ = {isa = PBXBuildFile; fileRef = BE197F60191173F200BA91D1 /* entitlements.plist */; }; + BE25C41618B83491003320E0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + BE2D511D1917739F0093C265 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2FEC5115755D710008BE39 /* libutilities.a */; }; + BE442BAE18B7FDB800F24DAE /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D690911652E06A0079537A /* libMobileGestalt.dylib */; }; + BE442BB218B7FDB800F24DAE /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2FEC5115755D710008BE39 /* libutilities.a */; }; + BE442BB318B7FDB800F24DAE /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C32C0AF0A4975F6002891BD /* Security.framework */; }; + BE442BB418B7FDB800F24DAE /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; + BE442BB518B7FDB800F24DAE /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60F1C409BE27E300B4040C /* CoreFoundation.framework */; }; + BE442BB618B7FDB800F24DAE /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF730310EF9CDE300E17471 /* CFNetwork.framework */; }; + BE442BB718B7FDB800F24DAE /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; + BE442BB818B7FDB800F24DAE /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB740680A4749C800D641BB /* libsqlite3.dylib */; }; + BE442BB918B7FDB800F24DAE /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 107227350D91FE89003CF14F /* libbsm.dylib */; }; + BE4AC9A218B7FFAD00B84964 /* swcagent.m in Sources */ = {isa = PBXBuildFile; fileRef = BE4AC9A118B7FFAD00B84964 /* swcagent.m */; }; + BE4AC9AE18B7FFC800B84964 /* com.apple.security.swcagent.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = BE4AC9AD18B7FFC800B84964 /* com.apple.security.swcagent.plist */; }; + BE4AC9B718B80CFF00B84964 /* libSWCAgent.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BE442B9B18B7FD6700F24DAE /* libSWCAgent.a */; }; + BE4AC9BA18B8273600B84964 /* SharedWebCredentials.strings in Resources */ = {isa = PBXBuildFile; fileRef = BE4AC9B818B8273600B84964 /* SharedWebCredentials.strings */; }; + BE5EC1E318C7F66D005E7682 /* libSWCAgent.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BE442B9B18B7FD6700F24DAE /* libSWCAgent.a */; }; + BE759DCB1917E38D00801E02 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE451314471B000DE34E /* CoreGraphics.framework */; }; + BE95AAFD18B846A8004495EB /* WebUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE95AAFC18B846A8004495EB /* WebUI.framework */; settings = {ATTRIBUTES = (Required, ); }; }; + BEF8AFF719176B0C00F80109 /* libsecurityd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F7F66514D77DF700F88A12 /* libsecurityd.a */; }; + BEF8AFF819176B1400F80109 /* libSWCAgent.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BE442B9B18B7FD6700F24DAE /* libSWCAgent.a */; }; + CDB9FCAB179CD098000AAD66 /* Info.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = CDB9FCA9179CC757000AAD66 /* Info.plist */; }; + CDDE9BD11729ABFA0013B0E8 /* SecPasswordGenerate.h in Headers */ = {isa = PBXBuildFile; fileRef = CDDE9BC31729AB910013B0E8 /* SecPasswordGenerate.h */; settings = {ATTRIBUTES = (Private, ); }; }; + E7104A07169E03CE00DB0045 /* libSecurityTool.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E7104A06169E038F00DB0045 /* libSecurityTool.a */; }; + E7104A0C169E171900DB0045 /* security_tool_commands.c in Sources */ = {isa = PBXBuildFile; fileRef = E7104A0B169E171900DB0045 /* security_tool_commands.c */; }; + E7104A24169E222F00DB0045 /* libSecurityCommands.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E7104A23169E21C000DB0045 /* libSecurityCommands.a */; }; + E71F3E3116EA69A900FAF9B4 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; + E71F3E3E16EA69CF00FAF9B4 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; + E71F3E3F16EA69E500FAF9B4 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; + E71F3E4016EA6A1800FAF9B4 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; + E71F3E4116EA6A5100FAF9B4 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; + E71F3E4216EA6A6300FAF9B4 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; }; + E72783FB159BDFE900028D6C /* Apple TEST RootCertificate.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E72783F6159BDFBB00028D6C /* Apple TEST RootCertificate.crt */; }; + E72783FC159BDFE900028D6C /* Apple Worldwide Developer Relations Certification Authority Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E72783F7159BDFBC00028D6C /* Apple Worldwide Developer Relations Certification Authority Cert.crt */; }; + E72783FD159BDFE900028D6C /* Apple Worldwide Developer Relations Certification Authority TEST Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E72783F8159BDFBC00028D6C /* Apple Worldwide Developer Relations Certification Authority TEST Cert.crt */; }; + E72783FE159BDFE900028D6C /* AppleRootCertificate.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E72783F9159BDFBC00028D6C /* AppleRootCertificate.crt */; }; + E7278401159BE01A00028D6C /* Apple TEST RootCertificate.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E72783F6159BDFBB00028D6C /* Apple TEST RootCertificate.crt */; }; + E7278402159BE02300028D6C /* Apple Worldwide Developer Relations Certification Authority Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E72783F7159BDFBC00028D6C /* Apple Worldwide Developer Relations Certification Authority Cert.crt */; }; + E7278403159BE03300028D6C /* AppleRootCertificate.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E72783F9159BDFBC00028D6C /* AppleRootCertificate.crt */; }; + E7278404159BE03600028D6C /* Apple Worldwide Developer Relations Certification Authority TEST Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E72783F8159BDFBC00028D6C /* Apple Worldwide Developer Relations Certification Authority TEST Cert.crt */; }; + E72D462B175FBF3E00F70B9B /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; + E73000EA13D90A5A00B0DA1B /* Invalid-asset_signing.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E73000DD13D90A1F00B0DA1B /* Invalid-asset_signing.crt */; }; + E73000EC13D90A5A00B0DA1B /* task_signing.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E73000DF13D90A1F00B0DA1B /* task_signing.crt */; }; + E73000EF13D90A7E00B0DA1B /* Invalid-asset_signing.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E73000DD13D90A1F00B0DA1B /* Invalid-asset_signing.crt */; }; + E73000F113D90A7E00B0DA1B /* task_signing.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E73000DF13D90A1F00B0DA1B /* task_signing.crt */; }; + E730010213D90CF200B0DA1B /* AppleRootCertificate.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E73000F513D90CD900B0DA1B /* AppleRootCertificate.crt */; }; + E730010313D90CF200B0DA1B /* asset_signing.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E73000F613D90CD900B0DA1B /* asset_signing.crt */; }; + E730010413D90CF200B0DA1B /* Invalid-task_signing.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E73000F713D90CD900B0DA1B /* Invalid-task_signing.crt */; }; + E730010513D90CF200B0DA1B /* iPhoneCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E73000F813D90CD900B0DA1B /* iPhoneCACert.crt */; }; + E730010713D90D0700B0DA1B /* AppleRootCertificate.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E73000F513D90CD900B0DA1B /* AppleRootCertificate.crt */; }; + E730010813D90D0700B0DA1B /* asset_signing.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E73000F613D90CD900B0DA1B /* asset_signing.crt */; }; + E730010913D90D0700B0DA1B /* Invalid-task_signing.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E73000F713D90CD900B0DA1B /* Invalid-task_signing.crt */; }; + E730010A13D90D0700B0DA1B /* iPhoneCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E73000F813D90CD900B0DA1B /* iPhoneCACert.crt */; }; + E730010B13D90DB900B0DA1B /* AppleRootCertificate.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E73000F513D90CD900B0DA1B /* AppleRootCertificate.crt */; }; + E730010C13D90DB900B0DA1B /* iPhoneCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E73000F813D90CD900B0DA1B /* iPhoneCACert.crt */; }; + E730010D13D90DBF00B0DA1B /* AppleRootCertificate.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E73000F513D90CD900B0DA1B /* AppleRootCertificate.crt */; }; + E730010E13D90DBF00B0DA1B /* iPhoneCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = E73000F813D90CD900B0DA1B /* iPhoneCACert.crt */; }; + E7450BB016D42B30009C07B8 /* SOSCloudCircle.h in Headers */ = {isa = PBXBuildFile; fileRef = E7450BAC16D42B17009C07B8 /* SOSCloudCircle.h */; settings = {ATTRIBUTES = (Private, ); }; }; + E7450BB116D42B39009C07B8 /* SOSPeerInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = E7450BAD16D42B17009C07B8 /* SOSPeerInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; + E75112EB166EFBF0008C578B /* PeerListCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E75112EA166EFBF0008C578B /* PeerListCell.m */; }; + E75112FA166F020E008C578B /* PeerListCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E75112EA166EFBF0008C578B /* PeerListCell.m */; }; + E76079DC1951FDBF00F69731 /* liblogging.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E76079DB1951FDBF00F69731 /* liblogging.a */; }; + E7676DB619411DF300498DD4 /* SecServerEncryptionSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = E7676DB519411DF300498DD4 /* SecServerEncryptionSupport.h */; settings = {ATTRIBUTES = (Private, ); }; }; + E7A011AE14E1B78800765C29 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + E7A011AF14E1B78C00765C29 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + E7A94B2F13D89F25001C5FEE /* AllCertificatesNoPoliciesTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540BB13D51D63008048AC /* AllCertificatesNoPoliciesTest2EE.crt */; }; + E7A94B3013D89F25001C5FEE /* AllCertificatesSamePoliciesTest10EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540BC13D51D63008048AC /* AllCertificatesSamePoliciesTest10EE.crt */; }; + E7A94B3113D89F25001C5FEE /* AllCertificatesSamePoliciesTest13EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540BD13D51D63008048AC /* AllCertificatesSamePoliciesTest13EE.crt */; }; + E7A94B3213D89F25001C5FEE /* AllCertificatesanyPolicyTest11EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540BE13D51D63008048AC /* AllCertificatesanyPolicyTest11EE.crt */; }; + E7A94B3313D89F25001C5FEE /* AnyPolicyTest14EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540BF13D51D63008048AC /* AnyPolicyTest14EE.crt */; }; + E7A94B3413D89F25001C5FEE /* BadCRLIssuerNameCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540C013D51D63008048AC /* BadCRLIssuerNameCACert.crt */; }; + E7A94B3513D89F25001C5FEE /* BadCRLSignatureCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540C113D51D63008048AC /* BadCRLSignatureCACert.crt */; }; + E7A94B3613D89F25001C5FEE /* BadSignedCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540C213D51D63008048AC /* BadSignedCACert.crt */; }; + E7A94B3713D89F25001C5FEE /* BadnotAfterDateCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540C313D51D63008048AC /* BadnotAfterDateCACert.crt */; }; + E7A94B3813D89F25001C5FEE /* BadnotBeforeDateCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540C413D51D63008048AC /* BadnotBeforeDateCACert.crt */; }; + E7A94B3913D89F25001C5FEE /* BasicSelfIssuedCRLSigningKeyCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540C513D51D63008048AC /* BasicSelfIssuedCRLSigningKeyCACert.crt */; }; + E7A94B3A13D89F25001C5FEE /* BasicSelfIssuedNewKeyCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540C613D51D63008048AC /* BasicSelfIssuedNewKeyCACert.crt */; }; + E7A94B3B13D89F25001C5FEE /* BasicSelfIssuedNewKeyOldWithNewCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540C713D51D63008048AC /* BasicSelfIssuedNewKeyOldWithNewCACert.crt */; }; + E7A94B3C13D89F25001C5FEE /* BasicSelfIssuedOldKeyCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540C813D51D63008048AC /* BasicSelfIssuedOldKeyCACert.crt */; }; + E7A94B3D13D89F25001C5FEE /* BasicSelfIssuedOldKeyNewWithOldCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540C913D51D63008048AC /* BasicSelfIssuedOldKeyNewWithOldCACert.crt */; }; + E7A94B3E13D89F25001C5FEE /* CPSPointerQualifierTest20EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540CA13D51D63008048AC /* CPSPointerQualifierTest20EE.crt */; }; + E7A94B3F13D89F25001C5FEE /* DSACACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540CB13D51D63008048AC /* DSACACert.crt */; }; + E7A94B4013D89F25001C5FEE /* DSAParametersInheritedCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540CC13D51D63008048AC /* DSAParametersInheritedCACert.crt */; }; + E7A94B4113D89F25001C5FEE /* DifferentPoliciesTest12EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540CD13D51D63008048AC /* DifferentPoliciesTest12EE.crt */; }; + E7A94B4213D89F25001C5FEE /* DifferentPoliciesTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540CE13D51D63008048AC /* DifferentPoliciesTest3EE.crt */; }; + E7A94B4313D89F25001C5FEE /* DifferentPoliciesTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540CF13D51D63008048AC /* DifferentPoliciesTest4EE.crt */; }; + E7A94B4413D89F25001C5FEE /* DifferentPoliciesTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540D013D51D63008048AC /* DifferentPoliciesTest5EE.crt */; }; + E7A94B4513D89F25001C5FEE /* DifferentPoliciesTest7EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540D113D51D63008048AC /* DifferentPoliciesTest7EE.crt */; }; + E7A94B4613D89F25001C5FEE /* DifferentPoliciesTest8EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540D213D51D63008048AC /* DifferentPoliciesTest8EE.crt */; }; + E7A94B4713D89F25001C5FEE /* DifferentPoliciesTest9EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540D313D51D63008048AC /* DifferentPoliciesTest9EE.crt */; }; + E7A94B4813D89F25001C5FEE /* GeneralizedTimeCRLnextUpdateCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540D413D51D63008048AC /* GeneralizedTimeCRLnextUpdateCACert.crt */; }; + E7A94B4913D89F25001C5FEE /* GoodCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540D513D51D63008048AC /* GoodCACert.crt */; }; + E7A94B4A13D89F25001C5FEE /* GoodsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540D613D51D63008048AC /* GoodsubCACert.crt */; }; + E7A94B4B13D89F26001C5FEE /* GoodsubCAPanyPolicyMapping1to2CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540D713D51D63008048AC /* GoodsubCAPanyPolicyMapping1to2CACert.crt */; }; + E7A94B4C13D89F26001C5FEE /* InvalidBasicSelfIssuedNewWithOldTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540D813D51D63008048AC /* InvalidBasicSelfIssuedNewWithOldTest5EE.crt */; }; + E7A94B4D13D89F26001C5FEE /* InvalidBasicSelfIssuedOldWithNewTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540D913D51D63008048AC /* InvalidBasicSelfIssuedOldWithNewTest2EE.crt */; }; + E7A94B4E13D89F26001C5FEE /* InvalidCASignatureTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540DA13D51D63008048AC /* InvalidCASignatureTest2EE.crt */; }; + E7A94B4F13D89F26001C5FEE /* InvalidCAnotAfterDateTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540DB13D51D63008048AC /* InvalidCAnotAfterDateTest5EE.crt */; }; + E7A94B5013D89F26001C5FEE /* InvalidCAnotBeforeDateTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540DC13D51D63008048AC /* InvalidCAnotBeforeDateTest1EE.crt */; }; + E7A94B5113D89F26001C5FEE /* InvalidDNSnameConstraintsTest31EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540DD13D51D63008048AC /* InvalidDNSnameConstraintsTest31EE.crt */; }; + E7A94B5213D89F26001C5FEE /* InvalidDNSnameConstraintsTest33EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540DE13D51D63008048AC /* InvalidDNSnameConstraintsTest33EE.crt */; }; + E7A94B5313D89F26001C5FEE /* InvalidDNSnameConstraintsTest38EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540DF13D51D63008048AC /* InvalidDNSnameConstraintsTest38EE.crt */; }; + E7A94B5413D89F26001C5FEE /* InvalidDNandRFC822nameConstraintsTest28EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540E013D51D63008048AC /* InvalidDNandRFC822nameConstraintsTest28EE.crt */; }; + E7A94B5513D89F26001C5FEE /* InvalidDNandRFC822nameConstraintsTest29EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540E113D51D63008048AC /* InvalidDNandRFC822nameConstraintsTest29EE.crt */; }; + E7A94B5613D89F26001C5FEE /* InvalidDNnameConstraintsTest10EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540E213D51D63008048AC /* InvalidDNnameConstraintsTest10EE.crt */; }; + E7A94B5713D89F26001C5FEE /* InvalidDNnameConstraintsTest12EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540E313D51D63008048AC /* InvalidDNnameConstraintsTest12EE.crt */; }; + E7A94B5813D89F26001C5FEE /* InvalidDNnameConstraintsTest13EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540E413D51D63008048AC /* InvalidDNnameConstraintsTest13EE.crt */; }; + E7A94B5913D89F26001C5FEE /* InvalidDNnameConstraintsTest15EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540E513D51D63008048AC /* InvalidDNnameConstraintsTest15EE.crt */; }; + E7A94B5A13D89F26001C5FEE /* InvalidDNnameConstraintsTest16EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540E613D51D63008048AC /* InvalidDNnameConstraintsTest16EE.crt */; }; + E7A94B5B13D89F26001C5FEE /* InvalidDNnameConstraintsTest17EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540E713D51D63008048AC /* InvalidDNnameConstraintsTest17EE.crt */; }; + E7A94B5C13D89F26001C5FEE /* InvalidDNnameConstraintsTest20EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540E813D51D63008048AC /* InvalidDNnameConstraintsTest20EE.crt */; }; + E7A94B5D13D89F26001C5FEE /* InvalidDNnameConstraintsTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540E913D51D63008048AC /* InvalidDNnameConstraintsTest2EE.crt */; }; + E7A94B5E13D89F26001C5FEE /* InvalidDNnameConstraintsTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540EA13D51D63008048AC /* InvalidDNnameConstraintsTest3EE.crt */; }; + E7A94B5F13D89F26001C5FEE /* InvalidDNnameConstraintsTest7EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540EB13D51D63008048AC /* InvalidDNnameConstraintsTest7EE.crt */; }; + E7A94B6013D89F26001C5FEE /* InvalidDNnameConstraintsTest8EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540EC13D51D63008048AC /* InvalidDNnameConstraintsTest8EE.crt */; }; + E7A94B6113D89F26001C5FEE /* InvalidDNnameConstraintsTest9EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540ED13D51D63008048AC /* InvalidDNnameConstraintsTest9EE.crt */; }; + E7A94B6213D89F26001C5FEE /* InvalidDSASignatureTest6EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540EE13D51D63008048AC /* InvalidDSASignatureTest6EE.crt */; }; + E7A94B6313D89F26001C5FEE /* InvalidEESignatureTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540EF13D51D63008048AC /* InvalidEESignatureTest3EE.crt */; }; + E7A94B6413D89F26001C5FEE /* InvalidEEnotAfterDateTest6EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540F013D51D63008048AC /* InvalidEEnotAfterDateTest6EE.crt */; }; + E7A94B6513D89F26001C5FEE /* InvalidEEnotBeforeDateTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540F113D51D63008048AC /* InvalidEEnotBeforeDateTest2EE.crt */; }; + E7A94B6613D89F26001C5FEE /* InvalidLongSerialNumberTest18EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540F213D51D63008048AC /* InvalidLongSerialNumberTest18EE.crt */; }; + E7A94B6713D89F26001C5FEE /* InvalidMappingFromanyPolicyTest7EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540F313D51D63008048AC /* InvalidMappingFromanyPolicyTest7EE.crt */; }; + E7A94B6813D89F26001C5FEE /* InvalidMappingToanyPolicyTest8EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540F413D51D63008048AC /* InvalidMappingToanyPolicyTest8EE.crt */; }; + E7A94B6913D89F26001C5FEE /* InvalidMissingbasicConstraintsTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540F513D51D63008048AC /* InvalidMissingbasicConstraintsTest1EE.crt */; }; + E7A94B6A13D89F26001C5FEE /* InvalidNameChainingOrderTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540F613D51D63008048AC /* InvalidNameChainingOrderTest2EE.crt */; }; + E7A94B6B13D89F26001C5FEE /* InvalidNameChainingTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540F713D51D63008048AC /* InvalidNameChainingTest1EE.crt */; }; + E7A94B6C13D89F26001C5FEE /* InvalidNegativeSerialNumberTest15EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540F813D51D63008048AC /* InvalidNegativeSerialNumberTest15EE.crt */; }; + E7A94B6D13D89F26001C5FEE /* InvalidPolicyMappingTest10EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540F913D51D63008048AC /* InvalidPolicyMappingTest10EE.crt */; }; + E7A94B6E13D89F26001C5FEE /* InvalidPolicyMappingTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540FA13D51D63008048AC /* InvalidPolicyMappingTest2EE.crt */; }; + E7A94B6F13D89F26001C5FEE /* InvalidPolicyMappingTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540FB13D51D63008048AC /* InvalidPolicyMappingTest4EE.crt */; }; + E7A94B7013D89F26001C5FEE /* InvalidRFC822nameConstraintsTest22EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540FC13D51D63008048AC /* InvalidRFC822nameConstraintsTest22EE.crt */; }; + E7A94B7113D89F26001C5FEE /* InvalidRFC822nameConstraintsTest24EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540FD13D51D63008048AC /* InvalidRFC822nameConstraintsTest24EE.crt */; }; + E7A94B7213D89F26001C5FEE /* InvalidRFC822nameConstraintsTest26EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540FE13D51D63008048AC /* InvalidRFC822nameConstraintsTest26EE.crt */; }; + E7A94B7313D89F26001C5FEE /* InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540FF13D51D63008048AC /* InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt */; }; + E7A94B7413D89F26001C5FEE /* InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410013D51D63008048AC /* InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt */; }; + E7A94B7513D89F26001C5FEE /* InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410113D51D63008048AC /* InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt */; }; + E7A94B7613D89F26001C5FEE /* InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410213D51D63008048AC /* InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt */; }; + E7A94B7713D89F26001C5FEE /* InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410313D51D63008048AC /* InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt */; }; + E7A94B7813D89F26001C5FEE /* InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410413D51D63008048AC /* InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt */; }; + E7A94B7913D89F26001C5FEE /* InvalidSelfIssuedpathLenConstraintTest16EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410513D51D63008048AC /* InvalidSelfIssuedpathLenConstraintTest16EE.crt */; }; + E7A94B7A13D89F26001C5FEE /* InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410613D51D63008048AC /* InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt */; }; + E7A94B7B13D89F26001C5FEE /* InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410713D51D63008048AC /* InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt */; }; + E7A94B7C13D89F26001C5FEE /* InvalidURInameConstraintsTest35EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410813D51D63008048AC /* InvalidURInameConstraintsTest35EE.crt */; }; + E7A94B7D13D89F26001C5FEE /* InvalidURInameConstraintsTest37EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410913D51D63008048AC /* InvalidURInameConstraintsTest37EE.crt */; }; + E7A94B7E13D89F26001C5FEE /* InvalidUnknownCriticalCertificateExtensionTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410A13D51D63008048AC /* InvalidUnknownCriticalCertificateExtensionTest2EE.crt */; }; + E7A94B7F13D89F26001C5FEE /* InvalidcAFalseTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410B13D51D63008048AC /* InvalidcAFalseTest2EE.crt */; }; + E7A94B8013D89F26001C5FEE /* InvalidcAFalseTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410C13D51D63008048AC /* InvalidcAFalseTest3EE.crt */; }; + E7A94B8113D89F26001C5FEE /* InvalidcRLIssuerTest27EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410D13D51D63008048AC /* InvalidcRLIssuerTest27EE.crt */; }; + E7A94B8213D89F26001C5FEE /* InvalidcRLIssuerTest31EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410E13D51D63008048AC /* InvalidcRLIssuerTest31EE.crt */; }; + E7A94B8313D89F26001C5FEE /* InvalidcRLIssuerTest32EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410F13D51D63008048AC /* InvalidcRLIssuerTest32EE.crt */; }; + E7A94B8413D89F26001C5FEE /* InvalidcRLIssuerTest34EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411013D51D63008048AC /* InvalidcRLIssuerTest34EE.crt */; }; + E7A94B8513D89F26001C5FEE /* InvalidcRLIssuerTest35EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411113D51D63008048AC /* InvalidcRLIssuerTest35EE.crt */; }; + E7A94B8613D89F26001C5FEE /* InvalidinhibitAnyPolicyTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411213D51D63008048AC /* InvalidinhibitAnyPolicyTest1EE.crt */; }; + E7A94B8713D89F26001C5FEE /* InvalidinhibitAnyPolicyTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411313D51D63008048AC /* InvalidinhibitAnyPolicyTest4EE.crt */; }; + E7A94B8813D89F26001C5FEE /* InvalidinhibitAnyPolicyTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411413D51D63008048AC /* InvalidinhibitAnyPolicyTest5EE.crt */; }; + E7A94B8913D89F26001C5FEE /* InvalidinhibitAnyPolicyTest6EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411513D51D63008048AC /* InvalidinhibitAnyPolicyTest6EE.crt */; }; + E7A94B8A13D89F26001C5FEE /* InvalidinhibitPolicyMappingTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411613D51D63008048AC /* InvalidinhibitPolicyMappingTest1EE.crt */; }; + E7A94B8B13D89F26001C5FEE /* InvalidinhibitPolicyMappingTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411713D51D63008048AC /* InvalidinhibitPolicyMappingTest3EE.crt */; }; + E7A94B8C13D89F26001C5FEE /* InvalidinhibitPolicyMappingTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411813D51D63008048AC /* InvalidinhibitPolicyMappingTest5EE.crt */; }; + E7A94B8D13D89F26001C5FEE /* InvalidinhibitPolicyMappingTest6EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411913D51D63008048AC /* InvalidinhibitPolicyMappingTest6EE.crt */; }; + E7A94B8E13D89F26001C5FEE /* InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411A13D51D63008048AC /* InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt */; }; + E7A94B8F13D89F26001C5FEE /* InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411B13D51D63008048AC /* InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt */; }; + E7A94B9013D89F26001C5FEE /* InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411C13D51D63008048AC /* InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt */; }; + E7A94B9113D89F26001C5FEE /* InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411D13D51D63008048AC /* InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt */; }; + E7A94B9213D89F26001C5FEE /* InvalidonlyContainsAttributeCertsTest14EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411E13D51D63008048AC /* InvalidonlyContainsAttributeCertsTest14EE.crt */; }; + E7A94B9313D89F26001C5FEE /* InvalidonlyContainsCACertsTest12EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411F13D51D63008048AC /* InvalidonlyContainsCACertsTest12EE.crt */; }; + E7A94B9413D89F26001C5FEE /* InvalidonlyContainsUserCertsTest11EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412013D51D63008048AC /* InvalidonlyContainsUserCertsTest11EE.crt */; }; + E7A94B9513D89F26001C5FEE /* InvalidonlySomeReasonsTest15EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412113D51D63008048AC /* InvalidonlySomeReasonsTest15EE.crt */; }; + E7A94B9613D89F26001C5FEE /* InvalidonlySomeReasonsTest16EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412213D51D63008048AC /* InvalidonlySomeReasonsTest16EE.crt */; }; + E7A94B9713D89F26001C5FEE /* InvalidonlySomeReasonsTest17EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412313D51D63008048AC /* InvalidonlySomeReasonsTest17EE.crt */; }; + E7A94B9813D89F26001C5FEE /* InvalidonlySomeReasonsTest20EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412413D51D63008048AC /* InvalidonlySomeReasonsTest20EE.crt */; }; + E7A94B9913D89F26001C5FEE /* InvalidonlySomeReasonsTest21EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412513D51D63008048AC /* InvalidonlySomeReasonsTest21EE.crt */; }; + E7A94B9A13D89F26001C5FEE /* InvalidpathLenConstraintTest10EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412613D51D63008048AC /* InvalidpathLenConstraintTest10EE.crt */; }; + E7A94B9B13D89F26001C5FEE /* InvalidpathLenConstraintTest11EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412713D51D63008048AC /* InvalidpathLenConstraintTest11EE.crt */; }; + E7A94B9C13D89F26001C5FEE /* InvalidpathLenConstraintTest12EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412813D51D63008048AC /* InvalidpathLenConstraintTest12EE.crt */; }; + E7A94B9D13D89F26001C5FEE /* InvalidpathLenConstraintTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412913D51D63008048AC /* InvalidpathLenConstraintTest5EE.crt */; }; + E7A94B9E13D89F26001C5FEE /* InvalidpathLenConstraintTest6EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412A13D51D63008048AC /* InvalidpathLenConstraintTest6EE.crt */; }; + E7A94B9F13D89F26001C5FEE /* InvalidpathLenConstraintTest9EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412B13D51D63008048AC /* InvalidpathLenConstraintTest9EE.crt */; }; + E7A94BA013D89F26001C5FEE /* Invalidpre2000UTCEEnotAfterDateTest7EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412C13D51D63008048AC /* Invalidpre2000UTCEEnotAfterDateTest7EE.crt */; }; + E7A94BA113D89F26001C5FEE /* InvalidrequireExplicitPolicyTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412D13D51D63008048AC /* InvalidrequireExplicitPolicyTest3EE.crt */; }; + E7A94BA213D89F26001C5FEE /* InvalidrequireExplicitPolicyTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412E13D51D63008048AC /* InvalidrequireExplicitPolicyTest5EE.crt */; }; + E7A94BA313D89F26001C5FEE /* LongSerialNumberCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412F13D51D63008048AC /* LongSerialNumberCACert.crt */; }; + E7A94BA413D89F26001C5FEE /* Mapping1to2CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413013D51D63008048AC /* Mapping1to2CACert.crt */; }; + E7A94BA513D89F26001C5FEE /* MappingFromanyPolicyCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413113D51D63008048AC /* MappingFromanyPolicyCACert.crt */; }; + E7A94BA613D89F26001C5FEE /* MappingToanyPolicyCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413213D51D63008048AC /* MappingToanyPolicyCACert.crt */; }; + E7A94BA713D89F26001C5FEE /* MissingbasicConstraintsCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413313D51D63008048AC /* MissingbasicConstraintsCACert.crt */; }; + E7A94BA813D89F26001C5FEE /* NameOrderingCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413413D51D63008048AC /* NameOrderingCACert.crt */; }; + E7A94BA913D89F26001C5FEE /* NegativeSerialNumberCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413513D51D63008048AC /* NegativeSerialNumberCACert.crt */; }; + E7A94BAA13D89F26001C5FEE /* NoCRLCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413613D51D63008048AC /* NoCRLCACert.crt */; }; + E7A94BAB13D89F26001C5FEE /* NoPoliciesCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413713D51D63008048AC /* NoPoliciesCACert.crt */; }; + E7A94BAC13D89F26001C5FEE /* NoissuingDistributionPointCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413813D51D63008048AC /* NoissuingDistributionPointCACert.crt */; }; + E7A94BAD13D89F26001C5FEE /* OldCRLnextUpdateCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413913D51D63008048AC /* OldCRLnextUpdateCACert.crt */; }; + E7A94BAE13D89F26001C5FEE /* OverlappingPoliciesTest6EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413A13D51D63008048AC /* OverlappingPoliciesTest6EE.crt */; }; + E7A94BAF13D89F26001C5FEE /* P12Mapping1to3CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413B13D51D63008048AC /* P12Mapping1to3CACert.crt */; }; + E7A94BB013D89F26001C5FEE /* P12Mapping1to3subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413C13D51D63008048AC /* P12Mapping1to3subCACert.crt */; }; + E7A94BB113D89F26001C5FEE /* P12Mapping1to3subsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413D13D51D63008048AC /* P12Mapping1to3subsubCACert.crt */; }; + E7A94BB213D89F26001C5FEE /* P1Mapping1to234CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413E13D51D63008048AC /* P1Mapping1to234CACert.crt */; }; + E7A94BB313D89F26001C5FEE /* P1Mapping1to234subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413F13D51D63008048AC /* P1Mapping1to234subCACert.crt */; }; + E7A94BB413D89F26001C5FEE /* P1anyPolicyMapping1to2CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414013D51D63008048AC /* P1anyPolicyMapping1to2CACert.crt */; }; + E7A94BB513D89F26001C5FEE /* PanyPolicyMapping1to2CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414113D51D63008048AC /* PanyPolicyMapping1to2CACert.crt */; }; + E7A94BB613D89F26001C5FEE /* PoliciesP1234CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414213D51D63008048AC /* PoliciesP1234CACert.crt */; }; + E7A94BB713D89F26001C5FEE /* PoliciesP1234subCAP123Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414313D51D63008048AC /* PoliciesP1234subCAP123Cert.crt */; }; + E7A94BB813D89F26001C5FEE /* PoliciesP1234subsubCAP123P12Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414413D51D63008048AC /* PoliciesP1234subsubCAP123P12Cert.crt */; }; + E7A94BB913D89F26001C5FEE /* PoliciesP123CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414513D51D63008048AC /* PoliciesP123CACert.crt */; }; + E7A94BBA13D89F26001C5FEE /* PoliciesP123subCAP12Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414613D51D63008048AC /* PoliciesP123subCAP12Cert.crt */; }; + E7A94BBB13D89F26001C5FEE /* PoliciesP123subsubCAP12P1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414713D51D63008048AC /* PoliciesP123subsubCAP12P1Cert.crt */; }; + E7A94BBC13D89F26001C5FEE /* PoliciesP123subsubCAP12P2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414813D51D63008048AC /* PoliciesP123subsubCAP12P2Cert.crt */; }; + E7A94BBD13D89F26001C5FEE /* PoliciesP123subsubsubCAP12P2P1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414913D51D63008048AC /* PoliciesP123subsubsubCAP12P2P1Cert.crt */; }; + E7A94BBE13D89F26001C5FEE /* PoliciesP12CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414A13D51D63008048AC /* PoliciesP12CACert.crt */; }; + E7A94BBF13D89F26001C5FEE /* PoliciesP12subCAP1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414B13D51D63008048AC /* PoliciesP12subCAP1Cert.crt */; }; + E7A94BC013D89F26001C5FEE /* PoliciesP12subsubCAP1P2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414C13D51D63008048AC /* PoliciesP12subsubCAP1P2Cert.crt */; }; + E7A94BC113D89F26001C5FEE /* PoliciesP2subCA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414D13D51D63008048AC /* PoliciesP2subCA2Cert.crt */; }; + E7A94BC213D89F26001C5FEE /* PoliciesP2subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414E13D51D63008048AC /* PoliciesP2subCACert.crt */; }; + E7A94BC313D89F26001C5FEE /* PoliciesP3CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414F13D51D63008048AC /* PoliciesP3CACert.crt */; }; + E7A94BC413D89F26001C5FEE /* RFC3280MandatoryAttributeTypesCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415013D51D63008048AC /* RFC3280MandatoryAttributeTypesCACert.crt */; }; + E7A94BC513D89F26001C5FEE /* RFC3280OptionalAttributeTypesCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415113D51D63008048AC /* RFC3280OptionalAttributeTypesCACert.crt */; }; + E7A94BC613D89F26001C5FEE /* RevokedsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415213D51D63008048AC /* RevokedsubCACert.crt */; }; + E7A94BC713D89F26001C5FEE /* RolloverfromPrintableStringtoUTF8StringCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415313D51D63008048AC /* RolloverfromPrintableStringtoUTF8StringCACert.crt */; }; + E7A94BC813D89F26001C5FEE /* SeparateCertificateandCRLKeysCA2CRLSigningCert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415413D51D63008048AC /* SeparateCertificateandCRLKeysCA2CRLSigningCert.crt */; }; + E7A94BC913D89F26001C5FEE /* SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415513D51D63008048AC /* SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt */; }; + E7A94BCA13D89F26001C5FEE /* SeparateCertificateandCRLKeysCertificateSigningCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415613D51D63008048AC /* SeparateCertificateandCRLKeysCertificateSigningCACert.crt */; }; + E7A94BCB13D89F26001C5FEE /* TrustAnchorRootCertificate.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415713D51D63008048AC /* TrustAnchorRootCertificate.crt */; }; + E7A94BCC13D89F26001C5FEE /* TwoCRLsCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415813D51D63008048AC /* TwoCRLsCACert.crt */; }; + E7A94BCD13D89F26001C5FEE /* UIDCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415913D51D63008048AC /* UIDCACert.crt */; }; + E7A94BCE13D89F26001C5FEE /* UTF8StringCaseInsensitiveMatchCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415A13D51D63008048AC /* UTF8StringCaseInsensitiveMatchCACert.crt */; }; + E7A94BCF13D89F26001C5FEE /* UTF8StringEncodedNamesCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415B13D51D63008048AC /* UTF8StringEncodedNamesCACert.crt */; }; + E7A94BD013D89F26001C5FEE /* UnknownCRLEntryExtensionCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415C13D51D63008048AC /* UnknownCRLEntryExtensionCACert.crt */; }; + E7A94BD113D89F26001C5FEE /* UnknownCRLExtensionCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415D13D51D63008048AC /* UnknownCRLExtensionCACert.crt */; }; + E7A94BD213D89F26001C5FEE /* UserNoticeQualifierTest15EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415E13D51D63008048AC /* UserNoticeQualifierTest15EE.crt */; }; + E7A94BD313D89F26001C5FEE /* UserNoticeQualifierTest16EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415F13D51D63008048AC /* UserNoticeQualifierTest16EE.crt */; }; + E7A94BD413D89F26001C5FEE /* UserNoticeQualifierTest17EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416013D51D63008048AC /* UserNoticeQualifierTest17EE.crt */; }; + E7A94BD513D89F26001C5FEE /* UserNoticeQualifierTest18EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416113D51D63008048AC /* UserNoticeQualifierTest18EE.crt */; }; + E7A94BD613D89F26001C5FEE /* UserNoticeQualifierTest19EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416213D51D63008048AC /* UserNoticeQualifierTest19EE.crt */; }; + E7A94BD713D89F26001C5FEE /* ValidBasicSelfIssuedNewWithOldTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416313D51D63008048AC /* ValidBasicSelfIssuedNewWithOldTest3EE.crt */; }; + E7A94BD813D89F26001C5FEE /* ValidBasicSelfIssuedNewWithOldTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416413D51D63008048AC /* ValidBasicSelfIssuedNewWithOldTest4EE.crt */; }; + E7A94BD913D89F26001C5FEE /* ValidBasicSelfIssuedOldWithNewTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416513D51D63008048AC /* ValidBasicSelfIssuedOldWithNewTest1EE.crt */; }; + E7A94BDA13D89F26001C5FEE /* ValidCertificatePathTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416613D51D63008048AC /* ValidCertificatePathTest1EE.crt */; }; + E7A94BDB13D89F26001C5FEE /* ValidDNSnameConstraintsTest30EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416713D51D63008048AC /* ValidDNSnameConstraintsTest30EE.crt */; }; + E7A94BDC13D89F26001C5FEE /* ValidDNSnameConstraintsTest32EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416813D51D63008048AC /* ValidDNSnameConstraintsTest32EE.crt */; }; + E7A94BDD13D89F26001C5FEE /* ValidDNandRFC822nameConstraintsTest27EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416913D51D63008048AC /* ValidDNandRFC822nameConstraintsTest27EE.crt */; }; + E7A94BDE13D89F26001C5FEE /* ValidDNnameConstraintsTest11EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416A13D51D63008048AC /* ValidDNnameConstraintsTest11EE.crt */; }; + E7A94BDF13D89F26001C5FEE /* ValidDNnameConstraintsTest14EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416B13D51D63008048AC /* ValidDNnameConstraintsTest14EE.crt */; }; + E7A94BE013D89F26001C5FEE /* ValidDNnameConstraintsTest18EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416C13D51D63008048AC /* ValidDNnameConstraintsTest18EE.crt */; }; + E7A94BE113D89F26001C5FEE /* ValidDNnameConstraintsTest19EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416D13D51D63008048AC /* ValidDNnameConstraintsTest19EE.crt */; }; + E7A94BE213D89F26001C5FEE /* ValidDNnameConstraintsTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416E13D51D63008048AC /* ValidDNnameConstraintsTest1EE.crt */; }; + E7A94BE313D89F26001C5FEE /* ValidDNnameConstraintsTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416F13D51D63008048AC /* ValidDNnameConstraintsTest4EE.crt */; }; + E7A94BE413D89F26001C5FEE /* ValidDNnameConstraintsTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417013D51D63008048AC /* ValidDNnameConstraintsTest5EE.crt */; }; + E7A94BE513D89F26001C5FEE /* ValidDNnameConstraintsTest6EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417113D51D63008048AC /* ValidDNnameConstraintsTest6EE.crt */; }; + E7A94BE613D89F26001C5FEE /* ValidDSAParameterInheritanceTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417213D51D63008048AC /* ValidDSAParameterInheritanceTest5EE.crt */; }; + E7A94BE713D89F26001C5FEE /* ValidDSASignaturesTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417313D51D63008048AC /* ValidDSASignaturesTest4EE.crt */; }; + E7A94BE813D89F26001C5FEE /* ValidGeneralizedTimenotAfterDateTest8EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417413D51D63008048AC /* ValidGeneralizedTimenotAfterDateTest8EE.crt */; }; + E7A94BE913D89F26001C5FEE /* ValidGeneralizedTimenotBeforeDateTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417513D51D63008048AC /* ValidGeneralizedTimenotBeforeDateTest4EE.crt */; }; + E7A94BEA13D89F26001C5FEE /* ValidLongSerialNumberTest16EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417613D51D63008048AC /* ValidLongSerialNumberTest16EE.crt */; }; + E7A94BEB13D89F26001C5FEE /* ValidLongSerialNumberTest17EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417713D51D63008048AC /* ValidLongSerialNumberTest17EE.crt */; }; + E7A94BEC13D89F26001C5FEE /* ValidNameChainingCapitalizationTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417813D51D63008048AC /* ValidNameChainingCapitalizationTest5EE.crt */; }; + E7A94BED13D89F26001C5FEE /* ValidNameChainingWhitespaceTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417913D51D63008048AC /* ValidNameChainingWhitespaceTest3EE.crt */; }; + E7A94BEE13D89F26001C5FEE /* ValidNameChainingWhitespaceTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417A13D51D63008048AC /* ValidNameChainingWhitespaceTest4EE.crt */; }; + E7A94BEF13D89F26001C5FEE /* ValidNameUIDsTest6EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417B13D51D63008048AC /* ValidNameUIDsTest6EE.crt */; }; + E7A94BF013D89F26001C5FEE /* ValidNegativeSerialNumberTest14EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417C13D51D63008048AC /* ValidNegativeSerialNumberTest14EE.crt */; }; + E7A94BF113D89F26001C5FEE /* ValidPolicyMappingTest11EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417D13D51D63008048AC /* ValidPolicyMappingTest11EE.crt */; }; + E7A94BF213D89F26001C5FEE /* ValidPolicyMappingTest12EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417E13D51D63008048AC /* ValidPolicyMappingTest12EE.crt */; }; + E7A94BF313D89F26001C5FEE /* ValidPolicyMappingTest13EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417F13D51D63008048AC /* ValidPolicyMappingTest13EE.crt */; }; + E7A94BF413D89F26001C5FEE /* ValidPolicyMappingTest14EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418013D51D63008048AC /* ValidPolicyMappingTest14EE.crt */; }; + E7A94BF513D89F26001C5FEE /* ValidPolicyMappingTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418113D51D63008048AC /* ValidPolicyMappingTest1EE.crt */; }; + E7A94BF613D89F26001C5FEE /* ValidPolicyMappingTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418213D51D63008048AC /* ValidPolicyMappingTest3EE.crt */; }; + E7A94BF713D89F26001C5FEE /* ValidPolicyMappingTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418313D51D63008048AC /* ValidPolicyMappingTest5EE.crt */; }; + E7A94BF813D89F26001C5FEE /* ValidPolicyMappingTest6EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418413D51D63008048AC /* ValidPolicyMappingTest6EE.crt */; }; + E7A94BF913D89F26001C5FEE /* ValidPolicyMappingTest9EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418513D51D63008048AC /* ValidPolicyMappingTest9EE.crt */; }; + E7A94BFA13D89F26001C5FEE /* ValidRFC3280MandatoryAttributeTypesTest7EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418613D51D63008048AC /* ValidRFC3280MandatoryAttributeTypesTest7EE.crt */; }; + E7A94BFB13D89F26001C5FEE /* ValidRFC3280OptionalAttributeTypesTest8EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418713D51D63008048AC /* ValidRFC3280OptionalAttributeTypesTest8EE.crt */; }; + E7A94BFC13D89F26001C5FEE /* ValidRFC822nameConstraintsTest21EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418813D51D63008048AC /* ValidRFC822nameConstraintsTest21EE.crt */; }; + E7A94BFD13D89F26001C5FEE /* ValidRFC822nameConstraintsTest23EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418913D51D63008048AC /* ValidRFC822nameConstraintsTest23EE.crt */; }; + E7A94BFE13D89F26001C5FEE /* ValidRFC822nameConstraintsTest25EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418A13D51D63008048AC /* ValidRFC822nameConstraintsTest25EE.crt */; }; + E7A94BFF13D89F26001C5FEE /* ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418B13D51D63008048AC /* ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt */; }; + E7A94C0013D89F26001C5FEE /* ValidSelfIssuedinhibitAnyPolicyTest7EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418C13D51D63008048AC /* ValidSelfIssuedinhibitAnyPolicyTest7EE.crt */; }; + E7A94C0113D89F26001C5FEE /* ValidSelfIssuedinhibitAnyPolicyTest9EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418D13D51D63008048AC /* ValidSelfIssuedinhibitAnyPolicyTest9EE.crt */; }; + E7A94C0213D89F26001C5FEE /* ValidSelfIssuedinhibitPolicyMappingTest7EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418E13D51D63008048AC /* ValidSelfIssuedinhibitPolicyMappingTest7EE.crt */; }; + E7A94C0313D89F26001C5FEE /* ValidSelfIssuedpathLenConstraintTest15EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418F13D51D63008048AC /* ValidSelfIssuedpathLenConstraintTest15EE.crt */; }; + E7A94C0413D89F26001C5FEE /* ValidSelfIssuedpathLenConstraintTest17EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419013D51D63008048AC /* ValidSelfIssuedpathLenConstraintTest17EE.crt */; }; + E7A94C0513D89F26001C5FEE /* ValidSelfIssuedrequireExplicitPolicyTest6EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419113D51D63008048AC /* ValidSelfIssuedrequireExplicitPolicyTest6EE.crt */; }; + E7A94C0613D89F26001C5FEE /* ValidURInameConstraintsTest34EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419213D51D63008048AC /* ValidURInameConstraintsTest34EE.crt */; }; + E7A94C0713D89F26001C5FEE /* ValidURInameConstraintsTest36EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419313D51D63008048AC /* ValidURInameConstraintsTest36EE.crt */; }; + E7A94C0813D89F26001C5FEE /* ValidUTF8StringCaseInsensitiveMatchTest11EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419413D51D63008048AC /* ValidUTF8StringCaseInsensitiveMatchTest11EE.crt */; }; + E7A94C0913D89F26001C5FEE /* ValidUTF8StringEncodedNamesTest9EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419513D51D63008048AC /* ValidUTF8StringEncodedNamesTest9EE.crt */; }; + E7A94C0A13D89F26001C5FEE /* ValidUnknownNotCriticalCertificateExtensionTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419613D51D63008048AC /* ValidUnknownNotCriticalCertificateExtensionTest1EE.crt */; }; + E7A94C0B13D89F26001C5FEE /* ValidbasicConstraintsNotCriticalTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419713D51D63008048AC /* ValidbasicConstraintsNotCriticalTest4EE.crt */; }; + E7A94C0C13D89F26001C5FEE /* ValidcRLIssuerTest28EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419813D51D63008048AC /* ValidcRLIssuerTest28EE.crt */; }; + E7A94C0D13D89F26001C5FEE /* ValidcRLIssuerTest29EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419913D51D63008048AC /* ValidcRLIssuerTest29EE.crt */; }; + E7A94C0E13D89F26001C5FEE /* ValidcRLIssuerTest30EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419A13D51D63008048AC /* ValidcRLIssuerTest30EE.crt */; }; + E7A94C0F13D89F26001C5FEE /* ValidcRLIssuerTest33EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419B13D51D63008048AC /* ValidcRLIssuerTest33EE.crt */; }; + E7A94C1013D89F26001C5FEE /* ValidinhibitAnyPolicyTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419C13D51D63008048AC /* ValidinhibitAnyPolicyTest2EE.crt */; }; + E7A94C1113D89F26001C5FEE /* ValidinhibitPolicyMappingTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419D13D51D63008048AC /* ValidinhibitPolicyMappingTest2EE.crt */; }; + E7A94C1213D89F27001C5FEE /* ValidinhibitPolicyMappingTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419E13D51D63008048AC /* ValidinhibitPolicyMappingTest4EE.crt */; }; + E7A94C1313D89F27001C5FEE /* ValidkeyUsageNotCriticalTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419F13D51D63008048AC /* ValidkeyUsageNotCriticalTest3EE.crt */; }; + E7A94C1413D89F27001C5FEE /* ValidonlyContainsCACertsTest13EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541A013D51D63008048AC /* ValidonlyContainsCACertsTest13EE.crt */; }; + E7A94C1513D89F27001C5FEE /* ValidonlySomeReasonsTest18EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541A113D51D63008048AC /* ValidonlySomeReasonsTest18EE.crt */; }; + E7A94C1613D89F27001C5FEE /* ValidonlySomeReasonsTest19EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541A213D51D63008048AC /* ValidonlySomeReasonsTest19EE.crt */; }; + E7A94C1713D89F27001C5FEE /* ValidpathLenConstraintTest13EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541A313D51D63008048AC /* ValidpathLenConstraintTest13EE.crt */; }; + E7A94C1813D89F27001C5FEE /* ValidpathLenConstraintTest14EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541A413D51D63008048AC /* ValidpathLenConstraintTest14EE.crt */; }; + E7A94C1913D89F27001C5FEE /* ValidpathLenConstraintTest7EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541A513D51D63008048AC /* ValidpathLenConstraintTest7EE.crt */; }; + E7A94C1A13D89F27001C5FEE /* ValidpathLenConstraintTest8EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541A613D51D63008048AC /* ValidpathLenConstraintTest8EE.crt */; }; + E7A94C1B13D89F27001C5FEE /* Validpre2000UTCnotBeforeDateTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541A713D51D63008048AC /* Validpre2000UTCnotBeforeDateTest3EE.crt */; }; + E7A94C1C13D89F27001C5FEE /* ValidrequireExplicitPolicyTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541A813D51D63008048AC /* ValidrequireExplicitPolicyTest1EE.crt */; }; + E7A94C1D13D89F27001C5FEE /* ValidrequireExplicitPolicyTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541A913D51D63008048AC /* ValidrequireExplicitPolicyTest2EE.crt */; }; + E7A94C1E13D89F27001C5FEE /* ValidrequireExplicitPolicyTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541AA13D51D63008048AC /* ValidrequireExplicitPolicyTest4EE.crt */; }; + E7A94C1F13D89F27001C5FEE /* WrongCRLCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541AB13D51D63008048AC /* WrongCRLCACert.crt */; }; + E7A94C2013D89F27001C5FEE /* anyPolicyCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541AC13D51D63008048AC /* anyPolicyCACert.crt */; }; + E7A94C2113D89F27001C5FEE /* basicConstraintsCriticalcAFalseCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541AD13D51D63008048AC /* basicConstraintsCriticalcAFalseCACert.crt */; }; + E7A94C2213D89F27001C5FEE /* basicConstraintsNotCriticalCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541AE13D51D63008048AC /* basicConstraintsNotCriticalCACert.crt */; }; + E7A94C2313D89F27001C5FEE /* basicConstraintsNotCriticalcAFalseCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541AF13D51D63008048AC /* basicConstraintsNotCriticalcAFalseCACert.crt */; }; + E7A94C2413D89F27001C5FEE /* deltaCRLCA1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541B013D51D63008048AC /* deltaCRLCA1Cert.crt */; }; + E7A94C2513D89F27001C5FEE /* deltaCRLCA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541B113D51D63008048AC /* deltaCRLCA2Cert.crt */; }; + E7A94C2613D89F27001C5FEE /* deltaCRLCA3Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541B213D51D63008048AC /* deltaCRLCA3Cert.crt */; }; + E7A94C2713D89F27001C5FEE /* deltaCRLIndicatorNoBaseCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541B313D51D63008048AC /* deltaCRLIndicatorNoBaseCACert.crt */; }; + E7A94C2813D89F27001C5FEE /* distributionPoint1CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541B413D51D63008048AC /* distributionPoint1CACert.crt */; }; + E7A94C2913D89F27001C5FEE /* distributionPoint2CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541B513D51D63008048AC /* distributionPoint2CACert.crt */; }; + E7A94C2A13D89F27001C5FEE /* indirectCRLCA1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541B613D51D63008048AC /* indirectCRLCA1Cert.crt */; }; + E7A94C2B13D89F27001C5FEE /* indirectCRLCA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541B713D51D63008048AC /* indirectCRLCA2Cert.crt */; }; + E7A94C2C13D89F27001C5FEE /* indirectCRLCA3Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541B813D51D63008048AC /* indirectCRLCA3Cert.crt */; }; + E7A94C2D13D89F27001C5FEE /* indirectCRLCA3cRLIssuerCert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541B913D51D63008048AC /* indirectCRLCA3cRLIssuerCert.crt */; }; + E7A94C2E13D89F27001C5FEE /* indirectCRLCA4Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541BA13D51D63008048AC /* indirectCRLCA4Cert.crt */; }; + E7A94C2F13D89F27001C5FEE /* indirectCRLCA4cRLIssuerCert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541BB13D51D63008048AC /* indirectCRLCA4cRLIssuerCert.crt */; }; + E7A94C3013D89F27001C5FEE /* indirectCRLCA5Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541BC13D51D63008048AC /* indirectCRLCA5Cert.crt */; }; + E7A94C3113D89F27001C5FEE /* indirectCRLCA6Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541BD13D51D63008048AC /* indirectCRLCA6Cert.crt */; }; + E7A94C3213D89F27001C5FEE /* inhibitAnyPolicy0CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541BE13D51D63008048AC /* inhibitAnyPolicy0CACert.crt */; }; + E7A94C3313D89F27001C5FEE /* inhibitAnyPolicy1CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541BF13D51D63008048AC /* inhibitAnyPolicy1CACert.crt */; }; + E7A94C3413D89F27001C5FEE /* inhibitAnyPolicy1SelfIssuedCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541C013D51D63008048AC /* inhibitAnyPolicy1SelfIssuedCACert.crt */; }; + E7A94C3513D89F27001C5FEE /* inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541C113D51D63008048AC /* inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt */; }; + E7A94C3613D89F27001C5FEE /* inhibitAnyPolicy1subCA1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541C213D51D63008048AC /* inhibitAnyPolicy1subCA1Cert.crt */; }; + E7A94C3713D89F27001C5FEE /* inhibitAnyPolicy1subCA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541C313D51D63008048AC /* inhibitAnyPolicy1subCA2Cert.crt */; }; + E7A94C3813D89F27001C5FEE /* inhibitAnyPolicy1subCAIAP5Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541C413D51D63008048AC /* inhibitAnyPolicy1subCAIAP5Cert.crt */; }; + E7A94C3913D89F27001C5FEE /* inhibitAnyPolicy1subsubCA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541C513D51D63008048AC /* inhibitAnyPolicy1subsubCA2Cert.crt */; }; + E7A94C3A13D89F27001C5FEE /* inhibitAnyPolicy5CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541C613D51D63008048AC /* inhibitAnyPolicy5CACert.crt */; }; + E7A94C3B13D89F27001C5FEE /* inhibitAnyPolicy5subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541C713D51D63008048AC /* inhibitAnyPolicy5subCACert.crt */; }; + E7A94C3C13D89F27001C5FEE /* inhibitAnyPolicy5subsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541C813D51D63008048AC /* inhibitAnyPolicy5subsubCACert.crt */; }; + E7A94C3D13D89F27001C5FEE /* inhibitAnyPolicyTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541C913D51D63008048AC /* inhibitAnyPolicyTest3EE.crt */; }; + E7A94C3E13D89F27001C5FEE /* inhibitPolicyMapping0CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541CA13D51D63008048AC /* inhibitPolicyMapping0CACert.crt */; }; + E7A94C3F13D89F27001C5FEE /* inhibitPolicyMapping0subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541CB13D51D63008048AC /* inhibitPolicyMapping0subCACert.crt */; }; + E7A94C4013D89F27001C5FEE /* inhibitPolicyMapping1P12CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541CC13D51D63008048AC /* inhibitPolicyMapping1P12CACert.crt */; }; + E7A94C4113D89F27001C5FEE /* inhibitPolicyMapping1P12subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541CD13D51D63008048AC /* inhibitPolicyMapping1P12subCACert.crt */; }; + E7A94C4213D89F27001C5FEE /* inhibitPolicyMapping1P12subCAIPM5Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541CE13D51D63008048AC /* inhibitPolicyMapping1P12subCAIPM5Cert.crt */; }; + E7A94C4313D89F27001C5FEE /* inhibitPolicyMapping1P12subsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541CF13D51D63008048AC /* inhibitPolicyMapping1P12subsubCACert.crt */; }; + E7A94C4413D89F27001C5FEE /* inhibitPolicyMapping1P12subsubCAIPM5Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541D013D51D63008048AC /* inhibitPolicyMapping1P12subsubCAIPM5Cert.crt */; }; + E7A94C4513D89F27001C5FEE /* inhibitPolicyMapping1P1CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541D113D51D63008048AC /* inhibitPolicyMapping1P1CACert.crt */; }; + E7A94C4613D89F27001C5FEE /* inhibitPolicyMapping1P1SelfIssuedCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541D213D51D63008048AC /* inhibitPolicyMapping1P1SelfIssuedCACert.crt */; }; + E7A94C4713D89F27001C5FEE /* inhibitPolicyMapping1P1SelfIssuedsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541D313D51D63008048AC /* inhibitPolicyMapping1P1SelfIssuedsubCACert.crt */; }; + E7A94C4813D89F27001C5FEE /* inhibitPolicyMapping1P1subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541D413D51D63008048AC /* inhibitPolicyMapping1P1subCACert.crt */; }; + E7A94C4913D89F27001C5FEE /* inhibitPolicyMapping1P1subsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541D513D51D63008048AC /* inhibitPolicyMapping1P1subsubCACert.crt */; }; + E7A94C4A13D89F27001C5FEE /* inhibitPolicyMapping5CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541D613D51D63008048AC /* inhibitPolicyMapping5CACert.crt */; }; + E7A94C4B13D89F27001C5FEE /* inhibitPolicyMapping5subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541D713D51D63008048AC /* inhibitPolicyMapping5subCACert.crt */; }; + E7A94C4C13D89F27001C5FEE /* inhibitPolicyMapping5subsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541D813D51D63008048AC /* inhibitPolicyMapping5subsubCACert.crt */; }; + E7A94C4D13D89F27001C5FEE /* inhibitPolicyMapping5subsubsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541D913D51D63008048AC /* inhibitPolicyMapping5subsubsubCACert.crt */; }; + E7A94C4E13D89F27001C5FEE /* keyUsageCriticalcRLSignFalseCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541DA13D51D63008048AC /* keyUsageCriticalcRLSignFalseCACert.crt */; }; + E7A94C4F13D89F27001C5FEE /* keyUsageCriticalkeyCertSignFalseCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541DB13D51D63008048AC /* keyUsageCriticalkeyCertSignFalseCACert.crt */; }; + E7A94C5013D89F27001C5FEE /* keyUsageNotCriticalCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541DC13D51D63008048AC /* keyUsageNotCriticalCACert.crt */; }; + E7A94C5113D89F27001C5FEE /* keyUsageNotCriticalcRLSignFalseCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541DD13D51D63008048AC /* keyUsageNotCriticalcRLSignFalseCACert.crt */; }; + E7A94C5213D89F27001C5FEE /* keyUsageNotCriticalkeyCertSignFalseCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541DE13D51D63008048AC /* keyUsageNotCriticalkeyCertSignFalseCACert.crt */; }; + E7A94C5313D89F27001C5FEE /* nameConstraintsDN1CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541DF13D51D63008048AC /* nameConstraintsDN1CACert.crt */; }; + E7A94C5413D89F27001C5FEE /* nameConstraintsDN1SelfIssuedCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541E013D51D63008048AC /* nameConstraintsDN1SelfIssuedCACert.crt */; }; + E7A94C5513D89F27001C5FEE /* nameConstraintsDN1subCA1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541E113D51D63008048AC /* nameConstraintsDN1subCA1Cert.crt */; }; + E7A94C5613D89F27001C5FEE /* nameConstraintsDN1subCA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541E213D51D63008048AC /* nameConstraintsDN1subCA2Cert.crt */; }; + E7A94C5713D89F27001C5FEE /* nameConstraintsDN1subCA3Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541E313D51D63008048AC /* nameConstraintsDN1subCA3Cert.crt */; }; + E7A94C5813D89F27001C5FEE /* nameConstraintsDN2CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541E413D51D63008048AC /* nameConstraintsDN2CACert.crt */; }; + E7A94C5913D89F27001C5FEE /* nameConstraintsDN3CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541E513D51D63008048AC /* nameConstraintsDN3CACert.crt */; }; + E7A94C5A13D89F27001C5FEE /* nameConstraintsDN3subCA1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541E613D51D63008048AC /* nameConstraintsDN3subCA1Cert.crt */; }; + E7A94C5B13D89F27001C5FEE /* nameConstraintsDN3subCA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541E713D51D63008048AC /* nameConstraintsDN3subCA2Cert.crt */; }; + E7A94C5C13D89F27001C5FEE /* nameConstraintsDN4CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541E813D51D63008048AC /* nameConstraintsDN4CACert.crt */; }; + E7A94C5D13D89F27001C5FEE /* nameConstraintsDN5CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541E913D51D63008048AC /* nameConstraintsDN5CACert.crt */; }; + E7A94C5E13D89F27001C5FEE /* nameConstraintsDNS1CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541EA13D51D63008048AC /* nameConstraintsDNS1CACert.crt */; }; + E7A94C5F13D89F27001C5FEE /* nameConstraintsDNS2CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541EB13D51D63008048AC /* nameConstraintsDNS2CACert.crt */; }; + E7A94C6013D89F27001C5FEE /* nameConstraintsRFC822CA1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541EC13D51D63008048AC /* nameConstraintsRFC822CA1Cert.crt */; }; + E7A94C6113D89F27001C5FEE /* nameConstraintsRFC822CA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541ED13D51D63008048AC /* nameConstraintsRFC822CA2Cert.crt */; }; + E7A94C6213D89F27001C5FEE /* nameConstraintsRFC822CA3Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541EE13D51D63008048AC /* nameConstraintsRFC822CA3Cert.crt */; }; + E7A94C6313D89F27001C5FEE /* nameConstraintsURI1CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541EF13D51D63008048AC /* nameConstraintsURI1CACert.crt */; }; + E7A94C6413D89F27001C5FEE /* nameConstraintsURI2CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541F013D51D63008048AC /* nameConstraintsURI2CACert.crt */; }; + E7A94C6513D89F27001C5FEE /* onlyContainsAttributeCertsCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541F113D51D63008048AC /* onlyContainsAttributeCertsCACert.crt */; }; + E7A94C6613D89F27001C5FEE /* onlyContainsCACertsCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541F213D51D63008048AC /* onlyContainsCACertsCACert.crt */; }; + E7A94C6713D89F27001C5FEE /* onlyContainsUserCertsCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541F313D51D63008048AC /* onlyContainsUserCertsCACert.crt */; }; + E7A94C6813D89F27001C5FEE /* onlySomeReasonsCA1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541F413D51D63008048AC /* onlySomeReasonsCA1Cert.crt */; }; + E7A94C6913D89F27001C5FEE /* onlySomeReasonsCA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541F513D51D63008048AC /* onlySomeReasonsCA2Cert.crt */; }; + E7A94C6A13D89F27001C5FEE /* onlySomeReasonsCA3Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541F613D51D63008048AC /* onlySomeReasonsCA3Cert.crt */; }; + E7A94C6B13D89F27001C5FEE /* onlySomeReasonsCA4Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541F713D51D63008048AC /* onlySomeReasonsCA4Cert.crt */; }; + E7A94C6C13D89F27001C5FEE /* pathLenConstraint0CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541F813D51D63008048AC /* pathLenConstraint0CACert.crt */; }; + E7A94C6D13D89F27001C5FEE /* pathLenConstraint0SelfIssuedCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541F913D51D63008048AC /* pathLenConstraint0SelfIssuedCACert.crt */; }; + E7A94C6E13D89F27001C5FEE /* pathLenConstraint0subCA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541FA13D51D63008048AC /* pathLenConstraint0subCA2Cert.crt */; }; + E7A94C6F13D89F27001C5FEE /* pathLenConstraint0subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541FB13D51D63008048AC /* pathLenConstraint0subCACert.crt */; }; + E7A94C7013D89F27001C5FEE /* pathLenConstraint1CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541FC13D51D63008048AC /* pathLenConstraint1CACert.crt */; }; + E7A94C7113D89F27001C5FEE /* pathLenConstraint1SelfIssuedCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541FD13D51D63008048AC /* pathLenConstraint1SelfIssuedCACert.crt */; }; + E7A94C7213D89F27001C5FEE /* pathLenConstraint1SelfIssuedsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541FE13D51D63008048AC /* pathLenConstraint1SelfIssuedsubCACert.crt */; }; + E7A94C7313D89F27001C5FEE /* pathLenConstraint1subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541FF13D51D63008048AC /* pathLenConstraint1subCACert.crt */; }; + E7A94C7413D89F27001C5FEE /* pathLenConstraint6CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420013D51D64008048AC /* pathLenConstraint6CACert.crt */; }; + E7A94C7513D89F27001C5FEE /* pathLenConstraint6subCA0Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420113D51D64008048AC /* pathLenConstraint6subCA0Cert.crt */; }; + E7A94C7613D89F27001C5FEE /* pathLenConstraint6subCA1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420213D51D64008048AC /* pathLenConstraint6subCA1Cert.crt */; }; + E7A94C7713D89F27001C5FEE /* pathLenConstraint6subCA4Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420313D51D64008048AC /* pathLenConstraint6subCA4Cert.crt */; }; + E7A94C7813D89F27001C5FEE /* pathLenConstraint6subsubCA00Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420413D51D64008048AC /* pathLenConstraint6subsubCA00Cert.crt */; }; + E7A94C7913D89F27001C5FEE /* pathLenConstraint6subsubCA11Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420513D51D64008048AC /* pathLenConstraint6subsubCA11Cert.crt */; }; + E7A94C7A13D89F27001C5FEE /* pathLenConstraint6subsubCA41Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420613D51D64008048AC /* pathLenConstraint6subsubCA41Cert.crt */; }; + E7A94C7B13D89F27001C5FEE /* pathLenConstraint6subsubsubCA11XCert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420713D51D64008048AC /* pathLenConstraint6subsubsubCA11XCert.crt */; }; + E7A94C7C13D89F27001C5FEE /* pathLenConstraint6subsubsubCA41XCert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420813D51D64008048AC /* pathLenConstraint6subsubsubCA41XCert.crt */; }; + E7A94C7D13D89F27001C5FEE /* pre2000CRLnextUpdateCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420913D51D64008048AC /* pre2000CRLnextUpdateCACert.crt */; }; + E7A94C7E13D89F27001C5FEE /* requireExplicitPolicy0CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420A13D51D64008048AC /* requireExplicitPolicy0CACert.crt */; }; + E7A94C7F13D89F27001C5FEE /* requireExplicitPolicy0subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420B13D51D64008048AC /* requireExplicitPolicy0subCACert.crt */; }; + E7A94C8013D89F27001C5FEE /* requireExplicitPolicy0subsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420C13D51D64008048AC /* requireExplicitPolicy0subsubCACert.crt */; }; + E7A94C8113D89F27001C5FEE /* requireExplicitPolicy0subsubsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420D13D51D64008048AC /* requireExplicitPolicy0subsubsubCACert.crt */; }; + E7A94C8213D89F27001C5FEE /* requireExplicitPolicy10CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420E13D51D64008048AC /* requireExplicitPolicy10CACert.crt */; }; + E7A94C8313D89F27001C5FEE /* requireExplicitPolicy10subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420F13D51D64008048AC /* requireExplicitPolicy10subCACert.crt */; }; + E7A94C8413D89F27001C5FEE /* requireExplicitPolicy10subsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421013D51D64008048AC /* requireExplicitPolicy10subsubCACert.crt */; }; + E7A94C8513D89F27001C5FEE /* requireExplicitPolicy10subsubsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421113D51D64008048AC /* requireExplicitPolicy10subsubsubCACert.crt */; }; + E7A94C8613D89F27001C5FEE /* requireExplicitPolicy2CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421213D51D64008048AC /* requireExplicitPolicy2CACert.crt */; }; + E7A94C8713D89F27001C5FEE /* requireExplicitPolicy2SelfIssuedCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421313D51D64008048AC /* requireExplicitPolicy2SelfIssuedCACert.crt */; }; + E7A94C8813D89F27001C5FEE /* requireExplicitPolicy2SelfIssuedsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421413D51D64008048AC /* requireExplicitPolicy2SelfIssuedsubCACert.crt */; }; + E7A94C8913D89F27001C5FEE /* requireExplicitPolicy2subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421513D51D64008048AC /* requireExplicitPolicy2subCACert.crt */; }; + E7A94C8A13D89F27001C5FEE /* requireExplicitPolicy4CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421613D51D64008048AC /* requireExplicitPolicy4CACert.crt */; }; + E7A94C8B13D89F27001C5FEE /* requireExplicitPolicy4subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421713D51D64008048AC /* requireExplicitPolicy4subCACert.crt */; }; + E7A94C8C13D89F27001C5FEE /* requireExplicitPolicy4subsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421813D51D64008048AC /* requireExplicitPolicy4subsubCACert.crt */; }; + E7A94C8D13D89F27001C5FEE /* requireExplicitPolicy4subsubsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421913D51D64008048AC /* requireExplicitPolicy4subsubsubCACert.crt */; }; + E7A94C8E13D89F27001C5FEE /* requireExplicitPolicy5CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421A13D51D64008048AC /* requireExplicitPolicy5CACert.crt */; }; + E7A94C8F13D89F27001C5FEE /* requireExplicitPolicy5subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421B13D51D64008048AC /* requireExplicitPolicy5subCACert.crt */; }; + E7A94C9013D89F27001C5FEE /* requireExplicitPolicy5subsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421C13D51D64008048AC /* requireExplicitPolicy5subsubCACert.crt */; }; + E7A94C9113D89F27001C5FEE /* requireExplicitPolicy5subsubsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421D13D51D64008048AC /* requireExplicitPolicy5subsubsubCACert.crt */; }; + E7A94C9213D89F27001C5FEE /* requireExplicitPolicy7CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421E13D51D64008048AC /* requireExplicitPolicy7CACert.crt */; }; + E7A94C9313D89F27001C5FEE /* requireExplicitPolicy7subCARE2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421F13D51D64008048AC /* requireExplicitPolicy7subCARE2Cert.crt */; }; + E7A94C9413D89F27001C5FEE /* requireExplicitPolicy7subsubCARE2RE4Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75422013D51D64008048AC /* requireExplicitPolicy7subsubCARE2RE4Cert.crt */; }; + E7A94C9513D89F27001C5FEE /* requireExplicitPolicy7subsubsubCARE2RE4Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75422113D51D64008048AC /* requireExplicitPolicy7subsubsubCARE2RE4Cert.crt */; }; + E7A94C9A13D8A128001C5FEE /* Expectations.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = E7A94C9713D8A0DF001C5FEE /* Expectations.plist */; }; + E7A94C9C13D8A1AC001C5FEE /* Expectations.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = E7A94C9713D8A0DF001C5FEE /* Expectations.plist */; }; + E7A94C9D13D8A1AC001C5FEE /* AllCertificatesNoPoliciesTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540BB13D51D63008048AC /* AllCertificatesNoPoliciesTest2EE.crt */; }; + E7A94C9E13D8A1AC001C5FEE /* AllCertificatesSamePoliciesTest10EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540BC13D51D63008048AC /* AllCertificatesSamePoliciesTest10EE.crt */; }; + E7A94C9F13D8A1AC001C5FEE /* AllCertificatesSamePoliciesTest13EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540BD13D51D63008048AC /* AllCertificatesSamePoliciesTest13EE.crt */; }; + E7A94CA013D8A1AC001C5FEE /* AllCertificatesanyPolicyTest11EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540BE13D51D63008048AC /* AllCertificatesanyPolicyTest11EE.crt */; }; + E7A94CA113D8A1AC001C5FEE /* AnyPolicyTest14EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540BF13D51D63008048AC /* AnyPolicyTest14EE.crt */; }; + E7A94CA213D8A1AC001C5FEE /* BadCRLIssuerNameCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540C013D51D63008048AC /* BadCRLIssuerNameCACert.crt */; }; + E7A94CA313D8A1AC001C5FEE /* BadCRLSignatureCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540C113D51D63008048AC /* BadCRLSignatureCACert.crt */; }; + E7A94CA413D8A1AC001C5FEE /* BadSignedCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540C213D51D63008048AC /* BadSignedCACert.crt */; }; + E7A94CA513D8A1AC001C5FEE /* BadnotAfterDateCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540C313D51D63008048AC /* BadnotAfterDateCACert.crt */; }; + E7A94CA613D8A1AC001C5FEE /* BadnotBeforeDateCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540C413D51D63008048AC /* BadnotBeforeDateCACert.crt */; }; + E7A94CA713D8A1AC001C5FEE /* BasicSelfIssuedCRLSigningKeyCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540C513D51D63008048AC /* BasicSelfIssuedCRLSigningKeyCACert.crt */; }; + E7A94CA813D8A1AC001C5FEE /* BasicSelfIssuedNewKeyCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540C613D51D63008048AC /* BasicSelfIssuedNewKeyCACert.crt */; }; + E7A94CA913D8A1AC001C5FEE /* BasicSelfIssuedNewKeyOldWithNewCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540C713D51D63008048AC /* BasicSelfIssuedNewKeyOldWithNewCACert.crt */; }; + E7A94CAA13D8A1AC001C5FEE /* BasicSelfIssuedOldKeyCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540C813D51D63008048AC /* BasicSelfIssuedOldKeyCACert.crt */; }; + E7A94CAB13D8A1AC001C5FEE /* BasicSelfIssuedOldKeyNewWithOldCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540C913D51D63008048AC /* BasicSelfIssuedOldKeyNewWithOldCACert.crt */; }; + E7A94CAC13D8A1AC001C5FEE /* CPSPointerQualifierTest20EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540CA13D51D63008048AC /* CPSPointerQualifierTest20EE.crt */; }; + E7A94CAD13D8A1AC001C5FEE /* DSACACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540CB13D51D63008048AC /* DSACACert.crt */; }; + E7A94CAE13D8A1AC001C5FEE /* DSAParametersInheritedCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540CC13D51D63008048AC /* DSAParametersInheritedCACert.crt */; }; + E7A94CAF13D8A1AC001C5FEE /* DifferentPoliciesTest12EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540CD13D51D63008048AC /* DifferentPoliciesTest12EE.crt */; }; + E7A94CB013D8A1AC001C5FEE /* DifferentPoliciesTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540CE13D51D63008048AC /* DifferentPoliciesTest3EE.crt */; }; + E7A94CB113D8A1AC001C5FEE /* DifferentPoliciesTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540CF13D51D63008048AC /* DifferentPoliciesTest4EE.crt */; }; + E7A94CB213D8A1AC001C5FEE /* DifferentPoliciesTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540D013D51D63008048AC /* DifferentPoliciesTest5EE.crt */; }; + E7A94CB313D8A1AC001C5FEE /* DifferentPoliciesTest7EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540D113D51D63008048AC /* DifferentPoliciesTest7EE.crt */; }; + E7A94CB413D8A1AC001C5FEE /* DifferentPoliciesTest8EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540D213D51D63008048AC /* DifferentPoliciesTest8EE.crt */; }; + E7A94CB513D8A1AC001C5FEE /* DifferentPoliciesTest9EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540D313D51D63008048AC /* DifferentPoliciesTest9EE.crt */; }; + E7A94CB613D8A1AC001C5FEE /* GeneralizedTimeCRLnextUpdateCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540D413D51D63008048AC /* GeneralizedTimeCRLnextUpdateCACert.crt */; }; + E7A94CB713D8A1AC001C5FEE /* GoodCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540D513D51D63008048AC /* GoodCACert.crt */; }; + E7A94CB813D8A1AC001C5FEE /* GoodsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540D613D51D63008048AC /* GoodsubCACert.crt */; }; + E7A94CB913D8A1AC001C5FEE /* GoodsubCAPanyPolicyMapping1to2CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540D713D51D63008048AC /* GoodsubCAPanyPolicyMapping1to2CACert.crt */; }; + E7A94CBA13D8A1AC001C5FEE /* InvalidBasicSelfIssuedNewWithOldTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540D813D51D63008048AC /* InvalidBasicSelfIssuedNewWithOldTest5EE.crt */; }; + E7A94CBB13D8A1AC001C5FEE /* InvalidBasicSelfIssuedOldWithNewTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540D913D51D63008048AC /* InvalidBasicSelfIssuedOldWithNewTest2EE.crt */; }; + E7A94CBC13D8A1AC001C5FEE /* InvalidCASignatureTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540DA13D51D63008048AC /* InvalidCASignatureTest2EE.crt */; }; + E7A94CBD13D8A1AC001C5FEE /* InvalidCAnotAfterDateTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540DB13D51D63008048AC /* InvalidCAnotAfterDateTest5EE.crt */; }; + E7A94CBE13D8A1AC001C5FEE /* InvalidCAnotBeforeDateTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540DC13D51D63008048AC /* InvalidCAnotBeforeDateTest1EE.crt */; }; + E7A94CBF13D8A1AC001C5FEE /* InvalidDNSnameConstraintsTest31EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540DD13D51D63008048AC /* InvalidDNSnameConstraintsTest31EE.crt */; }; + E7A94CC013D8A1AC001C5FEE /* InvalidDNSnameConstraintsTest33EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540DE13D51D63008048AC /* InvalidDNSnameConstraintsTest33EE.crt */; }; + E7A94CC113D8A1AC001C5FEE /* InvalidDNSnameConstraintsTest38EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540DF13D51D63008048AC /* InvalidDNSnameConstraintsTest38EE.crt */; }; + E7A94CC213D8A1AC001C5FEE /* InvalidDNandRFC822nameConstraintsTest28EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540E013D51D63008048AC /* InvalidDNandRFC822nameConstraintsTest28EE.crt */; }; + E7A94CC313D8A1AC001C5FEE /* InvalidDNandRFC822nameConstraintsTest29EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540E113D51D63008048AC /* InvalidDNandRFC822nameConstraintsTest29EE.crt */; }; + E7A94CC413D8A1AC001C5FEE /* InvalidDNnameConstraintsTest10EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540E213D51D63008048AC /* InvalidDNnameConstraintsTest10EE.crt */; }; + E7A94CC513D8A1AC001C5FEE /* InvalidDNnameConstraintsTest12EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540E313D51D63008048AC /* InvalidDNnameConstraintsTest12EE.crt */; }; + E7A94CC613D8A1AC001C5FEE /* InvalidDNnameConstraintsTest13EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540E413D51D63008048AC /* InvalidDNnameConstraintsTest13EE.crt */; }; + E7A94CC713D8A1AC001C5FEE /* InvalidDNnameConstraintsTest15EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540E513D51D63008048AC /* InvalidDNnameConstraintsTest15EE.crt */; }; + E7A94CC813D8A1AC001C5FEE /* InvalidDNnameConstraintsTest16EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540E613D51D63008048AC /* InvalidDNnameConstraintsTest16EE.crt */; }; + E7A94CC913D8A1AC001C5FEE /* InvalidDNnameConstraintsTest17EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540E713D51D63008048AC /* InvalidDNnameConstraintsTest17EE.crt */; }; + E7A94CCA13D8A1AC001C5FEE /* InvalidDNnameConstraintsTest20EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540E813D51D63008048AC /* InvalidDNnameConstraintsTest20EE.crt */; }; + E7A94CCB13D8A1AC001C5FEE /* InvalidDNnameConstraintsTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540E913D51D63008048AC /* InvalidDNnameConstraintsTest2EE.crt */; }; + E7A94CCC13D8A1AC001C5FEE /* InvalidDNnameConstraintsTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540EA13D51D63008048AC /* InvalidDNnameConstraintsTest3EE.crt */; }; + E7A94CCD13D8A1AC001C5FEE /* InvalidDNnameConstraintsTest7EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540EB13D51D63008048AC /* InvalidDNnameConstraintsTest7EE.crt */; }; + E7A94CCE13D8A1AC001C5FEE /* InvalidDNnameConstraintsTest8EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540EC13D51D63008048AC /* InvalidDNnameConstraintsTest8EE.crt */; }; + E7A94CCF13D8A1AC001C5FEE /* InvalidDNnameConstraintsTest9EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540ED13D51D63008048AC /* InvalidDNnameConstraintsTest9EE.crt */; }; + E7A94CD013D8A1AC001C5FEE /* InvalidDSASignatureTest6EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540EE13D51D63008048AC /* InvalidDSASignatureTest6EE.crt */; }; + E7A94CD113D8A1AC001C5FEE /* InvalidEESignatureTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540EF13D51D63008048AC /* InvalidEESignatureTest3EE.crt */; }; + E7A94CD213D8A1AC001C5FEE /* InvalidEEnotAfterDateTest6EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540F013D51D63008048AC /* InvalidEEnotAfterDateTest6EE.crt */; }; + E7A94CD313D8A1AC001C5FEE /* InvalidEEnotBeforeDateTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540F113D51D63008048AC /* InvalidEEnotBeforeDateTest2EE.crt */; }; + E7A94CD413D8A1AC001C5FEE /* InvalidLongSerialNumberTest18EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540F213D51D63008048AC /* InvalidLongSerialNumberTest18EE.crt */; }; + E7A94CD513D8A1AC001C5FEE /* InvalidMappingFromanyPolicyTest7EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540F313D51D63008048AC /* InvalidMappingFromanyPolicyTest7EE.crt */; }; + E7A94CD613D8A1AC001C5FEE /* InvalidMappingToanyPolicyTest8EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540F413D51D63008048AC /* InvalidMappingToanyPolicyTest8EE.crt */; }; + E7A94CD713D8A1AC001C5FEE /* InvalidMissingbasicConstraintsTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540F513D51D63008048AC /* InvalidMissingbasicConstraintsTest1EE.crt */; }; + E7A94CD813D8A1AC001C5FEE /* InvalidNameChainingOrderTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540F613D51D63008048AC /* InvalidNameChainingOrderTest2EE.crt */; }; + E7A94CD913D8A1AC001C5FEE /* InvalidNameChainingTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540F713D51D63008048AC /* InvalidNameChainingTest1EE.crt */; }; + E7A94CDA13D8A1AC001C5FEE /* InvalidNegativeSerialNumberTest15EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540F813D51D63008048AC /* InvalidNegativeSerialNumberTest15EE.crt */; }; + E7A94CDB13D8A1AC001C5FEE /* InvalidPolicyMappingTest10EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540F913D51D63008048AC /* InvalidPolicyMappingTest10EE.crt */; }; + E7A94CDC13D8A1AC001C5FEE /* InvalidPolicyMappingTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540FA13D51D63008048AC /* InvalidPolicyMappingTest2EE.crt */; }; + E7A94CDD13D8A1AC001C5FEE /* InvalidPolicyMappingTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540FB13D51D63008048AC /* InvalidPolicyMappingTest4EE.crt */; }; + E7A94CDE13D8A1AC001C5FEE /* InvalidRFC822nameConstraintsTest22EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540FC13D51D63008048AC /* InvalidRFC822nameConstraintsTest22EE.crt */; }; + E7A94CDF13D8A1AC001C5FEE /* InvalidRFC822nameConstraintsTest24EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540FD13D51D63008048AC /* InvalidRFC822nameConstraintsTest24EE.crt */; }; + E7A94CE013D8A1AC001C5FEE /* InvalidRFC822nameConstraintsTest26EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540FE13D51D63008048AC /* InvalidRFC822nameConstraintsTest26EE.crt */; }; + E7A94CE113D8A1AC001C5FEE /* InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7540FF13D51D63008048AC /* InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt */; }; + E7A94CE213D8A1AC001C5FEE /* InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410013D51D63008048AC /* InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt */; }; + E7A94CE313D8A1AC001C5FEE /* InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410113D51D63008048AC /* InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt */; }; + E7A94CE413D8A1AC001C5FEE /* InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410213D51D63008048AC /* InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt */; }; + E7A94CE513D8A1AC001C5FEE /* InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410313D51D63008048AC /* InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt */; }; + E7A94CE613D8A1AC001C5FEE /* InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410413D51D63008048AC /* InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt */; }; + E7A94CE713D8A1AC001C5FEE /* InvalidSelfIssuedpathLenConstraintTest16EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410513D51D63008048AC /* InvalidSelfIssuedpathLenConstraintTest16EE.crt */; }; + E7A94CE813D8A1AC001C5FEE /* InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410613D51D63008048AC /* InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt */; }; + E7A94CE913D8A1AC001C5FEE /* InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410713D51D63008048AC /* InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt */; }; + E7A94CEA13D8A1AC001C5FEE /* InvalidURInameConstraintsTest35EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410813D51D63008048AC /* InvalidURInameConstraintsTest35EE.crt */; }; + E7A94CEB13D8A1AC001C5FEE /* InvalidURInameConstraintsTest37EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410913D51D63008048AC /* InvalidURInameConstraintsTest37EE.crt */; }; + E7A94CEC13D8A1AC001C5FEE /* InvalidUnknownCriticalCertificateExtensionTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410A13D51D63008048AC /* InvalidUnknownCriticalCertificateExtensionTest2EE.crt */; }; + E7A94CED13D8A1AC001C5FEE /* InvalidcAFalseTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410B13D51D63008048AC /* InvalidcAFalseTest2EE.crt */; }; + E7A94CEE13D8A1AC001C5FEE /* InvalidcAFalseTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410C13D51D63008048AC /* InvalidcAFalseTest3EE.crt */; }; + E7A94CEF13D8A1AC001C5FEE /* InvalidcRLIssuerTest27EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410D13D51D63008048AC /* InvalidcRLIssuerTest27EE.crt */; }; + E7A94CF013D8A1AC001C5FEE /* InvalidcRLIssuerTest31EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410E13D51D63008048AC /* InvalidcRLIssuerTest31EE.crt */; }; + E7A94CF113D8A1AC001C5FEE /* InvalidcRLIssuerTest32EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75410F13D51D63008048AC /* InvalidcRLIssuerTest32EE.crt */; }; + E7A94CF213D8A1AC001C5FEE /* InvalidcRLIssuerTest34EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411013D51D63008048AC /* InvalidcRLIssuerTest34EE.crt */; }; + E7A94CF313D8A1AC001C5FEE /* InvalidcRLIssuerTest35EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411113D51D63008048AC /* InvalidcRLIssuerTest35EE.crt */; }; + E7A94CF413D8A1AC001C5FEE /* InvalidinhibitAnyPolicyTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411213D51D63008048AC /* InvalidinhibitAnyPolicyTest1EE.crt */; }; + E7A94CF513D8A1AC001C5FEE /* InvalidinhibitAnyPolicyTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411313D51D63008048AC /* InvalidinhibitAnyPolicyTest4EE.crt */; }; + E7A94CF613D8A1AC001C5FEE /* InvalidinhibitAnyPolicyTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411413D51D63008048AC /* InvalidinhibitAnyPolicyTest5EE.crt */; }; + E7A94CF713D8A1AC001C5FEE /* InvalidinhibitAnyPolicyTest6EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411513D51D63008048AC /* InvalidinhibitAnyPolicyTest6EE.crt */; }; + E7A94CF813D8A1AC001C5FEE /* InvalidinhibitPolicyMappingTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411613D51D63008048AC /* InvalidinhibitPolicyMappingTest1EE.crt */; }; + E7A94CF913D8A1AC001C5FEE /* InvalidinhibitPolicyMappingTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411713D51D63008048AC /* InvalidinhibitPolicyMappingTest3EE.crt */; }; + E7A94CFA13D8A1AC001C5FEE /* InvalidinhibitPolicyMappingTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411813D51D63008048AC /* InvalidinhibitPolicyMappingTest5EE.crt */; }; + E7A94CFB13D8A1AC001C5FEE /* InvalidinhibitPolicyMappingTest6EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411913D51D63008048AC /* InvalidinhibitPolicyMappingTest6EE.crt */; }; + E7A94CFC13D8A1AC001C5FEE /* InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411A13D51D63008048AC /* InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt */; }; + E7A94CFD13D8A1AC001C5FEE /* InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411B13D51D63008048AC /* InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt */; }; + E7A94CFE13D8A1AC001C5FEE /* InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411C13D51D63008048AC /* InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt */; }; + E7A94CFF13D8A1AC001C5FEE /* InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411D13D51D63008048AC /* InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt */; }; + E7A94D0013D8A1AC001C5FEE /* InvalidonlyContainsAttributeCertsTest14EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411E13D51D63008048AC /* InvalidonlyContainsAttributeCertsTest14EE.crt */; }; + E7A94D0113D8A1AC001C5FEE /* InvalidonlyContainsCACertsTest12EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75411F13D51D63008048AC /* InvalidonlyContainsCACertsTest12EE.crt */; }; + E7A94D0213D8A1AC001C5FEE /* InvalidonlyContainsUserCertsTest11EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412013D51D63008048AC /* InvalidonlyContainsUserCertsTest11EE.crt */; }; + E7A94D0313D8A1AC001C5FEE /* InvalidonlySomeReasonsTest15EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412113D51D63008048AC /* InvalidonlySomeReasonsTest15EE.crt */; }; + E7A94D0413D8A1AC001C5FEE /* InvalidonlySomeReasonsTest16EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412213D51D63008048AC /* InvalidonlySomeReasonsTest16EE.crt */; }; + E7A94D0513D8A1AC001C5FEE /* InvalidonlySomeReasonsTest17EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412313D51D63008048AC /* InvalidonlySomeReasonsTest17EE.crt */; }; + E7A94D0613D8A1AC001C5FEE /* InvalidonlySomeReasonsTest20EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412413D51D63008048AC /* InvalidonlySomeReasonsTest20EE.crt */; }; + E7A94D0713D8A1AC001C5FEE /* InvalidonlySomeReasonsTest21EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412513D51D63008048AC /* InvalidonlySomeReasonsTest21EE.crt */; }; + E7A94D0813D8A1AC001C5FEE /* InvalidpathLenConstraintTest10EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412613D51D63008048AC /* InvalidpathLenConstraintTest10EE.crt */; }; + E7A94D0913D8A1AC001C5FEE /* InvalidpathLenConstraintTest11EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412713D51D63008048AC /* InvalidpathLenConstraintTest11EE.crt */; }; + E7A94D0A13D8A1AC001C5FEE /* InvalidpathLenConstraintTest12EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412813D51D63008048AC /* InvalidpathLenConstraintTest12EE.crt */; }; + E7A94D0B13D8A1AC001C5FEE /* InvalidpathLenConstraintTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412913D51D63008048AC /* InvalidpathLenConstraintTest5EE.crt */; }; + E7A94D0C13D8A1AC001C5FEE /* InvalidpathLenConstraintTest6EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412A13D51D63008048AC /* InvalidpathLenConstraintTest6EE.crt */; }; + E7A94D0D13D8A1AC001C5FEE /* InvalidpathLenConstraintTest9EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412B13D51D63008048AC /* InvalidpathLenConstraintTest9EE.crt */; }; + E7A94D0E13D8A1AC001C5FEE /* Invalidpre2000UTCEEnotAfterDateTest7EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412C13D51D63008048AC /* Invalidpre2000UTCEEnotAfterDateTest7EE.crt */; }; + E7A94D0F13D8A1AC001C5FEE /* InvalidrequireExplicitPolicyTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412D13D51D63008048AC /* InvalidrequireExplicitPolicyTest3EE.crt */; }; + E7A94D1013D8A1AC001C5FEE /* InvalidrequireExplicitPolicyTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412E13D51D63008048AC /* InvalidrequireExplicitPolicyTest5EE.crt */; }; + E7A94D1113D8A1AC001C5FEE /* LongSerialNumberCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75412F13D51D63008048AC /* LongSerialNumberCACert.crt */; }; + E7A94D1213D8A1AC001C5FEE /* Mapping1to2CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413013D51D63008048AC /* Mapping1to2CACert.crt */; }; + E7A94D1313D8A1AC001C5FEE /* MappingFromanyPolicyCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413113D51D63008048AC /* MappingFromanyPolicyCACert.crt */; }; + E7A94D1413D8A1AC001C5FEE /* MappingToanyPolicyCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413213D51D63008048AC /* MappingToanyPolicyCACert.crt */; }; + E7A94D1513D8A1AC001C5FEE /* MissingbasicConstraintsCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413313D51D63008048AC /* MissingbasicConstraintsCACert.crt */; }; + E7A94D1613D8A1AC001C5FEE /* NameOrderingCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413413D51D63008048AC /* NameOrderingCACert.crt */; }; + E7A94D1713D8A1AC001C5FEE /* NegativeSerialNumberCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413513D51D63008048AC /* NegativeSerialNumberCACert.crt */; }; + E7A94D1813D8A1AC001C5FEE /* NoCRLCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413613D51D63008048AC /* NoCRLCACert.crt */; }; + E7A94D1913D8A1AC001C5FEE /* NoPoliciesCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413713D51D63008048AC /* NoPoliciesCACert.crt */; }; + E7A94D1A13D8A1AC001C5FEE /* NoissuingDistributionPointCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413813D51D63008048AC /* NoissuingDistributionPointCACert.crt */; }; + E7A94D1B13D8A1AC001C5FEE /* OldCRLnextUpdateCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413913D51D63008048AC /* OldCRLnextUpdateCACert.crt */; }; + E7A94D1C13D8A1AC001C5FEE /* OverlappingPoliciesTest6EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413A13D51D63008048AC /* OverlappingPoliciesTest6EE.crt */; }; + E7A94D1D13D8A1AC001C5FEE /* P12Mapping1to3CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413B13D51D63008048AC /* P12Mapping1to3CACert.crt */; }; + E7A94D1E13D8A1AC001C5FEE /* P12Mapping1to3subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413C13D51D63008048AC /* P12Mapping1to3subCACert.crt */; }; + E7A94D1F13D8A1AC001C5FEE /* P12Mapping1to3subsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413D13D51D63008048AC /* P12Mapping1to3subsubCACert.crt */; }; + E7A94D2013D8A1AC001C5FEE /* P1Mapping1to234CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413E13D51D63008048AC /* P1Mapping1to234CACert.crt */; }; + E7A94D2113D8A1AC001C5FEE /* P1Mapping1to234subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75413F13D51D63008048AC /* P1Mapping1to234subCACert.crt */; }; + E7A94D2213D8A1AC001C5FEE /* P1anyPolicyMapping1to2CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414013D51D63008048AC /* P1anyPolicyMapping1to2CACert.crt */; }; + E7A94D2313D8A1AC001C5FEE /* PanyPolicyMapping1to2CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414113D51D63008048AC /* PanyPolicyMapping1to2CACert.crt */; }; + E7A94D2413D8A1AC001C5FEE /* PoliciesP1234CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414213D51D63008048AC /* PoliciesP1234CACert.crt */; }; + E7A94D2513D8A1AC001C5FEE /* PoliciesP1234subCAP123Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414313D51D63008048AC /* PoliciesP1234subCAP123Cert.crt */; }; + E7A94D2613D8A1AC001C5FEE /* PoliciesP1234subsubCAP123P12Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414413D51D63008048AC /* PoliciesP1234subsubCAP123P12Cert.crt */; }; + E7A94D2713D8A1AC001C5FEE /* PoliciesP123CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414513D51D63008048AC /* PoliciesP123CACert.crt */; }; + E7A94D2813D8A1AC001C5FEE /* PoliciesP123subCAP12Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414613D51D63008048AC /* PoliciesP123subCAP12Cert.crt */; }; + E7A94D2913D8A1AC001C5FEE /* PoliciesP123subsubCAP12P1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414713D51D63008048AC /* PoliciesP123subsubCAP12P1Cert.crt */; }; + E7A94D2A13D8A1AC001C5FEE /* PoliciesP123subsubCAP12P2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414813D51D63008048AC /* PoliciesP123subsubCAP12P2Cert.crt */; }; + E7A94D2B13D8A1AC001C5FEE /* PoliciesP123subsubsubCAP12P2P1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414913D51D63008048AC /* PoliciesP123subsubsubCAP12P2P1Cert.crt */; }; + E7A94D2C13D8A1AC001C5FEE /* PoliciesP12CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414A13D51D63008048AC /* PoliciesP12CACert.crt */; }; + E7A94D2D13D8A1AC001C5FEE /* PoliciesP12subCAP1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414B13D51D63008048AC /* PoliciesP12subCAP1Cert.crt */; }; + E7A94D2E13D8A1AC001C5FEE /* PoliciesP12subsubCAP1P2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414C13D51D63008048AC /* PoliciesP12subsubCAP1P2Cert.crt */; }; + E7A94D2F13D8A1AC001C5FEE /* PoliciesP2subCA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414D13D51D63008048AC /* PoliciesP2subCA2Cert.crt */; }; + E7A94D3013D8A1AD001C5FEE /* PoliciesP2subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414E13D51D63008048AC /* PoliciesP2subCACert.crt */; }; + E7A94D3113D8A1AD001C5FEE /* PoliciesP3CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75414F13D51D63008048AC /* PoliciesP3CACert.crt */; }; + E7A94D3213D8A1AD001C5FEE /* RFC3280MandatoryAttributeTypesCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415013D51D63008048AC /* RFC3280MandatoryAttributeTypesCACert.crt */; }; + E7A94D3313D8A1AD001C5FEE /* RFC3280OptionalAttributeTypesCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415113D51D63008048AC /* RFC3280OptionalAttributeTypesCACert.crt */; }; + E7A94D3413D8A1AD001C5FEE /* RevokedsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415213D51D63008048AC /* RevokedsubCACert.crt */; }; + E7A94D3513D8A1AD001C5FEE /* RolloverfromPrintableStringtoUTF8StringCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415313D51D63008048AC /* RolloverfromPrintableStringtoUTF8StringCACert.crt */; }; + E7A94D3613D8A1AD001C5FEE /* SeparateCertificateandCRLKeysCA2CRLSigningCert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415413D51D63008048AC /* SeparateCertificateandCRLKeysCA2CRLSigningCert.crt */; }; + E7A94D3713D8A1AD001C5FEE /* SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415513D51D63008048AC /* SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt */; }; + E7A94D3813D8A1AD001C5FEE /* SeparateCertificateandCRLKeysCertificateSigningCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415613D51D63008048AC /* SeparateCertificateandCRLKeysCertificateSigningCACert.crt */; }; + E7A94D3913D8A1AD001C5FEE /* TrustAnchorRootCertificate.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415713D51D63008048AC /* TrustAnchorRootCertificate.crt */; }; + E7A94D3A13D8A1AD001C5FEE /* TwoCRLsCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415813D51D63008048AC /* TwoCRLsCACert.crt */; }; + E7A94D3B13D8A1AD001C5FEE /* UIDCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415913D51D63008048AC /* UIDCACert.crt */; }; + E7A94D3C13D8A1AD001C5FEE /* UTF8StringCaseInsensitiveMatchCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415A13D51D63008048AC /* UTF8StringCaseInsensitiveMatchCACert.crt */; }; + E7A94D3D13D8A1AD001C5FEE /* UTF8StringEncodedNamesCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415B13D51D63008048AC /* UTF8StringEncodedNamesCACert.crt */; }; + E7A94D3E13D8A1AD001C5FEE /* UnknownCRLEntryExtensionCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415C13D51D63008048AC /* UnknownCRLEntryExtensionCACert.crt */; }; + E7A94D3F13D8A1AD001C5FEE /* UnknownCRLExtensionCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415D13D51D63008048AC /* UnknownCRLExtensionCACert.crt */; }; + E7A94D4013D8A1AD001C5FEE /* UserNoticeQualifierTest15EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415E13D51D63008048AC /* UserNoticeQualifierTest15EE.crt */; }; + E7A94D4113D8A1AD001C5FEE /* UserNoticeQualifierTest16EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75415F13D51D63008048AC /* UserNoticeQualifierTest16EE.crt */; }; + E7A94D4213D8A1AD001C5FEE /* UserNoticeQualifierTest17EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416013D51D63008048AC /* UserNoticeQualifierTest17EE.crt */; }; + E7A94D4313D8A1AD001C5FEE /* UserNoticeQualifierTest18EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416113D51D63008048AC /* UserNoticeQualifierTest18EE.crt */; }; + E7A94D4413D8A1AD001C5FEE /* UserNoticeQualifierTest19EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416213D51D63008048AC /* UserNoticeQualifierTest19EE.crt */; }; + E7A94D4513D8A1AD001C5FEE /* ValidBasicSelfIssuedNewWithOldTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416313D51D63008048AC /* ValidBasicSelfIssuedNewWithOldTest3EE.crt */; }; + E7A94D4613D8A1AD001C5FEE /* ValidBasicSelfIssuedNewWithOldTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416413D51D63008048AC /* ValidBasicSelfIssuedNewWithOldTest4EE.crt */; }; + E7A94D4713D8A1AD001C5FEE /* ValidBasicSelfIssuedOldWithNewTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416513D51D63008048AC /* ValidBasicSelfIssuedOldWithNewTest1EE.crt */; }; + E7A94D4813D8A1AD001C5FEE /* ValidCertificatePathTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416613D51D63008048AC /* ValidCertificatePathTest1EE.crt */; }; + E7A94D4913D8A1AD001C5FEE /* ValidDNSnameConstraintsTest30EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416713D51D63008048AC /* ValidDNSnameConstraintsTest30EE.crt */; }; + E7A94D4A13D8A1AD001C5FEE /* ValidDNSnameConstraintsTest32EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416813D51D63008048AC /* ValidDNSnameConstraintsTest32EE.crt */; }; + E7A94D4B13D8A1AD001C5FEE /* ValidDNandRFC822nameConstraintsTest27EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416913D51D63008048AC /* ValidDNandRFC822nameConstraintsTest27EE.crt */; }; + E7A94D4C13D8A1AD001C5FEE /* ValidDNnameConstraintsTest11EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416A13D51D63008048AC /* ValidDNnameConstraintsTest11EE.crt */; }; + E7A94D4D13D8A1AD001C5FEE /* ValidDNnameConstraintsTest14EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416B13D51D63008048AC /* ValidDNnameConstraintsTest14EE.crt */; }; + E7A94D4E13D8A1AD001C5FEE /* ValidDNnameConstraintsTest18EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416C13D51D63008048AC /* ValidDNnameConstraintsTest18EE.crt */; }; + E7A94D4F13D8A1AD001C5FEE /* ValidDNnameConstraintsTest19EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416D13D51D63008048AC /* ValidDNnameConstraintsTest19EE.crt */; }; + E7A94D5013D8A1AD001C5FEE /* ValidDNnameConstraintsTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416E13D51D63008048AC /* ValidDNnameConstraintsTest1EE.crt */; }; + E7A94D5113D8A1AD001C5FEE /* ValidDNnameConstraintsTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75416F13D51D63008048AC /* ValidDNnameConstraintsTest4EE.crt */; }; + E7A94D5213D8A1AD001C5FEE /* ValidDNnameConstraintsTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417013D51D63008048AC /* ValidDNnameConstraintsTest5EE.crt */; }; + E7A94D5313D8A1AD001C5FEE /* ValidDNnameConstraintsTest6EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417113D51D63008048AC /* ValidDNnameConstraintsTest6EE.crt */; }; + E7A94D5413D8A1AD001C5FEE /* ValidDSAParameterInheritanceTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417213D51D63008048AC /* ValidDSAParameterInheritanceTest5EE.crt */; }; + E7A94D5513D8A1AD001C5FEE /* ValidDSASignaturesTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417313D51D63008048AC /* ValidDSASignaturesTest4EE.crt */; }; + E7A94D5613D8A1AD001C5FEE /* ValidGeneralizedTimenotAfterDateTest8EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417413D51D63008048AC /* ValidGeneralizedTimenotAfterDateTest8EE.crt */; }; + E7A94D5713D8A1AD001C5FEE /* ValidGeneralizedTimenotBeforeDateTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417513D51D63008048AC /* ValidGeneralizedTimenotBeforeDateTest4EE.crt */; }; + E7A94D5813D8A1AD001C5FEE /* ValidLongSerialNumberTest16EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417613D51D63008048AC /* ValidLongSerialNumberTest16EE.crt */; }; + E7A94D5913D8A1AD001C5FEE /* ValidLongSerialNumberTest17EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417713D51D63008048AC /* ValidLongSerialNumberTest17EE.crt */; }; + E7A94D5A13D8A1AD001C5FEE /* ValidNameChainingCapitalizationTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417813D51D63008048AC /* ValidNameChainingCapitalizationTest5EE.crt */; }; + E7A94D5B13D8A1AD001C5FEE /* ValidNameChainingWhitespaceTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417913D51D63008048AC /* ValidNameChainingWhitespaceTest3EE.crt */; }; + E7A94D5C13D8A1AD001C5FEE /* ValidNameChainingWhitespaceTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417A13D51D63008048AC /* ValidNameChainingWhitespaceTest4EE.crt */; }; + E7A94D5D13D8A1AD001C5FEE /* ValidNameUIDsTest6EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417B13D51D63008048AC /* ValidNameUIDsTest6EE.crt */; }; + E7A94D5E13D8A1AD001C5FEE /* ValidNegativeSerialNumberTest14EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417C13D51D63008048AC /* ValidNegativeSerialNumberTest14EE.crt */; }; + E7A94D5F13D8A1AD001C5FEE /* ValidPolicyMappingTest11EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417D13D51D63008048AC /* ValidPolicyMappingTest11EE.crt */; }; + E7A94D6013D8A1AD001C5FEE /* ValidPolicyMappingTest12EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417E13D51D63008048AC /* ValidPolicyMappingTest12EE.crt */; }; + E7A94D6113D8A1AD001C5FEE /* ValidPolicyMappingTest13EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75417F13D51D63008048AC /* ValidPolicyMappingTest13EE.crt */; }; + E7A94D6213D8A1AD001C5FEE /* ValidPolicyMappingTest14EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418013D51D63008048AC /* ValidPolicyMappingTest14EE.crt */; }; + E7A94D6313D8A1AD001C5FEE /* ValidPolicyMappingTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418113D51D63008048AC /* ValidPolicyMappingTest1EE.crt */; }; + E7A94D6413D8A1AD001C5FEE /* ValidPolicyMappingTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418213D51D63008048AC /* ValidPolicyMappingTest3EE.crt */; }; + E7A94D6513D8A1AD001C5FEE /* ValidPolicyMappingTest5EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418313D51D63008048AC /* ValidPolicyMappingTest5EE.crt */; }; + E7A94D6613D8A1AD001C5FEE /* ValidPolicyMappingTest6EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418413D51D63008048AC /* ValidPolicyMappingTest6EE.crt */; }; + E7A94D6713D8A1AD001C5FEE /* ValidPolicyMappingTest9EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418513D51D63008048AC /* ValidPolicyMappingTest9EE.crt */; }; + E7A94D6813D8A1AD001C5FEE /* ValidRFC3280MandatoryAttributeTypesTest7EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418613D51D63008048AC /* ValidRFC3280MandatoryAttributeTypesTest7EE.crt */; }; + E7A94D6913D8A1AD001C5FEE /* ValidRFC3280OptionalAttributeTypesTest8EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418713D51D63008048AC /* ValidRFC3280OptionalAttributeTypesTest8EE.crt */; }; + E7A94D6A13D8A1AD001C5FEE /* ValidRFC822nameConstraintsTest21EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418813D51D63008048AC /* ValidRFC822nameConstraintsTest21EE.crt */; }; + E7A94D6B13D8A1AD001C5FEE /* ValidRFC822nameConstraintsTest23EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418913D51D63008048AC /* ValidRFC822nameConstraintsTest23EE.crt */; }; + E7A94D6C13D8A1AD001C5FEE /* ValidRFC822nameConstraintsTest25EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418A13D51D63008048AC /* ValidRFC822nameConstraintsTest25EE.crt */; }; + E7A94D6D13D8A1AD001C5FEE /* ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418B13D51D63008048AC /* ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt */; }; + E7A94D6E13D8A1AD001C5FEE /* ValidSelfIssuedinhibitAnyPolicyTest7EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418C13D51D63008048AC /* ValidSelfIssuedinhibitAnyPolicyTest7EE.crt */; }; + E7A94D6F13D8A1AD001C5FEE /* ValidSelfIssuedinhibitAnyPolicyTest9EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418D13D51D63008048AC /* ValidSelfIssuedinhibitAnyPolicyTest9EE.crt */; }; + E7A94D7013D8A1AD001C5FEE /* ValidSelfIssuedinhibitPolicyMappingTest7EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418E13D51D63008048AC /* ValidSelfIssuedinhibitPolicyMappingTest7EE.crt */; }; + E7A94D7113D8A1AD001C5FEE /* ValidSelfIssuedpathLenConstraintTest15EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75418F13D51D63008048AC /* ValidSelfIssuedpathLenConstraintTest15EE.crt */; }; + E7A94D7213D8A1AD001C5FEE /* ValidSelfIssuedpathLenConstraintTest17EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419013D51D63008048AC /* ValidSelfIssuedpathLenConstraintTest17EE.crt */; }; + E7A94D7313D8A1AD001C5FEE /* ValidSelfIssuedrequireExplicitPolicyTest6EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419113D51D63008048AC /* ValidSelfIssuedrequireExplicitPolicyTest6EE.crt */; }; + E7A94D7413D8A1AD001C5FEE /* ValidURInameConstraintsTest34EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419213D51D63008048AC /* ValidURInameConstraintsTest34EE.crt */; }; + E7A94D7513D8A1AD001C5FEE /* ValidURInameConstraintsTest36EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419313D51D63008048AC /* ValidURInameConstraintsTest36EE.crt */; }; + E7A94D7613D8A1AD001C5FEE /* ValidUTF8StringCaseInsensitiveMatchTest11EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419413D51D63008048AC /* ValidUTF8StringCaseInsensitiveMatchTest11EE.crt */; }; + E7A94D7713D8A1AD001C5FEE /* ValidUTF8StringEncodedNamesTest9EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419513D51D63008048AC /* ValidUTF8StringEncodedNamesTest9EE.crt */; }; + E7A94D7813D8A1AD001C5FEE /* ValidUnknownNotCriticalCertificateExtensionTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419613D51D63008048AC /* ValidUnknownNotCriticalCertificateExtensionTest1EE.crt */; }; + E7A94D7913D8A1AD001C5FEE /* ValidbasicConstraintsNotCriticalTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419713D51D63008048AC /* ValidbasicConstraintsNotCriticalTest4EE.crt */; }; + E7A94D7A13D8A1AD001C5FEE /* ValidcRLIssuerTest28EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419813D51D63008048AC /* ValidcRLIssuerTest28EE.crt */; }; + E7A94D7B13D8A1AD001C5FEE /* ValidcRLIssuerTest29EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419913D51D63008048AC /* ValidcRLIssuerTest29EE.crt */; }; + E7A94D7C13D8A1AD001C5FEE /* ValidcRLIssuerTest30EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419A13D51D63008048AC /* ValidcRLIssuerTest30EE.crt */; }; + E7A94D7D13D8A1AD001C5FEE /* ValidcRLIssuerTest33EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419B13D51D63008048AC /* ValidcRLIssuerTest33EE.crt */; }; + E7A94D7E13D8A1AD001C5FEE /* ValidinhibitAnyPolicyTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419C13D51D63008048AC /* ValidinhibitAnyPolicyTest2EE.crt */; }; + E7A94D7F13D8A1AD001C5FEE /* ValidinhibitPolicyMappingTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419D13D51D63008048AC /* ValidinhibitPolicyMappingTest2EE.crt */; }; + E7A94D8013D8A1AD001C5FEE /* ValidinhibitPolicyMappingTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419E13D51D63008048AC /* ValidinhibitPolicyMappingTest4EE.crt */; }; + E7A94D8113D8A1AD001C5FEE /* ValidkeyUsageNotCriticalTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75419F13D51D63008048AC /* ValidkeyUsageNotCriticalTest3EE.crt */; }; + E7A94D8213D8A1AD001C5FEE /* ValidonlyContainsCACertsTest13EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541A013D51D63008048AC /* ValidonlyContainsCACertsTest13EE.crt */; }; + E7A94D8313D8A1AD001C5FEE /* ValidonlySomeReasonsTest18EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541A113D51D63008048AC /* ValidonlySomeReasonsTest18EE.crt */; }; + E7A94D8413D8A1AD001C5FEE /* ValidonlySomeReasonsTest19EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541A213D51D63008048AC /* ValidonlySomeReasonsTest19EE.crt */; }; + E7A94D8513D8A1AD001C5FEE /* ValidpathLenConstraintTest13EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541A313D51D63008048AC /* ValidpathLenConstraintTest13EE.crt */; }; + E7A94D8613D8A1AD001C5FEE /* ValidpathLenConstraintTest14EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541A413D51D63008048AC /* ValidpathLenConstraintTest14EE.crt */; }; + E7A94D8713D8A1AD001C5FEE /* ValidpathLenConstraintTest7EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541A513D51D63008048AC /* ValidpathLenConstraintTest7EE.crt */; }; + E7A94D8813D8A1AD001C5FEE /* ValidpathLenConstraintTest8EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541A613D51D63008048AC /* ValidpathLenConstraintTest8EE.crt */; }; + E7A94D8913D8A1AD001C5FEE /* Validpre2000UTCnotBeforeDateTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541A713D51D63008048AC /* Validpre2000UTCnotBeforeDateTest3EE.crt */; }; + E7A94D8A13D8A1AD001C5FEE /* ValidrequireExplicitPolicyTest1EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541A813D51D63008048AC /* ValidrequireExplicitPolicyTest1EE.crt */; }; + E7A94D8B13D8A1AD001C5FEE /* ValidrequireExplicitPolicyTest2EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541A913D51D63008048AC /* ValidrequireExplicitPolicyTest2EE.crt */; }; + E7A94D8C13D8A1AD001C5FEE /* ValidrequireExplicitPolicyTest4EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541AA13D51D63008048AC /* ValidrequireExplicitPolicyTest4EE.crt */; }; + E7A94D8D13D8A1AD001C5FEE /* WrongCRLCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541AB13D51D63008048AC /* WrongCRLCACert.crt */; }; + E7A94D8E13D8A1AD001C5FEE /* anyPolicyCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541AC13D51D63008048AC /* anyPolicyCACert.crt */; }; + E7A94D8F13D8A1AD001C5FEE /* basicConstraintsCriticalcAFalseCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541AD13D51D63008048AC /* basicConstraintsCriticalcAFalseCACert.crt */; }; + E7A94D9013D8A1AD001C5FEE /* basicConstraintsNotCriticalCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541AE13D51D63008048AC /* basicConstraintsNotCriticalCACert.crt */; }; + E7A94D9113D8A1AD001C5FEE /* basicConstraintsNotCriticalcAFalseCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541AF13D51D63008048AC /* basicConstraintsNotCriticalcAFalseCACert.crt */; }; + E7A94D9213D8A1AD001C5FEE /* deltaCRLCA1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541B013D51D63008048AC /* deltaCRLCA1Cert.crt */; }; + E7A94D9313D8A1AD001C5FEE /* deltaCRLCA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541B113D51D63008048AC /* deltaCRLCA2Cert.crt */; }; + E7A94D9413D8A1AD001C5FEE /* deltaCRLCA3Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541B213D51D63008048AC /* deltaCRLCA3Cert.crt */; }; + E7A94D9513D8A1AD001C5FEE /* deltaCRLIndicatorNoBaseCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541B313D51D63008048AC /* deltaCRLIndicatorNoBaseCACert.crt */; }; + E7A94D9613D8A1AD001C5FEE /* distributionPoint1CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541B413D51D63008048AC /* distributionPoint1CACert.crt */; }; + E7A94D9713D8A1AD001C5FEE /* distributionPoint2CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541B513D51D63008048AC /* distributionPoint2CACert.crt */; }; + E7A94D9813D8A1AD001C5FEE /* indirectCRLCA1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541B613D51D63008048AC /* indirectCRLCA1Cert.crt */; }; + E7A94D9913D8A1AD001C5FEE /* indirectCRLCA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541B713D51D63008048AC /* indirectCRLCA2Cert.crt */; }; + E7A94D9A13D8A1AD001C5FEE /* indirectCRLCA3Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541B813D51D63008048AC /* indirectCRLCA3Cert.crt */; }; + E7A94D9B13D8A1AD001C5FEE /* indirectCRLCA3cRLIssuerCert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541B913D51D63008048AC /* indirectCRLCA3cRLIssuerCert.crt */; }; + E7A94D9C13D8A1AD001C5FEE /* indirectCRLCA4Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541BA13D51D63008048AC /* indirectCRLCA4Cert.crt */; }; + E7A94D9D13D8A1AD001C5FEE /* indirectCRLCA4cRLIssuerCert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541BB13D51D63008048AC /* indirectCRLCA4cRLIssuerCert.crt */; }; + E7A94D9E13D8A1AD001C5FEE /* indirectCRLCA5Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541BC13D51D63008048AC /* indirectCRLCA5Cert.crt */; }; + E7A94D9F13D8A1AD001C5FEE /* indirectCRLCA6Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541BD13D51D63008048AC /* indirectCRLCA6Cert.crt */; }; + E7A94DA013D8A1AD001C5FEE /* inhibitAnyPolicy0CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541BE13D51D63008048AC /* inhibitAnyPolicy0CACert.crt */; }; + E7A94DA113D8A1AD001C5FEE /* inhibitAnyPolicy1CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541BF13D51D63008048AC /* inhibitAnyPolicy1CACert.crt */; }; + E7A94DA213D8A1AD001C5FEE /* inhibitAnyPolicy1SelfIssuedCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541C013D51D63008048AC /* inhibitAnyPolicy1SelfIssuedCACert.crt */; }; + E7A94DA313D8A1AD001C5FEE /* inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541C113D51D63008048AC /* inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt */; }; + E7A94DA413D8A1AD001C5FEE /* inhibitAnyPolicy1subCA1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541C213D51D63008048AC /* inhibitAnyPolicy1subCA1Cert.crt */; }; + E7A94DA513D8A1AD001C5FEE /* inhibitAnyPolicy1subCA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541C313D51D63008048AC /* inhibitAnyPolicy1subCA2Cert.crt */; }; + E7A94DA613D8A1AD001C5FEE /* inhibitAnyPolicy1subCAIAP5Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541C413D51D63008048AC /* inhibitAnyPolicy1subCAIAP5Cert.crt */; }; + E7A94DA713D8A1AD001C5FEE /* inhibitAnyPolicy1subsubCA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541C513D51D63008048AC /* inhibitAnyPolicy1subsubCA2Cert.crt */; }; + E7A94DA813D8A1AD001C5FEE /* inhibitAnyPolicy5CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541C613D51D63008048AC /* inhibitAnyPolicy5CACert.crt */; }; + E7A94DA913D8A1AD001C5FEE /* inhibitAnyPolicy5subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541C713D51D63008048AC /* inhibitAnyPolicy5subCACert.crt */; }; + E7A94DAA13D8A1AD001C5FEE /* inhibitAnyPolicy5subsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541C813D51D63008048AC /* inhibitAnyPolicy5subsubCACert.crt */; }; + E7A94DAB13D8A1AD001C5FEE /* inhibitAnyPolicyTest3EE.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541C913D51D63008048AC /* inhibitAnyPolicyTest3EE.crt */; }; + E7A94DAC13D8A1AD001C5FEE /* inhibitPolicyMapping0CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541CA13D51D63008048AC /* inhibitPolicyMapping0CACert.crt */; }; + E7A94DAD13D8A1AD001C5FEE /* inhibitPolicyMapping0subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541CB13D51D63008048AC /* inhibitPolicyMapping0subCACert.crt */; }; + E7A94DAE13D8A1AD001C5FEE /* inhibitPolicyMapping1P12CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541CC13D51D63008048AC /* inhibitPolicyMapping1P12CACert.crt */; }; + E7A94DAF13D8A1AD001C5FEE /* inhibitPolicyMapping1P12subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541CD13D51D63008048AC /* inhibitPolicyMapping1P12subCACert.crt */; }; + E7A94DB013D8A1AD001C5FEE /* inhibitPolicyMapping1P12subCAIPM5Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541CE13D51D63008048AC /* inhibitPolicyMapping1P12subCAIPM5Cert.crt */; }; + E7A94DB113D8A1AD001C5FEE /* inhibitPolicyMapping1P12subsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541CF13D51D63008048AC /* inhibitPolicyMapping1P12subsubCACert.crt */; }; + E7A94DB213D8A1AD001C5FEE /* inhibitPolicyMapping1P12subsubCAIPM5Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541D013D51D63008048AC /* inhibitPolicyMapping1P12subsubCAIPM5Cert.crt */; }; + E7A94DB313D8A1AD001C5FEE /* inhibitPolicyMapping1P1CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541D113D51D63008048AC /* inhibitPolicyMapping1P1CACert.crt */; }; + E7A94DB413D8A1AD001C5FEE /* inhibitPolicyMapping1P1SelfIssuedCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541D213D51D63008048AC /* inhibitPolicyMapping1P1SelfIssuedCACert.crt */; }; + E7A94DB513D8A1AD001C5FEE /* inhibitPolicyMapping1P1SelfIssuedsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541D313D51D63008048AC /* inhibitPolicyMapping1P1SelfIssuedsubCACert.crt */; }; + E7A94DB613D8A1AD001C5FEE /* inhibitPolicyMapping1P1subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541D413D51D63008048AC /* inhibitPolicyMapping1P1subCACert.crt */; }; + E7A94DB713D8A1AD001C5FEE /* inhibitPolicyMapping1P1subsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541D513D51D63008048AC /* inhibitPolicyMapping1P1subsubCACert.crt */; }; + E7A94DB813D8A1AD001C5FEE /* inhibitPolicyMapping5CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541D613D51D63008048AC /* inhibitPolicyMapping5CACert.crt */; }; + E7A94DB913D8A1AD001C5FEE /* inhibitPolicyMapping5subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541D713D51D63008048AC /* inhibitPolicyMapping5subCACert.crt */; }; + E7A94DBA13D8A1AD001C5FEE /* inhibitPolicyMapping5subsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541D813D51D63008048AC /* inhibitPolicyMapping5subsubCACert.crt */; }; + E7A94DBB13D8A1AD001C5FEE /* inhibitPolicyMapping5subsubsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541D913D51D63008048AC /* inhibitPolicyMapping5subsubsubCACert.crt */; }; + E7A94DBC13D8A1AD001C5FEE /* keyUsageCriticalcRLSignFalseCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541DA13D51D63008048AC /* keyUsageCriticalcRLSignFalseCACert.crt */; }; + E7A94DBD13D8A1AD001C5FEE /* keyUsageCriticalkeyCertSignFalseCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541DB13D51D63008048AC /* keyUsageCriticalkeyCertSignFalseCACert.crt */; }; + E7A94DBE13D8A1AD001C5FEE /* keyUsageNotCriticalCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541DC13D51D63008048AC /* keyUsageNotCriticalCACert.crt */; }; + E7A94DBF13D8A1AD001C5FEE /* keyUsageNotCriticalcRLSignFalseCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541DD13D51D63008048AC /* keyUsageNotCriticalcRLSignFalseCACert.crt */; }; + E7A94DC013D8A1AD001C5FEE /* keyUsageNotCriticalkeyCertSignFalseCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541DE13D51D63008048AC /* keyUsageNotCriticalkeyCertSignFalseCACert.crt */; }; + E7A94DC113D8A1AD001C5FEE /* nameConstraintsDN1CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541DF13D51D63008048AC /* nameConstraintsDN1CACert.crt */; }; + E7A94DC213D8A1AD001C5FEE /* nameConstraintsDN1SelfIssuedCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541E013D51D63008048AC /* nameConstraintsDN1SelfIssuedCACert.crt */; }; + E7A94DC313D8A1AD001C5FEE /* nameConstraintsDN1subCA1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541E113D51D63008048AC /* nameConstraintsDN1subCA1Cert.crt */; }; + E7A94DC413D8A1AD001C5FEE /* nameConstraintsDN1subCA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541E213D51D63008048AC /* nameConstraintsDN1subCA2Cert.crt */; }; + E7A94DC513D8A1AD001C5FEE /* nameConstraintsDN1subCA3Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541E313D51D63008048AC /* nameConstraintsDN1subCA3Cert.crt */; }; + E7A94DC613D8A1AD001C5FEE /* nameConstraintsDN2CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541E413D51D63008048AC /* nameConstraintsDN2CACert.crt */; }; + E7A94DC713D8A1AD001C5FEE /* nameConstraintsDN3CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541E513D51D63008048AC /* nameConstraintsDN3CACert.crt */; }; + E7A94DC813D8A1AD001C5FEE /* nameConstraintsDN3subCA1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541E613D51D63008048AC /* nameConstraintsDN3subCA1Cert.crt */; }; + E7A94DC913D8A1AD001C5FEE /* nameConstraintsDN3subCA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541E713D51D63008048AC /* nameConstraintsDN3subCA2Cert.crt */; }; + E7A94DCA13D8A1AD001C5FEE /* nameConstraintsDN4CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541E813D51D63008048AC /* nameConstraintsDN4CACert.crt */; }; + E7A94DCB13D8A1AD001C5FEE /* nameConstraintsDN5CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541E913D51D63008048AC /* nameConstraintsDN5CACert.crt */; }; + E7A94DCC13D8A1AD001C5FEE /* nameConstraintsDNS1CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541EA13D51D63008048AC /* nameConstraintsDNS1CACert.crt */; }; + E7A94DCD13D8A1AD001C5FEE /* nameConstraintsDNS2CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541EB13D51D63008048AC /* nameConstraintsDNS2CACert.crt */; }; + E7A94DCE13D8A1AD001C5FEE /* nameConstraintsRFC822CA1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541EC13D51D63008048AC /* nameConstraintsRFC822CA1Cert.crt */; }; + E7A94DCF13D8A1AD001C5FEE /* nameConstraintsRFC822CA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541ED13D51D63008048AC /* nameConstraintsRFC822CA2Cert.crt */; }; + E7A94DD013D8A1AD001C5FEE /* nameConstraintsRFC822CA3Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541EE13D51D63008048AC /* nameConstraintsRFC822CA3Cert.crt */; }; + E7A94DD113D8A1AD001C5FEE /* nameConstraintsURI1CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541EF13D51D63008048AC /* nameConstraintsURI1CACert.crt */; }; + E7A94DD213D8A1AD001C5FEE /* nameConstraintsURI2CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541F013D51D63008048AC /* nameConstraintsURI2CACert.crt */; }; + E7A94DD313D8A1AD001C5FEE /* onlyContainsAttributeCertsCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541F113D51D63008048AC /* onlyContainsAttributeCertsCACert.crt */; }; + E7A94DD413D8A1AD001C5FEE /* onlyContainsCACertsCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541F213D51D63008048AC /* onlyContainsCACertsCACert.crt */; }; + E7A94DD513D8A1AD001C5FEE /* onlyContainsUserCertsCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541F313D51D63008048AC /* onlyContainsUserCertsCACert.crt */; }; + E7A94DD613D8A1AD001C5FEE /* onlySomeReasonsCA1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541F413D51D63008048AC /* onlySomeReasonsCA1Cert.crt */; }; + E7A94DD713D8A1AD001C5FEE /* onlySomeReasonsCA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541F513D51D63008048AC /* onlySomeReasonsCA2Cert.crt */; }; + E7A94DD813D8A1AD001C5FEE /* onlySomeReasonsCA3Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541F613D51D63008048AC /* onlySomeReasonsCA3Cert.crt */; }; + E7A94DD913D8A1AD001C5FEE /* onlySomeReasonsCA4Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541F713D51D63008048AC /* onlySomeReasonsCA4Cert.crt */; }; + E7A94DDA13D8A1AD001C5FEE /* pathLenConstraint0CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541F813D51D63008048AC /* pathLenConstraint0CACert.crt */; }; + E7A94DDB13D8A1AD001C5FEE /* pathLenConstraint0SelfIssuedCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541F913D51D63008048AC /* pathLenConstraint0SelfIssuedCACert.crt */; }; + E7A94DDC13D8A1AD001C5FEE /* pathLenConstraint0subCA2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541FA13D51D63008048AC /* pathLenConstraint0subCA2Cert.crt */; }; + E7A94DDD13D8A1AD001C5FEE /* pathLenConstraint0subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541FB13D51D63008048AC /* pathLenConstraint0subCACert.crt */; }; + E7A94DDE13D8A1AD001C5FEE /* pathLenConstraint1CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541FC13D51D63008048AC /* pathLenConstraint1CACert.crt */; }; + E7A94DDF13D8A1AE001C5FEE /* pathLenConstraint1SelfIssuedCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541FD13D51D63008048AC /* pathLenConstraint1SelfIssuedCACert.crt */; }; + E7A94DE013D8A1AE001C5FEE /* pathLenConstraint1SelfIssuedsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541FE13D51D63008048AC /* pathLenConstraint1SelfIssuedsubCACert.crt */; }; + E7A94DE113D8A1AE001C5FEE /* pathLenConstraint1subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7541FF13D51D63008048AC /* pathLenConstraint1subCACert.crt */; }; + E7A94DE213D8A1AE001C5FEE /* pathLenConstraint6CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420013D51D64008048AC /* pathLenConstraint6CACert.crt */; }; + E7A94DE313D8A1AE001C5FEE /* pathLenConstraint6subCA0Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420113D51D64008048AC /* pathLenConstraint6subCA0Cert.crt */; }; + E7A94DE413D8A1AE001C5FEE /* pathLenConstraint6subCA1Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420213D51D64008048AC /* pathLenConstraint6subCA1Cert.crt */; }; + E7A94DE513D8A1AE001C5FEE /* pathLenConstraint6subCA4Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420313D51D64008048AC /* pathLenConstraint6subCA4Cert.crt */; }; + E7A94DE613D8A1AE001C5FEE /* pathLenConstraint6subsubCA00Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420413D51D64008048AC /* pathLenConstraint6subsubCA00Cert.crt */; }; + E7A94DE713D8A1AE001C5FEE /* pathLenConstraint6subsubCA11Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420513D51D64008048AC /* pathLenConstraint6subsubCA11Cert.crt */; }; + E7A94DE813D8A1AE001C5FEE /* pathLenConstraint6subsubCA41Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420613D51D64008048AC /* pathLenConstraint6subsubCA41Cert.crt */; }; + E7A94DE913D8A1AE001C5FEE /* pathLenConstraint6subsubsubCA11XCert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420713D51D64008048AC /* pathLenConstraint6subsubsubCA11XCert.crt */; }; + E7A94DEA13D8A1AE001C5FEE /* pathLenConstraint6subsubsubCA41XCert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420813D51D64008048AC /* pathLenConstraint6subsubsubCA41XCert.crt */; }; + E7A94DEB13D8A1AE001C5FEE /* pre2000CRLnextUpdateCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420913D51D64008048AC /* pre2000CRLnextUpdateCACert.crt */; }; + E7A94DEC13D8A1AE001C5FEE /* requireExplicitPolicy0CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420A13D51D64008048AC /* requireExplicitPolicy0CACert.crt */; }; + E7A94DED13D8A1AE001C5FEE /* requireExplicitPolicy0subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420B13D51D64008048AC /* requireExplicitPolicy0subCACert.crt */; }; + E7A94DEE13D8A1AE001C5FEE /* requireExplicitPolicy0subsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420C13D51D64008048AC /* requireExplicitPolicy0subsubCACert.crt */; }; + E7A94DEF13D8A1AE001C5FEE /* requireExplicitPolicy0subsubsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420D13D51D64008048AC /* requireExplicitPolicy0subsubsubCACert.crt */; }; + E7A94DF013D8A1AE001C5FEE /* requireExplicitPolicy10CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420E13D51D64008048AC /* requireExplicitPolicy10CACert.crt */; }; + E7A94DF113D8A1AE001C5FEE /* requireExplicitPolicy10subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75420F13D51D64008048AC /* requireExplicitPolicy10subCACert.crt */; }; + E7A94DF213D8A1AE001C5FEE /* requireExplicitPolicy10subsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421013D51D64008048AC /* requireExplicitPolicy10subsubCACert.crt */; }; + E7A94DF313D8A1AE001C5FEE /* requireExplicitPolicy10subsubsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421113D51D64008048AC /* requireExplicitPolicy10subsubsubCACert.crt */; }; + E7A94DF413D8A1AE001C5FEE /* requireExplicitPolicy2CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421213D51D64008048AC /* requireExplicitPolicy2CACert.crt */; }; + E7A94DF513D8A1AE001C5FEE /* requireExplicitPolicy2SelfIssuedCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421313D51D64008048AC /* requireExplicitPolicy2SelfIssuedCACert.crt */; }; + E7A94DF613D8A1AE001C5FEE /* requireExplicitPolicy2SelfIssuedsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421413D51D64008048AC /* requireExplicitPolicy2SelfIssuedsubCACert.crt */; }; + E7A94DF713D8A1AE001C5FEE /* requireExplicitPolicy2subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421513D51D64008048AC /* requireExplicitPolicy2subCACert.crt */; }; + E7A94DF813D8A1AE001C5FEE /* requireExplicitPolicy4CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421613D51D64008048AC /* requireExplicitPolicy4CACert.crt */; }; + E7A94DF913D8A1AE001C5FEE /* requireExplicitPolicy4subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421713D51D64008048AC /* requireExplicitPolicy4subCACert.crt */; }; + E7A94DFA13D8A1AE001C5FEE /* requireExplicitPolicy4subsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421813D51D64008048AC /* requireExplicitPolicy4subsubCACert.crt */; }; + E7A94DFB13D8A1AE001C5FEE /* requireExplicitPolicy4subsubsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421913D51D64008048AC /* requireExplicitPolicy4subsubsubCACert.crt */; }; + E7A94DFC13D8A1AE001C5FEE /* requireExplicitPolicy5CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421A13D51D64008048AC /* requireExplicitPolicy5CACert.crt */; }; + E7A94DFD13D8A1AE001C5FEE /* requireExplicitPolicy5subCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421B13D51D64008048AC /* requireExplicitPolicy5subCACert.crt */; }; + E7A94DFE13D8A1AE001C5FEE /* requireExplicitPolicy5subsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421C13D51D64008048AC /* requireExplicitPolicy5subsubCACert.crt */; }; + E7A94DFF13D8A1AE001C5FEE /* requireExplicitPolicy5subsubsubCACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421D13D51D64008048AC /* requireExplicitPolicy5subsubsubCACert.crt */; }; + E7A94E0013D8A1AE001C5FEE /* requireExplicitPolicy7CACert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421E13D51D64008048AC /* requireExplicitPolicy7CACert.crt */; }; + E7A94E0113D8A1AE001C5FEE /* requireExplicitPolicy7subCARE2Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75421F13D51D64008048AC /* requireExplicitPolicy7subCARE2Cert.crt */; }; + E7A94E0213D8A1AE001C5FEE /* requireExplicitPolicy7subsubCARE2RE4Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75422013D51D64008048AC /* requireExplicitPolicy7subsubCARE2RE4Cert.crt */; }; + E7A94E0313D8A1AE001C5FEE /* requireExplicitPolicy7subsubsubCARE2RE4Cert.crt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C75422113D51D64008048AC /* requireExplicitPolicy7subsubsubCARE2RE4Cert.crt */; }; + E7B00700170B581D00B27966 /* Security.exp-in in Sources */ = {isa = PBXBuildFile; fileRef = 4CB7405F0A47498100D641BB /* Security.exp-in */; }; + E7B01B7716572123000485F1 /* libSecureObjectSync.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60888B155C943D00A0904F /* libSecureObjectSync.a */; }; + E7B01BC3166594AB000485F1 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 52DE81741636347500F49F0C /* main.m */; }; + E7B01BC4166594AB000485F1 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 52DE81781636347600F49F0C /* AppDelegate.m */; }; + E7B01BC5166594AB000485F1 /* FirstViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52DE81871636347600F49F0C /* FirstViewController.m */; }; + E7B01BC6166594AB000485F1 /* ToolsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52DE818E1636347600F49F0C /* ToolsViewController.m */; }; + E7B01BC8166594AB000485F1 /* KCATableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52DE819B163636B900F49F0C /* KCATableViewController.m */; }; + E7B01BC9166594AB000485F1 /* KeychainItemCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 52DE819E16363C1A00F49F0C /* KeychainItemCell.m */; }; + E7B01BCA166594AB000485F1 /* MyKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 5264FB4D163674B50005D258 /* MyKeychain.m */; }; + E7B01BCB166594AB000485F1 /* KCAItemDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52CD69FA16384C2000961848 /* KCAItemDetailViewController.m */; }; + E7B01BCC166594AB000485F1 /* NewPasswordViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52704B801638F610007FEBB0 /* NewPasswordViewController.m */; }; + E7B01BCD166594AB000485F1 /* EditItemViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52704B83163905EE007FEBB0 /* EditItemViewController.m */; }; + E7B01BCE166594AB000485F1 /* DeviceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52F63A1F1659F04E0076D2DE /* DeviceViewController.m */; }; + E7B01BCF166594AB000485F1 /* DeviceTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 529990531661BA2600C297A2 /* DeviceTableViewController.m */; }; + E7B01BD0166594AB000485F1 /* DeviceItemCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 529990561661BADF00C297A2 /* DeviceItemCell.m */; }; + E7B01BD2166594AB000485F1 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF730310EF9CDE300E17471 /* CFNetwork.framework */; }; + E7B01BD3166594AB000485F1 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; + E7B01BD4166594AB000485F1 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB740680A4749C800D641BB /* libsqlite3.dylib */; }; + E7B01BD5166594AB000485F1 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60F1C409BE27E300B4040C /* CoreFoundation.framework */; }; + E7B01BD6166594AB000485F1 /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D690911652E06A0079537A /* libMobileGestalt.dylib */; }; + E7B01BD7166594AB000485F1 /* libsecurityd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F7F66514D77DF700F88A12 /* libsecurityd.a */; }; + E7B01BD9166594AB000485F1 /* libSOSRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60888D155C943D00A0904F /* libSOSRegressions.a */; }; + E7B01BDA166594AB000485F1 /* libutilitiesRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E7E0D8FE158FAB3B002CA176 /* libutilitiesRegressions.a */; }; + E7B01BDB166594AB000485F1 /* libSecureObjectSync.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60888B155C943D00A0904F /* libSecureObjectSync.a */; }; + E7B01BDC166594AB000485F1 /* libregressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E710C708133192EA00F85568 /* libregressions.a */; }; + E7B01BDD166594AB000485F1 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2FEC5115755D710008BE39 /* libutilities.a */; }; + E7B01BDE166594AB000485F1 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE411314471B000DE34E /* UIKit.framework */; }; + E7B01BDF166594AB000485F1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + E7B01BE0166594AB000485F1 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE451314471B000DE34E /* CoreGraphics.framework */; }; + E7B01BE1166594AB000485F1 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 520C98E7162485CA00A7C80B /* QuartzCore.framework */; }; + E7B01BE2166594AB000485F1 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52B35B051623753000B97D06 /* Security.framework */; }; + E7B01BE4166594AB000485F1 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 52DE817A1636347600F49F0C /* Default.png */; }; + E7B01BE5166594AB000485F1 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 52DE817C1636347600F49F0C /* Default@2x.png */; }; + E7B01BE6166594AB000485F1 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 52DE817E1636347600F49F0C /* Default-568h@2x.png */; }; + E7B01BE9166594AB000485F1 /* first.png in Resources */ = {isa = PBXBuildFile; fileRef = 52DE81891636347600F49F0C /* first.png */; }; + E7B01BEA166594AB000485F1 /* first@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 52DE818B1636347600F49F0C /* first@2x.png */; }; + E7B01BEB166594AB000485F1 /* second.png in Resources */ = {isa = PBXBuildFile; fileRef = 52DE81901636347600F49F0C /* second.png */; }; + E7B01BEC166594AB000485F1 /* second@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 52DE81921636347600F49F0C /* second@2x.png */; }; + E7B01BED166594AB000485F1 /* KeychainKeys.png in Resources */ = {isa = PBXBuildFile; fileRef = 52704B7D1638F4EB007FEBB0 /* KeychainKeys.png */; }; + E7B01BEE166594AB000485F1 /* Keychain-Entitlements.plist in Resources */ = {isa = PBXBuildFile; fileRef = 52704B871639193F007FEBB0 /* Keychain-Entitlements.plist */; }; + E7D690921652E06A0079537A /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D690911652E06A0079537A /* libMobileGestalt.dylib */; }; + E7D690A11652E07B0079537A /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D690911652E06A0079537A /* libMobileGestalt.dylib */; }; + E7D690A21652E0870079537A /* libMobileGestalt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D690911652E06A0079537A /* libMobileGestalt.dylib */; }; + E7E0D902158FAFED002CA176 /* libutilitiesRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E7E0D8FE158FAB3B002CA176 /* libutilitiesRegressions.a */; }; + E7E0D903158FAFF7002CA176 /* libutilitiesRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E7E0D8FE158FAB3B002CA176 /* libutilitiesRegressions.a */; }; + E7FEEEF81332B7F70025EB06 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB740680A4749C800D641BB /* libsqlite3.dylib */; }; + E7FEEEF91332B80A0025EB06 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C60F1C409BE27E300B4040C /* CoreFoundation.framework */; }; + 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 */; }; /* End PBXBuildFile section */ /* Begin PBXBuildRule section */ - E778BFB91717461800302C14 /* PBXBuildRule */ = { + E7B006FF170B56E700B27966 /* PBXBuildRule */ = { isa = PBXBuildRule; compilerSpec = com.apple.compilers.proxy.script; filePatterns = "*.exp-in"; @@ -475,5603 +1416,6809 @@ /* End PBXBuildRule section */ /* Begin PBXContainerItemProxy section */ - 0C4EAE711766865000773425 /* PBXContainerItemProxy */ = { + 051D8FD6194913E700AEF66A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 051D8F82194913E500AEF66A /* Security.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 0C0BDB5F175687EC00BC1A7E; - remoteInfo = libsecdRegressions; + remoteGlobalIDString = 1807384B146D0D4E00F05C24; + remoteInfo = Security; }; - 0C4EAE7817668DFF00773425 /* PBXContainerItemProxy */ = { + 051D8FD8194913E700AEF66A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 0C0BDB55175687EC00BC1A7E; - remoteInfo = libsecdRegressions; + containerPortal = 051D8F82194913E500AEF66A /* Security.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 182BB568146F4DCA000BF1F3; + remoteInfo = csparser; }; - 0C6C632D15D19D2900BC68CD /* PBXContainerItemProxy */ = { + 051D8FDA194913E700AEF66A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 0CCA415815C89E8B002AEC4C; - remoteInfo = libsecurity_ssl_regressions; + containerPortal = 051D8F82194913E500AEF66A /* Security.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 18FE67EA1471A3AA00A2CBE3; + remoteInfo = copyHeaders; }; - 0C6C642D15D5ADC900BC68CD /* PBXContainerItemProxy */ = { + 051D8FDC194913E700AEF66A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 0CC9A7EF146DF66000C18F89; - remoteInfo = tlsnke; + containerPortal = 051D8F82194913E500AEF66A /* Security.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 18270ED614CF282600B05E7F; + remoteInfo = secd; }; - 0C6C642F15D5AE4C00BC68CD /* PBXContainerItemProxy */ = { + 051D8FDE194913E700AEF66A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 0C1C92EF15C8AC81007D377B; - remoteInfo = libsecurity_ssl_kext; + containerPortal = 051D8F82194913E500AEF66A /* Security.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 0CC3352D16C1ED8000399E53; + remoteInfo = secdtests; }; - 0C6D77CC15C8B66000BB4405 /* PBXContainerItemProxy */ = { + 051D8FE0194913E700AEF66A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */; + containerPortal = 051D8F82194913E500AEF66A /* Security.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 0C1C933A15C8AC81007D377B; - remoteInfo = libsecurity_ssl_kext; + remoteGlobalIDString = 0C6C630B15D193C800BC68CD; + remoteInfo = sectests; }; - 0C6D77CE15C8B66000BB4405 /* PBXContainerItemProxy */ = { + 051D8FE2194913E700AEF66A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */; + containerPortal = 051D8F82194913E500AEF66A /* Security.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 0CCA415915C89E8B002AEC4C; - remoteInfo = libsecurity_ssl_regressions; + remoteGlobalIDString = 18F234EB15C9F9A600060520; + remoteInfo = authd; }; - 0C6D77D015C8B66000BB4405 /* PBXContainerItemProxy */ = { + 051D8FE4194913E700AEF66A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */; + containerPortal = 051D8F82194913E500AEF66A /* Security.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 0CCA42C915C8A387002AEC4C; - remoteInfo = dtlsEchoClient; + remoteGlobalIDString = 5214700616977CB800DF0DB3; + remoteInfo = CloudKeychainProxy; }; - 0C6D77D215C8B66000BB4405 /* PBXContainerItemProxy */ = { + 051D8FE6194913E700AEF66A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */; + containerPortal = 051D8F82194913E500AEF66A /* Security.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 0CCA42D715C8A395002AEC4C; - remoteInfo = dtlsEchoServer; + remoteGlobalIDString = 4CB23B46169F5873003A0131; + remoteInfo = security2; }; - 0C6D77E815C8C06600BB4405 /* PBXContainerItemProxy */ = { + 051D8FE8194913E700AEF66A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */; + containerPortal = 051D8F82194913E500AEF66A /* Security.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 0CC9A7F0146DF66000C18F89; - remoteInfo = tlsnke; + remoteGlobalIDString = 4CC7A7B316CC2A84003E10C1; + remoteInfo = "Cloud Keychain Utility"; }; - 0C6D77EA15C8C06600BB4405 /* PBXContainerItemProxy */ = { + 051D8FEA194913E700AEF66A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */; + containerPortal = 051D8F82194913E500AEF66A /* Security.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 0CE08A73148FF2C6000473EB; - remoteInfo = tlsnketest; + remoteGlobalIDString = 4C96F7C116D6DF8300D3B39D; + remoteInfo = "Keychain Circle Notification"; }; - 0C6D77EC15C8C06600BB4405 /* PBXContainerItemProxy */ = { + 051D8FEC194913E700AEF66A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */; + containerPortal = 051D8F82194913E500AEF66A /* Security.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 0CDF46A014DC794300FFE2FD; - remoteInfo = tlssocket; + remoteGlobalIDString = 72756BFE175D485D00F52070; + remoteInfo = cloud_keychain_diagnose; }; - 0CBD50B216C325F000713B6C /* PBXContainerItemProxy */ = { + 05EF68A41949143A007958C3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; + containerPortal = 05EF687F1949143A007958C3 /* securityd.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 0CBD509716C3242200713B6C; - remoteInfo = libsecurity_keychain_regressions; + remoteGlobalIDString = AA6D4B8A0E6F3BB80050206D; + remoteInfo = securityd; }; - 0CBD50C616C3260D00713B6C /* PBXContainerItemProxy */ = { + 05EF68AD19491453007958C3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 0CBD500016C3242200713B6C; - remoteInfo = libsecurity_keychain_regressions; + containerPortal = 05EF68A919491453007958C3 /* SecurityTool.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = AACD2CBE0E12D81D00D485EA; + remoteInfo = security; }; - 0CC3350916C1ED8000399E53 /* PBXContainerItemProxy */ = { + 05EF68B3194914C2007958C3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 051D8F82194913E500AEF66A /* Security.xcodeproj */; proxyType = 1; - remoteGlobalIDString = E702E73514E1F3EA00CDE635; - remoteInfo = libSecureObjectSync; + remoteGlobalIDString = 4CE4729E16D833FD009070D1; + remoteInfo = Security_temporary_UI; }; - 0CC3350B16C1ED8000399E53 /* PBXContainerItemProxy */ = { + 05EF68B919491577007958C3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; + containerPortal = 051D8F82194913E500AEF66A /* Security.xcodeproj */; proxyType = 1; - remoteGlobalIDString = E742A09B14E343E70052A486; - remoteInfo = utilities; + remoteGlobalIDString = 186F778814E59FB200434E1F; + remoteInfo = Security_frameworks; }; - 0CC3350D16C1ED8000399E53 /* PBXContainerItemProxy */ = { + 05EF68BF194915B6007958C3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 051D8F82194913E500AEF66A /* Security.xcodeproj */; proxyType = 1; - remoteGlobalIDString = E702E75714E1F48800CDE635; - remoteInfo = libSOSRegressions; + remoteGlobalIDString = 186F778C14E59FDA00434E1F; + remoteInfo = Security_executables; }; - 0CC3351116C1ED8000399E53 /* PBXContainerItemProxy */ = { + 05EF68C51949160C007958C3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 051D8F82194913E500AEF66A /* Security.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 18D4043414CE0CF300A2BE4E; - remoteInfo = libsecurity; + remoteGlobalIDString = 0C6C642915D5ADB500BC68CD; + remoteInfo = Security_kexts; }; - 0CC3351316C1ED8000399E53 /* PBXContainerItemProxy */ = { + 05EF68C71949166E007958C3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 05EF687F1949143A007958C3 /* securityd.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 18270F5414CF651900B05E7F; - remoteInfo = libsecipc_client; + remoteGlobalIDString = AA6D4B890E6F3BB80050206D; + remoteInfo = securityd; }; - 0CC3351516C1ED8000399E53 /* PBXContainerItemProxy */ = { + 05EF68C91949167B007958C3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 05EF68A919491453007958C3 /* SecurityTool.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 186CDD0E14CA116C00AF9171; - remoteInfo = libSecItemShimOSX; + remoteGlobalIDString = AACD2C7B0E12D81D00D485EA; + remoteInfo = security; }; - 0CC3355F16C1EF5D00399E53 /* PBXContainerItemProxy */ = { + 0C0BDB811756A1D700BC1A7E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 0CC3355B16C1EF5D00399E53 /* regressions.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 2; - remoteGlobalIDString = E710C6FE133192E900F85568; - remoteInfo = regressions; + remoteGlobalIDString = 0C0BDB5F175687EC00BC1A7E; + remoteInfo = libsecdRegressions; }; - 0CC3356116C1EF8B00399E53 /* PBXContainerItemProxy */ = { + 0C271D6D15C8C68800560531 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 0CC3355B16C1EF5D00399E53 /* regressions.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = E710C6FD133192E900F85568; - remoteInfo = regressions; + containerPortal = 0C95403F14E473AA00077526 /* libsecurity_ssl.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 0C1C933A15C8AC81007D377B; + remoteInfo = libsecurity_ssl_kext; }; - 0CCEBDB216C2CFD4001BD7F6 /* PBXContainerItemProxy */ = { + 0C62D60714E0588700A97963 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 0CC3355B16C1EF5D00399E53 /* regressions.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = E710C6FD133192E900F85568; - remoteInfo = regressions; + containerPortal = 0CF55E5514DB47DE003AD8F2 /* tlsnke.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 0CDF46A014DC794300FFE2FD; + remoteInfo = tlssocket; }; - 0CCEBDB916C303D8001BD7F6 /* PBXContainerItemProxy */ = { + 0C664AB31759270C0092D3D9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = 0CC3350716C1ED8000399E53; + remoteGlobalIDString = 0C0BDB2E175685B000BC1A7E; remoteInfo = secdtests; }; - 0CCEBDBC16C30948001BD7F6 /* PBXContainerItemProxy */ = { + 0C664AD5175938F20092D3D9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = E7E0D8E8158FA9A3002CA176; - remoteInfo = utilitiesRegressions; + remoteGlobalIDString = 18D4056114CE53C200A2BE4E; + remoteInfo = libsecurityd; }; - 0CFC55E215DDB86500BEC89E /* PBXContainerItemProxy */ = { + 0C664AD7175938F90092D3D9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 0C6C630A15D193C800BC68CD; - remoteInfo = sectests; + remoteGlobalIDString = 0C0BDB55175687EC00BC1A7E; + remoteInfo = libsecdRegressions; }; - 0CFE4BA6167943EF0077AE4F /* PBXContainerItemProxy */ = { + 0C664AD9175939490092D3D9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + containerPortal = 4C2FEC4915755D700008BE39 /* utilities.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 0C6C642915D5ADB500BC68CD; - remoteInfo = Security_kexts; - }; - 18270C7C14CE573D00B05E7F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 18D4056214CE53C200A2BE4E; - remoteInfo = securityd; + remoteGlobalIDString = E742A09B14E343E70052A486; + remoteInfo = utilities; }; - 18270EE014CF28D000B05E7F /* PBXContainerItemProxy */ = { + 0C664ADB1759395E0092D3D9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 0C25A871122726540050C2BD /* regressions.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 18D4043414CE0CF300A2BE4E; - remoteInfo = libsecurity; + remoteGlobalIDString = E710C6FD133192E900F85568; + remoteInfo = regressions; }; - 18270EE214CF28D900B05E7F /* PBXContainerItemProxy */ = { + 0C664ADD1759396C0092D3D9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 795CA97A0D38269B00BAE6A2 /* libsecurity_asn1.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 18D4056114CE53C200A2BE4E; - remoteInfo = libsecurityd; + remoteGlobalIDString = 795CA7FE0D38013D00BAE6A2; + remoteInfo = libASN1; }; - 18270F1114CF43C000B05E7F /* PBXContainerItemProxy */ = { + 0C664ADF175939740092D3D9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18270F0814CF43C000B05E7F /* libDER.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 053BA314091C00BF00A7007A; + containerPortal = 4C8786A10B03E05D00BB77D4 /* libDER.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 053BA313091C00BF00A7007A; remoteInfo = libDER; }; - 18270F1314CF43C000B05E7F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 18270F0814CF43C000B05E7F /* libDER.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 053BA445091FE58C00A7007A; - remoteInfo = parseCert; - }; - 18270F1514CF43C000B05E7F /* PBXContainerItemProxy */ = { + 0C664AE11759398A0092D3D9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18270F0814CF43C000B05E7F /* libDER.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 053BA46B091FE63E00A7007A; - remoteInfo = libDERUtils; - }; - 18270F1714CF43C000B05E7F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 18270F0814CF43C000B05E7F /* libDER.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 058F16540925135E009FA1C5; - remoteInfo = parseCrl; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 18D4043414CE0CF300A2BE4E; + remoteInfo = libsecurity; }; - 18270F1914CF43C000B05E7F /* PBXContainerItemProxy */ = { + 0C664AE31759398A0092D3D9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18270F0814CF43C000B05E7F /* libDER.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4C96C8CE113F4132005483E8; - remoteInfo = parseTicket; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E702E73514E1F3EA00CDE635; + remoteInfo = libSecureObjectSync; }; - 18270F5C14CF655B00B05E7F /* PBXContainerItemProxy */ = { + 0C664AE517593BED0092D3D9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; remoteGlobalIDString = 18270F5414CF651900B05E7F; remoteInfo = libsecipc_client; }; - 18270F5F14CF655B00B05E7F /* PBXContainerItemProxy */ = { + 0C7CFA3414E1BA7000DF9D95 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 18270F5514CF651900B05E7F; - remoteInfo = libsecipc_client; + containerPortal = 0CF55E5514DB47DE003AD8F2 /* tlsnke.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 0CE08A72148FF2C6000473EB; + remoteInfo = tlsnketest; }; - 182BB22B146F07DD000BF1F3 /* PBXContainerItemProxy */ = { + 0C7CFA3614E1BAEC00DF9D95 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = 4C5719C712FB5E9E00B31F85; - remoteInfo = XPCKeychainSandboxCheck; + remoteGlobalIDString = 4C541F950F250C3000E508AE; + remoteInfo = phase1; }; - 182BB3EB146F2448000BF1F3 /* PBXContainerItemProxy */ = { + 0C99B73F131C984900584CF4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B5F0146DE6FD007E536C /* libsecurity_apple_x509_tp.xcodeproj */; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_apple_x509_tp; + remoteGlobalIDString = 0C6799F912F7C37C00712919; + remoteInfo = dtlsTests; }; - 182BB3ED146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 0CC827F1138712B100BD99B7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B6EC146DE7EE007E536C /* libsecurity_pkcs12.xcodeproj */; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = 0592AC8B0415523C00003D05; - remoteInfo = libsecurity_pkcs12; + remoteGlobalIDString = E710C7411331946400F85568; + remoteInfo = SecurityTests; }; - 182BB3EF146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 0CCA406915C73CA1002AEC4C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B72B146DE844007E536C /* libsecurity_transform.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_transform; + containerPortal = 0C95403F14E473AA00077526 /* libsecurity_ssl.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_ssl; }; - 182BB3F1146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 0CCA408115C745C6002AEC4C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B6DF146DE7E7007E536C /* libsecurity_ocspd.xcodeproj */; + containerPortal = 0C95403F14E473AA00077526 /* libsecurity_ssl.xcodeproj */; proxyType = 1; remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_ocspd; + remoteInfo = libsecurity_ssl; }; - 182BB3F3146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 0CCA418015C89ECD002AEC4C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B66D146DE75D007E536C /* libsecurity_comcryption.xcodeproj */; + containerPortal = 0C95403F14E473AA00077526 /* libsecurity_ssl.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 7264321D00A8AD0A7F000001; - remoteInfo = libsecurity_comcryption; + remoteGlobalIDString = 0CCA415815C89E8B002AEC4C; + remoteInfo = libsecurity_ssl_regressions; }; - 182BB3F5146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 0CCA418315C89ECD002AEC4C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B637146DE748007E536C /* libsecurity_checkpw.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_checkpw; + containerPortal = 0C95403F14E473AA00077526 /* libsecurity_ssl.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 0CCA415915C89E8B002AEC4C; + remoteInfo = libsecurity_ssl_regressions; }; - 182BB3F7146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 0CCA418515C89EDD002AEC4C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */; + containerPortal = 0C95403F14E473AA00077526 /* libsecurity_ssl.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_ssl; + remoteGlobalIDString = 0CCA415815C89E8B002AEC4C; + remoteInfo = libsecurity_ssl_regressions; }; - 182BB3FB146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 0CCA42F015C8A806002AEC4C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B5C9146DE6CE007E536C /* libsecurity_apple_cspdl.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_apple_cspdl; + containerPortal = 0C95403F14E473AA00077526 /* libsecurity_ssl.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 0CCA42C915C8A387002AEC4C; + remoteInfo = dtlsEchoClient; }; - 182BB3FD146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 0CCA42F215C8A806002AEC4C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B6F8146DE7F7007E536C /* libsecurity_sd_cspdl.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_sd_cspdl; + containerPortal = 0C95403F14E473AA00077526 /* libsecurity_ssl.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 0CCA42D715C8A395002AEC4C; + remoteInfo = dtlsEchoServer; }; - 182BB3FF146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 0CCA42F415C8A815002AEC4C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B6C7146DE7D7007E536C /* libsecurity_manifest.xcodeproj */; + containerPortal = 0C95403F14E473AA00077526 /* libsecurity_ssl.xcodeproj */; proxyType = 1; - remoteGlobalIDString = D6C8AFAD05DD2430003DB724; - remoteInfo = libsecurity_manifest; + remoteGlobalIDString = 0CCA42C815C8A387002AEC4C; + remoteInfo = dtlsEchoClient; }; - 182BB401146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 0CCA42F615C8A820002AEC4C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B712146DE825007E536C /* libsecurity_smime.xcodeproj */; + containerPortal = 0C95403F14E473AA00077526 /* libsecurity_ssl.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 4C2741ED03E9FBF700A80181; - remoteInfo = libsecurity_smime; + remoteGlobalIDString = 0CCA42D615C8A395002AEC4C; + remoteInfo = dtlsEchoServer; }; - 182BB403146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 0CD72A4B16D54BD300A4B8A3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B64B146DE750007E536C /* libsecurity_cms.xcodeproj */; + containerPortal = 4C2FEC4915755D700008BE39 /* utilities.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_cms; + remoteGlobalIDString = E742A09B14E343E70052A486; + remoteInfo = utilities; }; - 182BB405146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 0CD72A5916D55BF100A4B8A3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B5BC146DE6C8007E536C /* libsecurity_apple_csp.xcodeproj */; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_apple_csp; + remoteGlobalIDString = 52DE81681636347500F49F0C; + remoteInfo = Keychain; }; - 182BB407146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 0CF55E5F14DB47DF003AD8F2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B5E1146DE6E7007E536C /* libsecurity_apple_x509_cl.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_apple_x509_cl; + containerPortal = 0CF55E5514DB47DE003AD8F2 /* tlsnke.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 0CC9A7F0146DF66000C18F89; + remoteInfo = tlsnke; }; - 182BB409146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 0CF55E6114DB47DF003AD8F2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_keychain; + containerPortal = 0CF55E5514DB47DE003AD8F2 /* tlsnke.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 0CE08A73148FF2C6000473EB; + remoteInfo = tlsnketest; }; - 182BB40B146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 18F7F66214D77DF700F88A12 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B5D5146DE6D7007E536C /* libsecurity_apple_file_dl.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_apple_file_dl; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 18D4043514CE0CF300A2BE4E; + remoteInfo = libsecurity; }; - 182BB40D146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 18F7F66414D77DF700F88A12 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B609146DE70A007E536C /* libsecurity_authorization.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_authorization; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 18D4056214CE53C200A2BE4E; + remoteInfo = libsecurityd; }; - 182BB40F146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 18F7F66614D77DF700F88A12 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B550146DE227007E536C /* libsecurity_cdsa_utilities.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 4CA2A5390523D32800978A7B; - remoteInfo = libsecurity_cdsa_utilities; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 186CDD0F14CA116C00AF9171; + remoteInfo = libSecItemShimOSX; }; - 182BB411146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 18F7F66814D77DF700F88A12 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B679146DE76E007E536C /* libsecurity_cryptkit.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 7264322800A8AD0A7F000001; - remoteInfo = libsecurity_cryptkit; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 18270F5514CF651900B05E7F; + remoteInfo = libsecipc_client; }; - 182BB413146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 18F7F66A14D77E8500F88A12 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B615146DE715007E536C /* libsecurity_cdsa_client.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_cdsa_client; + remoteGlobalIDString = 18D4043414CE0CF300A2BE4E; + remoteInfo = libsecurity; }; - 182BB417146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 18F7F66C14D77E8D00F88A12 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B694146DE797007E536C /* libsecurity_filedb.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_filedb; + remoteGlobalIDString = 18270F5414CF651900B05E7F; + remoteInfo = libsecipc_client; }; - 182BB419146F248D000BF1F3 /* PBXContainerItemProxy */ = { + 18F7F67014D77EC500F88A12 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B6D3146DE7E0007E536C /* libsecurity_mds.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_mds; + remoteGlobalIDString = 18D4056114CE53C200A2BE4E; + remoteInfo = libsecurityd; }; - 182BB4E6146F25AF000BF1F3 /* PBXContainerItemProxy */ = { + 18F7F67314D77EE900F88A12 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_codesigning; + remoteGlobalIDString = 18D4056114CE53C200A2BE4E; + remoteInfo = libsecurityd; }; - 182BB587146FE001000BF1F3 /* PBXContainerItemProxy */ = { + 18F7F67614D77EFF00F88A12 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_codesigning; + remoteGlobalIDString = 18D4056114CE53C200A2BE4E; + remoteInfo = libsecurityd; }; - 182BB58C146FE0FF000BF1F3 /* PBXContainerItemProxy */ = { + 4ACED92A15A1095B0060775A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B550146DE227007E536C /* libsecurity_cdsa_utilities.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 4CA2A5390523D32800978A7B; - remoteInfo = libsecurity_cdsa_utilities; + remoteGlobalIDString = 4A824AFB158FF07000F932C0; + remoteInfo = libSecOTRRegressions; }; - 182BB58E146FE11C000BF1F3 /* PBXContainerItemProxy */ = { + 4ACED92E15A10A3E0060775A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B532146DDBE5007E536C /* libsecurity_utilities.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 4CA2A5390523D32800978A7B; - remoteInfo = libsecurity_utilities; + remoteGlobalIDString = 4A824AFB158FF07000F932C0; + remoteInfo = libSecOTRRegressions; }; - 182BB595146FE27F000BF1F3 /* PBXContainerItemProxy */ = { + 4C0789C1113F4C7400422E2D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 1807384A146D0D4E00F05C24; - remoteInfo = Security; + containerPortal = 4C8786A10B03E05D00BB77D4 /* libDER.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4C96C8CE113F4132005483E8; + remoteInfo = parseTicket; }; - 18446081146DF52F00B12992 /* PBXContainerItemProxy */ = { + 4C1ADEB61615176500E4A8AF /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B621146DE720007E536C /* libsecurity_cdsa_plugin.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_cdsa_plugin; + remoteGlobalIDString = E702E73514E1F3EA00CDE635; + remoteInfo = libSecureObjectSync; }; - 184461B0146E9D3300B12992 /* PBXContainerItemProxy */ = { + 4C2FEC5015755D710008BE39 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 184461A3146E9D3200B12992 /* libsecurityd.xcodeproj */; + containerPortal = 4C2FEC4915755D700008BE39 /* utilities.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = libsecurityd_client; + remoteGlobalIDString = E742A09C14E343E70052A486; + remoteInfo = libutilities; }; - 184461B4146E9D3300B12992 /* PBXContainerItemProxy */ = { + 4C2FEC5F157571F80008BE39 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 184461A3146E9D3200B12992 /* libsecurityd.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA1FECD052A44A100F22E42; - remoteInfo = libsecurityd_server; - }; - 184461B8146E9D3300B12992 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 184461A3146E9D3200B12992 /* libsecurityd.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = C2A788730B7AA65B00CFF85C; - remoteInfo = ucspc; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E702E75714E1F48800CDE635; + remoteInfo = libSOSRegressions; }; - 186CDD1D14CA11C700AF9171 /* PBXContainerItemProxy */ = { + 4C2FEC61157572130008BE39 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 186CDD0F14CA116C00AF9171; - remoteInfo = sec; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E702E75714E1F48800CDE635; + remoteInfo = libSOSRegressions; }; - 186F779014E5A00F00434E1F /* PBXContainerItemProxy */ = { + 4C3AD81D157589380047A498 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 18270ED514CF282600B05E7F; - remoteInfo = secd; + remoteGlobalIDString = E702E73514E1F3EA00CDE635; + remoteInfo = libSecureObjectSync; }; - 186F779214E5A01700434E1F /* PBXContainerItemProxy */ = { + 4C3AD81F1575894C0047A498 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 1807384A146D0D4E00F05C24; - remoteInfo = Security; + remoteGlobalIDString = E702E73514E1F3EA00CDE635; + remoteInfo = libSecureObjectSync; }; - 186F779414E5A01C00434E1F /* PBXContainerItemProxy */ = { + 4C52D0ED16EFCD720079966E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = 182BB567146F4DCA000BF1F3; - remoteInfo = csparser; + remoteGlobalIDString = 4C52D0B316EFC61E0079966E; + remoteInfo = CircleJoinRequested; }; - 186F779614E5A04200434E1F /* PBXContainerItemProxy */ = { + 4C541F8B0F250C0400E508AE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = 18FE67E91471A3AA00A2CBE3; - remoteInfo = copyHeaders; + remoteGlobalIDString = 790851B50CA9859F0083CC4D; + remoteInfo = securityd; }; - 186F779814E5A06500434E1F /* PBXContainerItemProxy */ = { + 4C541F8D0F250C0900E508AE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = 186F778814E59FB200434E1F; - remoteInfo = Framework; + remoteGlobalIDString = 4CB740A20A47567C00D641BB; + remoteInfo = security; }; - 186F779A14E5A06800434E1F /* PBXContainerItemProxy */ = { + 4C541F8F0F250C0E00E508AE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = 186F778C14E59FDA00434E1F; - remoteInfo = Helpers; + remoteGlobalIDString = 4CE5A54C09C796E100D27A3F; + remoteInfo = sslViewer; }; - 1879B537146DDBE5007E536C /* PBXContainerItemProxy */ = { + 4C541F910F250C1300E508AE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B532146DDBE5007E536C /* libsecurity_utilities.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA2A53A0523D32800978A7B; - remoteInfo = utilities; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 7913B1FF0D172B3900601FE9; + remoteInfo = sslServer; }; - 1879B544146DE18D007E536C /* PBXContainerItemProxy */ = { + 4C541F9C0F250C3500E508AE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B532146DDBE5007E536C /* libsecurity_utilities.xcodeproj */; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = 4CA2A5390523D32800978A7B; - remoteInfo = libsecurity_utilities; + remoteGlobalIDString = 4C32C0AE0A4975F6002891BD; + remoteInfo = Security; }; - 1879B54E146DE212007E536C /* PBXContainerItemProxy */ = { + 4C541F9E0F250C4F00E508AE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B547146DE212007E536C /* libsecurity_cdsa_utils.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = cdsa_utils; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4C541F950F250C3000E508AE; + remoteInfo = phase1; }; - 1879B559146DE227007E536C /* PBXContainerItemProxy */ = { + 4C541FA00F250C5200E508AE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B550146DE227007E536C /* libsecurity_cdsa_utilities.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA2A53A0523D32800978A7B; - remoteInfo = cdsa_utilities; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4C541F840F250BF500E508AE; + remoteInfo = phase2; }; - 1879B55B146DE227007E536C /* PBXContainerItemProxy */ = { + 4C60888A155C943D00A0904F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B550146DE227007E536C /* libsecurity_cdsa_utilities.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 4CF9C5B90535E557009B9B8D; - remoteInfo = Schemas; + remoteGlobalIDString = E702E75614E1F3EA00CDE635; + remoteInfo = libSecureObjectSync; }; - 1879B564146DE244007E536C /* PBXContainerItemProxy */ = { + 4C60888C155C943D00A0904F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B55D146DE244007E536C /* libsecurity_cssm.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = cssm; + remoteGlobalIDString = E702E77814E1F48800CDE635; + remoteInfo = libSOSRegressions; }; - 1879B56B146DE2CF007E536C /* PBXContainerItemProxy */ = { + 4C711D5A13AFCD0900FE865D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B547146DE212007E536C /* libsecurity_cdsa_utils.xcodeproj */; + containerPortal = 4C8786A10B03E05D00BB77D4 /* libDER.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_cdsa_utils; + remoteGlobalIDString = 053BA313091C00BF00A7007A; + remoteInfo = libDER; }; - 1879B56D146DE2D3007E536C /* PBXContainerItemProxy */ = { + 4C711D6013AFCD0900FE865D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B55D146DE244007E536C /* libsecurity_cssm.xcodeproj */; + containerPortal = 0C25A871122726540050C2BD /* regressions.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_cssm; - }; - 1879B5C5146DE6C8007E536C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 1879B5BC146DE6C8007E536C /* libsecurity_apple_csp.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = libsecurity_apple_csp; + remoteGlobalIDString = E710C6FD133192E900F85568; + remoteInfo = regressions; }; - 1879B5D1146DE6CE007E536C /* PBXContainerItemProxy */ = { + 4C8786AC0B03E05E00BB77D4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B5C9146DE6CE007E536C /* libsecurity_apple_cspdl.xcodeproj */; + containerPortal = 4C8786A10B03E05D00BB77D4 /* libDER.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = libsecurity_apple_cspdl; + remoteGlobalIDString = 053BA314091C00BF00A7007A; + remoteInfo = libDER; }; - 1879B5DD146DE6D7007E536C /* PBXContainerItemProxy */ = { + 4C8786AE0B03E05E00BB77D4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B5D5146DE6D7007E536C /* libsecurity_apple_file_dl.xcodeproj */; + containerPortal = 4C8786A10B03E05D00BB77D4 /* libDER.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = libsecurity_apple_file_dl; + remoteGlobalIDString = 053BA445091FE58C00A7007A; + remoteInfo = parseCert; }; - 1879B5EA146DE6E8007E536C /* PBXContainerItemProxy */ = { + 4C8786B00B03E05E00BB77D4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B5E1146DE6E7007E536C /* libsecurity_apple_x509_cl.xcodeproj */; + containerPortal = 4C8786A10B03E05D00BB77D4 /* libDER.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 4CC7C27506127AA100E6CE35; - remoteInfo = libsecurity_apple_x509_cl; + remoteGlobalIDString = 053BA46B091FE63E00A7007A; + remoteInfo = libDERUtils; }; - 1879B5EE146DE6E8007E536C /* PBXContainerItemProxy */ = { + 4C8786B20B03E05E00BB77D4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B5E1146DE6E7007E536C /* libsecurity_apple_x509_cl.xcodeproj */; + containerPortal = 4C8786A10B03E05D00BB77D4 /* libDER.xcodeproj */; proxyType = 2; - remoteGlobalIDString = C207F277053B21E600FF85CB; - remoteInfo = plugin_apple_x509_cl; + remoteGlobalIDString = 058F16540925135E009FA1C5; + remoteInfo = parseCrl; }; - 1879B5F8146DE6FD007E536C /* PBXContainerItemProxy */ = { + 4C8786B40B03E0A400BB77D4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B5F0146DE6FD007E536C /* libsecurity_apple_x509_tp.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = libsecurity_apple_x509_tp; + containerPortal = 4C8786A10B03E05D00BB77D4 /* libDER.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 053BA313091C00BF00A7007A; + remoteInfo = libDER; }; - 1879B611146DE70A007E536C /* PBXContainerItemProxy */ = { + 4C9DE9EE1181ACA000CF5C27 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B609146DE70A007E536C /* libsecurity_authorization.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = libsecurity_authorization; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4C9DE9D11181AC4800CF5C27; + remoteInfo = sslEcdsa; }; - 1879B61D146DE715007E536C /* PBXContainerItemProxy */ = { + 4CC92B1915A3BF1E00C6D578 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B615146DE715007E536C /* libsecurity_cdsa_client.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = libsecurity_cdsa_client; + remoteGlobalIDString = 4CC92B1415A3BC6B00C6D578; + remoteInfo = "libsecuritydRegressions copy"; }; - 1879B62A146DE720007E536C /* PBXContainerItemProxy */ = { + 4CC92B2415A3C6DE00C6D578 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B621146DE720007E536C /* libsecurity_cdsa_plugin.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = libsecurity_cdsa_plugin; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CC92AC215A3BC6B00C6D578; + remoteInfo = libsecuritydRegressions; }; - 1879B643146DE748007E536C /* PBXContainerItemProxy */ = { + 4CC92B2C15A3C94500C6D578 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B637146DE748007E536C /* libsecurity_checkpw.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = libsecurity_checkpw; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CC92AC215A3BC6B00C6D578; + remoteInfo = libsecuritydRegressions; }; - 1879B647146DE748007E536C /* PBXContainerItemProxy */ = { + 4CE39041169F87C400026468 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B637146DE748007E536C /* libsecurity_checkpw.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 1CD90B6711011176008DD07F; - remoteInfo = "test-checkpw"; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E71049F1169E023B00DB0045; + remoteInfo = libSecurityTool; }; - 1879B649146DE748007E536C /* PBXContainerItemProxy */ = { + 4CE39043169F87DB00026468 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B637146DE748007E536C /* libsecurity_checkpw.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 1C6C402F1121FC0C00031CDE; - remoteInfo = "perf-checkpw"; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E71049F1169E023B00DB0045; + remoteInfo = libSecurityTool; }; - 1879B653146DE750007E536C /* PBXContainerItemProxy */ = { + 4CEC096E15758EAF008EB037 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B64B146DE750007E536C /* libsecurity_cms.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = libsecurity_cms; + containerPortal = 4C2FEC4915755D700008BE39 /* utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E742A09B14E343E70052A486; + remoteInfo = libutilities; }; - 1879B665146DE757007E536C /* PBXContainerItemProxy */ = { + 4CEC097015758EC5008EB037 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = libsecurity_codesigning; + containerPortal = 4C2FEC4915755D700008BE39 /* utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E742A09B14E343E70052A486; + remoteInfo = libutilities; }; - 1879B669146DE757007E536C /* PBXContainerItemProxy */ = { + 4CEC097415758F0A008EB037 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = C2BC1F260B580D3A003EC9DC; - remoteInfo = libintegrity; + containerPortal = 4C2FEC4915755D700008BE39 /* utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E742A09B14E343E70052A486; + remoteInfo = libutilities; }; - 1879B66B146DE757007E536C /* PBXContainerItemProxy */ = { + 4CEC097815758F17008EB037 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = C2BC1F2F0B580D4B003EC9DC; - remoteInfo = libcodehost; + containerPortal = 4C2FEC4915755D700008BE39 /* utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E742A09B14E343E70052A486; + remoteInfo = libutilities; }; - 1879B675146DE75E007E536C /* PBXContainerItemProxy */ = { + 4CEC097C15758F23008EB037 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B66D146DE75D007E536C /* libsecurity_comcryption.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 7264321400A8AD0A7F000001; - remoteInfo = libsecurity_comcryption; + containerPortal = 4C2FEC4915755D700008BE39 /* utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E742A09B14E343E70052A486; + remoteInfo = libutilities; }; - 1879B683146DE76F007E536C /* PBXContainerItemProxy */ = { + 4CEC098615758F60008EB037 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B679146DE76E007E536C /* libsecurity_cryptkit.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 7264321600A8AD0A7F000001; - remoteInfo = libsecurity_cryptkit; + containerPortal = 4C2FEC4915755D700008BE39 /* utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E742A09B14E343E70052A486; + remoteInfo = libutilities; }; - 1879B687146DE76F007E536C /* PBXContainerItemProxy */ = { + 52849FAD164462E7005CDF23 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B679146DE76E007E536C /* libsecurity_cryptkit.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 0535DCBE074A944D00805B04; - remoteInfo = libCryptKit; + remoteGlobalIDString = 528402A0164445760035F320; + remoteInfo = libCloudKeychainProxy; }; - 1879B689146DE76F007E536C /* PBXContainerItemProxy */ = { + 52D82BEB16A622100078DFE5 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B679146DE76E007E536C /* libsecurity_cryptkit.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 0536B295074BC91A00F9F1AD; - remoteInfo = CryptKitSignature; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 5284029F164445760035F320; + remoteInfo = libCloudKeychainProxy; }; - 1879B69C146DE797007E536C /* PBXContainerItemProxy */ = { + 52D82BF116A622600078DFE5 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B694146DE797007E536C /* libsecurity_filedb.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = libsecurity_filedb; + containerPortal = 4C2FEC4915755D700008BE39 /* utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E742A09B14E343E70052A486; + remoteInfo = utilities; }; - 1879B6B2146DE7A0007E536C /* PBXContainerItemProxy */ = { + 52D82BF516A627100078DFE5 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = libsecurity_keychain; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 52D82BDD16A621F70078DFE5; + remoteInfo = CloudKeychainProxy; }; - 1879B6B6146DE7A0007E536C /* PBXContainerItemProxy */ = { + 5346481A17331ED800FE9172 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4C5719C812FB5E9E00B31F85; - remoteInfo = XPCKeychainSandboxCheck; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5346480017331E1100FE9172; + remoteInfo = KeychainSyncAccountNotification; }; - 1879B6CF146DE7D7007E536C /* PBXContainerItemProxy */ = { + 5D403D3115C6FE9E0030D492 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B6C7146DE7D7007E536C /* libsecurity_manifest.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = D6C8AFAE05DD2430003DB724; - remoteInfo = libsecurity_manifest; + containerPortal = 4C2FEC4915755D700008BE39 /* utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E742A09B14E343E70052A486; + remoteInfo = utilities; }; - 1879B6DB146DE7E0007E536C /* PBXContainerItemProxy */ = { + 5DDD0BED16D6748900D6C0D6 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B6D3146DE7E0007E536C /* libsecurity_mds.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = libsecurity_mds; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 728B56A016D59979008FA3AB; + remoteInfo = OTAPKIAssetTool; }; - 1879B6E8146DE7E8007E536C /* PBXContainerItemProxy */ = { + 72D41315175D13E40052A8ED /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B6DF146DE7E7007E536C /* libsecurity_ocspd.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = libsecurity_ocspd; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 72979BE1175D095900BE8FD6; + remoteInfo = cloud_keychain_diagnose; }; - 1879B6F4146DE7EF007E536C /* PBXContainerItemProxy */ = { + 795CA9850D38269B00BAE6A2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B6EC146DE7EE007E536C /* libsecurity_pkcs12.xcodeproj */; + containerPortal = 795CA97A0D38269B00BAE6A2 /* libsecurity_asn1.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 0592AC8C0415523C00003D05; - remoteInfo = libsecurity_pkcs12; + remoteGlobalIDString = 795CA7FF0D38013D00BAE6A2; + remoteInfo = libASN1; }; - 1879B700146DE7F7007E536C /* PBXContainerItemProxy */ = { + 795CA9BC0D3829FC00BAE6A2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B6F8146DE7F7007E536C /* libsecurity_sd_cspdl.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = libsecurity_sd_cspdl; + containerPortal = 795CA97A0D38269B00BAE6A2 /* libsecurity_asn1.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 795CA7FE0D38013D00BAE6A2; + remoteInfo = libASN1; }; - 1879B71B146DE825007E536C /* PBXContainerItemProxy */ = { + 79BDD39A0D60D5F9000D84D3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B712146DE825007E536C /* libsecurity_smime.xcodeproj */; + containerPortal = 79BDD3940D60D5F9000D84D3 /* libsecurity_smime.xcodeproj */; proxyType = 2; remoteGlobalIDString = 4C817F8405ED4D7A007975E6; remoteInfo = libsecurity_smime; }; - 1879B727146DE839007E536C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = libsecurity_ssl; - }; - 1879B738146DE845007E536C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 1879B72B146DE844007E536C /* libsecurity_transform.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = libsecurity_transform; - }; - 1879B73C146DE845007E536C /* PBXContainerItemProxy */ = { + 79BDD39C0D60D5F9000D84D3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B72B146DE844007E536C /* libsecurity_transform.xcodeproj */; + containerPortal = 79BDD3940D60D5F9000D84D3 /* libsecurity_smime.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 4C738257112DF65200EA003B; - remoteInfo = "unit-tests"; + remoteGlobalIDString = 4C7FAB41056AC7A200FE0C44; + remoteInfo = security_smime; }; - 1879B73E146DE845007E536C /* PBXContainerItemProxy */ = { + 79BDD39E0D60D5F9000D84D3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B72B146DE844007E536C /* libsecurity_transform.xcodeproj */; + containerPortal = 79BDD3940D60D5F9000D84D3 /* libsecurity_smime.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 4CBCBEB61130A2D700CC18E9; - remoteInfo = "100-sha2"; + remoteGlobalIDString = 79DC33620D4E6EEA0039E4BC; + remoteInfo = cms; }; - 1879B740146DE845007E536C /* PBXContainerItemProxy */ = { + 79BDD3A40D60D637000D84D3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B72B146DE844007E536C /* libsecurity_transform.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4C010B87121AE8DF0094CB72; - remoteInfo = "input-speed-test"; - }; - 1885B3F814D8D9B100519375 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 1879B5FC146DE704007E536C /* libsecurity_asn1.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 795CA7FF0D38013D00BAE6A2; - remoteInfo = libASN1; - }; - 1885B45014D9AB3D00519375 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 1879B5FC146DE704007E536C /* libsecurity_asn1.xcodeproj */; + containerPortal = 79BDD3940D60D5F9000D84D3 /* libsecurity_smime.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 795CA7FE0D38013D00BAE6A2; - remoteInfo = libASN1; + remoteGlobalIDString = 79DC33610D4E6EEA0039E4BC; + remoteInfo = cms; }; - 18AD56A514CDED59008233F2 /* PBXContainerItemProxy */ = { + 79DCEA7C134A293D007F57DC /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 4C8786A10B03E05D00BB77D4 /* libDER.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 186CDD0E14CA116C00AF9171; - remoteInfo = sec; + remoteGlobalIDString = 053BA313091C00BF00A7007A; + remoteInfo = libDER; }; - 18B9655B1472F83C005A4D2E /* PBXContainerItemProxy */ = { + BE197F621911742900BA91D1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 184461A3146E9D3200B12992 /* libsecurityd.xcodeproj */; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = 4C31C2D9055341AA006D00BD; - remoteInfo = world; + remoteGlobalIDString = BE197F2519116FD100BA91D1; + remoteInfo = KeychainViewService; }; - 18D4053A14CE2C1600A2BE4E /* PBXContainerItemProxy */ = { + BE442B9A18B7FD6700F24DAE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 18D4043514CE0CF300A2BE4E; - remoteInfo = security; + remoteGlobalIDString = BEF9640618B4171200813FA3; + remoteInfo = libSWCAgent; }; - 18F235FE15CA100300060520 /* PBXContainerItemProxy */ = { + BE442B9E18B7FD7D00F24DAE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 18F234EA15C9F9A600060520; - remoteInfo = security.auth; + remoteGlobalIDString = BEF963FE18B4171200813FA3; + remoteInfo = libSWCAgent; }; - 18FE688E1471A4C900A2CBE3 /* PBXContainerItemProxy */ = { + BE442BAA18B7FDB800F24DAE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 18FE67E91471A3AA00A2CBE3; - remoteInfo = copyHeaders; + remoteGlobalIDString = BEF963FE18B4171200813FA3; + remoteInfo = libSWCAgent; }; - 37A7CED9197DBA8700926CE8 /* PBXContainerItemProxy */ = { + BE4AC9B318B8020400B84964 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = 37A7CEAA197DB8FA00926CE8; - remoteInfo = codesign_tests; + remoteGlobalIDString = BE442BA018B7FDB800F24DAE; + remoteInfo = swcagent; }; - 4AD6F6F31651CC2500DB4CE6 /* PBXContainerItemProxy */ = { + E7104A02169E038F00DB0045 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 4A5CCA4E15ACEFA500702357; - remoteInfo = libSecOtrOSX; + remoteGlobalIDString = E71049F1169E023B00DB0045; + remoteInfo = libSecurityTool; }; - 4C01DE31164C3793006798CD /* PBXContainerItemProxy */ = { + E7104A05169E038F00DB0045 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 528402A0164445760035F320; - remoteInfo = libCloudKeychainProxy; + remoteGlobalIDString = E71049F2169E023B00DB0045; + remoteInfo = libSecurityTool; }; - 4C01DF12164C3E74006798CD /* PBXContainerItemProxy */ = { + E7104A1F169E21C000DB0045 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = E702E73514E1F3EA00CDE635; - remoteInfo = libSecureObjectSync; + remoteGlobalIDString = E7104A12169E216E00DB0045; + remoteInfo = libSecurityCommands; }; - 4C1288E915FFE9D7008CE3E3 /* PBXContainerItemProxy */ = { + E7104A22169E21C000DB0045 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 2; - remoteGlobalIDString = E702E75614E1F3EA00CDE635; - remoteInfo = libSecureObjectSync; + remoteGlobalIDString = E7104A1D169E216E00DB0045; + remoteInfo = libSecurityCommands; }; - 4C1288EB15FFE9D7008CE3E3 /* PBXContainerItemProxy */ = { + E710C707133192EA00F85568 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 0C25A871122726540050C2BD /* regressions.xcodeproj */; proxyType = 2; - remoteGlobalIDString = E702E77814E1F48800CDE635; - remoteInfo = libSOSRegressions; + remoteGlobalIDString = E710C6FE133192E900F85568; + remoteInfo = regressions; }; - 4C1288ED15FFE9D7008CE3E3 /* PBXContainerItemProxy */ = { + E76079DA1951FDBF00F69731 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 4A824B03158FF07000F932C0; - remoteInfo = libSecurityRegressions; + remoteGlobalIDString = E76079D21951FD2800F69731; + remoteInfo = liblogging; }; - 4C1288EF15FFE9D7008CE3E3 /* PBXContainerItemProxy */ = { + E76079FB1951FE1F00F69731 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CC92B1415A3BC6B00C6D578; - remoteInfo = libsecuritydRegressions; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E76079971951FD2800F69731; + remoteInfo = liblogging; }; - 4C1288F115FFE9D7008CE3E3 /* PBXContainerItemProxy */ = { + E777C71415B63C0B004044A8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 2; remoteGlobalIDString = 4A5CCA4F15ACEFA500702357; remoteInfo = libSecOtrOSX; }; - 4C12893F15FFECF3008CE3E3 /* PBXContainerItemProxy */ = { + E79D3388135CBEB1005777CF /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = E742A09C14E343E70052A486; - remoteInfo = utilities; + containerPortal = 0C25A871122726540050C2BD /* regressions.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E710C6FD133192E900F85568; + remoteInfo = regressions; }; - 4C12894115FFECF3008CE3E3 /* PBXContainerItemProxy */ = { + E79D9CD4159BEA78000834EC /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 2; - remoteGlobalIDString = E7E0D8F9158FA9A3002CA176; - remoteInfo = utilitiesRegressions; + remoteGlobalIDString = 4A824B03158FF07000F932C0; + remoteInfo = libSecOTRRegressions; }; - 4C12894315FFED03008CE3E3 /* PBXContainerItemProxy */ = { + E7B01B8316572132000485F1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = E742A09B14E343E70052A486; - remoteInfo = utilities; + remoteGlobalIDString = E702E73514E1F3EA00CDE635; + remoteInfo = libSecureObjectSync; }; - 4C797BC816D83A3100C7B586 /* PBXContainerItemProxy */ = { + E7B01BA71664294D000485F1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; proxyType = 1; - remoteGlobalIDString = 4C96F7C016D6DF8300D3B39D; - remoteInfo = "Keychain Circle Notification"; + remoteGlobalIDString = 4C32C0AE0A4975F6002891BD; + remoteInfo = Security; }; - 4C797BF016D83A3800C7B586 /* PBXContainerItemProxy */ = { + E7B01BBF166594AB000485F1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 4CC7A7B216CC2A84003E10C1; - remoteInfo = "Cloud Keychain Utility"; + remoteGlobalIDString = E702E73514E1F3EA00CDE635; + remoteInfo = libSecureObjectSync; }; - 4C7D8763160A746E00D041E3 /* PBXContainerItemProxy */ = { + E7B01BC1166594AB000485F1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = E742A09B14E343E70052A486; - remoteInfo = utilities; + remoteGlobalIDString = E702E75714E1F48800CDE635; + remoteInfo = libSOSRegressions; }; - 4C8D864F177A75100019A804 /* PBXContainerItemProxy */ = { + E7E0D8FA158FAB3B002CA176 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 4C2FEC4915755D700008BE39 /* utilities.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 18270F5414CF651900B05E7F; - remoteInfo = libsecipc_client; - }; - 4CB23B75169F5873003A0131 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = E71049F2169E023B00DB0045; - remoteInfo = libSecurityTool; - }; - 4CB23B77169F5873003A0131 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = E7104A1D169E216E00DB0045; - remoteInfo = libSecurityCommands; + remoteGlobalIDString = E7E0D8E8158FA9A3002CA176; + remoteInfo = libutilitiesRegressions; }; - 4CB23B79169F5873003A0131 /* PBXContainerItemProxy */ = { + E7E0D8FD158FAB3B002CA176 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 4C2FEC4915755D700008BE39 /* utilities.xcodeproj */; proxyType = 2; - remoteGlobalIDString = E7FEFB8C169E363300E18152; - remoteInfo = libSOSCommands; - }; - 4CB23B83169F5961003A0131 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = E7FEFB82169E363300E18152; - remoteInfo = libSOSCommands; - }; - 4CB23B85169F5971003A0131 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = E7104A12169E216E00DB0045; - remoteInfo = libSecurityCommands; - }; - 4CB23B87169F597D003A0131 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = E71049F1169E023B00DB0045; - remoteInfo = libSecurityTool; + remoteGlobalIDString = E7E0D8F9158FA9A3002CA176; + remoteInfo = libutilitiesRegressions; }; - 4CB23B8F169F59D8003A0131 /* PBXContainerItemProxy */ = { + E7E0D8FF158FAB52002CA176 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + containerPortal = 4C2FEC4915755D700008BE39 /* utilities.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 4CB23B45169F5873003A0131; - remoteInfo = security2; + remoteGlobalIDString = E7E0D8E8158FA9A3002CA176; + remoteInfo = libutilitiesRegressions; }; - 5208C0FD16A0D3980062DDC5 /* PBXContainerItemProxy */ = { + E7EE5A33139DC042005C78BE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 4C8786A10B03E05D00BB77D4 /* libDER.xcodeproj */; proxyType = 1; - remoteGlobalIDString = E702E73514E1F3EA00CDE635; - remoteInfo = libSecureObjectSync; + remoteGlobalIDString = 053BA313091C00BF00A7007A; + remoteInfo = libDER; }; - 5214701716977D1D00DF0DB3 /* PBXContainerItemProxy */ = { + E7F0FC161651DA5E002BEC2D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; + containerPortal = 4C2FEC4915755D700008BE39 /* utilities.xcodeproj */; proxyType = 1; remoteGlobalIDString = E742A09B14E343E70052A486; remoteInfo = utilities; }; - 5214701916977D2500DF0DB3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 5284029F164445760035F320; - remoteInfo = libCloudKeychainProxy; - }; - 521470281697842500DF0DB3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 5214700516977CB800DF0DB3; - remoteInfo = CloudKeychainProxy; - }; - 529FF21F1523BD7F0029D842 /* PBXContainerItemProxy */ = { + E7FEFB8E169E36B000E18152 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 52200F8714F2B87F00F7F6E7; - remoteInfo = XPCTimeStampingService; - }; - 52B5A8F5151928B400664F11 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 52200F8F14F2B88000F7F6E7; - remoteInfo = XPCTimeStampingService; + remoteGlobalIDString = E7FEFB8C169E363300E18152; + remoteInfo = libSOSCommands; }; - 721680B2179B4C6C00406BB4 /* PBXContainerItemProxy */ = { + E7FEFB92169E377900E18152 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + containerPortal = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 721680A4179B40F600406BB4; - remoteInfo = iCloudStats; - }; - 722CF217175D602F00BCE0A5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 72756BFD175D485D00F52070; - remoteInfo = cloud_keychain_diagnose; - }; - C2432A0715C7112A0096DB5B /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = C209696015BF52040093035F; - remoteInfo = gkunpack; - }; - C2432A2415C726B50096DB5B /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = C209695F15BF52040093035F; - remoteInfo = gkunpack; - }; - EB2E1F57166D6B3700A7EF61 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = EB2E1F05166D69B800A7EF61; - remoteInfo = CodeSigningHelper; - }; - EBB9FFDF1682E71F00FF9774 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = EBB9FF6E1682E51300FF9774; - remoteInfo = CodeSigningHelper; + remoteGlobalIDString = E7FEFB82169E363300E18152; + remoteInfo = libSOSCommands; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ - 0C6D003C177B545D0095D167 /* CopyFiles */ = { + 0C0BDB2D175685B000BC1A7E /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = /private/etc/asl; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; dstSubfolderSpec = 0; files = ( - 0C6D0065177B54CB0095D167 /* com.apple.securityd in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; - 187D6B9615D4381C00E27494 /* Copy authorization.plist */ = { + 0C59B55317677BF200617746 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; - dstPath = "$(SYSTEM_LIBRARY_DIR)/Security"; + dstPath = "$(INDIGO_INSTALL_PATH_PREFIX)/private/etc/asl"; dstSubfolderSpec = 0; files = ( - 187D6B9715D438AD00E27494 /* authorization.plist in Copy authorization.plist */, + 0C59B55417677C3E00617746 /* com.apple.securityd in CopyFiles */, ); - name = "Copy authorization.plist"; runOnlyForDeploymentPostprocessing = 1; }; - 18BEB19914CF7F0B00C8BD36 /* CopyFiles */ = { + 4C50AD081410673800EE92DE /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = /System/Library/LaunchAgents; + buildActionMask = 2147483647; + dstPath = DigiNotar; + dstSubfolderSpec = 7; + files = ( + 4C50AD0C1410679000EE92DE /* Invalid-asterisk.google.com.crt in CopyFiles */, + 4C50AD0D1410679000EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in CopyFiles */, + 4C50AD0E1410679000EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in CopyFiles */, + 4C50AD0F1410679000EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in CopyFiles */, + 4C50AD101410679000EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in CopyFiles */, + 4C50AD111410679000EE92DE /* diginotar-public-ca-2025-Cert.crt in CopyFiles */, + 4C50AD121410679000EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in CopyFiles */, + 4C50AD131410679000EE92DE /* diginotar-services-diginotar-root-Cert.crt in CopyFiles */, + 4C50AD141410679000EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in CopyFiles */, + 4C50AD151410679000EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in CopyFiles */, + 4C8B91C91416ED7E00A254E2 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in CopyFiles */, + 4C8B91CA1416ED7E00A254E2 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in CopyFiles */, + 4C8B91CB1416ED7E00A254E2 /* Invalid-diginotarpkioverheidcaoverheid.crt in CopyFiles */, + 4C8B91CC1416ED7E00A254E2 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in CopyFiles */, + 4C8B91CD1416ED7E00A254E2 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in CopyFiles */, + 4C8B91CE1416ED7E00A254E2 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt in CopyFiles */, + 4C8B91CF1416ED7E00A254E2 /* staatdernederlandenorganisatieca-g2-Cert.crt in CopyFiles */, + 4C8B91D01416ED7E00A254E2 /* staatdernederlandenoverheidca-Cert.crt in CopyFiles */, + 4C8B91D11416ED7E00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C50AD091410675400EE92DE /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "DigiNotar-Entrust"; + dstSubfolderSpec = 7; + files = ( + 4C50AD181410679900EE92DE /* Invalid-asterisk.google.com.crt in CopyFiles */, + 4C50AD191410679900EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in CopyFiles */, + 4C50AD1A1410679900EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in CopyFiles */, + 4C50AD1B1410679900EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in CopyFiles */, + 4C50AD1C1410679900EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in CopyFiles */, + 4C50AD1D1410679900EE92DE /* diginotar-public-ca-2025-Cert.crt in CopyFiles */, + 4C50AD1E1410679900EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in CopyFiles */, + 4C50AD1F1410679900EE92DE /* diginotar-services-diginotar-root-Cert.crt in CopyFiles */, + 4C50AD201410679900EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in CopyFiles */, + 4C50AD211410679900EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in CopyFiles */, + 4C50AD221410679900EE92DE /* diginotar.root.ca-entrust-secure-server-Cert.crt in CopyFiles */, + 4C8B91D21416ED8E00A254E2 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in CopyFiles */, + 4C8B91D31416ED8E00A254E2 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in CopyFiles */, + 4C8B91D41416ED8E00A254E2 /* Invalid-diginotarpkioverheidcaoverheid.crt in CopyFiles */, + 4C8B91D51416ED8E00A254E2 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in CopyFiles */, + 4C8B91D61416ED8E00A254E2 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in CopyFiles */, + 4C8B91D71416ED8E00A254E2 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt in CopyFiles */, + 4C8B91D81416ED8E00A254E2 /* staatdernederlandenorganisatieca-g2-Cert.crt in CopyFiles */, + 4C8B91D91416ED8E00A254E2 /* staatdernederlandenoverheidca-Cert.crt in CopyFiles */, + 4C8B91DA1416ED8E00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C50AD0A1410676300EE92DE /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "DigiNotar-ok"; + dstSubfolderSpec = 7; + files = ( + 4C50AD23141067A100EE92DE /* DigiNotarCA2007RootCertificate.crt in CopyFiles */, + 4C8B91E41416ED9A00A254E2 /* DigiNotar_Root_CA_G2-RootCertificate.crt in CopyFiles */, + 4C50AD24141067A100EE92DE /* Invalid-asterisk.google.com.crt in CopyFiles */, + 4C50AD25141067A100EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in CopyFiles */, + 4C50AD26141067A100EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in CopyFiles */, + 4C50AD27141067A100EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in CopyFiles */, + 4C50AD28141067A100EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in CopyFiles */, + 4C50AD29141067A100EE92DE /* diginotar-public-ca-2025-Cert.crt in CopyFiles */, + 4C50AD2A141067A100EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in CopyFiles */, + 4C50AD2B141067A100EE92DE /* diginotar-services-diginotar-root-Cert.crt in CopyFiles */, + 4C50AD2C141067A100EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in CopyFiles */, + 4C50AD2D141067A100EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in CopyFiles */, + 4C8B91DB1416ED9400A254E2 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in CopyFiles */, + 4C8B91E31416ED9400A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in CopyFiles */, + 4C50AD30141068C100EE92DE /* Expectations.plist in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C50AD3414106A2900EE92DE /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = DigiNotar; + dstSubfolderSpec = 7; + files = ( + 4C50AD3914106A4E00EE92DE /* Invalid-asterisk.google.com.crt in CopyFiles */, + 4C50AD3A14106A4E00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in CopyFiles */, + 4C50AD3B14106A4E00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in CopyFiles */, + 4C50AD3C14106A4E00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in CopyFiles */, + 4C50AD3D14106A4E00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in CopyFiles */, + 4C50AD3E14106A4E00EE92DE /* diginotar-public-ca-2025-Cert.crt in CopyFiles */, + 4C50AD3F14106A4E00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in CopyFiles */, + 4C50AD4014106A4E00EE92DE /* diginotar-services-diginotar-root-Cert.crt in CopyFiles */, + 4C50AD4114106A4E00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in CopyFiles */, + 4C50AD4214106A4E00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in CopyFiles */, + 4C3CECF41416E2EC00947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in CopyFiles */, + 4C3CECF51416E2FA00947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in CopyFiles */, + 4C3CECF61416E31A00947741 /* Invalid-diginotarpkioverheidcaoverheid.crt in CopyFiles */, + 4C3CECF81416E33500947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in CopyFiles */, + 4C3CECF91416E34F00947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in CopyFiles */, + 4C3CECFA1416E34F00947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt in CopyFiles */, + 4C3CECFB1416E34F00947741 /* staatdernederlandenorganisatieca-g2-Cert.crt in CopyFiles */, + 4C3CECFC1416E34F00947741 /* staatdernederlandenoverheidca-Cert.crt in CopyFiles */, + 4C8B91C81416EBB500A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C50AD3514106A2B00EE92DE /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "DigiNotar-Entrust"; + dstSubfolderSpec = 7; + files = ( + 4C8B91C61416EB8B00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in CopyFiles */, + 4C50AD4614106A5000EE92DE /* Invalid-asterisk.google.com.crt in CopyFiles */, + 4C50AD4714106A5000EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in CopyFiles */, + 4C50AD4814106A5000EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in CopyFiles */, + 4C50AD4914106A5000EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in CopyFiles */, + 4C50AD4A14106A5000EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in CopyFiles */, + 4C50AD4B14106A5000EE92DE /* diginotar-public-ca-2025-Cert.crt in CopyFiles */, + 4C50AD4C14106A5000EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in CopyFiles */, + 4C50AD4D14106A5000EE92DE /* diginotar-services-diginotar-root-Cert.crt in CopyFiles */, + 4C50AD4E14106A5000EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in CopyFiles */, + 4C50AD4F14106A5000EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in CopyFiles */, + 4C50AD5014106A5000EE92DE /* diginotar.root.ca-entrust-secure-server-Cert.crt in CopyFiles */, + 4C3CECFD1416E35400947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in CopyFiles */, + 4C3CECFE1416E35400947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in CopyFiles */, + 4C3CECFF1416E35400947741 /* Invalid-diginotarpkioverheidcaoverheid.crt in CopyFiles */, + 4C3CED001416E35400947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in CopyFiles */, + 4C3CED011416E35400947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in CopyFiles */, + 4C3CED021416E35400947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt in CopyFiles */, + 4C3CED031416E35400947741 /* staatdernederlandenorganisatieca-g2-Cert.crt in CopyFiles */, + 4C3CED041416E35400947741 /* staatdernederlandenoverheidca-Cert.crt in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C50AD3614106A2C00EE92DE /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "DigiNotar-ok"; + dstSubfolderSpec = 7; + files = ( + 4C50AD5114106A5400EE92DE /* Expectations.plist in CopyFiles */, + 4C50AD5214106A5400EE92DE /* DigiNotarCA2007RootCertificate.crt in CopyFiles */, + 4C3CECF31416E25C00947741 /* DigiNotar_Root_CA_G2-RootCertificate.crt in CopyFiles */, + 4C50AD5314106A5400EE92DE /* Invalid-asterisk.google.com.crt in CopyFiles */, + 4C50AD5414106A5400EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in CopyFiles */, + 4C50AD5514106A5400EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in CopyFiles */, + 4C50AD5614106A5400EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt in CopyFiles */, + 4C50AD5714106A5400EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in CopyFiles */, + 4C50AD5814106A5400EE92DE /* diginotar-public-ca-2025-Cert.crt in CopyFiles */, + 4C50AD5914106A5400EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt in CopyFiles */, + 4C50AD5A14106A5400EE92DE /* diginotar-services-diginotar-root-Cert.crt in CopyFiles */, + 4C50AD5B14106A5400EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt in CopyFiles */, + 4C50AD5C14106A5400EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in CopyFiles */, + 4C3CED051416E35A00947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in CopyFiles */, + 4C8B91C71416EBA400A254E2 /* Invalid-webmail.portofamsterdam.nl.crt in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C52D0B216EFC61E0079966E /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(INDIGO_INSTALL_PATH_PREFIX)/System/Library/LaunchDaemons"; dstSubfolderSpec = 0; files = ( - 18BEB19A14CF7F8100C8BD36 /* com.apple.secd.plist in CopyFiles */, + 4C52D0E916EFCCF80079966E /* com.apple.security.CircleJoinRequested.plist in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; - 18CFEE8815DEE2BA00E3F2A3 /* Copy sandbox profile */ = { + 52D82BF316A622770078DFE5 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; - dstPath = "$(SYSTEM_LIBRARY_DIR)/Sandbox/Profiles"; + dstPath = "$(INDIGO_INSTALL_PATH_PREFIX)/System/Library/LaunchDaemons/"; dstSubfolderSpec = 0; files = ( - 18CFEE8915DEE2C600E3F2A3 /* com.apple.authd.sb in Copy sandbox profile */, + 52D82BF416A622E60078DFE5 /* com.apple.security.cloudkeychainproxy.plist in CopyFiles */, ); - name = "Copy sandbox profile"; runOnlyForDeploymentPostprocessing = 1; }; - 18D6803A16B768DE00DF6D2E /* Copy asl module */ = { + 728B569F16D59979008FA3AB /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = /private/etc/asl; + buildActionMask = 2147483647; + dstPath = "$(INDIGO_INSTALL_PATH_PREFIX)/System/Library/LaunchDaemons"; dstSubfolderSpec = 0; files = ( - 18D6803B16B768F700DF6D2E /* com.apple.authd in Copy asl module */, + 5DDD0BEC16D6747700D6C0D6 /* com.apple.OTAPKIAssetTool.plist in CopyFiles */, ); - name = "Copy asl module"; runOnlyForDeploymentPostprocessing = 1; }; - 37A7CEDC197DCECD00926CE8 /* CopyFiles */ = { + 72979BE0175D095900BE8FD6 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = /AppleInternal/CoreOS/codesign_tests; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; dstSubfolderSpec = 0; files = ( - 37A7CEDD197DCEE500926CE8 /* validation.sh in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; - 37A7CF21197DD10900926CE8 /* CopyFiles */ = { + 79679E231462023800CF997F /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = DigicertMalaysia; + dstSubfolderSpec = 7; + files = ( + 79679E29146202A800CF997F /* Digisign-Server-ID-Enrich-Entrust-Cert.crt in CopyFiles */, + 7947431E1462151E00D638A3 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt in CopyFiles */, + 79679E2A146202A800CF997F /* Invalid-webmail.jaring.my.crt in CopyFiles */, + 7947431A146213DC00D638A3 /* Invalid-www.cybersecurity.my.crt in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 79679E2B146202BC00CF997F /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = DigicertMalaysia; + dstSubfolderSpec = 7; + files = ( + 79679E2C146202CB00CF997F /* Digisign-Server-ID-Enrich-Entrust-Cert.crt in CopyFiles */, + 7947431D1462151400D638A3 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt in CopyFiles */, + 79679E2D146202CB00CF997F /* Invalid-webmail.jaring.my.crt in CopyFiles */, + 7947431B146213EF00D638A3 /* Invalid-www.cybersecurity.my.crt in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 79863B6C0CADCE4300818B0D /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; - dstPath = /AppleInternal/CoreOS; + dstPath = "$(INDIGO_INSTALL_PATH_PREFIX)/System/Library/LaunchDaemons"; dstSubfolderSpec = 0; files = ( + 79863B710CADCEAB00818B0D /* com.apple.securityd.plist in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; - 4A5C178F161A9DE000ABF784 /* CopyFiles */ = { + 79DCEA52134A27D2007F57DC /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = /usr/local/include; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; dstSubfolderSpec = 0; files = ( - 4A5C1790161A9DFB00ABF784 /* authd_private.h in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; - 4C49390E16E51ED100CE110C /* CopyFiles */ = { + 79E0D700143E551F0010CE0E /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; - buildActionMask = 12; - dstPath = /System/Library/LaunchAgents; - dstSubfolderSpec = 0; + buildActionMask = 2147483647; + dstPath = "AppleID-certs"; + dstSubfolderSpec = 7; files = ( - 4C49390F16E51FC700CE110C /* com.apple.security.keychain-circle-notification.plist in CopyFiles */, + 79E0D7AD143E68D70010CE0E /* iPhoneCACert.crt in CopyFiles */, + 79E0D7A8143E672A0010CE0E /* Invalid-asset_signing.crt in CopyFiles */, + 79E0D705143E55DB0010CE0E /* Apple Application Integration Certification Authority Cert.crt in CopyFiles */, + 79E0D706143E55DB0010CE0E /* Apple Production ShareServices-7130767241416543643077536561487847634e4d6f773d3d.crt in CopyFiles */, + 79E0D707143E55DB0010CE0E /* AppleRootCertificate.crt in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; - 4CB23B44169F5873003A0131 /* CopyFiles */ = { + 79E0D708143E55F70010CE0E /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; + dstPath = "AppleID-certs"; + dstSubfolderSpec = 7; files = ( - 4CB23B4C169F5873003A0131 /* security2.1 in CopyFiles */, + 79E0D7AC143E68CF0010CE0E /* iPhoneCACert.crt in CopyFiles */, + 79E0D7A9143E673B0010CE0E /* Invalid-asset_signing.crt in CopyFiles */, + 79E0D709143E56010010CE0E /* Apple Application Integration Certification Authority Cert.crt in CopyFiles */, + 79E0D70A143E56010010CE0E /* Apple Production ShareServices-7130767241416543643077536561487847634e4d6f773d3d.crt in CopyFiles */, + 79E0D70B143E56010010CE0E /* AppleRootCertificate.crt in CopyFiles */, ); - runOnlyForDeploymentPostprocessing = 1; + runOnlyForDeploymentPostprocessing = 0; }; - 4CB86AE4167A6F3D00F46643 /* CopyFiles */ = { + BE442BBA18B7FDB800F24DAE /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; - dstPath = PrivateHeaders/SecureObjectSync; - dstSubfolderSpec = 1; + dstPath = "$(INDIGO_INSTALL_PATH_PREFIX)/System/Library/LaunchDaemons"; + dstSubfolderSpec = 0; files = ( - 4CB86AFB167A8F2200F46643 /* SOSAccount.h in CopyFiles */, - 4CB86AF0167A6FF300F46643 /* SOSCircle.h in CopyFiles */, - 4CB86AF1167A6FF300F46643 /* SOSCloudCircle.h in CopyFiles */, - 4CB86AF2167A6FF300F46643 /* SOSCloudCircleInternal.h in CopyFiles */, - 4CB86AF3167A6FF300F46643 /* SOSEngine.h in CopyFiles */, - 4CB86AF4167A6FF300F46643 /* SOSFullPeerInfo.h in CopyFiles */, - 4CB86AF5167A6FF300F46643 /* SOSInternal.h in CopyFiles */, - 4CB86AF6167A6FF300F46643 /* SOSPeer.h in CopyFiles */, - 4CB86AF7167A6FF300F46643 /* SOSPeerInfo.h in CopyFiles */, - 4CB86AF8167A6FF300F46643 /* SOSTransport.h in CopyFiles */, + BE4AC9AE18B7FFC800B84964 /* com.apple.security.swcagent.plist in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; - 5214702316977EA600DF0DB3 /* CopyFiles */ = { + CDB9FCAA179CD054000AAD66 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; - dstPath = "$(INDIGO_INSTALL_PATH_PREFIX)/System/Library/LaunchAgents/"; + dstPath = "$(INDIGO_INSTALL_PATH_PREFIX)/System/Library/Frameworks/Security.framework/CircleJoinRequested"; dstSubfolderSpec = 0; files = ( - 521470261697800500DF0DB3 /* com.apple.security.cloudkeychainproxy.plist in CopyFiles */, + CDB9FCAB179CD098000AAD66 /* Info.plist in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; - 721680A3179B40F600406BB4 /* CopyFiles */ = { + E72783F3159BDF4C00028D6C /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; - dstPath = "$(INDIGO_INSTALL_PATH_PREFIX)/System/Library/LaunchDaemons"; - dstSubfolderSpec = 0; + dstPath = Shoebox; + dstSubfolderSpec = 7; files = ( - 721680BE179B509900406BB4 /* com.apple.iCloudStats.plist in CopyFiles */, + E72783FB159BDFE900028D6C /* Apple TEST RootCertificate.crt in CopyFiles */, + E72783FC159BDFE900028D6C /* Apple Worldwide Developer Relations Certification Authority Cert.crt in CopyFiles */, + 5D83979E16025A720075998F /* Invalid.com.apple.testcard.crt in CopyFiles */, + E72783FD159BDFE900028D6C /* Apple Worldwide Developer Relations Certification Authority TEST Cert.crt in CopyFiles */, + E72783FE159BDFE900028D6C /* AppleRootCertificate.crt in CopyFiles */, ); - runOnlyForDeploymentPostprocessing = 1; + runOnlyForDeploymentPostprocessing = 0; }; - 72756BFC175D485D00F52070 /* CopyFiles */ = { + E7278400159BDFFF00028D6C /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; + dstPath = Shoebox; + dstSubfolderSpec = 7; files = ( + E7278401159BE01A00028D6C /* Apple TEST RootCertificate.crt in CopyFiles */, + E7278402159BE02300028D6C /* Apple Worldwide Developer Relations Certification Authority Cert.crt in CopyFiles */, + E7278404159BE03600028D6C /* Apple Worldwide Developer Relations Certification Authority TEST Cert.crt in CopyFiles */, + E7278403159BE03300028D6C /* AppleRootCertificate.crt in CopyFiles */, ); - runOnlyForDeploymentPostprocessing = 1; + runOnlyForDeploymentPostprocessing = 0; + }; + E73000E813D90A4400B0DA1B /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "OTATasking-certs"; + dstSubfolderSpec = 7; + files = ( + E73000EA13D90A5A00B0DA1B /* Invalid-asset_signing.crt in CopyFiles */, + E730010B13D90DB900B0DA1B /* AppleRootCertificate.crt in CopyFiles */, + E730010C13D90DB900B0DA1B /* iPhoneCACert.crt in CopyFiles */, + E73000EC13D90A5A00B0DA1B /* task_signing.crt in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E73000ED13D90A7500B0DA1B /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "OTATasking-certs"; + dstSubfolderSpec = 7; + files = ( + E73000EF13D90A7E00B0DA1B /* Invalid-asset_signing.crt in CopyFiles */, + E73000F113D90A7E00B0DA1B /* task_signing.crt in CopyFiles */, + E730010D13D90DBF00B0DA1B /* AppleRootCertificate.crt in CopyFiles */, + E730010E13D90DBF00B0DA1B /* iPhoneCACert.crt in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E730010113D90CE200B0DA1B /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "mobileasset-certs"; + dstSubfolderSpec = 7; + files = ( + E730010213D90CF200B0DA1B /* AppleRootCertificate.crt in CopyFiles */, + E730010313D90CF200B0DA1B /* asset_signing.crt in CopyFiles */, + E730010413D90CF200B0DA1B /* Invalid-task_signing.crt in CopyFiles */, + E730010513D90CF200B0DA1B /* iPhoneCACert.crt in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E730010613D90CFF00B0DA1B /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "mobileasset-certs"; + dstSubfolderSpec = 7; + files = ( + E730010713D90D0700B0DA1B /* AppleRootCertificate.crt in CopyFiles */, + E730010813D90D0700B0DA1B /* asset_signing.crt in CopyFiles */, + E730010913D90D0700B0DA1B /* Invalid-task_signing.crt in CopyFiles */, + E730010A13D90D0700B0DA1B /* iPhoneCACert.crt in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E7A94B2E13D89EBF001C5FEE /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "nist-certs"; + dstSubfolderSpec = 7; + files = ( + E7A94C9A13D8A128001C5FEE /* Expectations.plist in CopyFiles */, + E7A94B2F13D89F25001C5FEE /* AllCertificatesNoPoliciesTest2EE.crt in CopyFiles */, + E7A94B3013D89F25001C5FEE /* AllCertificatesSamePoliciesTest10EE.crt in CopyFiles */, + E7A94B3113D89F25001C5FEE /* AllCertificatesSamePoliciesTest13EE.crt in CopyFiles */, + E7A94B3213D89F25001C5FEE /* AllCertificatesanyPolicyTest11EE.crt in CopyFiles */, + E7A94B3313D89F25001C5FEE /* AnyPolicyTest14EE.crt in CopyFiles */, + E7A94B3413D89F25001C5FEE /* BadCRLIssuerNameCACert.crt in CopyFiles */, + E7A94B3513D89F25001C5FEE /* BadCRLSignatureCACert.crt in CopyFiles */, + E7A94B3613D89F25001C5FEE /* BadSignedCACert.crt in CopyFiles */, + E7A94B3713D89F25001C5FEE /* BadnotAfterDateCACert.crt in CopyFiles */, + E7A94B3813D89F25001C5FEE /* BadnotBeforeDateCACert.crt in CopyFiles */, + E7A94B3913D89F25001C5FEE /* BasicSelfIssuedCRLSigningKeyCACert.crt in CopyFiles */, + E7A94B3A13D89F25001C5FEE /* BasicSelfIssuedNewKeyCACert.crt in CopyFiles */, + E7A94B3B13D89F25001C5FEE /* BasicSelfIssuedNewKeyOldWithNewCACert.crt in CopyFiles */, + E7A94B3C13D89F25001C5FEE /* BasicSelfIssuedOldKeyCACert.crt in CopyFiles */, + E7A94B3D13D89F25001C5FEE /* BasicSelfIssuedOldKeyNewWithOldCACert.crt in CopyFiles */, + E7A94B3E13D89F25001C5FEE /* CPSPointerQualifierTest20EE.crt in CopyFiles */, + E7A94B3F13D89F25001C5FEE /* DSACACert.crt in CopyFiles */, + E7A94B4013D89F25001C5FEE /* DSAParametersInheritedCACert.crt in CopyFiles */, + E7A94B4113D89F25001C5FEE /* DifferentPoliciesTest12EE.crt in CopyFiles */, + E7A94B4213D89F25001C5FEE /* DifferentPoliciesTest3EE.crt in CopyFiles */, + E7A94B4313D89F25001C5FEE /* DifferentPoliciesTest4EE.crt in CopyFiles */, + E7A94B4413D89F25001C5FEE /* DifferentPoliciesTest5EE.crt in CopyFiles */, + E7A94B4513D89F25001C5FEE /* DifferentPoliciesTest7EE.crt in CopyFiles */, + E7A94B4613D89F25001C5FEE /* DifferentPoliciesTest8EE.crt in CopyFiles */, + E7A94B4713D89F25001C5FEE /* DifferentPoliciesTest9EE.crt in CopyFiles */, + E7A94B4813D89F25001C5FEE /* GeneralizedTimeCRLnextUpdateCACert.crt in CopyFiles */, + E7A94B4913D89F25001C5FEE /* GoodCACert.crt in CopyFiles */, + E7A94B4A13D89F25001C5FEE /* GoodsubCACert.crt in CopyFiles */, + E7A94B4B13D89F26001C5FEE /* GoodsubCAPanyPolicyMapping1to2CACert.crt in CopyFiles */, + E7A94B4C13D89F26001C5FEE /* InvalidBasicSelfIssuedNewWithOldTest5EE.crt in CopyFiles */, + E7A94B4D13D89F26001C5FEE /* InvalidBasicSelfIssuedOldWithNewTest2EE.crt in CopyFiles */, + E7A94B4E13D89F26001C5FEE /* InvalidCASignatureTest2EE.crt in CopyFiles */, + E7A94B4F13D89F26001C5FEE /* InvalidCAnotAfterDateTest5EE.crt in CopyFiles */, + E7A94B5013D89F26001C5FEE /* InvalidCAnotBeforeDateTest1EE.crt in CopyFiles */, + E7A94B5113D89F26001C5FEE /* InvalidDNSnameConstraintsTest31EE.crt in CopyFiles */, + E7A94B5213D89F26001C5FEE /* InvalidDNSnameConstraintsTest33EE.crt in CopyFiles */, + E7A94B5313D89F26001C5FEE /* InvalidDNSnameConstraintsTest38EE.crt in CopyFiles */, + E7A94B5413D89F26001C5FEE /* InvalidDNandRFC822nameConstraintsTest28EE.crt in CopyFiles */, + E7A94B5513D89F26001C5FEE /* InvalidDNandRFC822nameConstraintsTest29EE.crt in CopyFiles */, + E7A94B5613D89F26001C5FEE /* InvalidDNnameConstraintsTest10EE.crt in CopyFiles */, + E7A94B5713D89F26001C5FEE /* InvalidDNnameConstraintsTest12EE.crt in CopyFiles */, + E7A94B5813D89F26001C5FEE /* InvalidDNnameConstraintsTest13EE.crt in CopyFiles */, + E7A94B5913D89F26001C5FEE /* InvalidDNnameConstraintsTest15EE.crt in CopyFiles */, + E7A94B5A13D89F26001C5FEE /* InvalidDNnameConstraintsTest16EE.crt in CopyFiles */, + E7A94B5B13D89F26001C5FEE /* InvalidDNnameConstraintsTest17EE.crt in CopyFiles */, + E7A94B5C13D89F26001C5FEE /* InvalidDNnameConstraintsTest20EE.crt in CopyFiles */, + E7A94B5D13D89F26001C5FEE /* InvalidDNnameConstraintsTest2EE.crt in CopyFiles */, + E7A94B5E13D89F26001C5FEE /* InvalidDNnameConstraintsTest3EE.crt in CopyFiles */, + E7A94B5F13D89F26001C5FEE /* InvalidDNnameConstraintsTest7EE.crt in CopyFiles */, + E7A94B6013D89F26001C5FEE /* InvalidDNnameConstraintsTest8EE.crt in CopyFiles */, + E7A94B6113D89F26001C5FEE /* InvalidDNnameConstraintsTest9EE.crt in CopyFiles */, + E7A94B6213D89F26001C5FEE /* InvalidDSASignatureTest6EE.crt in CopyFiles */, + E7A94B6313D89F26001C5FEE /* InvalidEESignatureTest3EE.crt in CopyFiles */, + E7A94B6413D89F26001C5FEE /* InvalidEEnotAfterDateTest6EE.crt in CopyFiles */, + E7A94B6513D89F26001C5FEE /* InvalidEEnotBeforeDateTest2EE.crt in CopyFiles */, + E7A94B6613D89F26001C5FEE /* InvalidLongSerialNumberTest18EE.crt in CopyFiles */, + E7A94B6713D89F26001C5FEE /* InvalidMappingFromanyPolicyTest7EE.crt in CopyFiles */, + E7A94B6813D89F26001C5FEE /* InvalidMappingToanyPolicyTest8EE.crt in CopyFiles */, + E7A94B6913D89F26001C5FEE /* InvalidMissingbasicConstraintsTest1EE.crt in CopyFiles */, + E7A94B6A13D89F26001C5FEE /* InvalidNameChainingOrderTest2EE.crt in CopyFiles */, + E7A94B6B13D89F26001C5FEE /* InvalidNameChainingTest1EE.crt in CopyFiles */, + E7A94B6C13D89F26001C5FEE /* InvalidNegativeSerialNumberTest15EE.crt in CopyFiles */, + E7A94B6D13D89F26001C5FEE /* InvalidPolicyMappingTest10EE.crt in CopyFiles */, + E7A94B6E13D89F26001C5FEE /* InvalidPolicyMappingTest2EE.crt in CopyFiles */, + E7A94B6F13D89F26001C5FEE /* InvalidPolicyMappingTest4EE.crt in CopyFiles */, + E7A94B7013D89F26001C5FEE /* InvalidRFC822nameConstraintsTest22EE.crt in CopyFiles */, + E7A94B7113D89F26001C5FEE /* InvalidRFC822nameConstraintsTest24EE.crt in CopyFiles */, + E7A94B7213D89F26001C5FEE /* InvalidRFC822nameConstraintsTest26EE.crt in CopyFiles */, + E7A94B7313D89F26001C5FEE /* InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt in CopyFiles */, + E7A94B7413D89F26001C5FEE /* InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt in CopyFiles */, + E7A94B7513D89F26001C5FEE /* InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt in CopyFiles */, + E7A94B7613D89F26001C5FEE /* InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt in CopyFiles */, + E7A94B7713D89F26001C5FEE /* InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt in CopyFiles */, + E7A94B7813D89F26001C5FEE /* InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt in CopyFiles */, + E7A94B7913D89F26001C5FEE /* InvalidSelfIssuedpathLenConstraintTest16EE.crt in CopyFiles */, + E7A94B7A13D89F26001C5FEE /* InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt in CopyFiles */, + E7A94B7B13D89F26001C5FEE /* InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt in CopyFiles */, + E7A94B7C13D89F26001C5FEE /* InvalidURInameConstraintsTest35EE.crt in CopyFiles */, + E7A94B7D13D89F26001C5FEE /* InvalidURInameConstraintsTest37EE.crt in CopyFiles */, + E7A94B7E13D89F26001C5FEE /* InvalidUnknownCriticalCertificateExtensionTest2EE.crt in CopyFiles */, + E7A94B7F13D89F26001C5FEE /* InvalidcAFalseTest2EE.crt in CopyFiles */, + E7A94B8013D89F26001C5FEE /* InvalidcAFalseTest3EE.crt in CopyFiles */, + E7A94B8113D89F26001C5FEE /* InvalidcRLIssuerTest27EE.crt in CopyFiles */, + E7A94B8213D89F26001C5FEE /* InvalidcRLIssuerTest31EE.crt in CopyFiles */, + E7A94B8313D89F26001C5FEE /* InvalidcRLIssuerTest32EE.crt in CopyFiles */, + E7A94B8413D89F26001C5FEE /* InvalidcRLIssuerTest34EE.crt in CopyFiles */, + E7A94B8513D89F26001C5FEE /* InvalidcRLIssuerTest35EE.crt in CopyFiles */, + E7A94B8613D89F26001C5FEE /* InvalidinhibitAnyPolicyTest1EE.crt in CopyFiles */, + E7A94B8713D89F26001C5FEE /* InvalidinhibitAnyPolicyTest4EE.crt in CopyFiles */, + E7A94B8813D89F26001C5FEE /* InvalidinhibitAnyPolicyTest5EE.crt in CopyFiles */, + E7A94B8913D89F26001C5FEE /* InvalidinhibitAnyPolicyTest6EE.crt in CopyFiles */, + E7A94B8A13D89F26001C5FEE /* InvalidinhibitPolicyMappingTest1EE.crt in CopyFiles */, + E7A94B8B13D89F26001C5FEE /* InvalidinhibitPolicyMappingTest3EE.crt in CopyFiles */, + E7A94B8C13D89F26001C5FEE /* InvalidinhibitPolicyMappingTest5EE.crt in CopyFiles */, + E7A94B8D13D89F26001C5FEE /* InvalidinhibitPolicyMappingTest6EE.crt in CopyFiles */, + E7A94B8E13D89F26001C5FEE /* InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt in CopyFiles */, + E7A94B8F13D89F26001C5FEE /* InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt in CopyFiles */, + E7A94B9013D89F26001C5FEE /* InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt in CopyFiles */, + E7A94B9113D89F26001C5FEE /* InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt in CopyFiles */, + E7A94B9213D89F26001C5FEE /* InvalidonlyContainsAttributeCertsTest14EE.crt in CopyFiles */, + E7A94B9313D89F26001C5FEE /* InvalidonlyContainsCACertsTest12EE.crt in CopyFiles */, + E7A94B9413D89F26001C5FEE /* InvalidonlyContainsUserCertsTest11EE.crt in CopyFiles */, + E7A94B9513D89F26001C5FEE /* InvalidonlySomeReasonsTest15EE.crt in CopyFiles */, + E7A94B9613D89F26001C5FEE /* InvalidonlySomeReasonsTest16EE.crt in CopyFiles */, + E7A94B9713D89F26001C5FEE /* InvalidonlySomeReasonsTest17EE.crt in CopyFiles */, + E7A94B9813D89F26001C5FEE /* InvalidonlySomeReasonsTest20EE.crt in CopyFiles */, + E7A94B9913D89F26001C5FEE /* InvalidonlySomeReasonsTest21EE.crt in CopyFiles */, + E7A94B9A13D89F26001C5FEE /* InvalidpathLenConstraintTest10EE.crt in CopyFiles */, + E7A94B9B13D89F26001C5FEE /* InvalidpathLenConstraintTest11EE.crt in CopyFiles */, + E7A94B9C13D89F26001C5FEE /* InvalidpathLenConstraintTest12EE.crt in CopyFiles */, + E7A94B9D13D89F26001C5FEE /* InvalidpathLenConstraintTest5EE.crt in CopyFiles */, + E7A94B9E13D89F26001C5FEE /* InvalidpathLenConstraintTest6EE.crt in CopyFiles */, + E7A94B9F13D89F26001C5FEE /* InvalidpathLenConstraintTest9EE.crt in CopyFiles */, + E7A94BA013D89F26001C5FEE /* Invalidpre2000UTCEEnotAfterDateTest7EE.crt in CopyFiles */, + E7A94BA113D89F26001C5FEE /* InvalidrequireExplicitPolicyTest3EE.crt in CopyFiles */, + E7A94BA213D89F26001C5FEE /* InvalidrequireExplicitPolicyTest5EE.crt in CopyFiles */, + E7A94BA313D89F26001C5FEE /* LongSerialNumberCACert.crt in CopyFiles */, + E7A94BA413D89F26001C5FEE /* Mapping1to2CACert.crt in CopyFiles */, + E7A94BA513D89F26001C5FEE /* MappingFromanyPolicyCACert.crt in CopyFiles */, + E7A94BA613D89F26001C5FEE /* MappingToanyPolicyCACert.crt in CopyFiles */, + E7A94BA713D89F26001C5FEE /* MissingbasicConstraintsCACert.crt in CopyFiles */, + E7A94BA813D89F26001C5FEE /* NameOrderingCACert.crt in CopyFiles */, + E7A94BA913D89F26001C5FEE /* NegativeSerialNumberCACert.crt in CopyFiles */, + E7A94BAA13D89F26001C5FEE /* NoCRLCACert.crt in CopyFiles */, + E7A94BAB13D89F26001C5FEE /* NoPoliciesCACert.crt in CopyFiles */, + E7A94BAC13D89F26001C5FEE /* NoissuingDistributionPointCACert.crt in CopyFiles */, + E7A94BAD13D89F26001C5FEE /* OldCRLnextUpdateCACert.crt in CopyFiles */, + E7A94BAE13D89F26001C5FEE /* OverlappingPoliciesTest6EE.crt in CopyFiles */, + E7A94BAF13D89F26001C5FEE /* P12Mapping1to3CACert.crt in CopyFiles */, + E7A94BB013D89F26001C5FEE /* P12Mapping1to3subCACert.crt in CopyFiles */, + E7A94BB113D89F26001C5FEE /* P12Mapping1to3subsubCACert.crt in CopyFiles */, + E7A94BB213D89F26001C5FEE /* P1Mapping1to234CACert.crt in CopyFiles */, + E7A94BB313D89F26001C5FEE /* P1Mapping1to234subCACert.crt in CopyFiles */, + E7A94BB413D89F26001C5FEE /* P1anyPolicyMapping1to2CACert.crt in CopyFiles */, + E7A94BB513D89F26001C5FEE /* PanyPolicyMapping1to2CACert.crt in CopyFiles */, + E7A94BB613D89F26001C5FEE /* PoliciesP1234CACert.crt in CopyFiles */, + E7A94BB713D89F26001C5FEE /* PoliciesP1234subCAP123Cert.crt in CopyFiles */, + E7A94BB813D89F26001C5FEE /* PoliciesP1234subsubCAP123P12Cert.crt in CopyFiles */, + E7A94BB913D89F26001C5FEE /* PoliciesP123CACert.crt in CopyFiles */, + E7A94BBA13D89F26001C5FEE /* PoliciesP123subCAP12Cert.crt in CopyFiles */, + E7A94BBB13D89F26001C5FEE /* PoliciesP123subsubCAP12P1Cert.crt in CopyFiles */, + E7A94BBC13D89F26001C5FEE /* PoliciesP123subsubCAP12P2Cert.crt in CopyFiles */, + E7A94BBD13D89F26001C5FEE /* PoliciesP123subsubsubCAP12P2P1Cert.crt in CopyFiles */, + E7A94BBE13D89F26001C5FEE /* PoliciesP12CACert.crt in CopyFiles */, + E7A94BBF13D89F26001C5FEE /* PoliciesP12subCAP1Cert.crt in CopyFiles */, + E7A94BC013D89F26001C5FEE /* PoliciesP12subsubCAP1P2Cert.crt in CopyFiles */, + E7A94BC113D89F26001C5FEE /* PoliciesP2subCA2Cert.crt in CopyFiles */, + E7A94BC213D89F26001C5FEE /* PoliciesP2subCACert.crt in CopyFiles */, + E7A94BC313D89F26001C5FEE /* PoliciesP3CACert.crt in CopyFiles */, + E7A94BC413D89F26001C5FEE /* RFC3280MandatoryAttributeTypesCACert.crt in CopyFiles */, + E7A94BC513D89F26001C5FEE /* RFC3280OptionalAttributeTypesCACert.crt in CopyFiles */, + E7A94BC613D89F26001C5FEE /* RevokedsubCACert.crt in CopyFiles */, + E7A94BC713D89F26001C5FEE /* RolloverfromPrintableStringtoUTF8StringCACert.crt in CopyFiles */, + E7A94BC813D89F26001C5FEE /* SeparateCertificateandCRLKeysCA2CRLSigningCert.crt in CopyFiles */, + E7A94BC913D89F26001C5FEE /* SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt in CopyFiles */, + E7A94BCA13D89F26001C5FEE /* SeparateCertificateandCRLKeysCertificateSigningCACert.crt in CopyFiles */, + E7A94BCB13D89F26001C5FEE /* TrustAnchorRootCertificate.crt in CopyFiles */, + E7A94BCC13D89F26001C5FEE /* TwoCRLsCACert.crt in CopyFiles */, + E7A94BCD13D89F26001C5FEE /* UIDCACert.crt in CopyFiles */, + E7A94BCE13D89F26001C5FEE /* UTF8StringCaseInsensitiveMatchCACert.crt in CopyFiles */, + E7A94BCF13D89F26001C5FEE /* UTF8StringEncodedNamesCACert.crt in CopyFiles */, + E7A94BD013D89F26001C5FEE /* UnknownCRLEntryExtensionCACert.crt in CopyFiles */, + E7A94BD113D89F26001C5FEE /* UnknownCRLExtensionCACert.crt in CopyFiles */, + E7A94BD213D89F26001C5FEE /* UserNoticeQualifierTest15EE.crt in CopyFiles */, + E7A94BD313D89F26001C5FEE /* UserNoticeQualifierTest16EE.crt in CopyFiles */, + E7A94BD413D89F26001C5FEE /* UserNoticeQualifierTest17EE.crt in CopyFiles */, + E7A94BD513D89F26001C5FEE /* UserNoticeQualifierTest18EE.crt in CopyFiles */, + E7A94BD613D89F26001C5FEE /* UserNoticeQualifierTest19EE.crt in CopyFiles */, + E7A94BD713D89F26001C5FEE /* ValidBasicSelfIssuedNewWithOldTest3EE.crt in CopyFiles */, + E7A94BD813D89F26001C5FEE /* ValidBasicSelfIssuedNewWithOldTest4EE.crt in CopyFiles */, + E7A94BD913D89F26001C5FEE /* ValidBasicSelfIssuedOldWithNewTest1EE.crt in CopyFiles */, + E7A94BDA13D89F26001C5FEE /* ValidCertificatePathTest1EE.crt in CopyFiles */, + E7A94BDB13D89F26001C5FEE /* ValidDNSnameConstraintsTest30EE.crt in CopyFiles */, + E7A94BDC13D89F26001C5FEE /* ValidDNSnameConstraintsTest32EE.crt in CopyFiles */, + E7A94BDD13D89F26001C5FEE /* ValidDNandRFC822nameConstraintsTest27EE.crt in CopyFiles */, + E7A94BDE13D89F26001C5FEE /* ValidDNnameConstraintsTest11EE.crt in CopyFiles */, + E7A94BDF13D89F26001C5FEE /* ValidDNnameConstraintsTest14EE.crt in CopyFiles */, + E7A94BE013D89F26001C5FEE /* ValidDNnameConstraintsTest18EE.crt in CopyFiles */, + E7A94BE113D89F26001C5FEE /* ValidDNnameConstraintsTest19EE.crt in CopyFiles */, + E7A94BE213D89F26001C5FEE /* ValidDNnameConstraintsTest1EE.crt in CopyFiles */, + E7A94BE313D89F26001C5FEE /* ValidDNnameConstraintsTest4EE.crt in CopyFiles */, + E7A94BE413D89F26001C5FEE /* ValidDNnameConstraintsTest5EE.crt in CopyFiles */, + E7A94BE513D89F26001C5FEE /* ValidDNnameConstraintsTest6EE.crt in CopyFiles */, + E7A94BE613D89F26001C5FEE /* ValidDSAParameterInheritanceTest5EE.crt in CopyFiles */, + E7A94BE713D89F26001C5FEE /* ValidDSASignaturesTest4EE.crt in CopyFiles */, + E7A94BE813D89F26001C5FEE /* ValidGeneralizedTimenotAfterDateTest8EE.crt in CopyFiles */, + E7A94BE913D89F26001C5FEE /* ValidGeneralizedTimenotBeforeDateTest4EE.crt in CopyFiles */, + E7A94BEA13D89F26001C5FEE /* ValidLongSerialNumberTest16EE.crt in CopyFiles */, + E7A94BEB13D89F26001C5FEE /* ValidLongSerialNumberTest17EE.crt in CopyFiles */, + E7A94BEC13D89F26001C5FEE /* ValidNameChainingCapitalizationTest5EE.crt in CopyFiles */, + E7A94BED13D89F26001C5FEE /* ValidNameChainingWhitespaceTest3EE.crt in CopyFiles */, + E7A94BEE13D89F26001C5FEE /* ValidNameChainingWhitespaceTest4EE.crt in CopyFiles */, + E7A94BEF13D89F26001C5FEE /* ValidNameUIDsTest6EE.crt in CopyFiles */, + E7A94BF013D89F26001C5FEE /* ValidNegativeSerialNumberTest14EE.crt in CopyFiles */, + E7A94BF113D89F26001C5FEE /* ValidPolicyMappingTest11EE.crt in CopyFiles */, + E7A94BF213D89F26001C5FEE /* ValidPolicyMappingTest12EE.crt in CopyFiles */, + E7A94BF313D89F26001C5FEE /* ValidPolicyMappingTest13EE.crt in CopyFiles */, + E7A94BF413D89F26001C5FEE /* ValidPolicyMappingTest14EE.crt in CopyFiles */, + E7A94BF513D89F26001C5FEE /* ValidPolicyMappingTest1EE.crt in CopyFiles */, + E7A94BF613D89F26001C5FEE /* ValidPolicyMappingTest3EE.crt in CopyFiles */, + E7A94BF713D89F26001C5FEE /* ValidPolicyMappingTest5EE.crt in CopyFiles */, + E7A94BF813D89F26001C5FEE /* ValidPolicyMappingTest6EE.crt in CopyFiles */, + E7A94BF913D89F26001C5FEE /* ValidPolicyMappingTest9EE.crt in CopyFiles */, + E7A94BFA13D89F26001C5FEE /* ValidRFC3280MandatoryAttributeTypesTest7EE.crt in CopyFiles */, + E7A94BFB13D89F26001C5FEE /* ValidRFC3280OptionalAttributeTypesTest8EE.crt in CopyFiles */, + E7A94BFC13D89F26001C5FEE /* ValidRFC822nameConstraintsTest21EE.crt in CopyFiles */, + E7A94BFD13D89F26001C5FEE /* ValidRFC822nameConstraintsTest23EE.crt in CopyFiles */, + E7A94BFE13D89F26001C5FEE /* ValidRFC822nameConstraintsTest25EE.crt in CopyFiles */, + E7A94BFF13D89F26001C5FEE /* ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt in CopyFiles */, + E7A94C0013D89F26001C5FEE /* ValidSelfIssuedinhibitAnyPolicyTest7EE.crt in CopyFiles */, + E7A94C0113D89F26001C5FEE /* ValidSelfIssuedinhibitAnyPolicyTest9EE.crt in CopyFiles */, + E7A94C0213D89F26001C5FEE /* ValidSelfIssuedinhibitPolicyMappingTest7EE.crt in CopyFiles */, + E7A94C0313D89F26001C5FEE /* ValidSelfIssuedpathLenConstraintTest15EE.crt in CopyFiles */, + E7A94C0413D89F26001C5FEE /* ValidSelfIssuedpathLenConstraintTest17EE.crt in CopyFiles */, + E7A94C0513D89F26001C5FEE /* ValidSelfIssuedrequireExplicitPolicyTest6EE.crt in CopyFiles */, + E7A94C0613D89F26001C5FEE /* ValidURInameConstraintsTest34EE.crt in CopyFiles */, + E7A94C0713D89F26001C5FEE /* ValidURInameConstraintsTest36EE.crt in CopyFiles */, + E7A94C0813D89F26001C5FEE /* ValidUTF8StringCaseInsensitiveMatchTest11EE.crt in CopyFiles */, + E7A94C0913D89F26001C5FEE /* ValidUTF8StringEncodedNamesTest9EE.crt in CopyFiles */, + E7A94C0A13D89F26001C5FEE /* ValidUnknownNotCriticalCertificateExtensionTest1EE.crt in CopyFiles */, + E7A94C0B13D89F26001C5FEE /* ValidbasicConstraintsNotCriticalTest4EE.crt in CopyFiles */, + E7A94C0C13D89F26001C5FEE /* ValidcRLIssuerTest28EE.crt in CopyFiles */, + E7A94C0D13D89F26001C5FEE /* ValidcRLIssuerTest29EE.crt in CopyFiles */, + E7A94C0E13D89F26001C5FEE /* ValidcRLIssuerTest30EE.crt in CopyFiles */, + E7A94C0F13D89F26001C5FEE /* ValidcRLIssuerTest33EE.crt in CopyFiles */, + E7A94C1013D89F26001C5FEE /* ValidinhibitAnyPolicyTest2EE.crt in CopyFiles */, + E7A94C1113D89F26001C5FEE /* ValidinhibitPolicyMappingTest2EE.crt in CopyFiles */, + E7A94C1213D89F27001C5FEE /* ValidinhibitPolicyMappingTest4EE.crt in CopyFiles */, + E7A94C1313D89F27001C5FEE /* ValidkeyUsageNotCriticalTest3EE.crt in CopyFiles */, + E7A94C1413D89F27001C5FEE /* ValidonlyContainsCACertsTest13EE.crt in CopyFiles */, + E7A94C1513D89F27001C5FEE /* ValidonlySomeReasonsTest18EE.crt in CopyFiles */, + E7A94C1613D89F27001C5FEE /* ValidonlySomeReasonsTest19EE.crt in CopyFiles */, + E7A94C1713D89F27001C5FEE /* ValidpathLenConstraintTest13EE.crt in CopyFiles */, + E7A94C1813D89F27001C5FEE /* ValidpathLenConstraintTest14EE.crt in CopyFiles */, + E7A94C1913D89F27001C5FEE /* ValidpathLenConstraintTest7EE.crt in CopyFiles */, + E7A94C1A13D89F27001C5FEE /* ValidpathLenConstraintTest8EE.crt in CopyFiles */, + E7A94C1B13D89F27001C5FEE /* Validpre2000UTCnotBeforeDateTest3EE.crt in CopyFiles */, + E7A94C1C13D89F27001C5FEE /* ValidrequireExplicitPolicyTest1EE.crt in CopyFiles */, + E7A94C1D13D89F27001C5FEE /* ValidrequireExplicitPolicyTest2EE.crt in CopyFiles */, + E7A94C1E13D89F27001C5FEE /* ValidrequireExplicitPolicyTest4EE.crt in CopyFiles */, + E7A94C1F13D89F27001C5FEE /* WrongCRLCACert.crt in CopyFiles */, + E7A94C2013D89F27001C5FEE /* anyPolicyCACert.crt in CopyFiles */, + E7A94C2113D89F27001C5FEE /* basicConstraintsCriticalcAFalseCACert.crt in CopyFiles */, + E7A94C2213D89F27001C5FEE /* basicConstraintsNotCriticalCACert.crt in CopyFiles */, + E7A94C2313D89F27001C5FEE /* basicConstraintsNotCriticalcAFalseCACert.crt in CopyFiles */, + E7A94C2413D89F27001C5FEE /* deltaCRLCA1Cert.crt in CopyFiles */, + E7A94C2513D89F27001C5FEE /* deltaCRLCA2Cert.crt in CopyFiles */, + E7A94C2613D89F27001C5FEE /* deltaCRLCA3Cert.crt in CopyFiles */, + E7A94C2713D89F27001C5FEE /* deltaCRLIndicatorNoBaseCACert.crt in CopyFiles */, + E7A94C2813D89F27001C5FEE /* distributionPoint1CACert.crt in CopyFiles */, + E7A94C2913D89F27001C5FEE /* distributionPoint2CACert.crt in CopyFiles */, + E7A94C2A13D89F27001C5FEE /* indirectCRLCA1Cert.crt in CopyFiles */, + E7A94C2B13D89F27001C5FEE /* indirectCRLCA2Cert.crt in CopyFiles */, + E7A94C2C13D89F27001C5FEE /* indirectCRLCA3Cert.crt in CopyFiles */, + E7A94C2D13D89F27001C5FEE /* indirectCRLCA3cRLIssuerCert.crt in CopyFiles */, + E7A94C2E13D89F27001C5FEE /* indirectCRLCA4Cert.crt in CopyFiles */, + E7A94C2F13D89F27001C5FEE /* indirectCRLCA4cRLIssuerCert.crt in CopyFiles */, + E7A94C3013D89F27001C5FEE /* indirectCRLCA5Cert.crt in CopyFiles */, + E7A94C3113D89F27001C5FEE /* indirectCRLCA6Cert.crt in CopyFiles */, + E7A94C3213D89F27001C5FEE /* inhibitAnyPolicy0CACert.crt in CopyFiles */, + E7A94C3313D89F27001C5FEE /* inhibitAnyPolicy1CACert.crt in CopyFiles */, + E7A94C3413D89F27001C5FEE /* inhibitAnyPolicy1SelfIssuedCACert.crt in CopyFiles */, + E7A94C3513D89F27001C5FEE /* inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt in CopyFiles */, + E7A94C3613D89F27001C5FEE /* inhibitAnyPolicy1subCA1Cert.crt in CopyFiles */, + E7A94C3713D89F27001C5FEE /* inhibitAnyPolicy1subCA2Cert.crt in CopyFiles */, + E7A94C3813D89F27001C5FEE /* inhibitAnyPolicy1subCAIAP5Cert.crt in CopyFiles */, + E7A94C3913D89F27001C5FEE /* inhibitAnyPolicy1subsubCA2Cert.crt in CopyFiles */, + E7A94C3A13D89F27001C5FEE /* inhibitAnyPolicy5CACert.crt in CopyFiles */, + E7A94C3B13D89F27001C5FEE /* inhibitAnyPolicy5subCACert.crt in CopyFiles */, + E7A94C3C13D89F27001C5FEE /* inhibitAnyPolicy5subsubCACert.crt in CopyFiles */, + E7A94C3D13D89F27001C5FEE /* inhibitAnyPolicyTest3EE.crt in CopyFiles */, + E7A94C3E13D89F27001C5FEE /* inhibitPolicyMapping0CACert.crt in CopyFiles */, + E7A94C3F13D89F27001C5FEE /* inhibitPolicyMapping0subCACert.crt in CopyFiles */, + E7A94C4013D89F27001C5FEE /* inhibitPolicyMapping1P12CACert.crt in CopyFiles */, + E7A94C4113D89F27001C5FEE /* inhibitPolicyMapping1P12subCACert.crt in CopyFiles */, + E7A94C4213D89F27001C5FEE /* inhibitPolicyMapping1P12subCAIPM5Cert.crt in CopyFiles */, + E7A94C4313D89F27001C5FEE /* inhibitPolicyMapping1P12subsubCACert.crt in CopyFiles */, + E7A94C4413D89F27001C5FEE /* inhibitPolicyMapping1P12subsubCAIPM5Cert.crt in CopyFiles */, + E7A94C4513D89F27001C5FEE /* inhibitPolicyMapping1P1CACert.crt in CopyFiles */, + E7A94C4613D89F27001C5FEE /* inhibitPolicyMapping1P1SelfIssuedCACert.crt in CopyFiles */, + E7A94C4713D89F27001C5FEE /* inhibitPolicyMapping1P1SelfIssuedsubCACert.crt in CopyFiles */, + E7A94C4813D89F27001C5FEE /* inhibitPolicyMapping1P1subCACert.crt in CopyFiles */, + E7A94C4913D89F27001C5FEE /* inhibitPolicyMapping1P1subsubCACert.crt in CopyFiles */, + E7A94C4A13D89F27001C5FEE /* inhibitPolicyMapping5CACert.crt in CopyFiles */, + E7A94C4B13D89F27001C5FEE /* inhibitPolicyMapping5subCACert.crt in CopyFiles */, + E7A94C4C13D89F27001C5FEE /* inhibitPolicyMapping5subsubCACert.crt in CopyFiles */, + E7A94C4D13D89F27001C5FEE /* inhibitPolicyMapping5subsubsubCACert.crt in CopyFiles */, + E7A94C4E13D89F27001C5FEE /* keyUsageCriticalcRLSignFalseCACert.crt in CopyFiles */, + E7A94C4F13D89F27001C5FEE /* keyUsageCriticalkeyCertSignFalseCACert.crt in CopyFiles */, + E7A94C5013D89F27001C5FEE /* keyUsageNotCriticalCACert.crt in CopyFiles */, + E7A94C5113D89F27001C5FEE /* keyUsageNotCriticalcRLSignFalseCACert.crt in CopyFiles */, + E7A94C5213D89F27001C5FEE /* keyUsageNotCriticalkeyCertSignFalseCACert.crt in CopyFiles */, + E7A94C5313D89F27001C5FEE /* nameConstraintsDN1CACert.crt in CopyFiles */, + E7A94C5413D89F27001C5FEE /* nameConstraintsDN1SelfIssuedCACert.crt in CopyFiles */, + E7A94C5513D89F27001C5FEE /* nameConstraintsDN1subCA1Cert.crt in CopyFiles */, + E7A94C5613D89F27001C5FEE /* nameConstraintsDN1subCA2Cert.crt in CopyFiles */, + E7A94C5713D89F27001C5FEE /* nameConstraintsDN1subCA3Cert.crt in CopyFiles */, + E7A94C5813D89F27001C5FEE /* nameConstraintsDN2CACert.crt in CopyFiles */, + E7A94C5913D89F27001C5FEE /* nameConstraintsDN3CACert.crt in CopyFiles */, + E7A94C5A13D89F27001C5FEE /* nameConstraintsDN3subCA1Cert.crt in CopyFiles */, + E7A94C5B13D89F27001C5FEE /* nameConstraintsDN3subCA2Cert.crt in CopyFiles */, + E7A94C5C13D89F27001C5FEE /* nameConstraintsDN4CACert.crt in CopyFiles */, + E7A94C5D13D89F27001C5FEE /* nameConstraintsDN5CACert.crt in CopyFiles */, + E7A94C5E13D89F27001C5FEE /* nameConstraintsDNS1CACert.crt in CopyFiles */, + E7A94C5F13D89F27001C5FEE /* nameConstraintsDNS2CACert.crt in CopyFiles */, + E7A94C6013D89F27001C5FEE /* nameConstraintsRFC822CA1Cert.crt in CopyFiles */, + E7A94C6113D89F27001C5FEE /* nameConstraintsRFC822CA2Cert.crt in CopyFiles */, + E7A94C6213D89F27001C5FEE /* nameConstraintsRFC822CA3Cert.crt in CopyFiles */, + E7A94C6313D89F27001C5FEE /* nameConstraintsURI1CACert.crt in CopyFiles */, + E7A94C6413D89F27001C5FEE /* nameConstraintsURI2CACert.crt in CopyFiles */, + E7A94C6513D89F27001C5FEE /* onlyContainsAttributeCertsCACert.crt in CopyFiles */, + E7A94C6613D89F27001C5FEE /* onlyContainsCACertsCACert.crt in CopyFiles */, + E7A94C6713D89F27001C5FEE /* onlyContainsUserCertsCACert.crt in CopyFiles */, + E7A94C6813D89F27001C5FEE /* onlySomeReasonsCA1Cert.crt in CopyFiles */, + E7A94C6913D89F27001C5FEE /* onlySomeReasonsCA2Cert.crt in CopyFiles */, + E7A94C6A13D89F27001C5FEE /* onlySomeReasonsCA3Cert.crt in CopyFiles */, + E7A94C6B13D89F27001C5FEE /* onlySomeReasonsCA4Cert.crt in CopyFiles */, + E7A94C6C13D89F27001C5FEE /* pathLenConstraint0CACert.crt in CopyFiles */, + E7A94C6D13D89F27001C5FEE /* pathLenConstraint0SelfIssuedCACert.crt in CopyFiles */, + E7A94C6E13D89F27001C5FEE /* pathLenConstraint0subCA2Cert.crt in CopyFiles */, + E7A94C6F13D89F27001C5FEE /* pathLenConstraint0subCACert.crt in CopyFiles */, + E7A94C7013D89F27001C5FEE /* pathLenConstraint1CACert.crt in CopyFiles */, + E7A94C7113D89F27001C5FEE /* pathLenConstraint1SelfIssuedCACert.crt in CopyFiles */, + E7A94C7213D89F27001C5FEE /* pathLenConstraint1SelfIssuedsubCACert.crt in CopyFiles */, + E7A94C7313D89F27001C5FEE /* pathLenConstraint1subCACert.crt in CopyFiles */, + E7A94C7413D89F27001C5FEE /* pathLenConstraint6CACert.crt in CopyFiles */, + E7A94C7513D89F27001C5FEE /* pathLenConstraint6subCA0Cert.crt in CopyFiles */, + E7A94C7613D89F27001C5FEE /* pathLenConstraint6subCA1Cert.crt in CopyFiles */, + E7A94C7713D89F27001C5FEE /* pathLenConstraint6subCA4Cert.crt in CopyFiles */, + E7A94C7813D89F27001C5FEE /* pathLenConstraint6subsubCA00Cert.crt in CopyFiles */, + E7A94C7913D89F27001C5FEE /* pathLenConstraint6subsubCA11Cert.crt in CopyFiles */, + E7A94C7A13D89F27001C5FEE /* pathLenConstraint6subsubCA41Cert.crt in CopyFiles */, + E7A94C7B13D89F27001C5FEE /* pathLenConstraint6subsubsubCA11XCert.crt in CopyFiles */, + E7A94C7C13D89F27001C5FEE /* pathLenConstraint6subsubsubCA41XCert.crt in CopyFiles */, + E7A94C7D13D89F27001C5FEE /* pre2000CRLnextUpdateCACert.crt in CopyFiles */, + E7A94C7E13D89F27001C5FEE /* requireExplicitPolicy0CACert.crt in CopyFiles */, + E7A94C7F13D89F27001C5FEE /* requireExplicitPolicy0subCACert.crt in CopyFiles */, + E7A94C8013D89F27001C5FEE /* requireExplicitPolicy0subsubCACert.crt in CopyFiles */, + E7A94C8113D89F27001C5FEE /* requireExplicitPolicy0subsubsubCACert.crt in CopyFiles */, + E7A94C8213D89F27001C5FEE /* requireExplicitPolicy10CACert.crt in CopyFiles */, + E7A94C8313D89F27001C5FEE /* requireExplicitPolicy10subCACert.crt in CopyFiles */, + E7A94C8413D89F27001C5FEE /* requireExplicitPolicy10subsubCACert.crt in CopyFiles */, + E7A94C8513D89F27001C5FEE /* requireExplicitPolicy10subsubsubCACert.crt in CopyFiles */, + E7A94C8613D89F27001C5FEE /* requireExplicitPolicy2CACert.crt in CopyFiles */, + E7A94C8713D89F27001C5FEE /* requireExplicitPolicy2SelfIssuedCACert.crt in CopyFiles */, + E7A94C8813D89F27001C5FEE /* requireExplicitPolicy2SelfIssuedsubCACert.crt in CopyFiles */, + E7A94C8913D89F27001C5FEE /* requireExplicitPolicy2subCACert.crt in CopyFiles */, + E7A94C8A13D89F27001C5FEE /* requireExplicitPolicy4CACert.crt in CopyFiles */, + E7A94C8B13D89F27001C5FEE /* requireExplicitPolicy4subCACert.crt in CopyFiles */, + E7A94C8C13D89F27001C5FEE /* requireExplicitPolicy4subsubCACert.crt in CopyFiles */, + E7A94C8D13D89F27001C5FEE /* requireExplicitPolicy4subsubsubCACert.crt in CopyFiles */, + E7A94C8E13D89F27001C5FEE /* requireExplicitPolicy5CACert.crt in CopyFiles */, + E7A94C8F13D89F27001C5FEE /* requireExplicitPolicy5subCACert.crt in CopyFiles */, + E7A94C9013D89F27001C5FEE /* requireExplicitPolicy5subsubCACert.crt in CopyFiles */, + E7A94C9113D89F27001C5FEE /* requireExplicitPolicy5subsubsubCACert.crt in CopyFiles */, + E7A94C9213D89F27001C5FEE /* requireExplicitPolicy7CACert.crt in CopyFiles */, + E7A94C9313D89F27001C5FEE /* requireExplicitPolicy7subCARE2Cert.crt in CopyFiles */, + E7A94C9413D89F27001C5FEE /* requireExplicitPolicy7subsubCARE2RE4Cert.crt in CopyFiles */, + E7A94C9513D89F27001C5FEE /* requireExplicitPolicy7subsubsubCARE2RE4Cert.crt in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E7A94C9B13D8A14A001C5FEE /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "nist-certs"; + dstSubfolderSpec = 7; + files = ( + E7A94C9C13D8A1AC001C5FEE /* Expectations.plist in CopyFiles */, + E7A94C9D13D8A1AC001C5FEE /* AllCertificatesNoPoliciesTest2EE.crt in CopyFiles */, + E7A94C9E13D8A1AC001C5FEE /* AllCertificatesSamePoliciesTest10EE.crt in CopyFiles */, + E7A94C9F13D8A1AC001C5FEE /* AllCertificatesSamePoliciesTest13EE.crt in CopyFiles */, + E7A94CA013D8A1AC001C5FEE /* AllCertificatesanyPolicyTest11EE.crt in CopyFiles */, + E7A94CA113D8A1AC001C5FEE /* AnyPolicyTest14EE.crt in CopyFiles */, + E7A94CA213D8A1AC001C5FEE /* BadCRLIssuerNameCACert.crt in CopyFiles */, + E7A94CA313D8A1AC001C5FEE /* BadCRLSignatureCACert.crt in CopyFiles */, + E7A94CA413D8A1AC001C5FEE /* BadSignedCACert.crt in CopyFiles */, + E7A94CA513D8A1AC001C5FEE /* BadnotAfterDateCACert.crt in CopyFiles */, + E7A94CA613D8A1AC001C5FEE /* BadnotBeforeDateCACert.crt in CopyFiles */, + E7A94CA713D8A1AC001C5FEE /* BasicSelfIssuedCRLSigningKeyCACert.crt in CopyFiles */, + E7A94CA813D8A1AC001C5FEE /* BasicSelfIssuedNewKeyCACert.crt in CopyFiles */, + E7A94CA913D8A1AC001C5FEE /* BasicSelfIssuedNewKeyOldWithNewCACert.crt in CopyFiles */, + E7A94CAA13D8A1AC001C5FEE /* BasicSelfIssuedOldKeyCACert.crt in CopyFiles */, + E7A94CAB13D8A1AC001C5FEE /* BasicSelfIssuedOldKeyNewWithOldCACert.crt in CopyFiles */, + E7A94CAC13D8A1AC001C5FEE /* CPSPointerQualifierTest20EE.crt in CopyFiles */, + E7A94CAD13D8A1AC001C5FEE /* DSACACert.crt in CopyFiles */, + E7A94CAE13D8A1AC001C5FEE /* DSAParametersInheritedCACert.crt in CopyFiles */, + E7A94CAF13D8A1AC001C5FEE /* DifferentPoliciesTest12EE.crt in CopyFiles */, + E7A94CB013D8A1AC001C5FEE /* DifferentPoliciesTest3EE.crt in CopyFiles */, + E7A94CB113D8A1AC001C5FEE /* DifferentPoliciesTest4EE.crt in CopyFiles */, + E7A94CB213D8A1AC001C5FEE /* DifferentPoliciesTest5EE.crt in CopyFiles */, + E7A94CB313D8A1AC001C5FEE /* DifferentPoliciesTest7EE.crt in CopyFiles */, + E7A94CB413D8A1AC001C5FEE /* DifferentPoliciesTest8EE.crt in CopyFiles */, + E7A94CB513D8A1AC001C5FEE /* DifferentPoliciesTest9EE.crt in CopyFiles */, + E7A94CB613D8A1AC001C5FEE /* GeneralizedTimeCRLnextUpdateCACert.crt in CopyFiles */, + E7A94CB713D8A1AC001C5FEE /* GoodCACert.crt in CopyFiles */, + E7A94CB813D8A1AC001C5FEE /* GoodsubCACert.crt in CopyFiles */, + E7A94CB913D8A1AC001C5FEE /* GoodsubCAPanyPolicyMapping1to2CACert.crt in CopyFiles */, + E7A94CBA13D8A1AC001C5FEE /* InvalidBasicSelfIssuedNewWithOldTest5EE.crt in CopyFiles */, + E7A94CBB13D8A1AC001C5FEE /* InvalidBasicSelfIssuedOldWithNewTest2EE.crt in CopyFiles */, + E7A94CBC13D8A1AC001C5FEE /* InvalidCASignatureTest2EE.crt in CopyFiles */, + E7A94CBD13D8A1AC001C5FEE /* InvalidCAnotAfterDateTest5EE.crt in CopyFiles */, + E7A94CBE13D8A1AC001C5FEE /* InvalidCAnotBeforeDateTest1EE.crt in CopyFiles */, + E7A94CBF13D8A1AC001C5FEE /* InvalidDNSnameConstraintsTest31EE.crt in CopyFiles */, + E7A94CC013D8A1AC001C5FEE /* InvalidDNSnameConstraintsTest33EE.crt in CopyFiles */, + E7A94CC113D8A1AC001C5FEE /* InvalidDNSnameConstraintsTest38EE.crt in CopyFiles */, + E7A94CC213D8A1AC001C5FEE /* InvalidDNandRFC822nameConstraintsTest28EE.crt in CopyFiles */, + E7A94CC313D8A1AC001C5FEE /* InvalidDNandRFC822nameConstraintsTest29EE.crt in CopyFiles */, + E7A94CC413D8A1AC001C5FEE /* InvalidDNnameConstraintsTest10EE.crt in CopyFiles */, + E7A94CC513D8A1AC001C5FEE /* InvalidDNnameConstraintsTest12EE.crt in CopyFiles */, + E7A94CC613D8A1AC001C5FEE /* InvalidDNnameConstraintsTest13EE.crt in CopyFiles */, + E7A94CC713D8A1AC001C5FEE /* InvalidDNnameConstraintsTest15EE.crt in CopyFiles */, + E7A94CC813D8A1AC001C5FEE /* InvalidDNnameConstraintsTest16EE.crt in CopyFiles */, + E7A94CC913D8A1AC001C5FEE /* InvalidDNnameConstraintsTest17EE.crt in CopyFiles */, + E7A94CCA13D8A1AC001C5FEE /* InvalidDNnameConstraintsTest20EE.crt in CopyFiles */, + E7A94CCB13D8A1AC001C5FEE /* InvalidDNnameConstraintsTest2EE.crt in CopyFiles */, + E7A94CCC13D8A1AC001C5FEE /* InvalidDNnameConstraintsTest3EE.crt in CopyFiles */, + E7A94CCD13D8A1AC001C5FEE /* InvalidDNnameConstraintsTest7EE.crt in CopyFiles */, + E7A94CCE13D8A1AC001C5FEE /* InvalidDNnameConstraintsTest8EE.crt in CopyFiles */, + E7A94CCF13D8A1AC001C5FEE /* InvalidDNnameConstraintsTest9EE.crt in CopyFiles */, + E7A94CD013D8A1AC001C5FEE /* InvalidDSASignatureTest6EE.crt in CopyFiles */, + E7A94CD113D8A1AC001C5FEE /* InvalidEESignatureTest3EE.crt in CopyFiles */, + E7A94CD213D8A1AC001C5FEE /* InvalidEEnotAfterDateTest6EE.crt in CopyFiles */, + E7A94CD313D8A1AC001C5FEE /* InvalidEEnotBeforeDateTest2EE.crt in CopyFiles */, + E7A94CD413D8A1AC001C5FEE /* InvalidLongSerialNumberTest18EE.crt in CopyFiles */, + E7A94CD513D8A1AC001C5FEE /* InvalidMappingFromanyPolicyTest7EE.crt in CopyFiles */, + E7A94CD613D8A1AC001C5FEE /* InvalidMappingToanyPolicyTest8EE.crt in CopyFiles */, + E7A94CD713D8A1AC001C5FEE /* InvalidMissingbasicConstraintsTest1EE.crt in CopyFiles */, + E7A94CD813D8A1AC001C5FEE /* InvalidNameChainingOrderTest2EE.crt in CopyFiles */, + E7A94CD913D8A1AC001C5FEE /* InvalidNameChainingTest1EE.crt in CopyFiles */, + E7A94CDA13D8A1AC001C5FEE /* InvalidNegativeSerialNumberTest15EE.crt in CopyFiles */, + E7A94CDB13D8A1AC001C5FEE /* InvalidPolicyMappingTest10EE.crt in CopyFiles */, + E7A94CDC13D8A1AC001C5FEE /* InvalidPolicyMappingTest2EE.crt in CopyFiles */, + E7A94CDD13D8A1AC001C5FEE /* InvalidPolicyMappingTest4EE.crt in CopyFiles */, + E7A94CDE13D8A1AC001C5FEE /* InvalidRFC822nameConstraintsTest22EE.crt in CopyFiles */, + E7A94CDF13D8A1AC001C5FEE /* InvalidRFC822nameConstraintsTest24EE.crt in CopyFiles */, + E7A94CE013D8A1AC001C5FEE /* InvalidRFC822nameConstraintsTest26EE.crt in CopyFiles */, + E7A94CE113D8A1AC001C5FEE /* InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt in CopyFiles */, + E7A94CE213D8A1AC001C5FEE /* InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt in CopyFiles */, + E7A94CE313D8A1AC001C5FEE /* InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt in CopyFiles */, + E7A94CE413D8A1AC001C5FEE /* InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt in CopyFiles */, + E7A94CE513D8A1AC001C5FEE /* InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt in CopyFiles */, + E7A94CE613D8A1AC001C5FEE /* InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt in CopyFiles */, + E7A94CE713D8A1AC001C5FEE /* InvalidSelfIssuedpathLenConstraintTest16EE.crt in CopyFiles */, + E7A94CE813D8A1AC001C5FEE /* InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt in CopyFiles */, + E7A94CE913D8A1AC001C5FEE /* InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt in CopyFiles */, + E7A94CEA13D8A1AC001C5FEE /* InvalidURInameConstraintsTest35EE.crt in CopyFiles */, + E7A94CEB13D8A1AC001C5FEE /* InvalidURInameConstraintsTest37EE.crt in CopyFiles */, + E7A94CEC13D8A1AC001C5FEE /* InvalidUnknownCriticalCertificateExtensionTest2EE.crt in CopyFiles */, + E7A94CED13D8A1AC001C5FEE /* InvalidcAFalseTest2EE.crt in CopyFiles */, + E7A94CEE13D8A1AC001C5FEE /* InvalidcAFalseTest3EE.crt in CopyFiles */, + E7A94CEF13D8A1AC001C5FEE /* InvalidcRLIssuerTest27EE.crt in CopyFiles */, + E7A94CF013D8A1AC001C5FEE /* InvalidcRLIssuerTest31EE.crt in CopyFiles */, + E7A94CF113D8A1AC001C5FEE /* InvalidcRLIssuerTest32EE.crt in CopyFiles */, + E7A94CF213D8A1AC001C5FEE /* InvalidcRLIssuerTest34EE.crt in CopyFiles */, + E7A94CF313D8A1AC001C5FEE /* InvalidcRLIssuerTest35EE.crt in CopyFiles */, + E7A94CF413D8A1AC001C5FEE /* InvalidinhibitAnyPolicyTest1EE.crt in CopyFiles */, + E7A94CF513D8A1AC001C5FEE /* InvalidinhibitAnyPolicyTest4EE.crt in CopyFiles */, + E7A94CF613D8A1AC001C5FEE /* InvalidinhibitAnyPolicyTest5EE.crt in CopyFiles */, + E7A94CF713D8A1AC001C5FEE /* InvalidinhibitAnyPolicyTest6EE.crt in CopyFiles */, + E7A94CF813D8A1AC001C5FEE /* InvalidinhibitPolicyMappingTest1EE.crt in CopyFiles */, + E7A94CF913D8A1AC001C5FEE /* InvalidinhibitPolicyMappingTest3EE.crt in CopyFiles */, + E7A94CFA13D8A1AC001C5FEE /* InvalidinhibitPolicyMappingTest5EE.crt in CopyFiles */, + E7A94CFB13D8A1AC001C5FEE /* InvalidinhibitPolicyMappingTest6EE.crt in CopyFiles */, + E7A94CFC13D8A1AC001C5FEE /* InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt in CopyFiles */, + E7A94CFD13D8A1AC001C5FEE /* InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt in CopyFiles */, + E7A94CFE13D8A1AC001C5FEE /* InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt in CopyFiles */, + E7A94CFF13D8A1AC001C5FEE /* InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt in CopyFiles */, + E7A94D0013D8A1AC001C5FEE /* InvalidonlyContainsAttributeCertsTest14EE.crt in CopyFiles */, + E7A94D0113D8A1AC001C5FEE /* InvalidonlyContainsCACertsTest12EE.crt in CopyFiles */, + E7A94D0213D8A1AC001C5FEE /* InvalidonlyContainsUserCertsTest11EE.crt in CopyFiles */, + E7A94D0313D8A1AC001C5FEE /* InvalidonlySomeReasonsTest15EE.crt in CopyFiles */, + E7A94D0413D8A1AC001C5FEE /* InvalidonlySomeReasonsTest16EE.crt in CopyFiles */, + E7A94D0513D8A1AC001C5FEE /* InvalidonlySomeReasonsTest17EE.crt in CopyFiles */, + E7A94D0613D8A1AC001C5FEE /* InvalidonlySomeReasonsTest20EE.crt in CopyFiles */, + E7A94D0713D8A1AC001C5FEE /* InvalidonlySomeReasonsTest21EE.crt in CopyFiles */, + E7A94D0813D8A1AC001C5FEE /* InvalidpathLenConstraintTest10EE.crt in CopyFiles */, + E7A94D0913D8A1AC001C5FEE /* InvalidpathLenConstraintTest11EE.crt in CopyFiles */, + E7A94D0A13D8A1AC001C5FEE /* InvalidpathLenConstraintTest12EE.crt in CopyFiles */, + E7A94D0B13D8A1AC001C5FEE /* InvalidpathLenConstraintTest5EE.crt in CopyFiles */, + E7A94D0C13D8A1AC001C5FEE /* InvalidpathLenConstraintTest6EE.crt in CopyFiles */, + E7A94D0D13D8A1AC001C5FEE /* InvalidpathLenConstraintTest9EE.crt in CopyFiles */, + E7A94D0E13D8A1AC001C5FEE /* Invalidpre2000UTCEEnotAfterDateTest7EE.crt in CopyFiles */, + E7A94D0F13D8A1AC001C5FEE /* InvalidrequireExplicitPolicyTest3EE.crt in CopyFiles */, + E7A94D1013D8A1AC001C5FEE /* InvalidrequireExplicitPolicyTest5EE.crt in CopyFiles */, + E7A94D1113D8A1AC001C5FEE /* LongSerialNumberCACert.crt in CopyFiles */, + E7A94D1213D8A1AC001C5FEE /* Mapping1to2CACert.crt in CopyFiles */, + E7A94D1313D8A1AC001C5FEE /* MappingFromanyPolicyCACert.crt in CopyFiles */, + E7A94D1413D8A1AC001C5FEE /* MappingToanyPolicyCACert.crt in CopyFiles */, + E7A94D1513D8A1AC001C5FEE /* MissingbasicConstraintsCACert.crt in CopyFiles */, + E7A94D1613D8A1AC001C5FEE /* NameOrderingCACert.crt in CopyFiles */, + E7A94D1713D8A1AC001C5FEE /* NegativeSerialNumberCACert.crt in CopyFiles */, + E7A94D1813D8A1AC001C5FEE /* NoCRLCACert.crt in CopyFiles */, + E7A94D1913D8A1AC001C5FEE /* NoPoliciesCACert.crt in CopyFiles */, + E7A94D1A13D8A1AC001C5FEE /* NoissuingDistributionPointCACert.crt in CopyFiles */, + E7A94D1B13D8A1AC001C5FEE /* OldCRLnextUpdateCACert.crt in CopyFiles */, + E7A94D1C13D8A1AC001C5FEE /* OverlappingPoliciesTest6EE.crt in CopyFiles */, + E7A94D1D13D8A1AC001C5FEE /* P12Mapping1to3CACert.crt in CopyFiles */, + E7A94D1E13D8A1AC001C5FEE /* P12Mapping1to3subCACert.crt in CopyFiles */, + E7A94D1F13D8A1AC001C5FEE /* P12Mapping1to3subsubCACert.crt in CopyFiles */, + E7A94D2013D8A1AC001C5FEE /* P1Mapping1to234CACert.crt in CopyFiles */, + E7A94D2113D8A1AC001C5FEE /* P1Mapping1to234subCACert.crt in CopyFiles */, + E7A94D2213D8A1AC001C5FEE /* P1anyPolicyMapping1to2CACert.crt in CopyFiles */, + E7A94D2313D8A1AC001C5FEE /* PanyPolicyMapping1to2CACert.crt in CopyFiles */, + E7A94D2413D8A1AC001C5FEE /* PoliciesP1234CACert.crt in CopyFiles */, + E7A94D2513D8A1AC001C5FEE /* PoliciesP1234subCAP123Cert.crt in CopyFiles */, + E7A94D2613D8A1AC001C5FEE /* PoliciesP1234subsubCAP123P12Cert.crt in CopyFiles */, + E7A94D2713D8A1AC001C5FEE /* PoliciesP123CACert.crt in CopyFiles */, + E7A94D2813D8A1AC001C5FEE /* PoliciesP123subCAP12Cert.crt in CopyFiles */, + E7A94D2913D8A1AC001C5FEE /* PoliciesP123subsubCAP12P1Cert.crt in CopyFiles */, + E7A94D2A13D8A1AC001C5FEE /* PoliciesP123subsubCAP12P2Cert.crt in CopyFiles */, + E7A94D2B13D8A1AC001C5FEE /* PoliciesP123subsubsubCAP12P2P1Cert.crt in CopyFiles */, + E7A94D2C13D8A1AC001C5FEE /* PoliciesP12CACert.crt in CopyFiles */, + E7A94D2D13D8A1AC001C5FEE /* PoliciesP12subCAP1Cert.crt in CopyFiles */, + E7A94D2E13D8A1AC001C5FEE /* PoliciesP12subsubCAP1P2Cert.crt in CopyFiles */, + E7A94D2F13D8A1AC001C5FEE /* PoliciesP2subCA2Cert.crt in CopyFiles */, + E7A94D3013D8A1AD001C5FEE /* PoliciesP2subCACert.crt in CopyFiles */, + E7A94D3113D8A1AD001C5FEE /* PoliciesP3CACert.crt in CopyFiles */, + E7A94D3213D8A1AD001C5FEE /* RFC3280MandatoryAttributeTypesCACert.crt in CopyFiles */, + E7A94D3313D8A1AD001C5FEE /* RFC3280OptionalAttributeTypesCACert.crt in CopyFiles */, + E7A94D3413D8A1AD001C5FEE /* RevokedsubCACert.crt in CopyFiles */, + E7A94D3513D8A1AD001C5FEE /* RolloverfromPrintableStringtoUTF8StringCACert.crt in CopyFiles */, + E7A94D3613D8A1AD001C5FEE /* SeparateCertificateandCRLKeysCA2CRLSigningCert.crt in CopyFiles */, + E7A94D3713D8A1AD001C5FEE /* SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt in CopyFiles */, + E7A94D3813D8A1AD001C5FEE /* SeparateCertificateandCRLKeysCertificateSigningCACert.crt in CopyFiles */, + E7A94D3913D8A1AD001C5FEE /* TrustAnchorRootCertificate.crt in CopyFiles */, + E7A94D3A13D8A1AD001C5FEE /* TwoCRLsCACert.crt in CopyFiles */, + E7A94D3B13D8A1AD001C5FEE /* UIDCACert.crt in CopyFiles */, + E7A94D3C13D8A1AD001C5FEE /* UTF8StringCaseInsensitiveMatchCACert.crt in CopyFiles */, + E7A94D3D13D8A1AD001C5FEE /* UTF8StringEncodedNamesCACert.crt in CopyFiles */, + E7A94D3E13D8A1AD001C5FEE /* UnknownCRLEntryExtensionCACert.crt in CopyFiles */, + E7A94D3F13D8A1AD001C5FEE /* UnknownCRLExtensionCACert.crt in CopyFiles */, + E7A94D4013D8A1AD001C5FEE /* UserNoticeQualifierTest15EE.crt in CopyFiles */, + E7A94D4113D8A1AD001C5FEE /* UserNoticeQualifierTest16EE.crt in CopyFiles */, + E7A94D4213D8A1AD001C5FEE /* UserNoticeQualifierTest17EE.crt in CopyFiles */, + E7A94D4313D8A1AD001C5FEE /* UserNoticeQualifierTest18EE.crt in CopyFiles */, + E7A94D4413D8A1AD001C5FEE /* UserNoticeQualifierTest19EE.crt in CopyFiles */, + E7A94D4513D8A1AD001C5FEE /* ValidBasicSelfIssuedNewWithOldTest3EE.crt in CopyFiles */, + E7A94D4613D8A1AD001C5FEE /* ValidBasicSelfIssuedNewWithOldTest4EE.crt in CopyFiles */, + E7A94D4713D8A1AD001C5FEE /* ValidBasicSelfIssuedOldWithNewTest1EE.crt in CopyFiles */, + E7A94D4813D8A1AD001C5FEE /* ValidCertificatePathTest1EE.crt in CopyFiles */, + E7A94D4913D8A1AD001C5FEE /* ValidDNSnameConstraintsTest30EE.crt in CopyFiles */, + E7A94D4A13D8A1AD001C5FEE /* ValidDNSnameConstraintsTest32EE.crt in CopyFiles */, + E7A94D4B13D8A1AD001C5FEE /* ValidDNandRFC822nameConstraintsTest27EE.crt in CopyFiles */, + E7A94D4C13D8A1AD001C5FEE /* ValidDNnameConstraintsTest11EE.crt in CopyFiles */, + E7A94D4D13D8A1AD001C5FEE /* ValidDNnameConstraintsTest14EE.crt in CopyFiles */, + E7A94D4E13D8A1AD001C5FEE /* ValidDNnameConstraintsTest18EE.crt in CopyFiles */, + E7A94D4F13D8A1AD001C5FEE /* ValidDNnameConstraintsTest19EE.crt in CopyFiles */, + E7A94D5013D8A1AD001C5FEE /* ValidDNnameConstraintsTest1EE.crt in CopyFiles */, + E7A94D5113D8A1AD001C5FEE /* ValidDNnameConstraintsTest4EE.crt in CopyFiles */, + E7A94D5213D8A1AD001C5FEE /* ValidDNnameConstraintsTest5EE.crt in CopyFiles */, + E7A94D5313D8A1AD001C5FEE /* ValidDNnameConstraintsTest6EE.crt in CopyFiles */, + E7A94D5413D8A1AD001C5FEE /* ValidDSAParameterInheritanceTest5EE.crt in CopyFiles */, + E7A94D5513D8A1AD001C5FEE /* ValidDSASignaturesTest4EE.crt in CopyFiles */, + E7A94D5613D8A1AD001C5FEE /* ValidGeneralizedTimenotAfterDateTest8EE.crt in CopyFiles */, + E7A94D5713D8A1AD001C5FEE /* ValidGeneralizedTimenotBeforeDateTest4EE.crt in CopyFiles */, + E7A94D5813D8A1AD001C5FEE /* ValidLongSerialNumberTest16EE.crt in CopyFiles */, + E7A94D5913D8A1AD001C5FEE /* ValidLongSerialNumberTest17EE.crt in CopyFiles */, + E7A94D5A13D8A1AD001C5FEE /* ValidNameChainingCapitalizationTest5EE.crt in CopyFiles */, + E7A94D5B13D8A1AD001C5FEE /* ValidNameChainingWhitespaceTest3EE.crt in CopyFiles */, + E7A94D5C13D8A1AD001C5FEE /* ValidNameChainingWhitespaceTest4EE.crt in CopyFiles */, + E7A94D5D13D8A1AD001C5FEE /* ValidNameUIDsTest6EE.crt in CopyFiles */, + E7A94D5E13D8A1AD001C5FEE /* ValidNegativeSerialNumberTest14EE.crt in CopyFiles */, + E7A94D5F13D8A1AD001C5FEE /* ValidPolicyMappingTest11EE.crt in CopyFiles */, + E7A94D6013D8A1AD001C5FEE /* ValidPolicyMappingTest12EE.crt in CopyFiles */, + E7A94D6113D8A1AD001C5FEE /* ValidPolicyMappingTest13EE.crt in CopyFiles */, + E7A94D6213D8A1AD001C5FEE /* ValidPolicyMappingTest14EE.crt in CopyFiles */, + E7A94D6313D8A1AD001C5FEE /* ValidPolicyMappingTest1EE.crt in CopyFiles */, + E7A94D6413D8A1AD001C5FEE /* ValidPolicyMappingTest3EE.crt in CopyFiles */, + E7A94D6513D8A1AD001C5FEE /* ValidPolicyMappingTest5EE.crt in CopyFiles */, + E7A94D6613D8A1AD001C5FEE /* ValidPolicyMappingTest6EE.crt in CopyFiles */, + E7A94D6713D8A1AD001C5FEE /* ValidPolicyMappingTest9EE.crt in CopyFiles */, + E7A94D6813D8A1AD001C5FEE /* ValidRFC3280MandatoryAttributeTypesTest7EE.crt in CopyFiles */, + E7A94D6913D8A1AD001C5FEE /* ValidRFC3280OptionalAttributeTypesTest8EE.crt in CopyFiles */, + E7A94D6A13D8A1AD001C5FEE /* ValidRFC822nameConstraintsTest21EE.crt in CopyFiles */, + E7A94D6B13D8A1AD001C5FEE /* ValidRFC822nameConstraintsTest23EE.crt in CopyFiles */, + E7A94D6C13D8A1AD001C5FEE /* ValidRFC822nameConstraintsTest25EE.crt in CopyFiles */, + E7A94D6D13D8A1AD001C5FEE /* ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt in CopyFiles */, + E7A94D6E13D8A1AD001C5FEE /* ValidSelfIssuedinhibitAnyPolicyTest7EE.crt in CopyFiles */, + E7A94D6F13D8A1AD001C5FEE /* ValidSelfIssuedinhibitAnyPolicyTest9EE.crt in CopyFiles */, + E7A94D7013D8A1AD001C5FEE /* ValidSelfIssuedinhibitPolicyMappingTest7EE.crt in CopyFiles */, + E7A94D7113D8A1AD001C5FEE /* ValidSelfIssuedpathLenConstraintTest15EE.crt in CopyFiles */, + E7A94D7213D8A1AD001C5FEE /* ValidSelfIssuedpathLenConstraintTest17EE.crt in CopyFiles */, + E7A94D7313D8A1AD001C5FEE /* ValidSelfIssuedrequireExplicitPolicyTest6EE.crt in CopyFiles */, + E7A94D7413D8A1AD001C5FEE /* ValidURInameConstraintsTest34EE.crt in CopyFiles */, + E7A94D7513D8A1AD001C5FEE /* ValidURInameConstraintsTest36EE.crt in CopyFiles */, + E7A94D7613D8A1AD001C5FEE /* ValidUTF8StringCaseInsensitiveMatchTest11EE.crt in CopyFiles */, + E7A94D7713D8A1AD001C5FEE /* ValidUTF8StringEncodedNamesTest9EE.crt in CopyFiles */, + E7A94D7813D8A1AD001C5FEE /* ValidUnknownNotCriticalCertificateExtensionTest1EE.crt in CopyFiles */, + E7A94D7913D8A1AD001C5FEE /* ValidbasicConstraintsNotCriticalTest4EE.crt in CopyFiles */, + E7A94D7A13D8A1AD001C5FEE /* ValidcRLIssuerTest28EE.crt in CopyFiles */, + E7A94D7B13D8A1AD001C5FEE /* ValidcRLIssuerTest29EE.crt in CopyFiles */, + E7A94D7C13D8A1AD001C5FEE /* ValidcRLIssuerTest30EE.crt in CopyFiles */, + E7A94D7D13D8A1AD001C5FEE /* ValidcRLIssuerTest33EE.crt in CopyFiles */, + E7A94D7E13D8A1AD001C5FEE /* ValidinhibitAnyPolicyTest2EE.crt in CopyFiles */, + E7A94D7F13D8A1AD001C5FEE /* ValidinhibitPolicyMappingTest2EE.crt in CopyFiles */, + E7A94D8013D8A1AD001C5FEE /* ValidinhibitPolicyMappingTest4EE.crt in CopyFiles */, + E7A94D8113D8A1AD001C5FEE /* ValidkeyUsageNotCriticalTest3EE.crt in CopyFiles */, + E7A94D8213D8A1AD001C5FEE /* ValidonlyContainsCACertsTest13EE.crt in CopyFiles */, + E7A94D8313D8A1AD001C5FEE /* ValidonlySomeReasonsTest18EE.crt in CopyFiles */, + E7A94D8413D8A1AD001C5FEE /* ValidonlySomeReasonsTest19EE.crt in CopyFiles */, + E7A94D8513D8A1AD001C5FEE /* ValidpathLenConstraintTest13EE.crt in CopyFiles */, + E7A94D8613D8A1AD001C5FEE /* ValidpathLenConstraintTest14EE.crt in CopyFiles */, + E7A94D8713D8A1AD001C5FEE /* ValidpathLenConstraintTest7EE.crt in CopyFiles */, + E7A94D8813D8A1AD001C5FEE /* ValidpathLenConstraintTest8EE.crt in CopyFiles */, + E7A94D8913D8A1AD001C5FEE /* Validpre2000UTCnotBeforeDateTest3EE.crt in CopyFiles */, + E7A94D8A13D8A1AD001C5FEE /* ValidrequireExplicitPolicyTest1EE.crt in CopyFiles */, + E7A94D8B13D8A1AD001C5FEE /* ValidrequireExplicitPolicyTest2EE.crt in CopyFiles */, + E7A94D8C13D8A1AD001C5FEE /* ValidrequireExplicitPolicyTest4EE.crt in CopyFiles */, + E7A94D8D13D8A1AD001C5FEE /* WrongCRLCACert.crt in CopyFiles */, + E7A94D8E13D8A1AD001C5FEE /* anyPolicyCACert.crt in CopyFiles */, + E7A94D8F13D8A1AD001C5FEE /* basicConstraintsCriticalcAFalseCACert.crt in CopyFiles */, + E7A94D9013D8A1AD001C5FEE /* basicConstraintsNotCriticalCACert.crt in CopyFiles */, + E7A94D9113D8A1AD001C5FEE /* basicConstraintsNotCriticalcAFalseCACert.crt in CopyFiles */, + E7A94D9213D8A1AD001C5FEE /* deltaCRLCA1Cert.crt in CopyFiles */, + E7A94D9313D8A1AD001C5FEE /* deltaCRLCA2Cert.crt in CopyFiles */, + E7A94D9413D8A1AD001C5FEE /* deltaCRLCA3Cert.crt in CopyFiles */, + E7A94D9513D8A1AD001C5FEE /* deltaCRLIndicatorNoBaseCACert.crt in CopyFiles */, + E7A94D9613D8A1AD001C5FEE /* distributionPoint1CACert.crt in CopyFiles */, + E7A94D9713D8A1AD001C5FEE /* distributionPoint2CACert.crt in CopyFiles */, + E7A94D9813D8A1AD001C5FEE /* indirectCRLCA1Cert.crt in CopyFiles */, + E7A94D9913D8A1AD001C5FEE /* indirectCRLCA2Cert.crt in CopyFiles */, + E7A94D9A13D8A1AD001C5FEE /* indirectCRLCA3Cert.crt in CopyFiles */, + E7A94D9B13D8A1AD001C5FEE /* indirectCRLCA3cRLIssuerCert.crt in CopyFiles */, + E7A94D9C13D8A1AD001C5FEE /* indirectCRLCA4Cert.crt in CopyFiles */, + E7A94D9D13D8A1AD001C5FEE /* indirectCRLCA4cRLIssuerCert.crt in CopyFiles */, + E7A94D9E13D8A1AD001C5FEE /* indirectCRLCA5Cert.crt in CopyFiles */, + E7A94D9F13D8A1AD001C5FEE /* indirectCRLCA6Cert.crt in CopyFiles */, + E7A94DA013D8A1AD001C5FEE /* inhibitAnyPolicy0CACert.crt in CopyFiles */, + E7A94DA113D8A1AD001C5FEE /* inhibitAnyPolicy1CACert.crt in CopyFiles */, + E7A94DA213D8A1AD001C5FEE /* inhibitAnyPolicy1SelfIssuedCACert.crt in CopyFiles */, + E7A94DA313D8A1AD001C5FEE /* inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt in CopyFiles */, + E7A94DA413D8A1AD001C5FEE /* inhibitAnyPolicy1subCA1Cert.crt in CopyFiles */, + E7A94DA513D8A1AD001C5FEE /* inhibitAnyPolicy1subCA2Cert.crt in CopyFiles */, + E7A94DA613D8A1AD001C5FEE /* inhibitAnyPolicy1subCAIAP5Cert.crt in CopyFiles */, + E7A94DA713D8A1AD001C5FEE /* inhibitAnyPolicy1subsubCA2Cert.crt in CopyFiles */, + E7A94DA813D8A1AD001C5FEE /* inhibitAnyPolicy5CACert.crt in CopyFiles */, + E7A94DA913D8A1AD001C5FEE /* inhibitAnyPolicy5subCACert.crt in CopyFiles */, + E7A94DAA13D8A1AD001C5FEE /* inhibitAnyPolicy5subsubCACert.crt in CopyFiles */, + E7A94DAB13D8A1AD001C5FEE /* inhibitAnyPolicyTest3EE.crt in CopyFiles */, + E7A94DAC13D8A1AD001C5FEE /* inhibitPolicyMapping0CACert.crt in CopyFiles */, + E7A94DAD13D8A1AD001C5FEE /* inhibitPolicyMapping0subCACert.crt in CopyFiles */, + E7A94DAE13D8A1AD001C5FEE /* inhibitPolicyMapping1P12CACert.crt in CopyFiles */, + E7A94DAF13D8A1AD001C5FEE /* inhibitPolicyMapping1P12subCACert.crt in CopyFiles */, + E7A94DB013D8A1AD001C5FEE /* inhibitPolicyMapping1P12subCAIPM5Cert.crt in CopyFiles */, + E7A94DB113D8A1AD001C5FEE /* inhibitPolicyMapping1P12subsubCACert.crt in CopyFiles */, + E7A94DB213D8A1AD001C5FEE /* inhibitPolicyMapping1P12subsubCAIPM5Cert.crt in CopyFiles */, + E7A94DB313D8A1AD001C5FEE /* inhibitPolicyMapping1P1CACert.crt in CopyFiles */, + E7A94DB413D8A1AD001C5FEE /* inhibitPolicyMapping1P1SelfIssuedCACert.crt in CopyFiles */, + E7A94DB513D8A1AD001C5FEE /* inhibitPolicyMapping1P1SelfIssuedsubCACert.crt in CopyFiles */, + E7A94DB613D8A1AD001C5FEE /* inhibitPolicyMapping1P1subCACert.crt in CopyFiles */, + E7A94DB713D8A1AD001C5FEE /* inhibitPolicyMapping1P1subsubCACert.crt in CopyFiles */, + E7A94DB813D8A1AD001C5FEE /* inhibitPolicyMapping5CACert.crt in CopyFiles */, + E7A94DB913D8A1AD001C5FEE /* inhibitPolicyMapping5subCACert.crt in CopyFiles */, + E7A94DBA13D8A1AD001C5FEE /* inhibitPolicyMapping5subsubCACert.crt in CopyFiles */, + E7A94DBB13D8A1AD001C5FEE /* inhibitPolicyMapping5subsubsubCACert.crt in CopyFiles */, + E7A94DBC13D8A1AD001C5FEE /* keyUsageCriticalcRLSignFalseCACert.crt in CopyFiles */, + E7A94DBD13D8A1AD001C5FEE /* keyUsageCriticalkeyCertSignFalseCACert.crt in CopyFiles */, + E7A94DBE13D8A1AD001C5FEE /* keyUsageNotCriticalCACert.crt in CopyFiles */, + E7A94DBF13D8A1AD001C5FEE /* keyUsageNotCriticalcRLSignFalseCACert.crt in CopyFiles */, + E7A94DC013D8A1AD001C5FEE /* keyUsageNotCriticalkeyCertSignFalseCACert.crt in CopyFiles */, + E7A94DC113D8A1AD001C5FEE /* nameConstraintsDN1CACert.crt in CopyFiles */, + E7A94DC213D8A1AD001C5FEE /* nameConstraintsDN1SelfIssuedCACert.crt in CopyFiles */, + E7A94DC313D8A1AD001C5FEE /* nameConstraintsDN1subCA1Cert.crt in CopyFiles */, + E7A94DC413D8A1AD001C5FEE /* nameConstraintsDN1subCA2Cert.crt in CopyFiles */, + E7A94DC513D8A1AD001C5FEE /* nameConstraintsDN1subCA3Cert.crt in CopyFiles */, + E7A94DC613D8A1AD001C5FEE /* nameConstraintsDN2CACert.crt in CopyFiles */, + E7A94DC713D8A1AD001C5FEE /* nameConstraintsDN3CACert.crt in CopyFiles */, + E7A94DC813D8A1AD001C5FEE /* nameConstraintsDN3subCA1Cert.crt in CopyFiles */, + E7A94DC913D8A1AD001C5FEE /* nameConstraintsDN3subCA2Cert.crt in CopyFiles */, + E7A94DCA13D8A1AD001C5FEE /* nameConstraintsDN4CACert.crt in CopyFiles */, + E7A94DCB13D8A1AD001C5FEE /* nameConstraintsDN5CACert.crt in CopyFiles */, + E7A94DCC13D8A1AD001C5FEE /* nameConstraintsDNS1CACert.crt in CopyFiles */, + E7A94DCD13D8A1AD001C5FEE /* nameConstraintsDNS2CACert.crt in CopyFiles */, + E7A94DCE13D8A1AD001C5FEE /* nameConstraintsRFC822CA1Cert.crt in CopyFiles */, + E7A94DCF13D8A1AD001C5FEE /* nameConstraintsRFC822CA2Cert.crt in CopyFiles */, + E7A94DD013D8A1AD001C5FEE /* nameConstraintsRFC822CA3Cert.crt in CopyFiles */, + E7A94DD113D8A1AD001C5FEE /* nameConstraintsURI1CACert.crt in CopyFiles */, + E7A94DD213D8A1AD001C5FEE /* nameConstraintsURI2CACert.crt in CopyFiles */, + E7A94DD313D8A1AD001C5FEE /* onlyContainsAttributeCertsCACert.crt in CopyFiles */, + E7A94DD413D8A1AD001C5FEE /* onlyContainsCACertsCACert.crt in CopyFiles */, + E7A94DD513D8A1AD001C5FEE /* onlyContainsUserCertsCACert.crt in CopyFiles */, + E7A94DD613D8A1AD001C5FEE /* onlySomeReasonsCA1Cert.crt in CopyFiles */, + E7A94DD713D8A1AD001C5FEE /* onlySomeReasonsCA2Cert.crt in CopyFiles */, + E7A94DD813D8A1AD001C5FEE /* onlySomeReasonsCA3Cert.crt in CopyFiles */, + E7A94DD913D8A1AD001C5FEE /* onlySomeReasonsCA4Cert.crt in CopyFiles */, + E7A94DDA13D8A1AD001C5FEE /* pathLenConstraint0CACert.crt in CopyFiles */, + E7A94DDB13D8A1AD001C5FEE /* pathLenConstraint0SelfIssuedCACert.crt in CopyFiles */, + E7A94DDC13D8A1AD001C5FEE /* pathLenConstraint0subCA2Cert.crt in CopyFiles */, + E7A94DDD13D8A1AD001C5FEE /* pathLenConstraint0subCACert.crt in CopyFiles */, + E7A94DDE13D8A1AD001C5FEE /* pathLenConstraint1CACert.crt in CopyFiles */, + E7A94DDF13D8A1AE001C5FEE /* pathLenConstraint1SelfIssuedCACert.crt in CopyFiles */, + E7A94DE013D8A1AE001C5FEE /* pathLenConstraint1SelfIssuedsubCACert.crt in CopyFiles */, + E7A94DE113D8A1AE001C5FEE /* pathLenConstraint1subCACert.crt in CopyFiles */, + E7A94DE213D8A1AE001C5FEE /* pathLenConstraint6CACert.crt in CopyFiles */, + E7A94DE313D8A1AE001C5FEE /* pathLenConstraint6subCA0Cert.crt in CopyFiles */, + E7A94DE413D8A1AE001C5FEE /* pathLenConstraint6subCA1Cert.crt in CopyFiles */, + E7A94DE513D8A1AE001C5FEE /* pathLenConstraint6subCA4Cert.crt in CopyFiles */, + E7A94DE613D8A1AE001C5FEE /* pathLenConstraint6subsubCA00Cert.crt in CopyFiles */, + E7A94DE713D8A1AE001C5FEE /* pathLenConstraint6subsubCA11Cert.crt in CopyFiles */, + E7A94DE813D8A1AE001C5FEE /* pathLenConstraint6subsubCA41Cert.crt in CopyFiles */, + E7A94DE913D8A1AE001C5FEE /* pathLenConstraint6subsubsubCA11XCert.crt in CopyFiles */, + E7A94DEA13D8A1AE001C5FEE /* pathLenConstraint6subsubsubCA41XCert.crt in CopyFiles */, + E7A94DEB13D8A1AE001C5FEE /* pre2000CRLnextUpdateCACert.crt in CopyFiles */, + E7A94DEC13D8A1AE001C5FEE /* requireExplicitPolicy0CACert.crt in CopyFiles */, + E7A94DED13D8A1AE001C5FEE /* requireExplicitPolicy0subCACert.crt in CopyFiles */, + E7A94DEE13D8A1AE001C5FEE /* requireExplicitPolicy0subsubCACert.crt in CopyFiles */, + E7A94DEF13D8A1AE001C5FEE /* requireExplicitPolicy0subsubsubCACert.crt in CopyFiles */, + E7A94DF013D8A1AE001C5FEE /* requireExplicitPolicy10CACert.crt in CopyFiles */, + E7A94DF113D8A1AE001C5FEE /* requireExplicitPolicy10subCACert.crt in CopyFiles */, + E7A94DF213D8A1AE001C5FEE /* requireExplicitPolicy10subsubCACert.crt in CopyFiles */, + E7A94DF313D8A1AE001C5FEE /* requireExplicitPolicy10subsubsubCACert.crt in CopyFiles */, + E7A94DF413D8A1AE001C5FEE /* requireExplicitPolicy2CACert.crt in CopyFiles */, + E7A94DF513D8A1AE001C5FEE /* requireExplicitPolicy2SelfIssuedCACert.crt in CopyFiles */, + E7A94DF613D8A1AE001C5FEE /* requireExplicitPolicy2SelfIssuedsubCACert.crt in CopyFiles */, + E7A94DF713D8A1AE001C5FEE /* requireExplicitPolicy2subCACert.crt in CopyFiles */, + E7A94DF813D8A1AE001C5FEE /* requireExplicitPolicy4CACert.crt in CopyFiles */, + E7A94DF913D8A1AE001C5FEE /* requireExplicitPolicy4subCACert.crt in CopyFiles */, + E7A94DFA13D8A1AE001C5FEE /* requireExplicitPolicy4subsubCACert.crt in CopyFiles */, + E7A94DFB13D8A1AE001C5FEE /* requireExplicitPolicy4subsubsubCACert.crt in CopyFiles */, + E7A94DFC13D8A1AE001C5FEE /* requireExplicitPolicy5CACert.crt in CopyFiles */, + E7A94DFD13D8A1AE001C5FEE /* requireExplicitPolicy5subCACert.crt in CopyFiles */, + E7A94DFE13D8A1AE001C5FEE /* requireExplicitPolicy5subsubCACert.crt in CopyFiles */, + E7A94DFF13D8A1AE001C5FEE /* requireExplicitPolicy5subsubsubCACert.crt in CopyFiles */, + E7A94E0013D8A1AE001C5FEE /* requireExplicitPolicy7CACert.crt in CopyFiles */, + E7A94E0113D8A1AE001C5FEE /* requireExplicitPolicy7subCARE2Cert.crt in CopyFiles */, + E7A94E0213D8A1AE001C5FEE /* requireExplicitPolicy7subsubCARE2RE4Cert.crt in CopyFiles */, + E7A94E0313D8A1AE001C5FEE /* requireExplicitPolicy7subsubsubCARE2RE4Cert.crt in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 0C4F055D15C9E51A00F9DFD5 /* sslTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sslTypes.h; path = libsecurity_ssl/lib/sslTypes.h; sourceTree = SOURCE_ROOT; }; - 0C6C630B15D193C800BC68CD /* sectests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sectests; sourceTree = BUILT_PRODUCTS_DIR; }; - 0C6C630E15D193C800BC68CD /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; - 0C6C632415D1964200BC68CD /* testlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testlist.h; sourceTree = ""; }; - 0C6C632F15D19DE600BC68CD /* test.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = test.xcconfig; sourceTree = ""; }; - 0C6D0064177B54C60095D167 /* com.apple.securityd */ = {isa = PBXFileReference; lastKnownFileType = text; name = com.apple.securityd; path = asl/com.apple.securityd; sourceTree = SOURCE_ROOT; }; - 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = tlsnke.xcodeproj; path = tlsnke/tlsnke.xcodeproj; sourceTree = ""; }; - 0CC3352D16C1ED8000399E53 /* secdtests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secdtests; sourceTree = BUILT_PRODUCTS_DIR; }; - 0CC3355716C1EEE700399E53 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = main.c; path = secdtests/main.c; sourceTree = ""; }; - 0CC3355816C1EEE700399E53 /* testlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = testlist.h; path = secdtests/testlist.h; sourceTree = ""; }; - 0CC3355B16C1EF5D00399E53 /* regressions.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = regressions.xcodeproj; path = regressions/regressions.xcodeproj; sourceTree = SOURCE_ROOT; }; - 1807384B146D0D4E00F05C24 /* Security.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Security.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 18073856146D0D4E00F05C24 /* Info-Security.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-Security.plist"; sourceTree = ""; }; - 181EA422146D4A2A00A6D320 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; - 181EA423146D4A2A00A6D320 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; - 181EA424146D4A2A00A6D320 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; wrapsLines = 0; }; - 181EA425146D4A2A00A6D320 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; - 18270ED614CF282600B05E7F /* secd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secd; sourceTree = BUILT_PRODUCTS_DIR; }; - 18270EEC14CF333400B05E7F /* client.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = client.c; sourceTree = ""; }; - 18270EED14CF333400B05E7F /* com.apple.securityd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.securityd.plist; sourceTree = ""; }; - 18270EEE14CF333400B05E7F /* securityd_client.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = securityd_client.h; sourceTree = ""; }; - 18270EEF14CF333400B05E7F /* securityd_ipc_types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = securityd_ipc_types.h; sourceTree = ""; }; - 18270EF014CF333400B05E7F /* securityd_rep.defs */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.mig; path = securityd_rep.defs; sourceTree = ""; }; - 18270EF114CF333400B05E7F /* securityd_req.defs */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.mig; path = securityd_req.defs; sourceTree = ""; }; - 18270EF214CF333400B05E7F /* securityd_server.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = securityd_server.h; sourceTree = ""; }; - 18270EF314CF333400B05E7F /* server.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = server.c; sourceTree = ""; }; - 18270EFB14CF427800B05E7F /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = /System/Library/Frameworks/CFNetwork.framework; sourceTree = ""; }; - 18270EFD14CF429600B05E7F /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = ""; }; - 18270EFF14CF42CA00B05E7F /* libcorecrypto.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcorecrypto.a; path = /usr/local/lib/libcorecrypto.a; sourceTree = ""; }; - 18270F0814CF43C000B05E7F /* libDER.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libDER.xcodeproj; path = libsecurity_keychain/libDER/libDER.xcodeproj; sourceTree = ""; }; - 18270F3A14CF44C400B05E7F /* debugging.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = debugging.c; sourceTree = ""; }; - 18270F3B14CF44C400B05E7F /* debugging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debugging.h; sourceTree = ""; }; - 182A190F15D09AF0006AB103 /* connection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = connection.h; sourceTree = ""; }; - 182A191015D09AFF006AB103 /* connection.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = connection.c; sourceTree = ""; }; - 182BB187146EAD4C000BF1F3 /* SecAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecAccess.h; path = libsecurity_keychain/lib/SecAccess.h; sourceTree = SOURCE_ROOT; }; - 182BB188146EAD4C000BF1F3 /* SecACL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecACL.h; path = libsecurity_keychain/lib/SecACL.h; sourceTree = SOURCE_ROOT; }; - 182BB189146EAD4C000BF1F3 /* SecBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecBase.h; path = libsecurity_keychain/lib/SecBase.h; sourceTree = SOURCE_ROOT; }; - 182BB18A146EAD4C000BF1F3 /* SecCertificate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCertificate.h; path = libsecurity_keychain/lib/SecCertificate.h; sourceTree = SOURCE_ROOT; }; - 182BB18B146EAD4C000BF1F3 /* SecIdentity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecIdentity.h; path = libsecurity_keychain/lib/SecIdentity.h; sourceTree = SOURCE_ROOT; }; - 182BB18C146EAD4C000BF1F3 /* SecIdentitySearch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecIdentitySearch.h; path = libsecurity_keychain/lib/SecIdentitySearch.h; sourceTree = SOURCE_ROOT; }; - 182BB18D146EAD4C000BF1F3 /* SecItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecItem.h; path = libsecurity_keychain/lib/SecItem.h; sourceTree = SOURCE_ROOT; }; - 182BB18E146EAD4C000BF1F3 /* SecKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKey.h; path = libsecurity_keychain/lib/SecKey.h; sourceTree = SOURCE_ROOT; }; - 182BB18F146EAD4C000BF1F3 /* SecKeychain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKeychain.h; path = libsecurity_keychain/lib/SecKeychain.h; sourceTree = SOURCE_ROOT; }; - 182BB190146EAD4C000BF1F3 /* SecKeychainItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKeychainItem.h; path = libsecurity_keychain/lib/SecKeychainItem.h; sourceTree = SOURCE_ROOT; }; - 182BB191146EAD4C000BF1F3 /* SecKeychainSearch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKeychainSearch.h; path = libsecurity_keychain/lib/SecKeychainSearch.h; sourceTree = SOURCE_ROOT; }; - 182BB192146EAD4C000BF1F3 /* SecPolicy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecPolicy.h; path = libsecurity_keychain/lib/SecPolicy.h; sourceTree = SOURCE_ROOT; }; - 182BB193146EAD4C000BF1F3 /* SecPolicySearch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecPolicySearch.h; path = libsecurity_keychain/lib/SecPolicySearch.h; sourceTree = SOURCE_ROOT; }; - 182BB194146EAD4C000BF1F3 /* SecTrust.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTrust.h; path = libsecurity_keychain/lib/SecTrust.h; sourceTree = SOURCE_ROOT; }; - 182BB195146EAD4C000BF1F3 /* SecTrustedApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTrustedApplication.h; path = libsecurity_keychain/lib/SecTrustedApplication.h; sourceTree = SOURCE_ROOT; }; - 182BB196146EAD4C000BF1F3 /* Security.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Security.h; path = libsecurity_keychain/lib/Security.h; sourceTree = SOURCE_ROOT; }; - 182BB197146EAD4C000BF1F3 /* SecImportExport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecImportExport.h; path = libsecurity_keychain/lib/SecImportExport.h; sourceTree = SOURCE_ROOT; }; - 182BB198146EAD4C000BF1F3 /* SecTrustSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTrustSettings.h; path = libsecurity_keychain/lib/SecTrustSettings.h; sourceTree = SOURCE_ROOT; }; - 182BB199146EAD4C000BF1F3 /* SecCertificateOIDs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCertificateOIDs.h; path = libsecurity_keychain/lib/SecCertificateOIDs.h; sourceTree = SOURCE_ROOT; }; - 182BB19A146EAD4C000BF1F3 /* SecRandom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecRandom.h; path = libsecurity_keychain/lib/SecRandom.h; sourceTree = SOURCE_ROOT; }; - 182BB1AF146EAD5D000BF1F3 /* SecFDERecoveryAsymmetricCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecFDERecoveryAsymmetricCrypto.h; path = libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.h; sourceTree = SOURCE_ROOT; }; - 182BB1B0146EAD5D000BF1F3 /* SecPassword.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecPassword.h; path = libsecurity_keychain/lib/SecPassword.h; sourceTree = SOURCE_ROOT; }; - 182BB1B2146EAD5D000BF1F3 /* SecAccessPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecAccessPriv.h; path = libsecurity_keychain/lib/SecAccessPriv.h; sourceTree = SOURCE_ROOT; }; - 182BB1B3146EAD5D000BF1F3 /* SecBasePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecBasePriv.h; path = libsecurity_keychain/lib/SecBasePriv.h; sourceTree = SOURCE_ROOT; }; - 182BB1B4146EAD5D000BF1F3 /* SecCertificateBundle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCertificateBundle.h; path = libsecurity_keychain/lib/SecCertificateBundle.h; sourceTree = SOURCE_ROOT; }; - 182BB1B5146EAD5D000BF1F3 /* SecCertificatePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCertificatePriv.h; path = libsecurity_keychain/lib/SecCertificatePriv.h; sourceTree = SOURCE_ROOT; }; - 182BB1B6146EAD5D000BF1F3 /* SecCertificateRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCertificateRequest.h; path = libsecurity_keychain/lib/SecCertificateRequest.h; sourceTree = SOURCE_ROOT; }; - 182BB1B7146EAD5D000BF1F3 /* SecIdentityPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecIdentityPriv.h; path = libsecurity_keychain/lib/SecIdentityPriv.h; sourceTree = SOURCE_ROOT; }; - 182BB1B8146EAD5D000BF1F3 /* SecKeychainItemPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKeychainItemPriv.h; path = libsecurity_keychain/lib/SecKeychainItemPriv.h; sourceTree = SOURCE_ROOT; }; - 182BB1B9146EAD5D000BF1F3 /* SecKeychainPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKeychainPriv.h; path = libsecurity_keychain/lib/SecKeychainPriv.h; sourceTree = SOURCE_ROOT; }; - 182BB1BA146EAD5D000BF1F3 /* SecKeyPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKeyPriv.h; path = libsecurity_keychain/lib/SecKeyPriv.h; sourceTree = SOURCE_ROOT; }; - 182BB1BB146EAD5D000BF1F3 /* SecPolicyPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecPolicyPriv.h; path = libsecurity_keychain/lib/SecPolicyPriv.h; sourceTree = SOURCE_ROOT; }; - 182BB1BC146EAD5D000BF1F3 /* SecTrustedApplicationPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTrustedApplicationPriv.h; path = libsecurity_keychain/lib/SecTrustedApplicationPriv.h; sourceTree = SOURCE_ROOT; }; - 182BB1BD146EAD5D000BF1F3 /* SecTrustPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTrustPriv.h; path = libsecurity_keychain/lib/SecTrustPriv.h; sourceTree = SOURCE_ROOT; }; - 182BB1C4146EAD5D000BF1F3 /* SecIdentitySearchPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecIdentitySearchPriv.h; path = libsecurity_keychain/lib/SecIdentitySearchPriv.h; sourceTree = SOURCE_ROOT; }; - 182BB1C5146EAD5D000BF1F3 /* SecKeychainSearchPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKeychainSearchPriv.h; path = libsecurity_keychain/lib/SecKeychainSearchPriv.h; sourceTree = SOURCE_ROOT; }; - 182BB1C6146EAD5D000BF1F3 /* SecTrustSettingsPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTrustSettingsPriv.h; path = libsecurity_keychain/lib/SecTrustSettingsPriv.h; sourceTree = SOURCE_ROOT; }; - 182BB1C8146EAD5D000BF1F3 /* TrustSettingsSchema.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TrustSettingsSchema.h; path = libsecurity_keychain/lib/TrustSettingsSchema.h; sourceTree = SOURCE_ROOT; }; - 182BB1CA146EAD5D000BF1F3 /* SecItemPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecItemPriv.h; path = libsecurity_keychain/lib/SecItemPriv.h; sourceTree = SOURCE_ROOT; }; - 182BB1CB146EAD5D000BF1F3 /* SecKeychainItemExtendedAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKeychainItemExtendedAttributes.h; path = libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h; sourceTree = SOURCE_ROOT; }; - 182BB1CE146EAD5D000BF1F3 /* SecRecoveryPassword.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecRecoveryPassword.h; path = libsecurity_keychain/lib/SecRecoveryPassword.h; sourceTree = SOURCE_ROOT; }; - 182BB1CF146EAD5D000BF1F3 /* SecRandomP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecRandomP.h; path = libsecurity_keychain/lib/SecRandomP.h; sourceTree = SOURCE_ROOT; }; - 182BB229146F068B000BF1F3 /* iToolsTrustedApps.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = iToolsTrustedApps.plist; path = libsecurity_keychain/plist/iToolsTrustedApps.plist; sourceTree = SOURCE_ROOT; }; - 182BB315146F0E7E000BF1F3 /* SecureDownload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecureDownload.h; path = libsecurity_manifest/lib/SecureDownload.h; sourceTree = SOURCE_ROOT; }; - 182BB317146F0E94000BF1F3 /* SecManifest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecManifest.h; path = libsecurity_manifest/lib/SecManifest.h; sourceTree = SOURCE_ROOT; }; - 182BB318146F0E94000BF1F3 /* SecureDownloadInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecureDownloadInternal.h; path = libsecurity_manifest/lib/SecureDownloadInternal.h; sourceTree = SOURCE_ROOT; }; - 182BB356146F1198000BF1F3 /* mds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mds.h; path = libsecurity_mds/lib/mds.h; sourceTree = SOURCE_ROOT; }; - 182BB357146F1198000BF1F3 /* mds_schema.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mds_schema.h; path = libsecurity_mds/lib/mds_schema.h; sourceTree = SOURCE_ROOT; }; - 182BB35A146F11A1000BF1F3 /* mdspriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mdspriv.h; path = libsecurity_mds/lib/mdspriv.h; sourceTree = SOURCE_ROOT; }; - 182BB36E146F13B4000BF1F3 /* CipherSuite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CipherSuite.h; path = libsecurity_ssl/Security/CipherSuite.h; sourceTree = SOURCE_ROOT; }; - 182BB36F146F13B4000BF1F3 /* SecureTransport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecureTransport.h; path = libsecurity_ssl/Security/SecureTransport.h; sourceTree = SOURCE_ROOT; }; - 182BB372146F13BB000BF1F3 /* SecureTransportPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecureTransportPriv.h; path = libsecurity_ssl/Security/SecureTransportPriv.h; sourceTree = SOURCE_ROOT; }; - 182BB383146F14D2000BF1F3 /* SecCmsBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsBase.h; path = libsecurity_smime/lib/SecCmsBase.h; sourceTree = SOURCE_ROOT; }; - 182BB384146F14D2000BF1F3 /* SecCmsContentInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsContentInfo.h; path = libsecurity_smime/lib/SecCmsContentInfo.h; sourceTree = SOURCE_ROOT; }; - 182BB385146F14D2000BF1F3 /* SecCmsDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsDecoder.h; path = libsecurity_smime/lib/SecCmsDecoder.h; sourceTree = SOURCE_ROOT; }; - 182BB386146F14D2000BF1F3 /* SecCmsDigestContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsDigestContext.h; path = libsecurity_smime/lib/SecCmsDigestContext.h; sourceTree = SOURCE_ROOT; }; - 182BB387146F14D2000BF1F3 /* SecCmsDigestedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsDigestedData.h; path = libsecurity_smime/lib/SecCmsDigestedData.h; sourceTree = SOURCE_ROOT; }; - 182BB388146F14D2000BF1F3 /* SecCmsEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsEncoder.h; path = libsecurity_smime/lib/SecCmsEncoder.h; sourceTree = SOURCE_ROOT; }; - 182BB389146F14D2000BF1F3 /* SecCmsEncryptedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsEncryptedData.h; path = libsecurity_smime/lib/SecCmsEncryptedData.h; sourceTree = SOURCE_ROOT; }; - 182BB38A146F14D2000BF1F3 /* SecCmsEnvelopedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsEnvelopedData.h; path = libsecurity_smime/lib/SecCmsEnvelopedData.h; sourceTree = SOURCE_ROOT; }; - 182BB38B146F14D2000BF1F3 /* SecCmsMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsMessage.h; path = libsecurity_smime/lib/SecCmsMessage.h; sourceTree = SOURCE_ROOT; }; - 182BB38C146F14D2000BF1F3 /* SecCmsRecipientInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsRecipientInfo.h; path = libsecurity_smime/lib/SecCmsRecipientInfo.h; sourceTree = SOURCE_ROOT; }; - 182BB38D146F14D2000BF1F3 /* SecCmsSignedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsSignedData.h; path = libsecurity_smime/lib/SecCmsSignedData.h; sourceTree = SOURCE_ROOT; }; - 182BB38E146F14D2000BF1F3 /* SecCmsSignerInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsSignerInfo.h; path = libsecurity_smime/lib/SecCmsSignerInfo.h; sourceTree = SOURCE_ROOT; }; - 182BB38F146F14D2000BF1F3 /* SecSMIME.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecSMIME.h; path = libsecurity_smime/lib/SecSMIME.h; sourceTree = SOURCE_ROOT; }; - 182BB3A3146F1BEC000BF1F3 /* SecDigestTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecDigestTransform.h; path = libsecurity_transform/lib/SecDigestTransform.h; sourceTree = SOURCE_ROOT; }; - 182BB3A4146F1BEC000BF1F3 /* SecReadTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecReadTransform.h; path = libsecurity_transform/lib/SecReadTransform.h; sourceTree = SOURCE_ROOT; }; - 182BB3A5146F1BEC000BF1F3 /* SecTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTransform.h; path = libsecurity_transform/lib/SecTransform.h; sourceTree = SOURCE_ROOT; }; - 182BB3A6146F1BEC000BF1F3 /* SecCustomTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCustomTransform.h; path = libsecurity_transform/lib/SecCustomTransform.h; sourceTree = SOURCE_ROOT; }; - 182BB3A7146F1BEC000BF1F3 /* SecDecodeTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecDecodeTransform.h; path = libsecurity_transform/lib/SecDecodeTransform.h; sourceTree = SOURCE_ROOT; }; - 182BB3A8146F1BEC000BF1F3 /* SecEncodeTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecEncodeTransform.h; path = libsecurity_transform/lib/SecEncodeTransform.h; sourceTree = SOURCE_ROOT; }; - 182BB3A9146F1BEC000BF1F3 /* SecEncryptTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecEncryptTransform.h; path = libsecurity_transform/lib/SecEncryptTransform.h; sourceTree = SOURCE_ROOT; }; - 182BB3AA146F1BEC000BF1F3 /* SecSignVerifyTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecSignVerifyTransform.h; path = libsecurity_transform/lib/SecSignVerifyTransform.h; sourceTree = SOURCE_ROOT; }; - 182BB3AB146F1BEC000BF1F3 /* SecTransformReadTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTransformReadTransform.h; path = libsecurity_transform/lib/SecTransformReadTransform.h; sourceTree = SOURCE_ROOT; }; - 182BB3B6146F1BF9000BF1F3 /* SecNullTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecNullTransform.h; path = libsecurity_transform/lib/SecNullTransform.h; sourceTree = SOURCE_ROOT; }; - 182BB3B7146F1BF9000BF1F3 /* SecTransformInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTransformInternal.h; path = libsecurity_transform/lib/SecTransformInternal.h; sourceTree = SOURCE_ROOT; }; - 182BB3C4146F1DCB000BF1F3 /* sd_cspdl_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = sd_cspdl_common.mdsinfo; path = libsecurity_sd_cspdl/mds/sd_cspdl_common.mdsinfo; sourceTree = SOURCE_ROOT; }; - 182BB556146F4510000BF1F3 /* csparser-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "csparser-Info.plist"; sourceTree = ""; }; - 182BB557146F4510000BF1F3 /* csparser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = csparser.cpp; sourceTree = ""; }; - 182BB558146F4510000BF1F3 /* csparser.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = csparser.exp; sourceTree = ""; }; - 182BB55C146F4544000BF1F3 /* FDEPrefs.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = FDEPrefs.plist; sourceTree = ""; }; - 182BB55D146F4544000BF1F3 /* generateErrStrings.pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = generateErrStrings.pl; sourceTree = ""; }; - 182BB55E146F4544000BF1F3 /* Security.order */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Security.order; sourceTree = ""; }; - 182BB562146F4C73000BF1F3 /* security.exp-in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "security.exp-in"; sourceTree = ""; }; - 182BB568146F4DCA000BF1F3 /* csparser.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = csparser.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; - 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; - 182BB593146FE1ED000BF1F3 /* libantlr2c++.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libantlr2c++.a"; path = "/usr/local/lib/libantlr2c++.a"; sourceTree = ""; }; - 182BB5AB146FEF14000BF1F3 /* libpam.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpam.dylib; path = /usr/lib/libpam.dylib; sourceTree = ""; }; - 182BB5AD146FEF43000BF1F3 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = /usr/lib/libsqlite3.dylib; sourceTree = ""; }; - 182BB5B1146FF039000BF1F3 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = ""; }; - 182BB5B3146FF04C000BF1F3 /* libxar.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxar.dylib; path = /usr/lib/libxar.dylib; sourceTree = ""; }; - 182BB5B5146FF08F000BF1F3 /* libauto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libauto.dylib; path = /usr/lib/libauto.dylib; sourceTree = ""; }; - 182BB5B7146FF0A1000BF1F3 /* libobjc.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libobjc.dylib; path = /usr/lib/libobjc.dylib; sourceTree = ""; }; - 182BB5B9146FF0BE000BF1F3 /* libbsm.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbsm.dylib; path = /usr/lib/libbsm.dylib; sourceTree = ""; }; - 1831329914EB2C6D00F0BCAC /* libASN1.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libASN1.a; path = /usr/local/lib/libASN1.a; sourceTree = ""; }; - 1831329A14EB2C6D00F0BCAC /* libDER.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libDER.a; path = /usr/local/lib/libDER.a; sourceTree = ""; }; - 1844605B146DE93E00B12992 /* csp_capabilities.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = csp_capabilities.mdsinfo; path = libsecurity_apple_csp/mds/csp_capabilities.mdsinfo; sourceTree = SOURCE_ROOT; }; - 1844605C146DE93E00B12992 /* csp_capabilities_common.mds */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = csp_capabilities_common.mds; path = libsecurity_apple_csp/mds/csp_capabilities_common.mds; sourceTree = SOURCE_ROOT; }; - 1844605D146DE93E00B12992 /* csp_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = csp_common.mdsinfo; path = libsecurity_apple_csp/mds/csp_common.mdsinfo; sourceTree = SOURCE_ROOT; }; - 1844605E146DE93E00B12992 /* csp_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = csp_primary.mdsinfo; path = libsecurity_apple_csp/mds/csp_primary.mdsinfo; sourceTree = SOURCE_ROOT; }; - 18446099146DFCB700B12992 /* secasn1t.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = secasn1t.h; path = libsecurity_asn1/lib/secasn1t.h; sourceTree = SOURCE_ROOT; }; - 1844609A146DFCB700B12992 /* certExtensionTemplates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = certExtensionTemplates.h; path = libsecurity_asn1/lib/certExtensionTemplates.h; sourceTree = SOURCE_ROOT; }; - 1844609B146DFCB700B12992 /* csrTemplates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = csrTemplates.h; path = libsecurity_asn1/lib/csrTemplates.h; sourceTree = SOURCE_ROOT; }; - 1844609C146DFCB700B12992 /* ocspTemplates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ocspTemplates.h; path = libsecurity_asn1/lib/ocspTemplates.h; sourceTree = SOURCE_ROOT; }; - 1844609D146DFCB700B12992 /* nameTemplates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nameTemplates.h; path = libsecurity_asn1/lib/nameTemplates.h; sourceTree = SOURCE_ROOT; }; - 1844609E146DFCB700B12992 /* X509Templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = X509Templates.h; path = libsecurity_asn1/lib/X509Templates.h; sourceTree = SOURCE_ROOT; }; - 1844609F146DFCB700B12992 /* osKeyTemplates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = osKeyTemplates.h; path = libsecurity_asn1/lib/osKeyTemplates.h; sourceTree = SOURCE_ROOT; }; - 184460A0146DFCB700B12992 /* keyTemplates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = keyTemplates.h; path = libsecurity_asn1/lib/keyTemplates.h; sourceTree = SOURCE_ROOT; }; - 184460A1146DFCB700B12992 /* asn1Templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = asn1Templates.h; path = libsecurity_asn1/lib/asn1Templates.h; sourceTree = SOURCE_ROOT; }; - 184460AB146DFCC100B12992 /* SecAsn1Coder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecAsn1Coder.h; path = libsecurity_asn1/lib/SecAsn1Coder.h; sourceTree = SOURCE_ROOT; }; - 184460AC146DFCC100B12992 /* SecAsn1Templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecAsn1Templates.h; path = libsecurity_asn1/lib/SecAsn1Templates.h; sourceTree = SOURCE_ROOT; }; - 184460AD146DFCC100B12992 /* SecAsn1Types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecAsn1Types.h; path = libsecurity_asn1/lib/SecAsn1Types.h; sourceTree = SOURCE_ROOT; }; - 184460C3146E7B1E00B12992 /* cspdl_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = cspdl_common.mdsinfo; path = libsecurity_apple_cspdl/mds/cspdl_common.mdsinfo; sourceTree = SOURCE_ROOT; }; - 184460C4146E7B1E00B12992 /* cspdl_csp_capabilities.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = cspdl_csp_capabilities.mdsinfo; path = libsecurity_apple_cspdl/mds/cspdl_csp_capabilities.mdsinfo; sourceTree = SOURCE_ROOT; }; - 184460C5146E7B1E00B12992 /* cspdl_csp_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = cspdl_csp_primary.mdsinfo; path = libsecurity_apple_cspdl/mds/cspdl_csp_primary.mdsinfo; sourceTree = SOURCE_ROOT; }; - 184460C6146E7B1E00B12992 /* cspdl_dl_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = cspdl_dl_primary.mdsinfo; path = libsecurity_apple_cspdl/mds/cspdl_dl_primary.mdsinfo; sourceTree = SOURCE_ROOT; }; - 184460E1146E806700B12992 /* dl_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = dl_common.mdsinfo; path = libsecurity_apple_file_dl/mds/dl_common.mdsinfo; sourceTree = SOURCE_ROOT; }; - 184460E2146E806700B12992 /* dl_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = dl_primary.mdsinfo; path = libsecurity_apple_file_dl/mds/dl_primary.mdsinfo; sourceTree = SOURCE_ROOT; }; - 18446103146E82C800B12992 /* cl_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = cl_common.mdsinfo; path = libsecurity_apple_x509_cl/mds/cl_common.mdsinfo; sourceTree = SOURCE_ROOT; }; - 18446104146E82C800B12992 /* cl_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = cl_primary.mdsinfo; path = libsecurity_apple_x509_cl/mds/cl_primary.mdsinfo; sourceTree = SOURCE_ROOT; }; - 18446112146E85A300B12992 /* tp_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = tp_common.mdsinfo; path = libsecurity_apple_x509_tp/mds/tp_common.mdsinfo; sourceTree = SOURCE_ROOT; }; - 18446113146E85A300B12992 /* tp_policyOids.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = tp_policyOids.mdsinfo; path = libsecurity_apple_x509_tp/mds/tp_policyOids.mdsinfo; sourceTree = SOURCE_ROOT; }; - 18446114146E85A300B12992 /* tp_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = tp_primary.mdsinfo; path = libsecurity_apple_x509_tp/mds/tp_primary.mdsinfo; sourceTree = SOURCE_ROOT; }; - 18446144146E923200B12992 /* AuthorizationTags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AuthorizationTags.h; path = libsecurity_authorization/lib/AuthorizationTags.h; sourceTree = SOURCE_ROOT; }; - 18446145146E923200B12992 /* AuthSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AuthSession.h; path = libsecurity_authorization/lib/AuthSession.h; sourceTree = SOURCE_ROOT; }; - 18446146146E923200B12992 /* Authorization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Authorization.h; path = libsecurity_authorization/lib/Authorization.h; sourceTree = SOURCE_ROOT; }; - 18446147146E923200B12992 /* AuthorizationDB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AuthorizationDB.h; path = libsecurity_authorization/lib/AuthorizationDB.h; sourceTree = SOURCE_ROOT; }; - 18446148146E923200B12992 /* AuthorizationPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AuthorizationPlugin.h; path = libsecurity_authorization/lib/AuthorizationPlugin.h; sourceTree = SOURCE_ROOT; }; - 1844614E146E923B00B12992 /* AuthorizationTagsPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AuthorizationTagsPriv.h; path = libsecurity_authorization/lib/AuthorizationTagsPriv.h; sourceTree = SOURCE_ROOT; }; - 1844614F146E923B00B12992 /* AuthorizationPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AuthorizationPriv.h; path = libsecurity_authorization/lib/AuthorizationPriv.h; sourceTree = SOURCE_ROOT; }; - 18446168146E95D700B12992 /* checkpw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkpw.h; path = libsecurity_checkpw/lib/checkpw.h; sourceTree = SOURCE_ROOT; }; - 18446170146E982800B12992 /* CMSDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CMSDecoder.h; path = libsecurity_cms/lib/CMSDecoder.h; sourceTree = SOURCE_ROOT; }; - 18446171146E982800B12992 /* CMSEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CMSEncoder.h; path = libsecurity_cms/lib/CMSEncoder.h; sourceTree = SOURCE_ROOT; }; - 18446174146E982D00B12992 /* CMSPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CMSPrivate.h; path = libsecurity_cms/lib/CMSPrivate.h; sourceTree = SOURCE_ROOT; }; - 1844617E146E9A8500B12992 /* SecTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTask.h; path = libsecurity_codesigning/lib/SecTask.h; sourceTree = SOURCE_ROOT; }; - 1844617F146E9A8500B12992 /* CodeSigning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CodeSigning.h; path = libsecurity_codesigning/lib/CodeSigning.h; sourceTree = SOURCE_ROOT; }; - 18446180146E9A8500B12992 /* CSCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSCommon.h; path = libsecurity_codesigning/lib/CSCommon.h; sourceTree = SOURCE_ROOT; }; - 18446181146E9A8500B12992 /* SecCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCode.h; path = libsecurity_codesigning/lib/SecCode.h; sourceTree = SOURCE_ROOT; }; - 18446182146E9A8500B12992 /* SecStaticCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecStaticCode.h; path = libsecurity_codesigning/lib/SecStaticCode.h; sourceTree = SOURCE_ROOT; }; - 18446183146E9A8500B12992 /* SecRequirement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecRequirement.h; path = libsecurity_codesigning/lib/SecRequirement.h; sourceTree = SOURCE_ROOT; }; - 18446184146E9A8500B12992 /* SecCodeHost.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCodeHost.h; path = libsecurity_codesigning/lib/SecCodeHost.h; sourceTree = SOURCE_ROOT; }; - 1844618C146E9A8F00B12992 /* CSCommonPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSCommonPriv.h; path = libsecurity_codesigning/lib/CSCommonPriv.h; sourceTree = SOURCE_ROOT; }; - 1844618D146E9A8F00B12992 /* SecCodePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCodePriv.h; path = libsecurity_codesigning/lib/SecCodePriv.h; sourceTree = SOURCE_ROOT; }; - 1844618E146E9A8F00B12992 /* SecStaticCodePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecStaticCodePriv.h; path = libsecurity_codesigning/lib/SecStaticCodePriv.h; sourceTree = SOURCE_ROOT; }; - 1844618F146E9A8F00B12992 /* SecRequirementPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecRequirementPriv.h; path = libsecurity_codesigning/lib/SecRequirementPriv.h; sourceTree = SOURCE_ROOT; }; - 18446190146E9A8F00B12992 /* SecCodeSigner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCodeSigner.h; path = libsecurity_codesigning/lib/SecCodeSigner.h; sourceTree = SOURCE_ROOT; }; - 18446191146E9A8F00B12992 /* SecIntegrity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecIntegrity.h; path = libsecurity_codesigning/lib/SecIntegrity.h; sourceTree = SOURCE_ROOT; }; - 18446192146E9A8F00B12992 /* SecIntegrityLib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecIntegrityLib.h; path = libsecurity_codesigning/lib/SecIntegrityLib.h; sourceTree = SOURCE_ROOT; }; - 18446193146E9A8F00B12992 /* SecCodeHostLib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCodeHostLib.h; path = libsecurity_codesigning/lib/SecCodeHostLib.h; sourceTree = SOURCE_ROOT; }; - 18446194146E9A8F00B12992 /* SecAssessment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecAssessment.h; path = libsecurity_codesigning/lib/SecAssessment.h; sourceTree = SOURCE_ROOT; }; - 184461A3146E9D3200B12992 /* libsecurityd.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurityd.xcodeproj; path = libsecurityd/libsecurityd.xcodeproj; sourceTree = ""; }; - 18500F9A14708D0E006F9AB4 /* SecDebugErrorMessages.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = SecDebugErrorMessages.strings; path = derived_src/SecDebugErrorMessages.strings; sourceTree = BUILT_PRODUCTS_DIR; }; - 18500FA014708F19006F9AB4 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = derived_src/en.lproj/SecErrorMessages.strings; sourceTree = BUILT_PRODUCTS_DIR; }; - 186CDD1614CA11C700AF9171 /* sec.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = sec.xcodeproj; sourceTree = ""; }; - 18752C1D16F2837A004E2799 /* libaks.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libaks.a; path = usr/local/lib/libaks.a; sourceTree = SDKROOT; }; - 1879B4A9146DCA18007E536C /* cssm.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = cssm.mdsinfo; path = libsecurity_cssm/mds/cssm.mdsinfo; sourceTree = SOURCE_ROOT; }; - 1879B4AB146DCA4A007E536C /* cssmapplePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmapplePriv.h; path = libsecurity_cssm/lib/cssmapplePriv.h; sourceTree = SOURCE_ROOT; }; - 1879B4AD146DCA84007E536C /* certextensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = certextensions.h; path = libsecurity_cssm/lib/certextensions.h; sourceTree = SOURCE_ROOT; }; - 1879B4AE146DCA84007E536C /* cssm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssm.h; path = libsecurity_cssm/lib/cssm.h; sourceTree = SOURCE_ROOT; }; - 1879B4AF146DCA84007E536C /* cssmaci.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmaci.h; path = libsecurity_cssm/lib/cssmaci.h; sourceTree = SOURCE_ROOT; }; - 1879B4B0146DCA84007E536C /* cssmapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmapi.h; path = libsecurity_cssm/lib/cssmapi.h; sourceTree = SOURCE_ROOT; }; - 1879B4B1146DCA84007E536C /* cssmapple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmapple.h; path = libsecurity_cssm/lib/cssmapple.h; sourceTree = SOURCE_ROOT; }; - 1879B4B2146DCA84007E536C /* cssmcli.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmcli.h; path = libsecurity_cssm/lib/cssmcli.h; sourceTree = SOURCE_ROOT; }; - 1879B4B3146DCA84007E536C /* cssmconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmconfig.h; path = libsecurity_cssm/lib/cssmconfig.h; sourceTree = SOURCE_ROOT; }; - 1879B4B4146DCA84007E536C /* cssmcspi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmcspi.h; path = libsecurity_cssm/lib/cssmcspi.h; sourceTree = SOURCE_ROOT; }; - 1879B4B5146DCA84007E536C /* cssmdli.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmdli.h; path = libsecurity_cssm/lib/cssmdli.h; sourceTree = SOURCE_ROOT; }; - 1879B4B6146DCA84007E536C /* cssmerr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmerr.h; path = libsecurity_cssm/lib/cssmerr.h; sourceTree = SOURCE_ROOT; }; - 1879B4B7146DCA84007E536C /* cssmkrapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmkrapi.h; path = libsecurity_cssm/lib/cssmkrapi.h; sourceTree = SOURCE_ROOT; }; - 1879B4B8146DCA84007E536C /* cssmkrspi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmkrspi.h; path = libsecurity_cssm/lib/cssmkrspi.h; sourceTree = SOURCE_ROOT; }; - 1879B4B9146DCA84007E536C /* cssmspi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmspi.h; path = libsecurity_cssm/lib/cssmspi.h; sourceTree = SOURCE_ROOT; }; - 1879B4BA146DCA84007E536C /* cssmtpi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmtpi.h; path = libsecurity_cssm/lib/cssmtpi.h; sourceTree = SOURCE_ROOT; }; - 1879B4BB146DCA84007E536C /* cssmtype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmtype.h; path = libsecurity_cssm/lib/cssmtype.h; sourceTree = SOURCE_ROOT; }; - 1879B4BC146DCA84007E536C /* eisl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eisl.h; path = libsecurity_cssm/lib/eisl.h; sourceTree = SOURCE_ROOT; }; - 1879B4BD146DCA84007E536C /* emmspi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = emmspi.h; path = libsecurity_cssm/lib/emmspi.h; sourceTree = SOURCE_ROOT; }; - 1879B4BE146DCA84007E536C /* emmtype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = emmtype.h; path = libsecurity_cssm/lib/emmtype.h; sourceTree = SOURCE_ROOT; }; - 1879B4C1146DCA84007E536C /* oidsbase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = oidsbase.h; path = libsecurity_cssm/lib/oidsbase.h; sourceTree = SOURCE_ROOT; }; - 1879B4C2146DCA84007E536C /* oidscert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = oidscert.h; path = libsecurity_cssm/lib/oidscert.h; sourceTree = SOURCE_ROOT; }; - 1879B4C3146DCA84007E536C /* oidscrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = oidscrl.h; path = libsecurity_cssm/lib/oidscrl.h; sourceTree = SOURCE_ROOT; }; - 1879B4C4146DCA84007E536C /* x509defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = x509defs.h; path = libsecurity_cssm/lib/x509defs.h; sourceTree = SOURCE_ROOT; }; - 1879B532146DDBE5007E536C /* libsecurity_utilities.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_utilities.xcodeproj; path = libsecurity_utilities/libsecurity_utilities.xcodeproj; sourceTree = ""; }; - 1879B547146DE212007E536C /* libsecurity_cdsa_utils.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cdsa_utils.xcodeproj; path = libsecurity_cdsa_utils/libsecurity_cdsa_utils.xcodeproj; sourceTree = ""; }; - 1879B550146DE227007E536C /* libsecurity_cdsa_utilities.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cdsa_utilities.xcodeproj; path = libsecurity_cdsa_utilities/libsecurity_cdsa_utilities.xcodeproj; sourceTree = ""; }; - 1879B55D146DE244007E536C /* libsecurity_cssm.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cssm.xcodeproj; path = libsecurity_cssm/libsecurity_cssm.xcodeproj; sourceTree = ""; }; - 1879B5BC146DE6C8007E536C /* libsecurity_apple_csp.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_apple_csp.xcodeproj; path = libsecurity_apple_csp/libsecurity_apple_csp.xcodeproj; sourceTree = ""; }; - 1879B5C9146DE6CE007E536C /* libsecurity_apple_cspdl.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_apple_cspdl.xcodeproj; path = libsecurity_apple_cspdl/libsecurity_apple_cspdl.xcodeproj; sourceTree = ""; }; - 1879B5D5146DE6D7007E536C /* libsecurity_apple_file_dl.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_apple_file_dl.xcodeproj; path = libsecurity_apple_file_dl/libsecurity_apple_file_dl.xcodeproj; sourceTree = ""; }; - 1879B5E1146DE6E7007E536C /* libsecurity_apple_x509_cl.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_apple_x509_cl.xcodeproj; path = libsecurity_apple_x509_cl/libsecurity_apple_x509_cl.xcodeproj; sourceTree = ""; }; - 1879B5F0146DE6FD007E536C /* libsecurity_apple_x509_tp.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_apple_x509_tp.xcodeproj; path = libsecurity_apple_x509_tp/libsecurity_apple_x509_tp.xcodeproj; sourceTree = ""; }; - 1879B5FC146DE704007E536C /* libsecurity_asn1.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_asn1.xcodeproj; path = libsecurity_asn1/libsecurity_asn1.xcodeproj; sourceTree = ""; }; - 1879B609146DE70A007E536C /* libsecurity_authorization.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_authorization.xcodeproj; path = libsecurity_authorization/libsecurity_authorization.xcodeproj; sourceTree = ""; }; - 1879B615146DE715007E536C /* libsecurity_cdsa_client.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cdsa_client.xcodeproj; path = libsecurity_cdsa_client/libsecurity_cdsa_client.xcodeproj; sourceTree = ""; }; - 1879B621146DE720007E536C /* libsecurity_cdsa_plugin.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cdsa_plugin.xcodeproj; path = libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj; sourceTree = ""; }; - 1879B637146DE748007E536C /* libsecurity_checkpw.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_checkpw.xcodeproj; path = libsecurity_checkpw/libsecurity_checkpw.xcodeproj; sourceTree = ""; }; - 1879B64B146DE750007E536C /* libsecurity_cms.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cms.xcodeproj; path = libsecurity_cms/libsecurity_cms.xcodeproj; sourceTree = ""; }; - 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_codesigning.xcodeproj; path = libsecurity_codesigning/libsecurity_codesigning.xcodeproj; sourceTree = ""; }; - 1879B66D146DE75D007E536C /* libsecurity_comcryption.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_comcryption.xcodeproj; path = libsecurity_comcryption/libsecurity_comcryption.xcodeproj; sourceTree = ""; }; - 1879B679146DE76E007E536C /* libsecurity_cryptkit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cryptkit.xcodeproj; path = libsecurity_cryptkit/libsecurity_cryptkit.xcodeproj; sourceTree = ""; }; - 1879B694146DE797007E536C /* libsecurity_filedb.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_filedb.xcodeproj; path = libsecurity_filedb/libsecurity_filedb.xcodeproj; sourceTree = ""; }; - 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_keychain.xcodeproj; path = libsecurity_keychain/libsecurity_keychain.xcodeproj; sourceTree = ""; }; - 1879B6C7146DE7D7007E536C /* libsecurity_manifest.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_manifest.xcodeproj; path = libsecurity_manifest/libsecurity_manifest.xcodeproj; sourceTree = ""; }; - 1879B6D3146DE7E0007E536C /* libsecurity_mds.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_mds.xcodeproj; path = libsecurity_mds/libsecurity_mds.xcodeproj; sourceTree = ""; }; - 1879B6DF146DE7E7007E536C /* libsecurity_ocspd.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_ocspd.xcodeproj; path = libsecurity_ocspd/libsecurity_ocspd.xcodeproj; sourceTree = ""; }; - 1879B6EC146DE7EE007E536C /* libsecurity_pkcs12.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_pkcs12.xcodeproj; path = libsecurity_pkcs12/libsecurity_pkcs12.xcodeproj; sourceTree = ""; }; - 1879B6F8146DE7F7007E536C /* libsecurity_sd_cspdl.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_sd_cspdl.xcodeproj; path = libsecurity_sd_cspdl/libsecurity_sd_cspdl.xcodeproj; sourceTree = ""; }; - 1879B712146DE825007E536C /* libsecurity_smime.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_smime.xcodeproj; path = libsecurity_smime/libsecurity_smime.xcodeproj; sourceTree = ""; }; - 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_ssl.xcodeproj; path = libsecurity_ssl/libsecurity_ssl.xcodeproj; sourceTree = ""; }; - 1879B72B146DE844007E536C /* libsecurity_transform.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_transform.xcodeproj; path = libsecurity_transform/libsecurity_transform.xcodeproj; sourceTree = ""; }; - 187D6B9015D4359F00E27494 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/authorization.buttons.strings; sourceTree = ""; }; - 187D6B9215D4359F00E27494 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/authorization.prompts.strings; sourceTree = ""; }; - 187D6B9515D436BF00E27494 /* authorization.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = authorization.plist; sourceTree = ""; }; - 188AD8D91471FE3D0081C619 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/FDELocalizable.strings; sourceTree = ""; }; - 188AD8DB1471FE3E0081C619 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 18A5493115EFD2F40059E6DC /* dummy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dummy.cpp; sourceTree = ""; }; - 18B647E814D9EB6300F538BF /* oidsalg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = oidsalg.h; path = ../libsecurity_asn1/lib/oidsalg.h; sourceTree = ""; }; - 18B647EA14D9EE4300F538BF /* oidsattr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = oidsattr.h; path = ../libsecurity_asn1/lib/oidsattr.h; sourceTree = ""; }; - 18B647EF14D9F75300F538BF /* generateErrStrings.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = generateErrStrings.mm; path = derived_src/generateErrStrings.mm; sourceTree = BUILT_PRODUCTS_DIR; }; - 18BBC6801471EF1600F2B224 /* security.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = security.xcconfig; sourceTree = ""; }; - 18BBC7351471F5A300F2B224 /* SecExternalSourceTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecExternalSourceTransform.h; path = libsecurity_transform/lib/SecExternalSourceTransform.h; sourceTree = SOURCE_ROOT; }; - 18BEB19614CF74C100C8BD36 /* com.apple.secd.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.secd.plist; sourceTree = ""; }; - 18BFC44017C43393005DE6C3 /* executable.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = executable.xcconfig; sourceTree = ""; }; - 18CFEE8715DEE25200E3F2A3 /* com.apple.authd.sb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = com.apple.authd.sb; sourceTree = ""; }; - 18D6803916B768D500DF6D2E /* com.apple.authd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = com.apple.authd; sourceTree = ""; }; - 18ED4D2317270DB6003AF11B /* SecurityTests-Entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SecurityTests-Entitlements.plist"; sourceTree = ""; }; - 18F234EB15C9F9A600060520 /* authd.xpc */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = authd.xpc; sourceTree = BUILT_PRODUCTS_DIR; }; - 18F234F915C9FA3B00060520 /* agent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = agent.c; sourceTree = ""; }; - 18F234FA15C9FA3B00060520 /* agent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = agent.h; sourceTree = ""; }; - 18F234FB15C9FA3B00060520 /* authdb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = authdb.c; sourceTree = ""; }; - 18F234FC15C9FA3B00060520 /* authdb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = authdb.h; sourceTree = ""; }; - 18F234FD15C9FA3B00060520 /* authitems.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = authitems.c; sourceTree = ""; }; - 18F234FE15C9FA3B00060520 /* authitems.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = authitems.h; sourceTree = ""; }; - 18F234FF15C9FA3B00060520 /* authtoken.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = authtoken.c; sourceTree = ""; }; - 18F2350015C9FA3B00060520 /* authtoken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = authtoken.h; sourceTree = ""; }; - 18F2350115C9FA3B00060520 /* authtypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = authtypes.h; sourceTree = ""; }; - 18F2350215C9FA3B00060520 /* authutilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = authutilities.c; sourceTree = ""; }; - 18F2350315C9FA3B00060520 /* authutilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = authutilities.h; sourceTree = ""; }; - 18F2350415C9FA3B00060520 /* ccaudit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ccaudit.c; sourceTree = ""; }; - 18F2350515C9FA3B00060520 /* ccaudit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ccaudit.h; sourceTree = ""; }; - 18F2350615C9FA3B00060520 /* crc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = crc.c; sourceTree = ""; }; - 18F2350715C9FA3B00060520 /* crc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crc.h; sourceTree = ""; }; - 18F2350815C9FA3B00060520 /* credential.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = credential.c; sourceTree = ""; }; - 18F2350915C9FA3B00060520 /* credential.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = credential.h; sourceTree = ""; }; - 18F2350A15C9FA3B00060520 /* debugging.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = debugging.c; sourceTree = ""; }; - 18F2350B15C9FA3B00060520 /* debugging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debugging.h; sourceTree = ""; }; - 18F2350E15C9FA3B00060520 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = InfoPlist.strings; sourceTree = ""; }; - 18F2350F15C9FA3B00060520 /* engine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = engine.c; sourceTree = ""; }; - 18F2351015C9FA3B00060520 /* engine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = engine.h; sourceTree = ""; }; - 18F2351115C9FA3B00060520 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; - 18F2351215C9FA3B00060520 /* mechanism.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mechanism.c; sourceTree = ""; }; - 18F2351315C9FA3B00060520 /* mechanism.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mechanism.h; sourceTree = ""; }; - 18F2351415C9FA3C00060520 /* object.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = object.c; sourceTree = ""; }; - 18F2351515C9FA3C00060520 /* object.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = object.h; sourceTree = ""; }; - 18F2351615C9FA3C00060520 /* process.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = process.c; sourceTree = ""; }; - 18F2351715C9FA3C00060520 /* process.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = process.h; sourceTree = ""; }; - 18F2351815C9FA3C00060520 /* rule.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rule.c; sourceTree = ""; }; - 18F2351915C9FA3C00060520 /* rule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rule.h; sourceTree = ""; }; - 18F2351A15C9FA3C00060520 /* authd_private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = authd_private.h; sourceTree = ""; }; - 18F2351B15C9FA3C00060520 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 18F2351C15C9FA3C00060520 /* security.auth-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "security.auth-Prefix.pch"; sourceTree = ""; }; - 18F2351D15C9FA3C00060520 /* server.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = server.c; sourceTree = ""; }; - 18F2351E15C9FA3C00060520 /* server.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = server.h; sourceTree = ""; }; - 18F2351F15C9FA3C00060520 /* session.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = session.c; sourceTree = ""; }; - 18F2352015C9FA3C00060520 /* session.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = session.h; sourceTree = ""; }; - 18F235F515CA0D8100060520 /* libsecurity_cdsa_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_cdsa_utilities.a; path = /usr/local/lib/libsecurity_cdsa_utilities.a; sourceTree = ""; }; - 18F235F715CA0D9D00060520 /* libsecurity_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_utilities.a; path = /usr/local/lib/libsecurity_utilities.a; sourceTree = ""; }; - 18F235F915CA0DB000060520 /* libsecurity_agent_client.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_agent_client.a; path = /usr/local/lib/libsecurity_agent_client.a; sourceTree = ""; }; - 18F235FC15CA0EDB00060520 /* libstdc++.6.0.9.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libstdc++.6.0.9.dylib"; path = "/usr/lib/libstdc++.6.0.9.dylib"; sourceTree = ""; }; - 18F2360015CAF41100060520 /* libsecurity_codesigning.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_codesigning.a; path = /usr/local/lib/libsecurity_codesigning.a; sourceTree = ""; }; - 18FE67EA1471A3AA00A2CBE3 /* Security.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Security.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 37A7CEAB197DB8FA00926CE8 /* codesign_tests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = codesign_tests; sourceTree = BUILT_PRODUCTS_DIR; }; - 37A7CEAD197DB8FA00926CE8 /* FatDynamicValidation.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = FatDynamicValidation.c; sourceTree = ""; }; - 37A7CEDB197DCDD700926CE8 /* validation.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = validation.sh; sourceTree = ""; }; - 395E7CED16C64EA500CD82A4 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; - 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = utilities.xcodeproj; sourceTree = ""; }; - 4C2505B616D2DF9F002CE025 /* Icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = Icon.icns; sourceTree = ""; }; - 4C328D2F1778EC4F0015EED1 /* AOSUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AOSUI.framework; path = ../../../../../../../System/Library/PrivateFrameworks/AOSUI.framework; sourceTree = ""; }; - 4C49390C16E51ACE00CE110C /* com.apple.security.keychain-circle-notification.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "com.apple.security.keychain-circle-notification.plist"; sourceTree = ""; }; - 4C5DD44217A5E31900696A79 /* KNPersistantState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KNPersistantState.h; sourceTree = ""; }; - 4C5DD44317A5E31900696A79 /* KNPersistantState.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KNPersistantState.m; sourceTree = ""; }; - 4C5DD46B17A5F67300696A79 /* AppleSystemInfo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppleSystemInfo.framework; path = ../../../../../../../System/Library/PrivateFrameworks/AppleSystemInfo.framework; sourceTree = ""; }; - 4C7D453B17BEE69B00DDD88F /* NSString+compactDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+compactDescription.h"; sourceTree = ""; }; - 4C7D453C17BEE69B00DDD88F /* NSString+compactDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+compactDescription.m"; sourceTree = ""; }; - 4C7D456417BEE6B700DDD88F /* NSDictionary+compactDescription.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+compactDescription.h"; sourceTree = ""; }; - 4C7D456517BEE6B700DDD88F /* NSDictionary+compactDescription.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+compactDescription.m"; sourceTree = ""; }; - 4C7D456617BEE6B700DDD88F /* NSSet+compactDescription.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSSet+compactDescription.h"; sourceTree = ""; }; - 4C7D456717BEE6B700DDD88F /* NSSet+compactDescription.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSSet+compactDescription.m"; sourceTree = ""; }; - 4C8313C814F5A26500DF7FDC /* libcorecrypto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcorecrypto.dylib; path = /usr/lib/system/libcorecrypto.dylib; sourceTree = ""; }; - 4C85DED816DBD5BF00ED8D47 /* KDCirclePeer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KDCirclePeer.h; sourceTree = ""; }; - 4C85DED916DBD5BF00ED8D47 /* KDCirclePeer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KDCirclePeer.m; sourceTree = ""; }; - 4C96F73816D5372C00D3B39D /* KDSecCircle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KDSecCircle.h; sourceTree = ""; }; - 4C96F73916D5372C00D3B39D /* KDSecCircle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KDSecCircle.m; sourceTree = ""; }; - 4C96F76116D54C9600D3B39D /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; }; - 4C96F7C116D6DF8300D3B39D /* Keychain Circle Notification.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Keychain Circle Notification.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C96F7C516D6DF8400D3B39D /* Keychain Circle Notification-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Keychain Circle Notification-Info.plist"; sourceTree = ""; }; - 4C96F7C716D6DF8400D3B39D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 4C96F7C916D6DF8400D3B39D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 4C96F7CB16D6DF8400D3B39D /* Keychain Circle Notification-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Keychain Circle Notification-Prefix.pch"; sourceTree = ""; }; - 4C96F7CD16D6DF8400D3B39D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; - 4C96F7CF16D6DF8400D3B39D /* KNAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KNAppDelegate.h; sourceTree = ""; }; - 4C96F7D016D6DF8400D3B39D /* KNAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KNAppDelegate.m; sourceTree = ""; }; - 4C96F7D316D6DF8400D3B39D /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; - 4C97761D17BEB23E0002BFE4 /* AOSAccounts.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AOSAccounts.framework; path = ../../../../../../../System/Library/PrivateFrameworks/AOSAccounts.framework; sourceTree = ""; }; - 4CB23B46169F5873003A0131 /* security2 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = security2; sourceTree = BUILT_PRODUCTS_DIR; }; - 4CB23B4B169F5873003A0131 /* security2.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = security2.1; sourceTree = ""; }; - 4CB23B80169F58DE003A0131 /* security_tool_commands.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = security_tool_commands.c; sourceTree = ""; }; - 4CB23B82169F592C003A0131 /* sub_commands.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sub_commands.h; sourceTree = ""; }; - 4CB23B91169F5CFF003A0131 /* command.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = command.xcconfig; sourceTree = ""; }; - 4CB86AE6167A6FF200F46643 /* SOSCircle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSCircle.h; path = ../sec/SOSCircle/SecureObjectSync/SOSCircle.h; sourceTree = ""; }; - 4CB86AE7167A6FF200F46643 /* SOSCloudCircle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSCloudCircle.h; path = ../sec/SOSCircle/SecureObjectSync/SOSCloudCircle.h; sourceTree = ""; }; - 4CB86AE8167A6FF200F46643 /* SOSCloudCircleInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSCloudCircleInternal.h; path = ../sec/SOSCircle/SecureObjectSync/SOSCloudCircleInternal.h; sourceTree = ""; }; - 4CB86AE9167A6FF200F46643 /* SOSEngine.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSEngine.h; path = ../sec/SOSCircle/SecureObjectSync/SOSEngine.h; sourceTree = ""; }; - 4CB86AEA167A6FF300F46643 /* SOSFullPeerInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSFullPeerInfo.h; path = ../sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.h; sourceTree = ""; }; - 4CB86AEB167A6FF300F46643 /* SOSInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSInternal.h; path = ../sec/SOSCircle/SecureObjectSync/SOSInternal.h; sourceTree = ""; }; - 4CB86AEC167A6FF300F46643 /* SOSPeer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSPeer.h; path = ../sec/SOSCircle/SecureObjectSync/SOSPeer.h; sourceTree = ""; }; - 4CB86AED167A6FF300F46643 /* SOSPeerInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSPeerInfo.h; path = ../sec/SOSCircle/SecureObjectSync/SOSPeerInfo.h; sourceTree = ""; }; - 4CB86AEE167A6FF300F46643 /* SOSTransport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSTransport.h; path = ../sec/SOSCircle/SecureObjectSync/SOSTransport.h; sourceTree = ""; }; - 4CB86AFA167A8F2200F46643 /* SOSAccount.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SOSAccount.h; path = ../sec/SOSCircle/SecureObjectSync/SOSAccount.h; sourceTree = ""; }; - 4CB9121C17750E6500C1CCCA /* entitlments.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = entitlments.plist; sourceTree = ""; }; - 4CC7A7B316CC2A84003E10C1 /* Cloud Keychain Utility.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Cloud Keychain Utility.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - 4CC7A7B716CC2A85003E10C1 /* Keychain-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Keychain-Info.plist"; sourceTree = ""; }; - 4CC7A7B916CC2A85003E10C1 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 4CC7A7BB16CC2A85003E10C1 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 4CC7A7BD16CC2A85003E10C1 /* Keychain-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Keychain-Prefix.pch"; sourceTree = ""; }; - 4CC7A7BF16CC2A85003E10C1 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; - 4CC7A7C116CC2A85003E10C1 /* KDAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KDAppDelegate.h; sourceTree = ""; }; - 4CC7A7C216CC2A85003E10C1 /* KDAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KDAppDelegate.m; sourceTree = ""; }; - 4CC7A7C516CC2A85003E10C1 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; - 4CC7A7F216CC2B0A003E10C1 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; - 4CC7A7F416CD95D2003E10C1 /* KDSecItems.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KDSecItems.h; sourceTree = ""; }; - 4CC7A7F516CD95D3003E10C1 /* KDSecItems.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KDSecItems.m; sourceTree = ""; }; - 4CD1980B16DD3BDF00A9E8FD /* NSArray+mapWithBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+mapWithBlock.h"; path = "Keychain Circle Notification/NSArray+mapWithBlock.h"; sourceTree = SOURCE_ROOT; }; - 4CD1980C16DD3BDF00A9E8FD /* NSArray+mapWithBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+mapWithBlock.m"; path = "Keychain Circle Notification/NSArray+mapWithBlock.m"; sourceTree = SOURCE_ROOT; }; - 4CF42B8F159E674D00ACACE1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 4CF42BB515A3947F00ACACE1 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = ""; }; - 4CFE1CB816DD4B9C0026E900 /* CloudKeychain.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = CloudKeychain.icns; sourceTree = ""; }; - 5214700616977CB800DF0DB3 /* CloudKeychainProxy.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CloudKeychainProxy.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; - 5214700716977CB800DF0DB3 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; - 5214700A16977CB800DF0DB3 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; - 5214700B16977CB800DF0DB3 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; - 5214700C16977CB800DF0DB3 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 5214700F16977CB800DF0DB3 /* CloudKeychainProxy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "CloudKeychainProxy-Info.plist"; sourceTree = ""; }; - 5214701116977CB800DF0DB3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 5214702416977FEC00DF0DB3 /* cloudkeychain.entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = cloudkeychain.entitlements.plist; sourceTree = ""; }; - 5214702516977FEC00DF0DB3 /* com.apple.security.cloudkeychainproxy.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.security.cloudkeychainproxy.plist; sourceTree = ""; }; - 52AEA484153C7581005AFC59 /* tsaSupportPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tsaSupportPriv.h; path = libsecurity_smime/lib/tsaSupportPriv.h; sourceTree = SOURCE_ROOT; }; - 52B006BF15238F76005D4556 /* TimeStampingPrefs.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = TimeStampingPrefs.plist; sourceTree = ""; }; - 52B5A9C01519330300664F11 /* tsaSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = tsaSupport.h; path = libsecurity_smime/lib/tsaSupport.h; sourceTree = SOURCE_ROOT; }; - 52B5A9C11519330300664F11 /* tsaTemplates.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = tsaTemplates.h; path = libsecurity_smime/lib/tsaTemplates.h; sourceTree = SOURCE_ROOT; }; - 52C3D235169B56860091D9D3 /* ckdmain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ckdmain.m; path = sec/SOSCircle/CloudKeychainProxy/ckdmain.m; sourceTree = SOURCE_ROOT; }; - 5328475217850741009118DC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; - 721680A5179B40F600406BB4 /* iCloudStats */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = iCloudStats; sourceTree = BUILT_PRODUCTS_DIR; }; - 721680A8179B40F600406BB4 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; - 721680AA179B40F600406BB4 /* iCloudStats.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = iCloudStats.1; sourceTree = ""; }; - 721680BD179B4F9100406BB4 /* com.apple.iCloudStats.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.iCloudStats.plist; sourceTree = ""; }; - 722CF215175D5E5000BCE0A5 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.Internal.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; - 72756BFE175D485D00F52070 /* cloud_keychain_diagnose */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = cloud_keychain_diagnose; sourceTree = BUILT_PRODUCTS_DIR; }; - 72756C04175D485D00F52070 /* cloud_keychain_diagnose-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "cloud_keychain_diagnose-Prefix.pch"; sourceTree = ""; }; - 72756C30175D48C100F52070 /* cloud_keychain_diagnose.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cloud_keychain_diagnose.c; path = utilities/src/cloud_keychain_diagnose.c; sourceTree = SOURCE_ROOT; }; - 72756C9A175D51B100F52070 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/IOKit.framework; sourceTree = DEVELOPER_DIR; }; - 72756C9C175D51C900F52070 /* Kernel.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Kernel.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/Kernel.framework; sourceTree = DEVELOPER_DIR; }; - 72756C9E175D566800F52070 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.Internal.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; }; - 72A3DE5B179B2C0400E78247 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.Internal.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - BE8C5F0916F7CE450074CF86 /* framework.sb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = framework.sb; sourceTree = ""; }; - BEC3A76716F79497003E5634 /* SecTaskPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTaskPriv.h; path = libsecurity_codesigning/lib/SecTaskPriv.h; sourceTree = SOURCE_ROOT; }; - C288A0881505795D00E773B7 /* libOpenScriptingUtil.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libOpenScriptingUtil.dylib; path = ../../../../../usr/lib/libOpenScriptingUtil.dylib; sourceTree = ""; }; - CDDE9D1C1729DF250013B0E8 /* SecPasswordGenerate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecPasswordGenerate.h; path = ../sec/Security/SecPasswordGenerate.h; sourceTree = ""; }; + 051D8F82194913E500AEF66A /* Security.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Security.xcodeproj; path = Security/Security.xcodeproj; sourceTree = ""; }; + 05EF687F1949143A007958C3 /* securityd.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = securityd.xcodeproj; path = securityd/securityd.xcodeproj; sourceTree = ""; }; + 05EF68A919491453007958C3 /* SecurityTool.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SecurityTool.xcodeproj; path = SecurityTool/SecurityTool.xcodeproj; sourceTree = ""; }; + 0C0BDB2F175685B000BC1A7E /* secdtests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secdtests; sourceTree = BUILT_PRODUCTS_DIR; }; + 0C0BDB31175685B000BC1A7E /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 0C0BDB441756868B00BC1A7E /* testlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testlist.h; sourceTree = ""; }; + 0C1EF18813A1946C000A4CE5 /* PostSecurityTests.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = PostSecurityTests.sh; sourceTree = ""; }; + 0C25A871122726540050C2BD /* regressions.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = regressions.xcodeproj; path = Security/regressions/regressions.xcodeproj; sourceTree = ""; }; + 0C3145551496B8FB00427C0B /* SecureTransport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecureTransport.h; path = Security/libsecurity_ssl/lib/SecureTransport.h; sourceTree = ""; }; + 0C3145561496B8FB00427C0B /* SecureTransportPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecureTransportPriv.h; path = Security/libsecurity_ssl/lib/SecureTransportPriv.h; sourceTree = ""; }; + 0C550308139F0B970019E5EB /* PreSecurityTests.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = PreSecurityTests.sh; sourceTree = ""; }; + 0C59B54517677A9900617746 /* com.apple.securityd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = com.apple.securityd; sourceTree = ""; }; + 0C5D2EEA167FEAAC0077501D /* SecAsn1Coder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = SecAsn1Coder.h; path = Security/libsecurity_asn1/lib/SecAsn1Coder.h; sourceTree = ""; }; + 0C5D2EEC167FEEC90077501D /* secasn1t.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = secasn1t.h; path = Security/libsecurity_asn1/lib/secasn1t.h; sourceTree = ""; }; + 0C5D2EEE167FF0560077501D /* SecAsn1Templates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = SecAsn1Templates.h; path = Security/libsecurity_asn1/lib/SecAsn1Templates.h; sourceTree = ""; }; + 0C5D2EF0167FF1FC0077501D /* oidsalg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = oidsalg.h; path = Security/libsecurity_asn1/lib/oidsalg.h; sourceTree = ""; }; + 0C664AB2175926B20092D3D9 /* secdtests-entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "secdtests-entitlements.plist"; sourceTree = ""; }; + 0C78F1C916A5E13400654E08 /* sectask_regressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sectask_regressions.h; sourceTree = ""; }; + 0C78F1CA16A5E1BF00654E08 /* sectask-10-sectask.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sectask-10-sectask.c"; sourceTree = ""; }; + 0C78F1CB16A5E1BF00654E08 /* sectask_ipc.defs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.mig; path = sectask_ipc.defs; sourceTree = ""; }; + 0C95403F14E473AA00077526 /* libsecurity_ssl.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_ssl.xcodeproj; path = Security/libsecurity_ssl/libsecurity_ssl.xcodeproj; sourceTree = ""; }; + 0CA31A4614BB5C9100BD348C /* CipherSuite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CipherSuite.h; path = Security/libsecurity_ssl/lib/CipherSuite.h; sourceTree = ""; }; + 0CA31A7314BB6C2500BD348C /* sslTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sslTypes.h; path = Security/libsecurity_ssl/lib/sslTypes.h; sourceTree = ""; }; + 0CB321F01464A95F00587CD3 /* CreateCerts.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = CreateCerts.sh; sourceTree = ""; }; + 0CC82947138716F400BD99B7 /* libregressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libregressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 0CD72A5B16D5769A00A4B8A3 /* utilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = utilities.c; sourceTree = ""; }; + 0CD72A5C16D5769A00A4B8A3 /* utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utilities.h; sourceTree = ""; }; + 0CF55E5514DB47DE003AD8F2 /* tlsnke.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = tlsnke.xcodeproj; path = Security/tlsnke/tlsnke.xcodeproj; sourceTree = ""; }; + 107226D00D91DB32003CF14F /* SecTask.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecTask.c; sourceTree = ""; }; + 107226D10D91DB32003CF14F /* SecTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTask.h; sourceTree = ""; }; + 107227350D91FE89003CF14F /* libbsm.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbsm.dylib; path = usr/lib/libbsm.dylib; sourceTree = SDKROOT; }; + 18351B8F14CB65870097860E /* SecBase64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecBase64.h; sourceTree = ""; }; + 18F7F65814D77DF700F88A12 /* sec.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = sec.xcodeproj; path = Security/sec/sec.xcodeproj; sourceTree = ""; }; + 2281820D17B4686C0067C9C9 /* BackgroundTaskAgent.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BackgroundTaskAgent.framework; path = System/Library/PrivateFrameworks/BackgroundTaskAgent.framework; sourceTree = SDKROOT; }; + 443381D918A3D81400215606 /* SecAccessControl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecAccessControl.h; sourceTree = ""; }; + 443381DA18A3D81400215606 /* SecAccessControlPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecAccessControlPriv.h; sourceTree = ""; }; + 4AF7FFF315AFB73800B9D400 /* SecOTR.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecOTR.h; sourceTree = ""; }; + 4AF7FFF415AFB73800B9D400 /* SecOTRDHKey.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecOTRDHKey.h; sourceTree = ""; }; + 4AF7FFF515AFB73800B9D400 /* SecOTRErrors.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecOTRErrors.h; sourceTree = ""; }; + 4AF7FFF615AFB73800B9D400 /* SecOTRIdentityPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecOTRIdentityPriv.h; sourceTree = ""; }; + 4AF7FFF715AFB73800B9D400 /* SecOTRMath.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecOTRMath.h; sourceTree = ""; }; + 4AF7FFF915AFB73800B9D400 /* SecOTRPacketData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecOTRPacketData.h; sourceTree = ""; }; + 4AF7FFFA15AFB73800B9D400 /* SecOTRPackets.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecOTRPackets.h; sourceTree = ""; }; + 4AF7FFFB15AFB73800B9D400 /* SecOTRSession.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecOTRSession.h; sourceTree = ""; }; + 4AF7FFFC15AFB73800B9D400 /* SecOTRSessionPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecOTRSessionPriv.h; sourceTree = ""; }; + 4C0208F80D3C154200BFE54E /* SecBasePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecBasePriv.h; sourceTree = ""; }; + 4C04A90811924BBC0020550C /* SecKeyInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecKeyInternal.h; sourceTree = ""; }; + 4C079EBC1794A96200D73970 /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = System/Library/PrivateFrameworks/ServiceManagement.framework; sourceTree = SDKROOT; }; + 4C0B906C0ACCBD240077CD03 /* SecFramework.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecFramework.h; sourceTree = ""; }; + 4C12828C0BB4957D00985BB0 /* SecTrustSettingsPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTrustSettingsPriv.h; sourceTree = ""; }; + 4C198F1E0ACDB4BF00AAB142 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/Certificate.strings; sourceTree = ""; }; + 4C198F200ACDB4BF00AAB142 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/OID.strings; sourceTree = ""; }; + 4C1B442C0BB9CAF900461B82 /* SecTrustStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTrustStore.h; sourceTree = ""; }; + 4C28BCD60986EBCB0020C665 /* certextensions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = certextensions.h; sourceTree = ""; }; + 4C2F81D40BF121D2003C4F77 /* SecRandom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecRandom.h; sourceTree = ""; }; + 4C2FEC4915755D700008BE39 /* utilities.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = utilities.xcodeproj; path = Security/utilities/utilities.xcodeproj; sourceTree = ""; }; + 4C32C0AF0A4975F6002891BD /* Security.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Security.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C35DC37094F9120002917C4 /* Security-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Security-Info.plist"; sourceTree = ""; }; + 4C3CECEA1416DB2200947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-CertiID_Enterprise_Certificate_Authority.crt"; sourceTree = ""; }; + 4C3CECEB1416DB2200947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt"; sourceTree = ""; }; + 4C3CECEC1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheid.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-diginotarpkioverheidcaoverheid.crt"; sourceTree = ""; }; + 4C3CECED1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt"; sourceTree = ""; }; + 4C3CECEE1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt; sourceTree = ""; }; + 4C3CECEF1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = Ministerie_van_Defensie_Certificatie_Autoriteit.crt; sourceTree = ""; }; + 4C3CECF01416DB2200947741 /* staatdernederlandenorganisatieca-g2-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "staatdernederlandenorganisatieca-g2-Cert.crt"; sourceTree = ""; }; + 4C3CECF11416DB2200947741 /* staatdernederlandenoverheidca-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "staatdernederlandenoverheidca-Cert.crt"; sourceTree = ""; }; + 4C3CECF21416E20400947741 /* DigiNotar_Root_CA_G2-RootCertificate.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "DigiNotar_Root_CA_G2-RootCertificate.crt"; sourceTree = ""; }; + 4C3DD6AE179755560093F9D8 /* NSDate+TimeIntervalDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+TimeIntervalDescription.h"; sourceTree = ""; }; + 4C3DD6AF179755560093F9D8 /* NSDate+TimeIntervalDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDate+TimeIntervalDescription.m"; sourceTree = ""; }; + 4C4296300BB0A68200491999 /* SecTrustSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTrustSettings.h; sourceTree = ""; }; + 4C465C7D13AFD82300E841AC /* SecurityDevTests-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "SecurityDevTests-Info.plist"; sourceTree = ""; }; + 4C494C560F4F884800CDCBFE /* EVRoots.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = EVRoots.plist; sourceTree = ""; }; + 4C4CB7100DDA44900026B660 /* entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = ""; }; + 4C4CE9070AF81ED80056B01D /* TODO */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = TODO; sourceTree = ""; }; + 4C4CE90D0AF81EF80056B01D /* WHITEPAPER */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = WHITEPAPER; sourceTree = ""; }; + 4C4CE9120AF81F0E0056B01D /* README */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = README; sourceTree = ""; }; + 4C50ACFC1410671D00EE92DE /* DigiNotarCA2007RootCertificate.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = DigiNotarCA2007RootCertificate.crt; sourceTree = ""; }; + 4C50ACFD1410671D00EE92DE /* Invalid-asterisk.google.com.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-asterisk.google.com.crt"; sourceTree = ""; }; + 4C50ACFE1410671D00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt"; sourceTree = ""; }; + 4C50ACFF1410671D00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-webmail.terneuzen.nl-diginotar-services.crt"; sourceTree = ""; }; + 4C50AD001410671D00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-www.maestre.com-diginotal.extended.validation.crt"; sourceTree = ""; }; + 4C50AD011410671D00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt"; sourceTree = ""; }; + 4C50AD021410671D00EE92DE /* diginotar-public-ca-2025-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "diginotar-public-ca-2025-Cert.crt"; sourceTree = ""; }; + 4C50AD031410671D00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "diginotar-services-1024-entrust-secure-server-Cert.crt"; sourceTree = ""; }; + 4C50AD041410671D00EE92DE /* diginotar-services-diginotar-root-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "diginotar-services-diginotar-root-Cert.crt"; sourceTree = ""; }; + 4C50AD051410671D00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "diginotar.cyberca-gte.global.root-Cert.crt"; sourceTree = ""; }; + 4C50AD061410671D00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "diginotar.extended.validation-diginotar.root.ca-Cert.crt"; sourceTree = ""; }; + 4C50AD071410671D00EE92DE /* diginotar.root.ca-entrust-secure-server-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "diginotar.root.ca-entrust-secure-server-Cert.crt"; sourceTree = ""; }; + 4C50AD2F1410689300EE92DE /* Expectations.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expectations.plist; sourceTree = ""; }; + 4C52D0B416EFC61E0079966E /* CircleJoinRequested */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = CircleJoinRequested; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C52D0B816EFC61E0079966E /* AspenFamily.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = AspenFamily.xcconfig; path = AppleInternal/XcodeConfig/AspenFamily.xcconfig; sourceTree = DEVELOPER_DIR; }; + 4C52D0B916EFC61E0079966E /* CircleJoinRequested.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CircleJoinRequested.m; sourceTree = ""; }; + 4C52D0BB16EFC61E0079966E /* CircleJoinRequested.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = CircleJoinRequested.1; sourceTree = ""; }; + 4C52D0BD16EFC61E0079966E /* Readme.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Readme.txt; sourceTree = ""; }; + 4C52D0E216EFCCA20079966E /* Applicant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Applicant.h; sourceTree = ""; }; + 4C52D0E316EFCCA20079966E /* Applicant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Applicant.m; sourceTree = ""; }; + 4C52D0E416EFCCA20079966E /* com.apple.security.CircleJoinRequested.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.security.CircleJoinRequested.plist; sourceTree = ""; }; + 4C52D0E516EFCCA20079966E /* NSArray+map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+map.h"; sourceTree = ""; }; + 4C52D0E616EFCCA20079966E /* NSArray+map.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+map.m"; sourceTree = ""; }; + 4C60F1C409BE27E300B4040C /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + 4C6416D40BB34F00001C83FD /* SecPolicyPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecPolicyPriv.h; sourceTree = ""; }; + 4C6416F00BB357D5001C83FD /* SecInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecInternal.h; sourceTree = ""; }; + 4C64E00B0B8FBBF3009B306C /* Security.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Security.h; sourceTree = ""; }; + 4C696B3709BFA94F000CBC75 /* SecBase.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = SecBase.h; sourceTree = ""; }; + 4C7072840AC9EA4E007CC205 /* SecKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecKey.h; sourceTree = ""; }; + 4C7072D30AC9ED5A007CC205 /* SecKeyPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecKeyPriv.h; sourceTree = ""; }; + 4C7073C80ACB2BAD007CC205 /* SecRSAKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecRSAKey.h; sourceTree = ""; }; + 4C711D7613AFCD0900FE865D /* SecurityDevTests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SecurityDevTests.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C7391770B01745000C4CBFA /* vmdh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vmdh.h; sourceTree = ""; }; + 4C7416020F1D71A2008E0E4D /* SecSCEP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecSCEP.h; sourceTree = ""; }; + 4C7540BB13D51D63008048AC /* AllCertificatesNoPoliciesTest2EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = AllCertificatesNoPoliciesTest2EE.crt; sourceTree = ""; }; + 4C7540BC13D51D63008048AC /* AllCertificatesSamePoliciesTest10EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = AllCertificatesSamePoliciesTest10EE.crt; sourceTree = ""; }; + 4C7540BD13D51D63008048AC /* AllCertificatesSamePoliciesTest13EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = AllCertificatesSamePoliciesTest13EE.crt; sourceTree = ""; }; + 4C7540BE13D51D63008048AC /* AllCertificatesanyPolicyTest11EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = AllCertificatesanyPolicyTest11EE.crt; sourceTree = ""; }; + 4C7540BF13D51D63008048AC /* AnyPolicyTest14EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = AnyPolicyTest14EE.crt; sourceTree = ""; }; + 4C7540C013D51D63008048AC /* BadCRLIssuerNameCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = BadCRLIssuerNameCACert.crt; sourceTree = ""; }; + 4C7540C113D51D63008048AC /* BadCRLSignatureCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = BadCRLSignatureCACert.crt; sourceTree = ""; }; + 4C7540C213D51D63008048AC /* BadSignedCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = BadSignedCACert.crt; sourceTree = ""; }; + 4C7540C313D51D63008048AC /* BadnotAfterDateCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = BadnotAfterDateCACert.crt; sourceTree = ""; }; + 4C7540C413D51D63008048AC /* BadnotBeforeDateCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = BadnotBeforeDateCACert.crt; sourceTree = ""; }; + 4C7540C513D51D63008048AC /* BasicSelfIssuedCRLSigningKeyCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = BasicSelfIssuedCRLSigningKeyCACert.crt; sourceTree = ""; }; + 4C7540C613D51D63008048AC /* BasicSelfIssuedNewKeyCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = BasicSelfIssuedNewKeyCACert.crt; sourceTree = ""; }; + 4C7540C713D51D63008048AC /* BasicSelfIssuedNewKeyOldWithNewCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = BasicSelfIssuedNewKeyOldWithNewCACert.crt; sourceTree = ""; }; + 4C7540C813D51D63008048AC /* BasicSelfIssuedOldKeyCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = BasicSelfIssuedOldKeyCACert.crt; sourceTree = ""; }; + 4C7540C913D51D63008048AC /* BasicSelfIssuedOldKeyNewWithOldCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = BasicSelfIssuedOldKeyNewWithOldCACert.crt; sourceTree = ""; }; + 4C7540CA13D51D63008048AC /* CPSPointerQualifierTest20EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = CPSPointerQualifierTest20EE.crt; sourceTree = ""; }; + 4C7540CB13D51D63008048AC /* DSACACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = DSACACert.crt; sourceTree = ""; }; + 4C7540CC13D51D63008048AC /* DSAParametersInheritedCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = DSAParametersInheritedCACert.crt; sourceTree = ""; }; + 4C7540CD13D51D63008048AC /* DifferentPoliciesTest12EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = DifferentPoliciesTest12EE.crt; sourceTree = ""; }; + 4C7540CE13D51D63008048AC /* DifferentPoliciesTest3EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = DifferentPoliciesTest3EE.crt; sourceTree = ""; }; + 4C7540CF13D51D63008048AC /* DifferentPoliciesTest4EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = DifferentPoliciesTest4EE.crt; sourceTree = ""; }; + 4C7540D013D51D63008048AC /* DifferentPoliciesTest5EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = DifferentPoliciesTest5EE.crt; sourceTree = ""; }; + 4C7540D113D51D63008048AC /* DifferentPoliciesTest7EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = DifferentPoliciesTest7EE.crt; sourceTree = ""; }; + 4C7540D213D51D63008048AC /* DifferentPoliciesTest8EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = DifferentPoliciesTest8EE.crt; sourceTree = ""; }; + 4C7540D313D51D63008048AC /* DifferentPoliciesTest9EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = DifferentPoliciesTest9EE.crt; sourceTree = ""; }; + 4C7540D413D51D63008048AC /* GeneralizedTimeCRLnextUpdateCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = GeneralizedTimeCRLnextUpdateCACert.crt; sourceTree = ""; }; + 4C7540D513D51D63008048AC /* GoodCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = GoodCACert.crt; sourceTree = ""; }; + 4C7540D613D51D63008048AC /* GoodsubCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = GoodsubCACert.crt; sourceTree = ""; }; + 4C7540D713D51D63008048AC /* GoodsubCAPanyPolicyMapping1to2CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = GoodsubCAPanyPolicyMapping1to2CACert.crt; sourceTree = ""; }; + 4C7540D813D51D63008048AC /* InvalidBasicSelfIssuedNewWithOldTest5EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidBasicSelfIssuedNewWithOldTest5EE.crt; sourceTree = ""; }; + 4C7540D913D51D63008048AC /* InvalidBasicSelfIssuedOldWithNewTest2EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidBasicSelfIssuedOldWithNewTest2EE.crt; sourceTree = ""; }; + 4C7540DA13D51D63008048AC /* InvalidCASignatureTest2EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidCASignatureTest2EE.crt; sourceTree = ""; }; + 4C7540DB13D51D63008048AC /* InvalidCAnotAfterDateTest5EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidCAnotAfterDateTest5EE.crt; sourceTree = ""; }; + 4C7540DC13D51D63008048AC /* InvalidCAnotBeforeDateTest1EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidCAnotBeforeDateTest1EE.crt; sourceTree = ""; }; + 4C7540DD13D51D63008048AC /* InvalidDNSnameConstraintsTest31EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidDNSnameConstraintsTest31EE.crt; sourceTree = ""; }; + 4C7540DE13D51D63008048AC /* InvalidDNSnameConstraintsTest33EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidDNSnameConstraintsTest33EE.crt; sourceTree = ""; }; + 4C7540DF13D51D63008048AC /* InvalidDNSnameConstraintsTest38EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidDNSnameConstraintsTest38EE.crt; sourceTree = ""; }; + 4C7540E013D51D63008048AC /* InvalidDNandRFC822nameConstraintsTest28EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidDNandRFC822nameConstraintsTest28EE.crt; sourceTree = ""; }; + 4C7540E113D51D63008048AC /* InvalidDNandRFC822nameConstraintsTest29EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidDNandRFC822nameConstraintsTest29EE.crt; sourceTree = ""; }; + 4C7540E213D51D63008048AC /* InvalidDNnameConstraintsTest10EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidDNnameConstraintsTest10EE.crt; sourceTree = ""; }; + 4C7540E313D51D63008048AC /* InvalidDNnameConstraintsTest12EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidDNnameConstraintsTest12EE.crt; sourceTree = ""; }; + 4C7540E413D51D63008048AC /* InvalidDNnameConstraintsTest13EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidDNnameConstraintsTest13EE.crt; sourceTree = ""; }; + 4C7540E513D51D63008048AC /* InvalidDNnameConstraintsTest15EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidDNnameConstraintsTest15EE.crt; sourceTree = ""; }; + 4C7540E613D51D63008048AC /* InvalidDNnameConstraintsTest16EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidDNnameConstraintsTest16EE.crt; sourceTree = ""; }; + 4C7540E713D51D63008048AC /* InvalidDNnameConstraintsTest17EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidDNnameConstraintsTest17EE.crt; sourceTree = ""; }; + 4C7540E813D51D63008048AC /* InvalidDNnameConstraintsTest20EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidDNnameConstraintsTest20EE.crt; sourceTree = ""; }; + 4C7540E913D51D63008048AC /* InvalidDNnameConstraintsTest2EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidDNnameConstraintsTest2EE.crt; sourceTree = ""; }; + 4C7540EA13D51D63008048AC /* InvalidDNnameConstraintsTest3EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidDNnameConstraintsTest3EE.crt; sourceTree = ""; }; + 4C7540EB13D51D63008048AC /* InvalidDNnameConstraintsTest7EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidDNnameConstraintsTest7EE.crt; sourceTree = ""; }; + 4C7540EC13D51D63008048AC /* InvalidDNnameConstraintsTest8EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidDNnameConstraintsTest8EE.crt; sourceTree = ""; }; + 4C7540ED13D51D63008048AC /* InvalidDNnameConstraintsTest9EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidDNnameConstraintsTest9EE.crt; sourceTree = ""; }; + 4C7540EE13D51D63008048AC /* InvalidDSASignatureTest6EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidDSASignatureTest6EE.crt; sourceTree = ""; }; + 4C7540EF13D51D63008048AC /* InvalidEESignatureTest3EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidEESignatureTest3EE.crt; sourceTree = ""; }; + 4C7540F013D51D63008048AC /* InvalidEEnotAfterDateTest6EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidEEnotAfterDateTest6EE.crt; sourceTree = ""; }; + 4C7540F113D51D63008048AC /* InvalidEEnotBeforeDateTest2EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidEEnotBeforeDateTest2EE.crt; sourceTree = ""; }; + 4C7540F213D51D63008048AC /* InvalidLongSerialNumberTest18EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidLongSerialNumberTest18EE.crt; sourceTree = ""; }; + 4C7540F313D51D63008048AC /* InvalidMappingFromanyPolicyTest7EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidMappingFromanyPolicyTest7EE.crt; sourceTree = ""; }; + 4C7540F413D51D63008048AC /* InvalidMappingToanyPolicyTest8EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidMappingToanyPolicyTest8EE.crt; sourceTree = ""; }; + 4C7540F513D51D63008048AC /* InvalidMissingbasicConstraintsTest1EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidMissingbasicConstraintsTest1EE.crt; sourceTree = ""; }; + 4C7540F613D51D63008048AC /* InvalidNameChainingOrderTest2EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidNameChainingOrderTest2EE.crt; sourceTree = ""; }; + 4C7540F713D51D63008048AC /* InvalidNameChainingTest1EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidNameChainingTest1EE.crt; sourceTree = ""; }; + 4C7540F813D51D63008048AC /* InvalidNegativeSerialNumberTest15EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidNegativeSerialNumberTest15EE.crt; sourceTree = ""; }; + 4C7540F913D51D63008048AC /* InvalidPolicyMappingTest10EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidPolicyMappingTest10EE.crt; sourceTree = ""; }; + 4C7540FA13D51D63008048AC /* InvalidPolicyMappingTest2EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidPolicyMappingTest2EE.crt; sourceTree = ""; }; + 4C7540FB13D51D63008048AC /* InvalidPolicyMappingTest4EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidPolicyMappingTest4EE.crt; sourceTree = ""; }; + 4C7540FC13D51D63008048AC /* InvalidRFC822nameConstraintsTest22EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidRFC822nameConstraintsTest22EE.crt; sourceTree = ""; }; + 4C7540FD13D51D63008048AC /* InvalidRFC822nameConstraintsTest24EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidRFC822nameConstraintsTest24EE.crt; sourceTree = ""; }; + 4C7540FE13D51D63008048AC /* InvalidRFC822nameConstraintsTest26EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidRFC822nameConstraintsTest26EE.crt; sourceTree = ""; }; + 4C7540FF13D51D63008048AC /* InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt; sourceTree = ""; }; + 4C75410013D51D63008048AC /* InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt; sourceTree = ""; }; + 4C75410113D51D63008048AC /* InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt; sourceTree = ""; }; + 4C75410213D51D63008048AC /* InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt; sourceTree = ""; }; + 4C75410313D51D63008048AC /* InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt; sourceTree = ""; }; + 4C75410413D51D63008048AC /* InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt; sourceTree = ""; }; + 4C75410513D51D63008048AC /* InvalidSelfIssuedpathLenConstraintTest16EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidSelfIssuedpathLenConstraintTest16EE.crt; sourceTree = ""; }; + 4C75410613D51D63008048AC /* InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt; sourceTree = ""; }; + 4C75410713D51D63008048AC /* InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt; sourceTree = ""; }; + 4C75410813D51D63008048AC /* InvalidURInameConstraintsTest35EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidURInameConstraintsTest35EE.crt; sourceTree = ""; }; + 4C75410913D51D63008048AC /* InvalidURInameConstraintsTest37EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidURInameConstraintsTest37EE.crt; sourceTree = ""; }; + 4C75410A13D51D63008048AC /* InvalidUnknownCriticalCertificateExtensionTest2EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidUnknownCriticalCertificateExtensionTest2EE.crt; sourceTree = ""; }; + 4C75410B13D51D63008048AC /* InvalidcAFalseTest2EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidcAFalseTest2EE.crt; sourceTree = ""; }; + 4C75410C13D51D63008048AC /* InvalidcAFalseTest3EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidcAFalseTest3EE.crt; sourceTree = ""; }; + 4C75410D13D51D63008048AC /* InvalidcRLIssuerTest27EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidcRLIssuerTest27EE.crt; sourceTree = ""; }; + 4C75410E13D51D63008048AC /* InvalidcRLIssuerTest31EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidcRLIssuerTest31EE.crt; sourceTree = ""; }; + 4C75410F13D51D63008048AC /* InvalidcRLIssuerTest32EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidcRLIssuerTest32EE.crt; sourceTree = ""; }; + 4C75411013D51D63008048AC /* InvalidcRLIssuerTest34EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidcRLIssuerTest34EE.crt; sourceTree = ""; }; + 4C75411113D51D63008048AC /* InvalidcRLIssuerTest35EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidcRLIssuerTest35EE.crt; sourceTree = ""; }; + 4C75411213D51D63008048AC /* InvalidinhibitAnyPolicyTest1EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidinhibitAnyPolicyTest1EE.crt; sourceTree = ""; }; + 4C75411313D51D63008048AC /* InvalidinhibitAnyPolicyTest4EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidinhibitAnyPolicyTest4EE.crt; sourceTree = ""; }; + 4C75411413D51D63008048AC /* InvalidinhibitAnyPolicyTest5EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidinhibitAnyPolicyTest5EE.crt; sourceTree = ""; }; + 4C75411513D51D63008048AC /* InvalidinhibitAnyPolicyTest6EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidinhibitAnyPolicyTest6EE.crt; sourceTree = ""; }; + 4C75411613D51D63008048AC /* InvalidinhibitPolicyMappingTest1EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidinhibitPolicyMappingTest1EE.crt; sourceTree = ""; }; + 4C75411713D51D63008048AC /* InvalidinhibitPolicyMappingTest3EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidinhibitPolicyMappingTest3EE.crt; sourceTree = ""; }; + 4C75411813D51D63008048AC /* InvalidinhibitPolicyMappingTest5EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidinhibitPolicyMappingTest5EE.crt; sourceTree = ""; }; + 4C75411913D51D63008048AC /* InvalidinhibitPolicyMappingTest6EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidinhibitPolicyMappingTest6EE.crt; sourceTree = ""; }; + 4C75411A13D51D63008048AC /* InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt; sourceTree = ""; }; + 4C75411B13D51D63008048AC /* InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt; sourceTree = ""; }; + 4C75411C13D51D63008048AC /* InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt; sourceTree = ""; }; + 4C75411D13D51D63008048AC /* InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt; sourceTree = ""; }; + 4C75411E13D51D63008048AC /* InvalidonlyContainsAttributeCertsTest14EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidonlyContainsAttributeCertsTest14EE.crt; sourceTree = ""; }; + 4C75411F13D51D63008048AC /* InvalidonlyContainsCACertsTest12EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidonlyContainsCACertsTest12EE.crt; sourceTree = ""; }; + 4C75412013D51D63008048AC /* InvalidonlyContainsUserCertsTest11EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidonlyContainsUserCertsTest11EE.crt; sourceTree = ""; }; + 4C75412113D51D63008048AC /* InvalidonlySomeReasonsTest15EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidonlySomeReasonsTest15EE.crt; sourceTree = ""; }; + 4C75412213D51D63008048AC /* InvalidonlySomeReasonsTest16EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidonlySomeReasonsTest16EE.crt; sourceTree = ""; }; + 4C75412313D51D63008048AC /* InvalidonlySomeReasonsTest17EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidonlySomeReasonsTest17EE.crt; sourceTree = ""; }; + 4C75412413D51D63008048AC /* InvalidonlySomeReasonsTest20EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidonlySomeReasonsTest20EE.crt; sourceTree = ""; }; + 4C75412513D51D63008048AC /* InvalidonlySomeReasonsTest21EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidonlySomeReasonsTest21EE.crt; sourceTree = ""; }; + 4C75412613D51D63008048AC /* InvalidpathLenConstraintTest10EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidpathLenConstraintTest10EE.crt; sourceTree = ""; }; + 4C75412713D51D63008048AC /* InvalidpathLenConstraintTest11EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidpathLenConstraintTest11EE.crt; sourceTree = ""; }; + 4C75412813D51D63008048AC /* InvalidpathLenConstraintTest12EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidpathLenConstraintTest12EE.crt; sourceTree = ""; }; + 4C75412913D51D63008048AC /* InvalidpathLenConstraintTest5EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidpathLenConstraintTest5EE.crt; sourceTree = ""; }; + 4C75412A13D51D63008048AC /* InvalidpathLenConstraintTest6EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidpathLenConstraintTest6EE.crt; sourceTree = ""; }; + 4C75412B13D51D63008048AC /* InvalidpathLenConstraintTest9EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidpathLenConstraintTest9EE.crt; sourceTree = ""; }; + 4C75412C13D51D63008048AC /* Invalidpre2000UTCEEnotAfterDateTest7EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = Invalidpre2000UTCEEnotAfterDateTest7EE.crt; sourceTree = ""; }; + 4C75412D13D51D63008048AC /* InvalidrequireExplicitPolicyTest3EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidrequireExplicitPolicyTest3EE.crt; sourceTree = ""; }; + 4C75412E13D51D63008048AC /* InvalidrequireExplicitPolicyTest5EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = InvalidrequireExplicitPolicyTest5EE.crt; sourceTree = ""; }; + 4C75412F13D51D63008048AC /* LongSerialNumberCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = LongSerialNumberCACert.crt; sourceTree = ""; }; + 4C75413013D51D63008048AC /* Mapping1to2CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = Mapping1to2CACert.crt; sourceTree = ""; }; + 4C75413113D51D63008048AC /* MappingFromanyPolicyCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = MappingFromanyPolicyCACert.crt; sourceTree = ""; }; + 4C75413213D51D63008048AC /* MappingToanyPolicyCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = MappingToanyPolicyCACert.crt; sourceTree = ""; }; + 4C75413313D51D63008048AC /* MissingbasicConstraintsCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = MissingbasicConstraintsCACert.crt; sourceTree = ""; }; + 4C75413413D51D63008048AC /* NameOrderingCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = NameOrderingCACert.crt; sourceTree = ""; }; + 4C75413513D51D63008048AC /* NegativeSerialNumberCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = NegativeSerialNumberCACert.crt; sourceTree = ""; }; + 4C75413613D51D63008048AC /* NoCRLCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = NoCRLCACert.crt; sourceTree = ""; }; + 4C75413713D51D63008048AC /* NoPoliciesCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = NoPoliciesCACert.crt; sourceTree = ""; }; + 4C75413813D51D63008048AC /* NoissuingDistributionPointCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = NoissuingDistributionPointCACert.crt; sourceTree = ""; }; + 4C75413913D51D63008048AC /* OldCRLnextUpdateCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = OldCRLnextUpdateCACert.crt; sourceTree = ""; }; + 4C75413A13D51D63008048AC /* OverlappingPoliciesTest6EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = OverlappingPoliciesTest6EE.crt; sourceTree = ""; }; + 4C75413B13D51D63008048AC /* P12Mapping1to3CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = P12Mapping1to3CACert.crt; sourceTree = ""; }; + 4C75413C13D51D63008048AC /* P12Mapping1to3subCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = P12Mapping1to3subCACert.crt; sourceTree = ""; }; + 4C75413D13D51D63008048AC /* P12Mapping1to3subsubCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = P12Mapping1to3subsubCACert.crt; sourceTree = ""; }; + 4C75413E13D51D63008048AC /* P1Mapping1to234CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = P1Mapping1to234CACert.crt; sourceTree = ""; }; + 4C75413F13D51D63008048AC /* P1Mapping1to234subCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = P1Mapping1to234subCACert.crt; sourceTree = ""; }; + 4C75414013D51D63008048AC /* P1anyPolicyMapping1to2CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = P1anyPolicyMapping1to2CACert.crt; sourceTree = ""; }; + 4C75414113D51D63008048AC /* PanyPolicyMapping1to2CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = PanyPolicyMapping1to2CACert.crt; sourceTree = ""; }; + 4C75414213D51D63008048AC /* PoliciesP1234CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = PoliciesP1234CACert.crt; sourceTree = ""; }; + 4C75414313D51D63008048AC /* PoliciesP1234subCAP123Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = PoliciesP1234subCAP123Cert.crt; sourceTree = ""; }; + 4C75414413D51D63008048AC /* PoliciesP1234subsubCAP123P12Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = PoliciesP1234subsubCAP123P12Cert.crt; sourceTree = ""; }; + 4C75414513D51D63008048AC /* PoliciesP123CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = PoliciesP123CACert.crt; sourceTree = ""; }; + 4C75414613D51D63008048AC /* PoliciesP123subCAP12Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = PoliciesP123subCAP12Cert.crt; sourceTree = ""; }; + 4C75414713D51D63008048AC /* PoliciesP123subsubCAP12P1Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = PoliciesP123subsubCAP12P1Cert.crt; sourceTree = ""; }; + 4C75414813D51D63008048AC /* PoliciesP123subsubCAP12P2Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = PoliciesP123subsubCAP12P2Cert.crt; sourceTree = ""; }; + 4C75414913D51D63008048AC /* PoliciesP123subsubsubCAP12P2P1Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = PoliciesP123subsubsubCAP12P2P1Cert.crt; sourceTree = ""; }; + 4C75414A13D51D63008048AC /* PoliciesP12CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = PoliciesP12CACert.crt; sourceTree = ""; }; + 4C75414B13D51D63008048AC /* PoliciesP12subCAP1Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = PoliciesP12subCAP1Cert.crt; sourceTree = ""; }; + 4C75414C13D51D63008048AC /* PoliciesP12subsubCAP1P2Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = PoliciesP12subsubCAP1P2Cert.crt; sourceTree = ""; }; + 4C75414D13D51D63008048AC /* PoliciesP2subCA2Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = PoliciesP2subCA2Cert.crt; sourceTree = ""; }; + 4C75414E13D51D63008048AC /* PoliciesP2subCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = PoliciesP2subCACert.crt; sourceTree = ""; }; + 4C75414F13D51D63008048AC /* PoliciesP3CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = PoliciesP3CACert.crt; sourceTree = ""; }; + 4C75415013D51D63008048AC /* RFC3280MandatoryAttributeTypesCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = RFC3280MandatoryAttributeTypesCACert.crt; sourceTree = ""; }; + 4C75415113D51D63008048AC /* RFC3280OptionalAttributeTypesCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = RFC3280OptionalAttributeTypesCACert.crt; sourceTree = ""; }; + 4C75415213D51D63008048AC /* RevokedsubCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = RevokedsubCACert.crt; sourceTree = ""; }; + 4C75415313D51D63008048AC /* RolloverfromPrintableStringtoUTF8StringCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = RolloverfromPrintableStringtoUTF8StringCACert.crt; sourceTree = ""; }; + 4C75415413D51D63008048AC /* SeparateCertificateandCRLKeysCA2CRLSigningCert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = SeparateCertificateandCRLKeysCA2CRLSigningCert.crt; sourceTree = ""; }; + 4C75415513D51D63008048AC /* SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt; sourceTree = ""; }; + 4C75415613D51D63008048AC /* SeparateCertificateandCRLKeysCertificateSigningCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = SeparateCertificateandCRLKeysCertificateSigningCACert.crt; sourceTree = ""; }; + 4C75415713D51D63008048AC /* TrustAnchorRootCertificate.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = TrustAnchorRootCertificate.crt; sourceTree = ""; }; + 4C75415813D51D63008048AC /* TwoCRLsCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = TwoCRLsCACert.crt; sourceTree = ""; }; + 4C75415913D51D63008048AC /* UIDCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = UIDCACert.crt; sourceTree = ""; }; + 4C75415A13D51D63008048AC /* UTF8StringCaseInsensitiveMatchCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = UTF8StringCaseInsensitiveMatchCACert.crt; sourceTree = ""; }; + 4C75415B13D51D63008048AC /* UTF8StringEncodedNamesCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = UTF8StringEncodedNamesCACert.crt; sourceTree = ""; }; + 4C75415C13D51D63008048AC /* UnknownCRLEntryExtensionCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = UnknownCRLEntryExtensionCACert.crt; sourceTree = ""; }; + 4C75415D13D51D63008048AC /* UnknownCRLExtensionCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = UnknownCRLExtensionCACert.crt; sourceTree = ""; }; + 4C75415E13D51D63008048AC /* UserNoticeQualifierTest15EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = UserNoticeQualifierTest15EE.crt; sourceTree = ""; }; + 4C75415F13D51D63008048AC /* UserNoticeQualifierTest16EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = UserNoticeQualifierTest16EE.crt; sourceTree = ""; }; + 4C75416013D51D63008048AC /* UserNoticeQualifierTest17EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = UserNoticeQualifierTest17EE.crt; sourceTree = ""; }; + 4C75416113D51D63008048AC /* UserNoticeQualifierTest18EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = UserNoticeQualifierTest18EE.crt; sourceTree = ""; }; + 4C75416213D51D63008048AC /* UserNoticeQualifierTest19EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = UserNoticeQualifierTest19EE.crt; sourceTree = ""; }; + 4C75416313D51D63008048AC /* ValidBasicSelfIssuedNewWithOldTest3EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidBasicSelfIssuedNewWithOldTest3EE.crt; sourceTree = ""; }; + 4C75416413D51D63008048AC /* ValidBasicSelfIssuedNewWithOldTest4EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidBasicSelfIssuedNewWithOldTest4EE.crt; sourceTree = ""; }; + 4C75416513D51D63008048AC /* ValidBasicSelfIssuedOldWithNewTest1EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidBasicSelfIssuedOldWithNewTest1EE.crt; sourceTree = ""; }; + 4C75416613D51D63008048AC /* ValidCertificatePathTest1EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidCertificatePathTest1EE.crt; sourceTree = ""; }; + 4C75416713D51D63008048AC /* ValidDNSnameConstraintsTest30EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidDNSnameConstraintsTest30EE.crt; sourceTree = ""; }; + 4C75416813D51D63008048AC /* ValidDNSnameConstraintsTest32EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidDNSnameConstraintsTest32EE.crt; sourceTree = ""; }; + 4C75416913D51D63008048AC /* ValidDNandRFC822nameConstraintsTest27EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidDNandRFC822nameConstraintsTest27EE.crt; sourceTree = ""; }; + 4C75416A13D51D63008048AC /* ValidDNnameConstraintsTest11EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidDNnameConstraintsTest11EE.crt; sourceTree = ""; }; + 4C75416B13D51D63008048AC /* ValidDNnameConstraintsTest14EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidDNnameConstraintsTest14EE.crt; sourceTree = ""; }; + 4C75416C13D51D63008048AC /* ValidDNnameConstraintsTest18EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidDNnameConstraintsTest18EE.crt; sourceTree = ""; }; + 4C75416D13D51D63008048AC /* ValidDNnameConstraintsTest19EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidDNnameConstraintsTest19EE.crt; sourceTree = ""; }; + 4C75416E13D51D63008048AC /* ValidDNnameConstraintsTest1EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidDNnameConstraintsTest1EE.crt; sourceTree = ""; }; + 4C75416F13D51D63008048AC /* ValidDNnameConstraintsTest4EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidDNnameConstraintsTest4EE.crt; sourceTree = ""; }; + 4C75417013D51D63008048AC /* ValidDNnameConstraintsTest5EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidDNnameConstraintsTest5EE.crt; sourceTree = ""; }; + 4C75417113D51D63008048AC /* ValidDNnameConstraintsTest6EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidDNnameConstraintsTest6EE.crt; sourceTree = ""; }; + 4C75417213D51D63008048AC /* ValidDSAParameterInheritanceTest5EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidDSAParameterInheritanceTest5EE.crt; sourceTree = ""; }; + 4C75417313D51D63008048AC /* ValidDSASignaturesTest4EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidDSASignaturesTest4EE.crt; sourceTree = ""; }; + 4C75417413D51D63008048AC /* ValidGeneralizedTimenotAfterDateTest8EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidGeneralizedTimenotAfterDateTest8EE.crt; sourceTree = ""; }; + 4C75417513D51D63008048AC /* ValidGeneralizedTimenotBeforeDateTest4EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidGeneralizedTimenotBeforeDateTest4EE.crt; sourceTree = ""; }; + 4C75417613D51D63008048AC /* ValidLongSerialNumberTest16EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidLongSerialNumberTest16EE.crt; sourceTree = ""; }; + 4C75417713D51D63008048AC /* ValidLongSerialNumberTest17EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidLongSerialNumberTest17EE.crt; sourceTree = ""; }; + 4C75417813D51D63008048AC /* ValidNameChainingCapitalizationTest5EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidNameChainingCapitalizationTest5EE.crt; sourceTree = ""; }; + 4C75417913D51D63008048AC /* ValidNameChainingWhitespaceTest3EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidNameChainingWhitespaceTest3EE.crt; sourceTree = ""; }; + 4C75417A13D51D63008048AC /* ValidNameChainingWhitespaceTest4EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidNameChainingWhitespaceTest4EE.crt; sourceTree = ""; }; + 4C75417B13D51D63008048AC /* ValidNameUIDsTest6EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidNameUIDsTest6EE.crt; sourceTree = ""; }; + 4C75417C13D51D63008048AC /* ValidNegativeSerialNumberTest14EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidNegativeSerialNumberTest14EE.crt; sourceTree = ""; }; + 4C75417D13D51D63008048AC /* ValidPolicyMappingTest11EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidPolicyMappingTest11EE.crt; sourceTree = ""; }; + 4C75417E13D51D63008048AC /* ValidPolicyMappingTest12EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidPolicyMappingTest12EE.crt; sourceTree = ""; }; + 4C75417F13D51D63008048AC /* ValidPolicyMappingTest13EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidPolicyMappingTest13EE.crt; sourceTree = ""; }; + 4C75418013D51D63008048AC /* ValidPolicyMappingTest14EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidPolicyMappingTest14EE.crt; sourceTree = ""; }; + 4C75418113D51D63008048AC /* ValidPolicyMappingTest1EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidPolicyMappingTest1EE.crt; sourceTree = ""; }; + 4C75418213D51D63008048AC /* ValidPolicyMappingTest3EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidPolicyMappingTest3EE.crt; sourceTree = ""; }; + 4C75418313D51D63008048AC /* ValidPolicyMappingTest5EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidPolicyMappingTest5EE.crt; sourceTree = ""; }; + 4C75418413D51D63008048AC /* ValidPolicyMappingTest6EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidPolicyMappingTest6EE.crt; sourceTree = ""; }; + 4C75418513D51D63008048AC /* ValidPolicyMappingTest9EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidPolicyMappingTest9EE.crt; sourceTree = ""; }; + 4C75418613D51D63008048AC /* ValidRFC3280MandatoryAttributeTypesTest7EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidRFC3280MandatoryAttributeTypesTest7EE.crt; sourceTree = ""; }; + 4C75418713D51D63008048AC /* ValidRFC3280OptionalAttributeTypesTest8EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidRFC3280OptionalAttributeTypesTest8EE.crt; sourceTree = ""; }; + 4C75418813D51D63008048AC /* ValidRFC822nameConstraintsTest21EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidRFC822nameConstraintsTest21EE.crt; sourceTree = ""; }; + 4C75418913D51D63008048AC /* ValidRFC822nameConstraintsTest23EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidRFC822nameConstraintsTest23EE.crt; sourceTree = ""; }; + 4C75418A13D51D63008048AC /* ValidRFC822nameConstraintsTest25EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidRFC822nameConstraintsTest25EE.crt; sourceTree = ""; }; + 4C75418B13D51D63008048AC /* ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt; sourceTree = ""; }; + 4C75418C13D51D63008048AC /* ValidSelfIssuedinhibitAnyPolicyTest7EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidSelfIssuedinhibitAnyPolicyTest7EE.crt; sourceTree = ""; }; + 4C75418D13D51D63008048AC /* ValidSelfIssuedinhibitAnyPolicyTest9EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidSelfIssuedinhibitAnyPolicyTest9EE.crt; sourceTree = ""; }; + 4C75418E13D51D63008048AC /* ValidSelfIssuedinhibitPolicyMappingTest7EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidSelfIssuedinhibitPolicyMappingTest7EE.crt; sourceTree = ""; }; + 4C75418F13D51D63008048AC /* ValidSelfIssuedpathLenConstraintTest15EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidSelfIssuedpathLenConstraintTest15EE.crt; sourceTree = ""; }; + 4C75419013D51D63008048AC /* ValidSelfIssuedpathLenConstraintTest17EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidSelfIssuedpathLenConstraintTest17EE.crt; sourceTree = ""; }; + 4C75419113D51D63008048AC /* ValidSelfIssuedrequireExplicitPolicyTest6EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidSelfIssuedrequireExplicitPolicyTest6EE.crt; sourceTree = ""; }; + 4C75419213D51D63008048AC /* ValidURInameConstraintsTest34EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidURInameConstraintsTest34EE.crt; sourceTree = ""; }; + 4C75419313D51D63008048AC /* ValidURInameConstraintsTest36EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidURInameConstraintsTest36EE.crt; sourceTree = ""; }; + 4C75419413D51D63008048AC /* ValidUTF8StringCaseInsensitiveMatchTest11EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidUTF8StringCaseInsensitiveMatchTest11EE.crt; sourceTree = ""; }; + 4C75419513D51D63008048AC /* ValidUTF8StringEncodedNamesTest9EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidUTF8StringEncodedNamesTest9EE.crt; sourceTree = ""; }; + 4C75419613D51D63008048AC /* ValidUnknownNotCriticalCertificateExtensionTest1EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidUnknownNotCriticalCertificateExtensionTest1EE.crt; sourceTree = ""; }; + 4C75419713D51D63008048AC /* ValidbasicConstraintsNotCriticalTest4EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidbasicConstraintsNotCriticalTest4EE.crt; sourceTree = ""; }; + 4C75419813D51D63008048AC /* ValidcRLIssuerTest28EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidcRLIssuerTest28EE.crt; sourceTree = ""; }; + 4C75419913D51D63008048AC /* ValidcRLIssuerTest29EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidcRLIssuerTest29EE.crt; sourceTree = ""; }; + 4C75419A13D51D63008048AC /* ValidcRLIssuerTest30EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidcRLIssuerTest30EE.crt; sourceTree = ""; }; + 4C75419B13D51D63008048AC /* ValidcRLIssuerTest33EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidcRLIssuerTest33EE.crt; sourceTree = ""; }; + 4C75419C13D51D63008048AC /* ValidinhibitAnyPolicyTest2EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidinhibitAnyPolicyTest2EE.crt; sourceTree = ""; }; + 4C75419D13D51D63008048AC /* ValidinhibitPolicyMappingTest2EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidinhibitPolicyMappingTest2EE.crt; sourceTree = ""; }; + 4C75419E13D51D63008048AC /* ValidinhibitPolicyMappingTest4EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidinhibitPolicyMappingTest4EE.crt; sourceTree = ""; }; + 4C75419F13D51D63008048AC /* ValidkeyUsageNotCriticalTest3EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidkeyUsageNotCriticalTest3EE.crt; sourceTree = ""; }; + 4C7541A013D51D63008048AC /* ValidonlyContainsCACertsTest13EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidonlyContainsCACertsTest13EE.crt; sourceTree = ""; }; + 4C7541A113D51D63008048AC /* ValidonlySomeReasonsTest18EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidonlySomeReasonsTest18EE.crt; sourceTree = ""; }; + 4C7541A213D51D63008048AC /* ValidonlySomeReasonsTest19EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidonlySomeReasonsTest19EE.crt; sourceTree = ""; }; + 4C7541A313D51D63008048AC /* ValidpathLenConstraintTest13EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidpathLenConstraintTest13EE.crt; sourceTree = ""; }; + 4C7541A413D51D63008048AC /* ValidpathLenConstraintTest14EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidpathLenConstraintTest14EE.crt; sourceTree = ""; }; + 4C7541A513D51D63008048AC /* ValidpathLenConstraintTest7EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidpathLenConstraintTest7EE.crt; sourceTree = ""; }; + 4C7541A613D51D63008048AC /* ValidpathLenConstraintTest8EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidpathLenConstraintTest8EE.crt; sourceTree = ""; }; + 4C7541A713D51D63008048AC /* Validpre2000UTCnotBeforeDateTest3EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = Validpre2000UTCnotBeforeDateTest3EE.crt; sourceTree = ""; }; + 4C7541A813D51D63008048AC /* ValidrequireExplicitPolicyTest1EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidrequireExplicitPolicyTest1EE.crt; sourceTree = ""; }; + 4C7541A913D51D63008048AC /* ValidrequireExplicitPolicyTest2EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidrequireExplicitPolicyTest2EE.crt; sourceTree = ""; }; + 4C7541AA13D51D63008048AC /* ValidrequireExplicitPolicyTest4EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = ValidrequireExplicitPolicyTest4EE.crt; sourceTree = ""; }; + 4C7541AB13D51D63008048AC /* WrongCRLCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = WrongCRLCACert.crt; sourceTree = ""; }; + 4C7541AC13D51D63008048AC /* anyPolicyCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = anyPolicyCACert.crt; sourceTree = ""; }; + 4C7541AD13D51D63008048AC /* basicConstraintsCriticalcAFalseCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = basicConstraintsCriticalcAFalseCACert.crt; sourceTree = ""; }; + 4C7541AE13D51D63008048AC /* basicConstraintsNotCriticalCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = basicConstraintsNotCriticalCACert.crt; sourceTree = ""; }; + 4C7541AF13D51D63008048AC /* basicConstraintsNotCriticalcAFalseCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = basicConstraintsNotCriticalcAFalseCACert.crt; sourceTree = ""; }; + 4C7541B013D51D63008048AC /* deltaCRLCA1Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = deltaCRLCA1Cert.crt; sourceTree = ""; }; + 4C7541B113D51D63008048AC /* deltaCRLCA2Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = deltaCRLCA2Cert.crt; sourceTree = ""; }; + 4C7541B213D51D63008048AC /* deltaCRLCA3Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = deltaCRLCA3Cert.crt; sourceTree = ""; }; + 4C7541B313D51D63008048AC /* deltaCRLIndicatorNoBaseCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = deltaCRLIndicatorNoBaseCACert.crt; sourceTree = ""; }; + 4C7541B413D51D63008048AC /* distributionPoint1CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = distributionPoint1CACert.crt; sourceTree = ""; }; + 4C7541B513D51D63008048AC /* distributionPoint2CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = distributionPoint2CACert.crt; sourceTree = ""; }; + 4C7541B613D51D63008048AC /* indirectCRLCA1Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = indirectCRLCA1Cert.crt; sourceTree = ""; }; + 4C7541B713D51D63008048AC /* indirectCRLCA2Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = indirectCRLCA2Cert.crt; sourceTree = ""; }; + 4C7541B813D51D63008048AC /* indirectCRLCA3Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = indirectCRLCA3Cert.crt; sourceTree = ""; }; + 4C7541B913D51D63008048AC /* indirectCRLCA3cRLIssuerCert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = indirectCRLCA3cRLIssuerCert.crt; sourceTree = ""; }; + 4C7541BA13D51D63008048AC /* indirectCRLCA4Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = indirectCRLCA4Cert.crt; sourceTree = ""; }; + 4C7541BB13D51D63008048AC /* indirectCRLCA4cRLIssuerCert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = indirectCRLCA4cRLIssuerCert.crt; sourceTree = ""; }; + 4C7541BC13D51D63008048AC /* indirectCRLCA5Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = indirectCRLCA5Cert.crt; sourceTree = ""; }; + 4C7541BD13D51D63008048AC /* indirectCRLCA6Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = indirectCRLCA6Cert.crt; sourceTree = ""; }; + 4C7541BE13D51D63008048AC /* inhibitAnyPolicy0CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitAnyPolicy0CACert.crt; sourceTree = ""; }; + 4C7541BF13D51D63008048AC /* inhibitAnyPolicy1CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitAnyPolicy1CACert.crt; sourceTree = ""; }; + 4C7541C013D51D63008048AC /* inhibitAnyPolicy1SelfIssuedCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitAnyPolicy1SelfIssuedCACert.crt; sourceTree = ""; }; + 4C7541C113D51D63008048AC /* inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt; sourceTree = ""; }; + 4C7541C213D51D63008048AC /* inhibitAnyPolicy1subCA1Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitAnyPolicy1subCA1Cert.crt; sourceTree = ""; }; + 4C7541C313D51D63008048AC /* inhibitAnyPolicy1subCA2Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitAnyPolicy1subCA2Cert.crt; sourceTree = ""; }; + 4C7541C413D51D63008048AC /* inhibitAnyPolicy1subCAIAP5Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitAnyPolicy1subCAIAP5Cert.crt; sourceTree = ""; }; + 4C7541C513D51D63008048AC /* inhibitAnyPolicy1subsubCA2Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitAnyPolicy1subsubCA2Cert.crt; sourceTree = ""; }; + 4C7541C613D51D63008048AC /* inhibitAnyPolicy5CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitAnyPolicy5CACert.crt; sourceTree = ""; }; + 4C7541C713D51D63008048AC /* inhibitAnyPolicy5subCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitAnyPolicy5subCACert.crt; sourceTree = ""; }; + 4C7541C813D51D63008048AC /* inhibitAnyPolicy5subsubCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitAnyPolicy5subsubCACert.crt; sourceTree = ""; }; + 4C7541C913D51D63008048AC /* inhibitAnyPolicyTest3EE.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitAnyPolicyTest3EE.crt; sourceTree = ""; }; + 4C7541CA13D51D63008048AC /* inhibitPolicyMapping0CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitPolicyMapping0CACert.crt; sourceTree = ""; }; + 4C7541CB13D51D63008048AC /* inhibitPolicyMapping0subCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitPolicyMapping0subCACert.crt; sourceTree = ""; }; + 4C7541CC13D51D63008048AC /* inhibitPolicyMapping1P12CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitPolicyMapping1P12CACert.crt; sourceTree = ""; }; + 4C7541CD13D51D63008048AC /* inhibitPolicyMapping1P12subCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitPolicyMapping1P12subCACert.crt; sourceTree = ""; }; + 4C7541CE13D51D63008048AC /* inhibitPolicyMapping1P12subCAIPM5Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitPolicyMapping1P12subCAIPM5Cert.crt; sourceTree = ""; }; + 4C7541CF13D51D63008048AC /* inhibitPolicyMapping1P12subsubCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitPolicyMapping1P12subsubCACert.crt; sourceTree = ""; }; + 4C7541D013D51D63008048AC /* inhibitPolicyMapping1P12subsubCAIPM5Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitPolicyMapping1P12subsubCAIPM5Cert.crt; sourceTree = ""; }; + 4C7541D113D51D63008048AC /* inhibitPolicyMapping1P1CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitPolicyMapping1P1CACert.crt; sourceTree = ""; }; + 4C7541D213D51D63008048AC /* inhibitPolicyMapping1P1SelfIssuedCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitPolicyMapping1P1SelfIssuedCACert.crt; sourceTree = ""; }; + 4C7541D313D51D63008048AC /* inhibitPolicyMapping1P1SelfIssuedsubCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitPolicyMapping1P1SelfIssuedsubCACert.crt; sourceTree = ""; }; + 4C7541D413D51D63008048AC /* inhibitPolicyMapping1P1subCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitPolicyMapping1P1subCACert.crt; sourceTree = ""; }; + 4C7541D513D51D63008048AC /* inhibitPolicyMapping1P1subsubCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitPolicyMapping1P1subsubCACert.crt; sourceTree = ""; }; + 4C7541D613D51D63008048AC /* inhibitPolicyMapping5CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitPolicyMapping5CACert.crt; sourceTree = ""; }; + 4C7541D713D51D63008048AC /* inhibitPolicyMapping5subCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitPolicyMapping5subCACert.crt; sourceTree = ""; }; + 4C7541D813D51D63008048AC /* inhibitPolicyMapping5subsubCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitPolicyMapping5subsubCACert.crt; sourceTree = ""; }; + 4C7541D913D51D63008048AC /* inhibitPolicyMapping5subsubsubCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = inhibitPolicyMapping5subsubsubCACert.crt; sourceTree = ""; }; + 4C7541DA13D51D63008048AC /* keyUsageCriticalcRLSignFalseCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = keyUsageCriticalcRLSignFalseCACert.crt; sourceTree = ""; }; + 4C7541DB13D51D63008048AC /* keyUsageCriticalkeyCertSignFalseCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = keyUsageCriticalkeyCertSignFalseCACert.crt; sourceTree = ""; }; + 4C7541DC13D51D63008048AC /* keyUsageNotCriticalCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = keyUsageNotCriticalCACert.crt; sourceTree = ""; }; + 4C7541DD13D51D63008048AC /* keyUsageNotCriticalcRLSignFalseCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = keyUsageNotCriticalcRLSignFalseCACert.crt; sourceTree = ""; }; + 4C7541DE13D51D63008048AC /* keyUsageNotCriticalkeyCertSignFalseCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = keyUsageNotCriticalkeyCertSignFalseCACert.crt; sourceTree = ""; }; + 4C7541DF13D51D63008048AC /* nameConstraintsDN1CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = nameConstraintsDN1CACert.crt; sourceTree = ""; }; + 4C7541E013D51D63008048AC /* nameConstraintsDN1SelfIssuedCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = nameConstraintsDN1SelfIssuedCACert.crt; sourceTree = ""; }; + 4C7541E113D51D63008048AC /* nameConstraintsDN1subCA1Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = nameConstraintsDN1subCA1Cert.crt; sourceTree = ""; }; + 4C7541E213D51D63008048AC /* nameConstraintsDN1subCA2Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = nameConstraintsDN1subCA2Cert.crt; sourceTree = ""; }; + 4C7541E313D51D63008048AC /* nameConstraintsDN1subCA3Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = nameConstraintsDN1subCA3Cert.crt; sourceTree = ""; }; + 4C7541E413D51D63008048AC /* nameConstraintsDN2CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = nameConstraintsDN2CACert.crt; sourceTree = ""; }; + 4C7541E513D51D63008048AC /* nameConstraintsDN3CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = nameConstraintsDN3CACert.crt; sourceTree = ""; }; + 4C7541E613D51D63008048AC /* nameConstraintsDN3subCA1Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = nameConstraintsDN3subCA1Cert.crt; sourceTree = ""; }; + 4C7541E713D51D63008048AC /* nameConstraintsDN3subCA2Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = nameConstraintsDN3subCA2Cert.crt; sourceTree = ""; }; + 4C7541E813D51D63008048AC /* nameConstraintsDN4CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = nameConstraintsDN4CACert.crt; sourceTree = ""; }; + 4C7541E913D51D63008048AC /* nameConstraintsDN5CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = nameConstraintsDN5CACert.crt; sourceTree = ""; }; + 4C7541EA13D51D63008048AC /* nameConstraintsDNS1CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = nameConstraintsDNS1CACert.crt; sourceTree = ""; }; + 4C7541EB13D51D63008048AC /* nameConstraintsDNS2CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = nameConstraintsDNS2CACert.crt; sourceTree = ""; }; + 4C7541EC13D51D63008048AC /* nameConstraintsRFC822CA1Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = nameConstraintsRFC822CA1Cert.crt; sourceTree = ""; }; + 4C7541ED13D51D63008048AC /* nameConstraintsRFC822CA2Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = nameConstraintsRFC822CA2Cert.crt; sourceTree = ""; }; + 4C7541EE13D51D63008048AC /* nameConstraintsRFC822CA3Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = nameConstraintsRFC822CA3Cert.crt; sourceTree = ""; }; + 4C7541EF13D51D63008048AC /* nameConstraintsURI1CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = nameConstraintsURI1CACert.crt; sourceTree = ""; }; + 4C7541F013D51D63008048AC /* nameConstraintsURI2CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = nameConstraintsURI2CACert.crt; sourceTree = ""; }; + 4C7541F113D51D63008048AC /* onlyContainsAttributeCertsCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = onlyContainsAttributeCertsCACert.crt; sourceTree = ""; }; + 4C7541F213D51D63008048AC /* onlyContainsCACertsCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = onlyContainsCACertsCACert.crt; sourceTree = ""; }; + 4C7541F313D51D63008048AC /* onlyContainsUserCertsCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = onlyContainsUserCertsCACert.crt; sourceTree = ""; }; + 4C7541F413D51D63008048AC /* onlySomeReasonsCA1Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = onlySomeReasonsCA1Cert.crt; sourceTree = ""; }; + 4C7541F513D51D63008048AC /* onlySomeReasonsCA2Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = onlySomeReasonsCA2Cert.crt; sourceTree = ""; }; + 4C7541F613D51D63008048AC /* onlySomeReasonsCA3Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = onlySomeReasonsCA3Cert.crt; sourceTree = ""; }; + 4C7541F713D51D63008048AC /* onlySomeReasonsCA4Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = onlySomeReasonsCA4Cert.crt; sourceTree = ""; }; + 4C7541F813D51D63008048AC /* pathLenConstraint0CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = pathLenConstraint0CACert.crt; sourceTree = ""; }; + 4C7541F913D51D63008048AC /* pathLenConstraint0SelfIssuedCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = pathLenConstraint0SelfIssuedCACert.crt; sourceTree = ""; }; + 4C7541FA13D51D63008048AC /* pathLenConstraint0subCA2Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = pathLenConstraint0subCA2Cert.crt; sourceTree = ""; }; + 4C7541FB13D51D63008048AC /* pathLenConstraint0subCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = pathLenConstraint0subCACert.crt; sourceTree = ""; }; + 4C7541FC13D51D63008048AC /* pathLenConstraint1CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = pathLenConstraint1CACert.crt; sourceTree = ""; }; + 4C7541FD13D51D63008048AC /* pathLenConstraint1SelfIssuedCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = pathLenConstraint1SelfIssuedCACert.crt; sourceTree = ""; }; + 4C7541FE13D51D63008048AC /* pathLenConstraint1SelfIssuedsubCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = pathLenConstraint1SelfIssuedsubCACert.crt; sourceTree = ""; }; + 4C7541FF13D51D63008048AC /* pathLenConstraint1subCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = pathLenConstraint1subCACert.crt; sourceTree = ""; }; + 4C75420013D51D64008048AC /* pathLenConstraint6CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = pathLenConstraint6CACert.crt; sourceTree = ""; }; + 4C75420113D51D64008048AC /* pathLenConstraint6subCA0Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = pathLenConstraint6subCA0Cert.crt; sourceTree = ""; }; + 4C75420213D51D64008048AC /* pathLenConstraint6subCA1Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = pathLenConstraint6subCA1Cert.crt; sourceTree = ""; }; + 4C75420313D51D64008048AC /* pathLenConstraint6subCA4Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = pathLenConstraint6subCA4Cert.crt; sourceTree = ""; }; + 4C75420413D51D64008048AC /* pathLenConstraint6subsubCA00Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = pathLenConstraint6subsubCA00Cert.crt; sourceTree = ""; }; + 4C75420513D51D64008048AC /* pathLenConstraint6subsubCA11Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = pathLenConstraint6subsubCA11Cert.crt; sourceTree = ""; }; + 4C75420613D51D64008048AC /* pathLenConstraint6subsubCA41Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = pathLenConstraint6subsubCA41Cert.crt; sourceTree = ""; }; + 4C75420713D51D64008048AC /* pathLenConstraint6subsubsubCA11XCert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = pathLenConstraint6subsubsubCA11XCert.crt; sourceTree = ""; }; + 4C75420813D51D64008048AC /* pathLenConstraint6subsubsubCA41XCert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = pathLenConstraint6subsubsubCA41XCert.crt; sourceTree = ""; }; + 4C75420913D51D64008048AC /* pre2000CRLnextUpdateCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = pre2000CRLnextUpdateCACert.crt; sourceTree = ""; }; + 4C75420A13D51D64008048AC /* requireExplicitPolicy0CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy0CACert.crt; sourceTree = ""; }; + 4C75420B13D51D64008048AC /* requireExplicitPolicy0subCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy0subCACert.crt; sourceTree = ""; }; + 4C75420C13D51D64008048AC /* requireExplicitPolicy0subsubCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy0subsubCACert.crt; sourceTree = ""; }; + 4C75420D13D51D64008048AC /* requireExplicitPolicy0subsubsubCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy0subsubsubCACert.crt; sourceTree = ""; }; + 4C75420E13D51D64008048AC /* requireExplicitPolicy10CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy10CACert.crt; sourceTree = ""; }; + 4C75420F13D51D64008048AC /* requireExplicitPolicy10subCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy10subCACert.crt; sourceTree = ""; }; + 4C75421013D51D64008048AC /* requireExplicitPolicy10subsubCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy10subsubCACert.crt; sourceTree = ""; }; + 4C75421113D51D64008048AC /* requireExplicitPolicy10subsubsubCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy10subsubsubCACert.crt; sourceTree = ""; }; + 4C75421213D51D64008048AC /* requireExplicitPolicy2CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy2CACert.crt; sourceTree = ""; }; + 4C75421313D51D64008048AC /* requireExplicitPolicy2SelfIssuedCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy2SelfIssuedCACert.crt; sourceTree = ""; }; + 4C75421413D51D64008048AC /* requireExplicitPolicy2SelfIssuedsubCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy2SelfIssuedsubCACert.crt; sourceTree = ""; }; + 4C75421513D51D64008048AC /* requireExplicitPolicy2subCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy2subCACert.crt; sourceTree = ""; }; + 4C75421613D51D64008048AC /* requireExplicitPolicy4CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy4CACert.crt; sourceTree = ""; }; + 4C75421713D51D64008048AC /* requireExplicitPolicy4subCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy4subCACert.crt; sourceTree = ""; }; + 4C75421813D51D64008048AC /* requireExplicitPolicy4subsubCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy4subsubCACert.crt; sourceTree = ""; }; + 4C75421913D51D64008048AC /* requireExplicitPolicy4subsubsubCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy4subsubsubCACert.crt; sourceTree = ""; }; + 4C75421A13D51D64008048AC /* requireExplicitPolicy5CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy5CACert.crt; sourceTree = ""; }; + 4C75421B13D51D64008048AC /* requireExplicitPolicy5subCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy5subCACert.crt; sourceTree = ""; }; + 4C75421C13D51D64008048AC /* requireExplicitPolicy5subsubCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy5subsubCACert.crt; sourceTree = ""; }; + 4C75421D13D51D64008048AC /* requireExplicitPolicy5subsubsubCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy5subsubsubCACert.crt; sourceTree = ""; }; + 4C75421E13D51D64008048AC /* requireExplicitPolicy7CACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy7CACert.crt; sourceTree = ""; }; + 4C75421F13D51D64008048AC /* requireExplicitPolicy7subCARE2Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy7subCARE2Cert.crt; sourceTree = ""; }; + 4C75422013D51D64008048AC /* requireExplicitPolicy7subsubCARE2RE4Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy7subsubCARE2RE4Cert.crt; sourceTree = ""; }; + 4C75422113D51D64008048AC /* requireExplicitPolicy7subsubsubCARE2RE4Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = requireExplicitPolicy7subsubsubCARE2RE4Cert.crt; sourceTree = ""; }; + 4C7608B10AC34A8100980096 /* SecCertificatePriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCertificatePriv.h; sourceTree = ""; }; + 4C7913241799A5CB00A9633E /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; + 4C7CE56E0DC7DB0A00AE53FC /* SecEntitlements.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecEntitlements.h; sourceTree = ""; }; + 4C84DA541720698900AEE225 /* AppleAccount.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppleAccount.framework; path = System/Library/PrivateFrameworks/AppleAccount.framework; sourceTree = SDKROOT; }; + 4C84DA6217207E8D00AEE225 /* entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = ""; }; + 4C86273C1137BEF8009EAB5A /* AspenFamily.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = AspenFamily.xcconfig; path = AppleInternal/XcodeConfig/AspenFamily.xcconfig; sourceTree = DEVELOPER_DIR; }; + 4C8786A10B03E05D00BB77D4 /* libDER.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libDER.xcodeproj; path = Security/libsecurity_keychain/libDER/libDER.xcodeproj; sourceTree = ""; }; + 4C8786D90B03E1BC00BB77D4 /* libDER.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libDER.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C87F3A70D611C26000E7104 /* SecTrustPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTrustPriv.h; sourceTree = ""; }; + 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudServices.framework; path = System/Library/PrivateFrameworks/CloudServices.framework; sourceTree = SDKROOT; }; + 4C8B91C51416EB6A00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-webmail.portofamsterdam.nl.crt"; sourceTree = ""; }; + 4C8E99C20FC601D50072EB4C /* SecFrameworkStrings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecFrameworkStrings.h; sourceTree = ""; }; + 4C8FD03D099D5C91006867B6 /* SecCertificate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCertificate.h; sourceTree = ""; }; + 4C8FD03E099D5C91006867B6 /* SecTrust.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrust.h; sourceTree = ""; }; + 4C97DD160AA65A94003FC05C /* SecItemConstants.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SecItemConstants.c; sourceTree = ""; }; + 4C999BA10AB5F0BB0010451D /* NtlmGenerator.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = NtlmGenerator.c; sourceTree = ""; }; + 4C999BA20AB5F0BB0010451D /* NtlmGenerator.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = NtlmGenerator.h; sourceTree = ""; }; + 4C999BA30AB5F0BB0010451D /* ntlmBlobPriv.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ntlmBlobPriv.c; sourceTree = ""; }; + 4C999BA40AB5F0BB0010451D /* ntlmBlobPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ntlmBlobPriv.h; sourceTree = ""; }; + 4C9A19890B95118F000A1399 /* SecRSAKeyPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecRSAKeyPriv.h; sourceTree = ""; }; + 4C9DE9D21181AC4800CF5C27 /* sslEcdsa */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sslEcdsa; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C9DE9E21181AC8300CF5C27 /* sslEcdsa.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sslEcdsa.cpp; sourceTree = ""; }; + 4CA692640DA4027F001094C2 /* libCMS.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libCMS.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CA880C20DDBC87200D9A0F2 /* sslServer-entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "sslServer-entitlements.plist"; sourceTree = ""; }; + 4CA880C30DDBC87200D9A0F2 /* sslViewer-entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "sslViewer-entitlements.plist"; sourceTree = ""; }; + 4CAB97FD1114CC5300EFB38D /* README.keychain */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.keychain; sourceTree = ""; }; + 4CAC87D60B8F82720009C9FC /* SecIdentity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecIdentity.h; sourceTree = ""; }; + 4CB7405F0A47498100D641BB /* Security.exp-in */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = "Security.exp-in"; sourceTree = ""; }; + 4CB740680A4749C800D641BB /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; }; + 4CB740A30A47567C00D641BB /* security */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = security; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CBA0E860BB33C0000E72B55 /* SecPolicy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecPolicy.h; sourceTree = ""; }; + 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; + 4CC3D28F178F310B0070FCC4 /* PersistantState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PersistantState.h; sourceTree = ""; }; + 4CC3D290178F310C0070FCC4 /* PersistantState.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PersistantState.m; sourceTree = ""; }; + 4CC92ABA15A3B3D900C6D578 /* testlist.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = testlist.h; sourceTree = ""; }; + 4CC92B1B15A3BF2F00C6D578 /* testmain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testmain.c; sourceTree = ""; }; + 4CCE0AD90D41797400DDBB21 /* SecIdentityPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecIdentityPriv.h; sourceTree = ""; }; + 4CCE0AE10D417A2700DDBB21 /* sslAppUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sslAppUtils.h; sourceTree = ""; }; + 4CD3BA601106FF4D00BE8B75 /* SecECKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecECKey.h; sourceTree = ""; }; + 4CE5A54D09C796E200D27A3F /* sslViewer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sslViewer; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CE5A55709C7970A00D27A3F /* SSLViewer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SSLViewer.cpp; sourceTree = ""; }; + 4CE5A55809C7970A00D27A3F /* SSL_Sites */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = SSL_Sites; sourceTree = ""; }; + 4CE5A55909C7970A00D27A3F /* pingSslSites */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.csh; path = pingSslSites; sourceTree = ""; }; + 4CE5A55A09C7970A00D27A3F /* verifyPing */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.csh; path = verifyPing; sourceTree = ""; }; + 4CE5A65809C79E0600D27A3F /* ioSock.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ioSock.c; sourceTree = ""; }; + 4CE5A65909C79E0600D27A3F /* ioSock.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ioSock.h; sourceTree = ""; }; + 4CE5A65A09C79E0600D27A3F /* sslAppUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = sslAppUtils.cpp; sourceTree = ""; }; + 4CE5A65B09C79E0600D27A3F /* sslClient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = sslClient.cpp; sourceTree = ""; }; + 4CE5A65C09C79E0600D27A3F /* sslServe.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = sslServe.cpp; sourceTree = ""; }; + 4CE5A65D09C79E0600D27A3F /* sslThreading.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslThreading.h; sourceTree = ""; }; + 4CEDF7370F3A6CFB0027C4FE /* SecItemInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecItemInternal.h; sourceTree = ""; }; + 4CEF4CA70C5551FE00062475 /* SecCertificateInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCertificateInternal.h; sourceTree = ""; }; + 4CF0484A0A5D988F00268236 /* SecItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecItem.h; sourceTree = ""; }; + 4CF0487F0A5F016300268236 /* SecItemPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecItemPriv.h; sourceTree = ""; }; + 4CF41D0A0BBB4022005F3248 /* SecCertificatePath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCertificatePath.h; sourceTree = ""; }; + 4CF4C19C171E0EA600877419 /* Accounts.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accounts.framework; path = System/Library/Frameworks/Accounts.framework; sourceTree = SDKROOT; }; + 4CF730310EF9CDE300E17471 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 4CFBF5F10D5A92E100969BBE /* SecPolicyInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecPolicyInternal.h; sourceTree = ""; }; + 4CFFEBDD1018EE6000F33F0D /* genevroots.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; path = genevroots.rb; sourceTree = ""; }; + 5208F4BB1670027400A49DDA /* SyncViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SyncViewController.h; sourceTree = ""; }; + 5208F4BC1670027400A49DDA /* SyncViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SyncViewController.m; sourceTree = ""; }; + 5208F4CD16702D8800A49DDA /* CircleStatusView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CircleStatusView.h; sourceTree = ""; }; + 5208F4CE16702D8800A49DDA /* CircleStatusView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CircleStatusView.m; sourceTree = ""; }; + 520C98E7162485CA00A7C80B /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = /System/Library/Frameworks/QuartzCore.framework; sourceTree = ""; }; + 52222CC0167BDAE100EDD09C /* SpringBoardServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SpringBoardServices.framework; path = System/Library/PrivateFrameworks/SpringBoardServices.framework; sourceTree = SDKROOT; }; + 52222D2C16A5CBCC00EDD09C /* com.apple.security.cloudkeychainproxy.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.security.cloudkeychainproxy.plist; sourceTree = ""; }; + 5264FB4C163674B50005D258 /* MyKeychain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyKeychain.h; sourceTree = ""; }; + 5264FB4D163674B50005D258 /* MyKeychain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyKeychain.m; sourceTree = ""; }; + 52704B7D1638F4EB007FEBB0 /* KeychainKeys.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = KeychainKeys.png; sourceTree = ""; }; + 52704B7F1638F610007FEBB0 /* NewPasswordViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NewPasswordViewController.h; sourceTree = ""; }; + 52704B801638F610007FEBB0 /* NewPasswordViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = NewPasswordViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 52704B82163905EE007FEBB0 /* EditItemViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditItemViewController.h; sourceTree = ""; }; + 52704B83163905EE007FEBB0 /* EditItemViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = EditItemViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 52704B871639193F007FEBB0 /* Keychain-Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Keychain-Entitlements.plist"; sourceTree = ""; }; + 527435A916A9E6D1001A96FF /* Keychain_57x57.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Keychain_57x57.png; sourceTree = SOURCE_ROOT; }; + 527435AB16A9E6DB001A96FF /* Keychain_114x114.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Keychain_114x114.png; sourceTree = SOURCE_ROOT; }; + 527435AD16A9E6E5001A96FF /* Keychain_72x72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Keychain_72x72.png; sourceTree = SOURCE_ROOT; }; + 527435AF16A9E6E9001A96FF /* Keychain_144x144.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Keychain_144x144.png; sourceTree = SOURCE_ROOT; }; + 529990521661BA2600C297A2 /* DeviceTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeviceTableViewController.h; sourceTree = ""; }; + 529990531661BA2600C297A2 /* DeviceTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DeviceTableViewController.m; sourceTree = ""; }; + 529990551661BADF00C297A2 /* DeviceItemCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeviceItemCell.h; sourceTree = ""; }; + 529990561661BADF00C297A2 /* DeviceItemCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DeviceItemCell.m; sourceTree = ""; }; + 52A23EDB161DEC3700E271E0 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = SOURCE_ROOT; }; + 52B35B051623753000B97D06 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = ""; }; + 52CD69F916384C1F00961848 /* KCAItemDetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KCAItemDetailViewController.h; sourceTree = ""; }; + 52CD69FA16384C2000961848 /* KCAItemDetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KCAItemDetailViewController.m; sourceTree = ""; }; + 52D82BD316A5EADA0078DFE5 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 52D82BDE16A621F70078DFE5 /* CloudKeychainProxy.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CloudKeychainProxy.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; + 52D82BE216A621F70078DFE5 /* CloudKeychainProxy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "CloudKeychainProxy-Info.plist"; sourceTree = ""; }; + 52D82BE416A621F70078DFE5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 52D82BE616A621F70078DFE5 /* AspenFamily.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = AspenFamily.xcconfig; path = AppleInternal/XcodeConfig/AspenFamily.xcconfig; sourceTree = DEVELOPER_DIR; }; + 52D82BF716A6283F0078DFE5 /* ckdmain.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ckdmain.m; path = ../Security/sec/SOSCircle/CloudKeychainProxy/ckdmain.m; sourceTree = ""; }; + 52DE81691636347500F49F0C /* Keychain.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Keychain.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 52DE81701636347500F49F0C /* Keychain-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Keychain-Info.plist"; sourceTree = ""; }; + 52DE81741636347500F49F0C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 52DE81771636347600F49F0C /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 52DE81781636347600F49F0C /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 52DE817A1636347600F49F0C /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; + 52DE817C1636347600F49F0C /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; + 52DE817E1636347600F49F0C /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; + 52DE81861636347600F49F0C /* FirstViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FirstViewController.h; sourceTree = ""; }; + 52DE81871636347600F49F0C /* FirstViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FirstViewController.m; sourceTree = ""; }; + 52DE81891636347600F49F0C /* first.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = first.png; sourceTree = ""; }; + 52DE818B1636347600F49F0C /* first@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "first@2x.png"; sourceTree = ""; }; + 52DE818D1636347600F49F0C /* ToolsViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ToolsViewController.h; sourceTree = ""; }; + 52DE818E1636347600F49F0C /* ToolsViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ToolsViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 52DE81901636347600F49F0C /* second.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = second.png; sourceTree = ""; }; + 52DE81921636347600F49F0C /* second@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "second@2x.png"; sourceTree = ""; }; + 52DE819A163636B900F49F0C /* KCATableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KCATableViewController.h; sourceTree = ""; }; + 52DE819B163636B900F49F0C /* KCATableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KCATableViewController.m; sourceTree = ""; }; + 52DE819D16363C1A00F49F0C /* KeychainItemCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeychainItemCell.h; sourceTree = ""; }; + 52DE819E16363C1A00F49F0C /* KeychainItemCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KeychainItemCell.m; sourceTree = ""; }; + 52F63A1E1659F04E0076D2DE /* DeviceViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeviceViewController.h; sourceTree = ""; }; + 52F63A1F1659F04E0076D2DE /* DeviceViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DeviceViewController.m; sourceTree = ""; }; + 5346480117331E1200FE9172 /* KeychainSyncAccountNotification.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KeychainSyncAccountNotification.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; + 5346480517331E1200FE9172 /* KeychainSyncAccountNotification-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "KeychainSyncAccountNotification-Info.plist"; sourceTree = ""; }; + 5346480717331E1200FE9172 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 5346480917331E1200FE9172 /* AspenFamily.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = AspenFamily.xcconfig; path = AppleInternal/XcodeConfig/AspenFamily.xcconfig; sourceTree = DEVELOPER_DIR; }; + 5346480A17331E1200FE9172 /* KeychainSyncAccountNotification-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "KeychainSyncAccountNotification-Prefix.pch"; sourceTree = ""; }; + 5346481C173322BD00FE9172 /* KeychainSyncAccountNotification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeychainSyncAccountNotification.h; sourceTree = ""; }; + 5346481D173322BD00FE9172 /* KeychainSyncAccountNotification.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KeychainSyncAccountNotification.m; sourceTree = ""; }; + 53C0E1F2177FAC2C00F8A018 /* English */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/CloudKeychain.strings; sourceTree = ""; }; + 5D83979C160259EE0075998F /* Invalid.com.apple.testcard.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = Invalid.com.apple.testcard.crt; path = "shoebox-certs/Invalid.com.apple.testcard.crt"; sourceTree = ""; }; + 5DDD0BDD16D6740E00D6C0D6 /* com.apple.OTAPKIAssetTool.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.OTAPKIAssetTool.plist; sourceTree = ""; }; + 5DDD0BDE16D6740E00D6C0D6 /* OTAPKIAssetTool-entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "OTAPKIAssetTool-entitlements.plist"; sourceTree = ""; }; + 721146CA177A80C3005B5871 /* AppleESCertificates.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = AppleESCertificates.plist; sourceTree = ""; }; + 721680C7179B514700406BB4 /* AspenFamily.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = AspenFamily.xcconfig; path = AppleInternal/XcodeConfig/AspenFamily.xcconfig; sourceTree = DEVELOPER_DIR; }; + 721680DC179B518400406BB4 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 721680DE179B51BC00406BB4 /* com.apple.icloudKeychainStats.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.icloudKeychainStats.plist; sourceTree = ""; }; + 7245AD1D16E801BB009096D8 /* AssetVersion.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = AssetVersion.plist; sourceTree = ""; }; + 7273402816CAFB3C0096622A /* MobileAsset.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileAsset.framework; path = System/Library/PrivateFrameworks/MobileAsset.framework; sourceTree = SDKROOT; }; + 728B56A116D59979008FA3AB /* OTAPKIAssetTool */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = OTAPKIAssetTool; sourceTree = BUILT_PRODUCTS_DIR; }; + 728B56A516D59979008FA3AB /* AspenFamily.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = AspenFamily.xcconfig; path = AppleInternal/XcodeConfig/AspenFamily.xcconfig; sourceTree = DEVELOPER_DIR; }; + 72979BE2175D095900BE8FD6 /* cloud_keychain_diagnose */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = cloud_keychain_diagnose; sourceTree = BUILT_PRODUCTS_DIR; }; + 72979BE6175D095900BE8FD6 /* AspenFamily.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = AspenFamily.xcconfig; path = AppleInternal/XcodeConfig/AspenFamily.xcconfig; sourceTree = DEVELOPER_DIR; }; + 72979BEF175D0B2D00BE8FD6 /* cloud_keychain_diagnose.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cloud_keychain_diagnose.c; path = Security/utilities/src/cloud_keychain_diagnose.c; sourceTree = SOURCE_ROOT; }; + 72B368BD179891FC004C37CE /* AggregateDictionary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AggregateDictionary.framework; path = System/Library/PrivateFrameworks/AggregateDictionary.framework; sourceTree = SDKROOT; }; + 72C3EC2D1705F24E0040C87C /* ManagedConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ManagedConfiguration.framework; path = System/Library/PrivateFrameworks/ManagedConfiguration.framework; sourceTree = SDKROOT; }; + 72CD2BBB16D59AE30064EEE1 /* OTAServiceApp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OTAServiceApp.m; sourceTree = ""; }; + 72CD2BBC16D59AE30064EEE1 /* OTAServiceApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OTAServiceApp.h; sourceTree = ""; }; + 72CD2BBD16D59AE30064EEE1 /* OTAServicemain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OTAServicemain.m; sourceTree = ""; }; + 72E2DBF316BC476E00E7B236 /* Blocked.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = Blocked.plist; sourceTree = ""; }; + 72E2DBF416BC476E00E7B236 /* certsIndex.data */ = {isa = PBXFileReference; lastKnownFileType = file; path = certsIndex.data; sourceTree = ""; }; + 72E2DBF516BC476E00E7B236 /* certsTable.data */ = {isa = PBXFileReference; lastKnownFileType = file; path = certsTable.data; sourceTree = ""; }; + 72F06A8D16D4315B003C8D56 /* GrayListedKeys.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = GrayListedKeys.plist; sourceTree = ""; }; + 78F92F10195128D70023B54B /* SecECKeyPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecECKeyPriv.h; sourceTree = ""; }; + 7901790E12D51F7200CA4D44 /* SecCmsBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsBase.h; path = libsecurity_smime/lib/SecCmsBase.h; sourceTree = ""; }; + 7901790F12D51F7200CA4D44 /* SecCmsContentInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsContentInfo.h; path = libsecurity_smime/lib/SecCmsContentInfo.h; sourceTree = ""; }; + 7901791012D51F7200CA4D44 /* SecCmsDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsDecoder.h; path = libsecurity_smime/lib/SecCmsDecoder.h; sourceTree = ""; }; + 7901791112D51F7200CA4D44 /* SecCmsDigestContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsDigestContext.h; path = libsecurity_smime/lib/SecCmsDigestContext.h; sourceTree = ""; }; + 7901791212D51F7200CA4D44 /* SecCmsEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsEncoder.h; path = libsecurity_smime/lib/SecCmsEncoder.h; sourceTree = ""; }; + 7901791312D51F7200CA4D44 /* SecCmsEnvelopedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsEnvelopedData.h; path = libsecurity_smime/lib/SecCmsEnvelopedData.h; sourceTree = ""; }; + 7901791412D51F7200CA4D44 /* SecCmsMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsMessage.h; path = libsecurity_smime/lib/SecCmsMessage.h; sourceTree = ""; }; + 7901791512D51F7200CA4D44 /* SecCmsRecipientInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsRecipientInfo.h; path = libsecurity_smime/lib/SecCmsRecipientInfo.h; sourceTree = ""; }; + 7901791612D51F7200CA4D44 /* SecCmsSignedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsSignedData.h; path = libsecurity_smime/lib/SecCmsSignedData.h; sourceTree = ""; }; + 7901791712D51F7200CA4D44 /* SecCmsSignerInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsSignerInfo.h; path = libsecurity_smime/lib/SecCmsSignerInfo.h; sourceTree = ""; }; + 7901792812D51FFC00CA4D44 /* SecAsn1Types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecAsn1Types.h; path = Security/libsecurity_asn1/lib/SecAsn1Types.h; sourceTree = ""; }; + 7908507F0CA87CF00083CC4D /* client.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = client.c; sourceTree = ""; }; + 790850820CA87CF00083CC4D /* securityd_client.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = securityd_client.h; sourceTree = ""; }; + 790850830CA87CF00083CC4D /* securityd_ipc_types.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = securityd_ipc_types.h; sourceTree = ""; }; + 790850840CA87CF00083CC4D /* server.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = server.c; sourceTree = ""; }; + 790851B60CA9859F0083CC4D /* securityd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = securityd; sourceTree = BUILT_PRODUCTS_DIR; }; + 7913B1DF0D17280500601FE9 /* sslServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sslServer.cpp; sourceTree = ""; }; + 7913B2110D172B3900601FE9 /* sslServer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sslServer; sourceTree = BUILT_PRODUCTS_DIR; }; + 791766DD0DD0162C00F3B974 /* SecCertificateRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCertificateRequest.h; sourceTree = ""; }; + 7940D4110C3ACF9000FDB5D8 /* SecDH.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecDH.h; sourceTree = ""; }; + 794743191462137C00D638A3 /* Invalid-www.cybersecurity.my.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-www.cybersecurity.my.crt"; sourceTree = ""; }; + 7947431C146214E500D638A3 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Digisign-Server-ID-Enrich-GTETrust-Cert.crt"; sourceTree = ""; }; + 795CA97A0D38269B00BAE6A2 /* libsecurity_asn1.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_asn1.xcodeproj; path = Security/libsecurity_asn1/libsecurity_asn1.xcodeproj; sourceTree = ""; }; + 795CA9CC0D38435E00BAE6A2 /* p12pbegen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p12pbegen.h; sourceTree = ""; }; + 79679E251462028800CF997F /* Digisign-Server-ID-Enrich-Entrust-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Digisign-Server-ID-Enrich-Entrust-Cert.crt"; sourceTree = ""; }; + 79679E261462028800CF997F /* Invalid-webmail.jaring.my.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-webmail.jaring.my.crt"; sourceTree = ""; }; + 79863B700CADCEAB00818B0D /* com.apple.securityd.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; path = com.apple.securityd.plist; sourceTree = ""; }; + 79863B940CADD21700818B0D /* securityd_server.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = securityd_server.h; sourceTree = ""; }; + 798B7FD40D3D7B5400AC1D04 /* libASN1.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libASN1.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 79BDD3940D60D5F9000D84D3 /* libsecurity_smime.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_smime.xcodeproj; path = libsecurity_smime/libsecurity_smime.xcodeproj; sourceTree = ""; }; + 79BDD3C00D60DB84000D84D3 /* SecCMS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCMS.h; sourceTree = ""; }; + 79DCEA54134A27D2007F57DC /* codesign_wrapper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = codesign_wrapper; sourceTree = BUILT_PRODUCTS_DIR; }; + 79DCEA5E134A280F007F57DC /* codesign_wrapper.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = codesign_wrapper.c; sourceTree = ""; }; + 79DCEA5F134A280F007F57DC /* codesign.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = codesign.c; sourceTree = ""; }; + 79DCEA60134A280F007F57DC /* MISEntitlement.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = MISEntitlement.c; sourceTree = ""; }; + 79DCEA67134A2820007F57DC /* codesign.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = codesign.h; sourceTree = ""; }; + 79DCEA69134A2820007F57DC /* codesign_wrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = codesign_wrapper.h; sourceTree = ""; }; + 79DCEA6B134A2820007F57DC /* MISBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MISBase.h; sourceTree = ""; }; + 79DCEA6D134A2820007F57DC /* MISEntitlement.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MISEntitlement.h; sourceTree = ""; }; + 79E0D702143E558B0010CE0E /* Apple Application Integration Certification Authority Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Apple Application Integration Certification Authority Cert.crt"; sourceTree = ""; }; + 79E0D703143E558B0010CE0E /* Apple Production ShareServices-7130767241416543643077536561487847634e4d6f773d3d.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Apple Production ShareServices-7130767241416543643077536561487847634e4d6f773d3d.crt"; sourceTree = ""; }; + 79E0D704143E558B0010CE0E /* AppleRootCertificate.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = AppleRootCertificate.crt; sourceTree = ""; }; + 79E0D7A6143E671C0010CE0E /* Invalid-asset_signing.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-asset_signing.crt"; sourceTree = ""; }; + 79E0D7AA143E68BF0010CE0E /* iPhoneCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = iPhoneCACert.crt; sourceTree = ""; }; + 79EF5B6C0D3D6A31009F5270 /* SecImportExport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecImportExport.h; sourceTree = ""; }; + 79EF5B720D3D6AFE009F5270 /* p12import.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p12import.h; sourceTree = ""; }; + 8E02FA691107BE460043545E /* pbkdf2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pbkdf2.h; sourceTree = ""; }; + 8ED6F6C8110904E300D2B368 /* SecPBKDF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecPBKDF.h; sourceTree = ""; }; + BE061FE01899ECEE00C739F6 /* SecSharedCredential.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecSharedCredential.h; sourceTree = ""; }; + BE197F2619116FD100BA91D1 /* SharedWebCredentialViewService.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SharedWebCredentialViewService.app; sourceTree = BUILT_PRODUCTS_DIR; }; + BE197F2919116FD100BA91D1 /* SharedWebCredentialViewService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SharedWebCredentialViewService-Info.plist"; sourceTree = ""; }; + BE197F2B19116FD100BA91D1 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + BE197F2D19116FD100BA91D1 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + BE197F2F19116FD100BA91D1 /* SharedWebCredentialViewService-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SharedWebCredentialViewService-Prefix.pch"; sourceTree = ""; }; + BE197F3019116FD100BA91D1 /* SWCAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SWCAppDelegate.h; sourceTree = ""; }; + BE197F3119116FD100BA91D1 /* SWCAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SWCAppDelegate.m; sourceTree = ""; }; + BE197F3319116FD100BA91D1 /* AspenFamily.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = AspenFamily.xcconfig; path = AppleInternal/XcodeConfig/AspenFamily.xcconfig; sourceTree = DEVELOPER_DIR; }; + BE197F5A1911723E00BA91D1 /* SpringBoardUIServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SpringBoardUIServices.framework; path = System/Library/PrivateFrameworks/SpringBoardUIServices.framework; sourceTree = SDKROOT; }; + BE197F5D191173A800BA91D1 /* SWCViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SWCViewController.m; sourceTree = ""; }; + BE197F5F191173C100BA91D1 /* SWCViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SWCViewController.h; sourceTree = ""; }; + BE197F60191173F200BA91D1 /* entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = ""; }; + BE442BC118B7FDB800F24DAE /* swcagent */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = swcagent; sourceTree = BUILT_PRODUCTS_DIR; }; + BE4AC9A118B7FFAD00B84964 /* swcagent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = swcagent.m; path = Security/sec/SharedWebCredential/swcagent.m; sourceTree = ""; }; + BE4AC9AD18B7FFC800B84964 /* com.apple.security.swcagent.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = com.apple.security.swcagent.plist; path = Security/sec/SharedWebCredential/com.apple.security.swcagent.plist; sourceTree = ""; }; + BE4AC9B918B8273600B84964 /* English */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/SharedWebCredentials.strings; sourceTree = ""; }; + BE95AAFC18B846A8004495EB /* WebUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebUI.framework; path = System/Library/PrivateFrameworks/WebUI.framework; sourceTree = SDKROOT; }; + CDB9FCA9179CC757000AAD66 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + CDDE9BC31729AB910013B0E8 /* SecPasswordGenerate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecPasswordGenerate.h; sourceTree = ""; }; + E7104A0B169E171900DB0045 /* security_tool_commands.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = security_tool_commands.c; sourceTree = ""; }; + E710C7421331946400F85568 /* SecurityTests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SecurityTests.app; sourceTree = BUILT_PRODUCTS_DIR; }; + E710C74C1331946500F85568 /* SecurityTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SecurityTests-Info.plist"; sourceTree = ""; }; + E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + E72783F6159BDFBB00028D6C /* Apple TEST RootCertificate.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Apple TEST RootCertificate.crt"; path = "shoebox-certs/Apple TEST RootCertificate.crt"; sourceTree = ""; }; + E72783F7159BDFBC00028D6C /* Apple Worldwide Developer Relations Certification Authority Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Apple Worldwide Developer Relations Certification Authority Cert.crt"; path = "shoebox-certs/Apple Worldwide Developer Relations Certification Authority Cert.crt"; sourceTree = ""; }; + E72783F8159BDFBC00028D6C /* Apple Worldwide Developer Relations Certification Authority TEST Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Apple Worldwide Developer Relations Certification Authority TEST Cert.crt"; path = "shoebox-certs/Apple Worldwide Developer Relations Certification Authority TEST Cert.crt"; sourceTree = ""; }; + E72783F9159BDFBC00028D6C /* AppleRootCertificate.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = AppleRootCertificate.crt; path = "shoebox-certs/AppleRootCertificate.crt"; sourceTree = ""; }; + E73000DD13D90A1F00B0DA1B /* Invalid-asset_signing.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Invalid-asset_signing.crt"; path = "OTATasking-certs/Invalid-asset_signing.crt"; sourceTree = ""; }; + E73000DF13D90A1F00B0DA1B /* task_signing.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = task_signing.crt; path = "OTATasking-certs/task_signing.crt"; sourceTree = ""; }; + E73000F513D90CD900B0DA1B /* AppleRootCertificate.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = AppleRootCertificate.crt; path = "mobileasset-certs/AppleRootCertificate.crt"; sourceTree = ""; }; + E73000F613D90CD900B0DA1B /* asset_signing.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = asset_signing.crt; sourceTree = ""; }; + E73000F713D90CD900B0DA1B /* Invalid-task_signing.crt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Invalid-task_signing.crt"; sourceTree = ""; }; + E73000F813D90CD900B0DA1B /* iPhoneCACert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = iPhoneCACert.crt; path = "mobileasset-certs/iPhoneCACert.crt"; sourceTree = ""; }; + E7450BAC16D42B17009C07B8 /* SOSCloudCircle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SOSCloudCircle.h; path = SecureObjectSync/SOSCloudCircle.h; sourceTree = ""; }; + E7450BAD16D42B17009C07B8 /* SOSPeerInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSPeerInfo.h; path = SecureObjectSync/SOSPeerInfo.h; sourceTree = ""; }; + E75112E9166EFBF0008C578B /* PeerListCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PeerListCell.h; sourceTree = ""; }; + E75112EA166EFBF0008C578B /* PeerListCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PeerListCell.m; sourceTree = ""; }; + E7676DB519411DF300498DD4 /* SecServerEncryptionSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecServerEncryptionSupport.h; sourceTree = ""; }; + E7A94C9713D8A0DF001C5FEE /* Expectations.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expectations.plist; sourceTree = ""; }; + E7AAB5F415929493005C8BCC /* libcorecrypto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcorecrypto.dylib; path = usr/lib/system/libcorecrypto.dylib; sourceTree = SDKROOT; }; + E7B01BF2166594AB000485F1 /* SyncDevTest2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SyncDevTest2.app; sourceTree = BUILT_PRODUCTS_DIR; }; + E7D690911652E06A0079537A /* libMobileGestalt.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libMobileGestalt.dylib; path = usr/lib/libMobileGestalt.dylib; sourceTree = SDKROOT; }; + E7E4318813319C0700AF0CFD /* SecurityTests-Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "SecurityTests-Entitlements.plist"; sourceTree = ""; }; + E7FC30AB1332DE9000802946 /* MobileKeyBag.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileKeyBag.framework; path = System/Library/PrivateFrameworks/MobileKeyBag.framework; sourceTree = SDKROOT; }; + E7FCBE411314471B000DE34E /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 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 = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 0C6C630815D193C800BC68CD /* Frameworks */ = { + 0C0BDB2C175685B000BC1A7E /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 18CD682717272EBC005345FB /* libaks.a in Frameworks */, - 0CBD50DC16C32C8D00713B6C /* libutilities.a in Frameworks */, - 0CCEBDB416C2D026001BD7F6 /* libregressions.a in Frameworks */, - 52669053169D181900ED8231 /* Security.framework in Frameworks */, - 4AD6F6F91651D2A600DB4CE6 /* Foundation.framework in Frameworks */, - 0C6C633015D19FF500BC68CD /* CoreFoundation.framework in Frameworks */, - 0C6C632A15D1989900BC68CD /* libsecurity_ssl_regressions.a in Frameworks */, - 0CAA7AB516C9A72A00A32C6D /* libsecurity_keychain_regressions.a in Frameworks */, - 18CD684E17272EE2005345FB /* IOKit.framework in Frameworks */, + 0C0BDB901756A80100BC1A7E /* libsecipc_client.a in Frameworks */, + 0C0BDB8C1756A5F500BC1A7E /* libregressions.a in Frameworks */, + 0C0BDB8B1756A5D900BC1A7E /* libASN1.a in Frameworks */, + 0C0BDB8A1756A5D500BC1A7E /* libDER.a in Frameworks */, + 0C0BDB851756A4B900BC1A7E /* libsecdRegressions.a in Frameworks */, + 0C0BDB891756A56A00BC1A7E /* libsecurity.a in Frameworks */, + 0C0BDB861756A4C100BC1A7E /* libsecurityd.a in Frameworks */, + 0C0BDB8E1756A69A00BC1A7E /* libSecureObjectSync.a in Frameworks */, + 0C0BDB871756A4FA00BC1A7E /* libutilities.a in Frameworks */, + 0C0BDB8D1756A66100BC1A7E /* CFNetwork.framework in Frameworks */, + 0C0BDB921756A8AA00BC1A7E /* CoreFoundation.framework in Frameworks */, + 0C0BDB911756A8A400BC1A7E /* IOKit.framework in Frameworks */, + 0C0BDB931756A8C900BC1A7E /* SystemConfiguration.framework in Frameworks */, + 0C0BDB8F1756A6D500BC1A7E /* libMobileGestalt.dylib in Frameworks */, + 0C0BDB881756A51000BC1A7E /* libsqlite3.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 0CC3351B16C1ED8000399E53 /* Frameworks */ = { + 4C32C0AD0A4975F6002891BD /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 187A05B1170393FF0038C158 /* libaks.a in Frameworks */, - 18363C1417026084002D5C1C /* IOKit.framework in Frameworks */, - 39BFB04516D304DE0022564B /* SystemConfiguration.framework in Frameworks */, - 0CC3351E16C1ED8000399E53 /* libDER.a in Frameworks */, - 0C10987616CAAE8200803B8F /* libASN1.a in Frameworks */, - 0CC3356316C1EFBE00399E53 /* libregressions.a in Frameworks */, - 0CC3351F16C1ED8000399E53 /* libSecItemShimOSX.a in Frameworks */, - 0CC3352016C1ED8000399E53 /* libutilities.a in Frameworks */, - 0CC3351C16C1ED8000399E53 /* libsecurity.a in Frameworks */, - 0CCEBDB616C2E431001BD7F6 /* libsecurityd.a in Frameworks */, - 0CC3352616C1ED8000399E53 /* libsecipc_client.a in Frameworks */, - 0CC3352716C1ED8000399E53 /* libSecureObjectSync.a in Frameworks */, - 0CCEBDB816C2E6CE001BD7F6 /* libsqlite3.dylib in Frameworks */, - 0CC3352216C1ED8000399E53 /* libcorecrypto.dylib in Frameworks */, - 0CC3352116C1ED8000399E53 /* Foundation.framework in Frameworks */, - 0CC3352416C1ED8000399E53 /* CoreFoundation.framework in Frameworks */, - 0CCEBDB716C2E6B0001BD7F6 /* CFNetwork.framework in Frameworks */, - 0CC3352316C1ED8000399E53 /* libSOSRegressions.a in Frameworks */, - 0CCEBDBB16C30924001BD7F6 /* libutilitiesRegressions.a in Frameworks */, - 0C4EAE7717668DDF00773425 /* libsecdRegressions.a in Frameworks */, + E7B01B7716572123000485F1 /* libSecureObjectSync.a in Frameworks */, + 5296CB4E1655B8F5009912AF /* libMobileGestalt.dylib in Frameworks */, + 0C78F1D016A5E3EB00654E08 /* libbsm.dylib in Frameworks */, + 0C15009B161D020000181E9D /* libASN1.a in Frameworks */, + 0C15009A161D01F400181E9D /* libCMS.a in Frameworks */, + 0C150099161D01D700181E9D /* libDER.a in Frameworks */, + 0CCA408015C745B9002AEC4C /* libsecurity_ssl.a in Frameworks */, + 18F7F66F14D77EA400F88A12 /* libsecipc_client.a in Frameworks */, + 18F7F66E14D77E9700F88A12 /* libsecurity.a in Frameworks */, + E76079DC1951FDBF00F69731 /* liblogging.a in Frameworks */, + 4C2FEC5215755D8C0008BE39 /* libutilities.a in Frameworks */, + 4C32C1680A4976D5002891BD /* CoreFoundation.framework in Frameworks */, + 4CAF67AC0F3A70220064A534 /* IOKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 18073847146D0D4E00F05C24 /* Frameworks */ = { + 4C52D0B116EFC61E0079966E /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 5241C60D16DC1BA100DB5C6F /* libSecOtrOSX.a in Frameworks */, - 5208C0D716A0C96F0062DDC5 /* libSecureObjectSync.a in Frameworks */, - 52146FDB1697673900DF0DB3 /* libutilities.a in Frameworks */, - 4C8313C914F5A26500DF7FDC /* libcorecrypto.dylib in Frameworks */, - 1885B45214D9AB8100519375 /* libASN1.a in Frameworks */, - 18270F6114CF656E00B05E7F /* libsecipc_client.a in Frameworks */, - 18AD56A414CDE7BE008233F2 /* libSecItemShimOSX.a in Frameworks */, - 182BB5BA146FF0BF000BF1F3 /* libbsm.dylib in Frameworks */, - 182BB5B8146FF0A2000BF1F3 /* libobjc.dylib in Frameworks */, - 182BB5B6146FF090000BF1F3 /* libauto.dylib in Frameworks */, - 182BB5B4146FF04C000BF1F3 /* libxar.dylib in Frameworks */, - 182BB5B2146FF039000BF1F3 /* libz.dylib in Frameworks */, - 182BB5AE146FEF43000BF1F3 /* libsqlite3.dylib in Frameworks */, - 182BB5AC146FEF15000BF1F3 /* libpam.dylib in Frameworks */, - 182BB5AA146FEE50000BF1F3 /* CoreFoundation.framework in Frameworks */, - 182BB4E1146F2591000BF1F3 /* libsecurity_manifest.a in Frameworks */, - 182BB4E2146F2591000BF1F3 /* libsecurity_mds.a in Frameworks */, - 182BB4E3146F2591000BF1F3 /* libsecurity_sd_cspdl.a in Frameworks */, - 182BB4E4146F2591000BF1F3 /* libsecurity_smime.a in Frameworks */, - 182BB4E5146F2591000BF1F3 /* libsecurity_ssl.a in Frameworks */, - 182BB41B146F2533000BF1F3 /* libsecurity_apple_csp.a in Frameworks */, - 182BB41C146F2533000BF1F3 /* libsecurity_apple_cspdl.a in Frameworks */, - 182BB41D146F2533000BF1F3 /* libsecurity_apple_file_dl.a in Frameworks */, - 182BB41E146F2533000BF1F3 /* libsecurity_apple_x509_cl.a in Frameworks */, - 182BB41F146F2533000BF1F3 /* libsecurity_apple_x509_tp.a in Frameworks */, - 182BB421146F2533000BF1F3 /* libsecurity_authorization.a in Frameworks */, - 182BB422146F2533000BF1F3 /* libsecurity_cdsa_client.a in Frameworks */, - 182BB423146F2533000BF1F3 /* libsecurity_cdsa_utilities.a in Frameworks */, - 182BB424146F2533000BF1F3 /* libsecurity_checkpw.a in Frameworks */, - 182BB425146F2533000BF1F3 /* libsecurity_cms.a in Frameworks */, - 182BB5BB146FF62F000BF1F3 /* libsecurity_comcryption.a in Frameworks */, - 182BB426146F2533000BF1F3 /* libsecurity_codesigning.a in Frameworks */, - 182BB428146F2533000BF1F3 /* libsecurity_cryptkit.a in Frameworks */, - 182BB429146F2533000BF1F3 /* libsecurity_filedb.a in Frameworks */, - 182BB42A146F2533000BF1F3 /* libsecurity_keychain.a in Frameworks */, - 182BB42B146F2533000BF1F3 /* libsecurity_ocspd.a in Frameworks */, - 182BB42C146F2533000BF1F3 /* libsecurity_pkcs12.a in Frameworks */, - 182BB42D146F2533000BF1F3 /* libsecurity_transform.a in Frameworks */, - 182BB42E146F2533000BF1F3 /* libsecurityd_client.a in Frameworks */, - 18446083146DF58B00B12992 /* libsecurity_cdsa_plugin.a in Frameworks */, - 1879B571146DE2FF007E536C /* libsecurity_cssm.a in Frameworks */, - 1879B546146DE192007E536C /* libsecurity_utilities.a in Frameworks */, - 1879B570146DE2E6007E536C /* libsecurity_cdsa_utils.a in Frameworks */, - C288A0891505796F00E773B7 /* libOpenScriptingUtil.dylib in Frameworks */, - 4CC8DEA416DC1AC800462517 /* libSecOtrOSX.a in Frameworks */, + 4C8A38C917B93DF10001B4C0 /* CloudServices.framework in Frameworks */, + 4C7913251799A5CC00A9633E /* MobileCoreServices.framework in Frameworks */, + 4C3DD6BD179760280093F9D8 /* libMobileGestalt.dylib in Frameworks */, + 533B5D4F177CD63100995334 /* SpringBoardServices.framework in Frameworks */, + 7200D76F177B9999009BB396 /* ManagedConfiguration.framework in Frameworks */, + 4C84DA551720698900AEE225 /* AppleAccount.framework in Frameworks */, + 4CF4C19D171E0EA600877419 /* Accounts.framework in Frameworks */, + 4C52D0EC16EFCD300079966E /* Security.framework in Frameworks */, + 4C52D0EB16EFCD150079966E /* CoreFoundation.framework in Frameworks */, + 4C52D0B516EFC61E0079966E /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 18270ED314CF282600B05E7F /* Frameworks */ = { + 4C711D6513AFCD0900FE865D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 189757871700CF4C00672567 /* libaks.a in Frameworks */, - 395E7CEE16C64EA500CD82A4 /* SystemConfiguration.framework in Frameworks */, - 5208BF4F16A0993C0062DDC5 /* libsecurity.a in Frameworks */, - AAF3DCCB1666D03300376593 /* libsecurity_utilities.a in Frameworks */, - 4C7D8765160A74C400D041E3 /* libutilities.a in Frameworks */, - 18F2360115CAF41200060520 /* libsecurity_codesigning.a in Frameworks */, - 1831329B14EB2C6D00F0BCAC /* libASN1.a in Frameworks */, - 1831329C14EB2C6D00F0BCAC /* libDER.a in Frameworks */, - 18270F0014CF42CA00B05E7F /* libcorecrypto.a in Frameworks */, - 18270EFE14CF429600B05E7F /* IOKit.framework in Frameworks */, - 18270EFA14CF426200B05E7F /* libsqlite3.dylib in Frameworks */, - 18270EF914CF425100B05E7F /* libbsm.dylib in Frameworks */, - 18270EE814CF294500B05E7F /* libsecurityd.a in Frameworks */, - 4C01DF14164C3E7C006798CD /* libSecureObjectSync.a in Frameworks */, - 4C8D8651177A752D0019A804 /* libsecipc_client.a in Frameworks */, - 18270EF814CF424900B05E7F /* CoreFoundation.framework in Frameworks */, - 18270EFC14CF427800B05E7F /* CFNetwork.framework in Frameworks */, + E7D690A11652E07B0079537A /* libMobileGestalt.dylib in Frameworks */, + 0CCA418715C89FBB002AEC4C /* libsecurity_ssl_regressions.a in Frameworks */, + 18F7F67814D77F0600F88A12 /* libsecurityd.a in Frameworks */, + 4C2FEC671575887D0008BE39 /* libSecureObjectSync.a in Frameworks */, + 4C711D6913AFCD0900FE865D /* libASN1.a in Frameworks */, + 4C711D6713AFCD0900FE865D /* libDER.a in Frameworks */, + 4C2FEC5B15755E2F0008BE39 /* libutilities.a in Frameworks */, + 4C711D7113AFCD0900FE865D /* libregressions.a in Frameworks */, + E7E0D902158FAFED002CA176 /* libutilitiesRegressions.a in Frameworks */, + 4ACED92D15A10A320060775A /* libSecurityRegressions.a in Frameworks */, + 4CC92B3115A3C99600C6D578 /* libsecuritydRegressions.a in Frameworks */, + 4C2FEC5D157571DD0008BE39 /* libSOSRegressions.a in Frameworks */, + 4C711D6C13AFCD0900FE865D /* libsqlite3.dylib in Frameworks */, + 4C711D6E13AFCD0900FE865D /* CoreFoundation.framework in Frameworks */, + 4C711D6F13AFCD0900FE865D /* CFNetwork.framework in Frameworks */, + 4C711D7013AFCD0900FE865D /* IOKit.framework in Frameworks */, + E7A011AF14E1B78C00765C29 /* Foundation.framework in Frameworks */, + 4C711D6D13AFCD0900FE865D /* Security.framework in Frameworks */, + E71F3E4216EA6A6300FAF9B4 /* SystemConfiguration.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 182BB565146F4DCA000BF1F3 /* Frameworks */ = { + 4C9DE9D01181AC4800CF5C27 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 182BB592146FE1D7000BF1F3 /* CoreFoundation.framework in Frameworks */, - 182BB591146FE12F000BF1F3 /* libsecurity_utilities.a in Frameworks */, - 182BB590146FE125000BF1F3 /* libsecurity_cdsa_utilities.a in Frameworks */, - 182BB589146FE013000BF1F3 /* libsecurity_codesigning.a in Frameworks */, - 529E948D169E29470000AC9B /* Security.framework in Frameworks */, + 5296CB521655B9B5009912AF /* libMobileGestalt.dylib in Frameworks */, + 4C2FEC5715755E040008BE39 /* libutilities.a in Frameworks */, + 4C9DEA451181B34C00CF5C27 /* Security.framework in Frameworks */, + E71F3E4016EA6A1800FAF9B4 /* SystemConfiguration.framework in Frameworks */, + 4C9DEA6C1181B35700CF5C27 /* CoreFoundation.framework in Frameworks */, + 4C9DEAA71181B37500CF5C27 /* CFNetwork.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 18F234E815C9F9A600060520 /* Frameworks */ = { + 4CB740A10A47567C00D641BB /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 18F2353815C9FDEF00060520 /* libsqlite3.dylib in Frameworks */, - 18F2353715C9FDE400060520 /* libbsm.dylib in Frameworks */, - 18F2353615C9FDD200060520 /* Security.framework in Frameworks */, - 18F2353515C9FDB700060520 /* CoreFoundation.framework in Frameworks */, - 187D6B9815D4476D00E27494 /* IOKit.framework in Frameworks */, + E7FEFB94169E378500E18152 /* libSOSCommands.a in Frameworks */, + E7104A07169E03CE00DB0045 /* libSecurityTool.a in Frameworks */, + E7104A24169E222F00DB0045 /* libSecurityCommands.a in Frameworks */, + 5296CB4F1655B92F009912AF /* libMobileGestalt.dylib in Frameworks */, + 4C2FEC5415755DCD0008BE39 /* libutilities.a in Frameworks */, + 4C32C1A60A497A21002891BD /* Security.framework in Frameworks */, + 4C2318BD0A48B5AD00792B82 /* CoreFoundation.framework in Frameworks */, + 4CAE95DC0F3D6E020075278E /* CFNetwork.framework in Frameworks */, + 4C0CC642174C580200CC799A /* SystemConfiguration.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 37A7CEA8197DB8FA00926CE8 /* Frameworks */ = { + 4CE5A54B09C796E100D27A3F /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 5296CB511655B9A3009912AF /* libMobileGestalt.dylib in Frameworks */, + 4C2FEC5615755DF40008BE39 /* libutilities.a in Frameworks */, + 4CE39045169F87E500026468 /* libSecurityTool.a in Frameworks */, + 4C32C1990A497A0C002891BD /* Security.framework in Frameworks */, + E71F3E3F16EA69E500FAF9B4 /* SystemConfiguration.framework in Frameworks */, + 4CE5A60E09C79DF200D27A3F /* CoreFoundation.framework in Frameworks */, + 4CAE95AA0F3D6DF20075278E /* CFNetwork.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 4C96F7BE16D6DF8300D3B39D /* Frameworks */ = { + 52D82BDB16A621F70078DFE5 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 4C97761E17BEB23E0002BFE4 /* AOSAccounts.framework in Frameworks */, - 4C5DD46C17A5F67300696A79 /* AppleSystemInfo.framework in Frameworks */, - 4C328D301778EC4F0015EED1 /* AOSUI.framework in Frameworks */, - 4CAEACCD16D6FC7600263776 /* Security.framework in Frameworks */, - 4C96F7C216D6DF8400D3B39D /* Cocoa.framework in Frameworks */, + 52D82BF016A622570078DFE5 /* libutilities.a in Frameworks */, + 52D82BEF16A622470078DFE5 /* libCloudKeychainProxy.a in Frameworks */, + 52D82BEE16A622370078DFE5 /* Security.framework in Frameworks */, + 52D82BDF16A621F70078DFE5 /* Foundation.framework in Frameworks */, + E72D462B175FBF3E00F70B9B /* IOKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 4CB23B43169F5873003A0131 /* Frameworks */ = { + 52DE81661636347500F49F0C /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 52CD052316A0E24900218387 /* Security.framework in Frameworks */, - 4CB23B8C169F59AD003A0131 /* libutilities.a in Frameworks */, - 4CB23B8A169F599A003A0131 /* libSecurityCommands.a in Frameworks */, - 4CB23B8B169F599A003A0131 /* libSOSCommands.a in Frameworks */, - 52CD052416A0E2A000218387 /* libcorecrypto.dylib in Frameworks */, - 4CB23B89169F5990003A0131 /* libSecurityTool.a in Frameworks */, - 4CB23B47169F5873003A0131 /* CoreFoundation.framework in Frameworks */, + 5233636418CA9B8900333A5C /* SystemConfiguration.framework in Frameworks */, + 5233636318CA9B3C00333A5C /* libSecureObjectSync.a in Frameworks */, + 5233635818CA9B2600333A5C /* libsecurityd.a in Frameworks */, + 52222CC1167BDAE100EDD09C /* SpringBoardServices.framework in Frameworks */, + 5296CBAC1656A7E9009912AF /* CFNetwork.framework in Frameworks */, + 5296CBAB1656A7E2009912AF /* IOKit.framework in Frameworks */, + 5296CBAA1656A7AC009912AF /* libsqlite3.dylib in Frameworks */, + 5223A7E416560CFB00804179 /* CoreFoundation.framework in Frameworks */, + 5223A7E316560CE400804179 /* libMobileGestalt.dylib in Frameworks */, + 5264FB52163675310005D258 /* libutilities.a in Frameworks */, + 52DE816B1636347500F49F0C /* UIKit.framework in Frameworks */, + 52DE816C1636347500F49F0C /* Foundation.framework in Frameworks */, + 52DE816D1636347500F49F0C /* CoreGraphics.framework in Frameworks */, + 5264FB4F163674C00005D258 /* QuartzCore.framework in Frameworks */, + 5264FB50163674CF0005D258 /* Security.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 4CC7A7B016CC2A84003E10C1 /* Frameworks */ = { + 534647FE17331E1100FE9172 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 4CC7A7F316CC2B0A003E10C1 /* Security.framework in Frameworks */, - 4CC7A7B416CC2A85003E10C1 /* Cocoa.framework in Frameworks */, - 4C96F76216D54C9600D3B39D /* CoreFoundation.framework in Frameworks */, + 5328C0521738903F00708984 /* Security.framework in Frameworks */, + 5346481F17332F9C00FE9172 /* Accounts.framework in Frameworks */, + 5346480217331E1200FE9172 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 5214700316977CB800DF0DB3 /* Frameworks */ = { + 728B569E16D59979008FA3AB /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 5214702A1697855800DF0DB3 /* Foundation.framework in Frameworks */, - 5214701E16977DA700DF0DB3 /* libCloudKeychainProxy.a in Frameworks */, - 5214701D16977D9500DF0DB3 /* libutilities.a in Frameworks */, - 529E948C169E29450000AC9B /* Security.framework in Frameworks */, - 0C4EAE4C1766864F00773425 /* libaks.a in Frameworks */, - 0C4EAE761766875E00773425 /* IOKit.framework in Frameworks */, + 72DF9EFE178360230054641E /* libMobileGestalt.dylib in Frameworks */, + 72C3EC2E1705F24E0040C87C /* ManagedConfiguration.framework in Frameworks */, + 72CD2BCE16D59B010064EEE1 /* MobileAsset.framework in Frameworks */, + 72CD2BCD16D59AF30064EEE1 /* Security.framework in Frameworks */, + 728B56A216D59979008FA3AB /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 721680A2179B40F600406BB4 /* Frameworks */ = { + 72979BDF175D095900BE8FD6 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 721680AF179B4C3200406BB4 /* Security.framework in Frameworks */, - 721680A6179B40F600406BB4 /* CoreFoundation.framework in Frameworks */, + 72979BF2175D0D4F00BE8FD6 /* IOKit.framework in Frameworks */, + 72979BF1175D0B5900BE8FD6 /* Security.framework in Frameworks */, + 72979BE3175D095900BE8FD6 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 72756BFB175D485D00F52070 /* Frameworks */ = { + 790851B40CA9859F0083CC4D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 72CC327C175D6E1800217455 /* Security.framework in Frameworks */, - 72CC327B175D6E0A00217455 /* CoreFoundation.framework in Frameworks */, + E7D690A21652E0870079537A /* libMobileGestalt.dylib in Frameworks */, + 18F7F67214D77ED000F88A12 /* libsecurityd.a in Frameworks */, + 4C1ADEAA1615175500E4A8AF /* libSecureObjectSync.a in Frameworks */, + BE5EC1E318C7F66D005E7682 /* libSWCAgent.a in Frameworks */, + 4C2FEC5315755DAB0008BE39 /* libutilities.a in Frameworks */, + 790851EE0CA9B3410083CC4D /* Security.framework in Frameworks */, + E71F3E3116EA69A900FAF9B4 /* SystemConfiguration.framework in Frameworks */, + 790851EF0CA9B3410083CC4D /* CoreFoundation.framework in Frameworks */, + 4CF730320EF9CDE300E17471 /* CFNetwork.framework in Frameworks */, + 4CAF66190F3A6FCD0064A534 /* IOKit.framework in Frameworks */, + 4C2215220F3A612C00835155 /* libsqlite3.dylib in Frameworks */, + 4C70664C0DDDFED9004DA56B /* libbsm.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 0C6C630D15D193C800BC68CD /* sectests */ = { - isa = PBXGroup; - children = ( - 18ED4D2317270DB6003AF11B /* SecurityTests-Entitlements.plist */, - 0C6C630E15D193C800BC68CD /* main.c */, - 0C6C632415D1964200BC68CD /* testlist.h */, + 7913B2060D172B3900601FE9 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4CE39035169F87BB00026468 /* libSecurityTool.a in Frameworks */, + 5296CB501655B990009912AF /* libMobileGestalt.dylib in Frameworks */, + 4C2FEC5515755DE50008BE39 /* libutilities.a in Frameworks */, + 7913B2080D172B3900601FE9 /* Security.framework in Frameworks */, + E71F3E3E16EA69CF00FAF9B4 /* SystemConfiguration.framework in Frameworks */, + 7913B2090D172B3900601FE9 /* CoreFoundation.framework in Frameworks */, + 4CAE95D80F3D6DFC0075278E /* CFNetwork.framework in Frameworks */, ); - path = sectests; - sourceTree = ""; + runOnlyForDeploymentPostprocessing = 0; }; - 0C6D0063177B54A70095D167 /* asl */ = { - isa = PBXGroup; - children = ( - 0C6D0064177B54C60095D167 /* com.apple.securityd */, + 79DCEA51134A27D2007F57DC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 79DCEA87134A2A1B007F57DC /* libDER.a in Frameworks */, + 7930B058134A2D97007062F8 /* libsqlite3.dylib in Frameworks */, + 79DCEA8B134A2A1B007F57DC /* CoreFoundation.framework in Frameworks */, + 79C0C675134A6E2D00A51BCB /* IOKit.framework in Frameworks */, + 79C0C6BC134A96C100A51BCB /* CFNetwork.framework in Frameworks */, ); - name = asl; - path = lib; - sourceTree = ""; + runOnlyForDeploymentPostprocessing = 0; }; - 0C6D77DF15C8C06500BB4405 /* Products */ = { - isa = PBXGroup; - children = ( - 0C6D77E915C8C06600BB4405 /* tlsnke.kext */, - 0C6D77EB15C8C06600BB4405 /* tlsnketest */, - 0C6D77ED15C8C06600BB4405 /* libtlssocket.a */, + BE197F2319116FD100BA91D1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + BE2D511D1917739F0093C265 /* libutilities.a in Frameworks */, + BEF8AFF819176B1400F80109 /* libSWCAgent.a in Frameworks */, + BEF8AFF719176B0C00F80109 /* libsecurityd.a in Frameworks */, + BE197F5B1911723E00BA91D1 /* SpringBoardUIServices.framework in Frameworks */, + BE197F5C1911724900BA91D1 /* UIKit.framework in Frameworks */, + BE759DCB1917E38D00801E02 /* CoreGraphics.framework in Frameworks */, ); - name = Products; - sourceTree = ""; + runOnlyForDeploymentPostprocessing = 0; }; - 0C6D77EE15C8C07C00BB4405 /* tlsnke */ = { - isa = PBXGroup; - children = ( - 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */, + BE442BAD18B7FDB800F24DAE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + BE442BAE18B7FDB800F24DAE /* libMobileGestalt.dylib in Frameworks */, + BE4AC9B718B80CFF00B84964 /* libSWCAgent.a in Frameworks */, + BE442BB218B7FDB800F24DAE /* libutilities.a in Frameworks */, + BE442BB318B7FDB800F24DAE /* Security.framework in Frameworks */, + BE442BB418B7FDB800F24DAE /* SystemConfiguration.framework in Frameworks */, + BE442BB518B7FDB800F24DAE /* CoreFoundation.framework in Frameworks */, + BE442BB618B7FDB800F24DAE /* CFNetwork.framework in Frameworks */, + BE25C41618B83491003320E0 /* Foundation.framework in Frameworks */, + BE95AAFD18B846A8004495EB /* WebUI.framework in Frameworks */, + BE442BB718B7FDB800F24DAE /* IOKit.framework in Frameworks */, + BE442BB818B7FDB800F24DAE /* libsqlite3.dylib in Frameworks */, + BE442BB918B7FDB800F24DAE /* libbsm.dylib in Frameworks */, ); - name = tlsnke; - sourceTree = ""; + runOnlyForDeploymentPostprocessing = 0; }; - 0CC3355516C1EEAD00399E53 /* secdtests */ = { - isa = PBXGroup; - children = ( - 0CC3355716C1EEE700399E53 /* main.c */, - 0CC3355816C1EEE700399E53 /* testlist.h */, + E710C73F1331946400F85568 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E7D690921652E06A0079537A /* libMobileGestalt.dylib in Frameworks */, + 0CCA418815C89FC4002AEC4C /* libsecurity_ssl_regressions.a in Frameworks */, + 18F7F67514D77EF400F88A12 /* libsecurityd.a in Frameworks */, + 4C2FEC66157588770008BE39 /* libSecureObjectSync.a in Frameworks */, + 0CC827F51387137900BD99B7 /* libASN1.a in Frameworks */, + B9499C24139DC391004F4EDE /* libDER.a in Frameworks */, + 4C2FEC5A15755E2A0008BE39 /* libutilities.a in Frameworks */, + 0CC82948138716F400BD99B7 /* libregressions.a in Frameworks */, + E7E0D903158FAFF7002CA176 /* libutilitiesRegressions.a in Frameworks */, + 4CC92B2615A3C6FE00C6D578 /* libSecurityRegressions.a in Frameworks */, + 4CC92B2715A3C73E00C6D578 /* libsecuritydRegressions.a in Frameworks */, + 4C2FEC5E157571E30008BE39 /* libSOSRegressions.a in Frameworks */, + E7FEEEF81332B7F70025EB06 /* libsqlite3.dylib in Frameworks */, + E7FEEEF91332B80A0025EB06 /* CoreFoundation.framework 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 */, ); - name = secdtests; - sourceTree = ""; + runOnlyForDeploymentPostprocessing = 0; + }; + E7B01BD1166594AB000485F1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 52222CD0167BDAEC00EDD09C /* SpringBoardServices.framework in Frameworks */, + E7B01BD2166594AB000485F1 /* CFNetwork.framework in Frameworks */, + E7B01BD3166594AB000485F1 /* IOKit.framework in Frameworks */, + E7B01BD4166594AB000485F1 /* libsqlite3.dylib in Frameworks */, + E7B01BD5166594AB000485F1 /* CoreFoundation.framework in Frameworks */, + E7B01BD6166594AB000485F1 /* libMobileGestalt.dylib in Frameworks */, + E7B01BD7166594AB000485F1 /* libsecurityd.a in Frameworks */, + E7B01BD9166594AB000485F1 /* libSOSRegressions.a in Frameworks */, + E7B01BDA166594AB000485F1 /* libutilitiesRegressions.a in Frameworks */, + E7B01BDB166594AB000485F1 /* libSecureObjectSync.a in Frameworks */, + E7B01BDC166594AB000485F1 /* libregressions.a in Frameworks */, + E7B01BDD166594AB000485F1 /* libutilities.a in Frameworks */, + E7B01BDE166594AB000485F1 /* UIKit.framework in Frameworks */, + E7B01BDF166594AB000485F1 /* Foundation.framework in Frameworks */, + E7B01BE0166594AB000485F1 /* CoreGraphics.framework in Frameworks */, + E7B01BE1166594AB000485F1 /* QuartzCore.framework in Frameworks */, + E7B01BE2166594AB000485F1 /* Security.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; }; - 0CC3355C16C1EF5D00399E53 /* Products */ = { +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 051D8F83194913E500AEF66A /* Products */ = { isa = PBXGroup; children = ( - 0CC3356016C1EF5D00399E53 /* libregressions.a */, + 051D8FD7194913E700AEF66A /* Security.framework */, + 051D8FD9194913E700AEF66A /* csparser.bundle */, + 051D8FDB194913E700AEF66A /* Security.framework */, + 051D8FDD194913E700AEF66A /* secd */, + 051D8FDF194913E700AEF66A /* secdtests */, + 051D8FE1194913E700AEF66A /* sectests */, + 051D8FE3194913E700AEF66A /* authd.xpc */, + 051D8FE5194913E700AEF66A /* CloudKeychainProxy.bundle */, + 051D8FE7194913E700AEF66A /* security2 */, + 051D8FE9194913E700AEF66A /* Cloud Keychain Utility.app */, + 051D8FEB194913E700AEF66A /* Keychain Circle Notification.app */, + 051D8FED194913E700AEF66A /* cloud_keychain_diagnose */, ); name = Products; sourceTree = ""; }; - 1807383F146D0D4E00F05C24 = { + 05EF68801949143A007958C3 /* Products */ = { isa = PBXGroup; children = ( - 0C6D0063177B54A70095D167 /* asl */, - 4C1288F615FFECF2008CE3E3 /* utilities */, - 18073854146D0D4E00F05C24 /* lib */, - 181EA3D0146D1ED200A6D320 /* libsecurity */, - 186CDD0314CA10E700AF9171 /* sec */, - 186CDE7914CA3A3800AF9171 /* secd */, - 0C6D77EE15C8C07C00BB4405 /* tlsnke */, - 181EA421146D4A2A00A6D320 /* config */, - 0CC3355516C1EEAD00399E53 /* secdtests */, - 0C6C630D15D193C800BC68CD /* sectests */, - 18F234ED15C9F9A700060520 /* authd */, - 5214700D16977CB800DF0DB3 /* CloudKeychainProxy */, - 4CB23B48169F5873003A0131 /* security2 */, - 4CC7A7B516CC2A85003E10C1 /* KeychainDemoApp */, - 4C96F7C316D6DF8400D3B39D /* Keychain Circle Notification */, - 72756C00175D485D00F52070 /* cloud_keychain_diagnose */, - 721680A7179B40F600406BB4 /* iCloudStats */, - 37A7CEAC197DB8FA00926CE8 /* codesign_tests */, - 1807384D146D0D4E00F05C24 /* Frameworks */, - 1807384C146D0D4E00F05C24 /* Products */, + 05EF68A51949143A007958C3 /* securityd */, ); + name = Products; sourceTree = ""; }; - 1807384C146D0D4E00F05C24 /* Products */ = { + 05EF68AA19491453007958C3 /* Products */ = { isa = PBXGroup; children = ( - 1807384B146D0D4E00F05C24 /* Security.framework */, - 182BB568146F4DCA000BF1F3 /* csparser.bundle */, - 18FE67EA1471A3AA00A2CBE3 /* Security.framework */, - 18270ED614CF282600B05E7F /* secd */, - 0C6C630B15D193C800BC68CD /* sectests */, - 18F234EB15C9F9A600060520 /* authd.xpc */, - 5214700616977CB800DF0DB3 /* CloudKeychainProxy.bundle */, - 4CB23B46169F5873003A0131 /* security2 */, - 0CC3352D16C1ED8000399E53 /* secdtests */, - 4CC7A7B316CC2A84003E10C1 /* Cloud Keychain Utility.app */, - 4C96F7C116D6DF8300D3B39D /* Keychain Circle Notification.app */, - 72756BFE175D485D00F52070 /* cloud_keychain_diagnose */, - 721680A5179B40F600406BB4 /* iCloudStats */, - 37A7CEAB197DB8FA00926CE8 /* codesign_tests */, + 05EF68AE19491453007958C3 /* security */, ); name = Products; sourceTree = ""; }; - 1807384D146D0D4E00F05C24 /* Frameworks */ = { + 0C0BDB30175685B000BC1A7E /* secdtests */ = { isa = PBXGroup; children = ( - 4C97761D17BEB23E0002BFE4 /* AOSAccounts.framework */, - 4C5DD46B17A5F67300696A79 /* AppleSystemInfo.framework */, - 72A3DE5B179B2C0400E78247 /* Foundation.framework */, - 4C328D2F1778EC4F0015EED1 /* AOSUI.framework */, - 722CF215175D5E5000BCE0A5 /* Security.framework */, - 72756C9E175D566800F52070 /* CoreFoundation.framework */, - 72756C9C175D51C900F52070 /* Kernel.framework */, - 72756C9A175D51B100F52070 /* IOKit.framework */, - 18752C1D16F2837A004E2799 /* libaks.a */, - 4C96F76116D54C9600D3B39D /* CoreFoundation.framework */, - 4CC7A7F216CC2B0A003E10C1 /* Security.framework */, - 395E7CED16C64EA500CD82A4 /* SystemConfiguration.framework */, - 18F2360015CAF41100060520 /* libsecurity_codesigning.a */, - 18F235FC15CA0EDB00060520 /* libstdc++.6.0.9.dylib */, - 18F235F915CA0DB000060520 /* libsecurity_agent_client.a */, - 18F235F715CA0D9D00060520 /* libsecurity_utilities.a */, - 18F235F515CA0D8100060520 /* libsecurity_cdsa_utilities.a */, - 4CF42BB515A3947F00ACACE1 /* Security.framework */, - 1831329914EB2C6D00F0BCAC /* libASN1.a */, - 1831329A14EB2C6D00F0BCAC /* libDER.a */, - 18270EFF14CF42CA00B05E7F /* libcorecrypto.a */, - 4C8313C814F5A26500DF7FDC /* libcorecrypto.dylib */, - 18270EFD14CF429600B05E7F /* IOKit.framework */, - 18270EFB14CF427800B05E7F /* CFNetwork.framework */, - 182BB5B9146FF0BE000BF1F3 /* libbsm.dylib */, - 182BB5B7146FF0A1000BF1F3 /* libobjc.dylib */, - 182BB5B5146FF08F000BF1F3 /* libauto.dylib */, - 182BB5B3146FF04C000BF1F3 /* libxar.dylib */, - 182BB5B1146FF039000BF1F3 /* libz.dylib */, - 182BB5AD146FEF43000BF1F3 /* libsqlite3.dylib */, - 182BB5AB146FEF14000BF1F3 /* libpam.dylib */, - 182BB593146FE1ED000BF1F3 /* libantlr2c++.a */, - C288A0881505795D00E773B7 /* libOpenScriptingUtil.dylib */, - 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */, - 4CF42B8F159E674D00ACACE1 /* Foundation.framework */, - 5214700716977CB800DF0DB3 /* Cocoa.framework */, - 5214700916977CB800DF0DB3 /* Other Frameworks */, + 0C664AB2175926B20092D3D9 /* secdtests-entitlements.plist */, + 0C0BDB31175685B000BC1A7E /* main.c */, + 0C0BDB441756868B00BC1A7E /* testlist.h */, ); - name = Frameworks; + path = secdtests; sourceTree = ""; }; - 18073854146D0D4E00F05C24 /* lib */ = { + 0C25A872122726540050C2BD /* Products */ = { isa = PBXGroup; children = ( - 1879B4A6146DC971007E536C /* Headers */, - 1879B4A7146DC999007E536C /* PrivateHeaders */, - 182BB228146F0674000BF1F3 /* Resources */, - 18073855146D0D4E00F05C24 /* Supporting Files */, - 182BB555146F450F000BF1F3 /* plugins */, - 182BB5A9146FEB27000BF1F3 /* derived_src */, - 18A5493115EFD2F40059E6DC /* dummy.cpp */, - ); - path = lib; + E710C708133192EA00F85568 /* libregressions.a */, + ); + name = Products; sourceTree = ""; }; - 18073855146D0D4E00F05C24 /* Supporting Files */ = { + 0C3145531496B02100427C0B /* security_ssl */ = { isa = PBXGroup; children = ( - 182BB562146F4C73000BF1F3 /* security.exp-in */, - 182BB55D146F4544000BF1F3 /* generateErrStrings.pl */, - 182BB55E146F4544000BF1F3 /* Security.order */, - 18073856146D0D4E00F05C24 /* Info-Security.plist */, + 0CA31A4614BB5C9100BD348C /* CipherSuite.h */, + 0C3145551496B8FB00427C0B /* SecureTransport.h */, + 0C3145561496B8FB00427C0B /* SecureTransportPriv.h */, + 0CA31A7314BB6C2500BD348C /* sslTypes.h */, ); - name = "Supporting Files"; + name = security_ssl; sourceTree = ""; }; - 181EA3D0146D1ED200A6D320 /* libsecurity */ = { + 0C59B54417677A9900617746 /* asl */ = { isa = PBXGroup; children = ( - 1879B532146DDBE5007E536C /* libsecurity_utilities.xcodeproj */, - 1879B547146DE212007E536C /* libsecurity_cdsa_utils.xcodeproj */, - 1879B550146DE227007E536C /* libsecurity_cdsa_utilities.xcodeproj */, - 1879B55D146DE244007E536C /* libsecurity_cssm.xcodeproj */, - 1879B5BC146DE6C8007E536C /* libsecurity_apple_csp.xcodeproj */, - 1879B5C9146DE6CE007E536C /* libsecurity_apple_cspdl.xcodeproj */, - 1879B5D5146DE6D7007E536C /* libsecurity_apple_file_dl.xcodeproj */, - 1879B5E1146DE6E7007E536C /* libsecurity_apple_x509_cl.xcodeproj */, - 1879B5F0146DE6FD007E536C /* libsecurity_apple_x509_tp.xcodeproj */, - 1879B5FC146DE704007E536C /* libsecurity_asn1.xcodeproj */, - 1879B609146DE70A007E536C /* libsecurity_authorization.xcodeproj */, - 1879B615146DE715007E536C /* libsecurity_cdsa_client.xcodeproj */, - 1879B621146DE720007E536C /* libsecurity_cdsa_plugin.xcodeproj */, - 1879B637146DE748007E536C /* libsecurity_checkpw.xcodeproj */, - 1879B64B146DE750007E536C /* libsecurity_cms.xcodeproj */, - 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */, - 1879B66D146DE75D007E536C /* libsecurity_comcryption.xcodeproj */, - 1879B679146DE76E007E536C /* libsecurity_cryptkit.xcodeproj */, - 1879B694146DE797007E536C /* libsecurity_filedb.xcodeproj */, - 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */, - 1879B6C7146DE7D7007E536C /* libsecurity_manifest.xcodeproj */, - 1879B6D3146DE7E0007E536C /* libsecurity_mds.xcodeproj */, - 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */, - 1879B712146DE825007E536C /* libsecurity_smime.xcodeproj */, - 1879B72B146DE844007E536C /* libsecurity_transform.xcodeproj */, - 1879B6DF146DE7E7007E536C /* libsecurity_ocspd.xcodeproj */, - 1879B6F8146DE7F7007E536C /* libsecurity_sd_cspdl.xcodeproj */, - 1879B6EC146DE7EE007E536C /* libsecurity_pkcs12.xcodeproj */, - 184461A3146E9D3200B12992 /* libsecurityd.xcodeproj */, - 18270F0814CF43C000B05E7F /* libDER.xcodeproj */, + 0C59B54517677A9900617746 /* com.apple.securityd */, ); - name = libsecurity; + path = asl; sourceTree = ""; }; - 181EA421146D4A2A00A6D320 /* config */ = { + 0C5D2EDC167FEA880077501D /* security_asn1 */ = { isa = PBXGroup; children = ( - 18BFC44017C43393005DE6C3 /* executable.xcconfig */, - 18BBC6801471EF1600F2B224 /* security.xcconfig */, - 181EA422146D4A2A00A6D320 /* base.xcconfig */, - 181EA423146D4A2A00A6D320 /* debug.xcconfig */, - 181EA424146D4A2A00A6D320 /* lib.xcconfig */, - 0C6C632F15D19DE600BC68CD /* test.xcconfig */, - 4CB23B91169F5CFF003A0131 /* command.xcconfig */, - 181EA425146D4A2A00A6D320 /* release.xcconfig */, - ); - path = config; + 7901792812D51FFC00CA4D44 /* SecAsn1Types.h */, + 0C5D2EEA167FEAAC0077501D /* SecAsn1Coder.h */, + 0C5D2EEE167FF0560077501D /* SecAsn1Templates.h */, + 0C5D2EF0167FF1FC0077501D /* oidsalg.h */, + 0C5D2EEC167FEEC90077501D /* secasn1t.h */, + ); + name = security_asn1; sourceTree = ""; }; - 18270EEB14CF331500B05E7F /* ipc */ = { + 0C78F1C816A5E13400654E08 /* regressions */ = { isa = PBXGroup; children = ( - 18BEB19614CF74C100C8BD36 /* com.apple.secd.plist */, - 18270EEC14CF333400B05E7F /* client.c */, - 18270EED14CF333400B05E7F /* com.apple.securityd.plist */, - 18270EEE14CF333400B05E7F /* securityd_client.h */, - 18270EEF14CF333400B05E7F /* securityd_ipc_types.h */, - 18270EF014CF333400B05E7F /* securityd_rep.defs */, - 18270EF114CF333400B05E7F /* securityd_req.defs */, - 18270EF214CF333400B05E7F /* securityd_server.h */, - 18270EF314CF333400B05E7F /* server.c */, + 0C78F1CA16A5E1BF00654E08 /* sectask-10-sectask.c */, + 0C78F1CB16A5E1BF00654E08 /* sectask_ipc.defs */, + 0C78F1C916A5E13400654E08 /* sectask_regressions.h */, ); - name = ipc; - path = sec/ipc; + path = regressions; sourceTree = ""; }; - 18270F0914CF43C000B05E7F /* Products */ = { + 0C95404014E473AA00077526 /* Products */ = { isa = PBXGroup; children = ( - 18270F1214CF43C000B05E7F /* libDER.a */, - 18270F1414CF43C000B05E7F /* parseCert */, - 18270F1614CF43C000B05E7F /* libDERUtils.a */, - 18270F1814CF43C000B05E7F /* parseCrl */, - 18270F1A14CF43C000B05E7F /* parseTicket */, + 0CCA406A15C73CA1002AEC4C /* libsecurity_ssl.a */, + 0C271D6E15C8C68800560531 /* libsecurity_ssl_kext.a */, + 0CCA418415C89ECD002AEC4C /* libsecurity_ssl_regressions.a */, + 0CCA42F115C8A806002AEC4C /* dtlsEchoClient */, + 0CCA42F315C8A806002AEC4C /* dtlsEchoServer */, ); name = Products; sourceTree = ""; }; - 18270F3114CF448600B05E7F /* security_utilities */ = { + 0CF55E5614DB47DE003AD8F2 /* Products */ = { isa = PBXGroup; children = ( - 18270F3A14CF44C400B05E7F /* debugging.c */, - 18270F3B14CF44C400B05E7F /* debugging.h */, + 0CF55E6014DB47DF003AD8F2 /* tlsnke.kext */, + 0CF55E6214DB47DF003AD8F2 /* tlsnketest */, + 0C62D60814E0588700A97963 /* libtlssocket.a */, ); - path = security_utilities; + name = Products; sourceTree = ""; }; - 182BB228146F0674000BF1F3 /* Resources */ = { + 107226CF0D91DB32003CF14F /* sectask */ = { isa = PBXGroup; children = ( - 187D6B8F15D4359F00E27494 /* authorization.buttons.strings */, - BE8C5F0916F7CE450074CF86 /* framework.sb */, - 187D6B9115D4359F00E27494 /* authorization.prompts.strings */, - 52B006BF15238F76005D4556 /* TimeStampingPrefs.plist */, - 188AD8D81471FE3D0081C619 /* FDELocalizable.strings */, - 188AD8DA1471FE3D0081C619 /* InfoPlist.strings */, - 182BB55C146F4544000BF1F3 /* FDEPrefs.plist */, - 182BB229146F068B000BF1F3 /* iToolsTrustedApps.plist */, - 1879B4A8146DC9D7007E536C /* mds */, - ); - name = Resources; + 0C78F1C816A5E13400654E08 /* regressions */, + 107226D00D91DB32003CF14F /* SecTask.c */, + 107226D10D91DB32003CF14F /* SecTask.h */, + 4C7CE56E0DC7DB0A00AE53FC /* SecEntitlements.h */, + ); + path = sectask; sourceTree = ""; }; - 182BB555146F450F000BF1F3 /* plugins */ = { + 18F7F65914D77DF700F88A12 /* Products */ = { isa = PBXGroup; children = ( - 182BB556146F4510000BF1F3 /* csparser-Info.plist */, - 182BB557146F4510000BF1F3 /* csparser.cpp */, - 182BB558146F4510000BF1F3 /* csparser.exp */, + 18F7F66314D77DF700F88A12 /* libsecurity.a */, + 18F7F66514D77DF700F88A12 /* libsecurityd.a */, + 18F7F66714D77DF700F88A12 /* libSecItemShimOSX.a */, + 18F7F66914D77DF700F88A12 /* libsecipc_client.a */, + 4C60888B155C943D00A0904F /* libSecureObjectSync.a */, + 4C60888D155C943D00A0904F /* libSOSRegressions.a */, + E79D9CD5159BEA78000834EC /* libSecurityRegressions.a */, + 4CC92B1A15A3BF1E00C6D578 /* libsecuritydRegressions.a */, + E777C71515B63C0B004044A8 /* libSecOtrOSX.a */, + 52849FAE164462E7005CDF23 /* libCloudKeychainProxy.a */, + E7104A06169E038F00DB0045 /* libSecurityTool.a */, + E7104A23169E21C000DB0045 /* libSecurityCommands.a */, + E7FEFB8F169E36B000E18152 /* libSOSCommands.a */, + 0C0BDB821756A1D700BC1A7E /* libsecdRegressions.a */, + BE442B9B18B7FD6700F24DAE /* libSWCAgent.a */, + E76079DB1951FDBF00F69731 /* liblogging.a */, ); - path = plugins; + name = Products; sourceTree = ""; }; - 182BB5A9146FEB27000BF1F3 /* derived_src */ = { + 4C198F1A0ACDB4BF00AAB142 /* resources */ = { isa = PBXGroup; children = ( - 18B647EF14D9F75300F538BF /* generateErrStrings.mm */, - 18500F9F14708F19006F9AB4 /* SecErrorMessages.strings */, - 18500F9A14708D0E006F9AB4 /* SecDebugErrorMessages.strings */, - ); - name = derived_src; + 53C0E1F1177FAC2C00F8A018 /* CloudKeychain.strings */, + BE4AC9B818B8273600B84964 /* SharedWebCredentials.strings */, + 721146CA177A80C3005B5871 /* AppleESCertificates.plist */, + 7245AD1D16E801BB009096D8 /* AssetVersion.plist */, + 72F06A8D16D4315B003C8D56 /* GrayListedKeys.plist */, + 72E2DBF316BC476E00E7B236 /* Blocked.plist */, + 72E2DBF416BC476E00E7B236 /* certsIndex.data */, + 72E2DBF516BC476E00E7B236 /* certsTable.data */, + 4C494C560F4F884800CDCBFE /* EVRoots.plist */, + 4C198F1D0ACDB4BF00AAB142 /* Certificate.strings */, + 4C198F1F0ACDB4BF00AAB142 /* OID.strings */, + 4CFFEBDD1018EE6000F33F0D /* genevroots.rb */, + ); + path = resources; sourceTree = ""; }; - 184461A4146E9D3200B12992 /* Products */ = { + 4C2FEC4A15755D700008BE39 /* Products */ = { isa = PBXGroup; children = ( - 184461B1146E9D3300B12992 /* libsecurityd_client.a */, - 184461B5146E9D3300B12992 /* libsecurityd_server.a */, - 184461B9146E9D3300B12992 /* ucspc.a */, + 4C2FEC5115755D710008BE39 /* libutilities.a */, + E7E0D8FE158FAB3B002CA176 /* libutilitiesRegressions.a */, ); name = Products; sourceTree = ""; }; - 186CDD0314CA10E700AF9171 /* sec */ = { + 4C35DB67094F906D002917C4 = { isa = PBXGroup; children = ( - 186CDD1614CA11C700AF9171 /* sec.xcodeproj */, + 05EF68A919491453007958C3 /* SecurityTool.xcodeproj */, + 05EF687F1949143A007958C3 /* securityd.xcodeproj */, + 051D8F82194913E500AEF66A /* Security.xcodeproj */, + 0CF55E5514DB47DE003AD8F2 /* tlsnke.xcodeproj */, + 0C25A871122726540050C2BD /* regressions.xcodeproj */, + 4C8786A10B03E05D00BB77D4 /* libDER.xcodeproj */, + 795CA97A0D38269B00BAE6A2 /* libsecurity_asn1.xcodeproj */, + 79BDD3940D60D5F9000D84D3 /* libsecurity_smime.xcodeproj */, + 18F7F65814D77DF700F88A12 /* sec.xcodeproj */, + 0C95403F14E473AA00077526 /* libsecurity_ssl.xcodeproj */, + 4C2FEC4915755D700008BE39 /* utilities.xcodeproj */, + 0C59B54417677A9900617746 /* asl */, + 4C999BA00AB5F0BB0010451D /* ntlm */, + 107226CF0D91DB32003CF14F /* sectask */, + 7908507E0CA87CF00083CC4D /* ipc */, + 4C198F1A0ACDB4BF00AAB142 /* resources */, + 4CE5A55609C7970A00D27A3F /* sslViewer */, + 4CB740FA0A47580400D641BB /* SecurityTool */, + BE4AC9AF18B7FFFA00B84964 /* SharedWebCredentialAgent */, + 72979BD1175D08C700BE8FD6 /* CloudKeychainDiagnoseTool */, + 4C86273C1137BEF8009EAB5A /* AspenFamily.xcconfig */, + E710C74A1331946500F85568 /* SecurityTests */, + 79DCEA56134A27D2007F57DC /* codesign_wrapper */, + 52DE816E1636347500F49F0C /* Keychain */, + 52D82BE016A621F70078DFE5 /* CloudKeychainProxy */, + E7450BB216D42BD4009C07B8 /* Security.framework headers */, + 728B56A316D59979008FA3AB /* OTAPKIAssetTool */, + 4C52D0B616EFC61E0079966E /* CircleJoinRequested */, + 5346480317331E1200FE9172 /* KeychainSyncAccountNotification */, + 0C0BDB30175685B000BC1A7E /* secdtests */, + 72979BE4175D095900BE8FD6 /* cloud_keychain_diagnose */, + 721680C5179B514700406BB4 /* iCloudStat */, + BE197F2719116FD100BA91D1 /* SharedWebCredentialViewService */, + E7FCBE401314471B000DE34E /* Frameworks */, + 4C35DC36094F9120002917C4 /* Products */, + 4C8BC620097DBC1B00C781D5 /* Libraries */, + 4CB7405F0A47498100D641BB /* Security.exp-in */, + 4C35DC37094F9120002917C4 /* Security-Info.plist */, + 4C4CE9120AF81F0E0056B01D /* README */, + 4CAB97FD1114CC5300EFB38D /* README.keychain */, + 4C4CE9070AF81ED80056B01D /* TODO */, + 4C4CE90D0AF81EF80056B01D /* WHITEPAPER */, ); - path = sec; sourceTree = ""; }; - 186CDD1714CA11C700AF9171 /* Products */ = { + 4C35DC36094F9120002917C4 /* Products */ = { isa = PBXGroup; children = ( - 18D4053B14CE2C1600A2BE4E /* libsecurity.a */, - 18270C7D14CE573D00B05E7F /* libsecurityd.a */, - 186CDD1E14CA11C700AF9171 /* libSecItemShimOSX.a */, - 18270F6014CF655B00B05E7F /* libsecipc_client.a */, - 4C1288EA15FFE9D7008CE3E3 /* libSecureObjectSync.a */, - 4C1288EC15FFE9D7008CE3E3 /* libSOSRegressions.a */, - 4C1288EE15FFE9D7008CE3E3 /* libSecurityRegressions.a */, - 4C1288F015FFE9D7008CE3E3 /* libsecuritydRegressions.a */, - 4C1288F215FFE9D7008CE3E3 /* libSecOtrOSX.a */, - 4C01DE32164C3793006798CD /* libCloudKeychainProxy.a */, - 4CB23B76169F5873003A0131 /* libSecurityTool.a */, - 4CB23B78169F5873003A0131 /* libSecurityCommands.a */, - 4CB23B7A169F5873003A0131 /* libSOSCommands.a */, - 0C4EAE721766865000773425 /* libsecdRegressions.a */, + 4C32C0AF0A4975F6002891BD /* Security.framework */, + 790851B60CA9859F0083CC4D /* securityd */, + 4CB740A30A47567C00D641BB /* security */, + 7913B2110D172B3900601FE9 /* sslServer */, + 4CE5A54D09C796E200D27A3F /* sslViewer */, + 4C9DE9D21181AC4800CF5C27 /* sslEcdsa */, + E710C7421331946400F85568 /* SecurityTests.app */, + 79DCEA54134A27D2007F57DC /* codesign_wrapper */, + 4C711D7613AFCD0900FE865D /* SecurityDevTests.app */, + 52DE81691636347500F49F0C /* Keychain.app */, + E7B01BF2166594AB000485F1 /* SyncDevTest2.app */, + 52D82BDE16A621F70078DFE5 /* CloudKeychainProxy.bundle */, + 728B56A116D59979008FA3AB /* OTAPKIAssetTool */, + 4C52D0B416EFC61E0079966E /* CircleJoinRequested */, + 5346480117331E1200FE9172 /* KeychainSyncAccountNotification.bundle */, + 0C0BDB2F175685B000BC1A7E /* secdtests */, + 72979BE2175D095900BE8FD6 /* cloud_keychain_diagnose */, + BE442BC118B7FDB800F24DAE /* swcagent */, + BE197F2619116FD100BA91D1 /* SharedWebCredentialViewService.app */, ); name = Products; sourceTree = ""; }; - 186CDE7914CA3A3800AF9171 /* secd */ = { + 4C50ACFB1410671D00EE92DE /* DigiNotar */ = { isa = PBXGroup; children = ( - 18270EEB14CF331500B05E7F /* ipc */, - 18270F3114CF448600B05E7F /* security_utilities */, - ); - name = secd; + 4C3CECF21416E20400947741 /* DigiNotar_Root_CA_G2-RootCertificate.crt */, + 4C3CECEA1416DB2200947741 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */, + 4C3CECEB1416DB2200947741 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt */, + 4C3CECEC1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheid.crt */, + 4C3CECED1416DB2200947741 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt */, + 4C3CECEE1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt */, + 4C3CECEF1416DB2200947741 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt */, + 4C3CECF01416DB2200947741 /* staatdernederlandenorganisatieca-g2-Cert.crt */, + 4C3CECF11416DB2200947741 /* staatdernederlandenoverheidca-Cert.crt */, + 4C8B91C51416EB6A00A254E2 /* Invalid-webmail.portofamsterdam.nl.crt */, + 4C50AD2F1410689300EE92DE /* Expectations.plist */, + 4C50ACFC1410671D00EE92DE /* DigiNotarCA2007RootCertificate.crt */, + 4C50ACFD1410671D00EE92DE /* Invalid-asterisk.google.com.crt */, + 4C50ACFE1410671D00EE92DE /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */, + 4C50ACFF1410671D00EE92DE /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */, + 4C50AD001410671D00EE92DE /* Invalid-www.maestre.com-diginotal.extended.validation.crt */, + 4C50AD011410671D00EE92DE /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */, + 4C50AD021410671D00EE92DE /* diginotar-public-ca-2025-Cert.crt */, + 4C50AD031410671D00EE92DE /* diginotar-services-1024-entrust-secure-server-Cert.crt */, + 4C50AD041410671D00EE92DE /* diginotar-services-diginotar-root-Cert.crt */, + 4C50AD051410671D00EE92DE /* diginotar.cyberca-gte.global.root-Cert.crt */, + 4C50AD061410671D00EE92DE /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */, + 4C50AD071410671D00EE92DE /* diginotar.root.ca-entrust-secure-server-Cert.crt */, + ); + path = DigiNotar; sourceTree = ""; }; - 1879B4A6146DC971007E536C /* Headers */ = { + 4C52D0B616EFC61E0079966E /* CircleJoinRequested */ = { isa = PBXGroup; children = ( - 18446146146E923200B12992 /* Authorization.h */, - 18446147146E923200B12992 /* AuthorizationDB.h */, - 18446148146E923200B12992 /* AuthorizationPlugin.h */, - 18446144146E923200B12992 /* AuthorizationTags.h */, - 18446145146E923200B12992 /* AuthSession.h */, - 1879B4AD146DCA84007E536C /* certextensions.h */, - 182BB36E146F13B4000BF1F3 /* CipherSuite.h */, - 18446170146E982800B12992 /* CMSDecoder.h */, - 18446171146E982800B12992 /* CMSEncoder.h */, - 1844617F146E9A8500B12992 /* CodeSigning.h */, - 18446180146E9A8500B12992 /* CSCommon.h */, - 1879B4AE146DCA84007E536C /* cssm.h */, - 1879B4AF146DCA84007E536C /* cssmaci.h */, - 1879B4B0146DCA84007E536C /* cssmapi.h */, - 1879B4B1146DCA84007E536C /* cssmapple.h */, - 1879B4B2146DCA84007E536C /* cssmcli.h */, - 1879B4B3146DCA84007E536C /* cssmconfig.h */, - 1879B4B4146DCA84007E536C /* cssmcspi.h */, - 1879B4B5146DCA84007E536C /* cssmdli.h */, - 1879B4B6146DCA84007E536C /* cssmerr.h */, - 1879B4B7146DCA84007E536C /* cssmkrapi.h */, - 1879B4B8146DCA84007E536C /* cssmkrspi.h */, - 1879B4B9146DCA84007E536C /* cssmspi.h */, - 1879B4BA146DCA84007E536C /* cssmtpi.h */, - 1879B4BB146DCA84007E536C /* cssmtype.h */, - 1879B4BC146DCA84007E536C /* eisl.h */, - 1879B4BD146DCA84007E536C /* emmspi.h */, - 1879B4BE146DCA84007E536C /* emmtype.h */, - 182BB356146F1198000BF1F3 /* mds.h */, - 182BB357146F1198000BF1F3 /* mds_schema.h */, - 18B647E814D9EB6300F538BF /* oidsalg.h */, - 18B647EA14D9EE4300F538BF /* oidsattr.h */, - 1879B4C1146DCA84007E536C /* oidsbase.h */, - 1879B4C2146DCA84007E536C /* oidscert.h */, - 1879B4C3146DCA84007E536C /* oidscrl.h */, - 182BB187146EAD4C000BF1F3 /* SecAccess.h */, - 182BB188146EAD4C000BF1F3 /* SecACL.h */, - 184460AB146DFCC100B12992 /* SecAsn1Coder.h */, - 184460AC146DFCC100B12992 /* SecAsn1Templates.h */, - 184460AD146DFCC100B12992 /* SecAsn1Types.h */, - 182BB189146EAD4C000BF1F3 /* SecBase.h */, - 182BB18A146EAD4C000BF1F3 /* SecCertificate.h */, - 182BB199146EAD4C000BF1F3 /* SecCertificateOIDs.h */, - 18446181146E9A8500B12992 /* SecCode.h */, - 18446184146E9A8500B12992 /* SecCodeHost.h */, - 182BB3A6146F1BEC000BF1F3 /* SecCustomTransform.h */, - 182BB3A7146F1BEC000BF1F3 /* SecDecodeTransform.h */, - 182BB3A3146F1BEC000BF1F3 /* SecDigestTransform.h */, - 182BB3A8146F1BEC000BF1F3 /* SecEncodeTransform.h */, - 182BB3A9146F1BEC000BF1F3 /* SecEncryptTransform.h */, - 182BB18B146EAD4C000BF1F3 /* SecIdentity.h */, - 182BB18C146EAD4C000BF1F3 /* SecIdentitySearch.h */, - 182BB197146EAD4C000BF1F3 /* SecImportExport.h */, - 182BB18D146EAD4C000BF1F3 /* SecItem.h */, - 182BB18E146EAD4C000BF1F3 /* SecKey.h */, - 182BB18F146EAD4C000BF1F3 /* SecKeychain.h */, - 182BB190146EAD4C000BF1F3 /* SecKeychainItem.h */, - 182BB191146EAD4C000BF1F3 /* SecKeychainSearch.h */, - 182BB192146EAD4C000BF1F3 /* SecPolicy.h */, - 182BB193146EAD4C000BF1F3 /* SecPolicySearch.h */, - 182BB19A146EAD4C000BF1F3 /* SecRandom.h */, - 182BB3A4146F1BEC000BF1F3 /* SecReadTransform.h */, - 18446183146E9A8500B12992 /* SecRequirement.h */, - 182BB3AA146F1BEC000BF1F3 /* SecSignVerifyTransform.h */, - 18446182146E9A8500B12992 /* SecStaticCode.h */, - 1844617E146E9A8500B12992 /* SecTask.h */, - BEC3A76716F79497003E5634 /* SecTaskPriv.h */, - 182BB3A5146F1BEC000BF1F3 /* SecTransform.h */, - 182BB3AB146F1BEC000BF1F3 /* SecTransformReadTransform.h */, - 182BB194146EAD4C000BF1F3 /* SecTrust.h */, - 182BB195146EAD4C000BF1F3 /* SecTrustedApplication.h */, - 182BB198146EAD4C000BF1F3 /* SecTrustSettings.h */, - 182BB315146F0E7E000BF1F3 /* SecureDownload.h */, - 182BB36F146F13B4000BF1F3 /* SecureTransport.h */, - 182BB196146EAD4C000BF1F3 /* Security.h */, - 4CB86AFA167A8F2200F46643 /* SOSAccount.h */, - 4CB86AE6167A6FF200F46643 /* SOSCircle.h */, - 4CB86AE7167A6FF200F46643 /* SOSCloudCircle.h */, - 4CB86AE8167A6FF200F46643 /* SOSCloudCircleInternal.h */, - 4CB86AE9167A6FF200F46643 /* SOSEngine.h */, - 4CB86AEA167A6FF300F46643 /* SOSFullPeerInfo.h */, - 4CB86AEB167A6FF300F46643 /* SOSInternal.h */, - 4CB86AEC167A6FF300F46643 /* SOSPeer.h */, - 4CB86AED167A6FF300F46643 /* SOSPeerInfo.h */, - 4CB86AEE167A6FF300F46643 /* SOSTransport.h */, - 1879B4C4146DCA84007E536C /* x509defs.h */, - ); - name = Headers; + 4C52D0B916EFC61E0079966E /* CircleJoinRequested.m */, + 4CC3D28F178F310B0070FCC4 /* PersistantState.h */, + 4CC3D290178F310C0070FCC4 /* PersistantState.m */, + 4C52D0E216EFCCA20079966E /* Applicant.h */, + 4C52D0E316EFCCA20079966E /* Applicant.m */, + 4C52D0E416EFCCA20079966E /* com.apple.security.CircleJoinRequested.plist */, + 4C52D0E516EFCCA20079966E /* NSArray+map.h */, + 4C52D0E616EFCCA20079966E /* NSArray+map.m */, + 4C52D0BB16EFC61E0079966E /* CircleJoinRequested.1 */, + 4C52D0BD16EFC61E0079966E /* Readme.txt */, + 4C3DD6AE179755560093F9D8 /* NSDate+TimeIntervalDescription.h */, + 4C3DD6AF179755560093F9D8 /* NSDate+TimeIntervalDescription.m */, + 4C52D0B716EFC61E0079966E /* Supporting Files */, + 4C84DA6217207E8D00AEE225 /* entitlements.plist */, + ); + path = CircleJoinRequested; sourceTree = ""; }; - 1879B4A7146DC999007E536C /* PrivateHeaders */ = { + 4C52D0B716EFC61E0079966E /* Supporting Files */ = { isa = PBXGroup; children = ( - 184460A1146DFCB700B12992 /* asn1Templates.h */, - 1844614F146E923B00B12992 /* AuthorizationPriv.h */, - 1844614E146E923B00B12992 /* AuthorizationTagsPriv.h */, - 1844609A146DFCB700B12992 /* certExtensionTemplates.h */, - 18446168146E95D700B12992 /* checkpw.h */, - 18446174146E982D00B12992 /* CMSPrivate.h */, - 1844618C146E9A8F00B12992 /* CSCommonPriv.h */, - 1844609B146DFCB700B12992 /* csrTemplates.h */, - 1879B4AB146DCA4A007E536C /* cssmapplePriv.h */, - 184460A0146DFCB700B12992 /* keyTemplates.h */, - 182BB35A146F11A1000BF1F3 /* mdspriv.h */, - 1844609D146DFCB700B12992 /* nameTemplates.h */, - 1844609C146DFCB700B12992 /* ocspTemplates.h */, - 1844609F146DFCB700B12992 /* osKeyTemplates.h */, - 182BB1B2146EAD5D000BF1F3 /* SecAccessPriv.h */, - 18446099146DFCB700B12992 /* secasn1t.h */, - 18446194146E9A8F00B12992 /* SecAssessment.h */, - 182BB1B3146EAD5D000BF1F3 /* SecBasePriv.h */, - 182BB1B4146EAD5D000BF1F3 /* SecCertificateBundle.h */, - 182BB1B5146EAD5D000BF1F3 /* SecCertificatePriv.h */, - 182BB1B6146EAD5D000BF1F3 /* SecCertificateRequest.h */, - 182BB383146F14D2000BF1F3 /* SecCmsBase.h */, - 182BB384146F14D2000BF1F3 /* SecCmsContentInfo.h */, - 182BB385146F14D2000BF1F3 /* SecCmsDecoder.h */, - 182BB386146F14D2000BF1F3 /* SecCmsDigestContext.h */, - 182BB387146F14D2000BF1F3 /* SecCmsDigestedData.h */, - 182BB388146F14D2000BF1F3 /* SecCmsEncoder.h */, - 182BB389146F14D2000BF1F3 /* SecCmsEncryptedData.h */, - 182BB38A146F14D2000BF1F3 /* SecCmsEnvelopedData.h */, - 182BB38B146F14D2000BF1F3 /* SecCmsMessage.h */, - 182BB38C146F14D2000BF1F3 /* SecCmsRecipientInfo.h */, - 182BB38D146F14D2000BF1F3 /* SecCmsSignedData.h */, - 182BB38E146F14D2000BF1F3 /* SecCmsSignerInfo.h */, - 18446193146E9A8F00B12992 /* SecCodeHostLib.h */, - 1844618D146E9A8F00B12992 /* SecCodePriv.h */, - 18446190146E9A8F00B12992 /* SecCodeSigner.h */, - 18BBC7351471F5A300F2B224 /* SecExternalSourceTransform.h */, - 182BB1AF146EAD5D000BF1F3 /* SecFDERecoveryAsymmetricCrypto.h */, - 182BB1B7146EAD5D000BF1F3 /* SecIdentityPriv.h */, - 182BB1C4146EAD5D000BF1F3 /* SecIdentitySearchPriv.h */, - 18446191146E9A8F00B12992 /* SecIntegrity.h */, - 18446192146E9A8F00B12992 /* SecIntegrityLib.h */, - 182BB1CA146EAD5D000BF1F3 /* SecItemPriv.h */, - 182BB1CB146EAD5D000BF1F3 /* SecKeychainItemExtendedAttributes.h */, - 182BB1B8146EAD5D000BF1F3 /* SecKeychainItemPriv.h */, - 182BB1B9146EAD5D000BF1F3 /* SecKeychainPriv.h */, - 182BB1C5146EAD5D000BF1F3 /* SecKeychainSearchPriv.h */, - 182BB1BA146EAD5D000BF1F3 /* SecKeyPriv.h */, - 182BB317146F0E94000BF1F3 /* SecManifest.h */, - 182BB3B6146F1BF9000BF1F3 /* SecNullTransform.h */, - 182BB1B0146EAD5D000BF1F3 /* SecPassword.h */, - CDDE9D1C1729DF250013B0E8 /* SecPasswordGenerate.h */, - 182BB1BB146EAD5D000BF1F3 /* SecPolicyPriv.h */, - 182BB1CF146EAD5D000BF1F3 /* SecRandomP.h */, - 182BB1CE146EAD5D000BF1F3 /* SecRecoveryPassword.h */, - 1844618F146E9A8F00B12992 /* SecRequirementPriv.h */, - 182BB38F146F14D2000BF1F3 /* SecSMIME.h */, - 1844618E146E9A8F00B12992 /* SecStaticCodePriv.h */, - 182BB3B7146F1BF9000BF1F3 /* SecTransformInternal.h */, - 182BB1BC146EAD5D000BF1F3 /* SecTrustedApplicationPriv.h */, - 182BB1BD146EAD5D000BF1F3 /* SecTrustPriv.h */, - 182BB1C6146EAD5D000BF1F3 /* SecTrustSettingsPriv.h */, - 182BB318146F0E94000BF1F3 /* SecureDownloadInternal.h */, - 182BB372146F13BB000BF1F3 /* SecureTransportPriv.h */, - 0C4F055D15C9E51A00F9DFD5 /* sslTypes.h */, - 182BB1C8146EAD5D000BF1F3 /* TrustSettingsSchema.h */, - 52B5A9C01519330300664F11 /* tsaSupport.h */, - 52AEA484153C7581005AFC59 /* tsaSupportPriv.h */, - 52B5A9C11519330300664F11 /* tsaTemplates.h */, - 1844609E146DFCB700B12992 /* X509Templates.h */, - ); - name = PrivateHeaders; + 4C52D0B816EFC61E0079966E /* AspenFamily.xcconfig */, + CDB9FCA9179CC757000AAD66 /* Info.plist */, + ); + name = "Supporting Files"; sourceTree = ""; }; - 1879B4A8146DC9D7007E536C /* mds */ = { + 4C7540BA13D51D63008048AC /* nist-certs */ = { isa = PBXGroup; children = ( - 182BB3C4146F1DCB000BF1F3 /* sd_cspdl_common.mdsinfo */, - 1879B4A9146DCA18007E536C /* cssm.mdsinfo */, - 1844605B146DE93E00B12992 /* csp_capabilities.mdsinfo */, - 1844605C146DE93E00B12992 /* csp_capabilities_common.mds */, - 1844605D146DE93E00B12992 /* csp_common.mdsinfo */, - 1844605E146DE93E00B12992 /* csp_primary.mdsinfo */, - 184460C3146E7B1E00B12992 /* cspdl_common.mdsinfo */, - 184460C4146E7B1E00B12992 /* cspdl_csp_capabilities.mdsinfo */, - 184460C5146E7B1E00B12992 /* cspdl_csp_primary.mdsinfo */, - 184460C6146E7B1E00B12992 /* cspdl_dl_primary.mdsinfo */, - 184460E1146E806700B12992 /* dl_common.mdsinfo */, - 184460E2146E806700B12992 /* dl_primary.mdsinfo */, - 18446103146E82C800B12992 /* cl_common.mdsinfo */, - 18446104146E82C800B12992 /* cl_primary.mdsinfo */, - 18446112146E85A300B12992 /* tp_common.mdsinfo */, - 18446113146E85A300B12992 /* tp_policyOids.mdsinfo */, - 18446114146E85A300B12992 /* tp_primary.mdsinfo */, - ); - name = mds; + E7A94C9713D8A0DF001C5FEE /* Expectations.plist */, + 4C7540BB13D51D63008048AC /* AllCertificatesNoPoliciesTest2EE.crt */, + 4C7540BC13D51D63008048AC /* AllCertificatesSamePoliciesTest10EE.crt */, + 4C7540BD13D51D63008048AC /* AllCertificatesSamePoliciesTest13EE.crt */, + 4C7540BE13D51D63008048AC /* AllCertificatesanyPolicyTest11EE.crt */, + 4C7540BF13D51D63008048AC /* AnyPolicyTest14EE.crt */, + 4C7540C013D51D63008048AC /* BadCRLIssuerNameCACert.crt */, + 4C7540C113D51D63008048AC /* BadCRLSignatureCACert.crt */, + 4C7540C213D51D63008048AC /* BadSignedCACert.crt */, + 4C7540C313D51D63008048AC /* BadnotAfterDateCACert.crt */, + 4C7540C413D51D63008048AC /* BadnotBeforeDateCACert.crt */, + 4C7540C513D51D63008048AC /* BasicSelfIssuedCRLSigningKeyCACert.crt */, + 4C7540C613D51D63008048AC /* BasicSelfIssuedNewKeyCACert.crt */, + 4C7540C713D51D63008048AC /* BasicSelfIssuedNewKeyOldWithNewCACert.crt */, + 4C7540C813D51D63008048AC /* BasicSelfIssuedOldKeyCACert.crt */, + 4C7540C913D51D63008048AC /* BasicSelfIssuedOldKeyNewWithOldCACert.crt */, + 4C7540CA13D51D63008048AC /* CPSPointerQualifierTest20EE.crt */, + 4C7540CB13D51D63008048AC /* DSACACert.crt */, + 4C7540CC13D51D63008048AC /* DSAParametersInheritedCACert.crt */, + 4C7540CD13D51D63008048AC /* DifferentPoliciesTest12EE.crt */, + 4C7540CE13D51D63008048AC /* DifferentPoliciesTest3EE.crt */, + 4C7540CF13D51D63008048AC /* DifferentPoliciesTest4EE.crt */, + 4C7540D013D51D63008048AC /* DifferentPoliciesTest5EE.crt */, + 4C7540D113D51D63008048AC /* DifferentPoliciesTest7EE.crt */, + 4C7540D213D51D63008048AC /* DifferentPoliciesTest8EE.crt */, + 4C7540D313D51D63008048AC /* DifferentPoliciesTest9EE.crt */, + 4C7540D413D51D63008048AC /* GeneralizedTimeCRLnextUpdateCACert.crt */, + 4C7540D513D51D63008048AC /* GoodCACert.crt */, + 4C7540D613D51D63008048AC /* GoodsubCACert.crt */, + 4C7540D713D51D63008048AC /* GoodsubCAPanyPolicyMapping1to2CACert.crt */, + 4C7540D813D51D63008048AC /* InvalidBasicSelfIssuedNewWithOldTest5EE.crt */, + 4C7540D913D51D63008048AC /* InvalidBasicSelfIssuedOldWithNewTest2EE.crt */, + 4C7540DA13D51D63008048AC /* InvalidCASignatureTest2EE.crt */, + 4C7540DB13D51D63008048AC /* InvalidCAnotAfterDateTest5EE.crt */, + 4C7540DC13D51D63008048AC /* InvalidCAnotBeforeDateTest1EE.crt */, + 4C7540DD13D51D63008048AC /* InvalidDNSnameConstraintsTest31EE.crt */, + 4C7540DE13D51D63008048AC /* InvalidDNSnameConstraintsTest33EE.crt */, + 4C7540DF13D51D63008048AC /* InvalidDNSnameConstraintsTest38EE.crt */, + 4C7540E013D51D63008048AC /* InvalidDNandRFC822nameConstraintsTest28EE.crt */, + 4C7540E113D51D63008048AC /* InvalidDNandRFC822nameConstraintsTest29EE.crt */, + 4C7540E213D51D63008048AC /* InvalidDNnameConstraintsTest10EE.crt */, + 4C7540E313D51D63008048AC /* InvalidDNnameConstraintsTest12EE.crt */, + 4C7540E413D51D63008048AC /* InvalidDNnameConstraintsTest13EE.crt */, + 4C7540E513D51D63008048AC /* InvalidDNnameConstraintsTest15EE.crt */, + 4C7540E613D51D63008048AC /* InvalidDNnameConstraintsTest16EE.crt */, + 4C7540E713D51D63008048AC /* InvalidDNnameConstraintsTest17EE.crt */, + 4C7540E813D51D63008048AC /* InvalidDNnameConstraintsTest20EE.crt */, + 4C7540E913D51D63008048AC /* InvalidDNnameConstraintsTest2EE.crt */, + 4C7540EA13D51D63008048AC /* InvalidDNnameConstraintsTest3EE.crt */, + 4C7540EB13D51D63008048AC /* InvalidDNnameConstraintsTest7EE.crt */, + 4C7540EC13D51D63008048AC /* InvalidDNnameConstraintsTest8EE.crt */, + 4C7540ED13D51D63008048AC /* InvalidDNnameConstraintsTest9EE.crt */, + 4C7540EE13D51D63008048AC /* InvalidDSASignatureTest6EE.crt */, + 4C7540EF13D51D63008048AC /* InvalidEESignatureTest3EE.crt */, + 4C7540F013D51D63008048AC /* InvalidEEnotAfterDateTest6EE.crt */, + 4C7540F113D51D63008048AC /* InvalidEEnotBeforeDateTest2EE.crt */, + 4C7540F213D51D63008048AC /* InvalidLongSerialNumberTest18EE.crt */, + 4C7540F313D51D63008048AC /* InvalidMappingFromanyPolicyTest7EE.crt */, + 4C7540F413D51D63008048AC /* InvalidMappingToanyPolicyTest8EE.crt */, + 4C7540F513D51D63008048AC /* InvalidMissingbasicConstraintsTest1EE.crt */, + 4C7540F613D51D63008048AC /* InvalidNameChainingOrderTest2EE.crt */, + 4C7540F713D51D63008048AC /* InvalidNameChainingTest1EE.crt */, + 4C7540F813D51D63008048AC /* InvalidNegativeSerialNumberTest15EE.crt */, + 4C7540F913D51D63008048AC /* InvalidPolicyMappingTest10EE.crt */, + 4C7540FA13D51D63008048AC /* InvalidPolicyMappingTest2EE.crt */, + 4C7540FB13D51D63008048AC /* InvalidPolicyMappingTest4EE.crt */, + 4C7540FC13D51D63008048AC /* InvalidRFC822nameConstraintsTest22EE.crt */, + 4C7540FD13D51D63008048AC /* InvalidRFC822nameConstraintsTest24EE.crt */, + 4C7540FE13D51D63008048AC /* InvalidRFC822nameConstraintsTest26EE.crt */, + 4C7540FF13D51D63008048AC /* InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt */, + 4C75410013D51D63008048AC /* InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt */, + 4C75410113D51D63008048AC /* InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt */, + 4C75410213D51D63008048AC /* InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt */, + 4C75410313D51D63008048AC /* InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt */, + 4C75410413D51D63008048AC /* InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt */, + 4C75410513D51D63008048AC /* InvalidSelfIssuedpathLenConstraintTest16EE.crt */, + 4C75410613D51D63008048AC /* InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt */, + 4C75410713D51D63008048AC /* InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt */, + 4C75410813D51D63008048AC /* InvalidURInameConstraintsTest35EE.crt */, + 4C75410913D51D63008048AC /* InvalidURInameConstraintsTest37EE.crt */, + 4C75410A13D51D63008048AC /* InvalidUnknownCriticalCertificateExtensionTest2EE.crt */, + 4C75410B13D51D63008048AC /* InvalidcAFalseTest2EE.crt */, + 4C75410C13D51D63008048AC /* InvalidcAFalseTest3EE.crt */, + 4C75410D13D51D63008048AC /* InvalidcRLIssuerTest27EE.crt */, + 4C75410E13D51D63008048AC /* InvalidcRLIssuerTest31EE.crt */, + 4C75410F13D51D63008048AC /* InvalidcRLIssuerTest32EE.crt */, + 4C75411013D51D63008048AC /* InvalidcRLIssuerTest34EE.crt */, + 4C75411113D51D63008048AC /* InvalidcRLIssuerTest35EE.crt */, + 4C75411213D51D63008048AC /* InvalidinhibitAnyPolicyTest1EE.crt */, + 4C75411313D51D63008048AC /* InvalidinhibitAnyPolicyTest4EE.crt */, + 4C75411413D51D63008048AC /* InvalidinhibitAnyPolicyTest5EE.crt */, + 4C75411513D51D63008048AC /* InvalidinhibitAnyPolicyTest6EE.crt */, + 4C75411613D51D63008048AC /* InvalidinhibitPolicyMappingTest1EE.crt */, + 4C75411713D51D63008048AC /* InvalidinhibitPolicyMappingTest3EE.crt */, + 4C75411813D51D63008048AC /* InvalidinhibitPolicyMappingTest5EE.crt */, + 4C75411913D51D63008048AC /* InvalidinhibitPolicyMappingTest6EE.crt */, + 4C75411A13D51D63008048AC /* InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt */, + 4C75411B13D51D63008048AC /* InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt */, + 4C75411C13D51D63008048AC /* InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt */, + 4C75411D13D51D63008048AC /* InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt */, + 4C75411E13D51D63008048AC /* InvalidonlyContainsAttributeCertsTest14EE.crt */, + 4C75411F13D51D63008048AC /* InvalidonlyContainsCACertsTest12EE.crt */, + 4C75412013D51D63008048AC /* InvalidonlyContainsUserCertsTest11EE.crt */, + 4C75412113D51D63008048AC /* InvalidonlySomeReasonsTest15EE.crt */, + 4C75412213D51D63008048AC /* InvalidonlySomeReasonsTest16EE.crt */, + 4C75412313D51D63008048AC /* InvalidonlySomeReasonsTest17EE.crt */, + 4C75412413D51D63008048AC /* InvalidonlySomeReasonsTest20EE.crt */, + 4C75412513D51D63008048AC /* InvalidonlySomeReasonsTest21EE.crt */, + 4C75412613D51D63008048AC /* InvalidpathLenConstraintTest10EE.crt */, + 4C75412713D51D63008048AC /* InvalidpathLenConstraintTest11EE.crt */, + 4C75412813D51D63008048AC /* InvalidpathLenConstraintTest12EE.crt */, + 4C75412913D51D63008048AC /* InvalidpathLenConstraintTest5EE.crt */, + 4C75412A13D51D63008048AC /* InvalidpathLenConstraintTest6EE.crt */, + 4C75412B13D51D63008048AC /* InvalidpathLenConstraintTest9EE.crt */, + 4C75412C13D51D63008048AC /* Invalidpre2000UTCEEnotAfterDateTest7EE.crt */, + 4C75412D13D51D63008048AC /* InvalidrequireExplicitPolicyTest3EE.crt */, + 4C75412E13D51D63008048AC /* InvalidrequireExplicitPolicyTest5EE.crt */, + 4C75412F13D51D63008048AC /* LongSerialNumberCACert.crt */, + 4C75413013D51D63008048AC /* Mapping1to2CACert.crt */, + 4C75413113D51D63008048AC /* MappingFromanyPolicyCACert.crt */, + 4C75413213D51D63008048AC /* MappingToanyPolicyCACert.crt */, + 4C75413313D51D63008048AC /* MissingbasicConstraintsCACert.crt */, + 4C75413413D51D63008048AC /* NameOrderingCACert.crt */, + 4C75413513D51D63008048AC /* NegativeSerialNumberCACert.crt */, + 4C75413613D51D63008048AC /* NoCRLCACert.crt */, + 4C75413713D51D63008048AC /* NoPoliciesCACert.crt */, + 4C75413813D51D63008048AC /* NoissuingDistributionPointCACert.crt */, + 4C75413913D51D63008048AC /* OldCRLnextUpdateCACert.crt */, + 4C75413A13D51D63008048AC /* OverlappingPoliciesTest6EE.crt */, + 4C75413B13D51D63008048AC /* P12Mapping1to3CACert.crt */, + 4C75413C13D51D63008048AC /* P12Mapping1to3subCACert.crt */, + 4C75413D13D51D63008048AC /* P12Mapping1to3subsubCACert.crt */, + 4C75413E13D51D63008048AC /* P1Mapping1to234CACert.crt */, + 4C75413F13D51D63008048AC /* P1Mapping1to234subCACert.crt */, + 4C75414013D51D63008048AC /* P1anyPolicyMapping1to2CACert.crt */, + 4C75414113D51D63008048AC /* PanyPolicyMapping1to2CACert.crt */, + 4C75414213D51D63008048AC /* PoliciesP1234CACert.crt */, + 4C75414313D51D63008048AC /* PoliciesP1234subCAP123Cert.crt */, + 4C75414413D51D63008048AC /* PoliciesP1234subsubCAP123P12Cert.crt */, + 4C75414513D51D63008048AC /* PoliciesP123CACert.crt */, + 4C75414613D51D63008048AC /* PoliciesP123subCAP12Cert.crt */, + 4C75414713D51D63008048AC /* PoliciesP123subsubCAP12P1Cert.crt */, + 4C75414813D51D63008048AC /* PoliciesP123subsubCAP12P2Cert.crt */, + 4C75414913D51D63008048AC /* PoliciesP123subsubsubCAP12P2P1Cert.crt */, + 4C75414A13D51D63008048AC /* PoliciesP12CACert.crt */, + 4C75414B13D51D63008048AC /* PoliciesP12subCAP1Cert.crt */, + 4C75414C13D51D63008048AC /* PoliciesP12subsubCAP1P2Cert.crt */, + 4C75414D13D51D63008048AC /* PoliciesP2subCA2Cert.crt */, + 4C75414E13D51D63008048AC /* PoliciesP2subCACert.crt */, + 4C75414F13D51D63008048AC /* PoliciesP3CACert.crt */, + 4C75415013D51D63008048AC /* RFC3280MandatoryAttributeTypesCACert.crt */, + 4C75415113D51D63008048AC /* RFC3280OptionalAttributeTypesCACert.crt */, + 4C75415213D51D63008048AC /* RevokedsubCACert.crt */, + 4C75415313D51D63008048AC /* RolloverfromPrintableStringtoUTF8StringCACert.crt */, + 4C75415413D51D63008048AC /* SeparateCertificateandCRLKeysCA2CRLSigningCert.crt */, + 4C75415513D51D63008048AC /* SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt */, + 4C75415613D51D63008048AC /* SeparateCertificateandCRLKeysCertificateSigningCACert.crt */, + 4C75415713D51D63008048AC /* TrustAnchorRootCertificate.crt */, + 4C75415813D51D63008048AC /* TwoCRLsCACert.crt */, + 4C75415913D51D63008048AC /* UIDCACert.crt */, + 4C75415A13D51D63008048AC /* UTF8StringCaseInsensitiveMatchCACert.crt */, + 4C75415B13D51D63008048AC /* UTF8StringEncodedNamesCACert.crt */, + 4C75415C13D51D63008048AC /* UnknownCRLEntryExtensionCACert.crt */, + 4C75415D13D51D63008048AC /* UnknownCRLExtensionCACert.crt */, + 4C75415E13D51D63008048AC /* UserNoticeQualifierTest15EE.crt */, + 4C75415F13D51D63008048AC /* UserNoticeQualifierTest16EE.crt */, + 4C75416013D51D63008048AC /* UserNoticeQualifierTest17EE.crt */, + 4C75416113D51D63008048AC /* UserNoticeQualifierTest18EE.crt */, + 4C75416213D51D63008048AC /* UserNoticeQualifierTest19EE.crt */, + 4C75416313D51D63008048AC /* ValidBasicSelfIssuedNewWithOldTest3EE.crt */, + 4C75416413D51D63008048AC /* ValidBasicSelfIssuedNewWithOldTest4EE.crt */, + 4C75416513D51D63008048AC /* ValidBasicSelfIssuedOldWithNewTest1EE.crt */, + 4C75416613D51D63008048AC /* ValidCertificatePathTest1EE.crt */, + 4C75416713D51D63008048AC /* ValidDNSnameConstraintsTest30EE.crt */, + 4C75416813D51D63008048AC /* ValidDNSnameConstraintsTest32EE.crt */, + 4C75416913D51D63008048AC /* ValidDNandRFC822nameConstraintsTest27EE.crt */, + 4C75416A13D51D63008048AC /* ValidDNnameConstraintsTest11EE.crt */, + 4C75416B13D51D63008048AC /* ValidDNnameConstraintsTest14EE.crt */, + 4C75416C13D51D63008048AC /* ValidDNnameConstraintsTest18EE.crt */, + 4C75416D13D51D63008048AC /* ValidDNnameConstraintsTest19EE.crt */, + 4C75416E13D51D63008048AC /* ValidDNnameConstraintsTest1EE.crt */, + 4C75416F13D51D63008048AC /* ValidDNnameConstraintsTest4EE.crt */, + 4C75417013D51D63008048AC /* ValidDNnameConstraintsTest5EE.crt */, + 4C75417113D51D63008048AC /* ValidDNnameConstraintsTest6EE.crt */, + 4C75417213D51D63008048AC /* ValidDSAParameterInheritanceTest5EE.crt */, + 4C75417313D51D63008048AC /* ValidDSASignaturesTest4EE.crt */, + 4C75417413D51D63008048AC /* ValidGeneralizedTimenotAfterDateTest8EE.crt */, + 4C75417513D51D63008048AC /* ValidGeneralizedTimenotBeforeDateTest4EE.crt */, + 4C75417613D51D63008048AC /* ValidLongSerialNumberTest16EE.crt */, + 4C75417713D51D63008048AC /* ValidLongSerialNumberTest17EE.crt */, + 4C75417813D51D63008048AC /* ValidNameChainingCapitalizationTest5EE.crt */, + 4C75417913D51D63008048AC /* ValidNameChainingWhitespaceTest3EE.crt */, + 4C75417A13D51D63008048AC /* ValidNameChainingWhitespaceTest4EE.crt */, + 4C75417B13D51D63008048AC /* ValidNameUIDsTest6EE.crt */, + 4C75417C13D51D63008048AC /* ValidNegativeSerialNumberTest14EE.crt */, + 4C75417D13D51D63008048AC /* ValidPolicyMappingTest11EE.crt */, + 4C75417E13D51D63008048AC /* ValidPolicyMappingTest12EE.crt */, + 4C75417F13D51D63008048AC /* ValidPolicyMappingTest13EE.crt */, + 4C75418013D51D63008048AC /* ValidPolicyMappingTest14EE.crt */, + 4C75418113D51D63008048AC /* ValidPolicyMappingTest1EE.crt */, + 4C75418213D51D63008048AC /* ValidPolicyMappingTest3EE.crt */, + 4C75418313D51D63008048AC /* ValidPolicyMappingTest5EE.crt */, + 4C75418413D51D63008048AC /* ValidPolicyMappingTest6EE.crt */, + 4C75418513D51D63008048AC /* ValidPolicyMappingTest9EE.crt */, + 4C75418613D51D63008048AC /* ValidRFC3280MandatoryAttributeTypesTest7EE.crt */, + 4C75418713D51D63008048AC /* ValidRFC3280OptionalAttributeTypesTest8EE.crt */, + 4C75418813D51D63008048AC /* ValidRFC822nameConstraintsTest21EE.crt */, + 4C75418913D51D63008048AC /* ValidRFC822nameConstraintsTest23EE.crt */, + 4C75418A13D51D63008048AC /* ValidRFC822nameConstraintsTest25EE.crt */, + 4C75418B13D51D63008048AC /* ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt */, + 4C75418C13D51D63008048AC /* ValidSelfIssuedinhibitAnyPolicyTest7EE.crt */, + 4C75418D13D51D63008048AC /* ValidSelfIssuedinhibitAnyPolicyTest9EE.crt */, + 4C75418E13D51D63008048AC /* ValidSelfIssuedinhibitPolicyMappingTest7EE.crt */, + 4C75418F13D51D63008048AC /* ValidSelfIssuedpathLenConstraintTest15EE.crt */, + 4C75419013D51D63008048AC /* ValidSelfIssuedpathLenConstraintTest17EE.crt */, + 4C75419113D51D63008048AC /* ValidSelfIssuedrequireExplicitPolicyTest6EE.crt */, + 4C75419213D51D63008048AC /* ValidURInameConstraintsTest34EE.crt */, + 4C75419313D51D63008048AC /* ValidURInameConstraintsTest36EE.crt */, + 4C75419413D51D63008048AC /* ValidUTF8StringCaseInsensitiveMatchTest11EE.crt */, + 4C75419513D51D63008048AC /* ValidUTF8StringEncodedNamesTest9EE.crt */, + 4C75419613D51D63008048AC /* ValidUnknownNotCriticalCertificateExtensionTest1EE.crt */, + 4C75419713D51D63008048AC /* ValidbasicConstraintsNotCriticalTest4EE.crt */, + 4C75419813D51D63008048AC /* ValidcRLIssuerTest28EE.crt */, + 4C75419913D51D63008048AC /* ValidcRLIssuerTest29EE.crt */, + 4C75419A13D51D63008048AC /* ValidcRLIssuerTest30EE.crt */, + 4C75419B13D51D63008048AC /* ValidcRLIssuerTest33EE.crt */, + 4C75419C13D51D63008048AC /* ValidinhibitAnyPolicyTest2EE.crt */, + 4C75419D13D51D63008048AC /* ValidinhibitPolicyMappingTest2EE.crt */, + 4C75419E13D51D63008048AC /* ValidinhibitPolicyMappingTest4EE.crt */, + 4C75419F13D51D63008048AC /* ValidkeyUsageNotCriticalTest3EE.crt */, + 4C7541A013D51D63008048AC /* ValidonlyContainsCACertsTest13EE.crt */, + 4C7541A113D51D63008048AC /* ValidonlySomeReasonsTest18EE.crt */, + 4C7541A213D51D63008048AC /* ValidonlySomeReasonsTest19EE.crt */, + 4C7541A313D51D63008048AC /* ValidpathLenConstraintTest13EE.crt */, + 4C7541A413D51D63008048AC /* ValidpathLenConstraintTest14EE.crt */, + 4C7541A513D51D63008048AC /* ValidpathLenConstraintTest7EE.crt */, + 4C7541A613D51D63008048AC /* ValidpathLenConstraintTest8EE.crt */, + 4C7541A713D51D63008048AC /* Validpre2000UTCnotBeforeDateTest3EE.crt */, + 4C7541A813D51D63008048AC /* ValidrequireExplicitPolicyTest1EE.crt */, + 4C7541A913D51D63008048AC /* ValidrequireExplicitPolicyTest2EE.crt */, + 4C7541AA13D51D63008048AC /* ValidrequireExplicitPolicyTest4EE.crt */, + 4C7541AB13D51D63008048AC /* WrongCRLCACert.crt */, + 4C7541AC13D51D63008048AC /* anyPolicyCACert.crt */, + 4C7541AD13D51D63008048AC /* basicConstraintsCriticalcAFalseCACert.crt */, + 4C7541AE13D51D63008048AC /* basicConstraintsNotCriticalCACert.crt */, + 4C7541AF13D51D63008048AC /* basicConstraintsNotCriticalcAFalseCACert.crt */, + 4C7541B013D51D63008048AC /* deltaCRLCA1Cert.crt */, + 4C7541B113D51D63008048AC /* deltaCRLCA2Cert.crt */, + 4C7541B213D51D63008048AC /* deltaCRLCA3Cert.crt */, + 4C7541B313D51D63008048AC /* deltaCRLIndicatorNoBaseCACert.crt */, + 4C7541B413D51D63008048AC /* distributionPoint1CACert.crt */, + 4C7541B513D51D63008048AC /* distributionPoint2CACert.crt */, + 4C7541B613D51D63008048AC /* indirectCRLCA1Cert.crt */, + 4C7541B713D51D63008048AC /* indirectCRLCA2Cert.crt */, + 4C7541B813D51D63008048AC /* indirectCRLCA3Cert.crt */, + 4C7541B913D51D63008048AC /* indirectCRLCA3cRLIssuerCert.crt */, + 4C7541BA13D51D63008048AC /* indirectCRLCA4Cert.crt */, + 4C7541BB13D51D63008048AC /* indirectCRLCA4cRLIssuerCert.crt */, + 4C7541BC13D51D63008048AC /* indirectCRLCA5Cert.crt */, + 4C7541BD13D51D63008048AC /* indirectCRLCA6Cert.crt */, + 4C7541BE13D51D63008048AC /* inhibitAnyPolicy0CACert.crt */, + 4C7541BF13D51D63008048AC /* inhibitAnyPolicy1CACert.crt */, + 4C7541C013D51D63008048AC /* inhibitAnyPolicy1SelfIssuedCACert.crt */, + 4C7541C113D51D63008048AC /* inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt */, + 4C7541C213D51D63008048AC /* inhibitAnyPolicy1subCA1Cert.crt */, + 4C7541C313D51D63008048AC /* inhibitAnyPolicy1subCA2Cert.crt */, + 4C7541C413D51D63008048AC /* inhibitAnyPolicy1subCAIAP5Cert.crt */, + 4C7541C513D51D63008048AC /* inhibitAnyPolicy1subsubCA2Cert.crt */, + 4C7541C613D51D63008048AC /* inhibitAnyPolicy5CACert.crt */, + 4C7541C713D51D63008048AC /* inhibitAnyPolicy5subCACert.crt */, + 4C7541C813D51D63008048AC /* inhibitAnyPolicy5subsubCACert.crt */, + 4C7541C913D51D63008048AC /* inhibitAnyPolicyTest3EE.crt */, + 4C7541CA13D51D63008048AC /* inhibitPolicyMapping0CACert.crt */, + 4C7541CB13D51D63008048AC /* inhibitPolicyMapping0subCACert.crt */, + 4C7541CC13D51D63008048AC /* inhibitPolicyMapping1P12CACert.crt */, + 4C7541CD13D51D63008048AC /* inhibitPolicyMapping1P12subCACert.crt */, + 4C7541CE13D51D63008048AC /* inhibitPolicyMapping1P12subCAIPM5Cert.crt */, + 4C7541CF13D51D63008048AC /* inhibitPolicyMapping1P12subsubCACert.crt */, + 4C7541D013D51D63008048AC /* inhibitPolicyMapping1P12subsubCAIPM5Cert.crt */, + 4C7541D113D51D63008048AC /* inhibitPolicyMapping1P1CACert.crt */, + 4C7541D213D51D63008048AC /* inhibitPolicyMapping1P1SelfIssuedCACert.crt */, + 4C7541D313D51D63008048AC /* inhibitPolicyMapping1P1SelfIssuedsubCACert.crt */, + 4C7541D413D51D63008048AC /* inhibitPolicyMapping1P1subCACert.crt */, + 4C7541D513D51D63008048AC /* inhibitPolicyMapping1P1subsubCACert.crt */, + 4C7541D613D51D63008048AC /* inhibitPolicyMapping5CACert.crt */, + 4C7541D713D51D63008048AC /* inhibitPolicyMapping5subCACert.crt */, + 4C7541D813D51D63008048AC /* inhibitPolicyMapping5subsubCACert.crt */, + 4C7541D913D51D63008048AC /* inhibitPolicyMapping5subsubsubCACert.crt */, + 4C7541DA13D51D63008048AC /* keyUsageCriticalcRLSignFalseCACert.crt */, + 4C7541DB13D51D63008048AC /* keyUsageCriticalkeyCertSignFalseCACert.crt */, + 4C7541DC13D51D63008048AC /* keyUsageNotCriticalCACert.crt */, + 4C7541DD13D51D63008048AC /* keyUsageNotCriticalcRLSignFalseCACert.crt */, + 4C7541DE13D51D63008048AC /* keyUsageNotCriticalkeyCertSignFalseCACert.crt */, + 4C7541DF13D51D63008048AC /* nameConstraintsDN1CACert.crt */, + 4C7541E013D51D63008048AC /* nameConstraintsDN1SelfIssuedCACert.crt */, + 4C7541E113D51D63008048AC /* nameConstraintsDN1subCA1Cert.crt */, + 4C7541E213D51D63008048AC /* nameConstraintsDN1subCA2Cert.crt */, + 4C7541E313D51D63008048AC /* nameConstraintsDN1subCA3Cert.crt */, + 4C7541E413D51D63008048AC /* nameConstraintsDN2CACert.crt */, + 4C7541E513D51D63008048AC /* nameConstraintsDN3CACert.crt */, + 4C7541E613D51D63008048AC /* nameConstraintsDN3subCA1Cert.crt */, + 4C7541E713D51D63008048AC /* nameConstraintsDN3subCA2Cert.crt */, + 4C7541E813D51D63008048AC /* nameConstraintsDN4CACert.crt */, + 4C7541E913D51D63008048AC /* nameConstraintsDN5CACert.crt */, + 4C7541EA13D51D63008048AC /* nameConstraintsDNS1CACert.crt */, + 4C7541EB13D51D63008048AC /* nameConstraintsDNS2CACert.crt */, + 4C7541EC13D51D63008048AC /* nameConstraintsRFC822CA1Cert.crt */, + 4C7541ED13D51D63008048AC /* nameConstraintsRFC822CA2Cert.crt */, + 4C7541EE13D51D63008048AC /* nameConstraintsRFC822CA3Cert.crt */, + 4C7541EF13D51D63008048AC /* nameConstraintsURI1CACert.crt */, + 4C7541F013D51D63008048AC /* nameConstraintsURI2CACert.crt */, + 4C7541F113D51D63008048AC /* onlyContainsAttributeCertsCACert.crt */, + 4C7541F213D51D63008048AC /* onlyContainsCACertsCACert.crt */, + 4C7541F313D51D63008048AC /* onlyContainsUserCertsCACert.crt */, + 4C7541F413D51D63008048AC /* onlySomeReasonsCA1Cert.crt */, + 4C7541F513D51D63008048AC /* onlySomeReasonsCA2Cert.crt */, + 4C7541F613D51D63008048AC /* onlySomeReasonsCA3Cert.crt */, + 4C7541F713D51D63008048AC /* onlySomeReasonsCA4Cert.crt */, + 4C7541F813D51D63008048AC /* pathLenConstraint0CACert.crt */, + 4C7541F913D51D63008048AC /* pathLenConstraint0SelfIssuedCACert.crt */, + 4C7541FA13D51D63008048AC /* pathLenConstraint0subCA2Cert.crt */, + 4C7541FB13D51D63008048AC /* pathLenConstraint0subCACert.crt */, + 4C7541FC13D51D63008048AC /* pathLenConstraint1CACert.crt */, + 4C7541FD13D51D63008048AC /* pathLenConstraint1SelfIssuedCACert.crt */, + 4C7541FE13D51D63008048AC /* pathLenConstraint1SelfIssuedsubCACert.crt */, + 4C7541FF13D51D63008048AC /* pathLenConstraint1subCACert.crt */, + 4C75420013D51D64008048AC /* pathLenConstraint6CACert.crt */, + 4C75420113D51D64008048AC /* pathLenConstraint6subCA0Cert.crt */, + 4C75420213D51D64008048AC /* pathLenConstraint6subCA1Cert.crt */, + 4C75420313D51D64008048AC /* pathLenConstraint6subCA4Cert.crt */, + 4C75420413D51D64008048AC /* pathLenConstraint6subsubCA00Cert.crt */, + 4C75420513D51D64008048AC /* pathLenConstraint6subsubCA11Cert.crt */, + 4C75420613D51D64008048AC /* pathLenConstraint6subsubCA41Cert.crt */, + 4C75420713D51D64008048AC /* pathLenConstraint6subsubsubCA11XCert.crt */, + 4C75420813D51D64008048AC /* pathLenConstraint6subsubsubCA41XCert.crt */, + 4C75420913D51D64008048AC /* pre2000CRLnextUpdateCACert.crt */, + 4C75420A13D51D64008048AC /* requireExplicitPolicy0CACert.crt */, + 4C75420B13D51D64008048AC /* requireExplicitPolicy0subCACert.crt */, + 4C75420C13D51D64008048AC /* requireExplicitPolicy0subsubCACert.crt */, + 4C75420D13D51D64008048AC /* requireExplicitPolicy0subsubsubCACert.crt */, + 4C75420E13D51D64008048AC /* requireExplicitPolicy10CACert.crt */, + 4C75420F13D51D64008048AC /* requireExplicitPolicy10subCACert.crt */, + 4C75421013D51D64008048AC /* requireExplicitPolicy10subsubCACert.crt */, + 4C75421113D51D64008048AC /* requireExplicitPolicy10subsubsubCACert.crt */, + 4C75421213D51D64008048AC /* requireExplicitPolicy2CACert.crt */, + 4C75421313D51D64008048AC /* requireExplicitPolicy2SelfIssuedCACert.crt */, + 4C75421413D51D64008048AC /* requireExplicitPolicy2SelfIssuedsubCACert.crt */, + 4C75421513D51D64008048AC /* requireExplicitPolicy2subCACert.crt */, + 4C75421613D51D64008048AC /* requireExplicitPolicy4CACert.crt */, + 4C75421713D51D64008048AC /* requireExplicitPolicy4subCACert.crt */, + 4C75421813D51D64008048AC /* requireExplicitPolicy4subsubCACert.crt */, + 4C75421913D51D64008048AC /* requireExplicitPolicy4subsubsubCACert.crt */, + 4C75421A13D51D64008048AC /* requireExplicitPolicy5CACert.crt */, + 4C75421B13D51D64008048AC /* requireExplicitPolicy5subCACert.crt */, + 4C75421C13D51D64008048AC /* requireExplicitPolicy5subsubCACert.crt */, + 4C75421D13D51D64008048AC /* requireExplicitPolicy5subsubsubCACert.crt */, + 4C75421E13D51D64008048AC /* requireExplicitPolicy7CACert.crt */, + 4C75421F13D51D64008048AC /* requireExplicitPolicy7subCARE2Cert.crt */, + 4C75422013D51D64008048AC /* requireExplicitPolicy7subsubCARE2RE4Cert.crt */, + 4C75422113D51D64008048AC /* requireExplicitPolicy7subsubsubCARE2RE4Cert.crt */, + ); + path = "nist-certs"; sourceTree = ""; }; - 1879B533146DDBE5007E536C /* Products */ = { + 4C8786A20B03E05D00BB77D4 /* Products */ = { isa = PBXGroup; children = ( - 1879B538146DDBE5007E536C /* libsecurity_utilities.a */, + 4C8786AD0B03E05E00BB77D4 /* libDER.a */, + 4C8786AF0B03E05E00BB77D4 /* parseCert */, + 4C8786B10B03E05E00BB77D4 /* libDERUtils.a */, + 4C8786B30B03E05E00BB77D4 /* parseCrl */, + 4C0789C2113F4C7400422E2D /* parseTicket */, ); name = Products; sourceTree = ""; }; - 1879B548146DE212007E536C /* Products */ = { + 4C8BC620097DBC1B00C781D5 /* Libraries */ = { isa = PBXGroup; children = ( - 1879B54F146DE212007E536C /* libsecurity_cdsa_utils.a */, - ); - name = Products; + E7D690911652E06A0079537A /* libMobileGestalt.dylib */, + E7AAB5F415929493005C8BCC /* libcorecrypto.dylib */, + 0CC82947138716F400BD99B7 /* libregressions.a */, + 4CA692640DA4027F001094C2 /* libCMS.a */, + 798B7FD40D3D7B5400AC1D04 /* libASN1.a */, + 4C8786D90B03E1BC00BB77D4 /* libDER.a */, + 4CB740680A4749C800D641BB /* libsqlite3.dylib */, + 4C60F1C409BE27E300B4040C /* CoreFoundation.framework */, + 4CF730310EF9CDE300E17471 /* CFNetwork.framework */, + 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */, + 52222CC0167BDAE100EDD09C /* SpringBoardServices.framework */, + 107227350D91FE89003CF14F /* libbsm.dylib */, + ); + name = Libraries; sourceTree = ""; }; - 1879B551146DE227007E536C /* Products */ = { + 4C922CB2097F1984004CEEBD /* Security */ = { isa = PBXGroup; children = ( - 1879B55A146DE227007E536C /* libsecurity_cdsa_utilities.a */, - 1879B55C146DE227007E536C /* Schemas */, + 4C28BCD60986EBCB0020C665 /* certextensions.h */, + 79EF5B720D3D6AFE009F5270 /* p12import.h */, + 795CA9CC0D38435E00BAE6A2 /* p12pbegen.h */, + 8E02FA691107BE460043545E /* pbkdf2.h */, + 443381D918A3D81400215606 /* SecAccessControl.h */, + 443381DA18A3D81400215606 /* SecAccessControlPriv.h */, + 4C696B3709BFA94F000CBC75 /* SecBase.h */, + 18351B8F14CB65870097860E /* SecBase64.h */, + 4C0208F80D3C154200BFE54E /* SecBasePriv.h */, + 4C8FD03D099D5C91006867B6 /* SecCertificate.h */, + 4CEF4CA70C5551FE00062475 /* SecCertificateInternal.h */, + 4CF41D0A0BBB4022005F3248 /* SecCertificatePath.h */, + 4C7608B10AC34A8100980096 /* SecCertificatePriv.h */, + 791766DD0DD0162C00F3B974 /* SecCertificateRequest.h */, + 79BDD3C00D60DB84000D84D3 /* SecCMS.h */, + 7940D4110C3ACF9000FDB5D8 /* SecDH.h */, + 4CD3BA601106FF4D00BE8B75 /* SecECKey.h */, + 78F92F10195128D70023B54B /* SecECKeyPriv.h */, + 4C0B906C0ACCBD240077CD03 /* SecFramework.h */, + 4C8E99C20FC601D50072EB4C /* SecFrameworkStrings.h */, + 4CAC87D60B8F82720009C9FC /* SecIdentity.h */, + 4CCE0AD90D41797400DDBB21 /* SecIdentityPriv.h */, + 79EF5B6C0D3D6A31009F5270 /* SecImportExport.h */, + 4C6416F00BB357D5001C83FD /* SecInternal.h */, + 4CF0484A0A5D988F00268236 /* SecItem.h */, + 4C97DD160AA65A94003FC05C /* SecItemConstants.c */, + 4CEDF7370F3A6CFB0027C4FE /* SecItemInternal.h */, + 4CF0487F0A5F016300268236 /* SecItemPriv.h */, + 4C7072840AC9EA4E007CC205 /* SecKey.h */, + 4C04A90811924BBC0020550C /* SecKeyInternal.h */, + 4C7072D30AC9ED5A007CC205 /* SecKeyPriv.h */, + 4AF7FFF315AFB73800B9D400 /* SecOTR.h */, + 4AF7FFF415AFB73800B9D400 /* SecOTRDHKey.h */, + 4AF7FFF515AFB73800B9D400 /* SecOTRErrors.h */, + 4AF7FFF615AFB73800B9D400 /* SecOTRIdentityPriv.h */, + 4AF7FFF715AFB73800B9D400 /* SecOTRMath.h */, + 4AF7FFF915AFB73800B9D400 /* SecOTRPacketData.h */, + 4AF7FFFA15AFB73800B9D400 /* SecOTRPackets.h */, + 4AF7FFFB15AFB73800B9D400 /* SecOTRSession.h */, + 4AF7FFFC15AFB73800B9D400 /* SecOTRSessionPriv.h */, + CDDE9BC31729AB910013B0E8 /* SecPasswordGenerate.h */, + 8ED6F6C8110904E300D2B368 /* SecPBKDF.h */, + 4CBA0E860BB33C0000E72B55 /* SecPolicy.h */, + 4CFBF5F10D5A92E100969BBE /* SecPolicyInternal.h */, + 4C6416D40BB34F00001C83FD /* SecPolicyPriv.h */, + 4C2F81D40BF121D2003C4F77 /* SecRandom.h */, + 4C7073C80ACB2BAD007CC205 /* SecRSAKey.h */, + 4C9A19890B95118F000A1399 /* SecRSAKeyPriv.h */, + 4C7416020F1D71A2008E0E4D /* SecSCEP.h */, + E7676DB519411DF300498DD4 /* SecServerEncryptionSupport.h */, + BE061FE01899ECEE00C739F6 /* SecSharedCredential.h */, + 4C8FD03E099D5C91006867B6 /* SecTrust.h */, + 4C87F3A70D611C26000E7104 /* SecTrustPriv.h */, + 4C4296300BB0A68200491999 /* SecTrustSettings.h */, + 4C12828C0BB4957D00985BB0 /* SecTrustSettingsPriv.h */, + 4C1B442C0BB9CAF900461B82 /* SecTrustStore.h */, + 4C64E00B0B8FBBF3009B306C /* Security.h */, + 4C7391770B01745000C4CBFA /* vmdh.h */, ); - name = Products; + name = Security; + path = Security/sec/Security; sourceTree = ""; }; - 1879B55E146DE244007E536C /* Products */ = { + 4C999BA00AB5F0BB0010451D /* ntlm */ = { isa = PBXGroup; children = ( - 1879B565146DE244007E536C /* libsecurity_cssm.a */, + 4C999BA10AB5F0BB0010451D /* NtlmGenerator.c */, + 4C999BA20AB5F0BB0010451D /* NtlmGenerator.h */, + 4C999BA30AB5F0BB0010451D /* ntlmBlobPriv.c */, + 4C999BA40AB5F0BB0010451D /* ntlmBlobPriv.h */, ); - name = Products; + path = ntlm; sourceTree = ""; }; - 1879B5BD146DE6C8007E536C /* Products */ = { + 4CB740FA0A47580400D641BB /* SecurityTool */ = { isa = PBXGroup; children = ( - 1879B5C6146DE6C8007E536C /* libsecurity_apple_csp.a */, + 4C4CB7100DDA44900026B660 /* entitlements.plist */, + E7104A0B169E171900DB0045 /* security_tool_commands.c */, + E7FEFB80169E26E200E18152 /* sub_commands.h */, ); - name = Products; + path = SecurityTool; sourceTree = ""; }; - 1879B5CA146DE6CE007E536C /* Products */ = { + 4CE5A55609C7970A00D27A3F /* sslViewer */ = { isa = PBXGroup; children = ( - 1879B5D2146DE6CE007E536C /* libsecurity_apple_cspdl.a */, - ); - name = Products; + 4C9DE9E21181AC8300CF5C27 /* sslEcdsa.cpp */, + 4CA880C20DDBC87200D9A0F2 /* sslServer-entitlements.plist */, + 4CA880C30DDBC87200D9A0F2 /* sslViewer-entitlements.plist */, + 4CCE0AE10D417A2700DDBB21 /* sslAppUtils.h */, + 7913B1DF0D17280500601FE9 /* sslServer.cpp */, + 4CE5A65809C79E0600D27A3F /* ioSock.c */, + 4CE5A65909C79E0600D27A3F /* ioSock.h */, + 4CE5A65A09C79E0600D27A3F /* sslAppUtils.cpp */, + 4CE5A65B09C79E0600D27A3F /* sslClient.cpp */, + 4CE5A65C09C79E0600D27A3F /* sslServe.cpp */, + 4CE5A65D09C79E0600D27A3F /* sslThreading.h */, + 4CE5A55709C7970A00D27A3F /* SSLViewer.cpp */, + 4CE5A55809C7970A00D27A3F /* SSL_Sites */, + 4CE5A55909C7970A00D27A3F /* pingSslSites */, + 4CE5A55A09C7970A00D27A3F /* verifyPing */, + ); + path = sslViewer; sourceTree = ""; }; - 1879B5D6146DE6D7007E536C /* Products */ = { + 52D82BE016A621F70078DFE5 /* CloudKeychainProxy */ = { isa = PBXGroup; children = ( - 1879B5DE146DE6D7007E536C /* libsecurity_apple_file_dl.a */, + 52D82BF716A6283F0078DFE5 /* ckdmain.m */, + 52D82BE116A621F70078DFE5 /* Supporting Files */, ); - name = Products; + path = CloudKeychainProxy; sourceTree = ""; }; - 1879B5E2146DE6E7007E536C /* Products */ = { + 52D82BE116A621F70078DFE5 /* Supporting Files */ = { isa = PBXGroup; children = ( - 1879B5EB146DE6E8007E536C /* libsecurity_apple_x509_cl.a */, - 1879B5EF146DE6E8007E536C /* apple_x509_cl.bundle */, + 52D82BE216A621F70078DFE5 /* CloudKeychainProxy-Info.plist */, + 52D82BE316A621F70078DFE5 /* InfoPlist.strings */, + 52222D2C16A5CBCC00EDD09C /* com.apple.security.cloudkeychainproxy.plist */, + 52D82BE616A621F70078DFE5 /* AspenFamily.xcconfig */, ); - name = Products; + name = "Supporting Files"; sourceTree = ""; }; - 1879B5F1146DE6FD007E536C /* Products */ = { + 52DE816E1636347500F49F0C /* Keychain */ = { isa = PBXGroup; children = ( - 1879B5F9146DE6FD007E536C /* libsecurity_apple_x509_tp.a */, + 0CD72A5B16D5769A00A4B8A3 /* utilities.c */, + 0CD72A5C16D5769A00A4B8A3 /* utilities.h */, + 5208F4CD16702D8800A49DDA /* CircleStatusView.h */, + 5208F4CE16702D8800A49DDA /* CircleStatusView.m */, + 5208F4BB1670027400A49DDA /* SyncViewController.h */, + 5208F4BC1670027400A49DDA /* SyncViewController.m */, + 520C98E7162485CA00A7C80B /* QuartzCore.framework */, + 52B35B051623753000B97D06 /* Security.framework */, + 52DE816F1636347500F49F0C /* Supporting Files */, + 52704B7D1638F4EB007FEBB0 /* KeychainKeys.png */, + 5264FB4C163674B50005D258 /* MyKeychain.h */, + 5264FB4D163674B50005D258 /* MyKeychain.m */, + 52DE819D16363C1A00F49F0C /* KeychainItemCell.h */, + 52DE819E16363C1A00F49F0C /* KeychainItemCell.m */, + E75112E9166EFBF0008C578B /* PeerListCell.h */, + E75112EA166EFBF0008C578B /* PeerListCell.m */, + 52DE819A163636B900F49F0C /* KCATableViewController.h */, + 52DE819B163636B900F49F0C /* KCATableViewController.m */, + 52CD69F916384C1F00961848 /* KCAItemDetailViewController.h */, + 52CD69FA16384C2000961848 /* KCAItemDetailViewController.m */, + 52DE81771636347600F49F0C /* AppDelegate.h */, + 52DE81781636347600F49F0C /* AppDelegate.m */, + 52DE81861636347600F49F0C /* FirstViewController.h */, + 52DE81871636347600F49F0C /* FirstViewController.m */, + 52DE81891636347600F49F0C /* first.png */, + 52DE818B1636347600F49F0C /* first@2x.png */, + 52DE818D1636347600F49F0C /* ToolsViewController.h */, + 52DE818E1636347600F49F0C /* ToolsViewController.m */, + 52DE81901636347600F49F0C /* second.png */, + 52DE81921636347600F49F0C /* second@2x.png */, + 52704B7F1638F610007FEBB0 /* NewPasswordViewController.h */, + 52704B801638F610007FEBB0 /* NewPasswordViewController.m */, + 52704B82163905EE007FEBB0 /* EditItemViewController.h */, + 52704B83163905EE007FEBB0 /* EditItemViewController.m */, + 529990551661BADF00C297A2 /* DeviceItemCell.h */, + 529990561661BADF00C297A2 /* DeviceItemCell.m */, + 529990521661BA2600C297A2 /* DeviceTableViewController.h */, + 529990531661BA2600C297A2 /* DeviceTableViewController.m */, + 52F63A1E1659F04E0076D2DE /* DeviceViewController.h */, + 52F63A1F1659F04E0076D2DE /* DeviceViewController.m */, ); - name = Products; + path = Keychain; sourceTree = ""; }; - 1879B5FD146DE704007E536C /* Products */ = { + 52DE816F1636347500F49F0C /* Supporting Files */ = { isa = PBXGroup; children = ( - 1885B3F914D8D9B100519375 /* libASN1.a */, + 527435A916A9E6D1001A96FF /* Keychain_57x57.png */, + 527435AB16A9E6DB001A96FF /* Keychain_114x114.png */, + 527435AD16A9E6E5001A96FF /* Keychain_72x72.png */, + 527435AF16A9E6E9001A96FF /* Keychain_144x144.png */, + 52DE81701636347500F49F0C /* Keychain-Info.plist */, + 52704B871639193F007FEBB0 /* Keychain-Entitlements.plist */, + 52DE81741636347500F49F0C /* main.m */, + 52DE817A1636347600F49F0C /* Default.png */, + 52DE817C1636347600F49F0C /* Default@2x.png */, + 52DE817E1636347600F49F0C /* Default-568h@2x.png */, ); - name = Products; + name = "Supporting Files"; sourceTree = ""; }; - 1879B60A146DE70A007E536C /* Products */ = { + 5346480317331E1200FE9172 /* KeychainSyncAccountNotification */ = { isa = PBXGroup; children = ( - 1879B612146DE70A007E536C /* libsecurity_authorization.a */, + 5346481C173322BD00FE9172 /* KeychainSyncAccountNotification.h */, + 5346481D173322BD00FE9172 /* KeychainSyncAccountNotification.m */, + 5346480417331E1200FE9172 /* Supporting Files */, ); - name = Products; + path = KeychainSyncAccountNotification; sourceTree = ""; }; - 1879B616146DE715007E536C /* Products */ = { + 5346480417331E1200FE9172 /* Supporting Files */ = { isa = PBXGroup; children = ( - 1879B61E146DE715007E536C /* libsecurity_cdsa_client.a */, + 5346480517331E1200FE9172 /* KeychainSyncAccountNotification-Info.plist */, + 5346480617331E1200FE9172 /* InfoPlist.strings */, + 5346480917331E1200FE9172 /* AspenFamily.xcconfig */, + 5346480A17331E1200FE9172 /* KeychainSyncAccountNotification-Prefix.pch */, ); - name = Products; + name = "Supporting Files"; sourceTree = ""; }; - 1879B622146DE720007E536C /* Products */ = { + 721680C5179B514700406BB4 /* iCloudStat */ = { isa = PBXGroup; children = ( - 1879B62B146DE720007E536C /* libsecurity_cdsa_plugin.a */, + 721680C6179B514700406BB4 /* Supporting Files */, + 721680DC179B518400406BB4 /* main.c */, + 721680DE179B51BC00406BB4 /* com.apple.icloudKeychainStats.plist */, ); - name = Products; + path = iCloudStat; sourceTree = ""; }; - 1879B638146DE748007E536C /* Products */ = { + 721680C6179B514700406BB4 /* Supporting Files */ = { isa = PBXGroup; children = ( - 1879B644146DE748007E536C /* libsecurity_checkpw.a */, - 1879B648146DE748007E536C /* test-checkpw */, - 1879B64A146DE748007E536C /* perf-checkpw */, + 721680C7179B514700406BB4 /* AspenFamily.xcconfig */, ); - name = Products; + name = "Supporting Files"; sourceTree = ""; }; - 1879B64C146DE750007E536C /* Products */ = { + 728B56A316D59979008FA3AB /* OTAPKIAssetTool */ = { isa = PBXGroup; children = ( - 1879B654146DE750007E536C /* libsecurity_cms.a */, + 72CD2BBB16D59AE30064EEE1 /* OTAServiceApp.m */, + 72CD2BBC16D59AE30064EEE1 /* OTAServiceApp.h */, + 72CD2BBD16D59AE30064EEE1 /* OTAServicemain.m */, + 728B56A416D59979008FA3AB /* Supporting Files */, ); - name = Products; + path = OTAPKIAssetTool; sourceTree = ""; }; - 1879B658146DE756007E536C /* Products */ = { + 728B56A416D59979008FA3AB /* Supporting Files */ = { isa = PBXGroup; children = ( - 1879B666146DE757007E536C /* libsecurity_codesigning.a */, - 1879B66A146DE757007E536C /* libintegrity.a */, - 1879B66C146DE757007E536C /* libcodehost.a */, - C2432A0815C7112A0096DB5B /* gkunpack */, - EB2E1F58166D6B3700A7EF61 /* com.apple.CodeSigningHelper.xpc */, + 5DDD0BDD16D6740E00D6C0D6 /* com.apple.OTAPKIAssetTool.plist */, + 5DDD0BDE16D6740E00D6C0D6 /* OTAPKIAssetTool-entitlements.plist */, + 728B56A516D59979008FA3AB /* AspenFamily.xcconfig */, ); - name = Products; + name = "Supporting Files"; sourceTree = ""; }; - 1879B66E146DE75D007E536C /* Products */ = { + 72979BD1175D08C700BE8FD6 /* CloudKeychainDiagnoseTool */ = { isa = PBXGroup; children = ( - 1879B676146DE75E007E536C /* libsecurity_comcryption.a */, ); - name = Products; + name = CloudKeychainDiagnoseTool; sourceTree = ""; }; - 1879B67A146DE76E007E536C /* Products */ = { + 72979BE4175D095900BE8FD6 /* cloud_keychain_diagnose */ = { isa = PBXGroup; children = ( - 1879B684146DE76F007E536C /* libsecurity_cryptkit.a */, - 1879B688146DE76F007E536C /* libCryptKit.a */, - 1879B68A146DE76F007E536C /* CryptKitSignature.a */, + 72979BEF175D0B2D00BE8FD6 /* cloud_keychain_diagnose.c */, + 72979BE5175D095900BE8FD6 /* Supporting Files */, ); - name = Products; + path = cloud_keychain_diagnose; sourceTree = ""; }; - 1879B695146DE797007E536C /* Products */ = { + 72979BE5175D095900BE8FD6 /* Supporting Files */ = { isa = PBXGroup; children = ( - 1879B69D146DE797007E536C /* libsecurity_filedb.a */, + 72979BE6175D095900BE8FD6 /* AspenFamily.xcconfig */, ); - name = Products; + name = "Supporting Files"; sourceTree = ""; }; - 1879B6A1146DE79F007E536C /* Products */ = { + 7908507E0CA87CF00083CC4D /* ipc */ = { isa = PBXGroup; children = ( - 1879B6B3146DE7A0007E536C /* libsecurity_keychain.a */, - 1879B6B7146DE7A0007E536C /* XPCKeychainSandboxCheck.xpc */, - 52B5A8F6151928B400664F11 /* XPCTimeStampingService.xpc */, - 0CBD50B316C325F000713B6C /* libsecurity_keychain_regressions.a */, + 79863B700CADCEAB00818B0D /* com.apple.securityd.plist */, + 790850820CA87CF00083CC4D /* securityd_client.h */, + 79863B940CADD21700818B0D /* securityd_server.h */, + 790850830CA87CF00083CC4D /* securityd_ipc_types.h */, + 7908507F0CA87CF00083CC4D /* client.c */, + 790850840CA87CF00083CC4D /* server.c */, ); - name = Products; + name = ipc; + path = Security/sec/ipc; sourceTree = ""; }; - 1879B6C8146DE7D7007E536C /* Products */ = { + 795CA97B0D38269B00BAE6A2 /* Products */ = { isa = PBXGroup; children = ( - 1879B6D0146DE7D7007E536C /* libsecurity_manifest.a */, + 795CA9860D38269B00BAE6A2 /* libASN1.a */, ); name = Products; sourceTree = ""; }; - 1879B6D4146DE7E0007E536C /* Products */ = { + 79679E241462028800CF997F /* DigicertMalaysia */ = { isa = PBXGroup; children = ( - 1879B6DC146DE7E0007E536C /* libsecurity_mds.a */, + 7947431C146214E500D638A3 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt */, + 794743191462137C00D638A3 /* Invalid-www.cybersecurity.my.crt */, + 79679E251462028800CF997F /* Digisign-Server-ID-Enrich-Entrust-Cert.crt */, + 79679E261462028800CF997F /* Invalid-webmail.jaring.my.crt */, ); - name = Products; + path = DigicertMalaysia; sourceTree = ""; }; - 1879B6E0146DE7E7007E536C /* Products */ = { + 79BDD3950D60D5F9000D84D3 /* Products */ = { isa = PBXGroup; children = ( - 1879B6E9146DE7E8007E536C /* libsecurity_ocspd.a */, + 79BDD39B0D60D5F9000D84D3 /* security_smime */, + 79BDD39D0D60D5F9000D84D3 /* security_smime.framework */, + 79BDD39F0D60D5F9000D84D3 /* libCMS.a */, ); name = Products; sourceTree = ""; }; - 1879B6ED146DE7EE007E536C /* Products */ = { + 79DCEA56134A27D2007F57DC /* codesign_wrapper */ = { isa = PBXGroup; children = ( - 1879B6F5146DE7EF007E536C /* libsecurity_pkcs12.a */, - ); - name = Products; + 79DCEA5E134A280F007F57DC /* codesign_wrapper.c */, + 79DCEA5F134A280F007F57DC /* codesign.c */, + 79DCEA60134A280F007F57DC /* MISEntitlement.c */, + 79DCEA67134A2820007F57DC /* codesign.h */, + 79DCEA69134A2820007F57DC /* codesign_wrapper.h */, + 79DCEA6B134A2820007F57DC /* MISBase.h */, + 79DCEA6D134A2820007F57DC /* MISEntitlement.h */, + ); + path = codesign_wrapper; sourceTree = ""; }; - 1879B6F9146DE7F7007E536C /* Products */ = { + 79E0D701143E558B0010CE0E /* AppleID-certs */ = { isa = PBXGroup; children = ( - 1879B701146DE7F7007E536C /* libsecurity_sd_cspdl.a */, + 79E0D7AA143E68BF0010CE0E /* iPhoneCACert.crt */, + 79E0D7A6143E671C0010CE0E /* Invalid-asset_signing.crt */, + 79E0D702143E558B0010CE0E /* Apple Application Integration Certification Authority Cert.crt */, + 79E0D703143E558B0010CE0E /* Apple Production ShareServices-7130767241416543643077536561487847634e4d6f773d3d.crt */, + 79E0D704143E558B0010CE0E /* AppleRootCertificate.crt */, ); - name = Products; + path = "AppleID-certs"; sourceTree = ""; }; - 1879B713146DE825007E536C /* Products */ = { + BE197F2719116FD100BA91D1 /* SharedWebCredentialViewService */ = { isa = PBXGroup; children = ( - 1879B71C146DE825007E536C /* libsecurity_smime.a */, + BE197F3019116FD100BA91D1 /* SWCAppDelegate.h */, + BE197F3119116FD100BA91D1 /* SWCAppDelegate.m */, + BE197F5F191173C100BA91D1 /* SWCViewController.h */, + BE197F5D191173A800BA91D1 /* SWCViewController.m */, + BE197F2819116FD100BA91D1 /* Supporting Files */, ); - name = Products; + path = SharedWebCredentialViewService; sourceTree = ""; }; - 1879B720146DE839007E536C /* Products */ = { + BE197F2819116FD100BA91D1 /* Supporting Files */ = { isa = PBXGroup; children = ( - 1879B728146DE839007E536C /* libsecurity_ssl.a */, - 0C6D77CD15C8B66000BB4405 /* libsecurity_ssl_kext.a */, - 0C6D77CF15C8B66000BB4405 /* libsecurity_ssl_regressions.a */, - 0C6D77D115C8B66000BB4405 /* dtlsEchoClient */, - 0C6D77D315C8B66000BB4405 /* dtlsEchoServer */, + BE197F2919116FD100BA91D1 /* SharedWebCredentialViewService-Info.plist */, + BE197F60191173F200BA91D1 /* entitlements.plist */, + BE197F2A19116FD100BA91D1 /* InfoPlist.strings */, + BE197F2D19116FD100BA91D1 /* main.m */, + BE197F2F19116FD100BA91D1 /* SharedWebCredentialViewService-Prefix.pch */, + BE197F3319116FD100BA91D1 /* AspenFamily.xcconfig */, ); - name = Products; + name = "Supporting Files"; sourceTree = ""; }; - 1879B72C146DE844007E536C /* Products */ = { + BE4AC9AF18B7FFFA00B84964 /* SharedWebCredentialAgent */ = { isa = PBXGroup; children = ( - 1879B739146DE845007E536C /* libsecurity_transform.a */, - 1879B73D146DE845007E536C /* unit-tests.octest */, - 1879B73F146DE845007E536C /* 100-sha2 */, - 1879B741146DE845007E536C /* input-speed-test */, + BE4AC9AD18B7FFC800B84964 /* com.apple.security.swcagent.plist */, + BE4AC9A118B7FFAD00B84964 /* swcagent.m */, ); - name = Products; + name = SharedWebCredentialAgent; sourceTree = ""; }; - 18F234ED15C9F9A700060520 /* authd */ = { + E710C74A1331946500F85568 /* SecurityTests */ = { isa = PBXGroup; children = ( - 18F234F915C9FA3B00060520 /* agent.c */, - 18F234FA15C9FA3B00060520 /* agent.h */, - 18F2351A15C9FA3C00060520 /* authd_private.h */, - 18F234FB15C9FA3B00060520 /* authdb.c */, - 18F234FC15C9FA3B00060520 /* authdb.h */, - 18F234FD15C9FA3B00060520 /* authitems.c */, - 18F234FE15C9FA3B00060520 /* authitems.h */, - 18F234FF15C9FA3B00060520 /* authtoken.c */, - 18F2350015C9FA3B00060520 /* authtoken.h */, - 18F2350115C9FA3B00060520 /* authtypes.h */, - 18F2350215C9FA3B00060520 /* authutilities.c */, - 18F2350315C9FA3B00060520 /* authutilities.h */, - 18F2350415C9FA3B00060520 /* ccaudit.c */, - 18F2350515C9FA3B00060520 /* ccaudit.h */, - 182A191015D09AFF006AB103 /* connection.c */, - 182A190F15D09AF0006AB103 /* connection.h */, - 18F2350615C9FA3B00060520 /* crc.c */, - 18F2350715C9FA3B00060520 /* crc.h */, - 18F2350815C9FA3B00060520 /* credential.c */, - 18F2350915C9FA3B00060520 /* credential.h */, - 18F2350A15C9FA3B00060520 /* debugging.c */, - 18F2350B15C9FA3B00060520 /* debugging.h */, - 18F2350F15C9FA3B00060520 /* engine.c */, - 18F2351015C9FA3B00060520 /* engine.h */, - 18F2351115C9FA3B00060520 /* main.c */, - 18F2351215C9FA3B00060520 /* mechanism.c */, - 18F2351315C9FA3B00060520 /* mechanism.h */, - 18F2351415C9FA3C00060520 /* object.c */, - 18F2351515C9FA3C00060520 /* object.h */, - 18F2351615C9FA3C00060520 /* process.c */, - 18F2351715C9FA3C00060520 /* process.h */, - 18F2351815C9FA3C00060520 /* rule.c */, - 18F2351915C9FA3C00060520 /* rule.h */, - 18F2351D15C9FA3C00060520 /* server.c */, - 18F2351E15C9FA3C00060520 /* server.h */, - 18F2351F15C9FA3C00060520 /* session.c */, - 18F2352015C9FA3C00060520 /* session.h */, - 18F2353415C9FA7F00060520 /* Supporting Files */, - ); - path = authd; + 4CC92ABA15A3B3D900C6D578 /* testlist.h */, + 4CC92B1B15A3BF2F00C6D578 /* testmain.c */, + 79E0D701143E558B0010CE0E /* AppleID-certs */, + E73000F513D90CD900B0DA1B /* AppleRootCertificate.crt */, + E73000F813D90CD900B0DA1B /* iPhoneCACert.crt */, + E73000F413D90CD900B0DA1B /* mobileasset-certs */, + 4C7540BA13D51D63008048AC /* nist-certs */, + E73000C713D9049B00B0DA1B /* OTATasking-certs */, + 4C50ACFB1410671D00EE92DE /* DigiNotar */, + 79679E241462028800CF997F /* DigicertMalaysia */, + E72783F5159BDF9600028D6C /* Shoebox */, + E710C74B1331946500F85568 /* Supporting Files */, + 0CB321F01464A95F00587CD3 /* CreateCerts.sh */, + 0C550308139F0B970019E5EB /* PreSecurityTests.sh */, + 0C1EF18813A1946C000A4CE5 /* PostSecurityTests.sh */, + ); + path = SecurityTests; sourceTree = ""; }; - 18F2353415C9FA7F00060520 /* Supporting Files */ = { + E710C74B1331946500F85568 /* Supporting Files */ = { isa = PBXGroup; children = ( - 18D6803916B768D500DF6D2E /* com.apple.authd */, - 18CFEE8715DEE25200E3F2A3 /* com.apple.authd.sb */, - 187D6B9515D436BF00E27494 /* authorization.plist */, - 18F2350D15C9FA3B00060520 /* InfoPlist.strings */, - 18F2351B15C9FA3C00060520 /* Info.plist */, - 18F2351C15C9FA3C00060520 /* security.auth-Prefix.pch */, + 52A23EDB161DEC3700E271E0 /* Default-568h@2x.png */, + 4C465C7D13AFD82300E841AC /* SecurityDevTests-Info.plist */, + E710C74C1331946500F85568 /* SecurityTests-Info.plist */, + E7E4318813319C0700AF0CFD /* SecurityTests-Entitlements.plist */, ); name = "Supporting Files"; sourceTree = ""; }; - 4C0F6FAF1985879300178101 /* sectask */ = { - isa = PBXGroup; - children = ( - 4C0F6F861985877800178101 /* SecEntitlements.h */, - ); - name = sectask; - path = ../sectask; - sourceTree = ""; - }; - 37A7CEAC197DB8FA00926CE8 /* codesign_tests */ = { + E72783F5159BDF9600028D6C /* Shoebox */ = { isa = PBXGroup; children = ( - 37A7CEAD197DB8FA00926CE8 /* FatDynamicValidation.c */, - 37A7CEDB197DCDD700926CE8 /* validation.sh */, + 5D83979C160259EE0075998F /* Invalid.com.apple.testcard.crt */, + E72783F6159BDFBB00028D6C /* Apple TEST RootCertificate.crt */, + E72783F7159BDFBC00028D6C /* Apple Worldwide Developer Relations Certification Authority Cert.crt */, + E72783F8159BDFBC00028D6C /* Apple Worldwide Developer Relations Certification Authority TEST Cert.crt */, + E72783F9159BDFBC00028D6C /* AppleRootCertificate.crt */, ); - path = codesign_tests; + name = Shoebox; sourceTree = ""; }; - 4C1288F615FFECF2008CE3E3 /* utilities */ = { + E73000C713D9049B00B0DA1B /* OTATasking-certs */ = { isa = PBXGroup; children = ( - 0CC3355B16C1EF5D00399E53 /* regressions.xcodeproj */, - 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */, + E73000DD13D90A1F00B0DA1B /* Invalid-asset_signing.crt */, + E73000DF13D90A1F00B0DA1B /* task_signing.crt */, ); - path = utilities; + name = "OTATasking-certs"; sourceTree = ""; }; - 4C12893815FFECF3008CE3E3 /* Products */ = { + E73000F413D90CD900B0DA1B /* mobileasset-certs */ = { isa = PBXGroup; children = ( - 4C12894015FFECF3008CE3E3 /* libutilities.a */, - 4C12894215FFECF3008CE3E3 /* libutilitiesRegressions.a */, + E73000F613D90CD900B0DA1B /* asset_signing.crt */, + E73000F713D90CD900B0DA1B /* Invalid-task_signing.crt */, ); - name = Products; - sourceTree = ""; - }; - 4C96F7C316D6DF8400D3B39D /* Keychain Circle Notification */ = { - isa = PBXGroup; - children = ( - 4CD1980B16DD3BDF00A9E8FD /* NSArray+mapWithBlock.h */, - 4CD1980C16DD3BDF00A9E8FD /* NSArray+mapWithBlock.m */, - 4C96F7CF16D6DF8400D3B39D /* KNAppDelegate.h */, - 4C96F7D016D6DF8400D3B39D /* KNAppDelegate.m */, - 4C96F7D216D6DF8400D3B39D /* MainMenu.xib */, - 4C5DD44217A5E31900696A79 /* KNPersistantState.h */, - 4C5DD44317A5E31900696A79 /* KNPersistantState.m */, - 4C96F7C416D6DF8400D3B39D /* Supporting Files */, - 4CB9121C17750E6500C1CCCA /* entitlments.plist */, - ); - path = "Keychain Circle Notification"; + path = "mobileasset-certs"; sourceTree = ""; }; - 4C96F7C416D6DF8400D3B39D /* Supporting Files */ = { + E7450BB216D42BD4009C07B8 /* Security.framework headers */ = { isa = PBXGroup; children = ( - 4C7D456417BEE6B700DDD88F /* NSDictionary+compactDescription.h */, - 4C7D456517BEE6B700DDD88F /* NSDictionary+compactDescription.m */, - 4C7D456617BEE6B700DDD88F /* NSSet+compactDescription.h */, - 4C7D456717BEE6B700DDD88F /* NSSet+compactDescription.m */, - 4C7D453B17BEE69B00DDD88F /* NSString+compactDescription.h */, - 4C7D453C17BEE69B00DDD88F /* NSString+compactDescription.m */, - 5328475117850741009118DC /* Localizable.strings */, - 4CFE1CB816DD4B9C0026E900 /* CloudKeychain.icns */, - 4C96F7C516D6DF8400D3B39D /* Keychain Circle Notification-Info.plist */, - 4C96F7C616D6DF8400D3B39D /* InfoPlist.strings */, - 4C96F7C916D6DF8400D3B39D /* main.m */, - 4C96F7CB16D6DF8400D3B39D /* Keychain Circle Notification-Prefix.pch */, - 4C96F7CC16D6DF8400D3B39D /* Credits.rtf */, - 4C49390C16E51ACE00CE110C /* com.apple.security.keychain-circle-notification.plist */, + 0C5D2EDC167FEA880077501D /* security_asn1 */, + 0C3145531496B02100427C0B /* security_ssl */, + E7C4D03512F9EB210022E067 /* security_smime */, + 4C922CB2097F1984004CEEBD /* Security */, + E7450BB316D42D37009C07B8 /* SOSCircle */, ); - name = "Supporting Files"; + name = "Security.framework headers"; sourceTree = ""; }; - 4CB23B48169F5873003A0131 /* security2 */ = { + E7450BB316D42D37009C07B8 /* SOSCircle */ = { isa = PBXGroup; children = ( - 4CB23B4B169F5873003A0131 /* security2.1 */, - 4CB23B80169F58DE003A0131 /* security_tool_commands.c */, - 4CB23B82169F592C003A0131 /* sub_commands.h */, + E7450BAC16D42B17009C07B8 /* SOSCloudCircle.h */, + E7450BAD16D42B17009C07B8 /* SOSPeerInfo.h */, ); - path = security2; + name = SOSCircle; + path = Security/sec/SOSCircle; sourceTree = ""; }; - 4CC7A7B516CC2A85003E10C1 /* KeychainDemoApp */ = { + E7C4D03512F9EB210022E067 /* security_smime */ = { isa = PBXGroup; children = ( - 4CC7A7C116CC2A85003E10C1 /* KDAppDelegate.h */, - 4CC7A7C216CC2A85003E10C1 /* KDAppDelegate.m */, - 4C85DED816DBD5BF00ED8D47 /* KDCirclePeer.h */, - 4C85DED916DBD5BF00ED8D47 /* KDCirclePeer.m */, - 4CC7A7F416CD95D2003E10C1 /* KDSecItems.h */, - 4CC7A7F516CD95D3003E10C1 /* KDSecItems.m */, - 4CC7A7C416CC2A85003E10C1 /* MainMenu.xib */, - 4C96F73816D5372C00D3B39D /* KDSecCircle.h */, - 4C96F73916D5372C00D3B39D /* KDSecCircle.m */, - 4CC7A7B616CC2A85003E10C1 /* Supporting Files */, - ); - name = KeychainDemoApp; - path = Keychain; - sourceTree = ""; - }; - 4CC7A7B616CC2A85003E10C1 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 4C2505B616D2DF9F002CE025 /* Icon.icns */, - 4CC7A7B716CC2A85003E10C1 /* Keychain-Info.plist */, - 4CC7A7B816CC2A85003E10C1 /* InfoPlist.strings */, - 4CC7A7BB16CC2A85003E10C1 /* main.m */, - 4CC7A7BD16CC2A85003E10C1 /* Keychain-Prefix.pch */, - 4CC7A7BE16CC2A85003E10C1 /* Credits.rtf */, - ); - name = "Supporting Files"; + 7901790E12D51F7200CA4D44 /* SecCmsBase.h */, + 7901790F12D51F7200CA4D44 /* SecCmsContentInfo.h */, + 7901791012D51F7200CA4D44 /* SecCmsDecoder.h */, + 7901791112D51F7200CA4D44 /* SecCmsDigestContext.h */, + 7901791212D51F7200CA4D44 /* SecCmsEncoder.h */, + 7901791312D51F7200CA4D44 /* SecCmsEnvelopedData.h */, + 7901791412D51F7200CA4D44 /* SecCmsMessage.h */, + 7901791512D51F7200CA4D44 /* SecCmsRecipientInfo.h */, + 7901791612D51F7200CA4D44 /* SecCmsSignedData.h */, + 7901791712D51F7200CA4D44 /* SecCmsSignerInfo.h */, + ); + name = security_smime; sourceTree = ""; }; - 5214700916977CB800DF0DB3 /* Other Frameworks */ = { + E7FCBE401314471B000DE34E /* Frameworks */ = { isa = PBXGroup; children = ( - 5214700A16977CB800DF0DB3 /* AppKit.framework */, - 5214700B16977CB800DF0DB3 /* CoreData.framework */, - 5214700C16977CB800DF0DB3 /* Foundation.framework */, + BE197F5A1911723E00BA91D1 /* SpringBoardUIServices.framework */, + BE95AAFC18B846A8004495EB /* WebUI.framework */, + 2281820D17B4686C0067C9C9 /* BackgroundTaskAgent.framework */, + 4C8A38C817B93DF10001B4C0 /* CloudServices.framework */, + 72B368BD179891FC004C37CE /* AggregateDictionary.framework */, + 4C7913241799A5CB00A9633E /* MobileCoreServices.framework */, + 4C079EBC1794A96200D73970 /* ServiceManagement.framework */, + 4C84DA541720698900AEE225 /* AppleAccount.framework */, + 4CF4C19C171E0EA600877419 /* Accounts.framework */, + 72C3EC2D1705F24E0040C87C /* ManagedConfiguration.framework */, + 7273402816CAFB3C0096622A /* MobileAsset.framework */, + E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */, + 52D82BD316A5EADA0078DFE5 /* Security.framework */, + E7FC30AB1332DE9000802946 /* MobileKeyBag.framework */, + E7FCBE411314471B000DE34E /* UIKit.framework */, + E7FCBE431314471B000DE34E /* Foundation.framework */, + E7FCBE451314471B000DE34E /* CoreGraphics.framework */, ); - name = "Other Frameworks"; - sourceTree = ""; - }; - 5214700D16977CB800DF0DB3 /* CloudKeychainProxy */ = { - isa = PBXGroup; - children = ( - 52C3D235169B56860091D9D3 /* ckdmain.m */, - 5214700E16977CB800DF0DB3 /* Supporting Files */, - ); - path = CloudKeychainProxy; - sourceTree = ""; - }; - 5214700E16977CB800DF0DB3 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 5214702416977FEC00DF0DB3 /* cloudkeychain.entitlements.plist */, - 5214702516977FEC00DF0DB3 /* com.apple.security.cloudkeychainproxy.plist */, - 5214700F16977CB800DF0DB3 /* CloudKeychainProxy-Info.plist */, - 5214701016977CB800DF0DB3 /* InfoPlist.strings */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 721680A7179B40F600406BB4 /* iCloudStats */ = { - isa = PBXGroup; - children = ( - 721680A8179B40F600406BB4 /* main.c */, - 721680AA179B40F600406BB4 /* iCloudStats.1 */, - 721680BD179B4F9100406BB4 /* com.apple.iCloudStats.plist */, - ); - path = iCloudStats; - sourceTree = ""; - }; - 72756C00175D485D00F52070 /* cloud_keychain_diagnose */ = { - isa = PBXGroup; - children = ( - 72756C30175D48C100F52070 /* cloud_keychain_diagnose.c */, - 72756C03175D485D00F52070 /* Supporting Files */, - ); - path = cloud_keychain_diagnose; - sourceTree = ""; - }; - 72756C03175D485D00F52070 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 72756C04175D485D00F52070 /* cloud_keychain_diagnose-Prefix.pch */, - ); - name = "Supporting Files"; + name = Frameworks; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 18073848146D0D4E00F05C24 /* Headers */ = { + 4C32C0AA0A4975F6002891BD /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 4C32C1030A4976BF002891BD /* certextensions.h in Headers */, + 4C32C1240A4976BF002891BD /* SecBase.h in Headers */, + 4C32C1250A4976BF002891BD /* SecCertificate.h in Headers */, + 4C32C1260A4976BF002891BD /* SecTrust.h in Headers */, + 4CF0484C0A5D988F00268236 /* SecItem.h in Headers */, + 4CF048800A5F016300268236 /* SecItemPriv.h in Headers */, + 4C999BA60AB5F0BB0010451D /* NtlmGenerator.h in Headers */, + 4C999BA80AB5F0BB0010451D /* ntlmBlobPriv.h in Headers */, + 4C7608B30AC34A8100980096 /* SecCertificatePriv.h in Headers */, + 4CEF4CA80C5551FE00062475 /* SecCertificateInternal.h in Headers */, + 0C3145571496B8FB00427C0B /* SecureTransport.h in Headers */, + BE061FE11899ECEE00C739F6 /* SecSharedCredential.h in Headers */, + 443381EE18A3D83A00215606 /* SecAccessControlPriv.h in Headers */, + 0CA31A4814BB5CDB00BD348C /* CipherSuite.h in Headers */, + CDDE9BD11729ABFA0013B0E8 /* SecPasswordGenerate.h in Headers */, + 0CA31A7514BB6C2500BD348C /* sslTypes.h in Headers */, + 0C5D2EEB167FEAAC0077501D /* SecAsn1Coder.h in Headers */, + 4C7072860AC9EA4F007CC205 /* SecKey.h in Headers */, + 4C7072D40AC9ED5A007CC205 /* SecKeyPriv.h in Headers */, + 4C7073CA0ACB2BAD007CC205 /* SecRSAKey.h in Headers */, + 4C0B906E0ACCBD240077CD03 /* SecFramework.h in Headers */, + 4C7391790B01745000C4CBFA /* vmdh.h in Headers */, + 4C64E01C0B8FBC71009B306C /* SecIdentity.h in Headers */, + 4C64E01D0B8FBC7E009B306C /* Security.h in Headers */, + E7676DB619411DF300498DD4 /* SecServerEncryptionSupport.h in Headers */, + 4C4296320BB0A68200491999 /* SecTrustSettings.h in Headers */, + 4CBA0E880BB33C0000E72B55 /* SecPolicy.h in Headers */, + 4C6416D50BB34F00001C83FD /* SecPolicyPriv.h in Headers */, + 78F92F11195128D70023B54B /* SecECKeyPriv.h in Headers */, + 4CD3BA621106FF4D00BE8B75 /* SecECKey.h in Headers */, + 4C6416F10BB357D5001C83FD /* SecInternal.h in Headers */, + 4C12828D0BB4957D00985BB0 /* SecTrustSettingsPriv.h in Headers */, + 443381ED18A3D83100215606 /* SecAccessControl.h in Headers */, + 4C1B442D0BB9CAF900461B82 /* SecTrustStore.h in Headers */, + 4CF41D0C0BBB4022005F3248 /* SecCertificatePath.h in Headers */, + 4C2F81D50BF121D2003C4F77 /* SecRandom.h in Headers */, + 7940D4130C3ACF9000FDB5D8 /* SecDH.h in Headers */, + 790850F70CA88AE10083CC4D /* securityd_client.h in Headers */, + 790850F80CA88AE10083CC4D /* securityd_ipc_types.h in Headers */, + 79863B960CADD21700818B0D /* securityd_server.h in Headers */, + 795CA9CE0D38435E00BAE6A2 /* p12pbegen.h in Headers */, + 79EF5B730D3D6AFE009F5270 /* p12import.h in Headers */, + 79EF5B6E0D3D6A31009F5270 /* SecImportExport.h in Headers */, + 4CCE0ADA0D41797400DDBB21 /* SecIdentityPriv.h in Headers */, + 4CCE0ADE0D4179E500DDBB21 /* SecBasePriv.h in Headers */, + 4CFBF6100D5A951100969BBE /* SecPolicyInternal.h in Headers */, + 4C87F3A80D611C26000E7104 /* SecTrustPriv.h in Headers */, + 79BDD3C20D60DB84000D84D3 /* SecCMS.h in Headers */, + 107226D30D91DB32003CF14F /* SecTask.h in Headers */, + 4C7CE5700DC7DC6600AE53FC /* SecEntitlements.h in Headers */, + 791766DE0DD0162C00F3B974 /* SecCertificateRequest.h in Headers */, + 4C7416040F1D71A2008E0E4D /* SecSCEP.h in Headers */, + 0C3145581496B8FB00427C0B /* SecureTransportPriv.h in Headers */, + 4AF7FFFD15AFB73800B9D400 /* SecOTR.h in Headers */, + 4AF7FFFE15AFB73800B9D400 /* SecOTRDHKey.h in Headers */, + 4AF7FFFF15AFB73800B9D400 /* SecOTRErrors.h in Headers */, + 4AF7000015AFB73800B9D400 /* SecOTRIdentityPriv.h in Headers */, + 4AF7000115AFB73800B9D400 /* SecOTRMath.h in Headers */, + 4AF7000315AFB73800B9D400 /* SecOTRPacketData.h in Headers */, + 4AF7000415AFB73800B9D400 /* SecOTRPackets.h in Headers */, + 4AF7000515AFB73800B9D400 /* SecOTRSession.h in Headers */, + 4AF7000615AFB73800B9D400 /* SecOTRSessionPriv.h in Headers */, + 0C5D2EED167FEEC90077501D /* secasn1t.h in Headers */, + 0C5D2EEF167FF0560077501D /* SecAsn1Templates.h in Headers */, + 8E02FA6B1107BE460043545E /* pbkdf2.h in Headers */, + E7450BB116D42B39009C07B8 /* SOSPeerInfo.h in Headers */, + E7450BB016D42B30009C07B8 /* SOSCloudCircle.h in Headers */, + 8ED6F6CA110904E300D2B368 /* SecPBKDF.h in Headers */, + 7901791812D51F7200CA4D44 /* SecCmsBase.h in Headers */, + 7901791912D51F7200CA4D44 /* SecCmsContentInfo.h in Headers */, + 7901791A12D51F7200CA4D44 /* SecCmsDecoder.h in Headers */, + 7901791B12D51F7200CA4D44 /* SecCmsDigestContext.h in Headers */, + 7901791C12D51F7200CA4D44 /* SecCmsEncoder.h in Headers */, + 7901791D12D51F7200CA4D44 /* SecCmsEnvelopedData.h in Headers */, + 7901791E12D51F7200CA4D44 /* SecCmsMessage.h in Headers */, + 7901791F12D51F7200CA4D44 /* SecCmsRecipientInfo.h in Headers */, + 7901792012D51F7200CA4D44 /* SecCmsSignedData.h in Headers */, + 7901792112D51F7200CA4D44 /* SecCmsSignerInfo.h in Headers */, + 7901792912D51FFC00CA4D44 /* SecAsn1Types.h in Headers */, + 0C5D2EF1167FF1FC0077501D /* oidsalg.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - 18FE67E71471A3AA00A2CBE3 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 18FE68021471A42900A2CBE3 /* SecDigestTransform.h in Headers */, - 18FE68031471A42900A2CBE3 /* SecReadTransform.h in Headers */, - 18FE68041471A42900A2CBE3 /* SecTransform.h in Headers */, - 18FE68051471A42900A2CBE3 /* SecCustomTransform.h in Headers */, - 18FE68061471A42900A2CBE3 /* SecDecodeTransform.h in Headers */, - 18FE68071471A42900A2CBE3 /* SecEncodeTransform.h in Headers */, - 18FE68081471A42900A2CBE3 /* SecEncryptTransform.h in Headers */, - 18FE68091471A42900A2CBE3 /* SecSignVerifyTransform.h in Headers */, - 18FE680A1471A42900A2CBE3 /* SecTransformReadTransform.h in Headers */, - 18FE680B1471A42900A2CBE3 /* CipherSuite.h in Headers */, - 18FE680C1471A42900A2CBE3 /* SecureTransport.h in Headers */, - 18FE680D1471A42900A2CBE3 /* mds.h in Headers */, - 18FE680E1471A42900A2CBE3 /* mds_schema.h in Headers */, - 18FE680F1471A42900A2CBE3 /* SecureDownload.h in Headers */, - 18FE68101471A42900A2CBE3 /* SecAccess.h in Headers */, - 18FE68111471A42900A2CBE3 /* SecACL.h in Headers */, - 18FE68121471A42900A2CBE3 /* SecBase.h in Headers */, - 18FE68131471A42900A2CBE3 /* SecCertificate.h in Headers */, - 18FE68141471A42900A2CBE3 /* SecIdentity.h in Headers */, - 18FE68151471A42900A2CBE3 /* SecIdentitySearch.h in Headers */, - 18FE68161471A42900A2CBE3 /* SecItem.h in Headers */, - 18FE68171471A42900A2CBE3 /* SecKey.h in Headers */, - 18FE68181471A42900A2CBE3 /* SecKeychain.h in Headers */, - 18FE68191471A42900A2CBE3 /* SecKeychainItem.h in Headers */, - 18FE681A1471A42900A2CBE3 /* SecKeychainSearch.h in Headers */, - 18FE681B1471A42900A2CBE3 /* SecPolicy.h in Headers */, - 18FE681C1471A42900A2CBE3 /* SecPolicySearch.h in Headers */, - 18FE681D1471A42900A2CBE3 /* SecTrust.h in Headers */, - 18FE681E1471A42900A2CBE3 /* SecTrustedApplication.h in Headers */, - 18FE681F1471A42900A2CBE3 /* Security.h in Headers */, - 18FE68201471A42900A2CBE3 /* SecImportExport.h in Headers */, - 18FE68211471A42900A2CBE3 /* SecTrustSettings.h in Headers */, - 18FE68221471A42900A2CBE3 /* SecCertificateOIDs.h in Headers */, - 18FE68231471A42900A2CBE3 /* SecRandom.h in Headers */, - 18FE68241471A42900A2CBE3 /* SecTask.h in Headers */, - 18FE68251471A42900A2CBE3 /* CodeSigning.h in Headers */, - 18FE68261471A42900A2CBE3 /* CSCommon.h in Headers */, - 18FE68271471A42900A2CBE3 /* SecCode.h in Headers */, - 18FE68281471A42900A2CBE3 /* SecStaticCode.h in Headers */, - 18FE68291471A42900A2CBE3 /* SecRequirement.h in Headers */, - 18FE682A1471A42900A2CBE3 /* SecCodeHost.h in Headers */, - 18FE682B1471A42900A2CBE3 /* CMSDecoder.h in Headers */, - 18FE682C1471A42900A2CBE3 /* CMSEncoder.h in Headers */, - 18FE682D1471A42900A2CBE3 /* AuthorizationTags.h in Headers */, - 18FE682E1471A42900A2CBE3 /* AuthSession.h in Headers */, - 18FE682F1471A42900A2CBE3 /* Authorization.h in Headers */, - 18FE68301471A42900A2CBE3 /* AuthorizationDB.h in Headers */, - 18FE68311471A42900A2CBE3 /* AuthorizationPlugin.h in Headers */, - 18FE68321471A42900A2CBE3 /* SecAsn1Coder.h in Headers */, - 18FE68331471A42900A2CBE3 /* SecAsn1Templates.h in Headers */, - 18FE68341471A42900A2CBE3 /* SecAsn1Types.h in Headers */, - 18FE68351471A42900A2CBE3 /* certextensions.h in Headers */, - 18FE68361471A42900A2CBE3 /* cssm.h in Headers */, - 18FE68371471A42900A2CBE3 /* cssmaci.h in Headers */, - 18FE68381471A42900A2CBE3 /* cssmapi.h in Headers */, - 18FE68391471A42900A2CBE3 /* cssmapple.h in Headers */, - 18FE683A1471A42900A2CBE3 /* cssmcli.h in Headers */, - 18FE683B1471A42900A2CBE3 /* cssmconfig.h in Headers */, - 18FE683C1471A42900A2CBE3 /* cssmcspi.h in Headers */, - 18FE683D1471A42900A2CBE3 /* cssmdli.h in Headers */, - 18FE683E1471A42900A2CBE3 /* cssmerr.h in Headers */, - 18FE683F1471A42900A2CBE3 /* cssmkrapi.h in Headers */, - 18FE68401471A42900A2CBE3 /* cssmkrspi.h in Headers */, - 18FE68411471A42900A2CBE3 /* cssmspi.h in Headers */, - 18FE68421471A42900A2CBE3 /* cssmtpi.h in Headers */, - 18FE68431471A42900A2CBE3 /* cssmtype.h in Headers */, - 18FE68441471A42900A2CBE3 /* eisl.h in Headers */, - 18FE68451471A42900A2CBE3 /* emmspi.h in Headers */, - 18FE68461471A42900A2CBE3 /* emmtype.h in Headers */, - 18FE68491471A42900A2CBE3 /* oidsbase.h in Headers */, - 18FE684A1471A42900A2CBE3 /* oidscert.h in Headers */, - 18FE684B1471A42900A2CBE3 /* oidscrl.h in Headers */, - 18FE684C1471A42900A2CBE3 /* x509defs.h in Headers */, - 18FE684D1471A46600A2CBE3 /* asn1Templates.h in Headers */, - 18FE684E1471A46600A2CBE3 /* AuthorizationPriv.h in Headers */, - 18FE684F1471A46600A2CBE3 /* AuthorizationTagsPriv.h in Headers */, - 18FE68501471A46600A2CBE3 /* certExtensionTemplates.h in Headers */, - 18FE68511471A46600A2CBE3 /* checkpw.h in Headers */, - CDDE9D1E1729E2E60013B0E8 /* SecPasswordGenerate.h in Headers */, - 18FE68521471A46600A2CBE3 /* CMSPrivate.h in Headers */, - 18FE68531471A46600A2CBE3 /* CSCommonPriv.h in Headers */, - 18FE68541471A46600A2CBE3 /* csrTemplates.h in Headers */, - 18FE68551471A46600A2CBE3 /* cssmapplePriv.h in Headers */, - 18FE68561471A46600A2CBE3 /* keyTemplates.h in Headers */, - 18FE68571471A46600A2CBE3 /* mdspriv.h in Headers */, - 18FE68581471A46600A2CBE3 /* nameTemplates.h in Headers */, - 18FE68591471A46600A2CBE3 /* ocspTemplates.h in Headers */, - 18FE685A1471A46600A2CBE3 /* osKeyTemplates.h in Headers */, - 18FE685B1471A46600A2CBE3 /* SecAccessPriv.h in Headers */, - 18FE685C1471A46600A2CBE3 /* secasn1t.h in Headers */, - 18FE685D1471A46600A2CBE3 /* SecAssessment.h in Headers */, - 18FE685E1471A46600A2CBE3 /* SecBasePriv.h in Headers */, - 18FE685F1471A46600A2CBE3 /* SecCertificateBundle.h in Headers */, - 18FE68611471A46600A2CBE3 /* SecCertificatePriv.h in Headers */, - 18FE68621471A46600A2CBE3 /* SecCertificateRequest.h in Headers */, - 18FE68631471A46600A2CBE3 /* SecCmsBase.h in Headers */, - 18FE68641471A46600A2CBE3 /* SecCmsContentInfo.h in Headers */, - 18FE68651471A46600A2CBE3 /* SecCmsDecoder.h in Headers */, - 18FE68661471A46600A2CBE3 /* SecCmsDigestContext.h in Headers */, - 18FE68671471A46600A2CBE3 /* SecCmsDigestedData.h in Headers */, - 18FE68681471A46600A2CBE3 /* SecCmsEncoder.h in Headers */, - 18FE68691471A46600A2CBE3 /* SecCmsEncryptedData.h in Headers */, - 18FE686A1471A46600A2CBE3 /* SecCmsEnvelopedData.h in Headers */, - 18FE686B1471A46600A2CBE3 /* SecCmsMessage.h in Headers */, - 18FE686C1471A46600A2CBE3 /* SecCmsRecipientInfo.h in Headers */, - 18FE686D1471A46600A2CBE3 /* SecCmsSignedData.h in Headers */, - 18FE686E1471A46600A2CBE3 /* SecCmsSignerInfo.h in Headers */, - 18FE686F1471A46600A2CBE3 /* SecCodeHostLib.h in Headers */, - 18FE68701471A46600A2CBE3 /* SecCodePriv.h in Headers */, - 18FE68711471A46600A2CBE3 /* SecCodeSigner.h in Headers */, - 18FE68721471A46600A2CBE3 /* SecFDERecoveryAsymmetricCrypto.h in Headers */, - 18FE68731471A46600A2CBE3 /* SecIdentityPriv.h in Headers */, - 18FE68741471A46600A2CBE3 /* SecIdentitySearchPriv.h in Headers */, - 18FE68751471A46600A2CBE3 /* SecIntegrity.h in Headers */, - 18FE68761471A46600A2CBE3 /* SecIntegrityLib.h in Headers */, - 18FE68771471A46600A2CBE3 /* SecItemPriv.h in Headers */, - 18FE68781471A46600A2CBE3 /* SecKeychainItemExtendedAttributes.h in Headers */, - 18FE68791471A46600A2CBE3 /* SecKeychainItemPriv.h in Headers */, - 18FE687A1471A46600A2CBE3 /* SecKeychainPriv.h in Headers */, - 18FE687B1471A46700A2CBE3 /* SecKeychainSearchPriv.h in Headers */, - 18FE687C1471A46700A2CBE3 /* SecKeyPriv.h in Headers */, - 18FE687D1471A46700A2CBE3 /* SecManifest.h in Headers */, - 18FE687E1471A46700A2CBE3 /* SecNullTransform.h in Headers */, - 18FE687F1471A46700A2CBE3 /* SecPassword.h in Headers */, - 18FE68801471A46700A2CBE3 /* SecPolicyPriv.h in Headers */, - 18FE68811471A46700A2CBE3 /* SecRandomP.h in Headers */, - 18FE68821471A46700A2CBE3 /* SecRecoveryPassword.h in Headers */, - 18FE68831471A46700A2CBE3 /* SecRequirementPriv.h in Headers */, - 18FE68841471A46700A2CBE3 /* SecSMIME.h in Headers */, - 18FE68851471A46700A2CBE3 /* SecStaticCodePriv.h in Headers */, - 18FE68861471A46700A2CBE3 /* SecTransformInternal.h in Headers */, - 18FE68871471A46700A2CBE3 /* SecTrustedApplicationPriv.h in Headers */, - BEC3A76816F79497003E5634 /* SecTaskPriv.h in Headers */, - 18FE68881471A46700A2CBE3 /* SecTrustPriv.h in Headers */, - 18FE68891471A46700A2CBE3 /* SecTrustSettingsPriv.h in Headers */, - 18FE688A1471A46700A2CBE3 /* SecureDownloadInternal.h in Headers */, - 18FE688B1471A46700A2CBE3 /* SecureTransportPriv.h in Headers */, - 18FE688C1471A46700A2CBE3 /* TrustSettingsSchema.h in Headers */, - 18FE688D1471A46700A2CBE3 /* X509Templates.h in Headers */, - 0C4F055E15C9E51A00F9DFD5 /* sslTypes.h in Headers */, - 18BBC7361471F5A300F2B224 /* SecExternalSourceTransform.h in Headers */, - 18B647EC14D9F20500F538BF /* oidsalg.h in Headers */, - 52B5A9C21519330300664F11 /* tsaSupport.h in Headers */, - 52B5A9C31519330300664F11 /* tsaTemplates.h in Headers */, - 52AEA489153C778C005AFC59 /* tsaSupportPriv.h in Headers */, - 18B647ED14D9F20F00F538BF /* oidsattr.h in Headers */, +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 0C0BDB2E175685B000BC1A7E /* secdtests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0C0BDB43175685B000BC1A7E /* Build configuration list for PBXNativeTarget "secdtests" */; + buildPhases = ( + 0C0BDB2B175685B000BC1A7E /* Sources */, + 0C0BDB2C175685B000BC1A7E /* Frameworks */, + 0C0BDB2D175685B000BC1A7E /* CopyFiles */, ); - runOnlyForDeploymentPostprocessing = 0; + buildRules = ( + ); + dependencies = ( + 0C664AE617593BED0092D3D9 /* PBXTargetDependency */, + 0C664AE21759398A0092D3D9 /* PBXTargetDependency */, + 0C664AE41759398A0092D3D9 /* PBXTargetDependency */, + 0C664AE0175939740092D3D9 /* PBXTargetDependency */, + 0C664ADE1759396C0092D3D9 /* PBXTargetDependency */, + 0C664ADC1759395E0092D3D9 /* PBXTargetDependency */, + 0C664AD8175938F90092D3D9 /* PBXTargetDependency */, + 0C664AD6175938F20092D3D9 /* PBXTargetDependency */, + 0C664ADA175939490092D3D9 /* PBXTargetDependency */, + ); + name = secdtests; + productName = secdtest; + productReference = 0C0BDB2F175685B000BC1A7E /* secdtests */; + productType = "com.apple.product-type.tool"; }; - 4AF95B8B16193B1B00662B04 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( + 4C32C0AE0A4975F6002891BD /* Security */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4C32C0B10A4975F7002891BD /* Build configuration list for PBXNativeTarget "Security" */; + buildPhases = ( + 4C32C0AA0A4975F6002891BD /* Headers */, + 4C32C0AB0A4975F6002891BD /* Resources */, + 4C32C0AC0A4975F6002891BD /* Sources */, + 4C32C0AD0A4975F6002891BD /* Frameworks */, ); - runOnlyForDeploymentPostprocessing = 0; + buildRules = ( + E7B006FF170B56E700B27966 /* PBXBuildRule */, + ); + dependencies = ( + E7B01B8416572132000485F1 /* PBXTargetDependency */, + 0CCA408215C745C6002AEC4C /* PBXTargetDependency */, + 18F7F66D14D77E8D00F88A12 /* PBXTargetDependency */, + 18F7F66B14D77E8500F88A12 /* PBXTargetDependency */, + E76079FC1951FE1F00F69731 /* PBXTargetDependency */, + 795CA9BD0D3829FC00BAE6A2 /* PBXTargetDependency */, + 79BDD3A50D60D637000D84D3 /* PBXTargetDependency */, + 4C8786B50B03E0A400BB77D4 /* PBXTargetDependency */, + 4CEC097115758EC5008EB037 /* PBXTargetDependency */, + ); + name = Security; + productName = Security2; + productReference = 4C32C0AF0A4975F6002891BD /* Security.framework */; + productType = "com.apple.product-type.framework"; }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 0C6C630A15D193C800BC68CD /* sectests */ = { + 4C52D0B316EFC61E0079966E /* CircleJoinRequested */ = { isa = PBXNativeTarget; - buildConfigurationList = 0C6C631215D193C900BC68CD /* Build configuration list for PBXNativeTarget "sectests" */; + buildConfigurationList = 4C52D0CC16EFC61E0079966E /* Build configuration list for PBXNativeTarget "CircleJoinRequested" */; buildPhases = ( - 0C6C630715D193C800BC68CD /* Sources */, - 0C6C630815D193C800BC68CD /* Frameworks */, + 4C52D0B016EFC61E0079966E /* Sources */, + 4C52D0B116EFC61E0079966E /* Frameworks */, + 4C52D0B216EFC61E0079966E /* CopyFiles */, + CDB9FCAA179CD054000AAD66 /* CopyFiles */, ); buildRules = ( ); dependencies = ( - 0CBD50C716C3260D00713B6C /* PBXTargetDependency */, - 0CCEBDB316C2CFD4001BD7F6 /* PBXTargetDependency */, - 0C6C632E15D19D2900BC68CD /* PBXTargetDependency */, ); - name = sectests; - productName = sectests; - productReference = 0C6C630B15D193C800BC68CD /* sectests */; + name = CircleJoinRequested; + productName = CircleJoinRequested; + productReference = 4C52D0B416EFC61E0079966E /* CircleJoinRequested */; productType = "com.apple.product-type.tool"; }; - 0CC3350716C1ED8000399E53 /* secdtests */ = { + 4C711D5813AFCD0900FE865D /* SecurityDevTests */ = { isa = PBXNativeTarget; - buildConfigurationList = 0CC3352A16C1ED8000399E53 /* Build configuration list for PBXNativeTarget "secdtests" */; + buildConfigurationList = 4C711D7313AFCD0900FE865D /* Build configuration list for PBXNativeTarget "SecurityDevTests" */; buildPhases = ( - 0CC3351616C1ED8000399E53 /* Sources */, - 0CC3351B16C1ED8000399E53 /* Frameworks */, + 4C711D6313AFCD0900FE865D /* Sources */, + 4C711D6513AFCD0900FE865D /* Frameworks */, + 4C711D7213AFCD0900FE865D /* Resources */, + E7A94B2E13D89EBF001C5FEE /* CopyFiles */, + E73000E813D90A4400B0DA1B /* CopyFiles */, + E730010613D90CFF00B0DA1B /* CopyFiles */, + 4C50AD3414106A2900EE92DE /* CopyFiles */, + 4C50AD3514106A2B00EE92DE /* CopyFiles */, + 4C50AD3614106A2C00EE92DE /* CopyFiles */, + 79E0D708143E55F70010CE0E /* CopyFiles */, + 79679E2B146202BC00CF997F /* CopyFiles */, + E7278400159BDFFF00028D6C /* CopyFiles */, ); buildRules = ( ); dependencies = ( - 0CC3350A16C1ED8000399E53 /* PBXTargetDependency */, - 0CC3351016C1ED8000399E53 /* PBXTargetDependency */, - 0CC3351216C1ED8000399E53 /* PBXTargetDependency */, - 0CC3351416C1ED8000399E53 /* PBXTargetDependency */, - 0CC3350816C1ED8000399E53 /* PBXTargetDependency */, - 0CC3356216C1EF8B00399E53 /* PBXTargetDependency */, - 0CC3350C16C1ED8000399E53 /* PBXTargetDependency */, - 0CCEBDBD16C30948001BD7F6 /* PBXTargetDependency */, - 0C4EAE7917668DFF00773425 /* PBXTargetDependency */, + 18F7F67714D77EFF00F88A12 /* PBXTargetDependency */, + 4C3AD8201575894C0047A498 /* PBXTargetDependency */, + 4C711D5913AFCD0900FE865D /* PBXTargetDependency */, + 4CEC098715758F60008EB037 /* PBXTargetDependency */, + 0CCA418615C89EDD002AEC4C /* PBXTargetDependency */, + 4C711D5F13AFCD0900FE865D /* PBXTargetDependency */, + E7E0D900158FAB52002CA176 /* PBXTargetDependency */, + 4ACED92F15A10A3E0060775A /* PBXTargetDependency */, + 4CC92B2D15A3C94500C6D578 /* PBXTargetDependency */, + 4C2FEC62157572130008BE39 /* PBXTargetDependency */, + ); + name = SecurityDevTests; + productName = SecurityTests; + productReference = 4C711D7613AFCD0900FE865D /* SecurityDevTests.app */; + productType = "com.apple.product-type.application"; + }; + 4C9DE9D11181AC4800CF5C27 /* sslEcdsa */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4C9DE9E11181AC4900CF5C27 /* Build configuration list for PBXNativeTarget "sslEcdsa" */; + buildPhases = ( + 4C9DE9CF1181AC4800CF5C27 /* Sources */, + 4C9DE9D01181AC4800CF5C27 /* Frameworks */, ); - name = secdtests; - productName = sectests; - productReference = 0CC3352D16C1ED8000399E53 /* secdtests */; + buildRules = ( + ); + dependencies = ( + 4CEC097D15758F23008EB037 /* PBXTargetDependency */, + ); + name = sslEcdsa; + productName = sslEcdsa; + productReference = 4C9DE9D21181AC4800CF5C27 /* sslEcdsa */; productType = "com.apple.product-type.tool"; }; - 1807384A146D0D4E00F05C24 /* Security */ = { + 4CB740A20A47567C00D641BB /* securitytool */ = { isa = PBXNativeTarget; - buildConfigurationList = 18073875146D0D4E00F05C24 /* Build configuration list for PBXNativeTarget "Security" */; + buildConfigurationList = 4CB740A90A4756B300D641BB /* Build configuration list for PBXNativeTarget "securitytool" */; buildPhases = ( - 18073846146D0D4E00F05C24 /* Sources */, - 18073847146D0D4E00F05C24 /* Frameworks */, - 18073848146D0D4E00F05C24 /* Headers */, - 18500F961470828E006F9AB4 /* Run Script Generate Strings */, - 18073849146D0D4E00F05C24 /* Resources */, - 18500F9114707E10006F9AB4 /* Run Script Copy XPC Service */, + 4CB740A00A47567C00D641BB /* Sources */, + 4CB740A10A47567C00D641BB /* Frameworks */, ); buildRules = ( - E778BFB91717461800302C14 /* PBXBuildRule */, ); dependencies = ( - 1879B545146DE18D007E536C /* PBXTargetDependency */, - 4AD6F6F41651CC2500DB4CE6 /* PBXTargetDependency */, - 4C12894415FFED03008CE3E3 /* PBXTargetDependency */, - 18FE688F1471A4C900A2CBE3 /* PBXTargetDependency */, - 1885B45114D9AB3D00519375 /* PBXTargetDependency */, - 18270F5D14CF655B00B05E7F /* PBXTargetDependency */, - 18AD56A614CDED59008233F2 /* PBXTargetDependency */, - 182BB410146F248D000BF1F3 /* PBXTargetDependency */, - 1879B56C146DE2CF007E536C /* PBXTargetDependency */, - 18B9655C1472F83C005A4D2E /* PBXTargetDependency */, - 182BB4E7146F25AF000BF1F3 /* PBXTargetDependency */, - 182BB3EE146F248D000BF1F3 /* PBXTargetDependency */, - 182BB3F0146F248D000BF1F3 /* PBXTargetDependency */, - 182BB3F2146F248D000BF1F3 /* PBXTargetDependency */, - 182BB3F4146F248D000BF1F3 /* PBXTargetDependency */, - 182BB3F6146F248D000BF1F3 /* PBXTargetDependency */, - 182BB3F8146F248D000BF1F3 /* PBXTargetDependency */, - 182BB3FC146F248D000BF1F3 /* PBXTargetDependency */, - 182BB3FE146F248D000BF1F3 /* PBXTargetDependency */, - 182BB400146F248D000BF1F3 /* PBXTargetDependency */, - 182BB402146F248D000BF1F3 /* PBXTargetDependency */, - 182BB404146F248D000BF1F3 /* PBXTargetDependency */, - 182BB406146F248D000BF1F3 /* PBXTargetDependency */, - 182BB408146F248D000BF1F3 /* PBXTargetDependency */, - 182BB40A146F248D000BF1F3 /* PBXTargetDependency */, - 182BB40C146F248D000BF1F3 /* PBXTargetDependency */, - 182BB40E146F248D000BF1F3 /* PBXTargetDependency */, - 182BB412146F248D000BF1F3 /* PBXTargetDependency */, - 182BB414146F248D000BF1F3 /* PBXTargetDependency */, - 182BB418146F248D000BF1F3 /* PBXTargetDependency */, - 182BB41A146F248D000BF1F3 /* PBXTargetDependency */, - 182BB3EC146F2448000BF1F3 /* PBXTargetDependency */, - 18446082146DF52F00B12992 /* PBXTargetDependency */, - 1879B56E146DE2D3007E536C /* PBXTargetDependency */, - 5208C0FE16A0D3980062DDC5 /* PBXTargetDependency */, - 182BB22C146F07DD000BF1F3 /* PBXTargetDependency */, - 529FF2201523BD7F0029D842 /* PBXTargetDependency */, + E7FEFB93169E377900E18152 /* PBXTargetDependency */, + E7104A20169E21C000DB0045 /* PBXTargetDependency */, + E7104A03169E038F00DB0045 /* PBXTargetDependency */, ); - name = Security; - productName = Security; - productReference = 1807384B146D0D4E00F05C24 /* Security.framework */; - productType = "com.apple.product-type.framework"; + name = securitytool; + productName = security; + productReference = 4CB740A30A47567C00D641BB /* security */; + productType = "com.apple.product-type.tool"; }; - 18270ED514CF282600B05E7F /* secd */ = { + 4CE5A54C09C796E100D27A3F /* sslViewer */ = { isa = PBXNativeTarget; - buildConfigurationList = 18270EDD14CF282600B05E7F /* Build configuration list for PBXNativeTarget "secd" */; + buildConfigurationList = 4CE5A55C09C7970A00D27A3F /* Build configuration list for PBXNativeTarget "sslViewer" */; buildPhases = ( - 18270ED214CF282600B05E7F /* Sources */, - 18270ED314CF282600B05E7F /* Frameworks */, - 18BEB19914CF7F0B00C8BD36 /* CopyFiles */, - 0C6D003C177B545D0095D167 /* CopyFiles */, + 4CE5A54A09C796E100D27A3F /* Sources */, + 4CE5A54B09C796E100D27A3F /* Frameworks */, ); buildRules = ( ); dependencies = ( - 4C8D8650177A75100019A804 /* PBXTargetDependency */, - 4C01DF13164C3E74006798CD /* PBXTargetDependency */, - 4C7D8764160A746E00D041E3 /* PBXTargetDependency */, - 18270EE314CF28D900B05E7F /* PBXTargetDependency */, - 18270EE114CF28D000B05E7F /* PBXTargetDependency */, - ); - name = secd; - productName = secd; - productReference = 18270ED614CF282600B05E7F /* secd */; + 4CE39044169F87DB00026468 /* PBXTargetDependency */, + 4CEC097915758F17008EB037 /* PBXTargetDependency */, + ); + name = sslViewer; + productName = sslViewer; + productReference = 4CE5A54D09C796E200D27A3F /* sslViewer */; productType = "com.apple.product-type.tool"; }; - 182BB567146F4DCA000BF1F3 /* csparser */ = { + 52D82BDD16A621F70078DFE5 /* CloudKeychainProxy */ = { isa = PBXNativeTarget; - buildConfigurationList = 182BB572146F4DCB000BF1F3 /* Build configuration list for PBXNativeTarget "csparser" */; + buildConfigurationList = 52D82BE816A621F80078DFE5 /* Build configuration list for PBXNativeTarget "CloudKeychainProxy" */; buildPhases = ( - 182BB564146F4DCA000BF1F3 /* Sources */, - 182BB565146F4DCA000BF1F3 /* Frameworks */, - 182BB566146F4DCA000BF1F3 /* Resources */, + 52D82BDA16A621F70078DFE5 /* Sources */, + 52D82BDB16A621F70078DFE5 /* Frameworks */, + 52D82BDC16A621F70078DFE5 /* Resources */, + 52D82BF316A622770078DFE5 /* CopyFiles */, ); buildRules = ( ); dependencies = ( - 182BB596146FE27F000BF1F3 /* PBXTargetDependency */, - 182BB58F146FE11C000BF1F3 /* PBXTargetDependency */, - 182BB58D146FE0FF000BF1F3 /* PBXTargetDependency */, - 182BB588146FE001000BF1F3 /* PBXTargetDependency */, - ); - name = csparser; - productName = csparser; - productReference = 182BB568146F4DCA000BF1F3 /* csparser.bundle */; + 52D82BF216A622600078DFE5 /* PBXTargetDependency */, + 52D82BEC16A622100078DFE5 /* PBXTargetDependency */, + ); + name = CloudKeychainProxy; + productName = CloudKeychainProxy; + productReference = 52D82BDE16A621F70078DFE5 /* CloudKeychainProxy.bundle */; productType = "com.apple.product-type.bundle"; }; - 18F234EA15C9F9A600060520 /* authd */ = { + 52DE81681636347500F49F0C /* Keychain */ = { isa = PBXNativeTarget; - buildConfigurationList = 18F234F615C9F9A700060520 /* Build configuration list for PBXNativeTarget "authd" */; + buildConfigurationList = 52DE81941636347600F49F0C /* Build configuration list for PBXNativeTarget "Keychain" */; buildPhases = ( - 4AF95B8B16193B1B00662B04 /* Headers */, - 18F234E715C9F9A600060520 /* Sources */, - 18F234E815C9F9A600060520 /* Frameworks */, - 187D6B9615D4381C00E27494 /* Copy authorization.plist */, - 18CFEE8815DEE2BA00E3F2A3 /* Copy sandbox profile */, - 4A5C178F161A9DE000ABF784 /* CopyFiles */, - 18D6803A16B768DE00DF6D2E /* Copy asl module */, + 52DE81651636347500F49F0C /* Sources */, + 52DE81661636347500F49F0C /* Frameworks */, + 52DE81671636347500F49F0C /* Resources */, ); buildRules = ( ); dependencies = ( + 0CD72A4C16D54BD300A4B8A3 /* PBXTargetDependency */, ); - name = authd; - productName = security.auth; - productReference = 18F234EB15C9F9A600060520 /* authd.xpc */; - productType = "com.apple.product-type.bundle"; + name = Keychain; + productName = Keychain; + productReference = 52DE81691636347500F49F0C /* Keychain.app */; + productType = "com.apple.product-type.application"; }; - 18FE67E91471A3AA00A2CBE3 /* copyHeaders */ = { + 5346480017331E1100FE9172 /* KeychainSyncAccountNotification */ = { isa = PBXNativeTarget; - buildConfigurationList = 18FE67FB1471A3AA00A2CBE3 /* Build configuration list for PBXNativeTarget "copyHeaders" */; + buildConfigurationList = 5346481917331E1200FE9172 /* Build configuration list for PBXNativeTarget "KeychainSyncAccountNotification" */; buildPhases = ( - 18FE67E71471A3AA00A2CBE3 /* Headers */, - 4CB86AE4167A6F3D00F46643 /* CopyFiles */, + 534647FD17331E1100FE9172 /* Sources */, + 534647FE17331E1100FE9172 /* Frameworks */, + 534647FF17331E1100FE9172 /* Resources */, ); buildRules = ( ); dependencies = ( ); - name = copyHeaders; - productName = copyHeaders; - productReference = 18FE67EA1471A3AA00A2CBE3 /* Security.framework */; - productType = "com.apple.product-type.framework"; + name = KeychainSyncAccountNotification; + productName = KeychainSyncAccountNotification; + productReference = 5346480117331E1200FE9172 /* KeychainSyncAccountNotification.bundle */; + productType = "com.apple.product-type.bundle"; }; - 37A7CEAA197DB8FA00926CE8 /* codesign_tests */ = { + 728B56A016D59979008FA3AB /* OTAPKIAssetTool */ = { isa = PBXNativeTarget; - buildConfigurationList = 37A7CED8197DB8FA00926CE8 /* Build configuration list for PBXNativeTarget "codesign_tests" */; + buildConfigurationList = 728B56AB16D59979008FA3AB /* Build configuration list for PBXNativeTarget "OTAPKIAssetTool" */; buildPhases = ( - 37A7CEA7197DB8FA00926CE8 /* Sources */, - 37A7CEA8197DB8FA00926CE8 /* Frameworks */, - 37A7CEDC197DCECD00926CE8 /* CopyFiles */, - 37A7CF21197DD10900926CE8 /* CopyFiles */, + 728B569D16D59979008FA3AB /* Sources */, + 728B569E16D59979008FA3AB /* Frameworks */, + 728B569F16D59979008FA3AB /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); - name = codesign_tests; - productName = codesign_tests; - productReference = 37A7CEAB197DB8FA00926CE8 /* codesign_tests */; + name = OTAPKIAssetTool; + productName = OTAPKIAssetTool; + productReference = 728B56A116D59979008FA3AB /* OTAPKIAssetTool */; productType = "com.apple.product-type.tool"; }; - 4C96F7C016D6DF8300D3B39D /* Keychain Circle Notification */ = { + 72979BE1175D095900BE8FD6 /* cloud_keychain_diagnose */ = { isa = PBXNativeTarget; - buildConfigurationList = 4C96F7D516D6DF8400D3B39D /* Build configuration list for PBXNativeTarget "Keychain Circle Notification" */; + buildConfigurationList = 72979BEC175D095900BE8FD6 /* Build configuration list for PBXNativeTarget "cloud_keychain_diagnose" */; buildPhases = ( - 4C96F7BD16D6DF8300D3B39D /* Sources */, - 4C96F7BE16D6DF8300D3B39D /* Frameworks */, - 4C96F7BF16D6DF8300D3B39D /* Resources */, - 4C49390E16E51ED100CE110C /* CopyFiles */, + 72979BDE175D095900BE8FD6 /* Sources */, + 72979BDF175D095900BE8FD6 /* Frameworks */, + 72979BE0175D095900BE8FD6 /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); - name = "Keychain Circle Notification"; - productName = "Keychain Circle Notification"; - productReference = 4C96F7C116D6DF8300D3B39D /* Keychain Circle Notification.app */; - productType = "com.apple.product-type.application"; + name = cloud_keychain_diagnose; + productName = cloud_keychain_diagnose; + productReference = 72979BE2175D095900BE8FD6 /* cloud_keychain_diagnose */; + productType = "com.apple.product-type.tool"; + }; + 790851B50CA9859F0083CC4D /* securityd */ = { + isa = PBXNativeTarget; + buildConfigurationList = 790851C90CA985C10083CC4D /* Build configuration list for PBXNativeTarget "securityd" */; + buildPhases = ( + 790851B30CA9859F0083CC4D /* Sources */, + 790851B40CA9859F0083CC4D /* Frameworks */, + 79863B6C0CADCE4300818B0D /* CopyFiles */, + 0C59B55317677BF200617746 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + 5D403D3215C6FE9E0030D492 /* PBXTargetDependency */, + 18F7F67114D77EC500F88A12 /* PBXTargetDependency */, + 4C1ADEB71615176500E4A8AF /* PBXTargetDependency */, + BE442B9F18B7FD7D00F24DAE /* PBXTargetDependency */, + ); + name = securityd; + productName = securityd; + productReference = 790851B60CA9859F0083CC4D /* securityd */; + productType = "com.apple.product-type.tool"; }; - 4CB23B45169F5873003A0131 /* security2 */ = { + 7913B1FF0D172B3900601FE9 /* sslServer */ = { isa = PBXNativeTarget; - buildConfigurationList = 4CB23B7F169F5873003A0131 /* Build configuration list for PBXNativeTarget "security2" */; + buildConfigurationList = 7913B20A0D172B3900601FE9 /* Build configuration list for PBXNativeTarget "sslServer" */; buildPhases = ( - 4CB23B42169F5873003A0131 /* Sources */, - 4CB23B43169F5873003A0131 /* Frameworks */, - 4CB23B44169F5873003A0131 /* CopyFiles */, + 7913B2000D172B3900601FE9 /* Sources */, + 7913B2060D172B3900601FE9 /* Frameworks */, ); buildRules = ( ); dependencies = ( - 4CB23B88169F597D003A0131 /* PBXTargetDependency */, - 4CB23B86169F5971003A0131 /* PBXTargetDependency */, - 4CB23B84169F5961003A0131 /* PBXTargetDependency */, + 4CE39042169F87C400026468 /* PBXTargetDependency */, + 4CEC097515758F0A008EB037 /* PBXTargetDependency */, ); - name = security2; - productName = security2; - productReference = 4CB23B46169F5873003A0131 /* security2 */; + name = sslServer; + productName = sslViewer; + productReference = 7913B2110D172B3900601FE9 /* sslServer */; productType = "com.apple.product-type.tool"; }; - 4CC7A7B216CC2A84003E10C1 /* Cloud Keychain Utility */ = { + 79DCEA53134A27D2007F57DC /* codesign_wrapper */ = { isa = PBXNativeTarget; - buildConfigurationList = 4CC7A7EF16CC2A85003E10C1 /* Build configuration list for PBXNativeTarget "Cloud Keychain Utility" */; + buildConfigurationList = 79DCEA5B134A27D2007F57DC /* Build configuration list for PBXNativeTarget "codesign_wrapper" */; buildPhases = ( - 4CC7A7AF16CC2A84003E10C1 /* Sources */, - 4CC7A7B016CC2A84003E10C1 /* Frameworks */, - 4CC7A7B116CC2A84003E10C1 /* Resources */, + 79DCEA50134A27D2007F57DC /* Sources */, + 79DCEA51134A27D2007F57DC /* Frameworks */, + 79DCEA52134A27D2007F57DC /* CopyFiles */, + 79C0C6BB134A967000A51BCB /* ShellScript */, ); buildRules = ( ); dependencies = ( + 79DCEA7D134A293D007F57DC /* PBXTargetDependency */, ); - name = "Cloud Keychain Utility"; - productName = Keychain; - productReference = 4CC7A7B316CC2A84003E10C1 /* Cloud Keychain Utility.app */; - productType = "com.apple.product-type.application"; + name = codesign_wrapper; + productName = codesign_wrapper; + productReference = 79DCEA54134A27D2007F57DC /* codesign_wrapper */; + productType = "com.apple.product-type.tool"; }; - 5214700516977CB800DF0DB3 /* CloudKeychainProxy */ = { + BE197F2519116FD100BA91D1 /* SharedWebCredentialViewService */ = { isa = PBXNativeTarget; - buildConfigurationList = 5214701416977CB800DF0DB3 /* Build configuration list for PBXNativeTarget "CloudKeychainProxy" */; + buildConfigurationList = BE197F5819116FD100BA91D1 /* Build configuration list for PBXNativeTarget "SharedWebCredentialViewService" */; buildPhases = ( - 5214700216977CB800DF0DB3 /* Sources */, - 5214700316977CB800DF0DB3 /* Frameworks */, - 5214700416977CB800DF0DB3 /* Resources */, - 5214702316977EA600DF0DB3 /* CopyFiles */, + BE197F2219116FD100BA91D1 /* Sources */, + BE197F2319116FD100BA91D1 /* Frameworks */, + BE197F2419116FD100BA91D1 /* Resources */, ); buildRules = ( ); dependencies = ( - 5214701A16977D2500DF0DB3 /* PBXTargetDependency */, - 5214701816977D1D00DF0DB3 /* PBXTargetDependency */, ); - name = CloudKeychainProxy; - productName = CloudKeychainProxy; - productReference = 5214700616977CB800DF0DB3 /* CloudKeychainProxy.bundle */; - productType = "com.apple.product-type.bundle"; + name = SharedWebCredentialViewService; + productName = KeychainViewService; + productReference = BE197F2619116FD100BA91D1 /* SharedWebCredentialViewService.app */; + productType = "com.apple.product-type.application"; }; - 721680A4179B40F600406BB4 /* iCloudStats */ = { + BE442BA018B7FDB800F24DAE /* swcagent */ = { isa = PBXNativeTarget; - buildConfigurationList = 721680AC179B40F600406BB4 /* Build configuration list for PBXNativeTarget "iCloudStats" */; + buildConfigurationList = BE442BBE18B7FDB800F24DAE /* Build configuration list for PBXNativeTarget "swcagent" */; buildPhases = ( - 721680A1179B40F600406BB4 /* Sources */, - 721680A2179B40F600406BB4 /* Frameworks */, - 721680A3179B40F600406BB4 /* CopyFiles */, + BE442BAB18B7FDB800F24DAE /* Sources */, + BE442BAD18B7FDB800F24DAE /* Frameworks */, + BE442BBA18B7FDB800F24DAE /* CopyFiles */, ); buildRules = ( ); dependencies = ( + BE442BA918B7FDB800F24DAE /* PBXTargetDependency */, ); - name = iCloudStats; - productName = iCloudStats; - productReference = 721680A5179B40F600406BB4 /* iCloudStats */; + name = swcagent; + productName = securityd; + productReference = BE442BC118B7FDB800F24DAE /* swcagent */; productType = "com.apple.product-type.tool"; }; - 72756BFD175D485D00F52070 /* cloud_keychain_diagnose */ = { + E710C7411331946400F85568 /* SecurityTests */ = { isa = PBXNativeTarget; - buildConfigurationList = 72756C2F175D485D00F52070 /* Build configuration list for PBXNativeTarget "cloud_keychain_diagnose" */; + buildConfigurationList = E710C75C1331946500F85568 /* Build configuration list for PBXNativeTarget "SecurityTests" */; buildPhases = ( - 72756BFA175D485D00F52070 /* Sources */, - 72756BFB175D485D00F52070 /* Frameworks */, - 72756BFC175D485D00F52070 /* CopyFiles */, + E710C73E1331946400F85568 /* Sources */, + E710C73F1331946400F85568 /* Frameworks */, + E710C7401331946400F85568 /* Resources */, + E7A94C9B13D8A14A001C5FEE /* CopyFiles */, + E73000ED13D90A7500B0DA1B /* CopyFiles */, + E730010113D90CE200B0DA1B /* CopyFiles */, + 4C50AD081410673800EE92DE /* CopyFiles */, + 4C50AD091410675400EE92DE /* CopyFiles */, + 4C50AD0A1410676300EE92DE /* CopyFiles */, + 79E0D700143E551F0010CE0E /* CopyFiles */, + 79679E231462023800CF997F /* CopyFiles */, + E72783F3159BDF4C00028D6C /* CopyFiles */, ); buildRules = ( ); dependencies = ( + 0CCA418115C89ECD002AEC4C /* PBXTargetDependency */, + 18F7F67414D77EE900F88A12 /* PBXTargetDependency */, + 4C3AD81E157589380047A498 /* PBXTargetDependency */, + E7EE5A34139DC042005C78BE /* PBXTargetDependency */, + 4CEC096F15758EAF008EB037 /* PBXTargetDependency */, + E79D3389135CBEB1005777CF /* PBXTargetDependency */, + E7E0D8FB158FAB3B002CA176 /* PBXTargetDependency */, + 4ACED92B15A1095B0060775A /* PBXTargetDependency */, + 4CC92B2515A3C6DE00C6D578 /* PBXTargetDependency */, + 4C2FEC60157571F80008BE39 /* PBXTargetDependency */, + ); + name = SecurityTests; + productName = SecurityTests; + productReference = E710C7421331946400F85568 /* SecurityTests.app */; + productType = "com.apple.product-type.application"; + }; + E7B01BBD166594AB000485F1 /* SyncDevTest2 */ = { + isa = PBXNativeTarget; + buildConfigurationList = E7B01BEF166594AB000485F1 /* Build configuration list for PBXNativeTarget "SyncDevTest2" */; + buildPhases = ( + E7B01BC2166594AB000485F1 /* Sources */, + E7B01BD1166594AB000485F1 /* Frameworks */, + E7B01BE3166594AB000485F1 /* Resources */, ); - name = cloud_keychain_diagnose; - productName = cloud_keychain_diagnose; - productReference = 72756BFE175D485D00F52070 /* cloud_keychain_diagnose */; - productType = "com.apple.product-type.tool"; + buildRules = ( + ); + dependencies = ( + E7B01BBE166594AB000485F1 /* PBXTargetDependency */, + E7B01BC0166594AB000485F1 /* PBXTargetDependency */, + ); + name = SyncDevTest2; + productName = Keychain; + productReference = E7B01BF2166594AB000485F1 /* SyncDevTest2.app */; + productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 18073841146D0D4E00F05C24 /* Project object */ = { + 4C35DB69094F906D002917C4 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0420; - TargetAttributes = { - 37A7CEAA197DB8FA00926CE8 = { - CreatedOnToolsVersion = 6.0; - }; - }; + LastUpgradeCheck = 0600; }; - buildConfigurationList = 18073844146D0D4E00F05C24 /* Build configuration list for PBXProject "Security" */; + buildConfigurationList = 4C35DB6A094F906D002917C4 /* Build configuration list for PBXProject "Security" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, + Japanese, + French, + German, en, ); - mainGroup = 1807383F146D0D4E00F05C24; - productRefGroup = 1807384C146D0D4E00F05C24 /* Products */; + mainGroup = 4C35DB67094F906D002917C4; + productRefGroup = 4C35DC36094F9120002917C4 /* Products */; projectDirPath = ""; projectReferences = ( { - ProductGroup = 18270F0914CF43C000B05E7F /* Products */; - ProjectRef = 18270F0814CF43C000B05E7F /* libDER.xcodeproj */; - }, - { - ProductGroup = 1879B5BD146DE6C8007E536C /* Products */; - ProjectRef = 1879B5BC146DE6C8007E536C /* libsecurity_apple_csp.xcodeproj */; - }, - { - ProductGroup = 1879B5CA146DE6CE007E536C /* Products */; - ProjectRef = 1879B5C9146DE6CE007E536C /* libsecurity_apple_cspdl.xcodeproj */; - }, - { - ProductGroup = 1879B5D6146DE6D7007E536C /* Products */; - ProjectRef = 1879B5D5146DE6D7007E536C /* libsecurity_apple_file_dl.xcodeproj */; - }, - { - ProductGroup = 1879B5E2146DE6E7007E536C /* Products */; - ProjectRef = 1879B5E1146DE6E7007E536C /* libsecurity_apple_x509_cl.xcodeproj */; - }, - { - ProductGroup = 1879B5F1146DE6FD007E536C /* Products */; - ProjectRef = 1879B5F0146DE6FD007E536C /* libsecurity_apple_x509_tp.xcodeproj */; - }, - { - ProductGroup = 1879B5FD146DE704007E536C /* Products */; - ProjectRef = 1879B5FC146DE704007E536C /* libsecurity_asn1.xcodeproj */; - }, - { - ProductGroup = 1879B60A146DE70A007E536C /* Products */; - ProjectRef = 1879B609146DE70A007E536C /* libsecurity_authorization.xcodeproj */; - }, - { - ProductGroup = 1879B616146DE715007E536C /* Products */; - ProjectRef = 1879B615146DE715007E536C /* libsecurity_cdsa_client.xcodeproj */; + ProductGroup = 4C8786A20B03E05D00BB77D4 /* Products */; + ProjectRef = 4C8786A10B03E05D00BB77D4 /* libDER.xcodeproj */; }, { - ProductGroup = 1879B622146DE720007E536C /* Products */; - ProjectRef = 1879B621146DE720007E536C /* libsecurity_cdsa_plugin.xcodeproj */; + ProductGroup = 795CA97B0D38269B00BAE6A2 /* Products */; + ProjectRef = 795CA97A0D38269B00BAE6A2 /* libsecurity_asn1.xcodeproj */; }, { - ProductGroup = 1879B551146DE227007E536C /* Products */; - ProjectRef = 1879B550146DE227007E536C /* libsecurity_cdsa_utilities.xcodeproj */; + ProductGroup = 79BDD3950D60D5F9000D84D3 /* Products */; + ProjectRef = 79BDD3940D60D5F9000D84D3 /* libsecurity_smime.xcodeproj */; }, { - ProductGroup = 1879B548146DE212007E536C /* Products */; - ProjectRef = 1879B547146DE212007E536C /* libsecurity_cdsa_utils.xcodeproj */; + ProductGroup = 0C95404014E473AA00077526 /* Products */; + ProjectRef = 0C95403F14E473AA00077526 /* libsecurity_ssl.xcodeproj */; }, { - ProductGroup = 1879B638146DE748007E536C /* Products */; - ProjectRef = 1879B637146DE748007E536C /* libsecurity_checkpw.xcodeproj */; + ProductGroup = 0C25A872122726540050C2BD /* Products */; + ProjectRef = 0C25A871122726540050C2BD /* regressions.xcodeproj */; }, { - ProductGroup = 1879B64C146DE750007E536C /* Products */; - ProjectRef = 1879B64B146DE750007E536C /* libsecurity_cms.xcodeproj */; + ProductGroup = 18F7F65914D77DF700F88A12 /* Products */; + ProjectRef = 18F7F65814D77DF700F88A12 /* sec.xcodeproj */; }, { - ProductGroup = 1879B658146DE756007E536C /* Products */; - ProjectRef = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; + ProductGroup = 051D8F83194913E500AEF66A /* Products */; + ProjectRef = 051D8F82194913E500AEF66A /* Security.xcodeproj */; }, { - ProductGroup = 1879B66E146DE75D007E536C /* Products */; - ProjectRef = 1879B66D146DE75D007E536C /* libsecurity_comcryption.xcodeproj */; + ProductGroup = 05EF68801949143A007958C3 /* Products */; + ProjectRef = 05EF687F1949143A007958C3 /* securityd.xcodeproj */; }, { - ProductGroup = 1879B67A146DE76E007E536C /* Products */; - ProjectRef = 1879B679146DE76E007E536C /* libsecurity_cryptkit.xcodeproj */; + ProductGroup = 05EF68AA19491453007958C3 /* Products */; + ProjectRef = 05EF68A919491453007958C3 /* SecurityTool.xcodeproj */; }, { - ProductGroup = 1879B55E146DE244007E536C /* Products */; - ProjectRef = 1879B55D146DE244007E536C /* libsecurity_cssm.xcodeproj */; + ProductGroup = 0CF55E5614DB47DE003AD8F2 /* Products */; + ProjectRef = 0CF55E5514DB47DE003AD8F2 /* tlsnke.xcodeproj */; }, { - ProductGroup = 1879B695146DE797007E536C /* Products */; - ProjectRef = 1879B694146DE797007E536C /* libsecurity_filedb.xcodeproj */; - }, - { - ProductGroup = 1879B6A1146DE79F007E536C /* Products */; - ProjectRef = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; - }, - { - ProductGroup = 1879B6C8146DE7D7007E536C /* Products */; - ProjectRef = 1879B6C7146DE7D7007E536C /* libsecurity_manifest.xcodeproj */; - }, - { - ProductGroup = 1879B6D4146DE7E0007E536C /* Products */; - ProjectRef = 1879B6D3146DE7E0007E536C /* libsecurity_mds.xcodeproj */; - }, - { - ProductGroup = 1879B6E0146DE7E7007E536C /* Products */; - ProjectRef = 1879B6DF146DE7E7007E536C /* libsecurity_ocspd.xcodeproj */; - }, - { - ProductGroup = 1879B6ED146DE7EE007E536C /* Products */; - ProjectRef = 1879B6EC146DE7EE007E536C /* libsecurity_pkcs12.xcodeproj */; - }, - { - ProductGroup = 1879B6F9146DE7F7007E536C /* Products */; - ProjectRef = 1879B6F8146DE7F7007E536C /* libsecurity_sd_cspdl.xcodeproj */; - }, - { - ProductGroup = 1879B713146DE825007E536C /* Products */; - ProjectRef = 1879B712146DE825007E536C /* libsecurity_smime.xcodeproj */; - }, - { - ProductGroup = 1879B720146DE839007E536C /* Products */; - ProjectRef = 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */; - }, - { - ProductGroup = 1879B72C146DE844007E536C /* Products */; - ProjectRef = 1879B72B146DE844007E536C /* libsecurity_transform.xcodeproj */; - }, - { - ProductGroup = 1879B533146DDBE5007E536C /* Products */; - ProjectRef = 1879B532146DDBE5007E536C /* libsecurity_utilities.xcodeproj */; - }, - { - ProductGroup = 184461A4146E9D3200B12992 /* Products */; - ProjectRef = 184461A3146E9D3200B12992 /* libsecurityd.xcodeproj */; - }, - { - ProductGroup = 0CC3355C16C1EF5D00399E53 /* Products */; - ProjectRef = 0CC3355B16C1EF5D00399E53 /* regressions.xcodeproj */; - }, - { - ProductGroup = 186CDD1714CA11C700AF9171 /* Products */; - ProjectRef = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; - }, - { - ProductGroup = 0C6D77DF15C8C06500BB4405 /* Products */; - ProjectRef = 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */; - }, - { - ProductGroup = 4C12893815FFECF3008CE3E3 /* Products */; - ProjectRef = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; + ProductGroup = 4C2FEC4A15755D700008BE39 /* Products */; + ProjectRef = 4C2FEC4915755D700008BE39 /* utilities.xcodeproj */; }, ); projectRoot = ""; targets = ( - 186F778814E59FB200434E1F /* Security_frameworks */, - 186F778C14E59FDA00434E1F /* Security_executables */, - 0C6C642915D5ADB500BC68CD /* Security_kexts */, - 182BB598146FE295000BF1F3 /* World */, - 1807384A146D0D4E00F05C24 /* Security */, - 182BB567146F4DCA000BF1F3 /* csparser */, - 18FE67E91471A3AA00A2CBE3 /* copyHeaders */, - 18270ED514CF282600B05E7F /* secd */, - 0CC3350716C1ED8000399E53 /* secdtests */, - 0C6C630A15D193C800BC68CD /* sectests */, - 18F234EA15C9F9A600060520 /* authd */, - 5214700516977CB800DF0DB3 /* CloudKeychainProxy */, - 4CB23B45169F5873003A0131 /* security2 */, - 4CC7A7B216CC2A84003E10C1 /* Cloud Keychain Utility */, - 4C96F7C016D6DF8300D3B39D /* Keychain Circle Notification */, - 4CE4729E16D833FD009070D1 /* Security_temporary_UI */, - 72756BFD175D485D00F52070 /* cloud_keychain_diagnose */, - 721680A4179B40F600406BB4 /* iCloudStats */, - 37A7CEAA197DB8FA00926CE8 /* codesign_tests */, + 05EF68B519491512007958C3 /* Security_frameworks */, + 05EF68BB194915A5007958C3 /* Security_executables */, + 05EF68C1194915FB007958C3 /* Security_kexts */, + 05EF68AF1949149C007958C3 /* Security_temporary_UI */, + 4C91273D0ADBF46200AF202E /* world */, + 4C541F950F250C3000E508AE /* phase1 */, + 4C541F840F250BF500E508AE /* phase2 */, + 0C7CFA2E14E1BA4800DF9D95 /* phase1_ios */, + 4C32C0AE0A4975F6002891BD /* Security */, + 790851B50CA9859F0083CC4D /* securityd */, + 4CB740A20A47567C00D641BB /* securitytool */, + 7913B1FF0D172B3900601FE9 /* sslServer */, + 4CE5A54C09C796E100D27A3F /* sslViewer */, + 4C9DE9D11181AC4800CF5C27 /* sslEcdsa */, + 0C6799F912F7C37C00712919 /* dtlsTests */, + E710C7411331946400F85568 /* SecurityTests */, + 4C711D5813AFCD0900FE865D /* SecurityDevTests */, + 79DCEA53134A27D2007F57DC /* codesign_wrapper */, + 52DE81681636347500F49F0C /* Keychain */, + E75533E01651D8A900D2B847 /* CKd-only */, + E7B01BBD166594AB000485F1 /* SyncDevTest2 */, + 52D82BDD16A621F70078DFE5 /* CloudKeychainProxy */, + 728B56A016D59979008FA3AB /* OTAPKIAssetTool */, + 4C52D0B316EFC61E0079966E /* CircleJoinRequested */, + 5346480017331E1100FE9172 /* KeychainSyncAccountNotification */, + 0C0BDB2E175685B000BC1A7E /* secdtests */, + 72979BE1175D095900BE8FD6 /* cloud_keychain_diagnose */, + BE197F2519116FD100BA91D1 /* SharedWebCredentialViewService */, + BE442BA018B7FDB800F24DAE /* swcagent */, ); }; /* End PBXProject section */ /* Begin PBXReferenceProxy section */ - 0C4EAE721766865000773425 /* libsecdRegressions.a */ = { + 051D8FD7194913E700AEF66A /* Security.framework */ = { isa = PBXReferenceProxy; - fileType = archive.ar; - path = libsecdRegressions.a; - remoteRef = 0C4EAE711766865000773425 /* PBXContainerItemProxy */; + fileType = wrapper.framework; + path = Security.framework; + remoteRef = 051D8FD6194913E700AEF66A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 0C6D77CD15C8B66000BB4405 /* libsecurity_ssl_kext.a */ = { + 051D8FD9194913E700AEF66A /* csparser.bundle */ = { isa = PBXReferenceProxy; - fileType = archive.ar; - path = libsecurity_ssl_kext.a; - remoteRef = 0C6D77CC15C8B66000BB4405 /* PBXContainerItemProxy */; + fileType = wrapper.cfbundle; + path = csparser.bundle; + remoteRef = 051D8FD8194913E700AEF66A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 0C6D77CF15C8B66000BB4405 /* libsecurity_ssl_regressions.a */ = { + 051D8FDB194913E700AEF66A /* Security.framework */ = { isa = PBXReferenceProxy; - fileType = archive.ar; - path = libsecurity_ssl_regressions.a; - remoteRef = 0C6D77CE15C8B66000BB4405 /* PBXContainerItemProxy */; + fileType = wrapper.framework; + path = Security.framework; + remoteRef = 051D8FDA194913E700AEF66A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 0C6D77D115C8B66000BB4405 /* dtlsEchoClient */ = { + 051D8FDD194913E700AEF66A /* secd */ = { isa = PBXReferenceProxy; fileType = "compiled.mach-o.executable"; - path = dtlsEchoClient; - remoteRef = 0C6D77D015C8B66000BB4405 /* PBXContainerItemProxy */; + path = secd; + remoteRef = 051D8FDC194913E700AEF66A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 0C6D77D315C8B66000BB4405 /* dtlsEchoServer */ = { + 051D8FDF194913E700AEF66A /* secdtests */ = { isa = PBXReferenceProxy; fileType = "compiled.mach-o.executable"; - path = dtlsEchoServer; - remoteRef = 0C6D77D215C8B66000BB4405 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 0C6D77E915C8C06600BB4405 /* tlsnke.kext */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = tlsnke.kext; - remoteRef = 0C6D77E815C8C06600BB4405 /* PBXContainerItemProxy */; + path = secdtests; + remoteRef = 051D8FDE194913E700AEF66A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 0C6D77EB15C8C06600BB4405 /* tlsnketest */ = { + 051D8FE1194913E700AEF66A /* sectests */ = { isa = PBXReferenceProxy; fileType = "compiled.mach-o.executable"; - path = tlsnketest; - remoteRef = 0C6D77EA15C8C06600BB4405 /* PBXContainerItemProxy */; + path = sectests; + remoteRef = 051D8FE0194913E700AEF66A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 0C6D77ED15C8C06600BB4405 /* libtlssocket.a */ = { + 051D8FE3194913E700AEF66A /* authd.xpc */ = { isa = PBXReferenceProxy; - fileType = archive.ar; - path = libtlssocket.a; - remoteRef = 0C6D77EC15C8C06600BB4405 /* PBXContainerItemProxy */; + fileType = wrapper.cfbundle; + path = authd.xpc; + remoteRef = 051D8FE2194913E700AEF66A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 0CBD50B316C325F000713B6C /* libsecurity_keychain_regressions.a */ = { + 051D8FE5194913E700AEF66A /* CloudKeychainProxy.bundle */ = { isa = PBXReferenceProxy; - fileType = archive.ar; - path = libsecurity_keychain_regressions.a; - remoteRef = 0CBD50B216C325F000713B6C /* PBXContainerItemProxy */; + fileType = wrapper.cfbundle; + path = CloudKeychainProxy.bundle; + remoteRef = 051D8FE4194913E700AEF66A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 0CC3356016C1EF5D00399E53 /* libregressions.a */ = { + 051D8FE7194913E700AEF66A /* security2 */ = { isa = PBXReferenceProxy; - fileType = archive.ar; - path = libregressions.a; - remoteRef = 0CC3355F16C1EF5D00399E53 /* PBXContainerItemProxy */; + fileType = "compiled.mach-o.executable"; + path = security2; + remoteRef = 051D8FE6194913E700AEF66A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 18270C7D14CE573D00B05E7F /* libsecurityd.a */ = { + 051D8FE9194913E700AEF66A /* Cloud Keychain Utility.app */ = { isa = PBXReferenceProxy; - fileType = archive.ar; - path = libsecurityd.a; - remoteRef = 18270C7C14CE573D00B05E7F /* PBXContainerItemProxy */; + fileType = wrapper.application; + path = "Cloud Keychain Utility.app"; + remoteRef = 051D8FE8194913E700AEF66A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 18270F1214CF43C000B05E7F /* libDER.a */ = { + 051D8FEB194913E700AEF66A /* Keychain Circle Notification.app */ = { isa = PBXReferenceProxy; - fileType = archive.ar; - path = libDER.a; - remoteRef = 18270F1114CF43C000B05E7F /* PBXContainerItemProxy */; + fileType = wrapper.application; + path = "Keychain Circle Notification.app"; + remoteRef = 051D8FEA194913E700AEF66A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 18270F1414CF43C000B05E7F /* parseCert */ = { + 051D8FED194913E700AEF66A /* cloud_keychain_diagnose */ = { isa = PBXReferenceProxy; fileType = "compiled.mach-o.executable"; - path = parseCert; - remoteRef = 18270F1314CF43C000B05E7F /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 18270F1614CF43C000B05E7F /* libDERUtils.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libDERUtils.a; - remoteRef = 18270F1514CF43C000B05E7F /* PBXContainerItemProxy */; + path = cloud_keychain_diagnose; + remoteRef = 051D8FEC194913E700AEF66A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 18270F1814CF43C000B05E7F /* parseCrl */ = { + 05EF68A51949143A007958C3 /* securityd */ = { isa = PBXReferenceProxy; fileType = "compiled.mach-o.executable"; - path = parseCrl; - remoteRef = 18270F1714CF43C000B05E7F /* PBXContainerItemProxy */; + path = securityd; + remoteRef = 05EF68A41949143A007958C3 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 18270F1A14CF43C000B05E7F /* parseTicket */ = { + 05EF68AE19491453007958C3 /* security */ = { isa = PBXReferenceProxy; fileType = "compiled.mach-o.executable"; - path = parseTicket; - remoteRef = 18270F1914CF43C000B05E7F /* PBXContainerItemProxy */; + path = security; + remoteRef = 05EF68AD19491453007958C3 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 18270F6014CF655B00B05E7F /* libsecipc_client.a */ = { + 0C0BDB821756A1D700BC1A7E /* libsecdRegressions.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecipc_client.a; - remoteRef = 18270F5F14CF655B00B05E7F /* PBXContainerItemProxy */; + path = libsecdRegressions.a; + remoteRef = 0C0BDB811756A1D700BC1A7E /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 184461B1146E9D3300B12992 /* libsecurityd_client.a */ = { + 0C271D6E15C8C68800560531 /* libsecurity_ssl_kext.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecurityd_client.a; - remoteRef = 184461B0146E9D3300B12992 /* PBXContainerItemProxy */; + path = libsecurity_ssl_kext.a; + remoteRef = 0C271D6D15C8C68800560531 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 184461B5146E9D3300B12992 /* libsecurityd_server.a */ = { + 0C62D60814E0588700A97963 /* libtlssocket.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecurityd_server.a; - remoteRef = 184461B4146E9D3300B12992 /* PBXContainerItemProxy */; + path = libtlssocket.a; + remoteRef = 0C62D60714E0588700A97963 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 184461B9146E9D3300B12992 /* ucspc.a */ = { + 0CCA406A15C73CA1002AEC4C /* libsecurity_ssl.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = ucspc.a; - remoteRef = 184461B8146E9D3300B12992 /* PBXContainerItemProxy */; + path = libsecurity_ssl.a; + remoteRef = 0CCA406915C73CA1002AEC4C /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 186CDD1E14CA11C700AF9171 /* libSecItemShimOSX.a */ = { + 0CCA418415C89ECD002AEC4C /* libsecurity_ssl_regressions.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libSecItemShimOSX.a; - remoteRef = 186CDD1D14CA11C700AF9171 /* PBXContainerItemProxy */; + path = libsecurity_ssl_regressions.a; + remoteRef = 0CCA418315C89ECD002AEC4C /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B538146DDBE5007E536C /* libsecurity_utilities.a */ = { + 0CCA42F115C8A806002AEC4C /* dtlsEchoClient */ = { isa = PBXReferenceProxy; - fileType = archive.ar; - path = libsecurity_utilities.a; - remoteRef = 1879B537146DDBE5007E536C /* PBXContainerItemProxy */; + fileType = "compiled.mach-o.executable"; + path = dtlsEchoClient; + remoteRef = 0CCA42F015C8A806002AEC4C /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B54F146DE212007E536C /* libsecurity_cdsa_utils.a */ = { + 0CCA42F315C8A806002AEC4C /* dtlsEchoServer */ = { isa = PBXReferenceProxy; - fileType = archive.ar; - path = libsecurity_cdsa_utils.a; - remoteRef = 1879B54E146DE212007E536C /* PBXContainerItemProxy */; + fileType = "compiled.mach-o.executable"; + path = dtlsEchoServer; + remoteRef = 0CCA42F215C8A806002AEC4C /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B55A146DE227007E536C /* libsecurity_cdsa_utilities.a */ = { + 0CF55E6014DB47DF003AD8F2 /* tlsnke.kext */ = { isa = PBXReferenceProxy; - fileType = archive.ar; - path = libsecurity_cdsa_utilities.a; - remoteRef = 1879B559146DE227007E536C /* PBXContainerItemProxy */; + fileType = wrapper.cfbundle; + path = tlsnke.kext; + remoteRef = 0CF55E5F14DB47DF003AD8F2 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B55C146DE227007E536C /* Schemas */ = { + 0CF55E6214DB47DF003AD8F2 /* tlsnketest */ = { isa = PBXReferenceProxy; fileType = "compiled.mach-o.executable"; - path = Schemas; - remoteRef = 1879B55B146DE227007E536C /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 1879B565146DE244007E536C /* libsecurity_cssm.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libsecurity_cssm.a; - remoteRef = 1879B564146DE244007E536C /* PBXContainerItemProxy */; + path = tlsnketest; + remoteRef = 0CF55E6114DB47DF003AD8F2 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B5C6146DE6C8007E536C /* libsecurity_apple_csp.a */ = { + 18F7F66314D77DF700F88A12 /* libsecurity.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecurity_apple_csp.a; - remoteRef = 1879B5C5146DE6C8007E536C /* PBXContainerItemProxy */; + path = libsecurity.a; + remoteRef = 18F7F66214D77DF700F88A12 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B5D2146DE6CE007E536C /* libsecurity_apple_cspdl.a */ = { + 18F7F66514D77DF700F88A12 /* libsecurityd.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecurity_apple_cspdl.a; - remoteRef = 1879B5D1146DE6CE007E536C /* PBXContainerItemProxy */; + path = libsecurityd.a; + remoteRef = 18F7F66414D77DF700F88A12 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B5DE146DE6D7007E536C /* libsecurity_apple_file_dl.a */ = { + 18F7F66714D77DF700F88A12 /* libSecItemShimOSX.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecurity_apple_file_dl.a; - remoteRef = 1879B5DD146DE6D7007E536C /* PBXContainerItemProxy */; + path = libSecItemShimOSX.a; + remoteRef = 18F7F66614D77DF700F88A12 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B5EB146DE6E8007E536C /* libsecurity_apple_x509_cl.a */ = { + 18F7F66914D77DF700F88A12 /* libsecipc_client.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecurity_apple_x509_cl.a; - remoteRef = 1879B5EA146DE6E8007E536C /* PBXContainerItemProxy */; + path = libsecipc_client.a; + remoteRef = 18F7F66814D77DF700F88A12 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B5EF146DE6E8007E536C /* apple_x509_cl.bundle */ = { + 4C0789C2113F4C7400422E2D /* parseTicket */ = { isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = apple_x509_cl.bundle; - remoteRef = 1879B5EE146DE6E8007E536C /* PBXContainerItemProxy */; + fileType = "compiled.mach-o.executable"; + path = parseTicket; + remoteRef = 4C0789C1113F4C7400422E2D /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B5F9146DE6FD007E536C /* libsecurity_apple_x509_tp.a */ = { + 4C2FEC5115755D710008BE39 /* libutilities.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecurity_apple_x509_tp.a; - remoteRef = 1879B5F8146DE6FD007E536C /* PBXContainerItemProxy */; + path = libutilities.a; + remoteRef = 4C2FEC5015755D710008BE39 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B612146DE70A007E536C /* libsecurity_authorization.a */ = { + 4C60888B155C943D00A0904F /* libSecureObjectSync.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecurity_authorization.a; - remoteRef = 1879B611146DE70A007E536C /* PBXContainerItemProxy */; + path = libSecureObjectSync.a; + remoteRef = 4C60888A155C943D00A0904F /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B61E146DE715007E536C /* libsecurity_cdsa_client.a */ = { + 4C60888D155C943D00A0904F /* libSOSRegressions.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecurity_cdsa_client.a; - remoteRef = 1879B61D146DE715007E536C /* PBXContainerItemProxy */; + path = libSOSRegressions.a; + remoteRef = 4C60888C155C943D00A0904F /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B62B146DE720007E536C /* libsecurity_cdsa_plugin.a */ = { + 4C8786AD0B03E05E00BB77D4 /* libDER.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecurity_cdsa_plugin.a; - remoteRef = 1879B62A146DE720007E536C /* PBXContainerItemProxy */; + path = libDER.a; + remoteRef = 4C8786AC0B03E05E00BB77D4 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B644146DE748007E536C /* libsecurity_checkpw.a */ = { + 4C8786AF0B03E05E00BB77D4 /* parseCert */ = { isa = PBXReferenceProxy; - fileType = archive.ar; - path = libsecurity_checkpw.a; - remoteRef = 1879B643146DE748007E536C /* PBXContainerItemProxy */; + fileType = "compiled.mach-o.executable"; + path = parseCert; + remoteRef = 4C8786AE0B03E05E00BB77D4 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B648146DE748007E536C /* test-checkpw */ = { + 4C8786B10B03E05E00BB77D4 /* libDERUtils.a */ = { isa = PBXReferenceProxy; - fileType = "compiled.mach-o.executable"; - path = "test-checkpw"; - remoteRef = 1879B647146DE748007E536C /* PBXContainerItemProxy */; + fileType = archive.ar; + path = libDERUtils.a; + remoteRef = 4C8786B00B03E05E00BB77D4 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B64A146DE748007E536C /* perf-checkpw */ = { + 4C8786B30B03E05E00BB77D4 /* parseCrl */ = { isa = PBXReferenceProxy; fileType = "compiled.mach-o.executable"; - path = "perf-checkpw"; - remoteRef = 1879B649146DE748007E536C /* PBXContainerItemProxy */; + path = parseCrl; + remoteRef = 4C8786B20B03E05E00BB77D4 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B654146DE750007E536C /* libsecurity_cms.a */ = { + 4CC92B1A15A3BF1E00C6D578 /* libsecuritydRegressions.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecurity_cms.a; - remoteRef = 1879B653146DE750007E536C /* PBXContainerItemProxy */; + path = libsecuritydRegressions.a; + remoteRef = 4CC92B1915A3BF1E00C6D578 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B666146DE757007E536C /* libsecurity_codesigning.a */ = { + 52849FAE164462E7005CDF23 /* libCloudKeychainProxy.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecurity_codesigning.a; - remoteRef = 1879B665146DE757007E536C /* PBXContainerItemProxy */; + path = libCloudKeychainProxy.a; + remoteRef = 52849FAD164462E7005CDF23 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B66A146DE757007E536C /* libintegrity.a */ = { + 795CA9860D38269B00BAE6A2 /* libASN1.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libintegrity.a; - remoteRef = 1879B669146DE757007E536C /* PBXContainerItemProxy */; + path = libASN1.a; + remoteRef = 795CA9850D38269B00BAE6A2 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B66C146DE757007E536C /* libcodehost.a */ = { + 79BDD39B0D60D5F9000D84D3 /* security_smime */ = { isa = PBXReferenceProxy; - fileType = archive.ar; - path = libcodehost.a; - remoteRef = 1879B66B146DE757007E536C /* PBXContainerItemProxy */; + fileType = "compiled.mach-o.dylib"; + path = security_smime; + remoteRef = 79BDD39A0D60D5F9000D84D3 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B676146DE75E007E536C /* libsecurity_comcryption.a */ = { + 79BDD39D0D60D5F9000D84D3 /* security_smime.framework */ = { isa = PBXReferenceProxy; - fileType = archive.ar; - path = libsecurity_comcryption.a; - remoteRef = 1879B675146DE75E007E536C /* PBXContainerItemProxy */; + fileType = wrapper.framework; + path = security_smime.framework; + remoteRef = 79BDD39C0D60D5F9000D84D3 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B684146DE76F007E536C /* libsecurity_cryptkit.a */ = { + 79BDD39F0D60D5F9000D84D3 /* libCMS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecurity_cryptkit.a; - remoteRef = 1879B683146DE76F007E536C /* PBXContainerItemProxy */; + path = libCMS.a; + remoteRef = 79BDD39E0D60D5F9000D84D3 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B688146DE76F007E536C /* libCryptKit.a */ = { + BE442B9B18B7FD6700F24DAE /* libSWCAgent.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libCryptKit.a; - remoteRef = 1879B687146DE76F007E536C /* PBXContainerItemProxy */; + path = libSWCAgent.a; + remoteRef = BE442B9A18B7FD6700F24DAE /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B68A146DE76F007E536C /* CryptKitSignature.a */ = { + E7104A06169E038F00DB0045 /* libSecurityTool.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = CryptKitSignature.a; - remoteRef = 1879B689146DE76F007E536C /* PBXContainerItemProxy */; + path = libSecurityTool.a; + remoteRef = E7104A05169E038F00DB0045 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B69D146DE797007E536C /* libsecurity_filedb.a */ = { + E7104A23169E21C000DB0045 /* libSecurityCommands.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecurity_filedb.a; - remoteRef = 1879B69C146DE797007E536C /* PBXContainerItemProxy */; + path = libSecurityCommands.a; + remoteRef = E7104A22169E21C000DB0045 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B6B3146DE7A0007E536C /* libsecurity_keychain.a */ = { + E710C708133192EA00F85568 /* libregressions.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecurity_keychain.a; - remoteRef = 1879B6B2146DE7A0007E536C /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 1879B6B7146DE7A0007E536C /* XPCKeychainSandboxCheck.xpc */ = { - isa = PBXReferenceProxy; - fileType = wrapper.application; - path = XPCKeychainSandboxCheck.xpc; - remoteRef = 1879B6B6146DE7A0007E536C /* PBXContainerItemProxy */; + path = libregressions.a; + remoteRef = E710C707133192EA00F85568 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B6D0146DE7D7007E536C /* libsecurity_manifest.a */ = { + E76079DB1951FDBF00F69731 /* liblogging.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecurity_manifest.a; - remoteRef = 1879B6CF146DE7D7007E536C /* PBXContainerItemProxy */; + path = liblogging.a; + remoteRef = E76079DA1951FDBF00F69731 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B6DC146DE7E0007E536C /* libsecurity_mds.a */ = { + E777C71515B63C0B004044A8 /* libSecOtrOSX.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecurity_mds.a; - remoteRef = 1879B6DB146DE7E0007E536C /* PBXContainerItemProxy */; + path = libSecOtrOSX.a; + remoteRef = E777C71415B63C0B004044A8 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B6E9146DE7E8007E536C /* libsecurity_ocspd.a */ = { + E79D9CD5159BEA78000834EC /* libSecurityRegressions.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecurity_ocspd.a; - remoteRef = 1879B6E8146DE7E8007E536C /* PBXContainerItemProxy */; + path = libSecurityRegressions.a; + remoteRef = E79D9CD4159BEA78000834EC /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B6F5146DE7EF007E536C /* libsecurity_pkcs12.a */ = { + E7E0D8FE158FAB3B002CA176 /* libutilitiesRegressions.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecurity_pkcs12.a; - remoteRef = 1879B6F4146DE7EF007E536C /* PBXContainerItemProxy */; + path = libutilitiesRegressions.a; + remoteRef = E7E0D8FD158FAB3B002CA176 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B701146DE7F7007E536C /* libsecurity_sd_cspdl.a */ = { + E7FEFB8F169E36B000E18152 /* libSOSCommands.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libsecurity_sd_cspdl.a; - remoteRef = 1879B700146DE7F7007E536C /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 1879B71C146DE825007E536C /* libsecurity_smime.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libsecurity_smime.a; - remoteRef = 1879B71B146DE825007E536C /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 1879B728146DE839007E536C /* libsecurity_ssl.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libsecurity_ssl.a; - remoteRef = 1879B727146DE839007E536C /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 1879B739146DE845007E536C /* libsecurity_transform.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libsecurity_transform.a; - remoteRef = 1879B738146DE845007E536C /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 1879B73D146DE845007E536C /* unit-tests.octest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = "unit-tests.octest"; - remoteRef = 1879B73C146DE845007E536C /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 1879B73F146DE845007E536C /* 100-sha2 */ = { - isa = PBXReferenceProxy; - fileType = "compiled.mach-o.executable"; - path = "100-sha2"; - remoteRef = 1879B73E146DE845007E536C /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 1879B741146DE845007E536C /* input-speed-test */ = { - isa = PBXReferenceProxy; - fileType = "compiled.mach-o.executable"; - path = "input-speed-test"; - remoteRef = 1879B740146DE845007E536C /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 1885B3F914D8D9B100519375 /* libASN1.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libASN1.a; - remoteRef = 1885B3F814D8D9B100519375 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 18D4053B14CE2C1600A2BE4E /* libsecurity.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libsecurity.a; - remoteRef = 18D4053A14CE2C1600A2BE4E /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 4C01DE32164C3793006798CD /* libCloudKeychainProxy.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libCloudKeychainProxy.a; - remoteRef = 4C01DE31164C3793006798CD /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 4C1288EA15FFE9D7008CE3E3 /* libSecureObjectSync.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libSecureObjectSync.a; - remoteRef = 4C1288E915FFE9D7008CE3E3 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 4C1288EC15FFE9D7008CE3E3 /* libSOSRegressions.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libSOSRegressions.a; - remoteRef = 4C1288EB15FFE9D7008CE3E3 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 4C1288EE15FFE9D7008CE3E3 /* libSecurityRegressions.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libSecurityRegressions.a; - remoteRef = 4C1288ED15FFE9D7008CE3E3 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 4C1288F015FFE9D7008CE3E3 /* libsecuritydRegressions.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libsecuritydRegressions.a; - remoteRef = 4C1288EF15FFE9D7008CE3E3 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 4C1288F215FFE9D7008CE3E3 /* libSecOtrOSX.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libSecOtrOSX.a; - remoteRef = 4C1288F115FFE9D7008CE3E3 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 4C12894015FFECF3008CE3E3 /* libutilities.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libutilities.a; - remoteRef = 4C12893F15FFECF3008CE3E3 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 4C12894215FFECF3008CE3E3 /* libutilitiesRegressions.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libutilitiesRegressions.a; - remoteRef = 4C12894115FFECF3008CE3E3 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 4CB23B76169F5873003A0131 /* libSecurityTool.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libSecurityTool.a; - remoteRef = 4CB23B75169F5873003A0131 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 4CB23B78169F5873003A0131 /* libSecurityCommands.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libSecurityCommands.a; - remoteRef = 4CB23B77169F5873003A0131 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 4CB23B7A169F5873003A0131 /* libSOSCommands.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libSOSCommands.a; - remoteRef = 4CB23B79169F5873003A0131 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 52B5A8F6151928B400664F11 /* XPCTimeStampingService.xpc */ = { - isa = PBXReferenceProxy; - fileType = wrapper.application; - path = XPCTimeStampingService.xpc; - remoteRef = 52B5A8F5151928B400664F11 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - C2432A0815C7112A0096DB5B /* gkunpack */ = { - isa = PBXReferenceProxy; - fileType = "compiled.mach-o.executable"; - path = gkunpack; - remoteRef = C2432A0715C7112A0096DB5B /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - EB2E1F58166D6B3700A7EF61 /* com.apple.CodeSigningHelper.xpc */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = com.apple.CodeSigningHelper.xpc; - remoteRef = EB2E1F57166D6B3700A7EF61 /* PBXContainerItemProxy */; + path = libSOSCommands.a; + remoteRef = E7FEFB8E169E36B000E18152 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ - 18073849146D0D4E00F05C24 /* Resources */ = { + 4C32C0AB0A4975F6002891BD /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 53C0E1FF177FB48A00F8A018 /* CloudKeychain.strings in Resources */, + 721146D7177A80CF005B5871 /* AppleESCertificates.plist in Resources */, + 7245AD2A16E80211009096D8 /* AssetVersion.plist in Resources */, + 72F06A9B16D431AA003C8D56 /* GrayListedKeys.plist in Resources */, + 72DCB35016C4371E009213D4 /* Blocked.plist in Resources */, + 72DCB35116C4371E009213D4 /* certsIndex.data in Resources */, + 72DCB35216C4371E009213D4 /* certsTable.data in Resources */, + BE4AC9BA18B8273600B84964 /* SharedWebCredentials.strings in Resources */, + 4C198F220ACDB4BF00AAB142 /* Certificate.strings in Resources */, + 4C198F230ACDB4BF00AAB142 /* OID.strings in Resources */, + 4C494C570F4F884800CDCBFE /* EVRoots.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C711D7213AFCD0900FE865D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 52A23EDD161DEC3F00E271E0 /* Default-568h@2x.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 52D82BDC16A621F70078DFE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 52D82BE516A621F70078DFE5 /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 52DE81671636347500F49F0C /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 1879B4AA146DCA18007E536C /* cssm.mdsinfo in Resources */, - 1844605F146DE93E00B12992 /* csp_capabilities.mdsinfo in Resources */, - 18446060146DE93E00B12992 /* csp_capabilities_common.mds in Resources */, - 18446061146DE93E00B12992 /* csp_common.mdsinfo in Resources */, - 18446062146DE93E00B12992 /* csp_primary.mdsinfo in Resources */, - 184460C7146E7B1E00B12992 /* cspdl_common.mdsinfo in Resources */, - 184460C8146E7B1E00B12992 /* cspdl_csp_capabilities.mdsinfo in Resources */, - 184460C9146E7B1E00B12992 /* cspdl_csp_primary.mdsinfo in Resources */, - 184460CA146E7B1E00B12992 /* cspdl_dl_primary.mdsinfo in Resources */, - 184460E3146E806700B12992 /* dl_common.mdsinfo in Resources */, - 184460E4146E806700B12992 /* dl_primary.mdsinfo in Resources */, - 18446105146E82C800B12992 /* cl_common.mdsinfo in Resources */, - 18446106146E82C800B12992 /* cl_primary.mdsinfo in Resources */, - 18446115146E85A300B12992 /* tp_common.mdsinfo in Resources */, - 18446116146E85A300B12992 /* tp_policyOids.mdsinfo in Resources */, - 18446117146E85A300B12992 /* tp_primary.mdsinfo in Resources */, - 182BB3C5146F1DCB000BF1F3 /* sd_cspdl_common.mdsinfo in Resources */, - 182BB22A146F068B000BF1F3 /* iToolsTrustedApps.plist in Resources */, - 182BB55F146F4544000BF1F3 /* FDEPrefs.plist in Resources */, - 18500F9B14708D0E006F9AB4 /* SecDebugErrorMessages.strings in Resources */, - 18500FA114708F19006F9AB4 /* SecErrorMessages.strings in Resources */, - BE8C5F0A16F7CE450074CF86 /* framework.sb in Resources */, - 188AD8DC1471FE3E0081C619 /* FDELocalizable.strings in Resources */, - 188AD8DD1471FE3E0081C619 /* InfoPlist.strings in Resources */, - 52B006C015238F76005D4556 /* TimeStampingPrefs.plist in Resources */, - 187D6B9315D435BD00E27494 /* authorization.buttons.strings in Resources */, - 187D6B9415D435C700E27494 /* authorization.prompts.strings in Resources */, + 52DE817B1636347600F49F0C /* Default.png in Resources */, + 52DE817D1636347600F49F0C /* Default@2x.png in Resources */, + 52DE817F1636347600F49F0C /* Default-568h@2x.png in Resources */, + 52DE818A1636347600F49F0C /* first.png in Resources */, + 52DE818C1636347600F49F0C /* first@2x.png in Resources */, + 52DE81911636347600F49F0C /* second.png in Resources */, + 52DE81931636347600F49F0C /* second@2x.png in Resources */, + 52704B7E1638F4EB007FEBB0 /* KeychainKeys.png in Resources */, + 52704B881639193F007FEBB0 /* Keychain-Entitlements.plist in Resources */, + 527435AC16A9E6DB001A96FF /* Keychain_114x114.png in Resources */, + 527435AE16A9E6E5001A96FF /* Keychain_72x72.png in Resources */, + 527435B016A9E6EA001A96FF /* Keychain_144x144.png in Resources */, + 5262A64216AA01910038AFC1 /* Keychain_57x57.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 182BB566146F4DCA000BF1F3 /* Resources */ = { + 534647FF17331E1100FE9172 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 5346480817331E1200FE9172 /* InfoPlist.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 4C96F7BF16D6DF8300D3B39D /* Resources */ = { + BE197F2419116FD100BA91D1 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 532847791785076B009118DC /* Localizable.strings in Resources */, - 4CFE1CB916DD4B9C0026E900 /* CloudKeychain.icns in Resources */, - 4C49390D16E51ACE00CE110C /* com.apple.security.keychain-circle-notification.plist in Resources */, - 4C96F7C816D6DF8400D3B39D /* InfoPlist.strings in Resources */, - 4C96F7CE16D6DF8400D3B39D /* Credits.rtf in Resources */, - 4C96F7D416D6DF8400D3B39D /* MainMenu.xib in Resources */, + BE197F61191173F200BA91D1 /* entitlements.plist in Resources */, + BE197F2C19116FD100BA91D1 /* InfoPlist.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 4CC7A7B116CC2A84003E10C1 /* Resources */ = { + E710C7401331946400F85568 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 4C2505B716D2DF9F002CE025 /* Icon.icns in Resources */, - 4CC7A7BA16CC2A85003E10C1 /* InfoPlist.strings in Resources */, - 4CC7A7C016CC2A85003E10C1 /* Credits.rtf in Resources */, - 4CC7A7C616CC2A85003E10C1 /* MainMenu.xib in Resources */, + 5D83979D160259EE0075998F /* Invalid.com.apple.testcard.crt in Resources */, + 52A23EDC161DEC3800E271E0 /* Default-568h@2x.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 5214700416977CB800DF0DB3 /* Resources */ = { + E7B01BE3166594AB000485F1 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 5214702216977E7D00DF0DB3 /* CloudKeychainProxy-Info.plist in Resources */, - 5214701216977CB800DF0DB3 /* InfoPlist.strings in Resources */, + E7B01BE4166594AB000485F1 /* Default.png in Resources */, + E7B01BE5166594AB000485F1 /* Default@2x.png in Resources */, + E7B01BE6166594AB000485F1 /* Default-568h@2x.png in Resources */, + E7B01BE9166594AB000485F1 /* first.png in Resources */, + E7B01BEA166594AB000485F1 /* first@2x.png in Resources */, + E7B01BEB166594AB000485F1 /* second.png in Resources */, + E7B01BEC166594AB000485F1 /* second@2x.png in Resources */, + E7B01BED166594AB000485F1 /* KeychainKeys.png in Resources */, + E7B01BEE166594AB000485F1 /* Keychain-Entitlements.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 18500F9114707E10006F9AB4 /* Run Script Copy XPC Service */ = { + 79C0C6BB134A967000A51BCB /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Run Script Copy XPC Service"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "DST=${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/XPCServices\n\nXPC_SERVICE=XPCKeychainSandboxCheck.xpc\nditto -v ${BUILT_PRODUCTS_DIR}/${XPC_SERVICE} ${DST}/${XPC_SERVICE}\nif [ $0 -ne 0]; then\n exit $0;\nfi\nXPC_SERVICE=XPCTimeStampingService.xpc\nditto -v ${BUILT_PRODUCTS_DIR}/${XPC_SERVICE} ${DST}/${XPC_SERVICE}\n\nif [ $0 -ne 0]; then\n exit $0;\nfi\n\nif [ ! -h ${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/XPCServices ]; then\n ln -s Versions/Current/XPCServices ${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/XPCServices\nfi\n\nif [ ! -h ${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/PlugIns ]; then\n ln -s Versions/Current/PlugIns ${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/PlugIns\nfi\n\n\nexit 0"; - showEnvVarsInLog = 0; + shellScript = "install_name_tool -change /System/Library/Frameworks/CFNetwork.framework/CFNetwork /System/Library/Frameworks/CoreServices.framework/CoreServices \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}\""; }; - 18500F961470828E006F9AB4 /* Run Script Generate Strings */ = { - isa = PBXShellScriptBuildPhase; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 0C0BDB2B175685B000BC1A7E /* Sources */ = { + isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 0C0BDB32175685B000BC1A7E /* main.c in Sources */, ); - inputPaths = ( + runOnlyForDeploymentPostprocessing = 0; + }; + 4C32C0AC0A4975F6002891BD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18F7F67914D77F4400F88A12 /* NtlmGenerator.c in Sources */, + 18F7F67A14D77F4400F88A12 /* ntlmBlobPriv.c in Sources */, + 18F7F67C14D77F5000F88A12 /* SecTask.c in Sources */, + E7B00700170B581D00B27966 /* Security.exp-in in Sources */, ); - name = "Run Script Generate Strings"; - outputPaths = ( + runOnlyForDeploymentPostprocessing = 0; + }; + 4C52D0B016EFC61E0079966E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C3DD6B0179755560093F9D8 /* NSDate+TimeIntervalDescription.m in Sources */, + 4C52D0E816EFCCA30079966E /* NSArray+map.m in Sources */, + 4C52D0E716EFCCA20079966E /* Applicant.m in Sources */, + 4CC3D29D178F698D0070FCC4 /* PersistantState.m in Sources */, + 4C52D0BA16EFC61E0079966E /* CircleJoinRequested.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "DERIVED_SRC=${BUILT_PRODUCTS_DIR}/derived_src\nmkdir -p ${DERIVED_SRC}\n\n# make error message string files\n\nGENDEBUGSTRS[0]=YES; ERRORSTRINGS[0]=${DERIVED_SRC}/SecDebugErrorMessages.strings\nGENDEBUGSTRS[1]=NO ; ERRORSTRINGS[1]=${DERIVED_SRC}/en.lproj/SecErrorMessages.strings\n\nmkdir -p ${DERIVED_SRC}/en.lproj\n\nfor ((ix=0;ix<2;ix++)) ; do\nperl lib/generateErrStrings.pl \\\n${GENDEBUGSTRS[ix]} \\\n${DERIVED_SRC} \\\n${ERRORSTRINGS[ix]} \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/Authorization.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/AuthSession.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/SecureTransport.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/SecBase.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/cssmerr.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/cssmapple.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/CSCommon.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/PrivateHeaders/AuthorizationPriv.h \\\n${PROJECT_DIR}/libsecurity_keychain/lib/MacOSErrorStrings.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/PrivateHeaders/SecureTransportPriv.h\ndone"; - showEnvVarsInLog = 0; }; - 18F2360315CB30EC00060520 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; + 4C711D6313AFCD0900FE865D /* Sources */ = { + isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4CC92B1D15A3BF2F00C6D578 /* testmain.c in Sources */, + 0C78F1CD16A5E1BF00654E08 /* sectask-10-sectask.c in Sources */, + 0C78F1CF16A5E1BF00654E08 /* sectask_ipc.defs in Sources */, ); - inputPaths = ( + runOnlyForDeploymentPostprocessing = 0; + }; + 4C9DE9CF1181AC4800CF5C27 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C9DE9E31181AC8300CF5C27 /* sslEcdsa.cpp in Sources */, + 4C9DEAAD1181B39300CF5C27 /* ioSock.c in Sources */, + 4C9DEAB11181B39800CF5C27 /* sslAppUtils.cpp in Sources */, ); - outputPaths = ( + runOnlyForDeploymentPostprocessing = 0; + }; + 4CB740A00A47567C00D641BB /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E7104A0C169E171900DB0045 /* security_tool_commands.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "DST=${BUILT_PRODUCTS_DIR}/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices\n\nXPC_SERVICE=authd.xpc\nditto -v ${BUILT_PRODUCTS_DIR}/${XPC_SERVICE} ${DST}/${XPC_SERVICE}\n\nexit 0"; - showEnvVarsInLog = 0; }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 0C6C630715D193C800BC68CD /* Sources */ = { + 4CE5A54A09C796E100D27A3F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 0CCEBDB116C2CFC1001BD7F6 /* main.c in Sources */, + 4CE5A55B09C7970A00D27A3F /* SSLViewer.cpp in Sources */, + 4CE5A66009C79E0600D27A3F /* ioSock.c in Sources */, + 4CE5A66109C79E0600D27A3F /* sslAppUtils.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 0CC3351616C1ED8000399E53 /* Sources */ = { + 52D82BDA16A621F70078DFE5 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 0CC3355A16C1EEE700399E53 /* main.c in Sources */, + 52D82BF816A6283F0078DFE5 /* ckdmain.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 18073846146D0D4E00F05C24 /* Sources */ = { + 52DE81651636347500F49F0C /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 18A5493315EFD3690059E6DC /* dummy.cpp in Sources */, - E778BFBC17176DDE00302C14 /* security.exp-in in Sources */, + 52DE81751636347500F49F0C /* main.m in Sources */, + 52DE81791636347600F49F0C /* AppDelegate.m in Sources */, + 52DE81881636347600F49F0C /* FirstViewController.m in Sources */, + 52DE818F1636347600F49F0C /* ToolsViewController.m in Sources */, + 52DE819C163636B900F49F0C /* KCATableViewController.m in Sources */, + 0CD72A5D16D5769A00A4B8A3 /* utilities.c in Sources */, + 52DE819F16363C1A00F49F0C /* KeychainItemCell.m in Sources */, + 5264FB4E163674B50005D258 /* MyKeychain.m in Sources */, + 52CD69FB16384C2000961848 /* KCAItemDetailViewController.m in Sources */, + 52704B811638F610007FEBB0 /* NewPasswordViewController.m in Sources */, + 52704B84163905EE007FEBB0 /* EditItemViewController.m in Sources */, + 52F63A201659F04E0076D2DE /* DeviceViewController.m in Sources */, + 529990541661BA2600C297A2 /* DeviceTableViewController.m in Sources */, + 529990571661BADF00C297A2 /* DeviceItemCell.m in Sources */, + E75112EB166EFBF0008C578B /* PeerListCell.m in Sources */, + 5208F4BD1670027400A49DDA /* SyncViewController.m in Sources */, + 5208F4CF16702D8800A49DDA /* CircleStatusView.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 18270ED214CF282600B05E7F /* Sources */ = { + 534647FD17331E1100FE9172 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 18270EF614CF334A00B05E7F /* server.c in Sources */, + 5346481E173322BD00FE9172 /* KeychainSyncAccountNotification.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 182BB564146F4DCA000BF1F3 /* Sources */ = { + 728B569D16D59979008FA3AB /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 182BB57F146F51A5000BF1F3 /* csparser.cpp in Sources */, + 72CD2BBE16D59AE30064EEE1 /* OTAServiceApp.m in Sources */, + 72CD2BBF16D59AE30064EEE1 /* OTAServicemain.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 18F234E715C9F9A600060520 /* Sources */ = { + 72979BDE175D095900BE8FD6 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 18F2352115C9FA3C00060520 /* agent.c in Sources */, - 18F2352215C9FA3C00060520 /* authdb.c in Sources */, - 18F2352315C9FA3C00060520 /* authitems.c in Sources */, - 18F2352415C9FA3C00060520 /* authtoken.c in Sources */, - 18F2352515C9FA3C00060520 /* authutilities.c in Sources */, - 18F2352615C9FA3C00060520 /* ccaudit.c in Sources */, - 18F2352715C9FA3C00060520 /* crc.c in Sources */, - 18F2352815C9FA3C00060520 /* credential.c in Sources */, - 18F2352915C9FA3C00060520 /* debugging.c in Sources */, - 18F2352B15C9FA3C00060520 /* engine.c in Sources */, - 18F2352C15C9FA3C00060520 /* main.c in Sources */, - 18F2352D15C9FA3C00060520 /* mechanism.c in Sources */, - 18F2352E15C9FA3C00060520 /* object.c in Sources */, - 18F2352F15C9FA3C00060520 /* process.c in Sources */, - 18F2353015C9FA3C00060520 /* rule.c in Sources */, - 18F2353215C9FA3C00060520 /* server.c in Sources */, - 18F2353315C9FA3C00060520 /* session.c in Sources */, - 182A191115D09AFF006AB103 /* connection.c in Sources */, + 72979BF0175D0B2D00BE8FD6 /* cloud_keychain_diagnose.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 37A7CEA7197DB8FA00926CE8 /* Sources */ = { + 790851B30CA9859F0083CC4D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 37A7CEAE197DB8FA00926CE8 /* FatDynamicValidation.c in Sources */, + 790851D40CA9B19D0083CC4D /* server.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 4C96F7BD16D6DF8300D3B39D /* Sources */ = { + 7913B2000D172B3900601FE9 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 4CAEACCC16D6FBF600263776 /* KDSecCircle.m in Sources */, - 4C5DD46A17A5E5D000696A79 /* KNPersistantState.m in Sources */, - 4CD1980E16DD3BDF00A9E8FD /* NSArray+mapWithBlock.m in Sources */, - 4C7D456817BEED0400DDD88F /* NSDictionary+compactDescription.m in Sources */, - 4C7D453D17BEE69B00DDD88F /* NSString+compactDescription.m in Sources */, - 4C96F7CA16D6DF8400D3B39D /* main.m in Sources */, - 4C85DEDB16DBD5BF00ED8D47 /* KDCirclePeer.m in Sources */, - 4C96F7D116D6DF8400D3B39D /* KNAppDelegate.m in Sources */, - 4C7D456917BEED1400DDD88F /* NSSet+compactDescription.m in Sources */, + 7913B2020D172B3900601FE9 /* ioSock.c in Sources */, + 7913B2030D172B3900601FE9 /* sslAppUtils.cpp in Sources */, + 7913B2050D172B3900601FE9 /* sslServer.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 4CB23B42169F5873003A0131 /* Sources */ = { + 79DCEA50134A27D2007F57DC /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 4CB23B81169F58DE003A0131 /* security_tool_commands.c in Sources */, + 79DCEA61134A280F007F57DC /* codesign_wrapper.c in Sources */, + 79DCEA62134A280F007F57DC /* codesign.c in Sources */, + 79DCEA63134A280F007F57DC /* MISEntitlement.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 4CC7A7AF16CC2A84003E10C1 /* Sources */ = { + BE197F2219116FD100BA91D1 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 4C96F76016D5462F00D3B39D /* KDSecCircle.m in Sources */, - 4C85DEDA16DBD5BF00ED8D47 /* KDCirclePeer.m in Sources */, - 4CC7A7BC16CC2A85003E10C1 /* main.m in Sources */, - 4CC7A7C316CC2A85003E10C1 /* KDAppDelegate.m in Sources */, - 4CC7A7F616CD99E2003E10C1 /* KDSecItems.m in Sources */, - 4CD1980D16DD3BDF00A9E8FD /* NSArray+mapWithBlock.m in Sources */, + BE197F5E191173A800BA91D1 /* SWCViewController.m in Sources */, + BE197F3219116FD100BA91D1 /* SWCAppDelegate.m in Sources */, + BE197F2E19116FD100BA91D1 /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 5214700216977CB800DF0DB3 /* Sources */ = { + BE442BAB18B7FDB800F24DAE /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 52C3D236169B56860091D9D3 /* ckdmain.m in Sources */, + BE4AC9A218B7FFAD00B84964 /* swcagent.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 721680A1179B40F600406BB4 /* Sources */ = { + E710C73E1331946400F85568 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 721680A9179B40F600406BB4 /* main.c in Sources */, + 4CC92B1C15A3BF2F00C6D578 /* testmain.c in Sources */, + 0C78F1CC16A5E1BF00654E08 /* sectask-10-sectask.c in Sources */, + 0C78F1CE16A5E1BF00654E08 /* sectask_ipc.defs in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 72756BFA175D485D00F52070 /* Sources */ = { + E7B01BC2166594AB000485F1 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 72756C31175D48C100F52070 /* cloud_keychain_diagnose.c in Sources */, + E7B01BC3166594AB000485F1 /* main.m in Sources */, + E7B01BC4166594AB000485F1 /* AppDelegate.m in Sources */, + E7B01BC5166594AB000485F1 /* FirstViewController.m in Sources */, + E7B01BC6166594AB000485F1 /* ToolsViewController.m in Sources */, + E7B01BC8166594AB000485F1 /* KCATableViewController.m in Sources */, + E7B01BC9166594AB000485F1 /* KeychainItemCell.m in Sources */, + E7B01BCA166594AB000485F1 /* MyKeychain.m in Sources */, + E7B01BCB166594AB000485F1 /* KCAItemDetailViewController.m in Sources */, + E7B01BCC166594AB000485F1 /* NewPasswordViewController.m in Sources */, + E7B01BCD166594AB000485F1 /* EditItemViewController.m in Sources */, + E7B01BCE166594AB000485F1 /* DeviceViewController.m in Sources */, + E7B01BCF166594AB000485F1 /* DeviceTableViewController.m in Sources */, + E7B01BD0166594AB000485F1 /* DeviceItemCell.m in Sources */, + E75112FA166F020E008C578B /* PeerListCell.m in Sources */, + 5208F4BE1670027400A49DDA /* SyncViewController.m in Sources */, + 5208F4D016702D8800A49DDA /* CircleStatusView.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 0C4EAE7917668DFF00773425 /* PBXTargetDependency */ = { + 05EF68B4194914C2007958C3 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecdRegressions; - targetProxy = 0C4EAE7817668DFF00773425 /* PBXContainerItemProxy */; + name = Security_temporary_UI; + targetProxy = 05EF68B3194914C2007958C3 /* PBXContainerItemProxy */; }; - 0C6C632E15D19D2900BC68CD /* PBXTargetDependency */ = { + 05EF68BA19491577007958C3 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_ssl_regressions; - targetProxy = 0C6C632D15D19D2900BC68CD /* PBXContainerItemProxy */; + name = Security_frameworks; + targetProxy = 05EF68B919491577007958C3 /* PBXContainerItemProxy */; }; - 0C6C642E15D5ADC900BC68CD /* PBXTargetDependency */ = { + 05EF68C0194915B6007958C3 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = tlsnke; - targetProxy = 0C6C642D15D5ADC900BC68CD /* PBXContainerItemProxy */; + name = Security_executables; + targetProxy = 05EF68BF194915B6007958C3 /* PBXContainerItemProxy */; }; - 0C6C643015D5AE4C00BC68CD /* PBXTargetDependency */ = { + 05EF68C61949160C007958C3 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_ssl_kext; - targetProxy = 0C6C642F15D5AE4C00BC68CD /* PBXContainerItemProxy */; + name = Security_kexts; + targetProxy = 05EF68C51949160C007958C3 /* PBXContainerItemProxy */; }; - 0CBD50C716C3260D00713B6C /* PBXTargetDependency */ = { + 05EF68C81949166E007958C3 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_keychain_regressions; - targetProxy = 0CBD50C616C3260D00713B6C /* PBXContainerItemProxy */; + name = securityd; + targetProxy = 05EF68C71949166E007958C3 /* PBXContainerItemProxy */; }; - 0CC3350816C1ED8000399E53 /* PBXTargetDependency */ = { + 05EF68CA1949167B007958C3 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libSecureObjectSync; - targetProxy = 0CC3350916C1ED8000399E53 /* PBXContainerItemProxy */; + name = security; + targetProxy = 05EF68C91949167B007958C3 /* PBXContainerItemProxy */; }; - 0CC3350A16C1ED8000399E53 /* PBXTargetDependency */ = { + 0C664AB41759270C0092D3D9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0C0BDB2E175685B000BC1A7E /* secdtests */; + targetProxy = 0C664AB31759270C0092D3D9 /* PBXContainerItemProxy */; + }; + 0C664AD6175938F20092D3D9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurityd; + targetProxy = 0C664AD5175938F20092D3D9 /* PBXContainerItemProxy */; + }; + 0C664AD8175938F90092D3D9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecdRegressions; + targetProxy = 0C664AD7175938F90092D3D9 /* PBXContainerItemProxy */; + }; + 0C664ADA175939490092D3D9 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = utilities; - targetProxy = 0CC3350B16C1ED8000399E53 /* PBXContainerItemProxy */; + targetProxy = 0C664AD9175939490092D3D9 /* PBXContainerItemProxy */; }; - 0CC3350C16C1ED8000399E53 /* PBXTargetDependency */ = { + 0C664ADC1759395E0092D3D9 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libSOSRegressions; - targetProxy = 0CC3350D16C1ED8000399E53 /* PBXContainerItemProxy */; + name = regressions; + targetProxy = 0C664ADB1759395E0092D3D9 /* PBXContainerItemProxy */; }; - 0CC3351016C1ED8000399E53 /* PBXTargetDependency */ = { + 0C664ADE1759396C0092D3D9 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity; - targetProxy = 0CC3351116C1ED8000399E53 /* PBXContainerItemProxy */; + name = libASN1; + targetProxy = 0C664ADD1759396C0092D3D9 /* PBXContainerItemProxy */; }; - 0CC3351216C1ED8000399E53 /* PBXTargetDependency */ = { + 0C664AE0175939740092D3D9 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecipc_client; - targetProxy = 0CC3351316C1ED8000399E53 /* PBXContainerItemProxy */; + name = libDER; + targetProxy = 0C664ADF175939740092D3D9 /* PBXContainerItemProxy */; }; - 0CC3351416C1ED8000399E53 /* PBXTargetDependency */ = { + 0C664AE21759398A0092D3D9 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libSecItemShimOSX; - targetProxy = 0CC3351516C1ED8000399E53 /* PBXContainerItemProxy */; + name = libsecurity; + targetProxy = 0C664AE11759398A0092D3D9 /* PBXContainerItemProxy */; }; - 0CC3356216C1EF8B00399E53 /* PBXTargetDependency */ = { + 0C664AE41759398A0092D3D9 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = regressions; - targetProxy = 0CC3356116C1EF8B00399E53 /* PBXContainerItemProxy */; + name = libSecureObjectSync; + targetProxy = 0C664AE31759398A0092D3D9 /* PBXContainerItemProxy */; }; - 0CCEBDB316C2CFD4001BD7F6 /* PBXTargetDependency */ = { + 0C664AE617593BED0092D3D9 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = regressions; - targetProxy = 0CCEBDB216C2CFD4001BD7F6 /* PBXContainerItemProxy */; + name = libsecipc_client; + targetProxy = 0C664AE517593BED0092D3D9 /* PBXContainerItemProxy */; }; - 0CCEBDBA16C303D8001BD7F6 /* PBXTargetDependency */ = { + 0C7CFA3514E1BA7000DF9D95 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 0CC3350716C1ED8000399E53 /* secdtests */; - targetProxy = 0CCEBDB916C303D8001BD7F6 /* PBXContainerItemProxy */; + name = tlsnketest; + targetProxy = 0C7CFA3414E1BA7000DF9D95 /* PBXContainerItemProxy */; }; - 0CCEBDBD16C30948001BD7F6 /* PBXTargetDependency */ = { + 0C7CFA3714E1BAEC00DF9D95 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = utilitiesRegressions; - targetProxy = 0CCEBDBC16C30948001BD7F6 /* PBXContainerItemProxy */; + target = 4C541F950F250C3000E508AE /* phase1 */; + targetProxy = 0C7CFA3614E1BAEC00DF9D95 /* PBXContainerItemProxy */; }; - 0CFC55E315DDB86500BEC89E /* PBXTargetDependency */ = { + 0C99B740131C984900584CF4 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 0C6C630A15D193C800BC68CD /* sectests */; - targetProxy = 0CFC55E215DDB86500BEC89E /* PBXContainerItemProxy */; + target = 0C6799F912F7C37C00712919 /* dtlsTests */; + targetProxy = 0C99B73F131C984900584CF4 /* PBXContainerItemProxy */; }; - 0CFE4BA7167943EF0077AE4F /* PBXTargetDependency */ = { + 0CC827F2138712B100BD99B7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 0C6C642915D5ADB500BC68CD /* Security_kexts */; - targetProxy = 0CFE4BA6167943EF0077AE4F /* PBXContainerItemProxy */; + target = E710C7411331946400F85568 /* SecurityTests */; + targetProxy = 0CC827F1138712B100BD99B7 /* PBXContainerItemProxy */; }; - 18270EE114CF28D000B05E7F /* PBXTargetDependency */ = { + 0CCA408215C745C6002AEC4C /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity; - targetProxy = 18270EE014CF28D000B05E7F /* PBXContainerItemProxy */; + name = libsecurity_ssl; + targetProxy = 0CCA408115C745C6002AEC4C /* PBXContainerItemProxy */; }; - 18270EE314CF28D900B05E7F /* PBXTargetDependency */ = { + 0CCA418115C89ECD002AEC4C /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurityd; - targetProxy = 18270EE214CF28D900B05E7F /* PBXContainerItemProxy */; + name = libsecurity_ssl_regressions; + targetProxy = 0CCA418015C89ECD002AEC4C /* PBXContainerItemProxy */; }; - 18270F5D14CF655B00B05E7F /* PBXTargetDependency */ = { + 0CCA418615C89EDD002AEC4C /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecipc_client; - targetProxy = 18270F5C14CF655B00B05E7F /* PBXContainerItemProxy */; + name = libsecurity_ssl_regressions; + targetProxy = 0CCA418515C89EDD002AEC4C /* PBXContainerItemProxy */; }; - 182BB22C146F07DD000BF1F3 /* PBXTargetDependency */ = { + 0CCA42F515C8A815002AEC4C /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = XPCKeychainSandboxCheck; - targetProxy = 182BB22B146F07DD000BF1F3 /* PBXContainerItemProxy */; + name = dtlsEchoClient; + targetProxy = 0CCA42F415C8A815002AEC4C /* PBXContainerItemProxy */; }; - 182BB3EC146F2448000BF1F3 /* PBXTargetDependency */ = { + 0CCA42F715C8A820002AEC4C /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_apple_x509_tp; - targetProxy = 182BB3EB146F2448000BF1F3 /* PBXContainerItemProxy */; + name = dtlsEchoServer; + targetProxy = 0CCA42F615C8A820002AEC4C /* PBXContainerItemProxy */; }; - 182BB3EE146F248D000BF1F3 /* PBXTargetDependency */ = { + 0CD72A4C16D54BD300A4B8A3 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_pkcs12; - targetProxy = 182BB3ED146F248D000BF1F3 /* PBXContainerItemProxy */; + name = utilities; + targetProxy = 0CD72A4B16D54BD300A4B8A3 /* PBXContainerItemProxy */; + }; + 0CD72A5A16D55BF100A4B8A3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 52DE81681636347500F49F0C /* Keychain */; + targetProxy = 0CD72A5916D55BF100A4B8A3 /* PBXContainerItemProxy */; }; - 182BB3F0146F248D000BF1F3 /* PBXTargetDependency */ = { + 18F7F66B14D77E8500F88A12 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_transform; - targetProxy = 182BB3EF146F248D000BF1F3 /* PBXContainerItemProxy */; + name = libsecurity; + targetProxy = 18F7F66A14D77E8500F88A12 /* PBXContainerItemProxy */; }; - 182BB3F2146F248D000BF1F3 /* PBXTargetDependency */ = { + 18F7F66D14D77E8D00F88A12 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_ocspd; - targetProxy = 182BB3F1146F248D000BF1F3 /* PBXContainerItemProxy */; + name = libsecipc_client; + targetProxy = 18F7F66C14D77E8D00F88A12 /* PBXContainerItemProxy */; }; - 182BB3F4146F248D000BF1F3 /* PBXTargetDependency */ = { + 18F7F67114D77EC500F88A12 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_comcryption; - targetProxy = 182BB3F3146F248D000BF1F3 /* PBXContainerItemProxy */; + name = libsecurityd; + targetProxy = 18F7F67014D77EC500F88A12 /* PBXContainerItemProxy */; }; - 182BB3F6146F248D000BF1F3 /* PBXTargetDependency */ = { + 18F7F67414D77EE900F88A12 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_checkpw; - targetProxy = 182BB3F5146F248D000BF1F3 /* PBXContainerItemProxy */; + name = libsecurityd; + targetProxy = 18F7F67314D77EE900F88A12 /* PBXContainerItemProxy */; }; - 182BB3F8146F248D000BF1F3 /* PBXTargetDependency */ = { + 18F7F67714D77EFF00F88A12 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_ssl; - targetProxy = 182BB3F7146F248D000BF1F3 /* PBXContainerItemProxy */; + name = libsecurityd; + targetProxy = 18F7F67614D77EFF00F88A12 /* PBXContainerItemProxy */; }; - 182BB3FC146F248D000BF1F3 /* PBXTargetDependency */ = { + 4ACED92B15A1095B0060775A /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_apple_cspdl; - targetProxy = 182BB3FB146F248D000BF1F3 /* PBXContainerItemProxy */; + name = libSecOTRRegressions; + targetProxy = 4ACED92A15A1095B0060775A /* PBXContainerItemProxy */; }; - 182BB3FE146F248D000BF1F3 /* PBXTargetDependency */ = { + 4ACED92F15A10A3E0060775A /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_sd_cspdl; - targetProxy = 182BB3FD146F248D000BF1F3 /* PBXContainerItemProxy */; + name = libSecOTRRegressions; + targetProxy = 4ACED92E15A10A3E0060775A /* PBXContainerItemProxy */; }; - 182BB400146F248D000BF1F3 /* PBXTargetDependency */ = { + 4C1ADEB71615176500E4A8AF /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_manifest; - targetProxy = 182BB3FF146F248D000BF1F3 /* PBXContainerItemProxy */; + name = libSecureObjectSync; + targetProxy = 4C1ADEB61615176500E4A8AF /* PBXContainerItemProxy */; }; - 182BB402146F248D000BF1F3 /* PBXTargetDependency */ = { + 4C2FEC60157571F80008BE39 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_smime; - targetProxy = 182BB401146F248D000BF1F3 /* PBXContainerItemProxy */; + name = libSOSRegressions; + targetProxy = 4C2FEC5F157571F80008BE39 /* PBXContainerItemProxy */; }; - 182BB404146F248D000BF1F3 /* PBXTargetDependency */ = { + 4C2FEC62157572130008BE39 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_cms; - targetProxy = 182BB403146F248D000BF1F3 /* PBXContainerItemProxy */; + name = libSOSRegressions; + targetProxy = 4C2FEC61157572130008BE39 /* PBXContainerItemProxy */; }; - 182BB406146F248D000BF1F3 /* PBXTargetDependency */ = { + 4C3AD81E157589380047A498 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_apple_csp; - targetProxy = 182BB405146F248D000BF1F3 /* PBXContainerItemProxy */; + name = libSecureObjectSync; + targetProxy = 4C3AD81D157589380047A498 /* PBXContainerItemProxy */; }; - 182BB408146F248D000BF1F3 /* PBXTargetDependency */ = { + 4C3AD8201575894C0047A498 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_apple_x509_cl; - targetProxy = 182BB407146F248D000BF1F3 /* PBXContainerItemProxy */; + name = libSecureObjectSync; + targetProxy = 4C3AD81F1575894C0047A498 /* PBXContainerItemProxy */; }; - 182BB40A146F248D000BF1F3 /* PBXTargetDependency */ = { + 4C52D0EE16EFCD720079966E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_keychain; - targetProxy = 182BB409146F248D000BF1F3 /* PBXContainerItemProxy */; + target = 4C52D0B316EFC61E0079966E /* CircleJoinRequested */; + targetProxy = 4C52D0ED16EFCD720079966E /* PBXContainerItemProxy */; }; - 182BB40C146F248D000BF1F3 /* PBXTargetDependency */ = { + 4C541F8C0F250C0400E508AE /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_apple_file_dl; - targetProxy = 182BB40B146F248D000BF1F3 /* PBXContainerItemProxy */; + target = 790851B50CA9859F0083CC4D /* securityd */; + targetProxy = 4C541F8B0F250C0400E508AE /* PBXContainerItemProxy */; }; - 182BB40E146F248D000BF1F3 /* PBXTargetDependency */ = { + 4C541F8E0F250C0900E508AE /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_authorization; - targetProxy = 182BB40D146F248D000BF1F3 /* PBXContainerItemProxy */; + target = 4CB740A20A47567C00D641BB /* securitytool */; + targetProxy = 4C541F8D0F250C0900E508AE /* PBXContainerItemProxy */; }; - 182BB410146F248D000BF1F3 /* PBXTargetDependency */ = { + 4C541F900F250C0E00E508AE /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_cdsa_utilities; - targetProxy = 182BB40F146F248D000BF1F3 /* PBXContainerItemProxy */; + target = 4CE5A54C09C796E100D27A3F /* sslViewer */; + targetProxy = 4C541F8F0F250C0E00E508AE /* PBXContainerItemProxy */; }; - 182BB412146F248D000BF1F3 /* PBXTargetDependency */ = { + 4C541F920F250C1300E508AE /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_cryptkit; - targetProxy = 182BB411146F248D000BF1F3 /* PBXContainerItemProxy */; + target = 7913B1FF0D172B3900601FE9 /* sslServer */; + targetProxy = 4C541F910F250C1300E508AE /* PBXContainerItemProxy */; }; - 182BB414146F248D000BF1F3 /* PBXTargetDependency */ = { + 4C541F9D0F250C3500E508AE /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_cdsa_client; - targetProxy = 182BB413146F248D000BF1F3 /* PBXContainerItemProxy */; + target = 4C32C0AE0A4975F6002891BD /* Security */; + targetProxy = 4C541F9C0F250C3500E508AE /* PBXContainerItemProxy */; }; - 182BB418146F248D000BF1F3 /* PBXTargetDependency */ = { + 4C541F9F0F250C4F00E508AE /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_filedb; - targetProxy = 182BB417146F248D000BF1F3 /* PBXContainerItemProxy */; + target = 4C541F950F250C3000E508AE /* phase1 */; + targetProxy = 4C541F9E0F250C4F00E508AE /* PBXContainerItemProxy */; }; - 182BB41A146F248D000BF1F3 /* PBXTargetDependency */ = { + 4C541FA10F250C5200E508AE /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_mds; - targetProxy = 182BB419146F248D000BF1F3 /* PBXContainerItemProxy */; + target = 4C541F840F250BF500E508AE /* phase2 */; + targetProxy = 4C541FA00F250C5200E508AE /* PBXContainerItemProxy */; }; - 182BB4E7146F25AF000BF1F3 /* PBXTargetDependency */ = { + 4C711D5913AFCD0900FE865D /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_codesigning; - targetProxy = 182BB4E6146F25AF000BF1F3 /* PBXContainerItemProxy */; + name = libDER; + targetProxy = 4C711D5A13AFCD0900FE865D /* PBXContainerItemProxy */; }; - 182BB588146FE001000BF1F3 /* PBXTargetDependency */ = { + 4C711D5F13AFCD0900FE865D /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_codesigning; - targetProxy = 182BB587146FE001000BF1F3 /* PBXContainerItemProxy */; + name = regressions; + targetProxy = 4C711D6013AFCD0900FE865D /* PBXContainerItemProxy */; }; - 182BB58D146FE0FF000BF1F3 /* PBXTargetDependency */ = { + 4C8786B50B03E0A400BB77D4 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_cdsa_utilities; - targetProxy = 182BB58C146FE0FF000BF1F3 /* PBXContainerItemProxy */; + name = libDER; + targetProxy = 4C8786B40B03E0A400BB77D4 /* PBXContainerItemProxy */; }; - 182BB58F146FE11C000BF1F3 /* PBXTargetDependency */ = { + 4C9DE9EF1181ACA000CF5C27 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_utilities; - targetProxy = 182BB58E146FE11C000BF1F3 /* PBXContainerItemProxy */; + target = 4C9DE9D11181AC4800CF5C27 /* sslEcdsa */; + targetProxy = 4C9DE9EE1181ACA000CF5C27 /* PBXContainerItemProxy */; }; - 182BB596146FE27F000BF1F3 /* PBXTargetDependency */ = { + 4CC92B2515A3C6DE00C6D578 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 1807384A146D0D4E00F05C24 /* Security */; - targetProxy = 182BB595146FE27F000BF1F3 /* PBXContainerItemProxy */; + name = libsecuritydRegressions; + targetProxy = 4CC92B2415A3C6DE00C6D578 /* PBXContainerItemProxy */; }; - 18446082146DF52F00B12992 /* PBXTargetDependency */ = { + 4CC92B2D15A3C94500C6D578 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_cdsa_plugin; - targetProxy = 18446081146DF52F00B12992 /* PBXContainerItemProxy */; + name = libsecuritydRegressions; + targetProxy = 4CC92B2C15A3C94500C6D578 /* PBXContainerItemProxy */; }; - 186F779114E5A00F00434E1F /* PBXTargetDependency */ = { + 4CE39042169F87C400026468 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 18270ED514CF282600B05E7F /* secd */; - targetProxy = 186F779014E5A00F00434E1F /* PBXContainerItemProxy */; + name = libSecurityTool; + targetProxy = 4CE39041169F87C400026468 /* PBXContainerItemProxy */; }; - 186F779314E5A01700434E1F /* PBXTargetDependency */ = { + 4CE39044169F87DB00026468 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 1807384A146D0D4E00F05C24 /* Security */; - targetProxy = 186F779214E5A01700434E1F /* PBXContainerItemProxy */; + name = libSecurityTool; + targetProxy = 4CE39043169F87DB00026468 /* PBXContainerItemProxy */; }; - 186F779514E5A01C00434E1F /* PBXTargetDependency */ = { + 4CEC096F15758EAF008EB037 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 182BB567146F4DCA000BF1F3 /* csparser */; - targetProxy = 186F779414E5A01C00434E1F /* PBXContainerItemProxy */; + name = libutilities; + targetProxy = 4CEC096E15758EAF008EB037 /* PBXContainerItemProxy */; }; - 186F779714E5A04200434E1F /* PBXTargetDependency */ = { + 4CEC097115758EC5008EB037 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 18FE67E91471A3AA00A2CBE3 /* copyHeaders */; - targetProxy = 186F779614E5A04200434E1F /* PBXContainerItemProxy */; + name = libutilities; + targetProxy = 4CEC097015758EC5008EB037 /* PBXContainerItemProxy */; }; - 186F779914E5A06500434E1F /* PBXTargetDependency */ = { + 4CEC097515758F0A008EB037 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 186F778814E59FB200434E1F /* Security_frameworks */; - targetProxy = 186F779814E5A06500434E1F /* PBXContainerItemProxy */; + name = libutilities; + targetProxy = 4CEC097415758F0A008EB037 /* PBXContainerItemProxy */; }; - 186F779B14E5A06800434E1F /* PBXTargetDependency */ = { + 4CEC097915758F17008EB037 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 186F778C14E59FDA00434E1F /* Security_executables */; - targetProxy = 186F779A14E5A06800434E1F /* PBXContainerItemProxy */; + name = libutilities; + targetProxy = 4CEC097815758F17008EB037 /* PBXContainerItemProxy */; }; - 1879B545146DE18D007E536C /* PBXTargetDependency */ = { + 4CEC097D15758F23008EB037 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_utilities; - targetProxy = 1879B544146DE18D007E536C /* PBXContainerItemProxy */; + name = libutilities; + targetProxy = 4CEC097C15758F23008EB037 /* PBXContainerItemProxy */; }; - 1879B56C146DE2CF007E536C /* PBXTargetDependency */ = { + 4CEC098715758F60008EB037 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_cdsa_utils; - targetProxy = 1879B56B146DE2CF007E536C /* PBXContainerItemProxy */; + name = libutilities; + targetProxy = 4CEC098615758F60008EB037 /* PBXContainerItemProxy */; }; - 1879B56E146DE2D3007E536C /* PBXTargetDependency */ = { + 52D82BEC16A622100078DFE5 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity_cssm; - targetProxy = 1879B56D146DE2D3007E536C /* PBXContainerItemProxy */; + name = libCloudKeychainProxy; + targetProxy = 52D82BEB16A622100078DFE5 /* PBXContainerItemProxy */; }; - 1885B45114D9AB3D00519375 /* PBXTargetDependency */ = { + 52D82BF216A622600078DFE5 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libASN1; - targetProxy = 1885B45014D9AB3D00519375 /* PBXContainerItemProxy */; + name = utilities; + targetProxy = 52D82BF116A622600078DFE5 /* PBXContainerItemProxy */; }; - 18AD56A614CDED59008233F2 /* PBXTargetDependency */ = { + 52D82BF616A627100078DFE5 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = sec; - targetProxy = 18AD56A514CDED59008233F2 /* PBXContainerItemProxy */; + target = 52D82BDD16A621F70078DFE5 /* CloudKeychainProxy */; + targetProxy = 52D82BF516A627100078DFE5 /* PBXContainerItemProxy */; }; - 18B9655C1472F83C005A4D2E /* PBXTargetDependency */ = { + 5346481B17331ED800FE9172 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = world; - targetProxy = 18B9655B1472F83C005A4D2E /* PBXContainerItemProxy */; + target = 5346480017331E1100FE9172 /* KeychainSyncAccountNotification */; + targetProxy = 5346481A17331ED800FE9172 /* PBXContainerItemProxy */; }; - 18F235FF15CA100300060520 /* PBXTargetDependency */ = { + 5D403D3215C6FE9E0030D492 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 18F234EA15C9F9A600060520 /* authd */; - targetProxy = 18F235FE15CA100300060520 /* PBXContainerItemProxy */; + name = utilities; + targetProxy = 5D403D3115C6FE9E0030D492 /* PBXContainerItemProxy */; }; - 18FE688F1471A4C900A2CBE3 /* PBXTargetDependency */ = { + 5DDD0BEE16D6748900D6C0D6 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 18FE67E91471A3AA00A2CBE3 /* copyHeaders */; - targetProxy = 18FE688E1471A4C900A2CBE3 /* PBXContainerItemProxy */; + target = 728B56A016D59979008FA3AB /* OTAPKIAssetTool */; + targetProxy = 5DDD0BED16D6748900D6C0D6 /* PBXContainerItemProxy */; }; - 37A7CEDA197DBA8700926CE8 /* PBXTargetDependency */ = { + 72D41316175D13E40052A8ED /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 37A7CEAA197DB8FA00926CE8 /* codesign_tests */; - targetProxy = 37A7CED9197DBA8700926CE8 /* PBXContainerItemProxy */; + target = 72979BE1175D095900BE8FD6 /* cloud_keychain_diagnose */; + targetProxy = 72D41315175D13E40052A8ED /* PBXContainerItemProxy */; }; - 4AD6F6F41651CC2500DB4CE6 /* PBXTargetDependency */ = { + 795CA9BD0D3829FC00BAE6A2 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libSecOtrOSX; - targetProxy = 4AD6F6F31651CC2500DB4CE6 /* PBXContainerItemProxy */; + name = libASN1; + targetProxy = 795CA9BC0D3829FC00BAE6A2 /* PBXContainerItemProxy */; }; - 4C01DF13164C3E74006798CD /* PBXTargetDependency */ = { + 79BDD3A50D60D637000D84D3 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libSecureObjectSync; - targetProxy = 4C01DF12164C3E74006798CD /* PBXContainerItemProxy */; + name = cms; + targetProxy = 79BDD3A40D60D637000D84D3 /* PBXContainerItemProxy */; }; - 4C12894415FFED03008CE3E3 /* PBXTargetDependency */ = { + 79DCEA7D134A293D007F57DC /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = utilities; - targetProxy = 4C12894315FFED03008CE3E3 /* PBXContainerItemProxy */; + name = libDER; + targetProxy = 79DCEA7C134A293D007F57DC /* PBXContainerItemProxy */; }; - 4C797BC916D83A3100C7B586 /* PBXTargetDependency */ = { + BE197F631911742900BA91D1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 4C96F7C016D6DF8300D3B39D /* Keychain Circle Notification */; - targetProxy = 4C797BC816D83A3100C7B586 /* PBXContainerItemProxy */; + target = BE197F2519116FD100BA91D1 /* SharedWebCredentialViewService */; + targetProxy = BE197F621911742900BA91D1 /* PBXContainerItemProxy */; }; - 4C797BF116D83A3800C7B586 /* PBXTargetDependency */ = { + BE442B9F18B7FD7D00F24DAE /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 4CC7A7B216CC2A84003E10C1 /* Cloud Keychain Utility */; - targetProxy = 4C797BF016D83A3800C7B586 /* PBXContainerItemProxy */; + name = libSWCAgent; + targetProxy = BE442B9E18B7FD7D00F24DAE /* PBXContainerItemProxy */; }; - 4C7D8764160A746E00D041E3 /* PBXTargetDependency */ = { + BE442BA918B7FDB800F24DAE /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = utilities; - targetProxy = 4C7D8763160A746E00D041E3 /* PBXContainerItemProxy */; + name = libSWCAgent; + targetProxy = BE442BAA18B7FDB800F24DAE /* PBXContainerItemProxy */; }; - 4C8D8650177A75100019A804 /* PBXTargetDependency */ = { + BE4AC9B418B8020400B84964 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecipc_client; - targetProxy = 4C8D864F177A75100019A804 /* PBXContainerItemProxy */; + target = BE442BA018B7FDB800F24DAE /* swcagent */; + targetProxy = BE4AC9B318B8020400B84964 /* PBXContainerItemProxy */; }; - 4CB23B84169F5961003A0131 /* PBXTargetDependency */ = { + E7104A03169E038F00DB0045 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libSOSCommands; - targetProxy = 4CB23B83169F5961003A0131 /* PBXContainerItemProxy */; + name = libSecurityTool; + targetProxy = E7104A02169E038F00DB0045 /* PBXContainerItemProxy */; }; - 4CB23B86169F5971003A0131 /* PBXTargetDependency */ = { + E7104A20169E21C000DB0045 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = libSecurityCommands; - targetProxy = 4CB23B85169F5971003A0131 /* PBXContainerItemProxy */; + targetProxy = E7104A1F169E21C000DB0045 /* PBXContainerItemProxy */; }; - 4CB23B88169F597D003A0131 /* PBXTargetDependency */ = { + E76079FC1951FE1F00F69731 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libSecurityTool; - targetProxy = 4CB23B87169F597D003A0131 /* PBXContainerItemProxy */; + name = liblogging; + targetProxy = E76079FB1951FE1F00F69731 /* PBXContainerItemProxy */; }; - 4CB23B90169F59D8003A0131 /* PBXTargetDependency */ = { + E79D3389135CBEB1005777CF /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 4CB23B45169F5873003A0131 /* security2 */; - targetProxy = 4CB23B8F169F59D8003A0131 /* PBXContainerItemProxy */; + name = regressions; + targetProxy = E79D3388135CBEB1005777CF /* PBXContainerItemProxy */; }; - 5208C0FE16A0D3980062DDC5 /* PBXTargetDependency */ = { + E7B01B8416572132000485F1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = libSecureObjectSync; - targetProxy = 5208C0FD16A0D3980062DDC5 /* PBXContainerItemProxy */; + targetProxy = E7B01B8316572132000485F1 /* PBXContainerItemProxy */; }; - 5214701816977D1D00DF0DB3 /* PBXTargetDependency */ = { + E7B01BA81664294D000485F1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = utilities; - targetProxy = 5214701716977D1D00DF0DB3 /* PBXContainerItemProxy */; + target = 4C32C0AE0A4975F6002891BD /* Security */; + targetProxy = E7B01BA71664294D000485F1 /* PBXContainerItemProxy */; }; - 5214701A16977D2500DF0DB3 /* PBXTargetDependency */ = { + E7B01BBE166594AB000485F1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libCloudKeychainProxy; - targetProxy = 5214701916977D2500DF0DB3 /* PBXContainerItemProxy */; + name = libSecureObjectSync; + targetProxy = E7B01BBF166594AB000485F1 /* PBXContainerItemProxy */; }; - 521470291697842500DF0DB3 /* PBXTargetDependency */ = { + E7B01BC0166594AB000485F1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 5214700516977CB800DF0DB3 /* CloudKeychainProxy */; - targetProxy = 521470281697842500DF0DB3 /* PBXContainerItemProxy */; + name = libSOSRegressions; + targetProxy = E7B01BC1166594AB000485F1 /* PBXContainerItemProxy */; }; - 529FF2201523BD7F0029D842 /* PBXTargetDependency */ = { + E7E0D8FB158FAB3B002CA176 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = XPCTimeStampingService; - targetProxy = 529FF21F1523BD7F0029D842 /* PBXContainerItemProxy */; + name = libutilitiesRegressions; + targetProxy = E7E0D8FA158FAB3B002CA176 /* PBXContainerItemProxy */; }; - 721680B3179B4C6C00406BB4 /* PBXTargetDependency */ = { + E7E0D900158FAB52002CA176 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 721680A4179B40F600406BB4 /* iCloudStats */; - targetProxy = 721680B2179B4C6C00406BB4 /* PBXContainerItemProxy */; + name = libutilitiesRegressions; + targetProxy = E7E0D8FF158FAB52002CA176 /* PBXContainerItemProxy */; }; - 722CF218175D602F00BCE0A5 /* PBXTargetDependency */ = { + E7EE5A34139DC042005C78BE /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 72756BFD175D485D00F52070 /* cloud_keychain_diagnose */; - targetProxy = 722CF217175D602F00BCE0A5 /* PBXContainerItemProxy */; + name = libDER; + targetProxy = E7EE5A33139DC042005C78BE /* PBXContainerItemProxy */; }; - C2432A2515C726B50096DB5B /* PBXTargetDependency */ = { + E7F0FC171651DA5E002BEC2D /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = gkunpack; - targetProxy = C2432A2415C726B50096DB5B /* PBXContainerItemProxy */; + name = utilities; + targetProxy = E7F0FC161651DA5E002BEC2D /* PBXContainerItemProxy */; }; - EBB9FFE01682E71F00FF9774 /* PBXTargetDependency */ = { + E7FEFB93169E377900E18152 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = CodeSigningHelper; - targetProxy = EBB9FFDF1682E71F00FF9774 /* PBXContainerItemProxy */; + name = libSOSCommands; + targetProxy = E7FEFB92169E377900E18152 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ - 18500F9F14708F19006F9AB4 /* SecErrorMessages.strings */ = { - isa = PBXVariantGroup; - children = ( - 18500FA014708F19006F9AB4 /* en */, - ); - name = SecErrorMessages.strings; - path = ../../Security; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 187D6B8F15D4359F00E27494 /* authorization.buttons.strings */ = { - isa = PBXVariantGroup; - children = ( - 187D6B9015D4359F00E27494 /* en */, - ); - name = authorization.buttons.strings; - sourceTree = ""; - }; - 187D6B9115D4359F00E27494 /* authorization.prompts.strings */ = { - isa = PBXVariantGroup; - children = ( - 187D6B9215D4359F00E27494 /* en */, - ); - name = authorization.prompts.strings; - sourceTree = ""; - }; - 188AD8D81471FE3D0081C619 /* FDELocalizable.strings */ = { + 4C198F1D0ACDB4BF00AAB142 /* Certificate.strings */ = { isa = PBXVariantGroup; children = ( - 188AD8D91471FE3D0081C619 /* en */, + 4C198F1E0ACDB4BF00AAB142 /* English */, ); - name = FDELocalizable.strings; + name = Certificate.strings; sourceTree = ""; }; - 188AD8DA1471FE3D0081C619 /* InfoPlist.strings */ = { + 4C198F1F0ACDB4BF00AAB142 /* OID.strings */ = { isa = PBXVariantGroup; children = ( - 188AD8DB1471FE3E0081C619 /* en */, + 4C198F200ACDB4BF00AAB142 /* English */, ); - name = InfoPlist.strings; + name = OID.strings; sourceTree = ""; }; - 18F2350D15C9FA3B00060520 /* InfoPlist.strings */ = { + 52D82BE316A621F70078DFE5 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( - 18F2350E15C9FA3B00060520 /* en */, + 52D82BE416A621F70078DFE5 /* en */, ); name = InfoPlist.strings; - path = en.lproj; sourceTree = ""; }; - 4C96F7C616D6DF8400D3B39D /* InfoPlist.strings */ = { + 5346480617331E1200FE9172 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( - 4C96F7C716D6DF8400D3B39D /* en */, + 5346480717331E1200FE9172 /* en */, ); name = InfoPlist.strings; sourceTree = ""; }; - 4C96F7CC16D6DF8400D3B39D /* Credits.rtf */ = { - isa = PBXVariantGroup; - children = ( - 4C96F7CD16D6DF8400D3B39D /* en */, - ); - name = Credits.rtf; - sourceTree = ""; - }; - 4C96F7D216D6DF8400D3B39D /* MainMenu.xib */ = { + 53C0E1F1177FAC2C00F8A018 /* CloudKeychain.strings */ = { isa = PBXVariantGroup; children = ( - 4C96F7D316D6DF8400D3B39D /* en */, + 53C0E1F2177FAC2C00F8A018 /* English */, ); - name = MainMenu.xib; + name = CloudKeychain.strings; sourceTree = ""; }; - 4CC7A7B816CC2A85003E10C1 /* InfoPlist.strings */ = { + BE197F2A19116FD100BA91D1 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( - 4CC7A7B916CC2A85003E10C1 /* en */, + BE197F2B19116FD100BA91D1 /* en */, ); name = InfoPlist.strings; sourceTree = ""; }; - 4CC7A7BE16CC2A85003E10C1 /* Credits.rtf */ = { + BE4AC9B818B8273600B84964 /* SharedWebCredentials.strings */ = { isa = PBXVariantGroup; children = ( - 4CC7A7BF16CC2A85003E10C1 /* en */, + BE4AC9B918B8273600B84964 /* English */, ); - name = Credits.rtf; + name = SharedWebCredentials.strings; sourceTree = ""; }; - 4CC7A7C416CC2A85003E10C1 /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 4CC7A7C516CC2A85003E10C1 /* en */, - ); - name = MainMenu.xib; - sourceTree = ""; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 05EF68B11949149C007958C3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; }; - 5214701016977CB800DF0DB3 /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 5214701116977CB800DF0DB3 /* en */, - ); - name = InfoPlist.strings; - sourceTree = ""; + 05EF68B21949149C007958C3 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; }; - 5328475117850741009118DC /* Localizable.strings */ = { - isa = PBXVariantGroup; - children = ( - 5328475217850741009118DC /* en */, - ); - name = Localizable.strings; - sourceTree = ""; + 05EF68B719491512007958C3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 0C6C631315D193C900BC68CD /* Debug */ = { + 05EF68B819491512007958C3 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 0C6C632F15D19DE600BC68CD /* test.xcconfig */; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CODE_SIGN_ENTITLEMENTS = "sectests/SecurityTests-Entitlements.plist"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - /usr/lib/system, - ); - OTHER_LDFLAGS = "-t"; - VALID_ARCHS = x86_64; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 05EF68BD194915A5007958C3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; - 0C6C631415D193C900BC68CD /* Release */ = { + 05EF68BE194915A5007958C3 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 0C6C632F15D19DE600BC68CD /* test.xcconfig */; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CODE_SIGN_ENTITLEMENTS = "sectests/SecurityTests-Entitlements.plist"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - /usr/lib/system, - ); - OTHER_LDFLAGS = "-t"; - VALID_ARCHS = x86_64; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; - 0C6C642B15D5ADB500BC68CD /* Debug */ = { + 05EF68C3194915FB007958C3 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; - 0C6C642C15D5ADB500BC68CD /* Release */ = { + 05EF68C4194915FB007958C3 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; - 0CC3352B16C1ED8000399E53 /* Debug */ = { + 0C0BDB35175685B000BC1A7E /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 0C6C632F15D19DE600BC68CD /* test.xcconfig */; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CODE_SIGN_ENTITLEMENTS = sec/securityd/entitlements.plist; - HEADER_SEARCH_PATHS = ( + CODE_SIGN_ENTITLEMENTS = "secdtests/secdtests-entitlements.plist"; + FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)/sec", - "$(PROJECT_DIR)/utilities", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", ); + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/bin"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - /usr/lib/system, + "$(SDKROOT)/usr/lib/system", + ); + OTHER_LDFLAGS = ""; + "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "-framework", + MobileKeyBag, + "-laks", + "-framework", + SharedWebCredentials, + "-lcoreauthd_client", + "-laks_acl", ); - OTHER_LDFLAGS = "-t"; - "OTHER_LDFLAGS[sdk=macosx*]" = ( - "-t", - "-F$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ( "-framework", - AppleSystemInfo, + SharedWebCredentials, + "-laks_acl", ); - PRODUCT_NAME = secdtests; - VALID_ARCHS = x86_64; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_STYLE = debugging; }; name = Debug; }; - 0CC3352C16C1ED8000399E53 /* Release */ = { + 0C0BDB36175685B000BC1A7E /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 0C6C632F15D19DE600BC68CD /* test.xcconfig */; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CODE_SIGN_ENTITLEMENTS = sec/securityd/entitlements.plist; - HEADER_SEARCH_PATHS = ( + CODE_SIGN_ENTITLEMENTS = "secdtests/secdtests-entitlements.plist"; + FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)/sec", - "$(PROJECT_DIR)/utilities", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", ); + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/bin"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - /usr/lib/system, + "$(SDKROOT)/usr/lib/system", + ); + OTHER_LDFLAGS = ""; + "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "-framework", + MobileKeyBag, + "-laks", + "-framework", + SharedWebCredentials, + "-lcoreauthd_client", + "-laks_acl", ); - OTHER_LDFLAGS = "-t"; - "OTHER_LDFLAGS[sdk=macosx*]" = ( - "-t", - "-F$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ( "-framework", - AppleSystemInfo, + SharedWebCredentials, + "-laks_acl", ); - PRODUCT_NAME = secdtests; - VALID_ARCHS = x86_64; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_STYLE = debugging; }; name = Release; }; - 18073873146D0D4E00F05C24 /* Debug */ = { + 0C6799FA12F7C37C00712919 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 181EA423146D4A2A00A6D320 /* debug.xcconfig */; buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + PRODUCT_NAME = dtlsTests; }; name = Debug; }; - 18073874146D0D4E00F05C24 /* Release */ = { + 0C6799FB12F7C37C00712919 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 181EA425146D4A2A00A6D320 /* release.xcconfig */; buildSettings = { + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + PRODUCT_NAME = dtlsTests; + ZERO_LINK = NO; }; name = Release; }; - 18073876146D0D4E00F05C24 /* Debug */ = { + 0C7CFA3014E1BA4800DF9D95 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; buildSettings = { - EXPORTED_SYMBOLS_FILE = "$(BUILT_PRODUCTS_DIR)/$(TARGETNAME).$(CURRENT_ARCH).exp"; - INFOPLIST_FILE = "lib/Info-Security.plist"; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - /usr/lib/system, - ); + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; - 18073877146D0D4E00F05C24 /* Release */ = { + 0C7CFA3114E1BA4800DF9D95 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; buildSettings = { - EXPORTED_SYMBOLS_FILE = "$(BUILT_PRODUCTS_DIR)/$(TARGETNAME).$(CURRENT_ARCH).exp"; - INFOPLIST_FILE = "lib/Info-Security.plist"; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - /usr/lib/system, - ); - ORDER_FILE = lib/Security.order; - SECTORDER_FLAGS = "-order_file_statistics"; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; - 18270EDE14CF282600B05E7F /* Debug */ = { + 4C52D0BE16EFC61E0079966E /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; buildSettings = { - CODE_SIGN_ENTITLEMENTS = sec/securityd/entitlements.plist; - GCC_PREPROCESSOR_DEFINITIONS = ( - "SECITEM_SHIM_OSX=1", + 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_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = CircleJoinRequested/entitlements.plist; + FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", ); - GCC_TREAT_WARNINGS_AS_ERRORS = YES; - HEADER_SEARCH_PATHS = ( - "$(PROJECT_DIR)/sec", - "$(PROJECT_DIR)/sec/securityd", - "$(PROJECT_DIR)/sec/ipc", - "$(PROJECT_DIR)/sec/SOSCircle", - "$(PROJECT_DIR)/utilities", - "$(PROJECT_DIR)", - "$(PROJECT_DIR)/../ios/asn1", - "$(PROJECT_DIR)/../libsecurity_keychain/libDER", - "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers", + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", "$(inherited)", ); - INSTALL_PATH = /usr/libexec; - "OTHER_LDFLAGS[sdk=macosx*]" = ( - "-F$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", - "-framework", - AppleSystemInfo, - ); - USE_HEADERMAP = NO; - VALID_ARCHS = x86_64; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INSTALL_PATH = /System/Library/Frameworks/Security.framework/CircleJoinRequested/; + "INSTALL_PATH[sdk=iphonesimulator*]" = "$(INDIGO_INSTALL_PATH_PREFIX)/System/Library/Frameworks/Security.framework/CircleJoinRequested/"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; - 18270EDF14CF282600B05E7F /* Release */ = { + 4C52D0BF16EFC61E0079966E /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; buildSettings = { - CODE_SIGN_ENTITLEMENTS = sec/securityd/entitlements.plist; - GCC_PREPROCESSOR_DEFINITIONS = ( - "SECITEM_SHIM_OSX=1", - "$(inherited)", - ); - GCC_TREAT_WARNINGS_AS_ERRORS = YES; - HEADER_SEARCH_PATHS = ( - "$(PROJECT_DIR)/sec", - "$(PROJECT_DIR)/sec/securityd", - "$(PROJECT_DIR)/sec/ipc", - "$(PROJECT_DIR)/sec/SOSCircle", - "$(PROJECT_DIR)/utilities", - "$(PROJECT_DIR)", - "$(PROJECT_DIR)/../ios/asn1", - "$(PROJECT_DIR)/../libsecurity_keychain/libDER", - "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers", + 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_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = CircleJoinRequested/entitlements.plist; + ENABLE_NS_ASSERTIONS = NO; + FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", ); - INSTALL_PATH = /usr/libexec; - "OTHER_LDFLAGS[sdk=macosx*]" = ( - "-F$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", - "-framework", - AppleSystemInfo, - ); - USE_HEADERMAP = NO; - VALID_ARCHS = x86_64; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_UNDECLARED_SELECTOR = YES; + INSTALL_PATH = /System/Library/Frameworks/Security.framework/CircleJoinRequested/; + "INSTALL_PATH[sdk=iphonesimulator*]" = "$(INDIGO_INSTALL_PATH_PREFIX)/System/Library/Frameworks/Security.framework/CircleJoinRequested/"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + PRODUCT_NAME = "$(TARGET_NAME)"; + VALIDATE_PRODUCT = YES; }; name = Release; }; - 182BB573146F4DCB000BF1F3 /* Debug */ = { + 4C541F870F250BF500E508AE /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; buildSettings = { - EXPORTED_SYMBOLS_FILE = lib/plugins/csparser.exp; - INFOPLIST_FILE = "lib/plugins/csparser-Info.plist"; - INSTALLHDRS_SCRIPT_PHASE = NO; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/PlugIns"; - WRAPPER_EXTENSION = bundle; + PRODUCT_NAME = phase2; }; name = Debug; }; - 182BB574146F4DCB000BF1F3 /* Release */ = { + 4C541F8A0F250BF500E508AE /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; buildSettings = { - EXPORTED_SYMBOLS_FILE = lib/plugins/csparser.exp; - INFOPLIST_FILE = "lib/plugins/csparser-Info.plist"; - INSTALLHDRS_SCRIPT_PHASE = NO; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/PlugIns"; - WRAPPER_EXTENSION = bundle; + PRODUCT_NAME = phase2; }; name = Release; }; - 182BB59A146FE295000BF1F3 /* Debug */ = { + 4C541F980F250C3000E508AE /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = phase1; }; name = Debug; }; - 182BB59B146FE295000BF1F3 /* Release */ = { + 4C541F9B0F250C3000E508AE /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = phase1; }; name = Release; }; - 186F778A14E59FB200434E1F /* Debug */ = { + 4C711D7413AFCD0900FE865D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; + CODE_SIGN_ENTITLEMENTS = "SecurityTests/SecurityTests-Entitlements.plist"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Security/regressions", + ); + INFOPLIST_FILE = "SecurityTests/SecurityDevTests-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)/usr/lib/system\"", + ); + OTHER_LDFLAGS = "$(inherited)"; + "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( + "$(inherited)", + "-framework", + MobileKeyBag, + "-laks", + "-framework", + SharedWebCredentials, + "-lcoreauthd_client", + "-laks_acl", + ); + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ( + "$(inherited)", + "-framework", + SharedWebCredentials, + "-laks_acl", + ); + PRODUCT_NAME = SecurityDevTests; + STRIP_STYLE = debugging; }; name = Debug; }; - 186F778B14E59FB200434E1F /* Release */ = { + 4C711D7513AFCD0900FE865D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; + CODE_SIGN_ENTITLEMENTS = "SecurityTests/SecurityTests-Entitlements.plist"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Security/regressions", + ); + INFOPLIST_FILE = "SecurityTests/SecurityDevTests-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)/usr/lib/system\"", + ); + OTHER_LDFLAGS = "$(inherited)"; + "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "$(inherited)", + "-framework", + MobileKeyBag, + "-laks", + "-framework", + SharedWebCredentials, + "-lcoreauthd_client", + "-laks_acl", + ); + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ( + "$(inherited)", + "-framework", + SharedWebCredentials, + "-laks_acl", + ); + PRODUCT_NAME = SecurityDevTests; + STRIP_STYLE = debugging; }; name = Release; }; - 186F778E14E59FDA00434E1F /* Debug */ = { + 4C9DE9D41181AC4900CF5C27 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/bin"; + OTHER_LDFLAGS = ( + "-lsecurityd", + "-lSecureObjectSync", + "-lsqlite3", + "-framework", + CFNetwork, + ); + "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( + "-lsecurityd", + "-lSecureObjectSync", + "-lsqlite3", + "-framework", + CFNetwork, + "-framework", + IOKit, + "-framework", + MobileKeyBag, + "-laks", + "-framework", + SharedWebCredentials, + "-lcoreauthd_client", + "-laks_acl", + ); + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ( + "-lsecurityd", + "-lSecureObjectSync", + "-lsqlite3", + "-framework", + CFNetwork, + "-framework", + IOKit, + "-framework", + SharedWebCredentials, + ); + PRODUCT_NAME = sslEcdsa; }; name = Debug; }; - 186F778F14E59FDA00434E1F /* Release */ = { + 4C9DE9D51181AC4900CF5C27 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/bin"; + "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "-lsecurityd", + "-lSecureObjectSync", + "-lsqlite3", + "-framework", + CFNetwork, + "-framework", + IOKit, + "-framework", + MobileKeyBag, + "-laks", + "-framework", + SharedWebCredentials, + "-lcoreauthd_client", + ); + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ( + "-lsecurityd", + "-lSecureObjectSync", + "-lsqlite3", + "-framework", + CFNetwork, + "-framework", + SharedWebCredentials, + ); + PRODUCT_NAME = sslEcdsa; }; name = Release; }; - 18F234F715C9F9A700060520 /* Debug */ = { + 52D82BE916A621F80078DFE5 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 18BFC44017C43393005DE6C3 /* executable.xcconfig */; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; - CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "authd/security.auth-Prefix.pch"; - GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; - GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; - GCC_WARN_SHADOW = YES; - GCC_WARN_SIGN_COMPARE = YES; + CODE_SIGN_ENTITLEMENTS = Security/sec/SOSCircle/CloudKeychainProxy/cloudkeychain.entitlements.plist; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNKNOWN_PRAGMAS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_LABEL = YES; - GCC_WARN_UNUSED_PARAMETER = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = authd/Info.plist; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; + INFOPLIST_FILE = "CloudKeychainProxy/CloudKeychainProxy-Info.plist"; + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; MACH_O_TYPE = mh_execute; + ONLY_ACTIVE_ARCH = YES; + "OTHER_LDFLAGS[sdk=iphoneos*]" = "-laks"; PRODUCT_NAME = "$(TARGET_NAME)"; - RUN_CLANG_STATIC_ANALYZER = YES; - SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; - WRAPPER_EXTENSION = xpc; + STRIP_INSTALLED_PRODUCT = NO; + STRIP_STYLE = all; + WRAPPER_EXTENSION = bundle; }; name = Debug; }; - 18F234F815C9F9A700060520 /* Release */ = { + 52D82BEA16A621F80078DFE5 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 18BFC44017C43393005DE6C3 /* executable.xcconfig */; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; - CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "authd/security.auth-Prefix.pch"; - GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; - GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; - GCC_WARN_SHADOW = YES; - GCC_WARN_SIGN_COMPARE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNKNOWN_PRAGMAS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_LABEL = YES; - GCC_WARN_UNUSED_PARAMETER = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = authd/Info.plist; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; + CODE_SIGN_ENTITLEMENTS = Security/sec/SOSCircle/CloudKeychainProxy/cloudkeychain.entitlements.plist; + GCC_C_LANGUAGE_STANDARD = gnu99; + INFOPLIST_FILE = "CloudKeychainProxy/CloudKeychainProxy-Info.plist"; + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; MACH_O_TYPE = mh_execute; + "OTHER_LDFLAGS[sdk=iphoneos*]" = "-laks"; PRODUCT_NAME = "$(TARGET_NAME)"; - SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; - WRAPPER_EXTENSION = xpc; - }; - name = Release; - }; - 18FE67FC1471A3AA00A2CBE3 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = ""; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; - PRODUCT_NAME = Security; - }; - name = Debug; - }; - 18FE67FD1471A3AA00A2CBE3 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = ""; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; - PRODUCT_NAME = Security; + STRIP_STYLE = all; + VALIDATE_PRODUCT = YES; + WRAPPER_EXTENSION = bundle; }; name = Release; }; - 37A7CEAF197DB8FA00926CE8 /* Debug */ = { + 52DE81951636347600F49F0C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + ALWAYS_SEARCH_USER_PATHS = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; + CODE_SIGN_ENTITLEMENTS = "Keychain/Keychain-Entitlements.plist"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = NO; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INSTALL_PATH = /AppleInternal/CoreOS/codesign_tests; - MACOSX_DEPLOYMENT_TARGET = 10.10; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx; - }; - name = Debug; - }; - 37A7CEB0197DB8FA00926CE8 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = YES; - 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; - INSTALL_PATH = /AppleInternal/CoreOS/codesign_tests; - MACOSX_DEPLOYMENT_TARGET = 10.10; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx; - }; - name = Release; - }; - 4C96F7D616D6DF8400D3B39D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_ENTITLEMENTS = "Keychain Circle Notification/entitlments.plist"; - CODE_SIGN_IDENTITY = "-"; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - FRAMEWORK_SEARCH_PATHS = ( + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Security/libsecurity_keychain/libDER", + "$(PROJECT_DIR)/Security/libsecurity_asn1", + "$(PROJECT_DIR)/libsecurity_smime", + "$(PROJECT_DIR)/Security/sec", + "$(PROJECT_DIR)/Security/utilities", + "$(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include", + "$(PROJECT_DIR)/Security/regressions", + "$(PROJECT_DIR)/Security/sec/SOSCircle", ); - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREFIX_HEADER = "Keychain Circle Notification/Keychain Circle Notification-Prefix.pch"; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", + "HEADER_SEARCH_PATHS[sdk=macosx*][arch=*]" = ( "$(inherited)", + "$(HEADER_SEARCH_PATHS)", + "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers", ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - /System/Library/Frameworks/Security.framework/PrivateHeaders, - /System/Library/Frameworks/CoreFoundation.framework/PrivateHeaders, - "$(PROJECT_DIR)/sec", + INFOPLIST_FILE = "Keychain/Keychain-Info.plist"; + INSTALL_PATH = "$(INSTALL_PATH_PREFIX)/AppleInternal/Applications"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)/usr/lib/system\"", ); - INFOPLIST_FILE = "Keychain Circle Notification/Keychain Circle Notification-Info.plist"; - INSTALL_PATH = /System/Library/CoreServices; - MACOSX_DEPLOYMENT_TARGET = 10.9; ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = "$(inherited)"; + "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( + "$(inherited)", + "-framework", + MobileKeyBag, + "-laks", + "-framework", + SharedWebCredentials, + "-lcoreauthd_client", + "-laks_acl", + ); + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ( + "$(inherited)", + "-framework", + SharedWebCredentials, + ); PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = ""; - VALID_ARCHS = x86_64; + SDKROOT = iphoneos.internal; + TARGETED_DEVICE_FAMILY = 1; WRAPPER_EXTENSION = app; }; name = Debug; }; - 4C96F7D716D6DF8400D3B39D /* Release */ = { + 52DE81961636347600F49F0C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; + ALWAYS_SEARCH_USER_PATHS = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_ENTITLEMENTS = "Keychain Circle Notification/entitlments.plist"; - CODE_SIGN_IDENTITY = "-"; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", - ); + CODE_SIGN_ENTITLEMENTS = "Keychain/Keychain-Entitlements.plist"; GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_PREFIX_HEADER = "Keychain Circle Notification/Keychain Circle Notification-Prefix.pch"; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; + GCC_PRECOMPILE_PREFIX_HEADER = NO; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; HEADER_SEARCH_PATHS = ( - /System/Library/Frameworks/Security.framework/PrivateHeaders, - /System/Library/Frameworks/CoreFoundation.framework/PrivateHeaders, - "$(PROJECT_DIR)/sec", + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Security/libsecurity_keychain/libDER", + "$(PROJECT_DIR)/Security/libsecurity_asn1", + "$(PROJECT_DIR)/Security/libsecurity_smime", + "$(PROJECT_DIR)/Security/sec", + "$(PROJECT_DIR)/Security/utilities", + "$(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include", + "$(PROJECT_DIR)/Security/regressions", + "$(PROJECT_DIR)/Security/sec/SOSCircle", + ); + "HEADER_SEARCH_PATHS[sdk=macosx*][arch=*]" = ( + "$(inherited)", + "$(HEADER_SEARCH_PATHS)", + "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers", + ); + INFOPLIST_FILE = "Keychain/Keychain-Info.plist"; + INSTALL_PATH = "$(INSTALL_PATH_PREFIX)/AppleInternal/Applications"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)/usr/lib/system\"", + ); + OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; + OTHER_LDFLAGS = "$(inherited)"; + "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "$(inherited)", + "-framework", + MobileKeyBag, + "-laks", + "-framework", + SharedWebCredentials, + "-lcoreauthd_client", + "-laks_acl", + ); + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ( + "$(inherited)", + "-framework", + SharedWebCredentials, ); - INFOPLIST_FILE = "Keychain Circle Notification/Keychain Circle Notification-Info.plist"; - INSTALL_PATH = /System/Library/CoreServices; - MACOSX_DEPLOYMENT_TARGET = 10.9; PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = ""; - VALID_ARCHS = x86_64; + SDKROOT = iphoneos.internal; + TARGETED_DEVICE_FAMILY = 1; + VALIDATE_PRODUCT = YES; WRAPPER_EXTENSION = app; }; name = Release; }; - 4CB23B4D169F5873003A0131 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 4CB23B91169F5CFF003A0131 /* command.xcconfig */; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CODE_SIGN_ENTITLEMENTS = sec/SecurityTool/entitlements.plist; - CODE_SIGN_IDENTITY = "-"; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_NAME = security2; - PROVISIONING_PROFILE = ""; - }; - name = Debug; - }; - 4CB23B4E169F5873003A0131 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 4CB23B91169F5CFF003A0131 /* command.xcconfig */; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CODE_SIGN_ENTITLEMENTS = sec/SecurityTool/entitlements.plist; - CODE_SIGN_IDENTITY = "-"; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - PRODUCT_NAME = security2; - PROVISIONING_PROFILE = ""; - }; - name = Release; - }; - 4CC7A7C716CC2A85003E10C1 /* Debug */ = { + 5346480B17331E1200FE9172 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_ENTITLEMENTS = sec/SecurityTool/entitlements.plist; - CODE_SIGN_IDENTITY = "-"; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREFIX_HEADER = "Keychain/Keychain-Prefix.pch"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "KeychainSyncAccountNotification/KeychainSyncAccountNotification-Prefix.pch"; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /System/Library/Frameworks/Security.framework/PrivateHeaders, - /System/Library/Frameworks/CoreFoundation.framework/PrivateHeaders, - ); - INFOPLIST_FILE = "Keychain/Keychain-Info.plist"; - INSTALL_PATH = /AppleInternal/Applications; - MACOSX_DEPLOYMENT_TARGET = 10.9; - ONLY_ACTIVE_ARCH = YES; + INFOPLIST_FILE = "KeychainSyncAccountNotification/KeychainSyncAccountNotification-Info.plist"; + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)$(SYSTEM_LIBRARY_DIR)/Accounts/Notification"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = ""; - VALID_ARCHS = x86_64; - WRAPPER_EXTENSION = app; + WRAPPER_EXTENSION = bundle; }; name = Debug; }; - 4CC7A7C816CC2A85003E10C1 /* Release */ = { + 5346480C17331E1200FE9172 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_ENTITLEMENTS = sec/SecurityTool/entitlements.plist; - CODE_SIGN_IDENTITY = "-"; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_PREFIX_HEADER = "Keychain/Keychain-Prefix.pch"; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /System/Library/Frameworks/Security.framework/PrivateHeaders, - /System/Library/Frameworks/CoreFoundation.framework/PrivateHeaders, - ); - INFOPLIST_FILE = "Keychain/Keychain-Info.plist"; - INSTALL_PATH = /AppleInternal/Applications; - MACOSX_DEPLOYMENT_TARGET = 10.9; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = ""; - VALID_ARCHS = x86_64; - WRAPPER_EXTENSION = app; - }; - name = Release; - }; - 4CE4729F16D833FE009070D1 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 4CE472A016D833FE009070D1 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "KeychainSyncAccountNotification/KeychainSyncAccountNotification-Prefix.pch"; + GCC_WARN_UNDECLARED_SELECTOR = YES; + INFOPLIST_FILE = "KeychainSyncAccountNotification/KeychainSyncAccountNotification-Info.plist"; + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)$(SYSTEM_LIBRARY_DIR)/Accounts/Notification"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; PRODUCT_NAME = "$(TARGET_NAME)"; + VALIDATE_PRODUCT = YES; + WRAPPER_EXTENSION = bundle; }; name = Release; }; - 5214701516977CB800DF0DB3 /* Debug */ = { + 728B56AC16D59979008FA3AB /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; @@ -6079,47 +8226,39 @@ CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_ENTITLEMENTS = CloudKeychainProxy/cloudkeychain.entitlements.plist; + CODE_SIGN_ENTITLEMENTS = "$(PROJECT_DIR)/OTAPKIAssetTool/OTAPKIAssetTool-entitlements.plist"; CODE_SIGN_IDENTITY = "-"; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "CloudKeychainProxy/CloudKeychainProxy-Info.plist"; - INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/A/Resources"; - MACH_O_TYPE = mh_execute; - MACOSX_DEPLOYMENT_TARGET = 10.9; + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/libexec"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = ""; "OTHER_LDFLAGS[sdk=iphoneos*]" = ( - "$(inherited)", "-framework", - MobileKeyBag, + BackgroundTaskAgent, ); PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - SDKROOT = ""; - VALID_ARCHS = "armv6 armv7 x86_64"; - WRAPPER_EXTENSION = bundle; }; name = Debug; }; - 5214701616977CB800DF0DB3 /* Release */ = { + 728B56AD16D59979008FA3AB /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; @@ -6127,36 +8266,30 @@ CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_ENTITLEMENTS = CloudKeychainProxy/cloudkeychain.entitlements.plist; + CODE_SIGN_ENTITLEMENTS = "$(PROJECT_DIR)/OTAPKIAssetTool/OTAPKIAssetTool-entitlements.plist"; CODE_SIGN_IDENTITY = "-"; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "CloudKeychainProxy/CloudKeychainProxy-Info.plist"; - INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/A/Resources"; - MACH_O_TYPE = mh_execute; - MACOSX_DEPLOYMENT_TARGET = 10.9; + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/libexec"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + OTHER_LDFLAGS = ""; "OTHER_LDFLAGS[sdk=iphoneos*]" = ( - "$(inherited)", "-framework", - MobileKeyBag, + BackgroundTaskAgent, ); PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - SDKROOT = ""; - VALID_ARCHS = "armv6 armv7 x86_64"; - WRAPPER_EXTENSION = bundle; + VALIDATE_PRODUCT = YES; }; name = Release; }; - 721680AD179B40F600406BB4 /* Debug */ = { + 72979BED175D095900BE8FD6 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -6172,36 +8305,29 @@ CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.Internal.sdk/System/Library/Frameworks", - ); GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = "$(PROJECT)/sec/SOSCircle"; - INSTALL_PATH = /usr/libexec; - MACOSX_DEPLOYMENT_TARGET = 10.9; + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/bin"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = ( + "-laks", + "-laks_acl", + ); + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ""; PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx; }; name = Debug; }; - 721680AE179B40F600406BB4 /* Release */ = { + 72979BEE175D095900BE8FD6 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -6217,86 +8343,636 @@ CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.Internal.sdk/System/Library/Frameworks", - ); GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = "$(PROJECT)/sec/SOSCircle"; - INSTALL_PATH = /usr/libexec; - MACOSX_DEPLOYMENT_TARGET = 10.9; + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/bin"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + OTHER_LDFLAGS = ( + "-laks", + "-laks_acl", + ); + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ""; PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx; + VALIDATE_PRODUCT = YES; }; name = Release; }; - 72756C07175D485D00F52070 /* Debug */ = { + 7913B20D0D172B3900601FE9 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = NO; + CODE_SIGN_ENTITLEMENTS = "sslViewer/sslServer-entitlements.plist"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/bin"; + OTHER_LDFLAGS = ( + "-lsecurityd", + "-lSecureObjectSync", + "-lsqlite3", + "-framework", + CFNetwork, + ); + "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( + "-lsecurityd", + "-lSecureObjectSync", + "-lsqlite3", + "-framework", + CFNetwork, + "-framework", + IOKit, + "-framework", + MobileKeyBag, + "-lcorecrypto$(Sim_Name)", + "-laks", + "-framework", + SharedWebCredentials, + "-lcoreauthd_client", + "-laks_acl", + ); + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ( + "-lsecurityd", + "-lSecureObjectSync", + "-lsqlite3", + "-framework", + CFNetwork, + "-framework", + SharedWebCredentials, + ); + PRODUCT_NAME = sslServer; + }; + name = Debug; + }; + 7913B2100D172B3900601FE9 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = "sslViewer/sslServer-entitlements.plist"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/bin"; + OTHER_LDFLAGS = ""; + "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "-lsecurityd", + "-lSecureObjectSync", + "-lsqlite3", + "-framework", + CFNetwork, + "-framework", + IOKit, + "-framework", + MobileKeyBag, + "-lcorecrypto$(Sim_Name)", + "-laks", + "-framework", + SharedWebCredentials, + "-lcoreauthd_client", + ); + "OTHER_LDFLAGS[sdk=iphonesimulator*][arch=*]" = ( + "-lsecurityd", + "-lSecureObjectSync", + "-lsqlite3", + "-framework", + CFNetwork, + "-framework", + SharedWebCredentials, + ); + PRODUCT_NAME = sslServer; + }; + name = Release; + }; + 792EFFDC0CBBF878007C00A0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEAD_CODE_STRIPPING = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = "$(CURRENT_PROJECT_VERSION)"; + EXPORTED_SYMBOLS_FILE = "$(BUILT_PRODUCTS_DIR)/$(TARGETNAME).$(CURRENT_ARCH).exp"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + FRAMEWORK_VERSION = B; + INFOPLIST_FILE = "Security-Info.plist"; + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)$(SYSTEM_LIBRARY_DIR)/Frameworks"; + INSTALL_PATH_ACTUAL = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; + OTHER_LDFLAGS = "-laks_acl"; + PRODUCT_NAME = Security; + STRIP_STYLE = debugging; + Sim_Name = ""; + "Sim_Name[sdk=iphonesimulator*][arch=*]" = _sim; + }; + name = Debug; + }; + 792EFFDD0CBBF878007C00A0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEAD_CODE_STRIPPING = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = "$(CURRENT_PROJECT_VERSION)"; + EXPORTED_SYMBOLS_FILE = "$(BUILT_PRODUCTS_DIR)/$(TARGETNAME).$(CURRENT_ARCH).exp"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + FRAMEWORK_VERSION = B; + INFOPLIST_FILE = "Security-Info.plist"; + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)$(SYSTEM_LIBRARY_DIR)/Frameworks"; + INSTALL_PATH_ACTUAL = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; + OTHER_LDFLAGS = "-laks_acl"; + PRODUCT_NAME = Security; + STRIP_STYLE = debugging; + Sim_Name = ""; + "Sim_Name[sdk=iphonesimulator*][arch=*]" = _sim; + }; + name = Release; + }; + 792EFFDE0CBBF878007C00A0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = SecurityTool/entitlements.plist; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/bin"; + "INSTALL_PATH[sdk=macosx*]" = /usr/bin; + OTHER_LDFLAGS = ( + "-lsecurityd", + "-lSecureObjectSync", + "-lsqlite3", + "-framework", + CFNetwork, + "-laks_acl", + ); + "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( + "-lsecurityd", + "-lSecureObjectSync", + "-lsqlite3", + "-framework", + CFNetwork, + "-framework", + IOKit, + "-framework", + MobileKeyBag, + "-laks", + "-framework", + SharedWebCredentials, + "-lcoreauthd_client", + "-laks_acl", + ); + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ( + "-lsecurityd", + "-lSecureObjectSync", + "-lsqlite3", + "-framework", + CFNetwork, + "-framework", + SharedWebCredentials, + "-laks_acl", + ); + PRODUCT_NAME = security; + STRIP_STYLE = debugging; + }; + name = Debug; + }; + 792EFFDF0CBBF878007C00A0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = SecurityTool/entitlements.plist; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/bin"; + "INSTALL_PATH[sdk=macosx*]" = /usr/bin; + OTHER_LDFLAGS = ""; + "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "-lsecurityd", + "-lSecureObjectSync", + "-lsqlite3", + "-framework", + CFNetwork, + "-framework", + IOKit, + "-framework", + MobileKeyBag, + "-laks", + "-framework", + SharedWebCredentials, + "-lcoreauthd_client", + "-laks_acl", + ); + "OTHER_LDFLAGS[sdk=iphonesimulator*][arch=*]" = ( + "-lsecurityd", + "-lSecureObjectSync", + "-lsqlite3", + "-framework", + CFNetwork, + "-framework", + SharedWebCredentials, + "-laks_acl", + ); + PRODUCT_NAME = security; + STRIP_STYLE = debugging; + }; + name = Release; + }; + 792EFFE00CBBF878007C00A0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = "sslViewer/sslViewer-entitlements.plist"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/bin"; + OTHER_LDFLAGS = ( + "-lsecurityd", + "-lSecureObjectSync", + "-lsqlite3", + "-framework", + CFNetwork, + ); + "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( + "-lsecurityd", + "-lSecureObjectSync", + "-lsqlite3", + "-framework", + CFNetwork, + "-framework", + IOKit, + "-framework", + MobileKeyBag, + "-laks", + "-framework", + SharedWebCredentials, + "-lcoreauthd_client", + "-laks_acl", + ); + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ( + "-lsecurityd", + "-lSecureObjectSync", + "-lsqlite3", + "-framework", + CFNetwork, + "-framework", + SharedWebCredentials, + ); + PRODUCT_NAME = sslViewer; + }; + name = Debug; + }; + 792EFFE10CBBF878007C00A0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = "sslViewer/sslViewer-entitlements.plist"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/bin"; + "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "-lsecurityd", + "-lSecureObjectSync", + "-lsqlite3", + "-framework", + CFNetwork, + "-framework", + IOKit, + "-framework", + MobileKeyBag, + "-laks", + "-framework", + SharedWebCredentials, + "-lcoreauthd_client", + ); + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ( + "-lsecurityd", + "-lSecureObjectSync", + "-lsqlite3", + "-framework", + CFNetwork, + "-framework", + SharedWebCredentials, + ); + PRODUCT_NAME = sslViewer; + }; + name = Release; + }; + 792EFFE20CBBF878007C00A0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = Security/sec/securityd/entitlements.plist; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/libexec"; + OTHER_LDFLAGS = ""; + "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( + "$(OTHER_LDFLAGS)", + "-framework", + SharedWebCredentials, + "-framework", + MobileKeyBag, + "-laks", + "-lcoreauthd_client", + "-laks_acl", + ); + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ( + "$(OTHER_LDFLAGS)", + "-framework", + SharedWebCredentials, + "-laks_acl", + ); + PRODUCT_NAME = securityd; + STRIP_STYLE = debugging; + }; + name = Debug; + }; + 792EFFE30CBBF878007C00A0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = Security/sec/securityd/entitlements.plist; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/libexec"; + OTHER_LDFLAGS = ""; + "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( + "$(OTHER_LDFLAGS)", + "-framework", + SharedWebCredentials, + "-framework", + MobileKeyBag, + "-laks", + "-lcoreauthd_client", + "-laks_acl", + ); + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ( + "$(OTHER_LDFLAGS)", + "-framework", + SharedWebCredentials, + "-laks_acl", + ); + PRODUCT_NAME = securityd; + STRIP_STYLE = debugging; + }; + name = Release; + }; + 792EFFE60CBBF878007C00A0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = world; + }; + name = Debug; + }; + 792EFFE70CBBF878007C00A0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = world; + }; + name = Release; + }; + 792EFFE80CBBF878007C00A0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4C86273C1137BEF8009EAB5A /* AspenFamily.xcconfig */; + buildSettings = { + APPLY_RULES_IN_COPY_FILES = YES; + CLANG_STATIC_ANALYZER_MODE = deep; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + "FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]" = ( + "$(SDKROOT)/System/Library/PrivateFrameworks/", + "$(SDKROOT)/usr/lib/system", + "$(inherited)", + ); + GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", + "NO_SERVER=1", + ); + "GCC_PREPROCESSOR_DEFINITIONS[sdk=iphonesimulator*]" = ( + "INDIGO=1", + "$(INDIGO_MISSING_FRAMEWORKS)", + "$(GCC_PREPROCESSOR_DEFINITIONS)", + ); + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = NO; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_VALUE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Security/libsecurity_keychain/libDER", + "$(PROJECT_DIR)/Security/libsecurity_asn1", + "$(PROJECT_DIR)/libsecurity_smime", + "$(PROJECT_DIR)/Security/sec", + "$(PROJECT_DIR)/Security/sec/SOSCircle", + "$(PROJECT_DIR)/Security/utilities", + "$(PROJECT_DIR)/Security/regressions", ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; + OTHER_CFLAGS = ( + "-fconstant-cfstrings", + "-fno-inline", + ); + RUN_CLANG_STATIC_ANALYZER = YES; + SDKROOT = iphoneos.internal; + STRIP_INSTALLED_PRODUCT = NO; + Sim_Name = ""; + "Sim_Name[sdk=iphonesimulator*][arch=*]" = _sim; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-unused-parameter", + "-Wno-missing-field-initializers", + ); + }; + name = Debug; + }; + 792EFFE90CBBF878007C00A0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4C86273C1137BEF8009EAB5A /* AspenFamily.xcconfig */; + buildSettings = { + APPLY_RULES_IN_COPY_FILES = YES; + CLANG_STATIC_ANALYZER_MODE = deep; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = YES; + "FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]" = ( + "$(SDKROOT)/System/Library/PrivateFrameworks/", + "$(SDKROOT)/usr/lib/system", + "$(inherited)", + ); + GCC_OPTIMIZATION_LEVEL = s; + GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1"; + "GCC_PREPROCESSOR_DEFINITIONS[sdk=iphonesimulator*]" = ( + "NO_SERVER=1", + "INDIGO=1", + "$(INDIGO_MISSING_FRAMEWORKS)", + "$(GCC_PREPROCESSOR_DEFINITIONS)", + ); + GCC_TREAT_WARNINGS_AS_ERRORS = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_VALUE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( - /usr/local/include, + "$(inherited)", "$(PROJECT_DIR)", - "$(PROJECT_DIR)/security2", - "$(PROJECT_DIR)/sec/SOSCircle", - "$(PROJECT_DIR)/utilities", - "$(PROJECT_DIR)/sec", + "$(PROJECT_DIR)/Security/libsecurity_keychain/libDER", + "$(PROJECT_DIR)/Security/libsecurity_asn1", + "$(PROJECT_DIR)/libsecurity_smime", + "$(PROJECT_DIR)/Security/sec", + "$(PROJECT_DIR)/Security/sec/SOSCircle", + "$(PROJECT_DIR)/Security/utilities", + "$(PROJECT_DIR)/Security/regressions", ); - MACOSX_DEPLOYMENT_TARGET = 10.9; + OTHER_CFLAGS = "-fconstant-cfstrings"; + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ""; + RUN_CLANG_STATIC_ANALYZER = YES; + SDKROOT = iphoneos.internal; + Sim_Name = ""; + "Sim_Name[sdk=iphonesimulator*][arch=*]" = _sim; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-unused-parameter", + "-Wno-missing-field-initializers", + ); + }; + name = Release; + }; + 79DCEA5C134A27D2007F57DC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_DYNAMIC_NO_PIC = NO; + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(SDKROOT)/usr/local/lib", + "$(inherited)", + ); + OTHER_LDFLAGS = ( + "-lASN1", + "-lCMS", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphonesimulator; + SUPPORTED_PLATFORMS = iphonesimulator; + }; + name = Debug; + }; + 79DCEA5D134A27D2007F57DC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(SDKROOT)/usr/local/lib", + "$(inherited)", + ); + OTHER_LDFLAGS = ( + "-lASN1", + "-lCMS", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphonesimulator; + SUPPORTED_PLATFORMS = iphonesimulator; + }; + name = Release; + }; + BE197F4619116FD100BA91D1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + AXLE_ENABLE_DEBUG_INFO = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_ASSIGN_ENUM = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "-"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(TARGET_NAME)/$(TARGET_NAME)-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_ABOUT_MISSING_NEWLINE = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INFOPLIST_FILE = "$(TARGET_NAME)/$(TARGET_NAME)-Info.plist"; + "INSTALL_PATH[sdk=iphoneos*]" = "$(LOCAL_APPS_DIR)"; + "INSTALL_PATH[sdk=iphonesimulator*]" = "$(INSTALL_PATH_PREFIX)$(INSTALL_PATH_ACTUAL)$(LOCAL_APPS_DIR)"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; ONLY_ACTIVE_ARCH = YES; - OTHER_LDFLAGS = "-laks"; PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx.internal; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = NO; }; name = Debug; }; - 72756C08175D485D00F52070 /* Release */ = { + BE197F4719116FD100BA91D1 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + AXLE_ENABLE_DEBUG_INFO = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_ASSIGN_ENUM = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -6305,217 +8981,564 @@ CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "-"; ENABLE_NS_ASSERTIONS = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_PRECOMPILE_PREFIX_HEADER = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(TARGET_NAME)/$(TARGET_NAME)-Prefix.pch"; + GCC_WARN_ABOUT_MISSING_NEWLINE = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INFOPLIST_FILE = "$(TARGET_NAME)/$(TARGET_NAME)-Info.plist"; + "INSTALL_PATH[sdk=iphoneos*]" = "$(LOCAL_APPS_DIR)"; + "INSTALL_PATH[sdk=iphonesimulator*]" = "$(INSTALL_PATH_PREFIX)$(INSTALL_PATH_ACTUAL)$(LOCAL_APPS_DIR)"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = NO; + }; + name = Release; + }; + BE442BBF18B7FDB800F24DAE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = Security/sec/securityd/entitlements.plist; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/"; + OTHER_LDFLAGS = ""; + "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( + "$(OTHER_LDFLAGS)", + "-framework", + SpringBoardServices, + "-framework", + WebUI, + ); + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ( + "$(OTHER_LDFLAGS)", + "-framework", + SpringBoardServices, + "-framework", + WebUI, + ); + PRODUCT_NAME = swcagent; + }; + name = Debug; + }; + BE442BC018B7FDB800F24DAE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = Security/sec/securityd/entitlements.plist; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/"; + OTHER_LDFLAGS = ""; + "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( + "$(OTHER_LDFLAGS)", + "-framework", + SpringBoardServices, + "-framework", + WebUI, + ); + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ( + "$(OTHER_LDFLAGS)", + "-framework", + SpringBoardServices, + "-framework", + WebUI, + ); + PRODUCT_NAME = swcagent; + }; + name = Release; + }; + E710C75D1331946500F85568 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = "SecurityTests/SecurityTests-Entitlements.plist"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Security/regressions", + ); + INFOPLIST_FILE = "SecurityTests/SecurityTests-Info.plist"; + INSTALL_PATH = "$(INSTALL_PATH_PREFIX)/AppleInternal/Applications"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)/usr/lib/system\"", + ); + OTHER_LDFLAGS = ""; + "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "$(inherited)", + "-framework", + MobileKeyBag, + "-laks", + "-framework", + SharedWebCredentials, + "-lcoreauthd_client", + "-laks_acl", + ); + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ( + "$(inherited)", + "-framework", + SharedWebCredentials, + "-laks_acl", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_STYLE = debugging; + }; + name = Debug; + }; + E710C75E1331946500F85568 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = "SecurityTests/SecurityTests-Entitlements.plist"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Security/regressions", + ); + INFOPLIST_FILE = "SecurityTests/SecurityTests-Info.plist"; + INSTALL_PATH = "$(INSTALL_PATH_PREFIX)/AppleInternal/Applications"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)/usr/lib/system\"", + ); + OTHER_LDFLAGS = ""; + "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "$(inherited)", + "-framework", + MobileKeyBag, + "-laks", + "-framework", + SharedWebCredentials, + "-lcoreauthd_client", + "-laks_acl", + ); + "OTHER_LDFLAGS[sdk=iphonesimulator*]" = ( + "$(inherited)", + "-framework", + SharedWebCredentials, + "-laks_acl", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_STYLE = debugging; + }; + name = Release; + }; + E75533F61651D8A900D2B847 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "phase2 copy"; + }; + name = Debug; + }; + E75533F71651D8A900D2B847 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "phase2 copy"; + }; + name = Release; + }; + E7B01BF0166594AB000485F1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = "Keychain/Keychain-Entitlements.plist"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_PRECOMPILE_PREFIX_HEADER = NO; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( - /usr/local/include, + "$(inherited)", "$(PROJECT_DIR)", - "$(PROJECT_DIR)/security2", - "$(PROJECT_DIR)/sec/SOSCircle", - "$(PROJECT_DIR)/utilities", - "$(PROJECT_DIR)/sec", + "$(PROJECT_DIR)/Security/libsecurity_keychain/libDER", + "$(PROJECT_DIR)/Security/libsecurity_asn1", + "$(PROJECT_DIR)/libsecurity_smime", + "$(PROJECT_DIR)/Security/sec", + "$(PROJECT_DIR)/Security/utilities", + "$(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include", + "$(PROJECT_DIR)/Security/regressions", + "$(PROJECT_DIR)/Security/sec/SOSCircle", ); - MACOSX_DEPLOYMENT_TARGET = 10.9; - OTHER_LDFLAGS = "-laks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx.internal; + "HEADER_SEARCH_PATHS[sdk=macosx*][arch=*]" = ( + "$(inherited)", + "$(HEADER_SEARCH_PATHS)", + "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers", + ); + INFOPLIST_FILE = "Keychain/Keychain-Info.plist"; + INSTALL_PATH = "$(INSTALL_PATH_PREFIX)/AppleInternal/Applications"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)/usr/lib/system\"", + ); + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = "$(inherited)"; + "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( + "$(inherited)", + "-framework", + MobileKeyBag, + ); + PRODUCT_NAME = SyncDevTest2; + SDKROOT = iphoneos.internal; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + E7B01BF1166594AB000485F1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = "Keychain/Keychain-Entitlements.plist"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_PRECOMPILE_PREFIX_HEADER = NO; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Security/libsecurity_keychain/libDER", + "$(PROJECT_DIR)/Security/libsecurity_asn1", + "$(PROJECT_DIR)/libsecurity_smime", + "$(PROJECT_DIR)/Security/sec", + "$(PROJECT_DIR)/Security/utilities", + "$(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include", + "$(PROJECT_DIR)/Security/regressions", + "$(PROJECT_DIR)/Security/sec/SOSCircle", + ); + "HEADER_SEARCH_PATHS[sdk=macosx*][arch=*]" = ( + "$(inherited)", + "$(HEADER_SEARCH_PATHS)", + "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers", + ); + INFOPLIST_FILE = "Keychain/Keychain-Info.plist"; + INSTALL_PATH = "$(INSTALL_PATH_PREFIX)/AppleInternal/Applications"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SDKROOT)/usr/lib/system\"", + ); + OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; + OTHER_LDFLAGS = "$(inherited)"; + "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "$(inherited)", + "-framework", + MobileKeyBag, + ); + PRODUCT_NAME = SyncDevTest2; + SDKROOT = iphoneos.internal; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + WRAPPER_EXTENSION = app; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 0C6C631215D193C900BC68CD /* Build configuration list for PBXNativeTarget "sectests" */ = { + 05EF68B01949149C007958C3 /* Build configuration list for PBXAggregateTarget "Security_temporary_UI" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 05EF68B11949149C007958C3 /* Debug */, + 05EF68B21949149C007958C3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 05EF68B619491512007958C3 /* Build configuration list for PBXAggregateTarget "Security_frameworks" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 05EF68B719491512007958C3 /* Debug */, + 05EF68B819491512007958C3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 05EF68BC194915A5007958C3 /* Build configuration list for PBXAggregateTarget "Security_executables" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 05EF68BD194915A5007958C3 /* Debug */, + 05EF68BE194915A5007958C3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 05EF68C2194915FB007958C3 /* Build configuration list for PBXAggregateTarget "Security_kexts" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 05EF68C3194915FB007958C3 /* Debug */, + 05EF68C4194915FB007958C3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0C0BDB43175685B000BC1A7E /* Build configuration list for PBXNativeTarget "secdtests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0C0BDB35175685B000BC1A7E /* Debug */, + 0C0BDB36175685B000BC1A7E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0C679A0412F7C3AE00712919 /* Build configuration list for PBXAggregateTarget "dtlsTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0C6799FA12F7C37C00712919 /* Debug */, + 0C6799FB12F7C37C00712919 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0C7CFA2F14E1BA4800DF9D95 /* Build configuration list for PBXAggregateTarget "phase1_ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0C7CFA3014E1BA4800DF9D95 /* Debug */, + 0C7CFA3114E1BA4800DF9D95 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4C32C0B10A4975F7002891BD /* Build configuration list for PBXNativeTarget "Security" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 792EFFDC0CBBF878007C00A0 /* Debug */, + 792EFFDD0CBBF878007C00A0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4C35DB6A094F906D002917C4 /* Build configuration list for PBXProject "Security" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 792EFFE80CBBF878007C00A0 /* Debug */, + 792EFFE90CBBF878007C00A0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4C52D0CC16EFC61E0079966E /* Build configuration list for PBXNativeTarget "CircleJoinRequested" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4C52D0BE16EFC61E0079966E /* Debug */, + 4C52D0BF16EFC61E0079966E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4C541FA20F250C8C00E508AE /* Build configuration list for PBXAggregateTarget "phase1" */ = { isa = XCConfigurationList; buildConfigurations = ( - 0C6C631315D193C900BC68CD /* Debug */, - 0C6C631415D193C900BC68CD /* Release */, + 4C541F980F250C3000E508AE /* Debug */, + 4C541F9B0F250C3000E508AE /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 0C6C642A15D5ADB500BC68CD /* Build configuration list for PBXAggregateTarget "Security_kexts" */ = { + 4C541FA30F250C8C00E508AE /* Build configuration list for PBXAggregateTarget "phase2" */ = { isa = XCConfigurationList; buildConfigurations = ( - 0C6C642B15D5ADB500BC68CD /* Debug */, - 0C6C642C15D5ADB500BC68CD /* Release */, + 4C541F870F250BF500E508AE /* Debug */, + 4C541F8A0F250BF500E508AE /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 0CC3352A16C1ED8000399E53 /* Build configuration list for PBXNativeTarget "secdtests" */ = { + 4C711D7313AFCD0900FE865D /* Build configuration list for PBXNativeTarget "SecurityDevTests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 0CC3352B16C1ED8000399E53 /* Debug */, - 0CC3352C16C1ED8000399E53 /* Release */, + 4C711D7413AFCD0900FE865D /* Debug */, + 4C711D7513AFCD0900FE865D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 18073844146D0D4E00F05C24 /* Build configuration list for PBXProject "Security" */ = { + 4C91274A0ADBF4A100AF202E /* Build configuration list for PBXAggregateTarget "world" */ = { isa = XCConfigurationList; buildConfigurations = ( - 18073873146D0D4E00F05C24 /* Debug */, - 18073874146D0D4E00F05C24 /* Release */, + 792EFFE60CBBF878007C00A0 /* Debug */, + 792EFFE70CBBF878007C00A0 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 18073875146D0D4E00F05C24 /* Build configuration list for PBXNativeTarget "Security" */ = { + 4C9DE9E11181AC4900CF5C27 /* Build configuration list for PBXNativeTarget "sslEcdsa" */ = { isa = XCConfigurationList; buildConfigurations = ( - 18073876146D0D4E00F05C24 /* Debug */, - 18073877146D0D4E00F05C24 /* Release */, + 4C9DE9D41181AC4900CF5C27 /* Debug */, + 4C9DE9D51181AC4900CF5C27 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 18270EDD14CF282600B05E7F /* Build configuration list for PBXNativeTarget "secd" */ = { + 4CB740A90A4756B300D641BB /* Build configuration list for PBXNativeTarget "securitytool" */ = { isa = XCConfigurationList; buildConfigurations = ( - 18270EDE14CF282600B05E7F /* Debug */, - 18270EDF14CF282600B05E7F /* Release */, + 792EFFDE0CBBF878007C00A0 /* Debug */, + 792EFFDF0CBBF878007C00A0 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 182BB572146F4DCB000BF1F3 /* Build configuration list for PBXNativeTarget "csparser" */ = { + 4CE5A55C09C7970A00D27A3F /* Build configuration list for PBXNativeTarget "sslViewer" */ = { isa = XCConfigurationList; buildConfigurations = ( - 182BB573146F4DCB000BF1F3 /* Debug */, - 182BB574146F4DCB000BF1F3 /* Release */, + 792EFFE00CBBF878007C00A0 /* Debug */, + 792EFFE10CBBF878007C00A0 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 182BB599146FE295000BF1F3 /* Build configuration list for PBXAggregateTarget "World" */ = { + 52D82BE816A621F80078DFE5 /* Build configuration list for PBXNativeTarget "CloudKeychainProxy" */ = { isa = XCConfigurationList; buildConfigurations = ( - 182BB59A146FE295000BF1F3 /* Debug */, - 182BB59B146FE295000BF1F3 /* Release */, + 52D82BE916A621F80078DFE5 /* Debug */, + 52D82BEA16A621F80078DFE5 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 186F778914E59FB200434E1F /* Build configuration list for PBXAggregateTarget "Security_frameworks" */ = { + 52DE81941636347600F49F0C /* Build configuration list for PBXNativeTarget "Keychain" */ = { isa = XCConfigurationList; buildConfigurations = ( - 186F778A14E59FB200434E1F /* Debug */, - 186F778B14E59FB200434E1F /* Release */, + 52DE81951636347600F49F0C /* Debug */, + 52DE81961636347600F49F0C /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 186F778D14E59FDA00434E1F /* Build configuration list for PBXAggregateTarget "Security_executables" */ = { + 5346481917331E1200FE9172 /* Build configuration list for PBXNativeTarget "KeychainSyncAccountNotification" */ = { isa = XCConfigurationList; buildConfigurations = ( - 186F778E14E59FDA00434E1F /* Debug */, - 186F778F14E59FDA00434E1F /* Release */, + 5346480B17331E1200FE9172 /* Debug */, + 5346480C17331E1200FE9172 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 18F234F615C9F9A700060520 /* Build configuration list for PBXNativeTarget "authd" */ = { + 728B56AB16D59979008FA3AB /* Build configuration list for PBXNativeTarget "OTAPKIAssetTool" */ = { isa = XCConfigurationList; buildConfigurations = ( - 18F234F715C9F9A700060520 /* Debug */, - 18F234F815C9F9A700060520 /* Release */, + 728B56AC16D59979008FA3AB /* Debug */, + 728B56AD16D59979008FA3AB /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 18FE67FB1471A3AA00A2CBE3 /* Build configuration list for PBXNativeTarget "copyHeaders" */ = { + 72979BEC175D095900BE8FD6 /* Build configuration list for PBXNativeTarget "cloud_keychain_diagnose" */ = { isa = XCConfigurationList; buildConfigurations = ( - 18FE67FC1471A3AA00A2CBE3 /* Debug */, - 18FE67FD1471A3AA00A2CBE3 /* Release */, + 72979BED175D095900BE8FD6 /* Debug */, + 72979BEE175D095900BE8FD6 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 37A7CED8197DB8FA00926CE8 /* Build configuration list for PBXNativeTarget "codesign_tests" */ = { + 790851C90CA985C10083CC4D /* Build configuration list for PBXNativeTarget "securityd" */ = { isa = XCConfigurationList; buildConfigurations = ( - 37A7CEAF197DB8FA00926CE8 /* Debug */, - 37A7CEB0197DB8FA00926CE8 /* Release */, + 792EFFE20CBBF878007C00A0 /* Debug */, + 792EFFE30CBBF878007C00A0 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 4C96F7D516D6DF8400D3B39D /* Build configuration list for PBXNativeTarget "Keychain Circle Notification" */ = { + 7913B20A0D172B3900601FE9 /* Build configuration list for PBXNativeTarget "sslServer" */ = { isa = XCConfigurationList; buildConfigurations = ( - 4C96F7D616D6DF8400D3B39D /* Debug */, - 4C96F7D716D6DF8400D3B39D /* Release */, + 7913B20D0D172B3900601FE9 /* Debug */, + 7913B2100D172B3900601FE9 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 4CB23B7F169F5873003A0131 /* Build configuration list for PBXNativeTarget "security2" */ = { + 79DCEA5B134A27D2007F57DC /* Build configuration list for PBXNativeTarget "codesign_wrapper" */ = { isa = XCConfigurationList; buildConfigurations = ( - 4CB23B4D169F5873003A0131 /* Debug */, - 4CB23B4E169F5873003A0131 /* Release */, + 79DCEA5C134A27D2007F57DC /* Debug */, + 79DCEA5D134A27D2007F57DC /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 4CC7A7EF16CC2A85003E10C1 /* Build configuration list for PBXNativeTarget "Cloud Keychain Utility" */ = { + BE197F5819116FD100BA91D1 /* Build configuration list for PBXNativeTarget "SharedWebCredentialViewService" */ = { isa = XCConfigurationList; buildConfigurations = ( - 4CC7A7C716CC2A85003E10C1 /* Debug */, - 4CC7A7C816CC2A85003E10C1 /* Release */, + BE197F4619116FD100BA91D1 /* Debug */, + BE197F4719116FD100BA91D1 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 4CE472C716D833FE009070D1 /* Build configuration list for PBXAggregateTarget "Security_temporary_UI" */ = { + BE442BBE18B7FDB800F24DAE /* Build configuration list for PBXNativeTarget "swcagent" */ = { isa = XCConfigurationList; buildConfigurations = ( - 4CE4729F16D833FE009070D1 /* Debug */, - 4CE472A016D833FE009070D1 /* Release */, + BE442BBF18B7FDB800F24DAE /* Debug */, + BE442BC018B7FDB800F24DAE /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 5214701416977CB800DF0DB3 /* Build configuration list for PBXNativeTarget "CloudKeychainProxy" */ = { + E710C75C1331946500F85568 /* Build configuration list for PBXNativeTarget "SecurityTests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 5214701516977CB800DF0DB3 /* Debug */, - 5214701616977CB800DF0DB3 /* Release */, + E710C75D1331946500F85568 /* Debug */, + E710C75E1331946500F85568 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 721680AC179B40F600406BB4 /* Build configuration list for PBXNativeTarget "iCloudStats" */ = { + E75533F51651D8A900D2B847 /* Build configuration list for PBXAggregateTarget "CKd-only" */ = { isa = XCConfigurationList; buildConfigurations = ( - 721680AD179B40F600406BB4 /* Debug */, - 721680AE179B40F600406BB4 /* Release */, + E75533F61651D8A900D2B847 /* Debug */, + E75533F71651D8A900D2B847 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 72756C2F175D485D00F52070 /* Build configuration list for PBXNativeTarget "cloud_keychain_diagnose" */ = { + E7B01BEF166594AB000485F1 /* Build configuration list for PBXNativeTarget "SyncDevTest2" */ = { isa = XCConfigurationList; buildConfigurations = ( - 72756C07175D485D00F52070 /* Debug */, - 72756C08175D485D00F52070 /* Release */, + E7B01BF0166594AB000485F1 /* Debug */, + E7B01BF1166594AB000485F1 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; - rootObject = 18073841146D0D4E00F05C24 /* Project object */; + rootObject = 4C35DB69094F906D002917C4 /* Project object */; } diff --git a/Security.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Security.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..8efcdaeb --- /dev/null +++ b/Security.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Security.xcodeproj/project.xcworkspace/xcuserdata/jkauth.xcuserdatad/UserInterfaceState.xcuserstate b/Security.xcodeproj/project.xcworkspace/xcuserdata/jkauth.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index a5e3d8807838a72705c55280b70469ecc9ca64b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 140968 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

K&vG%? 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 reBuQzaRq%YFOU6L-ikK(|N8vzKPjI2zkj~)!T + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/ProtectedCloudStorage.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/ProtectedCloudStorage.xcscheme new file mode 100644 index 00000000..223d7309 --- /dev/null +++ b/Security.xcodeproj/xcshareddata/xcschemes/ProtectedCloudStorage.xcscheme @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/Release.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/Release.xcscheme new file mode 100644 index 00000000..1d521a91 --- /dev/null +++ b/Security.xcodeproj/xcshareddata/xcschemes/Release.xcscheme @@ -0,0 +1,504 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/SyncTest.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/SyncTest.xcscheme new file mode 100644 index 00000000..e4363a3c --- /dev/null +++ b/Security.xcodeproj/xcshareddata/xcschemes/SyncTest.xcscheme @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/SyncTest2.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/SyncTest2.xcscheme new file mode 100644 index 00000000..2288cd40 --- /dev/null +++ b/Security.xcodeproj/xcshareddata/xcschemes/SyncTest2.xcscheme @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/codesigntester.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/codesigntester.xcscheme new file mode 100644 index 00000000..e7f3c6c6 --- /dev/null +++ b/Security.xcodeproj/xcshareddata/xcschemes/codesigntester.xcscheme @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/libsecurityd.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/libsecurityd.xcscheme new file mode 100644 index 00000000..d631fa39 --- /dev/null +++ b/Security.xcodeproj/xcshareddata/xcschemes/libsecurityd.xcscheme @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme index 06e4bd66..47e39f7a 100644 --- a/Security.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme +++ b/Security.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme @@ -1,7 +1,7 @@ + LastUpgradeVersion = "0600" + version = "2.0"> @@ -14,7 +14,7 @@ buildForAnalyzing = "YES"> @@ -32,7 +32,7 @@ @@ -47,11 +47,12 @@ buildConfiguration = "Debug" ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" + debugXPCServices = "NO" allowLocationSimulation = "YES"> @@ -59,7 +60,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -91,7 +152,7 @@ diff --git a/Security.xcodeproj/xcshareddata/xcschemes/security.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/security.xcscheme new file mode 100644 index 00000000..5a1426fc --- /dev/null +++ b/Security.xcodeproj/xcshareddata/xcschemes/security.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/securityd.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/securityd.xcscheme new file mode 100644 index 00000000..5f76c7d8 --- /dev/null +++ b/Security.xcodeproj/xcshareddata/xcschemes/securityd.xcscheme @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/sslEcdsa.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/sslEcdsa.xcscheme new file mode 100644 index 00000000..d91f5579 --- /dev/null +++ b/Security.xcodeproj/xcshareddata/xcschemes/sslEcdsa.xcscheme @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/sslServer.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/sslServer.xcscheme new file mode 100644 index 00000000..9c25cbae --- /dev/null +++ b/Security.xcodeproj/xcshareddata/xcschemes/sslServer.xcscheme @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/sslViewer.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/sslViewer.xcscheme new file mode 100644 index 00000000..a5630980 --- /dev/null +++ b/Security.xcodeproj/xcshareddata/xcschemes/sslViewer.xcscheme @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/Security.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index fc11631f..00000000 --- a/Security.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,104 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 0C6C630A15D193C800BC68CD - - primary - - - 0C6C642915D5ADB500BC68CD - - primary - - - 0CC3350716C1ED8000399E53 - - primary - - - 1807384A146D0D4E00F05C24 - - primary - - - 18270ED514CF282600B05E7F - - primary - - - 182BB567146F4DCA000BF1F3 - - primary - - - 182BB598146FE295000BF1F3 - - primary - - - 186F778814E59FB200434E1F - - primary - - - 186F778C14E59FDA00434E1F - - primary - - - 18F234EA15C9F9A600060520 - - primary - - - 18FE67E91471A3AA00A2CBE3 - - primary - - - 37A7CEAA197DB8FA00926CE8 - - primary - - - 4C96F7C016D6DF8300D3B39D - - primary - - - 4CB23B45169F5873003A0131 - - primary - - - 4CC7A7B216CC2A84003E10C1 - - primary - - - 4CE4729E16D833FD009070D1 - - primary - - - 5214700516977CB800DF0DB3 - - primary - - - 721680A4179B40F600406BB4 - - primary - - - 72756BFD175D485D00F52070 - - primary - - - - - diff --git a/APPLE_LICENSE b/Security/APPLE_LICENSE similarity index 100% rename from APPLE_LICENSE rename to Security/APPLE_LICENSE diff --git a/Security/Breadcrumb/README b/Security/Breadcrumb/README new file mode 100644 index 00000000..894c607d --- /dev/null +++ b/Security/Breadcrumb/README @@ -0,0 +1,99 @@ +Breadcrumbs +=========== + +simple defintions: + + old password + new password + K = random 16 byte key + EK = Encrypted K + EKold = ECB(PBKDF2(password_old), K) + EKnew = ECB(PBKDF2(password_new), K) + Breadcrumb = AES-GCM(K, old password) + + +Breadcrumbs are to make life easier when using AppleID password as +local password by allowing upgrade of keychains from old password to new +password. + +When changing the password on one machine, the keychains for the user are +still encrypted (AES-GCM, key derived using PBKDF2) with the old password on +all machines. + +This happens for one machine when changing password on the AppleID.apple.com webpage. + +An EK is stored on the apple server. Each machine have its own EK stored on the web server. + +When user change the password on the AppleID.apple.com website, the +web server will unwrap the key K with the old password and then rewrap +it with the new password. + + unwrap(EKold, old password) -> K + wrap(K, new password) -> EKnew + +This means that if the user changes password more then ones, the computer can still upgrade the keychain to the current password since K will be the same until a new EK is uploaded the the computer. + +PKDF2 is used to avoid prebuilt lists of string2key tables attacks on +the breadcrumb + encryptedKey if the attacker possesses both. + +Breadcrumb contain current password that encrypts the keychain. The breadcrumb itself is encrypted with a machine-specific key K. + +The breadcrumb is stored on the local machine and never leaves the +local machine. + +When the computer have upgrade keychain to the current password and new K, EK, and breadcrumb is generated. + +Format +====== + +K = Random 16 byte +EK = ECB(PBKDF2(pw), key K) (16byte) | pbkdf-salt (20byte) | 4byte int network order of pbdf-iter +Breadcrumb = version (1) 1byte | AES-GCM-ENC(key K, password length (4byte, network order) | password | pad ) | tag + +The encrypted key (EK) is a PKDF2 salt + iteration count + random AES-128 key (K) +encrypted with ECB of the PKDF2(salt, iteration, password). + +There is no integrity on this encryption on purpose since that would make the +EK an verifier. + +The format of the EncryptedKey is + + ECB(PBKDF2(pw), key K) (16byte) | pbkdf-salt (20byte) | 4byte int network order of pbdf-iter + +The random key (K) is used to encrypt a breadcrumb that is stored +locally on the machine. The breadcrumb allows you to recover the old +password if you know the new password and have the encrypted key. + +The client machine encrypts the password with AES-GCM using key K. The data +is padded to 256 bytes to no tell password length. + +The format of the breadcrumb + + version (1) 1byte | AES-GCM-ENC(key K, password length (4byte, network order) | password | pad ) | tag + +tag is the 16 byte GCM tag +key is the key (K) from the EncryptedKey (EK) +assoc data i AES-GCM covers version byte + +Password length including up to pad is encrypted with AES-GCM + +Password is padded to paddingSize (256) to avoid exposing length of password. + +The PBKDF2 function is PBKDF2-HMAC-SHA256. + + +Updating the Encrypted Key (EK) on server +========================================= + +When a user update the password on the apple id server the server +updates the breadcrumb for each machine that the user have associsated +with the account. + +1. The server takes the old password generates a the key using PBKDF2 + using the salt and interation count. + +2. The server takes the new password generates a the key using PBKDF2 + using the same salt and interation count. + +3. Decrypts the first block with the key of old password and + re-encrypt with the key of new password. diff --git a/Security/Breadcrumb/SecBreadcrumb.c b/Security/Breadcrumb/SecBreadcrumb.c new file mode 100644 index 00000000..e434f542 --- /dev/null +++ b/Security/Breadcrumb/SecBreadcrumb.c @@ -0,0 +1,335 @@ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#define CFReleaseNull(CF) ({ __typeof__(CF) *const _pcf = &(CF), _cf = *_pcf; (_cf ? (*_pcf) = ((__typeof__(CF))0), (CFRelease(_cf), ((__typeof__(CF))0)) : _cf); }) + +static const int kKeySize = CCAES_KEY_SIZE_128; +static const int kSaltSize = 20; +static const int kIterations = 5000; +static const CFIndex tagLen = 16; +static const uint8_t BCversion = 1; +static const size_t paddingSize = 256; +static const size_t maxSize = 1024; + +Boolean +SecBreadcrumbCreateFromPassword(CFStringRef inPassword, + CFDataRef *outBreadcrumb, + CFDataRef *outEncryptedKey, + CFErrorRef *outError) +{ + const struct ccmode_ecb *ecb = ccaes_ecb_encrypt_mode(); + const struct ccmode_gcm gcm = CCMODE_FACTORY_GCM_ENCRYPT(ecb); + const struct ccdigest_info *di = ccsha256_di(); + CFMutableDataRef key, npw; + CFDataRef pw; + + *outBreadcrumb = NULL; + *outEncryptedKey = NULL; + if (outError) + *outError = NULL; + + key = CFDataCreateMutable(NULL, 0); + if (key == NULL) + return false; + + CFDataSetLength(key, kKeySize + kSaltSize + 4); + CCRandomCopyBytes(kCCRandomDefault, CFDataGetMutableBytePtr(key), CFDataGetLength(key) - 4); + uint32_t size = htonl(kIterations); + memcpy(CFDataGetMutableBytePtr(key) + kKeySize + kSaltSize, &size, sizeof(size)); + + /* + * Create data for password + */ + + pw = CFStringCreateExternalRepresentation(NULL, inPassword, kCFStringEncodingUTF8, 0); + if (pw == NULL) { + CFReleaseNull(key); + return false; + } + + const CFIndex passwordLength = CFDataGetLength(pw); + + if (passwordLength > maxSize) { + CFReleaseNull(pw); + CFReleaseNull(key); + return false; + } + + CFIndex paddedSize = passwordLength + paddingSize - (passwordLength % paddingSize); + const CFIndex outLength = 1 + 4 + paddedSize + tagLen; + + npw = CFDataCreateMutable(NULL, outLength); + if (npw == NULL) { + CFReleaseNull(pw); + CFReleaseNull(key); + return false; + } + CFDataSetLength(npw, outLength); + + memset(CFDataGetMutableBytePtr(npw), 0, outLength); + CFDataGetMutableBytePtr(npw)[0] = BCversion; + size = htonl(passwordLength); + memcpy(CFDataGetMutableBytePtr(npw) + 1, &size, sizeof(size)); + memcpy(CFDataGetMutableBytePtr(npw) + 5, CFDataGetBytePtr(pw), passwordLength); + + /* + * Now create a GCM encrypted password using the random key + */ + + ccgcm_ctx_decl(gcm.size, ctx); + gcm.init(&gcm, ctx, kKeySize, CFDataGetMutableBytePtr(key)); + gcm.gmac(ctx, 1, CFDataGetMutableBytePtr(npw)); + gcm.gcm(ctx, outLength - tagLen - 1, CFDataGetMutableBytePtr(npw) + 1, CFDataGetMutableBytePtr(npw) + 1); + gcm.finalize(ctx, tagLen, CFDataGetMutableBytePtr(npw) + outLength - tagLen); + ccgcm_ctx_clear(gcm.size, ctx); + + /* + * Wrapping key is PBKDF2(sha256) over password + */ + + if (di->output_size < kKeySize) abort(); + + uint8_t rawkey[di->output_size]; + + if (ccpbkdf2_hmac(di, CFDataGetLength(pw), CFDataGetBytePtr(pw), + kSaltSize, CFDataGetMutableBytePtr(key) + kKeySize, + kIterations, + sizeof(rawkey), rawkey) != 0) + abort(); + + /* + * Wrap the random key with one round of ECB cryto + */ + + ccecb_ctx_decl(ecb->size, ecbkey); + ecb->init(ecb, ecbkey, kKeySize, rawkey); + ecb->ecb(ecbkey, 1, CFDataGetMutableBytePtr(key), CFDataGetMutableBytePtr(key)); + + /* + * + */ + + memset(rawkey, 0, sizeof(rawkey)); + CFReleaseNull(pw); + + *outBreadcrumb = npw; + *outEncryptedKey = key; + + return true; +} + + +Boolean +SecBreadcrumbCopyPassword(CFStringRef inPassword, + CFDataRef inBreadcrumb, + CFDataRef inEncryptedKey, + CFStringRef *outPassword, + CFErrorRef *outError) +{ + const struct ccmode_ecb *ecb = ccaes_ecb_decrypt_mode(); + const struct ccmode_gcm gcm = CCMODE_FACTORY_GCM_DECRYPT(ccaes_ecb_encrypt_mode()); + const struct ccdigest_info *di = ccsha256_di(); + CFMutableDataRef gcmkey, oldpw; + CFDataRef pw; + uint32_t size; + + *outPassword = NULL; + if (outError) + *outError = NULL; + + if (CFDataGetLength(inEncryptedKey) < kKeySize + kSaltSize + 4) { + return false; + } + + if (CFDataGetLength(inBreadcrumb) < 1 + 4 + paddingSize + tagLen) { + return false; + } + + if (CFDataGetBytePtr(inBreadcrumb)[0] != BCversion) { + return false; + } + + gcmkey = CFDataCreateMutableCopy(NULL, 0, inEncryptedKey); + if (gcmkey == NULL) { + return false; + } + + const CFIndex outLength = CFDataGetLength(inBreadcrumb) - 1 - tagLen; + if ((outLength % 16) != 0 && outLength < 4) { + CFReleaseNull(gcmkey); + return false; + } + + oldpw = CFDataCreateMutable(NULL, outLength); + if (oldpw == NULL) { + CFReleaseNull(gcmkey); + return false; + } + CFDataSetLength(oldpw, outLength); + + + /* + * Create data for password + */ + + pw = CFStringCreateExternalRepresentation(NULL, inPassword, kCFStringEncodingUTF8, 0); + if (pw == NULL) { + CFReleaseNull(oldpw); + CFReleaseNull(gcmkey); + return false; + } + + /* + * Wrapping key is HMAC(sha256) over password + */ + + if (di->output_size < kKeySize) abort(); + + uint8_t rawkey[di->output_size]; + + memcpy(&size, CFDataGetMutableBytePtr(gcmkey) + kKeySize + kSaltSize, sizeof(size)); + size = ntohl(size); + + if (ccpbkdf2_hmac(di, CFDataGetLength(pw), CFDataGetBytePtr(pw), + kSaltSize, CFDataGetMutableBytePtr(gcmkey) + kKeySize, + size, + sizeof(rawkey), rawkey) != 0) + abort(); + + CFReleaseNull(pw); + + /* + * Unwrap the random key with one round of ECB cryto + */ + + ccecb_ctx_decl(ecb->size, ecbkey); + ecb->init(ecb, ecbkey, kKeySize, rawkey); + ecb->ecb(ecbkey, 1, CFDataGetMutableBytePtr(gcmkey), CFDataGetMutableBytePtr(gcmkey)); + + /* + * GCM unwrap + */ + + uint8_t tag[tagLen]; + ccgcm_ctx_decl(gcm.size, ctx); + + gcm.init(&gcm, ctx, kKeySize, CFDataGetMutableBytePtr(gcmkey)); + gcm.gmac(ctx, 1, CFDataGetBytePtr(inBreadcrumb)); + gcm.gcm(ctx, outLength, CFDataGetBytePtr(inBreadcrumb) + 1, CFDataGetMutableBytePtr(oldpw)); + gcm.finalize(ctx, tagLen, tag); + ccgcm_ctx_clear(gcm.size, ctx); + + CFReleaseNull(gcmkey); + + if (memcmp(tag, CFDataGetBytePtr(inBreadcrumb) + 1 + outLength, tagLen) != 0) { + CFReleaseNull(oldpw); + return false; + } + + memcpy(&size, CFDataGetMutableBytePtr(oldpw), sizeof(size)); + size = ntohl(size); + if (size > outLength - 4) { + CFReleaseNull(oldpw); + return false; + } + memmove(CFDataGetMutableBytePtr(oldpw), CFDataGetMutableBytePtr(oldpw) + 4, size); + CFDataSetLength(oldpw, size); + + *outPassword = CFStringCreateFromExternalRepresentation(NULL, oldpw, kCFStringEncodingUTF8); + CFReleaseNull(oldpw); + + return true; +} + +CFDataRef +SecBreadcrumbCreateNewEncryptedKey(CFStringRef oldPassword, + CFStringRef newPassword, + CFDataRef encryptedKey, + CFErrorRef *outError) +{ + const struct ccmode_ecb *enc = ccaes_ecb_encrypt_mode(); + const struct ccmode_ecb *dec = ccaes_ecb_decrypt_mode(); + const struct ccdigest_info *di = ccsha256_di(); + CFMutableDataRef newEncryptedKey; + CFDataRef newpw = NULL, oldpw = NULL; + uint8_t rawkey[di->output_size]; + + if (CFDataGetLength(encryptedKey) < kKeySize + kSaltSize + 4) { + return NULL; + } + + newEncryptedKey = CFDataCreateMutableCopy(NULL, 0, encryptedKey); + if (newEncryptedKey == NULL) { + return NULL; + } + + oldpw = CFStringCreateExternalRepresentation(NULL, oldPassword, kCFStringEncodingUTF8, 0); + if (oldpw == NULL) { + CFReleaseNull(newEncryptedKey); + return false; + } + + newpw = CFStringCreateExternalRepresentation(NULL, newPassword, kCFStringEncodingUTF8, 0); + if (newpw == NULL) { + CFReleaseNull(newEncryptedKey); + CFReleaseNull(oldpw); + return false; + } + + if (di->output_size < kKeySize) abort(); + + /* + * Unwrap with new key + */ + + uint32_t iter; + + memcpy(&iter, CFDataGetMutableBytePtr(newEncryptedKey) + kKeySize + kSaltSize, sizeof(iter)); + iter = ntohl(iter); + + if (ccpbkdf2_hmac(di, CFDataGetLength(oldpw), CFDataGetBytePtr(oldpw), + kSaltSize, CFDataGetMutableBytePtr(newEncryptedKey) + kKeySize, + iter, + sizeof(rawkey), rawkey) != 0) + abort(); + + CFReleaseNull(oldpw); + + + ccecb_ctx_decl(dec->size, deckey); + dec->init(dec, deckey, kKeySize, rawkey); + dec->ecb(deckey, 1, CFDataGetMutableBytePtr(newEncryptedKey), CFDataGetMutableBytePtr(newEncryptedKey)); + + memset(rawkey, 0, sizeof(rawkey)); + + /* + * Re-wrap with new key + */ + + if (ccpbkdf2_hmac(di, CFDataGetLength(newpw), CFDataGetBytePtr(newpw), + kSaltSize, CFDataGetMutableBytePtr(newEncryptedKey) + kKeySize, + iter, + sizeof(rawkey), rawkey) != 0) + abort(); + + CFReleaseNull(newpw); + + + ccecb_ctx_decl(enc->size, enckey); + enc->init(enc, enckey, kKeySize, rawkey); + enc->ecb(enckey, 1, CFDataGetMutableBytePtr(newEncryptedKey), CFDataGetMutableBytePtr(newEncryptedKey)); + + memset(rawkey, 0, sizeof(rawkey)); + + return newEncryptedKey; +} diff --git a/Security/Breadcrumb/SecBreadcrumb.h b/Security/Breadcrumb/SecBreadcrumb.h new file mode 100644 index 00000000..ad02d1ff --- /dev/null +++ b/Security/Breadcrumb/SecBreadcrumb.h @@ -0,0 +1,61 @@ +/*! + @function SecBreadcrumbCreateFromPassword + @abstract Encryptes the password using a random key and then returns + the encrypted password (breadcrumb) and the password encrypted random key. + + @param inPassword is the password to encrypt and use to encrypt the random key. + @param outBreadcrumb is the password encrypted using a random key. + @param outEncryptedKey is the random key encrypted using inPassword. + @param error An optional pointer to a CFErrorRef. This value is set + if an error occurred. If not NULL, the caller is responsible for + releasing the CFErrorRef. + @result On return a Boolean indicating success or failure. + + @discussion This function generates the breadcrumb that will be used to + update the user's keychain password when their Apple ID Login password + is changed on appleid.apple.com. +*/ + +Boolean +SecBreadcrumbCreateFromPassword(CFStringRef inPassword, + CFDataRef *outBreadcrumb, + CFDataRef *outEncryptedKey, + CFErrorRef *outError); + + +/*! + @function SecBreadcrumbCopyPassword + @abstract Decryptes the encrypted key using the password and uses the key to + decrypt the breadcrumb and returns the password stored in the breadcrumb. + + @param inPassword is the password to decrypt the encrypted random key. + @param inBreadcrumb is the breadcrumb encrypted by the key. It contains + and encrypted version of the users old password. + @param inEcryptedKey is an encrypted version of the key used to encrypt the + breadcrumb. + @param outPassword is the cleartext password that was stored in the breadcrumb. + @param error An optional pointer to a CFErrorRef. This value is set + if an error occurred. If not NULL, the caller is responsible for + releasing the CFErrorRef. + @result On return a Boolean indicating success or failure. + + @discussion This function uses the password to decrypt the encrypted key and then + uses that key to decrypt the breadcrumb. +*/ + +Boolean +SecBreadcrumbCopyPassword(CFStringRef inPassword, + CFDataRef inBreadcrumb, + CFDataRef inEncryptedKey, + CFStringRef *outPassword, + CFErrorRef *outError); + +/* + * Change password used to encrypt the key from old password to new password + */ + +CFDataRef +SecBreadcrumbCreateNewEncryptedKey(CFStringRef oldPassword, + CFStringRef newPassword, + CFDataRef encryptedKey, + CFErrorRef *outError); diff --git a/Security/Breadcrumb/bc-10-knife-on-bread.c b/Security/Breadcrumb/bc-10-knife-on-bread.c new file mode 100644 index 00000000..e3d4409b --- /dev/null +++ b/Security/Breadcrumb/bc-10-knife-on-bread.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include + +#include "breadcrumb_regressions.h" + +static void +print_hex(const char *label, CFDataRef data) +{ + CFIndex count, n; + printf("%s = ", label); + const uint8_t *ptr = CFDataGetBytePtr(data); + count = CFDataGetLength(data); + for (n = 0; n < count; n++) { + printf("%02x", ptr[n]); + } + printf("\n"); +} + + + +#define kTestCount 6 +int bc_10_password(int argc, char *const *argv) +{ + CFDataRef breadcrumb = NULL, encryptedKey = NULL; + CFStringRef oldPassword = NULL; + CFStringRef password = CFSTR("password"); + CFStringRef newpassword = CFSTR("newpassword"); + CFErrorRef error = NULL; + + plan_tests(kTestCount); + + ok(SecBreadcrumbCreateFromPassword(password, &breadcrumb, &encryptedKey, &error), "wrap failed"); + + ok(SecBreadcrumbCopyPassword(password, breadcrumb, encryptedKey, &oldPassword, NULL), "unwrap failed"); + + ok(oldPassword && CFStringCompare(password, oldPassword, 0) == kCFCompareEqualTo, "not same password"); + CFRelease(oldPassword); + + print_hex("encrypted key before", encryptedKey); + + CFDataRef newEncryptedKey; + + + printf("changing password from \"password\" to \"newpassword\"\n"); + + newEncryptedKey = SecBreadcrumbCreateNewEncryptedKey(password, + newpassword, + encryptedKey, + &error); + ok(newEncryptedKey, "no new encrypted key"); + + print_hex("encrypted key after", newEncryptedKey); + + + ok(SecBreadcrumbCopyPassword(newpassword, breadcrumb, newEncryptedKey, &oldPassword, NULL), "unwrap failed"); + + ok(oldPassword && CFStringCompare(password, oldPassword, 0) == kCFCompareEqualTo, "not same password"); + + CFRelease(breadcrumb); + CFRelease(oldPassword); + CFRelease(newEncryptedKey); + + return 0; +} diff --git a/Security/Breadcrumb/breadcrumb_regressions.h b/Security/Breadcrumb/breadcrumb_regressions.h new file mode 100644 index 00000000..2b4b5b2a --- /dev/null +++ b/Security/Breadcrumb/breadcrumb_regressions.h @@ -0,0 +1,7 @@ +/* To add a test: + 1) add it here + 2) Add it as command line argument for SecurityTest.app in the Release and Debug schemes + */ +#include + +ONE_TEST(bc_10_password) diff --git a/Security/CloudKeychainProxy/CloudKeychainProxy-Info.plist b/Security/CloudKeychainProxy/CloudKeychainProxy-Info.plist new file mode 100644 index 00000000..d33c8687 --- /dev/null +++ b/Security/CloudKeychainProxy/CloudKeychainProxy-Info.plist @@ -0,0 +1,30 @@ + + + + + LSBackgroundOnly + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.apple.security.cloudkeychainproxy3 + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSHumanReadableCopyright + Copyright © 2013 Apple, Inc. All rights reserved. + + diff --git a/sec/SOSCircle/CloudKeychainProxy/cloudkeychain.entitlements.plist b/Security/CloudKeychainProxy/cloudkeychain.entitlements.plist similarity index 100% rename from sec/SOSCircle/CloudKeychainProxy/cloudkeychain.entitlements.plist rename to Security/CloudKeychainProxy/cloudkeychain.entitlements.plist diff --git a/Security/CloudKeychainProxy/com.apple.security.cloudkeychainproxy.plist b/Security/CloudKeychainProxy/com.apple.security.cloudkeychainproxy.plist new file mode 100644 index 00000000..b841f7f2 --- /dev/null +++ b/Security/CloudKeychainProxy/com.apple.security.cloudkeychainproxy.plist @@ -0,0 +1,57 @@ + + + + + ProcessType + Adaptive + LimitLoadToSessionType + Background + EnablePressuredExit + + ProgramArguments + + /System/Library/Frameworks/Security.framework/Versions/A/Resources/CloudKeychainProxy.bundle/Contents/MacOS/CloudKeychainProxy + + MachServices + + com.apple.security.cloudkeychainproxy3 + + + RunAtLoad + + KeepAlive + + Program + /System/Library/Frameworks/Security.framework/Versions/A/Resources/CloudKeychainProxy.bundle/Contents/MacOS/CloudKeychainProxy + Label + com.apple.security.cloudkeychainproxy3 + EnvironmentVariables + + DEBUGSCOPE + all + WAIT4DEBUGGER + NO + + LaunchEvents + + com.apple.notifyd.matching + + com.apple.keystore.lockstatus + + Notification + com.apple.keystore.lockstatus + + com.apple.security.cloudkeychainproxy.kvstorechange3 + + Notification + com.apple.security.cloudkeychainproxy.kvstorechange3 + + com.apple.security.cloudkeychain.forceupdate + + Notification + com.apple.security.cloudkeychain.forceupdate + + + + + diff --git a/Keychain/en.lproj/InfoPlist.strings b/Security/CloudKeychainProxy/en.lproj/InfoPlist.strings similarity index 100% rename from Keychain/en.lproj/InfoPlist.strings rename to Security/CloudKeychainProxy/en.lproj/InfoPlist.strings diff --git a/Security/Keychain Circle Notification/KNAppDelegate.h b/Security/Keychain Circle Notification/KNAppDelegate.h new file mode 100644 index 00000000..0ef34b7a --- /dev/null +++ b/Security/Keychain Circle Notification/KNAppDelegate.h @@ -0,0 +1,38 @@ +/* + * 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@ + */ + + +#import +#import +#import "KNPersistantState.h" + +@class KDSecCircle; + +@interface KNAppDelegate : NSObject + +@property (assign) IBOutlet NSWindow *window; +@property (retain) KDSecCircle *circle; +@property (retain) NSMutableSet *viewedIds; +@property (retain) KNPersistantState *state; + +@end diff --git a/Keychain Circle Notification/KNAppDelegate.m b/Security/Keychain Circle Notification/KNAppDelegate.m similarity index 86% rename from Keychain Circle Notification/KNAppDelegate.m rename to Security/Keychain Circle Notification/KNAppDelegate.m index 3e419e1f..529c2056 100644 --- a/Keychain Circle Notification/KNAppDelegate.m +++ b/Security/Keychain Circle Notification/KNAppDelegate.m @@ -1,10 +1,26 @@ -// -// KNAppDelegate.m -// Keychain Circle Notification -// -// Created by J Osborne on 2/21/13. -// -// +/* + * 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@ + */ + #import "KNAppDelegate.h" #import "KDSecCircle.h" @@ -18,6 +34,8 @@ #import static char *kLaunchLaterXPCName = "com.apple.security.Keychain-Circle-Notification-TICK"; +static const NSString *kKickedOutKey = @"KickedOut"; +static const NSString *kValidOnlyOutOfCircleKey = @"ValidOnlyOutOfCircle"; @implementation KNAppDelegate @@ -95,7 +113,7 @@ static NSUserNotificationCenter *appropriateNotificationCenter() CFNotificationCenterPostNotificationWithOptions(CFNotificationCenterGetDistributedCenter(), CFSTR("com.apple.security.secureobjectsync.pendingApplicationReminder"), (__bridge const void *)([self.state.applcationDate description]), NULL, 0); [self postApplicationReminder]; - self.state.pendingApplicationReminder = [self.state.applcationDate dateByAddingTimeInterval:[self getPendingApplicationReminderInterval]]; + self.state.pendingApplicationReminder = [nowish dateByAddingTimeInterval:[self getPendingApplicationReminderInterval]]; [self.state writeToStorage]; } } @@ -184,7 +202,16 @@ static NSUserNotificationCenter *appropriateNotificationCenter() if (body) { [me postKickedOutWithMessage: body]; } - } + } else if (me.circle.isInCircle) { + // We are in a circle, so we should get rid of any reset notifications that are hanging out + NSUserNotificationCenter *noteCenter = appropriateNotificationCenter(); + for (NSUserNotification *note in noteCenter.deliveredNotifications) { + if (note.userInfo[kValidOnlyOutOfCircleKey]) { + NSLog(@"Removing existing notification (%@) now that we are in circle", note); + [appropriateNotificationCenter() removeDeliveredNotification: note]; + } + } + } [me timerCheck]; @@ -319,7 +346,7 @@ static NSUserNotificationCenter *appropriateNotificationCenter() { NSUserNotificationCenter *noteCenter = appropriateNotificationCenter(); for (NSUserNotification *note in noteCenter.deliveredNotifications) { - if (note.userInfo[@"KickedOut"]) { + if (note.userInfo[kKickedOutKey]) { if (note.isPresented) { NSLog(@"Already posted&presented (removing): %@", note); [appropriateNotificationCenter() removeDeliveredNotification: note]; @@ -341,7 +368,8 @@ static NSUserNotificationCenter *appropriateNotificationCenter() note.identifier = [[NSUUID new] UUIDString]; - note.userInfo = @{@"KickedOut": @1, + note.userInfo = @{kKickedOutKey: @1, + kValidOnlyOutOfCircleKey: @1, @"SPECIAL": @1, @"Activate": (__bridge NSString *)kMMPropertyKeychainMRDetailsAEAction, }; @@ -377,11 +405,12 @@ static NSUserNotificationCenter *appropriateNotificationCenter() note.identifier = [[NSUUID new] UUIDString]; note.userInfo = @{@"ApplicationReminder": @1, + kValidOnlyOutOfCircleKey: @1, @"SPECIAL": @1, @"Activate": (__bridge NSString *)kMMPropertyKeychainWADetailsAEAction, }; - NSLog(@"About to post#-/%lu (REMINDER): %@", (unsigned long)noteCenter.deliveredNotifications.count, note); + NSLog(@"About to post#-/%lu (REMINDER): %@ (I=%@)", (unsigned long)noteCenter.deliveredNotifications.count, note, [note.userInfo compactDescription]); [appropriateNotificationCenter() deliverNotification:note]; } diff --git a/Security/Keychain Circle Notification/KNPersistantState.h b/Security/Keychain Circle Notification/KNPersistantState.h new file mode 100644 index 00000000..4fae62fd --- /dev/null +++ b/Security/Keychain Circle Notification/KNPersistantState.h @@ -0,0 +1,39 @@ +/* + * 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@ + */ + + +#import +#include "SecureObjectSync/SOSCloudCircle.h" +#include "SecureObjectSync/SOSPeerInfo.h" + +@interface KNPersistantState : NSObject ++(instancetype)loadFromStorage; +-(void)writeToStorage; + +@property SOSCCStatus lastCircleStatus; +@property NSNumber *debugLeftReason; +@property NSNumber *pendingApplicationReminderInterval; +@property NSDate *pendingApplicationReminder; +@property NSDate *applcationDate; +@property NSDate *lastWritten; +@end diff --git a/Keychain Circle Notification/KNPersistantState.m b/Security/Keychain Circle Notification/KNPersistantState.m similarity index 75% rename from Keychain Circle Notification/KNPersistantState.m rename to Security/Keychain Circle Notification/KNPersistantState.m index dd65f76b..a63eceeb 100644 --- a/Keychain Circle Notification/KNPersistantState.m +++ b/Security/Keychain Circle Notification/KNPersistantState.m @@ -1,10 +1,26 @@ -// -// KNPersistantState.m -// Security -// -// Created by J Osborne on 7/28/13. -// -// +/* + * 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@ + */ + #import "KNPersistantState.h" diff --git a/Keychain Circle Notification/Keychain Circle Notification-Info.plist b/Security/Keychain Circle Notification/Keychain Circle Notification-Info.plist similarity index 91% rename from Keychain Circle Notification/Keychain Circle Notification-Info.plist rename to Security/Keychain Circle Notification/Keychain Circle Notification-Info.plist index 0896253d..9955cea7 100644 --- a/Keychain Circle Notification/Keychain Circle Notification-Info.plist +++ b/Security/Keychain Circle Notification/Keychain Circle Notification-Info.plist @@ -6,8 +6,6 @@ en CFBundleExecutable ${EXECUTABLE_NAME} - CFBundleIconFile - CloudKeychain.icns CFBundleIdentifier com.security.apple.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion @@ -21,7 +19,7 @@ CFBundleSignature ???? CFBundleVersion - 55471.14.18 + ${CURRENT_PROJECT_VERSION} LSApplicationCategoryType LSMinimumSystemVersion diff --git a/Keychain Circle Notification/Keychain Circle Notification-Prefix.pch b/Security/Keychain Circle Notification/Keychain Circle Notification-Prefix.pch similarity index 100% rename from Keychain Circle Notification/Keychain Circle Notification-Prefix.pch rename to Security/Keychain Circle Notification/Keychain Circle Notification-Prefix.pch diff --git a/Security/Keychain Circle Notification/NSArray+mapWithBlock.h b/Security/Keychain Circle Notification/NSArray+mapWithBlock.h new file mode 100644 index 00000000..a6b0a7c2 --- /dev/null +++ b/Security/Keychain Circle Notification/NSArray+mapWithBlock.h @@ -0,0 +1,31 @@ +/* + * 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@ + */ + + +#import + +typedef id (^mapBlock)(id obj); + +@interface NSArray (mapWithBlock) +-(NSArray*)mapWithBlock:(mapBlock)block; +@end diff --git a/Security/Keychain Circle Notification/NSArray+mapWithBlock.m b/Security/Keychain Circle Notification/NSArray+mapWithBlock.m new file mode 100644 index 00000000..ac0b8d74 --- /dev/null +++ b/Security/Keychain Circle Notification/NSArray+mapWithBlock.m @@ -0,0 +1,40 @@ +/* + * 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@ + */ + + +#import "NSArray+mapWithBlock.h" + +@implementation NSArray (mapWithBlock) + +-(NSArray*)mapWithBlock:(mapBlock)block +{ + NSMutableArray *mapped = [[NSMutableArray alloc] initWithCapacity:self.count]; + + for (id obj in self) { + [mapped addObject:block(obj)]; + } + + return [mapped copy]; +} + +@end diff --git a/Security/Keychain Circle Notification/NSDictionary+compactDescription.h b/Security/Keychain Circle Notification/NSDictionary+compactDescription.h new file mode 100644 index 00000000..d82078d4 --- /dev/null +++ b/Security/Keychain Circle Notification/NSDictionary+compactDescription.h @@ -0,0 +1,30 @@ +/* + * 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@ + */ + + +#import + +@interface NSDictionary (compactDescription) +-(NSString*)compactDescription; +-(NSString*)compactDescriptionWithoutItemData; +@end diff --git a/Security/Keychain Circle Notification/NSDictionary+compactDescription.m b/Security/Keychain Circle Notification/NSDictionary+compactDescription.m new file mode 100644 index 00000000..64350b77 --- /dev/null +++ b/Security/Keychain Circle Notification/NSDictionary+compactDescription.m @@ -0,0 +1,68 @@ +/* + * 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@ + */ + + +#import "NSDictionary+compactDescription.h" +#import "NSString+compactDescription.h" + +@implementation NSDictionary (compactDescription) + +-(NSString*)compactDescription +{ + NSMutableArray *results = [NSMutableArray new]; + for (NSString *k in self) { + id v = self[k]; + if ([v respondsToSelector:@selector(compactDescription)]) { + v = [v compactDescription]; + } else { + v = [v description]; + } + + [results addObject:[NSString stringWithFormat:@"%@=%@", [k compactDescription], v]]; + } + return [NSString stringWithFormat:@"{%@}", [results componentsJoinedByString:@", "]]; +} + +-(NSString*)compactDescriptionWithoutItemData; +{ + NSMutableArray *results = [NSMutableArray new]; + for (NSString *k in self) { + if ([k isEqualToString:kSecValueData]) { + [results addObject:[NSString stringWithFormat:@"%@=", [k compactDescription]]]; + continue; + } + + id v = self[k]; + if ([v respondsToSelector:@selector(compactDescription)]) { + v = [v compactDescription]; + } else { + v = [v description]; + } + + [results addObject:[NSString stringWithFormat:@"%@=%@", [k compactDescription], v]]; + } + return [NSString stringWithFormat:@"{%@}", [results componentsJoinedByString:@", "]]; + +} + +@end diff --git a/Security/Keychain Circle Notification/NSSet+compactDescription.h b/Security/Keychain Circle Notification/NSSet+compactDescription.h new file mode 100644 index 00000000..8135178f --- /dev/null +++ b/Security/Keychain Circle Notification/NSSet+compactDescription.h @@ -0,0 +1,29 @@ +/* + * 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@ + */ + + +#import + +@interface NSSet (compactDescription) +-(NSString*)compactDescription; +@end diff --git a/Security/Keychain Circle Notification/NSSet+compactDescription.m b/Security/Keychain Circle Notification/NSSet+compactDescription.m new file mode 100644 index 00000000..ee51c843 --- /dev/null +++ b/Security/Keychain Circle Notification/NSSet+compactDescription.m @@ -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@ + */ + + +#import "NSSet+compactDescription.h" + +@implementation NSSet (compactDescription) + +-(NSString*)compactDescription +{ + NSMutableArray *results = [NSMutableArray new]; + for (id v in self) { + if ([v respondsToSelector:@selector(compactDescription)]) { + [results addObject:[v compactDescription]]; + } else { + [results addObject:[v description]]; + } + } + return [NSString stringWithFormat:@"[%@]", [results componentsJoinedByString:@", "]]; +} + +@end diff --git a/Security/Keychain Circle Notification/NSString+compactDescription.h b/Security/Keychain Circle Notification/NSString+compactDescription.h new file mode 100644 index 00000000..e8238df4 --- /dev/null +++ b/Security/Keychain Circle Notification/NSString+compactDescription.h @@ -0,0 +1,29 @@ +/* + * 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@ + */ + + +#import + +@interface NSString (compactDescription) +-(NSString*)compactDescription; +@end diff --git a/Security/Keychain Circle Notification/NSString+compactDescription.m b/Security/Keychain Circle Notification/NSString+compactDescription.m new file mode 100644 index 00000000..2cbe6cf0 --- /dev/null +++ b/Security/Keychain Circle Notification/NSString+compactDescription.m @@ -0,0 +1,46 @@ +/* + * 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@ + */ + + +#import "NSString+compactDescription.h" + +@implementation NSString (compactDescription) + +-(NSString*)compactDescription +{ + static NSCharacterSet *forceQuotes = nil; + static dispatch_once_t setup; + dispatch_once(&setup, ^{ + forceQuotes = [NSCharacterSet characterSetWithCharactersInString:@"\"' \t\n\r="]; + }); + + if ([self rangeOfCharacterFromSet:forceQuotes].location != NSNotFound) { + NSString *escaped = [self stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; + escaped = [escaped stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; + return [NSString stringWithFormat:@"\"%@\"", escaped]; + } else { + return self; + } +} + +@end diff --git a/Keychain Circle Notification/com.apple.security.keychain-circle-notification.plist b/Security/Keychain Circle Notification/com.apple.security.keychain-circle-notification.plist similarity index 86% rename from Keychain Circle Notification/com.apple.security.keychain-circle-notification.plist rename to Security/Keychain Circle Notification/com.apple.security.keychain-circle-notification.plist index 2c98255e..bc7d56c4 100644 --- a/Keychain Circle Notification/com.apple.security.keychain-circle-notification.plist +++ b/Security/Keychain Circle Notification/com.apple.security.keychain-circle-notification.plist @@ -5,7 +5,7 @@ Label com.apple.security.keychain-circle-notification RunAtLoad - + KeepAlive LaunchEvents @@ -17,11 +17,6 @@ Notification com.apple.security.tick - 1stunlock - - Notification - com.apple.keystore.firstunlock - kSOSCCCircleChangedNotification Notification diff --git a/Keychain Circle Notification/en.lproj/Credits.rtf b/Security/Keychain Circle Notification/en.lproj/Credits.rtf similarity index 100% rename from Keychain Circle Notification/en.lproj/Credits.rtf rename to Security/Keychain Circle Notification/en.lproj/Credits.rtf diff --git a/authd/en.lproj/InfoPlist.strings b/Security/Keychain Circle Notification/en.lproj/InfoPlist.strings similarity index 100% rename from authd/en.lproj/InfoPlist.strings rename to Security/Keychain Circle Notification/en.lproj/InfoPlist.strings diff --git a/Keychain Circle Notification/en.lproj/Localizable.strings b/Security/Keychain Circle Notification/en.lproj/Localizable.strings similarity index 100% rename from Keychain Circle Notification/en.lproj/Localizable.strings rename to Security/Keychain Circle Notification/en.lproj/Localizable.strings diff --git a/Keychain Circle Notification/en.lproj/MainMenu.xib b/Security/Keychain Circle Notification/en.lproj/MainMenu.xib similarity index 100% rename from Keychain Circle Notification/en.lproj/MainMenu.xib rename to Security/Keychain Circle Notification/en.lproj/MainMenu.xib diff --git a/Keychain Circle Notification/entitlments.plist b/Security/Keychain Circle Notification/entitlments.plist similarity index 100% rename from Keychain Circle Notification/entitlments.plist rename to Security/Keychain Circle Notification/entitlments.plist diff --git a/Security/Keychain Circle Notification/main.m b/Security/Keychain Circle Notification/main.m new file mode 100644 index 00000000..e297a2fb --- /dev/null +++ b/Security/Keychain Circle Notification/main.m @@ -0,0 +1,30 @@ +/* + * 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@ + */ + + +#import + +int main(int argc, char *argv[]) +{ + return NSApplicationMain(argc, (const char **)argv); +} diff --git a/Keychain/Icon.icns b/Security/Keychain/Icon.icns similarity index 100% rename from Keychain/Icon.icns rename to Security/Keychain/Icon.icns diff --git a/Security/Keychain/KDAppDelegate.h b/Security/Keychain/KDAppDelegate.h new file mode 100644 index 00000000..f4494c90 --- /dev/null +++ b/Security/Keychain/KDAppDelegate.h @@ -0,0 +1,49 @@ +/* + * 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@ + */ + + +#import +#import "KDSecItems.h" +#import "KDSecCircle.h" + +@interface KDAppDelegate : NSObject + +@property (assign) IBOutlet NSWindow *window; +@property (assign) IBOutlet NSTableView *itemTable; +@property (assign) IBOutlet NSTextFieldCell *itemTableTitle; +@property (retain) id itemDataSource; + +@property (assign) IBOutlet NSButton *enableKeychainSyncing; +@property (assign) IBOutlet NSTextFieldCell *circleStatusCell; +@property (assign) IBOutlet NSTextFieldCell *peerCountCell; +@property (assign) IBOutlet NSTextView *peerTextList; +@property (assign) IBOutlet NSTextFieldCell *applicantCountCell; +@property (assign) IBOutlet NSTextView *applicantTextList; +@property (assign) IBOutlet NSProgressIndicator *syncSpinner; + +@property (retain) KDSecCircle *circle; + +@property (retain) NSMutableArray *stuffNotToLeak; + +-(IBAction)enableKeychainSyncingClicked:(id)sender; +@end diff --git a/Security/Keychain/KDAppDelegate.m b/Security/Keychain/KDAppDelegate.m new file mode 100644 index 00000000..92431e81 --- /dev/null +++ b/Security/Keychain/KDAppDelegate.m @@ -0,0 +1,99 @@ +/* + * 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@ + */ + + +#import "KDAppDelegate.h" +#import "KDCirclePeer.h" +#import "NSArray+mapWithBlock.h" +#include + +#define kSecServerKeychainChangedNotification "com.apple.security.keychainchanged" + +@implementation KDAppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification +{ + self.stuffNotToLeak = [NSMutableArray new]; + [self.stuffNotToLeak addObject:[[NSNotificationCenter defaultCenter] addObserverForName:kKDSecItemsUpdated object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { + self.itemTableTitle.title = [NSString stringWithFormat:@"All Items (%ld)", (long)[self.itemDataSource numberOfRowsInTableView:self.itemTable]]; + }]]; + + [self.syncSpinner setUsesThreadedAnimation:YES]; + [self.syncSpinner startAnimation:nil]; + + self.itemDataSource = [[KDSecItems alloc] init]; + self.itemTable.dataSource = self.itemDataSource; + + int notificationToken; + uint32_t rc = notify_register_dispatch(kSecServerKeychainChangedNotification, ¬ificationToken, dispatch_get_main_queue(), ^(int token __unused) { + NSLog(@"Received %s", kSecServerKeychainChangedNotification); + [(KDSecItems*)self.itemDataSource loadItems]; + [self.itemTable reloadData]; + }); + NSAssert(rc == 0, @"Can't register for %s", kSecServerKeychainChangedNotification); + + self.circle = [KDSecCircle new]; + [self.circle addChangeCallback:^{ + self.circleStatusCell.stringValue = self.circle.status; + + [self setCheckbox]; + + self.peerCountCell.objectValue = @(self.circle.peers.count); + NSString *peerNames = [[self.circle.peers mapWithBlock:^id(id obj) { + return ((KDCirclePeer*)obj).name; + }] componentsJoinedByString:@"\n"]; + [self.peerTextList.textStorage replaceCharactersInRange:NSMakeRange(0, [self.peerTextList.textStorage length]) withString:peerNames]; + + self.applicantCountCell.objectValue = @(self.circle.applicants.count); + NSString *applicantNames = [[self.circle.applicants mapWithBlock:^id(id obj) { + return ((KDCirclePeer*)obj).name; + }] componentsJoinedByString:@"\n"]; + [self.applicantTextList.textStorage replaceCharactersInRange:NSMakeRange(0, [self.applicantTextList.textStorage length]) withString:applicantNames]; + + [self.syncSpinner stopAnimation:nil]; + }]; +} + +-(void)setCheckbox +{ + if (self.circle.isInCircle) { + [self.enableKeychainSyncing setState:NSOnState]; + } else if (self.circle.isOutOfCircle) { + [self.enableKeychainSyncing setState:NSOffState]; + } else { + [self.enableKeychainSyncing setState:NSMixedState]; + } +} + +-(IBAction)enableKeychainSyncingClicked:(id)sender +{ + [self.syncSpinner startAnimation:sender]; + if (self.circle.isOutOfCircle) { + [self.circle enableSync]; + } else { + [self.circle disableSync]; + } + [self setCheckbox]; +} + +@end diff --git a/Security/Keychain/KDCirclePeer.h b/Security/Keychain/KDCirclePeer.h new file mode 100644 index 00000000..12d07e3e --- /dev/null +++ b/Security/Keychain/KDCirclePeer.h @@ -0,0 +1,35 @@ +/* + * 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@ + */ + + +#import + +@interface KDCirclePeer : NSObject + +@property (readonly) NSString *name; +@property (readonly) NSString *idString; +@property (readonly) id peerObject; + +-(id)initWithPeerObject:(id)peerObject; + +@end diff --git a/Security/Keychain/KDCirclePeer.m b/Security/Keychain/KDCirclePeer.m new file mode 100644 index 00000000..a813b41c --- /dev/null +++ b/Security/Keychain/KDCirclePeer.m @@ -0,0 +1,58 @@ +/* + * 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@ + */ + + +#import "KDCirclePeer.h" +#include "SecureObjectSync/SOSCloudCircle.h" +#include "SecureObjectSync/SOSPeerInfo.h" + +@interface KDCirclePeer () + +@property (readwrite) NSString *name; +@property (readwrite) NSString *idString; +@property (readwrite) id peerObject; + +@end + +@implementation KDCirclePeer + +-(id)initWithPeerObject:(id)peerObject +{ + self = [super init]; + if (!self) { + return self; + } + + self.peerObject = peerObject; + self.name = (__bridge NSString *)(SOSPeerInfoGetPeerName((__bridge SOSPeerInfoRef)peerObject)); + self.idString = (__bridge NSString *)(SOSPeerInfoGetPeerID((__bridge SOSPeerInfoRef)peerObject)); + + return self; +} + +-(NSString*)description +{ + return [NSString stringWithFormat:@"[peer n='%@' id='%@' o=%@]", self.name, self.idString, self.peerObject]; +} + +@end diff --git a/Security/Keychain/KDSecCircle.h b/Security/Keychain/KDSecCircle.h new file mode 100644 index 00000000..214c77ab --- /dev/null +++ b/Security/Keychain/KDSecCircle.h @@ -0,0 +1,51 @@ +/* + * 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@ + */ + + +#import "SecureObjectSync/SOSCloudCircle.h" +#import + +@interface KDSecCircle : NSObject + +@property (readonly) BOOL isInCircle; +@property (readonly) BOOL isOutOfCircle; + +@property (readonly) SOSCCStatus rawStatus; + +@property (readonly) NSString *status; +@property (readonly) NSError *error; + +// Both of these are arrays of KDCircelPeer objects +@property (readonly) NSArray *peers; +@property (readonly) NSArray *applicants; + +-(void)addChangeCallback:(dispatch_block_t)callback; +-(id)init; + +// these are "try to", and may (most likely will) not complete by the time they return +-(void)enableSync; +-(void)disableSync; +-(void)rejectApplicantId:(NSString*)applicantId; +-(void)acceptApplicantId:(NSString*)applicantId; + +@end diff --git a/Keychain/KDSecCircle.m b/Security/Keychain/KDSecCircle.m similarity index 81% rename from Keychain/KDSecCircle.m rename to Security/Keychain/KDSecCircle.m index 0952b913..c1a91817 100644 --- a/Keychain/KDSecCircle.m +++ b/Security/Keychain/KDSecCircle.m @@ -1,10 +1,26 @@ -// -// KDSecCircle.m -// Security -// -// Created by J Osborne on 2/20/13. -// -// +/* + * 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@ + */ + #import "KDSecCircle.h" #import "KDCirclePeer.h" @@ -76,10 +92,6 @@ self.status = [NSString stringWithFormat:@"Error: %@", err]; break; - case kSOSCCParamErr: - self.status = [NSString stringWithFormat:@"ParamError: %@", err]; - break; - default: self.status = [NSString stringWithFormat:@"Unknown status code %d", self.rawStatus]; break; @@ -119,7 +131,7 @@ typedef void (^applicantBlock)(id applicant); -(void)acceptApplicantId:(NSString*)applicantId { [self forApplicantId:applicantId run:^void(id applicant) { - CFErrorRef err; + CFErrorRef err = NULL; bool ok = SOSCCAcceptApplicants((__bridge CFArrayRef)(@[applicant]), &err); NSAssert(ok, @"Error %@ while accepting %@ (%@)", err, applicantId, applicant); }]; @@ -128,7 +140,7 @@ typedef void (^applicantBlock)(id applicant); -(void)rejectApplicantId:(NSString*)applicantId { [self forApplicantId:applicantId run:^void(id applicant) { - CFErrorRef err; + CFErrorRef err = NULL; bool ok = SOSCCRejectApplicants((__bridge CFArrayRef)(@[applicant]), &err); NSAssert(ok, @"Error %@ while rejecting %@ (%@)", err, applicantId, applicant); }]; @@ -173,7 +185,7 @@ typedef void (^applicantBlock)(id applicant); -(void)enableSync { - CFErrorRef err; + CFErrorRef err = NULL; if (self.rawStatus == kSOSCCCircleAbsent) { SOSCCResetToOffering(&err); } else { @@ -183,7 +195,7 @@ typedef void (^applicantBlock)(id applicant); -(void)disableSync { - CFErrorRef err; + CFErrorRef err = NULL; SOSCCRemoveThisDeviceFromCircle(&err); } diff --git a/Security/Keychain/KDSecItems.h b/Security/Keychain/KDSecItems.h new file mode 100644 index 00000000..24a588f2 --- /dev/null +++ b/Security/Keychain/KDSecItems.h @@ -0,0 +1,34 @@ +/* + * 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@ + */ + + +#import + +extern NSString *kKDSecItemsUpdated; + +@interface KDSecItems : NSObject +-(NSInteger)numberOfRowsInTableView:(NSTableView*)t; +- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex; + +-(void)loadItems; +@end diff --git a/Keychain/KDSecItems.m b/Security/Keychain/KDSecItems.m similarity index 76% rename from Keychain/KDSecItems.m rename to Security/Keychain/KDSecItems.m index 0f26422d..0571aa28 100644 --- a/Keychain/KDSecItems.m +++ b/Security/Keychain/KDSecItems.m @@ -1,10 +1,26 @@ -// -// KDSecItems.m -// Security -// -// Created by J Osborne on 2/14/13. -// -// +/* + * 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@ + */ + #import "KDSecItems.h" #include diff --git a/Security/Keychain/Keychain-Info.plist b/Security/Keychain/Keychain-Info.plist new file mode 100644 index 00000000..36213f65 --- /dev/null +++ b/Security/Keychain/Keychain-Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + Icon.icns + CFBundleIdentifier + com.apple.security.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/Keychain/Keychain-Prefix.pch b/Security/Keychain/Keychain-Prefix.pch similarity index 100% rename from Keychain/Keychain-Prefix.pch rename to Security/Keychain/Keychain-Prefix.pch diff --git a/Keychain/en.lproj/Credits.rtf b/Security/Keychain/en.lproj/Credits.rtf similarity index 100% rename from Keychain/en.lproj/Credits.rtf rename to Security/Keychain/en.lproj/Credits.rtf diff --git a/sec/SOSCircle/CloudKeychainProxy/en.lproj/InfoPlist.strings b/Security/Keychain/en.lproj/InfoPlist.strings similarity index 100% rename from sec/SOSCircle/CloudKeychainProxy/en.lproj/InfoPlist.strings rename to Security/Keychain/en.lproj/InfoPlist.strings diff --git a/Keychain/en.lproj/MainMenu.xib b/Security/Keychain/en.lproj/MainMenu.xib similarity index 100% rename from Keychain/en.lproj/MainMenu.xib rename to Security/Keychain/en.lproj/MainMenu.xib diff --git a/Security/Keychain/main.m b/Security/Keychain/main.m new file mode 100644 index 00000000..a1578d7c --- /dev/null +++ b/Security/Keychain/main.m @@ -0,0 +1,30 @@ +/* + * 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@ + */ + + +#import + +int main(int argc, char *argv[]) +{ + return NSApplicationMain(argc, (const char **)argv); +} diff --git a/Security/README b/Security/README new file mode 100644 index 00000000..cfdcee72 --- /dev/null +++ b/Security/README @@ -0,0 +1,29 @@ +This code contains a Darwin version of CDSA along with many other security libraries. + +Information about CDSA may be obtained from the OpenGroup web site at: + + http://www.opengroup.org/pubs/catalog/c914.htm + +Further information regarding the security of the MacOSX product is available at: + + http://www.apple.com/support/security/ + +Developers wishing to know more about developing their products in a manner consistent with MacOS security should view: + + http://developer.apple.com/macos/security.html + + +To build this project in a Darwin environment (as opposed to building in-house +at Apple), use the Darwin buildstyle. If you're building with Xcode, select +"Darwin" from the "Active Build Style" popup. If you're building from the command +line, specify the build style like so: + +% xcodebuild -buildstyle Darwin install + +This build style is necessitated by the fact that the CSP built at (and +shipped by) Apple includes some algorithms which are proprietary to Apple; +the source code for these algorithms is not open source. Selecting the +Darwin build style allows the Security project (and also the CSP, in +the libsecurity_apple_csp project, which also must be built with the +Darwin build style) to be built from the Darwin open source tree without +requiring the source for these algorithms. diff --git a/Security/Security.xcodeproj/project.pbxproj b/Security/Security.xcodeproj/project.pbxproj new file mode 100644 index 00000000..ee84cb23 --- /dev/null +++ b/Security/Security.xcodeproj/project.pbxproj @@ -0,0 +1,6513 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + 0C6C642915D5ADB500BC68CD /* Security_kexts */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 0C6C642A15D5ADB500BC68CD /* Build configuration list for PBXAggregateTarget "Security_kexts" */; + buildPhases = ( + ); + dependencies = ( + 0C6C643015D5AE4C00BC68CD /* PBXTargetDependency */, + 0C6C642E15D5ADC900BC68CD /* PBXTargetDependency */, + ); + name = Security_kexts; + productName = Security_kexts; + }; + 182BB598146FE295000BF1F3 /* World */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 182BB599146FE295000BF1F3 /* Build configuration list for PBXAggregateTarget "World" */; + buildPhases = ( + 18F2360315CB30EC00060520 /* ShellScript */, + ); + dependencies = ( + 186F779914E5A06500434E1F /* PBXTargetDependency */, + 186F779B14E5A06800434E1F /* PBXTargetDependency */, + ); + name = World; + productName = SecurityFramework; + }; + 186F778814E59FB200434E1F /* Security_frameworks */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 186F778914E59FB200434E1F /* Build configuration list for PBXAggregateTarget "Security_frameworks" */; + buildPhases = ( + ); + dependencies = ( + 186F779714E5A04200434E1F /* PBXTargetDependency */, + 186F779514E5A01C00434E1F /* PBXTargetDependency */, + 186F779314E5A01700434E1F /* PBXTargetDependency */, + ); + name = Security_frameworks; + productName = Framework; + }; + 186F778C14E59FDA00434E1F /* Security_executables */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 186F778D14E59FDA00434E1F /* Build configuration list for PBXAggregateTarget "Security_executables" */; + buildPhases = ( + ); + dependencies = ( + 37A7CEDA197DBA8700926CE8 /* PBXTargetDependency */, + 722CF218175D602F00BCE0A5 /* PBXTargetDependency */, + 521470291697842500DF0DB3 /* PBXTargetDependency */, + 18F235FF15CA100300060520 /* PBXTargetDependency */, + 186F779114E5A00F00434E1F /* PBXTargetDependency */, + 0CCEBDBA16C303D8001BD7F6 /* PBXTargetDependency */, + 0CFC55E315DDB86500BEC89E /* PBXTargetDependency */, + C2432A2515C726B50096DB5B /* PBXTargetDependency */, + 4CB23B90169F59D8003A0131 /* PBXTargetDependency */, + EBB9FFE01682E71F00FF9774 /* PBXTargetDependency */, + 7AADF6E119C1062200292339 /* PBXTargetDependency */, + ); + name = Security_executables; + productName = Other; + }; + 4CE4729E16D833FD009070D1 /* Security_temporary_UI */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 4CE472C716D833FE009070D1 /* Build configuration list for PBXAggregateTarget "Security_temporary_UI" */; + buildPhases = ( + ); + dependencies = ( + 4C797BC916D83A3100C7B586 /* PBXTargetDependency */, + 4C797BF116D83A3800C7B586 /* PBXTargetDependency */, + ); + name = Security_temporary_UI; + productName = "Security_ temporary_UI"; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 0C03D62B17D93EED0087643B /* SecDH.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C03D60317D93E810087643B /* SecDH.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0C10987616CAAE8200803B8F /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1831329914EB2C6D00F0BCAC /* libASN1.a */; }; + 0C4EAE4C1766864F00773425 /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18752C1D16F2837A004E2799 /* libaks.a */; }; + 0C4EAE761766875E00773425 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFD14CF429600B05E7F /* IOKit.framework */; }; + 0C4EAE7717668DDF00773425 /* libsecdRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C4EAE721766865000773425 /* libsecdRegressions.a */; }; + 0C4F055E15C9E51A00F9DFD5 /* sslTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C4F055D15C9E51A00F9DFD5 /* sslTypes.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0C6C632A15D1989900BC68CD /* libsecurity_ssl_regressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C6D77CF15C8B66000BB4405 /* libsecurity_ssl_regressions.a */; }; + 0C6C633015D19FF500BC68CD /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; + 0C6D0065177B54CB0095D167 /* com.apple.securityd in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0C6D0064177B54C60095D167 /* com.apple.securityd */; }; + 0CAA7AB516C9A72A00A32C6D /* libsecurity_keychain_regressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CBD50B316C325F000713B6C /* libsecurity_keychain_regressions.a */; }; + 0CC3351C16C1ED8000399E53 /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18D4053B14CE2C1600A2BE4E /* libsecurity.a */; }; + 0CC3351E16C1ED8000399E53 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1831329A14EB2C6D00F0BCAC /* libDER.a */; }; + 0CC3351F16C1ED8000399E53 /* libSecItemShimOSX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 186CDD1E14CA11C700AF9171 /* libSecItemShimOSX.a */; }; + 0CC3352016C1ED8000399E53 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894015FFECF3008CE3E3 /* libutilities.a */; }; + 0CC3352316C1ED8000399E53 /* libSOSRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1288EC15FFE9D7008CE3E3 /* libSOSRegressions.a */; }; + 0CC3352416C1ED8000399E53 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; + 0CC3352616C1ED8000399E53 /* libsecipc_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270F6014CF655B00B05E7F /* libsecipc_client.a */; }; + 0CC3352716C1ED8000399E53 /* libSecureObjectSync.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1288EA15FFE9D7008CE3E3 /* libSecureObjectSync.a */; }; + 0CC3355A16C1EEE700399E53 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CC3355716C1EEE700399E53 /* main.c */; }; + 0CC3356316C1EFBE00399E53 /* libregressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CC3356016C1EF5D00399E53 /* libregressions.a */; }; + 0CCEBDB116C2CFC1001BD7F6 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C6C630E15D193C800BC68CD /* main.c */; }; + 0CCEBDB416C2D026001BD7F6 /* libregressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CC3356016C1EF5D00399E53 /* libregressions.a */; }; + 0CCEBDB616C2E431001BD7F6 /* libsecurityd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270C7D14CE573D00B05E7F /* libsecurityd.a */; }; + 0CCEBDB716C2E6B0001BD7F6 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFB14CF427800B05E7F /* CFNetwork.framework */; }; + 0CCEBDB816C2E6CE001BD7F6 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5AD146FEF43000BF1F3 /* libsqlite3.dylib */; }; + 0CCEBDBB16C30924001BD7F6 /* libutilitiesRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894215FFECF3008CE3E3 /* libutilitiesRegressions.a */; }; + 18270EE814CF294500B05E7F /* libsecurityd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270C7D14CE573D00B05E7F /* libsecurityd.a */; }; + 18270EF614CF334A00B05E7F /* server.c in Sources */ = {isa = PBXBuildFile; fileRef = 18270EF314CF333400B05E7F /* server.c */; }; + 18270EF814CF424900B05E7F /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; + 18270EF914CF425100B05E7F /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5B9146FF0BE000BF1F3 /* libbsm.dylib */; }; + 18270EFA14CF426200B05E7F /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5AD146FEF43000BF1F3 /* libsqlite3.dylib */; }; + 18270EFC14CF427800B05E7F /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFB14CF427800B05E7F /* CFNetwork.framework */; }; + 18270EFE14CF429600B05E7F /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFD14CF429600B05E7F /* IOKit.framework */; }; + 18270F6114CF656E00B05E7F /* libsecipc_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270F6014CF655B00B05E7F /* libsecipc_client.a */; }; + 182A191115D09AFF006AB103 /* connection.c in Sources */ = {isa = PBXBuildFile; fileRef = 182A191015D09AFF006AB103 /* connection.c */; }; + 182BB22A146F068B000BF1F3 /* iToolsTrustedApps.plist in Resources */ = {isa = PBXBuildFile; fileRef = 182BB229146F068B000BF1F3 /* iToolsTrustedApps.plist */; }; + 182BB3C5146F1DCB000BF1F3 /* sd_cspdl_common.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 182BB3C4146F1DCB000BF1F3 /* sd_cspdl_common.mdsinfo */; }; + 182BB41B146F2533000BF1F3 /* libsecurity_apple_csp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B5C6146DE6C8007E536C /* libsecurity_apple_csp.a */; }; + 182BB41C146F2533000BF1F3 /* libsecurity_apple_cspdl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B5D2146DE6CE007E536C /* libsecurity_apple_cspdl.a */; }; + 182BB41D146F2533000BF1F3 /* libsecurity_apple_file_dl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B5DE146DE6D7007E536C /* libsecurity_apple_file_dl.a */; }; + 182BB41E146F2533000BF1F3 /* libsecurity_apple_x509_cl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B5EB146DE6E8007E536C /* libsecurity_apple_x509_cl.a */; }; + 182BB41F146F2533000BF1F3 /* libsecurity_apple_x509_tp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B5F9146DE6FD007E536C /* libsecurity_apple_x509_tp.a */; }; + 182BB421146F2533000BF1F3 /* libsecurity_authorization.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B612146DE70A007E536C /* libsecurity_authorization.a */; }; + 182BB422146F2533000BF1F3 /* libsecurity_cdsa_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B61E146DE715007E536C /* libsecurity_cdsa_client.a */; }; + 182BB423146F2533000BF1F3 /* libsecurity_cdsa_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B55A146DE227007E536C /* libsecurity_cdsa_utilities.a */; }; + 182BB424146F2533000BF1F3 /* libsecurity_checkpw.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B644146DE748007E536C /* libsecurity_checkpw.a */; }; + 182BB425146F2533000BF1F3 /* libsecurity_cms.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B654146DE750007E536C /* libsecurity_cms.a */; }; + 182BB426146F2533000BF1F3 /* libsecurity_codesigning.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B666146DE757007E536C /* libsecurity_codesigning.a */; }; + 182BB428146F2533000BF1F3 /* libsecurity_cryptkit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B684146DE76F007E536C /* libsecurity_cryptkit.a */; }; + 182BB429146F2533000BF1F3 /* libsecurity_filedb.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B69D146DE797007E536C /* libsecurity_filedb.a */; }; + 182BB42A146F2533000BF1F3 /* libsecurity_keychain.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B6B3146DE7A0007E536C /* libsecurity_keychain.a */; }; + 182BB42B146F2533000BF1F3 /* libsecurity_ocspd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B6E9146DE7E8007E536C /* libsecurity_ocspd.a */; }; + 182BB42C146F2533000BF1F3 /* libsecurity_pkcs12.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B6F5146DE7EF007E536C /* libsecurity_pkcs12.a */; }; + 182BB42D146F2533000BF1F3 /* libsecurity_transform.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B739146DE845007E536C /* libsecurity_transform.a */; }; + 182BB42E146F2533000BF1F3 /* libsecurityd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 184461B1146E9D3300B12992 /* libsecurityd_client.a */; }; + 182BB4E1146F2591000BF1F3 /* libsecurity_manifest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B6D0146DE7D7007E536C /* libsecurity_manifest.a */; }; + 182BB4E2146F2591000BF1F3 /* libsecurity_mds.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B6DC146DE7E0007E536C /* libsecurity_mds.a */; }; + 182BB4E3146F2591000BF1F3 /* libsecurity_sd_cspdl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B701146DE7F7007E536C /* libsecurity_sd_cspdl.a */; }; + 182BB4E4146F2591000BF1F3 /* libsecurity_smime.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B71C146DE825007E536C /* libsecurity_smime.a */; }; + 182BB4E5146F2591000BF1F3 /* libsecurity_ssl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B728146DE839007E536C /* libsecurity_ssl.a */; }; + 182BB55F146F4544000BF1F3 /* FDEPrefs.plist in Resources */ = {isa = PBXBuildFile; fileRef = 182BB55C146F4544000BF1F3 /* FDEPrefs.plist */; }; + 182BB57F146F51A5000BF1F3 /* csparser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 182BB557146F4510000BF1F3 /* csparser.cpp */; }; + 182BB589146FE013000BF1F3 /* libsecurity_codesigning.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B666146DE757007E536C /* libsecurity_codesigning.a */; }; + 182BB590146FE125000BF1F3 /* libsecurity_cdsa_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B55A146DE227007E536C /* libsecurity_cdsa_utilities.a */; }; + 182BB591146FE12F000BF1F3 /* libsecurity_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B538146DDBE5007E536C /* libsecurity_utilities.a */; }; + 182BB592146FE1D7000BF1F3 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; + 182BB5AA146FEE50000BF1F3 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; + 182BB5AC146FEF15000BF1F3 /* libpam.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5AB146FEF14000BF1F3 /* libpam.dylib */; }; + 182BB5AE146FEF43000BF1F3 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5AD146FEF43000BF1F3 /* libsqlite3.dylib */; }; + 182BB5B2146FF039000BF1F3 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5B1146FF039000BF1F3 /* libz.dylib */; }; + 182BB5B4146FF04C000BF1F3 /* libxar.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5B3146FF04C000BF1F3 /* libxar.dylib */; }; + 182BB5B6146FF090000BF1F3 /* libauto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5B5146FF08F000BF1F3 /* libauto.dylib */; }; + 182BB5B8146FF0A2000BF1F3 /* libobjc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5B7146FF0A1000BF1F3 /* libobjc.dylib */; }; + 182BB5BA146FF0BF000BF1F3 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5B9146FF0BE000BF1F3 /* libbsm.dylib */; }; + 182BB5BB146FF62F000BF1F3 /* libsecurity_comcryption.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B676146DE75E007E536C /* libsecurity_comcryption.a */; }; + 1831329B14EB2C6D00F0BCAC /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1831329914EB2C6D00F0BCAC /* libASN1.a */; }; + 1831329C14EB2C6D00F0BCAC /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1831329A14EB2C6D00F0BCAC /* libDER.a */; }; + 18363C1417026084002D5C1C /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFD14CF429600B05E7F /* IOKit.framework */; }; + 1844605F146DE93E00B12992 /* csp_capabilities.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 1844605B146DE93E00B12992 /* csp_capabilities.mdsinfo */; }; + 18446060146DE93E00B12992 /* csp_capabilities_common.mds in Resources */ = {isa = PBXBuildFile; fileRef = 1844605C146DE93E00B12992 /* csp_capabilities_common.mds */; }; + 18446061146DE93E00B12992 /* csp_common.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 1844605D146DE93E00B12992 /* csp_common.mdsinfo */; }; + 18446062146DE93E00B12992 /* csp_primary.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 1844605E146DE93E00B12992 /* csp_primary.mdsinfo */; }; + 18446083146DF58B00B12992 /* libsecurity_cdsa_plugin.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B62B146DE720007E536C /* libsecurity_cdsa_plugin.a */; }; + 184460C7146E7B1E00B12992 /* cspdl_common.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 184460C3146E7B1E00B12992 /* cspdl_common.mdsinfo */; }; + 184460C8146E7B1E00B12992 /* cspdl_csp_capabilities.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 184460C4146E7B1E00B12992 /* cspdl_csp_capabilities.mdsinfo */; }; + 184460C9146E7B1E00B12992 /* cspdl_csp_primary.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 184460C5146E7B1E00B12992 /* cspdl_csp_primary.mdsinfo */; }; + 184460CA146E7B1E00B12992 /* cspdl_dl_primary.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 184460C6146E7B1E00B12992 /* cspdl_dl_primary.mdsinfo */; }; + 184460E3146E806700B12992 /* dl_common.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 184460E1146E806700B12992 /* dl_common.mdsinfo */; }; + 184460E4146E806700B12992 /* dl_primary.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 184460E2146E806700B12992 /* dl_primary.mdsinfo */; }; + 18446105146E82C800B12992 /* cl_common.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 18446103146E82C800B12992 /* cl_common.mdsinfo */; }; + 18446106146E82C800B12992 /* cl_primary.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 18446104146E82C800B12992 /* cl_primary.mdsinfo */; }; + 18446115146E85A300B12992 /* tp_common.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 18446112146E85A300B12992 /* tp_common.mdsinfo */; }; + 18446116146E85A300B12992 /* tp_policyOids.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 18446113146E85A300B12992 /* tp_policyOids.mdsinfo */; }; + 18446117146E85A300B12992 /* tp_primary.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 18446114146E85A300B12992 /* tp_primary.mdsinfo */; }; + 18500F9B14708D0E006F9AB4 /* SecDebugErrorMessages.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18500F9A14708D0E006F9AB4 /* SecDebugErrorMessages.strings */; }; + 18500FA114708F19006F9AB4 /* SecErrorMessages.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18500F9F14708F19006F9AB4 /* SecErrorMessages.strings */; }; + 1879B4AA146DCA18007E536C /* cssm.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 1879B4A9146DCA18007E536C /* cssm.mdsinfo */; }; + 1879B546146DE192007E536C /* libsecurity_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B538146DDBE5007E536C /* libsecurity_utilities.a */; }; + 1879B570146DE2E6007E536C /* libsecurity_cdsa_utils.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B54F146DE212007E536C /* libsecurity_cdsa_utils.a */; }; + 1879B571146DE2FF007E536C /* libsecurity_cssm.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B565146DE244007E536C /* libsecurity_cssm.a */; }; + 187A05B1170393FF0038C158 /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18752C1D16F2837A004E2799 /* libaks.a */; }; + 187D6B9315D435BD00E27494 /* authorization.buttons.strings in Resources */ = {isa = PBXBuildFile; fileRef = 187D6B8F15D4359F00E27494 /* authorization.buttons.strings */; }; + 187D6B9415D435C700E27494 /* authorization.prompts.strings in Resources */ = {isa = PBXBuildFile; fileRef = 187D6B9115D4359F00E27494 /* authorization.prompts.strings */; }; + 187D6B9715D438AD00E27494 /* authorization.plist in Copy authorization.plist */ = {isa = PBXBuildFile; fileRef = 187D6B9515D436BF00E27494 /* authorization.plist */; }; + 187D6B9815D4476D00E27494 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFD14CF429600B05E7F /* IOKit.framework */; }; + 1885B45214D9AB8100519375 /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1885B3F914D8D9B100519375 /* libASN1.a */; }; + 188AD8DC1471FE3E0081C619 /* FDELocalizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 188AD8D81471FE3D0081C619 /* FDELocalizable.strings */; }; + 188AD8DD1471FE3E0081C619 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 188AD8DA1471FE3D0081C619 /* InfoPlist.strings */; }; + 189757871700CF4C00672567 /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18752C1D16F2837A004E2799 /* libaks.a */; }; + 18A5493315EFD3690059E6DC /* dummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18A5493115EFD2F40059E6DC /* dummy.cpp */; }; + 18AD56A414CDE7BE008233F2 /* libSecItemShimOSX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 186CDD1E14CA11C700AF9171 /* libSecItemShimOSX.a */; }; + 18B647EC14D9F20500F538BF /* oidsalg.h in Headers */ = {isa = PBXBuildFile; fileRef = 18B647E814D9EB6300F538BF /* oidsalg.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18B647ED14D9F20F00F538BF /* oidsattr.h in Headers */ = {isa = PBXBuildFile; fileRef = 18B647EA14D9EE4300F538BF /* oidsattr.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18BBC7361471F5A300F2B224 /* SecExternalSourceTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 18BBC7351471F5A300F2B224 /* SecExternalSourceTransform.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18BEB19A14CF7F8100C8BD36 /* com.apple.secd.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 18BEB19614CF74C100C8BD36 /* com.apple.secd.plist */; }; + 18CD682717272EBC005345FB /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18752C1D16F2837A004E2799 /* libaks.a */; }; + 18CD684E17272EE2005345FB /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFD14CF429600B05E7F /* IOKit.framework */; }; + 18CFEE8915DEE2C600E3F2A3 /* com.apple.authd.sb in Copy sandbox profile */ = {isa = PBXBuildFile; fileRef = 18CFEE8715DEE25200E3F2A3 /* com.apple.authd.sb */; }; + 18D6803B16B768F700DF6D2E /* com.apple.authd in Copy asl module */ = {isa = PBXBuildFile; fileRef = 18D6803916B768D500DF6D2E /* com.apple.authd */; }; + 18F2352115C9FA3C00060520 /* agent.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F234F915C9FA3B00060520 /* agent.c */; }; + 18F2352215C9FA3C00060520 /* authdb.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F234FB15C9FA3B00060520 /* authdb.c */; }; + 18F2352315C9FA3C00060520 /* authitems.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F234FD15C9FA3B00060520 /* authitems.c */; }; + 18F2352415C9FA3C00060520 /* authtoken.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F234FF15C9FA3B00060520 /* authtoken.c */; }; + 18F2352515C9FA3C00060520 /* authutilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2350215C9FA3B00060520 /* authutilities.c */; }; + 18F2352615C9FA3C00060520 /* ccaudit.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2350415C9FA3B00060520 /* ccaudit.c */; }; + 18F2352715C9FA3C00060520 /* crc.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2350615C9FA3B00060520 /* crc.c */; }; + 18F2352815C9FA3C00060520 /* credential.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2350815C9FA3B00060520 /* credential.c */; }; + 18F2352915C9FA3C00060520 /* debugging.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2350A15C9FA3B00060520 /* debugging.c */; }; + 18F2352B15C9FA3C00060520 /* engine.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2350F15C9FA3B00060520 /* engine.c */; }; + 18F2352C15C9FA3C00060520 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2351115C9FA3B00060520 /* main.c */; }; + 18F2352D15C9FA3C00060520 /* mechanism.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2351215C9FA3B00060520 /* mechanism.c */; }; + 18F2352E15C9FA3C00060520 /* object.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2351415C9FA3C00060520 /* object.c */; }; + 18F2352F15C9FA3C00060520 /* process.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2351615C9FA3C00060520 /* process.c */; }; + 18F2353015C9FA3C00060520 /* rule.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2351815C9FA3C00060520 /* rule.c */; }; + 18F2353215C9FA3C00060520 /* server.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2351D15C9FA3C00060520 /* server.c */; }; + 18F2353315C9FA3C00060520 /* session.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F2351F15C9FA3C00060520 /* session.c */; }; + 18F2353515C9FDB700060520 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; + 18F2353615C9FDD200060520 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF42BB515A3947F00ACACE1 /* Security.framework */; }; + 18F2353715C9FDE400060520 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5B9146FF0BE000BF1F3 /* libbsm.dylib */; }; + 18F2353815C9FDEF00060520 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5AD146FEF43000BF1F3 /* libsqlite3.dylib */; }; + 18F2360115CAF41200060520 /* libsecurity_codesigning.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F2360015CAF41100060520 /* libsecurity_codesigning.a */; }; + 18FE68021471A42900A2CBE3 /* SecDigestTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3A3146F1BEC000BF1F3 /* SecDigestTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68031471A42900A2CBE3 /* SecReadTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3A4146F1BEC000BF1F3 /* SecReadTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68041471A42900A2CBE3 /* SecTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3A5146F1BEC000BF1F3 /* SecTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68051471A42900A2CBE3 /* SecCustomTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3A6146F1BEC000BF1F3 /* SecCustomTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68061471A42900A2CBE3 /* SecDecodeTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3A7146F1BEC000BF1F3 /* SecDecodeTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68071471A42900A2CBE3 /* SecEncodeTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3A8146F1BEC000BF1F3 /* SecEncodeTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68081471A42900A2CBE3 /* SecEncryptTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3A9146F1BEC000BF1F3 /* SecEncryptTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68091471A42900A2CBE3 /* SecSignVerifyTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3AA146F1BEC000BF1F3 /* SecSignVerifyTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE680A1471A42900A2CBE3 /* SecTransformReadTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3AB146F1BEC000BF1F3 /* SecTransformReadTransform.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE680B1471A42900A2CBE3 /* CipherSuite.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB36E146F13B4000BF1F3 /* CipherSuite.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE680C1471A42900A2CBE3 /* SecureTransport.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB36F146F13B4000BF1F3 /* SecureTransport.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE680D1471A42900A2CBE3 /* mds.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB356146F1198000BF1F3 /* mds.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE680E1471A42900A2CBE3 /* mds_schema.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB357146F1198000BF1F3 /* mds_schema.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE680F1471A42900A2CBE3 /* SecureDownload.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB315146F0E7E000BF1F3 /* SecureDownload.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68101471A42900A2CBE3 /* SecAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB187146EAD4C000BF1F3 /* SecAccess.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68111471A42900A2CBE3 /* SecACL.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB188146EAD4C000BF1F3 /* SecACL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68121471A42900A2CBE3 /* SecBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB189146EAD4C000BF1F3 /* SecBase.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68131471A42900A2CBE3 /* SecCertificate.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB18A146EAD4C000BF1F3 /* SecCertificate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68141471A42900A2CBE3 /* SecIdentity.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB18B146EAD4C000BF1F3 /* SecIdentity.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68151471A42900A2CBE3 /* SecIdentitySearch.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB18C146EAD4C000BF1F3 /* SecIdentitySearch.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68161471A42900A2CBE3 /* SecItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB18D146EAD4C000BF1F3 /* SecItem.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68171471A42900A2CBE3 /* SecKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB18E146EAD4C000BF1F3 /* SecKey.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68181471A42900A2CBE3 /* SecKeychain.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB18F146EAD4C000BF1F3 /* SecKeychain.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68191471A42900A2CBE3 /* SecKeychainItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB190146EAD4C000BF1F3 /* SecKeychainItem.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE681A1471A42900A2CBE3 /* SecKeychainSearch.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB191146EAD4C000BF1F3 /* SecKeychainSearch.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE681B1471A42900A2CBE3 /* SecPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB192146EAD4C000BF1F3 /* SecPolicy.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE681C1471A42900A2CBE3 /* SecPolicySearch.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB193146EAD4C000BF1F3 /* SecPolicySearch.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE681D1471A42900A2CBE3 /* SecTrust.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB194146EAD4C000BF1F3 /* SecTrust.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE681E1471A42900A2CBE3 /* SecTrustedApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB195146EAD4C000BF1F3 /* SecTrustedApplication.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE681F1471A42900A2CBE3 /* Security.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB196146EAD4C000BF1F3 /* Security.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68201471A42900A2CBE3 /* SecImportExport.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB197146EAD4C000BF1F3 /* SecImportExport.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68211471A42900A2CBE3 /* SecTrustSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB198146EAD4C000BF1F3 /* SecTrustSettings.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68221471A42900A2CBE3 /* SecCertificateOIDs.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB199146EAD4C000BF1F3 /* SecCertificateOIDs.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68231471A42900A2CBE3 /* SecRandom.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB19A146EAD4C000BF1F3 /* SecRandom.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68241471A42900A2CBE3 /* SecTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844617E146E9A8500B12992 /* SecTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68251471A42900A2CBE3 /* CodeSigning.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844617F146E9A8500B12992 /* CodeSigning.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68261471A42900A2CBE3 /* CSCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446180146E9A8500B12992 /* CSCommon.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68271471A42900A2CBE3 /* SecCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446181146E9A8500B12992 /* SecCode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68281471A42900A2CBE3 /* SecStaticCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446182146E9A8500B12992 /* SecStaticCode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68291471A42900A2CBE3 /* SecRequirement.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446183146E9A8500B12992 /* SecRequirement.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE682A1471A42900A2CBE3 /* SecCodeHost.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446184146E9A8500B12992 /* SecCodeHost.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE682B1471A42900A2CBE3 /* CMSDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446170146E982800B12992 /* CMSDecoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE682C1471A42900A2CBE3 /* CMSEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446171146E982800B12992 /* CMSEncoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE682D1471A42900A2CBE3 /* AuthorizationTags.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446144146E923200B12992 /* AuthorizationTags.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE682E1471A42900A2CBE3 /* AuthSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446145146E923200B12992 /* AuthSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE682F1471A42900A2CBE3 /* Authorization.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446146146E923200B12992 /* Authorization.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68301471A42900A2CBE3 /* AuthorizationDB.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446147146E923200B12992 /* AuthorizationDB.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68311471A42900A2CBE3 /* AuthorizationPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446148146E923200B12992 /* AuthorizationPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68321471A42900A2CBE3 /* SecAsn1Coder.h in Headers */ = {isa = PBXBuildFile; fileRef = 184460AB146DFCC100B12992 /* SecAsn1Coder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68331471A42900A2CBE3 /* SecAsn1Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 184460AC146DFCC100B12992 /* SecAsn1Templates.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68341471A42900A2CBE3 /* SecAsn1Types.h in Headers */ = {isa = PBXBuildFile; fileRef = 184460AD146DFCC100B12992 /* SecAsn1Types.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68351471A42900A2CBE3 /* certextensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4AD146DCA84007E536C /* certextensions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68361471A42900A2CBE3 /* cssm.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4AE146DCA84007E536C /* cssm.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68371471A42900A2CBE3 /* cssmaci.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4AF146DCA84007E536C /* cssmaci.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68381471A42900A2CBE3 /* cssmapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4B0146DCA84007E536C /* cssmapi.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68391471A42900A2CBE3 /* cssmapple.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4B1146DCA84007E536C /* cssmapple.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE683A1471A42900A2CBE3 /* cssmcli.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4B2146DCA84007E536C /* cssmcli.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE683B1471A42900A2CBE3 /* cssmconfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4B3146DCA84007E536C /* cssmconfig.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE683C1471A42900A2CBE3 /* cssmcspi.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4B4146DCA84007E536C /* cssmcspi.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE683D1471A42900A2CBE3 /* cssmdli.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4B5146DCA84007E536C /* cssmdli.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE683E1471A42900A2CBE3 /* cssmerr.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4B6146DCA84007E536C /* cssmerr.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE683F1471A42900A2CBE3 /* cssmkrapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4B7146DCA84007E536C /* cssmkrapi.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68401471A42900A2CBE3 /* cssmkrspi.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4B8146DCA84007E536C /* cssmkrspi.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68411471A42900A2CBE3 /* cssmspi.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4B9146DCA84007E536C /* cssmspi.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68421471A42900A2CBE3 /* cssmtpi.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4BA146DCA84007E536C /* cssmtpi.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68431471A42900A2CBE3 /* cssmtype.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4BB146DCA84007E536C /* cssmtype.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68441471A42900A2CBE3 /* eisl.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4BC146DCA84007E536C /* eisl.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68451471A42900A2CBE3 /* emmspi.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4BD146DCA84007E536C /* emmspi.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68461471A42900A2CBE3 /* emmtype.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4BE146DCA84007E536C /* emmtype.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE68491471A42900A2CBE3 /* oidsbase.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4C1146DCA84007E536C /* oidsbase.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE684A1471A42900A2CBE3 /* oidscert.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4C2146DCA84007E536C /* oidscert.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE684B1471A42900A2CBE3 /* oidscrl.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4C3146DCA84007E536C /* oidscrl.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE684C1471A42900A2CBE3 /* x509defs.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4C4146DCA84007E536C /* x509defs.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18FE684D1471A46600A2CBE3 /* asn1Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 184460A1146DFCB700B12992 /* asn1Templates.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE684E1471A46600A2CBE3 /* AuthorizationPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844614F146E923B00B12992 /* AuthorizationPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE684F1471A46600A2CBE3 /* AuthorizationTagsPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844614E146E923B00B12992 /* AuthorizationTagsPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68501471A46600A2CBE3 /* certExtensionTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844609A146DFCB700B12992 /* certExtensionTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68511471A46600A2CBE3 /* checkpw.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446168146E95D700B12992 /* checkpw.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68521471A46600A2CBE3 /* CMSPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446174146E982D00B12992 /* CMSPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68531471A46600A2CBE3 /* CSCommonPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844618C146E9A8F00B12992 /* CSCommonPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68541471A46600A2CBE3 /* csrTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844609B146DFCB700B12992 /* csrTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68551471A46600A2CBE3 /* cssmapplePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 1879B4AB146DCA4A007E536C /* cssmapplePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68561471A46600A2CBE3 /* keyTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 184460A0146DFCB700B12992 /* keyTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68571471A46600A2CBE3 /* mdspriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB35A146F11A1000BF1F3 /* mdspriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68581471A46600A2CBE3 /* nameTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844609D146DFCB700B12992 /* nameTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68591471A46600A2CBE3 /* ocspTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844609C146DFCB700B12992 /* ocspTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE685A1471A46600A2CBE3 /* osKeyTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844609F146DFCB700B12992 /* osKeyTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE685B1471A46600A2CBE3 /* SecAccessPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1B2146EAD5D000BF1F3 /* SecAccessPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE685C1471A46600A2CBE3 /* secasn1t.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446099146DFCB700B12992 /* secasn1t.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE685D1471A46600A2CBE3 /* SecAssessment.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446194146E9A8F00B12992 /* SecAssessment.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE685E1471A46600A2CBE3 /* SecBasePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1B3146EAD5D000BF1F3 /* SecBasePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE685F1471A46600A2CBE3 /* SecCertificateBundle.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1B4146EAD5D000BF1F3 /* SecCertificateBundle.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68611471A46600A2CBE3 /* SecCertificatePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1B5146EAD5D000BF1F3 /* SecCertificatePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68621471A46600A2CBE3 /* SecCertificateRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1B6146EAD5D000BF1F3 /* SecCertificateRequest.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68631471A46600A2CBE3 /* SecCmsBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB383146F14D2000BF1F3 /* SecCmsBase.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68641471A46600A2CBE3 /* SecCmsContentInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB384146F14D2000BF1F3 /* SecCmsContentInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68651471A46600A2CBE3 /* SecCmsDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB385146F14D2000BF1F3 /* SecCmsDecoder.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68661471A46600A2CBE3 /* SecCmsDigestContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB386146F14D2000BF1F3 /* SecCmsDigestContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68671471A46600A2CBE3 /* SecCmsDigestedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB387146F14D2000BF1F3 /* SecCmsDigestedData.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68681471A46600A2CBE3 /* SecCmsEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB388146F14D2000BF1F3 /* SecCmsEncoder.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68691471A46600A2CBE3 /* SecCmsEncryptedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB389146F14D2000BF1F3 /* SecCmsEncryptedData.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE686A1471A46600A2CBE3 /* SecCmsEnvelopedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB38A146F14D2000BF1F3 /* SecCmsEnvelopedData.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE686B1471A46600A2CBE3 /* SecCmsMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB38B146F14D2000BF1F3 /* SecCmsMessage.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE686C1471A46600A2CBE3 /* SecCmsRecipientInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB38C146F14D2000BF1F3 /* SecCmsRecipientInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE686D1471A46600A2CBE3 /* SecCmsSignedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB38D146F14D2000BF1F3 /* SecCmsSignedData.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE686E1471A46600A2CBE3 /* SecCmsSignerInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB38E146F14D2000BF1F3 /* SecCmsSignerInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE686F1471A46600A2CBE3 /* SecCodeHostLib.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446193146E9A8F00B12992 /* SecCodeHostLib.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68701471A46600A2CBE3 /* SecCodePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844618D146E9A8F00B12992 /* SecCodePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68711471A46600A2CBE3 /* SecCodeSigner.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446190146E9A8F00B12992 /* SecCodeSigner.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68721471A46600A2CBE3 /* SecFDERecoveryAsymmetricCrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1AF146EAD5D000BF1F3 /* SecFDERecoveryAsymmetricCrypto.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68731471A46600A2CBE3 /* SecIdentityPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1B7146EAD5D000BF1F3 /* SecIdentityPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68741471A46600A2CBE3 /* SecIdentitySearchPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1C4146EAD5D000BF1F3 /* SecIdentitySearchPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68751471A46600A2CBE3 /* SecIntegrity.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446191146E9A8F00B12992 /* SecIntegrity.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68761471A46600A2CBE3 /* SecIntegrityLib.h in Headers */ = {isa = PBXBuildFile; fileRef = 18446192146E9A8F00B12992 /* SecIntegrityLib.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68771471A46600A2CBE3 /* SecItemPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1CA146EAD5D000BF1F3 /* SecItemPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68781471A46600A2CBE3 /* SecKeychainItemExtendedAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1CB146EAD5D000BF1F3 /* SecKeychainItemExtendedAttributes.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68791471A46600A2CBE3 /* SecKeychainItemPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1B8146EAD5D000BF1F3 /* SecKeychainItemPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE687A1471A46600A2CBE3 /* SecKeychainPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1B9146EAD5D000BF1F3 /* SecKeychainPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE687B1471A46700A2CBE3 /* SecKeychainSearchPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1C5146EAD5D000BF1F3 /* SecKeychainSearchPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE687C1471A46700A2CBE3 /* SecKeyPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1BA146EAD5D000BF1F3 /* SecKeyPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE687D1471A46700A2CBE3 /* SecManifest.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB317146F0E94000BF1F3 /* SecManifest.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE687E1471A46700A2CBE3 /* SecNullTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3B6146F1BF9000BF1F3 /* SecNullTransform.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE687F1471A46700A2CBE3 /* SecPassword.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1B0146EAD5D000BF1F3 /* SecPassword.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68801471A46700A2CBE3 /* SecPolicyPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1BB146EAD5D000BF1F3 /* SecPolicyPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68811471A46700A2CBE3 /* SecRandomP.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1CF146EAD5D000BF1F3 /* SecRandomP.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68821471A46700A2CBE3 /* SecRecoveryPassword.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1CE146EAD5D000BF1F3 /* SecRecoveryPassword.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68831471A46700A2CBE3 /* SecRequirementPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844618F146E9A8F00B12992 /* SecRequirementPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68841471A46700A2CBE3 /* SecSMIME.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB38F146F14D2000BF1F3 /* SecSMIME.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68851471A46700A2CBE3 /* SecStaticCodePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844618E146E9A8F00B12992 /* SecStaticCodePriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68861471A46700A2CBE3 /* SecTransformInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB3B7146F1BF9000BF1F3 /* SecTransformInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68871471A46700A2CBE3 /* SecTrustedApplicationPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1BC146EAD5D000BF1F3 /* SecTrustedApplicationPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68881471A46700A2CBE3 /* SecTrustPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1BD146EAD5D000BF1F3 /* SecTrustPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE68891471A46700A2CBE3 /* SecTrustSettingsPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1C6146EAD5D000BF1F3 /* SecTrustSettingsPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE688A1471A46700A2CBE3 /* SecureDownloadInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB318146F0E94000BF1F3 /* SecureDownloadInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE688B1471A46700A2CBE3 /* SecureTransportPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB372146F13BB000BF1F3 /* SecureTransportPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE688C1471A46700A2CBE3 /* TrustSettingsSchema.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1C8146EAD5D000BF1F3 /* TrustSettingsSchema.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18FE688D1471A46700A2CBE3 /* X509Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844609E146DFCB700B12992 /* X509Templates.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 37A7CEAE197DB8FA00926CE8 /* FatDynamicValidation.c in Sources */ = {isa = PBXBuildFile; fileRef = 37A7CEAD197DB8FA00926CE8 /* FatDynamicValidation.c */; }; + 37A7CEDD197DCEE500926CE8 /* validation.sh in CopyFiles */ = {isa = PBXBuildFile; fileRef = 37A7CEDB197DCDD700926CE8 /* validation.sh */; }; + 395E7CEE16C64EA500CD82A4 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 395E7CED16C64EA500CD82A4 /* SystemConfiguration.framework */; }; + 39BFB04516D304DE0022564B /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 395E7CED16C64EA500CD82A4 /* SystemConfiguration.framework */; }; + 44B2606818F81A7D008DF20F /* SecAccessControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 44B2603E18F81A6A008DF20F /* SecAccessControl.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 44B2606A18F81C0F008DF20F /* SecAccessControlPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 44B2606918F81BFE008DF20F /* SecAccessControlPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4A5C1790161A9DFB00ABF784 /* authd_private.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 18F2351A15C9FA3C00060520 /* authd_private.h */; }; + 4C01DF14164C3E7C006798CD /* libSecureObjectSync.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1288EA15FFE9D7008CE3E3 /* libSecureObjectSync.a */; }; + 4C0F6F871985877800178101 /* SecEntitlements.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0F6F861985877800178101 /* SecEntitlements.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4C2505B716D2DF9F002CE025 /* Icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 4C2505B616D2DF9F002CE025 /* Icon.icns */; }; + 4C328D301778EC4F0015EED1 /* AOSUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C328D2F1778EC4F0015EED1 /* AOSUI.framework */; }; + 4C49390D16E51ACE00CE110C /* com.apple.security.keychain-circle-notification.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4C49390C16E51ACE00CE110C /* com.apple.security.keychain-circle-notification.plist */; }; + 4C49390F16E51FC700CE110C /* com.apple.security.keychain-circle-notification.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C49390C16E51ACE00CE110C /* com.apple.security.keychain-circle-notification.plist */; }; + 4C5DD46A17A5E5D000696A79 /* KNPersistantState.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C5DD44317A5E31900696A79 /* KNPersistantState.m */; }; + 4C5DD46C17A5F67300696A79 /* AppleSystemInfo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C5DD46B17A5F67300696A79 /* AppleSystemInfo.framework */; }; + 4C7D453D17BEE69B00DDD88F /* NSString+compactDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C7D453C17BEE69B00DDD88F /* NSString+compactDescription.m */; }; + 4C7D456817BEED0400DDD88F /* NSDictionary+compactDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C7D456517BEE6B700DDD88F /* NSDictionary+compactDescription.m */; }; + 4C7D456917BEED1400DDD88F /* NSSet+compactDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C7D456717BEE6B700DDD88F /* NSSet+compactDescription.m */; }; + 4C7D8765160A74C400D041E3 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894015FFECF3008CE3E3 /* libutilities.a */; }; + 4C85DEDA16DBD5BF00ED8D47 /* KDCirclePeer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C85DED916DBD5BF00ED8D47 /* KDCirclePeer.m */; }; + 4C85DEDB16DBD5BF00ED8D47 /* KDCirclePeer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C85DED916DBD5BF00ED8D47 /* KDCirclePeer.m */; }; + 4C8D8651177A752D0019A804 /* libsecipc_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270F6014CF655B00B05E7F /* libsecipc_client.a */; }; + 4C96F76016D5462F00D3B39D /* KDSecCircle.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C96F73916D5372C00D3B39D /* KDSecCircle.m */; }; + 4C96F76216D54C9600D3B39D /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C96F76116D54C9600D3B39D /* CoreFoundation.framework */; }; + 4C96F7C216D6DF8400D3B39D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5214700716977CB800DF0DB3 /* Cocoa.framework */; }; + 4C96F7C816D6DF8400D3B39D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4C96F7C616D6DF8400D3B39D /* InfoPlist.strings */; }; + 4C96F7CA16D6DF8400D3B39D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C96F7C916D6DF8400D3B39D /* main.m */; }; + 4C96F7CE16D6DF8400D3B39D /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 4C96F7CC16D6DF8400D3B39D /* Credits.rtf */; }; + 4C96F7D116D6DF8400D3B39D /* KNAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C96F7D016D6DF8400D3B39D /* KNAppDelegate.m */; }; + 4C96F7D416D6DF8400D3B39D /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C96F7D216D6DF8400D3B39D /* MainMenu.xib */; }; + 4C97761E17BEB23E0002BFE4 /* AOSAccounts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C97761D17BEB23E0002BFE4 /* AOSAccounts.framework */; }; + 4CAEACCC16D6FBF600263776 /* KDSecCircle.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C96F73916D5372C00D3B39D /* KDSecCircle.m */; }; + 4CAEACCD16D6FC7600263776 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF42BB515A3947F00ACACE1 /* Security.framework */; }; + 4CB23B47169F5873003A0131 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; + 4CB23B4C169F5873003A0131 /* security2.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB23B4B169F5873003A0131 /* security2.1 */; }; + 4CB23B81169F58DE003A0131 /* security_tool_commands.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CB23B80169F58DE003A0131 /* security_tool_commands.c */; }; + 4CB23B89169F5990003A0131 /* libSecurityTool.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB23B76169F5873003A0131 /* libSecurityTool.a */; }; + 4CB23B8A169F599A003A0131 /* libSecurityCommands.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB23B78169F5873003A0131 /* libSecurityCommands.a */; }; + 4CB23B8B169F599A003A0131 /* libSOSCommands.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CB23B7A169F5873003A0131 /* libSOSCommands.a */; }; + 4CB23B8C169F59AD003A0131 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894015FFECF3008CE3E3 /* libutilities.a */; }; + 4CB86AF0167A6FF300F46643 /* SOSCircle.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB86AE6167A6FF200F46643 /* SOSCircle.h */; }; + 4CB86AF1167A6FF300F46643 /* SOSCloudCircle.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB86AE7167A6FF200F46643 /* SOSCloudCircle.h */; }; + 4CB86AF2167A6FF300F46643 /* SOSCloudCircleInternal.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB86AE8167A6FF200F46643 /* SOSCloudCircleInternal.h */; }; + 4CB86AF3167A6FF300F46643 /* SOSEngine.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB86AE9167A6FF200F46643 /* SOSEngine.h */; }; + 4CB86AF4167A6FF300F46643 /* SOSFullPeerInfo.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB86AEA167A6FF300F46643 /* SOSFullPeerInfo.h */; }; + 4CB86AF5167A6FF300F46643 /* SOSInternal.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB86AEB167A6FF300F46643 /* SOSInternal.h */; }; + 4CB86AF6167A6FF300F46643 /* SOSPeer.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB86AEC167A6FF300F46643 /* SOSPeer.h */; }; + 4CB86AF7167A6FF300F46643 /* SOSPeerInfo.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB86AED167A6FF300F46643 /* SOSPeerInfo.h */; }; + 4CB86AF8167A6FF300F46643 /* SOSTransport.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB86AEE167A6FF300F46643 /* SOSTransport.h */; }; + 4CB86AFB167A8F2200F46643 /* SOSAccount.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CB86AFA167A8F2200F46643 /* SOSAccount.h */; }; + 4CC7A7B416CC2A85003E10C1 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5214700716977CB800DF0DB3 /* Cocoa.framework */; }; + 4CC7A7BA16CC2A85003E10C1 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4CC7A7B816CC2A85003E10C1 /* InfoPlist.strings */; }; + 4CC7A7BC16CC2A85003E10C1 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7A7BB16CC2A85003E10C1 /* main.m */; }; + 4CC7A7C016CC2A85003E10C1 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 4CC7A7BE16CC2A85003E10C1 /* Credits.rtf */; }; + 4CC7A7C316CC2A85003E10C1 /* KDAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7A7C216CC2A85003E10C1 /* KDAppDelegate.m */; }; + 4CC7A7C616CC2A85003E10C1 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4CC7A7C416CC2A85003E10C1 /* MainMenu.xib */; }; + 4CC7A7F316CC2B0A003E10C1 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CC7A7F216CC2B0A003E10C1 /* Security.framework */; }; + 4CC7A7F616CD99E2003E10C1 /* KDSecItems.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7A7F516CD95D3003E10C1 /* KDSecItems.m */; }; + 4CC8DEA416DC1AC800462517 /* libSecOtrOSX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1288F215FFE9D7008CE3E3 /* libSecOtrOSX.a */; }; + 4CD1980D16DD3BDF00A9E8FD /* NSArray+mapWithBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CD1980C16DD3BDF00A9E8FD /* NSArray+mapWithBlock.m */; }; + 4CD1980E16DD3BDF00A9E8FD /* NSArray+mapWithBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CD1980C16DD3BDF00A9E8FD /* NSArray+mapWithBlock.m */; }; + 5208BF4F16A0993C0062DDC5 /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18D4053B14CE2C1600A2BE4E /* libsecurity.a */; }; + 5208C0D716A0C96F0062DDC5 /* libSecureObjectSync.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1288EA15FFE9D7008CE3E3 /* libSecureObjectSync.a */; }; + 52146FDB1697673900DF0DB3 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894015FFECF3008CE3E3 /* libutilities.a */; }; + 5214701216977CB800DF0DB3 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5214701016977CB800DF0DB3 /* InfoPlist.strings */; }; + 5214701D16977D9500DF0DB3 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894015FFECF3008CE3E3 /* libutilities.a */; }; + 5214701E16977DA700DF0DB3 /* libCloudKeychainProxy.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C01DE32164C3793006798CD /* libCloudKeychainProxy.a */; }; + 5214702216977E7D00DF0DB3 /* CloudKeychainProxy-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5214700F16977CB800DF0DB3 /* CloudKeychainProxy-Info.plist */; }; + 521470261697800500DF0DB3 /* com.apple.security.cloudkeychainproxy.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5214702516977FEC00DF0DB3 /* com.apple.security.cloudkeychainproxy.plist */; }; + 5214702A1697855800DF0DB3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5214700C16977CB800DF0DB3 /* Foundation.framework */; }; + 5241C60D16DC1BA100DB5C6F /* libSecOtrOSX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1288F215FFE9D7008CE3E3 /* libSecOtrOSX.a */; }; + 52669053169D181900ED8231 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF42BB515A3947F00ACACE1 /* Security.framework */; }; + 529E948C169E29450000AC9B /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18FE67EA1471A3AA00A2CBE3 /* Security.framework */; }; + 529E948D169E29470000AC9B /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18FE67EA1471A3AA00A2CBE3 /* Security.framework */; }; + 52AEA489153C778C005AFC59 /* tsaSupportPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 52AEA484153C7581005AFC59 /* tsaSupportPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 52B006C015238F76005D4556 /* TimeStampingPrefs.plist in Resources */ = {isa = PBXBuildFile; fileRef = 52B006BF15238F76005D4556 /* TimeStampingPrefs.plist */; }; + 52B5A9C21519330300664F11 /* tsaSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B5A9C01519330300664F11 /* tsaSupport.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 52B5A9C31519330300664F11 /* tsaTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B5A9C11519330300664F11 /* tsaTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 52C3D236169B56860091D9D3 /* ckdmain.m in Sources */ = {isa = PBXBuildFile; fileRef = 52C3D235169B56860091D9D3 /* ckdmain.m */; }; + 52CD052316A0E24900218387 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF42BB515A3947F00ACACE1 /* Security.framework */; }; + 532847791785076B009118DC /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5328475117850741009118DC /* Localizable.strings */; }; + 5E27BBFB18F4103100B6C79A /* libcoreauthd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E27BBFA18F4103100B6C79A /* libcoreauthd_client.a */; }; + 5E3A07071962B0B000463F09 /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E3A07061962B0B000463F09 /* libaks_acl.a */; }; + 5E48A8EA1907893C0011BC31 /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E48A8E91907893C0011BC31 /* libaks_acl.a */; }; + 5E59414418F43964005153AD /* libcoreauthd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E27BBFA18F4103100B6C79A /* libcoreauthd_client.a */; }; + 5E8ADED2190A2E380012271C /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E8ADED1190A2E380012271C /* libaks_acl.a */; }; + 5EC2284D190A437D00DB2DF2 /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E8ADED1190A2E380012271C /* libaks_acl.a */; }; + 72756C31175D48C100F52070 /* cloud_keychain_diagnose.c in Sources */ = {isa = PBXBuildFile; fileRef = 72756C30175D48C100F52070 /* cloud_keychain_diagnose.c */; }; + 72CC327B175D6E0A00217455 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72756C9E175D566800F52070 /* CoreFoundation.framework */; }; + 72CC327C175D6E1800217455 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 722CF215175D5E5000BCE0A5 /* Security.framework */; }; + AAF3DCCB1666D03300376593 /* libsecurity_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F235F715CA0D9D00060520 /* libsecurity_utilities.a */; }; + AC5688BC18B4396D00F0526C /* SecCMS.h in Headers */ = {isa = PBXBuildFile; fileRef = AC5688BA18B4396D00F0526C /* SecCMS.h */; settings = {ATTRIBUTES = (Private, ); }; }; + ACB6171918B5231800EBEDD7 /* libsecurity_smime_regressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ACB6171818B5231800EBEDD7 /* libsecurity_smime_regressions.a */; }; + BE8C5F0A16F7CE450074CF86 /* framework.sb in Resources */ = {isa = PBXBuildFile; fileRef = BE8C5F0916F7CE450074CF86 /* framework.sb */; }; + BEC3A76816F79497003E5634 /* SecTaskPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = BEC3A76716F79497003E5634 /* SecTaskPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + C288A0891505796F00E773B7 /* libOpenScriptingUtil.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = C288A0881505795D00E773B7 /* libOpenScriptingUtil.dylib */; settings = {ATTRIBUTES = (Weak, ); }; }; + CDDE9D1E1729E2E60013B0E8 /* SecPasswordGenerate.h in Headers */ = {isa = PBXBuildFile; fileRef = CDDE9D1C1729DF250013B0E8 /* SecPasswordGenerate.h */; settings = {ATTRIBUTES = (Private, ); }; }; + E76079D61951FDAF00F69731 /* liblogging.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E76079D51951FDA800F69731 /* liblogging.a */; }; + E778BFBC17176DDE00302C14 /* security.exp-in in Sources */ = {isa = PBXBuildFile; fileRef = 182BB562146F4C73000BF1F3 /* security.exp-in */; }; + EB22F3F918A26BCA0016A8EC /* SecBreadcrumb.c in Sources */ = {isa = PBXBuildFile; fileRef = EB22F3F718A26BA50016A8EC /* SecBreadcrumb.c */; }; + EB22F3FA18A26BCE0016A8EC /* SecBreadcrumb.h in Headers */ = {isa = PBXBuildFile; fileRef = EB22F3F818A26BA50016A8EC /* SecBreadcrumb.h */; settings = {ATTRIBUTES = (Private, ); }; }; + EB22F3FB18A26BE40016A8EC /* bc-10-knife-on-bread.c in Sources */ = {isa = PBXBuildFile; fileRef = EB22F3F518A26BA50016A8EC /* bc-10-knife-on-bread.c */; }; +/* End PBXBuildFile section */ + +/* Begin PBXBuildRule section */ + E778BFB91717461800302C14 /* PBXBuildRule */ = { + isa = PBXBuildRule; + compilerSpec = com.apple.compilers.proxy.script; + filePatterns = "*.exp-in"; + fileType = pattern.proxy; + isEditable = 1; + outputFiles = ( + "$(BUILT_PRODUCTS_DIR)/$(TARGETNAME).$(CURRENT_ARCH).exp", + ); + script = "#!/bin/sh\n\nfor file in ${HEADER_SEARCH_PATHS[@]} ; do\nHEADER_SEARCH_OPTIONS=\"${HEADER_SEARCH_OPTIONS} -I${file}\"\ndone\n\nxcrun clang -E -Xpreprocessor -P -x c -arch ${CURRENT_ARCH} ${HEADER_SEARCH_OPTIONS} ${INPUT_FILE_PATH} -o ${BUILT_PRODUCTS_DIR}/${TARGETNAME}.${CURRENT_ARCH}.exp\n"; + }; +/* End PBXBuildRule section */ + +/* Begin PBXContainerItemProxy section */ + 0C4EAE711766865000773425 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 0C0BDB5F175687EC00BC1A7E; + remoteInfo = libsecdRegressions; + }; + 0C4EAE7817668DFF00773425 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 0C0BDB55175687EC00BC1A7E; + remoteInfo = libsecdRegressions; + }; + 0C6C632D15D19D2900BC68CD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 0CCA415815C89E8B002AEC4C; + remoteInfo = libsecurity_ssl_regressions; + }; + 0C6C642D15D5ADC900BC68CD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 0CC9A7EF146DF66000C18F89; + remoteInfo = tlsnke; + }; + 0C6C642F15D5AE4C00BC68CD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 0C1C92EF15C8AC81007D377B; + remoteInfo = libsecurity_ssl_kext; + }; + 0C6D77CC15C8B66000BB4405 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 0C1C933A15C8AC81007D377B; + remoteInfo = libsecurity_ssl_kext; + }; + 0C6D77CE15C8B66000BB4405 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 0CCA415915C89E8B002AEC4C; + remoteInfo = libsecurity_ssl_regressions; + }; + 0C6D77D015C8B66000BB4405 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 0CCA42C915C8A387002AEC4C; + remoteInfo = dtlsEchoClient; + }; + 0C6D77D215C8B66000BB4405 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 0CCA42D715C8A395002AEC4C; + remoteInfo = dtlsEchoServer; + }; + 0C6D77E815C8C06600BB4405 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 0CC9A7F0146DF66000C18F89; + remoteInfo = tlsnke; + }; + 0C6D77EA15C8C06600BB4405 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 0CE08A73148FF2C6000473EB; + remoteInfo = tlsnketest; + }; + 0C6D77EC15C8C06600BB4405 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 0CDF46A014DC794300FFE2FD; + remoteInfo = tlssocket; + }; + 0CBD50B216C325F000713B6C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 0CBD509716C3242200713B6C; + remoteInfo = libsecurity_keychain_regressions; + }; + 0CBD50C616C3260D00713B6C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 0CBD500016C3242200713B6C; + remoteInfo = libsecurity_keychain_regressions; + }; + 0CC3350916C1ED8000399E53 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E702E73514E1F3EA00CDE635; + remoteInfo = libSecureObjectSync; + }; + 0CC3350B16C1ED8000399E53 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E742A09B14E343E70052A486; + remoteInfo = utilities; + }; + 0CC3350D16C1ED8000399E53 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E702E75714E1F48800CDE635; + remoteInfo = libSOSRegressions; + }; + 0CC3351116C1ED8000399E53 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 18D4043414CE0CF300A2BE4E; + remoteInfo = libsecurity; + }; + 0CC3351316C1ED8000399E53 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 18270F5414CF651900B05E7F; + remoteInfo = libsecipc_client; + }; + 0CC3351516C1ED8000399E53 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 186CDD0E14CA116C00AF9171; + remoteInfo = libSecItemShimOSX; + }; + 0CC3355F16C1EF5D00399E53 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0CC3355B16C1EF5D00399E53 /* regressions.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = E710C6FE133192E900F85568; + remoteInfo = regressions; + }; + 0CC3356116C1EF8B00399E53 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0CC3355B16C1EF5D00399E53 /* regressions.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E710C6FD133192E900F85568; + remoteInfo = regressions; + }; + 0CCEBDB216C2CFD4001BD7F6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0CC3355B16C1EF5D00399E53 /* regressions.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E710C6FD133192E900F85568; + remoteInfo = regressions; + }; + 0CCEBDB916C303D8001BD7F6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0CC3350716C1ED8000399E53; + remoteInfo = secdtests; + }; + 0CCEBDBC16C30948001BD7F6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E7E0D8E8158FA9A3002CA176; + remoteInfo = utilitiesRegressions; + }; + 0CFC55E215DDB86500BEC89E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0C6C630A15D193C800BC68CD; + remoteInfo = sectests; + }; + 18270C7C14CE573D00B05E7F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 18D4056214CE53C200A2BE4E; + remoteInfo = securityd; + }; + 18270EE014CF28D000B05E7F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 18D4043414CE0CF300A2BE4E; + remoteInfo = libsecurity; + }; + 18270EE214CF28D900B05E7F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 18D4056114CE53C200A2BE4E; + remoteInfo = libsecurityd; + }; + 18270F1114CF43C000B05E7F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18270F0814CF43C000B05E7F /* libDER.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 053BA314091C00BF00A7007A; + remoteInfo = libDER; + }; + 18270F1314CF43C000B05E7F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18270F0814CF43C000B05E7F /* libDER.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 053BA445091FE58C00A7007A; + remoteInfo = parseCert; + }; + 18270F1514CF43C000B05E7F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18270F0814CF43C000B05E7F /* libDER.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 053BA46B091FE63E00A7007A; + remoteInfo = libDERUtils; + }; + 18270F1714CF43C000B05E7F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18270F0814CF43C000B05E7F /* libDER.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 058F16540925135E009FA1C5; + remoteInfo = parseCrl; + }; + 18270F1914CF43C000B05E7F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18270F0814CF43C000B05E7F /* libDER.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4C96C8CE113F4132005483E8; + remoteInfo = parseTicket; + }; + 18270F5C14CF655B00B05E7F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 18270F5414CF651900B05E7F; + remoteInfo = libsecipc_client; + }; + 18270F5F14CF655B00B05E7F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 18270F5514CF651900B05E7F; + remoteInfo = libsecipc_client; + }; + 182BB22B146F07DD000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4C5719C712FB5E9E00B31F85; + remoteInfo = XPCKeychainSandboxCheck; + }; + 182BB3EB146F2448000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B5F0146DE6FD007E536C /* libsecurity_apple_x509_tp.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_apple_x509_tp; + }; + 182BB3ED146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B6EC146DE7EE007E536C /* libsecurity_pkcs12.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 0592AC8B0415523C00003D05; + remoteInfo = libsecurity_pkcs12; + }; + 182BB3EF146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B72B146DE844007E536C /* libsecurity_transform.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_transform; + }; + 182BB3F1146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B6DF146DE7E7007E536C /* libsecurity_ocspd.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_ocspd; + }; + 182BB3F3146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B66D146DE75D007E536C /* libsecurity_comcryption.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 7264321D00A8AD0A7F000001; + remoteInfo = libsecurity_comcryption; + }; + 182BB3F5146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B637146DE748007E536C /* libsecurity_checkpw.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_checkpw; + }; + 182BB3F7146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_ssl; + }; + 182BB3FB146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B5C9146DE6CE007E536C /* libsecurity_apple_cspdl.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_apple_cspdl; + }; + 182BB3FD146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B6F8146DE7F7007E536C /* libsecurity_sd_cspdl.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_sd_cspdl; + }; + 182BB3FF146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B6C7146DE7D7007E536C /* libsecurity_manifest.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = D6C8AFAD05DD2430003DB724; + remoteInfo = libsecurity_manifest; + }; + 182BB401146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B712146DE825007E536C /* libsecurity_smime.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4C2741ED03E9FBF700A80181; + remoteInfo = libsecurity_smime; + }; + 182BB403146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B64B146DE750007E536C /* libsecurity_cms.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_cms; + }; + 182BB405146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B5BC146DE6C8007E536C /* libsecurity_apple_csp.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_apple_csp; + }; + 182BB407146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B5E1146DE6E7007E536C /* libsecurity_apple_x509_cl.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_apple_x509_cl; + }; + 182BB409146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_keychain; + }; + 182BB40B146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B5D5146DE6D7007E536C /* libsecurity_apple_file_dl.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_apple_file_dl; + }; + 182BB40D146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B609146DE70A007E536C /* libsecurity_authorization.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_authorization; + }; + 182BB40F146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B550146DE227007E536C /* libsecurity_cdsa_utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA2A5390523D32800978A7B; + remoteInfo = libsecurity_cdsa_utilities; + }; + 182BB411146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B679146DE76E007E536C /* libsecurity_cryptkit.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 7264322800A8AD0A7F000001; + remoteInfo = libsecurity_cryptkit; + }; + 182BB413146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B615146DE715007E536C /* libsecurity_cdsa_client.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_cdsa_client; + }; + 182BB417146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B694146DE797007E536C /* libsecurity_filedb.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_filedb; + }; + 182BB419146F248D000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B6D3146DE7E0007E536C /* libsecurity_mds.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_mds; + }; + 182BB4E6146F25AF000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_codesigning; + }; + 182BB587146FE001000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_codesigning; + }; + 182BB58C146FE0FF000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B550146DE227007E536C /* libsecurity_cdsa_utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA2A5390523D32800978A7B; + remoteInfo = libsecurity_cdsa_utilities; + }; + 182BB58E146FE11C000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B532146DDBE5007E536C /* libsecurity_utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA2A5390523D32800978A7B; + remoteInfo = libsecurity_utilities; + }; + 182BB595146FE27F000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1807384A146D0D4E00F05C24; + remoteInfo = Security; + }; + 18446081146DF52F00B12992 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B621146DE720007E536C /* libsecurity_cdsa_plugin.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_cdsa_plugin; + }; + 184461B0146E9D3300B12992 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 184461A3146E9D3200B12992 /* libsecurityd.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurityd_client; + }; + 184461B4146E9D3300B12992 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 184461A3146E9D3200B12992 /* libsecurityd.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FECD052A44A100F22E42; + remoteInfo = libsecurityd_server; + }; + 184461B8146E9D3300B12992 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 184461A3146E9D3200B12992 /* libsecurityd.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = C2A788730B7AA65B00CFF85C; + remoteInfo = ucspc; + }; + 186CDD1D14CA11C700AF9171 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 186CDD0F14CA116C00AF9171; + remoteInfo = sec; + }; + 186F779014E5A00F00434E1F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 18270ED514CF282600B05E7F; + remoteInfo = secd; + }; + 186F779214E5A01700434E1F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 1807384A146D0D4E00F05C24; + remoteInfo = Security; + }; + 186F779414E5A01C00434E1F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 182BB567146F4DCA000BF1F3; + remoteInfo = csparser; + }; + 186F779614E5A04200434E1F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 18FE67E91471A3AA00A2CBE3; + remoteInfo = copyHeaders; + }; + 186F779814E5A06500434E1F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 186F778814E59FB200434E1F; + remoteInfo = Framework; + }; + 186F779A14E5A06800434E1F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 186F778C14E59FDA00434E1F; + remoteInfo = Helpers; + }; + 1879B537146DDBE5007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B532146DDBE5007E536C /* libsecurity_utilities.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA2A53A0523D32800978A7B; + remoteInfo = utilities; + }; + 1879B544146DE18D007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B532146DDBE5007E536C /* libsecurity_utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA2A5390523D32800978A7B; + remoteInfo = libsecurity_utilities; + }; + 1879B54E146DE212007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B547146DE212007E536C /* libsecurity_cdsa_utils.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = cdsa_utils; + }; + 1879B559146DE227007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B550146DE227007E536C /* libsecurity_cdsa_utilities.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA2A53A0523D32800978A7B; + remoteInfo = cdsa_utilities; + }; + 1879B55B146DE227007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B550146DE227007E536C /* libsecurity_cdsa_utilities.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CF9C5B90535E557009B9B8D; + remoteInfo = Schemas; + }; + 1879B564146DE244007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B55D146DE244007E536C /* libsecurity_cssm.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = cssm; + }; + 1879B56B146DE2CF007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B547146DE212007E536C /* libsecurity_cdsa_utils.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_cdsa_utils; + }; + 1879B56D146DE2D3007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B55D146DE244007E536C /* libsecurity_cssm.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_cssm; + }; + 1879B5C5146DE6C8007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B5BC146DE6C8007E536C /* libsecurity_apple_csp.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_apple_csp; + }; + 1879B5D1146DE6CE007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B5C9146DE6CE007E536C /* libsecurity_apple_cspdl.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_apple_cspdl; + }; + 1879B5DD146DE6D7007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B5D5146DE6D7007E536C /* libsecurity_apple_file_dl.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_apple_file_dl; + }; + 1879B5EA146DE6E8007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B5E1146DE6E7007E536C /* libsecurity_apple_x509_cl.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CC7C27506127AA100E6CE35; + remoteInfo = libsecurity_apple_x509_cl; + }; + 1879B5EE146DE6E8007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B5E1146DE6E7007E536C /* libsecurity_apple_x509_cl.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = C207F277053B21E600FF85CB; + remoteInfo = plugin_apple_x509_cl; + }; + 1879B5F8146DE6FD007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B5F0146DE6FD007E536C /* libsecurity_apple_x509_tp.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_apple_x509_tp; + }; + 1879B611146DE70A007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B609146DE70A007E536C /* libsecurity_authorization.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_authorization; + }; + 1879B61D146DE715007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B615146DE715007E536C /* libsecurity_cdsa_client.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_cdsa_client; + }; + 1879B62A146DE720007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B621146DE720007E536C /* libsecurity_cdsa_plugin.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_cdsa_plugin; + }; + 1879B643146DE748007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B637146DE748007E536C /* libsecurity_checkpw.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_checkpw; + }; + 1879B647146DE748007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B637146DE748007E536C /* libsecurity_checkpw.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 1CD90B6711011176008DD07F; + remoteInfo = "test-checkpw"; + }; + 1879B649146DE748007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B637146DE748007E536C /* libsecurity_checkpw.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 1C6C402F1121FC0C00031CDE; + remoteInfo = "perf-checkpw"; + }; + 1879B653146DE750007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B64B146DE750007E536C /* libsecurity_cms.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_cms; + }; + 1879B665146DE757007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_codesigning; + }; + 1879B669146DE757007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = C2BC1F260B580D3A003EC9DC; + remoteInfo = libintegrity; + }; + 1879B66B146DE757007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = C2BC1F2F0B580D4B003EC9DC; + remoteInfo = libcodehost; + }; + 1879B675146DE75E007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B66D146DE75D007E536C /* libsecurity_comcryption.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 7264321400A8AD0A7F000001; + remoteInfo = libsecurity_comcryption; + }; + 1879B683146DE76F007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B679146DE76E007E536C /* libsecurity_cryptkit.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 7264321600A8AD0A7F000001; + remoteInfo = libsecurity_cryptkit; + }; + 1879B687146DE76F007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B679146DE76E007E536C /* libsecurity_cryptkit.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 0535DCBE074A944D00805B04; + remoteInfo = libCryptKit; + }; + 1879B689146DE76F007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B679146DE76E007E536C /* libsecurity_cryptkit.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 0536B295074BC91A00F9F1AD; + remoteInfo = CryptKitSignature; + }; + 1879B69C146DE797007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B694146DE797007E536C /* libsecurity_filedb.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_filedb; + }; + 1879B6B2146DE7A0007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_keychain; + }; + 1879B6B6146DE7A0007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4C5719C812FB5E9E00B31F85; + remoteInfo = XPCKeychainSandboxCheck; + }; + 1879B6CF146DE7D7007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B6C7146DE7D7007E536C /* libsecurity_manifest.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D6C8AFAE05DD2430003DB724; + remoteInfo = libsecurity_manifest; + }; + 1879B6DB146DE7E0007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B6D3146DE7E0007E536C /* libsecurity_mds.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_mds; + }; + 1879B6E8146DE7E8007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B6DF146DE7E7007E536C /* libsecurity_ocspd.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_ocspd; + }; + 1879B6F4146DE7EF007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B6EC146DE7EE007E536C /* libsecurity_pkcs12.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 0592AC8C0415523C00003D05; + remoteInfo = libsecurity_pkcs12; + }; + 1879B700146DE7F7007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B6F8146DE7F7007E536C /* libsecurity_sd_cspdl.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_sd_cspdl; + }; + 1879B71B146DE825007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B712146DE825007E536C /* libsecurity_smime.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4C817F8405ED4D7A007975E6; + remoteInfo = libsecurity_smime; + }; + 1879B727146DE839007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_ssl; + }; + 1879B738146DE845007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B72B146DE844007E536C /* libsecurity_transform.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_transform; + }; + 1879B73C146DE845007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B72B146DE844007E536C /* libsecurity_transform.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4C738257112DF65200EA003B; + remoteInfo = "unit-tests"; + }; + 1879B73E146DE845007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B72B146DE844007E536C /* libsecurity_transform.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CBCBEB61130A2D700CC18E9; + remoteInfo = "100-sha2"; + }; + 1879B740146DE845007E536C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B72B146DE844007E536C /* libsecurity_transform.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4C010B87121AE8DF0094CB72; + remoteInfo = "input-speed-test"; + }; + 1885B3F814D8D9B100519375 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B5FC146DE704007E536C /* libsecurity_asn1.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 795CA7FF0D38013D00BAE6A2; + remoteInfo = libASN1; + }; + 1885B45014D9AB3D00519375 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B5FC146DE704007E536C /* libsecurity_asn1.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 795CA7FE0D38013D00BAE6A2; + remoteInfo = libASN1; + }; + 18AD56A514CDED59008233F2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 186CDD0E14CA116C00AF9171; + remoteInfo = sec; + }; + 18B9655B1472F83C005A4D2E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 184461A3146E9D3200B12992 /* libsecurityd.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4C31C2D9055341AA006D00BD; + remoteInfo = world; + }; + 18D4053A14CE2C1600A2BE4E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 18D4043514CE0CF300A2BE4E; + remoteInfo = security; + }; + 18F235FE15CA100300060520 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 18F234EA15C9F9A600060520; + remoteInfo = security.auth; + }; + 18FE688E1471A4C900A2CBE3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 18FE67E91471A3AA00A2CBE3; + remoteInfo = copyHeaders; + }; + 37A7CED9197DBA8700926CE8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 37A7CEAA197DB8FA00926CE8; + remoteInfo = codesign_tests; + }; + 4AD6F6F31651CC2500DB4CE6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4A5CCA4E15ACEFA500702357; + remoteInfo = libSecOtrOSX; + }; + 4C01DE31164C3793006798CD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 528402A0164445760035F320; + remoteInfo = libCloudKeychainProxy; + }; + 4C01DF12164C3E74006798CD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E702E73514E1F3EA00CDE635; + remoteInfo = libSecureObjectSync; + }; + 4C1288E915FFE9D7008CE3E3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = E702E75614E1F3EA00CDE635; + remoteInfo = libSecureObjectSync; + }; + 4C1288EB15FFE9D7008CE3E3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = E702E77814E1F48800CDE635; + remoteInfo = libSOSRegressions; + }; + 4C1288ED15FFE9D7008CE3E3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4A824B03158FF07000F932C0; + remoteInfo = libSecurityRegressions; + }; + 4C1288EF15FFE9D7008CE3E3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CC92B1415A3BC6B00C6D578; + remoteInfo = libsecuritydRegressions; + }; + 4C1288F115FFE9D7008CE3E3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4A5CCA4F15ACEFA500702357; + remoteInfo = libSecOtrOSX; + }; + 4C12893F15FFECF3008CE3E3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = E742A09C14E343E70052A486; + remoteInfo = utilities; + }; + 4C12894115FFECF3008CE3E3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = E7E0D8F9158FA9A3002CA176; + remoteInfo = utilitiesRegressions; + }; + 4C12894315FFED03008CE3E3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E742A09B14E343E70052A486; + remoteInfo = utilities; + }; + 4C797BC816D83A3100C7B586 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4C96F7C016D6DF8300D3B39D; + remoteInfo = "Keychain Circle Notification"; + }; + 4C797BF016D83A3800C7B586 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4CC7A7B216CC2A84003E10C1; + remoteInfo = "Cloud Keychain Utility"; + }; + 4C7D8763160A746E00D041E3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E742A09B14E343E70052A486; + remoteInfo = utilities; + }; + 4C8D864F177A75100019A804 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 18270F5414CF651900B05E7F; + remoteInfo = libsecipc_client; + }; + 4CB23B75169F5873003A0131 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = E71049F2169E023B00DB0045; + remoteInfo = libSecurityTool; + }; + 4CB23B77169F5873003A0131 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = E7104A1D169E216E00DB0045; + remoteInfo = libSecurityCommands; + }; + 4CB23B79169F5873003A0131 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = E7FEFB8C169E363300E18152; + remoteInfo = libSOSCommands; + }; + 4CB23B83169F5961003A0131 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E7FEFB82169E363300E18152; + remoteInfo = libSOSCommands; + }; + 4CB23B85169F5971003A0131 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E7104A12169E216E00DB0045; + remoteInfo = libSecurityCommands; + }; + 4CB23B87169F597D003A0131 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E71049F1169E023B00DB0045; + remoteInfo = libSecurityTool; + }; + 4CB23B8F169F59D8003A0131 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4CB23B45169F5873003A0131; + remoteInfo = security2; + }; + 5208C0FD16A0D3980062DDC5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E702E73514E1F3EA00CDE635; + remoteInfo = libSecureObjectSync; + }; + 5214701716977D1D00DF0DB3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E742A09B14E343E70052A486; + remoteInfo = utilities; + }; + 5214701916977D2500DF0DB3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 5284029F164445760035F320; + remoteInfo = libCloudKeychainProxy; + }; + 521470281697842500DF0DB3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5214700516977CB800DF0DB3; + remoteInfo = CloudKeychainProxy; + }; + 529FF21F1523BD7F0029D842 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 52200F8714F2B87F00F7F6E7; + remoteInfo = XPCTimeStampingService; + }; + 52B5A8F5151928B400664F11 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 52200F8F14F2B88000F7F6E7; + remoteInfo = XPCTimeStampingService; + }; + 722CF217175D602F00BCE0A5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 72756BFD175D485D00F52070; + remoteInfo = cloud_keychain_diagnose; + }; + 7AADF6E019C1062200292339 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 7AADF57C19C0CE8C00292339; + remoteInfo = gkoverride; + }; + 7AADF6F519C1062200292339 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 7AADF57D19C0CE8C00292339; + remoteInfo = gkoverride; + }; + ACB6171718B5231800EBEDD7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B712146DE825007E536C /* libsecurity_smime.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = AC62F5F018B4356A00704BBD; + remoteInfo = libsecurity_smime_regressions; + }; + ACB6173E18B5232700EBEDD7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B712146DE825007E536C /* libsecurity_smime.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = AC62F5EF18B4356A00704BBD; + remoteInfo = libsecurity_smime_regressions; + }; + C2432A0715C7112A0096DB5B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = C209696015BF52040093035F; + remoteInfo = gkunpack; + }; + C2432A2415C726B50096DB5B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = C209695F15BF52040093035F; + remoteInfo = gkunpack; + }; + E760796E1951F99600F69731 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = BEF9640618B4171200813FA3; + remoteInfo = libSWCAgent; + }; + E76079D41951FDA800F69731 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = E76079D21951FD2800F69731; + remoteInfo = liblogging; + }; + E76079F91951FDF600F69731 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E76079971951FD2800F69731; + remoteInfo = liblogging; + }; + EB2E1F57166D6B3700A7EF61 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = EB2E1F05166D69B800A7EF61; + remoteInfo = CodeSigningHelper; + }; + EBB9FFDF1682E71F00FF9774 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = EBB9FF6E1682E51300FF9774; + remoteInfo = CodeSigningHelper; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 0C6D003C177B545D0095D167 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /private/etc/asl; + dstSubfolderSpec = 0; + files = ( + 0C6D0065177B54CB0095D167 /* com.apple.securityd in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 187D6B9615D4381C00E27494 /* Copy authorization.plist */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "$(SYSTEM_LIBRARY_DIR)/Security"; + dstSubfolderSpec = 0; + files = ( + 187D6B9715D438AD00E27494 /* authorization.plist in Copy authorization.plist */, + ); + name = "Copy authorization.plist"; + runOnlyForDeploymentPostprocessing = 1; + }; + 18BEB19914CF7F0B00C8BD36 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /System/Library/LaunchAgents; + dstSubfolderSpec = 0; + files = ( + 18BEB19A14CF7F8100C8BD36 /* com.apple.secd.plist in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 18CFEE8815DEE2BA00E3F2A3 /* Copy sandbox profile */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "$(SYSTEM_LIBRARY_DIR)/Sandbox/Profiles"; + dstSubfolderSpec = 0; + files = ( + 18CFEE8915DEE2C600E3F2A3 /* com.apple.authd.sb in Copy sandbox profile */, + ); + name = "Copy sandbox profile"; + runOnlyForDeploymentPostprocessing = 1; + }; + 18D6803A16B768DE00DF6D2E /* Copy asl module */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /private/etc/asl; + dstSubfolderSpec = 0; + files = ( + 18D6803B16B768F700DF6D2E /* com.apple.authd in Copy asl module */, + ); + name = "Copy asl module"; + runOnlyForDeploymentPostprocessing = 1; + }; + 37A7CEDC197DCECD00926CE8 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /AppleInternal/CoreOS/codesign_tests; + dstSubfolderSpec = 0; + files = ( + 37A7CEDD197DCEE500926CE8 /* validation.sh in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 37A7CF21197DD10900926CE8 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /AppleInternal/CoreOS; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 4A5C178F161A9DE000ABF784 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/local/include; + dstSubfolderSpec = 0; + files = ( + 4A5C1790161A9DFB00ABF784 /* authd_private.h in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 4C49390E16E51ED100CE110C /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = /System/Library/LaunchAgents; + dstSubfolderSpec = 0; + files = ( + 4C49390F16E51FC700CE110C /* com.apple.security.keychain-circle-notification.plist in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CB23B44169F5873003A0131 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + 4CB23B4C169F5873003A0131 /* security2.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 4CB86AE4167A6F3D00F46643 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = PrivateHeaders/SecureObjectSync; + dstSubfolderSpec = 1; + files = ( + 4CB86AFB167A8F2200F46643 /* SOSAccount.h in CopyFiles */, + 4CB86AF0167A6FF300F46643 /* SOSCircle.h in CopyFiles */, + 4CB86AF1167A6FF300F46643 /* SOSCloudCircle.h in CopyFiles */, + 4CB86AF2167A6FF300F46643 /* SOSCloudCircleInternal.h in CopyFiles */, + 4CB86AF3167A6FF300F46643 /* SOSEngine.h in CopyFiles */, + 4CB86AF4167A6FF300F46643 /* SOSFullPeerInfo.h in CopyFiles */, + 4CB86AF5167A6FF300F46643 /* SOSInternal.h in CopyFiles */, + 4CB86AF6167A6FF300F46643 /* SOSPeer.h in CopyFiles */, + 4CB86AF7167A6FF300F46643 /* SOSPeerInfo.h in CopyFiles */, + 4CB86AF8167A6FF300F46643 /* SOSTransport.h in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 5214702316977EA600DF0DB3 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "$(INDIGO_INSTALL_PATH_PREFIX)/System/Library/LaunchAgents/"; + dstSubfolderSpec = 0; + files = ( + 521470261697800500DF0DB3 /* com.apple.security.cloudkeychainproxy.plist in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 72756BFC175D485D00F52070 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0C03D60317D93E810087643B /* SecDH.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SecDH.h; path = sec/Security/SecDH.h; sourceTree = SOURCE_ROOT; }; + 0C4F055D15C9E51A00F9DFD5 /* sslTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sslTypes.h; path = libsecurity_ssl/lib/sslTypes.h; sourceTree = SOURCE_ROOT; }; + 0C6C630B15D193C800BC68CD /* sectests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sectests; sourceTree = BUILT_PRODUCTS_DIR; }; + 0C6C630E15D193C800BC68CD /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 0C6C632415D1964200BC68CD /* testlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testlist.h; sourceTree = ""; }; + 0C6C632F15D19DE600BC68CD /* test.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = test.xcconfig; sourceTree = ""; }; + 0C6D0064177B54C60095D167 /* com.apple.securityd */ = {isa = PBXFileReference; lastKnownFileType = text; name = com.apple.securityd; path = asl/com.apple.securityd; sourceTree = SOURCE_ROOT; }; + 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = tlsnke.xcodeproj; path = tlsnke/tlsnke.xcodeproj; sourceTree = ""; }; + 0CC3352D16C1ED8000399E53 /* secdtests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secdtests; sourceTree = BUILT_PRODUCTS_DIR; }; + 0CC3355716C1EEE700399E53 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = main.c; path = secdtests/main.c; sourceTree = ""; }; + 0CC3355816C1EEE700399E53 /* testlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = testlist.h; path = secdtests/testlist.h; sourceTree = ""; }; + 0CC3355B16C1EF5D00399E53 /* regressions.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = regressions.xcodeproj; path = regressions/regressions.xcodeproj; sourceTree = SOURCE_ROOT; }; + 1807384B146D0D4E00F05C24 /* Security.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Security.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 18073856146D0D4E00F05C24 /* Info-Security.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-Security.plist"; sourceTree = ""; }; + 181EA422146D4A2A00A6D320 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 181EA423146D4A2A00A6D320 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 181EA424146D4A2A00A6D320 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; wrapsLines = 0; }; + 181EA425146D4A2A00A6D320 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 18270ED614CF282600B05E7F /* secd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secd; sourceTree = BUILT_PRODUCTS_DIR; }; + 18270EEC14CF333400B05E7F /* client.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = client.c; sourceTree = ""; }; + 18270EED14CF333400B05E7F /* com.apple.securityd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.securityd.plist; sourceTree = ""; }; + 18270EEE14CF333400B05E7F /* securityd_client.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = securityd_client.h; sourceTree = ""; }; + 18270EEF14CF333400B05E7F /* securityd_ipc_types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = securityd_ipc_types.h; sourceTree = ""; }; + 18270EF014CF333400B05E7F /* securityd_rep.defs */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.mig; path = securityd_rep.defs; sourceTree = ""; }; + 18270EF114CF333400B05E7F /* securityd_req.defs */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.mig; path = securityd_req.defs; sourceTree = ""; }; + 18270EF214CF333400B05E7F /* securityd_server.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = securityd_server.h; sourceTree = ""; }; + 18270EF314CF333400B05E7F /* server.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = server.c; sourceTree = ""; }; + 18270EFB14CF427800B05E7F /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = /System/Library/Frameworks/CFNetwork.framework; sourceTree = ""; }; + 18270EFD14CF429600B05E7F /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = ""; }; + 18270EFF14CF42CA00B05E7F /* libcorecrypto.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcorecrypto.a; path = /usr/local/lib/libcorecrypto.a; sourceTree = ""; }; + 18270F0814CF43C000B05E7F /* libDER.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libDER.xcodeproj; path = libsecurity_keychain/libDER/libDER.xcodeproj; sourceTree = ""; }; + 18270F3A14CF44C400B05E7F /* debugging.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = debugging.c; sourceTree = ""; }; + 18270F3B14CF44C400B05E7F /* debugging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debugging.h; sourceTree = ""; }; + 182A190F15D09AF0006AB103 /* connection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = connection.h; sourceTree = ""; }; + 182A191015D09AFF006AB103 /* connection.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = connection.c; sourceTree = ""; }; + 182BB187146EAD4C000BF1F3 /* SecAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecAccess.h; path = libsecurity_keychain/lib/SecAccess.h; sourceTree = SOURCE_ROOT; }; + 182BB188146EAD4C000BF1F3 /* SecACL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecACL.h; path = libsecurity_keychain/lib/SecACL.h; sourceTree = SOURCE_ROOT; }; + 182BB189146EAD4C000BF1F3 /* SecBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecBase.h; path = libsecurity_keychain/lib/SecBase.h; sourceTree = SOURCE_ROOT; }; + 182BB18A146EAD4C000BF1F3 /* SecCertificate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCertificate.h; path = libsecurity_keychain/lib/SecCertificate.h; sourceTree = SOURCE_ROOT; }; + 182BB18B146EAD4C000BF1F3 /* SecIdentity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecIdentity.h; path = libsecurity_keychain/lib/SecIdentity.h; sourceTree = SOURCE_ROOT; }; + 182BB18C146EAD4C000BF1F3 /* SecIdentitySearch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecIdentitySearch.h; path = libsecurity_keychain/lib/SecIdentitySearch.h; sourceTree = SOURCE_ROOT; }; + 182BB18D146EAD4C000BF1F3 /* SecItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecItem.h; path = libsecurity_keychain/lib/SecItem.h; sourceTree = SOURCE_ROOT; }; + 182BB18E146EAD4C000BF1F3 /* SecKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKey.h; path = libsecurity_keychain/lib/SecKey.h; sourceTree = SOURCE_ROOT; }; + 182BB18F146EAD4C000BF1F3 /* SecKeychain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKeychain.h; path = libsecurity_keychain/lib/SecKeychain.h; sourceTree = SOURCE_ROOT; }; + 182BB190146EAD4C000BF1F3 /* SecKeychainItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKeychainItem.h; path = libsecurity_keychain/lib/SecKeychainItem.h; sourceTree = SOURCE_ROOT; }; + 182BB191146EAD4C000BF1F3 /* SecKeychainSearch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKeychainSearch.h; path = libsecurity_keychain/lib/SecKeychainSearch.h; sourceTree = SOURCE_ROOT; }; + 182BB192146EAD4C000BF1F3 /* SecPolicy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecPolicy.h; path = libsecurity_keychain/lib/SecPolicy.h; sourceTree = SOURCE_ROOT; }; + 182BB193146EAD4C000BF1F3 /* SecPolicySearch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecPolicySearch.h; path = libsecurity_keychain/lib/SecPolicySearch.h; sourceTree = SOURCE_ROOT; }; + 182BB194146EAD4C000BF1F3 /* SecTrust.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTrust.h; path = libsecurity_keychain/lib/SecTrust.h; sourceTree = SOURCE_ROOT; }; + 182BB195146EAD4C000BF1F3 /* SecTrustedApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTrustedApplication.h; path = libsecurity_keychain/lib/SecTrustedApplication.h; sourceTree = SOURCE_ROOT; }; + 182BB196146EAD4C000BF1F3 /* Security.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Security.h; path = libsecurity_keychain/lib/Security.h; sourceTree = SOURCE_ROOT; }; + 182BB197146EAD4C000BF1F3 /* SecImportExport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecImportExport.h; path = libsecurity_keychain/lib/SecImportExport.h; sourceTree = SOURCE_ROOT; }; + 182BB198146EAD4C000BF1F3 /* SecTrustSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTrustSettings.h; path = libsecurity_keychain/lib/SecTrustSettings.h; sourceTree = SOURCE_ROOT; }; + 182BB199146EAD4C000BF1F3 /* SecCertificateOIDs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCertificateOIDs.h; path = libsecurity_keychain/lib/SecCertificateOIDs.h; sourceTree = SOURCE_ROOT; }; + 182BB19A146EAD4C000BF1F3 /* SecRandom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecRandom.h; path = libsecurity_keychain/lib/SecRandom.h; sourceTree = SOURCE_ROOT; }; + 182BB1AF146EAD5D000BF1F3 /* SecFDERecoveryAsymmetricCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecFDERecoveryAsymmetricCrypto.h; path = libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.h; sourceTree = SOURCE_ROOT; }; + 182BB1B0146EAD5D000BF1F3 /* SecPassword.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecPassword.h; path = libsecurity_keychain/lib/SecPassword.h; sourceTree = SOURCE_ROOT; }; + 182BB1B2146EAD5D000BF1F3 /* SecAccessPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecAccessPriv.h; path = libsecurity_keychain/lib/SecAccessPriv.h; sourceTree = SOURCE_ROOT; }; + 182BB1B3146EAD5D000BF1F3 /* SecBasePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecBasePriv.h; path = libsecurity_keychain/lib/SecBasePriv.h; sourceTree = SOURCE_ROOT; }; + 182BB1B4146EAD5D000BF1F3 /* SecCertificateBundle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCertificateBundle.h; path = libsecurity_keychain/lib/SecCertificateBundle.h; sourceTree = SOURCE_ROOT; }; + 182BB1B5146EAD5D000BF1F3 /* SecCertificatePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCertificatePriv.h; path = libsecurity_keychain/lib/SecCertificatePriv.h; sourceTree = SOURCE_ROOT; }; + 182BB1B6146EAD5D000BF1F3 /* SecCertificateRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCertificateRequest.h; path = libsecurity_keychain/lib/SecCertificateRequest.h; sourceTree = SOURCE_ROOT; }; + 182BB1B7146EAD5D000BF1F3 /* SecIdentityPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecIdentityPriv.h; path = libsecurity_keychain/lib/SecIdentityPriv.h; sourceTree = SOURCE_ROOT; }; + 182BB1B8146EAD5D000BF1F3 /* SecKeychainItemPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKeychainItemPriv.h; path = libsecurity_keychain/lib/SecKeychainItemPriv.h; sourceTree = SOURCE_ROOT; }; + 182BB1B9146EAD5D000BF1F3 /* SecKeychainPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKeychainPriv.h; path = libsecurity_keychain/lib/SecKeychainPriv.h; sourceTree = SOURCE_ROOT; }; + 182BB1BA146EAD5D000BF1F3 /* SecKeyPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKeyPriv.h; path = libsecurity_keychain/lib/SecKeyPriv.h; sourceTree = SOURCE_ROOT; }; + 182BB1BB146EAD5D000BF1F3 /* SecPolicyPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecPolicyPriv.h; path = libsecurity_keychain/lib/SecPolicyPriv.h; sourceTree = SOURCE_ROOT; }; + 182BB1BC146EAD5D000BF1F3 /* SecTrustedApplicationPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTrustedApplicationPriv.h; path = libsecurity_keychain/lib/SecTrustedApplicationPriv.h; sourceTree = SOURCE_ROOT; }; + 182BB1BD146EAD5D000BF1F3 /* SecTrustPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTrustPriv.h; path = libsecurity_keychain/lib/SecTrustPriv.h; sourceTree = SOURCE_ROOT; }; + 182BB1C4146EAD5D000BF1F3 /* SecIdentitySearchPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecIdentitySearchPriv.h; path = libsecurity_keychain/lib/SecIdentitySearchPriv.h; sourceTree = SOURCE_ROOT; }; + 182BB1C5146EAD5D000BF1F3 /* SecKeychainSearchPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKeychainSearchPriv.h; path = libsecurity_keychain/lib/SecKeychainSearchPriv.h; sourceTree = SOURCE_ROOT; }; + 182BB1C6146EAD5D000BF1F3 /* SecTrustSettingsPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTrustSettingsPriv.h; path = libsecurity_keychain/lib/SecTrustSettingsPriv.h; sourceTree = SOURCE_ROOT; }; + 182BB1C8146EAD5D000BF1F3 /* TrustSettingsSchema.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TrustSettingsSchema.h; path = libsecurity_keychain/lib/TrustSettingsSchema.h; sourceTree = SOURCE_ROOT; }; + 182BB1CA146EAD5D000BF1F3 /* SecItemPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecItemPriv.h; path = libsecurity_keychain/lib/SecItemPriv.h; sourceTree = SOURCE_ROOT; }; + 182BB1CB146EAD5D000BF1F3 /* SecKeychainItemExtendedAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKeychainItemExtendedAttributes.h; path = libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h; sourceTree = SOURCE_ROOT; }; + 182BB1CE146EAD5D000BF1F3 /* SecRecoveryPassword.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecRecoveryPassword.h; path = libsecurity_keychain/lib/SecRecoveryPassword.h; sourceTree = SOURCE_ROOT; }; + 182BB1CF146EAD5D000BF1F3 /* SecRandomP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecRandomP.h; path = libsecurity_keychain/lib/SecRandomP.h; sourceTree = SOURCE_ROOT; }; + 182BB229146F068B000BF1F3 /* iToolsTrustedApps.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = iToolsTrustedApps.plist; path = libsecurity_keychain/plist/iToolsTrustedApps.plist; sourceTree = SOURCE_ROOT; }; + 182BB315146F0E7E000BF1F3 /* SecureDownload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecureDownload.h; path = libsecurity_manifest/lib/SecureDownload.h; sourceTree = SOURCE_ROOT; }; + 182BB317146F0E94000BF1F3 /* SecManifest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecManifest.h; path = libsecurity_manifest/lib/SecManifest.h; sourceTree = SOURCE_ROOT; }; + 182BB318146F0E94000BF1F3 /* SecureDownloadInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecureDownloadInternal.h; path = libsecurity_manifest/lib/SecureDownloadInternal.h; sourceTree = SOURCE_ROOT; }; + 182BB356146F1198000BF1F3 /* mds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mds.h; path = libsecurity_mds/lib/mds.h; sourceTree = SOURCE_ROOT; }; + 182BB357146F1198000BF1F3 /* mds_schema.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mds_schema.h; path = libsecurity_mds/lib/mds_schema.h; sourceTree = SOURCE_ROOT; }; + 182BB35A146F11A1000BF1F3 /* mdspriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mdspriv.h; path = libsecurity_mds/lib/mdspriv.h; sourceTree = SOURCE_ROOT; }; + 182BB36E146F13B4000BF1F3 /* CipherSuite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CipherSuite.h; path = libsecurity_ssl/Security/CipherSuite.h; sourceTree = SOURCE_ROOT; }; + 182BB36F146F13B4000BF1F3 /* SecureTransport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecureTransport.h; path = libsecurity_ssl/Security/SecureTransport.h; sourceTree = SOURCE_ROOT; }; + 182BB372146F13BB000BF1F3 /* SecureTransportPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecureTransportPriv.h; path = libsecurity_ssl/Security/SecureTransportPriv.h; sourceTree = SOURCE_ROOT; }; + 182BB383146F14D2000BF1F3 /* SecCmsBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsBase.h; path = libsecurity_smime/lib/SecCmsBase.h; sourceTree = SOURCE_ROOT; }; + 182BB384146F14D2000BF1F3 /* SecCmsContentInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsContentInfo.h; path = libsecurity_smime/lib/SecCmsContentInfo.h; sourceTree = SOURCE_ROOT; }; + 182BB385146F14D2000BF1F3 /* SecCmsDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsDecoder.h; path = libsecurity_smime/lib/SecCmsDecoder.h; sourceTree = SOURCE_ROOT; }; + 182BB386146F14D2000BF1F3 /* SecCmsDigestContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsDigestContext.h; path = libsecurity_smime/lib/SecCmsDigestContext.h; sourceTree = SOURCE_ROOT; }; + 182BB387146F14D2000BF1F3 /* SecCmsDigestedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsDigestedData.h; path = libsecurity_smime/lib/SecCmsDigestedData.h; sourceTree = SOURCE_ROOT; }; + 182BB388146F14D2000BF1F3 /* SecCmsEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsEncoder.h; path = libsecurity_smime/lib/SecCmsEncoder.h; sourceTree = SOURCE_ROOT; }; + 182BB389146F14D2000BF1F3 /* SecCmsEncryptedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsEncryptedData.h; path = libsecurity_smime/lib/SecCmsEncryptedData.h; sourceTree = SOURCE_ROOT; }; + 182BB38A146F14D2000BF1F3 /* SecCmsEnvelopedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsEnvelopedData.h; path = libsecurity_smime/lib/SecCmsEnvelopedData.h; sourceTree = SOURCE_ROOT; }; + 182BB38B146F14D2000BF1F3 /* SecCmsMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsMessage.h; path = libsecurity_smime/lib/SecCmsMessage.h; sourceTree = SOURCE_ROOT; }; + 182BB38C146F14D2000BF1F3 /* SecCmsRecipientInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsRecipientInfo.h; path = libsecurity_smime/lib/SecCmsRecipientInfo.h; sourceTree = SOURCE_ROOT; }; + 182BB38D146F14D2000BF1F3 /* SecCmsSignedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsSignedData.h; path = libsecurity_smime/lib/SecCmsSignedData.h; sourceTree = SOURCE_ROOT; }; + 182BB38E146F14D2000BF1F3 /* SecCmsSignerInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsSignerInfo.h; path = libsecurity_smime/lib/SecCmsSignerInfo.h; sourceTree = SOURCE_ROOT; }; + 182BB38F146F14D2000BF1F3 /* SecSMIME.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecSMIME.h; path = libsecurity_smime/lib/SecSMIME.h; sourceTree = SOURCE_ROOT; }; + 182BB3A3146F1BEC000BF1F3 /* SecDigestTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecDigestTransform.h; path = libsecurity_transform/lib/SecDigestTransform.h; sourceTree = SOURCE_ROOT; }; + 182BB3A4146F1BEC000BF1F3 /* SecReadTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecReadTransform.h; path = libsecurity_transform/lib/SecReadTransform.h; sourceTree = SOURCE_ROOT; }; + 182BB3A5146F1BEC000BF1F3 /* SecTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTransform.h; path = libsecurity_transform/lib/SecTransform.h; sourceTree = SOURCE_ROOT; }; + 182BB3A6146F1BEC000BF1F3 /* SecCustomTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCustomTransform.h; path = libsecurity_transform/lib/SecCustomTransform.h; sourceTree = SOURCE_ROOT; }; + 182BB3A7146F1BEC000BF1F3 /* SecDecodeTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecDecodeTransform.h; path = libsecurity_transform/lib/SecDecodeTransform.h; sourceTree = SOURCE_ROOT; }; + 182BB3A8146F1BEC000BF1F3 /* SecEncodeTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecEncodeTransform.h; path = libsecurity_transform/lib/SecEncodeTransform.h; sourceTree = SOURCE_ROOT; }; + 182BB3A9146F1BEC000BF1F3 /* SecEncryptTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecEncryptTransform.h; path = libsecurity_transform/lib/SecEncryptTransform.h; sourceTree = SOURCE_ROOT; }; + 182BB3AA146F1BEC000BF1F3 /* SecSignVerifyTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecSignVerifyTransform.h; path = libsecurity_transform/lib/SecSignVerifyTransform.h; sourceTree = SOURCE_ROOT; }; + 182BB3AB146F1BEC000BF1F3 /* SecTransformReadTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTransformReadTransform.h; path = libsecurity_transform/lib/SecTransformReadTransform.h; sourceTree = SOURCE_ROOT; }; + 182BB3B6146F1BF9000BF1F3 /* SecNullTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecNullTransform.h; path = libsecurity_transform/lib/SecNullTransform.h; sourceTree = SOURCE_ROOT; }; + 182BB3B7146F1BF9000BF1F3 /* SecTransformInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTransformInternal.h; path = libsecurity_transform/lib/SecTransformInternal.h; sourceTree = SOURCE_ROOT; }; + 182BB3C4146F1DCB000BF1F3 /* sd_cspdl_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = sd_cspdl_common.mdsinfo; path = libsecurity_sd_cspdl/mds/sd_cspdl_common.mdsinfo; sourceTree = SOURCE_ROOT; }; + 182BB556146F4510000BF1F3 /* csparser-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "csparser-Info.plist"; sourceTree = ""; }; + 182BB557146F4510000BF1F3 /* csparser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = csparser.cpp; sourceTree = ""; }; + 182BB558146F4510000BF1F3 /* csparser.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = csparser.exp; sourceTree = ""; }; + 182BB55C146F4544000BF1F3 /* FDEPrefs.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = FDEPrefs.plist; sourceTree = ""; }; + 182BB55D146F4544000BF1F3 /* generateErrStrings.pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = generateErrStrings.pl; sourceTree = ""; }; + 182BB55E146F4544000BF1F3 /* Security.order */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Security.order; sourceTree = ""; }; + 182BB562146F4C73000BF1F3 /* security.exp-in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "security.exp-in"; sourceTree = ""; }; + 182BB568146F4DCA000BF1F3 /* csparser.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = csparser.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; + 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + 182BB593146FE1ED000BF1F3 /* libantlr2c++.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libantlr2c++.a"; path = "/usr/local/lib/libantlr2c++.a"; sourceTree = ""; }; + 182BB5AB146FEF14000BF1F3 /* libpam.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpam.dylib; path = /usr/lib/libpam.dylib; sourceTree = ""; }; + 182BB5AD146FEF43000BF1F3 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = /usr/lib/libsqlite3.dylib; sourceTree = ""; }; + 182BB5B1146FF039000BF1F3 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = ""; }; + 182BB5B3146FF04C000BF1F3 /* libxar.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxar.dylib; path = /usr/lib/libxar.dylib; sourceTree = ""; }; + 182BB5B5146FF08F000BF1F3 /* libauto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libauto.dylib; path = /usr/lib/libauto.dylib; sourceTree = ""; }; + 182BB5B7146FF0A1000BF1F3 /* libobjc.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libobjc.dylib; path = /usr/lib/libobjc.dylib; sourceTree = ""; }; + 182BB5B9146FF0BE000BF1F3 /* libbsm.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbsm.dylib; path = /usr/lib/libbsm.dylib; sourceTree = ""; }; + 1831329914EB2C6D00F0BCAC /* libASN1.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libASN1.a; path = /usr/local/lib/libASN1.a; sourceTree = ""; }; + 1831329A14EB2C6D00F0BCAC /* libDER.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libDER.a; path = /usr/local/lib/libDER.a; sourceTree = ""; }; + 1844605B146DE93E00B12992 /* csp_capabilities.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = csp_capabilities.mdsinfo; path = libsecurity_apple_csp/mds/csp_capabilities.mdsinfo; sourceTree = SOURCE_ROOT; }; + 1844605C146DE93E00B12992 /* csp_capabilities_common.mds */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = csp_capabilities_common.mds; path = libsecurity_apple_csp/mds/csp_capabilities_common.mds; sourceTree = SOURCE_ROOT; }; + 1844605D146DE93E00B12992 /* csp_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = csp_common.mdsinfo; path = libsecurity_apple_csp/mds/csp_common.mdsinfo; sourceTree = SOURCE_ROOT; }; + 1844605E146DE93E00B12992 /* csp_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = csp_primary.mdsinfo; path = libsecurity_apple_csp/mds/csp_primary.mdsinfo; sourceTree = SOURCE_ROOT; }; + 18446099146DFCB700B12992 /* secasn1t.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = secasn1t.h; path = libsecurity_asn1/lib/secasn1t.h; sourceTree = SOURCE_ROOT; }; + 1844609A146DFCB700B12992 /* certExtensionTemplates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = certExtensionTemplates.h; path = libsecurity_asn1/lib/certExtensionTemplates.h; sourceTree = SOURCE_ROOT; }; + 1844609B146DFCB700B12992 /* csrTemplates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = csrTemplates.h; path = libsecurity_asn1/lib/csrTemplates.h; sourceTree = SOURCE_ROOT; }; + 1844609C146DFCB700B12992 /* ocspTemplates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ocspTemplates.h; path = libsecurity_asn1/lib/ocspTemplates.h; sourceTree = SOURCE_ROOT; }; + 1844609D146DFCB700B12992 /* nameTemplates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nameTemplates.h; path = libsecurity_asn1/lib/nameTemplates.h; sourceTree = SOURCE_ROOT; }; + 1844609E146DFCB700B12992 /* X509Templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = X509Templates.h; path = libsecurity_asn1/lib/X509Templates.h; sourceTree = SOURCE_ROOT; }; + 1844609F146DFCB700B12992 /* osKeyTemplates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = osKeyTemplates.h; path = libsecurity_asn1/lib/osKeyTemplates.h; sourceTree = SOURCE_ROOT; }; + 184460A0146DFCB700B12992 /* keyTemplates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = keyTemplates.h; path = libsecurity_asn1/lib/keyTemplates.h; sourceTree = SOURCE_ROOT; }; + 184460A1146DFCB700B12992 /* asn1Templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = asn1Templates.h; path = libsecurity_asn1/lib/asn1Templates.h; sourceTree = SOURCE_ROOT; }; + 184460AB146DFCC100B12992 /* SecAsn1Coder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecAsn1Coder.h; path = libsecurity_asn1/lib/SecAsn1Coder.h; sourceTree = SOURCE_ROOT; }; + 184460AC146DFCC100B12992 /* SecAsn1Templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecAsn1Templates.h; path = libsecurity_asn1/lib/SecAsn1Templates.h; sourceTree = SOURCE_ROOT; }; + 184460AD146DFCC100B12992 /* SecAsn1Types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecAsn1Types.h; path = libsecurity_asn1/lib/SecAsn1Types.h; sourceTree = SOURCE_ROOT; }; + 184460C3146E7B1E00B12992 /* cspdl_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = cspdl_common.mdsinfo; path = libsecurity_apple_cspdl/mds/cspdl_common.mdsinfo; sourceTree = SOURCE_ROOT; }; + 184460C4146E7B1E00B12992 /* cspdl_csp_capabilities.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = cspdl_csp_capabilities.mdsinfo; path = libsecurity_apple_cspdl/mds/cspdl_csp_capabilities.mdsinfo; sourceTree = SOURCE_ROOT; }; + 184460C5146E7B1E00B12992 /* cspdl_csp_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = cspdl_csp_primary.mdsinfo; path = libsecurity_apple_cspdl/mds/cspdl_csp_primary.mdsinfo; sourceTree = SOURCE_ROOT; }; + 184460C6146E7B1E00B12992 /* cspdl_dl_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = cspdl_dl_primary.mdsinfo; path = libsecurity_apple_cspdl/mds/cspdl_dl_primary.mdsinfo; sourceTree = SOURCE_ROOT; }; + 184460E1146E806700B12992 /* dl_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = dl_common.mdsinfo; path = libsecurity_apple_file_dl/mds/dl_common.mdsinfo; sourceTree = SOURCE_ROOT; }; + 184460E2146E806700B12992 /* dl_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = dl_primary.mdsinfo; path = libsecurity_apple_file_dl/mds/dl_primary.mdsinfo; sourceTree = SOURCE_ROOT; }; + 18446103146E82C800B12992 /* cl_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = cl_common.mdsinfo; path = libsecurity_apple_x509_cl/mds/cl_common.mdsinfo; sourceTree = SOURCE_ROOT; }; + 18446104146E82C800B12992 /* cl_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = cl_primary.mdsinfo; path = libsecurity_apple_x509_cl/mds/cl_primary.mdsinfo; sourceTree = SOURCE_ROOT; }; + 18446112146E85A300B12992 /* tp_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = tp_common.mdsinfo; path = libsecurity_apple_x509_tp/mds/tp_common.mdsinfo; sourceTree = SOURCE_ROOT; }; + 18446113146E85A300B12992 /* tp_policyOids.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = tp_policyOids.mdsinfo; path = libsecurity_apple_x509_tp/mds/tp_policyOids.mdsinfo; sourceTree = SOURCE_ROOT; }; + 18446114146E85A300B12992 /* tp_primary.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = tp_primary.mdsinfo; path = libsecurity_apple_x509_tp/mds/tp_primary.mdsinfo; sourceTree = SOURCE_ROOT; }; + 18446144146E923200B12992 /* AuthorizationTags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AuthorizationTags.h; path = libsecurity_authorization/lib/AuthorizationTags.h; sourceTree = SOURCE_ROOT; }; + 18446145146E923200B12992 /* AuthSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AuthSession.h; path = libsecurity_authorization/lib/AuthSession.h; sourceTree = SOURCE_ROOT; }; + 18446146146E923200B12992 /* Authorization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Authorization.h; path = libsecurity_authorization/lib/Authorization.h; sourceTree = SOURCE_ROOT; }; + 18446147146E923200B12992 /* AuthorizationDB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AuthorizationDB.h; path = libsecurity_authorization/lib/AuthorizationDB.h; sourceTree = SOURCE_ROOT; }; + 18446148146E923200B12992 /* AuthorizationPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AuthorizationPlugin.h; path = libsecurity_authorization/lib/AuthorizationPlugin.h; sourceTree = SOURCE_ROOT; }; + 1844614E146E923B00B12992 /* AuthorizationTagsPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AuthorizationTagsPriv.h; path = libsecurity_authorization/lib/AuthorizationTagsPriv.h; sourceTree = SOURCE_ROOT; }; + 1844614F146E923B00B12992 /* AuthorizationPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AuthorizationPriv.h; path = libsecurity_authorization/lib/AuthorizationPriv.h; sourceTree = SOURCE_ROOT; }; + 18446168146E95D700B12992 /* checkpw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkpw.h; path = libsecurity_checkpw/lib/checkpw.h; sourceTree = SOURCE_ROOT; }; + 18446170146E982800B12992 /* CMSDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CMSDecoder.h; path = libsecurity_cms/lib/CMSDecoder.h; sourceTree = SOURCE_ROOT; }; + 18446171146E982800B12992 /* CMSEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CMSEncoder.h; path = libsecurity_cms/lib/CMSEncoder.h; sourceTree = SOURCE_ROOT; }; + 18446174146E982D00B12992 /* CMSPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CMSPrivate.h; path = libsecurity_cms/lib/CMSPrivate.h; sourceTree = SOURCE_ROOT; }; + 1844617E146E9A8500B12992 /* SecTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTask.h; path = libsecurity_codesigning/lib/SecTask.h; sourceTree = SOURCE_ROOT; }; + 1844617F146E9A8500B12992 /* CodeSigning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CodeSigning.h; path = libsecurity_codesigning/lib/CodeSigning.h; sourceTree = SOURCE_ROOT; }; + 18446180146E9A8500B12992 /* CSCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSCommon.h; path = libsecurity_codesigning/lib/CSCommon.h; sourceTree = SOURCE_ROOT; }; + 18446181146E9A8500B12992 /* SecCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCode.h; path = libsecurity_codesigning/lib/SecCode.h; sourceTree = SOURCE_ROOT; }; + 18446182146E9A8500B12992 /* SecStaticCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecStaticCode.h; path = libsecurity_codesigning/lib/SecStaticCode.h; sourceTree = SOURCE_ROOT; }; + 18446183146E9A8500B12992 /* SecRequirement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecRequirement.h; path = libsecurity_codesigning/lib/SecRequirement.h; sourceTree = SOURCE_ROOT; }; + 18446184146E9A8500B12992 /* SecCodeHost.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCodeHost.h; path = libsecurity_codesigning/lib/SecCodeHost.h; sourceTree = SOURCE_ROOT; }; + 1844618C146E9A8F00B12992 /* CSCommonPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSCommonPriv.h; path = libsecurity_codesigning/lib/CSCommonPriv.h; sourceTree = SOURCE_ROOT; }; + 1844618D146E9A8F00B12992 /* SecCodePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCodePriv.h; path = libsecurity_codesigning/lib/SecCodePriv.h; sourceTree = SOURCE_ROOT; }; + 1844618E146E9A8F00B12992 /* SecStaticCodePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecStaticCodePriv.h; path = libsecurity_codesigning/lib/SecStaticCodePriv.h; sourceTree = SOURCE_ROOT; }; + 1844618F146E9A8F00B12992 /* SecRequirementPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecRequirementPriv.h; path = libsecurity_codesigning/lib/SecRequirementPriv.h; sourceTree = SOURCE_ROOT; }; + 18446190146E9A8F00B12992 /* SecCodeSigner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCodeSigner.h; path = libsecurity_codesigning/lib/SecCodeSigner.h; sourceTree = SOURCE_ROOT; }; + 18446191146E9A8F00B12992 /* SecIntegrity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecIntegrity.h; path = libsecurity_codesigning/lib/SecIntegrity.h; sourceTree = SOURCE_ROOT; }; + 18446192146E9A8F00B12992 /* SecIntegrityLib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecIntegrityLib.h; path = libsecurity_codesigning/lib/SecIntegrityLib.h; sourceTree = SOURCE_ROOT; }; + 18446193146E9A8F00B12992 /* SecCodeHostLib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCodeHostLib.h; path = libsecurity_codesigning/lib/SecCodeHostLib.h; sourceTree = SOURCE_ROOT; }; + 18446194146E9A8F00B12992 /* SecAssessment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecAssessment.h; path = libsecurity_codesigning/lib/SecAssessment.h; sourceTree = SOURCE_ROOT; }; + 184461A3146E9D3200B12992 /* libsecurityd.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurityd.xcodeproj; path = libsecurityd/libsecurityd.xcodeproj; sourceTree = ""; }; + 18500F9A14708D0E006F9AB4 /* SecDebugErrorMessages.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = SecDebugErrorMessages.strings; path = derived_src/SecDebugErrorMessages.strings; sourceTree = BUILT_PRODUCTS_DIR; }; + 18500FA014708F19006F9AB4 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = derived_src/en.lproj/SecErrorMessages.strings; sourceTree = BUILT_PRODUCTS_DIR; }; + 186CDD1614CA11C700AF9171 /* sec.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = sec.xcodeproj; sourceTree = ""; }; + 18752C1D16F2837A004E2799 /* libaks.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libaks.a; path = usr/local/lib/libaks.a; sourceTree = SDKROOT; }; + 1879B4A9146DCA18007E536C /* cssm.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = cssm.mdsinfo; path = libsecurity_cssm/mds/cssm.mdsinfo; sourceTree = SOURCE_ROOT; }; + 1879B4AB146DCA4A007E536C /* cssmapplePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmapplePriv.h; path = libsecurity_cssm/lib/cssmapplePriv.h; sourceTree = SOURCE_ROOT; }; + 1879B4AD146DCA84007E536C /* certextensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = certextensions.h; path = libsecurity_cssm/lib/certextensions.h; sourceTree = SOURCE_ROOT; }; + 1879B4AE146DCA84007E536C /* cssm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssm.h; path = libsecurity_cssm/lib/cssm.h; sourceTree = SOURCE_ROOT; }; + 1879B4AF146DCA84007E536C /* cssmaci.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmaci.h; path = libsecurity_cssm/lib/cssmaci.h; sourceTree = SOURCE_ROOT; }; + 1879B4B0146DCA84007E536C /* cssmapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmapi.h; path = libsecurity_cssm/lib/cssmapi.h; sourceTree = SOURCE_ROOT; }; + 1879B4B1146DCA84007E536C /* cssmapple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmapple.h; path = libsecurity_cssm/lib/cssmapple.h; sourceTree = SOURCE_ROOT; }; + 1879B4B2146DCA84007E536C /* cssmcli.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmcli.h; path = libsecurity_cssm/lib/cssmcli.h; sourceTree = SOURCE_ROOT; }; + 1879B4B3146DCA84007E536C /* cssmconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmconfig.h; path = libsecurity_cssm/lib/cssmconfig.h; sourceTree = SOURCE_ROOT; }; + 1879B4B4146DCA84007E536C /* cssmcspi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmcspi.h; path = libsecurity_cssm/lib/cssmcspi.h; sourceTree = SOURCE_ROOT; }; + 1879B4B5146DCA84007E536C /* cssmdli.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmdli.h; path = libsecurity_cssm/lib/cssmdli.h; sourceTree = SOURCE_ROOT; }; + 1879B4B6146DCA84007E536C /* cssmerr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmerr.h; path = libsecurity_cssm/lib/cssmerr.h; sourceTree = SOURCE_ROOT; }; + 1879B4B7146DCA84007E536C /* cssmkrapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmkrapi.h; path = libsecurity_cssm/lib/cssmkrapi.h; sourceTree = SOURCE_ROOT; }; + 1879B4B8146DCA84007E536C /* cssmkrspi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmkrspi.h; path = libsecurity_cssm/lib/cssmkrspi.h; sourceTree = SOURCE_ROOT; }; + 1879B4B9146DCA84007E536C /* cssmspi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmspi.h; path = libsecurity_cssm/lib/cssmspi.h; sourceTree = SOURCE_ROOT; }; + 1879B4BA146DCA84007E536C /* cssmtpi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmtpi.h; path = libsecurity_cssm/lib/cssmtpi.h; sourceTree = SOURCE_ROOT; }; + 1879B4BB146DCA84007E536C /* cssmtype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cssmtype.h; path = libsecurity_cssm/lib/cssmtype.h; sourceTree = SOURCE_ROOT; }; + 1879B4BC146DCA84007E536C /* eisl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eisl.h; path = libsecurity_cssm/lib/eisl.h; sourceTree = SOURCE_ROOT; }; + 1879B4BD146DCA84007E536C /* emmspi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = emmspi.h; path = libsecurity_cssm/lib/emmspi.h; sourceTree = SOURCE_ROOT; }; + 1879B4BE146DCA84007E536C /* emmtype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = emmtype.h; path = libsecurity_cssm/lib/emmtype.h; sourceTree = SOURCE_ROOT; }; + 1879B4C1146DCA84007E536C /* oidsbase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = oidsbase.h; path = libsecurity_cssm/lib/oidsbase.h; sourceTree = SOURCE_ROOT; }; + 1879B4C2146DCA84007E536C /* oidscert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = oidscert.h; path = libsecurity_cssm/lib/oidscert.h; sourceTree = SOURCE_ROOT; }; + 1879B4C3146DCA84007E536C /* oidscrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = oidscrl.h; path = libsecurity_cssm/lib/oidscrl.h; sourceTree = SOURCE_ROOT; }; + 1879B4C4146DCA84007E536C /* x509defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = x509defs.h; path = libsecurity_cssm/lib/x509defs.h; sourceTree = SOURCE_ROOT; }; + 1879B532146DDBE5007E536C /* libsecurity_utilities.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_utilities.xcodeproj; path = libsecurity_utilities/libsecurity_utilities.xcodeproj; sourceTree = ""; }; + 1879B547146DE212007E536C /* libsecurity_cdsa_utils.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cdsa_utils.xcodeproj; path = libsecurity_cdsa_utils/libsecurity_cdsa_utils.xcodeproj; sourceTree = ""; }; + 1879B550146DE227007E536C /* libsecurity_cdsa_utilities.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cdsa_utilities.xcodeproj; path = libsecurity_cdsa_utilities/libsecurity_cdsa_utilities.xcodeproj; sourceTree = ""; }; + 1879B55D146DE244007E536C /* libsecurity_cssm.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cssm.xcodeproj; path = libsecurity_cssm/libsecurity_cssm.xcodeproj; sourceTree = ""; }; + 1879B5BC146DE6C8007E536C /* libsecurity_apple_csp.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_apple_csp.xcodeproj; path = libsecurity_apple_csp/libsecurity_apple_csp.xcodeproj; sourceTree = ""; }; + 1879B5C9146DE6CE007E536C /* libsecurity_apple_cspdl.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_apple_cspdl.xcodeproj; path = libsecurity_apple_cspdl/libsecurity_apple_cspdl.xcodeproj; sourceTree = ""; }; + 1879B5D5146DE6D7007E536C /* libsecurity_apple_file_dl.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_apple_file_dl.xcodeproj; path = libsecurity_apple_file_dl/libsecurity_apple_file_dl.xcodeproj; sourceTree = ""; }; + 1879B5E1146DE6E7007E536C /* libsecurity_apple_x509_cl.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_apple_x509_cl.xcodeproj; path = libsecurity_apple_x509_cl/libsecurity_apple_x509_cl.xcodeproj; sourceTree = ""; }; + 1879B5F0146DE6FD007E536C /* libsecurity_apple_x509_tp.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_apple_x509_tp.xcodeproj; path = libsecurity_apple_x509_tp/libsecurity_apple_x509_tp.xcodeproj; sourceTree = ""; }; + 1879B5FC146DE704007E536C /* libsecurity_asn1.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_asn1.xcodeproj; path = libsecurity_asn1/libsecurity_asn1.xcodeproj; sourceTree = ""; }; + 1879B609146DE70A007E536C /* libsecurity_authorization.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_authorization.xcodeproj; path = libsecurity_authorization/libsecurity_authorization.xcodeproj; sourceTree = ""; }; + 1879B615146DE715007E536C /* libsecurity_cdsa_client.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cdsa_client.xcodeproj; path = libsecurity_cdsa_client/libsecurity_cdsa_client.xcodeproj; sourceTree = ""; }; + 1879B621146DE720007E536C /* libsecurity_cdsa_plugin.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cdsa_plugin.xcodeproj; path = libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj; sourceTree = ""; }; + 1879B637146DE748007E536C /* libsecurity_checkpw.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_checkpw.xcodeproj; path = libsecurity_checkpw/libsecurity_checkpw.xcodeproj; sourceTree = ""; }; + 1879B64B146DE750007E536C /* libsecurity_cms.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cms.xcodeproj; path = libsecurity_cms/libsecurity_cms.xcodeproj; sourceTree = ""; }; + 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_codesigning.xcodeproj; path = libsecurity_codesigning/libsecurity_codesigning.xcodeproj; sourceTree = ""; }; + 1879B66D146DE75D007E536C /* libsecurity_comcryption.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_comcryption.xcodeproj; path = libsecurity_comcryption/libsecurity_comcryption.xcodeproj; sourceTree = ""; }; + 1879B679146DE76E007E536C /* libsecurity_cryptkit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cryptkit.xcodeproj; path = libsecurity_cryptkit/libsecurity_cryptkit.xcodeproj; sourceTree = ""; }; + 1879B694146DE797007E536C /* libsecurity_filedb.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_filedb.xcodeproj; path = libsecurity_filedb/libsecurity_filedb.xcodeproj; sourceTree = ""; }; + 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_keychain.xcodeproj; path = libsecurity_keychain/libsecurity_keychain.xcodeproj; sourceTree = ""; }; + 1879B6C7146DE7D7007E536C /* libsecurity_manifest.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_manifest.xcodeproj; path = libsecurity_manifest/libsecurity_manifest.xcodeproj; sourceTree = ""; }; + 1879B6D3146DE7E0007E536C /* libsecurity_mds.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_mds.xcodeproj; path = libsecurity_mds/libsecurity_mds.xcodeproj; sourceTree = ""; }; + 1879B6DF146DE7E7007E536C /* libsecurity_ocspd.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_ocspd.xcodeproj; path = libsecurity_ocspd/libsecurity_ocspd.xcodeproj; sourceTree = ""; }; + 1879B6EC146DE7EE007E536C /* libsecurity_pkcs12.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_pkcs12.xcodeproj; path = libsecurity_pkcs12/libsecurity_pkcs12.xcodeproj; sourceTree = ""; }; + 1879B6F8146DE7F7007E536C /* libsecurity_sd_cspdl.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_sd_cspdl.xcodeproj; path = libsecurity_sd_cspdl/libsecurity_sd_cspdl.xcodeproj; sourceTree = ""; }; + 1879B712146DE825007E536C /* libsecurity_smime.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_smime.xcodeproj; path = libsecurity_smime/libsecurity_smime.xcodeproj; sourceTree = ""; }; + 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_ssl.xcodeproj; path = libsecurity_ssl/libsecurity_ssl.xcodeproj; sourceTree = ""; }; + 1879B72B146DE844007E536C /* libsecurity_transform.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_transform.xcodeproj; path = libsecurity_transform/libsecurity_transform.xcodeproj; sourceTree = ""; }; + 187D6B9015D4359F00E27494 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/authorization.buttons.strings; sourceTree = ""; }; + 187D6B9215D4359F00E27494 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/authorization.prompts.strings; sourceTree = ""; }; + 187D6B9515D436BF00E27494 /* authorization.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = authorization.plist; sourceTree = ""; }; + 188AD8D91471FE3D0081C619 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/FDELocalizable.strings; sourceTree = ""; }; + 188AD8DB1471FE3E0081C619 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 18A5493115EFD2F40059E6DC /* dummy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dummy.cpp; sourceTree = ""; }; + 18B647E814D9EB6300F538BF /* oidsalg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = oidsalg.h; path = ../libsecurity_asn1/lib/oidsalg.h; sourceTree = ""; }; + 18B647EA14D9EE4300F538BF /* oidsattr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = oidsattr.h; path = ../libsecurity_asn1/lib/oidsattr.h; sourceTree = ""; }; + 18B647EF14D9F75300F538BF /* generateErrStrings.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = generateErrStrings.mm; path = derived_src/generateErrStrings.mm; sourceTree = BUILT_PRODUCTS_DIR; }; + 18BBC6801471EF1600F2B224 /* security.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = security.xcconfig; sourceTree = ""; }; + 18BBC7351471F5A300F2B224 /* SecExternalSourceTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecExternalSourceTransform.h; path = libsecurity_transform/lib/SecExternalSourceTransform.h; sourceTree = SOURCE_ROOT; }; + 18BEB19614CF74C100C8BD36 /* com.apple.secd.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.secd.plist; sourceTree = ""; }; + 18BFC44017C43393005DE6C3 /* executable.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = executable.xcconfig; sourceTree = ""; }; + 18CFEE8715DEE25200E3F2A3 /* com.apple.authd.sb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = com.apple.authd.sb; sourceTree = ""; }; + 18D6803916B768D500DF6D2E /* com.apple.authd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = com.apple.authd; sourceTree = ""; }; + 18ED4D2317270DB6003AF11B /* SecurityTests-Entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SecurityTests-Entitlements.plist"; sourceTree = ""; }; + 18F234EB15C9F9A600060520 /* authd.xpc */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = authd.xpc; sourceTree = BUILT_PRODUCTS_DIR; }; + 18F234F915C9FA3B00060520 /* agent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = agent.c; sourceTree = ""; }; + 18F234FA15C9FA3B00060520 /* agent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = agent.h; sourceTree = ""; }; + 18F234FB15C9FA3B00060520 /* authdb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = authdb.c; sourceTree = ""; }; + 18F234FC15C9FA3B00060520 /* authdb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = authdb.h; sourceTree = ""; }; + 18F234FD15C9FA3B00060520 /* authitems.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = authitems.c; sourceTree = ""; }; + 18F234FE15C9FA3B00060520 /* authitems.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = authitems.h; sourceTree = ""; }; + 18F234FF15C9FA3B00060520 /* authtoken.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = authtoken.c; sourceTree = ""; }; + 18F2350015C9FA3B00060520 /* authtoken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = authtoken.h; sourceTree = ""; }; + 18F2350115C9FA3B00060520 /* authtypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = authtypes.h; sourceTree = ""; }; + 18F2350215C9FA3B00060520 /* authutilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = authutilities.c; sourceTree = ""; }; + 18F2350315C9FA3B00060520 /* authutilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = authutilities.h; sourceTree = ""; }; + 18F2350415C9FA3B00060520 /* ccaudit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ccaudit.c; sourceTree = ""; }; + 18F2350515C9FA3B00060520 /* ccaudit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ccaudit.h; sourceTree = ""; }; + 18F2350615C9FA3B00060520 /* crc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = crc.c; sourceTree = ""; }; + 18F2350715C9FA3B00060520 /* crc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crc.h; sourceTree = ""; }; + 18F2350815C9FA3B00060520 /* credential.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = credential.c; sourceTree = ""; }; + 18F2350915C9FA3B00060520 /* credential.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = credential.h; sourceTree = ""; }; + 18F2350A15C9FA3B00060520 /* debugging.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = debugging.c; sourceTree = ""; }; + 18F2350B15C9FA3B00060520 /* debugging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debugging.h; sourceTree = ""; }; + 18F2350E15C9FA3B00060520 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = InfoPlist.strings; sourceTree = ""; }; + 18F2350F15C9FA3B00060520 /* engine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = engine.c; sourceTree = ""; }; + 18F2351015C9FA3B00060520 /* engine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = engine.h; sourceTree = ""; }; + 18F2351115C9FA3B00060520 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 18F2351215C9FA3B00060520 /* mechanism.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mechanism.c; sourceTree = ""; }; + 18F2351315C9FA3B00060520 /* mechanism.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mechanism.h; sourceTree = ""; }; + 18F2351415C9FA3C00060520 /* object.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = object.c; sourceTree = ""; }; + 18F2351515C9FA3C00060520 /* object.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = object.h; sourceTree = ""; }; + 18F2351615C9FA3C00060520 /* process.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = process.c; sourceTree = ""; }; + 18F2351715C9FA3C00060520 /* process.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = process.h; sourceTree = ""; }; + 18F2351815C9FA3C00060520 /* rule.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rule.c; sourceTree = ""; }; + 18F2351915C9FA3C00060520 /* rule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rule.h; sourceTree = ""; }; + 18F2351A15C9FA3C00060520 /* authd_private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = authd_private.h; sourceTree = ""; }; + 18F2351B15C9FA3C00060520 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 18F2351C15C9FA3C00060520 /* security.auth-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "security.auth-Prefix.pch"; sourceTree = ""; }; + 18F2351D15C9FA3C00060520 /* server.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = server.c; sourceTree = ""; }; + 18F2351E15C9FA3C00060520 /* server.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = server.h; sourceTree = ""; }; + 18F2351F15C9FA3C00060520 /* session.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = session.c; sourceTree = ""; }; + 18F2352015C9FA3C00060520 /* session.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = session.h; sourceTree = ""; }; + 18F235F515CA0D8100060520 /* libsecurity_cdsa_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_cdsa_utilities.a; path = /usr/local/lib/libsecurity_cdsa_utilities.a; sourceTree = ""; }; + 18F235F715CA0D9D00060520 /* libsecurity_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_utilities.a; path = /usr/local/lib/libsecurity_utilities.a; sourceTree = ""; }; + 18F235F915CA0DB000060520 /* libsecurity_agent_client.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_agent_client.a; path = /usr/local/lib/libsecurity_agent_client.a; sourceTree = ""; }; + 18F235FC15CA0EDB00060520 /* libstdc++.6.0.9.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libstdc++.6.0.9.dylib"; path = "/usr/lib/libstdc++.6.0.9.dylib"; sourceTree = ""; }; + 18F2360015CAF41100060520 /* libsecurity_codesigning.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_codesigning.a; path = /usr/local/lib/libsecurity_codesigning.a; sourceTree = ""; }; + 18FE67EA1471A3AA00A2CBE3 /* Security.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Security.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 37A7CEAB197DB8FA00926CE8 /* codesign_tests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = codesign_tests; sourceTree = BUILT_PRODUCTS_DIR; }; + 37A7CEAD197DB8FA00926CE8 /* FatDynamicValidation.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = FatDynamicValidation.c; sourceTree = ""; }; + 37A7CEDB197DCDD700926CE8 /* validation.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = validation.sh; sourceTree = ""; }; + 395E7CED16C64EA500CD82A4 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + 44B2603E18F81A6A008DF20F /* SecAccessControl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SecAccessControl.h; path = sec/Security/SecAccessControl.h; sourceTree = SOURCE_ROOT; }; + 44B2606918F81BFE008DF20F /* SecAccessControlPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SecAccessControlPriv.h; path = sec/Security/SecAccessControlPriv.h; sourceTree = SOURCE_ROOT; }; + 4C0F6F861985877800178101 /* SecEntitlements.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecEntitlements.h; sourceTree = ""; }; + 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = utilities.xcodeproj; sourceTree = ""; }; + 4C2505B616D2DF9F002CE025 /* Icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = Icon.icns; sourceTree = ""; }; + 4C328D2F1778EC4F0015EED1 /* AOSUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AOSUI.framework; path = ../../../../../../../System/Library/PrivateFrameworks/AOSUI.framework; sourceTree = ""; }; + 4C49390C16E51ACE00CE110C /* com.apple.security.keychain-circle-notification.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "com.apple.security.keychain-circle-notification.plist"; sourceTree = ""; }; + 4C5DD44217A5E31900696A79 /* KNPersistantState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KNPersistantState.h; sourceTree = ""; }; + 4C5DD44317A5E31900696A79 /* KNPersistantState.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KNPersistantState.m; sourceTree = ""; }; + 4C5DD46B17A5F67300696A79 /* AppleSystemInfo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppleSystemInfo.framework; path = ../../../../../../../System/Library/PrivateFrameworks/AppleSystemInfo.framework; sourceTree = ""; }; + 4C7D453B17BEE69B00DDD88F /* NSString+compactDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+compactDescription.h"; sourceTree = ""; }; + 4C7D453C17BEE69B00DDD88F /* NSString+compactDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+compactDescription.m"; sourceTree = ""; }; + 4C7D456417BEE6B700DDD88F /* NSDictionary+compactDescription.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+compactDescription.h"; sourceTree = ""; }; + 4C7D456517BEE6B700DDD88F /* NSDictionary+compactDescription.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+compactDescription.m"; sourceTree = ""; }; + 4C7D456617BEE6B700DDD88F /* NSSet+compactDescription.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSSet+compactDescription.h"; sourceTree = ""; }; + 4C7D456717BEE6B700DDD88F /* NSSet+compactDescription.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSSet+compactDescription.m"; sourceTree = ""; }; + 4C85DED816DBD5BF00ED8D47 /* KDCirclePeer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KDCirclePeer.h; sourceTree = ""; }; + 4C85DED916DBD5BF00ED8D47 /* KDCirclePeer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KDCirclePeer.m; sourceTree = ""; }; + 4C96F73816D5372C00D3B39D /* KDSecCircle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KDSecCircle.h; sourceTree = ""; }; + 4C96F73916D5372C00D3B39D /* KDSecCircle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KDSecCircle.m; sourceTree = ""; }; + 4C96F76116D54C9600D3B39D /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; }; + 4C96F7C116D6DF8300D3B39D /* Keychain Circle Notification.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Keychain Circle Notification.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C96F7C516D6DF8400D3B39D /* Keychain Circle Notification-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Keychain Circle Notification-Info.plist"; sourceTree = ""; }; + 4C96F7C716D6DF8400D3B39D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 4C96F7C916D6DF8400D3B39D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 4C96F7CB16D6DF8400D3B39D /* Keychain Circle Notification-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Keychain Circle Notification-Prefix.pch"; sourceTree = ""; }; + 4C96F7CD16D6DF8400D3B39D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; + 4C96F7CF16D6DF8400D3B39D /* KNAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KNAppDelegate.h; sourceTree = ""; }; + 4C96F7D016D6DF8400D3B39D /* KNAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KNAppDelegate.m; sourceTree = ""; }; + 4C96F7D316D6DF8400D3B39D /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; + 4C97761D17BEB23E0002BFE4 /* AOSAccounts.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AOSAccounts.framework; path = ../../../../../../../System/Library/PrivateFrameworks/AOSAccounts.framework; sourceTree = ""; }; + 4CB23B46169F5873003A0131 /* security2 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = security2; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CB23B4B169F5873003A0131 /* security2.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = security2.1; sourceTree = ""; }; + 4CB23B80169F58DE003A0131 /* security_tool_commands.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = security_tool_commands.c; sourceTree = ""; }; + 4CB23B82169F592C003A0131 /* sub_commands.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sub_commands.h; sourceTree = ""; }; + 4CB23B91169F5CFF003A0131 /* command.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = command.xcconfig; sourceTree = ""; }; + 4CB86AE6167A6FF200F46643 /* SOSCircle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSCircle.h; path = ../sec/SOSCircle/SecureObjectSync/SOSCircle.h; sourceTree = ""; }; + 4CB86AE7167A6FF200F46643 /* SOSCloudCircle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSCloudCircle.h; path = ../sec/SOSCircle/SecureObjectSync/SOSCloudCircle.h; sourceTree = ""; }; + 4CB86AE8167A6FF200F46643 /* SOSCloudCircleInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSCloudCircleInternal.h; path = ../sec/SOSCircle/SecureObjectSync/SOSCloudCircleInternal.h; sourceTree = ""; }; + 4CB86AE9167A6FF200F46643 /* SOSEngine.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSEngine.h; path = ../sec/SOSCircle/SecureObjectSync/SOSEngine.h; sourceTree = ""; }; + 4CB86AEA167A6FF300F46643 /* SOSFullPeerInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSFullPeerInfo.h; path = ../sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.h; sourceTree = ""; }; + 4CB86AEB167A6FF300F46643 /* SOSInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSInternal.h; path = ../sec/SOSCircle/SecureObjectSync/SOSInternal.h; sourceTree = ""; }; + 4CB86AEC167A6FF300F46643 /* SOSPeer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSPeer.h; path = ../sec/SOSCircle/SecureObjectSync/SOSPeer.h; sourceTree = ""; }; + 4CB86AED167A6FF300F46643 /* SOSPeerInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSPeerInfo.h; path = ../sec/SOSCircle/SecureObjectSync/SOSPeerInfo.h; sourceTree = ""; }; + 4CB86AEE167A6FF300F46643 /* SOSTransport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSTransport.h; path = ../sec/SOSCircle/SecureObjectSync/SOSTransport.h; sourceTree = ""; }; + 4CB86AFA167A8F2200F46643 /* SOSAccount.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SOSAccount.h; path = ../sec/SOSCircle/SecureObjectSync/SOSAccount.h; sourceTree = ""; }; + 4CB9121C17750E6500C1CCCA /* entitlments.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = entitlments.plist; sourceTree = ""; }; + 4CC7A7B316CC2A84003E10C1 /* Cloud Keychain Utility.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Cloud Keychain Utility.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CC7A7B716CC2A85003E10C1 /* Keychain-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Keychain-Info.plist"; sourceTree = ""; }; + 4CC7A7B916CC2A85003E10C1 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 4CC7A7BB16CC2A85003E10C1 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 4CC7A7BD16CC2A85003E10C1 /* Keychain-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Keychain-Prefix.pch"; sourceTree = ""; }; + 4CC7A7BF16CC2A85003E10C1 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; + 4CC7A7C116CC2A85003E10C1 /* KDAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KDAppDelegate.h; sourceTree = ""; }; + 4CC7A7C216CC2A85003E10C1 /* KDAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KDAppDelegate.m; sourceTree = ""; }; + 4CC7A7C516CC2A85003E10C1 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; + 4CC7A7F216CC2B0A003E10C1 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; + 4CC7A7F416CD95D2003E10C1 /* KDSecItems.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KDSecItems.h; sourceTree = ""; }; + 4CC7A7F516CD95D3003E10C1 /* KDSecItems.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KDSecItems.m; sourceTree = ""; }; + 4CD1980B16DD3BDF00A9E8FD /* NSArray+mapWithBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+mapWithBlock.h"; path = "Keychain Circle Notification/NSArray+mapWithBlock.h"; sourceTree = SOURCE_ROOT; }; + 4CD1980C16DD3BDF00A9E8FD /* NSArray+mapWithBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+mapWithBlock.m"; path = "Keychain Circle Notification/NSArray+mapWithBlock.m"; sourceTree = SOURCE_ROOT; }; + 4CF42BB515A3947F00ACACE1 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = ""; }; + 5214700616977CB800DF0DB3 /* CloudKeychainProxy.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CloudKeychainProxy.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; + 5214700716977CB800DF0DB3 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + 5214700A16977CB800DF0DB3 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + 5214700B16977CB800DF0DB3 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; + 5214700C16977CB800DF0DB3 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 5214700F16977CB800DF0DB3 /* CloudKeychainProxy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "CloudKeychainProxy-Info.plist"; sourceTree = ""; }; + 5214701116977CB800DF0DB3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 5214702416977FEC00DF0DB3 /* cloudkeychain.entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = cloudkeychain.entitlements.plist; sourceTree = ""; }; + 5214702516977FEC00DF0DB3 /* com.apple.security.cloudkeychainproxy.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.security.cloudkeychainproxy.plist; sourceTree = ""; }; + 52AEA484153C7581005AFC59 /* tsaSupportPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tsaSupportPriv.h; path = libsecurity_smime/lib/tsaSupportPriv.h; sourceTree = SOURCE_ROOT; }; + 52B006BF15238F76005D4556 /* TimeStampingPrefs.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = TimeStampingPrefs.plist; sourceTree = ""; }; + 52B5A9C01519330300664F11 /* tsaSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = tsaSupport.h; path = libsecurity_smime/lib/tsaSupport.h; sourceTree = SOURCE_ROOT; }; + 52B5A9C11519330300664F11 /* tsaTemplates.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = tsaTemplates.h; path = libsecurity_smime/lib/tsaTemplates.h; sourceTree = SOURCE_ROOT; }; + 52C3D235169B56860091D9D3 /* ckdmain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ckdmain.m; path = sec/SOSCircle/CloudKeychainProxy/ckdmain.m; sourceTree = SOURCE_ROOT; }; + 5328475217850741009118DC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; + 5E27BBFA18F4103100B6C79A /* libcoreauthd_client.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcoreauthd_client.a; path = usr/local/lib/libcoreauthd_client.a; sourceTree = SDKROOT; }; + 5E3A07061962B0B000463F09 /* libaks_acl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libaks_acl.a; path = usr/local/lib/libaks_acl.a; sourceTree = ""; }; + 5E48A8E91907893C0011BC31 /* libaks_acl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libaks_acl.a; path = usr/local/lib/libaks_acl.a; sourceTree = ""; }; + 5E8ADED1190A2E380012271C /* libaks_acl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libaks_acl.a; path = usr/local/lib/libaks_acl.a; sourceTree = ""; }; + 721680A8179B40F600406BB4 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 721680AA179B40F600406BB4 /* iCloudStats.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = iCloudStats.1; sourceTree = ""; }; + 721680BD179B4F9100406BB4 /* com.apple.iCloudStats.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.iCloudStats.plist; sourceTree = ""; }; + 722CF215175D5E5000BCE0A5 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.Internal.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; + 72756BFE175D485D00F52070 /* cloud_keychain_diagnose */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = cloud_keychain_diagnose; sourceTree = BUILT_PRODUCTS_DIR; }; + 72756C04175D485D00F52070 /* cloud_keychain_diagnose-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "cloud_keychain_diagnose-Prefix.pch"; sourceTree = ""; }; + 72756C30175D48C100F52070 /* cloud_keychain_diagnose.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cloud_keychain_diagnose.c; path = utilities/src/cloud_keychain_diagnose.c; sourceTree = SOURCE_ROOT; }; + 72756C9A175D51B100F52070 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/IOKit.framework; sourceTree = DEVELOPER_DIR; }; + 72756C9C175D51C900F52070 /* Kernel.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Kernel.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/Kernel.framework; sourceTree = DEVELOPER_DIR; }; + 72756C9E175D566800F52070 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.Internal.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; }; + 72A3DE5B179B2C0400E78247 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.Internal.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + AC5688BA18B4396D00F0526C /* SecCMS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCMS.h; path = libsecurity_smime/lib/SecCMS.h; sourceTree = SOURCE_ROOT; }; + BE8C5F0916F7CE450074CF86 /* framework.sb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = framework.sb; sourceTree = ""; }; + BEC3A76716F79497003E5634 /* SecTaskPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTaskPriv.h; path = libsecurity_codesigning/lib/SecTaskPriv.h; sourceTree = SOURCE_ROOT; }; + C288A0881505795D00E773B7 /* libOpenScriptingUtil.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libOpenScriptingUtil.dylib; path = ../../../../../usr/lib/libOpenScriptingUtil.dylib; sourceTree = ""; }; + CDDE9D1C1729DF250013B0E8 /* SecPasswordGenerate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecPasswordGenerate.h; path = ../sec/Security/SecPasswordGenerate.h; sourceTree = ""; }; + EB22F3F518A26BA50016A8EC /* bc-10-knife-on-bread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "bc-10-knife-on-bread.c"; path = "Breadcrumb/bc-10-knife-on-bread.c"; sourceTree = ""; }; + EB22F3F618A26BA50016A8EC /* breadcrumb_regressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = breadcrumb_regressions.h; path = Breadcrumb/breadcrumb_regressions.h; sourceTree = ""; }; + EB22F3F718A26BA50016A8EC /* SecBreadcrumb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SecBreadcrumb.c; path = Breadcrumb/SecBreadcrumb.c; sourceTree = ""; }; + EB22F3F818A26BA50016A8EC /* SecBreadcrumb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecBreadcrumb.h; path = Breadcrumb/SecBreadcrumb.h; sourceTree = ""; }; + EB9732B7189E68840063DFED /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + EBD8B52718A55668004A650F /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README; path = Breadcrumb/README; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 0C6C630815D193C800BC68CD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 18CD682717272EBC005345FB /* libaks.a in Frameworks */, + 0CCEBDB416C2D026001BD7F6 /* libregressions.a in Frameworks */, + 52669053169D181900ED8231 /* Security.framework in Frameworks */, + 0C6C633015D19FF500BC68CD /* CoreFoundation.framework in Frameworks */, + 0C6C632A15D1989900BC68CD /* libsecurity_ssl_regressions.a in Frameworks */, + 0CAA7AB516C9A72A00A32C6D /* libsecurity_keychain_regressions.a in Frameworks */, + ACB6171918B5231800EBEDD7 /* libsecurity_smime_regressions.a in Frameworks */, + 18CD684E17272EE2005345FB /* IOKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0CC3351B16C1ED8000399E53 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5EC2284D190A437D00DB2DF2 /* libaks_acl.a in Frameworks */, + 5E59414418F43964005153AD /* libcoreauthd_client.a in Frameworks */, + 187A05B1170393FF0038C158 /* libaks.a in Frameworks */, + 18363C1417026084002D5C1C /* IOKit.framework in Frameworks */, + 39BFB04516D304DE0022564B /* SystemConfiguration.framework in Frameworks */, + 0CC3351E16C1ED8000399E53 /* libDER.a in Frameworks */, + 0C10987616CAAE8200803B8F /* libASN1.a in Frameworks */, + 0CC3356316C1EFBE00399E53 /* libregressions.a in Frameworks */, + 0CC3351F16C1ED8000399E53 /* libSecItemShimOSX.a in Frameworks */, + 0CC3352016C1ED8000399E53 /* libutilities.a in Frameworks */, + 0CC3351C16C1ED8000399E53 /* libsecurity.a in Frameworks */, + 0CCEBDB616C2E431001BD7F6 /* libsecurityd.a in Frameworks */, + 0CC3352616C1ED8000399E53 /* libsecipc_client.a in Frameworks */, + 0CC3352716C1ED8000399E53 /* libSecureObjectSync.a in Frameworks */, + 0CCEBDB816C2E6CE001BD7F6 /* libsqlite3.dylib in Frameworks */, + 0CC3352416C1ED8000399E53 /* CoreFoundation.framework in Frameworks */, + 0CCEBDB716C2E6B0001BD7F6 /* CFNetwork.framework in Frameworks */, + 0CC3352316C1ED8000399E53 /* libSOSRegressions.a in Frameworks */, + 0CCEBDBB16C30924001BD7F6 /* libutilitiesRegressions.a in Frameworks */, + 0C4EAE7717668DDF00773425 /* libsecdRegressions.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18073847146D0D4E00F05C24 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5E8ADED2190A2E380012271C /* libaks_acl.a in Frameworks */, + 5241C60D16DC1BA100DB5C6F /* libSecOtrOSX.a in Frameworks */, + 5208C0D716A0C96F0062DDC5 /* libSecureObjectSync.a in Frameworks */, + 52146FDB1697673900DF0DB3 /* libutilities.a in Frameworks */, + 1885B45214D9AB8100519375 /* libASN1.a in Frameworks */, + 18270F6114CF656E00B05E7F /* libsecipc_client.a in Frameworks */, + 18AD56A414CDE7BE008233F2 /* libSecItemShimOSX.a in Frameworks */, + 182BB5BA146FF0BF000BF1F3 /* libbsm.dylib in Frameworks */, + 182BB5B8146FF0A2000BF1F3 /* libobjc.dylib in Frameworks */, + 182BB5B6146FF090000BF1F3 /* libauto.dylib in Frameworks */, + 182BB5B4146FF04C000BF1F3 /* libxar.dylib in Frameworks */, + 182BB5B2146FF039000BF1F3 /* libz.dylib in Frameworks */, + 182BB5AE146FEF43000BF1F3 /* libsqlite3.dylib in Frameworks */, + 182BB5AC146FEF15000BF1F3 /* libpam.dylib in Frameworks */, + 182BB5AA146FEE50000BF1F3 /* CoreFoundation.framework in Frameworks */, + 182BB4E1146F2591000BF1F3 /* libsecurity_manifest.a in Frameworks */, + 182BB4E2146F2591000BF1F3 /* libsecurity_mds.a in Frameworks */, + 182BB4E3146F2591000BF1F3 /* libsecurity_sd_cspdl.a in Frameworks */, + 182BB4E4146F2591000BF1F3 /* libsecurity_smime.a in Frameworks */, + 182BB4E5146F2591000BF1F3 /* libsecurity_ssl.a in Frameworks */, + 182BB41B146F2533000BF1F3 /* libsecurity_apple_csp.a in Frameworks */, + 182BB41C146F2533000BF1F3 /* libsecurity_apple_cspdl.a in Frameworks */, + 182BB41D146F2533000BF1F3 /* libsecurity_apple_file_dl.a in Frameworks */, + 182BB41E146F2533000BF1F3 /* libsecurity_apple_x509_cl.a in Frameworks */, + 182BB41F146F2533000BF1F3 /* libsecurity_apple_x509_tp.a in Frameworks */, + 182BB421146F2533000BF1F3 /* libsecurity_authorization.a in Frameworks */, + 182BB422146F2533000BF1F3 /* libsecurity_cdsa_client.a in Frameworks */, + 182BB423146F2533000BF1F3 /* libsecurity_cdsa_utilities.a in Frameworks */, + 182BB424146F2533000BF1F3 /* libsecurity_checkpw.a in Frameworks */, + 182BB425146F2533000BF1F3 /* libsecurity_cms.a in Frameworks */, + 182BB5BB146FF62F000BF1F3 /* libsecurity_comcryption.a in Frameworks */, + 182BB426146F2533000BF1F3 /* libsecurity_codesigning.a in Frameworks */, + 182BB428146F2533000BF1F3 /* libsecurity_cryptkit.a in Frameworks */, + 182BB429146F2533000BF1F3 /* libsecurity_filedb.a in Frameworks */, + 182BB42A146F2533000BF1F3 /* libsecurity_keychain.a in Frameworks */, + 182BB42B146F2533000BF1F3 /* libsecurity_ocspd.a in Frameworks */, + 182BB42C146F2533000BF1F3 /* libsecurity_pkcs12.a in Frameworks */, + 182BB42D146F2533000BF1F3 /* libsecurity_transform.a in Frameworks */, + 182BB42E146F2533000BF1F3 /* libsecurityd_client.a in Frameworks */, + 18446083146DF58B00B12992 /* libsecurity_cdsa_plugin.a in Frameworks */, + 1879B571146DE2FF007E536C /* libsecurity_cssm.a in Frameworks */, + 1879B546146DE192007E536C /* libsecurity_utilities.a in Frameworks */, + 1879B570146DE2E6007E536C /* libsecurity_cdsa_utils.a in Frameworks */, + C288A0891505796F00E773B7 /* libOpenScriptingUtil.dylib in Frameworks */, + 4CC8DEA416DC1AC800462517 /* libSecOtrOSX.a in Frameworks */, + E76079D61951FDAF00F69731 /* liblogging.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18270ED314CF282600B05E7F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5E27BBFB18F4103100B6C79A /* libcoreauthd_client.a in Frameworks */, + 5E48A8EA1907893C0011BC31 /* libaks_acl.a in Frameworks */, + 189757871700CF4C00672567 /* libaks.a in Frameworks */, + 395E7CEE16C64EA500CD82A4 /* SystemConfiguration.framework in Frameworks */, + 5208BF4F16A0993C0062DDC5 /* libsecurity.a in Frameworks */, + AAF3DCCB1666D03300376593 /* libsecurity_utilities.a in Frameworks */, + 4C7D8765160A74C400D041E3 /* libutilities.a in Frameworks */, + 18F2360115CAF41200060520 /* libsecurity_codesigning.a in Frameworks */, + 1831329B14EB2C6D00F0BCAC /* libASN1.a in Frameworks */, + 1831329C14EB2C6D00F0BCAC /* libDER.a in Frameworks */, + 18270EFE14CF429600B05E7F /* IOKit.framework in Frameworks */, + 18270EFA14CF426200B05E7F /* libsqlite3.dylib in Frameworks */, + 18270EF914CF425100B05E7F /* libbsm.dylib in Frameworks */, + 18270EE814CF294500B05E7F /* libsecurityd.a in Frameworks */, + 4C01DF14164C3E7C006798CD /* libSecureObjectSync.a in Frameworks */, + 4C8D8651177A752D0019A804 /* libsecipc_client.a in Frameworks */, + 18270EF814CF424900B05E7F /* CoreFoundation.framework in Frameworks */, + 18270EFC14CF427800B05E7F /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 182BB565146F4DCA000BF1F3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 182BB592146FE1D7000BF1F3 /* CoreFoundation.framework in Frameworks */, + 182BB591146FE12F000BF1F3 /* libsecurity_utilities.a in Frameworks */, + 182BB590146FE125000BF1F3 /* libsecurity_cdsa_utilities.a in Frameworks */, + 182BB589146FE013000BF1F3 /* libsecurity_codesigning.a in Frameworks */, + 529E948D169E29470000AC9B /* Security.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18F234E815C9F9A600060520 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 18F2353815C9FDEF00060520 /* libsqlite3.dylib in Frameworks */, + 18F2353715C9FDE400060520 /* libbsm.dylib in Frameworks */, + 18F2353615C9FDD200060520 /* Security.framework in Frameworks */, + 18F2353515C9FDB700060520 /* CoreFoundation.framework in Frameworks */, + 187D6B9815D4476D00E27494 /* IOKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 37A7CEA8197DB8FA00926CE8 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C96F7BE16D6DF8300D3B39D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C97761E17BEB23E0002BFE4 /* AOSAccounts.framework in Frameworks */, + 4C5DD46C17A5F67300696A79 /* AppleSystemInfo.framework in Frameworks */, + 4C328D301778EC4F0015EED1 /* AOSUI.framework in Frameworks */, + 4CAEACCD16D6FC7600263776 /* Security.framework in Frameworks */, + 4C96F7C216D6DF8400D3B39D /* Cocoa.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CB23B43169F5873003A0131 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5E3A07071962B0B000463F09 /* libaks_acl.a in Frameworks */, + 52CD052316A0E24900218387 /* Security.framework in Frameworks */, + 4CB23B8C169F59AD003A0131 /* libutilities.a in Frameworks */, + 4CB23B8A169F599A003A0131 /* libSecurityCommands.a in Frameworks */, + 4CB23B8B169F599A003A0131 /* libSOSCommands.a in Frameworks */, + 4CB23B89169F5990003A0131 /* libSecurityTool.a in Frameworks */, + 4CB23B47169F5873003A0131 /* CoreFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CC7A7B016CC2A84003E10C1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4CC7A7F316CC2B0A003E10C1 /* Security.framework in Frameworks */, + 4CC7A7B416CC2A85003E10C1 /* Cocoa.framework in Frameworks */, + 4C96F76216D54C9600D3B39D /* CoreFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5214700316977CB800DF0DB3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5214702A1697855800DF0DB3 /* Foundation.framework in Frameworks */, + 5214701E16977DA700DF0DB3 /* libCloudKeychainProxy.a in Frameworks */, + 5214701D16977D9500DF0DB3 /* libutilities.a in Frameworks */, + 529E948C169E29450000AC9B /* Security.framework in Frameworks */, + 0C4EAE4C1766864F00773425 /* libaks.a in Frameworks */, + 0C4EAE761766875E00773425 /* IOKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 72756BFB175D485D00F52070 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 72CC327C175D6E1800217455 /* Security.framework in Frameworks */, + 72CC327B175D6E0A00217455 /* CoreFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0C6C630D15D193C800BC68CD /* sectests */ = { + isa = PBXGroup; + children = ( + 18ED4D2317270DB6003AF11B /* SecurityTests-Entitlements.plist */, + 0C6C630E15D193C800BC68CD /* main.c */, + 0C6C632415D1964200BC68CD /* testlist.h */, + ); + path = sectests; + sourceTree = ""; + }; + 0C6D0063177B54A70095D167 /* asl */ = { + isa = PBXGroup; + children = ( + 0C6D0064177B54C60095D167 /* com.apple.securityd */, + ); + name = asl; + path = lib; + sourceTree = ""; + }; + 0C6D77DF15C8C06500BB4405 /* Products */ = { + isa = PBXGroup; + children = ( + 0C6D77E915C8C06600BB4405 /* tlsnke.kext */, + 0C6D77EB15C8C06600BB4405 /* tlsnketest */, + 0C6D77ED15C8C06600BB4405 /* libtlssocket.a */, + ); + name = Products; + sourceTree = ""; + }; + 0C6D77EE15C8C07C00BB4405 /* tlsnke */ = { + isa = PBXGroup; + children = ( + 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */, + ); + name = tlsnke; + sourceTree = ""; + }; + 0CC3355516C1EEAD00399E53 /* secdtests */ = { + isa = PBXGroup; + children = ( + 0CC3355716C1EEE700399E53 /* main.c */, + 0CC3355816C1EEE700399E53 /* testlist.h */, + ); + name = secdtests; + sourceTree = ""; + }; + 0CC3355C16C1EF5D00399E53 /* Products */ = { + isa = PBXGroup; + children = ( + 0CC3356016C1EF5D00399E53 /* libregressions.a */, + ); + name = Products; + sourceTree = ""; + }; + 1807383F146D0D4E00F05C24 = { + isa = PBXGroup; + children = ( + EB22F3CE18A26B640016A8EC /* Breadcrumb */, + 0C6D0063177B54A70095D167 /* asl */, + 4C1288F615FFECF2008CE3E3 /* utilities */, + 18073854146D0D4E00F05C24 /* lib */, + 181EA3D0146D1ED200A6D320 /* libsecurity */, + 186CDD0314CA10E700AF9171 /* sec */, + 186CDE7914CA3A3800AF9171 /* secd */, + 4C0F6FAF1985879300178101 /* sectask */, + 0C6D77EE15C8C07C00BB4405 /* tlsnke */, + 181EA421146D4A2A00A6D320 /* config */, + 0CC3355516C1EEAD00399E53 /* secdtests */, + 0C6C630D15D193C800BC68CD /* sectests */, + 18F234ED15C9F9A700060520 /* authd */, + 5214700D16977CB800DF0DB3 /* CloudKeychainProxy */, + 4CB23B48169F5873003A0131 /* security2 */, + 4CC7A7B516CC2A85003E10C1 /* KeychainDemoApp */, + 4C96F7C316D6DF8400D3B39D /* Keychain Circle Notification */, + 72756C00175D485D00F52070 /* cloud_keychain_diagnose */, + 721680A7179B40F600406BB4 /* iCloudStats */, + 37A7CEAC197DB8FA00926CE8 /* codesign_tests */, + 1807384D146D0D4E00F05C24 /* Frameworks */, + 1807384C146D0D4E00F05C24 /* Products */, + ); + sourceTree = ""; + }; + 1807384C146D0D4E00F05C24 /* Products */ = { + isa = PBXGroup; + children = ( + 1807384B146D0D4E00F05C24 /* Security.framework */, + 182BB568146F4DCA000BF1F3 /* csparser.bundle */, + 18FE67EA1471A3AA00A2CBE3 /* Security.framework */, + 18270ED614CF282600B05E7F /* secd */, + 0C6C630B15D193C800BC68CD /* sectests */, + 18F234EB15C9F9A600060520 /* authd.xpc */, + 5214700616977CB800DF0DB3 /* CloudKeychainProxy.bundle */, + 4CB23B46169F5873003A0131 /* security2 */, + 0CC3352D16C1ED8000399E53 /* secdtests */, + 4CC7A7B316CC2A84003E10C1 /* Cloud Keychain Utility.app */, + 4C96F7C116D6DF8300D3B39D /* Keychain Circle Notification.app */, + 72756BFE175D485D00F52070 /* cloud_keychain_diagnose */, + 37A7CEAB197DB8FA00926CE8 /* codesign_tests */, + ); + name = Products; + sourceTree = ""; + }; + 1807384D146D0D4E00F05C24 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 5E3A07061962B0B000463F09 /* libaks_acl.a */, + 5E8ADED1190A2E380012271C /* libaks_acl.a */, + 5E27BBFA18F4103100B6C79A /* libcoreauthd_client.a */, + 5E48A8E91907893C0011BC31 /* libaks_acl.a */, + 4C97761D17BEB23E0002BFE4 /* AOSAccounts.framework */, + 4C5DD46B17A5F67300696A79 /* AppleSystemInfo.framework */, + 72A3DE5B179B2C0400E78247 /* Foundation.framework */, + 4C328D2F1778EC4F0015EED1 /* AOSUI.framework */, + 722CF215175D5E5000BCE0A5 /* Security.framework */, + 72756C9E175D566800F52070 /* CoreFoundation.framework */, + 72756C9C175D51C900F52070 /* Kernel.framework */, + 72756C9A175D51B100F52070 /* IOKit.framework */, + 18752C1D16F2837A004E2799 /* libaks.a */, + 4C96F76116D54C9600D3B39D /* CoreFoundation.framework */, + 4CC7A7F216CC2B0A003E10C1 /* Security.framework */, + 395E7CED16C64EA500CD82A4 /* SystemConfiguration.framework */, + 18F2360015CAF41100060520 /* libsecurity_codesigning.a */, + 18F235FC15CA0EDB00060520 /* libstdc++.6.0.9.dylib */, + 18F235F915CA0DB000060520 /* libsecurity_agent_client.a */, + 18F235F715CA0D9D00060520 /* libsecurity_utilities.a */, + 18F235F515CA0D8100060520 /* libsecurity_cdsa_utilities.a */, + 4CF42BB515A3947F00ACACE1 /* Security.framework */, + 1831329914EB2C6D00F0BCAC /* libASN1.a */, + 1831329A14EB2C6D00F0BCAC /* libDER.a */, + 18270EFF14CF42CA00B05E7F /* libcorecrypto.a */, + 18270EFD14CF429600B05E7F /* IOKit.framework */, + 18270EFB14CF427800B05E7F /* CFNetwork.framework */, + 182BB5B9146FF0BE000BF1F3 /* libbsm.dylib */, + 182BB5B7146FF0A1000BF1F3 /* libobjc.dylib */, + 182BB5B5146FF08F000BF1F3 /* libauto.dylib */, + 182BB5B3146FF04C000BF1F3 /* libxar.dylib */, + 182BB5B1146FF039000BF1F3 /* libz.dylib */, + 182BB5AD146FEF43000BF1F3 /* libsqlite3.dylib */, + 182BB5AB146FEF14000BF1F3 /* libpam.dylib */, + 182BB593146FE1ED000BF1F3 /* libantlr2c++.a */, + C288A0881505795D00E773B7 /* libOpenScriptingUtil.dylib */, + 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */, + 5214700716977CB800DF0DB3 /* Cocoa.framework */, + EB9732B7189E68840063DFED /* XCTest.framework */, + 5214700916977CB800DF0DB3 /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + 18073854146D0D4E00F05C24 /* lib */ = { + isa = PBXGroup; + children = ( + 1879B4A6146DC971007E536C /* Headers */, + 1879B4A7146DC999007E536C /* PrivateHeaders */, + 182BB228146F0674000BF1F3 /* Resources */, + 18073855146D0D4E00F05C24 /* Supporting Files */, + 182BB555146F450F000BF1F3 /* plugins */, + 182BB5A9146FEB27000BF1F3 /* derived_src */, + 18A5493115EFD2F40059E6DC /* dummy.cpp */, + ); + path = lib; + sourceTree = ""; + }; + 18073855146D0D4E00F05C24 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 182BB562146F4C73000BF1F3 /* security.exp-in */, + 182BB55D146F4544000BF1F3 /* generateErrStrings.pl */, + 182BB55E146F4544000BF1F3 /* Security.order */, + 18073856146D0D4E00F05C24 /* Info-Security.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 181EA3D0146D1ED200A6D320 /* libsecurity */ = { + isa = PBXGroup; + children = ( + 1879B532146DDBE5007E536C /* libsecurity_utilities.xcodeproj */, + 1879B547146DE212007E536C /* libsecurity_cdsa_utils.xcodeproj */, + 1879B550146DE227007E536C /* libsecurity_cdsa_utilities.xcodeproj */, + 1879B55D146DE244007E536C /* libsecurity_cssm.xcodeproj */, + 1879B5BC146DE6C8007E536C /* libsecurity_apple_csp.xcodeproj */, + 1879B5C9146DE6CE007E536C /* libsecurity_apple_cspdl.xcodeproj */, + 1879B5D5146DE6D7007E536C /* libsecurity_apple_file_dl.xcodeproj */, + 1879B5E1146DE6E7007E536C /* libsecurity_apple_x509_cl.xcodeproj */, + 1879B5F0146DE6FD007E536C /* libsecurity_apple_x509_tp.xcodeproj */, + 1879B5FC146DE704007E536C /* libsecurity_asn1.xcodeproj */, + 1879B609146DE70A007E536C /* libsecurity_authorization.xcodeproj */, + 1879B615146DE715007E536C /* libsecurity_cdsa_client.xcodeproj */, + 1879B621146DE720007E536C /* libsecurity_cdsa_plugin.xcodeproj */, + 1879B637146DE748007E536C /* libsecurity_checkpw.xcodeproj */, + 1879B64B146DE750007E536C /* libsecurity_cms.xcodeproj */, + 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */, + 1879B66D146DE75D007E536C /* libsecurity_comcryption.xcodeproj */, + 1879B679146DE76E007E536C /* libsecurity_cryptkit.xcodeproj */, + 1879B694146DE797007E536C /* libsecurity_filedb.xcodeproj */, + 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */, + 1879B6C7146DE7D7007E536C /* libsecurity_manifest.xcodeproj */, + 1879B6D3146DE7E0007E536C /* libsecurity_mds.xcodeproj */, + 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */, + 1879B712146DE825007E536C /* libsecurity_smime.xcodeproj */, + 1879B72B146DE844007E536C /* libsecurity_transform.xcodeproj */, + 1879B6DF146DE7E7007E536C /* libsecurity_ocspd.xcodeproj */, + 1879B6F8146DE7F7007E536C /* libsecurity_sd_cspdl.xcodeproj */, + 1879B6EC146DE7EE007E536C /* libsecurity_pkcs12.xcodeproj */, + 184461A3146E9D3200B12992 /* libsecurityd.xcodeproj */, + 18270F0814CF43C000B05E7F /* libDER.xcodeproj */, + ); + name = libsecurity; + sourceTree = ""; + }; + 181EA421146D4A2A00A6D320 /* config */ = { + isa = PBXGroup; + children = ( + 18BFC44017C43393005DE6C3 /* executable.xcconfig */, + 18BBC6801471EF1600F2B224 /* security.xcconfig */, + 181EA422146D4A2A00A6D320 /* base.xcconfig */, + 181EA423146D4A2A00A6D320 /* debug.xcconfig */, + 181EA424146D4A2A00A6D320 /* lib.xcconfig */, + 0C6C632F15D19DE600BC68CD /* test.xcconfig */, + 4CB23B91169F5CFF003A0131 /* command.xcconfig */, + 181EA425146D4A2A00A6D320 /* release.xcconfig */, + ); + path = config; + sourceTree = ""; + }; + 18270EEB14CF331500B05E7F /* ipc */ = { + isa = PBXGroup; + children = ( + 18BEB19614CF74C100C8BD36 /* com.apple.secd.plist */, + 18270EEC14CF333400B05E7F /* client.c */, + 18270EED14CF333400B05E7F /* com.apple.securityd.plist */, + 18270EEE14CF333400B05E7F /* securityd_client.h */, + 18270EEF14CF333400B05E7F /* securityd_ipc_types.h */, + 18270EF014CF333400B05E7F /* securityd_rep.defs */, + 18270EF114CF333400B05E7F /* securityd_req.defs */, + 18270EF214CF333400B05E7F /* securityd_server.h */, + 18270EF314CF333400B05E7F /* server.c */, + ); + name = ipc; + path = sec/ipc; + sourceTree = ""; + }; + 18270F0914CF43C000B05E7F /* Products */ = { + isa = PBXGroup; + children = ( + 18270F1214CF43C000B05E7F /* libDER.a */, + 18270F1414CF43C000B05E7F /* parseCert */, + 18270F1614CF43C000B05E7F /* libDERUtils.a */, + 18270F1814CF43C000B05E7F /* parseCrl */, + 18270F1A14CF43C000B05E7F /* parseTicket */, + ); + name = Products; + sourceTree = ""; + }; + 18270F3114CF448600B05E7F /* security_utilities */ = { + isa = PBXGroup; + children = ( + 18270F3A14CF44C400B05E7F /* debugging.c */, + 18270F3B14CF44C400B05E7F /* debugging.h */, + ); + path = security_utilities; + sourceTree = ""; + }; + 182BB228146F0674000BF1F3 /* Resources */ = { + isa = PBXGroup; + children = ( + 187D6B8F15D4359F00E27494 /* authorization.buttons.strings */, + BE8C5F0916F7CE450074CF86 /* framework.sb */, + 187D6B9115D4359F00E27494 /* authorization.prompts.strings */, + 52B006BF15238F76005D4556 /* TimeStampingPrefs.plist */, + 188AD8D81471FE3D0081C619 /* FDELocalizable.strings */, + 188AD8DA1471FE3D0081C619 /* InfoPlist.strings */, + 182BB55C146F4544000BF1F3 /* FDEPrefs.plist */, + 182BB229146F068B000BF1F3 /* iToolsTrustedApps.plist */, + 1879B4A8146DC9D7007E536C /* mds */, + ); + name = Resources; + sourceTree = ""; + }; + 182BB555146F450F000BF1F3 /* plugins */ = { + isa = PBXGroup; + children = ( + 182BB556146F4510000BF1F3 /* csparser-Info.plist */, + 182BB557146F4510000BF1F3 /* csparser.cpp */, + 182BB558146F4510000BF1F3 /* csparser.exp */, + ); + path = plugins; + sourceTree = ""; + }; + 182BB5A9146FEB27000BF1F3 /* derived_src */ = { + isa = PBXGroup; + children = ( + 18B647EF14D9F75300F538BF /* generateErrStrings.mm */, + 18500F9F14708F19006F9AB4 /* SecErrorMessages.strings */, + 18500F9A14708D0E006F9AB4 /* SecDebugErrorMessages.strings */, + ); + name = derived_src; + sourceTree = ""; + }; + 184461A4146E9D3200B12992 /* Products */ = { + isa = PBXGroup; + children = ( + 184461B1146E9D3300B12992 /* libsecurityd_client.a */, + 184461B5146E9D3300B12992 /* libsecurityd_server.a */, + 184461B9146E9D3300B12992 /* ucspc.a */, + ); + name = Products; + sourceTree = ""; + }; + 186CDD0314CA10E700AF9171 /* sec */ = { + isa = PBXGroup; + children = ( + 186CDD1614CA11C700AF9171 /* sec.xcodeproj */, + ); + path = sec; + sourceTree = ""; + }; + 186CDD1714CA11C700AF9171 /* Products */ = { + isa = PBXGroup; + children = ( + 18D4053B14CE2C1600A2BE4E /* libsecurity.a */, + 18270C7D14CE573D00B05E7F /* libsecurityd.a */, + 186CDD1E14CA11C700AF9171 /* libSecItemShimOSX.a */, + 18270F6014CF655B00B05E7F /* libsecipc_client.a */, + 4C1288EA15FFE9D7008CE3E3 /* libSecureObjectSync.a */, + 4C1288EC15FFE9D7008CE3E3 /* libSOSRegressions.a */, + 4C1288EE15FFE9D7008CE3E3 /* libSecurityRegressions.a */, + 4C1288F015FFE9D7008CE3E3 /* libsecuritydRegressions.a */, + 4C1288F215FFE9D7008CE3E3 /* libSecOtrOSX.a */, + 4C01DE32164C3793006798CD /* libCloudKeychainProxy.a */, + 4CB23B76169F5873003A0131 /* libSecurityTool.a */, + 4CB23B78169F5873003A0131 /* libSecurityCommands.a */, + 4CB23B7A169F5873003A0131 /* libSOSCommands.a */, + 0C4EAE721766865000773425 /* libsecdRegressions.a */, + E760796F1951F99600F69731 /* libSWCAgent.a */, + E76079D51951FDA800F69731 /* liblogging.a */, + ); + name = Products; + sourceTree = ""; + }; + 186CDE7914CA3A3800AF9171 /* secd */ = { + isa = PBXGroup; + children = ( + 18270EEB14CF331500B05E7F /* ipc */, + 18270F3114CF448600B05E7F /* security_utilities */, + ); + name = secd; + sourceTree = ""; + }; + 1879B4A6146DC971007E536C /* Headers */ = { + isa = PBXGroup; + children = ( + 18446146146E923200B12992 /* Authorization.h */, + 18446147146E923200B12992 /* AuthorizationDB.h */, + 18446148146E923200B12992 /* AuthorizationPlugin.h */, + 18446144146E923200B12992 /* AuthorizationTags.h */, + 18446145146E923200B12992 /* AuthSession.h */, + 1879B4AD146DCA84007E536C /* certextensions.h */, + 182BB36E146F13B4000BF1F3 /* CipherSuite.h */, + 18446170146E982800B12992 /* CMSDecoder.h */, + 18446171146E982800B12992 /* CMSEncoder.h */, + 1844617F146E9A8500B12992 /* CodeSigning.h */, + 18446180146E9A8500B12992 /* CSCommon.h */, + 1879B4AE146DCA84007E536C /* cssm.h */, + 1879B4AF146DCA84007E536C /* cssmaci.h */, + 1879B4B0146DCA84007E536C /* cssmapi.h */, + 1879B4B1146DCA84007E536C /* cssmapple.h */, + 1879B4B2146DCA84007E536C /* cssmcli.h */, + 1879B4B3146DCA84007E536C /* cssmconfig.h */, + 1879B4B4146DCA84007E536C /* cssmcspi.h */, + 1879B4B5146DCA84007E536C /* cssmdli.h */, + 1879B4B6146DCA84007E536C /* cssmerr.h */, + 1879B4B7146DCA84007E536C /* cssmkrapi.h */, + 1879B4B8146DCA84007E536C /* cssmkrspi.h */, + 1879B4B9146DCA84007E536C /* cssmspi.h */, + 1879B4BA146DCA84007E536C /* cssmtpi.h */, + 1879B4BB146DCA84007E536C /* cssmtype.h */, + 1879B4BC146DCA84007E536C /* eisl.h */, + 1879B4BD146DCA84007E536C /* emmspi.h */, + 1879B4BE146DCA84007E536C /* emmtype.h */, + 182BB356146F1198000BF1F3 /* mds.h */, + 182BB357146F1198000BF1F3 /* mds_schema.h */, + 18B647E814D9EB6300F538BF /* oidsalg.h */, + 18B647EA14D9EE4300F538BF /* oidsattr.h */, + 1879B4C1146DCA84007E536C /* oidsbase.h */, + 1879B4C2146DCA84007E536C /* oidscert.h */, + 1879B4C3146DCA84007E536C /* oidscrl.h */, + 182BB187146EAD4C000BF1F3 /* SecAccess.h */, + 44B2603E18F81A6A008DF20F /* SecAccessControl.h */, + 182BB188146EAD4C000BF1F3 /* SecACL.h */, + 184460AB146DFCC100B12992 /* SecAsn1Coder.h */, + 184460AC146DFCC100B12992 /* SecAsn1Templates.h */, + 184460AD146DFCC100B12992 /* SecAsn1Types.h */, + 182BB189146EAD4C000BF1F3 /* SecBase.h */, + 182BB18A146EAD4C000BF1F3 /* SecCertificate.h */, + 182BB199146EAD4C000BF1F3 /* SecCertificateOIDs.h */, + 18446181146E9A8500B12992 /* SecCode.h */, + 18446184146E9A8500B12992 /* SecCodeHost.h */, + 182BB3A6146F1BEC000BF1F3 /* SecCustomTransform.h */, + 182BB3A7146F1BEC000BF1F3 /* SecDecodeTransform.h */, + 182BB3A3146F1BEC000BF1F3 /* SecDigestTransform.h */, + 182BB3A8146F1BEC000BF1F3 /* SecEncodeTransform.h */, + 182BB3A9146F1BEC000BF1F3 /* SecEncryptTransform.h */, + 182BB18B146EAD4C000BF1F3 /* SecIdentity.h */, + 182BB18C146EAD4C000BF1F3 /* SecIdentitySearch.h */, + 182BB197146EAD4C000BF1F3 /* SecImportExport.h */, + 182BB18D146EAD4C000BF1F3 /* SecItem.h */, + 182BB18E146EAD4C000BF1F3 /* SecKey.h */, + 182BB18F146EAD4C000BF1F3 /* SecKeychain.h */, + 182BB190146EAD4C000BF1F3 /* SecKeychainItem.h */, + 182BB191146EAD4C000BF1F3 /* SecKeychainSearch.h */, + 182BB192146EAD4C000BF1F3 /* SecPolicy.h */, + 182BB193146EAD4C000BF1F3 /* SecPolicySearch.h */, + 182BB19A146EAD4C000BF1F3 /* SecRandom.h */, + 182BB3A4146F1BEC000BF1F3 /* SecReadTransform.h */, + 18446183146E9A8500B12992 /* SecRequirement.h */, + 182BB3AA146F1BEC000BF1F3 /* SecSignVerifyTransform.h */, + 18446182146E9A8500B12992 /* SecStaticCode.h */, + 1844617E146E9A8500B12992 /* SecTask.h */, + BEC3A76716F79497003E5634 /* SecTaskPriv.h */, + 182BB3A5146F1BEC000BF1F3 /* SecTransform.h */, + 182BB3AB146F1BEC000BF1F3 /* SecTransformReadTransform.h */, + 182BB194146EAD4C000BF1F3 /* SecTrust.h */, + 182BB195146EAD4C000BF1F3 /* SecTrustedApplication.h */, + 182BB198146EAD4C000BF1F3 /* SecTrustSettings.h */, + 182BB315146F0E7E000BF1F3 /* SecureDownload.h */, + 182BB36F146F13B4000BF1F3 /* SecureTransport.h */, + 182BB196146EAD4C000BF1F3 /* Security.h */, + 4CB86AFA167A8F2200F46643 /* SOSAccount.h */, + 4CB86AE6167A6FF200F46643 /* SOSCircle.h */, + 4CB86AE7167A6FF200F46643 /* SOSCloudCircle.h */, + 4CB86AE8167A6FF200F46643 /* SOSCloudCircleInternal.h */, + 4CB86AE9167A6FF200F46643 /* SOSEngine.h */, + 4CB86AEA167A6FF300F46643 /* SOSFullPeerInfo.h */, + 4CB86AEB167A6FF300F46643 /* SOSInternal.h */, + 4CB86AEC167A6FF300F46643 /* SOSPeer.h */, + 4CB86AED167A6FF300F46643 /* SOSPeerInfo.h */, + 4CB86AEE167A6FF300F46643 /* SOSTransport.h */, + 1879B4C4146DCA84007E536C /* x509defs.h */, + ); + name = Headers; + sourceTree = ""; + }; + 1879B4A7146DC999007E536C /* PrivateHeaders */ = { + isa = PBXGroup; + children = ( + 184460A1146DFCB700B12992 /* asn1Templates.h */, + 1844614F146E923B00B12992 /* AuthorizationPriv.h */, + 1844614E146E923B00B12992 /* AuthorizationTagsPriv.h */, + 1844609A146DFCB700B12992 /* certExtensionTemplates.h */, + 18446168146E95D700B12992 /* checkpw.h */, + 18446174146E982D00B12992 /* CMSPrivate.h */, + 1844618C146E9A8F00B12992 /* CSCommonPriv.h */, + 1844609B146DFCB700B12992 /* csrTemplates.h */, + 1879B4AB146DCA4A007E536C /* cssmapplePriv.h */, + 184460A0146DFCB700B12992 /* keyTemplates.h */, + 182BB35A146F11A1000BF1F3 /* mdspriv.h */, + 1844609D146DFCB700B12992 /* nameTemplates.h */, + 1844609C146DFCB700B12992 /* ocspTemplates.h */, + 1844609F146DFCB700B12992 /* osKeyTemplates.h */, + 182BB1B2146EAD5D000BF1F3 /* SecAccessPriv.h */, + 44B2606918F81BFE008DF20F /* SecAccessControlPriv.h */, + 18446099146DFCB700B12992 /* secasn1t.h */, + 18446194146E9A8F00B12992 /* SecAssessment.h */, + 182BB1B3146EAD5D000BF1F3 /* SecBasePriv.h */, + 182BB1B4146EAD5D000BF1F3 /* SecCertificateBundle.h */, + 182BB1B5146EAD5D000BF1F3 /* SecCertificatePriv.h */, + 182BB1B6146EAD5D000BF1F3 /* SecCertificateRequest.h */, + AC5688BA18B4396D00F0526C /* SecCMS.h */, + 182BB383146F14D2000BF1F3 /* SecCmsBase.h */, + 182BB384146F14D2000BF1F3 /* SecCmsContentInfo.h */, + 182BB385146F14D2000BF1F3 /* SecCmsDecoder.h */, + 182BB386146F14D2000BF1F3 /* SecCmsDigestContext.h */, + 182BB387146F14D2000BF1F3 /* SecCmsDigestedData.h */, + 182BB388146F14D2000BF1F3 /* SecCmsEncoder.h */, + 182BB389146F14D2000BF1F3 /* SecCmsEncryptedData.h */, + 182BB38A146F14D2000BF1F3 /* SecCmsEnvelopedData.h */, + 182BB38B146F14D2000BF1F3 /* SecCmsMessage.h */, + 182BB38C146F14D2000BF1F3 /* SecCmsRecipientInfo.h */, + 182BB38D146F14D2000BF1F3 /* SecCmsSignedData.h */, + 182BB38E146F14D2000BF1F3 /* SecCmsSignerInfo.h */, + 18446193146E9A8F00B12992 /* SecCodeHostLib.h */, + 1844618D146E9A8F00B12992 /* SecCodePriv.h */, + 18446190146E9A8F00B12992 /* SecCodeSigner.h */, + 0C03D60317D93E810087643B /* SecDH.h */, + 18BBC7351471F5A300F2B224 /* SecExternalSourceTransform.h */, + 182BB1AF146EAD5D000BF1F3 /* SecFDERecoveryAsymmetricCrypto.h */, + 182BB1B7146EAD5D000BF1F3 /* SecIdentityPriv.h */, + 182BB1C4146EAD5D000BF1F3 /* SecIdentitySearchPriv.h */, + 18446191146E9A8F00B12992 /* SecIntegrity.h */, + 18446192146E9A8F00B12992 /* SecIntegrityLib.h */, + 182BB1CA146EAD5D000BF1F3 /* SecItemPriv.h */, + 182BB1CB146EAD5D000BF1F3 /* SecKeychainItemExtendedAttributes.h */, + 182BB1B8146EAD5D000BF1F3 /* SecKeychainItemPriv.h */, + 182BB1B9146EAD5D000BF1F3 /* SecKeychainPriv.h */, + 182BB1C5146EAD5D000BF1F3 /* SecKeychainSearchPriv.h */, + 182BB1BA146EAD5D000BF1F3 /* SecKeyPriv.h */, + 182BB317146F0E94000BF1F3 /* SecManifest.h */, + 182BB3B6146F1BF9000BF1F3 /* SecNullTransform.h */, + 182BB1B0146EAD5D000BF1F3 /* SecPassword.h */, + CDDE9D1C1729DF250013B0E8 /* SecPasswordGenerate.h */, + 182BB1BB146EAD5D000BF1F3 /* SecPolicyPriv.h */, + 182BB1CF146EAD5D000BF1F3 /* SecRandomP.h */, + 182BB1CE146EAD5D000BF1F3 /* SecRecoveryPassword.h */, + 1844618F146E9A8F00B12992 /* SecRequirementPriv.h */, + 182BB38F146F14D2000BF1F3 /* SecSMIME.h */, + 1844618E146E9A8F00B12992 /* SecStaticCodePriv.h */, + 182BB3B7146F1BF9000BF1F3 /* SecTransformInternal.h */, + 182BB1BC146EAD5D000BF1F3 /* SecTrustedApplicationPriv.h */, + 182BB1BD146EAD5D000BF1F3 /* SecTrustPriv.h */, + 182BB1C6146EAD5D000BF1F3 /* SecTrustSettingsPriv.h */, + 182BB318146F0E94000BF1F3 /* SecureDownloadInternal.h */, + 182BB372146F13BB000BF1F3 /* SecureTransportPriv.h */, + 0C4F055D15C9E51A00F9DFD5 /* sslTypes.h */, + 182BB1C8146EAD5D000BF1F3 /* TrustSettingsSchema.h */, + 52B5A9C01519330300664F11 /* tsaSupport.h */, + 52AEA484153C7581005AFC59 /* tsaSupportPriv.h */, + 52B5A9C11519330300664F11 /* tsaTemplates.h */, + 1844609E146DFCB700B12992 /* X509Templates.h */, + ); + name = PrivateHeaders; + sourceTree = ""; + }; + 1879B4A8146DC9D7007E536C /* mds */ = { + isa = PBXGroup; + children = ( + 182BB3C4146F1DCB000BF1F3 /* sd_cspdl_common.mdsinfo */, + 1879B4A9146DCA18007E536C /* cssm.mdsinfo */, + 1844605B146DE93E00B12992 /* csp_capabilities.mdsinfo */, + 1844605C146DE93E00B12992 /* csp_capabilities_common.mds */, + 1844605D146DE93E00B12992 /* csp_common.mdsinfo */, + 1844605E146DE93E00B12992 /* csp_primary.mdsinfo */, + 184460C3146E7B1E00B12992 /* cspdl_common.mdsinfo */, + 184460C4146E7B1E00B12992 /* cspdl_csp_capabilities.mdsinfo */, + 184460C5146E7B1E00B12992 /* cspdl_csp_primary.mdsinfo */, + 184460C6146E7B1E00B12992 /* cspdl_dl_primary.mdsinfo */, + 184460E1146E806700B12992 /* dl_common.mdsinfo */, + 184460E2146E806700B12992 /* dl_primary.mdsinfo */, + 18446103146E82C800B12992 /* cl_common.mdsinfo */, + 18446104146E82C800B12992 /* cl_primary.mdsinfo */, + 18446112146E85A300B12992 /* tp_common.mdsinfo */, + 18446113146E85A300B12992 /* tp_policyOids.mdsinfo */, + 18446114146E85A300B12992 /* tp_primary.mdsinfo */, + ); + name = mds; + sourceTree = ""; + }; + 1879B533146DDBE5007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B538146DDBE5007E536C /* libsecurity_utilities.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B548146DE212007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B54F146DE212007E536C /* libsecurity_cdsa_utils.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B551146DE227007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B55A146DE227007E536C /* libsecurity_cdsa_utilities.a */, + 1879B55C146DE227007E536C /* Schemas */, + ); + name = Products; + sourceTree = ""; + }; + 1879B55E146DE244007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B565146DE244007E536C /* libsecurity_cssm.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B5BD146DE6C8007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B5C6146DE6C8007E536C /* libsecurity_apple_csp.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B5CA146DE6CE007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B5D2146DE6CE007E536C /* libsecurity_apple_cspdl.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B5D6146DE6D7007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B5DE146DE6D7007E536C /* libsecurity_apple_file_dl.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B5E2146DE6E7007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B5EB146DE6E8007E536C /* libsecurity_apple_x509_cl.a */, + 1879B5EF146DE6E8007E536C /* apple_x509_cl.bundle */, + ); + name = Products; + sourceTree = ""; + }; + 1879B5F1146DE6FD007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B5F9146DE6FD007E536C /* libsecurity_apple_x509_tp.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B5FD146DE704007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1885B3F914D8D9B100519375 /* libASN1.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B60A146DE70A007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B612146DE70A007E536C /* libsecurity_authorization.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B616146DE715007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B61E146DE715007E536C /* libsecurity_cdsa_client.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B622146DE720007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B62B146DE720007E536C /* libsecurity_cdsa_plugin.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B638146DE748007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B644146DE748007E536C /* libsecurity_checkpw.a */, + 1879B648146DE748007E536C /* test-checkpw */, + 1879B64A146DE748007E536C /* perf-checkpw */, + ); + name = Products; + sourceTree = ""; + }; + 1879B64C146DE750007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B654146DE750007E536C /* libsecurity_cms.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B658146DE756007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B666146DE757007E536C /* libsecurity_codesigning.a */, + 1879B66A146DE757007E536C /* libintegrity.a */, + 1879B66C146DE757007E536C /* libcodehost.a */, + C2432A0815C7112A0096DB5B /* gkunpack */, + 7AADF6F619C1062200292339 /* gkoverride */, + EB2E1F58166D6B3700A7EF61 /* com.apple.CodeSigningHelper.xpc */, + ); + name = Products; + sourceTree = ""; + }; + 1879B66E146DE75D007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B676146DE75E007E536C /* libsecurity_comcryption.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B67A146DE76E007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B684146DE76F007E536C /* libsecurity_cryptkit.a */, + 1879B688146DE76F007E536C /* libCryptKit.a */, + 1879B68A146DE76F007E536C /* CryptKitSignature.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B695146DE797007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B69D146DE797007E536C /* libsecurity_filedb.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B6A1146DE79F007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B6B3146DE7A0007E536C /* libsecurity_keychain.a */, + 1879B6B7146DE7A0007E536C /* XPCKeychainSandboxCheck.xpc */, + 52B5A8F6151928B400664F11 /* XPCTimeStampingService.xpc */, + 0CBD50B316C325F000713B6C /* libsecurity_keychain_regressions.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B6C8146DE7D7007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B6D0146DE7D7007E536C /* libsecurity_manifest.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B6D4146DE7E0007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B6DC146DE7E0007E536C /* libsecurity_mds.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B6E0146DE7E7007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B6E9146DE7E8007E536C /* libsecurity_ocspd.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B6ED146DE7EE007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B6F5146DE7EF007E536C /* libsecurity_pkcs12.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B6F9146DE7F7007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B701146DE7F7007E536C /* libsecurity_sd_cspdl.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B713146DE825007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B71C146DE825007E536C /* libsecurity_smime.a */, + ACB6171818B5231800EBEDD7 /* libsecurity_smime_regressions.a */, + ); + name = Products; + sourceTree = ""; + }; + 1879B720146DE839007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B728146DE839007E536C /* libsecurity_ssl.a */, + 0C6D77CD15C8B66000BB4405 /* libsecurity_ssl_kext.a */, + 0C6D77CF15C8B66000BB4405 /* libsecurity_ssl_regressions.a */, + 0C6D77D115C8B66000BB4405 /* dtlsEchoClient */, + 0C6D77D315C8B66000BB4405 /* dtlsEchoServer */, + ); + name = Products; + sourceTree = ""; + }; + 1879B72C146DE844007E536C /* Products */ = { + isa = PBXGroup; + children = ( + 1879B739146DE845007E536C /* libsecurity_transform.a */, + 1879B73D146DE845007E536C /* unit-tests.octest */, + 1879B73F146DE845007E536C /* 100-sha2 */, + 1879B741146DE845007E536C /* input-speed-test */, + ); + name = Products; + sourceTree = ""; + }; + 18F234ED15C9F9A700060520 /* authd */ = { + isa = PBXGroup; + children = ( + 18F234F915C9FA3B00060520 /* agent.c */, + 18F234FA15C9FA3B00060520 /* agent.h */, + 18F2351A15C9FA3C00060520 /* authd_private.h */, + 18F234FB15C9FA3B00060520 /* authdb.c */, + 18F234FC15C9FA3B00060520 /* authdb.h */, + 18F234FD15C9FA3B00060520 /* authitems.c */, + 18F234FE15C9FA3B00060520 /* authitems.h */, + 18F234FF15C9FA3B00060520 /* authtoken.c */, + 18F2350015C9FA3B00060520 /* authtoken.h */, + 18F2350115C9FA3B00060520 /* authtypes.h */, + 18F2350215C9FA3B00060520 /* authutilities.c */, + 18F2350315C9FA3B00060520 /* authutilities.h */, + 18F2350415C9FA3B00060520 /* ccaudit.c */, + 18F2350515C9FA3B00060520 /* ccaudit.h */, + 182A191015D09AFF006AB103 /* connection.c */, + 182A190F15D09AF0006AB103 /* connection.h */, + 18F2350615C9FA3B00060520 /* crc.c */, + 18F2350715C9FA3B00060520 /* crc.h */, + 18F2350815C9FA3B00060520 /* credential.c */, + 18F2350915C9FA3B00060520 /* credential.h */, + 18F2350A15C9FA3B00060520 /* debugging.c */, + 18F2350B15C9FA3B00060520 /* debugging.h */, + 18F2350F15C9FA3B00060520 /* engine.c */, + 18F2351015C9FA3B00060520 /* engine.h */, + 18F2351115C9FA3B00060520 /* main.c */, + 18F2351215C9FA3B00060520 /* mechanism.c */, + 18F2351315C9FA3B00060520 /* mechanism.h */, + 18F2351415C9FA3C00060520 /* object.c */, + 18F2351515C9FA3C00060520 /* object.h */, + 18F2351615C9FA3C00060520 /* process.c */, + 18F2351715C9FA3C00060520 /* process.h */, + 18F2351815C9FA3C00060520 /* rule.c */, + 18F2351915C9FA3C00060520 /* rule.h */, + 18F2351D15C9FA3C00060520 /* server.c */, + 18F2351E15C9FA3C00060520 /* server.h */, + 18F2351F15C9FA3C00060520 /* session.c */, + 18F2352015C9FA3C00060520 /* session.h */, + 18F2353415C9FA7F00060520 /* Supporting Files */, + ); + path = authd; + sourceTree = ""; + }; + 18F2353415C9FA7F00060520 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 18D6803916B768D500DF6D2E /* com.apple.authd */, + 18CFEE8715DEE25200E3F2A3 /* com.apple.authd.sb */, + 187D6B9515D436BF00E27494 /* authorization.plist */, + 18F2350D15C9FA3B00060520 /* InfoPlist.strings */, + 18F2351B15C9FA3C00060520 /* Info.plist */, + 18F2351C15C9FA3C00060520 /* security.auth-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 4C0F6FAF1985879300178101 /* sectask */ = { + isa = PBXGroup; + children = ( + 4C0F6F861985877800178101 /* SecEntitlements.h */, + ); + name = sectask; + path = ../sectask; + sourceTree = ""; + }; + 37A7CEAC197DB8FA00926CE8 /* codesign_tests */ = { + isa = PBXGroup; + children = ( + 37A7CEAD197DB8FA00926CE8 /* FatDynamicValidation.c */, + 37A7CEDB197DCDD700926CE8 /* validation.sh */, + ); + path = codesign_tests; + sourceTree = ""; + }; + 4C1288F615FFECF2008CE3E3 /* utilities */ = { + isa = PBXGroup; + children = ( + 0CC3355B16C1EF5D00399E53 /* regressions.xcodeproj */, + 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */, + ); + path = utilities; + sourceTree = ""; + }; + 4C12893815FFECF3008CE3E3 /* Products */ = { + isa = PBXGroup; + children = ( + 4C12894015FFECF3008CE3E3 /* libutilities.a */, + 4C12894215FFECF3008CE3E3 /* libutilitiesRegressions.a */, + ); + name = Products; + sourceTree = ""; + }; + 4C96F7C316D6DF8400D3B39D /* Keychain Circle Notification */ = { + isa = PBXGroup; + children = ( + 4CD1980B16DD3BDF00A9E8FD /* NSArray+mapWithBlock.h */, + 4CD1980C16DD3BDF00A9E8FD /* NSArray+mapWithBlock.m */, + 4C96F7CF16D6DF8400D3B39D /* KNAppDelegate.h */, + 4C96F7D016D6DF8400D3B39D /* KNAppDelegate.m */, + 4C96F7D216D6DF8400D3B39D /* MainMenu.xib */, + 4C5DD44217A5E31900696A79 /* KNPersistantState.h */, + 4C5DD44317A5E31900696A79 /* KNPersistantState.m */, + 4C96F7C416D6DF8400D3B39D /* Supporting Files */, + 4CB9121C17750E6500C1CCCA /* entitlments.plist */, + ); + path = "Keychain Circle Notification"; + sourceTree = ""; + }; + 4C96F7C416D6DF8400D3B39D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 4C7D456417BEE6B700DDD88F /* NSDictionary+compactDescription.h */, + 4C7D456517BEE6B700DDD88F /* NSDictionary+compactDescription.m */, + 4C7D456617BEE6B700DDD88F /* NSSet+compactDescription.h */, + 4C7D456717BEE6B700DDD88F /* NSSet+compactDescription.m */, + 4C7D453B17BEE69B00DDD88F /* NSString+compactDescription.h */, + 4C7D453C17BEE69B00DDD88F /* NSString+compactDescription.m */, + 5328475117850741009118DC /* Localizable.strings */, + 4C96F7C516D6DF8400D3B39D /* Keychain Circle Notification-Info.plist */, + 4C96F7C616D6DF8400D3B39D /* InfoPlist.strings */, + 4C96F7C916D6DF8400D3B39D /* main.m */, + 4C96F7CB16D6DF8400D3B39D /* Keychain Circle Notification-Prefix.pch */, + 4C96F7CC16D6DF8400D3B39D /* Credits.rtf */, + 4C49390C16E51ACE00CE110C /* com.apple.security.keychain-circle-notification.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 4CB23B48169F5873003A0131 /* security2 */ = { + isa = PBXGroup; + children = ( + 4CB23B4B169F5873003A0131 /* security2.1 */, + 4CB23B80169F58DE003A0131 /* security_tool_commands.c */, + 4CB23B82169F592C003A0131 /* sub_commands.h */, + ); + path = security2; + sourceTree = ""; + }; + 4CC7A7B516CC2A85003E10C1 /* KeychainDemoApp */ = { + isa = PBXGroup; + children = ( + 4CC7A7C116CC2A85003E10C1 /* KDAppDelegate.h */, + 4CC7A7C216CC2A85003E10C1 /* KDAppDelegate.m */, + 4C85DED816DBD5BF00ED8D47 /* KDCirclePeer.h */, + 4C85DED916DBD5BF00ED8D47 /* KDCirclePeer.m */, + 4CC7A7F416CD95D2003E10C1 /* KDSecItems.h */, + 4CC7A7F516CD95D3003E10C1 /* KDSecItems.m */, + 4CC7A7C416CC2A85003E10C1 /* MainMenu.xib */, + 4C96F73816D5372C00D3B39D /* KDSecCircle.h */, + 4C96F73916D5372C00D3B39D /* KDSecCircle.m */, + 4CC7A7B616CC2A85003E10C1 /* Supporting Files */, + ); + name = KeychainDemoApp; + path = Keychain; + sourceTree = ""; + }; + 4CC7A7B616CC2A85003E10C1 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 4C2505B616D2DF9F002CE025 /* Icon.icns */, + 4CC7A7B716CC2A85003E10C1 /* Keychain-Info.plist */, + 4CC7A7B816CC2A85003E10C1 /* InfoPlist.strings */, + 4CC7A7BB16CC2A85003E10C1 /* main.m */, + 4CC7A7BD16CC2A85003E10C1 /* Keychain-Prefix.pch */, + 4CC7A7BE16CC2A85003E10C1 /* Credits.rtf */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 5214700916977CB800DF0DB3 /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 5214700A16977CB800DF0DB3 /* AppKit.framework */, + 5214700B16977CB800DF0DB3 /* CoreData.framework */, + 5214700C16977CB800DF0DB3 /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 5214700D16977CB800DF0DB3 /* CloudKeychainProxy */ = { + isa = PBXGroup; + children = ( + 52C3D235169B56860091D9D3 /* ckdmain.m */, + 5214700E16977CB800DF0DB3 /* Supporting Files */, + ); + path = CloudKeychainProxy; + sourceTree = ""; + }; + 5214700E16977CB800DF0DB3 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 5214702416977FEC00DF0DB3 /* cloudkeychain.entitlements.plist */, + 5214702516977FEC00DF0DB3 /* com.apple.security.cloudkeychainproxy.plist */, + 5214700F16977CB800DF0DB3 /* CloudKeychainProxy-Info.plist */, + 5214701016977CB800DF0DB3 /* InfoPlist.strings */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 721680A7179B40F600406BB4 /* iCloudStats */ = { + isa = PBXGroup; + children = ( + 721680A8179B40F600406BB4 /* main.c */, + 721680AA179B40F600406BB4 /* iCloudStats.1 */, + 721680BD179B4F9100406BB4 /* com.apple.iCloudStats.plist */, + ); + path = iCloudStats; + sourceTree = ""; + }; + 72756C00175D485D00F52070 /* cloud_keychain_diagnose */ = { + isa = PBXGroup; + children = ( + 72756C30175D48C100F52070 /* cloud_keychain_diagnose.c */, + 72756C03175D485D00F52070 /* Supporting Files */, + ); + path = cloud_keychain_diagnose; + sourceTree = ""; + }; + 72756C03175D485D00F52070 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 72756C04175D485D00F52070 /* cloud_keychain_diagnose-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + EB22F3CE18A26B640016A8EC /* Breadcrumb */ = { + isa = PBXGroup; + children = ( + EBD8B52718A55668004A650F /* README */, + EB22F3F518A26BA50016A8EC /* bc-10-knife-on-bread.c */, + EB22F3F618A26BA50016A8EC /* breadcrumb_regressions.h */, + EB22F3F718A26BA50016A8EC /* SecBreadcrumb.c */, + EB22F3F818A26BA50016A8EC /* SecBreadcrumb.h */, + ); + name = Breadcrumb; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 18073848146D0D4E00F05C24 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18FE67E71471A3AA00A2CBE3 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 18FE68021471A42900A2CBE3 /* SecDigestTransform.h in Headers */, + 18FE68031471A42900A2CBE3 /* SecReadTransform.h in Headers */, + 18FE68041471A42900A2CBE3 /* SecTransform.h in Headers */, + 18FE68051471A42900A2CBE3 /* SecCustomTransform.h in Headers */, + 18FE68061471A42900A2CBE3 /* SecDecodeTransform.h in Headers */, + 18FE68071471A42900A2CBE3 /* SecEncodeTransform.h in Headers */, + 18FE68081471A42900A2CBE3 /* SecEncryptTransform.h in Headers */, + 18FE68091471A42900A2CBE3 /* SecSignVerifyTransform.h in Headers */, + 18FE680A1471A42900A2CBE3 /* SecTransformReadTransform.h in Headers */, + 18FE680B1471A42900A2CBE3 /* CipherSuite.h in Headers */, + 18FE680C1471A42900A2CBE3 /* SecureTransport.h in Headers */, + 18FE680D1471A42900A2CBE3 /* mds.h in Headers */, + 18FE680E1471A42900A2CBE3 /* mds_schema.h in Headers */, + 18FE680F1471A42900A2CBE3 /* SecureDownload.h in Headers */, + 18FE68101471A42900A2CBE3 /* SecAccess.h in Headers */, + 18FE68111471A42900A2CBE3 /* SecACL.h in Headers */, + 18FE68121471A42900A2CBE3 /* SecBase.h in Headers */, + 18FE68131471A42900A2CBE3 /* SecCertificate.h in Headers */, + 18FE68141471A42900A2CBE3 /* SecIdentity.h in Headers */, + 18FE68151471A42900A2CBE3 /* SecIdentitySearch.h in Headers */, + 18FE68161471A42900A2CBE3 /* SecItem.h in Headers */, + 18FE68171471A42900A2CBE3 /* SecKey.h in Headers */, + 18FE68181471A42900A2CBE3 /* SecKeychain.h in Headers */, + 18FE68191471A42900A2CBE3 /* SecKeychainItem.h in Headers */, + 18FE681A1471A42900A2CBE3 /* SecKeychainSearch.h in Headers */, + 18FE681B1471A42900A2CBE3 /* SecPolicy.h in Headers */, + 18FE681C1471A42900A2CBE3 /* SecPolicySearch.h in Headers */, + 18FE681D1471A42900A2CBE3 /* SecTrust.h in Headers */, + 18FE681E1471A42900A2CBE3 /* SecTrustedApplication.h in Headers */, + 18FE681F1471A42900A2CBE3 /* Security.h in Headers */, + 18FE68201471A42900A2CBE3 /* SecImportExport.h in Headers */, + 18FE68211471A42900A2CBE3 /* SecTrustSettings.h in Headers */, + 18FE68221471A42900A2CBE3 /* SecCertificateOIDs.h in Headers */, + 18FE68231471A42900A2CBE3 /* SecRandom.h in Headers */, + 18FE68241471A42900A2CBE3 /* SecTask.h in Headers */, + 18FE68251471A42900A2CBE3 /* CodeSigning.h in Headers */, + 18FE68261471A42900A2CBE3 /* CSCommon.h in Headers */, + 18FE68271471A42900A2CBE3 /* SecCode.h in Headers */, + 18FE68281471A42900A2CBE3 /* SecStaticCode.h in Headers */, + 18FE68291471A42900A2CBE3 /* SecRequirement.h in Headers */, + 18FE682A1471A42900A2CBE3 /* SecCodeHost.h in Headers */, + 18FE682B1471A42900A2CBE3 /* CMSDecoder.h in Headers */, + 18FE682C1471A42900A2CBE3 /* CMSEncoder.h in Headers */, + EB22F3FA18A26BCE0016A8EC /* SecBreadcrumb.h in Headers */, + 18FE682D1471A42900A2CBE3 /* AuthorizationTags.h in Headers */, + 18FE682E1471A42900A2CBE3 /* AuthSession.h in Headers */, + 18FE682F1471A42900A2CBE3 /* Authorization.h in Headers */, + 18FE68301471A42900A2CBE3 /* AuthorizationDB.h in Headers */, + 18FE68311471A42900A2CBE3 /* AuthorizationPlugin.h in Headers */, + 18FE68321471A42900A2CBE3 /* SecAsn1Coder.h in Headers */, + 18FE68331471A42900A2CBE3 /* SecAsn1Templates.h in Headers */, + 18FE68341471A42900A2CBE3 /* SecAsn1Types.h in Headers */, + 44B2606818F81A7D008DF20F /* SecAccessControl.h in Headers */, + 18FE68351471A42900A2CBE3 /* certextensions.h in Headers */, + 18FE68361471A42900A2CBE3 /* cssm.h in Headers */, + 18FE68371471A42900A2CBE3 /* cssmaci.h in Headers */, + 18FE68381471A42900A2CBE3 /* cssmapi.h in Headers */, + 18FE68391471A42900A2CBE3 /* cssmapple.h in Headers */, + 18FE683A1471A42900A2CBE3 /* cssmcli.h in Headers */, + 18FE683B1471A42900A2CBE3 /* cssmconfig.h in Headers */, + 18FE683C1471A42900A2CBE3 /* cssmcspi.h in Headers */, + 18FE683D1471A42900A2CBE3 /* cssmdli.h in Headers */, + 18FE683E1471A42900A2CBE3 /* cssmerr.h in Headers */, + 18FE683F1471A42900A2CBE3 /* cssmkrapi.h in Headers */, + 18FE68401471A42900A2CBE3 /* cssmkrspi.h in Headers */, + 18FE68411471A42900A2CBE3 /* cssmspi.h in Headers */, + 18FE68421471A42900A2CBE3 /* cssmtpi.h in Headers */, + 18FE68431471A42900A2CBE3 /* cssmtype.h in Headers */, + 18FE68441471A42900A2CBE3 /* eisl.h in Headers */, + 18FE68451471A42900A2CBE3 /* emmspi.h in Headers */, + 18FE68461471A42900A2CBE3 /* emmtype.h in Headers */, + 18FE68491471A42900A2CBE3 /* oidsbase.h in Headers */, + 18FE684A1471A42900A2CBE3 /* oidscert.h in Headers */, + 18FE684B1471A42900A2CBE3 /* oidscrl.h in Headers */, + 18FE684C1471A42900A2CBE3 /* x509defs.h in Headers */, + 18FE684D1471A46600A2CBE3 /* asn1Templates.h in Headers */, + 18FE684E1471A46600A2CBE3 /* AuthorizationPriv.h in Headers */, + 18FE684F1471A46600A2CBE3 /* AuthorizationTagsPriv.h in Headers */, + 18FE68501471A46600A2CBE3 /* certExtensionTemplates.h in Headers */, + 18FE68511471A46600A2CBE3 /* checkpw.h in Headers */, + CDDE9D1E1729E2E60013B0E8 /* SecPasswordGenerate.h in Headers */, + 18FE68521471A46600A2CBE3 /* CMSPrivate.h in Headers */, + 18FE68531471A46600A2CBE3 /* CSCommonPriv.h in Headers */, + 18FE68541471A46600A2CBE3 /* csrTemplates.h in Headers */, + 18FE68551471A46600A2CBE3 /* cssmapplePriv.h in Headers */, + 18FE68561471A46600A2CBE3 /* keyTemplates.h in Headers */, + 18FE68571471A46600A2CBE3 /* mdspriv.h in Headers */, + 18FE68581471A46600A2CBE3 /* nameTemplates.h in Headers */, + 18FE68591471A46600A2CBE3 /* ocspTemplates.h in Headers */, + 44B2606A18F81C0F008DF20F /* SecAccessControlPriv.h in Headers */, + 18FE685A1471A46600A2CBE3 /* osKeyTemplates.h in Headers */, + 18FE685B1471A46600A2CBE3 /* SecAccessPriv.h in Headers */, + 18FE685C1471A46600A2CBE3 /* secasn1t.h in Headers */, + 18FE685D1471A46600A2CBE3 /* SecAssessment.h in Headers */, + 18FE685E1471A46600A2CBE3 /* SecBasePriv.h in Headers */, + 18FE685F1471A46600A2CBE3 /* SecCertificateBundle.h in Headers */, + 18FE68611471A46600A2CBE3 /* SecCertificatePriv.h in Headers */, + 18FE68621471A46600A2CBE3 /* SecCertificateRequest.h in Headers */, + 18FE68631471A46600A2CBE3 /* SecCmsBase.h in Headers */, + AC5688BC18B4396D00F0526C /* SecCMS.h in Headers */, + 18FE68641471A46600A2CBE3 /* SecCmsContentInfo.h in Headers */, + 18FE68651471A46600A2CBE3 /* SecCmsDecoder.h in Headers */, + 18FE68661471A46600A2CBE3 /* SecCmsDigestContext.h in Headers */, + 18FE68671471A46600A2CBE3 /* SecCmsDigestedData.h in Headers */, + 18FE68681471A46600A2CBE3 /* SecCmsEncoder.h in Headers */, + 18FE68691471A46600A2CBE3 /* SecCmsEncryptedData.h in Headers */, + 18FE686A1471A46600A2CBE3 /* SecCmsEnvelopedData.h in Headers */, + 18FE686B1471A46600A2CBE3 /* SecCmsMessage.h in Headers */, + 18FE686C1471A46600A2CBE3 /* SecCmsRecipientInfo.h in Headers */, + 18FE686D1471A46600A2CBE3 /* SecCmsSignedData.h in Headers */, + 18FE686E1471A46600A2CBE3 /* SecCmsSignerInfo.h in Headers */, + 18FE686F1471A46600A2CBE3 /* SecCodeHostLib.h in Headers */, + 18FE68701471A46600A2CBE3 /* SecCodePriv.h in Headers */, + 18FE68711471A46600A2CBE3 /* SecCodeSigner.h in Headers */, + 18FE68721471A46600A2CBE3 /* SecFDERecoveryAsymmetricCrypto.h in Headers */, + 18FE68731471A46600A2CBE3 /* SecIdentityPriv.h in Headers */, + 4C0F6F871985877800178101 /* SecEntitlements.h in Headers */, + 18FE68741471A46600A2CBE3 /* SecIdentitySearchPriv.h in Headers */, + 18FE68751471A46600A2CBE3 /* SecIntegrity.h in Headers */, + 18FE68761471A46600A2CBE3 /* SecIntegrityLib.h in Headers */, + 18FE68771471A46600A2CBE3 /* SecItemPriv.h in Headers */, + 18FE68781471A46600A2CBE3 /* SecKeychainItemExtendedAttributes.h in Headers */, + 0C03D62B17D93EED0087643B /* SecDH.h in Headers */, + 18FE68791471A46600A2CBE3 /* SecKeychainItemPriv.h in Headers */, + 18FE687A1471A46600A2CBE3 /* SecKeychainPriv.h in Headers */, + 18FE687B1471A46700A2CBE3 /* SecKeychainSearchPriv.h in Headers */, + 18FE687C1471A46700A2CBE3 /* SecKeyPriv.h in Headers */, + 18FE687D1471A46700A2CBE3 /* SecManifest.h in Headers */, + 18FE687E1471A46700A2CBE3 /* SecNullTransform.h in Headers */, + 18FE687F1471A46700A2CBE3 /* SecPassword.h in Headers */, + 18FE68801471A46700A2CBE3 /* SecPolicyPriv.h in Headers */, + 18FE68811471A46700A2CBE3 /* SecRandomP.h in Headers */, + 18FE68821471A46700A2CBE3 /* SecRecoveryPassword.h in Headers */, + 18FE68831471A46700A2CBE3 /* SecRequirementPriv.h in Headers */, + 18FE68841471A46700A2CBE3 /* SecSMIME.h in Headers */, + 18FE68851471A46700A2CBE3 /* SecStaticCodePriv.h in Headers */, + 18FE68861471A46700A2CBE3 /* SecTransformInternal.h in Headers */, + 18FE68871471A46700A2CBE3 /* SecTrustedApplicationPriv.h in Headers */, + BEC3A76816F79497003E5634 /* SecTaskPriv.h in Headers */, + 18FE68881471A46700A2CBE3 /* SecTrustPriv.h in Headers */, + 18FE68891471A46700A2CBE3 /* SecTrustSettingsPriv.h in Headers */, + 18FE688A1471A46700A2CBE3 /* SecureDownloadInternal.h in Headers */, + 18FE688B1471A46700A2CBE3 /* SecureTransportPriv.h in Headers */, + 18FE688C1471A46700A2CBE3 /* TrustSettingsSchema.h in Headers */, + 18FE688D1471A46700A2CBE3 /* X509Templates.h in Headers */, + 0C4F055E15C9E51A00F9DFD5 /* sslTypes.h in Headers */, + 18BBC7361471F5A300F2B224 /* SecExternalSourceTransform.h in Headers */, + 18B647EC14D9F20500F538BF /* oidsalg.h in Headers */, + 52B5A9C21519330300664F11 /* tsaSupport.h in Headers */, + 52B5A9C31519330300664F11 /* tsaTemplates.h in Headers */, + 52AEA489153C778C005AFC59 /* tsaSupportPriv.h in Headers */, + 18B647ED14D9F20F00F538BF /* oidsattr.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4AF95B8B16193B1B00662B04 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 0C6C630A15D193C800BC68CD /* sectests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0C6C631215D193C900BC68CD /* Build configuration list for PBXNativeTarget "sectests" */; + buildPhases = ( + 0C6C630715D193C800BC68CD /* Sources */, + 0C6C630815D193C800BC68CD /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 0C6C632E15D19D2900BC68CD /* PBXTargetDependency */, + ACB6173F18B5232700EBEDD7 /* PBXTargetDependency */, + 0CBD50C716C3260D00713B6C /* PBXTargetDependency */, + 0CCEBDB316C2CFD4001BD7F6 /* PBXTargetDependency */, + ); + name = sectests; + productName = sectests; + productReference = 0C6C630B15D193C800BC68CD /* sectests */; + productType = "com.apple.product-type.tool"; + }; + 0CC3350716C1ED8000399E53 /* secdtests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0CC3352A16C1ED8000399E53 /* Build configuration list for PBXNativeTarget "secdtests" */; + buildPhases = ( + 0CC3351616C1ED8000399E53 /* Sources */, + 0CC3351B16C1ED8000399E53 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 0CC3350A16C1ED8000399E53 /* PBXTargetDependency */, + 0CC3351016C1ED8000399E53 /* PBXTargetDependency */, + 0CC3351216C1ED8000399E53 /* PBXTargetDependency */, + 0CC3351416C1ED8000399E53 /* PBXTargetDependency */, + 0CC3350816C1ED8000399E53 /* PBXTargetDependency */, + 0CC3356216C1EF8B00399E53 /* PBXTargetDependency */, + 0CC3350C16C1ED8000399E53 /* PBXTargetDependency */, + 0CCEBDBD16C30948001BD7F6 /* PBXTargetDependency */, + 0C4EAE7917668DFF00773425 /* PBXTargetDependency */, + ); + name = secdtests; + productName = sectests; + productReference = 0CC3352D16C1ED8000399E53 /* secdtests */; + productType = "com.apple.product-type.tool"; + }; + 1807384A146D0D4E00F05C24 /* Security */ = { + isa = PBXNativeTarget; + buildConfigurationList = 18073875146D0D4E00F05C24 /* Build configuration list for PBXNativeTarget "Security" */; + buildPhases = ( + 18073846146D0D4E00F05C24 /* Sources */, + 18073847146D0D4E00F05C24 /* Frameworks */, + 18073848146D0D4E00F05C24 /* Headers */, + 18500F961470828E006F9AB4 /* Run Script Generate Strings */, + 18073849146D0D4E00F05C24 /* Resources */, + 18500F9114707E10006F9AB4 /* Run Script Copy XPC Service */, + ); + buildRules = ( + E778BFB91717461800302C14 /* PBXBuildRule */, + ); + dependencies = ( + 1879B545146DE18D007E536C /* PBXTargetDependency */, + 4AD6F6F41651CC2500DB4CE6 /* PBXTargetDependency */, + 4C12894415FFED03008CE3E3 /* PBXTargetDependency */, + 18FE688F1471A4C900A2CBE3 /* PBXTargetDependency */, + 1885B45114D9AB3D00519375 /* PBXTargetDependency */, + 18270F5D14CF655B00B05E7F /* PBXTargetDependency */, + 18AD56A614CDED59008233F2 /* PBXTargetDependency */, + 182BB410146F248D000BF1F3 /* PBXTargetDependency */, + 1879B56C146DE2CF007E536C /* PBXTargetDependency */, + 18B9655C1472F83C005A4D2E /* PBXTargetDependency */, + 182BB4E7146F25AF000BF1F3 /* PBXTargetDependency */, + 182BB3EE146F248D000BF1F3 /* PBXTargetDependency */, + 182BB3F0146F248D000BF1F3 /* PBXTargetDependency */, + 182BB3F2146F248D000BF1F3 /* PBXTargetDependency */, + 182BB3F4146F248D000BF1F3 /* PBXTargetDependency */, + 182BB3F6146F248D000BF1F3 /* PBXTargetDependency */, + 182BB3F8146F248D000BF1F3 /* PBXTargetDependency */, + 182BB3FC146F248D000BF1F3 /* PBXTargetDependency */, + 182BB3FE146F248D000BF1F3 /* PBXTargetDependency */, + 182BB400146F248D000BF1F3 /* PBXTargetDependency */, + 182BB402146F248D000BF1F3 /* PBXTargetDependency */, + 182BB404146F248D000BF1F3 /* PBXTargetDependency */, + 182BB406146F248D000BF1F3 /* PBXTargetDependency */, + 182BB408146F248D000BF1F3 /* PBXTargetDependency */, + 182BB40A146F248D000BF1F3 /* PBXTargetDependency */, + 182BB40C146F248D000BF1F3 /* PBXTargetDependency */, + 182BB40E146F248D000BF1F3 /* PBXTargetDependency */, + 182BB412146F248D000BF1F3 /* PBXTargetDependency */, + 182BB414146F248D000BF1F3 /* PBXTargetDependency */, + 182BB418146F248D000BF1F3 /* PBXTargetDependency */, + 182BB41A146F248D000BF1F3 /* PBXTargetDependency */, + 182BB3EC146F2448000BF1F3 /* PBXTargetDependency */, + 18446082146DF52F00B12992 /* PBXTargetDependency */, + 1879B56E146DE2D3007E536C /* PBXTargetDependency */, + 5208C0FE16A0D3980062DDC5 /* PBXTargetDependency */, + E76079FA1951FDF600F69731 /* PBXTargetDependency */, + 182BB22C146F07DD000BF1F3 /* PBXTargetDependency */, + 529FF2201523BD7F0029D842 /* PBXTargetDependency */, + ); + name = Security; + productName = Security; + productReference = 1807384B146D0D4E00F05C24 /* Security.framework */; + productType = "com.apple.product-type.framework"; + }; + 18270ED514CF282600B05E7F /* secd */ = { + isa = PBXNativeTarget; + buildConfigurationList = 18270EDD14CF282600B05E7F /* Build configuration list for PBXNativeTarget "secd" */; + buildPhases = ( + 18270ED214CF282600B05E7F /* Sources */, + 18270ED314CF282600B05E7F /* Frameworks */, + 18BEB19914CF7F0B00C8BD36 /* CopyFiles */, + 0C6D003C177B545D0095D167 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + 4C8D8650177A75100019A804 /* PBXTargetDependency */, + 4C01DF13164C3E74006798CD /* PBXTargetDependency */, + 4C7D8764160A746E00D041E3 /* PBXTargetDependency */, + 18270EE314CF28D900B05E7F /* PBXTargetDependency */, + 18270EE114CF28D000B05E7F /* PBXTargetDependency */, + ); + name = secd; + productName = secd; + productReference = 18270ED614CF282600B05E7F /* secd */; + productType = "com.apple.product-type.tool"; + }; + 182BB567146F4DCA000BF1F3 /* csparser */ = { + isa = PBXNativeTarget; + buildConfigurationList = 182BB572146F4DCB000BF1F3 /* Build configuration list for PBXNativeTarget "csparser" */; + buildPhases = ( + 182BB564146F4DCA000BF1F3 /* Sources */, + 182BB565146F4DCA000BF1F3 /* Frameworks */, + 182BB566146F4DCA000BF1F3 /* Resources */, + 182BB583146FDD3C000BF1F3 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 182BB596146FE27F000BF1F3 /* PBXTargetDependency */, + 182BB58F146FE11C000BF1F3 /* PBXTargetDependency */, + 182BB58D146FE0FF000BF1F3 /* PBXTargetDependency */, + 182BB588146FE001000BF1F3 /* PBXTargetDependency */, + ); + name = csparser; + productName = csparser; + productReference = 182BB568146F4DCA000BF1F3 /* csparser.bundle */; + productType = "com.apple.product-type.bundle"; + }; + 18F234EA15C9F9A600060520 /* authd */ = { + isa = PBXNativeTarget; + buildConfigurationList = 18F234F615C9F9A700060520 /* Build configuration list for PBXNativeTarget "authd" */; + buildPhases = ( + 4AF95B8B16193B1B00662B04 /* Headers */, + 18F234E715C9F9A600060520 /* Sources */, + 18F234E815C9F9A600060520 /* Frameworks */, + 187D6B9615D4381C00E27494 /* Copy authorization.plist */, + 18CFEE8815DEE2BA00E3F2A3 /* Copy sandbox profile */, + 4A5C178F161A9DE000ABF784 /* CopyFiles */, + 18D6803A16B768DE00DF6D2E /* Copy asl module */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = authd; + productName = security.auth; + productReference = 18F234EB15C9F9A600060520 /* authd.xpc */; + productType = "com.apple.product-type.bundle"; + }; + 18FE67E91471A3AA00A2CBE3 /* copyHeaders */ = { + isa = PBXNativeTarget; + buildConfigurationList = 18FE67FB1471A3AA00A2CBE3 /* Build configuration list for PBXNativeTarget "copyHeaders" */; + buildPhases = ( + 18FE67E71471A3AA00A2CBE3 /* Headers */, + 4CB86AE4167A6F3D00F46643 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = copyHeaders; + productName = copyHeaders; + productReference = 18FE67EA1471A3AA00A2CBE3 /* Security.framework */; + productType = "com.apple.product-type.framework"; + }; + 37A7CEAA197DB8FA00926CE8 /* codesign_tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 37A7CED8197DB8FA00926CE8 /* Build configuration list for PBXNativeTarget "codesign_tests" */; + buildPhases = ( + 37A7CEA7197DB8FA00926CE8 /* Sources */, + 37A7CEA8197DB8FA00926CE8 /* Frameworks */, + 37A7CEDC197DCECD00926CE8 /* CopyFiles */, + 37A7CF21197DD10900926CE8 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = codesign_tests; + productName = codesign_tests; + productReference = 37A7CEAB197DB8FA00926CE8 /* codesign_tests */; + productType = "com.apple.product-type.tool"; + }; + 4C96F7C016D6DF8300D3B39D /* Keychain Circle Notification */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4C96F7D516D6DF8400D3B39D /* Build configuration list for PBXNativeTarget "Keychain Circle Notification" */; + buildPhases = ( + 4C96F7BD16D6DF8300D3B39D /* Sources */, + 4C96F7BE16D6DF8300D3B39D /* Frameworks */, + 4C96F7BF16D6DF8300D3B39D /* Resources */, + 4C49390E16E51ED100CE110C /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Keychain Circle Notification"; + productName = "Keychain Circle Notification"; + productReference = 4C96F7C116D6DF8300D3B39D /* Keychain Circle Notification.app */; + productType = "com.apple.product-type.application"; + }; + 4CB23B45169F5873003A0131 /* security2 */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4CB23B7F169F5873003A0131 /* Build configuration list for PBXNativeTarget "security2" */; + buildPhases = ( + 4CB23B42169F5873003A0131 /* Sources */, + 4CB23B43169F5873003A0131 /* Frameworks */, + 4CB23B44169F5873003A0131 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + 4CB23B88169F597D003A0131 /* PBXTargetDependency */, + 4CB23B86169F5971003A0131 /* PBXTargetDependency */, + 4CB23B84169F5961003A0131 /* PBXTargetDependency */, + ); + name = security2; + productName = security2; + productReference = 4CB23B46169F5873003A0131 /* security2 */; + productType = "com.apple.product-type.tool"; + }; + 4CC7A7B216CC2A84003E10C1 /* Cloud Keychain Utility */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4CC7A7EF16CC2A85003E10C1 /* Build configuration list for PBXNativeTarget "Cloud Keychain Utility" */; + buildPhases = ( + 4CC7A7AF16CC2A84003E10C1 /* Sources */, + 4CC7A7B016CC2A84003E10C1 /* Frameworks */, + 4CC7A7B116CC2A84003E10C1 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Cloud Keychain Utility"; + productName = Keychain; + productReference = 4CC7A7B316CC2A84003E10C1 /* Cloud Keychain Utility.app */; + productType = "com.apple.product-type.application"; + }; + 5214700516977CB800DF0DB3 /* CloudKeychainProxy */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5214701416977CB800DF0DB3 /* Build configuration list for PBXNativeTarget "CloudKeychainProxy" */; + buildPhases = ( + 5214700216977CB800DF0DB3 /* Sources */, + 5214700316977CB800DF0DB3 /* Frameworks */, + 5214700416977CB800DF0DB3 /* Resources */, + 5214702316977EA600DF0DB3 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + 5214701A16977D2500DF0DB3 /* PBXTargetDependency */, + 5214701816977D1D00DF0DB3 /* PBXTargetDependency */, + ); + name = CloudKeychainProxy; + productName = CloudKeychainProxy; + productReference = 5214700616977CB800DF0DB3 /* CloudKeychainProxy.bundle */; + productType = "com.apple.product-type.bundle"; + }; + 72756BFD175D485D00F52070 /* cloud_keychain_diagnose */ = { + isa = PBXNativeTarget; + buildConfigurationList = 72756C2F175D485D00F52070 /* Build configuration list for PBXNativeTarget "cloud_keychain_diagnose" */; + buildPhases = ( + 72756BFA175D485D00F52070 /* Sources */, + 72756BFB175D485D00F52070 /* Frameworks */, + 72756BFC175D485D00F52070 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = cloud_keychain_diagnose; + productName = cloud_keychain_diagnose; + productReference = 72756BFE175D485D00F52070 /* cloud_keychain_diagnose */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 18073841146D0D4E00F05C24 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + TargetAttributes = { + 37A7CEAA197DB8FA00926CE8 = { + CreatedOnToolsVersion = 6.0; + }; + }; + }; + buildConfigurationList = 18073844146D0D4E00F05C24 /* Build configuration list for PBXProject "Security" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 1807383F146D0D4E00F05C24; + productRefGroup = 1807384C146D0D4E00F05C24 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 18270F0914CF43C000B05E7F /* Products */; + ProjectRef = 18270F0814CF43C000B05E7F /* libDER.xcodeproj */; + }, + { + ProductGroup = 1879B5BD146DE6C8007E536C /* Products */; + ProjectRef = 1879B5BC146DE6C8007E536C /* libsecurity_apple_csp.xcodeproj */; + }, + { + ProductGroup = 1879B5CA146DE6CE007E536C /* Products */; + ProjectRef = 1879B5C9146DE6CE007E536C /* libsecurity_apple_cspdl.xcodeproj */; + }, + { + ProductGroup = 1879B5D6146DE6D7007E536C /* Products */; + ProjectRef = 1879B5D5146DE6D7007E536C /* libsecurity_apple_file_dl.xcodeproj */; + }, + { + ProductGroup = 1879B5E2146DE6E7007E536C /* Products */; + ProjectRef = 1879B5E1146DE6E7007E536C /* libsecurity_apple_x509_cl.xcodeproj */; + }, + { + ProductGroup = 1879B5F1146DE6FD007E536C /* Products */; + ProjectRef = 1879B5F0146DE6FD007E536C /* libsecurity_apple_x509_tp.xcodeproj */; + }, + { + ProductGroup = 1879B5FD146DE704007E536C /* Products */; + ProjectRef = 1879B5FC146DE704007E536C /* libsecurity_asn1.xcodeproj */; + }, + { + ProductGroup = 1879B60A146DE70A007E536C /* Products */; + ProjectRef = 1879B609146DE70A007E536C /* libsecurity_authorization.xcodeproj */; + }, + { + ProductGroup = 1879B616146DE715007E536C /* Products */; + ProjectRef = 1879B615146DE715007E536C /* libsecurity_cdsa_client.xcodeproj */; + }, + { + ProductGroup = 1879B622146DE720007E536C /* Products */; + ProjectRef = 1879B621146DE720007E536C /* libsecurity_cdsa_plugin.xcodeproj */; + }, + { + ProductGroup = 1879B551146DE227007E536C /* Products */; + ProjectRef = 1879B550146DE227007E536C /* libsecurity_cdsa_utilities.xcodeproj */; + }, + { + ProductGroup = 1879B548146DE212007E536C /* Products */; + ProjectRef = 1879B547146DE212007E536C /* libsecurity_cdsa_utils.xcodeproj */; + }, + { + ProductGroup = 1879B638146DE748007E536C /* Products */; + ProjectRef = 1879B637146DE748007E536C /* libsecurity_checkpw.xcodeproj */; + }, + { + ProductGroup = 1879B64C146DE750007E536C /* Products */; + ProjectRef = 1879B64B146DE750007E536C /* libsecurity_cms.xcodeproj */; + }, + { + ProductGroup = 1879B658146DE756007E536C /* Products */; + ProjectRef = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; + }, + { + ProductGroup = 1879B66E146DE75D007E536C /* Products */; + ProjectRef = 1879B66D146DE75D007E536C /* libsecurity_comcryption.xcodeproj */; + }, + { + ProductGroup = 1879B67A146DE76E007E536C /* Products */; + ProjectRef = 1879B679146DE76E007E536C /* libsecurity_cryptkit.xcodeproj */; + }, + { + ProductGroup = 1879B55E146DE244007E536C /* Products */; + ProjectRef = 1879B55D146DE244007E536C /* libsecurity_cssm.xcodeproj */; + }, + { + ProductGroup = 1879B695146DE797007E536C /* Products */; + ProjectRef = 1879B694146DE797007E536C /* libsecurity_filedb.xcodeproj */; + }, + { + ProductGroup = 1879B6A1146DE79F007E536C /* Products */; + ProjectRef = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; + }, + { + ProductGroup = 1879B6C8146DE7D7007E536C /* Products */; + ProjectRef = 1879B6C7146DE7D7007E536C /* libsecurity_manifest.xcodeproj */; + }, + { + ProductGroup = 1879B6D4146DE7E0007E536C /* Products */; + ProjectRef = 1879B6D3146DE7E0007E536C /* libsecurity_mds.xcodeproj */; + }, + { + ProductGroup = 1879B6E0146DE7E7007E536C /* Products */; + ProjectRef = 1879B6DF146DE7E7007E536C /* libsecurity_ocspd.xcodeproj */; + }, + { + ProductGroup = 1879B6ED146DE7EE007E536C /* Products */; + ProjectRef = 1879B6EC146DE7EE007E536C /* libsecurity_pkcs12.xcodeproj */; + }, + { + ProductGroup = 1879B6F9146DE7F7007E536C /* Products */; + ProjectRef = 1879B6F8146DE7F7007E536C /* libsecurity_sd_cspdl.xcodeproj */; + }, + { + ProductGroup = 1879B713146DE825007E536C /* Products */; + ProjectRef = 1879B712146DE825007E536C /* libsecurity_smime.xcodeproj */; + }, + { + ProductGroup = 1879B720146DE839007E536C /* Products */; + ProjectRef = 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */; + }, + { + ProductGroup = 1879B72C146DE844007E536C /* Products */; + ProjectRef = 1879B72B146DE844007E536C /* libsecurity_transform.xcodeproj */; + }, + { + ProductGroup = 1879B533146DDBE5007E536C /* Products */; + ProjectRef = 1879B532146DDBE5007E536C /* libsecurity_utilities.xcodeproj */; + }, + { + ProductGroup = 184461A4146E9D3200B12992 /* Products */; + ProjectRef = 184461A3146E9D3200B12992 /* libsecurityd.xcodeproj */; + }, + { + ProductGroup = 0CC3355C16C1EF5D00399E53 /* Products */; + ProjectRef = 0CC3355B16C1EF5D00399E53 /* regressions.xcodeproj */; + }, + { + ProductGroup = 186CDD1714CA11C700AF9171 /* Products */; + ProjectRef = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + }, + { + ProductGroup = 0C6D77DF15C8C06500BB4405 /* Products */; + ProjectRef = 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */; + }, + { + ProductGroup = 4C12893815FFECF3008CE3E3 /* Products */; + ProjectRef = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 186F778814E59FB200434E1F /* Security_frameworks */, + 186F778C14E59FDA00434E1F /* Security_executables */, + 0C6C642915D5ADB500BC68CD /* Security_kexts */, + 182BB598146FE295000BF1F3 /* World */, + 1807384A146D0D4E00F05C24 /* Security */, + 182BB567146F4DCA000BF1F3 /* csparser */, + 18FE67E91471A3AA00A2CBE3 /* copyHeaders */, + 18270ED514CF282600B05E7F /* secd */, + 0CC3350716C1ED8000399E53 /* secdtests */, + 0C6C630A15D193C800BC68CD /* sectests */, + 18F234EA15C9F9A600060520 /* authd */, + 5214700516977CB800DF0DB3 /* CloudKeychainProxy */, + 4CB23B45169F5873003A0131 /* security2 */, + 4CC7A7B216CC2A84003E10C1 /* Cloud Keychain Utility */, + 4C96F7C016D6DF8300D3B39D /* Keychain Circle Notification */, + 4CE4729E16D833FD009070D1 /* Security_temporary_UI */, + 72756BFD175D485D00F52070 /* cloud_keychain_diagnose */, + 37A7CEAA197DB8FA00926CE8 /* codesign_tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 0C4EAE721766865000773425 /* libsecdRegressions.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecdRegressions.a; + remoteRef = 0C4EAE711766865000773425 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 0C6D77CD15C8B66000BB4405 /* libsecurity_ssl_kext.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_ssl_kext.a; + remoteRef = 0C6D77CC15C8B66000BB4405 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 0C6D77CF15C8B66000BB4405 /* libsecurity_ssl_regressions.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_ssl_regressions.a; + remoteRef = 0C6D77CE15C8B66000BB4405 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 0C6D77D115C8B66000BB4405 /* dtlsEchoClient */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = dtlsEchoClient; + remoteRef = 0C6D77D015C8B66000BB4405 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 0C6D77D315C8B66000BB4405 /* dtlsEchoServer */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = dtlsEchoServer; + remoteRef = 0C6D77D215C8B66000BB4405 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 0C6D77E915C8C06600BB4405 /* tlsnke.kext */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = tlsnke.kext; + remoteRef = 0C6D77E815C8C06600BB4405 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 0C6D77EB15C8C06600BB4405 /* tlsnketest */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = tlsnketest; + remoteRef = 0C6D77EA15C8C06600BB4405 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 0C6D77ED15C8C06600BB4405 /* libtlssocket.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libtlssocket.a; + remoteRef = 0C6D77EC15C8C06600BB4405 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 0CBD50B316C325F000713B6C /* libsecurity_keychain_regressions.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_keychain_regressions.a; + remoteRef = 0CBD50B216C325F000713B6C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 0CC3356016C1EF5D00399E53 /* libregressions.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libregressions.a; + remoteRef = 0CC3355F16C1EF5D00399E53 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 18270C7D14CE573D00B05E7F /* libsecurityd.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurityd.a; + remoteRef = 18270C7C14CE573D00B05E7F /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 18270F1214CF43C000B05E7F /* libDER.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libDER.a; + remoteRef = 18270F1114CF43C000B05E7F /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 18270F1414CF43C000B05E7F /* parseCert */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = parseCert; + remoteRef = 18270F1314CF43C000B05E7F /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 18270F1614CF43C000B05E7F /* libDERUtils.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libDERUtils.a; + remoteRef = 18270F1514CF43C000B05E7F /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 18270F1814CF43C000B05E7F /* parseCrl */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = parseCrl; + remoteRef = 18270F1714CF43C000B05E7F /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 18270F1A14CF43C000B05E7F /* parseTicket */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = parseTicket; + remoteRef = 18270F1914CF43C000B05E7F /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 18270F6014CF655B00B05E7F /* libsecipc_client.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecipc_client.a; + remoteRef = 18270F5F14CF655B00B05E7F /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 184461B1146E9D3300B12992 /* libsecurityd_client.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurityd_client.a; + remoteRef = 184461B0146E9D3300B12992 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 184461B5146E9D3300B12992 /* libsecurityd_server.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurityd_server.a; + remoteRef = 184461B4146E9D3300B12992 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 184461B9146E9D3300B12992 /* ucspc.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = ucspc.a; + remoteRef = 184461B8146E9D3300B12992 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 186CDD1E14CA11C700AF9171 /* libSecItemShimOSX.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libSecItemShimOSX.a; + remoteRef = 186CDD1D14CA11C700AF9171 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B538146DDBE5007E536C /* libsecurity_utilities.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_utilities.a; + remoteRef = 1879B537146DDBE5007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B54F146DE212007E536C /* libsecurity_cdsa_utils.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_cdsa_utils.a; + remoteRef = 1879B54E146DE212007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B55A146DE227007E536C /* libsecurity_cdsa_utilities.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_cdsa_utilities.a; + remoteRef = 1879B559146DE227007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B55C146DE227007E536C /* Schemas */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = Schemas; + remoteRef = 1879B55B146DE227007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B565146DE244007E536C /* libsecurity_cssm.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_cssm.a; + remoteRef = 1879B564146DE244007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B5C6146DE6C8007E536C /* libsecurity_apple_csp.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_apple_csp.a; + remoteRef = 1879B5C5146DE6C8007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B5D2146DE6CE007E536C /* libsecurity_apple_cspdl.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_apple_cspdl.a; + remoteRef = 1879B5D1146DE6CE007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B5DE146DE6D7007E536C /* libsecurity_apple_file_dl.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_apple_file_dl.a; + remoteRef = 1879B5DD146DE6D7007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B5EB146DE6E8007E536C /* libsecurity_apple_x509_cl.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_apple_x509_cl.a; + remoteRef = 1879B5EA146DE6E8007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B5EF146DE6E8007E536C /* apple_x509_cl.bundle */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = apple_x509_cl.bundle; + remoteRef = 1879B5EE146DE6E8007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B5F9146DE6FD007E536C /* libsecurity_apple_x509_tp.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_apple_x509_tp.a; + remoteRef = 1879B5F8146DE6FD007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B612146DE70A007E536C /* libsecurity_authorization.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_authorization.a; + remoteRef = 1879B611146DE70A007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B61E146DE715007E536C /* libsecurity_cdsa_client.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_cdsa_client.a; + remoteRef = 1879B61D146DE715007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B62B146DE720007E536C /* libsecurity_cdsa_plugin.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_cdsa_plugin.a; + remoteRef = 1879B62A146DE720007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B644146DE748007E536C /* libsecurity_checkpw.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_checkpw.a; + remoteRef = 1879B643146DE748007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B648146DE748007E536C /* test-checkpw */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = "test-checkpw"; + remoteRef = 1879B647146DE748007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B64A146DE748007E536C /* perf-checkpw */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = "perf-checkpw"; + remoteRef = 1879B649146DE748007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B654146DE750007E536C /* libsecurity_cms.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_cms.a; + remoteRef = 1879B653146DE750007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B666146DE757007E536C /* libsecurity_codesigning.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_codesigning.a; + remoteRef = 1879B665146DE757007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B66A146DE757007E536C /* libintegrity.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libintegrity.a; + remoteRef = 1879B669146DE757007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B66C146DE757007E536C /* libcodehost.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libcodehost.a; + remoteRef = 1879B66B146DE757007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B676146DE75E007E536C /* libsecurity_comcryption.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_comcryption.a; + remoteRef = 1879B675146DE75E007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B684146DE76F007E536C /* libsecurity_cryptkit.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_cryptkit.a; + remoteRef = 1879B683146DE76F007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B688146DE76F007E536C /* libCryptKit.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libCryptKit.a; + remoteRef = 1879B687146DE76F007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B68A146DE76F007E536C /* CryptKitSignature.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = CryptKitSignature.a; + remoteRef = 1879B689146DE76F007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B69D146DE797007E536C /* libsecurity_filedb.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_filedb.a; + remoteRef = 1879B69C146DE797007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B6B3146DE7A0007E536C /* libsecurity_keychain.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_keychain.a; + remoteRef = 1879B6B2146DE7A0007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B6B7146DE7A0007E536C /* XPCKeychainSandboxCheck.xpc */ = { + isa = PBXReferenceProxy; + fileType = wrapper.application; + path = XPCKeychainSandboxCheck.xpc; + remoteRef = 1879B6B6146DE7A0007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B6D0146DE7D7007E536C /* libsecurity_manifest.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_manifest.a; + remoteRef = 1879B6CF146DE7D7007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B6DC146DE7E0007E536C /* libsecurity_mds.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_mds.a; + remoteRef = 1879B6DB146DE7E0007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B6E9146DE7E8007E536C /* libsecurity_ocspd.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_ocspd.a; + remoteRef = 1879B6E8146DE7E8007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B6F5146DE7EF007E536C /* libsecurity_pkcs12.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_pkcs12.a; + remoteRef = 1879B6F4146DE7EF007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B701146DE7F7007E536C /* libsecurity_sd_cspdl.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_sd_cspdl.a; + remoteRef = 1879B700146DE7F7007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B71C146DE825007E536C /* libsecurity_smime.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_smime.a; + remoteRef = 1879B71B146DE825007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B728146DE839007E536C /* libsecurity_ssl.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_ssl.a; + remoteRef = 1879B727146DE839007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B739146DE845007E536C /* libsecurity_transform.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_transform.a; + remoteRef = 1879B738146DE845007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B73D146DE845007E536C /* unit-tests.octest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = "unit-tests.octest"; + remoteRef = 1879B73C146DE845007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B73F146DE845007E536C /* 100-sha2 */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = "100-sha2"; + remoteRef = 1879B73E146DE845007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1879B741146DE845007E536C /* input-speed-test */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = "input-speed-test"; + remoteRef = 1879B740146DE845007E536C /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1885B3F914D8D9B100519375 /* libASN1.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libASN1.a; + remoteRef = 1885B3F814D8D9B100519375 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 18D4053B14CE2C1600A2BE4E /* libsecurity.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity.a; + remoteRef = 18D4053A14CE2C1600A2BE4E /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4C01DE32164C3793006798CD /* libCloudKeychainProxy.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libCloudKeychainProxy.a; + remoteRef = 4C01DE31164C3793006798CD /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4C1288EA15FFE9D7008CE3E3 /* libSecureObjectSync.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libSecureObjectSync.a; + remoteRef = 4C1288E915FFE9D7008CE3E3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4C1288EC15FFE9D7008CE3E3 /* libSOSRegressions.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libSOSRegressions.a; + remoteRef = 4C1288EB15FFE9D7008CE3E3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4C1288EE15FFE9D7008CE3E3 /* libSecurityRegressions.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libSecurityRegressions.a; + remoteRef = 4C1288ED15FFE9D7008CE3E3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4C1288F015FFE9D7008CE3E3 /* libsecuritydRegressions.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecuritydRegressions.a; + remoteRef = 4C1288EF15FFE9D7008CE3E3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4C1288F215FFE9D7008CE3E3 /* libSecOtrOSX.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libSecOtrOSX.a; + remoteRef = 4C1288F115FFE9D7008CE3E3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4C12894015FFECF3008CE3E3 /* libutilities.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libutilities.a; + remoteRef = 4C12893F15FFECF3008CE3E3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4C12894215FFECF3008CE3E3 /* libutilitiesRegressions.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libutilitiesRegressions.a; + remoteRef = 4C12894115FFECF3008CE3E3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4CB23B76169F5873003A0131 /* libSecurityTool.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libSecurityTool.a; + remoteRef = 4CB23B75169F5873003A0131 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4CB23B78169F5873003A0131 /* libSecurityCommands.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libSecurityCommands.a; + remoteRef = 4CB23B77169F5873003A0131 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4CB23B7A169F5873003A0131 /* libSOSCommands.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libSOSCommands.a; + remoteRef = 4CB23B79169F5873003A0131 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 52B5A8F6151928B400664F11 /* XPCTimeStampingService.xpc */ = { + isa = PBXReferenceProxy; + fileType = wrapper.application; + path = XPCTimeStampingService.xpc; + remoteRef = 52B5A8F5151928B400664F11 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 7AADF6F619C1062200292339 /* gkoverride */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = gkoverride; + remoteRef = 7AADF6F519C1062200292339 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + ACB6171818B5231800EBEDD7 /* libsecurity_smime_regressions.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_smime_regressions.a; + remoteRef = ACB6171718B5231800EBEDD7 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + C2432A0815C7112A0096DB5B /* gkunpack */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = gkunpack; + remoteRef = C2432A0715C7112A0096DB5B /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + E760796F1951F99600F69731 /* libSWCAgent.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libSWCAgent.a; + remoteRef = E760796E1951F99600F69731 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + E76079D51951FDA800F69731 /* liblogging.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = liblogging.a; + remoteRef = E76079D41951FDA800F69731 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + EB2E1F58166D6B3700A7EF61 /* com.apple.CodeSigningHelper.xpc */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = com.apple.CodeSigningHelper.xpc; + remoteRef = EB2E1F57166D6B3700A7EF61 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 18073849146D0D4E00F05C24 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1879B4AA146DCA18007E536C /* cssm.mdsinfo in Resources */, + 1844605F146DE93E00B12992 /* csp_capabilities.mdsinfo in Resources */, + 18446060146DE93E00B12992 /* csp_capabilities_common.mds in Resources */, + 18446061146DE93E00B12992 /* csp_common.mdsinfo in Resources */, + 18446062146DE93E00B12992 /* csp_primary.mdsinfo in Resources */, + 184460C7146E7B1E00B12992 /* cspdl_common.mdsinfo in Resources */, + 184460C8146E7B1E00B12992 /* cspdl_csp_capabilities.mdsinfo in Resources */, + 184460C9146E7B1E00B12992 /* cspdl_csp_primary.mdsinfo in Resources */, + 184460CA146E7B1E00B12992 /* cspdl_dl_primary.mdsinfo in Resources */, + 184460E3146E806700B12992 /* dl_common.mdsinfo in Resources */, + 184460E4146E806700B12992 /* dl_primary.mdsinfo in Resources */, + 18446105146E82C800B12992 /* cl_common.mdsinfo in Resources */, + 18446106146E82C800B12992 /* cl_primary.mdsinfo in Resources */, + 18446115146E85A300B12992 /* tp_common.mdsinfo in Resources */, + 18446116146E85A300B12992 /* tp_policyOids.mdsinfo in Resources */, + 18446117146E85A300B12992 /* tp_primary.mdsinfo in Resources */, + 182BB3C5146F1DCB000BF1F3 /* sd_cspdl_common.mdsinfo in Resources */, + 182BB22A146F068B000BF1F3 /* iToolsTrustedApps.plist in Resources */, + 182BB55F146F4544000BF1F3 /* FDEPrefs.plist in Resources */, + 18500F9B14708D0E006F9AB4 /* SecDebugErrorMessages.strings in Resources */, + 18500FA114708F19006F9AB4 /* SecErrorMessages.strings in Resources */, + BE8C5F0A16F7CE450074CF86 /* framework.sb in Resources */, + 188AD8DC1471FE3E0081C619 /* FDELocalizable.strings in Resources */, + 188AD8DD1471FE3E0081C619 /* InfoPlist.strings in Resources */, + 52B006C015238F76005D4556 /* TimeStampingPrefs.plist in Resources */, + 187D6B9315D435BD00E27494 /* authorization.buttons.strings in Resources */, + 187D6B9415D435C700E27494 /* authorization.prompts.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 182BB566146F4DCA000BF1F3 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C96F7BF16D6DF8300D3B39D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 532847791785076B009118DC /* Localizable.strings in Resources */, + 4C49390D16E51ACE00CE110C /* com.apple.security.keychain-circle-notification.plist in Resources */, + 4C96F7C816D6DF8400D3B39D /* InfoPlist.strings in Resources */, + 4C96F7CE16D6DF8400D3B39D /* Credits.rtf in Resources */, + 4C96F7D416D6DF8400D3B39D /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CC7A7B116CC2A84003E10C1 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C2505B716D2DF9F002CE025 /* Icon.icns in Resources */, + 4CC7A7BA16CC2A85003E10C1 /* InfoPlist.strings in Resources */, + 4CC7A7C016CC2A85003E10C1 /* Credits.rtf in Resources */, + 4CC7A7C616CC2A85003E10C1 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5214700416977CB800DF0DB3 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5214702216977E7D00DF0DB3 /* CloudKeychainProxy-Info.plist in Resources */, + 5214701216977CB800DF0DB3 /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 182BB583146FDD3C000BF1F3 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "cd ${BUILT_PRODUCTS_DIR}/Security.framework\n/bin/ln -sF Versions/Current/PlugIns PlugIns\nexit 0"; + showEnvVarsInLog = 0; + }; + 18500F9114707E10006F9AB4 /* Run Script Copy XPC Service */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script Copy XPC Service"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "DST=${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/XPCServices\n\nXPC_SERVICE=XPCKeychainSandboxCheck.xpc\nditto -v ${BUILT_PRODUCTS_DIR}/${XPC_SERVICE} ${DST}/${XPC_SERVICE}\nif [ $0 -ne 0]; then\n exit $0;\nfi\nXPC_SERVICE=XPCTimeStampingService.xpc\nditto -v ${BUILT_PRODUCTS_DIR}/${XPC_SERVICE} ${DST}/${XPC_SERVICE}\n\nif [ $0 -ne 0]; then\n exit $0;\nfi\n\nif [ ! -h ${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/XPCServices ]; then\n ln -s Versions/Current/XPCServices ${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}/XPCServices\nfi\n\nexit 0"; + showEnvVarsInLog = 0; + }; + 18500F961470828E006F9AB4 /* Run Script Generate Strings */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script Generate Strings"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "DERIVED_SRC=${BUILT_PRODUCTS_DIR}/derived_src\nmkdir -p ${DERIVED_SRC}\n\n# make error message string files\n\nGENDEBUGSTRS[0]=YES; ERRORSTRINGS[0]=${DERIVED_SRC}/SecDebugErrorMessages.strings\nGENDEBUGSTRS[1]=NO ; ERRORSTRINGS[1]=${DERIVED_SRC}/en.lproj/SecErrorMessages.strings\n\nmkdir -p ${DERIVED_SRC}/en.lproj\n\nfor ((ix=0;ix<2;ix++)) ; do\nperl lib/generateErrStrings.pl \\\n${GENDEBUGSTRS[ix]} \\\n${DERIVED_SRC} \\\n${ERRORSTRINGS[ix]} \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/Authorization.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/AuthSession.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/SecureTransport.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/SecBase.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/cssmerr.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/cssmapple.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/CSCommon.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/PrivateHeaders/AuthorizationPriv.h \\\n${PROJECT_DIR}/libsecurity_keychain/lib/MacOSErrorStrings.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/PrivateHeaders/SecureTransportPriv.h\ndone"; + showEnvVarsInLog = 0; + }; + 18F2360315CB30EC00060520 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "DST=${BUILT_PRODUCTS_DIR}/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices\n\nXPC_SERVICE=authd.xpc\nditto -v ${BUILT_PRODUCTS_DIR}/${XPC_SERVICE} ${DST}/${XPC_SERVICE}\n\nexit 0"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 0C6C630715D193C800BC68CD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0CCEBDB116C2CFC1001BD7F6 /* main.c in Sources */, + EB22F3FB18A26BE40016A8EC /* bc-10-knife-on-bread.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0CC3351616C1ED8000399E53 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0CC3355A16C1EEE700399E53 /* main.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18073846146D0D4E00F05C24 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18A5493315EFD3690059E6DC /* dummy.cpp in Sources */, + E778BFBC17176DDE00302C14 /* security.exp-in in Sources */, + EB22F3F918A26BCA0016A8EC /* SecBreadcrumb.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18270ED214CF282600B05E7F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18270EF614CF334A00B05E7F /* server.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 182BB564146F4DCA000BF1F3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 182BB57F146F51A5000BF1F3 /* csparser.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18F234E715C9F9A600060520 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18F2352115C9FA3C00060520 /* agent.c in Sources */, + 18F2352215C9FA3C00060520 /* authdb.c in Sources */, + 18F2352315C9FA3C00060520 /* authitems.c in Sources */, + 18F2352415C9FA3C00060520 /* authtoken.c in Sources */, + 18F2352515C9FA3C00060520 /* authutilities.c in Sources */, + 18F2352615C9FA3C00060520 /* ccaudit.c in Sources */, + 18F2352715C9FA3C00060520 /* crc.c in Sources */, + 18F2352815C9FA3C00060520 /* credential.c in Sources */, + 18F2352915C9FA3C00060520 /* debugging.c in Sources */, + 18F2352B15C9FA3C00060520 /* engine.c in Sources */, + 18F2352C15C9FA3C00060520 /* main.c in Sources */, + 18F2352D15C9FA3C00060520 /* mechanism.c in Sources */, + 18F2352E15C9FA3C00060520 /* object.c in Sources */, + 18F2352F15C9FA3C00060520 /* process.c in Sources */, + 18F2353015C9FA3C00060520 /* rule.c in Sources */, + 18F2353215C9FA3C00060520 /* server.c in Sources */, + 18F2353315C9FA3C00060520 /* session.c in Sources */, + 182A191115D09AFF006AB103 /* connection.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 37A7CEA7197DB8FA00926CE8 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 37A7CEAE197DB8FA00926CE8 /* FatDynamicValidation.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C96F7BD16D6DF8300D3B39D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4CAEACCC16D6FBF600263776 /* KDSecCircle.m in Sources */, + 4C5DD46A17A5E5D000696A79 /* KNPersistantState.m in Sources */, + 4CD1980E16DD3BDF00A9E8FD /* NSArray+mapWithBlock.m in Sources */, + 4C7D456817BEED0400DDD88F /* NSDictionary+compactDescription.m in Sources */, + 4C7D453D17BEE69B00DDD88F /* NSString+compactDescription.m in Sources */, + 4C96F7CA16D6DF8400D3B39D /* main.m in Sources */, + 4C85DEDB16DBD5BF00ED8D47 /* KDCirclePeer.m in Sources */, + 4C96F7D116D6DF8400D3B39D /* KNAppDelegate.m in Sources */, + 4C7D456917BEED1400DDD88F /* NSSet+compactDescription.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CB23B42169F5873003A0131 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4CB23B81169F58DE003A0131 /* security_tool_commands.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CC7A7AF16CC2A84003E10C1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C96F76016D5462F00D3B39D /* KDSecCircle.m in Sources */, + 4C85DEDA16DBD5BF00ED8D47 /* KDCirclePeer.m in Sources */, + 4CC7A7BC16CC2A85003E10C1 /* main.m in Sources */, + 4CC7A7C316CC2A85003E10C1 /* KDAppDelegate.m in Sources */, + 4CC7A7F616CD99E2003E10C1 /* KDSecItems.m in Sources */, + 4CD1980D16DD3BDF00A9E8FD /* NSArray+mapWithBlock.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5214700216977CB800DF0DB3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 52C3D236169B56860091D9D3 /* ckdmain.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 72756BFA175D485D00F52070 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 72756C31175D48C100F52070 /* cloud_keychain_diagnose.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 0C4EAE7917668DFF00773425 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecdRegressions; + targetProxy = 0C4EAE7817668DFF00773425 /* PBXContainerItemProxy */; + }; + 0C6C632E15D19D2900BC68CD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_ssl_regressions; + targetProxy = 0C6C632D15D19D2900BC68CD /* PBXContainerItemProxy */; + }; + 0C6C642E15D5ADC900BC68CD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = tlsnke; + targetProxy = 0C6C642D15D5ADC900BC68CD /* PBXContainerItemProxy */; + }; + 0C6C643015D5AE4C00BC68CD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_ssl_kext; + targetProxy = 0C6C642F15D5AE4C00BC68CD /* PBXContainerItemProxy */; + }; + 0CBD50C716C3260D00713B6C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_keychain_regressions; + targetProxy = 0CBD50C616C3260D00713B6C /* PBXContainerItemProxy */; + }; + 0CC3350816C1ED8000399E53 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libSecureObjectSync; + targetProxy = 0CC3350916C1ED8000399E53 /* PBXContainerItemProxy */; + }; + 0CC3350A16C1ED8000399E53 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = utilities; + targetProxy = 0CC3350B16C1ED8000399E53 /* PBXContainerItemProxy */; + }; + 0CC3350C16C1ED8000399E53 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libSOSRegressions; + targetProxy = 0CC3350D16C1ED8000399E53 /* PBXContainerItemProxy */; + }; + 0CC3351016C1ED8000399E53 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity; + targetProxy = 0CC3351116C1ED8000399E53 /* PBXContainerItemProxy */; + }; + 0CC3351216C1ED8000399E53 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecipc_client; + targetProxy = 0CC3351316C1ED8000399E53 /* PBXContainerItemProxy */; + }; + 0CC3351416C1ED8000399E53 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libSecItemShimOSX; + targetProxy = 0CC3351516C1ED8000399E53 /* PBXContainerItemProxy */; + }; + 0CC3356216C1EF8B00399E53 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = regressions; + targetProxy = 0CC3356116C1EF8B00399E53 /* PBXContainerItemProxy */; + }; + 0CCEBDB316C2CFD4001BD7F6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = regressions; + targetProxy = 0CCEBDB216C2CFD4001BD7F6 /* PBXContainerItemProxy */; + }; + 0CCEBDBA16C303D8001BD7F6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0CC3350716C1ED8000399E53 /* secdtests */; + targetProxy = 0CCEBDB916C303D8001BD7F6 /* PBXContainerItemProxy */; + }; + 0CCEBDBD16C30948001BD7F6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = utilitiesRegressions; + targetProxy = 0CCEBDBC16C30948001BD7F6 /* PBXContainerItemProxy */; + }; + 0CFC55E315DDB86500BEC89E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0C6C630A15D193C800BC68CD /* sectests */; + targetProxy = 0CFC55E215DDB86500BEC89E /* PBXContainerItemProxy */; + }; + 18270EE114CF28D000B05E7F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity; + targetProxy = 18270EE014CF28D000B05E7F /* PBXContainerItemProxy */; + }; + 18270EE314CF28D900B05E7F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurityd; + targetProxy = 18270EE214CF28D900B05E7F /* PBXContainerItemProxy */; + }; + 18270F5D14CF655B00B05E7F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecipc_client; + targetProxy = 18270F5C14CF655B00B05E7F /* PBXContainerItemProxy */; + }; + 182BB22C146F07DD000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = XPCKeychainSandboxCheck; + targetProxy = 182BB22B146F07DD000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB3EC146F2448000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_apple_x509_tp; + targetProxy = 182BB3EB146F2448000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB3EE146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_pkcs12; + targetProxy = 182BB3ED146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB3F0146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_transform; + targetProxy = 182BB3EF146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB3F2146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_ocspd; + targetProxy = 182BB3F1146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB3F4146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_comcryption; + targetProxy = 182BB3F3146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB3F6146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_checkpw; + targetProxy = 182BB3F5146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB3F8146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_ssl; + targetProxy = 182BB3F7146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB3FC146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_apple_cspdl; + targetProxy = 182BB3FB146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB3FE146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_sd_cspdl; + targetProxy = 182BB3FD146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB400146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_manifest; + targetProxy = 182BB3FF146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB402146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_smime; + targetProxy = 182BB401146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB404146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_cms; + targetProxy = 182BB403146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB406146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_apple_csp; + targetProxy = 182BB405146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB408146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_apple_x509_cl; + targetProxy = 182BB407146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB40A146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_keychain; + targetProxy = 182BB409146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB40C146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_apple_file_dl; + targetProxy = 182BB40B146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB40E146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_authorization; + targetProxy = 182BB40D146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB410146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_cdsa_utilities; + targetProxy = 182BB40F146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB412146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_cryptkit; + targetProxy = 182BB411146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB414146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_cdsa_client; + targetProxy = 182BB413146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB418146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_filedb; + targetProxy = 182BB417146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB41A146F248D000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_mds; + targetProxy = 182BB419146F248D000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB4E7146F25AF000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_codesigning; + targetProxy = 182BB4E6146F25AF000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB588146FE001000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_codesigning; + targetProxy = 182BB587146FE001000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB58D146FE0FF000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_cdsa_utilities; + targetProxy = 182BB58C146FE0FF000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB58F146FE11C000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_utilities; + targetProxy = 182BB58E146FE11C000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB596146FE27F000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1807384A146D0D4E00F05C24 /* Security */; + targetProxy = 182BB595146FE27F000BF1F3 /* PBXContainerItemProxy */; + }; + 18446082146DF52F00B12992 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_cdsa_plugin; + targetProxy = 18446081146DF52F00B12992 /* PBXContainerItemProxy */; + }; + 186F779114E5A00F00434E1F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 18270ED514CF282600B05E7F /* secd */; + targetProxy = 186F779014E5A00F00434E1F /* PBXContainerItemProxy */; + }; + 186F779314E5A01700434E1F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 1807384A146D0D4E00F05C24 /* Security */; + targetProxy = 186F779214E5A01700434E1F /* PBXContainerItemProxy */; + }; + 186F779514E5A01C00434E1F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 182BB567146F4DCA000BF1F3 /* csparser */; + targetProxy = 186F779414E5A01C00434E1F /* PBXContainerItemProxy */; + }; + 186F779714E5A04200434E1F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 18FE67E91471A3AA00A2CBE3 /* copyHeaders */; + targetProxy = 186F779614E5A04200434E1F /* PBXContainerItemProxy */; + }; + 186F779914E5A06500434E1F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 186F778814E59FB200434E1F /* Security_frameworks */; + targetProxy = 186F779814E5A06500434E1F /* PBXContainerItemProxy */; + }; + 186F779B14E5A06800434E1F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 186F778C14E59FDA00434E1F /* Security_executables */; + targetProxy = 186F779A14E5A06800434E1F /* PBXContainerItemProxy */; + }; + 1879B545146DE18D007E536C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_utilities; + targetProxy = 1879B544146DE18D007E536C /* PBXContainerItemProxy */; + }; + 1879B56C146DE2CF007E536C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_cdsa_utils; + targetProxy = 1879B56B146DE2CF007E536C /* PBXContainerItemProxy */; + }; + 1879B56E146DE2D3007E536C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_cssm; + targetProxy = 1879B56D146DE2D3007E536C /* PBXContainerItemProxy */; + }; + 1885B45114D9AB3D00519375 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libASN1; + targetProxy = 1885B45014D9AB3D00519375 /* PBXContainerItemProxy */; + }; + 18AD56A614CDED59008233F2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = sec; + targetProxy = 18AD56A514CDED59008233F2 /* PBXContainerItemProxy */; + }; + 18B9655C1472F83C005A4D2E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = world; + targetProxy = 18B9655B1472F83C005A4D2E /* PBXContainerItemProxy */; + }; + 18F235FF15CA100300060520 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 18F234EA15C9F9A600060520 /* authd */; + targetProxy = 18F235FE15CA100300060520 /* PBXContainerItemProxy */; + }; + 18FE688F1471A4C900A2CBE3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 18FE67E91471A3AA00A2CBE3 /* copyHeaders */; + targetProxy = 18FE688E1471A4C900A2CBE3 /* PBXContainerItemProxy */; + }; + 37A7CEDA197DBA8700926CE8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 37A7CEAA197DB8FA00926CE8 /* codesign_tests */; + targetProxy = 37A7CED9197DBA8700926CE8 /* PBXContainerItemProxy */; + }; + 4AD6F6F41651CC2500DB4CE6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libSecOtrOSX; + targetProxy = 4AD6F6F31651CC2500DB4CE6 /* PBXContainerItemProxy */; + }; + 4C01DF13164C3E74006798CD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libSecureObjectSync; + targetProxy = 4C01DF12164C3E74006798CD /* PBXContainerItemProxy */; + }; + 4C12894415FFED03008CE3E3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = utilities; + targetProxy = 4C12894315FFED03008CE3E3 /* PBXContainerItemProxy */; + }; + 4C797BC916D83A3100C7B586 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4C96F7C016D6DF8300D3B39D /* Keychain Circle Notification */; + targetProxy = 4C797BC816D83A3100C7B586 /* PBXContainerItemProxy */; + }; + 4C797BF116D83A3800C7B586 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4CC7A7B216CC2A84003E10C1 /* Cloud Keychain Utility */; + targetProxy = 4C797BF016D83A3800C7B586 /* PBXContainerItemProxy */; + }; + 4C7D8764160A746E00D041E3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = utilities; + targetProxy = 4C7D8763160A746E00D041E3 /* PBXContainerItemProxy */; + }; + 4C8D8650177A75100019A804 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecipc_client; + targetProxy = 4C8D864F177A75100019A804 /* PBXContainerItemProxy */; + }; + 4CB23B84169F5961003A0131 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libSOSCommands; + targetProxy = 4CB23B83169F5961003A0131 /* PBXContainerItemProxy */; + }; + 4CB23B86169F5971003A0131 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libSecurityCommands; + targetProxy = 4CB23B85169F5971003A0131 /* PBXContainerItemProxy */; + }; + 4CB23B88169F597D003A0131 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libSecurityTool; + targetProxy = 4CB23B87169F597D003A0131 /* PBXContainerItemProxy */; + }; + 4CB23B90169F59D8003A0131 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4CB23B45169F5873003A0131 /* security2 */; + targetProxy = 4CB23B8F169F59D8003A0131 /* PBXContainerItemProxy */; + }; + 5208C0FE16A0D3980062DDC5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libSecureObjectSync; + targetProxy = 5208C0FD16A0D3980062DDC5 /* PBXContainerItemProxy */; + }; + 5214701816977D1D00DF0DB3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = utilities; + targetProxy = 5214701716977D1D00DF0DB3 /* PBXContainerItemProxy */; + }; + 5214701A16977D2500DF0DB3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libCloudKeychainProxy; + targetProxy = 5214701916977D2500DF0DB3 /* PBXContainerItemProxy */; + }; + 521470291697842500DF0DB3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5214700516977CB800DF0DB3 /* CloudKeychainProxy */; + targetProxy = 521470281697842500DF0DB3 /* PBXContainerItemProxy */; + }; + 529FF2201523BD7F0029D842 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = XPCTimeStampingService; + targetProxy = 529FF21F1523BD7F0029D842 /* PBXContainerItemProxy */; + }; + 722CF218175D602F00BCE0A5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 72756BFD175D485D00F52070 /* cloud_keychain_diagnose */; + targetProxy = 722CF217175D602F00BCE0A5 /* PBXContainerItemProxy */; + }; + 7AADF6E119C1062200292339 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = gkoverride; + targetProxy = 7AADF6E019C1062200292339 /* PBXContainerItemProxy */; + }; + ACB6173F18B5232700EBEDD7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_smime_regressions; + targetProxy = ACB6173E18B5232700EBEDD7 /* PBXContainerItemProxy */; + }; + C2432A2515C726B50096DB5B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = gkunpack; + targetProxy = C2432A2415C726B50096DB5B /* PBXContainerItemProxy */; + }; + E76079FA1951FDF600F69731 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = liblogging; + targetProxy = E76079F91951FDF600F69731 /* PBXContainerItemProxy */; + }; + EBB9FFE01682E71F00FF9774 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = CodeSigningHelper; + targetProxy = EBB9FFDF1682E71F00FF9774 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 18500F9F14708F19006F9AB4 /* SecErrorMessages.strings */ = { + isa = PBXVariantGroup; + children = ( + 18500FA014708F19006F9AB4 /* en */, + ); + name = SecErrorMessages.strings; + path = ../../Security; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 187D6B8F15D4359F00E27494 /* authorization.buttons.strings */ = { + isa = PBXVariantGroup; + children = ( + 187D6B9015D4359F00E27494 /* en */, + ); + name = authorization.buttons.strings; + sourceTree = ""; + }; + 187D6B9115D4359F00E27494 /* authorization.prompts.strings */ = { + isa = PBXVariantGroup; + children = ( + 187D6B9215D4359F00E27494 /* en */, + ); + name = authorization.prompts.strings; + sourceTree = ""; + }; + 188AD8D81471FE3D0081C619 /* FDELocalizable.strings */ = { + isa = PBXVariantGroup; + children = ( + 188AD8D91471FE3D0081C619 /* en */, + ); + name = FDELocalizable.strings; + sourceTree = ""; + }; + 188AD8DA1471FE3D0081C619 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 188AD8DB1471FE3E0081C619 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 18F2350D15C9FA3B00060520 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 18F2350E15C9FA3B00060520 /* en */, + ); + name = InfoPlist.strings; + path = en.lproj; + sourceTree = ""; + }; + 4C96F7C616D6DF8400D3B39D /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 4C96F7C716D6DF8400D3B39D /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 4C96F7CC16D6DF8400D3B39D /* Credits.rtf */ = { + isa = PBXVariantGroup; + children = ( + 4C96F7CD16D6DF8400D3B39D /* en */, + ); + name = Credits.rtf; + sourceTree = ""; + }; + 4C96F7D216D6DF8400D3B39D /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 4C96F7D316D6DF8400D3B39D /* en */, + ); + name = MainMenu.xib; + sourceTree = ""; + }; + 4CC7A7B816CC2A85003E10C1 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 4CC7A7B916CC2A85003E10C1 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 4CC7A7BE16CC2A85003E10C1 /* Credits.rtf */ = { + isa = PBXVariantGroup; + children = ( + 4CC7A7BF16CC2A85003E10C1 /* en */, + ); + name = Credits.rtf; + sourceTree = ""; + }; + 4CC7A7C416CC2A85003E10C1 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 4CC7A7C516CC2A85003E10C1 /* en */, + ); + name = MainMenu.xib; + sourceTree = ""; + }; + 5214701016977CB800DF0DB3 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 5214701116977CB800DF0DB3 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 5328475117850741009118DC /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + 5328475217850741009118DC /* en */, + ); + name = Localizable.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 0C6C631315D193C900BC68CD /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0C6C632F15D19DE600BC68CD /* test.xcconfig */; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CODE_SIGN_ENTITLEMENTS = "sectests/SecurityTests-Entitlements.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /usr/lib/system, + ); + OTHER_LDFLAGS = "-t"; + VALID_ARCHS = x86_64; + }; + name = Debug; + }; + 0C6C631415D193C900BC68CD /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0C6C632F15D19DE600BC68CD /* test.xcconfig */; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CODE_SIGN_ENTITLEMENTS = "sectests/SecurityTests-Entitlements.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /usr/lib/system, + ); + OTHER_LDFLAGS = "-t"; + VALID_ARCHS = x86_64; + }; + name = Release; + }; + 0C6C642B15D5ADB500BC68CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 0C6C642C15D5ADB500BC68CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 0CC3352B16C1ED8000399E53 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0C6C632F15D19DE600BC68CD /* test.xcconfig */; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CODE_SIGN_ENTITLEMENTS = sec/securityd/entitlements.plist; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/sec", + "$(PROJECT_DIR)/utilities", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /usr/lib/system, + ); + OTHER_LDFLAGS = "-t"; + "OTHER_LDFLAGS[sdk=macosx*]" = ( + "-t", + "-F$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + "-framework", + AppleSystemInfo, + ); + PRODUCT_NAME = secdtests; + VALID_ARCHS = x86_64; + }; + name = Debug; + }; + 0CC3352C16C1ED8000399E53 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0C6C632F15D19DE600BC68CD /* test.xcconfig */; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CODE_SIGN_ENTITLEMENTS = sec/securityd/entitlements.plist; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/sec", + "$(PROJECT_DIR)/utilities", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /usr/lib/system, + ); + OTHER_LDFLAGS = "-t"; + "OTHER_LDFLAGS[sdk=macosx*]" = ( + "-t", + "-F$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + "-framework", + AppleSystemInfo, + ); + PRODUCT_NAME = secdtests; + VALID_ARCHS = x86_64; + }; + name = Release; + }; + 18073873146D0D4E00F05C24 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 181EA423146D4A2A00A6D320 /* debug.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + 18073874146D0D4E00F05C24 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 181EA425146D4A2A00A6D320 /* release.xcconfig */; + buildSettings = { + }; + name = Release; + }; + 18073876146D0D4E00F05C24 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; + buildSettings = { + EXPORTED_SYMBOLS_FILE = "$(BUILT_PRODUCTS_DIR)/$(TARGETNAME).$(CURRENT_ARCH).exp"; + INFOPLIST_FILE = "lib/Info-Security.plist"; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /usr/lib/system, + ); + }; + name = Debug; + }; + 18073877146D0D4E00F05C24 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; + buildSettings = { + EXPORTED_SYMBOLS_FILE = "$(BUILT_PRODUCTS_DIR)/$(TARGETNAME).$(CURRENT_ARCH).exp"; + INFOPLIST_FILE = "lib/Info-Security.plist"; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /usr/lib/system, + ); + ORDER_FILE = lib/Security.order; + SECTORDER_FLAGS = "-order_file_statistics"; + }; + name = Release; + }; + 18270EDE14CF282600B05E7F /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = sec/securityd/entitlements.plist; + GCC_PREPROCESSOR_DEFINITIONS = ( + "SECITEM_SHIM_OSX=1", + "$(inherited)", + ); + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/sec", + "$(PROJECT_DIR)/sec/securityd", + "$(PROJECT_DIR)/sec/ipc", + "$(PROJECT_DIR)/sec/SOSCircle", + "$(PROJECT_DIR)/utilities", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/../ios/asn1", + "$(PROJECT_DIR)/../libsecurity_keychain/libDER", + "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers", + "$(inherited)", + ); + INSTALL_PATH = /usr/libexec; + "OTHER_LDFLAGS[sdk=macosx*]" = ( + "-F$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + "-framework", + AppleSystemInfo, + ); + USE_HEADERMAP = NO; + VALID_ARCHS = x86_64; + }; + name = Debug; + }; + 18270EDF14CF282600B05E7F /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = sec/securityd/entitlements.plist; + GCC_PREPROCESSOR_DEFINITIONS = ( + "SECITEM_SHIM_OSX=1", + "$(inherited)", + ); + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/sec", + "$(PROJECT_DIR)/sec/securityd", + "$(PROJECT_DIR)/sec/ipc", + "$(PROJECT_DIR)/sec/SOSCircle", + "$(PROJECT_DIR)/utilities", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/../ios/asn1", + "$(PROJECT_DIR)/../libsecurity_keychain/libDER", + "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers", + "$(inherited)", + ); + INSTALL_PATH = /usr/libexec; + "OTHER_LDFLAGS[sdk=macosx*]" = ( + "-F$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + "-framework", + AppleSystemInfo, + ); + USE_HEADERMAP = NO; + VALID_ARCHS = x86_64; + }; + name = Release; + }; + 182BB573146F4DCB000BF1F3 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; + buildSettings = { + EXPORTED_SYMBOLS_FILE = lib/plugins/csparser.exp; + INFOPLIST_FILE = "lib/plugins/csparser-Info.plist"; + INSTALLHDRS_SCRIPT_PHASE = NO; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/A/PlugIns"; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + 182BB574146F4DCB000BF1F3 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; + buildSettings = { + EXPORTED_SYMBOLS_FILE = lib/plugins/csparser.exp; + INFOPLIST_FILE = "lib/plugins/csparser-Info.plist"; + INSTALLHDRS_SCRIPT_PHASE = NO; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/A/PlugIns"; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; + 182BB59A146FE295000BF1F3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 182BB59B146FE295000BF1F3 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 186F778A14E59FB200434E1F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 186F778B14E59FB200434E1F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 186F778E14E59FDA00434E1F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 186F778F14E59FDA00434E1F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 18F234F715C9F9A700060520 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18BFC44017C43393005DE6C3 /* executable.xcconfig */; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "authd/security.auth-Prefix.pch"; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = authd/Info.plist; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; + MACH_O_TYPE = mh_execute; + PRODUCT_NAME = "$(TARGET_NAME)"; + RUN_CLANG_STATIC_ANALYZER = YES; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; + WRAPPER_EXTENSION = xpc; + }; + name = Debug; + }; + 18F234F815C9F9A700060520 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18BFC44017C43393005DE6C3 /* executable.xcconfig */; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "authd/security.auth-Prefix.pch"; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = authd/Info.plist; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; + MACH_O_TYPE = mh_execute; + PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; + WRAPPER_EXTENSION = xpc; + }; + name = Release; + }; + 18FE67FC1471A3AA00A2CBE3 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; + PRODUCT_NAME = Security; + }; + name = Debug; + }; + 18FE67FD1471A3AA00A2CBE3 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; + PRODUCT_NAME = Security; + }; + name = Release; + }; + 37A7CEAF197DB8FA00926CE8 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INSTALL_PATH = /AppleInternal/CoreOS/codesign_tests; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + 37A7CEB0197DB8FA00926CE8 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = YES; + 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; + INSTALL_PATH = /AppleInternal/CoreOS/codesign_tests; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + 4C96F7D616D6DF8400D3B39D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = "Keychain Circle Notification/entitlments.plist"; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREFIX_HEADER = "Keychain Circle Notification/Keychain Circle Notification-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + /System/Library/Frameworks/Security.framework/PrivateHeaders, + /System/Library/Frameworks/CoreFoundation.framework/PrivateHeaders, + "$(PROJECT_DIR)/sec", + ); + INFOPLIST_FILE = "Keychain Circle Notification/Keychain Circle Notification-Info.plist"; + INSTALL_PATH = /System/Library/CoreServices; + MACOSX_DEPLOYMENT_TARGET = 10.9; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = ""; + VALID_ARCHS = x86_64; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 4C96F7D716D6DF8400D3B39D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = "Keychain Circle Notification/entitlments.plist"; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_PREFIX_HEADER = "Keychain Circle Notification/Keychain Circle Notification-Prefix.pch"; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + /System/Library/Frameworks/Security.framework/PrivateHeaders, + /System/Library/Frameworks/CoreFoundation.framework/PrivateHeaders, + "$(PROJECT_DIR)/sec", + ); + INFOPLIST_FILE = "Keychain Circle Notification/Keychain Circle Notification-Info.plist"; + INSTALL_PATH = /System/Library/CoreServices; + MACOSX_DEPLOYMENT_TARGET = 10.9; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = ""; + VALID_ARCHS = x86_64; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; + 4CB23B4D169F5873003A0131 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4CB23B91169F5CFF003A0131 /* command.xcconfig */; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CODE_SIGN_ENTITLEMENTS = sec/SecurityTool/entitlements.plist; + CODE_SIGN_IDENTITY = "-"; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = security2; + PROVISIONING_PROFILE = ""; + }; + name = Debug; + }; + 4CB23B4E169F5873003A0131 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4CB23B91169F5CFF003A0131 /* command.xcconfig */; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CODE_SIGN_ENTITLEMENTS = sec/SecurityTool/entitlements.plist; + CODE_SIGN_IDENTITY = "-"; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + PRODUCT_NAME = security2; + PROVISIONING_PROFILE = ""; + }; + name = Release; + }; + 4CC7A7C716CC2A85003E10C1 /* 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_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = sec/SecurityTool/entitlements.plist; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREFIX_HEADER = "Keychain/Keychain-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /System/Library/Frameworks/Security.framework/PrivateHeaders, + /System/Library/Frameworks/CoreFoundation.framework/PrivateHeaders, + ); + INFOPLIST_FILE = "Keychain/Keychain-Info.plist"; + INSTALL_PATH = /AppleInternal/Applications; + MACOSX_DEPLOYMENT_TARGET = 10.9; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = ""; + VALID_ARCHS = x86_64; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 4CC7A7C816CC2A85003E10C1 /* 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_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = sec/SecurityTool/entitlements.plist; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_PREFIX_HEADER = "Keychain/Keychain-Prefix.pch"; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /System/Library/Frameworks/Security.framework/PrivateHeaders, + /System/Library/Frameworks/CoreFoundation.framework/PrivateHeaders, + ); + INFOPLIST_FILE = "Keychain/Keychain-Info.plist"; + INSTALL_PATH = /AppleInternal/Applications; + MACOSX_DEPLOYMENT_TARGET = 10.9; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = ""; + VALID_ARCHS = x86_64; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; + 4CE4729F16D833FE009070D1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 4CE472A016D833FE009070D1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 5214701516977CB800DF0DB3 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18BFC44017C43393005DE6C3 /* executable.xcconfig */; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = CloudKeychainProxy/cloudkeychain.entitlements.plist; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = "CloudKeychainProxy/CloudKeychainProxy-Info.plist"; + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/A/Resources"; + MACH_O_TYPE = mh_execute; + MACOSX_DEPLOYMENT_TARGET = 10.9; + ONLY_ACTIVE_ARCH = YES; + "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "$(inherited)", + "-framework", + MobileKeyBag, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; + SDKROOT = ""; + VALID_ARCHS = "armv6 armv7 x86_64"; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + 5214701616977CB800DF0DB3 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18BFC44017C43393005DE6C3 /* executable.xcconfig */; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = CloudKeychainProxy/cloudkeychain.entitlements.plist; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = "CloudKeychainProxy/CloudKeychainProxy-Info.plist"; + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/A/Resources"; + MACH_O_TYPE = mh_execute; + MACOSX_DEPLOYMENT_TARGET = 10.9; + "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "$(inherited)", + "-framework", + MobileKeyBag, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; + SDKROOT = ""; + VALID_ARCHS = "armv6 armv7 x86_64"; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; + 72756C07175D485D00F52070 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = NO; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + /usr/local/include, + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/security2", + "$(PROJECT_DIR)/sec/SOSCircle", + "$(PROJECT_DIR)/utilities", + "$(PROJECT_DIR)/sec", + ); + MACOSX_DEPLOYMENT_TARGET = 10.9; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = "-laks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx.internal; + }; + name = Debug; + }; + 72756C08175D485D00F52070 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_PRECOMPILE_PREFIX_HEADER = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + /usr/local/include, + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/security2", + "$(PROJECT_DIR)/sec/SOSCircle", + "$(PROJECT_DIR)/utilities", + "$(PROJECT_DIR)/sec", + ); + MACOSX_DEPLOYMENT_TARGET = 10.9; + OTHER_LDFLAGS = "-laks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx.internal; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 0C6C631215D193C900BC68CD /* Build configuration list for PBXNativeTarget "sectests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0C6C631315D193C900BC68CD /* Debug */, + 0C6C631415D193C900BC68CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0C6C642A15D5ADB500BC68CD /* Build configuration list for PBXAggregateTarget "Security_kexts" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0C6C642B15D5ADB500BC68CD /* Debug */, + 0C6C642C15D5ADB500BC68CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0CC3352A16C1ED8000399E53 /* Build configuration list for PBXNativeTarget "secdtests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0CC3352B16C1ED8000399E53 /* Debug */, + 0CC3352C16C1ED8000399E53 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 18073844146D0D4E00F05C24 /* Build configuration list for PBXProject "Security" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 18073873146D0D4E00F05C24 /* Debug */, + 18073874146D0D4E00F05C24 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 18073875146D0D4E00F05C24 /* Build configuration list for PBXNativeTarget "Security" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 18073876146D0D4E00F05C24 /* Debug */, + 18073877146D0D4E00F05C24 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 18270EDD14CF282600B05E7F /* Build configuration list for PBXNativeTarget "secd" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 18270EDE14CF282600B05E7F /* Debug */, + 18270EDF14CF282600B05E7F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 182BB572146F4DCB000BF1F3 /* Build configuration list for PBXNativeTarget "csparser" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 182BB573146F4DCB000BF1F3 /* Debug */, + 182BB574146F4DCB000BF1F3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 182BB599146FE295000BF1F3 /* Build configuration list for PBXAggregateTarget "World" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 182BB59A146FE295000BF1F3 /* Debug */, + 182BB59B146FE295000BF1F3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 186F778914E59FB200434E1F /* Build configuration list for PBXAggregateTarget "Security_frameworks" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 186F778A14E59FB200434E1F /* Debug */, + 186F778B14E59FB200434E1F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 186F778D14E59FDA00434E1F /* Build configuration list for PBXAggregateTarget "Security_executables" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 186F778E14E59FDA00434E1F /* Debug */, + 186F778F14E59FDA00434E1F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 18F234F615C9F9A700060520 /* Build configuration list for PBXNativeTarget "authd" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 18F234F715C9F9A700060520 /* Debug */, + 18F234F815C9F9A700060520 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 18FE67FB1471A3AA00A2CBE3 /* Build configuration list for PBXNativeTarget "copyHeaders" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 18FE67FC1471A3AA00A2CBE3 /* Debug */, + 18FE67FD1471A3AA00A2CBE3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 37A7CED8197DB8FA00926CE8 /* Build configuration list for PBXNativeTarget "codesign_tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 37A7CEAF197DB8FA00926CE8 /* Debug */, + 37A7CEB0197DB8FA00926CE8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4C96F7D516D6DF8400D3B39D /* Build configuration list for PBXNativeTarget "Keychain Circle Notification" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4C96F7D616D6DF8400D3B39D /* Debug */, + 4C96F7D716D6DF8400D3B39D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4CB23B7F169F5873003A0131 /* Build configuration list for PBXNativeTarget "security2" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4CB23B4D169F5873003A0131 /* Debug */, + 4CB23B4E169F5873003A0131 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4CC7A7EF16CC2A85003E10C1 /* Build configuration list for PBXNativeTarget "Cloud Keychain Utility" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4CC7A7C716CC2A85003E10C1 /* Debug */, + 4CC7A7C816CC2A85003E10C1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4CE472C716D833FE009070D1 /* Build configuration list for PBXAggregateTarget "Security_temporary_UI" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4CE4729F16D833FE009070D1 /* Debug */, + 4CE472A016D833FE009070D1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5214701416977CB800DF0DB3 /* Build configuration list for PBXNativeTarget "CloudKeychainProxy" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5214701516977CB800DF0DB3 /* Debug */, + 5214701616977CB800DF0DB3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 72756C2F175D485D00F52070 /* Build configuration list for PBXNativeTarget "cloud_keychain_diagnose" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 72756C07175D485D00F52070 /* Debug */, + 72756C08175D485D00F52070 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 18073841146D0D4E00F05C24 /* Project object */; +} diff --git a/Security/Security.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Security/Security.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..8efcdaeb --- /dev/null +++ b/Security/Security.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Security/Security.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Security/Security.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..08de0be8 --- /dev/null +++ b/Security/Security.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/Security.xcscheme b/Security/Security.xcodeproj/xcshareddata/xcschemes/Security.xcscheme similarity index 100% rename from Security.xcodeproj/xcshareddata/xcschemes/Security.xcscheme rename to Security/Security.xcodeproj/xcshareddata/xcschemes/Security.xcscheme diff --git a/Security.xcodeproj/xcshareddata/xcschemes/Security_executables.xcscheme b/Security/Security.xcodeproj/xcshareddata/xcschemes/Security_executables.xcscheme similarity index 100% rename from Security.xcodeproj/xcshareddata/xcschemes/Security_executables.xcscheme rename to Security/Security.xcodeproj/xcshareddata/xcschemes/Security_executables.xcscheme diff --git a/Security.xcodeproj/xcshareddata/xcschemes/Security_frameworks.xcscheme b/Security/Security.xcodeproj/xcshareddata/xcschemes/Security_frameworks.xcscheme similarity index 100% rename from Security.xcodeproj/xcshareddata/xcschemes/Security_frameworks.xcscheme rename to Security/Security.xcodeproj/xcshareddata/xcschemes/Security_frameworks.xcscheme diff --git a/Security.xcodeproj/xcshareddata/xcschemes/World.xcscheme b/Security/Security.xcodeproj/xcshareddata/xcschemes/World.xcscheme similarity index 96% rename from Security.xcodeproj/xcshareddata/xcschemes/World.xcscheme rename to Security/Security.xcodeproj/xcshareddata/xcschemes/World.xcscheme index 741e66b5..daf76c77 100644 --- a/Security.xcodeproj/xcshareddata/xcschemes/World.xcscheme +++ b/Security/Security.xcodeproj/xcshareddata/xcschemes/World.xcscheme @@ -38,7 +38,8 @@ buildConfiguration = "Debug" ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" - allowLocationSimulation = "YES"> + allowLocationSimulation = "YES" + showNonLocalizedStrings = "NO"> diff --git a/Security.xcodeproj/xcshareddata/xcschemes/authd.xcscheme b/Security/Security.xcodeproj/xcshareddata/xcschemes/authd.xcscheme similarity index 100% rename from Security.xcodeproj/xcshareddata/xcschemes/authd.xcscheme rename to Security/Security.xcodeproj/xcshareddata/xcschemes/authd.xcscheme diff --git a/Security.xcodeproj/xcshareddata/xcschemes/copyHeaders.xcscheme b/Security/Security.xcodeproj/xcshareddata/xcschemes/copyHeaders.xcscheme similarity index 100% rename from Security.xcodeproj/xcshareddata/xcschemes/copyHeaders.xcscheme rename to Security/Security.xcodeproj/xcshareddata/xcschemes/copyHeaders.xcscheme diff --git a/Security.xcodeproj/xcshareddata/xcschemes/secd.xcscheme b/Security/Security.xcodeproj/xcshareddata/xcschemes/secd.xcscheme similarity index 100% rename from Security.xcodeproj/xcshareddata/xcschemes/secd.xcscheme rename to Security/Security.xcodeproj/xcshareddata/xcschemes/secd.xcscheme diff --git a/Security/Security.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme b/Security/Security.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme new file mode 100644 index 00000000..0900729a --- /dev/null +++ b/Security/Security.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Security/asl/com.apple.securityd b/Security/asl/com.apple.securityd new file mode 100644 index 00000000..9a003307 --- /dev/null +++ b/Security/asl/com.apple.securityd @@ -0,0 +1,28 @@ +> security.log format='$Time $(Sender)[$(PID)] <$((Level)(str))> [$(Facility){$(SecAPITrace)} $(CALLER)]: $Message' rotate=utc-basic crashlog compress file_max=5M all_max=20M + +# Note: this file is for OSX only. + +# Note: +# securityd is the iOS securityd +# com.apple.securityd is the OSX securityd +# com.apple.secd is the iOS version of securityd running on OSX + +? [T SecAPITrace] file security.log +? [= Sender com.apple.securityd] file security.log +? [= Sender com.apple.secd] file security.log +? [= Sender CloudKeychainProxy] file security.log +? [= Sender securityd] file security.log +? [= Sender secd] file security.log +? [= Sender securityd_service] file security.log + +# Claim prevents the built-in ASL configuration from +# processing our messages. We claim anything short +# of errors, and let ASL do what it wants with the rest + +? [T SecAPITrace] [> Level error] claim +? [= Sender com.apple.securityd] [> Level error] claim +? [= Sender com.apple.secd] [> Level error] claim +? [= Sender CloudKeychainProxy] [> Level error] claim +? [= Sender securityd] [> Level error] claim +? [= Sender secd] [> Level error] claim +? [= Sender securityd_service] [> Level error] claim diff --git a/Security/authd/Info.plist b/Security/authd/Info.plist new file mode 100644 index 00000000..36b0c23c --- /dev/null +++ b/Security/authd/Info.plist @@ -0,0 +1,31 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.apple.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + XPC! + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSHumanReadableCopyright + Copyright © 2012 Apple. All rights reserved. + XPCService + + ServiceType + System + + + diff --git a/authd/agent.c b/Security/authd/agent.c similarity index 98% rename from authd/agent.c rename to Security/authd/agent.c index 677b7118..4cdab906 100644 --- a/authd/agent.c +++ b/Security/authd/agent.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ #include "agent.h" #include "authitems.h" @@ -209,6 +209,10 @@ agent_create(engine_t engine, mechanism_t mech, auth_token_t auth, process_t pro if (0 == audit_session_port(audit_info->asid, &jobPort)) { LOGV("agent[%i]: attaching an audit session port", agent->agentPid); xpc_dictionary_set_mach_send(requestObject, AUTH_XPC_AUDIT_SESSION_PORT, jobPort); + + if (mach_port_mod_refs(mach_task_self(), jobPort, MACH_PORT_RIGHT_SEND, -1) != KERN_SUCCESS) { + LOGE("unable to release send right for audit session, leaking"); + } } } } diff --git a/authd/agent.h b/Security/authd/agent.h similarity index 97% rename from authd/agent.h rename to Security/authd/agent.h index 5b1a18bc..96c382a1 100644 --- a/authd/agent.h +++ b/Security/authd/agent.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ #ifndef _SECURITY_AUTH_AGENT_H_ #define _SECURITY_AUTH_AGENT_H_ diff --git a/authd/authd_private.h b/Security/authd/authd_private.h similarity index 98% rename from authd/authd_private.h rename to Security/authd/authd_private.h index 9e3b232e..4ada56ee 100644 --- a/authd/authd_private.h +++ b/Security/authd/authd_private.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ #ifndef _AUTHD_PRIVATE_H_ #define _AUTHD_PRIVATE_H_ diff --git a/authd/authdb.c b/Security/authd/authdb.c similarity index 99% rename from authd/authdb.c rename to Security/authd/authdb.c index d6952d01..c52e61ba 100644 --- a/authd/authdb.c +++ b/Security/authd/authdb.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. */ #include "authdb.h" #include "mechanism.h" @@ -202,7 +202,8 @@ static void _db_load_data(authdb_connection_t dbconn, auth_items_t config) } old_ts = auth_items_get_double(config, "data_ts"); - if (ts > old_ts) { + + if (ts != old_ts) { LOGV("authdb: %s modified old=%f, new=%f", AUTHDB_DATA, old_ts, ts); CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, authURL, &data, NULL, NULL, (SInt32*)&rc); require_noerr_action(rc, done, LOGE("authdb: failed to load %s", AUTHDB_DATA)); diff --git a/authd/authdb.h b/Security/authd/authdb.h similarity index 96% rename from authd/authdb.h rename to Security/authd/authdb.h index b1eb9ed9..abe29998 100644 --- a/authd/authdb.h +++ b/Security/authd/authdb.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012 Apple Inc. All Rights Reserved. */ #ifndef _SECURITY_AUTH_AUTHDB_H_ #define _SECURITY_AUTH_AUTHDB_H_ diff --git a/authd/authitems.c b/Security/authd/authitems.c similarity index 99% rename from authd/authitems.c rename to Security/authd/authitems.c index a55850b9..1871eaa8 100644 --- a/authd/authitems.c +++ b/Security/authd/authitems.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ #include "authitems.h" #include "crc.h" diff --git a/authd/authitems.h b/Security/authd/authitems.h similarity index 98% rename from authd/authitems.h rename to Security/authd/authitems.h index c8bebc5d..f55ebab8 100644 --- a/authd/authitems.h +++ b/Security/authd/authitems.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012 Apple Inc. All Rights Reserved. */ #ifndef _SECURITY_AUTH_ITEMS_H_ #define _SECURITY_AUTH_ITEMS_H_ diff --git a/authd/authorization.plist b/Security/authd/authorization.plist similarity index 91% rename from authd/authorization.plist rename to Security/authd/authorization.plist index 16dd2de2..ca131696 100644 --- a/authd/authorization.plist +++ b/Security/authd/authorization.plist @@ -595,17 +595,15 @@ See remaining rules for examples. system.csfde.requestpassword class - user + rule comment Used by CoreStorage Full Disk Encryption to request the user's password. - extract-password - - group - staff - shared - - timeout - 0 + rule + + authenticate-admin-or-staff-extract + + version + 1 system.device.dvd.setregion.initial @@ -708,6 +706,17 @@ See remaining rules for examples. timeout 10 + system.install.software.mdm-provided + + allow-root + + version + 1 + class + rule + rule + entitled + system.install.apple-config-data allow-root @@ -741,17 +750,6 @@ See remaining rules for examples. timeout 10 - system.install.iap-software - - allow-root - - authenticate-user - - class - user - entitled - - system.install.software allow-root @@ -767,6 +765,17 @@ See remaining rules for examples. timeout 300 + system.install.software.iap + + allow-root + + authenticate-user + + class + user + entitled + + system.keychain.create.loginkc allow-root @@ -825,6 +834,25 @@ See remaining rules for examples. version 1 + system.login.fus + + class + evaluate-mechanisms + comment + Login mechanism based rule. Not for general use, yet. + mechanisms + + builtin:smartcard-sniffer,privileged + loginwindow:login + builtin:reset-password,privileged + builtin:auto-login,privileged + builtin:authenticate-nocred,privileged + loginwindow:success + loginwindow:done + + version + 1 + system.login.done class @@ -846,13 +874,16 @@ See remaining rules for examples. system.login.tty class - evaluate-mechanisms - mechanisms + rule + created + 420083170.08267599 + modified + 420083170.08267599 + rule - push_hints_to_context - authinternal + default - tries + version 1 system.preferences @@ -1192,6 +1223,36 @@ See remaining rules for examples. shared + system.services.networkextension.filtering + + allow-root + + class + user + comment + For making changes to the Content Filtering configuration using NetworkExtension. + entitled-group + + group + admin + vpn-entitled-group + + + system.services.networkextension.vpn + + allow-root + + class + user + comment + For making changes to the VPN configuration using NetworkExtension. + entitled-group + + group + admin + vpn-entitled-group + + system.services.systemconfiguration.network allow-root @@ -1281,6 +1342,53 @@ See remaining rules for examples. authenticate-admin-30 + system.volume.network. + + class + rule + comment + system.volume.network.unmount + k-of-n + 1 + rule + + is-root + is-admin + on-console + authenticate-admin-30 + + + system.volume.optical. + + class + rule + comment + system.volume.optical.(adopt|encode|mount|rename|unmount) + k-of-n + 1 + rule + + is-root + is-admin + on-console + authenticate-admin-30 + + + system.volume.optical.adopt + + class + rule + comment + system.volume.optical.adopt + k-of-n + 1 + rule + + is-root + is-admin + authenticate-admin-30 + + system.volume.removable. class @@ -1393,6 +1501,48 @@ See remaining rules for examples. timeout 30 + authenticate-admin-extract + + class + user + comment + Authenticate as an administrator + allow password extraction. + extract-password + + group + admin + require-apple-signed + + timeout + 0 + + authenticate-staff-extract + + class + user + comment + Authenticate as group staff + allow password to be extracted. + extract-password + + group + staff + require-apple-signed + + timeout + 0 + + authenticate-admin-or-staff-extract + + class + rule + k-of-n + 1 + rule + + authenticate-admin-extract + authenticate-staff-extract + + authenticate-appstore-30 class diff --git a/authd/authtoken.c b/Security/authd/authtoken.c similarity index 99% rename from authd/authtoken.c rename to Security/authd/authtoken.c index fe495354..e073b894 100644 --- a/authd/authtoken.c +++ b/Security/authd/authtoken.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ #include "authtoken.h" #include "authd_private.h" diff --git a/authd/authtoken.h b/Security/authd/authtoken.h similarity index 97% rename from authd/authtoken.h rename to Security/authd/authtoken.h index 6f6282cf..c745a82a 100644 --- a/authd/authtoken.h +++ b/Security/authd/authtoken.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ #ifndef _SECURITY_AUTH_AUTHTOKEN_H_ #define _SECURITY_AUTH_AUTHTOKEN_H_ diff --git a/authd/authtypes.h b/Security/authd/authtypes.h similarity index 94% rename from authd/authtypes.h rename to Security/authd/authtypes.h index 5f5a1708..5001669e 100644 --- a/authd/authtypes.h +++ b/Security/authd/authtypes.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012 Apple Inc. All Rights Reserved. */ #ifndef _SECURITY_AUTH_TYPES_H_ #define _SECURITY_AUTH_TYPES_H_ diff --git a/authd/authutilities.c b/Security/authd/authutilities.c similarity index 99% rename from authd/authutilities.c rename to Security/authd/authutilities.c index 52e4b0fe..8d5d0544 100644 --- a/authd/authutilities.c +++ b/Security/authd/authutilities.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ #include "authutilities.h" #include "authd_private.h" diff --git a/authd/authutilities.h b/Security/authd/authutilities.h similarity index 93% rename from authd/authutilities.h rename to Security/authd/authutilities.h index 6d07c9c3..ebe1e5a4 100644 --- a/authd/authutilities.h +++ b/Security/authd/authutilities.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ #ifndef _SECURITY_AUTH_UTILITIES_H_ #define _SECURITY_AUTH_UTILITIES_H_ diff --git a/authd/ccaudit.c b/Security/authd/ccaudit.c similarity index 99% rename from authd/ccaudit.c rename to Security/authd/ccaudit.c index 69147376..52a1504e 100644 --- a/authd/ccaudit.c +++ b/Security/authd/ccaudit.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ #include "ccaudit.h" #include "debugging.h" diff --git a/Security/authd/ccaudit.h b/Security/authd/ccaudit.h new file mode 100644 index 00000000..4ce4ffa0 --- /dev/null +++ b/Security/authd/ccaudit.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ + +#ifndef _SECURITY_AUTH_CCAUDIT_H_ +#define _SECURITY_AUTH_CCAUDIT_H_ + +#include + +AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED +ccaudit_t ccaudit_create(process_t, auth_token_t, int32_t event); + +AUTH_NONNULL_ALL +void ccaudit_log_authorization(ccaudit_t, const char * right, OSStatus err); + +AUTH_NONNULL_ALL +void ccaudit_log_success(ccaudit_t, credential_t cred, const char * right); + +AUTH_NONNULL_ALL +void ccaudit_log_failure(ccaudit_t, const char * credName, const char * right); + +AUTH_NONNULL1 +void ccaudit_log_mechanism(ccaudit_t, const char * right, const char * mech, uint32_t status, const char * interrupted); + +AUTH_NONNULL1 +void ccaudit_log(ccaudit_t, const char * right, const char * msg, OSStatus err); + +#endif /* !_SECURITY_AUTH_CCAUDIT_H_ */ diff --git a/authd/com.apple.authd b/Security/authd/com.apple.authd similarity index 80% rename from authd/com.apple.authd rename to Security/authd/com.apple.authd index ead3047a..f1a68ebe 100644 --- a/authd/com.apple.authd +++ b/Security/authd/com.apple.authd @@ -1,4 +1,4 @@ -? [= Sender com.apple.authd] claim only +? [= Sender authd] claim only * file /var/log/authd.log mode=0640 compress format=bsd rotate=seq file_max=5M all_max=20M ? [<= Level error] file /var/log/system.log ? [<= Level error] store diff --git a/authd/com.apple.authd.sb b/Security/authd/com.apple.authd.sb similarity index 100% rename from authd/com.apple.authd.sb rename to Security/authd/com.apple.authd.sb diff --git a/authd/connection.c b/Security/authd/connection.c similarity index 97% rename from authd/connection.c rename to Security/authd/connection.c index 1f34d741..e88f93f7 100644 --- a/authd/connection.c +++ b/Security/authd/connection.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ #include "connection.h" #include "process.h" diff --git a/Security/authd/connection.h b/Security/authd/connection.h new file mode 100644 index 00000000..4cf51d2a --- /dev/null +++ b/Security/authd/connection.h @@ -0,0 +1,38 @@ +/* Copyright (c) 2012 Apple Inc. All Rights Reserved. */ + +#ifndef _SECURITY_AUTH_CONNECTION_H_ +#define _SECURITY_AUTH_CONNECTION_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED +connection_t connection_create(process_t); + +AUTH_NONNULL_ALL +pid_t connection_get_pid(connection_t); + +AUTH_NONNULL_ALL +process_t connection_get_process(connection_t); + +AUTH_NONNULL_ALL +dispatch_queue_t connection_get_dispatch_queue(connection_t); + +AUTH_NONNULL1 +void connection_set_engine(connection_t, engine_t); + +AUTH_NONNULL_ALL +void connection_destory_agents(connection_t); + +AUTH_NONNULL_ALL +bool connection_get_syslog_warn(connection_t); + +AUTH_NONNULL_ALL +void connection_set_syslog_warn(connection_t); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_AUTH_CONNECTION_H_ */ diff --git a/authd/crc.c b/Security/authd/crc.c similarity index 99% rename from authd/crc.c rename to Security/authd/crc.c index 3feadcc5..1b481ecf 100644 --- a/authd/crc.c +++ b/Security/authd/crc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012 Apple Inc. All Rights Reserved. */ #include "crc.h" diff --git a/authd/crc.h b/Security/authd/crc.h similarity index 93% rename from authd/crc.h rename to Security/authd/crc.h index 3459678d..85184384 100644 --- a/authd/crc.h +++ b/Security/authd/crc.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012 Apple Inc. All Rights Reserved. */ #ifndef _SECURITY_AUTH_CRC_H_ #define _SECURITY_AUTH_CRC_H_ diff --git a/authd/credential.c b/Security/authd/credential.c similarity index 99% rename from authd/credential.c rename to Security/authd/credential.c index bbfaae1b..c800b5ae 100644 --- a/authd/credential.c +++ b/Security/authd/credential.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ #include "credential.h" #include "authutilities.h" diff --git a/Security/authd/credential.h b/Security/authd/credential.h new file mode 100644 index 00000000..1f7576e7 --- /dev/null +++ b/Security/authd/credential.h @@ -0,0 +1,54 @@ +/* Copyright (c) 2012 Apple Inc. All Rights Reserved. */ + +#ifndef _SECURITY_AUTH_CREDENTIAL_H_ +#define _SECURITY_AUTH_CREDENTIAL_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifdef __BLOCKS__ + typedef bool (^credential_iterator_t)(credential_t); +#endif /* __BLOCKS__ */ + +AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED +credential_t credential_create(uid_t); + +AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED +credential_t credential_create_with_credential(credential_t,bool); + +AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED +credential_t credential_create_with_right(const char *); + +AUTH_NONNULL_ALL +uid_t credential_get_uid(credential_t); + +AUTH_NONNULL_ALL +const char * credential_get_name(credential_t); + +AUTH_NONNULL_ALL +const char * credential_get_realname(credential_t); + +AUTH_NONNULL_ALL +CFAbsoluteTime credential_get_creation_time(credential_t); + +AUTH_NONNULL_ALL +bool credential_get_valid(credential_t); + +AUTH_NONNULL_ALL +bool credential_get_shared(credential_t); + +AUTH_NONNULL_ALL +bool credential_is_right(credential_t); + +AUTH_NONNULL_ALL +bool credential_check_membership(credential_t,const char*); + +AUTH_NONNULL_ALL +void credential_invalidate(credential_t); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_AUTH_CREDENTIAL_H_ */ diff --git a/Security/authd/debugging.c b/Security/authd/debugging.c new file mode 100644 index 00000000..a7682194 --- /dev/null +++ b/Security/authd/debugging.c @@ -0,0 +1,75 @@ +/* Copyright (c) 2012 Apple Inc. All Rights Reserved. */ + +#include "debugging.h" +#include "authd_private.h" +#include "authutilities.h" +#include +#include +#include +#include + +// sudo defaults write /Library/Preferences/com.apple.security.coderequirements Entitlements -string always + +static bool +security_auth_verbose(void) +{ + static dispatch_once_t onceToken; + static bool verbose_enabled = false; + + //sudo defaults write /Library/Preferences/com.apple.authd verbose -bool true + dispatch_once(&onceToken, ^{ + CFTypeRef verbose = (CFNumberRef)CFPreferencesCopyValue(CFSTR("verbose"), CFSTR(SECURITY_AUTH_NAME), kCFPreferencesAnyUser, kCFPreferencesCurrentHost); + + if (verbose && CFGetTypeID(verbose) == CFBooleanGetTypeID()) { + verbose_enabled = CFBooleanGetValue((CFBooleanRef)verbose); + } +#if DEBUG + syslog(LOG_NOTICE, "verbose: %s", verbose_enabled ? "enabled" : "disabled"); +#endif + CFReleaseSafe(verbose); + }); + + return verbose_enabled; +} + +void +security_auth_log(int type,const char * format,...) +{ + va_list ap; + va_start(ap, format); + switch (type) { + case AUTH_LOG_NORMAL: + vsyslog(LOG_NOTICE, format, ap); + break; + case AUTH_LOG_VERBOSE: + if (security_auth_verbose()) { + vsyslog(LOG_NOTICE, format, ap); + } + break; + case AUTH_LOG_ERROR: + vsyslog(LOG_ERR, format, ap); + break; + default: + break; + } + va_end(ap); +} + +void _show_cf(CFTypeRef value) +{ + CFStringRef string = NULL; + char * tmp = NULL; + require(value != NULL, done); + + if (security_auth_verbose()) { + string = CFCopyDescription(value); + tmp = _copy_cf_string(string, NULL); + + syslog(LOG_NOTICE, "%s", tmp); + } + +done: + CFReleaseSafe(string); + free_safe(tmp); + return; +} diff --git a/Security/authd/debugging.h b/Security/authd/debugging.h new file mode 100644 index 00000000..f6534197 --- /dev/null +++ b/Security/authd/debugging.h @@ -0,0 +1,41 @@ +/* Copyright (c) 2012 Apple Inc. All Rights Reserved. */ + +#ifndef _SECURITY_AUTH_DEBUGGING_H_ +#define _SECURITY_AUTH_DEBUGGING_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +enum { + AUTH_LOG_NORMAL, + AUTH_LOG_VERBOSE, + AUTH_LOG_ERROR +}; + +#define LOG(...) security_auth_log(AUTH_LOG_NORMAL, ##__VA_ARGS__) +#define LOGV(...) security_auth_log(AUTH_LOG_VERBOSE, ##__VA_ARGS__) +#define LOGE(...) security_auth_log(AUTH_LOG_ERROR, ##__VA_ARGS__) +#if DEBUG +#define LOGD(...) security_auth_log(AUTH_LOG_VERBOSE, ##__VA_ARGS__) +#else +#define LOGD(...) +#endif + +void security_auth_log(int,const char *,...) __printflike(2, 3); + +#define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) CFRelease(_cf); } +#define CFReleaseNull(CF) { CFTypeRef _cf = (CF); \ + if (_cf) { (CF) = NULL; CFRelease(_cf); } } +#define CFRetainSafe(CF) { CFTypeRef _cf = (CF); if (_cf) CFRetain(_cf); } + +#define xpc_release_safe(obj) if (obj) { xpc_release(obj); obj = NULL; } +#define free_safe(obj) if (obj) { free(obj); obj = NULL; } + +void _show_cf(CFTypeRef); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_AUTH_DEBUGGING_H_ */ diff --git a/tlsnke/tlsnke/en.lproj/InfoPlist.strings b/Security/authd/en.lproj/InfoPlist.strings similarity index 100% rename from tlsnke/tlsnke/en.lproj/InfoPlist.strings rename to Security/authd/en.lproj/InfoPlist.strings diff --git a/authd/engine.c b/Security/authd/engine.c similarity index 93% rename from authd/engine.c rename to Security/authd/engine.c index f52fa214..e9247196 100644 --- a/authd/engine.c +++ b/Security/authd/engine.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. */ #include "engine.h" #include "rule.h" @@ -29,7 +29,7 @@ static void _set_process_immutable_hints(auth_items_t, process_t); static void _set_auth_token_hints(auth_items_t, auth_token_t); static OSStatus _evaluate_user_credential_for_rule(engine_t, credential_t, rule_t, bool, bool, enum Reason *); static void _engine_set_credential(engine_t, credential_t, bool); -static OSStatus _evaluate_rule(engine_t, rule_t); +static OSStatus _evaluate_rule(engine_t, rule_t, bool *); enum { kEngineHintsFlagTemporary = (1 << 30) @@ -417,6 +417,35 @@ _evaluate_mechanisms(engine_t engine, CFArrayRef mechanisms) } else { agent_t agent = _get_agent(engine, mech, true, i == 0); require_action(agent != NULL, done, result = kAuthorizationResultUndefined; LOGE("engine[%i]: error creating mechanism agent", connection_get_pid(engine->conn))); + + // check if any agent has been interrupted (it necessary if interrupt will come during creation) + CFIndex j; + agent_t agent1; + for (j = 0; j < i; j++) { + agent1 = _get_agent(engine, (mechanism_t)CFArrayGetValueAtIndex(mechanisms, j), false, j == 0); + if(agent_get_state(agent1) == interrupting) { + break; + } + } + if (j < i) { + LOGV("engine[%i]: mechanisms interrupted", connection_get_pid(engine->conn)); + char * buf = NULL; + asprintf(&buf, "evaluation interrupted by %s; restarting evaluation there", mechanism_get_string(agent_get_mechanism(agent1))); + ccaudit_log_mechanism(ccaudit, engine->currentRightName, mechanism_get_string(agent_get_mechanism(agent1)), kAuthorizationResultAllow, buf); + free_safe(buf); + ccaudit_log_mechanism(ccaudit, engine->currentRightName, mechanism_get_string(mech), kAuthorizationResultAllow, NULL); + const char * token_name = auth_items_get_string(hints, AGENT_HINT_TOKEN_NAME); + if (token_name && strlen(token_name) == 0) { + auth_items_remove(hints, AGENT_HINT_TOKEN_NAME); + } + auth_items_copy(context, agent_get_context(agent1)); + auth_items_copy(hints, agent_get_hints(agent1)); + + i = j - 1; + + continue; + } + LOGV("engine[%i]: running mechanism %s (%li of %li)", connection_get_pid(engine->conn), mechanism_get_string(agent_get_mechanism(agent)), i+1, count); result = agent_run(agent, hints, context, engine->immutable_hints); @@ -472,6 +501,8 @@ done: if ((result == kAuthorizationResultUserCanceled) || (result == kAuthorizationResultAllow)) { // only make non-sticky context values available externally auth_items_set_flags(context, kAuthorizationEnvironmentPassword, kAuthorizationContextFlagVolatile); + // Takauthorizationenvironmentusername should always be extractable + auth_items_set_flags(context, kAuthorizationEnvironmentUsername, kAuthorizationContextFlagExtractable); auth_items_copy_with_flags(engine->context, context, kAuthorizationContextFlagExtractable | kAuthorizationContextFlagVolatile); } else if (result == kAuthorizationResultDeny) { auth_items_clear(engine->sticky_context); @@ -552,7 +583,7 @@ _evaluate_authentication(engine_t engine, rule_t rule) if (status == errAuthorizationSuccess) { _engine_set_credential(engine, newCred, rule_get_shared(rule)); CFReleaseSafe(newCred); - + if (auth_token_least_privileged(engine->auth)) { credential_t rightCred = credential_create_with_right(engine->currentRightName); _engine_set_credential(engine, rightCred, rule_get_shared(rule)); @@ -715,12 +746,12 @@ _evaluate_class_user(engine_t engine, rule_t rule) LOGV("engine[%i]: authorization denied (in DarkWake)", connection_get_pid(engine->conn)); return errAuthorizationDenied; } - - return _evaluate_authentication(engine,rule); + + return _evaluate_authentication(engine, rule); } static OSStatus -_evaluate_class_rule(engine_t engine, rule_t rule) +_evaluate_class_rule(engine_t engine, rule_t rule, bool *save_pwd) { __block OSStatus status = errAuthorizationDenied; int64_t kofn = rule_get_kofn(rule); @@ -738,7 +769,7 @@ _evaluate_class_rule(engine_t engine, rule_t rule) } LOGV("engine[%i]: * evaluate rule %s (%i)", connection_get_pid(engine->conn), rule_get_name(delegate), count); - status = _evaluate_rule(engine, delegate); + status = _evaluate_rule(engine, delegate, save_pwd); // if status is cancel/internal error abort if ((status == errAuthorizationCanceled) || (status == errAuthorizationInternal)) @@ -746,7 +777,7 @@ _evaluate_class_rule(engine_t engine, rule_t rule) if (status != errAuthorizationSuccess) { if (kofn != 0) { - // if remaining is less then required abort + // if remaining is less than required abort if ((total - count) < (kofn - success_count)) { LOGD("engine[%i]: rule evaluation remaining: %i, required: %lli", connection_get_pid(engine->conn), (total - count), (kofn - success_count)); return false; @@ -792,33 +823,30 @@ _evaluate_class_mechanism(engine_t engine, rule_t rule) status = _evaluate_mechanisms(engine, mechanisms); LOGV("engine[%i]: evaluate mechanisms result %i", connection_get_pid(engine->conn), status); - if ((status == errAuthorizationSuccess) || (status == errAuthorizationCanceled)) { - - if (status == errAuthorizationSuccess) { - credential_t newCred = NULL; - if (auth_items_exist(engine->context, "uid")) { - newCred = credential_create(auth_items_get_uint(engine->context, "uid")); - } else { - LOGV("engine[%i]: mechanism did not return a uid", connection_get_pid(engine->conn)); - } - - if (newCred) { - _engine_set_credential(engine, newCred, rule_get_shared(rule)); - - if (auth_token_least_privileged(engine->auth)) { - credential_t rightCred = credential_create_with_right(engine->currentRightName); - _engine_set_credential(engine, rightCred, rule_get_shared(rule)); - CFReleaseSafe(rightCred); - } - - if (strcmp(engine->currentRightName, "system.login.console") == 0 && !auth_items_exist(engine->context, AGENT_CONTEXT_AUTO_LOGIN)) { - session_set_attributes(auth_token_get_session(engine->auth), AU_SESSION_FLAG_HAS_AUTHENTICATED); - } - - CFReleaseSafe(newCred); - } - } - } // mechanism errAuthorizationSuccess + if (status == errAuthorizationSuccess) { + credential_t newCred = NULL; + if (auth_items_exist(engine->context, "uid")) { + newCred = credential_create(auth_items_get_uint(engine->context, "uid")); + } else { + LOGV("engine[%i]: mechanism did not return a uid", connection_get_pid(engine->conn)); + } + + if (newCred) { + _engine_set_credential(engine, newCred, rule_get_shared(rule)); + + if (auth_token_least_privileged(engine->auth)) { + credential_t rightCred = credential_create_with_right(engine->currentRightName); + _engine_set_credential(engine, rightCred, rule_get_shared(rule)); + CFReleaseSafe(rightCred); + } + + if (strcmp(engine->currentRightName, "system.login.console") == 0 && !auth_items_exist(engine->context, AGENT_CONTEXT_AUTO_LOGIN)) { + session_set_attributes(auth_token_get_session(engine->auth), AU_SESSION_FLAG_HAS_AUTHENTICATED); + } + + CFReleaseSafe(newCred); + } + } engine->tries++; @@ -830,7 +858,7 @@ done: } static OSStatus -_evaluate_rule(engine_t engine, rule_t rule) +_evaluate_rule(engine_t engine, rule_t rule, bool *save_pwd) { if (rule_check_flags(rule, RuleFlagEntitled)) { if (auth_token_has_entitlement_for_right(engine->auth, engine->currentRightName)) { @@ -845,7 +873,9 @@ _evaluate_rule(engine_t engine, rule_t rule) return errAuthorizationDenied; } } - + + *save_pwd |= rule_get_extract_password(rule); + switch (rule_get_class(rule)) { case RC_ALLOW: LOGV("engine[%i]: rule set to allow", connection_get_pid(engine->conn)); @@ -854,9 +884,9 @@ _evaluate_rule(engine_t engine, rule_t rule) LOGV("engine[%i]: rule set to deny", connection_get_pid(engine->conn)); return errAuthorizationDenied; case RC_USER: - return _evaluate_class_user(engine,rule); + return _evaluate_class_user(engine, rule); case RC_RULE: - return _evaluate_class_rule(engine, rule); + return _evaluate_class_rule(engine, rule, save_pwd); case RC_MECHANISM: return _evaluate_class_mechanism(engine, rule); default: @@ -1039,7 +1069,7 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en ccaudit_log(ccaudit, key, rule_name, 0); - status = _evaluate_rule(engine, engine->currentRule); + status = _evaluate_rule(engine, engine->currentRule, &savePassword); switch (status) { case errAuthorizationSuccess: auth_rights_add(engine->grantedRights, key); @@ -1048,15 +1078,13 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en if ((engine->flags & kAuthorizationFlagPreAuthorize) && (rule_get_class(engine->currentRule) == RC_USER) && (rule_get_timeout(engine->currentRule) == 0)) { + // FIXME: kAuthorizationFlagPreAuthorize => kAuthorizationFlagCanNotPreAuthorize ??? auth_rights_set_flags(engine->grantedRights, engine->currentRightName, kAuthorizationFlagPreAuthorize); } LOG("Succeeded authorizing right '%s' by client '%s' [%d] for authorization created by '%s' [%d] (%X,%d)", key, process_get_code_url(engine->proc), process_get_pid(engine->proc), auth_token_get_code_url(engine->auth), auth_token_get_pid(engine->auth), engine->flags, auth_token_least_privileged(engine->auth)); - if (rule_get_extract_password(engine->currentRule)) { - savePassword = true; - } break; case errAuthorizationDenied: case errAuthorizationInteractionNotAllowed: @@ -1122,12 +1150,12 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en return true; }); } - + + if (status == errAuthorizationSuccess && savePassword) { + auth_items_set_flags(engine->context, kAuthorizationEnvironmentPassword, kAuthorizationContextFlagExtractable); + } + if ((status == errAuthorizationSuccess) || (status == errAuthorizationCanceled)) { - if (savePassword && (status == errAuthorizationSuccess)) { - auth_items_set_flags(engine->context, kAuthorizationEnvironmentPassword, kAuthorizationContextFlagExtractable); - } - auth_items_copy_with_flags(auth_token_get_context(engine->auth), engine->context, kAuthorizationContextFlagExtractable); } diff --git a/authd/engine.h b/Security/authd/engine.h similarity index 93% rename from authd/engine.h rename to Security/authd/engine.h index 42170f08..9ca5355a 100644 --- a/authd/engine.h +++ b/Security/authd/engine.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ #ifndef _SECURITY_AUTH_ENGINE_H_ #define _SECURITY_AUTH_ENGINE_H_ diff --git a/Security/authd/main.c b/Security/authd/main.c new file mode 100644 index 00000000..f5c90f2f --- /dev/null +++ b/Security/authd/main.c @@ -0,0 +1,208 @@ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ + +#include "debugging.h" +#include "server.h" +#include "process.h" +#include "session.h" +#include "authtoken.h" +#include "engine.h" +#include "authd_private.h" +#include "connection.h" + +#include + +#include +#include +#include +#include +#include + +#if DEBUG +#include +#endif + +static void +security_auth_peer_event_handler(xpc_connection_t connection, xpc_object_t event) +{ + __block OSStatus status = errAuthorizationDenied; + + connection_t conn = (connection_t)xpc_connection_get_context(connection); + require_action(conn != NULL, done, LOGE("xpc[%i]: process context not found", xpc_connection_get_pid(connection))); + + CFRetainSafe(conn); + + xpc_type_t type = xpc_get_type(event); + + if (type == XPC_TYPE_ERROR) { + if (event == XPC_ERROR_CONNECTION_INVALID) { + // The client process on the other end of the connection has either + // crashed or cancelled the connection. After receiving this error, + // the connection is in an invalid state, and you do not need to + // call xpc_connection_cancel(). Just tear down any associated state + // here. + LOGV("xpc[%i]: client disconnected", xpc_connection_get_pid(connection)); + connection_destory_agents(conn); + } else if (event == XPC_ERROR_TERMINATION_IMMINENT) { + // Handle per-connection termination cleanup. + LOGD("xpc[%i]: per-connection termination", xpc_connection_get_pid(connection)); + } + } else { + assert(type == XPC_TYPE_DICTIONARY); + + xpc_object_t reply = xpc_dictionary_create_reply(event); + require(reply != NULL, done); + + uint64_t auth_type = xpc_dictionary_get_uint64(event, AUTH_XPC_TYPE); + LOGV("xpc[%i]: received message type=%llu", connection_get_pid(conn), auth_type); + + switch (auth_type) { + case AUTHORIZATION_CREATE: + status = authorization_create(conn,event,reply); + break; + case AUTHORIZATION_CREATE_WITH_AUDIT_TOKEN: + status = authorization_create_with_audit_token(conn,event,reply); + break; + case AUTHORIZATION_FREE: + status = authorization_free(conn,event,reply); + break; + case AUTHORIZATION_COPY_RIGHTS: + status = authorization_copy_rights(conn,event,reply); + break; + case AUTHORIZATION_COPY_INFO: + status = authorization_copy_info(conn,event,reply); + break; + case AUTHORIZATION_MAKE_EXTERNAL_FORM: + status = authorization_make_external_form(conn,event,reply); + break; + case AUTHORIZATION_CREATE_FROM_EXTERNAL_FORM: + status = authorization_create_from_external_form(conn,event,reply); + break; + case AUTHORIZATION_RIGHT_GET: + status = authorization_right_get(conn,event,reply); + break; + case AUTHORIZATION_RIGHT_SET: + status = authorization_right_set(conn,event,reply); + break; + case AUTHORIZATION_RIGHT_REMOVE: + status = authorization_right_remove(conn,event,reply); + break; + case SESSION_SET_USER_PREFERENCES: + status = session_set_user_preferences(conn,event,reply); + break; + case AUTHORIZATION_DISMISS: + connection_destory_agents(conn); + status = errAuthorizationSuccess; + break; + case AUTHORIZATION_ENABLE_SMARTCARD: + status = authorization_enable_smartcard(conn,event,reply); + break; + case AUTHORIZATION_SETUP: + { + mach_port_t bootstrap = xpc_dictionary_copy_mach_send(event, AUTH_XPC_BOOTSTRAP); + if (!process_set_bootstrap(connection_get_process(conn), bootstrap)) { + if (bootstrap != MACH_PORT_NULL) { + mach_port_deallocate(mach_task_self(), bootstrap); + } + } + } + status = errAuthorizationSuccess; + break; +#if DEBUG + case AUTHORIZATION_DEV: + server_dev(); + break; +#endif + default: + break; + } + + xpc_dictionary_set_int64(reply, AUTH_XPC_STATUS, status); + xpc_connection_send_message(connection, reply); + xpc_release(reply); + } + +done: + CFReleaseSafe(conn); +} + +static void +connection_finalizer(void * conn) +{ + LOGD("xpc[%i]: connection_finalizer", connection_get_pid(conn)); + server_unregister_connection(conn); + +//#if DEBUG +// malloc_printf("-=-=-=- connection_finalizer() -=-=-=-\n"); +// malloc_zone_print(malloc_default_zone(), false); +//#endif +} + +static void +security_auth_event_handler(xpc_connection_t xpc_conn) +{ + connection_t conn = server_register_connection(xpc_conn); + + if (conn) { + xpc_connection_set_context(xpc_conn, conn); + xpc_connection_set_finalizer_f(xpc_conn, connection_finalizer); + + xpc_connection_set_event_handler(xpc_conn, ^(xpc_object_t event) { + xpc_retain(xpc_conn); + xpc_retain(event); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + security_auth_peer_event_handler(xpc_conn, event); + xpc_release(event); + xpc_release(xpc_conn); + }); + }); + xpc_connection_resume(xpc_conn); + + } else { + LOGE("xpc[%i]: failed to register connection", xpc_connection_get_pid(xpc_conn)); + xpc_connection_cancel(xpc_conn); + } +} + +static void sandbox() +{ + char * errorbuf; + int32_t rc; + + rc = sandbox_init(SECURITY_AUTH_NAME, SANDBOX_NAMED, &errorbuf); + + if (rc) { + LOGE("server: sandbox_init failed %s (%i)", errorbuf, rc); + sandbox_free_error(errorbuf); +#ifndef DEBUG + abort(); +#endif + } +} + +int main(int argc AUTH_UNUSED, const char *argv[] AUTH_UNUSED) +{ +//#if DEBUG +// malloc_printf("-=-=-=- main() -=-=-=-\n"); +// malloc_zone_print(malloc_default_zone(), false); +//#endif + + LOGV("starting"); + + sandbox(); + + if (server_init() != errAuthorizationSuccess) { + LOGE("auth: server_init() failed"); + return errAuthorizationInternal; + } + +//#if DEBUG +// malloc_printf("-=-=-=- server_init() -=-=-=-\n"); +// malloc_zone_print(malloc_default_zone(), false); +//#endif + + xpc_main(security_auth_event_handler); + + server_cleanup(); + + return 0; +} diff --git a/authd/mechanism.c b/Security/authd/mechanism.c similarity index 99% rename from authd/mechanism.c rename to Security/authd/mechanism.c index e57c8200..f2860f12 100644 --- a/authd/mechanism.c +++ b/Security/authd/mechanism.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012 Apple Inc. All Rights Reserved. */ #include "mechanism.h" #include "authdb.h" diff --git a/authd/mechanism.h b/Security/authd/mechanism.h similarity index 95% rename from authd/mechanism.h rename to Security/authd/mechanism.h index f483a98d..a908c448 100644 --- a/authd/mechanism.h +++ b/Security/authd/mechanism.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012 Apple Inc. All Rights Reserved. */ #ifndef _SECURITY_AUTH_MECHANISM_H_ #define _SECURITY_AUTH_MECHANISM_H_ diff --git a/Security/authd/object.c b/Security/authd/object.c new file mode 100644 index 00000000..2b44b4f8 --- /dev/null +++ b/Security/authd/object.c @@ -0,0 +1,5 @@ +/* Copyright (c) 2012 Apple Inc. All Rights Reserved. */ + +#include "object.h" +#include "crc.h" +#include "authutilities.h" diff --git a/authd/object.h b/Security/authd/object.h similarity index 92% rename from authd/object.h rename to Security/authd/object.h index 7731f788..c4525fb8 100644 --- a/authd/object.h +++ b/Security/authd/object.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012 Apple Inc. All Rights Reserved. */ #ifndef _SECURITY_AUTH_OBJECT_H_ #define _SECURITY_AUTH_OBJECT_H_ diff --git a/authd/process.c b/Security/authd/process.c similarity index 99% rename from authd/process.c rename to Security/authd/process.c index 9f1b2163..59e78f40 100644 --- a/authd/process.c +++ b/Security/authd/process.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ #include "process.h" #include "server.h" @@ -188,7 +188,7 @@ process_create(const audit_info_s * auditInfo, session_t session) if (status == errSecSuccess) { proc->appleSigned = process_verify_requirment(proc, secRequirementRef); } - CFRelease(secRequirementRef); + CFReleaseSafe(secRequirementRef); LOGV("process[%i]: created (sid=%i) %s %p", proc->auditInfo.pid, proc->auditInfo.asid, proc->code_url, proc); diff --git a/Security/authd/process.h b/Security/authd/process.h new file mode 100644 index 00000000..cb89b4d4 --- /dev/null +++ b/Security/authd/process.h @@ -0,0 +1,102 @@ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ + +#ifndef _SECURITY_AUTH_PROCESS_H_ +#define _SECURITY_AUTH_PROCESS_H_ + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED +process_t process_create(const audit_info_s*,session_t); + +AUTH_NONNULL_ALL +const void * process_get_key(process_t); + +AUTH_NONNULL_ALL +uid_t process_get_uid(process_t); + +AUTH_NONNULL_ALL +pid_t process_get_pid(process_t); + +AUTH_NONNULL_ALL +int32_t process_get_generation(process_t); + +AUTH_NONNULL_ALL +session_id_t process_get_session_id(process_t); + +AUTH_NONNULL_ALL +session_t process_get_session(process_t); + +AUTH_NONNULL_ALL +uint32_t process_get_count(process_t); + +AUTH_NONNULL_ALL +const audit_info_s * process_get_audit_info(process_t); + +AUTH_NONNULL_ALL +SecCodeRef process_get_code(process_t); + +AUTH_NONNULL_ALL +const char * process_get_code_url(process_t); + +AUTH_NONNULL_ALL +CFIndex process_add_connection(process_t, connection_t); + +AUTH_NONNULL_ALL +CFIndex process_remove_connection(process_t, connection_t); + +AUTH_NONNULL_ALL +CFIndex process_get_connection_count(process_t); + +AUTH_NONNULL_ALL +void process_add_auth_token(process_t,auth_token_t); + +AUTH_NONNULL_ALL +void process_remove_auth_token(process_t,auth_token_t, uint32_t flags); + +AUTH_NONNULL_ALL +auth_token_t process_find_copy_auth_token(process_t,const AuthorizationBlob*); + +AUTH_NONNULL_ALL +CFIndex process_get_auth_token_count(process_t); + +AUTH_NONNULL_ALL +CFTypeRef process_copy_entitlement_value(process_t, const char * entitlement); + +AUTH_NONNULL_ALL +bool process_has_entitlement(process_t, const char * entitlement); + +AUTH_NONNULL_ALL +bool process_has_entitlement_for_right(process_t, const char * right); + +AUTH_NONNULL_ALL +const char * process_get_identifier(process_t); + +AUTH_NONNULL_ALL +CFDataRef process_get_requirement_data(process_t); + +AUTH_NONNULL_ALL +SecRequirementRef process_get_requirement(process_t); + +AUTH_NONNULL_ALL +bool process_verify_requirment(process_t,SecRequirementRef); + +AUTH_NONNULL_ALL +bool process_apple_signed(process_t proc); + +AUTH_NONNULL_ALL +mach_port_t process_get_bootstrap(process_t); + +AUTH_NONNULL_ALL +bool process_set_bootstrap(process_t, mach_port_t); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_AUTH_PROCESS_H_ */ diff --git a/authd/rule.c b/Security/authd/rule.c similarity index 99% rename from authd/rule.c rename to Security/authd/rule.c index bf31c89a..e1395280 100644 --- a/authd/rule.c +++ b/Security/authd/rule.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ #include "rule.h" #include "authutilities.h" diff --git a/authd/rule.h b/Security/authd/rule.h similarity index 98% rename from authd/rule.h rename to Security/authd/rule.h index 1aefb226..1d757949 100644 --- a/authd/rule.h +++ b/Security/authd/rule.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ #ifndef _SECURITY_AUTH_RULE_H_ #define _SECURITY_AUTH_RULE_H_ diff --git a/authd/security.auth-Prefix.pch b/Security/authd/security.auth-Prefix.pch similarity index 100% rename from authd/security.auth-Prefix.pch rename to Security/authd/security.auth-Prefix.pch diff --git a/Security/authd/server.c b/Security/authd/server.c new file mode 100644 index 00000000..7449ca92 --- /dev/null +++ b/Security/authd/server.c @@ -0,0 +1,1169 @@ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ + +#include "server.h" +#include "session.h" +#include "process.h" +#include "authtoken.h" +#include "authdb.h" +#include "rule.h" +#include "authutilities.h" +#include "crc.h" +#include "mechanism.h" +#include "agent.h" +#include "authitems.h" +#include "debugging.h" +#include "engine.h" +#include "connection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_PROCESS_RIGHTS 100 + +static CFMutableDictionaryRef gProcessMap = NULL; +static CFMutableDictionaryRef gSessionMap = NULL; +static CFMutableDictionaryRef gAuthTokenMap = NULL; +static authdb_t gDatabase = NULL; + +static dispatch_queue_t power_queue; +static bool gInDarkWake = false; +static IOPMConnection gIOPMconn = NULL; +static bool gXPCTransaction = false; + +static dispatch_queue_t +get_server_dispatch_queue() +{ + static dispatch_once_t onceToken; + static dispatch_queue_t server_queue = NULL; + + dispatch_once(&onceToken, ^{ + server_queue = dispatch_queue_create("com.apple.security.auth.server", DISPATCH_QUEUE_SERIAL); + check(server_queue != NULL); + }); + + return server_queue; +} + +static Boolean _processEqualCallBack(const void *value1, const void *value2) +{ + audit_info_s * info1 = (audit_info_s*)value1; + audit_info_s * info2 = (audit_info_s*)value2; + if (info1->pid == info2->pid) { + if (info1->tid == info2->tid) { + return true; + } + } + return false; +} + +static CFHashCode _processHashCallBack(const void *value) +{ + audit_info_s * info = (audit_info_s*)value; + uint64_t crc = crc64_init(); + crc = crc64_update(crc, &info->pid, sizeof(info->pid)); + crc = crc64_update(crc, &info->tid, sizeof(info->tid)); + crc = crc64_final(crc); + return crc; +} + +static const CFDictionaryKeyCallBacks kProcessMapKeyCallBacks = { + .version = 0, + .retain = NULL, + .release = NULL, + .copyDescription = NULL, + .equal = &_processEqualCallBack, + .hash = &_processHashCallBack +}; + +static Boolean _sessionEqualCallBack(const void *value1, const void *value2) +{ + return (*(session_id_t*)value1) == (*(session_id_t*)value2); +} + +static CFHashCode _sessionHashCallBack(const void *value) +{ + return (CFHashCode)(*(session_id_t*)(value)); +} + +static const CFDictionaryKeyCallBacks kSessionMapKeyCallBacks = { + .version = 0, + .retain = NULL, + .release = NULL, + .copyDescription = NULL, + .equal = &_sessionEqualCallBack, + .hash = &_sessionHashCallBack +}; + +void server_cleanup() +{ + CFRelease(gProcessMap); + CFRelease(gSessionMap); + CFRelease(gAuthTokenMap); + + IOPMConnectionSetDispatchQueue(gIOPMconn, NULL); + IOPMConnectionRelease(gIOPMconn); + + dispatch_queue_t queue = get_server_dispatch_queue(); + if (queue) { + dispatch_release(queue); + } + dispatch_release(power_queue); +} + +static void _IOMPCallBack(void * param AUTH_UNUSED, IOPMConnection connection, IOPMConnectionMessageToken token, IOPMSystemPowerStateCapabilities capabilities) +{ + LOGV("server: IOMP powerstates %i", capabilities); + if (capabilities & kIOPMSystemPowerStateCapabilityDisk) + LOGV("server: disk"); + if (capabilities & kIOPMSystemPowerStateCapabilityNetwork) + LOGV("server: net"); + if (capabilities & kIOPMSystemPowerStateCapabilityAudio) + LOGV("server: audio"); + if (capabilities & kIOPMSystemPowerStateCapabilityVideo) + LOGV("server: video"); + + /* if cpu and no display -> in DarkWake */ + LOGD("server: DarkWake check current=%i==%i", (capabilities & (kIOPMSystemPowerStateCapabilityCPU|kIOPMSystemPowerStateCapabilityVideo)), kIOPMSystemPowerStateCapabilityCPU); + if ((capabilities & (kIOPMSystemPowerStateCapabilityCPU|kIOPMSystemPowerStateCapabilityVideo)) == kIOPMSystemPowerStateCapabilityCPU) { + LOGV("server: enter DarkWake"); + gInDarkWake = true; + } else if (gInDarkWake) { + LOGV("server: exit DarkWake"); + gInDarkWake = false; + } + + (void)IOPMConnectionAcknowledgeEvent(connection, token); + + return; +} + +static void +_setupDarkWake(void *ctx) +{ + IOReturn ret; + + IOPMConnectionCreate(CFSTR("IOPowerWatcher"), + kIOPMSystemPowerStateCapabilityDisk + | kIOPMSystemPowerStateCapabilityNetwork + | kIOPMSystemPowerStateCapabilityAudio + | kIOPMSystemPowerStateCapabilityVideo, + &gIOPMconn); + + ret = IOPMConnectionSetNotification(gIOPMconn, NULL, _IOMPCallBack); + if (ret != kIOReturnSuccess) + return; + + IOPMConnectionSetDispatchQueue(gIOPMconn, power_queue); + + IOPMScheduleUserActiveChangedNotification(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(bool active) { + if (active) { + gInDarkWake = false; + } + }); +} + +bool server_in_dark_wake() +{ + return gInDarkWake; +} + +authdb_t server_get_database() +{ + return gDatabase; +} + +static void _setupAuditSessionMonitor() +{ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + au_sdev_handle_t *dev = au_sdev_open(AU_SDEVF_ALLSESSIONS); + int event; + auditinfo_addr_t aia; + + if (NULL == dev) { + LOGE("server: could not open %s %d", AUDIT_SDEV_PATH, errno); + return; + } + + for (;;) { + if (0 != au_sdev_read_aia(dev, &event, &aia)) { + LOGE("server: au_sdev_read_aia failed: %d", errno); + continue; + } + LOGD("server: au_sdev_handle_t event=%i, session=%i", event, aia.ai_asid); + if (event == AUE_SESSION_CLOSE) { + dispatch_async(get_server_dispatch_queue(), ^{ + LOGV("server: session %i destroyed", aia.ai_asid); + CFDictionaryRemoveValue(gSessionMap, &aia.ai_asid); + }); + } + } + + }); +} + +static void _setupSignalHandlers() +{ + signal(SIGTERM, SIG_IGN); + static dispatch_source_t sigtermHandler; + sigtermHandler = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGTERM, 0, get_server_dispatch_queue()); + if (sigtermHandler) { + dispatch_source_set_event_handler(sigtermHandler, ^{ + + // should we clean up any state? + exit(EXIT_SUCCESS); + }); + dispatch_resume(sigtermHandler); + } +} + +OSStatus server_init(void) +{ + OSStatus status = errAuthorizationSuccess; + + auditinfo_addr_t info; + memset(&info, 0, sizeof(info)); + getaudit_addr(&info, sizeof(info)); + LOGV("server: uid=%i, sid=%i", info.ai_auid, info.ai_asid); + + require_action(get_server_dispatch_queue() != NULL, done, status = errAuthorizationInternal); + + gProcessMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kProcessMapKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + require_action(gProcessMap != NULL, done, status = errAuthorizationInternal); + + gSessionMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kSessionMapKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + require_action(gSessionMap != NULL, done, status = errAuthorizationInternal); + + gAuthTokenMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kAuthTokenKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + require_action(gAuthTokenMap != NULL, done, status = errAuthorizationInternal); + + gDatabase = authdb_create(); + require_action(gDatabase != NULL, done, status = errAuthorizationInternal); + + // check to see if we have an updates + authdb_connection_t dbconn = authdb_connection_acquire(gDatabase); + authdb_maintenance(dbconn); + authdb_connection_release(&dbconn); + + power_queue = dispatch_queue_create("com.apple.security.auth.power", DISPATCH_QUEUE_SERIAL); + check(power_queue != NULL); + dispatch_async_f(power_queue, NULL, _setupDarkWake); + + _setupAuditSessionMonitor(); + _setupSignalHandlers(); + +done: + return status; +} + +static void _server_parse_audit_token(audit_token_t * token, audit_info_s * info) +{ + if (token && info) { + memset(info, 0, sizeof(*info)); + au_tid_t tid; + memset(&tid, 0, sizeof(tid)); + audit_token_to_au32(*token, &info->auid, &info->euid, + &info->egid, &info->ruid, &info->rgid, + &info->pid, &info->asid, &tid); + info->tid = tid.port; + info->opaqueToken = *token; + } +} + +connection_t +server_register_connection(xpc_connection_t connection) +{ + __block connection_t conn = NULL; + __block session_t session = NULL; + __block process_t proc = NULL; + __block CFIndex conn_count = 0; + + require(connection != NULL, done); + + audit_token_t auditToken; + audit_info_s info; + xpc_connection_get_audit_token(connection, &auditToken); + _server_parse_audit_token(&auditToken, &info); + + + dispatch_sync(get_server_dispatch_queue(), ^{ + session = (session_t)CFDictionaryGetValue(gSessionMap, &info.asid); + if (session) { + CFRetain(session); + } else { + session = session_create(info.asid); + CFDictionarySetValue(gSessionMap, session_get_key(session), session); + } + + proc = (process_t)CFDictionaryGetValue(gProcessMap, &info); + if (proc) { + CFRetain(proc); + } + + if (proc) { + conn = connection_create(proc); + conn_count = process_add_connection(proc, conn); + } else { + proc = process_create(&info, session); + if (proc) { + conn = connection_create(proc); + conn_count = process_add_connection(proc, conn); + session_add_process(session, proc); + CFDictionarySetValue(gProcessMap, process_get_key(proc), proc); + } + } + + if (!gXPCTransaction) { + xpc_transaction_begin(); + gXPCTransaction = true; + } + }); + + LOGV("server[%i]: registered connection (total=%li)", info.pid, conn_count); + +done: + CFReleaseSafe(session); + CFReleaseSafe(proc); + return conn; +} + +void +server_unregister_connection(connection_t conn) +{ + if (conn != NULL) { + process_t proc = connection_get_process(conn); + + dispatch_sync(get_server_dispatch_queue(), ^{ + CFIndex connectionCount = process_get_connection_count(proc); + LOGV("server[%i]: unregistered connection (total=%li)", process_get_pid(proc), connectionCount); + + if (connectionCount == 1) { + CFDictionaryRemoveValue(gProcessMap, process_get_key(proc)); + } + + if (CFDictionaryGetCount(gProcessMap) == 0) { + xpc_transaction_end(); + gXPCTransaction = false; + } + }); + // move the destruction of the connection/process off the server queue + CFRelease(conn); + } +} + +void +server_register_auth_token(auth_token_t auth) +{ + if (auth != NULL) { + dispatch_sync(get_server_dispatch_queue(), ^{ + LOGV("server: registering auth %p", auth); + CFDictionarySetValue(gAuthTokenMap, auth_token_get_key(auth), auth); + auth_token_set_state(auth, auth_token_state_registered); + }); + } +} + +void +server_unregister_auth_token(auth_token_t auth) +{ + if (auth != NULL) { + AuthorizationBlob blob = *(AuthorizationBlob*)auth_token_get_key(auth); + dispatch_async(get_server_dispatch_queue(), ^{ + LOGV("server: unregistering auth %p", auth); + CFDictionaryRemoveValue(gAuthTokenMap, &blob); + }); + } +} + +auth_token_t +server_find_copy_auth_token(AuthorizationBlob * blob) +{ + __block auth_token_t auth = NULL; + if (blob != NULL) { + dispatch_sync(get_server_dispatch_queue(), ^{ + auth = (auth_token_t)CFDictionaryGetValue(gAuthTokenMap, blob); + if (auth) { + CFRetain(auth); + } + }); + } + return auth; +} + +session_t +server_find_copy_session(session_id_t sid, bool create) +{ + __block session_t session = NULL; + + dispatch_sync(get_server_dispatch_queue(), ^{ + session = (session_t)CFDictionaryGetValue(gSessionMap, &sid); + if (session) { + CFRetain(session); + } else if (create) { + session = session_create(sid); + if (session) { + CFDictionarySetValue(gSessionMap, session_get_key(session), session); + } + } + }); + + return session; +} + +#pragma mark - +#pragma mark API + +static OSStatus +_process_find_copy_auth_token_from_xpc(process_t proc, xpc_object_t message, auth_token_t * auth_out) +{ + OSStatus status = errAuthorizationSuccess; + require_action(auth_out != NULL, done, status = errAuthorizationInternal); + + size_t len; + AuthorizationBlob * blob = (AuthorizationBlob *)xpc_dictionary_get_data(message, AUTH_XPC_BLOB, &len); + require_action(blob != NULL, done, status = errAuthorizationInvalidRef); + require_action(len == sizeof(AuthorizationBlob), done, status = errAuthorizationInvalidRef); + + auth_token_t auth = process_find_copy_auth_token(proc, blob); + require_action(auth != NULL, done, status = errAuthorizationInvalidRef); + +#if DEBUG + LOGV("server[%i]: authtoken lookup %#x%x %p", process_get_pid(proc), blob->data[1],blob->data[0], auth); +#else + LOGV("server[%i]: authtoken lookup %p", process_get_pid(proc), auth); +#endif + + *auth_out = auth; + +done: + return status; +} + +static OSStatus _server_authorize(connection_t conn, auth_token_t auth, AuthorizationFlags flags, auth_rights_t rights, auth_items_t enviroment, engine_t * engine_out) +{ + __block OSStatus status = errAuthorizationDenied; + engine_t engine = NULL; + + require_action(conn, done, status = errAuthorizationInternal); + + engine = engine_create(conn, auth); + require_action(engine, done, status = errAuthorizationInternal); + + if (flags & kAuthorizationFlagInteractionAllowed) { + dispatch_sync(connection_get_dispatch_queue(conn), ^{ + connection_set_engine(conn, engine); + status = engine_authorize(engine, rights, enviroment, flags); + connection_set_engine(conn, NULL); + }); + } else { + status = engine_authorize(engine, rights, enviroment, flags); + } + +done: + if (engine) { + if (engine_out) { + *engine_out = engine; + } else { + CFRelease(engine); + } + } + return status; +} + +// IN: AUTH_XPC_RIGHTS, AUTH_XPC_ENVIROMENT, AUTH_XPC_FLAGS +// OUT: AUTH_XPC_BLOB +OSStatus +authorization_create(connection_t conn, xpc_object_t message, xpc_object_t reply) +{ + OSStatus status = errAuthorizationDenied; + + process_t proc = connection_get_process(conn); + + // Passed in args + auth_rights_t rights = auth_rights_create_with_xpc(xpc_dictionary_get_value(message, AUTH_XPC_RIGHTS)); + auth_items_t enviroment = auth_items_create_with_xpc(xpc_dictionary_get_value(message, AUTH_XPC_ENVIROMENT)); + AuthorizationFlags flags = (AuthorizationFlags)xpc_dictionary_get_uint64(message, AUTH_XPC_FLAGS); + + // Create Authorization Token + auth_token_t auth = auth_token_create(proc, flags & kAuthorizationFlagLeastPrivileged); + require_action(auth != NULL, done, status = errAuthorizationInternal); + + if (!(flags & kAuthorizationFlagNoData)) { + process_add_auth_token(proc,auth); + } + + status = _server_authorize(conn, auth, flags, rights, enviroment, NULL); + require_noerr(status, done); + + //reply + xpc_dictionary_set_data(reply, AUTH_XPC_BLOB, auth_token_get_blob(auth), sizeof(AuthorizationBlob)); + +done: + CFReleaseSafe(rights); + CFReleaseSafe(enviroment); + CFReleaseSafe(auth); + return status; +} + +// IN: AUTH_XPC_DATA, AUTH_XPC_ENVIROMENT, AUTH_XPC_FLAGS +// OUT: AUTH_XPC_BLOB +OSStatus authorization_create_with_audit_token(connection_t conn, xpc_object_t message, xpc_object_t reply) +{ + OSStatus status = errAuthorizationDenied; + auth_token_t auth = NULL; + + process_t proc = connection_get_process(conn); + require(process_get_uid(proc) == 0, done); //only root can use this call + + // Passed in args + size_t len = 0; + const char * data = xpc_dictionary_get_data(message, AUTH_XPC_DATA, &len); + require(data != NULL, done); + require(len == sizeof(audit_token_t), done); + +// auth_items_t enviroment = auth_items_create_with_xpc(xpc_dictionary_get_value(message, AUTH_XPC_ENVIROMENT)); + AuthorizationFlags flags = (AuthorizationFlags)xpc_dictionary_get_uint64(message, AUTH_XPC_FLAGS); + + audit_info_s auditInfo; + _server_parse_audit_token((audit_token_t*)data, &auditInfo); + + // Create Authorization Token + auth = auth_token_create(proc, flags & kAuthorizationFlagLeastPrivileged); + require_action(auth != NULL, done, status = errAuthorizationInternal); + + process_add_auth_token(proc,auth); + + //reply + xpc_dictionary_set_data(reply, AUTH_XPC_BLOB, auth_token_get_blob(auth), sizeof(AuthorizationBlob)); + +done: +// CFReleaseSafe(enviroment); + CFReleaseSafe(auth); + return status; +} + +// IN: AUTH_XPC_BLOB, AUTH_XPC_FLAGS +// OUT: +OSStatus +authorization_free(connection_t conn, xpc_object_t message, xpc_object_t reply AUTH_UNUSED) +{ + OSStatus status = errAuthorizationSuccess; + AuthorizationFlags flags = 0; + process_t proc = connection_get_process(conn); + + auth_token_t auth = NULL; + status = _process_find_copy_auth_token_from_xpc(proc, message, &auth); + require_noerr(status, done); + + flags = (AuthorizationFlags)xpc_dictionary_get_uint64(message, AUTH_XPC_FLAGS); + + if (flags & kAuthorizationFlagDestroyRights) { + auth_token_credentials_iterate(auth, ^bool(credential_t cred) { + credential_invalidate(cred); + LOGV("engine[%i]: invalidating %scredential %s (%i) from authorization (%p)", connection_get_pid(conn), credential_get_shared(cred) ? "shared " : "", credential_get_name(cred), credential_get_uid(cred), auth); + return true; + }); + + session_credentials_purge(auth_token_get_session(auth)); + } + + process_remove_auth_token(proc, auth, flags); + +done: + CFReleaseSafe(auth); + LOGV("server[%i]: AuthorizationFree %i (flags:%x)", connection_get_pid(conn), status, flags); + return status; +} + +// IN: AUTH_XPC_BLOB, AUTH_XPC_RIGHTS, AUTH_XPC_ENVIROMENT, AUTH_XPC_FLAGS +// OUT: AUTH_XPC_OUT_ITEMS +OSStatus +authorization_copy_rights(connection_t conn, xpc_object_t message, xpc_object_t reply) +{ + OSStatus status = errAuthorizationDenied; + engine_t engine = NULL; + + process_t proc = connection_get_process(conn); + + // Passed in args + auth_rights_t rights = auth_rights_create_with_xpc(xpc_dictionary_get_value(message, AUTH_XPC_RIGHTS)); + auth_items_t enviroment = auth_items_create_with_xpc(xpc_dictionary_get_value(message, AUTH_XPC_ENVIROMENT)); + AuthorizationFlags flags = (AuthorizationFlags)xpc_dictionary_get_uint64(message, AUTH_XPC_FLAGS); + + auth_token_t auth = NULL; + status = _process_find_copy_auth_token_from_xpc(proc, message, &auth); + require_noerr(status, done); + + status = _server_authorize(conn, auth, flags, rights, enviroment, &engine); + require_noerr(status, done); + + //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); + +done: + CFReleaseSafe(rights); + CFReleaseSafe(enviroment); + CFReleaseSafe(auth); + CFReleaseSafe(engine); + + return status; +} + +// IN: AUTH_XPC_BLOB, AUTH_XPC_TAG +// OUT: AUTH_XPC_OUT_ITEMS +OSStatus +authorization_copy_info(connection_t conn, xpc_object_t message, xpc_object_t reply) +{ + + OSStatus status = errAuthorizationSuccess; + auth_items_t items = NULL; + const char * tag = NULL; + + process_t proc = connection_get_process(conn); + + auth_token_t auth = NULL; + status = _process_find_copy_auth_token_from_xpc(proc, message, &auth); + require_noerr(status, done); + + items = auth_items_create(); + + tag = xpc_dictionary_get_string(message, AUTH_XPC_TAG); + LOGV("server[%i]: requested tag: %s", connection_get_pid(conn), tag ? tag : "(all)"); + if (tag) { + size_t len; + const void * data = auth_items_get_data(auth_token_get_context(auth), tag, &len); + if (data) { + auth_items_set_data(items, tag, data, len); + } + } else { + auth_items_copy(items, auth_token_get_context(auth)); + } + +#if DEBUG + LOGV("server[%i]: Dumping requested AuthRef items", connection_get_pid(conn)); + _show_cf(items); +#endif + + //reply + xpc_object_t outItems = auth_items_export_xpc(items); + xpc_dictionary_set_value(reply, AUTH_XPC_OUT_ITEMS, outItems); + xpc_release_safe(outItems); + +done: + CFReleaseSafe(items); + CFReleaseSafe(auth); + LOGV("server[%i]: AuthorizationCopyInfo %i", connection_get_pid(conn), status); + return status; +} + +// IN: AUTH_XPC_BLOB +// OUT: AUTH_XPC_EXTERNAL +OSStatus +authorization_make_external_form(connection_t conn, xpc_object_t message, xpc_object_t reply) +{ + OSStatus status = errAuthorizationSuccess; + + process_t proc = connection_get_process(conn); + + auth_token_t auth = NULL; + status = _process_find_copy_auth_token_from_xpc(proc, message, &auth); + require_noerr(status, done); + + AuthorizationExternalForm exForm; + AuthorizationExternalBlob * exBlob = (AuthorizationExternalBlob *)&exForm; + memset(&exForm, 0, sizeof(exForm)); + + exBlob->blob = *auth_token_get_blob(auth); + exBlob->session = process_get_session_id(proc); + + xpc_dictionary_set_data(reply, AUTH_XPC_EXTERNAL, &exForm, sizeof(exForm)); + server_register_auth_token(auth); + +done: + CFReleaseSafe(auth); + LOGV("server[%i]: AuthorizationMakeExternalForm %i", connection_get_pid(conn), status); + return status; +} + +// IN: AUTH_XPC_EXTERNAL +// OUT: AUTH_XPC_BLOB +OSStatus +authorization_create_from_external_form(connection_t conn, xpc_object_t message, xpc_object_t reply) +{ + OSStatus status = errAuthorizationSuccess; + auth_token_t auth = NULL; + + process_t proc = connection_get_process(conn); + + size_t len; + AuthorizationExternalForm * exForm = (AuthorizationExternalForm *)xpc_dictionary_get_data(message, AUTH_XPC_EXTERNAL, &len); + require_action(exForm != NULL, done, status = errAuthorizationInternal); + require_action(len == sizeof(AuthorizationExternalForm), done, status = errAuthorizationInvalidRef); + + AuthorizationExternalBlob * exBlob = (AuthorizationExternalBlob *)exForm; + auth = server_find_copy_auth_token(&exBlob->blob); + require_action(auth != NULL, done, status = errAuthorizationDenied); + + process_add_auth_token(proc, auth); + xpc_dictionary_set_data(reply, AUTH_XPC_BLOB, auth_token_get_blob(auth), sizeof(AuthorizationBlob)); + +done: + CFReleaseSafe(auth); + LOGV("server[%i]: AuthorizationCreateFromExternalForm %i", connection_get_pid(conn), status); + return status; +} + +// IN: AUTH_XPC_RIGHT_NAME +// OUT: AUTH_XPC_DATA +OSStatus +authorization_right_get(connection_t conn AUTH_UNUSED, xpc_object_t message, xpc_object_t reply) +{ + OSStatus status = errAuthorizationDenied; + rule_t rule = NULL; + CFTypeRef cfdict = NULL; + xpc_object_t xpcdict = NULL; + + authdb_connection_t dbconn = authdb_connection_acquire(server_get_database()); + rule = rule_create_with_string(xpc_dictionary_get_string(message, AUTH_XPC_RIGHT_NAME), dbconn); + require(rule != NULL, done); + require(rule_get_id(rule) != 0, done); + + cfdict = rule_copy_to_cfobject(rule, dbconn); + require(cfdict != NULL, done); + + xpcdict = _CFXPCCreateXPCObjectFromCFObject(cfdict); + require(xpcdict != NULL, done); + + // reply + xpc_dictionary_set_value(reply, AUTH_XPC_DATA, xpcdict); + + status = errAuthorizationSuccess; + +done: + authdb_connection_release(&dbconn); + CFReleaseSafe(cfdict); + xpc_release_safe(xpcdict); + CFReleaseSafe(rule); + LOGV("server[%i]: AuthorizationRightGet %i", connection_get_pid(conn), status); + return status; +} + +static bool _prompt_for_modifications(process_t proc, rule_t rule) +{ +// will put back it back at some later date +// SecRequirementRef ruleReq = rule_get_requirment(rule); +// +// if (ruleReq && process_verify_requirment(proc, ruleReq)) { +// return false; +// } + + return true; +} + +static CFIndex _get_mechanism_index(CFArrayRef mechanisms, CFStringRef m_name) +{ + CFIndex index = -1; + require(mechanisms, done); + + CFIndex c = CFArrayGetCount(mechanisms); + CFStringRef i_name = NULL; + for (CFIndex i = 0; i < c; ++i) + { + i_name = CFArrayGetValueAtIndex(mechanisms, i); + if (i_name && (CFGetTypeID(m_name) == CFStringGetTypeID())) { + if (CFStringCompare(i_name, m_name, kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + index = i; + break; + } + } + } + +done: + return index; +} + +static bool _update_rule_mechanism(authdb_connection_t dbconn, const char * rule_name, CFStringRef mechanism_name, CFStringRef insert_after_name, bool remove) +{ + bool updated = false; + rule_t rule = NULL; + rule_t update_rule = NULL; + CFMutableDictionaryRef cfdict = NULL; + CFStringRef update_name = NULL; + + require(mechanism_name, done); + + rule = rule_create_with_string(rule_name, dbconn); + require(rule_get_id(rule) != 0, done); // rule doesn't exist in the database + + cfdict = rule_copy_to_cfobject(rule, dbconn); + require(cfdict != NULL, done); + + CFMutableArrayRef mechanisms = NULL; + bool res = CFDictionaryGetValueIfPresent(cfdict, CFSTR(kAuthorizationRuleParameterMechanisms), (void*)&mechanisms); + require(res == true, done); + + CFIndex index = -1; + + if (remove) { + index = _get_mechanism_index(mechanisms, mechanism_name); + } else { + if (insert_after_name) { + if ((index = _get_mechanism_index(mechanisms, insert_after_name)) != -1) { + index++; + } else { + index = 0; // if we couldn't find the index add it to the begining + } + } else { + index = 0; + } + } + + if (index != -1) { + if(remove) { + CFArrayRemoveValueAtIndex(mechanisms, index); + } else { + if (index < CFArrayGetCount(mechanisms)) { + require_action(CFStringCompare(CFArrayGetValueAtIndex(mechanisms, index), mechanism_name, kCFCompareCaseInsensitive) != kCFCompareEqualTo, done, updated = true); + } + CFArrayInsertValueAtIndex(mechanisms, index, mechanism_name); + } + + CFDictionarySetValue(cfdict, CFSTR(kAuthorizationRuleParameterMechanisms), mechanisms); + + // and write it back + update_name = CFStringCreateWithCString(kCFAllocatorDefault, rule_name, kCFStringEncodingUTF8); + require(update_name, done); + update_rule = rule_create_with_plist(rule_get_type(rule), update_name, cfdict, dbconn); + require(update_rule, done); + + require(rule_sql_commit(update_rule, dbconn, CFAbsoluteTimeGetCurrent(), NULL), done); + } + + updated = true; + +done: + CFReleaseSafe(rule); + CFReleaseSafe(update_rule); + CFReleaseSafe(cfdict); + CFReleaseSafe(update_name); + return updated; +} + +/// IN: AUTH_XPC_BLOB, AUTH_XPC_INT64 +// OUT: +OSStatus +authorization_enable_smartcard(connection_t conn, xpc_object_t message, xpc_object_t reply AUTH_UNUSED) +{ + const CFStringRef SMARTCARD_LINE = CFSTR("builtin:smartcard-sniffer,privileged"); + const CFStringRef BUILTIN_LINE = CFSTR("builtin:policy-banner"); + const char* SYSTEM_LOGIN_CONSOLE = "system.login.console"; + const char* AUTHENTICATE = "authenticate"; + + __block OSStatus status = errAuthorizationSuccess; + bool enable_smartcard = false; + authdb_connection_t dbconn = NULL; + auth_token_t auth = NULL; + auth_rights_t checkRight = NULL; + + process_t proc = connection_get_process(conn); + + status = _process_find_copy_auth_token_from_xpc(proc, message, &auth); + require_noerr(status, done); + + checkRight = auth_rights_create(); + auth_rights_add(checkRight, "config.modify.smartcard"); + status = _server_authorize(conn, auth, kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights, checkRight, NULL, NULL); + require_noerr(status, done); + + enable_smartcard = xpc_dictionary_get_bool(message, AUTH_XPC_DATA); + + dbconn = authdb_connection_acquire(server_get_database()); + + if (!_update_rule_mechanism(dbconn, SYSTEM_LOGIN_CONSOLE, SMARTCARD_LINE, BUILTIN_LINE, enable_smartcard ? false : true)) { + status = errAuthorizationInternal; + LOGE("server[%i]: smartcard: enable(%i) failed to update %s", connection_get_pid(conn), enable_smartcard, SYSTEM_LOGIN_CONSOLE); + } + if (!_update_rule_mechanism(dbconn, AUTHENTICATE, SMARTCARD_LINE, NULL, enable_smartcard ? false : true)) { + status = errAuthorizationInternal; + LOGE("server[%i]: smartcard: enable(%i) failed to update %s", connection_get_pid(conn), enable_smartcard, AUTHENTICATE); + } + + authdb_checkpoint(dbconn); + +done: + authdb_connection_release(&dbconn); + CFReleaseSafe(checkRight); + CFReleaseSafe(auth); + return status; +} + +static int64_t _process_get_identifier_count(process_t proc, authdb_connection_t conn) +{ + __block int64_t result = 0; + + authdb_step(conn, "SELECT COUNT(*) AS cnt FROM rules WHERE identifier = ? ", ^(sqlite3_stmt *stmt) { + sqlite3_bind_text(stmt, 1, process_get_identifier(proc), -1, NULL); + }, ^bool(auth_items_t data) { + result = auth_items_get_int64(data, "cnt"); + return true; + }); + + return result; +} + +static int64_t _get_max_process_rights() +{ + static dispatch_once_t onceToken; + static int64_t max_rights = MAX_PROCESS_RIGHTS; + + //sudo defaults write /Library/Preferences/com.apple.authd max_process_rights -bool true + dispatch_once(&onceToken, ^{ + CFTypeRef max = (CFNumberRef)CFPreferencesCopyValue(CFSTR("max_process_rights"), CFSTR(SECURITY_AUTH_NAME), kCFPreferencesAnyUser, kCFPreferencesCurrentHost); + + if (max && CFGetTypeID(max) == CFNumberGetTypeID()) { + CFNumberGetValue(max, kCFNumberSInt64Type, &max_rights); + } + CFReleaseSafe(max); + }); + + return max_rights; +} + +// IN: AUTH_XPC_BLOB, AUTH_XPC_RIGHT_NAME, AUTH_XPC_DATA +// OUT: +OSStatus +authorization_right_set(connection_t conn, xpc_object_t message, xpc_object_t reply AUTH_UNUSED) +{ + __block OSStatus status = errAuthorizationDenied; + __block engine_t engine = NULL; + CFStringRef cf_rule_name = NULL; + CFDictionaryRef cf_rule_dict = NULL; + rule_t rule = NULL; + rule_t existingRule = NULL; + authdb_connection_t dbconn = NULL; + auth_token_t auth = NULL; + bool force_modify = false; + RuleType rule_type = RT_RIGHT; + const char * rule_name = NULL; + bool auth_rule = false; + + process_t proc = connection_get_process(conn); + + status = _process_find_copy_auth_token_from_xpc(proc, message, &auth); + require_noerr(status, done); + + require_action(xpc_dictionary_get_string(message, AUTH_XPC_RIGHT_NAME) != NULL, done, status = errAuthorizationInternal); + require_action(xpc_dictionary_get_value(message, AUTH_XPC_DATA) != NULL, done, status = errAuthorizationInternal); + + rule_name = xpc_dictionary_get_string(message, AUTH_XPC_RIGHT_NAME); + require(rule_name != NULL, done); + + if (_compare_string(rule_name, "authenticate")) { + rule_type = RT_RULE; + auth_rule = true; + } + + cf_rule_name = CFStringCreateWithCString(kCFAllocatorDefault, rule_name, kCFStringEncodingUTF8); + require(cf_rule_name != NULL, done); + + cf_rule_dict = _CFXPCCreateCFObjectFromXPCObject(xpc_dictionary_get_value(message, AUTH_XPC_DATA)); + require(cf_rule_dict != NULL, done); + + dbconn = authdb_connection_acquire(server_get_database()); + + rule = rule_create_with_plist(rule_type, cf_rule_name, cf_rule_dict, dbconn); + if (process_get_uid(proc) != 0) { + require_action(rule_get_extract_password(rule) == false, done, status = errAuthorizationDenied; LOGE("server[%i]: AuthorizationRightSet not allowed to set extract-password. (denied)", connection_get_pid(conn))); + } + + // if rule doesn't currently exist then we have to check to see if they are over the Max. + if (rule_get_id(rule) == 0) { + if (process_get_identifier(proc) == NULL) { + LOGE("server[%i]: AuthorizationRightSet required for process %s (missing code signature). To add rights to the Authorization database, your process must have a code signature.", connection_get_pid(conn), process_get_code_url(proc)); + force_modify = true; + } else { + int64_t process_rule_count = _process_get_identifier_count(proc, dbconn); + if ((process_rule_count >= _get_max_process_rights())) { + if (!connection_get_syslog_warn(conn)) { + LOGE("server[%i]: AuthorizationRightSet Denied API abuse process %s already contains %lli rights.", connection_get_pid(conn), process_get_code_url(proc), _get_max_process_rights()); + connection_set_syslog_warn(conn); + } + status = errAuthorizationDenied; + goto done; + } + } + } else { + if (auth_rule) { + if (process_get_uid(proc) != 0) { + LOGE("server[%i]: AuthorizationRightSet denied, root required to update the 'authenticate' rule", connection_get_pid(conn)); + status = errAuthorizationDenied; + goto done; + } + } else { + // verify they are updating a right and not a rule + existingRule = rule_create_with_string(rule_get_name(rule), dbconn); + if (rule_get_type(existingRule) == RT_RULE) { + LOGE("server[%i]: AuthorizationRightSet Denied updating '%s' rule is prohibited", connection_get_pid(conn), rule_get_name(existingRule)); + status = errAuthorizationDenied; + goto done; + } + } + } + + if (_prompt_for_modifications(proc,rule)) { + authdb_connection_release(&dbconn); + + dispatch_sync(connection_get_dispatch_queue(conn), ^{ + engine = engine_create(conn, auth); + connection_set_engine(conn, engine); + status = engine_verify_modification(engine, rule, false, force_modify); + connection_set_engine(conn, NULL); + }); + require_noerr(status, done); + + dbconn = authdb_connection_acquire(server_get_database()); + } + + if (rule_sql_commit(rule, dbconn, engine ? engine_get_time(engine) : CFAbsoluteTimeGetCurrent(), proc)) { + LOGV("server[%i]: Successfully updated rule %s", connection_get_pid(conn), rule_get_name(rule)); + authdb_checkpoint(dbconn); + status = errAuthorizationSuccess; + } else { + LOGE("server[%i]: Failed to update rule %s", connection_get_pid(conn), rule_get_name(rule)); + status = errAuthorizationDenied; + } + +done: + authdb_connection_release(&dbconn); + CFReleaseSafe(existingRule); + CFReleaseSafe(cf_rule_name); + CFReleaseSafe(cf_rule_dict); + CFReleaseSafe(auth); + CFReleaseSafe(rule); + CFReleaseSafe(engine); + return status; +} + +// IN: AUTH_XPC_BLOB, AUTH_XPC_RIGHT_NAME +// OUT: +OSStatus +authorization_right_remove(connection_t conn, xpc_object_t message, xpc_object_t reply AUTH_UNUSED) +{ + __block OSStatus status = errAuthorizationDenied; + __block engine_t engine = NULL; + rule_t rule = NULL; + authdb_connection_t dbconn = NULL; + + process_t proc = connection_get_process(conn); + + auth_token_t auth = NULL; + status = _process_find_copy_auth_token_from_xpc(proc, message, &auth); + require_noerr(status, done); + + dbconn = authdb_connection_acquire(server_get_database()); + + rule = rule_create_with_string(xpc_dictionary_get_string(message, AUTH_XPC_RIGHT_NAME), dbconn); + require(rule != NULL, done); + + if (_prompt_for_modifications(proc,rule)) { + authdb_connection_release(&dbconn); + + dispatch_sync(connection_get_dispatch_queue(conn), ^{ + engine = engine_create(conn, auth); + connection_set_engine(conn, engine); + status = engine_verify_modification(engine, rule, true, false); + connection_set_engine(conn, NULL); + }); + require_noerr(status, done); + + dbconn = authdb_connection_acquire(server_get_database()); + } + + if (rule_get_id(rule) != 0) { + rule_sql_remove(rule, dbconn); + } + +done: + authdb_connection_release(&dbconn); + CFReleaseSafe(auth); + CFReleaseSafe(rule); + CFReleaseSafe(engine); + LOGV("server[%i]: AuthorizationRightRemove %i", connection_get_pid(conn), status); + return status; +} + +#pragma mark - +#pragma mark test code + +OSStatus +session_set_user_preferences(connection_t conn, xpc_object_t message, xpc_object_t reply) +{ + (void)conn; + (void)message; + (void)reply; + return errAuthorizationSuccess; +} + +void +server_dev() { +// rule_t rule = rule_create_with_string("system.preferences.accounts"); +// CFDictionaryRef dict = rule_copy_to_cfobject(rule); +// _show_cf(dict); +// CFReleaseSafe(rule); +// CFReleaseSafe(dict); + +// auth_items_t config = NULL; +// double d2 = 0, d1 = 5; +// authdb_get_key_value(server_get_authdb_reader(), "config", &config); +// auth_items_set_double(config, "test", d1); +// d2 = auth_items_get_double(config, "test"); +// LOGV("d1=%f d2=%f", d1, d2); +// CFReleaseSafe(config); + + +// auth_items_t items = auth_items_create(); +// auth_items_set_string(items, "test", "testing 1"); +// auth_items_set_string(items, "test2", "testing 2"); +// auth_items_set_string(items, "test3", "testing 3"); +// auth_items_set_flags(items, "test3", 4); +// auth_items_set_string(items, "apple", "apple"); +// auth_items_set_flags(items, "apple", 1); +// auth_items_set_int(items, "int", 45); +// auth_items_set_flags(items, "int", 2); +// auth_items_set_bool(items, "true", true); +// auth_items_set_bool(items, "false", false); +// auth_items_set(items, "com.apple."); +// auth_show(items); +// LOGD("Yeah it works: %s", auth_items_get_string(items, "test3")); +// LOGD("Yeah it works: %i", auth_items_get_bool(items, "true")); +// LOGD("Yeah it works: %i", auth_items_get_bool(items, "false")); +// LOGD("Yeah it works: %i", auth_items_get_int(items, "int")); +// (void)auth_items_get_bool(items, "test3"); +// AuthorizationItemSet * itemSet = auth_items_get_item_set(items); +// for (uint32_t i = 0; i < itemSet->count; i++) { +// LOGD("item: %s", itemSet->items[i].name); +// } +// +// xpc_object_t xpcdata = SerializeItemSet(auth_items_get_item_set(items)); +// auth_items_t items2 = auth_items_create_with_xpc(xpcdata); +// xpc_release(xpcdata); +// auth_items_remove_with_flags(items2, 7); +//// auth_items_set_string(items2, "test3", "testing 3 very good"); +// auth_items_copy_with_flags(items2, items, 7); +// LOGD("Yeah it works: %s", auth_items_get_string(items2, "test3")); +// auth_show(items2); +// CFReleaseSafe(items2); +// +// CFReleaseSafe(items); +} + diff --git a/Security/authd/server.h b/Security/authd/server.h new file mode 100644 index 00000000..5ccb765d --- /dev/null +++ b/Security/authd/server.h @@ -0,0 +1,80 @@ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ + +#ifndef _SECURITY_AUTH_SERVER_H_ +#define _SECURITY_AUTH_SERVER_H_ + +#include "authd_private.h" +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +OSStatus server_init(void); +void server_cleanup(void); +bool server_in_dark_wake(void); +authdb_t server_get_database(void); + +AUTH_NONNULL_ALL +connection_t server_register_connection(xpc_connection_t); + +AUTH_NONNULL_ALL +void server_unregister_connection(connection_t); + +AUTH_NONNULL_ALL +void server_register_auth_token(auth_token_t); + +AUTH_NONNULL_ALL +void server_unregister_auth_token(auth_token_t); + +AUTH_NONNULL_ALL +auth_token_t server_find_copy_auth_token(AuthorizationBlob * blob); + +AUTH_NONNULL_ALL +session_t server_find_copy_session(session_id_t,bool create); + +void server_dev(void); + +/* API */ + +AUTH_NONNULL_ALL +OSStatus authorization_create(connection_t,xpc_object_t,xpc_object_t); + +AUTH_NONNULL_ALL +OSStatus authorization_create_with_audit_token(connection_t,xpc_object_t,xpc_object_t); + +AUTH_NONNULL_ALL +OSStatus authorization_free(connection_t,xpc_object_t,xpc_object_t); + +AUTH_NONNULL_ALL +OSStatus authorization_copy_rights(connection_t,xpc_object_t,xpc_object_t); + +AUTH_NONNULL_ALL +OSStatus authorization_copy_info(connection_t,xpc_object_t,xpc_object_t); + +AUTH_NONNULL_ALL +OSStatus authorization_make_external_form(connection_t,xpc_object_t,xpc_object_t); + +AUTH_NONNULL_ALL +OSStatus authorization_create_from_external_form(connection_t,xpc_object_t,xpc_object_t); + +AUTH_NONNULL_ALL +OSStatus authorization_right_get(connection_t,xpc_object_t,xpc_object_t); + +AUTH_NONNULL_ALL +OSStatus authorization_right_set(connection_t,xpc_object_t,xpc_object_t); + +AUTH_NONNULL_ALL +OSStatus authorization_enable_smartcard(connection_t,xpc_object_t,xpc_object_t); + +AUTH_NONNULL_ALL +OSStatus authorization_right_remove(connection_t,xpc_object_t,xpc_object_t); + +AUTH_NONNULL_ALL +OSStatus session_set_user_preferences(connection_t,xpc_object_t,xpc_object_t); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_AUTH_SERVER_H_ */ diff --git a/authd/session.c b/Security/authd/session.c similarity index 98% rename from authd/session.c rename to Security/authd/session.c index 2484ddf3..3e0d76f6 100644 --- a/authd/session.c +++ b/Security/authd/session.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012 Apple Inc. All Rights Reserved. */ #include "session.h" #include "process.h" diff --git a/Security/authd/session.h b/Security/authd/session.h new file mode 100644 index 00000000..4091adc8 --- /dev/null +++ b/Security/authd/session.h @@ -0,0 +1,60 @@ +/* Copyright (c) 2012 Apple Inc. All Rights Reserved. */ + +#ifndef _SECURITY_AUTH_SESSION_H_ +#define _SECURITY_AUTH_SESSION_H_ + +#include "credential.h" +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED +session_t session_create(session_id_t); + +AUTH_NONNULL_ALL +bool session_update(session_t); + +AUTH_NONNULL_ALL +uint64_t session_get_attributes(session_t); + +AUTH_NONNULL_ALL +void session_set_attributes(session_t,uint64_t flags); + +AUTH_NONNULL_ALL +void session_clear_attributes(session_t,uint64_t flags); + +AUTH_NONNULL_ALL +const void * session_get_key(session_t); + +AUTH_NONNULL_ALL +session_id_t session_get_id(session_t); + +AUTH_NONNULL_ALL +uid_t session_get_uid(session_t); + +AUTH_NONNULL_ALL +CFIndex session_add_process(session_t, process_t); + +AUTH_NONNULL_ALL +CFIndex session_remove_process(session_t, process_t); + +AUTH_NONNULL_ALL +CFIndex session_get_process_count(session_t); + +AUTH_NONNULL_ALL +void session_set_credential(session_t,credential_t); + +AUTH_NONNULL_ALL +void session_credentials_purge(session_t); + +AUTH_NONNULL_ALL +bool session_credentials_iterate(session_t, credential_iterator_t iter); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_AUTH_SESSION_H_ */ diff --git a/cloud_keychain_diagnose/cloud_keychain_diagnose-Prefix.pch b/Security/cloud_keychain_diagnose/cloud_keychain_diagnose-Prefix.pch similarity index 100% rename from cloud_keychain_diagnose/cloud_keychain_diagnose-Prefix.pch rename to Security/cloud_keychain_diagnose/cloud_keychain_diagnose-Prefix.pch diff --git a/codesign_tests/FatDynamicValidation.c b/Security/codesign_tests/FatDynamicValidation.c similarity index 94% rename from codesign_tests/FatDynamicValidation.c rename to Security/codesign_tests/FatDynamicValidation.c index a8bfeae9..a5e30c24 100644 --- a/codesign_tests/FatDynamicValidation.c +++ b/Security/codesign_tests/FatDynamicValidation.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/codesign_tests/validation.sh b/Security/codesign_tests/validation.sh similarity index 100% rename from codesign_tests/validation.sh rename to Security/codesign_tests/validation.sh diff --git a/Security/config/base.xcconfig b/Security/config/base.xcconfig new file mode 100644 index 00000000..9bb6e941 --- /dev/null +++ b/Security/config/base.xcconfig @@ -0,0 +1,14 @@ +ARCHS = $(ARCHS_STANDARD_32_64_BIT) +CODE_SIGN_IDENTITY = -; +GCC_VERSION = com.apple.compilers.llvm.clang.1_0 +DEBUG_INFORMATION_FORMAT = dwarf-with-dsym +CURRENT_PROJECT_VERSION = $(RC_ProjectSourceVersion) +VERSIONING_SYSTEM = apple-generic; + +DEAD_CODE_STRIPPING = YES + +// Debug symbols should be on obviously +GCC_GENERATE_DEBUGGING_SYMBOLS = YES +COPY_PHASE_STRIP = NO +STRIP_STYLE = debugging +STRIP_INSTALLED_PRODUCT = NO diff --git a/config/command.xcconfig b/Security/config/command.xcconfig similarity index 89% rename from config/command.xcconfig rename to Security/config/command.xcconfig index 9e80246d..878dc00c 100644 --- a/config/command.xcconfig +++ b/Security/config/command.xcconfig @@ -10,4 +10,4 @@ HEADER_SEARCH_PATHS = $(PROJECT_DIR) $(PROJECT_DIR)/security2 $(PROJECT_DIR)/sec STRIP_STYLE = all STRIP_INSTALLED_PRODUCT = YES -DEPLOYMENT_POSTPROCESSING = YES +DEPLOYMENT_POSTPROCESSING = NO diff --git a/config/debug.xcconfig b/Security/config/debug.xcconfig similarity index 100% rename from config/debug.xcconfig rename to Security/config/debug.xcconfig diff --git a/config/executable.xcconfig b/Security/config/executable.xcconfig similarity index 76% rename from config/executable.xcconfig rename to Security/config/executable.xcconfig index e6f1e683..ad9091e9 100644 --- a/config/executable.xcconfig +++ b/Security/config/executable.xcconfig @@ -4,4 +4,4 @@ PRODUCT_NAME = $(TARGET_NAME) STRIP_STYLE = all STRIP_INSTALLED_PRODUCT = YES -DEPLOYMENT_POSTPROCESSING = YES +DEPLOYMENT_POSTPROCESSING = NO diff --git a/config/lib.xcconfig b/Security/config/lib.xcconfig similarity index 100% rename from config/lib.xcconfig rename to Security/config/lib.xcconfig diff --git a/config/release.xcconfig b/Security/config/release.xcconfig similarity index 100% rename from config/release.xcconfig rename to Security/config/release.xcconfig diff --git a/config/security.xcconfig b/Security/config/security.xcconfig similarity index 95% rename from config/security.xcconfig rename to Security/config/security.xcconfig index bf031881..57e604fc 100644 --- a/config/security.xcconfig +++ b/Security/config/security.xcconfig @@ -16,7 +16,7 @@ HEADER_SEARCH_PATHS = $(PROJECT_DIR)/include $(PROJECT_DIR)/sec/SOSCircle $(PROJ //INSTALLHDRS_SCRIPT_PHASE = YES STRIP_INSTALLED_PRODUCT = YES -DEPLOYMENT_POSTPROCESSING = YES +DEPLOYMENT_POSTPROCESSING = NO GCC_C_LANGUAGE_STANDARD = gnu99 diff --git a/config/test.xcconfig b/Security/config/test.xcconfig similarity index 100% rename from config/test.xcconfig rename to Security/config/test.xcconfig diff --git a/doc/ACLsInCDSA.cwk b/Security/doc/ACLsInCDSA.cwk similarity index 100% rename from doc/ACLsInCDSA.cwk rename to Security/doc/ACLsInCDSA.cwk diff --git a/doc/APIStrategy.cwk b/Security/doc/APIStrategy.cwk similarity index 100% rename from doc/APIStrategy.cwk rename to Security/doc/APIStrategy.cwk diff --git a/doc/AccessControlArchitecture.cwk b/Security/doc/AccessControlArchitecture.cwk similarity index 100% rename from doc/AccessControlArchitecture.cwk rename to Security/doc/AccessControlArchitecture.cwk diff --git a/doc/AppleCL_Spec.doc b/Security/doc/AppleCL_Spec.doc similarity index 100% rename from doc/AppleCL_Spec.doc rename to Security/doc/AppleCL_Spec.doc diff --git a/doc/AppleCSP.doc b/Security/doc/AppleCSP.doc similarity index 100% rename from doc/AppleCSP.doc rename to Security/doc/AppleCSP.doc diff --git a/doc/AppleTP_Spec.doc b/Security/doc/AppleTP_Spec.doc similarity index 100% rename from doc/AppleTP_Spec.doc rename to Security/doc/AppleTP_Spec.doc diff --git a/doc/Apple_OID_Assignments.rtf b/Security/doc/Apple_OID_Assignments.rtf similarity index 100% rename from doc/Apple_OID_Assignments.rtf rename to Security/doc/Apple_OID_Assignments.rtf diff --git a/doc/ArchitectureOverview.cwk b/Security/doc/ArchitectureOverview.cwk similarity index 100% rename from doc/ArchitectureOverview.cwk rename to Security/doc/ArchitectureOverview.cwk diff --git a/Security/doc/C++Utilities.cwk b/Security/doc/C++Utilities.cwk new file mode 100644 index 00000000..7018a6d7 --- /dev/null +++ b/Security/doc/C++Utilities.cwk @@ -0,0 +1,1019 @@ +/* + * Copyright (c) 2014 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +à + + +È +Ÿ +¬ + + + + +’ +Ÿ +¬ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Ô + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ÿÿ + + + + + + + + + + + + + + + + +, +, + + +& +' +( +) + + + + +- ++ ++ +* +* +* +r¹*X + + + + + + + + + + + + + + + + + + + + + + + + +¿ + + + + +) +1 +: + +ÿ +ÿ + Ö + + + + + ¿ +à +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 + + +d&ÿ + + +Default SS +Bullet +Definition +3D Table 1 +3D Table 2 +Accounting +Default TB + +w½ÿÿ{Þÿ{Þÿÿw½ÿw½ýÿ +ZÖsœF1NsR”NsR”VµkZNso{þVµþR”6ckZNsF1ZÖkZVµBVµF1Vµo{VµR”R”JR{ÞNsVµR”NsR”VµVµZÖJRsœNsR”NsR”o{ZÖNsR”F1ccVµkZZÖF1R”kZVµF1NsÿR”VµR”ZÖJRVµZÖæÿ +{Þw½sœw½sœkZsœ{Þw½cZÖüsœkZÿw½kZýsœ(o{{Þw½o{ÿsœsœo{w½o{ckZw½sœw½g9w½g9o{sœÿ{Þw½sœw½{Þsœsœÿsœsœ{Þw½ÿo{w½ÿw½o{sœsœæÿ +sœkZÿw½{Þsœsœ{Þw½w½{Þýw½{Þw½{ÞkZýw½ +kZÿw½ÿÿw½o{g9o{w½{Þûÿsœw½þÿ + + + + com.apple.print.PrintSettings.PMColorMode + + com.apple.print.ticket.creator + com.apple.printingmanager + com.apple.print.ticket.itemArray + + + com.apple.print.PrintSettings.PMColorMode + 3 + com.apple.print.ticket.client + com.apple.printingmanager + com.apple.print.ticket.modDate + 2003-06-17T17:46:54Z + com.apple.print.ticket.stateFlag + 0 + + + + com.apple.print.PrintSettings.PMCopies + + com.apple.print.ticket.creator + com.apple.printingmanager + com.apple.print.ticket.itemArray + + + com.apple.print.PrintSettings.PMCopies + 1 + com.apple.print.ticket.client + com.apple.printingmanager + com.apple.print.ticket.modDate + 2003-06-17T17:46:54Z + com.apple.print.ticket.stateFlag + 0 + + + + com.apple.print.PrintSettings.PMDestinationType + + com.apple.print.ticket.creator + com.apple.printingmanager + com.apple.print.ticket.itemArray + + + com.apple.print.PrintSettings.PMDestinationType + 1 + com.apple.print.ticket.client + com.apple.printingmanager + com.apple.print.ticket.modDate + 2003-06-17T17:46:54Z + com.apple.print.ticket.stateFlag + 0 + + + + com.apple.print.PrintSettings.PMFirstPage + + com.apple.print.ticket.creator + com.apple.printingmanager + com.apple.print.ticket.itemArray + + + com.apple.print.PrintSettings.PMFirstPage + 1 + com.apple.print.ticket.client + com.apple.printingmanager + com.apple.print.ticket.modDate + 2003-06-17T17:46:54Z + com.apple.print.ticket.stateFlag + 0 + + + + com.apple.print.PrintSettings.PMLastPage + + com.apple.print.ticket.creator + com.apple.printingmanager + com.apple.print.ticket.itemArray + + + com.apple.print.PrintSettings.PMLastPage + 9999 + com.apple.print.ticket.client + com.apple.printingmanager + com.apple.print.ticket.modDate + 2003-06-17T17:46:54Z + com.apple.print.ticket.stateFlag + 0 + + + + com.apple.print.PrintSettings.PMPageRange + + com.apple.print.ticket.creator + com.apple.printingmanager + com.apple.print.ticket.itemArray + + + com.apple.print.PrintSettings.PMPageRange + + 1 + 32000 + + com.apple.print.ticket.client + com.apple.printingmanager + com.apple.print.ticket.modDate + 2003-06-17T17:46:54Z + com.apple.print.ticket.stateFlag + 0 + + + + com.apple.print.ticket.APIVersion + 00.20 + com.apple.print.ticket.privateLock + + com.apple.print.ticket.type + com.apple.print.PrintSettingsTicket + + + + + + + com.apple.print.PageFormat.PMHorizontalRes + + com.apple.print.ticket.creator + com.apple.printingmanager + com.apple.print.ticket.itemArray + + + com.apple.print.PageFormat.PMHorizontalRes + 72 + com.apple.print.ticket.client + com.apple.printingmanager + com.apple.print.ticket.modDate + 2003-06-17T17:46:54Z + com.apple.print.ticket.stateFlag + 0 + + + + com.apple.print.PageFormat.PMOrientation + + com.apple.print.ticket.creator + com.apple.printingmanager + com.apple.print.ticket.itemArray + + + com.apple.print.PageFormat.PMOrientation + 1 + com.apple.print.ticket.client + com.apple.printingmanager + com.apple.print.ticket.modDate + 2003-06-17T17:46:54Z + com.apple.print.ticket.stateFlag + 0 + + + + com.apple.print.PageFormat.PMScaling + + com.apple.print.ticket.creator + com.apple.printingmanager + com.apple.print.ticket.itemArray + + + com.apple.print.PageFormat.PMScaling + 1 + com.apple.print.ticket.client + com.apple.printingmanager + com.apple.print.ticket.modDate + 2003-06-17T17:46:54Z + com.apple.print.ticket.stateFlag + 0 + + + + com.apple.print.PageFormat.PMVerticalRes + + com.apple.print.ticket.creator + com.apple.printingmanager + com.apple.print.ticket.itemArray + + + com.apple.print.PageFormat.PMVerticalRes + 72 + com.apple.print.ticket.client + com.apple.printingmanager + com.apple.print.ticket.modDate + 2003-06-17T17:46:54Z + com.apple.print.ticket.stateFlag + 0 + + + + com.apple.print.PageFormat.PMVerticalScaling + + com.apple.print.ticket.creator + com.apple.printingmanager + com.apple.print.ticket.itemArray + + + com.apple.print.PageFormat.PMVerticalScaling + 1 + com.apple.print.ticket.client + com.apple.printingmanager + com.apple.print.ticket.modDate + 2003-06-17T17:46:54Z + com.apple.print.ticket.stateFlag + 0 + + + + com.apple.print.subTicket.paper_info_ticket + + com.apple.print.PageFormat.PMAdjustedPageRect + + com.apple.print.ticket.creator + com.apple.printingmanager + com.apple.print.ticket.itemArray + + + com.apple.print.PageFormat.PMAdjustedPageRect + + 0.0 + 0.0 + 767.8798828125 + 587.51995849609375 + + com.apple.print.ticket.client + com.apple.printingmanager + com.apple.print.ticket.modDate + 2003-06-17T17:46:54Z + com.apple.print.ticket.stateFlag + 0 + + + + com.apple.print.PageFormat.PMAdjustedPaperRect + + com.apple.print.ticket.creator + com.apple.printingmanager + com.apple.print.ticket.itemArray + + + com.apple.print.PageFormat.PMAdjustedPaperRect + + -9.96002197265625 + -11.520000457763672 + 782.03997802734375 + 600.47998046875 + + com.apple.print.ticket.client + com.apple.printingmanager + com.apple.print.ticket.modDate + 2003-06-17T17:46:54Z + com.apple.print.ticket.stateFlag + 0 + + + + com.apple.print.PaperInfo.PMPaperName + + com.apple.print.ticket.creator + CUPS_CPL + com.apple.print.ticket.itemArray + + + com.apple.print.PaperInfo.PMPaperName + na-letter + com.apple.print.ticket.client + CUPS_CPL + com.apple.print.ticket.modDate + 2003-06-17T17:46:54Z + com.apple.print.ticket.stateFlag + 1 + + + + com.apple.print.PaperInfo.PMUnadjustedPageRect + + com.apple.print.ticket.creator + CUPS_CPL + com.apple.print.ticket.itemArray + + + com.apple.print.PaperInfo.PMUnadjustedPageRect + + 0.0 + 0.0 + 767.8798828125 + 587.51995849609375 + + com.apple.print.ticket.client + CUPS_CPL + com.apple.print.ticket.modDate + 2003-06-17T17:46:54Z + com.apple.print.ticket.stateFlag + 1 + + + + com.apple.print.PaperInfo.PMUnadjustedPaperRect + + com.apple.print.ticket.creator + CUPS_CPL + com.apple.print.ticket.itemArray + + + com.apple.print.PaperInfo.PMUnadjustedPaperRect + + -9.96002197265625 + -11.520000457763672 + 782.03997802734375 + 600.47998046875 + + com.apple.print.ticket.client + CUPS_CPL + com.apple.print.ticket.modDate + 2003-06-17T17:46:54Z + com.apple.print.ticket.stateFlag + 1 + + + + com.apple.print.PaperInfo.ppd.PMPaperName + + com.apple.print.ticket.creator + CUPS_CPL + com.apple.print.ticket.itemArray + + + com.apple.print.PaperInfo.ppd.PMPaperName + Letter + com.apple.print.ticket.client + CUPS_CPL + com.apple.print.ticket.modDate + 2003-06-17T17:46:54Z + com.apple.print.ticket.stateFlag + 1 + + + + com.apple.print.ticket.APIVersion + 00.20 + com.apple.print.ticket.privateLock + + com.apple.print.ticket.type + com.apple.print.PaperInfoTicket + + com.apple.print.ticket.APIVersion + 00.20 + com.apple.print.ticket.privateLock + + com.apple.print.ticket.type + com.apple.print.PageFormatTicket + + +ETBL diff --git a/doc/DebuggingAids.cwk b/Security/doc/DebuggingAids.cwk similarity index 100% rename from doc/DebuggingAids.cwk rename to Security/doc/DebuggingAids.cwk diff --git a/doc/HowToWriteA_CSP.cwk b/Security/doc/HowToWriteA_CSP.cwk similarity index 100% rename from doc/HowToWriteA_CSP.cwk rename to Security/doc/HowToWriteA_CSP.cwk diff --git a/doc/HowToWriteA_Plugin.cwk b/Security/doc/HowToWriteA_Plugin.cwk similarity index 100% rename from doc/HowToWriteA_Plugin.cwk rename to Security/doc/HowToWriteA_Plugin.cwk diff --git a/doc/SecuritySupport.doc b/Security/doc/SecuritySupport.doc similarity index 100% rename from doc/SecuritySupport.doc rename to Security/doc/SecuritySupport.doc diff --git a/doc/Supported_CSP_Algorithms.doc b/Security/doc/Supported_CSP_Algorithms.doc similarity index 100% rename from doc/Supported_CSP_Algorithms.doc rename to Security/doc/Supported_CSP_Algorithms.doc diff --git a/doc/cwk_styles b/Security/doc/cwk_styles similarity index 100% rename from doc/cwk_styles rename to Security/doc/cwk_styles diff --git a/include/security_asn1 b/Security/include/security_asn1 similarity index 100% rename from include/security_asn1 rename to Security/include/security_asn1 diff --git a/include/security_cdsa_client b/Security/include/security_cdsa_client similarity index 100% rename from include/security_cdsa_client rename to Security/include/security_cdsa_client diff --git a/include/security_cdsa_plugin b/Security/include/security_cdsa_plugin similarity index 100% rename from include/security_cdsa_plugin rename to Security/include/security_cdsa_plugin diff --git a/include/security_cdsa_utilities b/Security/include/security_cdsa_utilities similarity index 100% rename from include/security_cdsa_utilities rename to Security/include/security_cdsa_utilities diff --git a/include/security_cdsa_utils b/Security/include/security_cdsa_utils similarity index 100% rename from include/security_cdsa_utils rename to Security/include/security_cdsa_utils diff --git a/include/security_codesigning b/Security/include/security_codesigning similarity index 100% rename from include/security_codesigning rename to Security/include/security_codesigning diff --git a/include/security_comcryption b/Security/include/security_comcryption similarity index 100% rename from include/security_comcryption rename to Security/include/security_comcryption diff --git a/include/security_cryptkit b/Security/include/security_cryptkit similarity index 100% rename from include/security_cryptkit rename to Security/include/security_cryptkit diff --git a/include/security_filedb b/Security/include/security_filedb similarity index 100% rename from include/security_filedb rename to Security/include/security_filedb diff --git a/include/security_keychain b/Security/include/security_keychain similarity index 100% rename from include/security_keychain rename to Security/include/security_keychain diff --git a/include/security_ocspd b/Security/include/security_ocspd similarity index 100% rename from include/security_ocspd rename to Security/include/security_ocspd diff --git a/include/security_pkcs12 b/Security/include/security_pkcs12 similarity index 100% rename from include/security_pkcs12 rename to Security/include/security_pkcs12 diff --git a/include/security_smime b/Security/include/security_smime similarity index 100% rename from include/security_smime rename to Security/include/security_smime diff --git a/include/security_utilities b/Security/include/security_utilities similarity index 100% rename from include/security_utilities rename to Security/include/security_utilities diff --git a/include/securityd_client b/Security/include/securityd_client similarity index 100% rename from include/securityd_client rename to Security/include/securityd_client diff --git a/lib/FDEPrefs.plist b/Security/lib/FDEPrefs.plist similarity index 100% rename from lib/FDEPrefs.plist rename to Security/lib/FDEPrefs.plist diff --git a/lib/Info-Security.plist b/Security/lib/Info-Security.plist similarity index 93% rename from lib/Info-Security.plist rename to Security/lib/Info-Security.plist index 4be65305..dfb79010 100644 --- a/lib/Info-Security.plist +++ b/Security/lib/Info-Security.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 55471.14.18 + ${CURRENT_PROJECT_VERSION} diff --git a/lib/Security.order b/Security/lib/Security.order similarity index 100% rename from lib/Security.order rename to Security/lib/Security.order diff --git a/lib/TimeStampingPrefs.plist b/Security/lib/TimeStampingPrefs.plist similarity index 100% rename from lib/TimeStampingPrefs.plist rename to Security/lib/TimeStampingPrefs.plist diff --git a/lib/copy_pieces.mk b/Security/lib/copy_pieces.mk similarity index 96% rename from lib/copy_pieces.mk rename to Security/lib/copy_pieces.mk index be5f3983..47f9ad09 100644 --- a/lib/copy_pieces.mk +++ b/Security/lib/copy_pieces.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. +# Copyright (c) 2003-2004,2014 Apple Inc. All Rights Reserved. # # @APPLE_LICENSE_HEADER_START@ # diff --git a/lib/dummy.cpp b/Security/lib/dummy.cpp similarity index 100% rename from lib/dummy.cpp rename to Security/lib/dummy.cpp diff --git a/lib/en.lproj/FDELocalizable.strings b/Security/lib/en.lproj/FDELocalizable.strings similarity index 100% rename from lib/en.lproj/FDELocalizable.strings rename to Security/lib/en.lproj/FDELocalizable.strings diff --git a/lib/en.lproj/InfoPlist.strings b/Security/lib/en.lproj/InfoPlist.strings similarity index 100% rename from lib/en.lproj/InfoPlist.strings rename to Security/lib/en.lproj/InfoPlist.strings diff --git a/lib/en.lproj/authorization.buttons.strings b/Security/lib/en.lproj/authorization.buttons.strings similarity index 96% rename from lib/en.lproj/authorization.buttons.strings rename to Security/lib/en.lproj/authorization.buttons.strings index f2a53e69..b20d42ac 100644 --- a/lib/en.lproj/authorization.buttons.strings +++ b/Security/lib/en.lproj/authorization.buttons.strings @@ -129,3 +129,7 @@ "com.apple.ReportPanic.fixRight" = "Move to Trash"; "com.apple.iBooksX.ParentalControl" = "Unlock"; + +"system.services.networkextension.vpn" = "Modify Configuration"; + +"system.services.networkextension.filtering" = "Modify Configuration"; diff --git a/lib/en.lproj/authorization.prompts.strings b/Security/lib/en.lproj/authorization.prompts.strings similarity index 95% rename from lib/en.lproj/authorization.prompts.strings rename to Security/lib/en.lproj/authorization.prompts.strings index 9ef4fe71..f7b112c4 100644 --- a/lib/en.lproj/authorization.prompts.strings +++ b/Security/lib/en.lproj/authorization.prompts.strings @@ -100,7 +100,7 @@ "system.preferences" = "__APPNAME__ is trying to modify your system settings."; -"com.apple.SoftwareUpdate.modify-settings" = "__APPNAME__ is trying to unlock the Software Update preferences."; +"com.apple.SoftwareUpdate.modify-settings" = "__APPNAME__ is trying to unlock the App Store preferences."; "com.apple.uninstalld.uninstall" = "__APPNAME__ is trying to delete an application."; @@ -116,7 +116,7 @@ "com.apple.server.admin.streaming" = "__APPNAME__ is trying to modify the QuickTime Streaming Server settings."; -"system.preferences.softwareupdate" = "__APPNAME__ is trying to unlock the Software Update preferences."; +"system.preferences.softwareupdate" = "__APPNAME__ is trying to unlock the App Store preferences."; "system.keychain.modify" = "__APPNAME__ is trying to modify the system keychain."; @@ -137,3 +137,7 @@ "com.apple.AOSNotification.FindMyMac.remove" = "__APPNAME__ is trying to turn off Find My Mac."; "com.apple.iBooksX.ParentalControl" = "__APPNAME__ is trying to unlock your Parental Controls preferences."; + +"system.services.networkextension.vpn" = "__APPNAME__ is trying to modify the VPN configuration."; + +"system.services.networkextension.filtering" = "__APPNAME__ is trying to modify the content filtering configuration."; diff --git a/lib/framework.sb b/Security/lib/framework.sb similarity index 100% rename from lib/framework.sb rename to Security/lib/framework.sb diff --git a/Security/lib/generateErrStrings.pl b/Security/lib/generateErrStrings.pl new file mode 100644 index 00000000..56b85709 --- /dev/null +++ b/Security/lib/generateErrStrings.pl @@ -0,0 +1,343 @@ +#!/usr/bin/perl +# +# Copyright (c) 2003-2004,2006,2008,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@ +# +# generateErrStrings.pl - create error strings files from the Security header files +# +# Usage: +# +# perl generateErrStrings.pl +# +# Currently supported files are SecBase.h, SecureTransport.h,cssmapple.h, +# cssmerr.h and Authorization.h. These are used by: +# +# void cssmPerror(const char *how, CSSM_RETURN error); +# +# which is in SecBase.cpp. +# +# Paths of input files: +# +# ./libsecurity_authorization/lib/Authorization.h +# ./libsecurity_cssm/lib/cssmapple.h +# ./libsecurity_cssm/lib/cssmerr.h +# ./libsecurity_keychain/lib/SecBase.h +# ./libsecurity_ssl/lib/SecureTransport.h +# +# Sample run: +# +# perl generateErrStrings.pl "YES" "SecErrorMessages.strings" Authorization.h SecBase.h \ +# cssmapple.h cssmerr.h SecureTransport.h +# +# Input to script: header file(s) containing enum declarations +# Output: C++ program with one cout statement per decl +# +# The input headers are scanned for enums containing error numbers and +# optional comments. Only certain prefixes for the identifiers in the +# enums are considered, to avoid non-error message type defines. See +# the line in the file with CSSM_ERRCODE for acceptable prefixes. +# +# There are three styles of comments that this script parses: +# +# Style A [see /System/Library/Frameworks/Security.framework/Headers/SecBase.h]: +# +# errSSLProtocol = -9800, /* SSL protocol error */ +# +# Style B [see /System/Library/Frameworks/Security.framework/Headers/cssmapple.h]: +# +# /* a code signature match failed */ +# CSSMERR_CSP_APPLE_SIGNATURE_MISMATCH = CSSM_CSP_PRIVATE_ERROR + 2, +# +# Style C [see /System/Library/Frameworks/Security.framework/Headers/cssmerr.h]: +# +# CSSM_CSSM_BASE_CSSM_ERROR = +# CSSM_CSSM_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT + 0x10, +# CSSMERR_CSSM_SCOPE_NOT_SUPPORTED = CSSM_CSSM_BASE_CSSM_ERROR + 1, +# +# Style A has the comment after the comment. Style has the comment before the value, +# and Style C has no comment. In cases where both Style A and B apply, the +# comment at the end of the line is used. +# +# The final output after the generated Objective-C++ program is run looks like: +# +# /* errSSLProtocol */ +# "-9800" = "SSL protocol error"; +# +# /* errSSLNegotiation */ +# "-9801" = "Cipher Suite negotiation failure"; +# +# The appropriate byte order marker for UTF-16 is written to the start of the file. +# Note that the list of errors must be numerically unique across all input files, +# or the strings file will be invalid. Comments in "Style B" may span multiple lines. +# C++ style comments are not supported. Double quotes in a comment are hardened with +# "\" in the output. +# +# The English versions of the error messages can be seen with: +# +# cat /System/Library/Frameworks/Security.framework/Resources/English.lproj/SecErrorMessages.strings +# +# find -H -X -x . -name "*.h" -print0 2>/dev/null | xargs -0 grep -ri err +# ----------------------------------------------------------------------------------- + +# Style questions: +# - what should I make PROGNAME? +# - should I use a special call to make the temp file in the .mm file? +# + +#use strict; +#use warnings; + +die "Usage: $0 <.strings file> \n" if ($#ARGV < 3); + +$GENDEBUGSTRINGS=$ARGV[0]; # If "YES", include all strings & don't localize +$TMPDIR=$ARGV[1]; # temporary directory for program compile, link, run +$TARGETSTR=$ARGV[2]; # path of .strings file, e.g. + # ${DERIVED_SRC}/English.lproj/SecErrorMessages.strings +@INPUTFILES=@ARGV[3 .. 9999]; # list of input files + +$#INPUTFILES = $#ARGV - 3; # truncate to actual number of files + +print "gend: $GENDEBUGSTRINGS, tmpdir: $TMPDIR, targetstr: $TARGETSTR\n"; +$PROGNAME="${TMPDIR}/generateErrStrings.mm"; +open PROGRAM,"> $PROGNAME" or die "can't open $PROGNAME: $!"; +select PROGRAM; + +printAdditionalIncludes(); +printInputIncludes(); +printMainProgram(); + +# ----------------------------------------------------------------------------------- +# Parse error headers and build array of all relevant lines +open(ERR, "cat " . join(" ", @INPUTFILES) . "|") or die "Cannot open error header files"; +$/="\};"; #We set the section termination string - very important +processInput(); +close(ERR); +# ----------------------------------------------------------------------------------- + +printTrailer(); +select STDOUT; +close PROGRAM; + +compileLinkAndRun(); + +# 4: Done! +exit; + +# ----------------------------------------------------------------------------------- +# Subroutines +# ----------------------------------------------------------------------------------- + +sub processInput +{ + # 3: Read input, process each line, output it. + while ( $line = ) + { + ($enum) = ($line =~ /\n\s*enum\s*{\s*([^}]*)};/); + while ($enum ne '') #basic filter for badly formed enums + { + #Drop leading whitespace + $enum =~ s/^\s+//; + # print "A:", $enum,"\n"; + ($leadingcomment) = ($enum =~ m%^(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|(//.*)%); + if ($leadingcomment ne '') + { + $enum = substr($enum, length($leadingcomment)); + $leadingcomment = substr($leadingcomment, 2); # drop leading "/*" + $leadingcomment = substr($leadingcomment, 0, -2); # drop trailing "*/" + $leadingcomment = cleanupComment($leadingcomment); + } + next if ($enum eq ''); #basic filter for badly formed enums + + # Check for C++ style comments at start of line + if ($enum =~ /\s*(\/\/)/) + { + #Drop everything before the end of line + $enum =~ s/[^\n]*[\n]*//; + next; + } + ($identifier) = ($enum =~ /\s*([_A-Za-z][_A-Za-z0-9]*)/); + +# print "identifier: ", $identifier,"\n" if ($identifier ne ''); + + #Drop everything before the comma + $enum =~ s/[^,]*,//; + + # Now look for trailing comment. We only consider them + # trailing if they come before the end of the line + ($trailingcomment) = ($enum =~ /^[ \t]*\/\*((.)*)?\*\//); + # ($trailingcomment) = ($enum =~ m%^(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|(//.*)%); + $trailingcomment = cleanupComment($trailingcomment); + + #Drop everything before the end of line + $enum =~ s/[^\n]*[\n]*//; + # print "B:", $enum,"\n"; + # print "lc:$leadingcomment, id:$identifier, tc:$trailingcomment\n"; + # print "===========================================\n"; + + writecomment($leadingcomment, $identifier, $trailingcomment); + } + } +} + +sub writecomment +{ + # Leading comment, id, trailing comment + # To aid localizers, we will not output a line with no comment + # + # Output is e.g. + # tmp << "/* errAuthorizationSuccess */\n\"" << errAuthorizationSuccess + # << "\" = \"The operation completed successfully.\"\n" << endl; + + my($mylc,$myid,$mytc) = @_; + if ($myid =~ /(CSSM_ERRCODE|CSSMERR_|errSec|errCS|errAuth|errSSL)[_A-Za-z][_A-Za-z0-9]*/) + { + $errormessage = ''; + if ($mytc ne '') + { $errormessage = $mytc; } + elsif ($mylc ne '') + { $errormessage = $mylc; } + elsif ($GENDEBUGSTRINGS eq "YES") + { $errormessage = $myid; } + + if ($errormessage ne '') + { + print "\ttmp << \"/* ", $myid, " */\\n\\\"\" << "; + print $myid, " << \"\\\" = \\\""; + print $errormessage, "\\\";\\n\" << endl;\n"; + } + } +}; + + +sub printAdditionalIncludes +{ + #This uses the "here" construct to dump out lines verbatim + print <<"AdditionalIncludes"; + +#include +#include +#include +#include + +using namespace std; +AdditionalIncludes +} + +sub printInputIncludes +{ + #Now "#include" each of the input files + print "\n#include \"$_\"" foreach @INPUTFILES; + print "\n"; +} + +sub printMainProgram +{ + #Output the main part of the program using the "here" construct + print <<"MAINPROGRAM"; + +void writeStrings(const char *stringsFileName); +void createStringsTemp(); + +int main (int argc, char * const argv[]) +{ + const char *stringsFileName = NULL; + + if (argc == 2) + stringsFileName = argv[1]; + else + if (argc == 1) + stringsFileName = "SecErrorMessages.strings"; + else + return -1; + + cout << "Strings file to create: " << stringsFileName << endl; + createStringsTemp(); + writeStrings(stringsFileName); +} + +void writeStrings(const char *stringsFileName) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:@"generateErrStrings.tmp"]; + NSData *rawstrings = [fh readDataToEndOfFile]; + UInt32 encoding = CFStringConvertEncodingToNSStringEncoding (kCFStringEncodingUTF8); + NSString *instring = [[NSString alloc] initWithData:rawstrings encoding:(NSStringEncoding)encoding]; + + if (instring) + { + NSString *path = [NSString stringWithUTF8String:stringsFileName]; + NSFileManager *fm = [NSFileManager defaultManager]; + if ([fm fileExistsAtPath:path]) + [fm removeFileAtPath:path handler:nil]; + BOOL bx = [fm createFileAtPath:path contents:nil attributes:nil]; + NSFileHandle *fs = [NSFileHandle fileHandleForWritingAtPath:path]; + [fs writeData:[instring dataUsingEncoding:NSUnicodeStringEncoding]]; + } + + [pool release]; +} + +void createStringsTemp() +{ + ofstream tmp("generateErrStrings.tmp") ; + +MAINPROGRAM +} + +sub cleanupComment +{ + my $comment = shift @_; +# print "A:",$comment,"\n"; + if ($comment ne '') + { + $comment =~ s/\s\s+/ /g; # Squeeze multiple spaces to one + $comment =~ s/^\s+//; # Drop leading whitespace + $comment =~ s/\s+$//; # Drop trailing whitespace + $comment =~ s/[\"]/\\\\\\"/g; # Replace double quotes with \" (backslash is sextupled to make it through regex and printf) + } +# print "B:",$comment,"\n"; + $comment; +} + +sub printTrailer +{ + print " tmp.close();\n"; + print "}\n"; +} + +sub compileLinkAndRun +{ + $status = system( <<"MAINPROGRAM"); +(cd ${TMPDIR} ; /usr/bin/cc -x objective-c++ -pipe -Wno-trigraphs -fpascal-strings -fasm-blocks -g -O0 -Wreturn-type -fmessage-length=0 -F$ENV{'BUILT_PRODUCTS_DIR'} -I$ENV{'BUILT_PRODUCTS_DIR'}/SecurityPieces/Headers -I$ENV{'BUILT_PRODUCTS_DIR'}/SecurityPieces/PrivateHeaders -c generateErrStrings.mm -o generateErrStrings.o) +MAINPROGRAM + die "$compile exited funny: $?" unless $status == 0; + + $status = system( <<"LINKERSTEP"); +(cd ${TMPDIR} ; /usr/bin/clang++ -o generateErrStrings generateErrStrings.o -framework Foundation ) +LINKERSTEP + die "$linker exited funny: $?" unless $status == 0; + + $status = system( <<"RUNSTEP"); +(cd ${TMPDIR} ; ./generateErrStrings $TARGETSTR ) +RUNSTEP + die "$built program exited funny: $?" unless $status == 0; +} + diff --git a/lib/plugins/csparser-Info.plist b/Security/lib/plugins/csparser-Info.plist similarity index 94% rename from lib/plugins/csparser-Info.plist rename to Security/lib/plugins/csparser-Info.plist index 0d076c45..42f9d3a8 100644 --- a/lib/plugins/csparser-Info.plist +++ b/Security/lib/plugins/csparser-Info.plist @@ -17,7 +17,7 @@ CFBundleSignature ???? CFBundleVersion - 55471.14.18 + ${CURRENT_PROJECT_VERSION} CFBundleShortVersionString 3.0 diff --git a/lib/plugins/csparser.cpp b/Security/lib/plugins/csparser.cpp similarity index 94% rename from lib/plugins/csparser.cpp rename to Security/lib/plugins/csparser.cpp index 854f6d6c..aaf1f612 100644 --- a/lib/plugins/csparser.cpp +++ b/Security/lib/plugins/csparser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/lib/plugins/csparser.exp b/Security/lib/plugins/csparser.exp similarity index 93% rename from lib/plugins/csparser.exp rename to Security/lib/plugins/csparser.exp index 4eea439c..0fea7488 100644 --- a/lib/plugins/csparser.exp +++ b/Security/lib/plugins/csparser.exp @@ -1,5 +1,5 @@ # -# Copyright (c) 2007 Apple Inc. All Rights Reserved. +# Copyright (c) 2007,2011 Apple Inc. All Rights Reserved. # # @APPLE_LICENSE_HEADER_START@ # diff --git a/lib/security.exp-in b/Security/lib/security.exp-in similarity index 97% rename from lib/security.exp-in rename to Security/lib/security.exp-in index e3d3e437..25d19b32 100644 --- a/lib/security.exp-in +++ b/Security/lib/security.exp-in @@ -256,8 +256,10 @@ _CMSDecoderCopySignerCert _CmsMessageSetTSAContext _CMSDecoderCopySignerSigningTime _CMSDecoderCopySignerTimestamp +_CMSDecoderCopySignerTimestampWithPolicy _CMSDecoderCopySignerTimestampCertificates _CMSEncoderCopySignerTimestamp +_CMSEncoderCopySignerTimestampWithPolicy // // libsecurity_codesigning @@ -288,6 +290,8 @@ _SecStaticCodeCreateWithPathAndAttributes _SecStaticCodeCheckValidity _SecStaticCodeCheckValidityWithErrors _SecStaticCodeSetCallback +_SecStaticCodeSetValidationConditions +_SecStaticCodeCancelValidation _SecRequirementGetTypeID _SecRequirementCreateWithData _SecRequirementCreateWithResource @@ -393,6 +397,10 @@ _kSecAssessmentContextKeyOperation _kSecAssessmentOperationTypeExecute _kSecAssessmentOperationTypeInstall _kSecAssessmentOperationTypeOpenDocument +_kSecAssessmentContextKeyFeedback +_kSecAssessmentFeedbackProgress +_kSecAssessmentFeedbackInfoCurrent +_kSecAssessmentFeedbackInfoTotal _kSecAssessmentContextKeyUpdate _kSecAssessmentUpdateOperationAdd _kSecAssessmentUpdateOperationRemove @@ -1112,6 +1120,7 @@ _kSecAttrAccessibleAlways _kSecAttrAccessibleWhenUnlockedThisDeviceOnly _kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly _kSecAttrAccessibleAlwaysThisDeviceOnly +_kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly _kSecAttrCreationDate _kSecAttrModificationDate _kSecAttrDescription @@ -1267,9 +1276,11 @@ _kSecPolicyAppleRevocation _kSecPolicyApplePassbookSigning _kSecPolicyAppleMobileStore _kSecPolicyAppleEscrowService +_kSecPolicyApplePCSEscrowService _kSecPolicyAppleProfileSigner _kSecPolicyAppleQAProfileSigner _kSecPolicyAppleTestMobileStore +_kSecPolicyAppleServerAuthentication _kSecPolicyOid _kSecPolicyName _kSecPolicyClient @@ -1496,6 +1507,7 @@ _SecCertificateCopyLongDescription _SecCertificateCopyShortDescription _SecCertificateCopyEscrowRoots _kSecCertificateProductionEscrowKey +_kSecCertificateProductionPCSEscrowKey _kSecCertificateEscrowFileName _SecCopyErrorMessageString _SecDigestGetData @@ -1549,8 +1561,11 @@ _SecECKeyGetNamedCurve _SecItemExport _SecItemImport _SecKeyCopyPublicBytes +_SecKeyCopyModulus +_SecKeyCopyExponent _SecKeyCreate _SecKeyCreatePair +_SecKeyCreateRSAPublicKey _SecKeyCreateWithCSSMKey _SecKeyDecrypt _SecKeyEncrypt @@ -1610,6 +1625,7 @@ _SecKeychainGetStatus _SecKeychainGetTypeID _SecKeychainGetUserInteractionAllowed _SecKeychainGetVersion +_SecKeychainMDSInstall _SecKeychainIsValid _SecKeychainItemAdd _SecKeychainItemAddNoUI @@ -1680,7 +1696,10 @@ _SecKeychainSetServerMode _SecKeychainSetSettings _SecKeychainSetUserInteractionAllowed _SecKeychainSystemKeychainCheckWouldDeadlock -__SecKeychainSyncUpdate +_SecKeychainStoreUnlockKey +__SecKeychainSyncUpdateKeyParameter +__SecKeychainSyncUpdateCircle +__SecKeychainSyncUpdateMessage _SecKeychainUnlock _SecKeychainVerifyKeyStorePassphrase _SecKeychainChangeKeyStorePassphrase @@ -1688,11 +1707,16 @@ _SecGenericPasswordCreate _SecPasswordSetInitialAccess _SecPasswordAction _SecPKCS12Import +_SecPolicyCreateAppleIDSService +_SecPolicyCreateApplePushService +_SecPolicyCreateAppleMMCSService +_SecPolicyCreateAppleSSLService _SecPolicyCreateBasicX509 _SecPolicyCreateRevocation _SecPolicyCreateSSL _SecPolicyCreateWithOID _SecPolicyCreateWithProperties +_SecPolicyCreateAppleTimeStampingAndRevocationPolicies _SecPolicyGetOID _SecPolicyGetTPHandle _SecPolicyGetTypeID @@ -1963,6 +1987,8 @@ _SecCmsSignerInfoIncludeCerts _SecCmsSignerInfoSaveSMIMEProfile _SecCmsUtilVerificationStatusToString _SecSMIMEFindBulkAlgForRecipients +_SecCMSCertificatesOnlyMessageCopyCertificates +_SecCMSCreateCertificatesOnlyMessageIAP // // libsecurity_ssl @@ -2040,6 +2066,9 @@ _SSLSetRecordContext _SSLSetRsaBlinding _SSLSetTrustedRoots _SSLWrite +_SSLSetNPNFunc +_SSLSetNPNData +_SSLGetNPNData _SSLSetSessionCacheTimeout _SSLSetSessionOption _SSLInternalSetMasterSecretFunction @@ -2168,6 +2197,7 @@ _SecKeyCreatePublicFromPrivate // // libsecurity_utilities // +_add_security_log_handler _secdebug_internal // @@ -2180,6 +2210,7 @@ _SecFrameworkCopyLocalizedString _SecPasswordCopyDefaultPasswordLength _SecPasswordGenerate _SecPasswordIsPasswordWeak +_SecPasswordIsPasswordWeak2 _kSecPasswordDefaultForType _kSecPasswordMinLengthKey _kSecPasswordMaxLengthKey @@ -2197,11 +2228,38 @@ _kSecPasswordGroupSize _kSecPasswordNumberOfGroups _kSecPasswordSeparator +// +// Logging +// + +_SecGetCurrentServerLoggingInfo +_SecSetLoggingInfoForXPCScope + +// +// sec/Security SecAccessControl +// +#include "../sec/Security/SecAccessControlExports.exp-in" // // utilities // -_add_security_log_hanlder + +// SecDH +_SecDHComputeKey +_SecDHCreate +_SecDHCreateFromParameters +_SecDHDestroy +_SecDHGenerateKeypair +_SecDHGetMaxKeyLength +_SecDHDecodeParams +_SecDHEncodeParams + +_SecECKeyCopyPublicBits + +//breadcrumb +_SecBreadcrumbCreateFromPassword +_SecBreadcrumbCopyPassword +_SecBreadcrumbCreateNewEncryptedKey // gate keeper logging diff --git a/libsecurity_apple_csp/Info-security_apple_csp.plist b/Security/libsecurity_apple_csp/Info-security_apple_csp.plist similarity index 100% rename from libsecurity_apple_csp/Info-security_apple_csp.plist rename to Security/libsecurity_apple_csp/Info-security_apple_csp.plist diff --git a/libsecurity_apple_csp/README b/Security/libsecurity_apple_csp/README similarity index 100% rename from libsecurity_apple_csp/README rename to Security/libsecurity_apple_csp/README diff --git a/libsecurity_apple_csp/TODO b/Security/libsecurity_apple_csp/TODO similarity index 100% rename from libsecurity_apple_csp/TODO rename to Security/libsecurity_apple_csp/TODO diff --git a/libsecurity_apple_csp/docs/libsecurity_apple_csp.plist b/Security/libsecurity_apple_csp/docs/libsecurity_apple_csp.plist similarity index 100% rename from libsecurity_apple_csp/docs/libsecurity_apple_csp.plist rename to Security/libsecurity_apple_csp/docs/libsecurity_apple_csp.plist diff --git a/libsecurity_apple_csp/docs/libsecurity_apple_csp.txt b/Security/libsecurity_apple_csp/docs/libsecurity_apple_csp.txt similarity index 100% rename from libsecurity_apple_csp/docs/libsecurity_apple_csp.txt rename to Security/libsecurity_apple_csp/docs/libsecurity_apple_csp.txt diff --git a/libsecurity_apple_csp/lib/AppleCSP.cpp b/Security/libsecurity_apple_csp/lib/AppleCSP.cpp similarity index 99% rename from libsecurity_apple_csp/lib/AppleCSP.cpp rename to Security/libsecurity_apple_csp/lib/AppleCSP.cpp index 7fd55f16..ec9e78ca 100644 --- a/libsecurity_apple_csp/lib/AppleCSP.cpp +++ b/Security/libsecurity_apple_csp/lib/AppleCSP.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/AppleCSP.h b/Security/libsecurity_apple_csp/lib/AppleCSP.h similarity index 97% rename from libsecurity_apple_csp/lib/AppleCSP.h rename to Security/libsecurity_apple_csp/lib/AppleCSP.h index e8531a73..513cba29 100644 --- a/libsecurity_apple_csp/lib/AppleCSP.h +++ b/Security/libsecurity_apple_csp/lib/AppleCSP.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/AppleCSPBuiltin.cpp b/Security/libsecurity_apple_csp/lib/AppleCSPBuiltin.cpp similarity index 94% rename from libsecurity_apple_csp/lib/AppleCSPBuiltin.cpp rename to Security/libsecurity_apple_csp/lib/AppleCSPBuiltin.cpp index b7b5278a..30eb1726 100644 --- a/libsecurity_apple_csp/lib/AppleCSPBuiltin.cpp +++ b/Security/libsecurity_apple_csp/lib/AppleCSPBuiltin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/AppleCSPContext.cpp b/Security/libsecurity_apple_csp/lib/AppleCSPContext.cpp similarity index 99% rename from libsecurity_apple_csp/lib/AppleCSPContext.cpp rename to Security/libsecurity_apple_csp/lib/AppleCSPContext.cpp index f393e930..fc836c85 100644 --- a/libsecurity_apple_csp/lib/AppleCSPContext.cpp +++ b/Security/libsecurity_apple_csp/lib/AppleCSPContext.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/AppleCSPContext.h b/Security/libsecurity_apple_csp/lib/AppleCSPContext.h similarity index 98% rename from libsecurity_apple_csp/lib/AppleCSPContext.h rename to Security/libsecurity_apple_csp/lib/AppleCSPContext.h index ad7b3739..326e4e82 100644 --- a/libsecurity_apple_csp/lib/AppleCSPContext.h +++ b/Security/libsecurity_apple_csp/lib/AppleCSPContext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/AppleCSPKeys.cpp b/Security/libsecurity_apple_csp/lib/AppleCSPKeys.cpp similarity index 97% rename from libsecurity_apple_csp/lib/AppleCSPKeys.cpp rename to Security/libsecurity_apple_csp/lib/AppleCSPKeys.cpp index 957c72f1..2bb59bab 100644 --- a/libsecurity_apple_csp/lib/AppleCSPKeys.cpp +++ b/Security/libsecurity_apple_csp/lib/AppleCSPKeys.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/AppleCSPKeys.h b/Security/libsecurity_apple_csp/lib/AppleCSPKeys.h similarity index 98% rename from libsecurity_apple_csp/lib/AppleCSPKeys.h rename to Security/libsecurity_apple_csp/lib/AppleCSPKeys.h index 2fdc407e..e06dbe86 100644 --- a/libsecurity_apple_csp/lib/AppleCSPKeys.h +++ b/Security/libsecurity_apple_csp/lib/AppleCSPKeys.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/AppleCSPPlugin.cpp b/Security/libsecurity_apple_csp/lib/AppleCSPPlugin.cpp similarity index 94% rename from libsecurity_apple_csp/lib/AppleCSPPlugin.cpp rename to Security/libsecurity_apple_csp/lib/AppleCSPPlugin.cpp index cc8d5414..4fca2aa4 100644 --- a/libsecurity_apple_csp/lib/AppleCSPPlugin.cpp +++ b/Security/libsecurity_apple_csp/lib/AppleCSPPlugin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/AppleCSPSession.h b/Security/libsecurity_apple_csp/lib/AppleCSPSession.h similarity index 99% rename from libsecurity_apple_csp/lib/AppleCSPSession.h rename to Security/libsecurity_apple_csp/lib/AppleCSPSession.h index 56ef2c14..c64dbe68 100644 --- a/libsecurity_apple_csp/lib/AppleCSPSession.h +++ b/Security/libsecurity_apple_csp/lib/AppleCSPSession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/AppleCSPUtils.cpp b/Security/libsecurity_apple_csp/lib/AppleCSPUtils.cpp similarity index 99% rename from libsecurity_apple_csp/lib/AppleCSPUtils.cpp rename to Security/libsecurity_apple_csp/lib/AppleCSPUtils.cpp index 246bba25..5ba459d3 100644 --- a/libsecurity_apple_csp/lib/AppleCSPUtils.cpp +++ b/Security/libsecurity_apple_csp/lib/AppleCSPUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/AppleCSPUtils.h b/Security/libsecurity_apple_csp/lib/AppleCSPUtils.h similarity index 98% rename from libsecurity_apple_csp/lib/AppleCSPUtils.h rename to Security/libsecurity_apple_csp/lib/AppleCSPUtils.h index 2ddadac0..bad98732 100644 --- a/libsecurity_apple_csp/lib/AppleCSPUtils.h +++ b/Security/libsecurity_apple_csp/lib/AppleCSPUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/BinaryKey.h b/Security/libsecurity_apple_csp/lib/BinaryKey.h similarity index 98% rename from libsecurity_apple_csp/lib/BinaryKey.h rename to Security/libsecurity_apple_csp/lib/BinaryKey.h index 36055b9a..71ed0c31 100644 --- a/libsecurity_apple_csp/lib/BinaryKey.h +++ b/Security/libsecurity_apple_csp/lib/BinaryKey.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/BlockCryptor.cpp b/Security/libsecurity_apple_csp/lib/BlockCryptor.cpp similarity index 99% rename from libsecurity_apple_csp/lib/BlockCryptor.cpp rename to Security/libsecurity_apple_csp/lib/BlockCryptor.cpp index 23ab8203..d694ee91 100644 --- a/libsecurity_apple_csp/lib/BlockCryptor.cpp +++ b/Security/libsecurity_apple_csp/lib/BlockCryptor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * BlockCryptor.cpp - common context for block-oriented encryption algorithms * - * Created March 5 2001 by dmitch */ #include "BlockCryptor.h" diff --git a/libsecurity_apple_csp/lib/BlockCryptor.h b/Security/libsecurity_apple_csp/lib/BlockCryptor.h similarity index 98% rename from libsecurity_apple_csp/lib/BlockCryptor.h rename to Security/libsecurity_apple_csp/lib/BlockCryptor.h index 13ceb8b7..4e933186 100644 --- a/libsecurity_apple_csp/lib/BlockCryptor.h +++ b/Security/libsecurity_apple_csp/lib/BlockCryptor.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * BlockCryptor.h - common context for block-oriented encryption algorithms * - * Created March 5 2001 by dmitch */ #ifndef _BLOCK_CRYPTOR_H_ diff --git a/libsecurity_apple_csp/lib/CryptKitSpace.h b/Security/libsecurity_apple_csp/lib/CryptKitSpace.h similarity index 91% rename from libsecurity_apple_csp/lib/CryptKitSpace.h rename to Security/libsecurity_apple_csp/lib/CryptKitSpace.h index ac546d7c..643706a6 100755 --- a/libsecurity_apple_csp/lib/CryptKitSpace.h +++ b/Security/libsecurity_apple_csp/lib/CryptKitSpace.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * CryptKitSpace.h - bare-bones declaration of CryptKit namespace. * - * Created by dmitch on Wed Feb 21 2001. */ #ifdef CRYPTKIT_CSP_ENABLE diff --git a/libsecurity_apple_csp/lib/DH_csp.cpp b/Security/libsecurity_apple_csp/lib/DH_csp.cpp similarity index 96% rename from libsecurity_apple_csp/lib/DH_csp.cpp rename to Security/libsecurity_apple_csp/lib/DH_csp.cpp index 7c2a903a..65be7b1c 100644 --- a/libsecurity_apple_csp/lib/DH_csp.cpp +++ b/Security/libsecurity_apple_csp/lib/DH_csp.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/DH_csp.h b/Security/libsecurity_apple_csp/lib/DH_csp.h similarity index 96% rename from libsecurity_apple_csp/lib/DH_csp.h rename to Security/libsecurity_apple_csp/lib/DH_csp.h index 1a73293b..7399c9dc 100644 --- a/libsecurity_apple_csp/lib/DH_csp.h +++ b/Security/libsecurity_apple_csp/lib/DH_csp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/DH_exchange.cpp b/Security/libsecurity_apple_csp/lib/DH_exchange.cpp similarity index 98% rename from libsecurity_apple_csp/lib/DH_exchange.cpp rename to Security/libsecurity_apple_csp/lib/DH_exchange.cpp index f09c83f7..bb57f38e 100644 --- a/libsecurity_apple_csp/lib/DH_exchange.cpp +++ b/Security/libsecurity_apple_csp/lib/DH_exchange.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/DH_exchange.h b/Security/libsecurity_apple_csp/lib/DH_exchange.h similarity index 94% rename from libsecurity_apple_csp/lib/DH_exchange.h rename to Security/libsecurity_apple_csp/lib/DH_exchange.h index 7e408d8a..b839a4b5 100644 --- a/libsecurity_apple_csp/lib/DH_exchange.h +++ b/Security/libsecurity_apple_csp/lib/DH_exchange.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/DH_keys.cpp b/Security/libsecurity_apple_csp/lib/DH_keys.cpp similarity index 99% rename from libsecurity_apple_csp/lib/DH_keys.cpp rename to Security/libsecurity_apple_csp/lib/DH_keys.cpp index 3ad1b392..81fbafee 100644 --- a/libsecurity_apple_csp/lib/DH_keys.cpp +++ b/Security/libsecurity_apple_csp/lib/DH_keys.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/DH_keys.h b/Security/libsecurity_apple_csp/lib/DH_keys.h similarity index 98% rename from libsecurity_apple_csp/lib/DH_keys.h rename to Security/libsecurity_apple_csp/lib/DH_keys.h index c75d403f..95966cb2 100644 --- a/libsecurity_apple_csp/lib/DH_keys.h +++ b/Security/libsecurity_apple_csp/lib/DH_keys.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/DH_utils.cpp b/Security/libsecurity_apple_csp/lib/DH_utils.cpp similarity index 98% rename from libsecurity_apple_csp/lib/DH_utils.cpp rename to Security/libsecurity_apple_csp/lib/DH_utils.cpp index 3b92db4a..3eccf481 100644 --- a/libsecurity_apple_csp/lib/DH_utils.cpp +++ b/Security/libsecurity_apple_csp/lib/DH_utils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/DH_utils.h b/Security/libsecurity_apple_csp/lib/DH_utils.h similarity index 97% rename from libsecurity_apple_csp/lib/DH_utils.h rename to Security/libsecurity_apple_csp/lib/DH_utils.h index 4bf45f24..bdf10f6f 100644 --- a/libsecurity_apple_csp/lib/DH_utils.h +++ b/Security/libsecurity_apple_csp/lib/DH_utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/DigestContext.cpp b/Security/libsecurity_apple_csp/lib/DigestContext.cpp similarity index 96% rename from libsecurity_apple_csp/lib/DigestContext.cpp rename to Security/libsecurity_apple_csp/lib/DigestContext.cpp index 395d3d61..db5f4d4b 100644 --- a/libsecurity_apple_csp/lib/DigestContext.cpp +++ b/Security/libsecurity_apple_csp/lib/DigestContext.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/DigestContext.h b/Security/libsecurity_apple_csp/lib/DigestContext.h similarity index 96% rename from libsecurity_apple_csp/lib/DigestContext.h rename to Security/libsecurity_apple_csp/lib/DigestContext.h index 5053315b..4af669a0 100644 --- a/libsecurity_apple_csp/lib/DigestContext.h +++ b/Security/libsecurity_apple_csp/lib/DigestContext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp b/Security/libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp similarity index 99% rename from libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp rename to Security/libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp index 3556c887..080d555d 100644 --- a/libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp +++ b/Security/libsecurity_apple_csp/lib/FEEAsymmetricContext.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * FEEAsymmetricContext.cpp - CSPContexts for FEE asymmetric encryption * - * Created March 8 2001 by dmitch. */ #ifdef CRYPTKIT_CSP_ENABLE diff --git a/libsecurity_apple_csp/lib/FEEAsymmetricContext.h b/Security/libsecurity_apple_csp/lib/FEEAsymmetricContext.h similarity index 97% rename from libsecurity_apple_csp/lib/FEEAsymmetricContext.h rename to Security/libsecurity_apple_csp/lib/FEEAsymmetricContext.h index 6546cb51..2f0a2c0e 100644 --- a/libsecurity_apple_csp/lib/FEEAsymmetricContext.h +++ b/Security/libsecurity_apple_csp/lib/FEEAsymmetricContext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * FEEAsymmetricContext.h - CSPContexts for FEE asymmetric encryption * - * Created March 8 2001 by dmitch. */ #ifdef CRYPTKIT_CSP_ENABLE diff --git a/libsecurity_apple_csp/lib/FEECSPUtils.cpp b/Security/libsecurity_apple_csp/lib/FEECSPUtils.cpp similarity index 99% rename from libsecurity_apple_csp/lib/FEECSPUtils.cpp rename to Security/libsecurity_apple_csp/lib/FEECSPUtils.cpp index 9db7a700..7e29a84c 100644 --- a/libsecurity_apple_csp/lib/FEECSPUtils.cpp +++ b/Security/libsecurity_apple_csp/lib/FEECSPUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * FEECSPUtils.h - Misc. utility function for FEE/CryptKit CSP. * - * Created 2/20/2001 by dmitch. */ #ifdef CRYPTKIT_CSP_ENABLE diff --git a/libsecurity_apple_csp/lib/FEECSPUtils.h b/Security/libsecurity_apple_csp/lib/FEECSPUtils.h similarity index 96% rename from libsecurity_apple_csp/lib/FEECSPUtils.h rename to Security/libsecurity_apple_csp/lib/FEECSPUtils.h index 986d29ce..37dc1c4f 100644 --- a/libsecurity_apple_csp/lib/FEECSPUtils.h +++ b/Security/libsecurity_apple_csp/lib/FEECSPUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * FEECSPUtils.h - Misc. utility function for FEE/CryptKit CSP. * - * Created 2/20/2001 by dmitch. */ #ifdef CRYPTKIT_CSP_ENABLE diff --git a/libsecurity_apple_csp/lib/FEEKeys.cpp b/Security/libsecurity_apple_csp/lib/FEEKeys.cpp similarity index 99% rename from libsecurity_apple_csp/lib/FEEKeys.cpp rename to Security/libsecurity_apple_csp/lib/FEEKeys.cpp index 831ce376..5571510d 100644 --- a/libsecurity_apple_csp/lib/FEEKeys.cpp +++ b/Security/libsecurity_apple_csp/lib/FEEKeys.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * FEEKeys.cpp - FEE-related asymmetric key pair classes. * - * Created 2/21/2001 by dmitch. */ #ifdef CRYPTKIT_CSP_ENABLE diff --git a/libsecurity_apple_csp/lib/FEEKeys.h b/Security/libsecurity_apple_csp/lib/FEEKeys.h similarity index 96% rename from libsecurity_apple_csp/lib/FEEKeys.h rename to Security/libsecurity_apple_csp/lib/FEEKeys.h index cf757076..54d6b009 100644 --- a/libsecurity_apple_csp/lib/FEEKeys.h +++ b/Security/libsecurity_apple_csp/lib/FEEKeys.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * FEEKeys.h - FEE-related asymmetric key pair classes. * - * Created 2/21/2001 by dmitch. */ #ifdef CRYPTKIT_CSP_ENABLE diff --git a/libsecurity_apple_csp/lib/FEESignatureObject.cpp b/Security/libsecurity_apple_csp/lib/FEESignatureObject.cpp similarity index 98% rename from libsecurity_apple_csp/lib/FEESignatureObject.cpp rename to Security/libsecurity_apple_csp/lib/FEESignatureObject.cpp index 74fa0959..2b961162 100644 --- a/libsecurity_apple_csp/lib/FEESignatureObject.cpp +++ b/Security/libsecurity_apple_csp/lib/FEESignatureObject.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * FEESignatureObject.cpp - implementations of FEE-style raw sign/verify classes * - * Created 2/20/2001 by dmitch. */ #ifdef CRYPTKIT_CSP_ENABLE diff --git a/libsecurity_apple_csp/lib/FEESignatureObject.h b/Security/libsecurity_apple_csp/lib/FEESignatureObject.h similarity index 97% rename from libsecurity_apple_csp/lib/FEESignatureObject.h rename to Security/libsecurity_apple_csp/lib/FEESignatureObject.h index c5e144ef..e63480e7 100644 --- a/libsecurity_apple_csp/lib/FEESignatureObject.h +++ b/Security/libsecurity_apple_csp/lib/FEESignatureObject.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/HMACSHA1.c b/Security/libsecurity_apple_csp/lib/HMACSHA1.c similarity index 87% rename from libsecurity_apple_csp/lib/HMACSHA1.c rename to Security/libsecurity_apple_csp/lib/HMACSHA1.c index 10dd203b..82b8ae3f 100644 --- a/libsecurity_apple_csp/lib/HMACSHA1.c +++ b/Security/libsecurity_apple_csp/lib/HMACSHA1.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,8 +19,7 @@ /* File: HMACSHA1.c Contains: Apple Data Security Services HMACSHA1 function definition. - Copyright: (C) 1999 by Apple Computer, Inc., all rights reserved - Written by: Michael Brouwer + Copyright (c) 1999,2011,2014 Apple Inc. All Rights Reserved. */ #include "HMACSHA1.h" #include diff --git a/libsecurity_apple_csp/lib/HMACSHA1.h b/Security/libsecurity_apple_csp/lib/HMACSHA1.h similarity index 89% rename from libsecurity_apple_csp/lib/HMACSHA1.h rename to Security/libsecurity_apple_csp/lib/HMACSHA1.h index 1c3bf71d..acc21a82 100644 --- a/libsecurity_apple_csp/lib/HMACSHA1.h +++ b/Security/libsecurity_apple_csp/lib/HMACSHA1.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,8 +19,7 @@ /* File: HMACSHA1.h Contains: Apple Data Security Services HMAC{SHA1,MD5} function declaration. - Copyright: (C) 1999 by Apple Computer, Inc., all rights reserved - Written by: Michael Brouwer + Copyright (c) 1999,2011,2013-2014 Apple Inc. All Rights Reserved. */ #ifndef __HMACSHA1__ #define __HMACSHA1__ diff --git a/libsecurity_apple_csp/lib/MD2Object.cpp b/Security/libsecurity_apple_csp/lib/MD2Object.cpp similarity index 95% rename from libsecurity_apple_csp/lib/MD2Object.cpp rename to Security/libsecurity_apple_csp/lib/MD2Object.cpp index 18531cb4..a6399b90 100644 --- a/libsecurity_apple_csp/lib/MD2Object.cpp +++ b/Security/libsecurity_apple_csp/lib/MD2Object.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/MD2Object.h b/Security/libsecurity_apple_csp/lib/MD2Object.h similarity index 94% rename from libsecurity_apple_csp/lib/MD2Object.h rename to Security/libsecurity_apple_csp/lib/MD2Object.h index b247e3b8..12bedd70 100644 --- a/libsecurity_apple_csp/lib/MD2Object.h +++ b/Security/libsecurity_apple_csp/lib/MD2Object.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/MacContext.cpp b/Security/libsecurity_apple_csp/lib/MacContext.cpp similarity index 98% rename from libsecurity_apple_csp/lib/MacContext.cpp rename to Security/libsecurity_apple_csp/lib/MacContext.cpp index 67e27328..1fdbe4f0 100644 --- a/libsecurity_apple_csp/lib/MacContext.cpp +++ b/Security/libsecurity_apple_csp/lib/MacContext.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/MacContext.h b/Security/libsecurity_apple_csp/lib/MacContext.h similarity index 97% rename from libsecurity_apple_csp/lib/MacContext.h rename to Security/libsecurity_apple_csp/lib/MacContext.h index 62d69fca..8d817c9b 100644 --- a/libsecurity_apple_csp/lib/MacContext.h +++ b/Security/libsecurity_apple_csp/lib/MacContext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/NullCryptor.h b/Security/libsecurity_apple_csp/lib/NullCryptor.h similarity index 95% rename from libsecurity_apple_csp/lib/NullCryptor.h rename to Security/libsecurity_apple_csp/lib/NullCryptor.h index 0fde61cd..1ea56aa9 100644 --- a/libsecurity_apple_csp/lib/NullCryptor.h +++ b/Security/libsecurity_apple_csp/lib/NullCryptor.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -18,7 +18,6 @@ /* * NullCryptor.h - null symmetric encryptor for measurement only - * Written by Doug Mitchell 12/17/2001 */ #ifndef _NULL_CRYPTOR_H_ #define _NULL_CRYPTOR_H_ diff --git a/libsecurity_apple_csp/lib/RSA_DSA_csp.cpp b/Security/libsecurity_apple_csp/lib/RSA_DSA_csp.cpp similarity index 98% rename from libsecurity_apple_csp/lib/RSA_DSA_csp.cpp rename to Security/libsecurity_apple_csp/lib/RSA_DSA_csp.cpp index 723e2294..352fa6cb 100644 --- a/libsecurity_apple_csp/lib/RSA_DSA_csp.cpp +++ b/Security/libsecurity_apple_csp/lib/RSA_DSA_csp.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/RSA_DSA_csp.h b/Security/libsecurity_apple_csp/lib/RSA_DSA_csp.h similarity index 96% rename from libsecurity_apple_csp/lib/RSA_DSA_csp.h rename to Security/libsecurity_apple_csp/lib/RSA_DSA_csp.h index b4e7b05c..fb610247 100644 --- a/libsecurity_apple_csp/lib/RSA_DSA_csp.h +++ b/Security/libsecurity_apple_csp/lib/RSA_DSA_csp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/RSA_DSA_keys.cpp b/Security/libsecurity_apple_csp/lib/RSA_DSA_keys.cpp similarity index 99% rename from libsecurity_apple_csp/lib/RSA_DSA_keys.cpp rename to Security/libsecurity_apple_csp/lib/RSA_DSA_keys.cpp index b73fc470..8a7a9553 100644 --- a/libsecurity_apple_csp/lib/RSA_DSA_keys.cpp +++ b/Security/libsecurity_apple_csp/lib/RSA_DSA_keys.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/RSA_DSA_keys.h b/Security/libsecurity_apple_csp/lib/RSA_DSA_keys.h similarity index 98% rename from libsecurity_apple_csp/lib/RSA_DSA_keys.h rename to Security/libsecurity_apple_csp/lib/RSA_DSA_keys.h index c5cd8886..3d90129e 100644 --- a/libsecurity_apple_csp/lib/RSA_DSA_keys.h +++ b/Security/libsecurity_apple_csp/lib/RSA_DSA_keys.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/RSA_DSA_signature.cpp b/Security/libsecurity_apple_csp/lib/RSA_DSA_signature.cpp similarity index 99% rename from libsecurity_apple_csp/lib/RSA_DSA_signature.cpp rename to Security/libsecurity_apple_csp/lib/RSA_DSA_signature.cpp index 1864d32e..d1be94cb 100644 --- a/libsecurity_apple_csp/lib/RSA_DSA_signature.cpp +++ b/Security/libsecurity_apple_csp/lib/RSA_DSA_signature.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/RSA_DSA_signature.h b/Security/libsecurity_apple_csp/lib/RSA_DSA_signature.h similarity index 97% rename from libsecurity_apple_csp/lib/RSA_DSA_signature.h rename to Security/libsecurity_apple_csp/lib/RSA_DSA_signature.h index 7a5d1574..6baf03f2 100644 --- a/libsecurity_apple_csp/lib/RSA_DSA_signature.h +++ b/Security/libsecurity_apple_csp/lib/RSA_DSA_signature.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp b/Security/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp similarity index 99% rename from libsecurity_apple_csp/lib/RSA_DSA_utils.cpp rename to Security/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp index f85ecfa9..cda4042b 100644 --- a/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp +++ b/Security/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/RSA_DSA_utils.h b/Security/libsecurity_apple_csp/lib/RSA_DSA_utils.h similarity index 98% rename from libsecurity_apple_csp/lib/RSA_DSA_utils.h rename to Security/libsecurity_apple_csp/lib/RSA_DSA_utils.h index fecfd88d..0ad0ca35 100644 --- a/libsecurity_apple_csp/lib/RSA_DSA_utils.h +++ b/Security/libsecurity_apple_csp/lib/RSA_DSA_utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/RSA_asymmetric.cpp b/Security/libsecurity_apple_csp/lib/RSA_asymmetric.cpp similarity index 98% rename from libsecurity_apple_csp/lib/RSA_asymmetric.cpp rename to Security/libsecurity_apple_csp/lib/RSA_asymmetric.cpp index b7866b79..7d0f0222 100644 --- a/libsecurity_apple_csp/lib/RSA_asymmetric.cpp +++ b/Security/libsecurity_apple_csp/lib/RSA_asymmetric.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/RSA_asymmetric.h b/Security/libsecurity_apple_csp/lib/RSA_asymmetric.h similarity index 97% rename from libsecurity_apple_csp/lib/RSA_asymmetric.h rename to Security/libsecurity_apple_csp/lib/RSA_asymmetric.h index eb387c26..92950baf 100644 --- a/libsecurity_apple_csp/lib/RSA_asymmetric.h +++ b/Security/libsecurity_apple_csp/lib/RSA_asymmetric.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/RawSigner.h b/Security/libsecurity_apple_csp/lib/RawSigner.h similarity index 97% rename from libsecurity_apple_csp/lib/RawSigner.h rename to Security/libsecurity_apple_csp/lib/RawSigner.h index 92d6532d..f2f228c9 100644 --- a/libsecurity_apple_csp/lib/RawSigner.h +++ b/Security/libsecurity_apple_csp/lib/RawSigner.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/SHA1_MD5_Object.cpp b/Security/libsecurity_apple_csp/lib/SHA1_MD5_Object.cpp similarity index 95% rename from libsecurity_apple_csp/lib/SHA1_MD5_Object.cpp rename to Security/libsecurity_apple_csp/lib/SHA1_MD5_Object.cpp index 7e79c005..3b20eac5 100644 --- a/libsecurity_apple_csp/lib/SHA1_MD5_Object.cpp +++ b/Security/libsecurity_apple_csp/lib/SHA1_MD5_Object.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -25,7 +25,6 @@ /* * DigestObject.cpp - generic C++ implementations of SHA1 and MD5. * - * Created 2/19/2001 by dmitch. */ #include "SHA1_MD5_Object.h" diff --git a/libsecurity_apple_csp/lib/SHA1_MD5_Object.h b/Security/libsecurity_apple_csp/lib/SHA1_MD5_Object.h similarity index 95% rename from libsecurity_apple_csp/lib/SHA1_MD5_Object.h rename to Security/libsecurity_apple_csp/lib/SHA1_MD5_Object.h index d66f9f08..ca41aeae 100644 --- a/libsecurity_apple_csp/lib/SHA1_MD5_Object.h +++ b/Security/libsecurity_apple_csp/lib/SHA1_MD5_Object.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -25,7 +25,6 @@ /* * SHA1_MD5_Object.h - SHA1, MD5 digest objects * - * Created 2/19/2001 by dmitch. */ #ifndef _SHA1_MD5_OBJECT_H_ diff --git a/libsecurity_apple_csp/lib/SHA2_Object.cpp b/Security/libsecurity_apple_csp/lib/SHA2_Object.cpp similarity index 96% rename from libsecurity_apple_csp/lib/SHA2_Object.cpp rename to Security/libsecurity_apple_csp/lib/SHA2_Object.cpp index 169c9ec3..ea264cad 100644 --- a/libsecurity_apple_csp/lib/SHA2_Object.cpp +++ b/Security/libsecurity_apple_csp/lib/SHA2_Object.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -24,8 +24,6 @@ /* * SHA2_Object.cpp - SHA2 digest objects - * Created 8/12/2004 by dmitch. - * Created 2/19/2001 by dmitch. */ #include "SHA2_Object.h" diff --git a/libsecurity_apple_csp/lib/SHA2_Object.h b/Security/libsecurity_apple_csp/lib/SHA2_Object.h similarity index 96% rename from libsecurity_apple_csp/lib/SHA2_Object.h rename to Security/libsecurity_apple_csp/lib/SHA2_Object.h index 68bba6b0..6836c4fd 100644 --- a/libsecurity_apple_csp/lib/SHA2_Object.h +++ b/Security/libsecurity_apple_csp/lib/SHA2_Object.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -25,7 +25,6 @@ /* * SHA2_Object.h - SHA2 digest objects * - * Created 8/12/2004 by dmitch. */ #ifndef _SHA2_OBJECT_H_ diff --git a/libsecurity_apple_csp/lib/SignatureContext.cpp b/Security/libsecurity_apple_csp/lib/SignatureContext.cpp similarity index 97% rename from libsecurity_apple_csp/lib/SignatureContext.cpp rename to Security/libsecurity_apple_csp/lib/SignatureContext.cpp index f7085c7d..22591749 100644 --- a/libsecurity_apple_csp/lib/SignatureContext.cpp +++ b/Security/libsecurity_apple_csp/lib/SignatureContext.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/SignatureContext.h b/Security/libsecurity_apple_csp/lib/SignatureContext.h similarity index 97% rename from libsecurity_apple_csp/lib/SignatureContext.h rename to Security/libsecurity_apple_csp/lib/SignatureContext.h index 1edc6e28..6a621e98 100644 --- a/libsecurity_apple_csp/lib/SignatureContext.h +++ b/Security/libsecurity_apple_csp/lib/SignatureContext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/YarrowConnection.cpp b/Security/libsecurity_apple_csp/lib/YarrowConnection.cpp similarity index 96% rename from libsecurity_apple_csp/lib/YarrowConnection.cpp rename to Security/libsecurity_apple_csp/lib/YarrowConnection.cpp index 064e1b71..e6a8da60 100644 --- a/libsecurity_apple_csp/lib/YarrowConnection.cpp +++ b/Security/libsecurity_apple_csp/lib/YarrowConnection.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/YarrowConnection.h b/Security/libsecurity_apple_csp/lib/YarrowConnection.h similarity index 95% rename from libsecurity_apple_csp/lib/YarrowConnection.h rename to Security/libsecurity_apple_csp/lib/YarrowConnection.h index a5521df9..e654a3b8 100644 --- a/libsecurity_apple_csp/lib/YarrowConnection.h +++ b/Security/libsecurity_apple_csp/lib/YarrowConnection.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/aesCommon.h b/Security/libsecurity_apple_csp/lib/aesCommon.h similarity index 95% rename from libsecurity_apple_csp/lib/aesCommon.h rename to Security/libsecurity_apple_csp/lib/aesCommon.h index 6e3480f6..8be253f3 100644 --- a/libsecurity_apple_csp/lib/aesCommon.h +++ b/Security/libsecurity_apple_csp/lib/aesCommon.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/aescsp.cpp b/Security/libsecurity_apple_csp/lib/aescsp.cpp similarity index 98% rename from libsecurity_apple_csp/lib/aescsp.cpp rename to Security/libsecurity_apple_csp/lib/aescsp.cpp index 65d769df..6da8bdb9 100644 --- a/libsecurity_apple_csp/lib/aescsp.cpp +++ b/Security/libsecurity_apple_csp/lib/aescsp.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -18,7 +18,6 @@ /* * aescsp.cpp - glue between BlockCryptor and AES implementation - * Written by Doug Mitchell 10/3/2000 */ #include "aescspi.h" diff --git a/libsecurity_apple_csp/lib/aescspi.h b/Security/libsecurity_apple_csp/lib/aescspi.h similarity index 97% rename from libsecurity_apple_csp/lib/aescspi.h rename to Security/libsecurity_apple_csp/lib/aescspi.h index 368db4b1..0c340eab 100644 --- a/libsecurity_apple_csp/lib/aescspi.h +++ b/Security/libsecurity_apple_csp/lib/aescspi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/algmaker.cpp b/Security/libsecurity_apple_csp/lib/algmaker.cpp similarity index 99% rename from libsecurity_apple_csp/lib/algmaker.cpp rename to Security/libsecurity_apple_csp/lib/algmaker.cpp index 5b7e558b..9b672903 100644 --- a/libsecurity_apple_csp/lib/algmaker.cpp +++ b/Security/libsecurity_apple_csp/lib/algmaker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/ascContext.cpp b/Security/libsecurity_apple_csp/lib/ascContext.cpp similarity index 89% rename from libsecurity_apple_csp/lib/ascContext.cpp rename to Security/libsecurity_apple_csp/lib/ascContext.cpp index 253468c7..e1b88e84 100644 --- a/libsecurity_apple_csp/lib/ascContext.cpp +++ b/Security/libsecurity_apple_csp/lib/ascContext.cpp @@ -1,8 +1,26 @@ /* - * ascContext.cpp - glue between BlockCrytpor and ComCryption (a.k.a. Apple - * Secure Compression). - * Written by Doug Mitchell 4/4/2001 + * Copyright (c) 2001,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@ */ + #ifdef ASC_CSP_ENABLE diff --git a/Security/libsecurity_apple_csp/lib/ascContext.h b/Security/libsecurity_apple_csp/lib/ascContext.h new file mode 100644 index 00000000..f1c51ee4 --- /dev/null +++ b/Security/libsecurity_apple_csp/lib/ascContext.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2001,2011,2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifdef ASC_CSP_ENABLE + +#ifndef _ASC_CONTEXT_H_ +#define _ASC_CONTEXT_H_ + +#include "AppleCSPContext.h" +#include + +/* symmetric encrypt/decrypt context */ +class ASCContext : public AppleCSPContext { +public: + ASCContext(AppleCSPSession &session) : + AppleCSPContext(session), + mCcObj(NULL) { } + ~ASCContext(); + + // called by CSPFullPluginSession + void init( + const Context &context, + bool encoding = true); + void update( + void *inp, + size_t &inSize, // in/out + void *outp, + size_t &outSize); // in/out + void final( + CssmData &out); + + size_t inputSize( + size_t outSize); // input for given output size + size_t outputSize( + bool final = false, + size_t inSize = 0); // output for given input size + void minimumProgress( + size_t &in, + size_t &out); // minimum progress chunks + +private: + comcryptObj mCcObj; + + /* + * For first implementation, we have to cope with the fact that the final + * decrypt call down to the comcryption engine requires *some* ciphertext. + * On decrypt, we'll just save one byte on each update in preparation for + * the final call. Hopefull we'll have time to fix deComcryptData() so this + * is unneccesary. + */ + unsigned char mDecryptBuf; + bool mDecryptBufValid; + +}; /* RC4Context */ + +#endif /*_ASC_CONTEXT_H_ */ +#endif /* ASC_CSP_ENABLE */ diff --git a/Security/libsecurity_apple_csp/lib/ascFactory.h b/Security/libsecurity_apple_csp/lib/ascFactory.h new file mode 100644 index 00000000..5929cd48 --- /dev/null +++ b/Security/libsecurity_apple_csp/lib/ascFactory.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2001,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifdef ASC_CSP_ENABLE + +#ifndef _ASC_ALG_FACTORY_H_ +#define _ASC_ALG_FACTORY_H_ + +#include +#include "AppleCSP.h" + +class AppleCSPSession; + +/* Algorithm factory */ +class AscAlgFactory : public AppleCSPAlgorithmFactory { +public: + + AscAlgFactory( + Allocator *normAlloc, + Allocator *privAlloc); + ~AscAlgFactory() { } + + bool setup( + AppleCSPSession &session, + CSPFullPluginSession::CSPContext * &cspCtx, + const Context &context); + +}; + + +#endif /*_ASC_ALG_FACTORY_H_ */ +#endif /* ASC_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/bfContext.cpp b/Security/libsecurity_apple_csp/lib/bfContext.cpp similarity index 96% rename from libsecurity_apple_csp/lib/bfContext.cpp rename to Security/libsecurity_apple_csp/lib/bfContext.cpp index 8c809b5c..f6a31eb5 100644 --- a/libsecurity_apple_csp/lib/bfContext.cpp +++ b/Security/libsecurity_apple_csp/lib/bfContext.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * bfContext.cpp - glue between BlockCrytpor and ssleay Blowfish * implementation - * Written by Doug Mitchell 4/23/2003 */ #include "bfContext.h" diff --git a/libsecurity_apple_csp/lib/bfContext.h b/Security/libsecurity_apple_csp/lib/bfContext.h similarity index 95% rename from libsecurity_apple_csp/lib/bfContext.h rename to Security/libsecurity_apple_csp/lib/bfContext.h index 15525f14..8d995ab3 100644 --- a/libsecurity_apple_csp/lib/bfContext.h +++ b/Security/libsecurity_apple_csp/lib/bfContext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * bfContext.h - glue between BlockCrytpor and ssleay Blowfish * implementation - * Written by Doug Mitchell 4/23/2003 */ #ifndef _BF_CONTEXT_H_ diff --git a/libsecurity_apple_csp/lib/boxes-ref.c b/Security/libsecurity_apple_csp/lib/boxes-ref.c similarity index 99% rename from libsecurity_apple_csp/lib/boxes-ref.c rename to Security/libsecurity_apple_csp/lib/boxes-ref.c index ddc63573..bc63bbda 100644 --- a/libsecurity_apple_csp/lib/boxes-ref.c +++ b/Security/libsecurity_apple_csp/lib/boxes-ref.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/Security/libsecurity_apple_csp/lib/boxes-ref.h b/Security/libsecurity_apple_csp/lib/boxes-ref.h new file mode 100644 index 00000000..f3445630 --- /dev/null +++ b/Security/libsecurity_apple_csp/lib/boxes-ref.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please obtain + * a copy of the License at http://www.apple.com/publicsource and read it before + * using this file. + * + * This 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. + */ + + +#ifndef _AES_BOXES_H_ +#define _AES_BOXES_H_ + +#include "rijndael-alg-ref.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define AES_MUL_BY_LOOKUP 1 + +#if AES_MUL_BY_LOOKUP +extern const word8 mulBy0x02[256]; +extern const word8 mulBy0x03[256]; +extern const word8 mulBy0x0e[256]; +extern const word8 mulBy0x0b[256]; +extern const word8 mulBy0x0d[256]; +extern const word8 mulBy0x09[256]; +#else +extern const unsigned char Logtable[256]; +extern const unsigned char Alogtable[256]; +#endif /* AES_MUL_BY_LOOKUP */ + +extern const unsigned char S[256]; +extern const unsigned char Si[256]; +extern const unsigned char iG[4][4]; +extern const unsigned long rcon[30]; + +#ifdef __cplusplus +} +#endif + +#endif /* _AES_BOXES_H_ */ diff --git a/libsecurity_apple_csp/lib/bsafeAsymmetric.cpp b/Security/libsecurity_apple_csp/lib/bsafeAsymmetric.cpp similarity index 97% rename from libsecurity_apple_csp/lib/bsafeAsymmetric.cpp rename to Security/libsecurity_apple_csp/lib/bsafeAsymmetric.cpp index 7cffdd25..e9b06e93 100644 --- a/libsecurity_apple_csp/lib/bsafeAsymmetric.cpp +++ b/Security/libsecurity_apple_csp/lib/bsafeAsymmetric.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/bsafeContext.cpp b/Security/libsecurity_apple_csp/lib/bsafeContext.cpp similarity index 99% rename from libsecurity_apple_csp/lib/bsafeContext.cpp rename to Security/libsecurity_apple_csp/lib/bsafeContext.cpp index a58f2afd..e69c8bd8 100644 --- a/libsecurity_apple_csp/lib/bsafeContext.cpp +++ b/Security/libsecurity_apple_csp/lib/bsafeContext.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/bsafeKeyGen.cpp b/Security/libsecurity_apple_csp/lib/bsafeKeyGen.cpp similarity index 99% rename from libsecurity_apple_csp/lib/bsafeKeyGen.cpp rename to Security/libsecurity_apple_csp/lib/bsafeKeyGen.cpp index 8e76232d..2e5391ff 100644 --- a/libsecurity_apple_csp/lib/bsafeKeyGen.cpp +++ b/Security/libsecurity_apple_csp/lib/bsafeKeyGen.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/bsafePKCS1.cpp b/Security/libsecurity_apple_csp/lib/bsafePKCS1.cpp similarity index 98% rename from libsecurity_apple_csp/lib/bsafePKCS1.cpp rename to Security/libsecurity_apple_csp/lib/bsafePKCS1.cpp index 1c7e0196..6eebba27 100644 --- a/libsecurity_apple_csp/lib/bsafePKCS1.cpp +++ b/Security/libsecurity_apple_csp/lib/bsafePKCS1.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/bsafePKCS1.h b/Security/libsecurity_apple_csp/lib/bsafePKCS1.h similarity index 96% rename from libsecurity_apple_csp/lib/bsafePKCS1.h rename to Security/libsecurity_apple_csp/lib/bsafePKCS1.h index 9a10f80e..c65c0130 100644 --- a/libsecurity_apple_csp/lib/bsafePKCS1.h +++ b/Security/libsecurity_apple_csp/lib/bsafePKCS1.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/bsafeSymmetric.cpp b/Security/libsecurity_apple_csp/lib/bsafeSymmetric.cpp similarity index 99% rename from libsecurity_apple_csp/lib/bsafeSymmetric.cpp rename to Security/libsecurity_apple_csp/lib/bsafeSymmetric.cpp index 5d7280ef..db15758c 100644 --- a/libsecurity_apple_csp/lib/bsafeSymmetric.cpp +++ b/Security/libsecurity_apple_csp/lib/bsafeSymmetric.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/bsafecsp.h b/Security/libsecurity_apple_csp/lib/bsafecsp.h similarity index 96% rename from libsecurity_apple_csp/lib/bsafecsp.h rename to Security/libsecurity_apple_csp/lib/bsafecsp.h index cfe21a59..14d4511f 100644 --- a/libsecurity_apple_csp/lib/bsafecsp.h +++ b/Security/libsecurity_apple_csp/lib/bsafecsp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/bsafecspi.h b/Security/libsecurity_apple_csp/lib/bsafecspi.h similarity index 99% rename from libsecurity_apple_csp/lib/bsafecspi.h rename to Security/libsecurity_apple_csp/lib/bsafecspi.h index 9c649d7e..f5d6d4fa 100644 --- a/libsecurity_apple_csp/lib/bsafecspi.h +++ b/Security/libsecurity_apple_csp/lib/bsafecspi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/bsobjects.h b/Security/libsecurity_apple_csp/lib/bsobjects.h similarity index 97% rename from libsecurity_apple_csp/lib/bsobjects.h rename to Security/libsecurity_apple_csp/lib/bsobjects.h index 4b8ad096..0491af22 100644 --- a/libsecurity_apple_csp/lib/bsobjects.h +++ b/Security/libsecurity_apple_csp/lib/bsobjects.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/castContext.cpp b/Security/libsecurity_apple_csp/lib/castContext.cpp similarity index 97% rename from libsecurity_apple_csp/lib/castContext.cpp rename to Security/libsecurity_apple_csp/lib/castContext.cpp index 503d667e..ed7e6052 100644 --- a/libsecurity_apple_csp/lib/castContext.cpp +++ b/Security/libsecurity_apple_csp/lib/castContext.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/castContext.h b/Security/libsecurity_apple_csp/lib/castContext.h similarity index 96% rename from libsecurity_apple_csp/lib/castContext.h rename to Security/libsecurity_apple_csp/lib/castContext.h index 5d3d1fd1..928c19a4 100644 --- a/libsecurity_apple_csp/lib/castContext.h +++ b/Security/libsecurity_apple_csp/lib/castContext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -20,7 +20,6 @@ * castContext.h - glue between BlockCrytpor and ssleay CAST-128 (CAST5) * implementation * - * Written by Doug Mitchell 4/24/2003 * * Here's what RFC 2144 has to say about CAST128 and CAST5 nomenclature: * diff --git a/libsecurity_apple_csp/lib/cryptkitcsp.cpp b/Security/libsecurity_apple_csp/lib/cryptkitcsp.cpp similarity index 98% rename from libsecurity_apple_csp/lib/cryptkitcsp.cpp rename to Security/libsecurity_apple_csp/lib/cryptkitcsp.cpp index 300d0d30..8f4ebbd7 100644 --- a/libsecurity_apple_csp/lib/cryptkitcsp.cpp +++ b/Security/libsecurity_apple_csp/lib/cryptkitcsp.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/cryptkitcsp.h b/Security/libsecurity_apple_csp/lib/cryptkitcsp.h similarity index 96% rename from libsecurity_apple_csp/lib/cryptkitcsp.h rename to Security/libsecurity_apple_csp/lib/cryptkitcsp.h index 1494a8d4..cab8645a 100644 --- a/libsecurity_apple_csp/lib/cryptkitcsp.h +++ b/Security/libsecurity_apple_csp/lib/cryptkitcsp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/cspdebugging.c b/Security/libsecurity_apple_csp/lib/cspdebugging.c similarity index 92% rename from libsecurity_apple_csp/lib/cspdebugging.c rename to Security/libsecurity_apple_csp/lib/cspdebugging.c index a06bcf20..cbc0533f 100644 --- a/libsecurity_apple_csp/lib/cspdebugging.c +++ b/Security/libsecurity_apple_csp/lib/cspdebugging.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -21,9 +21,8 @@ Contains: Debugging support. - Written by: Doug Mitchell - Copyright: (c) 1998 by Apple Computer, Inc., all rights reserved. + Copyright (c) 1998,2011,2013-2014 Apple Inc. All Rights Reserved. Change History (most recent first): diff --git a/libsecurity_apple_csp/lib/cspdebugging.h b/Security/libsecurity_apple_csp/lib/cspdebugging.h similarity index 96% rename from libsecurity_apple_csp/lib/cspdebugging.h rename to Security/libsecurity_apple_csp/lib/cspdebugging.h index 9492d274..8648f239 100644 --- a/libsecurity_apple_csp/lib/cspdebugging.h +++ b/Security/libsecurity_apple_csp/lib/cspdebugging.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -21,9 +21,8 @@ Contains: Debugging macros. - Written by: Doug Mitchell - Copyright: (c) 1998 by Apple Computer, Inc., all rights reserved. + Copyright (c) 1998,2011,2013-2014 Apple Inc. All Rights Reserved. Change History (most recent first): diff --git a/libsecurity_apple_csp/lib/cssmplugin.exp b/Security/libsecurity_apple_csp/lib/cssmplugin.exp similarity index 100% rename from libsecurity_apple_csp/lib/cssmplugin.exp rename to Security/libsecurity_apple_csp/lib/cssmplugin.exp diff --git a/libsecurity_apple_csp/lib/deriveKey.cpp b/Security/libsecurity_apple_csp/lib/deriveKey.cpp similarity index 98% rename from libsecurity_apple_csp/lib/deriveKey.cpp rename to Security/libsecurity_apple_csp/lib/deriveKey.cpp index f329020c..55a88372 100644 --- a/libsecurity_apple_csp/lib/deriveKey.cpp +++ b/Security/libsecurity_apple_csp/lib/deriveKey.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -21,9 +21,8 @@ Contains: CSSM_DeriveKey functions - Copyright: (C) 2000 by Apple Computer, Inc., all rights reserved + Copyright (c) 2000,2011-2012,2014 Apple Inc. All Rights Reserved. - Written by: Doug Mitchell */ #include diff --git a/libsecurity_apple_csp/lib/desContext.cpp b/Security/libsecurity_apple_csp/lib/desContext.cpp similarity index 98% rename from libsecurity_apple_csp/lib/desContext.cpp rename to Security/libsecurity_apple_csp/lib/desContext.cpp index 6b546d29..2e93686a 100644 --- a/libsecurity_apple_csp/lib/desContext.cpp +++ b/Security/libsecurity_apple_csp/lib/desContext.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -18,7 +18,6 @@ /* * desContext.cpp - glue between BlockCrytpor and DES implementation - * Written by Doug Mitchell 3/28/2001 */ #include "desContext.h" diff --git a/libsecurity_apple_csp/lib/desContext.h b/Security/libsecurity_apple_csp/lib/desContext.h similarity index 96% rename from libsecurity_apple_csp/lib/desContext.h rename to Security/libsecurity_apple_csp/lib/desContext.h index bd52b145..a6fde7d2 100644 --- a/libsecurity_apple_csp/lib/desContext.h +++ b/Security/libsecurity_apple_csp/lib/desContext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -18,7 +18,6 @@ /* * desContext.h - glue between BlockCrytpor and DES/3DES implementations - * Written by Doug Mitchell 3/28/2001 */ #ifndef _DES_CONTEXT_H_ #define _DES_CONTEXT_H_ diff --git a/libsecurity_apple_csp/lib/gladmanContext.cpp b/Security/libsecurity_apple_csp/lib/gladmanContext.cpp similarity index 97% rename from libsecurity_apple_csp/lib/gladmanContext.cpp rename to Security/libsecurity_apple_csp/lib/gladmanContext.cpp index 16fddca7..64a2a4e9 100644 --- a/libsecurity_apple_csp/lib/gladmanContext.cpp +++ b/Security/libsecurity_apple_csp/lib/gladmanContext.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -18,7 +18,6 @@ /* * gladmanContext.cpp - glue between BlockCryptor and Gladman AES implementation - * Written by Doug Mitchell 12/12/2001 */ #include "gladmanContext.h" diff --git a/libsecurity_apple_csp/lib/gladmanContext.h b/Security/libsecurity_apple_csp/lib/gladmanContext.h similarity index 97% rename from libsecurity_apple_csp/lib/gladmanContext.h rename to Security/libsecurity_apple_csp/lib/gladmanContext.h index 87a8d329..6b1586b7 100644 --- a/libsecurity_apple_csp/lib/gladmanContext.h +++ b/Security/libsecurity_apple_csp/lib/gladmanContext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/memory.cpp b/Security/libsecurity_apple_csp/lib/memory.cpp similarity index 96% rename from libsecurity_apple_csp/lib/memory.cpp rename to Security/libsecurity_apple_csp/lib/memory.cpp index 9de47bec..036db142 100644 --- a/libsecurity_apple_csp/lib/memory.cpp +++ b/Security/libsecurity_apple_csp/lib/memory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/miscAlgFactory.cpp b/Security/libsecurity_apple_csp/lib/miscAlgFactory.cpp similarity index 98% rename from libsecurity_apple_csp/lib/miscAlgFactory.cpp rename to Security/libsecurity_apple_csp/lib/miscAlgFactory.cpp index 9ce82235..89b81d2c 100644 --- a/libsecurity_apple_csp/lib/miscAlgFactory.cpp +++ b/Security/libsecurity_apple_csp/lib/miscAlgFactory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -18,7 +18,6 @@ // // miscAlgFactory.h - miscellaneous algorithm factory -// Written by Doug Mitchell 3/28/2001 // #include "miscAlgFactory.h" diff --git a/libsecurity_apple_csp/lib/miscAlgFactory.h b/Security/libsecurity_apple_csp/lib/miscAlgFactory.h similarity index 93% rename from libsecurity_apple_csp/lib/miscAlgFactory.h rename to Security/libsecurity_apple_csp/lib/miscAlgFactory.h index 6a0eec7a..39fc5444 100644 --- a/libsecurity_apple_csp/lib/miscAlgFactory.h +++ b/Security/libsecurity_apple_csp/lib/miscAlgFactory.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -18,7 +18,6 @@ // // miscAlgFactory.h - miscellaneous algorithm factory -// Written by Doug Mitchell 3/28/2001 // #ifndef _MISC_ALG_FACTORY_H_ #define _MISC_ALG_FACTORY_H_ diff --git a/libsecurity_apple_csp/lib/miscalgorithms.cpp b/Security/libsecurity_apple_csp/lib/miscalgorithms.cpp similarity index 98% rename from libsecurity_apple_csp/lib/miscalgorithms.cpp rename to Security/libsecurity_apple_csp/lib/miscalgorithms.cpp index 4934cf22..10832749 100644 --- a/libsecurity_apple_csp/lib/miscalgorithms.cpp +++ b/Security/libsecurity_apple_csp/lib/miscalgorithms.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/opensshCoding.cpp b/Security/libsecurity_apple_csp/lib/opensshCoding.cpp similarity index 99% rename from libsecurity_apple_csp/lib/opensshCoding.cpp rename to Security/libsecurity_apple_csp/lib/opensshCoding.cpp index f331813b..e9f90ba3 100644 --- a/libsecurity_apple_csp/lib/opensshCoding.cpp +++ b/Security/libsecurity_apple_csp/lib/opensshCoding.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -25,7 +25,6 @@ /* * opensshCoding.cpp - Encoding and decoding of OpenSSH format public keys. * - * Created 8/29/2006 by dmitch. */ #include "opensshCoding.h" diff --git a/libsecurity_apple_csp/lib/opensshCoding.h b/Security/libsecurity_apple_csp/lib/opensshCoding.h similarity index 96% rename from libsecurity_apple_csp/lib/opensshCoding.h rename to Security/libsecurity_apple_csp/lib/opensshCoding.h index 61d4f76c..246a487e 100644 --- a/libsecurity_apple_csp/lib/opensshCoding.h +++ b/Security/libsecurity_apple_csp/lib/opensshCoding.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -24,7 +24,6 @@ /* * opensshCoding.h - Encoding and decoding of OpenSSH format public keys. * - * Created 8/29/2006 by dmitch. */ #ifndef _OPENSSH_CODING_H_ diff --git a/libsecurity_apple_csp/lib/opensshWrap.cpp b/Security/libsecurity_apple_csp/lib/opensshWrap.cpp similarity index 99% rename from libsecurity_apple_csp/lib/opensshWrap.cpp rename to Security/libsecurity_apple_csp/lib/opensshWrap.cpp index 18f448ee..fba13d70 100644 --- a/libsecurity_apple_csp/lib/opensshWrap.cpp +++ b/Security/libsecurity_apple_csp/lib/opensshWrap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -24,7 +24,6 @@ /* * opensshCoding.h - Encoding and decoding of OpenSSH format public keys. * - * Created 8/29/2006 by dmitch. */ #include "AppleCSPSession.h" diff --git a/Security/libsecurity_apple_csp/lib/pbkdDigest.cpp b/Security/libsecurity_apple_csp/lib/pbkdDigest.cpp new file mode 100644 index 00000000..84433e30 --- /dev/null +++ b/Security/libsecurity_apple_csp/lib/pbkdDigest.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2003,2011,2014 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please + * obtain a copy of the License at http://www.apple.com/publicsource and + * read it before using this file. + * + * This 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. + */ +/* + * pbkdDigest.cpp - SHA1/MD5 digest object for HMAC and PBE routines + */ + +#include "pbkdDigest.h" +#include +#include + +/* the casts are necessary to cover the polymorphous context types */ +DigestOps Md2Ops = { + (DigestInitFcn)CC_MD2_Init, + (DigestUpdateFcn)CC_MD2_Update, + (DigestFinalFcn)CC_MD2_Final +}; +DigestOps Md5Ops = { + (DigestInitFcn)CC_MD5_Init, + (DigestUpdateFcn)CC_MD5_Update, + (DigestFinalFcn)CC_MD5_Final +}; +DigestOps Sha1Ops = { + (DigestInitFcn)CC_SHA1_Init, + (DigestUpdateFcn)CC_SHA1_Update, + (DigestFinalFcn)CC_SHA1_Final +}; + +/* Ops on a DigestCtx - all return zero on error, like the underlying digests do */ +int DigestCtxInit( + DigestCtx *ctx, + CSSM_ALGORITHMS hashAlg) +{ + switch(hashAlg) { + case CSSM_ALGID_SHA1: + ctx->ops = &Sha1Ops; + break; + case CSSM_ALGID_MD5: + ctx->ops = &Md5Ops; + break; + case CSSM_ALGID_MD2: + ctx->ops = &Md2Ops; + break; + default: + return 0; + } + ctx->hashAlg = hashAlg; + return ctx->ops->init(&ctx->dig); +} + +void DigestCtxFree( + DigestCtx *ctx) +{ + memset(ctx, 0, sizeof(DigestCtx)); +} + +int DigestCtxUpdate( + DigestCtx *ctx, + const void *textPtr, + uint32 textLen) +{ + return ctx->ops->update(&ctx->dig, textPtr, textLen); +} + +int DigestCtxFinal( + DigestCtx *ctx, + void *digest) +{ + return ctx->ops->final(digest, &ctx->dig); +} diff --git a/Security/libsecurity_apple_csp/lib/pbkdDigest.h b/Security/libsecurity_apple_csp/lib/pbkdDigest.h new file mode 100644 index 00000000..cb7a2974 --- /dev/null +++ b/Security/libsecurity_apple_csp/lib/pbkdDigest.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2003,2011,2014 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please + * obtain a copy of the License at http://www.apple.com/publicsource and + * read it before using this file. + * + * This 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. + */ +/* + * pbkdDigest.h - SHA1/MD5 digest object for HMAC and PBE routines + */ + +#ifndef _PBKD_DIGEST_H_ +#define _PBKD_DIGEST_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define kSHA1DigestSize CC_SHA1_DIGEST_LENGTH +#define kSHA1BlockSize CC_SHA1_BLOCK_BYTES + +#define kMD5DigestSize CC_MD5_DIGEST_LENGTH +#define kMD5BlockSize CC_MD5_BLOCK_BYTES + +#define kMD2DigestSize CC_MD2_DIGEST_LENGTH +#define kMD2BlockSize CC_MD2_BLOCK_BYTES + +#define kMaxDigestSize kSHA1DigestSize + +typedef int (*DigestInitFcn)(void *ctx); +typedef int (*DigestUpdateFcn)(void *ctx, const void *data, unsigned long len); +typedef int (*DigestFinalFcn)(void *md, void *c); + +/* callouts to eay/libmd implementations */ +typedef struct { + DigestInitFcn init; + DigestUpdateFcn update; + DigestFinalFcn final; +} DigestOps; + +typedef struct { + union { + CC_SHA1_CTX sha1Context; + CC_MD5_CTX md5Context; + CC_MD2_CTX md2Context; + } dig; + DigestOps *ops; + CSSM_ALGORITHMS hashAlg; +} DigestCtx; + +/* Ops on a DigestCtx - all return zero on error, like the underlying digests do */ +int DigestCtxInit( + DigestCtx *ctx, + CSSM_ALGORITHMS hashAlg); +void DigestCtxFree( + DigestCtx *ctx); +int DigestCtxUpdate( + DigestCtx *ctx, + const void *textPtr, + uint32 textLen); +int DigestCtxFinal( + DigestCtx *ctx, + void *digest); + +#ifdef __cplusplus +} +#endif + +#endif /* _PBKD_DIGEST_H_ */ + diff --git a/Security/libsecurity_apple_csp/lib/pbkdf2.c b/Security/libsecurity_apple_csp/lib/pbkdf2.c new file mode 100644 index 00000000..de2f63e0 --- /dev/null +++ b/Security/libsecurity_apple_csp/lib/pbkdf2.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please obtain + * a copy of the License at http://www.apple.com/publicsource and read it before + * using this file. + * + * This 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. + */ + + +/* + File: pbkdf2.c + Contains: Apple Data Security Services PKCS #5 PBKDF2 function definition. + Copyright (c) 1999,2011,2013-2014 Apple Inc. All Rights Reserved. +*/ +#include "pbkdf2.h" +#include +#include +/* Will write hLen bytes into dataPtr according to PKCS #5 2.0 spec. + See: http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-5.html for details. + tempBuffer is a pointer to at least MAX (hLen, saltLen + 4) + hLen bytes. */ +static void +F (PRF prf, uint32 hLen, + const void *passwordPtr, uint32 passwordLen, + const void *saltPtr, uint32 saltLen, + uint32 iterationCount, + uint32 blockNumber, + void *dataPtr, + void *tempBuffer) +{ + uint8 *inBlock, *outBlock, *resultBlockPtr; + uint32 iteration; + outBlock = (uint8*)tempBuffer; + inBlock = outBlock + hLen; + /* Set up inBlock to contain Salt || INT (blockNumber). */ + memcpy (inBlock, saltPtr, saltLen); + + inBlock[saltLen + 0] = (uint8)(blockNumber >> 24); + inBlock[saltLen + 1] = (uint8)(blockNumber >> 16); + inBlock[saltLen + 2] = (uint8)(blockNumber >> 8); + inBlock[saltLen + 3] = (uint8)(blockNumber); + + /* Caculate U1 (result goes to outBlock) and copy it to resultBlockPtr. */ + resultBlockPtr = (uint8*)dataPtr; + prf (passwordPtr, passwordLen, inBlock, saltLen + 4, outBlock); + memcpy (resultBlockPtr, outBlock, hLen); + /* Calculate U2 though UiterationCount. */ + for (iteration = 2; iteration <= iterationCount; iteration++) + { + uint8 *tempBlock; + uint32 byte; + /* Swap inBlock and outBlock pointers. */ + tempBlock = inBlock; + inBlock = outBlock; + outBlock = tempBlock; + /* Now inBlock conatins Uiteration-1. Calclulate Uiteration into outBlock. */ + prf (passwordPtr, passwordLen, inBlock, hLen, outBlock); + /* Xor data in dataPtr (U1 \xor U2 \xor ... \xor Uiteration-1) with + outBlock (Uiteration). */ + for (byte = 0; byte < hLen; byte++) + resultBlockPtr[byte] ^= outBlock[byte]; + } +} +void pbkdf2 (PRF prf, uint32 hLen, + const void *passwordPtr, uint32 passwordLen, + const void *saltPtr, uint32 saltLen, + uint32 iterationCount, + void *dkPtr, uint32 dkLen, + void *tempBuffer) +{ + uint32 completeBlocks = dkLen / hLen; + uint32 partialBlockSize = dkLen % hLen; + uint32 blockNumber; + uint8 *dataPtr = (uint8*)dkPtr; + uint8 *blkBuffer = (uint8*)tempBuffer; + /* First calculate all the complete hLen sized blocks required. */ + for (blockNumber = 1; blockNumber <= completeBlocks; blockNumber++) + { + F (prf, hLen, passwordPtr, passwordLen, saltPtr, saltLen, + iterationCount, blockNumber, dataPtr, blkBuffer + hLen); + dataPtr += hLen; + } + /* Finally if the requested output size was not an even multiple of hLen, calculate + the final block and copy the first partialBlockSize bytes of it to the output. */ + if (partialBlockSize > 0) + { + F (prf, hLen, passwordPtr, passwordLen, saltPtr, saltLen, + iterationCount, blockNumber, blkBuffer, blkBuffer + hLen); + memcpy (dataPtr, blkBuffer, partialBlockSize); + } +} diff --git a/Security/libsecurity_apple_csp/lib/pbkdf2.h b/Security/libsecurity_apple_csp/lib/pbkdf2.h new file mode 100644 index 00000000..55b93ae9 --- /dev/null +++ b/Security/libsecurity_apple_csp/lib/pbkdf2.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please obtain + * a copy of the License at http://www.apple.com/publicsource and read it before + * using this file. + * + * This 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. + */ + + +/* + File: pbkdf2.h + Contains: Apple Data Security Services PKCS #5 PBKDF2 function declaration. + Copyright (c) 1999,2011,2014 Apple Inc. All Rights Reserved. +*/ + +#ifndef __PBKDF2__ +#define __PBKDF2__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* This function should generate a pseudo random octect stream + of hLen bytes long (The value hLen is specified as an argument to pbkdf2 + and should be constant for any given prf function.) which is output in the buffer + pointed to by randomPtr (the caller of this function is responsible for allocation + of the buffer). + The inputs to the pseudo random function are the first keyLen octets pointed + to by keyPtr and the first textLen octets pointed to by textPtr. + Both keyLen and textLen can have any nonzero value. + A good prf would be a HMAC-SHA-1 algorithm where the keyPtr octets serve as + HMAC's "key" and the textPtr octets serve as HMAC's "text". */ +typedef void (*PRF)(const void *keyPtr, uint32 keyLen, + const void *textPtr, uint32 textLen, + void *randomPtr); + +/* This function implements the PBKDF2 key derrivation algorithm described in + http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-5.html + The output is a derived key of dkLen bytes which is written to the buffer + pointed to by dkPtr. + The caller should ensure dkPtr is at least dkLen bytes long. + The Key is derived from passwordPtr (which is passwordLen bytes long) and from + saltPtr (which is saltLen bytes long). The algorithm used is desacribed in + PKCS #5 version 2.0 and iterationCount iterations are performed. + The argument prf is a pointer to a psuedo random number generator declared above. + It should write exactly hLen bytes into its output buffer each time it is called. + The argument tempBuffer should point to a buffer MAX (hLen, saltLen + 4) + 2 * hLen + bytes long. This buffer is used during the calculation for intermediate results. + Security Considerations: + The argument saltPtr should be a pointer to a buffer of at least 8 random bytes + (64 bits). Thus saltLen should be >= 8. + For each session a new salt should be generated. + The value of iterationCount should be at least 1000 (one thousand). + A good prf would be a HMAC-SHA-1 algorithm where the password serves as + HMAC's "key" and the data serves as HMAC's "text". */ +void pbkdf2 (PRF prf, uint32 hLen, + const void *passwordPtr, uint32 passwordLen, + const void *saltPtr, uint32 saltLen, + uint32 iterationCount, + void *dkPtr, uint32 dkLen, + void *tempBuffer); + +#ifdef __cplusplus +} +#endif + +#endif /* __PBKDF2__ */ diff --git a/libsecurity_apple_csp/lib/pkcs12Derive.cpp b/Security/libsecurity_apple_csp/lib/pkcs12Derive.cpp similarity index 99% rename from libsecurity_apple_csp/lib/pkcs12Derive.cpp rename to Security/libsecurity_apple_csp/lib/pkcs12Derive.cpp index 10d465b2..72ba60a9 100644 --- a/libsecurity_apple_csp/lib/pkcs12Derive.cpp +++ b/Security/libsecurity_apple_csp/lib/pkcs12Derive.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -18,7 +18,6 @@ /* * pkcs12Derive.cpp - PKCS12 PBE routine * - * Created 2/28/03 by Doug Mitchell. */ #include diff --git a/libsecurity_apple_csp/lib/pkcs12Derive.h b/Security/libsecurity_apple_csp/lib/pkcs12Derive.h similarity index 93% rename from libsecurity_apple_csp/lib/pkcs12Derive.h rename to Security/libsecurity_apple_csp/lib/pkcs12Derive.h index 893cc0ba..ebc57065 100644 --- a/libsecurity_apple_csp/lib/pkcs12Derive.h +++ b/Security/libsecurity_apple_csp/lib/pkcs12Derive.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * pkcs12Derive.cpp - PKCS12 PBE routine * - * Created 2/28/03 by Doug Mitchell. */ #ifndef _PKCS12_DERIVE_H_ diff --git a/libsecurity_apple_csp/lib/pkcs8.cpp b/Security/libsecurity_apple_csp/lib/pkcs8.cpp similarity index 98% rename from libsecurity_apple_csp/lib/pkcs8.cpp rename to Security/libsecurity_apple_csp/lib/pkcs8.cpp index d0dc5b8e..6d1a16c7 100644 --- a/libsecurity_apple_csp/lib/pkcs8.cpp +++ b/Security/libsecurity_apple_csp/lib/pkcs8.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/pkcs8.h b/Security/libsecurity_apple_csp/lib/pkcs8.h similarity index 95% rename from libsecurity_apple_csp/lib/pkcs8.h rename to Security/libsecurity_apple_csp/lib/pkcs8.h index d7e5810e..8caa6358 100644 --- a/libsecurity_apple_csp/lib/pkcs8.h +++ b/Security/libsecurity_apple_csp/lib/pkcs8.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/rc2Context.cpp b/Security/libsecurity_apple_csp/lib/rc2Context.cpp similarity index 97% rename from libsecurity_apple_csp/lib/rc2Context.cpp rename to Security/libsecurity_apple_csp/lib/rc2Context.cpp index d8810225..bf943c35 100644 --- a/libsecurity_apple_csp/lib/rc2Context.cpp +++ b/Security/libsecurity_apple_csp/lib/rc2Context.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -18,7 +18,6 @@ /* * rc2Context.cpp - glue between BlockCrytpor and ssleay RC2 implementation - * Written by Doug Mitchell 04/03/2001 */ #include diff --git a/libsecurity_apple_csp/lib/rc2Context.h b/Security/libsecurity_apple_csp/lib/rc2Context.h similarity index 94% rename from libsecurity_apple_csp/lib/rc2Context.h rename to Security/libsecurity_apple_csp/lib/rc2Context.h index b71c710a..24393729 100644 --- a/libsecurity_apple_csp/lib/rc2Context.h +++ b/Security/libsecurity_apple_csp/lib/rc2Context.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -18,7 +18,6 @@ /* * rc2Context.h - glue between BlockCrytpor and ssleay RC2 implementation - * Written by Doug Mitchell 4/3/2001 */ #ifndef _RC2_CONTEXT_H_ #define _RC2_CONTEXT_H_ diff --git a/libsecurity_apple_csp/lib/rc4Context.cpp b/Security/libsecurity_apple_csp/lib/rc4Context.cpp similarity index 96% rename from libsecurity_apple_csp/lib/rc4Context.cpp rename to Security/libsecurity_apple_csp/lib/rc4Context.cpp index 29ee478d..10e8da75 100644 --- a/libsecurity_apple_csp/lib/rc4Context.cpp +++ b/Security/libsecurity_apple_csp/lib/rc4Context.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -18,7 +18,6 @@ /* * rc4Context.cpp - glue between AppleCSPContext and ssleay RC4 implementation - * Written by Doug Mitchell 04/03/2001 */ #include "rc4Context.h" diff --git a/libsecurity_apple_csp/lib/rc4Context.h b/Security/libsecurity_apple_csp/lib/rc4Context.h similarity index 94% rename from libsecurity_apple_csp/lib/rc4Context.h rename to Security/libsecurity_apple_csp/lib/rc4Context.h index 71a5a69a..33ae6d01 100644 --- a/libsecurity_apple_csp/lib/rc4Context.h +++ b/Security/libsecurity_apple_csp/lib/rc4Context.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -18,7 +18,6 @@ /* * rc4Context.h - glue between BlockCrytpor and ssleay RC4 implementation - * Written by Doug Mitchell 4/3/2001 */ #ifndef _RC4_CONTEXT_H_ #define _RC4_CONTEXT_H_ diff --git a/libsecurity_apple_csp/lib/rc5Context.cpp b/Security/libsecurity_apple_csp/lib/rc5Context.cpp similarity index 96% rename from libsecurity_apple_csp/lib/rc5Context.cpp rename to Security/libsecurity_apple_csp/lib/rc5Context.cpp index 0b3566f4..b3f86524 100644 --- a/libsecurity_apple_csp/lib/rc5Context.cpp +++ b/Security/libsecurity_apple_csp/lib/rc5Context.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -18,7 +18,6 @@ /* * rc5Context.cpp - glue between BlockCrytpor and ssleay RC5 implementation - * Written by Doug Mitchell 04/03/2001 */ #include diff --git a/libsecurity_apple_csp/lib/rc5Context.h b/Security/libsecurity_apple_csp/lib/rc5Context.h similarity index 94% rename from libsecurity_apple_csp/lib/rc5Context.h rename to Security/libsecurity_apple_csp/lib/rc5Context.h index 423dca51..fa9182af 100644 --- a/libsecurity_apple_csp/lib/rc5Context.h +++ b/Security/libsecurity_apple_csp/lib/rc5Context.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -18,7 +18,6 @@ /* * rc5Context.h - glue between BlockCrytpor and ssleay RC5 implementation - * Written by Doug Mitchell 4/3/2001 */ #ifndef _RC5_CONTEXT_H_ #define _RC5_CONTEXT_H_ diff --git a/Security/libsecurity_apple_csp/lib/rijndael-alg-ref.c b/Security/libsecurity_apple_csp/lib/rijndael-alg-ref.c new file mode 100644 index 00000000..e0038a10 --- /dev/null +++ b/Security/libsecurity_apple_csp/lib/rijndael-alg-ref.c @@ -0,0 +1,619 @@ +/* + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please obtain + * a copy of the License at http://www.apple.com/publicsource and read it before + * using this file. + * + * This 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. + */ + + +/* rijndael-alg-ref.c v2.0 August '99 + * Reference ANSI C code + * authors: Paulo Barreto + * Vincent Rijmen + * + */ + +#include +#include +#include + +#include "rijndael-alg-ref.h" +#include + +#define SC ((BC - 4) >> 1) + +#include "boxes-ref.h" + +static const word8 shifts[3][4][2] = { + { { 0, 0 }, + { 1, 3 }, + { 2, 2 }, + { 3, 1 } + }, + { { 0, 0 }, + { 1, 5 }, + { 2, 4 }, + { 3, 3 } + }, + { { 0, 0 }, + { 1, 7 }, + { 3, 5 }, + { 4, 4 } + } +}; + +#if !GLADMAN_AES_128_ENABLE + +/* 128 bit key/word shift table in bits */ +static const word8 shifts128[4][2] = { + { 0, 0 }, + { 8, 24 }, + { 16, 16 }, + { 24, 8 } +}; + +#endif /* GLADMAN_AES_128_ENABLE */ + +#if !AES_MUL_BY_LOOKUP +/* + * Profiling measurements showed that the mul routine is where a large propertion of + * the time is spent. Since the first argument to mul is always one of six + * constants (2, 3, 0xe, etc.), we implement six 256x256 byte lookup tables to + * do the multiplies. This eliminates the need for the log/antilog tables, so + * it's only adding one kilobyte of const data. Throughput improvement for this + * mod is a factor of 3.3 for encrypt and 4.1 for decrypt in the 128-bit optimized + * case. Improvement for the general case (with a 256 bit key) is 1.46 for encrypt + * and 1.88 for decrypt. (Decrypt wins more for this enhancement because the + * InvMixColumn does four muls, vs. 2 muls for MixColumn). Measurements taken + * on a 500 MHz G4 with 1 MB of L2 cache. + */ + +/* + * The mod 255 op in mul is really expensive... + * + * We know that b <= (254 * 2), so there are only two cases. Either return b, + * or return b-255. + * + * On a G4 this single optimization results in a 24% speedup for encrypt and + * a 25% speedup for decrypt. + */ +static inline word8 mod255(word32 b) +{ + if(b >= 255) { + b -= 255; + } + return b; +} + +word8 mul(word8 a, word8 b) { + /* multiply two elements of GF(2^m) + * needed for MixColumn and InvMixColumn + */ + if (a && b) return Alogtable[mod255(Logtable[a] + Logtable[b])]; + else return 0; +} +#endif /* !AES_MUL_BY_LOOKUP */ + +static +void KeyAddition(word8 a[4][MAXBC], word8 rk[4][MAXBC], word8 BC) { + /* Exor corresponding text input and round key input bytes + */ + int i, j; + + for(i = 0; i < 4; i++) + for(j = 0; j < BC; j++) a[i][j] ^= rk[i][j]; +} + +static +void ShiftRow(word8 a[4][MAXBC], word8 d, word8 BC) { + /* Row 0 remains unchanged + * The other three rows are shifted a variable amount + */ + word8 tmp[MAXBC]; + int i, j; + + for(i = 1; i < 4; i++) { + for(j = 0; j < BC; j++) tmp[j] = a[i][(j + shifts[SC][i][d]) % BC]; + for(j = 0; j < BC; j++) a[i][j] = tmp[j]; + } +} + +static +void Substitution(word8 a[4][MAXBC], const word8 box[256], word8 BC) { + /* Replace every byte of the input by the byte at that place + * in the nonlinear S-box + */ + int i, j; + + for(i = 0; i < 4; i++) + for(j = 0; j < BC; j++) a[i][j] = box[a[i][j]] ; +} + +static +void MixColumn(word8 a[4][MAXBC], word8 BC) { + /* Mix the four bytes of every column in a linear way + */ + word8 b[4][MAXBC]; + int i, j; + + for(j = 0; j < BC; j++) { + for(i = 0; i < 4; i++) { + #if AES_MUL_BY_LOOKUP + b[i][j] = mulBy0x02[a[i][j]] + ^ mulBy0x03[a[(i + 1) % 4][j]] + ^ a[(i + 2) % 4][j] + ^ a[(i + 3) % 4][j]; + #else + b[i][j] = mul(2,a[i][j]) + ^ mul(3,a[(i + 1) % 4][j]) + ^ a[(i + 2) % 4][j] + ^ a[(i + 3) % 4][j]; + #endif + } + } + for(i = 0; i < 4; i++) { + for(j = 0; j < BC; j++) a[i][j] = b[i][j]; + } +} + +static +void InvMixColumn(word8 a[4][MAXBC], word8 BC) { + /* Mix the four bytes of every column in a linear way + * This is the opposite operation of Mixcolumn + */ + word8 b[4][MAXBC]; + int i, j; + + for(j = 0; j < BC; j++) { + for(i = 0; i < 4; i++) { + #if AES_MUL_BY_LOOKUP + b[i][j] = mulBy0x0e[a[i][j]] + ^ mulBy0x0b[a[(i + 1) % 4][j]] + ^ mulBy0x0d[a[(i + 2) % 4][j]] + ^ mulBy0x09[a[(i + 3) % 4][j]]; + #else + b[i][j] = mul(0xe,a[i][j]) + ^ mul(0xb,a[(i + 1) % 4][j]) + ^ mul(0xd,a[(i + 2) % 4][j]) + ^ mul(0x9,a[(i + 3) % 4][j]); + #endif + } + } + for(i = 0; i < 4; i++) { + for(j = 0; j < BC; j++) a[i][j] = b[i][j]; + } +} + +int rijndaelKeySched ( + word8 k[4][MAXKC], + int keyBits, + int blockBits, + word8 W[MAXROUNDS+1][4][MAXBC]) { + + /* Calculate the necessary round keys + * The number of calculations depends on keyBits and blockBits + */ + int KC, BC, ROUNDS; + int i, j, t, rconpointer = 0; + word8 tk[4][MAXKC]; + + switch (keyBits) { + case 128: KC = 4; break; + case 192: KC = 6; break; + case 256: KC = 8; break; + default : return (-1); + } + + switch (blockBits) { + case 128: BC = 4; break; + case 192: BC = 6; break; + case 256: BC = 8; break; + default : return (-2); + } + + switch (keyBits >= blockBits ? keyBits : blockBits) { + case 128: ROUNDS = 10; break; + case 192: ROUNDS = 12; break; + case 256: ROUNDS = 14; break; + default : return (-3); /* this cannot happen */ + } + + + for(j = 0; j < KC; j++) + for(i = 0; i < 4; i++) + tk[i][j] = k[i][j]; + t = 0; + /* copy values into round key array */ + for(j = 0; (j < KC) && (t < (ROUNDS+1)*BC); j++, t++) + for(i = 0; i < 4; i++) W[t / BC][i][t % BC] = tk[i][j]; + + while (t < (ROUNDS+1)*BC) { /* while not enough round key material calculated */ + /* calculate new values */ + for(i = 0; i < 4; i++) + tk[i][0] ^= S[tk[(i+1)%4][KC-1]]; + tk[0][0] ^= rcon[rconpointer++]; + + if (KC != 8) + for(j = 1; j < KC; j++) + for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1]; + else { + for(j = 1; j < KC/2; j++) + for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1]; + for(i = 0; i < 4; i++) tk[i][KC/2] ^= S[tk[i][KC/2 - 1]]; + for(j = KC/2 + 1; j < KC; j++) + for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1]; + } + /* copy values into round key array */ + for(j = 0; (j < KC) && (t < (ROUNDS+1)*BC); j++, t++) + for(i = 0; i < 4; i++) W[t / BC][i][t % BC] = tk[i][j]; + } + + return 0; +} + +int rijndaelEncrypt ( + word8 a[4][MAXBC], + int keyBits, + int blockBits, + word8 rk[MAXROUNDS+1][4][MAXBC]) +{ + /* Encryption of one block, general case. + */ + int r, BC, ROUNDS; + + switch (blockBits) { + case 128: BC = 4; break; + case 192: BC = 6; break; + case 256: BC = 8; break; + default : return (-2); + } + + switch (keyBits >= blockBits ? keyBits : blockBits) { + case 128: ROUNDS = 10; break; + case 192: ROUNDS = 12; break; + case 256: ROUNDS = 14; break; + default : return (-3); /* this cannot happen */ + } + + /* begin with a key addition + */ + KeyAddition(a,rk[0],BC); + + /* ROUNDS-1 ordinary rounds + */ + for(r = 1; r < ROUNDS; r++) { + Substitution(a,S,BC); + ShiftRow(a,0,BC); + MixColumn(a,BC); + KeyAddition(a,rk[r],BC); + } + + /* Last round is special: there is no MixColumn + */ + Substitution(a,S,BC); + ShiftRow(a,0,BC); + KeyAddition(a,rk[ROUNDS],BC); + + return 0; +} + +int rijndaelDecrypt ( + word8 a[4][MAXBC], + int keyBits, + int blockBits, + word8 rk[MAXROUNDS+1][4][MAXBC]) +{ + int r, BC, ROUNDS; + + switch (blockBits) { + case 128: BC = 4; break; + case 192: BC = 6; break; + case 256: BC = 8; break; + default : return (-2); + } + + switch (keyBits >= blockBits ? keyBits : blockBits) { + case 128: ROUNDS = 10; break; + case 192: ROUNDS = 12; break; + case 256: ROUNDS = 14; break; + default : return (-3); /* this cannot happen */ + } + + /* To decrypt: apply the inverse operations of the encrypt routine, + * in opposite order + * + * (KeyAddition is an involution: it 's equal to its inverse) + * (the inverse of Substitution with table S is Substitution with the + * inverse table of S) + * (the inverse of Shiftrow is Shiftrow over a suitable distance) + */ + + /* First the special round: + * without InvMixColumn + * with extra KeyAddition + */ + KeyAddition(a,rk[ROUNDS],BC); + Substitution(a,Si,BC); + ShiftRow(a,1,BC); + + /* ROUNDS-1 ordinary rounds + */ + for(r = ROUNDS-1; r > 0; r--) { + KeyAddition(a,rk[r],BC); + InvMixColumn(a,BC); + Substitution(a,Si,BC); + ShiftRow(a,1,BC); + } + + /* End with the extra key addition + */ + + KeyAddition(a,rk[0],BC); + + return 0; +} + +#if !GLADMAN_AES_128_ENABLE + +/* + * All of these 128-bit-key-and-block routines require 32-bit word-aligned + * char array pointers.ÊThe key schedule arrays are easy; they come from + * keyInstance which has a 4-byte-aligned element preceeding the key schedule. + * Others require manual alignment of a local variable by the caller. + */ + +static inline void KeyAddition128( + word8 a[4][BC_128_OPT], + word8 rk[4][MAXBC]) { + + /* these casts are endian-independent */ + ((word32 *)a)[0] ^= *((word32 *)(&rk[0])); + ((word32 *)a)[1] ^= *((word32 *)(&rk[1])); + ((word32 *)a)[2] ^= *((word32 *)(&rk[2])); + ((word32 *)a)[3] ^= *((word32 *)(&rk[3])); +} + +static void Substitution128( + word8 a[4][BC_128_OPT], + const word8 box[256]) { + /* Replace every byte of the input by the byte at that place + * in the nonlinear S-box + */ + int i, j; + + /* still to be optimized - larger S boxes? */ + for(i = 0; i < 4; i++) { + for(j = 0; j < BC_128_OPT; j++) { + a[i][j] = box[a[i][j]]; + } + } +} + +#if defined(__ppc__) && defined(__GNUC__) + +static inline void rotateWordLeft( + word8 *word, // known to be word aligned + unsigned rotCount) // in bits +{ + word32 lword = *((word32 *)word); + asm("rlwnm %0,%1,%2,0,31" : "=r"(lword) : "0"(lword), "r"(rotCount)); + *((word32 *)word) = lword; +} + +#else + +/* + * Insert your machine/compiler dependent code here, + * or just use this, which works on any platform and compiler + * which supports the __attribute__((aligned(4))) directive. + */ +static void rotateWordLeft( + word8 *word, // known to be word aligned + unsigned rotCount) // in bits +{ + word8 tmp[BC_128_OPT] __attribute__((aligned(4))); + unsigned bytes = rotCount / 8; + + tmp[0] = word[bytes & (BC_128_OPT-1)]; + tmp[1] = word[(1+bytes) & (BC_128_OPT-1)]; + tmp[2] = word[(2+bytes) & (BC_128_OPT-1)]; + tmp[3] = word[(3+bytes) & (BC_128_OPT-1)]; + *((word32 *)word) = *((word32 *)tmp); +} +#endif + +static inline void ShiftRow128( + word8 a[4][BC_128_OPT], + word8 d) { + /* Row 0 remains unchanged + * The other three rows are shifted (actually rotated) a variable amount + */ + int i; + + for(i = 1; i < 4; i++) { + rotateWordLeft(a[i], shifts128[i][d]); + } +} + +/* + * The following two routines are where most of the time is spent in this + * module. Further optimization would have to focus here. + */ +static void MixColumn128(word8 a[4][BC_128_OPT]) { + /* Mix the four bytes of every column in a linear way + */ + word8 b[4][BC_128_OPT]; + int i, j; + + for(j = 0; j < BC_128_OPT; j++) { + for(i = 0; i < 4; i++) { + #if AES_MUL_BY_LOOKUP + b[i][j] = mulBy0x02[a[i][j]] + ^ mulBy0x03[a[(i + 1) % 4][j]] + ^ a[(i + 2) % 4][j] + ^ a[(i + 3) % 4][j]; + #else + b[i][j] = mul(2,a[i][j]) + ^ mul(3,a[(i + 1) % 4][j]) + ^ a[(i + 2) % 4][j] + ^ a[(i + 3) % 4][j]; + #endif + } + } + memmove(a, b, 4 * BC_128_OPT); +} + +static void InvMixColumn128(word8 a[4][BC_128_OPT]) { + /* Mix the four bytes of every column in a linear way + * This is the opposite operation of Mixcolumn + */ + word8 b[4][BC_128_OPT]; + int i, j; + + for(j = 0; j < BC_128_OPT; j++) { + for(i = 0; i < 4; i++) { + #if AES_MUL_BY_LOOKUP + b[i][j] = mulBy0x0e[a[i][j]] + ^ mulBy0x0b[a[(i + 1) % 4][j]] + ^ mulBy0x0d[a[(i + 2) % 4][j]] + ^ mulBy0x09[a[(i + 3) % 4][j]]; + #else + b[i][j] = mul(0xe,a[i][j]) + ^ mul(0xb,a[(i + 1) % 4][j]) + ^ mul(0xd,a[(i + 2) % 4][j]) + ^ mul(0x9,a[(i + 3) % 4][j]); + #endif + } + } + memmove(a, b, 4 * BC_128_OPT); +} + +int rijndaelKeySched128 ( + word8 k[4][KC_128_OPT], + word8 W[MAXROUNDS+1][4][MAXBC]) { + + /* Calculate the necessary round keys + * The number of calculations depends on keyBits and blockBits + */ + int i, j, t, rconpointer = 0; + word8 tk[4][KC_128_OPT]; + unsigned numSchedRows = (ROUNDS_128_OPT + 1) * BC_128_OPT; + + for(j = 0; j < KC_128_OPT; j++) + for(i = 0; i < 4; i++) + tk[i][j] = k[i][j]; + t = 0; + /* copy values into round key array */ + for(j = 0; (j < KC_128_OPT) && (t < numSchedRows); j++, t++) { + for(i = 0; i < 4; i++) { + W[t / BC_128_OPT][i][t % BC_128_OPT] = tk[i][j]; + } + } + + while (t < numSchedRows) { + /* while not enough round key material calculated */ + /* calculate new values */ + for(i = 0; i < 4; i++) { + tk[i][0] ^= S[tk[(i+1)%4][KC_128_OPT-1]]; + } + tk[0][0] ^= rcon[rconpointer++]; + + for(j = 1; j < KC_128_OPT; j++) { + for(i = 0; i < 4; i++) { + tk[i][j] ^= tk[i][j-1]; + } + } + + /* copy values into round key array */ + for(j = 0; (j < KC_128_OPT) && (t < numSchedRows); j++, t++) { + for(i = 0; i < 4; i++) { + W[t / BC_128_OPT][i][t % BC_128_OPT] = tk[i][j]; + } + } + } + + return 0; +} + +int rijndaelEncrypt128 ( + word8 a[4][BC_128_OPT], + word8 rk[MAXROUNDS+1][4][MAXBC]) +{ + /* Encryption of one block. + */ + int r; + + /* begin with a key addition + */ + KeyAddition128(a,rk[0]); + + /* ROUNDS-1 ordinary rounds + */ + for(r = 1; r < ROUNDS_128_OPT; r++) { + Substitution128(a,S); + ShiftRow128(a,0); + MixColumn128(a); + KeyAddition128(a,rk[r]); + } + + /* Last round is special: there is no MixColumn + */ + Substitution128(a,S); + ShiftRow128(a,0); + KeyAddition128(a,rk[ROUNDS_128_OPT]); + + return 0; +} + +int rijndaelDecrypt128 ( + word8 a[4][BC_128_OPT], + word8 rk[MAXROUNDS+1][4][MAXBC]) +{ + int r; + + /* To decrypt: apply the inverse operations of the encrypt routine, + * in opposite order + * + * (KeyAddition is an involution: it 's equal to its inverse) + * (the inverse of Substitution with table S is Substitution with the + * inverse table of S) + * (the inverse of Shiftrow is Shiftrow over a suitable distance) + */ + + /* First the special round: + * without InvMixColumn + * with extra KeyAddition + */ + KeyAddition128(a,rk[ROUNDS_128_OPT]); + Substitution128(a,Si); + ShiftRow128(a,1); + + /* ROUNDS-1 ordinary rounds + */ + for(r = ROUNDS_128_OPT-1; r > 0; r--) { + KeyAddition128(a,rk[r]); + InvMixColumn128(a); + Substitution128(a,Si); + ShiftRow128(a,1); + } + + /* End with the extra key addition + */ + + KeyAddition128(a,rk[0]); + + return 0; +} + +#endif /* !GLADMAN_AES_128_ENABLE */ + diff --git a/Security/libsecurity_apple_csp/lib/rijndael-alg-ref.h b/Security/libsecurity_apple_csp/lib/rijndael-alg-ref.h new file mode 100644 index 00000000..e2d3d3be --- /dev/null +++ b/Security/libsecurity_apple_csp/lib/rijndael-alg-ref.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please obtain + * a copy of the License at http://www.apple.com/publicsource and read it before + * using this file. + * + * This 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. + */ + + +/* rijndael-alg-ref.h v2.0 August '99 + * Reference ANSI C code + * authors: Paulo Barreto + * Vincent Rijmen + */ +#ifndef __RIJNDAEL_ALG_H +#define __RIJNDAEL_ALG_H + +#include "aesCommon.h" + +#define MAXBC (MAX_AES_BLOCK_BITS/32) +#define MAXKC (MAX_AES_KEY_BITS/32) +#define MAXROUNDS 14 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned char word8; +typedef unsigned short word16; +typedef unsigned int word32; + + +int rijndaelKeySched (word8 k[4][MAXKC], int keyBits, int blockBits, + word8 rk[MAXROUNDS+1][4][MAXBC]); +int rijndaelEncrypt (word8 a[4][MAXBC], int keyBits, int blockBits, + word8 rk[MAXROUNDS+1][4][MAXBC]); +#ifndef __APPLE__ +int rijndaelEncryptRound (word8 a[4][MAXBC], int keyBits, int blockBits, + word8 rk[MAXROUNDS+1][4][MAXBC], int rounds); +#endif +int rijndaelDecrypt (word8 a[4][MAXBC], int keyBits, int blockBits, + word8 rk[MAXROUNDS+1][4][MAXBC]); +#ifndef __APPLE__ +int rijndaelDecryptRound (word8 a[4][MAXBC], int keyBits, int blockBits, + word8 rk[MAXROUNDS+1][4][MAXBC], int rounds); +#endif + +#if !GLADMAN_AES_128_ENABLE + +/* + * Optimized routines for 128-bit block and key. + */ +#define ROUNDS_128_OPT 10 +#define BC_128_OPT 4 +#define KC_128_OPT 4 + +/* + * These require 32-bit word-aligned a, k, and rk arrays + */ +int rijndaelKeySched128 (word8 k[4][KC_128_OPT], + word8 rk[MAXROUNDS+1][4][MAXBC]); +int rijndaelEncrypt128 (word8 a[4][BC_128_OPT], + word8 rk[MAXROUNDS+1][4][MAXBC]); +int rijndaelDecrypt128 (word8 a[4][BC_128_OPT], + word8 rk[MAXROUNDS+1][4][MAXBC]); + +#endif /* !GLADMAN_AES_128_ENABLE */ + +#ifdef __cplusplus +} +#endif + +#endif /* __RIJNDAEL_ALG_H */ diff --git a/Security/libsecurity_apple_csp/lib/rijndaelApi.c b/Security/libsecurity_apple_csp/lib/rijndaelApi.c new file mode 100644 index 00000000..7d2dc109 --- /dev/null +++ b/Security/libsecurity_apple_csp/lib/rijndaelApi.c @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please obtain + * a copy of the License at http://www.apple.com/publicsource and read it before + * using this file. + * + * This 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. + */ + + +/* + * rijndaelApi.c - AES API layer + * + * Based on rijndael-api-ref.h v2.0 written by Paulo Barreto + * and Vincent Rijmen + */ +#include +#include + +#include "rijndael-alg-ref.h" +#include "rijndaelApi.h" + +#ifdef ALTIVEC_ENABLE +/* this goes somewhere else and gets init'd by the plugin object.... */ +/* as of 4/11/2001, the vectorized routines do NOT work */ +int gHasAltivec = 0; +#endif + +int doAES128 = 1; + +#define CBC_DEBUG 0 +#if CBC_DEBUG +static void dumpChainBuf(cipherInstance *cipher, char *op) +{ + int t,j; + int columns = cipher->blockLen / 32; + + printf("chainBuf %s: ", op); + for (j = 0; j < columns; j++) { + for(t = 0; t < 4; t++) { + printf("%02x ", cipher->chainBlock[t][j]); + } + } + printf("\n"); +} +#else +#define dumpChainBuf(c, o) +#endif + +int makeKey( + keyInstance *key, + int keyLen, // in BITS + int blockLen, // in BITS + word8 *keyMaterial, + int enable128Opt) +{ + unsigned keyBytes; + unsigned i; + + if (key == NULL) { + return BAD_KEY_INSTANCE; + } + if(keyMaterial == NULL) { + return BAD_KEY_MAT; + } + if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) { + key->keyLen = keyLen; + } else { + return BAD_KEY_MAT; + } + key->blockLen = blockLen; + key->columns = blockLen / 32; + + /* initialize key schedule */ +#if !GLADMAN_AES_128_ENABLE + if(enable128Opt && + (keyLen == MIN_AES_KEY_BITS) && + (blockLen == MIN_AES_BLOCK_BITS)) { + /* optimized, 128 bit key and block size */ + word8 k[4][KC_128_OPT] __attribute__((aligned(4))); + + for(i = 0; i < (MIN_AES_KEY_BITS/8); i++) { + /* speed this up */ + k[i % 4][i / 4] = keyMaterial[i]; + } + rijndaelKeySched128 (k, key->keySched); + memset(k, 0, 4 * KC_128_OPT); + } + else +#endif /* !GLADMAN_AES_128_ENABLE */ + { + + /* general case */ + word8 k[4][MAXKC]; + + keyBytes = keyLen / 8; + for(i = 0; i < keyBytes; i++) { + k[i % 4][i / 4] = keyMaterial[i]; + } + rijndaelKeySched (k, key->keyLen, key->blockLen, key->keySched); + memset(k, 0, 4 * MAXKC); + } + return TRUE; +} + +/* + * Simplified single-block encrypt/decrypt. + */ +#define AES_CONSISTENCY_CHECK 1 + +int rijndaelBlockEncrypt( + keyInstance *key, + word8 *input, + word8 *outBuffer) +{ + int t; + unsigned j; + word8 localBlock[4][MAXBC]; // working memory: encrypt/decrypt in place here + + #if AES_CONSISTENCY_CHECK + if (key == NULL || + (key->keyLen != 128 && key->keyLen != 192 && key->keyLen != 256) || + (key->blockLen != 128 && key->blockLen != 192 && key->blockLen != 256)) { + return BAD_KEY_INSTANCE; + } + #endif /* AES_CONSISTENCY_CHECK */ + + #if defined(__ppc__) && defined(ALTIVEC_ENABLE) + if(gHasAltivec && (key->blockLen == 128)) { + vBlockEncrypt128(key, input, outBuffer); + return 128; + } + #endif + + for (j = 0; j < key->columns; j++) { + for(t = 0; t < 4; t++) + /* parse input stream into rectangular array */ + localBlock[t][j] = input[4*j+t]; + } + rijndaelEncrypt (localBlock, key->keyLen, key->blockLen, key->keySched); + for (j = 0; j < key->columns; j++) { + /* parse rectangular array into output ciphertext bytes */ + for(t = 0; t < 4; t++) + outBuffer[4*j+t] = (word8) localBlock[t][j]; + } + memset(localBlock, 0, 4 * MAXBC); + return key->blockLen; +} + +int rijndaelBlockDecrypt( + keyInstance *key, + word8 *input, + word8 *outBuffer) +{ + int t; + unsigned j; + word8 localBlock[4][MAXBC]; // working memory: encrypt/decrypt in place here + + #if AES_CONSISTENCY_CHECK + if (key == NULL || + (key->keyLen != 128 && key->keyLen != 192 && key->keyLen != 256) || + (key->blockLen != 128 && key->blockLen != 192 && key->blockLen != 256)) { + return BAD_KEY_INSTANCE; + } + #endif /* AES_CONSISTENCY_CHECK */ + + #if defined(__ppc__) && defined(ALTIVEC_ENABLE) + if(gHasAltivec && (cipher->blockLen == 128)) { + vBlockDecrypt128(key, input, outBuffer); + return 128; + } + #endif + + for (j = 0; j < key->columns; j++) { + for(t = 0; t < 4; t++) + /* parse input stream into rectangular array */ + localBlock[t][j] = input[4*j+t]; + } + rijndaelDecrypt (localBlock, key->keyLen, key->blockLen, key->keySched); + for (j = 0; j < key->columns; j++) { + /* parse rectangular array into output ciphertext bytes */ + for(t = 0; t < 4; t++) + outBuffer[4*j+t] = (word8) localBlock[t][j]; + } + memset(localBlock, 0, 4 * MAXBC); + return key->blockLen; +} + +#if !GLADMAN_AES_128_ENABLE +/* + * Optimized routines for 128 bit block and 128 bit key. + */ +int rijndaelBlockEncrypt128( + keyInstance *key, + word8 *input, + word8 *outBuffer) +{ + int j; + word8 localBlock[4][BC_128_OPT] __attribute__((aligned(4))); + word8 *row0 = localBlock[0]; + word8 *row1 = localBlock[1]; + word8 *row2 = localBlock[2]; + word8 *row3 = localBlock[3]; + + /* parse input stream into rectangular array */ + for (j = 0; j < BC_128_OPT; j++) { + *row0++ = *input++; + *row1++ = *input++; + *row2++ = *input++; + *row3++ = *input++; + } + rijndaelEncrypt128 (localBlock, key->keySched); + + /* parse rectangular array into output ciphertext bytes */ + row0 = localBlock[0]; + row1 = localBlock[1]; + row2 = localBlock[2]; + row3 = localBlock[3]; + + for (j = 0; j < BC_128_OPT; j++) { + *outBuffer++ = *row0++; + *outBuffer++ = *row1++; + *outBuffer++ = *row2++; + *outBuffer++ = *row3++; + } + memset(localBlock, 0, 4*BC_128_OPT); + return MIN_AES_BLOCK_BITS; +} + +int rijndaelBlockDecrypt128( + keyInstance *key, + word8 *input, + word8 *outBuffer) +{ + int j; + word8 localBlock[4][BC_128_OPT] __attribute__((aligned(4))); + word8 *row0 = localBlock[0]; + word8 *row1 = localBlock[1]; + word8 *row2 = localBlock[2]; + word8 *row3 = localBlock[3]; + + /* parse input stream into rectangular array */ + for (j = 0; j < BC_128_OPT; j++) { + *row0++ = *input++; + *row1++ = *input++; + *row2++ = *input++; + *row3++ = *input++; + } + + rijndaelDecrypt128 (localBlock, key->keySched); + + /* parse rectangular array into output ciphertext bytes */ + row0 = localBlock[0]; + row1 = localBlock[1]; + row2 = localBlock[2]; + row3 = localBlock[3]; + + for (j = 0; j < BC_128_OPT; j++) { + *outBuffer++ = *row0++; + *outBuffer++ = *row1++; + *outBuffer++ = *row2++; + *outBuffer++ = *row3++; + } + memset(localBlock, 0, 4*BC_128_OPT); + return MIN_AES_BLOCK_BITS; +} +#endif /* !GLADMAN_AES_128_ENABLE */ + diff --git a/Security/libsecurity_apple_csp/lib/rijndaelApi.h b/Security/libsecurity_apple_csp/lib/rijndaelApi.h new file mode 100644 index 00000000..2dc61b6e --- /dev/null +++ b/Security/libsecurity_apple_csp/lib/rijndaelApi.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please obtain + * a copy of the License at http://www.apple.com/publicsource and read it before + * using this file. + * + * This 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. + */ + + +/* + * rijndaelApi.h - AES API layer + * + * Based on rijndael-api-ref.h v2.0 written by Paulo Barreto + * and Vincent Rijmen + */ + +#ifndef _RIJNDAEL_API_REF_H_ +#define _RIJNDAEL_API_REF_H_ + +#include +#include "rijndael-alg-ref.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Error Codes */ +#define BAD_KEY_MAT -1 /* Key material not of correct + length */ +#define BAD_KEY_INSTANCE -2 /* Key passed is not valid */ + +#define MAX_AES_KEY_SIZE (MAX_AES_KEY_BITS / 8) +#define MAX_AES_BLOCK_SIZE (MAX_AES_BLOCK_BITS / 8) +#define MAX_AES_IV_SIZE MAX_AES_BLOCK_SIZE + +#define TRUE 1 +#define FALSE 0 + +/* The structure for key information */ +typedef struct { + word32 keyLen; /* Length of the key in bits */ + word32 blockLen; /* Length of block in bits */ + word32 columns; /* optimization, blockLen / 32 */ + word8 keySched[MAXROUNDS+1][4][MAXBC]; +} keyInstance; + +int makeKey( + keyInstance *key, + int keyLen, // in BITS + int blockLen, // in BITS + word8 *keyMaterial, + int enable128Opt); + +/* + * Simplified single-block encrypt/decrypt. + */ +int rijndaelBlockEncrypt( + keyInstance *key, + word8 *input, + word8 *outBuffer); +int rijndaelBlockDecrypt( + keyInstance *key, + word8 *input, + word8 *outBuffer); + +#if !GLADMAN_AES_128_ENABLE +/* + * Optimized routines for 128 bit block and 128 bit key. + */ +int rijndaelBlockEncrypt128( + keyInstance *key, + word8 *input, + word8 *outBuffer); +int rijndaelBlockDecrypt128( + keyInstance *key, + word8 *input, + word8 *outBuffer); +#endif /* !GLADMAN_AES_128_ENABLE */ + +#if defined(__ppc__) && defined(ALTIVEC_ENABLE) +/* + * dmitch addenda 4/11/2001: 128-bit only vectorized encrypt/decrypt with no CBC + */ +void vBlockEncrypt128( + keyInstance *key, + word8 *input, + word8 *outBuffer); +void vBlockDecrypt128( + keyInstance *key, + word8 *input, + word8 *outBuffer); + +/* temp switch for runtime enable/disable */ +extern int doAES128; + +#endif /* __ppc__ && ALTIVEC_ENABLE */ + +/* ptr to one of several (possibly optimized) encrypt/decrypt functions */ +typedef int (*aesCryptFcn)( + keyInstance *key, + word8 *input, + word8 *outBuffer); + +#ifdef __cplusplus +} +#endif // cplusplus + +#endif // RIJNDAEL_API_REF + + diff --git a/libsecurity_apple_csp/lib/vRijndael-alg-ref.c b/Security/libsecurity_apple_csp/lib/vRijndael-alg-ref.c similarity index 99% rename from libsecurity_apple_csp/lib/vRijndael-alg-ref.c rename to Security/libsecurity_apple_csp/lib/vRijndael-alg-ref.c index f5afda69..45484ef7 100644 --- a/libsecurity_apple_csp/lib/vRijndael-alg-ref.c +++ b/Security/libsecurity_apple_csp/lib/vRijndael-alg-ref.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,8 +19,7 @@ /* * vRijndael-alg-ref.c * - * Created by Robert A. Murley on Mon Jan 22 2001. - * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2001,2011,2014 Apple Inc. All Rights Reserved. * */ diff --git a/libsecurity_apple_csp/lib/wrapKey.cpp b/Security/libsecurity_apple_csp/lib/wrapKey.cpp similarity index 99% rename from libsecurity_apple_csp/lib/wrapKey.cpp rename to Security/libsecurity_apple_csp/lib/wrapKey.cpp index 44c3eb94..00ab865e 100644 --- a/libsecurity_apple_csp/lib/wrapKey.cpp +++ b/Security/libsecurity_apple_csp/lib/wrapKey.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/lib/wrapKeyCms.cpp b/Security/libsecurity_apple_csp/lib/wrapKeyCms.cpp similarity index 99% rename from libsecurity_apple_csp/lib/wrapKeyCms.cpp rename to Security/libsecurity_apple_csp/lib/wrapKeyCms.cpp index 75d64867..048ce9fe 100644 --- a/libsecurity_apple_csp/lib/wrapKeyCms.cpp +++ b/Security/libsecurity_apple_csp/lib/wrapKeyCms.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/libsecurity_apple_csp.xcodeproj/project.pbxproj b/Security/libsecurity_apple_csp/libsecurity_apple_csp.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_apple_csp/libsecurity_apple_csp.xcodeproj/project.pbxproj rename to Security/libsecurity_apple_csp/libsecurity_apple_csp.xcodeproj/project.pbxproj diff --git a/libsecurity_apple_csp/mds/csp_capabilities.mdsinfo b/Security/libsecurity_apple_csp/mds/csp_capabilities.mdsinfo similarity index 100% rename from libsecurity_apple_csp/mds/csp_capabilities.mdsinfo rename to Security/libsecurity_apple_csp/mds/csp_capabilities.mdsinfo diff --git a/libsecurity_apple_csp/mds/csp_capabilities_common.mds b/Security/libsecurity_apple_csp/mds/csp_capabilities_common.mds similarity index 100% rename from libsecurity_apple_csp/mds/csp_capabilities_common.mds rename to Security/libsecurity_apple_csp/mds/csp_capabilities_common.mds diff --git a/libsecurity_apple_csp/mds/csp_common.mdsinfo b/Security/libsecurity_apple_csp/mds/csp_common.mdsinfo similarity index 100% rename from libsecurity_apple_csp/mds/csp_common.mdsinfo rename to Security/libsecurity_apple_csp/mds/csp_common.mdsinfo diff --git a/libsecurity_apple_csp/mds/csp_primary.mdsinfo b/Security/libsecurity_apple_csp/mds/csp_primary.mdsinfo similarity index 100% rename from libsecurity_apple_csp/mds/csp_primary.mdsinfo rename to Security/libsecurity_apple_csp/mds/csp_primary.mdsinfo diff --git a/libsecurity_apple_csp/open_ssl/LICENSE b/Security/libsecurity_apple_csp/open_ssl/LICENSE similarity index 100% rename from libsecurity_apple_csp/open_ssl/LICENSE rename to Security/libsecurity_apple_csp/open_ssl/LICENSE diff --git a/libsecurity_apple_csp/open_ssl/bf/COPYRIGHT b/Security/libsecurity_apple_csp/open_ssl/bf/COPYRIGHT similarity index 100% rename from libsecurity_apple_csp/open_ssl/bf/COPYRIGHT rename to Security/libsecurity_apple_csp/open_ssl/bf/COPYRIGHT diff --git a/libsecurity_apple_csp/open_ssl/bf/README b/Security/libsecurity_apple_csp/open_ssl/bf/README similarity index 100% rename from libsecurity_apple_csp/open_ssl/bf/README rename to Security/libsecurity_apple_csp/open_ssl/bf/README diff --git a/libsecurity_apple_csp/open_ssl/bf/bf_ecb.c b/Security/libsecurity_apple_csp/open_ssl/bf/bf_ecb.c similarity index 100% rename from libsecurity_apple_csp/open_ssl/bf/bf_ecb.c rename to Security/libsecurity_apple_csp/open_ssl/bf/bf_ecb.c diff --git a/libsecurity_apple_csp/open_ssl/bf/bf_enc.c b/Security/libsecurity_apple_csp/open_ssl/bf/bf_enc.c similarity index 100% rename from libsecurity_apple_csp/open_ssl/bf/bf_enc.c rename to Security/libsecurity_apple_csp/open_ssl/bf/bf_enc.c diff --git a/libsecurity_apple_csp/open_ssl/bf/bf_locl.h b/Security/libsecurity_apple_csp/open_ssl/bf/bf_locl.h similarity index 100% rename from libsecurity_apple_csp/open_ssl/bf/bf_locl.h rename to Security/libsecurity_apple_csp/open_ssl/bf/bf_locl.h diff --git a/libsecurity_apple_csp/open_ssl/bf/bf_pi.h b/Security/libsecurity_apple_csp/open_ssl/bf/bf_pi.h similarity index 100% rename from libsecurity_apple_csp/open_ssl/bf/bf_pi.h rename to Security/libsecurity_apple_csp/open_ssl/bf/bf_pi.h diff --git a/libsecurity_apple_csp/open_ssl/bf/bf_skey.c b/Security/libsecurity_apple_csp/open_ssl/bf/bf_skey.c similarity index 100% rename from libsecurity_apple_csp/open_ssl/bf/bf_skey.c rename to Security/libsecurity_apple_csp/open_ssl/bf/bf_skey.c diff --git a/libsecurity_apple_csp/open_ssl/bio/bio_lib.c b/Security/libsecurity_apple_csp/open_ssl/bio/bio_lib.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/bio/bio_lib.c rename to Security/libsecurity_apple_csp/open_ssl/bio/bio_lib.c index 4040be73..dac3c3fc 100644 --- a/libsecurity_apple_csp/open_ssl/bio/bio_lib.c +++ b/Security/libsecurity_apple_csp/open_ssl/bio/bio_lib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bio/bss_file.c b/Security/libsecurity_apple_csp/open_ssl/bio/bss_file.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/bio/bss_file.c rename to Security/libsecurity_apple_csp/open_ssl/bio/bss_file.c index ccaabd7b..b74e618f 100644 --- a/libsecurity_apple_csp/open_ssl/bio/bss_file.c +++ b/Security/libsecurity_apple_csp/open_ssl/bio/bss_file.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_add.c b/Security/libsecurity_apple_csp/open_ssl/bn/bn_add.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/bn/bn_add.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_add.c index 3abd7499..e63e2b29 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bn_add.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bn_add.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_asm.c b/Security/libsecurity_apple_csp/open_ssl/bn/bn_asm.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/bn/bn_asm.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_asm.c index d5c137f3..b956a092 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bn_asm.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bn_asm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_blind.c b/Security/libsecurity_apple_csp/open_ssl/bn/bn_blind.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/bn/bn_blind.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_blind.c index 73ddc1c0..bd11d138 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bn_blind.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bn_blind.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_ctx.c b/Security/libsecurity_apple_csp/open_ssl/bn/bn_ctx.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/bn/bn_ctx.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_ctx.c index bcb922cb..76c6c0bc 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bn_ctx.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bn_ctx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_div.c b/Security/libsecurity_apple_csp/open_ssl/bn/bn_div.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/bn/bn_div.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_div.c index a85fb3a4..05c700ee 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bn_div.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bn_div.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_err.c b/Security/libsecurity_apple_csp/open_ssl/bn/bn_err.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/bn/bn_err.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_err.c index d706e586..f547d25e 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bn_err.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bn_err.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_exp.c b/Security/libsecurity_apple_csp/open_ssl/bn/bn_exp.c similarity index 100% rename from libsecurity_apple_csp/open_ssl/bn/bn_exp.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_exp.c diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_exp2.c b/Security/libsecurity_apple_csp/open_ssl/bn/bn_exp2.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/bn/bn_exp2.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_exp2.c index 4317bdba..87a50c43 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bn_exp2.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bn_exp2.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_gcd.c b/Security/libsecurity_apple_csp/open_ssl/bn/bn_gcd.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/bn/bn_gcd.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_gcd.c index f0d6eacc..6729b1bb 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bn_gcd.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bn_gcd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_lcl.h b/Security/libsecurity_apple_csp/open_ssl/bn/bn_lcl.h similarity index 100% rename from libsecurity_apple_csp/open_ssl/bn/bn_lcl.h rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_lcl.h diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_lib.c b/Security/libsecurity_apple_csp/open_ssl/bn/bn_lib.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/bn/bn_lib.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_lib.c index 667dca23..4ac941ab 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bn_lib.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bn_lib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_mont.c b/Security/libsecurity_apple_csp/open_ssl/bn/bn_mont.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/bn/bn_mont.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_mont.c index 69e573b3..9a1700a5 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bn_mont.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bn_mont.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_mpi.c b/Security/libsecurity_apple_csp/open_ssl/bn/bn_mpi.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/bn/bn_mpi.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_mpi.c index 1aefdaaf..78441831 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bn_mpi.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bn_mpi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_mul.c b/Security/libsecurity_apple_csp/open_ssl/bn/bn_mul.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/bn/bn_mul.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_mul.c index 20987d95..83c21dfb 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bn_mul.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bn_mul.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_prime.c b/Security/libsecurity_apple_csp/open_ssl/bn/bn_prime.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/bn/bn_prime.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_prime.c index a1dad1ec..83730079 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bn_prime.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bn_prime.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_prime.h b/Security/libsecurity_apple_csp/open_ssl/bn/bn_prime.h similarity index 99% rename from libsecurity_apple_csp/open_ssl/bn/bn_prime.h rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_prime.h index 64907456..6e352c34 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bn_prime.h +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bn_prime.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_print.c b/Security/libsecurity_apple_csp/open_ssl/bn/bn_print.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/bn/bn_print.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_print.c index 58f22f0c..08949623 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bn_print.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bn_print.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_rand.c b/Security/libsecurity_apple_csp/open_ssl/bn/bn_rand.c similarity index 100% rename from libsecurity_apple_csp/open_ssl/bn/bn_rand.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_rand.c diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_recp.c b/Security/libsecurity_apple_csp/open_ssl/bn/bn_recp.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/bn/bn_recp.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_recp.c index 6fc6952a..908d65c9 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bn_recp.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bn_recp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_shift.c b/Security/libsecurity_apple_csp/open_ssl/bn/bn_shift.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/bn/bn_shift.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_shift.c index 879a6757..7e72f07b 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bn_shift.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bn_shift.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_sqr.c b/Security/libsecurity_apple_csp/open_ssl/bn/bn_sqr.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/bn/bn_sqr.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_sqr.c index 0c08ced2..75fe8033 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bn_sqr.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bn_sqr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bn_word.c b/Security/libsecurity_apple_csp/open_ssl/bn/bn_word.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/bn/bn_word.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bn_word.c index d970d351..7d4abdf5 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bn_word.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bn_word.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bnspeed.c b/Security/libsecurity_apple_csp/open_ssl/bn/bnspeed.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/bn/bnspeed.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bnspeed.c index 41b47b06..cc085c39 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bnspeed.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bnspeed.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/bntest.c b/Security/libsecurity_apple_csp/open_ssl/bn/bntest.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/bn/bntest.c rename to Security/libsecurity_apple_csp/open_ssl/bn/bntest.c index 4549814f..f358d657 100644 --- a/libsecurity_apple_csp/open_ssl/bn/bntest.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/bntest.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/divtest.c b/Security/libsecurity_apple_csp/open_ssl/bn/divtest.c similarity index 96% rename from libsecurity_apple_csp/open_ssl/bn/divtest.c rename to Security/libsecurity_apple_csp/open_ssl/bn/divtest.c index 9a1417df..3532ae21 100644 --- a/libsecurity_apple_csp/open_ssl/bn/divtest.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/divtest.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/exp.c b/Security/libsecurity_apple_csp/open_ssl/bn/exp.c similarity index 96% rename from libsecurity_apple_csp/open_ssl/bn/exp.c rename to Security/libsecurity_apple_csp/open_ssl/bn/exp.c index 7daec41d..00c2d771 100644 --- a/libsecurity_apple_csp/open_ssl/bn/exp.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/exp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/expspeed.c b/Security/libsecurity_apple_csp/open_ssl/bn/expspeed.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/bn/expspeed.c rename to Security/libsecurity_apple_csp/open_ssl/bn/expspeed.c index b2cb29e1..abef0fb7 100644 --- a/libsecurity_apple_csp/open_ssl/bn/expspeed.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/expspeed.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/exptest.c b/Security/libsecurity_apple_csp/open_ssl/bn/exptest.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/bn/exptest.c rename to Security/libsecurity_apple_csp/open_ssl/bn/exptest.c index 92ce6b00..2255397d 100644 --- a/libsecurity_apple_csp/open_ssl/bn/exptest.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/exptest.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/bn/vms-helper.c b/Security/libsecurity_apple_csp/open_ssl/bn/vms-helper.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/bn/vms-helper.c rename to Security/libsecurity_apple_csp/open_ssl/bn/vms-helper.c index f0ec672a..0ef3eb0f 100644 --- a/libsecurity_apple_csp/open_ssl/bn/vms-helper.c +++ b/Security/libsecurity_apple_csp/open_ssl/bn/vms-helper.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/buffer/buf_err.c b/Security/libsecurity_apple_csp/open_ssl/buffer/buf_err.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/buffer/buf_err.c rename to Security/libsecurity_apple_csp/open_ssl/buffer/buf_err.c index 223547fd..38c5c9c6 100644 --- a/libsecurity_apple_csp/open_ssl/buffer/buf_err.c +++ b/Security/libsecurity_apple_csp/open_ssl/buffer/buf_err.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/buffer/buffer.c b/Security/libsecurity_apple_csp/open_ssl/buffer/buffer.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/buffer/buffer.c rename to Security/libsecurity_apple_csp/open_ssl/buffer/buffer.c index 317b6953..37a4c33a 100644 --- a/libsecurity_apple_csp/open_ssl/buffer/buffer.c +++ b/Security/libsecurity_apple_csp/open_ssl/buffer/buffer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/cryptlib.c b/Security/libsecurity_apple_csp/open_ssl/cryptlib.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/cryptlib.c rename to Security/libsecurity_apple_csp/open_ssl/cryptlib.c index 50255293..ddadde1b 100644 --- a/libsecurity_apple_csp/open_ssl/cryptlib.c +++ b/Security/libsecurity_apple_csp/open_ssl/cryptlib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/cryptlib.h b/Security/libsecurity_apple_csp/open_ssl/cryptlib.h similarity index 98% rename from libsecurity_apple_csp/open_ssl/cryptlib.h rename to Security/libsecurity_apple_csp/open_ssl/cryptlib.h index 438031b3..c4d8d2f2 100644 --- a/libsecurity_apple_csp/open_ssl/cryptlib.h +++ b/Security/libsecurity_apple_csp/open_ssl/cryptlib.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/dh/dh_check.c b/Security/libsecurity_apple_csp/open_ssl/dh/dh_check.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/dh/dh_check.c rename to Security/libsecurity_apple_csp/open_ssl/dh/dh_check.c index 3737f379..7ce1d167 100644 --- a/libsecurity_apple_csp/open_ssl/dh/dh_check.c +++ b/Security/libsecurity_apple_csp/open_ssl/dh/dh_check.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/dh/dh_err.c b/Security/libsecurity_apple_csp/open_ssl/dh/dh_err.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/dh/dh_err.c rename to Security/libsecurity_apple_csp/open_ssl/dh/dh_err.c index edf04592..9d34ad59 100644 --- a/libsecurity_apple_csp/open_ssl/dh/dh_err.c +++ b/Security/libsecurity_apple_csp/open_ssl/dh/dh_err.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/dh/dh_gen.c b/Security/libsecurity_apple_csp/open_ssl/dh/dh_gen.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/dh/dh_gen.c rename to Security/libsecurity_apple_csp/open_ssl/dh/dh_gen.c index e0d7ffba..f93be224 100644 --- a/libsecurity_apple_csp/open_ssl/dh/dh_gen.c +++ b/Security/libsecurity_apple_csp/open_ssl/dh/dh_gen.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/dh/dh_key.c b/Security/libsecurity_apple_csp/open_ssl/dh/dh_key.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/dh/dh_key.c rename to Security/libsecurity_apple_csp/open_ssl/dh/dh_key.c index d1af8573..8fc8e179 100644 --- a/libsecurity_apple_csp/open_ssl/dh/dh_key.c +++ b/Security/libsecurity_apple_csp/open_ssl/dh/dh_key.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/dh/dh_lib.c b/Security/libsecurity_apple_csp/open_ssl/dh/dh_lib.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/dh/dh_lib.c rename to Security/libsecurity_apple_csp/open_ssl/dh/dh_lib.c index ff639b2a..a9449da0 100644 --- a/libsecurity_apple_csp/open_ssl/dh/dh_lib.c +++ b/Security/libsecurity_apple_csp/open_ssl/dh/dh_lib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/dsa/dsa_asn1.c b/Security/libsecurity_apple_csp/open_ssl/dsa/dsa_asn1.c similarity index 97% rename from libsecurity_apple_csp/open_ssl/dsa/dsa_asn1.c rename to Security/libsecurity_apple_csp/open_ssl/dsa/dsa_asn1.c index ac46c6cb..1d6916d8 100644 --- a/libsecurity_apple_csp/open_ssl/dsa/dsa_asn1.c +++ b/Security/libsecurity_apple_csp/open_ssl/dsa/dsa_asn1.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/dsa/dsa_err.c b/Security/libsecurity_apple_csp/open_ssl/dsa/dsa_err.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/dsa/dsa_err.c rename to Security/libsecurity_apple_csp/open_ssl/dsa/dsa_err.c index 9ddab261..5596d9d8 100644 --- a/libsecurity_apple_csp/open_ssl/dsa/dsa_err.c +++ b/Security/libsecurity_apple_csp/open_ssl/dsa/dsa_err.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/dsa/dsa_gen.c b/Security/libsecurity_apple_csp/open_ssl/dsa/dsa_gen.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/dsa/dsa_gen.c rename to Security/libsecurity_apple_csp/open_ssl/dsa/dsa_gen.c index 951b4b80..9cda9604 100644 --- a/libsecurity_apple_csp/open_ssl/dsa/dsa_gen.c +++ b/Security/libsecurity_apple_csp/open_ssl/dsa/dsa_gen.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/dsa/dsa_key.c b/Security/libsecurity_apple_csp/open_ssl/dsa/dsa_key.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/dsa/dsa_key.c rename to Security/libsecurity_apple_csp/open_ssl/dsa/dsa_key.c index 0af87775..3ae4dac8 100644 --- a/libsecurity_apple_csp/open_ssl/dsa/dsa_key.c +++ b/Security/libsecurity_apple_csp/open_ssl/dsa/dsa_key.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/dsa/dsa_lib.c b/Security/libsecurity_apple_csp/open_ssl/dsa/dsa_lib.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/dsa/dsa_lib.c rename to Security/libsecurity_apple_csp/open_ssl/dsa/dsa_lib.c index aad0f5e5..f2021a84 100644 --- a/libsecurity_apple_csp/open_ssl/dsa/dsa_lib.c +++ b/Security/libsecurity_apple_csp/open_ssl/dsa/dsa_lib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/dsa/dsa_ossl.c b/Security/libsecurity_apple_csp/open_ssl/dsa/dsa_ossl.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/dsa/dsa_ossl.c rename to Security/libsecurity_apple_csp/open_ssl/dsa/dsa_ossl.c index aae23451..6d5e56ab 100644 --- a/libsecurity_apple_csp/open_ssl/dsa/dsa_ossl.c +++ b/Security/libsecurity_apple_csp/open_ssl/dsa/dsa_ossl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/dsa/dsa_sign.c b/Security/libsecurity_apple_csp/open_ssl/dsa/dsa_sign.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/dsa/dsa_sign.c rename to Security/libsecurity_apple_csp/open_ssl/dsa/dsa_sign.c index e4d62a79..a11ddf2a 100644 --- a/libsecurity_apple_csp/open_ssl/dsa/dsa_sign.c +++ b/Security/libsecurity_apple_csp/open_ssl/dsa/dsa_sign.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/dsa/dsa_vrf.c b/Security/libsecurity_apple_csp/open_ssl/dsa/dsa_vrf.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/dsa/dsa_vrf.c rename to Security/libsecurity_apple_csp/open_ssl/dsa/dsa_vrf.c index 1ed605b7..13a2cf96 100644 --- a/libsecurity_apple_csp/open_ssl/dsa/dsa_vrf.c +++ b/Security/libsecurity_apple_csp/open_ssl/dsa/dsa_vrf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/err/err.c b/Security/libsecurity_apple_csp/open_ssl/err/err.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/err/err.c rename to Security/libsecurity_apple_csp/open_ssl/err/err.c index ebf63535..dfe09242 100644 --- a/libsecurity_apple_csp/open_ssl/err/err.c +++ b/Security/libsecurity_apple_csp/open_ssl/err/err.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/err/err_prn.c b/Security/libsecurity_apple_csp/open_ssl/err/err_prn.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/err/err_prn.c rename to Security/libsecurity_apple_csp/open_ssl/err/err_prn.c index 3d786019..cd25ae7c 100644 --- a/libsecurity_apple_csp/open_ssl/err/err_prn.c +++ b/Security/libsecurity_apple_csp/open_ssl/err/err_prn.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/ex_data.c b/Security/libsecurity_apple_csp/open_ssl/ex_data.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/ex_data.c rename to Security/libsecurity_apple_csp/open_ssl/ex_data.c index faadeea2..6b1aa4e5 100644 --- a/libsecurity_apple_csp/open_ssl/ex_data.c +++ b/Security/libsecurity_apple_csp/open_ssl/ex_data.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/lhash/lhash.c b/Security/libsecurity_apple_csp/open_ssl/lhash/lhash.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/lhash/lhash.c rename to Security/libsecurity_apple_csp/open_ssl/lhash/lhash.c index 9169be4b..05f3f6b4 100644 --- a/libsecurity_apple_csp/open_ssl/lhash/lhash.c +++ b/Security/libsecurity_apple_csp/open_ssl/lhash/lhash.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/mem.c b/Security/libsecurity_apple_csp/open_ssl/mem.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/mem.c rename to Security/libsecurity_apple_csp/open_ssl/mem.c index fd995d0c..a788e791 100644 --- a/libsecurity_apple_csp/open_ssl/mem.c +++ b/Security/libsecurity_apple_csp/open_ssl/mem.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/misc/rc2_cbc.c b/Security/libsecurity_apple_csp/open_ssl/misc/rc2_cbc.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/misc/rc2_cbc.c rename to Security/libsecurity_apple_csp/open_ssl/misc/rc2_cbc.c index a2b5492a..8bc139de 100644 --- a/libsecurity_apple_csp/open_ssl/misc/rc2_cbc.c +++ b/Security/libsecurity_apple_csp/open_ssl/misc/rc2_cbc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/misc/rc2_locl.h b/Security/libsecurity_apple_csp/open_ssl/misc/rc2_locl.h similarity index 99% rename from libsecurity_apple_csp/open_ssl/misc/rc2_locl.h rename to Security/libsecurity_apple_csp/open_ssl/misc/rc2_locl.h index 8ac27a1a..ef6ba8a5 100644 --- a/libsecurity_apple_csp/open_ssl/misc/rc2_locl.h +++ b/Security/libsecurity_apple_csp/open_ssl/misc/rc2_locl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/misc/rc2_skey.c b/Security/libsecurity_apple_csp/open_ssl/misc/rc2_skey.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/misc/rc2_skey.c rename to Security/libsecurity_apple_csp/open_ssl/misc/rc2_skey.c index ea73fb6a..ee7a5a1e 100644 --- a/libsecurity_apple_csp/open_ssl/misc/rc2_skey.c +++ b/Security/libsecurity_apple_csp/open_ssl/misc/rc2_skey.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/misc/rc5_enc.c b/Security/libsecurity_apple_csp/open_ssl/misc/rc5_enc.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/misc/rc5_enc.c rename to Security/libsecurity_apple_csp/open_ssl/misc/rc5_enc.c index 630e5eac..0683256b 100644 --- a/libsecurity_apple_csp/open_ssl/misc/rc5_enc.c +++ b/Security/libsecurity_apple_csp/open_ssl/misc/rc5_enc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/misc/rc5_locl.h b/Security/libsecurity_apple_csp/open_ssl/misc/rc5_locl.h similarity index 99% rename from libsecurity_apple_csp/open_ssl/misc/rc5_locl.h rename to Security/libsecurity_apple_csp/open_ssl/misc/rc5_locl.h index 98408615..2ad785fe 100644 --- a/libsecurity_apple_csp/open_ssl/misc/rc5_locl.h +++ b/Security/libsecurity_apple_csp/open_ssl/misc/rc5_locl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/misc/rc5_skey.c b/Security/libsecurity_apple_csp/open_ssl/misc/rc5_skey.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/misc/rc5_skey.c rename to Security/libsecurity_apple_csp/open_ssl/misc/rc5_skey.c index f1aad501..8c42be8f 100644 --- a/libsecurity_apple_csp/open_ssl/misc/rc5_skey.c +++ b/Security/libsecurity_apple_csp/open_ssl/misc/rc5_skey.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/asn1.h b/Security/libsecurity_apple_csp/open_ssl/openssl/asn1.h similarity index 99% rename from libsecurity_apple_csp/open_ssl/openssl/asn1.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/asn1.h index 021405ca..1173f0a5 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/asn1.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/asn1.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/bio.h b/Security/libsecurity_apple_csp/open_ssl/openssl/bio.h similarity index 99% rename from libsecurity_apple_csp/open_ssl/openssl/bio.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/bio.h index 0c96f118..d593fe52 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/bio.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/bio.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/blowfish.h b/Security/libsecurity_apple_csp/open_ssl/openssl/blowfish.h similarity index 100% rename from libsecurity_apple_csp/open_ssl/openssl/blowfish.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/blowfish.h diff --git a/libsecurity_apple_csp/open_ssl/openssl/bn.h b/Security/libsecurity_apple_csp/open_ssl/openssl/bn.h similarity index 99% rename from libsecurity_apple_csp/open_ssl/openssl/bn.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/bn.h index 6a731afc..4a336fd4 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/bn.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/bn.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/buffer.h b/Security/libsecurity_apple_csp/open_ssl/openssl/buffer.h similarity index 98% rename from libsecurity_apple_csp/open_ssl/openssl/buffer.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/buffer.h index 9f9103ab..353e480d 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/buffer.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/buffer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/cast.h b/Security/libsecurity_apple_csp/open_ssl/openssl/cast.h similarity index 100% rename from libsecurity_apple_csp/open_ssl/openssl/cast.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/cast.h diff --git a/libsecurity_apple_csp/open_ssl/openssl/crypto.h b/Security/libsecurity_apple_csp/open_ssl/openssl/crypto.h similarity index 99% rename from libsecurity_apple_csp/open_ssl/openssl/crypto.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/crypto.h index b2c7a6c9..b55530d1 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/crypto.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/crypto.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/dh.h b/Security/libsecurity_apple_csp/open_ssl/openssl/dh.h similarity index 99% rename from libsecurity_apple_csp/open_ssl/openssl/dh.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/dh.h index 4903c1a4..ae24a355 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/dh.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/dh.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/dsa.h b/Security/libsecurity_apple_csp/open_ssl/openssl/dsa.h similarity index 99% rename from libsecurity_apple_csp/open_ssl/openssl/dsa.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/dsa.h index 08fdfaca..224b2f94 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/dsa.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/dsa.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/e_os.h b/Security/libsecurity_apple_csp/open_ssl/openssl/e_os.h similarity index 99% rename from libsecurity_apple_csp/open_ssl/openssl/e_os.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/e_os.h index c94d6dd9..127b0920 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/e_os.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/e_os.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/e_os2.h b/Security/libsecurity_apple_csp/open_ssl/openssl/e_os2.h similarity index 96% rename from libsecurity_apple_csp/open_ssl/openssl/e_os2.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/e_os2.h index 47ab43b3..e3235a96 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/e_os2.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/e_os2.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/err.h b/Security/libsecurity_apple_csp/open_ssl/openssl/err.h similarity index 99% rename from libsecurity_apple_csp/open_ssl/openssl/err.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/err.h index 255c8cca..6ce7f17b 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/err.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/err.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/evp.h b/Security/libsecurity_apple_csp/open_ssl/openssl/evp.h similarity index 99% rename from libsecurity_apple_csp/open_ssl/openssl/evp.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/evp.h index 02d69fd3..aa186474 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/evp.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/evp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/lhash.h b/Security/libsecurity_apple_csp/open_ssl/openssl/lhash.h similarity index 98% rename from libsecurity_apple_csp/open_ssl/openssl/lhash.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/lhash.h index 748d47b5..aae8e744 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/lhash.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/lhash.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/objects.h b/Security/libsecurity_apple_csp/open_ssl/openssl/objects.h similarity index 99% rename from libsecurity_apple_csp/open_ssl/openssl/objects.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/objects.h index d65f8cf9..ce8fb358 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/objects.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/objects.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/openssl_pkcs7.h b/Security/libsecurity_apple_csp/open_ssl/openssl/openssl_pkcs7.h similarity index 99% rename from libsecurity_apple_csp/open_ssl/openssl/openssl_pkcs7.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/openssl_pkcs7.h index 223438ba..760a7b88 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/openssl_pkcs7.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/openssl_pkcs7.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/opensslconf.h b/Security/libsecurity_apple_csp/open_ssl/openssl/opensslconf.h similarity index 96% rename from libsecurity_apple_csp/open_ssl/openssl/opensslconf.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/opensslconf.h index 4de0f709..3242b5ec 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/opensslconf.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/opensslconf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -17,7 +17,7 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/opensslv.h b/Security/libsecurity_apple_csp/open_ssl/openssl/opensslv.h similarity index 96% rename from libsecurity_apple_csp/open_ssl/openssl/opensslv.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/opensslv.h index 81326858..35e55edd 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/opensslv.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/opensslv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/rand.h b/Security/libsecurity_apple_csp/open_ssl/openssl/rand.h similarity index 98% rename from libsecurity_apple_csp/open_ssl/openssl/rand.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/rand.h index 3175a468..8b705ade 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/rand.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/rand.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/rc2.h b/Security/libsecurity_apple_csp/open_ssl/openssl/rc2.h similarity index 98% rename from libsecurity_apple_csp/open_ssl/openssl/rc2.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/rc2.h index 563365e0..7d1dae2e 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/rc2.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/rc2.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/rc5.h b/Security/libsecurity_apple_csp/open_ssl/openssl/rc5.h similarity index 98% rename from libsecurity_apple_csp/open_ssl/openssl/rc5.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/rc5.h index 123374b5..9a8f9624 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/rc5.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/rc5.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/rsa.h b/Security/libsecurity_apple_csp/open_ssl/openssl/rsa.h similarity index 99% rename from libsecurity_apple_csp/open_ssl/openssl/rsa.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/rsa.h index b103eda0..99a69eab 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/rsa.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/rsa.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/safestack.h b/Security/libsecurity_apple_csp/open_ssl/openssl/safestack.h similarity index 99% rename from libsecurity_apple_csp/open_ssl/openssl/safestack.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/safestack.h index ce7d3cf5..ed14c875 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/safestack.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/safestack.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/stack.h b/Security/libsecurity_apple_csp/open_ssl/openssl/stack.h similarity index 98% rename from libsecurity_apple_csp/open_ssl/openssl/stack.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/stack.h index d126b5b1..ca788f2d 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/stack.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/stack.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/x509.h b/Security/libsecurity_apple_csp/open_ssl/openssl/x509.h similarity index 99% rename from libsecurity_apple_csp/open_ssl/openssl/x509.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/x509.h index b9cc05dd..0a2d0328 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/x509.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/x509.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/openssl/x509_vfy.h b/Security/libsecurity_apple_csp/open_ssl/openssl/x509_vfy.h similarity index 99% rename from libsecurity_apple_csp/open_ssl/openssl/x509_vfy.h rename to Security/libsecurity_apple_csp/open_ssl/openssl/x509_vfy.h index 7ddfde7b..3e2dadf4 100644 --- a/libsecurity_apple_csp/open_ssl/openssl/x509_vfy.h +++ b/Security/libsecurity_apple_csp/open_ssl/openssl/x509_vfy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp b/Security/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp similarity index 99% rename from libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp rename to Security/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp index 74d064a0..5f3b68e6 100644 --- a/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp +++ b/Security/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.h b/Security/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.h similarity index 98% rename from libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.h rename to Security/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.h index e52012f6..0e29271a 100644 --- a/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.h +++ b/Security/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.cpp b/Security/libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.cpp similarity index 98% rename from libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.cpp rename to Security/libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.cpp index 1ebbce9a..ca332942 100644 --- a/libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.cpp +++ b/Security/libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.h b/Security/libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.h similarity index 96% rename from libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.h rename to Security/libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.h index 6551447d..8662075a 100644 --- a/libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.h +++ b/Security/libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_chk.c b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_chk.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/rsa/rsa_chk.c rename to Security/libsecurity_apple_csp/open_ssl/rsa/rsa_chk.c index a68408ba..a7b09586 100644 --- a/libsecurity_apple_csp/open_ssl/rsa/rsa_chk.c +++ b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_chk.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_eay.c b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_eay.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/rsa/rsa_eay.c rename to Security/libsecurity_apple_csp/open_ssl/rsa/rsa_eay.c index 3f79f3ab..b2836aa8 100644 --- a/libsecurity_apple_csp/open_ssl/rsa/rsa_eay.c +++ b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_eay.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_err.c b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_err.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/rsa/rsa_err.c rename to Security/libsecurity_apple_csp/open_ssl/rsa/rsa_err.c index 17db7db3..053cd570 100644 --- a/libsecurity_apple_csp/open_ssl/rsa/rsa_err.c +++ b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_err.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_gen.c b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_gen.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/rsa/rsa_gen.c rename to Security/libsecurity_apple_csp/open_ssl/rsa/rsa_gen.c index 23ab1977..3687e0c4 100644 --- a/libsecurity_apple_csp/open_ssl/rsa/rsa_gen.c +++ b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_gen.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_lib.c b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_lib.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/rsa/rsa_lib.c rename to Security/libsecurity_apple_csp/open_ssl/rsa/rsa_lib.c index 733cbf17..8b09b64c 100644 --- a/libsecurity_apple_csp/open_ssl/rsa/rsa_lib.c +++ b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_lib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_none.c b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_none.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/rsa/rsa_none.c rename to Security/libsecurity_apple_csp/open_ssl/rsa/rsa_none.c index d340c8f3..91dbf2ff 100644 --- a/libsecurity_apple_csp/open_ssl/rsa/rsa_none.c +++ b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_none.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_null.c b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_null.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/rsa/rsa_null.c rename to Security/libsecurity_apple_csp/open_ssl/rsa/rsa_null.c index f3268fa8..ae373438 100644 --- a/libsecurity_apple_csp/open_ssl/rsa/rsa_null.c +++ b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_null.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_pk1.c b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_pk1.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/rsa/rsa_pk1.c rename to Security/libsecurity_apple_csp/open_ssl/rsa/rsa_pk1.c index 98fc3c88..46f90e38 100644 --- a/libsecurity_apple_csp/open_ssl/rsa/rsa_pk1.c +++ b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_pk1.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_saos.c b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_saos.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/rsa/rsa_saos.c rename to Security/libsecurity_apple_csp/open_ssl/rsa/rsa_saos.c index 82d4c617..29f51127 100644 --- a/libsecurity_apple_csp/open_ssl/rsa/rsa_saos.c +++ b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_saos.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_sign.c b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_sign.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/rsa/rsa_sign.c rename to Security/libsecurity_apple_csp/open_ssl/rsa/rsa_sign.c index ebfd14f5..899811c4 100644 --- a/libsecurity_apple_csp/open_ssl/rsa/rsa_sign.c +++ b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_sign.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/rsa/rsa_ssl.c b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_ssl.c similarity index 98% rename from libsecurity_apple_csp/open_ssl/rsa/rsa_ssl.c rename to Security/libsecurity_apple_csp/open_ssl/rsa/rsa_ssl.c index 3b5ca851..9abd2a79 100644 --- a/libsecurity_apple_csp/open_ssl/rsa/rsa_ssl.c +++ b/Security/libsecurity_apple_csp/open_ssl/rsa/rsa_ssl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/open_ssl/stack/stack.c b/Security/libsecurity_apple_csp/open_ssl/stack/stack.c similarity index 99% rename from libsecurity_apple_csp/open_ssl/stack/stack.c rename to Security/libsecurity_apple_csp/open_ssl/stack/stack.c index d62120c7..0a0bd676 100644 --- a/libsecurity_apple_csp/open_ssl/stack/stack.c +++ b/Security/libsecurity_apple_csp/open_ssl/stack/stack.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/tests/t-dsa.cpp b/Security/libsecurity_apple_csp/tests/t-dsa.cpp similarity index 98% rename from libsecurity_apple_csp/tests/t-dsa.cpp rename to Security/libsecurity_apple_csp/tests/t-dsa.cpp index 47d20b31..bc995519 100644 --- a/libsecurity_apple_csp/tests/t-dsa.cpp +++ b/Security/libsecurity_apple_csp/tests/t-dsa.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/tests/t-rsa.cpp b/Security/libsecurity_apple_csp/tests/t-rsa.cpp similarity index 98% rename from libsecurity_apple_csp/tests/t-rsa.cpp rename to Security/libsecurity_apple_csp/tests/t-rsa.cpp index 950c647e..5a09f88a 100644 --- a/libsecurity_apple_csp/tests/t-rsa.cpp +++ b/Security/libsecurity_apple_csp/tests/t-rsa.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_csp/tests/t.cpp b/Security/libsecurity_apple_csp/tests/t.cpp similarity index 98% rename from libsecurity_apple_csp/tests/t.cpp rename to Security/libsecurity_apple_csp/tests/t.cpp index 3ed1c7f4..fe402dad 100644 --- a/libsecurity_apple_csp/tests/t.cpp +++ b/Security/libsecurity_apple_csp/tests/t.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_cspdl/Info-security_apple_cspdl.plist b/Security/libsecurity_apple_cspdl/Info-security_apple_cspdl.plist similarity index 100% rename from libsecurity_apple_cspdl/Info-security_apple_cspdl.plist rename to Security/libsecurity_apple_cspdl/Info-security_apple_cspdl.plist diff --git a/libsecurity_apple_cspdl/lib/AppleCSPDLBuiltin.cpp b/Security/libsecurity_apple_cspdl/lib/AppleCSPDLBuiltin.cpp similarity index 94% rename from libsecurity_apple_cspdl/lib/AppleCSPDLBuiltin.cpp rename to Security/libsecurity_apple_cspdl/lib/AppleCSPDLBuiltin.cpp index ca98a901..23ba8bdf 100644 --- a/libsecurity_apple_cspdl/lib/AppleCSPDLBuiltin.cpp +++ b/Security/libsecurity_apple_cspdl/lib/AppleCSPDLBuiltin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_cspdl/lib/AppleCSPDLPlugin.cpp b/Security/libsecurity_apple_cspdl/lib/AppleCSPDLPlugin.cpp similarity index 94% rename from libsecurity_apple_cspdl/lib/AppleCSPDLPlugin.cpp rename to Security/libsecurity_apple_cspdl/lib/AppleCSPDLPlugin.cpp index 3727274e..97c700bb 100644 --- a/libsecurity_apple_cspdl/lib/AppleCSPDLPlugin.cpp +++ b/Security/libsecurity_apple_cspdl/lib/AppleCSPDLPlugin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_cspdl/lib/CSPDLDatabase.cpp b/Security/libsecurity_apple_cspdl/lib/CSPDLDatabase.cpp similarity index 95% rename from libsecurity_apple_cspdl/lib/CSPDLDatabase.cpp rename to Security/libsecurity_apple_cspdl/lib/CSPDLDatabase.cpp index 219b4881..8860cd0d 100644 --- a/libsecurity_apple_cspdl/lib/CSPDLDatabase.cpp +++ b/Security/libsecurity_apple_cspdl/lib/CSPDLDatabase.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_cspdl/lib/CSPDLDatabase.h b/Security/libsecurity_apple_cspdl/lib/CSPDLDatabase.h similarity index 95% rename from libsecurity_apple_cspdl/lib/CSPDLDatabase.h rename to Security/libsecurity_apple_cspdl/lib/CSPDLDatabase.h index 499cebc8..38ca1344 100644 --- a/libsecurity_apple_cspdl/lib/CSPDLDatabase.h +++ b/Security/libsecurity_apple_cspdl/lib/CSPDLDatabase.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_cspdl/lib/CSPDLPlugin.cpp b/Security/libsecurity_apple_cspdl/lib/CSPDLPlugin.cpp similarity index 96% rename from libsecurity_apple_cspdl/lib/CSPDLPlugin.cpp rename to Security/libsecurity_apple_cspdl/lib/CSPDLPlugin.cpp index f101211d..629d738e 100644 --- a/libsecurity_apple_cspdl/lib/CSPDLPlugin.cpp +++ b/Security/libsecurity_apple_cspdl/lib/CSPDLPlugin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_cspdl/lib/CSPDLPlugin.h b/Security/libsecurity_apple_cspdl/lib/CSPDLPlugin.h similarity index 96% rename from libsecurity_apple_cspdl/lib/CSPDLPlugin.h rename to Security/libsecurity_apple_cspdl/lib/CSPDLPlugin.h index 9fd62d43..bdc8da03 100644 --- a/libsecurity_apple_cspdl/lib/CSPDLPlugin.h +++ b/Security/libsecurity_apple_cspdl/lib/CSPDLPlugin.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_cspdl/lib/SSCSPDLSession.cpp b/Security/libsecurity_apple_cspdl/lib/SSCSPDLSession.cpp similarity index 98% rename from libsecurity_apple_cspdl/lib/SSCSPDLSession.cpp rename to Security/libsecurity_apple_cspdl/lib/SSCSPDLSession.cpp index 30514716..3c6b24e4 100644 --- a/libsecurity_apple_cspdl/lib/SSCSPDLSession.cpp +++ b/Security/libsecurity_apple_cspdl/lib/SSCSPDLSession.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2008,2011-2012 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_cspdl/lib/SSCSPDLSession.h b/Security/libsecurity_apple_cspdl/lib/SSCSPDLSession.h similarity index 96% rename from libsecurity_apple_cspdl/lib/SSCSPDLSession.h rename to Security/libsecurity_apple_cspdl/lib/SSCSPDLSession.h index f8c942ab..637655c8 100644 --- a/libsecurity_apple_cspdl/lib/SSCSPDLSession.h +++ b/Security/libsecurity_apple_cspdl/lib/SSCSPDLSession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_cspdl/lib/SSCSPSession.cpp b/Security/libsecurity_apple_cspdl/lib/SSCSPSession.cpp similarity index 99% rename from libsecurity_apple_cspdl/lib/SSCSPSession.cpp rename to Security/libsecurity_apple_cspdl/lib/SSCSPSession.cpp index 994ef203..199ae3ae 100644 --- a/libsecurity_apple_cspdl/lib/SSCSPSession.cpp +++ b/Security/libsecurity_apple_cspdl/lib/SSCSPSession.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_cspdl/lib/SSCSPSession.h b/Security/libsecurity_apple_cspdl/lib/SSCSPSession.h similarity index 98% rename from libsecurity_apple_cspdl/lib/SSCSPSession.h rename to Security/libsecurity_apple_cspdl/lib/SSCSPSession.h index 35da7496..b56b5f17 100644 --- a/libsecurity_apple_cspdl/lib/SSCSPSession.h +++ b/Security/libsecurity_apple_cspdl/lib/SSCSPSession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_cspdl/lib/SSContext.cpp b/Security/libsecurity_apple_cspdl/lib/SSContext.cpp similarity index 99% rename from libsecurity_apple_cspdl/lib/SSContext.cpp rename to Security/libsecurity_apple_cspdl/lib/SSContext.cpp index df3e887b..3d5de0ab 100644 --- a/libsecurity_apple_cspdl/lib/SSContext.cpp +++ b/Security/libsecurity_apple_cspdl/lib/SSContext.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_cspdl/lib/SSContext.h b/Security/libsecurity_apple_cspdl/lib/SSContext.h similarity index 98% rename from libsecurity_apple_cspdl/lib/SSContext.h rename to Security/libsecurity_apple_cspdl/lib/SSContext.h index 942d2d93..bf59ec76 100644 --- a/libsecurity_apple_cspdl/lib/SSContext.h +++ b/Security/libsecurity_apple_cspdl/lib/SSContext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_cspdl/lib/SSDLSession.cpp b/Security/libsecurity_apple_cspdl/lib/SSDLSession.cpp similarity index 98% rename from libsecurity_apple_cspdl/lib/SSDLSession.cpp rename to Security/libsecurity_apple_cspdl/lib/SSDLSession.cpp index cde4301a..8fa42e44 100644 --- a/libsecurity_apple_cspdl/lib/SSDLSession.cpp +++ b/Security/libsecurity_apple_cspdl/lib/SSDLSession.cpp @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. - * + * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved. + * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). * You may not use this file except in compliance with the License. Please obtain * a copy of the License at http://www.apple.com/publicsource and read it before * using this file. - * + * * This 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 @@ -351,7 +351,7 @@ SSDLSession::DataGetFirst(CSSM_DB_HANDLE inDbHandle, // Set the length and data on the data we return to the client inoutData->Length = sizeof(*outKey); - inoutData->Data = reinterpret_cast(outKey); + inoutData->Data = reinterpret_cast(outKey); } } @@ -412,7 +412,7 @@ SSDLSession::DataGetNext(CSSM_DB_HANDLE inDbHandle, // Set the length and data on the data we return to the client inoutData->Length = sizeof(*outKey); - inoutData->Data = reinterpret_cast(outKey); + inoutData->Data = reinterpret_cast(outKey); } } @@ -440,7 +440,7 @@ SSDLSession::DataGetFromUniqueRecordId(CSSM_DB_HANDLE inDbHandle, { SSDatabase db = findDbHandle(inDbHandle); const SSUniqueRecord uniqueId = findSSUniqueRecord(inUniqueRecord); - + // Setup so we always retrive the attributes even if the client // doesn't want them so we can figure out if we just retrived a key. CSSM_DB_RECORD_ATTRIBUTE_DATA attributes; @@ -453,7 +453,7 @@ SSDLSession::DataGetFromUniqueRecordId(CSSM_DB_HANDLE inDbHandle, memset(pAttributes, 0, sizeof(attributes)); } - CSSM_RETURN result = CSSM_DL_DataGetFromUniqueRecordId(db->handle(), + CSSM_RETURN result = CSSM_DL_DataGetFromUniqueRecordId(db->handle(), uniqueId, pAttributes, inoutData); if (result) CssmError::throwMe(result); @@ -474,7 +474,7 @@ SSDLSession::DataGetFromUniqueRecordId(CSSM_DB_HANDLE inDbHandle, // Set the length and data on the data we return to the client inoutData->Length = sizeof(*outKey); - inoutData->Data = reinterpret_cast(outKey); + inoutData->Data = reinterpret_cast(outKey); } } } @@ -486,6 +486,9 @@ SSDLSession::FreeUniqueRecord(CSSM_DB_HANDLE inDbHandle, killSSUniqueRecord(inUniqueRecordIdentifier); } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-const-variable" + static const uint32 kGenericAttributeNames[] = { 'cdat', 'mdat', 'desc', 'icmt', 'crtr', 'type', 'scrp', 7, 8, 'invi', 'nega', 'cusi', 'prot', 'acct', 'svce', @@ -528,6 +531,8 @@ const unsigned kSymmetricKeyLabel = 6; // record id for the symmetric key const unsigned kLabelSize = 20; const unsigned kNumSymmetricAttributes = 27; // number of attributes to request +#pragma clang diagnostic pop + static void appendUInt32ToData (const uint32 value, CssmDataContainer &data) { data.append (CssmPolyData (uint32 (htonl (value)))); @@ -549,13 +554,13 @@ SSDLSession::unwrapAttributesAndData (uint32 &numAttributes, // get the number of attributes uint8* finger = input.Data; numAttributes = GetUInt32AtFinger (finger); - + // compute the end of the data for sanity checking later uint8* maximum = input.Data + input.Length; - + // make the attribute array attributes = (CSSM_DB_ATTRIBUTE_DATA*) allocator ().malloc (numAttributes * sizeof (CSSM_DB_ATTRIBUTE_DATA)); - + // for each attribute, retrieve the name format, name, type, and number of values unsigned i; for (i = 0; i < numAttributes; ++i) @@ -564,7 +569,7 @@ SSDLSession::unwrapAttributesAndData (uint32 &numAttributes, attributes[i].Info.Label.AttributeID = GetUInt32AtFinger (finger); attributes[i].Info.AttributeFormat = GetUInt32AtFinger (finger); attributes[i].NumberOfValues = GetUInt32AtFinger (finger); - + // for each value, get the length and data attributes[i].Value = (CSSM_DATA*) allocator ().malloc (sizeof (CSSM_DATA) * attributes[i].NumberOfValues); unsigned j; @@ -580,7 +585,7 @@ SSDLSession::unwrapAttributesAndData (uint32 &numAttributes, } attributes[i].Value[j].Data = (uint8*) allocator ().malloc (attributes[i].Value[j].Length); - + switch (attributes[i].Info.AttributeFormat) { default: @@ -589,14 +594,14 @@ SSDLSession::unwrapAttributesAndData (uint32 &numAttributes, finger += attributes[i].Value[j].Length; break; } - + case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: { *(uint32*) attributes[i].Value[j].Data = GetUInt32AtFinger (finger); break; } - + case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32: { uint32* d = (uint32*) attributes[i].Value[j].Data; @@ -615,7 +620,7 @@ SSDLSession::unwrapAttributesAndData (uint32 &numAttributes, } } } - + // get the data data.Length = GetUInt32AtFinger (finger); if (data.Length != 0) @@ -646,7 +651,7 @@ SSDLSession::getWrappedAttributesAndData (SSDatabase &db, // figure out which attributes to use const uint32* attributeNameArray; uint32 numAttributeNames; - + switch (recordType) { case CSSM_DL_DB_RECORD_GENERIC_PASSWORD: @@ -655,28 +660,28 @@ SSDLSession::getWrappedAttributesAndData (SSDatabase &db, numAttributeNames = kNumGenericAttributes; break; } - + case CSSM_DL_DB_RECORD_INTERNET_PASSWORD: { attributeNameArray = kInternetPasswordNames; numAttributeNames = kNumInternetPasswordAttributes; break; } - + case CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD: { attributeNameArray = kApplesharePasswordNames; numAttributeNames = kNumApplesharePasswordAttributes; break; } - + case CSSM_DL_DB_RECORD_X509_CERTIFICATE: { attributeNameArray = kCertificateAttributeNames; numAttributeNames = kNumCertificateAttributes; break; } - + case CSSM_DL_DB_RECORD_PUBLIC_KEY: case CSSM_DL_DB_RECORD_PRIVATE_KEY: case CSSM_DL_DB_RECORD_SYMMETRIC_KEY: @@ -691,13 +696,13 @@ SSDLSession::getWrappedAttributesAndData (SSDatabase &db, CssmError::throwMe (CSSMERR_DL_FUNCTION_NOT_IMPLEMENTED); } } - + // make the attribute array size_t arraySize = numAttributeNames * sizeof (CSSM_DB_ATTRIBUTE_DATA); - + CSSM_DB_ATTRIBUTE_DATA_PTR attributes = (CSSM_DB_ATTRIBUTE_DATA_PTR) allocator ().malloc (arraySize); - + // initialize the array memset (attributes, 0, arraySize); unsigned i; @@ -706,14 +711,14 @@ SSDLSession::getWrappedAttributesAndData (SSDatabase &db, attributes[i].Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER; attributes[i].Info.Label.AttributeID = attributeNameArray[i]; } - + // make the attribute record CSSM_DB_RECORD_ATTRIBUTE_DATA attrData; attrData.DataRecordType = recordType; attrData.SemanticInformation = 0; attrData.NumberOfAttributes = numAttributeNames; attrData.AttributeData = attributes; - + // get the data CssmDataContainer data; CSSM_RETURN result = CSSM_DL_DataGetFromUniqueRecordId (db->handle (), @@ -724,10 +729,10 @@ SSDLSession::getWrappedAttributesAndData (SSDatabase &db, { CssmError::throwMe (result); } - + // wrap the data -- write the number of attributes appendUInt32ToData (numAttributeNames, output); - + // for each attribute, write the type and number of values for (i = 0; i < numAttributeNames; ++i) { @@ -735,7 +740,7 @@ SSDLSession::getWrappedAttributesAndData (SSDatabase &db, appendUInt32ToData (attributes[i].Info.Label.AttributeID, output); appendUInt32ToData (attributes[i].Info.AttributeFormat, output); appendUInt32ToData (attributes[i].NumberOfValues, output); - + // for each value, write the name format, name, length and the data unsigned j; for (j = 0; j < attributes[i].NumberOfValues; ++j) @@ -750,7 +755,7 @@ SSDLSession::getWrappedAttributesAndData (SSDatabase &db, output.append (CssmPolyData (attributes[i].Value[j])); break; } - + case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: { @@ -765,16 +770,16 @@ SSDLSession::getWrappedAttributesAndData (SSDatabase &db, } } } - + // write the length of the data appendUInt32ToData ((uint32)data.Length, output); - + // write the data itself if (data.Length != 0) { output.append (CssmPolyData (data)); } - + // clean up for (i = 0; i < numAttributeNames; ++i) { @@ -783,12 +788,12 @@ SSDLSession::getWrappedAttributesAndData (SSDatabase &db, { allocator ().free (attributes[i].Value[j].Data); } - + allocator ().free (attributes[i].Value); } - + allocator ().free (attributes); - + // copy out the data if the caller needs it if (dataBlob) { @@ -818,14 +823,14 @@ SSDLSession::getUniqueIdForSymmetricKey (SSDatabase &db, CSSM_DATA &label, query.Conjunctive = CSSM_DB_NONE; query.NumSelectionPredicates = 1; query.SelectionPredicate = &predicate; - + // fill out the record data CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttributeData; recordAttributeData.DataRecordType = CSSM_DL_DB_RECORD_SYMMETRIC_KEY; recordAttributeData.SemanticInformation = 0; recordAttributeData.NumberOfAttributes = 0; recordAttributeData.AttributeData = NULL; - + // get the data CSSM_HANDLE handle; CSSM_RETURN result = CSSM_DL_DataGetFirst (db->handle (), &query, &handle, &recordAttributeData, NULL, @@ -848,7 +853,7 @@ SSDLSession::getCorrespondingSymmetricKey (SSDatabase &db, CSSM_DATA &labelData, // from this. get the wrapped attributes and data getWrappedAttributesAndData (db, CSSM_DL_DB_RECORD_SYMMETRIC_KEY, uniqueRecord, data, NULL); - + // clean up after the query CSSM_DL_FreeUniqueRecord (db->handle (), uniqueRecord); } @@ -857,19 +862,19 @@ void SSDLSession::doGetWithoutEncryption (SSDatabase &db, const void *inInputPar { CSSM_APPLECSPDL_DB_GET_WITHOUT_ENCRYPTION_PARAMETERS* params = (CSSM_APPLECSPDL_DB_GET_WITHOUT_ENCRYPTION_PARAMETERS*) inInputParams; - + SSUniqueRecord uniqueID = findSSUniqueRecord(*(params->uniqueID)); - + CSSM_DATA *outputData = (CSSM_DATA*) outOutputParams; CssmDataContainer output; - + // get the record type and requested attributes from the DL CssmDataContainer data; CSSM_RETURN result = CSSM_DL_DataGetFromUniqueRecordId(db->handle(), uniqueID, params->attributes, NULL); - + if (result) { CssmError::throwMe(result); @@ -878,11 +883,11 @@ void SSDLSession::doGetWithoutEncryption (SSDatabase &db, const void *inInputPar // get the real data and all of the attributes from the DL CssmDataContainer blobData; getWrappedAttributesAndData (db, params->attributes->DataRecordType, uniqueID, data, &blobData); - + // write out the data blob appendUInt32ToData ((uint32)data.Length, output); output.append (CssmPolyData (data)); - + // figure out what we need to do with the key blob CssmDataContainer key; switch (params->attributes->DataRecordType) @@ -898,14 +903,14 @@ void SSDLSession::doGetWithoutEncryption (SSDatabase &db, const void *inInputPar getCorrespondingSymmetricKey (db, label, key); } break; - + default: { break; } } - - + + // write out the length of the key blob appendUInt32ToData ((uint32)key.Length, output); @@ -914,7 +919,7 @@ void SSDLSession::doGetWithoutEncryption (SSDatabase &db, const void *inInputPar // write the key output.append (CssmPolyData (key)); } - + // copy out the results outputData->Data = output.Data; output.Data = NULL; @@ -933,10 +938,10 @@ SSDLSession::cleanupAttributes (uint32 numAttributes, CSSM_DB_ATTRIBUTE_DATA_PTR { free (attributes[i].Value[j].Data); } - + free (attributes[i].Value); } - + free (attributes); } @@ -946,7 +951,7 @@ SSDLSession::doModifyWithoutEncryption (SSDatabase &db, const void* inInputParam CSSM_RETURN result; CSSM_APPLECSPDL_DB_MODIFY_WITHOUT_ENCRYPTION_PARAMETERS* params = (CSSM_APPLECSPDL_DB_MODIFY_WITHOUT_ENCRYPTION_PARAMETERS*) inInputParams; - + // extract the data for this modify. uint8* finger = params->data->Data; CSSM_DATA data; @@ -956,28 +961,28 @@ SSDLSession::doModifyWithoutEncryption (SSDatabase &db, const void* inInputParam { CssmError::throwMe (CSSM_ERRCODE_INVALID_POINTER); } - + // point to the key finger += data.Length; - + // reconstruct the attributes and data uint32 numAttributes; CSSM_DB_ATTRIBUTE_DATA_PTR attributes; CssmDataContainer dataBlob; - + unwrapAttributesAndData (numAttributes, attributes, dataBlob, data); - + CSSM_DB_RECORD_ATTRIBUTE_DATA attrData; attrData.DataRecordType = params->attributes->DataRecordType; attrData.SemanticInformation = 0; attrData.NumberOfAttributes = numAttributes; attrData.AttributeData = attributes; - + // get the unique ID for this record (from the db's perspective) SSUniqueRecord uniqueID = findSSUniqueRecord(*(params->uniqueID)); CSSM_DB_UNIQUE_RECORD *uniqueIDPtr = uniqueID; // for readability. There's cast overloading // going on here. - + switch (attrData.DataRecordType) { case CSSM_DL_DB_RECORD_GENERIC_PASSWORD: @@ -994,33 +999,33 @@ SSDLSession::doModifyWithoutEncryption (SSDatabase &db, const void* inInputParam { CssmError::throwMe (result); } - + CSSM_DB_MODIFY_MODE modifyMode = params->modifyMode; // parse the key data blob CssmDataContainer keyBlob; data.Length = GetUInt32AtFinger (finger); data.Data = finger; - + CSSM_DB_RECORD_ATTRIBUTE_DATA* attrDataPtr = NULL; CSSM_DB_RECORD_ATTRIBUTE_DATA attrData; - + CSSM_DATA labelData = {kLabelSize, oldData.Data}; CSSM_DB_UNIQUE_RECORD_PTR recordID; getUniqueIdForSymmetricKey (db, labelData, recordID); - + CSSM_DB_ATTRIBUTE_DATA_PTR keyAttributes; uint32 numKeyAttributes; unwrapAttributesAndData (numKeyAttributes, keyAttributes, keyBlob, data); - + // make the attribute data attrData.DataRecordType = params->recordType; attrData.SemanticInformation = 0; attrData.NumberOfAttributes = numKeyAttributes; attrData.AttributeData = keyAttributes; - + attrDataPtr = &attrData; - + result = CSSM_DL_DataModify (db->handle(), CSSM_DL_DB_RECORD_SYMMETRIC_KEY, recordID, @@ -1030,11 +1035,11 @@ SSDLSession::doModifyWithoutEncryption (SSDatabase &db, const void* inInputParam // clean up CSSM_DL_FreeUniqueRecord (db->handle (), recordID); - + cleanupAttributes (numKeyAttributes, keyAttributes); break; } - + default: { break; @@ -1051,7 +1056,7 @@ SSDLSession::doModifyWithoutEncryption (SSDatabase &db, const void* inInputParam // clean up cleanupAttributes (numAttributes, attributes); - + if (result) { CssmError::throwMe(result); @@ -1066,28 +1071,28 @@ SSDLSession::doInsertWithoutEncryption (SSDatabase &db, const void* inInputParam CSSM_APPLECSPDL_DB_INSERT_WITHOUT_ENCRYPTION_PARAMETERS* params = (CSSM_APPLECSPDL_DB_INSERT_WITHOUT_ENCRYPTION_PARAMETERS*) inInputParams; - + // extract the data for this insert. uint8* finger = params->data.Data; CSSM_DATA data; data.Length = GetUInt32AtFinger (finger); data.Data = finger; finger += data.Length; - + // reconstruct the attributes and data uint32 numAttributes; CSSM_DB_ATTRIBUTE_DATA_PTR attributes; CSSM_DATA dataBlob; - + unwrapAttributesAndData (numAttributes, attributes, dataBlob, data); - + // make the attribute data CSSM_DB_RECORD_ATTRIBUTE_DATA attrData; attrData.DataRecordType = params->recordType; attrData.SemanticInformation = 0; attrData.NumberOfAttributes = numAttributes; attrData.AttributeData = attributes; - + // insert into the database SSUniqueRecord uniqueID (db); result = CSSM_DL_DataInsert (db->handle(), params->recordType, @@ -1102,7 +1107,7 @@ SSDLSession::doInsertWithoutEncryption (SSDatabase &db, const void* inInputParam // attach into the CSP/DL mechanism CSSM_DB_UNIQUE_RECORD_PTR newRecord = makeSSUniqueRecord(uniqueID); *(CSSM_DB_UNIQUE_RECORD_PTR*) outOutputParams = newRecord; - + if (result) { CssmError::throwMe(result); @@ -1116,7 +1121,7 @@ SSDLSession::doInsertWithoutEncryption (SSDatabase &db, const void* inInputParam // parse the key data blob unwrapAttributesAndData (numAttributes, attributes, dataBlob, data); - + // make the attribute data CSSM_DB_RECORD_ATTRIBUTE_DATA attrData; attrData.DataRecordType = params->recordType; @@ -1132,7 +1137,7 @@ SSDLSession::doInsertWithoutEncryption (SSDatabase &db, const void* inInputParam { CssmError::throwMe (result); } - + // clean up after inserting the key CSSM_DL_FreeUniqueRecord (db->handle (), uniqueRecord); allocator ().free (dataBlob.Data); @@ -1151,13 +1156,13 @@ SSDLSession::doConvertRecordIdentifier (SSDatabase &db, const void *inInputParam // set the value of the unique record uniqueId->setUniqueRecordPtr (clone); - + // byte swap the retrieved record pointer to host order uint32* idArray = (uint32*) clone->RecordIdentifier.Data; idArray[0] = ntohl (idArray[0]); idArray[1] = ntohl (idArray[1]); idArray[2] = ntohl (idArray[2]); - + CSSM_DB_UNIQUE_RECORD_PTR newRecord = makeSSUniqueRecord(uniqueId); *(CSSM_DB_UNIQUE_RECORD_PTR*) outOutputParams = newRecord; } @@ -1175,7 +1180,7 @@ SSDLSession::PassThrough(CSSM_DB_HANDLE inDbHandle, * (CSSM_DB_HANDLE*) outOutputParams); return; } - + SSDatabase db = findDbHandle(inDbHandle); switch (inPassThroughId) { @@ -1270,7 +1275,7 @@ SSDLSession::PassThrough(CSSM_DB_HANDLE inDbHandle, const CSSM_APPLECSPDL_RECODE_PARAMETERS *params = reinterpret_cast(inInputParams); - + db->recode(CssmData::overlay(params->dbBlob), CssmData::overlay(params->extraData)); break; @@ -1339,7 +1344,7 @@ SSDLSession::killDbHandle(CSSM_DB_HANDLE inDbHandle) // fprintf(stderr, "Can't find %p in %p\n", (void*) inDbHandle, this); CssmError::throwMe(CSSMERR_DL_INVALID_DB_HANDLE); } - + SSDatabase db = it->second; // fprintf(stderr, "%p Removed %p from %p\n", pthread_self(), (void*) it->first, (void*) this); mDbHandleMap.erase(it); @@ -1361,7 +1366,7 @@ SSDLSession::findDbHandle(CSSM_DB_HANDLE inDbHandle) // fprintf(stderr, "\t%p\n", (void*) it->first); it++; } - + CssmError::throwMe(CSSMERR_DL_INVALID_DB_HANDLE); } diff --git a/libsecurity_apple_cspdl/lib/SSDLSession.h b/Security/libsecurity_apple_cspdl/lib/SSDLSession.h similarity index 99% rename from libsecurity_apple_cspdl/lib/SSDLSession.h rename to Security/libsecurity_apple_cspdl/lib/SSDLSession.h index a053a362..6ecb2959 100644 --- a/libsecurity_apple_cspdl/lib/SSDLSession.h +++ b/Security/libsecurity_apple_cspdl/lib/SSDLSession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_cspdl/lib/SSDatabase.cpp b/Security/libsecurity_apple_cspdl/lib/SSDatabase.cpp similarity index 99% rename from libsecurity_apple_cspdl/lib/SSDatabase.cpp rename to Security/libsecurity_apple_cspdl/lib/SSDatabase.cpp index fe5de190..672dae88 100644 --- a/libsecurity_apple_cspdl/lib/SSDatabase.cpp +++ b/Security/libsecurity_apple_cspdl/lib/SSDatabase.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_cspdl/lib/SSDatabase.h b/Security/libsecurity_apple_cspdl/lib/SSDatabase.h similarity index 98% rename from libsecurity_apple_cspdl/lib/SSDatabase.h rename to Security/libsecurity_apple_cspdl/lib/SSDatabase.h index c1f6ea8b..1566aed2 100644 --- a/libsecurity_apple_cspdl/lib/SSDatabase.h +++ b/Security/libsecurity_apple_cspdl/lib/SSDatabase.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_cspdl/lib/SSFactory.cpp b/Security/libsecurity_apple_cspdl/lib/SSFactory.cpp similarity index 97% rename from libsecurity_apple_cspdl/lib/SSFactory.cpp rename to Security/libsecurity_apple_cspdl/lib/SSFactory.cpp index 93f0dcaa..49e044c8 100644 --- a/libsecurity_apple_cspdl/lib/SSFactory.cpp +++ b/Security/libsecurity_apple_cspdl/lib/SSFactory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_cspdl/lib/SSFactory.h b/Security/libsecurity_apple_cspdl/lib/SSFactory.h similarity index 95% rename from libsecurity_apple_cspdl/lib/SSFactory.h rename to Security/libsecurity_apple_cspdl/lib/SSFactory.h index 8fadae8b..1aa9c7c8 100644 --- a/libsecurity_apple_cspdl/lib/SSFactory.h +++ b/Security/libsecurity_apple_cspdl/lib/SSFactory.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_cspdl/lib/SSKey.cpp b/Security/libsecurity_apple_cspdl/lib/SSKey.cpp similarity index 99% rename from libsecurity_apple_cspdl/lib/SSKey.cpp rename to Security/libsecurity_apple_cspdl/lib/SSKey.cpp index 472170d8..5eacdf95 100644 --- a/libsecurity_apple_cspdl/lib/SSKey.cpp +++ b/Security/libsecurity_apple_cspdl/lib/SSKey.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2008,2011-2012 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_cspdl/lib/SSKey.h b/Security/libsecurity_apple_cspdl/lib/SSKey.h similarity index 97% rename from libsecurity_apple_cspdl/lib/SSKey.h rename to Security/libsecurity_apple_cspdl/lib/SSKey.h index 03d5447d..8771e160 100644 --- a/libsecurity_apple_cspdl/lib/SSKey.h +++ b/Security/libsecurity_apple_cspdl/lib/SSKey.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_cspdl/libsecurity_apple_cspdl.xcodeproj/project.pbxproj b/Security/libsecurity_apple_cspdl/libsecurity_apple_cspdl.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_apple_cspdl/libsecurity_apple_cspdl.xcodeproj/project.pbxproj rename to Security/libsecurity_apple_cspdl/libsecurity_apple_cspdl.xcodeproj/project.pbxproj diff --git a/libsecurity_apple_cspdl/mds/cspdl_common.mdsinfo b/Security/libsecurity_apple_cspdl/mds/cspdl_common.mdsinfo similarity index 100% rename from libsecurity_apple_cspdl/mds/cspdl_common.mdsinfo rename to Security/libsecurity_apple_cspdl/mds/cspdl_common.mdsinfo diff --git a/libsecurity_apple_cspdl/mds/cspdl_csp_capabilities.mdsinfo b/Security/libsecurity_apple_cspdl/mds/cspdl_csp_capabilities.mdsinfo similarity index 100% rename from libsecurity_apple_cspdl/mds/cspdl_csp_capabilities.mdsinfo rename to Security/libsecurity_apple_cspdl/mds/cspdl_csp_capabilities.mdsinfo diff --git a/libsecurity_apple_cspdl/mds/cspdl_csp_primary.mdsinfo b/Security/libsecurity_apple_cspdl/mds/cspdl_csp_primary.mdsinfo similarity index 100% rename from libsecurity_apple_cspdl/mds/cspdl_csp_primary.mdsinfo rename to Security/libsecurity_apple_cspdl/mds/cspdl_csp_primary.mdsinfo diff --git a/libsecurity_apple_cspdl/mds/cspdl_dl_primary.mdsinfo b/Security/libsecurity_apple_cspdl/mds/cspdl_dl_primary.mdsinfo similarity index 100% rename from libsecurity_apple_cspdl/mds/cspdl_dl_primary.mdsinfo rename to Security/libsecurity_apple_cspdl/mds/cspdl_dl_primary.mdsinfo diff --git a/libsecurity_apple_file_dl/Info-security_apple_file_dl.plist b/Security/libsecurity_apple_file_dl/Info-security_apple_file_dl.plist similarity index 100% rename from libsecurity_apple_file_dl/Info-security_apple_file_dl.plist rename to Security/libsecurity_apple_file_dl/Info-security_apple_file_dl.plist diff --git a/libsecurity_apple_file_dl/TODO b/Security/libsecurity_apple_file_dl/TODO similarity index 100% rename from libsecurity_apple_file_dl/TODO rename to Security/libsecurity_apple_file_dl/TODO diff --git a/libsecurity_apple_file_dl/doc/FORMAT b/Security/libsecurity_apple_file_dl/doc/FORMAT similarity index 100% rename from libsecurity_apple_file_dl/doc/FORMAT rename to Security/libsecurity_apple_file_dl/doc/FORMAT diff --git a/libsecurity_apple_file_dl/doc/ISSUES b/Security/libsecurity_apple_file_dl/doc/ISSUES similarity index 100% rename from libsecurity_apple_file_dl/doc/ISSUES rename to Security/libsecurity_apple_file_dl/doc/ISSUES diff --git a/libsecurity_apple_file_dl/lib/AppleDLBuiltin.cpp b/Security/libsecurity_apple_file_dl/lib/AppleDLBuiltin.cpp similarity index 94% rename from libsecurity_apple_file_dl/lib/AppleDLBuiltin.cpp rename to Security/libsecurity_apple_file_dl/lib/AppleDLBuiltin.cpp index 1c022fc2..f7136530 100644 --- a/libsecurity_apple_file_dl/lib/AppleDLBuiltin.cpp +++ b/Security/libsecurity_apple_file_dl/lib/AppleDLBuiltin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_file_dl/lib/AppleDLPlugin.cpp b/Security/libsecurity_apple_file_dl/lib/AppleDLPlugin.cpp similarity index 94% rename from libsecurity_apple_file_dl/lib/AppleDLPlugin.cpp rename to Security/libsecurity_apple_file_dl/lib/AppleDLPlugin.cpp index 3425ef45..06dfdad2 100644 --- a/libsecurity_apple_file_dl/lib/AppleDLPlugin.cpp +++ b/Security/libsecurity_apple_file_dl/lib/AppleDLPlugin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_file_dl/lib/AppleFileDL.cpp b/Security/libsecurity_apple_file_dl/lib/AppleFileDL.cpp similarity index 97% rename from libsecurity_apple_file_dl/lib/AppleFileDL.cpp rename to Security/libsecurity_apple_file_dl/lib/AppleFileDL.cpp index 7e4e43e8..ce3030dc 100644 --- a/libsecurity_apple_file_dl/lib/AppleFileDL.cpp +++ b/Security/libsecurity_apple_file_dl/lib/AppleFileDL.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_file_dl/lib/AppleFileDL.h b/Security/libsecurity_apple_file_dl/lib/AppleFileDL.h similarity index 96% rename from libsecurity_apple_file_dl/lib/AppleFileDL.h rename to Security/libsecurity_apple_file_dl/lib/AppleFileDL.h index a18d31ef..20b8f67d 100644 --- a/libsecurity_apple_file_dl/lib/AppleFileDL.h +++ b/Security/libsecurity_apple_file_dl/lib/AppleFileDL.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_file_dl/libsecurity_apple_file_dl.xcodeproj/project.pbxproj b/Security/libsecurity_apple_file_dl/libsecurity_apple_file_dl.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_apple_file_dl/libsecurity_apple_file_dl.xcodeproj/project.pbxproj rename to Security/libsecurity_apple_file_dl/libsecurity_apple_file_dl.xcodeproj/project.pbxproj diff --git a/libsecurity_apple_file_dl/mds/dl_common.mdsinfo b/Security/libsecurity_apple_file_dl/mds/dl_common.mdsinfo similarity index 100% rename from libsecurity_apple_file_dl/mds/dl_common.mdsinfo rename to Security/libsecurity_apple_file_dl/mds/dl_common.mdsinfo diff --git a/libsecurity_apple_file_dl/mds/dl_primary.mdsinfo b/Security/libsecurity_apple_file_dl/mds/dl_primary.mdsinfo similarity index 100% rename from libsecurity_apple_file_dl/mds/dl_primary.mdsinfo rename to Security/libsecurity_apple_file_dl/mds/dl_primary.mdsinfo diff --git a/libsecurity_apple_x509_cl/Info-plugin_apple_x509_cl.plist b/Security/libsecurity_apple_x509_cl/Info-plugin_apple_x509_cl.plist similarity index 100% rename from libsecurity_apple_x509_cl/Info-plugin_apple_x509_cl.plist rename to Security/libsecurity_apple_x509_cl/Info-plugin_apple_x509_cl.plist diff --git a/libsecurity_apple_x509_cl/Info-security_apple_x509_cl.plist b/Security/libsecurity_apple_x509_cl/Info-security_apple_x509_cl.plist similarity index 100% rename from libsecurity_apple_x509_cl/Info-security_apple_x509_cl.plist rename to Security/libsecurity_apple_x509_cl/Info-security_apple_x509_cl.plist diff --git a/libsecurity_apple_x509_cl/TODO b/Security/libsecurity_apple_x509_cl/TODO similarity index 100% rename from libsecurity_apple_x509_cl/TODO rename to Security/libsecurity_apple_x509_cl/TODO diff --git a/libsecurity_apple_x509_cl/lib/AppleX509CL.cpp b/Security/libsecurity_apple_x509_cl/lib/AppleX509CL.cpp similarity index 96% rename from libsecurity_apple_x509_cl/lib/AppleX509CL.cpp rename to Security/libsecurity_apple_x509_cl/lib/AppleX509CL.cpp index 15a693b9..187e429f 100644 --- a/libsecurity_apple_x509_cl/lib/AppleX509CL.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/AppleX509CL.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/AppleX509CL.h b/Security/libsecurity_apple_x509_cl/lib/AppleX509CL.h similarity index 95% rename from libsecurity_apple_x509_cl/lib/AppleX509CL.h rename to Security/libsecurity_apple_x509_cl/lib/AppleX509CL.h index 426fdd4f..5c1c2236 100644 --- a/libsecurity_apple_x509_cl/lib/AppleX509CL.h +++ b/Security/libsecurity_apple_x509_cl/lib/AppleX509CL.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/AppleX509CLBuiltin.cpp b/Security/libsecurity_apple_x509_cl/lib/AppleX509CLBuiltin.cpp similarity index 94% rename from libsecurity_apple_x509_cl/lib/AppleX509CLBuiltin.cpp rename to Security/libsecurity_apple_x509_cl/lib/AppleX509CLBuiltin.cpp index eff07ff6..ccc07cd7 100644 --- a/libsecurity_apple_x509_cl/lib/AppleX509CLBuiltin.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/AppleX509CLBuiltin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/AppleX509CLPlugin.cpp b/Security/libsecurity_apple_x509_cl/lib/AppleX509CLPlugin.cpp similarity index 94% rename from libsecurity_apple_x509_cl/lib/AppleX509CLPlugin.cpp rename to Security/libsecurity_apple_x509_cl/lib/AppleX509CLPlugin.cpp index b233f89b..433cfb9c 100644 --- a/libsecurity_apple_x509_cl/lib/AppleX509CLPlugin.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/AppleX509CLPlugin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/AppleX509CLSession.cpp b/Security/libsecurity_apple_x509_cl/lib/AppleX509CLSession.cpp similarity index 97% rename from libsecurity_apple_x509_cl/lib/AppleX509CLSession.cpp rename to Security/libsecurity_apple_x509_cl/lib/AppleX509CLSession.cpp index 3793da9f..41002892 100644 --- a/libsecurity_apple_x509_cl/lib/AppleX509CLSession.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/AppleX509CLSession.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/AppleX509CLSession.h b/Security/libsecurity_apple_x509_cl/lib/AppleX509CLSession.h similarity index 99% rename from libsecurity_apple_x509_cl/lib/AppleX509CLSession.h rename to Security/libsecurity_apple_x509_cl/lib/AppleX509CLSession.h index 2ba29639..762dce74 100644 --- a/libsecurity_apple_x509_cl/lib/AppleX509CLSession.h +++ b/Security/libsecurity_apple_x509_cl/lib/AppleX509CLSession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/CLCachedEntry.cpp b/Security/libsecurity_apple_x509_cl/lib/CLCachedEntry.cpp similarity index 91% rename from libsecurity_apple_x509_cl/lib/CLCachedEntry.cpp rename to Security/libsecurity_apple_x509_cl/lib/CLCachedEntry.cpp index 2508b8c9..1e9614d3 100644 --- a/libsecurity_apple_x509_cl/lib/CLCachedEntry.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/CLCachedEntry.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,8 +19,7 @@ /* * CLCachedEntry.cpp - classes representing cached certs and CRLs. * - * Created 9/1/2000 by Doug Mitchell. - * Copyright (c) 2000 by Apple Computer. + * Copyright (c) 2000,2011,2014 Apple Inc. */ #include "CLCachedEntry.h" diff --git a/libsecurity_apple_x509_cl/lib/CLCachedEntry.h b/Security/libsecurity_apple_x509_cl/lib/CLCachedEntry.h similarity index 96% rename from libsecurity_apple_x509_cl/lib/CLCachedEntry.h rename to Security/libsecurity_apple_x509_cl/lib/CLCachedEntry.h index a0e7ee7a..30dfd0e6 100644 --- a/libsecurity_apple_x509_cl/lib/CLCachedEntry.h +++ b/Security/libsecurity_apple_x509_cl/lib/CLCachedEntry.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,8 +19,7 @@ /* * CLCachedEntry.h - classes representing cached certs and CRLs. * - * Created 9/1/2000 by Doug Mitchell. - * Copyright (c) 2000 by Apple Computer. + * Copyright (c) 2000,2011,2014 Apple Inc. */ #ifndef _APPLE_X509_CL_CACHED_ENTRY_H_ diff --git a/libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp b/Security/libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp similarity index 99% rename from libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp rename to Security/libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp index 2a5d845d..aa198e08 100644 --- a/libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/CLCertExtensions.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2012 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/CLCertExtensions.h b/Security/libsecurity_apple_x509_cl/lib/CLCertExtensions.h similarity index 97% rename from libsecurity_apple_x509_cl/lib/CLCertExtensions.h rename to Security/libsecurity_apple_x509_cl/lib/CLCertExtensions.h index 272a22e0..349b31bc 100644 --- a/libsecurity_apple_x509_cl/lib/CLCertExtensions.h +++ b/Security/libsecurity_apple_x509_cl/lib/CLCertExtensions.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2011 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/CLCrlExtensions.cpp b/Security/libsecurity_apple_x509_cl/lib/CLCrlExtensions.cpp similarity index 98% rename from libsecurity_apple_x509_cl/lib/CLCrlExtensions.cpp rename to Security/libsecurity_apple_x509_cl/lib/CLCrlExtensions.cpp index 38018df5..cf2047c1 100644 --- a/libsecurity_apple_x509_cl/lib/CLCrlExtensions.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/CLCrlExtensions.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/CLCrlExtensions.h b/Security/libsecurity_apple_x509_cl/lib/CLCrlExtensions.h similarity index 90% rename from libsecurity_apple_x509_cl/lib/CLCrlExtensions.h rename to Security/libsecurity_apple_x509_cl/lib/CLCrlExtensions.h index 6c1c4d66..be2b038e 100644 --- a/libsecurity_apple_x509_cl/lib/CLCrlExtensions.h +++ b/Security/libsecurity_apple_x509_cl/lib/CLCrlExtensions.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -21,8 +21,7 @@ * implemented in CLCrlExtensions.cpp and used * only in CrlFields.cpp. * - * Created 9/8/2000 by Doug Mitchell. - * Copyright (c) 2000 by Apple Computer. + * Copyright (c) 2000,2011,2014 Apple Inc. */ #ifndef _CL_CRL_EXTENSIONS_H_ diff --git a/libsecurity_apple_x509_cl/lib/CLFieldsCommon.cpp b/Security/libsecurity_apple_x509_cl/lib/CLFieldsCommon.cpp similarity index 99% rename from libsecurity_apple_x509_cl/lib/CLFieldsCommon.cpp rename to Security/libsecurity_apple_x509_cl/lib/CLFieldsCommon.cpp index f507a236..75943ce2 100644 --- a/libsecurity_apple_x509_cl/lib/CLFieldsCommon.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/CLFieldsCommon.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/CLFieldsCommon.h b/Security/libsecurity_apple_x509_cl/lib/CLFieldsCommon.h similarity index 98% rename from libsecurity_apple_x509_cl/lib/CLFieldsCommon.h rename to Security/libsecurity_apple_x509_cl/lib/CLFieldsCommon.h index 5a403894..b9e93437 100644 --- a/libsecurity_apple_x509_cl/lib/CLFieldsCommon.h +++ b/Security/libsecurity_apple_x509_cl/lib/CLFieldsCommon.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/CSPAttacher.cpp b/Security/libsecurity_apple_x509_cl/lib/CSPAttacher.cpp similarity index 98% rename from libsecurity_apple_x509_cl/lib/CSPAttacher.cpp rename to Security/libsecurity_apple_x509_cl/lib/CSPAttacher.cpp index b2e12a55..abdea3c2 100644 --- a/libsecurity_apple_x509_cl/lib/CSPAttacher.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/CSPAttacher.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/CSPAttacher.h b/Security/libsecurity_apple_x509_cl/lib/CSPAttacher.h similarity index 95% rename from libsecurity_apple_x509_cl/lib/CSPAttacher.h rename to Security/libsecurity_apple_x509_cl/lib/CSPAttacher.h index 31223bdf..da5f27c5 100644 --- a/libsecurity_apple_x509_cl/lib/CSPAttacher.h +++ b/Security/libsecurity_apple_x509_cl/lib/CSPAttacher.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/CertFields.cpp b/Security/libsecurity_apple_x509_cl/lib/CertFields.cpp similarity index 99% rename from libsecurity_apple_x509_cl/lib/CertFields.cpp rename to Security/libsecurity_apple_x509_cl/lib/CertFields.cpp index 8fcdc5cf..1ba276eb 100644 --- a/libsecurity_apple_x509_cl/lib/CertFields.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/CertFields.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -20,8 +20,7 @@ * CertFields.cpp - convert between NSS-based Certificate components and CDSA-style * fields. A major component of DecodedCert. * - * Created 9/1/2000 by Doug Mitchell. - * Copyright (c) 2000 by Apple Computer. + * Copyright (c) 2000,2011-2012,2014 Apple Inc. */ #include "DecodedCert.h" diff --git a/libsecurity_apple_x509_cl/lib/CrlFields.cpp b/Security/libsecurity_apple_x509_cl/lib/CrlFields.cpp similarity index 99% rename from libsecurity_apple_x509_cl/lib/CrlFields.cpp rename to Security/libsecurity_apple_x509_cl/lib/CrlFields.cpp index 7e0c3260..c3476017 100644 --- a/libsecurity_apple_x509_cl/lib/CrlFields.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/CrlFields.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -20,8 +20,7 @@ * CrlFields.cpp - convert between NSS-based NSS_Crl components and CDSA-style * fields. A major component of DecodedCrl. * - * Created 8/29/2002 by Doug Mitchell. - * Copyright (c) 2002 by Apple Computer. + * Copyright (c) 2002,2011-2012,2014 Apple Inc. */ #include "DecodedCrl.h" diff --git a/libsecurity_apple_x509_cl/lib/DecodedCert.cpp b/Security/libsecurity_apple_x509_cl/lib/DecodedCert.cpp similarity index 98% rename from libsecurity_apple_x509_cl/lib/DecodedCert.cpp rename to Security/libsecurity_apple_x509_cl/lib/DecodedCert.cpp index f1e233c9..c681d589 100644 --- a/libsecurity_apple_x509_cl/lib/DecodedCert.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/DecodedCert.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -20,8 +20,7 @@ * DecodedCert.cpp - object representing a decoded cert, in NSS * format, with extensions parsed and decoded (still in NSS format). * - * Created 9/1/2000 by Doug Mitchell. - * Copyright (c) 2000 by Apple Computer. + * Copyright (c) 2000,2011,2014 Apple Inc. */ #include "DecodedCert.h" diff --git a/libsecurity_apple_x509_cl/lib/DecodedCert.h b/Security/libsecurity_apple_x509_cl/lib/DecodedCert.h similarity index 95% rename from libsecurity_apple_x509_cl/lib/DecodedCert.h rename to Security/libsecurity_apple_x509_cl/lib/DecodedCert.h index cb3a7663..668f66e7 100644 --- a/libsecurity_apple_x509_cl/lib/DecodedCert.h +++ b/Security/libsecurity_apple_x509_cl/lib/DecodedCert.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -20,8 +20,7 @@ * DecodedCert.h - object representing an NSS-decoded cert, with extensions * parsed and decoded (still in NSS format). * - * Created 9/1/2000 by Doug Mitchell. - * Copyright (c) 2000 by Apple Computer. + * Copyright (c) 2000,2011,2014 Apple Inc. * * See DecodedItem.h for details on the care and feeding of this * module. diff --git a/libsecurity_apple_x509_cl/lib/DecodedCrl.cpp b/Security/libsecurity_apple_x509_cl/lib/DecodedCrl.cpp similarity index 96% rename from libsecurity_apple_x509_cl/lib/DecodedCrl.cpp rename to Security/libsecurity_apple_x509_cl/lib/DecodedCrl.cpp index 7f68bcb5..1613ef44 100644 --- a/libsecurity_apple_x509_cl/lib/DecodedCrl.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/DecodedCrl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -20,7 +20,6 @@ * DecodedCrl.cpp - object representing a decoded CRL, in NSS format, * with extensions parsed and decoded (still in NSS format). * - * Created 8/28/2002 by Doug Mitchell. */ #include "DecodedCrl.h" diff --git a/libsecurity_apple_x509_cl/lib/DecodedCrl.h b/Security/libsecurity_apple_x509_cl/lib/DecodedCrl.h similarity index 96% rename from libsecurity_apple_x509_cl/lib/DecodedCrl.h rename to Security/libsecurity_apple_x509_cl/lib/DecodedCrl.h index 5e889294..495e0388 100644 --- a/libsecurity_apple_x509_cl/lib/DecodedCrl.h +++ b/Security/libsecurity_apple_x509_cl/lib/DecodedCrl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -20,7 +20,6 @@ * DecodedCrl.h - object representing a decoded cert in NSS form, with * extensions parsed and decoded (still in NSS format). * - * Created 8/28/2002 by Doug Mitchell. * * See DecodedItem.h for details on the care and feeding of this * module. diff --git a/libsecurity_apple_x509_cl/lib/DecodedExtensions.cpp b/Security/libsecurity_apple_x509_cl/lib/DecodedExtensions.cpp similarity index 99% rename from libsecurity_apple_x509_cl/lib/DecodedExtensions.cpp rename to Security/libsecurity_apple_x509_cl/lib/DecodedExtensions.cpp index 2f5bedc6..ace807be 100644 --- a/libsecurity_apple_x509_cl/lib/DecodedExtensions.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/DecodedExtensions.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/DecodedExtensions.h b/Security/libsecurity_apple_x509_cl/lib/DecodedExtensions.h similarity index 98% rename from libsecurity_apple_x509_cl/lib/DecodedExtensions.h rename to Security/libsecurity_apple_x509_cl/lib/DecodedExtensions.h index 8841115b..a44f6188 100644 --- a/libsecurity_apple_x509_cl/lib/DecodedExtensions.h +++ b/Security/libsecurity_apple_x509_cl/lib/DecodedExtensions.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/DecodedItem.cpp b/Security/libsecurity_apple_x509_cl/lib/DecodedItem.cpp similarity index 97% rename from libsecurity_apple_x509_cl/lib/DecodedItem.cpp rename to Security/libsecurity_apple_x509_cl/lib/DecodedItem.cpp index 17ba9869..0dab4560 100644 --- a/libsecurity_apple_x509_cl/lib/DecodedItem.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/DecodedItem.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/DecodedItem.h b/Security/libsecurity_apple_x509_cl/lib/DecodedItem.h similarity index 99% rename from libsecurity_apple_x509_cl/lib/DecodedItem.h rename to Security/libsecurity_apple_x509_cl/lib/DecodedItem.h index c6295a01..ab67ed1f 100644 --- a/libsecurity_apple_x509_cl/lib/DecodedItem.h +++ b/Security/libsecurity_apple_x509_cl/lib/DecodedItem.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/LockedMap.h b/Security/libsecurity_apple_x509_cl/lib/LockedMap.h similarity index 93% rename from libsecurity_apple_x509_cl/lib/LockedMap.h rename to Security/libsecurity_apple_x509_cl/lib/LockedMap.h index 03da5fc1..2386a755 100644 --- a/libsecurity_apple_x509_cl/lib/LockedMap.h +++ b/Security/libsecurity_apple_x509_cl/lib/LockedMap.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,8 +19,7 @@ /* * LockedMap.h - STL-style map with attached Mutex * - * Created 9/1/2000 by Doug Mitchell. - * Copyright (c) 2000 by Apple Computer. + * Copyright (c) 2000,2011,2014 Apple Inc. */ #ifndef _LOCKED_MAP_H_ diff --git a/libsecurity_apple_x509_cl/lib/Session_CRL.cpp b/Security/libsecurity_apple_x509_cl/lib/Session_CRL.cpp similarity index 99% rename from libsecurity_apple_x509_cl/lib/Session_CRL.cpp rename to Security/libsecurity_apple_x509_cl/lib/Session_CRL.cpp index 47b6c8a8..08204e08 100644 --- a/libsecurity_apple_x509_cl/lib/Session_CRL.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/Session_CRL.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/Session_CSR.cpp b/Security/libsecurity_apple_x509_cl/lib/Session_CSR.cpp similarity index 99% rename from libsecurity_apple_x509_cl/lib/Session_CSR.cpp rename to Security/libsecurity_apple_x509_cl/lib/Session_CSR.cpp index d5a03848..ba20ba66 100644 --- a/libsecurity_apple_x509_cl/lib/Session_CSR.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/Session_CSR.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/Session_Cert.cpp b/Security/libsecurity_apple_x509_cl/lib/Session_Cert.cpp similarity index 99% rename from libsecurity_apple_x509_cl/lib/Session_Cert.cpp rename to Security/libsecurity_apple_x509_cl/lib/Session_Cert.cpp index baef2332..f15bbf4e 100644 --- a/libsecurity_apple_x509_cl/lib/Session_Cert.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/Session_Cert.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/Session_Crypto.cpp b/Security/libsecurity_apple_x509_cl/lib/Session_Crypto.cpp similarity index 98% rename from libsecurity_apple_x509_cl/lib/Session_Crypto.cpp rename to Security/libsecurity_apple_x509_cl/lib/Session_Crypto.cpp index 5b545825..cc1a8ffb 100644 --- a/libsecurity_apple_x509_cl/lib/Session_Crypto.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/Session_Crypto.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,8 +19,7 @@ /* * Session_Crypto.cpp: CL session functions: sign, verify, CSSM_KEY extraction. * - * Created 9/1/2000 by Doug Mitchell. - * Copyright (c) 2000 by Apple Computer. + * Copyright (c) 2000,2011,2014 Apple Inc. */ #include "AppleX509CLSession.h" diff --git a/libsecurity_apple_x509_cl/lib/clNameUtils.cpp b/Security/libsecurity_apple_x509_cl/lib/clNameUtils.cpp similarity index 99% rename from libsecurity_apple_x509_cl/lib/clNameUtils.cpp rename to Security/libsecurity_apple_x509_cl/lib/clNameUtils.cpp index 0c88a1eb..4eb46399 100644 --- a/libsecurity_apple_x509_cl/lib/clNameUtils.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/clNameUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/clNameUtils.h b/Security/libsecurity_apple_x509_cl/lib/clNameUtils.h similarity index 98% rename from libsecurity_apple_x509_cl/lib/clNameUtils.h rename to Security/libsecurity_apple_x509_cl/lib/clNameUtils.h index e9ffbff1..be39d41f 100644 --- a/libsecurity_apple_x509_cl/lib/clNameUtils.h +++ b/Security/libsecurity_apple_x509_cl/lib/clNameUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/clNssUtils.cpp b/Security/libsecurity_apple_x509_cl/lib/clNssUtils.cpp similarity index 99% rename from libsecurity_apple_x509_cl/lib/clNssUtils.cpp rename to Security/libsecurity_apple_x509_cl/lib/clNssUtils.cpp index a559e6ae..bad0ce39 100644 --- a/libsecurity_apple_x509_cl/lib/clNssUtils.cpp +++ b/Security/libsecurity_apple_x509_cl/lib/clNssUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/clNssUtils.h b/Security/libsecurity_apple_x509_cl/lib/clNssUtils.h similarity index 99% rename from libsecurity_apple_x509_cl/lib/clNssUtils.h rename to Security/libsecurity_apple_x509_cl/lib/clNssUtils.h index 541cb518..e62cffac 100644 --- a/libsecurity_apple_x509_cl/lib/clNssUtils.h +++ b/Security/libsecurity_apple_x509_cl/lib/clNssUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/lib/cldebugging.h b/Security/libsecurity_apple_x509_cl/lib/cldebugging.h similarity index 95% rename from libsecurity_apple_x509_cl/lib/cldebugging.h rename to Security/libsecurity_apple_x509_cl/lib/cldebugging.h index 80078490..79709bb1 100644 --- a/libsecurity_apple_x509_cl/lib/cldebugging.h +++ b/Security/libsecurity_apple_x509_cl/lib/cldebugging.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_cl/libsecurity_apple_x509_cl.xcodeproj/project.pbxproj b/Security/libsecurity_apple_x509_cl/libsecurity_apple_x509_cl.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_apple_x509_cl/libsecurity_apple_x509_cl.xcodeproj/project.pbxproj rename to Security/libsecurity_apple_x509_cl/libsecurity_apple_x509_cl.xcodeproj/project.pbxproj diff --git a/libsecurity_apple_x509_cl/mds/cl_common.mdsinfo b/Security/libsecurity_apple_x509_cl/mds/cl_common.mdsinfo similarity index 100% rename from libsecurity_apple_x509_cl/mds/cl_common.mdsinfo rename to Security/libsecurity_apple_x509_cl/mds/cl_common.mdsinfo diff --git a/libsecurity_apple_x509_cl/mds/cl_primary.mdsinfo b/Security/libsecurity_apple_x509_cl/mds/cl_primary.mdsinfo similarity index 100% rename from libsecurity_apple_x509_cl/mds/cl_primary.mdsinfo rename to Security/libsecurity_apple_x509_cl/mds/cl_primary.mdsinfo diff --git a/libsecurity_apple_x509_tp/Info-security_apple_x509_tp.plist b/Security/libsecurity_apple_x509_tp/Info-security_apple_x509_tp.plist similarity index 100% rename from libsecurity_apple_x509_tp/Info-security_apple_x509_tp.plist rename to Security/libsecurity_apple_x509_tp/Info-security_apple_x509_tp.plist diff --git a/libsecurity_apple_x509_tp/lib/AppleTP.cpp b/Security/libsecurity_apple_x509_tp/lib/AppleTP.cpp similarity index 96% rename from libsecurity_apple_x509_tp/lib/AppleTP.cpp rename to Security/libsecurity_apple_x509_tp/lib/AppleTP.cpp index 6bd8977b..f61d5475 100644 --- a/libsecurity_apple_x509_tp/lib/AppleTP.cpp +++ b/Security/libsecurity_apple_x509_tp/lib/AppleTP.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_tp/lib/AppleTP.h b/Security/libsecurity_apple_x509_tp/lib/AppleTP.h similarity index 95% rename from libsecurity_apple_x509_tp/lib/AppleTP.h rename to Security/libsecurity_apple_x509_tp/lib/AppleTP.h index ce9780e4..3d4c75c8 100644 --- a/libsecurity_apple_x509_tp/lib/AppleTP.h +++ b/Security/libsecurity_apple_x509_tp/lib/AppleTP.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_tp/lib/AppleTPSession.cpp b/Security/libsecurity_apple_x509_tp/lib/AppleTPSession.cpp similarity index 99% rename from libsecurity_apple_x509_tp/lib/AppleTPSession.cpp rename to Security/libsecurity_apple_x509_tp/lib/AppleTPSession.cpp index 211ccb01..b019a7bb 100644 --- a/libsecurity_apple_x509_tp/lib/AppleTPSession.cpp +++ b/Security/libsecurity_apple_x509_tp/lib/AppleTPSession.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_tp/lib/AppleTPSession.h b/Security/libsecurity_apple_x509_tp/lib/AppleTPSession.h similarity index 98% rename from libsecurity_apple_x509_tp/lib/AppleTPSession.h rename to Security/libsecurity_apple_x509_tp/lib/AppleTPSession.h index a595e3b7..366e021c 100644 --- a/libsecurity_apple_x509_tp/lib/AppleTPSession.h +++ b/Security/libsecurity_apple_x509_tp/lib/AppleTPSession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * AppleTPSession.h - TP session functions. * - * Created 10/5/2000 by Doug Mitchell. */ #ifndef _H_APPLE_TP_SESSION diff --git a/libsecurity_apple_x509_tp/lib/AppleX509TPBuiltin.cpp b/Security/libsecurity_apple_x509_tp/lib/AppleX509TPBuiltin.cpp similarity index 94% rename from libsecurity_apple_x509_tp/lib/AppleX509TPBuiltin.cpp rename to Security/libsecurity_apple_x509_tp/lib/AppleX509TPBuiltin.cpp index 4488d108..c55d464b 100644 --- a/libsecurity_apple_x509_tp/lib/AppleX509TPBuiltin.cpp +++ b/Security/libsecurity_apple_x509_tp/lib/AppleX509TPBuiltin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_tp/lib/AppleX509TPPlugin.cpp b/Security/libsecurity_apple_x509_tp/lib/AppleX509TPPlugin.cpp similarity index 94% rename from libsecurity_apple_x509_tp/lib/AppleX509TPPlugin.cpp rename to Security/libsecurity_apple_x509_tp/lib/AppleX509TPPlugin.cpp index 268860a7..8175c348 100644 --- a/libsecurity_apple_x509_tp/lib/AppleX509TPPlugin.cpp +++ b/Security/libsecurity_apple_x509_tp/lib/AppleX509TPPlugin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp b/Security/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp similarity index 97% rename from libsecurity_apple_x509_tp/lib/TPCertInfo.cpp rename to Security/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp index 2b12425f..2cf881e5 100644 --- a/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp +++ b/Security/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2013 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -1660,7 +1660,7 @@ CSSM_RETURN TPCertGroup::buildCertGroup( break; case kSecTrustSettingsResultUnspecified: /* special case here: this means "keep going, we don't trust or - * distrust this cert". Typically used to express allowed errors + * distrust this cert". Typically used to express allowed errors * only. */ tpTrustSettingsDbg("TrustResultUnspecified found"); @@ -1886,6 +1886,65 @@ post_trust_setting: } } + /* + * If we found a candidate issuer in input or gathered certs, check whether it + * might be a cross-signed intermediate that can be replaced with an anchor. + */ + if(issuerCert != NULL && !issuerCert->isSelfSigned()) { + bool partial = false; + TPCertInfo *possibleAnchorCert = NULL; + try { + possibleAnchorCert = tpDbFindIssuerCert(mAlloc, + clHand, + cspHand, + thisSubject, + dbList, + verifyTime, + partial); + } + catch (...) {} + + if(possibleAnchorCert != NULL) { + if(possibleAnchorCert->isSelfSigned()) { + /* + * We found a better replacement issuer, so use it. + * note that we don't need to free the old issuerCert first as it + * comes from inCertGroup or gatheredCerts (not from dbList). + * However, code from this point on cannot assume the same thing. + */ + tpDebug("buildCertGroup: replacement anchor for issuer FOUND in dbList"); + issuerCert = possibleAnchorCert; + + /* Caller must free, since this cert came from a DLDB */ + certsToBeFreed.appendCert(issuerCert); + if(partial) { + /* deal with this later */ + foundPartialIssuer = true; + } + + /* unconditionally done with possible expiredIssuer */ + #ifndef NDEBUG + if(expiredIssuer != NULL) { + tpDebug("buildCertGroup: DISCARDING expired cert %p (3)", expiredIssuer); + } + #endif + expiredIssuer = NULL; + /* unconditionally done with possible unmatchedKeyIDIssuer */ + #ifndef NDEBUG + if(unmatchedKeyIDIssuer != NULL) { + tpDebug("buildCertGroup: DISCARDING unmatched key id issuer %p (3)", unmatchedKeyIDIssuer); + } + #endif + unmatchedKeyIDIssuer = NULL; + } + else { + possibleAnchorCert->freeUniqueRecord(); + delete possibleAnchorCert; + possibleAnchorCert = NULL; + } + } + } + if((issuerCert == NULL) && (dbList != NULL)) { /* Issuer not in incoming cert group or gathered certs. Search DBList. */ bool partial = false; @@ -1904,19 +1963,18 @@ post_trust_setting: /* unconditionally done with possible expiredIssuer */ #ifndef NDEBUG if(expiredIssuer != NULL) { - tpDebug("buildCertGroup: DISCARDING expired cert %p (3)", expiredIssuer); + tpDebug("buildCertGroup: DISCARDING expired cert %p (4)", expiredIssuer); } #endif expiredIssuer = NULL; /* unconditionally done with possible unmatchedKeyIDIssuer */ #ifndef NDEBUG if(unmatchedKeyIDIssuer != NULL) { - tpDebug("buildCertGroup: DISCARDING unmatched key id issuer %p (3)", unmatchedKeyIDIssuer); + tpDebug("buildCertGroup: DISCARDING unmatched key id issuer %p (4)", unmatchedKeyIDIssuer); } #endif unmatchedKeyIDIssuer = NULL; - /* * Handle Radar 4566041, endless loop of cross-signed certs. * This can only happen when fetching certs from a DLDB or diff --git a/libsecurity_apple_x509_tp/lib/TPCertInfo.h b/Security/libsecurity_apple_x509_tp/lib/TPCertInfo.h similarity index 99% rename from libsecurity_apple_x509_tp/lib/TPCertInfo.h rename to Security/libsecurity_apple_x509_tp/lib/TPCertInfo.h index f1fb63c7..231bb870 100644 --- a/libsecurity_apple_x509_tp/lib/TPCertInfo.h +++ b/Security/libsecurity_apple_x509_tp/lib/TPCertInfo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2013 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_tp/lib/TPCrlInfo.cpp b/Security/libsecurity_apple_x509_tp/lib/TPCrlInfo.cpp similarity index 99% rename from libsecurity_apple_x509_tp/lib/TPCrlInfo.cpp rename to Security/libsecurity_apple_x509_tp/lib/TPCrlInfo.cpp index eef40e68..21581d2f 100644 --- a/libsecurity_apple_x509_tp/lib/TPCrlInfo.cpp +++ b/Security/libsecurity_apple_x509_tp/lib/TPCrlInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * TPCrlInfo.h - TP's private CRL and CRL group * - * Written 9/30/2002 by Doug Mitchell. */ #include "TPCrlInfo.h" diff --git a/libsecurity_apple_x509_tp/lib/TPCrlInfo.h b/Security/libsecurity_apple_x509_tp/lib/TPCrlInfo.h similarity index 98% rename from libsecurity_apple_x509_tp/lib/TPCrlInfo.h rename to Security/libsecurity_apple_x509_tp/lib/TPCrlInfo.h index 743b5850..124f9551 100644 --- a/libsecurity_apple_x509_tp/lib/TPCrlInfo.h +++ b/Security/libsecurity_apple_x509_tp/lib/TPCrlInfo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * TPCrlInfo.h - TP's private CRL and CRL group classes * - * Written 9/25/2001 by Doug Mitchell. */ #ifndef _TP_CRL_INFO_H_ diff --git a/libsecurity_apple_x509_tp/lib/TPDatabase.cpp b/Security/libsecurity_apple_x509_tp/lib/TPDatabase.cpp similarity index 77% rename from libsecurity_apple_x509_tp/lib/TPDatabase.cpp rename to Security/libsecurity_apple_x509_tp/lib/TPDatabase.cpp index 5c2ba89b..583b7c10 100644 --- a/libsecurity_apple_x509_tp/lib/TPDatabase.cpp +++ b/Security/libsecurity_apple_x509_tp/lib/TPDatabase.cpp @@ -1,12 +1,12 @@ /* - * Copyright (c) 2002-2009 Apple Inc. All Rights Reserved. - * + * Copyright (c) 2002-2009,2011-2012,2014 Apple Inc. All Rights Reserved. + * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). * You may not use this file except in compliance with the License. Please obtain * a copy of the License at http://www.apple.com/publicsource and read it before * using this file. - * + * * This 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 @@ -19,11 +19,10 @@ /* * TPDatabase.cpp - TP's DL/DB access functions. * - * Created 10/9/2002 by Doug Mitchell. */ #include -#include +#include #include /* private API */ #include /* private SecTrustKeychainsGetMutex() */ #include /* private SecInferLabelFromX509Name() */ @@ -48,21 +47,21 @@ static CSSM_DB_UNIQUE_RECORD_PTR tpCertLookup( CSSM_DATA_PTR cert) // RETURNED { CSSM_QUERY query; - CSSM_SELECTION_PREDICATE predicate; + CSSM_SELECTION_PREDICATE predicate; CSSM_DB_UNIQUE_RECORD_PTR record = NULL; - + cert->Data = NULL; cert->Length = 0; - + /* SWAG until cert schema nailed down */ predicate.DbOperator = CSSM_DB_EQUAL; - predicate.Attribute.Info.AttributeNameFormat = + predicate.Attribute.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; predicate.Attribute.Info.Label.AttributeName = (char*) "Subject"; predicate.Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; predicate.Attribute.Value = const_cast(subjectName); predicate.Attribute.NumberOfValues = 1; - + query.RecordType = CSSM_DL_DB_RECORD_X509_CERTIFICATE; query.Conjunctive = CSSM_DB_NONE; query.NumSelectionPredicates = 1; @@ -70,7 +69,7 @@ static CSSM_DB_UNIQUE_RECORD_PTR tpCertLookup( query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? query.QueryFlags = 0; // FIXME - used? - + CSSM_DL_DataGetFirst(dlDb, &query, resultHand, @@ -82,13 +81,13 @@ static CSSM_DB_UNIQUE_RECORD_PTR tpCertLookup( } /* - * Search a list of DBs for a cert which verifies specified subject item. + * Search a list of DBs for a cert which verifies specified subject item. * Just a boolean return - we found it, or not. If we did, we return - * TPCertInfo associated with the raw cert. + * TPCertInfo associated with the raw cert. * A true partialIssuerKey on return indicates that caller must deal - * with partial public key processing later. + * with partial public key processing later. * If verifyCurrent is true, we will not return a cert which is not - * temporally valid; else we may well do so. + * temporally valid; else we may well do so. */ TPCertInfo *tpDbFindIssuerCert( Allocator &alloc, @@ -103,13 +102,14 @@ TPCertInfo *tpDbFindIssuerCert( uint32 dbDex; CSSM_HANDLE resultHand; - CSSM_DATA cert; + CSSM_DATA cert; CSSM_DL_DB_HANDLE dlDb; CSSM_DB_UNIQUE_RECORD_PTR record; TPCertInfo *issuerCert = NULL; bool foundIt; TPCertInfo *expiredIssuer = NULL; - + TPCertInfo *nonRootIssuer = NULL; + partialIssuerKey = false; if(dbList == NULL) { return NULL; @@ -123,16 +123,16 @@ TPCertInfo *tpDbFindIssuerCert( subjectItem->issuerName(), &resultHand, &cert); - /* remember we have to: - * -- abort this query regardless, and - * -- free the CSSM_DATA cert regardless, and - * -- free the unique record if we don't use it + /* remember we have to: + * -- abort this query regardless, and + * -- free the CSSM_DATA cert regardless, and + * -- free the unique record if we don't use it * (by placing it in issuerCert)... */ if(record != NULL) { /* Found one */ assert(cert.Data != NULL); - tpDbDebug("tpDbFindIssuerCert: found cert record %p", record); + tpDbDebug("tpDbFindIssuerCert: found cert record (1) %p", record); issuerCert = NULL; CSSM_RETURN crtn = CSSM_OK; try { @@ -146,20 +146,20 @@ TPCertInfo *tpDbFindIssuerCert( tpFreePluginMemory(dlDb.DLHandle, cert.Data); cert.Data = NULL; cert.Length = 0; - + /* Does it verify the subject cert? */ if(crtn == CSSM_OK) { crtn = subjectItem->verifyWithIssuer(issuerCert); } - + /* - * Handle temporal invalidity - if so and this is the first one + * 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(issuerCert->isExpired() || issuerCert->isNotValidYet()) { - /* - * Exact value not important here, this just uniquely identifies + /* + * Exact value not important here, this just uniquely identifies * this situation in the switch below. */ tpDbDebug("tpDbFindIssuerCert: holding expired cert (1)"); @@ -169,6 +169,23 @@ TPCertInfo *tpDbFindIssuerCert( expiredIssuer->uniqueRecord(record); } } + /* + * 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; + nonRootIssuer = issuerCert; + nonRootIssuer->dlDbHandle(dlDb); + nonRootIssuer->uniqueRecord(record); + } + } switch(crtn) { case CSSM_OK: break; @@ -176,23 +193,27 @@ TPCertInfo *tpDbFindIssuerCert( partialIssuerKey = true; break; default: - issuerCert = NULL; - if(crtn != CSSM_CERT_STATUS_EXPIRED) { - delete issuerCert; - CSSM_DL_FreeUniqueRecord(dlDb, record); + if(issuerCert != NULL) { + /* either holding onto this cert, or done with it. */ + if(crtn != CSSM_CERT_STATUS_EXPIRED && + crtn != CSSM_CERT_STATUS_IS_ROOT) { + delete issuerCert; + CSSM_DL_FreeUniqueRecord(dlDb, record); + } + issuerCert = NULL; } - + /* - * Continue searching this DB. Break on finding the holy - * grail or no more records found. + * Continue searching this DB. Break on finding the holy + * grail or no more records found. */ for(;;) { cert.Data = NULL; cert.Length = 0; record = NULL; - CSSM_RETURN crtn = CSSM_DL_DataGetNext(dlDb, + CSSM_RETURN crtn = CSSM_DL_DataGetNext(dlDb, resultHand, - NULL, // no attrs + NULL, // no attrs &cert, &record); if(crtn) { @@ -201,11 +222,11 @@ TPCertInfo *tpDbFindIssuerCert( break; } assert(cert.Data != NULL); - tpDbDebug("tpDbFindIssuerCert: found cert record %p", record); - + tpDbDebug("tpDbFindIssuerCert: found cert record (2) %p", record); + /* found one - does it verify subject? */ try { - issuerCert = new TPCertInfo(clHand, cspHand, &cert, TIC_CopyData, + issuerCert = new TPCertInfo(clHand, cspHand, &cert, TIC_CopyData, verifyTime); } catch(...) { @@ -215,7 +236,7 @@ TPCertInfo *tpDbFindIssuerCert( tpFreePluginMemory(dlDb.DLHandle, cert.Data); cert.Data = NULL; cert.Length = 0; - + if(crtn == CSSM_OK) { crtn = subjectItem->verifyWithIssuer(issuerCert); } @@ -230,6 +251,16 @@ TPCertInfo *tpDbFindIssuerCert( 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; + nonRootIssuer = issuerCert; + nonRootIssuer->dlDbHandle(dlDb); + nonRootIssuer->uniqueRecord(record); + } + } foundIt = false; switch(crtn) { @@ -247,11 +278,15 @@ TPCertInfo *tpDbFindIssuerCert( /* yes! */ break; } - if(crtn != CSSM_CERT_STATUS_EXPIRED) { - delete issuerCert; - CSSM_DL_FreeUniqueRecord(dlDb, record); + if(issuerCert != NULL) { + /* either holding onto this cert, or done with it. */ + if(crtn != CSSM_CERT_STATUS_EXPIRED && + crtn != CSSM_CERT_STATUS_IS_ROOT) { + delete issuerCert; + CSSM_DL_FreeUniqueRecord(dlDb, record); + } + issuerCert = NULL; } - issuerCert = NULL; } /* searching subsequent records */ } /* switch verify */ @@ -271,6 +306,13 @@ TPCertInfo *tpDbFindIssuerCert( expiredIssuer->freeUniqueRecord(); delete expiredIssuer; } + /* Avoid deleting the non-root cert if same as expired cert */ + if(nonRootIssuer != NULL && nonRootIssuer != expiredIssuer) { + /* We found a replacement */ + tpDbDebug("tpDbFindIssuer: discarding non-root cert"); + nonRootIssuer->freeUniqueRecord(); + delete nonRootIssuer; + } return issuerCert; } } /* tpCertLookup, i.e., CSSM_DL_DataGetFirst, succeeded */ @@ -280,9 +322,20 @@ TPCertInfo *tpDbFindIssuerCert( } } /* main loop searching dbList */ + if(nonRootIssuer != NULL) { + /* didn't find root issuer, so use this one */ + tpDbDebug("tpDbFindIssuer: taking non-root issuer cert, record %p", + nonRootIssuer->uniqueRecord()); + if(expiredIssuer != NULL && expiredIssuer != nonRootIssuer) { + expiredIssuer->freeUniqueRecord(); + delete expiredIssuer; + } + return nonRootIssuer; + } + if(expiredIssuer != NULL) { /* OK, we'll take this one */ - tpDbDebug("tpDbFindIssuer: taking expired cert after all, record %p", + tpDbDebug("tpDbFindIssuer: taking expired cert after all, record %p", expiredIssuer->uniqueRecord()); return expiredIssuer; } @@ -291,8 +344,8 @@ TPCertInfo *tpDbFindIssuerCert( } /* - * Given a DL/DB, look up CRL by issuer name and validity time. - * Subsequent CRLs can be found using the returned result handle. + * Given a DL/DB, look up CRL by issuer name and validity time. + * Subsequent CRLs can be found using the returned result handle. */ #define SEARCH_BY_DATE 1 @@ -304,22 +357,22 @@ static CSSM_DB_UNIQUE_RECORD_PTR tpCrlLookup( CSSM_DATA_PTR crl) // RETURNED { CSSM_QUERY query; - CSSM_SELECTION_PREDICATE pred[3]; + CSSM_SELECTION_PREDICATE pred[3]; CSSM_DB_UNIQUE_RECORD_PTR record = NULL; char timeStr[CSSM_TIME_STRLEN + 1]; - + crl->Data = NULL; crl->Length = 0; - + /* Three predicates...first, the issuer name */ pred[0].DbOperator = CSSM_DB_EQUAL; - pred[0].Attribute.Info.AttributeNameFormat = + pred[0].Attribute.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; pred[0].Attribute.Info.Label.AttributeName = (char*) "Issuer"; pred[0].Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; pred[0].Attribute.Value = const_cast(issuerName); pred[0].Attribute.NumberOfValues = 1; - + /* now before/after. Cook up an appropriate time string. */ if(verifyTime != NULL) { /* Caller spec'd tolerate any format */ @@ -337,7 +390,7 @@ static CSSM_DB_UNIQUE_RECORD_PTR tpCrlLookup( CSSM_DATA timeData; timeData.Data = (uint8 *)timeStr; timeData.Length = CSSM_TIME_STRLEN; - + #if SEARCH_BY_DATE pred[1].DbOperator = CSSM_DB_LESS_THAN; pred[1].Attribute.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; @@ -345,7 +398,7 @@ static CSSM_DB_UNIQUE_RECORD_PTR tpCrlLookup( pred[1].Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; pred[1].Attribute.Value = &timeData; pred[1].Attribute.NumberOfValues = 1; - + pred[2].DbOperator = CSSM_DB_GREATER_THAN; pred[2].Attribute.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; pred[2].Attribute.Info.Label.AttributeName = (char*) "ThisUpdate"; @@ -353,7 +406,7 @@ static CSSM_DB_UNIQUE_RECORD_PTR tpCrlLookup( pred[2].Attribute.Value = &timeData; pred[2].Attribute.NumberOfValues = 1; #endif - + query.RecordType = CSSM_DL_DB_RECORD_X509_CRL; query.Conjunctive = CSSM_DB_AND; #if SEARCH_BY_DATE @@ -365,7 +418,7 @@ static CSSM_DB_UNIQUE_RECORD_PTR tpCrlLookup( query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? query.QueryFlags = 0; // FIXME - used? - + CSSM_DL_DataGetFirst(dlDb, &query, resultHand, @@ -376,8 +429,8 @@ static CSSM_DB_UNIQUE_RECORD_PTR tpCrlLookup( } /* - * Search a list of DBs for a CRL from the specified issuer and (optional) - * TPVerifyContext.verifyTime. + * Search a list of DBs for a CRL from the specified issuer and (optional) + * TPVerifyContext.verifyTime. * Just a boolean return - we found it, or not. If we did, we return a * TPCrlInfo which has been verified with the specified TPVerifyContext. */ @@ -390,13 +443,13 @@ TPCrlInfo *tpDbFindIssuerCrl( uint32 dbDex; CSSM_HANDLE resultHand; - CSSM_DATA crl; + CSSM_DATA crl; CSSM_DL_DB_HANDLE dlDb; CSSM_DB_UNIQUE_RECORD_PTR record; TPCrlInfo *issuerCrl = NULL; CSSM_DL_DB_LIST_PTR dbList = vfyCtx.dbList; CSSM_RETURN crtn; - + if(dbList == NULL) { return NULL; } @@ -409,47 +462,47 @@ TPCrlInfo *tpDbFindIssuerCrl( vfyCtx.verifyTime, &resultHand, &crl); - /* remember we have to: - * -- abort this query regardless, and - * -- free the CSSM_DATA crl regardless, and - * -- free the unique record if we don't use it + /* remember we have to: + * -- abort this query regardless, and + * -- free the CSSM_DATA crl regardless, and + * -- free the unique record if we don't use it * (by placing it in issuerCert)... */ if(record != NULL) { /* Found one */ assert(crl.Data != NULL); - issuerCrl = new TPCrlInfo(vfyCtx.clHand, + issuerCrl = new TPCrlInfo(vfyCtx.clHand, vfyCtx.cspHand, - &crl, - TIC_CopyData, + &crl, + TIC_CopyData, vfyCtx.verifyTime); /* we're done with raw CRL data */ - /* FIXME this assumes that vfyCtx.alloc is the same as the + /* FIXME this assumes that vfyCtx.alloc is the same as the * allocator associated with DlDB...OK? */ tpFreeCssmData(vfyCtx.alloc, &crl, CSSM_FALSE); crl.Data = NULL; crl.Length = 0; - + /* and we're done with the record */ CSSM_DL_FreeUniqueRecord(dlDb, record); - + /* Does it verify with specified context? */ crtn = issuerCrl->verifyWithContextNow(vfyCtx, &forCert); if(crtn) { - + delete issuerCrl; issuerCrl = NULL; - + /* - * Verify fail. Continue searching this DB. Break on - * finding the holy grail or no more records found. + * Verify fail. Continue searching this DB. Break on + * finding the holy grail or no more records found. */ for(;;) { crl.Data = NULL; crl.Length = 0; - crtn = CSSM_DL_DataGetNext(dlDb, + crtn = CSSM_DL_DataGetNext(dlDb, resultHand, - NULL, // no attrs + NULL, // no attrs &crl, &record); if(crtn) { @@ -458,15 +511,15 @@ TPCrlInfo *tpDbFindIssuerCrl( break; } assert(crl.Data != NULL); - + /* found one - is it any good? */ - issuerCrl = new TPCrlInfo(vfyCtx.clHand, + issuerCrl = new TPCrlInfo(vfyCtx.clHand, vfyCtx.cspHand, - &crl, - TIC_CopyData, + &crl, + TIC_CopyData, vfyCtx.verifyTime); /* we're done with raw CRL data */ - /* FIXME this assumes that vfyCtx.alloc is the same as the + /* FIXME this assumes that vfyCtx.alloc is the same as the * allocator associated with DlDB...OK? */ tpFreeCssmData(vfyCtx.alloc, &crl, CSSM_FALSE); crl.Data = NULL; @@ -497,7 +550,7 @@ TPCrlInfo *tpDbFindIssuerCrl( } /* in any case, abort the query for this db */ CSSM_DL_DataAbortQuery(dlDb, resultHand); - + } /* main loop searching dbList */ /* issuer not found */ diff --git a/libsecurity_apple_x509_tp/lib/TPDatabase.h b/Security/libsecurity_apple_x509_tp/lib/TPDatabase.h similarity index 95% rename from libsecurity_apple_x509_tp/lib/TPDatabase.h rename to Security/libsecurity_apple_x509_tp/lib/TPDatabase.h index a7ad4369..6e618a41 100644 --- a/libsecurity_apple_x509_tp/lib/TPDatabase.h +++ b/Security/libsecurity_apple_x509_tp/lib/TPDatabase.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * TPDatabase.h - TP's DL/DB access functions. * - * Created 10/9/2002 by Doug Mitchell. */ #ifndef _TP_DATABASE_H_ diff --git a/libsecurity_apple_x509_tp/lib/TPNetwork.cpp b/Security/libsecurity_apple_x509_tp/lib/TPNetwork.cpp similarity index 99% rename from libsecurity_apple_x509_tp/lib/TPNetwork.cpp rename to Security/libsecurity_apple_x509_tp/lib/TPNetwork.cpp index e6895229..bc9cf3fe 100644 --- a/libsecurity_apple_x509_tp/lib/TPNetwork.cpp +++ b/Security/libsecurity_apple_x509_tp/lib/TPNetwork.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2012 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_tp/lib/TPNetwork.h b/Security/libsecurity_apple_x509_tp/lib/TPNetwork.h similarity index 95% rename from libsecurity_apple_x509_tp/lib/TPNetwork.h rename to Security/libsecurity_apple_x509_tp/lib/TPNetwork.h index 6bc97a2d..57a37bde 100644 --- a/libsecurity_apple_x509_tp/lib/TPNetwork.h +++ b/Security/libsecurity_apple_x509_tp/lib/TPNetwork.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * TPNetwork.h - LDAP (and eventually) other network tools * - * Written 10/3/2002 by Doug Mitchell. */ #ifndef _TP_NETWORK_H_ diff --git a/libsecurity_apple_x509_tp/lib/certGroupUtils.cpp b/Security/libsecurity_apple_x509_tp/lib/certGroupUtils.cpp similarity index 87% rename from libsecurity_apple_x509_tp/lib/certGroupUtils.cpp rename to Security/libsecurity_apple_x509_tp/lib/certGroupUtils.cpp index a86c310f..8686e5fd 100644 --- a/libsecurity_apple_x509_tp/lib/certGroupUtils.cpp +++ b/Security/libsecurity_apple_x509_tp/lib/certGroupUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -18,8 +18,6 @@ /* certGroupUtils.cpp - - Created 10/9/2000 by Doug Mitchell. */ #include @@ -559,6 +557,81 @@ CSSM_BOOL tpCompareEmailAddr( } } +/* + * Check whether the provided hostName has a domainName suffix. + * This function does not process wildcards, and allows hostName to match + * any subdomain level of the provided domainName. + * + * To match, the last domainNameLen chars of hostName must equal domainName, + * and the character immediately preceding domainName in hostName (if any) + * must be a dot. This means that domainName 'bar.com' will match hostName + * values 'host.bar.com' or 'host.sub.bar.com', but not 'host.foobar.com'. + * + * The incoming hostname is assumed to have been processed by tpToLower(); + * we'll perform that processing on domainName here. + * + * Trailing '.' characters in both host names will be ignored per Radar 3996792. + * + * Returns CSSM_TRUE on match, else CSSM_FALSE. + */ +CSSM_BOOL tpCompareDomainSuffix( + const char *hostName, // spec'd by app, tpToLower'd + uint32 hostNameLen, + char *domainName, // we tpToLower + uint32 domainNameLen) +{ + tpToLower(domainName, domainNameLen); + + /* tolerate optional NULL terminators for both */ + if(hostNameLen && (hostName[hostNameLen - 1] == '\0')) { + hostNameLen--; + } + if(domainNameLen && (domainName[domainNameLen - 1] == '\0')) { + domainNameLen--; + } + + if((hostNameLen == 0) || (domainNameLen == 0)) { + /* trivial case with at least one empty name */ + if(hostNameLen == domainNameLen) { + return CSSM_TRUE; + } + else { + return CSSM_FALSE; + } + } + + /* trim off trailing dots */ + if(hostName[hostNameLen - 1] == '.') { + hostNameLen--; + } + if(domainName[domainNameLen - 1] == '.') { + domainNameLen--; + } + + /* trim off leading dot in suffix, if present */ + if((domainNameLen > 0) && (domainName[0] == '.')) { + domainName++; + domainNameLen--; + } + + if(hostNameLen < domainNameLen) { + return CSSM_FALSE; + } + + if(memcmp(hostName+(hostNameLen-domainNameLen),domainName,domainNameLen)) { + return CSSM_FALSE; + } + + /* require a dot prior to domain suffix, unless host == domain */ + if(hostNameLen > domainNameLen) { + if(hostName[hostNameLen-(domainNameLen+1)] != '.') { + return CSSM_FALSE; + } + } + + return CSSM_TRUE; +} + /* * Following a CSSMOID_ECDSA_WithSpecified algorithm is an encoded * ECDSA_SigAlgParams containing the digest agorithm OID. Decode and return diff --git a/libsecurity_apple_x509_tp/lib/certGroupUtils.h b/Security/libsecurity_apple_x509_tp/lib/certGroupUtils.h similarity index 89% rename from libsecurity_apple_x509_tp/lib/certGroupUtils.h rename to Security/libsecurity_apple_x509_tp/lib/certGroupUtils.h index a1719524..7417ef7b 100644 --- a/libsecurity_apple_x509_tp/lib/certGroupUtils.h +++ b/Security/libsecurity_apple_x509_tp/lib/certGroupUtils.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. - * + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. + * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). * You may not use this file except in compliance with the License. Please obtain * a copy of the License at http://www.apple.com/publicsource and read it before * using this file. - * + * * This 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 @@ -18,8 +18,6 @@ /* certGroupUtils.h - - Created 10/9/2000 by Doug Mitchell. */ #ifndef _CERT_GROUP_UTILS_H @@ -52,7 +50,7 @@ void tpFreeCssmData( CSSM_BOOL tpCompareCssmData( const CSSM_DATA *data1, const CSSM_DATA *data2); - + /* * This should break if/when CSSM_OID is not the same as * CSSM_DATA, which is exactly what we want. @@ -63,14 +61,14 @@ void tpFreePluginMemory( CSSM_HANDLE hand, void *p); -CSSM_DATA_PTR tp_CertGetPublicKey( +CSSM_DATA_PTR tp_CertGetPublicKey( TPCertInfo *cert, CSSM_DATA_PTR *valueToFree); // used in tp_CertFreePublicKey void tp_CertFreePublicKey( CSSM_CL_HANDLE clHand, CSSM_DATA_PTR value); -CSSM_X509_ALGORITHM_IDENTIFIER_PTR tp_CertGetAlgId( +CSSM_X509_ALGORITHM_IDENTIFIER_PTR tp_CertGetAlgId( TPCertInfo *cert, CSSM_DATA_PTR *valueToFree); // used in tp_CertFreeAlgId void tp_CertFreeAlgId( @@ -103,6 +101,12 @@ CSSM_BOOL tpCompareEmailAddr( uint32 certEmailLen, bool normalizeAll); // true : lower-case all certEmail characters +CSSM_BOOL tpCompareDomainSuffix( + const char *hostName, // spec'd by app, tpToLower'd + uint32 hostNameLen, + char *domainName, // we tpToLower + uint32 domainNameLen); + int decodeECDSA_SigAlgParams( const CSSM_DATA *params, CSSM_ALGORITHMS *cssmAlg); /* RETURNED */ diff --git a/Security/libsecurity_apple_x509_tp/lib/cuEnc64.c b/Security/libsecurity_apple_x509_tp/lib/cuEnc64.c new file mode 100644 index 00000000..879001cd --- /dev/null +++ b/Security/libsecurity_apple_x509_tp/lib/cuEnc64.c @@ -0,0 +1,587 @@ +/* + * Copyright (c) 1998-2003,2010-2012 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please + * obtain a copy of the License at http://www.apple.com/publicsource and + * read it before using this file. + * + * This 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. + * + * cuEnc64.c - encode/decode in 64-char IA5 format, per RFC 1421 + */ + +#include "cuEnc64.h" +#include +#include +#include + +#ifndef NULL +#define NULL ((void *)0) +#endif /* NULL */ + +/* + * map a 6-bit binary value to a printable character. + */ +static const +unsigned char bintoasc[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* + * Map an 7-bit printable character to its corresponding binary value. + * Any illegal characters return high bit set. + */ +static const +unsigned char asctobin[] = +{ + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x3e, 0x80, 0x80, 0x80, 0x3f, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80 +}; + +/* + * map 6 bits to a printing char + */ +#define ENC(c) (bintoasc[((c) & 0x3f)]) + +#define PAD '=' + +/* + * map one group of up to 3 bytes at inp to 4 bytes at outp. + * Count is number of valid bytes in *inp; if less than 3, the + * 1 or two extras must be zeros. + */ +static void encChunk(const unsigned char *inp, + unsigned char *outp, + int count) +{ + unsigned char c1, c2, c3, c4; + + c1 = *inp >> 2; + c2 = ((inp[0] << 4) & 0x30) | ((inp[1] >> 4) & 0xf); + c3 = ((inp[1] << 2) & 0x3c) | ((inp[2] >> 6) & 0x3); + c4 = inp[2] & 0x3f; + *outp++ = ENC(c1); + *outp++ = ENC(c2); + if (count == 1) { + *outp++ = PAD; + *outp = PAD; + } else { + *outp++ = ENC(c3); + if (count == 2) { + *outp = PAD; + } + else { + *outp = ENC(c4); + } + } +} + +/* + * Given input buffer inbuf, length inlen, encode to 64-char IA5 format. + * Result is fmalloc'd and returned; it is terminated by Microsoft-style + * newline and NULL. Its length (including the trailing newline and NULL) + * is returned in *outlen. + */ + +unsigned char *cuEnc64(const unsigned char *inbuf, + unsigned inlen, + unsigned *outlen) // RETURNED +{ + return cuEnc64WithLines(inbuf, inlen, 0, outlen); +} + +unsigned char *cuEnc64WithLines(const unsigned char *inbuf, + unsigned inlen, + unsigned linelen, + unsigned *outlen) +{ + unsigned outTextLen; + unsigned len; // to malloc, liberal + unsigned olen = 0; // actual output size + unsigned char *outbuf; + unsigned char endbuf[3]; + unsigned i; + unsigned char *outp; + unsigned numLines; + unsigned thisLine; + + outTextLen = ((inlen + 2) / 3) * 4; + if(linelen) { + /* + * linelen must be 0 mod 4 for this to work; round up... + */ + if((linelen & 0x03) != 0) { + linelen = (linelen + 3) & 0xfffffffc; + } + numLines = (outTextLen + linelen - 1)/ linelen; + } + else { + numLines = 1; + } + + /* + * Total output size = encoded text size plus one newline per + * line of output, plus trailing NULL. We always generate newlines + * as \n; when decoding, we tolerate \r\n (Microsoft) or \n. + */ + len = outTextLen + (2 * numLines) + 1; + outbuf = (unsigned char*)malloc(len); + outp = outbuf; + thisLine = 0; + + while(inlen) { + if(inlen < 3) { + for(i=0; i<3; i++) { + if(i < inlen) { + endbuf[i] = inbuf[i]; + } + else { + endbuf[i] = 0; + } + } + encChunk(endbuf, outp, inlen); + inlen = 0; + } + else { + encChunk(inbuf, outp, 3); + inlen -= 3; + inbuf += 3; + } + outp += 4; + thisLine += 4; + olen += 4; + if((linelen != 0) && (thisLine >= linelen) && inlen) { + /* + * last trailing newline added below + * Note we don't split 4-byte output chunks over newlines + */ + *outp++ = '\n'; + olen++; + thisLine = 0; + } + } + *outp++ = '\n'; + *outp = '\0'; + olen += 2; + *outlen = olen; + return outbuf; +} + +static inline int isWhite(unsigned char c) +{ + switch(c) { + case '\n': + case '\r': + case ' ': + case '\t': + case '\0': + return 1; + default: + return 0; + } +} + +/* + * Strip off all whitespace from a (supposedly) enc64-format string. + * Returns a malloc'd string. + */ +static unsigned char *stringCleanse(const unsigned char *inbuf, + unsigned inlen, + unsigned *outlen) +{ + unsigned char *news; // cleansed inbuf + unsigned newsDex; // index into news + unsigned i; + + news = (unsigned char*)malloc(inlen); + newsDex = 0; + for(i=0; i 0) { + goto errorOut; + } + } + else { + goto errorOut; + } + } else if (*bp & 0x80 || (c3 = asctobin[*bp]) & 0x80) { + goto errorOut; + } else { + bp++; + inlen--; + if (*bp == PAD) { + /* + * Three input bytes, two output + */ + c4 = 0; + thisOlen = 2; + if (c3 & 3) { + goto errorOut; + } + } else if (*bp & 0x80 || (c4 = asctobin[*bp]) & 0x80) { + goto errorOut; + } else { + /* + * Normal non-pad case + */ + thisOlen = 3; + } + bp++; + inlen--; + } + j = (c1 << 2) | (c2 >> 4); + *outp++ = j; + if(thisOlen > 1) { + j = (c2 << 4) | (c3 >> 2); + *outp++ = j; + if(thisOlen == 3) { + j = (c3 << 6) | c4; + *outp++ = j; + } + } + olen += thisOlen; + } + free(news); + *outlen = olen; + return outbuf; /* normal return */ + +errorOut: + free(news); + free(outbuf); + return (unsigned char*) NULL; +} + +/* + * Determine if specified input data is valid enc64 format. Returns 1 + * if valid, 0 if not. + * This doesn't do a full enc64 parse job; it scans for legal characters + * and proper sync when a possible pad is found. + */ +int cuIsValidEnc64(const unsigned char *inbuf, + unsigned inlen) +{ + int padChars = 0; // running count of PAD chars + int validEncChars = 0; + unsigned char c; + + /* + * -- scan inbuf + * -- skip whitespace + * -- count valid chars + * -- ensure not more than 2 PAD chars, only at end + * -- ensure valid chars mod 4 == 0 + */ + + while(inlen) { + c = *inbuf++; + inlen--; + if(isWhite(c)) { + continue; + } + if(c == PAD) { + if(++padChars > 2) { + return 0; // max of 2 PAD chars at end + } + } + else if(padChars > 0) { + return 0; // no normal chars after seeing PAD + } + else if((c & 0x80) || ((asctobin[c]) & 0x80)) { + return 0; // invalid encoded char + } + validEncChars++; + } + if((validEncChars & 0x03) != 0) { + return 0; + } + else { + return 1; + } +} + +/* + * Text parsing routines. + * + * Search incoming text for specified string. Does not assume inText is + * NULL terminated. Returns pointer to start of found string in inText. + */ +static const char *findStr( + const char *inText, + unsigned inTextLen, + const char *str) // NULL terminated - search for this +{ + /* probably not the hottest string search algorithm... */ + const char *cp; + size_t srchStrLen = strlen(str); + char c = str[0]; + + /* last char * we can search in inText for start of str */ + const char *endCp = inText + inTextLen - srchStrLen; + + for(cp=inText; cp<=endCp; cp++) { + if(*cp == c) { + if(!memcmp(cp, str, srchStrLen)) { + return cp; + } + } + } + return NULL; +} + +/* + * Obtain one line from current text. Returns a mallocd, NULL-terminated string + * which caller must free(). Also returns the number of chars consumed including + * the returned chars PLUS EOL terminators (\n and/or \r). + * + * ALWAYS returns a mallocd string if there is ANY data remaining per the + * incoming inTextLen. Returns NULL if inTextLen is zero. + */ +static const char *getLine( + const char *inText, + unsigned inTextLen, // RETURNED + unsigned *consumed) // RETURNED + +{ + *consumed = 0; + const char *cp = inText; + const char *newline = NULL; // if we found a newline, this points to the first one + + while(inTextLen) { + char c = *cp; + if((c == '\r') || (c == '\n')) { + if(newline == NULL) { + /* first newline */ + newline = cp; + } + } + else if(newline != NULL) { + /* non newline after newline, done */ + break; + } + (*consumed)++; + inTextLen--; + cp++; + } + ptrdiff_t linelen; + if(newline) { + linelen = newline - inText; + } + else { + linelen = *consumed; + } + char *rtn = (char *)malloc(linelen + 1); + memmove(rtn, inText, linelen); + rtn[linelen] = 0; + return rtn; +} + +#define UNSUPPORTED_FORMAT_ERR -25256 + +/* + * Given input buffer containing a PEM-encoded certificate, convert to DER + * and return in outbuf. Result is malloced and must be freed by caller; + * its length is returned in *outlen. Returns 0 on success. + */ +int cuConvertPem( + const unsigned char *inbuf, + unsigned inlen, + unsigned char **outbuf, // RETURNED (caller must free) + unsigned *outlen) // RETURNED +{ + unsigned lenToGo = (inlen) ? inlen : 0; + const char *currCp = (inbuf) ? (const char *)inbuf : NULL; + const char *currLine = NULL; // mallocd by getLine() + unsigned consumed; + int ortn = 0; + const char *start64; + unsigned base64Len; + const char *end64; + unsigned char *decData; + unsigned decDataLen; + + /* search to START line, parse it to get type/format/alg */ + const char *startLine = findStr(currCp, lenToGo, "-----BEGIN"); + if(startLine != NULL) { + /* possibly skip over leading garbage */ + consumed = (unsigned)(startLine - currCp); + lenToGo -= consumed; + currCp = startLine; + + /* get C string of START line */ + currLine = getLine(startLine, lenToGo, &consumed); + if(currLine == NULL) { + /* somehow got here with no data */ + // assert(lenToGo == 0); + ortn = UNSUPPORTED_FORMAT_ERR; + goto errOut; + } + // assert(consumed <= lenToGo); + currCp += consumed; + lenToGo -= consumed; + + free((void *)currLine); + } + + /* Skip empty lines. */ + for( ; ; ) { + currLine = getLine(currCp, lenToGo, &consumed); + if(currLine == NULL) { + /* out of data */ + ortn = UNSUPPORTED_FORMAT_ERR; + goto errOut; + } + int skipThis = 0; + size_t lineLen = strlen(currLine); + if(lineLen == 0) { + /* empty line */ + skipThis = 1; + } + free((void *)currLine); + + if(!skipThis) { + /* looks like good stuff; process */ + break; + } + /* skip this line */ + // assert(consumed <= lenToGo); + currCp += consumed; + lenToGo -= consumed; + } + if(lenToGo == 0) { + /* no valid base64 data */ + ortn = UNSUPPORTED_FORMAT_ERR; + goto errOut; + } + + /* + * currCP points to start of base64 data - mark it and search for end line. + * We skip everything after the end line. + */ + start64 = currCp; + base64Len = lenToGo; // if no END + end64 = findStr(currCp, lenToGo, "-----END"); + if(end64 != NULL) { + if(end64 == start64) { + /* Empty, nothing between START and END */ + ortn = UNSUPPORTED_FORMAT_ERR; + goto errOut; + } + base64Len = (unsigned)(end64 - start64); + } + /* else no END, no reason to complain about that as long as base64 decode works OK */ + + /* Base 64 decode */ + decData = cuDec64((const unsigned char *)start64, base64Len, &decDataLen); + if(decData == NULL) { + /* bad base64 data */ + ortn = UNSUPPORTED_FORMAT_ERR; + goto errOut; + } + + if(outlen) { + *outlen = decDataLen; + } + if(outbuf) { + *outbuf = decData; + } + else { + free((void *)decData); + } + +errOut: + return ortn; +} diff --git a/Security/libsecurity_apple_x509_tp/lib/cuEnc64.h b/Security/libsecurity_apple_x509_tp/lib/cuEnc64.h new file mode 100644 index 00000000..7644ed7a --- /dev/null +++ b/Security/libsecurity_apple_x509_tp/lib/cuEnc64.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1998-2003,2010-2011 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please + * obtain a copy of the License at http://www.apple.com/publicsource and + * read it before using this file. + * + * This 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. + * + * cuEnc64.h - encode/decode in 64-char IA5 format, per RFC 1421 + */ + +#ifndef _CU_ENC64_H_ +#define _CU_ENC64_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Given input buffer inbuf, length inlen, decode from 64-char IA5 format to + * binary. Result is malloced and returned; its length is returned in *outlen. + * NULL return indicates corrupted input. + */ +unsigned char *cuEnc64(const unsigned char *inbuf, + unsigned inlen, + unsigned *outlen); // RETURNED + +/* + * Enc64, with embedded newlines every lineLen in result. A newline is + * the UNIX \n. Result is mallocd. + */ +unsigned char *cuEnc64WithLines(const unsigned char *inbuf, + unsigned inlen, + unsigned linelen, + unsigned *outlen); // RETURNED + +/* + * Given input buffer inbuf, length inlen, decode from 64-char IA5 format to + * binary. Result is malloced and returned; its length is returned in *outlen. + * NULL return indicates corrupted input. All whitespace in inbuf is + * ignored. + */ +unsigned char *cuDec64(const unsigned char *inbuf, + unsigned inlen, + unsigned *outlen); + +/* + * Determine if specified input data is valid enc64 format. Returns 1 + * if valid, 0 if not. + */ +int cuIsValidEnc64(const unsigned char *inbuf, + unsigned inbufLen); + +/* + * Given input buffer containing a PEM-encoded certificate, convert to DER + * and return in outbuf. Result is malloced and must be freed by caller; + * its length is returned in *outlen. Returns 0 on success. + */ +int cuConvertPem(const unsigned char *inbuf, + unsigned inlen, + unsigned char **outbuf, // RETURNED (caller must free) + unsigned *outlen); // RETURNED + +#ifdef __cplusplus +} +#endif + +#endif /*_CU_ENC64_H_*/ diff --git a/Security/libsecurity_apple_x509_tp/lib/ocspRequest.cpp b/Security/libsecurity_apple_x509_tp/lib/ocspRequest.cpp new file mode 100644 index 00000000..6add077c --- /dev/null +++ b/Security/libsecurity_apple_x509_tp/lib/ocspRequest.cpp @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * ocspRequest.cpp - OCSP Request class + */ + +#include "ocspRequest.h" +#include "certGroupUtils.h" +#include "tpdebugging.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* preencoded DER NULL */ +static uint8 nullParam[2] = {5, 0}; + +/* size of nonce we generate, in bytes */ +#define OCSP_NONCE_SIZE 8 + +/* + * The only constructor. Subject and issuer must remain valid for the + * lifetime of this object (they are not refcounted). + */ +OCSPRequest::OCSPRequest( + TPCertInfo &subject, + TPCertInfo &issuer, + bool genNonce) + : mCoder(NULL), + mSubject(subject), + mIssuer(issuer), + mGenNonce(genNonce), + mCertID(NULL) +{ + SecAsn1CoderCreate(&mCoder); + mNonce.Data = NULL; + mNonce.Length = 0; + mEncoded.Data = NULL; + mEncoded.Length = 0; +} + +OCSPRequest::~OCSPRequest() +{ + delete mCertID; + if(mCoder) { + SecAsn1CoderRelease(mCoder); + } +} + +const CSSM_DATA *OCSPRequest::encode() +{ + /* fields obtained from issuer */ + CSSM_DATA_PTR issuerName; + CSSM_DATA_PTR issuerKey; + CSSM_KEY_PTR issuerPubKey; + /* from subject */ + CSSM_DATA_PTR subjectSerial=NULL; + + CSSM_RETURN crtn; + uint8 issuerNameHash[CC_SHA1_DIGEST_LENGTH]; + uint8 pubKeyHash[CC_SHA1_DIGEST_LENGTH]; + SecAsn1OCSPRequest singleReq; + SecAsn1OCSPCertID &certId = singleReq.reqCert; + SecAsn1OCSPSignedRequest signedReq; + SecAsn1OCSPRequest *reqArray[2] = { &singleReq, NULL }; + SecAsn1OCSPTbsRequest &tbs = signedReq.tbsRequest; + uint8 version = 0; + CSSM_DATA vers = {1, &version}; + uint8 nonceBytes[OCSP_NONCE_SIZE]; + CSSM_DATA nonceData = {OCSP_NONCE_SIZE, nonceBytes}; + OCSPNonce *nonce = NULL; + NSS_CertExtension *extenArray[2] = {NULL, NULL}; + + if(mEncoded.Data) { + /* already done */ + return &mEncoded; + } + + /* + * One single request, no extensions + */ + memset(&singleReq, 0, sizeof(singleReq)); + + /* algId refers to the hash we'll perform in issuer name and key */ + certId.algId.algorithm = CSSMOID_SHA1; + certId.algId.parameters.Data = nullParam; + certId.algId.parameters.Length = sizeof(nullParam); + + /* gather fields from two certs */ + crtn = mSubject.fetchField(&CSSMOID_X509V1IssuerNameStd, &issuerName); + if(crtn) { + CssmError::throwMe(crtn); + } + crtn = mIssuer.fetchField(&CSSMOID_CSSMKeyStruct, &issuerKey); + if(crtn) { + goto errOut; + } + crtn = mSubject.fetchField(&CSSMOID_X509V1SerialNumber, &subjectSerial); + if(crtn) { + goto errOut; + } + + /* SHA1(issuerName) */ + ocspdSha1(issuerName->Data, (CC_LONG)issuerName->Length, issuerNameHash); + + /* SHA1(issuer public key) */ + if(issuerKey->Length != sizeof(CSSM_KEY)) { + tpErrorLog("OCSPRequest::encode: malformed issuer key\n"); + crtn = CSSMERR_TP_INTERNAL_ERROR; + goto errOut; + } + issuerPubKey = (CSSM_KEY_PTR)issuerKey->Data; + ocspdSha1(issuerPubKey->KeyData.Data, (CC_LONG)issuerPubKey->KeyData.Length, pubKeyHash); + + /* build the CertID from those components */ + certId.issuerNameHash.Data = issuerNameHash; + certId.issuerNameHash.Length = CC_SHA1_DIGEST_LENGTH; + certId.issuerPubKeyHash.Data = pubKeyHash; + certId.issuerPubKeyHash.Length = CC_SHA1_DIGEST_LENGTH; + certId.serialNumber = *subjectSerial; + + /* + * Build top level request with one entry in requestList, no signature, + * one optional extension (a nonce) + */ + memset(&signedReq, 0, sizeof(signedReq)); + tbs.version = &vers; + tbs.requestList = reqArray; + + /* one extension - the nonce */ + if(mGenNonce) { + DevRandomGenerator drg; + drg.random(nonceBytes, OCSP_NONCE_SIZE); + nonce = new OCSPNonce(mCoder, false, nonceData); + extenArray[0] = nonce->nssExt(); + tbs.requestExtensions = extenArray; + SecAsn1AllocCopyItem(mCoder, &nonceData, &mNonce); + } + + /* Encode */ + if(SecAsn1EncodeItem(mCoder, &signedReq, kSecAsn1OCSPSignedRequestTemplate, + &mEncoded)) { + tpErrorLog("OCSPRequest::encode: error encoding OCSP req\n"); + crtn = CSSMERR_TP_INTERNAL_ERROR; + goto errOut; + } + /* save a copy of the CertID */ + mCertID = new OCSPClientCertID(*issuerName, issuerPubKey->KeyData, *subjectSerial); + +errOut: + if(issuerName) { + mIssuer.freeField(&CSSMOID_X509V1IssuerNameStd, issuerName); + } + if(issuerKey) { + mIssuer.freeField(&CSSMOID_CSSMKeyStruct, issuerKey); + } + if(subjectSerial) { + mSubject.freeField(&CSSMOID_X509V1SerialNumber, subjectSerial); + } + if(nonce) { + delete nonce; + } + if(crtn) { + CssmError::throwMe(crtn); + } + return &mEncoded; +} + +const CSSM_DATA *OCSPRequest::nonce() +{ + /* not legal before encode() called */ + assert(mEncoded.Data != NULL); + if(mNonce.Data) { + return &mNonce; + } + else { + return NULL; + } +} + +OCSPClientCertID *OCSPRequest::certID() +{ + encode(); + return mCertID; +} + diff --git a/Security/libsecurity_apple_x509_tp/lib/ocspRequest.h b/Security/libsecurity_apple_x509_tp/lib/ocspRequest.h new file mode 100644 index 00000000..7d68fd0d --- /dev/null +++ b/Security/libsecurity_apple_x509_tp/lib/ocspRequest.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * ocspRequest.h - OCSP Request class + */ + +#ifndef _OCSP_REQUEST_H_ +#define _OCSP_REQUEST_H_ + +#include "TPCertInfo.h" +#include +#include + +class OCSPClientCertID; + +class OCSPRequest +{ + NOCOPY(OCSPRequest) +public: + /* + * The only constructor. Subject and issuer must remain valid for the + * lifetime of this object (they are not refcounted). + */ + OCSPRequest( + TPCertInfo &subject, + TPCertInfo &issuer, + bool genNonce); + + ~OCSPRequest(); + + /* + * Obtain encoded OCSP request suitable for posting to responder. + * This object owns and maintains the memory. + */ + const CSSM_DATA *encode(); + + /* + * Obtain this request's nonce (which we randomly generate at encode() time), + * This object owns and maintains the memory. Result is NULL} if we + * didn't generate a nonce. + */ + const CSSM_DATA *nonce(); + + /* + * Obtain this request's CertID. Used to look up matching SingleResponse + * in the OCSPResponse. + */ + OCSPClientCertID *certID(); + +private: + SecAsn1CoderRef mCoder; + TPCertInfo &mSubject; + TPCertInfo &mIssuer; + bool mGenNonce; + CSSM_DATA mNonce; + CSSM_DATA mEncoded; /* lazily evaluated */ + OCSPClientCertID *mCertID; /* calculated during encode() */ + +}; + +#endif /* _OCSP_REQUEST_H_ */ + diff --git a/libsecurity_apple_x509_tp/lib/tpCertGroup.cpp b/Security/libsecurity_apple_x509_tp/lib/tpCertGroup.cpp similarity index 99% rename from libsecurity_apple_x509_tp/lib/tpCertGroup.cpp rename to Security/libsecurity_apple_x509_tp/lib/tpCertGroup.cpp index 80e40b7d..bf50c70a 100644 --- a/libsecurity_apple_x509_tp/lib/tpCertGroup.cpp +++ b/Security/libsecurity_apple_x509_tp/lib/tpCertGroup.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001, 2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -469,6 +469,10 @@ static bool checkPolicyOid( tpPolicy = kTP_QAProfileSigning; return true; } + else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_PCS_ESCROW_SERVICE)) { + tpPolicy = kTP_PCSEscrowService; + return true; + } return false; } diff --git a/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp b/Security/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp similarity index 99% rename from libsecurity_apple_x509_tp/lib/tpCredRequest.cpp rename to Security/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp index 038f328f..efd88960 100644 --- a/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp +++ b/Security/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -20,7 +20,6 @@ * tpCredRequest.cpp - credential request functions SubmitCredRequest, * RetrieveCredResult * - * Created 1/24/2002 by Doug Mitchell. */ #include "AppleTPSession.h" diff --git a/libsecurity_apple_x509_tp/lib/tpCrlVerify.cpp b/Security/libsecurity_apple_x509_tp/lib/tpCrlVerify.cpp similarity index 99% rename from libsecurity_apple_x509_tp/lib/tpCrlVerify.cpp rename to Security/libsecurity_apple_x509_tp/lib/tpCrlVerify.cpp index 483ad49b..346b97c7 100644 --- a/libsecurity_apple_x509_tp/lib/tpCrlVerify.cpp +++ b/Security/libsecurity_apple_x509_tp/lib/tpCrlVerify.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2012 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_apple_x509_tp/lib/tpCrlVerify.h b/Security/libsecurity_apple_x509_tp/lib/tpCrlVerify.h similarity index 97% rename from libsecurity_apple_x509_tp/lib/tpCrlVerify.h rename to Security/libsecurity_apple_x509_tp/lib/tpCrlVerify.h index e05e19fd..4fd11570 100644 --- a/libsecurity_apple_x509_tp/lib/tpCrlVerify.h +++ b/Security/libsecurity_apple_x509_tp/lib/tpCrlVerify.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * tpCrlVerify.h - routines to verify CRLs and to verify certs against CRLs. * - * Written 9/26/02 by Doug Mitchell. */ #ifndef _TP_CRL_VERIFY_H_ diff --git a/libsecurity_apple_x509_tp/lib/tpOcspCache.cpp b/Security/libsecurity_apple_x509_tp/lib/tpOcspCache.cpp similarity index 99% rename from libsecurity_apple_x509_tp/lib/tpOcspCache.cpp rename to Security/libsecurity_apple_x509_tp/lib/tpOcspCache.cpp index cbb24ef5..5ac0ef4f 100644 --- a/libsecurity_apple_x509_tp/lib/tpOcspCache.cpp +++ b/Security/libsecurity_apple_x509_tp/lib/tpOcspCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_apple_x509_tp/lib/tpOcspCache.h b/Security/libsecurity_apple_x509_tp/lib/tpOcspCache.h similarity index 96% rename from libsecurity_apple_x509_tp/lib/tpOcspCache.h rename to Security/libsecurity_apple_x509_tp/lib/tpOcspCache.h index 09412e4e..980e1984 100644 --- a/libsecurity_apple_x509_tp/lib/tpOcspCache.h +++ b/Security/libsecurity_apple_x509_tp/lib/tpOcspCache.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_apple_x509_tp/lib/tpOcspCertVfy.cpp b/Security/libsecurity_apple_x509_tp/lib/tpOcspCertVfy.cpp similarity index 99% rename from libsecurity_apple_x509_tp/lib/tpOcspCertVfy.cpp rename to Security/libsecurity_apple_x509_tp/lib/tpOcspCertVfy.cpp index f0a7815a..6fdb9e69 100644 --- a/libsecurity_apple_x509_tp/lib/tpOcspCertVfy.cpp +++ b/Security/libsecurity_apple_x509_tp/lib/tpOcspCertVfy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_apple_x509_tp/lib/tpOcspCertVfy.h b/Security/libsecurity_apple_x509_tp/lib/tpOcspCertVfy.h similarity index 96% rename from libsecurity_apple_x509_tp/lib/tpOcspCertVfy.h rename to Security/libsecurity_apple_x509_tp/lib/tpOcspCertVfy.h index 395b29af..def53690 100644 --- a/libsecurity_apple_x509_tp/lib/tpOcspCertVfy.h +++ b/Security/libsecurity_apple_x509_tp/lib/tpOcspCertVfy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_apple_x509_tp/lib/tpOcspVerify.cpp b/Security/libsecurity_apple_x509_tp/lib/tpOcspVerify.cpp similarity index 99% rename from libsecurity_apple_x509_tp/lib/tpOcspVerify.cpp rename to Security/libsecurity_apple_x509_tp/lib/tpOcspVerify.cpp index d85a0434..e17e7cf0 100644 --- a/libsecurity_apple_x509_tp/lib/tpOcspVerify.cpp +++ b/Security/libsecurity_apple_x509_tp/lib/tpOcspVerify.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_apple_x509_tp/lib/tpOcspVerify.h b/Security/libsecurity_apple_x509_tp/lib/tpOcspVerify.h similarity index 95% rename from libsecurity_apple_x509_tp/lib/tpOcspVerify.h rename to Security/libsecurity_apple_x509_tp/lib/tpOcspVerify.h index 2b0caf5f..2bccca4a 100644 --- a/libsecurity_apple_x509_tp/lib/tpOcspVerify.h +++ b/Security/libsecurity_apple_x509_tp/lib/tpOcspVerify.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_apple_x509_tp/lib/tpPolicies.cpp b/Security/libsecurity_apple_x509_tp/lib/tpPolicies.cpp similarity index 95% rename from libsecurity_apple_x509_tp/lib/tpPolicies.cpp rename to Security/libsecurity_apple_x509_tp/lib/tpPolicies.cpp index 4dcb08b6..761dc806 100644 --- a/libsecurity_apple_x509_tp/lib/tpPolicies.cpp +++ b/Security/libsecurity_apple_x509_tp/lib/tpPolicies.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2013 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -40,6 +40,9 @@ #include #include +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-const-variable" + /* * Our private per-extension info. One of these per (understood) extension per * cert. @@ -47,7 +50,7 @@ typedef struct { CSSM_BOOL present; CSSM_BOOL critical; - CE_Data *extnData; // mallocd by CL + CE_Data *extnData; // mallocd by CL CSSM_DATA *valToFree; // the data we pass to freeField() } iSignExtenInfo; @@ -76,6 +79,8 @@ typedef struct { CSSM_BOOL foundPassbookSigning; /* flag indicating presence of CSSMOID_APPLE_EXTENSION_SYSINT2_INTERMEDIATE */ CSSM_BOOL foundAppleSysInt2Marker; + /* flag indicating presence of CSSMOID_APPLE_EXTENSION_SERVER_AUTHENTICATION */ + CSSM_BOOL foundAppleServerAuthMarker; /* flag indicating presence of CSSMOID_APPLE_EXTENSION_ESCROW_SERVICE */ CSSM_BOOL foundEscrowServiceMarker; /* flag indicating presence of a critical extension we don't understand */ @@ -120,6 +125,11 @@ static const UInt8 kMobileRootSHA1[kSecPolicySHA1Size] = { 0xCD, 0x32, 0xCB, 0xF4, 0x54, 0x69, 0xA1, 0xF1, 0x6B, 0x09 }; +static const UInt8 kAppleCorpCASHA1[kSecPolicySHA1Size] = { + 0xA1, 0x71, 0xDC, 0xDE, 0xE0, 0x8B, 0x1B, 0xAE, 0x30, 0xA1, + 0xAE, 0x6C, 0xC6, 0xD4, 0x03, 0x3B, 0xFD, 0xEF, 0x91, 0xCE +}; + /* * Certificate policy OIDs */ @@ -331,6 +341,12 @@ static CSSM_RETURN iSignSearchUnknownExtensions( /* this is the Apple System Integration 2 Signing extension */ certInfo->foundAppleSysInt2Marker = CSSM_TRUE; } + if (cssmExt->extnId.Length == APPLE_EXTENSION_SERVER_AUTHENTICATION_LENGTH && + !memcmp(cssmExt->extnId.Data, CSSMOID_APPLE_EXTENSION_SERVER_AUTHENTICATION.Data, + APPLE_EXTENSION_SERVER_AUTHENTICATION_LENGTH)) { + /* this is the Apple Server Authentication extension */ + certInfo->foundAppleServerAuthMarker = CSSM_TRUE; + } if (cssmExt->extnId.Length == APPLE_EXTENSION_ESCROW_SERVICE_LENGTH && !memcmp(cssmExt->extnId.Data, CSSMOID_APPLE_EXTENSION_ESCROW_SERVICE.Data, APPLE_EXTENSION_ESCROW_SERVICE_LENGTH)) { @@ -1173,8 +1189,9 @@ static CSSM_RETURN tp_verifySslOpts( TPPolicy policy, TPCertGroup &certGroup, const CSSM_DATA *sslFieldOpts, - const iSignCertInfo &leafCertInfo) + const iSignCertInfo *certInfo) // all certs, size certGroup.numCerts() { + const iSignCertInfo &leafCertInfo = certInfo[0]; CSSM_APPLE_TP_SSL_OPTIONS *sslOpts = NULL; unsigned hostNameLen = 0; const char *serverName = NULL; @@ -1229,12 +1246,49 @@ static CSSM_RETURN tp_verifySslOpts( match = tpCompareSubjectName(*leaf, SN_CommonName, false, hostName, hostNameLen, fieldFound); } + + /* + * Limit allowed domains for specific anchors + */ + CSSM_BOOL domainMatch = CSSM_TRUE; + if(match) { + TPCertInfo *tpCert = certGroup.lastCert(); + if (tpCert) { + const CSSM_DATA *certData = tpCert->itemData(); + unsigned char digest[CC_SHA1_DIGEST_LENGTH]; + CC_SHA1(certData->Data, (CC_LONG)certData->Length, digest); + if (!memcmp(digest, kAppleCorpCASHA1, sizeof(digest))) { + const char *dnlist[] = { "apple.com", "icloud.com" }; + unsigned int idx, dncount=2; + domainMatch = CSSM_FALSE; + for(idx=0;idxaddStatusCode(CSSMERR_APPLETP_HOSTNAME_MISMATCH)) { return CSSMERR_APPLETP_HOSTNAME_MISMATCH; } } + if(!domainMatch) { + if(leaf->addStatusCode(CSSMERR_APPLETP_CA_PIN_MISMATCH)) { + return CSSMERR_APPLETP_CA_PIN_MISMATCH; + } + } } /* @@ -1293,6 +1347,31 @@ static CSSM_RETURN tp_verifySslOpts( } } } + + /* + * Check for additional options flag (2nd lowest bit set) which indicates + * we must be issued by an Apple intermediate with a particular extension. + * (This flag is set by SecPolicyCreateAppleSSLService in SecPolicy.cpp.) + */ + if((sslOpts != NULL) && + (sslOpts->Version > 0) && /* this was added in struct version 1 */ + (sslOpts->Flags & 0x00000002)) { + + if (certGroup.numCerts() > 1) { + const iSignCertInfo *isCertInfo = &certInfo[1]; + if (!(isCertInfo->foundAppleServerAuthMarker == CSSM_TRUE)) { + TPCertInfo *tpCert = certGroup.certAtIndex(1); + tpCert->addStatusCode(CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION); + return CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION; + } + } + else { + /* we only have the leaf? */ + if(leaf->addStatusCode(CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION)) { + return CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION; + } + } + } return CSSM_OK; } @@ -1308,10 +1387,10 @@ static CSSM_RETURN tp_verifySmimeOpts( TPPolicy policy, TPCertGroup &certGroup, const CSSM_DATA *smimeFieldOpts, - const iSignCertInfo &leafCertInfo) + const iSignCertInfo *certInfo) // all certs, size certGroup.numCerts() { + const iSignCertInfo &leafCertInfo = certInfo[0]; bool iChat = (policy == kTP_iChat) ? true : false; - /* * The CSSM_APPLE_TP_SMIME_OPTIONS pointer is optional as is everything in it. */ @@ -2399,9 +2478,10 @@ cleanup: * -- Leaf has CSSMOID_APPLE_EXTENSION_ESCROW_SERVICE_MARKER extension * (1.2.840.113635.100.6.23.1) */ -static CSSM_RETURN tp_verifyEscrowServiceSigningOpts(TPCertGroup &certGroup, +static CSSM_RETURN tp_verifyEscrowServiceCommon(TPCertGroup &certGroup, const CSSM_DATA *fieldOpts, - const iSignCertInfo *certInfo) // all certs, size certGroup.numCerts() + const iSignCertInfo *certInfo, // all certs, size certGroup.numCerts() + SecCertificateEscrowRootType rootType) { unsigned numCerts = certGroup.numCerts(); const iSignCertInfo *isCertInfo; @@ -2414,7 +2494,7 @@ static CSSM_RETURN tp_verifyEscrowServiceSigningOpts(TPCertGroup &certGroup, /* Check that KU extension is present */ if (!isCertInfo->keyUsage.present) { - tpPolicyError("tp_verifyEscrowServiceSigningOpts: no keyUsage in leaf"); + tpPolicyError("tp_verifyEscrowServiceCommon: no keyUsage in leaf"); tpCert->addStatusCode(CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION); crtn = CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION; goto cleanup; @@ -2423,7 +2503,7 @@ static CSSM_RETURN tp_verifyEscrowServiceSigningOpts(TPCertGroup &certGroup, /* Check that KU contains Key Encipherment usage */ ku = isCertInfo->keyUsage.extnData->keyUsage; if (!(ku & CE_KU_KeyEncipherment)) { - tpPolicyError("tp_verifyEscrowServiceSigningOpts: KeyEncipherment usage not found"); + tpPolicyError("tp_verifyEscrowServiceCommon: KeyEncipherment usage not found"); tpCert->addStatusCode(CSSMERR_APPLETP_INVALID_KEY_USAGE); crtn = CSSMERR_APPLETP_INVALID_KEY_USAGE; goto cleanup; @@ -2431,7 +2511,7 @@ static CSSM_RETURN tp_verifyEscrowServiceSigningOpts(TPCertGroup &certGroup, /* Check that Escrow Service marker extension is present */ if (!(isCertInfo->foundEscrowServiceMarker == CSSM_TRUE)) { - tpPolicyError("tp_verifyEscrowServiceSigningOpts: no Escrow Service extension in leaf"); + tpPolicyError("tp_verifyEscrowServiceCommon: no Escrow Service extension in leaf"); tpCert->addStatusCode(CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION); crtn = CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION; goto cleanup; @@ -2439,7 +2519,7 @@ static CSSM_RETURN tp_verifyEscrowServiceSigningOpts(TPCertGroup &certGroup, /* Check that cert chain length is 2 */ if (numCerts != 2) { - tpPolicyError("tp_verifyEscrowServiceSigningOpts: numCerts %u", numCerts); + tpPolicyError("tp_verifyEscrowServiceCommon: numCerts %u", numCerts); crtn = CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH; goto cleanup; } @@ -2452,7 +2532,7 @@ static CSSM_RETURN tp_verifyEscrowServiceSigningOpts(TPCertGroup &certGroup, SecCertificateRef anchor = NULL; OSStatus status = SecCertificateCreateFromData(certData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &anchor); if (!status) { - CFArrayRef anchors = SecCertificateCopyEscrowRoots(kSecCertificateProductionEscrowRoot); + CFArrayRef anchors = SecCertificateCopyEscrowRoots(rootType); CFIndex idx, count = (anchors) ? CFArrayGetCount(anchors) : 0; for (idx = 0; idx < count; idx++) { SecCertificateRef cert = (SecCertificateRef) CFArrayGetValueAtIndex(anchors, idx); @@ -2468,7 +2548,7 @@ static CSSM_RETURN tp_verifyEscrowServiceSigningOpts(TPCertGroup &certGroup, CFRelease(anchor); if (!anchorMatch) { - tpPolicyError("tp_verifyEscrowServiceSigningOpts: invalid anchor for policy"); + tpPolicyError("tp_verifyEscrowServiceCommon: invalid anchor for policy"); tpCert->addStatusCode(CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH); crtn = CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH; goto cleanup; @@ -2479,6 +2559,20 @@ cleanup: return crtn; } +static CSSM_RETURN tp_verifyEscrowServiceSigningOpts(TPCertGroup &certGroup, + const CSSM_DATA *fieldOpts, + const iSignCertInfo *certInfo) // all certs, size certGroup.numCerts() +{ + return tp_verifyEscrowServiceCommon(certGroup, fieldOpts, certInfo, kSecCertificateProductionEscrowRoot); +} + +static CSSM_RETURN tp_verifyPCSEscrowServiceSigningOpts(TPCertGroup &certGroup, + const CSSM_DATA *fieldOpts, + const iSignCertInfo *certInfo) // all certs, size certGroup.numCerts() +{ + return tp_verifyEscrowServiceCommon(certGroup, fieldOpts, certInfo, kSecCertificateProductionPCSEscrowRoot); +} + /* * Verify Configuration Profile Signing policy options. * @@ -3116,15 +3210,14 @@ CSSM_RETURN tp_policyVerify( * FIXME - should this be before or after the root cert test? How can * we return both errors? */ - policyError = tp_verifySslOpts(policy, *certGroup, policyFieldData, certInfo[0]); + policyError = tp_verifySslOpts(policy, *certGroup, policyFieldData, certInfo); break; case kTP_iChat: tpDebug("iChat policy"); /* fall thru */ case kTP_SMIME: - policyError = tp_verifySmimeOpts(policy, *certGroup, policyFieldData, - certInfo[0]); + policyError = tp_verifySmimeOpts(policy, *certGroup, policyFieldData, certInfo); break; case kTP_SWUpdateSign: policyError = tp_verifySWUpdateSigningOpts(*certGroup, policyFieldData, certInfo); @@ -3163,6 +3256,9 @@ CSSM_RETURN tp_policyVerify( case kTP_QAProfileSigning: policyError = tp_verifyProfileSigningOpts(*certGroup, policyFieldData, certInfo, true); break; + case kTP_PCSEscrowService: + policyError = tp_verifyPCSEscrowServiceSigningOpts(*certGroup, policyFieldData, certInfo); + break; case kTPx509Basic: case kTPiSign: case kCrlPolicy: @@ -3266,3 +3362,5 @@ void tp_policyTrustSettingParams( return; } } + +#pragma clang diagnostic pop diff --git a/libsecurity_apple_x509_tp/lib/tpPolicies.h b/Security/libsecurity_apple_x509_tp/lib/tpPolicies.h similarity index 96% rename from libsecurity_apple_x509_tp/lib/tpPolicies.h rename to Security/libsecurity_apple_x509_tp/lib/tpPolicies.h index 9013f0f5..8784b19a 100644 --- a/libsecurity_apple_x509_tp/lib/tpPolicies.h +++ b/Security/libsecurity_apple_x509_tp/lib/tpPolicies.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2013 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -60,6 +60,7 @@ typedef enum { kTP_EscrowService, /* Apple Escrow Service Signing */ kTP_ProfileSigning, /* Apple Configuration Profile Signing */ kTP_QAProfileSigning, /* Apple QA Configuration Profile Signing */ + kTP_PCSEscrowService, /* Apple PCS Escrow Service Signing */ } TPPolicy; /* diff --git a/libsecurity_apple_x509_tp/lib/tpTime.c b/Security/libsecurity_apple_x509_tp/lib/tpTime.c similarity index 98% rename from libsecurity_apple_x509_tp/lib/tpTime.c rename to Security/libsecurity_apple_x509_tp/lib/tpTime.c index eb164202..7d6cc7a9 100644 --- a/libsecurity_apple_x509_tp/lib/tpTime.c +++ b/Security/libsecurity_apple_x509_tp/lib/tpTime.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * tpTime.c - cert related time functions * - * Written 10/10/2000 by Doug Mitchell. */ #include "tpTime.h" diff --git a/libsecurity_apple_x509_tp/lib/tpTime.h b/Security/libsecurity_apple_x509_tp/lib/tpTime.h similarity index 96% rename from libsecurity_apple_x509_tp/lib/tpTime.h rename to Security/libsecurity_apple_x509_tp/lib/tpTime.h index 82d109fa..0c9019a9 100644 --- a/libsecurity_apple_x509_tp/lib/tpTime.h +++ b/Security/libsecurity_apple_x509_tp/lib/tpTime.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,7 +19,6 @@ /* * tpTime.h - cert related time functions * - * Written 10/10/2000 by Doug Mitchell. */ #ifndef _TP_TIME_H_ diff --git a/libsecurity_apple_x509_tp/lib/tpdebugging.h b/Security/libsecurity_apple_x509_tp/lib/tpdebugging.h similarity index 97% rename from libsecurity_apple_x509_tp/lib/tpdebugging.h rename to Security/libsecurity_apple_x509_tp/lib/tpdebugging.h index 681dd811..91032aa6 100644 --- a/libsecurity_apple_x509_tp/lib/tpdebugging.h +++ b/Security/libsecurity_apple_x509_tp/lib/tpdebugging.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_apple_x509_tp/libsecurity_apple_x509_tp.xcodeproj/project.pbxproj b/Security/libsecurity_apple_x509_tp/libsecurity_apple_x509_tp.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_apple_x509_tp/libsecurity_apple_x509_tp.xcodeproj/project.pbxproj rename to Security/libsecurity_apple_x509_tp/libsecurity_apple_x509_tp.xcodeproj/project.pbxproj diff --git a/libsecurity_apple_x509_tp/mds/tp_common.mdsinfo b/Security/libsecurity_apple_x509_tp/mds/tp_common.mdsinfo similarity index 100% rename from libsecurity_apple_x509_tp/mds/tp_common.mdsinfo rename to Security/libsecurity_apple_x509_tp/mds/tp_common.mdsinfo diff --git a/libsecurity_apple_x509_tp/mds/tp_policyOids.mdsinfo b/Security/libsecurity_apple_x509_tp/mds/tp_policyOids.mdsinfo similarity index 100% rename from libsecurity_apple_x509_tp/mds/tp_policyOids.mdsinfo rename to Security/libsecurity_apple_x509_tp/mds/tp_policyOids.mdsinfo diff --git a/libsecurity_apple_x509_tp/mds/tp_primary.mdsinfo b/Security/libsecurity_apple_x509_tp/mds/tp_primary.mdsinfo similarity index 100% rename from libsecurity_apple_x509_tp/mds/tp_primary.mdsinfo rename to Security/libsecurity_apple_x509_tp/mds/tp_primary.mdsinfo diff --git a/libsecurity_asn1/APPLE_LICENSE b/Security/libsecurity_asn1/APPLE_LICENSE similarity index 100% rename from libsecurity_asn1/APPLE_LICENSE rename to Security/libsecurity_asn1/APPLE_LICENSE diff --git a/libsecurity_asn1/CHANGES.Apple b/Security/libsecurity_asn1/CHANGES.Apple similarity index 100% rename from libsecurity_asn1/CHANGES.Apple rename to Security/libsecurity_asn1/CHANGES.Apple diff --git a/libsecurity_asn1/Info-security_asn1.plist b/Security/libsecurity_asn1/Info-security_asn1.plist similarity index 100% rename from libsecurity_asn1/Info-security_asn1.plist rename to Security/libsecurity_asn1/Info-security_asn1.plist diff --git a/libsecurity_asn1/Makefile b/Security/libsecurity_asn1/Makefile similarity index 100% rename from libsecurity_asn1/Makefile rename to Security/libsecurity_asn1/Makefile diff --git a/libsecurity_asn1/MozillaPublicLicense1.1.html b/Security/libsecurity_asn1/MozillaPublicLicense1.1.html similarity index 100% rename from libsecurity_asn1/MozillaPublicLicense1.1.html rename to Security/libsecurity_asn1/MozillaPublicLicense1.1.html diff --git a/libsecurity_asn1/Security b/Security/libsecurity_asn1/Security similarity index 100% rename from libsecurity_asn1/Security rename to Security/libsecurity_asn1/Security diff --git a/libsecurity_asn1/asn1/README b/Security/libsecurity_asn1/asn1/README similarity index 100% rename from libsecurity_asn1/asn1/README rename to Security/libsecurity_asn1/asn1/README diff --git a/libsecurity_asn1/asn1/appleoids.asn b/Security/libsecurity_asn1/asn1/appleoids.asn similarity index 100% rename from libsecurity_asn1/asn1/appleoids.asn rename to Security/libsecurity_asn1/asn1/appleoids.asn diff --git a/libsecurity_asn1/asn1/asn-useful.asn1 b/Security/libsecurity_asn1/asn1/asn-useful.asn1 similarity index 100% rename from libsecurity_asn1/asn1/asn-useful.asn1 rename to Security/libsecurity_asn1/asn1/asn-useful.asn1 diff --git a/libsecurity_asn1/asn1/pkcs1.asn1 b/Security/libsecurity_asn1/asn1/pkcs1.asn1 similarity index 100% rename from libsecurity_asn1/asn1/pkcs1.asn1 rename to Security/libsecurity_asn1/asn1/pkcs1.asn1 diff --git a/libsecurity_asn1/asn1/pkcs10.asn b/Security/libsecurity_asn1/asn1/pkcs10.asn similarity index 100% rename from libsecurity_asn1/asn1/pkcs10.asn rename to Security/libsecurity_asn1/asn1/pkcs10.asn diff --git a/libsecurity_asn1/asn1/pkcs1oids.asn b/Security/libsecurity_asn1/asn1/pkcs1oids.asn similarity index 100% rename from libsecurity_asn1/asn1/pkcs1oids.asn rename to Security/libsecurity_asn1/asn1/pkcs1oids.asn diff --git a/libsecurity_asn1/asn1/pkcs5.asn1 b/Security/libsecurity_asn1/asn1/pkcs5.asn1 similarity index 100% rename from libsecurity_asn1/asn1/pkcs5.asn1 rename to Security/libsecurity_asn1/asn1/pkcs5.asn1 diff --git a/libsecurity_asn1/asn1/pkcs7.asn b/Security/libsecurity_asn1/asn1/pkcs7.asn similarity index 100% rename from libsecurity_asn1/asn1/pkcs7.asn rename to Security/libsecurity_asn1/asn1/pkcs7.asn diff --git a/libsecurity_asn1/asn1/pkcs8.asn b/Security/libsecurity_asn1/asn1/pkcs8.asn similarity index 100% rename from libsecurity_asn1/asn1/pkcs8.asn rename to Security/libsecurity_asn1/asn1/pkcs8.asn diff --git a/libsecurity_asn1/asn1/pkcs9oids.asn b/Security/libsecurity_asn1/asn1/pkcs9oids.asn similarity index 100% rename from libsecurity_asn1/asn1/pkcs9oids.asn rename to Security/libsecurity_asn1/asn1/pkcs9oids.asn diff --git a/libsecurity_asn1/asn1/rfc3161.asn1 b/Security/libsecurity_asn1/asn1/rfc3161.asn1 similarity index 100% rename from libsecurity_asn1/asn1/rfc3161.asn1 rename to Security/libsecurity_asn1/asn1/rfc3161.asn1 diff --git a/libsecurity_asn1/asn1/sm_cms.asn b/Security/libsecurity_asn1/asn1/sm_cms.asn similarity index 100% rename from libsecurity_asn1/asn1/sm_cms.asn rename to Security/libsecurity_asn1/asn1/sm_cms.asn diff --git a/libsecurity_asn1/asn1/sm_ess.asn b/Security/libsecurity_asn1/asn1/sm_ess.asn similarity index 100% rename from libsecurity_asn1/asn1/sm_ess.asn rename to Security/libsecurity_asn1/asn1/sm_ess.asn diff --git a/libsecurity_asn1/asn1/sm_vdatypes.asn b/Security/libsecurity_asn1/asn1/sm_vdatypes.asn similarity index 100% rename from libsecurity_asn1/asn1/sm_vdatypes.asn rename to Security/libsecurity_asn1/asn1/sm_vdatypes.asn diff --git a/libsecurity_asn1/asn1/sm_x411mtsas.asn b/Security/libsecurity_asn1/asn1/sm_x411mtsas.asn similarity index 100% rename from libsecurity_asn1/asn1/sm_x411mtsas.asn rename to Security/libsecurity_asn1/asn1/sm_x411mtsas.asn diff --git a/libsecurity_asn1/asn1/sm_x411ub.asn b/Security/libsecurity_asn1/asn1/sm_x411ub.asn similarity index 100% rename from libsecurity_asn1/asn1/sm_x411ub.asn rename to Security/libsecurity_asn1/asn1/sm_x411ub.asn diff --git a/libsecurity_asn1/asn1/sm_x501if.asn b/Security/libsecurity_asn1/asn1/sm_x501if.asn similarity index 100% rename from libsecurity_asn1/asn1/sm_x501if.asn rename to Security/libsecurity_asn1/asn1/sm_x501if.asn diff --git a/libsecurity_asn1/asn1/sm_x501ud.asn b/Security/libsecurity_asn1/asn1/sm_x501ud.asn similarity index 100% rename from libsecurity_asn1/asn1/sm_x501ud.asn rename to Security/libsecurity_asn1/asn1/sm_x501ud.asn diff --git a/libsecurity_asn1/asn1/sm_x509af.asn b/Security/libsecurity_asn1/asn1/sm_x509af.asn similarity index 100% rename from libsecurity_asn1/asn1/sm_x509af.asn rename to Security/libsecurity_asn1/asn1/sm_x509af.asn diff --git a/libsecurity_asn1/asn1/sm_x509ce.asn b/Security/libsecurity_asn1/asn1/sm_x509ce.asn similarity index 100% rename from libsecurity_asn1/asn1/sm_x509ce.asn rename to Security/libsecurity_asn1/asn1/sm_x509ce.asn diff --git a/libsecurity_asn1/asn1/sm_x509cmn.asn b/Security/libsecurity_asn1/asn1/sm_x509cmn.asn similarity index 100% rename from libsecurity_asn1/asn1/sm_x509cmn.asn rename to Security/libsecurity_asn1/asn1/sm_x509cmn.asn diff --git a/libsecurity_asn1/asn1/sm_x520sa.asn b/Security/libsecurity_asn1/asn1/sm_x520sa.asn similarity index 100% rename from libsecurity_asn1/asn1/sm_x520sa.asn rename to Security/libsecurity_asn1/asn1/sm_x520sa.asn diff --git a/Security/libsecurity_asn1/config/base.xcconfig b/Security/libsecurity_asn1/config/base.xcconfig new file mode 100644 index 00000000..3cb11215 --- /dev/null +++ b/Security/libsecurity_asn1/config/base.xcconfig @@ -0,0 +1,10 @@ +CODE_SIGN_IDENTITY = -; +GCC_VERSION = com.apple.compilers.llvm.clang.1_0 +DEBUG_INFORMATION_FORMAT = dwarf-with-dsym +CURRENT_PROJECT_VERSION = $(RC_ProjectSourceVersion) +VERSIONING_SYSTEM = apple-generic; +DEAD_CODE_STRIPPING = YES; + +ARCHS = $(ARCHS_STANDARD_32_64_BIT) + +WARNING_CFLAGS = -Wglobal-constructors -Wno-deprecated-declarations $(inherited) diff --git a/libsecurity_asn1/config/debug.xcconfig b/Security/libsecurity_asn1/config/debug.xcconfig similarity index 100% rename from libsecurity_asn1/config/debug.xcconfig rename to Security/libsecurity_asn1/config/debug.xcconfig diff --git a/Security/libsecurity_asn1/config/lib.xcconfig b/Security/libsecurity_asn1/config/lib.xcconfig new file mode 100644 index 00000000..2373abe7 --- /dev/null +++ b/Security/libsecurity_asn1/config/lib.xcconfig @@ -0,0 +1,39 @@ +#include "base.xcconfig" + +PRODUCT_NAME = $(TARGET_NAME) +EXECUTABLE_PREFIX = + +CODE_SIGN_IDENTITY = + +HEADER_SEARCH_PATHS[sdk=macosx*] = $(PROJECT_DIR) $(PROJECT_DIR)/../include $(BUILT_PRODUCTS_DIR)/derived_src $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers $(inherited) + +HEADER_SEARCH_PATHS[sdk=iphone*] = $(PROJECT_DIR) $(PROJECT_DIR)/../sec $(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include $(inherited) + +#include "/AppleInternal/XcodeConfig/SimulatorSupport.xcconfig" + +// Set INSTALL_PATH_ACTUAL to whatever INSTALL_PATH would normally be +INSTALL_PATH_ACTUAL = /usr/local/lib + +// Set INSTALL_PATH[sdk=macosx*] when SimulatorSupport.xcconfig is unavailable +INSTALL_PATH[sdk=macosx*] = $(INSTALL_PATH_ACTUAL) + +// Use $(INSTALL_PATH_PREFIX) instead of $(SDKROOT) as a prefix for other +// variables as appropriate +PUBLIC_HEADERS_FOLDER_PATH = $(INSTALL_PATH_PREFIX)/usr/local/include/security_asn1 +PRIVATE_HEADERS_FOLDER_PATH = $(INSTALL_PATH_PREFIX)/usr/local/include/security_asn1 + +ALWAYS_SEARCH_USER_PATHS = NO + +GCC_C_LANGUAGE_STANDARD = gnu99 + +WARNING_CFLAGS = -Wmost -Wno-four-char-constants -Wno-unknown-pragmas $(inherited) + +GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO + +GCC_SYMBOLS_PRIVATE_EXTERN = NO +GCC_WARN_64_TO_32_BIT_CONVERSION = YES +GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES +GCC_WARN_ABOUT_RETURN_TYPE = YES +GCC_WARN_UNUSED_VARIABLE = YES + +SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator diff --git a/libsecurity_asn1/config/release.xcconfig b/Security/libsecurity_asn1/config/release.xcconfig similarity index 100% rename from libsecurity_asn1/config/release.xcconfig rename to Security/libsecurity_asn1/config/release.xcconfig diff --git a/libsecurity_asn1/docs/libsecurity_asn1.plist b/Security/libsecurity_asn1/docs/libsecurity_asn1.plist similarity index 100% rename from libsecurity_asn1/docs/libsecurity_asn1.plist rename to Security/libsecurity_asn1/docs/libsecurity_asn1.plist diff --git a/libsecurity_asn1/docs/libsecurity_asn1.txt b/Security/libsecurity_asn1/docs/libsecurity_asn1.txt similarity index 100% rename from libsecurity_asn1/docs/libsecurity_asn1.txt rename to Security/libsecurity_asn1/docs/libsecurity_asn1.txt diff --git a/libsecurity_asn1/lib/SecAsn1Coder.c b/Security/libsecurity_asn1/lib/SecAsn1Coder.c similarity index 98% rename from libsecurity_asn1/lib/SecAsn1Coder.c rename to Security/libsecurity_asn1/lib/SecAsn1Coder.c index 3512ffce..a4605f99 100644 --- a/libsecurity_asn1/lib/SecAsn1Coder.c +++ b/Security/libsecurity_asn1/lib/SecAsn1Coder.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/SecAsn1Coder.h b/Security/libsecurity_asn1/lib/SecAsn1Coder.h similarity index 98% rename from libsecurity_asn1/lib/SecAsn1Coder.h rename to Security/libsecurity_asn1/lib/SecAsn1Coder.h index d27e768d..1901ff0c 100644 --- a/libsecurity_asn1/lib/SecAsn1Coder.h +++ b/Security/libsecurity_asn1/lib/SecAsn1Coder.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/SecAsn1Templates.c b/Security/libsecurity_asn1/lib/SecAsn1Templates.c similarity index 99% rename from libsecurity_asn1/lib/SecAsn1Templates.c rename to Security/libsecurity_asn1/lib/SecAsn1Templates.c index 38b25ff6..edd945e0 100644 --- a/libsecurity_asn1/lib/SecAsn1Templates.c +++ b/Security/libsecurity_asn1/lib/SecAsn1Templates.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2008,2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/SecAsn1Templates.h b/Security/libsecurity_asn1/lib/SecAsn1Templates.h similarity index 98% rename from libsecurity_asn1/lib/SecAsn1Templates.h rename to Security/libsecurity_asn1/lib/SecAsn1Templates.h index 78cd73e3..7c2018ce 100644 --- a/libsecurity_asn1/lib/SecAsn1Templates.h +++ b/Security/libsecurity_asn1/lib/SecAsn1Templates.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/SecAsn1Types.h b/Security/libsecurity_asn1/lib/SecAsn1Types.h similarity index 100% rename from libsecurity_asn1/lib/SecAsn1Types.h rename to Security/libsecurity_asn1/lib/SecAsn1Types.h diff --git a/Security/libsecurity_asn1/lib/SecNssCoder.cpp b/Security/libsecurity_asn1/lib/SecNssCoder.cpp new file mode 100644 index 00000000..86bb8d2e --- /dev/null +++ b/Security/libsecurity_asn1/lib/SecNssCoder.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + * + * SecNssCoder.cpp: simple C++ wrapper for PLArenaPool and the + * high-level ANS1 encode/decode routines. + */ + +#include +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) + +#include "SecNssCoder.h" +#include +#include +#include +#include +#include + +#ifdef NDEBUG +#define THROW_ENABLE 1 +#else +/* disable link against Security framework when true */ +#define THROW_ENABLE 0 +#endif + +#if THROW_ENABLE +#define THROW_ERROR Security::CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR) +#else +#define THROW_ERROR +#endif + +SecNssCoder::SecNssCoder(PRUint32 chunkSize /* = SNC_CHUNKSIZE_DEF */) + : mPool(NULL) +{ + mPool = PORT_NewArena(chunkSize); + if(mPool == NULL) { + THROW_ERROR; + } +} + +SecNssCoder::~SecNssCoder() +{ + if(mPool != NULL) { + /* + * Note: we're asking for a memory zero here, but + * PORT_FreeArena doesn't do that (yet). + */ + PORT_FreeArena(mPool, PR_TRUE); + mPool = NULL; + } +} + +PRErrorCode SecNssCoder::decode( + const void *src, // BER-encoded source + size_t len, + const SecAsn1Template *templ, + void *dest) +{ + SECStatus prtn; + + assert(mPool != NULL); + prtn = SEC_ASN1Decode(mPool, dest, templ, (const char *)src, len); + if(prtn) { + return PR_GetError(); + } + else { + return 0; + } +} + +PRErrorCode SecNssCoder::encodeItem( + const void *src, + const SecAsn1Template *templ, + SECItem &dest) +{ + assert(mPool != NULL); + + dest.Data = NULL; + dest.Length = 0; + + SECItem *rtnItem = SEC_ASN1EncodeItem(mPool, &dest, src, templ); + if(rtnItem == NULL) { + return PR_GetError(); + } + else { + return 0; + } +} + +void *SecNssCoder::malloc(size_t len) +{ + assert(mPool != NULL); + void *rtn = PORT_ArenaAlloc(mPool, len); + if(rtn == NULL) { + THROW_ERROR; + } + return rtn; +} + +/* malloc item.Data, set item.Length */ +void SecNssCoder::allocItem( + SECItem &item, + size_t len) +{ + item.Data = (uint8 *)malloc(len); + item.Length = len; +} + +/* malloc and copy */ +void SecNssCoder::allocCopyItem( + const void *src, + size_t len, + SECItem &dest) +{ + allocItem(dest, len); + memmove(dest.Data, src, len); +} + +/* + * This is pretty much a copy of SEC_ASN1EncodeItem, with a Allocator + * malloc replacing the sec_asn1e_allocate_item to alloc the output data. + */ +PRErrorCode SecNssEncodeItem( + const void *src, + const SecAsn1Template *templ, + Security::Allocator &alloc, + SECItem &dest) +{ + unsigned long encoding_length = 0; + SECStatus rv; + + dest.Data = NULL; + dest.Length = 0; + + rv = SEC_ASN1Encode (src, templ, + sec_asn1e_encode_item_count, &encoding_length); + if (rv != SECSuccess) { + return PR_GetError(); + } + + /* replace this... + dest = sec_asn1e_allocate_item (poolp, dest, encoding_length); + if (dest == NULL) + return NULL; + ... with this: */ + dest.Data = (uint8 *)alloc.malloc(encoding_length); + dest.Length = 0; + /* end replacement */ + + rv = SEC_ASN1Encode (src, templ, sec_asn1e_encode_item_store, &dest); + if (rv != SECSuccess) { + return PR_GetError(); + } + + assert(encoding_length == dest.Length); + return 0; +} + +PRErrorCode SecNssEncodeItemOdata( + const void *src, + const SecAsn1Template *templ, + CssmOwnedData &odata) +{ + Allocator &alloc = odata.allocator; + SECItem sitem; + PRErrorCode prtn; + + prtn = SecNssEncodeItem(src, templ, alloc, sitem); + if(prtn) { + return prtn; + } + odata.set(sitem.Data, sitem.Length); + return 0; +} + +#endif /* TARGET_OS_MAC */ diff --git a/Security/libsecurity_asn1/lib/SecNssCoder.h b/Security/libsecurity_asn1/lib/SecNssCoder.h new file mode 100644 index 00000000..52d83cec --- /dev/null +++ b/Security/libsecurity_asn1/lib/SecNssCoder.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + * + * SecNssCoder.h: simple C++ wrapper for PLArenaPool and the + * high-level ANS1 encode/decode routines. + */ +#ifndef _SEC_NSS_CODER_H_ +#define _SEC_NSS_CODER_H_ + +#include +#include +#include +#include +#include +#include + +/* + * Default chunk size for new arena pool. + * FIXME: analyze & measure different defaults here. I'm pretty sure + * that only performance - not correct behavior - is affected by + * an arena pool's chunk size. + */ +#define SNC_CHUNKSIZE_DEF 1024 + +class SecNssCoder +{ +public: + SecNssCoder( + PRUint32 chunkSize = SNC_CHUNKSIZE_DEF); + ~SecNssCoder(); + + /* + * BER decode an untyped item per the specified + * template array. The result is allocated + * by this object's PLArenaPool and is freed when + * this object is deleted. + * + * The dest pointer is a template-specific struct allocated + * by the caller and must be zeroed by the caller. + * + * This does not throw any exceptions; error status + * (obtained from PR_GetError() is returned. + */ + PRErrorCode decode( + const void *src, // BER-encoded source + size_t len, + const SecAsn1Template *templ, + void *dest); + + /* convenience routine, decode from an SECItem */ + PRErrorCode decodeItem( + const SECItem &item, // BER-encoded source + const SecAsn1Template *templ, + void *dest) + { + return decode(item.Data, item.Length, templ, dest); + } + + + /* + * BER-encode. This object's arena pool retains a copy of + * the encoded data. + * + * The src pointer is a template-specific struct. + * + * This does not throw any exceptions; error status + * (obtained from PR_GetError() is returned. + */ + PRErrorCode encodeItem( + const void *src, + const SecAsn1Template *templ, + SECItem &dest); + + /* + * Some alloc-related methods which come in handy when using + * this class. All memory is allocated using this object's + * arena pool. Caller never has to free it. Used for + * temp allocs of memory which only needs a scope which is the + * same as this object. + * + * These throw a CssmError in the highly unlikely event of + * a malloc failure. + */ + void *malloc( + size_t len); + + /* allocate space for num copies of specified type */ + template T *mallocn(unsigned num = 1) + { return reinterpret_cast(malloc(sizeof(T) * num)); } + + /* malloc item.Data, set item.Length */ + void allocItem( + SECItem &item, + size_t len); + + /* malloc and copy, various forms */ + void allocCopyItem( + const void *src, + size_t len, + SECItem &dest); + + void allocCopyItem( + const SECItem &src, + SECItem &dest) + { allocCopyItem(src.Data, src.Length, dest); } + + void allocCopyItem( + const CssmData &src, + SECItem &dest) + { allocCopyItem(src.data(), src.length(), dest); } + + PLArenaPool *pool() const { return mPool;} + +private: + PLArenaPool *mPool; +}; + +/* + * Stateless function to BER-encode directly into a Allocator's + * space. The only persistent allocated memory is allocated by + * the Allocator. + * + * The src pointer is a template-specific struct. + * + * This does not throw any exceptions; error status + * (obtained from PR_GetError() is returned. + */ +PRErrorCode SecNssEncodeItem( + const void *src, + const SecAsn1Template *templ, + Allocator &alloc, + SECItem &dest); + +/* + * Same thing, using a CssmOwnedData. + */ +PRErrorCode SecNssEncodeItemOdata( + const void *src, + const SecAsn1Template *templ, + CssmOwnedData &odata); + +#endif /* _SEC_NSS_CODER_H_ */ diff --git a/libsecurity_asn1/lib/X509Templates.c b/Security/libsecurity_asn1/lib/X509Templates.c similarity index 98% rename from libsecurity_asn1/lib/X509Templates.c rename to Security/libsecurity_asn1/lib/X509Templates.c index 67ac9e79..4677b4ee 100644 --- a/libsecurity_asn1/lib/X509Templates.c +++ b/Security/libsecurity_asn1/lib/X509Templates.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/X509Templates.h b/Security/libsecurity_asn1/lib/X509Templates.h similarity index 98% rename from libsecurity_asn1/lib/X509Templates.h rename to Security/libsecurity_asn1/lib/X509Templates.h index ad071bb2..c4532d14 100644 --- a/libsecurity_asn1/lib/X509Templates.h +++ b/Security/libsecurity_asn1/lib/X509Templates.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/asn1Templates.h b/Security/libsecurity_asn1/lib/asn1Templates.h similarity index 94% rename from libsecurity_asn1/lib/asn1Templates.h rename to Security/libsecurity_asn1/lib/asn1Templates.h index 70f6fa47..ec00625f 100644 --- a/libsecurity_asn1/lib/asn1Templates.h +++ b/Security/libsecurity_asn1/lib/asn1Templates.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2006,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2005-2006,2008,2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/certExtensionTemplates.c b/Security/libsecurity_asn1/lib/certExtensionTemplates.c similarity index 99% rename from libsecurity_asn1/lib/certExtensionTemplates.c rename to Security/libsecurity_asn1/lib/certExtensionTemplates.c index b15c23be..02315128 100644 --- a/libsecurity_asn1/lib/certExtensionTemplates.c +++ b/Security/libsecurity_asn1/lib/certExtensionTemplates.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/certExtensionTemplates.h b/Security/libsecurity_asn1/lib/certExtensionTemplates.h similarity index 99% rename from libsecurity_asn1/lib/certExtensionTemplates.h rename to Security/libsecurity_asn1/lib/certExtensionTemplates.h index 644c8fe9..fd575fb1 100644 --- a/libsecurity_asn1/lib/certExtensionTemplates.h +++ b/Security/libsecurity_asn1/lib/certExtensionTemplates.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/csrTemplates.c b/Security/libsecurity_asn1/lib/csrTemplates.c similarity index 97% rename from libsecurity_asn1/lib/csrTemplates.c rename to Security/libsecurity_asn1/lib/csrTemplates.c index 9d01f713..d4ea114b 100644 --- a/libsecurity_asn1/lib/csrTemplates.c +++ b/Security/libsecurity_asn1/lib/csrTemplates.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/csrTemplates.h b/Security/libsecurity_asn1/lib/csrTemplates.h similarity index 96% rename from libsecurity_asn1/lib/csrTemplates.h rename to Security/libsecurity_asn1/lib/csrTemplates.h index a97ec5fa..bedc7e67 100644 --- a/libsecurity_asn1/lib/csrTemplates.h +++ b/Security/libsecurity_asn1/lib/csrTemplates.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/keyTemplates.c b/Security/libsecurity_asn1/lib/keyTemplates.c similarity index 99% rename from libsecurity_asn1/lib/keyTemplates.c rename to Security/libsecurity_asn1/lib/keyTemplates.c index 8f4e4651..d3c28816 100644 --- a/libsecurity_asn1/lib/keyTemplates.c +++ b/Security/libsecurity_asn1/lib/keyTemplates.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/keyTemplates.h b/Security/libsecurity_asn1/lib/keyTemplates.h similarity index 99% rename from libsecurity_asn1/lib/keyTemplates.h rename to Security/libsecurity_asn1/lib/keyTemplates.h index 9b766faf..ce726ff3 100644 --- a/libsecurity_asn1/lib/keyTemplates.h +++ b/Security/libsecurity_asn1/lib/keyTemplates.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/nameTemplates.c b/Security/libsecurity_asn1/lib/nameTemplates.c similarity index 95% rename from libsecurity_asn1/lib/nameTemplates.c rename to Security/libsecurity_asn1/lib/nameTemplates.c index e466cb3c..0403ab4e 100644 --- a/libsecurity_asn1/lib/nameTemplates.c +++ b/Security/libsecurity_asn1/lib/nameTemplates.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -187,9 +187,6 @@ const SecAsn1Template kSecAsn1GenNameOtherNameTemplate[] = { */ /* inner contents of an ASN_ANY */ -static const SecAsn1Template kSecAsn1InnerAnyTemplate[] = { - { SEC_ASN1_ANY | SEC_ASN1_INNER, 0, NULL, sizeof(SecAsn1Item) } -}; #define NSS_GEN_NAME_OFFSET (offsetof(NSS_GeneralName,item)) #define NSS_GEN_NAME_SIZE (sizeof(NSS_GeneralName)) @@ -210,18 +207,11 @@ const SecAsn1Template kSecAsn1X400AddressTemplate[] = { { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | NGT_X400Address, NSS_GEN_NAME_OFFSET, kSecAsn1AnyTemplate, NSS_GEN_NAME_SIZE } }; -#if 0 -const SecAsn1Template kSecAsn1DirectoryNameTemplate[] = { - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | NGT_DirectoryName, - NSS_GEN_NAME_OFFSET, kSecAsn1InnerAnyTemplate, NSS_GEN_NAME_SIZE } -}; -#else const SecAsn1Template kSecAsn1DirectoryNameTemplate[] = { { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | NGT_DirectoryName, NSS_GEN_NAME_OFFSET, kSecAsn1AnyTemplate, NSS_GEN_NAME_SIZE } }; -#endif const SecAsn1Template kSecAsn1EdiPartyNameTemplate[] = { { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | NGT_EdiPartyName, NSS_GEN_NAME_OFFSET, kSecAsn1AnyTemplate, NSS_GEN_NAME_SIZE } diff --git a/libsecurity_asn1/lib/nameTemplates.h b/Security/libsecurity_asn1/lib/nameTemplates.h similarity index 98% rename from libsecurity_asn1/lib/nameTemplates.h rename to Security/libsecurity_asn1/lib/nameTemplates.h index 0e55eae8..638bd09a 100644 --- a/libsecurity_asn1/lib/nameTemplates.h +++ b/Security/libsecurity_asn1/lib/nameTemplates.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/nsprPortX.c b/Security/libsecurity_asn1/lib/nsprPortX.c similarity index 98% rename from libsecurity_asn1/lib/nsprPortX.c rename to Security/libsecurity_asn1/lib/nsprPortX.c index 6c642fb3..16d5b79c 100644 --- a/libsecurity_asn1/lib/nsprPortX.c +++ b/Security/libsecurity_asn1/lib/nsprPortX.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/nssUtils.c b/Security/libsecurity_asn1/lib/nssUtils.c similarity index 95% rename from libsecurity_asn1/lib/nssUtils.c rename to Security/libsecurity_asn1/lib/nssUtils.c index d03dc753..80cb1fc3 100644 --- a/libsecurity_asn1/lib/nssUtils.c +++ b/Security/libsecurity_asn1/lib/nssUtils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/nssUtils.h b/Security/libsecurity_asn1/lib/nssUtils.h similarity index 95% rename from libsecurity_asn1/lib/nssUtils.h rename to Security/libsecurity_asn1/lib/nssUtils.h index bd09e6c1..bd42ac29 100644 --- a/libsecurity_asn1/lib/nssUtils.h +++ b/Security/libsecurity_asn1/lib/nssUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/nssilckt.h b/Security/libsecurity_asn1/lib/nssilckt.h similarity index 100% rename from libsecurity_asn1/lib/nssilckt.h rename to Security/libsecurity_asn1/lib/nssilckt.h diff --git a/libsecurity_asn1/lib/nssilock.h b/Security/libsecurity_asn1/lib/nssilock.h similarity index 100% rename from libsecurity_asn1/lib/nssilock.h rename to Security/libsecurity_asn1/lib/nssilock.h diff --git a/libsecurity_asn1/lib/nsslocks.h b/Security/libsecurity_asn1/lib/nsslocks.h similarity index 100% rename from libsecurity_asn1/lib/nsslocks.h rename to Security/libsecurity_asn1/lib/nsslocks.h diff --git a/libsecurity_asn1/lib/ocspTemplates.c b/Security/libsecurity_asn1/lib/ocspTemplates.c similarity index 99% rename from libsecurity_asn1/lib/ocspTemplates.c rename to Security/libsecurity_asn1/lib/ocspTemplates.c index fb32f56a..173bc769 100644 --- a/libsecurity_asn1/lib/ocspTemplates.c +++ b/Security/libsecurity_asn1/lib/ocspTemplates.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/ocspTemplates.h b/Security/libsecurity_asn1/lib/ocspTemplates.h similarity index 99% rename from libsecurity_asn1/lib/ocspTemplates.h rename to Security/libsecurity_asn1/lib/ocspTemplates.h index af742a37..2af1efc3 100644 --- a/libsecurity_asn1/lib/ocspTemplates.h +++ b/Security/libsecurity_asn1/lib/ocspTemplates.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_asn1/lib/oidsalg.c b/Security/libsecurity_asn1/lib/oidsalg.c new file mode 100644 index 00000000..6aa61312 --- /dev/null +++ b/Security/libsecurity_asn1/lib/oidsalg.c @@ -0,0 +1,501 @@ +/* + * Copyright (c) 2000-2004,2008,2010,2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * oidsalg.c - OIDs defining crypto algorithms + */ + +#include +#include "SecAsn1Types.h" +#include "oidsbase.h" + +static const uint8_t + OID_MD2[] = { OID_RSA_HASH, 2 }, + OID_MD4[] = { OID_RSA_HASH, 4 }, + OID_MD5[] = { OID_RSA_HASH, 5 }, + OID_RSAEncryption[] = { OID_PKCS_1, 1 }, + OID_MD2WithRSA[] = { OID_PKCS_1, 2 }, + OID_MD4WithRSA[] = { OID_PKCS_1, 3 }, + OID_MD5WithRSA[] = { OID_PKCS_1, 4 }, + OID_SHA1WithRSA[] = { OID_PKCS_1, 5 }, + OID_RSAWithOAEP[] = { OID_PKCS_1, 7 }, + OID_OAEP_MGF1[] = { OID_PKCS_1, 8 }, + OID_OAEP_ID_PSPECIFIED[]= { OID_PKCS_1, 9 }, + OID_SHA224WithRSA[] = { OID_PKCS_1, 14 }, + OID_SHA256WithRSA[] = { OID_PKCS_1, 11 }, + OID_SHA384WithRSA[] = { OID_PKCS_1, 12 }, + OID_SHA512WithRSA[] = { OID_PKCS_1, 13 }, + OID_PKCS_3_ARC[] = { OID_PKCS_3 }, + OID_DHKeyAgreement[] = { OID_PKCS_3, 1 }, + /* BSAFE-specific DSA */ + OID_OIW_DSA[] = { OID_OIW_ALGORITHM, 12 }, + OID_OIW_DSAWithSHA1[] = { OID_OIW_ALGORITHM, 27 }, + /* DSA from CMS */ + OID_CMS_DSA[] = { 0x2A, 0x86, 0x48, 0xCE, 0x38, 4, 1 }, + OID_CMS_DSAWithSHA1[] = { 0x2A, 0x86, 0x48, 0xCE, 0x38, 4, 3 }, + /* DSA from JDK 1.1 */ + OID_JDK_DSA[] = { 0x2B, 0x0E, 0x03, 0x02, 0x0c }, + OID_JDK_DSAWithSHA1[] = { 0x2B, 0x0E, 0x03, 0x02, 0x0D }, + + OID_OIW_SHA1[] = { OID_OIW_ALGORITHM, 26 }, + OID_OIW_RSAWithSHA1[] = { OID_OIW_ALGORITHM, 29 }, + OID_OIW_DES_CBC[] = { OID_OIW_ALGORITHM, 7 }, + + OID_SHA224[] = { OID_NIST_HASHALG, 4}, + OID_SHA256[] = { OID_NIST_HASHALG, 1}, + OID_SHA384[] = { OID_NIST_HASHALG, 2}, + OID_SHA512[] = { OID_NIST_HASHALG, 3}, + + /* ANSI X9.42 */ + OID_ANSI_DH_PUB_NUMBER[]= { OID_ANSI_X9_42, 1 }, + OID_ANSI_DH_STATIC[] = { OID_ANSI_X9_42_SCHEME, 1 }, + OID_ANSI_DH_EPHEM[] = { OID_ANSI_X9_42_SCHEME, 2 }, + OID_ANSI_DH_ONE_FLOW[] = { OID_ANSI_X9_42_SCHEME, 3 }, + OID_ANSI_DH_HYBRID1[] = { OID_ANSI_X9_42_SCHEME, 4 }, + OID_ANSI_DH_HYBRID2[] = { OID_ANSI_X9_42_SCHEME, 5 }, + OID_ANSI_DH_HYBRID_ONEFLOW[] = { OID_ANSI_X9_42_SCHEME, 6 }, + /* sic - enumerated in reverse order in the spec */ + OID_ANSI_MQV1[] = { OID_ANSI_X9_42_SCHEME, 8 }, + OID_ANSI_MQV2[] = { OID_ANSI_X9_42_SCHEME, 7 }, + + OID_ANSI_DH_STATIC_SHA1[] = { OID_ANSI_X9_42_NAMED_SCHEME, 1 }, + OID_ANSI_DH_EPHEM_SHA1[] = { OID_ANSI_X9_42_NAMED_SCHEME, 2 }, + OID_ANSI_DH_ONE_FLOW_SHA1[] = { OID_ANSI_X9_42_NAMED_SCHEME, 3 }, + OID_ANSI_DH_HYBRID1_SHA1[] = { OID_ANSI_X9_42_NAMED_SCHEME, 4 }, + OID_ANSI_DH_HYBRID2_SHA1[] = { OID_ANSI_X9_42_NAMED_SCHEME, 5 }, + OID_ANSI_DH_HYBRID_ONEFLOW_SHA1[] = { OID_ANSI_X9_42_NAMED_SCHEME, 6 }, + /* sic - enumerated in reverse order in the spec */ + OID_ANSI_MQV1_SHA1[] = { OID_ANSI_X9_42_NAMED_SCHEME, 8 }, + OID_ANSI_MQV2_SHA1[] = { OID_ANSI_X9_42_NAMED_SCHEME, 7 }; + +const SecAsn1Oid + CSSMOID_MD2 = {OID_RSA_HASH_LENGTH+1, (uint8_t *)OID_MD2}, + CSSMOID_MD4 = {OID_RSA_HASH_LENGTH+1, (uint8_t *)OID_MD4}, + CSSMOID_MD5 = {OID_RSA_HASH_LENGTH+1, (uint8_t *)OID_MD5}, + CSSMOID_RSA = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_RSAEncryption}, + CSSMOID_MD2WithRSA = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_MD2WithRSA}, + CSSMOID_MD4WithRSA = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_MD4WithRSA}, + CSSMOID_MD5WithRSA = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_MD5WithRSA}, + CSSMOID_SHA1WithRSA = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_SHA1WithRSA}, + CSSMOID_RSAWithOAEP = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_RSAWithOAEP}, + CSSMOID_OAEP_MGF1 = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_OAEP_MGF1}, + CSSMOID_OAEP_ID_PSPECIFIED = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_OAEP_ID_PSPECIFIED}, + CSSMOID_SHA224WithRSA = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_SHA224WithRSA}, + CSSMOID_SHA256WithRSA = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_SHA256WithRSA}, + CSSMOID_SHA384WithRSA = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_SHA384WithRSA}, + CSSMOID_SHA512WithRSA = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_SHA512WithRSA}, + CSSMOID_PKCS3 = {OID_PKCS_3_LENGTH, (uint8_t *)OID_PKCS_3_ARC}, + CSSMOID_DH = {OID_PKCS_3_LENGTH+1, (uint8_t *)OID_DHKeyAgreement}, + CSSMOID_DSA = {OID_OIW_ALGORITHM_LENGTH+1, (uint8_t *)OID_OIW_DSA}, + CSSMOID_DSA_CMS = { 7, (uint8_t *)OID_CMS_DSA}, + CSSMOID_DSA_JDK = { 5, (uint8_t *)OID_JDK_DSA}, + CSSMOID_SHA1WithDSA = {OID_OIW_ALGORITHM_LENGTH+1, (uint8_t *)OID_OIW_DSAWithSHA1}, + CSSMOID_SHA1WithDSA_CMS = { 7, (uint8_t *)OID_CMS_DSAWithSHA1}, + CSSMOID_SHA1WithDSA_JDK = { 5, (uint8_t *)OID_JDK_DSAWithSHA1}, + CSSMOID_SHA1 = {OID_OIW_ALGORITHM_LENGTH+1, (uint8_t *)OID_OIW_SHA1}, + CSSMOID_SHA224 = {OID_NIST_HASHALG_LENGTH+1, (uint8_t *)OID_SHA224}, + CSSMOID_SHA256 = {OID_NIST_HASHALG_LENGTH+1, (uint8_t *)OID_SHA256}, + CSSMOID_SHA384 = {OID_NIST_HASHALG_LENGTH+1, (uint8_t *)OID_SHA384}, + CSSMOID_SHA512 = {OID_NIST_HASHALG_LENGTH+1, (uint8_t *)OID_SHA512}, + CSSMOID_SHA1WithRSA_OIW = {OID_OIW_ALGORITHM_LENGTH+1, (uint8_t *)OID_OIW_RSAWithSHA1}, + CSSMOID_DES_CBC = {OID_OIW_ALGORITHM_LENGTH+1, (uint8_t *)OID_OIW_DES_CBC}, + CSSMOID_ANSI_DH_PUB_NUMBER = {OID_ANSI_X9_42_LEN + 1, (uint8_t *)OID_ANSI_DH_PUB_NUMBER}, + CSSMOID_ANSI_DH_STATIC = {OID_ANSI_X9_42_SCHEME_LEN + 1, (uint8_t *)OID_ANSI_DH_STATIC}, + CSSMOID_ANSI_DH_ONE_FLOW = {OID_ANSI_X9_42_SCHEME_LEN + 1, (uint8_t *)OID_ANSI_DH_ONE_FLOW}, + CSSMOID_ANSI_DH_EPHEM = {OID_ANSI_X9_42_SCHEME_LEN + 1, (uint8_t *)OID_ANSI_DH_EPHEM}, + CSSMOID_ANSI_DH_HYBRID1 = {OID_ANSI_X9_42_SCHEME_LEN + 1, (uint8_t *)OID_ANSI_DH_HYBRID1}, + CSSMOID_ANSI_DH_HYBRID2 = {OID_ANSI_X9_42_SCHEME_LEN + 1, (uint8_t *)OID_ANSI_DH_HYBRID2}, + CSSMOID_ANSI_DH_HYBRID_ONEFLOW = {OID_ANSI_X9_42_SCHEME_LEN + 1, + (uint8_t *)OID_ANSI_DH_HYBRID_ONEFLOW}, + CSSMOID_ANSI_MQV1 = {OID_ANSI_X9_42_SCHEME_LEN + 1, (uint8_t *)OID_ANSI_MQV1}, + CSSMOID_ANSI_MQV2 = {OID_ANSI_X9_42_SCHEME_LEN + 1, (uint8_t *)OID_ANSI_MQV2}, + CSSMOID_ANSI_DH_STATIC_SHA1 = {OID_ANSI_X9_42_NAMED_SCHEME_LEN + 1, + (uint8_t *)OID_ANSI_DH_STATIC_SHA1}, + CSSMOID_ANSI_DH_ONE_FLOW_SHA1 = {OID_ANSI_X9_42_NAMED_SCHEME_LEN + 1, + (uint8_t *)OID_ANSI_DH_ONE_FLOW_SHA1}, + CSSMOID_ANSI_DH_EPHEM_SHA1 = {OID_ANSI_X9_42_NAMED_SCHEME_LEN + 1, + (uint8_t *)OID_ANSI_DH_EPHEM_SHA1}, + CSSMOID_ANSI_DH_HYBRID1_SHA1 = {OID_ANSI_X9_42_NAMED_SCHEME_LEN + 1, + (uint8_t *)OID_ANSI_DH_HYBRID1_SHA1}, + CSSMOID_ANSI_DH_HYBRID2_SHA1 = {OID_ANSI_X9_42_NAMED_SCHEME_LEN + 1, + (uint8_t *)OID_ANSI_DH_HYBRID2_SHA1}, + CSSMOID_ANSI_DH_HYBRID_ONEFLOW_SHA1 = {OID_ANSI_X9_42_NAMED_SCHEME_LEN + 1, + (uint8_t *)OID_ANSI_DH_HYBRID_ONEFLOW_SHA1}, + CSSMOID_ANSI_MQV1_SHA1 = {OID_ANSI_X9_42_NAMED_SCHEME_LEN + 1, + (uint8_t *)OID_ANSI_MQV1_SHA1}, + CSSMOID_ANSI_MQV2_SHA1 = {OID_ANSI_X9_42_NAMED_SCHEME_LEN + 1, + (uint8_t *)OID_ANSI_MQV2_SHA1}; + + +/* iSignTP OBJECT IDENTIFIER ::= + * { appleTrustPolicy 1 } + * { 1 2 840 113635 100 1 1 } + * + * BER = 06 09 2A 86 48 86 F7 63 64 01 01 + */ +static const uint8_t +APPLE_TP_ISIGN[] = {APPLE_TP_OID, 1}, + +/* AppleX509Basic OBJECT IDENTIFIER ::= + * { appleTrustPolicy 2 } + * { 1 2 840 113635 100 1 2 } + * + * BER = 06 09 2A 86 48 86 F7 63 64 01 01 + */ +APPLE_TP_X509_BASIC[] = {APPLE_TP_OID, 2}, + +/* AppleSSLPolicy := {appleTrustPolicy 3 } */ +APPLE_TP_SSL[] = {APPLE_TP_OID, 3}, + +/* AppleLocalCertGenPolicy := {appleTrustPolicy 4 } */ +APPLE_TP_LOCAL_CERT_GEN[] = {APPLE_TP_OID, 4}, + +/* AppleCSRGenPolicy := {appleTrustPolicy 5 } */ +APPLE_TP_CSR_GEN[] = {APPLE_TP_OID, 5}, + +/* Apple CRL-based revocation policy := {appleTrustPolicy 6 } */ +APPLE_TP_REVOCATION_CRL[] = {APPLE_TP_OID, 6}, + +/* Apple OCSP-based revocation policy := {appleTrustPolicy 7 } */ +APPLE_TP_REVOCATION_OCSP[] = {APPLE_TP_OID, 7}, + +/* Apple S/MIME trust policy := {appleTrustPolicy 8 } */ +APPLE_TP_SMIME[] = {APPLE_TP_OID, 8}, + +/* Apple EAP trust policy := {appleTrustPolicy 9 } */ +APPLE_TP_EAP[] = {APPLE_TP_OID, 9}, + +/* + * NOTE: "Apple Code Signing Policy", CSSMOID_APPLE_TP_CODE_SIGN, was renamed + * to "Apple Software Update Signing Policy", CSSMOID_APPLE_TP_SW_UPDATE_SIGNING, + * on 8/16/06. For compatibility, we keep the TP_CODE_SIGN OID here until + * SoftwareUpdate converts to the new symbol. + * + * Apple Code Signing Policy := { appleTrustPolicy 10 } + * Apple Software Update Signing Policy := { appleTrustPolicy 10 } + */ +APPLE_SW_UPDATE_SIGNING[] = {APPLE_TP_OID, 10}, +#define APPLE_TP_CODE_SIGN APPLE_SW_UPDATE_SIGNING + +/* Apple IPSec Policy := { appleTrustPolicy 11 } */ +APPLE_TP_IP_SEC[] = {APPLE_TP_OID, 11}, + +/* Apple iChat Policy := { appleTrustPolicy 12 } */ +APPLE_TP_ICHAT[] = {APPLE_TP_OID, 12}, + +/* Apple Resource Signing Policy := { appleTrustPolicy 13 } */ +APPLE_TP_RESOURCE_SIGN[] = {APPLE_TP_OID, 13}, + +/* Apple PKINIT Client Cert Policy := { appleTrustPolicy 14 } */ +APPLE_TP_PKINIT_CLIENT[] = {APPLE_TP_OID, 14}, + +/* Apple PKINIT Server Cert Policy := { appleTrustPolicy 15 } */ +APPLE_TP_PKINIT_SERVER[] = {APPLE_TP_OID, 15}, + +/* Apple Code Signing Cert Policy := { appleTrustPolicy 16 } */ +APPLE_TP_CODE_SIGNING[] = {APPLE_TP_OID, 16}, + +/* Apple Package Signing Cert Policy := { appleTrustPolicy 17 } */ +APPLE_TP_PACKAGE_SIGNING[] = {APPLE_TP_OID, 17}, + +/* AppleID Sharing Cert Policy := { appleTrustPolicy 18 } */ +APPLE_TP_APPLEID_SHARING[] = {APPLE_TP_OID, 18}, +/* appleIDValidationPolicy */ + +/* Apple MacAppStore receipt verification policy := { appleTrustPolicy 19 } */ +APPLE_TP_MACAPPSTORE_RECEIPT[] = {APPLE_TP_OID, 19}, + +/* Apple Time Stamping Server Cert Policy := { appleTrustPolicy 20 } */ +APPLE_TP_TIMESTAMPING[] = {APPLE_TP_OID, 20}, + +/* Apple Revocation Policy := { appleTrustPolicy 21 } */ +APPLE_TP_REVOCATION[] = {APPLE_TP_OID, 21}, + +/* Apple Passbook Signing Policy := { appleTrustPolicy 22 } */ +APPLE_TP_PASSBOOK_SIGNING[] = {APPLE_TP_OID, 22}, + +/* Apple Mobile Store Policy := { appleTrustPolicy 23 } */ +APPLE_TP_MOBILE_STORE[] = {APPLE_TP_OID, 23}, + +/* Apple Escrow Service Policy := { appleTrustPolicy 24 } */ +APPLE_TP_ESCROW_SERVICE[] = {APPLE_TP_OID, 24}, + +/* Apple Configuration Profile Signing Policy := { appleTrustPolicy 25 } */ +APPLE_TP_PROFILE_SIGNING[] = {APPLE_TP_OID, 25}, + +/* Apple QA Configuration Profile Signing Policy := { appleTrustPolicy 26 } */ +APPLE_TP_QA_PROFILE_SIGNING[] = {APPLE_TP_OID, 26}, + +/* Apple Test Mobile Store Policy := { appleTrustPolicy 27 } */ +APPLE_TP_TEST_MOBILE_STORE[] = {APPLE_TP_OID, 27}, + +/* Apple PCS Escrow Service Policy := { appleTrustPolicy 34 } */ +APPLE_TP_PCS_ESCROW_SERVICE[] = {APPLE_TP_OID, 34}, + +/* + * fee OBJECT IDENTIFIER ::= + * { appleSecurityAlgorithm 1 } + * { 1 2 840 113635 100 2 1 } + * + * BER = 06 09 2A 86 48 86 F7 63 64 02 01 + */ +APPLE_FEE[] = {APPLE_ALG_OID, 1}, + +/* + * asc OBJECT IDENTIFIER ::= + * { appleSecurityAlgorithm 2 } + * { 1 2 840 113635 100 2 2 } + * + * BER = 06 09 2A 86 48 86 F7 63 64 02 02 + */ +APPLE_ASC[] = {APPLE_ALG_OID, 2}, + +/* + * fee_MD5 OBJECT IDENTIFIER ::= + * { appleSecurityAlgorithm 3 } + * { 1 2 840 113635 100 2 3 } + * + * BER = 06 09 2A 86 48 86 F7 63 64 02 03 + */ +APPLE_FEE_MD5[] = {APPLE_ALG_OID, 3}, + +/* + * fee_SHA1 OBJECT IDENTIFIER ::= + * { appleSecurityAlgorithm 4 } + * { 1 2 840 113635 100 2 4 } + * + * BER = 06 09 2A 86 48 86 F7 63 64 02 04 + */ +APPLE_FEE_SHA1[] = {APPLE_ALG_OID, 4}, + +/* + * feed OBJECT IDENTIFIER ::= + * { appleSecurityAlgorithm 5 } + * { 1 2 840 113635 100 2 5 } + * + * BER = 06 09 2A 86 48 86 F7 63 64 02 05 + */ +APPLE_FEED[] = {APPLE_ALG_OID, 5}, + +/* + * feedExp OBJECT IDENTIFIER ::= + * { appleSecurityAlgorithm 6 } + * { 1 2 840 113635 100 2 6 } + * + * BER = 06 09 2A 86 48 86 F7 63 64 02 06 + */ +APPLE_FEEDEXP[] = {APPLE_ALG_OID, 6}, + +/* + * AppleECDSA OBJECT IDENTIFIER ::= + * { appleSecurityAlgorithm 7 } + * { 1 2 840 113635 100 2 7 } + * + * BER = 06 09 2A 86 48 86 F7 63 64 02 07 + */ +APPLE_ECDSA[] = {APPLE_ALG_OID, 7}, + +/* .mac cert OIDs */ +OID_DOTMAC_CERT[] = { APPLE_DOTMAC_CERT_OID }, +OID_DOTMAC_CERT_REQ[] = { APPLE_DOTMAC_CERT_REQ_OID }, +OID_DOTMAC_CERT_REQ_IDENTITY[] = { APPLE_DOTMAC_CERT_REQ_OID, 1 }, /* deprecated */ +OID_DOTMAC_CERT_REQ_EMAIL_SIGN[] = { APPLE_DOTMAC_CERT_REQ_OID, 2 }, /* deprecated */ +OID_DOTMAC_CERT_REQ_EMAIL_ENCRYPT[] = { APPLE_DOTMAC_CERT_REQ_OID, 3 }, /* deprecated */ +OID_DOTMAC_CERT_REQ_ARCHIVE_LIST[] = { APPLE_DOTMAC_CERT_REQ_OID, 4 }, +OID_DOTMAC_CERT_REQ_ARCHIVE_STORE[] = { APPLE_DOTMAC_CERT_REQ_OID, 5 }, +OID_DOTMAC_CERT_REQ_ARCHIVE_FETCH[] = { APPLE_DOTMAC_CERT_REQ_OID, 6 }, +OID_DOTMAC_CERT_REQ_ARCHIVE_REMOVE[] = { APPLE_DOTMAC_CERT_REQ_OID, 7 }, +OID_DOTMAC_CERT_REQ_SHARED_SERVICES[] = { APPLE_DOTMAC_CERT_REQ_OID, 8 }, /* treadstone - Shared Services */ + +/* OIDs for specifying OID/values pairs in a cert request */ +OID_DOTMAC_CERT_REQ_VALUE_USERNAME[] = { APPLE_DOTMAC_CERT_REQ_VALUE_OID, 1 }, +OID_DOTMAC_CERT_REQ_VALUE_PASSWORD[] = { APPLE_DOTMAC_CERT_REQ_VALUE_OID, 2 }, +OID_DOTMAC_CERT_REQ_VALUE_HOSTNAME[] = { APPLE_DOTMAC_CERT_REQ_VALUE_OID, 3 }, +OID_DOTMAC_CERT_REQ_VALUE_RENEW[] = { APPLE_DOTMAC_CERT_REQ_VALUE_OID, 4 }, +OID_DOTMAC_CERT_REQ_VALUE_ASYNC[] = { APPLE_DOTMAC_CERT_REQ_VALUE_OID, 5 }, +OID_DOTMAC_CERT_REQ_VALUE_IS_PENDING[] = { APPLE_DOTMAC_CERT_REQ_VALUE_OID, 6 }, +__unused OID_DOTMAC_CERT_REQ_VALUE_TYPE_ICHAT[] = { APPLE_DOTMAC_CERT_REQ_VALUE_OID, 7 }, +__unused OID_DOTMAC_CERT_REQ_VALUE_TYPE_SHARED_SERVICE[] = { APPLE_DOTMAC_CERT_REQ_VALUE_OID, 8 }, +__unused OID_DOTMAC_CERT_REQ_VALUE_TYPE_EMAIL_ENCRYPT[] = { APPLE_DOTMAC_CERT_REQ_VALUE_OID, 9 }, +__unused OID_DOTMAC_CERT_REQ_VALUE_TYPE_EMAIL_SIGN[] = { APPLE_DOTMAC_CERT_REQ_VALUE_OID, 10 } +; + +const SecAsn1Oid + +CSSMOID_APPLE_ISIGN = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_ISIGN}, +CSSMOID_APPLE_X509_BASIC = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_X509_BASIC}, +CSSMOID_APPLE_TP_SSL = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_SSL}, +CSSMOID_APPLE_TP_LOCAL_CERT_GEN = + {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_LOCAL_CERT_GEN}, +CSSMOID_APPLE_TP_CSR_GEN = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_CSR_GEN}, +CSSMOID_APPLE_TP_REVOCATION_CRL = + {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_REVOCATION_CRL}, +CSSMOID_APPLE_TP_REVOCATION_OCSP = + {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_REVOCATION_OCSP}, +CSSMOID_APPLE_TP_SMIME = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_SMIME}, +CSSMOID_APPLE_TP_EAP = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_EAP}, +/* CSSMOID_APPLE_TP_CODE_SIGN here for temporary compatibility */ +CSSMOID_APPLE_TP_CODE_SIGN = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_CODE_SIGN}, +CSSMOID_APPLE_TP_SW_UPDATE_SIGNING = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_SW_UPDATE_SIGNING}, +CSSMOID_APPLE_TP_IP_SEC = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_IP_SEC}, +CSSMOID_APPLE_TP_ICHAT = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_ICHAT}, +CSSMOID_APPLE_TP_RESOURCE_SIGN = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_RESOURCE_SIGN}, +CSSMOID_APPLE_TP_PKINIT_CLIENT = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_PKINIT_CLIENT}, +CSSMOID_APPLE_TP_PKINIT_SERVER = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_PKINIT_SERVER}, +CSSMOID_APPLE_TP_CODE_SIGNING = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_CODE_SIGNING}, +CSSMOID_APPLE_TP_PACKAGE_SIGNING = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_PACKAGE_SIGNING}, +CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_MACAPPSTORE_RECEIPT}, +CSSMOID_APPLE_TP_APPLEID_SHARING = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_APPLEID_SHARING}, +CSSMOID_APPLE_TP_TIMESTAMPING = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_TIMESTAMPING}, +CSSMOID_APPLE_TP_REVOCATION = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_REVOCATION}, +CSSMOID_APPLE_TP_PASSBOOK_SIGNING = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_PASSBOOK_SIGNING}, +CSSMOID_APPLE_TP_MOBILE_STORE = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_MOBILE_STORE}, +CSSMOID_APPLE_TP_ESCROW_SERVICE = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_ESCROW_SERVICE}, +CSSMOID_APPLE_TP_PROFILE_SIGNING = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_PROFILE_SIGNING}, +CSSMOID_APPLE_TP_QA_PROFILE_SIGNING = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_QA_PROFILE_SIGNING}, +CSSMOID_APPLE_TP_TEST_MOBILE_STORE = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_TEST_MOBILE_STORE}, +CSSMOID_APPLE_TP_PCS_ESCROW_SERVICE = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_PCS_ESCROW_SERVICE}, +CSSMOID_APPLE_FEE = {APPLE_ALG_OID_LENGTH+1, (uint8_t *)APPLE_FEE}, +CSSMOID_APPLE_ASC = {APPLE_ALG_OID_LENGTH+1, (uint8_t *)APPLE_ASC}, +CSSMOID_APPLE_FEE_MD5 = {APPLE_ALG_OID_LENGTH+1, (uint8_t *)APPLE_FEE_MD5}, +CSSMOID_APPLE_FEE_SHA1 = {APPLE_ALG_OID_LENGTH+1, (uint8_t *)APPLE_FEE_SHA1}, +CSSMOID_APPLE_FEED = {APPLE_ALG_OID_LENGTH+1, (uint8_t *)APPLE_FEED}, +CSSMOID_APPLE_FEEDEXP = {APPLE_ALG_OID_LENGTH+1, (uint8_t *)APPLE_FEEDEXP}, +CSSMOID_APPLE_ECDSA = {APPLE_ALG_OID_LENGTH+1, (uint8_t *)APPLE_ECDSA}, +/* .mac cert OIDs */ +CSSMOID_DOTMAC_CERT = { APPLE_DOTMAC_CERT_OID_LENGTH, + (uint8_t *)OID_DOTMAC_CERT }, +CSSMOID_DOTMAC_CERT_REQ = { APPLE_DOTMAC_CERT_REQ_OID_LENGTH, + (uint8_t *)OID_DOTMAC_CERT_REQ }, +/* This actually used to be for requesting an encrypted iChat cert; deprecated in Leopard */ +CSSMOID_DOTMAC_CERT_REQ_IDENTITY = { APPLE_DOTMAC_CERT_REQ_OID_LENGTH + 1, + (uint8_t *)OID_DOTMAC_CERT_REQ_IDENTITY}, +CSSMOID_DOTMAC_CERT_REQ_EMAIL_SIGN = { APPLE_DOTMAC_CERT_REQ_OID_LENGTH + 1, + (uint8_t *)OID_DOTMAC_CERT_REQ_EMAIL_SIGN}, +CSSMOID_DOTMAC_CERT_REQ_EMAIL_ENCRYPT = { APPLE_DOTMAC_CERT_REQ_OID_LENGTH + 1, + (uint8_t *)OID_DOTMAC_CERT_REQ_EMAIL_ENCRYPT}, +CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_LIST = { APPLE_DOTMAC_CERT_REQ_OID_LENGTH + 1, + (uint8_t *)OID_DOTMAC_CERT_REQ_ARCHIVE_LIST}, +CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_STORE = { APPLE_DOTMAC_CERT_REQ_OID_LENGTH + 1, + (uint8_t *)OID_DOTMAC_CERT_REQ_ARCHIVE_STORE}, +CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_FETCH = { APPLE_DOTMAC_CERT_REQ_OID_LENGTH + 1, + (uint8_t *)OID_DOTMAC_CERT_REQ_ARCHIVE_FETCH}, +CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_REMOVE = { APPLE_DOTMAC_CERT_REQ_OID_LENGTH + 1, + (uint8_t *)OID_DOTMAC_CERT_REQ_ARCHIVE_REMOVE}, +CSSMOID_DOTMAC_CERT_REQ_SHARED_SERVICES = { APPLE_DOTMAC_CERT_REQ_OID_LENGTH + 1, + (uint8_t *)OID_DOTMAC_CERT_REQ_SHARED_SERVICES}, +CSSMOID_DOTMAC_CERT_REQ_VALUE_USERNAME = { APPLE_DOTMAC_CERT_REQ_VALUE_OID_LENGTH + 1, + (uint8_t *)OID_DOTMAC_CERT_REQ_VALUE_USERNAME}, +CSSMOID_DOTMAC_CERT_REQ_VALUE_PASSWORD = { APPLE_DOTMAC_CERT_REQ_VALUE_OID_LENGTH + 1, + (uint8_t *)OID_DOTMAC_CERT_REQ_VALUE_PASSWORD}, +CSSMOID_DOTMAC_CERT_REQ_VALUE_HOSTNAME = { APPLE_DOTMAC_CERT_REQ_VALUE_OID_LENGTH + 1, + (uint8_t *)OID_DOTMAC_CERT_REQ_VALUE_HOSTNAME}, +CSSMOID_DOTMAC_CERT_REQ_VALUE_RENEW = { APPLE_DOTMAC_CERT_REQ_VALUE_OID_LENGTH + 1, + (uint8_t *)OID_DOTMAC_CERT_REQ_VALUE_RENEW}, +CSSMOID_DOTMAC_CERT_REQ_VALUE_ASYNC = { APPLE_DOTMAC_CERT_REQ_VALUE_OID_LENGTH + 1, + (uint8_t *)OID_DOTMAC_CERT_REQ_VALUE_ASYNC}, +CSSMOID_DOTMAC_CERT_REQ_VALUE_IS_PENDING = { APPLE_DOTMAC_CERT_REQ_VALUE_OID_LENGTH + 1, + (uint8_t *)OID_DOTMAC_CERT_REQ_VALUE_IS_PENDING} +; + +/* PKCS5 algorithms */ + +static const uint8_t + OID_PKCS5_DIGEST_ALG[] = { OID_RSA_HASH }, + OID_PKCS5_ENCRYPT_ALG[] = { OID_RSA_ENCRYPT }, + OID_PKCS5_HMAC_SHA1[] = { OID_RSA_HASH, 7 }, + OID_PKCS5_pbeWithMD2AndDES[] = { OID_PKCS_5, 1 }, + OID_PKCS5_pbeWithMD5AndDES[] = { OID_PKCS_5, 3 }, + OID_PKCS5_pbeWithMD2AndRC2[] = { OID_PKCS_5, 4 }, + OID_PKCS5_pbeWithMD5AndRC2[] = { OID_PKCS_5, 6 }, + OID_PKCS5_pbeWithSHA1AndDES[] = { OID_PKCS_5, 10 }, + OID_PKCS5_pbeWithSHA1AndRC2[] = { OID_PKCS_5, 11 }, + OID_PKCS5_PBKDF2[] = { OID_PKCS_5, 12 }, + OID_PKCS5_PBES2[] = { OID_PKCS_5, 13 }, + OID_PKCS5_PBMAC1[] = { OID_PKCS_5, 14 }, + OID_PKCS5_RC2_CBC[] = { OID_RSA_ENCRYPT, 2 }, + OID_PKCS5_DES_EDE3_CBC[] = { OID_RSA_ENCRYPT, 7 }, + OID_PKCS5_RC5_CBC[] = { OID_RSA_ENCRYPT, 9 }; + +const SecAsn1Oid + CSSMOID_PKCS5_DIGEST_ALG = { OID_RSA_HASH_LENGTH, (uint8_t *)OID_PKCS5_DIGEST_ALG }, + CSSMOID_PKCS5_ENCRYPT_ALG = { OID_RSA_ENCRYPT_LENGTH, (uint8_t *)OID_PKCS5_ENCRYPT_ALG }, + CSSMOID_PKCS5_HMAC_SHA1 = { OID_RSA_HASH_LENGTH+1, (uint8_t *)OID_PKCS5_HMAC_SHA1 }, + CSSMOID_PKCS5_pbeWithMD2AndDES = { OID_PKCS_5_LENGTH+1, (uint8_t *)OID_PKCS5_pbeWithMD2AndDES }, + CSSMOID_PKCS5_pbeWithMD5AndDES = { OID_PKCS_5_LENGTH+1, (uint8_t *)OID_PKCS5_pbeWithMD5AndDES }, + CSSMOID_PKCS5_pbeWithMD2AndRC2 = { OID_PKCS_5_LENGTH+1, (uint8_t *)OID_PKCS5_pbeWithMD2AndRC2 }, + CSSMOID_PKCS5_pbeWithMD5AndRC2 = { OID_PKCS_5_LENGTH+1, (uint8_t *)OID_PKCS5_pbeWithMD5AndRC2 }, + CSSMOID_PKCS5_pbeWithSHA1AndDES = { OID_PKCS_5_LENGTH+1, (uint8_t *)OID_PKCS5_pbeWithSHA1AndDES }, + CSSMOID_PKCS5_pbeWithSHA1AndRC2 = { OID_PKCS_5_LENGTH+1, (uint8_t *)OID_PKCS5_pbeWithSHA1AndRC2 }, + CSSMOID_PKCS5_PBKDF2 = { OID_PKCS_5_LENGTH+1, (uint8_t *)OID_PKCS5_PBKDF2 }, + CSSMOID_PKCS5_PBES2 = { OID_PKCS_5_LENGTH+1, (uint8_t *)OID_PKCS5_PBES2 }, + CSSMOID_PKCS5_PBMAC1 = { OID_PKCS_5_LENGTH+1, (uint8_t *)OID_PKCS5_PBMAC1 }, + CSSMOID_PKCS5_RC2_CBC = { OID_RSA_ENCRYPT_LENGTH+1, (uint8_t *)OID_PKCS5_RC2_CBC }, + CSSMOID_PKCS5_DES_EDE3_CBC = { OID_RSA_ENCRYPT_LENGTH+1, (uint8_t *)OID_PKCS5_DES_EDE3_CBC }, + CSSMOID_PKCS5_RC5_CBC = { OID_RSA_ENCRYPT_LENGTH+1, (uint8_t *)OID_PKCS5_RC5_CBC }; + +/* PKCS12 algorithms */ +#define OID_PKCS12_PbeIds OID_PKCS_12,1 +#define OID_PKCS12_PbeIds_Length OID_PKCS_12_LENGTH+1 + +static const uint8_t + OID_PKCS12_pbeWithSHAAnd128BitRC4[] = { OID_PKCS12_PbeIds, 1 }, + OID_PKCS12_pbeWithSHAAnd40BitRC4[] = { OID_PKCS12_PbeIds, 2 }, + OID_PKCS12_pbeWithSHAAnd3Key3DESCBC[] = { OID_PKCS12_PbeIds, 3 }, + OID_PKCS12_pbeWithSHAAnd2Key3DESCBC[] = { OID_PKCS12_PbeIds, 4 }, + OID_PKCS12_pbeWithSHAAnd128BitRC2CBC[] ={ OID_PKCS12_PbeIds, 5 }, + OID_PKCS12_pbewithSHAAnd40BitRC2CBC[] = { OID_PKCS12_PbeIds, 6 }; + + +const SecAsn1Oid +CSSMOID_PKCS12_pbeWithSHAAnd128BitRC4 = {OID_PKCS12_PbeIds_Length + 1, + (uint8_t *)OID_PKCS12_pbeWithSHAAnd128BitRC4 }, +CSSMOID_PKCS12_pbeWithSHAAnd40BitRC4 = {OID_PKCS12_PbeIds_Length + 1, + (uint8_t *)OID_PKCS12_pbeWithSHAAnd40BitRC4 }, +CSSMOID_PKCS12_pbeWithSHAAnd3Key3DESCBC = {OID_PKCS12_PbeIds_Length + 1, + (uint8_t *)OID_PKCS12_pbeWithSHAAnd3Key3DESCBC }, +CSSMOID_PKCS12_pbeWithSHAAnd2Key3DESCBC = {OID_PKCS12_PbeIds_Length + 1, + (uint8_t *)OID_PKCS12_pbeWithSHAAnd2Key3DESCBC }, +CSSMOID_PKCS12_pbeWithSHAAnd128BitRC2CBC = {OID_PKCS12_PbeIds_Length + 1, + (uint8_t *)OID_PKCS12_pbeWithSHAAnd128BitRC2CBC }, +CSSMOID_PKCS12_pbewithSHAAnd40BitRC2CBC = {OID_PKCS12_PbeIds_Length + 1, + (uint8_t *)OID_PKCS12_pbewithSHAAnd40BitRC2CBC }; + +/* ANSI X9.62 and Certicom elliptic curve algorithms */ +static const uint8_t + OID_ecPublicKey[] = { OID_ANSI_X9_62_PUBKEY_TYPE, 1 }, + OID_ECDSA_WithSHA1[] = { OID_ANSI_X9_62_SIG_TYPE, 1 }, + OID_ECDSA_WithSHA224[] = { OID_ANSI_X9_62_SIG_TYPE, 3, 1 }, + OID_ECDSA_WithSHA256[] = { OID_ANSI_X9_62_SIG_TYPE, 3, 2 }, + OID_ECDSA_WithSHA384[] = { OID_ANSI_X9_62_SIG_TYPE, 3, 3 }, + OID_ECDSA_WithSHA512[] = { OID_ANSI_X9_62_SIG_TYPE, 3, 4 }, + OID_ECDSA_WithSpecified[] = { OID_ANSI_X9_62_SIG_TYPE, 3 }; + +const SecAsn1Oid +CSSMOID_ecPublicKey = {OID_ANSI_X9_62_LEN+2, (uint8_t *)OID_ecPublicKey}, +CSSMOID_ECDSA_WithSHA1 = {OID_ANSI_X9_62_SIG_TYPE_LEN+1, (uint8_t *)OID_ECDSA_WithSHA1 }, +CSSMOID_ECDSA_WithSHA224 = {OID_ANSI_X9_62_SIG_TYPE_LEN+2, (uint8_t *)OID_ECDSA_WithSHA224 }, +CSSMOID_ECDSA_WithSHA256 = {OID_ANSI_X9_62_SIG_TYPE_LEN+2, (uint8_t *)OID_ECDSA_WithSHA256 }, +CSSMOID_ECDSA_WithSHA384 = {OID_ANSI_X9_62_SIG_TYPE_LEN+2, (uint8_t *)OID_ECDSA_WithSHA384 }, +CSSMOID_ECDSA_WithSHA512 = {OID_ANSI_X9_62_SIG_TYPE_LEN+2, (uint8_t *)OID_ECDSA_WithSHA512 }, +CSSMOID_ECDSA_WithSpecified = {OID_ANSI_X9_62_SIG_TYPE_LEN+1, (uint8_t *)OID_ECDSA_WithSpecified }; diff --git a/libsecurity_asn1/lib/oidsalg.h b/Security/libsecurity_asn1/lib/oidsalg.h similarity index 98% rename from libsecurity_asn1/lib/oidsalg.h rename to Security/libsecurity_asn1/lib/oidsalg.h index b1c1df20..301b7002 100644 --- a/libsecurity_asn1/lib/oidsalg.h +++ b/Security/libsecurity_asn1/lib/oidsalg.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2004,2008-2013 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2004,2008-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ * * oidsalg.h -- OIDs defining crypto algorithms @@ -114,6 +114,7 @@ extern const SecAsn1Oid CSSMOID_APPLE_TP_PROFILE_SIGNING DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, CSSMOID_APPLE_TP_QA_PROFILE_SIGNING DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, CSSMOID_APPLE_TP_TEST_MOBILE_STORE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_TP_PCS_ESCROW_SERVICE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, CSSMOID_APPLE_FEE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, CSSMOID_APPLE_ASC DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, CSSMOID_APPLE_FEE_MD5 DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, diff --git a/libsecurity_asn1/lib/oidsattr.c b/Security/libsecurity_asn1/lib/oidsattr.c similarity index 98% rename from libsecurity_asn1/lib/oidsattr.c rename to Security/libsecurity_asn1/lib/oidsattr.c index 83127a75..be1625d6 100644 --- a/libsecurity_asn1/lib/oidsattr.c +++ b/Security/libsecurity_asn1/lib/oidsattr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2008,2010,2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -229,10 +229,10 @@ static const uint8_t /* ETSI */ static const uint8_t - OID_ETSI_QCS_QC_COMPLICANCE[] = { OID_ETSI_QCS, 1 }, - OID_ETSI_QCS_QC_LIMIT_VALUE[] = { OID_ETSI_QCS, 2 }, - OID_ETSI_QCS_QC_RETENTION[] = { OID_ETSI_QCS, 3 }, - OID_ETSI_QCS_QC_SSCD[] = { OID_ETSI_QCS, 4 } + OID_ETSI_QCS_QC_COMPLICANCE[] = { OID_ETSI_QCS, 1 }, + OID_ETSI_QCS_QC_LIMIT_VALUE[] = { OID_ETSI_QCS, 2 }, + __unused OID_ETSI_QCS_QC_RETENTION[] = { OID_ETSI_QCS, 3 }, + __unused OID_ETSI_QCS_QC_SSCD[] = { OID_ETSI_QCS, 4 } ; const SecAsn1Oid diff --git a/libsecurity_asn1/lib/oidsattr.h b/Security/libsecurity_asn1/lib/oidsattr.h similarity index 99% rename from libsecurity_asn1/lib/oidsattr.h rename to Security/libsecurity_asn1/lib/oidsattr.h index 2a98b499..10ced8e8 100644 --- a/libsecurity_asn1/lib/oidsattr.h +++ b/Security/libsecurity_asn1/lib/oidsattr.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2001,2003-2004,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2003-2004,2008,2010,2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_asn1/lib/oidsbase.h b/Security/libsecurity_asn1/lib/oidsbase.h new file mode 100644 index 00000000..c866b250 --- /dev/null +++ b/Security/libsecurity_asn1/lib/oidsbase.h @@ -0,0 +1,356 @@ +/* + * Copyright (c) 1999-2001,2003-2004,2008-2010,2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * oidsbase.h -- Basic Object Identifier Macros and Data Types. + */ + +#include "SecAsn1Types.h" + +#ifndef _OIDSBASE_H_ +#define _OIDSBASE_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#define SECASN1OID_DEF(NAME, VALUE, ARGS...) \ +static const uint8_t _##NAME[] = { VALUE, ## ARGS }; \ +const SecAsn1Oid NAME = { sizeof(_##NAME), (uint8_t *)_##NAME } + +/* Intel CSSM */ + +#define INTEL 96, 134, 72, 1, 134, 248, 77 +#define INTEL_LENGTH 7 + +#define INTEL_CDSASECURITY INTEL, 2 +#define INTEL_CDSASECURITY_LENGTH (INTEL_LENGTH + 1) + +#define INTEL_SEC_FORMATS INTEL_CDSASECURITY, 1 +#define INTEL_SEC_FORMATS_LENGTH (INTEL_CDSASECURITY_LENGTH + 1) + +#define INTEL_SEC_ALGS INTEL_CDSASECURITY, 2, 5 +#define INTEL_SEC_ALGS_LENGTH (INTEL_CDSASECURITY_LENGTH + 2) + +#define INTEL_SEC_OBJECT_BUNDLE INTEL_SEC_FORMATS, 4 +#define INTEL_SEC_OBJECT_BUNDLE_LENGTH (INTEL_SEC_FORMATS_LENGTH + 1) + +#define INTEL_CERT_AND_PRIVATE_KEY_2_0 INTEL_SEC_OBJECT_BUNDLE, 1 +#define INTEL_CERT_AND_PRIVATE_KEY_2_0_LENGTH (INTEL_SEC_OBJECT_BUNDLE_LENGTH + 1) + +/* Suffix specifying format or representation of a field value */ +/* Note that if a format suffix is not specified, a flat data +representation is implied */ +#define INTEL_X509_C_DATATYPE 1 +#define INTEL_X509_LDAPSTRING_DATATYPE 2 + +#define OID_ISO_CCITT_DIR_SERVICE 85 +#define OID_DS OID_ISO_CCITT_DIR_SERVICE +#define OID_DS_LENGTH 1 +#define OID_ATTR_TYPE OID_DS, 4 +#define OID_ATTR_TYPE_LENGTH OID_DS_LENGTH + 1 +#define OID_EXTENSION OID_DS, 29 +#define OID_EXTENSION_LENGTH OID_DS_LENGTH + 1 +#define OID_ISO_STANDARD 40 +#define OID_ISO_MEMBER 42 +#define OID_US OID_ISO_MEMBER, 134, 72 + +#define OID_ISO_IDENTIFIED_ORG 43 +#define OID_OSINET OID_ISO_IDENTIFIED_ORG, 4 +#define OID_GOSIP OID_ISO_IDENTIFIED_ORG, 5 +#define OID_DOD OID_ISO_IDENTIFIED_ORG, 6 +#define OID_OIW OID_ISO_IDENTIFIED_ORG, 14 + +#define OID_ITU_RFCDATA_MEMBER_LENGTH 1 +#define OID_ITU_RFCDATA 9 + +/* From the PKCS Standards */ +#define OID_ISO_MEMBER_LENGTH 1 +#define OID_US_LENGTH OID_ISO_MEMBER_LENGTH + 2 +#define OID_RSA OID_US, 134, 247, 13 +#define OID_RSA_LENGTH OID_US_LENGTH + 3 +#define OID_RSA_HASH OID_RSA, 2 +#define OID_RSA_HASH_LENGTH OID_RSA_LENGTH + 1 +#define OID_RSA_ENCRYPT OID_RSA, 3 +#define OID_RSA_ENCRYPT_LENGTH OID_RSA_LENGTH + 1 +#define OID_PKCS OID_RSA, 1 +#define OID_PKCS_LENGTH OID_RSA_LENGTH +1 +#define OID_PKCS_1 OID_PKCS, 1 +#define OID_PKCS_1_LENGTH OID_PKCS_LENGTH +1 +#define OID_PKCS_2 OID_PKCS, 2 +#define OID_PKCS_3 OID_PKCS, 3 +#define OID_PKCS_3_LENGTH OID_PKCS_LENGTH +1 +#define OID_PKCS_4 OID_PKCS, 4 +#define OID_PKCS_5 OID_PKCS, 5 +#define OID_PKCS_5_LENGTH OID_PKCS_LENGTH +1 +#define OID_PKCS_6 OID_PKCS, 6 +#define OID_PKCS_7 OID_PKCS, 7 +#define OID_PKCS_7_LENGTH OID_PKCS_LENGTH +1 +#define OID_PKCS_8 OID_PKCS, 8 +#define OID_PKCS_9 OID_PKCS, 9 +#define OID_PKCS_9_LENGTH OID_PKCS_LENGTH +1 +#define OID_PKCS_10 OID_PKCS, 10 +#define OID_PKCS_11 OID_PKCS, 11 +#define OID_PKCS_11_LENGTH OID_PKCS_LENGTH +1 +#define OID_PKCS_12 OID_PKCS, 12 +#define OID_PKCS_12_LENGTH OID_PKCS_LENGTH +1 + +/* ANSI X9.42 */ +#define OID_ANSI_X9_42 OID_US, 206, 62, 2 +#define OID_ANSI_X9_42_LEN OID_US_LENGTH + 3 +#define OID_ANSI_X9_42_SCHEME OID_ANSI_X9_42, 3 +#define OID_ANSI_X9_42_SCHEME_LEN OID_ANSI_X9_42_LEN + 1 +#define OID_ANSI_X9_42_NAMED_SCHEME OID_ANSI_X9_42, 4 +#define OID_ANSI_X9_42_NAMED_SCHEME_LEN OID_ANSI_X9_42_LEN + 1 + +/* ANSI X9.62 (1 2 840 10045) */ +#define OID_ANSI_X9_62 0x2A, 0x86, 0x48, 0xCE, 0x3D +#define OID_ANSI_X9_62_LEN 5 +#define OID_ANSI_X9_62_FIELD_TYPE OID_ANSI_X9_62, 1 +#define OID_ANSI_X9_62_PUBKEY_TYPE OID_ANSI_X9_62, 2 +#define OID_ANSI_X9_62_ELL_CURVE OID_ANSI_X9_62, 3 +#define OID_ANSI_X9_62_ELL_CURVE_LEN OID_ANSI_X9_62_LEN+1 +#define OID_ANSI_X9_62_C_TWO_CURVE OID_ANSI_X9_62_ELL_CURVE, 0 +#define OID_ANSI_X9_62_PRIME_CURVE OID_ANSI_X9_62_ELL_CURVE, 1 +#define OID_ANSI_X9_62_SIG_TYPE OID_ANSI_X9_62, 4 +#define OID_ANSI_X9_62_SIG_TYPE_LEN OID_ANSI_X9_62_LEN+1 + +/* PKIX */ +#define OID_PKIX OID_DOD, 1, 5, 5, 7 +#define OID_PKIX_LENGTH 6 +#define OID_PE OID_PKIX, 1 +#define OID_PE_LENGTH OID_PKIX_LENGTH + 1 +#define OID_QT OID_PKIX, 2 +#define OID_QT_LENGTH OID_PKIX_LENGTH + 1 +#define OID_KP OID_PKIX, 3 +#define OID_KP_LENGTH OID_PKIX_LENGTH + 1 +#define OID_OTHER_NAME OID_PKIX, 8 +#define OID_OTHER_NAME_LENGTH OID_PKIX_LENGTH + 1 +#define OID_PDA OID_PKIX, 9 +#define OID_PDA_LENGTH OID_PKIX_LENGTH + 1 +#define OID_QCS OID_PKIX, 11 +#define OID_QCS_LENGTH OID_PKIX_LENGTH + 1 +#define OID_AD OID_PKIX, 48 +#define OID_AD_LENGTH OID_PKIX_LENGTH + 1 +#define OID_AD_OCSP OID_AD, 1 +#define OID_AD_OCSP_LENGTH OID_AD_LENGTH + 1 + +/* ETSI */ +#define OID_ETSI 0x04, 0x00 +#define OID_ETSI_LENGTH 2 +#define OID_ETSI_QCS 0x04, 0x00, 0x8E, 0x46, 0x01 +#define OID_ETSI_QCS_LENGTH 5 + +#define OID_OIW_SECSIG OID_OIW, 3 +#define OID_OIW_LENGTH 2 +#define OID_OIW_SECSIG_LENGTH OID_OIW_LENGTH +1 + +#define OID_OIW_ALGORITHM OID_OIW_SECSIG, 2 +#define OID_OIW_ALGORITHM_LENGTH OID_OIW_SECSIG_LENGTH +1 + +/* NIST defined digest algorithm arc (2, 16, 840, 1, 101, 3, 4, 2) */ +#define OID_NIST_HASHALG 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02 +#define OID_NIST_HASHALG_LENGTH 8 + +/* Kerberos PKINIT */ +#define OID_KERBv5 0x2b, 6, 1, 5, 2 +#define OID_KERBv5_LEN 5 +#define OID_KERBv5_PKINIT OID_KERBv5, 3 +#define OID_KERBv5_PKINIT_LEN OID_KERBv5_LEN + 1 + +/* Certicom (1 3 132) */ +#define OID_CERTICOM 0x2B, 0x81, 0x04 +#define OID_CERTICOM_LEN 3 +#define OID_CERTICOM_ELL_CURVE OID_CERTICOM, 0 +#define OID_CERTICOM_ELL_CURVE_LEN OID_CERTICOM_LEN+1 + +/* + * Apple-specific OID bases + */ + +/* + * apple OBJECT IDENTIFIER ::= + * { iso(1) member-body(2) US(840) 113635 } + * + * BER = 06 06 2A 86 48 86 F7 63 + */ +#define APPLE_OID OID_US, 0x86, 0xf7, 0x63 +#define APPLE_OID_LENGTH OID_US_LENGTH + 3 + +/* appleDataSecurity OBJECT IDENTIFIER ::= + * { apple 100 } + * { 1 2 840 113635 100 } + * + * BER = 06 07 2A 86 48 86 F7 63 64 + */ +#define APPLE_ADS_OID APPLE_OID, 0x64 +#define APPLE_ADS_OID_LENGTH APPLE_OID_LENGTH + 1 + +/* + * appleTrustPolicy OBJECT IDENTIFIER ::= + * { appleDataSecurity 1 } + * { 1 2 840 113635 100 1 } + * + * BER = 06 08 2A 86 48 86 F7 63 64 01 + */ +#define APPLE_TP_OID APPLE_ADS_OID, 1 +#define APPLE_TP_OID_LENGTH APPLE_ADS_OID_LENGTH + 1 + +/* + * appleSecurityAlgorithm OBJECT IDENTIFIER ::= + * { appleDataSecurity 2 } + * { 1 2 840 113635 100 2 } + * + * BER = 06 08 2A 86 48 86 F7 63 64 02 + */ +#define APPLE_ALG_OID APPLE_ADS_OID, 2 +#define APPLE_ALG_OID_LENGTH APPLE_ADS_OID_LENGTH + 1 + +/* + * appleDotMacCertificate OBJECT IDENTIFIER ::= + * { appleDataSecurity 3 } + * { 1 2 840 113635 100 3 } + */ +#define APPLE_DOTMAC_CERT_OID APPLE_ADS_OID, 3 +#define APPLE_DOTMAC_CERT_OID_LENGTH APPLE_ADS_OID_LENGTH + 1 + +/* + * Basis of Policy OIDs for .mac TP requests + * + * dotMacCertificateRequest OBJECT IDENTIFIER ::= + * { appleDotMacCertificate 1 } + * { 1 2 840 113635 100 3 1 } + */ +#define APPLE_DOTMAC_CERT_REQ_OID APPLE_DOTMAC_CERT_OID, 1 +#define APPLE_DOTMAC_CERT_REQ_OID_LENGTH APPLE_DOTMAC_CERT_OID_LENGTH + 1 + +/* + * Basis of .mac Certificate Extensions + * + * dotMacCertificateExtension OBJECT IDENTIFIER ::= + * { appleDotMacCertificate 2 } + * { 1 2 840 113635 100 3 2 } + */ +#define APPLE_DOTMAC_CERT_EXTEN_OID APPLE_DOTMAC_CERT_OID, 2 +#define APPLE_DOTMAC_CERT_EXTEN_OID_LENGTH APPLE_DOTMAC_CERT_OID_LENGTH + 1 + +/* + * Basis of .mac Certificate request OID/value identifiers + * + * dotMacCertificateRequestValues OBJECT IDENTIFIER ::= + * { appleDotMacCertificate 3 } + * { 1 2 840 113635 100 3 3 } + */ +#define APPLE_DOTMAC_CERT_REQ_VALUE_OID APPLE_DOTMAC_CERT_OID, 3 +#define APPLE_DOTMAC_CERT_REQ_VALUE_OID_LENGTH APPLE_DOTMAC_CERT_OID_LENGTH + 1 + +/* + * Basis of Apple-specific extended key usages + * + * appleExtendedKeyUsage OBJECT IDENTIFIER ::= + * { appleDataSecurity 4 } + * { 1 2 840 113635 100 4 } + */ +#define APPLE_EKU_OID APPLE_ADS_OID, 4 +#define APPLE_EKU_OID_LENGTH APPLE_ADS_OID_LENGTH + 1 + +/* + * Basis of Apple Code Signing extended key usages + * appleCodeSigning OBJECT IDENTIFIER ::= + * { appleExtendedKeyUsage 1 } + * { 1 2 840 113635 100 4 1 } + */ +#define APPLE_EKU_CODE_SIGNING APPLE_EKU_OID, 1 +#define APPLE_EKU_CODE_SIGNING_LENGTH APPLE_EKU_OID_LENGTH + 1 + +/* + * Basis of Apple-specific Certificate Policy identifiers + * appleCertificatePolicies OBJECT IDENTIFIER ::= + * { appleDataSecurity 5 } + * { 1 2 840 113635 100 5 } + */ +#define APPLE_CERT_POLICIES APPLE_ADS_OID, 5 +#define APPLE_CERT_POLICIES_LENGTH APPLE_ADS_OID_LENGTH + 1 + +/* + * Basis of Apple-specific certificate extensions + * appleCertificateExtensions OBJECT IDENTIFIER ::= + * { appleDataSecurity 6 } + * { 1 2 840 113635 100 6 } + */ +#define APPLE_EXTENSION_OID APPLE_ADS_OID, 6 +#define APPLE_EXTENSION_OID_LENGTH APPLE_ADS_OID_LENGTH + 1 + +/* + * Basis of Apple-specific Code Signing certificate extensions + * appleCertificateExtensionCodeSigning OBJECT IDENTIFIER ::= + * { appleCertificateExtensions 1 } + * { 1 2 840 113635 100 6 1 } + */ +#define APPLE_EXTENSION_CODE_SIGNING APPLE_EXTENSION_OID, 1 +#define APPLE_EXTENSION_CODE_SIGNING_LENGTH APPLE_EXTENSION_OID_LENGTH + 1 + +/* + * Netscape OIDs. + */ +#define NETSCAPE_BASE_OID 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42 +#define NETSCAPE_BASE_OID_LEN 7 + +/* + * Netscape cert extension. + * + * netscape-cert-extension OBJECT IDENTIFIER ::= + * { 2 16 840 1 113730 1 } + * + * BER = 06 08 60 86 48 01 86 F8 42 01 + */ +#define NETSCAPE_CERT_EXTEN NETSCAPE_BASE_OID, 0x01 +#define NETSCAPE_CERT_EXTEN_LENGTH NETSCAPE_BASE_OID_LEN + 1 + +#define NETSCAPE_CERT_POLICY NETSCAPE_BASE_OID, 0x04 +#define NETSCAPE_CERT_POLICY_LENGTH NETSCAPE_BASE_OID_LEN + 1 + +/* + * Domain Component OID + */ +#define OID_ITU_RFCDATA_2342 OID_ITU_RFCDATA, 0x49, 0x86 +#define OID_ITU_RFCDATA_2342_LENGTH OID_ITU_RFCDATA_MEMBER_LENGTH + 2 + +#define OID_ITU_RFCDATA_2342_UCL OID_ITU_RFCDATA_2342, 0x49, 0x1F, 0x12, 0x8C +#define OID_ITU_RFCDATA_2342_UCL_LENGTH OID_ITU_RFCDATA_2342_LENGTH + 4 + +#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT OID_ITU_RFCDATA_2342_UCL, 0xE4 +#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_LENGTH OID_ITU_RFCDATA_2342_UCL_LENGTH + 1 + +#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT, 0x81 +#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_LENGTH OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_LENGTH + 1 + +#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_DOMAINCOMPONENT OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES, 0x99 +#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_DOMAINCOMPONENT_LENGTH OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_LENGTH + 1 + +#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_USERID OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES, 0x81 +#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_USERID_LENGTH OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_LENGTH + 1 + +#ifdef __cplusplus +} +#endif + +#endif /* _OIDSBASE_H_ */ diff --git a/libsecurity_asn1/lib/oidsocsp.c b/Security/libsecurity_asn1/lib/oidsocsp.c similarity index 96% rename from libsecurity_asn1/lib/oidsocsp.c rename to Security/libsecurity_asn1/lib/oidsocsp.c index d28744f4..1eaea73e 100644 --- a/libsecurity_asn1/lib/oidsocsp.c +++ b/Security/libsecurity_asn1/lib/oidsocsp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2009-2010,2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/oidsocsp.h b/Security/libsecurity_asn1/lib/oidsocsp.h similarity index 95% rename from libsecurity_asn1/lib/oidsocsp.h rename to Security/libsecurity_asn1/lib/oidsocsp.h index 5db1c207..5963d1e6 100644 --- a/libsecurity_asn1/lib/oidsocsp.h +++ b/Security/libsecurity_asn1/lib/oidsocsp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2009-2010,2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/osKeyTemplates.c b/Security/libsecurity_asn1/lib/osKeyTemplates.c similarity index 98% rename from libsecurity_asn1/lib/osKeyTemplates.c rename to Security/libsecurity_asn1/lib/osKeyTemplates.c index 726f3968..84c22aca 100644 --- a/libsecurity_asn1/lib/osKeyTemplates.c +++ b/Security/libsecurity_asn1/lib/osKeyTemplates.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/osKeyTemplates.h b/Security/libsecurity_asn1/lib/osKeyTemplates.h similarity index 98% rename from libsecurity_asn1/lib/osKeyTemplates.h rename to Security/libsecurity_asn1/lib/osKeyTemplates.h index 38e274a7..2a018796 100644 --- a/libsecurity_asn1/lib/osKeyTemplates.h +++ b/Security/libsecurity_asn1/lib/osKeyTemplates.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/pkcs12Templates.c b/Security/libsecurity_asn1/lib/pkcs12Templates.c similarity index 99% rename from libsecurity_asn1/lib/pkcs12Templates.c rename to Security/libsecurity_asn1/lib/pkcs12Templates.c index 313dda40..c9effec0 100644 --- a/libsecurity_asn1/lib/pkcs12Templates.c +++ b/Security/libsecurity_asn1/lib/pkcs12Templates.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2008,2010,2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_asn1/lib/pkcs12Templates.h b/Security/libsecurity_asn1/lib/pkcs12Templates.h new file mode 100644 index 00000000..ea2cc6f9 --- /dev/null +++ b/Security/libsecurity_asn1/lib/pkcs12Templates.h @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2003-2004,2008,2010,2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + */ +/* + * pkcs12Templates.h + * + ******************************************************************* + * + * In a probably vain attempt to clarify the structure of a PKCS12 + * PFX, here is a high-level summary. + * + * The top level item in P12 is a PFX. + * + * PFX = { + * int version; + * ContentInfo authSafe; -- from PKCS7 + * MacData mac; -- optional, password integrity version + * } + * + * The authSafe in a PFX has two legal contentTypes in the P12 + * world, CT_Data (password integrity mode) or CT_SignedData + * (public key integrity mode). The current version of this library + * only supports password integrity mode. Thus the integrity of + * the whole authSafe item is protected by a MAC in the PFX. + * + * The authSafe.content field is a BER-encoded AuthenticatedSafe. + * + * AuthenticatedSafe = { + * SEQUENCE OF ContentInfo; + * } + * + * OK. Each ContentInfo in an AuthenticatedSafe can either be type + * CT_Data, CT_EnvData, or CT_EncryptedData. In the latter cases the + * content is decrypted to produce an encoded SafeContents; in the + * former case the content *is* an encoded SafeContents. + * + * A SafeContents is a sequence of SafeBags. + * + * Each SafeBag can be of several types: + * + * BT_KeyBag + * BT_ShroudedKeyBag + * BT_CertBag + * BT_CrlBag + * BT_SecretBag + * BT_SafeContentsBag + * + */ + +#ifndef _PKCS12_TEMPLATES_H_ +#define _PKCS12_TEMPLATES_H_ + +#include /* for NSS_Attribute */ +#include /* will be lib-specific place */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * MacData ::= SEQUENCE { + * mac DigestInfo, + * macSalt OCTET STRING, + * iterations INTEGER DEFAULT 1 + * } + */ +typedef struct { + NSS_P7_DigestInfo mac; + SecAsn1Item macSalt; + SecAsn1Item iterations; // optional +} NSS_P12_MacData; + +extern const SecAsn1Template NSS_P12_MacDataTemplate[]; + +/* + * PFX ::= SEQUENCE { + * version INTEGER {v3(3)}(v3,...), + * authSafe ContentInfo, + * macData MacData OPTIONAL + * } + */ + +/* + * First the top level PFX with unparsed ContentInfo.content. + */ +typedef struct { + SecAsn1Item version; + NSS_P7_RawContentInfo authSafe; + NSS_P12_MacData *macData; +} NSS_P12_RawPFX; + +extern const SecAsn1Template NSS_P12_RawPFXTemplate[]; + +/* + * And a PFX with a decoded ContentInfo.content. + */ +typedef struct { + SecAsn1Item version; + NSS_P7_DecodedContentInfo authSafe; + NSS_P12_MacData *macData; +} NSS_P12_DecodedPFX; + +extern const SecAsn1Template NSS_P12_DecodedPFXTemplate[]; + +/* + * The CSSMOID_PKCS7_Data-style ContentInfo.content of a PFX + * contains an encoded AuthenticatedSafe. + * + * AuthenticatedSafe ::= SEQUENCE OF ContentInfo + * -- Data if unencrypted + * -- EncryptedData if password-encrypted + * -- EnvelopedData if public key-encrypted + */ +typedef struct { + NSS_P7_DecodedContentInfo **info; +} NSS_P12_AuthenticatedSafe; + +extern const SecAsn1Template NSS_P12_AuthenticatedSafeTemplate[]; + +/* + * Individual BagTypes. + * Code on demand. + */ +typedef SecAsn1Item NSS_P12_KeyBag; +typedef NSS_EncryptedPrivateKeyInfo NSS_P12_ShroudedKeyBag; +typedef SecAsn1Item NSS_P12_SecretBag; +typedef SecAsn1Item NSS_P12_SafeContentsBag; + +/* + * CertBag + * + * CertBag ::= SEQUENCE { + * certId BAG-TYPE.&id ({CertTypes}), + * certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId}) + * } + * + * x509Certificate BAG-TYPE ::= + * {OCTET STRING IDENTIFIED BY {certTypes 1}} + * -- DER-encoded X.509 certificate stored in OCTET STRING + * sdsiCertificate BAG-TYPE ::= + * {IA5String IDENTIFIED BY {certTypes 2}} + * -- Base64-encoded SDSI certificate stored in IA5String + */ +typedef enum { + CT_Unknown, // --> ASN_ANY + CT_X509, + CT_SDSI, +} NSS_P12_CertBagType; + +typedef struct { + SecAsn1Oid bagType; + NSS_P12_CertBagType type; + SecAsn1Item certValue; +} NSS_P12_CertBag; + +extern const SecAsn1Template NSS_P12_CertBagTemplate[]; + +/* + * CRLBag + * + * CRLBag ::= SEQUENCE { + * certId BAG-TYPE.&id ({CertTypes}), + * certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId}) + * } + * + * x509Certificate BAG-TYPE ::= + * {OCTET STRING IDENTIFIED BY {certTypes 1}} + * -- DER-encoded X.509 certificate stored in OCTET STRING + * sdsiCertificate BAG-TYPE ::= + * {IA5String IDENTIFIED BY {certTypes 2}} + * -- Base64-encoded SDSI certificate stored in IA5String + */ +typedef enum { + CRT_Unknown, // --> ASN_ANY + CRT_X509, +} NSS_P12_CrlBagType; + +typedef struct { + SecAsn1Oid bagType; + NSS_P12_CrlBagType type; + SecAsn1Item crlValue; +} NSS_P12_CrlBag; + +extern const SecAsn1Template NSS_P12_CrlBagTemplate[]; + +/* + * BagId OIDs map to one of these for convenience. Our dynamic + * template chooser drops one of these into NSS_P12_SafeBag.type + * on decode. + */ +typedef enum { + BT_None = 0, + BT_KeyBag, + BT_ShroudedKeyBag, + BT_CertBag, + BT_CrlBag, + BT_SecretBag, + BT_SafeContentsBag +} NSS_P12_SB_Type; + +/* + * The ContentInfo.content values of each element in + * an AuthenticatedSafe map to a sequence of these - either directly + * (contentType CSSMOID_PKCS7_Data, octet string contents are + * the DER encoding of this) or indirectly (encrypted or + * shrouded, the decrypted content is the DER encoding of this). + */ +typedef struct { + SecAsn1Oid bagId; + NSS_P12_SB_Type type; + union { + NSS_P12_KeyBag *keyBag; + NSS_P12_ShroudedKeyBag *shroudedKeyBag; + NSS_P12_CertBag *certBag; + NSS_P12_CrlBag *crlBag; + NSS_P12_SecretBag *secretBag; + NSS_P12_SafeContentsBag *safeContentsBag; + } bagValue; + NSS_Attribute **bagAttrs; // optional +} NSS_P12_SafeBag; + +extern const SecAsn1Template NSS_P12_SafeBagTemplate[]; + +/* + * SafeContents, the contents of an element in an AuthenticatedSafe. + */ +typedef struct { + NSS_P12_SafeBag **bags; +} +NSS_P12_SafeContents; + +extern const SecAsn1Template NSS_P12_SafeContentsTemplate[]; + +/* + * PKCS12-specific algorithm parameters. + * A DER encoded version of this is the parameters value of + * a CSSM_X509_ALGORITHM_IDENTIFIER used in a + * NSS_P7_EncrContentInfo.encrAlg in P12 password privacy mode. + * + * pkcs-12PbeParams ::= SEQUENCE { + * salt OCTET STRING, + * iterations INTEGER + * } + * + * NOTE the P12 spec does place a limit on the value of iterations. + * I guess we have to assume in actual usage that it's + * restricted to (0..MAX), i.e., uint32-sized. + * + * We're also assuming that it is explicitly an unsigned value, + * so that the value bytes in the encoding of 0xff would be + * (0, 255). + */ +typedef struct { + SecAsn1Item salt; + SecAsn1Item iterations; +} NSS_P12_PBE_Params; + +extern const SecAsn1Template NSS_P12_PBE_ParamsTemplate[]; + +#ifdef __cplusplus +} +#endif + +#endif /* _PKCS12_TEMPLATES_H_ */ + diff --git a/libsecurity_asn1/lib/pkcs7Templates.c b/Security/libsecurity_asn1/lib/pkcs7Templates.c similarity index 98% rename from libsecurity_asn1/lib/pkcs7Templates.c rename to Security/libsecurity_asn1/lib/pkcs7Templates.c index afde23ba..125fd6b3 100644 --- a/libsecurity_asn1/lib/pkcs7Templates.c +++ b/Security/libsecurity_asn1/lib/pkcs7Templates.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2008,2010,2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_asn1/lib/pkcs7Templates.h b/Security/libsecurity_asn1/lib/pkcs7Templates.h new file mode 100644 index 00000000..b6f35e9c --- /dev/null +++ b/Security/libsecurity_asn1/lib/pkcs7Templates.h @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2003-2004,2008,2010,2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + */ +/* + * pkcs7Templates.h + */ + +#ifndef _PKCS7_TEMPLATES_H_ +#define _PKCS7_TEMPLATES_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest + * } + * + * Digest ::= OCTET STRING + */ +typedef struct { + SecAsn1AlgId digestAlgorithm; + SecAsn1Item digest; +} NSS_P7_DigestInfo; + +extern const SecAsn1Template NSS_P7_DigestInfoTemplate[]; + +/* + * Uninterpreted ContentInfo, with content stripped from its + * EXPLICIT CONTEXT_SPECIFIC wrapper + * + * ContentInfo ::= SEQUENCE { + * contentType ContentType, + * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL + * } + */ +typedef struct { + SecAsn1Oid contentType; + SecAsn1Item content; +} NSS_P7_RawContentInfo; + +extern const SecAsn1Template NSS_P7_RawContentInfoTemplate[]; + +// MARK: ---- ContentInfo.content types ----- + +/* + * Expand beyond ASN_ANY/CSSM_DATA as needed + */ +typedef SecAsn1Item NSS_P7_SignedData; +typedef SecAsn1Item NSS_P7_EnvelData; +typedef SecAsn1Item NSS_P7_SignEnvelData; +typedef SecAsn1Item NSS_P7_DigestedData; + +/* EncryptedData */ + +/* + * EncryptedContentInfo ::= SEQUENCE { + * contentType ContentType, + * contentEncryptionAlgorithm + * ContentEncryptionAlgorithmIdentifier, + * encryptedContent + * [0] IMPLICIT EncryptedContent OPTIONAL + * } + * + * EncryptedContent ::= OCTET STRING + */ + +typedef struct { + SecAsn1Oid contentType; + SecAsn1AlgId encrAlg; + SecAsn1Item encrContent; +} NSS_P7_EncrContentInfo; + +/* + * EncryptedData ::= SEQUENCE { + * version Version, + * encryptedContentInfo EncryptedContentInfo + * } + */ +typedef struct { + SecAsn1Item version; + NSS_P7_EncrContentInfo contentInfo; +} NSS_P7_EncryptedData; + +extern const SecAsn1Template NSS_P7_EncrContentInfoTemplate[]; +extern const SecAsn1Template NSS_P7_EncryptedDataTemplate[]; +extern const SecAsn1Template NSS_P7_PtrToEncryptedDataTemplate[]; + +/* the stub templates for unimplemented contentTypes */ +#define NSS_P7_PtrToSignedDataTemplate kSecAsn1PointerToAnyTemplate +#define NSS_P7_PtrToEnvelDataTemplate kSecAsn1PointerToAnyTemplate +#define NSS_P7_PtrToSignEnvelDataTemplate kSecAsn1PointerToAnyTemplate +#define NSS_P7_PtrToDigestedDataTemplate kSecAsn1PointerToAnyTemplate + +// MARK: ---- decoded ContentInfo ----- + +/* + * For convenience, out dynamic template chooser for ContentInfo.content + * drops one of these into the decoded struct. Thus, higher level + * code doesn't have to grunge around comparing OIDs to figure out + * what's there. + */ +typedef enum { + CT_None = 0, + CT_Data, + CT_SignedData, + CT_EnvData, + CT_SignedEnvData, + CT_DigestData, + CT_EncryptedData +} NSS_P7_CI_Type; + +/* + * Decoded ContentInfo. Decoded via SEC_ASN1_DYNAMIC per contentType. + */ +typedef struct { + SecAsn1Oid contentType; + NSS_P7_CI_Type type; + union { + SecAsn1Item *data; // CSSMOID_PKCS7_Data + // contents of Octet String + NSS_P7_SignedData *signedData; + // CSSMOID_PKCS7_SignedData + NSS_P7_EnvelData *envData; // CSSMOID_PKCS7_EnvelopedData + NSS_P7_SignEnvelData *signEnvelData; + // CSSMOID_PKCS7_SignedAndEnvelopedData + NSS_P7_DigestedData *digestedData; + // CSSMOID_PKCS7_DigestedData + NSS_P7_EncryptedData *encryptData; + //CSSMOID_PKCS7_EncryptedData + + } content; +} NSS_P7_DecodedContentInfo; + +extern const SecAsn1Template NSS_P7_DecodedContentInfoTemplate[]; + +#ifdef __cplusplus +} +#endif + +#endif /* _PKCS7_TEMPLATES_H_ */ + diff --git a/libsecurity_asn1/lib/plarena.c b/Security/libsecurity_asn1/lib/plarena.c similarity index 99% rename from libsecurity_asn1/lib/plarena.c rename to Security/libsecurity_asn1/lib/plarena.c index 44d2df72..0b8eb8a1 100644 --- a/libsecurity_asn1/lib/plarena.c +++ b/Security/libsecurity_asn1/lib/plarena.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/plarena.h b/Security/libsecurity_asn1/lib/plarena.h similarity index 100% rename from libsecurity_asn1/lib/plarena.h rename to Security/libsecurity_asn1/lib/plarena.h diff --git a/libsecurity_asn1/lib/plarenas.h b/Security/libsecurity_asn1/lib/plarenas.h similarity index 100% rename from libsecurity_asn1/lib/plarenas.h rename to Security/libsecurity_asn1/lib/plarenas.h diff --git a/libsecurity_asn1/lib/plstr.h b/Security/libsecurity_asn1/lib/plstr.h similarity index 100% rename from libsecurity_asn1/lib/plstr.h rename to Security/libsecurity_asn1/lib/plstr.h diff --git a/libsecurity_asn1/lib/prbit.h b/Security/libsecurity_asn1/lib/prbit.h similarity index 100% rename from libsecurity_asn1/lib/prbit.h rename to Security/libsecurity_asn1/lib/prbit.h diff --git a/libsecurity_asn1/lib/prcpucfg.h b/Security/libsecurity_asn1/lib/prcpucfg.h similarity index 100% rename from libsecurity_asn1/lib/prcpucfg.h rename to Security/libsecurity_asn1/lib/prcpucfg.h diff --git a/libsecurity_asn1/lib/prcvar.h b/Security/libsecurity_asn1/lib/prcvar.h similarity index 100% rename from libsecurity_asn1/lib/prcvar.h rename to Security/libsecurity_asn1/lib/prcvar.h diff --git a/libsecurity_asn1/lib/prenv.h b/Security/libsecurity_asn1/lib/prenv.h similarity index 100% rename from libsecurity_asn1/lib/prenv.h rename to Security/libsecurity_asn1/lib/prenv.h diff --git a/libsecurity_asn1/lib/prerr.h b/Security/libsecurity_asn1/lib/prerr.h similarity index 100% rename from libsecurity_asn1/lib/prerr.h rename to Security/libsecurity_asn1/lib/prerr.h diff --git a/libsecurity_asn1/lib/prerror.h b/Security/libsecurity_asn1/lib/prerror.h similarity index 100% rename from libsecurity_asn1/lib/prerror.h rename to Security/libsecurity_asn1/lib/prerror.h diff --git a/libsecurity_asn1/lib/prinit.h b/Security/libsecurity_asn1/lib/prinit.h similarity index 100% rename from libsecurity_asn1/lib/prinit.h rename to Security/libsecurity_asn1/lib/prinit.h diff --git a/libsecurity_asn1/lib/prinrval.h b/Security/libsecurity_asn1/lib/prinrval.h similarity index 100% rename from libsecurity_asn1/lib/prinrval.h rename to Security/libsecurity_asn1/lib/prinrval.h diff --git a/libsecurity_asn1/lib/prlock.h b/Security/libsecurity_asn1/lib/prlock.h similarity index 100% rename from libsecurity_asn1/lib/prlock.h rename to Security/libsecurity_asn1/lib/prlock.h diff --git a/libsecurity_asn1/lib/prlog.h b/Security/libsecurity_asn1/lib/prlog.h similarity index 100% rename from libsecurity_asn1/lib/prlog.h rename to Security/libsecurity_asn1/lib/prlog.h diff --git a/libsecurity_asn1/lib/prlong.h b/Security/libsecurity_asn1/lib/prlong.h similarity index 100% rename from libsecurity_asn1/lib/prlong.h rename to Security/libsecurity_asn1/lib/prlong.h diff --git a/libsecurity_asn1/lib/prmem.h b/Security/libsecurity_asn1/lib/prmem.h similarity index 100% rename from libsecurity_asn1/lib/prmem.h rename to Security/libsecurity_asn1/lib/prmem.h diff --git a/libsecurity_asn1/lib/prmon.h b/Security/libsecurity_asn1/lib/prmon.h similarity index 100% rename from libsecurity_asn1/lib/prmon.h rename to Security/libsecurity_asn1/lib/prmon.h diff --git a/libsecurity_asn1/lib/protypes.h b/Security/libsecurity_asn1/lib/protypes.h similarity index 100% rename from libsecurity_asn1/lib/protypes.h rename to Security/libsecurity_asn1/lib/protypes.h diff --git a/libsecurity_asn1/lib/prthread.h b/Security/libsecurity_asn1/lib/prthread.h similarity index 100% rename from libsecurity_asn1/lib/prthread.h rename to Security/libsecurity_asn1/lib/prthread.h diff --git a/libsecurity_asn1/lib/prtime.h b/Security/libsecurity_asn1/lib/prtime.h similarity index 100% rename from libsecurity_asn1/lib/prtime.h rename to Security/libsecurity_asn1/lib/prtime.h diff --git a/libsecurity_asn1/lib/prtypes.h b/Security/libsecurity_asn1/lib/prtypes.h similarity index 100% rename from libsecurity_asn1/lib/prtypes.h rename to Security/libsecurity_asn1/lib/prtypes.h diff --git a/libsecurity_asn1/lib/prvrsion.h b/Security/libsecurity_asn1/lib/prvrsion.h similarity index 100% rename from libsecurity_asn1/lib/prvrsion.h rename to Security/libsecurity_asn1/lib/prvrsion.h diff --git a/libsecurity_asn1/lib/secErrorStr.c b/Security/libsecurity_asn1/lib/secErrorStr.c similarity index 98% rename from libsecurity_asn1/lib/secErrorStr.c rename to Security/libsecurity_asn1/lib/secErrorStr.c index 482edaa1..138dbc14 100644 --- a/libsecurity_asn1/lib/secErrorStr.c +++ b/Security/libsecurity_asn1/lib/secErrorStr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006,2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2008,2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_asn1/lib/secasn1.h b/Security/libsecurity_asn1/lib/secasn1.h similarity index 100% rename from libsecurity_asn1/lib/secasn1.h rename to Security/libsecurity_asn1/lib/secasn1.h diff --git a/libsecurity_asn1/lib/secasn1d.c b/Security/libsecurity_asn1/lib/secasn1d.c similarity index 99% rename from libsecurity_asn1/lib/secasn1d.c rename to Security/libsecurity_asn1/lib/secasn1d.c index d4b6d2e3..c3971d0e 100644 --- a/libsecurity_asn1/lib/secasn1d.c +++ b/Security/libsecurity_asn1/lib/secasn1d.c @@ -534,7 +534,7 @@ sec_asn1d_init_state_based_on_template (sec_asn1d_state *state, /* XXX Check that both of these tests are really needed/appropriate. */ - if (state == NULL || state->top->status == decodeError) + if (state == NULL || state->top->status == decodeError || state->theTemplate == NULL) return state; encode_kind = state->theTemplate->kind; @@ -1058,7 +1058,7 @@ sec_asn1d_prepare_for_contents (sec_asn1d_state *state, #endif ) { - SecAsn1Item *item; + SecAsn1Item *item=NULL; PRArenaPool *poolp; unsigned long alloc_len; @@ -1143,6 +1143,7 @@ sec_asn1d_prepare_for_contents (sec_asn1d_state *state, if (state != NULL) state = sec_asn1d_init_state_based_on_template (state, buf /* __APPLE__ */); + (void) state; return; } @@ -1187,6 +1188,7 @@ sec_asn1d_prepare_for_contents (sec_asn1d_state *state, */ state->place = afterGroup; } + (void) state; return; } @@ -1206,6 +1208,7 @@ sec_asn1d_prepare_for_contents (sec_asn1d_state *state, state = sec_asn1d_init_state_based_on_template (state, buf /* __APPLE__ */); } + (void) state; break; case SEC_ASN1_SET: /* XXX SET is not really implemented */ @@ -1335,7 +1338,13 @@ regular_string_type: struct subitem *subitem; unsigned long len; - PORT_Assert (item != NULL && item->Length == 0 && item->Data == NULL); + PORT_Assert (item!=NULL); + if (item==NULL) { + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return; + } + PORT_Assert (item->Length == 0 && item->Data == NULL); /* * Check for and handle an ANY which has stashed aside the * header (identifier and length) bytes for us to include @@ -1449,6 +1458,7 @@ regular_string_type: else state->place = duringLeaf; } + (void) state; break; default: @@ -1763,6 +1773,8 @@ sec_asn1d_add_to_subitems (sec_asn1d_state *state, if (copy == NULL) { dprintf("decodeError: alloc\n"); state->top->status = decodeError; + if (!state->top->our_pool) + PORT_Free(thing); return NULL; } PORT_Memcpy (copy, data, len); @@ -2130,7 +2142,7 @@ sec_asn1d_next_in_sequence (sec_asn1d_state *state, state->top->current = child; child = sec_asn1d_init_state_based_on_template (child, buf /* __APPLE__ */); - if (child_missing) { + if (child_missing && child) { child->place = afterIdentifier; child->found_tag_modifiers = child_found_tag_modifiers; child->found_tag_number = child_found_tag_number; diff --git a/libsecurity_asn1/lib/secasn1e.c b/Security/libsecurity_asn1/lib/secasn1e.c similarity index 99% rename from libsecurity_asn1/lib/secasn1e.c rename to Security/libsecurity_asn1/lib/secasn1e.c index e7d608f8..0dee92c6 100644 --- a/libsecurity_asn1/lib/secasn1e.c +++ b/Security/libsecurity_asn1/lib/secasn1e.c @@ -814,6 +814,8 @@ sec_asn1e_write_header (sec_asn1e_state *state) state = sec_asn1e_init_state_based_on_template (state); } + (void) state; + return; } @@ -886,6 +888,9 @@ sec_asn1e_write_header (sec_asn1e_state *state) state->src, PR_TRUE); if (state != NULL) state = sec_asn1e_init_state_based_on_template (state); + + (void) state; + return; } @@ -941,6 +946,8 @@ sec_asn1e_write_header (sec_asn1e_state *state) state->place = duringContents; break; } + + (void) state; } diff --git a/libsecurity_asn1/lib/secasn1t.h b/Security/libsecurity_asn1/lib/secasn1t.h similarity index 100% rename from libsecurity_asn1/lib/secasn1t.h rename to Security/libsecurity_asn1/lib/secasn1t.h diff --git a/libsecurity_asn1/lib/secasn1u.c b/Security/libsecurity_asn1/lib/secasn1u.c similarity index 100% rename from libsecurity_asn1/lib/secasn1u.c rename to Security/libsecurity_asn1/lib/secasn1u.c diff --git a/libsecurity_asn1/lib/seccomon.h b/Security/libsecurity_asn1/lib/seccomon.h similarity index 100% rename from libsecurity_asn1/lib/seccomon.h rename to Security/libsecurity_asn1/lib/seccomon.h diff --git a/libsecurity_asn1/lib/secerr.h b/Security/libsecurity_asn1/lib/secerr.h similarity index 100% rename from libsecurity_asn1/lib/secerr.h rename to Security/libsecurity_asn1/lib/secerr.h diff --git a/libsecurity_asn1/lib/secport.c b/Security/libsecurity_asn1/lib/secport.c similarity index 100% rename from libsecurity_asn1/lib/secport.c rename to Security/libsecurity_asn1/lib/secport.c diff --git a/libsecurity_asn1/lib/secport.h b/Security/libsecurity_asn1/lib/secport.h similarity index 100% rename from libsecurity_asn1/lib/secport.h rename to Security/libsecurity_asn1/lib/secport.h diff --git a/libsecurity_asn1/lib/security_asn1.exp b/Security/libsecurity_asn1/lib/security_asn1.exp similarity index 100% rename from libsecurity_asn1/lib/security_asn1.exp rename to Security/libsecurity_asn1/lib/security_asn1.exp diff --git a/Security/libsecurity_asn1/libsecurity_asn1.xcodeproj/project.pbxproj b/Security/libsecurity_asn1/libsecurity_asn1.xcodeproj/project.pbxproj new file mode 100644 index 00000000..51d8fc12 --- /dev/null +++ b/Security/libsecurity_asn1/libsecurity_asn1.xcodeproj/project.pbxproj @@ -0,0 +1,477 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 18312F9714E99A3F00F0BCAC /* SecNssCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434290534D3B800F287B2 /* SecNssCoder.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 1885B45314D9BB1A00519375 /* SecNssCoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434280534D3B800F287B2 /* SecNssCoder.cpp */; }; + 18B6B2A714DB73A000EDDE5F /* secErrorStr.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434270534D3B800F287B2 /* secErrorStr.c */; }; + 4C28246B0F1BC75800CAADEC /* oidsocsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2824670F1BC75800CAADEC /* oidsocsp.c */; }; + 4C28246C0F1BC75800CAADEC /* oidsocsp.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C2824680F1BC75800CAADEC /* oidsocsp.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 795CA8220D38041D00BAE6A2 /* SecAsn1Coder.c in Sources */ = {isa = PBXBuildFile; fileRef = 0545C7B806502D1100543007 /* SecAsn1Coder.c */; }; + 795CA8230D38041D00BAE6A2 /* SecAsn1Coder.h in Headers */ = {isa = PBXBuildFile; fileRef = 0545C7B906502D1100543007 /* SecAsn1Coder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 795CA8240D38041D00BAE6A2 /* SecAsn1Templates.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6433F80534D3B800F287B2 /* SecAsn1Templates.c */; }; + 795CA8250D38041D00BAE6A2 /* SecAsn1Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6433F90534D3B800F287B2 /* SecAsn1Templates.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 795CA8260D38041D00BAE6A2 /* SecAsn1Types.h in Headers */ = {isa = PBXBuildFile; fileRef = 0554F5B609892C980085E7C5 /* SecAsn1Types.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 795CA8270D38041D00BAE6A2 /* certExtensionTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6433FA0534D3B800F287B2 /* certExtensionTemplates.c */; }; + 795CA8280D38041D00BAE6A2 /* certExtensionTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6433FB0534D3B800F287B2 /* certExtensionTemplates.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 795CA8290D38041D00BAE6A2 /* csrTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6433FC0534D3B800F287B2 /* csrTemplates.c */; }; + 795CA82A0D38041D00BAE6A2 /* csrTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6433FD0534D3B800F287B2 /* csrTemplates.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 795CA82B0D38041D00BAE6A2 /* keyTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6433FE0534D3B800F287B2 /* keyTemplates.c */; }; + 795CA82C0D38041D00BAE6A2 /* keyTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 0502B640068A5920006168D5 /* keyTemplates.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 795CA82D0D38041D00BAE6A2 /* nameTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434000534D3B800F287B2 /* nameTemplates.c */; }; + 795CA82E0D38041D00BAE6A2 /* nameTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434010534D3B800F287B2 /* nameTemplates.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 795CA82F0D38041D00BAE6A2 /* nsprPortX.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434020534D3B800F287B2 /* nsprPortX.c */; }; + 795CA8300D38041D00BAE6A2 /* nssUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434060534D3B800F287B2 /* nssUtils.c */; }; + 795CA8310D38041D00BAE6A2 /* nssUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434070534D3B800F287B2 /* nssUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 795CA8320D38041D00BAE6A2 /* ocspTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = 0502BF9A068B51E3006168D5 /* ocspTemplates.c */; }; + 795CA8330D38041D00BAE6A2 /* ocspTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6433FF0534D3B800F287B2 /* ocspTemplates.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 795CA8350D38041D00BAE6A2 /* secasn1d.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434210534D3B800F287B2 /* secasn1d.c */; }; + 795CA8360D38041D00BAE6A2 /* secasn1e.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434220534D3B800F287B2 /* secasn1e.c */; }; + 795CA8380D38041D00BAE6A2 /* secasn1u.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434240534D3B800F287B2 /* secasn1u.c */; }; + 795CA8390D38041D00BAE6A2 /* X509Templates.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C64342D0534D3B800F287B2 /* X509Templates.c */; }; + 795CA83A0D38041D00BAE6A2 /* X509Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64342E0534D3B800F287B2 /* X509Templates.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 795CA83B0D38041D00BAE6A2 /* osKeyTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = 0504B16106517A730011D5F5 /* osKeyTemplates.c */; }; + 795CA83C0D38041D00BAE6A2 /* osKeyTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 0504B16206517A730011D5F5 /* osKeyTemplates.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 795CAAD10D3BEDBB00BAE6A2 /* pkcs7Templates.c in Sources */ = {isa = PBXBuildFile; fileRef = 795CAACD0D3BEDBB00BAE6A2 /* pkcs7Templates.c */; }; + 795CAAD20D3BEDBB00BAE6A2 /* pkcs7Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 795CAACE0D3BEDBB00BAE6A2 /* pkcs7Templates.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 795CAAD30D3BEDBB00BAE6A2 /* pkcs12Templates.c in Sources */ = {isa = PBXBuildFile; fileRef = 795CAACF0D3BEDBB00BAE6A2 /* pkcs12Templates.c */; }; + 795CAAD40D3BEDBB00BAE6A2 /* pkcs12Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 795CAAD00D3BEDBB00BAE6A2 /* pkcs12Templates.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 798B80C10D3E8B6700AC1D04 /* secasn1.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434200534D3B800F287B2 /* secasn1.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 798B80E00D3E8BFC00AC1D04 /* secasn1t.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434230534D3B800F287B2 /* secasn1t.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 79BDD2D10D60CE82000D84D3 /* plarenas.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64340C0534D3B800F287B2 /* plarenas.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 79BDD2ED0D60CEF5000D84D3 /* prtypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64341E0534D3B800F287B2 /* prtypes.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 79BDD2F60D60CF24000D84D3 /* prcpucfg.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64340F0534D3B800F287B2 /* prcpucfg.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 79BDD2FC0D60CF66000D84D3 /* secerr.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434260534D3B800F287B2 /* secerr.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 79BDD3020D60CFC9000D84D3 /* protypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64341B0534D3B800F287B2 /* protypes.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 79BDD30C0D60D0E5000D84D3 /* seccomon.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434250534D3B800F287B2 /* seccomon.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 79BDD3100D60D116000D84D3 /* plstr.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64340D0534D3B800F287B2 /* plstr.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 79BDD3110D60D116000D84D3 /* prlog.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434170534D3B800F287B2 /* prlog.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 79BDD33F0D60D29A000D84D3 /* prerror.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434130534D3B800F287B2 /* prerror.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 79BDD3420D60D2B2000D84D3 /* prerr.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434120534D3B800F287B2 /* prerr.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 79BDD3490D60D4A4000D84D3 /* prbit.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64340E0534D3B800F287B2 /* prbit.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 79BDD34A0D60D4A4000D84D3 /* prmem.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434190534D3B800F287B2 /* prmem.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 79EF5A780D3C1984009F5270 /* oidsalg.c in Sources */ = {isa = PBXBuildFile; fileRef = 79EF5A730D3C1984009F5270 /* oidsalg.c */; }; + 79EF5A790D3C1984009F5270 /* oidsalg.h in Headers */ = {isa = PBXBuildFile; fileRef = 79EF5A740D3C1984009F5270 /* oidsalg.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 79EF5A7A0D3C1984009F5270 /* oidsattr.c in Sources */ = {isa = PBXBuildFile; fileRef = 79EF5A750D3C1984009F5270 /* oidsattr.c */; }; + 79EF5A7B0D3C1984009F5270 /* oidsattr.h in Headers */ = {isa = PBXBuildFile; fileRef = 79EF5A760D3C1984009F5270 /* oidsattr.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 79EF5A7C0D3C1984009F5270 /* oidsbase.h in Headers */ = {isa = PBXBuildFile; fileRef = 79EF5A770D3C1984009F5270 /* oidsbase.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 79EF5BA30D3D6EF4009F5270 /* secport.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64342B0534D3B800F287B2 /* secport.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 79EF5BA50D3D6EF8009F5270 /* secport.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C64342A0534D3B800F287B2 /* secport.c */; }; + 79EF5BC90D3D6F44009F5270 /* plarena.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C64340A0534D3B800F287B2 /* plarena.c */; }; + 79EF5BCA0D3D6F44009F5270 /* plarena.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64340B0534D3B800F287B2 /* plarena.h */; settings = {ATTRIBUTES = (Private, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 0502B640068A5920006168D5 /* keyTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = keyTemplates.h; sourceTree = ""; }; + 0502BF9A068B51E3006168D5 /* ocspTemplates.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ocspTemplates.c; sourceTree = ""; }; + 0504B16106517A730011D5F5 /* osKeyTemplates.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = osKeyTemplates.c; sourceTree = ""; }; + 0504B16206517A730011D5F5 /* osKeyTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = osKeyTemplates.h; sourceTree = ""; }; + 0545C78806502BAD00543007 /* security_asn1.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = security_asn1.exp; sourceTree = ""; }; + 0545C7B806502D1100543007 /* SecAsn1Coder.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SecAsn1Coder.c; sourceTree = ""; }; + 0545C7B906502D1100543007 /* SecAsn1Coder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecAsn1Coder.h; sourceTree = ""; }; + 0554F5B609892C980085E7C5 /* SecAsn1Types.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecAsn1Types.h; sourceTree = ""; }; + 05ABB7BB0989387700FA0183 /* asn1Templates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = asn1Templates.h; sourceTree = ""; }; + 05BE7E6B0A37669000C055B0 /* libsecurity_asn1.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; path = libsecurity_asn1.plist; sourceTree = ""; }; + 05BE7E6C0A37669000C055B0 /* libsecurity_asn1.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = libsecurity_asn1.txt; sourceTree = ""; }; + 18B647F514D9FD4500F538BF /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 18B647F614D9FD4500F538BF /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 18B647F714D9FD4500F538BF /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 18B647F814D9FD4500F538BF /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 4C2824670F1BC75800CAADEC /* oidsocsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = oidsocsp.c; sourceTree = ""; }; + 4C2824680F1BC75800CAADEC /* oidsocsp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oidsocsp.h; sourceTree = ""; }; + 4C6433F80534D3B800F287B2 /* SecAsn1Templates.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SecAsn1Templates.c; sourceTree = ""; }; + 4C6433F90534D3B800F287B2 /* SecAsn1Templates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecAsn1Templates.h; sourceTree = ""; }; + 4C6433FA0534D3B800F287B2 /* certExtensionTemplates.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = certExtensionTemplates.c; sourceTree = ""; }; + 4C6433FB0534D3B800F287B2 /* certExtensionTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = certExtensionTemplates.h; sourceTree = ""; }; + 4C6433FC0534D3B800F287B2 /* csrTemplates.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = csrTemplates.c; sourceTree = ""; }; + 4C6433FD0534D3B800F287B2 /* csrTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = csrTemplates.h; sourceTree = ""; }; + 4C6433FE0534D3B800F287B2 /* keyTemplates.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = keyTemplates.c; sourceTree = ""; }; + 4C6433FF0534D3B800F287B2 /* ocspTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ocspTemplates.h; sourceTree = ""; }; + 4C6434000534D3B800F287B2 /* nameTemplates.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = nameTemplates.c; sourceTree = ""; }; + 4C6434010534D3B800F287B2 /* nameTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = nameTemplates.h; sourceTree = ""; }; + 4C6434020534D3B800F287B2 /* nsprPortX.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = nsprPortX.c; sourceTree = ""; }; + 4C6434030534D3B800F287B2 /* nssilckt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = nssilckt.h; sourceTree = ""; }; + 4C6434040534D3B800F287B2 /* nssilock.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = nssilock.h; sourceTree = ""; }; + 4C6434050534D3B800F287B2 /* nsslocks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = nsslocks.h; sourceTree = ""; }; + 4C6434060534D3B800F287B2 /* nssUtils.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = nssUtils.c; sourceTree = ""; }; + 4C6434070534D3B800F287B2 /* nssUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = nssUtils.h; sourceTree = ""; }; + 4C64340A0534D3B800F287B2 /* plarena.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = plarena.c; sourceTree = ""; }; + 4C64340B0534D3B800F287B2 /* plarena.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = plarena.h; sourceTree = ""; }; + 4C64340C0534D3B800F287B2 /* plarenas.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = plarenas.h; sourceTree = ""; }; + 4C64340D0534D3B800F287B2 /* plstr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = plstr.h; sourceTree = ""; }; + 4C64340E0534D3B800F287B2 /* prbit.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prbit.h; sourceTree = ""; }; + 4C64340F0534D3B800F287B2 /* prcpucfg.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prcpucfg.h; sourceTree = ""; }; + 4C6434100534D3B800F287B2 /* prcvar.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prcvar.h; sourceTree = ""; }; + 4C6434110534D3B800F287B2 /* prenv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prenv.h; sourceTree = ""; }; + 4C6434120534D3B800F287B2 /* prerr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prerr.h; sourceTree = ""; }; + 4C6434130534D3B800F287B2 /* prerror.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prerror.h; sourceTree = ""; }; + 4C6434140534D3B800F287B2 /* prinit.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prinit.h; sourceTree = ""; }; + 4C6434150534D3B800F287B2 /* prinrval.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prinrval.h; sourceTree = ""; }; + 4C6434160534D3B800F287B2 /* prlock.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prlock.h; sourceTree = ""; }; + 4C6434170534D3B800F287B2 /* prlog.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prlog.h; sourceTree = ""; }; + 4C6434180534D3B800F287B2 /* prlong.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prlong.h; sourceTree = ""; }; + 4C6434190534D3B800F287B2 /* prmem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prmem.h; sourceTree = ""; }; + 4C64341A0534D3B800F287B2 /* prmon.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prmon.h; sourceTree = ""; }; + 4C64341B0534D3B800F287B2 /* protypes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = protypes.h; sourceTree = ""; }; + 4C64341C0534D3B800F287B2 /* prthread.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prthread.h; sourceTree = ""; }; + 4C64341D0534D3B800F287B2 /* prtime.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prtime.h; sourceTree = ""; }; + 4C64341E0534D3B800F287B2 /* prtypes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prtypes.h; sourceTree = ""; }; + 4C64341F0534D3B800F287B2 /* prvrsion.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prvrsion.h; sourceTree = ""; }; + 4C6434200534D3B800F287B2 /* secasn1.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = secasn1.h; sourceTree = ""; }; + 4C6434210534D3B800F287B2 /* secasn1d.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = secasn1d.c; sourceTree = ""; }; + 4C6434220534D3B800F287B2 /* secasn1e.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = secasn1e.c; sourceTree = ""; }; + 4C6434230534D3B800F287B2 /* secasn1t.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = secasn1t.h; sourceTree = ""; }; + 4C6434240534D3B800F287B2 /* secasn1u.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = secasn1u.c; sourceTree = ""; }; + 4C6434250534D3B800F287B2 /* seccomon.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = seccomon.h; sourceTree = ""; }; + 4C6434260534D3B800F287B2 /* secerr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = secerr.h; sourceTree = ""; }; + 4C6434270534D3B800F287B2 /* secErrorStr.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = secErrorStr.c; sourceTree = ""; }; + 4C6434280534D3B800F287B2 /* SecNssCoder.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecNssCoder.cpp; sourceTree = ""; }; + 4C6434290534D3B800F287B2 /* SecNssCoder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecNssCoder.h; sourceTree = ""; }; + 4C64342A0534D3B800F287B2 /* secport.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = secport.c; sourceTree = ""; }; + 4C64342B0534D3B800F287B2 /* secport.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = secport.h; sourceTree = ""; }; + 4C64342D0534D3B800F287B2 /* X509Templates.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = X509Templates.c; sourceTree = ""; }; + 4C64342E0534D3B800F287B2 /* X509Templates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = X509Templates.h; sourceTree = ""; }; + 795CA7FF0D38013D00BAE6A2 /* libASN1.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libASN1.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 795CAACD0D3BEDBB00BAE6A2 /* pkcs7Templates.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkcs7Templates.c; sourceTree = ""; }; + 795CAACE0D3BEDBB00BAE6A2 /* pkcs7Templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pkcs7Templates.h; sourceTree = ""; }; + 795CAACF0D3BEDBB00BAE6A2 /* pkcs12Templates.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkcs12Templates.c; sourceTree = ""; }; + 795CAAD00D3BEDBB00BAE6A2 /* pkcs12Templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pkcs12Templates.h; sourceTree = ""; }; + 79EF5A730D3C1984009F5270 /* oidsalg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = oidsalg.c; sourceTree = ""; }; + 79EF5A740D3C1984009F5270 /* oidsalg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oidsalg.h; sourceTree = ""; }; + 79EF5A750D3C1984009F5270 /* oidsattr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = oidsattr.c; sourceTree = ""; }; + 79EF5A760D3C1984009F5270 /* oidsattr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oidsattr.h; sourceTree = ""; }; + 79EF5A770D3C1984009F5270 /* oidsbase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oidsbase.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 795CA7FD0D38013D00BAE6A2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 05BE7E680A37663E00C055B0 /* docs */ = { + isa = PBXGroup; + children = ( + 05BE7E6B0A37669000C055B0 /* libsecurity_asn1.plist */, + 05BE7E6C0A37669000C055B0 /* libsecurity_asn1.txt */, + ); + path = docs; + sourceTree = ""; + }; + 18B647F414D9FD4500F538BF /* config */ = { + isa = PBXGroup; + children = ( + 18B647F514D9FD4500F538BF /* base.xcconfig */, + 18B647F614D9FD4500F538BF /* debug.xcconfig */, + 18B647F714D9FD4500F538BF /* lib.xcconfig */, + 18B647F814D9FD4500F538BF /* release.xcconfig */, + ); + path = config; + sourceTree = ""; + }; + 4C6433F70534D3B800F287B2 /* lib */ = { + isa = PBXGroup; + children = ( + 05ABB7BB0989387700FA0183 /* asn1Templates.h */, + 0545C7B806502D1100543007 /* SecAsn1Coder.c */, + 0545C7B906502D1100543007 /* SecAsn1Coder.h */, + 4C6433F80534D3B800F287B2 /* SecAsn1Templates.c */, + 4C6433F90534D3B800F287B2 /* SecAsn1Templates.h */, + 0554F5B609892C980085E7C5 /* SecAsn1Types.h */, + 4C6433FA0534D3B800F287B2 /* certExtensionTemplates.c */, + 4C6433FB0534D3B800F287B2 /* certExtensionTemplates.h */, + 4C6433FC0534D3B800F287B2 /* csrTemplates.c */, + 4C6433FD0534D3B800F287B2 /* csrTemplates.h */, + 4C6433FE0534D3B800F287B2 /* keyTemplates.c */, + 0502B640068A5920006168D5 /* keyTemplates.h */, + 4C6434000534D3B800F287B2 /* nameTemplates.c */, + 4C6434010534D3B800F287B2 /* nameTemplates.h */, + 795CAACD0D3BEDBB00BAE6A2 /* pkcs7Templates.c */, + 795CAACE0D3BEDBB00BAE6A2 /* pkcs7Templates.h */, + 795CAACF0D3BEDBB00BAE6A2 /* pkcs12Templates.c */, + 795CAAD00D3BEDBB00BAE6A2 /* pkcs12Templates.h */, + 4C6434020534D3B800F287B2 /* nsprPortX.c */, + 4C6434030534D3B800F287B2 /* nssilckt.h */, + 4C6434040534D3B800F287B2 /* nssilock.h */, + 4C6434050534D3B800F287B2 /* nsslocks.h */, + 4C6434060534D3B800F287B2 /* nssUtils.c */, + 4C6434070534D3B800F287B2 /* nssUtils.h */, + 0502BF9A068B51E3006168D5 /* ocspTemplates.c */, + 4C6433FF0534D3B800F287B2 /* ocspTemplates.h */, + 4C64340A0534D3B800F287B2 /* plarena.c */, + 4C64340B0534D3B800F287B2 /* plarena.h */, + 4C64340C0534D3B800F287B2 /* plarenas.h */, + 4C64340D0534D3B800F287B2 /* plstr.h */, + 4C64340E0534D3B800F287B2 /* prbit.h */, + 4C64340F0534D3B800F287B2 /* prcpucfg.h */, + 4C6434100534D3B800F287B2 /* prcvar.h */, + 4C6434110534D3B800F287B2 /* prenv.h */, + 4C6434120534D3B800F287B2 /* prerr.h */, + 4C6434130534D3B800F287B2 /* prerror.h */, + 4C6434140534D3B800F287B2 /* prinit.h */, + 4C6434150534D3B800F287B2 /* prinrval.h */, + 4C6434160534D3B800F287B2 /* prlock.h */, + 4C6434170534D3B800F287B2 /* prlog.h */, + 4C6434180534D3B800F287B2 /* prlong.h */, + 4C6434190534D3B800F287B2 /* prmem.h */, + 4C64341A0534D3B800F287B2 /* prmon.h */, + 4C64341B0534D3B800F287B2 /* protypes.h */, + 4C64341C0534D3B800F287B2 /* prthread.h */, + 4C64341D0534D3B800F287B2 /* prtime.h */, + 4C64341E0534D3B800F287B2 /* prtypes.h */, + 4C64341F0534D3B800F287B2 /* prvrsion.h */, + 4C6434200534D3B800F287B2 /* secasn1.h */, + 4C6434210534D3B800F287B2 /* secasn1d.c */, + 4C6434220534D3B800F287B2 /* secasn1e.c */, + 4C6434230534D3B800F287B2 /* secasn1t.h */, + 4C6434240534D3B800F287B2 /* secasn1u.c */, + 4C6434250534D3B800F287B2 /* seccomon.h */, + 4C6434260534D3B800F287B2 /* secerr.h */, + 4C6434270534D3B800F287B2 /* secErrorStr.c */, + 4C6434280534D3B800F287B2 /* SecNssCoder.cpp */, + 4C6434290534D3B800F287B2 /* SecNssCoder.h */, + 4C64342A0534D3B800F287B2 /* secport.c */, + 4C64342B0534D3B800F287B2 /* secport.h */, + 4C64342D0534D3B800F287B2 /* X509Templates.c */, + 4C64342E0534D3B800F287B2 /* X509Templates.h */, + 0504B16106517A730011D5F5 /* osKeyTemplates.c */, + 0504B16206517A730011D5F5 /* osKeyTemplates.h */, + 79EF5A730D3C1984009F5270 /* oidsalg.c */, + 79EF5A740D3C1984009F5270 /* oidsalg.h */, + 79EF5A750D3C1984009F5270 /* oidsattr.c */, + 79EF5A760D3C1984009F5270 /* oidsattr.h */, + 79EF5A770D3C1984009F5270 /* oidsbase.h */, + 4C2824670F1BC75800CAADEC /* oidsocsp.c */, + 4C2824680F1BC75800CAADEC /* oidsocsp.h */, + 0545C78806502BAD00543007 /* security_asn1.exp */, + ); + path = lib; + sourceTree = ""; + }; + 9D56980803E74D6100003D05 = { + isa = PBXGroup; + children = ( + 18B647F414D9FD4500F538BF /* config */, + 4C6433F70534D3B800F287B2 /* lib */, + 05BE7E680A37663E00C055B0 /* docs */, + 9D56981D03E74E4100003D05 /* Products */, + ); + sourceTree = ""; + }; + 9D56981D03E74E4100003D05 /* Products */ = { + isa = PBXGroup; + children = ( + 795CA7FF0D38013D00BAE6A2 /* libASN1.a */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 795CA7FB0D38013D00BAE6A2 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 79BDD3490D60D4A4000D84D3 /* prbit.h in Headers */, + 79BDD34A0D60D4A4000D84D3 /* prmem.h in Headers */, + 79BDD3100D60D116000D84D3 /* plstr.h in Headers */, + 79BDD3110D60D116000D84D3 /* prlog.h in Headers */, + 79BDD30C0D60D0E5000D84D3 /* seccomon.h in Headers */, + 79BDD3420D60D2B2000D84D3 /* prerr.h in Headers */, + 79BDD33F0D60D29A000D84D3 /* prerror.h in Headers */, + 79BDD2FC0D60CF66000D84D3 /* secerr.h in Headers */, + 79EF5BA30D3D6EF4009F5270 /* secport.h in Headers */, + 798B80C10D3E8B6700AC1D04 /* secasn1.h in Headers */, + 798B80E00D3E8BFC00AC1D04 /* secasn1t.h in Headers */, + 79BDD2F60D60CF24000D84D3 /* prcpucfg.h in Headers */, + 79BDD2ED0D60CEF5000D84D3 /* prtypes.h in Headers */, + 79EF5BCA0D3D6F44009F5270 /* plarena.h in Headers */, + 79BDD3020D60CFC9000D84D3 /* protypes.h in Headers */, + 79BDD2D10D60CE82000D84D3 /* plarenas.h in Headers */, + 795CA8230D38041D00BAE6A2 /* SecAsn1Coder.h in Headers */, + 795CA8250D38041D00BAE6A2 /* SecAsn1Templates.h in Headers */, + 795CA8260D38041D00BAE6A2 /* SecAsn1Types.h in Headers */, + 795CA8280D38041D00BAE6A2 /* certExtensionTemplates.h in Headers */, + 795CA82A0D38041D00BAE6A2 /* csrTemplates.h in Headers */, + 795CA82C0D38041D00BAE6A2 /* keyTemplates.h in Headers */, + 795CA82E0D38041D00BAE6A2 /* nameTemplates.h in Headers */, + 795CA8310D38041D00BAE6A2 /* nssUtils.h in Headers */, + 795CA8330D38041D00BAE6A2 /* ocspTemplates.h in Headers */, + 795CA83A0D38041D00BAE6A2 /* X509Templates.h in Headers */, + 795CA83C0D38041D00BAE6A2 /* osKeyTemplates.h in Headers */, + 795CAAD20D3BEDBB00BAE6A2 /* pkcs7Templates.h in Headers */, + 795CAAD40D3BEDBB00BAE6A2 /* pkcs12Templates.h in Headers */, + 79EF5A790D3C1984009F5270 /* oidsalg.h in Headers */, + 79EF5A7B0D3C1984009F5270 /* oidsattr.h in Headers */, + 79EF5A7C0D3C1984009F5270 /* oidsbase.h in Headers */, + 4C28246C0F1BC75800CAADEC /* oidsocsp.h in Headers */, + 18312F9714E99A3F00F0BCAC /* SecNssCoder.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 795CA7FE0D38013D00BAE6A2 /* libASN1 */ = { + isa = PBXNativeTarget; + buildConfigurationList = 795CA8030D38017E00BAE6A2 /* Build configuration list for PBXNativeTarget "libASN1" */; + buildPhases = ( + 795CA7FB0D38013D00BAE6A2 /* Headers */, + 795CA7FC0D38013D00BAE6A2 /* Sources */, + 795CA7FD0D38013D00BAE6A2 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libASN1; + productName = libASN1; + productReference = 795CA7FF0D38013D00BAE6A2 /* libASN1.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 9D56980C03E74D6100003D05 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0600; + }; + buildConfigurationList = C23B0CEC09A298C500B7FCED /* Build configuration list for PBXProject "libsecurity_asn1" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 9D56980803E74D6100003D05; + productRefGroup = 9D56981D03E74E4100003D05 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 795CA7FE0D38013D00BAE6A2 /* libASN1 */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 795CA7FC0D38013D00BAE6A2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 79EF5BC90D3D6F44009F5270 /* plarena.c in Sources */, + 795CA8220D38041D00BAE6A2 /* SecAsn1Coder.c in Sources */, + 795CA8240D38041D00BAE6A2 /* SecAsn1Templates.c in Sources */, + 79EF5BA50D3D6EF8009F5270 /* secport.c in Sources */, + 795CA8270D38041D00BAE6A2 /* certExtensionTemplates.c in Sources */, + 795CA8290D38041D00BAE6A2 /* csrTemplates.c in Sources */, + 795CA82B0D38041D00BAE6A2 /* keyTemplates.c in Sources */, + 795CA82D0D38041D00BAE6A2 /* nameTemplates.c in Sources */, + 795CA82F0D38041D00BAE6A2 /* nsprPortX.c in Sources */, + 795CA8300D38041D00BAE6A2 /* nssUtils.c in Sources */, + 795CA8320D38041D00BAE6A2 /* ocspTemplates.c in Sources */, + 795CA8350D38041D00BAE6A2 /* secasn1d.c in Sources */, + 795CA8360D38041D00BAE6A2 /* secasn1e.c in Sources */, + 795CA8380D38041D00BAE6A2 /* secasn1u.c in Sources */, + 795CA8390D38041D00BAE6A2 /* X509Templates.c in Sources */, + 795CA83B0D38041D00BAE6A2 /* osKeyTemplates.c in Sources */, + 795CAAD10D3BEDBB00BAE6A2 /* pkcs7Templates.c in Sources */, + 795CAAD30D3BEDBB00BAE6A2 /* pkcs12Templates.c in Sources */, + 79EF5A780D3C1984009F5270 /* oidsalg.c in Sources */, + 79EF5A7A0D3C1984009F5270 /* oidsattr.c in Sources */, + 4C28246B0F1BC75800CAADEC /* oidsocsp.c in Sources */, + 1885B45314D9BB1A00519375 /* SecNssCoder.cpp in Sources */, + 18B6B2A714DB73A000EDDE5F /* secErrorStr.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 795CA8090D3801A700BAE6A2 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18B647F614D9FD4500F538BF /* debug.xcconfig */; + buildSettings = { + CLANG_STATIC_ANALYZER_MODE = deep; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + RUN_CLANG_STATIC_ANALYZER = YES; + }; + name = Debug; + }; + 795CA80D0D3801A700BAE6A2 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18B647F714D9FD4500F538BF /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + LIBRARY_STYLE = STATIC; + }; + name = Debug; + }; + 795CA8180D3801A900BAE6A2 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18B647F814D9FD4500F538BF /* release.xcconfig */; + buildSettings = { + CLANG_STATIC_ANALYZER_MODE = deep; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + RUN_CLANG_STATIC_ANALYZER = YES; + }; + name = Release; + }; + 795CA81C0D3801A900BAE6A2 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18B647F714D9FD4500F538BF /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + LIBRARY_STYLE = STATIC; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 795CA8030D38017E00BAE6A2 /* Build configuration list for PBXNativeTarget "libASN1" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 795CA80D0D3801A700BAE6A2 /* Debug */, + 795CA81C0D3801A900BAE6A2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C23B0CEC09A298C500B7FCED /* Build configuration list for PBXProject "libsecurity_asn1" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 795CA8090D3801A700BAE6A2 /* Debug */, + 795CA8180D3801A900BAE6A2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 9D56980C03E74D6100003D05 /* Project object */; +} diff --git a/libsecurity_asn1/security_asn1 b/Security/libsecurity_asn1/security_asn1 similarity index 100% rename from libsecurity_asn1/security_asn1 rename to Security/libsecurity_asn1/security_asn1 diff --git a/libsecurity_authorization/APPLE_LICENSE b/Security/libsecurity_authorization/APPLE_LICENSE similarity index 100% rename from libsecurity_authorization/APPLE_LICENSE rename to Security/libsecurity_authorization/APPLE_LICENSE diff --git a/libsecurity_authorization/Info-security_authorization.plist b/Security/libsecurity_authorization/Info-security_authorization.plist similarity index 100% rename from libsecurity_authorization/Info-security_authorization.plist rename to Security/libsecurity_authorization/Info-security_authorization.plist diff --git a/libsecurity_authorization/lib/AuthSession.h b/Security/libsecurity_authorization/lib/AuthSession.h similarity index 99% rename from libsecurity_authorization/lib/AuthSession.h rename to Security/libsecurity_authorization/lib/AuthSession.h index 65c01918..90b9763f 100644 --- a/libsecurity_authorization/lib/AuthSession.h +++ b/Security/libsecurity_authorization/lib/AuthSession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2003,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_authorization/lib/Authorization.c b/Security/libsecurity_authorization/lib/Authorization.c similarity index 99% rename from libsecurity_authorization/lib/Authorization.c rename to Security/libsecurity_authorization/lib/Authorization.c index dde4d1aa..468668e4 100644 --- a/libsecurity_authorization/lib/Authorization.c +++ b/Security/libsecurity_authorization/lib/Authorization.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ +/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ #include "Authorization.h" #include "authd_private.h" diff --git a/libsecurity_authorization/lib/Authorization.cpp b/Security/libsecurity_authorization/lib/Authorization.cpp similarity index 99% rename from libsecurity_authorization/lib/Authorization.cpp rename to Security/libsecurity_authorization/lib/Authorization.cpp index 2e6af978..71db80cf 100644 --- a/libsecurity_authorization/lib/Authorization.cpp +++ b/Security/libsecurity_authorization/lib/Authorization.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_authorization/lib/Authorization.h b/Security/libsecurity_authorization/lib/Authorization.h similarity index 99% rename from libsecurity_authorization/lib/Authorization.h rename to Security/libsecurity_authorization/lib/Authorization.h index fde3207d..16f5d9c8 100644 --- a/libsecurity_authorization/lib/Authorization.h +++ b/Security/libsecurity_authorization/lib/Authorization.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2007,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_authorization/lib/AuthorizationDB.h b/Security/libsecurity_authorization/lib/AuthorizationDB.h similarity index 98% rename from libsecurity_authorization/lib/AuthorizationDB.h rename to Security/libsecurity_authorization/lib/AuthorizationDB.h index 326f870d..7a864e83 100644 --- a/libsecurity_authorization/lib/AuthorizationDB.h +++ b/Security/libsecurity_authorization/lib/AuthorizationDB.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_authorization/lib/AuthorizationPlugin.h b/Security/libsecurity_authorization/lib/AuthorizationPlugin.h similarity index 99% rename from libsecurity_authorization/lib/AuthorizationPlugin.h rename to Security/libsecurity_authorization/lib/AuthorizationPlugin.h index 746a8c00..6e31926a 100644 --- a/libsecurity_authorization/lib/AuthorizationPlugin.h +++ b/Security/libsecurity_authorization/lib/AuthorizationPlugin.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2002,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2001-2002,2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_authorization/lib/AuthorizationPriv.h b/Security/libsecurity_authorization/lib/AuthorizationPriv.h similarity index 99% rename from libsecurity_authorization/lib/AuthorizationPriv.h rename to Security/libsecurity_authorization/lib/AuthorizationPriv.h index 82a98aee..092f7a12 100644 --- a/libsecurity_authorization/lib/AuthorizationPriv.h +++ b/Security/libsecurity_authorization/lib/AuthorizationPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_authorization/lib/AuthorizationTags.h b/Security/libsecurity_authorization/lib/AuthorizationTags.h similarity index 98% rename from libsecurity_authorization/lib/AuthorizationTags.h rename to Security/libsecurity_authorization/lib/AuthorizationTags.h index 22876b79..f2018dd9 100644 --- a/libsecurity_authorization/lib/AuthorizationTags.h +++ b/Security/libsecurity_authorization/lib/AuthorizationTags.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_authorization/lib/AuthorizationTagsPriv.h b/Security/libsecurity_authorization/lib/AuthorizationTagsPriv.h similarity index 99% rename from libsecurity_authorization/lib/AuthorizationTagsPriv.h rename to Security/libsecurity_authorization/lib/AuthorizationTagsPriv.h index c3d52ba7..0e11f023 100644 --- a/libsecurity_authorization/lib/AuthorizationTagsPriv.h +++ b/Security/libsecurity_authorization/lib/AuthorizationTagsPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_authorization/lib/privPort.h b/Security/libsecurity_authorization/lib/privPort.h similarity index 95% rename from libsecurity_authorization/lib/privPort.h rename to Security/libsecurity_authorization/lib/privPort.h index cd98665f..205f325e 100644 --- a/libsecurity_authorization/lib/privPort.h +++ b/Security/libsecurity_authorization/lib/privPort.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_authorization/lib/security_authorization.exp b/Security/libsecurity_authorization/lib/security_authorization.exp similarity index 95% rename from libsecurity_authorization/lib/security_authorization.exp rename to Security/libsecurity_authorization/lib/security_authorization.exp index 8a88e4e7..70831acd 100644 --- a/libsecurity_authorization/lib/security_authorization.exp +++ b/Security/libsecurity_authorization/lib/security_authorization.exp @@ -1,5 +1,5 @@ # -# Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. +# Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. # # @APPLE_LICENSE_HEADER_START@ # diff --git a/libsecurity_authorization/lib/trampolineClient.cpp b/Security/libsecurity_authorization/lib/trampolineClient.cpp similarity index 99% rename from libsecurity_authorization/lib/trampolineClient.cpp rename to Security/libsecurity_authorization/lib/trampolineClient.cpp index cfc71a79..a640f0a0 100644 --- a/libsecurity_authorization/lib/trampolineClient.cpp +++ b/Security/libsecurity_authorization/lib/trampolineClient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_authorization/lib/trampolineServer.cpp b/Security/libsecurity_authorization/lib/trampolineServer.cpp similarity index 96% rename from libsecurity_authorization/lib/trampolineServer.cpp rename to Security/libsecurity_authorization/lib/trampolineServer.cpp index d886ba51..bf25a801 100644 --- a/libsecurity_authorization/lib/trampolineServer.cpp +++ b/Security/libsecurity_authorization/lib/trampolineServer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_authorization/libsecurity_authorization.xcodeproj/project.pbxproj b/Security/libsecurity_authorization/libsecurity_authorization.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_authorization/libsecurity_authorization.xcodeproj/project.pbxproj rename to Security/libsecurity_authorization/libsecurity_authorization.xcodeproj/project.pbxproj diff --git a/libsecurity_cdsa_client/Info-security_cdsa_client.plist b/Security/libsecurity_cdsa_client/Info-security_cdsa_client.plist similarity index 100% rename from libsecurity_cdsa_client/Info-security_cdsa_client.plist rename to Security/libsecurity_cdsa_client/Info-security_cdsa_client.plist diff --git a/libsecurity_cdsa_client/lib/DLDBList.cpp b/Security/libsecurity_cdsa_client/lib/DLDBList.cpp similarity index 96% rename from libsecurity_cdsa_client/lib/DLDBList.cpp rename to Security/libsecurity_cdsa_client/lib/DLDBList.cpp index 1deb70d9..1fede0e1 100644 --- a/libsecurity_cdsa_client/lib/DLDBList.cpp +++ b/Security/libsecurity_cdsa_client/lib/DLDBList.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/DLDBList.h b/Security/libsecurity_cdsa_client/lib/DLDBList.h similarity index 97% rename from libsecurity_cdsa_client/lib/DLDBList.h rename to Security/libsecurity_cdsa_client/lib/DLDBList.h index ffca3e2a..3a85a3d2 100644 --- a/libsecurity_cdsa_client/lib/DLDBList.h +++ b/Security/libsecurity_cdsa_client/lib/DLDBList.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/aclclient.cpp b/Security/libsecurity_cdsa_client/lib/aclclient.cpp similarity index 99% rename from libsecurity_cdsa_client/lib/aclclient.cpp rename to Security/libsecurity_cdsa_client/lib/aclclient.cpp index b2c8a383..988943fd 100644 --- a/libsecurity_cdsa_client/lib/aclclient.cpp +++ b/Security/libsecurity_cdsa_client/lib/aclclient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2007,2011 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/aclclient.h b/Security/libsecurity_cdsa_client/lib/aclclient.h similarity index 98% rename from libsecurity_cdsa_client/lib/aclclient.h rename to Security/libsecurity_cdsa_client/lib/aclclient.h index b3db4856..00b5b513 100644 --- a/libsecurity_cdsa_client/lib/aclclient.h +++ b/Security/libsecurity_cdsa_client/lib/aclclient.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2007,2011 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/clclient.cpp b/Security/libsecurity_cdsa_client/lib/clclient.cpp similarity index 95% rename from libsecurity_cdsa_client/lib/clclient.cpp rename to Security/libsecurity_cdsa_client/lib/clclient.cpp index 33e0c55d..c816acd6 100644 --- a/libsecurity_cdsa_client/lib/clclient.cpp +++ b/Security/libsecurity_cdsa_client/lib/clclient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/clclient.h b/Security/libsecurity_cdsa_client/lib/clclient.h similarity index 96% rename from libsecurity_cdsa_client/lib/clclient.h rename to Security/libsecurity_cdsa_client/lib/clclient.h index 4b2bbf75..aa68fa81 100644 --- a/libsecurity_cdsa_client/lib/clclient.h +++ b/Security/libsecurity_cdsa_client/lib/clclient.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/cryptoclient.cpp b/Security/libsecurity_cdsa_client/lib/cryptoclient.cpp similarity index 97% rename from libsecurity_cdsa_client/lib/cryptoclient.cpp rename to Security/libsecurity_cdsa_client/lib/cryptoclient.cpp index 3a4bb7e7..067113f7 100644 --- a/libsecurity_cdsa_client/lib/cryptoclient.cpp +++ b/Security/libsecurity_cdsa_client/lib/cryptoclient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/cryptoclient.h b/Security/libsecurity_cdsa_client/lib/cryptoclient.h similarity index 97% rename from libsecurity_cdsa_client/lib/cryptoclient.h rename to Security/libsecurity_cdsa_client/lib/cryptoclient.h index 707bcd32..d708ca16 100644 --- a/libsecurity_cdsa_client/lib/cryptoclient.h +++ b/Security/libsecurity_cdsa_client/lib/cryptoclient.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/cspclient.cpp b/Security/libsecurity_cdsa_client/lib/cspclient.cpp similarity index 98% rename from libsecurity_cdsa_client/lib/cspclient.cpp rename to Security/libsecurity_cdsa_client/lib/cspclient.cpp index 8f189336..186c2fa2 100644 --- a/libsecurity_cdsa_client/lib/cspclient.cpp +++ b/Security/libsecurity_cdsa_client/lib/cspclient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/cspclient.h b/Security/libsecurity_cdsa_client/lib/cspclient.h similarity index 99% rename from libsecurity_cdsa_client/lib/cspclient.h rename to Security/libsecurity_cdsa_client/lib/cspclient.h index add128b5..67c35d70 100644 --- a/libsecurity_cdsa_client/lib/cspclient.h +++ b/Security/libsecurity_cdsa_client/lib/cspclient.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/cssmclient.cpp b/Security/libsecurity_cdsa_client/lib/cssmclient.cpp similarity index 99% rename from libsecurity_cdsa_client/lib/cssmclient.cpp rename to Security/libsecurity_cdsa_client/lib/cssmclient.cpp index dc091bb5..05a59c49 100644 --- a/libsecurity_cdsa_client/lib/cssmclient.cpp +++ b/Security/libsecurity_cdsa_client/lib/cssmclient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/cssmclient.h b/Security/libsecurity_cdsa_client/lib/cssmclient.h similarity index 99% rename from libsecurity_cdsa_client/lib/cssmclient.h rename to Security/libsecurity_cdsa_client/lib/cssmclient.h index faa2fe8d..53719b82 100644 --- a/libsecurity_cdsa_client/lib/cssmclient.h +++ b/Security/libsecurity_cdsa_client/lib/cssmclient.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/dl_standard.cpp b/Security/libsecurity_cdsa_client/lib/dl_standard.cpp similarity index 98% rename from libsecurity_cdsa_client/lib/dl_standard.cpp rename to Security/libsecurity_cdsa_client/lib/dl_standard.cpp index 961105a8..4c11ba11 100644 --- a/libsecurity_cdsa_client/lib/dl_standard.cpp +++ b/Security/libsecurity_cdsa_client/lib/dl_standard.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/dl_standard.h b/Security/libsecurity_cdsa_client/lib/dl_standard.h similarity index 98% rename from libsecurity_cdsa_client/lib/dl_standard.h rename to Security/libsecurity_cdsa_client/lib/dl_standard.h index 130fcfaf..b39cdd90 100644 --- a/libsecurity_cdsa_client/lib/dl_standard.h +++ b/Security/libsecurity_cdsa_client/lib/dl_standard.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/dlclient.cpp b/Security/libsecurity_cdsa_client/lib/dlclient.cpp similarity index 99% rename from libsecurity_cdsa_client/lib/dlclient.cpp rename to Security/libsecurity_cdsa_client/lib/dlclient.cpp index 31510a53..882fde1e 100644 --- a/libsecurity_cdsa_client/lib/dlclient.cpp +++ b/Security/libsecurity_cdsa_client/lib/dlclient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -27,10 +27,11 @@ using namespace CssmClient; - +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-const-variable" // blob type for blobs created by these classes -- done so that we can change the formats later const uint32 kBlobType = 0x1; - +#pragma clang diagnostic pop // // Abstract classes diff --git a/libsecurity_cdsa_client/lib/dlclient.h b/Security/libsecurity_cdsa_client/lib/dlclient.h similarity index 99% rename from libsecurity_cdsa_client/lib/dlclient.h rename to Security/libsecurity_cdsa_client/lib/dlclient.h index a26d6915..23c242c2 100644 --- a/libsecurity_cdsa_client/lib/dlclient.h +++ b/Security/libsecurity_cdsa_client/lib/dlclient.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/dlclientpriv.cpp b/Security/libsecurity_cdsa_client/lib/dlclientpriv.cpp similarity index 95% rename from libsecurity_cdsa_client/lib/dlclientpriv.cpp rename to Security/libsecurity_cdsa_client/lib/dlclientpriv.cpp index 560c9db0..96d609bb 100644 --- a/libsecurity_cdsa_client/lib/dlclientpriv.cpp +++ b/Security/libsecurity_cdsa_client/lib/dlclientpriv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/dliterators.cpp b/Security/libsecurity_cdsa_client/lib/dliterators.cpp similarity index 98% rename from libsecurity_cdsa_client/lib/dliterators.cpp rename to Security/libsecurity_cdsa_client/lib/dliterators.cpp index 18617f83..817ae646 100644 --- a/libsecurity_cdsa_client/lib/dliterators.cpp +++ b/Security/libsecurity_cdsa_client/lib/dliterators.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/dliterators.h b/Security/libsecurity_cdsa_client/lib/dliterators.h similarity index 99% rename from libsecurity_cdsa_client/lib/dliterators.h rename to Security/libsecurity_cdsa_client/lib/dliterators.h index e93b6c13..5512c3a5 100644 --- a/libsecurity_cdsa_client/lib/dliterators.h +++ b/Security/libsecurity_cdsa_client/lib/dliterators.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/dlquery.cpp b/Security/libsecurity_cdsa_client/lib/dlquery.cpp similarity index 98% rename from libsecurity_cdsa_client/lib/dlquery.cpp rename to Security/libsecurity_cdsa_client/lib/dlquery.cpp index 5b0ce87c..f0d2bbac 100644 --- a/libsecurity_cdsa_client/lib/dlquery.cpp +++ b/Security/libsecurity_cdsa_client/lib/dlquery.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/dlquery.h b/Security/libsecurity_cdsa_client/lib/dlquery.h similarity index 98% rename from libsecurity_cdsa_client/lib/dlquery.h rename to Security/libsecurity_cdsa_client/lib/dlquery.h index a7d79384..dc976b1e 100644 --- a/libsecurity_cdsa_client/lib/dlquery.h +++ b/Security/libsecurity_cdsa_client/lib/dlquery.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/genkey.cpp b/Security/libsecurity_cdsa_client/lib/genkey.cpp similarity index 97% rename from libsecurity_cdsa_client/lib/genkey.cpp rename to Security/libsecurity_cdsa_client/lib/genkey.cpp index aabcb225..ab881784 100644 --- a/libsecurity_cdsa_client/lib/genkey.cpp +++ b/Security/libsecurity_cdsa_client/lib/genkey.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/genkey.h b/Security/libsecurity_cdsa_client/lib/genkey.h similarity index 97% rename from libsecurity_cdsa_client/lib/genkey.h rename to Security/libsecurity_cdsa_client/lib/genkey.h index 30e3248a..4d112f3f 100644 --- a/libsecurity_cdsa_client/lib/genkey.h +++ b/Security/libsecurity_cdsa_client/lib/genkey.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/keychainacl.cpp b/Security/libsecurity_cdsa_client/lib/keychainacl.cpp similarity index 98% rename from libsecurity_cdsa_client/lib/keychainacl.cpp rename to Security/libsecurity_cdsa_client/lib/keychainacl.cpp index 58ddbb8a..271774c9 100644 --- a/libsecurity_cdsa_client/lib/keychainacl.cpp +++ b/Security/libsecurity_cdsa_client/lib/keychainacl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/keychainacl.h b/Security/libsecurity_cdsa_client/lib/keychainacl.h similarity index 97% rename from libsecurity_cdsa_client/lib/keychainacl.h rename to Security/libsecurity_cdsa_client/lib/keychainacl.h index 9e7748d8..05e1354d 100644 --- a/libsecurity_cdsa_client/lib/keychainacl.h +++ b/Security/libsecurity_cdsa_client/lib/keychainacl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/keyclient.cpp b/Security/libsecurity_cdsa_client/lib/keyclient.cpp similarity index 97% rename from libsecurity_cdsa_client/lib/keyclient.cpp rename to Security/libsecurity_cdsa_client/lib/keyclient.cpp index 77e56255..5bf04d6e 100644 --- a/libsecurity_cdsa_client/lib/keyclient.cpp +++ b/Security/libsecurity_cdsa_client/lib/keyclient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/keyclient.h b/Security/libsecurity_cdsa_client/lib/keyclient.h similarity index 98% rename from libsecurity_cdsa_client/lib/keyclient.h rename to Security/libsecurity_cdsa_client/lib/keyclient.h index 0f2e6040..36e332c7 100644 --- a/libsecurity_cdsa_client/lib/keyclient.h +++ b/Security/libsecurity_cdsa_client/lib/keyclient.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/macclient.cpp b/Security/libsecurity_cdsa_client/lib/macclient.cpp similarity index 96% rename from libsecurity_cdsa_client/lib/macclient.cpp rename to Security/libsecurity_cdsa_client/lib/macclient.cpp index c821cc99..63ddacc1 100644 --- a/libsecurity_cdsa_client/lib/macclient.cpp +++ b/Security/libsecurity_cdsa_client/lib/macclient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/macclient.h b/Security/libsecurity_cdsa_client/lib/macclient.h similarity index 97% rename from libsecurity_cdsa_client/lib/macclient.h rename to Security/libsecurity_cdsa_client/lib/macclient.h index 4621d5f2..10635b15 100644 --- a/libsecurity_cdsa_client/lib/macclient.h +++ b/Security/libsecurity_cdsa_client/lib/macclient.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/mds_standard.cpp b/Security/libsecurity_cdsa_client/lib/mds_standard.cpp similarity index 99% rename from libsecurity_cdsa_client/lib/mds_standard.cpp rename to Security/libsecurity_cdsa_client/lib/mds_standard.cpp index 5c2eb46a..8d709150 100644 --- a/libsecurity_cdsa_client/lib/mds_standard.cpp +++ b/Security/libsecurity_cdsa_client/lib/mds_standard.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/mds_standard.h b/Security/libsecurity_cdsa_client/lib/mds_standard.h similarity index 98% rename from libsecurity_cdsa_client/lib/mds_standard.h rename to Security/libsecurity_cdsa_client/lib/mds_standard.h index 6dc30900..0f5bd344 100644 --- a/libsecurity_cdsa_client/lib/mds_standard.h +++ b/Security/libsecurity_cdsa_client/lib/mds_standard.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/mdsclient.cpp b/Security/libsecurity_cdsa_client/lib/mdsclient.cpp similarity index 98% rename from libsecurity_cdsa_client/lib/mdsclient.cpp rename to Security/libsecurity_cdsa_client/lib/mdsclient.cpp index 16eade72..15e8ae32 100644 --- a/libsecurity_cdsa_client/lib/mdsclient.cpp +++ b/Security/libsecurity_cdsa_client/lib/mdsclient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/mdsclient.h b/Security/libsecurity_cdsa_client/lib/mdsclient.h similarity index 98% rename from libsecurity_cdsa_client/lib/mdsclient.h rename to Security/libsecurity_cdsa_client/lib/mdsclient.h index fcc0aa4e..96a381ed 100644 --- a/libsecurity_cdsa_client/lib/mdsclient.h +++ b/Security/libsecurity_cdsa_client/lib/mdsclient.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/multidldb.cpp b/Security/libsecurity_cdsa_client/lib/multidldb.cpp similarity index 98% rename from libsecurity_cdsa_client/lib/multidldb.cpp rename to Security/libsecurity_cdsa_client/lib/multidldb.cpp index 03829193..596d01c7 100644 --- a/libsecurity_cdsa_client/lib/multidldb.cpp +++ b/Security/libsecurity_cdsa_client/lib/multidldb.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/multidldb.h b/Security/libsecurity_cdsa_client/lib/multidldb.h similarity index 97% rename from libsecurity_cdsa_client/lib/multidldb.h rename to Security/libsecurity_cdsa_client/lib/multidldb.h index efb33649..fb5fd909 100644 --- a/libsecurity_cdsa_client/lib/multidldb.h +++ b/Security/libsecurity_cdsa_client/lib/multidldb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/securestorage.cpp b/Security/libsecurity_cdsa_client/lib/securestorage.cpp similarity index 99% rename from libsecurity_cdsa_client/lib/securestorage.cpp rename to Security/libsecurity_cdsa_client/lib/securestorage.cpp index 6918bc87..6fb56f0d 100644 --- a/libsecurity_cdsa_client/lib/securestorage.cpp +++ b/Security/libsecurity_cdsa_client/lib/securestorage.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/securestorage.h b/Security/libsecurity_cdsa_client/lib/securestorage.h similarity index 99% rename from libsecurity_cdsa_client/lib/securestorage.h rename to Security/libsecurity_cdsa_client/lib/securestorage.h index 2771f4bb..7474fbfd 100644 --- a/libsecurity_cdsa_client/lib/securestorage.h +++ b/Security/libsecurity_cdsa_client/lib/securestorage.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/signclient.cpp b/Security/libsecurity_cdsa_client/lib/signclient.cpp similarity index 96% rename from libsecurity_cdsa_client/lib/signclient.cpp rename to Security/libsecurity_cdsa_client/lib/signclient.cpp index 39c7a02f..d7744a65 100644 --- a/libsecurity_cdsa_client/lib/signclient.cpp +++ b/Security/libsecurity_cdsa_client/lib/signclient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/signclient.h b/Security/libsecurity_cdsa_client/lib/signclient.h similarity index 97% rename from libsecurity_cdsa_client/lib/signclient.h rename to Security/libsecurity_cdsa_client/lib/signclient.h index a0e2fe0b..81c90dbb 100644 --- a/libsecurity_cdsa_client/lib/signclient.h +++ b/Security/libsecurity_cdsa_client/lib/signclient.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/tpclient.cpp b/Security/libsecurity_cdsa_client/lib/tpclient.cpp similarity index 97% rename from libsecurity_cdsa_client/lib/tpclient.cpp rename to Security/libsecurity_cdsa_client/lib/tpclient.cpp index 4e2f779b..f64fef31 100644 --- a/libsecurity_cdsa_client/lib/tpclient.cpp +++ b/Security/libsecurity_cdsa_client/lib/tpclient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/tpclient.h b/Security/libsecurity_cdsa_client/lib/tpclient.h similarity index 97% rename from libsecurity_cdsa_client/lib/tpclient.h rename to Security/libsecurity_cdsa_client/lib/tpclient.h index a592cd61..ca28f2a4 100644 --- a/libsecurity_cdsa_client/lib/tpclient.h +++ b/Security/libsecurity_cdsa_client/lib/tpclient.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/wrapkey.cpp b/Security/libsecurity_cdsa_client/lib/wrapkey.cpp similarity index 98% rename from libsecurity_cdsa_client/lib/wrapkey.cpp rename to Security/libsecurity_cdsa_client/lib/wrapkey.cpp index 68cb6504..541b7748 100644 --- a/libsecurity_cdsa_client/lib/wrapkey.cpp +++ b/Security/libsecurity_cdsa_client/lib/wrapkey.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/lib/wrapkey.h b/Security/libsecurity_cdsa_client/lib/wrapkey.h similarity index 98% rename from libsecurity_cdsa_client/lib/wrapkey.h rename to Security/libsecurity_cdsa_client/lib/wrapkey.h index 9b75870f..41d7c752 100644 --- a/libsecurity_cdsa_client/lib/wrapkey.h +++ b/Security/libsecurity_cdsa_client/lib/wrapkey.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_client/libsecurity_cdsa_client.xcodeproj/project.pbxproj b/Security/libsecurity_cdsa_client/libsecurity_cdsa_client.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_cdsa_client/libsecurity_cdsa_client.xcodeproj/project.pbxproj rename to Security/libsecurity_cdsa_client/libsecurity_cdsa_client.xcodeproj/project.pbxproj diff --git a/libsecurity_cdsa_plugin/Info-security_cdsa_plugin.plist b/Security/libsecurity_cdsa_plugin/Info-security_cdsa_plugin.plist similarity index 100% rename from libsecurity_cdsa_plugin/Info-security_cdsa_plugin.plist rename to Security/libsecurity_cdsa_plugin/Info-security_cdsa_plugin.plist diff --git a/libsecurity_cdsa_plugin/lib/ACsession.h b/Security/libsecurity_cdsa_plugin/lib/ACsession.h similarity index 96% rename from libsecurity_cdsa_plugin/lib/ACsession.h rename to Security/libsecurity_cdsa_plugin/lib/ACsession.h index 67ad37f6..bf2c4fca 100644 --- a/libsecurity_cdsa_plugin/lib/ACsession.h +++ b/Security/libsecurity_cdsa_plugin/lib/ACsession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_plugin/lib/CLsession.h b/Security/libsecurity_cdsa_plugin/lib/CLsession.h similarity index 96% rename from libsecurity_cdsa_plugin/lib/CLsession.h rename to Security/libsecurity_cdsa_plugin/lib/CLsession.h index 8d9ff050..d53c53fa 100644 --- a/libsecurity_cdsa_plugin/lib/CLsession.h +++ b/Security/libsecurity_cdsa_plugin/lib/CLsession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_plugin/lib/CSPsession.cpp b/Security/libsecurity_cdsa_plugin/lib/CSPsession.cpp similarity index 99% rename from libsecurity_cdsa_plugin/lib/CSPsession.cpp rename to Security/libsecurity_cdsa_plugin/lib/CSPsession.cpp index d3eb9608..41f4ee85 100644 --- a/libsecurity_cdsa_plugin/lib/CSPsession.cpp +++ b/Security/libsecurity_cdsa_plugin/lib/CSPsession.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_plugin/lib/CSPsession.h b/Security/libsecurity_cdsa_plugin/lib/CSPsession.h similarity index 99% rename from libsecurity_cdsa_plugin/lib/CSPsession.h rename to Security/libsecurity_cdsa_plugin/lib/CSPsession.h index 74234bdb..b755bf77 100644 --- a/libsecurity_cdsa_plugin/lib/CSPsession.h +++ b/Security/libsecurity_cdsa_plugin/lib/CSPsession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_plugin/lib/DLsession.cpp b/Security/libsecurity_cdsa_plugin/lib/DLsession.cpp similarity index 97% rename from libsecurity_cdsa_plugin/lib/DLsession.cpp rename to Security/libsecurity_cdsa_plugin/lib/DLsession.cpp index 508d4712..89a88690 100644 --- a/libsecurity_cdsa_plugin/lib/DLsession.cpp +++ b/Security/libsecurity_cdsa_plugin/lib/DLsession.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_plugin/lib/DLsession.h b/Security/libsecurity_cdsa_plugin/lib/DLsession.h similarity index 96% rename from libsecurity_cdsa_plugin/lib/DLsession.h rename to Security/libsecurity_cdsa_plugin/lib/DLsession.h index bd1b221c..67c35ecb 100644 --- a/libsecurity_cdsa_plugin/lib/DLsession.h +++ b/Security/libsecurity_cdsa_plugin/lib/DLsession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_plugin/lib/Database.cpp b/Security/libsecurity_cdsa_plugin/lib/Database.cpp similarity index 99% rename from libsecurity_cdsa_plugin/lib/Database.cpp rename to Security/libsecurity_cdsa_plugin/lib/Database.cpp index 2343108b..ef7da434 100644 --- a/libsecurity_cdsa_plugin/lib/Database.cpp +++ b/Security/libsecurity_cdsa_plugin/lib/Database.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_plugin/lib/Database.h b/Security/libsecurity_cdsa_plugin/lib/Database.h similarity index 99% rename from libsecurity_cdsa_plugin/lib/Database.h rename to Security/libsecurity_cdsa_plugin/lib/Database.h index 52753ae3..a674243d 100644 --- a/libsecurity_cdsa_plugin/lib/Database.h +++ b/Security/libsecurity_cdsa_plugin/lib/Database.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_plugin/lib/DatabaseSession.cpp b/Security/libsecurity_cdsa_plugin/lib/DatabaseSession.cpp similarity index 99% rename from libsecurity_cdsa_plugin/lib/DatabaseSession.cpp rename to Security/libsecurity_cdsa_plugin/lib/DatabaseSession.cpp index 5c0b2ac6..637806ba 100644 --- a/libsecurity_cdsa_plugin/lib/DatabaseSession.cpp +++ b/Security/libsecurity_cdsa_plugin/lib/DatabaseSession.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_plugin/lib/DatabaseSession.h b/Security/libsecurity_cdsa_plugin/lib/DatabaseSession.h similarity index 98% rename from libsecurity_cdsa_plugin/lib/DatabaseSession.h rename to Security/libsecurity_cdsa_plugin/lib/DatabaseSession.h index 9e65d8b4..46d22535 100644 --- a/libsecurity_cdsa_plugin/lib/DatabaseSession.h +++ b/Security/libsecurity_cdsa_plugin/lib/DatabaseSession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_plugin/lib/DbContext.cpp b/Security/libsecurity_cdsa_plugin/lib/DbContext.cpp similarity index 95% rename from libsecurity_cdsa_plugin/lib/DbContext.cpp rename to Security/libsecurity_cdsa_plugin/lib/DbContext.cpp index 43461b9e..51810fae 100644 --- a/libsecurity_cdsa_plugin/lib/DbContext.cpp +++ b/Security/libsecurity_cdsa_plugin/lib/DbContext.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_plugin/lib/DbContext.h b/Security/libsecurity_cdsa_plugin/lib/DbContext.h similarity index 97% rename from libsecurity_cdsa_plugin/lib/DbContext.h rename to Security/libsecurity_cdsa_plugin/lib/DbContext.h index d5877195..e3df05c4 100644 --- a/libsecurity_cdsa_plugin/lib/DbContext.h +++ b/Security/libsecurity_cdsa_plugin/lib/DbContext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_plugin/lib/TPsession.h b/Security/libsecurity_cdsa_plugin/lib/TPsession.h similarity index 96% rename from libsecurity_cdsa_plugin/lib/TPsession.h rename to Security/libsecurity_cdsa_plugin/lib/TPsession.h index 1aa72a7d..e95a869e 100644 --- a/libsecurity_cdsa_plugin/lib/TPsession.h +++ b/Security/libsecurity_cdsa_plugin/lib/TPsession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_plugin/lib/c++plugin.h b/Security/libsecurity_cdsa_plugin/lib/c++plugin.h similarity index 95% rename from libsecurity_cdsa_plugin/lib/c++plugin.h rename to Security/libsecurity_cdsa_plugin/lib/c++plugin.h index d272895c..d59e41d5 100644 --- a/libsecurity_cdsa_plugin/lib/c++plugin.h +++ b/Security/libsecurity_cdsa_plugin/lib/c++plugin.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_plugin/lib/csputilities.cpp b/Security/libsecurity_cdsa_plugin/lib/csputilities.cpp similarity index 98% rename from libsecurity_cdsa_plugin/lib/csputilities.cpp rename to Security/libsecurity_cdsa_plugin/lib/csputilities.cpp index 467cdd5f..e0d78ff1 100644 --- a/libsecurity_cdsa_plugin/lib/csputilities.cpp +++ b/Security/libsecurity_cdsa_plugin/lib/csputilities.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_plugin/lib/cssmplugin.cpp b/Security/libsecurity_cdsa_plugin/lib/cssmplugin.cpp similarity index 98% rename from libsecurity_cdsa_plugin/lib/cssmplugin.cpp rename to Security/libsecurity_cdsa_plugin/lib/cssmplugin.cpp index 36597e7e..c8680c4b 100644 --- a/libsecurity_cdsa_plugin/lib/cssmplugin.cpp +++ b/Security/libsecurity_cdsa_plugin/lib/cssmplugin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_plugin/lib/cssmplugin.h b/Security/libsecurity_cdsa_plugin/lib/cssmplugin.h similarity index 98% rename from libsecurity_cdsa_plugin/lib/cssmplugin.h rename to Security/libsecurity_cdsa_plugin/lib/cssmplugin.h index 294a3a8a..f8113c7c 100644 --- a/libsecurity_cdsa_plugin/lib/cssmplugin.h +++ b/Security/libsecurity_cdsa_plugin/lib/cssmplugin.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_plugin/lib/generator.cfg b/Security/libsecurity_cdsa_plugin/lib/generator.cfg similarity index 100% rename from libsecurity_cdsa_plugin/lib/generator.cfg rename to Security/libsecurity_cdsa_plugin/lib/generator.cfg diff --git a/libsecurity_cdsa_plugin/lib/generator.mk b/Security/libsecurity_cdsa_plugin/lib/generator.mk similarity index 100% rename from libsecurity_cdsa_plugin/lib/generator.mk rename to Security/libsecurity_cdsa_plugin/lib/generator.mk diff --git a/libsecurity_cdsa_plugin/lib/generator.pl b/Security/libsecurity_cdsa_plugin/lib/generator.pl similarity index 100% rename from libsecurity_cdsa_plugin/lib/generator.pl rename to Security/libsecurity_cdsa_plugin/lib/generator.pl diff --git a/libsecurity_cdsa_plugin/lib/pluginsession.cpp b/Security/libsecurity_cdsa_plugin/lib/pluginsession.cpp similarity index 97% rename from libsecurity_cdsa_plugin/lib/pluginsession.cpp rename to Security/libsecurity_cdsa_plugin/lib/pluginsession.cpp index ae284222..c73328ce 100644 --- a/libsecurity_cdsa_plugin/lib/pluginsession.cpp +++ b/Security/libsecurity_cdsa_plugin/lib/pluginsession.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_plugin/lib/pluginsession.h b/Security/libsecurity_cdsa_plugin/lib/pluginsession.h similarity index 98% rename from libsecurity_cdsa_plugin/lib/pluginsession.h rename to Security/libsecurity_cdsa_plugin/lib/pluginsession.h index c747fe23..d58ba5ea 100644 --- a/libsecurity_cdsa_plugin/lib/pluginsession.h +++ b/Security/libsecurity_cdsa_plugin/lib/pluginsession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_plugin/lib/pluginspi.h b/Security/libsecurity_cdsa_plugin/lib/pluginspi.h similarity index 98% rename from libsecurity_cdsa_plugin/lib/pluginspi.h rename to Security/libsecurity_cdsa_plugin/lib/pluginspi.h index b435c4ae..f5d8d491 100644 --- a/libsecurity_cdsa_plugin/lib/pluginspi.h +++ b/Security/libsecurity_cdsa_plugin/lib/pluginspi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj/project.pbxproj b/Security/libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj/project.pbxproj rename to Security/libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj/project.pbxproj diff --git a/libsecurity_cdsa_utilities/APPLE_LICENSE b/Security/libsecurity_cdsa_utilities/APPLE_LICENSE similarity index 100% rename from libsecurity_cdsa_utilities/APPLE_LICENSE rename to Security/libsecurity_cdsa_utilities/APPLE_LICENSE diff --git a/libsecurity_cdsa_utilities/Info-security_cdsa_utilities.plist b/Security/libsecurity_cdsa_utilities/Info-security_cdsa_utilities.plist similarity index 100% rename from libsecurity_cdsa_utilities/Info-security_cdsa_utilities.plist rename to Security/libsecurity_cdsa_utilities/Info-security_cdsa_utilities.plist diff --git a/libsecurity_cdsa_utilities/lib/AuthorizationData.cpp b/Security/libsecurity_cdsa_utilities/lib/AuthorizationData.cpp similarity index 99% rename from libsecurity_cdsa_utilities/lib/AuthorizationData.cpp rename to Security/libsecurity_cdsa_utilities/lib/AuthorizationData.cpp index a1f5b3b2..26ccdea1 100644 --- a/libsecurity_cdsa_utilities/lib/AuthorizationData.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/AuthorizationData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/AuthorizationData.h b/Security/libsecurity_cdsa_utilities/lib/AuthorizationData.h similarity index 98% rename from libsecurity_cdsa_utilities/lib/AuthorizationData.h rename to Security/libsecurity_cdsa_utilities/lib/AuthorizationData.h index d841db28..3b2c24fa 100644 --- a/libsecurity_cdsa_utilities/lib/AuthorizationData.h +++ b/Security/libsecurity_cdsa_utilities/lib/AuthorizationData.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000,2002-2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000,2002-2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/AuthorizationWalkers.h b/Security/libsecurity_cdsa_utilities/lib/AuthorizationWalkers.h similarity index 97% rename from libsecurity_cdsa_utilities/lib/AuthorizationWalkers.h rename to Security/libsecurity_cdsa_utilities/lib/AuthorizationWalkers.h index 94631a58..2ef7dd0f 100644 --- a/libsecurity_cdsa_utilities/lib/AuthorizationWalkers.h +++ b/Security/libsecurity_cdsa_utilities/lib/AuthorizationWalkers.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/KeySchema.h b/Security/libsecurity_cdsa_utilities/lib/KeySchema.h similarity index 97% rename from libsecurity_cdsa_utilities/lib/KeySchema.h rename to Security/libsecurity_cdsa_utilities/lib/KeySchema.h index 6eed5196..000d63b7 100644 --- a/libsecurity_cdsa_utilities/lib/KeySchema.h +++ b/Security/libsecurity_cdsa_utilities/lib/KeySchema.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/KeySchema.m4 b/Security/libsecurity_cdsa_utilities/lib/KeySchema.m4 similarity index 98% rename from libsecurity_cdsa_utilities/lib/KeySchema.m4 rename to Security/libsecurity_cdsa_utilities/lib/KeySchema.m4 index 38996b5a..cbbe75ea 100644 --- a/libsecurity_cdsa_utilities/lib/KeySchema.m4 +++ b/Security/libsecurity_cdsa_utilities/lib/KeySchema.m4 @@ -1,7 +1,7 @@ divert(-1) changecom(/*, */) /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_utilities/lib/Schema.h b/Security/libsecurity_cdsa_utilities/lib/Schema.h similarity index 98% rename from libsecurity_cdsa_utilities/lib/Schema.h rename to Security/libsecurity_cdsa_utilities/lib/Schema.h index 49735347..69fd626f 100644 --- a/libsecurity_cdsa_utilities/lib/Schema.h +++ b/Security/libsecurity_cdsa_utilities/lib/Schema.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/Schema.m4 b/Security/libsecurity_cdsa_utilities/lib/Schema.m4 similarity index 99% rename from libsecurity_cdsa_utilities/lib/Schema.m4 rename to Security/libsecurity_cdsa_utilities/lib/Schema.m4 index 08de9989..5bc9248f 100644 --- a/libsecurity_cdsa_utilities/lib/Schema.m4 +++ b/Security/libsecurity_cdsa_utilities/lib/Schema.m4 @@ -1,7 +1,7 @@ divert(-1) changecom(/*, */) /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -187,6 +187,9 @@ divert(0)dnl `#include ' `#include ' +`#pragma clang diagnostic push' +`#pragma clang diagnostic ignored "-Wunused-const-variable"' + namespace Security { namespace KeychainCore { @@ -464,3 +467,5 @@ attributeInfo(SecKeychainAttrType attrType) } // end namespace KeychainCore } // end namespace Security + +`#pragma clang diagnostic pop' diff --git a/libsecurity_cdsa_utilities/lib/acl_any.cpp b/Security/libsecurity_cdsa_utilities/lib/acl_any.cpp similarity index 96% rename from libsecurity_cdsa_utilities/lib/acl_any.cpp rename to Security/libsecurity_cdsa_utilities/lib/acl_any.cpp index 50e4aea8..25f6a0e5 100644 --- a/libsecurity_cdsa_utilities/lib/acl_any.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/acl_any.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/acl_any.h b/Security/libsecurity_cdsa_utilities/lib/acl_any.h similarity index 96% rename from libsecurity_cdsa_utilities/lib/acl_any.h rename to Security/libsecurity_cdsa_utilities/lib/acl_any.h index d7dc25a8..b985c872 100644 --- a/libsecurity_cdsa_utilities/lib/acl_any.h +++ b/Security/libsecurity_cdsa_utilities/lib/acl_any.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/acl_codesigning.cpp b/Security/libsecurity_cdsa_utilities/lib/acl_codesigning.cpp similarity index 99% rename from libsecurity_cdsa_utilities/lib/acl_codesigning.cpp rename to Security/libsecurity_cdsa_utilities/lib/acl_codesigning.cpp index 9869ec64..a848449f 100644 --- a/libsecurity_cdsa_utilities/lib/acl_codesigning.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/acl_codesigning.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/acl_codesigning.h b/Security/libsecurity_cdsa_utilities/lib/acl_codesigning.h similarity index 98% rename from libsecurity_cdsa_utilities/lib/acl_codesigning.h rename to Security/libsecurity_cdsa_utilities/lib/acl_codesigning.h index 552f5f54..2dc2b2b3 100644 --- a/libsecurity_cdsa_utilities/lib/acl_codesigning.h +++ b/Security/libsecurity_cdsa_utilities/lib/acl_codesigning.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/acl_comment.cpp b/Security/libsecurity_cdsa_utilities/lib/acl_comment.cpp similarity index 98% rename from libsecurity_cdsa_utilities/lib/acl_comment.cpp rename to Security/libsecurity_cdsa_utilities/lib/acl_comment.cpp index a10adb2f..8cf7501f 100644 --- a/libsecurity_cdsa_utilities/lib/acl_comment.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/acl_comment.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/acl_comment.h b/Security/libsecurity_cdsa_utilities/lib/acl_comment.h similarity index 97% rename from libsecurity_cdsa_utilities/lib/acl_comment.h rename to Security/libsecurity_cdsa_utilities/lib/acl_comment.h index 3a3c6344..98a90b92 100644 --- a/libsecurity_cdsa_utilities/lib/acl_comment.h +++ b/Security/libsecurity_cdsa_utilities/lib/acl_comment.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/acl_password.cpp b/Security/libsecurity_cdsa_utilities/lib/acl_password.cpp similarity index 97% rename from libsecurity_cdsa_utilities/lib/acl_password.cpp rename to Security/libsecurity_cdsa_utilities/lib/acl_password.cpp index 8e6d3fda..96801a94 100644 --- a/libsecurity_cdsa_utilities/lib/acl_password.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/acl_password.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/acl_password.h b/Security/libsecurity_cdsa_utilities/lib/acl_password.h similarity index 97% rename from libsecurity_cdsa_utilities/lib/acl_password.h rename to Security/libsecurity_cdsa_utilities/lib/acl_password.h index 83444866..46c94b5c 100644 --- a/libsecurity_cdsa_utilities/lib/acl_password.h +++ b/Security/libsecurity_cdsa_utilities/lib/acl_password.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/acl_preauth.cpp b/Security/libsecurity_cdsa_utilities/lib/acl_preauth.cpp similarity index 98% rename from libsecurity_cdsa_utilities/lib/acl_preauth.cpp rename to Security/libsecurity_cdsa_utilities/lib/acl_preauth.cpp index a2f3e417..121b2a27 100644 --- a/libsecurity_cdsa_utilities/lib/acl_preauth.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/acl_preauth.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006-2007,2011,2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/acl_preauth.h b/Security/libsecurity_cdsa_utilities/lib/acl_preauth.h similarity index 98% rename from libsecurity_cdsa_utilities/lib/acl_preauth.h rename to Security/libsecurity_cdsa_utilities/lib/acl_preauth.h index 4f84bc6f..ee56b95e 100644 --- a/libsecurity_cdsa_utilities/lib/acl_preauth.h +++ b/Security/libsecurity_cdsa_utilities/lib/acl_preauth.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004,2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2004,2006-2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/acl_process.cpp b/Security/libsecurity_cdsa_utilities/lib/acl_process.cpp similarity index 98% rename from libsecurity_cdsa_utilities/lib/acl_process.cpp rename to Security/libsecurity_cdsa_utilities/lib/acl_process.cpp index 37a48674..f8a8cea9 100644 --- a/libsecurity_cdsa_utilities/lib/acl_process.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/acl_process.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/acl_process.h b/Security/libsecurity_cdsa_utilities/lib/acl_process.h similarity index 97% rename from libsecurity_cdsa_utilities/lib/acl_process.h rename to Security/libsecurity_cdsa_utilities/lib/acl_process.h index f34c67ca..79bf66b3 100644 --- a/libsecurity_cdsa_utilities/lib/acl_process.h +++ b/Security/libsecurity_cdsa_utilities/lib/acl_process.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/acl_prompted.cpp b/Security/libsecurity_cdsa_utilities/lib/acl_prompted.cpp similarity index 98% rename from libsecurity_cdsa_utilities/lib/acl_prompted.cpp rename to Security/libsecurity_cdsa_utilities/lib/acl_prompted.cpp index 15496a3c..cc3e85a0 100644 --- a/libsecurity_cdsa_utilities/lib/acl_prompted.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/acl_prompted.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/acl_prompted.h b/Security/libsecurity_cdsa_utilities/lib/acl_prompted.h similarity index 97% rename from libsecurity_cdsa_utilities/lib/acl_prompted.h rename to Security/libsecurity_cdsa_utilities/lib/acl_prompted.h index 26b47f96..59c92341 100644 --- a/libsecurity_cdsa_utilities/lib/acl_prompted.h +++ b/Security/libsecurity_cdsa_utilities/lib/acl_prompted.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/acl_protectedpw.cpp b/Security/libsecurity_cdsa_utilities/lib/acl_protectedpw.cpp similarity index 98% rename from libsecurity_cdsa_utilities/lib/acl_protectedpw.cpp rename to Security/libsecurity_cdsa_utilities/lib/acl_protectedpw.cpp index 7ebff0eb..be4c2587 100644 --- a/libsecurity_cdsa_utilities/lib/acl_protectedpw.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/acl_protectedpw.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/acl_protectedpw.h b/Security/libsecurity_cdsa_utilities/lib/acl_protectedpw.h similarity index 97% rename from libsecurity_cdsa_utilities/lib/acl_protectedpw.h rename to Security/libsecurity_cdsa_utilities/lib/acl_protectedpw.h index 8acf952e..10c11fdc 100644 --- a/libsecurity_cdsa_utilities/lib/acl_protectedpw.h +++ b/Security/libsecurity_cdsa_utilities/lib/acl_protectedpw.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/acl_secret.cpp b/Security/libsecurity_cdsa_utilities/lib/acl_secret.cpp similarity index 98% rename from libsecurity_cdsa_utilities/lib/acl_secret.cpp rename to Security/libsecurity_cdsa_utilities/lib/acl_secret.cpp index 825ce5fe..87a6c193 100644 --- a/libsecurity_cdsa_utilities/lib/acl_secret.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/acl_secret.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/acl_secret.h b/Security/libsecurity_cdsa_utilities/lib/acl_secret.h similarity index 98% rename from libsecurity_cdsa_utilities/lib/acl_secret.h rename to Security/libsecurity_cdsa_utilities/lib/acl_secret.h index f321a66f..1166eafa 100644 --- a/libsecurity_cdsa_utilities/lib/acl_secret.h +++ b/Security/libsecurity_cdsa_utilities/lib/acl_secret.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/acl_threshold.cpp b/Security/libsecurity_cdsa_utilities/lib/acl_threshold.cpp similarity index 98% rename from libsecurity_cdsa_utilities/lib/acl_threshold.cpp rename to Security/libsecurity_cdsa_utilities/lib/acl_threshold.cpp index aea04434..17e568f9 100644 --- a/libsecurity_cdsa_utilities/lib/acl_threshold.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/acl_threshold.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/acl_threshold.h b/Security/libsecurity_cdsa_utilities/lib/acl_threshold.h similarity index 98% rename from libsecurity_cdsa_utilities/lib/acl_threshold.h rename to Security/libsecurity_cdsa_utilities/lib/acl_threshold.h index 71ff0b8b..437f78f0 100644 --- a/libsecurity_cdsa_utilities/lib/acl_threshold.h +++ b/Security/libsecurity_cdsa_utilities/lib/acl_threshold.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/aclsubject.cpp b/Security/libsecurity_cdsa_utilities/lib/aclsubject.cpp similarity index 98% rename from libsecurity_cdsa_utilities/lib/aclsubject.cpp rename to Security/libsecurity_cdsa_utilities/lib/aclsubject.cpp index e1e6e214..70ec05e5 100644 --- a/libsecurity_cdsa_utilities/lib/aclsubject.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/aclsubject.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/aclsubject.h b/Security/libsecurity_cdsa_utilities/lib/aclsubject.h similarity index 99% rename from libsecurity_cdsa_utilities/lib/aclsubject.h rename to Security/libsecurity_cdsa_utilities/lib/aclsubject.h index ee996361..4ad71347 100644 --- a/libsecurity_cdsa_utilities/lib/aclsubject.h +++ b/Security/libsecurity_cdsa_utilities/lib/aclsubject.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/callback.cpp b/Security/libsecurity_cdsa_utilities/lib/callback.cpp similarity index 97% rename from libsecurity_cdsa_utilities/lib/callback.cpp rename to Security/libsecurity_cdsa_utilities/lib/callback.cpp index 023fff0f..72a16361 100644 --- a/libsecurity_cdsa_utilities/lib/callback.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/callback.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/callback.h b/Security/libsecurity_cdsa_utilities/lib/callback.h similarity index 97% rename from libsecurity_cdsa_utilities/lib/callback.h rename to Security/libsecurity_cdsa_utilities/lib/callback.h index ed51eb1c..05695891 100644 --- a/libsecurity_cdsa_utilities/lib/callback.h +++ b/Security/libsecurity_cdsa_utilities/lib/callback.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/constdata.cpp b/Security/libsecurity_cdsa_utilities/lib/constdata.cpp similarity index 95% rename from libsecurity_cdsa_utilities/lib/constdata.cpp rename to Security/libsecurity_cdsa_utilities/lib/constdata.cpp index 40ba116e..c3061751 100644 --- a/libsecurity_cdsa_utilities/lib/constdata.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/constdata.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/constdata.h b/Security/libsecurity_cdsa_utilities/lib/constdata.h similarity index 97% rename from libsecurity_cdsa_utilities/lib/constdata.h rename to Security/libsecurity_cdsa_utilities/lib/constdata.h index 0dbee228..dfa716ec 100644 --- a/libsecurity_cdsa_utilities/lib/constdata.h +++ b/Security/libsecurity_cdsa_utilities/lib/constdata.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/context.cpp b/Security/libsecurity_cdsa_utilities/lib/context.cpp similarity index 99% rename from libsecurity_cdsa_utilities/lib/context.cpp rename to Security/libsecurity_cdsa_utilities/lib/context.cpp index 3a3a3a26..23137bdf 100644 --- a/libsecurity_cdsa_utilities/lib/context.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/context.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/context.h b/Security/libsecurity_cdsa_utilities/lib/context.h similarity index 93% rename from libsecurity_cdsa_utilities/lib/context.h rename to Security/libsecurity_cdsa_utilities/lib/context.h index 0df2e5bd..f5eb57d7 100644 --- a/libsecurity_cdsa_utilities/lib/context.h +++ b/Security/libsecurity_cdsa_utilities/lib/context.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -324,6 +324,31 @@ public: CssmError::throwMe(invalidError); } + void setup(const CSSM_KEY *k, CSSM_RETURN invalidError = CSSM_OK) + { + if (!invalidError) { + if (k) { + slotCount++; + walk(sizer, unconst_ref_cast(k)); + } + return; // no additional validation performed + } + // perform a basic sanity check of the input CSSM_KEY + if (!(k) || (k->KeyHeader.HeaderVersion > CSSM_KEYHEADER_VERSION)) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); + } + // must not point to an odd address or NULL + if (!(k->KeyData.Data) || ((uint64_t)k->KeyData.Data & (uint64_t)1)) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_POINTER); + } + // simplistic key data length check + if ((k->KeyData.Length < 4) || (k->KeyData.Length > 32768)) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); + } + slotCount++; + walk(sizer, unconst_ref_cast(k)); + } + // dynamic attribute type void setup(const CSSM_CONTEXT_ATTRIBUTE &attr) { slotCount++; walk(sizer, const_cast(attr)); } diff --git a/libsecurity_cdsa_utilities/lib/cssmacl.cpp b/Security/libsecurity_cdsa_utilities/lib/cssmacl.cpp similarity index 94% rename from libsecurity_cdsa_utilities/lib/cssmacl.cpp rename to Security/libsecurity_cdsa_utilities/lib/cssmacl.cpp index 62baccc3..58a65464 100644 --- a/libsecurity_cdsa_utilities/lib/cssmacl.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/cssmacl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmacl.h b/Security/libsecurity_cdsa_utilities/lib/cssmacl.h similarity index 97% rename from libsecurity_cdsa_utilities/lib/cssmacl.h rename to Security/libsecurity_cdsa_utilities/lib/cssmacl.h index 9c891741..abb2795f 100644 --- a/libsecurity_cdsa_utilities/lib/cssmacl.h +++ b/Security/libsecurity_cdsa_utilities/lib/cssmacl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp b/Security/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp similarity index 98% rename from libsecurity_cdsa_utilities/lib/cssmaclpod.cpp rename to Security/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp index e7144c43..96a32b50 100644 --- a/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006-2007,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmaclpod.h b/Security/libsecurity_cdsa_utilities/lib/cssmaclpod.h similarity index 99% rename from libsecurity_cdsa_utilities/lib/cssmaclpod.h rename to Security/libsecurity_cdsa_utilities/lib/cssmaclpod.h index 7e4acc0e..bf23f7df 100644 --- a/libsecurity_cdsa_utilities/lib/cssmaclpod.h +++ b/Security/libsecurity_cdsa_utilities/lib/cssmaclpod.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmalloc.cpp b/Security/libsecurity_cdsa_utilities/lib/cssmalloc.cpp similarity index 97% rename from libsecurity_cdsa_utilities/lib/cssmalloc.cpp rename to Security/libsecurity_cdsa_utilities/lib/cssmalloc.cpp index 1df102b7..b2a47672 100644 --- a/libsecurity_cdsa_utilities/lib/cssmalloc.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/cssmalloc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmalloc.h b/Security/libsecurity_cdsa_utilities/lib/cssmalloc.h similarity index 98% rename from libsecurity_cdsa_utilities/lib/cssmalloc.h rename to Security/libsecurity_cdsa_utilities/lib/cssmalloc.h index e1a39cb1..01a14e37 100644 --- a/libsecurity_cdsa_utilities/lib/cssmalloc.h +++ b/Security/libsecurity_cdsa_utilities/lib/cssmalloc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmbridge.h b/Security/libsecurity_cdsa_utilities/lib/cssmbridge.h similarity index 97% rename from libsecurity_cdsa_utilities/lib/cssmbridge.h rename to Security/libsecurity_cdsa_utilities/lib/cssmbridge.h index dd1e2e99..f2f92dbd 100644 --- a/libsecurity_cdsa_utilities/lib/cssmbridge.h +++ b/Security/libsecurity_cdsa_utilities/lib/cssmbridge.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmcert.cpp b/Security/libsecurity_cdsa_utilities/lib/cssmcert.cpp similarity index 97% rename from libsecurity_cdsa_utilities/lib/cssmcert.cpp rename to Security/libsecurity_cdsa_utilities/lib/cssmcert.cpp index 37eded60..dc7c0c05 100644 --- a/libsecurity_cdsa_utilities/lib/cssmcert.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/cssmcert.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmcert.h b/Security/libsecurity_cdsa_utilities/lib/cssmcert.h similarity index 98% rename from libsecurity_cdsa_utilities/lib/cssmcert.h rename to Security/libsecurity_cdsa_utilities/lib/cssmcert.h index 2090685e..551a9a6e 100644 --- a/libsecurity_cdsa_utilities/lib/cssmcert.h +++ b/Security/libsecurity_cdsa_utilities/lib/cssmcert.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmcred.cpp b/Security/libsecurity_cdsa_utilities/lib/cssmcred.cpp similarity index 97% rename from libsecurity_cdsa_utilities/lib/cssmcred.cpp rename to Security/libsecurity_cdsa_utilities/lib/cssmcred.cpp index 72cf2645..ff7d0925 100644 --- a/libsecurity_cdsa_utilities/lib/cssmcred.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/cssmcred.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmcred.h b/Security/libsecurity_cdsa_utilities/lib/cssmcred.h similarity index 98% rename from libsecurity_cdsa_utilities/lib/cssmcred.h rename to Security/libsecurity_cdsa_utilities/lib/cssmcred.h index 045ff7ed..e0e8aae3 100644 --- a/libsecurity_cdsa_utilities/lib/cssmcred.h +++ b/Security/libsecurity_cdsa_utilities/lib/cssmcred.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmdata.cpp b/Security/libsecurity_cdsa_utilities/lib/cssmdata.cpp similarity index 98% rename from libsecurity_cdsa_utilities/lib/cssmdata.cpp rename to Security/libsecurity_cdsa_utilities/lib/cssmdata.cpp index 74b50566..5dec094e 100644 --- a/libsecurity_cdsa_utilities/lib/cssmdata.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/cssmdata.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmdata.h b/Security/libsecurity_cdsa_utilities/lib/cssmdata.h similarity index 99% rename from libsecurity_cdsa_utilities/lib/cssmdata.h rename to Security/libsecurity_cdsa_utilities/lib/cssmdata.h index 591a1ddb..eee84a0a 100644 --- a/libsecurity_cdsa_utilities/lib/cssmdata.h +++ b/Security/libsecurity_cdsa_utilities/lib/cssmdata.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -351,7 +351,6 @@ public: template void copy(const T *data, size_t length) { - // don't leave any open windows for Mr. Murphy CssmAutoPtr newData(allocator, memcpy(allocator.malloc(length), data, length)); reset(); referent = CssmData(newData.release(), length); diff --git a/libsecurity_cdsa_utilities/lib/cssmdates.cpp b/Security/libsecurity_cdsa_utilities/lib/cssmdates.cpp similarity index 98% rename from libsecurity_cdsa_utilities/lib/cssmdates.cpp rename to Security/libsecurity_cdsa_utilities/lib/cssmdates.cpp index d4bceb5a..e5b46b8c 100644 --- a/libsecurity_cdsa_utilities/lib/cssmdates.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/cssmdates.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmdates.h b/Security/libsecurity_cdsa_utilities/lib/cssmdates.h similarity index 98% rename from libsecurity_cdsa_utilities/lib/cssmdates.h rename to Security/libsecurity_cdsa_utilities/lib/cssmdates.h index afbe3d5a..a452308b 100644 --- a/libsecurity_cdsa_utilities/lib/cssmdates.h +++ b/Security/libsecurity_cdsa_utilities/lib/cssmdates.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmdb.cpp b/Security/libsecurity_cdsa_utilities/lib/cssmdb.cpp similarity index 98% rename from libsecurity_cdsa_utilities/lib/cssmdb.cpp rename to Security/libsecurity_cdsa_utilities/lib/cssmdb.cpp index 85c49a26..e3546459 100644 --- a/libsecurity_cdsa_utilities/lib/cssmdb.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/cssmdb.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -33,8 +33,8 @@ bool DLDbIdentifier::Impl::operator < (const DLDbIdentifier::Impl &other) const return true; if (mCssmSubserviceUid != other.mCssmSubserviceUid) // i.e. greater than return false; - - // Murf correctly points out that this test will produce unreproducible results, + + // This test will produce unreproducible results, // depending on what items are being compared. To do this properly, we need to // assign a lexical value to NULL. // diff --git a/libsecurity_cdsa_utilities/lib/cssmdb.h b/Security/libsecurity_cdsa_utilities/lib/cssmdb.h similarity index 99% rename from libsecurity_cdsa_utilities/lib/cssmdb.h rename to Security/libsecurity_cdsa_utilities/lib/cssmdb.h index f49fa482..5ecb5a29 100644 --- a/libsecurity_cdsa_utilities/lib/cssmdb.h +++ b/Security/libsecurity_cdsa_utilities/lib/cssmdb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmdbname.cpp b/Security/libsecurity_cdsa_utilities/lib/cssmdbname.cpp similarity index 97% rename from libsecurity_cdsa_utilities/lib/cssmdbname.cpp rename to Security/libsecurity_cdsa_utilities/lib/cssmdbname.cpp index 269f86bd..48706c99 100644 --- a/libsecurity_cdsa_utilities/lib/cssmdbname.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/cssmdbname.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmdbname.h b/Security/libsecurity_cdsa_utilities/lib/cssmdbname.h similarity index 98% rename from libsecurity_cdsa_utilities/lib/cssmdbname.h rename to Security/libsecurity_cdsa_utilities/lib/cssmdbname.h index 4986864d..a4954935 100644 --- a/libsecurity_cdsa_utilities/lib/cssmdbname.h +++ b/Security/libsecurity_cdsa_utilities/lib/cssmdbname.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmendian.cpp b/Security/libsecurity_cdsa_utilities/lib/cssmendian.cpp similarity index 96% rename from libsecurity_cdsa_utilities/lib/cssmendian.cpp rename to Security/libsecurity_cdsa_utilities/lib/cssmendian.cpp index ac73c09d..687489ab 100644 --- a/libsecurity_cdsa_utilities/lib/cssmendian.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/cssmendian.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmendian.h b/Security/libsecurity_cdsa_utilities/lib/cssmendian.h similarity index 95% rename from libsecurity_cdsa_utilities/lib/cssmendian.h rename to Security/libsecurity_cdsa_utilities/lib/cssmendian.h index 71e23d20..99edcf91 100644 --- a/libsecurity_cdsa_utilities/lib/cssmendian.h +++ b/Security/libsecurity_cdsa_utilities/lib/cssmendian.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmerrors.cpp b/Security/libsecurity_cdsa_utilities/lib/cssmerrors.cpp similarity index 97% rename from libsecurity_cdsa_utilities/lib/cssmerrors.cpp rename to Security/libsecurity_cdsa_utilities/lib/cssmerrors.cpp index 2d9a688c..0d0f7c29 100644 --- a/libsecurity_cdsa_utilities/lib/cssmerrors.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/cssmerrors.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmerrors.h b/Security/libsecurity_cdsa_utilities/lib/cssmerrors.h similarity index 96% rename from libsecurity_cdsa_utilities/lib/cssmerrors.h rename to Security/libsecurity_cdsa_utilities/lib/cssmerrors.h index a41fd2bf..fc83b898 100644 --- a/libsecurity_cdsa_utilities/lib/cssmerrors.h +++ b/Security/libsecurity_cdsa_utilities/lib/cssmerrors.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmkey.cpp b/Security/libsecurity_cdsa_utilities/lib/cssmkey.cpp similarity index 96% rename from libsecurity_cdsa_utilities/lib/cssmkey.cpp rename to Security/libsecurity_cdsa_utilities/lib/cssmkey.cpp index 9ad142fe..111d9594 100644 --- a/libsecurity_cdsa_utilities/lib/cssmkey.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/cssmkey.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmkey.h b/Security/libsecurity_cdsa_utilities/lib/cssmkey.h similarity index 98% rename from libsecurity_cdsa_utilities/lib/cssmkey.h rename to Security/libsecurity_cdsa_utilities/lib/cssmkey.h index 4154fb42..74a7f918 100644 --- a/libsecurity_cdsa_utilities/lib/cssmkey.h +++ b/Security/libsecurity_cdsa_utilities/lib/cssmkey.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmlist.cpp b/Security/libsecurity_cdsa_utilities/lib/cssmlist.cpp similarity index 98% rename from libsecurity_cdsa_utilities/lib/cssmlist.cpp rename to Security/libsecurity_cdsa_utilities/lib/cssmlist.cpp index 7fa52a1f..911cf2c6 100644 --- a/libsecurity_cdsa_utilities/lib/cssmlist.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/cssmlist.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006-2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmlist.h b/Security/libsecurity_cdsa_utilities/lib/cssmlist.h similarity index 99% rename from libsecurity_cdsa_utilities/lib/cssmlist.h rename to Security/libsecurity_cdsa_utilities/lib/cssmlist.h index fd594995..6506b0df 100644 --- a/libsecurity_cdsa_utilities/lib/cssmlist.h +++ b/Security/libsecurity_cdsa_utilities/lib/cssmlist.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmpods.cpp b/Security/libsecurity_cdsa_utilities/lib/cssmpods.cpp similarity index 98% rename from libsecurity_cdsa_utilities/lib/cssmpods.cpp rename to Security/libsecurity_cdsa_utilities/lib/cssmpods.cpp index d17dba41..44d366ed 100644 --- a/libsecurity_cdsa_utilities/lib/cssmpods.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/cssmpods.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmpods.h b/Security/libsecurity_cdsa_utilities/lib/cssmpods.h similarity index 98% rename from libsecurity_cdsa_utilities/lib/cssmpods.h rename to Security/libsecurity_cdsa_utilities/lib/cssmpods.h index b154c7df..c1b1c542 100644 --- a/libsecurity_cdsa_utilities/lib/cssmpods.h +++ b/Security/libsecurity_cdsa_utilities/lib/cssmpods.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmtrust.cpp b/Security/libsecurity_cdsa_utilities/lib/cssmtrust.cpp similarity index 95% rename from libsecurity_cdsa_utilities/lib/cssmtrust.cpp rename to Security/libsecurity_cdsa_utilities/lib/cssmtrust.cpp index cb20471d..d3192024 100644 --- a/libsecurity_cdsa_utilities/lib/cssmtrust.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/cssmtrust.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmtrust.h b/Security/libsecurity_cdsa_utilities/lib/cssmtrust.h similarity index 99% rename from libsecurity_cdsa_utilities/lib/cssmtrust.h rename to Security/libsecurity_cdsa_utilities/lib/cssmtrust.h index a24138a6..7dcc79f7 100644 --- a/libsecurity_cdsa_utilities/lib/cssmtrust.h +++ b/Security/libsecurity_cdsa_utilities/lib/cssmtrust.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmwalkers.cpp b/Security/libsecurity_cdsa_utilities/lib/cssmwalkers.cpp similarity index 94% rename from libsecurity_cdsa_utilities/lib/cssmwalkers.cpp rename to Security/libsecurity_cdsa_utilities/lib/cssmwalkers.cpp index eb812a2b..3a94fe2e 100644 --- a/libsecurity_cdsa_utilities/lib/cssmwalkers.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/cssmwalkers.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/cssmwalkers.h b/Security/libsecurity_cdsa_utilities/lib/cssmwalkers.h similarity index 98% rename from libsecurity_cdsa_utilities/lib/cssmwalkers.h rename to Security/libsecurity_cdsa_utilities/lib/cssmwalkers.h index cb103439..bf6f0941 100644 --- a/libsecurity_cdsa_utilities/lib/cssmwalkers.h +++ b/Security/libsecurity_cdsa_utilities/lib/cssmwalkers.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/db++.cpp b/Security/libsecurity_cdsa_utilities/lib/db++.cpp similarity index 98% rename from libsecurity_cdsa_utilities/lib/db++.cpp rename to Security/libsecurity_cdsa_utilities/lib/db++.cpp index 2f64123c..94874b5a 100644 --- a/libsecurity_cdsa_utilities/lib/db++.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/db++.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/db++.h b/Security/libsecurity_cdsa_utilities/lib/db++.h similarity index 97% rename from libsecurity_cdsa_utilities/lib/db++.h rename to Security/libsecurity_cdsa_utilities/lib/db++.h index d947e466..79d84a5e 100644 --- a/libsecurity_cdsa_utilities/lib/db++.h +++ b/Security/libsecurity_cdsa_utilities/lib/db++.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/digestobject.h b/Security/libsecurity_cdsa_utilities/lib/digestobject.h similarity index 97% rename from libsecurity_cdsa_utilities/lib/digestobject.h rename to Security/libsecurity_cdsa_utilities/lib/digestobject.h index 3ba1408e..0698974b 100644 --- a/libsecurity_cdsa_utilities/lib/digestobject.h +++ b/Security/libsecurity_cdsa_utilities/lib/digestobject.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/generator.mk b/Security/libsecurity_cdsa_utilities/lib/generator.mk similarity index 100% rename from libsecurity_cdsa_utilities/lib/generator.mk rename to Security/libsecurity_cdsa_utilities/lib/generator.mk diff --git a/libsecurity_cdsa_utilities/lib/generator.pl b/Security/libsecurity_cdsa_utilities/lib/generator.pl similarity index 100% rename from libsecurity_cdsa_utilities/lib/generator.pl rename to Security/libsecurity_cdsa_utilities/lib/generator.pl diff --git a/libsecurity_cdsa_utilities/lib/handleobject.cpp b/Security/libsecurity_cdsa_utilities/lib/handleobject.cpp similarity index 94% rename from libsecurity_cdsa_utilities/lib/handleobject.cpp rename to Security/libsecurity_cdsa_utilities/lib/handleobject.cpp index 2a57a98f..f847d87e 100644 --- a/libsecurity_cdsa_utilities/lib/handleobject.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/handleobject.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2008,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/handleobject.h b/Security/libsecurity_cdsa_utilities/lib/handleobject.h similarity index 95% rename from libsecurity_cdsa_utilities/lib/handleobject.h rename to Security/libsecurity_cdsa_utilities/lib/handleobject.h index 80fbae33..8636a599 100644 --- a/libsecurity_cdsa_utilities/lib/handleobject.h +++ b/Security/libsecurity_cdsa_utilities/lib/handleobject.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2008,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/handletemplates.cpp b/Security/libsecurity_cdsa_utilities/lib/handletemplates.cpp similarity index 95% rename from libsecurity_cdsa_utilities/lib/handletemplates.cpp rename to Security/libsecurity_cdsa_utilities/lib/handletemplates.cpp index 453b9e20..4d550d79 100644 --- a/libsecurity_cdsa_utilities/lib/handletemplates.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/handletemplates.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2008,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/handletemplates.h b/Security/libsecurity_cdsa_utilities/lib/handletemplates.h similarity index 99% rename from libsecurity_cdsa_utilities/lib/handletemplates.h rename to Security/libsecurity_cdsa_utilities/lib/handletemplates.h index d28572a3..ed9da369 100644 --- a/libsecurity_cdsa_utilities/lib/handletemplates.h +++ b/Security/libsecurity_cdsa_utilities/lib/handletemplates.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2008,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/handletemplates_defs.h b/Security/libsecurity_cdsa_utilities/lib/handletemplates_defs.h similarity index 98% rename from libsecurity_cdsa_utilities/lib/handletemplates_defs.h rename to Security/libsecurity_cdsa_utilities/lib/handletemplates_defs.h index 033704f8..1d365838 100644 --- a/libsecurity_cdsa_utilities/lib/handletemplates_defs.h +++ b/Security/libsecurity_cdsa_utilities/lib/handletemplates_defs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2008,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/objectacl.cpp b/Security/libsecurity_cdsa_utilities/lib/objectacl.cpp similarity index 99% rename from libsecurity_cdsa_utilities/lib/objectacl.cpp rename to Security/libsecurity_cdsa_utilities/lib/objectacl.cpp index 23e0b9b7..c89cb273 100644 --- a/libsecurity_cdsa_utilities/lib/objectacl.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/objectacl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/objectacl.h b/Security/libsecurity_cdsa_utilities/lib/objectacl.h similarity index 99% rename from libsecurity_cdsa_utilities/lib/objectacl.h rename to Security/libsecurity_cdsa_utilities/lib/objectacl.h index 319af792..c1d08253 100644 --- a/libsecurity_cdsa_utilities/lib/objectacl.h +++ b/Security/libsecurity_cdsa_utilities/lib/objectacl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/osxverifier.cpp b/Security/libsecurity_cdsa_utilities/lib/osxverifier.cpp similarity index 98% rename from libsecurity_cdsa_utilities/lib/osxverifier.cpp rename to Security/libsecurity_cdsa_utilities/lib/osxverifier.cpp index d09e9a41..3bf4520b 100644 --- a/libsecurity_cdsa_utilities/lib/osxverifier.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/osxverifier.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_utilities/lib/osxverifier.h b/Security/libsecurity_cdsa_utilities/lib/osxverifier.h similarity index 97% rename from libsecurity_cdsa_utilities/lib/osxverifier.h rename to Security/libsecurity_cdsa_utilities/lib/osxverifier.h index 791878d8..0703c57d 100644 --- a/libsecurity_cdsa_utilities/lib/osxverifier.h +++ b/Security/libsecurity_cdsa_utilities/lib/osxverifier.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_utilities/lib/u32handleobject.cpp b/Security/libsecurity_cdsa_utilities/lib/u32handleobject.cpp similarity index 94% rename from libsecurity_cdsa_utilities/lib/u32handleobject.cpp rename to Security/libsecurity_cdsa_utilities/lib/u32handleobject.cpp index 6bd056c4..647b1132 100644 --- a/libsecurity_cdsa_utilities/lib/u32handleobject.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/u32handleobject.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2008,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/u32handleobject.h b/Security/libsecurity_cdsa_utilities/lib/u32handleobject.h similarity index 95% rename from libsecurity_cdsa_utilities/lib/u32handleobject.h rename to Security/libsecurity_cdsa_utilities/lib/u32handleobject.h index 630f9246..b9e44c95 100644 --- a/libsecurity_cdsa_utilities/lib/u32handleobject.h +++ b/Security/libsecurity_cdsa_utilities/lib/u32handleobject.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2008,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/uniformrandom.cpp b/Security/libsecurity_cdsa_utilities/lib/uniformrandom.cpp similarity index 94% rename from libsecurity_cdsa_utilities/lib/uniformrandom.cpp rename to Security/libsecurity_cdsa_utilities/lib/uniformrandom.cpp index a87a6cde..92c6f507 100644 --- a/libsecurity_cdsa_utilities/lib/uniformrandom.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/uniformrandom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/uniformrandom.h b/Security/libsecurity_cdsa_utilities/lib/uniformrandom.h similarity index 96% rename from libsecurity_cdsa_utilities/lib/uniformrandom.h rename to Security/libsecurity_cdsa_utilities/lib/uniformrandom.h index 5fc9d4ae..ecbdae36 100644 --- a/libsecurity_cdsa_utilities/lib/uniformrandom.h +++ b/Security/libsecurity_cdsa_utilities/lib/uniformrandom.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/walkers.cpp b/Security/libsecurity_cdsa_utilities/lib/walkers.cpp similarity index 95% rename from libsecurity_cdsa_utilities/lib/walkers.cpp rename to Security/libsecurity_cdsa_utilities/lib/walkers.cpp index 23b510c2..c0a23774 100644 --- a/libsecurity_cdsa_utilities/lib/walkers.cpp +++ b/Security/libsecurity_cdsa_utilities/lib/walkers.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/lib/walkers.h b/Security/libsecurity_cdsa_utilities/lib/walkers.h similarity index 99% rename from libsecurity_cdsa_utilities/lib/walkers.h rename to Security/libsecurity_cdsa_utilities/lib/walkers.h index 2d3a897f..6178a359 100644 --- a/libsecurity_cdsa_utilities/lib/walkers.h +++ b/Security/libsecurity_cdsa_utilities/lib/walkers.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cdsa_utilities/libsecurity_cdsa_utilities.xcodeproj/project.pbxproj b/Security/libsecurity_cdsa_utilities/libsecurity_cdsa_utilities.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_cdsa_utilities/libsecurity_cdsa_utilities.xcodeproj/project.pbxproj rename to Security/libsecurity_cdsa_utilities/libsecurity_cdsa_utilities.xcodeproj/project.pbxproj diff --git a/libsecurity_cdsa_utils/Info-security_cdsa_utils.plist b/Security/libsecurity_cdsa_utils/Info-security_cdsa_utils.plist similarity index 100% rename from libsecurity_cdsa_utils/Info-security_cdsa_utils.plist rename to Security/libsecurity_cdsa_utils/Info-security_cdsa_utils.plist diff --git a/libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp b/Security/libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp similarity index 99% rename from libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp rename to Security/libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp index 2b3779f4..a516d362 100644 --- a/libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp +++ b/Security/libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2001-2003,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_utils/lib/cuCdsaUtils.h b/Security/libsecurity_cdsa_utils/lib/cuCdsaUtils.h similarity index 98% rename from libsecurity_cdsa_utils/lib/cuCdsaUtils.h rename to Security/libsecurity_cdsa_utils/lib/cuCdsaUtils.h index a4843c88..cac544eb 100644 --- a/libsecurity_cdsa_utils/lib/cuCdsaUtils.h +++ b/Security/libsecurity_cdsa_utils/lib/cuCdsaUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2001-2003,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_utils/lib/cuDbUtils.cpp b/Security/libsecurity_cdsa_utils/lib/cuDbUtils.cpp similarity index 99% rename from libsecurity_cdsa_utils/lib/cuDbUtils.cpp rename to Security/libsecurity_cdsa_utils/lib/cuDbUtils.cpp index 6b26056a..9e8f65a0 100644 --- a/libsecurity_cdsa_utils/lib/cuDbUtils.cpp +++ b/Security/libsecurity_cdsa_utils/lib/cuDbUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2003,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_utils/lib/cuDbUtils.h b/Security/libsecurity_cdsa_utils/lib/cuDbUtils.h similarity index 96% rename from libsecurity_cdsa_utils/lib/cuDbUtils.h rename to Security/libsecurity_cdsa_utils/lib/cuDbUtils.h index 62ba854a..c2c0d76d 100644 --- a/libsecurity_cdsa_utils/lib/cuDbUtils.h +++ b/Security/libsecurity_cdsa_utils/lib/cuDbUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2003,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/Security/libsecurity_cdsa_utils/lib/cuEnc64.c b/Security/libsecurity_cdsa_utils/lib/cuEnc64.c new file mode 100644 index 00000000..41e0b005 --- /dev/null +++ b/Security/libsecurity_cdsa_utils/lib/cuEnc64.c @@ -0,0 +1,392 @@ +/* + * Copyright (c) 1998-2003,2011,2014 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please + * obtain a copy of the License at http://www.apple.com/publicsource and + * read it before using this file. + * + * This 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. + * + * cuEnc64.c - encode/decode in 64-char IA5 format, per RFC 1421 + */ + +#include "cuEnc64.h" +#include + +#ifndef NULL +#define NULL ((void *)0) +#endif /* NULL */ + +/* + * map a 6-bit binary value to a printable character. + */ +static const +unsigned char bintoasc[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* + * Map an 7-bit printable character to its corresponding binary value. + * Any illegal characters return high bit set. + */ +static const +unsigned char asctobin[] = +{ + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x3e, 0x80, 0x80, 0x80, 0x3f, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80 +}; + +/* + * map 6 bits to a printing char + */ +#define ENC(c) (bintoasc[((c) & 0x3f)]) + +#define PAD '=' + +/* + * map one group of up to 3 bytes at inp to 4 bytes at outp. + * Count is number of valid bytes in *inp; if less than 3, the + * 1 or two extras must be zeros. + */ +static void encChunk(const unsigned char *inp, + unsigned char *outp, + int count) +{ + unsigned char c1, c2, c3, c4; + + c1 = *inp >> 2; + c2 = ((inp[0] << 4) & 0x30) | ((inp[1] >> 4) & 0xf); + c3 = ((inp[1] << 2) & 0x3c) | ((inp[2] >> 6) & 0x3); + c4 = inp[2] & 0x3f; + *outp++ = ENC(c1); + *outp++ = ENC(c2); + if (count == 1) { + *outp++ = PAD; + *outp = PAD; + } else { + *outp++ = ENC(c3); + if (count == 2) { + *outp = PAD; + } + else { + *outp = ENC(c4); + } + } +} + +/* + * Given input buffer inbuf, length inlen, encode to 64-char IA5 format. + * Result is fmalloc'd and returned; it is terminated by Microsoft-style + * newline and NULL. Its length (including the trailing newline and NULL) + * is returned in *outlen. + */ + +unsigned char *cuEnc64(const unsigned char *inbuf, + unsigned inlen, + unsigned *outlen) // RETURNED +{ + return cuEnc64WithLines(inbuf, inlen, 0, outlen); +} + +unsigned char *cuEnc64WithLines(const unsigned char *inbuf, + unsigned inlen, + unsigned linelen, + unsigned *outlen) +{ + unsigned outTextLen; + unsigned len; // to malloc, liberal + unsigned olen = 0; // actual output size + unsigned char *outbuf; + unsigned char endbuf[3]; + unsigned i; + unsigned char *outp; + unsigned numLines; + unsigned thisLine; + + outTextLen = ((inlen + 2) / 3) * 4; + if(linelen) { + /* + * linelen must be 0 mod 4 for this to work; round up... + */ + if((linelen & 0x03) != 0) { + linelen = (linelen + 3) & 0xfffffffc; + } + numLines = (outTextLen + linelen - 1)/ linelen; + } + else { + numLines = 1; + } + + /* + * Total output size = encoded text size plus one newline per + * line of output, plus trailing NULL. We always generate newlines + * as \n; when decoding, we tolerate \r\n (Microsoft) or \n. + */ + len = outTextLen + (2 * numLines) + 1; + outbuf = (unsigned char*)malloc(len); + outp = outbuf; + thisLine = 0; + + while(inlen) { + if(inlen < 3) { + for(i=0; i<3; i++) { + if(i < inlen) { + endbuf[i] = inbuf[i]; + } + else { + endbuf[i] = 0; + } + } + encChunk(endbuf, outp, inlen); + inlen = 0; + } + else { + encChunk(inbuf, outp, 3); + inlen -= 3; + inbuf += 3; + } + outp += 4; + thisLine += 4; + olen += 4; + if((linelen != 0) && (thisLine >= linelen) && inlen) { + /* + * last trailing newline added below + * Note we don't split 4-byte output chunks over newlines + */ + *outp++ = '\n'; + olen++; + thisLine = 0; + } + } + *outp++ = '\n'; + *outp = '\0'; + olen += 2; + *outlen = olen; + return outbuf; +} + +static inline int isWhite(unsigned char c) +{ + switch(c) { + case '\n': + case '\r': + case ' ': + case '\t': + case '\0': + return 1; + default: + return 0; + } +} + +/* + * Strip off all whitespace from a (supposedly) enc64-format string. + * Returns a malloc'd string. + */ +static unsigned char *stringCleanse(const unsigned char *inbuf, + unsigned inlen, + unsigned *outlen) +{ + unsigned char *news; // cleansed inbuf + unsigned newsDex; // index into news + unsigned i; + + news = (unsigned char*)malloc(inlen); + newsDex = 0; + for(i=0; i 0) { + goto errorOut; + } + } + else { + goto errorOut; + } + } else if (*bp & 0x80 || (c3 = asctobin[*bp]) & 0x80) { + goto errorOut; + } else { + bp++; + inlen--; + if (*bp == PAD) { + /* + * Three input bytes, two output + */ + c4 = 0; + thisOlen = 2; + if (c3 & 3) { + goto errorOut; + } + } else if (*bp & 0x80 || (c4 = asctobin[*bp]) & 0x80) { + goto errorOut; + } else { + /* + * Normal non-pad case + */ + thisOlen = 3; + } + bp++; + inlen--; + } + j = (c1 << 2) | (c2 >> 4); + *outp++ = j; + if(thisOlen > 1) { + j = (c2 << 4) | (c3 >> 2); + *outp++ = j; + if(thisOlen == 3) { + j = (c3 << 6) | c4; + *outp++ = j; + } + } + olen += thisOlen; + } + free(news); + *outlen = olen; + return outbuf; /* normal return */ + +errorOut: + free(news); + free(outbuf); + return (unsigned char*) NULL; +} + +/* + * Determine if specified input data is valid enc64 format. Returns 1 + * if valid, 0 if not. + * This doesn't do a full enc64 parse job; it scans for legal characters + * and proper sync when a possible pad is found. + */ +int cuIsValidEnc64(const unsigned char *inbuf, + unsigned inlen) +{ + int padChars = 0; // running count of PAD chars + int validEncChars = 0; + unsigned char c; + + /* + * -- scan inbuf + * -- skip whitespace + * -- count valid chars + * -- ensure not more than 2 PAD chars, only at end + * -- ensure valid chars mod 4 == 0 + */ + + while(inlen) { + c = *inbuf++; + inlen--; + if(isWhite(c)) { + continue; + } + if(c == PAD) { + if(++padChars > 2) { + return 0; // max of 2 PAD chars at end + } + } + else if(padChars > 0) { + return 0; // no normal chars after seeing PAD + } + else if((c & 0x80) || ((asctobin[c]) & 0x80)) { + return 0; // invalid encoded char + } + validEncChars++; + } + if((validEncChars & 0x03) != 0) { + return 0; + } + else { + return 1; + } +} diff --git a/Security/libsecurity_cdsa_utils/lib/cuEnc64.h b/Security/libsecurity_cdsa_utils/lib/cuEnc64.h new file mode 100644 index 00000000..925e98b6 --- /dev/null +++ b/Security/libsecurity_cdsa_utils/lib/cuEnc64.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1998-2003,2011,2014 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please + * obtain a copy of the License at http://www.apple.com/publicsource and + * read it before using this file. + * + * This 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. + * + * cuEnc64.h - encode/decode in 64-char IA5 format, per RFC 1421 + */ + +#ifndef _CU_ENC64_H_ +#define _CU_ENC64_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Given input buffer inbuf, length inlen, decode from 64-char IA5 format to + * binary. Result is malloced and returned; its length is returned in *outlen. + * NULL return indicates corrupted input. + */ +unsigned char *cuEnc64(const unsigned char *inbuf, + unsigned inlen, + unsigned *outlen); // RETURNED + +/* + * Enc64, with embedded newlines every lineLen in result. A newline is + * the UNIX \n. Result is mallocd. + */ +unsigned char *cuEnc64WithLines(const unsigned char *inbuf, + unsigned inlen, + unsigned linelen, + unsigned *outlen); // RETURNED + +/* + * Given input buffer inbuf, length inlen, decode from 64-char IA5 format to + * binary. Result is malloced and returned; its length is returned in *outlen. + * NULL return indicates corrupted input. All whitespace in inbuf is + * ignored. + */ +unsigned char *cuDec64(const unsigned char *inbuf, + unsigned inlen, + unsigned *outlen); + +/* + * Determine if specified input data is valid enc64 format. Returns 1 + * if valid, 0 if not. + */ +int cuIsValidEnc64(const unsigned char *inbuf, + unsigned inbufLen); + +#ifdef __cplusplus +} +#endif + +#endif /*_CU_ENC64_H_*/ diff --git a/libsecurity_cdsa_utils/lib/cuFileIo.c b/Security/libsecurity_cdsa_utils/lib/cuFileIo.c similarity index 96% rename from libsecurity_cdsa_utils/lib/cuFileIo.c rename to Security/libsecurity_cdsa_utils/lib/cuFileIo.c index 6b643d99..bb1403e0 100644 --- a/libsecurity_cdsa_utils/lib/cuFileIo.c +++ b/Security/libsecurity_cdsa_utils/lib/cuFileIo.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2001-2003,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_utils/lib/cuFileIo.h b/Security/libsecurity_cdsa_utils/lib/cuFileIo.h similarity index 94% rename from libsecurity_cdsa_utils/lib/cuFileIo.h rename to Security/libsecurity_cdsa_utils/lib/cuFileIo.h index bb3de3f8..c02fdbde 100644 --- a/libsecurity_cdsa_utils/lib/cuFileIo.h +++ b/Security/libsecurity_cdsa_utils/lib/cuFileIo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2001-2003,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_utils/lib/cuOidParser.cpp b/Security/libsecurity_cdsa_utils/lib/cuOidParser.cpp similarity index 99% rename from libsecurity_cdsa_utils/lib/cuOidParser.cpp rename to Security/libsecurity_cdsa_utils/lib/cuOidParser.cpp index e03f1239..7b2b7def 100644 --- a/libsecurity_cdsa_utils/lib/cuOidParser.cpp +++ b/Security/libsecurity_cdsa_utils/lib/cuOidParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2003,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_utils/lib/cuOidParser.h b/Security/libsecurity_cdsa_utils/lib/cuOidParser.h similarity index 96% rename from libsecurity_cdsa_utils/lib/cuOidParser.h rename to Security/libsecurity_cdsa_utils/lib/cuOidParser.h index fcadc5a7..229688cf 100644 --- a/libsecurity_cdsa_utils/lib/cuOidParser.h +++ b/Security/libsecurity_cdsa_utils/lib/cuOidParser.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2003,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_utils/lib/cuPem.cpp b/Security/libsecurity_cdsa_utils/lib/cuPem.cpp similarity index 98% rename from libsecurity_cdsa_utils/lib/cuPem.cpp rename to Security/libsecurity_cdsa_utils/lib/cuPem.cpp index 94925b74..cbf87203 100644 --- a/libsecurity_cdsa_utils/lib/cuPem.cpp +++ b/Security/libsecurity_cdsa_utils/lib/cuPem.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_utils/lib/cuPem.h b/Security/libsecurity_cdsa_utils/lib/cuPem.h similarity index 95% rename from libsecurity_cdsa_utils/lib/cuPem.h rename to Security/libsecurity_cdsa_utils/lib/cuPem.h index 58a08fde..a7ef5d90 100644 --- a/libsecurity_cdsa_utils/lib/cuPem.h +++ b/Security/libsecurity_cdsa_utils/lib/cuPem.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_utils/lib/cuPrintCert.cpp b/Security/libsecurity_cdsa_utils/lib/cuPrintCert.cpp similarity index 99% rename from libsecurity_cdsa_utils/lib/cuPrintCert.cpp rename to Security/libsecurity_cdsa_utils/lib/cuPrintCert.cpp index cf640573..5f0281ba 100644 --- a/libsecurity_cdsa_utils/lib/cuPrintCert.cpp +++ b/Security/libsecurity_cdsa_utils/lib/cuPrintCert.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_utils/lib/cuPrintCert.h b/Security/libsecurity_cdsa_utils/lib/cuPrintCert.h similarity index 96% rename from libsecurity_cdsa_utils/lib/cuPrintCert.h rename to Security/libsecurity_cdsa_utils/lib/cuPrintCert.h index b62ec735..2ff3c150 100644 --- a/libsecurity_cdsa_utils/lib/cuPrintCert.h +++ b/Security/libsecurity_cdsa_utils/lib/cuPrintCert.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_utils/lib/cuTimeStr.cpp b/Security/libsecurity_cdsa_utils/lib/cuTimeStr.cpp similarity index 98% rename from libsecurity_cdsa_utils/lib/cuTimeStr.cpp rename to Security/libsecurity_cdsa_utils/lib/cuTimeStr.cpp index f99c69e0..fe246994 100644 --- a/libsecurity_cdsa_utils/lib/cuTimeStr.cpp +++ b/Security/libsecurity_cdsa_utils/lib/cuTimeStr.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_utils/lib/cuTimeStr.h b/Security/libsecurity_cdsa_utils/lib/cuTimeStr.h similarity index 96% rename from libsecurity_cdsa_utils/lib/cuTimeStr.h rename to Security/libsecurity_cdsa_utils/lib/cuTimeStr.h index cad00720..0eefc56e 100644 --- a/libsecurity_cdsa_utils/lib/cuTimeStr.h +++ b/Security/libsecurity_cdsa_utils/lib/cuTimeStr.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_cdsa_utils/libsecurity_cdsa_utils.xcodeproj/project.pbxproj b/Security/libsecurity_cdsa_utils/libsecurity_cdsa_utils.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_cdsa_utils/libsecurity_cdsa_utils.xcodeproj/project.pbxproj rename to Security/libsecurity_cdsa_utils/libsecurity_cdsa_utils.xcodeproj/project.pbxproj diff --git a/libsecurity_checkpw/APPLE_LICENSE b/Security/libsecurity_checkpw/APPLE_LICENSE similarity index 100% rename from libsecurity_checkpw/APPLE_LICENSE rename to Security/libsecurity_checkpw/APPLE_LICENSE diff --git a/libsecurity_checkpw/Info-security_checkpw.plist b/Security/libsecurity_checkpw/Info-security_checkpw.plist similarity index 100% rename from libsecurity_checkpw/Info-security_checkpw.plist rename to Security/libsecurity_checkpw/Info-security_checkpw.plist diff --git a/libsecurity_checkpw/checkpw.pam b/Security/libsecurity_checkpw/checkpw.pam similarity index 100% rename from libsecurity_checkpw/checkpw.pam rename to Security/libsecurity_checkpw/checkpw.pam diff --git a/libsecurity_checkpw/lib/checkpw.c b/Security/libsecurity_checkpw/lib/checkpw.c similarity index 97% rename from libsecurity_checkpw/lib/checkpw.c rename to Security/libsecurity_checkpw/lib/checkpw.c index 1d1b2071..a7a8ec4e 100644 --- a/libsecurity_checkpw/lib/checkpw.c +++ b/Security/libsecurity_checkpw/lib/checkpw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2012 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_checkpw/lib/checkpw.h b/Security/libsecurity_checkpw/lib/checkpw.h similarity index 96% rename from libsecurity_checkpw/lib/checkpw.h rename to Security/libsecurity_checkpw/lib/checkpw.h index 4625903d..3adaad65 100644 --- a/libsecurity_checkpw/lib/checkpw.h +++ b/Security/libsecurity_checkpw/lib/checkpw.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2011 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_checkpw/lib/security_checkpw.exp b/Security/libsecurity_checkpw/lib/security_checkpw.exp similarity index 100% rename from libsecurity_checkpw/lib/security_checkpw.exp rename to Security/libsecurity_checkpw/lib/security_checkpw.exp diff --git a/libsecurity_checkpw/libsecurity_checkpw.xcodeproj/project.pbxproj b/Security/libsecurity_checkpw/libsecurity_checkpw.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_checkpw/libsecurity_checkpw.xcodeproj/project.pbxproj rename to Security/libsecurity_checkpw/libsecurity_checkpw.xcodeproj/project.pbxproj diff --git a/libsecurity_checkpw/test/perf-checkpw.c b/Security/libsecurity_checkpw/test/perf-checkpw.c similarity index 100% rename from libsecurity_checkpw/test/perf-checkpw.c rename to Security/libsecurity_checkpw/test/perf-checkpw.c diff --git a/libsecurity_checkpw/test/test-checkpw.c b/Security/libsecurity_checkpw/test/test-checkpw.c similarity index 100% rename from libsecurity_checkpw/test/test-checkpw.c rename to Security/libsecurity_checkpw/test/test-checkpw.c diff --git a/libsecurity_cms/APPLE_LICENSE b/Security/libsecurity_cms/APPLE_LICENSE similarity index 100% rename from libsecurity_cms/APPLE_LICENSE rename to Security/libsecurity_cms/APPLE_LICENSE diff --git a/libsecurity_cms/Info-security_cms.plist b/Security/libsecurity_cms/Info-security_cms.plist similarity index 100% rename from libsecurity_cms/Info-security_cms.plist rename to Security/libsecurity_cms/Info-security_cms.plist diff --git a/libsecurity_cms/lib/CMSDecoder.cpp b/Security/libsecurity_cms/lib/CMSDecoder.cpp similarity index 98% rename from libsecurity_cms/lib/CMSDecoder.cpp rename to Security/libsecurity_cms/lib/CMSDecoder.cpp index 930c0c5e..e4ed76ad 100644 --- a/libsecurity_cms/lib/CMSDecoder.cpp +++ b/Security/libsecurity_cms/lib/CMSDecoder.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -882,10 +882,20 @@ xit: * * This cannot be called until after CMSDecoderFinalizeMessage() is called. */ + OSStatus CMSDecoderCopySignerTimestamp( CMSDecoderRef cmsDecoder, size_t signerIndex, /* usually 0 */ CFAbsoluteTime *timestamp) /* RETURNED */ +{ + return CMSDecoderCopySignerTimestampWithPolicy(cmsDecoder, NULL, signerIndex, timestamp); +} + +OSStatus CMSDecoderCopySignerTimestampWithPolicy( + CMSDecoderRef cmsDecoder, + CFTypeRef timeStampPolicy, + size_t signerIndex, /* usually 0 */ + CFAbsoluteTime *timestamp) /* RETURNED */ { OSStatus status = errSecParam; SecCmsMessageRef cmsg; @@ -903,7 +913,7 @@ OSStatus CMSDecoderCopySignerTimestamp( if ((signedData = SecCmsSignedDataRef(SecCmsContentInfoGetContent(ci)))) if (SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex)) { - status = SecCmsSignerInfoGetTimestampTime(signerInfo, timestamp); + status = SecCmsSignerInfoGetTimestampTimeWithPolicy(signerInfo, timeStampPolicy, timestamp); break; } } diff --git a/libsecurity_cms/lib/CMSDecoder.h b/Security/libsecurity_cms/lib/CMSDecoder.h similarity index 93% rename from libsecurity_cms/lib/CMSDecoder.h rename to Security/libsecurity_cms/lib/CMSDecoder.h index 6886be00..3606fa0a 100644 --- a/libsecurity_cms/lib/CMSDecoder.h +++ b/Security/libsecurity_cms/lib/CMSDecoder.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -336,6 +336,23 @@ OSStatus CMSDecoderCopySignerTimestamp( CFAbsoluteTime *timestamp) /* RETURNED */ __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_NA); + /* + * Obtain the timestamp of signer 'signerIndex' of a CMS message, if + * present. This timestamp is an authenticated timestamp provided by + * a timestamping authority. Use the policy provided as a parameter + * + * 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 CMSDecoderCopySignerTimestampWithPolicy( + CMSDecoderRef cmsDecoder, + CFTypeRef timeStampPolicy, + size_t signerIndex, /* usually 0 */ + CFAbsoluteTime *timestamp) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_NA); + /* * Obtain an array of the certificates in a timestamp response. Elements of the * returned array are SecCertificateRefs. The caller must CFRelease the returned diff --git a/libsecurity_cms/lib/CMSEncoder.cpp b/Security/libsecurity_cms/lib/CMSEncoder.cpp similarity index 98% rename from libsecurity_cms/lib/CMSEncoder.cpp rename to Security/libsecurity_cms/lib/CMSEncoder.cpp index 36a2f1bd..12829f51 100644 --- a/libsecurity_cms/lib/CMSEncoder.cpp +++ b/Security/libsecurity_cms/lib/CMSEncoder.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -1408,7 +1408,20 @@ OSStatus CMSEncoderGetEncoder( * This cannot be called until after CMSEncoderCopyEncodedContent() is called. */ OSStatus CMSEncoderCopySignerTimestamp( + CMSEncoderRef cmsEncoder, + size_t signerIndex, /* usually 0 */ + CFAbsoluteTime *timestamp) /* RETURNED */ +{ + return CMSEncoderCopySignerTimestampWithPolicy( + cmsEncoder, + NULL, + signerIndex, + timestamp); +} + +OSStatus CMSEncoderCopySignerTimestampWithPolicy( CMSEncoderRef cmsEncoder, + CFTypeRef timeStampPolicy, size_t signerIndex, /* usually 0 */ CFAbsoluteTime *timestamp) /* RETURNED */ { @@ -1428,7 +1441,7 @@ OSStatus CMSEncoderCopySignerTimestamp( if ((signedData = SecCmsSignedDataRef(SecCmsContentInfoGetContent(ci)))) if (SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex)) { - status = SecCmsSignerInfoGetTimestampTime(signerInfo, timestamp); + status = SecCmsSignerInfoGetTimestampTimeWithPolicy(signerInfo, timeStampPolicy, timestamp); break; } } diff --git a/libsecurity_cms/lib/CMSEncoder.h b/Security/libsecurity_cms/lib/CMSEncoder.h similarity index 97% rename from libsecurity_cms/lib/CMSEncoder.h rename to Security/libsecurity_cms/lib/CMSEncoder.h index 0ae1d8c8..b887f4de 100644 --- a/libsecurity_cms/lib/CMSEncoder.h +++ b/Security/libsecurity_cms/lib/CMSEncoder.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -395,6 +395,13 @@ OSStatus CMSEncoderCopySignerTimestamp( CFAbsoluteTime *timestamp) /* RETURNED */ __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_NA); +OSStatus CMSEncoderCopySignerTimestampWithPolicy( + CMSEncoderRef cmsEncoder, + CFTypeRef timeStampPolicy, + size_t signerIndex, /* usually 0 */ + CFAbsoluteTime *timestamp) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_NA); + #ifdef __cplusplus } #endif diff --git a/libsecurity_cms/lib/CMSPrivate.h b/Security/libsecurity_cms/lib/CMSPrivate.h similarity index 98% rename from libsecurity_cms/lib/CMSPrivate.h rename to Security/libsecurity_cms/lib/CMSPrivate.h index bf2e7ab4..3b90d51a 100644 --- a/libsecurity_cms/lib/CMSPrivate.h +++ b/Security/libsecurity_cms/lib/CMSPrivate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cms/lib/CMSUtils.cpp b/Security/libsecurity_cms/lib/CMSUtils.cpp similarity index 97% rename from libsecurity_cms/lib/CMSUtils.cpp rename to Security/libsecurity_cms/lib/CMSUtils.cpp index da0d7ad4..61122562 100644 --- a/libsecurity_cms/lib/CMSUtils.cpp +++ b/Security/libsecurity_cms/lib/CMSUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,7 +23,6 @@ /* * CMSUtils.cpp - common utility routines for libCMS. - * Created 1/12/06 by Doug Mitchell. */ #include "CMSUtils.h" diff --git a/libsecurity_cms/lib/CMSUtils.h b/Security/libsecurity_cms/lib/CMSUtils.h similarity index 97% rename from libsecurity_cms/lib/CMSUtils.h rename to Security/libsecurity_cms/lib/CMSUtils.h index 17bedd86..6211a11d 100644 --- a/libsecurity_cms/lib/CMSUtils.h +++ b/Security/libsecurity_cms/lib/CMSUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cms/lib/security_cms.exp b/Security/libsecurity_cms/lib/security_cms.exp similarity index 93% rename from libsecurity_cms/lib/security_cms.exp rename to Security/libsecurity_cms/lib/security_cms.exp index f43d1c02..c416c46a 100644 --- a/libsecurity_cms/lib/security_cms.exp +++ b/Security/libsecurity_cms/lib/security_cms.exp @@ -42,5 +42,9 @@ _CMSDecoderCopySignerEmailAddress _CMSDecoderCopySignerCert _CMSDecoderCopySignerSigningTime _CMSDecoderCopySignerTimestamp +_CMSDecoderCopySignerTimestampWithPolicy _CMSDecoderCopySignerTimestampCertificates _CMSEncoderCopySignerTimestamp +_CMSEncoderCopySignerTimestampWithPolicy + + diff --git a/libsecurity_cms/libsecurity_cms.xcodeproj/project.pbxproj b/Security/libsecurity_cms/libsecurity_cms.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_cms/libsecurity_cms.xcodeproj/project.pbxproj rename to Security/libsecurity_cms/libsecurity_cms.xcodeproj/project.pbxproj diff --git a/libsecurity_codesigning/APPLE_LICENSE b/Security/libsecurity_codesigning/APPLE_LICENSE similarity index 100% rename from libsecurity_codesigning/APPLE_LICENSE rename to Security/libsecurity_codesigning/APPLE_LICENSE diff --git a/libsecurity_codesigning/CodeSigningHelper/CodeSigningHelper-Info.plist b/Security/libsecurity_codesigning/CodeSigningHelper/CodeSigningHelper-Info.plist similarity index 100% rename from libsecurity_codesigning/CodeSigningHelper/CodeSigningHelper-Info.plist rename to Security/libsecurity_codesigning/CodeSigningHelper/CodeSigningHelper-Info.plist diff --git a/libsecurity_codesigning/CodeSigningHelper/com.apple.CodeSigningHelper.sb b/Security/libsecurity_codesigning/CodeSigningHelper/com.apple.CodeSigningHelper.sb similarity index 100% rename from libsecurity_codesigning/CodeSigningHelper/com.apple.CodeSigningHelper.sb rename to Security/libsecurity_codesigning/CodeSigningHelper/com.apple.CodeSigningHelper.sb diff --git a/Security/libsecurity_codesigning/CodeSigningHelper/main.c b/Security/libsecurity_codesigning/CodeSigningHelper/main.c new file mode 100644 index 00000000..553a8c4d --- /dev/null +++ b/Security/libsecurity_codesigning/CodeSigningHelper/main.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * A simple XPCService that returns the Info.plist for a specific pid, + * the use-case is is for service that is not running as the user or + * in a sandbox and can't access the file directly. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static CFDataRef +CopyDataFromURL(CFURLRef url) +{ + CFReadStreamRef stream = CFReadStreamCreateWithFile(NULL, url); + if (stream == NULL) + return NULL; + + if (!CFReadStreamOpen(stream)) { + CFRelease(stream); + return NULL; + } + + CFMutableDataRef data = CFDataCreateMutable(NULL, 0); + if (data == NULL) { + CFRelease(stream); + return NULL; + } + + UInt8 buf[4096]; + + while (1) { + /* limit to 100k */ + if (CFDataGetLength(data) > 100 * 1024) { + syslog(LOG_ERR, "refusing to handle back Info.plist that is more then 100K"); + CFRelease(stream); + CFRelease(data); + return NULL; + } + CFIndex readBytes = CFReadStreamRead(stream, buf, sizeof(buf)); + if (readBytes == 0) { + break; + } else if (readBytes <= 0) { + CFRelease(data); + CFRelease(stream); + return NULL; + } + + assert(readBytes <= sizeof(buf)); + CFDataAppendBytes(data, (void *)buf, readBytes); + } + + CFReadStreamClose(stream); + CFRelease(stream); + + return data; +} + +static void +fetchData(xpc_connection_t peer, xpc_object_t event) +{ + CFBundleRef bundle = NULL; + char path[MAXPATHLEN]; + pid_t pid; + + pid = (pid_t)xpc_dictionary_get_int64(event, "pid"); + if (pid <= 0) + return; + + xpc_object_t reply = xpc_dictionary_create_reply(event); + if (reply == NULL) + return; + + if (proc_pidpath(pid, path, sizeof(path)) == 0) { + xpc_dictionary_set_string(reply, "error", "no process for that pid"); + goto send; + } + path[sizeof(path) - 1] = '\0'; + + CFURLRef url = CFURLCreateFromFileSystemRepresentation(NULL, (const uint8_t *)path, strlen(path), 0); + if (url == NULL) { + xpc_dictionary_set_string(reply, "error", "failed to create URL"); + goto send; + } + + bundle = _CFBundleCreateWithExecutableURLIfMightBeBundle(NULL, url); + CFRelease(url); + if (bundle == NULL) { + xpc_dictionary_set_string(reply, "error", "Failed to create a bundle"); + goto send; + } + + CFURLRef infoPlistURL = _CFBundleCopyInfoPlistURL(bundle); + if (infoPlistURL == NULL) { + xpc_dictionary_set_string(reply, "error", "Info.plist missing"); + goto send; + } + + CFDataRef data = CopyDataFromURL(infoPlistURL); + CFRelease(infoPlistURL); + if (data == NULL) { + xpc_dictionary_set_string(reply, "error", "can't get content of Info.plist"); + goto send; + } + + xpc_dictionary_set_data(reply, "infoPlist", CFDataGetBytePtr(data), CFDataGetLength(data)); + CFRelease(data); + + CFURLRef bundleURL = CFBundleCopyBundleURL(bundle); + if (bundleURL == NULL) + goto send; + + data = CFURLCreateData(NULL, bundleURL, kCFStringEncodingUTF8, true); + CFRelease(bundleURL); + if (data == NULL) + goto send; + + xpc_dictionary_set_data(reply, "bundleURL", CFDataGetBytePtr(data), CFDataGetLength(data)); + CFRelease(data); + +send: + if (bundle) + CFRelease(bundle); + xpc_connection_send_message(peer, reply); + xpc_release(reply); +} + + +static void CodeSigningHelper_peer_event_handler(xpc_connection_t peer, xpc_object_t event) +{ + xpc_type_t type = xpc_get_type(event); + if (type == XPC_TYPE_ERROR) + return; + + assert(type == XPC_TYPE_DICTIONARY); + + const char *cmd = xpc_dictionary_get_string(event, "command"); + if (cmd == NULL) { + xpc_connection_cancel(peer); + } else if (strcmp(cmd, "fetchData") == 0) + fetchData(peer, event); + else { + syslog(LOG_ERR, "peer sent invalid command %s", cmd); + xpc_connection_cancel(peer); + } +} + +static void CodeSigningHelper_event_handler(xpc_connection_t peer) +{ + xpc_connection_set_event_handler(peer, ^(xpc_object_t event) { + CodeSigningHelper_peer_event_handler(peer, event); + }); + xpc_connection_resume(peer); +} + +int main(int argc, const char *argv[]) +{ + char *error = NULL; + if (sandbox_init("com.apple.CodeSigningHelper", SANDBOX_NAMED, &error)) { + syslog(LOG_ERR, "failed to enter sandbox: %s", error); + exit(EXIT_FAILURE); + } + xpc_main(CodeSigningHelper_event_handler); + return 0; +} + diff --git a/libsecurity_codesigning/Info-security_codesigning.plist b/Security/libsecurity_codesigning/Info-security_codesigning.plist similarity index 100% rename from libsecurity_codesigning/Info-security_codesigning.plist rename to Security/libsecurity_codesigning/Info-security_codesigning.plist diff --git a/libsecurity_codesigning/antlr2/AUTHORS b/Security/libsecurity_codesigning/antlr2/AUTHORS similarity index 100% rename from libsecurity_codesigning/antlr2/AUTHORS rename to Security/libsecurity_codesigning/antlr2/AUTHORS diff --git a/libsecurity_codesigning/antlr2/ChangeLog b/Security/libsecurity_codesigning/antlr2/ChangeLog similarity index 100% rename from libsecurity_codesigning/antlr2/ChangeLog rename to Security/libsecurity_codesigning/antlr2/ChangeLog diff --git a/libsecurity_codesigning/antlr2/LICENSE.txt b/Security/libsecurity_codesigning/antlr2/LICENSE.txt similarity index 100% rename from libsecurity_codesigning/antlr2/LICENSE.txt rename to Security/libsecurity_codesigning/antlr2/LICENSE.txt diff --git a/libsecurity_codesigning/antlr2/Makefile.in b/Security/libsecurity_codesigning/antlr2/Makefile.in similarity index 100% rename from libsecurity_codesigning/antlr2/Makefile.in rename to Security/libsecurity_codesigning/antlr2/Makefile.in diff --git a/libsecurity_codesigning/antlr2/README b/Security/libsecurity_codesigning/antlr2/README similarity index 100% rename from libsecurity_codesigning/antlr2/README rename to Security/libsecurity_codesigning/antlr2/README diff --git a/libsecurity_codesigning/antlr2/TODO b/Security/libsecurity_codesigning/antlr2/TODO similarity index 100% rename from libsecurity_codesigning/antlr2/TODO rename to Security/libsecurity_codesigning/antlr2/TODO diff --git a/libsecurity_codesigning/antlr2/antlr.jar b/Security/libsecurity_codesigning/antlr2/antlr.jar similarity index 100% rename from libsecurity_codesigning/antlr2/antlr.jar rename to Security/libsecurity_codesigning/antlr2/antlr.jar diff --git a/libsecurity_codesigning/antlr2/antlr/ANTLRException.hpp b/Security/libsecurity_codesigning/antlr2/antlr/ANTLRException.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/ANTLRException.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/ANTLRException.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/ANTLRUtil.hpp b/Security/libsecurity_codesigning/antlr2/antlr/ANTLRUtil.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/ANTLRUtil.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/ANTLRUtil.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/AST.hpp b/Security/libsecurity_codesigning/antlr2/antlr/AST.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/AST.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/AST.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/ASTArray.hpp b/Security/libsecurity_codesigning/antlr2/antlr/ASTArray.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/ASTArray.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/ASTArray.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/ASTFactory.hpp b/Security/libsecurity_codesigning/antlr2/antlr/ASTFactory.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/ASTFactory.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/ASTFactory.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/ASTNULLType.hpp b/Security/libsecurity_codesigning/antlr2/antlr/ASTNULLType.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/ASTNULLType.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/ASTNULLType.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/ASTPair.hpp b/Security/libsecurity_codesigning/antlr2/antlr/ASTPair.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/ASTPair.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/ASTPair.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/ASTRefCount.hpp b/Security/libsecurity_codesigning/antlr2/antlr/ASTRefCount.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/ASTRefCount.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/ASTRefCount.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/BaseAST.hpp b/Security/libsecurity_codesigning/antlr2/antlr/BaseAST.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/BaseAST.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/BaseAST.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/BitSet.hpp b/Security/libsecurity_codesigning/antlr2/antlr/BitSet.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/BitSet.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/BitSet.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/CharBuffer.hpp b/Security/libsecurity_codesigning/antlr2/antlr/CharBuffer.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/CharBuffer.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/CharBuffer.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/CharInputBuffer.hpp b/Security/libsecurity_codesigning/antlr2/antlr/CharInputBuffer.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/CharInputBuffer.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/CharInputBuffer.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/CharScanner.hpp b/Security/libsecurity_codesigning/antlr2/antlr/CharScanner.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/CharScanner.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/CharScanner.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/CharStreamException.hpp b/Security/libsecurity_codesigning/antlr2/antlr/CharStreamException.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/CharStreamException.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/CharStreamException.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/CharStreamIOException.hpp b/Security/libsecurity_codesigning/antlr2/antlr/CharStreamIOException.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/CharStreamIOException.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/CharStreamIOException.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/CircularQueue.hpp b/Security/libsecurity_codesigning/antlr2/antlr/CircularQueue.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/CircularQueue.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/CircularQueue.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/CommonAST.hpp b/Security/libsecurity_codesigning/antlr2/antlr/CommonAST.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/CommonAST.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/CommonAST.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/CommonASTWithHiddenTokens.hpp b/Security/libsecurity_codesigning/antlr2/antlr/CommonASTWithHiddenTokens.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/CommonASTWithHiddenTokens.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/CommonASTWithHiddenTokens.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/CommonHiddenStreamToken.hpp b/Security/libsecurity_codesigning/antlr2/antlr/CommonHiddenStreamToken.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/CommonHiddenStreamToken.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/CommonHiddenStreamToken.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/CommonToken.hpp b/Security/libsecurity_codesigning/antlr2/antlr/CommonToken.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/CommonToken.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/CommonToken.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/IOException.hpp b/Security/libsecurity_codesigning/antlr2/antlr/IOException.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/IOException.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/IOException.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/InputBuffer.hpp b/Security/libsecurity_codesigning/antlr2/antlr/InputBuffer.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/InputBuffer.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/InputBuffer.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/LLkParser.hpp b/Security/libsecurity_codesigning/antlr2/antlr/LLkParser.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/LLkParser.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/LLkParser.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/LexerSharedInputState.hpp b/Security/libsecurity_codesigning/antlr2/antlr/LexerSharedInputState.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/LexerSharedInputState.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/LexerSharedInputState.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/Makefile.in b/Security/libsecurity_codesigning/antlr2/antlr/Makefile.in similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/Makefile.in rename to Security/libsecurity_codesigning/antlr2/antlr/Makefile.in diff --git a/libsecurity_codesigning/antlr2/antlr/MismatchedCharException.hpp b/Security/libsecurity_codesigning/antlr2/antlr/MismatchedCharException.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/MismatchedCharException.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/MismatchedCharException.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/MismatchedTokenException.hpp b/Security/libsecurity_codesigning/antlr2/antlr/MismatchedTokenException.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/MismatchedTokenException.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/MismatchedTokenException.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/NoViableAltException.hpp b/Security/libsecurity_codesigning/antlr2/antlr/NoViableAltException.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/NoViableAltException.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/NoViableAltException.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/NoViableAltForCharException.hpp b/Security/libsecurity_codesigning/antlr2/antlr/NoViableAltForCharException.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/NoViableAltForCharException.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/NoViableAltForCharException.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/Parser.hpp b/Security/libsecurity_codesigning/antlr2/antlr/Parser.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/Parser.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/Parser.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/ParserSharedInputState.hpp b/Security/libsecurity_codesigning/antlr2/antlr/ParserSharedInputState.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/ParserSharedInputState.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/ParserSharedInputState.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/RecognitionException.hpp b/Security/libsecurity_codesigning/antlr2/antlr/RecognitionException.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/RecognitionException.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/RecognitionException.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/RefCount.hpp b/Security/libsecurity_codesigning/antlr2/antlr/RefCount.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/RefCount.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/RefCount.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/SemanticException.hpp b/Security/libsecurity_codesigning/antlr2/antlr/SemanticException.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/SemanticException.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/SemanticException.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/String.hpp b/Security/libsecurity_codesigning/antlr2/antlr/String.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/String.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/String.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/Token.hpp b/Security/libsecurity_codesigning/antlr2/antlr/Token.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/Token.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/Token.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/TokenBuffer.hpp b/Security/libsecurity_codesigning/antlr2/antlr/TokenBuffer.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/TokenBuffer.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/TokenBuffer.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/TokenRefCount.hpp b/Security/libsecurity_codesigning/antlr2/antlr/TokenRefCount.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/TokenRefCount.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/TokenRefCount.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/TokenStream.hpp b/Security/libsecurity_codesigning/antlr2/antlr/TokenStream.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/TokenStream.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/TokenStream.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/TokenStreamBasicFilter.hpp b/Security/libsecurity_codesigning/antlr2/antlr/TokenStreamBasicFilter.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/TokenStreamBasicFilter.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/TokenStreamBasicFilter.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/TokenStreamException.hpp b/Security/libsecurity_codesigning/antlr2/antlr/TokenStreamException.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/TokenStreamException.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/TokenStreamException.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/TokenStreamHiddenTokenFilter.hpp b/Security/libsecurity_codesigning/antlr2/antlr/TokenStreamHiddenTokenFilter.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/TokenStreamHiddenTokenFilter.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/TokenStreamHiddenTokenFilter.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/TokenStreamIOException.hpp b/Security/libsecurity_codesigning/antlr2/antlr/TokenStreamIOException.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/TokenStreamIOException.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/TokenStreamIOException.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/TokenStreamRecognitionException.hpp b/Security/libsecurity_codesigning/antlr2/antlr/TokenStreamRecognitionException.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/TokenStreamRecognitionException.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/TokenStreamRecognitionException.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/TokenStreamRetryException.hpp b/Security/libsecurity_codesigning/antlr2/antlr/TokenStreamRetryException.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/TokenStreamRetryException.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/TokenStreamRetryException.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/TokenStreamRewriteEngine.hpp b/Security/libsecurity_codesigning/antlr2/antlr/TokenStreamRewriteEngine.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/TokenStreamRewriteEngine.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/TokenStreamRewriteEngine.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/TokenStreamSelector.hpp b/Security/libsecurity_codesigning/antlr2/antlr/TokenStreamSelector.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/TokenStreamSelector.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/TokenStreamSelector.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/TokenWithIndex.hpp b/Security/libsecurity_codesigning/antlr2/antlr/TokenWithIndex.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/TokenWithIndex.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/TokenWithIndex.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/TreeParser.hpp b/Security/libsecurity_codesigning/antlr2/antlr/TreeParser.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/TreeParser.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/TreeParser.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/TreeParserSharedInputState.hpp b/Security/libsecurity_codesigning/antlr2/antlr/TreeParserSharedInputState.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/TreeParserSharedInputState.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/TreeParserSharedInputState.hpp diff --git a/libsecurity_codesigning/antlr2/antlr/config.hpp b/Security/libsecurity_codesigning/antlr2/antlr/config.hpp similarity index 100% rename from libsecurity_codesigning/antlr2/antlr/config.hpp rename to Security/libsecurity_codesigning/antlr2/antlr/config.hpp diff --git a/libsecurity_codesigning/antlr2/contrib/bcb4/README b/Security/libsecurity_codesigning/antlr2/contrib/bcb4/README similarity index 100% rename from libsecurity_codesigning/antlr2/contrib/bcb4/README rename to Security/libsecurity_codesigning/antlr2/contrib/bcb4/README diff --git a/libsecurity_codesigning/antlr2/contrib/bcb4/antlr.bpr b/Security/libsecurity_codesigning/antlr2/contrib/bcb4/antlr.bpr similarity index 100% rename from libsecurity_codesigning/antlr2/contrib/bcb4/antlr.bpr rename to Security/libsecurity_codesigning/antlr2/contrib/bcb4/antlr.bpr diff --git a/libsecurity_codesigning/antlr2/contrib/bcb4/antlr.cpp b/Security/libsecurity_codesigning/antlr2/contrib/bcb4/antlr.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/contrib/bcb4/antlr.cpp rename to Security/libsecurity_codesigning/antlr2/contrib/bcb4/antlr.cpp diff --git a/libsecurity_codesigning/antlr2/doxygen.cfg b/Security/libsecurity_codesigning/antlr2/doxygen.cfg similarity index 100% rename from libsecurity_codesigning/antlr2/doxygen.cfg rename to Security/libsecurity_codesigning/antlr2/doxygen.cfg diff --git a/libsecurity_codesigning/antlr2/libsecurity_codesigning.plist b/Security/libsecurity_codesigning/antlr2/libsecurity_codesigning.plist similarity index 100% rename from libsecurity_codesigning/antlr2/libsecurity_codesigning.plist rename to Security/libsecurity_codesigning/antlr2/libsecurity_codesigning.plist diff --git a/libsecurity_codesigning/antlr2/libsecurity_codesigning.txt b/Security/libsecurity_codesigning/antlr2/libsecurity_codesigning.txt similarity index 100% rename from libsecurity_codesigning/antlr2/libsecurity_codesigning.txt rename to Security/libsecurity_codesigning/antlr2/libsecurity_codesigning.txt diff --git a/libsecurity_codesigning/antlr2/scripts/cr_stripper.sh b/Security/libsecurity_codesigning/antlr2/scripts/cr_stripper.sh similarity index 100% rename from libsecurity_codesigning/antlr2/scripts/cr_stripper.sh rename to Security/libsecurity_codesigning/antlr2/scripts/cr_stripper.sh diff --git a/libsecurity_codesigning/antlr2/scripts/make_change_log.tcl b/Security/libsecurity_codesigning/antlr2/scripts/make_change_log.tcl similarity index 100% rename from libsecurity_codesigning/antlr2/scripts/make_change_log.tcl rename to Security/libsecurity_codesigning/antlr2/scripts/make_change_log.tcl diff --git a/libsecurity_codesigning/antlr2/src/ANTLRUtil.cpp b/Security/libsecurity_codesigning/antlr2/src/ANTLRUtil.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/ANTLRUtil.cpp rename to Security/libsecurity_codesigning/antlr2/src/ANTLRUtil.cpp diff --git a/libsecurity_codesigning/antlr2/src/ASTFactory.cpp b/Security/libsecurity_codesigning/antlr2/src/ASTFactory.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/ASTFactory.cpp rename to Security/libsecurity_codesigning/antlr2/src/ASTFactory.cpp diff --git a/libsecurity_codesigning/antlr2/src/ASTNULLType.cpp b/Security/libsecurity_codesigning/antlr2/src/ASTNULLType.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/ASTNULLType.cpp rename to Security/libsecurity_codesigning/antlr2/src/ASTNULLType.cpp diff --git a/libsecurity_codesigning/antlr2/src/ASTRefCount.cpp b/Security/libsecurity_codesigning/antlr2/src/ASTRefCount.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/ASTRefCount.cpp rename to Security/libsecurity_codesigning/antlr2/src/ASTRefCount.cpp diff --git a/libsecurity_codesigning/antlr2/src/BaseAST.cpp b/Security/libsecurity_codesigning/antlr2/src/BaseAST.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/BaseAST.cpp rename to Security/libsecurity_codesigning/antlr2/src/BaseAST.cpp diff --git a/libsecurity_codesigning/antlr2/src/BitSet.cpp b/Security/libsecurity_codesigning/antlr2/src/BitSet.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/BitSet.cpp rename to Security/libsecurity_codesigning/antlr2/src/BitSet.cpp diff --git a/libsecurity_codesigning/antlr2/src/CharBuffer.cpp b/Security/libsecurity_codesigning/antlr2/src/CharBuffer.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/CharBuffer.cpp rename to Security/libsecurity_codesigning/antlr2/src/CharBuffer.cpp diff --git a/libsecurity_codesigning/antlr2/src/CharScanner.cpp b/Security/libsecurity_codesigning/antlr2/src/CharScanner.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/CharScanner.cpp rename to Security/libsecurity_codesigning/antlr2/src/CharScanner.cpp diff --git a/libsecurity_codesigning/antlr2/src/CommonAST.cpp b/Security/libsecurity_codesigning/antlr2/src/CommonAST.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/CommonAST.cpp rename to Security/libsecurity_codesigning/antlr2/src/CommonAST.cpp diff --git a/libsecurity_codesigning/antlr2/src/CommonASTWithHiddenTokens.cpp b/Security/libsecurity_codesigning/antlr2/src/CommonASTWithHiddenTokens.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/CommonASTWithHiddenTokens.cpp rename to Security/libsecurity_codesigning/antlr2/src/CommonASTWithHiddenTokens.cpp diff --git a/libsecurity_codesigning/antlr2/src/CommonHiddenStreamToken.cpp b/Security/libsecurity_codesigning/antlr2/src/CommonHiddenStreamToken.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/CommonHiddenStreamToken.cpp rename to Security/libsecurity_codesigning/antlr2/src/CommonHiddenStreamToken.cpp diff --git a/libsecurity_codesigning/antlr2/src/CommonToken.cpp b/Security/libsecurity_codesigning/antlr2/src/CommonToken.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/CommonToken.cpp rename to Security/libsecurity_codesigning/antlr2/src/CommonToken.cpp diff --git a/libsecurity_codesigning/antlr2/src/InputBuffer.cpp b/Security/libsecurity_codesigning/antlr2/src/InputBuffer.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/InputBuffer.cpp rename to Security/libsecurity_codesigning/antlr2/src/InputBuffer.cpp diff --git a/libsecurity_codesigning/antlr2/src/LLkParser.cpp b/Security/libsecurity_codesigning/antlr2/src/LLkParser.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/LLkParser.cpp rename to Security/libsecurity_codesigning/antlr2/src/LLkParser.cpp diff --git a/libsecurity_codesigning/antlr2/src/Makefile.in b/Security/libsecurity_codesigning/antlr2/src/Makefile.in similarity index 100% rename from libsecurity_codesigning/antlr2/src/Makefile.in rename to Security/libsecurity_codesigning/antlr2/src/Makefile.in diff --git a/libsecurity_codesigning/antlr2/src/MismatchedCharException.cpp b/Security/libsecurity_codesigning/antlr2/src/MismatchedCharException.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/MismatchedCharException.cpp rename to Security/libsecurity_codesigning/antlr2/src/MismatchedCharException.cpp diff --git a/libsecurity_codesigning/antlr2/src/MismatchedTokenException.cpp b/Security/libsecurity_codesigning/antlr2/src/MismatchedTokenException.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/MismatchedTokenException.cpp rename to Security/libsecurity_codesigning/antlr2/src/MismatchedTokenException.cpp diff --git a/libsecurity_codesigning/antlr2/src/NoViableAltException.cpp b/Security/libsecurity_codesigning/antlr2/src/NoViableAltException.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/NoViableAltException.cpp rename to Security/libsecurity_codesigning/antlr2/src/NoViableAltException.cpp diff --git a/libsecurity_codesigning/antlr2/src/NoViableAltForCharException.cpp b/Security/libsecurity_codesigning/antlr2/src/NoViableAltForCharException.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/NoViableAltForCharException.cpp rename to Security/libsecurity_codesigning/antlr2/src/NoViableAltForCharException.cpp diff --git a/libsecurity_codesigning/antlr2/src/Parser.cpp b/Security/libsecurity_codesigning/antlr2/src/Parser.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/Parser.cpp rename to Security/libsecurity_codesigning/antlr2/src/Parser.cpp diff --git a/libsecurity_codesigning/antlr2/src/RecognitionException.cpp b/Security/libsecurity_codesigning/antlr2/src/RecognitionException.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/RecognitionException.cpp rename to Security/libsecurity_codesigning/antlr2/src/RecognitionException.cpp diff --git a/libsecurity_codesigning/antlr2/src/String.cpp b/Security/libsecurity_codesigning/antlr2/src/String.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/String.cpp rename to Security/libsecurity_codesigning/antlr2/src/String.cpp diff --git a/libsecurity_codesigning/antlr2/src/Token.cpp b/Security/libsecurity_codesigning/antlr2/src/Token.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/Token.cpp rename to Security/libsecurity_codesigning/antlr2/src/Token.cpp diff --git a/libsecurity_codesigning/antlr2/src/TokenBuffer.cpp b/Security/libsecurity_codesigning/antlr2/src/TokenBuffer.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/TokenBuffer.cpp rename to Security/libsecurity_codesigning/antlr2/src/TokenBuffer.cpp diff --git a/libsecurity_codesigning/antlr2/src/TokenRefCount.cpp b/Security/libsecurity_codesigning/antlr2/src/TokenRefCount.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/TokenRefCount.cpp rename to Security/libsecurity_codesigning/antlr2/src/TokenRefCount.cpp diff --git a/libsecurity_codesigning/antlr2/src/TokenStreamBasicFilter.cpp b/Security/libsecurity_codesigning/antlr2/src/TokenStreamBasicFilter.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/TokenStreamBasicFilter.cpp rename to Security/libsecurity_codesigning/antlr2/src/TokenStreamBasicFilter.cpp diff --git a/libsecurity_codesigning/antlr2/src/TokenStreamHiddenTokenFilter.cpp b/Security/libsecurity_codesigning/antlr2/src/TokenStreamHiddenTokenFilter.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/TokenStreamHiddenTokenFilter.cpp rename to Security/libsecurity_codesigning/antlr2/src/TokenStreamHiddenTokenFilter.cpp diff --git a/libsecurity_codesigning/antlr2/src/TokenStreamRewriteEngine.cpp b/Security/libsecurity_codesigning/antlr2/src/TokenStreamRewriteEngine.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/TokenStreamRewriteEngine.cpp rename to Security/libsecurity_codesigning/antlr2/src/TokenStreamRewriteEngine.cpp diff --git a/libsecurity_codesigning/antlr2/src/TokenStreamSelector.cpp b/Security/libsecurity_codesigning/antlr2/src/TokenStreamSelector.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/TokenStreamSelector.cpp rename to Security/libsecurity_codesigning/antlr2/src/TokenStreamSelector.cpp diff --git a/libsecurity_codesigning/antlr2/src/TreeParser.cpp b/Security/libsecurity_codesigning/antlr2/src/TreeParser.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/TreeParser.cpp rename to Security/libsecurity_codesigning/antlr2/src/TreeParser.cpp diff --git a/libsecurity_codesigning/antlr2/src/dll.cpp b/Security/libsecurity_codesigning/antlr2/src/dll.cpp similarity index 100% rename from libsecurity_codesigning/antlr2/src/dll.cpp rename to Security/libsecurity_codesigning/antlr2/src/dll.cpp diff --git a/libsecurity_codesigning/dtrace/codesign-watch.d b/Security/libsecurity_codesigning/dtrace/codesign-watch.d similarity index 100% rename from libsecurity_codesigning/dtrace/codesign-watch.d rename to Security/libsecurity_codesigning/dtrace/codesign-watch.d diff --git a/libsecurity_codesigning/dtrace/reqint.d b/Security/libsecurity_codesigning/dtrace/reqint.d similarity index 100% rename from libsecurity_codesigning/dtrace/reqint.d rename to Security/libsecurity_codesigning/dtrace/reqint.d diff --git a/libsecurity_codesigning/dtrace/sp-watch.d b/Security/libsecurity_codesigning/dtrace/sp-watch.d similarity index 100% rename from libsecurity_codesigning/dtrace/sp-watch.d rename to Security/libsecurity_codesigning/dtrace/sp-watch.d diff --git a/libsecurity_codesigning/gke/com.apple.gkreport.plist b/Security/libsecurity_codesigning/gke/com.apple.gkreport.plist similarity index 100% rename from libsecurity_codesigning/gke/com.apple.gkreport.plist rename to Security/libsecurity_codesigning/gke/com.apple.gkreport.plist diff --git a/libsecurity_codesigning/gke/gkclear b/Security/libsecurity_codesigning/gke/gkclear similarity index 100% rename from libsecurity_codesigning/gke/gkclear rename to Security/libsecurity_codesigning/gke/gkclear diff --git a/libsecurity_codesigning/gke/gkgenerate b/Security/libsecurity_codesigning/gke/gkgenerate similarity index 100% rename from libsecurity_codesigning/gke/gkgenerate rename to Security/libsecurity_codesigning/gke/gkgenerate diff --git a/libsecurity_codesigning/gke/gkhandmake b/Security/libsecurity_codesigning/gke/gkhandmake similarity index 100% rename from libsecurity_codesigning/gke/gkhandmake rename to Security/libsecurity_codesigning/gke/gkhandmake diff --git a/libsecurity_codesigning/gke/gklist b/Security/libsecurity_codesigning/gke/gklist similarity index 100% rename from libsecurity_codesigning/gke/gklist rename to Security/libsecurity_codesigning/gke/gklist diff --git a/libsecurity_codesigning/gke/gkmerge b/Security/libsecurity_codesigning/gke/gkmerge similarity index 100% rename from libsecurity_codesigning/gke/gkmerge rename to Security/libsecurity_codesigning/gke/gkmerge diff --git a/libsecurity_codesigning/gke/gkrecord b/Security/libsecurity_codesigning/gke/gkrecord similarity index 100% rename from libsecurity_codesigning/gke/gkrecord rename to Security/libsecurity_codesigning/gke/gkrecord diff --git a/libsecurity_codesigning/gke/gkreport b/Security/libsecurity_codesigning/gke/gkreport similarity index 79% rename from libsecurity_codesigning/gke/gkreport rename to Security/libsecurity_codesigning/gke/gkreport index 4dc6da83..8bf49fa5 100755 --- a/libsecurity_codesigning/gke/gkreport +++ b/Security/libsecurity_codesigning/gke/gkreport @@ -5,7 +5,7 @@ main=$(/usr/sbin/spctl --status) gk=$(/usr/sbin/spctl --test-devid-status) /usr/bin/syslog -s -k \ - com.apple.message.domain com.apple.security.assessment.state \ + com.apple.message.domain com.apple.security.assessment.current_state \ com.apple.message.signature "$main" \ com.apple.message.signature2 "$gk" \ Message "Gatekeeper state $main/$gk" diff --git a/libsecurity_codesigning/gke/gkunpack.cpp b/Security/libsecurity_codesigning/gke/gkunpack.cpp similarity index 100% rename from libsecurity_codesigning/gke/gkunpack.cpp rename to Security/libsecurity_codesigning/gke/gkunpack.cpp diff --git a/libsecurity_codesigning/lib/CSCommon.h b/Security/libsecurity_codesigning/lib/CSCommon.h similarity index 95% rename from libsecurity_codesigning/lib/CSCommon.h rename to Security/libsecurity_codesigning/lib/CSCommon.h index 37259229..6d81ca12 100644 --- a/libsecurity_codesigning/lib/CSCommon.h +++ b/Security/libsecurity_codesigning/lib/CSCommon.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -103,12 +103,14 @@ enum { errSecCSResourceNotSupported = -67016, /* unsupported resource found (something not a directory, file or symlink) */ errSecCSRegularFile = -67015, /* the main executable or Info.plist must be a regular file (no symlinks, etc.) */ errSecCSUnsealedAppRoot = -67014, /* unsealed contents present in the bundle root */ - errSecCSWeakResourceRules = -67013, /* resource envelope is obsolete */ + errSecCSWeakResourceRules = -67013, /* resource envelope is obsolete (custom omit rules) */ errSecCSDSStoreSymlink = -67012, /* .DS_Store files cannot be a symlink */ errSecCSAmbiguousBundleFormat = -67011, /* bundle format is ambiguous (could be app or framework) */ errSecCSBadMainExecutable = -67010, /* main executable failed strict validation */ errSecCSBadFrameworkVersion = -67009, /* embedded framework contains modified or invalid version */ errSecCSUnsealedFrameworkRoot = -67008, /* unsealed contents present in the root directory of an embedded framework */ + errSecCSWeakResourceEnvelope = -67007, /* resource envelope is obsolete (version 1 signature) */ + errSecCSCancelled = -67006, /* operation was terminated by explicit cancellation */ }; @@ -193,10 +195,12 @@ enum { typedef uint32_t SecCSFlags; enum { - kSecCSDefaultFlags = 0, /* no particular flags (default behavior) */ + kSecCSDefaultFlags = 0, /* no particular flags (default behavior) */ - kSecCSConsiderExpiration = 1 << 31, /* consider expired certificates invalid */ - kSecCSEnforceRevocationChecks = 1 << 30, /* force revocation checks regardless of preference settings */ + kSecCSConsiderExpiration = 1 << 31, /* consider expired certificates invalid */ + kSecCSEnforceRevocationChecks = 1 << 30, /* force revocation checks regardless of preference settings */ + kSecCSNoNetworkAccess = 1 << 29, /* do not use the network, cancels "kSecCSEnforceRevocationChecks" */ + kSecCSReportProgress = 1 << 28, /* make progress report call-backs when configured */ }; diff --git a/libsecurity_codesigning/lib/CSCommonPriv.h b/Security/libsecurity_codesigning/lib/CSCommonPriv.h similarity index 98% rename from libsecurity_codesigning/lib/CSCommonPriv.h rename to Security/libsecurity_codesigning/lib/CSCommonPriv.h index 81106fbe..08b90df2 100644 --- a/libsecurity_codesigning/lib/CSCommonPriv.h +++ b/Security/libsecurity_codesigning/lib/CSCommonPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/Code.cpp b/Security/libsecurity_codesigning/lib/Code.cpp similarity index 98% rename from libsecurity_codesigning/lib/Code.cpp rename to Security/libsecurity_codesigning/lib/Code.cpp index ec5da804..643c4f58 100644 --- a/libsecurity_codesigning/lib/Code.cpp +++ b/Security/libsecurity_codesigning/lib/Code.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2011,2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -201,6 +201,7 @@ void SecCode::checkValidity(SecCSFlags flags) this->host()->checkValidity(flags); SecStaticCode *myDisk = this->staticCode(); + myDisk->setValidationFlags(flags); SecStaticCode *hostDisk = this->host()->staticCode(); // check my static state diff --git a/libsecurity_codesigning/lib/Code.h b/Security/libsecurity_codesigning/lib/Code.h similarity index 97% rename from libsecurity_codesigning/lib/Code.h rename to Security/libsecurity_codesigning/lib/Code.h index 715378c2..aa5942c9 100644 --- a/libsecurity_codesigning/lib/Code.h +++ b/Security/libsecurity_codesigning/lib/Code.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/CodeSigner.cpp b/Security/libsecurity_codesigning/lib/CodeSigner.cpp similarity index 98% rename from libsecurity_codesigning/lib/CodeSigner.cpp rename to Security/libsecurity_codesigning/lib/CodeSigner.cpp index 004fb125..004b25b7 100644 --- a/libsecurity_codesigning/lib/CodeSigner.cpp +++ b/Security/libsecurity_codesigning/lib/CodeSigner.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -132,6 +132,7 @@ bool SecCodeSigner::valid() const // void SecCodeSigner::sign(SecStaticCode *code, SecCSFlags flags) { + code->setValidationFlags(flags); if (code->isSigned() && (flags & kSecCSSignPreserveSignature)) return; Signer operation(*this, code); diff --git a/libsecurity_codesigning/lib/CodeSigner.h b/Security/libsecurity_codesigning/lib/CodeSigner.h similarity index 98% rename from libsecurity_codesigning/lib/CodeSigner.h rename to Security/libsecurity_codesigning/lib/CodeSigner.h index 18f327ef..be888dbd 100644 --- a/libsecurity_codesigning/lib/CodeSigner.h +++ b/Security/libsecurity_codesigning/lib/CodeSigner.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/CodeSigning.h b/Security/libsecurity_codesigning/lib/CodeSigning.h similarity index 95% rename from libsecurity_codesigning/lib/CodeSigning.h rename to Security/libsecurity_codesigning/lib/CodeSigning.h index a33e9e73..138801b2 100644 --- a/libsecurity_codesigning/lib/CodeSigning.h +++ b/Security/libsecurity_codesigning/lib/CodeSigning.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/RequirementKeywords.h b/Security/libsecurity_codesigning/lib/RequirementKeywords.h similarity index 100% rename from libsecurity_codesigning/lib/RequirementKeywords.h rename to Security/libsecurity_codesigning/lib/RequirementKeywords.h diff --git a/libsecurity_codesigning/lib/RequirementLexer.cpp b/Security/libsecurity_codesigning/lib/RequirementLexer.cpp similarity index 100% rename from libsecurity_codesigning/lib/RequirementLexer.cpp rename to Security/libsecurity_codesigning/lib/RequirementLexer.cpp diff --git a/libsecurity_codesigning/lib/RequirementLexer.hpp b/Security/libsecurity_codesigning/lib/RequirementLexer.hpp similarity index 100% rename from libsecurity_codesigning/lib/RequirementLexer.hpp rename to Security/libsecurity_codesigning/lib/RequirementLexer.hpp diff --git a/libsecurity_codesigning/lib/RequirementParser.cpp b/Security/libsecurity_codesigning/lib/RequirementParser.cpp similarity index 100% rename from libsecurity_codesigning/lib/RequirementParser.cpp rename to Security/libsecurity_codesigning/lib/RequirementParser.cpp diff --git a/libsecurity_codesigning/lib/RequirementParser.hpp b/Security/libsecurity_codesigning/lib/RequirementParser.hpp similarity index 100% rename from libsecurity_codesigning/lib/RequirementParser.hpp rename to Security/libsecurity_codesigning/lib/RequirementParser.hpp diff --git a/libsecurity_codesigning/lib/RequirementParserTokenTypes.hpp b/Security/libsecurity_codesigning/lib/RequirementParserTokenTypes.hpp similarity index 100% rename from libsecurity_codesigning/lib/RequirementParserTokenTypes.hpp rename to Security/libsecurity_codesigning/lib/RequirementParserTokenTypes.hpp diff --git a/libsecurity_codesigning/lib/RequirementParserTokenTypes.txt b/Security/libsecurity_codesigning/lib/RequirementParserTokenTypes.txt similarity index 100% rename from libsecurity_codesigning/lib/RequirementParserTokenTypes.txt rename to Security/libsecurity_codesigning/lib/RequirementParserTokenTypes.txt diff --git a/libsecurity_codesigning/lib/Requirements.cpp b/Security/libsecurity_codesigning/lib/Requirements.cpp similarity index 97% rename from libsecurity_codesigning/lib/Requirements.cpp rename to Security/libsecurity_codesigning/lib/Requirements.cpp index 5169f0f9..d2fb04fe 100644 --- a/libsecurity_codesigning/lib/Requirements.cpp +++ b/Security/libsecurity_codesigning/lib/Requirements.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/Requirements.h b/Security/libsecurity_codesigning/lib/Requirements.h similarity index 96% rename from libsecurity_codesigning/lib/Requirements.h rename to Security/libsecurity_codesigning/lib/Requirements.h index e2c6ccc7..8a266f1c 100644 --- a/libsecurity_codesigning/lib/Requirements.h +++ b/Security/libsecurity_codesigning/lib/Requirements.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/SecAssessment.cpp b/Security/libsecurity_codesigning/lib/SecAssessment.cpp similarity index 95% rename from libsecurity_codesigning/lib/SecAssessment.cpp rename to Security/libsecurity_codesigning/lib/SecAssessment.cpp index 68417ce6..60da620f 100644 --- a/libsecurity_codesigning/lib/SecAssessment.cpp +++ b/Security/libsecurity_codesigning/lib/SecAssessment.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -48,10 +48,9 @@ static void esp_do_check(const char *op, CFDictionaryRef dict) // struct _SecAssessment : private CFRuntimeBase { public: - _SecAssessment(CFURLRef p, AuthorityType typ, CFDictionaryRef c, CFDictionaryRef r) : path(p), context(c), type(typ), result(r) { } + _SecAssessment(CFURLRef p, AuthorityType typ, CFDictionaryRef r) : path(p), type(typ), result(r) { } CFCopyRef path; - CFCopyRef context; AuthorityType type; CFRef result; @@ -107,8 +106,6 @@ CFStringRef kSecAssessmentOperationTypeExecute = CFSTR("operation:execute"); CFStringRef kSecAssessmentOperationTypeInstall = CFSTR("operation:install"); CFStringRef kSecAssessmentOperationTypeOpenDocument = CFSTR("operation:lsopen"); -CFStringRef kSecAssessmentContextQuarantineFlags = CFSTR("context:qtnflags"); - // // Read-only in-process access to the policy database @@ -129,6 +126,11 @@ ModuleNexus gEngine; // // Policy evaluation ("assessment") operations // +CFStringRef kSecAssessmentContextKeyFeedback = CFSTR("context:feedback"); +CFStringRef kSecAssessmentFeedbackProgress = CFSTR("feedback:progress"); +CFStringRef kSecAssessmentFeedbackInfoCurrent = CFSTR("current"); +CFStringRef kSecAssessmentFeedbackInfoTotal = CFSTR("total"); + CFStringRef kSecAssessmentAssessmentVerdict = CFSTR("assessment:verdict"); CFStringRef kSecAssessmentAssessmentOriginator = CFSTR("assessment:originator"); CFStringRef kSecAssessmentAssessmentAuthority = CFSTR("assessment:authority"); @@ -163,12 +165,6 @@ SecAssessmentRef SecAssessmentCreate(CFURLRef path, esp_do_check("cs-assessment-evaluate", dict); } - // check the object cache first unless caller denied that or we need extended processing - if (!(flags & (kSecAssessmentFlagRequestOrigin | kSecAssessmentFlagIgnoreCache))) { - if (gDatabase().checkCache(path, type, flags, result)) - return new SecAssessment(path, type, context, result.yield()); - } - if (flags & kSecAssessmentFlagDirect) { // ask the engine right here to do its thing SYSPOLICY_ASSESS_LOCAL(); @@ -201,7 +197,7 @@ SecAssessmentRef SecAssessmentCreate(CFURLRef path, __esp_notify_ns("cs-assessment-evaluate", (void *)(CFDictionaryRef)dict); } - return new SecAssessment(path, type, context, result.yield()); + return new SecAssessment(path, type, result.yield()); END_CSAPI_ERRORS1(NULL) } @@ -273,7 +269,7 @@ static void traceResult(CFURLRef target, MessageTrace &trace, std::string &sanit trace.add("signature3", "%s", sanitized.c_str()); trace.add("signature5", "%s", version.c_str()); } - + static void traceAssessment(SecAssessment &assessment, AuthorityType type, CFDictionaryRef result) { if (CFDictionaryGetValue(result, CFSTR("assessment:remote"))) @@ -360,9 +356,7 @@ CFDictionaryRef SecAssessmentCopyResult(SecAssessmentRef assessmentRef, result = adulterated.get(); } } - bool trace = CFDictionaryContainsKey(assessment.context, kSecAssessmentContextQuarantineFlags); - if (trace) - traceAssessment(assessment, assessment.type, result); + traceAssessment(assessment, assessment.type, result); return result.yield(); END_CSAPI_ERRORS1(NULL) @@ -519,6 +513,11 @@ Boolean SecAssessmentControl(CFStringRef control, void *arguments, CFErrorRef *e else result = NULL; return true; + } else if (CFEqual(control, CFSTR("rearm-status"))) { + CFTimeInterval &result = *(CFTimeInterval*)(arguments); + if (!queryRearmTimer(result)) + result = 0; + return true; } else MacOSError::throwMe(errSecCSInvalidAttributeValues); diff --git a/libsecurity_codesigning/lib/SecAssessment.h b/Security/libsecurity_codesigning/lib/SecAssessment.h similarity index 97% rename from libsecurity_codesigning/lib/SecAssessment.h rename to Security/libsecurity_codesigning/lib/SecAssessment.h index 04a43bb4..f59dbd22 100644 --- a/libsecurity_codesigning/lib/SecAssessment.h +++ b/Security/libsecurity_codesigning/lib/SecAssessment.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -70,8 +70,6 @@ extern CFStringRef kSecAssessmentOperationTypeExecute; // .. execute code extern CFStringRef kSecAssessmentOperationTypeInstall; // .. install software extern CFStringRef kSecAssessmentOperationTypeOpenDocument; // .. LaunchServices-level document open -extern CFStringRef kSecAssessmentContextQuarantineFlags; - /*! Operational flags for SecAssessment calls @@ -132,6 +130,12 @@ enum { @constant kSecAssessmentContextKeyOperation Type of operation (see overview above). This defaults to the kSecAssessmentOperationTypeExecute. */ +extern CFStringRef kSecAssessmentContextKeyFeedback; // feedback reporting block +typedef Boolean (^SecAssessmentFeedback)(CFStringRef type, CFDictionaryRef information); +extern CFStringRef kSecAssessmentFeedbackProgress; // progress reporting feedback +extern CFStringRef kSecAssessmentFeedbackInfoCurrent; // info key: current work progress +extern CFStringRef kSecAssessmentFeedbackInfoTotal; // info key: total expected work + extern CFStringRef kSecAssessmentAssessmentVerdict; // CFBooleanRef: master result - allow or deny extern CFStringRef kSecAssessmentAssessmentOriginator; // CFStringRef: describing the signature originator extern CFStringRef kSecAssessmentAssessmentAuthority; // CFDictionaryRef: authority used to arrive at result diff --git a/libsecurity_codesigning/lib/SecCode.cpp b/Security/libsecurity_codesigning/lib/SecCode.cpp similarity index 99% rename from libsecurity_codesigning/lib/SecCode.cpp rename to Security/libsecurity_codesigning/lib/SecCode.cpp index 12e719fa..b78beb8d 100644 --- a/libsecurity_codesigning/lib/SecCode.cpp +++ b/Security/libsecurity_codesigning/lib/SecCode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/SecCode.h b/Security/libsecurity_codesigning/lib/SecCode.h similarity index 99% rename from libsecurity_codesigning/lib/SecCode.h rename to Security/libsecurity_codesigning/lib/SecCode.h index ee773ae1..bd0d258f 100644 --- a/libsecurity_codesigning/lib/SecCode.h +++ b/Security/libsecurity_codesigning/lib/SecCode.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/SecCodeHost.cpp b/Security/libsecurity_codesigning/lib/SecCodeHost.cpp similarity index 97% rename from libsecurity_codesigning/lib/SecCodeHost.cpp rename to Security/libsecurity_codesigning/lib/SecCodeHost.cpp index f6989f29..7de4bf90 100644 --- a/libsecurity_codesigning/lib/SecCodeHost.cpp +++ b/Security/libsecurity_codesigning/lib/SecCodeHost.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/SecCodeHost.h b/Security/libsecurity_codesigning/lib/SecCodeHost.h similarity index 99% rename from libsecurity_codesigning/lib/SecCodeHost.h rename to Security/libsecurity_codesigning/lib/SecCodeHost.h index 2607422e..65936db8 100644 --- a/libsecurity_codesigning/lib/SecCodeHost.h +++ b/Security/libsecurity_codesigning/lib/SecCodeHost.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2011,2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/SecCodeHostLib.c b/Security/libsecurity_codesigning/lib/SecCodeHostLib.c similarity index 98% rename from libsecurity_codesigning/lib/SecCodeHostLib.c rename to Security/libsecurity_codesigning/lib/SecCodeHostLib.c index 50dadf16..44774523 100644 --- a/libsecurity_codesigning/lib/SecCodeHostLib.c +++ b/Security/libsecurity_codesigning/lib/SecCodeHostLib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/SecCodeHostLib.h b/Security/libsecurity_codesigning/lib/SecCodeHostLib.h similarity index 98% rename from libsecurity_codesigning/lib/SecCodeHostLib.h rename to Security/libsecurity_codesigning/lib/SecCodeHostLib.h index 813b3993..3cceb306 100644 --- a/libsecurity_codesigning/lib/SecCodeHostLib.h +++ b/Security/libsecurity_codesigning/lib/SecCodeHostLib.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/SecCodePriv.h b/Security/libsecurity_codesigning/lib/SecCodePriv.h similarity index 99% rename from libsecurity_codesigning/lib/SecCodePriv.h rename to Security/libsecurity_codesigning/lib/SecCodePriv.h index d924ddf6..158121a9 100644 --- a/libsecurity_codesigning/lib/SecCodePriv.h +++ b/Security/libsecurity_codesigning/lib/SecCodePriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2011,2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/SecCodeSigner.cpp b/Security/libsecurity_codesigning/lib/SecCodeSigner.cpp similarity index 97% rename from libsecurity_codesigning/lib/SecCodeSigner.cpp rename to Security/libsecurity_codesigning/lib/SecCodeSigner.cpp index 8fed4b1d..95ecf7b2 100644 --- a/libsecurity_codesigning/lib/SecCodeSigner.cpp +++ b/Security/libsecurity_codesigning/lib/SecCodeSigner.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -115,7 +115,9 @@ OSStatus SecCodeSignerAddSignatureWithErrors(SecCodeSignerRef signerRef, SecStaticCodeRef codeRef, SecCSFlags flags, CFErrorRef *errors) { BEGIN_CSAPI - checkFlags(flags); + checkFlags(flags, + kSecCSReportProgress + ); SecCodeSigner::required(signerRef)->sign(SecStaticCode::required(codeRef), flags); END_CSAPI_ERRORS } diff --git a/libsecurity_codesigning/lib/SecCodeSigner.h b/Security/libsecurity_codesigning/lib/SecCodeSigner.h similarity index 99% rename from libsecurity_codesigning/lib/SecCodeSigner.h rename to Security/libsecurity_codesigning/lib/SecCodeSigner.h index f34f273b..f7f73710 100644 --- a/libsecurity_codesigning/lib/SecCodeSigner.h +++ b/Security/libsecurity_codesigning/lib/SecCodeSigner.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/SecIntegrity.cpp b/Security/libsecurity_codesigning/lib/SecIntegrity.cpp similarity index 94% rename from libsecurity_codesigning/lib/SecIntegrity.cpp rename to Security/libsecurity_codesigning/lib/SecIntegrity.cpp index 5bbb6035..dc266a02 100644 --- a/libsecurity_codesigning/lib/SecIntegrity.cpp +++ b/Security/libsecurity_codesigning/lib/SecIntegrity.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/SecIntegrity.h b/Security/libsecurity_codesigning/lib/SecIntegrity.h similarity index 96% rename from libsecurity_codesigning/lib/SecIntegrity.h rename to Security/libsecurity_codesigning/lib/SecIntegrity.h index c8fb0699..4c92f44e 100644 --- a/libsecurity_codesigning/lib/SecIntegrity.h +++ b/Security/libsecurity_codesigning/lib/SecIntegrity.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/SecIntegrityLib.c b/Security/libsecurity_codesigning/lib/SecIntegrityLib.c similarity index 94% rename from libsecurity_codesigning/lib/SecIntegrityLib.c rename to Security/libsecurity_codesigning/lib/SecIntegrityLib.c index a6ffb626..17b1825a 100644 --- a/libsecurity_codesigning/lib/SecIntegrityLib.c +++ b/Security/libsecurity_codesigning/lib/SecIntegrityLib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/SecIntegrityLib.h b/Security/libsecurity_codesigning/lib/SecIntegrityLib.h similarity index 96% rename from libsecurity_codesigning/lib/SecIntegrityLib.h rename to Security/libsecurity_codesigning/lib/SecIntegrityLib.h index b0960c65..0a0a0c51 100644 --- a/libsecurity_codesigning/lib/SecIntegrityLib.h +++ b/Security/libsecurity_codesigning/lib/SecIntegrityLib.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/SecRequirement.cpp b/Security/libsecurity_codesigning/lib/SecRequirement.cpp similarity index 99% rename from libsecurity_codesigning/lib/SecRequirement.cpp rename to Security/libsecurity_codesigning/lib/SecRequirement.cpp index 7414cec9..eab15a41 100644 --- a/libsecurity_codesigning/lib/SecRequirement.cpp +++ b/Security/libsecurity_codesigning/lib/SecRequirement.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/SecRequirement.h b/Security/libsecurity_codesigning/lib/SecRequirement.h similarity index 98% rename from libsecurity_codesigning/lib/SecRequirement.h rename to Security/libsecurity_codesigning/lib/SecRequirement.h index dce6a83d..90d51c16 100644 --- a/libsecurity_codesigning/lib/SecRequirement.h +++ b/Security/libsecurity_codesigning/lib/SecRequirement.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/SecRequirementPriv.h b/Security/libsecurity_codesigning/lib/SecRequirementPriv.h similarity index 99% rename from libsecurity_codesigning/lib/SecRequirementPriv.h rename to Security/libsecurity_codesigning/lib/SecRequirementPriv.h index 17dc575f..c7ad3683 100644 --- a/libsecurity_codesigning/lib/SecRequirementPriv.h +++ b/Security/libsecurity_codesigning/lib/SecRequirementPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/SecStaticCode.cpp b/Security/libsecurity_codesigning/lib/SecStaticCode.cpp similarity index 92% rename from libsecurity_codesigning/lib/SecStaticCode.cpp rename to Security/libsecurity_codesigning/lib/SecStaticCode.cpp index ee14ed9c..6d71272c 100644 --- a/libsecurity_codesigning/lib/SecStaticCode.cpp +++ b/Security/libsecurity_codesigning/lib/SecStaticCode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -85,7 +85,7 @@ OSStatus SecStaticCodeCreateWithPathAndAttributes(CFURLRef path, SecCSFlags flag if (cfscan(attributes, "{%O=%s}", kSecCodeAttributeBundleVersion, &version)) ctx.version = version.c_str(); } - + CodeSigning::Required(staticCodeRef) = (new SecStaticCode(DiskRep::bestGuess(cfString(path).c_str(), &ctx)))->handle(); END_CSAPI @@ -107,15 +107,21 @@ OSStatus SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef staticCodeRef, Se BEGIN_CSAPI checkFlags(flags, - kSecCSCheckAllArchitectures + kSecCSReportProgress + | kSecCSCheckAllArchitectures | kSecCSDoNotValidateExecutable | kSecCSDoNotValidateResources | kSecCSConsiderExpiration - | kSecCSEnforceRevocationChecks + | kSecCSEnforceRevocationChecks + | kSecCSNoNetworkAccess | kSecCSCheckNestedCode | kSecCSStrictValidate); + + if (errors) + flags |= kSecCSFullReport; // internal-use flag SecPointer code = SecStaticCode::requiredStatic(staticCodeRef); + code->setValidationFlags(flags); const SecRequirement *req = SecRequirement::optional(requirementRef); DTRACK(CODESIGN_EVAL_STATIC, code, (char*)code->mainExecutablePath().c_str()); code->staticValidate(flags, req); @@ -206,7 +212,7 @@ OSStatus SecCodeSetDetachedSignature(SecStaticCodeRef codeRef, CFDataRef signatu OSStatus SecCodeMapMemory(SecStaticCodeRef codeRef, SecCSFlags flags) { BEGIN_CSAPI - + checkFlags(flags); SecPointer code = SecStaticCode::requiredStatic(codeRef); if (const CodeDirectory *cd = code->codeDirectory(false)) { @@ -246,3 +252,18 @@ OSStatus SecStaticCodeSetValidationConditions(SecStaticCodeRef codeRef, CFDictio END_CSAPI } + + +// +// Set cancellation flag on a static code object. +// +OSStatus SecStaticCodeCancelValidation(SecStaticCodeRef codeRef, SecCSFlags flags) +{ + BEGIN_CSAPI + + checkFlags(0); + SecStaticCode *code = SecStaticCode::requiredStatic(codeRef); + code->cancelValidation(); + + END_CSAPI +} diff --git a/libsecurity_codesigning/lib/SecStaticCode.h b/Security/libsecurity_codesigning/lib/SecStaticCode.h similarity index 98% rename from libsecurity_codesigning/lib/SecStaticCode.h rename to Security/libsecurity_codesigning/lib/SecStaticCode.h index 8e5f8c20..397de4ff 100644 --- a/libsecurity_codesigning/lib/SecStaticCode.h +++ b/Security/libsecurity_codesigning/lib/SecStaticCode.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -147,6 +147,7 @@ enum { kSecCSBasicValidateOnly = kSecCSDoNotValidateExecutable | kSecCSDoNotValidateResources, kSecCSCheckNestedCode = 1 << 3, kSecCSStrictValidate = 1 << 4, + kSecCSFullReport = 1 << 5, }; OSStatus SecStaticCodeCheckValidity(SecStaticCodeRef staticCode, SecCSFlags flags, diff --git a/libsecurity_codesigning/lib/SecStaticCodePriv.h b/Security/libsecurity_codesigning/lib/SecStaticCodePriv.h similarity index 81% rename from libsecurity_codesigning/lib/SecStaticCodePriv.h rename to Security/libsecurity_codesigning/lib/SecStaticCodePriv.h index ccd9d2b5..c534c0e5 100644 --- a/libsecurity_codesigning/lib/SecStaticCodePriv.h +++ b/Security/libsecurity_codesigning/lib/SecStaticCodePriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -69,6 +69,20 @@ OSStatus SecStaticCodeSetCallback(SecStaticCodeRef code, SecCSFlags flag, SecCod @param conditions A dictionary containing one or more validation conditions. Must not be NULL. */ OSStatus SecStaticCodeSetValidationConditions(SecStaticCodeRef code, CFDictionaryRef conditions); + + +/* + @function SecStaticCodeCancelValidation + Ask for an ongoing static validation using this (static) code object to be cancelled as soon as feasible. + if no validation is pending, this does nothing. + Since validation is synchronous, this call must be made from another thread. + This call will return immediately. If a validation operation is terminated due to it, + it will fail with the errSecCSVetoed error. + + @param code A Code or StaticCode object whose validation should be modified. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + */ +OSStatus SecStaticCodeCancelValidation(SecStaticCodeRef code, SecCSFlags flags); #ifdef __cplusplus diff --git a/Security/libsecurity_codesigning/lib/SecTask.c b/Security/libsecurity_codesigning/lib/SecTask.c new file mode 100644 index 00000000..f3a36d2a --- /dev/null +++ b/Security/libsecurity_codesigning/lib/SecTask.c @@ -0,0 +1,292 @@ +/* + * Copyright (c) 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@ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SecCode.h" +#include "SecCodePriv.h" +#include "SecRequirement.h" + +#include "SecTask.h" +#include "SecTaskPriv.h" + + +struct __SecTask { + CFRuntimeBase base; + + pid_t pid; + + audit_token_t *token; + audit_token_t token_storage; + + /* Track whether we've loaded entitlements independently since after the + * load, entitlements may legitimately be NULL */ + Boolean entitlementsLoaded; + CFDictionaryRef entitlements; +}; + +enum { + kSecCodeMagicEntitlement = 0xfade7171, /* entitlement blob */ +}; + + +CFTypeID _kSecTaskTypeID = _kCFRuntimeNotATypeID; + +static void SecTaskFinalize(CFTypeRef cfTask) +{ + SecTaskRef task = (SecTaskRef) cfTask; + + if (task->entitlements != NULL) { + CFRelease(task->entitlements); + task->entitlements = NULL; + } +} + + +// Define PRIdPID (proper printf format string for pid_t) +#define PRIdPID PRId32 + +static CFStringRef SecTaskCopyDebugDescription(CFTypeRef cfTask) +{ + SecTaskRef task = (SecTaskRef) cfTask; + const char *task_name; + int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, task->pid}; + struct kinfo_proc kp; + size_t len = sizeof(kp); + if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1 || len == 0) + task_name = strerror(errno); + else + task_name = kp.kp_proc.p_comm; + + return CFStringCreateWithFormat(CFGetAllocator(task), NULL, CFSTR("%s[%" PRIdPID "]"), task_name, task->pid); +} + +static void SecTaskRegisterClass(void) +{ + static const CFRuntimeClass SecTaskClass = { + .version = 0, + .className = "SecTask", + .init = NULL, + .copy = NULL, + .finalize = SecTaskFinalize, + .equal = NULL, + .hash = NULL, + .copyFormattingDesc = NULL, + .copyDebugDesc = SecTaskCopyDebugDescription, + }; + + _kSecTaskTypeID = _CFRuntimeRegisterClass(&SecTaskClass); +} + +CFTypeID SecTaskGetTypeID(void) +{ + static pthread_once_t secTaskRegisterClassOnce = PTHREAD_ONCE_INIT; + + /* Register the class with the CF runtime the first time through */ + pthread_once(&secTaskRegisterClassOnce, SecTaskRegisterClass); + + return _kSecTaskTypeID; +} + +static SecTaskRef SecTaskCreateWithPID(CFAllocatorRef allocator, pid_t pid) +{ + CFIndex extra = sizeof(struct __SecTask) - sizeof(CFRuntimeBase); + SecTaskRef task = (SecTaskRef) _CFRuntimeCreateInstance(allocator, SecTaskGetTypeID(), extra, NULL); + if (task != NULL) { + task->pid = pid; + task->entitlementsLoaded = false; + task->entitlements = NULL; + } + + return task; +} + +SecTaskRef SecTaskCreateWithAuditToken(CFAllocatorRef allocator, audit_token_t token) +{ + SecTaskRef task; + + task = SecTaskCreateWithPID(allocator, audit_token_to_pid(token)); + if (task != NULL) { +#if 0 + task->token_storage = token; + task->token = &task->token_storage; +#endif + } + + return task; +} + +SecTaskRef SecTaskCreateFromSelf(CFAllocatorRef allocator) +{ + return SecTaskCreateWithPID(allocator, getpid()); +} + +/* + * Determine if the given task meets a specified requirement. + */ +OSStatus +SecTaskValidateForRequirement(SecTaskRef task, CFStringRef requirement) +{ + OSStatus status; + SecCodeRef code = NULL; + SecRequirementRef req = NULL; + pid_t pid = task->pid; + if (pid <= 0) { + return errSecParam; + } + status = SecCodeCreateWithPID(pid, kSecCSDefaultFlags, &code); + //syslog(LOG_NOTICE, "SecTaskValidateForRequirement: SecCodeCreateWithPID=%d", status); + if (!status) { + status = SecRequirementCreateWithString(requirement, + kSecCSDefaultFlags, &req); + //syslog(LOG_NOTICE, "SecTaskValidateForRequirement: SecRequirementCreateWithString=%d", status); + } + if (!status) { + status = SecCodeCheckValidity(code, kSecCSDefaultFlags, req); + //syslog(LOG_NOTICE, "SecTaskValidateForRequirement: SecCodeCheckValidity=%d", status); + } + if (req) + CFRelease(req); + if (code) + CFRelease(code); + + return status; +} + +static CFRange myMakeRange(CFIndex loc, CFIndex len) { + CFRange r = {.location = loc, .length = len }; + return r; +} +struct csheader { + uint32_t magic; + uint32_t length; +}; + +static int +csops_task(SecTaskRef task, int ops, void *blob, size_t size) +{ + if (task->token) + return csops_audittoken(task->pid, ops, blob, size, task->token); + else + return csops(task->pid, ops, blob, size); +} + +static int SecTaskLoadEntitlements(SecTaskRef task, CFErrorRef *error) +{ + CFMutableDataRef data = NULL; + struct csheader header; + uint32_t bufferlen; + int ret; + + ret = csops_task(task, CS_OPS_ENTITLEMENTS_BLOB, &header, sizeof(header)); + if (ret != -1 || errno != ERANGE) { + /* no entitlements */ + task->entitlementsLoaded = true; + return 0; + } + + bufferlen = ntohl(header.length); + /* check for insane values */ + if (bufferlen > 1024 * 1024 || bufferlen < 8) { + ret = EINVAL; + goto out; + } + data = CFDataCreateMutable(NULL, bufferlen); + if (data == NULL) { + ret = ENOMEM; + goto out; + } + CFDataSetLength(data, bufferlen); + ret = csops_task(task, CS_OPS_ENTITLEMENTS_BLOB, CFDataGetMutableBytePtr(data), bufferlen); + if (ret) { + ret = errno; + goto out; + } + CFDataDeleteBytes(data, myMakeRange(0, 8)); + task->entitlements = CFPropertyListCreateWithData(NULL, data, 0, NULL, error); + task->entitlementsLoaded = true; + out: + if (data) + CFRelease(data); + if (ret && error) + *error = CFErrorCreate(NULL, kCFErrorDomainMach, ret, NULL); + + return ret; +} + +CFTypeRef SecTaskCopyValueForEntitlement(SecTaskRef task, CFStringRef entitlement, CFErrorRef *error) +{ + /* Load entitlements if necessary */ + if (task->entitlementsLoaded == false) { + SecTaskLoadEntitlements(task, error); + } + + CFTypeRef value = NULL; + if (task->entitlements != NULL) { + value = CFDictionaryGetValue(task->entitlements, entitlement); + + /* Return something the caller must release */ + if (value != NULL) { + CFRetain(value); + } + } + + return value; +} + +CFDictionaryRef SecTaskCopyValuesForEntitlements(SecTaskRef task, CFArrayRef entitlements, CFErrorRef *error) +{ + /* Load entitlements if necessary */ + if (task->entitlementsLoaded == false) { + SecTaskLoadEntitlements(task, error); + } + + /* Iterate over the passed in entitlements, populating the dictionary + * If entitlements were loaded but none were present, return an empty + * dictionary */ + CFMutableDictionaryRef values = NULL; + if (task->entitlementsLoaded == true) { + + CFIndex i, count = CFArrayGetCount(entitlements); + values = CFDictionaryCreateMutable(CFGetAllocator(task), count, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (task->entitlements != NULL) { + for (i = 0; i < count; i++) { + CFStringRef entitlement = CFArrayGetValueAtIndex(entitlements, i); + CFTypeRef value = CFDictionaryGetValue(task->entitlements, entitlement); + if (value != NULL) { + CFDictionarySetValue(values, entitlement, value); + } + } + } + } + + return values; +} diff --git a/Security/libsecurity_codesigning/lib/SecTask.h b/Security/libsecurity_codesigning/lib/SecTask.h new file mode 100644 index 00000000..21f904f0 --- /dev/null +++ b/Security/libsecurity_codesigning/lib/SecTask.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2008-2009,2011 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SECURITY_SECTASK_H_ +#define _SECURITY_SECTASK_H_ + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + @typedef SecTaskRef + @abstract CFType used for representing a task +*/ +typedef struct __SecTask *SecTaskRef; + +/*! + @function SecTaskGetTypeID + @abstract Returns the type ID for CF instances of SecTask. + @result A CFTypeID for SecTask +*/ +CFTypeID SecTaskGetTypeID(void); + +/*! + @function SecTaskCreateWithAuditToken + @abstract Create a SecTask object for the task that sent the mach message + represented by the audit token. + @param token The audit token of a mach message + @result The newly created SecTask object or NULL on error. The caller must + CFRelease the returned object. +*/ +SecTaskRef SecTaskCreateWithAuditToken(CFAllocatorRef allocator, audit_token_t token); + +/*! + @function SecTaskCreateFromSelf + @abstract Create a SecTask object for the current task. + @result The newly created SecTask object or NULL on error. The caller must + CFRelease the returned object. +*/ +SecTaskRef SecTaskCreateFromSelf(CFAllocatorRef allocator); + +/*! + @function SecTaskCopyValueForEntitlement + @abstract Returns the value of a single entitlement for the represented + task. + @param task A previously created SecTask object + @param entitlement The name of the entitlement to be fetched + @param error On a NULL return, this may be contain a CFError describing + the problem. This argument may be NULL if the caller is not interested in + detailed errors. + @result The value of the specified entitlement for the process or NULL if + the entitlement value could not be retrieved. The type of the returned + value will depend on the entitlement specified. The caller must release + the returned object. + @discussion A NULL return may indicate an error, or it may indicate that + the entitlement is simply not present. In the latter case, no CFError is + returned. +*/ +CFTypeRef SecTaskCopyValueForEntitlement(SecTaskRef task, CFStringRef entitlement, CFErrorRef *error); + +/*! + @function SecTaskCopyValuesForEntitlements + @abstract Returns the values of multiple entitlements for the represented + task. + @param task A previously created SecTask object + @param entitlements An array of entitlement names to be fetched + @param error On a NULL return, this will contain a CFError describing + the problem. This argument may be NULL if the caller is not interested in + detailed errors. If a requested entitlement is not present for the + returned dictionary, the entitlement is not set on the task. The caller + must CFRelease the returned value +*/ +CFDictionaryRef SecTaskCopyValuesForEntitlements(SecTaskRef task, CFArrayRef entitlements, CFErrorRef *error); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECTASK_H_ */ diff --git a/libsecurity_codesigning/lib/SecTaskPriv.h b/Security/libsecurity_codesigning/lib/SecTaskPriv.h similarity index 100% rename from libsecurity_codesigning/lib/SecTaskPriv.h rename to Security/libsecurity_codesigning/lib/SecTaskPriv.h diff --git a/libsecurity_codesigning/lib/StaticCode.cpp b/Security/libsecurity_codesigning/lib/StaticCode.cpp similarity index 90% rename from libsecurity_codesigning/lib/StaticCode.cpp rename to Security/libsecurity_codesigning/lib/StaticCode.cpp index 446647ad..7a5fb176 100644 --- a/libsecurity_codesigning/lib/StaticCode.cpp +++ b/Security/libsecurity_codesigning/lib/StaticCode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -59,8 +59,8 @@ namespace CodeSigning { using namespace UnixPlusPlus; // A requirement representing a Mac or iOS dev cert, a Mac or iOS distribution cert, or a developer ID -static const char WWDRRequirement[] = "anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.1] exists " - "and ( cert leaf[subject.CN] = \"Mac Developer: \"* or cert leaf[subject.CN] = \"iPhone Developer: \"* )"; +static const char WWDRRequirement[] = "anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.2] exists"; +static const char MACWWDRRequirement[] = "anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.12] exists"; static const char developerID[] = "anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists" " and certificate leaf[field.1.2.840.113635.100.6.1.13] exists"; static const char distributionCertificate[] = "anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.7] exists"; @@ -91,6 +91,9 @@ SecStaticCode::SecStaticCode(DiskRep *rep) mDesignatedReq(NULL), mGotResourceBase(false), mMonitor(NULL), mEvalDetails(NULL) { CODESIGN_STATIC_CREATE(this, rep); + CFRef codeDirectory = rep->codeDirectory(); + if (codeDirectory && CFDataGetLength(codeDirectory) <= 0) + MacOSError::throwMe(errSecCSSignatureInvalid); checkForSystemSignature(); } @@ -142,8 +145,35 @@ CFTypeRef SecStaticCode::reportEvent(CFStringRef stage, CFDictionaryRef info) else return NULL; } - - + +void SecStaticCode::prepareProgress(unsigned int workload) +{ + { + StLock _(mCancelLock); + mCancelPending = false; // not cancelled + } + if (mValidationFlags & kSecCSReportProgress) { + mCurrentWork = 0; // nothing done yet + mTotalWork = workload; // totally fake - we don't know how many files we'll get to chew + } +} + +void SecStaticCode::reportProgress(unsigned amount /* = 1 */) +{ + if (mMonitor && (mValidationFlags & kSecCSReportProgress)) { + { + // if cancellation is pending, abort now + StLock _(mCancelLock); + if (mCancelPending) + MacOSError::throwMe(errSecCSCancelled); + } + // update progress and report + mCurrentWork += amount; + mMonitor(this->handle(false), CFSTR("progress"), CFTemp("{current=%d,total=%d}", mCurrentWork, mTotalWork)); + } +} + + // // Set validation conditions for fine-tuning legacy tolerance // @@ -167,6 +197,19 @@ void SecStaticCode::setValidationModifiers(CFDictionaryRef conditions) } } + +// +// Request cancellation of a validation in progress. +// We do this by posting an abort flag that is checked periodically. +// +void SecStaticCode::cancelValidation() +{ + StLock _(mCancelLock); + if (!(mValidationFlags & kSecCSReportProgress)) // not using progress reporting; cancel won't make it through + MacOSError::throwMe(errSecCSInvalidFlags); + mCancelPending = true; +} + // // Attach a detached signature. @@ -397,7 +440,7 @@ void SecStaticCode::validateDirectory() assert(validated()); if (mValidationResult == errSecSuccess) { if (mValidationExpired) - if ((apiFlags() & kSecCSConsiderExpiration) + if ((mValidationFlags & kSecCSConsiderExpiration) || (codeDirectory()->flags & kSecCodeSignatureForceExpiration)) MacOSError::throwMe(CSSMERR_TP_CERT_EXPIRED); } else @@ -459,7 +502,7 @@ bool SecStaticCode::verifySignature() CODESIGN_EVAL_STATIC_SIGNATURE_ADHOC(this); return false; } - + DTRACK(CODESIGN_EVAL_STATIC_SIGNATURE, this, (char*)this->mainExecutablePath().c_str()); // decode CMS and extract SecTrust for verification @@ -471,13 +514,15 @@ bool SecStaticCode::verifySignature() MacOSError::check(CMSDecoderSetDetachedContent(cms, mDir)); MacOSError::check(CMSDecoderFinalizeMessage(cms)); MacOSError::check(CMSDecoderSetSearchKeychain(cms, cfEmptyArray())); - CFRef policy = verificationPolicy(apiFlags()); + CFRef vf_policies = verificationPolicies(); + CFRef ts_policies = SecPolicyCreateAppleTimeStampingAndRevocationPolicies(vf_policies); CMSSignerStatus status; - MacOSError::check(CMSDecoderCopySignerStatus(cms, 0, policy, - false, &status, &mTrust.aref(), NULL)); + MacOSError::check(CMSDecoderCopySignerStatus(cms, 0, vf_policies, + false, &status, &mTrust.aref(), NULL)); + if (status != kCMSSignerValid) MacOSError::throwMe(errSecCSSignatureFailed); - + // internal signing time (as specified by the signer; optional) mSigningTime = 0; // "not present" marker (nobody could code sign on Jan 1, 2001 :-) switch (OSStatus rc = CMSDecoderCopySignerSigningTime(cms, 0, &mSigningTime)) { @@ -490,7 +535,7 @@ bool SecStaticCode::verifySignature() // certified signing time (as specified by a TSA; optional) mSigningTimestamp = 0; - switch (OSStatus rc = CMSDecoderCopySignerTimestamp(cms, 0, &mSigningTimestamp)) { + switch (OSStatus rc = CMSDecoderCopySignerTimestampWithPolicy(cms, ts_policies, 0, &mSigningTimestamp)) { case errSecSuccess: case errSecTimestampMissing: break; @@ -499,6 +544,9 @@ bool SecStaticCode::verifySignature() } // set up the environment for SecTrust + if (mValidationFlags & kSecCSNoNetworkAccess) { + MacOSError::check(SecTrustSetNetworkFetchAllowed(mTrust,false)); // no network? + } MacOSError::check(SecTrustSetAnchorCertificates(mTrust, cfEmptyArray())); // no anchors MacOSError::check(SecTrustSetKeychains(mTrust, cfEmptyArray())); // no keychains CSSM_APPLE_TP_ACTION_DATA actionData = { @@ -615,17 +663,24 @@ static SecPolicyRef makeOCSPPolicy() return policy.yield(); } -CFTypeRef SecStaticCode::verificationPolicy(SecCSFlags flags) +CFArrayRef SecStaticCode::verificationPolicies() { CFRef core; MacOSError::check(SecPolicyCopy(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_CODE_SIGNING, &core.aref())); - if (flags & kSecCSEnforceRevocationChecks) { + if (mValidationFlags & kSecCSNoNetworkAccess) { + // Skips all revocation since they require network connectivity + // therefore annihilates kSecCSEnforceRevocationChecks if present + CFRef no_revoc = SecPolicyCreateRevocation(kSecRevocationNetworkAccessDisabled); + return makeCFArray(2, core.get(), no_revoc.get()); + } + else if (mValidationFlags & kSecCSEnforceRevocationChecks) { + // Add CRL and OCSPPolicies CFRef crl = makeCRLPolicy(); CFRef ocsp = makeOCSPPolicy(); return makeCFArray(3, core.get(), crl.get(), ocsp.get()); } else { - return core.yield(); + return makeCFArray(1, core.get()); } } @@ -706,6 +761,16 @@ void SecStaticCode::validateExecutable() // computes a concordance between what's on disk and what's in the ResourceDirectory. // Any unsanctioned difference causes an error. // +unsigned SecStaticCode::estimateResourceWorkload() +{ + // workload estimate = number of sealed files + CFDictionaryRef sealedResources = resourceDictionary(); + CFDictionaryRef files = cfget(sealedResources, "files2"); + if (files == NULL) + files = cfget(sealedResources, "files"); + return files ? unsigned(CFDictionaryGetCount(files)) : 0; +} + void SecStaticCode::validateResources(SecCSFlags flags) { // do we have a superset of this requested validation cached? @@ -734,7 +799,11 @@ void SecStaticCode::validateResources(SecCSFlags flags) (char*)this->mainExecutablePath().c_str(), 0); // scan through the resources on disk, checking each against the resourceDirectory - mResourcesValidContext = new CollectingContext(*this); // collect all failures in here + if (mValidationFlags & kSecCSFullReport) + mResourcesValidContext = new CollectingContext(*this); // collect all failures in here + else + mResourcesValidContext = new ValidationContext(*this); // simple bug-out on first error + CFDictionaryRef rules; CFDictionaryRef files; uint32_t version; @@ -751,20 +820,27 @@ void SecStaticCode::validateResources(SecCSFlags flags) MacOSError::throwMe(errSecCSResourcesInvalid); // check for weak resource rules bool strict = flags & kSecCSStrictValidate; - if (strict && (version == 1 || hasWeakResourceRules(rules, mAllowOmissions))) - if (mTolerateErrors.find(errSecCSWeakResourceRules) == mTolerateErrors.end()) - MacOSError::throwMe(errSecCSWeakResourceRules); + if (strict) { + if (hasWeakResourceRules(rules, version, mAllowOmissions)) + if (mTolerateErrors.find(errSecCSWeakResourceRules) == mTolerateErrors.end()) + MacOSError::throwMe(errSecCSWeakResourceRules); + if (version == 1) + if (mTolerateErrors.find(errSecCSWeakResourceEnvelope) == mTolerateErrors.end()) + MacOSError::throwMe(errSecCSWeakResourceEnvelope); + } __block CFRef resourceMap = makeCFMutableDictionary(files); string base = cfString(this->resourceBase()); ResourceBuilder resources(base, base, rules, codeDirectory()->hashType, strict, mTolerateErrors); diskRep()->adjustResources(resources); resources.scan(^(FTSENT *ent, uint32_t ruleFlags, const char *relpath, ResourceBuilder::Rule *rule) { validateResource(files, relpath, ent->fts_info == FTS_SL, *mResourcesValidContext, flags, version); + reportProgress(); CFDictionaryRemoveValue(resourceMap, CFTempString(relpath)); }); - if (CFDictionaryGetCount(resourceMap) > 0) { - secdebug("staticCode", "%p sealed resource(s) not found in code", this); + unsigned leftovers = unsigned(CFDictionaryGetCount(resourceMap)); + if (leftovers > 0) { + secdebug("staticCode", "%d sealed resource(s) not found in code", int(leftovers)); CFDictionaryApplyFunction(resourceMap, SecStaticCode::checkOptionalResource, mResourcesValidContext); } @@ -796,12 +872,16 @@ void SecStaticCode::validateResources(SecCSFlags flags) void SecStaticCode::checkOptionalResource(CFTypeRef key, CFTypeRef value, void *context) { - CollectingContext *ctx = static_cast(context); + ValidationContext *ctx = static_cast(context); ResourceSeal seal(value); if (!seal.optional()) { if (key && CFGetTypeID(key) == CFStringGetTypeID()) { - ctx->reportProblem(errSecCSBadResource, kSecCFErrorResourceMissing, - CFTempURL(CFStringRef(key), false, ctx->code.resourceBase())); + CFTempURL tempURL(CFStringRef(key), false, ctx->code.resourceBase()); + if (!tempURL.get()) { + ctx->reportProblem(errSecCSBadDictionaryFormat, kSecCFErrorResourceSeal, key); + } else { + ctx->reportProblem(errSecCSBadResource, kSecCFErrorResourceMissing, tempURL); + } } else { ctx->reportProblem(errSecCSBadResource, kSecCFErrorResourceSeal, key); } @@ -817,23 +897,25 @@ static bool isOmitRule(CFTypeRef value) return rule.get("omit") == kCFBooleanTrue; } -bool SecStaticCode::hasWeakResourceRules(CFDictionaryRef rulesDict, CFArrayRef allowedOmissions) +bool SecStaticCode::hasWeakResourceRules(CFDictionaryRef rulesDict, uint32_t version, CFArrayRef allowedOmissions) { // compute allowed omissions CFRef defaultOmissions = this->diskRep()->allowedResourceOmissions(); - assert(defaultOmissions); + if (!defaultOmissions) + MacOSError::throwMe(errSecCSInternalError); CFRef allowed = CFArrayCreateMutableCopy(NULL, 0, defaultOmissions); if (allowedOmissions) CFArrayAppendArray(allowed, allowedOmissions, CFRangeMake(0, CFArrayGetCount(allowedOmissions))); CFRange range = CFRangeMake(0, CFArrayGetCount(allowed)); // check all resource rules for weakness + string catchAllRule = (version == 1) ? "^Resources/" : "^.*"; __block bool coversAll = false; __block bool forbiddenOmission = false; CFDictionary rules(rulesDict, errSecCSResourceRulesInvalid); rules.apply(^(CFStringRef key, CFTypeRef value) { string pattern = cfString(key, errSecCSResourceRulesInvalid); - if (pattern == "^.*" && value == kCFBooleanTrue) { + if (pattern == catchAllRule && value == kCFBooleanTrue) { coversAll = true; return; } @@ -973,11 +1055,10 @@ CFDataRef SecStaticCode::resource(string path, ValidationContext &ctx) CFDataRef SecStaticCode::resource(string path) { - ValidationContext ctx; + ValidationContext ctx(*this); return resource(path, ctx); } - void SecStaticCode::validateResource(CFDictionaryRef files, string path, bool isSymlink, ValidationContext &ctx, SecCSFlags flags, uint32_t version) { if (!resourceBase()) // no resources in DiskRep @@ -1430,8 +1511,8 @@ void SecStaticCode::CollectingContext::throwMe() // Master validation driver. // This is the static validation (only) driver for the API. // -// SecStaticCode exposes an à la carte menu of topical validators applying -// to a given object. The static validation API pulls the together reliably, +// 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 // validation matrix based on which options it is given, creating temporary @@ -1440,6 +1521,11 @@ void SecStaticCode::CollectingContext::throwMe() // void SecStaticCode::staticValidate(SecCSFlags flags, const SecRequirement *req) { + setValidationFlags(flags); + + // initialize progress/cancellation state + prepareProgress(estimateResourceWorkload() + 2); // +1 head, +1 tail + // core components: once per architecture (if any) this->staticValidateCore(flags, req); if (flags & kSecCSCheckAllArchitectures) @@ -1447,6 +1533,7 @@ void SecStaticCode::staticValidate(SecCSFlags flags, const SecRequirement *req) subcode->detachedSignature(this->mDetachedSig); // carry over explicit (but not implicit) architecture subcode->staticValidateCore(flags, req); }); + reportProgress(); // allow monitor intervention in source validation phase reportEvent(CFSTR("prepared"), NULL); @@ -1458,6 +1545,7 @@ void SecStaticCode::staticValidate(SecCSFlags flags, const SecRequirement *req) // perform strict validation if desired if (flags & kSecCSStrictValidate) mRep->strictValidate(mTolerateErrors); + reportProgress(); // allow monitor intervention if (CFRef veto = reportEvent(CFSTR("validated"), NULL)) { @@ -1537,8 +1625,8 @@ void SecStaticCode::handleOtherArchitectures(void (^handle)(SecStaticCode* other // bool SecStaticCode::isAppleDeveloperCert(CFArrayRef certs) { - static const std::string appleDeveloperRequirement = "(" + std::string(WWDRRequirement) + ") or (" + developerID + ") or (" + distributionCertificate + ") or (" + iPhoneDistributionCert + ")"; - SecRequirement *req = new SecRequirement(parseRequirement(appleDeveloperRequirement), true); + static const std::string appleDeveloperRequirement = "(" + std::string(WWDRRequirement) + ") or (" + MACWWDRRequirement + ") or (" + developerID + ") or (" + distributionCertificate + ") or (" + iPhoneDistributionCert + ")"; + SecPointer req = new SecRequirement(parseRequirement(appleDeveloperRequirement), true); Requirement::Context ctx(certs, NULL, NULL, "", NULL); return req->requirement()->validates(ctx); diff --git a/libsecurity_codesigning/lib/StaticCode.h b/Security/libsecurity_codesigning/lib/StaticCode.h similarity index 90% rename from libsecurity_codesigning/lib/StaticCode.h rename to Security/libsecurity_codesigning/lib/StaticCode.h index 29816541..9974a3d5 100644 --- a/libsecurity_codesigning/lib/StaticCode.h +++ b/Security/libsecurity_codesigning/lib/StaticCode.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -68,8 +68,14 @@ protected: // class ValidationContext { public: + ValidationContext(SecStaticCode &c) : code(c) { } virtual ~ValidationContext(); virtual void reportProblem(OSStatus rc, CFStringRef type, CFTypeRef value); + + virtual OSStatus osStatus() { return noErr; } + virtual void throwMe() { } + + SecStaticCode &code; }; // @@ -77,14 +83,12 @@ protected: // class CollectingContext : public ValidationContext { public: - CollectingContext(SecStaticCode &c) : code(c), mStatus(errSecSuccess) { } + CollectingContext(SecStaticCode &c) : ValidationContext(c), mStatus(errSecSuccess) { } void reportProblem(OSStatus rc, CFStringRef type, CFTypeRef value); OSStatus osStatus() { return mStatus; } operator OSStatus () const { return mStatus; } void throwMe() __attribute__((noreturn)); - - SecStaticCode &code; private: CFRef mCollection; @@ -138,7 +142,9 @@ public: SecCodeCallback monitor() const { return mMonitor; } void setMonitor(SecCodeCallback monitor) { mMonitor = monitor; } CFTypeRef reportEvent(CFStringRef stage, CFDictionaryRef info); + void reportProgress(unsigned amount = 1); + void setValidationFlags(SecCSFlags flags) { mValidationFlags = flags; } void setValidationModifiers(CFDictionaryRef modifiers); void resetValidity(); // clear validation caches (if something may have changed) @@ -148,10 +154,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(); + unsigned estimateResourceWorkload(); void validateResources(SecCSFlags flags); void validateExecutable(); void validateNestedCode(CFURLRef path, const ResourceSeal &seal, SecCSFlags flags, bool isFramework); @@ -177,14 +187,14 @@ public: public: void staticValidate(SecCSFlags flags, const SecRequirement *req); void staticValidateCore(SecCSFlags flags, const SecRequirement *req); - + protected: CFDictionaryRef getDictionary(CodeDirectory::SpecialSlot slot, bool check = true); // component value as a dictionary bool verifySignature(); - CFTypeRef verificationPolicy(SecCSFlags flags); + CFArrayRef verificationPolicies(); static void checkOptionalResource(CFTypeRef key, CFTypeRef value, void *context); - bool hasWeakResourceRules(CFDictionaryRef rulesDict, CFArrayRef allowedOmissions); + bool hasWeakResourceRules(CFDictionaryRef rulesDict, uint32_t version, CFArrayRef allowedOmissions); void handleOtherArchitectures(void (^handle)(SecStaticCode* other)); @@ -212,7 +222,14 @@ private: bool mResourcesValidated; // tried to validate resources bool mResourcesDeep; // cached validation was deep OSStatus mResourcesValidResult; // outcome if mResourceValidated or... - CollectingContext *mResourcesValidContext; // + ValidationContext *mResourcesValidContext; // resource error reporting funnel + + // validation progress state (set when static validation starts) + SecCSFlags mValidationFlags; // API flags passed to static validation + unsigned mTotalWork; // total expected work (arbitrary units) + unsigned mCurrentWork; // currently completed work + bool mCancelPending; // cancellation was requested + Mutex mCancelLock; // protects mCancelPending // cached contents CFRef mDir; // code directory data diff --git a/libsecurity_codesigning/lib/antlrplugin.cpp b/Security/libsecurity_codesigning/lib/antlrplugin.cpp similarity index 98% rename from libsecurity_codesigning/lib/antlrplugin.cpp rename to Security/libsecurity_codesigning/lib/antlrplugin.cpp index 2a0ddbcd..0e4dee56 100644 --- a/libsecurity_codesigning/lib/antlrplugin.cpp +++ b/Security/libsecurity_codesigning/lib/antlrplugin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2007,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/antlrplugin.h b/Security/libsecurity_codesigning/lib/antlrplugin.h similarity index 97% rename from libsecurity_codesigning/lib/antlrplugin.h rename to Security/libsecurity_codesigning/lib/antlrplugin.h index 2d111399..6ebb0abc 100644 --- a/libsecurity_codesigning/lib/antlrplugin.h +++ b/Security/libsecurity_codesigning/lib/antlrplugin.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/bundlediskrep.cpp b/Security/libsecurity_codesigning/lib/bundlediskrep.cpp similarity index 99% rename from libsecurity_codesigning/lib/bundlediskrep.cpp rename to Security/libsecurity_codesigning/lib/bundlediskrep.cpp index 636e213a..aaf8bc06 100644 --- a/libsecurity_codesigning/lib/bundlediskrep.cpp +++ b/Security/libsecurity_codesigning/lib/bundlediskrep.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -28,7 +28,7 @@ #include #include #include - +#include namespace Security { namespace CodeSigning { diff --git a/libsecurity_codesigning/lib/bundlediskrep.h b/Security/libsecurity_codesigning/lib/bundlediskrep.h similarity index 98% rename from libsecurity_codesigning/lib/bundlediskrep.h rename to Security/libsecurity_codesigning/lib/bundlediskrep.h index a697237a..66542394 100644 --- a/libsecurity_codesigning/lib/bundlediskrep.h +++ b/Security/libsecurity_codesigning/lib/bundlediskrep.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -77,7 +77,7 @@ public: CFArrayRef allowedResourceOmissions(); CFBundleRef bundle() const { return mBundle; } - + public: Writer *writer(); class Writer; diff --git a/libsecurity_codesigning/lib/cdbuilder.cpp b/Security/libsecurity_codesigning/lib/cdbuilder.cpp similarity index 99% rename from libsecurity_codesigning/lib/cdbuilder.cpp rename to Security/libsecurity_codesigning/lib/cdbuilder.cpp index 279998f8..61900bc1 100644 --- a/libsecurity_codesigning/lib/cdbuilder.cpp +++ b/Security/libsecurity_codesigning/lib/cdbuilder.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/cdbuilder.h b/Security/libsecurity_codesigning/lib/cdbuilder.h similarity index 98% rename from libsecurity_codesigning/lib/cdbuilder.h rename to Security/libsecurity_codesigning/lib/cdbuilder.h index 5e697896..453a804a 100644 --- a/libsecurity_codesigning/lib/cdbuilder.h +++ b/Security/libsecurity_codesigning/lib/cdbuilder.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/codedirectory.cpp b/Security/libsecurity_codesigning/lib/codedirectory.cpp similarity index 99% rename from libsecurity_codesigning/lib/codedirectory.cpp rename to Security/libsecurity_codesigning/lib/codedirectory.cpp index 706a7b0f..d48d7dea 100644 --- a/libsecurity_codesigning/lib/codedirectory.cpp +++ b/Security/libsecurity_codesigning/lib/codedirectory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/codedirectory.h b/Security/libsecurity_codesigning/lib/codedirectory.h similarity index 99% rename from libsecurity_codesigning/lib/codedirectory.h rename to Security/libsecurity_codesigning/lib/codedirectory.h index 4b64c146..352870b4 100644 --- a/libsecurity_codesigning/lib/codedirectory.h +++ b/Security/libsecurity_codesigning/lib/codedirectory.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/cs.cpp b/Security/libsecurity_codesigning/lib/cs.cpp similarity index 96% rename from libsecurity_codesigning/lib/cs.cpp rename to Security/libsecurity_codesigning/lib/cs.cpp index 825e3356..787d75b4 100644 --- a/libsecurity_codesigning/lib/cs.cpp +++ b/Security/libsecurity_codesigning/lib/cs.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/cs.h b/Security/libsecurity_codesigning/lib/cs.h similarity index 96% rename from libsecurity_codesigning/lib/cs.h rename to Security/libsecurity_codesigning/lib/cs.h index d07e05ab..9e40ac8e 100644 --- a/libsecurity_codesigning/lib/cs.h +++ b/Security/libsecurity_codesigning/lib/cs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -72,8 +72,6 @@ struct CFObjects { extern ModuleNexus gCFObjects; -static inline SecCSFlags apiFlags() { return gCFObjects().flags(); } - OSStatus dbError(const SQLite3::Error &err); @@ -156,7 +154,6 @@ static inline void checkFlags(SecCSFlags flags, SecCSFlags acceptable = 0) { if (flags & ~acceptable) MacOSError::throwMe(errSecCSInvalidFlags); - gCFObjects().flags() = flags; } diff --git a/libsecurity_codesigning/lib/cscdefs.c b/Security/libsecurity_codesigning/lib/cscdefs.c similarity index 100% rename from libsecurity_codesigning/lib/cscdefs.c rename to Security/libsecurity_codesigning/lib/cscdefs.c diff --git a/libsecurity_codesigning/lib/cscdefs.h b/Security/libsecurity_codesigning/lib/cscdefs.h similarity index 100% rename from libsecurity_codesigning/lib/cscdefs.h rename to Security/libsecurity_codesigning/lib/cscdefs.h diff --git a/libsecurity_codesigning/lib/csdatabase.cpp b/Security/libsecurity_codesigning/lib/csdatabase.cpp similarity index 98% rename from libsecurity_codesigning/lib/csdatabase.cpp rename to Security/libsecurity_codesigning/lib/csdatabase.cpp index b8b0e42f..a8bdf7f3 100644 --- a/libsecurity_codesigning/lib/csdatabase.cpp +++ b/Security/libsecurity_codesigning/lib/csdatabase.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2011-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/csdatabase.h b/Security/libsecurity_codesigning/lib/csdatabase.h similarity index 97% rename from libsecurity_codesigning/lib/csdatabase.h rename to Security/libsecurity_codesigning/lib/csdatabase.h index 1d4b9d19..c2790fa7 100644 --- a/libsecurity_codesigning/lib/csdatabase.h +++ b/Security/libsecurity_codesigning/lib/csdatabase.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2007,2011,2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/cserror.cpp b/Security/libsecurity_codesigning/lib/cserror.cpp similarity index 97% rename from libsecurity_codesigning/lib/cserror.cpp rename to Security/libsecurity_codesigning/lib/cserror.cpp index 16732056..1e6d98e7 100644 --- a/libsecurity_codesigning/lib/cserror.cpp +++ b/Security/libsecurity_codesigning/lib/cserror.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/cserror.h b/Security/libsecurity_codesigning/lib/cserror.h similarity index 97% rename from libsecurity_codesigning/lib/cserror.h rename to Security/libsecurity_codesigning/lib/cserror.h index d737f0f9..f46528f1 100644 --- a/libsecurity_codesigning/lib/cserror.h +++ b/Security/libsecurity_codesigning/lib/cserror.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/csgeneric.cpp b/Security/libsecurity_codesigning/lib/csgeneric.cpp similarity index 99% rename from libsecurity_codesigning/lib/csgeneric.cpp rename to Security/libsecurity_codesigning/lib/csgeneric.cpp index 5913fd7d..f8986325 100644 --- a/libsecurity_codesigning/lib/csgeneric.cpp +++ b/Security/libsecurity_codesigning/lib/csgeneric.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/csgeneric.h b/Security/libsecurity_codesigning/lib/csgeneric.h similarity index 97% rename from libsecurity_codesigning/lib/csgeneric.h rename to Security/libsecurity_codesigning/lib/csgeneric.h index 5b953a1c..0a3a1729 100644 --- a/libsecurity_codesigning/lib/csgeneric.h +++ b/Security/libsecurity_codesigning/lib/csgeneric.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/cskernel.cpp b/Security/libsecurity_codesigning/lib/cskernel.cpp similarity index 98% rename from libsecurity_codesigning/lib/cskernel.cpp rename to Security/libsecurity_codesigning/lib/cskernel.cpp index 96f73418..530fa722 100644 --- a/libsecurity_codesigning/lib/cskernel.cpp +++ b/Security/libsecurity_codesigning/lib/cskernel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2011-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/cskernel.h b/Security/libsecurity_codesigning/lib/cskernel.h similarity index 97% rename from libsecurity_codesigning/lib/cskernel.h rename to Security/libsecurity_codesigning/lib/cskernel.h index c50598ee..444981a6 100644 --- a/libsecurity_codesigning/lib/cskernel.h +++ b/Security/libsecurity_codesigning/lib/cskernel.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/csprocess.cpp b/Security/libsecurity_codesigning/lib/csprocess.cpp similarity index 97% rename from libsecurity_codesigning/lib/csprocess.cpp rename to Security/libsecurity_codesigning/lib/csprocess.cpp index 5d3b5878..bc406aa3 100644 --- a/libsecurity_codesigning/lib/csprocess.cpp +++ b/Security/libsecurity_codesigning/lib/csprocess.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/csprocess.h b/Security/libsecurity_codesigning/lib/csprocess.h similarity index 97% rename from libsecurity_codesigning/lib/csprocess.h rename to Security/libsecurity_codesigning/lib/csprocess.h index fcc908ab..f98126bd 100644 --- a/libsecurity_codesigning/lib/csprocess.h +++ b/Security/libsecurity_codesigning/lib/csprocess.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/csutilities.cpp b/Security/libsecurity_codesigning/lib/csutilities.cpp similarity index 99% rename from libsecurity_codesigning/lib/csutilities.cpp rename to Security/libsecurity_codesigning/lib/csutilities.cpp index 0f33281e..092ec1ed 100644 --- a/libsecurity_codesigning/lib/csutilities.cpp +++ b/Security/libsecurity_codesigning/lib/csutilities.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/csutilities.h b/Security/libsecurity_codesigning/lib/csutilities.h similarity index 98% rename from libsecurity_codesigning/lib/csutilities.h rename to Security/libsecurity_codesigning/lib/csutilities.h index 664d6e2c..f9556a5a 100644 --- a/libsecurity_codesigning/lib/csutilities.h +++ b/Security/libsecurity_codesigning/lib/csutilities.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/detachedrep.cpp b/Security/libsecurity_codesigning/lib/detachedrep.cpp similarity index 98% rename from libsecurity_codesigning/lib/detachedrep.cpp rename to Security/libsecurity_codesigning/lib/detachedrep.cpp index c7c5b8e3..257fe65a 100644 --- a/libsecurity_codesigning/lib/detachedrep.cpp +++ b/Security/libsecurity_codesigning/lib/detachedrep.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2008,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/detachedrep.h b/Security/libsecurity_codesigning/lib/detachedrep.h similarity index 97% rename from libsecurity_codesigning/lib/detachedrep.h rename to Security/libsecurity_codesigning/lib/detachedrep.h index 5851f2e0..64266b38 100644 --- a/libsecurity_codesigning/lib/detachedrep.h +++ b/Security/libsecurity_codesigning/lib/detachedrep.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2008,2011-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/dirscanner.cpp b/Security/libsecurity_codesigning/lib/dirscanner.cpp similarity index 100% rename from libsecurity_codesigning/lib/dirscanner.cpp rename to Security/libsecurity_codesigning/lib/dirscanner.cpp diff --git a/libsecurity_codesigning/lib/dirscanner.h b/Security/libsecurity_codesigning/lib/dirscanner.h similarity index 100% rename from libsecurity_codesigning/lib/dirscanner.h rename to Security/libsecurity_codesigning/lib/dirscanner.h diff --git a/libsecurity_codesigning/lib/diskrep.cpp b/Security/libsecurity_codesigning/lib/diskrep.cpp similarity index 98% rename from libsecurity_codesigning/lib/diskrep.cpp rename to Security/libsecurity_codesigning/lib/diskrep.cpp index 69598084..a3e8ed06 100644 --- a/libsecurity_codesigning/lib/diskrep.cpp +++ b/Security/libsecurity_codesigning/lib/diskrep.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -31,7 +31,6 @@ // specific disk representations created by the bestGuess() function #include "filediskrep.h" #include "bundlediskrep.h" -#include "cfmdiskrep.h" #include "slcrep.h" @@ -110,8 +109,6 @@ DiskRep *DiskRep::bestGuess(const char *path, const Context *ctx) AutoFileDesc fd(path, O_RDONLY); if (MachORep::candidate(fd)) return new MachORep(path, ctx); - if (CFMDiskRep::candidate(fd)) - return new CFMDiskRep(path); if (DYLDCacheRep::candidate(fd)) return new DYLDCacheRep(path); diff --git a/libsecurity_codesigning/lib/diskrep.h b/Security/libsecurity_codesigning/lib/diskrep.h similarity index 95% rename from libsecurity_codesigning/lib/diskrep.h rename to Security/libsecurity_codesigning/lib/diskrep.h index c63a3d2b..d158c7cf 100644 --- a/libsecurity_codesigning/lib/diskrep.h +++ b/Security/libsecurity_codesigning/lib/diskrep.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -84,7 +84,7 @@ public: virtual CFArrayRef allowedResourceOmissions(); // allowed (default) resource omission rules bool mainExecutableIsMachO() { return mainExecutableImage() != NULL; } - + // shorthands CFDataRef codeDirectory() { return component(cdCodeDirectorySlot); } CFDataRef signature() { return component(cdSignatureSlot); } @@ -216,6 +216,12 @@ public: { return mOriginal->recommendedIdentifier(ctx); } CFDictionaryRef defaultResourceRules(const SigningContext &ctx) { return mOriginal->defaultResourceRules(ctx); } + const Requirements *defaultRequirements(const Architecture *arch, const SigningContext &ctx) + { return mOriginal->defaultRequirements(arch, ctx); } + size_t pageSize(const SigningContext &ctx) { return mOriginal->pageSize(ctx); } + + void strictValidate(const ToleratedErrors& tolerated) { mOriginal->strictValidate(tolerated); } + CFArrayRef allowedResourceOmissions() { return mOriginal->allowedResourceOmissions(); } private: RefPointer mOriginal; // underlying representation diff --git a/libsecurity_codesigning/lib/drmaker.cpp b/Security/libsecurity_codesigning/lib/drmaker.cpp similarity index 100% rename from libsecurity_codesigning/lib/drmaker.cpp rename to Security/libsecurity_codesigning/lib/drmaker.cpp diff --git a/libsecurity_codesigning/lib/drmaker.h b/Security/libsecurity_codesigning/lib/drmaker.h similarity index 100% rename from libsecurity_codesigning/lib/drmaker.h rename to Security/libsecurity_codesigning/lib/drmaker.h diff --git a/libsecurity_codesigning/lib/filediskrep.cpp b/Security/libsecurity_codesigning/lib/filediskrep.cpp similarity index 98% rename from libsecurity_codesigning/lib/filediskrep.cpp rename to Security/libsecurity_codesigning/lib/filediskrep.cpp index 7a098c22..d0e294dc 100644 --- a/libsecurity_codesigning/lib/filediskrep.cpp +++ b/Security/libsecurity_codesigning/lib/filediskrep.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/filediskrep.h b/Security/libsecurity_codesigning/lib/filediskrep.h similarity index 97% rename from libsecurity_codesigning/lib/filediskrep.h rename to Security/libsecurity_codesigning/lib/filediskrep.h index 70410eea..77733782 100644 --- a/libsecurity_codesigning/lib/filediskrep.h +++ b/Security/libsecurity_codesigning/lib/filediskrep.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_codesigning/lib/gkoverride.m b/Security/libsecurity_codesigning/lib/gkoverride.m new file mode 100644 index 00000000..47a7066e --- /dev/null +++ b/Security/libsecurity_codesigning/lib/gkoverride.m @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#import +#import +#import + +static bool useInternalServer() { + struct utsname name; + return ((uname(&name) == 0 && strstr(name.version, "DEVELOPMENT") != NULL) + && access("/var/db/gkoverride_use_internal", F_OK) == 0); +} + +@interface OverrideClient : NSObject { + BOOL allow; + NSMutableData *buffer; + NSURLConnection *connection; + int state; +} +@property NSString *currentHash; +@property NSString *opaqueHash; +@property NSString *bundleID; +@property NSString *bundleVersion; +- (NSString *)serverHost; +- (void)sendQuery; +- (void)sendReport; +- (void)abort; +@end + +@implementation OverrideClient + +- (NSString *)serverHost { + if (useInternalServer()) + return @"gkq-stg.siri.apple.com"; + else + return @"gkq.apple.com"; +} + +- (id)init { + self = [super init]; + allow = NO; + buffer = [NSMutableData new]; + return self; +} + +- (void)sendQuery { + state = 1; + NSMutableURLRequest *request = [NSMutableURLRequest new]; + NSString *url = [NSString stringWithFormat:@"https://%@/q/%@/%@", [self serverHost], self.currentHash, self.opaqueHash]; + [request setURL:[NSURL URLWithString:url]]; + [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData]; + [request setTimeoutInterval:5]; + connection = [NSURLConnection connectionWithRequest:request delegate:self]; +} + +- (void)sendReport { + state = 2; + NSMutableURLRequest *request = [NSMutableURLRequest new]; + NSString *body = [NSString stringWithFormat:@"current=%@&bundleid=%@&version=%@", + [self.currentHash stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding], + [self.bundleID stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding], + [self.bundleVersion stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + NSString *url = [NSString stringWithFormat:@"https://%@/report", [self serverHost]]; + [request setURL:[NSURL URLWithString:url]]; + [request setTimeoutInterval:5]; + [request setHTTPMethod:@"POST"]; + [request setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]]; + connection = [NSURLConnection connectionWithRequest:request delegate:self]; +} + +- (BOOL)connection:(NSURLConnection *)conn canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace { + SecTrustRef trust = [protectionSpace serverTrust]; + // abort if untrusted + SecTrustResultType trustResult; + SecTrustEvaluate(trust, &trustResult); + if (trustResult != kSecTrustResultProceed && trustResult != kSecTrustResultUnspecified) { + [conn cancel]; + [self abort]; + return NO; + } + // allow if server presented an EV cert + NSDictionary *result = CFBridgingRelease(SecTrustCopyResult(trust)); + if (result) { + NSNumber *ev = [result objectForKey:(__bridge id)kSecTrustExtendedValidation]; + if (ev != NULL && [ev boolValue] == YES) { + return NO; + } + } + // allow if using internal server (EV not required) + if (useInternalServer()) + return NO; + // otherwise abort + [conn cancel]; + [self abort]; + return NO; +} + +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { + [buffer appendData:data]; + if ([buffer length] > 100) + [self abort]; +} + +- (void)connectionDidFinishLoading:(NSURLConnection *)connection { + if (state == 1) { + NSString *verdict = [[NSString alloc] initWithData:buffer encoding:NSUTF8StringEncoding]; + if ([verdict isEqualToString:@"allow"]) { + allow = YES; + [self abort]; + } else if (CRIsAutoSubmitEnabled()) { // "Send diagnostic & usage data to Apple" checked + [self sendReport]; + } + } else { + [self abort]; // report sent + } +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { + [self abort]; +} + +- (void)abort { + if (allow) { + printf("allow\n"); + exit(42); + } else { + printf("deny\n"); + exit(1); + } +} + +@end + +int main(int argc, const char * argv[]) { + if (argc != 5) { + fprintf(stderr, "usage: %s \n", argv[0]); + return 1; + } + @autoreleasepool { + OverrideClient *client = [OverrideClient new]; + client.currentHash = [NSString stringWithUTF8String:argv[1]]; + client.opaqueHash = [NSString stringWithUTF8String:argv[2]]; + client.bundleID = [NSString stringWithUTF8String:argv[3]]; + client.bundleVersion = [NSString stringWithUTF8String:argv[4]]; + [client sendQuery]; + [[NSRunLoop currentRunLoop] run]; + } + return 0; +} diff --git a/libsecurity_codesigning/lib/kerneldiskrep.cpp b/Security/libsecurity_codesigning/lib/kerneldiskrep.cpp similarity index 96% rename from libsecurity_codesigning/lib/kerneldiskrep.cpp rename to Security/libsecurity_codesigning/lib/kerneldiskrep.cpp index b196c071..91f62435 100644 --- a/libsecurity_codesigning/lib/kerneldiskrep.cpp +++ b/Security/libsecurity_codesigning/lib/kerneldiskrep.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/kerneldiskrep.h b/Security/libsecurity_codesigning/lib/kerneldiskrep.h similarity index 96% rename from libsecurity_codesigning/lib/kerneldiskrep.h rename to Security/libsecurity_codesigning/lib/kerneldiskrep.h index 0b1085e1..deb1facf 100644 --- a/libsecurity_codesigning/lib/kerneldiskrep.h +++ b/Security/libsecurity_codesigning/lib/kerneldiskrep.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/machorep.cpp b/Security/libsecurity_codesigning/lib/machorep.cpp similarity index 97% rename from libsecurity_codesigning/lib/machorep.cpp rename to Security/libsecurity_codesigning/lib/machorep.cpp index 7d9f5d02..07c70a9c 100644 --- a/libsecurity_codesigning/lib/machorep.cpp +++ b/Security/libsecurity_codesigning/lib/machorep.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -123,6 +123,10 @@ CFDataRef MachORep::identificationFor(MachO *macho) // if there is a LC_UUID load command, use the UUID contained therein if (const load_command *cmd = macho->findCommand(LC_UUID)) { const uuid_command *uuidc = reinterpret_cast(cmd); + // uuidc->cmdsize should be sizeof(uuid_command), so if it is not, + // something is wrong. Fail out. + if (macho->flip(uuidc->cmdsize) != sizeof(uuid_command)) + MacOSError::throwMe(errSecCSSignatureInvalid); char result[4 + sizeof(uuidc->uuid)]; memcpy(result, "UUID", 4); memcpy(result+4, uuidc->uuid, sizeof(uuidc->uuid)); diff --git a/libsecurity_codesigning/lib/machorep.h b/Security/libsecurity_codesigning/lib/machorep.h similarity index 98% rename from libsecurity_codesigning/lib/machorep.h rename to Security/libsecurity_codesigning/lib/machorep.h index b7f248ab..c338e91e 100644 --- a/libsecurity_codesigning/lib/machorep.h +++ b/Security/libsecurity_codesigning/lib/machorep.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_codesigning/lib/opaquewhitelist.cpp b/Security/libsecurity_codesigning/lib/opaquewhitelist.cpp new file mode 100644 index 00000000..e8f50afa --- /dev/null +++ b/Security/libsecurity_codesigning/lib/opaquewhitelist.cpp @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#include "opaquewhitelist.h" +#include "csutilities.h" +#include "StaticCode.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Security { +namespace CodeSigning { + +using namespace SQLite; + + +static std::string hashString(CFDataRef hash); +static void attachOpaque(SecStaticCodeRef code, SecAssessmentFeedback feedback); + + +// +// Open the database +// +OpaqueWhitelist::OpaqueWhitelist(const char *path, int flags) + : SQLite::Database(path ? path : opaqueDatabase, flags) +{ + SQLite::Statement createConditions(*this, + "CREATE TABLE IF NOT EXISTS conditions (" + " label text," + " weight real not null unique," + " source text," + " identifier text," + " version text," + " conditions text not null);" + ); + createConditions.execute(); + mOverrideQueue = dispatch_queue_create("com.apple.security.assessment.whitelist-override", DISPATCH_QUEUE_SERIAL); +} + +OpaqueWhitelist::~OpaqueWhitelist() +{ + dispatch_release(mOverrideQueue); +} + + +// +// Check if a code object is whitelisted +// +bool OpaqueWhitelist::contains(SecStaticCodeRef codeRef, SecAssessmentFeedback feedback, OSStatus reason) +{ + // make our own copy of the code object, so we can poke at it without disturbing the original + SecPointer code = new SecStaticCode(SecStaticCode::requiredStatic(codeRef)->diskRep()); + + CFCopyRef current = code->cdHash(); // current cdhash + CFDataRef opaque = NULL; // holds computed opaque cdhash + bool match = false; // holds final result + + if (!current) + return false; // unsigned + + // collect auxiliary information for trace + CFRef info; + std::string team = ""; + CFStringRef cfVersion = NULL, cfShortVersion = NULL, cfExecutable = NULL; + if (errSecSuccess == SecCodeCopySigningInformation(code->handle(false), kSecCSSigningInformation, &info.aref())) { + if (CFStringRef cfTeam = CFStringRef(CFDictionaryGetValue(info, kSecCodeInfoTeamIdentifier))) + team = cfString(cfTeam); + if (CFDictionaryRef infoPlist = CFDictionaryRef(CFDictionaryGetValue(info, kSecCodeInfoPList))) { + if (CFTypeRef version = CFDictionaryGetValue(infoPlist, kCFBundleVersionKey)) + if (CFGetTypeID(version) == CFStringGetTypeID()) + cfVersion = CFStringRef(version); + if (CFTypeRef shortVersion = CFDictionaryGetValue(infoPlist, _kCFBundleShortVersionStringKey)) + if (CFGetTypeID(shortVersion) == CFStringGetTypeID()) + cfShortVersion = CFStringRef(shortVersion); + if (CFTypeRef executable = CFDictionaryGetValue(infoPlist, kCFBundleExecutableKey)) + if (CFGetTypeID(executable) == CFStringGetTypeID()) + cfExecutable = CFStringRef(executable); + } + } + + // compute and attach opaque signature + attachOpaque(code->handle(false), feedback); + opaque = code->cdHash(); + + // lookup current cdhash in whitelist + SQLite::Statement lookup(*this, "SELECT opaque FROM whitelist WHERE current=:current" + " AND opaque != 'disable override'"); + lookup.bind(":current") = current.get(); + while (lookup.nextRow()) { + CFRef expected = lookup[0].data(); + if (CFEqual(opaque, expected)) { + match = true; // actual opaque cdhash matches expected + break; + } + } + + // prepare strings for use inside block + std::string currentHash = hashString(current); + std::string opaqueHash = hashString(opaque); + std::string identifier = code->identifier(); + std::string longVersion = cfString(cfShortVersion) + " (" + cfString(cfVersion) + ")"; + + // check override killswitch + bool enableOverride = true; + SQLite::Statement killswitch(*this, + "SELECT 1 FROM whitelist" + " WHERE current='disable override'" + " OR (current=:current AND opaque='disable override')" + " LIMIT 1"); + killswitch.bind(":current") = current.get(); + if (killswitch.nextRow()) + enableOverride = false; + + // allow external program to override decision + __block bool override = false; + if (!match && enableOverride) { + dispatch_group_t group = dispatch_group_create(); + dispatch_group_async(group, mOverrideQueue, ^{ + const char *argv[] = { + "/usr/libexec/gkoverride", + currentHash.c_str(), + opaqueHash.c_str(), + identifier.c_str(), + longVersion.c_str(), + NULL // sentinel + }; + int pid, status = 0; + if (posix_spawn(&pid, argv[0], NULL, NULL, (char **)argv, NULL) == 0) + if (waitpid(pid, &status, 0) == pid && WIFEXITED(status) && WEXITSTATUS(status) == 42) + override = true; + }); + dispatch_group_wait(group, dispatch_walltime(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC)); + dispatch_release(group); + if (override) + match = true; + } + + // send a trace indicating the result + MessageTrace trace("com.apple.security.assessment.whitelist2", code->identifier().c_str()); + trace.add("signature2", "%s", currentHash.c_str()); + trace.add("signature3", "%s", opaqueHash.c_str()); + trace.add("result", match ? "pass" : "fail"); + trace.add("reason", "%d", reason); + trace.add("override", "%d", override); + if (!team.empty()) + trace.add("teamid", "%s", team.c_str()); + if (cfVersion) + trace.add("version", "%s", cfString(cfVersion).c_str()); + if (cfShortVersion) + trace.add("version2", "%s", cfString(cfShortVersion).c_str()); + if (cfExecutable) + trace.add("execname", "%s", cfString(cfExecutable).c_str()); + trace.send(""); + + return match; +} + + +// +// Obtain special validation conditions for a static code, based on database configuration. +// +CFDictionaryRef OpaqueWhitelist::validationConditionsFor(SecStaticCodeRef code) +{ + // figure out which team key to use + std::string team = "UNKNOWN"; + CFStringRef cfId = NULL; + CFStringRef cfVersion = NULL; + CFRef info; // holds lifetimes for the above + if (errSecSuccess == SecCodeCopySigningInformation(code, kSecCSSigningInformation, &info.aref())) { + if (CFStringRef cfTeam = CFStringRef(CFDictionaryGetValue(info, kSecCodeInfoTeamIdentifier))) + team = cfString(cfTeam); + cfId = CFStringRef(CFDictionaryGetValue(info, kSecCodeInfoIdentifier)); + if (CFDictionaryRef infoPlist = CFDictionaryRef(CFDictionaryGetValue(info, kSecCodeInfoPList))) + if (CFTypeRef version = CFDictionaryGetValue(infoPlist, _kCFBundleShortVersionStringKey)) + if (CFGetTypeID(version) == CFStringGetTypeID()) + cfVersion = CFStringRef(version); + } + if (cfId == NULL) // unsigned; punt + return NULL; + + // find the highest weight matching condition. We perform no merging and the heaviest rule wins + SQLite::Statement matches(*this, + "SELECT conditions FROM conditions" + " WHERE (source = :source or source IS NULL)" + " AND (identifier = :identifier or identifier is NULL)" + " AND ((:version IS NULL AND version IS NULL) OR (version = :version OR version IS NULL))" + " ORDER BY weight DESC" + " LIMIT 1" + ); + matches.bind(":source") = team; + matches.bind(":identifier") = cfString(cfId); + if (cfVersion) + matches.bind(":version") = cfString(cfVersion); + if (matches.nextRow()) { + CFTemp conditions((const char*)matches[0]); + return conditions.yield(); + } + // no matches + return NULL; +} + + +// +// Convert a SHA1 hash to a hex string +// +static std::string hashString(CFDataRef hash) +{ + if (CFDataGetLength(hash) != sizeof(SHA1::Digest)) { + return std::string(); + } else { + const UInt8 *bytes = CFDataGetBytePtr(hash); + char s[2 * SHA1::digestLength + 1]; + for (unsigned n = 0; n < SHA1::digestLength; n++) + sprintf(&s[2*n], "%2.2x", bytes[n]); + return std::string(s); + } +} + + +// +// Add a code object to the whitelist +// +void OpaqueWhitelist::add(SecStaticCodeRef codeRef) +{ + // make our own copy of the code object + SecPointer code = new SecStaticCode(SecStaticCode::requiredStatic(codeRef)->diskRep()); + + CFCopyRef current = code->cdHash(); + attachOpaque(code->handle(false), NULL); // compute and attach an opaque signature + CFDataRef opaque = code->cdHash(); + + SQLite::Statement insert(*this, "INSERT OR REPLACE INTO whitelist (current,opaque) VALUES (:current, :opaque)"); + insert.bind(":current") = current.get(); + insert.bind(":opaque") = opaque; + insert.execute(); +} + + +// +// Generate and attach an ad-hoc opaque signature +// +static void attachOpaque(SecStaticCodeRef code, SecAssessmentFeedback feedback) +{ + CFTemp rules("{" // same resource rules as used for collection + "rules={" + "'^.*' = #T" + "'^Info\\.plist$' = {omit=#T,weight=10}" + "},rules2={" + "'^(Frameworks|SharedFrameworks|Plugins|Plug-ins|XPCServices|Helpers|MacOS)/' = {nested=#T, weight=0}" + "'^.*' = #T" + "'^Info\\.plist$' = {omit=#T,weight=10}" + "'^[^/]+$' = {top=#T, weight=0}" + "}" + "}"); + + CFRef signature = CFDataCreateMutable(NULL, 0); + CFTemp arguments("{%O=%O, %O=#N, %O=%O}", + kSecCodeSignerDetached, signature.get(), + kSecCodeSignerIdentity, /* kCFNull, */ + kSecCodeSignerResourceRules, rules.get()); + CFRef signer; + SecCSFlags creationFlags = kSecCSSignOpaque | kSecCSSignNoV1 | kSecCSSignBundleRoot; + SecCSFlags operationFlags = 0; + + if (feedback) + operationFlags |= kSecCSReportProgress; + MacOSError::check(SecStaticCodeSetCallback(code, kSecCSDefaultFlags, NULL, ^CFTypeRef(SecStaticCodeRef code, CFStringRef stage, CFDictionaryRef info) { + if (CFEqual(stage, CFSTR("progress"))) { + bool proceed = feedback(kSecAssessmentFeedbackProgress, info); + if (!proceed) + SecStaticCodeCancelValidation(code, kSecCSDefaultFlags); + } + return NULL; + })); + + MacOSError::check(SecCodeSignerCreate(arguments, creationFlags, &signer.aref())); + MacOSError::check(SecCodeSignerAddSignature(signer, code, operationFlags)); + MacOSError::check(SecCodeSetDetachedSignature(code, signature, kSecCSDefaultFlags)); +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/libsecurity_codesigning/lib/opaquewhitelist.h b/Security/libsecurity_codesigning/lib/opaquewhitelist.h similarity index 91% rename from libsecurity_codesigning/lib/opaquewhitelist.h rename to Security/libsecurity_codesigning/lib/opaquewhitelist.h index 732cce3c..066efcbe 100644 --- a/libsecurity_codesigning/lib/opaquewhitelist.h +++ b/Security/libsecurity_codesigning/lib/opaquewhitelist.h @@ -26,6 +26,7 @@ #include "SecAssessment.h" #include #include +#include namespace Security { namespace CodeSigning { @@ -44,9 +45,12 @@ public: public: void add(SecStaticCodeRef code); - bool contains(SecStaticCodeRef code, OSStatus reason, bool trace); + bool contains(SecStaticCodeRef code, SecAssessmentFeedback feedback, OSStatus reason); CFDictionaryRef validationConditionsFor(SecStaticCodeRef code); + +private: + dispatch_queue_t mOverrideQueue; }; diff --git a/libsecurity_codesigning/lib/piddiskrep.cpp b/Security/libsecurity_codesigning/lib/piddiskrep.cpp similarity index 92% rename from libsecurity_codesigning/lib/piddiskrep.cpp rename to Security/libsecurity_codesigning/lib/piddiskrep.cpp index 37398eb0..f3488088 100644 --- a/libsecurity_codesigning/lib/piddiskrep.cpp +++ b/Security/libsecurity_codesigning/lib/piddiskrep.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -67,6 +67,9 @@ PidDiskRep::fetchData(void) xpc_release(request); xpc_release(conn); + + if (!mBundleURL) + MacOSError::throwMe(errSecCSNoSuchCode); } @@ -78,8 +81,8 @@ PidDiskRep::PidDiskRep(pid_t pid, CFDataRef infoPlist) mPid = pid; mInfoPlist = infoPlist; - fetchData(); - + fetchData(); + int rcent = ::csops(pid, CS_OPS_BLOB, &header, sizeof(header)); if (rcent == 0) MacOSError::throwMe(errSecCSNoSuchCode); @@ -95,11 +98,9 @@ PidDiskRep::PidDiskRep(pid_t pid, CFDataRef infoPlist) UnixError::check(::csops(pid, CS_OPS_BLOB, mBuffer, bufferLen)); - const BlobCore *b = (const BlobCore *)mBuffer; - if (b->magic() != kSecCodeMagicEmbeddedSignature) - MacOSError::throwMe(errSecCSSignatureInvalid); - if (b->length() < sizeof(*b)) - MacOSError::throwMe(errSecCSNoSuchCode); + const EmbeddedSignatureBlob *b = (const EmbeddedSignatureBlob *)mBuffer; + if (!b->validateBlob(bufferLen)) + MacOSError::throwMe(errSecCSSignatureInvalid); } PidDiskRep::~PidDiskRep() diff --git a/libsecurity_codesigning/lib/piddiskrep.h b/Security/libsecurity_codesigning/lib/piddiskrep.h similarity index 94% rename from libsecurity_codesigning/lib/piddiskrep.h rename to Security/libsecurity_codesigning/lib/piddiskrep.h index b804a20d..fc1e3249 100644 --- a/libsecurity_codesigning/lib/piddiskrep.h +++ b/Security/libsecurity_codesigning/lib/piddiskrep.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -56,11 +56,11 @@ public: bool supportInfoPlist(); private: const BlobCore *blob() { return (const BlobCore *)mBuffer; } - void fetchData(void); + void fetchData(void); pid_t mPid; uint8_t *mBuffer; CFRef mInfoPlist; - CFRef mBundleURL; + CFRef mBundleURL; }; diff --git a/libsecurity_codesigning/lib/policydb.cpp b/Security/libsecurity_codesigning/lib/policydb.cpp similarity index 92% rename from libsecurity_codesigning/lib/policydb.cpp rename to Security/libsecurity_codesigning/lib/policydb.cpp index 17467990..be72b432 100644 --- a/libsecurity_codesigning/lib/policydb.cpp +++ b/Security/libsecurity_codesigning/lib/policydb.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -437,6 +437,37 @@ void setAssessment(bool masterSwitch) ::chmod(prefsFile, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); notify_post(kNotifySecAssessmentMasterSwitch); + + /* reset the automatic rearm timer */ + resetRearmTimer("masterswitch"); +} + + +// +// Reset or query the automatic rearm timer +// +void resetRearmTimer(const char *event) +{ + CFRef now = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()); + CFTemp info("{event=%s, timestamp=%O}", event, now.get()); + CFRef infoData = makeCFData(info.get()); + UnixPlusPlus::AutoFileDesc fd(rearmTimerFile, O_WRONLY | O_CREAT | O_TRUNC, 0644); + fd.write(CFDataGetBytePtr(infoData), CFDataGetLength(infoData)); +} + +bool queryRearmTimer(CFTimeInterval &delta) +{ + if (CFRef infoData = cfLoadFile(rearmTimerFile)) { + if (CFRef info = makeCFDictionaryFrom(infoData)) { + CFDateRef timestamp = (CFDateRef)CFDictionaryGetValue(info, CFSTR("timestamp")); + if (timestamp && CFGetTypeID(timestamp) == CFDateGetTypeID()) { + delta = CFAbsoluteTimeGetCurrent() - CFDateGetAbsoluteTime(timestamp); + return true; + } + } + MacOSError::throwMe(errSecCSDbCorrupt); + } + return false; } diff --git a/libsecurity_codesigning/lib/policydb.h b/Security/libsecurity_codesigning/lib/policydb.h similarity index 94% rename from libsecurity_codesigning/lib/policydb.h rename to Security/libsecurity_codesigning/lib/policydb.h index 5614f4fc..b26c7e6c 100644 --- a/libsecurity_codesigning/lib/policydb.h +++ b/Security/libsecurity_codesigning/lib/policydb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -41,6 +41,7 @@ static const char visibleSecurityFlagFile[] = "/var/db/.sp_visible"; /* old duch static const char prefsFile[] = "/var/db/SystemPolicy-prefs.plist"; static const char lastRejectFile[] = "/var/db/.LastGKReject"; static const char lastApprovedFile[] = "/var/db/.LastGKApp"; +static const char rearmTimerFile[] = "/var/db/.GKRearmTimer"; static const char gkeAuthFile[] = "/var/db/gke.auth"; static const char gkeSigsFile[] = "/var/db/gke.sigs"; @@ -131,6 +132,13 @@ private: bool overrideAssessment(SecAssessmentFlags flags = 0); void setAssessment(bool masterSwitch); + +// +// Reset or query the automatic rearm timer +// +void resetRearmTimer(const char *event); +bool queryRearmTimer(CFTimeInterval &delta); + } // end namespace CodeSigning } // end namespace Security diff --git a/libsecurity_codesigning/lib/policyengine.cpp b/Security/libsecurity_codesigning/lib/policyengine.cpp similarity index 97% rename from libsecurity_codesigning/lib/policyengine.cpp rename to Security/libsecurity_codesigning/lib/policyengine.cpp index eb253d43..286199b2 100644 --- a/libsecurity_codesigning/lib/policyengine.cpp +++ b/Security/libsecurity_codesigning/lib/policyengine.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -101,6 +101,10 @@ void PolicyEngine::evaluate(CFURLRef path, AuthorityType type, SecAssessmentFlag MacOSError::throwMe(errSecCSInvalidAttributeValues); break; } + + // if rejected, reset the automatic rearm timer + if (CFDictionaryGetValue(result, kSecAssessmentAssessmentVerdict) == kCFBooleanFalse) + resetRearmTimer("reject"); } @@ -323,9 +327,8 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment validationFlags |= kSecCSStrictValidate; adjustValidation(code); - // first, perform a shallow check - OSStatus rc = SecStaticCodeCheckValidity(code, validationFlags, NULL); - + // deal with a very special case (broken 10.6/10.7 Applet bundles) + OSStatus rc = SecStaticCodeCheckValidity(code, validationFlags | kSecCSBasicValidateOnly, NULL); if (rc == errSecCSSignatureFailed) { if (!codeInvalidityExceptions(code, result)) { // invalidly signed, no exceptions -> error if (SYSPOLICY_ASSESS_OUTCOME_BROKEN_ENABLED()) @@ -338,6 +341,7 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment rc = errSecCSUnsigned; } + // ad-hoc sign unsigned code if (rc == errSecCSUnsigned && handleUnsigned && (!overrideAssessment(flags) || SYSPOLICY_RECORDER_MODE_ENABLED())) { if (temporarySigning(code, type, path, 0)) { rc = errSecSuccess; // clear unsigned; we are now well-signed @@ -345,11 +349,19 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment } } + // prepare for deep traversal of (hopefully) good signatures + SecAssessmentFeedback feedback = SecAssessmentFeedback(CFDictionaryGetValue(context, kSecAssessmentContextKeyFeedback)); MacOSError::check(SecStaticCodeSetCallback(code, kSecCSDefaultFlags, NULL, ^CFTypeRef (SecStaticCodeRef item, CFStringRef cfStage, CFDictionaryRef info) { string stage = cfString(cfStage); if (stage == "prepared") { if (!CFEqual(item, code)) // genuine nested (not top) code adjustValidation(item); + } else if (stage == "progress") { + if (feedback && CFEqual(item, code)) { // top level progress + bool proceed = feedback(kSecAssessmentFeedbackProgress, info); + if (!proceed) + SecStaticCodeCancelValidation(code, kSecCSDefaultFlags); + } } else if (stage == "validated") { SecStaticCodeSetCallback(item, kSecCSDefaultFlags, NULL, NULL); // clear callback to avoid unwanted recursion evaluateCodeItem(item, path, type, flags, item != code, result); @@ -359,7 +371,9 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment } return NULL; })); - switch (rc = SecStaticCodeCheckValidity(code, validationFlags | kSecCSCheckNestedCode, NULL)) { + + // go for it! + switch (rc = SecStaticCodeCheckValidity(code, validationFlags | kSecCSCheckNestedCode | kSecCSReportProgress, NULL)) { case errSecSuccess: // continue below break; case errSecCSUnsigned: @@ -369,6 +383,7 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment case errSecCSVetoed: // nested code rejected by rule book; result was filled out there return; case errSecCSWeakResourceRules: + case errSecCSWeakResourceEnvelope: case errSecCSResourceNotSupported: case errSecCSAmbiguousBundleFormat: case errSecCSSignatureNotVerifiable: @@ -388,11 +403,9 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment // verdict rendered from a nested component - signature not acceptable to Gatekeeper if (CFEqual(verdict, kCFBooleanFalse)) // nested code rejected by rule book; result was filled out there return; - if (CFEqual(verdict, kCFBooleanTrue) && !(flags & kSecAssessmentFlagIgnoreWhitelist)) { - bool trace = CFDictionaryContainsKey(context, kSecAssessmentContextQuarantineFlags); - if (mOpaqueWhitelist.contains(code, rc, trace)) + if (CFEqual(verdict, kCFBooleanTrue) && !(flags & kSecAssessmentFlagIgnoreWhitelist)) + if (mOpaqueWhitelist.contains(code, feedback, rc)) allow = true; - } } if (allow) { label = "allowed cdhash"; @@ -419,13 +432,6 @@ void PolicyEngine::evaluateInstall(CFURLRef path, SecAssessmentFlags flags, CFDi { const AuthorityType type = kAuthorityInstall; - Xar xar(cfString(path).c_str()); - if (!xar) { - // follow the code signing path - evaluateCode(path, type, flags, context, result, true); - return; - } - // check for recent explicit approval, using a bookmark's FileResourceIdentifierKey if (CFRef bookmark = cfLoadFile(lastApprovedFile)) { Boolean stale; @@ -445,6 +451,13 @@ void PolicyEngine::evaluateInstall(CFURLRef path, SecAssessmentFlags flags, CFDi } } + Xar xar(cfString(path).c_str()); + if (!xar) { + // follow the code signing path + evaluateCode(path, type, flags, context, result, true); + return; + } + SQLite3::int64 latentID = 0; // first (highest priority) disabled matching ID std::string latentLabel; // ... and associated label, if any if (!xar.isSigned()) { diff --git a/libsecurity_codesigning/lib/policyengine.h b/Security/libsecurity_codesigning/lib/policyengine.h similarity index 98% rename from libsecurity_codesigning/lib/policyengine.h rename to Security/libsecurity_codesigning/lib/policyengine.h index 8f4d7a17..673f1e66 100644 --- a/libsecurity_codesigning/lib/policyengine.h +++ b/Security/libsecurity_codesigning/lib/policyengine.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/quarantine++.cpp b/Security/libsecurity_codesigning/lib/quarantine++.cpp similarity index 97% rename from libsecurity_codesigning/lib/quarantine++.cpp rename to Security/libsecurity_codesigning/lib/quarantine++.cpp index 866627d9..ccf7a5c0 100644 --- a/libsecurity_codesigning/lib/quarantine++.cpp +++ b/Security/libsecurity_codesigning/lib/quarantine++.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/quarantine++.h b/Security/libsecurity_codesigning/lib/quarantine++.h similarity index 97% rename from libsecurity_codesigning/lib/quarantine++.h rename to Security/libsecurity_codesigning/lib/quarantine++.h index 53c56091..b2680d5e 100644 --- a/libsecurity_codesigning/lib/quarantine++.h +++ b/Security/libsecurity_codesigning/lib/quarantine++.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/reqdumper.cpp b/Security/libsecurity_codesigning/lib/reqdumper.cpp similarity index 99% rename from libsecurity_codesigning/lib/reqdumper.cpp rename to Security/libsecurity_codesigning/lib/reqdumper.cpp index 9b91ec53..b2f003b9 100644 --- a/libsecurity_codesigning/lib/reqdumper.cpp +++ b/Security/libsecurity_codesigning/lib/reqdumper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2011-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/reqdumper.h b/Security/libsecurity_codesigning/lib/reqdumper.h similarity index 97% rename from libsecurity_codesigning/lib/reqdumper.h rename to Security/libsecurity_codesigning/lib/reqdumper.h index 70c881f0..ebd9c25c 100644 --- a/libsecurity_codesigning/lib/reqdumper.h +++ b/Security/libsecurity_codesigning/lib/reqdumper.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/reqinterp.cpp b/Security/libsecurity_codesigning/lib/reqinterp.cpp similarity index 99% rename from libsecurity_codesigning/lib/reqinterp.cpp rename to Security/libsecurity_codesigning/lib/reqinterp.cpp index 077eb90a..b492acd0 100644 --- a/libsecurity_codesigning/lib/reqinterp.cpp +++ b/Security/libsecurity_codesigning/lib/reqinterp.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/reqinterp.h b/Security/libsecurity_codesigning/lib/reqinterp.h similarity index 97% rename from libsecurity_codesigning/lib/reqinterp.h rename to Security/libsecurity_codesigning/lib/reqinterp.h index ad1ddb84..1ab52186 100644 --- a/libsecurity_codesigning/lib/reqinterp.h +++ b/Security/libsecurity_codesigning/lib/reqinterp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/reqmaker.cpp b/Security/libsecurity_codesigning/lib/reqmaker.cpp similarity index 98% rename from libsecurity_codesigning/lib/reqmaker.cpp rename to Security/libsecurity_codesigning/lib/reqmaker.cpp index 0480a85e..984ec918 100644 --- a/libsecurity_codesigning/lib/reqmaker.cpp +++ b/Security/libsecurity_codesigning/lib/reqmaker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/reqmaker.h b/Security/libsecurity_codesigning/lib/reqmaker.h similarity index 98% rename from libsecurity_codesigning/lib/reqmaker.h rename to Security/libsecurity_codesigning/lib/reqmaker.h index 2209d118..6ed77a5a 100644 --- a/libsecurity_codesigning/lib/reqmaker.h +++ b/Security/libsecurity_codesigning/lib/reqmaker.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/reqparser.cpp b/Security/libsecurity_codesigning/lib/reqparser.cpp similarity index 98% rename from libsecurity_codesigning/lib/reqparser.cpp rename to Security/libsecurity_codesigning/lib/reqparser.cpp index 5a8e94e1..8a0c370a 100644 --- a/libsecurity_codesigning/lib/reqparser.cpp +++ b/Security/libsecurity_codesigning/lib/reqparser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/reqparser.h b/Security/libsecurity_codesigning/lib/reqparser.h similarity index 96% rename from libsecurity_codesigning/lib/reqparser.h rename to Security/libsecurity_codesigning/lib/reqparser.h index 21e1baac..3ecb9f48 100644 --- a/libsecurity_codesigning/lib/reqparser.h +++ b/Security/libsecurity_codesigning/lib/reqparser.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/reqreader.cpp b/Security/libsecurity_codesigning/lib/reqreader.cpp similarity index 97% rename from libsecurity_codesigning/lib/reqreader.cpp rename to Security/libsecurity_codesigning/lib/reqreader.cpp index 8c79912b..a5f2225d 100644 --- a/libsecurity_codesigning/lib/reqreader.cpp +++ b/Security/libsecurity_codesigning/lib/reqreader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/reqreader.h b/Security/libsecurity_codesigning/lib/reqreader.h similarity index 97% rename from libsecurity_codesigning/lib/reqreader.h rename to Security/libsecurity_codesigning/lib/reqreader.h index 25d198db..e5d6fb13 100644 --- a/libsecurity_codesigning/lib/reqreader.h +++ b/Security/libsecurity_codesigning/lib/reqreader.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2007,2011,2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/requirement.cpp b/Security/libsecurity_codesigning/lib/requirement.cpp similarity index 100% rename from libsecurity_codesigning/lib/requirement.cpp rename to Security/libsecurity_codesigning/lib/requirement.cpp diff --git a/libsecurity_codesigning/lib/requirement.h b/Security/libsecurity_codesigning/lib/requirement.h similarity index 100% rename from libsecurity_codesigning/lib/requirement.h rename to Security/libsecurity_codesigning/lib/requirement.h diff --git a/libsecurity_codesigning/lib/resources.cpp b/Security/libsecurity_codesigning/lib/resources.cpp similarity index 96% rename from libsecurity_codesigning/lib/resources.cpp rename to Security/libsecurity_codesigning/lib/resources.cpp index 1a4d1e2a..8d26b6e1 100644 --- a/libsecurity_codesigning/lib/resources.cpp +++ b/Security/libsecurity_codesigning/lib/resources.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -84,7 +84,7 @@ ResourceBuilder::~ResourceBuilder() { for (Rules::iterator it = mRules.begin(); it != mRules.end(); ++it) delete *it; - UnixPlusPlus::checkError(fts_close(mFTS)); + fts_close(mFTS); // do not check error - it's not worth aborting over (double fault etc.) } @@ -139,6 +139,7 @@ void ResourceBuilder::scan(Scanner next) bool first = true; while (FTSENT *ent = fts_read(mFTS)) { + static const char ds_store[] = ".DS_Store"; const char *relpath = ent->fts_path + mRoot.size() + 1; // skip prefix + "/" std::string rp; if (mRelBase != mRoot) { @@ -158,7 +159,6 @@ void ResourceBuilder::scan(Scanner next) if (strncasecmp(ent->fts_name, underbar, strlen(underbar)) == 0) GKBIS_Dot_underbar_Present++; - static const char ds_store[] = ".DS_Store"; if (strcasecmp(ent->fts_name, ds_store) == 0) GKBIS_DS_Store_Present++; @@ -170,6 +170,9 @@ void ResourceBuilder::scan(Scanner next) // symlinks cannot ever be nested code, so quietly convert to resource file secdebug("rdirenum", "symlink %s", ent->fts_path); GKBIS_Num_symlinks++; + + if (strcasecmp(ent->fts_name, ds_store) == 0) + MacOSError::throwMe(errSecCSDSStoreSymlink); if (Rule *rule = findRule(relpath)) if (!(rule->flags & (omitted | exclusion))) @@ -308,7 +311,7 @@ std::string ResourceBuilder::escapeRE(const std::string &s) string r; for (string::const_iterator it = s.begin(); it != s.end(); ++it) { char c = *it; - if (strchr("\\[]{}().+*", c)) + if (strchr("\\[]{}().+*?", c)) r.push_back('\\'); r.push_back(c); } diff --git a/libsecurity_codesigning/lib/resources.h b/Security/libsecurity_codesigning/lib/resources.h similarity index 98% rename from libsecurity_codesigning/lib/resources.h rename to Security/libsecurity_codesigning/lib/resources.h index 3bdd8e8b..05344a50 100644 --- a/libsecurity_codesigning/lib/resources.h +++ b/Security/libsecurity_codesigning/lib/resources.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/security_codesigning.d b/Security/libsecurity_codesigning/lib/security_codesigning.d similarity index 99% rename from libsecurity_codesigning/lib/security_codesigning.d rename to Security/libsecurity_codesigning/lib/security_codesigning.d index c4849d97..acbd15f1 100644 --- a/libsecurity_codesigning/lib/security_codesigning.d +++ b/Security/libsecurity_codesigning/lib/security_codesigning.d @@ -4,6 +4,8 @@ #define int32_t int #define uint32_t unsigned #define mach_port_t uint32_t +#define bool uint8_t +#define off_t uint64_t /* diff --git a/libsecurity_codesigning/lib/security_codesigning.exp b/Security/libsecurity_codesigning/lib/security_codesigning.exp similarity index 98% rename from libsecurity_codesigning/lib/security_codesigning.exp rename to Security/libsecurity_codesigning/lib/security_codesigning.exp index b4e83480..e865acbd 100644 --- a/libsecurity_codesigning/lib/security_codesigning.exp +++ b/Security/libsecurity_codesigning/lib/security_codesigning.exp @@ -1,5 +1,5 @@ # -# Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. +# Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. # # @APPLE_LICENSE_HEADER_START@ # diff --git a/libsecurity_codesigning/lib/sigblob.cpp b/Security/libsecurity_codesigning/lib/sigblob.cpp similarity index 96% rename from libsecurity_codesigning/lib/sigblob.cpp rename to Security/libsecurity_codesigning/lib/sigblob.cpp index a82a6548..619986a1 100644 --- a/libsecurity_codesigning/lib/sigblob.cpp +++ b/Security/libsecurity_codesigning/lib/sigblob.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/sigblob.h b/Security/libsecurity_codesigning/lib/sigblob.h similarity index 97% rename from libsecurity_codesigning/lib/sigblob.h rename to Security/libsecurity_codesigning/lib/sigblob.h index c90f5e8e..50d8d21d 100644 --- a/libsecurity_codesigning/lib/sigblob.h +++ b/Security/libsecurity_codesigning/lib/sigblob.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/signer.cpp b/Security/libsecurity_codesigning/lib/signer.cpp similarity index 97% rename from libsecurity_codesigning/lib/signer.cpp rename to Security/libsecurity_codesigning/lib/signer.cpp index c11ce0c7..59d0e05b 100644 --- a/libsecurity_codesigning/lib/signer.cpp +++ b/Security/libsecurity_codesigning/lib/signer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -120,6 +120,9 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags) // make sure the rep passes strict validation if (strict) rep->strictValidate(MacOSErrorSet()); + + // initialize progress/cancellation state + code->prepareProgress(0); // totally fake workload - we don't know how many files we'll encounter // get the Info.plist out of the rep for some creative defaulting CFRef infoDict; @@ -288,8 +291,7 @@ void SecCodeSigner::Signer::buildResources(std::string root, std::string relBase // Clone V1 rules and add default nesting rules at weight 0 (overridden by anything in rules). // V1 rules typically do not cover these places so we'll prevail, but if they do, we defer to them. rules2 = cfmake("{+%O" - "'^[^/]+$' = {top=#T, weight=0}" // files directly in Contents - "'^(Frameworks|SharedFrameworks|Plugins|Plug-ins|XPCServices|Helpers|MacOS)/' = {nested=#T, weight=0}" // exclude dynamic repositories + "'^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/' = {nested=#T, weight=0}" // exclude dynamic repositories "}", rules); } // build the modern (V2) resource seal @@ -319,6 +321,7 @@ void SecCodeSigner::Signer::buildResources(std::string root, std::string relBase CFDictionaryAddValue(files, CFTempString(relpath).get(), hash); else CFDictionaryAddValue(files, CFTempString(relpath).get(), seal.get()); + code->reportProgress(); }); CFDictionaryAddValue(result, CFSTR("rules2"), resourceBuilder.rules()); files2 = files; @@ -402,6 +405,14 @@ void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context for (MachOEditor::Iterator it = editor->begin(); it != editor->end(); ++it) { MachOEditor::Arch &arch = *it->second; arch.source.reset(fat->architecture(it->first)); + + // library validation is not compatible with i386 + if (arch.architecture.cpuType() == CPU_TYPE_I386) { + if (cdFlags & kSecCodeSignatureLibraryValidation) { + MacOSError::throwMe(errSecCSBadLVArch); + } + } + arch.ireqs(requirements, rep->defaultRequirements(&arch.architecture, state), context); if (editor->attribute(writerNoGlobal)) // can't store globally, add per-arch populate(arch); @@ -466,7 +477,7 @@ void SecCodeSigner::Signer::signArchitectureAgnostic(const Requirement::Context if (state.mDetached) { CFRef identification = rep->identification(); writer->component(cdIdentificationSlot, identification); - } + } CodeDirectory *cd = builder.build(); CFRef signature = signCodeDirectory(cd); diff --git a/libsecurity_codesigning/lib/signer.h b/Security/libsecurity_codesigning/lib/signer.h similarity index 96% rename from libsecurity_codesigning/lib/signer.h rename to Security/libsecurity_codesigning/lib/signer.h index d27abcb2..c7ac989c 100644 --- a/libsecurity_codesigning/lib/signer.h +++ b/Security/libsecurity_codesigning/lib/signer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -57,7 +57,7 @@ public: CodeDirectory::HashAlgorithm digestAlgorithm() const { return state.mDigestAlgorithm; } - std::string path() const { return cfString(rep->copyCanonicalPath()); } + std::string path() const { return cfStringRelease(rep->copyCanonicalPath()); } SecIdentityRef signingIdentity() const { return state.mSigner; } std::string signingIdentifier() const { return identifier; } diff --git a/libsecurity_codesigning/lib/signerutils.cpp b/Security/libsecurity_codesigning/lib/signerutils.cpp similarity index 99% rename from libsecurity_codesigning/lib/signerutils.cpp rename to Security/libsecurity_codesigning/lib/signerutils.cpp index 74dd23ce..6b6bbad0 100644 --- a/libsecurity_codesigning/lib/signerutils.cpp +++ b/Security/libsecurity_codesigning/lib/signerutils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/signerutils.h b/Security/libsecurity_codesigning/lib/signerutils.h similarity index 99% rename from libsecurity_codesigning/lib/signerutils.h rename to Security/libsecurity_codesigning/lib/signerutils.h index b4d3b193..906be1ea 100644 --- a/libsecurity_codesigning/lib/signerutils.h +++ b/Security/libsecurity_codesigning/lib/signerutils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/singlediskrep.cpp b/Security/libsecurity_codesigning/lib/singlediskrep.cpp similarity index 96% rename from libsecurity_codesigning/lib/singlediskrep.cpp rename to Security/libsecurity_codesigning/lib/singlediskrep.cpp index c3ba5207..e7ac3281 100644 --- a/libsecurity_codesigning/lib/singlediskrep.cpp +++ b/Security/libsecurity_codesigning/lib/singlediskrep.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -27,6 +27,7 @@ #include "singlediskrep.h" #include "csutilities.h" #include +#include namespace Security { namespace CodeSigning { @@ -81,7 +82,6 @@ size_t SingleDiskRep::signingLimit() return fd().fileSize(); } - // // A lazily opened read-only file descriptor for the path. // @@ -89,10 +89,10 @@ FileDesc &SingleDiskRep::fd() { if (!mFd) mFd.open(mPath, O_RDONLY); + return mFd; } - // // Flush cached state // diff --git a/libsecurity_codesigning/lib/singlediskrep.h b/Security/libsecurity_codesigning/lib/singlediskrep.h similarity index 97% rename from libsecurity_codesigning/lib/singlediskrep.h rename to Security/libsecurity_codesigning/lib/singlediskrep.h index c8e94c60..7d802b61 100644 --- a/libsecurity_codesigning/lib/singlediskrep.h +++ b/Security/libsecurity_codesigning/lib/singlediskrep.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2007,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -54,7 +54,7 @@ public: void flush(); // close cached fd std::string recommendedIdentifier(const SigningContext &ctx); // basename(path) - + public: class Writer; diff --git a/libsecurity_codesigning/lib/slcrep.cpp b/Security/libsecurity_codesigning/lib/slcrep.cpp similarity index 98% rename from libsecurity_codesigning/lib/slcrep.cpp rename to Security/libsecurity_codesigning/lib/slcrep.cpp index 4bb94434..8a0ecbd4 100644 --- a/libsecurity_codesigning/lib/slcrep.cpp +++ b/Security/libsecurity_codesigning/lib/slcrep.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2009,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/slcrep.h b/Security/libsecurity_codesigning/lib/slcrep.h similarity index 97% rename from libsecurity_codesigning/lib/slcrep.h rename to Security/libsecurity_codesigning/lib/slcrep.h index f500f26b..d1b2a554 100644 --- a/libsecurity_codesigning/lib/slcrep.h +++ b/Security/libsecurity_codesigning/lib/slcrep.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2009,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/syspolicy.sql b/Security/libsecurity_codesigning/lib/syspolicy.sql similarity index 100% rename from libsecurity_codesigning/lib/syspolicy.sql rename to Security/libsecurity_codesigning/lib/syspolicy.sql diff --git a/libsecurity_codesigning/lib/xar++.cpp b/Security/libsecurity_codesigning/lib/xar++.cpp similarity index 97% rename from libsecurity_codesigning/lib/xar++.cpp rename to Security/libsecurity_codesigning/lib/xar++.cpp index 30e9665e..3029c5bb 100644 --- a/libsecurity_codesigning/lib/xar++.cpp +++ b/Security/libsecurity_codesigning/lib/xar++.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/xar++.h b/Security/libsecurity_codesigning/lib/xar++.h similarity index 96% rename from libsecurity_codesigning/lib/xar++.h rename to Security/libsecurity_codesigning/lib/xar++.h index 11f4f7e4..8d9dccff 100644 --- a/libsecurity_codesigning/lib/xar++.h +++ b/Security/libsecurity_codesigning/lib/xar++.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_codesigning/lib/xpcengine.cpp b/Security/libsecurity_codesigning/lib/xpcengine.cpp similarity index 82% rename from libsecurity_codesigning/lib/xpcengine.cpp rename to Security/libsecurity_codesigning/lib/xpcengine.cpp index 4a289f63..2da4e67f 100644 --- a/libsecurity_codesigning/lib/xpcengine.cpp +++ b/Security/libsecurity_codesigning/lib/xpcengine.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -25,10 +25,15 @@ #include #include #include +#include namespace Security { namespace CodeSigning { + + +static void doProgress(xpc_object_t msg); + static const char serviceName[] = "com.apple.security.syspolicy"; @@ -45,7 +50,13 @@ static void init() name = env; queue = dispatch_queue_create("spd-client", 0); service = xpc_connection_create_mach_service(name, queue, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED); - xpc_connection_set_event_handler(service, ^(xpc_object_t ev) { + xpc_connection_set_event_handler(service, ^(xpc_object_t msg) { + if (xpc_get_type(msg) == XPC_TYPE_DICTIONARY) { + const char *function = xpc_dictionary_get_string(msg, "function"); + if (!strcmp(function, "progress")) { + doProgress(msg); + } + } }); xpc_connection_resume(service); }); @@ -103,6 +114,8 @@ static void copyCFDictionary(const void *key, const void *value, void *ctx) if (CFGetTypeID(value) == CFURLGetTypeID()) { CFRef path = CFURLCopyFileSystemPath(CFURLRef(value), kCFURLPOSIXPathStyle); CFDictionaryAddValue(target, key, path); + } else if (CFEqual(key, kSecAssessmentContextKeyFeedback)) { + CFDictionaryAddValue(target, key, CFTempNumber(uint64_t(value))); } else { CFDictionaryAddValue(target, key, value); } @@ -130,6 +143,25 @@ void xpcEngineAssess(CFURLRef path, SecAssessmentFlags flags, CFDictionaryRef co CFDictionaryApplyFunction(resultDict, copyCFDictionary, result); CFDictionaryAddValue(result, CFSTR("assessment:remote"), kCFBooleanTrue); } + +static void doProgress(xpc_object_t msg) +{ + uint64_t current = xpc_dictionary_get_uint64(msg, "current"); + uint64_t total = xpc_dictionary_get_uint64(msg, "total"); + uint64_t ref = xpc_dictionary_get_uint64(msg, "ref"); + const char *token = xpc_dictionary_get_string(msg, "token"); + SecAssessmentFeedback feedback = SecAssessmentFeedback(ref); + CFTemp info("{current=%d,total=%d}", current, total); + Boolean proceed = feedback(kSecAssessmentFeedbackProgress, info); + if (!proceed) { + xpc_connection_t connection = xpc_dictionary_get_remote_connection(msg); + xpc_object_t cancelRequest = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_string(cancelRequest, "function", "cancel"); + xpc_dictionary_set_string(cancelRequest, "token", token); + xpc_connection_send_message(connection, cancelRequest); + xpc_release(cancelRequest); + } +} CFDictionaryRef xpcEngineUpdate(CFTypeRef target, SecAssessmentFlags flags, CFDictionaryRef context) diff --git a/libsecurity_codesigning/lib/xpcengine.h b/Security/libsecurity_codesigning/lib/xpcengine.h similarity index 96% rename from libsecurity_codesigning/lib/xpcengine.h rename to Security/libsecurity_codesigning/lib/xpcengine.h index 0e64f478..cd70387d 100644 --- a/libsecurity_codesigning/lib/xpcengine.h +++ b/Security/libsecurity_codesigning/lib/xpcengine.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj b/Security/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj new file mode 100644 index 00000000..b42baeda --- /dev/null +++ b/Security/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj @@ -0,0 +1,2172 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + C26AC0EB143BCF01001C98CE /* SystemPolicy */ = { + isa = PBXAggregateTarget; + buildConfigurationList = C26AC0EC143BCF01001C98CE /* Build configuration list for PBXAggregateTarget "SystemPolicy" */; + buildPhases = ( + C26AC0F0143BCF18001C98CE /* ShellScript */, + C26AC0F4143BD1C4001C98CE /* CopyFiles */, + C2F24DFE14BCBBF200309FCD /* ShellScript */, + C2578CB11579627200D4FE48 /* CopyFiles */, + C25C18CD15CB0C470007A2DE /* CopyFiles */, + C25C18D015CB0FB30007A2DE /* CopyFiles */, + ); + dependencies = ( + ); + name = SystemPolicy; + productName = SystemPolicy; + }; + C26AC7090DAEB3A7005BFB40 /* DTrace */ = { + isa = PBXAggregateTarget; + buildConfigurationList = C26AC70D0DAEB3C6005BFB40 /* Build configuration list for PBXAggregateTarget "DTrace" */; + buildPhases = ( + C26AC7080DAEB3A7005BFB40 /* ShellScript */, + ); + dependencies = ( + ); + name = DTrace; + productName = DTrace; + }; + C2D383B80A23A8C4005C63A2 /* Requirements Language */ = { + isa = PBXAggregateTarget; + buildConfigurationList = C2D383C00A23A8E3005C63A2 /* Build configuration list for PBXAggregateTarget "Requirements Language" */; + buildPhases = ( + C2D383B70A23A8C4005C63A2 /* ShellScript */, + ); + dependencies = ( + ); + name = "Requirements Language"; + productName = "Requirements Language"; + }; + C2E2873F0B5D8F8F009336A0 /* Everything */ = { + isa = PBXAggregateTarget; + buildConfigurationList = C2E287470B5D8FD8009336A0 /* Build configuration list for PBXAggregateTarget "Everything" */; + buildPhases = ( + ); + dependencies = ( + C2E287410B5D8F97009336A0 /* PBXTargetDependency */, + C250F6C50B5EF4E40076098F /* PBXTargetDependency */, + C2E287430B5D8F9A009336A0 /* PBXTargetDependency */, + C26AC0F2143BD02B001C98CE /* PBXTargetDependency */, + C209697015BF53330093035F /* PBXTargetDependency */, + ); + name = Everything; + productName = Everything; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 18B965861472FBF6005A4D2E /* reqdumper.h in Headers */ = {isa = PBXBuildFile; fileRef = C21CFC5E0A250D1C006CD5B1 /* reqdumper.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18B965871472FC5B005A4D2E /* requirement.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D383360A237F47005C63A2 /* requirement.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18B965881472FC5B005A4D2E /* reqmaker.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C1DFC20A2F820500D1B02B /* reqmaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18B965891472FC5B005A4D2E /* reqreader.h in Headers */ = {isa = PBXBuildFile; fileRef = C2093AA70BB0948000EB8599 /* reqreader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18B9658A1472FC5B005A4D2E /* reqinterp.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C1DFBA0A2F80EB00D1B02B /* reqinterp.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18B9658B1472FC5B005A4D2E /* reqparser.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D383340A237F47005C63A2 /* reqparser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18B9658C1472FC9E005A4D2E /* codedirectory.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D383170A237F47005C63A2 /* codedirectory.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18B965951472FE30005A4D2E /* cdbuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D383150A237F47005C63A2 /* cdbuilder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 37DDE33C1947A4F3005CE18B /* dirscanner.h in Headers */ = {isa = PBXBuildFile; fileRef = 37DDE33B1947A4F3005CE18B /* dirscanner.h */; }; + 37DDE3421947A501005CE18B /* dirscanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 37DDE3411947A501005CE18B /* dirscanner.cpp */; }; + 7A4FAF1B19C215DF00D297CB /* CrashReporterSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A4FAF1A19C215DF00D297CB /* CrashReporterSupport.framework */; }; + 7A9DA65C1948D1BA004635E6 /* opaquewhitelist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A9DA65A1948D1BA004635E6 /* opaquewhitelist.cpp */; }; + 7A9DA65D1948D1BA004635E6 /* opaquewhitelist.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A9DA65B1948D1BA004635E6 /* opaquewhitelist.h */; }; + 7AADF58919C0CED800292339 /* gkoverride.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AADF58819C0CED800292339 /* gkoverride.m */; }; + 7ACF261219958B6F00849B25 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2CC30A00B8519CC005FA59D /* CoreFoundation.framework */; }; + BEC3A75C16F78D21003E5634 /* SecTaskPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = BEC3A75B16F78D21003E5634 /* SecTaskPriv.h */; }; + C200424D15D425D9004AE0A1 /* libsecurity_codesigning.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C200424915D425B7004AE0A1 /* libsecurity_codesigning.a */; }; + C200424E15D425D9004AE0A1 /* libsecurity_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C200424A15D425B7004AE0A1 /* libsecurity_utilities.a */; }; + C2093AA80BB0948000EB8599 /* reqreader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2093AA60BB0948000EB8599 /* reqreader.cpp */; }; + C209696415BF52040093035F /* gkunpack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C209696315BF52040093035F /* gkunpack.cpp */; }; + C211070A158C1082001D7F76 /* gkmerge in CopyFiles */ = {isa = PBXBuildFile; fileRef = C2110704158BF5C8001D7F76 /* gkmerge */; }; + C21CFC5F0A250D1C006CD5B1 /* reqdumper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C21CFC5D0A250D1C006CD5B1 /* reqdumper.cpp */; }; + C21EA3DD0AD2F81300E6E31C /* SecCodeSigner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C21EA3DB0AD2F81300E6E31C /* SecCodeSigner.cpp */; }; + C21EA3E30AD2FA0900E6E31C /* CodeSigner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C21EA3E10AD2FA0900E6E31C /* CodeSigner.cpp */; }; + C22463610B86210100626F1B /* antlrplugin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2CC31130B85254F005FA59D /* antlrplugin.cpp */; }; + C2256BDD158BC0F200F72211 /* gkhandmake in CopyFiles */ = {isa = PBXBuildFile; fileRef = C278A19B158AB2C300FA6767 /* gkhandmake */; }; + C2256BDE158BC0F200F72211 /* gklist in CopyFiles */ = {isa = PBXBuildFile; fileRef = C278A19C158AB2C300FA6767 /* gklist */; }; + C236E3D70AD59446000F5140 /* signer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C236E3D50AD59446000F5140 /* signer.cpp */; }; + C236E3DB0AD595C2000F5140 /* signerutils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C236E3D90AD595C2000F5140 /* signerutils.cpp */; }; + C24EABAB1421432800C16AA9 /* policydb.h in Headers */ = {isa = PBXBuildFile; fileRef = C24EABAA1421432800C16AA9 /* policydb.h */; }; + C24EABAD1421433700C16AA9 /* policydb.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C24EABAC1421433700C16AA9 /* policydb.cpp */; }; + C250F6C30B5EF1910076098F /* SecIntegrity.h in Headers */ = {isa = PBXBuildFile; fileRef = C250F6C20B5EF1910076098F /* SecIntegrity.h */; }; + C259DFD60AD6D9BA00C9ACC6 /* sigblob.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C259DFD40AD6D9BA00C9ACC6 /* sigblob.cpp */; }; + C25C18CE15CB0C5C0007A2DE /* gkreport in CopyFiles */ = {isa = PBXBuildFile; fileRef = C25C18C615CB0BC10007A2DE /* gkreport */; }; + C25C18D115CB0FC30007A2DE /* com.apple.gkreport.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = C25C18CF15CB0FA00007A2DE /* com.apple.gkreport.plist */; }; + C26763D714FD9EBE00A46EDF /* drmaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C26763D514FD9EBE00A46EDF /* drmaker.cpp */; }; + C26763D814FD9EBE00A46EDF /* drmaker.h in Headers */ = {isa = PBXBuildFile; fileRef = C26763D614FD9EBE00A46EDF /* drmaker.h */; }; + C26AC0F5143BD1C8001C98CE /* SystemPolicy in CopyFiles */ = {isa = PBXBuildFile; fileRef = C26AC0F3143BD1B3001C98CE /* SystemPolicy */; }; + C26B45C10B8A9C0A003C0ACA /* ucspc in Frameworks */ = {isa = PBXBuildFile; fileRef = C26B45C00B8A9C00003C0ACA /* ucspc */; }; + C26FF62D0E5B375A00F640A0 /* SecIntegrityLib.h in Headers */ = {isa = PBXBuildFile; fileRef = C2CC31040B8523AD005FA59D /* SecIntegrityLib.h */; settings = {ATTRIBUTES = (); }; }; + C26FF62E0E5B375A00F640A0 /* SecCodeHostLib.h in Headers */ = {isa = PBXBuildFile; fileRef = C2BC1F340B580DA7003EC9DC /* SecCodeHostLib.h */; settings = {ATTRIBUTES = (); }; }; + C26FF62F0E5B376B00F640A0 /* CodeSigning.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D383180A237F47005C63A2 /* CodeSigning.h */; settings = {ATTRIBUTES = (); }; }; + C26FF6300E5B376B00F640A0 /* CSCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D3831C0A237F47005C63A2 /* CSCommon.h */; settings = {ATTRIBUTES = (); }; }; + C26FF6310E5B376B00F640A0 /* CSCommonPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D50CDF0E155A4F0059A195 /* CSCommonPriv.h */; settings = {ATTRIBUTES = (); }; }; + C26FF6320E5B376B00F640A0 /* SecCode.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D3831E0A237F47005C63A2 /* SecCode.h */; settings = {ATTRIBUTES = (); }; }; + C26FF6330E5B376B00F640A0 /* SecCodePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2E8AF240DE25CA7000F6D3B /* SecCodePriv.h */; settings = {ATTRIBUTES = (); }; }; + C26FF6340E5B376B00F640A0 /* SecStaticCode.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D383220A237F47005C63A2 /* SecStaticCode.h */; settings = {ATTRIBUTES = (); }; }; + C26FF6350E5B376B00F640A0 /* SecStaticCodePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2E8AF260DE25CA7000F6D3B /* SecStaticCodePriv.h */; settings = {ATTRIBUTES = (); }; }; + C26FF6360E5B376B00F640A0 /* SecRequirement.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D383260A237F47005C63A2 /* SecRequirement.h */; settings = {ATTRIBUTES = (); }; }; + C26FF6370E5B376B00F640A0 /* SecRequirementPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2E8AF250DE25CA7000F6D3B /* SecRequirementPriv.h */; settings = {ATTRIBUTES = (); }; }; + C26FF6380E5B376B00F640A0 /* SecCodeSigner.h in Headers */ = {isa = PBXBuildFile; fileRef = C21EA3DC0AD2F81300E6E31C /* SecCodeSigner.h */; settings = {ATTRIBUTES = (); }; }; + C26FF6390E5B376B00F640A0 /* SecCodeHost.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D383190A237F47005C63A2 /* SecCodeHost.h */; settings = {ATTRIBUTES = (); }; }; + C26FF63A0E5B376B00F640A0 /* SecIntegrity.h in Headers */ = {isa = PBXBuildFile; fileRef = C250F6C20B5EF1910076098F /* SecIntegrity.h */; settings = {ATTRIBUTES = (); }; }; + C273606E1433F09000A9A5FF /* SecAssessment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C273606C1433F09000A9A5FF /* SecAssessment.cpp */; }; + C273606F1433F09000A9A5FF /* SecAssessment.h in Headers */ = {isa = PBXBuildFile; fileRef = C273606D1433F09000A9A5FF /* SecAssessment.h */; settings = {ATTRIBUTES = (); }; }; + C27360D51436866D00A9A5FF /* xpcengine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C27360D41436866C00A9A5FF /* xpcengine.cpp */; }; + C28342E70E366E6800E54360 /* csdatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C28342E40E366E6800E54360 /* csdatabase.cpp */; }; + C28342EE0E36719D00E54360 /* detachedrep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C28342EB0E36719D00E54360 /* detachedrep.cpp */; }; + C29CDE2A1583F46F00A42059 /* gkclear in CopyFiles */ = {isa = PBXBuildFile; fileRef = C2578CC215798D0F00D4FE48 /* gkclear */; }; + C29CDE2B1583F46F00A42059 /* gkgenerate in CopyFiles */ = {isa = PBXBuildFile; fileRef = C2578CC315798D0F00D4FE48 /* gkgenerate */; }; + C29CDE2C1583F46F00A42059 /* gkrecord in CopyFiles */ = {isa = PBXBuildFile; fileRef = C2578CC415798D0F00D4FE48 /* gkrecord */; }; + C2A436150F2133B2007A41A6 /* slcrep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2A436130F2133B2007A41A6 /* slcrep.cpp */; }; + C2A436160F2133B2007A41A6 /* slcrep.h in Headers */ = {isa = PBXBuildFile; fileRef = C2A436140F2133B2007A41A6 /* slcrep.h */; }; + C2A976AA0B8A2E36008B4EA0 /* csutilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2A976A80B8A2E36008B4EA0 /* csutilities.cpp */; }; + C2BC1F350B580DA7003EC9DC /* SecCodeHostLib.h in Headers */ = {isa = PBXBuildFile; fileRef = C2BC1F340B580DA7003EC9DC /* SecCodeHostLib.h */; }; + C2BD519C0A9392FD000FE43D /* machorep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2BD519A0A9392FD000FE43D /* machorep.cpp */; }; + C2BD60FA0AC863FC0057FD3D /* csgeneric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2BD60F80AC863FC0057FD3D /* csgeneric.cpp */; }; + C2C1DF140A2E3D7200D1B02B /* requirement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383350A237F47005C63A2 /* requirement.cpp */; }; + C2C1DFBB0A2F80EB00D1B02B /* reqinterp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2C1DFB90A2F80EB00D1B02B /* reqinterp.cpp */; }; + C2C1DFC30A2F820500D1B02B /* reqmaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2C1DFC10A2F820500D1B02B /* reqmaker.cpp */; }; + 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 */; }; + 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 */; }; + C2D383440A237F47005C63A2 /* cs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D3831A0A237F47005C63A2 /* cs.cpp */; }; + C2D383470A237F47005C63A2 /* SecCode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D3831D0A237F47005C63A2 /* SecCode.cpp */; }; + C2D383490A237F47005C63A2 /* cskernel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D3831F0A237F47005C63A2 /* cskernel.cpp */; }; + C2D3834B0A237F47005C63A2 /* SecStaticCode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383210A237F47005C63A2 /* SecStaticCode.cpp */; }; + C2D3834D0A237F47005C63A2 /* csprocess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383230A237F47005C63A2 /* csprocess.cpp */; }; + C2D3834F0A237F47005C63A2 /* SecRequirement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383250A237F47005C63A2 /* SecRequirement.cpp */; }; + C2D383510A237F47005C63A2 /* diskrep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383270A237F47005C63A2 /* diskrep.cpp */; }; + C2D383550A237F47005C63A2 /* filediskrep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D3832B0A237F47005C63A2 /* filediskrep.cpp */; }; + C2D383570A237F47005C63A2 /* Code.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D3832D0A237F47005C63A2 /* Code.cpp */; }; + C2D383590A237F47005C63A2 /* kerneldiskrep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D3832F0A237F47005C63A2 /* kerneldiskrep.cpp */; }; + C2D3835B0A237F47005C63A2 /* StaticCode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383310A237F47005C63A2 /* StaticCode.cpp */; }; + C2D3835D0A237F47005C63A2 /* reqparser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383330A237F47005C63A2 /* reqparser.cpp */; }; + C2D383610A237F47005C63A2 /* Requirements.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383370A237F47005C63A2 /* Requirements.cpp */; }; + C2DC2DCA145F594000AD2A3A /* xar++.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2353410145F1B110073F964 /* xar++.cpp */; }; + C2DC2DCB145F5CD000AD2A3A /* policyengine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C27360201432A61900A9A5FF /* policyengine.cpp */; }; + C2E2873D0B5D8D80009336A0 /* SecCodeHostLib.c in Sources */ = {isa = PBXBuildFile; fileRef = C2E2873C0B5D8D80009336A0 /* SecCodeHostLib.c */; }; + C2E911E20ADEBE3200275CB2 /* resources.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2E911E00ADEBE3200275CB2 /* resources.cpp */; }; + C2F4439A14C626D4000A01E6 /* quarantine++.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F4439814C626D4000A01E6 /* quarantine++.cpp */; }; + C2F4439B14C626D4000A01E6 /* quarantine++.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F4439914C626D4000A01E6 /* quarantine++.h */; }; + C2F6566E0BCBFB250078779E /* cserror.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F6566C0BCBFB250078779E /* cserror.cpp */; }; + EB68B111150DAEEA00B4013D /* RequirementLexer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB68B10B150DAEBB00B4013D /* RequirementLexer.cpp */; }; + EB68B112150DAEEA00B4013D /* RequirementParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB68B10D150DAEBB00B4013D /* RequirementParser.cpp */; }; + EB68B133150DB04400B4013D /* RequirementKeywords.h in Headers */ = {isa = PBXBuildFile; fileRef = EB68B10A150DAEBB00B4013D /* RequirementKeywords.h */; }; + EB68B134150DB04400B4013D /* RequirementLexer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EB68B10C150DAEBB00B4013D /* RequirementLexer.hpp */; }; + EB68B135150DB04400B4013D /* RequirementParser.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EB68B10E150DAEBB00B4013D /* RequirementParser.hpp */; }; + EB976FB81684D7C500A68EE6 /* ANTLRUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976F981684D77600A68EE6 /* ANTLRUtil.cpp */; }; + EB976FB91684D7C500A68EE6 /* ASTFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976F991684D77600A68EE6 /* ASTFactory.cpp */; }; + EB976FBA1684D7C500A68EE6 /* ASTNULLType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976F9A1684D77600A68EE6 /* ASTNULLType.cpp */; }; + EB976FBB1684D7C500A68EE6 /* ASTRefCount.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976F9B1684D77600A68EE6 /* ASTRefCount.cpp */; }; + EB976FBC1684D7C500A68EE6 /* BaseAST.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976F9C1684D77600A68EE6 /* BaseAST.cpp */; }; + EB976FBD1684D7C500A68EE6 /* BitSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976F9D1684D77600A68EE6 /* BitSet.cpp */; }; + EB976FBE1684D7C500A68EE6 /* CharBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976F9E1684D77600A68EE6 /* CharBuffer.cpp */; }; + EB976FBF1684D7C500A68EE6 /* CharScanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976F9F1684D77600A68EE6 /* CharScanner.cpp */; }; + EB976FC01684D7C500A68EE6 /* CommonAST.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FA01684D77600A68EE6 /* CommonAST.cpp */; }; + EB976FC11684D7C500A68EE6 /* CommonASTWithHiddenTokens.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FA11684D77600A68EE6 /* CommonASTWithHiddenTokens.cpp */; }; + EB976FC21684D7C500A68EE6 /* CommonHiddenStreamToken.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FA21684D77600A68EE6 /* CommonHiddenStreamToken.cpp */; }; + EB976FC31684D7C500A68EE6 /* CommonToken.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FA31684D77600A68EE6 /* CommonToken.cpp */; }; + EB976FC41684D7C500A68EE6 /* InputBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FA51684D77600A68EE6 /* InputBuffer.cpp */; }; + EB976FC51684D7C500A68EE6 /* LLkParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FA61684D77600A68EE6 /* LLkParser.cpp */; }; + EB976FC61684D7C500A68EE6 /* MismatchedCharException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FA81684D77600A68EE6 /* MismatchedCharException.cpp */; }; + EB976FC71684D7C500A68EE6 /* MismatchedTokenException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FA91684D77600A68EE6 /* MismatchedTokenException.cpp */; }; + EB976FC81684D7C500A68EE6 /* NoViableAltException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FAA1684D77600A68EE6 /* NoViableAltException.cpp */; }; + EB976FC91684D7C500A68EE6 /* NoViableAltForCharException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FAB1684D77600A68EE6 /* NoViableAltForCharException.cpp */; }; + EB976FCA1684D7C500A68EE6 /* Parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FAC1684D77600A68EE6 /* Parser.cpp */; }; + EB976FCB1684D7C500A68EE6 /* RecognitionException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FAD1684D77600A68EE6 /* RecognitionException.cpp */; }; + EB976FCC1684D7C500A68EE6 /* String.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FAE1684D77600A68EE6 /* String.cpp */; }; + EB976FCD1684D7C500A68EE6 /* Token.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FAF1684D77600A68EE6 /* Token.cpp */; }; + EB976FCE1684D7C500A68EE6 /* TokenBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FB01684D77600A68EE6 /* TokenBuffer.cpp */; }; + EB976FCF1684D7C500A68EE6 /* TokenRefCount.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FB11684D77600A68EE6 /* TokenRefCount.cpp */; }; + EB976FD01684D7C500A68EE6 /* TokenStreamBasicFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FB21684D77600A68EE6 /* TokenStreamBasicFilter.cpp */; }; + EB976FD11684D7C500A68EE6 /* TokenStreamHiddenTokenFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FB31684D77600A68EE6 /* TokenStreamHiddenTokenFilter.cpp */; }; + EB976FD21684D7C500A68EE6 /* TokenStreamRewriteEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FB41684D77600A68EE6 /* TokenStreamRewriteEngine.cpp */; }; + EB976FD31684D7C500A68EE6 /* TokenStreamSelector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FB51684D77600A68EE6 /* TokenStreamSelector.cpp */; }; + EB976FD41684D7C500A68EE6 /* TreeParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FB61684D77600A68EE6 /* TreeParser.cpp */; }; + EBB9FF7A1682E51300FF9774 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = EBB9FF791682E51300FF9774 /* main.c */; }; + EBB9FF7F1682E5A200FF9774 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBB9FF7E1682E5A200FF9774 /* CoreFoundation.framework */; }; + EBB9FFE21682E83600FF9774 /* com.apple.CodeSigningHelper.sb in CopyFiles */ = {isa = PBXBuildFile; fileRef = EBB9FF801682E65700FF9774 /* com.apple.CodeSigningHelper.sb */; }; + EBDAF04F166D65FA0042CDCE /* piddiskrep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EBDAF04D166D65FA0042CDCE /* piddiskrep.cpp */; }; + EBDAF050166D65FA0042CDCE /* piddiskrep.h in Headers */ = {isa = PBXBuildFile; fileRef = EBDAF04E166D65FA0042CDCE /* piddiskrep.h */; }; + EBF9A1581684E12700BCECA6 /* libsecurity_codesigning.plist in Copy OpenSourceVersions */ = {isa = PBXBuildFile; fileRef = EBF9A1551684E0F300BCECA6 /* libsecurity_codesigning.plist */; }; + EBF9A15A1684E14100BCECA6 /* libsecurity_codesigning.txt in OpenSourceLicenses */ = {isa = PBXBuildFile; fileRef = EBF9A1561684E0F300BCECA6 /* libsecurity_codesigning.txt */; }; + FEB30C9310DAC89D00557BA2 /* SecTask.c in Sources */ = {isa = PBXBuildFile; fileRef = FEB30C9210DAC89D00557BA2 /* SecTask.c */; }; + FEB30CA410DAC97400557BA2 /* SecTask.h in Headers */ = {isa = PBXBuildFile; fileRef = FEB30C9410DAC8A500557BA2 /* SecTask.h */; settings = {ATTRIBUTES = (); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 182BB504146F2823000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 182BB4FC146F2823000BF1F3 /* libsecurityd.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurityd_client; + }; + 182BB506146F2823000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 182BB4FC146F2823000BF1F3 /* libsecurityd.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FECD052A44A100F22E42; + remoteInfo = libsecurityd_server; + }; + 182BB508146F2823000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 182BB4FC146F2823000BF1F3 /* libsecurityd.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = C2A788730B7AA65B00CFF85C; + remoteInfo = ucspc; + }; + 182BB50E146F28F6000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 182BB4FC146F2823000BF1F3 /* libsecurityd.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4C09A2920557240300FED7A3; + remoteInfo = libsecurityd_generate; + }; + 182BB510146F292B000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C26AC0EB143BCF01001C98CE; + remoteInfo = SystemPolicy; + }; + 1844617C146E9A5200B12992 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C26AC7090DAEB3A7005BFB40; + remoteInfo = DTrace; + }; + C209696F15BF53330093035F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C209695F15BF52040093035F; + remoteInfo = gkunpack; + }; + C250F6C40B5EF4E40076098F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C2BC1F250B580D3A003EC9DC; + remoteInfo = libintegrity; + }; + C26AC0F1143BD02B001C98CE /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C26AC0EB143BCF01001C98CE; + remoteInfo = SystemPolicy; + }; + C2E287400B5D8F97009336A0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_codesigning; + }; + C2E287420B5D8F9A009336A0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C2BC1F2E0B580D4B003EC9DC; + remoteInfo = libcodehost; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + C2578CB11579627200D4FE48 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/local/bin; + dstSubfolderSpec = 0; + files = ( + C211070A158C1082001D7F76 /* gkmerge in CopyFiles */, + C2256BDD158BC0F200F72211 /* gkhandmake in CopyFiles */, + C2256BDE158BC0F200F72211 /* gklist in CopyFiles */, + C29CDE2A1583F46F00A42059 /* gkclear in CopyFiles */, + C29CDE2B1583F46F00A42059 /* gkgenerate in CopyFiles */, + C29CDE2C1583F46F00A42059 /* gkrecord in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + C25C18CD15CB0C470007A2DE /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/libexec; + dstSubfolderSpec = 0; + files = ( + C25C18CE15CB0C5C0007A2DE /* gkreport in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + C25C18D015CB0FB30007A2DE /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /System/Library/LaunchDaemons; + dstSubfolderSpec = 0; + files = ( + C25C18D115CB0FC30007A2DE /* com.apple.gkreport.plist in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + C26AC0F4143BD1C4001C98CE /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = private/var/db; + dstSubfolderSpec = 0; + files = ( + C26AC0F5143BD1C8001C98CE /* SystemPolicy in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + EBB9FFE11682E80A00FF9774 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /System/Library/Sandbox/Profiles; + dstSubfolderSpec = 0; + files = ( + EBB9FFE21682E83600FF9774 /* com.apple.CodeSigningHelper.sb in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + EBF9A1501684E0DF00BCECA6 /* Copy OpenSourceVersions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/local/OpenSourceVersions; + dstSubfolderSpec = 0; + files = ( + EBF9A1581684E12700BCECA6 /* libsecurity_codesigning.plist in Copy OpenSourceVersions */, + ); + name = "Copy OpenSourceVersions"; + runOnlyForDeploymentPostprocessing = 1; + }; + EBF9A1591684E12C00BCECA6 /* OpenSourceLicenses */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/local/OpenSourceLicenses; + dstSubfolderSpec = 0; + files = ( + EBF9A15A1684E14100BCECA6 /* libsecurity_codesigning.txt in OpenSourceLicenses */, + ); + name = OpenSourceLicenses; + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 182BB4FC146F2823000BF1F3 /* libsecurityd.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurityd.xcodeproj; path = ../libsecurityd/libsecurityd.xcodeproj; sourceTree = ""; }; + 1844619F146E9AD100B12992 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 184461A0146E9AD100B12992 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 184461A1146E9AD100B12992 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 184461A2146E9AD100B12992 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 37DDE33B1947A4F3005CE18B /* dirscanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dirscanner.h; sourceTree = ""; }; + 37DDE3411947A501005CE18B /* dirscanner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dirscanner.cpp; sourceTree = ""; }; + 4CA1FEBE052A3C8100F22E42 /* libsecurity_codesigning.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_codesigning.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 7A4FAF1A19C215DF00D297CB /* CrashReporterSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CrashReporterSupport.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.Internal.sdk/System/Library/PrivateFrameworks/CrashReporterSupport.framework; sourceTree = DEVELOPER_DIR; }; + 7A9DA65A1948D1BA004635E6 /* opaquewhitelist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = opaquewhitelist.cpp; sourceTree = ""; }; + 7A9DA65B1948D1BA004635E6 /* opaquewhitelist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = opaquewhitelist.h; sourceTree = ""; }; + 7AADF57D19C0CE8C00292339 /* gkoverride */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = gkoverride; sourceTree = BUILT_PRODUCTS_DIR; }; + 7AADF58819C0CED800292339 /* gkoverride.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = gkoverride.m; sourceTree = ""; }; + BEC3A75B16F78D21003E5634 /* SecTaskPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTaskPriv.h; sourceTree = ""; }; + C200424915D425B7004AE0A1 /* libsecurity_codesigning.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_codesigning.a; path = ../../../usr/local/lib/libsecurity_codesigning.a; sourceTree = ""; }; + C200424A15D425B7004AE0A1 /* libsecurity_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_utilities.a; path = ../../../usr/local/lib/libsecurity_utilities.a; sourceTree = ""; }; + C2093AA60BB0948000EB8599 /* reqreader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = reqreader.cpp; sourceTree = ""; }; + C2093AA70BB0948000EB8599 /* reqreader.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = reqreader.h; sourceTree = ""; }; + C209696015BF52040093035F /* gkunpack */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = gkunpack; sourceTree = BUILT_PRODUCTS_DIR; }; + C209696315BF52040093035F /* gkunpack.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = gkunpack.cpp; sourceTree = ""; }; + C209697215BF57EB0093035F /* libsecurity_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libsecurity_utilities.a; sourceTree = ""; }; + C2110704158BF5C8001D7F76 /* gkmerge */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = gkmerge; sourceTree = ""; }; + C21CFC5D0A250D1C006CD5B1 /* reqdumper.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = reqdumper.cpp; sourceTree = ""; }; + C21CFC5E0A250D1C006CD5B1 /* reqdumper.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = reqdumper.h; sourceTree = ""; }; + C21EA3DB0AD2F81300E6E31C /* SecCodeSigner.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecCodeSigner.cpp; sourceTree = ""; }; + C21EA3DC0AD2F81300E6E31C /* SecCodeSigner.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCodeSigner.h; sourceTree = ""; }; + C21EA3E10AD2FA0900E6E31C /* CodeSigner.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CodeSigner.cpp; sourceTree = ""; }; + C21EA3E20AD2FA0900E6E31C /* CodeSigner.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CodeSigner.h; sourceTree = ""; }; + C235340E145F1B050073F964 /* xar++.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "xar++.h"; sourceTree = ""; }; + C2353410145F1B110073F964 /* xar++.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "xar++.cpp"; sourceTree = ""; }; + C236E3D50AD59446000F5140 /* signer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = signer.cpp; sourceTree = ""; }; + C236E3D60AD59446000F5140 /* signer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = signer.h; sourceTree = ""; }; + C236E3D90AD595C2000F5140 /* signerutils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = signerutils.cpp; sourceTree = ""; }; + C236E3DA0AD595C2000F5140 /* signerutils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = signerutils.h; sourceTree = ""; }; + C24EABAA1421432800C16AA9 /* policydb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = policydb.h; sourceTree = ""; }; + C24EABAC1421433700C16AA9 /* policydb.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = policydb.cpp; sourceTree = ""; }; + C250F6C20B5EF1910076098F /* SecIntegrity.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecIntegrity.h; sourceTree = ""; }; + C250F6C60B5EF5B50076098F /* SecIntegrity.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecIntegrity.cpp; sourceTree = ""; }; + C2578CC215798D0F00D4FE48 /* gkclear */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = gkclear; sourceTree = ""; }; + C2578CC315798D0F00D4FE48 /* gkgenerate */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = gkgenerate; sourceTree = ""; }; + C2578CC415798D0F00D4FE48 /* gkrecord */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = gkrecord; sourceTree = ""; }; + C259DFD40AD6D9BA00C9ACC6 /* sigblob.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = sigblob.cpp; sourceTree = ""; }; + C259DFD50AD6D9BA00C9ACC6 /* sigblob.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sigblob.h; sourceTree = ""; }; + C25C18C615CB0BC10007A2DE /* gkreport */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = gkreport; path = gke/gkreport; sourceTree = SOURCE_ROOT; }; + C25C18CF15CB0FA00007A2DE /* com.apple.gkreport.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.gkreport.plist; path = gke/com.apple.gkreport.plist; sourceTree = SOURCE_ROOT; }; + C26763D514FD9EBE00A46EDF /* drmaker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = drmaker.cpp; sourceTree = ""; }; + C26763D614FD9EBE00A46EDF /* drmaker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = drmaker.h; sourceTree = ""; }; + C26AC0F3143BD1B3001C98CE /* SystemPolicy */ = {isa = PBXFileReference; lastKnownFileType = text; name = SystemPolicy; path = cstemp/SystemPolicy; sourceTree = BUILT_PRODUCTS_DIR; }; + C26AC6FD0DAEB2C4005BFB40 /* security_codesigning.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = security_codesigning.d; sourceTree = ""; }; + C26B45C00B8A9C00003C0ACA /* ucspc */ = {isa = PBXFileReference; lastKnownFileType = text; name = ucspc; path = cstemp/ucspc; sourceTree = BUILT_PRODUCTS_DIR; }; + C27249D2143237CD0058B552 /* syspolicy.sql */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = syspolicy.sql; sourceTree = ""; }; + C273601D1432A60B00A9A5FF /* policyengine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = policyengine.h; sourceTree = ""; }; + C27360201432A61900A9A5FF /* policyengine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = policyengine.cpp; sourceTree = ""; }; + C273606C1433F09000A9A5FF /* SecAssessment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SecAssessment.cpp; sourceTree = ""; }; + C273606D1433F09000A9A5FF /* SecAssessment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = SecAssessment.h; sourceTree = ""; }; + C27360D41436866C00A9A5FF /* xpcengine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = xpcengine.cpp; sourceTree = ""; }; + C27360D71436868600A9A5FF /* xpcengine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xpcengine.h; sourceTree = ""; }; + C278A19B158AB2C300FA6767 /* gkhandmake */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = gkhandmake; sourceTree = ""; }; + C278A19C158AB2C300FA6767 /* gklist */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = gklist; sourceTree = ""; }; + C28342E40E366E6800E54360 /* csdatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = csdatabase.cpp; sourceTree = ""; }; + C28342E50E366E6800E54360 /* csdatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = csdatabase.h; sourceTree = ""; }; + C28342EB0E36719D00E54360 /* detachedrep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = detachedrep.cpp; sourceTree = ""; }; + C28342EC0E36719D00E54360 /* detachedrep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = detachedrep.h; sourceTree = ""; }; + C293E2C21554653700F3E396 /* sp-watch.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; name = "sp-watch.d"; path = "dtrace/sp-watch.d"; sourceTree = SOURCE_ROOT; }; + C2A436130F2133B2007A41A6 /* slcrep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = slcrep.cpp; sourceTree = ""; }; + C2A436140F2133B2007A41A6 /* slcrep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = slcrep.h; sourceTree = ""; }; + C2A976A80B8A2E36008B4EA0 /* csutilities.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = csutilities.cpp; sourceTree = ""; }; + C2A976A90B8A2E36008B4EA0 /* csutilities.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = csutilities.h; sourceTree = ""; }; + C2BC1F260B580D3A003EC9DC /* libintegrity.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libintegrity.a; sourceTree = BUILT_PRODUCTS_DIR; }; + C2BC1F2F0B580D4B003EC9DC /* libcodehost.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libcodehost.a; sourceTree = BUILT_PRODUCTS_DIR; }; + C2BC1F340B580DA7003EC9DC /* SecCodeHostLib.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCodeHostLib.h; sourceTree = ""; }; + C2BD519A0A9392FD000FE43D /* machorep.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = machorep.cpp; sourceTree = ""; }; + C2BD519B0A9392FD000FE43D /* machorep.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = machorep.h; sourceTree = ""; }; + C2BD60F80AC863FC0057FD3D /* csgeneric.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = csgeneric.cpp; sourceTree = ""; }; + C2BD60F90AC863FC0057FD3D /* csgeneric.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = csgeneric.h; sourceTree = ""; }; + C2C1DF8F0A2E4A2700D1B02B /* requirements.grammar */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = requirements.grammar; sourceTree = SOURCE_ROOT; }; + C2C1DFB90A2F80EB00D1B02B /* reqinterp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = reqinterp.cpp; sourceTree = ""; }; + C2C1DFBA0A2F80EB00D1B02B /* reqinterp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = reqinterp.h; sourceTree = ""; }; + C2C1DFC10A2F820500D1B02B /* reqmaker.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = reqmaker.cpp; sourceTree = ""; }; + C2C1DFC20A2F820500D1B02B /* reqmaker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = reqmaker.h; sourceTree = ""; }; + C2C3BCD10BA1E47E00E869D1 /* singlediskrep.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = singlediskrep.cpp; sourceTree = ""; }; + C2C3BCD20BA1E47E00E869D1 /* singlediskrep.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = singlediskrep.h; sourceTree = ""; }; + C2C4F4EE0E0980C700137848 /* codesigning_dtrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = codesigning_dtrace.h; path = cstemp/codesigning_dtrace.h; sourceTree = BUILT_PRODUCTS_DIR; }; + C2C931B30AB8BA1200F83950 /* SecCodeHost.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecCodeHost.cpp; sourceTree = ""; }; + C2CC30A00B8519CC005FA59D /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CoreFoundation.framework; sourceTree = ""; }; + C2CC31040B8523AD005FA59D /* SecIntegrityLib.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecIntegrityLib.h; sourceTree = ""; }; + C2CC310E0B852424005FA59D /* SecIntegrityLib.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SecIntegrityLib.c; sourceTree = ""; }; + C2CC31130B85254F005FA59D /* antlrplugin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = antlrplugin.cpp; path = lib/antlrplugin.cpp; sourceTree = ""; }; + C2CC31140B85254F005FA59D /* antlrplugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = antlrplugin.h; path = lib/antlrplugin.h; sourceTree = ""; }; + C2D383120A237F47005C63A2 /* bundlediskrep.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = bundlediskrep.cpp; sourceTree = ""; }; + C2D383130A237F47005C63A2 /* bundlediskrep.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bundlediskrep.h; sourceTree = ""; }; + C2D383140A237F47005C63A2 /* cdbuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cdbuilder.cpp; sourceTree = ""; }; + C2D383150A237F47005C63A2 /* cdbuilder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cdbuilder.h; sourceTree = ""; }; + C2D383160A237F47005C63A2 /* codedirectory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = codedirectory.cpp; sourceTree = ""; }; + C2D383170A237F47005C63A2 /* codedirectory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = codedirectory.h; sourceTree = ""; }; + C2D383180A237F47005C63A2 /* CodeSigning.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CodeSigning.h; sourceTree = ""; }; + C2D383190A237F47005C63A2 /* SecCodeHost.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCodeHost.h; sourceTree = ""; }; + C2D3831A0A237F47005C63A2 /* cs.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cs.cpp; sourceTree = ""; }; + C2D3831B0A237F47005C63A2 /* cs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cs.h; sourceTree = ""; }; + C2D3831C0A237F47005C63A2 /* CSCommon.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CSCommon.h; sourceTree = ""; }; + C2D3831D0A237F47005C63A2 /* SecCode.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecCode.cpp; sourceTree = ""; }; + C2D3831E0A237F47005C63A2 /* SecCode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCode.h; sourceTree = ""; }; + C2D3831F0A237F47005C63A2 /* cskernel.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cskernel.cpp; sourceTree = ""; }; + C2D383200A237F47005C63A2 /* cskernel.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cskernel.h; sourceTree = ""; }; + C2D383210A237F47005C63A2 /* SecStaticCode.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecStaticCode.cpp; sourceTree = ""; }; + C2D383220A237F47005C63A2 /* SecStaticCode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecStaticCode.h; sourceTree = ""; }; + C2D383230A237F47005C63A2 /* csprocess.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = csprocess.cpp; sourceTree = ""; }; + C2D383240A237F47005C63A2 /* csprocess.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = csprocess.h; sourceTree = ""; }; + C2D383250A237F47005C63A2 /* SecRequirement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecRequirement.cpp; sourceTree = ""; }; + C2D383260A237F47005C63A2 /* SecRequirement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecRequirement.h; sourceTree = ""; }; + C2D383270A237F47005C63A2 /* diskrep.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = diskrep.cpp; sourceTree = ""; }; + C2D383280A237F47005C63A2 /* diskrep.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = diskrep.h; sourceTree = ""; }; + C2D3832B0A237F47005C63A2 /* filediskrep.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = filediskrep.cpp; sourceTree = ""; }; + C2D3832C0A237F47005C63A2 /* filediskrep.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = filediskrep.h; sourceTree = ""; }; + C2D3832D0A237F47005C63A2 /* Code.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Code.cpp; sourceTree = ""; }; + C2D3832E0A237F47005C63A2 /* Code.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Code.h; sourceTree = ""; }; + C2D3832F0A237F47005C63A2 /* kerneldiskrep.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = kerneldiskrep.cpp; sourceTree = ""; }; + C2D383300A237F47005C63A2 /* kerneldiskrep.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = kerneldiskrep.h; sourceTree = ""; }; + C2D383310A237F47005C63A2 /* StaticCode.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = StaticCode.cpp; sourceTree = ""; }; + C2D383320A237F47005C63A2 /* StaticCode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = StaticCode.h; sourceTree = ""; }; + C2D383330A237F47005C63A2 /* reqparser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = reqparser.cpp; sourceTree = ""; }; + C2D383340A237F47005C63A2 /* reqparser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = reqparser.h; sourceTree = ""; }; + C2D383350A237F47005C63A2 /* requirement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = requirement.cpp; sourceTree = ""; }; + C2D383360A237F47005C63A2 /* requirement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = requirement.h; sourceTree = ""; }; + C2D383370A237F47005C63A2 /* Requirements.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Requirements.cpp; sourceTree = ""; }; + C2D383380A237F47005C63A2 /* Requirements.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Requirements.h; sourceTree = ""; }; + C2D383390A237F47005C63A2 /* security_codesigning.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = security_codesigning.exp; sourceTree = ""; }; + C2D50CDF0E155A4F0059A195 /* CSCommonPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSCommonPriv.h; sourceTree = ""; }; + C2E2873C0B5D8D80009336A0 /* SecCodeHostLib.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SecCodeHostLib.c; sourceTree = ""; }; + C2E8AF240DE25CA7000F6D3B /* SecCodePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCodePriv.h; sourceTree = ""; }; + C2E8AF250DE25CA7000F6D3B /* SecRequirementPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecRequirementPriv.h; sourceTree = ""; }; + C2E8AF260DE25CA7000F6D3B /* SecStaticCodePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecStaticCodePriv.h; sourceTree = ""; }; + C2E911E00ADEBE3200275CB2 /* resources.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = resources.cpp; sourceTree = ""; }; + C2E911E10ADEBE3200275CB2 /* resources.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = resources.h; sourceTree = ""; }; + C2F4439814C626D4000A01E6 /* quarantine++.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "quarantine++.cpp"; sourceTree = ""; }; + C2F4439914C626D4000A01E6 /* quarantine++.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "quarantine++.h"; sourceTree = ""; }; + C2F6071B107D575700A83618 /* codesign-watch.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; name = "codesign-watch.d"; path = "dtrace/codesign-watch.d"; sourceTree = SOURCE_ROOT; }; + C2F6566C0BCBFB250078779E /* cserror.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cserror.cpp; sourceTree = ""; }; + C2F6566D0BCBFB250078779E /* cserror.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cserror.h; sourceTree = ""; }; + EB68B10A150DAEBB00B4013D /* RequirementKeywords.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RequirementKeywords.h; sourceTree = ""; }; + EB68B10B150DAEBB00B4013D /* RequirementLexer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RequirementLexer.cpp; sourceTree = ""; }; + EB68B10C150DAEBB00B4013D /* RequirementLexer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = RequirementLexer.hpp; sourceTree = ""; }; + EB68B10D150DAEBB00B4013D /* RequirementParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RequirementParser.cpp; sourceTree = ""; }; + EB68B10E150DAEBB00B4013D /* RequirementParser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = RequirementParser.hpp; sourceTree = ""; }; + EB68B10F150DAEBB00B4013D /* RequirementParserTokenTypes.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = RequirementParserTokenTypes.hpp; sourceTree = ""; }; + EB68B110150DAEBB00B4013D /* RequirementParserTokenTypes.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = RequirementParserTokenTypes.txt; sourceTree = ""; }; + EB976F571684D77500A68EE6 /* ANTLRException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ANTLRException.hpp; sourceTree = ""; }; + EB976F581684D77500A68EE6 /* ANTLRUtil.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ANTLRUtil.hpp; sourceTree = ""; }; + EB976F591684D77500A68EE6 /* AST.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AST.hpp; sourceTree = ""; }; + EB976F5A1684D77500A68EE6 /* ASTArray.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ASTArray.hpp; sourceTree = ""; }; + EB976F5B1684D77500A68EE6 /* ASTFactory.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ASTFactory.hpp; sourceTree = ""; }; + EB976F5C1684D77500A68EE6 /* ASTNULLType.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ASTNULLType.hpp; sourceTree = ""; }; + EB976F5D1684D77500A68EE6 /* ASTPair.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ASTPair.hpp; sourceTree = ""; }; + EB976F5E1684D77500A68EE6 /* ASTRefCount.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ASTRefCount.hpp; sourceTree = ""; }; + EB976F5F1684D77500A68EE6 /* BaseAST.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = BaseAST.hpp; sourceTree = ""; }; + EB976F601684D77500A68EE6 /* BitSet.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = BitSet.hpp; sourceTree = ""; }; + EB976F611684D77500A68EE6 /* CharBuffer.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CharBuffer.hpp; sourceTree = ""; }; + EB976F621684D77500A68EE6 /* CharInputBuffer.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CharInputBuffer.hpp; sourceTree = ""; }; + EB976F631684D77500A68EE6 /* CharScanner.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CharScanner.hpp; sourceTree = ""; }; + EB976F641684D77500A68EE6 /* CharStreamException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CharStreamException.hpp; sourceTree = ""; }; + EB976F651684D77500A68EE6 /* CharStreamIOException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CharStreamIOException.hpp; sourceTree = ""; }; + EB976F661684D77500A68EE6 /* CircularQueue.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CircularQueue.hpp; sourceTree = ""; }; + EB976F671684D77500A68EE6 /* CommonAST.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CommonAST.hpp; sourceTree = ""; }; + EB976F681684D77500A68EE6 /* CommonASTWithHiddenTokens.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CommonASTWithHiddenTokens.hpp; sourceTree = ""; }; + EB976F691684D77500A68EE6 /* CommonHiddenStreamToken.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CommonHiddenStreamToken.hpp; sourceTree = ""; }; + EB976F6A1684D77500A68EE6 /* CommonToken.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CommonToken.hpp; sourceTree = ""; }; + EB976F6B1684D77500A68EE6 /* config.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = config.hpp; sourceTree = ""; }; + EB976F6C1684D77500A68EE6 /* InputBuffer.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = InputBuffer.hpp; sourceTree = ""; }; + EB976F6D1684D77500A68EE6 /* IOException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = IOException.hpp; sourceTree = ""; }; + EB976F6E1684D77500A68EE6 /* LexerSharedInputState.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = LexerSharedInputState.hpp; sourceTree = ""; }; + EB976F6F1684D77500A68EE6 /* LLkParser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = LLkParser.hpp; sourceTree = ""; }; + EB976F701684D77500A68EE6 /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; + EB976F711684D77500A68EE6 /* MismatchedCharException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MismatchedCharException.hpp; sourceTree = ""; }; + EB976F721684D77500A68EE6 /* MismatchedTokenException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MismatchedTokenException.hpp; sourceTree = ""; }; + EB976F731684D77500A68EE6 /* NoViableAltException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = NoViableAltException.hpp; sourceTree = ""; }; + EB976F741684D77500A68EE6 /* NoViableAltForCharException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = NoViableAltForCharException.hpp; sourceTree = ""; }; + EB976F751684D77500A68EE6 /* Parser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Parser.hpp; sourceTree = ""; }; + EB976F761684D77500A68EE6 /* ParserSharedInputState.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ParserSharedInputState.hpp; sourceTree = ""; }; + EB976F771684D77500A68EE6 /* RecognitionException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = RecognitionException.hpp; sourceTree = ""; }; + EB976F781684D77500A68EE6 /* RefCount.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = RefCount.hpp; sourceTree = ""; }; + EB976F791684D77500A68EE6 /* SemanticException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = SemanticException.hpp; sourceTree = ""; }; + EB976F7A1684D77500A68EE6 /* String.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = String.hpp; sourceTree = ""; }; + EB976F7B1684D77500A68EE6 /* Token.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Token.hpp; sourceTree = ""; }; + EB976F7C1684D77500A68EE6 /* TokenBuffer.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenBuffer.hpp; sourceTree = ""; }; + EB976F7D1684D77500A68EE6 /* TokenRefCount.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenRefCount.hpp; sourceTree = ""; }; + EB976F7E1684D77500A68EE6 /* TokenStream.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenStream.hpp; sourceTree = ""; }; + EB976F7F1684D77500A68EE6 /* TokenStreamBasicFilter.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenStreamBasicFilter.hpp; sourceTree = ""; }; + EB976F801684D77500A68EE6 /* TokenStreamException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenStreamException.hpp; sourceTree = ""; }; + EB976F811684D77500A68EE6 /* TokenStreamHiddenTokenFilter.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenStreamHiddenTokenFilter.hpp; sourceTree = ""; }; + EB976F821684D77500A68EE6 /* TokenStreamIOException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenStreamIOException.hpp; sourceTree = ""; }; + EB976F831684D77500A68EE6 /* TokenStreamRecognitionException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenStreamRecognitionException.hpp; sourceTree = ""; }; + EB976F841684D77500A68EE6 /* TokenStreamRetryException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenStreamRetryException.hpp; sourceTree = ""; }; + EB976F851684D77500A68EE6 /* TokenStreamRewriteEngine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenStreamRewriteEngine.hpp; sourceTree = ""; }; + EB976F861684D77500A68EE6 /* TokenStreamSelector.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenStreamSelector.hpp; sourceTree = ""; }; + EB976F871684D77500A68EE6 /* TokenWithIndex.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenWithIndex.hpp; sourceTree = ""; }; + EB976F881684D77500A68EE6 /* TreeParser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TreeParser.hpp; sourceTree = ""; }; + EB976F891684D77500A68EE6 /* TreeParserSharedInputState.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TreeParserSharedInputState.hpp; sourceTree = ""; }; + EB976F8A1684D77500A68EE6 /* AUTHORS */ = {isa = PBXFileReference; lastKnownFileType = text; name = AUTHORS; path = antlr2/AUTHORS; sourceTree = ""; }; + EB976F8B1684D77500A68EE6 /* ChangeLog */ = {isa = PBXFileReference; lastKnownFileType = text; name = ChangeLog; path = antlr2/ChangeLog; sourceTree = ""; }; + EB976F8E1684D77500A68EE6 /* antlr.bpr */ = {isa = PBXFileReference; lastKnownFileType = text; path = antlr.bpr; sourceTree = ""; }; + EB976F8F1684D77500A68EE6 /* antlr.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = antlr.cpp; sourceTree = ""; }; + EB976F901684D77500A68EE6 /* README */ = {isa = PBXFileReference; lastKnownFileType = text; path = README; sourceTree = ""; }; + EB976F911684D77500A68EE6 /* doxygen.cfg */ = {isa = PBXFileReference; lastKnownFileType = text; name = doxygen.cfg; path = antlr2/doxygen.cfg; sourceTree = ""; }; + EB976F921684D77500A68EE6 /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; name = Makefile.in; path = antlr2/Makefile.in; sourceTree = ""; }; + EB976F931684D77500A68EE6 /* README */ = {isa = PBXFileReference; lastKnownFileType = text; name = README; path = antlr2/README; sourceTree = ""; }; + EB976F951684D77500A68EE6 /* cr_stripper.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = cr_stripper.sh; sourceTree = ""; }; + EB976F961684D77500A68EE6 /* make_change_log.tcl */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = make_change_log.tcl; sourceTree = ""; }; + EB976F981684D77600A68EE6 /* ANTLRUtil.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ANTLRUtil.cpp; sourceTree = ""; }; + EB976F991684D77600A68EE6 /* ASTFactory.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ASTFactory.cpp; sourceTree = ""; }; + EB976F9A1684D77600A68EE6 /* ASTNULLType.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ASTNULLType.cpp; sourceTree = ""; }; + EB976F9B1684D77600A68EE6 /* ASTRefCount.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ASTRefCount.cpp; sourceTree = ""; }; + EB976F9C1684D77600A68EE6 /* BaseAST.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = BaseAST.cpp; sourceTree = ""; }; + EB976F9D1684D77600A68EE6 /* BitSet.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = BitSet.cpp; sourceTree = ""; }; + EB976F9E1684D77600A68EE6 /* CharBuffer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CharBuffer.cpp; sourceTree = ""; }; + EB976F9F1684D77600A68EE6 /* CharScanner.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CharScanner.cpp; sourceTree = ""; }; + EB976FA01684D77600A68EE6 /* CommonAST.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CommonAST.cpp; sourceTree = ""; }; + EB976FA11684D77600A68EE6 /* CommonASTWithHiddenTokens.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CommonASTWithHiddenTokens.cpp; sourceTree = ""; }; + EB976FA21684D77600A68EE6 /* CommonHiddenStreamToken.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CommonHiddenStreamToken.cpp; sourceTree = ""; }; + EB976FA31684D77600A68EE6 /* CommonToken.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CommonToken.cpp; sourceTree = ""; }; + EB976FA41684D77600A68EE6 /* dll.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = dll.cpp; sourceTree = ""; }; + EB976FA51684D77600A68EE6 /* InputBuffer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InputBuffer.cpp; sourceTree = ""; }; + EB976FA61684D77600A68EE6 /* LLkParser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LLkParser.cpp; sourceTree = ""; }; + EB976FA71684D77600A68EE6 /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; + EB976FA81684D77600A68EE6 /* MismatchedCharException.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MismatchedCharException.cpp; sourceTree = ""; }; + EB976FA91684D77600A68EE6 /* MismatchedTokenException.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MismatchedTokenException.cpp; sourceTree = ""; }; + EB976FAA1684D77600A68EE6 /* NoViableAltException.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = NoViableAltException.cpp; sourceTree = ""; }; + EB976FAB1684D77600A68EE6 /* NoViableAltForCharException.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = NoViableAltForCharException.cpp; sourceTree = ""; }; + EB976FAC1684D77600A68EE6 /* Parser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Parser.cpp; sourceTree = ""; }; + EB976FAD1684D77600A68EE6 /* RecognitionException.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RecognitionException.cpp; sourceTree = ""; }; + EB976FAE1684D77600A68EE6 /* String.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = String.cpp; sourceTree = ""; }; + EB976FAF1684D77600A68EE6 /* Token.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Token.cpp; sourceTree = ""; }; + EB976FB01684D77600A68EE6 /* TokenBuffer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TokenBuffer.cpp; sourceTree = ""; }; + EB976FB11684D77600A68EE6 /* TokenRefCount.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TokenRefCount.cpp; sourceTree = ""; }; + EB976FB21684D77600A68EE6 /* TokenStreamBasicFilter.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TokenStreamBasicFilter.cpp; sourceTree = ""; }; + EB976FB31684D77600A68EE6 /* TokenStreamHiddenTokenFilter.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TokenStreamHiddenTokenFilter.cpp; sourceTree = ""; }; + EB976FB41684D77600A68EE6 /* TokenStreamRewriteEngine.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TokenStreamRewriteEngine.cpp; sourceTree = ""; }; + EB976FB51684D77600A68EE6 /* TokenStreamSelector.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TokenStreamSelector.cpp; sourceTree = ""; }; + EB976FB61684D77600A68EE6 /* TreeParser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TreeParser.cpp; sourceTree = ""; }; + EB976FB71684D77600A68EE6 /* TODO */ = {isa = PBXFileReference; lastKnownFileType = text; name = TODO; path = antlr2/TODO; sourceTree = ""; }; + EBB9FF6F1682E51300FF9774 /* com.apple.CodeSigningHelper.xpc */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = com.apple.CodeSigningHelper.xpc; sourceTree = BUILT_PRODUCTS_DIR; }; + EBB9FF701682E51300FF9774 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + EBB9FF741682E51300FF9774 /* CodeSigningHelper-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "CodeSigningHelper-Info.plist"; sourceTree = ""; }; + EBB9FF791682E51300FF9774 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + EBB9FF7E1682E5A200FF9774 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; }; + EBB9FF801682E65700FF9774 /* com.apple.CodeSigningHelper.sb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = com.apple.CodeSigningHelper.sb; sourceTree = ""; }; + EBDAF04D166D65FA0042CDCE /* piddiskrep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = piddiskrep.cpp; sourceTree = ""; }; + EBDAF04E166D65FA0042CDCE /* piddiskrep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = piddiskrep.h; sourceTree = ""; }; + EBF9A1551684E0F300BCECA6 /* libsecurity_codesigning.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = libsecurity_codesigning.plist; path = antlr2/libsecurity_codesigning.plist; sourceTree = ""; }; + EBF9A1561684E0F300BCECA6 /* libsecurity_codesigning.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = libsecurity_codesigning.txt; path = antlr2/libsecurity_codesigning.txt; sourceTree = ""; }; + EBF9A1571684E0F300BCECA6 /* LICENSE.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = LICENSE.txt; path = antlr2/LICENSE.txt; sourceTree = ""; }; + FEB30C9210DAC89D00557BA2 /* SecTask.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecTask.c; sourceTree = ""; }; + FEB30C9410DAC8A500557BA2 /* SecTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTask.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7AADF57A19C0CE8C00292339 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7A4FAF1B19C215DF00D297CB /* CrashReporterSupport.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C209695D15BF52040093035F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C200424D15D425D9004AE0A1 /* libsecurity_codesigning.a in Frameworks */, + C200424E15D425D9004AE0A1 /* libsecurity_utilities.a in Frameworks */, + 7ACF261219958B6F00849B25 /* CoreFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C2BC1F240B580D3A003EC9DC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C2BC1F2D0B580D4B003EC9DC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C26B45C10B8A9C0A003C0ACA /* ucspc in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EBB9FF6C1682E51300FF9774 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + EBB9FF7F1682E5A200FF9774 /* CoreFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 182BB4FD146F2823000BF1F3 /* Products */ = { + isa = PBXGroup; + children = ( + 182BB505146F2823000BF1F3 /* libsecurityd_client.a */, + 182BB507146F2823000BF1F3 /* libsecurityd_server.a */, + 182BB509146F2823000BF1F3 /* ucspc.a */, + ); + name = Products; + sourceTree = ""; + }; + 1844619E146E9AD100B12992 /* config */ = { + isa = PBXGroup; + children = ( + 1844619F146E9AD100B12992 /* base.xcconfig */, + 184461A0146E9AD100B12992 /* debug.xcconfig */, + 184461A1146E9AD100B12992 /* lib.xcconfig */, + 184461A2146E9AD100B12992 /* release.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 4C308388053237100028A8C6 /* lib */ = { + isa = PBXGroup; + children = ( + C2C1DF5F0A2E457E00D1B02B /* API */, + C2C1DF600A2E458D00D1B02B /* API Objects */, + C216C72D0AD59B22003B07D4 /* Signing Operations */, + C2C1DF630A2E45BF00D1B02B /* Code Directory */, + C2C1DF620A2E45B600D1B02B /* Requirements */, + C2C1DF640A2E45F500D1B02B /* Code Classes */, + C2C1DF610A2E459E00D1B02B /* Disk Representations */, + C2BC1F370B580DAE003EC9DC /* Static Support */, + C26AC6FF0DAEB2D0005BFB40 /* DTrace */, + C293E2B915543F0800F3E396 /* gke */, + C2CCF0360A3F524B0085795A /* Local Utilities */, + C2CC31160B852554005FA59D /* Security Plugins */, + FEB30C9110DAC6C400557BA2 /* Entitlements */, + C24EABA914213FAF00C16AA9 /* System Policy */, + ); + path = lib; + sourceTree = ""; + }; + 4CA1FEA7052A3C3800F22E42 = { + isa = PBXGroup; + children = ( + EBB9FF7E1682E5A200FF9774 /* CoreFoundation.framework */, + C209697215BF57EB0093035F /* libsecurity_utilities.a */, + 182BB4FC146F2823000BF1F3 /* libsecurityd.xcodeproj */, + 4C308388053237100028A8C6 /* lib */, + 1844619E146E9AD100B12992 /* config */, + C2D383F90A23A9D9005C63A2 /* cstemp */, + EB976F511684D73900A68EE6 /* antlr2 */, + EBB9FF721682E51300FF9774 /* CodeSigningHelper */, + C2CC30EF0B8519CF005FA59D /* Frameworks */, + 4CA1FEBF052A3C8100F22E42 /* Products */, + ); + sourceTree = ""; + }; + 4CA1FEBF052A3C8100F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + 4CA1FEBE052A3C8100F22E42 /* libsecurity_codesigning.a */, + C2BC1F260B580D3A003EC9DC /* libintegrity.a */, + C2BC1F2F0B580D4B003EC9DC /* libcodehost.a */, + C209696015BF52040093035F /* gkunpack */, + EBB9FF6F1682E51300FF9774 /* com.apple.CodeSigningHelper.xpc */, + 7AADF57D19C0CE8C00292339 /* gkoverride */, + ); + name = Products; + sourceTree = ""; + }; + C216C72D0AD59B22003B07D4 /* Signing Operations */ = { + isa = PBXGroup; + children = ( + C236E3D60AD59446000F5140 /* signer.h */, + C236E3D50AD59446000F5140 /* signer.cpp */, + C236E3DA0AD595C2000F5140 /* signerutils.h */, + C236E3D90AD595C2000F5140 /* signerutils.cpp */, + ); + name = "Signing Operations"; + sourceTree = ""; + }; + C24EABA914213FAF00C16AA9 /* System Policy */ = { + isa = PBXGroup; + children = ( + C273606D1433F09000A9A5FF /* SecAssessment.h */, + C273606C1433F09000A9A5FF /* SecAssessment.cpp */, + 7A9DA65B1948D1BA004635E6 /* opaquewhitelist.h */, + 7A9DA65A1948D1BA004635E6 /* opaquewhitelist.cpp */, + C24EABAA1421432800C16AA9 /* policydb.h */, + C24EABAC1421433700C16AA9 /* policydb.cpp */, + C273601D1432A60B00A9A5FF /* policyengine.h */, + C27360201432A61900A9A5FF /* policyengine.cpp */, + C27360D71436868600A9A5FF /* xpcengine.h */, + C27360D41436866C00A9A5FF /* xpcengine.cpp */, + C27249D2143237CD0058B552 /* syspolicy.sql */, + 7AADF58819C0CED800292339 /* gkoverride.m */, + ); + name = "System Policy"; + sourceTree = ""; + }; + C26AC6FF0DAEB2D0005BFB40 /* DTrace */ = { + isa = PBXGroup; + children = ( + C293E2C21554653700F3E396 /* sp-watch.d */, + C26AC6FD0DAEB2C4005BFB40 /* security_codesigning.d */, + C2F6071B107D575700A83618 /* codesign-watch.d */, + ); + name = DTrace; + sourceTree = ""; + }; + C293E2B915543F0800F3E396 /* gke */ = { + isa = PBXGroup; + children = ( + C2110704158BF5C8001D7F76 /* gkmerge */, + C278A19B158AB2C300FA6767 /* gkhandmake */, + C278A19C158AB2C300FA6767 /* gklist */, + C2578CC215798D0F00D4FE48 /* gkclear */, + C2578CC315798D0F00D4FE48 /* gkgenerate */, + C2578CC415798D0F00D4FE48 /* gkrecord */, + C25C18C615CB0BC10007A2DE /* gkreport */, + C25C18CF15CB0FA00007A2DE /* com.apple.gkreport.plist */, + C209696315BF52040093035F /* gkunpack.cpp */, + ); + path = gke; + sourceTree = SOURCE_ROOT; + }; + C2BC1F370B580DAE003EC9DC /* Static Support */ = { + isa = PBXGroup; + children = ( + C2CC31040B8523AD005FA59D /* SecIntegrityLib.h */, + C2CC310E0B852424005FA59D /* SecIntegrityLib.c */, + C2BC1F340B580DA7003EC9DC /* SecCodeHostLib.h */, + C2E2873C0B5D8D80009336A0 /* SecCodeHostLib.c */, + ); + name = "Static Support"; + sourceTree = ""; + }; + C2C1DF5F0A2E457E00D1B02B /* API */ = { + isa = PBXGroup; + children = ( + C2D383180A237F47005C63A2 /* CodeSigning.h */, + C2D3831C0A237F47005C63A2 /* CSCommon.h */, + C2D50CDF0E155A4F0059A195 /* CSCommonPriv.h */, + C2D3831E0A237F47005C63A2 /* SecCode.h */, + C2E8AF240DE25CA7000F6D3B /* SecCodePriv.h */, + C2D3831D0A237F47005C63A2 /* SecCode.cpp */, + C2D383220A237F47005C63A2 /* SecStaticCode.h */, + C2E8AF260DE25CA7000F6D3B /* SecStaticCodePriv.h */, + C2D383210A237F47005C63A2 /* SecStaticCode.cpp */, + C2D383260A237F47005C63A2 /* SecRequirement.h */, + C2E8AF250DE25CA7000F6D3B /* SecRequirementPriv.h */, + C2D383250A237F47005C63A2 /* SecRequirement.cpp */, + C21EA3DC0AD2F81300E6E31C /* SecCodeSigner.h */, + C21EA3DB0AD2F81300E6E31C /* SecCodeSigner.cpp */, + C2D383190A237F47005C63A2 /* SecCodeHost.h */, + C2C931B30AB8BA1200F83950 /* SecCodeHost.cpp */, + C250F6C20B5EF1910076098F /* SecIntegrity.h */, + C250F6C60B5EF5B50076098F /* SecIntegrity.cpp */, + C2D383390A237F47005C63A2 /* security_codesigning.exp */, + ); + name = API; + sourceTree = ""; + }; + C2C1DF600A2E458D00D1B02B /* API Objects */ = { + isa = PBXGroup; + children = ( + C2D3831B0A237F47005C63A2 /* cs.h */, + C2D3831A0A237F47005C63A2 /* cs.cpp */, + C2D3832E0A237F47005C63A2 /* Code.h */, + C2D3832D0A237F47005C63A2 /* Code.cpp */, + C2D383320A237F47005C63A2 /* StaticCode.h */, + C2D383310A237F47005C63A2 /* StaticCode.cpp */, + C2D383380A237F47005C63A2 /* Requirements.h */, + C2D383370A237F47005C63A2 /* Requirements.cpp */, + C21EA3E20AD2FA0900E6E31C /* CodeSigner.h */, + C21EA3E10AD2FA0900E6E31C /* CodeSigner.cpp */, + ); + name = "API Objects"; + sourceTree = ""; + }; + C2C1DF610A2E459E00D1B02B /* Disk Representations */ = { + isa = PBXGroup; + children = ( + C2D383280A237F47005C63A2 /* diskrep.h */, + C2D383270A237F47005C63A2 /* diskrep.cpp */, + C2D3832C0A237F47005C63A2 /* filediskrep.h */, + C2D3832B0A237F47005C63A2 /* filediskrep.cpp */, + C2D383130A237F47005C63A2 /* bundlediskrep.h */, + C2D383120A237F47005C63A2 /* bundlediskrep.cpp */, + C2D383300A237F47005C63A2 /* kerneldiskrep.h */, + C2D3832F0A237F47005C63A2 /* kerneldiskrep.cpp */, + C2BD519B0A9392FD000FE43D /* machorep.h */, + C2BD519A0A9392FD000FE43D /* machorep.cpp */, + C2A436140F2133B2007A41A6 /* slcrep.h */, + C2A436130F2133B2007A41A6 /* slcrep.cpp */, + C2C3BCD20BA1E47E00E869D1 /* singlediskrep.h */, + C2C3BCD10BA1E47E00E869D1 /* singlediskrep.cpp */, + C28342EC0E36719D00E54360 /* detachedrep.h */, + C28342EB0E36719D00E54360 /* detachedrep.cpp */, + EBDAF04D166D65FA0042CDCE /* piddiskrep.cpp */, + EBDAF04E166D65FA0042CDCE /* piddiskrep.h */, + ); + name = "Disk Representations"; + sourceTree = ""; + }; + C2C1DF620A2E45B600D1B02B /* Requirements */ = { + isa = PBXGroup; + children = ( + C2C1DF8F0A2E4A2700D1B02B /* requirements.grammar */, + EB68B10A150DAEBB00B4013D /* RequirementKeywords.h */, + EB68B10B150DAEBB00B4013D /* RequirementLexer.cpp */, + EB68B10C150DAEBB00B4013D /* RequirementLexer.hpp */, + EB68B10D150DAEBB00B4013D /* RequirementParser.cpp */, + EB68B10E150DAEBB00B4013D /* RequirementParser.hpp */, + EB68B10F150DAEBB00B4013D /* RequirementParserTokenTypes.hpp */, + EB68B110150DAEBB00B4013D /* RequirementParserTokenTypes.txt */, + C2D383360A237F47005C63A2 /* requirement.h */, + C2D383350A237F47005C63A2 /* requirement.cpp */, + C2C1DFC20A2F820500D1B02B /* reqmaker.h */, + C2C1DFC10A2F820500D1B02B /* reqmaker.cpp */, + C2093AA70BB0948000EB8599 /* reqreader.h */, + C2093AA60BB0948000EB8599 /* reqreader.cpp */, + C2C1DFBA0A2F80EB00D1B02B /* reqinterp.h */, + C2C1DFB90A2F80EB00D1B02B /* reqinterp.cpp */, + C2D383340A237F47005C63A2 /* reqparser.h */, + C2D383330A237F47005C63A2 /* reqparser.cpp */, + C21CFC5E0A250D1C006CD5B1 /* reqdumper.h */, + C21CFC5D0A250D1C006CD5B1 /* reqdumper.cpp */, + C26763D614FD9EBE00A46EDF /* drmaker.h */, + C26763D514FD9EBE00A46EDF /* drmaker.cpp */, + ); + name = Requirements; + sourceTree = ""; + }; + C2C1DF630A2E45BF00D1B02B /* Code Directory */ = { + isa = PBXGroup; + children = ( + C2D383170A237F47005C63A2 /* codedirectory.h */, + C2D383160A237F47005C63A2 /* codedirectory.cpp */, + C2D383150A237F47005C63A2 /* cdbuilder.h */, + C2D383140A237F47005C63A2 /* cdbuilder.cpp */, + ); + name = "Code Directory"; + sourceTree = ""; + }; + C2C1DF640A2E45F500D1B02B /* Code Classes */ = { + isa = PBXGroup; + children = ( + C2D383200A237F47005C63A2 /* cskernel.h */, + C2D3831F0A237F47005C63A2 /* cskernel.cpp */, + C2D383240A237F47005C63A2 /* csprocess.h */, + C2D383230A237F47005C63A2 /* csprocess.cpp */, + C2BD60F90AC863FC0057FD3D /* csgeneric.h */, + C2BD60F80AC863FC0057FD3D /* csgeneric.cpp */, + ); + name = "Code Classes"; + sourceTree = ""; + }; + C2CC30EF0B8519CF005FA59D /* Frameworks */ = { + isa = PBXGroup; + children = ( + C200424915D425B7004AE0A1 /* libsecurity_codesigning.a */, + C200424A15D425B7004AE0A1 /* libsecurity_utilities.a */, + C2CC30A00B8519CC005FA59D /* CoreFoundation.framework */, + EBB9FF701682E51300FF9774 /* Foundation.framework */, + 7A4FAF1A19C215DF00D297CB /* CrashReporterSupport.framework */, + ); + name = Frameworks; + path = /System/Library/Frameworks; + sourceTree = ""; + }; + C2CC31160B852554005FA59D /* Security Plugins */ = { + isa = PBXGroup; + children = ( + C2CC31140B85254F005FA59D /* antlrplugin.h */, + C2CC31130B85254F005FA59D /* antlrplugin.cpp */, + ); + name = "Security Plugins"; + path = ..; + sourceTree = ""; + }; + C2CCF0360A3F524B0085795A /* Local Utilities */ = { + isa = PBXGroup; + children = ( + C28342E50E366E6800E54360 /* csdatabase.h */, + C28342E40E366E6800E54360 /* csdatabase.cpp */, + C2F6566D0BCBFB250078779E /* cserror.h */, + C2F6566C0BCBFB250078779E /* cserror.cpp */, + C2E911E10ADEBE3200275CB2 /* resources.h */, + C2E911E00ADEBE3200275CB2 /* resources.cpp */, + C259DFD50AD6D9BA00C9ACC6 /* sigblob.h */, + C259DFD40AD6D9BA00C9ACC6 /* sigblob.cpp */, + C2A976A90B8A2E36008B4EA0 /* csutilities.h */, + C2A976A80B8A2E36008B4EA0 /* csutilities.cpp */, + C235340E145F1B050073F964 /* xar++.h */, + C2353410145F1B110073F964 /* xar++.cpp */, + C2F4439914C626D4000A01E6 /* quarantine++.h */, + C2F4439814C626D4000A01E6 /* quarantine++.cpp */, + 37DDE33B1947A4F3005CE18B /* dirscanner.h */, + 37DDE3411947A501005CE18B /* dirscanner.cpp */, + ); + name = "Local Utilities"; + sourceTree = ""; + }; + C2D383F90A23A9D9005C63A2 /* cstemp */ = { + isa = PBXGroup; + children = ( + C2C4F4EE0E0980C700137848 /* codesigning_dtrace.h */, + C26AC0F3143BD1B3001C98CE /* SystemPolicy */, + C26B45C00B8A9C00003C0ACA /* ucspc */, + ); + path = cstemp; + sourceTree = BUILT_PRODUCTS_DIR; + }; + EB976F511684D73900A68EE6 /* antlr2 */ = { + isa = PBXGroup; + children = ( + EB976F561684D77500A68EE6 /* antlr */, + EB976F8A1684D77500A68EE6 /* AUTHORS */, + EB976F8B1684D77500A68EE6 /* ChangeLog */, + EB976F8C1684D77500A68EE6 /* contrib */, + EB976F911684D77500A68EE6 /* doxygen.cfg */, + EBF9A1551684E0F300BCECA6 /* libsecurity_codesigning.plist */, + EBF9A1561684E0F300BCECA6 /* libsecurity_codesigning.txt */, + EBF9A1571684E0F300BCECA6 /* LICENSE.txt */, + EB976F921684D77500A68EE6 /* Makefile.in */, + EB976F931684D77500A68EE6 /* README */, + EB976F941684D77500A68EE6 /* scripts */, + EB976F971684D77600A68EE6 /* src */, + EB976FB71684D77600A68EE6 /* TODO */, + ); + name = antlr2; + sourceTree = ""; + }; + EB976F561684D77500A68EE6 /* antlr */ = { + isa = PBXGroup; + children = ( + EB976F571684D77500A68EE6 /* ANTLRException.hpp */, + EB976F581684D77500A68EE6 /* ANTLRUtil.hpp */, + EB976F591684D77500A68EE6 /* AST.hpp */, + EB976F5A1684D77500A68EE6 /* ASTArray.hpp */, + EB976F5B1684D77500A68EE6 /* ASTFactory.hpp */, + EB976F5C1684D77500A68EE6 /* ASTNULLType.hpp */, + EB976F5D1684D77500A68EE6 /* ASTPair.hpp */, + EB976F5E1684D77500A68EE6 /* ASTRefCount.hpp */, + EB976F5F1684D77500A68EE6 /* BaseAST.hpp */, + EB976F601684D77500A68EE6 /* BitSet.hpp */, + EB976F611684D77500A68EE6 /* CharBuffer.hpp */, + EB976F621684D77500A68EE6 /* CharInputBuffer.hpp */, + EB976F631684D77500A68EE6 /* CharScanner.hpp */, + EB976F641684D77500A68EE6 /* CharStreamException.hpp */, + EB976F651684D77500A68EE6 /* CharStreamIOException.hpp */, + EB976F661684D77500A68EE6 /* CircularQueue.hpp */, + EB976F671684D77500A68EE6 /* CommonAST.hpp */, + EB976F681684D77500A68EE6 /* CommonASTWithHiddenTokens.hpp */, + EB976F691684D77500A68EE6 /* CommonHiddenStreamToken.hpp */, + EB976F6A1684D77500A68EE6 /* CommonToken.hpp */, + EB976F6B1684D77500A68EE6 /* config.hpp */, + EB976F6C1684D77500A68EE6 /* InputBuffer.hpp */, + EB976F6D1684D77500A68EE6 /* IOException.hpp */, + EB976F6E1684D77500A68EE6 /* LexerSharedInputState.hpp */, + EB976F6F1684D77500A68EE6 /* LLkParser.hpp */, + EB976F701684D77500A68EE6 /* Makefile.in */, + EB976F711684D77500A68EE6 /* MismatchedCharException.hpp */, + EB976F721684D77500A68EE6 /* MismatchedTokenException.hpp */, + EB976F731684D77500A68EE6 /* NoViableAltException.hpp */, + EB976F741684D77500A68EE6 /* NoViableAltForCharException.hpp */, + EB976F751684D77500A68EE6 /* Parser.hpp */, + EB976F761684D77500A68EE6 /* ParserSharedInputState.hpp */, + EB976F771684D77500A68EE6 /* RecognitionException.hpp */, + EB976F781684D77500A68EE6 /* RefCount.hpp */, + EB976F791684D77500A68EE6 /* SemanticException.hpp */, + EB976F7A1684D77500A68EE6 /* String.hpp */, + EB976F7B1684D77500A68EE6 /* Token.hpp */, + EB976F7C1684D77500A68EE6 /* TokenBuffer.hpp */, + EB976F7D1684D77500A68EE6 /* TokenRefCount.hpp */, + EB976F7E1684D77500A68EE6 /* TokenStream.hpp */, + EB976F7F1684D77500A68EE6 /* TokenStreamBasicFilter.hpp */, + EB976F801684D77500A68EE6 /* TokenStreamException.hpp */, + EB976F811684D77500A68EE6 /* TokenStreamHiddenTokenFilter.hpp */, + EB976F821684D77500A68EE6 /* TokenStreamIOException.hpp */, + EB976F831684D77500A68EE6 /* TokenStreamRecognitionException.hpp */, + EB976F841684D77500A68EE6 /* TokenStreamRetryException.hpp */, + EB976F851684D77500A68EE6 /* TokenStreamRewriteEngine.hpp */, + EB976F861684D77500A68EE6 /* TokenStreamSelector.hpp */, + EB976F871684D77500A68EE6 /* TokenWithIndex.hpp */, + EB976F881684D77500A68EE6 /* TreeParser.hpp */, + EB976F891684D77500A68EE6 /* TreeParserSharedInputState.hpp */, + ); + name = antlr; + path = antlr2/antlr; + sourceTree = ""; + }; + EB976F8C1684D77500A68EE6 /* contrib */ = { + isa = PBXGroup; + children = ( + EB976F8D1684D77500A68EE6 /* bcb4 */, + ); + name = contrib; + path = antlr2/contrib; + sourceTree = ""; + }; + EB976F8D1684D77500A68EE6 /* bcb4 */ = { + isa = PBXGroup; + children = ( + EB976F8E1684D77500A68EE6 /* antlr.bpr */, + EB976F8F1684D77500A68EE6 /* antlr.cpp */, + EB976F901684D77500A68EE6 /* README */, + ); + path = bcb4; + sourceTree = ""; + }; + EB976F941684D77500A68EE6 /* scripts */ = { + isa = PBXGroup; + children = ( + EB976F951684D77500A68EE6 /* cr_stripper.sh */, + EB976F961684D77500A68EE6 /* make_change_log.tcl */, + ); + name = scripts; + path = antlr2/scripts; + sourceTree = ""; + }; + EB976F971684D77600A68EE6 /* src */ = { + isa = PBXGroup; + children = ( + EB976F981684D77600A68EE6 /* ANTLRUtil.cpp */, + EB976F991684D77600A68EE6 /* ASTFactory.cpp */, + EB976F9A1684D77600A68EE6 /* ASTNULLType.cpp */, + EB976F9B1684D77600A68EE6 /* ASTRefCount.cpp */, + EB976F9C1684D77600A68EE6 /* BaseAST.cpp */, + EB976F9D1684D77600A68EE6 /* BitSet.cpp */, + EB976F9E1684D77600A68EE6 /* CharBuffer.cpp */, + EB976F9F1684D77600A68EE6 /* CharScanner.cpp */, + EB976FA01684D77600A68EE6 /* CommonAST.cpp */, + EB976FA11684D77600A68EE6 /* CommonASTWithHiddenTokens.cpp */, + EB976FA21684D77600A68EE6 /* CommonHiddenStreamToken.cpp */, + EB976FA31684D77600A68EE6 /* CommonToken.cpp */, + EB976FA41684D77600A68EE6 /* dll.cpp */, + EB976FA51684D77600A68EE6 /* InputBuffer.cpp */, + EB976FA61684D77600A68EE6 /* LLkParser.cpp */, + EB976FA71684D77600A68EE6 /* Makefile.in */, + EB976FA81684D77600A68EE6 /* MismatchedCharException.cpp */, + EB976FA91684D77600A68EE6 /* MismatchedTokenException.cpp */, + EB976FAA1684D77600A68EE6 /* NoViableAltException.cpp */, + EB976FAB1684D77600A68EE6 /* NoViableAltForCharException.cpp */, + EB976FAC1684D77600A68EE6 /* Parser.cpp */, + EB976FAD1684D77600A68EE6 /* RecognitionException.cpp */, + EB976FAE1684D77600A68EE6 /* String.cpp */, + EB976FAF1684D77600A68EE6 /* Token.cpp */, + EB976FB01684D77600A68EE6 /* TokenBuffer.cpp */, + EB976FB11684D77600A68EE6 /* TokenRefCount.cpp */, + EB976FB21684D77600A68EE6 /* TokenStreamBasicFilter.cpp */, + EB976FB31684D77600A68EE6 /* TokenStreamHiddenTokenFilter.cpp */, + EB976FB41684D77600A68EE6 /* TokenStreamRewriteEngine.cpp */, + EB976FB51684D77600A68EE6 /* TokenStreamSelector.cpp */, + EB976FB61684D77600A68EE6 /* TreeParser.cpp */, + ); + name = src; + path = antlr2/src; + sourceTree = ""; + }; + EBB9FF721682E51300FF9774 /* CodeSigningHelper */ = { + isa = PBXGroup; + children = ( + EBB9FF791682E51300FF9774 /* main.c */, + EBB9FF801682E65700FF9774 /* com.apple.CodeSigningHelper.sb */, + EBB9FF731682E51300FF9774 /* Supporting Files */, + ); + path = CodeSigningHelper; + sourceTree = ""; + }; + EBB9FF731682E51300FF9774 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + EBB9FF741682E51300FF9774 /* CodeSigningHelper-Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + FEB30C9110DAC6C400557BA2 /* Entitlements */ = { + isa = PBXGroup; + children = ( + FEB30C9410DAC8A500557BA2 /* SecTask.h */, + BEC3A75B16F78D21003E5634 /* SecTaskPriv.h */, + FEB30C9210DAC89D00557BA2 /* SecTask.c */, + ); + name = Entitlements; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4CA1FEB9052A3C8100F22E42 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 18B965861472FBF6005A4D2E /* reqdumper.h in Headers */, + 18B965871472FC5B005A4D2E /* requirement.h in Headers */, + 18B965881472FC5B005A4D2E /* reqmaker.h in Headers */, + 7A9DA65D1948D1BA004635E6 /* opaquewhitelist.h in Headers */, + 18B965891472FC5B005A4D2E /* reqreader.h in Headers */, + 18B9658A1472FC5B005A4D2E /* reqinterp.h in Headers */, + 18B9658B1472FC5B005A4D2E /* reqparser.h in Headers */, + 18B9658C1472FC9E005A4D2E /* codedirectory.h in Headers */, + 18B965951472FE30005A4D2E /* cdbuilder.h in Headers */, + EB68B133150DB04400B4013D /* RequirementKeywords.h in Headers */, + BEC3A75C16F78D21003E5634 /* SecTaskPriv.h in Headers */, + EB68B134150DB04400B4013D /* RequirementLexer.hpp in Headers */, + EB68B135150DB04400B4013D /* RequirementParser.hpp in Headers */, + FEB30CA410DAC97400557BA2 /* SecTask.h in Headers */, + 37DDE33C1947A4F3005CE18B /* dirscanner.h in Headers */, + C26FF6310E5B376B00F640A0 /* CSCommonPriv.h in Headers */, + C26FF6330E5B376B00F640A0 /* SecCodePriv.h in Headers */, + C26FF6350E5B376B00F640A0 /* SecStaticCodePriv.h in Headers */, + C26FF6370E5B376B00F640A0 /* SecRequirementPriv.h in Headers */, + C26FF6380E5B376B00F640A0 /* SecCodeSigner.h in Headers */, + C26FF63A0E5B376B00F640A0 /* SecIntegrity.h in Headers */, + C26FF62D0E5B375A00F640A0 /* SecIntegrityLib.h in Headers */, + C26FF62E0E5B375A00F640A0 /* SecCodeHostLib.h in Headers */, + C273606F1433F09000A9A5FF /* SecAssessment.h in Headers */, + C26FF62F0E5B376B00F640A0 /* CodeSigning.h in Headers */, + C26FF6300E5B376B00F640A0 /* CSCommon.h in Headers */, + C26FF6320E5B376B00F640A0 /* SecCode.h in Headers */, + C26FF6340E5B376B00F640A0 /* SecStaticCode.h in Headers */, + C26FF6360E5B376B00F640A0 /* SecRequirement.h in Headers */, + C26FF6390E5B376B00F640A0 /* SecCodeHost.h in Headers */, + C2A436160F2133B2007A41A6 /* slcrep.h in Headers */, + C24EABAB1421432800C16AA9 /* policydb.h in Headers */, + C2F4439B14C626D4000A01E6 /* quarantine++.h in Headers */, + C26763D814FD9EBE00A46EDF /* drmaker.h in Headers */, + EBDAF050166D65FA0042CDCE /* piddiskrep.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C2BC1F220B580D3A003EC9DC /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + C250F6C30B5EF1910076098F /* SecIntegrity.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C2BC1F2B0B580D4B003EC9DC /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + C2BC1F350B580DA7003EC9DC /* SecCodeHostLib.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 4CA1FEBD052A3C8100F22E42 /* libsecurity_codesigning */ = { + isa = PBXNativeTarget; + buildConfigurationList = C263E67509A2971B000043F1 /* Build configuration list for PBXNativeTarget "libsecurity_codesigning" */; + buildPhases = ( + 4CA1FEB9052A3C8100F22E42 /* Headers */, + 4CA1FEBA052A3C8100F22E42 /* Sources */, + 4CA1FEBB052A3C8100F22E42 /* Frameworks */, + 1865FFD5147517A300FD79DF /* ShellScript */, + EBF9A1501684E0DF00BCECA6 /* Copy OpenSourceVersions */, + EBF9A1591684E12C00BCECA6 /* OpenSourceLicenses */, + ); + buildRules = ( + ); + dependencies = ( + 182BB50F146F28F6000BF1F3 /* PBXTargetDependency */, + 1844617D146E9A5200B12992 /* PBXTargetDependency */, + 182BB511146F292B000BF1F3 /* PBXTargetDependency */, + ); + name = libsecurity_codesigning; + productName = libsecurity_codesigning; + productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_codesigning.a */; + productType = "com.apple.product-type.library.static"; + }; + 7AADF57C19C0CE8C00292339 /* gkoverride */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7AADF58719C0CE8C00292339 /* Build configuration list for PBXNativeTarget "gkoverride" */; + buildPhases = ( + 7AADF57919C0CE8C00292339 /* Sources */, + 7AADF57A19C0CE8C00292339 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = gkoverride; + productName = gkoverride; + productReference = 7AADF57D19C0CE8C00292339 /* gkoverride */; + productType = "com.apple.product-type.tool"; + }; + C209695F15BF52040093035F /* gkunpack */ = { + isa = PBXNativeTarget; + buildConfigurationList = C209696B15BF52040093035F /* Build configuration list for PBXNativeTarget "gkunpack" */; + buildPhases = ( + C209695C15BF52040093035F /* Sources */, + C209695D15BF52040093035F /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = gkunpack; + productName = gkunpack; + productReference = C209696015BF52040093035F /* gkunpack */; + productType = "com.apple.product-type.tool"; + }; + C2BC1F250B580D3A003EC9DC /* libintegrity */ = { + isa = PBXNativeTarget; + buildConfigurationList = C2BC1F270B580D3F003EC9DC /* Build configuration list for PBXNativeTarget "libintegrity" */; + buildPhases = ( + C2BC1F220B580D3A003EC9DC /* Headers */, + C2BC1F230B580D3A003EC9DC /* Sources */, + C2BC1F240B580D3A003EC9DC /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libintegrity; + productName = libintegrity; + productReference = C2BC1F260B580D3A003EC9DC /* libintegrity.a */; + productType = "com.apple.product-type.library.static"; + }; + C2BC1F2E0B580D4B003EC9DC /* libcodehost */ = { + isa = PBXNativeTarget; + buildConfigurationList = C2BC1F300B580D69003EC9DC /* Build configuration list for PBXNativeTarget "libcodehost" */; + buildPhases = ( + C26B45C30B8A9C1A003C0ACA /* Prepare ucspc */, + C2BC1F2B0B580D4B003EC9DC /* Headers */, + C2BC1F2C0B580D4B003EC9DC /* Sources */, + C2BC1F2D0B580D4B003EC9DC /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libcodehost; + productName = libcodehost; + productReference = C2BC1F2F0B580D4B003EC9DC /* libcodehost.a */; + productType = "com.apple.product-type.library.static"; + }; + EBB9FF6E1682E51300FF9774 /* CodeSigningHelper */ = { + isa = PBXNativeTarget; + buildConfigurationList = EBB9FF7B1682E51300FF9774 /* Build configuration list for PBXNativeTarget "CodeSigningHelper" */; + buildPhases = ( + EBB9FF6B1682E51300FF9774 /* Sources */, + EBB9FF6C1682E51300FF9774 /* Frameworks */, + EBB9FFE11682E80A00FF9774 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = CodeSigningHelper; + productName = CodeSigningHelper; + productReference = EBB9FF6F1682E51300FF9774 /* com.apple.CodeSigningHelper.xpc */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA1FEAB052A3C3800F22E42 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + TargetAttributes = { + 7AADF57C19C0CE8C00292339 = { + CreatedOnToolsVersion = 6.0; + }; + }; + }; + buildConfigurationList = C263E67909A2971B000043F1 /* Build configuration list for PBXProject "libsecurity_codesigning" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + en, + ); + mainGroup = 4CA1FEA7052A3C3800F22E42; + productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 182BB4FD146F2823000BF1F3 /* Products */; + ProjectRef = 182BB4FC146F2823000BF1F3 /* libsecurityd.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + C2E2873F0B5D8F8F009336A0 /* Everything */, + 4CA1FEBD052A3C8100F22E42 /* libsecurity_codesigning */, + C2D383B80A23A8C4005C63A2 /* Requirements Language */, + C2BC1F250B580D3A003EC9DC /* libintegrity */, + C2BC1F2E0B580D4B003EC9DC /* libcodehost */, + C26AC7090DAEB3A7005BFB40 /* DTrace */, + C26AC0EB143BCF01001C98CE /* SystemPolicy */, + C209695F15BF52040093035F /* gkunpack */, + 7AADF57C19C0CE8C00292339 /* gkoverride */, + EBB9FF6E1682E51300FF9774 /* CodeSigningHelper */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 182BB505146F2823000BF1F3 /* libsecurityd_client.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurityd_client.a; + remoteRef = 182BB504146F2823000BF1F3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 182BB507146F2823000BF1F3 /* libsecurityd_server.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurityd_server.a; + remoteRef = 182BB506146F2823000BF1F3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 182BB509146F2823000BF1F3 /* ucspc.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = ucspc.a; + remoteRef = 182BB508146F2823000BF1F3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXShellScriptBuildPhase section */ + 1865FFD5147517A300FD79DF /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "ranlib \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\""; + }; + C26AC0F0143BCF18001C98CE /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 12; + files = ( + ); + inputPaths = ( + "$(PROJECT_DIR)/lib/syspolicy.sql", + ); + outputPaths = ( + "$(TEMPDIR)/SystemPolicy", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "mkdir -p \"$(dirname \"$SCRIPT_OUTPUT_FILE_0\")\"\nrm -f \"$SCRIPT_OUTPUT_FILE_0\"\nsqlite3 \"$SCRIPT_OUTPUT_FILE_0\" <$SRCROOT/lib/RequirementKeywords.h\n"; + }; + C2F24DFE14BCBBF200309FCD /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputPaths = ( + "$(TEMPDIR)/SystemPolicy", + ); + outputPaths = ( + "$(DSTROOT)/private/var/db/.SystemPolicy-default", + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/bash; + shellScript = "cp \"$SCRIPT_INPUT_FILE_0\" \"$SCRIPT_OUTPUT_FILE_0\"\nchmod 444 \"$SCRIPT_OUTPUT_FILE_0\""; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 4CA1FEBA052A3C8100F22E42 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EB976FB81684D7C500A68EE6 /* ANTLRUtil.cpp in Sources */, + EB976FB91684D7C500A68EE6 /* ASTFactory.cpp in Sources */, + EB976FBA1684D7C500A68EE6 /* ASTNULLType.cpp in Sources */, + EB976FBB1684D7C500A68EE6 /* ASTRefCount.cpp in Sources */, + EB976FBC1684D7C500A68EE6 /* BaseAST.cpp in Sources */, + EB976FBD1684D7C500A68EE6 /* BitSet.cpp in Sources */, + EB976FBE1684D7C500A68EE6 /* CharBuffer.cpp in Sources */, + EB976FBF1684D7C500A68EE6 /* CharScanner.cpp in Sources */, + 37DDE3421947A501005CE18B /* dirscanner.cpp in Sources */, + EB976FC01684D7C500A68EE6 /* CommonAST.cpp in Sources */, + EB976FC11684D7C500A68EE6 /* CommonASTWithHiddenTokens.cpp in Sources */, + EB976FC21684D7C500A68EE6 /* CommonHiddenStreamToken.cpp in Sources */, + EB976FC31684D7C500A68EE6 /* CommonToken.cpp in Sources */, + EB976FC41684D7C500A68EE6 /* InputBuffer.cpp in Sources */, + EB976FC51684D7C500A68EE6 /* LLkParser.cpp in Sources */, + EB976FC61684D7C500A68EE6 /* MismatchedCharException.cpp in Sources */, + EB976FC71684D7C500A68EE6 /* MismatchedTokenException.cpp in Sources */, + EB976FC81684D7C500A68EE6 /* NoViableAltException.cpp in Sources */, + EB976FC91684D7C500A68EE6 /* NoViableAltForCharException.cpp in Sources */, + EB976FCA1684D7C500A68EE6 /* Parser.cpp in Sources */, + EB976FCB1684D7C500A68EE6 /* RecognitionException.cpp in Sources */, + EB976FCC1684D7C500A68EE6 /* String.cpp in Sources */, + EB976FCD1684D7C500A68EE6 /* Token.cpp in Sources */, + EB976FCE1684D7C500A68EE6 /* TokenBuffer.cpp in Sources */, + EB976FCF1684D7C500A68EE6 /* TokenRefCount.cpp in Sources */, + EB976FD01684D7C500A68EE6 /* TokenStreamBasicFilter.cpp in Sources */, + EB976FD11684D7C500A68EE6 /* TokenStreamHiddenTokenFilter.cpp in Sources */, + EB976FD21684D7C500A68EE6 /* TokenStreamRewriteEngine.cpp in Sources */, + EB976FD31684D7C500A68EE6 /* TokenStreamSelector.cpp in Sources */, + EB976FD41684D7C500A68EE6 /* TreeParser.cpp in Sources */, + C2D3833C0A237F47005C63A2 /* bundlediskrep.cpp in Sources */, + C2D3833E0A237F47005C63A2 /* cdbuilder.cpp in Sources */, + C2D383400A237F47005C63A2 /* codedirectory.cpp in Sources */, + C2D383440A237F47005C63A2 /* cs.cpp in Sources */, + C2D383470A237F47005C63A2 /* SecCode.cpp in Sources */, + C2D383490A237F47005C63A2 /* cskernel.cpp in Sources */, + C2D3834B0A237F47005C63A2 /* SecStaticCode.cpp in Sources */, + C2D3834D0A237F47005C63A2 /* csprocess.cpp in Sources */, + C2D3834F0A237F47005C63A2 /* SecRequirement.cpp in Sources */, + C2D383510A237F47005C63A2 /* diskrep.cpp in Sources */, + C2D383550A237F47005C63A2 /* filediskrep.cpp in Sources */, + C2D383570A237F47005C63A2 /* Code.cpp in Sources */, + C2D383590A237F47005C63A2 /* kerneldiskrep.cpp in Sources */, + C2D3835B0A237F47005C63A2 /* StaticCode.cpp in Sources */, + C2D3835D0A237F47005C63A2 /* reqparser.cpp in Sources */, + C2C1DF140A2E3D7200D1B02B /* requirement.cpp in Sources */, + C2D383610A237F47005C63A2 /* Requirements.cpp in Sources */, + C21CFC5F0A250D1C006CD5B1 /* reqdumper.cpp in Sources */, + C2C1DFBB0A2F80EB00D1B02B /* reqinterp.cpp in Sources */, + C2C1DFC30A2F820500D1B02B /* reqmaker.cpp in Sources */, + C22463610B86210100626F1B /* antlrplugin.cpp in Sources */, + C2BD519C0A9392FD000FE43D /* machorep.cpp in Sources */, + C2C931B40AB8BA1200F83950 /* SecCodeHost.cpp in Sources */, + C2BD60FA0AC863FC0057FD3D /* csgeneric.cpp in Sources */, + C21EA3DD0AD2F81300E6E31C /* SecCodeSigner.cpp in Sources */, + C21EA3E30AD2FA0900E6E31C /* CodeSigner.cpp in Sources */, + C236E3D70AD59446000F5140 /* signer.cpp in Sources */, + C236E3DB0AD595C2000F5140 /* signerutils.cpp in Sources */, + C259DFD60AD6D9BA00C9ACC6 /* sigblob.cpp in Sources */, + C2E911E20ADEBE3200275CB2 /* resources.cpp in Sources */, + C2A976AA0B8A2E36008B4EA0 /* csutilities.cpp in Sources */, + C2C3BCD30BA1E47E00E869D1 /* singlediskrep.cpp in Sources */, + C2093AA80BB0948000EB8599 /* reqreader.cpp in Sources */, + C2F6566E0BCBFB250078779E /* cserror.cpp in Sources */, + C28342E70E366E6800E54360 /* csdatabase.cpp in Sources */, + C28342EE0E36719D00E54360 /* detachedrep.cpp in Sources */, + C2A436150F2133B2007A41A6 /* slcrep.cpp in Sources */, + FEB30C9310DAC89D00557BA2 /* SecTask.c in Sources */, + C24EABAD1421433700C16AA9 /* policydb.cpp in Sources */, + 7A9DA65C1948D1BA004635E6 /* opaquewhitelist.cpp in Sources */, + C273606E1433F09000A9A5FF /* SecAssessment.cpp in Sources */, + C27360D51436866D00A9A5FF /* xpcengine.cpp in Sources */, + C2DC2DCA145F594000AD2A3A /* xar++.cpp in Sources */, + C2DC2DCB145F5CD000AD2A3A /* policyengine.cpp in Sources */, + C2F4439A14C626D4000A01E6 /* quarantine++.cpp in Sources */, + C26763D714FD9EBE00A46EDF /* drmaker.cpp in Sources */, + EB68B111150DAEEA00B4013D /* RequirementLexer.cpp in Sources */, + EB68B112150DAEEA00B4013D /* RequirementParser.cpp in Sources */, + EBDAF04F166D65FA0042CDCE /* piddiskrep.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7AADF57919C0CE8C00292339 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7AADF58919C0CED800292339 /* gkoverride.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C209695C15BF52040093035F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C209696415BF52040093035F /* gkunpack.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C2BC1F230B580D3A003EC9DC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C2CC310F0B852424005FA59D /* SecIntegrityLib.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C2BC1F2C0B580D4B003EC9DC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C2E2873D0B5D8D80009336A0 /* SecCodeHostLib.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EBB9FF6B1682E51300FF9774 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EBB9FF7A1682E51300FF9774 /* main.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 182BB50F146F28F6000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurityd_generate; + targetProxy = 182BB50E146F28F6000BF1F3 /* PBXContainerItemProxy */; + }; + 182BB511146F292B000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C26AC0EB143BCF01001C98CE /* SystemPolicy */; + targetProxy = 182BB510146F292B000BF1F3 /* PBXContainerItemProxy */; + }; + 1844617D146E9A5200B12992 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C26AC7090DAEB3A7005BFB40 /* DTrace */; + targetProxy = 1844617C146E9A5200B12992 /* PBXContainerItemProxy */; + }; + C209697015BF53330093035F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C209695F15BF52040093035F /* gkunpack */; + targetProxy = C209696F15BF53330093035F /* PBXContainerItemProxy */; + }; + C250F6C50B5EF4E40076098F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C2BC1F250B580D3A003EC9DC /* libintegrity */; + targetProxy = C250F6C40B5EF4E40076098F /* PBXContainerItemProxy */; + }; + C26AC0F2143BD02B001C98CE /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C26AC0EB143BCF01001C98CE /* SystemPolicy */; + targetProxy = C26AC0F1143BD02B001C98CE /* PBXContainerItemProxy */; + }; + C2E287410B5D8F97009336A0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4CA1FEBD052A3C8100F22E42 /* libsecurity_codesigning */; + targetProxy = C2E287400B5D8F97009336A0 /* PBXContainerItemProxy */; + }; + C2E287430B5D8F9A009336A0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C2BC1F2E0B580D4B003EC9DC /* libcodehost */; + targetProxy = C2E287420B5D8F9A009336A0 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 7AADF58119C0CE8C00292339 /* 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; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ""; + INSTALL_PATH = /usr/libexec; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx.internal; + SKIP_INSTALL = NO; + }; + name = Debug; + }; + 7AADF58219C0CE8C00292339 /* 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; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); + 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; + HEADER_SEARCH_PATHS = ""; + INSTALL_PATH = /usr/libexec; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx.internal; + SKIP_INSTALL = NO; + }; + name = Release; + }; + C209696C15BF52040093035F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = NO; + }; + name = Debug; + }; + C209696D15BF52040093035F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = NO; + }; + name = Release; + }; + C263E67609A2971B000043F1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184461A0146E9AD100B12992 /* debug.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/antlr2", + "$(inherited)", + "$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders", + ); + PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/security_codesigning; + SKIP_INSTALL = NO; + }; + name = Debug; + }; + C263E67809A2971B000043F1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184461A2146E9AD100B12992 /* release.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/antlr2", + "$(inherited)", + "$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders", + ); + PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/security_codesigning; + SKIP_INSTALL = NO; + }; + name = Release; + }; + C263E67A09A2971B000043F1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184461A1146E9AD100B12992 /* lib.xcconfig */; + buildSettings = { + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/../include", + "$(BUILT_PRODUCTS_DIR)/derived_src", + "$(BUILT_PRODUCTS_DIR)", + "$(PROJECT_DIR)/lib", + /usr/local/include, + ); + TEMPDIR = "$(BUILT_PRODUCTS_DIR)/cstemp"; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + "$(inherited)", + ); + }; + name = Debug; + }; + C263E67C09A2971B000043F1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184461A1146E9AD100B12992 /* lib.xcconfig */; + buildSettings = { + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/../include", + "$(BUILT_PRODUCTS_DIR)/derived_src", + "$(BUILT_PRODUCTS_DIR)", + "$(PROJECT_DIR)/lib", + /usr/local/include, + ); + TEMPDIR = "$(BUILT_PRODUCTS_DIR)/cstemp"; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + "$(inherited)", + ); + }; + name = Release; + }; + C26AC0ED143BCF01001C98CE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Debug; + }; + C26AC0EF143BCF01001C98CE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Release; + }; + C26AC70A0DAEB3A8005BFB40 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Debug; + }; + C26AC70C0DAEB3A8005BFB40 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Release; + }; + C2BC1F280B580D3F003EC9DC /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184461A0146E9AD100B12992 /* debug.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + SKIP_INSTALL = NO; + }; + name = Debug; + }; + C2BC1F2A0B580D3F003EC9DC /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184461A2146E9AD100B12992 /* release.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + SKIP_INSTALL = NO; + }; + name = Release; + }; + C2BC1F310B580D69003EC9DC /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184461A0146E9AD100B12992 /* debug.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + SKIP_INSTALL = NO; + }; + name = Debug; + }; + C2BC1F330B580D69003EC9DC /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 184461A2146E9AD100B12992 /* release.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + SKIP_INSTALL = NO; + }; + name = Release; + }; + C2D383C10A23A8E3005C63A2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Debug; + }; + C2D383C30A23A8E3005C63A2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Release; + }; + C2E287480B5D8FD8009336A0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/../include", + "$(BUILT_PRODUCTS_DIR)/derived_src", + "$(BUILT_PRODUCTS_DIR)", + "$(PROJECT_DIR)/lib", + /usr/local/include, + ); + }; + name = Debug; + }; + C2E2874A0B5D8FD8009336A0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/../include", + "$(BUILT_PRODUCTS_DIR)/derived_src", + "$(BUILT_PRODUCTS_DIR)", + "$(PROJECT_DIR)/lib", + /usr/local/include, + ); + }; + name = Release; + }; + EBB9FF7C1682E51300FF9774 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = "CodeSigningHelper/CodeSigningHelper-Info.plist"; + INSTALL_PATH = /System/Library/Frameworks/Security.framework/Versions/A/XPCServices; + MACH_O_TYPE = mh_execute; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "com.apple.$(TARGET_NAME:rfc1034identifier)"; + SKIP_INSTALL = NO; + WRAPPER_EXTENSION = xpc; + }; + name = Debug; + }; + EBB9FF7D1682E51300FF9774 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = "CodeSigningHelper/CodeSigningHelper-Info.plist"; + INSTALL_PATH = /System/Library/Frameworks/Security.framework/Versions/A/XPCServices; + MACH_O_TYPE = mh_execute; + PRODUCT_NAME = "com.apple.$(TARGET_NAME:rfc1034identifier)"; + SKIP_INSTALL = NO; + WRAPPER_EXTENSION = xpc; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7AADF58719C0CE8C00292339 /* Build configuration list for PBXNativeTarget "gkoverride" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7AADF58119C0CE8C00292339 /* Debug */, + 7AADF58219C0CE8C00292339 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C209696B15BF52040093035F /* Build configuration list for PBXNativeTarget "gkunpack" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C209696C15BF52040093035F /* Debug */, + C209696D15BF52040093035F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C263E67509A2971B000043F1 /* Build configuration list for PBXNativeTarget "libsecurity_codesigning" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C263E67609A2971B000043F1 /* Debug */, + C263E67809A2971B000043F1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C263E67909A2971B000043F1 /* Build configuration list for PBXProject "libsecurity_codesigning" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C263E67A09A2971B000043F1 /* Debug */, + C263E67C09A2971B000043F1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C26AC0EC143BCF01001C98CE /* Build configuration list for PBXAggregateTarget "SystemPolicy" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C26AC0ED143BCF01001C98CE /* Debug */, + C26AC0EF143BCF01001C98CE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C26AC70D0DAEB3C6005BFB40 /* Build configuration list for PBXAggregateTarget "DTrace" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C26AC70A0DAEB3A8005BFB40 /* Debug */, + C26AC70C0DAEB3A8005BFB40 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C2BC1F270B580D3F003EC9DC /* Build configuration list for PBXNativeTarget "libintegrity" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C2BC1F280B580D3F003EC9DC /* Debug */, + C2BC1F2A0B580D3F003EC9DC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C2BC1F300B580D69003EC9DC /* Build configuration list for PBXNativeTarget "libcodehost" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C2BC1F310B580D69003EC9DC /* Debug */, + C2BC1F330B580D69003EC9DC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C2D383C00A23A8E3005C63A2 /* Build configuration list for PBXAggregateTarget "Requirements Language" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C2D383C10A23A8E3005C63A2 /* Debug */, + C2D383C30A23A8E3005C63A2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C2E287470B5D8FD8009336A0 /* Build configuration list for PBXAggregateTarget "Everything" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C2E287480B5D8FD8009336A0 /* Debug */, + C2E2874A0B5D8FD8009336A0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + EBB9FF7B1682E51300FF9774 /* Build configuration list for PBXNativeTarget "CodeSigningHelper" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EBB9FF7C1682E51300FF9774 /* Debug */, + EBB9FF7D1682E51300FF9774 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; +} diff --git a/libsecurity_codesigning/req/cfm.ireqs b/Security/libsecurity_codesigning/req/cfm.ireqs similarity index 100% rename from libsecurity_codesigning/req/cfm.ireqs rename to Security/libsecurity_codesigning/req/cfm.ireqs diff --git a/libsecurity_codesigning/req/ppc-host.ireq b/Security/libsecurity_codesigning/req/ppc-host.ireq similarity index 100% rename from libsecurity_codesigning/req/ppc-host.ireq rename to Security/libsecurity_codesigning/req/ppc-host.ireq diff --git a/libsecurity_codesigning/requirements.grammar b/Security/libsecurity_codesigning/requirements.grammar similarity index 100% rename from libsecurity_codesigning/requirements.grammar rename to Security/libsecurity_codesigning/requirements.grammar diff --git a/libsecurity_comcryption/Info-security_comcryption.plist b/Security/libsecurity_comcryption/Info-security_comcryption.plist similarity index 100% rename from libsecurity_comcryption/Info-security_comcryption.plist rename to Security/libsecurity_comcryption/Info-security_comcryption.plist diff --git a/libsecurity_comcryption/lib/comDebug.h b/Security/libsecurity_comcryption/lib/comDebug.h similarity index 99% rename from libsecurity_comcryption/lib/comDebug.h rename to Security/libsecurity_comcryption/lib/comDebug.h index aee978f6..efc823d9 100644 --- a/libsecurity_comcryption/lib/comDebug.h +++ b/Security/libsecurity_comcryption/lib/comDebug.h @@ -1,4 +1,4 @@ -/* Copyright (c) 1997 Apple Computer, Inc. +/* Copyright (c) 1997,2011,2014 Apple Inc. * * comDebug.h */ diff --git a/libsecurity_comcryption/lib/comcryptPriv.c b/Security/libsecurity_comcryption/lib/comcryptPriv.c similarity index 90% rename from libsecurity_comcryption/lib/comcryptPriv.c rename to Security/libsecurity_comcryption/lib/comcryptPriv.c index b584235e..873b32c8 100644 --- a/libsecurity_comcryption/lib/comcryptPriv.c +++ b/Security/libsecurity_comcryption/lib/comcryptPriv.c @@ -1,23 +1,26 @@ /* - File: comcryptPriv.c - - Contains: private routines for comcryption library. - - Written by: Doug Mitchell - - Copyright: (c) 1997 by Apple Computer, Inc., all rights reserved. - - Change History (most recent first): - - 05/28/98 dpm Added platform-dependent ascMalloc and ascFree - 12/23/97 dpm Added keyHash(), used result to initialize - nybbleDex and queue. - 12/18/97 dpm Improved queue initialization. - 12/03/97 dpm Added queue lookahead; various optimizations. - 11/13/97 dpm Created; broke out from comcryption.c + * Copyright (c) 1997,2011,2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ - To Do: -*/ #include "comcryptPriv.h" #include diff --git a/libsecurity_comcryption/lib/comcryptPriv.h b/Security/libsecurity_comcryption/lib/comcryptPriv.h similarity index 92% rename from libsecurity_comcryption/lib/comcryptPriv.h rename to Security/libsecurity_comcryption/lib/comcryptPriv.h index be167f6c..d99c9637 100644 --- a/libsecurity_comcryption/lib/comcryptPriv.h +++ b/Security/libsecurity_comcryption/lib/comcryptPriv.h @@ -1,21 +1,26 @@ /* - File: comcryptPriv.h - - Contains: private typedefs and #defines for comcryption library. - - Written by: Doug Mitchell - - Copyright: (c) 1997 by Apple Computer, Inc., all rights reserved. - - Change History (most recent first): - - 05/28/98 dpm Added platform-dependent ascMalloc and ascFree - 12/08/97 dpm Added Signature Sequence mechanism. - 12/03/97 dpm Added queue lookahead; various optimizations. - 11/13/97 dpm Created; broke out from comcryption.c + * Copyright (c) 1997,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ - To Do: -*/ #ifndef _COMCRYPT_PRIV_H_ #define _COMCRYPT_PRIV_H_ diff --git a/libsecurity_comcryption/lib/comcryption.c b/Security/libsecurity_comcryption/lib/comcryption.c similarity index 97% rename from libsecurity_comcryption/lib/comcryption.c rename to Security/libsecurity_comcryption/lib/comcryption.c index 56d89b60..a7d23e95 100644 --- a/libsecurity_comcryption/lib/comcryption.c +++ b/Security/libsecurity_comcryption/lib/comcryption.c @@ -1,32 +1,26 @@ /* - File: comcryption.c - - Contains: implementation of low-level comcryption engine - - Written by: Richard Crandall and Doug Mitchell - - Copyright: (c) 1997 by Apple Computer, Inc., all rights reserved. - - Change History (most recent first): - - 05/28/98 dpm Added platform-dependent ascMalloc and ascFree - 12/08/97 dpm Added Signature Sequence mechanism. - 12/03/97 dpm Added queue lookahead; various optimizations. - 11/13/97 dpm Rewrote for block-oriented ciphertext with - two-level comcryption. - 11/11/97 gab Modified for MacOS (fixed implicit type - conversions) - 10/29/97 dpm Extensive mods for stream-oriented API. - 10/01/97 rc original by Richard Crandall - - To Do: - - - Library for holistic (one-pass) compress-encrypt. - This is an explicit embodiment of the Comcryption^(TM) - invention. + * Copyright (c) 1997,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@ + */ -*/ #include #include diff --git a/libsecurity_comcryption/lib/comcryption.h b/Security/libsecurity_comcryption/lib/comcryption.h similarity index 81% rename from libsecurity_comcryption/lib/comcryption.h rename to Security/libsecurity_comcryption/lib/comcryption.h index fefff98c..fd10934f 100644 --- a/libsecurity_comcryption/lib/comcryption.h +++ b/Security/libsecurity_comcryption/lib/comcryption.h @@ -1,20 +1,26 @@ /* - File: comcryption.h - - Contains: interface for low-level comcryption engine - - Written by: Doug Mitchell - - Copyright: (c) 1997 by Apple Computer, Inc., all rights reserved. - - Change History (most recent first): - - 11/11/97 gab Updated for MPW - 10/29/97 dm Created, based on work by R. Crandall, - G. Brown, A. Perez - To Do: + * Copyright (c) 1997,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@ + */ -*/ #ifndef _COMCRYPTION_H_ #define _COMCRYPTION_H_ diff --git a/libsecurity_comcryption/libsecurity_comcryption.xcodeproj/project.pbxproj b/Security/libsecurity_comcryption/libsecurity_comcryption.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_comcryption/libsecurity_comcryption.xcodeproj/project.pbxproj rename to Security/libsecurity_comcryption/libsecurity_comcryption.xcodeproj/project.pbxproj diff --git a/libsecurity_cryptkit/Info-security_cryptkit.plist b/Security/libsecurity_cryptkit/Info-security_cryptkit.plist similarity index 100% rename from libsecurity_cryptkit/Info-security_cryptkit.plist rename to Security/libsecurity_cryptkit/Info-security_cryptkit.plist diff --git a/libsecurity_cryptkit/ckutils/Makefile b/Security/libsecurity_cryptkit/ckutils/Makefile similarity index 100% rename from libsecurity_cryptkit/ckutils/Makefile rename to Security/libsecurity_cryptkit/ckutils/Makefile diff --git a/libsecurity_cryptkit/ckutils/Makefile.common b/Security/libsecurity_cryptkit/ckutils/Makefile.common similarity index 100% rename from libsecurity_cryptkit/ckutils/Makefile.common rename to Security/libsecurity_cryptkit/ckutils/Makefile.common diff --git a/libsecurity_cryptkit/ckutils/atomTime/Makefile b/Security/libsecurity_cryptkit/ckutils/atomTime/Makefile similarity index 100% rename from libsecurity_cryptkit/ckutils/atomTime/Makefile rename to Security/libsecurity_cryptkit/ckutils/atomTime/Makefile diff --git a/libsecurity_cryptkit/ckutils/atomTime/atomTime.c b/Security/libsecurity_cryptkit/ckutils/atomTime/atomTime.c similarity index 100% rename from libsecurity_cryptkit/ckutils/atomTime/atomTime.c rename to Security/libsecurity_cryptkit/ckutils/atomTime/atomTime.c diff --git a/libsecurity_cryptkit/ckutils/badsig/Makefile b/Security/libsecurity_cryptkit/ckutils/badsig/Makefile similarity index 100% rename from libsecurity_cryptkit/ckutils/badsig/Makefile rename to Security/libsecurity_cryptkit/ckutils/badsig/Makefile diff --git a/Security/libsecurity_cryptkit/ckutils/badsig/badsig.c b/Security/libsecurity_cryptkit/ckutils/badsig/badsig.c new file mode 100644 index 00000000..3a438059 --- /dev/null +++ b/Security/libsecurity_cryptkit/ckutils/badsig/badsig.c @@ -0,0 +1,475 @@ +/* + * Copyright (c) 1996-1997,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* + * text size = {random, from 100 bytes to 1 megabyte, in + * geometrical steps, i.e. the number of + * bytes would be 10^r, where r is random out of + * {2,3,4,5,6}, plus a random integer in {0,..99}}; + * + * password size = constant; + * + * for loop_count + * text contents = {random data, random size as specified above}; + * passsword data = random; + * + Alternate between ECDSA and ElGamal on sucessive loops: + * generate signature, validate; + * for each byte of signature { + * corrupt text byte; + * verify bad signature; + * restore corrupted byte; + * } + * } + */ + +#import "Crypt.h" +#include "ckconfig.h" + +#if !CRYPTKIT_HIGH_LEVEL_SIG +#error Can not build this program against a lib with !CRYPTKIT_HIGH_LEVEL_SIG. +#endif + +#import +#import + +static unsigned char *passwdPool; /* all passwords come from here */ +static unsigned char *dataPool; /* plaintext comes from here */ + +#define MAX_DATA_SIZE ((1024 * 1024) + 100) /* bytes */ + +/* + * Defaults. + */ +#define LOOPS_DEF 1 +#define MIN_EXP 2 /* for data size 10**exp */ +#define MAX_EXP 4 +#define PWD_LENGTH 15 /* bytes */ +#define DEPTH_DEFAULT FEE_DEPTH_DEFAULT +#define INCR_DEFAULT 1 /* munge every incr bytes */ + +///#define DEPTH_DEFAULT FEE_DEPTH_5 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" n=minExp (default=%d)\n", MIN_EXP); + printf(" x=maxExp (default=max=%d)\n", MAX_EXP); + printf(" p=passwdLength (default=%d)\n", PWD_LENGTH); + printf(" D=depth (default=%d)\n", DEPTH_DEFAULT); + printf(" i=increment (default=%d)\n", INCR_DEFAULT); + #if CRYPTKIT_ECDSA_ENABLE + printf(" e (ElGamal only, no ECDSA)\n"); + #endif + printf(" s=seed\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +/* + * ...min <= return <= max + */ +static int genRand(int min, int max) +{ + + /* note random() only yields a 31-bit number... */ + + if(max == min) /* avoid % 1 ! */ + return(max); + else + return(min + (random() % (max-min+1))); +} + +static unsigned char *genPasswd(unsigned passwdLength) +{ + unsigned *ip = (unsigned *)passwdPool; + unsigned intCount = passwdLength / 4; + int i; + unsigned char *cp; + unsigned residue = passwdLength & 0x3; + + for (i=0; i MAX_ASCII) { + ac = MIN_ASCII; + } + } + break; + case DT_Random: + intCount = size >> 2; + ip = (unsigned *)dataPool; + for(i=0; i MAX_EXP) { + usage(argv); + } + break; + case 'D': + depth = atoi(&argp[2]); + break; + case 'i': + incr = atoi(&argp[2]); + break; + case 's': + seed = atoi(&argp[2]); + seedSpec = 1; + break; + case 'p': + passwdLen = atoi(&argp[2]); + if(passwdLen == 0) { + usage(argv); + } + break; + case 'e': + elGamalOnly = 1; + break; + case 'v': + verbose = 1; + break; + case 'q': + quiet = 1; + break; + case 'h': + default: + usage(argv); + } + } + + if(seedSpec == 0) { + time((long *)(&seed)); + } + srandom(seed); + passwdPool = malloc(passwdLen); + dataPool = malloc(MAX_DATA_SIZE); + + printf("Starting %s test: loops %d seed %d elGamalOnly %d depth %d\n", + argv[0], loops, seed, elGamalOnly, depth); + + #if 0 + /* debug only */ + { + char s[20]; + printf("attach, then CR to continue: "); + gets(s); + } + #endif 0 + + for(loop=1; ; loop++) { + + ptext = genData(minExp, maxExp, DT_Random, &ptextLen); + passwd = genPasswd(passwdLen); + + /* + * Alternate between ECDSA and ElGamal + */ + if(elGamalOnly) { + doECDSA = 0; + doECDSAVfy = 0; + } + else { + if(loop & 1) { + doECDSA = 1; + if(loop & 2) { + doECDSAVfy = 1; + } + else { + doECDSAVfy = 0; + } + } + else { + doECDSA = 0; + doECDSAVfy = 0; + } + } + if(!quiet) { + printf("..loop %d text size %d ECDSA %d ECDSAVfy %d\n", + loop, ptextLen, doECDSA, doECDSAVfy); + } + if(doTest(ptext, ptextLen, passwd, passwdLen, + verbose, quiet, depth, incr, + doECDSA, doECDSAVfy)) { + exit(1); + } + + if(loops && (loop == loops)) { + break; + } + } + if(!quiet) { + printf("%s test complete\n", argv[0]); + } + return 0; +} diff --git a/libsecurity_cryptkit/ckutils/blobtest/Makefile b/Security/libsecurity_cryptkit/ckutils/blobtest/Makefile similarity index 100% rename from libsecurity_cryptkit/ckutils/blobtest/Makefile rename to Security/libsecurity_cryptkit/ckutils/blobtest/Makefile diff --git a/libsecurity_cryptkit/ckutils/blobtest/blobtest.c b/Security/libsecurity_cryptkit/ckutils/blobtest/blobtest.c similarity index 87% rename from libsecurity_cryptkit/ckutils/blobtest/blobtest.c rename to Security/libsecurity_cryptkit/ckutils/blobtest/blobtest.c index c76c0a47..0f678f8b 100644 --- a/libsecurity_cryptkit/ckutils/blobtest/blobtest.c +++ b/Security/libsecurity_cryptkit/ckutils/blobtest/blobtest.c @@ -1,12 +1,26 @@ -/* Copyright 1998 Apple Computer, Inc. +/* + * Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * - * blobtest.c - test key blob functions - * - * Revision History - * ---------------- - * 23 Mar 1998 Doug Mitchell - * Created. + * @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 "Crypt.h" #include "falloc.h" diff --git a/libsecurity_cryptkit/ckutils/cfileTest/Makefile b/Security/libsecurity_cryptkit/ckutils/cfileTest/Makefile similarity index 100% rename from libsecurity_cryptkit/ckutils/cfileTest/Makefile rename to Security/libsecurity_cryptkit/ckutils/cfileTest/Makefile diff --git a/libsecurity_cryptkit/ckutils/cfileTest/cfileTest.c b/Security/libsecurity_cryptkit/ckutils/cfileTest/cfileTest.c similarity index 92% rename from libsecurity_cryptkit/ckutils/cfileTest/cfileTest.c rename to Security/libsecurity_cryptkit/ckutils/cfileTest/cfileTest.c index bf0a4193..e0951b68 100644 --- a/libsecurity_cryptkit/ckutils/cfileTest/cfileTest.c +++ b/Security/libsecurity_cryptkit/ckutils/cfileTest/cfileTest.c @@ -1,17 +1,27 @@ -/* Copyright 1997 Apple Computer, Inc. -* - * cfileTest.c - General standalone CipherFile test +/* + * Copyright (c) 1997,2011,2014 Apple Inc. All Rights Reserved. * - * Revision History - * ---------------- - * 28 May 98 Doug Mitchell at Apple - * Checged to use fmalloc(), ffree(), ccommand() - * 24 Jun 97 Doug Mitchell at Apple - * Mods for Mac CodeWarrior build - standalone; no feeLib - * 7 Mar 97 Doug Mitchell at Apple - * Created. + * @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 "ckutilsPlatform.h" #include "Crypt.h" #include "feeCipherFile.h" diff --git a/libsecurity_cryptkit/ckutils/ckutilsPlatform.h b/Security/libsecurity_cryptkit/ckutils/ckutilsPlatform.h similarity index 100% rename from libsecurity_cryptkit/ckutils/ckutilsPlatform.h rename to Security/libsecurity_cryptkit/ckutils/ckutilsPlatform.h diff --git a/libsecurity_cryptkit/ckutils/giantAsmBench/Makefile b/Security/libsecurity_cryptkit/ckutils/giantAsmBench/Makefile similarity index 100% rename from libsecurity_cryptkit/ckutils/giantAsmBench/Makefile rename to Security/libsecurity_cryptkit/ckutils/giantAsmBench/Makefile diff --git a/libsecurity_cryptkit/ckutils/giantAsmBench/giantAsmBench.c b/Security/libsecurity_cryptkit/ckutils/giantAsmBench/giantAsmBench.c similarity index 83% rename from libsecurity_cryptkit/ckutils/giantAsmBench/giantAsmBench.c rename to Security/libsecurity_cryptkit/ckutils/giantAsmBench/giantAsmBench.c index 0760c292..2f5a0872 100644 --- a/libsecurity_cryptkit/ckutils/giantAsmBench/giantAsmBench.c +++ b/Security/libsecurity_cryptkit/ckutils/giantAsmBench/giantAsmBench.c @@ -1,13 +1,27 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * giantAsmBench.c - Benchmark of platform-specific giantInteger primitives. +/* + * Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * - * Revision History - * ---------------- - * 18 Apr 98 Doug Mitchell at Apple - * Created. + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include #include #include diff --git a/libsecurity_cryptkit/ckutils/giantBench/Makefile b/Security/libsecurity_cryptkit/ckutils/giantBench/Makefile similarity index 100% rename from libsecurity_cryptkit/ckutils/giantBench/Makefile rename to Security/libsecurity_cryptkit/ckutils/giantBench/Makefile diff --git a/libsecurity_cryptkit/ckutils/giantBench/giantBench.c b/Security/libsecurity_cryptkit/ckutils/giantBench/giantBench.c similarity index 83% rename from libsecurity_cryptkit/ckutils/giantBench/giantBench.c rename to Security/libsecurity_cryptkit/ckutils/giantBench/giantBench.c index 465ea422..989a613c 100644 --- a/libsecurity_cryptkit/ckutils/giantBench/giantBench.c +++ b/Security/libsecurity_cryptkit/ckutils/giantBench/giantBench.c @@ -1,13 +1,27 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * giantBench.c - Benchmark of NSGiantInteger primitives. +/* + * Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * - * Revision History - * ---------------- - * 13 Apr 98 Doug Mitchell at Apple - * Created. + * @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 "giantIntegers.h" #include "ckutilities.h" #include "feeFunctions.h" diff --git a/libsecurity_cryptkit/ckutils/giantDvt/Makefile b/Security/libsecurity_cryptkit/ckutils/giantDvt/Makefile similarity index 100% rename from libsecurity_cryptkit/ckutils/giantDvt/Makefile rename to Security/libsecurity_cryptkit/ckutils/giantDvt/Makefile diff --git a/libsecurity_cryptkit/ckutils/giantDvt/giantDvt.c b/Security/libsecurity_cryptkit/ckutils/giantDvt/giantDvt.c similarity index 92% rename from libsecurity_cryptkit/ckutils/giantDvt/giantDvt.c rename to Security/libsecurity_cryptkit/ckutils/giantDvt/giantDvt.c index cfcd51f5..4e9047c2 100644 --- a/libsecurity_cryptkit/ckutils/giantDvt/giantDvt.c +++ b/Security/libsecurity_cryptkit/ckutils/giantDvt/giantDvt.c @@ -1,13 +1,27 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * giantDvt.c - DVT of NSGiantInteger primitives. +/* + * Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * - * Revision History - * ---------------- - * 09 Apr 98 Doug Mitchell at Apple - * Created. + * @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 "giantIntegers.h" #include "ckutilities.h" #include "feeFunctions.h" diff --git a/libsecurity_cryptkit/ckutils/sigTime/Makefile b/Security/libsecurity_cryptkit/ckutils/sigTime/Makefile similarity index 100% rename from libsecurity_cryptkit/ckutils/sigTime/Makefile rename to Security/libsecurity_cryptkit/ckutils/sigTime/Makefile diff --git a/libsecurity_cryptkit/ckutils/sigTime/sigTime.cpp b/Security/libsecurity_cryptkit/ckutils/sigTime/sigTime.cpp similarity index 100% rename from libsecurity_cryptkit/ckutils/sigTime/sigTime.cpp rename to Security/libsecurity_cryptkit/ckutils/sigTime/sigTime.cpp diff --git a/libsecurity_cryptkit/lib/ByteRep.txt b/Security/libsecurity_cryptkit/lib/ByteRep.txt similarity index 100% rename from libsecurity_cryptkit/lib/ByteRep.txt rename to Security/libsecurity_cryptkit/lib/ByteRep.txt diff --git a/libsecurity_cryptkit/lib/CipherFileDES.c b/Security/libsecurity_cryptkit/lib/CipherFileDES.c similarity index 97% rename from libsecurity_cryptkit/lib/CipherFileDES.c rename to Security/libsecurity_cryptkit/lib/CipherFileDES.c index 28593507..f4554ea9 100644 --- a/libsecurity_cryptkit/lib/CipherFileDES.c +++ b/Security/libsecurity_cryptkit/lib/CipherFileDES.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,9 +12,9 @@ * * Revision History * ---------------- - * 24 Jun 97 Doug Mitchell at Apple + * 24 Jun 97 at Apple * Fixed memory leaks via sigData - * 18 Feb 97 Doug Mitchell at Apple + * 18 Feb 97 at Apple * Split off from feeCipherFile.c */ diff --git a/libsecurity_cryptkit/lib/CipherFileDES.h b/Security/libsecurity_cryptkit/lib/CipherFileDES.h similarity index 87% rename from libsecurity_cryptkit/lib/CipherFileDES.h rename to Security/libsecurity_cryptkit/lib/CipherFileDES.h index 8f73474e..78139888 100644 --- a/libsecurity_cryptkit/lib/CipherFileDES.h +++ b/Security/libsecurity_cryptkit/lib/CipherFileDES.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 18 Feb 97 Doug Mitchell at Apple + * 18 Feb 97 at Apple * Created. */ diff --git a/libsecurity_cryptkit/lib/CipherFileFEED.c b/Security/libsecurity_cryptkit/lib/CipherFileFEED.c similarity index 96% rename from libsecurity_cryptkit/lib/CipherFileFEED.c rename to Security/libsecurity_cryptkit/lib/CipherFileFEED.c index d11a2338..ce9e075a 100644 --- a/libsecurity_cryptkit/lib/CipherFileFEED.c +++ b/Security/libsecurity_cryptkit/lib/CipherFileFEED.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,9 +12,9 @@ * * Revision History * ---------------- - * 24 Jun 97 Doug Mitchell at Apple + * 24 Jun 97 at Apple * Fixed memory leaks via sigData - * 18 Feb 97 Doug Mitchell at Apple + * 18 Feb 97 at Apple * Split off from feeCipherFile.c */ diff --git a/libsecurity_cryptkit/lib/CipherFileFEED.h b/Security/libsecurity_cryptkit/lib/CipherFileFEED.h similarity index 87% rename from libsecurity_cryptkit/lib/CipherFileFEED.h rename to Security/libsecurity_cryptkit/lib/CipherFileFEED.h index e6c165d0..5e6890bc 100644 --- a/libsecurity_cryptkit/lib/CipherFileFEED.h +++ b/Security/libsecurity_cryptkit/lib/CipherFileFEED.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 18 Feb 97 Doug Mitchell at Apple + * 18 Feb 97 at Apple * Created. */ diff --git a/libsecurity_cryptkit/lib/CipherFileTypes.h b/Security/libsecurity_cryptkit/lib/CipherFileTypes.h similarity index 88% rename from libsecurity_cryptkit/lib/CipherFileTypes.h rename to Security/libsecurity_cryptkit/lib/CipherFileTypes.h index 27b09bc1..e0307dc9 100644 --- a/libsecurity_cryptkit/lib/CipherFileTypes.h +++ b/Security/libsecurity_cryptkit/lib/CipherFileTypes.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -14,7 +14,7 @@ * ---------------- * 8/24/98 ap * Added tags around #endif comment. - * 19 Feb 97 Doug Mitchell at NeXT + * 19 Feb 97 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/Crypt.h b/Security/libsecurity_cryptkit/lib/Crypt.h similarity index 83% rename from libsecurity_cryptkit/lib/Crypt.h rename to Security/libsecurity_cryptkit/lib/Crypt.h index 4af8afa1..29a47d58 100644 --- a/libsecurity_cryptkit/lib/Crypt.h +++ b/Security/libsecurity_cryptkit/lib/Crypt.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -14,9 +14,9 @@ * ---------------- * 8/24/98 ap * Added tags around #endif comment. - * 28 May 1996 Doug Mitchell at Apple + * 28 May 1996 at Apple * Added falloc.h, newly exported API. - * 27 Aug 1996 Doug Mitchell at NeXT + * 27 Aug 1996 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/CryptKit.def b/Security/libsecurity_cryptkit/lib/CryptKit.def similarity index 100% rename from libsecurity_cryptkit/lib/CryptKit.def rename to Security/libsecurity_cryptkit/lib/CryptKit.def diff --git a/libsecurity_cryptkit/lib/CryptKit.h b/Security/libsecurity_cryptkit/lib/CryptKit.h similarity index 80% rename from libsecurity_cryptkit/lib/CryptKit.h rename to Security/libsecurity_cryptkit/lib/CryptKit.h index c641a901..6c6f2bc5 100644 --- a/libsecurity_cryptkit/lib/CryptKit.h +++ b/Security/libsecurity_cryptkit/lib/CryptKit.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** diff --git a/libsecurity_cryptkit/lib/CryptKitAsn1.cpp b/Security/libsecurity_cryptkit/lib/CryptKitAsn1.cpp similarity index 100% rename from libsecurity_cryptkit/lib/CryptKitAsn1.cpp rename to Security/libsecurity_cryptkit/lib/CryptKitAsn1.cpp diff --git a/libsecurity_cryptkit/lib/CryptKitAsn1.h b/Security/libsecurity_cryptkit/lib/CryptKitAsn1.h similarity index 100% rename from libsecurity_cryptkit/lib/CryptKitAsn1.h rename to Security/libsecurity_cryptkit/lib/CryptKitAsn1.h diff --git a/libsecurity_cryptkit/lib/CryptKitDER.cpp b/Security/libsecurity_cryptkit/lib/CryptKitDER.cpp similarity index 99% rename from libsecurity_cryptkit/lib/CryptKitDER.cpp rename to Security/libsecurity_cryptkit/lib/CryptKitDER.cpp index bf1bb334..e6fe06ab 100644 --- a/libsecurity_cryptkit/lib/CryptKitDER.cpp +++ b/Security/libsecurity_cryptkit/lib/CryptKitDER.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -20,7 +20,6 @@ * CryptKitDER.h - snacc-based routines to create and parse DER-encoded FEE * keys and signatures * - * Created 3/12/2001 by dmitch. */ #include "ckconfig.h" diff --git a/libsecurity_cryptkit/lib/CryptKitDER.h b/Security/libsecurity_cryptkit/lib/CryptKitDER.h similarity index 82% rename from libsecurity_cryptkit/lib/CryptKitDER.h rename to Security/libsecurity_cryptkit/lib/CryptKitDER.h index 9ecd44b1..b826b6b3 100644 --- a/libsecurity_cryptkit/lib/CryptKitDER.h +++ b/Security/libsecurity_cryptkit/lib/CryptKitDER.h @@ -1,10 +1,27 @@ /* - * CryptKitDER.h - snacc-based routines to create and parse DER-encoded FEE - * keys and signatures + * Copyright (c) 2001,2011,2014 Apple Inc. All Rights Reserved. * - * Created 3/12/2001 by dmitch. + * @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 _CRYPTKIT_DER_H_ #define _CRYPTKIT_DER_H_ diff --git a/Security/libsecurity_cryptkit/lib/CryptKitSA.h b/Security/libsecurity_cryptkit/lib/CryptKitSA.h new file mode 100644 index 00000000..b5a902c8 --- /dev/null +++ b/Security/libsecurity_cryptkit/lib/CryptKitSA.h @@ -0,0 +1,23 @@ +/* Copyright (c) 1998-2004,2011,2014 Apple Inc. All Rights Reserved. + * + * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT + * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, + * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL + * EXPOSE YOU TO LIABILITY. + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/FEEDaffine.nb b/Security/libsecurity_cryptkit/lib/CurveParamDocs/FEEDaffine.nb similarity index 100% rename from libsecurity_cryptkit/lib/CurveParamDocs/FEEDaffine.nb rename to Security/libsecurity_cryptkit/lib/CurveParamDocs/FEEDaffine.nb diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/FEEDsansY.nb b/Security/libsecurity_cryptkit/lib/CurveParamDocs/FEEDsansY.nb similarity index 100% rename from libsecurity_cryptkit/lib/CurveParamDocs/FEEDsansY.nb rename to Security/libsecurity_cryptkit/lib/CurveParamDocs/FEEDsansY.nb diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/README b/Security/libsecurity_cryptkit/lib/CurveParamDocs/README similarity index 100% rename from libsecurity_cryptkit/lib/CurveParamDocs/README rename to Security/libsecurity_cryptkit/lib/CurveParamDocs/README diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/curvegen.c b/Security/libsecurity_cryptkit/lib/CurveParamDocs/curvegen.c similarity index 100% rename from libsecurity_cryptkit/lib/CurveParamDocs/curvegen.c rename to Security/libsecurity_cryptkit/lib/CurveParamDocs/curvegen.c diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/curverecords.nb b/Security/libsecurity_cryptkit/lib/CurveParamDocs/curverecords.nb similarity index 100% rename from libsecurity_cryptkit/lib/CurveParamDocs/curverecords.nb rename to Security/libsecurity_cryptkit/lib/CurveParamDocs/curverecords.nb diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/disc.h b/Security/libsecurity_cryptkit/lib/CurveParamDocs/disc.h similarity index 100% rename from libsecurity_cryptkit/lib/CurveParamDocs/disc.h rename to Security/libsecurity_cryptkit/lib/CurveParamDocs/disc.h diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/ellproj.c b/Security/libsecurity_cryptkit/lib/CurveParamDocs/ellproj.c similarity index 100% rename from libsecurity_cryptkit/lib/CurveParamDocs/ellproj.c rename to Security/libsecurity_cryptkit/lib/CurveParamDocs/ellproj.c diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/ellproj.h b/Security/libsecurity_cryptkit/lib/CurveParamDocs/ellproj.h similarity index 100% rename from libsecurity_cryptkit/lib/CurveParamDocs/ellproj.h rename to Security/libsecurity_cryptkit/lib/CurveParamDocs/ellproj.h diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/factor.c b/Security/libsecurity_cryptkit/lib/CurveParamDocs/factor.c similarity index 100% rename from libsecurity_cryptkit/lib/CurveParamDocs/factor.c rename to Security/libsecurity_cryptkit/lib/CurveParamDocs/factor.c diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/fmodule.c b/Security/libsecurity_cryptkit/lib/CurveParamDocs/fmodule.c similarity index 100% rename from libsecurity_cryptkit/lib/CurveParamDocs/fmodule.c rename to Security/libsecurity_cryptkit/lib/CurveParamDocs/fmodule.c diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/fmodule.h b/Security/libsecurity_cryptkit/lib/CurveParamDocs/fmodule.h similarity index 100% rename from libsecurity_cryptkit/lib/CurveParamDocs/fmodule.h rename to Security/libsecurity_cryptkit/lib/CurveParamDocs/fmodule.h diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/giants.c b/Security/libsecurity_cryptkit/lib/CurveParamDocs/giants.c similarity index 100% rename from libsecurity_cryptkit/lib/CurveParamDocs/giants.c rename to Security/libsecurity_cryptkit/lib/CurveParamDocs/giants.c diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/giants.h b/Security/libsecurity_cryptkit/lib/CurveParamDocs/giants.h similarity index 100% rename from libsecurity_cryptkit/lib/CurveParamDocs/giants.h rename to Security/libsecurity_cryptkit/lib/CurveParamDocs/giants.h diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/schoof.c b/Security/libsecurity_cryptkit/lib/CurveParamDocs/schoof.c similarity index 100% rename from libsecurity_cryptkit/lib/CurveParamDocs/schoof.c rename to Security/libsecurity_cryptkit/lib/CurveParamDocs/schoof.c diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/schoofs.c b/Security/libsecurity_cryptkit/lib/CurveParamDocs/schoofs.c similarity index 100% rename from libsecurity_cryptkit/lib/CurveParamDocs/schoofs.c rename to Security/libsecurity_cryptkit/lib/CurveParamDocs/schoofs.c diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/tools.c b/Security/libsecurity_cryptkit/lib/CurveParamDocs/tools.c similarity index 100% rename from libsecurity_cryptkit/lib/CurveParamDocs/tools.c rename to Security/libsecurity_cryptkit/lib/CurveParamDocs/tools.c diff --git a/libsecurity_cryptkit/lib/CurveParamDocs/tools.h b/Security/libsecurity_cryptkit/lib/CurveParamDocs/tools.h similarity index 100% rename from libsecurity_cryptkit/lib/CurveParamDocs/tools.h rename to Security/libsecurity_cryptkit/lib/CurveParamDocs/tools.h diff --git a/libsecurity_cryptkit/lib/ECDSA_Profile.h b/Security/libsecurity_cryptkit/lib/ECDSA_Profile.h similarity index 86% rename from libsecurity_cryptkit/lib/ECDSA_Profile.h rename to Security/libsecurity_cryptkit/lib/ECDSA_Profile.h index d0be400c..eb7a7cc9 100644 --- a/libsecurity_cryptkit/lib/ECDSA_Profile.h +++ b/Security/libsecurity_cryptkit/lib/ECDSA_Profile.h @@ -3,9 +3,8 @@ Contains: ECDSA Profiling support. - Written by: Doug Mitchell - Copyright: Copyright 1998 by Apple Computer, Inc., all rights reserved. + Copyright: Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. Change History (most recent first): @@ -14,12 +13,12 @@ To Do: */ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** diff --git a/libsecurity_cryptkit/lib/ECDSA_Verify_Prefix.h b/Security/libsecurity_cryptkit/lib/ECDSA_Verify_Prefix.h similarity index 100% rename from libsecurity_cryptkit/lib/ECDSA_Verify_Prefix.h rename to Security/libsecurity_cryptkit/lib/ECDSA_Verify_Prefix.h diff --git a/libsecurity_cryptkit/lib/HmacSha1Legacy.c b/Security/libsecurity_cryptkit/lib/HmacSha1Legacy.c similarity index 96% rename from libsecurity_cryptkit/lib/HmacSha1Legacy.c rename to Security/libsecurity_cryptkit/lib/HmacSha1Legacy.c index 90ae6c09..83e77619 100644 --- a/libsecurity_cryptkit/lib/HmacSha1Legacy.c +++ b/Security/libsecurity_cryptkit/lib/HmacSha1Legacy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,8 +19,7 @@ /* File: HmacSha1Legacy.c Contains: HMAC/SHA1, bug-for-bug compatible with BSAFE 4.0. - Copyright: (C) 2001 by Apple Computer, Inc., all rights reserved - Written by: Doug Mitchell + Copyright (c) 2001,2011-2014 Apple Inc. All Rights Reserved. */ #include "ckconfig.h" diff --git a/libsecurity_cryptkit/lib/HmacSha1Legacy.h b/Security/libsecurity_cryptkit/lib/HmacSha1Legacy.h similarity index 92% rename from libsecurity_cryptkit/lib/HmacSha1Legacy.h rename to Security/libsecurity_cryptkit/lib/HmacSha1Legacy.h index a2889fdb..691ca5bb 100644 --- a/libsecurity_cryptkit/lib/HmacSha1Legacy.h +++ b/Security/libsecurity_cryptkit/lib/HmacSha1Legacy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -19,8 +19,7 @@ /* File: HmacSha1Legacy.h Contains: HMAC/SHA1, bug-for-bug compatible a legacy implementation. - Copyright: (C) 2001 by Apple Computer, Inc., all rights reserved - Written by: Doug Mitchell + Copyright (c) 2001,2011-2014 Apple Inc. All Rights Reserved. */ #ifndef __HMAC_SHA1_LEGACY__ #define __HMAC_SHA1_LEGACY__ diff --git a/libsecurity_cryptkit/lib/Mathematica.FEE b/Security/libsecurity_cryptkit/lib/Mathematica.FEE similarity index 100% rename from libsecurity_cryptkit/lib/Mathematica.FEE rename to Security/libsecurity_cryptkit/lib/Mathematica.FEE diff --git a/libsecurity_cryptkit/lib/NSCipherFile.h b/Security/libsecurity_cryptkit/lib/NSCipherFile.h similarity index 93% rename from libsecurity_cryptkit/lib/NSCipherFile.h rename to Security/libsecurity_cryptkit/lib/NSCipherFile.h index a1d21bc8..13f103c5 100644 --- a/libsecurity_cryptkit/lib/NSCipherFile.h +++ b/Security/libsecurity_cryptkit/lib/NSCipherFile.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 28 Oct 96 Doug Mitchell at NeXT + * 28 Oct 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/NSCipherFile.m b/Security/libsecurity_cryptkit/lib/NSCipherFile.m similarity index 96% rename from libsecurity_cryptkit/lib/NSCipherFile.m rename to Security/libsecurity_cryptkit/lib/NSCipherFile.m index 000b00e3..93598d72 100644 --- a/libsecurity_cryptkit/lib/NSCipherFile.m +++ b/Security/libsecurity_cryptkit/lib/NSCipherFile.m @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 28 Oct 96 Doug Mitchell at NeXT + * 28 Oct 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/NSCryptors.h b/Security/libsecurity_cryptkit/lib/NSCryptors.h similarity index 90% rename from libsecurity_cryptkit/lib/NSCryptors.h rename to Security/libsecurity_cryptkit/lib/NSCryptors.h index 81b22862..33935a7d 100644 --- a/libsecurity_cryptkit/lib/NSCryptors.h +++ b/Security/libsecurity_cryptkit/lib/NSCryptors.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** diff --git a/libsecurity_cryptkit/lib/NSDESCryptor.h b/Security/libsecurity_cryptkit/lib/NSDESCryptor.h similarity index 81% rename from libsecurity_cryptkit/lib/NSDESCryptor.h rename to Security/libsecurity_cryptkit/lib/NSDESCryptor.h index 0590ff27..6f3ed08b 100644 --- a/libsecurity_cryptkit/lib/NSDESCryptor.h +++ b/Security/libsecurity_cryptkit/lib/NSDESCryptor.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** diff --git a/libsecurity_cryptkit/lib/NSDESCryptor.m b/Security/libsecurity_cryptkit/lib/NSDESCryptor.m similarity index 90% rename from libsecurity_cryptkit/lib/NSDESCryptor.m rename to Security/libsecurity_cryptkit/lib/NSDESCryptor.m index 3e3d566f..2e071b2e 100644 --- a/libsecurity_cryptkit/lib/NSDESCryptor.m +++ b/Security/libsecurity_cryptkit/lib/NSDESCryptor.m @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,9 +12,9 @@ * * Revision History * ---------------- - * 28 Mar 97 Doug Mitchell at Apple + * 28 Mar 97 at Apple * Rewrote using feeDES module. - * 22 Feb 96 Blaine Garst at NeXT + * 22 Feb 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/NSFEEPublicKey.h b/Security/libsecurity_cryptkit/lib/NSFEEPublicKey.h similarity index 88% rename from libsecurity_cryptkit/lib/NSFEEPublicKey.h rename to Security/libsecurity_cryptkit/lib/NSFEEPublicKey.h index 8cebd4d2..42377a28 100644 --- a/libsecurity_cryptkit/lib/NSFEEPublicKey.h +++ b/Security/libsecurity_cryptkit/lib/NSFEEPublicKey.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 27 Feb 1997 Doug Mitchell at Apple + * 27 Feb 1997 at Apple * Broke out from NSCryptors.h. */ diff --git a/libsecurity_cryptkit/lib/NSFEEPublicKey.m b/Security/libsecurity_cryptkit/lib/NSFEEPublicKey.m similarity index 97% rename from libsecurity_cryptkit/lib/NSFEEPublicKey.m rename to Security/libsecurity_cryptkit/lib/NSFEEPublicKey.m index 3e99d642..034af79d 100644 --- a/libsecurity_cryptkit/lib/NSFEEPublicKey.m +++ b/Security/libsecurity_cryptkit/lib/NSFEEPublicKey.m @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,9 +12,9 @@ * * Revision History * ---------------- - * 17 Jul 97 Doug Mitchell at Apple + * 17 Jul 97 at Apple * Added ECDSA signature routines. - * 21 Aug 96 Doug Mitchell at NeXT + * 21 Aug 96 at NeXT * Modified to use C-only FeePublicKey module. * ???? 1994 Blaine Garst at NeXT * Created. diff --git a/Security/libsecurity_cryptkit/lib/NSFEEPublicKeyPrivate.h b/Security/libsecurity_cryptkit/lib/NSFEEPublicKeyPrivate.h new file mode 100644 index 00000000..37576972 --- /dev/null +++ b/Security/libsecurity_cryptkit/lib/NSFEEPublicKeyPrivate.h @@ -0,0 +1,36 @@ +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. + * + * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT + * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, + * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL + * EXPOSE YOU TO LIABILITY. + *************************************************************************** + * + * NSFEEPublicKeyPrivate.h + * + * Revision History + * ---------------- + * 21 Aug 96 at NeXT + * Created. + */ + +#import "NSFEEPublicKey.h" +#import "elliptic.h" +#import "feeDebug.h" +#import "feePublicKey.h" + +@interface NSFEEPublicKey(Private) + +- (key)minus; +- (key)plus; +#if 0 +- (NSData *)privData; +#endif 0 +- (feePubKey)feePubKey; + +#if FEE_DEBUG +- (void)dump; +#endif FEE_DEBUG +@end diff --git a/libsecurity_cryptkit/lib/NSMD5Hash.h b/Security/libsecurity_cryptkit/lib/NSMD5Hash.h similarity index 75% rename from libsecurity_cryptkit/lib/NSMD5Hash.h rename to Security/libsecurity_cryptkit/lib/NSMD5Hash.h index 468832c6..1553a496 100644 --- a/libsecurity_cryptkit/lib/NSMD5Hash.h +++ b/Security/libsecurity_cryptkit/lib/NSMD5Hash.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 28 Mar 97 Doug Mitchell at Apple + * 28 Mar 97 at Apple * Created. */ diff --git a/libsecurity_cryptkit/lib/NSMD5Hash.m b/Security/libsecurity_cryptkit/lib/NSMD5Hash.m similarity index 84% rename from libsecurity_cryptkit/lib/NSMD5Hash.m rename to Security/libsecurity_cryptkit/lib/NSMD5Hash.m index 30eed334..8e372be7 100644 --- a/libsecurity_cryptkit/lib/NSMD5Hash.m +++ b/Security/libsecurity_cryptkit/lib/NSMD5Hash.m @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 28 Mar 97 Doug Mitchell at Apple + * 28 Mar 97 at Apple * Created. */ diff --git a/libsecurity_cryptkit/lib/NSRandomNumberGenerator.h b/Security/libsecurity_cryptkit/lib/NSRandomNumberGenerator.h similarity index 76% rename from libsecurity_cryptkit/lib/NSRandomNumberGenerator.h rename to Security/libsecurity_cryptkit/lib/NSRandomNumberGenerator.h index bb76867e..1de469cd 100644 --- a/libsecurity_cryptkit/lib/NSRandomNumberGenerator.h +++ b/Security/libsecurity_cryptkit/lib/NSRandomNumberGenerator.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 28 Mar 97 Doug Mitchell at Apple + * 28 Mar 97 at Apple * Simplified. * ?? 96 Blaine Garst at NeXT * Created. diff --git a/libsecurity_cryptkit/lib/NSRandomNumberGenerator.m b/Security/libsecurity_cryptkit/lib/NSRandomNumberGenerator.m similarity index 85% rename from libsecurity_cryptkit/lib/NSRandomNumberGenerator.m rename to Security/libsecurity_cryptkit/lib/NSRandomNumberGenerator.m index 6a969bda..4d92fc55 100644 --- a/libsecurity_cryptkit/lib/NSRandomNumberGenerator.m +++ b/Security/libsecurity_cryptkit/lib/NSRandomNumberGenerator.m @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 28 Mar 97 Doug Mitchell at Apple + * 28 Mar 97 at Apple * Rewrote using feeRandom module. * ?? 96 Blaine Garst at NeXT * Created. diff --git a/Security/libsecurity_cryptkit/lib/README b/Security/libsecurity_cryptkit/lib/README new file mode 100644 index 00000000..e4b8f04a --- /dev/null +++ b/Security/libsecurity_cryptkit/lib/README @@ -0,0 +1,221 @@ + Apple FEE Library Source, v. 1.0 + Last Update: 26 Sep 2001 + + + NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT + TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE + SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE + ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL + EXPOSE YOU TO LIABILITY. + + +This directory contains the source code for Apple's Fast Elliptic +Encryption (FEE) library. All code is written in ANSI C. A UNIX +Makefile is provided. + +Note that all source files in this directory are best viewed with an +editor configured for 8-space tabs, a fixed pitch font, and a window +of at least 80 characters in width. + + +Public Header Files +------------------- + +These files contain the public API used by clients of the FEE library. + + Crypt.h + ------- + A top-level header which includes all of the other public headers. + Typically a client application will only include this file. + + feeTypes.h + ---------- + Common #defines and typedefs used throughout the library. + + feePublicKey.h + -------------- + Functions for generating and manipulating FEE public and private keys, + performing key exchange, and high-level digital signature operations. + + feeDigitalSignature.h + --------------------- + Low-level primitives for performing ElGamal digital signature + operations. Not normally used by clients; high-level functions + for performing signature operations are provided in feePublicKey.h. + + feeECDSA.h + ---------- + Low-level primitives for performing ECDSA digital signature operations. + Not normally used by clients; high-level functions for performing + signature operations are provided in feePublicKey.h. + + feeDES.h + -------- + DES symmetric encryption and decryption functions. + + feeHash.h + --------- + MD5 Hash functions. + + ckSHA1.h + ------ + SHA-1 hash functions. + + feeRandom.h + ----------- + Pseudo-random number generator. + + feeFunctions.h + -------------- + General-purpose C functions. + + feeFEED.h + --------- + Asymmetric encryption functions using the FEE Direct Embedding, + or FEED, algorithm. + + feeFEEDExp.h + ------------ + Asymmetric encryption functions using the Expanding FEED algorithm. + + enc64.h + ------- + Functions for performing encoding and decoding via base-64 IA5 + format, per RFC 1421. + + feeCipherFile.h + CipherFileTypes.h + ------------------ + High-level CipherFile support. Provides encapsulation of ciphertext, + digital signature, and public key strings in a portable format. + + falloc.h + -------- + Memory alloc/free routines. All memory mallocd by CryptKit and + returned to called must be freed via ffree(), declared here. + + +'C' Files +--------- + +In addition to the '.c' files associated with the abovementioned public +headers (e.g., feePublicKey.c, feeCipherFile.c), the FEE library +contains the following source files: + + giantIntegers.[ch] + -------------------- + Large-precision integer arithmetic package. + + elliptic.[ch] + ------------- + Elliptic Curve algebra, Apple "FEE" style. + + ellipticProj.[ch] + ----------------- + Elliptic Curve Algebra using projective coordinates. + + curveParams.[ch], curveParamData.h + ---------------------------------- + Elliptic curve parameters. Declarations of known curves. + + byteRep.[ch] + ------------ + Platform-independent implement implementation of portable + representation of all aggregate data types used in FEE library. + + ckutilities.[ch] + -------------- + Miscellaneous C utilities. + + feeCipherFileAtom.c + CipherFileDES.c + CipherFileFEED.c + ---------------- + CipherFile support. + + ckDES.c + ckMD5.c + ckSHA1_priv.c + ----------- + Low-level primitives for DES, MD5, SHA-1 algorithms. + + +Porting to other platforms +-------------------------- + +The FEE library has been built and tested on the Macintosh platform using Metrowerks CodeWarrior, on the OpenStep OS on both the 68k and Pentium platforms, and on Windows NT (on which it was built using the Gnu gcc compiler). + +There are at least 3 files which need to be edited in order to port the +FEE library to other platforms. One is platform.c. This file has two +platform-specific functions: + + void NSGiantRaise(const char *reason); + + This function is called interally in the library in the unlikely + event of a fatal runtime error. The current versions of this + function use printf() to log the reason and call exit(1). + + unsigned createRandomSeed(); + + This function obtains a 32-bit number with which FEE's + pseudo-random number generator is seeded. The implementation + of this function is highly platform-specific and also depends + on the amount of security required from the RNG in a + particular application. Common (and simple) implementations + involve obtaining a high-precision system clock, process + ID values. etc. + + Note that this function is called during a call to feeRandAlloc() + in feeRandom.c. Clients of the FEE library can also avoid this + mechanism by instantiating the RNG via feeRandAllocWithSeed(), + passing in an application-specific seed. + +The file platform.h contains a definition for the endianness of the +current platform. Either __BIG_ENDIAN__ or __LITTLE_ENDIAN__ must +be #defined at compile time. If your compiler does not implicitly +define one of these symbols, edit platform.h appropriately. + +Another file which may be modified during a port is falloc.c. All +memory allocation calls in the library are performed via fmalloc() and +ffree() in falloc.c. The current implementation of falloc.c merely +passes these calls on to the standard malloc() and free(). A port to +another platform may require the use of different memory allocators. + +The giantIntegers module, which implements large integer arithmetic, +allows for specification of platform-dependent digit size. In addition, +provisions are made for implementation of platform-dependent routines +to perform low-level digit arithmetic (single and double precision add, +subtract with carry, double precision multiply, multiply an array +of digits by another digit). The current library contains assembly +languange macros for the Intel and PPC platforms. The specification of +the size of a giant digit, type giantDigit, is found in giantIntegers.h. +The files which use low-level platform-dependent giant arithmentic +include giantPortCommon.h, which select one of several possible header +files. The header giantPortGeneric.h can be specified; this has +no assembly language, but implements the necessary functions using +the C "unsigned long long" type and static lines functions. The API for +the low-level digit functions is the same in all three of the following +files: + + giantPortGeneric.h + giantPort_i486.h + giantPort_PPC.h + +Currently, the implementation of the PPC-specific giant digit routines +is in giantPort_PPC.c; the implementation of the Intels-specific giant +routines is found in both giantPort_i486.h and giantPort_i486.s. + +Building the library +-------------------- + +This directory contains a UNIX Makefile. Just type 'make' in the current +(writable) directory to build the library. The result is libFEE.a. + + + Copyright (c) 1998 Apple Inc. All rights reserved. + +Apple and Macintosh are trademarks of Apple Computer, Inc., registered +in the U.S.A. and other countries. OpenStep is a trademark of NeXT +Software, Inc. registered in the U.S.A. and other countries. All other +trademarks are the property of their respective owners. diff --git a/libsecurity_cryptkit/lib/TOP_README b/Security/libsecurity_cryptkit/lib/TOP_README similarity index 95% rename from libsecurity_cryptkit/lib/TOP_README rename to Security/libsecurity_cryptkit/lib/TOP_README index cf6207e4..b177be81 100644 --- a/libsecurity_cryptkit/lib/TOP_README +++ b/Security/libsecurity_cryptkit/lib/TOP_README @@ -22,7 +22,7 @@ editor configured for 8-space tabs, a fixed pitch font, and a window of at least 80 characters in width. - Copyright (c) 1998 Apple Computer, Inc. All rights reserved. + Copyright (c) 1998 Apple Inc. All rights reserved. Apple and Macintosh are trademarks of Apple Computer, Inc., registered in the U.S.A. and other countries. OpenStep is a trademark of NeXT diff --git a/libsecurity_cryptkit/lib/buildSrcTree b/Security/libsecurity_cryptkit/lib/buildSrcTree similarity index 100% rename from libsecurity_cryptkit/lib/buildSrcTree rename to Security/libsecurity_cryptkit/lib/buildSrcTree diff --git a/libsecurity_cryptkit/lib/byteRep.c b/Security/libsecurity_cryptkit/lib/byteRep.c similarity index 96% rename from libsecurity_cryptkit/lib/byteRep.c rename to Security/libsecurity_cryptkit/lib/byteRep.c index a6f07c2f..f24f6d80 100644 --- a/libsecurity_cryptkit/lib/byteRep.c +++ b/Security/libsecurity_cryptkit/lib/byteRep.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -14,13 +14,13 @@ * ---------------- * 10/06/98 ap * Changed to compile with C++. - * 18 Apr 98 Doug Mitchell at Apple + * 18 Apr 98 at Apple * Mods for variable size giantDigit. - * 20 Jan 98 Doug Mitchell at Apple + * 20 Jan 98 at Apple * Added curve param fields for CURVE_PARAM_VERSION 2. - * 17 Jul 97 Doug Mitchell at Apple + * 17 Jul 97 at Apple * Added signature routines. - * 9 Jan 97 Doug Mitchell at NeXT + * 9 Jan 97 at NeXT * Split off from utilities.c */ diff --git a/libsecurity_cryptkit/lib/byteRep.h b/Security/libsecurity_cryptkit/lib/byteRep.h similarity index 87% rename from libsecurity_cryptkit/lib/byteRep.h rename to Security/libsecurity_cryptkit/lib/byteRep.h index 71bb45ae..134f0482 100644 --- a/libsecurity_cryptkit/lib/byteRep.h +++ b/Security/libsecurity_cryptkit/lib/byteRep.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,9 +12,9 @@ * * Revision History * ---------------- - * 17 Jul 97 Doug Mitchell at Apple + * 17 Jul 97 at Apple * Added signature routines. - * 9 Jan 97 Doug Mitchell at NeXT + * 9 Jan 97 at NeXT * Split off from ckutilities.h */ diff --git a/libsecurity_cryptkit/lib/changes b/Security/libsecurity_cryptkit/lib/changes similarity index 100% rename from libsecurity_cryptkit/lib/changes rename to Security/libsecurity_cryptkit/lib/changes diff --git a/libsecurity_cryptkit/lib/ckDES.c b/Security/libsecurity_cryptkit/lib/ckDES.c similarity index 97% rename from libsecurity_cryptkit/lib/ckDES.c rename to Security/libsecurity_cryptkit/lib/ckDES.c index 713f9d47..983f59e1 100644 --- a/libsecurity_cryptkit/lib/ckDES.c +++ b/Security/libsecurity_cryptkit/lib/ckDES.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,18 +12,17 @@ * * Revision History * ---------------- - * 11/03/98 Michael Brouwer at Apple * Added braces to static array definition of si[][]. * 10/06/98 ap * Changed to compile with C++. - * 28 May 98 Doug Mitchel at Apple + * 28 May 98 at Apple * Changed to use platform-dependent fmalloc(), ffree() - * 31 Mar 97 Doug Mitchell at Apple + * 31 Mar 97 at Apple * Put per-instance data in struct _desInst * Changed setkey() to dessetkey() to avoid collision with libc version - * 21 Aug 96 Doug Mitchell at NeXT + * 21 Aug 96 at NeXT * Broke out from NSDESCryptor.m - * 22 Feb 96 Blaine Garst at NeXT + * 22 Feb 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/ckDES.h b/Security/libsecurity_cryptkit/lib/ckDES.h similarity index 84% rename from libsecurity_cryptkit/lib/ckDES.h rename to Security/libsecurity_cryptkit/lib/ckDES.h index 0cd9d7ff..8f1da0a2 100644 --- a/libsecurity_cryptkit/lib/ckDES.h +++ b/Security/libsecurity_cryptkit/lib/ckDES.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,11 +12,11 @@ * * Revision History * ---------------- - * 31 Mar 97 Doug Mitchell at Apple + * 31 Mar 97 at Apple * Put per-instance data in struct _desInst - * 21 Aug 96 Doug Mitchell at NeXT + * 21 Aug 96 at NeXT * Broke out from NSDESCryptor.m - * 22 Feb 96 Blaine Garst at NeXT + * 22 Feb 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/ckMD5.c b/Security/libsecurity_cryptkit/lib/ckMD5.c similarity index 97% rename from libsecurity_cryptkit/lib/ckMD5.c rename to Security/libsecurity_cryptkit/lib/ckMD5.c index 6d59f3d1..76f61d19 100644 --- a/libsecurity_cryptkit/lib/ckMD5.c +++ b/Security/libsecurity_cryptkit/lib/ckMD5.c @@ -3,7 +3,7 @@ Written by: Colin Plumb - Copyright: Copyright 1998 by Apple Computer, Inc., all rights reserved. + Copyright: Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. Change History (most recent first): @@ -12,12 +12,12 @@ To Do: */ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -45,7 +45,7 @@ /* * Revision History * ---------------- - * 06 Feb 1997 Doug Mitchell at Apple + * 06 Feb 1997 at Apple * Fixed endian-dependent cast in MD5Final() * Made byteReverse() tolerant of platform-dependent alignment * restrictions diff --git a/libsecurity_cryptkit/lib/ckMD5.h b/Security/libsecurity_cryptkit/lib/ckMD5.h similarity index 87% rename from libsecurity_cryptkit/lib/ckMD5.h rename to Security/libsecurity_cryptkit/lib/ckMD5.h index 251a89d9..a4833b37 100644 --- a/libsecurity_cryptkit/lib/ckMD5.h +++ b/Security/libsecurity_cryptkit/lib/ckMD5.h @@ -3,7 +3,7 @@ Written by: Colin Plumb - Copyright: Copyright 1998 by Apple Computer, Inc., all rights reserved. + Copyright: Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. Change History (most recent first): @@ -12,12 +12,12 @@ To Do: */ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** diff --git a/libsecurity_cryptkit/lib/ckSHA1.c b/Security/libsecurity_cryptkit/lib/ckSHA1.c similarity index 94% rename from libsecurity_cryptkit/lib/ckSHA1.c rename to Security/libsecurity_cryptkit/lib/ckSHA1.c index 1da6b492..94a20a6a 100644 --- a/libsecurity_cryptkit/lib/ckSHA1.c +++ b/Security/libsecurity_cryptkit/lib/ckSHA1.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -14,7 +14,7 @@ * ---------------- * 10/06/98 ap * Changed to compile with C++. - * 07 Jan 1998 Doug Mitchell at Apple + * 07 Jan 1998 at Apple * Created. */ diff --git a/libsecurity_cryptkit/lib/ckSHA1.h b/Security/libsecurity_cryptkit/lib/ckSHA1.h similarity index 84% rename from libsecurity_cryptkit/lib/ckSHA1.h rename to Security/libsecurity_cryptkit/lib/ckSHA1.h index 4fd08316..de101716 100644 --- a/libsecurity_cryptkit/lib/ckSHA1.h +++ b/Security/libsecurity_cryptkit/lib/ckSHA1.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 05 Jan 1998 Doug Mitchell at Apple + * 05 Jan 1998 at Apple * Created. */ diff --git a/libsecurity_cryptkit/lib/ckSHA1_priv.c b/Security/libsecurity_cryptkit/lib/ckSHA1_priv.c similarity index 97% rename from libsecurity_cryptkit/lib/ckSHA1_priv.c rename to Security/libsecurity_cryptkit/lib/ckSHA1_priv.c index 356a07e3..4ea15ae0 100644 --- a/libsecurity_cryptkit/lib/ckSHA1_priv.c +++ b/Security/libsecurity_cryptkit/lib/ckSHA1_priv.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 05 Jan 1998 Doug Mitchell at Apple + * 05 Jan 1998 at Apple * Created, based on source by Peter C. Gutmann. * Mods: made reentrant, added NIST fix to expand(), eliminated * unnecessary copy to local W[] array. diff --git a/libsecurity_cryptkit/lib/ckSHA1_priv.h b/Security/libsecurity_cryptkit/lib/ckSHA1_priv.h similarity index 84% rename from libsecurity_cryptkit/lib/ckSHA1_priv.h rename to Security/libsecurity_cryptkit/lib/ckSHA1_priv.h index d3d953bb..05cb9cb6 100644 --- a/libsecurity_cryptkit/lib/ckSHA1_priv.h +++ b/Security/libsecurity_cryptkit/lib/ckSHA1_priv.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 22 Aug 96 Doug Mitchell at NeXT + * 22 Aug 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/ckconfig.h b/Security/libsecurity_cryptkit/lib/ckconfig.h similarity index 91% rename from libsecurity_cryptkit/lib/ckconfig.h rename to Security/libsecurity_cryptkit/lib/ckconfig.h index 9deb12e6..c1737ea6 100644 --- a/libsecurity_cryptkit/lib/ckconfig.h +++ b/Security/libsecurity_cryptkit/lib/ckconfig.h @@ -3,9 +3,8 @@ Contains: Common config info. - Written by: Doug Mitchell - Copyright: Copyright 1998 by Apple Computer, Inc. + Copyright: Copyright (c) 1998,2011,2014 Apple Inc. All rights reserved. Change History (most recent first): @@ -15,12 +14,12 @@ To Do: */ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** diff --git a/libsecurity_cryptkit/lib/ckutilities.c b/Security/libsecurity_cryptkit/lib/ckutilities.c similarity index 95% rename from libsecurity_cryptkit/lib/ckutilities.c rename to Security/libsecurity_cryptkit/lib/ckutilities.c index 9774e600..bbbe252b 100644 --- a/libsecurity_cryptkit/lib/ckutilities.c +++ b/Security/libsecurity_cryptkit/lib/ckutilities.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011-2012,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -14,21 +14,21 @@ * ---------------- * 10/06/98 ap * Changed to compile with C++. - * 08 Apr 98 Doug Mitchell at Apple + * 08 Apr 98 at Apple * Mods for variable size giantDigit. * Rewrote serializeGiant(), deserializeGiant() to conform to IEEE P1363. - * 23 Mar 98 Doug Mitchell at Apple + * 23 Mar 98 at Apple * Added FR_WrongSignatureType, FR_BadKeyBlob to frtnStrings. * Added initCryptKit(). - * 19 Jan 98 Doug Mitchell at Apple + * 19 Jan 98 at Apple * Added cStringToUc() - * 09 Jan 98 Doug Mitchell at Apple + * 09 Jan 98 at Apple * Added non-FEE_DEBUG version of printGiantHex() - * 27 Jan 97 Doug Mitchell at NeXT + * 27 Jan 97 at NeXT * Addd serializeGiant(), deserializeGiant; Deleted data_to_giant() - * 12 Dec 96 Doug Mitchell at NeXT + * 12 Dec 96 at NeXT * Added byteRepTo{int,key,giant}(). - * 2 Aug 96 Doug Mitchell at NeXT + * 2 Aug 96 at NeXT * Broke out from Blaine Garst's original NSCryptors.m */ diff --git a/libsecurity_cryptkit/lib/ckutilities.h b/Security/libsecurity_cryptkit/lib/ckutilities.h similarity index 80% rename from libsecurity_cryptkit/lib/ckutilities.h rename to Security/libsecurity_cryptkit/lib/ckutilities.h index f74f3788..8bf8a228 100644 --- a/libsecurity_cryptkit/lib/ckutilities.h +++ b/Security/libsecurity_cryptkit/lib/ckutilities.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -14,7 +14,7 @@ * ---------------- * 10/06/98 ap * Changed to compile with C++. - * 2 Aug 96 Doug Mitchell at NeXT + * 2 Aug 96 at NeXT * Broke out from Blaine Garst's original NSCryptors.m */ diff --git a/libsecurity_cryptkit/lib/curveParamData.h b/Security/libsecurity_cryptkit/lib/curveParamData.h similarity index 100% rename from libsecurity_cryptkit/lib/curveParamData.h rename to Security/libsecurity_cryptkit/lib/curveParamData.h diff --git a/libsecurity_cryptkit/lib/curveParamDataOld.h b/Security/libsecurity_cryptkit/lib/curveParamDataOld.h similarity index 100% rename from libsecurity_cryptkit/lib/curveParamDataOld.h rename to Security/libsecurity_cryptkit/lib/curveParamDataOld.h diff --git a/libsecurity_cryptkit/lib/curveParams.c b/Security/libsecurity_cryptkit/lib/curveParams.c similarity index 98% rename from libsecurity_cryptkit/lib/curveParams.c rename to Security/libsecurity_cryptkit/lib/curveParams.c index cce030b5..94ec2195 100644 --- a/libsecurity_cryptkit/lib/curveParams.c +++ b/Security/libsecurity_cryptkit/lib/curveParams.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -14,23 +14,23 @@ * ---------------- * 10/06/98 ap * Changed to compile with C++. - * 9 Sep 98 Doug Mitchell at NeXT + * 9 Sep 98 at NeXT * Added y1Plus for IEEE P1363 compliance. * Added curveParamsInferFields(). - * 08 Apr 98 Doug Mitchell at Apple + * 08 Apr 98 at Apple * Mods for giantDigit. - * 20 Jan 98 Doug Mitchell at Apple + * 20 Jan 98 at Apple * Added primeType, m, basePrimeRecip; added a few PT_GENERAL curves. - * 19 Jan 1998 Doug Mitchell at Apple + * 19 Jan 1998 at Apple * New curve: q=160, k=57 - * 09 Jan 1998 Doug Mitchell at Apple + * 09 Jan 1998 at Apple * Removed obsolete (i.e., incomplete) curves parameters. - * 11 Jun 1997 Doug Mitchell at Apple + * 11 Jun 1997 at Apple * Added x1OrderPlusRecip and lesserX1OrderRecip fields * Added curveParamsInitGiants() - * 9 Jan 1997 Doug Mitchell at NeXT + * 9 Jan 1997 at NeXT * Major mods for IEEE-style parameters. - * 7 Aug 1996 Doug Mitchell at NeXT + * 7 Aug 1996 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/curveParams.h b/Security/libsecurity_cryptkit/lib/curveParams.h similarity index 93% rename from libsecurity_cryptkit/lib/curveParams.h rename to Security/libsecurity_cryptkit/lib/curveParams.h index bac245ca..47a87756 100644 --- a/libsecurity_cryptkit/lib/curveParams.h +++ b/Security/libsecurity_cryptkit/lib/curveParams.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011-2012,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,16 +12,16 @@ * * Revision History * ---------------- - * 9 Sep 98 Doug Mitchell at NeXT + * 9 Sep 98 at NeXT * Added y1Plus for IEEE P1363 compliance. - * 20 Jan 98 Doug Mitchell at Apple + * 20 Jan 98 at Apple * Added primeType, m, basePrimeRecip. - * 11 Jun 97 Doug Mitchell at Apple + * 11 Jun 97 at Apple * Added x1OrderPlusRecip and lesserX1OrderRecip * Disabled CP_SET_GIANT_SIZE hack - * 9 Jan 1997 Doug Mitchell at NeXT + * 9 Jan 1997 at NeXT * Major mods for IEEE-style parameters. - * 7 Aug 1996 Doug Mitchell at NeXT + * 7 Aug 1996 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/elliptic.c b/Security/libsecurity_cryptkit/lib/elliptic.c similarity index 97% rename from libsecurity_cryptkit/lib/elliptic.c rename to Security/libsecurity_cryptkit/lib/elliptic.c index c025e8ee..3f45d199 100644 --- a/libsecurity_cryptkit/lib/elliptic.c +++ b/Security/libsecurity_cryptkit/lib/elliptic.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -32,48 +32,47 @@ ------------------------------------------- 10/06/98 ap Changed to compile with C++. - 9 Sep 98 Doug Mitchell at Apple + 9 Sep 98 at Apple cp->curveType optimizations. Removed code which handled "unknown" curve orders. elliptic() now exported for timing measurements. - 21 Apr 98 Doug Mitchell at Apple + 21 Apr 98 at Apple Used inline platform-dependent giant arithmetic. - 20 Jan 98 Doug Mitchell at Apple + 20 Jan 98 at Apple feemod now handles PT_MERSENNE, PT_FEE, PT_GENERAL. Added calcGiantSizes(), rewrote giantMinBytes(), giantMaxShorts(). Updated heading comments on FEE curve algebra. - 11 Jan 98 Doug Mitchell and Richard Crandall at Apple + 11 Jan 98 at Apple Microscopic feemod optimization. - 10 Jan 98 Doug Mitchell and Richard Crandall at Apple + 10 Jan 98 at Apple ell_odd, ell_even() Montgomery optimization. - 09 Jan 98 Doug Mitchell and Richard Crandall at Apple + 09 Jan 98 at Apple ell_odd, ell_even() Atkin3 optimization. - 08 Jan 97 Doug Mitchell at Apple + 08 Jan 97 at Apple Cleaned up some debugging code; added gsquareTime - 11 Jun 97 Doug Mitchell and Richard Crandall at Apple + 11 Jun 97 at Apple Mods for modg_via_recip(), divg_via_recip() math Deleted a lot of obsolete code (previously ifdef'd out) Added lesserX1OrderJustify(), x1OrderPlusJustify() Added binvg_cp(), avoiding general modg in favor of feemod - 05 Feb 97 Doug Mitchell and Richard Crandall at Apple + 05 Feb 97 at Apple New optimized numer_plus(), denom_double(), and numer_times() All calls to borrowGiant() and newGiant have explicit giant size - 08 Jan 97 Doug Mitchell and Richard Crandall at NeXT + 08 Jan 97 at NeXT Major mods to accomodate IEEE-style curve parameters. New functions feepowermodg() and curveOrderJustify(); elliptic_add(), elliptic(), signature_compare(), and which_curve() completely rewritten. - 19 Dec 96 Doug Mitchell at NeXT + 19 Dec 96 at NeXT Added mersennePrimes[24..26] - 08 Aug 96 Doug Mitchell at NeXT + 08 Aug 96 at NeXT Fixed giant leak in elliptic_add() - 05 Aug 96 Doug Mitchell at NeXT + 05 Aug 96 at NeXT Removed dead code - 24 Jul 96 Doug Mitchell at NeXT + 24 Jul 96 at NeXT Added ENGINE_127_BITS dependency for use of security engine - 24 Oct 92 Richard Crandall at NeXT + 24 Oct 92 at NeXT Modified new_public_from_private() - 1991 Richard Crandall at NeXT Created. diff --git a/libsecurity_cryptkit/lib/elliptic.h b/Security/libsecurity_cryptkit/lib/elliptic.h similarity index 93% rename from libsecurity_cryptkit/lib/elliptic.h rename to Security/libsecurity_cryptkit/lib/elliptic.h index 04d2383d..5b955194 100644 --- a/libsecurity_cryptkit/lib/elliptic.h +++ b/Security/libsecurity_cryptkit/lib/elliptic.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -14,7 +14,7 @@ * ---------------- * 10/06/98 ap * Changed to compile with C++. - * 19 Feb 97 Doug Mitchell at NeXT + * 19 Feb 97 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/ellipticMeasure.h b/Security/libsecurity_cryptkit/lib/ellipticMeasure.h similarity index 85% rename from libsecurity_cryptkit/lib/ellipticMeasure.h rename to Security/libsecurity_cryptkit/lib/ellipticMeasure.h index 73c614f9..ed5e36c9 100644 --- a/libsecurity_cryptkit/lib/ellipticMeasure.h +++ b/Security/libsecurity_cryptkit/lib/ellipticMeasure.h @@ -3,9 +3,8 @@ Contains: xxx put contents here xxx - Written by: Doug Mitchell - Copyright: Copyright 1998 by Apple Computer, Inc. + Copyright: Copyright (c) 1998,2011,2014 Apple Inc. All rights reserved. Change History (most recent first): @@ -15,12 +14,12 @@ To Do: */ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** diff --git a/libsecurity_cryptkit/lib/ellipticProj.c b/Security/libsecurity_cryptkit/lib/ellipticProj.c similarity index 97% rename from libsecurity_cryptkit/lib/ellipticProj.c rename to Security/libsecurity_cryptkit/lib/ellipticProj.c index d4d3ada5..bdb24316 100644 --- a/libsecurity_cryptkit/lib/ellipticProj.c +++ b/Security/libsecurity_cryptkit/lib/ellipticProj.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 1 Sep 1998 Doug Mitchell and Richard Crandall at Apple + * 1 Sep 1998 at Apple * Created. * ************************************************************** @@ -56,7 +56,6 @@ REFERENCES - Crandall R and Pomerance C 1998, "Prime numbers: a computational perspective," Springer-Verlag, manuscript Solinas J 1998, IEEE P1363 Annex A (draft standard) diff --git a/libsecurity_cryptkit/lib/ellipticProj.h b/Security/libsecurity_cryptkit/lib/ellipticProj.h similarity index 88% rename from libsecurity_cryptkit/lib/ellipticProj.h rename to Security/libsecurity_cryptkit/lib/ellipticProj.h index 3dfc3288..c71add72 100644 --- a/libsecurity_cryptkit/lib/ellipticProj.h +++ b/Security/libsecurity_cryptkit/lib/ellipticProj.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -14,7 +14,7 @@ * ---------------- * 10/06/98 ap * Changed to compile with C++. - * 1 Sep 1998 Doug Mitchell at Apple + * 1 Sep 1998 at Apple * Created. */ diff --git a/libsecurity_cryptkit/lib/enc64.c b/Security/libsecurity_cryptkit/lib/enc64.c similarity index 97% rename from libsecurity_cryptkit/lib/enc64.c rename to Security/libsecurity_cryptkit/lib/enc64.c index 46de4710..f49a8d6b 100644 --- a/libsecurity_cryptkit/lib/enc64.c +++ b/Security/libsecurity_cryptkit/lib/enc64.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -16,9 +16,9 @@ * Added ECDSA_VERIFY_ONLY dependencies. * 10/06/98 ap * Changed to compile with C++. - * 12 Dec 96 Doug Mitchell at NeXT + * 12 Dec 96 at NeXT * Newlines optional in dec64() and isValidEnc64(). - * 9 Oct 96 Doug Mitchell at NeXT + * 9 Oct 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/enc64.h b/Security/libsecurity_cryptkit/lib/enc64.h similarity index 86% rename from libsecurity_cryptkit/lib/enc64.h rename to Security/libsecurity_cryptkit/lib/enc64.h index bdf32cae..2a52ea24 100644 --- a/libsecurity_cryptkit/lib/enc64.h +++ b/Security/libsecurity_cryptkit/lib/enc64.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 9 Oct 96 Doug Mitchell at NeXT + * 9 Oct 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/engineNSA127.c b/Security/libsecurity_cryptkit/lib/engineNSA127.c similarity index 96% rename from libsecurity_cryptkit/lib/engineNSA127.c rename to Security/libsecurity_cryptkit/lib/engineNSA127.c index 2c0cc3a1..0e8ea4af 100644 --- a/libsecurity_cryptkit/lib/engineNSA127.c +++ b/Security/libsecurity_cryptkit/lib/engineNSA127.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -31,7 +31,6 @@ BELOW UNLESS YOU ARE EXPLICITLY AUTHORIZED TO DO SO BY NeXT OR ITS DESIGNEE. - R. E. Crandall c. 1996, NeXT Software, Inc. All Rights Reserved. */ @@ -63,19 +62,19 @@ * ---------------- * 10/06/98 ap * Changed to compile with C++. - * 6 Aug 06 Doug Mitchell at NeXT + * 6 Aug 06 at NeXT * 'a' argument to elliptic() and ell_even() is now a giant. - * 25 Jul 96 Richard Crandall and Doug Mitchell at NeXT + * 25 Jul 96 at NeXT * Wrapped ENGINEmul() with gmersennemod(127,.) to guarantee no * overflow in the hard-coded mul. * Fixed sign calculation bug in ENGINEmul(). - * 24 Jul 96 Doug Mitchell at NeXT + * 24 Jul 96 at NeXT * Made conditional on ENGINE_127_BITS. * Made all functions except for elliptic() static. * Renamed some giants function calls via #define. * Deleted use of array of static pseudo-giants. * Cosmetic changes for debuggability. - * 19 Jun 96 Richard Crandall at NeXT + * 19 Jun 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/falloc.c b/Security/libsecurity_cryptkit/lib/falloc.c similarity index 88% rename from libsecurity_cryptkit/lib/falloc.c rename to Security/libsecurity_cryptkit/lib/falloc.c index b19237c0..8a41af7b 100644 --- a/libsecurity_cryptkit/lib/falloc.c +++ b/Security/libsecurity_cryptkit/lib/falloc.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,9 +12,9 @@ * * Revision History * ---------------- - * 28 May 98 Doug Mitchell at Apple + * 28 May 98 at Apple * Added Mac-specific allocators from temp memory - * 20 Aug 96 Doug Mitchell at NeXT + * 20 Aug 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/falloc.h b/Security/libsecurity_cryptkit/lib/falloc.h similarity index 82% rename from libsecurity_cryptkit/lib/falloc.h rename to Security/libsecurity_cryptkit/lib/falloc.h index 56adfaef..dba207c5 100644 --- a/libsecurity_cryptkit/lib/falloc.h +++ b/Security/libsecurity_cryptkit/lib/falloc.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 20 Aug 96 Doug Mitchell at NeXT + * 20 Aug 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/feeCipherFile.c b/Security/libsecurity_cryptkit/lib/feeCipherFile.c similarity index 95% rename from libsecurity_cryptkit/lib/feeCipherFile.c rename to Security/libsecurity_cryptkit/lib/feeCipherFile.c index 4edde3d4..9c79156d 100644 --- a/libsecurity_cryptkit/lib/feeCipherFile.c +++ b/Security/libsecurity_cryptkit/lib/feeCipherFile.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,9 +12,9 @@ * * Revision History * ---------------- - * 05 Feb 97 Doug Mitchell at Apple + * 05 Feb 97 at Apple * Added CFE_FEED and CFE_FEEDExp types. - * 24 Oct 96 Doug Mitchell at NeXT + * 24 Oct 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/feeCipherFile.h b/Security/libsecurity_cryptkit/lib/feeCipherFile.h similarity index 95% rename from libsecurity_cryptkit/lib/feeCipherFile.h rename to Security/libsecurity_cryptkit/lib/feeCipherFile.h index 2c67f51d..a46f3baf 100644 --- a/libsecurity_cryptkit/lib/feeCipherFile.h +++ b/Security/libsecurity_cryptkit/lib/feeCipherFile.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 24 Oct 96 Doug Mitchell at NeXT + * 24 Oct 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/feeCipherFileAtom.c b/Security/libsecurity_cryptkit/lib/feeCipherFileAtom.c similarity index 97% rename from libsecurity_cryptkit/lib/feeCipherFileAtom.c rename to Security/libsecurity_cryptkit/lib/feeCipherFileAtom.c index a68aecd7..3576551d 100644 --- a/libsecurity_cryptkit/lib/feeCipherFileAtom.c +++ b/Security/libsecurity_cryptkit/lib/feeCipherFileAtom.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -14,9 +14,9 @@ * ---------------- * 10/06/98 ap * Changed to compile with C++. - * 05 Feb 97 Doug Mitchell at Apple + * 05 Feb 97 at Apple * Modified to use portable byte representation. - * 23 Oct 96 Doug Mitchell at NeXT + * 23 Oct 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/feeDES.c b/Security/libsecurity_cryptkit/lib/feeDES.c similarity index 97% rename from libsecurity_cryptkit/lib/feeDES.c rename to Security/libsecurity_cryptkit/lib/feeDES.c index 632457a5..57cc150a 100644 --- a/libsecurity_cryptkit/lib/feeDES.c +++ b/Security/libsecurity_cryptkit/lib/feeDES.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -14,11 +14,11 @@ * ---------------- * 10/06/98 ap * Changed to compile with C++. - * 05 Jan 98 Doug Mitchell at Apple + * 05 Jan 98 at Apple * Avoid a bcopy() on encrypt/decrypt of each block - * 31 Mar 97 Doug Mitchell at Apple + * 31 Mar 97 at Apple * New per-instance API for DES.c - * 26 Aug 96 Doug Mitchell at NeXT + * 26 Aug 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/feeDES.h b/Security/libsecurity_cryptkit/lib/feeDES.h similarity index 92% rename from libsecurity_cryptkit/lib/feeDES.h rename to Security/libsecurity_cryptkit/lib/feeDES.h index 299e805a..07a8da9c 100644 --- a/libsecurity_cryptkit/lib/feeDES.h +++ b/Security/libsecurity_cryptkit/lib/feeDES.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 26 Aug 96 Doug Mitchell at NeXT + * 26 Aug 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/feeDebug.h b/Security/libsecurity_cryptkit/lib/feeDebug.h similarity index 93% rename from libsecurity_cryptkit/lib/feeDebug.h rename to Security/libsecurity_cryptkit/lib/feeDebug.h index 8cd39fd2..878e3c77 100644 --- a/libsecurity_cryptkit/lib/feeDebug.h +++ b/Security/libsecurity_cryptkit/lib/feeDebug.h @@ -3,9 +3,8 @@ Contains: Debug macros. - Written by: Doug Mitchell - Copyright: Copyright 1998 by Apple Computer, Inc. + Copyright: Copyright (c) 1998,2011,2014 Apple Inc. All rights reserved. Change History (most recent first): @@ -15,12 +14,12 @@ To Do: */ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** diff --git a/libsecurity_cryptkit/lib/feeDigitalSignature.c b/Security/libsecurity_cryptkit/lib/feeDigitalSignature.c similarity index 97% rename from libsecurity_cryptkit/lib/feeDigitalSignature.c rename to Security/libsecurity_cryptkit/lib/feeDigitalSignature.c index 08ccc5ae..0fdc48a9 100644 --- a/libsecurity_cryptkit/lib/feeDigitalSignature.c +++ b/Security/libsecurity_cryptkit/lib/feeDigitalSignature.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -14,15 +14,15 @@ * ---------------- * 10/06/98 ap * Changed to compile with C++. - * 9 Sep 98 Doug Mitchell at NeXT + * 9 Sep 98 at NeXT * Major changes to use projective elliptic algebra for * Weierstrass curves. - * 15 Jan 97 Doug Mitchell at NeXT + * 15 Jan 97 at NeXT * FEE_SIG_VERSION = 3 (removed code for compatibilty with all older * versions). * Was modg(), is curveOrderJustify() * Use plus curve for ellipic algebra per IEEE standards - * 22 Aug 96 Doug Mitchell at NeXT + * 22 Aug 96 at NeXT * Ported guts of Blaine Garst's NSFEEDigitalSignature.m to C. */ diff --git a/libsecurity_cryptkit/lib/feeDigitalSignature.h b/Security/libsecurity_cryptkit/lib/feeDigitalSignature.h similarity index 91% rename from libsecurity_cryptkit/lib/feeDigitalSignature.h rename to Security/libsecurity_cryptkit/lib/feeDigitalSignature.h index 3f9b1b22..7429cbab 100644 --- a/libsecurity_cryptkit/lib/feeDigitalSignature.h +++ b/Security/libsecurity_cryptkit/lib/feeDigitalSignature.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 22 Aug 96 Doug Mitchell at NeXT + * 22 Aug 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/feeECDSA.c b/Security/libsecurity_cryptkit/lib/feeECDSA.c similarity index 97% rename from libsecurity_cryptkit/lib/feeECDSA.c rename to Security/libsecurity_cryptkit/lib/feeECDSA.c index c312bf45..6c8600e6 100644 --- a/libsecurity_cryptkit/lib/feeECDSA.c +++ b/Security/libsecurity_cryptkit/lib/feeECDSA.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -16,11 +16,10 @@ * Added ECDSA_VERIFY_ONLY dependencies. * 10/06/98 ap * Changed to compile with C++. - * 3 Sep 98 Doug Mitchell at Apple + * 3 Sep 98 at Apple * Rewrote using projective elliptic algebra, per IEEE P1363. - * 17 Dec 97 Doug Mitchell at Apple + * 17 Dec 97 at Apple * Fixed c==0 bug in feeECDSAVerify() - * 16 Jul 97 Doug Mitchell at Apple, based on algorithms by Richard Crandall * Created. */ diff --git a/libsecurity_cryptkit/lib/feeECDSA.h b/Security/libsecurity_cryptkit/lib/feeECDSA.h similarity index 88% rename from libsecurity_cryptkit/lib/feeECDSA.h rename to Security/libsecurity_cryptkit/lib/feeECDSA.h index d092bb85..3d402e13 100644 --- a/libsecurity_cryptkit/lib/feeECDSA.h +++ b/Security/libsecurity_cryptkit/lib/feeECDSA.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 16 Jul 97 Doug Mitchell at Apple + * 16 Jul 97 at Apple * Created. */ diff --git a/libsecurity_cryptkit/lib/feeFEED.c b/Security/libsecurity_cryptkit/lib/feeFEED.c similarity index 98% rename from libsecurity_cryptkit/lib/feeFEED.c rename to Security/libsecurity_cryptkit/lib/feeFEED.c index ecefc79d..144f7345 100644 --- a/libsecurity_cryptkit/lib/feeFEED.c +++ b/Security/libsecurity_cryptkit/lib/feeFEED.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -14,15 +14,15 @@ * ---------------- * 10/06/98 ap * Changed to compile with C++. - * 20 Jan 1998 Doug Mitchell at Apple + * 20 Jan 1998 at Apple * Mods for primeType == PT_GENERAL case. - * 12 Jun 1997 Doug Mitchell at Apple + * 12 Jun 1997 at Apple * Was curveOrderJustify(), is lesserX1OrderJustify() - * 31 Mar 1997 Doug Mitchell at Apple + * 31 Mar 1997 at Apple * Fixed initialRS leak - * 3 Mar 1997 Doug Mitchell at Apple + * 3 Mar 1997 at Apple * Trimmed plainBlockSize by one byte if q mod 8 = 0 - * 30 Jan 1997 Doug Mitchell at NeXT + * 30 Jan 1997 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/feeFEED.h b/Security/libsecurity_cryptkit/lib/feeFEED.h similarity index 93% rename from libsecurity_cryptkit/lib/feeFEED.h rename to Security/libsecurity_cryptkit/lib/feeFEED.h index e825e480..ce84de8a 100644 --- a/libsecurity_cryptkit/lib/feeFEED.h +++ b/Security/libsecurity_cryptkit/lib/feeFEED.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 28 Aug 96 Doug Mitchell at NeXT + * 28 Aug 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/feeFEEDExp.c b/Security/libsecurity_cryptkit/lib/feeFEEDExp.c similarity index 97% rename from libsecurity_cryptkit/lib/feeFEEDExp.c rename to Security/libsecurity_cryptkit/lib/feeFEEDExp.c index 685c2968..4126c2bb 100644 --- a/libsecurity_cryptkit/lib/feeFEEDExp.c +++ b/Security/libsecurity_cryptkit/lib/feeFEEDExp.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -14,19 +14,19 @@ * ---------------- * 10/06/98 ap * Changed to compile with C++. - * 20 Jan 1998 Doug Mitchell at Apple + * 20 Jan 1998 at Apple * Mods for primeType == PT_GENERAL case. - * 12 Jun 1997 Doug Mitchell at Apple + * 12 Jun 1997 at Apple * Was curveOrderJustify(), is lesserX1OrderJustify() - * 03 Mar 1997 Doug Mitchell at Apple + * 03 Mar 1997 at Apple * Trimmed plainBlockSize by one byte if q mod 8 = 0 - * 03 Feb 97 Doug Mitchell at NeXT + * 03 Feb 97 at NeXT * Renamed to feeFEEDExp.c * Justified random xaux to [2, minimumX1Order] * Added feeFEEDExpCipherTextSize() - * 15 Jan 97 Doug Mitchell at NeXT + * 15 Jan 97 at NeXT * Cleaned up which_curve/index code to use CURVE_MINUS/CURVE_PLUS - * 28 Aug 96 Doug Mitchell at NeXT + * 28 Aug 96 at NeXT * Created from Blaine Garst's NSFEECryptor.m. */ diff --git a/libsecurity_cryptkit/lib/feeFEEDExp.h b/Security/libsecurity_cryptkit/lib/feeFEEDExp.h similarity index 93% rename from libsecurity_cryptkit/lib/feeFEEDExp.h rename to Security/libsecurity_cryptkit/lib/feeFEEDExp.h index e20d2689..aa190379 100644 --- a/libsecurity_cryptkit/lib/feeFEEDExp.h +++ b/Security/libsecurity_cryptkit/lib/feeFEEDExp.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 28 Aug 96 Doug Mitchell at NeXT + * 28 Aug 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/feeFunctions.h b/Security/libsecurity_cryptkit/lib/feeFunctions.h similarity index 82% rename from libsecurity_cryptkit/lib/feeFunctions.h rename to Security/libsecurity_cryptkit/lib/feeFunctions.h index 6592bf23..928fb5c5 100644 --- a/libsecurity_cryptkit/lib/feeFunctions.h +++ b/Security/libsecurity_cryptkit/lib/feeFunctions.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011-2012,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -16,9 +16,9 @@ * Fixed previous check-in comment. * 8/24/98 ap * Added tags around #endif comment. - * 23 Mar 98 Doug Mitchell at Apple + * 23 Mar 98 at Apple * Added initCryptKit(). - * 27 Aug 96 Doug Mitchell at NeXT + * 27 Aug 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/feeHash.c b/Security/libsecurity_cryptkit/lib/feeHash.c similarity index 89% rename from libsecurity_cryptkit/lib/feeHash.c rename to Security/libsecurity_cryptkit/lib/feeHash.c index 2eef6431..b193af24 100644 --- a/libsecurity_cryptkit/lib/feeHash.c +++ b/Security/libsecurity_cryptkit/lib/feeHash.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -14,7 +14,7 @@ * ---------------- * 10/06/98 ap * Changed to compile with C++. - * 22 Aug 96 Doug Mitchell at NeXT + * 22 Aug 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/feeHash.h b/Security/libsecurity_cryptkit/lib/feeHash.h similarity index 86% rename from libsecurity_cryptkit/lib/feeHash.h rename to Security/libsecurity_cryptkit/lib/feeHash.h index 8cab22fc..bcb66398 100644 --- a/libsecurity_cryptkit/lib/feeHash.h +++ b/Security/libsecurity_cryptkit/lib/feeHash.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,7 +12,7 @@ * * Revision History * ---------------- - * 22 Aug 96 Doug Mitchell at NeXT + * 22 Aug 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/feePublicKey.c b/Security/libsecurity_cryptkit/lib/feePublicKey.c similarity index 98% rename from libsecurity_cryptkit/lib/feePublicKey.c rename to Security/libsecurity_cryptkit/lib/feePublicKey.c index e889bb00..3105723a 100644 --- a/libsecurity_cryptkit/lib/feePublicKey.c +++ b/Security/libsecurity_cryptkit/lib/feePublicKey.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011-2012,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -16,29 +16,29 @@ * Added ECDSA_VERIFY_ONLY dependencies. * 10/06/98 ap * Changed to compile with C++. - * 9 Sep 98 Doug Mitchell at NeXT + * 9 Sep 98 at NeXT * Major changes for IEEE P1363 compliance. - * 23 Mar 98 Doug Mitchell at Apple + * 23 Mar 98 at Apple * Added blob support. - * 21 Jan 98 Doug Mitchell at Apple + * 21 Jan 98 at Apple * Fixed feePubKeyBitsize bitlen bug for PT_GENERAL case. - * 05 Jan 98 Doug Mitchell at Apple + * 05 Jan 98 at Apple * ECDSA now uses SHA-1 hash. Imcompatible with old ECDSA signatures. - * 17 Jul 97 Doug Mitchell at Apple + * 17 Jul 97 at Apple * Added ECDSA signature routines. - * 12 Jun 97 Doug Mitchell at Apple + * 12 Jun 97 at Apple * Added feePubKeyInitGiants() * Deleted obsolete code * Changes for lesserX1OrderJustify (was curveOrderJustify) - * 31 Mar 97 Doug Mitchell at Apple + * 31 Mar 97 at Apple * Fixed leak in feePubKeyCreateKeyString() - * 15 Jan 97 Doug Mitchell at NeXT + * 15 Jan 97 at NeXT * PUBLIC_KEY_STRING_VERSION = 3; broke compatibility with all older * versions. * Cleaned up which_curve/index code to use CURVE_MINUS/CURVE_PLUS. - * 12 Dec 96 Doug Mitchell at NeXT + * 12 Dec 96 at NeXT * Added initFromEnc64KeyStr(). - * 20 Aug 96 Doug Mitchell at NeXT + * 20 Aug 96 at NeXT * Ported to C. * ???? 1994 Blaine Garst at NeXT * Created. diff --git a/libsecurity_cryptkit/lib/feePublicKey.h b/Security/libsecurity_cryptkit/lib/feePublicKey.h similarity index 96% rename from libsecurity_cryptkit/lib/feePublicKey.h rename to Security/libsecurity_cryptkit/lib/feePublicKey.h index 8b42e444..6f88fa62 100644 --- a/libsecurity_cryptkit/lib/feePublicKey.h +++ b/Security/libsecurity_cryptkit/lib/feePublicKey.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011-2012,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,11 +12,11 @@ * * Revision History * ---------------- - * 23 Mar 98 Doug Mitchell at Apple + * 23 Mar 98 at Apple * Added blob support. - * 17 Jul 97 Doug Mitchell at Apple + * 17 Jul 97 at Apple * Added ECDSA signature routines. - * 20 Aug 96 Doug Mitchell at NeXT + * 20 Aug 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/feePublicKeyPrivate.h b/Security/libsecurity_cryptkit/lib/feePublicKeyPrivate.h similarity index 79% rename from libsecurity_cryptkit/lib/feePublicKeyPrivate.h rename to Security/libsecurity_cryptkit/lib/feePublicKeyPrivate.h index 006deaf1..9aa2f2ad 100644 --- a/libsecurity_cryptkit/lib/feePublicKeyPrivate.h +++ b/Security/libsecurity_cryptkit/lib/feePublicKeyPrivate.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -14,7 +14,7 @@ * ---------------- * 10/06/98 ap * Changed to compile with C++. - * 28 Aug 96 Doug Mitchell at NeXT + * 28 Aug 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/feeRandom.c b/Security/libsecurity_cryptkit/lib/feeRandom.c similarity index 93% rename from libsecurity_cryptkit/lib/feeRandom.c rename to Security/libsecurity_cryptkit/lib/feeRandom.c index 0e11654f..1fedc6ca 100644 --- a/libsecurity_cryptkit/lib/feeRandom.c +++ b/Security/libsecurity_cryptkit/lib/feeRandom.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -14,11 +14,11 @@ * ---------------- * 10/06/98 ap * Changed to compile with C++. - * 19 Jun 97 Doug Mitchell at Apple + * 19 Jun 97 at Apple * Eliminated predictability of bytes 4 thru 15 of random data - * 18 Jun 97 Doug Mitchell at Apple + * 18 Jun 97 at Apple * Reduced size of per-instance giants from 128 to 32 shorts - * 23 Aug 96 Doug Mitchell at NeXT + * 23 Aug 96 at NeXT * Created, based on Blaine Garst's NSRandomNumberGenerator class */ diff --git a/libsecurity_cryptkit/lib/feeRandom.h b/Security/libsecurity_cryptkit/lib/feeRandom.h similarity index 81% rename from libsecurity_cryptkit/lib/feeRandom.h rename to Security/libsecurity_cryptkit/lib/feeRandom.h index a1953b3b..1bffef06 100644 --- a/libsecurity_cryptkit/lib/feeRandom.h +++ b/Security/libsecurity_cryptkit/lib/feeRandom.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -16,7 +16,7 @@ * Fixed previous check-in comment. * 8/24/98 ap * Added tags around #endif comment. - * 23 Aug 96 Doug Mitchell at NeXT + * 23 Aug 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/feeTypes.h b/Security/libsecurity_cryptkit/lib/feeTypes.h similarity index 93% rename from libsecurity_cryptkit/lib/feeTypes.h rename to Security/libsecurity_cryptkit/lib/feeTypes.h index a10f4db1..2f5229e4 100644 --- a/libsecurity_cryptkit/lib/feeTypes.h +++ b/Security/libsecurity_cryptkit/lib/feeTypes.h @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,13 +12,13 @@ * * Revision History * ---------------- - * 23 Mar 98 Doug Mitchell at Apple + * 23 Mar 98 at Apple * Added FR_BadKeyBlob. - * 20 Jan 98 Doug Mitchell at Apple + * 20 Jan 98 at Apple * New PT_GENERAL depth values. - * 09 Jan 98 Doug Mitchell at Apple + * 09 Jan 98 at Apple * Removed obsolete FEE_DEPTH_* values. - * 20 Aug 96 Doug Mitchell at NeXT + * 20 Aug 96 at NeXT * Created. */ diff --git a/libsecurity_cryptkit/lib/giantFFT.c b/Security/libsecurity_cryptkit/lib/giantFFT.c similarity index 97% rename from libsecurity_cryptkit/lib/giantFFT.c rename to Security/libsecurity_cryptkit/lib/giantFFT.c index 411a6d19..21e91983 100644 --- a/libsecurity_cryptkit/lib/giantFFT.c +++ b/Security/libsecurity_cryptkit/lib/giantFFT.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,11 +12,10 @@ Library for large-integer arithmetic via FFT. Currently unused in CryptKit. - R. E. Crandall, Scientific Computation Group, NeXT Computer, Inc. Revision History ---------------- - 19 Jan 1998 Doug Mitchell at Apple + 19 Jan 1998 at Apple Split off from NSGiantIntegers.c. */ diff --git a/libsecurity_cryptkit/lib/giantIntegers.c b/Security/libsecurity_cryptkit/lib/giantIntegers.c similarity index 97% rename from libsecurity_cryptkit/lib/giantIntegers.c rename to Security/libsecurity_cryptkit/lib/giantIntegers.c index d4cd7ccd..e7872b58 100644 --- a/libsecurity_cryptkit/lib/giantIntegers.c +++ b/Security/libsecurity_cryptkit/lib/giantIntegers.c @@ -1,9 +1,9 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. +/* Copyright (c) 1998,2011-2014 Apple Inc. All Rights Reserved. * * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL * EXPOSE YOU TO LIABILITY. *************************************************************************** @@ -12,24 +12,23 @@ Revision History ---------------- - 12/04/98 dmitch/R. Crandall Fixed a==b bug in addg(). 10/06/98 ap Changed to compile with C++. 13 Apr 98 Fixed shiftright(1) bug in modg_via_recip. - 09 Apr 98 Doug Mitchell at Apple + 09 Apr 98 at Apple Major rewrite of core arithmetic routines to make this module independent of size of giantDigit. Removed idivg() and radixdiv(). - 20 Jan 98 Doug Mitchell at Apple + 20 Jan 98 at Apple Deleted FFT arithmetic; simplified mulg(). - 09 Jan 98 Doug Mitchell and Richard Crandall at Apple + 09 Jan 98 at Apple gshiftright() optimization. - 08 Jan 98 Doug Mitchell at Apple + 08 Jan 98 at Apple newGiant() returns NULL on malloc failure - 24 Dec 97 Doug Mitchell and Richard Crandall at Apple + 24 Dec 97 at Apple New grammarSquare(); optimized modg_via_recip() - 11 Jun 97 Doug Mitchell and Richard Crandall at Apple + 11 Jun 97 at Apple Added modg_via_recip(), divg_via_recip(), make_recip() Added new multiple giant stack mechanism Fixed potential packing/alignment bug in copyGiant() @@ -38,29 +37,28 @@ Deleted newgiant() All calls to borrowGiant() now specify required size (no more borrowGiant(0) calls) - 08 May 97 Doug Mitchell at Apple + 08 May 97 at Apple Changed size of giantstruct.n to 1 for Mac build - 05 Feb 97 Doug Mitchell at Apple + 05 Feb 97 at Apple newGiant() no longer modifies CurrentMaxShorts or giant stack Added modg profiling - 01 Feb 97 Doug Mitchell at NeXT + 01 Feb 97 at NeXT Added iszero() check in gcompg - 17 Jan 97 Richard Crandall, Doug Mitchell at NeXT + 17 Jan 97 at NeXT Fixed negation bug in gmersennemod() Fixed n[words-1] == 0 bug in extractbits() Cleaned up lots of static declarations - 19 Sep 96 Doug Mitchell at NeXT + 19 Sep 96 at NeXT Fixed --size underflow bug in normal_subg(). - 4 Sep 96 Doug Mitchell at NeXT + 4 Sep 96 at NeXT Fixed (b + +/*** + *** Structs for declaring extension-specific data. + ***/ + +/* + * GeneralName, used in AuthorityKeyID, SubjectAltName, and + * IssuerAltName. + * + * For now, we just provide explicit support for the types which are + * represented as IA5Strings, OIDs, and octet strings. Constructed types + * such as EDIPartyName and x400Address are not explicitly handled + * right now and must be encoded and decoded by the caller. (See exception + * for Name and OtherName, below). In those cases the CE_GeneralName.name.Data field + * represents the BER contents octets; CE_GeneralName.name.Length is the + * length of the contents; the tag of the field is not needed - the BER + * encoding uses context-specific implicit tagging. The berEncoded field + * is set to CSSM_TRUE in these case. Simple types have berEncoded = CSSM_FALSE. + * + * In the case of a GeneralName in the form of a Name, we parse the Name + * into a CSSM_X509_NAME and place a pointer to the CSSM_X509_NAME in the + * CE_GeneralName.name.Data field. CE_GeneralName.name.Length is set to + * sizeof(CSSM_X509_NAME). In this case berEncoded is false. + * + * In the case of a GeneralName in the form of a OtherName, we parse the fields + * into a CE_OtherName and place a pointer to the CE_OtherName in the + * CE_GeneralName.name.Data field. CE_GeneralName.name.Length is set to + * sizeof(CE_OtherName). In this case berEncoded is false. + * + * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + * + * GeneralName ::= CHOICE { + * otherName [0] OtherName + * rfc822Name [1] IA5String, + * dNSName [2] IA5String, + * x400Address [3] ORAddress, + * directoryName [4] Name, + * ediPartyName [5] EDIPartyName, + * uniformResourceIdentifier [6] IA5String, + * iPAddress [7] OCTET STRING, + * registeredID [8] OBJECT IDENTIFIER} + * + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + * + * EDIPartyName ::= SEQUENCE { + * nameAssigner [0] DirectoryString OPTIONAL, + * partyName [1] DirectoryString } + */ +typedef enum __CE_GeneralNameType { + GNT_OtherName = 0, + GNT_RFC822Name, + GNT_DNSName, + GNT_X400Address, + GNT_DirectoryName, + GNT_EdiPartyName, + GNT_URI, + GNT_IPAddress, + GNT_RegisteredID +} CE_GeneralNameType; + +typedef struct __CE_OtherName { + CSSM_OID typeId; + CSSM_DATA value; // unparsed, BER-encoded +} CE_OtherName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct __CE_GeneralName { + CE_GeneralNameType nameType; // GNT_RFC822Name, etc. + CSSM_BOOL berEncoded; + CSSM_DATA name; +} CE_GeneralName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct __CE_GeneralNames { + uint32 numNames; + CE_GeneralName *generalName; +} CE_GeneralNames DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* + * id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } + * + * AuthorityKeyIdentifier ::= SEQUENCE { + * keyIdentifier [0] KeyIdentifier OPTIONAL, + * authorityCertIssuer [1] GeneralNames OPTIONAL, + * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } + * + * KeyIdentifier ::= OCTET STRING + * + * CSSM OID = CSSMOID_AuthorityKeyIdentifier + */ +typedef struct __CE_AuthorityKeyID { + CSSM_BOOL keyIdentifierPresent; + CSSM_DATA keyIdentifier; + CSSM_BOOL generalNamesPresent; + CE_GeneralNames *generalNames; + CSSM_BOOL serialNumberPresent; + CSSM_DATA serialNumber; +} CE_AuthorityKeyID DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* + * id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } + * SubjectKeyIdentifier ::= KeyIdentifier + * + * CSSM OID = CSSMOID_SubjectKeyIdentifier + */ +typedef CSSM_DATA CE_SubjectKeyID DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* + * id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } + * + * KeyUsage ::= BIT STRING { + * digitalSignature (0), + * nonRepudiation (1), + * keyEncipherment (2), + * dataEncipherment (3), + * keyAgreement (4), + * keyCertSign (5), + * cRLSign (6), + * encipherOnly (7), + * decipherOnly (8) } + * + * CSSM OID = CSSMOID_KeyUsage + * + */ +typedef uint16 CE_KeyUsage DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +#define CE_KU_DigitalSignature 0x8000 +#define CE_KU_NonRepudiation 0x4000 +#define CE_KU_KeyEncipherment 0x2000 +#define CE_KU_DataEncipherment 0x1000 +#define CE_KU_KeyAgreement 0x0800 +#define CE_KU_KeyCertSign 0x0400 +#define CE_KU_CRLSign 0x0200 +#define CE_KU_EncipherOnly 0x0100 +#define CE_KU_DecipherOnly 0x0080 + +/* + * id-ce-cRLReason OBJECT IDENTIFIER ::= { id-ce 21 } + * + * -- reasonCode ::= { CRLReason } + * + * CRLReason ::= ENUMERATED { + * unspecified (0), + * keyCompromise (1), + * cACompromise (2), + * affiliationChanged (3), + * superseded (4), + * cessationOfOperation (5), + * certificateHold (6), + * removeFromCRL (8) } + * + * CSSM OID = CSSMOID_CrlReason + * + */ +typedef uint32 CE_CrlReason DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +#define CE_CR_Unspecified 0 +#define CE_CR_KeyCompromise 1 +#define CE_CR_CACompromise 2 +#define CE_CR_AffiliationChanged 3 +#define CE_CR_Superseded 4 +#define CE_CR_CessationOfOperation 5 +#define CE_CR_CertificateHold 6 +#define CE_CR_RemoveFromCRL 8 + +/* + * id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } + * + * SubjectAltName ::= GeneralNames + * + * CSSM OID = CSSMOID_SubjectAltName + * + * GeneralNames defined above. + */ + +/* + * id-ce-extKeyUsage OBJECT IDENTIFIER ::= {id-ce 37} + * + * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId* + * + * KeyPurposeId ::= OBJECT IDENTIFIER + * + * CSSM OID = CSSMOID_ExtendedKeyUsage + */ +typedef struct __CE_ExtendedKeyUsage { + uint32 numPurposes; + CSSM_OID_PTR purposes; // in Intel pre-encoded format +} CE_ExtendedKeyUsage; + +/* + * id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } + * + * BasicConstraints ::= SEQUENCE { + * cA BOOLEAN DEFAULT FALSE, + * pathLenConstraint INTEGER (0..MAX) OPTIONAL } + * + * CSSM OID = CSSMOID_BasicConstraints + */ +typedef struct __CE_BasicConstraints { + CSSM_BOOL cA; + CSSM_BOOL pathLenConstraintPresent; + uint32 pathLenConstraint; +} CE_BasicConstraints DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* + * id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } + * + * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation + * + * PolicyInformation ::= SEQUENCE { + * policyIdentifier CertPolicyId, + * policyQualifiers SEQUENCE SIZE (1..MAX) OF + * PolicyQualifierInfo OPTIONAL } + * + * CertPolicyId ::= OBJECT IDENTIFIER + * + * PolicyQualifierInfo ::= SEQUENCE { + * policyQualifierId PolicyQualifierId, + * qualifier ANY DEFINED BY policyQualifierId } + * + * -- policyQualifierIds for Internet policy qualifiers + * + * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } + * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } + * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } + * + * PolicyQualifierId ::= + * OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) + * + * Qualifier ::= CHOICE { + * cPSuri CPSuri, + * userNotice UserNotice } + * + * CPSuri ::= IA5String + * + * UserNotice ::= SEQUENCE { + * noticeRef NoticeReference OPTIONAL, + * explicitText DisplayText OPTIONAL} + * + * NoticeReference ::= SEQUENCE { + * organization DisplayText, + * noticeNumbers SEQUENCE OF INTEGER } + * + * DisplayText ::= CHOICE { + * visibleString VisibleString (SIZE (1..200)), + * bmpString BMPString (SIZE (1..200)), + * utf8String UTF8String (SIZE (1..200)) } + * + * CSSM OID = CSSMOID_CertificatePolicies + * + * We only support down to the level of Qualifier, and then only the CPSuri + * choice. UserNotice is transmitted to and from this library as a raw + * CSSM_DATA containing the BER-encoded UserNotice sequence. + */ + +typedef struct __CE_PolicyQualifierInfo { + CSSM_OID policyQualifierId; // CSSMOID_QT_CPS, CSSMOID_QT_UNOTICE + CSSM_DATA qualifier; // CSSMOID_QT_CPS: IA5String contents + // CSSMOID_QT_UNOTICE : Sequence contents +} CE_PolicyQualifierInfo DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct __CE_PolicyInformation { + CSSM_OID certPolicyId; + uint32 numPolicyQualifiers; // size of *policyQualifiers; + CE_PolicyQualifierInfo *policyQualifiers; +} CE_PolicyInformation DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct __CE_CertPolicies { + uint32 numPolicies; // size of *policies; + CE_PolicyInformation *policies; +} CE_CertPolicies DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* + * netscape-cert-type, a bit string. + * + * CSSM OID = CSSMOID_NetscapeCertType + * + * Bit fields defined in oidsattr.h: CE_NCT_SSL_Client, etc. + */ +typedef uint16 CE_NetscapeCertType DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* + * CRLDistributionPoints. + * + * id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } + * + * cRLDistributionPoints ::= { + * CRLDistPointsSyntax } + * + * CRLDistPointsSyntax ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint + * + * NOTE: RFC 2459 claims that the tag for the optional DistributionPointName + * is IMPLICIT as shown here, but in practice it is EXPLICIT. It has to be - + * because the underlying type also uses an implicit tag for distinguish + * between CHOICEs. + * + * DistributionPoint ::= SEQUENCE { + * distributionPoint [0] DistributionPointName OPTIONAL, + * reasons [1] ReasonFlags OPTIONAL, + * cRLIssuer [2] GeneralNames OPTIONAL } + * + * DistributionPointName ::= CHOICE { + * fullName [0] GeneralNames, + * nameRelativeToCRLIssuer [1] RelativeDistinguishedName } + * + * ReasonFlags ::= BIT STRING { + * unused (0), + * keyCompromise (1), + * cACompromise (2), + * affiliationChanged (3), + * superseded (4), + * cessationOfOperation (5), + * certificateHold (6) } + * + * CSSM OID = CSSMOID_CrlDistributionPoints + */ + +/* + * Note that this looks similar to CE_CrlReason, but that's an enum and this + * is an OR-able bit string. + */ +typedef uint8 CE_CrlDistReasonFlags DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +#define CE_CD_Unspecified 0x80 +#define CE_CD_KeyCompromise 0x40 +#define CE_CD_CACompromise 0x20 +#define CE_CD_AffiliationChanged 0x10 +#define CE_CD_Superseded 0x08 +#define CE_CD_CessationOfOperation 0x04 +#define CE_CD_CertificateHold 0x02 + +typedef enum __CE_CrlDistributionPointNameType { + CE_CDNT_FullName, + CE_CDNT_NameRelativeToCrlIssuer +} CE_CrlDistributionPointNameType DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct __CE_DistributionPointName { + CE_CrlDistributionPointNameType nameType; + union { + CE_GeneralNames *fullName; + CSSM_X509_RDN_PTR rdn; + } dpn; +} CE_DistributionPointName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* + * The top-level CRLDistributionPoint. + * All fields are optional; NULL pointers indicate absence. + */ +typedef struct __CE_CRLDistributionPoint { + CE_DistributionPointName *distPointName; + CSSM_BOOL reasonsPresent; + CE_CrlDistReasonFlags reasons; + CE_GeneralNames *crlIssuer; +} CE_CRLDistributionPoint DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct __CE_CRLDistPointsSyntax { + uint32 numDistPoints; + CE_CRLDistributionPoint *distPoints; +} CE_CRLDistPointsSyntax DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* + * Authority Information Access and Subject Information Access. + * + * CSSM OID = CSSMOID_AuthorityInfoAccess + * CSSM OID = CSSMOID_SubjectInfoAccess + * + * SubjAuthInfoAccessSyntax ::= + * SEQUENCE SIZE (1..MAX) OF AccessDescription + * + * AccessDescription ::= SEQUENCE { + * accessMethod OBJECT IDENTIFIER, + * accessLocation GeneralName } + */ +typedef struct __CE_AccessDescription { + CSSM_OID accessMethod; + CE_GeneralName accessLocation; +} CE_AccessDescription DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct __CE_AuthorityInfoAccess { + uint32 numAccessDescriptions; + CE_AccessDescription *accessDescriptions; +} CE_AuthorityInfoAccess DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* + * Qualified Certificate Statement support, per RFC 3739. + * + * First, NameRegistrationAuthorities, a component of + * SemanticsInformation; it's the same as a GeneralNames - + * a sequence of GeneralName. + */ +typedef CE_GeneralNames CE_NameRegistrationAuthorities DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* + * SemanticsInformation, identified as the qcType field + * of a CE_QC_Statement for statementId value id-qcs-pkixQCSyntax-v2. + * Both fields optional; at least one must be present. + */ +typedef struct __CE_SemanticsInformation { + CSSM_OID *semanticsIdentifier; + CE_NameRegistrationAuthorities *nameRegistrationAuthorities; +} CE_SemanticsInformation DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* + * One Qualified Certificate Statement. + * The statementId OID is required; zero or one of {semanticsInfo, + * otherInfo} can be valid, depending on the value of statementId. + * For statementId id-qcs-pkixQCSyntax-v2 (CSSMOID_OID_QCS_SYNTAX_V2), + * the semanticsInfo field may be present; otherwise, DER-encoded + * information may be present in otherInfo. Both semanticsInfo and + * otherInfo are optional. + */ +typedef struct __CE_QC_Statement { + CSSM_OID statementId; + CE_SemanticsInformation *semanticsInfo; + CSSM_DATA *otherInfo; +} CE_QC_Statement DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* + * The top-level Qualified Certificate Statements extension. + */ +typedef struct __CE_QC_Statements { + uint32 numQCStatements; + CE_QC_Statement *qcStatements; +} CE_QC_Statements DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/*** CRL extensions ***/ + +/* + * cRLNumber, an integer. + * + * CSSM OID = CSSMOID_CrlNumber + */ +typedef uint32 CE_CrlNumber; + +/* + * deltaCRLIndicator, an integer. + * + * CSSM OID = CSSMOID_DeltaCrlIndicator + */ +typedef uint32 CE_DeltaCrl; + +/* + * IssuingDistributionPoint + * + * id-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-ce 28 } + * + * issuingDistributionPoint ::= SEQUENCE { + * distributionPoint [0] DistributionPointName OPTIONAL, + * onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE, + * onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE, + * onlySomeReasons [3] ReasonFlags OPTIONAL, + * indirectCRL [4] BOOLEAN DEFAULT FALSE } + * + * CSSM OID = CSSMOID_IssuingDistributionPoint + */ +typedef struct __CE_IssuingDistributionPoint { + CE_DistributionPointName *distPointName; // optional + CSSM_BOOL onlyUserCertsPresent; + CSSM_BOOL onlyUserCerts; + CSSM_BOOL onlyCACertsPresent; + CSSM_BOOL onlyCACerts; + CSSM_BOOL onlySomeReasonsPresent; + CE_CrlDistReasonFlags onlySomeReasons; + CSSM_BOOL indirectCrlPresent; + CSSM_BOOL indirectCrl; +} CE_IssuingDistributionPoint DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* + * NameConstraints + * + * id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } + * + * NameConstraints ::= SEQUENCE { + * permittedSubtrees [0] GeneralSubtrees OPTIONAL, + * excludedSubtrees [1] GeneralSubtrees OPTIONAL } + * + * GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree + * + * GeneralSubtree ::= SEQUENCE { + * base GeneralName, + * minimum [0] BaseDistance DEFAULT 0, + * maximum [1] BaseDistance OPTIONAL } + * + * BaseDistance ::= INTEGER (0..MAX) + */ +typedef struct __CE_GeneralSubtree { + CE_GeneralNames *base; + uint32 minimum; // default=0 + CSSM_BOOL maximumPresent; + uint32 maximum; // optional +} CE_GeneralSubtree DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct __CE_GeneralSubtrees { + uint32 numSubtrees; + CE_GeneralSubtree *subtrees; +} CE_GeneralSubtrees DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct __CE_NameConstraints { + CE_GeneralSubtrees *permitted; // optional + CE_GeneralSubtrees *excluded; // optional +} CE_NameConstraints DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* + * PolicyMappings + * + * id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } + * + * PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { + * issuerDomainPolicy CertPolicyId, + * subjectDomainPolicy CertPolicyId } + * + * Note that both issuer and subject policy OIDs are required, + * and are stored by value in this structure. + */ +typedef struct __CE_PolicyMapping { + CSSM_OID issuerDomainPolicy; + CSSM_OID subjectDomainPolicy; +} CE_PolicyMapping DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct __CE_PolicyMappings { + uint32 numPolicyMappings; + CE_PolicyMapping *policyMappings; +} CE_PolicyMappings DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* + * PolicyConstraints + * + * id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } + * + * PolicyConstraints ::= SEQUENCE { + * requireExplicitPolicy [0] SkipCerts OPTIONAL, + * inhibitPolicyMapping [1] SkipCerts OPTIONAL } + * + * SkipCerts ::= INTEGER (0..MAX) + */ +typedef struct __CE_PolicyConstraints { + CSSM_BOOL requireExplicitPolicyPresent; + uint32 requireExplicitPolicy; // optional + CSSM_BOOL inhibitPolicyMappingPresent; + uint32 inhibitPolicyMapping; // optional +} CE_PolicyConstraints DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* + * InhibitAnyPolicy, an integer. + * + * CSSM OID = CSSMOID_InhibitAnyPolicy + */ +typedef uint32 CE_InhibitAnyPolicy DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* + * An enumerated list identifying one of the above per-extension + * structs. + */ +typedef enum __CE_DataType { + DT_AuthorityKeyID, // CE_AuthorityKeyID + DT_SubjectKeyID, // CE_SubjectKeyID + DT_KeyUsage, // CE_KeyUsage + DT_SubjectAltName, // implies CE_GeneralName + DT_IssuerAltName, // implies CE_GeneralName + DT_ExtendedKeyUsage, // CE_ExtendedKeyUsage + DT_BasicConstraints, // CE_BasicConstraints + DT_CertPolicies, // CE_CertPolicies + DT_NetscapeCertType, // CE_NetscapeCertType + DT_CrlNumber, // CE_CrlNumber + DT_DeltaCrl, // CE_DeltaCrl + DT_CrlReason, // CE_CrlReason + DT_CrlDistributionPoints, // CE_CRLDistPointsSyntax + DT_IssuingDistributionPoint,// CE_IssuingDistributionPoint + DT_AuthorityInfoAccess, // CE_AuthorityInfoAccess + DT_Other, // unknown, raw data as a CSSM_DATA + DT_QC_Statements, // CE_QC_Statements + DT_NameConstraints, // CE_NameConstraints + DT_PolicyMappings, // CE_PolicyMappings + DT_PolicyConstraints, // CE_PolicyConstraints + DT_InhibitAnyPolicy // CE_InhibitAnyPolicy +} CE_DataType; + +/* + * One unified representation of all the cert and CRL extensions we know about. + */ +typedef union { + CE_AuthorityKeyID authorityKeyID; + CE_SubjectKeyID subjectKeyID; + CE_KeyUsage keyUsage; + CE_GeneralNames subjectAltName; + CE_GeneralNames issuerAltName; + CE_ExtendedKeyUsage extendedKeyUsage; + CE_BasicConstraints basicConstraints; + CE_CertPolicies certPolicies; + CE_NetscapeCertType netscapeCertType; + CE_CrlNumber crlNumber; + CE_DeltaCrl deltaCrl; + CE_CrlReason crlReason; + CE_CRLDistPointsSyntax crlDistPoints; + CE_IssuingDistributionPoint issuingDistPoint; + CE_AuthorityInfoAccess authorityInfoAccess; + CE_QC_Statements qualifiedCertStatements; + CE_NameConstraints nameConstraints; + CE_PolicyMappings policyMappings; + CE_PolicyConstraints policyConstraints; + CE_InhibitAnyPolicy inhibitAnyPolicy; + CSSM_DATA rawData; // unknown, not decoded +} CE_Data DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +typedef struct __CE_DataAndType { + CE_DataType type; + CE_Data extension; + CSSM_BOOL critical; +} CE_DataAndType DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +#endif /* _CERT_EXTENSIONS_H_ */ diff --git a/libsecurity_cssm/lib/cspattachment.cpp b/Security/libsecurity_cssm/lib/cspattachment.cpp similarity index 94% rename from libsecurity_cssm/lib/cspattachment.cpp rename to Security/libsecurity_cssm/lib/cspattachment.cpp index c35f6329..8ec2dfd4 100644 --- a/libsecurity_cssm/lib/cspattachment.cpp +++ b/Security/libsecurity_cssm/lib/cspattachment.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/cspattachment.h b/Security/libsecurity_cssm/lib/cspattachment.h similarity index 95% rename from libsecurity_cssm/lib/cspattachment.h rename to Security/libsecurity_cssm/lib/cspattachment.h index 4255ce4d..f67d2a70 100644 --- a/libsecurity_cssm/lib/cspattachment.h +++ b/Security/libsecurity_cssm/lib/cspattachment.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/cssm.cpp b/Security/libsecurity_cssm/lib/cssm.cpp similarity index 99% rename from libsecurity_cssm/lib/cssm.cpp rename to Security/libsecurity_cssm/lib/cssm.cpp index 67d6dccf..496d039c 100644 --- a/libsecurity_cssm/lib/cssm.cpp +++ b/Security/libsecurity_cssm/lib/cssm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/cssm.h b/Security/libsecurity_cssm/lib/cssm.h similarity index 94% rename from libsecurity_cssm/lib/cssm.h rename to Security/libsecurity_cssm/lib/cssm.h index 27f7084d..8b054af7 100644 --- a/libsecurity_cssm/lib/cssm.h +++ b/Security/libsecurity_cssm/lib/cssm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/cssmaci.h b/Security/libsecurity_cssm/lib/cssmaci.h similarity index 96% rename from libsecurity_cssm/lib/cssmaci.h rename to Security/libsecurity_cssm/lib/cssmaci.h index 7a81d6fe..f71dd4b8 100644 --- a/libsecurity_cssm/lib/cssmaci.h +++ b/Security/libsecurity_cssm/lib/cssmaci.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/cssmapi.h b/Security/libsecurity_cssm/lib/cssmapi.h similarity index 99% rename from libsecurity_cssm/lib/cssmapi.h rename to Security/libsecurity_cssm/lib/cssmapi.h index f1de11cb..68680f05 100644 --- a/libsecurity_cssm/lib/cssmapi.h +++ b/Security/libsecurity_cssm/lib/cssmapi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_cssm/lib/cssmapple.h b/Security/libsecurity_cssm/lib/cssmapple.h new file mode 100644 index 00000000..4d1c72fb --- /dev/null +++ b/Security/libsecurity_cssm/lib/cssmapple.h @@ -0,0 +1,1160 @@ +/* + * Copyright (c) 2000-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@ + * + * cssmapple.h -- CSSM features specific to Apple's Implementation + */ + +#ifndef _CSSMAPPLE_H_ +#define _CSSMAPPLE_H_ 1 + +#include +#include +#include /* for CSSM_APPLE_TP_CERT_REQUEST fields */ +#include /* ditto */ +#include /* for the BSD *_t types */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Guids for standard Apple addin modules. */ + +/* CSSM itself: {87191ca0-0fc9-11d4-849a-000502b52122} */ +extern const CSSM_GUID gGuidCssm; + +/* File based DL (aka "Keychain DL"): {87191ca1-0fc9-11d4-849a-000502b52122} */ +extern const CSSM_GUID gGuidAppleFileDL; + +/* Core CSP (local space): {87191ca2-0fc9-11d4-849a-000502b52122} */ +extern const CSSM_GUID gGuidAppleCSP; + +/* Secure CSP/DL (aka "Keychain CSPDL): {87191ca3-0fc9-11d4-849a-000502b52122} */ +extern const CSSM_GUID gGuidAppleCSPDL; + +/* X509 Certificate CL: {87191ca4-0fc9-11d4-849a-000502b52122} */ +extern const CSSM_GUID gGuidAppleX509CL; + +/* X509 Certificate TP: {87191ca5-0fc9-11d4-849a-000502b52122} */ +extern const CSSM_GUID gGuidAppleX509TP; + +/* DLAP/OpenDirectory access DL: {87191ca6-0fc9-11d4-849a-000502b52122} */ +extern const CSSM_GUID gGuidAppleLDAPDL; + +/* TP for ".mac" related policies: {87191ca7-0fc9-11d4-849a-000502b52122} */ +extern const CSSM_GUID gGuidAppleDotMacTP; + +/* Smartcard CSP/DL: {87191ca8-0fc9-11d4-849a-000502b52122} */ +extern const CSSM_GUID gGuidAppleSdCSPDL; + +/* DL for ".mac" certificate access: {87191ca9-0fc9-11d4-849a-000502b52122} */ +extern const CSSM_GUID gGuidAppleDotMacDL; + + +/* Apple defined WORDID values */ +enum +{ + CSSM_WORDID_KEYCHAIN_PROMPT = CSSM_WORDID_VENDOR_START, + CSSM_WORDID_KEYCHAIN_LOCK, + CSSM_WORDID_KEYCHAIN_CHANGE_LOCK, + CSSM_WORDID_PROCESS, + CSSM_WORDID__RESERVED_1, /* was used in 10.2 test seeds; no longer in use */ + CSSM_WORDID_SYMMETRIC_KEY, + CSSM_WORDID_SYSTEM, + CSSM_WORDID_KEY, + CSSM_WORDID_PIN, + CSSM_WORDID_PREAUTH, + CSSM_WORDID_PREAUTH_SOURCE, + CSSM_WORDID_ASYMMETRIC_KEY, + CSSM_WORDID__FIRST_UNUSED +}; + +/* Apple defined ACL subject and credential types */ +enum +{ + CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT = CSSM_WORDID_KEYCHAIN_PROMPT, + CSSM_ACL_SUBJECT_TYPE_PROCESS = CSSM_WORDID_PROCESS, + CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE = CSSM_WORDID_SIGNATURE, + CSSM_ACL_SUBJECT_TYPE_COMMENT = CSSM_WORDID_COMMENT, + 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 +}; + +enum +{ + CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT = CSSM_WORDID_KEYCHAIN_PROMPT, + CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK = CSSM_WORDID_KEYCHAIN_LOCK, + CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK = CSSM_WORDID_KEYCHAIN_CHANGE_LOCK, + CSSM_SAMPLE_TYPE_PROCESS = CSSM_WORDID_PROCESS, + CSSM_SAMPLE_TYPE_COMMENT = CSSM_WORDID_COMMENT, + CSSM_SAMPLE_TYPE_RETRY_ID = CSSM_WORDID_PROPAGATE, + CSSM_SAMPLE_TYPE_SYMMETRIC_KEY = CSSM_WORDID_SYMMETRIC_KEY, + CSSM_SAMPLE_TYPE_PREAUTH = CSSM_WORDID_PREAUTH, + CSSM_SAMPLE_TYPE_ASYMMETRIC_KEY = CSSM_WORDID_ASYMMETRIC_KEY + // there is no CSSM_SAMPLE_TYPE_PREAUTH_SOURCE +}; + + +/* Apple-defined ACL authorization tags */ +enum { + CSSM_ACL_AUTHORIZATION_CHANGE_ACL = CSSM_ACL_AUTHORIZATION_TAG_VENDOR_DEFINED_START, + CSSM_ACL_AUTHORIZATION_CHANGE_OWNER, + + // the "pre-auth" tags form a contiguous range of (up to) 64K pre-authorizations + CSSM_ACL_AUTHORIZATION_PREAUTH_BASE = + CSSM_ACL_AUTHORIZATION_TAG_VENDOR_DEFINED_START + 0x1000000, + CSSM_ACL_AUTHORIZATION_PREAUTH_END = CSSM_ACL_AUTHORIZATION_PREAUTH_BASE + 0x10000 +}; + +/* pre-authorization conversions (auth-tag to slot and back) */ +#define CSSM_ACL_AUTHORIZATION_PREAUTH(slot) \ + (CSSM_ACL_AUTHORIZATION_PREAUTH_BASE + (slot)) +#define CSSM_ACL_AUTHORIZATION_PREAUTH_SLOT(auth) \ + ((auth) - CSSM_ACL_AUTHORIZATION_PREAUTH_BASE) +#define CSSM_ACL_AUTHORIZATION_IS_PREAUTH(auth) \ + ((auth) >= CSSM_ACL_AUTHORIZATION_PREAUTH_BASE && \ + (auth) < CSSM_ACL_AUTHORIZATION_PREAUTH_END) + + +/* Parameters and structures for Apple-defined ACL subjects and samples */ + +enum { /* types of code signatures - item 1 of CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE subjects */ + CSSM_ACL_CODE_SIGNATURE_INVALID = 0, /* standard OS X code signature */ + CSSM_ACL_CODE_SIGNATURE_OSX = 1 /* standard OS X code signature */ +}; + +/* ACL subjects of type PROCESS */ + +enum { /* PROCESS_SUBJECT mask fields */ + CSSM_ACL_MATCH_UID = 0x01, /* match userid against uid field */ + CSSM_ACL_MATCH_GID = 0x02, /* match groupid against gid field */ + CSSM_ACL_MATCH_HONOR_ROOT = 0x100, /* let root (uid 0) match any userid */ + CSSM_ACL_MATCH_BITS = CSSM_ACL_MATCH_UID | CSSM_ACL_MATCH_GID +}; + +enum { /* PROCESS_SUBJECT structure version field */ + CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION = 0x101 +}; + +typedef struct cssm_acl_process_subject_selector { /* PROCESS_SUBJECT selector */ + uint16 version; /* version of this selector */ + uint16 mask; /* active fields mask */ + uint32 uid; /* effective user id match */ + uint32 gid; /* effective group id match */ +} CSSM_ACL_PROCESS_SUBJECT_SELECTOR; + +/* ACL subjects of type KEYCHAIN_PROMPT */ + +enum { /* KEYCHAIN_PROMPT structure version field */ + CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION = 0x101 +}; + +enum { /* KEYCHAIN_PROMPT operational flags */ + CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE = 0x0001, /* require re-entering of passphrase */ + /* the following bits are ignored by 10.4 and earlier */ + CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED = 0x0010, /* prompt for unsigned clients */ + CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED_ACT = 0x0020, /* UNSIGNED bit overrides system default */ + CSSM_ACL_KEYCHAIN_PROMPT_INVALID = 0x0040, /* prompt for invalid signed clients */ + CSSM_ACL_KEYCHAIN_PROMPT_INVALID_ACT = 0x0080, /* INVALID bit overrides system default */ +}; + +typedef struct cssm_acl_keychain_prompt_selector { /* KEYCHAIN_PROMPT selector */ + uint16 version; /* version of this selector */ + uint16 flags; /* flag bits */ +} CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR; + +/* ACL subjects of type CSSM_ACL_SUBJECT_TYPE_PREAUTH_SOURCE */ +typedef uint32 CSSM_ACL_PREAUTH_TRACKING_STATE; +enum { /* preauth tracking state */ + CSSM_ACL_PREAUTH_TRACKING_COUNT_MASK = 0xff, /* mask for count status */ + CSSM_ACL_PREAUTH_TRACKING_BLOCKED = 0, /* retries exhausted; the slot is blocked */ + /* 0 .. 255 is a count of (re)tries remaining */ + + /* bits or'ed into any count given */ + CSSM_ACL_PREAUTH_TRACKING_UNKNOWN = 0x40000000, /* status of slot is unknown (ignore count) */ + CSSM_ACL_PREAUTH_TRACKING_AUTHORIZED = 0x80000000 /* the slot is currently authorized (or'ed in) */ +}; + + +/* Apple defined values of a CSSM_DB_ACCESS_TYPE */ +enum { + CSSM_DB_ACCESS_RESET = 0x10000 /* clear pre-authentications (or'ed bit) */ +}; + + +/* Apple defined algorithm IDs */ +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) device, 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_SHA224WithECDSA, /* ECDSA signature on SHA224 digest */ + CSSM_ALGID_SHA256WithECDSA, /* ECDSA signature on SHA256 digest */ + CSSM_ALGID_SHA384WithECDSA, /* ECDSA signature on SHA384 digest */ + CSSM_ALGID_SHA512WithECDSA, /* ECDSA signature on SHA512 digest */ + CSSM_ALGID_ECDSA_SPECIFIED, /* ECDSA with separate digest algorithm specifier */ + CSSM_ALGID_ECDH_X963_KDF, /* ECDH with X9.63 key derivation */ + CSSM_ALGID__FIRST_UNUSED +}; + +/* Apple defined padding */ +enum +{ + /* RFC 2246 section E.2 for SSLv2 rollback detection */ + CSSM_PADDING_APPLE_SSLv2 = CSSM_PADDING_VENDOR_DEFINED +}; + + +/* Apple defined keyblob formats */ +enum { + CSSM_KEYBLOB_RAW_FORMAT_VENDOR_DEFINED = 0x80000000 +}; +enum { + /* X509 SubjectPublicKeyInfo */ + CSSM_KEYBLOB_RAW_FORMAT_X509 = CSSM_KEYBLOB_RAW_FORMAT_VENDOR_DEFINED, + /* OpenSSH v1 */ + CSSM_KEYBLOB_RAW_FORMAT_OPENSSH, + /* openssl-style DSA private key */ + CSSM_KEYBLOB_RAW_FORMAT_OPENSSL, + /* OpenSSH v2 */ + CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2 +}; + +/* Apple adds some "common" error codes. CDSA does not define an official start value for this. */ +enum +{ + CSSM_CUSTOM_COMMON_ERROR_EXTENT = 0x00e0, + + CSSM_ERRCODE_NO_USER_INTERACTION = 0x00e0, + CSSM_ERRCODE_USER_CANCELED = 0x00e1, + CSSM_ERRCODE_SERVICE_NOT_AVAILABLE = 0x00e2, + CSSM_ERRCODE_INSUFFICIENT_CLIENT_IDENTIFICATION = 0x00e3, + CSSM_ERRCODE_DEVICE_RESET = 0x00e4, + CSSM_ERRCODE_DEVICE_FAILED = 0x00e5, + CSSM_ERRCODE_IN_DARK_WAKE = 0x00e6 +}; + +enum { + CSSMERR_CSSM_NO_USER_INTERACTION = CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_NO_USER_INTERACTION, + CSSMERR_AC_NO_USER_INTERACTION = CSSM_AC_BASE_ERROR + CSSM_ERRCODE_NO_USER_INTERACTION, + CSSMERR_CSP_NO_USER_INTERACTION = CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_NO_USER_INTERACTION, + CSSMERR_CL_NO_USER_INTERACTION = CSSM_CL_BASE_ERROR + CSSM_ERRCODE_NO_USER_INTERACTION, + CSSMERR_DL_NO_USER_INTERACTION = CSSM_DL_BASE_ERROR + CSSM_ERRCODE_NO_USER_INTERACTION, + CSSMERR_TP_NO_USER_INTERACTION = CSSM_TP_BASE_ERROR + CSSM_ERRCODE_NO_USER_INTERACTION, + + CSSMERR_CSSM_USER_CANCELED = CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_USER_CANCELED, + CSSMERR_AC_USER_CANCELED = CSSM_AC_BASE_ERROR + CSSM_ERRCODE_USER_CANCELED, + CSSMERR_CSP_USER_CANCELED = CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_USER_CANCELED, + CSSMERR_CL_USER_CANCELED = CSSM_CL_BASE_ERROR + CSSM_ERRCODE_USER_CANCELED, + CSSMERR_DL_USER_CANCELED = CSSM_DL_BASE_ERROR + CSSM_ERRCODE_USER_CANCELED, + CSSMERR_TP_USER_CANCELED = CSSM_TP_BASE_ERROR + CSSM_ERRCODE_USER_CANCELED, + + CSSMERR_CSSM_SERVICE_NOT_AVAILABLE = CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_SERVICE_NOT_AVAILABLE, + CSSMERR_AC_SERVICE_NOT_AVAILABLE = CSSM_AC_BASE_ERROR + CSSM_ERRCODE_SERVICE_NOT_AVAILABLE, + CSSMERR_CSP_SERVICE_NOT_AVAILABLE = CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_SERVICE_NOT_AVAILABLE, + CSSMERR_CL_SERVICE_NOT_AVAILABLE = CSSM_CL_BASE_ERROR + CSSM_ERRCODE_SERVICE_NOT_AVAILABLE, + CSSMERR_DL_SERVICE_NOT_AVAILABLE = CSSM_DL_BASE_ERROR + CSSM_ERRCODE_SERVICE_NOT_AVAILABLE, + CSSMERR_TP_SERVICE_NOT_AVAILABLE = CSSM_TP_BASE_ERROR + CSSM_ERRCODE_SERVICE_NOT_AVAILABLE, + + CSSMERR_CSSM_INSUFFICIENT_CLIENT_IDENTIFICATION = CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_INSUFFICIENT_CLIENT_IDENTIFICATION, + CSSMERR_AC_INSUFFICIENT_CLIENT_IDENTIFICATION = CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INSUFFICIENT_CLIENT_IDENTIFICATION, + CSSMERR_CSP_INSUFFICIENT_CLIENT_IDENTIFICATION = CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INSUFFICIENT_CLIENT_IDENTIFICATION, + CSSMERR_CL_INSUFFICIENT_CLIENT_IDENTIFICATION = CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INSUFFICIENT_CLIENT_IDENTIFICATION, + CSSMERR_DL_INSUFFICIENT_CLIENT_IDENTIFICATION = CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INSUFFICIENT_CLIENT_IDENTIFICATION, + CSSMERR_TP_INSUFFICIENT_CLIENT_IDENTIFICATION = CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INSUFFICIENT_CLIENT_IDENTIFICATION, + + CSSMERR_CSSM_DEVICE_RESET = CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_DEVICE_RESET, + CSSMERR_AC_DEVICE_RESET = CSSM_AC_BASE_ERROR + CSSM_ERRCODE_DEVICE_RESET, + CSSMERR_CSP_DEVICE_RESET = CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_DEVICE_RESET, + CSSMERR_CL_DEVICE_RESET = CSSM_CL_BASE_ERROR + CSSM_ERRCODE_DEVICE_RESET, + CSSMERR_DL_DEVICE_RESET = CSSM_DL_BASE_ERROR + CSSM_ERRCODE_DEVICE_RESET, + CSSMERR_TP_DEVICE_RESET = CSSM_TP_BASE_ERROR + CSSM_ERRCODE_DEVICE_RESET, + + CSSMERR_CSSM_DEVICE_FAILED = CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_DEVICE_FAILED, + CSSMERR_AC_DEVICE_FAILED = CSSM_AC_BASE_ERROR + CSSM_ERRCODE_DEVICE_FAILED, + CSSMERR_CSP_DEVICE_FAILED = CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_DEVICE_FAILED, + CSSMERR_CL_DEVICE_FAILED = CSSM_CL_BASE_ERROR + CSSM_ERRCODE_DEVICE_FAILED, + CSSMERR_DL_DEVICE_FAILED = CSSM_DL_BASE_ERROR + CSSM_ERRCODE_DEVICE_FAILED, + CSSMERR_TP_DEVICE_FAILED = CSSM_TP_BASE_ERROR + CSSM_ERRCODE_DEVICE_FAILED, + + CSSMERR_CSSM_IN_DARK_WAKE = CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_IN_DARK_WAKE, + CSSMERR_AC_IN_DARK_WAKE = CSSM_AC_BASE_ERROR + CSSM_ERRCODE_IN_DARK_WAKE, + CSSMERR_CSP_IN_DARK_WAKE = CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_IN_DARK_WAKE, + CSSMERR_CL_IN_DARK_WAKE = CSSM_CL_BASE_ERROR + CSSM_ERRCODE_IN_DARK_WAKE, + CSSMERR_DL_IN_DARK_WAKE = CSSM_DL_BASE_ERROR + CSSM_ERRCODE_IN_DARK_WAKE, + CSSMERR_TP_IN_DARK_WAKE = CSSM_TP_BASE_ERROR + CSSM_ERRCODE_IN_DARK_WAKE +}; + +/* AppleCSPDL, AppleCSP private error codes. */ +enum { + CSSMERR_CSP_APPLE_ADD_APPLICATION_ACL_SUBJECT = CSSM_CSP_PRIVATE_ERROR + 0, + /* + * An attempt was made to use a public key which is incomplete due to + * the lack of algorithm-specific parameters. + */ + CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE = CSSM_CSP_PRIVATE_ERROR + 1, + + /* a code signature match failed */ + CSSMERR_CSP_APPLE_SIGNATURE_MISMATCH = CSSM_CSP_PRIVATE_ERROR + 2, + + /* Key StartDate/EndDate invalid */ + CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE = CSSM_CSP_PRIVATE_ERROR + 3, + CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE = CSSM_CSP_PRIVATE_ERROR + 4, + + /* Keychain Syncing error codes */ + CSSMERR_CSPDL_APPLE_DL_CONVERSION_ERROR = CSSM_CSP_PRIVATE_ERROR + 5, + + /* SSLv2 padding check: rollback attack detected */ + CSSMERR_CSP_APPLE_SSLv2_ROLLBACK = CSSM_CSP_PRIVATE_ERROR + 6 +}; + + +/* AppleFileDL record types. */ +enum +{ + CSSM_DL_DB_RECORD_GENERIC_PASSWORD = CSSM_DB_RECORDTYPE_APP_DEFINED_START + 0, + CSSM_DL_DB_RECORD_INTERNET_PASSWORD = CSSM_DB_RECORDTYPE_APP_DEFINED_START + 1, + CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD = CSSM_DB_RECORDTYPE_APP_DEFINED_START + 2, + + CSSM_DL_DB_RECORD_X509_CERTIFICATE = CSSM_DB_RECORDTYPE_APP_DEFINED_START + 0x1000, + CSSM_DL_DB_RECORD_USER_TRUST, + CSSM_DL_DB_RECORD_X509_CRL, + CSSM_DL_DB_RECORD_UNLOCK_REFERRAL, + CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE, + CSSM_DL_DB_RECORD_METADATA = CSSM_DB_RECORDTYPE_APP_DEFINED_START + 0x8000 +}; + +/* AppleFileDL extentions: passthrough ids */ +enum { + // Toggle whether or not to autocommit after modifying the database. + // The input parameter is a CSSM_BOOL, where TRUE turns autocommit on + // and FALSE turns it off. + CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, + + // Commit any pending changes to the database. + CSSM_APPLEFILEDL_COMMIT, + + // Rollback and discard any pending changes to the database. + CSSM_APPLEFILEDL_ROLLBACK +}; + +/* UNLOCK_REFERRAL "type" attribute values */ +enum { + CSSM_APPLE_UNLOCK_TYPE_KEY_DIRECT = 1, // master secret key stored directly + CSSM_APPLE_UNLOCK_TYPE_WRAPPED_PRIVATE = 2 // master key wrapped by public key +}; + +/* Apple DL private error codes. */ +enum +{ + /* The OpenParameters argument passed to CSSM_DL_DbCreate or CSSM_DL_DbOpen + was neither NULL nor a pointer to a valid CSSM_APPLEDL_OPEN_PARAMETERS + structure. */ + CSSMERR_APPLEDL_INVALID_OPEN_PARAMETERS = CSSM_DL_PRIVATE_ERROR + 0, + + /* an operation failed because the disk was full */ + CSSMERR_APPLEDL_DISK_FULL = CSSM_DL_PRIVATE_ERROR + 1, + + /* an operation failed because a disk quota was exceeded */ + CSSMERR_APPLEDL_QUOTA_EXCEEDED = CSSM_DL_PRIVATE_ERROR + 2, + + /* an operation failed because a file was too large */ + CSSMERR_APPLEDL_FILE_TOO_BIG = CSSM_DL_PRIVATE_ERROR + 3, + + /* a keychain database's internal information ("blob") is invalid */ + CSSMERR_APPLEDL_INVALID_DATABASE_BLOB = CSSM_DL_PRIVATE_ERROR + 4, + CSSMERR_APPLEDL_INVALID_KEY_BLOB = CSSM_DL_PRIVATE_ERROR + 5, + + /* the internal data format version for a database's internal information ("blob") is invalid */ + CSSMERR_APPLEDL_INCOMPATIBLE_DATABASE_BLOB = CSSM_DL_PRIVATE_ERROR + 6, + CSSMERR_APPLEDL_INCOMPATIBLE_KEY_BLOB = CSSM_DL_PRIVATE_ERROR + 7, +}; + +/* Apple X509TP private error codes. */ +enum +{ + /* Host name mismatch */ + CSSMERR_APPLETP_HOSTNAME_MISMATCH = CSSM_TP_PRIVATE_ERROR + 0, + /* Non-understood extension with Critical flag true */ + CSSMERR_APPLETP_UNKNOWN_CRITICAL_EXTEN = CSSM_TP_PRIVATE_ERROR + 1, + /* Basic Constraints extension required per policy, but not present */ + CSSMERR_APPLETP_NO_BASIC_CONSTRAINTS = CSSM_TP_PRIVATE_ERROR + 2, + /* Invalid BasicConstraints.CA */ + CSSMERR_APPLETP_INVALID_CA = CSSM_TP_PRIVATE_ERROR + 3, + /* Invalid Authority Key ID */ + CSSMERR_APPLETP_INVALID_AUTHORITY_ID = CSSM_TP_PRIVATE_ERROR + 4, + /* Invalid Subject Key ID */ + CSSMERR_APPLETP_INVALID_SUBJECT_ID = CSSM_TP_PRIVATE_ERROR + 5, + /* Invalid Key Usage for policy */ + CSSMERR_APPLETP_INVALID_KEY_USAGE = CSSM_TP_PRIVATE_ERROR + 6, + /* Invalid Extended Key Usage for policy */ + CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE = CSSM_TP_PRIVATE_ERROR + 7, + /* Invalid Subject/Authority Key ID Linkage */ + CSSMERR_APPLETP_INVALID_ID_LINKAGE = CSSM_TP_PRIVATE_ERROR + 8, + /* PathLengthConstraint exceeded */ + CSSMERR_APPLETP_PATH_LEN_CONSTRAINT = CSSM_TP_PRIVATE_ERROR + 9, + /* Cert group terminated at a root cert which did not self-verify */ + CSSMERR_APPLETP_INVALID_ROOT = CSSM_TP_PRIVATE_ERROR + 10, + /* CRL expired/not valid yet */ + CSSMERR_APPLETP_CRL_EXPIRED = CSSM_TP_PRIVATE_ERROR + 11, + CSSMERR_APPLETP_CRL_NOT_VALID_YET = CSSM_TP_PRIVATE_ERROR + 12, + /* Cannot find appropriate CRL */ + CSSMERR_APPLETP_CRL_NOT_FOUND = CSSM_TP_PRIVATE_ERROR + 13, + /* specified CRL server down */ + CSSMERR_APPLETP_CRL_SERVER_DOWN = CSSM_TP_PRIVATE_ERROR + 14, + /* illegible CRL distribution point URL */ + CSSMERR_APPLETP_CRL_BAD_URI = CSSM_TP_PRIVATE_ERROR + 15, + /* Unknown critical cert/CRL extension */ + CSSMERR_APPLETP_UNKNOWN_CERT_EXTEN = CSSM_TP_PRIVATE_ERROR + 16, + CSSMERR_APPLETP_UNKNOWN_CRL_EXTEN = CSSM_TP_PRIVATE_ERROR + 17, + /* CRL not verifiable to anchor or root */ + CSSMERR_APPLETP_CRL_NOT_TRUSTED = CSSM_TP_PRIVATE_ERROR + 18, + /* CRL verified to untrusted root */ + CSSMERR_APPLETP_CRL_INVALID_ANCHOR_CERT = CSSM_TP_PRIVATE_ERROR + 19, + /* CRL failed policy verification */ + CSSMERR_APPLETP_CRL_POLICY_FAIL = CSSM_TP_PRIVATE_ERROR + 20, + /* IssuingDistributionPoint extension violation */ + CSSMERR_APPLETP_IDP_FAIL = CSSM_TP_PRIVATE_ERROR + 21, + /* Cert not found at specified issuerAltName */ + CSSMERR_APPLETP_CERT_NOT_FOUND_FROM_ISSUER = CSSM_TP_PRIVATE_ERROR + 22, + /* Bad cert obtained from specified issuerAltName */ + CSSMERR_APPLETP_BAD_CERT_FROM_ISSUER = CSSM_TP_PRIVATE_ERROR + 23, + /* S/MIME Email address mismatch */ + CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND = CSSM_TP_PRIVATE_ERROR + 24, + /* Appropriate S/MIME ExtendedKeyUsage not found */ + CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE = CSSM_TP_PRIVATE_ERROR + 25, + /* S/MIME KeyUsage incompatibility */ + CSSMERR_APPLETP_SMIME_BAD_KEY_USE = CSSM_TP_PRIVATE_ERROR + 26, + /* S/MIME, cert with KeyUsage flagged !critical */ + CSSMERR_APPLETP_SMIME_KEYUSAGE_NOT_CRITICAL = CSSM_TP_PRIVATE_ERROR + 27, + /* S/MIME, leaf with empty subject name and no email addrs + * in SubjectAltName */ + CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS = CSSM_TP_PRIVATE_ERROR + 28, + /* S/MIME, leaf with empty subject name, SubjectAltName + * not critical */ + CSSMERR_APPLETP_SMIME_SUBJ_ALT_NAME_NOT_CRIT = CSSM_TP_PRIVATE_ERROR + 29, + /* Appropriate SSL ExtendedKeyUsage not found */ + CSSMERR_APPLETP_SSL_BAD_EXT_KEY_USE = CSSM_TP_PRIVATE_ERROR + 30, + /* unparseable OCSP response */ + CSSMERR_APPLETP_OCSP_BAD_RESPONSE = CSSM_TP_PRIVATE_ERROR + 31, + /* unparseable OCSP request */ + CSSMERR_APPLETP_OCSP_BAD_REQUEST = CSSM_TP_PRIVATE_ERROR + 32, + /* OCSP service unavailable */ + CSSMERR_APPLETP_OCSP_UNAVAILABLE = CSSM_TP_PRIVATE_ERROR + 33, + /* OCSP status: cert unrecognized */ + CSSMERR_APPLETP_OCSP_STATUS_UNRECOGNIZED = CSSM_TP_PRIVATE_ERROR + 34, + /* revocation check not successful for each cert */ + CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK = CSSM_TP_PRIVATE_ERROR + 35, + /* general network error */ + CSSMERR_APPLETP_NETWORK_FAILURE = CSSM_TP_PRIVATE_ERROR + 36, + /* OCSP response not verifiable to anchor or root */ + CSSMERR_APPLETP_OCSP_NOT_TRUSTED = CSSM_TP_PRIVATE_ERROR + 37, + /* OCSP response verified to untrusted root */ + CSSMERR_APPLETP_OCSP_INVALID_ANCHOR_CERT = CSSM_TP_PRIVATE_ERROR + 38, + /* OCSP response signature error */ + CSSMERR_APPLETP_OCSP_SIG_ERROR = CSSM_TP_PRIVATE_ERROR + 39, + /* No signer for OCSP response found */ + CSSMERR_APPLETP_OCSP_NO_SIGNER = CSSM_TP_PRIVATE_ERROR + 40, + /* OCSP responder status: malformed request */ + CSSMERR_APPLETP_OCSP_RESP_MALFORMED_REQ = CSSM_TP_PRIVATE_ERROR + 41, + /* OCSP responder status: internal error */ + CSSMERR_APPLETP_OCSP_RESP_INTERNAL_ERR = CSSM_TP_PRIVATE_ERROR + 42, + /* OCSP responder status: try later */ + CSSMERR_APPLETP_OCSP_RESP_TRY_LATER = CSSM_TP_PRIVATE_ERROR + 43, + /* OCSP responder status: signature required */ + CSSMERR_APPLETP_OCSP_RESP_SIG_REQUIRED = CSSM_TP_PRIVATE_ERROR + 44, + /* OCSP responder status: unauthorized */ + CSSMERR_APPLETP_OCSP_RESP_UNAUTHORIZED = CSSM_TP_PRIVATE_ERROR + 45, + /* OCSP response nonce did not match request */ + CSSMERR_APPLETP_OCSP_NONCE_MISMATCH = CSSM_TP_PRIVATE_ERROR + 46, + /* Illegal cert chain length for Code Signing */ + CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH = CSSM_TP_PRIVATE_ERROR + 47, + /* Missing Basic Constraints for Code Signing */ + CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS = CSSM_TP_PRIVATE_ERROR + 48, + /* Bad PathLengthConstraint for Code Signing */ + CSSMERR_APPLETP_CS_BAD_PATH_LENGTH = CSSM_TP_PRIVATE_ERROR + 49, + /* Missing ExtendedKeyUsage for Code Signing */ + CSSMERR_APPLETP_CS_NO_EXTENDED_KEY_USAGE = CSSM_TP_PRIVATE_ERROR + 50, + /* Development style Code Signing Cert Detected */ + CSSMERR_APPLETP_CODE_SIGN_DEVELOPMENT = CSSM_TP_PRIVATE_ERROR + 51, + /* Illegal cert chain length for Resource Signing */ + CSSMERR_APPLETP_RS_BAD_CERT_CHAIN_LENGTH = CSSM_TP_PRIVATE_ERROR + 52, + /* Bad extended key usage for Resource Signing */ + CSSMERR_APPLETP_RS_BAD_EXTENDED_KEY_USAGE = CSSM_TP_PRIVATE_ERROR + 53, + /* Trust Setting: deny */ + CSSMERR_APPLETP_TRUST_SETTING_DENY = CSSM_TP_PRIVATE_ERROR + 54, + /* Invalid empty SubjectName */ + CSSMERR_APPLETP_INVALID_EMPTY_SUBJECT = CSSM_TP_PRIVATE_ERROR + 55, + /* Unknown critical Qualified Cert Statement ID */ + CSSMERR_APPLETP_UNKNOWN_QUAL_CERT_STATEMENT = CSSM_TP_PRIVATE_ERROR + 56, + /* Missing required extension */ + CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION = CSSM_TP_PRIVATE_ERROR + 57, + /* Extended key usage not marked critical */ + CSSMERR_APPLETP_EXT_KEYUSAGE_NOT_CRITICAL = CSSM_TP_PRIVATE_ERROR + 58, + /* Required name or identifier not present */ + CSSMERR_APPLETP_IDENTIFIER_MISSING = CSSM_TP_PRIVATE_ERROR + 59, + /* Certificate authority pinning mismatch */ + CSSMERR_APPLETP_CA_PIN_MISMATCH = CSSM_TP_PRIVATE_ERROR + 60 +}; + +/* Apple .mac TP private error codes. */ +enum +{ + /* cert request queued */ + CSSMERR_APPLE_DOTMAC_REQ_QUEUED = CSSM_TP_PRIVATE_ERROR + 100, + /* cert request redirected */ + CSSMERR_APPLE_DOTMAC_REQ_REDIRECT = CSSM_TP_PRIVATE_ERROR + 101, + /* general server-reported error */ + CSSMERR_APPLE_DOTMAC_REQ_SERVER_ERR = CSSM_TP_PRIVATE_ERROR + 102, + /* server-reported parameter error */ + CSSMERR_APPLE_DOTMAC_REQ_SERVER_PARAM = CSSM_TP_PRIVATE_ERROR + 103, + /* server-reported authorization error */ + CSSMERR_APPLE_DOTMAC_REQ_SERVER_AUTH = CSSM_TP_PRIVATE_ERROR + 104, + /* server-reported unimplemented */ + CSSMERR_APPLE_DOTMAC_REQ_SERVER_UNIMPL = CSSM_TP_PRIVATE_ERROR + 105, + /* server-reported not available */ + CSSMERR_APPLE_DOTMAC_REQ_SERVER_NOT_AVAIL = CSSM_TP_PRIVATE_ERROR + 106, + /* server-reported already exists */ + CSSMERR_APPLE_DOTMAC_REQ_SERVER_ALREADY_EXIST = CSSM_TP_PRIVATE_ERROR + 107, + /* server-reported service error */ + CSSMERR_APPLE_DOTMAC_REQ_SERVER_SERVICE_ERROR = CSSM_TP_PRIVATE_ERROR + 108, + /* request already pending for specified user */ + CSSMERR_APPLE_DOTMAC_REQ_IS_PENDING = CSSM_TP_PRIVATE_ERROR + 109, + /* no request pending for specified user */ + CSSMERR_APPLE_DOTMAC_NO_REQ_PENDING = CSSM_TP_PRIVATE_ERROR + 110, + /* CSR failed to verify */ + CSSMERR_APPLE_DOTMAC_CSR_VERIFY_FAIL = CSSM_TP_PRIVATE_ERROR + 111, + /* server reported failed consistency check */ + CSSMERR_APPLE_DOTMAC_FAILED_CONSISTENCY_CHECK = CSSM_TP_PRIVATE_ERROR + 112 +}; + +enum +{ + CSSM_APPLEDL_OPEN_PARAMETERS_VERSION = 1 +}; + +enum cssm_appledl_open_parameters_mask +{ + kCSSM_APPLEDL_MASK_MODE = (1 << 0) +}; + +/* Pass a CSSM_APPLEDL_OPEN_PARAMETERS_PTR as the OpenParameters argument to + CSSM_DL_DbCreate or CSSM_DL_DbOpen. When using this struct, you must zero + out the entire struct before setting any additional parameters to ensure + forward compatibility. */ +typedef struct cssm_appledl_open_parameters +{ + uint32 length; /* Should be sizeof(CSSM_APPLEDL_OPEN_PARAMETERS). */ + uint32 version; /* Should be CSSM_APPLEDL_OPEN_PARAMETERS_VERSION. */ + + /* If no OpenParameters are specified, autoCommit is on (!CSSM_FALSE) by default. + When autoCommit is on (!CSSM_FALSE), changes made to the Db are written to disk + before returning from each function. + When autoCommit is off (CSSM_FALSE), changes made to the database are not guaranteed + to be written to disk until the Db is closed. This is useful for bulk writes. + Be aware that if autoCommit is off, changes made in previous calls to the DL might + get rolled back if a new modification operation fails. */ + CSSM_BOOL autoCommit; + + /* Mask marking which of the following fields are to be used. */ + uint32 mask; + + /* When calling DbCreate, the initial mode to create the database file with; ignored on DbOpen. You must set the kCSSM_APPLEDL_MASK_MODE bit in mask or mode is ignored. */ + mode_t mode; +} CSSM_APPLEDL_OPEN_PARAMETERS, *CSSM_APPLEDL_OPEN_PARAMETERS_PTR; + + +/* AppleCSPDL passthough ids */ +enum +{ + /* Tell the SecurityServer to lock the database specified by the DLDBHandle argument. + The InputParams and OutputParams arguments are ignored. */ + CSSM_APPLECSPDL_DB_LOCK = 0, + + /* Tell the SecurityServer to unlock the database specified by the DLDBHandle argument. + The InputParameters argument is a CSSM_DATA_PTR containing the password, or NULL if + the SecurityServer should prompt for the password. + The OutputParams argument is ignored. + The SecurityServer will put up UI (though the SecurityAgent) when this function is called + iff InputParameters is NULL. */ + CSSM_APPLECSPDL_DB_UNLOCK = 1, + + /* Ask the SecurityServer to get the db settings specified for the database + specified by the DLDBHandle argument. The settings are returned in the OutputParameters argument. + The OutputParameters argument is a pointer to a CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS_PTR. + Upon successful completion, the AppleCSPDL will have allocated a + CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS structure using the application-specified + allocators for the DL attachment specified by the DLDBHandle argument. The structure will contain + the current database settings for the specified database. The client should free the + CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS_PTR after it has finished using it. + The InputParameters argument is ignored. + The SecurityServer might put up UI (though the SecurityAgent) when this function is called. */ + CSSM_APPLECSPDL_DB_GET_SETTINGS = 2, + + /* Tell the SecurityServer to set the db settings specified in InputParameters on the database + specified by the DLDBHandle argument. + The InputParameters argument is a const CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS * containing + the new settings for the specified database. + The OutputParams argument is ignored. + The SecurityServer might put up UI (though the SecurityAgent) when this function is called. */ + CSSM_APPLECSPDL_DB_SET_SETTINGS = 3, + + /* Ask the SecurityServer whether the database specified by the DLDBHandle argument is locked. + The InputParameters argument is ignored. + The OutputParameters argument is a pointer to a CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS_PTR. + Upon successful completion, the AppleCSPDL will have allocated a + CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS structure using the application-specified + allocators for the DL attachment specified by the DLDBHandle argument. The structure will contain + the current lock status for the specified database. The client should free the + CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS_PTR after it has finished using it. + The SecurityServer will put up UI (though the SecurityAgent) when this function is called. */ + CSSM_APPLECSPDL_DB_IS_LOCKED = 4, + + /* Tell the SecurityServer to change the password for the database specified by + the DLDBHandle. + + The InputParameters argument is a const CSSM_APPLECSPDL_DB_CHANGE_PASSWORD_PARAMETERS * containing + a CSSM_ACCESS_CREDENTIALS * which determines how the password will be changed. If the + accessCredentials are NULL, the SecurityAgent will prompt for the old and the new password for the + specified database. If credentials are specified, there should be 2 entries: + 1. a 3-element list containing: + CSSM_WORDID_KEYCHAIN_LOCK, CSSM_SAMPLE_TYPE_PASSWORD, and the old password. + 2. a 3-element list containing: + CSSM_WORDID_KEYCHAIN_CHANGE_LOCK, CSSM_SAMPLE_TYPE_PASSWORD, and the new password. + + The OutputParams argument is ignored. + The SecurityServer might put up UI (though the SecurityAgent) when this function is called. */ + CSSM_APPLECSPDL_DB_CHANGE_PASSWORD =5, + + /* Return the SecurityServer database handle for the database specified by the DLDBHandle */ + CSSM_APPLECSPDL_DB_GET_HANDLE = 6, + + /* Given a CSSM_KEY for the CSPDL, return the SecurityServer key handle */ + CSSM_APPLESCPDL_CSP_GET_KEYHANDLE = 7, + + CSSM_APPLE_PRIVATE_CSPDL_CODE_8 = 8, + CSSM_APPLE_PRIVATE_CSPDL_CODE_9 = 9, + CSSM_APPLE_PRIVATE_CSPDL_CODE_10 = 10, + CSSM_APPLE_PRIVATE_CSPDL_CODE_11 = 11, + CSSM_APPLE_PRIVATE_CSPDL_CODE_12 = 12, + CSSM_APPLE_PRIVATE_CSPDL_CODE_13 = 13, + CSSM_APPLE_PRIVATE_CSPDL_CODE_14 = 14, + CSSM_APPLE_PRIVATE_CSPDL_CODE_15 = 15, + CSSM_APPLE_PRIVATE_CSPDL_CODE_16 = 16, + CSSM_APPLE_PRIVATE_CSPDL_CODE_17 = 17, + CSSM_APPLE_PRIVATE_CSPDL_CODE_18 = 18, + + /* Given a CSSM_KEY_PTR in any format, obtain the SHA-1 hash of the + * associated key blob. + * Key is specified in CSSM_CSP_CreatePassThroughContext. + * Hash is allocated bythe CSP, in the App's memory, and returned + * in *outData. */ + CSSM_APPLECSP_KEYDIGEST = 0x100 +}; + + + +/* AppleCSPDL passthough parameters */ +typedef struct cssm_applecspdl_db_settings_parameters +{ + uint32 idleTimeout; // seconds idle timeout lock + uint8 lockOnSleep; // lock database when system sleeps +} CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS, *CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS_PTR; + +/* AppleCSPDL passthough parameters */ +typedef struct cssm_applecspdl_db_is_locked_parameters +{ + uint8 isLocked; // True iff the database is locked +} CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS, *CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS_PTR; + +/* AppleCSPDL passthough parameters */ +typedef struct cssm_applecspdl_db_change_password_parameters +{ + CSSM_ACCESS_CREDENTIALS *accessCredentials; +} CSSM_APPLECSPDL_DB_CHANGE_PASSWORD_PARAMETERS, *CSSM_APPLECSPDL_DB_CHANGE_PASSWORD_PARAMETERS_PTR; + +/* Custom wrapped key formats */ +enum { + CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM = 100, + CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSL, // traditional openssl + CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1 // OpenSSH v1 +}; + +/* + * Custom context attributes for AppleCSP. + */ +enum { + CSSM_ATTRIBUTE_VENDOR_DEFINED = 0x800000 +}; + +enum { + /* + * Public Key attribute for use with CSSM_ALGID_FEED. + */ + CSSM_ATTRIBUTE_PUBLIC_KEY = + (CSSM_ATTRIBUTE_DATA_KEY | (CSSM_ATTRIBUTE_VENDOR_DEFINED + 0)), + + /* + * FEE key attributes. + * See CSSM_FEE_PRIME_TYPE_xxx, CSSM_FEE_CURVE_TYPE_xxx enums, below. + */ + CSSM_ATTRIBUTE_FEE_PRIME_TYPE = + (CSSM_ATTRIBUTE_DATA_UINT32 | (CSSM_ATTRIBUTE_VENDOR_DEFINED + 1)), + CSSM_ATTRIBUTE_FEE_CURVE_TYPE = + (CSSM_ATTRIBUTE_DATA_UINT32 | (CSSM_ATTRIBUTE_VENDOR_DEFINED + 2)), + + /* + * Apple Secure Compression (ComCryption) optimization. + * See CSSM_ASC_OPTIMIZE_xxx, enums, below. + */ + CSSM_ATTRIBUTE_ASC_OPTIMIZATION = + (CSSM_ATTRIBUTE_DATA_UINT32 | (CSSM_ATTRIBUTE_VENDOR_DEFINED + 3)), + + /* + * RSA blinding. Value is integer, nonzero (blinding on) or zero. + */ + CSSM_ATTRIBUTE_RSA_BLINDING = + (CSSM_ATTRIBUTE_DATA_UINT32 | (CSSM_ATTRIBUTE_VENDOR_DEFINED + 4)), + + /* + * Additional public key from which to obtain algorithm-specific + * parameters. + */ + CSSM_ATTRIBUTE_PARAM_KEY = + (CSSM_ATTRIBUTE_DATA_KEY | (CSSM_ATTRIBUTE_VENDOR_DEFINED + 5)), + + /* + * Prompt string for CSSM_ALGID_SECURE_PASSPHRASE key acquisition. + * Data is a UTF8-encoded external representation of a CFString. + */ + CSSM_ATTRIBUTE_PROMPT = + (CSSM_ATTRIBUTE_DATA_CSSM_DATA | (CSSM_ATTRIBUTE_VENDOR_DEFINED + 6)), + + /* + * Alert panel title for CSSM_ALGID_SECURE_PASSPHRASE key acquisition. + * Data is a UTF8-encoded external representation of a CFString. + */ + CSSM_ATTRIBUTE_ALERT_TITLE = + (CSSM_ATTRIBUTE_DATA_CSSM_DATA | (CSSM_ATTRIBUTE_VENDOR_DEFINED + 7)), + + /* + * Boolean to specify whether secure passphrase is being used to encrypt or to + * recover data. In the former case the user will be prompted to enter the + * passphrase twice. Value is integer, nonzero (verify passphrase) or zero. + */ + CSSM_ATTRIBUTE_VERIFY_PASSPHRASE = + (CSSM_ATTRIBUTE_DATA_UINT32 | (CSSM_ATTRIBUTE_VENDOR_DEFINED + 8)) + +}; + +/* + * FEE key pair prime modulus types. + */ +enum { + CSSM_FEE_PRIME_TYPE_DEFAULT = 0, /* default per key size */ + CSSM_FEE_PRIME_TYPE_MERSENNE, /* (2 ** q) - 1Ê*/ + CSSM_FEE_PRIME_TYPE_FEE, /* (2 ** q) - k */ + CSSM_FEE_PRIME_TYPE_GENERAL /* random prime */ +}; + +/* + * FEE curve types. Comments refer to equation + * + * y**2 = x**3 + c(x**2) + ax + b + */ +enum { + CSSM_FEE_CURVE_TYPE_DEFAULT = 0, /* default per key size */ + CSSM_FEE_CURVE_TYPE_MONTGOMERY, /* a==1, b==0 */ + CSSM_FEE_CURVE_TYPE_WEIERSTRASS, /* c==0. IEEE P1363 compliant. */ + CSSM_FEE_CURVE_TYPE_ANSI_X9_62 /* ANSI X9.62 compatible */ +}; + +/* + * Apple Secure Compression (ComCryption) optimization attributes. + */ +enum { + CSSM_ASC_OPTIMIZE_DEFAULT = 0, + CSSM_ASC_OPTIMIZE_SIZE, /* max compression (currently the default) */ + CSSM_ASC_OPTIMIZE_SECURITY, /* currently not implemented */ + CSSM_ASC_OPTIMIZE_TIME, /* min runtime */ + CSSM_ASC_OPTIMIZE_TIME_SIZE, /* implies loss of security */ + CSSM_ASC_OPTIMIZE_ASCII, /* optimized for ASCC text, not implemented */ +}; + +/* + * Apple custom CSSM_KEYATTR_FLAGS. + */ +enum { + /* + * When set, indicates a public key which is incomplete (though + * still valid) due to the lack of algorithm-specific parameters. + */ + CSSM_KEYATTR_PARTIAL = 0x00010000, + + /* + * When set, public keys are stored encrypted. Default is to store + * public keys in the clear. AppleCSPDL only. + */ + CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT = 0x00020000 +}; + +/* + * Name/OID pair used in CSSM_APPLE_TP_CERT_REQUEST + */ +typedef struct { + const char *string; + const CSSM_OID *oid; +} CSSM_APPLE_TP_NAME_OID; + +/* + * Certificate request passed to CSSM_TP_SubmitCredRequest() in the + * CSSM_TP_AUTHORITY_REQUEST_TYPE.Requests field. Used for requesting + * both locally-generated certs (CSSMOID_APPLE_TP_LOCAL_CERT_GEN) and + * cert signing requests (CSSMOID_APPLE_TP_CSR_GEN). + */ +typedef struct { + CSSM_CSP_HANDLE cspHand; // sign with this CSP + CSSM_CL_HANDLE clHand; // and this CL + uint32 serialNumber; + uint32 numSubjectNames;// size subjectNames[] + CSSM_APPLE_TP_NAME_OID *subjectNames; + + /* + * Issuer name can be expressed in the simplified CSSM_APPLE_TP_NAME_OID + * array, as is the subject name, or as an CSSM_X509_NAME, which is + * typically obtained from a signing cert. + * Exactly one of {issuerNames, issuerNameX509} must be non-NULL. + */ + uint32 numIssuerNames; // size issuerNames[] + CSSM_APPLE_TP_NAME_OID *issuerNames; // optional; NULL implies root + // (signer == subject) + CSSM_X509_NAME_PTR issuerNameX509; + const CSSM_KEY *certPublicKey; + const CSSM_KEY *issuerPrivateKey; + + /* Unfortunately there is no practical way to map any algorithm + * to its appropriate OID, and we need both.... */ + CSSM_ALGORITHMS signatureAlg; // e.g., CSSM_ALGID_SHA1WithRSA + CSSM_OID signatureOid; // e.g., CSSMOID_SHA1WithRSA + uint32 notBefore; // relative to "now" + uint32 notAfter; + uint32 numExtensions; + CE_DataAndType *extensions; // optional + + /* + * Optional challenge string for CSSMOID_APPLE_TP_CSR_GEN. + */ + const char *challengeString; +} CSSM_APPLE_TP_CERT_REQUEST; + +/* + * Options for X509TP's CSSM_TP_CertGroupVerify for policy CSSMOID_APPLE_TP_SSL. + * A pointer to, and length of, one of these is optionally placed in + * CSSM_TP_VERIFY_CONTEXT.Cred->Policy.PolicyIds[n].FieldValue. + */ +#define CSSM_APPLE_TP_SSL_OPTS_VERSION 1 + +/* + * Values for CSSM_APPLE_TP_SSL_OPTIONS.flags. + * + * Set this flag when evaluating a client cert. + */ +#define CSSM_APPLE_TP_SSL_CLIENT 0x00000001 + +typedef struct { + uint32 Version; // CSSM_APPLE_TP_SSL_OPTS_VERSION + + /* + * The domain name of the server (e.g., "store.apple.com".) In the + * SSL and TLS protocols, this must match the common name of the + * subject cert. Expressed as a C string, optionally NULL terminated + * if it is NULL terminated, the length field should include the NULL). + */ + uint32 ServerNameLen; + const char *ServerName; // optional + + /* new fields for struct version 1 */ + uint32 Flags; +} CSSM_APPLE_TP_SSL_OPTIONS; + +/* + * Options for X509TP's CSSM_TP_CertGroupVerify for policy + * CSSMOID_APPLE_TP_REVOCATION_CRL. A pointer to, and length of, one + * of these is optionally placed in + * CSSM_TP_VERIFY_CONTEXT.Cred->Policy.PolicyIds[n].FieldValue. + */ +#define CSSM_APPLE_TP_CRL_OPTS_VERSION 0 + +typedef uint32 CSSM_APPLE_TP_CRL_OPT_FLAGS; +enum { + // require CRL verification for each cert; default is "try" + CSSM_TP_ACTION_REQUIRE_CRL_PER_CERT = 0x00000001, + // enable fetch from network + CSSM_TP_ACTION_FETCH_CRL_FROM_NET = 0x00000002, + // if set and positive OCSP verify for given cert, no further revocation + // checking need be done on that cert + CSSM_TP_ACTION_CRL_SUFFICIENT = 0x00000004, + // require CRL verification for certs which claim a CRL provider + CSSM_TP_ACTION_REQUIRE_CRL_IF_PRESENT = 0x00000008 +}; + +typedef struct { + uint32 Version; // CSSM_APPLE_TP_CRL_OPTS_VERSION + CSSM_APPLE_TP_CRL_OPT_FLAGS CrlFlags; + + /* + * When non-NULL, store CRLs fetched from net here. + * This is most likely a pointer to one of the + * CSSM_TP_CALLERAUTH_CONTEXT.DBList entries but that + * is not a strict requirement. + */ + CSSM_DL_DB_HANDLE_PTR crlStore; +} CSSM_APPLE_TP_CRL_OPTIONS; + +/* + * Options for X509TP's CSSM_TP_CertGroupVerify for policy + * CSSMOID_APPLE_TP_SMIME. A pointer to, and length of, one + * of these is optionally placed in + * CSSM_TP_VERIFY_CONTEXT.Cred->Policy.PolicyIds[n].FieldValue. + */ +#define CSSM_APPLE_TP_SMIME_OPTS_VERSION 0 +typedef struct { + uint32 Version; // CSSM_APPLE_TP_SMIME_OPTS_VERSION + + /* + * Intended usage of the leaf cert. The cert's KeyUsage extension, + * if present, must be a superset of this. + */ + CE_KeyUsage IntendedUsage; + + /* + * The email address of the sender. If there is an email address + * in the sender's cert, that email address must match this one. + * Both (email address in the cert, and this one) are optional. + * Expressed as a C string, optionally NULL terminated (i.e., + * SenderEmail[SenderEmailLen - 1] may or may not be NULL). + */ + uint32 SenderEmailLen; + const char *SenderEmail; // optional +} CSSM_APPLE_TP_SMIME_OPTIONS; + + +/* + * Optional ActionData for all X509TP CertGroupVerify policies. + * A pointer to, and length of, one of these is optionally placed in + * CSSM_TP_VERIFY_CONTEXT.ActionData. + */ +typedef uint32 CSSM_APPLE_TP_ACTION_FLAGS; +enum { + CSSM_TP_ACTION_ALLOW_EXPIRED = 0x00000001, // allow expired certs + CSSM_TP_ACTION_LEAF_IS_CA = 0x00000002, // first cert is a CA + CSSM_TP_ACTION_FETCH_CERT_FROM_NET = 0x00000004, // enable net fetch of CA cert + CSSM_TP_ACTION_ALLOW_EXPIRED_ROOT = 0x00000008, // allow expired roots + CSSM_TP_ACTION_REQUIRE_REV_PER_CERT = 0x00000010, // require positive revocation + // check per cert + CSSM_TP_ACTION_TRUST_SETTINGS = 0x00000020, // use TrustSettings instead of + // anchors + CSSM_TP_ACTION_IMPLICIT_ANCHORS = 0x00000040 // properly self-signed certs are + // treated as anchors implicitly +}; + +#define CSSM_APPLE_TP_ACTION_VERSION 0 +typedef struct { + uint32 Version; // CSSM_APPLE_TP_ACTION_VERSION + CSSM_APPLE_TP_ACTION_FLAGS ActionFlags; // CSSM_TP_ACTION_ALLOW_EXPIRED, etc. +} CSSM_APPLE_TP_ACTION_DATA; + +/* + * Per-cert evidence returned from CSSM_TP_CertGroupVerify. + * An array of these is presented in CSSM_TP_VERIFY_CONTEXT_RESULT.Evidence[2]. + * Same number of these as in the cert group in Evidence[1]. + */ + +/* First, an array of bits indicating various status of the cert. */ +typedef uint32 CSSM_TP_APPLE_CERT_STATUS; +enum +{ + CSSM_CERT_STATUS_EXPIRED = 0x00000001, + CSSM_CERT_STATUS_NOT_VALID_YET = 0x00000002, + CSSM_CERT_STATUS_IS_IN_INPUT_CERTS = 0x00000004, + CSSM_CERT_STATUS_IS_IN_ANCHORS = 0x00000008, + CSSM_CERT_STATUS_IS_ROOT = 0x00000010, + CSSM_CERT_STATUS_IS_FROM_NET = 0x00000020, + /* settings found in per-user Trust Settings */ + CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_USER = 0x00000040, + /* settings found in Admin Trust Settings */ + CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_ADMIN = 0x00000080, + /* settings found in System Trust Settings */ + CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_SYSTEM = 0x00000100, + /* Trust Settings result = Trust */ + CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST = 0x00000200, + /* Trust Settings result = Deny */ + CSSM_CERT_STATUS_TRUST_SETTINGS_DENY = 0x00000400, + /* Per-cert error ignored due to Trust Settings */ + CSSM_CERT_STATUS_TRUST_SETTINGS_IGNORED_ERROR = 0x00000800 +}; + +typedef struct { + CSSM_TP_APPLE_CERT_STATUS StatusBits; + uint32 NumStatusCodes; + CSSM_RETURN *StatusCodes; + + /* index into raw cert group or AnchorCerts depending on IS_IN_ANCHORS */ + uint32 Index; + + /* nonzero if cert came from a DLDB */ + CSSM_DL_DB_HANDLE DlDbHandle; + CSSM_DB_UNIQUE_RECORD_PTR UniqueRecord; +} CSSM_TP_APPLE_EVIDENCE_INFO; + +/* + * CSSM_TP_VERIFY_CONTEXT_RESULT.Evidence[0], basically defines which version/flavor + * of remaining evidence is. + */ +#define CSSM_TP_APPLE_EVIDENCE_VERSION 0 +typedef struct +{ + uint32 Version; +} CSSM_TP_APPLE_EVIDENCE_HEADER; + + +/* + * Apple-specific CSSM_EVIDENCE_FORM values + * + * The form of the evidence returns from CSSM_TP_CertGroupVerify is: + * + * EvidenceForm contents of *Evidence + * ------------ --------------------- + * CSSM_EVIDENCE_FORM_APPLE_HEADER CSSM_TP_APPLE_EVIDENCE_HEADER + * CSSM_EVIDENCE_FORM_APPLE_CERTGROUP CSSM_CERTGROUP + * CSSM_EVIDENCE_FORM_APPLE_CERT_INFO array of CSSM_TP_APPLE_EVIDENCE_INFO, size + * CSSM_CERTGROUP.NumCerts + */ + +#define CSSM_EVIDENCE_FORM_APPLE_CUSTOM 0x80000000 +enum +{ + CSSM_EVIDENCE_FORM_APPLE_HEADER = CSSM_EVIDENCE_FORM_APPLE_CUSTOM + 0, + CSSM_EVIDENCE_FORM_APPLE_CERTGROUP = CSSM_EVIDENCE_FORM_APPLE_CUSTOM + 1, + CSSM_EVIDENCE_FORM_APPLE_CERT_INFO = CSSM_EVIDENCE_FORM_APPLE_CUSTOM + 2 +}; + +/* AppleX509CL extensions: passthrough ids */ +enum { + /* + * Obtain a signed Certificate Signing Request. + * Input = CSSM_APPLE_CL_CSR_REQUEST + * Output = allocated CSSM_DATA which points to a DER-encoded CSR. + */ + CSSM_APPLEX509CL_OBTAIN_CSR, + + /* + * Perform signature verify of a CSR. + * Input: CSSM_DATA referring to a DER-encoded CSR. + * Output: Nothing, returns CSSMERR_CL_VERIFICATION_FAILURE on + * on failure. + */ + CSSM_APPLEX509CL_VERIFY_CSR +}; + +/* + * Used in CL's CSSM_APPLEX509_OBTAIN_CSR Passthrough. This is the + * input; the output is a CSSM_DATA * containing the signed and + * DER-encoded CSR. + */ +typedef struct { + CSSM_X509_NAME_PTR subjectNameX509; + + /* Unfortunately there is no practical way to map any algorithm + * to its appropriate OID, and we need both.... */ + CSSM_ALGORITHMS signatureAlg; // e.g., CSSM_ALGID_SHA1WithRSA + CSSM_OID signatureOid; // e.g., CSSMOID_SHA1WithRSA + + CSSM_CSP_HANDLE cspHand; // sign with this CSP + const CSSM_KEY *subjectPublicKey; + const CSSM_KEY *subjectPrivateKey; + + /* + * Optional challenge string. + */ + const char *challengeString; +} CSSM_APPLE_CL_CSR_REQUEST; + +/* + * When a CRL with no NextUpdate field is encountered, we use this time + * as the NextUpdate attribute when storing in a DB. It represents the + * virtual end of time in CSSM_TIMESTRING form. + */ +#define CSSM_APPLE_CRL_END_OF_TIME "99991231235959" + +/* + * Default filesystem names and locations for SecurityServer features + * (included here for lack of a better place) + */ +#define kKeychainSuffix ".keychain" +#define kSystemKeychainName "System.keychain" +#define kSystemKeychainDir "/Library/Keychains/" +#define kSystemUnlockFile "/var/db/SystemKey" + + +void cssmPerror(const char *how, CSSM_RETURN error); + +/* Convert between CSSM_OID and CSSM_ALGORITHMS */ +bool cssmOidToAlg(const CSSM_OID *oid, CSSM_ALGORITHMS *alg); +const CSSM_OID *cssmAlgToOid(CSSM_ALGORITHMS algId); + +/* + * The MacOS OSStatus space has an embedding for UNIX errno values, similar to + * the way we embed CSSM_RETURN values in OSStatus. These are the base and limit + * values for this embedding. + */ +#define errSecErrnoBase 100000 +#define errSecErrnoLimit 100255 + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* _CSSMAPPLE_H_ */ diff --git a/libsecurity_cssm/lib/cssmapplePriv.h b/Security/libsecurity_cssm/lib/cssmapplePriv.h similarity index 98% rename from libsecurity_cssm/lib/cssmapplePriv.h rename to Security/libsecurity_cssm/lib/cssmapplePriv.h index 4b008fd4..f5dc442e 100644 --- a/libsecurity_cssm/lib/cssmapplePriv.h +++ b/Security/libsecurity_cssm/lib/cssmapplePriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/cssmcli.h b/Security/libsecurity_cssm/lib/cssmcli.h similarity index 99% rename from libsecurity_cssm/lib/cssmcli.h rename to Security/libsecurity_cssm/lib/cssmcli.h index 5fdffbc8..61c02bd6 100644 --- a/libsecurity_cssm/lib/cssmcli.h +++ b/Security/libsecurity_cssm/lib/cssmcli.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/cssmconfig.h b/Security/libsecurity_cssm/lib/cssmconfig.h similarity index 96% rename from libsecurity_cssm/lib/cssmconfig.h rename to Security/libsecurity_cssm/lib/cssmconfig.h index f1fcd5fa..560e0828 100644 --- a/libsecurity_cssm/lib/cssmconfig.h +++ b/Security/libsecurity_cssm/lib/cssmconfig.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004,2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2007,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/cssmcontext.cpp b/Security/libsecurity_cssm/lib/cssmcontext.cpp similarity index 99% rename from libsecurity_cssm/lib/cssmcontext.cpp rename to Security/libsecurity_cssm/lib/cssmcontext.cpp index 14f09861..6e5763a7 100644 --- a/libsecurity_cssm/lib/cssmcontext.cpp +++ b/Security/libsecurity_cssm/lib/cssmcontext.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/cssmcontext.h b/Security/libsecurity_cssm/lib/cssmcontext.h similarity index 98% rename from libsecurity_cssm/lib/cssmcontext.h rename to Security/libsecurity_cssm/lib/cssmcontext.h index 3f3f120f..6f825019 100644 --- a/libsecurity_cssm/lib/cssmcontext.h +++ b/Security/libsecurity_cssm/lib/cssmcontext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/cssmcspi.h b/Security/libsecurity_cssm/lib/cssmcspi.h similarity index 99% rename from libsecurity_cssm/lib/cssmcspi.h rename to Security/libsecurity_cssm/lib/cssmcspi.h index ac989941..44c9ecee 100644 --- a/libsecurity_cssm/lib/cssmcspi.h +++ b/Security/libsecurity_cssm/lib/cssmcspi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/cssmdli.h b/Security/libsecurity_cssm/lib/cssmdli.h similarity index 98% rename from libsecurity_cssm/lib/cssmdli.h rename to Security/libsecurity_cssm/lib/cssmdli.h index a62fe845..14848fd5 100644 --- a/libsecurity_cssm/lib/cssmdli.h +++ b/Security/libsecurity_cssm/lib/cssmdli.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/cssmerr.h b/Security/libsecurity_cssm/lib/cssmerr.h similarity index 99% rename from libsecurity_cssm/lib/cssmerr.h rename to Security/libsecurity_cssm/lib/cssmerr.h index 047380ea..9d518fd5 100644 --- a/libsecurity_cssm/lib/cssmerr.h +++ b/Security/libsecurity_cssm/lib/cssmerr.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2002,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 1999-2002,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/cssmint.h b/Security/libsecurity_cssm/lib/cssmint.h similarity index 97% rename from libsecurity_cssm/lib/cssmint.h rename to Security/libsecurity_cssm/lib/cssmint.h index b682653a..10dcaaf3 100644 --- a/libsecurity_cssm/lib/cssmint.h +++ b/Security/libsecurity_cssm/lib/cssmint.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/cssmkrapi.h b/Security/libsecurity_cssm/lib/cssmkrapi.h similarity index 99% rename from libsecurity_cssm/lib/cssmkrapi.h rename to Security/libsecurity_cssm/lib/cssmkrapi.h index a60add52..984f2f4f 100644 --- a/libsecurity_cssm/lib/cssmkrapi.h +++ b/Security/libsecurity_cssm/lib/cssmkrapi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/cssmkrspi.h b/Security/libsecurity_cssm/lib/cssmkrspi.h similarity index 98% rename from libsecurity_cssm/lib/cssmkrspi.h rename to Security/libsecurity_cssm/lib/cssmkrspi.h index 8e5bf5c8..e27c165f 100644 --- a/libsecurity_cssm/lib/cssmkrspi.h +++ b/Security/libsecurity_cssm/lib/cssmkrspi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/cssmmds.cpp b/Security/libsecurity_cssm/lib/cssmmds.cpp similarity index 95% rename from libsecurity_cssm/lib/cssmmds.cpp rename to Security/libsecurity_cssm/lib/cssmmds.cpp index 2b3c2c5d..e6dada5d 100644 --- a/libsecurity_cssm/lib/cssmmds.cpp +++ b/Security/libsecurity_cssm/lib/cssmmds.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/cssmmds.h b/Security/libsecurity_cssm/lib/cssmmds.h similarity index 96% rename from libsecurity_cssm/lib/cssmmds.h rename to Security/libsecurity_cssm/lib/cssmmds.h index 0286fa1c..b0ed1fd9 100644 --- a/libsecurity_cssm/lib/cssmmds.h +++ b/Security/libsecurity_cssm/lib/cssmmds.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/cssmspi.h b/Security/libsecurity_cssm/lib/cssmspi.h similarity index 98% rename from libsecurity_cssm/lib/cssmspi.h rename to Security/libsecurity_cssm/lib/cssmspi.h index 2a911b01..35e8ea91 100644 --- a/libsecurity_cssm/lib/cssmspi.h +++ b/Security/libsecurity_cssm/lib/cssmspi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2003-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/cssmtpi.h b/Security/libsecurity_cssm/lib/cssmtpi.h similarity index 99% rename from libsecurity_cssm/lib/cssmtpi.h rename to Security/libsecurity_cssm/lib/cssmtpi.h index 81be4eea..701a5ebd 100644 --- a/libsecurity_cssm/lib/cssmtpi.h +++ b/Security/libsecurity_cssm/lib/cssmtpi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/cssmtype.h b/Security/libsecurity_cssm/lib/cssmtype.h similarity index 99% rename from libsecurity_cssm/lib/cssmtype.h rename to Security/libsecurity_cssm/lib/cssmtype.h index aaf17466..7904d1fd 100644 --- a/libsecurity_cssm/lib/cssmtype.h +++ b/Security/libsecurity_cssm/lib/cssmtype.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2002,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 1999-2002,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -1220,7 +1220,7 @@ typedef struct cssm_csp_operational_statistics { /* Indicates that the statistical value can not be revealed or is not relevant for a CSP */ enum { - CSSM_VALUE_NOT_AVAILABLE = (uint32)(~0) + CSSM_VALUE_NOT_AVAILABLE = -1 }; typedef struct cssm_pkcs5_pbkdf1_params { diff --git a/libsecurity_cssm/lib/eisl.h b/Security/libsecurity_cssm/lib/eisl.h similarity index 99% rename from libsecurity_cssm/lib/eisl.h rename to Security/libsecurity_cssm/lib/eisl.h index 48d44fca..fa044731 100644 --- a/libsecurity_cssm/lib/eisl.h +++ b/Security/libsecurity_cssm/lib/eisl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2002,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 1999-2002,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -304,7 +304,7 @@ EISL_LocateProcedureAddress (ISL_VERIFIED_MODULE_PTR Module, #ifdef MACOSX #define EISL_GetReturnAddress(Address) \ {\ - /* Platform specific code in here */ + /* Platform specific code in here */ \ } #endif diff --git a/libsecurity_cssm/lib/emmspi.h b/Security/libsecurity_cssm/lib/emmspi.h similarity index 98% rename from libsecurity_cssm/lib/emmspi.h rename to Security/libsecurity_cssm/lib/emmspi.h index 4a8b4247..f986952d 100644 --- a/libsecurity_cssm/lib/emmspi.h +++ b/Security/libsecurity_cssm/lib/emmspi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/emmtype.h b/Security/libsecurity_cssm/lib/emmtype.h similarity index 96% rename from libsecurity_cssm/lib/emmtype.h rename to Security/libsecurity_cssm/lib/emmtype.h index 3ed3a60b..2fb04a5e 100644 --- a/libsecurity_cssm/lib/emmtype.h +++ b/Security/libsecurity_cssm/lib/emmtype.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/generator.cfg b/Security/libsecurity_cssm/lib/generator.cfg similarity index 100% rename from libsecurity_cssm/lib/generator.cfg rename to Security/libsecurity_cssm/lib/generator.cfg diff --git a/libsecurity_cssm/lib/generator.mk b/Security/libsecurity_cssm/lib/generator.mk similarity index 95% rename from libsecurity_cssm/lib/generator.mk rename to Security/libsecurity_cssm/lib/generator.mk index 55aeb165..95f0be1d 100644 --- a/libsecurity_cssm/lib/generator.mk +++ b/Security/libsecurity_cssm/lib/generator.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2001,2004 Apple Computer, Inc. All Rights Reserved. +# Copyright (c) 2001,2004,2011,2014 Apple Inc. All Rights Reserved. # # @APPLE_LICENSE_HEADER_START@ # diff --git a/libsecurity_cssm/lib/generator.pl b/Security/libsecurity_cssm/lib/generator.pl similarity index 98% rename from libsecurity_cssm/lib/generator.pl rename to Security/libsecurity_cssm/lib/generator.pl index db6ad204..e4792ac9 100644 --- a/libsecurity_cssm/lib/generator.pl +++ b/Security/libsecurity_cssm/lib/generator.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl # -# Copyright (c) 2001-2004 Apple Computer, Inc. All Rights Reserved. +# Copyright (c) 2001-2004,2011-2012,2014 Apple Inc. All Rights Reserved. # # @APPLE_LICENSE_HEADER_START@ # @@ -131,7 +131,6 @@ for $name (sort keys %formals) { $prefix = ""; # match the SPI; take care of the Privilege variants of some calls - # Jim Murphy Added [^;]* before the ; to allow for deprecation macros ($args) = $spi{$type} =~ /CSSM_RETURN \(CSSM${type}I \*$barename\)\s+\(([^)]*)\)[^;]*;/s or $barename =~ s/P$// && # second chance for FooBarP() API functions (($args) = $spi{$type} =~ /CSSM_RETURN \(CSSM${type}I \*$barename\)\s+\(([^)]*)\)[^;]*;/s) diff --git a/libsecurity_cssm/lib/guids.cpp b/Security/libsecurity_cssm/lib/guids.cpp similarity index 98% rename from libsecurity_cssm/lib/guids.cpp rename to Security/libsecurity_cssm/lib/guids.cpp index e3e6be7b..0baa49da 100644 --- a/libsecurity_cssm/lib/guids.cpp +++ b/Security/libsecurity_cssm/lib/guids.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/manager.cpp b/Security/libsecurity_cssm/lib/manager.cpp similarity index 99% rename from libsecurity_cssm/lib/manager.cpp rename to Security/libsecurity_cssm/lib/manager.cpp index 1441e71b..28511ed0 100644 --- a/libsecurity_cssm/lib/manager.cpp +++ b/Security/libsecurity_cssm/lib/manager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/manager.h b/Security/libsecurity_cssm/lib/manager.h similarity index 98% rename from libsecurity_cssm/lib/manager.h rename to Security/libsecurity_cssm/lib/manager.h index e4c634eb..2a59c4d0 100644 --- a/libsecurity_cssm/lib/manager.h +++ b/Security/libsecurity_cssm/lib/manager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/modload_plugin.cpp b/Security/libsecurity_cssm/lib/modload_plugin.cpp similarity index 98% rename from libsecurity_cssm/lib/modload_plugin.cpp rename to Security/libsecurity_cssm/lib/modload_plugin.cpp index 61770ad7..14ab1293 100644 --- a/libsecurity_cssm/lib/modload_plugin.cpp +++ b/Security/libsecurity_cssm/lib/modload_plugin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/modload_plugin.h b/Security/libsecurity_cssm/lib/modload_plugin.h similarity index 96% rename from libsecurity_cssm/lib/modload_plugin.h rename to Security/libsecurity_cssm/lib/modload_plugin.h index a834661c..9d131dff 100644 --- a/libsecurity_cssm/lib/modload_plugin.h +++ b/Security/libsecurity_cssm/lib/modload_plugin.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/modload_static.cpp b/Security/libsecurity_cssm/lib/modload_static.cpp similarity index 97% rename from libsecurity_cssm/lib/modload_static.cpp rename to Security/libsecurity_cssm/lib/modload_static.cpp index 9db19169..2596b899 100644 --- a/libsecurity_cssm/lib/modload_static.cpp +++ b/Security/libsecurity_cssm/lib/modload_static.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/modload_static.h b/Security/libsecurity_cssm/lib/modload_static.h similarity index 96% rename from libsecurity_cssm/lib/modload_static.h rename to Security/libsecurity_cssm/lib/modload_static.h index 4c0b5263..62ecc181 100644 --- a/libsecurity_cssm/lib/modload_static.h +++ b/Security/libsecurity_cssm/lib/modload_static.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/modloader.cpp b/Security/libsecurity_cssm/lib/modloader.cpp similarity index 98% rename from libsecurity_cssm/lib/modloader.cpp rename to Security/libsecurity_cssm/lib/modloader.cpp index 1f80798f..bf99d6d1 100644 --- a/libsecurity_cssm/lib/modloader.cpp +++ b/Security/libsecurity_cssm/lib/modloader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/modloader.h b/Security/libsecurity_cssm/lib/modloader.h similarity index 97% rename from libsecurity_cssm/lib/modloader.h rename to Security/libsecurity_cssm/lib/modloader.h index a34b2003..eb508179 100644 --- a/libsecurity_cssm/lib/modloader.h +++ b/Security/libsecurity_cssm/lib/modloader.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/module.cpp b/Security/libsecurity_cssm/lib/module.cpp similarity index 98% rename from libsecurity_cssm/lib/module.cpp rename to Security/libsecurity_cssm/lib/module.cpp index e7388ab3..7dce28fe 100644 --- a/libsecurity_cssm/lib/module.cpp +++ b/Security/libsecurity_cssm/lib/module.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/module.h b/Security/libsecurity_cssm/lib/module.h similarity index 97% rename from libsecurity_cssm/lib/module.h rename to Security/libsecurity_cssm/lib/module.h index 62e0b4b0..f1e26cdd 100644 --- a/libsecurity_cssm/lib/module.h +++ b/Security/libsecurity_cssm/lib/module.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_cssm/lib/oidsalg.c b/Security/libsecurity_cssm/lib/oidsalg.c new file mode 100644 index 00000000..f8372867 --- /dev/null +++ b/Security/libsecurity_cssm/lib/oidsalg.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* + * oidsalg.c - OIDs defining crypto algorithms + */ + +#include +#include +#include "cssmapple.h" +#include +#include + +#pragma mark ----- CSSM_OID <--> CSSM_ALGORITHMS ----- + +typedef struct { + const CSSM_OID *oid; + CSSM_ALGORITHMS alg; +} OidToAlgEnt; + +static const OidToAlgEnt oidToAlgMap[] = +{ + {&CSSMOID_RSA, CSSM_ALGID_RSA }, + {&CSSMOID_MD2WithRSA, CSSM_ALGID_MD2WithRSA }, + {&CSSMOID_MD5WithRSA, CSSM_ALGID_MD5WithRSA }, + {&CSSMOID_SHA1WithRSA, CSSM_ALGID_SHA1WithRSA }, + {&CSSMOID_SHA1WithRSA_OIW, CSSM_ALGID_SHA1WithRSA }, + {&CSSMOID_SHA1, CSSM_ALGID_SHA1}, + {&CSSMOID_MD5, CSSM_ALGID_MD5 }, + /* + * These OIDs have three variants - one for BSAFE, CMS, and JDK 1.1. + * On the oid-to-alg map, we'll handle either one, mapping to + * the same CSSM alg. When we map from alg to OID, we'll use + * the CMS variant (being first in the list). + */ + {&CSSMOID_DSA_CMS, CSSM_ALGID_DSA }, + {&CSSMOID_DSA, CSSM_ALGID_DSA }, + {&CSSMOID_DSA_JDK, CSSM_ALGID_DSA }, + {&CSSMOID_SHA1WithDSA_CMS, CSSM_ALGID_SHA1WithDSA }, + {&CSSMOID_SHA1WithDSA, CSSM_ALGID_SHA1WithDSA }, + {&CSSMOID_SHA1WithDSA_JDK, CSSM_ALGID_SHA1WithDSA }, + /* + * Multiple entries for Diffie-Hellman. We favor the PKCS3 version for + * mapping alg to OID. + */ + {&CSSMOID_DH, CSSM_ALGID_DH}, + {&CSSMOID_ANSI_DH_PUB_NUMBER, CSSM_ALGID_DH}, + {&CSSMOID_ANSI_DH_STATIC, CSSM_ALGID_DH}, + {&CSSMOID_ANSI_DH_ONE_FLOW, CSSM_ALGID_DH}, + {&CSSMOID_ANSI_DH_EPHEM, CSSM_ALGID_DH}, + {&CSSMOID_ANSI_DH_HYBRID1, CSSM_ALGID_DH}, + {&CSSMOID_ANSI_DH_HYBRID2, CSSM_ALGID_DH}, + {&CSSMOID_ANSI_DH_HYBRID_ONEFLOW, CSSM_ALGID_DH}, + {&CSSMOID_APPLE_FEE, CSSM_ALGID_FEE }, + {&CSSMOID_APPLE_ASC, CSSM_ALGID_ASC }, + {&CSSMOID_APPLE_FEE_MD5, CSSM_ALGID_FEE_MD5 }, + {&CSSMOID_APPLE_FEE_SHA1, CSSM_ALGID_FEE_SHA1 }, + {&CSSMOID_APPLE_FEED, CSSM_ALGID_FEED }, + {&CSSMOID_APPLE_FEEDEXP, CSSM_ALGID_FEEDEXP }, + /* the current valid alg --> OID mapping */ + {&CSSMOID_ECDSA_WithSHA1, CSSM_ALGID_SHA1WithECDSA}, + /* for backwards compatibility */ + {&CSSMOID_APPLE_ECDSA, CSSM_ALGID_SHA1WithECDSA }, + {&CSSMOID_SHA224, CSSM_ALGID_SHA224}, + {&CSSMOID_SHA256, CSSM_ALGID_SHA256}, + {&CSSMOID_SHA384, CSSM_ALGID_SHA384}, + {&CSSMOID_SHA512, CSSM_ALGID_SHA512}, + {&CSSMOID_SHA224WithRSA, CSSM_ALGID_SHA224WithRSA }, + {&CSSMOID_SHA256WithRSA, CSSM_ALGID_SHA256WithRSA }, + {&CSSMOID_SHA384WithRSA, CSSM_ALGID_SHA384WithRSA }, + {&CSSMOID_SHA512WithRSA, CSSM_ALGID_SHA512WithRSA }, + {&CSSMOID_RSAWithOAEP, CSSM_ALGMODE_PKCS1_EME_OAEP }, + {&CSSMOID_ECDSA_WithSHA224, CSSM_ALGID_SHA224WithECDSA }, + {&CSSMOID_ECDSA_WithSHA256, CSSM_ALGID_SHA256WithECDSA }, + {&CSSMOID_ECDSA_WithSHA384, CSSM_ALGID_SHA384WithECDSA }, + {&CSSMOID_ECDSA_WithSHA512, CSSM_ALGID_SHA512WithECDSA }, + /* AlgId.algorithm for ECDSA public key */ + {&CSSMOID_ecPublicKey, CSSM_ALGID_ECDSA }, + /* This OID is accompanied by an additional digest OID in AlgId.parameters */ + {&CSSMOID_ECDSA_WithSpecified, CSSM_ALGID_ECDSA_SPECIFIED }, + {NULL, 0} +}; + +#define NUM_OID_TO_ALGS (sizeof(oidToAlgMap) / sizeof(oidToAlgMap[0])) + +/* + * Compare two CSSM_DATAs (or two CSSM_OIDs), return true if identical. + */ +static bool compareCssmData( + const CSSM_DATA *data1, + const CSSM_DATA *data2) +{ + if((data1 == NULL) || (data1->Data == NULL) || + (data2 == NULL) || (data2->Data == NULL) || + (data1->Length != data2->Length)) { + return false; + } + if(data1->Length != data2->Length) { + return false; + } + if(memcmp(data1->Data, data2->Data, data1->Length) == 0) { + return true; + } + else { + return false; + } +} + +bool cssmOidToAlg( + const CSSM_OID *oid, + CSSM_ALGORITHMS *alg) // RETURNED +{ + const OidToAlgEnt *ent; + + for(ent=oidToAlgMap; ent->oid; ent++) { + if(compareCssmData(ent->oid, oid)) { + *alg = ent->alg; + return true; + } + } + return false; +} + +const CSSM_OID *cssmAlgToOid( + CSSM_ALGORITHMS algId) +{ + const OidToAlgEnt *ent; + + for(ent=oidToAlgMap; ent->oid; ent++) { + if(ent->alg == algId) { + return ent->oid; + } + } + return NULL; +} + + diff --git a/Security/libsecurity_cssm/lib/oidsbase.h b/Security/libsecurity_cssm/lib/oidsbase.h new file mode 100644 index 00000000..5e2f9f5d --- /dev/null +++ b/Security/libsecurity_cssm/lib/oidsbase.h @@ -0,0 +1,517 @@ +/* + * Copyright (c) 1999-2001,2003-2004,2008-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * oidsbase.h -- Basic Object Identifier Macros and Data Types. + */ + +#ifndef _OIDSBASE_H_ +#define _OIDSBASE_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Intel CSSM */ + +#define INTEL 96, 134, 72, 1, 134, 248, 77 +#define INTEL_LENGTH 7 + +#define INTEL_CDSASECURITY INTEL, 2 +#define INTEL_CDSASECURITY_LENGTH (INTEL_LENGTH + 1) + +#define INTEL_SEC_FORMATS INTEL_CDSASECURITY, 1 +#define INTEL_SEC_FORMATS_LENGTH (INTEL_CDSASECURITY_LENGTH + 1) + +#define INTEL_SEC_ALGS INTEL_CDSASECURITY, 2, 5 +#define INTEL_SEC_ALGS_LENGTH (INTEL_CDSASECURITY_LENGTH + 2) + +#define INTEL_SEC_OBJECT_BUNDLE INTEL_SEC_FORMATS, 4 +#define INTEL_SEC_OBJECT_BUNDLE_LENGTH (INTEL_SEC_FORMATS_LENGTH + 1) + +#define INTEL_CERT_AND_PRIVATE_KEY_2_0 INTEL_SEC_OBJECT_BUNDLE, 1 +#define INTEL_CERT_AND_PRIVATE_KEY_2_0_LENGTH (INTEL_SEC_OBJECT_BUNDLE_LENGTH + 1) + +/* Suffix specifying format or representation of a field value */ +/* Note that if a format suffix is not specified, a flat data +representation is implied */ +#define INTEL_X509_C_DATATYPE 1 +#define INTEL_X509_LDAPSTRING_DATATYPE 2 + +#define OID_ISO_CCITT_DIR_SERVICE 85 +#define OID_DS OID_ISO_CCITT_DIR_SERVICE +#define OID_DS_LENGTH 1 +#define OID_ATTR_TYPE OID_DS, 4 +#define OID_ATTR_TYPE_LENGTH OID_DS_LENGTH + 1 +#define OID_EXTENSION OID_DS, 29 +#define OID_EXTENSION_LENGTH OID_DS_LENGTH + 1 +#define OID_ISO_STANDARD 40 +#define OID_ISO_MEMBER 42 +#define OID_US OID_ISO_MEMBER, 134, 72 + +#define OID_ISO_IDENTIFIED_ORG 43 +#define OID_OSINET OID_ISO_IDENTIFIED_ORG, 4 +#define OID_GOSIP OID_ISO_IDENTIFIED_ORG, 5 +#define OID_DOD OID_ISO_IDENTIFIED_ORG, 6 +#define OID_OIW OID_ISO_IDENTIFIED_ORG, 14 + +#define OID_ITU_RFCDATA_MEMBER_LENGTH 1 +#define OID_ITU_RFCDATA 9 + +/* From the PKCS Standards */ +#define OID_ISO_MEMBER_LENGTH 1 +#define OID_US_LENGTH OID_ISO_MEMBER_LENGTH + 2 +#define OID_RSA OID_US, 134, 247, 13 +#define OID_RSA_LENGTH OID_US_LENGTH + 3 +#define OID_RSA_HASH OID_RSA, 2 +#define OID_RSA_HASH_LENGTH OID_RSA_LENGTH + 1 +#define OID_RSA_ENCRYPT OID_RSA, 3 +#define OID_RSA_ENCRYPT_LENGTH OID_RSA_LENGTH + 1 +#define OID_PKCS OID_RSA, 1 +#define OID_PKCS_LENGTH OID_RSA_LENGTH +1 +#define OID_PKCS_1 OID_PKCS, 1 +#define OID_PKCS_1_LENGTH OID_PKCS_LENGTH +1 +#define OID_PKCS_2 OID_PKCS, 2 +#define OID_PKCS_3 OID_PKCS, 3 +#define OID_PKCS_3_LENGTH OID_PKCS_LENGTH +1 +#define OID_PKCS_4 OID_PKCS, 4 +#define OID_PKCS_5 OID_PKCS, 5 +#define OID_PKCS_5_LENGTH OID_PKCS_LENGTH +1 +#define OID_PKCS_6 OID_PKCS, 6 +#define OID_PKCS_7 OID_PKCS, 7 +#define OID_PKCS_7_LENGTH OID_PKCS_LENGTH +1 +#define OID_PKCS_8 OID_PKCS, 8 +#define OID_PKCS_9 OID_PKCS, 9 +#define OID_PKCS_9_LENGTH OID_PKCS_LENGTH +1 +#define OID_PKCS_10 OID_PKCS, 10 +#define OID_PKCS_11 OID_PKCS, 11 +#define OID_PKCS_11_LENGTH OID_PKCS_LENGTH +1 +#define OID_PKCS_12 OID_PKCS, 12 +#define OID_PKCS_12_LENGTH OID_PKCS_LENGTH +1 + +/* ANSI X9.42 */ +#define OID_ANSI_X9_42 OID_US, 206, 62, 2 +#define OID_ANSI_X9_42_LEN OID_US_LENGTH + 3 +#define OID_ANSI_X9_42_SCHEME OID_ANSI_X9_42, 3 +#define OID_ANSI_X9_42_SCHEME_LEN OID_ANSI_X9_42_LEN + 1 +#define OID_ANSI_X9_42_NAMED_SCHEME OID_ANSI_X9_42, 4 +#define OID_ANSI_X9_42_NAMED_SCHEME_LEN OID_ANSI_X9_42_LEN + 1 + +/* ANSI X9.62 (1 2 840 10045) */ +#define OID_ANSI_X9_62 0x2A, 0x86, 0x48, 0xCE, 0x3D +#define OID_ANSI_X9_62_LEN 5 +#define OID_ANSI_X9_62_FIELD_TYPE OID_ANSI_X9_62, 1 +#define OID_ANSI_X9_62_PUBKEY_TYPE OID_ANSI_X9_62, 2 +#define OID_ANSI_X9_62_ELL_CURVE OID_ANSI_X9_62, 3 +#define OID_ANSI_X9_62_ELL_CURVE_LEN OID_ANSI_X9_62_LEN+1 +#define OID_ANSI_X9_62_C_TWO_CURVE OID_ANSI_X9_62_ELL_CURVE, 0 +#define OID_ANSI_X9_62_PRIME_CURVE OID_ANSI_X9_62_ELL_CURVE, 1 +#define OID_ANSI_X9_62_SIG_TYPE OID_ANSI_X9_62, 4 +#define OID_ANSI_X9_62_SIG_TYPE_LEN OID_ANSI_X9_62_LEN+1 + +/* PKIX */ +#define OID_PKIX OID_DOD, 1, 5, 5, 7 +#define OID_PKIX_LENGTH 6 +#define OID_PE OID_PKIX, 1 +#define OID_PE_LENGTH OID_PKIX_LENGTH + 1 +#define OID_QT OID_PKIX, 2 +#define OID_QT_LENGTH OID_PKIX_LENGTH + 1 +#define OID_KP OID_PKIX, 3 +#define OID_KP_LENGTH OID_PKIX_LENGTH + 1 +#define OID_OTHER_NAME OID_PKIX, 8 +#define OID_OTHER_NAME_LENGTH OID_PKIX_LENGTH + 1 +#define OID_PDA OID_PKIX, 9 +#define OID_PDA_LENGTH OID_PKIX_LENGTH + 1 +#define OID_QCS OID_PKIX, 11 +#define OID_QCS_LENGTH OID_PKIX_LENGTH + 1 +#define OID_AD OID_PKIX, 48 +#define OID_AD_LENGTH OID_PKIX_LENGTH + 1 +#define OID_AD_OCSP OID_AD, 1 +#define OID_AD_OCSP_LENGTH OID_AD_LENGTH + 1 + +/* ETSI */ +#define OID_ETSI 0x04, 0x00 +#define OID_ETSI_LENGTH 2 +#define OID_ETSI_QCS 0x04, 0x00, 0x8E, 0x46, 0x01 +#define OID_ETSI_QCS_LENGTH 5 + +#define OID_OIW_SECSIG OID_OIW, 3 +#define OID_OIW_LENGTH 2 +#define OID_OIW_SECSIG_LENGTH OID_OIW_LENGTH +1 + +#define OID_OIW_ALGORITHM OID_OIW_SECSIG, 2 +#define OID_OIW_ALGORITHM_LENGTH OID_OIW_SECSIG_LENGTH +1 + +/* NIST defined digest algorithm arc (2, 16, 840, 1, 101, 3, 4, 2) */ +#define OID_NIST_HASHALG 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02 +#define OID_NIST_HASHALG_LENGTH 8 + +/* Kerberos PKINIT */ +#define OID_KERBv5 0x2b, 6, 1, 5, 2 +#define OID_KERBv5_LEN 5 +#define OID_KERBv5_PKINIT OID_KERBv5, 3 +#define OID_KERBv5_PKINIT_LEN OID_KERBv5_LEN + 1 + +/* Certicom (1 3 132) */ +#define OID_CERTICOM 0x2B, 0x81, 0x04 +#define OID_CERTICOM_LEN 3 +#define OID_CERTICOM_ELL_CURVE OID_CERTICOM, 0 +#define OID_CERTICOM_ELL_CURVE_LEN OID_CERTICOM_LEN+1 + +/* + * Apple-specific OID bases + */ + +/* + * apple OBJECT IDENTIFIER ::= + * { iso(1) member-body(2) US(840) 113635 } + * + * BER = 06 06 2A 86 48 86 F7 63 + */ +#define APPLE_OID OID_US, 0x86, 0xf7, 0x63 +#define APPLE_OID_LENGTH OID_US_LENGTH + 3 + +/* appleDataSecurity OBJECT IDENTIFIER ::= + * { apple 100 } + * { 1 2 840 113635 100 } + * + * BER = 06 07 2A 86 48 86 F7 63 64 + */ +#define APPLE_ADS_OID APPLE_OID, 0x64 +#define APPLE_ADS_OID_LENGTH APPLE_OID_LENGTH + 1 + +/* + * appleTrustPolicy OBJECT IDENTIFIER ::= + * { appleDataSecurity 1 } + * { 1 2 840 113635 100 1 } + * + * BER = 06 08 2A 86 48 86 F7 63 64 01 + */ +#define APPLE_TP_OID APPLE_ADS_OID, 1 +#define APPLE_TP_OID_LENGTH APPLE_ADS_OID_LENGTH + 1 + +/* + * appleSecurityAlgorithm OBJECT IDENTIFIER ::= + * { appleDataSecurity 2 } + * { 1 2 840 113635 100 2 } + * + * BER = 06 08 2A 86 48 86 F7 63 64 02 + */ +#define APPLE_ALG_OID APPLE_ADS_OID, 2 +#define APPLE_ALG_OID_LENGTH APPLE_ADS_OID_LENGTH + 1 + +/* + * appleDotMacCertificate OBJECT IDENTIFIER ::= + * { appleDataSecurity 3 } + * { 1 2 840 113635 100 3 } + */ +#define APPLE_DOTMAC_CERT_OID APPLE_ADS_OID, 3 +#define APPLE_DOTMAC_CERT_OID_LENGTH APPLE_ADS_OID_LENGTH + 1 + +/* + * Basis of Policy OIDs for .mac TP requests + * + * dotMacCertificateRequest OBJECT IDENTIFIER ::= + * { appleDotMacCertificate 1 } + * { 1 2 840 113635 100 3 1 } + */ +#define APPLE_DOTMAC_CERT_REQ_OID APPLE_DOTMAC_CERT_OID, 1 +#define APPLE_DOTMAC_CERT_REQ_OID_LENGTH APPLE_DOTMAC_CERT_OID_LENGTH + 1 + +/* + * Basis of .mac Certificate Extensions + * + * dotMacCertificateExtension OBJECT IDENTIFIER ::= + * { appleDotMacCertificate 2 } + * { 1 2 840 113635 100 3 2 } + */ +#define APPLE_DOTMAC_CERT_EXTEN_OID APPLE_DOTMAC_CERT_OID, 2 +#define APPLE_DOTMAC_CERT_EXTEN_OID_LENGTH APPLE_DOTMAC_CERT_OID_LENGTH + 1 + +/* + * Basis of .mac Certificate request OID/value identifiers + * + * dotMacCertificateRequestValues OBJECT IDENTIFIER ::= + * { appleDotMacCertificate 3 } + * { 1 2 840 113635 100 3 3 } + */ +#define APPLE_DOTMAC_CERT_REQ_VALUE_OID APPLE_DOTMAC_CERT_OID, 3 +#define APPLE_DOTMAC_CERT_REQ_VALUE_OID_LENGTH APPLE_DOTMAC_CERT_OID_LENGTH + 1 + +/* + * Basis of Apple-specific extended key usages + * + * appleExtendedKeyUsage OBJECT IDENTIFIER ::= + * { appleDataSecurity 4 } + * { 1 2 840 113635 100 4 } + */ +#define APPLE_EKU_OID APPLE_ADS_OID, 4 +#define APPLE_EKU_OID_LENGTH APPLE_ADS_OID_LENGTH + 1 + +/* + * Basis of Apple Code Signing extended key usages + * appleCodeSigning OBJECT IDENTIFIER ::= + * { appleExtendedKeyUsage 1 } + * { 1 2 840 113635 100 4 1 } + */ +#define APPLE_EKU_CODE_SIGNING APPLE_EKU_OID, 1 +#define APPLE_EKU_CODE_SIGNING_LENGTH APPLE_EKU_OID_LENGTH + 1 + +/* -------------------------------------------------------------------------*/ + +/* + * Basis of Apple-specific Certificate Policy identifiers + * appleCertificatePolicies OBJECT IDENTIFIER ::= + * { appleDataSecurity 5 } + * { 1 2 840 113635 100 5 } + */ +#define APPLE_CERT_POLICIES APPLE_ADS_OID, 5 +#define APPLE_CERT_POLICIES_LENGTH APPLE_ADS_OID_LENGTH + 1 + +/* + * Base for MacAppStore Certificate Policy identifiers + * macAppStoreCertificatePolicyIDs OBJECT IDENTIFIER ::= + * { appleCertificatePolicies 6 } + * { 1 2 840 113635 100 5 6 } + */ +#define APPLE_CERT_POLICIES_MACAPPSTORE APPLE_CERT_POLICIES, 6 +#define APPLE_CERT_POLICIES_MACAPPSTORE_LENGTH APPLE_CERT_POLICIES_LENGTH + 1 + +/* + * MacAppStore receipt verification Certificate Policy identifier + * macAppStoreReceiptCertificatePolicyID OBJECT IDENTIFIER ::= + * { appleCertificatePolicies 6 1 } + * { 1 2 840 113635 100 5 6 1 } + */ +#define APPLE_CERT_POLICIES_MACAPPSTORE_RECEIPT APPLE_CERT_POLICIES_MACAPPSTORE, 1 +#define APPLE_CERT_POLICIES_MACAPPSTORE_RECEIPT_LENGTH APPLE_CERT_POLICIES_MACAPPSTORE_LENGTH + 1 + +/* + * Base for AppleID Certificate Policy identifiers + * macAppStoreCertificatePolicyIDs OBJECT IDENTIFIER ::= + * { appleCertificatePolicies 7 } + * { 1 2 840 113635 100 5 7 } + */ +#define APPLE_CERT_POLICIES_APPLEID APPLE_CERT_POLICIES, 7 +#define APPLE_CERT_POLICIES_APPLEID_LENGTH APPLE_CERT_POLICIES_LENGTH + 1 + +/* + * AppleID Sharing Certificate Policy identifier + * appleIDSharingPolicyID OBJECT IDENTIFIER ::= + * { appleCertificatePolicies 7 1 } + * { 1 2 840 113635 100 5 7 1 } + */ +#define APPLE_CERT_POLICIES_APPLEID_SHARING APPLE_CERT_POLICIES_APPLEID, 1 +#define APPLE_CERT_POLICIES_APPLEID_SHARING_LENGTH APPLE_CERT_POLICIES_APPLEID_LENGTH + 1 + +/* + * Apple Mobile Store Signing Policy identifier + * + * appleDemoContentReleaseSigningID ::= { appleCertificatePolicies 12} + * { 1 2 840 113635 100 5 12 } + */ +#define APPLE_CERT_POLICIES_MOBILE_STORE_SIGNING APPLE_CERT_POLICIES, 12 +#define APPLE_CERT_POLICIES_MOBILE_STORE_SIGNING_LENGTH APPLE_CERT_POLICIES_LENGTH + 1 + +/* + * Apple Test Mobile Store Signing Policy identifier + * + * appleDemoContentTestSigningID ::= { appleDemoContentReleaseSigningID 1} + * { 1 2 840 113635 100 5 12 1 } + */ +#define APPLE_CERT_POLICIES_TEST_MOBILE_STORE_SIGNING APPLE_CERT_POLICIES, 12, 1 +#define APPLE_CERT_POLICIES_TEST_MOBILE_STORE_SIGNING_LENGTH APPLE_CERT_POLICIES_LENGTH + 2 + + +/* -------------------------------------------------------------------------*/ + +/* + * Basis of Apple-specific certificate extensions + * appleCertificateExtensions OBJECT IDENTIFIER ::= + * { appleDataSecurity 6 } + * { 1 2 840 113635 100 6 } + */ +#define APPLE_EXTENSION_OID APPLE_ADS_OID, 6 +#define APPLE_EXTENSION_OID_LENGTH APPLE_ADS_OID_LENGTH + 1 + +/* + * Basis of Apple-specific Code Signing certificate extensions + * appleCertificateExtensionCodeSigning OBJECT IDENTIFIER ::= + * { appleCertificateExtensions 1 } + * { 1 2 840 113635 100 6 1 } + */ +#define APPLE_EXTENSION_CODE_SIGNING APPLE_EXTENSION_OID, 1 +#define APPLE_EXTENSION_CODE_SIGNING_LENGTH APPLE_EXTENSION_OID_LENGTH + 1 + +/* + * Basis of MacAppStore receipt verification certificate extensions + * macAppStoreReceiptExtension OBJECT IDENTIFIER ::= + * { appleCertificateExtensions 11 1 } + * { 1 2 840 113635 100 6 11 1 } + */ +#define APPLE_EXTENSION_MACAPPSTORE_RECEIPT APPLE_EXTENSION_OID, 11, 1 +#define APPLE_EXTENSION_MACAPPSTORE_RECEIPT_LENGTH APPLE_EXTENSION_OID_LENGTH + 2 + +/* + * Basis of Apple-specific Intermediate Certificate extensions + * appleCertificateExtensionIntermediateMarker OBJECT IDENTIFIER ::= + * { appleCertificateExtensions 2 } + * { 1 2 840 113635 100 6 2 } + */ +#define APPLE_EXTENSION_INTERMEDIATE_MARKER APPLE_EXTENSION_OID, 2 +#define APPLE_EXTENSION_INTERMEDIATE_MARKER_LENGTH APPLE_EXTENSION_OID_LENGTH + 1 + +/* + * Marker for the WWDR Intermediate Certificate + * appleCertificateExtensionWWDRIntermediate OBJECT IDENTIFIER ::= + * { appleCertificateExtensionIntermediateMarker 1 } + * { 1 2 840 113635 100 6 2 1 } + */ +#define APPLE_EXTENSION_WWDR_INTERMEDIATE APPLE_EXTENSION_INTERMEDIATE_MARKER, 1 +#define APPLE_EXTENSION_WWDR_INTERMEDIATE_LENGTH APPLE_EXTENSION_INTERMEDIATE_MARKER_LENGTH + 1 + +/* + * Marker for the iTunes Store Intermediate Certificate + * appleCertificateExtensioniTunesStoreIntermediate OBJECT IDENTIFIER ::= + * { appleCertificateExtensionIntermediateMarker 2 } + * { 1 2 840 113635 100 6 2 2 } + */ +#define APPLE_EXTENSION_ITMS_INTERMEDIATE APPLE_EXTENSION_INTERMEDIATE_MARKER, 2 +#define APPLE_EXTENSION_ITMS_INTERMEDIATE_LENGTH APPLE_EXTENSION_INTERMEDIATE_MARKER_LENGTH + 1 + +/* + * Marker for the Application Integration Intermediate Certificate + * appleCertificateExtensionApplicationIntegrationIntermediate OBJECT IDENTIFIER ::= + * { appleCertificateExtensionIntermediateMarker 3 } + * { 1 2 840 113635 100 6 2 3 } + */ +#define APPLE_EXTENSION_AAI_INTERMEDIATE APPLE_EXTENSION_INTERMEDIATE_MARKER, 3 +#define APPLE_EXTENSION_AAI_INTERMEDIATE_LENGTH APPLE_EXTENSION_INTERMEDIATE_MARKER_LENGTH + 1 + +/* + * Apple Apple ID Intermediate Marker (New subCA, no longer shared with push notification server cert issuer + * + * appleCertificateExtensionAppleIDIntermediate ::= + * { appleCertificateExtensionIntermediateMarker 7 } + * { 1 2 840 113635 100 6 2 7 } + * + * shared intermediate OID is APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID + * Apple Apple ID Intermediate Marker + * Same as APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID_2 on iOS +*/ +#define APPLE_EXTENSION_APPLEID_INTERMEDIATE APPLE_EXTENSION_INTERMEDIATE_MARKER, 7 +#define APPLE_EXTENSION_APPLEID_INTERMEDIATE_LENGTH APPLE_EXTENSION_INTERMEDIATE_MARKER_LENGTH + 1 + +/* + * Apple System Integration 2 Intermediate Marker (New subCA) + * + * appleCertificateExtensionSystemIntegration2Intermediate ::= + * { appleCertificateExtensionIntermediateMarker 10 } + * { 1 2 840 113635 100 6 2 10 } +*/ +#define APPLE_EXTENSION_SYSINT2_INTERMEDIATE APPLE_EXTENSION_INTERMEDIATE_MARKER, 10 +#define APPLE_EXTENSION_SYSINT2_INTERMEDIATE_LENGTH APPLE_EXTENSION_INTERMEDIATE_MARKER_LENGTH + 1 + +/* + * Apple Developer Authentication Intermediate Marker (New subCA) + * + * appleCertificateExtensionDeveloperAuthentication ::= + * { appleCertificateExtensionIntermediateMarker 11 } + * { 1 2 840 113635 100 6 2 11 } +*/ +#define APPLE_EXTENSION_DEVELOPER_AUTHENTICATION APPLE_EXTENSION_INTERMEDIATE_MARKER, 11 +#define APPLE_EXTENSION_DEVELOPER_AUTHENTICATION_LENGTH APPLE_EXTENSION_INTERMEDIATE_MARKER_LENGTH + 1 + +/* + * Apple Server Authentication Intermediate Marker (New subCA) + * + * appleCertificateExtensionServerAuthentication ::= + * { appleCertificateExtensionIntermediateMarker 12 } + * { 1 2 840 113635 100 6 2 12 } +*/ +#define APPLE_EXTENSION_SERVER_AUTHENTICATION APPLE_EXTENSION_INTERMEDIATE_MARKER, 12 +#define APPLE_EXTENSION_SERVER_AUTHENTICATION_LENGTH APPLE_EXTENSION_INTERMEDIATE_MARKER_LENGTH + 1 + +/* + * Apple Secure Escrow Service Marker + * + * appleEscrowService ::= { appleCertificateExtensions 23 1 } + * { 1 2 840 113635 100 6 23 1 } + */ +#define APPLE_EXTENSION_ESCROW_SERVICE APPLE_EXTENSION_OID, 23, 1 +#define APPLE_EXTENSION_ESCROW_SERVICE_LENGTH APPLE_EXTENSION_OID_LENGTH + 2 + +/* + * Marker for the AppleID Sharing Certificate + * appleID OBJECT IDENTIFIER ::= + * { appleExtendedKeyUsage 7} + * { 1 2 840 113635 100 4 7 } + */ + +#define APPLE_EXTENSION_APPLEID_SHARING APPLE_EKU_OID, 7 +#define APPLE_EXTENSION_APPLEID_SHARING_LENGTH APPLE_EKU_OID_LENGTH + 1 + +/* + * Netscape OIDs. + */ +#define NETSCAPE_BASE_OID 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42 +#define NETSCAPE_BASE_OID_LEN 7 + +/* + * Netscape cert extension. + * + * netscape-cert-extension OBJECT IDENTIFIER ::= + * { 2 16 840 1 113730 1 } + * + * BER = 06 08 60 86 48 01 86 F8 42 01 + */ +#define NETSCAPE_CERT_EXTEN NETSCAPE_BASE_OID, 0x01 +#define NETSCAPE_CERT_EXTEN_LENGTH NETSCAPE_BASE_OID_LEN + 1 + +#define NETSCAPE_CERT_POLICY NETSCAPE_BASE_OID, 0x04 +#define NETSCAPE_CERT_POLICY_LENGTH NETSCAPE_BASE_OID_LEN + 1 + +/* + * Domain Component OID + */ +#define OID_ITU_RFCDATA_2342 OID_ITU_RFCDATA, 0x49, 0x86 +#define OID_ITU_RFCDATA_2342_LENGTH OID_ITU_RFCDATA_MEMBER_LENGTH + 2 + +#define OID_ITU_RFCDATA_2342_UCL OID_ITU_RFCDATA_2342, 0x49, 0x1F, 0x12, 0x8C +#define OID_ITU_RFCDATA_2342_UCL_LENGTH OID_ITU_RFCDATA_2342_LENGTH + 4 + +#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT OID_ITU_RFCDATA_2342_UCL, 0xE4 +#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_LENGTH OID_ITU_RFCDATA_2342_UCL_LENGTH + 1 + +#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT, 0x81 +#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_LENGTH OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_LENGTH + 1 + +#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_DOMAINCOMPONENT OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES, 0x99 +#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_DOMAINCOMPONENT_LENGTH OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_LENGTH + 1 + +#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_USERID OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES, 0x81 +#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_USERID_LENGTH OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_LENGTH + 1 + +#ifdef __cplusplus +} +#endif + +#endif /* _OIDSBASE_H_ */ diff --git a/libsecurity_cssm/lib/oidscert.cpp b/Security/libsecurity_cssm/lib/oidscert.cpp similarity index 97% rename from libsecurity_cssm/lib/oidscert.cpp rename to Security/libsecurity_cssm/lib/oidscert.cpp index 70838512..de7c9259 100644 --- a/libsecurity_cssm/lib/oidscert.cpp +++ b/Security/libsecurity_cssm/lib/oidscert.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2000-2004,2008-2013 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2008-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -28,13 +28,14 @@ Contains: Object Identifiers for X509 Certificate Library - Copyright (c) 1999,2001-2004 Apple Computer, Inc. All Rights Reserved. - */ #include "oidsbase.h" #include "oidscert.h" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-const-variable" + /* required until PR-3347430 Security/cdsa/cdsa/oidscert.h is checked * into TOT - pending public API review */ extern "C" { @@ -252,6 +253,8 @@ static const uint8 OID_APPLE_EXTENSION_APPLEID_INTERMEDIATE[] = { APPLE_EXTENSION_APPLEID_INTERMEDIATE }, OID_APPLE_EXTENSION_APPLEID_SHARING[] = { APPLE_EXTENSION_APPLEID_SHARING }, OID_APPLE_EXTENSION_SYSINT2_INTERMEDIATE[] = { APPLE_EXTENSION_SYSINT2_INTERMEDIATE }, + OID_APPLE_EXTENSION_DEVELOPER_AUTHENTICATION[] = { APPLE_EXTENSION_DEVELOPER_AUTHENTICATION }, + OID_APPLE_EXTENSION_SERVER_AUTHENTICATION[] = { APPLE_EXTENSION_SERVER_AUTHENTICATION }, OID_APPLE_EXTENSION_ESCROW_SERVICE[] = { APPLE_EXTENSION_ESCROW_SERVICE } ; @@ -370,6 +373,10 @@ CSSMOID_APPLE_EXTENSION_APPLEID_SHARING = { APPLE_EXTENSION_APPLEID_SHAR (uint8 *)OID_APPLE_EXTENSION_APPLEID_SHARING }, CSSMOID_APPLE_EXTENSION_SYSINT2_INTERMEDIATE = { APPLE_EXTENSION_SYSINT2_INTERMEDIATE_LENGTH, (uint8 *)OID_APPLE_EXTENSION_SYSINT2_INTERMEDIATE }, +CSSMOID_APPLE_EXTENSION_DEVELOPER_AUTHENTICATION= { APPLE_EXTENSION_DEVELOPER_AUTHENTICATION_LENGTH, + (uint8 *)OID_APPLE_EXTENSION_DEVELOPER_AUTHENTICATION }, +CSSMOID_APPLE_EXTENSION_SERVER_AUTHENTICATION = { APPLE_EXTENSION_SERVER_AUTHENTICATION_LENGTH, + (uint8 *)OID_APPLE_EXTENSION_SERVER_AUTHENTICATION }, CSSMOID_APPLE_EXTENSION_ESCROW_SERVICE = { APPLE_EXTENSION_ESCROW_SERVICE_LENGTH + 1, (uint8 *)OID_APPLE_EXTENSION_ESCROW_SERVICE } ; @@ -427,3 +434,5 @@ const CSSM_OID CSSMOID_MicrosoftSGC = /* * .mac Certificate Extended Key Use values. */ + +#pragma clang diagnostic pop diff --git a/libsecurity_cssm/lib/oidscert.h b/Security/libsecurity_cssm/lib/oidscert.h similarity index 97% rename from libsecurity_cssm/lib/oidscert.h rename to Security/libsecurity_cssm/lib/oidscert.h index ff50039f..b0414f83 100644 --- a/libsecurity_cssm/lib/oidscert.h +++ b/Security/libsecurity_cssm/lib/oidscert.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2004,2008-2013 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2004,2008-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ * * oidscert.h -- Object Identifiers for X509 Certificate Library @@ -182,6 +182,8 @@ extern const CSSM_OID CSSMOID_APPLE_EXTENSION_APPLEID_INTERMEDIATE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, CSSMOID_APPLE_EXTENSION_APPLEID_SHARING DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, CSSMOID_APPLE_EXTENSION_SYSINT2_INTERMEDIATE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_EXTENSION_DEVELOPER_AUTHENTICATION DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, + CSSMOID_APPLE_EXTENSION_SERVER_AUTHENTICATION DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, CSSMOID_APPLE_EXTENSION_ESCROW_SERVICE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER ; diff --git a/libsecurity_cssm/lib/oidscrl.cpp b/Security/libsecurity_cssm/lib/oidscrl.cpp similarity index 98% rename from libsecurity_cssm/lib/oidscrl.cpp rename to Security/libsecurity_cssm/lib/oidscrl.cpp index 6e6532a8..788c2068 100644 --- a/libsecurity_cssm/lib/oidscrl.cpp +++ b/Security/libsecurity_cssm/lib/oidscrl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -28,7 +28,7 @@ Contains: Object Identifiers for X509 CRLs and OCSP - Copyright (c) 1999,2001-2002,2004 Apple Computer, Inc. All Rights Reserved. + Copyright (c) 1999,2001-2002,2004,2011,2014 Apple Inc. All Rights Reserved. */ diff --git a/libsecurity_cssm/lib/oidscrl.h b/Security/libsecurity_cssm/lib/oidscrl.h similarity index 98% rename from libsecurity_cssm/lib/oidscrl.h rename to Security/libsecurity_cssm/lib/oidscrl.h index 65cbda54..f02f8f04 100644 --- a/libsecurity_cssm/lib/oidscrl.h +++ b/Security/libsecurity_cssm/lib/oidscrl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/lib/security_cssm.exp b/Security/libsecurity_cssm/lib/security_cssm.exp similarity index 99% rename from libsecurity_cssm/lib/security_cssm.exp rename to Security/libsecurity_cssm/lib/security_cssm.exp index 95b1e137..85aece61 100644 --- a/libsecurity_cssm/lib/security_cssm.exp +++ b/Security/libsecurity_cssm/lib/security_cssm.exp @@ -1,5 +1,5 @@ # -# Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. +# Copyright (c) 2003-2004,2011-2012,2014 Apple Inc. All Rights Reserved. # # @APPLE_LICENSE_HEADER_START@ # diff --git a/Security/libsecurity_cssm/lib/transition.cpp b/Security/libsecurity_cssm/lib/transition.cpp new file mode 100644 index 00000000..99c81b06 --- /dev/null +++ b/Security/libsecurity_cssm/lib/transition.cpp @@ -0,0 +1,519 @@ +/* + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +// +// transition - transition layer for CSSM API/SPI calls. +// +// This file defines all functions that connect the CSSM API (CSSM_*) +// to a plugin's SPI (CSSM_SPI_*) functions. The bulk of these functions +// is automatically generated by the Perl script transition.pl (thanks, Larry!) +// from the cssm*.h official header files, under control of the configuration +// file transition.cfg. Those that need special magic are marked "custom" in +// transition.cfg and are defined here. +// +// @@@ Reconsider CSP locking for context operations +// +#include "cssmint.h" +#include "attachfactory.h" +#include "manager.h" +#include "cssmcontext.h" +#include +#include +#include +#include +#include +#include +#include +#include + + +// +// Names for the standard Attachment types +// +typedef StandardAttachment CSPAttachment; +typedef StandardAttachment DLAttachment; +typedef StandardAttachment CLAttachment; +typedef StandardAttachment ACAttachment; +typedef StandardAttachment TPAttachment; + + +// +// A conditional locking class for always-right(TM) lock management. +// +class TransitLock { +public: + Attachment &attachment; + + TransitLock(Attachment &att) : attachment(att) + { + attachment.module.safeLock(); + } + + ~TransitLock() + { + attachment.module.safeUnlock(); + attachment.exit(); + } +}; + + +// +// Context management functions +// +CSSM_RETURN CSSMAPI +CSSM_CSP_CreateSignatureContext (CSSM_CSP_HANDLE CSPHandle, + CSSM_ALGORITHMS AlgorithmID, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_KEY *Key, + CSSM_CC_HANDLE *NewContextHandle) +{ + BEGIN_API + HandleContext::Maker maker(CSPHandle); + maker.setup(AccessCred); + maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY); + maker.make(); + maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred); + maker.put(CSSM_ATTRIBUTE_KEY, Key); + Required(NewContextHandle) = maker(CSSM_ALGCLASS_SIGNATURE, AlgorithmID); + END_API(CSSM) +} + + +CSSM_RETURN CSSMAPI +CSSM_CSP_CreateSymmetricContext (CSSM_CSP_HANDLE CSPHandle, + CSSM_ALGORITHMS AlgorithmID, + CSSM_ENCRYPT_MODE Mode, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_KEY *Key, + const CSSM_DATA *InitVector, + CSSM_PADDING Padding, + void *Reserved, + CSSM_CC_HANDLE *NewContextHandle) +{ + BEGIN_API + if (Reserved != NULL) + CssmError::throwMe(CSSM_ERRCODE_INVALID_POINTER); + HandleContext::Maker maker(CSPHandle); + maker.setup(Mode); + maker.setup(AccessCred); + maker.setup(Key); + maker.setup(InitVector); + maker.setup(Padding); + maker.make(); + maker.put(CSSM_ATTRIBUTE_MODE, Mode); + maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred); + maker.put(CSSM_ATTRIBUTE_KEY, Key); + maker.put(CSSM_ATTRIBUTE_INIT_VECTOR, InitVector); + maker.put(CSSM_ATTRIBUTE_PADDING, Padding); + Required(NewContextHandle) = maker(CSSM_ALGCLASS_SYMMETRIC, AlgorithmID); + END_API(CSSM) +} + + +CSSM_RETURN CSSMAPI +CSSM_CSP_CreateDigestContext (CSSM_CSP_HANDLE CSPHandle, + CSSM_ALGORITHMS AlgorithmID, + CSSM_CC_HANDLE *NewContextHandle) +{ + BEGIN_API + HandleContext::Maker maker(CSPHandle); + maker.make(); + Required(NewContextHandle) = maker(CSSM_ALGCLASS_DIGEST, AlgorithmID); + END_API(CSSM) +} + + +CSSM_RETURN CSSMAPI +CSSM_CSP_CreateMacContext (CSSM_CSP_HANDLE CSPHandle, + CSSM_ALGORITHMS AlgorithmID, + const CSSM_KEY *Key, + CSSM_CC_HANDLE *NewContextHandle) +{ + BEGIN_API + HandleContext::Maker maker(CSPHandle); + maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY); + maker.make(); + maker.put(CSSM_ATTRIBUTE_KEY, Key); + Required(NewContextHandle) = maker(CSSM_ALGCLASS_MAC, AlgorithmID); + END_API(CSSM) +} + + +CSSM_RETURN CSSMAPI +CSSM_CSP_CreateRandomGenContext (CSSM_CSP_HANDLE CSPHandle, + CSSM_ALGORITHMS AlgorithmID, + const CSSM_CRYPTO_DATA *Seed, + CSSM_SIZE Length, + CSSM_CC_HANDLE *NewContextHandle) +{ + BEGIN_API + HandleContext::Maker maker(CSPHandle); + maker.setup(Seed); + maker.setup(Length, CSSMERR_CSP_INVALID_ATTR_OUTPUT_SIZE); + maker.make(); + maker.put(CSSM_ATTRIBUTE_SEED, Seed); + maker.put(CSSM_ATTRIBUTE_OUTPUT_SIZE, (uint32_t)Length); + Required(NewContextHandle) = maker(CSSM_ALGCLASS_RANDOMGEN, AlgorithmID); + END_API(CSSM) +} + + +CSSM_RETURN CSSMAPI +CSSM_CSP_CreateAsymmetricContext (CSSM_CSP_HANDLE CSPHandle, + CSSM_ALGORITHMS AlgorithmID, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_KEY *Key, + CSSM_PADDING Padding, + CSSM_CC_HANDLE *NewContextHandle) +{ + BEGIN_API + HandleContext::Maker maker(CSPHandle); + maker.setup(AccessCred, CSSMERR_CSP_MISSING_ATTR_ACCESS_CREDENTIALS); + maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY); + maker.setup(Padding); + maker.make(); + maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred); + maker.put(CSSM_ATTRIBUTE_KEY, Key); + maker.put(CSSM_ATTRIBUTE_PADDING, Padding); + Required(NewContextHandle) = maker(CSSM_ALGCLASS_ASYMMETRIC, AlgorithmID); + END_API(CSSM) +} + + +CSSM_RETURN CSSMAPI +CSSM_CSP_CreateDeriveKeyContext (CSSM_CSP_HANDLE CSPHandle, + CSSM_ALGORITHMS AlgorithmID, + CSSM_KEY_TYPE DeriveKeyType, + uint32 DeriveKeyLengthInBits, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_KEY *BaseKey, + uint32 IterationCount, + const CSSM_DATA *Salt, + const CSSM_CRYPTO_DATA *Seed, + CSSM_CC_HANDLE *NewContextHandle) +{ + BEGIN_API + HandleContext::Maker maker(CSPHandle); + maker.setup(DeriveKeyType, CSSMERR_CSP_INVALID_ATTR_KEY_TYPE); + maker.setup(DeriveKeyLengthInBits, CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); + maker.setup(AccessCred); + maker.setup(BaseKey); + maker.setup(IterationCount); + maker.setup(Salt); + maker.setup(Seed); + maker.make(); + maker.put(CSSM_ATTRIBUTE_KEY_TYPE, DeriveKeyType); + maker.put(CSSM_ATTRIBUTE_KEY_LENGTH, DeriveKeyLengthInBits); + maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred); + maker.put(CSSM_ATTRIBUTE_KEY, BaseKey); + maker.put(CSSM_ATTRIBUTE_ITERATION_COUNT, IterationCount); + maker.put(CSSM_ATTRIBUTE_SALT, Salt); + maker.put(CSSM_ATTRIBUTE_SEED, Seed); + Required(NewContextHandle) = maker(CSSM_ALGCLASS_DERIVEKEY, AlgorithmID); + END_API(CSSM) +} + + +CSSM_RETURN CSSMAPI +CSSM_CSP_CreateKeyGenContext (CSSM_CSP_HANDLE CSPHandle, + CSSM_ALGORITHMS AlgorithmID, + uint32 KeySizeInBits, + const CSSM_CRYPTO_DATA *Seed, + const CSSM_DATA *Salt, + const CSSM_DATE *StartDate, + const CSSM_DATE *EndDate, + const CSSM_DATA *Params, + CSSM_CC_HANDLE *NewContextHandle) +{ + BEGIN_API + HandleContext::Maker maker(CSPHandle); + maker.setup(KeySizeInBits, CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); + maker.setup(Seed); + maker.setup(Salt); + maker.setup(StartDate); + maker.setup(EndDate); + maker.setup(Params); + maker.make(); + maker.put(CSSM_ATTRIBUTE_KEY_LENGTH, KeySizeInBits); + maker.put(CSSM_ATTRIBUTE_SEED, Seed); + maker.put(CSSM_ATTRIBUTE_SALT, Salt); + maker.put(CSSM_ATTRIBUTE_START_DATE, StartDate); + maker.put(CSSM_ATTRIBUTE_END_DATE, EndDate); + maker.put(CSSM_ATTRIBUTE_ALG_PARAMS, Params); + Required(NewContextHandle) = maker(CSSM_ALGCLASS_KEYGEN, AlgorithmID); + END_API(CSSM) +} + + +CSSM_RETURN CSSMAPI +CSSM_CSP_CreatePassThroughContext (CSSM_CSP_HANDLE CSPHandle, + const CSSM_KEY *Key, + CSSM_CC_HANDLE *NewContextHandle) +{ + BEGIN_API + HandleContext::Maker maker(CSPHandle); + maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY); + maker.make(); + maker.put(CSSM_ATTRIBUTE_KEY, Key); + Required(NewContextHandle) = maker(CSSM_ALGCLASS_NONE, CSSM_ALGID_NONE); + END_API(CSSM) +} + + +// +// CSSM_GetContext makes a deep copy of a CSP context and hands it to the +// caller. The result is NOT a HandleContext, but a bare Context that is +// in no dictionaries etc. User must delete it by calling CSSM_FreeContext. +// +CSSM_RETURN CSSMAPI +CSSM_GetContext (CSSM_CC_HANDLE CCHandle, + CSSM_CONTEXT_PTR *ContextP) +{ + BEGIN_API +#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE + HandleContext &context = HandleObject::find((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); + Context *newContext = new(context.attachment) Context(context.type(), context.algorithm()); + try { + newContext->CSPHandle = context.attachment.handle(); + newContext->copyFrom(context, context.attachment); + Required(ContextP) = newContext; + } catch (...) { + context.attachment.free(newContext); + throw; + } + END_API(CSSM) +} + + +// +// Since we allocated all the data in one fell heap, our FreeContext +// function is disappointingly simple. +// +CSSM_RETURN CSSMAPI +CSSM_FreeContext (CSSM_CONTEXT_PTR ContextP) +{ + BEGIN_API + Context *context = &Context::required(ContextP); + context->destroy(context, HandleObject::find(context->CSPHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE)); + END_API(CSSM) +} + + +CSSM_RETURN CSSMAPI +CSSM_SetContext (CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *ContextP) +{ + BEGIN_API + const Context &source = Context::required(ContextP); +#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE + HandleContext &context = HandleObject::find((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); + + CSSM_CONTEXT_ATTRIBUTE *oldAttributes = context.ContextAttributes; + uint32 oldCount = context.NumberOfAttributes; + CSSM_CONTEXT_TYPE oldType = context.ContextType; + CSSM_ALGORITHMS oldAlgorithm = context.AlgorithmType; + + context.copyFrom(source, context.attachment); + context.ContextType = source.ContextType; + context.AlgorithmType = source.AlgorithmType; + + if (CSSM_RETURN err = context.validateChange(CSSM_CONTEXT_EVENT_UPDATE)) { + context.attachment.free(context.ContextAttributes); // free rejected attribute blob + context.ContextAttributes = oldAttributes; // restore... + context.NumberOfAttributes = oldCount; // ... old + context.ContextType = oldType; // ... values + context.AlgorithmType = oldAlgorithm; // ... in context + CssmError::throwMe(err); // tell the caller it failed + } + + context.attachment.free(oldAttributes); + END_API(CSSM) +} + + +CSSM_RETURN CSSMAPI +CSSM_DeleteContext (CSSM_CC_HANDLE CCHandle) +{ + BEGIN_API + HandleContext &context = enterContext(CCHandle); + StLock + _(context.attachment, true); + + // ignore error return from CSP event notify (can't decline deletion) + context.validateChange(CSSM_CONTEXT_EVENT_DELETE); + + context.destroy(&context, context.attachment); + END_API(CSSM) +} + + +// +// The GetContextAttribute API is fatally flawed. The standard implies a deep +// copy of the attribute value, but no release function exists. Instead, we +// return a shallow copy (sharing structure) which you need not release, but +// which becomes invalid when the source Context is destroyed. +// +CSSM_RETURN CSSMAPI +CSSM_GetContextAttribute (const CSSM_CONTEXT *Context, + uint32 AttributeType, + CSSM_CONTEXT_ATTRIBUTE_PTR *ContextAttribute) +{ + BEGIN_API + CSSM_ATTRIBUTE_TYPE type = CSSM_ATTRIBUTE_TYPE(AttributeType); // CDSA defect + Required(ContextAttribute) = Context::required(Context).find(type); + END_API(CSSM) +} + + +CSSM_RETURN CSSMAPI +CSSM_UpdateContextAttributes (CSSM_CC_HANDLE CCHandle, + uint32 NumberAttributes, + const CSSM_CONTEXT_ATTRIBUTE *ContextAttributes) +{ + BEGIN_API +#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE + HandleContext &context = HandleObject::find((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); + context.mergeAttributes(ContextAttributes, NumberAttributes); + END_API(CSSM) +} + + +CSSM_RETURN CSSMAPI +CSSM_DeleteContextAttributes (CSSM_CC_HANDLE CCHandle, + uint32 NumberOfAttributes, + const CSSM_CONTEXT_ATTRIBUTE *ContextAttributes) +{ + BEGIN_API + if (NumberOfAttributes == 0) + return CSSM_OK; // I suppose + Required(ContextAttributes); // preflight +#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE + HandleContext &context = HandleObject::find((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); + for (uint32 n = 0; n < NumberOfAttributes; n++) + context.deleteAttribute(ContextAttributes[n].AttributeType); + END_API(CSSM) +} + + +// +// Miscellaneous odds and ends - these functions just need a wee bit of +// manual massaging to fit. +// +CSSM_RETURN CSSMAPI +CSSM_DigestDataClone (CSSM_CC_HANDLE ccHandle, + CSSM_CC_HANDLE *newCCHandle) +{ + BEGIN_API +#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE + HandleContext &context = HandleObject::findAndLock((CSSM_HANDLE)ccHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); + TransitLock _(context.attachment); + HandleContext *newContext = + new(context.attachment) HandleContext(context.attachment, context.type(), context.algorithm()); + try { + newContext->CSPHandle = context.attachment.handle(); + newContext->copyFrom(context, context.attachment); + context.attachment.downcalls.DigestDataClone(context.attachment.handle(), ccHandle, newContext->handle()); + Required(newCCHandle) = newContext->handle(); + } catch (...) { + newContext->destroy(newContext, context.attachment); + throw; + } + END_API(CSSM) +} + + +CSSM_RETURN CSSMAPI +CSSM_QueryKeySizeInBits (CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE ccHandle, + const CSSM_KEY *key, + CSSM_KEY_SIZE_PTR keySize) +{ + //@@@ could afford not to lock attachment in have-CC case + BEGIN_API + Required(keySize); + Context *context; + CSPAttachment *attachment; + if (ccHandle == (CSSM_CC_HANDLE) HandleObject::invalidHandle) { + // key specified by CSPHandle and Key + attachment = &enterAttachment(CSPHandle); + context = NULL; + } else { + // key specified by ccHandle + HandleContext *ctx = &enterContext(ccHandle); + try { + attachment = &ctx->attachment; + context = ctx; + CSPHandle = context->CSPHandle; + key = &context->get(CSSM_ATTRIBUTE_KEY, + CSSMERR_CSP_INVALID_KEY); + } catch (...) { + attachment->exit(); + throw; + } + } + TransitLock _(*attachment); + CSSM_RETURN result = attachment->downcalls.QueryKeySizeInBits(CSPHandle, + ccHandle, context, key, keySize); + return result; + END_API(CSSM) +} + + +CSSM_RETURN CSSMAPI +CSSM_GenerateAlgorithmParams (CSSM_CC_HANDLE CCHandle, + uint32 ParamBits, + CSSM_DATA_PTR Param) +{ + BEGIN_API + // this function has more subtle locking than usual. Pay attention: + + // (1) Resolve context and ensure attachment exit + HandleContext &context = enterContext(CCHandle); + StLock _(context.attachment, true); + + // (2) Call CSP, acquiring module safe-lock for a moment (only) + CSSM_CONTEXT_ATTRIBUTE_PTR attributes; + uint32 count; + { + StLock _(context.attachment.module); + if (CSSM_RETURN err = + context.attachment.downcalls.GenerateAlgorithmParams(context.attachment.handle(), + CCHandle, &context, + ParamBits, Param, + &count, &attributes)) + CssmError::throwMe(err); + } + + // (3) Merge the attributes returned into the context, which will (again) acquire the module safe-lock internally + if (count) + context.mergeAttributes(attributes, count); + // the memory at (attributes, count) belongs to the CSP; don't free it here + END_API(CSSM) +} + + +// +// Include the auto-generated functions +// +#include diff --git a/libsecurity_cssm/lib/x509defs.h b/Security/libsecurity_cssm/lib/x509defs.h similarity index 99% rename from libsecurity_cssm/lib/x509defs.h rename to Security/libsecurity_cssm/lib/x509defs.h index b53e84ee..398cbc67 100644 --- a/libsecurity_cssm/lib/x509defs.h +++ b/Security/libsecurity_cssm/lib/x509defs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2002,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 1999-2002,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_cssm/libsecurity_cssm.xcodeproj/project.pbxproj b/Security/libsecurity_cssm/libsecurity_cssm.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_cssm/libsecurity_cssm.xcodeproj/project.pbxproj rename to Security/libsecurity_cssm/libsecurity_cssm.xcodeproj/project.pbxproj diff --git a/libsecurity_cssm/mds/cssm.mdsinfo b/Security/libsecurity_cssm/mds/cssm.mdsinfo similarity index 100% rename from libsecurity_cssm/mds/cssm.mdsinfo rename to Security/libsecurity_cssm/mds/cssm.mdsinfo diff --git a/libsecurity_filedb/Info-security_filedb.plist b/Security/libsecurity_filedb/Info-security_filedb.plist similarity index 100% rename from libsecurity_filedb/Info-security_filedb.plist rename to Security/libsecurity_filedb/Info-security_filedb.plist diff --git a/libsecurity_filedb/lib/AppleDatabase.cpp b/Security/libsecurity_filedb/lib/AppleDatabase.cpp similarity index 99% rename from libsecurity_filedb/lib/AppleDatabase.cpp rename to Security/libsecurity_filedb/lib/AppleDatabase.cpp index 4d640ebd..ddad1a74 100644 --- a/libsecurity_filedb/lib/AppleDatabase.cpp +++ b/Security/libsecurity_filedb/lib/AppleDatabase.cpp @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2001, 2003 Apple Computer, Inc. All Rights Reserved. - * + * Copyright (c) 2000-2001,2003,2011-2014 Apple Inc. All Rights Reserved. + * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). * You may not use this file except in compliance with the License. Please obtain * a copy of the License at http://www.apple.com/publicsource and read it before * using this file. - * + * * This 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 @@ -61,10 +61,10 @@ static void initCommon(void) { return; } - + // set the segment size ftruncate (segmentDescriptor, kSegmentSize); - + // map it into memory int32_t* tmp = (int32_t*) mmap (NULL, kSegmentSize, PROT_READ | PROT_WRITE, MAP_SHARED, segmentDescriptor, 0); close (segmentDescriptor); @@ -93,7 +93,7 @@ Table::Table(const ReadSection &inTableSection) : // until much later... see DbVersion::open() } -Table::~Table() +Table::~Table() { for_each_map_delete(mIndexMap.begin(), mIndexMap.end()); } @@ -108,7 +108,7 @@ Table::readIndexSection() for (uint32 i = 0; i < numIndexes; i++) { uint32 indexOffset = mTableSection.at(indexSectionOffset + (i + 2) * AtomSize); ReadSection indexSection(mTableSection.subsection(indexOffset)); - + auto_ptr index(new DbConstIndex(*this, indexSection)); mIndexMap.insert(ConstIndexMap::value_type(index->indexId(), index.get())); index.release(); @@ -122,7 +122,7 @@ Table::createCursor(const CSSM_QUERY *inQuery, const DbVersion &inDbVersion) con ConstIndexMap::const_iterator it; DbQueryKey *queryKey; - + for (it = mIndexMap.begin(); it != mIndexMap.end(); it++) if (it->second->matchesQuery(*inQuery, queryKey)) { IndexCursor *cursor = new IndexCursor(queryKey, inDbVersion, *this, it->second); @@ -240,7 +240,7 @@ ModifiedTable::deleteRecord(const RecordId &inRecordId) modifyTable(); uint32 aRecordNumber = inRecordId.mRecordNumber; - + // remove the record from all the indexes MutableIndexMap::iterator it; for (it = mIndexMap.begin(); it != mIndexMap.end(); it++) @@ -276,7 +276,7 @@ ModifiedTable::deleteRecord(const RecordId &inRecordId) // Remove the inserted (but uncommited) record. It should already be in mDeletedSet // if it existed previously in mTable. - delete anIt->second; + delete anIt->second; mInsertedMap.erase(anIt); } } @@ -287,11 +287,11 @@ ModifiedTable::insertRecord(uint32 inVersionId, const CssmData *inData) { modifyTable(); - + auto_ptr aWriteSection(new WriteSection()); getMetaRecord().packRecord(*aWriteSection, inAttributes, inData); uint32 aRecordNumber = nextRecordNumber(); - + // add the record to all the indexes; this will throw if the new record // violates a unique index MutableIndexMap::iterator it; @@ -304,7 +304,7 @@ ModifiedTable::insertRecord(uint32 inVersionId, mInsertedMap.insert(InsertedMap::value_type(aRecordNumber, aWriteSection.get())); aWriteSection.release(); - + return aRecordId; } @@ -503,7 +503,7 @@ ModifiedTable::createMutableIndexes() { if (mTable == NULL) return; - + Table::ConstIndexMap::const_iterator it; for (it = mTable->mIndexMap.begin(); it != mTable->mIndexMap.end(); it++) { auto_ptr mutableIndex(new DbMutableIndex(*it->second)); @@ -533,25 +533,25 @@ uint32 ModifiedTable::writeIndexSection(WriteSection &tableSection, uint32 offset) { MutableIndexMap::iterator it; - + tableSection.put(Table::OffsetIndexesOffset, offset); - + // leave room for the size, to be written later uint32 indexSectionOffset = offset; offset += AtomSize; - + offset = tableSection.put(offset, (uint32)mIndexMap.size()); - + // leave room for the array of offsets to the indexes uint32 indexOffsetOffset = offset; offset += mIndexMap.size() * AtomSize; - + // write the indexes for (it = mIndexMap.begin(); it != mIndexMap.end(); it++) { indexOffsetOffset = tableSection.put(indexOffsetOffset, offset); offset = it->second->writeIndex(tableSection, offset); } - + // write the total index section size tableSection.put(indexSectionOffset, offset - indexSectionOffset); @@ -567,7 +567,7 @@ ModifiedTable::writeTable(AtomicTempFile &inAtomicTempFile, uint32 inSectionOffs const ReadSection &tableSection = mTable->getTableSection(); uint32 tableSize = tableSection.at(Table::OffsetSize); - + inAtomicTempFile.write(AtomicFile::FromStart, inSectionOffset, tableSection.range(Range(0, tableSize)), tableSize); @@ -577,7 +577,7 @@ ModifiedTable::writeTable(AtomicTempFile &inAtomicTempFile, uint32 inSectionOffs // We should have an old mTable or a mNewMetaRecord but not both. assert(mTable != nil ^ mNewMetaRecord != nil); const MetaRecord &aNewMetaRecord = getMetaRecord(); - + uint32 aRecordsCount = 0; uint32 aRecordNumbersCount = recordNumberCount(); uint32 aRecordsOffset = Table::OffsetRecordNumbers + AtomSize * aRecordNumbersCount; @@ -586,14 +586,14 @@ ModifiedTable::writeTable(AtomicTempFile &inAtomicTempFile, uint32 inSectionOffs aTableSection.put(Table::OffsetId, aNewMetaRecord.dataRecordType()); aTableSection.put(Table::OffsetRecords, aRecordsOffset); aTableSection.put(Table::OffsetRecordNumbersCount, aRecordNumbersCount); - + uint32 anOffset = inSectionOffset + aRecordsOffset; if (mTable) { // XXX Handle schema changes in the future. assert(mNewMetaRecord == nil); - + // We have a modified old table so copy all non deleted records // The code below is rather elaborate, but this is because it attempts // to copy large ranges of non deleted records with single calls @@ -602,7 +602,7 @@ ModifiedTable::writeTable(AtomicTempFile &inAtomicTempFile, uint32 inSectionOffs ReadSection aRecordsSection = mTable->getRecordsSection(); uint32 aReadOffset = 0; // Offset of current record uint32 aWriteOffset = aRecordsOffset; // Offset for current write record - uint32 aBlockStart = aReadOffset; // Starting point for read + uint32 aBlockStart = aReadOffset; // Starting point for read uint32 aBlockSize = 0; // Size of block to read for (uint32 aRecord = 0; aRecord < anOldRecordsCount; aRecord++) { @@ -697,10 +697,10 @@ ModifiedTable::writeTable(AtomicTempFile &inAtomicTempFile, uint32 inSectionOffs aTableSection.put(Table::OffsetFreeListHead, aFreeListHead); anOffset -= inSectionOffset; - + // Write out indexes, which are part of the table section - { + { uint32 indexOffset = anOffset; anOffset = writeIndexSection(aTableSection, anOffset); inAtomicTempFile.write(AtomicFile::FromStart, inSectionOffset + indexOffset, @@ -719,6 +719,8 @@ ModifiedTable::writeTable(AtomicTempFile &inAtomicTempFile, uint32 inSectionOffs } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-const-variable" // // Metadata @@ -813,7 +815,7 @@ static const CSSM_DB_ATTRIBUTE_INFO SubserviceType = #define ATTRIBUTE(type, name) \ { CSSM_DB_ATTRIBUTE_NAME_AS_STRING, { (char*) #name }, CSSM_DB_ATTRIBUTE_FORMAT_ ## type } - + static const CSSM_DB_ATTRIBUTE_INFO AttrSchemaRelations[] = { //RelationID, RelationName @@ -858,6 +860,7 @@ static const CSSM_DB_ATTRIBUTE_INFO AttrSchemaParsingModule[] = }; #undef ATTRIBUTE +#pragma clang diagnostic pop // // DbVersion @@ -896,30 +899,30 @@ DbVersion::open() HeaderSize); if (aHeaderSection.at(OffsetMagic) != HeaderMagic) CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); - + // We currently only support one version. If we support additional // file format versions in the future fix this. uint32 aVersion = aHeaderSection.at(OffsetVersion); if (aVersion != HeaderVersion) CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); - + //const ReadSection anAuthSection = // mDatabase.subsection(HeaderOffset + aHeaderSection.at(OffsetAuthOffset)); // XXX Do something with anAuthSection. - + uint32 aSchemaOffset = aHeaderSection.at(OffsetSchemaOffset); const ReadSection aSchemaSection = mDatabase.subsection(HeaderOffset + aSchemaOffset); - + uint32 aSchemaSize = aSchemaSection[OffsetSchemaSize]; // Make sure that the given range exists. aSchemaSection.subsection(0, aSchemaSize); uint32 aTableCount = aSchemaSection[OffsetTablesCount]; - + // Assert that the size of this section is big enough. if (aSchemaSize < OffsetTables + AtomSize * aTableCount) CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); - + for (uint32 aTableNumber = 0; aTableNumber < aTableCount; aTableNumber++) { @@ -935,7 +938,7 @@ DbVersion::open() } // Fill in the schema for the meta tables. - + findTable(mDb.schemaRelations.DataRecordType).getMetaRecord(). setRecordAttributeInfo(mDb.schemaRelations); findTable(mDb.schemaIndexes.DataRecordType).getMetaRecord(). @@ -1023,8 +1026,8 @@ DbVersion::open() // Skip the schema relations for the meta tables themselves. // FIXME: this hard-wires the meta-table relation IDs to be // within {CSSM_DB_RECORDTYPE_SCHEMA_START... - // CSSM_DB_RECORDTYPE_SCHEMA_END} (which is {0..4}). - // Bogus - the MDS schema relation IDs start at + // CSSM_DB_RECORDTYPE_SCHEMA_END} (which is {0..4}). + // Bogus - the MDS schema relation IDs start at // CSSM_DB_RELATIONID_MDS_START which is 0x40000000. // Ref. Radar 2817921. if (CSSM_DB_RECORDTYPE_SCHEMA_START <= aRelationId && aRelationId < CSSM_DB_RECORDTYPE_SCHEMA_END) @@ -1066,7 +1069,7 @@ DbVersion::open() aNameID = &static_cast(aRecordData[4]); } - // Make sure that the attribute specified by anAttributeNameFormat is present. + // Make sure that the attribute specified by anAttributeNameFormat is present. switch (anAttributeNameFormat) { case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: @@ -1086,7 +1089,7 @@ DbVersion::open() // Create the attribute aMetaRecord.createAttribute(aName.get(), aNameID, anAttributeId, anAttributeFormat); } - + // initialize the indexes associated with each table { TableMap::iterator it; @@ -1285,7 +1288,7 @@ LinearCursor::next(Table::Id &outTableId, // // IndexCursor -// +// IndexCursor::IndexCursor(DbQueryKey *queryKey, const DbVersion &inDbVersion, const Table &table, const DbConstIndex *index) : @@ -1307,13 +1310,13 @@ IndexCursor::next(Table::Id &outTableId, { if (mBegin == mEnd) return false; - + ReadSection rs = mIndex->getRecordSection(mBegin++); const MetaRecord &metaRecord = mTable.getMetaRecord(); outTableId = metaRecord.dataRecordType(); metaRecord.unpackRecord(rs, inAllocator, outAttributes, outData, 0); - + recordId = MetaRecord::unpackRecordId(rs); return true; } @@ -1358,7 +1361,7 @@ MultiCursor::next(Table::Id &outTableId, if (mCursor->next(outTableId, inoutAttributes, inoutData, inAllocator, recordId)) return true; - + mCursor.reset(NULL); } } @@ -1412,7 +1415,7 @@ DbModifier::getDbVersion(bool force) { mNotifyCount = *gSegment; } - + mDbLastRead = CFAbsoluteTimeGetCurrent(); /* If we already have a mDbVersion, let's check if we can reuse it. */ @@ -1459,7 +1462,7 @@ DbModifier::createDatabase(const CSSM_DBINFO &inDbInfo, createTable(new MetaRecord(mDb.schemaAttributes)); createTable(new MetaRecord(mDb.schemaIndexes)); createTable(new MetaRecord(mDb.schemaParsingModule)); - + // now add the meta-tables' schema to the meta tables themselves insertTableSchema(mDb.schemaRelations); insertTableSchema(mDb.schemaAttributes); @@ -1715,18 +1718,18 @@ DbModifier::commit() mAtomicTempFile = NULL; /* Initialize the shared memory file change mechanism */ pthread_once(&gCommonInitMutex, initCommon); - + if (gSegment != NULL) { /* PLEASE NOTE: - - The following operation is endian safe because we are not looking - for monotonic increase. I have tested every possible value of + + The following operation is endian safe because we are not looking + for monotonic increase. I have tested every possible value of *gSegment, and there is no value for which alternating big and little endian increments will produce the original value. */ - + OSAtomicIncrement32Barrier (gSegment); } } @@ -1768,7 +1771,7 @@ DbModifier::createCursor(const CSSM_QUERY *inQuery) if (mAtomicTempFile) { // We are modifying this database. - + // If we have a mDbVersion already then it's a snapshot of the database // right before the modifications started. So return a cursor using // that. @@ -1804,7 +1807,7 @@ DbModifier::insertTableSchema(const CssmDbRecordAttributeInfo &inInfo, // Insert the record into the SchemaRelations ModifiedTable findTable(mDb.schemaRelations.DataRecordType).insertRecord(mVersionId, &aRecordBuilder, NULL); - + ModifiedTable &anAttributeTable = findTable(mDb.schemaAttributes.DataRecordType); for (uint32 anIndex = 0; anIndex < inInfo.size(); anIndex++) { @@ -1814,7 +1817,7 @@ DbModifier::insertTableSchema(const CssmDbRecordAttributeInfo &inInfo, aRecordBuilder.add(AttributeNameFormat, inInfo.at(anIndex).nameFormat()); uint32 attributeId = aMetaRecord.metaAttribute(inInfo.at(anIndex)).attributeId(); - + switch (inInfo.at(anIndex).nameFormat()) { case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: @@ -1837,33 +1840,33 @@ DbModifier::insertTableSchema(const CssmDbRecordAttributeInfo &inInfo, } if (inIndexInfo != NULL) { - + if (inIndexInfo->DataRecordType != inInfo.DataRecordType && inIndexInfo->NumberOfIndexes > 0) CssmError::throwMe(CSSMERR_DL_INVALID_RECORDTYPE); - + ModifiedTable &indexMetaTable = findTable(mDb.schemaIndexes.DataRecordType); uint32 aNumberOfIndexes = inIndexInfo->NumberOfIndexes; - + for (uint32 anIndex = 0; anIndex < aNumberOfIndexes; anIndex++) { const CssmDbIndexInfo &thisIndex = CssmDbIndexInfo::overlay(inIndexInfo->IndexInfo[anIndex]); - + // make sure the index is supported if (thisIndex.dataLocation() != CSSM_DB_INDEX_ON_ATTRIBUTE) CssmError::throwMe(CSSMERR_DL_INVALID_INDEX_INFO); - + // assign an index ID: the unique index is ID 0, all others are ID > 0 uint32 indexId; if (thisIndex.IndexType == CSSM_DB_INDEX_UNIQUE) indexId = 0; else indexId = anIndex + 1; - + // figure out the attribute ID uint32 attributeId = aMetaRecord.metaAttribute(thisIndex.Info).attributeId(); - + // Create an entry for the SchemaIndexes table. aRecordBuilder.clear(); aRecordBuilder.add(RelationID, inInfo.DataRecordType); @@ -1874,7 +1877,7 @@ DbModifier::insertTableSchema(const CssmDbRecordAttributeInfo &inInfo, // Insert the record into the SchemaIndexes ModifiedTable indexMetaTable.insertRecord(mVersionId, &aRecordBuilder, NULL); - + // update the table's index objects DbMutableIndex &index = aTable.findIndex(indexId, aMetaRecord, indexId == 0); index.appendAttribute(attributeId); @@ -1952,7 +1955,7 @@ DbModifier::insertTable(Table::Id inTableId, const string &inTableName, // Insert the record into the SchemaIndexes ModifiedTable anIndexTable.insertRecord(mVersionId, &aRecordBuilder, NULL); - + // update the table's index objects DbMutableIndex &index = aTable->findIndex(inIndexInfo[anIndex].IndexId, aTable->getMetaRecord(), inIndexInfo[anIndex].IndexType == CSSM_DB_INDEX_UNIQUE); @@ -1988,7 +1991,7 @@ AppleDatabaseManager::AppleDatabaseManager(const AppleDatabaseTableName *tableNa mTableNames(tableNames) { // make sure that a proper set of table ids and names has been provided - + if (!mTableNames) CssmError::throwMe(CSSMERR_DL_INTERNAL_ERROR); else { @@ -2100,11 +2103,11 @@ const char *AppleDatabase::recordName(CSSM_DB_RECORDTYPE inRecordType) const { if (inRecordType == CSSM_DL_DB_RECORD_ANY || inRecordType == CSSM_DL_DB_RECORD_ALL_KEYS) CssmError::throwMe(CSSMERR_DL_INVALID_RECORDTYPE); - + for (uint32 i = 0; mTableNames[i].mTableName; i++) if (mTableNames[i].mTableId == inRecordType) return mTableNames[i].mTableName; - + return ""; } @@ -2294,11 +2297,11 @@ AppleDatabase::dataDelete(DbContext &inDbContext, // an exception. memset(&attrData, 0, sizeof(attrData)); dataGetFromUniqueRecordId(inDbContext, inUniqueRecord, &attrData, NULL); - + if (attrData.DataRecordType == CSSM_DL_DB_RECORD_GENERIC_PASSWORD) { CSSM_DB_ATTRIBUTE_DATA attributes; - + // setup some attributes and see if we are indeed the .Mac password attributes.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER; attributes.Info.Label.AttributeID = 'svce'; @@ -2307,21 +2310,21 @@ AppleDatabase::dataDelete(DbContext &inDbContext, attributes.Value = NULL; attrData.NumberOfAttributes = 1; - attrData.AttributeData = &attributes; - + attrData.AttributeData = &attributes; + dataGetFromUniqueRecordId(inDbContext, inUniqueRecord, &attrData, NULL); - + // now check the results std::string dataString((const char*) attrData.AttributeData[0].Value[0].Data, attrData.AttributeData[0].Value[0].Length); if (dataString == "iTools") { syslog(LOG_WARNING, "Warning: Removed .Me password"); } - + free(attrData.AttributeData[0].Value[0].Data); free(attrData.AttributeData[0].Value); } - + StLock _(mWriteLock); Table::Id aTableId; const RecordId aRecordId(parseUniqueRecord(inUniqueRecord, aTableId)); @@ -2398,7 +2401,7 @@ AppleDatabase::dataGetFirst(DbContext &inDbContext, auto_ptr aCursor(mDbModifier.createCursor(inQuery)); Table::Id aTableId; RecordId aRecordId; - + if (!aCursor->next(aTableId, inoutAttributes, inoutData, inDbContext.mDatabaseSession, aRecordId)) // return a NULL handle, and implicitly delete the cursor @@ -2418,7 +2421,7 @@ AppleDatabase::dataGetNext(DbContext &inDbContext, auto_ptr aCursor(&HandleObject::find(inResultsHandle, CSSMERR_DL_INVALID_RESULTS_HANDLE)); Table::Id aTableId; RecordId aRecordId; - + if (!aCursor->next(aTableId, inoutAttributes, inoutData, inDbContext.mDatabaseSession, aRecordId)) return false; @@ -2527,11 +2530,11 @@ AppleDatabase::passThrough(DbContext &dbContext, dbc.autoCommit(inputParams ? CSSM_TRUE : CSSM_FALSE); } break; - + case CSSM_APPLEFILEDL_COMMIT: mDbModifier.commit(); break; - + case CSSM_APPLEFILEDL_ROLLBACK: mDbModifier.rollback(); break; @@ -2539,7 +2542,7 @@ AppleDatabase::passThrough(DbContext &dbContext, case CSSM_APPLECSPDL_DB_RELATION_EXISTS: { CSSM_BOOL returnValue; - + CSSM_DB_RECORDTYPE recordType = *(CSSM_DB_RECORDTYPE*) inputParams; if (recordType == CSSM_DL_DB_RECORD_ANY || recordType == CSSM_DL_DB_RECORD_ALL_KEYS) { @@ -2549,7 +2552,7 @@ AppleDatabase::passThrough(DbContext &dbContext, { returnValue = mDbModifier.hasTable(recordType); } - + *(CSSM_BOOL*) outputParams = returnValue; break; } diff --git a/libsecurity_filedb/lib/AppleDatabase.h b/Security/libsecurity_filedb/lib/AppleDatabase.h similarity index 99% rename from libsecurity_filedb/lib/AppleDatabase.h rename to Security/libsecurity_filedb/lib/AppleDatabase.h index 738b9126..c0e9dbd7 100644 --- a/libsecurity_filedb/lib/AppleDatabase.h +++ b/Security/libsecurity_filedb/lib/AppleDatabase.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001, 2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_filedb/lib/AtomicFile.cpp b/Security/libsecurity_filedb/lib/AtomicFile.cpp similarity index 99% rename from libsecurity_filedb/lib/AtomicFile.cpp rename to Security/libsecurity_filedb/lib/AtomicFile.cpp index 7ff71756..68049c24 100644 --- a/libsecurity_filedb/lib/AtomicFile.cpp +++ b/Security/libsecurity_filedb/lib/AtomicFile.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2013 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_filedb/lib/AtomicFile.h b/Security/libsecurity_filedb/lib/AtomicFile.h similarity index 98% rename from libsecurity_filedb/lib/AtomicFile.h rename to Security/libsecurity_filedb/lib/AtomicFile.h index eb94691a..65d8905a 100644 --- a/libsecurity_filedb/lib/AtomicFile.h +++ b/Security/libsecurity_filedb/lib/AtomicFile.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001, 2003 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_filedb/lib/DbIndex.cpp b/Security/libsecurity_filedb/lib/DbIndex.cpp similarity index 99% rename from libsecurity_filedb/lib/DbIndex.cpp rename to Security/libsecurity_filedb/lib/DbIndex.cpp index d31a8775..8c1d40e6 100644 --- a/libsecurity_filedb/lib/DbIndex.cpp +++ b/Security/libsecurity_filedb/lib/DbIndex.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_filedb/lib/DbIndex.h b/Security/libsecurity_filedb/lib/DbIndex.h similarity index 98% rename from libsecurity_filedb/lib/DbIndex.h rename to Security/libsecurity_filedb/lib/DbIndex.h index 2e4b1c7b..d178b26d 100644 --- a/libsecurity_filedb/lib/DbIndex.h +++ b/Security/libsecurity_filedb/lib/DbIndex.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_filedb/lib/DbQuery.cpp b/Security/libsecurity_filedb/lib/DbQuery.cpp similarity index 93% rename from libsecurity_filedb/lib/DbQuery.cpp rename to Security/libsecurity_filedb/lib/DbQuery.cpp index f88d487b..90ed4ca5 100644 --- a/libsecurity_filedb/lib/DbQuery.cpp +++ b/Security/libsecurity_filedb/lib/DbQuery.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_filedb/lib/DbQuery.h b/Security/libsecurity_filedb/lib/DbQuery.h similarity index 94% rename from libsecurity_filedb/lib/DbQuery.h rename to Security/libsecurity_filedb/lib/DbQuery.h index 1e48853c..6a7c38b4 100644 --- a/libsecurity_filedb/lib/DbQuery.h +++ b/Security/libsecurity_filedb/lib/DbQuery.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_filedb/lib/DbValue.cpp b/Security/libsecurity_filedb/lib/DbValue.cpp similarity index 99% rename from libsecurity_filedb/lib/DbValue.cpp rename to Security/libsecurity_filedb/lib/DbValue.cpp index 47e924e7..f004fa34 100644 --- a/libsecurity_filedb/lib/DbValue.cpp +++ b/Security/libsecurity_filedb/lib/DbValue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_filedb/lib/DbValue.h b/Security/libsecurity_filedb/lib/DbValue.h similarity index 98% rename from libsecurity_filedb/lib/DbValue.h rename to Security/libsecurity_filedb/lib/DbValue.h index b4580d6c..1d4fa103 100644 --- a/libsecurity_filedb/lib/DbValue.h +++ b/Security/libsecurity_filedb/lib/DbValue.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_filedb/lib/MetaAttribute.cpp b/Security/libsecurity_filedb/lib/MetaAttribute.cpp similarity index 98% rename from libsecurity_filedb/lib/MetaAttribute.cpp rename to Security/libsecurity_filedb/lib/MetaAttribute.cpp index 7d8c1ab4..7a6214ae 100644 --- a/libsecurity_filedb/lib/MetaAttribute.cpp +++ b/Security/libsecurity_filedb/lib/MetaAttribute.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_filedb/lib/MetaAttribute.h b/Security/libsecurity_filedb/lib/MetaAttribute.h similarity index 98% rename from libsecurity_filedb/lib/MetaAttribute.h rename to Security/libsecurity_filedb/lib/MetaAttribute.h index 2e61d2ed..1456cd3a 100644 --- a/libsecurity_filedb/lib/MetaAttribute.h +++ b/Security/libsecurity_filedb/lib/MetaAttribute.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_filedb/lib/MetaRecord.cpp b/Security/libsecurity_filedb/lib/MetaRecord.cpp similarity index 99% rename from libsecurity_filedb/lib/MetaRecord.cpp rename to Security/libsecurity_filedb/lib/MetaRecord.cpp index 9fc54a90..63be9447 100644 --- a/libsecurity_filedb/lib/MetaRecord.cpp +++ b/Security/libsecurity_filedb/lib/MetaRecord.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_filedb/lib/MetaRecord.h b/Security/libsecurity_filedb/lib/MetaRecord.h similarity index 98% rename from libsecurity_filedb/lib/MetaRecord.h rename to Security/libsecurity_filedb/lib/MetaRecord.h index b71a77dd..f119772d 100644 --- a/libsecurity_filedb/lib/MetaRecord.h +++ b/Security/libsecurity_filedb/lib/MetaRecord.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_filedb/lib/OverUnderflowCheck.h b/Security/libsecurity_filedb/lib/OverUnderflowCheck.h similarity index 100% rename from libsecurity_filedb/lib/OverUnderflowCheck.h rename to Security/libsecurity_filedb/lib/OverUnderflowCheck.h diff --git a/libsecurity_filedb/lib/ReadWriteSection.cpp b/Security/libsecurity_filedb/lib/ReadWriteSection.cpp similarity index 100% rename from libsecurity_filedb/lib/ReadWriteSection.cpp rename to Security/libsecurity_filedb/lib/ReadWriteSection.cpp diff --git a/libsecurity_filedb/lib/ReadWriteSection.h b/Security/libsecurity_filedb/lib/ReadWriteSection.h similarity index 98% rename from libsecurity_filedb/lib/ReadWriteSection.h rename to Security/libsecurity_filedb/lib/ReadWriteSection.h index 8c5240fa..f77e8c4c 100644 --- a/libsecurity_filedb/lib/ReadWriteSection.h +++ b/Security/libsecurity_filedb/lib/ReadWriteSection.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_filedb/lib/SelectionPredicate.cpp b/Security/libsecurity_filedb/lib/SelectionPredicate.cpp similarity index 96% rename from libsecurity_filedb/lib/SelectionPredicate.cpp rename to Security/libsecurity_filedb/lib/SelectionPredicate.cpp index 85426ac2..fe9efaf0 100644 --- a/libsecurity_filedb/lib/SelectionPredicate.cpp +++ b/Security/libsecurity_filedb/lib/SelectionPredicate.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_filedb/lib/SelectionPredicate.h b/Security/libsecurity_filedb/lib/SelectionPredicate.h similarity index 95% rename from libsecurity_filedb/lib/SelectionPredicate.h rename to Security/libsecurity_filedb/lib/SelectionPredicate.h index d5b93c5d..a0a14c2a 100644 --- a/libsecurity_filedb/lib/SelectionPredicate.h +++ b/Security/libsecurity_filedb/lib/SelectionPredicate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_filedb/libsecurity_filedb.xcodeproj/project.pbxproj b/Security/libsecurity_filedb/libsecurity_filedb.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_filedb/libsecurity_filedb.xcodeproj/project.pbxproj rename to Security/libsecurity_filedb/libsecurity_filedb.xcodeproj/project.pbxproj diff --git a/libsecurity_keychain/APPLE_LICENSE b/Security/libsecurity_keychain/APPLE_LICENSE similarity index 100% rename from libsecurity_keychain/APPLE_LICENSE rename to Security/libsecurity_keychain/APPLE_LICENSE diff --git a/libsecurity_keychain/Info-security_keychain.plist b/Security/libsecurity_keychain/Info-security_keychain.plist similarity index 100% rename from libsecurity_keychain/Info-security_keychain.plist rename to Security/libsecurity_keychain/Info-security_keychain.plist diff --git a/libsecurity_keychain/Security b/Security/libsecurity_keychain/Security similarity index 100% rename from libsecurity_keychain/Security rename to Security/libsecurity_keychain/Security diff --git a/libsecurity_keychain/lib/ACL.cpp b/Security/libsecurity_keychain/lib/ACL.cpp similarity index 99% rename from libsecurity_keychain/lib/ACL.cpp rename to Security/libsecurity_keychain/lib/ACL.cpp index 150ca350..9b655a69 100644 --- a/libsecurity_keychain/lib/ACL.cpp +++ b/Security/libsecurity_keychain/lib/ACL.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/ACL.h b/Security/libsecurity_keychain/lib/ACL.h similarity index 98% rename from libsecurity_keychain/lib/ACL.h rename to Security/libsecurity_keychain/lib/ACL.h index 93850df6..5ad2a2df 100644 --- a/libsecurity_keychain/lib/ACL.h +++ b/Security/libsecurity_keychain/lib/ACL.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/Access.cpp b/Security/libsecurity_keychain/lib/Access.cpp similarity index 99% rename from libsecurity_keychain/lib/Access.cpp rename to Security/libsecurity_keychain/lib/Access.cpp index cd76f67d..d510cd98 100644 --- a/libsecurity_keychain/lib/Access.cpp +++ b/Security/libsecurity_keychain/lib/Access.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/Access.h b/Security/libsecurity_keychain/lib/Access.h similarity index 98% rename from libsecurity_keychain/lib/Access.h rename to Security/libsecurity_keychain/lib/Access.h index 1d57909a..ec562dd8 100644 --- a/libsecurity_keychain/lib/Access.h +++ b/Security/libsecurity_keychain/lib/Access.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_keychain/lib/AppleBaselineEscrowCertificates.h b/Security/libsecurity_keychain/lib/AppleBaselineEscrowCertificates.h new file mode 100644 index 00000000..56a9b6cf --- /dev/null +++ b/Security/libsecurity_keychain/lib/AppleBaselineEscrowCertificates.h @@ -0,0 +1,178 @@ +/* + * 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@ + */ + + +#ifndef sec_AppleBaselineEscrowCertificates_h +#define sec_AppleBaselineEscrowCertificates_h + +struct RootRecord +{ + size_t _length; + UInt8* _bytes; +}; + +/* ========================================================================== + Production Escrow Certificates + ========================================================================== */ + + +static const UInt8 kBaseLineEscrowRootGM[] = { + 0x30,0x82,0x03,0xd0,0x30,0x82,0x02,0xb8,0xa0,0x03,0x02,0x01,0x02,0x02,0x01,0x64, + 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x30, + 0x79,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,0x04,0x05,0x13,0x03,0x31,0x30,0x30,0x31, + 0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11, + 0x06,0x03,0x55,0x04,0x0a,0x13,0x0a,0x41,0x70,0x70,0x6c,0x65,0x20,0x49,0x6e,0x63, + 0x2e,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0b,0x13,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,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,0x33, + 0x30,0x38,0x30,0x32,0x32,0x33,0x32,0x34,0x34,0x34,0x5a,0x17,0x0d,0x32,0x33,0x30, + 0x38,0x30,0x32,0x32,0x33,0x32,0x34,0x34,0x34,0x5a,0x30,0x79,0x31,0x0c,0x30,0x0a, + 0x06,0x03,0x55,0x04,0x05,0x13,0x03,0x31,0x30,0x30,0x31,0x0b,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0a, + 0x13,0x0a,0x41,0x70,0x70,0x6c,0x65,0x20,0x49,0x6e,0x63,0x2e,0x31,0x26,0x30,0x24, + 0x06,0x03,0x55,0x04,0x0b,0x13,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,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,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48, + 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01, + 0x0a,0x02,0x82,0x01,0x01,0x00,0xd0,0xa3,0xf4,0x56,0x7d,0x3f,0x46,0x31,0xd2,0x56, + 0xa0,0xdf,0x42,0xa0,0x29,0x83,0x1e,0xb9,0x82,0xb5,0xa5,0xff,0x3e,0xde,0xb5,0x0f, + 0x4a,0x8a,0x28,0x60,0xcf,0x75,0xb4,0xa0,0x70,0x7c,0xf5,0xe2,0x94,0xf3,0x22,0x02, + 0xc8,0x81,0xce,0x34,0xc7,0x66,0x6a,0x18,0xaa,0xb4,0xfd,0x6d,0xb0,0x0b,0xdd,0x4a, + 0xdd,0xcf,0xe0,0x08,0x1b,0x1c,0xa6,0xdb,0xba,0xb2,0xc1,0xa4,0x10,0x5f,0x35,0x4f, + 0x8b,0x8b,0x7a,0xa3,0xdb,0x3c,0xf6,0x54,0x95,0x42,0xad,0x2a,0x3b,0xfe,0x06,0x8c, + 0xe1,0x92,0xf1,0x60,0x97,0x58,0x1b,0xd9,0x8f,0xbe,0xfb,0x46,0x4c,0x29,0x5c,0x1c, + 0xf0,0x20,0xb6,0x2b,0xa5,0x12,0x09,0x9b,0x28,0x41,0x34,0x97,0x9f,0xf3,0x88,0x4b, + 0x69,0x72,0xea,0x3a,0x27,0xb0,0x50,0x1d,0x88,0x29,0x0d,0xbb,0xed,0x04,0xa2,0x11, + 0xcf,0x0c,0x5b,0x65,0x61,0x35,0xbd,0xf2,0x0d,0xfc,0xe2,0xb9,0x20,0xd3,0xb7,0x03, + 0x70,0x39,0xd5,0xe0,0x86,0x7c,0x04,0xcc,0xc9,0xa1,0x85,0xb4,0x9b,0xbc,0x88,0x4e, + 0xd7,0xad,0x5c,0xff,0x2c,0x0d,0x80,0x8e,0x51,0x39,0x20,0x8b,0xaf,0x1e,0x46,0x95, + 0xfa,0x0d,0x1b,0xd2,0xbf,0x80,0xe0,0x9f,0x6d,0x4a,0xf5,0x31,0x67,0x18,0x11,0xa5, + 0x63,0x27,0x08,0xee,0xd9,0x07,0x29,0xd0,0xd4,0x36,0x91,0x5b,0xfb,0x4a,0x0b,0x07, + 0xd1,0x0d,0x79,0x16,0x6e,0x16,0x02,0x23,0x80,0xc6,0x15,0x07,0x6d,0xa0,0x06,0xb6, + 0x45,0x90,0xb0,0xae,0xa4,0xad,0x0e,0x75,0x04,0x2b,0x2b,0x78,0xf1,0x57,0x84,0x23, + 0x87,0x24,0xec,0x58,0xc4,0xf1,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,0x01,0x06, + 0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e,0x04,0x16,0x04,0x14,0xfd,0x78,0x96,0x53,0x80, + 0xd6,0xf6,0xdc,0xa6,0xc3,0x59,0x06,0x38,0xed,0x79,0x3e,0x8f,0x50,0x1b,0x50,0x30, + 0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xfd,0x78,0x96,0x53, + 0x80,0xd6,0xf6,0xdc,0xa6,0xc3,0x59,0x06,0x38,0xed,0x79,0x3e,0x8f,0x50,0x1b,0x50, + 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03, + 0x82,0x01,0x01,0x00,0x71,0x15,0xca,0x87,0xd0,0x2d,0xb5,0x18,0xd5,0x35,0x7a,0xcd, + 0xdf,0x62,0x28,0xf0,0x0b,0x63,0x4d,0x4e,0x02,0xba,0x3d,0xb8,0xb4,0x37,0xea,0xb0, + 0x93,0x93,0xab,0x1c,0xfd,0x9f,0xe8,0x72,0xbf,0xf3,0xdb,0xe6,0xad,0x16,0xfe,0x71, + 0x61,0xa8,0x5a,0xd0,0x58,0x0f,0x65,0x7a,0x57,0x7a,0xe0,0x34,0x80,0x8e,0xbb,0x41, + 0x01,0xe7,0xb0,0x3b,0xf7,0x2b,0x3a,0x6d,0x44,0x2a,0x3a,0x04,0x52,0xfa,0x2b,0x7b, + 0x3b,0x21,0xdd,0x0c,0x70,0x3d,0xfb,0x45,0xc6,0x79,0x68,0x62,0xe2,0x89,0xb8,0x25, + 0xee,0x63,0x76,0x02,0xb2,0x22,0xe9,0x53,0x85,0x68,0x3e,0x75,0xb6,0x0b,0x65,0xe9, + 0x1c,0xba,0x84,0x93,0xb0,0x8a,0xef,0xb5,0x1a,0x12,0xe4,0x8f,0xae,0xd5,0x5c,0xa1, + 0x05,0x4a,0x01,0xbc,0x6f,0xf9,0x58,0x5e,0xf7,0x04,0x61,0xee,0xf5,0xc6,0xa0,0x1b, + 0x44,0x2e,0x5a,0x3a,0x59,0xa1,0xb3,0xb0,0xf4,0xb6,0xcb,0xe0,0x6c,0x2b,0x59,0x8a, + 0xfb,0x6a,0xe0,0xa2,0x57,0x09,0x79,0xc1,0xdd,0xfb,0x84,0x86,0xeb,0x66,0x29,0x73, + 0xae,0xbf,0x58,0xae,0x47,0x4d,0x48,0x37,0xd6,0xb1,0x8c,0x5f,0x26,0x5f,0xb5,0x26, + 0x07,0x0b,0x85,0xb7,0x36,0x37,0x14,0xcf,0x5e,0x55,0xa5,0x3c,0xf3,0x1e,0x79,0x50, + 0xbb,0x85,0x3b,0xb2,0x94,0x68,0xb0,0x25,0x4f,0x75,0xec,0xf0,0xf9,0xc0,0x5a,0x2d, + 0xe5,0xed,0x67,0xcd,0x88,0x55,0xa0,0x42,0xde,0x78,0xbc,0xfe,0x30,0xb1,0x62,0x2d, + 0xe1,0xfd,0xec,0x75,0x03,0xa6,0x1f,0x7c,0xc4,0x3a,0x4a,0x59,0xfe,0x77,0xc3,0x99, + 0x96,0x87,0x44,0xc3, +}; + +static const UInt8 kBaseLinePCSEscrowRootGM[] = { + 0x30,0x82,0x03,0xD8,0x30,0x82,0x02,0xC0,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x64, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30, + 0x7D,0x31,0x0C,0x30,0x0A,0x06,0x03,0x55,0x04,0x05,0x13,0x03,0x31,0x30,0x30,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11, + 0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, + 0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,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,0x23,0x30,0x21,0x06,0x03,0x55, + 0x04,0x03,0x13,0x1A,0x45,0x66,0x66,0x61,0x63,0x65,0x61,0x62,0x6C,0x65,0x20,0x53, + 0x65,0x72,0x76,0x69,0x63,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x1E, + 0x17,0x0D,0x31,0x34,0x30,0x37,0x32,0x38,0x32,0x31,0x30,0x33,0x35,0x32,0x5A,0x17, + 0x0D,0x32,0x34,0x30,0x37,0x32,0x38,0x32,0x31,0x30,0x33,0x35,0x32,0x5A,0x30,0x7D, + 0x31,0x0C,0x30,0x0A,0x06,0x03,0x55,0x04,0x05,0x13,0x03,0x31,0x30,0x30,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06, + 0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E, + 0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,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,0x23,0x30,0x21,0x06,0x03,0x55,0x04, + 0x03,0x13,0x1A,0x45,0x66,0x66,0x61,0x63,0x65,0x61,0x62,0x6C,0x65,0x20,0x53,0x65, + 0x72,0x76,0x69,0x63,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,0xC0,0x55, + 0xCC,0x74,0xCF,0x49,0xE9,0xEC,0x9A,0x76,0x17,0x30,0x12,0x40,0x7D,0xC1,0x69,0x98, + 0x97,0x2C,0xA7,0xC0,0xD6,0xF4,0x9A,0x1D,0xC2,0x46,0x75,0xB6,0xAD,0x81,0xE2,0x2F, + 0x65,0xF1,0xAF,0xF6,0xBA,0xBD,0xC1,0x44,0x37,0x93,0xB8,0x92,0x2A,0x83,0xCC,0xE3, + 0x6F,0xFD,0x95,0xAA,0x86,0xAE,0x4D,0x62,0x98,0xBC,0xE6,0x90,0x40,0x5B,0x5A,0x2E, + 0x65,0x0C,0xFF,0x07,0xB9,0x79,0xC4,0x2E,0x2E,0x72,0x80,0xE3,0xB9,0x98,0x08,0xE9, + 0x3B,0x79,0x3B,0x46,0x99,0xD7,0xB9,0xDF,0x1F,0xC4,0x0D,0x49,0xB9,0x78,0x39,0xAF, + 0x7F,0xF5,0xDC,0x9C,0xEE,0xC1,0xB0,0x90,0x70,0x97,0xD6,0xE7,0x49,0x0C,0x11,0x19, + 0xE9,0xDD,0xEA,0x38,0x30,0xB9,0x1D,0xF4,0xD7,0xFF,0xBB,0xFC,0x6B,0x49,0xFC,0x69, + 0xE8,0x05,0x8E,0x96,0x14,0x87,0x62,0xD6,0x82,0x2F,0xA2,0x97,0xB5,0x4A,0x80,0x46, + 0x43,0xF5,0xF2,0x1B,0x94,0xBF,0xFE,0x48,0x8B,0x7F,0x4D,0xD6,0x3D,0x3E,0x64,0xBE, + 0x09,0x7C,0x9E,0x24,0x80,0xDE,0xAB,0xC9,0x17,0x91,0xAC,0x60,0x06,0x98,0x9C,0xCB, + 0xAD,0x04,0x41,0x1F,0x7F,0xE5,0xC2,0x08,0xD5,0x80,0xD7,0x63,0xF1,0x5C,0x60,0xA2, + 0xE5,0xAD,0x5F,0x6E,0xBC,0x3A,0xC4,0x9F,0x4D,0xE4,0x65,0xA3,0xF2,0x18,0x0B,0x1A, + 0x2D,0xB4,0x64,0x3D,0x53,0x5A,0x14,0xF6,0x26,0x92,0x13,0x23,0x83,0x33,0xBE,0xE0, + 0xA4,0x43,0xFC,0x79,0xA0,0x91,0xFB,0x1C,0x17,0xF0,0x87,0xE5,0x8C,0x68,0xF2,0xCF, + 0xAE,0x3B,0xC5,0xD5,0xD2,0x58,0x8E,0xFB,0x29,0x53,0xFE,0x9E,0xDE,0x4F,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,0x01,0x06,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04, + 0x16,0x04,0x14,0x64,0x0B,0xE4,0x72,0x73,0x5C,0x54,0xB2,0x58,0x59,0xAE,0x42,0xDF, + 0x2B,0xB7,0xBA,0xB9,0xEB,0x86,0xAE,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18, + 0x30,0x16,0x80,0x14,0x64,0x0B,0xE4,0x72,0x73,0x5C,0x54,0xB2,0x58,0x59,0xAE,0x42, + 0xDF,0x2B,0xB7,0xBA,0xB9,0xEB,0x86,0xAE,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x79,0xF4,0x22,0xC9, + 0x6C,0x25,0x64,0x2D,0x8E,0x91,0x53,0x7B,0xFB,0xA7,0xD2,0x0C,0xAD,0xDC,0xA9,0x83, + 0x90,0x75,0x16,0x98,0xC1,0x2C,0xFE,0x7C,0x16,0xCE,0x2A,0xA0,0xB8,0x8A,0xF6,0xDB, + 0x3E,0x2D,0x6C,0x5D,0x61,0x41,0x10,0xBB,0x02,0xBA,0x51,0x5B,0x42,0x62,0x18,0x9F, + 0xC4,0x25,0xF3,0x24,0xCC,0x1D,0xD2,0xFF,0x47,0xB2,0x14,0x9E,0x6A,0x31,0xA3,0xA7, + 0xB1,0x0C,0x7E,0x55,0xCE,0xC4,0x9E,0xA6,0x0A,0x06,0x9B,0x50,0x40,0x04,0x13,0xA0, + 0xC7,0x4D,0x37,0xD9,0x85,0xCF,0xB2,0xD9,0x16,0x38,0x4B,0xA3,0xA5,0x3E,0xDC,0x06, + 0x0D,0xE0,0xB1,0x13,0x7C,0x8B,0x79,0x1F,0x67,0xD8,0xBA,0xB4,0x58,0x9C,0x84,0x18, + 0xE4,0xED,0x22,0x17,0x41,0xA9,0x3B,0x88,0xD5,0x55,0x54,0x5F,0x33,0x4D,0xE2,0xBD, + 0xBE,0x66,0x46,0x59,0xC0,0x60,0xC5,0xB2,0x7A,0xF6,0xCA,0xCD,0xB9,0x2D,0xBD,0x50, + 0xB3,0xD6,0x18,0xD5,0x1F,0xFA,0x42,0x30,0x4C,0x10,0xFB,0x12,0xA9,0x9A,0x0E,0x39, + 0xFA,0x77,0xB6,0x82,0x53,0xF3,0x35,0x74,0xB5,0x10,0x5A,0x22,0xAE,0x17,0x25,0xD1, + 0x09,0xB9,0x71,0x08,0xA1,0xFA,0x2D,0xB9,0xEA,0x8C,0xC5,0xAC,0x31,0x6C,0x45,0x46, + 0x2E,0x11,0x2D,0x75,0x07,0x88,0x39,0xA3,0x14,0x08,0xA6,0xBF,0x7B,0x2C,0x26,0xAE, + 0x28,0xE9,0x1D,0x6C,0xFF,0xAC,0x99,0x53,0x44,0x91,0x26,0x2E,0x82,0x1A,0x11,0x66, + 0xB5,0x9C,0xEF,0x9E,0xC1,0x52,0x8F,0xCE,0x12,0xF3,0x88,0x86,0x06,0xF0,0xE8,0x62, + 0x69,0x12,0x04,0x6D,0x2B,0x75,0x83,0xE1,0x12,0xFC,0x3E,0xF1, +}; + + +static struct RootRecord kBaseLineEscrowRootRecord = {sizeof(kBaseLineEscrowRootGM), (UInt8*)kBaseLineEscrowRootGM}; +static struct RootRecord* kBaseLineEscrowRoots[] = {&kBaseLineEscrowRootRecord}; +static const int kNumberOfBaseLineEscrowRoots = (int)(sizeof(kBaseLineEscrowRoots)/sizeof(kBaseLineEscrowRoots[0])); + +static struct RootRecord kBaseLinePCSEscrowRootRecord = {sizeof(kBaseLinePCSEscrowRootGM), (UInt8*)kBaseLinePCSEscrowRootGM}; +static struct RootRecord* kBaseLinePCSEscrowRoots[] = {&kBaseLinePCSEscrowRootRecord}; +static const int kNumberOfBaseLinePCSEscrowRoots = (int)(sizeof(kBaseLinePCSEscrowRoots)/sizeof(kBaseLinePCSEscrowRoots[0])); + +#endif diff --git a/libsecurity_keychain/lib/CCallbackMgr.cp b/Security/libsecurity_keychain/lib/CCallbackMgr.cp similarity index 99% rename from libsecurity_keychain/lib/CCallbackMgr.cp rename to Security/libsecurity_keychain/lib/CCallbackMgr.cp index 6c9320bc..66741f9f 100644 --- a/libsecurity_keychain/lib/CCallbackMgr.cp +++ b/Security/libsecurity_keychain/lib/CCallbackMgr.cp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/CCallbackMgr.h b/Security/libsecurity_keychain/lib/CCallbackMgr.h similarity index 97% rename from libsecurity_keychain/lib/CCallbackMgr.h rename to Security/libsecurity_keychain/lib/CCallbackMgr.h index 5098a7e1..52ea8d11 100644 --- a/libsecurity_keychain/lib/CCallbackMgr.h +++ b/Security/libsecurity_keychain/lib/CCallbackMgr.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 1998-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/Certificate.cpp b/Security/libsecurity_keychain/lib/Certificate.cpp similarity index 99% rename from libsecurity_keychain/lib/Certificate.cpp rename to Security/libsecurity_keychain/lib/Certificate.cpp index 0dbc174b..76d6c1ce 100644 --- a/libsecurity_keychain/lib/Certificate.cpp +++ b/Security/libsecurity_keychain/lib/Certificate.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2007,2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2007,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/Certificate.h b/Security/libsecurity_keychain/lib/Certificate.h similarity index 98% rename from libsecurity_keychain/lib/Certificate.h rename to Security/libsecurity_keychain/lib/Certificate.h index ec34cd78..7c478976 100644 --- a/libsecurity_keychain/lib/Certificate.h +++ b/Security/libsecurity_keychain/lib/Certificate.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2007,2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2007,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/CertificateRequest.cpp b/Security/libsecurity_keychain/lib/CertificateRequest.cpp similarity index 99% rename from libsecurity_keychain/lib/CertificateRequest.cpp rename to Security/libsecurity_keychain/lib/CertificateRequest.cpp index 44b83400..76c1808c 100644 --- a/libsecurity_keychain/lib/CertificateRequest.cpp +++ b/Security/libsecurity_keychain/lib/CertificateRequest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/CertificateRequest.h b/Security/libsecurity_keychain/lib/CertificateRequest.h similarity index 98% rename from libsecurity_keychain/lib/CertificateRequest.h rename to Security/libsecurity_keychain/lib/CertificateRequest.h index 9f45b6dd..fcecb54c 100644 --- a/libsecurity_keychain/lib/CertificateRequest.h +++ b/Security/libsecurity_keychain/lib/CertificateRequest.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/CertificateValues.cpp b/Security/libsecurity_keychain/lib/CertificateValues.cpp similarity index 99% rename from libsecurity_keychain/lib/CertificateValues.cpp rename to Security/libsecurity_keychain/lib/CertificateValues.cpp index d7edbe4d..098ae505 100644 --- a/libsecurity_keychain/lib/CertificateValues.cpp +++ b/Security/libsecurity_keychain/lib/CertificateValues.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/CertificateValues.h b/Security/libsecurity_keychain/lib/CertificateValues.h similarity index 96% rename from libsecurity_keychain/lib/CertificateValues.h rename to Security/libsecurity_keychain/lib/CertificateValues.h index a080a385..5f56bbe9 100644 --- a/libsecurity_keychain/lib/CertificateValues.h +++ b/Security/libsecurity_keychain/lib/CertificateValues.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/DLDBListCFPref.cpp b/Security/libsecurity_keychain/lib/DLDBListCFPref.cpp similarity index 99% rename from libsecurity_keychain/lib/DLDBListCFPref.cpp rename to Security/libsecurity_keychain/lib/DLDBListCFPref.cpp index 20b08095..4836f4dc 100644 --- a/libsecurity_keychain/lib/DLDBListCFPref.cpp +++ b/Security/libsecurity_keychain/lib/DLDBListCFPref.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -1008,12 +1008,13 @@ DLDbListCFPref::defaultDLDbIdentifier() secdebug("secpref", "now we think the default keychain is: %s", (mDefaultDLDbIdentifier) ? mDefaultDLDbIdentifier.dbName() : "Name doesn't exist"); - - //"Name doesn't exist"); - struct stat st; - int st_result = stat(mDefaultDLDbIdentifier.dbName(), &st); + int st_result = -1; + if (mDefaultDLDbIdentifier.mImpl != NULL) + { + st_result = stat(mDefaultDLDbIdentifier.dbName(), &st); + } if (st_result) { diff --git a/libsecurity_keychain/lib/DLDBListCFPref.h b/Security/libsecurity_keychain/lib/DLDBListCFPref.h similarity index 99% rename from libsecurity_keychain/lib/DLDBListCFPref.h rename to Security/libsecurity_keychain/lib/DLDBListCFPref.h index c7eddc7b..966f75f0 100644 --- a/libsecurity_keychain/lib/DLDBListCFPref.h +++ b/Security/libsecurity_keychain/lib/DLDBListCFPref.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/DynamicDLDBList.cpp b/Security/libsecurity_keychain/lib/DynamicDLDBList.cpp similarity index 99% rename from libsecurity_keychain/lib/DynamicDLDBList.cpp rename to Security/libsecurity_keychain/lib/DynamicDLDBList.cpp index 5c6eb510..0539e474 100644 --- a/libsecurity_keychain/lib/DynamicDLDBList.cpp +++ b/Security/libsecurity_keychain/lib/DynamicDLDBList.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/DynamicDLDBList.h b/Security/libsecurity_keychain/lib/DynamicDLDBList.h similarity index 97% rename from libsecurity_keychain/lib/DynamicDLDBList.h rename to Security/libsecurity_keychain/lib/DynamicDLDBList.h index 12c75be3..8f3656df 100644 --- a/libsecurity_keychain/lib/DynamicDLDBList.h +++ b/Security/libsecurity_keychain/lib/DynamicDLDBList.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/ExtendedAttribute.cpp b/Security/libsecurity_keychain/lib/ExtendedAttribute.cpp similarity index 98% rename from libsecurity_keychain/lib/ExtendedAttribute.cpp rename to Security/libsecurity_keychain/lib/ExtendedAttribute.cpp index a667eb91..88b5a5d7 100644 --- a/libsecurity_keychain/lib/ExtendedAttribute.cpp +++ b/Security/libsecurity_keychain/lib/ExtendedAttribute.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -24,7 +24,6 @@ /* * ExtendedAttribute.cpp - Extended Keychain Item Attribute class. * - * Created 9/6/06 by dmitch. */ #include "ExtendedAttribute.h" diff --git a/libsecurity_keychain/lib/ExtendedAttribute.h b/Security/libsecurity_keychain/lib/ExtendedAttribute.h similarity index 96% rename from libsecurity_keychain/lib/ExtendedAttribute.h rename to Security/libsecurity_keychain/lib/ExtendedAttribute.h index d98626d4..ed2b1f75 100644 --- a/libsecurity_keychain/lib/ExtendedAttribute.h +++ b/Security/libsecurity_keychain/lib/ExtendedAttribute.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -24,7 +24,6 @@ /* * ExtendedAttribute.h - Extended Keychain Item Attribute class. * - * Created 9/6/06 by dmitch. */ #ifndef _SECURITY_EXTENDED_ATTRIBUTE_H_ diff --git a/libsecurity_keychain/lib/Globals.cpp b/Security/libsecurity_keychain/lib/Globals.cpp similarity index 96% rename from libsecurity_keychain/lib/Globals.cpp rename to Security/libsecurity_keychain/lib/Globals.cpp index f49a48c4..f8d1e70e 100644 --- a/libsecurity_keychain/lib/Globals.cpp +++ b/Security/libsecurity_keychain/lib/Globals.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/Globals.h b/Security/libsecurity_keychain/lib/Globals.h similarity index 96% rename from libsecurity_keychain/lib/Globals.h rename to Security/libsecurity_keychain/lib/Globals.h index 7c484adc..4b192b0d 100644 --- a/libsecurity_keychain/lib/Globals.h +++ b/Security/libsecurity_keychain/lib/Globals.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/Identity.cpp b/Security/libsecurity_keychain/lib/Identity.cpp similarity index 98% rename from libsecurity_keychain/lib/Identity.cpp rename to Security/libsecurity_keychain/lib/Identity.cpp index ea6b96ea..826ed985 100644 --- a/libsecurity_keychain/lib/Identity.cpp +++ b/Security/libsecurity_keychain/lib/Identity.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/Identity.h b/Security/libsecurity_keychain/lib/Identity.h similarity index 96% rename from libsecurity_keychain/lib/Identity.h rename to Security/libsecurity_keychain/lib/Identity.h index 5ea548bd..9a1d68c7 100644 --- a/libsecurity_keychain/lib/Identity.h +++ b/Security/libsecurity_keychain/lib/Identity.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/IdentityCursor.cpp b/Security/libsecurity_keychain/lib/IdentityCursor.cpp similarity index 99% rename from libsecurity_keychain/lib/IdentityCursor.cpp rename to Security/libsecurity_keychain/lib/IdentityCursor.cpp index d8a55b93..e7f24d82 100644 --- a/libsecurity_keychain/lib/IdentityCursor.cpp +++ b/Security/libsecurity_keychain/lib/IdentityCursor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2008,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/IdentityCursor.h b/Security/libsecurity_keychain/lib/IdentityCursor.h similarity index 97% rename from libsecurity_keychain/lib/IdentityCursor.h rename to Security/libsecurity_keychain/lib/IdentityCursor.h index b9a8de09..aa9d7f58 100644 --- a/libsecurity_keychain/lib/IdentityCursor.h +++ b/Security/libsecurity_keychain/lib/IdentityCursor.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2008,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/Item.cpp b/Security/libsecurity_keychain/lib/Item.cpp similarity index 99% rename from libsecurity_keychain/lib/Item.cpp rename to Security/libsecurity_keychain/lib/Item.cpp index eac4dcab..057f0618 100644 --- a/libsecurity_keychain/lib/Item.cpp +++ b/Security/libsecurity_keychain/lib/Item.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2000-2004,2012-2013 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/Item.h b/Security/libsecurity_keychain/lib/Item.h similarity index 98% rename from libsecurity_keychain/lib/Item.h rename to Security/libsecurity_keychain/lib/Item.h index 712b4f59..ff1e205a 100644 --- a/libsecurity_keychain/lib/Item.h +++ b/Security/libsecurity_keychain/lib/Item.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2000-2004,2012-2013 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/KCCursor.cpp b/Security/libsecurity_keychain/lib/KCCursor.cpp similarity index 99% rename from libsecurity_keychain/lib/KCCursor.cpp rename to Security/libsecurity_keychain/lib/KCCursor.cpp index 48bba91f..fc968cfc 100644 --- a/libsecurity_keychain/lib/KCCursor.cpp +++ b/Security/libsecurity_keychain/lib/KCCursor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/KCCursor.h b/Security/libsecurity_keychain/lib/KCCursor.h similarity index 97% rename from libsecurity_keychain/lib/KCCursor.h rename to Security/libsecurity_keychain/lib/KCCursor.h index 67ab482c..a05db8e7 100644 --- a/libsecurity_keychain/lib/KCCursor.h +++ b/Security/libsecurity_keychain/lib/KCCursor.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/KCEventNotifier.cpp b/Security/libsecurity_keychain/lib/KCEventNotifier.cpp similarity index 97% rename from libsecurity_keychain/lib/KCEventNotifier.cpp rename to Security/libsecurity_keychain/lib/KCEventNotifier.cpp index f33a0a56..fd78da60 100644 --- a/libsecurity_keychain/lib/KCEventNotifier.cpp +++ b/Security/libsecurity_keychain/lib/KCEventNotifier.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/KCEventNotifier.h b/Security/libsecurity_keychain/lib/KCEventNotifier.h similarity index 96% rename from libsecurity_keychain/lib/KCEventNotifier.h rename to Security/libsecurity_keychain/lib/KCEventNotifier.h index 23b7ee86..30d8713b 100644 --- a/libsecurity_keychain/lib/KCEventNotifier.h +++ b/Security/libsecurity_keychain/lib/KCEventNotifier.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/KCExceptions.h b/Security/libsecurity_keychain/lib/KCExceptions.h similarity index 96% rename from libsecurity_keychain/lib/KCExceptions.h rename to Security/libsecurity_keychain/lib/KCExceptions.h index de97a67f..4f1fb819 100644 --- a/libsecurity_keychain/lib/KCExceptions.h +++ b/Security/libsecurity_keychain/lib/KCExceptions.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/KCUtilities.cpp b/Security/libsecurity_keychain/lib/KCUtilities.cpp similarity index 94% rename from libsecurity_keychain/lib/KCUtilities.cpp rename to Security/libsecurity_keychain/lib/KCUtilities.cpp index d90869b1..f9e0f57e 100644 --- a/libsecurity_keychain/lib/KCUtilities.cpp +++ b/Security/libsecurity_keychain/lib/KCUtilities.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/KCUtilities.h b/Security/libsecurity_keychain/lib/KCUtilities.h similarity index 94% rename from libsecurity_keychain/lib/KCUtilities.h rename to Security/libsecurity_keychain/lib/KCUtilities.h index 6bfaf438..b0174e5b 100644 --- a/libsecurity_keychain/lib/KCUtilities.h +++ b/Security/libsecurity_keychain/lib/KCUtilities.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/KeyItem.cpp b/Security/libsecurity_keychain/lib/KeyItem.cpp similarity index 99% rename from libsecurity_keychain/lib/KeyItem.cpp rename to Security/libsecurity_keychain/lib/KeyItem.cpp index 84db4ef9..b1c4d17c 100644 --- a/libsecurity_keychain/lib/KeyItem.cpp +++ b/Security/libsecurity_keychain/lib/KeyItem.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -40,9 +40,12 @@ #include // @@@ This needs to be shared. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-const-variable" static CSSM_DB_NAME_ATTR(kInfoKeyPrintName, kSecKeyPrintName, (char*) "PrintName", 0, NULL, BLOB); static CSSM_DB_NAME_ATTR(kInfoKeyLabel, kSecKeyLabel, (char*) "Label", 0, NULL, BLOB); static CSSM_DB_NAME_ATTR(kInfoKeyApplicationTag, kSecKeyApplicationTag, (char*) "ApplicationTag", 0, NULL, BLOB); +#pragma clang diagnostic pop using namespace KeychainCore; using namespace CssmClient; diff --git a/libsecurity_keychain/lib/KeyItem.h b/Security/libsecurity_keychain/lib/KeyItem.h similarity index 98% rename from libsecurity_keychain/lib/KeyItem.h rename to Security/libsecurity_keychain/lib/KeyItem.h index ae50ec80..9ac071d1 100644 --- a/libsecurity_keychain/lib/KeyItem.h +++ b/Security/libsecurity_keychain/lib/KeyItem.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2011,2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/Keychains.cpp b/Security/libsecurity_keychain/lib/Keychains.cpp similarity index 99% rename from libsecurity_keychain/lib/Keychains.cpp rename to Security/libsecurity_keychain/lib/Keychains.cpp index b83383e2..1d94dee2 100644 --- a/libsecurity_keychain/lib/Keychains.cpp +++ b/Security/libsecurity_keychain/lib/Keychains.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -782,7 +782,9 @@ void KeychainImpl::completeAdd(Item &inItem, PrimaryKey &primaryKey) assert(oldItem->inCache()); secdebug("keychain", "add of new item %p somehow replaced %p", inItem.get(), oldItem); - oldItem->inCache(false); + + // make sure that we both mark the item and remove the item from the cache + removeItem(oldItem->primaryKey(), oldItem); oldItem = inItem.get(); } diff --git a/libsecurity_keychain/lib/Keychains.h b/Security/libsecurity_keychain/lib/Keychains.h similarity index 99% rename from libsecurity_keychain/lib/Keychains.h rename to Security/libsecurity_keychain/lib/Keychains.h index f6b64f8f..df870843 100644 --- a/libsecurity_keychain/lib/Keychains.h +++ b/Security/libsecurity_keychain/lib/Keychains.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/MacOSErrorStrings.h b/Security/libsecurity_keychain/lib/MacOSErrorStrings.h similarity index 98% rename from libsecurity_keychain/lib/MacOSErrorStrings.h rename to Security/libsecurity_keychain/lib/MacOSErrorStrings.h index 28b648bc..bac2d85f 100644 --- a/libsecurity_keychain/lib/MacOSErrorStrings.h +++ b/Security/libsecurity_keychain/lib/MacOSErrorStrings.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/Password.cpp b/Security/libsecurity_keychain/lib/Password.cpp similarity index 98% rename from libsecurity_keychain/lib/Password.cpp rename to Security/libsecurity_keychain/lib/Password.cpp index 345fc849..68cdcce2 100644 --- a/libsecurity_keychain/lib/Password.cpp +++ b/Security/libsecurity_keychain/lib/Password.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/Password.h b/Security/libsecurity_keychain/lib/Password.h similarity index 97% rename from libsecurity_keychain/lib/Password.h rename to Security/libsecurity_keychain/lib/Password.h index 90e2e33e..f142a9a4 100644 --- a/libsecurity_keychain/lib/Password.h +++ b/Security/libsecurity_keychain/lib/Password.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/Policies.cpp b/Security/libsecurity_keychain/lib/Policies.cpp similarity index 99% rename from libsecurity_keychain/lib/Policies.cpp rename to Security/libsecurity_keychain/lib/Policies.cpp index b86f9735..769a78bf 100644 --- a/libsecurity_keychain/lib/Policies.cpp +++ b/Security/libsecurity_keychain/lib/Policies.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2004,2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/Policies.h b/Security/libsecurity_keychain/lib/Policies.h similarity index 96% rename from libsecurity_keychain/lib/Policies.h rename to Security/libsecurity_keychain/lib/Policies.h index 69e0687a..f4331b4d 100644 --- a/libsecurity_keychain/lib/Policies.h +++ b/Security/libsecurity_keychain/lib/Policies.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2004,2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/PolicyCursor.cpp b/Security/libsecurity_keychain/lib/PolicyCursor.cpp similarity index 97% rename from libsecurity_keychain/lib/PolicyCursor.cpp rename to Security/libsecurity_keychain/lib/PolicyCursor.cpp index 242d65f2..aa12338f 100644 --- a/libsecurity_keychain/lib/PolicyCursor.cpp +++ b/Security/libsecurity_keychain/lib/PolicyCursor.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2004,2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/PolicyCursor.h b/Security/libsecurity_keychain/lib/PolicyCursor.h similarity index 96% rename from libsecurity_keychain/lib/PolicyCursor.h rename to Security/libsecurity_keychain/lib/PolicyCursor.h index 84fbf73a..b8c1b40f 100644 --- a/libsecurity_keychain/lib/PolicyCursor.h +++ b/Security/libsecurity_keychain/lib/PolicyCursor.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2004,2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/PrimaryKey.cpp b/Security/libsecurity_keychain/lib/PrimaryKey.cpp similarity index 97% rename from libsecurity_keychain/lib/PrimaryKey.cpp rename to Security/libsecurity_keychain/lib/PrimaryKey.cpp index dfd407a6..b0170141 100644 --- a/libsecurity_keychain/lib/PrimaryKey.cpp +++ b/Security/libsecurity_keychain/lib/PrimaryKey.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/PrimaryKey.h b/Security/libsecurity_keychain/lib/PrimaryKey.h similarity index 96% rename from libsecurity_keychain/lib/PrimaryKey.h rename to Security/libsecurity_keychain/lib/PrimaryKey.h index cde32749..b8845028 100644 --- a/libsecurity_keychain/lib/PrimaryKey.h +++ b/Security/libsecurity_keychain/lib/PrimaryKey.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecACL.cpp b/Security/libsecurity_keychain/lib/SecACL.cpp similarity index 99% rename from libsecurity_keychain/lib/SecACL.cpp rename to Security/libsecurity_keychain/lib/SecACL.cpp index d0a98f8f..335c6cf9 100644 --- a/libsecurity_keychain/lib/SecACL.cpp +++ b/Security/libsecurity_keychain/lib/SecACL.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecACL.h b/Security/libsecurity_keychain/lib/SecACL.h similarity index 99% rename from libsecurity_keychain/lib/SecACL.h rename to Security/libsecurity_keychain/lib/SecACL.h index 6138adde..8121e1e9 100644 --- a/libsecurity_keychain/lib/SecACL.h +++ b/Security/libsecurity_keychain/lib/SecACL.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2010 Apple, Inc. All Rights Reserved. + * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecAccess.cpp b/Security/libsecurity_keychain/lib/SecAccess.cpp similarity index 99% rename from libsecurity_keychain/lib/SecAccess.cpp rename to Security/libsecurity_keychain/lib/SecAccess.cpp index fdc92ba5..239f4f57 100644 --- a/libsecurity_keychain/lib/SecAccess.cpp +++ b/Security/libsecurity_keychain/lib/SecAccess.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2004,2013 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/SecAccess.h b/Security/libsecurity_keychain/lib/SecAccess.h similarity index 99% rename from libsecurity_keychain/lib/SecAccess.h rename to Security/libsecurity_keychain/lib/SecAccess.h index fbbc95d4..411caf7d 100644 --- a/libsecurity_keychain/lib/SecAccess.h +++ b/Security/libsecurity_keychain/lib/SecAccess.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecAccessPriv.h b/Security/libsecurity_keychain/lib/SecAccessPriv.h similarity index 98% rename from libsecurity_keychain/lib/SecAccessPriv.h rename to Security/libsecurity_keychain/lib/SecAccessPriv.h index e96eaefc..6b1e5ce2 100644 --- a/libsecurity_keychain/lib/SecAccessPriv.h +++ b/Security/libsecurity_keychain/lib/SecAccessPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecAsn1TypesP.h b/Security/libsecurity_keychain/lib/SecAsn1TypesP.h similarity index 100% rename from libsecurity_keychain/lib/SecAsn1TypesP.h rename to Security/libsecurity_keychain/lib/SecAsn1TypesP.h diff --git a/libsecurity_keychain/lib/SecBase.cpp b/Security/libsecurity_keychain/lib/SecBase.cpp similarity index 99% rename from libsecurity_keychain/lib/SecBase.cpp rename to Security/libsecurity_keychain/lib/SecBase.cpp index 42af692d..cb7d0152 100644 --- a/libsecurity_keychain/lib/SecBase.cpp +++ b/Security/libsecurity_keychain/lib/SecBase.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_keychain/lib/SecBase.h b/Security/libsecurity_keychain/lib/SecBase.h new file mode 100644 index 00000000..0dbcbaba --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecBase.h @@ -0,0 +1,648 @@ +/* + * Copyright (c) 2000-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecBase + SecBase contains common declarations for the Security functions. +*/ + +#ifndef _SECURITY_SECBASE_H_ +#define _SECURITY_SECBASE_H_ + +#include +#include + +#if defined(__clang__) +#define SEC_DEPRECATED_ATTRIBUTE DEPRECATED_ATTRIBUTE +#else +#define SEC_DEPRECATED_ATTRIBUTE +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef __SEC_TYPES__ +#define __SEC_TYPES__ + +/*! + @typedef SecKeychainRef + @abstract Contains information about a keychain. +*/ +typedef struct OpaqueSecKeychainRef *SecKeychainRef; + +/*! + @typedef SecKeychainItemRef + @abstract Contains information about a keychain item. +*/ +typedef struct OpaqueSecKeychainItemRef *SecKeychainItemRef; + +/*! + @typedef SecKeychainSearchRef + @abstract Contains information about a keychain search. +*/ +typedef struct OpaqueSecKeychainSearchRef *SecKeychainSearchRef; + +/*! + @typedef SecKeychainAttrType + @abstract Represents a keychain attribute type. +*/ +typedef OSType SecKeychainAttrType; + +/*! + @struct SecKeychainAttribute + @abstract Contains keychain attributes. + @field tag A 4-byte attribute tag. + @field length The length of the buffer pointed to by data. + @field data A pointer to the attribute data. +*/ +struct SecKeychainAttribute +{ + SecKeychainAttrType tag; + UInt32 length; + void *data; +}; +typedef struct SecKeychainAttribute SecKeychainAttribute; + +/*! + @typedef SecKeychainAttributePtr + @abstract Represents a pointer to a keychain attribute structure. +*/ +typedef SecKeychainAttribute *SecKeychainAttributePtr; + +/*! + @typedef SecKeychainAttributeList + @abstract Represents a list of keychain attributes. + @field count An unsigned 32-bit integer that represents the number of keychain attributes in the array. + @field attr A pointer to the first keychain attribute in the array. +*/ +struct SecKeychainAttributeList +{ + UInt32 count; + SecKeychainAttribute *attr; +}; +typedef struct SecKeychainAttributeList SecKeychainAttributeList; + +/*! + @typedef SecKeychainStatus + @abstract Represents the status of a keychain. +*/ +typedef UInt32 SecKeychainStatus; +#endif + +/*! + @typedef SecTrustedApplicationRef + @abstract Contains information about a trusted application. +*/ +typedef struct OpaqueSecTrustedApplicationRef *SecTrustedApplicationRef; + +/*! + @typedef SecPolicyRef + @abstract Contains information about a policy. +*/ +typedef struct OpaqueSecPolicyRef *SecPolicyRef; + +/*! + @typedef SecCertificateRef + @abstract Contains information about a certificate. +*/ +typedef struct OpaqueSecCertificateRef *SecCertificateRef; + +/*! + @typedef SecAccessRef + @abstract Contains information about an access. +*/ +typedef struct OpaqueSecAccessRef *SecAccessRef; + +/*! + @typedef SecIdentityRef + @abstract Contains information about an identity. +*/ +typedef struct OpaqueSecIdentityRef *SecIdentityRef; + +/*! + @typedef SecKeyRef + @abstract Contains information about a key. +*/ +typedef struct OpaqueSecKeyRef *SecKeyRef; + +/*! + @typedef SecACLRef + @abstract Contains information about an access control list (ACL) entry. +*/ +typedef struct OpaqueSecTrustRef *SecACLRef; + +/*! + @typedef SecAccessControlRef + @abstract CFType representing access control for an item. +*/ +typedef struct OpaqueSecAccessControl *SecAccessControlRef; + +/*! + @typedef SecPasswordRef + @abstract Contains information about a password. +*/ +typedef struct OpaqueSecPasswordRef *SecPasswordRef; + +/*! + @typedef SecKeychainAttributeInfo + @abstract Represents an attribute. + @field count The number of tag-format pairs in the respective arrays. + @field tag A pointer to the first attribute tag in the array. + @field format A pointer to the first CSSM_DB_ATTRIBUTE_FORMAT in the array. + @discussion Each tag and format item form a pair. +*/ +struct SecKeychainAttributeInfo +{ + UInt32 count; + UInt32 *tag; + UInt32 *format; +}; +typedef struct SecKeychainAttributeInfo SecKeychainAttributeInfo; + +/*! + @function SecCopyErrorMessageString + @abstract Returns a string describing the specified error result code. + @param status An error result code of type OSStatus or CSSM_RETURN, as returned by a Security or CSSM function. + @reserved Reserved for future use. Your code should pass NULL in this parameter. + @result A reference to an error string, or NULL if no error string is available for the specified result code. Your code must release this reference by calling the CFRelease function. +*/ +CFStringRef SecCopyErrorMessageString(OSStatus status, void *reserved) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); +/*! +@enum Security Error Codes +@abstract Result codes returned from Security framework functions. +@constant errSecSuccess No error. +@constant errSecUnimplemented Function or operation not implemented. +@constant errSecDskFull Disk Full error. +@constant errSecIO I/O error. +@constant errSecParam One or more parameters passed to a function were not valid. +@constant errSecWrPerm Write permissions error. +@constant errSecAllocate Failed to allocate memory. +@constant errSecUserCanceled User canceled the operation. +@constant errSecBadReq Bad parameter or invalid state for operation. +@constant errSecInternalComponent +@constant errSecCoreFoundationUnknown +@constant errSecNotAvailable No keychain is available. +@constant errSecReadOnly Read only error. +@constant errSecAuthFailed Authorization/Authentication failed. +@constant errSecNoSuchKeychain The keychain does not exist. +@constant errSecInvalidKeychain The keychain is not valid. +@constant errSecDuplicateKeychain A keychain with the same name already exists. +@constant errSecDuplicateCallback The specified callback is already installed. +@constant errSecInvalidCallback The specified callback is not valid. +@constant errSecDuplicateItem The item already exists. +@constant errSecItemNotFound The item cannot be found. +@constant errSecBufferTooSmall The buffer is too small. +@constant errSecDataTooLarge The data is too large. +@constant errSecNoSuchAttr The attribute does not exist. +@constant errSecInvalidItemRef The item reference is invalid. +@constant errSecInvalidSearchRef The search reference is invalid. +@constant errSecNoSuchClass The keychain item class does not exist. +@constant errSecNoDefaultKeychain A default keychain does not exist. +@constant errSecInteractionNotAllowed User interaction is not allowed. +@constant errSecReadOnlyAttr The attribute is read only. +@constant errSecWrongSecVersion The version is incorrect. +@constant errSecKeySizeNotAllowed The key size is not allowed. +@constant errSecNoStorageModule There is no storage module available. +@constant errSecNoCertificateModule There is no certificate module available. +@constant errSecNoPolicyModule There is no policy module available. +@constant errSecInteractionRequired User interaction is required. +@constant errSecDataNotAvailable The data is not available. +@constant errSecDataNotModifiable The data is not modifiable. +@constant errSecCreateChainFailed The attempt to create a certificate chain failed. +@constant errSecACLNotSimple The access control list is not in standard simple form. +@constant errSecPolicyNotFound The policy specified cannot be found. +@constant errSecInvalidTrustSetting The specified trust setting is invalid. +@constant errSecNoAccessForItem The specified item has no access control. +@constant errSecInvalidOwnerEdit Invalid attempt to change the owner of this item. +@constant errSecTrustNotAvailable No trust results are available. +@constant errSecUnsupportedFormat Import/Export format unsupported. +@constant errSecUnknownFormat Unknown format in import. +@constant errSecKeyIsSensitive Key material must be wrapped for export. +@constant errSecMultiplePrivKeys An attempt was made to import multiple private keys. +@constant errSecPassphraseRequired Passphrase is required for import/export. +@constant errSecInvalidPasswordRef The password reference was invalid. +@constant errSecInvalidTrustSettings The Trust Settings Record was corrupted. +@constant errSecNoTrustSettings No Trust Settings were found. +@constant errSecPkcs12VerifyFailure MAC verification failed during PKCS12 Import. +@constant errSecDecode Unable to decode the provided data. + +@discussion The assigned error space is discontinuous: e.g. -25240..-25279, -25290..-25329, -68608..-67585, and so on. +*/ + +/* + Note: the comments that appear after these errors are used to create SecErrorMessages.strings. + The comments must not be multi-line, and should be in a form meaningful to an end user. If + a different or additional comment is needed, it can be put in the header doc format, or on a + line that does not start with errZZZ. +*/ + +enum +{ + errSecSuccess = 0, /* No error. */ + errSecUnimplemented = -4, /* Function or operation not implemented. */ + errSecDskFull = -34, + errSecIO = -36, /*I/O error (bummers)*/ + + errSecParam = -50, /* One or more parameters passed to a function were not valid. */ + errSecWrPerm = -61, /* write permissions error*/ + errSecAllocate = -108, /* Failed to allocate memory. */ + errSecUserCanceled = -128, /* User canceled the operation. */ + errSecBadReq = -909, /* Bad parameter or invalid state for operation. */ + + errSecInternalComponent = -2070, + errSecCoreFoundationUnknown = -4960, + + errSecNotAvailable = -25291, /* No keychain is available. You may need to restart your computer. */ + errSecReadOnly = -25292, /* This keychain cannot be modified. */ + errSecAuthFailed = -25293, /* The user name or passphrase you entered is not correct. */ + errSecNoSuchKeychain = -25294, /* The specified keychain could not be found. */ + errSecInvalidKeychain = -25295, /* The specified keychain is not a valid keychain file. */ + errSecDuplicateKeychain = -25296, /* A keychain with the same name already exists. */ + errSecDuplicateCallback = -25297, /* The specified callback function is already installed. */ + errSecInvalidCallback = -25298, /* The specified callback function is not valid. */ + errSecDuplicateItem = -25299, /* The specified item already exists in the keychain. */ + errSecItemNotFound = -25300, /* The specified item could not be found in the keychain. */ + errSecBufferTooSmall = -25301, /* There is not enough memory available to use the specified item. */ + errSecDataTooLarge = -25302, /* This item contains information which is too large or in a format that cannot be displayed. */ + errSecNoSuchAttr = -25303, /* The specified attribute does not exist. */ + errSecInvalidItemRef = -25304, /* The specified item is no longer valid. It may have been deleted from the keychain. */ + errSecInvalidSearchRef = -25305, /* Unable to search the current keychain. */ + errSecNoSuchClass = -25306, /* The specified item does not appear to be a valid keychain item. */ + errSecNoDefaultKeychain = -25307, /* A default keychain could not be found. */ + errSecInteractionNotAllowed = -25308, /* User interaction is not allowed. */ + errSecReadOnlyAttr = -25309, /* The specified attribute could not be modified. */ + errSecWrongSecVersion = -25310, /* This keychain was created by a different version of the system software and cannot be opened. */ + errSecKeySizeNotAllowed = -25311, /* This item specifies a key size which is too large. */ + errSecNoStorageModule = -25312, /* A required component (data storage module) could not be loaded. You may need to restart your computer. */ + errSecNoCertificateModule = -25313, /* A required component (certificate module) could not be loaded. You may need to restart your computer. */ + errSecNoPolicyModule = -25314, /* A required component (policy module) could not be loaded. You may need to restart your computer. */ + errSecInteractionRequired = -25315, /* User interaction is required, but is currently not allowed. */ + errSecDataNotAvailable = -25316, /* The contents of this item cannot be retrieved. */ + errSecDataNotModifiable = -25317, /* The contents of this item cannot be modified. */ + errSecCreateChainFailed = -25318, /* One or more certificates required to validate this certificate cannot be found. */ + errSecInvalidPrefsDomain = -25319, /* The specified preferences domain is not valid. */ + errSecInDarkWake = -25320, /* In dark wake, no UI possible */ + + errSecACLNotSimple = -25240, /* The specified access control list is not in standard (simple) form. */ + errSecPolicyNotFound = -25241, /* The specified policy cannot be found. */ + errSecInvalidTrustSetting = -25242, /* The specified trust setting is invalid. */ + errSecNoAccessForItem = -25243, /* The specified item has no access control. */ + errSecInvalidOwnerEdit = -25244, /* Invalid attempt to change the owner of this item. */ + errSecTrustNotAvailable = -25245, /* No trust results are available. */ + errSecUnsupportedFormat = -25256, /* Import/Export format unsupported. */ + errSecUnknownFormat = -25257, /* Unknown format in import. */ + errSecKeyIsSensitive = -25258, /* Key material must be wrapped for export. */ + errSecMultiplePrivKeys = -25259, /* An attempt was made to import multiple private keys. */ + errSecPassphraseRequired = -25260, /* Passphrase is required for import/export. */ + errSecInvalidPasswordRef = -25261, /* The password reference was invalid. */ + errSecInvalidTrustSettings = -25262, /* The Trust Settings Record was corrupted. */ + errSecNoTrustSettings = -25263, /* No Trust Settings were found. */ + errSecPkcs12VerifyFailure = -25264, /* MAC verification failed during PKCS12 import (wrong password?) */ + errSecNotSigner = -26267, /* A certificate was not signed by its proposed parent. */ + + errSecDecode = -26275, /* Unable to decode the provided data. */ + + errSecServiceNotAvailable = -67585, /* The required service is not available. */ + errSecInsufficientClientID = -67586, /* The client ID is not correct. */ + errSecDeviceReset = -67587, /* A device reset has occurred. */ + errSecDeviceFailed = -67588, /* A device failure has occurred. */ + errSecAppleAddAppACLSubject = -67589, /* Adding an application ACL subject failed. */ + errSecApplePublicKeyIncomplete = -67590, /* The public key is incomplete. */ + errSecAppleSignatureMismatch = -67591, /* A signature mismatch has occurred. */ + errSecAppleInvalidKeyStartDate = -67592, /* The specified key has an invalid start date. */ + errSecAppleInvalidKeyEndDate = -67593, /* The specified key has an invalid end date. */ + errSecConversionError = -67594, /* A conversion error has occurred. */ + errSecAppleSSLv2Rollback = -67595, /* A SSLv2 rollback error has occurred. */ + errSecDiskFull = -34, /* The disk is full. */ + errSecQuotaExceeded = -67596, /* The quota was exceeded. */ + errSecFileTooBig = -67597, /* The file is too big. */ + errSecInvalidDatabaseBlob = -67598, /* The specified database has an invalid blob. */ + errSecInvalidKeyBlob = -67599, /* The specified database has an invalid key blob. */ + errSecIncompatibleDatabaseBlob = -67600, /* The specified database has an incompatible blob. */ + errSecIncompatibleKeyBlob = -67601, /* The specified database has an incompatible key blob. */ + errSecHostNameMismatch = -67602, /* A host name mismatch has occurred. */ + errSecUnknownCriticalExtensionFlag = -67603, /* There is an unknown critical extension flag. */ + errSecNoBasicConstraints = -67604, /* No basic constraints were found. */ + errSecNoBasicConstraintsCA = -67605, /* No basic CA constraints were found. */ + errSecInvalidAuthorityKeyID = -67606, /* The authority key ID is not valid. */ + errSecInvalidSubjectKeyID = -67607, /* The subject key ID is not valid. */ + errSecInvalidKeyUsageForPolicy = -67608, /* The key usage is not valid for the specified policy. */ + errSecInvalidExtendedKeyUsage = -67609, /* The extended key usage is not valid. */ + errSecInvalidIDLinkage = -67610, /* The ID linkage is not valid. */ + errSecPathLengthConstraintExceeded = -67611, /* The path length constraint was exceeded. */ + errSecInvalidRoot = -67612, /* The root or anchor certificate is not valid. */ + errSecCRLExpired = -67613, /* The CRL has expired. */ + errSecCRLNotValidYet = -67614, /* The CRL is not yet valid. */ + errSecCRLNotFound = -67615, /* The CRL was not found. */ + errSecCRLServerDown = -67616, /* The CRL server is down. */ + errSecCRLBadURI = -67617, /* The CRL has a bad Uniform Resource Identifier. */ + errSecUnknownCertExtension = -67618, /* An unknown certificate extension was encountered. */ + errSecUnknownCRLExtension = -67619, /* An unknown CRL extension was encountered. */ + errSecCRLNotTrusted = -67620, /* The CRL is not trusted. */ + errSecCRLPolicyFailed = -67621, /* The CRL policy failed. */ + errSecIDPFailure = -67622, /* The issuing distribution point was not valid. */ + errSecSMIMEEmailAddressesNotFound = -67623, /* An email address mismatch was encountered. */ + errSecSMIMEBadExtendedKeyUsage = -67624, /* The appropriate extended key usage for SMIME was not found. */ + errSecSMIMEBadKeyUsage = -67625, /* The key usage is not compatible with SMIME. */ + errSecSMIMEKeyUsageNotCritical = -67626, /* The key usage extension is not marked as critical. */ + errSecSMIMENoEmailAddress = -67627, /* No email address was found in the certificate. */ + errSecSMIMESubjAltNameNotCritical = -67628, /* The subject alternative name extension is not marked as critical. */ + errSecSSLBadExtendedKeyUsage = -67629, /* The appropriate extended key usage for SSL was not found. */ + errSecOCSPBadResponse = -67630, /* The OCSP response was incorrect or could not be parsed. */ + errSecOCSPBadRequest = -67631, /* The OCSP request was incorrect or could not be parsed. */ + errSecOCSPUnavailable = -67632, /* OCSP service is unavailable. */ + errSecOCSPStatusUnrecognized = -67633, /* The OCSP server did not recognize this certificate. */ + errSecEndOfData = -67634, /* An end-of-data was detected. */ + errSecIncompleteCertRevocationCheck = -67635, /* An incomplete certificate revocation check occurred. */ + errSecNetworkFailure = -67636, /* A network failure occurred. */ + errSecOCSPNotTrustedToAnchor = -67637, /* The OCSP response was not trusted to a root or anchor certificate. */ + errSecRecordModified = -67638, /* The record was modified. */ + errSecOCSPSignatureError = -67639, /* The OCSP response had an invalid signature. */ + errSecOCSPNoSigner = -67640, /* The OCSP response had no signer. */ + errSecOCSPResponderMalformedReq = -67641, /* The OCSP responder was given a malformed request. */ + errSecOCSPResponderInternalError = -67642, /* The OCSP responder encountered an internal error. */ + errSecOCSPResponderTryLater = -67643, /* The OCSP responder is busy, try again later. */ + errSecOCSPResponderSignatureRequired = -67644, /* The OCSP responder requires a signature. */ + errSecOCSPResponderUnauthorized = -67645, /* The OCSP responder rejected this request as unauthorized. */ + errSecOCSPResponseNonceMismatch = -67646, /* The OCSP response nonce did not match the request. */ + errSecCodeSigningBadCertChainLength = -67647, /* Code signing encountered an incorrect certificate chain length. */ + errSecCodeSigningNoBasicConstraints = -67648, /* Code signing found no basic constraints. */ + errSecCodeSigningBadPathLengthConstraint= -67649, /* Code signing encountered an incorrect path length constraint. */ + errSecCodeSigningNoExtendedKeyUsage = -67650, /* Code signing found no extended key usage. */ + errSecCodeSigningDevelopment = -67651, /* Code signing indicated use of a development-only certificate. */ + errSecResourceSignBadCertChainLength = -67652, /* Resource signing has encountered an incorrect certificate chain length. */ + errSecResourceSignBadExtKeyUsage = -67653, /* Resource signing has encountered an error in the extended key usage. */ + errSecTrustSettingDeny = -67654, /* The trust setting for this policy was set to Deny. */ + errSecInvalidSubjectName = -67655, /* An invalid certificate subject name was encountered. */ + errSecUnknownQualifiedCertStatement = -67656, /* An unknown qualified certificate statement was encountered. */ + errSecMobileMeRequestQueued = -67657, /* The MobileMe request will be sent during the next connection. */ + errSecMobileMeRequestRedirected = -67658, /* The MobileMe request was redirected. */ + errSecMobileMeServerError = -67659, /* A MobileMe server error occurred. */ + errSecMobileMeServerNotAvailable = -67660, /* The MobileMe server is not available. */ + errSecMobileMeServerAlreadyExists = -67661, /* The MobileMe server reported that the item already exists. */ + errSecMobileMeServerServiceErr = -67662, /* A MobileMe service error has occurred. */ + errSecMobileMeRequestAlreadyPending = -67663, /* A MobileMe request is already pending. */ + errSecMobileMeNoRequestPending = -67664, /* MobileMe has no request pending. */ + errSecMobileMeCSRVerifyFailure = -67665, /* A MobileMe CSR verification failure has occurred. */ + errSecMobileMeFailedConsistencyCheck = -67666, /* MobileMe has found a failed consistency check. */ + errSecNotInitialized = -67667, /* A function was called without initializing CSSM. */ + errSecInvalidHandleUsage = -67668, /* The CSSM handle does not match with the service type. */ + errSecPVCReferentNotFound = -67669, /* A reference to the calling module was not found in the list of authorized callers. */ + errSecFunctionIntegrityFail = -67670, /* A function address was not within the verified module. */ + errSecInternalError = -67671, /* An internal error has occurred. */ + errSecMemoryError = -67672, /* A memory error has occurred. */ + errSecInvalidData = -67673, /* Invalid data was encountered. */ + errSecMDSError = -67674, /* A Module Directory Service error has occurred. */ + errSecInvalidPointer = -67675, /* An invalid pointer was encountered. */ + errSecSelfCheckFailed = -67676, /* Self-check has failed. */ + errSecFunctionFailed = -67677, /* A function has failed. */ + errSecModuleManifestVerifyFailed = -67678, /* A module manifest verification failure has occurred. */ + errSecInvalidGUID = -67679, /* An invalid GUID was encountered. */ + errSecInvalidHandle = -67680, /* An invalid handle was encountered. */ + errSecInvalidDBList = -67681, /* An invalid DB list was encountered. */ + errSecInvalidPassthroughID = -67682, /* An invalid passthrough ID was encountered. */ + errSecInvalidNetworkAddress = -67683, /* An invalid network address was encountered. */ + errSecCRLAlreadySigned = -67684, /* The certificate revocation list is already signed. */ + errSecInvalidNumberOfFields = -67685, /* An invalid number of fields were encountered. */ + errSecVerificationFailure = -67686, /* A verification failure occurred. */ + errSecUnknownTag = -67687, /* An unknown tag was encountered. */ + errSecInvalidSignature = -67688, /* An invalid signature was encountered. */ + errSecInvalidName = -67689, /* An invalid name was encountered. */ + errSecInvalidCertificateRef = -67690, /* An invalid certificate reference was encountered. */ + errSecInvalidCertificateGroup = -67691, /* An invalid certificate group was encountered. */ + errSecTagNotFound = -67692, /* The specified tag was not found. */ + errSecInvalidQuery = -67693, /* The specified query was not valid. */ + errSecInvalidValue = -67694, /* An invalid value was detected. */ + errSecCallbackFailed = -67695, /* A callback has failed. */ + errSecACLDeleteFailed = -67696, /* An ACL delete operation has failed. */ + errSecACLReplaceFailed = -67697, /* An ACL replace operation has failed. */ + errSecACLAddFailed = -67698, /* An ACL add operation has failed. */ + errSecACLChangeFailed = -67699, /* An ACL change operation has failed. */ + errSecInvalidAccessCredentials = -67700, /* Invalid access credentials were encountered. */ + errSecInvalidRecord = -67701, /* An invalid record was encountered. */ + errSecInvalidACL = -67702, /* An invalid ACL was encountered. */ + errSecInvalidSampleValue = -67703, /* An invalid sample value was encountered. */ + errSecIncompatibleVersion = -67704, /* An incompatible version was encountered. */ + errSecPrivilegeNotGranted = -67705, /* The privilege was not granted. */ + errSecInvalidScope = -67706, /* An invalid scope was encountered. */ + errSecPVCAlreadyConfigured = -67707, /* The PVC is already configured. */ + errSecInvalidPVC = -67708, /* An invalid PVC was encountered. */ + errSecEMMLoadFailed = -67709, /* The EMM load has failed. */ + errSecEMMUnloadFailed = -67710, /* The EMM unload has failed. */ + errSecAddinLoadFailed = -67711, /* The add-in load operation has failed. */ + errSecInvalidKeyRef = -67712, /* An invalid key was encountered. */ + errSecInvalidKeyHierarchy = -67713, /* An invalid key hierarchy was encountered. */ + errSecAddinUnloadFailed = -67714, /* The add-in unload operation has failed. */ + errSecLibraryReferenceNotFound = -67715, /* A library reference was not found. */ + errSecInvalidAddinFunctionTable = -67716, /* An invalid add-in function table was encountered. */ + errSecInvalidServiceMask = -67717, /* An invalid service mask was encountered. */ + errSecModuleNotLoaded = -67718, /* A module was not loaded. */ + errSecInvalidSubServiceID = -67719, /* An invalid subservice ID was encountered. */ + errSecAttributeNotInContext = -67720, /* An attribute was not in the context. */ + errSecModuleManagerInitializeFailed = -67721, /* A module failed to initialize. */ + errSecModuleManagerNotFound = -67722, /* A module was not found. */ + errSecEventNotificationCallbackNotFound = -67723, /* An event notification callback was not found. */ + errSecInputLengthError = -67724, /* An input length error was encountered. */ + errSecOutputLengthError = -67725, /* An output length error was encountered. */ + errSecPrivilegeNotSupported = -67726, /* The privilege is not supported. */ + errSecDeviceError = -67727, /* A device error was encountered. */ + errSecAttachHandleBusy = -67728, /* The CSP handle was busy. */ + errSecNotLoggedIn = -67729, /* You are not logged in. */ + errSecAlgorithmMismatch = -67730, /* An algorithm mismatch was encountered. */ + errSecKeyUsageIncorrect = -67731, /* The key usage is incorrect. */ + errSecKeyBlobTypeIncorrect = -67732, /* The key blob type is incorrect. */ + errSecKeyHeaderInconsistent = -67733, /* The key header is inconsistent. */ + errSecUnsupportedKeyFormat = -67734, /* The key header format is not supported. */ + errSecUnsupportedKeySize = -67735, /* The key size is not supported. */ + errSecInvalidKeyUsageMask = -67736, /* The key usage mask is not valid. */ + errSecUnsupportedKeyUsageMask = -67737, /* The key usage mask is not supported. */ + errSecInvalidKeyAttributeMask = -67738, /* The key attribute mask is not valid. */ + errSecUnsupportedKeyAttributeMask = -67739, /* The key attribute mask is not supported. */ + errSecInvalidKeyLabel = -67740, /* The key label is not valid. */ + errSecUnsupportedKeyLabel = -67741, /* The key label is not supported. */ + errSecInvalidKeyFormat = -67742, /* The key format is not valid. */ + errSecUnsupportedVectorOfBuffers = -67743, /* The vector of buffers is not supported. */ + errSecInvalidInputVector = -67744, /* The input vector is not valid. */ + errSecInvalidOutputVector = -67745, /* The output vector is not valid. */ + errSecInvalidContext = -67746, /* An invalid context was encountered. */ + errSecInvalidAlgorithm = -67747, /* An invalid algorithm was encountered. */ + errSecInvalidAttributeKey = -67748, /* A key attribute was not valid. */ + errSecMissingAttributeKey = -67749, /* A key attribute was missing. */ + errSecInvalidAttributeInitVector = -67750, /* An init vector attribute was not valid. */ + errSecMissingAttributeInitVector = -67751, /* An init vector attribute was missing. */ + errSecInvalidAttributeSalt = -67752, /* A salt attribute was not valid. */ + errSecMissingAttributeSalt = -67753, /* A salt attribute was missing. */ + errSecInvalidAttributePadding = -67754, /* A padding attribute was not valid. */ + errSecMissingAttributePadding = -67755, /* A padding attribute was missing. */ + errSecInvalidAttributeRandom = -67756, /* A random number attribute was not valid. */ + errSecMissingAttributeRandom = -67757, /* A random number attribute was missing. */ + errSecInvalidAttributeSeed = -67758, /* A seed attribute was not valid. */ + errSecMissingAttributeSeed = -67759, /* A seed attribute was missing. */ + errSecInvalidAttributePassphrase = -67760, /* A passphrase attribute was not valid. */ + errSecMissingAttributePassphrase = -67761, /* A passphrase attribute was missing. */ + errSecInvalidAttributeKeyLength = -67762, /* A key length attribute was not valid. */ + errSecMissingAttributeKeyLength = -67763, /* A key length attribute was missing. */ + errSecInvalidAttributeBlockSize = -67764, /* A block size attribute was not valid. */ + errSecMissingAttributeBlockSize = -67765, /* A block size attribute was missing. */ + errSecInvalidAttributeOutputSize = -67766, /* An output size attribute was not valid. */ + errSecMissingAttributeOutputSize = -67767, /* An output size attribute was missing. */ + errSecInvalidAttributeRounds = -67768, /* The number of rounds attribute was not valid. */ + errSecMissingAttributeRounds = -67769, /* The number of rounds attribute was missing. */ + errSecInvalidAlgorithmParms = -67770, /* An algorithm parameters attribute was not valid. */ + errSecMissingAlgorithmParms = -67771, /* An algorithm parameters attribute was missing. */ + errSecInvalidAttributeLabel = -67772, /* A label attribute was not valid. */ + errSecMissingAttributeLabel = -67773, /* A label attribute was missing. */ + errSecInvalidAttributeKeyType = -67774, /* A key type attribute was not valid. */ + errSecMissingAttributeKeyType = -67775, /* A key type attribute was missing. */ + errSecInvalidAttributeMode = -67776, /* A mode attribute was not valid. */ + errSecMissingAttributeMode = -67777, /* A mode attribute was missing. */ + errSecInvalidAttributeEffectiveBits = -67778, /* An effective bits attribute was not valid. */ + errSecMissingAttributeEffectiveBits = -67779, /* An effective bits attribute was missing. */ + errSecInvalidAttributeStartDate = -67780, /* A start date attribute was not valid. */ + errSecMissingAttributeStartDate = -67781, /* A start date attribute was missing. */ + errSecInvalidAttributeEndDate = -67782, /* An end date attribute was not valid. */ + errSecMissingAttributeEndDate = -67783, /* An end date attribute was missing. */ + errSecInvalidAttributeVersion = -67784, /* A version attribute was not valid. */ + errSecMissingAttributeVersion = -67785, /* A version attribute was missing. */ + errSecInvalidAttributePrime = -67786, /* A prime attribute was not valid. */ + errSecMissingAttributePrime = -67787, /* A prime attribute was missing. */ + errSecInvalidAttributeBase = -67788, /* A base attribute was not valid. */ + errSecMissingAttributeBase = -67789, /* A base attribute was missing. */ + errSecInvalidAttributeSubprime = -67790, /* A subprime attribute was not valid. */ + errSecMissingAttributeSubprime = -67791, /* A subprime attribute was missing. */ + errSecInvalidAttributeIterationCount = -67792, /* An iteration count attribute was not valid. */ + errSecMissingAttributeIterationCount = -67793, /* An iteration count attribute was missing. */ + errSecInvalidAttributeDLDBHandle = -67794, /* A database handle attribute was not valid. */ + errSecMissingAttributeDLDBHandle = -67795, /* A database handle attribute was missing. */ + errSecInvalidAttributeAccessCredentials = -67796, /* An access credentials attribute was not valid. */ + errSecMissingAttributeAccessCredentials = -67797, /* An access credentials attribute was missing. */ + errSecInvalidAttributePublicKeyFormat = -67798, /* A public key format attribute was not valid. */ + errSecMissingAttributePublicKeyFormat = -67799, /* A public key format attribute was missing. */ + errSecInvalidAttributePrivateKeyFormat = -67800, /* A private key format attribute was not valid. */ + errSecMissingAttributePrivateKeyFormat = -67801, /* A private key format attribute was missing. */ + errSecInvalidAttributeSymmetricKeyFormat = -67802, /* A symmetric key format attribute was not valid. */ + errSecMissingAttributeSymmetricKeyFormat = -67803, /* A symmetric key format attribute was missing. */ + errSecInvalidAttributeWrappedKeyFormat = -67804, /* A wrapped key format attribute was not valid. */ + errSecMissingAttributeWrappedKeyFormat = -67805, /* A wrapped key format attribute was missing. */ + errSecStagedOperationInProgress = -67806, /* A staged operation is in progress. */ + errSecStagedOperationNotStarted = -67807, /* A staged operation was not started. */ + errSecVerifyFailed = -67808, /* A cryptographic verification failure has occurred. */ + errSecQuerySizeUnknown = -67809, /* The query size is unknown. */ + errSecBlockSizeMismatch = -67810, /* A block size mismatch occurred. */ + errSecPublicKeyInconsistent = -67811, /* The public key was inconsistent. */ + errSecDeviceVerifyFailed = -67812, /* A device verification failure has occurred. */ + errSecInvalidLoginName = -67813, /* An invalid login name was detected. */ + errSecAlreadyLoggedIn = -67814, /* The user is already logged in. */ + errSecInvalidDigestAlgorithm = -67815, /* An invalid digest algorithm was detected. */ + errSecInvalidCRLGroup = -67816, /* An invalid CRL group was detected. */ + errSecCertificateCannotOperate = -67817, /* The certificate cannot operate. */ + errSecCertificateExpired = -67818, /* An expired certificate was detected. */ + errSecCertificateNotValidYet = -67819, /* The certificate is not yet valid. */ + errSecCertificateRevoked = -67820, /* The certificate was revoked. */ + errSecCertificateSuspended = -67821, /* The certificate was suspended. */ + errSecInsufficientCredentials = -67822, /* Insufficient credentials were detected. */ + errSecInvalidAction = -67823, /* The action was not valid. */ + errSecInvalidAuthority = -67824, /* The authority was not valid. */ + errSecVerifyActionFailed = -67825, /* A verify action has failed. */ + errSecInvalidCertAuthority = -67826, /* The certificate authority was not valid. */ + errSecInvaldCRLAuthority = -67827, /* The CRL authority was not valid. */ + errSecInvalidCRLEncoding = -67828, /* The CRL encoding was not valid. */ + errSecInvalidCRLType = -67829, /* The CRL type was not valid. */ + errSecInvalidCRL = -67830, /* The CRL was not valid. */ + errSecInvalidFormType = -67831, /* The form type was not valid. */ + errSecInvalidID = -67832, /* The ID was not valid. */ + errSecInvalidIdentifier = -67833, /* The identifier was not valid. */ + errSecInvalidIndex = -67834, /* The index was not valid. */ + errSecInvalidPolicyIdentifiers = -67835, /* The policy identifiers are not valid. */ + errSecInvalidTimeString = -67836, /* The time specified was not valid. */ + errSecInvalidReason = -67837, /* The trust policy reason was not valid. */ + errSecInvalidRequestInputs = -67838, /* The request inputs are not valid. */ + errSecInvalidResponseVector = -67839, /* The response vector was not valid. */ + errSecInvalidStopOnPolicy = -67840, /* The stop-on policy was not valid. */ + errSecInvalidTuple = -67841, /* The tuple was not valid. */ + errSecMultipleValuesUnsupported = -67842, /* Multiple values are not supported. */ + errSecNotTrusted = -67843, /* The trust policy was not trusted. */ + errSecNoDefaultAuthority = -67844, /* No default authority was detected. */ + errSecRejectedForm = -67845, /* The trust policy had a rejected form. */ + errSecRequestLost = -67846, /* The request was lost. */ + errSecRequestRejected = -67847, /* The request was rejected. */ + errSecUnsupportedAddressType = -67848, /* The address type is not supported. */ + errSecUnsupportedService = -67849, /* The service is not supported. */ + errSecInvalidTupleGroup = -67850, /* The tuple group was not valid. */ + errSecInvalidBaseACLs = -67851, /* The base ACLs are not valid. */ + errSecInvalidTupleCredendtials = -67852, /* The tuple credentials are not valid. */ + errSecInvalidEncoding = -67853, /* The encoding was not valid. */ + errSecInvalidValidityPeriod = -67854, /* The validity period was not valid. */ + errSecInvalidRequestor = -67855, /* The requestor was not valid. */ + errSecRequestDescriptor = -67856, /* The request descriptor was not valid. */ + errSecInvalidBundleInfo = -67857, /* The bundle information was not valid. */ + errSecInvalidCRLIndex = -67858, /* The CRL index was not valid. */ + errSecNoFieldValues = -67859, /* No field values were detected. */ + errSecUnsupportedFieldFormat = -67860, /* The field format is not supported. */ + errSecUnsupportedIndexInfo = -67861, /* The index information is not supported. */ + errSecUnsupportedLocality = -67862, /* The locality is not supported. */ + errSecUnsupportedNumAttributes = -67863, /* The number of attributes is not supported. */ + errSecUnsupportedNumIndexes = -67864, /* The number of indexes is not supported. */ + errSecUnsupportedNumRecordTypes = -67865, /* The number of record types is not supported. */ + errSecFieldSpecifiedMultiple = -67866, /* Too many fields were specified. */ + errSecIncompatibleFieldFormat = -67867, /* The field format was incompatible. */ + errSecInvalidParsingModule = -67868, /* The parsing module was not valid. */ + errSecDatabaseLocked = -67869, /* The database is locked. */ + errSecDatastoreIsOpen = -67870, /* The data store is open. */ + errSecMissingValue = -67871, /* A missing value was detected. */ + errSecUnsupportedQueryLimits = -67872, /* The query limits are not supported. */ + errSecUnsupportedNumSelectionPreds = -67873, /* The number of selection predicates is not supported. */ + errSecUnsupportedOperator = -67874, /* The operator is not supported. */ + errSecInvalidDBLocation = -67875, /* The database location is not valid. */ + errSecInvalidAccessRequest = -67876, /* The access request is not valid. */ + errSecInvalidIndexInfo = -67877, /* The index information is not valid. */ + errSecInvalidNewOwner = -67878, /* The new owner is not valid. */ + errSecInvalidModifyMode = -67879, /* The modify mode is not valid. */ + errSecMissingRequiredExtension = -67880, /* A required certificate extension is missing. */ + errSecExtendedKeyUsageNotCritical = -67881, /* The extended key usage extension was not marked critical. */ + errSecTimestampMissing = -67882, /* A timestamp was expected but was not found. */ + errSecTimestampInvalid = -67883, /* The timestamp was not valid. */ + errSecTimestampNotTrusted = -67884, /* The timestamp was not trusted. */ + errSecTimestampServiceNotAvailable = -67885, /* The timestamp service is not available. */ + errSecTimestampBadAlg = -67886, /* An unrecognized or unsupported Algorithm Identifier in timestamp. */ + errSecTimestampBadRequest = -67887, /* The timestamp transaction is not permitted or supported. */ + errSecTimestampBadDataFormat = -67888, /* The timestamp data submitted has the wrong format. */ + errSecTimestampTimeNotAvailable = -67889, /* The time source for the Timestamp Authority is not available. */ + errSecTimestampUnacceptedPolicy = -67890, /* The requested policy is not supported by the Timestamp Authority. */ + errSecTimestampUnacceptedExtension = -67891, /* The requested extension is not supported by the Timestamp Authority. */ + errSecTimestampAddInfoNotAvailable = -67892, /* The additional information requested is not available. */ + errSecTimestampSystemFailure = -67893, /* The timestamp request cannot be handled due to system failure. */ + errSecSigningTimeMissing = -67894, /* A signing time was expected but was not found. */ + errSecTimestampRejection = -67895, /* A timestamp transaction was rejected. */ + errSecTimestampWaiting = -67896, /* A timestamp transaction is waiting. */ + errSecTimestampRevocationWarning = -67897, /* A timestamp authority revocation warning was issued. */ + errSecTimestampRevocationNotification = -67898, /* A timestamp authority revocation notification was issued. */ +}; + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECBASE_H_ */ diff --git a/libsecurity_keychain/lib/SecBase64P.c b/Security/libsecurity_keychain/lib/SecBase64P.c similarity index 100% rename from libsecurity_keychain/lib/SecBase64P.c rename to Security/libsecurity_keychain/lib/SecBase64P.c diff --git a/libsecurity_keychain/lib/SecBase64P.h b/Security/libsecurity_keychain/lib/SecBase64P.h similarity index 100% rename from libsecurity_keychain/lib/SecBase64P.h rename to Security/libsecurity_keychain/lib/SecBase64P.h diff --git a/libsecurity_keychain/lib/SecBaseP.h b/Security/libsecurity_keychain/lib/SecBaseP.h similarity index 97% rename from libsecurity_keychain/lib/SecBaseP.h rename to Security/libsecurity_keychain/lib/SecBaseP.h index 1259d65c..dc4f9cd1 100644 --- a/libsecurity_keychain/lib/SecBaseP.h +++ b/Security/libsecurity_keychain/lib/SecBaseP.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2009,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_keychain/lib/SecBasePriv.h b/Security/libsecurity_keychain/lib/SecBasePriv.h new file mode 100644 index 00000000..88721e24 --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecBasePriv.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2003-2008,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecBasePriv + SecBasePriv contains private error codes for the Security framework. + */ +#ifndef _SECURITY_SECBASEPRIV_H_ +#define _SECURITY_SECBASEPRIV_H_ + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/******************************************************* + *** Private OSStatus values unique to Security APIs *** + *******************************************************/ + +/* + Note: the comments that appear after these errors are used to create SecErrorMessages.strings. + The comments must not be multi-line, and should be in a form meaningful to an end user. If + a different or additional comment is needed, it can be put in the header doc format, or on a + line that does not start with errZZZ. +*/ + +enum +{ + priv_errSecUnimplemented = -4, /* Private version of errSecUnimplemented constant. */ + priv_errSecParam = -50, /* Private version of errSecParam constant. */ + priv_errSecDecode = -26275, /* Private version of errSecDecode constant. */ +}; + +enum +{ + errSecInvalidCertificate = priv_errSecDecode, // -26265, /* This certificate could not be decoded. */ + errSecPolicyDenied = -26270, /* The certificate chain was not trusted due to a policy not accepting it. */ + errSecInvalidKey = priv_errSecDecode, // -26274, /* The provided key material was not valid. */ + errSecInternal = -26276, /* An internal error occured in the Security framework. */ + errSecUnsupportedAlgorithm = priv_errSecUnimplemented, // -26268, /* An unsupported algorithm was encountered. */ + errSecUnsupportedOperation = priv_errSecUnimplemented, // -26271, /* The operation you requested is not supported by this key. */ + errSecUnsupportedPadding = priv_errSecParam, // -26273, /* The padding you requested is not supported. */ + errSecItemInvalidKey = priv_errSecParam, // -34000, /* A string key in dictionary is not one of the supported keys. */ + errSecItemInvalidKeyType = priv_errSecParam, // -34001, /* A key in a dictionary is neither a CFStringRef nor a CFNumberRef. */ + errSecItemInvalidValue = priv_errSecParam, // -34002, /* A value in a dictionary is an invalid (or unsupported) CF type. */ + errSecItemClassMissing = priv_errSecParam, // -34003, /* No kSecItemClass key was specified in a dictionary. */ + errSecItemMatchUnsupported = priv_errSecParam, // -34004, /* The caller passed one or more kSecMatch keys to a function which does not support matches. */ + errSecUseItemListUnsupported = priv_errSecParam, // -34005, /* The caller passed in a kSecUseItemList key to a function which does not support it. */ + errSecUseKeychainUnsupported = priv_errSecParam, // -34006, /* The caller passed in a kSecUseKeychain key to a function which does not support it. */ + errSecUseKeychainListUnsupported = priv_errSecParam, // -34007, /* The caller passed in a kSecUseKeychainList key to a function which does not support it. */ + errSecReturnDataUnsupported = priv_errSecParam, // -34008, /* The caller passed in a kSecReturnData key to a function which does not support it. */ + errSecReturnAttributesUnsupported = priv_errSecParam, // -34009, /* The caller passed in a kSecReturnAttributes key to a function which does not support it. */ + errSecReturnRefUnsupported = priv_errSecParam, // -34010, /* The caller passed in a kSecReturnRef key to a function which does not support it. */ + errSecValueRefUnsupported = priv_errSecParam, // -34012, /* The caller passed in a kSecValueRef key to a function which does not support it. */ + errSecValuePersistentRefUnsupported = priv_errSecParam, // -34013, /* The caller passed in a kSecValuePersistentRef key to a function which does not support it. */ + errSecReturnMissingPointer = priv_errSecParam, // -34014, /* The caller passed asked for something to be returned but did not pass in a result pointer. */ + errSecMatchLimitUnsupported = priv_errSecParam, // -34015, /* The caller passed in a kSecMatchLimit key to a call which does not support limits. */ + errSecItemIllegalQuery = priv_errSecParam, // -34016, /* The caller passed in a query which contained too many keys. */ +}; + +const char *cssmErrorString(CSSM_RETURN error); + +OSStatus SecKeychainErrFromOSStatus(OSStatus osStatus) + __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECBASEPRIV_H_ */ diff --git a/libsecurity_keychain/lib/SecBridge.h b/Security/libsecurity_keychain/lib/SecBridge.h similarity index 97% rename from libsecurity_keychain/lib/SecBridge.h rename to Security/libsecurity_keychain/lib/SecBridge.h index cd2c25d8..c02c7bb6 100644 --- a/libsecurity_keychain/lib/SecBridge.h +++ b/Security/libsecurity_keychain/lib/SecBridge.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecCFTypes.cpp b/Security/libsecurity_keychain/lib/SecCFTypes.cpp similarity index 96% rename from libsecurity_keychain/lib/SecCFTypes.cpp rename to Security/libsecurity_keychain/lib/SecCFTypes.cpp index 025b6bb7..474d8206 100644 --- a/libsecurity_keychain/lib/SecCFTypes.cpp +++ b/Security/libsecurity_keychain/lib/SecCFTypes.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecCFTypes.h b/Security/libsecurity_keychain/lib/SecCFTypes.h similarity index 98% rename from libsecurity_keychain/lib/SecCFTypes.h rename to Security/libsecurity_keychain/lib/SecCFTypes.h index f58133f1..18935453 100644 --- a/libsecurity_keychain/lib/SecCFTypes.h +++ b/Security/libsecurity_keychain/lib/SecCFTypes.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecCertificate.cpp b/Security/libsecurity_keychain/lib/SecCertificate.cpp similarity index 83% rename from libsecurity_keychain/lib/SecCertificate.cpp rename to Security/libsecurity_keychain/lib/SecCertificate.cpp index 138acb22..4f204eed 100644 --- a/libsecurity_keychain/lib/SecCertificate.cpp +++ b/Security/libsecurity_keychain/lib/SecCertificate.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2013 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -44,104 +44,8 @@ #include "CertificateValues.h" #include "SecCertificateP.h" #include "SecCertificatePrivP.h" -// -//#include "AppleBaselineEscrowCertificates.h" -// -//###################################################################### -//%%% start workaround: rdar://14292830 -//###################################################################### -#ifndef sec_AppleBaselineEscrowCertificates_h -#define sec_AppleBaselineEscrowCertificates_h - -struct RootRecord -{ - size_t _length; - UInt8* _bytes; -}; - -/* ========================================================================== - Production Escrow Certificates - ========================================================================== */ - -static const UInt8 kProductionEscrowRootGM[] = { - 0x30,0x82,0x03,0xD0,0x30,0x82,0x02,0xB8,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x64, - 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30, - 0x79,0x31,0x0C,0x30,0x0A,0x06,0x03,0x55,0x04,0x05,0x13,0x03,0x31,0x30,0x30,0x31, - 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11, - 0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, - 0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,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,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,0x33, - 0x30,0x38,0x30,0x32,0x32,0x33,0x32,0x34,0x34,0x34,0x5A,0x17,0x0D,0x32,0x33,0x30, - 0x38,0x30,0x32,0x32,0x33,0x32,0x34,0x34,0x34,0x5A,0x30,0x79,0x31,0x0C,0x30,0x0A, - 0x06,0x03,0x55,0x04,0x05,0x13,0x03,0x31,0x30,0x30,0x31,0x0B,0x30,0x09,0x06,0x03, - 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A, - 0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24, - 0x06,0x03,0x55,0x04,0x0B,0x13,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,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,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, - 0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01, - 0x0A,0x02,0x82,0x01,0x01,0x00,0xD0,0xA3,0xF4,0x56,0x7D,0x3F,0x46,0x31,0xD2,0x56, - 0xA0,0xDF,0x42,0xA0,0x29,0x83,0x1E,0xB9,0x82,0xB5,0xA5,0xFF,0x3E,0xDE,0xB5,0x0F, - 0x4A,0x8A,0x28,0x60,0xCF,0x75,0xB4,0xA0,0x70,0x7C,0xF5,0xE2,0x94,0xF3,0x22,0x02, - 0xC8,0x81,0xCE,0x34,0xC7,0x66,0x6A,0x18,0xAA,0xB4,0xFD,0x6D,0xB0,0x0B,0xDD,0x4A, - 0xDD,0xCF,0xE0,0x08,0x1B,0x1C,0xA6,0xDB,0xBA,0xB2,0xC1,0xA4,0x10,0x5F,0x35,0x4F, - 0x8B,0x8B,0x7A,0xA3,0xDB,0x3C,0xF6,0x54,0x95,0x42,0xAD,0x2A,0x3B,0xFE,0x06,0x8C, - 0xE1,0x92,0xF1,0x60,0x97,0x58,0x1B,0xD9,0x8F,0xBE,0xFB,0x46,0x4C,0x29,0x5C,0x1C, - 0xF0,0x20,0xB6,0x2B,0xA5,0x12,0x09,0x9B,0x28,0x41,0x34,0x97,0x9F,0xF3,0x88,0x4B, - 0x69,0x72,0xEA,0x3A,0x27,0xB0,0x50,0x1D,0x88,0x29,0x0D,0xBB,0xED,0x04,0xA2,0x11, - 0xCF,0x0C,0x5B,0x65,0x61,0x35,0xBD,0xF2,0x0D,0xFC,0xE2,0xB9,0x20,0xD3,0xB7,0x03, - 0x70,0x39,0xD5,0xE0,0x86,0x7C,0x04,0xCC,0xC9,0xA1,0x85,0xB4,0x9B,0xBC,0x88,0x4E, - 0xD7,0xAD,0x5C,0xFF,0x2C,0x0D,0x80,0x8E,0x51,0x39,0x20,0x8B,0xAF,0x1E,0x46,0x95, - 0xFA,0x0D,0x1B,0xD2,0xBF,0x80,0xE0,0x9F,0x6D,0x4A,0xF5,0x31,0x67,0x18,0x11,0xA5, - 0x63,0x27,0x08,0xEE,0xD9,0x07,0x29,0xD0,0xD4,0x36,0x91,0x5B,0xFB,0x4A,0x0B,0x07, - 0xD1,0x0D,0x79,0x16,0x6E,0x16,0x02,0x23,0x80,0xC6,0x15,0x07,0x6D,0xA0,0x06,0xB6, - 0x45,0x90,0xB0,0xAE,0xA4,0xAD,0x0E,0x75,0x04,0x2B,0x2B,0x78,0xF1,0x57,0x84,0x23, - 0x87,0x24,0xEC,0x58,0xC4,0xF1,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,0x01,0x06, - 0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xFD,0x78,0x96,0x53,0x80, - 0xD6,0xF6,0xDC,0xA6,0xC3,0x59,0x06,0x38,0xED,0x79,0x3E,0x8F,0x50,0x1B,0x50,0x30, - 0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xFD,0x78,0x96,0x53, - 0x80,0xD6,0xF6,0xDC,0xA6,0xC3,0x59,0x06,0x38,0xED,0x79,0x3E,0x8F,0x50,0x1B,0x50, - 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03, - 0x82,0x01,0x01,0x00,0x71,0x15,0xCA,0x87,0xD0,0x2D,0xB5,0x18,0xD5,0x35,0x7A,0xCD, - 0xDF,0x62,0x28,0xF0,0x0B,0x63,0x4D,0x4E,0x02,0xBA,0x3D,0xB8,0xB4,0x37,0xEA,0xB0, - 0x93,0x93,0xAB,0x1C,0xFD,0x9F,0xE8,0x72,0xBF,0xF3,0xDB,0xE6,0xAD,0x16,0xFE,0x71, - 0x61,0xA8,0x5A,0xD0,0x58,0x0F,0x65,0x7A,0x57,0x7A,0xE0,0x34,0x80,0x8E,0xBB,0x41, - 0x01,0xE7,0xB0,0x3B,0xF7,0x2B,0x3A,0x6D,0x44,0x2A,0x3A,0x04,0x52,0xFA,0x2B,0x7B, - 0x3B,0x21,0xDD,0x0C,0x70,0x3D,0xFB,0x45,0xC6,0x79,0x68,0x62,0xE2,0x89,0xB8,0x25, - 0xEE,0x63,0x76,0x02,0xB2,0x22,0xE9,0x53,0x85,0x68,0x3E,0x75,0xB6,0x0B,0x65,0xE9, - 0x1C,0xBA,0x84,0x93,0xB0,0x8A,0xEF,0xB5,0x1A,0x12,0xE4,0x8F,0xAE,0xD5,0x5C,0xA1, - 0x05,0x4A,0x01,0xBC,0x6F,0xF9,0x58,0x5E,0xF7,0x04,0x61,0xEE,0xF5,0xC6,0xA0,0x1B, - 0x44,0x2E,0x5A,0x3A,0x59,0xA1,0xB3,0xB0,0xF4,0xB6,0xCB,0xE0,0x6C,0x2B,0x59,0x8A, - 0xFB,0x6A,0xE0,0xA2,0x57,0x09,0x79,0xC1,0xDD,0xFB,0x84,0x86,0xEB,0x66,0x29,0x73, - 0xAE,0xBF,0x58,0xAE,0x47,0x4D,0x48,0x37,0xD6,0xB1,0x8C,0x5F,0x26,0x5F,0xB5,0x26, - 0x07,0x0B,0x85,0xB7,0x36,0x37,0x14,0xCF,0x5E,0x55,0xA5,0x3C,0xF3,0x1E,0x79,0x50, - 0xBB,0x85,0x3B,0xB2,0x94,0x68,0xB0,0x25,0x4F,0x75,0xEC,0xF0,0xF9,0xC0,0x5A,0x2D, - 0xE5,0xED,0x67,0xCD,0x88,0x55,0xA0,0x42,0xDE,0x78,0xBC,0xFE,0x30,0xB1,0x62,0x2D, - 0xE1,0xFD,0xEC,0x75,0x03,0xA6,0x1F,0x7C,0xC4,0x3A,0x4A,0x59,0xFE,0x77,0xC3,0x99, - 0x96,0x87,0x44,0xC3, -}; - -static struct RootRecord kProductionEscrowRootRecord = {sizeof(kProductionEscrowRootGM), (UInt8*)kProductionEscrowRootGM}; -static struct RootRecord* kProductionEscrowRoots[] = {&kProductionEscrowRootRecord}; -static const int kNumberOfProductionEscrowRoots = (int)(sizeof(kProductionEscrowRoots)/sizeof(kProductionEscrowRoots[0])); - -static struct RootRecord kBaseLineEscrowRootRecord = {sizeof(kProductionEscrowRootGM), (UInt8*)kProductionEscrowRootGM}; -static struct RootRecord* kBaseLineEscrowRoots[] = {&kBaseLineEscrowRootRecord}; -static const int kNumberOfBaseLineEscrowRoots = (int)(sizeof(kBaseLineEscrowRoots)/sizeof(kBaseLineEscrowRoots[0])); - - -#endif -//###################################################################### -//%%% end workaround: rdar://14292830 -////###################################################################### +#include "AppleBaselineEscrowCertificates.h" extern CSSM_KEYUSE ConvertArrayToKeyUsage(CFArrayRef usage); @@ -149,6 +53,7 @@ extern CSSM_KEYUSE ConvertArrayToKeyUsage(CFArrayRef usage); #define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); SEC_CONST_DECL (kSecCertificateProductionEscrowKey, "ProductionEscrowKey"); +SEC_CONST_DECL (kSecCertificateProductionPCSEscrowKey, "ProductionPCSEscrowKey"); SEC_CONST_DECL (kSecCertificateEscrowFileName, "AppleESCertificates"); @@ -1133,7 +1038,7 @@ const UInt8 *SecCertificateGetBytePtr(SecCertificateRef certificate) return bytes; } -static CFArrayRef CopyEscrowCertificates(CFErrorRef *error) +static CFArrayRef CopyEscrowCertificates(SecCertificateEscrowRootType escrowRootType, CFErrorRef *error) { // Return array of CFDataRef certificates. CFArrayRef result = NULL; @@ -1143,13 +1048,34 @@ static CFArrayRef CopyEscrowCertificates(CFErrorRef *error) // Get the hard coded set of production roots // static struct RootRecord* kProductionEscrowRoots[] = {&kOldEscrowRootRecord, &kProductionEscrowRootRecord}; - numRoots = kNumberOfProductionEscrowRoots; + struct RootRecord** pEscrowRoots = NULL; + switch (escrowRootType) { + case kSecCertificateBaselineEscrowRoot: + numRoots = kNumberOfBaseLineEscrowRoots; + pEscrowRoots = kBaseLineEscrowRoots; + break; + case kSecCertificateProductionEscrowRoot: + numRoots = kNumberOfBaseLineEscrowRoots; //%%% currently, production == baseline on OS X + pEscrowRoots = kBaseLineEscrowRoots; + break; + case kSecCertificateBaselinePCSEscrowRoot: + numRoots = kNumberOfBaseLinePCSEscrowRoots; + pEscrowRoots = kBaseLinePCSEscrowRoots; + break; + case kSecCertificateProductionPCSEscrowRoot: + numRoots = kNumberOfBaseLinePCSEscrowRoots; //%%% currently, production == baseline on OS X + pEscrowRoots = kBaseLinePCSEscrowRoots; + break; + default: + break; + } + CFDataRef productionCerts[numRoots]; struct RootRecord* pRootRecord = NULL; - for (iCnt = 0; iCnt < numRoots; iCnt++) + for (iCnt = 0; pEscrowRoots != NULL && iCnt < numRoots; iCnt++) { - pRootRecord = kProductionEscrowRoots[iCnt]; + pRootRecord = pEscrowRoots[iCnt]; if (NULL != pRootRecord && pRootRecord->_length > 0 && NULL != pRootRecord->_bytes) { productionCerts[iCnt] = CFDataCreate(kCFAllocatorDefault, pRootRecord->_bytes, pRootRecord->_length); @@ -1207,10 +1133,10 @@ CFArrayRef SecCertificateCopyEscrowRoots(SecCertificateEscrowRootType escrowRoot } } // The request is for the current certificates. - else if (kSecCertificateProductionEscrowRoot == escrowRootType) + else { CFErrorRef error = NULL; - CFArrayRef cert_datas = CopyEscrowCertificates(&error); + CFArrayRef cert_datas = CopyEscrowCertificates(escrowRootType, &error); if (NULL != error || NULL == cert_datas || 0 == (numRoots = (int)CFArrayGetCount(cert_datas))) { if (NULL != error) diff --git a/Security/libsecurity_keychain/lib/SecCertificate.h b/Security/libsecurity_keychain/lib/SecCertificate.h new file mode 100644 index 00000000..f266766f --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecCertificate.h @@ -0,0 +1,466 @@ +/* + * Copyright (c) 2002-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@ + */ + +/*! + @header SecCertificate + The functions provided in SecCertificate implement and manage a particular type of keychain item that represents a certificate. You can store a certificate in a keychain, but a certificate can also be a transient object. + + You can use a certificate as a keychain item in most functions. +*/ + +#ifndef _SECURITY_SECCERTIFICATE_H_ +#define _SECURITY_SECCERTIFICATE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* +#include +#include +*/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + @enum CertificateItemAttributes + @abstract Indicates the type of a certificate item attribute. + @constant kSecSubjectItemAttr Indicates a DER-encoded subject distinguished name. + @constant kSecIssuerItemAttr Indicates a DER-encoded issuer distinguished name. + @constant kSecSerialNumberItemAttr Indicates a DER-encoded certificate serial number (without the tag and length). + @constant kSecPublicKeyHashItemAttr Indicates a public key hash. + @constant kSecSubjectKeyIdentifierItemAttr Indicates a subject key identifier. + @constant kSecCertTypeItemAttr Indicates a certificate type. + @constant kSecCertEncodingItemAttr Indicates a certificate encoding. +*/ +enum +{ + kSecSubjectItemAttr = 'subj', + kSecIssuerItemAttr = 'issu', + kSecSerialNumberItemAttr = 'snbr', + kSecPublicKeyHashItemAttr = 'hpky', + kSecSubjectKeyIdentifierItemAttr = 'skid', + kSecCertTypeItemAttr = 'ctyp', + kSecCertEncodingItemAttr = 'cenc' +} /*DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER*/; + +/*! + @function SecCertificateGetTypeID + @abstract Returns the type identifier of SecCertificate instances. + @result The CFTypeID of SecCertificate instances. +*/ +CFTypeID SecCertificateGetTypeID(void) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +#pragma mark ---- Certificate Operations ---- + +/*! + @function SecCertificateCreateFromData + @abstract Creates a certificate based on the input data, type, and encoding. + @param data A pointer to the certificate data. + @param type The certificate type as defined in cssmtype.h. + @param encoding The certificate encoding as defined in cssmtype.h. + @param certificate On return, a reference to the newly created certificate. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This API is deprecated in 10.7 Please use the SecCertificateCreateWithData API instead. +*/ +OSStatus SecCertificateCreateFromData(const CSSM_DATA *data, CSSM_CERT_TYPE type, CSSM_CERT_ENCODING encoding, SecCertificateRef *certificate) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/*! + @function SecCertificateCreateWithData + @abstract Create a certificate reference given its DER representation as a CFData. + @param allocator CFAllocator to allocate the certificate data. Pass NULL to use the default allocator. + @param certificate DER encoded X.509 certificate. + @result On return, a reference to the certificate. Returns NULL if the passed-in data is not a valid DER-encoded X.509 certificate. +*/ +SecCertificateRef SecCertificateCreateWithData(CFAllocatorRef allocator, CFDataRef data) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @function SecCertificateAddToKeychain + @abstract Adds a certificate to the specified keychain. + @param certificate A reference to a certificate. + @param keychain A reference to the keychain in which to add the certificate. Pass NULL to add the certificate to the default keychain. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is successful only if the certificate was created using the SecCertificateCreateFromData or + SecCertificateCreateWithData functions, and the certificate has not yet been added to the specified keychain. +*/ +OSStatus SecCertificateAddToKeychain(SecCertificateRef certificate, SecKeychainRef keychain) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); + +/*! + @function SecCertificateGetData + @abstract Retrieves the data for a given certificate. + @param certificate A reference to the certificate from which to retrieve the data. + @param data On return, the CSSM_DATA structure pointed to by data is filled in. You must allocate the space for a CSSM_DATA structure before calling this function. This data pointer is only guaranteed to remain valid as long as the certificate remains unchanged and valid. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This API is deprecated in 10.7. Please use the SecCertificateCopyData API instead. +*/ +OSStatus SecCertificateGetData(SecCertificateRef certificate, CSSM_DATA_PTR data) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/*! + @function SecCertificateCopyData + @abstract Returns the DER representation of an X.509 certificate. + @param certificate A reference to a certificate. + @result On return, a data reference containing the DER encoded representation of the X.509 certificate. +*/ +CFDataRef SecCertificateCopyData(SecCertificateRef certificate) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @function SecCertificateGetType + @abstract Retrieves the type for a given certificate. + @param certificate A reference to the certificate from which to obtain the type. + @param certificateType On return, the certificate type of the certificate. Certificate types are defined in cssmtype.h. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This API is deprecated in 10.7. Please use the SecCertificateCopyValues API instead. +*/ +OSStatus SecCertificateGetType(SecCertificateRef certificate, CSSM_CERT_TYPE *certificateType) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/*! + @function SecCertificateGetSubject + @abstract Retrieves the subject name for a given certificate. + @param certificate A reference to the certificate from which to obtain the subject name. + @param subject On return, a pointer to a CSSM_X509_NAME struct which contains the subject's X.509 name (x509defs.h). This pointer remains valid until the certificate reference is released. The caller should not attempt to free this pointer. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Prior to Mac OS X 10.5, this function did not return any output in the subject parameter. Your code should check the returned pointer value (in addition to the function result) before attempting to use it. + For example: + const CSSM_X509_NAME *subject = NULL; + OSStatus status = SecCertificateGetSubject(certificate, &subject); + if ( (status == errSecSuccess) && (subject != NULL) ) { + // subject is valid + } + This API is deprecated in 10.7. Please use the SecCertificateCopyValues API instead. +*/ +OSStatus SecCertificateGetSubject(SecCertificateRef certificate, const CSSM_X509_NAME **subject) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/*! + @function SecCertificateGetIssuer + @abstract Retrieves the issuer name for a given certificate. + @param certificate A reference to the certificate from which to obtain the issuer name. + @param issuer On return, a pointer to a CSSM_X509_NAME struct which contains the issuer's X.509 name (x509defs.h). This pointer remains valid until the certificate reference is released. The caller should not attempt to free this pointer. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Prior to Mac OS X 10.5, this function did not return any output in the issuer parameter. Your code should check the returned pointer value (in addition to the function result) before attempting to use it. + For example: + const CSSM_X509_NAME *issuer = NULL; + OSStatus status = SecCertificateGetIssuer(certificate, &issuer); + if ( (status == errSecSuccess) && (issuer != NULL) ) { + // issuer is valid + } + This API is deprecated in 10.7. Please use the SecCertificateCopyValues API instead. +*/ +OSStatus SecCertificateGetIssuer(SecCertificateRef certificate, const CSSM_X509_NAME **issuer) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/*! + @function SecCertificateGetCLHandle + @abstract Retrieves the certificate library handle for a given certificate. + @param certificate A reference to the certificate from which to obtain the certificate library handle. + @param clHandle On return, the certificate library handle of the given certificate. This handle remains valid at least as long as the certificate does. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This API is deprecated in 10.7. Please use the SecCertificateCopyValues API instead. +*/ +OSStatus SecCertificateGetCLHandle(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/*! + @function SecCertificateGetAlgorithmID + @abstract Retrieves the algorithm identifier for a given certificate. + @param certificate A reference to the certificate from which to retrieve the algorithm identifier. + @param algid On return, a pointer to a CSSM_X509_ALGORITHM_IDENTIFIER struct which identifies the algorithm for this certificate (x509defs.h). This pointer remains valid until the certificate reference is released. The caller should not attempt to free this pointer. + @result A result code. See "Security Error Codes" (SecBase.h). + discussion This API is deprecated in 10.7. Please use the SecCertificateCopyValues API instead. +*/ +OSStatus SecCertificateGetAlgorithmID(SecCertificateRef certificate, const CSSM_X509_ALGORITHM_IDENTIFIER **algid) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/*! + @function SecCertificateCopyPublicKey + @abstract Retrieves the public key for a given certificate. + @param certificate A reference to the certificate from which to retrieve the public key. + @param key On return, a reference to the public key for the specified certificate. Your code must release this reference by calling the CFRelease function. + @result A result code. See "Security Error Codes" (SecBase.h). +*/ +OSStatus SecCertificateCopyPublicKey(SecCertificateRef certificate, SecKeyRef *key) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); + +/*! + @function SecCertificateCopyCommonName + @abstract Retrieves the common name of the subject of a given certificate. + @param certificate A reference to the certificate from which to retrieve the common name. + @param commonName On return, a reference to the common name. Your code must release this reference by calling the CFRelease function. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion All the data in this string comes from the certificate itself, and thus it's in whatever language the certificate itself is in. + Note that the certificate's common name field may not be present, or may be inadequate to describe the certificate; for display purposes, + you should consider using SecCertificateCopySubjectSummary instead of this function. +*/ +OSStatus SecCertificateCopyCommonName(SecCertificateRef certificate, CFStringRef *commonName) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/*! + @function SecCertificateCopySubjectSummary + @abstract Returns a simple string which hopefully represents a human understandable summary. + @param certificate A reference to the certificate from which to derive the subject summary string. + @result On return, a reference to the subject summary string. Your code must release this reference by calling the CFRelease function. + @discussion All the data in this string comes from the certificate itself, and thus it's in whatever language the certificate itself is in. +*/ +CFStringRef SecCertificateCopySubjectSummary(SecCertificateRef certificate) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @function SecCertificateCopyEmailAddresses + @abstract Returns an array of zero or more email addresses for the subject of a given certificate. + @param certificate A reference to the certificate from which to retrieve the email addresses. + @param emailAddresses On return, an array of zero or more CFStringRef elements corresponding to each email address found. + Your code must release this array reference by calling the CFRelease function. + @result A result code. See "Security Error Codes" (SecBase.h). +*/ +OSStatus SecCertificateCopyEmailAddresses(SecCertificateRef certificate, CFArrayRef *emailAddresses) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/*! + @function SecCertificateCopyPreference + @abstract Returns the preferred certificate for the specified name and key usage. If a preferred certificate does not exist for the specified name and key usage, NULL is returned. + @param name A string containing an email address (RFC822) or other name for which a preferred certificate is requested. + @param keyUsage A CSSM_KEYUSE key usage value, as defined in cssmtype.h. Pass 0 to ignore this parameter. + @param certificate On return, a reference to the preferred certificate, or NULL if none was found. You are responsible for releasing this reference by calling the CFRelease function. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function will typically be used to obtain the preferred encryption certificate for an email recipient. + This API is deprecated in 10.7. Please use the SecCertificateCopyPreferred API instead. +*/ +OSStatus SecCertificateCopyPreference(CFStringRef name, uint32 keyUsage, SecCertificateRef *certificate) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/*! + @function SecCertificateCopyPreferred + @abstract Returns the preferred certificate for the specified name and key usage. If a preferred certificate does not exist for the specified name and key usage, NULL is returned. + @param name A string containing an email address (RFC822) or other name for which a preferred certificate is requested. + @param keyUsage A CFArrayRef value, containing items defined in SecItem.h Pass NULL to ignore this parameter. (kSecAttrCanEncrypt, kSecAttrCanDecrypt, kSecAttrCanDerive, kSecAttrCanSign, kSecAttrCanVerify, kSecAttrCanWrap, kSecAttrCanUnwrap) + @result On return, a reference to the preferred certificate, or NULL if none was found. You are responsible for releasing this reference by calling the CFRelease function. + @discussion This function will typically be used to obtain the preferred encryption certificate for an email recipient. If a preferred certificate has not been set + for the supplied name, the returned reference will be NULL. Your code should then perform a search for possible certificates, using the SecItemCopyMatching API. +*/ +SecCertificateRef SecCertificateCopyPreferred(CFStringRef name, CFArrayRef keyUsage) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @function SecCertificateSetPreference + @abstract Sets the preferred certificate for a specified name, key usage, and date. + @param certificate A reference to the certificate which will be preferred. + @param name A string containing an email address (RFC822) or other name for which a preferred certificate will be associated. + @param keyUsage A CSSM_KEYUSE key usage value, as defined in cssmtype.h. Pass 0 to avoid specifying a particular key usage. + @param date (optional) A date reference. If supplied, the preferred certificate will be changed only if this date is later than the currently saved setting. Pass NULL if this preference should not be restricted by date. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function will typically be used to set the preferred encryption certificate for an email recipient, either manually (when encrypting email to a recipient) or automatically upon receipt of encrypted email. + This API is deprecated in 10.7. Plese use the SecCertificateSetPreferred API instead. +*/ +OSStatus SecCertificateSetPreference(SecCertificateRef certificate, CFStringRef name, uint32 keyUsage, CFDateRef date) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/*! + @function SecCertificateSetPreferred + @abstract Sets the preferred certificate for a specified name and optional key usage. + @param certificate A reference to the preferred certificate. If NULL is passed, any existing preference for the specified name is cleared instead. + @param name A string containing an email address (RFC822) or other name for which a preferred certificate will be associated. + @param keyUsage A CFArrayRef value, containing items defined in SecItem.h Pass NULL to ignore this parameter. (kSecAttrCanEncrypt, kSecAttrCanDecrypt, kSecAttrCanDerive, kSecAttrCanSign, kSecAttrCanVerify, kSecAttrCanWrap, kSecAttrCanUnwrap) + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function will typically be used to set the preferred encryption certificate for an email recipient, either manually (when encrypting email to a recipient) + or automatically upon receipt of encrypted email. +*/ +OSStatus SecCertificateSetPreferred(SecCertificateRef certificate, CFStringRef name, CFArrayRef keyUsage) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @enum kSecPropertyKey + @abstract Constants used to access dictionary entries returned by SecCertificateCopyValues + @constant kSecPropertyKeyType The type of the entry + @constant kSecPropertyKeyLabel The label of the entry + @constant kSecPropertyKeyLocalizedLabel The localized label of the entry + @constant kSecPropertyKeyValue The value of the entry + */ + +extern CFStringRef kSecPropertyKeyType __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFStringRef kSecPropertyKeyLabel __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFStringRef kSecPropertyKeyLocalizedLabel __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFStringRef kSecPropertyKeyValue __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @enum kSecPropertyType + @abstract Public Constants for property list values returned by SecCertificateCopyValues + @discussion Note that kSecPropertyTypeTitle and kSecPropertyTypeError are defined in SecTrust.h +*/ +extern CFStringRef kSecPropertyTypeWarning __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFStringRef kSecPropertyTypeSuccess __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFStringRef kSecPropertyTypeSection __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFStringRef kSecPropertyTypeData __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFStringRef kSecPropertyTypeString __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFStringRef kSecPropertyTypeURL __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFStringRef kSecPropertyTypeDate __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @function SecCertificateCopyValues + @abstract Creates a dictionary that represents a certificate's contents. + @param certificate The certificate from which to get values + @param keys An array of string OID values, or NULL. If present, this is + the subset of values from the certificate to return. If NULL, + all values will be returned. Only OIDs that are top level keys + in the returned dictionary can be specified. Unknown OIDs are + ignored. + @param error An optional pointer to a CFErrorRef. This value is + set if an error occurred. If not NULL the caller is + responsible for releasing the CFErrorRef. + @discussion The keys array will contain all of the keys used in the + returned dictionary. The top level keys in the returned + dictionary are OIDs, many of which are found in SecCertificateOIDs.h. + Each entry that is returned is itself a dictionary with four + entries, whose keys are kSecPropertyKeyType, kSecPropertyKeyLabel, + kSecPropertyKeyLocalizedLabel, kSecPropertyKeyValue. The label + entries may contain a descriptive (localized) string, or an + OID string. The kSecPropertyKeyType describes the type in the + value entry. The value entry may be any CFType, although it + is usually a CFStringRef, CFArrayRef or a CFDictionaryRef. +*/ +CFDictionaryRef SecCertificateCopyValues(SecCertificateRef certificate, CFArrayRef keys, CFErrorRef *error) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @enum Transform Key Value Constants + @discussion Predefined values for the kSecTransformAttrCertificateUsage attribute. + + + kSecCertificateUsageSigning + kSecCertificateUsageSigningAndEncrypting + kSecCertificateUsageDeriveAndSign + +*/ + +extern const CFStringRef kSecCertificateUsageSigning __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFStringRef kSecCertificateUsageSigningAndEncrypting __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFStringRef kSecCertificateUsageDeriveAndSign __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @function SecCertificateCopyLongDescription + @abstract Return the long description of a certificate + @param alloc The CFAllocator which should be used to allocate + memory for the dictionary and its storage for values. This + parameter may be NULL in which case the current default + CFAllocator is used. If this reference is not a valid + CFAllocator, the behavior is undefined. + @param certificate The certificate from which to retrieve the long description + @param error An optional pointer to a CFErrorRef. This value is + set if an error occurred. If not NULL the caller is + responsible for releasing the CFErrorRef. + @result A CFStringRef of the long description or NULL. If NULL and the error + parameter is supplied the error will be returned in the error parameter + @discussion Note that the format of this string may change in the future +*/ + +CFStringRef SecCertificateCopyLongDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @function SecCertificateCopyShortDescription + @abstract Return the short description of a certificate + @param alloc The CFAllocator which should be used to allocate + memory for the dictionary and its storage for values. This + parameter may be NULL in which case the current default + CFAllocator is used. If this reference is not a valid + CFAllocator, the behavior is undefined. + @param certificate The certificate from which to retrieve the short description + @param error An optional pointer to a CFErrorRef. This value is + set if an error occurred. If not NULL the caller is + responsible for releasing the CFErrorRef. + @result A CFStringRef of the short description or NULL. If NULL and the error + parameter is supplied the error will be returned in the error parameter + @discussion Note that the format of this string may change in the future +*/ + +CFStringRef SecCertificateCopyShortDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @function SecCertificateCopySerialNumber + @abstract Return the certificate's serial number. + @param certificate The certificate from which to get values + @param error An optional pointer to a CFErrorRef. This value is + set if an error occurred. If not NULL the caller is + responsible for releasing the CFErrorRef. + @discussion Return the content of a DER-encoded integer (without the + tag and length fields) for this certificate's serial + number. The caller must CFRelease the value returned. +*/ + +CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate, CFErrorRef *error) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @function SecCertificateCopyNormalizedIssuerContent + @abstract Return the certificate's normalized issuer + @param certificate The certificate from which to get values + @param error An optional pointer to a CFErrorRef. This value is + set if an error occurred. If not NULL the caller is + responsible for releasing the CFErrorRef. + @discussion The issuer is a sequence in the format used by + SecItemCopyMatching. The content returned is a DER-encoded + X.509 distinguished name. For a display version of the issuer, + call SecCertificateCopyValues. The caller must CFRelease + the value returned. +*/ + +CFDataRef SecCertificateCopyNormalizedIssuerContent(SecCertificateRef certificate, CFErrorRef *error) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @function SecCertificateCopyNormalizedSubjectContent + @abstract Return the certificate's normalized subject + @param certificate The certificate from which to get values + @param error An optional pointer to a CFErrorRef. This value is + set if an error occurred. If not NULL the caller is + responsible for releasing the CFErrorRef. + @discussion The subject is a sequence in the format used by + SecItemCopyMatching. The content returned is a DER-encoded + X.509 distinguished name. For a display version of the subject, + call SecCertificateCopyValues. The caller must CFRelease + the value returned. +*/ + +CFDataRef SecCertificateCopyNormalizedSubjectContent(SecCertificateRef certificate, CFErrorRef *error) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECCERTIFICATE_H_ */ diff --git a/libsecurity_keychain/lib/SecCertificateBundle.cpp b/Security/libsecurity_keychain/lib/SecCertificateBundle.cpp similarity index 96% rename from libsecurity_keychain/lib/SecCertificateBundle.cpp rename to Security/libsecurity_keychain/lib/SecCertificateBundle.cpp index 598dcdf9..5e60033d 100644 --- a/libsecurity_keychain/lib/SecCertificateBundle.cpp +++ b/Security/libsecurity_keychain/lib/SecCertificateBundle.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecCertificateBundle.h b/Security/libsecurity_keychain/lib/SecCertificateBundle.h similarity index 97% rename from libsecurity_keychain/lib/SecCertificateBundle.h rename to Security/libsecurity_keychain/lib/SecCertificateBundle.h index 3929d8ec..f63160e0 100644 --- a/libsecurity_keychain/lib/SecCertificateBundle.h +++ b/Security/libsecurity_keychain/lib/SecCertificateBundle.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecCertificateInternalP.h b/Security/libsecurity_keychain/lib/SecCertificateInternalP.h similarity index 99% rename from libsecurity_keychain/lib/SecCertificateInternalP.h rename to Security/libsecurity_keychain/lib/SecCertificateInternalP.h index 7296c532..8ed813f9 100644 --- a/libsecurity_keychain/lib/SecCertificateInternalP.h +++ b/Security/libsecurity_keychain/lib/SecCertificateInternalP.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2007-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/SecCertificateOIDs.h b/Security/libsecurity_keychain/lib/SecCertificateOIDs.h similarity index 99% rename from libsecurity_keychain/lib/SecCertificateOIDs.h rename to Security/libsecurity_keychain/lib/SecCertificateOIDs.h index 076e76ba..eb1af098 100644 --- a/libsecurity_keychain/lib/SecCertificateOIDs.h +++ b/Security/libsecurity_keychain/lib/SecCertificateOIDs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecCertificateP.c b/Security/libsecurity_keychain/lib/SecCertificateP.c similarity index 99% rename from libsecurity_keychain/lib/SecCertificateP.c rename to Security/libsecurity_keychain/lib/SecCertificateP.c index fd98e68d..0fe9d528 100644 --- a/libsecurity_keychain/lib/SecCertificateP.c +++ b/Security/libsecurity_keychain/lib/SecCertificateP.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/SecCertificateP.h b/Security/libsecurity_keychain/lib/SecCertificateP.h similarity index 98% rename from libsecurity_keychain/lib/SecCertificateP.h rename to Security/libsecurity_keychain/lib/SecCertificateP.h index 9a49ca60..3bab16b8 100644 --- a/libsecurity_keychain/lib/SecCertificateP.h +++ b/Security/libsecurity_keychain/lib/SecCertificateP.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2006-2009,2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2009,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/Security/libsecurity_keychain/lib/SecCertificatePriv.h b/Security/libsecurity_keychain/lib/SecCertificatePriv.h new file mode 100644 index 00000000..402f7d5c --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecCertificatePriv.h @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2002-2004,2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SECURITY_SECCERTIFICATEPRIV_H_ +#define _SECURITY_SECCERTIFICATEPRIV_H_ + +#include +#include +#include +#include +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef uint32_t SecCertificateEscrowRootType; +enum { + kSecCertificateBaselineEscrowRoot = 0, + kSecCertificateProductionEscrowRoot = 1, + kSecCertificateBaselinePCSEscrowRoot = 2, + kSecCertificateProductionPCSEscrowRoot = 3, +}; + +extern CFTypeRef kSecCertificateProductionEscrowKey; +extern CFTypeRef kSecCertificateProductionPCSEscrowKey; +extern CFTypeRef kSecCertificateEscrowFileName; + + +/* Return a certificate for the DER representation of this certificate. + Return NULL if the passed-in data is not a valid DER-encoded X.509 + certificate. */ +SecCertificateRef SecCertificateCreateWithBytes(CFAllocatorRef allocator, + const UInt8 *bytes, CFIndex length); + +/* Return the length of the DER representation of this certificate. */ +CFIndex SecCertificateGetLength(SecCertificateRef certificate); + +/* Return the bytes of the DER representation of this certificate. */ +const UInt8 *SecCertificateGetBytePtr(SecCertificateRef certificate); + +/* Return the SHA-1 hash of this certificate. */ +CFDataRef SecCertificateGetSHA1Digest(SecCertificateRef certificate); + +/* Deprecated; use SecCertificateCopyCommonName() instead. */ +OSStatus SecCertificateGetCommonName(SecCertificateRef certificate, CFStringRef *commonName); + +/* Deprecated; use SecCertificateCopyEmailAddresses() instead. */ +/* This should have been Copy instead of Get since the returned address is not autoreleased. */ +OSStatus SecCertificateGetEmailAddress(SecCertificateRef certificate, CFStringRef *emailAddress); + +/* Return an array of CFStringRefs representing the dns addresses in the + certificate if any. */ +CFArrayRef SecCertificateCopyDNSNames(SecCertificateRef certificate); + +/*! + @function SecCertificateCopyIssuerSummary + @abstract Return a simple string which hopefully represents a human understandable issuer. + @param certificate SecCertificate object created with SecCertificateCreateWithData(). + @discussion All the data in this string comes from the certificate itself + and thus it's in whatever language the certificate itself is in. + @result A CFStringRef which the caller should CFRelease() once it's no longer needed. +*/ +CFStringRef SecCertificateCopyIssuerSummary(SecCertificateRef certificate); + +/* + * Private API to infer a display name for a SecCertificateRef which + * may or may not be in a keychain. + */ +OSStatus SecCertificateInferLabel(SecCertificateRef certificate, CFStringRef *label); + +/* + * Subset of the above, useful for both certs and CRLs. + * Infer printable label for a given an CSSM_X509_NAME. Returns NULL + * if no appropriate printable name found. + */ +const CSSM_DATA *SecInferLabelFromX509Name( + const CSSM_X509_NAME *x509Name); + +/* Accessors for fields in the cached certificate */ + +/*! + @function SecCertificateCopyFieldValues + @abstract Retrieves the values for a particular field in a given certificate. + @param certificate A valid SecCertificateRef to the certificate. + @param field Pointer to the OID whose values should be returned. + @param fieldValues On return, a zero terminated list of CSSM_DATA_PTR's. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Return a zero terminated list of CSSM_DATA_PTR's with the + values of the field specified by field. Caller must call + SecCertificateReleaseFieldValues to free the storage allocated by this call. +*/ +OSStatus SecCertificateCopyFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR **fieldValues); + +/*! + @function SecCertificateReleaseFieldValues + @abstract Release the storage associated with the values returned by SecCertificateCopyFieldValues. + @param certificate A valid SecCertificateRef to the certificate. + @param field Pointer to the OID whose values were returned by SecCertificateCopyFieldValues. + @param fieldValues Pointer to a zero terminated list of CSSM_DATA_PTR's. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Release the storage associated with the values returned by SecCertificateCopyFieldValues. +*/ +OSStatus SecCertificateReleaseFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValues); + +/*! + @function SecCertificateCopyFirstFieldValue + @abstract Return a CSSM_DATA_PTR with the value of the first field specified by field. + @param certificate A valid SecCertificateRef to the certificate. + @param field Pointer to the OID whose value should be returned. + @param fieldValue On return, a CSSM_DATA_PTR to the field data. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Return a CSSM_DATA_PTR with the value of the first field specified by field. Caller must call + SecCertificateReleaseFieldValue to free the storage allocated by this call. +*/ +OSStatus SecCertificateCopyFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValue); + +/*! + @function SecCertificateReleaseFirstFieldValue + @abstract Release the storage associated with the values returned by SecCertificateCopyFirstFieldValue. + @param certificate A valid SecCertificateRef to the certificate. + @param field Pointer to the OID whose values were returned by SecCertificateCopyFieldValue. + @param fieldValue The field data to release. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Release the storage associated with the values returned by SecCertificateCopyFieldValue. +*/ +OSStatus SecCertificateReleaseFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR fieldValue); + +/*! + @function SecCertificateCopySubjectComponent + @abstract Retrieves a component of the subject distinguished name of a given certificate. + @param certificate A reference to the certificate from which to retrieve the common name. + @param component A component oid naming the component desired. See . + @param result On return, a reference to the string form of the component, if present in the subject. + Your code must release this reference by calling the CFRelease function. + @result A result code. See "Security Error Codes" (SecBase.h). + */ +OSStatus SecCertificateCopySubjectComponent(SecCertificateRef certificate, const CSSM_OID *component, + CFStringRef *result); + +/* Return the DER encoded issuer sequence for the certificate's issuer. */ +CFDataRef SecCertificateCopyIssuerSequence(SecCertificateRef certificate); + +/* Return the DER encoded subject sequence for the certificate's subject. */ +CFDataRef SecCertificateCopySubjectSequence(SecCertificateRef certificate); + + +/* Convenience functions for searching. +*/ + +OSStatus SecCertificateFindByIssuerAndSN(CFTypeRef keychainOrArray, const CSSM_DATA *issuer, + const CSSM_DATA *serialNumber, SecCertificateRef *certificate); + +OSStatus SecCertificateFindBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID, + SecCertificateRef *certificate); + +OSStatus SecCertificateFindByEmail(CFTypeRef keychainOrArray, const char *emailAddress, + SecCertificateRef *certificate); + + +/* These should go to SecKeychainSearchPriv.h. */ +OSStatus SecKeychainSearchCreateForCertificateByIssuerAndSN(CFTypeRef keychainOrArray, const CSSM_DATA *issuer, + const CSSM_DATA *serialNumber, SecKeychainSearchRef *searchRef); + +OSStatus SecKeychainSearchCreateForCertificateByIssuerAndSN_CF(CFTypeRef keychainOrArray, CFDataRef issuer, + CFDataRef serialNumber, SecKeychainSearchRef *searchRef); + +OSStatus SecKeychainSearchCreateForCertificateBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID, + SecKeychainSearchRef *searchRef); + +OSStatus SecKeychainSearchCreateForCertificateByEmail(CFTypeRef keychainOrArray, const char *emailAddress, + SecKeychainSearchRef *searchRef); + +/* Convenience function for generating digests; should be moved elsewhere. */ +CSSM_RETURN SecDigestGetData(CSSM_ALGORITHMS alg, CSSM_DATA* digest, const CSSM_DATA* data); + +/* Return true iff certificate is valid as of verifyTime. */ +/* DEPRECATED: Use SecCertificateIsValid instead. */ +bool SecCertificateIsValidX(SecCertificateRef certificate, CFAbsoluteTime verifyTime) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecCertificateIsValid + @abstract Check certificate validity on a given date. + @param certificate A certificate reference. + @result Returns true if the specified date falls within the certificate's validity period, false otherwise. +*/ +bool SecCertificateIsValid(SecCertificateRef certificate, CFAbsoluteTime verifyTime) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_2_0); + +/*! + @function SecCertificateNotValidBefore + @abstract Obtain the starting date of the given certificate. + @param certificate A certificate reference. + @result Returns the absolute time at which the given certificate becomes valid, + or 0 if this value could not be obtained. +*/ +CFAbsoluteTime SecCertificateNotValidBefore(SecCertificateRef certificate) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_2_0); + +/*! + @function SecCertificateNotValidAfter + @abstract Obtain the expiration date of the given certificate. + @param certificate A certificate reference. + @result Returns the absolute time at which the given certificate expires, + or 0 if this value could not be obtained. +*/ +CFAbsoluteTime SecCertificateNotValidAfter(SecCertificateRef certificate) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_2_0); + +/*! + @function SecCertificateIsSelfSigned + @abstract Determine if the given certificate is self-signed. + @param certRef A certificate reference. + @param isSelfSigned Will be set to true on return if the certificate is self-signed, false otherwise. + @result A result code. Returns errSecSuccess if the certificate's status can be determined. +*/ +OSStatus SecCertificateIsSelfSigned(SecCertificateRef certRef, Boolean *isSelfSigned) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/*! + @function SecCertificateCopyEscrowRoots + @abstract Retrieve the array of valid escrow certificates for a given root type. + @param escrowRootType An enumerated type indicating which root type to return. + @result An array of zero or more escrow certificates matching the provided type. +*/ +CFArrayRef SecCertificateCopyEscrowRoots(SecCertificateEscrowRootType escrowRootType) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECCERTIFICATEPRIV_H_ */ diff --git a/libsecurity_keychain/lib/SecCertificatePrivP.h b/Security/libsecurity_keychain/lib/SecCertificatePrivP.h similarity index 98% rename from libsecurity_keychain/lib/SecCertificatePrivP.h rename to Security/libsecurity_keychain/lib/SecCertificatePrivP.h index 7240e4a6..4b26ff00 100644 --- a/libsecurity_keychain/lib/SecCertificatePrivP.h +++ b/Security/libsecurity_keychain/lib/SecCertificatePrivP.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2006-2010,2013 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/SecCertificateRequest.cpp b/Security/libsecurity_keychain/lib/SecCertificateRequest.cpp similarity index 98% rename from libsecurity_keychain/lib/SecCertificateRequest.cpp rename to Security/libsecurity_keychain/lib/SecCertificateRequest.cpp index 81353eb8..9cd90525 100644 --- a/libsecurity_keychain/lib/SecCertificateRequest.cpp +++ b/Security/libsecurity_keychain/lib/SecCertificateRequest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_keychain/lib/SecCertificateRequest.h b/Security/libsecurity_keychain/lib/SecCertificateRequest.h new file mode 100644 index 00000000..f4389c5c --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecCertificateRequest.h @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2002-2004,2011,2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecCertificateRequest + SecCertificateRequest implements a way to issue a certificate request to a + certificate authority. +*/ + +#ifndef _SECURITY_SECCERTIFICATEREQUEST_H_ +#define _SECURITY_SECCERTIFICATEREQUEST_H_ + +#include +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + +struct SecCertificateRequestAttribute /* for optional oids */ +{ + CSSM_OID oid; + CSSM_DATA value; +}; +typedef struct SecCertificateRequestAttribute SecCertificateRequestAttribute; + +struct SecCertificateRequestAttributeList +{ + UInt32 count; + SecCertificateRequestAttribute *attr; +}; +typedef struct SecCertificateRequestAttributeList SecCertificateRequestAttributeList; + +/*! + @typedef SecCertificateRequestRef + @abstract Contains information about a certificate request. +*/ +typedef struct OpaqueSecCertificateRequestRef *SecCertificateRequestRef; + +/*! + @function SecCertificateRequestGetTypeID + Returns the type identifier of all SecCertificateRequest instances. +*/ +CFTypeID SecCertificateRequestGetTypeID(void); + +/*! + @function SecCertificateRequestCreate + + Create a certificate request operation based on a policy and certificate + type. If a policy is not specified, one will be chosen for the caller. + Once the requeste is created, a request reference is returned. + To submit the request call SecCertificateRequestSubmit(). + + @param policy A policy. + @param certificateType The certificate type (i.e. X509, PGP, etc). + These types are in cssmtype.h + @param requestType The identifier to the type of request to submit (i.e. + issue, verify, revoke, etc.). These are defined in cssmtype.h + @param privateKeyItemRef The keychain item private key to be used for this + certificate request. The private key item must be of class type + kSecAppleKeyItemClass. + @param attributeList An optional list of OIDs for the certificate request. + @param certRequest A returned reference to the certificate request. Call CFRelease when done with this certificate request. + @result errSecSuccess 0 No error. +*/ +OSStatus SecCertificateRequestCreate( + const CSSM_OID *policy, + CSSM_CERT_TYPE certificateType, + CSSM_TP_AUTHORITY_REQUEST_TYPE requestType, + SecKeyRef privateKeyItemRef, + SecKeyRef publicKeyItemRef, + const SecCertificateRequestAttributeList* attributeList, + SecCertificateRequestRef* certRequest); + +/*! + @function SecCertificateRequestSubmit + + Submit a certificate request to be processed by the Security framework. + Once the request is submitted, an estimated time is returned indicating + when the request results can be retrieved. Once the estimated time has + elapsed, obtain the result by calling SecCertificateRequestGetResult(). + + @param certRequest A reference to the certificate request. + @param estimatedTime The number of estimated seconds before the result + can be retrieved. + @result errSecSuccess 0 No error. +*/ +OSStatus SecCertificateRequestSubmit( + SecCertificateRequestRef certRequest, + sint32* estimatedTime); + +/*! + @function SecCertificateRequestGetType + Returns the certificate request type (i.e. issue, revoke, etc) for a given + certificate request item reference. + @param certRequestRef A reference to a submitted request. + @param requestType The returned request type. + @result errSecSuccess 0 No error. +*/ +OSStatus SecCertificateRequestGetType( + SecCertificateRequestRef certRequestRef, + CSSM_TP_AUTHORITY_REQUEST_TYPE* requestType); + +/*! + @function SecCertificateRequestGetResult + Get the results of a certificate request. If the request is still + pending, the estimated time will be returned which indicates when to + call this function again. + @param certRequestRef A reference for the submitted request. + @param keychain The keychain in which to store the new certificate (for + a new cert request) and the cert request item reference. Pass NULL + to specify the default keychain. + @param estimatedTime The number of estimated seconds before the result can + be retrieved. + @param certficateRef The returned certificate reference for a + CSSM_TP_AUTHORITY_REQUEST_CERTISSUE only. All other request types return + NULL here. Call CFRelease when done with this certificate reference. + @result errSecSuccess 0 No error. +*/ +OSStatus SecCertificateRequestGetResult( + SecCertificateRequestRef certRequestRef, + SecKeychainRef keychain, + sint32* estimatedTime, + SecCertificateRef* certificateRef); + +/*! + @function SecCertificateFindRequest + Find a pending certificate request and return a reference object + for it. The search criteria is based on the input parameters. + @param policy A policy. + @param certificateType The certificate type (i.e. X509, PGP, etc). + These types are in cssmtype.h + @param requestType The identifier to the type of request to find (i.e. + issue, verify, revoke, etc.). These are defined in cssmtype.h + @param privateKeyItemRef Optional private key to be used + for the certificate request. Matches the same argument as passed to + SecCertificateRequestCreate(). + @param publicKeyItemRef Optional public key to be used + for the certificate request. Matches the same argument as passed to + SecCertificateRequestCreate(). + @param attributeList An optional list of OID/value pairs for finding the + certificate request. + @param certRequest A returned reference to the certificate request. Call CFRelease when done with this reference. +*/ +OSStatus SecCertificateFindRequest( + const CSSM_OID *policy, + CSSM_CERT_TYPE certificateType, + CSSM_TP_AUTHORITY_REQUEST_TYPE requestType, + SecKeyRef privateKeyItemRef, + SecKeyRef publicKeyItemRef, + const SecCertificateRequestAttributeList* attributeList, + SecCertificateRequestRef* certRequest); + +/*! + @function SecCertificateRequestGetData + Get policy-specific data following a SecCertificateRequestSubmit. + @param certRequestRef A reference for the submitted request. + @param data Policy-specific data. + @result errSecSuccess 0 No error. +*/ + +OSStatus SecCertificateRequestGetData( + SecCertificateRequestRef certRequestRef, + CSSM_DATA *data); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECCERTIFICATEREQUEST_H_ */ diff --git a/libsecurity_keychain/lib/SecExport.cpp b/Security/libsecurity_keychain/lib/SecExport.cpp similarity index 99% rename from libsecurity_keychain/lib/SecExport.cpp rename to Security/libsecurity_keychain/lib/SecExport.cpp index ce4e3de5..2e836255 100644 --- a/libsecurity_keychain/lib/SecExport.cpp +++ b/Security/libsecurity_keychain/lib/SecExport.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecExternalRep.cpp b/Security/libsecurity_keychain/lib/SecExternalRep.cpp similarity index 96% rename from libsecurity_keychain/lib/SecExternalRep.cpp rename to Security/libsecurity_keychain/lib/SecExternalRep.cpp index fe681e16..14784c12 100644 --- a/libsecurity_keychain/lib/SecExternalRep.cpp +++ b/Security/libsecurity_keychain/lib/SecExternalRep.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -508,9 +508,14 @@ OSStatus SecImportRep::importRep( case kSecFormatSSHv2: case kSecFormatBSAFE: case kSecFormatRawKey: - ortn = impExpImportRawKey(mExternal, mExternFormat, mExternType, - mKeyAlg, importKeychain, cspHand, flags, keyParams, mPrintName, outArray); - break; + if(mExternal != NULL || CFDataGetLength(mExternal) != 0){ + ortn = impExpImportRawKey(mExternal, mExternFormat, mExternType, + mKeyAlg, importKeychain, cspHand, flags, keyParams, mPrintName, outArray); + } + else{ + MacOSError::throwMe(errSecUnsupportedKeySize); + } + break; case kSecFormatWrappedPKCS8: ortn = impExpPkcs8Import(mExternal, importKeychain, cspHand, flags, keyParams, outArray); diff --git a/libsecurity_keychain/lib/SecExternalRep.h b/Security/libsecurity_keychain/lib/SecExternalRep.h similarity index 98% rename from libsecurity_keychain/lib/SecExternalRep.h rename to Security/libsecurity_keychain/lib/SecExternalRep.h index 4d064bac..5c38e106 100644 --- a/libsecurity_keychain/lib/SecExternalRep.h +++ b/Security/libsecurity_keychain/lib/SecExternalRep.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.cpp b/Security/libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.cpp similarity index 99% rename from libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.cpp rename to Security/libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.cpp index 4b671032..8dfb57f8 100644 --- a/libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.cpp +++ b/Security/libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.h b/Security/libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.h similarity index 97% rename from libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.h rename to Security/libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.h index 622ca9c7..c97ac937 100644 --- a/libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.h +++ b/Security/libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecFrameworkP.c b/Security/libsecurity_keychain/lib/SecFrameworkP.c similarity index 99% rename from libsecurity_keychain/lib/SecFrameworkP.c rename to Security/libsecurity_keychain/lib/SecFrameworkP.c index 86c5fca8..8be6b22d 100644 --- a/libsecurity_keychain/lib/SecFrameworkP.c +++ b/Security/libsecurity_keychain/lib/SecFrameworkP.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecFrameworkP.h b/Security/libsecurity_keychain/lib/SecFrameworkP.h similarity index 97% rename from libsecurity_keychain/lib/SecFrameworkP.h rename to Security/libsecurity_keychain/lib/SecFrameworkP.h index ca563719..3a7135a8 100644 --- a/libsecurity_keychain/lib/SecFrameworkP.h +++ b/Security/libsecurity_keychain/lib/SecFrameworkP.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007,2009-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2009-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecIdentity.cpp b/Security/libsecurity_keychain/lib/SecIdentity.cpp similarity index 99% rename from libsecurity_keychain/lib/SecIdentity.cpp rename to Security/libsecurity_keychain/lib/SecIdentity.cpp index 2c249db7..5c16a1b3 100644 --- a/libsecurity_keychain/lib/SecIdentity.cpp +++ b/Security/libsecurity_keychain/lib/SecIdentity.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/Security/libsecurity_keychain/lib/SecIdentity.h b/Security/libsecurity_keychain/lib/SecIdentity.h new file mode 100644 index 00000000..564a4d3a --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecIdentity.h @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2002-2011 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 SecIdentity + The functions provided in SecIdentity implement a convenient way to match private keys with certificates. +*/ + +#ifndef _SECURITY_SECIDENTITY_H_ +#define _SECURITY_SECIDENTITY_H_ + +#include +#include +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + @function SecIdentityGetTypeID + @abstract Returns the type identifier of SecIdentity instances. + @result The CFTypeID of SecIdentity instances. +*/ +CFTypeID SecIdentityGetTypeID(void) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +/*! + @function SecIdentityCreateWithCertificate + @abstract Creates a new identity reference for the given certificate, assuming the associated private key is in one of the specified keychains. + @param keychainOrArray A reference to an array of keychains to search, a single keychain, or NULL to search the user's default keychain search list. + @param certificateRef A certificate reference. + @param identityRef On return, an identity reference. You are responsible for releasing this reference by calling the CFRelease function. + @result A result code. See "Security Error Codes" (SecBase.h). +*/ +OSStatus SecIdentityCreateWithCertificate( + CFTypeRef keychainOrArray, + SecCertificateRef certificateRef, + SecIdentityRef *identityRef) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/*! + @function SecIdentityCopyCertificate + @abstract Returns a reference to a certificate for the given identity reference. + @param identityRef An identity reference. + @param certificateRef On return, a reference to the found certificate. You are responsible for releasing this reference by calling the CFRelease function. + @result A result code. See "Security Error Codes" (SecBase.h). +*/ +OSStatus SecIdentityCopyCertificate( + SecIdentityRef identityRef, + SecCertificateRef *certificateRef) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +/*! + @function SecIdentityCopyPrivateKey + @abstract Returns the private key associated with an identity. + @param identityRef An identity reference. + @param privateKeyRef On return, a reference to the private key for the given identity. You are responsible for releasing this reference by calling the CFRelease function. + @result A result code. See "Security Error Codes" (SecBase.h). +*/ +OSStatus SecIdentityCopyPrivateKey( + SecIdentityRef identityRef, + SecKeyRef *privateKeyRef) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +/*! + @function SecIdentityCopyPreference + @abstract Returns the preferred identity for the specified name and key usage, optionally limiting the result to an identity issued by a certificate whose subject is one of the distinguished names in validIssuers. If a preferred identity does not exist, NULL is returned. + @param name A string containing a URI, RFC822 email address, DNS hostname, or other name which uniquely identifies the service requiring an identity. + @param keyUsage A CSSM_KEYUSE key usage value, as defined in cssmtype.h. Pass 0 to ignore this parameter. + @param validIssuers (optional) An array of CFDataRef instances whose contents are the subject names of allowable issuers, as returned by a call to SSLCopyDistinguishedNames (SecureTransport.h). Pass NULL if any issuer is allowed. + @param identity On return, a reference to the preferred identity, or NULL if none was found. You are responsible for releasing this reference by calling the CFRelease function. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This API is deprecated in 10.7. Please use the SecIdentityCopyPreferred API instead. +*/ +OSStatus SecIdentityCopyPreference(CFStringRef name, CSSM_KEYUSE keyUsage, CFArrayRef validIssuers, SecIdentityRef *identity) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/*! + @function SecIdentityCopyPreferred + @abstract Returns the preferred identity for the specified name and key usage, optionally limiting the result to an identity issued by a certificate whose subject is one of the distinguished names in validIssuers. If a preferred identity does not exist, NULL is returned. + @param name A string containing a URI, RFC822 email address, DNS hostname, or other name which uniquely identifies the service requiring an identity. + @param keyUsage A CFArrayRef value, containing items defined in SecItem.h Pass NULL to ignore this parameter. (kSecAttrCanEncrypt, kSecAttrCanDecrypt, kSecAttrCanDerive, kSecAttrCanSign, kSecAttrCanVerify, kSecAttrCanWrap, kSecAttrCanUnwrap) + @param validIssuers (optional) An array of CFDataRef instances whose contents are the subject names of allowable issuers, as returned by a call to SSLCopyDistinguishedNames (SecureTransport.h). Pass NULL if any issuer is allowed. + @param identity On return, a reference to the preferred identity, or NULL if none was found. You are responsible for releasing this reference by calling the CFRelease function. + @result An identity or NULL. if the preferred identity has not been set. Your code should then typically perform a search for possible identities using the SecItem APIs. + @discussion If a preferred identity has not been set for the supplied name, the returned identity reference will be NULL. Your code should then perform a search for possible identities, using the SecItemCopyMatching API. +*/ +SecIdentityRef SecIdentityCopyPreferred(CFStringRef name, CFArrayRef keyUsage, CFArrayRef validIssuers) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @function SecIdentitySetPreference + @abstract Sets the preferred identity for the specified name and key usage. + @param identity A reference to the identity which will be preferred. + @param name A string containing a URI, RFC822 email address, DNS hostname, or other name which uniquely identifies a service requiring this identity. + @param keyUsage A CSSM_KEYUSE key usage value, as defined in cssmtype.h. Pass 0 to specify any key usage. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This API is deprecated in 10.7. Please use the SecIdentitySetPreferred API instead. +*/ +OSStatus SecIdentitySetPreference(SecIdentityRef identity, CFStringRef name, CSSM_KEYUSE keyUsage) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/*! + @function SecIdentitySetPreferred + @abstract Sets the preferred identity for the specified name and key usage. + @param identity A reference to the identity which will be preferred. If NULL is passed, any existing preference for the specified name is cleared instead. + @param name A string containing a URI, RFC822 email address, DNS hostname, or other name which uniquely identifies a service requiring this identity. + @param keyUsage A CFArrayRef value, containing items defined in SecItem.h Pass NULL to specify any key usage. (kSecAttrCanEncrypt, kSecAttrCanDecrypt, kSecAttrCanDerive, kSecAttrCanSign, kSecAttrCanVerify, kSecAttrCanWrap, kSecAttrCanUnwrap) + @result A result code. See "Security Error Codes" (SecBase.h). +*/ +OSStatus SecIdentitySetPreferred(SecIdentityRef identity, CFStringRef name, CFArrayRef keyUsage) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @function SecIdentityCopySystemIdentity + @abstract Obtain the system-wide SecIdentityRef associated with + a specified domain. + @param domain Identifies the SecIdentityRef to be obtained, typically + in the form "com.apple.subdomain...". + @param idRef On return, the system SecIdentityRef assicated with + the specified domain. Caller must CFRelease this when + finished with it. + @param actualDomain (optional) The actual domain name of the + the returned identity is returned here. This + may be different from the requested domain. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion If no system SecIdentityRef exists for the specified + domain, a domain-specific alternate may be returned + instead, typically (but not exclusively) the + kSecIdentityDomainDefault SecIdentityRef. + */ +OSStatus SecIdentityCopySystemIdentity( + CFStringRef domain, + SecIdentityRef *idRef, + CFStringRef *actualDomain) /* optional */ + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/*! + @function SecIdentitySetSystemIdentity + @abstract Assign the supplied SecIdentityRef to the specified + domain. + @param domain Identifies the domain to which the specified + SecIdentityRef will be assigned. + @param idRef (optional) The identity to be assigned to the specified + domain. Pass NULL to delete a possible entry for the specified + domain; in this case, it is not an error if no identity + exists for the specified domain. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion The caller must be running as root. +*/ +OSStatus SecIdentitySetSystemIdentity( + CFStringRef domain, + SecIdentityRef idRef) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + + +/* + * Defined system identity domains. + */ + +/*! + @const kSecIdentityDomainDefault The system-wide default identity. + */ +extern const CFStringRef kSecIdentityDomainDefault __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/*! + @const kSecIdentityDomainKerberosKDC Kerberos KDC identity. +*/ +extern const CFStringRef kSecIdentityDomainKerberosKDC __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECIDENTITY_H_ */ diff --git a/Security/libsecurity_keychain/lib/SecIdentityPriv.h b/Security/libsecurity_keychain/lib/SecIdentityPriv.h new file mode 100644 index 00000000..161b65a8 --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecIdentityPriv.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SECURITY_SECIDENTITYPRIV_H_ +#define _SECURITY_SECIDENTITYPRIV_H_ + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! @function SecIdentityCreate + @abstract create a new identity object from the provided certificate and its associated private key. + @param allocator CFAllocator to allocate the identity object. Pass NULL to use the default allocator. + @param certificate A certificate reference. + @param privateKey A private key reference. + @result An identity reference. +*/ +SecIdentityRef SecIdentityCreate( + CFAllocatorRef allocator, + SecCertificateRef certificate, + SecKeyRef privateKey) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); + +/*! + @function SecIdentityCompare + @abstract Compares two SecIdentityRef instances for equality. + @param identity1 An identity reference. + @param identity2 An identity reference. + @param compareOptions A value containing option flags. Currently there are no compare options, so 0 should be passed for this parameter. + @result An enumerated value of type CFComparisonResult. See CFBase.h. + @discussion Two identities are considered equal if they contain identical certificate and private key components. + @deprecated in Mac OS X 10.5 and later; the CFEqual function should be used instead (CFBase.h). +*/ +CFComparisonResult SecIdentityCompare( + SecIdentityRef identity1, + SecIdentityRef identity2, + CFOptionFlags compareOptions) + DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER; + +/*! + @function SecIdentityFindPreferenceItem + @abstract Returns an identity preference item, given an identity string. + @param keychainOrArray A reference to an array of keychains to search, a single keychain, or NULL to search the user's default keychain search list. + @param idString A string containing a URI, hostname, or email (RFC822) address. + @param itemRef On return, a reference to the keychain item which was found. The caller is responsible for releasing this reference. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion An identity preference item maps a particular identity to a string, such as a URI or email address. It specifies that this identity should be preferred in transactions which match the provided string. + @deprecated in Mac OS X 10.7 and later; use SecIdentityCopyPreferred() instead (SecIdentity.h) + + WARNING: This function is based on an implementation detail and will go away + in a future release; its use should be avoided at all costs. It does not + provide a way to find a preference item based on key usage, and it can only + find preferences which are stored as keychain items, so it may fail to find + the item you expect. Please use the public API functions to manipulate + identity preferences. +*/ +OSStatus SecIdentityFindPreferenceItem( + CFTypeRef keychainOrArray, + CFStringRef idString, + SecKeychainItemRef *itemRef) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/*! + @function SecIdentityAddPreferenceItem + @abstract Adds a new identity preference item to the specified keychain. + @param keychainRef A reference to the keychain in which to store the preference item. Pass NULL to specify the user's default keychain. + @param identityRef An identity reference. + @param idString A string containing a URI, hostname, or email (RFC822) address. + @param itemRef On return, a reference to the new keychain item. The caller is responsible for releasing this reference. Pass NULL if the reference is not needed. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion An identity preference item maps a particular identity to a string, such as a URI or email address. It specifies that this identity should be preferred in transactions which match the provided string. + @deprecated in Mac OS X 10.5; use SecIdentitySetPreference() instead (SecIdentity.h). +*/ +OSStatus SecIdentityAddPreferenceItem( + SecKeychainRef keychainRef, + SecIdentityRef identityRef, + CFStringRef idString, + SecKeychainItemRef *itemRef) + DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER; + +/*! + @function SecIdentityUpdatePreferenceItem + @abstract Given an existing identity preference keychain item, update it with the provided identity. + @param itemRef An identity preference keychain item, as returned by SecIdentityFindPreferenceItem or SecIdentityAddPreferenceItem. + @param identityRef An identity reference. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is used to update an existing preference item when a different identity is preferred. + @deprecated in Mac OS X 10.5; use SecIdentitySetPreference() instead (SecIdentity.h). +*/ +OSStatus SecIdentityUpdatePreferenceItem( + SecKeychainItemRef itemRef, + SecIdentityRef identityRef) + DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER; + +/*! + @function SecIdentityCopyFromPreferenceItem + @abstract Given an existing identity preference keychain item, obtain a SecIdentityRef for the identity it specifies. + @param itemRef An identity preference keychain item, as returned by SecIdentityFindPreferenceItem or SecIdentityAddPreferenceItem. + @param identityRef On return, an identity reference. The caller is responsible for releasing this reference. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is used to obtain a SecIdentityRef from an existing preference item. + @deprecated in Mac OS X 10.5; use SecIdentityCopyPreference() instead (SecIdentity.h). +*/ +OSStatus SecIdentityCopyFromPreferenceItem( + SecKeychainItemRef itemRef, + SecIdentityRef *identityRef) + DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER; + +/*! + @function ConvertArrayToKeyUsage + @abstract Given an array of key usages defined in SecItem.h return the equivalent CSSM_KEYUSE + @param usage An CFArrayRef containing CFTypeRefs defined in SecItem.h + kSecAttrCanEncrypt, + kSecAttrCanDecrypt, + kSecAttrCanDerive, + kSecAttrCanSign, + kSecAttrCanVerify, + kSecAttrCanWrap, + kSecAttrCanUnwrap + If the CFArrayRef is NULL then the CSSM_KEYUSAGE will be CSSM_KEYUSE_ANY + @result A CSSM_KEYUSE. Derived from the passed in Array +*/ +CSSM_KEYUSE ConvertArrayToKeyUsage(CFArrayRef usage); + + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECIDENTITYPRIV_H_ */ diff --git a/libsecurity_keychain/lib/SecIdentitySearch.cpp b/Security/libsecurity_keychain/lib/SecIdentitySearch.cpp similarity index 97% rename from libsecurity_keychain/lib/SecIdentitySearch.cpp rename to Security/libsecurity_keychain/lib/SecIdentitySearch.cpp index 890f380f..a918a14d 100644 --- a/libsecurity_keychain/lib/SecIdentitySearch.cpp +++ b/Security/libsecurity_keychain/lib/SecIdentitySearch.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecIdentitySearch.h b/Security/libsecurity_keychain/lib/SecIdentitySearch.h similarity index 98% rename from libsecurity_keychain/lib/SecIdentitySearch.h rename to Security/libsecurity_keychain/lib/SecIdentitySearch.h index 7fb6e036..95f5c9c4 100644 --- a/libsecurity_keychain/lib/SecIdentitySearch.h +++ b/Security/libsecurity_keychain/lib/SecIdentitySearch.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecIdentitySearchPriv.h b/Security/libsecurity_keychain/lib/SecIdentitySearchPriv.h similarity index 98% rename from libsecurity_keychain/lib/SecIdentitySearchPriv.h rename to Security/libsecurity_keychain/lib/SecIdentitySearchPriv.h index 2893b931..edf27f14 100644 --- a/libsecurity_keychain/lib/SecIdentitySearchPriv.h +++ b/Security/libsecurity_keychain/lib/SecIdentitySearchPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecImport.cpp b/Security/libsecurity_keychain/lib/SecImport.cpp similarity index 99% rename from libsecurity_keychain/lib/SecImport.cpp rename to Security/libsecurity_keychain/lib/SecImport.cpp index df3fa5f4..3a135656 100644 --- a/libsecurity_keychain/lib/SecImport.cpp +++ b/Security/libsecurity_keychain/lib/SecImport.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ * * SecImport.cpp - high-level facility for importing Sec layer objects. diff --git a/Security/libsecurity_keychain/lib/SecImportExport.c b/Security/libsecurity_keychain/lib/SecImportExport.c new file mode 100644 index 00000000..47ed119f --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecImportExport.c @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2007-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include "SecInternal.h" + +//#include +#include + +//#include "p12import.h" +#include "SecImportExport.h" + +CFStringRef kSecImportExportPassphrase = CFSTR("passphrase"); +CFStringRef kSecImportExportKeychain = CFSTR("keychain"); +CFStringRef kSecImportExportAccess = CFSTR("access"); + +CFStringRef kSecImportItemLabel = CFSTR("label"); +CFStringRef kSecImportItemKeyID = CFSTR("keyid"); +CFStringRef kSecImportItemTrust = CFSTR("trust"); +CFStringRef kSecImportItemCertChain = CFSTR("chain"); +CFStringRef kSecImportItemIdentity = CFSTR("identity"); + +#if 0 +static void collect_certs(const void *key, const void *value, void *context) +{ + if (!CFDictionaryContainsKey(value, CFSTR("key"))) { + CFDataRef cert_bytes = CFDictionaryGetValue(value, CFSTR("cert")); + if (!cert_bytes) + return; + SecCertificateRef cert = + SecCertificateCreateWithData(kCFAllocatorDefault, cert_bytes); + if (!cert) + return; + CFMutableArrayRef cert_array = (CFMutableArrayRef)context; + CFArrayAppendValue(cert_array, cert); + CFRelease(cert); + } +} + +typedef struct { + CFMutableArrayRef identities; + CFArrayRef certs; +} build_trust_chains_context; + +static void build_trust_chains(const void *key, const void *value, + void *context) +{ + CFMutableDictionaryRef identity_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, + 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + SecKeyRef private_key = NULL; + SecCertificateRef cert = NULL; + SecIdentityRef identity = NULL; + SecPolicyRef policy = NULL; + CFMutableArrayRef cert_chain = NULL, eval_chain = NULL; + SecTrustRef trust = NULL; + build_trust_chains_context * a_build_trust_chains_context = (build_trust_chains_context*)context; + + CFDataRef key_bytes = CFDictionaryGetValue(value, CFSTR("key")); + if(!key_bytes) goto out; //require(key_bytes, out); + CFDataRef cert_bytes = CFDictionaryGetValue(value, CFSTR("cert")); + if(!cert_bytes) goto out; //require(cert_bytes, out); + + /* p12import only passes up rsa keys */ +//FIXME: needs SecKeyCreateRSAPrivateKey implementation +//#if 0 +// private_key = SecKeyCreateRSAPrivateKey(kCFAllocatorDefault, +// CFDataGetBytePtr(key_bytes), CFDataGetLength(key_bytes), +// kSecKeyEncodingPkcs1); +//#endif + if(!private_key) goto out; //require(private_key, out); + cert = SecCertificateCreateWithData(kCFAllocatorDefault, cert_bytes); + if(!cert) goto out; //require(cert, out); + identity = SecIdentityCreate(kCFAllocatorDefault, cert, private_key); + if(!identity) goto out; //require(identity, out); + CFDictionarySetValue(identity_dict, kSecImportItemIdentity, identity); + + eval_chain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + if(!eval_chain) goto out; //require(eval_chain, out); + CFArrayAppendValue(eval_chain, cert); + CFRange all_certs = { 0, CFArrayGetCount(a_build_trust_chains_context->certs) }; + CFArrayAppendArray(eval_chain, a_build_trust_chains_context->certs, all_certs); + policy = SecPolicyCreateBasicX509(); + if(!policy) goto out; //require(policy, out); + SecTrustResultType result; + SecTrustCreateWithCertificates(eval_chain, policy, &trust); + if(!trust) goto out; //require(trust, out); + SecTrustEvaluate(trust, &result); + CFDictionarySetValue(identity_dict, kSecImportItemTrust, trust); + + cert_chain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + if(!cert_chain) goto out; //require(cert_chain, out); + CFIndex cert_chain_length = SecTrustGetCertificateCount(trust); + int i; + for (i = 0; i < cert_chain_length; i++) + CFArrayAppendValue(cert_chain, SecTrustGetCertificateAtIndex(trust, i)); + CFDictionarySetValue(identity_dict, kSecImportItemCertChain, cert_chain); + + CFArrayAppendValue(a_build_trust_chains_context->identities, identity_dict); +out: + CFReleaseSafe(identity_dict); + CFReleaseSafe(identity); + CFReleaseSafe(private_key); + CFReleaseSafe(cert); + CFReleaseSafe(policy); + CFReleaseSafe(cert_chain); + CFReleaseSafe(eval_chain); + CFReleaseSafe(trust); +} +#endif // if 0 + +OSStatus SecPKCS12Import(CFDataRef pkcs12_data, CFDictionaryRef options, CFArrayRef *items) +{ + // SecPKCS12Import is implemented on Mac OS X in terms of the existing + // SecKeychainItemImport API, which supports importing items into a + // specified keychain with initial access control settings for keys. + // + OSStatus status = errSecSuccess; + SecExternalFormat inputFormat = kSecFormatPKCS12; + SecExternalItemType itemType = kSecItemTypeAggregate; + SecItemImportExportFlags flags = 0; /* don't know if it's PEM armoured */ + SecKeyImportExportParameters keyParams; /* filled in below... */ + SecKeychainRef importKeychain = NULL; + SecAccessRef importAccess = NULL; + CFStringRef importPassword = NULL; + CFArrayRef tmpItems = NULL; /* items returned by SecKeychainItemImport */ + CFMutableArrayRef certs = NULL; /* certificates imported by this function */ + CFMutableArrayRef identities = NULL; /* items returned by this function */ + + if (options) { + importKeychain = (SecKeychainRef) CFDictionaryGetValue(options, kSecImportExportKeychain); + if (importKeychain) + CFRetain(importKeychain); + importAccess = (SecAccessRef) CFDictionaryGetValue(options, kSecImportExportAccess); + if (importAccess) + CFRetain(importAccess); + importPassword = (CFStringRef) CFDictionaryGetValue(options, kSecImportExportPassphrase); + if (importPassword) + CFRetain(importPassword); + } + + if (!importKeychain) { + // SecKeychainItemImport requires a keychain, so use default + status = SecKeychainCopyDefault(&importKeychain); + } + + memset(&keyParams, 0, sizeof(SecKeyImportExportParameters)); + keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; + keyParams.passphrase = importPassword; + keyParams.accessRef = importAccess; + + status = SecKeychainItemImport(pkcs12_data, + NULL, /* no filename */ + &inputFormat, + &itemType, + flags, + &keyParams, + importKeychain, + &tmpItems); + + // build an array of all non-identity certificates which were imported + if (!status) { + certs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFIndex i, count = CFArrayGetCount(tmpItems); + for (i=0; iKeyData.Data, (CC_LONG)cssmKey->KeyData.Length, &hash[0]); + CFDataRef digest = CFDataCreate(NULL, (const UInt8 *)hash, CC_SHA1_DIGEST_LENGTH); + if (digest) { + CFDictionaryAddValue(itemDict, kSecImportItemKeyID, digest); + CFRelease(digest); + } + } + CFRelease(itemKey); + } + } + + // trust + SecTrustRef trust = NULL; + SecPolicyRef policy = SecPolicyCreateBasicX509(); + CFMutableArrayRef certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(certArray, itemCert); + if (certs) { + CFArrayAppendArray(certArray, certs, CFRangeMake(0, CFArrayGetCount(certs))); + } + status = SecTrustCreateWithCertificates(certArray, policy, &trust); + if (policy) { + CFRelease(policy); + } + if (trust) { + CFDictionaryAddValue(itemDict, kSecImportItemTrust, trust); + CFRelease(trust); + } + + // certificate chain + if (certArray) { + CFDictionaryAddValue(itemDict, kSecImportItemCertChain, certArray); + CFRelease(certArray); + } + + // identity + CFDictionaryAddValue(itemDict, kSecImportItemIdentity, anItem); + + if (itemCert) + CFRelease(itemCert); + CFArrayAppendValue(identities, itemDict); + CFRelease(itemDict); + } + } + } + + if (items) + *items = identities; + else if (identities) + CFRelease(identities); + + if (certs) + CFRelease(certs); + if (tmpItems) + CFRelease(tmpItems); + if (importKeychain) + CFRelease(importKeychain); + if (importAccess) + CFRelease(importAccess); + if (importPassword) + CFRelease(importPassword); + + return status; + +//FIXME: needs SecAsn1Coder implementation +#if 0 + pkcs12_context context = {}; + SecAsn1CoderCreate(&context.coder); + if (options) + context.passphrase = CFDictionaryGetValue(options, kSecImportExportPassphrase); + context.items = CFDictionaryCreateMutable(kCFAllocatorDefault, + 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + int status = p12decode(&context, pkcs12_data); + if (!status) { + CFMutableArrayRef certs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFDictionaryApplyFunction(context.items, collect_certs, certs); + + CFMutableArrayRef identities = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + build_trust_chains_context a_build_trust_chains_context = { identities, certs }; + CFDictionaryApplyFunction(context.items, build_trust_chains, &a_build_trust_chains_context); + CFReleaseSafe(certs); + + /* ignoring certs that weren't picked up as part of the certchain for found keys */ + + *items = identities; + } + + CFReleaseSafe(context.items); + SecAsn1CoderRelease(context.coder); + + switch (status) { + case p12_noErr: return errSecSuccess; + case p12_passwordErr: return errSecAuthFailed; + case p12_decodeErr: return errSecDecode; + default: return errSecInternal; + }; + return errSecSuccess; +#endif +} + diff --git a/Security/libsecurity_keychain/lib/SecImportExport.h b/Security/libsecurity_keychain/lib/SecImportExport.h new file mode 100644 index 00000000..404b04c9 --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecImportExport.h @@ -0,0 +1,681 @@ +/* + * Copyright (c) 2000-2011,2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecImportExport + contains import/export functionality for keys and certificates. +*/ +#ifndef _SECURITY_SEC_IMPORT_EXPORT_H_ +#define _SECURITY_SEC_IMPORT_EXPORT_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Supported import/export Formats + */ +enum +{ + /* + * When importing: unknown format + * When exporting: default format for item + */ + kSecFormatUnknown = 0, + + /* + * Public and Private Key formats. + * Default for export is kSecFormatOpenSSL. + */ + kSecFormatOpenSSL, /* a.k.a. X509 for public keys */ + kSecFormatSSH, /* OpenSSH v.1 */ + kSecFormatBSAFE, + + /* Symmetric Key Formats */ + kSecFormatRawKey, /* raw unformatted key bits; default */ + + /* Formats for wrapped symmetric and private keys */ + kSecFormatWrappedPKCS8, + kSecFormatWrappedOpenSSL, /* traditional openssl */ + kSecFormatWrappedSSH, /* OpenSSH v.1 */ + kSecFormatWrappedLSH, + + /* Formats for certificates */ + kSecFormatX509Cert, /* DER encoded; default */ + + /* Aggregate Types */ + kSecFormatPEMSequence, /* sequence of certs and/or keys, implies PEM + * armour. Default format for multiple items */ + kSecFormatPKCS7, /* sequence of certs */ + kSecFormatPKCS12, /* set of certs and private keys */ + kSecFormatNetscapeCertSequence, /* sequence of certs, form netscape-cert-sequence */ + + /* Added in Mac OS X 10.5 */ + kSecFormatSSHv2 /* OpenSSH v.2. Note that OpenSSH v2 private keys + * are in format kSecFormatOpenSSL or + * kSecFormatWrappedOpenSSL. */ +}; +typedef uint32_t SecExternalFormat; + +/* + * Indication of basic item type when importing. + */ +enum { + kSecItemTypeUnknown, /* caller doesn't know what this is */ + kSecItemTypePrivateKey, + kSecItemTypePublicKey, + kSecItemTypeSessionKey, + kSecItemTypeCertificate, + kSecItemTypeAggregate /* PKCS7, PKCS12, kSecFormatPEMSequence, etc. */ +}; +typedef uint32_t SecExternalItemType; + +/* + * Flags passed to SecKeychainItemExport() and SecKeychainItemImport(). + */ +enum +{ + kSecItemPemArmour = 0x00000001, /* exported blob is PEM formatted */ +}; +typedef uint32_t SecItemImportExportFlags; + +/* + * SecKeyRef-specific flags, specified in SecKeyImportExportParameters.flags + */ +enum +{ + /* + * When true, prevents the importing of more than one private key + * in a given SecKeychainItemImport(). + */ + kSecKeyImportOnlyOne = 0x00000001, + + /* + * When true, passphrase for import/export is obtained by user prompt + * instead of by caller-supplied data (SecKeyImportExportParameters.passphrase). + * This is the preferred method for obtaining a user-supplied passphrase + * as it avoids having the cleartext passphrase appear in the app's + * address space at any time. + */ + kSecKeySecurePassphrase = 0x00000002, + + /* + * When true, imported private keys will have no Access Control List + * (ACL) attached to them. In the absence of both this bit and the accessRef + * field in SecKeyImportExportParameters (see below), imported private + * keys are given a default ACL. + */ + kSecKeyNoAccessControl = 0x00000004 +}; +typedef uint32_t SecKeyImportExportFlags; + +/* + * Version of a SecKeyImportExportParameters. + */ +#define SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION 0 + +/* + * Parameters specific to SecKeyRefs. + */ +typedef struct +{ + /* for import and export */ + uint32_t version; /* SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION */ + SecKeyImportExportFlags flags; /* SecKeyImportExportFlags bits */ + CFTypeRef passphrase; /* kSecFormatPKCS12, kSecFormatWrapped* + * formats only. Legal types are + * CFStringRef and CFDataRef. */ + CFStringRef alertTitle; /* title of secure passphrase alert panel */ + CFStringRef alertPrompt; /* prompt in secure passphrase alert panel */ + + /* for import only */ + SecAccessRef accessRef; /* specifies the initial ACL of imported + * key(s) */ + CSSM_KEYUSE keyUsage; /* CSSM_KEYUSE_DECRYPT, CSSM_KEYUSE_SIGN, + * etc. */ + CSSM_KEYATTR_FLAGS keyAttributes; /* CSSM_KEYATTR_PERMANENT, etc. */ +} SecKeyImportExportParameters; + + +typedef struct +{ + /* for import and export */ + uint32_t version; /* SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION */ + SecKeyImportExportFlags flags; /* SecKeyImportExportFlags bits */ + CFTypeRef passphrase; /* kSecFormatPKCS12, kSecFormatWrapped* + * formats only. Legal types are + * CFStringRef and CFDataRef. */ + CFStringRef alertTitle; /* title of secure passphrase alert panel */ + CFStringRef alertPrompt; /* prompt in secure passphrase alert panel */ + + /* for import only */ + SecAccessRef accessRef; /* specifies the initial ACL of imported + * key(s) */ + CFArrayRef keyUsage; /* An Array containing usage attributes from SecItem.h, e.g. + kSecAttrCanEncrypt;, kSecAttrCanDecrypt, kSecAttrCanDerive, etc. + */ + + CFArrayRef keyAttributes; /* An array containing zero or more key attributes + for an imported key. Possible values (from SecItem.h): + kSecAttrIsPermanent, kSecAttrIsSensitive, kSecAttrIsExtractable + Pass NULL in this field to use default attributes: + - kSecAttrIsPermanent if a keychain is specified + - kSecAttrIsSensitive for private keys + - kSecAttrIsExtractable by default + */ +} SecItemImportExportKeyParameters; + +/* + * SecKeychainItemExport() + * + * This function takes one or more SecKeychainItemRefs and creates an + * external representation of the item(s) in the form of a CFDataRef. + * Caller specifies the format of the external representation via a + * SecExternalFormat enum. Caller may specify kSecFormatUnknown for + * the format, in which case a the default format for the item + * being exported is used (as described in the SecExternalFormat enums). + * PEM armouring is optional and is specified by the kSecItemPemArmour + * flag in importFlags. + * + * If exactly one item is to be exported, the keychainItemOrArray argument + * can be a SecKeychainItem. Otherwise this argument is a CFArrayRef + * containing a number of SecKeychainItems. + * + * The exported item(s) is (are) returned to the caller via the + * CFDataRef *exportedData argument. Caller must CFRelease the result. + * + * The following SecKeychainItems may be exported: + * + * SecCertificateRef + * SecKeyRef + * SecIdentityRef + * + * + * Key-related SecKeyImportExportParameters fields + * ----------------------------------------------- + * + * When exporting SecKeyRefs in one of the wrapped formats + * (kSecFormatWrappedOpenSSL, kSecFormatWrappedSSH, + * kSecFormatWrappedPKCS8), or in PKCS12 format, caller must + * either explicitly specify the passphrase field or set + * the kSecKeySecurePassphrase bit in SecKeyImportExportFlags. + * + * If kSecKeySecurePassphrase is selected, caller can optionally + * specify strings for the passphrase panel's title bar and for + * the prompt which appears in the panel via the alertTitle and + * alertPrompt fields in SecKeyImportExportParameters. + * + * If an explicit passphrase is specified, note that PKCS12 + * explicitly requires that passphrases are in Unicode format; + * passing in a CFStringRef as the passphrase is the safest way + * to ensure that this requirement is met (and that the result + * will be compatible with other implementations). If a CFDataRef + * is supplied as the passphrase for a PKCS12 export operation, + * the referent data is assumed to be in UTF8 form and will be + * converted as appropriate. + * + * If no key items are being exported, the keyParams argument may be NULL. + * @discussion This API has been deprecated. Please us the SecItemExport API instead. + */ +OSStatus SecKeychainItemExport( + CFTypeRef keychainItemOrArray, + SecExternalFormat outputFormat, + SecItemImportExportFlags flags, /* kSecItemPemArmor, etc. */ + const SecKeyImportExportParameters *keyParams, /* optional */ + CFDataRef *exportedData) /* external representation returned here */ + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* + * SecItemExport() + * + * This function takes one or more SecItemRefs and creates an + * external representation of the item(s) in the form of a CFDataRef. + * Caller specifies the format of the external representation via a + * SecExternalFormat enum. Caller may specify kSecFormatUnknown for + * the format, in which case a the default format for the item + * being exported is used (as described in the SecExternalFormat enums). + * PEM armouring is optional and is specified by the kSecItemPemArmour + * flag in importFlags. + * + * If exactly one item is to be exported, the keychainItemOrArray argument + * can be a SecKeychainItem. Otherwise this argument is a CFArrayRef + * containing a number of SecKeychainItems. + * + * The exported item(s) is (are) returned to the caller via the + * CFDataRef *exportedData argument. Caller must CFRelease the result. + * + * The following SecKeychainItems may be exported: + * + * SecCertificateRef + * SecKeyRef + * SecIdentityRef + * + * + * Key-related SecItemExport fields + * ----------------------------------------------- + * + * When exporting SecKeyRefs in one of the wrapped formats + * (kSecFormatWrappedOpenSSL, kSecFormatWrappedSSH, + * kSecFormatWrappedPKCS8), or in PKCS12 format, caller must + * either explicitly specify the passphrase field or set + * the kSecKeySecurePassphrase bit in SecKeyImportExportFlags. + * + * If kSecKeySecurePassphrase is selected, caller can optionally + * specify strings for the passphrase panel's title bar and for + * the prompt which appears in the panel via the alertTitle and + * alertPrompt fields in SecItemImportExportKeyParameters. + * + * If an explicit passphrase is specified, note that PKCS12 + * explicitly requires that passphrases are in Unicode format; + * passing in a CFStringRef as the passphrase is the safest way + * to ensure that this requirement is met (and that the result + * will be compatible with other implementations). If a CFDataRef + * is supplied as the passphrase for a PKCS12 export operation, + * the referent data is assumed to be in UTF8 form and will be + * converted as appropriate. + * + * If no key items are being exported, the keyParams argument may be NULL. + * + */ +OSStatus SecItemExport( + CFTypeRef secItemOrArray, + SecExternalFormat outputFormat, + SecItemImportExportFlags flags, /* kSecItemPemArmor, etc. */ + const SecItemImportExportKeyParameters *keyParams, /* optional */ + CFDataRef *exportedData) /* external representation returned here */ + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +/* + * SecKeychainItemImport() + * + * This function takes a CFDataRef containing the external representation + * of one or more objects and creates SecKeychainItems corresponding to + * those objects and optionally imports those SecKeychainItems into a + * specified keychain. The format of the incoming representation is + * specified by one or more of the following: + * + * -- A SecExternalFormat. This optional in/out argument is used when + * the caller knows exactly what format the external representation + * is in. It's also used to return to the caller the format which the + * function actually determines the external representation to be in. + * A value of kSecFormatUnknown is specified on entry when the caller + * wishes to know the inferred format on return. + * + * -- A SecExternalItemType - optional, in/out. Used to specify what kind + * of item is in the incoming representation, if known by the caller. + * It's also used to return to the caller the item type which the + * function actually determines the external representation to contain. + * A value of kSecItemTypeUnknown is specified on entry when the caller + * wishes to know the inferred item type on return. + * + * -- fileNameOrExtension, a CFStringRef. This optional argument contains + * the name of the file from which the external representation was + * obtained; it can also be simply an extension like CFSTR(".p7r"). + * This is a convenience for apps like KeychainAccess which can import a + * number of different formats. + * + * The SecKeychainItemImport() call does its best to figure out what is + * in an incoming external item given the info provided by the above three + * arguments. In most cases, SecKeychainItemImport() can even figure out + * what's in an external item if none of these are specified, but it would + * be unwise for an application to count on that ability. + * + * PEM formatting is determined internally via inspection of the incoming + * data, so the kSecItemPemArmuor in the flags field is ignored. + * + * Zero, one, or both of the following occurs upon successful completion + * of this function: + * + * -- The imported item(s) is (are) imported to the specified importKeychain. + * If importKeychain is NULL, this step does not occur. + * + * -- The imported item(s) is (are) returned to the caller via the + * CFArrayRef *outItems argument. If outItems is NULL, this step + * does not occur. If outItems is NON-NULL, then *outItems will be + * a CFArrayRef containing a number of SecKeychainItems upon return. + * Caller must CFRelease the result. + * + * The possible types of returned SecKeychainItems are: + * + * SecCertificateRef + * SecKeyRef + * SecIdentityRef + * + * Note that when importing a PKCS12 blob, typically one SecIdentityRef + * and zero or more additional SecCertificateRefs are returned in + * outItems. No SecKeyRefs will appear there unless a key + * is found in the incoming blob with does not have a matching + * certificate. + * + * A typical case in which an app specifies the outItems + * argument and a NULL for importKeychain is when the app wishes to + * perform some user interaction, perhaps on a per-item basis, before + * committing to actually import the item(s). In this case, if the app + * does wish to proceed with the import, the standard import calls + * (SecCertificateAddToKeychain(), SecKeyAddToKeychain (implementation + * TBD)) would be used. + * + * Passing in NULL for both outItems and importKeychain + * is a perfectly acceptable way of using this function to determine, + * in a non-intrusive way, what is inside a given data blob. No effect + * other than returning inputFormat and/or itemType occurs in this + * case. + + * + * Key-related SecKeyImportExportParameters fields + * ----------------------------------------------- + * + * If importKeychain is NULL, the kSecKeyImportOnlyOne bit in the flags + * argument is ignored. Otherwise, if the kSecKeyImportOnlyOne bit is set, and + * there is more than one key in the incoming external representation, no + * items will be imported to the specified keychain and errSecMultipleKeys will + * be returned. + * + * The accessRef field allows the caller to specify the initial SecAccessRef + * for imported private keys. If more than one private key is being imported, + * all private keys get the same initial SecAccessRef. If this field is NULL + * when private keys are being imported, then the ACL attached to imported + * private keys depends on the kSecKeyNoAccessControl bit in the specified + * keyParams->flags. If this bit is 0, or keyParams is NULL, the default ACL + * will be used. If this bit is 1, no ACL will be attached to imported + * private keys. + * + * keyUsage and keyAttributes specify the low-level usage and attribute flags + * of imported keys. Each is a word of bits. The default value for keyUsage + * (used when keyParams is NULL or if keyParams->keyUsage is zero) is + * CSSM_KEYUSE_ANY. The default value for keyAttributes defaults is + * CSSM_KEYATTR_SENSITIVE | CSSM_KEYATTR_EXTRACTABLE; the CSSM_KEYATTR_PERMANENT + * bit is also added to the default if a non-NULL importKeychain is provided. + * + * The following are valid bits in keyAttributes: + * + * CSSM_KEYATTR_PERMANENT + * CSSM_KEYATTR_SENSITIVE + * CSSM_KEYATTR_EXTRACTABLE + * + * If the CSSM_KEYATTR_PERMANENT is set then the importKeychain argument must + * be valid or errSecInvalidKeychain will be returned if in fact any keys are found + * in the external representation. + * + * Note that if the caller does not set the CSSM_KEYATTR_EXTRACTABLE, this key + * will never be able to be extracted from the keychain in any form, not even + * in wrapped form. The CSSM_KEYATTR_SENSITIVE indicates that the key can only + * be extracted in wrapped form. + * + * The CSSM_KEYATTR_RETURN_xxx bits are always forced to + * CSSM_KEYATTR_RETURN_REF regardless of the specified keyAttributes + * field. + * + * When importing SecKeyRefs in one of the wrapped formats + * (kSecFormatWrappedOpenSSL, kSecFormatWrappedSSH, + * kSecFormatWrappedPKCS8), or in PKCS12 format, caller must + * either explicitly specify the passphrase field or set + * the kSecKeySecurePassphrase bit in SecKeyImportExportFlags. + * + * If kSecKeySecurePassphrase is selected, caller can optionally + * specify strings for the passphrase panel's title bar and for + * the prompt which appears in the panel via the alertTitle and + * alertPrompt fields in SecKeyImportExportParameters. + * + * If an explicit passphrase is specified, note that PKCS12 + * explicitly requires that passphrases are in Unicode format; + * passing in a CFStringRef as the passphrase is the safest way + * to ensure that this requirement is met (and that the result + * will be compatible with other implementations). If a CFDataRef + * is supplied as the passphrase for a PKCS12 export operation, + * the referent data is assumed to be in UTF8 form and will be + * converted as appropriate. + + * If no key items are being imported, the keyParams argument may be NULL. + * + * The SecItemImportExportFlags argument is currently unused; caller should pass + * in 0. + * + * @discussion This API has been deprecated. Please use the SecItemImport API instead. + */ +OSStatus SecKeychainItemImport( + CFDataRef importedData, + CFStringRef fileNameOrExtension, /* optional */ + SecExternalFormat *inputFormat, /* optional, IN/OUT */ + SecExternalItemType *itemType, /* optional, IN/OUT */ + SecItemImportExportFlags flags, + const SecKeyImportExportParameters *keyParams, /* optional */ + SecKeychainRef importKeychain, /* optional */ + CFArrayRef *outItems) /* optional */ + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/* + * SecItemImport() + * + * This function takes a CFDataRef containing the external representation + * of one or more objects and creates SecKeychainItems corresponding to + * those objects and optionally imports those SecKeychainItems into a + * specified keychain. The format of the incoming representation is + * specified by one or more of the following: + * + * -- A SecExternalFormat. This optional in/out argument is used when + * the caller knows exactly what format the external representation + * is in. It's also used to return to the caller the format which the + * function actually determines the external representation to be in. + * A value of kSecFormatUnknown is specified on entry when the caller + * wishes to know the inferred format on return. + * + * -- A SecExternalItemType - optional, in/out. Used to specify what kind + * of item is in the incoming representation, if known by the caller. + * It's also used to return to the caller the item type which the + * function actually determines the external representation to contain. + * A value of kSecItemTypeUnknown is specified on entry when the caller + * wishes to know the inferred item type on return. + * + * -- fileNameOrExtension, a CFStringRef. This optional argument contains + * the name of the file from which the external representation was + * obtained; it can also be simply an extension like CFSTR(".p7r"). + * This is a convenience for apps like KeychainAccess which can import a + * number of different formats. + * + * The SecItemImport() call does its best to figure out what is + * in an incoming external item given the info provided by the above three + * arguments. In most cases, SecItemImport() can even figure out + * what's in an external item if none of these are specified, but it would + * be unwise for an application to count on that ability. + * + * PEM formatting is determined internally via inspection of the incoming + * data, so the kSecItemPemArmuor in the flags field is ignored. + * + * Zero, one, or both of the following occurs upon successful completion + * of this function: + * + * -- The imported item(s) is (are) imported to the specified importKeychain. + * If importKeychain is NULL, this step does not occur. + * + * -- The imported item(s) is (are) returned to the caller via the + * CFArrayRef *outItems argument. If outItems is NULL, this step + * does not occur. If outItems is NON-NULL, then *outItems will be + * a CFArrayRef containing a number of SecKeychainItems upon return. + * Caller must CFRelease the result. + * + * The possible types of returned SecKeychainItems are: + * + * SecCertificateRef + * SecKeyRef + * SecIdentityRef + * + * Note that when importing a PKCS12 blob, typically one SecIdentityRef + * and zero or more additional SecCertificateRefs are returned in + * outItems. No SecKeyRefs will appear there unless a key + * is found in the incoming blob with does not have a matching + * certificate. + * + * A typical case in which an app specifies the outItems + * argument and a NULL for importKeychain is when the app wishes to + * perform some user interaction, perhaps on a per-item basis, before + * committing to actually import the item(s). In this case, if the app + * does wish to proceed with the import, the standard import calls + * (SecCertificateAddToKeychain(), SecKeyAddToKeychain (implementation + * TBD)) would be used. + * + * Passing in NULL for both outItems and importKeychain + * is a perfectly acceptable way of using this function to determine, + * in a non-intrusive way, what is inside a given data blob. No effect + * other than returning inputFormat and/or itemType occurs in this + * case. + + * + * Key-related SecItemImportExportKeyParameters fields + * ----------------------------------------------- + * + * If importKeychain is NULL, the kSecKeyImportOnlyOne bit in the flags + * argument is ignored. Otherwise, if the kSecKeyImportOnlyOne bit is set, and + * there is more than one key in the incoming external representation, no + * items will be imported to the specified keychain and errSecMultipleKeys will + * be returned. + * + * The accessRef field allows the caller to specify the initial SecAccessRef + * for imported private keys. If more than one private key is being imported, + * all private keys get the same initial SecAccessRef. If this field is NULL + * when private keys are being imported, then the ACL attached to imported + * private keys depends on the kSecKeyNoAccessControl bit in the specified + * keyParams->flags. If this bit is 0, or keyParams is NULL, the default ACL + * will be used. If this bit is 1, no ACL will be attached to imported + * private keys. + * + * keyUsage and keyAttributes specify the low-level usage and attribute flags + * of imported keys. These fields contain a CFArray whose values are constants + * from SecItem.h. + * + * Possible values in the keyUsage array: + * + * kSecAttrCanEncrypt + * kSecAttrCanDecrypt + * kSecAttrCanDerive + * kSecAttrCanSign + * kSecAttrCanVerify + * kSecAttrCanWrap + * kSecAttrCanUnwrap + * + * If keyUsage is set to NULL, then any key usage is permitted. + * + * Possible values in the keyAttributes array: + * + * kSecAttrIsPermanent + * kSecAttrIsSensitive + * kSecAttrIsExtractable + * + * If keyAttributes is set to NULL, then default values are used: + * kSecAttrIsPermanent if an import keychain is specified + * kSecAttrIsSensitive for non-public keys + * kSecAttrIsExtractable + * + * If the kSecAttrIsPermanent attribute is set, then the + * importKeychain argument must be valid or errSecInvalidKeychain + * will be returned even if keys were able to be imported. + * + * Note that if the caller provides a keyAttributes array but + * does not set kSecAttrIsExtractable, this key will never be + * able to be extracted from the keychain in any form, not even + * in wrapped form. kSecAttrIsSensitive indicates that the key + * can only be extracted in wrapped form. + * + * When importing SecKeyRefs in one of the wrapped formats + * (kSecFormatWrappedOpenSSL, kSecFormatWrappedSSH, + * kSecFormatWrappedPKCS8), or in PKCS12 format, caller must + * either explicitly specify the passphrase field or set + * the kSecKeySecurePassphrase bit in SecKeyImportExportFlags. + * + * If kSecKeySecurePassphrase is selected, caller can optionally + * specify strings for the passphrase panel's title bar and for + * the prompt which appears in the panel via the alertTitle and + * alertPrompt fields in SecItemImportExportKeyParameters. + * + * If an explicit passphrase is specified, note that PKCS12 + * explicitly requires that passphrases are in Unicode format; + * passing in a CFStringRef as the passphrase is the safest way + * to ensure that this requirement is met (and that the result + * will be compatible with other implementations). If a CFDataRef + * is supplied as the passphrase for a PKCS12 export operation, + * the referent data is assumed to be in UTF8 form and will be + * converted as appropriate. + + * If no key items are being imported, the keyParams argument may be NULL. + * + * The SecItemImportExportFlags argument is currently unused; caller should pass + * in 0. + */ + +OSStatus SecItemImport( + CFDataRef importedData, + CFStringRef fileNameOrExtension, /* optional */ + SecExternalFormat *inputFormat, /* optional, IN/OUT */ + SecExternalItemType *itemType, /* optional, IN/OUT */ + SecItemImportExportFlags flags, + const SecItemImportExportKeyParameters *keyParams, /* optional */ + SecKeychainRef importKeychain, /* optional */ + CFArrayRef *outItems) /* optional */ + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +/*! + @enum Import/Export options + @discussion Predefined key constants used when passing dictionary-based arguments to import/export functions. + @constant kSecImportExportPassphrase Specifies a passphrase represented by a CFStringRef to be used when exporting to (or importing from) PKCS#12 format. + @constant kSecImportExportKeychain Specifies a keychain represented by a SecKeychainRef to be used as the target when importing from PKCS#12 format. + @constant kSecImportExportAccess Specifies an access represented by a SecAccessRef for the initial access (ACL) of a key imported from PKCS#12 format. +*/ +extern CFStringRef kSecImportExportPassphrase; +extern CFStringRef kSecImportExportKeychain; +extern CFStringRef kSecImportExportAccess; + +/*! + @enum Import/Export item description + @discussion Predefined key constants used by functions which return a CFArray with a CFDictionary per item. + @constant kSecImportItemLabel A CFStringRef representing the item label. This implementation specific identifier cannot be expected to have any format. + @constant kSecImportItemKeyID A CFDataRef representing the key id. Typically this is the SHA-1 digest of the public key. + @constant kSecImportItemIdentity A SecIdentityRef representing the identity. + @constant kSecImportItemTrust A SecTrustRef set up with all relevant certificates. Not guaranteed to succesfully evaluate. + @constant kSecImportItemCertChain A CFArrayRef holding all relevant certificates for this item's identity. +*/ +extern CFStringRef kSecImportItemLabel; +extern CFStringRef kSecImportItemKeyID; +extern CFStringRef kSecImportItemTrust; +extern CFStringRef kSecImportItemCertChain; +extern CFStringRef kSecImportItemIdentity; + +/*! + @function SecPKCS12Import + @abstract Imports the contents of a PKCS12 formatted blob. + @param pkcs12_data The PKCS12 data to be imported. + @param options A dictionary containing import options. A kSecImportExportPassphrase entry is required at minimum. Only password-based PKCS12 blobs are currently supported. + @param items On return, an array containing a dictionary for every item extracted. Use kSecImportItem constants to access specific elements of these dictionaries. Your code must CFRelease the array when it is no longer needed. + @result errSecSuccess in case of success. errSecDecode means either the blob can't be read or it is malformed. + errSecAuthFailed means an incorrect password was supplied, or data in the container is damaged. +*/ +OSStatus SecPKCS12Import(CFDataRef pkcs12_data, CFDictionaryRef options, CFArrayRef *items); + +#ifdef __cplusplus +} +#endif + +#endif /* _SECURITY_SEC_IMPORT_EXPORT_H_ */ diff --git a/libsecurity_keychain/lib/SecImportExportAgg.cpp b/Security/libsecurity_keychain/lib/SecImportExportAgg.cpp similarity index 99% rename from libsecurity_keychain/lib/SecImportExportAgg.cpp rename to Security/libsecurity_keychain/lib/SecImportExportAgg.cpp index 6440c796..cc1802c4 100644 --- a/libsecurity_keychain/lib/SecImportExportAgg.cpp +++ b/Security/libsecurity_keychain/lib/SecImportExportAgg.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecImportExportAgg.h b/Security/libsecurity_keychain/lib/SecImportExportAgg.h similarity index 97% rename from libsecurity_keychain/lib/SecImportExportAgg.h rename to Security/libsecurity_keychain/lib/SecImportExportAgg.h index 2d56ce41..ac38dcc1 100644 --- a/libsecurity_keychain/lib/SecImportExportAgg.h +++ b/Security/libsecurity_keychain/lib/SecImportExportAgg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecImportExportCrypto.cpp b/Security/libsecurity_keychain/lib/SecImportExportCrypto.cpp similarity index 92% rename from libsecurity_keychain/lib/SecImportExportCrypto.cpp rename to Security/libsecurity_keychain/lib/SecImportExportCrypto.cpp index d72d2e61..71a4b315 100644 --- a/libsecurity_keychain/lib/SecImportExportCrypto.cpp +++ b/Security/libsecurity_keychain/lib/SecImportExportCrypto.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. - * + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. + * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code @@ -62,8 +62,8 @@ #define SEC_SESSIONKEY_PRINT_NAME_ATTR_VALUE "Imported Key" /* - * Set private key's Label and PrintName attributes. On entry Label - * is typically a random string to faciliate finding the key in a DL; + * Set private key's Label and PrintName attributes. On entry Label + * is typically a random string to faciliate finding the key in a DL; * the PrintName is currently set to the same value by the DL. We * replace the Label attr with the public key hash and the PrintName * attr with a caller-supplied value. @@ -72,7 +72,7 @@ static CSSM_RETURN impExpSetKeyLabel( CSSM_CSP_HANDLE cspHand, // where the key lives CSSM_DL_DB_HANDLE dlDbHand, // ditto SecKeychainRef kcRef, // ditto - CSSM_KEY_PTR cssmKey, + CSSM_KEY_PTR cssmKey, const CSSM_DATA *existKeyLabel, // existing label, a random string const CSSM_DATA *newPrintName, CssmOwnedData &newLabel, // RETURNED as what we set @@ -80,25 +80,36 @@ static CSSM_RETURN impExpSetKeyLabel( { CSSM_RETURN crtn; CSSM_DATA keyDigest = {0, NULL}; - + crtn = impExpKeyDigest(cspHand, cssmKey, &keyDigest); if(crtn) { return crtn; } - + /* caller needs this for subsequent DL lookup */ newLabel.copy(keyDigest); /* Find this key as a SecKeychainItem */ - SecItemClass itemClass = (cssmKey->KeyHeader.KeyClass == - CSSM_KEYCLASS_PRIVATE_KEY) ? kSecPrivateKeyItemClass : - kSecPublicKeyItemClass; + SecItemClass itemClass; + switch (cssmKey->KeyHeader.KeyClass) { + case CSSM_KEYCLASS_PRIVATE_KEY: + itemClass = kSecPrivateKeyItemClass; + break; + case CSSM_KEYCLASS_PUBLIC_KEY: + itemClass = kSecPublicKeyItemClass; + break; + case CSSM_KEYCLASS_SESSION_KEY: + itemClass = kSecSymmetricKeyItemClass; + break; + default: + itemClass = (SecItemClass) 0; + } SecKeychainAttribute kcAttr = {kSecKeyLabel, (UInt32)existKeyLabel->Length, existKeyLabel->Data}; SecKeychainAttributeList kcAttrList = {1, &kcAttr}; SecKeychainSearchRef srchRef = NULL; OSStatus ortn; SecKeychainItemRef itemRef = NULL; - + ortn = SecKeychainSearchCreateFromAttributes(kcRef, itemClass, &kcAttrList, &srchRef); if(ortn) { @@ -120,7 +131,7 @@ static CSSM_RETURN impExpSetKeyLabel( goto errOut; } #endif /* NDEBUG */ - + /* modify two attributes... */ SecKeychainAttribute modAttrs[2]; modAttrs[0].tag = kSecKeyLabel; @@ -149,10 +160,10 @@ errOut: } return crtn; } - + /* - * Import a raw key. This can be used as a lightweight "guess" evaluator - * if a handle to the raw CSP is passed in (with no keychain), or as + * Import a raw key. This can be used as a lightweight "guess" evaluator + * if a handle to the raw CSP is passed in (with no keychain), or as * the real thing which does full keychain import. */ OSStatus impExpImportRawKey( @@ -163,9 +174,9 @@ OSStatus impExpImportRawKey( SecKeychainRef importKeychain, // optional CSSM_CSP_HANDLE cspHand, // required SecItemImportExportFlags flags, - const SecKeyImportExportParameters *keyParams, // optional + const SecKeyImportExportParameters *keyParams, // optional const char *printName, // optional - CFMutableArrayRef outArray) // optional, append here + CFMutableArrayRef outArray) // optional, append here { CSSM_RETURN crtn; CSSM_KEY wrappedKey; @@ -174,15 +185,15 @@ OSStatus impExpImportRawKey( CSSM_KEY_SIZE keySize; CSSM_KEYBLOB_FORMAT format; CSSM_KEYCLASS keyClass; - + /* First convert external format and types to CSSM style. */ crtn = impExpKeyForm(externForm, itemType, keyAlg, &format, &keyClass); - + /* cook up key to be null-unwrapped */ memset(&wrappedKey, 0, sizeof(CSSM_KEY)); wrappedKey.KeyData.Length = CFDataGetLength(inData); wrappedKey.KeyData.Data = (uint8 *)CFDataGetBytePtr(inData); - + hdr.HeaderVersion = CSSM_KEYHEADER_VERSION; /* CspId don't care */ hdr.BlobType = CSSM_KEYBLOB_RAW; @@ -193,12 +204,12 @@ OSStatus impExpImportRawKey( /* attr and usage are for the incoming unwrapped key... */ hdr.KeyAttr = CSSM_KEYATTR_EXTRACTABLE; hdr.KeyUsage = CSSM_KEYUSE_ANY; - - /* + + /* * Get key size in bits from raw CSP. Doing this right now is a good - * optimization for the "guessing" case; getting the key size from the + * optimization for the "guessing" case; getting the key size from the * raw CSP involves a full decode on an alg- and format-specific manner. - * If we've been given the wrong params, we'll fail right here without + * If we've been given the wrong params, we'll fail right here without * the complication of a full UnwrapKey op. */ rawCspHand = cuCspStartup(CSSM_TRUE); @@ -212,14 +223,14 @@ OSStatus impExpImportRawKey( return crtn; } hdr.LogicalKeySizeInBits = keySize.LogicalKeySizeInBits; - + impExpKeyUnwrapParams unwrapParams; memset(&unwrapParams, 0, sizeof(unwrapParams)); unwrapParams.encrAlg = CSSM_ALGID_NONE; unwrapParams.encrMode = CSSM_ALGMODE_NONE; unwrapParams.unwrappingKey = NULL; unwrapParams.encrPad = CSSM_PADDING_NONE; - + return impExpImportKeyCommon( &wrappedKey, importKeychain, @@ -233,22 +244,22 @@ OSStatus impExpImportRawKey( using namespace KeychainCore; -/* +/* * Post notification of a "new key added" event. * If you know of another way to do this, other than a dlclient-based lookup of the - * existing key in order to get a KeychainCore::Item, by all means have at it. + * existing key in order to get a KeychainCore::Item, by all means have at it. */ OSStatus impExpKeyNotify( SecKeychainRef importKeychain, const CssmData &keyLabel, // stored with this, we use it to do a lookup const CSSM_KEY &cssmKey) // unwrapped key in CSSM format { - /* + /* * Look up key in the DLDB by label, key class, algorithm, and key size. */ CSSM_DB_RECORDTYPE recordType; const CSSM_KEYHEADER &hdr = cssmKey.KeyHeader; - + switch(hdr.KeyClass) { case CSSM_KEYCLASS_PUBLIC_KEY: recordType = CSSM_DL_DB_RECORD_PUBLIC_KEY; @@ -264,15 +275,15 @@ OSStatus impExpKeyNotify( } assert(importKeychain != NULL); Keychain keychain = KeychainImpl::required(importKeychain); - + SSDbImpl* impl = dynamic_cast(&(*keychain->database())); if (impl == NULL) // did we go bad? { CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); } - + CssmClient::SSDb ssDb(impl); - + CssmClient::DbAttributes dbAttributes; CssmClient::DbUniqueRecord uniqueId; CssmClient::SSDbCursor dbCursor(ssDb, 3); // three attributes @@ -285,9 +296,9 @@ OSStatus impExpKeyNotify( SecImpExpDbg("impExpKeyNotify: key not found"); return errSecItemNotFound; } - - /* - * Get a Keychain-style Item, post notification. + + /* + * Get a Keychain-style Item, post notification. */ Item keyItem = keychain->item(recordType, uniqueId); keychain->postEvent(kSecAddEvent, keyItem); @@ -304,19 +315,19 @@ OSStatus impExpKeyNotify( (CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_RETURN_NONE) /* - * Common code to unwrap a key, used for raw keys (which do a NULL unwrap) and + * Common code to unwrap a key, used for raw keys (which do a NULL unwrap) and * wrapped keys. */ OSStatus impExpImportKeyCommon( const CSSM_KEY *wrappedKey, SecKeychainRef importKeychain, // optional - CSSM_CSP_HANDLE cspHand, // required, if importKeychain is + CSSM_CSP_HANDLE cspHand, // required, if importKeychain is // present, must be from there SecItemImportExportFlags flags, - const SecKeyImportExportParameters *keyParams, // optional + const SecKeyImportExportParameters *keyParams, // optional const impExpKeyUnwrapParams *unwrapParams, const char *printName, // optional - CFMutableArrayRef outArray) // optional, append here + CFMutableArrayRef outArray) // optional, append here { CSSM_CC_HANDLE ccHand = 0; CSSM_RETURN crtn; @@ -338,10 +349,10 @@ OSStatus impExpImportKeyCommon( CssmAutoData keyLabel(Allocator::standard()); SecKeyRef secKeyRef = NULL; bool usedSecKeyCreate = false; - + assert(unwrapParams != NULL); assert(cspHand != 0); - + if(importKeychain) { ortn = SecKeychainGetDLDBHandle(importKeychain, &dlDbHandle); if(ortn) { @@ -349,10 +360,10 @@ OSStatus impExpImportKeyCommon( } dlDbPtr = &dlDbHandle; } - + memset(&unwrappedKey, 0, sizeof(CSSM_KEY)); memset(&nullCreds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); - + /* context for unwrap */ crtn = CSSM_CSP_CreateSymmetricContext(cspHand, unwrapParams->encrAlg, @@ -368,7 +379,7 @@ OSStatus impExpImportKeyCommon( } if(dlDbPtr) { /* Importing to a keychain - add DLDB to context */ - crtn = impExpAddContextAttribute(ccHand, + crtn = impExpAddContextAttribute(ccHand, CSSM_ATTRIBUTE_DL_DB_HANDLE, sizeof(CSSM_ATTRIBUTE_DL_DB_HANDLE), dlDbPtr); @@ -380,7 +391,7 @@ OSStatus impExpImportKeyCommon( if((hdr.KeyClass != CSSM_KEYCLASS_SESSION_KEY) && (dlDbPtr != NULL)) { /* Generate random 16-char label to facilitate DL lookup */ - char *randAscii = (char *)randLabel; + char *randAscii = (char *)randLabel; uint8 randBinary[SEC_RANDOM_LABEL_LEN / 2]; unsigned randBinaryLen = SEC_RANDOM_LABEL_LEN / 2; DevRandomGenerator rng; @@ -399,7 +410,7 @@ OSStatus impExpImportKeyCommon( labelData.Length = strlen(SEC_SESSIONKEY_PRINT_NAME_ATTR_VALUE); keyLabel.copy(labelData); } - + /* * key attr flags and usage. First the defaults. */ @@ -426,14 +437,14 @@ OSStatus impExpImportKeyCommon( keyAttributes &= ~SEC_KEYATTR_RETURN_MASK; keyAttributes |= CSSM_KEYATTR_RETURN_REF; } - + if( (dlDbPtr != NULL) && // not permanent, no ACL (hdr.KeyClass == CSSM_KEYCLASS_PRIVATE_KEY) && // ACLs only for private key ( (keyParams == NULL) || // NULL --> default ACL !(keyParams->flags & kSecKeyNoAccessControl) // explicity request no ACL ) ) { - /* + /* * Prepare to set up either a default ACL or one provided by caller via * keyParams->accessRef. */ @@ -442,8 +453,8 @@ OSStatus impExpImportKeyCommon( rccPtr = &rcc; } - /* - * Additional optional parameters: block size, rounds, + /* + * Additional optional parameters: block size, rounds, * effectiveKeySize. * WARNING: block size and rounds, used for RC5, have not been tested. * OpenSSL, as of Panther ship, did not support RC5 encryption. @@ -453,7 +464,7 @@ OSStatus impExpImportKeyCommon( CSSM_ALGID_RC2); SecImpExpDbg("impExpImportKeyCommon: setting effectiveKeySizeInBits to %lu", (unsigned long)unwrapParams->effectiveKeySizeInBits); - crtn = impExpAddContextAttribute(ccHand, + crtn = impExpAddContextAttribute(ccHand, CSSM_ATTRIBUTE_EFFECTIVE_BITS, sizeof(uint32), (void *)((size_t) unwrapParams->effectiveKeySizeInBits)); @@ -462,13 +473,13 @@ OSStatus impExpImportKeyCommon( goto errOut; } } - + if(unwrapParams->rounds != 0) { assert(unwrapParams->unwrappingKey->KeyHeader.AlgorithmId == CSSM_ALGID_RC5); SecImpExpDbg("impExpImportKeyCommon: setting rounds to %lu", (unsigned long)unwrapParams->rounds); - crtn = impExpAddContextAttribute(ccHand, + crtn = impExpAddContextAttribute(ccHand, CSSM_ATTRIBUTE_ROUNDS, sizeof(uint32), (void *)((size_t)unwrapParams->rounds)); @@ -483,10 +494,10 @@ OSStatus impExpImportKeyCommon( if(unwrapParams->blockSizeInBits != 64) { SecImpExpDbg("WARNING impExpImportKeyCommon: setting block size to %lu", (unsigned long)unwrapParams->blockSizeInBits); - /* - * With the current CSP this will actually be ignored + /* + * With the current CSP this will actually be ignored */ - crtn = impExpAddContextAttribute(ccHand, + crtn = impExpAddContextAttribute(ccHand, CSSM_ATTRIBUTE_BLOCK_SIZE, sizeof(uint32), (void *)((size_t)unwrapParams->blockSizeInBits)); @@ -515,7 +526,7 @@ OSStatus impExpImportKeyCommon( } goto errOut; } - + /* Private and public keys: update Label as public key hash */ if((hdr.KeyClass != CSSM_KEYCLASS_SESSION_KEY) && (dlDbPtr != NULL)) { CSSM_DATA newPrintName; @@ -534,7 +545,7 @@ OSStatus impExpImportKeyCommon( } newPrintName.Length = strlen((char *)newPrintName.Data); #if old_way - crtn = impExpSetKeyLabel(cspHand, *dlDbPtr, &unwrappedKey, + crtn = impExpSetKeyLabel(cspHand, *dlDbPtr, &unwrappedKey, &labelData, &newPrintName, keyLabel); #else crtn = impExpSetKeyLabel(cspHand, *dlDbPtr, importKeychain, @@ -544,11 +555,11 @@ OSStatus impExpImportKeyCommon( goto errOut; } } - + /* Private key: adjust ACL as appropriate */ if(rccPtr != NULL) { - SecPointer theAccess(accessRef ? - KeychainCore::Access::required(accessRef) : + SecPointer theAccess(accessRef ? + KeychainCore::Access::required(accessRef) : new KeychainCore::Access("Imported Private Key")); try { CssmClient::KeyAclBearer bearer(cspHand, unwrappedKey, Allocator::standard()); @@ -566,7 +577,7 @@ OSStatus impExpImportKeyCommon( crtn = errSecAuthFailed; /* ??? */ } } - + /* * If importKeychain is non-NULL we've already added the key to the keychain. * If importKeychain is NULL, and outArray is non-NULL, we have to use the @@ -586,11 +597,11 @@ OSStatus impExpImportKeyCommon( } CFArrayAppendValue(outArray, secKeyRef); } - + if(importKeychain) { impExpKeyNotify(importKeychain, keyLabel.get(), unwrappedKey); } - + errOut: if(ccHand != 0) { CSSM_DeleteContext(ccHand); @@ -604,8 +615,8 @@ errOut: } return crtn; } - -/* + +/* * Common code to wrap a key for export. */ CSSM_RETURN impExpExportKeyCommon( @@ -624,7 +635,7 @@ CSSM_RETURN impExpExportKeyCommon( { OSStatus ortn; CSSM_RETURN crtn; - + const CSSM_KEY *unwrappedKey; ortn = SecKeyGetCSSMKey(secKey, &unwrappedKey); if(ortn) { @@ -637,18 +648,16 @@ CSSM_RETURN impExpExportKeyCommon( } /* - * Creds needed only for wrapping private keys. - * We bother checking in case we ever want to use this to wrap - * session keys. + * Creds are needed for wrapping private and session keys. */ CSSM_ACCESS_CREDENTIALS nullCreds; memset(&nullCreds, 0, sizeof(nullCreds)); const CSSM_ACCESS_CREDENTIALS *creds = &nullCreds; // default - + CSSM_KEYCLASS keyClass = unwrappedKey->KeyHeader.KeyClass; - if(keyClass == CSSM_KEYCLASS_PRIVATE_KEY) { + if(keyClass == CSSM_KEYCLASS_PRIVATE_KEY || keyClass == CSSM_KEYCLASS_SESSION_KEY) { ortn = SecKeyGetCredentials(secKey, - CSSM_ACL_AUTHORIZATION_DECRYPT, // HACK will change! + CSSM_ACL_AUTHORIZATION_DECRYPT, kSecCredentialTypeDefault, &creds); if(ortn) { @@ -656,7 +665,7 @@ CSSM_RETURN impExpExportKeyCommon( return ortn; } } - + CSSM_CC_HANDLE ccHand; crtn = CSSM_CSP_CreateSymmetricContext(cspHand, wrapAlg, @@ -671,12 +680,12 @@ CSSM_RETURN impExpExportKeyCommon( SecImpExpDbg("impExpExportKeyCommon CSSM_CSP_CreateSymmetricContext error"); return crtn; } - + /* a couple of optional caller-specified attributes */ if(wrapFormat != CSSM_KEYBLOB_WRAPPED_FORMAT_NONE) { crtn = impExpAddContextAttribute(ccHand, CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT, - sizeof(uint32), + sizeof(uint32), (void *)((size_t)wrapFormat)); if(crtn) { SecImpExpDbg("impExpExportKeyCommon AddContextAttribute error (1)"); @@ -684,11 +693,11 @@ CSSM_RETURN impExpExportKeyCommon( return crtn; } } - + if(blobAttrType != CSSM_ATTRIBUTE_NONE) { crtn = impExpAddContextAttribute(ccHand, blobAttrType, - sizeof(uint32), + sizeof(uint32), (void *)((size_t)blobForm)); if(crtn) { SecImpExpDbg("impExpExportKeyCommon AddContextAttribute error"); @@ -704,7 +713,7 @@ CSSM_RETURN impExpExportKeyCommon( crtn = CSSM_WrapKey(ccHand, creds, unwrappedKey, - &dData, + &dData, wrappedKey); CSSM_DeleteContext(ccHand); switch(crtn) { @@ -714,7 +723,7 @@ CSSM_RETURN impExpExportKeyCommon( { /* * This is what comes back when we try to wrap an unextractable - * key, or when we null wrap a sensitive key. Give the caller + * key, or when we null wrap a sensitive key. Give the caller * some useful info. */ CSSM_KEYATTR_FLAGS attr = unwrappedKey->KeyHeader.KeyAttr; diff --git a/libsecurity_keychain/lib/SecImportExportCrypto.h b/Security/libsecurity_keychain/lib/SecImportExportCrypto.h similarity index 98% rename from libsecurity_keychain/lib/SecImportExportCrypto.h rename to Security/libsecurity_keychain/lib/SecImportExportCrypto.h index 00001550..d609c745 100644 --- a/libsecurity_keychain/lib/SecImportExportCrypto.h +++ b/Security/libsecurity_keychain/lib/SecImportExportCrypto.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecImportExportOpenSSH.cpp b/Security/libsecurity_keychain/lib/SecImportExportOpenSSH.cpp similarity index 99% rename from libsecurity_keychain/lib/SecImportExportOpenSSH.cpp rename to Security/libsecurity_keychain/lib/SecImportExportOpenSSH.cpp index 7ab90d1c..d066c49c 100644 --- a/libsecurity_keychain/lib/SecImportExportOpenSSH.cpp +++ b/Security/libsecurity_keychain/lib/SecImportExportOpenSSH.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -25,7 +25,6 @@ /* * opensshCoding.cpp - Encoding and decoding of OpenSSH format public keys. * - * Created 8/29/2006 by dmitch. */ #include "SecImportExportOpenSSH.h" diff --git a/libsecurity_keychain/lib/SecImportExportOpenSSH.h b/Security/libsecurity_keychain/lib/SecImportExportOpenSSH.h similarity index 96% rename from libsecurity_keychain/lib/SecImportExportOpenSSH.h rename to Security/libsecurity_keychain/lib/SecImportExportOpenSSH.h index a91b49db..9f949426 100644 --- a/libsecurity_keychain/lib/SecImportExportOpenSSH.h +++ b/Security/libsecurity_keychain/lib/SecImportExportOpenSSH.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -24,7 +24,6 @@ /* * SecImportExportOpenSSH.h - support for importing and exporting OpenSSH keys. * - * Created 8/31/2006 by dmitch. */ #ifndef _SEC_IMPORT_EXPORT_OPENSSH_H_ diff --git a/libsecurity_keychain/lib/SecImportExportPem.cpp b/Security/libsecurity_keychain/lib/SecImportExportPem.cpp similarity index 99% rename from libsecurity_keychain/lib/SecImportExportPem.cpp rename to Security/libsecurity_keychain/lib/SecImportExportPem.cpp index 95958f4c..df675564 100644 --- a/libsecurity_keychain/lib/SecImportExportPem.cpp +++ b/Security/libsecurity_keychain/lib/SecImportExportPem.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecImportExportPem.h b/Security/libsecurity_keychain/lib/SecImportExportPem.h similarity index 97% rename from libsecurity_keychain/lib/SecImportExportPem.h rename to Security/libsecurity_keychain/lib/SecImportExportPem.h index bf515717..b91773d0 100644 --- a/libsecurity_keychain/lib/SecImportExportPem.h +++ b/Security/libsecurity_keychain/lib/SecImportExportPem.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecImportExportPkcs8.cpp b/Security/libsecurity_keychain/lib/SecImportExportPkcs8.cpp similarity index 99% rename from libsecurity_keychain/lib/SecImportExportPkcs8.cpp rename to Security/libsecurity_keychain/lib/SecImportExportPkcs8.cpp index 04a217bd..13547958 100644 --- a/libsecurity_keychain/lib/SecImportExportPkcs8.cpp +++ b/Security/libsecurity_keychain/lib/SecImportExportPkcs8.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecImportExportPkcs8.h b/Security/libsecurity_keychain/lib/SecImportExportPkcs8.h similarity index 96% rename from libsecurity_keychain/lib/SecImportExportPkcs8.h rename to Security/libsecurity_keychain/lib/SecImportExportPkcs8.h index 41be4058..2116cd91 100644 --- a/libsecurity_keychain/lib/SecImportExportPkcs8.h +++ b/Security/libsecurity_keychain/lib/SecImportExportPkcs8.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecImportExportUtils.cpp b/Security/libsecurity_keychain/lib/SecImportExportUtils.cpp similarity index 99% rename from libsecurity_keychain/lib/SecImportExportUtils.cpp rename to Security/libsecurity_keychain/lib/SecImportExportUtils.cpp index ab5e0af1..e0f17768 100644 --- a/libsecurity_keychain/lib/SecImportExportUtils.cpp +++ b/Security/libsecurity_keychain/lib/SecImportExportUtils.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2004,2013 Apple Inc. All Rights Reserved. + * Copyright (c) 2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ * * SecImportExportUtils.cpp - misc. utilities for import/export module @@ -341,6 +341,11 @@ static bool impExpGuessKeyParams( SecExternalItemType minType = kSecItemTypePrivateKey; // just two SecExternalItemType maxType = kSecItemTypePublicKey; + + if(keyData == NULL || CFDataGetLength(keyData) == 0){ + MacOSError::throwMe(errSecUnsupportedKeySize); + } + switch(*externForm) { case kSecFormatUnknown: break; // run through all formats diff --git a/libsecurity_keychain/lib/SecImportExportUtils.h b/Security/libsecurity_keychain/lib/SecImportExportUtils.h similarity index 99% rename from libsecurity_keychain/lib/SecImportExportUtils.h rename to Security/libsecurity_keychain/lib/SecImportExportUtils.h index 7190ba17..7b02ac0e 100644 --- a/libsecurity_keychain/lib/SecImportExportUtils.h +++ b/Security/libsecurity_keychain/lib/SecImportExportUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_keychain/lib/SecInternal.h b/Security/libsecurity_keychain/lib/SecInternal.h new file mode 100644 index 00000000..4bae0414 --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecInternal.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2007-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecInternal + SecInternal defines common internal constants macros and SPI functions. +*/ + +#ifndef _SECURITY_SECINTERNAL_H_ +#define _SECURITY_SECINTERNAL_H_ + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +#define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) CFRelease(_cf); } +#define CFReleaseNull(CF) { CFTypeRef _cf = (CF); \ + if (_cf) { (CF) = NULL; CFRelease(_cf); } } + +#define AssignOrReleaseResult(CF,OUT) { \ + CFTypeRef _cf = (CF), *_out = (OUT); \ + if (_out) { *_out = _cf; } else { if (_cf) CFRelease(_cf); } } + +#define DICT_DECLARE(MAXVALUES) \ + CFIndex numValues = 0, maxValues = (MAXVALUES); \ + const void *keys[maxValues]; \ + const void *values[maxValues]; + +#define DICT_ADDPAIR(KEY,VALUE) do { \ + if (numValues < maxValues) { \ + keys[numValues] = (KEY); \ + values[numValues] = (VALUE); \ + numValues++; \ + } else \ + assert(false); \ +} while(0) + +#define DICT_CREATE(ALLOCATOR) CFDictionaryCreate((ALLOCATOR), keys, values, \ + numValues, NULL, &kCFTypeDictionaryValueCallBacks) + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECINTERNAL_H_ */ diff --git a/libsecurity_keychain/lib/SecInternalP.h b/Security/libsecurity_keychain/lib/SecInternalP.h similarity index 95% rename from libsecurity_keychain/lib/SecInternalP.h rename to Security/libsecurity_keychain/lib/SecInternalP.h index 22a8107c..e92d7356 100644 --- a/libsecurity_keychain/lib/SecInternalP.h +++ b/Security/libsecurity_keychain/lib/SecInternalP.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2007,2009-2010,2013 Apple Inc. All Rights Reserved. + * Copyright (c) 2007,2009-2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/SecItem.cpp b/Security/libsecurity_keychain/lib/SecItem.cpp similarity index 97% rename from libsecurity_keychain/lib/SecItem.cpp rename to Security/libsecurity_keychain/lib/SecItem.cpp index 00bb4c41..87fe7af3 100644 --- a/libsecurity_keychain/lib/SecItem.cpp +++ b/Security/libsecurity_keychain/lib/SecItem.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2006-2013 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -67,6 +67,8 @@ CFDictionaryRef SecItemCopyTranslatedAttributes(CFDictionaryRef inOSXDict, CFTyp bool iOSOut, bool pruneMatch, bool pruneSync, bool pruneReturn, bool pruneData, bool pruneAccess); } +static Boolean SecItemSynchronizable(CFDictionaryRef query); + static void secitemlog(int priority, const char *format, ...) { #ifndef NDEBUG @@ -2026,7 +2028,7 @@ _AppNameFromSecTrustedApplication( } if ( nameRange.length > 0 ) { - // find last slash and adjust nameRange be everything after it + // find last slash and adjust nameRange to be everything after it if ( CFStringFindWithOptions(path, CFSTR("/"), nameRange, kCFCompareBackwards, &compRg) ) { nameRange.length = nameRange.location + nameRange.length - (compRg.location + 1); nameRange.location = compRg.location + 1; @@ -2149,17 +2151,21 @@ _SafeSecKeychainItemDelete( SecKeychainItemRef itemRef) { OSStatus status; - SecAccessRef access; - CFArrayRef aclList; - SecACLRef acl; - CFArrayRef appList; - CFStringRef description; + SecAccessRef access = NULL; + CFArrayRef aclList = NULL; + SecACLRef acl = NULL; + CFArrayRef appList = NULL; + CFStringRef description = NULL; CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector; + CFIndex count = 0; + SecTrustedApplicationRef currentAppRef = NULL; + CFStringRef itemAppName = NULL, currentAppName = NULL; - SecItemClass itemClass; + SecItemClass itemClass = (SecItemClass)0; status = SecKeychainItemCopyAttributesAndData(itemRef, NULL, &itemClass, NULL, NULL, NULL); - if (!status && (itemClass == kSecCertificateItemClass || itemClass == kSecPublicKeyItemClass)) { - // the item doesn't have any access controls, so delete it normally + if (!(itemClass == kSecInternetPasswordItemClass || itemClass == kSecGenericPasswordItemClass)) { + // only perform the access control safety check on deletion of password credentials; + // if the item is of some other type, delete it normally. return SecKeychainItemDelete(itemRef); } @@ -2182,71 +2188,74 @@ _SafeSecKeychainItemDelete( // copy the access of the keychain item status = SecKeychainItemCopyAccess(itemRef, &access); - require_noerr(status, SecKeychainItemCopyAccessFailed); + require_noerr(status, finish); + require_quiet(access != NULL, finish); // copy the decrypt access control lists -- this is what has access to the keychain item status = SecAccessCopySelectedACLList(access, CSSM_ACL_AUTHORIZATION_DECRYPT, &aclList); - require_noerr(status, SecAccessCopySelectedACLListFailed); - require_quiet(aclList != NULL, noACLList); + require_noerr(status, finish); + require_quiet(aclList != NULL, finish); // get the access control list acl = (SecACLRef)CFArrayGetValueAtIndex(aclList, 0); - require_quiet(acl != NULL, noACL); + require_quiet(acl != NULL, finish); // copy the application list, description, and CSSM prompt selector for a given access control list entry status = SecACLCopySimpleContents(acl, &appList, &description, &promptSelector); - require_noerr(status, SecACLCopySimpleContentsFailed); - require_quiet(appList != NULL, noAppList); + require_noerr(status, finish); + require_quiet(appList != NULL, finish); // does only a single application/tool have decrypt access to this item? - if ( CFArrayGetCount(appList) == 1 ) { - SecTrustedApplicationRef itemAppRef, currentAppRef; - CFStringRef itemAppName, currentAppName; - + count = CFArrayGetCount(appList); + if ( count == 1 ) { // get SecTrustedApplicationRef for item's application/tool - itemAppRef = (SecTrustedApplicationRef)CFArrayGetValueAtIndex(appList, 0); - require(itemAppRef != NULL, noItemAppRef); + SecTrustedApplicationRef itemAppRef = (SecTrustedApplicationRef)CFArrayGetValueAtIndex(appList, 0); + require_quiet(itemAppRef != NULL, finish); // copy the name out itemAppName = _AppNameFromSecTrustedApplication(CFGetAllocator(itemRef), itemAppRef); - require(itemAppName != NULL, noAppName); + if (itemAppName == NULL) { + /* + * If there is no app name, it's probably because it's not an appname + * in the ACE but an entitlement/info.plist based rule instead; + * just let the caller have it. */ + count--; + goto finish; + } // create SecTrustedApplicationRef for current application/tool status = SecTrustedApplicationCreateFromPath(NULL, ¤tAppRef); - require((status == errSecSuccess) && (currentAppRef != NULL), SecTrustedApplicationCreateFromPathFailed); + require_noerr(status, finish); + require_quiet(currentAppRef != NULL, finish); // copy the name out currentAppName = _AppNameFromSecTrustedApplication(CFGetAllocator(itemRef), currentAppRef); - require(currentAppName != NULL, noCurrentAppName); + require_quiet(currentAppName != NULL, finish); - // compare the current application/tool's name to this item's application/tool's name to see if we own the decrypt access + // compare the names to see if we own the decrypt access if ( CFStringCompare(currentAppName, itemAppName, 0) == kCFCompareEqualTo ) { - // delete the keychain item - SecKeychainItemDelete(itemRef); + // decrement the count to zero, which will remove the item below + --count; } - - CFRelease(currentAppName); - noCurrentAppName: - CFRelease(currentAppRef); - SecTrustedApplicationCreateFromPathFailed: - CFRelease(itemAppName); - noAppName: - noItemAppRef: - ; } - if ( description ) { - CFRelease(description); +finish: + + CFReleaseSafe(currentAppName); + CFReleaseSafe(itemAppName); + CFReleaseSafe(currentAppRef); + CFReleaseSafe(description); + CFReleaseSafe(appList); + CFReleaseSafe(aclList); + CFReleaseSafe(access); + + if ((count == 0) || (status == errSecVerifyFailed)) { + // no "owners" remain in the ACL list (or unable to get ACL) + status = SecKeychainItemDelete(itemRef); + } else { + // caller is not the "owner" of the item + status = errSecInvalidOwnerEdit; } - CFRelease(appList); -noAppList: -SecACLCopySimpleContentsFailed: -noACL: - CFRelease(aclList); -noACLList: -SecAccessCopySelectedACLListFailed: - CFRelease(access); -SecKeychainItemCopyAccessFailed: return status; } @@ -2666,6 +2675,7 @@ struct SecItemParams { CFTypeRef itemRef; // item reference (to find, add, update or delete, depending on context) SecIdentityRef identityRef; // identity reference (input as kSecValueRef) CFDataRef itemPersistentRef; // item persistent reference (to find, add, update or delete, depending on context) + Boolean isPCSItem; // true if this query is for a Protected Cloud Storage item }; static OSStatus @@ -2702,6 +2712,52 @@ _ValidateDictionaryEntry(CFDictionaryRef dict, CFTypeRef key, const void **value return errSecSuccess; } +static void +_EnsureUserDefaultKeychainIsSearched(SecItemParams *itemParams) +{ + OSStatus status; + CFArrayRef tmpList = (CFArrayRef) itemParams->searchList; + if (tmpList) { + // search list exists; make it mutable + itemParams->searchList = (CFArrayRef) CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, tmpList); + CFRelease(tmpList); + } else { + // no search list; start with default list + status = SecKeychainCopySearchList(&tmpList); + if (!status && tmpList) { + itemParams->searchList = (CFArrayRef) CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, tmpList); + CFRelease(tmpList); + } + else { + itemParams->searchList = (CFArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + } + } + + SecKeychainRef userKeychain = NULL; + status = SecKeychainCopyDomainDefault(kSecPreferencesDomainUser, &userKeychain); + if (!status && userKeychain) { + if (!CFArrayContainsValue((CFArrayRef)itemParams->searchList, + CFRangeMake(0, CFArrayGetCount((CFArrayRef)itemParams->searchList)), userKeychain)) { + // user's default keychain isn't currently in the search list, so append it + CFArrayAppendValue((CFMutableArrayRef)itemParams->searchList, userKeychain); + } + CFRelease(userKeychain); + } +} + +static void +_EnsureUserDefaultKeychainIsTargeted(SecItemParams *itemParams) +{ + if (itemParams->keychain) { + return; // keychain is already explicitly specified, assume it's correct + } + SecKeychainRef userKeychain = NULL; + OSStatus status = SecKeychainCopyDomainDefault(kSecPreferencesDomainUser, &userKeychain); + if (!status && userKeychain) { + itemParams->keychain = userKeychain; + } +} + static void _FreeSecItemParams(SecItemParams *itemParams) { @@ -2763,6 +2819,14 @@ _CreateSecItemParamsFromDictionary(CFDictionaryRef dict, OSStatus *error) require_noerr(status = _ValidateDictionaryEntry(dict, kSecAttrService, (const void **)&itemParams->service, CFStringGetTypeID(), NULL), error_exit); require_noerr(status = _ValidateDictionaryEntry(dict, kSecAttrKeyClass, (const void **)&itemParams->keyClass, CFStringGetTypeID(), NULL), error_exit); + if (itemParams->service && CFStringHasPrefix((CFStringRef)itemParams->service, CFSTR("ProtectedCloudStorage"))) { + itemParams->isPCSItem = true; + if (!SecItemSynchronizable(dict)) { + _EnsureUserDefaultKeychainIsSearched(itemParams); // for SecItemCopyMatching, SecItemUpdate, SecItemDelete + _EnsureUserDefaultKeychainIsTargeted(itemParams); // for SecItemAdd + } + } + // validate the payload (password, key or certificate data), used for SecItemAdd but not for finding items require_noerr(status = _ValidateDictionaryEntry(dict, kSecValueData, (const void **)&itemParams->itemData, CFDataGetTypeID(), CFStringGetTypeID()), error_exit); diff --git a/Security/libsecurity_keychain/lib/SecItem.h b/Security/libsecurity_keychain/lib/SecItem.h new file mode 100644 index 00000000..76a774dd --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecItem.h @@ -0,0 +1,1113 @@ +/* + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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 SecItem + SecItem defines CoreFoundation-based constants and functions for + access to Security items (certificates, keys, identities, and + passwords.) +*/ + +#ifndef _SECURITY_SECITEM_H_ +#define _SECURITY_SECITEM_H_ + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + @enum Class Key Constant + @discussion Predefined key constant used to get or set item class values in + a dictionary. Its value is one of the constants defined in the Value + Constants for kSecClass. + @constant kSecClass Specifies a dictionary key whose value is the item's + class code. You use this key to get or set a value of type CFTypeRef + that contains the item class code. +*/ +extern const CFTypeRef kSecClass + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @enum Class Value Constants + @discussion Predefined item class constants used to get or set values in + a dictionary. The kSecClass constant is the key and its value is one + of the constants defined here. Note: on Mac OS X 10.6, only items + of class kSecClassInternetPassword are supported. + @constant kSecClassInternetPassword Specifies Internet password items. + @constant kSecClassGenericPassword Specifies generic password items. + @constant kSecClassCertificate Specifies certificate items. + @constant kSecClassKey Specifies key items. + @constant kSecClassIdentity Specifies identity items. +*/ +extern const CFTypeRef kSecClassInternetPassword + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecClassGenericPassword + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); +extern const CFTypeRef kSecClassCertificate + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); +extern const CFTypeRef kSecClassKey + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); +extern const CFTypeRef kSecClassIdentity + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + +/*! + @enum Attribute Key Constants + @discussion Predefined item attribute keys used to get or set values in a + dictionary. Not all attributes apply to each item class. The table + below lists the currently defined attributes for each item class: + + kSecClassGenericPassword item attributes: + kSecAttrAccess (OS X only) + kSecAttrAccessControl + kSecAttrAccessGroup (iOS; also OS X if kSecAttrSynchronizable specified) + kSecAttrAccessible (iOS; also OS X if kSecAttrSynchronizable specified) + kSecAttrCreationDate + kSecAttrModificationDate + kSecAttrDescription + kSecAttrComment + kSecAttrCreator + kSecAttrType + kSecAttrLabel + kSecAttrIsInvisible + kSecAttrIsNegative + kSecAttrAccount + kSecAttrService + kSecAttrGeneric + + kSecClassInternetPassword item attributes: + kSecAttrAccess (OS X only) + kSecAttrAccessGroup (iOS; also OS X if kSecAttrSynchronizable specified) + kSecAttrAccessible (iOS; also OS X if kSecAttrSynchronizable specified) + kSecAttrCreationDate + kSecAttrModificationDate + kSecAttrDescription + kSecAttrComment + kSecAttrCreator + kSecAttrType + kSecAttrLabel + kSecAttrIsInvisible + kSecAttrIsNegative + kSecAttrAccount + kSecAttrSecurityDomain + kSecAttrServer + kSecAttrProtocol + kSecAttrAuthenticationType + kSecAttrPort + kSecAttrPath + + kSecClassCertificate item attributes: + kSecAttrCertificateType + kSecAttrCertificateEncoding + kSecAttrLabel + kSecAttrSubject + kSecAttrIssuer + kSecAttrSerialNumber + kSecAttrSubjectKeyID + kSecAttrPublicKeyHash + + kSecClassKey item attributes: + kSecAttrAccess (OS X only) + kSecAttrAccessGroup (iOS only) + kSecAttrAccessible (iOS only) + kSecAttrKeyClass + kSecAttrLabel + kSecAttrApplicationLabel + kSecAttrIsPermanent + kSecAttrApplicationTag + kSecAttrKeyType + kSecAttrPRF + kSecAttrSalt + kSecAttrRounds + kSecAttrKeySizeInBits + kSecAttrEffectiveKeySize + kSecAttrCanEncrypt + kSecAttrCanDecrypt + kSecAttrCanDerive + kSecAttrCanSign + kSecAttrCanVerify + kSecAttrCanWrap + kSecAttrCanUnwrap + + Note that the attributes kSecAttrCan* describe attributes of the + key itself at relatively high level. Some of these attributes are + mathematical -- for example, a DSA key cannot encrypt. Others are + key-level policy issues -- for example, it is good cryptographic + hygiene to use an RSA key either for encryption or signing but not + both. Compare these to the certificate-level policy values in + SecPolicy.h. + + kSecClassIdentity item attributes: + Since an identity is the combination of a private key and a + certificate, this class shares attributes of both kSecClassKey and + kSecClassCertificate. + + @constant kSecAttrAccessible Specifies a dictionary key whose value + indicates when your application needs access to an item's data. You + should choose the most restrictive option that meets your application's + needs to allow the system to protect that item in the best way possible. + See the "kSecAttrAccessible Value Constants" section for a list of + values which can be specified. + IMPORTANT: This attribute is currently not supported for OS X keychain + items, unless the kSecAttrSynchronizable attribute is also present. If + both attributes are specified on either OS X or iOS, the value for the + kSecAttrAccessible key may only be one whose name does not end with + "ThisDeviceOnly", as those cannot sync to another device. + + @constant kSecAttrAccessControl Specifies a dictionary key whose value + is SecAccessControl instance which contains access control conditions + for item. + IMPORTANT: This attribute is mutually exclusive with kSecAttrAccess + attribute. + + @constant kSecAttrAccess Specifies a dictionary key whose value + is a SecAccessRef describing the access control settings for this item. + This key is available on OS X only. + + @constant kSecAttrAccessGroup Specifies a dictionary key whose value is + a CFStringRef indicating which access group a item is in. The access + groups that a particular application has membership in are determined by + two entitlements for that application. The application-identifier + entitlement contains the application's single access group, unless + there is a keychain-access-groups entitlement present. The latter + has as its value a list of access groups; the first item in this list + is the default access group. Unless a specific access group is provided + as the value of kSecAttrAccessGroup when SecItemAdd is called, new items + are created in the application's default access group. Specifying this + attribute in SecItemCopyMatching, SecItemUpdate, or SecItemDelete calls + limits the search to the specified access group (of which the calling + application must be a member to obtain matching results.) To share + keychain items between multiple applications, each application must have + a common group listed in its keychain-access-groups entitlement, and each + must specify this shared access group name as the value for the + kSecAttrAccessGroup key in the dictionary passed to SecItem functions. + + @constant kSecAttrSynchronizable Specifies a dictionary key whose value is + a CFBooleanRef indicating whether the item in question can be synchronized. + To add a new item which can be synced to other devices, or to obtain + synchronizable results from a query, supply this key with a value of + kCFBooleanTrue. If the key is not supplied, or has a value of + kCFBooleanFalse, then no synchronizable items will be added or returned. + A predefined value, kSecAttrSynchronizableAny, may be provided instead of + kCFBooleanTrue if both synchronizable and non-synchronizable results are + desired. + + IMPORTANT: Specifying the kSecAttrSynchronizable key has several caveats: + + - Updating or deleting items using the kSecAttrSynchronizable key will + affect all copies of the item, not just the one on your local device. + Be sure that it makes sense to use the same password on all devices + before deciding to make a password synchronizable. + - Only password items can currently be synchronized. Keychain syncing + is not supported for certificates or cryptographic keys. + - Items stored or obtained using the kSecAttrSynchronizable key cannot + specify SecAccessRef-based access control with kSecAttrAccess. If a + password is intended to be shared between multiple applications, the + kSecAttrAccessGroup key must be specified, and each application + using this password must have a 'keychain-access-groups' entitlement + with the specified access group value. + - Items stored or obtained using the kSecAttrSynchronizable key may + not also specify a kSecAttrAccessible value which is incompatible + with syncing (namely, those whose names end with "ThisDeviceOnly".) + - Items stored or obtained using the kSecAttrSynchronizable key cannot + be specified by reference. You must pass kSecReturnAttributes and/or + kSecReturnData to retrieve results; kSecReturnRef is currently not + supported for synchronizable items. + - Persistent references to synchronizable items should be avoided; + while they may work locally, they cannot be moved between devices, + and may not resolve if the item is modified on some other device. + - When specifying a query that uses the kSecAttrSynchronizable key, + search keys are limited to the item's class and attributes. + The only search constant which may be used is kSecMatchLimit; other + constants using the kSecMatch prefix are not supported at this time. + + @constant kSecAttrSynchronizableAny Specifies that both synchronizable and + non-synchronizable results should be returned from this query. This may be + used as a value for the kSecAttrSynchronizable dictionary key in a call to + SecItemCopyMatching, SecItemUpdate, or SecItemDelete. + + @constant kSecAttrCreationDate (read-only) Specifies a dictionary key whose + value is the item's creation date. You use this key to get a value + of type CFDateRef that represents the date the item was created. + @constant kSecAttrModificationDate (read-only) Specifies a dictionary key + whose value is the item's modification date. You use this key to get + a value of type CFDateRef that represents the last time the item was + updated. + @constant kSecAttrDescription Specifies a dictionary key whose value is + the item's description attribute. You use this key to set or get a + value of type CFStringRef that represents a user-visible string + describing this particular kind of item (e.g., "disk image password"). + @constant kSecAttrComment Specifies a dictionary key whose value is the + item's comment attribute. You use this key to set or get a value of + type CFStringRef containing the user-editable comment for this item. + @constant kSecAttrCreator Specifies a dictionary key whose value is the + item's creator attribute. You use this key to set or get a value of + type CFNumberRef that represents the item's creator. This number is + the unsigned integer representation of a four-character code (e.g., + 'aCrt'). + @constant kSecAttrType Specifies a dictionary key whose value is the item's + type attribute. You use this key to set or get a value of type + CFNumberRef that represents the item's type. This number is the + unsigned integer representation of a four-character code (e.g., + 'aTyp'). + @constant kSecAttrLabel Specifies a dictionary key whose value is the + item's label attribute. You use this key to set or get a value of + type CFStringRef containing the user-visible label for this item. + @constant kSecAttrIsInvisible Specifies a dictionary key whose value is the + item's invisible attribute. You use this key to set or get a value + of type CFBooleanRef that indicates whether the item is invisible + (i.e., should not be displayed.) + @constant kSecAttrIsNegative Specifies a dictionary key whose value is the + item's negative attribute. You use this key to set or get a value of + type CFBooleanRef that indicates whether there is a valid password + associated with this keychain item. This is useful if your application + doesn't want a password for some particular service to be stored in + the keychain, but prefers that it always be entered by the user. + @constant kSecAttrAccount Specifies a dictionary key whose value is the + item's account attribute. You use this key to set or get a CFStringRef + that contains an account name. (Items of class + kSecClassGenericPassword, kSecClassInternetPassword have this + attribute.) + @constant kSecAttrService Specifies a dictionary key whose value is the + item's service attribute. You use this key to set or get a CFStringRef + that represents the service associated with this item. (Items of class + kSecClassGenericPassword have this attribute.) + @constant kSecAttrGeneric Specifies a dictionary key whose value is the + item's generic attribute. You use this key to set or get a value of + CFDataRef that contains a user-defined attribute. (Items of class + kSecClassGenericPassword have this attribute.) + @constant kSecAttrSecurityDomain Specifies a dictionary key whose value + is the item's security domain attribute. You use this key to set or + get a CFStringRef value that represents the Internet security domain. + (Items of class kSecClassInternetPassword have this attribute.) + @constant kSecAttrServer Specifies a dictionary key whose value is the + item's server attribute. You use this key to set or get a value of + type CFStringRef that contains the server's domain name or IP address. + (Items of class kSecClassInternetPassword have this attribute.) + @constant kSecAttrProtocol Specifies a dictionary key whose value is the + item's protocol attribute. You use this key to set or get a value of + type CFNumberRef that denotes the protocol for this item (see the + SecProtocolType enum in SecKeychainItem.h). (Items of class + kSecClassInternetPassword have this attribute.) + @constant kSecAttrAuthenticationType Specifies a dictionary key whose value + is the item's authentication type attribute. You use this key to set + or get a value of type CFNumberRef that denotes the authentication + scheme for this item (see the kSecAttrAuthenticationType value + constants below). + @constant kSecAttrPort Specifies a dictionary key whose value is the item's + port attribute. You use this key to set or get a CFNumberRef value + that represents an Internet port number. (Items of class + kSecClassInternetPassword have this attribute.) + @constant kSecAttrPath Specifies a dictionary key whose value is the item's + path attribute, typically this is the path component of the URL. You use + this key to set or get a CFStringRef value that represents a path. (Items + of class kSecClassInternetPassword have this attribute.) + @constant kSecAttrSubject (read-only) Specifies a dictionary key whose + value is the item's subject. You use this key to get a value of type + CFDataRef that contains the X.500 subject name of a certificate. + (Items of class kSecClassCertificate have this attribute.) + @constant kSecAttrIssuer (read-only) Specifies a dictionary key whose value + is the item's issuer. You use this key to get a value of type + CFDataRef that contains the X.500 issuer name of a certificate. (Items + of class kSecClassCertificate have this attribute.) + @constant kSecAttrSerialNumber (read-only) Specifies a dictionary key whose + value is the item's serial number. You use this key to get a value + of type CFDataRef that contains the serial number data of a + certificate. (Items of class kSecClassCertificate have this + attribute.) + @constant kSecAttrSubjectKeyID (read-only) Specifies a dictionary key whose + value is the item's subject key ID. You use this key to get a value + of type CFDataRef that contains the subject key ID of a certificate. + (Items of class kSecClassCertificate have this attribute.) + @constant kSecAttrPublicKeyHash (read-only) Specifies a dictionary key + whose value is the item's public key hash. You use this key to get a + value of type CFDataRef that contains the hash of a certificate's + public key. (Items of class kSecClassCertificate have this attribute.) + @constant kSecAttrCertificateType (read-only) Specifies a dictionary key + whose value is the item's certificate type. You use this key to get + a value of type CFNumberRef that denotes the certificate type (see the + CSSM_CERT_TYPE enum in cssmtype.h). (Items of class + kSecClassCertificate have this attribute.) + @constant kSecAttrCertificateEncoding (read-only) Specifies a dictionary + key whose value is the item's certificate encoding. You use this key + to get a value of type CFNumberRef that denotes the certificate + encoding (see the CSSM_CERT_ENCODING enum in cssmtype.h). (Items of + class kSecClassCertificate have this attribute.) + @constant kSecAttrKeyClass (read only) Specifies a dictionary key whose + value is one of kSecAttrKeyClassPublic, kSecAttrKeyClassPrivate or + kSecAttrKeyClassSymmetric. + @constant kSecAttrApplicationLabel Specifies a dictionary key whose value + is the key's application label attribute. This is different from the + kSecAttrLabel (which is intended to be human-readable). This attribute + is used to look up a key programmatically; in particular, for keys of + class kSecAttrKeyClassPublic and kSecAttrKeyClassPrivate, the value of + this attribute is the hash of the public key. This item is a type of CFDataRef. + Legacy keys may contain a UUID in this field as a CFStringRef. + @constant kSecAttrIsPermanent Specifies a dictionary key whose value is a + CFBooleanRef indicating whether the key in question will be stored + permanently. + @constant kSecAttrIsSensitive Specifies a dictionary key whose value is a + CFBooleanRef indicating that the key in question can only be exported + in a wrapped (encrypted) format. + @constant kSecAttrIsExtractable Specifies a dictionary key whose value is a + CFBooleanRef indicating whether the key in question can be exported from + its keychain container. + @constant kSecAttrApplicationTag Specifies a dictionary key whose value is a + CFDataRef containing private tag data. + @constant kSecAttrKeyType Specifies a dictionary key whose value is a + CFNumberRef indicating the algorithm associated with this key (see the + CSSM_ALGORITHMS enum in cssmtype.h). + @constant kSecAttrPRF Specifies a dictionary key whose value is the PRF + (pseudo-random function) for this key (see "kSecAttrPRF Value Constants".) + @constant kSecAttrSalt Specifies a dictionary key whose value is a + CFData containing the salt to use for this key. + @constant kSecAttrRounds Specifies a dictionary key whose value is the + number of rounds for the pseudo-random function specified by kSecAttrPRF. + @constant kSecAttrKeySizeInBits Specifies a dictionary key whose value + is a CFNumberRef indicating the number of bits in this key. + @constant kSecAttrEffectiveKeySize Specifies a dictionary key whose value + is a CFNumberRef indicating the effective number of bits in this key. + For example, a DES key has a kSecAttrKeySizeInBits of 64, but a + kSecAttrEffectiveKeySize of 56 bits. + @constant kSecAttrCanEncrypt Specifies a dictionary key whole value is a + CFBooleanRef indicating whether the key in question can be used to + encrypt data. + @constant kSecAttrCanDecrypt Specifies a dictionary key whole value is a + CFBooleanRef indicating whether the key in question can be used to + decrypt data. + @constant kSecAttrCanDerive Specifies a dictionary key whole value is a + CFBooleanRef indicating whether the key in question can be used to + derive another key. + @constant kSecAttrCanSign Specifies a dictionary key whole value is a + CFBooleanRef indicating whether the key in question can be used to + create a digital signature. + @constant kSecAttrCanVerify Specifies a dictionary key whole value is a + CFBooleanRef indicating whether the key in question can be used to + verify a digital signature. + @constant kSecAttrCanWrap Specifies a dictionary key whole value is a + CFBooleanRef indicating whether the key in question can be used to + wrap another key. + @constant kSecAttrCanUnwrap Specifies a dictionary key whole value is a + CFBooleanRef indicating whether the key in question can be used to + unwrap another key. +*/ +extern const CFTypeRef kSecAttrAccessible + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); +extern const CFTypeRef kSecAttrAccess + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecAttrAccessControl + __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); +extern const CFTypeRef kSecAttrAccessGroup + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_3_0); +extern const CFTypeRef kSecAttrSynchronizable + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern const CFTypeRef kSecAttrSynchronizableAny + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern const CFTypeRef kSecAttrCreationDate + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrModificationDate + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrDescription + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrComment + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrCreator + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrType + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrLabel + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrIsInvisible + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrIsNegative + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrAccount + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrService + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrGeneric + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrSecurityDomain + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrServer + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocol + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrAuthenticationType + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrPort + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrPath + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrSubject + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrIssuer + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrSerialNumber + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrSubjectKeyID + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrPublicKeyHash + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrCertificateType + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrCertificateEncoding + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrKeyClass + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrApplicationLabel + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrIsPermanent + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrIsSensitive + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrIsExtractable + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrApplicationTag + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrKeyType + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrPRF + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFTypeRef kSecAttrSalt + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFTypeRef kSecAttrRounds + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFTypeRef kSecAttrKeySizeInBits + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrEffectiveKeySize + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrCanEncrypt + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrCanDecrypt + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrCanDerive + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrCanSign + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrCanVerify + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrCanWrap + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrCanUnwrap + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @enum kSecAttrAccessible Value Constants + @discussion Predefined item attribute constants used to get or set values + in a dictionary. The kSecAttrAccessible constant is the key and its + value is one of the constants defined here. + When asking SecItemCopyMatching to return the item's data, the error + errSecInteractionNotAllowed will be returned if the item's data is not + available until a device unlock occurs. + @constant kSecAttrAccessibleWhenUnlocked Item data can only be accessed + while the device is unlocked. This is recommended for items that only + need be accesible while the application is in the foreground. Items + with this attribute will migrate to a new device when using encrypted + backups. + @constant kSecAttrAccessibleAfterFirstUnlock Item data can only be + accessed once the device has been unlocked after a restart. This is + recommended for items that need to be accesible by background + applications. Items with this attribute will migrate to a new device + when using encrypted backups. + @constant kSecAttrAccessibleAlways Item data can always be accessed + regardless of the lock state of the device. This is not recommended + for anything except system use. Items with this attribute will migrate + to a new device when using encrypted backups. + @constant kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly Item data can + only be accessed while the device is unlocked. This is recommended for + items that only need to be accessible while the application is in the + foreground and requires a passcode to be set on the device. Items with + this attribute will never migrate to a new device, so after a backup + is restored to a new device, these items will be missing. This + attribute will not be available on devices without a passcode. Disabling + the device passcode will cause all previously protected items to + be deleted. + @constant kSecAttrAccessibleWhenUnlockedThisDeviceOnly Item data can only + be accessed while the device is unlocked. This is recommended for items + that only need be accesible while the application is in the foreground. + Items with this attribute will never migrate to a new device, so after + a backup is restored to a new device, these items will be missing. + @constant kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly Item data can + only be accessed once the device has been unlocked after a restart. + This is recommended for items that need to be accessible by background + applications. Items with this attribute will never migrate to a new + device, so after a backup is restored to a new device these items will + be missing. + @constant kSecAttrAccessibleAlwaysThisDeviceOnly Item data can always + be accessed regardless of the lock state of the device. This option + is not recommended for anything except system use. Items with this + attribute will never migrate to a new device, so after a backup is + restored to a new device, these items will be missing. +*/ +extern const CFTypeRef kSecAttrAccessibleWhenUnlocked + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); +extern const CFTypeRef kSecAttrAccessibleAfterFirstUnlock + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); +extern const CFTypeRef kSecAttrAccessibleAlways + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); +extern CFTypeRef kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly + __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); +extern const CFTypeRef kSecAttrAccessibleWhenUnlockedThisDeviceOnly + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); +extern const CFTypeRef kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); +extern const CFTypeRef kSecAttrAccessibleAlwaysThisDeviceOnly + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); + +/*! + @enum kSecAttrProtocol Value Constants + @discussion Predefined item attribute constants used to get or set values + in a dictionary. The kSecAttrProtocol constant is the key and its + value is one of the constants defined here. + @constant kSecAttrProtocolFTP + @constant kSecAttrProtocolFTPAccount + @constant kSecAttrProtocolHTTP + @constant kSecAttrProtocolIRC + @constant kSecAttrProtocolNNTP + @constant kSecAttrProtocolPOP3 + @constant kSecAttrProtocolSMTP + @constant kSecAttrProtocolSOCKS + @constant kSecAttrProtocolIMAP + @constant kSecAttrProtocolLDAP + @constant kSecAttrProtocolAppleTalk + @constant kSecAttrProtocolAFP + @constant kSecAttrProtocolTelnet + @constant kSecAttrProtocolSSH + @constant kSecAttrProtocolFTPS + @constant kSecAttrProtocolHTTPS + @constant kSecAttrProtocolHTTPProxy + @constant kSecAttrProtocolHTTPSProxy + @constant kSecAttrProtocolFTPProxy + @constant kSecAttrProtocolSMB + @constant kSecAttrProtocolRTSP + @constant kSecAttrProtocolRTSPProxy + @constant kSecAttrProtocolDAAP + @constant kSecAttrProtocolEPPC + @constant kSecAttrProtocolIPP + @constant kSecAttrProtocolNNTPS + @constant kSecAttrProtocolLDAPS + @constant kSecAttrProtocolTelnetS + @constant kSecAttrProtocolIMAPS + @constant kSecAttrProtocolIRCS + @constant kSecAttrProtocolPOP3S +*/ +extern const CFTypeRef kSecAttrProtocolFTP + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolFTPAccount + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolHTTP + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolIRC + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolNNTP + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolPOP3 + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolSMTP + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolSOCKS + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolIMAP + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolLDAP + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolAppleTalk + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolAFP + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolTelnet + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolSSH + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolFTPS + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolHTTPS + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolHTTPProxy + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolHTTPSProxy + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolFTPProxy + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolSMB + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolRTSP + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolRTSPProxy + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolDAAP + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolEPPC + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolIPP + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolNNTPS + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolLDAPS + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolTelnetS + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolIMAPS + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolIRCS + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrProtocolPOP3S + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @enum kSecAttrAuthenticationType Value Constants + @discussion Predefined item attribute constants used to get or set values + in a dictionary. The kSecAttrAuthenticationType constant is the key + and its value is one of the constants defined here. + @constant kSecAttrAuthenticationTypeNTLM + @constant kSecAttrAuthenticationTypeMSN + @constant kSecAttrAuthenticationTypeDPA + @constant kSecAttrAuthenticationTypeRPA + @constant kSecAttrAuthenticationTypeHTTPBasic + @constant kSecAttrAuthenticationTypeHTTPDigest + @constant kSecAttrAuthenticationTypeHTMLForm + @constant kSecAttrAuthenticationTypeDefault +*/ +extern const CFTypeRef kSecAttrAuthenticationTypeNTLM + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrAuthenticationTypeMSN + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrAuthenticationTypeDPA + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrAuthenticationTypeRPA + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrAuthenticationTypeHTTPBasic + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrAuthenticationTypeHTTPDigest + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrAuthenticationTypeHTMLForm + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecAttrAuthenticationTypeDefault + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @enum kSecAttrKeyClass Value Constants + @discussion Predefined item attribute constants used to get or set values + in a dictionary. The kSecAttrKeyClass constant is the key + and its value is one of the constants defined here. + @constant kSecAttrKeyClassPublic + @constant kSecAttrKeyClassPrivate + @constant kSecAttrKeyClassSymmetric +*/ +extern const CFTypeRef kSecAttrKeyClassPublic + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); +extern const CFTypeRef kSecAttrKeyClassPrivate + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); +extern const CFTypeRef kSecAttrKeyClassSymmetric + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + +/*! + @enum kSecAttrKeyType Value Constants + @discussion Predefined item attribute constants used to get or set values + in a dictionary. The kSecAttrKeyType constant is the key + and its value is one of the constants defined here. + @constant kSecAttrKeyTypeRSA + @constant kSecAttrKeyTypeDSA + @constant kSecAttrKeyTypeAES + @constant kSecAttrKeyType3DES + @constant kSecAttrKeyTypeRC4 + @constant kSecAttrKeyTypeRC2 + @constant kSecAttrKeyTypeCAST + @constant kSecAttrKeyTypeECDSA (deprecated; use kSecAttrKeyTypeEC instead.) + @constant kSecAttrKeyTypeEC +*/ +extern const CFTypeRef kSecAttrKeyTypeRSA + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); +extern const CFTypeRef kSecAttrKeyTypeDSA + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFTypeRef kSecAttrKeyTypeAES + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFTypeRef kSecAttrKeyTypeDES + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFTypeRef kSecAttrKeyType3DES + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFTypeRef kSecAttrKeyTypeRC4 + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFTypeRef kSecAttrKeyTypeRC2 + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFTypeRef kSecAttrKeyTypeCAST + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFTypeRef kSecAttrKeyTypeECDSA + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFTypeRef kSecAttrKeyTypeEC + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); + +/*! + @enum kSecAttrPRF Value Constants + @discussion Predefined item attribute constants used to specify the PRF + to use with SecKeyDeriveFromPassword. + @constant kSecAttrPRFHmacAlgSHA1 + @constant kSecAttrPRFHmacAlgSHA224 + @constant kSecAttrPRFHmacAlgSHA256 + @constant kSecAttrPRFHmacAlgSHA384 + @constant kSecAttrPRFHmacAlgSHA512 +*/ +extern const CFTypeRef kSecAttrPRFHmacAlgSHA1 + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFTypeRef kSecAttrPRFHmacAlgSHA224 + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFTypeRef kSecAttrPRFHmacAlgSHA256 + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFTypeRef kSecAttrPRFHmacAlgSHA384 + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFTypeRef kSecAttrPRFHmacAlgSHA512 + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @enum Search Constants + @discussion Predefined search constants used to set values in a query + dictionary. You can specify a combination of search attributes and + item attributes when looking for matching items with the + SecItemCopyMatching function. + @constant kSecMatchPolicy Specifies a dictionary key whose value is a + SecPolicyRef. If provided, returned certificates or identities must + verify with this policy. + @constant kSecMatchItemList Specifies a dictionary key whose value is a + CFArray of SecKeychainItemRef items. If provided, returned items will be + limited to the subset which are contained in this list. + @constant kSecMatchSearchList Specifies a dictionary key whose value is a + CFArray of SecKeychainRef items. If provided, the search will be limited + to the keychains contained in this list. + @constant kSecMatchIssuers Specifies a dictionary key whose value is a + CFArray of X.500 names (of type CFDataRef). If provided, returned + certificates or identities will be limited to those whose + certificate chain contains one of the issuers provided in this list. + @constant kSecMatchEmailAddressIfPresent Specifies a dictionary key whose + value is a CFStringRef containing an RFC822 email address. If + provided, returned certificates or identities will be limited to those + that contain the address, or do not contain any email address. + @constant kSecMatchSubjectContains Specifies a dictionary key whose value + is a CFStringRef. If provided, returned certificates or identities + will be limited to those containing this string in the subject. + @constant kSecMatchSubjectStartsWith Specifies a dictionary key whose value + is a CFStringRef. If provided, returned certificates or identities + will be limited to those with subject names that start with this string. + @constant kSecMatchSubjectEndsWith Specifies a dictionary key whose value + is a CFStringRef. If provided, returned certificates or identities + will be limited to those with subject names that end with this string. + @constant kSecMatchSubjectWholeString Specifies a dictionary key whose + value is a CFStringRef. If provided, returned certificates or identities + will be limited to those matching this string exactly in the subject. + @constant kSecMatchCaseInsensitive Specifies a dictionary key whose value + is a CFBooleanRef. If this value is kCFBooleanFalse, or is not + provided, then case-sensitive string matching is performed. + @constant kSecMatchDiacriticInsensitive Specifies a dictionary key whose + value is a CFBooleanRef. If this value is kCFBooleanFalse, or is not + provided, then diacritic-sensitive string matching is performed. + @constant kSecMatchWidthInsensitive Specifies a dictionary key whose + value is a CFBooleanRef. If this value is kCFBooleanFalse, or is not + provided, then string matching is width-sensitive (e.g. 'a' != 0xFF41). + @constant kSecMatchTrustedOnly Specifies a dictionary key whose value is + a CFBooleanRef. If provided with a value of kCFBooleanTrue, only + certificates which can be verified back to a trusted anchor will be + returned. If this value is kCFBooleanFalse, or is not provided, then + both trusted and untrusted certificates may be returned. + @constant kSecMatchValidOnDate Specifies a dictionary key whose value is + of type CFDateRef. If provided, returned keys, certificates or + identities will be limited to those which are valid for the given date. + Pass a value of kCFNull to indicate the current date. + @constant kSecMatchLimit Specifies a dictionary key whose value is a + CFNumberRef. If provided, this value specifies the maximum number of + results to return. If not provided, results are limited to the first + item found. Predefined values are provided for a single item + (kSecMatchLimitOne) and all matching items (kSecMatchLimitAll). + @constant kSecMatchLimitOne Specifies that results are limited to the first + item found; used as a value for the kSecMatchLimit dictionary key. + @constant kSecMatchLimitAll Specifies that an unlimited number of results + may be returned; used as a value for the kSecMatchLimit dictionary + key. +*/ +extern const CFTypeRef kSecMatchPolicy + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecMatchItemList + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecMatchSearchList + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecMatchIssuers + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecMatchEmailAddressIfPresent + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecMatchSubjectContains + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecMatchSubjectStartsWith + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFTypeRef kSecMatchSubjectEndsWith + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFTypeRef kSecMatchSubjectWholeString + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFTypeRef kSecMatchCaseInsensitive + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecMatchDiacriticInsensitive + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFTypeRef kSecMatchWidthInsensitive + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFTypeRef kSecMatchTrustedOnly + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecMatchValidOnDate + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecMatchLimit + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecMatchLimitOne + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecMatchLimitAll + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + + +/*! + @enum Return Type Key Constants + @discussion Predefined return type keys used to set values in a dictionary. + You use these keys to specify the type of results which should be + returned by the SecItemCopyMatching or SecItemAdd function. You can + specify zero or more of these return types. If more than one of these + result types is specified, the result is returned as a CFDictionaryRef + whose keys are the result types and values are the requested data. + @constant kSecReturnData Specifies a dictionary key whose value is of type + CFBooleanRef. A value of kCFBooleanTrue indicates that the data of + an item (CFDataRef) should be returned. For keys and password + items, data is secret (encrypted) and may require the user to enter + a password for access. + @constant kSecReturnAttributes Specifies a dictionary key whose value is + of type CFBooleanRef. A value of kCFBooleanTrue indicates that the + (non-encrypted) attributes of an item (in a CFDictionaryRef) should be + returned. + @constant kSecReturnRef Specifies a dictionary key whose value is a + CFBooleanRef. A value of kCFBooleanTrue indicates that a reference + should be returned. Depending on the item class requested, the + returned reference(s) may be of type SecKeychainItemRef, SecKeyRef, + SecCertificateRef, or SecIdentityRef. + @constant kSecReturnPersistentRef Specifies a dictionary key whose value + is of type CFBooleanRef. A value of kCFBooleanTrue indicates that a + persistent reference to an item (CFDataRef) should be returned. +*/ +extern const CFTypeRef kSecReturnData + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecReturnAttributes + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecReturnRef + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecReturnPersistentRef + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + + +/*! + @enum Value Type Key Constants + @discussion Predefined value type keys used to pass values in a dictionary. + You can specify zero or more of these types depending on the function + you are calling. For SecItemCopyMatching or SecItemAdd these are + used as keys in the results dictionary. + @constant kSecValueData Specifies a dictionary key whose value is of type + CFDataRef. For keys and password items, data is secret (encrypted) + and may require the user to enter a password for access. + @constant kSecValueRef Specifies a dictionary key whose value, depending + on the item class requested, is of type SecKeychainItemRef, SecKeyRef, + SecCertificateRef, or SecIdentityRef. + @constant kSecValuePersistentRef Specifies a dictionary key whose value + is of type CFDataRef. The bytes in this CFDataRef can be stored by + the caller and used on a subsequent invocation of the application (or + even a different application) to retrieve the item referenced by it. +*/ +extern const CFTypeRef kSecValueData + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecValueRef + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecValuePersistentRef + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + + +/*! + @enum Other Constants + @discussion Predefined constants used to set values in a dictionary. + @constant kSecUseItemList Specifies a dictionary key whose value is a + CFArray of items. If provided, this array is treated as the set of + all possible items to search, or add if the API being called is + SecItemAdd. The items in this array may be of type SecKeyRef, + SecCertificateRef, SecIdentityRef, or CFDataRef (for a persistent + item reference.) The items in the array must all be of the same + type. When this attribute is provided, no keychains are searched. + @constant kSecUseKeychain Specifies a dictionary key whose value is a + keychain reference. You use this key to specify a value of type + SecKeychainRef to which SecItemAdd will add the provided item(s). +*/ +extern const CFTypeRef kSecUseItemList + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFTypeRef kSecUseKeychain + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @function SecItemCopyMatching + @abstract Returns one or more items which match a search query. + @param query A dictionary containing an item class specification and + optional attributes for controlling the search. See the "Keychain + Search Attributes" section for a description of currently defined + search attributes. + @param result On return, a CFTypeRef reference to the found item(s). The + exact type of the result is based on the search attributes supplied + in the query, as discussed below. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Attributes defining a search are specified by adding key/value + pairs to the query dictionary. + + A typical query consists of: + + * a kSecClass key, whose value is a constant from the Class + Constants section that specifies the class of item(s) to be searched + * one or more keys from the "Attribute Key Constants" section, whose value + is the attribute data to be matched + * one or more keys from the "Search Constants" section, whose value is + used to further refine the search + * a key from the "Return Type Key Constants" section, specifying the type of + results desired + + Result types are specified as follows: + + * To obtain the data of a matching item (CFDataRef), specify + kSecReturnData with a value of kCFBooleanTrue. + * To obtain the attributes of a matching item (CFDictionaryRef), specify + kSecReturnAttributes with a value of kCFBooleanTrue. + * To obtain a reference to a matching item (SecKeychainItemRef, + SecKeyRef, SecCertificateRef, or SecIdentityRef), specify kSecReturnRef + with a value of kCFBooleanTrue. + * To obtain a persistent reference to a matching item (CFDataRef), + specify kSecReturnPersistentRef with a value of kCFBooleanTrue. Note + that unlike normal references, a persistent reference may be stored + on disk or passed between processes. + * If more than one of these result types is specified, the result is + returned as a CFDictionaryRef containing all the requested data. + + By default, this function returns only the first match found. To obtain + more than one matching item at a time, specify kSecMatchLimit with a value + greater than 1. The result will be a CFArrayRef containing up to that + number of matching items; the items' types are described above. + + To filter a provided list of items down to those matching the query, + specify a kSecMatchItemList whose value is a CFArray of SecKeychainItemRef, + SecKeyRef, SecCertificateRef, or SecIdentityRef items. The objects in the + provided array must be of the same type. + + To convert from persistent item references to normal item references, + specify a kSecMatchItemList whose value is a CFArray containing one or + more CFDataRef elements (the persistent reference), and a kSecReturnRef + whose value is kCFBooleanTrue. The objects in the provided array must be + of the same type. +*/ +OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @function SecItemAdd + @abstract Add one or more items to a keychain. + @param attributes A dictionary containing an item class specification and + optional entries specifying the item's attribute values. See the + "Attribute Key Constants" section for a description of currently defined + attributes. + @param result On return, a CFTypeRef reference to the newly added item(s). + The exact type of the result is based on the values supplied + in attributes, as discussed below. Pass NULL if this result is not + required. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Attributes defining an item are specified by adding key/value + pairs to the attributes dictionary. To add multiple items to a keychain + at once use the kSecUseItemList key with an array of items as its value. + This is currently only supported for non password items. To add an item + to a particular keychain, supply kSecUseKeychain with a SecKeychainRef as + its value. + + Result types are specified as follows: + + * To obtain the data of the added item (CFDataRef), specify + kSecReturnData with a value of kCFBooleanTrue. + * To obtain all the attributes of the added item (CFDictionaryRef), + specify kSecReturnAttributes with a value of kCFBooleanTrue. + * To obtain a reference to the added item (SecKeychainItemRef, SecKeyRef, + SecCertificateRef, or SecIdentityRef), specify kSecReturnRef with a + value of kCFBooleanTrue. This is the default behavior if a result + type is not explicitly specified. + * To obtain a persistent reference to the added item (CFDataRef), specify + kSecReturnPersistentRef with a value of kCFBooleanTrue. Note that + unlike normal references, a persistent reference may be stored on disk + or passed between processes. + * If more than one of these result types is specified, the result is + returned as a CFDictionaryRef containing all the requested data. +*/ +OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @function SecItemUpdate + @abstract Modify zero or more items which match a search query. + @param query A dictionary containing an item class specification and + optional attributes for controlling the search. See the "Attribute + Constants" and "Search Constants" sections for a description of + currently defined search attributes. + @param attributesToUpdate A dictionary containing one or more attributes + whose values should be set to the ones specified. Only real keychain + attributes are permitted in this dictionary (no "meta" attributes are + allowed.) See the "Attribute Key Constants" section for a description of + currently defined value attributes. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Attributes defining a search are specified by adding key/value + pairs to the query dictionary. +*/ +OSStatus SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @function SecItemDelete + @abstract Delete zero or more items which match a search query. + @param query A dictionary containing an item class specification and + optional attributes for controlling the search. See the "Attribute + Constants" and "Search Constants" sections for a description of + currently defined search attributes. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Attributes defining a search are specified by adding key/value + pairs to the query dictionary. + + By default, this function deletes all items matching the specified query. + You can change this behavior by specifying one of the follow keys: + + * To delete an item identified by a transient reference, specify + kSecMatchItemList with a reference returned by using the kSecReturnRef + key in a previous call to SecItemCopyMatching or SecItemAdd. + * To delete an item identified by a persistent reference, specify + kSecMatchItemList with a persistent reference returned by using the + kSecReturnPersistentRef key to SecItemCopyMatching or SecItemAdd. + * If more than one of these result keys is specified, the behavior is + undefined. +*/ +OSStatus SecItemDelete(CFDictionaryRef query) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECITEM_H_ */ diff --git a/Security/libsecurity_keychain/lib/SecItemConstants.c b/Security/libsecurity_keychain/lib/SecItemConstants.c new file mode 100644 index 00000000..91c580c5 --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecItemConstants.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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 __CONSTANT_CFSTRINGS__ 1 +#include + +/* String constant declarations */ + +#define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); + +/* Class Key Constant */ +SEC_CONST_DECL (kSecClass, "class"); + +/* Class Value Constants */ +SEC_CONST_DECL (kSecClassGenericPassword, "genp"); +SEC_CONST_DECL (kSecClassInternetPassword, "inet"); +SEC_CONST_DECL (kSecClassAppleSharePassword, "apls"); +SEC_CONST_DECL (kSecClassCertificate, "cert"); +SEC_CONST_DECL (kSecClassKey, "keys"); +SEC_CONST_DECL (kSecClassIdentity, "idnt"); + +/* Attribute Key Constants */ +SEC_CONST_DECL (kSecAttrAccessible, "pdmn"); +SEC_CONST_DECL (kSecAttrAccessGroup, "agrp"); +SEC_CONST_DECL (kSecAttrAccess, "acls"); +SEC_CONST_DECL (kSecAttrCreationDate, "cdat"); +SEC_CONST_DECL (kSecAttrModificationDate, "mdat"); +SEC_CONST_DECL (kSecAttrDescription, "desc"); +SEC_CONST_DECL (kSecAttrComment, "icmt"); +SEC_CONST_DECL (kSecAttrCreator, "crtr"); +SEC_CONST_DECL (kSecAttrType, "type"); +SEC_CONST_DECL (kSecAttrLabel, "labl"); +SEC_CONST_DECL (kSecAttrIsInvisible, "invi"); +SEC_CONST_DECL (kSecAttrIsNegative, "nega"); +SEC_CONST_DECL (kSecAttrAccount, "acct"); +SEC_CONST_DECL (kSecAttrService, "svce"); +SEC_CONST_DECL (kSecAttrGeneric, "gena"); +SEC_CONST_DECL (kSecAttrSecurityDomain, "sdmn"); +SEC_CONST_DECL (kSecAttrServer, "srvr"); +SEC_CONST_DECL (kSecAttrProtocol, "ptcl"); +SEC_CONST_DECL (kSecAttrAuthenticationType, "atyp"); +SEC_CONST_DECL (kSecAttrPort, "port"); +SEC_CONST_DECL (kSecAttrPath, "path"); +SEC_CONST_DECL (kSecAttrVolume, "volm"); +SEC_CONST_DECL (kSecAttrAddress, "addr"); +SEC_CONST_DECL (kSecAttrAFPServerSignature, "afps"); +SEC_CONST_DECL (kSecAttrAlias, "alis"); +SEC_CONST_DECL (kSecAttrSubject, "subj"); +SEC_CONST_DECL (kSecAttrIssuer, "issr"); +SEC_CONST_DECL (kSecAttrSerialNumber, "slnr"); +SEC_CONST_DECL (kSecAttrSubjectKeyID, "skid"); +SEC_CONST_DECL (kSecAttrPublicKeyHash, "pkhh"); +SEC_CONST_DECL (kSecAttrCertificateType, "ctyp"); +SEC_CONST_DECL (kSecAttrCertificateEncoding, "cenc"); +SEC_CONST_DECL (kSecAttrKeyClass, "kcls"); +SEC_CONST_DECL (kSecAttrApplicationLabel, "klbl"); +SEC_CONST_DECL (kSecAttrIsPermanent, "perm"); +SEC_CONST_DECL (kSecAttrIsModifiable, "modi"); +SEC_CONST_DECL (kSecAttrIsPrivate, "priv"); +SEC_CONST_DECL (kSecAttrApplicationTag, "atag"); +SEC_CONST_DECL (kSecAttrKeyCreator, "crtr"); +SEC_CONST_DECL (kSecAttrKeyType, "type"); +SEC_CONST_DECL (kSecAttrPRF, "prf"); +SEC_CONST_DECL (kSecAttrSalt, "salt"); +SEC_CONST_DECL (kSecAttrRounds, "rounds"); +SEC_CONST_DECL (kSecAttrKeySizeInBits, "bsiz"); +SEC_CONST_DECL (kSecAttrEffectiveKeySize, "esiz"); +SEC_CONST_DECL (kSecAttrStartDate, "sdat"); +SEC_CONST_DECL (kSecAttrEndDate, "edat"); +SEC_CONST_DECL (kSecAttrIsSensitive, "sens"); +SEC_CONST_DECL (kSecAttrWasAlwaysSensitive, "asen"); +SEC_CONST_DECL (kSecAttrIsExtractable, "extr"); +SEC_CONST_DECL (kSecAttrWasNeverExtractable, "next"); +SEC_CONST_DECL (kSecAttrCanEncrypt, "encr"); +SEC_CONST_DECL (kSecAttrCanDecrypt, "decr"); +SEC_CONST_DECL (kSecAttrCanDerive, "drve"); +SEC_CONST_DECL (kSecAttrCanSign, "sign"); +SEC_CONST_DECL (kSecAttrCanVerify, "vrfy"); +SEC_CONST_DECL (kSecAttrCanSignRecover, "snrc"); +SEC_CONST_DECL (kSecAttrCanVerifyRecover, "vyrc"); +SEC_CONST_DECL (kSecAttrCanWrap, "wrap"); +SEC_CONST_DECL (kSecAttrCanUnwrap, "unwp"); +/* Attribute Constants (Private) */ +SEC_CONST_DECL (kSecAttrScriptCode, "scrp"); +SEC_CONST_DECL (kSecAttrHasCustomIcon, "cusi"); +SEC_CONST_DECL (kSecAttrCRLType, "crlt"); +SEC_CONST_DECL (kSecAttrCRLEncoding, "crle"); +SEC_CONST_DECL (kSecAttrSynchronizable, "sync"); +SEC_CONST_DECL (kSecAttrSynchronizableAny, "syna"); +SEC_CONST_DECL (kSecAttrTombstone, "tomb"); + +/* Search Constants */ +SEC_CONST_DECL (kSecMatchPolicy, "m_Policy"); +SEC_CONST_DECL (kSecMatchItemList, "m_ItemList"); +SEC_CONST_DECL (kSecMatchSearchList, "m_SearchList"); +SEC_CONST_DECL (kSecMatchIssuers, "m_Issuers"); +SEC_CONST_DECL (kSecMatchEmailAddressIfPresent, "m_EmailAddressIfPresent"); +SEC_CONST_DECL (kSecMatchSubjectContains, "m_SubjectContains"); +SEC_CONST_DECL (kSecMatchSubjectStartsWith, "m_SubjectStartsWith"); +SEC_CONST_DECL (kSecMatchSubjectEndsWith, "m_SubjectEndsWith"); +SEC_CONST_DECL (kSecMatchSubjectWholeString, "m_SubjectWholeString"); +SEC_CONST_DECL (kSecMatchCaseInsensitive, "m_CaseInsensitive"); +SEC_CONST_DECL (kSecMatchDiacriticInsensitive, "m_DiacriticInsensitive"); +SEC_CONST_DECL (kSecMatchWidthInsensitive, "m_WidthInsensitive"); +SEC_CONST_DECL (kSecMatchTrustedOnly, "m_TrustedOnly"); +SEC_CONST_DECL (kSecMatchValidOnDate, "m_ValidOnDate"); +SEC_CONST_DECL (kSecMatchLimit, "m_Limit"); +/* Could just use kCFBooleanTrue and kCFBooleanFalse for these 2. */ +SEC_CONST_DECL (kSecMatchLimitOne, "m_LimitOne"); +SEC_CONST_DECL (kSecMatchLimitAll, "m_LimitAll"); + +/* Return Type Key Constants */ +SEC_CONST_DECL (kSecReturnData, "r_Data"); +SEC_CONST_DECL (kSecReturnAttributes, "r_Attributes"); +SEC_CONST_DECL (kSecReturnRef, "r_Ref"); +SEC_CONST_DECL (kSecReturnPersistentRef, "r_PersistentRef"); + +/* Value Type Key Constants */ +SEC_CONST_DECL (kSecValueData, "v_Data"); +SEC_CONST_DECL (kSecValueRef, "v_Ref"); +SEC_CONST_DECL (kSecValuePersistentRef, "v_PersistentRef"); + +/* Other Constants */ +SEC_CONST_DECL (kSecUseItemList, "u_ItemList"); +SEC_CONST_DECL (kSecUseKeychain, "u_Keychain"); + +/* kSecAttrAccessible Value Constants. */ +SEC_CONST_DECL (kSecAttrAccessibleWhenUnlocked, "ak"); +SEC_CONST_DECL (kSecAttrAccessibleAfterFirstUnlock, "ck"); +SEC_CONST_DECL (kSecAttrAccessibleAlways, "dk"); +SEC_CONST_DECL (kSecAttrAccessibleWhenUnlockedThisDeviceOnly, "aku"); +SEC_CONST_DECL (kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, "cku"); +SEC_CONST_DECL (kSecAttrAccessibleAlwaysThisDeviceOnly, "dku"); +SEC_CONST_DECL (kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, "akpu"); + +/* kSecAttrProtocol Value Constants. */ +SEC_CONST_DECL (kSecAttrProtocolFTP, "ftp "); +SEC_CONST_DECL (kSecAttrProtocolFTPAccount, "ftpa"); +SEC_CONST_DECL (kSecAttrProtocolHTTP, "http"); +SEC_CONST_DECL (kSecAttrProtocolIRC, "irc "); +SEC_CONST_DECL (kSecAttrProtocolNNTP, "nntp"); +SEC_CONST_DECL (kSecAttrProtocolPOP3, "pop3"); +SEC_CONST_DECL (kSecAttrProtocolSMTP, "smtp"); +SEC_CONST_DECL (kSecAttrProtocolSOCKS, "sox "); +SEC_CONST_DECL (kSecAttrProtocolIMAP, "imap"); +SEC_CONST_DECL (kSecAttrProtocolLDAP, "ldap"); +SEC_CONST_DECL (kSecAttrProtocolAppleTalk, "atlk"); +SEC_CONST_DECL (kSecAttrProtocolAFP, "afp "); +SEC_CONST_DECL (kSecAttrProtocolTelnet, "teln"); +SEC_CONST_DECL (kSecAttrProtocolSSH, "ssh "); +SEC_CONST_DECL (kSecAttrProtocolFTPS, "ftps"); +SEC_CONST_DECL (kSecAttrProtocolHTTPS, "htps"); +SEC_CONST_DECL (kSecAttrProtocolHTTPProxy, "htpx"); +SEC_CONST_DECL (kSecAttrProtocolHTTPSProxy, "htsx"); +SEC_CONST_DECL (kSecAttrProtocolFTPProxy, "ftpx"); +SEC_CONST_DECL (kSecAttrProtocolSMB, "smb "); +SEC_CONST_DECL (kSecAttrProtocolRTSP, "rtsp"); +SEC_CONST_DECL (kSecAttrProtocolRTSPProxy, "rtsx"); +SEC_CONST_DECL (kSecAttrProtocolDAAP, "daap"); +SEC_CONST_DECL (kSecAttrProtocolEPPC, "eppc"); +SEC_CONST_DECL (kSecAttrProtocolIPP, "ipp "); +SEC_CONST_DECL (kSecAttrProtocolNNTPS, "ntps"); +SEC_CONST_DECL (kSecAttrProtocolLDAPS, "ldps"); +SEC_CONST_DECL (kSecAttrProtocolTelnetS, "tels"); +SEC_CONST_DECL (kSecAttrProtocolIMAPS, "imps"); +SEC_CONST_DECL (kSecAttrProtocolIRCS, "ircs"); +SEC_CONST_DECL (kSecAttrProtocolPOP3S, "pops"); + +/* kSecAttrAuthenticationType Value Constants. */ +SEC_CONST_DECL (kSecAttrAuthenticationTypeNTLM, "ntlm"); +SEC_CONST_DECL (kSecAttrAuthenticationTypeMSN, "msna"); +SEC_CONST_DECL (kSecAttrAuthenticationTypeDPA, "dpaa"); +SEC_CONST_DECL (kSecAttrAuthenticationTypeRPA, "rpaa"); +SEC_CONST_DECL (kSecAttrAuthenticationTypeHTTPBasic, "http"); +SEC_CONST_DECL (kSecAttrAuthenticationTypeHTTPDigest, "httd"); +SEC_CONST_DECL (kSecAttrAuthenticationTypeHTMLForm, "form"); +SEC_CONST_DECL (kSecAttrAuthenticationTypeDefault, "dflt"); + +/* kSecAttrKeyClass Value Constants. Based on + CSSM_KEYCLASS_PUBLIC_KEY = 0, + CSSM_KEYCLASS_PRIVATE_KEY = 1, + CSSM_KEYCLASS_SESSION_KEY = 2, + */ +SEC_CONST_DECL (kSecAttrKeyClassPublic, "0"); +SEC_CONST_DECL (kSecAttrKeyClassPrivate, "1"); +SEC_CONST_DECL (kSecAttrKeyClassSymmetric, "2"); + +/* kSecAttrKeyType Value Constants. Based on CSSM_ALGORITHMS. */ +SEC_CONST_DECL (kSecAttrKeyTypeDES, "14"); +SEC_CONST_DECL (kSecAttrKeyType3DES, "17"); +SEC_CONST_DECL (kSecAttrKeyTypeRC2, "23"); +SEC_CONST_DECL (kSecAttrKeyTypeRC4, "25"); +SEC_CONST_DECL (kSecAttrKeyTypeRSA, "42"); +SEC_CONST_DECL (kSecAttrKeyTypeDSA, "43"); +SEC_CONST_DECL (kSecAttrKeyTypeCAST, "56"); +SEC_CONST_DECL (kSecAttrKeyTypeECDSA, "73"); +SEC_CONST_DECL (kSecAttrKeyTypeEC, "73"); /* rdar://13326326 */ +SEC_CONST_DECL (kSecAttrKeyTypeAES, "2147483649"); /* */ + +SEC_CONST_DECL (kSecAttrPRFHmacAlgSHA1, "hsha1"); +SEC_CONST_DECL (kSecAttrPRFHmacAlgSHA224, "hsha224"); +SEC_CONST_DECL (kSecAttrPRFHmacAlgSHA256, "hsha256"); +SEC_CONST_DECL (kSecAttrPRFHmacAlgSHA384, "hsha384"); +SEC_CONST_DECL (kSecAttrPRFHmacAlgSHA512, "hsha512"); + + +/* Constants used by SecKeyGeneratePair() - in SecKey.h. Never used in + any SecItem apis directly. */ +SEC_CONST_DECL (kSecPrivateKeyAttrs, "private"); +SEC_CONST_DECL (kSecPublicKeyAttrs, "public"); +/* Used for SecKeyGenerateSymmetric */ +SEC_CONST_DECL (kSecSymmetricKeyAttrs, "symmetric"); + diff --git a/Security/libsecurity_keychain/lib/SecItemPriv.h b/Security/libsecurity_keychain/lib/SecItemPriv.h new file mode 100644 index 00000000..db018b99 --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecItemPriv.h @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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 SecItemPriv + SecItemPriv defines private constants and SPI functions for access to + Security items (certificates, identities, keys, and keychain items.) + */ + +#ifndef _SECURITY_SECITEMPRIV_H_ +#define _SECURITY_SECITEMPRIV_H_ + +#include +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + /*! + @enum Class Value Constants (Private) + @discussion Predefined item class constants used to get or set values in + a dictionary. The kSecClass constant is the key and its value is one + of the constants defined here. + @constant kSecClassAppleSharePassword Specifies AppleShare password items. + */ + extern const CFTypeRef kSecClassAppleSharePassword; + + /*! + @enum Attribute Key Constants (Private) + @discussion Predefined item attribute keys used to get or set values in a + dictionary. Not all attributes apply to each item class. The table + below lists the currently defined attributes for each item class: + + kSecClassGenericPassword item attributes: + kSecAttrAccessGroup + kSecAttrCreationDate + kSecAttrModificationDate + kSecAttrDescription + kSecAttrComment + kSecAttrCreator + kSecAttrType + kSecAttrScriptCode (private) + kSecAttrLabel + kSecAttrAlias (private) + kSecAttrIsInvisible + kSecAttrIsNegative + kSecAttrHasCustomIcon (private) + kSecAttrProtected (private) + kSecAttrAccount + kSecAttrService + kSecAttrGeneric + + kSecClassInternetPassword item attributes: + kSecAttrAccessGroup + kSecAttrCreationDate + kSecAttrModificationDate + kSecAttrDescription + kSecAttrComment + kSecAttrCreator + kSecAttrType + kSecAttrScriptCode (private) + kSecAttrLabel + kSecAttrAlias (private) + kSecAttrIsInvisible + kSecAttrIsNegative + kSecAttrHasCustomIcon (private) + kSecAttrProtected (private) + kSecAttrAccount + kSecAttrSecurityDomain + kSecAttrServer + kSecAttrProtocol + kSecAttrAuthenticationType + kSecAttrPort + kSecAttrPath + + kSecClassAppleSharePassword item attributes: + kSecAttrAccessGroup + kSecAttrCreationDate + kSecAttrModificationDate + kSecAttrDescription + kSecAttrComment + kSecAttrCreator + kSecAttrType + kSecAttrScriptCode (private) + kSecAttrLabel + kSecAttrAlias (private) + kSecAttrIsInvisible + kSecAttrIsNegative + kSecAttrHasCustomIcon (private) + kSecAttrProtected (private) + kSecAttrAccount + kSecAttrVolume + kSecAttrAddress + kSecAttrAFPServerSignature + + kSecClassCertificate item attributes: + kSecAttrAccessGroup + kSecAttrCertificateType + kSecAttrCertificateEncoding + kSecAttrLabel + kSecAttrAlias (private) + kSecAttrSubject + kSecAttrIssuer + kSecAttrSerialNumber + kSecAttrSubjectKeyID + kSecAttrPublicKeyHash + + kSecClassKey item attributes: + kSecAttrAccessGroup + kSecAttrKeyClass + kSecAttrLabel + kSecAttrAlias (private) + kSecAttrApplicationLabel + kSecAttrIsPermanent + kSecAttrIsPrivate (private) + kSecAttrIsModifiable (private) + kSecAttrApplicationTag + kSecAttrKeyCreator (private) + kSecAttrKeyType + kSecAttrKeySizeInBits + kSecAttrEffectiveKeySize + kSecAttrStartDate (private) + kSecAttrEndDate (private) + kSecAttrIsSensitive (private) + kSecAttrWasAlwaysSensitive (private) + kSecAttrIsExtractable (private) + kSecAttrWasNeverExtractable (private) + kSecAttrCanEncrypt + kSecAttrCanDecrypt + kSecAttrCanDerive + kSecAttrCanSign + kSecAttrCanVerify + kSecAttrCanSignRecover (private) + kSecAttrCanVerifyRecover (private) + kSecAttrCanWrap + kSecAttrCanUnwrap + + kSecClassIdentity item attributes: + Since an identity is the combination of a private key and a + certificate, this class shares attributes of both kSecClassKey and + kSecClassCertificate. + + @constant kSecAttrScriptCode Specifies a dictionary key whose value is the + item's script code attribute. You use this tag to set or get a value + of type CFNumberRef that represents a script code for this item's + strings. (Note: use of this attribute is deprecated; string attributes + should always be stored in UTF-8 encoding. This is currently private + for use by syncing; new code should not ever access this attribute.) + @constant kSecAttrAlias Specifies a dictionary key whose value is the + item's alias. You use this key to get or set a value of type CFDataRef + which represents an alias. For certificate items, the alias is either + a single email address, an array of email addresses, or the common + name of the certificate if it does not contain any email address. + (Items of class kSecClassCertificate have this attribute.) + @constant kSecAttrHasCustomIcon Specifies a dictionary key whose value is the + item's custom icon attribute. You use this tag to set or get a value + of type CFBooleanRef that indicates whether the item should have an + application-specific icon. (Note: use of this attribute is deprecated; + custom item icons are not supported in Mac OS X. This is currently + private for use by syncing; new code should not use this attribute.) + @constant kSecAttrVolume Specifies a dictionary key whose value is the + item's volume attribute. You use this key to set or get a CFStringRef + value that represents an AppleShare volume name. (Items of class + kSecClassAppleSharePassword have this attribute.) + @constant kSecAttrAddress Specifies a dictionary key whose value is the + item's address attribute. You use this key to set or get a CFStringRef + value that contains the AppleTalk zone name, or the IP or domain name + that represents the server address. (Items of class + kSecClassAppleSharePassword have this attribute.) + @constant kSecAttrAFPServerSignature Specifies a dictionary key whose value + is the item's AFP server signature attribute. You use this key to set + or get a CFDataRef value containing 16 bytes that represents the + server's signature block. (Items of class kSecClassAppleSharePassword + have this attribute.) + @constant kSecAttrCRLType (read-only) Specifies a dictionary key whose + value is the item's certificate revocation list type. You use this + key to get a value of type CFNumberRef that denotes the CRL type (see + the CSSM_CRL_TYPE enum in cssmtype.h). (Items of class + kSecClassCertificate have this attribute.) + @constant kSecAttrCRLEncoding (read-only) Specifies a dictionary key whose + value is the item's certificate revocation list encoding. You use + this key to get a value of type CFNumberRef that denotes the CRL + encoding (see the CSSM_CRL_ENCODING enum in cssmtype.h). (Items of + class kSecClassCertificate have this attribute.) + @constant kSecAttrKeyCreator Specifies a dictionary key whose value is a + CFDataRef containing a CSSM_GUID structure representing the module ID of + the CSP that owns this key. + @constant kSecAttrIsPrivate Specifies a dictionary key whose value is a + CFBooleanRef indicating whether the raw key material of the key in + question is private. + @constant kSecAttrIsModifiable Specifies a dictionary key whose value is a + CFBooleanRef indicating whether any of the attributes of this key are + modifiable. + @constant kSecAttrStartDate Specifies a dictionary key whose value is a + CFDateRef indicating the earliest date on which this key may be used. + If kSecAttrStartDate is not present, the restriction does not apply. + @constant kSecAttrEndDate Specifies a dictionary key whose value is a + CFDateRef indicating the last date on which this key may be used. + If kSecAttrEndDate is not present, the restriction does not apply. + @constant kSecAttrWasAlwaysSensitive Specifies a dictionary key whose value + is a CFBooleanRef indicating that the key in question has always been + marked as sensitive. + @constant kSecAttrWasNeverExtractable Specifies a dictionary key whose value + is a CFBooleanRef indicating that the key in question has never been + marked as extractable. + @constant kSecAttrCanSignRecover Specifies a dictionary key whose value is a + CFBooleanRef indicating whether the key in question can be used to + perform sign recovery. + @constant kSecAttrCanVerifyRecover Specifies a dictionary key whose value is + a CFBooleanRef indicating whether the key in question can be used to + perform verify recovery. + @constant kSecAttrTombstone Specifies a dictionary key whose value is + a CFBooleanRef indicating that the item in question is a tombstone. + @constant kSecCredentialReference Specifies a CFDataRef containing CoreAuthentication + reference handle to be used when authorizing access to the item. + */ + extern CFTypeRef kSecAttrScriptCode; + extern CFTypeRef kSecAttrAlias; + extern CFTypeRef kSecAttrHasCustomIcon; + extern CFTypeRef kSecAttrVolume; + extern CFTypeRef kSecAttrAddress; + extern CFTypeRef kSecAttrAFPServerSignature; + extern CFTypeRef kSecAttrCRLType; + extern CFTypeRef kSecAttrCRLEncoding; + extern CFTypeRef kSecAttrKeyCreator; + extern CFTypeRef kSecAttrIsPrivate; + extern CFTypeRef kSecAttrIsModifiable; + extern CFTypeRef kSecAttrStartDate; + extern CFTypeRef kSecAttrEndDate; + extern CFTypeRef kSecAttrWasAlwaysSensitive; + extern CFTypeRef kSecAttrWasNeverExtractable; + extern CFTypeRef kSecAttrCanSignRecover; + extern CFTypeRef kSecAttrCanVerifyRecover; + extern CFTypeRef kSecAttrTombstone; + extern CFTypeRef kSecCredentialReference; + + /*! + @function SecItemCopyDisplayNames + @abstract Returns an array containing unique display names for each of the + certificates, keys, identities, or passwords in the provided items + array. + @param items An array containing items of type SecKeychainItemRef, + SecKeyRef, SecCertificateRef, or SecIdentityRef. All items in the + array should be of the same type. + @param displayNames On return, an array of CFString references containing + unique names for the supplied items. You are responsible for releasing + this array reference by calling the CFRelease function. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Use this function to obtain item names which are suitable for + display in a menu or list view. The returned names are guaranteed to + be unique across the set of provided items. + */ + OSStatus SecItemCopyDisplayNames(CFArrayRef items, CFArrayRef *displayNames); + + /*! + @function SecItemDeleteAll + @abstract Removes all items from the keychain and added root certificates + from the trust store. + @result A result code. See "Security Error Codes" (SecBase.h). + */ + OSStatus SecItemDeleteAll(void); + +/* Called by clients to push sync circle and message changes to us. + Requires caller to have the kSecEntitlementKeychainSyncUpdates entitlement. */ +CFArrayRef _SecKeychainSyncUpdateKeyParameter(CFDictionaryRef updates, CFErrorRef *error); +CFArrayRef _SecKeychainSyncUpdateCircle(CFDictionaryRef updates, CFErrorRef *error); +CFArrayRef _SecKeychainSyncUpdateMessage(CFDictionaryRef updates, CFErrorRef *error); + +CFDataRef _SecItemGetPersistentReference(CFTypeRef raw_item); + +bool _SecKeychainBackupSyncable(CFDataRef keybag, CFDataRef password, CFDictionaryRef backup_in, CFDictionaryRef *backup_out); +bool _SecKeychainRestoreSyncable(CFDataRef keybag, CFDataRef password, CFDictionaryRef backup_in); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECITEMPRIV_H_ */ diff --git a/libsecurity_keychain/lib/SecKey.cpp b/Security/libsecurity_keychain/lib/SecKey.cpp similarity index 97% rename from libsecurity_keychain/lib/SecKey.cpp rename to Security/libsecurity_keychain/lib/SecKey.cpp index a08bdd15..d11deeb1 100644 --- a/libsecurity_keychain/lib/SecKey.cpp +++ b/Security/libsecurity_keychain/lib/SecKey.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -327,6 +327,12 @@ SecKeyCreateWithCSSMKey(const CSSM_KEY *cssmKey, BEGIN_SECAPI Required(cssmKey); + if(cssmKey->KeyData.Length == 0){ + MacOSError::throwMe(errSecInvalidAttributeKeyLength); + } + if(cssmKey->KeyData.Data == NULL){ + MacOSError::throwMe(errSecInvalidPointer); + } CssmClient::CSP csp(cssmKey->KeyHeader.CspId); CssmClient::Key key(csp, *cssmKey); KeyItem *item = new KeyItem(key); @@ -1267,7 +1273,11 @@ SecKeyCreateFromData(CFDictionaryRef parameters, CFDataRef keyData, CFErrorRef * CSSM_KEYUSE keyUsage; CSSM_KEYCLASS keyClass; CSSM_RETURN crtn; - + + if(keyData == NULL || CFDataGetLength(keyData) == 0){ + MacOSError::throwMe(errSecUnsupportedKeySize); + } + utilGetKeyParametersFromCFDict(parameters, &algorithm, &keySizeInBits, &keyUsage, &keyClass); CSSM_CSP_HANDLE cspHandle = cuCspStartup(CSSM_FALSE); // TRUE => CSP, FALSE => CSPDL @@ -1338,24 +1348,32 @@ SecKeyGeneratePairAsync(CFDictionaryRef parametersWhichMightBeMutiable, dispatch }); } +static inline void utilClearAndFree(void *p, size_t len) { + if(p) { + if(len) bzero(p, len); + free(p); + } +} + SecKeyRef SecKeyDeriveFromPassword(CFStringRef password, CFDictionaryRef parameters, CFErrorRef *error) { + CCPBKDFAlgorithm algorithm; + CFIndex passwordLen = 0; + CFDataRef keyData = NULL; char *thePassword = NULL; - CFIndex passwordLen; uint8_t *salt = NULL; - size_t saltLen; - CCPBKDFAlgorithm algorithm; - uint rounds; uint8_t *derivedKey = NULL; - size_t derivedKeyLen; + size_t saltLen = 0, derivedKeyLen = 0; + uint rounds; CFDataRef saltDictValue, algorithmDictValue; - + SecKeyRef retval = NULL; + /* Pick Values from parameters */ if((saltDictValue = (CFDataRef) CFDictionaryGetValue(parameters, kSecAttrSalt)) == NULL) { *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecMissingAlgorithmParms, NULL); - return NULL; + goto errOut; } derivedKeyLen = utilGetNumberFromCFDict(parameters, kSecAttrKeySizeInBits, 128); @@ -1371,28 +1389,23 @@ SecKeyDeriveFromPassword(CFStringRef password, CFDictionaryRef parameters, CFErr saltLen = CFDataGetLength(saltDictValue); if((salt = (uint8_t *) malloc(saltLen)) == NULL) { *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL); - return NULL; + goto errOut; } CFDataGetBytes(saltDictValue, CFRangeMake(0, saltLen), (UInt8 *) salt); passwordLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(password), kCFStringEncodingUTF8) + 1; if((thePassword = (char *) malloc(passwordLen)) == NULL) { - free(salt); *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL); - return NULL; + goto errOut; } CFStringGetBytes(password, CFRangeMake(0, CFStringGetLength(password)), kCFStringEncodingUTF8, '?', FALSE, (UInt8*)thePassword, passwordLen, &passwordLen); if((derivedKey = (uint8_t *) malloc(derivedKeyLen)) == NULL) { - free(salt); - bzero(thePassword, strlen(thePassword)); - free(thePassword); *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecAllocate, NULL); - return NULL; + goto errOut; } - if(algorithmDictValue == NULL) { algorithm = kCCPRFHmacAlgSHA1; /* default */ } else if(CFEqual(algorithmDictValue, kSecAttrPRFHmacAlgSHA1)) { @@ -1406,32 +1419,31 @@ SecKeyDeriveFromPassword(CFStringRef password, CFDictionaryRef parameters, CFErr } else if(CFEqual(algorithmDictValue, kSecAttrPRFHmacAlgSHA512)) { algorithm = kCCPRFHmacAlgSHA512; } else { -#warning "This else clause is here to prevent the use of unitialized variable, but really, this should return an error, without leaking." - algorithm = kCCPRFHmacAlgSHA1; + *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInvalidAlgorithmParms, NULL); + goto errOut; } if(rounds == 0) { rounds = 33333; // we need to pass back a consistent value since there's no way to record the round count. } - if(CCKeyDerivationPBKDF(kCCPBKDF2, thePassword, passwordLen, salt, saltLen, algorithm, rounds, derivedKey, derivedKeyLen)) { -#warning "Aren't we leaking salt and thePassword when this fail???" *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInternalError, NULL); - return NULL; + goto errOut; } - - free(salt); - bzero(thePassword, strlen(thePassword)); - free(thePassword); - - CFDataRef keyData = CFDataCreate(NULL, derivedKey, derivedKeyLen); - bzero(derivedKey, derivedKeyLen); - free(derivedKey); - - SecKeyRef retval = SecKeyCreateFromData(parameters, keyData, error); + + if((keyData = CFDataCreate(NULL, derivedKey, derivedKeyLen)) != NULL) { + retval = SecKeyCreateFromData(parameters, keyData, error); + CFRelease(keyData); + } else { + *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInternalError, NULL); + } + +errOut: + utilClearAndFree(salt, saltLen); + utilClearAndFree(thePassword, passwordLen); + utilClearAndFree(derivedKey, derivedKeyLen); return retval; - } CFDataRef @@ -1768,6 +1780,8 @@ static inline CFDataRef _CFDataCreateCopyFromRange(CFAllocatorRef allocator, CFD return CFDataCreate(allocator, CFDataGetBytePtr(sourceData) + range.location, range.length); } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" static inline bool _CFDataEquals(CFDataRef left, CFDataRef right) { return (left != NULL) && @@ -1775,6 +1789,7 @@ static inline bool _CFDataEquals(CFDataRef left, CFDataRef right) (CFDataGetLength(left) == CFDataGetLength(right)) && (0 == memcmp(CFDataGetBytePtr(left), CFDataGetBytePtr(right), (size_t)CFDataGetLength(left))); } +#pragma clang diagnostic pop #if ECDSA_DEBUG void secdump(const unsigned char *data, unsigned long len) @@ -1965,7 +1980,7 @@ SecKeyRef SecKeyCreateFromPublicData(CFAllocatorRef allocator, CFIndex algorithm CFDataRef workingData = NULL; CFArrayRef outArray = NULL; SecKeyRef retVal = NULL; - + if (kSecRSAAlgorithmID == algorithmID) { /* * kSecFormatBSAFE uses the original PKCS#1 definition: @@ -1979,15 +1994,27 @@ SecKeyRef SecKeyCreateFromPublicData(CFAllocatorRef allocator, CFIndex algorithm workingData = _CFDataCreateReferenceFromRange(kCFAllocatorDefault, publicBytes, CFRangeMake(0, CFDataGetLength(publicBytes))); } else if (kSecECDSAAlgorithmID == algorithmID) { CFMutableDataRef tempData; + uint8 requiredFirstDERByte [] = {0x04}; + uint8 placeholder[1]; uint8 headerBytes[] = { 0x30,0x59,0x30,0x13,0x06,0x07,0x2a,0x86, 0x48,0xce,0x3d,0x02,0x01,0x06,0x08,0x2a, 0x86,0x48,0xce,0x3d,0x03,0x01,0x07,0x03, 0x42,0x00 }; - /* FIXME: this code only handles one specific curve type; need to expand this */ + /* FIXME: this code only handles one specific curve type; need to expand this */ + if(CFDataGetLength(publicBytes) != 65) + goto cleanup; + + CFDataGetBytes(publicBytes, CFRangeMake(0, 1), placeholder); + + if(requiredFirstDERByte[0] != placeholder[0]) + goto cleanup; + + tempData = CFDataCreateMutable(kCFAllocatorDefault, 0); CFDataAppendBytes(tempData, headerBytes, sizeof(headerBytes)); CFDataAppendBytes(tempData, CFDataGetBytePtr(publicBytes), CFDataGetLength(publicBytes)); + workingData = tempData; } if(SecItemImport(workingData, NULL, &externalFormat, &externalItemType, 0, NULL, NULL, &outArray) != errSecSuccess) { diff --git a/Security/libsecurity_keychain/lib/SecKey.h b/Security/libsecurity_keychain/lib/SecKey.h new file mode 100644 index 00000000..8c70dfa2 --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecKey.h @@ -0,0 +1,604 @@ +/* + * Copyright (c) 2002-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecKey + The functions provided in SecKey.h implement and manage a particular + type of keychain item that represents a key. A key can be stored in a + keychain, but a key can also be a transient object. + + You can use a key as a keychain item in most functions. +*/ + +#ifndef _SECURITY_SECKEY_H_ +#define _SECURITY_SECKEY_H_ + +#include +#include +#include +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + @enum KeyItemAttributeConstants + @abstract Specifies keychain item attributes for keys. + @constant kSecKeyKeyClass type uint32 (CSSM_KEYCLASS), value + is one of CSSM_KEYCLASS_PUBLIC_KEY, CSSM_KEYCLASS_PRIVATE_KEY + or CSSM_KEYCLASS_SESSION_KEY. + @constant kSecKeyPrintName type blob, human readable name of + the key. Same as kSecLabelItemAttr for normal keychain items. + @constant kSecKeyAlias type blob, currently unused. + @constant kSecKeyPermanent type uint32, value is nonzero iff + this key is permanent (stored in some keychain). This is always + 1. + @constant kSecKeyPrivate type uint32, value is nonzero iff this + key is protected by a user login or a password, or both. + @constant kSecKeyModifiable type uint32, value is nonzero iff + attributes of this key can be modified. + @constant kSecKeyLabel type blob, for private and public keys + this contains the hash of the public key. This is used to + associate certificates and keys. Its value matches the value + of the kSecPublicKeyHashItemAttr of a certificate and it's used + to construct an identity from a certificate and a key. + For symmetric keys this is whatever the creator of the key + passed in during the generate key call. + @constant kSecKeyApplicationTag type blob, currently unused. + @constant kSecKeyKeyCreator type data, the data points to a + CSSM_GUID structure representing the moduleid of the csp owning + this key. + @constant kSecKeyKeyType type uint32, value is a CSSM_ALGORITHMS + representing the algorithm associated with this key. + @constant kSecKeyKeySizeInBits type uint32, value is the number + of bits in this key. + @constant kSecKeyEffectiveKeySize type uint32, value is the + effective number of bits in this key. For example a des key + has a kSecKeyKeySizeInBits of 64 but a kSecKeyEffectiveKeySize + of 56. + @constant kSecKeyStartDate type CSSM_DATE. Earliest date from + which this key may be used. If the value is all zeros or not + present, no restriction applies. + @constant kSecKeyEndDate type CSSM_DATE. Latest date at + which this key may be used. If the value is all zeros or not + present, no restriction applies. + @constant kSecKeySensitive type uint32, iff value is nonzero + this key cannot be wrapped with CSSM_ALGID_NONE. + @constant kSecKeyAlwaysSensitive type uint32, value is nonzero + iff this key has always been marked sensitive. + @constant kSecKeyExtractable type uint32, value is nonzero iff + this key can be wrapped. + @constant kSecKeyNeverExtractable type uint32, value is nonzero + iff this key was never marked extractable. + @constant kSecKeyEncrypt type uint32, value is nonzero iff this + key can be used in an encrypt operation. + @constant kSecKeyDecrypt type uint32, value is nonzero iff this + key can be used in a decrypt operation. + @constant kSecKeyDerive type uint32, value is nonzero iff this + key can be used in a deriveKey operation. + @constant kSecKeySign type uint32, value is nonzero iff this + key can be used in a sign operation. + @constant kSecKeyVerify type uint32, value is nonzero iff this + key can be used in a verify operation. + @constant kSecKeySignRecover type uint32. + @constant kSecKeyVerifyRecover type uint32. + key can unwrap other keys. + @constant kSecKeyWrap type uint32, value is nonzero iff this + key can wrap other keys. + @constant kSecKeyUnwrap type uint32, value is nonzero iff this + key can unwrap other keys. + @discussion + The use of these enumerations has been deprecated. Please + use the equivalent items defined in SecItem.h + @@@. +*/ +enum +{ + kSecKeyKeyClass = 0, + kSecKeyPrintName = 1, + kSecKeyAlias = 2, + kSecKeyPermanent = 3, + kSecKeyPrivate = 4, + kSecKeyModifiable = 5, + kSecKeyLabel = 6, + kSecKeyApplicationTag = 7, + kSecKeyKeyCreator = 8, + kSecKeyKeyType = 9, + kSecKeyKeySizeInBits = 10, + kSecKeyEffectiveKeySize = 11, + kSecKeyStartDate = 12, + kSecKeyEndDate = 13, + kSecKeySensitive = 14, + kSecKeyAlwaysSensitive = 15, + kSecKeyExtractable = 16, + kSecKeyNeverExtractable = 17, + kSecKeyEncrypt = 18, + kSecKeyDecrypt = 19, + kSecKeyDerive = 20, + kSecKeySign = 21, + kSecKeyVerify = 22, + kSecKeySignRecover = 23, + kSecKeyVerifyRecover = 24, + kSecKeyWrap = 25, + kSecKeyUnwrap = 26 +}; + +/*! + @typedef SecCredentialType + @abstract Determines the type of credential returned by SecKeyGetCredentials. +*/ +typedef uint32 SecCredentialType; + +/*! + @enum SecCredentialType + @abstract Determines the type of credential returned by SecKeyGetCredentials. + @constant kSecCredentialTypeWithUI Operations with this key are allowed to present UI if required. + @constant kSecCredentialTypeNoUI Operations with this key are not allowed to present UI, and will fail if UI is required. + @constant kSecCredentialTypeDefault The default setting for determining whether to present UI is used. This setting can be changed with a call to SecKeychainSetUserInteractionAllowed. +*/ +enum +{ + kSecCredentialTypeDefault = 0, + kSecCredentialTypeWithUI, + kSecCredentialTypeNoUI +}; + +/*! + @typedef SecPadding + @abstract Supported padding types. +*/ +typedef uint32_t SecPadding; +enum +{ + kSecPaddingNone = 0, + kSecPaddingPKCS1 = 1, + + /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is an MD2 + hash; standard ASN.1 padding will be done, as well as PKCS1 padding + of the underlying RSA operation. */ + kSecPaddingPKCS1MD2 = 0x8000, + + /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is an MD5 + hash; standard ASN.1 padding will be done, as well as PKCS1 padding + of the underlying RSA operation. */ + kSecPaddingPKCS1MD5 = 0x8001, + + /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is a SHA1 + hash; standard ASN.1 padding will be done, as well as PKCS1 padding + of the underlying RSA operation. */ + kSecPaddingPKCS1SHA1 = 0x8002, +}; + +/*! + @typedef SecKeySizes + @abstract Supported key lengths. +*/ +typedef uint32_t SecKeySizes; +enum +{ + kSecDefaultKeySize = 0, + + // Symmetric Keysizes - default is currently kSecAES128 for AES. + kSec3DES192 = 192, + kSecAES128 = 128, + kSecAES192 = 192, + kSecAES256 = 256, + + // Supported ECC Keys for Suite-B from RFC 4492 section 5.1.1. + // default is currently kSecp256r1 + kSecp192r1 = 192, + kSecp256r1 = 256, + kSecp384r1 = 384, + kSecp521r1 = 521, // Yes, 521 + + // Boundaries for RSA KeySizes - default is currently 2048 + // RSA keysizes must be multiples of 8 + kSecRSAMin = 1024, + kSecRSAMax = 4096 +}; + +/*! + @enum Key Parameter Constants + @discussion Predefined key constants used to get or set values in a dictionary. + These are used to provide explicit parameters to key generation functions + when non-default values are desired. See the description of the + SecKeyGeneratePair API for usage information. + @constant kSecPrivateKeyAttrs The value for this key is a CFDictionaryRef + containing attributes specific for the private key to be generated. + @constant kSecPublicKeyAttrs The value for this key is a CFDictionaryRef + containing attributes specific for the public key to be generated. +*/ +extern CFTypeRef kSecPrivateKeyAttrs + __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_2_0); +extern CFTypeRef kSecPublicKeyAttrs + __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_2_0); + + +/*! + @function SecKeyGetTypeID + @abstract Returns the type identifier of SecKey instances. + @result The CFTypeID of SecKey instances. +*/ +CFTypeID SecKeyGetTypeID(void) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +/*! + @function SecKeyCreatePair + @abstract Creates an asymmetric key pair and stores it in a specified keychain. + @param keychainRef A reference to the keychain in which to store the private and public key items. Specify NULL for the default keychain. + @param algorithm An algorithm for the key pair. This parameter is ignored if a valid (non-zero) contextHandle is supplied. + @param keySizeInBits A key size for the key pair. This parameter is ignored if a valid (non-zero) contextHandle is supplied. + @param contextHandle (optional) A CSSM_CC_HANDLE, or 0. If this argument is supplied, the algorithm and keySizeInBits parameters are ignored. If extra parameters are needed to generate a key (some algorithms require this), you should create a context using CSSM_CSP_CreateKeyGenContext, using the CSPHandle obtained by calling SecKeychainGetCSPHandle. Then use CSSM_UpdateContextAttributes to add parameters, and dispose of the context using CSSM_DeleteContext after calling this function. + @param publicKeyUsage A bit mask indicating all permitted uses for the new public key. CSSM_KEYUSE bit mask values are defined in cssmtype.h. + @param publicKeyAttr A bit mask defining attribute values for the new public key. The bit mask values are equivalent to a CSSM_KEYATTR_FLAGS and are defined in cssmtype.h. + @param privateKeyUsage A bit mask indicating all permitted uses for the new private key. CSSM_KEYUSE bit mask values are defined in cssmtype.h. + @param privateKeyAttr A bit mask defining attribute values for the new private key. The bit mask values are equivalent to a CSSM_KEYATTR_FLAGS and are defined in cssmtype.h. + @param initialAccess (optional) A SecAccess object that determines the initial access rights to the private key. The public key is given "any/any" access rights by default. + @param publicKey (optional) On return, the keychain item reference of the generated public key. Use the SecKeyGetCSSMKey function to obtain the CSSM_KEY. The caller must call CFRelease on this value if it is returned. Pass NULL if a reference to this key is not required. + @param privateKey (optional) On return, the keychain item reference of the generated private key. Use the SecKeyGetCSSMKey function to obtain the CSSM_KEY. The caller must call CFRelease on this value if it is returned. Pass NULL if a reference to this key is not required. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This API is deprecated for 10.7. Please use the SecKeyGeneratePair API instead. +*/ +OSStatus SecKeyCreatePair( + SecKeychainRef keychainRef, + CSSM_ALGORITHMS algorithm, + uint32 keySizeInBits, + CSSM_CC_HANDLE contextHandle, + CSSM_KEYUSE publicKeyUsage, + uint32 publicKeyAttr, + CSSM_KEYUSE privateKeyUsage, + uint32 privateKeyAttr, + SecAccessRef initialAccess, + SecKeyRef* publicKey, + SecKeyRef* privateKey) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/*! + @function SecKeyGenerate + @abstract Creates a symmetric key and optionally stores it in a specified keychain. + @param keychainRef (optional) A reference to the keychain in which to store the generated key. Specify NULL to generate a transient key. + @param algorithm An algorithm for the symmetric key. This parameter is ignored if a valid (non-zero) contextHandle is supplied. + @param keySizeInBits A key size for the key pair. This parameter is ignored if a valid (non-zero) contextHandle is supplied. + @param contextHandle (optional) A CSSM_CC_HANDLE, or 0. If this argument is supplied, the algorithm and keySizeInBits parameters are ignored. If extra parameters are needed to generate a key (some algorithms require this), you should create a context using CSSM_CSP_CreateKeyGenContext, using the CSPHandle obtained by calling SecKeychainGetCSPHandle. Then use CSSM_UpdateContextAttributes to add parameters, and dispose of the context using CSSM_DeleteContext after calling this function. + @param keyUsage A bit mask indicating all permitted uses for the new key. CSSM_KEYUSE bit mask values are defined in cssmtype.h. + @param keyAttr A bit mask defining attribute values for the new key. The bit mask values are equivalent to a CSSM_KEYATTR_FLAGS and are defined in cssmtype.h. + @param initialAccess (optional) A SecAccess object that determines the initial access rights for the key. This parameter is ignored if the keychainRef is NULL. + @param keyRef On return, a reference to the generated key. Use the SecKeyGetCSSMKey function to obtain the CSSM_KEY. The caller must call CFRelease on this value if it is returned. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This API is deprecated for 10.7. Please use the SecKeyGenerateSymmetric API instead. +*/ +OSStatus SecKeyGenerate( + SecKeychainRef keychainRef, + CSSM_ALGORITHMS algorithm, + uint32 keySizeInBits, + CSSM_CC_HANDLE contextHandle, + CSSM_KEYUSE keyUsage, + uint32 keyAttr, + SecAccessRef initialAccess, + SecKeyRef* keyRef) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/*! + @function SecKeyGetCSSMKey + @abstract Returns a pointer to the CSSM_KEY for the given key item reference. + @param key A keychain key item reference. The key item must be of class type kSecPublicKeyItemClass, kSecPrivateKeyItemClass, or kSecSymmetricKeyItemClass. + @param cssmKey On return, a pointer to a CSSM_KEY structure for the given key. This pointer remains valid until the key reference is released. The caller should not attempt to modify or free this data. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion The CSSM_KEY is valid until the key item reference is released. This API is deprecated in 10.7. Its use should no longer be needed. +*/ +OSStatus SecKeyGetCSSMKey(SecKeyRef key, const CSSM_KEY **cssmKey) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;; + +/*! + @function SecKeyGetCSPHandle + @abstract Returns the CSSM_CSP_HANDLE for the given key reference. The handle is valid until the key reference is released. + @param keyRef A key reference. + @param cspHandle On return, the CSSM_CSP_HANDLE for the given keychain. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This API is deprecated in 10.7. Its use should no longer be needed. +*/ +OSStatus SecKeyGetCSPHandle(SecKeyRef keyRef, CSSM_CSP_HANDLE *cspHandle) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/*! + @function SecKeyGetCredentials + @abstract For a given key, return a pointer to a CSSM_ACCESS_CREDENTIALS structure which will allow the key to be used. + @param keyRef The key for which a credential is requested. + @param operation The type of operation to be performed with this key. See "Authorization tag type" for defined operations (cssmtype.h). + @param credentialType The type of credential requested. + @param outCredentials On return, a pointer to a CSSM_ACCESS_CREDENTIALS structure. This pointer remains valid until the key reference is released. The caller should not attempt to modify or free this data. + @result A result code. See "Security Error Codes" (SecBase.h). +*/ +OSStatus SecKeyGetCredentials( + SecKeyRef keyRef, + CSSM_ACL_AUTHORIZATION_TAG operation, + SecCredentialType credentialType, + const CSSM_ACCESS_CREDENTIALS **outCredentials) + DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + +/*! + @function SecKeyGetBlockSize + @abstract Decrypt a block of ciphertext. + @param key The key for which the block length is requested. + @result The block length of the key in bytes. + @discussion If for example key is an RSA key the value returned by + this function is the size of the modulus. + */ +size_t SecKeyGetBlockSize(SecKeyRef key) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @function SecKeyGenerateSymmetric + @abstract Generates a random symmetric key with the specified length + and algorithm type. + + @param parameters A dictionary containing one or more key-value pairs. + See the discussion sections below for a complete overview of options. + @param error An optional pointer to a CFErrorRef. This value is set + if an error occurred. If not NULL, the caller is responsible for + releasing the CFErrorRef. + @result On return, a SecKeyRef reference to the symmetric key, or + NULL if the key could not be created. + + @discussion In order to generate a symmetric key, the parameters dictionary + must at least contain the following keys: + + * kSecAttrKeyType with a value of kSecAttrKeyTypeAES or any other + kSecAttrKeyType defined in SecItem.h + * kSecAttrKeySizeInBits with a value being a CFNumberRef containing + the requested key size in bits. Example sizes for AES keys are: + 128, 192, 256, 512. + + To store the generated symmetric key in a keychain, set these keys: + * kSecUseKeychain (value is a SecKeychainRef) + * kSecAttrLabel (a user-visible label whose value is a CFStringRef, + e.g. "My App's Encryption Key") + * kSecAttrApplicationLabel (a label defined by your application, whose + value is a CFStringRef and which can be used to find this key in a + subsequent call to SecItemCopyMatching, e.g. "ID-1234567890-9876-0151") + + To specify the generated key's access control settings, set this key: + * kSecAttrAccess (value is a SecAccessRef) + + The keys below may be optionally set in the parameters dictionary + (with a CFBooleanRef value) to override the default usage values: + + * kSecAttrCanEncrypt (defaults to true if not explicitly specified) + * kSecAttrCanDecrypt (defaults to true if not explicitly specified) + * kSecAttrCanWrap (defaults to true if not explicitly specified) + * kSecAttrCanUnwrap (defaults to true if not explicitly specified) + +*/ +SecKeyRef SecKeyGenerateSymmetric(CFDictionaryRef parameters, CFErrorRef *error) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + + +/*! + @function SecKeyCreateFromData + @abstract Creates a symmetric key with the given data and sets the + algorithm type specified. + + @param parameters A dictionary containing one or more key-value pairs. + See the discussion sections below for a complete overview of options. + @result On return, a SecKeyRef reference to the symmetric key. + + @discussion In order to generate a symmetric key the parameters dictionary must + at least contain the following keys: + + * kSecAttrKeyType with a value of kSecAttrKeyTypeAES or any other + kSecAttrKeyType defined in SecItem.h + + The keys below may be optionally set in the parameters dictionary + (with a CFBooleanRef value) to override the default usage values: + + * kSecAttrCanEncrypt (defaults to true if not explicitly specified) + * kSecAttrCanDecrypt (defaults to true if not explicitly specified) + * kSecAttrCanWrap (defaults to true if not explicitly specified) + * kSecAttrCanUnwrap (defaults to true if not explicitly specified) + +*/ +SecKeyRef SecKeyCreateFromData(CFDictionaryRef parameters, + CFDataRef keyData, CFErrorRef *error) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + + +/*! + @function SecKeyGeneratePair + @abstract Generate a private/public keypair. + @param parameters A dictionary containing one or more key-value pairs. + @result A result code. See "Security Error Codes" (SecBase.h). On success, + the result code will be errSecSuccess, and the output parameters will + contain the public SecKeyRef and private SecKeyRef. It is the caller's + responsibility to CFRelease these key references when finished with them. + + @discussion In order to generate a keypair the parameters dictionary must + at least contain the following keys: + + * kSecAttrKeyType with a value of kSecAttrKeyTypeRSA or any other + kSecAttrKeyType defined in SecItem.h + * kSecAttrKeySizeInBits with a value being a CFNumberRef containing + the requested key size in bits. Example sizes for RSA keys are: + 512, 768, 1024, 2048. + + The values below may be set either in the top-level dictionary or in a + dictionary that is the value of the kSecPrivateKeyAttrs or + kSecPublicKeyAttrs key in the top-level dictionary. Setting these + attributes explicitly will override the defaults below. See SecItem.h + for detailed information on these attributes including the types of + the values. + + * kSecAttrLabel default NULL + * kSecUseKeychain default NULL, which specifies the default keychain + * kSecAttrApplicationTag default NULL + * kSecAttrEffectiveKeySize default NULL same as kSecAttrKeySizeInBits + * kSecAttrCanEncrypt default false for private keys, true for public keys + * kSecAttrCanDecrypt default true for private keys, false for public keys + * kSecAttrCanDerive default true + * kSecAttrCanSign default true for private keys, false for public keys + * kSecAttrCanVerify default false for private keys, true for public keys + * kSecAttrCanWrap default false for private keys, true for public keys + * kSecAttrCanUnwrap default true for private keys, false for public keys + +*/ +OSStatus SecKeyGeneratePair(CFDictionaryRef parameters, + SecKeyRef *publicKey, SecKeyRef *privateKey) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + +/*! + @typedef SecKeyGeneratePairBlock + @abstract Delivers the result from an asynchronous key pair generation. + @param publicKey - the public key generated. You must retain publicKey if you wish to use it after your block returns. + @param privateKey - the private key generated. You must retain publicKey if you wish to use it after your block returns. + @param error - Any errors returned. You must retain error if you wish to use it after your block returns. + */ + +#ifdef __BLOCKS__ +typedef void (^SecKeyGeneratePairBlock)(SecKeyRef publicKey, SecKeyRef privateKey, CFErrorRef error); + + +/*! + @function SecKeyGeneratePairAsync + @abstract Generate a private/public keypair returning the values in a callback. + @param parameters A dictionary containing one or more key-value pairs. + @param deliveryQueue A dispatch queue to be used to deliver the results. + @param result A callback function to result when the operation has completed. + @result On success the function returns NULL. + + @discussion In order to generate a keypair the parameters dictionary must + at least contain the following keys: + + * kSecAttrKeyType with a value being kSecAttrKeyTypeRSA or any other + kSecAttrKeyType defined in SecItem.h + * kSecAttrKeySizeInBits with a value being a CFNumberRef or CFStringRef + containing the requested key size in bits. Example sizes for RSA + keys are: 512, 768, 1024, 2048. + + Setting the following attributes explicitly will override the defaults below. + See SecItem.h for detailed information on these attributes including the types + of the values. + + * kSecAttrLabel default NULL + * kSecAttrIsPermanent if this key is present and has a Boolean + value of true, the key or key pair will be added to the default + keychain. + * kSecAttrApplicationTag default NULL + * kSecAttrEffectiveKeySize default NULL same as kSecAttrKeySizeInBits + * kSecAttrCanEncrypt default false for private keys, true for public keys + * kSecAttrCanDecrypt default true for private keys, false for public keys + * kSecAttrCanDerive default true + * kSecAttrCanSign default true for private keys, false for public keys + * kSecAttrCanVerify default false for private keys, true for public keys + * kSecAttrCanWrap default false for private keys, true for public keys + * kSecAttrCanUnwrap default true for private keys, false for public keys + +*/ +void SecKeyGeneratePairAsync(CFDictionaryRef parameters, + dispatch_queue_t deliveryQueue, SecKeyGeneratePairBlock result) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +#endif /* __BLOCKS__ */ + +// Derive, Wrap, and Unwrap + +/*! + @function SecKeyDeriveFromPassword + @abstract Derives a symmetric key from a password. + + @param password The password from which the keyis to be derived. + @param parameters A dictionary containing one or more key-value pairs. + @param error If the call fails this will contain the error code. + + @discussion In order to derive a key the parameters dictionary must contain at least contain the following keys: + * kSecAttrSalt - a CFData for the salt value for mixing in the pseudo-random rounds. + * kSecAttrPRF - the algorithm to use for the pseudo-random-function. + If 0, this defaults to kSecAttrPRFHmacAlgSHA1. Possible values are: + + * kSecAttrPRFHmacAlgSHA1 + * kSecAttrPRFHmacAlgSHA224 + * kSecAttrPRFHmacAlgSHA256 + * kSecAttrPRFHmacAlgSHA384 + * kSecAttrPRFHmacAlgSHA512 + + * kSecAttrRounds - the number of rounds to call the pseudo random function. + If 0, a count will be computed to average 1/10 of a second. + * kSecAttrKeySizeInBits with a value being a CFNumberRef + containing the requested key size in bits. Example sizes for RSA keys are: + 512, 768, 1024, 2048. + + @result On success a SecKeyRef is returned. On failure this result is NULL and the + error parameter contains the reason. + +*/ +SecKeyRef SecKeyDeriveFromPassword(CFStringRef password, + CFDictionaryRef parameters, CFErrorRef *error) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @function SecKeyWrapSymmetric + @abstract Wraps a symmetric key with a symmetric key. + + @param keyToWrap The key which is to be wrapped. + @param wrappingKey The key wrapping key. + #param parameters The parameter list to use for wrapping the key. + @param error If the call fails this will contain the error code. + + @result On success a CFDataRef is returned. On failure this result is NULL and the + error parameter contains the reason. + + @discussion In order to wrap a key the parameters dictionary may contain the following key: + * kSecSalt - a CFData for the salt value for the encrypt. + +*/ +CFDataRef SecKeyWrapSymmetric(SecKeyRef keyToWrap, + SecKeyRef wrappingKey, CFDictionaryRef parameters, CFErrorRef *error) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @function SecKeyUnwrapSymmetric + @abstract Unwrap a wrapped symmetric key. + + @param keyToUnwrap The wrapped key to unwrap. + @param unwrappingKey The key unwrapping key. + #param parameters The parameter list to use for unwrapping the key. + @param error If the call fails this will contain the error code. + + @result On success a SecKeyRef is returned. On failure this result is NULL and the + error parameter contains the reason. + + @discussion In order to unwrap a key the parameters dictionary may contain the following key: + * kSecSalt - a CFData for the salt value for the decrypt. + +*/ +SecKeyRef SecKeyUnwrapSymmetric(CFDataRef *keyToUnwrap, + SecKeyRef unwrappingKey, CFDictionaryRef parameters, CFErrorRef *error) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECKEY_H_ */ diff --git a/Security/libsecurity_keychain/lib/SecKeyPriv.h b/Security/libsecurity_keychain/lib/SecKeyPriv.h new file mode 100644 index 00000000..8c281dec --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecKeyPriv.h @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2002-2009,2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * SecKeyPriv.h - SPIs to SecKeyRef objects. + */ + +/*! + @header SecKeyPriv + The functions provided in SecKeyPriv.h implement and manage a particular + type of keychain item that represents a key. A key can be stored in a + keychain, but a key can also be a transient object. + + You can use a key as a keychain item in most functions. +*/ + +#ifndef _SECURITY_SECKEYPRIV_H_ +#define _SECURITY_SECKEYPRIV_H_ + +#include +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef struct SecRSAPublicKeyParams { + uint8_t *modulus; /* modulus */ + CFIndex modulusLength; + uint8_t *exponent; /* public exponent */ + CFIndex exponentLength; +} SecRSAPublicKeyParams; + +typedef uint32_t SecKeyEncoding; +enum { + /* Typically only used for symmetric keys. */ + kSecKeyEncodingRaw = 0, + + /* RSA keys are DER-encoded according to PKCS1. */ + kSecKeyEncodingPkcs1 = 1, + + /* RSA keys are DER-encoded according to PKCS1 with Apple Extensions. */ + kSecKeyEncodingApplePkcs1 = 2, + + /* RSA public key in SecRSAPublicKeyParams format. keyData is a pointer + to a SecRSAPublicKeyParams and keyDataLength is + sizeof(SecRSAPublicKeyParams). */ + kSecKeyEncodingRSAPublicParams = 3, +}; + +typedef OSStatus (*SecKeyInitMethod)(SecKeyRef, const uint8_t *, CFIndex, + SecKeyEncoding); +typedef void *(*SecKeyCopyMethod)(SecKeyRef); +typedef void (*SecKeyDestroyMethod)(SecKeyRef); +typedef void (*SecKeyDeleteMethod)(SecKeyRef); +typedef void (*SecKeyShowMethod)(SecKeyRef); +typedef OSStatus (*SecKeyRawSignMethod)(SecKeyRef key, SecPadding padding, + const uint8_t *dataToSign, size_t dataToSignLen, + uint8_t *sig, size_t *sigLen); +typedef OSStatus (*SecKeyRawVerifyMethod)( + SecKeyRef key, SecPadding padding, const uint8_t *signedData, + size_t signedDataLen, const uint8_t *sig, size_t sigLen); +typedef OSStatus (*SecKeyEncryptMethod)(SecKeyRef key, SecPadding padding, + const uint8_t *plainText, size_t plainTextLen, + uint8_t *cipherText, size_t *cipherTextLen); +typedef OSStatus (*SecKeyDecryptMethod)(SecKeyRef key, SecPadding padding, + const uint8_t *cipherText, size_t cipherTextLen, + uint8_t *plainText, size_t *plainTextLen); +typedef size_t (*SecKeyBlockSizeMethod)(SecKeyRef key); +typedef CFDictionaryRef (*SecKeyCopyDictionaryMethod)(SecKeyRef key); + +typedef struct { + const char *name; + SecKeyInitMethod init; + SecKeyCopyMethod copy; + SecKeyDestroyMethod destroy; + SecKeyDeleteMethod remove; + SecKeyShowMethod show; + SecKeyRawSignMethod rawSign; + SecKeyRawVerifyMethod rawVerify; + SecKeyEncryptMethod encrypt; + SecKeyDecryptMethod decrypt; + SecKeyBlockSizeMethod blockSize; + SecKeyCopyDictionaryMethod copyDictionary; + /* If known, the number of bytes to allocate for the key field in the SecKey struct. */ + int extraBytes; +} SecKeyDescriptor; + +/*! + @function SecKeyGetAlgorithmID + @abstract Returns a pointer to a CSSM_X509_ALGORITHM_IDENTIFIER structure for the given key. + @param key A key reference. + @param algid On return, a pointer to a CSSM_X509_ALGORITHM_IDENTIFIER structure. + @result A result code. See "Security Error Codes" (SecBase.h). +*/ +OSStatus SecKeyGetAlgorithmID(SecKeyRef key, const CSSM_X509_ALGORITHM_IDENTIFIER **algid) + DEPRECATED_IN_MAC_OS_X_VERSION_10_8_AND_LATER; + +enum { + kSecNullAlgorithmID = 0, + kSecRSAAlgorithmID = 1, + kSecDSAAlgorithmID = 2, /* unsupported, just here for reference. */ + kSecECDSAAlgorithmID = 3, +}; + +/*! + @function SecKeyGetAlgorithmId + @abstract Returns an enumerated constant value which identifies the algorithm for the given key. + @param key A key reference. + @result An algorithm identifier. +*/ +CFIndex SecKeyGetAlgorithmId(SecKeyRef key) + __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_NA); + +/*! + @function SecKeyGetStrengthInBits + @abstract Returns key strength in bits for the given key. + @param key A key reference. + @param algid A pointer to a CSSM_X509_ALGORITHM_IDENTIFIER structure, as returned from a call to SecKeyGetAlgorithmID. + @param strength On return, the key strength in bits. + @result A result code. See "Security Error Codes" (SecBase.h). +*/ +OSStatus SecKeyGetStrengthInBits(SecKeyRef key, const CSSM_X509_ALGORITHM_IDENTIFIER *algid, unsigned int *strength); + +/*! + @function SecKeyImportPair + @abstract Takes an asymmetric key pair and stores it in the keychain specified by the keychain parameter. + @param keychainRef A reference to the keychain in which to store the private and public key items. Specify NULL for the default keychain. + @param publicCssmKey A CSSM_KEY which is valid for the CSP returned by SecKeychainGetCSPHandle(). This may be a normal key or reference key. + @param privateCssmKey A CSSM_KEY which is valid for the CSP returned by SecKeychainGetCSPHandle(). This may be a normal key or reference key. + @param initialAccess A SecAccess object that determines the initial access rights to the private key. The public key is given an any/any acl by default. + @param publicKey Optional output pointer to the keychain item reference of the imported public key. The caller must call CFRelease on this value if it is returned. + @param privateKey Optional output pointer to the keychain item reference of the imported private key. The caller must call CFRelease on this value if it is returned. + @result A result code. See "Security Error Codes" (SecBase.h). + @deprecated in 10.5 and later. Use the SecKeychainItemImport function instead; see +*/ +OSStatus SecKeyImportPair( + SecKeychainRef keychainRef, + const CSSM_KEY *publicCssmKey, + const CSSM_KEY *privateCssmKey, + SecAccessRef initialAccess, + SecKeyRef* publicKey, + SecKeyRef* privateKey) + DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER; + +/*! + @function SecKeyCreate + @abstract Create a key reference from the supplied key data. + @param allocator CFAllocator to allocate the key data. Pass NULL to use the default allocator. + @param keyClass A descriptor for the particular class of key that is being created. + @param keyData Data from which to create the key. Specify the format of this data in the encoding parameter. + @param keyDataLength Length of the data pointed to by keyData. + @param encoding A value of type SecKeyEncoding which describes the format of keyData. + @result A key reference. + @discussion Warning: this function is NOT intended for use outside the Security stack in its current state. + IMPORTANT: on Mac OS X 10.5 and earlier, the SecKeyCreate function had a different parameter list. + The current parameter list matches the iPhone OS implementation. Existing clients of this function + on Mac OS X (and there should not be any outside the Security stack, per the warning above) must + migrate to the replacement function, SecKeyCreateWithCSSMKey. +*/ +SecKeyRef SecKeyCreate(CFAllocatorRef allocator, + const SecKeyDescriptor *keyClass, const uint8_t *keyData, + CFIndex keyDataLength, SecKeyEncoding encoding); + +/*! + @function SecKeyCreateWithCSSMKey + @abstract Generate a temporary floating key reference for a CSSM_KEY. + @param key A pointer to a CSSM_KEY structure. + @param keyRef On return, a key reference. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Warning: this function is NOT intended for use outside the Security stack in its current state. +*/ +OSStatus SecKeyCreateWithCSSMKey(const CSSM_KEY *key, SecKeyRef* keyRef); + + +/*! + @function SecKeyRawSign + @abstract Given a private key and data to sign, generate a digital signature. + @param key Private key with which to sign. + @param padding See Padding Types above, typically kSecPaddingPKCS1SHA1. + @param dataToSign The data to be signed, typically the digest of the actual data. + @param dataToSignLen Length of dataToSign in bytes. + @param sig Pointer to buffer in which the signature will be returned. + @param sigLen IN/OUT maximum length of sig buffer on input, actualy length of sig on output. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion If the padding argument is kSecPaddingPKCS1, PKCS1 padding + will be performed prior to signing. If this argument is kSecPaddingNone, + the incoming data will be signed "as is". + + When PKCS1 padding is performed, the maximum length of data that can + be signed is the value returned by SecKeyGetBlockSize() - 11. + + NOTE: The behavior this function with kSecPaddingNone is undefined if the + first byte of dataToSign is zero; there is no way to verify leading zeroes + as they are discarded during the calculation. + + If you want to generate a proper PKCS1 style signature with DER encoding of + the digest type - and the dataToSign is a SHA1 digest - use kSecPaddingPKCS1SHA1. +*/ +OSStatus SecKeyRawSign( + SecKeyRef key, + SecPadding padding, + const uint8_t *dataToSign, + size_t dataToSignLen, + uint8_t *sig, + size_t *sigLen); + + +/*! + @function SecKeyRawVerify + @abstract Given a public key, data which has been signed, and a signature, verify the signature. + @param key Public key with which to verify the signature. + @param padding See Padding Types above, typically kSecPaddingPKCS1SHA1. + @param signedData The data over which sig is being verified, typically the digest of the actual data. + @param signedDataLen Length of signedData in bytes. + @param sig Pointer to the signature to verify. + @param sigLen Length of sig in bytes. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion If the padding argument is kSecPaddingPKCS1, PKCS1 padding + will be checked during verification. If this argument is kSecPaddingNone, + the incoming data will be compared directly to sig. + + If you are verifying a proper PKCS1-style signature, with DER encoding of the digest + type - and the signedData is a SHA1 digest - use kSecPaddingPKCS1SHA1. +*/ +OSStatus SecKeyRawVerify( + SecKeyRef key, + SecPadding padding, + const uint8_t *signedData, + size_t signedDataLen, + const uint8_t *sig, + size_t sigLen); + + +/*! + @function SecKeyEncrypt + @abstract Encrypt a block of plaintext. + @param key Public key with which to encrypt the data. + @param padding See Padding Types above, typically kSecPaddingPKCS1. + @param plainText The data to encrypt. + @param plainTextLen Length of plainText in bytes, this must be less + or equal to the value returned by SecKeyGetBlockSize(). + @param cipherText Pointer to the output buffer. + @param cipherTextLen On input, specifies how much space is available at + cipherText; on return, it is the actual number of cipherText bytes written. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion If the padding argument is kSecPaddingPKCS1, PKCS1 padding + will be performed prior to encryption. If this argument is kSecPaddingNone, + the incoming data will be encrypted "as is". + + When PKCS1 padding is performed, the maximum length of data that can + be encrypted is the value returned by SecKeyGetBlockSize() - 11. + + When memory usage is a critical issue, note that the input buffer + (plainText) can be the same as the output buffer (cipherText). +*/ +OSStatus SecKeyEncrypt( + SecKeyRef key, + SecPadding padding, + const uint8_t *plainText, + size_t plainTextLen, + uint8_t *cipherText, + size_t *cipherTextLen); + + +/*! + @function SecKeyDecrypt + @abstract Decrypt a block of ciphertext. + @param key Private key with which to decrypt the data. + @param padding See SecPadding types above; typically kSecPaddingPKCS1. + @param cipherText The data to decrypt. + @param cipherTextLen Length of cipherText in bytes; this must be less + or equal to the value returned by SecKeyGetBlockSize(). + @param plainText Pointer to the output buffer. + @param plainTextLen On input, specifies how much space is available at + plainText; on return, it is the actual number of plainText bytes written. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion If the padding argument is kSecPaddingPKCS1, PKCS1 padding + will be removed after decryption. If this argument is kSecPaddingNone, + the decrypted data will be returned "as is". + + When memory usage is a critical issue, note that the input buffer + (plainText) can be the same as the output buffer (cipherText). +*/ +OSStatus SecKeyDecrypt( + SecKeyRef key, /* Private key */ + SecPadding padding, /* kSecPaddingNone, kSecPaddingPKCS1, kSecPaddingOAEP */ + const uint8_t *cipherText, + size_t cipherTextLen, /* length of cipherText */ + uint8_t *plainText, + size_t *plainTextLen); /* IN/OUT */ + +OSStatus SecKeyVerifyDigest( + SecKeyRef key, /* Private key */ + const SecAsn1AlgId *algId, /* algorithm oid/params */ + const uint8_t *digestData, /* signature over this digest */ + size_t digestDataLen, /* length of dataToDigest */ + const uint8_t *sig, /* signature to verify */ + size_t sigLen); /* length of sig */ + +OSStatus SecKeySignDigest( + SecKeyRef key, /* Private key */ + const SecAsn1AlgId *algId, /* algorithm oid/params */ + const uint8_t *digestData, /* signature over this digest */ + size_t digestDataLen, /* length of digestData */ + uint8_t *sig, /* signature, RETURNED */ + size_t *sigLen); /* IN/OUT */ + + +/* These are the named curves we support. These values come from RFC 4492 + section 5.1.1, with the exception of SSL_Curve_None which means + "ECDSA not negotiated". */ +typedef enum +{ + kSecECCurveNone = -1, + kSecECCurveSecp256r1 = 23, + kSecECCurveSecp384r1 = 24, + kSecECCurveSecp521r1 = 25 +} SecECNamedCurve; + +/* Return a named curve enum for ecPrivateKey. */ +SecECNamedCurve SecECKeyGetNamedCurve(SecKeyRef ecPrivateKey); +CFDataRef SecECKeyCopyPublicBits(SecKeyRef key); + +/* Given an RSA public key in encoded form return a SecKeyRef representing + that key. Supported encodings are kSecKeyEncodingPkcs1. */ +SecKeyRef SecKeyCreateRSAPublicKey(CFAllocatorRef allocator, + const uint8_t *keyData, CFIndex keyDataLength, + SecKeyEncoding encoding); + +CFDataRef SecKeyCopyModulus(SecKeyRef rsaPublicKey); +CFDataRef SecKeyCopyExponent(SecKeyRef rsaPublicKey); + +/*! + @function SecKeyCopyPublicBytes + @abstract Gets the bits of a public key + @param key Key to retrieve the bits. + @param publicBytes An out parameter to receive the public key bits + @result Errors if any when retrieving the public key bits.. + */ +OSStatus SecKeyCopyPublicBytes(SecKeyRef key, CFDataRef* publicBytes); + +/*! + @function SecKeyCreatePublicFromPrivate + @abstract Create a public SecKeyRef from a private SecKeyRef + @param privateKey The private SecKeyRef for which you want the public key + @result A public SecKeyRef, or NULL if the conversion failed + @discussion This is a "best attempt" function, hence the SPI nature. If the public + key bits are not in memory, it attempts to load from the keychain. If the public + key was not tracked on the keychain, it will fail. +*/ +SecKeyRef SecKeyCreatePublicFromPrivate(SecKeyRef privateKey); + +/*! + @function SecKeyCreateFromPublicData +*/ +SecKeyRef SecKeyCreateFromPublicData(CFAllocatorRef allocator, CFIndex algorithmID, CFDataRef publicBytes); + +OSStatus SecKeyRawVerifyOSX( + SecKeyRef key, + SecPadding padding, + const uint8_t *signedData, + size_t signedDataLen, + const uint8_t *sig, + size_t sigLen); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECKEYPRIV_H_ */ + diff --git a/libsecurity_keychain/lib/SecKeychain.cpp b/Security/libsecurity_keychain/lib/SecKeychain.cpp similarity index 84% rename from libsecurity_keychain/lib/SecKeychain.cpp rename to Security/libsecurity_keychain/lib/SecKeychain.cpp index ceaffd81..8a48d3f2 100644 --- a/libsecurity_keychain/lib/SecKeychain.cpp +++ b/Security/libsecurity_keychain/lib/SecKeychain.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -25,13 +25,28 @@ #include #include #include +#include #include #include +#include +#include #include "SecBridge.h" #include "CCallbackMgr.h" #include +#include #include +OSStatus +SecKeychainMDSInstall() +{ + BEGIN_SECAPI + + Security::MDSClient::Directory d; + d.install(); + + END_SECAPI +} + CFTypeID SecKeychainGetTypeID(void) { @@ -222,7 +237,9 @@ OSStatus SecKeychainResetLogin(UInt32 passwordLength, const void* password, Bool } if ( userName.length() == 0 ) // did we ultimately get one? MacOSError::throwMe(errAuthorizationInternal); - + + SecurityServer::ClientSession().resetKeyStorePassphrase(password ? CssmData(const_cast(password), passwordLength) : CssmData()); + if (password) { // Clear the plist and move aside (rename) the existing login.keychain @@ -242,8 +259,6 @@ OSStatus SecKeychainResetLogin(UInt32 passwordLength, const void* password, Bool globals().storageManager.makeLoginAuthUI(NULL); } - SecurityServer::ClientSession().resetKeyStorePassphrase(password ? CssmData(const_cast(password), passwordLength) : CssmData()); - // Post a "list changed" event after a reset, so apps can refresh their list. // Make sure we are not holding mLock when we post this event. KCEventNotifier::PostKeychainEvent(kSecKeychainListChangedEvent); @@ -1138,4 +1153,131 @@ OSStatus SecKeychainChangeKeyStorePassphrase() BEGIN_SECAPI SecurityServer::ClientSession().changeKeyStorePassphrase(); END_SECAPI -} \ No newline at end of file +} + +static OSStatus SecKeychainGetMasterKey(SecKeychainRef userKeychainRef, CFDataRef *masterKey, CFStringRef password) +{ + BEGIN_SECAPI + + // make a keychain object "wrapper" for this keychain ref + Keychain keychain = Keychain::optional(userKeychainRef); + + CssmClient::Db db = keychain->database(); + + // create the keychain, using appropriate credentials + Allocator &alloc = db->allocator(); + AutoCredentials cred(alloc); // will leak, but we're quitting soon :-) + + char passphrase[1024]; + CFStringGetCString(password, passphrase, sizeof(passphrase), kCFStringEncodingUTF8); + + // use this passphrase + cred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, + new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), + new(alloc) ListElement(StringData(passphrase))); + db->accessCredentials(&cred); + + CSSM_DL_DB_HANDLE dlDb = db->handle(); + CssmData dlDbData = CssmData::wrap(dlDb); + CssmKey refKey; + KeySpec spec(CSSM_KEYUSE_ANY, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE); + + DeriveKey derive(keychain->csp(), CSSM_ALGID_KEYCHAIN_KEY, CSSM_ALGID_3DES_3KEY, 3 * 64); + derive(&dlDbData, spec, refKey); + + // now extract the raw keybits + CssmKey rawKey; + WrapKey wrap(keychain->csp(), CSSM_ALGID_NONE); + wrap(refKey, rawKey); + + *masterKey = CFDataCreate(kCFAllocatorDefault, rawKey.keyData(), rawKey.length()); + + END_SECAPI +} + + +OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRef systemKeychainRef, CFStringRef username, CFStringRef password) { + SecTrustedApplicationRef itemPath; + SecAccessRef ourAccessRef = NULL; + + OSStatus result = errSecParam; + + CFDataRef masterKey = NULL; + result = SecKeychainGetMasterKey(userKeychainRef, &masterKey, password); + if (errSecSuccess != result) { + return result; + } + + result = SecKeychainStash(); + if (errSecSuccess != result) { + if (NULL != masterKey) CFRelease(masterKey); + return result; + } + + CFMutableArrayRef trustedApplications = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + if ( noErr == SecTrustedApplicationCreateApplicationGroup("com.apple.security.auto-login", NULL, &itemPath) && itemPath ) + CFArrayAppendValue(trustedApplications, itemPath); + + if ( trustedApplications && (CFArrayGetCount(trustedApplications) > 0)) { + if (errSecSuccess == (result = SecAccessCreate(CFSTR("Auto-Login applications"), trustedApplications, &ourAccessRef))) { + if (NULL == systemKeychainRef) { + SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, &systemKeychainRef); + } + + const void *queryKeys[] = { kSecClass, + kSecAttrService, + kSecAttrAccount, + kSecUseKeychain, + }; + const void *queryValues[] = { kSecClassGenericPassword, + CFSTR("com.apple.loginwindow.auto-login"), + username, + systemKeychainRef, + }; + + const void *updateKeys[] = { kSecAttrAccess, + kSecValueData, + }; + const void *updateValues[] = { ourAccessRef, + masterKey, + }; + + CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefault, queryKeys, queryValues, sizeof(queryValues)/sizeof(*queryValues), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionaryRef update = CFDictionaryCreate(kCFAllocatorDefault, updateKeys, updateValues, sizeof(updateValues)/sizeof(*updateValues), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + result = SecItemUpdate(query, update); + + if (errSecSuccess != result) { + const void *addKeys[] = { kSecClass, + kSecAttrService, + kSecAttrAccount, + kSecUseKeychain, + kSecAttrAccess, + kSecValueData, + }; + const void *addValues[] = { kSecClassGenericPassword, + CFSTR("com.apple.loginwindow.auto-login"), + username, + systemKeychainRef, + ourAccessRef, + masterKey, + }; + + CFDictionaryRef add = CFDictionaryCreate(kCFAllocatorDefault, addKeys, addValues, sizeof(addValues)/sizeof(*addValues), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + result = SecItemAdd(add, NULL); + if (NULL != add) CFRelease(add); + } + + if (NULL != query) CFRelease(query); + if (NULL != update) CFRelease(update); + } + } + + if (NULL != masterKey) CFRelease(masterKey); + if (NULL != trustedApplications) CFRelease(trustedApplications); + if (NULL != ourAccessRef) CFRelease(ourAccessRef); + if (NULL != systemKeychainRef) CFRelease(systemKeychainRef); + + return result; +} diff --git a/libsecurity_keychain/lib/SecKeychain.h b/Security/libsecurity_keychain/lib/SecKeychain.h similarity index 99% rename from libsecurity_keychain/lib/SecKeychain.h rename to Security/libsecurity_keychain/lib/SecKeychain.h index 992cce8e..9961d9d4 100644 --- a/libsecurity_keychain/lib/SecKeychain.h +++ b/Security/libsecurity_keychain/lib/SecKeychain.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -449,7 +449,7 @@ OSStatus SecKeychainGetPath(SecKeychainRef keychain, UInt32 *ioPathLength, char @function SecKeychainAttributeInfoForItemID @abstract Obtains tags for all possible attributes for a given item class. @param keychain A keychain reference. - @param itemID The relation identifier of the item tags (an itemID is a CSSM_DB_RECORDTYPE defined in cssmtype.h). + @param itemID The relation identifier of the item tags (an itemID is a CSSM_DB_RECORDTYPE defined in cssmapple.h). @param info On return, a pointer to the keychain attribute information. User should call the SecKeychainFreeAttributeInfo function to release the structure when done with it. @result A result code. See "Security Error Codes" (SecBase.h). In addition, errSecParam (-50) may be returned if not enough valid parameters were supplied (NULL). @discussion Warning, this call returns more attributes than are support by the old style Keychain API and passing them into older calls will yield an invalid attribute error. The recommended call to retrieve the attribute values is the SecKeychainItemCopyAttributesAndData function. diff --git a/libsecurity_keychain/lib/SecKeychainAddIToolsPassword.cpp b/Security/libsecurity_keychain/lib/SecKeychainAddIToolsPassword.cpp similarity index 98% rename from libsecurity_keychain/lib/SecKeychainAddIToolsPassword.cpp rename to Security/libsecurity_keychain/lib/SecKeychainAddIToolsPassword.cpp index 9b0633b8..5983311a 100644 --- a/libsecurity_keychain/lib/SecKeychainAddIToolsPassword.cpp +++ b/Security/libsecurity_keychain/lib/SecKeychainAddIToolsPassword.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecKeychainItem.cpp b/Security/libsecurity_keychain/lib/SecKeychainItem.cpp similarity index 99% rename from libsecurity_keychain/lib/SecKeychainItem.cpp rename to Security/libsecurity_keychain/lib/SecKeychainItem.cpp index 1056f16a..1350e607 100644 --- a/libsecurity_keychain/lib/SecKeychainItem.cpp +++ b/Security/libsecurity_keychain/lib/SecKeychainItem.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2000-2004,2012-2013 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/SecKeychainItem.h b/Security/libsecurity_keychain/lib/SecKeychainItem.h similarity index 99% rename from libsecurity_keychain/lib/SecKeychainItem.h rename to Security/libsecurity_keychain/lib/SecKeychainItem.h index 2d3e7446..59d4e205 100644 --- a/libsecurity_keychain/lib/SecKeychainItem.h +++ b/Security/libsecurity_keychain/lib/SecKeychainItem.h @@ -1,14 +1,14 @@ -/* * Copyright (c) 2000-2008,2012 Apple Inc. All Rights Reserved. +/* * Copyright (c) 2000-2008,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -16,7 +16,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@ */ diff --git a/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.cpp b/Security/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.cpp similarity index 99% rename from libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.cpp rename to Security/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.cpp index a23b47cd..0664f399 100644 --- a/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.cpp +++ b/Security/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h b/Security/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h similarity index 98% rename from libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h rename to Security/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h index 189fc208..8a8f4080 100644 --- a/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h +++ b/Security/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecKeychainItemPriv.h b/Security/libsecurity_keychain/lib/SecKeychainItemPriv.h similarity index 99% rename from libsecurity_keychain/lib/SecKeychainItemPriv.h rename to Security/libsecurity_keychain/lib/SecKeychainItemPriv.h index 9ec5b60a..c7eb963d 100644 --- a/libsecurity_keychain/lib/SecKeychainItemPriv.h +++ b/Security/libsecurity_keychain/lib/SecKeychainItemPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2008,2011,2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_keychain/lib/SecKeychainPriv.h b/Security/libsecurity_keychain/lib/SecKeychainPriv.h new file mode 100644 index 00000000..d4528aca --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecKeychainPriv.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2003-2004,2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SECURITY_SECKEYCHAINPRIV_H_ +#define _SECURITY_SECKEYCHAINPRIV_H_ + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +enum {kSecKeychainEnteredBatchModeEvent = 14, + kSecKeychainLeftBatchModeEvent = 15}; +enum {kSecKeychainEnteredBatchModeEventMask = 1 << kSecKeychainEnteredBatchModeEvent, + kSecKeychainLeftBatchModeEventMask = 1 << kSecKeychainLeftBatchModeEvent}; + + +/* Keychain management */ +OSStatus SecKeychainCreateNew(SecKeychainRef keychainRef, UInt32 passwordLength, const char* inPassword) + __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA); +OSStatus SecKeychainMakeFromFullPath(const char *fullPathName, SecKeychainRef *keychainRef) + __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA); +OSStatus SecKeychainIsValid(SecKeychainRef keychainRef, Boolean* isValid) + __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA); +OSStatus SecKeychainChangePassword(SecKeychainRef keychainRef, UInt32 oldPasswordLength, const void *oldPassword, UInt32 newPasswordLength, const void *newPassword) + __OSX_AVAILABLE_STARTING(__MAC_10_2, __IPHONE_NA); +OSStatus SecKeychainOpenWithGuid(const CSSM_GUID *guid, uint32 subserviceId, uint32 subserviceType, const char* dbName, const CSSM_NET_ADDRESS *dbLocation, SecKeychainRef *keychain) + __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA); +OSStatus SecKeychainSetBatchMode (SecKeychainRef kcRef, Boolean mode, Boolean rollback) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* Keychain list management */ +UInt16 SecKeychainListGetCount(void) + __OSX_AVAILABLE_STARTING(__MAC_10_2, __IPHONE_NA); +OSStatus SecKeychainListCopyKeychainAtIndex(UInt16 index, SecKeychainRef *keychainRef) + __OSX_AVAILABLE_STARTING(__MAC_10_2, __IPHONE_NA); +OSStatus SecKeychainListRemoveKeychain(SecKeychainRef *keychainRef) + __OSX_AVAILABLE_STARTING(__MAC_10_2, __IPHONE_NA); +OSStatus SecKeychainRemoveFromSearchList(SecKeychainRef keychainRef) + __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA); + +/* Login keychain support */ +OSStatus SecKeychainLogin(UInt32 nameLength, const void* name, UInt32 passwordLength, const void* password) + __OSX_AVAILABLE_STARTING(__MAC_10_2, __IPHONE_NA); +OSStatus SecKeychainStash() + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_NA); +OSStatus SecKeychainLogout() + __OSX_AVAILABLE_STARTING(__MAC_10_2, __IPHONE_NA); +OSStatus SecKeychainCopyLogin(SecKeychainRef *keychainRef) + __OSX_AVAILABLE_STARTING(__MAC_10_2, __IPHONE_NA); +OSStatus SecKeychainResetLogin(UInt32 passwordLength, const void* password, Boolean resetSearchList) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); + +OSStatus SecKeychainVerifyKeyStorePassphrase(uint32_t retries) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_NA); +OSStatus SecKeychainChangeKeyStorePassphrase() + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_NA); + +/* Keychain synchronization */ +enum { + kSecKeychainNotSynchronized = 0, + kSecKeychainSynchronizedWithDotMac = 1 +}; +typedef UInt32 SecKeychainSyncState; + +OSStatus SecKeychainCopySignature(SecKeychainRef keychainRef, CFDataRef *keychainSignature) + __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA); +OSStatus SecKeychainCopyBlob(SecKeychainRef keychainRef, CFDataRef *dbBlob) + __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA); +OSStatus SecKeychainRecodeKeychain(SecKeychainRef keychainRef, CFArrayRef dbBlobArray, CFDataRef extraData) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA); +OSStatus SecKeychainCreateWithBlob(const char* fullPathName, CFDataRef dbBlob, SecKeychainRef *kcRef) + __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA); + +/* Keychain list manipulation */ +OSStatus SecKeychainAddDBToKeychainList (SecPreferencesDomain domain, const char* dbName, const CSSM_GUID *guid, uint32 subServiceType) + __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA); +OSStatus SecKeychainDBIsInKeychainList (SecPreferencesDomain domain, const char* dbName, const CSSM_GUID *guid, uint32 subServiceType) + __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA); +OSStatus SecKeychainRemoveDBFromKeychainList (SecPreferencesDomain domain, const char* dbName, const CSSM_GUID *guid, uint32 subServiceType) + __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA); + +/* server operation (keychain inhibit) */ +void SecKeychainSetServerMode() + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + +/* special calls */ +OSStatus SecKeychainCleanupHandles() + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); +OSStatus SecKeychainSystemKeychainCheckWouldDeadlock() + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRef systemKeychainRef, CFStringRef username, CFStringRef password) + __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_NA); + +/*! + @function SecKeychainMDSInstall + Set up MDS. + */ +OSStatus SecKeychainMDSInstall(); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECKEYCHAINPRIV_H_ */ diff --git a/libsecurity_keychain/lib/SecKeychainSearch.cpp b/Security/libsecurity_keychain/lib/SecKeychainSearch.cpp similarity index 97% rename from libsecurity_keychain/lib/SecKeychainSearch.cpp rename to Security/libsecurity_keychain/lib/SecKeychainSearch.cpp index fb044095..df491e71 100644 --- a/libsecurity_keychain/lib/SecKeychainSearch.cpp +++ b/Security/libsecurity_keychain/lib/SecKeychainSearch.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecKeychainSearch.h b/Security/libsecurity_keychain/lib/SecKeychainSearch.h similarity index 98% rename from libsecurity_keychain/lib/SecKeychainSearch.h rename to Security/libsecurity_keychain/lib/SecKeychainSearch.h index b6c86ec2..506fc5c9 100644 --- a/libsecurity_keychain/lib/SecKeychainSearch.h +++ b/Security/libsecurity_keychain/lib/SecKeychainSearch.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecKeychainSearchPriv.h b/Security/libsecurity_keychain/lib/SecKeychainSearchPriv.h similarity index 97% rename from libsecurity_keychain/lib/SecKeychainSearchPriv.h rename to Security/libsecurity_keychain/lib/SecKeychainSearchPriv.h index c7206ef8..6d907fd9 100644 --- a/libsecurity_keychain/lib/SecKeychainSearchPriv.h +++ b/Security/libsecurity_keychain/lib/SecKeychainSearchPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecNetscapeTemplates.cpp b/Security/libsecurity_keychain/lib/SecNetscapeTemplates.cpp similarity index 97% rename from libsecurity_keychain/lib/SecNetscapeTemplates.cpp rename to Security/libsecurity_keychain/lib/SecNetscapeTemplates.cpp index c5c37831..287612ed 100644 --- a/libsecurity_keychain/lib/SecNetscapeTemplates.cpp +++ b/Security/libsecurity_keychain/lib/SecNetscapeTemplates.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecNetscapeTemplates.h b/Security/libsecurity_keychain/lib/SecNetscapeTemplates.h similarity index 97% rename from libsecurity_keychain/lib/SecNetscapeTemplates.h rename to Security/libsecurity_keychain/lib/SecNetscapeTemplates.h index 043156a9..f28f801d 100644 --- a/libsecurity_keychain/lib/SecNetscapeTemplates.h +++ b/Security/libsecurity_keychain/lib/SecNetscapeTemplates.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecPassword.cpp b/Security/libsecurity_keychain/lib/SecPassword.cpp similarity index 99% rename from libsecurity_keychain/lib/SecPassword.cpp rename to Security/libsecurity_keychain/lib/SecPassword.cpp index f6e2e497..c5989d05 100644 --- a/libsecurity_keychain/lib/SecPassword.cpp +++ b/Security/libsecurity_keychain/lib/SecPassword.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecPassword.h b/Security/libsecurity_keychain/lib/SecPassword.h similarity index 98% rename from libsecurity_keychain/lib/SecPassword.h rename to Security/libsecurity_keychain/lib/SecPassword.h index c961d4c4..926e3c47 100644 --- a/libsecurity_keychain/lib/SecPassword.h +++ b/Security/libsecurity_keychain/lib/SecPassword.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecPkcs8Templates.cpp b/Security/libsecurity_keychain/lib/SecPkcs8Templates.cpp similarity index 97% rename from libsecurity_keychain/lib/SecPkcs8Templates.cpp rename to Security/libsecurity_keychain/lib/SecPkcs8Templates.cpp index d3080379..6fca0000 100644 --- a/libsecurity_keychain/lib/SecPkcs8Templates.cpp +++ b/Security/libsecurity_keychain/lib/SecPkcs8Templates.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecPkcs8Templates.h b/Security/libsecurity_keychain/lib/SecPkcs8Templates.h similarity index 98% rename from libsecurity_keychain/lib/SecPkcs8Templates.h rename to Security/libsecurity_keychain/lib/SecPkcs8Templates.h index 6f1274ac..97d9703f 100644 --- a/libsecurity_keychain/lib/SecPkcs8Templates.h +++ b/Security/libsecurity_keychain/lib/SecPkcs8Templates.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_keychain/lib/SecPolicy.cpp b/Security/libsecurity_keychain/lib/SecPolicy.cpp new file mode 100644 index 00000000..7f403883 --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecPolicy.cpp @@ -0,0 +1,453 @@ +/* + * Copyright (c) 2002-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "SecBridge.h" +#include "utilities/SecCFRelease.h" + + +// String constant declarations + +#define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); + +SEC_CONST_DECL (kSecPolicyAppleX509Basic, "1.2.840.113635.100.1.2"); +SEC_CONST_DECL (kSecPolicyAppleSSL, "1.2.840.113635.100.1.3"); +SEC_CONST_DECL (kSecPolicyAppleSMIME, "1.2.840.113635.100.1.8"); +SEC_CONST_DECL (kSecPolicyAppleEAP, "1.2.840.113635.100.1.9"); +SEC_CONST_DECL (kSecPolicyAppleIPsec, "1.2.840.113635.100.1.11"); +SEC_CONST_DECL (kSecPolicyAppleiChat, "1.2.840.113635.100.1.12"); +SEC_CONST_DECL (kSecPolicyApplePKINITClient, "1.2.840.113635.100.1.14"); +SEC_CONST_DECL (kSecPolicyApplePKINITServer, "1.2.840.113635.100.1.15"); +SEC_CONST_DECL (kSecPolicyAppleCodeSigning, "1.2.840.113635.100.1.16"); +SEC_CONST_DECL (kSecPolicyApplePackageSigning, "1.2.840.113635.100.1.17"); +SEC_CONST_DECL (kSecPolicyAppleIDValidation, "1.2.840.113635.100.1.18"); +SEC_CONST_DECL (kSecPolicyMacAppStoreReceipt, "1.2.840.113635.100.1.19"); +SEC_CONST_DECL (kSecPolicyAppleTimeStamping, "1.2.840.113635.100.1.20"); +SEC_CONST_DECL (kSecPolicyAppleRevocation, "1.2.840.113635.100.1.21"); +SEC_CONST_DECL (kSecPolicyApplePassbookSigning, "1.2.840.113635.100.1.22"); +SEC_CONST_DECL (kSecPolicyAppleMobileStore, "1.2.840.113635.100.1.23"); +SEC_CONST_DECL (kSecPolicyAppleEscrowService, "1.2.840.113635.100.1.24"); +SEC_CONST_DECL (kSecPolicyAppleProfileSigner, "1.2.840.113635.100.1.25"); +SEC_CONST_DECL (kSecPolicyAppleQAProfileSigner, "1.2.840.113635.100.1.26"); +SEC_CONST_DECL (kSecPolicyAppleTestMobileStore, "1.2.840.113635.100.1.27"); +#if TARGET_OS_IPHONE +SEC_CONST_DECL (kSecPolicyAppleOTAPKISigner, "1.2.840.113635.100.1.28"); +SEC_CONST_DECL (kSecPolicyAppleTestOTAPKISigner, "1.2.840.113635.100.1.29"); +/* FIXME: this policy name should be deprecated and replaced with "kSecPolicyAppleIDValidationRecordSigning" */ +SEC_CONST_DECL (kSecPolicyAppleIDValidationRecordSigningPolicy, "1.2.840.113625.100.1.30"); +SEC_CONST_DECL (kSecPolicyAppleSMPEncryption, "1.2.840.113625.100.1.31"); +SEC_CONST_DECL (kSecPolicyAppleTestSMPEncryption, "1.2.840.113625.100.1.32"); +#endif +SEC_CONST_DECL (kSecPolicyAppleServerAuthentication, "1.2.840.113635.100.1.33"); +SEC_CONST_DECL (kSecPolicyApplePCSEscrowService, "1.2.840.113635.100.1.34"); + +SEC_CONST_DECL (kSecPolicyOid, "SecPolicyOid"); +SEC_CONST_DECL (kSecPolicyName, "SecPolicyName"); +SEC_CONST_DECL (kSecPolicyClient, "SecPolicyClient"); +SEC_CONST_DECL (kSecPolicyRevocationFlags, "SecPolicyRevocationFlags"); +SEC_CONST_DECL (kSecPolicyTeamIdentifier, "SecPolicyTeamIdentifier"); + +SEC_CONST_DECL (kSecPolicyKU_DigitalSignature, "CE_KU_DigitalSignature"); +SEC_CONST_DECL (kSecPolicyKU_NonRepudiation, "CE_KU_NonRepudiation"); +SEC_CONST_DECL (kSecPolicyKU_KeyEncipherment, "CE_KU_KeyEncipherment"); +SEC_CONST_DECL (kSecPolicyKU_DataEncipherment, "CE_KU_DataEncipherment"); +SEC_CONST_DECL (kSecPolicyKU_KeyAgreement, "CE_KU_KeyAgreement"); +SEC_CONST_DECL (kSecPolicyKU_KeyCertSign, "CE_KU_KeyCertSign"); +SEC_CONST_DECL (kSecPolicyKU_CRLSign, "CE_KU_CRLSign"); +SEC_CONST_DECL (kSecPolicyKU_EncipherOnly, "CE_KU_EncipherOnly"); +SEC_CONST_DECL (kSecPolicyKU_DecipherOnly, "CE_KU_DecipherOnly"); + +// Private functions + +SecPolicyRef SecPolicyCreateWithSecAsn1Oid(SecAsn1Oid *oidPtr); +extern "C" { CFArrayRef SecPolicyCopyEscrowRootCertificates(void); } + +// +// CF boilerplate +// +CFTypeID +SecPolicyGetTypeID(void) +{ + BEGIN_SECAPI + return gTypes().Policy.typeID; + END_SECAPI1(_kCFRuntimeNotATypeID) +} + + +// +// Sec API bridge functions +// +OSStatus +SecPolicyGetOID(SecPolicyRef policyRef, CSSM_OID* oid) +{ + BEGIN_SECAPI + Required(oid) = Policy::required(policyRef)->oid(); + END_SECAPI +} + +OSStatus +SecPolicyGetValue(SecPolicyRef policyRef, CSSM_DATA* value) +{ + BEGIN_SECAPI + Required(value) = Policy::required(policyRef)->value(); + END_SECAPI +} + +CFDictionaryRef +SecPolicyCopyProperties(SecPolicyRef policyRef) +{ + /* can't use SECAPI macros, since this function does not return OSStatus */ + CFDictionaryRef result = NULL; + try { + result = Policy::required(policyRef)->properties(); + } + catch (...) { + if (result) { + CFRelease(result); + result = NULL; + } + }; + return result; +} + +OSStatus +SecPolicySetValue(SecPolicyRef policyRef, const CSSM_DATA *value) +{ + BEGIN_SECAPI + Required(value); + const CssmData newValue(value->Data, value->Length); + Policy::required(policyRef)->setValue(newValue); + END_SECAPI +} + +OSStatus +SecPolicySetProperties(SecPolicyRef policyRef, CFDictionaryRef properties) +{ + BEGIN_SECAPI + Policy::required(policyRef)->setProperties(properties); + END_SECAPI +} + +OSStatus +SecPolicyGetTPHandle(SecPolicyRef policyRef, CSSM_TP_HANDLE* tpHandle) +{ + BEGIN_SECAPI + Required(tpHandle) = Policy::required(policyRef)->tp()->handle(); + END_SECAPI +} + +OSStatus +SecPolicyCopyAll(CSSM_CERT_TYPE certificateType, CFArrayRef* policies) +{ + BEGIN_SECAPI + Required(policies); + CFMutableArrayRef currPolicies = NULL; + currPolicies = CFArrayCreateMutable(NULL, 0, NULL); + if ( currPolicies ) + { + SecPointer cursor(new PolicyCursor(NULL, NULL)); + SecPointer policy; + while ( cursor->next(policy) ) /* copies the next policy */ + { + CFArrayAppendValue(currPolicies, policy->handle()); /* 'SecPolicyRef' appended */ + CFRelease(policy->handle()); /* refcount bumped up when appended to array */ + } + *policies = CFArrayCreateCopy(NULL, currPolicies); + CFRelease(currPolicies); + CFRelease(cursor->handle()); + } + END_SECAPI +} + +OSStatus +SecPolicyCopy(CSSM_CERT_TYPE certificateType, const CSSM_OID *policyOID, SecPolicyRef* policy) +{ + Required(policy); + Required(policyOID); + + SecPolicySearchRef srchRef = NULL; + OSStatus ortn; + + ortn = SecPolicySearchCreate(certificateType, policyOID, NULL, &srchRef); + if(ortn) { + return ortn; + } + ortn = SecPolicySearchCopyNext(srchRef, policy); + CFRelease(srchRef); + return ortn; +} + +/* new in 10.6 */ +SecPolicyRef +SecPolicyCreateBasicX509(void) +{ + // return a SecPolicyRef object for the X.509 Basic policy + SecPolicyRef policy = nil; + SecPolicySearchRef policySearch = nil; + OSStatus status = SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_X509_BASIC, NULL, &policySearch); + if (!status) { + status = SecPolicySearchCopyNext(policySearch, &policy); + } + if (policySearch) { + CFRelease(policySearch); + } + return policy; +} + +/* new in 10.6 */ +SecPolicyRef +SecPolicyCreateSSL(Boolean server, CFStringRef hostname) +{ + // return a SecPolicyRef object for the SSL policy, given hostname and client options + SecPolicyRef policy = nil; + SecPolicySearchRef policySearch = nil; + OSStatus status = SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_SSL, NULL, &policySearch); + if (!status) { + status = SecPolicySearchCopyNext(policySearch, &policy); + } + if (!status && policy) { + // set options for client-side or server-side policy evaluation + char *strbuf = NULL; + const char *hostnamestr = NULL; + if (hostname) { + hostnamestr = CFStringGetCStringPtr(hostname, kCFStringEncodingUTF8); + if (hostnamestr == NULL) { + CFIndex maxLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(hostname), kCFStringEncodingUTF8) + 1; + strbuf = (char *)malloc(maxLen); + if (CFStringGetCString(hostname, strbuf, maxLen, kCFStringEncodingUTF8)) { + hostnamestr = strbuf; + } + } + } + uint32 hostnamelen = (hostnamestr) ? (uint32)strlen(hostnamestr) : 0; + uint32 flags = (!server) ? CSSM_APPLE_TP_SSL_CLIENT : 0; + CSSM_APPLE_TP_SSL_OPTIONS opts = {CSSM_APPLE_TP_SSL_OPTS_VERSION, hostnamelen, hostnamestr, flags}; + CSSM_DATA data = {sizeof(opts), (uint8*)&opts}; + SecPolicySetValue(policy, &data); + + if (strbuf) { + free(strbuf); + } + } + if (policySearch) { + CFRelease(policySearch); + } + return policy; +} + +SecPolicyRef +SecPolicyCreateWithSecAsn1Oid(SecAsn1Oid *oidPtr) +{ + SecPolicyRef policy = NULL; + try { + SecPointer policyObj; + PolicyCursor::policy(oidPtr, policyObj); + policy = policyObj->handle(); + } + catch (...) {} + + return policy; +} + +/* new in 10.7 */ +SecPolicyRef +SecPolicyCreateWithOID(CFTypeRef policyOID) +{ + // for now, we only accept the policy constants that are defined in SecPolicy.h + CFStringRef oidStr = (CFStringRef)policyOID; + CSSM_OID *oidPtr = NULL; + SecPolicyRef policy = NULL; + if (!oidStr) { + return policy; + } + struct oidmap_entry_t { + const CFTypeRef oidstr; + const SecAsn1Oid *oidptr; + }; + const oidmap_entry_t oidmap[] = { + { kSecPolicyAppleX509Basic, &CSSMOID_APPLE_X509_BASIC }, + { kSecPolicyAppleSSL, &CSSMOID_APPLE_TP_SSL }, + { kSecPolicyAppleSMIME, &CSSMOID_APPLE_TP_SMIME }, + { kSecPolicyAppleEAP, &CSSMOID_APPLE_TP_EAP }, + { kSecPolicyAppleIPsec, &CSSMOID_APPLE_TP_IP_SEC }, + { kSecPolicyAppleiChat, &CSSMOID_APPLE_TP_ICHAT }, + { kSecPolicyApplePKINITClient, &CSSMOID_APPLE_TP_PKINIT_CLIENT }, + { kSecPolicyApplePKINITServer, &CSSMOID_APPLE_TP_PKINIT_SERVER }, + { kSecPolicyAppleCodeSigning, &CSSMOID_APPLE_TP_CODE_SIGNING }, + { kSecPolicyMacAppStoreReceipt, &CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT }, + { kSecPolicyAppleIDValidation, &CSSMOID_APPLE_TP_APPLEID_SHARING }, + { kSecPolicyAppleTimeStamping, &CSSMOID_APPLE_TP_TIMESTAMPING }, + { kSecPolicyAppleRevocation, &CSSMOID_APPLE_TP_REVOCATION }, + { kSecPolicyApplePassbookSigning, &CSSMOID_APPLE_TP_PASSBOOK_SIGNING }, + { kSecPolicyAppleMobileStore, &CSSMOID_APPLE_TP_MOBILE_STORE }, + { kSecPolicyAppleEscrowService, &CSSMOID_APPLE_TP_ESCROW_SERVICE }, + { kSecPolicyAppleProfileSigner, &CSSMOID_APPLE_TP_PROFILE_SIGNING }, + { kSecPolicyAppleQAProfileSigner, &CSSMOID_APPLE_TP_QA_PROFILE_SIGNING }, + { kSecPolicyAppleTestMobileStore, &CSSMOID_APPLE_TP_TEST_MOBILE_STORE }, + { kSecPolicyApplePCSEscrowService, &CSSMOID_APPLE_TP_PCS_ESCROW_SERVICE }, + }; + unsigned int i, oidmaplen = sizeof(oidmap) / sizeof(oidmap_entry_t); + for (i=0; i +/* New in 10.10 */ +// Takes the "context" policies to extract the revocation and apply it to timeStamp. +CFArrayRef +SecPolicyCreateAppleTimeStampingAndRevocationPolicies(CFTypeRef policyOrArray) +{ + /* can't use SECAPI macros, since this function does not return OSStatus */ + CFArrayRef resultPolicyArray=NULL; + try { + // Set default policy + CFRef policyArray = cfArrayize(policyOrArray); + CFRef defaultPolicy = SecPolicyCreateWithOID(kSecPolicyAppleTimeStamping); + CFRef appleTimeStampingPolicies = makeCFMutableArray(1,defaultPolicy.get()); + + // Parse the policy and add revocation related ones + CFIndex numPolicies = CFArrayGetCount(policyArray); + for(CFIndex dex=0; dex pol = Policy::required(SecPolicyRef(secPol)); + const CssmOid &oid = pol->oid(); + if ((oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION)) + || (oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL)) + || (oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP))) + { + CFArrayAppendValue(appleTimeStampingPolicies, secPol); + } + } + // Transfer of ownership + resultPolicyArray=appleTimeStampingPolicies.yield(); + } + catch (...) { + CFReleaseNull(resultPolicyArray); + }; + return resultPolicyArray; +} + + diff --git a/Security/libsecurity_keychain/lib/SecPolicy.h b/Security/libsecurity_keychain/lib/SecPolicy.h new file mode 100644 index 00000000..3a42320a --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecPolicy.h @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2002-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecPolicy + The functions provided in SecPolicy.h provide an interface to various + X.509 certificate trust policies. +*/ + +#ifndef _SECURITY_SECPOLICY_H_ +#define _SECURITY_SECPOLICY_H_ + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + @enum Policy Constants + @discussion Predefined constants used to specify a policy. + @constant kSecPolicyAppleX509Basic + @constant kSecPolicyAppleSSL + @constant kSecPolicyAppleSMIME + @constant kSecPolicyAppleEAP + @constant kSecPolicyAppleIPsec + @constant kSecPolicyAppleiChat + @constant kSecPolicyApplePKINITClient + @constant kSecPolicyApplePKINITServer + @constant kSecPolicyAppleCodeSigning + @constant kSecPolicyMacAppStoreReceipt + @constant kSecPolicyAppleIDValidation + @constant kSecPolicyAppleTimeStamping + @constant kSecPolicyAppleRevocation + @constant kSecPolicyApplePassbookSigning +*/ +extern CFTypeRef kSecPolicyAppleX509Basic + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleSSL + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleSMIME + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleEAP + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleIPsec + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleiChat + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); +extern CFTypeRef kSecPolicyApplePKINITClient + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyApplePKINITServer + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyAppleCodeSigning + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPolicyMacAppStoreReceipt + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyAppleIDValidation + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleTimeStamping + __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleRevocation + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecPolicyApplePassbookSigning + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + +/*! + @enum Policy Value Constants + @abstract Predefined property key constants used to get or set values in + a dictionary for a policy instance. + @discussion + All policies will have the following read-only value: + kSecPolicyOid (the policy object identifier) + + Additional policy values which your code can optionally set: + kSecPolicyName (name which must be matched) + kSecPolicyClient (evaluate for client, rather than server) + kSecPolicyRevocationFlags (only valid for a revocation policy) + + @constant kSecPolicyOid Specifies the policy OID (value is a CFStringRef) + @constant kSecPolicyName Specifies a CFStringRef (or CFArrayRef of same) + containing a name which must be matched in the certificate to satisfy + this policy. For SSL/TLS, EAP, and IPSec policies, this specifies the + server name which must match the common name of the certificate. + For S/MIME, this specifies the RFC822 email address. + For Passbook signing, this specifies the pass signer. + @constant kSecPolicyClient Specifies a CFBooleanRef value that indicates + this evaluation should be for a client certificate. If not set (or + false), the policy evaluates the certificate as a server certificate. + @constant kSecPolicyRevocationFlags Specifies a CFNumberRef that holds a + kCFNumberCFIndexType bitmask value. See "Revocation Policy Constants" + for a description of individual bits in this value. + @constant kSecPolicyTeamIdentifier Specifies a CFStringRef containing a + team identifier which must be matched in the certificate to satisfy + this policy. For the Passbook signing policy, this string must match + the Organizational Unit field of the certificate subject. + */ +extern CFTypeRef kSecPolicyOid + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPolicyName + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPolicyClient + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPolicyRevocationFlags + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecPolicyTeamIdentifier + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + + +/*! + @function SecPolicyGetTypeID + @abstract Returns the type identifier of SecPolicy instances. + @result The CFTypeID of SecPolicy instances. +*/ +CFTypeID SecPolicyGetTypeID(void) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +/*! + @function SecPolicyCopyProperties + @abstract Returns a dictionary of this policy's properties. + @param policyRef A policy reference. + @result A properties dictionary. See "Policy Value Constants" for a list + of currently defined property keys. It is the caller's responsibility to + CFRelease this reference when it is no longer needed. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function returns the properties for a policy, as set by the + policy's construction function or by a prior call to SecPolicySetProperties. +*/ +CFDictionaryRef SecPolicyCopyProperties(SecPolicyRef policyRef) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); + +/*! + @function SecPolicyCreateBasicX509 + @abstract Returns a policy object for the default X.509 policy. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. +*/ +SecPolicyRef SecPolicyCreateBasicX509(void) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @function SecPolicyCreateSSL + @abstract Returns a policy object for evaluating SSL certificate chains. + @param server Passing true for this parameter creates a policy for SSL + server certificates. + @param hostname (Optional) If present, the policy will require the specified + hostname to match the hostname in the leaf certificate. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. +*/ +SecPolicyRef SecPolicyCreateSSL(Boolean server, CFStringRef hostname) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @enum Revocation Policy Constants + @abstract Predefined constants which allow you to specify how revocation + checking will be performed for a trust evaluation. + @constant kSecRevocationOCSPMethod If this flag is set, perform revocation + checking using OCSP (Online Certificate Status Protocol). + @constant kSecRevocationCRLMethod If this flag is set, perform revocation + checking using the CRL (Certificate Revocation List) method. + @constant kSecRevocationPreferCRL If this flag is set, then CRL revocation + checking will be preferred over OCSP (by default, OCSP is preferred.) + Note that this flag only matters if both revocation methods are specified. + @constant kSecRevocationRequirePositiveResponse If this flag is set, then + the policy will fail unless a verified positive response is obtained. If + the flag is not set, revocation checking is done on a "best attempt" basis, + where failure to reach the server is not considered fatal. + @constant kSecRevocationNetworkAccessDisabled If this flag is set, then + no network access is performed; only locally cached replies are consulted. + @constant kSecRevocationUseAnyAvailableMethod Specifies that either + OCSP or CRL may be used, depending on the method(s) specified in the + certificate and the value of kSecRevocationPreferCRL. + */ +enum { + kSecRevocationOCSPMethod = (1 << 0), + kSecRevocationCRLMethod = (1 << 1), + kSecRevocationPreferCRL = (1 << 2), + kSecRevocationRequirePositiveResponse = (1 << 3), + kSecRevocationNetworkAccessDisabled = (1 << 4), + kSecRevocationUseAnyAvailableMethod = (kSecRevocationOCSPMethod | + kSecRevocationCRLMethod) +}; + +/*! + @function SecPolicyCreateRevocation + @abstract Returns a policy object for checking revocation of certificates. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + @param revocationFlags Flags to specify revocation checking options. + @discussion Use this function to create a revocation policy with behavior + specified by revocationFlags. See the "Revocation Policy Constants" section + for a description of these flags. Note: it is usually not necessary to + create a revocation policy yourself unless you wish to override default + system behavior (e.g. to force a particular method, or to disable + revocation checking entirely.) +*/ +SecPolicyRef SecPolicyCreateRevocation(CFOptionFlags revocationFlags) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + +/*! + @function SecPolicyCreateWithProperties + @abstract Returns a policy object based on an object identifier for the + policy type. See the "Policy Constants" section for a list of defined + policy object identifiers. + @param policyIdentifier The identifier for the desired policy type. + @param properties (Optional) A properties dictionary. See "Policy Value + Constants" for a list of currently defined property keys. + @result The returned policy reference, or NULL if the policy could not be + created. +*/ +SecPolicyRef SecPolicyCreateWithProperties(CFTypeRef policyIdentifier, + CFDictionaryRef properties) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + + +/* + * Legacy functions (OS X only) + */ +#if TARGET_OS_MAC && !TARGET_OS_IPHONE +#include + +/*! + @enum Policy Value Constants (OS X) + @discussion Predefined property key constants used to get or set values in + a dictionary for a policy instance. + + Some policy values may specify CFBooleanRef key usage constraints: + kSecPolicyKU_DigitalSignature + kSecPolicyKU_NonRepudiation + kSecPolicyKU_KeyEncipherment + kSecPolicyKU_DataEncipherment + kSecPolicyKU_KeyAgreement + kSecPolicyKU_KeyCertSign + kSecPolicyKU_CRLSign + kSecPolicyKU_EncipherOnly + kSecPolicyKU_DecipherOnly + + kSecPolicyKU policy values define certificate-level key purposes, + in contrast to the key-level definitions in SecItem.h + + For example, a key in a certificate might be acceptable to use for + signing a CRL, but not for signing another certificate. In either + case, this key would have the ability to sign (i.e. kSecAttrCanSign + is true), but may only sign for specific purposes allowed by these + policy constants. Similarly, a public key might have the capability + to perform encryption or decryption, but the certificate in which it + resides might have a decipher-only certificate policy. + + These constants correspond to values defined in RFC 5280, section + 4.2.1.3 (Key Usage) which define the purpose of a key contained in a + certificate, in contrast to section 4.1.2.7 which define the uses that + a key is capable of. + + Note: these constants are not available on iOS. Your code should + avoid direct reliance on these values for making policy decisions + and use higher level policies where possible. + + @constant kSecPolicyKU_DigitalSignature Specifies that the certificate must + have a key usage that allows it to be used for signing. + @constant kSecPolicyKU_NonRepudiation Specifies that the certificate must + have a key usage that allows it to be used for non-repudiation. + @constant kSecPolicyKU_KeyEncipherment Specifies that the certificate must + have a key usage that allows it to be used for key encipherment. + @constant kSecPolicyKU_DataEncipherment Specifies that the certificate must + have a key usage that allows it to be used for data encipherment. + @constant kSecPolicyKU_KeyAgreement Specifies that the certificate must + have a key usage that allows it to be used for key agreement. + @constant kSecPolicyKU_KeyCertSign Specifies that the certificate must + have a key usage that allows it to be used for signing certificates. + @constant kSecPolicyKU_CRLSign Specifies that the certificate must + have a key usage that allows it to be used for signing CRLs. + @constant kSecPolicyKU_EncipherOnly Specifies that the certificate must + have a key usage that permits it to be used for encryption only. + @constant kSecPolicyKU_DecipherOnly Specifies that the certificate must + have a key usage that permits it to be used for decryption only. + */ +extern CFTypeRef kSecPolicyKU_DigitalSignature + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyKU_NonRepudiation + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyKU_KeyEncipherment + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyKU_DataEncipherment + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyKU_KeyAgreement + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyKU_KeyCertSign + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyKU_CRLSign + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyKU_EncipherOnly + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyKU_DecipherOnly + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @function SecPolicyCreateWithOID + @abstract Returns a policy object based on an object identifier for the + policy type. See the "Policy Constants" section for a list of defined + policy object identifiers. + @param policyOID The OID of the desired policy. + @result The returned policy reference, or NULL if the policy could not be + created. + @discussion This function is deprecated in Mac OS X 10.9 and later; + use SecPolicyCreateWithProperties (or a more specific policy creation + function) instead. +*/ +SecPolicyRef SecPolicyCreateWithOID(CFTypeRef policyOID) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecPolicyGetOID + @abstract Returns a policy's object identifier. + @param policyRef A policy reference. + @param oid On return, a pointer to the policy's object identifier. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in Mac OS X 10.7 and later; + use SecPolicyCopyProperties instead. +*/ +OSStatus SecPolicyGetOID(SecPolicyRef policyRef, CSSM_OID *oid) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecPolicyGetValue + @abstract Returns a policy's value. + @param policyRef A policy reference. + @param value On return, a pointer to the policy's value. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in Mac OS X 10.7 and later; + use SecPolicyCopyProperties instead. +*/ +OSStatus SecPolicyGetValue(SecPolicyRef policyRef, CSSM_DATA *value) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecPolicySetValue + @abstract Sets a policy's value. + @param policyRef A policy reference. + @param value The value to be set into the policy object, replacing any + previous value. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in Mac OS X 10.7 and later. Policy + instances should be considered read-only; in cases where your code would + consider changing properties of a policy, it should instead create a new + policy instance with the desired properties. +*/ +OSStatus SecPolicySetValue(SecPolicyRef policyRef, const CSSM_DATA *value) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecPolicySetProperties + @abstract Sets a policy's properties. + @param policyRef A policy reference. + @param properties A properties dictionary. See "Policy Value Constants" + for a list of currently defined property keys. This dictionary replaces the + policy's existing properties, if any. Note that the policy OID (specified + by kSecPolicyOid) is a read-only property of the policy and cannot be set. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in Mac OS X 10.9 and later. Policy + instances should be considered read-only; in cases where your code would + consider changing properties of a policy, it should instead create a new + policy instance with the desired properties. +*/ +OSStatus SecPolicySetProperties(SecPolicyRef policyRef, + CFDictionaryRef properties) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecPolicyGetTPHandle + @abstract Returns the CSSM trust policy handle for the given policy. + @param policyRef A policy reference. + @param tpHandle On return, a pointer to a value of type CSSM_TP_HANDLE. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in Mac OS X 10.7 and later. +*/ +OSStatus SecPolicyGetTPHandle(SecPolicyRef policyRef, CSSM_TP_HANDLE *tpHandle) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + +#endif /* TARGET_OS_MAC && !TARGET_OS_IPHONE */ + + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECPOLICY_H_ */ diff --git a/Security/libsecurity_keychain/lib/SecPolicyPriv.h b/Security/libsecurity_keychain/lib/SecPolicyPriv.h new file mode 100644 index 00000000..4860d676 --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecPolicyPriv.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2003-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecPolicyPriv + Private part of SecPolicy.h +*/ + +#ifndef _SECURITY_SECPOLICYPRIV_H_ +#define _SECURITY_SECPOLICYPRIV_H_ + +#include +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + @enum Policy Constants (Private) + @discussion Predefined constants used to specify a policy. + @constant kSecPolicyAppleMobileStore + @constant kSecPolicyAppleTestMobileStore + @constant kSecPolicyAppleEscrowService + @constant kSecPolicyAppleProfileSigner + @constant kSecPolicyAppleQAProfileSigner + @constant kSecPolicyAppleServerAuthentication + @constant kSecPolicyAppleOTAPKISigner + @constant kSecPolicyAppleTestOTAPKISigner + @constant kSecPolicyAppleIDValidationRecordSigning + @constant kSecPolicyAppleSMPEncryption + @constant kSecPolicyAppleTestSMPEncryption + @constant kSecPolicyApplePCSEscrowService + +*/ +extern CFTypeRef kSecPolicyAppleMobileStore + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleTestMobileStore + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleEscrowService + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleProfileSigner + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleQAProfileSigner + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleServerAuthentication + __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); +#if TARGET_OS_IPHONE +extern CFTypeRef kSecPolicyAppleOTAPKISigner + __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleTestOTAPKISigner + __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleIDValidationRecordSigningPolicy + __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleSMPEncryption + __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0); +extern CFTypeRef kSecPolicyAppleTestSMPEncryption + __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0); +#endif +extern CFTypeRef kSecPolicyApplePCSEscrowService + __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); + +/*! + @function SecPolicyCopy + @abstract Returns a copy of a policy reference based on certificate type and OID. + @param certificateType A certificate type. + @param policyOID The OID of the policy you want to find. This is a required parameter. See oidsalg.h to see a list of policy OIDs. + @param policy The returned policy reference. This is a required parameter. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in Mac OS X 10.7 and later; + to obtain a policy reference, use one of the SecPolicyCreate* functions in SecPolicy.h. +*/ +OSStatus SecPolicyCopy(CSSM_CERT_TYPE certificateType, const CSSM_OID *policyOID, SecPolicyRef* policy) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_3, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecPolicyCopyAll + @abstract Returns an array of all known policies based on certificate type. + @param certificateType A certificate type. This is a optional parameter. Pass CSSM_CERT_UNKNOWN if the certificate type is unknown. + @param policies The returned array of policies. This is a required parameter. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in Mac OS X 10.7 and later; + to obtain a policy reference, use one of the SecPolicyCreate* functions in SecPolicy.h. (Note: there is normally + no reason to iterate over multiple disjointed policies, except to provide a way to edit trust settings for each + policy, as is done in certain certificate UI views. In that specific case, your code should call SecPolicyCreateWithOID + for each desired policy from the list of supported OID constants in SecPolicy.h.) +*/ +OSStatus SecPolicyCopyAll(CSSM_CERT_TYPE certificateType, CFArrayRef* policies) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_3, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecPolicyCreateAppleIDSService + @abstract Ensure we're appropriately pinned to the IDS service (SSL + Apple restrictions) + */ +SecPolicyRef SecPolicyCreateAppleIDSService(CFStringRef hostname); + +/*! + @function SecPolicyCreateApplePushService + @abstract Ensure we're appropriately pinned to the Push service (SSL + Apple restrictions) + */ +SecPolicyRef SecPolicyCreateApplePushService(CFStringRef hostname); + +/*! + @function SecPolicyCreateAppleMMCSService + @abstract Ensure we're appropriately pinned to the IDS service (SSL + Apple restrictions) + */ +SecPolicyRef SecPolicyCreateAppleMMCSService(CFStringRef hostname); + +/*! + @function SecPolicyCreateAppleSSLService + @abstract Ensure we're appropriately pinned to an Apple server (SSL + Apple restrictions) + */ +SecPolicyRef SecPolicyCreateAppleSSLService(CFStringRef hostname); + +/*! + @function SecPolicyCreateAppleTimeStampingAndRevocationPolicies + @abstract Create timeStamping policy array from a given set of policies by applying identical revocation behavior + @param policyOrArray can be a SecPolicyRef or a CFArray of SecPolicyRef + */ +CFArrayRef SecPolicyCreateAppleTimeStampingAndRevocationPolicies(CFTypeRef policyOrArray); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECPOLICYPRIV_H_ */ diff --git a/libsecurity_keychain/lib/SecPolicySearch.cpp b/Security/libsecurity_keychain/lib/SecPolicySearch.cpp similarity index 96% rename from libsecurity_keychain/lib/SecPolicySearch.cpp rename to Security/libsecurity_keychain/lib/SecPolicySearch.cpp index 67493ca8..967ff835 100644 --- a/libsecurity_keychain/lib/SecPolicySearch.cpp +++ b/Security/libsecurity_keychain/lib/SecPolicySearch.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecPolicySearch.h b/Security/libsecurity_keychain/lib/SecPolicySearch.h similarity index 98% rename from libsecurity_keychain/lib/SecPolicySearch.h rename to Security/libsecurity_keychain/lib/SecPolicySearch.h index c4bd7718..091b70b4 100644 --- a/libsecurity_keychain/lib/SecPolicySearch.h +++ b/Security/libsecurity_keychain/lib/SecPolicySearch.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecRSAKeyP.h b/Security/libsecurity_keychain/lib/SecRSAKeyP.h similarity index 96% rename from libsecurity_keychain/lib/SecRSAKeyP.h rename to Security/libsecurity_keychain/lib/SecRSAKeyP.h index a97a60d3..c7fb515b 100644 --- a/libsecurity_keychain/lib/SecRSAKeyP.h +++ b/Security/libsecurity_keychain/lib/SecRSAKeyP.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2008,2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecRandom.c b/Security/libsecurity_keychain/lib/SecRandom.c similarity index 97% rename from libsecurity_keychain/lib/SecRandom.c rename to Security/libsecurity_keychain/lib/SecRandom.c index f52d979a..dcdb1aef 100644 --- a/libsecurity_keychain/lib/SecRandom.c +++ b/Security/libsecurity_keychain/lib/SecRandom.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_keychain/lib/SecRandom.h b/Security/libsecurity_keychain/lib/SecRandom.h new file mode 100644 index 00000000..242c6230 --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecRandom.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2007-2009,2011 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 SecRandom + The functions provided in SecRandom.h implement high-level accessors + to cryptographically secure random numbers. +*/ + +#ifndef _SECURITY_SECRANDOM_H_ +#define _SECURITY_SECRANDOM_H_ + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + @typedef SecRandomRef + @abstract Reference to a (psuedo) random number generator. +*/ +typedef const struct __SecRandom * SecRandomRef; + +/* This is a synonym for NULL, if you'd rather use a named constant. This + refers to a cryptographically secure random number generator. */ +extern const SecRandomRef kSecRandomDefault + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + +/*! + @function SecRandomCopyBytes + @abstract Return count random bytes in *bytes, allocated by the caller. + @result Return 0 on success or -1 if something went wrong, check errno + to find out the real error. +*/ +int SecRandomCopyBytes(SecRandomRef rnd, size_t count, uint8_t *bytes) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECRANDOM_H_ */ diff --git a/libsecurity_keychain/lib/SecRandomP.h b/Security/libsecurity_keychain/lib/SecRandomP.h similarity index 96% rename from libsecurity_keychain/lib/SecRandomP.h rename to Security/libsecurity_keychain/lib/SecRandomP.h index e93e5afa..881c1397 100644 --- a/libsecurity_keychain/lib/SecRandomP.h +++ b/Security/libsecurity_keychain/lib/SecRandomP.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2009,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecRecoveryPassword.c b/Security/libsecurity_keychain/lib/SecRecoveryPassword.c similarity index 99% rename from libsecurity_keychain/lib/SecRecoveryPassword.c rename to Security/libsecurity_keychain/lib/SecRecoveryPassword.c index f59c0975..0c93c311 100644 --- a/libsecurity_keychain/lib/SecRecoveryPassword.c +++ b/Security/libsecurity_keychain/lib/SecRecoveryPassword.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecRecoveryPassword.h b/Security/libsecurity_keychain/lib/SecRecoveryPassword.h similarity index 98% rename from libsecurity_keychain/lib/SecRecoveryPassword.h rename to Security/libsecurity_keychain/lib/SecRecoveryPassword.h index fdc8d1c8..27c5cb2e 100644 --- a/libsecurity_keychain/lib/SecRecoveryPassword.h +++ b/Security/libsecurity_keychain/lib/SecRecoveryPassword.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecTrust.cpp b/Security/libsecurity_keychain/lib/SecTrust.cpp similarity index 99% rename from libsecurity_keychain/lib/SecTrust.cpp rename to Security/libsecurity_keychain/lib/SecTrust.cpp index efdb501f..0c56946d 100644 --- a/libsecurity_keychain/lib/SecTrust.cpp +++ b/Security/libsecurity_keychain/lib/SecTrust.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2010,2012-2013 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/Security/libsecurity_keychain/lib/SecTrust.h b/Security/libsecurity_keychain/lib/SecTrust.h new file mode 100644 index 00000000..4a71e296 --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecTrust.h @@ -0,0 +1,686 @@ +/* + * Copyright (c) 2002-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecTrust + The functions and data types in SecTrust implement trust computation + and allow the caller to apply trust decisions to the evaluation. + */ + +#ifndef _SECURITY_SECTRUST_H_ +#define _SECURITY_SECTRUST_H_ + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + @typedef SecTrustResultType + @abstract Specifies the trust result type. + @discussion SecTrustResultType results have two dimensions. They specify + both whether evaluation suceeded and whether this is because of a user + decision. The commonly expected result is kSecTrustResultUnspecified, + which indicates a positive result that wasn't decided by the user. The + common failure is kSecTrustResultRecoverableTrustFailure, which means a + negative result. kSecTrustResultProceed and kSecTrustResultDeny are the + positive and negative result respectively when decided by the user. User + decisions are persisted through the use of SecTrustCopyExceptions() and + SecTrustSetExceptions(). Finally, kSecTrustResultFatalTrustFailure is a + negative result that must not be circumvented. + @constant kSecTrustResultInvalid Indicates an invalid setting or result. + This result usually means that SecTrustEvaluate has not yet been called. + @constant kSecTrustResultProceed Indicates you may proceed. This value + may be returned by the SecTrustEvaluate function or stored as part of + the user trust settings. + @constant kSecTrustResultConfirm Indicates confirmation with the user + is required before proceeding. Important: this value is no longer returned + or supported by SecTrustEvaluate or the SecTrustSettings API starting in + OS X 10.5; its use is deprecated in OS X 10.9 and later, as well as in iOS. + @constant kSecTrustResultDeny Indicates a user-configured deny; do not + proceed. This value may be returned by the SecTrustEvaluate function + or stored as part of the user trust settings. + @constant kSecTrustResultUnspecified Indicates the evaluation succeeded + and the certificate is implicitly trusted, but user intent was not + explicitly specified. This value may be returned by the SecTrustEvaluate + function or stored as part of the user trust settings. + @constant kSecTrustResultRecoverableTrustFailure Indicates a trust policy + failure which can be overridden by the user. This value may be returned + by the SecTrustEvaluate function but not stored as part of the user + trust settings. + @constant kSecTrustResultFatalTrustFailure Indicates a trust failure + which cannot be overridden by the user. This value may be returned by the + SecTrustEvaluate function but not stored as part of the user trust + settings. + @constant kSecTrustResultOtherError Indicates a failure other than that + of trust evaluation. This value may be returned by the SecTrustEvaluate + function but not stored as part of the user trust settings. + */ + +typedef uint32_t SecTrustResultType; +enum { + kSecTrustResultInvalid = 0, + kSecTrustResultProceed = 1, + kSecTrustResultConfirm CF_ENUM_DEPRECATED(10_0, 10_9, NA, NA) = 2, + kSecTrustResultDeny = 3, + kSecTrustResultUnspecified = 4, + kSecTrustResultRecoverableTrustFailure = 5, + kSecTrustResultFatalTrustFailure = 6, + kSecTrustResultOtherError = 7 +}; + +/*! + @typedef SecTrustRef + @abstract CFType used for performing X.509 certificate trust evaluations. + */ +typedef struct __SecTrust *SecTrustRef; + +/*! + @enum Trust Property Constants + @discussion Predefined key constants used to obtain values in a + per-certificate dictionary of trust evaluation results, + as retrieved from a call to SecTrustCopyProperties. + @constant kSecPropertyTypeTitle Specifies a key whose value is a + CFStringRef containing the title (display name) of this certificate. + @constant kSecPropertyTypeError Specifies a key whose value is a + CFStringRef containing the reason for a trust evaluation failure. + */ +extern CFTypeRef kSecPropertyTypeTitle + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPropertyTypeError + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); + +/*! + @enum Trust Result Constants + @discussion Predefined key constants used to obtain values in a + dictionary of trust evaluation results for a certificate chain, + as retrieved from a call to SecTrustCopyResult. + @constant kSecTrustEvaluationDate + This key will be present if a trust evaluation has been performed + and results are available. Its value is a CFDateRef representing + when the evaluation for this trust object took place. + @constant kSecTrustExtendedValidation + This key will be present and have a value of kCFBooleanTrue + if this chain was validated for EV. + @constant kSecTrustOrganizationName + Organization name field of subject of leaf certificate. This + field is meant to be displayed to the user as the validated + name of the company or entity that owns the certificate if the + kSecTrustExtendedValidation key is present. + @constant kSecTrustResultValue + This key will be present if a trust evaluation has been performed. + Its value is a CFNumberRef representing the SecTrustResultType result + for the evaluation. + @constant kSecTrustRevocationChecked + This key will be present iff this chain had its revocation checked. + The value will be a kCFBooleanTrue if revocation checking was + successful and none of the certificates in the chain were revoked. + The value will be kCFBooleanFalse if no current revocation status + could be obtained for one or more certificates in the chain due + to connection problems or timeouts. This is a hint to a client + to retry revocation checking at a later time. + @constant kSecTrustRevocationValidUntilDate + This key will be present iff kSecTrustRevocationChecked has a + value of kCFBooleanTrue. The value will be a CFDateRef representing + the earliest date at which the revocation info for one of the + certificates in this chain might change. + */ +extern CFTypeRef kSecTrustEvaluationDate + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecTrustExtendedValidation + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecTrustOrganizationName + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecTrustResultValue + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecTrustRevocationChecked + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecTrustRevocationValidUntilDate + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + +#ifdef __BLOCKS__ +/*! + @typedef SecTrustCallback + @abstract Delivers the result from an asynchronous trust evaluation. + @param trustRef A reference to the trust object which has been evaluated. + @param trustResult The trust result of the evaluation. Additional status + information can be obtained by calling SecTrustCopyProperties(). + */ +typedef void (^SecTrustCallback)(SecTrustRef trustRef, SecTrustResultType trustResult); +#endif /* __BLOCKS__ */ + + +/*! + @function SecTrustGetTypeID + @abstract Returns the type identifier of SecTrust instances. + @result The CFTypeID of SecTrust instances. + */ +CFTypeID SecTrustGetTypeID(void) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +/*! + @function SecTrustCreateWithCertificates + @abstract Creates a trust object based on the given certificates and + policies. + @param certificates The group of certificates to verify. This can either + be a CFArrayRef of SecCertificateRef objects or a single SecCertificateRef + @param policies An array of one or more policies. You may pass a + SecPolicyRef to represent a single policy. + @param trust On return, a pointer to the trust management reference. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion If multiple policies are passed in, all policies must verify + for the chain to be considered valid. + */ +OSStatus SecTrustCreateWithCertificates(CFTypeRef certificates, + CFTypeRef policies, SecTrustRef *trust) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +/*! + @function SecTrustSetPolicies + @abstract Set the policies for which trust should be verified. + @param trust A trust reference. + @param policies An array of one or more policies. You may pass a + SecPolicyRef to represent a single policy. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function will invalidate the existing trust result, + requiring a fresh evaluation for the newly-set policies. + */ +OSStatus SecTrustSetPolicies(SecTrustRef trust, CFTypeRef policies) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_6_0); + +/*! + @function SecTrustCopyPolicies + @abstract Returns an array of policies used for this evaluation. + @param trust A reference to a trust object. + @param policies On return, an array of policies used by this trust. + Call the CFRelease function to release this reference. + @result A result code. See "Security Error Codes" (SecBase.h). + */ +OSStatus SecTrustCopyPolicies(SecTrustRef trust, CFArrayRef *policies) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_7_0); + +/*! + @function SecTrustSetNetworkFetchAllowed + @abstract Specifies whether a trust evaluation is permitted to fetch missing + intermediate certificates from the network. + @param trust A trust reference. + @param allowFetch If true, and a certificate's issuer is not present in the + trust reference but its network location is known, the evaluation is permitted + to attempt to download it automatically. Pass false to disable network fetch + for this trust evaluation. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion By default, network fetch of missing certificates is enabled if + the trust evaluation includes the SSL policy, otherwise it is disabled. + */ +OSStatus SecTrustSetNetworkFetchAllowed(SecTrustRef trust, + Boolean allowFetch) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + +/*! + @function SecTrustGetNetworkFetchAllowed + @abstract Returns whether a trust evaluation is permitted to fetch missing + intermediate certificates from the network. + @param trust A trust reference. + @param allowFetch On return, the boolean pointed to by this parameter is + set to true if the evaluation is permitted to download missing certificates. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion By default, network fetch of missing certificates is enabled if + the trust evaluation includes the SSL policy, otherwise it is disabled. + */ +OSStatus SecTrustGetNetworkFetchAllowed(SecTrustRef trust, + Boolean *allowFetch) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + +/*! + @function SecTrustSetAnchorCertificates + @abstract Sets the anchor certificates for a given trust. + @param trust A reference to a trust object. + @param anchorCertificates An array of anchor certificates. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Calling this function without also calling + SecTrustSetAnchorCertificatesOnly() will disable trusting any + anchors other than the ones in anchorCertificates. + */ +OSStatus SecTrustSetAnchorCertificates(SecTrustRef trust, + CFArrayRef anchorCertificates) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +/*! + @function SecTrustSetAnchorCertificatesOnly + @abstract Reenables trusting anchor certificates in addition to those + passed in via the SecTrustSetAnchorCertificates API. + @param trust A reference to a trust object. + @param anchorCertificatesOnly If true, disables trusting any anchors other + than the ones passed in via SecTrustSetAnchorCertificates(). If false, + the built in anchor certificates are also trusted. + @result A result code. See "Security Error Codes" (SecBase.h). + */ +OSStatus SecTrustSetAnchorCertificatesOnly(SecTrustRef trust, + Boolean anchorCertificatesOnly) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @function SecTrustCopyCustomAnchorCertificates + @abstract Returns an array of custom anchor certificates used by a given + trust, as set by a prior call to SecTrustSetAnchorCertificates, or NULL if + no custom anchors have been specified. + @param trust A reference to a trust object. + @param anchors On return, an array of custom anchor certificates (roots) + used by this trust, or NULL if no custom anchors have been specified. Call + the CFRelease function to release this reference. + @result A result code. See "Security Error Codes" (SecBase.h). + */ +OSStatus SecTrustCopyCustomAnchorCertificates(SecTrustRef trust, + CFArrayRef *anchors) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_7_0); + +/*! + @function SecTrustSetVerifyDate + @abstract Set the date for which the trust should be verified. + @param trust A reference to a trust object. + @param verifyDate The date for which to verify trust. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function lets you evaluate certificate validity for a + given date (for example, to determine if a signature was valid on the date + it was signed, even if the certificate has since expired.) If this function + is not called, the time at which SecTrustEvaluate() is called is used + implicitly as the verification time. + */ +OSStatus SecTrustSetVerifyDate(SecTrustRef trust, CFDateRef verifyDate) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +/*! + @function SecTrustGetVerifyTime + @abstract Returns the verify time. + @param trust A reference to the trust object being verified. + @result A CFAbsoluteTime value representing the time at which certificates + should be checked for validity. + @discussion This function retrieves the verification time for the given + trust reference, as set by a prior call to SecTrustSetVerifyDate(). If the + verification time has not been set, this function returns a value of 0, + indicating that the current date/time is implicitly used for verification. + */ +CFAbsoluteTime SecTrustGetVerifyTime(SecTrustRef trust) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @function SecTrustEvaluate + @abstract Evaluates a trust reference synchronously. + @param trust A reference to the trust object to evaluate. + @param result A pointer to a result type. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function will completely evaluate trust before returning, + possibly including network access to fetch intermediate certificates or to + perform revocation checking. Since this function can block during those + operations, you should call it from within a function that is placed on a + dispatch queue, or in a separate thread from your application's main + run loop. Alternatively, you can use the SecTrustEvaluateAsync function. + */ +OSStatus SecTrustEvaluate(SecTrustRef trust, SecTrustResultType *result) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +#ifdef __BLOCKS__ +/*! + @function SecTrustEvaluateAsync + @abstract Evaluates a trust reference asynchronously. + @param trust A reference to the trust object to evaluate. + @param queue A dispatch queue on which the result callback should be + executed. Pass NULL to use the current dispatch queue. + @param result A SecTrustCallback block which will be executed when the + trust evaluation is complete. + @result A result code. See "Security Error Codes" (SecBase.h). + */ +OSStatus SecTrustEvaluateAsync(SecTrustRef trust, + dispatch_queue_t queue, SecTrustCallback result) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +#endif + +/*! + @function SecTrustGetTrustResult + @param trust A reference to a trust object. + @param result A pointer to the result from the most recent call to + SecTrustEvaluate for this trust reference. If SecTrustEvaluate has not been + called or trust parameters have changed, the result is kSecTrustResultInvalid. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function replaces SecTrustGetResult for the purpose of + obtaining the current evaluation result of a given trust reference. + */ +OSStatus SecTrustGetTrustResult(SecTrustRef trust, + SecTrustResultType *result) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); + +/*! + @function SecTrustCopyPublicKey + @abstract Return the public key for a leaf certificate after it has + been evaluated. + @param trust A reference to the trust object which has been evaluated. + @result The certificate's public key, or NULL if it the public key could + not be extracted (this can happen with DSA certificate chains if the + parameters in the chain cannot be found). The caller is responsible + for calling CFRelease on the returned key when it is no longer needed. + */ +SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + +/*! + @function SecTrustGetCertificateCount + @abstract Returns the number of certificates in an evaluated certificate + chain. + @param trust A reference to a trust object. + @result The number of certificates in the trust chain, including the anchor. + @discussion Important: if the trust reference has not yet been evaluated, + this function will evaluate it first before returning. If speed is critical, + you may want to call SecTrustGetTrustResult first to make sure that a + result other than kSecTrustResultInvalid is present for the trust object. + */ +CFIndex SecTrustGetCertificateCount(SecTrustRef trust) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + +/*! + @function SecTrustGetCertificateAtIndex + @abstract Returns a certificate from the trust chain. + @param trust Reference to a trust object. + @param ix The index of the requested certificate. Indices run from 0 + (leaf) to the anchor (or last certificate found if no anchor was found). + The leaf cert (index 0) is always present regardless of whether the trust + reference has been evaluated or not. + @result A SecCertificateRef for the requested certificate. + */ +SecCertificateRef SecTrustGetCertificateAtIndex(SecTrustRef trust, CFIndex ix) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + +/*! + @function SecTrustCopyExceptions + @abstract Returns an opaque cookie which will allow future evaluations + of the current certificate to succeed. + @param trust A reference to an evaluated trust object. + @result An opaque cookie which when passed to SecTrustSetExceptions() will + cause a call to SecTrustEvaluate() return kSecTrustResultProceed. This + will happen upon subsequent evaluation of the current certificate unless + some new error starts happening that wasn't being reported when the cookie + was returned from this function (for example, if the certificate expires + then evaluation will start failing again until a new cookie is obtained.) + @discussion Normally this API should only be called once the errors have + been presented to the user and the user decided to trust the current + certificate chain regardless of the errors being presented, for the + current application/server/protocol combination. + */ +CFDataRef SecTrustCopyExceptions(SecTrustRef trust) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); + +/*! + @function SecTrustSetExceptions + @abstract Set a trust cookie to be used for evaluating this certificate chain. + @param trust A reference to a trust object. + @param exceptions An exceptions cookie as returned by a call to + SecTrustCopyExceptions() in the past. + @result Upon calling SecTrustEvaluate(), any failures that where present at the + time the exceptions object was created are ignored, and instead of returning + kSecTrustResultRecoverableTrustFailure, kSecTrustResultProceed will be returned + (if the certificate for which exceptions was created matches the current leaf + certificate). + @result Returns true if the exceptions cookies was valid and matches the current + leaf certificate, false otherwise. This function will invalidate the existing + trust result, requiring a subsequent evaluation for the newly-set exceptions. + Note that this function returning true doesn't mean the caller can skip calling + SecTrustEvaluate, as there may be new errors since the exceptions cookie was + created (for example, a certificate may have subsequently expired.) + @discussion Clients of this interface will need to establish the context of this + exception to later decide when this exception cookie is to be used. + Examples of this context would be the server we are connecting to, the ssid + of the wireless network for which this cert is needed, the account for which + this cert should be considered valid, and so on. + */ +bool SecTrustSetExceptions(SecTrustRef trust, CFDataRef exceptions) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); + +/*! + @function SecTrustCopyProperties + @abstract Return a property array for this trust evaluation. + @param trust A reference to a trust object. If the trust has not been + evaluated, the returned property array will be empty. + @result A property array. It is the caller's responsibility to CFRelease + the returned array when it is no longer needed. + @discussion This function returns an ordered array of CFDictionaryRef + instances for each certificate in the chain. Indices run from 0 (leaf) to + the anchor (or last certificate found if no anchor was found.) See the + "Trust Property Constants" section for a list of currently defined keys. + */ +CFArrayRef SecTrustCopyProperties(SecTrustRef trust) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + +/*! + @function SecTrustCopyResult + @abstract Returns a dictionary containing information about the + evaluated certificate chain for use by clients. + @param trust A reference to a trust object. + @result A dictionary with various fields that can be displayed to the user, + or NULL if no additional info is available or the trust has not yet been + validated. The caller is responsible for calling CFRelease on the value + returned when it is no longer needed. + @discussion Returns a dictionary for the overall trust evaluation. See the + "Trust Result Constants" section for a list of currently defined keys. + */ +CFDictionaryRef SecTrustCopyResult(SecTrustRef trust) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + +/*! + @function SecTrustSetOCSPResponse + @abstract Attach OCSPResponse data to a trust object. + @param trust A reference to a trust object. + @param responseData This may be either a CFData object containing a single + DER-encoded OCSPResponse (per RFC 2560), or a CFArray of these. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Allows the caller to provide OCSPResponse data (which may be + obtained during a TLS/SSL handshake, per RFC 3546) as input to a trust + evaluation. If this data is available, it can obviate the need to contact + an OCSP server for current revocation information. + */ +OSStatus SecTrustSetOCSPResponse(SecTrustRef trust, CFTypeRef responseData) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + + +/* + * Legacy functions (OS X only) + */ +#if TARGET_OS_MAC && !TARGET_OS_IPHONE +#include +#include + +/*! + @typedef SecTrustUserSetting + @abstract Specifies a user-specified trust setting value. + @discussion Deprecated in OS X 10.9. User trust settings are managed by + functions in SecTrustSettings.h (starting with OS X 10.5), and by the + SecTrustCopyExceptions and SecTrustSetExceptions functions (starting with + iOS 4 and OS X 10.9). The latter two functions are recommended for both OS X + and iOS, as they avoid the need to explicitly specify these values. + */ +typedef SecTrustResultType SecTrustUserSetting + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); + +/*! + @typedef SecTrustOptionFlags + @abstract Options for customizing trust evaluation. + @constant kSecTrustOptionAllowExpired Allow expired certificates. + @constant kSecTrustOptionLeafIsCA Allow CA as leaf certificate. + @constant kSecTrustOptionFetchIssuerFromNet Allow network fetch of CA cert. + @constant kSecTrustOptionAllowExpiredRoot Allow expired roots. + @constant kSecTrustOptionRequireRevPerCert Require positive revocation + check per certificate. + @constant kSecTrustOptionUseTrustSettings Use TrustSettings instead of + anchors. + @constant kSecTrustOptionImplicitAnchors Properly self-signed certs are + treated as anchors implicitly. + */ +typedef uint32_t SecTrustOptionFlags; +enum { + kSecTrustOptionAllowExpired = 0x00000001, + kSecTrustOptionLeafIsCA = 0x00000002, + kSecTrustOptionFetchIssuerFromNet = 0x00000004, + kSecTrustOptionAllowExpiredRoot = 0x00000008, + kSecTrustOptionRequireRevPerCert = 0x00000010, + kSecTrustOptionUseTrustSettings = 0x00000020, + kSecTrustOptionImplicitAnchors = 0x00000040 +}; + +/*! + @function SecTrustSetOptions + @abstract Sets optional flags for customizing a trust evaluation. + @param trustRef A trust reference. + @param options Flags to change evaluation behavior for this trust. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is not available on iOS. Use SecTrustSetExceptions + and SecTrustCopyExceptions to modify default trust results, and + SecTrustSetNetworkFetchAllowed to specify whether missing CA certificates + can be fetched from the network. + */ +OSStatus SecTrustSetOptions(SecTrustRef trustRef, SecTrustOptionFlags options) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @function SecTrustSetParameters + @abstract Sets the action and action data for a trust object. + @param trustRef The reference to the trust to change. + @param action A trust action. + @param actionData A reference to data associated with this action. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in OS X 10.7 and later, where it + was replaced by SecTrustSetOptions, and is not available on iOS. Your code + should use SecTrustSetExceptions and SecTrustCopyExceptions to modify default + trust results, and SecTrustSetNetworkFetchAllowed to specify whether missing + CA certificates can be fetched from the network. + */ +OSStatus SecTrustSetParameters(SecTrustRef trustRef, + CSSM_TP_ACTION action, CFDataRef actionData) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecTrustSetKeychains + @abstract Sets the keychains for a given trust object. + @param trust A reference to a trust object. + @param keychainOrArray A reference to an array of keychains to search, a + single keychain, or NULL to use the default keychain search list. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion By default, the user's keychain search list and the system + anchors keychain are searched for certificates to complete the chain. You + can specify a zero-element array if you do not want any keychains searched. + Note: this function is not applicable to iOS. + */ +OSStatus SecTrustSetKeychains(SecTrustRef trust, CFTypeRef keychainOrArray) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); + +/*! + @function SecTrustGetResult + @abstract Returns detailed information on the outcome of an evaluation. + @param trustRef A reference to a trust object. + @param result A pointer to the result from the call to SecTrustEvaluate. + @param certChain On return, a pointer to the certificate chain used to + validate the input certificate. Call the CFRelease function to release + this pointer. + @param statusChain On return, a pointer to the status of the certificate + chain. Do not attempt to free this pointer; it remains valid until the + trust is destroyed or the next call to SecTrustEvaluate. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in OS X 10.7 and later, + and is not available on iOS. + To get the complete certificate chain, use SecTrustGetCertificateCount and + SecTrustGetCertificateAtIndex. To get detailed status information for each + certificate, use SecTrustCopyProperties. To get the overall trust result + for the evaluation, use SecTrustGetTrustResult. + */ +OSStatus SecTrustGetResult(SecTrustRef trustRef, SecTrustResultType *result, + CFArrayRef *certChain, CSSM_TP_APPLE_EVIDENCE_INFO **statusChain) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecTrustGetCssmResult + @abstract Gets the CSSM trust result. + @param trust A reference to a trust. + @param result On return, a pointer to the CSSM trust result. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in OS X 10.7 and later, + and is not available on iOS. + To get detailed status information for each certificate, use + SecTrustCopyProperties. To get the overall trust result for the evaluation, + use SecTrustGetTrustResult. + */ +OSStatus SecTrustGetCssmResult(SecTrustRef trust, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR *result) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecTrustGetCssmResultCode + @abstract Gets the result code from the most recent call to SecTrustEvaluate + for the specified trust. + @param trust A reference to a trust. + @param resultCode On return, the result code produced by the most recent + evaluation of the given trust (cssmerr.h). The value of resultCode is + undefined if SecTrustEvaluate has not been called. + @result A result code. See "Security Error Codes" (SecBase.h). Returns + errSecTrustNotAvailable if SecTrustEvaluate has not been called for the + specified trust. + @discussion This function is deprecated in OS X 10.7 and later, + and is not available on iOS. + To get detailed status information for each certificate, use + SecTrustCopyProperties. To get the overall trust result for the evaluation, + use SecTrustGetTrustResult. + */ +OSStatus SecTrustGetCssmResultCode(SecTrustRef trust, OSStatus *resultCode) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecTrustGetTPHandle + @abstract Gets the CSSM trust handle + @param trust A reference to a trust. + @param handle On return, a CSSM trust handle. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in OS X 10.7 and later. + */ +OSStatus SecTrustGetTPHandle(SecTrustRef trust, CSSM_TP_HANDLE *handle) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecTrustCopyAnchorCertificates + @abstract Returns an array of default anchor (root) certificates used by + the system. + @param anchors On return, an array containing the system's default anchors + (roots). Call the CFRelease function to release this pointer. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is not available on iOS, as certificate data + for system-trusted roots is currently unavailable on that platform. + */ +OSStatus SecTrustCopyAnchorCertificates(CFArrayRef *anchors) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); + +#endif /* TARGET_OS_MAC && !TARGET_OS_IPHONE */ + + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECTRUST_H_ */ diff --git a/Security/libsecurity_keychain/lib/SecTrustPriv.h b/Security/libsecurity_keychain/lib/SecTrustPriv.h new file mode 100644 index 00000000..a4ee4e7b --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecTrustPriv.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2003-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@ + */ + +/*! + @header SecTrustPriv + Private part of SecTrust.h +*/ + +#ifndef _SECURITY_SECTRUST_PRIV_H_ +#define _SECURITY_SECTRUST_PRIV_H_ + +#include +#include +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + unique keychain item attributes for user trust records. +*/ +enum { + kSecTrustCertAttr = 'tcrt', + kSecTrustPolicyAttr = 'tpol', + /* Leopard and later */ + kSecTrustPubKeyAttr = 'tpbk', + kSecTrustSignatureAttr = 'tsig' +}; + +/*! + @function SecTrustGetUserTrust + @abstract Gets the user-specified trust settings of a certificate and policy. + @param certificate A reference to a certificate. + @param policy A reference to a policy. + @param trustSetting On return, a pointer to the user specified trust settings. + @result A result code. See "Security Error Codes" (SecBase.h). + @availability Mac OS X version 10.4. Deprecated in Mac OS X version 10.5. +*/ +OSStatus SecTrustGetUserTrust(SecCertificateRef certificate, SecPolicyRef policy, SecTrustUserSetting *trustSetting) + /*DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER*/; + +/*! + @function SecTrustSetUserTrust + @abstract Sets the user-specified trust settings of a certificate and policy. + @param certificate A reference to a certificate. + @param policy A reference to a policy. + @param trustSetting The user-specified trust settings. + @result A result code. See "Security Error Codes" (SecBase.h). + @availability Mac OS X version 10.4. Deprecated in Mac OS X version 10.5. + @discussion as of Mac OS version 10.5, this will result in a call to + SecTrustSettingsSetTrustSettings(). +*/ +OSStatus SecTrustSetUserTrust(SecCertificateRef certificate, SecPolicyRef policy, SecTrustUserSetting trustSetting) + /*DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER*/; + +/*! + @function SecTrustSetUserTrustLegacy + @abstract Sets the user-specified trust settings of a certificate and policy. + @param certificate A reference to a certificate. + @param policy A reference to a policy. + @param trustSetting The user-specified trust settings. + @result A result code. See "Security Error Codes" (SecBase.h). + + @This is the private version of what used to be SecTrustSetUserTrust(); it operates + on UserTrust entries as that function used to. The current SecTrustSetUserTrust() + function operated on Trust Settings. +*/ +OSStatus SecTrustSetUserTrustLegacy(SecCertificateRef certificate, SecPolicyRef policy, SecTrustUserSetting trustSetting); + +/*! + @function SecTrustGetCSSMAnchorCertificates + @abstract Retrieves the CSSM anchor certificates. + @param cssmAnchors A pointer to an array of anchor certificates. + @param cssmAnchorCount A pointer to the number of certificates in anchors. + @result A result code. See "Security Error Codes" (SecBase.h). + @availability Mac OS X version 10.4. Deprecated in Mac OS X version 10.5. +*/ +OSStatus SecTrustGetCSSMAnchorCertificates(const CSSM_DATA **cssmAnchors, uint32 *cssmAnchorCount) + /*DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER*/; + +/*! + @function SecTrustCopyExtendedResult + @abstract Gets the extended trust result after an evaluation has been performed. + @param trust A trust reference. + @param result On return, result points to a CFDictionaryRef containing extended trust results (if no error occurred). + The caller is responsible for releasing this dictionary with CFRelease when finished with it. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function may only be used after SecTrustEvaluate has been called for the trust reference, otherwise + errSecTrustNotAvailable is returned. If the certificate is not an extended validation certificate, there is + no extended result data and errSecDataNotAvailable is returned. Currently, only one dictionary key is defined + (kSecEVOrganizationName). + + Note: this function will be deprecated in a future release of OS X. Your + code should use SecTrustCopyResult to obtain the trust results dictionary. +*/ +OSStatus SecTrustCopyExtendedResult(SecTrustRef trust, CFDictionaryRef *result) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); + + +/*! + @enum Trust Result Constants + @discussion Predefined key constants used to obtain values in a + dictionary of trust evaluation results for a certificate chain, + as retrieved from a call to SecTrustCopyResult. + + @constant kSecTrustResultDetails + This key will be present if a trust evaluation has been performed. + Its value is a CFArrayRef of CFDictionaryRef representing detailed + status info for each certificate in the completed chain. + */ +extern CFTypeRef kSecTrustResultDetails + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_NA); + + +/* + * Preference-related strings for Revocation policies. + */ + +/* + * Preference domain, i.e., the name of a plist in ~/Library/Preferences or in + * /Library/Preferences + */ +#define kSecRevocationDomain "com.apple.security.revocation" + +/* OCSP and CRL style keys, followed by values used for both of them */ +#define kSecRevocationOcspStyle CFSTR("OCSPStyle") +#define kSecRevocationCrlStyle CFSTR("CRLStyle") + #define kSecRevocationOff CFSTR("None") /* default for each one */ + #define kSecRevocationBestAttempt CFSTR("BestAttempt") + #define kSecRevocationRequireIfPresent CFSTR("RequireIfPresent") + #define kSecRevocationRequireForAll CFSTR("RequireForAll") + +/* Which first if both enabled? */ +#define kSecRevocationWhichFirst CFSTR("RevocationFirst") + #define kSecRevocationOcspFirst CFSTR("OCSP") + #define kSecRevocationCrlFirst CFSTR("CRL") + +/* boolean: A "this policy is sufficient per cert" for each */ +#define kSecRevocationOCSPSufficientPerCert CFSTR("OCSPSufficientPerCert") +#define kSecRevocationCRLSufficientPerCert CFSTR("CRLSufficientPerCert") + +/* local OCSP responder URI, value arbitrary string value */ +#define kSecOCSPLocalResponder CFSTR("OCSPLocalResponder") + +/* Extended trust result keys (now in public API) */ +#define kSecEVOrganizationName kSecTrustOrganizationName +#define kSecTrustExpirationDate kSecTrustRevocationValidUntilDate + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECTRUST_PRIV_H_ */ diff --git a/libsecurity_keychain/lib/SecTrustSettings.cpp b/Security/libsecurity_keychain/lib/SecTrustSettings.cpp similarity index 97% rename from libsecurity_keychain/lib/SecTrustSettings.cpp rename to Security/libsecurity_keychain/lib/SecTrustSettings.cpp index 15dedbea..ed7485ad 100644 --- a/libsecurity_keychain/lib/SecTrustSettings.cpp +++ b/Security/libsecurity_keychain/lib/SecTrustSettings.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2005,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -24,7 +24,6 @@ /* * SecTrustSettings.cpp - Public interface for manipulation of Trust Settings. * - * Created May 10 2005 by dmitch. */ #include "SecBridge.h" @@ -194,11 +193,19 @@ static TrustSettings *tsGetGlobalTrustSettings( TrustSettings *ts = NULL; /* don't create; trim if found */ result = TrustSettings::CreateTrustSettings(domain, CREATE_NO, TRIM_YES, ts); - if(result != errSecSuccess && result != errSecNoTrustSettings) { - /* gross error */ - MacOSError::throwMe(result); - } - else if (result != errSecSuccess) { + if ( (domain != kSecTrustSettingsDomainSystem) + && (result == errSecInternalComponent)) { + /* + * Could not connect to ocspd to get the user/admin domain trust settings + * This happens in single user mode for example. + * Valid flag is set to false and continue. + */ + trustSettingsDbg("tsGetGlobalTrustSettings: could not connect to ocspd for domain (%d)",(int)domain); + globalTrustSettingsValid[domain] = false; + tsRegisterCallback(); + return NULL; + } + else if (result == errSecNoTrustSettings) { /* * No TrustSettings for this domain, actually a fairly common case. * Optimize: don't bother trying this again. @@ -208,6 +215,10 @@ static TrustSettings *tsGetGlobalTrustSettings( tsRegisterCallback(); return NULL; } + else if(result != errSecSuccess) { + /* gross error */ + MacOSError::throwMe(result); + } tsSetGlobalTrustSettings(ts, domain); return ts; diff --git a/Security/libsecurity_keychain/lib/SecTrustSettings.h b/Security/libsecurity_keychain/lib/SecTrustSettings.h new file mode 100644 index 00000000..d5fc9fdf --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecTrustSettings.h @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * SecTrustSettings.h - Public interface for manipulation of certificate + * Trust Settings. + */ + +#ifndef _SECURITY_SEC_TRUST_SETTINGS_H_ +#define _SECURITY_SEC_TRUST_SETTINGS_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Any certificate (cert) which resides in a keychain can have associated with + * it a set of Trust Settings. Trust Settings specify conditions in which a + * given cert can be trusted or explicitly distrusted. A "trusted" cert is + * either a root (self-signed) cert that, when a cert chain verifies back to that + * root, the entire cert chain is trusted; or a non-root cert that does not need + * to verify to a trusted root cert (which is normally the case when verifying a + * cert chain). An "explicitly distrusted" cert is one which will, when encountered + * during the evaluation of a cert chain, cause immediate and unconditional failure + * of the verify operation. + * + * Trust Settings are configurable by the user; they can apply on three levels + * (called domains): + * + * -- Per-user. + * -- Locally administered, system-wide. Administrator privileges are required + * to make changes to this domain. + * -- System. These Trust Settings are immutable and comprise the set of trusted + * root certificates supplied in Mac OS X. + * + * Per-user Trust Settings override locally administered Trust Settings, which + * in turn override the System Trust Settings. + * + * Each cert's Trust Settings are expressed as a CFArray which includes any + * number (including zero) of CFDictionaries, each of which comprises one set of + * Usage Constraints. Each Usage Constraints dictionary contains zero or one of + * each the following components: + * + * key = kSecTrustSettingsPolicy value = SecPolicyRef + * key = kSecTrustSettingsApplication value = SecTrustedApplicationRef + * key = kSecTrustSettingsPolicyString value = CFString, policy-specific + * key = kSecTrustSettingsKeyUsage value = CFNumber, an SInt32 key usage + * + * A given Usage Constraints dictionary applies to a given cert if *all* of the + * usage constraint components specified in the dictionary match the usage of + * the cert being evaluated; when this occurs, the value of the + * kSecTrustSettingsResult entry in the dictionary, shown below, is the effective + * trust setting for the cert. + * + * key = kSecTrustSettingsResult value = CFNumber, an SInt32 SecTrustSettingsResult + * + * The overall Trust Settings of a given cert are the sum of all such Usage + * Constraints CFDictionaries: Trust Settings for a given usage apply if *any* + * of the CFDictionaries in the cert's Trust Settings array satisfies + * the specified usage. Thus, when a cert has multiple Usage Constraints + * dictionaries in its Trust Settings array, the overall Trust Settings + * for the cert are + * + * (Usage Constraint 0 component 0 AND Usage Constraint 0 component 1 ...) + * -- OR -- + * (Usage Constraint 1 component 0 AND Usage Constraint 1 component 1 ...) + * -- OR -- + * ... + * + * Notes on the various Usage Constraints components: + * + * kSecTrustSettingsPolicy Specifies a cert verification policy, e.g., SSL, + * SMIME, etc. + * kSecTrustSettingsApplication Specifies the application performing the cert + * verification. + * kSecTrustSettingsPolicyString Policy-specific. For the SMIME policy, this is + * an email address. + * For the SSL policy, this is a host name. + * kSecTrustSettingsKeyUsage A bitfield indicating key operations (sign, + * encrypt, etc.) for which this Usage Constraint + * apply. Values are defined below as the + * SecTrustSettingsKeyUsage enum. + * kSecTrustSettingsResult The resulting trust value. If not present this has a + * default of kSecTrustSettingsResultTrustRoot, meaning + * "trust this root cert". Other legal values are: + * kSecTrustSettingsResultTrustAsRoot : trust non-root + * cert as if it were a trusted root. + * kSecTrustSettingsResultDeny : explicitly distrust this + * cert. + * kSecTrustSettingsResultUnspecified : neither trust nor + * distrust; can be used to specify an "Allowed error" + * (see below) without assigning trust to a specific + * cert. + * + * Another optional component in a Usage Constraints dictionary is a CSSM_RETURN + * which, if encountered during certificate verification, is ignored for that + * cert. These "allowed error" values are constrained by Usage Constraints as + * described above; a Usage Constraint dictionary with no constraints but with + * an Allowed Error value causes that error to always be allowed when the cert + * is being evaluated. + * + * The "allowed error" entry in a Usage Constraints dictionary is formatted + * as follows: + * + * key = kSecTrustSettingsAllowedError value = CFNumber, an SInt32 CSSM_RETURN + * + * Note that if kSecTrustSettingsResult value of kSecTrustSettingsResultUnspecified + * is *not* present for a Usage Constraints dictionary with no Usage + * Constraints, the default of kSecTrustSettingsResultTrustRoot is assumed. To + * specify a kSecTrustSettingsAllowedError without explicitly trusting (or + * distrusting) the associated cert, specify kSecTrustSettingsResultUnspecified + * for the kSecTrustSettingsResult component. + * + * Note that an empty Trust Settings array means "always trust this cert, + * with a resulting kSecTrustSettingsResult of kSecTrustSettingsResultTrustRoot". + * An empty Trust Settings array is definitely not the same as *no* Trust + * Settings, which means "this cert must be verified to a known trusted cert". + * + * Note the distinction between kSecTrustSettingsResultTrustRoot and + * kSecTrustSettingsResultTrustAsRoot; the former can only be applied to + * root (self-signed) certs; the latter can only be applied to non-root + * certs. This also means that an empty TrustSettings array for a non-root + * cert is invalid, since the default value for kSecTrustSettingsResult is + * kSecTrustSettingsResultTrustRoot, which is invalid for a non-root cert. + * + * Authentication + * -------------- + * + * When making changes to the per-user Trust Settings, the user will be + * prompted with an alert panel asking for authentication via user name a + * password (or other credentials normally used for login). This means + * that it is not possible to modify per-user Trust Settings when not + * running in a GUI environment (i.e. the user is not logged in via + * Loginwindow). + * + * When making changes to the system-wide Trust Settings, the user will be + * prompted with an alert panel asking for an administrator's name and + * password, unless the calling process is running as root in which case + * no futher authentication is needed. + */ + +/* + * The keys in one Usage Constraints dictionary. + */ +#define kSecTrustSettingsPolicy CFSTR("kSecTrustSettingsPolicy") +#define kSecTrustSettingsApplication CFSTR("kSecTrustSettingsApplication") +#define kSecTrustSettingsPolicyString CFSTR("kSecTrustSettingsPolicyString") +#define kSecTrustSettingsKeyUsage CFSTR("kSecTrustSettingsKeyUsage") +#define kSecTrustSettingsAllowedError CFSTR("kSecTrustSettingsAllowedError") +#define kSecTrustSettingsResult CFSTR("kSecTrustSettingsResult") + +/* + * Key usage bits, the value for Usage Constraints key kSecTrustSettingsKeyUsage. + */ +enum { + /* sign/verify data */ + kSecTrustSettingsKeyUseSignature = 0x00000001, + /* bulk encryption */ + kSecTrustSettingsKeyUseEnDecryptData = 0x00000002, + /* key wrap/unwrap */ + kSecTrustSettingsKeyUseEnDecryptKey = 0x00000004, + /* sign/verify cert */ + kSecTrustSettingsKeyUseSignCert = 0x00000008, + /* sign/verify CRL and OCSP */ + kSecTrustSettingsKeyUseSignRevocation = 0x00000010, + /* key exchange, e.g., Diffie-Hellman */ + kSecTrustSettingsKeyUseKeyExchange = 0x00000020, + /* any usage (the default if this value is not specified) */ + kSecTrustSettingsKeyUseAny = 0xffffffff +}; +typedef uint32 SecTrustSettingsKeyUsage; + +/* + * The effective Trust Setting result. + */ +enum { + kSecTrustSettingsResultInvalid = 0, /* Never valid in a Trust Settings array or + * in an API call. */ + kSecTrustSettingsResultTrustRoot, /* Root cert is explicitly trusted */ + kSecTrustSettingsResultTrustAsRoot, /* Non-root cert is explicitly trusted */ + kSecTrustSettingsResultDeny, /* Cert is explicitly distrusted */ + kSecTrustSettingsResultUnspecified /* Neither trusted nor distrusted; evaluation + * proceeds as usual */ +}; +typedef uint32 SecTrustSettingsResult; + +/* + * Specify user, local administrator, or system domain Trust Settings. + * Note that kSecTrustSettingsDomainSystem settings are read-only, even by + * root. + */ +enum { + kSecTrustSettingsDomainUser = 0, + kSecTrustSettingsDomainAdmin, + kSecTrustSettingsDomainSystem +}; +typedef uint32 SecTrustSettingsDomain; + +/* + * SecCertificateRef value indicating the default Root Certificate Trust Settings + * for a given domain. When evaluating Trust Settings for a root cert in + * a given domain, *and* no matching explicit Trust Settings exists for the + * root cert in questions, *and* default Root Cert Trust Settings exist + * in that domain which matches the evaluation condition, then the + * SecTrustSettingsResult for that default Trust Setting (if not + * kSecTrustSettingsResultUnspecified) will apply. + * + * This can be used e.g. by a system administrator to explicilty distrust all + * of the root certs in the (immutable) system domain for a specific policy. + * + * This const is passed as the 'SecCertificateRef certRef' argument to + * SecTrustSettingsCopyTrustSettings(), SecTrustSettingsSetTrustSettings(), + * and SecTrustSettingsRemoveTrustSettings(), and + * SecTrustSettingsCopyModificationDate(). + */ +#define kSecTrustSettingsDefaultRootCertSetting ((SecCertificateRef)-1) + +/* + * Obtain Trust Settings for specified cert. + * Caller must CFRelease() the returned CFArray. + * Returns errSecItemNotFound if no Trust settings exist for the cert. + */ +OSStatus SecTrustSettingsCopyTrustSettings( + SecCertificateRef certRef, + SecTrustSettingsDomain domain, + CFArrayRef *trustSettings); /* RETURNED */ + +/* + * Specify Trust Settings for specified cert. If specified cert + * already has Trust Settings in the specified domain, they will + * be replaced. + * The trustSettingsDictOrArray parameter is either a CFDictionary, + * a CFArray of them, or NULL. NULL indicates "always trust this + * root cert regardless of usage". + */ +OSStatus SecTrustSettingsSetTrustSettings( + SecCertificateRef certRef, + SecTrustSettingsDomain domain, + CFTypeRef trustSettingsDictOrArray); + +/* + * Delete Trust Settings for specified cert. + * Returns errSecItemNotFound if no Trust settings exist for the cert. + */ +OSStatus SecTrustSettingsRemoveTrustSettings( + SecCertificateRef certRef, + SecTrustSettingsDomain domain); + +/* + * Obtain an array of all certs which have Trust Settings in the + * specified domain. Elements in the returned certArray are + * SecCertificateRefs. + * Caller must CFRelease() the returned array. + * Returns errSecNoTrustSettings if no trust settings exist + * for the specified domain. + */ +OSStatus SecTrustSettingsCopyCertificates( + SecTrustSettingsDomain domain, + CFArrayRef *certArray); + +/* + * Obtain the time at which a specified cert's Trust Settings + * were last modified. Caller must CFRelease the result. + * Returns errSecItemNotFound if no Trust Settings exist for specified + * cert and domain. + */ +OSStatus SecTrustSettingsCopyModificationDate( + SecCertificateRef certRef, + SecTrustSettingsDomain domain, + CFDateRef *modificationDate); /* RETURNED */ + +/* + * Obtain an external, portable representation of the specified + * domain's TrustSettings. Caller must CFRelease the returned data. + * Returns errSecNoTrustSettings if no trust settings exist + * for the specified domain. + */ +OSStatus SecTrustSettingsCreateExternalRepresentation( + SecTrustSettingsDomain domain, + CFDataRef *trustSettings); + +/* + * Import trust settings, obtained via SecTrustSettingsCreateExternalRepresentation, + * into the specified domain. + */ +OSStatus SecTrustSettingsImportExternalRepresentation( + SecTrustSettingsDomain domain, + CFDataRef trustSettings); + +#ifdef __cplusplus +} +#endif + +#endif /* _SECURITY_SEC_TRUST_SETTINGS_H_ */ + diff --git a/Security/libsecurity_keychain/lib/SecTrustSettingsPriv.h b/Security/libsecurity_keychain/lib/SecTrustSettingsPriv.h new file mode 100644 index 00000000..af8a1aec --- /dev/null +++ b/Security/libsecurity_keychain/lib/SecTrustSettingsPriv.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * SecTrustSettingsPriv.h - TrustSettings SPI functions. + */ + +#ifndef _SEC_TRUST_SETTINGS_PRIV_H_ +#define _SEC_TRUST_SETTINGS_PRIV_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Fundamental routine used by TP to ascertain status of one cert. + * + * Returns true in *foundMatchingEntry if a trust setting matching + * specific constraints was found for the cert. Returns true in + * *foundAnyEntry if any entry was found for the cert, even if it + * did not match the specified constraints. The TP uses this to + * optimize for the case where a cert is being evaluated for + * one type of usage, and then later for another type. If + * foundAnyEntry is false, the second evaluation need not occur. + * + * Returns the domain in which a setting was found in *foundDomain. + * + * Allowed errors applying to the specified cert evaluation + * are returned in a mallocd array in *allowedErrors and must + * be freed by caller. + */ +OSStatus SecTrustSettingsEvaluateCert( + CFStringRef certHashStr, + /* parameters describing the current cert evalaution */ + const CSSM_OID *policyOID, + const char *policyString, /* optional */ + uint32 policyStringLen, + SecTrustSettingsKeyUsage keyUsage, /* optional */ + bool isRootCert, /* for checking default setting */ + /* RETURNED values */ + SecTrustSettingsDomain *foundDomain, + CSSM_RETURN **allowedErrors, /* mallocd and RETURNED */ + uint32 *numAllowedErrors, /* RETURNED */ + SecTrustSettingsResult *resultType, /* RETURNED */ + bool *foundMatchingEntry,/* RETURNED */ + bool *foundAnyEntry); /* RETURNED */ + +/* + * Obtain trusted certs which match specified usage. + * Only certs with a SecTrustSettingsResult of + * kSecTrustSettingsResultTrustRoot or + * or kSecTrustSettingsResultTrustAsRoot will be returned. + * + * To be used by SecureTransport for its (hopefully soon-to-be- + * deprecated) SSLSetTrustedRoots() call; I hope nothing else has + * to use this... + * + * Caller must CFRelease the returned CFArrayRef. + */ +OSStatus SecTrustSettingsCopyQualifiedCerts( + const CSSM_OID *policyOID, + const char *policyString, /* optional */ + uint32 policyStringLen, + SecTrustSettingsKeyUsage keyUsage, /* optional */ + CFArrayRef *certArray); /* RETURNED */ + +/* + * Obtain unrestricted root certificates from the specified domain(s). + * Only returns root certificates with no usage constraints. + * Caller must CFRelease the returned CFArrayRef. + */ +OSStatus SecTrustSettingsCopyUnrestrictedRoots( + Boolean userDomain, + Boolean adminDomain, + Boolean systemDomain, + CFArrayRef *certArray); /* RETURNED */ + +/* + * Obtain a string representing a cert's SHA1 digest. This string is + * the key used to look up per-cert trust settings in a TrustSettings record. + */ +CFStringRef SecTrustSettingsCertHashStrFromCert( + SecCertificateRef certRef); + +CFStringRef SecTrustSettingsCertHashStrFromData( + const void *cert, + size_t certLen); + +/* + * Add a cert's TrustSettings to a non-persistent TrustSettings record. + * Primarily intended for use in creating a system TrustSettings record + * (which is itself immutable via this module). + * + * The settingsIn argument is an external representation of a TrustSettings + * record, obtained from this function or from + * SecTrustSettingsCreateExternalRepresentation(). + * If settingsIn is NULL, a new (empty) TrustSettings will be created. + * + * The certRef and trustSettingsDictOrArray arguments are as in + * SecTrustSettingsSetTrustSettings(). May be NULL, when e.g. creating + * a new and empty TrustSettings record. + * + * The external representation is written to the settingOut argument, + * which must eventually be CFReleased by the caller. + */ +OSStatus SecTrustSettingsSetTrustSettingsExternal( + CFDataRef settingsIn, /* optional */ + SecCertificateRef certRef, /* optional */ + CFTypeRef trustSettingsDictOrArray, /* optional */ + CFDataRef *settingsOut); /* RETURNED */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SEC_TRUST_SETTINGS_PRIV_H_ */ + diff --git a/libsecurity_keychain/lib/SecTrustedApplication.cpp b/Security/libsecurity_keychain/lib/SecTrustedApplication.cpp similarity index 97% rename from libsecurity_keychain/lib/SecTrustedApplication.cpp rename to Security/libsecurity_keychain/lib/SecTrustedApplication.cpp index 3b41c457..93839377 100644 --- a/libsecurity_keychain/lib/SecTrustedApplication.cpp +++ b/Security/libsecurity_keychain/lib/SecTrustedApplication.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -30,11 +30,14 @@ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" static inline CssmData cfData(CFDataRef data) { return CssmData(const_cast(CFDataGetBytePtr(data)), CFDataGetLength(data)); } +#pragma clang diagnostic pop CFTypeID diff --git a/libsecurity_keychain/lib/SecTrustedApplication.h b/Security/libsecurity_keychain/lib/SecTrustedApplication.h similarity index 97% rename from libsecurity_keychain/lib/SecTrustedApplication.h rename to Security/libsecurity_keychain/lib/SecTrustedApplication.h index 62a71d0f..478b8779 100644 --- a/libsecurity_keychain/lib/SecTrustedApplication.h +++ b/Security/libsecurity_keychain/lib/SecTrustedApplication.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/SecTrustedApplicationPriv.h b/Security/libsecurity_keychain/lib/SecTrustedApplicationPriv.h similarity index 99% rename from libsecurity_keychain/lib/SecTrustedApplicationPriv.h rename to Security/libsecurity_keychain/lib/SecTrustedApplicationPriv.h index 1cee40cb..9b549a47 100644 --- a/libsecurity_keychain/lib/SecTrustedApplicationPriv.h +++ b/Security/libsecurity_keychain/lib/SecTrustedApplicationPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/SecWrappedKeys.cpp b/Security/libsecurity_keychain/lib/SecWrappedKeys.cpp similarity index 99% rename from libsecurity_keychain/lib/SecWrappedKeys.cpp rename to Security/libsecurity_keychain/lib/SecWrappedKeys.cpp index 8d042310..e42f34c2 100644 --- a/libsecurity_keychain/lib/SecWrappedKeys.cpp +++ b/Security/libsecurity_keychain/lib/SecWrappedKeys.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_keychain/lib/Security.h b/Security/libsecurity_keychain/lib/Security.h new file mode 100644 index 00000000..6f373f89 --- /dev/null +++ b/Security/libsecurity_keychain/lib/Security.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2000-2011,2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* CDSA */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Security */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Code Signing */ +#include +#include +#include +#include +#include + +/* Authorization */ +#include +#include +#include + +/* CMS */ +#include +#include + +/* Secure Transport */ +#include +#include + +#ifdef __BLOCKS__ +#include +#include +#include +#include +#include +#include +#include +#include +#endif + diff --git a/libsecurity_keychain/lib/StorageManager.cpp b/Security/libsecurity_keychain/lib/StorageManager.cpp similarity index 96% rename from libsecurity_keychain/lib/StorageManager.cpp rename to Security/libsecurity_keychain/lib/StorageManager.cpp index 0c46e0c7..f5d16aed 100644 --- a/libsecurity_keychain/lib/StorageManager.cpp +++ b/Security/libsecurity_keychain/lib/StorageManager.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2000-2004,2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -51,6 +51,7 @@ #include #include #include "TrustSettingsSchema.h" +#include //%%% add this to AuthorizationTagsPriv.h later #ifndef AGENT_HINT_LOGIN_KC_SUPPRESS_RESET_PANEL @@ -1322,6 +1323,49 @@ void StorageManager::login(UInt32 nameLength, const void *name, } } + if (!loginUnlocked) { + try { + loginResult = errSecSuccess; + Keychain theKeychain(keychain(loginDLDbIdentifier)); + + // build a fake key + CssmKey key; + key.header().BlobType = CSSM_KEYBLOB_RAW; + key.header().Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; + key.header().AlgorithmId = CSSM_ALGID_3DES_3KEY; + key.header().KeyClass = CSSM_KEYCLASS_SESSION_KEY; + key.header().KeyUsage = CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT | CSSM_KEYATTR_EXTRACTABLE; + key.header().KeyAttr = 0; + key.KeyData = CssmData(const_cast(password), passwordLength); + + // unwrap it into the CSP (but keep it raw) + UnwrapKey unwrap(theKeychain->csp(), CSSM_ALGID_NONE); + CssmKey masterKey; + CssmData descriptiveData; + unwrap(key, + KeySpec(CSSM_KEYUSE_ANY, CSSM_KEYATTR_EXTRACTABLE), + masterKey, &descriptiveData, NULL); + + CssmClient::Db db = theKeychain->database(); + + // create the keychain, using appropriate credentials + Allocator &alloc = db->allocator(); + AutoCredentials cred(alloc); // will leak, but we're quitting soon :-) + + // use this passphrase + cred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, + new(alloc) ListElement(CSSM_SAMPLE_TYPE_SYMMETRIC_KEY), + new(alloc) ListElement(CssmData::wrap(theKeychain->csp()->handle())), + new(alloc) ListElement(CssmData::wrap(masterKey)), + new(alloc) ListElement(CssmData())); + db->authenticate(CSSM_DB_ACCESS_READ, &cred); + db->unlock(); + loginUnlocked = true; + } catch (const CssmError &e) { + loginResult = e.osStatus(); + } + } + // if "shortname.keychain" exists and is in the search list, attempt to auto-unlock it with the same password if (shortnameDotKeychainExists && mSavedList.member(shortnameDotDLDbIdentifier)) { try diff --git a/libsecurity_keychain/lib/StorageManager.h b/Security/libsecurity_keychain/lib/StorageManager.h similarity index 99% rename from libsecurity_keychain/lib/StorageManager.h rename to Security/libsecurity_keychain/lib/StorageManager.h index 1c3bee09..edd02841 100644 --- a/libsecurity_keychain/lib/StorageManager.h +++ b/Security/libsecurity_keychain/lib/StorageManager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/Trust.cpp b/Security/libsecurity_keychain/lib/Trust.cpp similarity index 98% rename from libsecurity_keychain/lib/Trust.cpp rename to Security/libsecurity_keychain/lib/Trust.cpp index 49f23236..1a6f96c2 100644 --- a/libsecurity_keychain/lib/Trust.cpp +++ b/Security/libsecurity_keychain/lib/Trust.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2010,2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -237,9 +237,12 @@ void Trust::evaluate(bool disableEV) clearResults(); // determine whether the leaf certificate is an EV candidate - CFArrayRef allowedAnchors = allowedEVRootsForLeafCertificate(mCerts); + CFArrayRef allowedAnchors = NULL; + if (!disableEV) { + allowedAnchors = allowedEVRootsForLeafCertificate(mCerts); + isEVCandidate = (allowedAnchors != NULL); + } CFArrayRef filteredCerts = NULL; - isEVCandidate = (allowedAnchors && !disableEV) ? true : false; if (isEVCandidate) { secdebug("evTrust", "Trust::evaluate() certificate is EV candidate"); filteredCerts = potentialEVChainWithCertificates(mCerts); @@ -520,7 +523,7 @@ void Trust::evaluate(bool disableEV) if (isEVCandidate && mResult == kSecTrustResultRecoverableTrustFailure && - isRevocationServerMetaError(mTpReturn)) { + (mTpReturn == CSSMERR_TP_NOT_TRUSTED || isRevocationServerMetaError(mTpReturn))) { // re-do the evaluation, this time disabling EV evaluate(true); } diff --git a/libsecurity_keychain/lib/Trust.h b/Security/libsecurity_keychain/lib/Trust.h similarity index 98% rename from libsecurity_keychain/lib/Trust.h rename to Security/libsecurity_keychain/lib/Trust.h index 77f8aac1..ad7662b8 100644 --- a/libsecurity_keychain/lib/Trust.h +++ b/Security/libsecurity_keychain/lib/Trust.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2010,2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/TrustAdditions.cpp b/Security/libsecurity_keychain/lib/TrustAdditions.cpp similarity index 99% rename from libsecurity_keychain/lib/TrustAdditions.cpp rename to Security/libsecurity_keychain/lib/TrustAdditions.cpp index 6fffe9cb..8bfd749a 100644 --- a/libsecurity_keychain/lib/TrustAdditions.cpp +++ b/Security/libsecurity_keychain/lib/TrustAdditions.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2009,2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2009,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/TrustAdditions.h b/Security/libsecurity_keychain/lib/TrustAdditions.h similarity index 95% rename from libsecurity_keychain/lib/TrustAdditions.h rename to Security/libsecurity_keychain/lib/TrustAdditions.h index 8e69e266..8112929a 100644 --- a/libsecurity_keychain/lib/TrustAdditions.h +++ b/Security/libsecurity_keychain/lib/TrustAdditions.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-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, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/TrustItem.cpp b/Security/libsecurity_keychain/lib/TrustItem.cpp similarity index 98% rename from libsecurity_keychain/lib/TrustItem.cpp rename to Security/libsecurity_keychain/lib/TrustItem.cpp index 185bb691..4c2e3632 100644 --- a/libsecurity_keychain/lib/TrustItem.cpp +++ b/Security/libsecurity_keychain/lib/TrustItem.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/TrustItem.h b/Security/libsecurity_keychain/lib/TrustItem.h similarity index 97% rename from libsecurity_keychain/lib/TrustItem.h rename to Security/libsecurity_keychain/lib/TrustItem.h index e9927e26..54712c74 100644 --- a/libsecurity_keychain/lib/TrustItem.h +++ b/Security/libsecurity_keychain/lib/TrustItem.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/TrustKeychains.h b/Security/libsecurity_keychain/lib/TrustKeychains.h similarity index 96% rename from libsecurity_keychain/lib/TrustKeychains.h rename to Security/libsecurity_keychain/lib/TrustKeychains.h index 14cfb340..f13f18ca 100644 --- a/libsecurity_keychain/lib/TrustKeychains.h +++ b/Security/libsecurity_keychain/lib/TrustKeychains.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2009,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/TrustRevocation.cpp b/Security/libsecurity_keychain/lib/TrustRevocation.cpp similarity index 95% rename from libsecurity_keychain/lib/TrustRevocation.cpp rename to Security/libsecurity_keychain/lib/TrustRevocation.cpp index 9816df52..591ff209 100644 --- a/libsecurity_keychain/lib/TrustRevocation.cpp +++ b/Security/libsecurity_keychain/lib/TrustRevocation.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -135,12 +135,25 @@ CFMutableArrayRef Trust::convertRevocationPolicy( SecPointer crlPolicy; // fetch policy value - CFIndex policyValue = kSecRevocationUseAnyAvailableMethod; //%%%FIXME + CFOptionFlags policyFlags = kSecRevocationUseAnyAvailableMethod; + CSSM_DATA policyValue = { 0, NULL }; + OSStatus status = SecPolicyGetValue(revPolicy, &policyValue); + if (!status && policyValue.Data) { + policyFlags = (CFOptionFlags) *((CFOptionFlags*)policyValue.Data); + } + if (mNetworkPolicy == useNetworkDisabled) { + policyFlags = 0 | kSecRevocationNetworkAccessDisabled; + } CFRelease(revPolicy); // all done with this policy reference - if (policyValue & kSecRevocationOCSPMethod) { + + if (policyFlags & kSecRevocationOCSPMethod) { /* cook up a new Policy object */ ocspPolicy = new Policy(mTP, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP)); CSSM_APPLE_TP_OCSP_OPT_FLAGS ocspFlags = CSSM_TP_ACTION_OCSP_SUFFICIENT; + if (policyFlags & kSecRevocationRequirePositiveResponse) { + // FIXME: possibly set CSSM_TP_ACTION_REQUIRE_REV_PER_CERT in actionFlags, + // but verify whether that only applies to certs which specify a revocation method + } CSSM_APPLE_TP_OCSP_OPTIONS opts; memset(&opts, 0, sizeof(opts)); opts.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION; @@ -154,10 +167,14 @@ CFMutableArrayRef Trust::convertRevocationPolicy( CFArrayAppendValue(policies, ocspPolicy->handle(false)); numAdded++; } - if (policyValue & kSecRevocationCRLMethod) { + if (policyFlags & kSecRevocationCRLMethod) { /* cook up a new Policy object */ crlPolicy = new Policy(mTP, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL)); CSSM_APPLE_TP_CRL_OPT_FLAGS crlFlags = 0; + if (policyFlags & kSecRevocationRequirePositiveResponse) { + // FIXME: possibly set CSSM_TP_ACTION_REQUIRE_REV_PER_CERT in actionFlags, + // but verify whether that only applies to certs which specify a revocation method + } CSSM_APPLE_TP_CRL_OPTIONS opts; memset(&opts, 0, sizeof(opts)); opts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION; diff --git a/libsecurity_keychain/lib/TrustSettings.cpp b/Security/libsecurity_keychain/lib/TrustSettings.cpp similarity index 99% rename from libsecurity_keychain/lib/TrustSettings.cpp rename to Security/libsecurity_keychain/lib/TrustSettings.cpp index 47cf13d5..12a9c44e 100644 --- a/libsecurity_keychain/lib/TrustSettings.cpp +++ b/Security/libsecurity_keychain/lib/TrustSettings.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2005,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -24,7 +24,6 @@ /* * TrustSettings.h - class to manage cert trust settings. * - * Created May 10 2005 by dmitch. */ #include "TrustSettings.h" diff --git a/libsecurity_keychain/lib/TrustSettings.h b/Security/libsecurity_keychain/lib/TrustSettings.h similarity index 99% rename from libsecurity_keychain/lib/TrustSettings.h rename to Security/libsecurity_keychain/lib/TrustSettings.h index 99bf9072..ffebdd33 100644 --- a/libsecurity_keychain/lib/TrustSettings.h +++ b/Security/libsecurity_keychain/lib/TrustSettings.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2005,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/TrustSettingsSchema.h b/Security/libsecurity_keychain/lib/TrustSettingsSchema.h similarity index 98% rename from libsecurity_keychain/lib/TrustSettingsSchema.h rename to Security/libsecurity_keychain/lib/TrustSettingsSchema.h index 3dda8998..2310dc43 100644 --- a/libsecurity_keychain/lib/TrustSettingsSchema.h +++ b/Security/libsecurity_keychain/lib/TrustSettingsSchema.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2005,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/TrustSettingsUtils.cpp b/Security/libsecurity_keychain/lib/TrustSettingsUtils.cpp similarity index 96% rename from libsecurity_keychain/lib/TrustSettingsUtils.cpp rename to Security/libsecurity_keychain/lib/TrustSettingsUtils.cpp index 66fc59dd..e001afd0 100644 --- a/libsecurity_keychain/lib/TrustSettingsUtils.cpp +++ b/Security/libsecurity_keychain/lib/TrustSettingsUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2005,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -24,7 +24,6 @@ /* * TrustSettingsUtils.cpp - Utility routines for TrustSettings module * - * Created May 10 2005 by dmitch. */ #include "TrustSettingsUtils.h" diff --git a/libsecurity_keychain/lib/TrustSettingsUtils.h b/Security/libsecurity_keychain/lib/TrustSettingsUtils.h similarity index 96% rename from libsecurity_keychain/lib/TrustSettingsUtils.h rename to Security/libsecurity_keychain/lib/TrustSettingsUtils.h index f2aae0b1..0b1191c5 100644 --- a/libsecurity_keychain/lib/TrustSettingsUtils.h +++ b/Security/libsecurity_keychain/lib/TrustSettingsUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2005,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/TrustStore.cpp b/Security/libsecurity_keychain/lib/TrustStore.cpp similarity index 99% rename from libsecurity_keychain/lib/TrustStore.cpp rename to Security/libsecurity_keychain/lib/TrustStore.cpp index 716ea3bc..c703d431 100644 --- a/libsecurity_keychain/lib/TrustStore.cpp +++ b/Security/libsecurity_keychain/lib/TrustStore.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/TrustStore.h b/Security/libsecurity_keychain/lib/TrustStore.h similarity index 97% rename from libsecurity_keychain/lib/TrustStore.h rename to Security/libsecurity_keychain/lib/TrustStore.h index 7f5f3a1f..535917a4 100644 --- a/libsecurity_keychain/lib/TrustStore.h +++ b/Security/libsecurity_keychain/lib/TrustStore.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/TrustedApplication.cpp b/Security/libsecurity_keychain/lib/TrustedApplication.cpp similarity index 98% rename from libsecurity_keychain/lib/TrustedApplication.cpp rename to Security/libsecurity_keychain/lib/TrustedApplication.cpp index 6d91146a..955b429b 100644 --- a/libsecurity_keychain/lib/TrustedApplication.cpp +++ b/Security/libsecurity_keychain/lib/TrustedApplication.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/TrustedApplication.h b/Security/libsecurity_keychain/lib/TrustedApplication.h similarity index 97% rename from libsecurity_keychain/lib/TrustedApplication.h rename to Security/libsecurity_keychain/lib/TrustedApplication.h index 70073d3c..13d6ba3f 100644 --- a/libsecurity_keychain/lib/TrustedApplication.h +++ b/Security/libsecurity_keychain/lib/TrustedApplication.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_keychain/lib/UnlockReferralItem.cpp b/Security/libsecurity_keychain/lib/UnlockReferralItem.cpp similarity index 98% rename from libsecurity_keychain/lib/UnlockReferralItem.cpp rename to Security/libsecurity_keychain/lib/UnlockReferralItem.cpp index e5e1755d..f9b004a3 100644 --- a/libsecurity_keychain/lib/UnlockReferralItem.cpp +++ b/Security/libsecurity_keychain/lib/UnlockReferralItem.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/UnlockReferralItem.h b/Security/libsecurity_keychain/lib/UnlockReferralItem.h similarity index 96% rename from libsecurity_keychain/lib/UnlockReferralItem.h rename to Security/libsecurity_keychain/lib/UnlockReferralItem.h index 1ae195f0..cdea8e41 100644 --- a/libsecurity_keychain/lib/UnlockReferralItem.h +++ b/Security/libsecurity_keychain/lib/UnlockReferralItem.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/certextensionsP.h b/Security/libsecurity_keychain/lib/certextensionsP.h similarity index 99% rename from libsecurity_keychain/lib/certextensionsP.h rename to Security/libsecurity_keychain/lib/certextensionsP.h index b2753d9d..93cb28fa 100644 --- a/libsecurity_keychain/lib/certextensionsP.h +++ b/Security/libsecurity_keychain/lib/certextensionsP.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2009,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/cssmdatetime.cpp b/Security/libsecurity_keychain/lib/cssmdatetime.cpp similarity index 99% rename from libsecurity_keychain/lib/cssmdatetime.cpp rename to Security/libsecurity_keychain/lib/cssmdatetime.cpp index 54aa8447..dd0378e6 100644 --- a/libsecurity_keychain/lib/cssmdatetime.cpp +++ b/Security/libsecurity_keychain/lib/cssmdatetime.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/cssmdatetime.h b/Security/libsecurity_keychain/lib/cssmdatetime.h similarity index 97% rename from libsecurity_keychain/lib/cssmdatetime.h rename to Security/libsecurity_keychain/lib/cssmdatetime.h index c0a8e0f9..eb9af160 100644 --- a/libsecurity_keychain/lib/cssmdatetime.h +++ b/Security/libsecurity_keychain/lib/cssmdatetime.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2002,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 1997-2002,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/defaultcreds.cpp b/Security/libsecurity_keychain/lib/defaultcreds.cpp similarity index 98% rename from libsecurity_keychain/lib/defaultcreds.cpp rename to Security/libsecurity_keychain/lib/defaultcreds.cpp index 02cb5131..5188b0e0 100644 --- a/libsecurity_keychain/lib/defaultcreds.cpp +++ b/Security/libsecurity_keychain/lib/defaultcreds.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/defaultcreds.h b/Security/libsecurity_keychain/lib/defaultcreds.h similarity index 97% rename from libsecurity_keychain/lib/defaultcreds.h rename to Security/libsecurity_keychain/lib/defaultcreds.h index bc9225a6..86e3fb5e 100644 --- a/libsecurity_keychain/lib/defaultcreds.h +++ b/Security/libsecurity_keychain/lib/defaultcreds.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_keychain/lib/generateErrStrings.pl b/Security/libsecurity_keychain/lib/generateErrStrings.pl new file mode 100644 index 00000000..0cbe03f8 --- /dev/null +++ b/Security/libsecurity_keychain/lib/generateErrStrings.pl @@ -0,0 +1,98 @@ +#!/usr/bin/perl +# +# Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. +# +# @APPLE_LICENSE_HEADER_START@ +# +# This file contains Original Code and/or Modifications of Original Code +# as defined in and that are subject to the Apple Public Source License +# Version 2.0 (the 'License'). You may not use this file except in +# compliance with the License. Please obtain a copy of the License at +# http://www.opensource.apple.com/apsl/ and read it before using this +# file. +# +# The Original Code and all software distributed under the License are +# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +# Please see the License for the specific language governing rights and +# limitations under the License. +# +# @APPLE_LICENSE_HEADER_END@ +# +# generatorX.pl - create error strings files from the Security header files +# +# Usage: +# perl generatorX.pl input-directory output-directory +# +# Currently supported files are SecBase.h, SecureTransport.h and Authorization.h +# +# perl generatorX.pl `pwd` `pwd` SecBase2.h SecureTransport2.h Authorization.h +# +# Input will be like: +# +# errSSLProtocol = -9800, /* SSL protocol error */ +# errSSLNegotiation = -9801, /* Cipher Suite negotiation failure */ +# +# Output should be like (in Unicode): +# +# /* errSSLProtocol */ +# "-9800" = "SSL protocol error"; +# +# /* errSSLNegotiation */ +# "-9801" = "Cipher Suite negotiation failure"; +# +# Note that the list of errors must be numerically unique across all input files, or the strings file +# will be invalid.Comments that span multiple lines will be ignored, as will lines with no comment. C++ +# style comments are not supported. +# + +use Encode; + +$SOURCEDIR=$ARGV[0]; # directory with error headers +$TARGETDIR=$ARGV[1]; # where to put the output file +@INPUTFILES=@ARGV[2 .. 9999]; # list of input files + +$TABLES="$TARGETDIR/SecErrorMessages.strings"; # error strings + +$tabs = "\t\t\t"; # argument indentation (noncritical) +$warning = "This file was automatically generated. Do not edit on penalty of futility!"; + +# +# Parse error headers and build array of all relevant lines +# + +open(ERR, "cat " . join(" ", @INPUTFILES) . "|") or die "Cannot open error header files"; +$/=undef; # big gulp mode +$_ = ; +@errorlines = m{(?:^\s*)(err[Sec|Authorization|SSL]\w+)(?:\s*=\s*)(-?\d+)(?:\s*,?\s*)(?:/\*\s*)(.*)(?:\*/)(?:$\s*)}gm; +close(ERR); + +$nFull = $#errorlines / 3; + +# +# Now we will generate the error name tables. +# +open(OUT, ">$TABLES") or die "Cannot write $TABLES: $^E"; + +# Print warning comment +$msg = "//\n// Security error code tables.\n// $warning\n//\n"; + +# Print the error messages +while ($errx = shift @errorlines) +{ + $value = shift @errorlines; # or die; + $str = shift @errorlines; # or die; + $str =~ s/\s*$//; # drop trailing white space + if ( $value != 0) # can't output duplicate error codes + { + $msg = $msg . "\n/* $errx */\n\"$value\" = \"$str\";\n"; + } +}; +$msg = $msg . "\n"; +$output = encode("UTF-16", $msg, Encode::FB_PERLQQ); +print OUT "$output"; + +close(OUT); +select(STDOUT); diff --git a/libsecurity_keychain/lib/security_keychain.exp b/Security/libsecurity_keychain/lib/security_keychain.exp similarity index 97% rename from libsecurity_keychain/lib/security_keychain.exp rename to Security/libsecurity_keychain/lib/security_keychain.exp index 9658bb6c..93930e85 100644 --- a/libsecurity_keychain/lib/security_keychain.exp +++ b/Security/libsecurity_keychain/lib/security_keychain.exp @@ -1,5 +1,5 @@ # -# Copyright (c) 2003-2013 Apple Inc. All Rights Reserved. +# Copyright (c) 2003-2014 Apple Inc. All Rights Reserved. # # @APPLE_LICENSE_HEADER_START@ # @@ -203,6 +203,13 @@ _kSecPolicyAppleIDValidation _kSecPolicyAppleTimeStamping _kSecPolicyAppleRevocation _kSecPolicyApplePassbookSigning +_kSecPolicyAppleMobileStore +_kSecPolicyAppleEscrowService +_kSecPolicyApplePCSEscrowService +_kSecPolicyAppleProfileSigner +_kSecPolicyAppleQAProfileSigner +_kSecPolicyAppleTestMobileStore +_kSecPolicyAppleServerAuthentication _kSecPolicyOid _kSecPolicyName _kSecPolicyClient @@ -535,6 +542,7 @@ _SecKeychainGetTypeID _SecKeychainGetUserInteractionAllowed _SecKeychainGetVersion _SecKeychainIsValid +_SecKeychainMDSInstall _SecKeychainItemAdd _SecKeychainItemAddNoUI _SecKeychainItemCopyAccess @@ -608,11 +616,16 @@ _SecGenericPasswordCreate _SecPasswordSetInitialAccess _SecPasswordAction _SecPKCS12Import +_SecPolicyCreateAppleIDSService +_SecPolicyCreateApplePushService +_SecPolicyCreateAppleMMCSService +_SecPolicyCreateAppleSSLService _SecPolicyCreateBasicX509 _SecPolicyCreateRevocation _SecPolicyCreateSSL _SecPolicyCreateWithOID _SecPolicyCreateWithProperties +_SecPolicyCreateAppleTimeStampingAndRevocationPolicies _SecPolicyGetOID _SecPolicyGetTPHandle _SecPolicyGetTypeID diff --git a/libsecurity_keychain/lib/tsaDERUtilities.c b/Security/libsecurity_keychain/lib/tsaDERUtilities.c similarity index 98% rename from libsecurity_keychain/lib/tsaDERUtilities.c rename to Security/libsecurity_keychain/lib/tsaDERUtilities.c index 671aa1f3..87cc6df1 100644 --- a/libsecurity_keychain/lib/tsaDERUtilities.c +++ b/Security/libsecurity_keychain/lib/tsaDERUtilities.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/lib/tsaDERUtilities.h b/Security/libsecurity_keychain/lib/tsaDERUtilities.h similarity index 95% rename from libsecurity_keychain/lib/tsaDERUtilities.h rename to Security/libsecurity_keychain/lib/tsaDERUtilities.h index 61e2a21f..281b84ea 100644 --- a/libsecurity_keychain/lib/tsaDERUtilities.h +++ b/Security/libsecurity_keychain/lib/tsaDERUtilities.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/libDER/README.txt b/Security/libsecurity_keychain/libDER/README.txt similarity index 100% rename from libsecurity_keychain/libDER/README.txt rename to Security/libsecurity_keychain/libDER/README.txt diff --git a/libsecurity_keychain/libDER/Tests/AppleMobilePersonalizedTicket.h b/Security/libsecurity_keychain/libDER/Tests/AppleMobilePersonalizedTicket.h similarity index 86% rename from libsecurity_keychain/libDER/Tests/AppleMobilePersonalizedTicket.h rename to Security/libsecurity_keychain/libDER/Tests/AppleMobilePersonalizedTicket.h index 875624c0..37b4033b 100644 --- a/libsecurity_keychain/libDER/Tests/AppleMobilePersonalizedTicket.h +++ b/Security/libsecurity_keychain/libDER/Tests/AppleMobilePersonalizedTicket.h @@ -1,12 +1,27 @@ /* - * AppleMobilePersonalizedTicket.h - * ticketlib - * - * Created by Jason Gosnell on 9/24/09. - * Copyright 2009 Apple, Inc. All rights reserved. + * Copyright (c) 2009,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@ */ + #ifndef APPLEMOBILEPERSONALIZEDTICKET_H #define APPLEMOBILEPERSONALIZEDTICKET_H diff --git a/libsecurity_keychain/libDER/Tests/DER_Ticket.c b/Security/libsecurity_keychain/libDER/Tests/DER_Ticket.c similarity index 85% rename from libsecurity_keychain/libDER/Tests/DER_Ticket.c rename to Security/libsecurity_keychain/libDER/Tests/DER_Ticket.c index c7c5fd97..c5be4816 100644 --- a/libsecurity_keychain/libDER/Tests/DER_Ticket.c +++ b/Security/libsecurity_keychain/libDER/Tests/DER_Ticket.c @@ -1,12 +1,27 @@ /* - * DER_Ticket.c - * libDER - * - * Created by Michael Brouwer on 10/13/09. - * Copyright 2009 Apple Inc. All rights reserved. + * Copyright (c) 2009,2012,2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include "DER_Ticket.h" #include diff --git a/Security/libsecurity_keychain/libDER/Tests/DER_Ticket.h b/Security/libsecurity_keychain/libDER/Tests/DER_Ticket.h new file mode 100644 index 00000000..080b98ff --- /dev/null +++ b/Security/libsecurity_keychain/libDER/Tests/DER_Ticket.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2009,2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + + +#define FAST_SET_LOOKUP 1 + +#ifdef FAST_SET_LOOKUP +/* state representing a fast by tag set accessor, the caller needs to provide + a set large enough to hold all */ +typedef struct { + DERTag capacity; /* should be large enough to hold all encountered tags. + otherwise DR_UnexpectedTag will be returned, note + that only one tag per tag number can exist. */ + DERByte *end; + DERByte *byTag[]; /* maxTag element array of pointers to tag + length + of items in set indexed by tagNumber. */ +} DERSet; + +/* Iterates over all the tags in the set to build an index returned in + derSet. */ +DERReturn DERDecodeSetContentInit( + const DERItem *der, /* data to decode */ + DERSet *derSet); /* IN/OUT, to use in DERDecodeSetTag */ + +/* Returns DR_UnexpectedTag if the requested tag is not in derSet, returns + the content of the decoded item in content otherwise. */ +DERReturn DERDecodeSetTag( + DERSet *derSeq, /* data to decode */ + DERTag tag, /* tag in sequence/set we are looking for. */ + DERItem *content); /* RETURNED */ +#endif /* FAST_SET_LOOKUP */ + + +DERReturn DERSetDecodeItemWithTag( + const DERItem *der, /* data to decode */ + DERTag tag, /* tag in sequence/set we are looking for. */ + DERItem *content); /* RETURNED */ + + +/* Application Processor Ticket */ +typedef struct { + DERItem signatureAlgorithm; /* AlgorithmId */ + DERItem body; /* SET OF OCTECT STRING, DER_DEC_SAVE_DER */ + DERItem signature; /* OCTET STRING */ + DERItem certificates; /* SEQUENCE of CERTIFICATE */ +} DERApTicket; + +/* DERItemSpecs to decode into a DERApTicket */ +extern const DERItemSpec DERApTicketItemSpecs[]; +extern const DERSize DERNumApTicketItemSpecs; + +DERReturn DERDecodeApTicket( + const DERItem *contents, + DERApTicket *ticket, /* RETURNED */ + DERSize *numUsedBytes); /* RETURNED */ + + +/* Baseband Ticket */ +typedef struct { + DERItem signatureAlgorithm; /* AlgorithmId */ + DERItem body; /* SET OF OCTECT STRING, DER_DEC_SAVE_DER */ + DERItem signature; /* OCTET STRING */ + DERItem gpuk; /* OCTET STRING */ +} DERBbTicket; + +/* DERItemSpecs to decode into a DERBbTicket */ +extern const DERItemSpec DERBbTicketItemSpecs[]; +extern const DERSize DERNumBbTicketItemSpecs; + +DERReturn DERDecodeBbTicket( + const DERItem *contents, + DERBbTicket *ticket, /* RETURNED */ + DERSize *numUsedBytes); /* RETURNED */ diff --git a/libsecurity_keychain/libDER/Tests/certsCrls/EndCertificateCP.01.01.crt b/Security/libsecurity_keychain/libDER/Tests/certsCrls/EndCertificateCP.01.01.crt similarity index 100% rename from libsecurity_keychain/libDER/Tests/certsCrls/EndCertificateCP.01.01.crt rename to Security/libsecurity_keychain/libDER/Tests/certsCrls/EndCertificateCP.01.01.crt diff --git a/libsecurity_keychain/libDER/Tests/certsCrls/Test_CRL_CA1.crl b/Security/libsecurity_keychain/libDER/Tests/certsCrls/Test_CRL_CA1.crl similarity index 100% rename from libsecurity_keychain/libDER/Tests/certsCrls/Test_CRL_CA1.crl rename to Security/libsecurity_keychain/libDER/Tests/certsCrls/Test_CRL_CA1.crl diff --git a/libsecurity_keychain/libDER/Tests/certsCrls/Test_CRL_CA1.crl.pem b/Security/libsecurity_keychain/libDER/Tests/certsCrls/Test_CRL_CA1.crl.pem similarity index 100% rename from libsecurity_keychain/libDER/Tests/certsCrls/Test_CRL_CA1.crl.pem rename to Security/libsecurity_keychain/libDER/Tests/certsCrls/Test_CRL_CA1.crl.pem diff --git a/libsecurity_keychain/libDER/Tests/certsCrls/TrustAnchorCP.01.01.crt b/Security/libsecurity_keychain/libDER/Tests/certsCrls/TrustAnchorCP.01.01.crt similarity index 100% rename from libsecurity_keychain/libDER/Tests/certsCrls/TrustAnchorCP.01.01.crt rename to Security/libsecurity_keychain/libDER/Tests/certsCrls/TrustAnchorCP.01.01.crt diff --git a/libsecurity_keychain/libDER/Tests/certsCrls/TrustAnchorCRLCP.01.01.crl b/Security/libsecurity_keychain/libDER/Tests/certsCrls/TrustAnchorCRLCP.01.01.crl similarity index 100% rename from libsecurity_keychain/libDER/Tests/certsCrls/TrustAnchorCRLCP.01.01.crl rename to Security/libsecurity_keychain/libDER/Tests/certsCrls/TrustAnchorCRLCP.01.01.crl diff --git a/libsecurity_keychain/libDER/Tests/certsCrls/apple_v3.000.cer b/Security/libsecurity_keychain/libDER/Tests/certsCrls/apple_v3.000.cer similarity index 100% rename from libsecurity_keychain/libDER/Tests/certsCrls/apple_v3.000.cer rename to Security/libsecurity_keychain/libDER/Tests/certsCrls/apple_v3.000.cer diff --git a/libsecurity_keychain/libDER/Tests/certsCrls/apple_v3.001.cer b/Security/libsecurity_keychain/libDER/Tests/certsCrls/apple_v3.001.cer similarity index 100% rename from libsecurity_keychain/libDER/Tests/certsCrls/apple_v3.001.cer rename to Security/libsecurity_keychain/libDER/Tests/certsCrls/apple_v3.001.cer diff --git a/libsecurity_keychain/libDER/Tests/certsCrls/entrust_v3.100.cer b/Security/libsecurity_keychain/libDER/Tests/certsCrls/entrust_v3.100.cer similarity index 100% rename from libsecurity_keychain/libDER/Tests/certsCrls/entrust_v3.100.cer rename to Security/libsecurity_keychain/libDER/Tests/certsCrls/entrust_v3.100.cer diff --git a/libsecurity_keychain/libDER/Tests/certsCrls/entrust_v3.101.cer b/Security/libsecurity_keychain/libDER/Tests/certsCrls/entrust_v3.101.cer similarity index 100% rename from libsecurity_keychain/libDER/Tests/certsCrls/entrust_v3.101.cer rename to Security/libsecurity_keychain/libDER/Tests/certsCrls/entrust_v3.101.cer diff --git a/libsecurity_keychain/libDER/Tests/certsCrls/keybank_v3.100.cer b/Security/libsecurity_keychain/libDER/Tests/certsCrls/keybank_v3.100.cer similarity index 100% rename from libsecurity_keychain/libDER/Tests/certsCrls/keybank_v3.100.cer rename to Security/libsecurity_keychain/libDER/Tests/certsCrls/keybank_v3.100.cer diff --git a/libsecurity_keychain/libDER/Tests/certsCrls/keybank_v3.101.cer b/Security/libsecurity_keychain/libDER/Tests/certsCrls/keybank_v3.101.cer similarity index 100% rename from libsecurity_keychain/libDER/Tests/certsCrls/keybank_v3.101.cer rename to Security/libsecurity_keychain/libDER/Tests/certsCrls/keybank_v3.101.cer diff --git a/libsecurity_keychain/libDER/Tests/certsCrls/keybank_v3.102.cer b/Security/libsecurity_keychain/libDER/Tests/certsCrls/keybank_v3.102.cer similarity index 100% rename from libsecurity_keychain/libDER/Tests/certsCrls/keybank_v3.102.cer rename to Security/libsecurity_keychain/libDER/Tests/certsCrls/keybank_v3.102.cer diff --git a/libsecurity_keychain/libDER/Tests/parseCert.c b/Security/libsecurity_keychain/libDER/Tests/parseCert.c similarity index 98% rename from libsecurity_keychain/libDER/Tests/parseCert.c rename to Security/libsecurity_keychain/libDER/Tests/parseCert.c index de5076a5..2ad3a914 100644 --- a/libsecurity_keychain/libDER/Tests/parseCert.c +++ b/Security/libsecurity_keychain/libDER/Tests/parseCert.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2007,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2005-2007,2010-2011 Apple Inc. All Rights Reserved. * * parseCert.c - parse a DER-encoded X509 certificate using libDER. */ diff --git a/libsecurity_keychain/libDER/Tests/parseCrl.c b/Security/libsecurity_keychain/libDER/Tests/parseCrl.c similarity index 98% rename from libsecurity_keychain/libDER/Tests/parseCrl.c rename to Security/libsecurity_keychain/libDER/Tests/parseCrl.c index 41595e72..4eabc130 100644 --- a/libsecurity_keychain/libDER/Tests/parseCrl.c +++ b/Security/libsecurity_keychain/libDER/Tests/parseCrl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2007,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2005-2007,2010-2011 Apple Inc. All Rights Reserved. * * parseCrl.c - parse a DER-encoded X509 CRL using libDER. */ diff --git a/libsecurity_keychain/libDER/Tests/parseTicket.c b/Security/libsecurity_keychain/libDER/Tests/parseTicket.c similarity index 100% rename from libsecurity_keychain/libDER/Tests/parseTicket.c rename to Security/libsecurity_keychain/libDER/Tests/parseTicket.c diff --git a/Security/libsecurity_keychain/libDER/config/base.xcconfig b/Security/libsecurity_keychain/libDER/config/base.xcconfig new file mode 100644 index 00000000..b6aaf1bc --- /dev/null +++ b/Security/libsecurity_keychain/libDER/config/base.xcconfig @@ -0,0 +1,16 @@ +CODE_SIGN_IDENTITY = -; +GCC_VERSION = com.apple.compilers.llvm.clang.1_0 +DEBUG_INFORMATION_FORMAT = dwarf-with-dsym +CURRENT_PROJECT_VERSION = $(RC_ProjectSourceVersion) +VERSIONING_SYSTEM = apple-generic; +DEAD_CODE_STRIPPING = YES; + +ARCHS = $(ARCHS_STANDARD_32_64_BIT) + +// Debug symbols should be on obviously +GCC_GENERATE_DEBUGGING_SYMBOLS = YES +COPY_PHASE_STRIP = NO +STRIP_STYLE = debugging +STRIP_INSTALLED_PRODUCT = NO + +WARNING_CFLAGS = -Wglobal-constructors -Wno-deprecated-declarations $(inherited) diff --git a/libsecurity_keychain/libDER/config/debug.xcconfig b/Security/libsecurity_keychain/libDER/config/debug.xcconfig similarity index 100% rename from libsecurity_keychain/libDER/config/debug.xcconfig rename to Security/libsecurity_keychain/libDER/config/debug.xcconfig diff --git a/libsecurity_keychain/libDER/config/lib.xcconfig b/Security/libsecurity_keychain/libDER/config/lib.xcconfig similarity index 100% rename from libsecurity_keychain/libDER/config/lib.xcconfig rename to Security/libsecurity_keychain/libDER/config/lib.xcconfig diff --git a/libsecurity_keychain/libDER/config/release.xcconfig b/Security/libsecurity_keychain/libDER/config/release.xcconfig similarity index 100% rename from libsecurity_keychain/libDER/config/release.xcconfig rename to Security/libsecurity_keychain/libDER/config/release.xcconfig diff --git a/Security/libsecurity_keychain/libDER/libDER.xcodeproj/project.pbxproj b/Security/libsecurity_keychain/libDER/libDER.xcodeproj/project.pbxproj new file mode 100644 index 00000000..abcee2a8 --- /dev/null +++ b/Security/libsecurity_keychain/libDER/libDER.xcodeproj/project.pbxproj @@ -0,0 +1,756 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + 053BA30F091C00B100A7007A /* World */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 4CD81A6D09BE1FD2000A9641 /* Build configuration list for PBXAggregateTarget "World" */; + buildPhases = ( + ); + dependencies = ( + 053BA317091C017E00A7007A /* PBXTargetDependency */, + 053BA463091FE60E00A7007A /* PBXTargetDependency */, + 058ECC54091FF0000050AA30 /* PBXTargetDependency */, + 058F16680925224F009FA1C5 /* PBXTargetDependency */, + 4C96C8DC113F4174005483E8 /* PBXTargetDependency */, + ); + name = World; + productName = World; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 053BA324091C02B700A7007A /* DER_Decode.h in Headers */ = {isa = PBXBuildFile; fileRef = 053BA321091C02B700A7007A /* DER_Decode.h */; }; + 053BA325091C02B700A7007A /* libDER_config.h in Headers */ = {isa = PBXBuildFile; fileRef = 053BA322091C02B700A7007A /* libDER_config.h */; }; + 053BA326091C02B700A7007A /* libDER.h in Headers */ = {isa = PBXBuildFile; fileRef = 053BA323091C02B700A7007A /* libDER.h */; }; + 053BA344091C089B00A7007A /* asn1Types.h in Headers */ = {isa = PBXBuildFile; fileRef = 053BA342091C089B00A7007A /* asn1Types.h */; }; + 053BA345091C089B00A7007A /* DER_Decode.c in Sources */ = {isa = PBXBuildFile; fileRef = 053BA343091C089B00A7007A /* DER_Decode.c */; }; + 053BA399091C258100A7007A /* DER_CertCrl.c in Sources */ = {isa = PBXBuildFile; fileRef = 053BA397091C258100A7007A /* DER_CertCrl.c */; }; + 053BA39A091C258100A7007A /* DER_CertCrl.h in Headers */ = {isa = PBXBuildFile; fileRef = 053BA398091C258100A7007A /* DER_CertCrl.h */; }; + 053BA45D091FE5E700A7007A /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 053BA314091C00BF00A7007A /* libDER.a */; }; + 053BA461091FE60700A7007A /* parseCert.c in Sources */ = {isa = PBXBuildFile; fileRef = 053BA460091FE60700A7007A /* parseCert.c */; }; + 053BA470091FE6C100A7007A /* fileIo.c in Sources */ = {isa = PBXBuildFile; fileRef = 053BA46E091FE6C100A7007A /* fileIo.c */; }; + 053BA471091FE6C100A7007A /* fileIo.h in Headers */ = {isa = PBXBuildFile; fileRef = 053BA46F091FE6C100A7007A /* fileIo.h */; }; + 053BA47D091FE7CC00A7007A /* libDERUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 053BA47B091FE7CC00A7007A /* libDERUtils.h */; }; + 053BA47E091FE7CC00A7007A /* libDERUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 053BA47C091FE7CC00A7007A /* libDERUtils.c */; }; + 0544AEA10940939C00DD6C0B /* DER_Encode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0544AE9F0940939C00DD6C0B /* DER_Encode.h */; }; + 0544AEA20940939C00DD6C0B /* DER_Encode.c in Sources */ = {isa = PBXBuildFile; fileRef = 0544AEA00940939C00DD6C0B /* DER_Encode.c */; }; + 058ECC52091FEFF70050AA30 /* libDERUtils.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 053BA46B091FE63E00A7007A /* libDERUtils.a */; }; + 058ECD350920F5E30050AA30 /* DER_Keys.c in Sources */ = {isa = PBXBuildFile; fileRef = 058ECD330920F5E30050AA30 /* DER_Keys.c */; }; + 058ECD360920F5E30050AA30 /* DER_Keys.h in Headers */ = {isa = PBXBuildFile; fileRef = 058ECD340920F5E30050AA30 /* DER_Keys.h */; }; + 058F15C20922B73F009FA1C5 /* printFields.h in Headers */ = {isa = PBXBuildFile; fileRef = 058F15C00922B73F009FA1C5 /* printFields.h */; }; + 058F15C30922B73F009FA1C5 /* printFields.c in Sources */ = {isa = PBXBuildFile; fileRef = 058F15C10922B73F009FA1C5 /* printFields.c */; }; + 058F163109250D16009FA1C5 /* oids.c in Sources */ = {isa = PBXBuildFile; fileRef = 058F162D09250D0D009FA1C5 /* oids.c */; }; + 058F163209250D17009FA1C5 /* oids.h in Headers */ = {isa = PBXBuildFile; fileRef = 058F162E09250D0D009FA1C5 /* oids.h */; }; + 058F1659092513A7009FA1C5 /* parseCrl.c in Sources */ = {isa = PBXBuildFile; fileRef = 058F1658092513A7009FA1C5 /* parseCrl.c */; }; + 058F16710925230E009FA1C5 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 053BA314091C00BF00A7007A /* libDER.a */; }; + 058F16720925230F009FA1C5 /* libDERUtils.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 053BA46B091FE63E00A7007A /* libDERUtils.a */; }; + 05E0E40709228A5E005F4693 /* DER_Digest.h in Headers */ = {isa = PBXBuildFile; fileRef = 05E0E40509228A5E005F4693 /* DER_Digest.h */; }; + 05E0E40809228A5E005F4693 /* DER_Digest.c in Sources */ = {isa = PBXBuildFile; fileRef = 05E0E40609228A5E005F4693 /* DER_Digest.c */; }; + 4C96C8D6113F4165005483E8 /* DER_Ticket.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C96C8D3113F4165005483E8 /* DER_Ticket.c */; }; + 4C96C8D7113F4165005483E8 /* parseTicket.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C96C8D5113F4165005483E8 /* parseTicket.c */; }; + 4C96C8E2113F4232005483E8 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 053BA314091C00BF00A7007A /* libDER.a */; }; + 4C96C8ED113F42D1005483E8 /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C96C8EC113F42C4005483E8 /* libcrypto.dylib */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 053BA316091C017E00A7007A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 053BA30A091C00A400A7007A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 053BA313091C00BF00A7007A; + remoteInfo = libDER; + }; + 053BA458091FE59900A7007A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 053BA30A091C00A400A7007A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 053BA313091C00BF00A7007A; + remoteInfo = libDER; + }; + 053BA462091FE60E00A7007A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 053BA30A091C00A400A7007A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 053BA444091FE58C00A7007A; + remoteInfo = parseCert; + }; + 058ECC53091FF0000050AA30 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 053BA30A091C00A400A7007A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 053BA46A091FE63E00A7007A; + remoteInfo = libDERUtils; + }; + 058ECC55091FF0090050AA30 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 053BA30A091C00A400A7007A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 053BA46A091FE63E00A7007A; + remoteInfo = libDERUtils; + }; + 058F16670925224F009FA1C5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 053BA30A091C00A400A7007A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 058F16530925135E009FA1C5; + remoteInfo = parseCrl; + }; + 058F1675092523D8009FA1C5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 053BA30A091C00A400A7007A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 053BA313091C00BF00A7007A; + remoteInfo = libDER; + }; + 058F1677092523DD009FA1C5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 053BA30A091C00A400A7007A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 053BA46A091FE63E00A7007A; + remoteInfo = libDERUtils; + }; + 4C96C8DB113F4174005483E8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 053BA30A091C00A400A7007A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4C96C8CD113F4132005483E8; + remoteInfo = parseTicket; + }; + 4C96C8E0113F4223005483E8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 053BA30A091C00A400A7007A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 053BA313091C00BF00A7007A; + remoteInfo = libDER; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 053BA314091C00BF00A7007A /* libDER.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libDER.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 053BA321091C02B700A7007A /* DER_Decode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DER_Decode.h; sourceTree = ""; }; + 053BA322091C02B700A7007A /* libDER_config.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = libDER_config.h; sourceTree = ""; }; + 053BA323091C02B700A7007A /* libDER.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = libDER.h; sourceTree = ""; }; + 053BA342091C089B00A7007A /* asn1Types.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = asn1Types.h; sourceTree = ""; }; + 053BA343091C089B00A7007A /* DER_Decode.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = DER_Decode.c; sourceTree = ""; }; + 053BA397091C258100A7007A /* DER_CertCrl.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = DER_CertCrl.c; sourceTree = ""; }; + 053BA398091C258100A7007A /* DER_CertCrl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DER_CertCrl.h; sourceTree = ""; }; + 053BA445091FE58C00A7007A /* parseCert */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = parseCert; sourceTree = BUILT_PRODUCTS_DIR; }; + 053BA460091FE60700A7007A /* parseCert.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = parseCert.c; sourceTree = ""; }; + 053BA46B091FE63E00A7007A /* libDERUtils.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libDERUtils.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 053BA46E091FE6C100A7007A /* fileIo.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = fileIo.c; sourceTree = ""; }; + 053BA46F091FE6C100A7007A /* fileIo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = fileIo.h; sourceTree = ""; }; + 053BA47B091FE7CC00A7007A /* libDERUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libDERUtils.h; sourceTree = ""; }; + 053BA47C091FE7CC00A7007A /* libDERUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libDERUtils.c; sourceTree = ""; }; + 0544AE9F0940939C00DD6C0B /* DER_Encode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DER_Encode.h; sourceTree = ""; }; + 0544AEA00940939C00DD6C0B /* DER_Encode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DER_Encode.c; sourceTree = ""; }; + 058ECD330920F5E30050AA30 /* DER_Keys.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = DER_Keys.c; sourceTree = ""; }; + 058ECD340920F5E30050AA30 /* DER_Keys.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DER_Keys.h; sourceTree = ""; }; + 058F15C00922B73F009FA1C5 /* printFields.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = printFields.h; sourceTree = ""; }; + 058F15C10922B73F009FA1C5 /* printFields.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = printFields.c; sourceTree = ""; }; + 058F162D09250D0D009FA1C5 /* oids.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = oids.c; sourceTree = ""; }; + 058F162E09250D0D009FA1C5 /* oids.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = oids.h; sourceTree = ""; }; + 058F16540925135E009FA1C5 /* parseCrl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = parseCrl; sourceTree = BUILT_PRODUCTS_DIR; }; + 058F1658092513A7009FA1C5 /* parseCrl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = parseCrl.c; sourceTree = ""; }; + 05E0E40509228A5E005F4693 /* DER_Digest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DER_Digest.h; sourceTree = ""; }; + 05E0E40609228A5E005F4693 /* DER_Digest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DER_Digest.c; sourceTree = ""; }; + 1828EAA014E334E200BE00C2 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 1828EAA114E334E200BE00C2 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 1828EAA214E334E200BE00C2 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 1828EAA314E334E200BE00C2 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 4C96C8CE113F4132005483E8 /* parseTicket */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = parseTicket; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C96C8D2113F4165005483E8 /* AppleMobilePersonalizedTicket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppleMobilePersonalizedTicket.h; sourceTree = ""; }; + 4C96C8D3113F4165005483E8 /* DER_Ticket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DER_Ticket.c; sourceTree = ""; }; + 4C96C8D4113F4165005483E8 /* DER_Ticket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DER_Ticket.h; sourceTree = ""; }; + 4C96C8D5113F4165005483E8 /* parseTicket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = parseTicket.c; sourceTree = ""; }; + 4C96C8EC113F42C4005483E8 /* libcrypto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcrypto.dylib; path = /usr/lib/libcrypto.dylib; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 053BA312091C00BF00A7007A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 053BA443091FE58C00A7007A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 058ECC52091FEFF70050AA30 /* libDERUtils.a in Frameworks */, + 053BA45D091FE5E700A7007A /* libDER.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 053BA469091FE63E00A7007A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 058F16520925135E009FA1C5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 058F16720925230F009FA1C5 /* libDERUtils.a in Frameworks */, + 058F16710925230E009FA1C5 /* libDER.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C96C8CC113F4132005483E8 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C96C8E2113F4232005483E8 /* libDER.a in Frameworks */, + 4C96C8ED113F42D1005483E8 /* libcrypto.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 053BA306091C00A400A7007A = { + isa = PBXGroup; + children = ( + 1828EA9F14E334E200BE00C2 /* config */, + 053BA31E091C029900A7007A /* libDER */, + 053BA466091FE62100A7007A /* libDERUtils */, + 053BA45C091FE5CE00A7007A /* Tests */, + 058ECE5B09211AB20050AA30 /* External Libs */, + 053BA315091C00BF00A7007A /* Products */, + ); + sourceTree = ""; + }; + 053BA315091C00BF00A7007A /* Products */ = { + isa = PBXGroup; + children = ( + 053BA314091C00BF00A7007A /* libDER.a */, + 053BA445091FE58C00A7007A /* parseCert */, + 053BA46B091FE63E00A7007A /* libDERUtils.a */, + 058F16540925135E009FA1C5 /* parseCrl */, + 4C96C8CE113F4132005483E8 /* parseTicket */, + ); + name = Products; + sourceTree = ""; + }; + 053BA31E091C029900A7007A /* libDER */ = { + isa = PBXGroup; + children = ( + 058ECD330920F5E30050AA30 /* DER_Keys.c */, + 058ECD340920F5E30050AA30 /* DER_Keys.h */, + 053BA342091C089B00A7007A /* asn1Types.h */, + 053BA397091C258100A7007A /* DER_CertCrl.c */, + 053BA398091C258100A7007A /* DER_CertCrl.h */, + 053BA343091C089B00A7007A /* DER_Decode.c */, + 053BA321091C02B700A7007A /* DER_Decode.h */, + 0544AEA00940939C00DD6C0B /* DER_Encode.c */, + 0544AE9F0940939C00DD6C0B /* DER_Encode.h */, + 053BA322091C02B700A7007A /* libDER_config.h */, + 053BA323091C02B700A7007A /* libDER.h */, + 05E0E40509228A5E005F4693 /* DER_Digest.h */, + 05E0E40609228A5E005F4693 /* DER_Digest.c */, + 058F162D09250D0D009FA1C5 /* oids.c */, + 058F162E09250D0D009FA1C5 /* oids.h */, + ); + path = libDER; + sourceTree = ""; + }; + 053BA45C091FE5CE00A7007A /* Tests */ = { + isa = PBXGroup; + children = ( + 4C96C8D2113F4165005483E8 /* AppleMobilePersonalizedTicket.h */, + 4C96C8D3113F4165005483E8 /* DER_Ticket.c */, + 4C96C8D4113F4165005483E8 /* DER_Ticket.h */, + 4C96C8D5113F4165005483E8 /* parseTicket.c */, + 053BA460091FE60700A7007A /* parseCert.c */, + 058F1658092513A7009FA1C5 /* parseCrl.c */, + ); + path = Tests; + sourceTree = ""; + }; + 053BA466091FE62100A7007A /* libDERUtils */ = { + isa = PBXGroup; + children = ( + 053BA47B091FE7CC00A7007A /* libDERUtils.h */, + 053BA47C091FE7CC00A7007A /* libDERUtils.c */, + 053BA46E091FE6C100A7007A /* fileIo.c */, + 053BA46F091FE6C100A7007A /* fileIo.h */, + 058F15C00922B73F009FA1C5 /* printFields.h */, + 058F15C10922B73F009FA1C5 /* printFields.c */, + ); + path = libDERUtils; + sourceTree = ""; + }; + 058ECE5B09211AB20050AA30 /* External Libs */ = { + isa = PBXGroup; + children = ( + 4C96C8EC113F42C4005483E8 /* libcrypto.dylib */, + ); + name = "External Libs"; + sourceTree = ""; + }; + 1828EA9F14E334E200BE00C2 /* config */ = { + isa = PBXGroup; + children = ( + 1828EAA014E334E200BE00C2 /* base.xcconfig */, + 1828EAA114E334E200BE00C2 /* debug.xcconfig */, + 1828EAA214E334E200BE00C2 /* lib.xcconfig */, + 1828EAA314E334E200BE00C2 /* release.xcconfig */, + ); + path = config; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 053BA310091C00BF00A7007A /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 053BA324091C02B700A7007A /* DER_Decode.h in Headers */, + 053BA325091C02B700A7007A /* libDER_config.h in Headers */, + 053BA326091C02B700A7007A /* libDER.h in Headers */, + 053BA344091C089B00A7007A /* asn1Types.h in Headers */, + 053BA39A091C258100A7007A /* DER_CertCrl.h in Headers */, + 058ECD360920F5E30050AA30 /* DER_Keys.h in Headers */, + 05E0E40709228A5E005F4693 /* DER_Digest.h in Headers */, + 058F163209250D17009FA1C5 /* oids.h in Headers */, + 0544AEA10940939C00DD6C0B /* DER_Encode.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 053BA467091FE63E00A7007A /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 053BA471091FE6C100A7007A /* fileIo.h in Headers */, + 053BA47D091FE7CC00A7007A /* libDERUtils.h in Headers */, + 058F15C20922B73F009FA1C5 /* printFields.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 053BA313091C00BF00A7007A /* libDER */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4CD81A5D09BE1FD2000A9641 /* Build configuration list for PBXNativeTarget "libDER" */; + buildPhases = ( + 053BA310091C00BF00A7007A /* Headers */, + 053BA311091C00BF00A7007A /* Sources */, + 053BA312091C00BF00A7007A /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libDER; + productName = libDER; + productReference = 053BA314091C00BF00A7007A /* libDER.a */; + productType = "com.apple.product-type.library.static"; + }; + 053BA444091FE58C00A7007A /* parseCert */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4CD81A6509BE1FD2000A9641 /* Build configuration list for PBXNativeTarget "parseCert" */; + buildPhases = ( + 053BA442091FE58C00A7007A /* Sources */, + 053BA443091FE58C00A7007A /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 053BA459091FE59900A7007A /* PBXTargetDependency */, + 058ECC56091FF0090050AA30 /* PBXTargetDependency */, + ); + name = parseCert; + productName = parseCert; + productReference = 053BA445091FE58C00A7007A /* parseCert */; + productType = "com.apple.product-type.tool"; + }; + 053BA46A091FE63E00A7007A /* libDERUtils */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4CD81A6109BE1FD2000A9641 /* Build configuration list for PBXNativeTarget "libDERUtils" */; + buildPhases = ( + 053BA467091FE63E00A7007A /* Headers */, + 053BA468091FE63E00A7007A /* Sources */, + 053BA469091FE63E00A7007A /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libDERUtils; + productName = libDERUtils; + productReference = 053BA46B091FE63E00A7007A /* libDERUtils.a */; + productType = "com.apple.product-type.library.static"; + }; + 058F16530925135E009FA1C5 /* parseCrl */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4CD81A6909BE1FD2000A9641 /* Build configuration list for PBXNativeTarget "parseCrl" */; + buildPhases = ( + 058F16510925135E009FA1C5 /* Sources */, + 058F16520925135E009FA1C5 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 058F1676092523D8009FA1C5 /* PBXTargetDependency */, + 058F1678092523DD009FA1C5 /* PBXTargetDependency */, + ); + name = parseCrl; + productName = parseCrl; + productReference = 058F16540925135E009FA1C5 /* parseCrl */; + productType = "com.apple.product-type.tool"; + }; + 4C96C8CD113F4132005483E8 /* parseTicket */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4C96C8D8113F4165005483E8 /* Build configuration list for PBXNativeTarget "parseTicket" */; + buildPhases = ( + 4C96C8CB113F4132005483E8 /* Sources */, + 4C96C8CC113F4132005483E8 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 4C96C8E1113F4223005483E8 /* PBXTargetDependency */, + ); + name = parseTicket; + productName = parseTicket; + productReference = 4C96C8CE113F4132005483E8 /* parseTicket */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 053BA30A091C00A400A7007A /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0600; + }; + buildConfigurationList = 4CD81A7109BE1FD2000A9641 /* Build configuration list for PBXProject "libDER" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 053BA306091C00A400A7007A; + productRefGroup = 053BA315091C00BF00A7007A /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 053BA30F091C00B100A7007A /* World */, + 053BA313091C00BF00A7007A /* libDER */, + 053BA444091FE58C00A7007A /* parseCert */, + 053BA46A091FE63E00A7007A /* libDERUtils */, + 058F16530925135E009FA1C5 /* parseCrl */, + 4C96C8CD113F4132005483E8 /* parseTicket */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 053BA311091C00BF00A7007A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 053BA345091C089B00A7007A /* DER_Decode.c in Sources */, + 053BA399091C258100A7007A /* DER_CertCrl.c in Sources */, + 058ECD350920F5E30050AA30 /* DER_Keys.c in Sources */, + 05E0E40809228A5E005F4693 /* DER_Digest.c in Sources */, + 058F163109250D16009FA1C5 /* oids.c in Sources */, + 0544AEA20940939C00DD6C0B /* DER_Encode.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 053BA442091FE58C00A7007A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 053BA461091FE60700A7007A /* parseCert.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 053BA468091FE63E00A7007A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 053BA470091FE6C100A7007A /* fileIo.c in Sources */, + 053BA47E091FE7CC00A7007A /* libDERUtils.c in Sources */, + 058F15C30922B73F009FA1C5 /* printFields.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 058F16510925135E009FA1C5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 058F1659092513A7009FA1C5 /* parseCrl.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C96C8CB113F4132005483E8 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C96C8D6113F4165005483E8 /* DER_Ticket.c in Sources */, + 4C96C8D7113F4165005483E8 /* parseTicket.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 053BA317091C017E00A7007A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 053BA313091C00BF00A7007A /* libDER */; + targetProxy = 053BA316091C017E00A7007A /* PBXContainerItemProxy */; + }; + 053BA459091FE59900A7007A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 053BA313091C00BF00A7007A /* libDER */; + targetProxy = 053BA458091FE59900A7007A /* PBXContainerItemProxy */; + }; + 053BA463091FE60E00A7007A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 053BA444091FE58C00A7007A /* parseCert */; + targetProxy = 053BA462091FE60E00A7007A /* PBXContainerItemProxy */; + }; + 058ECC54091FF0000050AA30 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 053BA46A091FE63E00A7007A /* libDERUtils */; + targetProxy = 058ECC53091FF0000050AA30 /* PBXContainerItemProxy */; + }; + 058ECC56091FF0090050AA30 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 053BA46A091FE63E00A7007A /* libDERUtils */; + targetProxy = 058ECC55091FF0090050AA30 /* PBXContainerItemProxy */; + }; + 058F16680925224F009FA1C5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 058F16530925135E009FA1C5 /* parseCrl */; + targetProxy = 058F16670925224F009FA1C5 /* PBXContainerItemProxy */; + }; + 058F1676092523D8009FA1C5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 053BA313091C00BF00A7007A /* libDER */; + targetProxy = 058F1675092523D8009FA1C5 /* PBXContainerItemProxy */; + }; + 058F1678092523DD009FA1C5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 053BA46A091FE63E00A7007A /* libDERUtils */; + targetProxy = 058F1677092523DD009FA1C5 /* PBXContainerItemProxy */; + }; + 4C96C8DC113F4174005483E8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4C96C8CD113F4132005483E8 /* parseTicket */; + targetProxy = 4C96C8DB113F4174005483E8 /* PBXContainerItemProxy */; + }; + 4C96C8E1113F4223005483E8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 053BA313091C00BF00A7007A /* libDER */; + targetProxy = 4C96C8E0113F4223005483E8 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 4C96C8D0113F4132005483E8 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1828EAA114E334E200BE00C2 /* debug.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + 4C96C8D1113F4132005483E8 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1828EAA314E334E200BE00C2 /* release.xcconfig */; + buildSettings = { + }; + name = Release; + }; + 792E01120CBC0CE3007C00A0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1828EAA114E334E200BE00C2 /* debug.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Debug; + }; + 792E01130CBC0CE3007C00A0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1828EAA314E334E200BE00C2 /* release.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Release; + }; + 792E01140CBC0CE3007C00A0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1828EAA114E334E200BE00C2 /* debug.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Debug; + }; + 792E01150CBC0CE3007C00A0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1828EAA314E334E200BE00C2 /* release.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Release; + }; + 792E01160CBC0CE3007C00A0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1828EAA114E334E200BE00C2 /* debug.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + 792E01170CBC0CE3007C00A0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1828EAA314E334E200BE00C2 /* release.xcconfig */; + buildSettings = { + }; + name = Release; + }; + 792E01180CBC0CE3007C00A0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1828EAA114E334E200BE00C2 /* debug.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + 792E01190CBC0CE3007C00A0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1828EAA314E334E200BE00C2 /* release.xcconfig */; + buildSettings = { + }; + name = Release; + }; + 792E011A0CBC0CE3007C00A0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1828EAA114E334E200BE00C2 /* debug.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Debug; + }; + 792E011B0CBC0CE3007C00A0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1828EAA314E334E200BE00C2 /* release.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Release; + }; + 792E011C0CBC0CE3007C00A0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1828EAA214E334E200BE00C2 /* lib.xcconfig */; + buildSettings = { + CLANG_STATIC_ANALYZER_MODE = deep; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + RUN_CLANG_STATIC_ANALYZER = YES; + }; + name = Debug; + }; + 792E011D0CBC0CE3007C00A0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1828EAA214E334E200BE00C2 /* lib.xcconfig */; + buildSettings = { + CLANG_STATIC_ANALYZER_MODE = deep; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + RUN_CLANG_STATIC_ANALYZER = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4C96C8D8113F4165005483E8 /* Build configuration list for PBXNativeTarget "parseTicket" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4C96C8D0113F4132005483E8 /* Debug */, + 4C96C8D1113F4132005483E8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4CD81A5D09BE1FD2000A9641 /* Build configuration list for PBXNativeTarget "libDER" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 792E01120CBC0CE3007C00A0 /* Debug */, + 792E01130CBC0CE3007C00A0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4CD81A6109BE1FD2000A9641 /* Build configuration list for PBXNativeTarget "libDERUtils" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 792E01140CBC0CE3007C00A0 /* Debug */, + 792E01150CBC0CE3007C00A0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4CD81A6509BE1FD2000A9641 /* Build configuration list for PBXNativeTarget "parseCert" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 792E01160CBC0CE3007C00A0 /* Debug */, + 792E01170CBC0CE3007C00A0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4CD81A6909BE1FD2000A9641 /* Build configuration list for PBXNativeTarget "parseCrl" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 792E01180CBC0CE3007C00A0 /* Debug */, + 792E01190CBC0CE3007C00A0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4CD81A6D09BE1FD2000A9641 /* Build configuration list for PBXAggregateTarget "World" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 792E011A0CBC0CE3007C00A0 /* Debug */, + 792E011B0CBC0CE3007C00A0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4CD81A7109BE1FD2000A9641 /* Build configuration list for PBXProject "libDER" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 792E011C0CBC0CE3007C00A0 /* Debug */, + 792E011D0CBC0CE3007C00A0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 053BA30A091C00A400A7007A /* Project object */; +} diff --git a/libsecurity_keychain/libDER/libDER/DER_CertCrl.c b/Security/libsecurity_keychain/libDER/libDER/DER_CertCrl.c similarity index 90% rename from libsecurity_keychain/libDER/libDER/DER_CertCrl.c rename to Security/libsecurity_keychain/libDER/libDER/DER_CertCrl.c index aa996619..40aac585 100644 --- a/libsecurity_keychain/libDER/libDER/DER_CertCrl.c +++ b/Security/libsecurity_keychain/libDER/libDER/DER_CertCrl.c @@ -1,9 +1,30 @@ -/* Copyright (c) 2005-2009 Apple Inc. All Rights Reserved. */ +/* + * Copyright (c) 2005-2009,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + /* * DER_Cert.c - support for decoding X509 certificates * - * Created Nov. 4 2005 by Doug Mitchell. */ #include diff --git a/libsecurity_keychain/libDER/libDER/DER_CertCrl.h b/Security/libsecurity_keychain/libDER/libDER/DER_CertCrl.h similarity index 87% rename from libsecurity_keychain/libDER/libDER/DER_CertCrl.h rename to Security/libsecurity_keychain/libDER/libDER/DER_CertCrl.h index 20bb72b5..6bdab191 100644 --- a/libsecurity_keychain/libDER/libDER/DER_CertCrl.h +++ b/Security/libsecurity_keychain/libDER/libDER/DER_CertCrl.h @@ -1,9 +1,30 @@ -/* Copyright (c) 2005-2009 Apple Inc. All Rights Reserved. */ +/* + * Copyright (c) 2005-2009,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + /* * DER_CertCrl.h - support for decoding X509 certificates and CRLs * - * Created Nov. 4 2005 by dmitch */ #ifndef _DER_CERT_CRL_H_ diff --git a/libsecurity_keychain/libDER/libDER/DER_Decode.c b/Security/libsecurity_keychain/libDER/libDER/DER_Decode.c similarity index 99% rename from libsecurity_keychain/libDER/libDER/DER_Decode.c rename to Security/libsecurity_keychain/libDER/libDER/DER_Decode.c index 819c97c4..78df3f10 100644 --- a/libsecurity_keychain/libDER/libDER/DER_Decode.c +++ b/Security/libsecurity_keychain/libDER/libDER/DER_Decode.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2005-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/libDER/libDER/DER_Decode.h b/Security/libsecurity_keychain/libDER/libDER/DER_Decode.h similarity index 99% rename from libsecurity_keychain/libDER/libDER/DER_Decode.h rename to Security/libsecurity_keychain/libDER/libDER/DER_Decode.h index bfe65b43..827c2bcf 100644 --- a/libsecurity_keychain/libDER/libDER/DER_Decode.h +++ b/Security/libsecurity_keychain/libDER/libDER/DER_Decode.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2005-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/libDER/libDER/DER_Digest.c b/Security/libsecurity_keychain/libDER/libDER/DER_Digest.c similarity index 82% rename from libsecurity_keychain/libDER/libDER/DER_Digest.c rename to Security/libsecurity_keychain/libDER/libDER/DER_Digest.c index df4234ea..86e67c18 100644 --- a/libsecurity_keychain/libDER/libDER/DER_Digest.c +++ b/Security/libsecurity_keychain/libDER/libDER/DER_Digest.c @@ -1,9 +1,30 @@ -/* Copyright (c) 2005-2008,2010 Apple Inc. All Rights Reserved. */ +/* + * Copyright (c) 2005-2008,2010-2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + /* * DER_Digest.h - DER encode a DigestInfo * - * Created Nov. 9 2005 by dmitch */ #include diff --git a/Security/libsecurity_keychain/libDER/libDER/DER_Digest.h b/Security/libsecurity_keychain/libDER/libDER/DER_Digest.h new file mode 100644 index 00000000..68503a35 --- /dev/null +++ b/Security/libsecurity_keychain/libDER/libDER/DER_Digest.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2005-2008,2010-2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* + * DER_Digest.h - DER encode a DigestInfo + * + */ + +#ifndef _DER_DIGEST_H_ +#define _DER_DIGEST_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + * Create an encoded DigestInfo based on the specified SHA1 digest. + * The incoming digest must be 20 bytes long. + * + * Result is placed in caller's buffer, which must be at least of + * length DER_SHA1_DIGEST_INFO_LEN bytes. + * + * The *resultLen parameter is the available size in the result + * buffer on input, and the actual length of the encoded DigestInfo + * on output. + */ +#define DER_SHA1_DIGEST_LEN 20 +#define DER_SHA1_DIGEST_INFO_LEN 35 + +DERReturn DEREncodeSHA1DigestInfo( + const DERByte *sha1Digest, + DERSize sha1DigestLen, + DERByte *result, /* encoded result RETURNED here */ + DERSize *resultLen); /* IN/OUT */ + +#define DER_SHA256_DIGEST_LEN 32 +#define DER_SHA256_DIGEST_INFO_LEN 51 + +DERReturn DEREncodeSHA256DigestInfo( + const DERByte *sha256Digest, + DERSize sha256DigestLen, + DERByte *result, /* encoded result RETURNED here */ + DERSize *resultLen); /* IN/OUT */ + +/* + * Likewise, create an encoded DIgestInfo for specified MD5 or MD2 digest. + */ +#define DER_MD_DIGEST_LEN 16 +#define DER_MD_DIGEST_INFO_LEN 34 + +typedef enum { + WD_MD2 = 1, + WD_MD5 = 2 +} WhichDigest; + +DERReturn DEREncodeMDDigestInfo( + WhichDigest whichDigest, + const DERByte *mdDigest, + DERSize mdDigestLen, + DERByte *result, /* encoded result RETURNED here */ + DERSize *resultLen); /* IN/OUT */ + +/* max sizes you'll need in the general cases */ +#define DER_MAX_DIGEST_LEN DER_SHA256_DIGEST_LEN +#define DER_MAX_ENCODED_INFO_LEN DER_SHA256_DIGEST_INFO_LEN + +#ifdef __cplusplus +} +#endif + +#endif /* _DER_DIGEST_H_ */ + diff --git a/libsecurity_keychain/libDER/libDER/DER_Encode.c b/Security/libsecurity_keychain/libDER/libDER/DER_Encode.c similarity index 88% rename from libsecurity_keychain/libDER/libDER/DER_Encode.c rename to Security/libsecurity_keychain/libDER/libDER/DER_Encode.c index e1d222f0..9b694617 100644 --- a/libsecurity_keychain/libDER/libDER/DER_Encode.c +++ b/Security/libsecurity_keychain/libDER/libDER/DER_Encode.c @@ -1,9 +1,30 @@ -/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */ +/* + * Copyright (c) 2005-2007,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + /* * DER_Encode.h - DER encoding routines * - * Created Dec. 2 2005 by dmitch */ #include @@ -159,6 +180,8 @@ DERReturn DEREncodeItem( bytesLeft -= itemLen; DERMemmove(currPtr, src, length); + (void) bytesLeft; + return DR_Success; } diff --git a/Security/libsecurity_keychain/libDER/libDER/DER_Encode.h b/Security/libsecurity_keychain/libDER/libDER/DER_Encode.h new file mode 100644 index 00000000..6dc3d636 --- /dev/null +++ b/Security/libsecurity_keychain/libDER/libDER/DER_Encode.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2005-2007,2011,2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* + * DER_Encode.h - DER encoding routines + * + */ + +#ifndef _DER_ENCODE_H_ +#define _DER_ENCODE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + * Max size of an encoded item given its length. + * This includes a possible leading zero prepended to a signed integer + * (see DER_ENC_SIGNED_INT below). + */ +#define DER_MAX_ENCODED_SIZE(len) \ + ( 1 + /* tag */ \ + 5 + /* max length */ \ + 1 + /* possible prepended zero */ \ + len) + +/* calculate size of encoded length */ +DERSize DERLengthOfLength( + DERSize length); + +/* encode length */ +DERReturn DEREncodeLength( + DERSize length, + DERByte *buf, /* encoded length goes here */ + DERSize *inOutLen); /* IN/OUT */ + +/* calculate size of encoded length */ +DERSize DERLengthOfItem( + DERTag tag, + DERSize length); + +/* encode item */ +DERReturn DEREncodeItem( + DERTag tag, + DERSize length, + const DERByte *src, + DERByte *derOut, /* encoded item goes here */ + DERSize *inOutLen); /* IN/OUT */ + +/* + * Per-item encode options. + */ + +/* explicit default, no options */ +#define DER_ENC_NO_OPTS 0x0000 + +/* signed integer check: if incoming m.s. bit is 1, prepend a zero */ +#define DER_ENC_SIGNED_INT 0x0100 + +/* DERItem contains fully encoded item - copy, don't encode */ +#define DER_ENC_WRITE_DER 0x0200 + + +/* + * High-level sequence or set encode support. + * + * The outgoing sequence is expressed as an array of DERItemSpecs, each + * of which corresponds to one item in the encoded sequence. + * + * Normally the tag of the encoded item comes from the associated + * DERItemSpec, and the content comes from the DERItem whose address is + * the src arg plus the offset value in the associated DERItemSpec. + * + * If the DER_ENC_WRITE_DER option is true for a given DERItemSpec then + * no per-item encoding is done; the DER - with tag, length, and content - + * is taken en masse from the associated DERItem. + */ +DERReturn DEREncodeSequence( + DERTag topTag, /* ASN1_CONSTR_SEQUENCE, ASN1_CONSTR_SET */ + const void *src, /* generally a ptr to a struct full of + * DERItems */ + DERShort numItems, /* size of itemSpecs[] */ + const DERItemSpec *itemSpecs, + DERByte *derOut, /* encoded data written here */ + DERSize *inOutLen); /* IN/OUT */ + +/* precalculate the length of an encoded sequence. */ +DERSize DERLengthOfEncodedSequence( + DERTag topTag, /* ASN1_CONSTR_SEQUENCE, ASN1_CONSTR_SET */ + const void *src, /* generally a ptr to a struct full of + * DERItems */ + DERShort numItems, /* size of itemSpecs[] */ + const DERItemSpec *itemSpecs); + + +#ifdef __cplusplus +} +#endif + +#endif /* _DER_ENCODE_H_ */ + diff --git a/libsecurity_keychain/libDER/libDER/DER_Keys.c b/Security/libsecurity_keychain/libDER/libDER/DER_Keys.c similarity index 80% rename from libsecurity_keychain/libDER/libDER/DER_Keys.c rename to Security/libsecurity_keychain/libDER/libDER/DER_Keys.c index 82e96fe7..0d41496f 100644 --- a/libsecurity_keychain/libDER/libDER/DER_Keys.c +++ b/Security/libsecurity_keychain/libDER/libDER/DER_Keys.c @@ -1,9 +1,30 @@ -/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */ +/* + * Copyright (c) 2005-2007,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + /* * DER_Cert.c - support for decoding RSA keys * - * Created Nov. 8 2005 by Doug Mitchell. */ #include diff --git a/Security/libsecurity_keychain/libDER/libDER/DER_Keys.h b/Security/libsecurity_keychain/libDER/libDER/DER_Keys.h new file mode 100644 index 00000000..849974fc --- /dev/null +++ b/Security/libsecurity_keychain/libDER/libDER/DER_Keys.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2005-2007,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* + * DER_Keys.h - support for decoding RSA keys + * + */ + +#ifndef _DER_KEYS_H_ +#define _DER_KEYS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* Algorithm Identifier components */ +typedef struct { + DERItem oid; /* OID */ + DERItem params; /* ASN_ANY, optional, DER_DEC_SAVE_DER */ +} DERAlgorithmId; + +/* DERItemSpecs to decode into a DERAlgorithmId */ +extern const DERItemSpec DERAlgorithmIdItemSpecs[]; +extern const DERSize DERNumAlgorithmIdItemSpecs; + +/* X509 SubjectPublicKeyInfo */ +typedef struct { + DERItem algId; /* sequence, DERAlgorithmId */ + DERItem pubKey; /* BIT STRING */ +} DERSubjPubKeyInfo; + +/* DERItemSpecs to decode into a DERSubjPubKeyInfo */ +extern const DERItemSpec DERSubjPubKeyInfoItemSpecs[]; +extern const DERSize DERNumSubjPubKeyInfoItemSpecs; + +/* + * RSA public key in PKCS1 format; this is inside the BIT_STRING in + * DERSubjPubKeyInfo.pubKey. + */ +typedef struct { + DERItem modulus; /* n - INTEGER */ + DERItem pubExponent; /* e - INTEGER */ +} DERRSAPubKeyPKCS1; + +/* DERItemSpecs to decode/encode into/from a DERRSAPubKeyPKCS1 */ +extern const DERItemSpec DERRSAPubKeyPKCS1ItemSpecs[]; +extern const DERSize DERNumRSAPubKeyPKCS1ItemSpecs; + +/* + * RSA public key in custom (to this library) format, including + * the reciprocal. All fields are integers. + */ +typedef struct { + DERItem modulus; /* n */ + DERItem reciprocal; /* reciprocal of modulus */ + DERItem pubExponent; /* e */ +} DERRSAPubKeyApple; + +/* DERItemSpecs to decode/encode into/from a DERRSAPubKeyApple */ +extern const DERItemSpec DERRSAPubKeyAppleItemSpecs[]; +extern const DERSize DERNumRSAPubKeyAppleItemSpecs; + +/* + * RSA Private key, PKCS1 format, CRT option. + * All fields are integers. + */ +typedef struct { + DERItem p; /* p * q = n */ + DERItem q; + DERItem dp; /* d mod (p-1) */ + DERItem dq; /* d mod (q-1) */ + DERItem qInv; +} DERRSAPrivKeyCRT; + +/* DERItemSpecs to decode into a DERRSAPrivKeyCRT */ +extern const DERItemSpec DERRSAPrivKeyCRTItemSpecs[]; +extern const DERSize DERNumRSAPrivKeyCRTItemSpecs; + +/* Fully formed RSA key pair, for generating a PKCS1 private key */ +typedef struct { + DERItem version; + DERItem n; /* modulus */ + DERItem e; /* public exponent */ + DERItem d; /* private exponent */ + DERItem p; /* n = p*q */ + DERItem q; + DERItem dp; /* d mod (p-1) */ + DERItem dq; /* d mod (q-1) */ + DERItem qInv; /* q^(-1) mod p */ +} DERRSAKeyPair; + +/* DERItemSpecs to encode a DERRSAKeyPair */ +extern const DERItemSpec DERRSAKeyPairItemSpecs[]; +extern const DERSize DERNumRSAKeyPairItemSpecs; + +#ifdef __cplusplus +} +#endif + +#endif /* _DER_KEYS_H_ */ + diff --git a/Security/libsecurity_keychain/libDER/libDER/asn1Types.h b/Security/libsecurity_keychain/libDER/libDER/asn1Types.h new file mode 100644 index 00000000..5275af3c --- /dev/null +++ b/Security/libsecurity_keychain/libDER/libDER/asn1Types.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2005-2007,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* + * asn1Types.h - ASN.1/DER #defines - strictly hard coded per the real world + * + */ + +#ifndef _ASN1_TYPES_H_ +#define _ASN1_TYPES_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* copied from libsecurity_asn1 project */ + +#define ASN1_BOOLEAN 0x01 +#define ASN1_INTEGER 0x02 +#define ASN1_BIT_STRING 0x03 +#define ASN1_OCTET_STRING 0x04 +#define ASN1_NULL 0x05 +#define ASN1_OBJECT_ID 0x06 +#define ASN1_OBJECT_DESCRIPTOR 0x07 +/* External type and instance-of type 0x08 */ +#define ASN1_REAL 0x09 +#define ASN1_ENUMERATED 0x0a +#define ASN1_EMBEDDED_PDV 0x0b +#define ASN1_UTF8_STRING 0x0c +/* 0x0d */ +/* 0x0e */ +/* 0x0f */ +#define ASN1_SEQUENCE 0x10 +#define ASN1_SET 0x11 +#define ASN1_NUMERIC_STRING 0x12 +#define ASN1_PRINTABLE_STRING 0x13 +#define ASN1_T61_STRING 0x14 +#define ASN1_VIDEOTEX_STRING 0x15 +#define ASN1_IA5_STRING 0x16 +#define ASN1_UTC_TIME 0x17 +#define ASN1_GENERALIZED_TIME 0x18 +#define ASN1_GRAPHIC_STRING 0x19 +#define ASN1_VISIBLE_STRING 0x1a +#define ASN1_GENERAL_STRING 0x1b +#define ASN1_UNIVERSAL_STRING 0x1c +/* 0x1d */ +#define ASN1_BMP_STRING 0x1e +#define ASN1_HIGH_TAG_NUMBER 0x1f +#define ASN1_TELETEX_STRING ASN1_T61_STRING + +#ifdef DER_MULTIBYTE_TAGS + +#define ASN1_TAG_MASK ((DERTag)~0) +#define ASN1_TAGNUM_MASK ((DERTag)~((DERTag)7 << (sizeof(DERTag) * 8 - 3))) + +#define ASN1_METHOD_MASK ((DERTag)1 << (sizeof(DERTag) * 8 - 3)) +#define ASN1_PRIMITIVE ((DERTag)0 << (sizeof(DERTag) * 8 - 3)) +#define ASN1_CONSTRUCTED ((DERTag)1 << (sizeof(DERTag) * 8 - 3)) + +#define ASN1_CLASS_MASK ((DERTag)3 << (sizeof(DERTag) * 8 - 2)) +#define ASN1_UNIVERSAL ((DERTag)0 << (sizeof(DERTag) * 8 - 2)) +#define ASN1_APPLICATION ((DERTag)1 << (sizeof(DERTag) * 8 - 2)) +#define ASN1_CONTEXT_SPECIFIC ((DERTag)2 << (sizeof(DERTag) * 8 - 2)) +#define ASN1_PRIVATE ((DERTag)3 << (sizeof(DERTag) * 8 - 2)) + +#else /* DER_MULTIBYTE_TAGS */ + +#define ASN1_TAG_MASK 0xff +#define ASN1_TAGNUM_MASK 0x1f +#define ASN1_METHOD_MASK 0x20 +#define ASN1_PRIMITIVE 0x00 +#define ASN1_CONSTRUCTED 0x20 + +#define ASN1_CLASS_MASK 0xc0 +#define ASN1_UNIVERSAL 0x00 +#define ASN1_APPLICATION 0x40 +#define ASN1_CONTEXT_SPECIFIC 0x80 +#define ASN1_PRIVATE 0xc0 + +#endif /* !DER_MULTIBYTE_TAGS */ + +/* sequence and set appear as the following */ +#define ASN1_CONSTR_SEQUENCE (ASN1_CONSTRUCTED | ASN1_SEQUENCE) +#define ASN1_CONSTR_SET (ASN1_CONSTRUCTED | ASN1_SET) + +#ifdef __cplusplus +} +#endif + +#endif /* _ASN1_TYPES_H_ */ + diff --git a/Security/libsecurity_keychain/libDER/libDER/libDER.h b/Security/libsecurity_keychain/libDER/libDER/libDER.h new file mode 100644 index 00000000..cde53fe5 --- /dev/null +++ b/Security/libsecurity_keychain/libDER/libDER/libDER.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2005-2007,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* + * libDER.h - main header for libDER, a ROM-capable DER decoding library. + * + */ + +#ifndef _LIB_DER_H_ +#define _LIB_DER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +/* + * Error returns generated by this library. + */ +typedef enum { + DR_Success, + DR_EndOfSequence, /* end of sequence or set */ + DR_UnexpectedTag, /* unexpected tag found while decoding */ + DR_DecodeError, /* misc. decoding error (badly formatted DER) */ + DR_Unimplemented, /* function not implemented in this configuration */ + DR_IncompleteSeq, /* incomplete sequence */ + DR_ParamErr, /* incoming parameter error */ + DR_BufOverflow /* buffer overflow */ + /* etc. */ +} DERReturn; + +/* + * Primary representation of a block of memory. + */ +typedef struct { + DERByte *data; + DERSize length; +} DERItem; + +/* + * The structure of a sequence during decode or encode is expressed as + * an array of DERItemSpecs. While decoding or encoding a sequence, + * each item in the sequence corresponds to one DERItemSpec. + */ +typedef struct { + DERSize offset; /* offset of destination DERItem */ + DERTag tag; /* DER tag */ + DERShort options; /* DER_DEC_xxx or DER_ENC_xxx */ +} DERItemSpec; + +/* + * Macro to obtain offset of a DERDecodedInfo within a struct. + * FIXME this is going to need reworking to avoid compiler warnings + * on 64-bit compiles. It'll work OK as long as an offset can't be larger + * than a DERSize, but the cast from a pointer to a DERSize may + * provoke compiler warnings. + */ +#define DER_OFFSET(type, field) ((DERSize)(&((type *)0)->field)) + +#ifdef __cplusplus +} +#endif + +#endif /* _LIB_DER_H_ */ + diff --git a/Security/libsecurity_keychain/libDER/libDER/libDER_config.h b/Security/libsecurity_keychain/libDER/libDER/libDER_config.h new file mode 100644 index 00000000..e02fdfdb --- /dev/null +++ b/Security/libsecurity_keychain/libDER/libDER/libDER_config.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2005-2007,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@ + */ + + +/* + * libDER_config.h - platform dependent #defines and typedefs for libDER + * + */ + +#ifndef _LIB_DER_CONFIG_H_ +#define _LIB_DER_CONFIG_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Basic data types: unsigned 8-bit integer, unsigned 32-bit integer + */ +typedef uint8_t DERByte; +typedef uint16_t DERShort; +typedef size_t DERSize; + +/* + * Use these #defines of you have memset, memmove, and memcmp; else + * write your own equivalents. + */ + +#define DERMemset(ptr, c, len) memset(ptr, c, len) +#define DERMemmove(dst, src, len) memmove(dst, src, len) +#define DERMemcmp(b1, b2, len) memcmp(b1, b2, len) + + +/*** + *** Compile time options to trim size of the library. + ***/ + +/* enable general DER encode */ +#define DER_ENCODE_ENABLE 1 + +/* enable general DER decode */ +#define DER_DECODE_ENABLE 1 + +#ifndef DER_MULTIBYTE_TAGS +/* enable multibyte tag support. */ +#define DER_MULTIBYTE_TAGS 1 +#endif + +#ifndef DER_TAG_SIZE +/* Iff DER_MULTIBYTE_TAGS is 1 this is the sizeof(DERTag) in bytes. Note that + tags are still encoded and decoded from a minimally encoded DER + represantation. This value determines how big each DERItemSpecs is, we + choose 2 since that makes DERItemSpecs 8 bytes wide. */ +#define DER_TAG_SIZE 2 +#endif + + +/* ---------------------- Do not edit below this line ---------------------- */ + +/* + * Logical representation of a tag (the encoded representation is always in + * the minimal number of bytes). The top 3 bits encode class and method + * The remaining bits encode the tag value. To obtain smaller DERItemSpecs + * sizes, choose the smallest type that fits your needs. Most standard ASN.1 + * usage only needs single byte tags, but ocasionally custom applications + * require a larger tag namespace. + */ +#if DER_MULTIBYTE_TAGS + +#if DER_TAG_SIZE == 1 +typedef uint8_t DERTag; +#elif DER_TAG_SIZE == 2 +typedef uint16_t DERTag; +#elif DER_TAG_SIZE == 4 +typedef uint32_t DERTag; +#elif DER_TAG_SIZE == 8 +typedef uint64_t DERTag; +#else +#error DER_TAG_SIZE invalid +#endif + +#else /* DER_MULTIBYTE_TAGS */ +typedef DERByte DERTag; +#endif /* !DER_MULTIBYTE_TAGS */ + +#ifdef __cplusplus +} +#endif + +#endif /* _LIB_DER_CONFIG_H_ */ diff --git a/libsecurity_keychain/libDER/libDER/oids.c b/Security/libsecurity_keychain/libDER/libDER/oids.c similarity index 81% rename from libsecurity_keychain/libDER/libDER/oids.c rename to Security/libsecurity_keychain/libDER/libDER/oids.c index 8f407719..d35f8fcd 100644 --- a/libsecurity_keychain/libDER/libDER/oids.c +++ b/Security/libsecurity_keychain/libDER/libDER/oids.c @@ -1,27 +1,48 @@ -/* Copyright (c) 2005-2009 Apple Inc. All Rights Reserved. */ +/* + * Copyright (c) 2005-2009,2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + /* - * oids.c - OID consts + * oids.c - OID consts * - * Created Nov. 11 2005 by dmitch */ #include #include #define OID_ISO_CCITT_DIR_SERVICE 85 -#define OID_DS OID_ISO_CCITT_DIR_SERVICE -#define OID_ATTR_TYPE OID_DS, 4 -#define OID_EXTENSION OID_DS, 29 +#define OID_DS OID_ISO_CCITT_DIR_SERVICE +#define OID_ATTR_TYPE OID_DS, 4 +#define OID_EXTENSION OID_DS, 29 #define OID_ISO_STANDARD 40 -#define OID_ISO_MEMBER 42 +#define OID_ISO_MEMBER 42 #define OID_US OID_ISO_MEMBER, 134, 72 #define OID_ISO_IDENTIFIED_ORG 43 #define OID_OSINET OID_ISO_IDENTIFIED_ORG, 4 #define OID_GOSIP OID_ISO_IDENTIFIED_ORG, 5 #define OID_DOD OID_ISO_IDENTIFIED_ORG, 6 -#define OID_OIW OID_ISO_IDENTIFIED_ORG, 14 +#define OID_OIW OID_ISO_IDENTIFIED_ORG, 14 /* From the PKCS Standards */ #define OID_RSA OID_US, 134, 247, 13 @@ -80,7 +101,7 @@ /* ETSI */ #define OID_ETSI 0x04, 0x00 #define OID_ETSI_QCS 0x04, 0x00, 0x8E, 0x46, 0x01 - + #define OID_OIW_SECSIG OID_OIW, 3 #define OID_OIW_ALGORITHM OID_OIW_SECSIG, 2 @@ -91,11 +112,11 @@ /* * Apple-specific OID bases */ - -/* + +/* * apple OBJECT IDENTIFIER ::= * { iso(1) member-body(2) US(840) 113635 } - * + * * BER = 06 06 2A 86 48 86 F7 63 */ #define APPLE_OID OID_US, 0x86, 0xf7, 0x63 @@ -113,8 +134,8 @@ * { appleDataSecurity 1 } * { 1 2 840 113635 100 1 } * - * BER = 06 08 2A 86 48 86 F7 63 64 01 - */ + * BER = 06 08 2A 86 48 86 F7 63 64 01 + */ #define APPLE_TP_OID APPLE_ADS_OID, 1 /* @@ -127,7 +148,7 @@ #define APPLE_ALG_OID APPLE_ADS_OID, 2 /* - * appleDotMacCertificate OBJECT IDENTIFIER ::= + * appleDotMacCertificate OBJECT IDENTIFIER ::= * { appleDataSecurity 3 } * { 1 2 840 113635 100 3 } */ @@ -136,7 +157,7 @@ /* * Basis of Policy OIDs for .mac TP requests * - * dotMacCertificateRequest OBJECT IDENTIFIER ::= + * dotMacCertificateRequest OBJECT IDENTIFIER ::= * { appleDotMacCertificate 1 } * { 1 2 840 113635 100 3 1 } */ @@ -145,7 +166,7 @@ /* * Basis of .mac Certificate Extensions * - * dotMacCertificateExtension OBJECT IDENTIFIER ::= + * dotMacCertificateExtension OBJECT IDENTIFIER ::= * { appleDotMacCertificate 2 } * { 1 2 840 113635 100 3 2 } */ @@ -154,7 +175,7 @@ /* * Basis of .mac Certificate request OID/value identitifiers * - * dotMacCertificateRequestValues OBJECT IDENTIFIER ::= + * dotMacCertificateRequestValues OBJECT IDENTIFIER ::= * { appleDotMacCertificate 3 } * { 1 2 840 113635 100 3 3 } */ @@ -163,15 +184,15 @@ /* * Basis of Apple-specific extended key usages * - * appleExtendedKeyUsage OBJECT IDENTIFIER ::= + * appleExtendedKeyUsage OBJECT IDENTIFIER ::= * { appleDataSecurity 4 } * { 1 2 840 113635 100 4 } */ #define APPLE_EKU_OID APPLE_ADS_OID, 4 -/* +/* * Basis of Apple Code Signing extended key usages - * appleCodeSigning OBJECT IDENTIFIER ::= + * appleCodeSigning OBJECT IDENTIFIER ::= * { appleExtendedKeyUsage 1 } * { 1 2 840 113635 100 4 1} */ @@ -184,7 +205,7 @@ /* * Basis of Apple-specific Certificate Policy IDs. - * appleCertificatePolicies OBJECT IDENTIFIER ::= + * appleCertificatePolicies OBJECT IDENTIFIER ::= * { appleDataSecurity 5 } * { 1 2 840 113635 100 5 } */ @@ -204,17 +225,19 @@ #define APPLE_CERT_EXT_INTERMEDIATE_MARKER APPLE_CERT_EXT, 2 /* Apple Apple ID Intermediate Marker */ #define APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID APPLE_CERT_EXT_INTERMEDIATE_MARKER, 3 -/* - * Apple Apple ID Intermediate Marker (New subCA, no longer shared with push notification server cert issuer +/* + * Apple Apple ID Intermediate Marker (New subCA, no longer shared with push notification server cert issuer * - * appleCertificateExtensionAppleIDIntermediate ::= - * { appleCertificateExtensionIntermediateMarker 7 } + * appleCertificateExtensionAppleIDIntermediate ::= + * { appleCertificateExtensionIntermediateMarker 7 } * { 1 2 840 113635 100 6 2 7 } */ #define APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID_2 APPLE_CERT_EXT_INTERMEDIATE_MARKER, 7 #define APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID_SYSTEM_INTEGRATION_2 APPLE_CERT_EXT_INTERMEDIATE_MARKER, 10 +#define APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID_SYSTEM_INTEGRATION_G3 APPLE_CERT_EXT_INTERMEDIATE_MARKER, 13 + #define APPLE_CERT_EXT_APPLE_PUSH_MARKER APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID, 2 @@ -226,15 +249,21 @@ /* iPhone Provisioning Profile Signing leaf - on the intermediate marker arc? */ #define APPLE_PROVISIONING_PROFILE_OID APPLE_CERT_EXT_INTERMEDIATE_MARKER, 1 /* iPhone Application Signing leaf */ -#define APPLE_APP_SIGINING_OID APPLE_CERT_EXTENSION_CODESIGNING, 3 -/* Shoebox card signing leaf */ +#define APPLE_APP_SIGNING_OID APPLE_CERT_EXTENSION_CODESIGNING, 3 + #define APPLE_INSTALLER_PACKAGE_SIGNING_EXTERNAL_OID APPLE_CERT_EXTENSION_CODESIGNING, 16 #define APPLE_ESCROW_ARC APPLE_CERT_EXT, 23 #define APPLE_ESCROW_POLICY_OID APPLE_ESCROW_ARC, 1 -#define APPLE_CERT_EXTENSTION_APPLE_ID_VALIDATION_RECORD_SIGNING APPLE_CERT_EXT, 25 +#define APPLE_CERT_EXT_APPLE_ID_VALIDATION_RECORD_SIGNING APPLE_CERT_EXT, 25 + +#define APPLE_SERVER_AUTHENTICATION APPLE_CERT_EXT, 27 +#define APPLE_CERT_EXT_APPLE_SERVER_AUTHENTICATION APPLE_SERVER_AUTHENTICATION, 1 +#define APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLE_SERVER_AUTHENTICATION APPLE_CERT_EXT_INTERMEDIATE_MARKER, 12 + +#define APPLE_CERT_EXT_APPLE_SMP_ENCRYPTION APPLE_CERT_EXT, 30 /* * Netscape OIDs. @@ -333,7 +362,7 @@ const DERItem sizeof(_oidSha224) }; /* Extension OIDs. */ -static const DERByte +__unused static const DERByte _oidSubjectKeyIdentifier[] = { OID_EXTENSION, 14 }, _oidKeyUsage[] = { OID_EXTENSION, 15 }, _oidPrivateKeyUsagePeriod[] = { OID_EXTENSION, 16 }, @@ -350,7 +379,7 @@ static const DERByte _oidAnyExtendedKeyUsage[] = { OID_EXTENSION, 37, 0 }, _oidInhibitAnyPolicy[] = { OID_EXTENSION, 54 }, _oidAuthorityInfoAccess[] = { OID_PE, 1 }, - _oidSubjectInfoAccess[] = { OID_PE, 11 }, + _oidSubjectInfoAccess[] = { OID_PE, 11 }, _oidAdOCSP[] = { OID_AD_OCSP }, _oidAdCAIssuer[] = { OID_AD_CAISSUERS }, _oidNetscapeCertType[] = { NETSCAPE_CERT_EXTEN, 1 }, @@ -380,7 +409,7 @@ static const DERByte _oidExtendedKeyUsageNetscapeSGC[] = { NETSCAPE_CERT_POLICY, 1 }, _oidAppleSecureBootCertSpec[] = { APPLE_SBOOT_CERT_EXTEN_SBOOT_SPEC_OID }, _oidAppleProvisioningProfile[] = {APPLE_PROVISIONING_PROFILE_OID }, - _oidAppleApplicationSigning[] = { APPLE_APP_SIGINING_OID }, + _oidAppleApplicationSigning[] = { APPLE_APP_SIGNING_OID }, _oidAppleInstallerPackagingSigningExternal[] = { APPLE_INSTALLER_PACKAGE_SIGNING_EXTERNAL_OID }, _oidAppleExtendedKeyUsageAppleID[] = { APPLE_EKU_APPLE_ID }, _oidAppleExtendedKeyUsageShoebox[] = { APPLE_EKU_SHOEBOX }, @@ -389,13 +418,17 @@ static const DERByte _oidAppleIntmMarkerAppleID[] = { APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID }, _oidAppleIntmMarkerAppleID2[] = {APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID_2 }, _oidApplePushServiceClient[] = { APPLE_CERT_EXT_APPLE_PUSH_MARKER, 2 }, - _oidApplePolicyMobileStore[] = { APPLE_CERT_POLICY_MOBILE_STORE }, - _oidApplePolicyTestMobileStore[] = { APPLE_CERT_POLICY_TEST_MOBILE_STORE }, - _oidApplePolicyEscrowService[] = { APPLE_ESCROW_POLICY_OID }, - _oidAppleCertExtensionAppleIDRecordValidationSigning[] = { APPLE_CERT_EXTENSTION_APPLE_ID_VALIDATION_RECORD_SIGNING }, - _oidAppleIntmMarkerAppleSystemIntg2[] = {APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID_SYSTEM_INTEGRATION_2}; - -const DERItem + _oidApplePolicyMobileStore[] = { APPLE_CERT_POLICY_MOBILE_STORE }, + _oidApplePolicyTestMobileStore[] = { APPLE_CERT_POLICY_TEST_MOBILE_STORE }, + _oidApplePolicyEscrowService[] = { APPLE_ESCROW_POLICY_OID }, + _oidAppleCertExtensionAppleIDRecordValidationSigning[] = { APPLE_CERT_EXT_APPLE_ID_VALIDATION_RECORD_SIGNING }, + _oidAppleIntmMarkerAppleSystemIntg2[] = {APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID_SYSTEM_INTEGRATION_2}, + _oidAppleIntmMarkerAppleSystemIntgG3[] = {APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID_SYSTEM_INTEGRATION_G3}, + _oidAppleCertExtAppleSMPEncryption[] = {APPLE_CERT_EXT_APPLE_SMP_ENCRYPTION}, + _oidAppleCertExtAppleServerAuthentication[] = {APPLE_CERT_EXT_APPLE_SERVER_AUTHENTICATION}, + _oidAppleIntmMarkerAppleServerAuthentication[] = {APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLE_SERVER_AUTHENTICATION}; + +__unused const DERItem oidSubjectKeyIdentifier = { (DERByte *)_oidSubjectKeyIdentifier, sizeof(_oidSubjectKeyIdentifier) }, oidKeyUsage = { (DERByte *)_oidKeyUsage, @@ -428,7 +461,7 @@ const DERItem sizeof(_oidInhibitAnyPolicy) }, oidAuthorityInfoAccess = { (DERByte *)_oidAuthorityInfoAccess, sizeof(_oidAuthorityInfoAccess) }, - oidSubjectInfoAccess = { (DERByte *)_oidSubjectInfoAccess, + oidSubjectInfoAccess = { (DERByte *)_oidSubjectInfoAccess, sizeof(_oidSubjectInfoAccess) }, oidAdOCSP = { (DERByte *)_oidAdOCSP, sizeof(_oidAdOCSP) }, @@ -462,7 +495,7 @@ const DERItem sizeof(_oidDescription) }, oidEmailAddress = { (DERByte *)_oidEmailAddress, sizeof(_oidEmailAddress) }, - oidFriendlyName = { (DERByte *)_oidFriendlyName, + oidFriendlyName = { (DERByte *)_oidFriendlyName, sizeof(_oidFriendlyName) }, oidLocalKeyId = { (DERByte *)_oidLocalKeyId, sizeof(_oidLocalKeyId) }, @@ -494,7 +527,7 @@ const DERItem sizeof(_oidAppleExtendedKeyUsageAppleID) }, oidAppleExtendedKeyUsageShoebox = { (DERByte *)_oidAppleExtendedKeyUsageShoebox, sizeof(_oidAppleExtendedKeyUsageShoebox) }, - oidAppleExtendedKeyUsageProfileSigning + oidAppleExtendedKeyUsageProfileSigning = { (DERByte *)_oidAppleExtendedKeyUsageProfileSigning, sizeof(_oidAppleExtendedKeyUsageProfileSigning) }, oidAppleExtendedKeyUsageQAProfileSigning @@ -506,16 +539,26 @@ const DERItem sizeof(_oidAppleIntmMarkerAppleID2) }, oidApplePushServiceClient = { (DERByte *)_oidAppleIntmMarkerAppleID2, sizeof(_oidAppleIntmMarkerAppleID2) }, - oidApplePolicyMobileStore = { (DERByte *)_oidApplePolicyMobileStore, - sizeof(_oidApplePolicyMobileStore)}, - oidApplePolicyTestMobileStore = { (DERByte *)_oidApplePolicyTestMobileStore, - sizeof(_oidApplePolicyTestMobileStore)}, - oidApplePolicyEscrowService = { (DERByte *)_oidApplePolicyEscrowService, - sizeof(_oidApplePolicyEscrowService)}, - oidAppleCertExtensionAppleIDRecordValidationSigning = { (DERByte *)_oidAppleCertExtensionAppleIDRecordValidationSigning, - sizeof(_oidAppleCertExtensionAppleIDRecordValidationSigning)}, - oidAppleIntmMarkerAppleSystemIntg2 = { (DERByte *) _oidAppleIntmMarkerAppleSystemIntg2, - sizeof(_oidAppleIntmMarkerAppleSystemIntg2)}; + oidApplePolicyMobileStore = { (DERByte *)_oidApplePolicyMobileStore, + sizeof(_oidApplePolicyMobileStore)}, + oidApplePolicyTestMobileStore = { (DERByte *)_oidApplePolicyTestMobileStore, + sizeof(_oidApplePolicyTestMobileStore)}, + oidApplePolicyEscrowService = { (DERByte *)_oidApplePolicyEscrowService, + sizeof(_oidApplePolicyEscrowService)}, + oidAppleCertExtensionAppleIDRecordValidationSigning = { (DERByte *)_oidAppleCertExtensionAppleIDRecordValidationSigning, + sizeof(_oidAppleCertExtensionAppleIDRecordValidationSigning)}, + oidAppleIntmMarkerAppleSystemIntg2 = { (DERByte *) _oidAppleIntmMarkerAppleSystemIntg2, + sizeof(_oidAppleIntmMarkerAppleSystemIntg2)}, + oidAppleIntmMarkerAppleSystemIntgG3 = { (DERByte *) _oidAppleIntmMarkerAppleSystemIntgG3, + sizeof(_oidAppleIntmMarkerAppleSystemIntgG3)}, + oidAppleCertExtAppleSMPEncryption = { (DERByte *)_oidAppleCertExtAppleSMPEncryption, + sizeof(_oidAppleCertExtAppleSMPEncryption)}, + oidAppleCertExtAppleServerAuthentication + = { (DERByte *)_oidAppleCertExtAppleServerAuthentication, + sizeof(_oidAppleCertExtAppleServerAuthentication) }, + oidAppleIntmMarkerAppleServerAuthentication + = { (DERByte *)_oidAppleIntmMarkerAppleServerAuthentication, + sizeof(_oidAppleIntmMarkerAppleServerAuthentication) }; bool DEROidCompare(const DERItem *oid1, const DERItem *oid2) { diff --git a/Security/libsecurity_keychain/libDER/libDER/oids.h b/Security/libsecurity_keychain/libDER/libDER/oids.h new file mode 100644 index 00000000..33ddabca --- /dev/null +++ b/Security/libsecurity_keychain/libDER/libDER/oids.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2005-2009,2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* + * oids.h - declaration of OID consts + * + */ + +#ifndef _LIB_DER_OIDS_H_ +#define _LIB_DER_OIDS_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Algorithm oids. */ +extern const DERItem + oidRsa, /* PKCS1 RSA encryption, used to identify RSA keys */ + oidMd2Rsa, /* PKCS1 md2withRSAEncryption signature alg */ + oidMd5Rsa, /* PKCS1 md5withRSAEncryption signature alg */ + oidSha1Rsa, /* PKCS1 sha1withRSAEncryption signature alg */ + oidSha256Rsa, /* PKCS1 sha256WithRSAEncryption signature alg */ + oidEcPubKey, /* ECDH or ECDSA public key in a certificate */ + oidSha1Ecdsa, /* ECDSA with SHA1 signature alg */ + oidSha224Ecdsa, /* ECDSA with SHA224 signature alg */ + oidSha256Ecdsa, /* ECDSA with SHA256 signature alg */ + oidSha384Ecdsa, /* ECDSA with SHA384 signature alg */ + oidSha512Ecdsa, /* ECDSA with SHA512 signature alg */ + oidMd2, /* OID_RSA_HASH 2 */ + oidMd4, /* OID_RSA_HASH 4 */ + oidMd5, /* OID_RSA_HASH 5 */ + oidSha1, /* OID_OIW_ALGORITHM 26 */ + oidSha256, /* OID_NIST_HASHALG 1 */ + oidSha384, /* OID_NIST_HASHALG 2 */ + oidSha512, /* OID_NIST_HASHALG 3 */ + oidSha224; /* OID_NIST_HASHALG 4 */ + +/* Standard X.509 Cert and CRL extensions. */ +extern const DERItem + oidSubjectKeyIdentifier, + oidKeyUsage, + oidPrivateKeyUsagePeriod, + oidSubjectAltName, + oidIssuerAltName, + oidBasicConstraints, + oidCrlDistributionPoints, + oidCertificatePolicies, + oidAnyPolicy, + oidPolicyMappings, + oidAuthorityKeyIdentifier, + oidPolicyConstraints, + oidExtendedKeyUsage, + oidAnyExtendedKeyUsage, + oidInhibitAnyPolicy, + oidAuthorityInfoAccess, + oidSubjectInfoAccess, + oidAdOCSP, + oidAdCAIssuer, + oidNetscapeCertType, + oidEntrustVersInfo, + oidMSNTPrincipalName, + /* Policy Qualifier IDs for Internet policy qualifiers. */ + oidQtCps, + oidQtUNotice, + /* X.501 Name IDs. */ + oidCommonName, + oidCountryName, + oidLocalityName, + oidStateOrProvinceName, + oidOrganizationName, + oidOrganizationalUnitName, + oidDescription, + oidEmailAddress, + oidFriendlyName, + oidLocalKeyId, + oidExtendedKeyUsageServerAuth, + oidExtendedKeyUsageClientAuth, + oidExtendedKeyUsageCodeSigning, + oidExtendedKeyUsageEmailProtection, + oidExtendedKeyUsageOCSPSigning, + oidExtendedKeyUsageIPSec, + oidExtendedKeyUsageMicrosoftSGC, + oidExtendedKeyUsageNetscapeSGC, + /* Secure Boot Spec oid */ + oidAppleSecureBootCertSpec, + oidAppleProvisioningProfile, + oidAppleApplicationSigning, + oidAppleInstallerPackagingSigningExternal, + oidAppleExtendedKeyUsageAppleID, + oidAppleExtendedKeyUsageShoebox, + oidAppleExtendedKeyUsageProfileSigning, + oidAppleExtendedKeyUsageQAProfileSigning, + oidAppleIntmMarkerAppleID, + oidAppleIntmMarkerAppleID2, + oidApplePushServiceClient, + oidApplePolicyMobileStore, + oidApplePolicyTestMobileStore, + oidApplePolicyEscrowService, + oidAppleCertExtensionAppleIDRecordValidationSigning, + oidAppleIntmMarkerAppleSystemIntg2, + oidAppleIntmMarkerAppleSystemIntgG3, + oidAppleCertExtAppleSMPEncryption, + oidAppleCertExtAppleServerAuthentication, + oidAppleIntmMarkerAppleServerAuthentication; + +/* Compare two decoded OIDs. Returns true iff they are equivalent. */ +bool DEROidCompare(const DERItem *oid1, const DERItem *oid2); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIB_DER_UTILS_H_ */ diff --git a/Security/libsecurity_keychain/libDER/libDERUtils/fileIo.c b/Security/libsecurity_keychain/libDER/libDERUtils/fileIo.c new file mode 100644 index 00000000..93f8d642 --- /dev/null +++ b/Security/libsecurity_keychain/libDER/libDERUtils/fileIo.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2005-2007,2010-2012 Apple Inc. All Rights Reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "fileIo.h" + +int writeFile( + const char *fileName, + const unsigned char *bytes, + unsigned numBytes) +{ + int rtn; + int fd; + + fd = open(fileName, O_RDWR | O_CREAT | O_TRUNC, 0600); + if(fd <= 0) { + return errno; + } + rtn = (int)write(fd, bytes, (size_t)numBytes); + if(rtn != (int)numBytes) { + if(rtn >= 0) { + fprintf(stderr, "writeFile: short write\n"); + } + rtn = EIO; + } + else { + rtn = 0; + } + close(fd); + return rtn; +} + +/* + * Read entire file. + */ +int readFile( + const char *fileName, + unsigned char **bytes, // mallocd and returned + unsigned *numBytes) // returned +{ + int rtn; + int fd; + char *buf; + struct stat sb; + unsigned size; + + *numBytes = 0; + *bytes = NULL; + fd = open(fileName, O_RDONLY, 0); + if(fd <= 0) { + return errno; + } + rtn = fstat(fd, &sb); + if(rtn) { + goto errOut; + } + size = (unsigned) sb.st_size; + buf = (char *)malloc(size); + if(buf == NULL) { + rtn = ENOMEM; + goto errOut; + } + rtn = (int)read(fd, buf, size); + if(rtn != size) { + if(rtn >= 0) { + fprintf(stderr, "readFile: short read\n"); + } + rtn = EIO; + } + else { + rtn = 0; + *bytes = (unsigned char *)buf; + *numBytes = size; + } +errOut: + close(fd); + return rtn; +} diff --git a/Security/libsecurity_keychain/libDER/libDERUtils/fileIo.h b/Security/libsecurity_keychain/libDER/libDERUtils/fileIo.h new file mode 100644 index 00000000..26e31f71 --- /dev/null +++ b/Security/libsecurity_keychain/libDER/libDERUtils/fileIo.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2005-2007,2010-2011 Apple Inc. All Rights Reserved. + */ + +#ifndef _DER_FILE_IO_H_ +#define _DER_FILE_IO_H_ + +/* + * Read entire file. + */ +#ifdef __cplusplus +extern "C" { +#endif + +int readFile( + const char *fileName, + unsigned char **bytes, // mallocd and returned + unsigned *numBytes); // returned + +int writeFile( + const char *fileName, + const unsigned char *bytes, + unsigned numBytes); + +#ifdef __cplusplus +} +#endif + +#endif /* _DER_FILE_IO_H_ */ diff --git a/Security/libsecurity_keychain/libDER/libDERUtils/libDERUtils.c b/Security/libsecurity_keychain/libDER/libDERUtils/libDERUtils.c new file mode 100644 index 00000000..62cfe717 --- /dev/null +++ b/Security/libsecurity_keychain/libDER/libDERUtils/libDERUtils.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2005-2007,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* + * libDERUtils.c - support routines for libDER tests & examples + * + */ + +#include +#include + +const char *DERReturnString( + DERReturn drtn) +{ + static char unknown[128]; + + switch(drtn) { + case DR_Success: return "DR_Success"; + case DR_EndOfSequence: return "DR_EndOfSequence"; + case DR_UnexpectedTag: return "DR_UnexpectedTag"; + case DR_DecodeError: return "DR_DecodeError"; + case DR_Unimplemented: return "DR_Unimplemented"; + case DR_IncompleteSeq: return "DR_IncompleteSeq"; + default: + sprintf(unknown, "Unknown error (%d)", (int)drtn); + return unknown; + } +} + +void DERPerror( + const char *op, + DERReturn drtn) +{ + fprintf(stderr, "*** %s: %s\n", op, DERReturnString(drtn)); +} + diff --git a/Security/libsecurity_keychain/libDER/libDERUtils/libDERUtils.h b/Security/libsecurity_keychain/libDER/libDERUtils/libDERUtils.h new file mode 100644 index 00000000..6cd93078 --- /dev/null +++ b/Security/libsecurity_keychain/libDER/libDERUtils/libDERUtils.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2005-2007,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* + * libDERUtils.h - support routines for libDER tests & examples + * + */ + +#ifndef _LIB_DER_UTILS_H_ +#define _LIB_DER_UTILS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +const char *DERReturnString( + DERReturn drtn); + +void DERPerror( + const char *op, + DERReturn rtn); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIB_DER_UTILS_H_ */ diff --git a/libsecurity_keychain/libDER/libDERUtils/printFields.c b/Security/libsecurity_keychain/libDER/libDERUtils/printFields.c similarity index 87% rename from libsecurity_keychain/libDER/libDERUtils/printFields.c rename to Security/libsecurity_keychain/libDER/libDERUtils/printFields.c index 6269ebb8..51bcffe9 100644 --- a/libsecurity_keychain/libDER/libDERUtils/printFields.c +++ b/Security/libsecurity_keychain/libDER/libDERUtils/printFields.c @@ -1,9 +1,30 @@ -/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */ +/* + * Copyright (c) 2005-2007,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@ + */ + /* * printFeilds.h - print various DER objects * - * Created Nov. 9 2005 by dmitch */ #include diff --git a/Security/libsecurity_keychain/libDER/libDERUtils/printFields.h b/Security/libsecurity_keychain/libDER/libDERUtils/printFields.h new file mode 100644 index 00000000..182cfc5b --- /dev/null +++ b/Security/libsecurity_keychain/libDER/libDERUtils/printFields.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2005-2007,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@ + */ + + +/* + * printFeilds.h - print various DER objects + * + */ + +#ifndef _PRINT_FIELDS_H_ +#define _PRINT_FIELDS_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void doIndent(void); +void incrIndent(void); +void decrIndent(void); +void printHex(DERItem *item); +void printBitString(DERItem *item); +void printString(DERItem *item); +void printHeader(const char *label); + +typedef enum { + IT_Leaf, // leaf; always print contents + IT_Branch // branch; print contents iff verbose +} ItemType; + +void printItem( + const char *label, + ItemType itemType, + int verbose, + DERTag tag, // maybe from decoding, maybe the real tag underlying + // an implicitly tagged item + DERItem *item); // content + +void printAlgId( + const DERItem *content, + int verbose); +void printSubjPubKeyInfo( + const DERItem *content, + int verbose); + +/* decode one item and print it */ +void decodePrintItem( + const char *label, + ItemType itemType, + int verbose, + DERItem *derItem); + +#ifdef __cplusplus +} +#endif + +#endif /* _PRINT_FIELDS_H_ */ diff --git a/Security/libsecurity_keychain/libsecurity_keychain.xcodeproj/project.pbxproj b/Security/libsecurity_keychain/libsecurity_keychain.xcodeproj/project.pbxproj new file mode 100644 index 00000000..97c47c2a --- /dev/null +++ b/Security/libsecurity_keychain/libsecurity_keychain.xcodeproj/project.pbxproj @@ -0,0 +1,1319 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 05012D46060B94A000C044CB /* SecImportExportCrypto.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05012D45060B94A000C044CB /* SecImportExportCrypto.cpp */; }; + 05012D4A060B94B200C044CB /* SecImportExportCrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 05012D49060B94B200C044CB /* SecImportExportCrypto.h */; settings = {ATTRIBUTES = (); }; }; + 051A034805D9A68C00E02A64 /* SecImportExportAgg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 051A034705D9A68C00E02A64 /* SecImportExportAgg.cpp */; }; + 051A035005D9A69900E02A64 /* SecImportExportAgg.h in Headers */ = {isa = PBXBuildFile; fileRef = 051A034F05D9A69900E02A64 /* SecImportExportAgg.h */; settings = {ATTRIBUTES = (); }; }; + 051A053305DAC86400E02A64 /* SecImportExportPem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 051A053205DAC86400E02A64 /* SecImportExportPem.cpp */; }; + 052AF723060A3472003FEB8D /* SecWrappedKeys.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 052AF722060A3472003FEB8D /* SecWrappedKeys.cpp */; }; + 054F90AE05E2860E0013C1D1 /* SecImportExportUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 054F90AD05E2860E0013C1D1 /* SecImportExportUtils.cpp */; }; + 054F90B005E286180013C1D1 /* SecImportExportUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 054F90AF05E286180013C1D1 /* SecImportExportUtils.h */; settings = {ATTRIBUTES = (); }; }; + 055EA6B106AC5C13005079CE /* TrustRevocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 055EA6B006AC5C13005079CE /* TrustRevocation.cpp */; }; + 056CDA3905FD573B00820BC3 /* SecImportExportPkcs8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 056CDA3805FD573B00820BC3 /* SecImportExportPkcs8.cpp */; }; + 056CDA5D05FD5AEB00820BC3 /* SecPkcs8Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 056CDA5C05FD5AEB00820BC3 /* SecPkcs8Templates.h */; }; + 056CDA6505FD5B3400820BC3 /* SecPkcs8Templates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 056CDA6405FD5B3400820BC3 /* SecPkcs8Templates.cpp */; }; + 056CDA8E05FD63C200820BC3 /* SecImportExportPkcs8.h in Headers */ = {isa = PBXBuildFile; fileRef = 056CDA8D05FD63C200820BC3 /* SecImportExportPkcs8.h */; settings = {ATTRIBUTES = (); }; }; + 058AA95A05D93B4300F543ED /* SecExport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 058AA95805D93B4300F543ED /* SecExport.cpp */; }; + 058AA95B05D93B4300F543ED /* SecImportExport.h in Headers */ = {isa = PBXBuildFile; fileRef = 058AA95905D93B4300F543ED /* SecImportExport.h */; settings = {ATTRIBUTES = (); }; }; + 058AA96C05D93CDD00F543ED /* SecImport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 058AA96B05D93CDD00F543ED /* SecImport.cpp */; }; + 058AA9CA05D96FD200F543ED /* SecExternalRep.h in Headers */ = {isa = PBXBuildFile; fileRef = 058AA9C905D96FD200F543ED /* SecExternalRep.h */; settings = {ATTRIBUTES = (); }; }; + 058AA9CE05D96FE600F543ED /* SecExternalRep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 058AA9CD05D96FE600F543ED /* SecExternalRep.cpp */; }; + 058AAA9205D97EAE00F543ED /* SecImportExportPem.h in Headers */ = {isa = PBXBuildFile; fileRef = 058AAA9105D97EAE00F543ED /* SecImportExportPem.h */; settings = {ATTRIBUTES = (); }; }; + 058C797109F56CCB00DB7E98 /* SecTrustSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 058C796F09F56CCB00DB7E98 /* SecTrustSettings.h */; settings = {ATTRIBUTES = (); }; }; + 058C797209F56CCC00DB7E98 /* SecTrustSettingsPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 058C797009F56CCB00DB7E98 /* SecTrustSettingsPriv.h */; settings = {ATTRIBUTES = (); }; }; + 058C797609F56CFB00DB7E98 /* SecTrustSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 058C797509F56CFB00DB7E98 /* SecTrustSettings.cpp */; }; + 058C797C09F56D1400DB7E98 /* TrustSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 058C797709F56D1400DB7E98 /* TrustSettings.cpp */; }; + 058C797D09F56D1400DB7E98 /* TrustSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 058C797809F56D1400DB7E98 /* TrustSettings.h */; settings = {ATTRIBUTES = (); }; }; + 058C797E09F56D1400DB7E98 /* TrustSettingsSchema.h in Headers */ = {isa = PBXBuildFile; fileRef = 058C797909F56D1400DB7E98 /* TrustSettingsSchema.h */; settings = {ATTRIBUTES = (); }; }; + 058C797F09F56D1400DB7E98 /* TrustSettingsUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 058C797A09F56D1400DB7E98 /* TrustSettingsUtils.cpp */; }; + 058C798009F56D1400DB7E98 /* TrustSettingsUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 058C797B09F56D1400DB7E98 /* TrustSettingsUtils.h */; settings = {ATTRIBUTES = (); }; }; + 05A83C380AAF591100906F28 /* SecKeychainItemExtendedAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 05A83C360AAF591100906F28 /* SecKeychainItemExtendedAttributes.h */; settings = {ATTRIBUTES = (); }; }; + 05A83C800AAF5CEA00906F28 /* ExtendedAttribute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05A83C7E0AAF5CEA00906F28 /* ExtendedAttribute.cpp */; }; + 05A83C880AAF5E0A00906F28 /* SecKeychainItemExtendedAttributes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05A83C870AAF5E0A00906F28 /* SecKeychainItemExtendedAttributes.cpp */; }; + 05AE95490AA748570076501C /* SecImportExportOpenSSH.h in Headers */ = {isa = PBXBuildFile; fileRef = 05AE95470AA748570076501C /* SecImportExportOpenSSH.h */; }; + 05AE954A0AA748580076501C /* SecImportExportOpenSSH.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05AE95480AA748570076501C /* SecImportExportOpenSSH.cpp */; }; + 05FB016805E54A3A00A5194C /* SecNetscapeTemplates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05FB016605E54A3A00A5194C /* SecNetscapeTemplates.cpp */; }; + 05FB016905E54A3A00A5194C /* SecNetscapeTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 05FB016705E54A3A00A5194C /* SecNetscapeTemplates.h */; }; + 0CBD509A16C3246D00713B6C /* kc-40-seckey.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CBD509816C3246D00713B6C /* kc-40-seckey.c */; }; + 0CBD509B16C3246D00713B6C /* kc-41-sececkey.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CBD509916C3246D00713B6C /* kc-41-sececkey.c */; }; + 182BB5CD146FF72B000BF1F3 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5297A731112CB13800EAA0C0 /* libDER.a */; }; + 188BB546171DD8B5009D22CE /* si-33-keychain-backup.c in Sources */ = {isa = PBXBuildFile; fileRef = 188BB53F171DD774009D22CE /* si-33-keychain-backup.c */; }; + 1B11967B062F4C1800F3B659 /* SecKeychainSearchPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B11967A062F4C1800F3B659 /* SecKeychainSearchPriv.h */; settings = {ATTRIBUTES = (); }; }; + 30E17F5B062B0A25004208EB /* SecIdentitySearchPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E17F5A062B0A25004208EB /* SecIdentitySearchPriv.h */; settings = {ATTRIBUTES = (); }; }; + 407AC2C0066661620030E07D /* SecPassword.h in Headers */ = {isa = PBXBuildFile; fileRef = 407AC2BE066661620030E07D /* SecPassword.h */; settings = {ATTRIBUTES = (); }; }; + 407AC2C1066661620030E07D /* SecPassword.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 407AC2BF066661620030E07D /* SecPassword.cpp */; }; + 407AC2C5066798420030E07D /* Password.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 407AC2C3066798420030E07D /* Password.cpp */; }; + 4885CFF811C8182D0093ECF6 /* SecRecoveryPassword.c in Sources */ = {isa = PBXBuildFile; fileRef = 4885CFF611C8182D0093ECF6 /* SecRecoveryPassword.c */; }; + 4885CFF911C8182D0093ECF6 /* SecRecoveryPassword.h in Headers */ = {isa = PBXBuildFile; fileRef = 4885CFF711C8182D0093ECF6 /* SecRecoveryPassword.h */; settings = {ATTRIBUTES = (); }; }; + 489C4FCC1202547600A8C58A /* SecRandom.h in Headers */ = {isa = PBXBuildFile; fileRef = 489C4FCB1202547600A8C58A /* SecRandom.h */; settings = {ATTRIBUTES = (); }; }; + 48E66AE3120254D700E878AD /* SecRandom.c in Sources */ = {isa = PBXBuildFile; fileRef = 48E66AE2120254D700E878AD /* SecRandom.c */; }; + 48E66AE5120254FC00E878AD /* SecRandomP.h in Headers */ = {isa = PBXBuildFile; fileRef = 48E66AE4120254FC00E878AD /* SecRandomP.h */; settings = {ATTRIBUTES = (); }; }; + 4C21181B058A75B000014C42 /* SecBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C21181A058A75B000014C42 /* SecBase.cpp */; }; + 4C5719DB12FB5F6800B31F85 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C5719D812FB5F6800B31F85 /* main.c */; }; + 4C86848C058A59430072F261 /* MacOSErrorStrings.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C868429058A55A10072F261 /* MacOSErrorStrings.h */; settings = {ATTRIBUTES = (); }; }; + 4CF00661058A51180060AF78 /* SecBasePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF00660058A51180060AF78 /* SecBasePriv.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F5E0581376700834D11 /* SecKeychain.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B8E052E099D006D0211 /* SecKeychain.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F5F0581376700834D11 /* SecKeychainSearch.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B96052E099D006D0211 /* SecKeychainSearch.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F600581376700834D11 /* SecPolicySearch.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B9C052E099D006D0211 /* SecPolicySearch.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F610581376700834D11 /* SecTrust.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2BA0052E099D006D0211 /* SecTrust.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F620581376700834D11 /* SecKey.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B8C052E099D006D0211 /* SecKey.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F630581376700834D11 /* SecKeychainItem.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B94052E099D006D0211 /* SecKeychainItem.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F640581376700834D11 /* Security.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2BA5052E099D006D0211 /* Security.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F650581376700834D11 /* SecAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B75052E099D006D0211 /* SecAccess.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F660581376700834D11 /* SecPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B99052E099D006D0211 /* SecPolicy.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F670581376700834D11 /* SecIdentitySearch.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B8A052E099D006D0211 /* SecIdentitySearch.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F680581376700834D11 /* SecACL.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B78052E099D006D0211 /* SecACL.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F690581376700834D11 /* SecCertificate.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B7C052E099D006D0211 /* SecCertificate.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F6A0581376700834D11 /* SecBase.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B79052E099D006D0211 /* SecBase.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F6B0581376700834D11 /* SecTrustedApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2BA2052E099D006D0211 /* SecTrustedApplication.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F6C0581376700834D11 /* SecIdentity.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B87052E099D006D0211 /* SecIdentity.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F6E0581377300834D11 /* SecPolicyPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B9A052E099D006D0211 /* SecPolicyPriv.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F6F0581377300834D11 /* SecKeychainItemPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C4A397FA053B21F9000E1B34 /* SecKeychainItemPriv.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F700581377300834D11 /* SecTrustPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2BA4052E099D006D0211 /* SecTrustPriv.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F710581377300834D11 /* SecCertificateRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B81052E099D006D0211 /* SecCertificateRequest.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F720581377300834D11 /* SecAccessPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B76052E099D006D0211 /* SecAccessPriv.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F730581377300834D11 /* SecKeychainPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C4A397A1053B1D50000E1B34 /* SecKeychainPriv.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F740581377300834D11 /* SecIdentityPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B88052E099D006D0211 /* SecIdentityPriv.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F750581377300834D11 /* SecTrustedApplicationPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2BA3052E099D006D0211 /* SecTrustedApplicationPriv.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F760581377300834D11 /* SecCertificatePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B7F052E099D006D0211 /* SecCertificatePriv.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F780581377300834D11 /* SecKeyPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B97052E099D006D0211 /* SecKeyPriv.h */; settings = {ATTRIBUTES = (); }; }; + 4CF36F790581377300834D11 /* SecCertificateBundle.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B7E052E099D006D0211 /* SecCertificateBundle.h */; settings = {ATTRIBUTES = (); }; }; + 4CFDC28506CD9C6A007BEE7E /* DynamicDLDBList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFDC28306CD9C6A007BEE7E /* DynamicDLDBList.cpp */; }; + 52008C6411496BD200E8CA78 /* SecCertificateInternalP.h in Headers */ = {isa = PBXBuildFile; fileRef = 52008C6311496BD200E8CA78 /* SecCertificateInternalP.h */; settings = {ATTRIBUTES = (); }; }; + 521DC57F1125FEE300937BF2 /* SecCertificateP.c in Sources */ = {isa = PBXBuildFile; fileRef = 521DC57D1125FEE300937BF2 /* SecCertificateP.c */; }; + 521DC5801125FEE300937BF2 /* SecCertificateP.h in Headers */ = {isa = PBXBuildFile; fileRef = 521DC57E1125FEE300937BF2 /* SecCertificateP.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 52200F8B14F2B87F00F7F6E7 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA31456E134B716B00133245 /* CoreFoundation.framework */; }; + 5261C28A112F0D570047EF8B /* SecFrameworkP.c in Sources */ = {isa = PBXBuildFile; fileRef = 5261C289112F0D570047EF8B /* SecFrameworkP.c */; }; + 5261C310112F1C560047EF8B /* SecBase64P.c in Sources */ = {isa = PBXBuildFile; fileRef = 5261C30F112F1C560047EF8B /* SecBase64P.c */; }; + 52B609D914F55B6800134209 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52B609D814F55B6800134209 /* Foundation.framework */; }; + 52B609E314F55BFA00134209 /* timestampclient.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B609E214F55BFA00134209 /* timestampclient.m */; }; + 52B60A0714F5CA9600134209 /* main-tsa.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B60A0614F5CA9500134209 /* main-tsa.m */; }; + 52B88DFB11DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52B88DF911DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.cpp */; }; + 52B88DFC11DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B88DFA11DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.h */; settings = {ATTRIBUTES = (); }; }; + 52BA735D112231C70012875E /* CertificateValues.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52BA735B112231C70012875E /* CertificateValues.cpp */; }; + 52BA735E112231C70012875E /* CertificateValues.h in Headers */ = {isa = PBXBuildFile; fileRef = 52BA735C112231C70012875E /* CertificateValues.h */; }; + 52C23EF81135AE5100E079D2 /* SecCertificatePrivP.h in Headers */ = {isa = PBXBuildFile; fileRef = 52C23EF71135AE5100E079D2 /* SecCertificatePrivP.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 52E950CD1509B47000DA6511 /* tsaDERUtilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 52E950CC1509B47000DA6511 /* tsaDERUtilities.c */; }; + 52E950D61509B48D00DA6511 /* tsaDERUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 52E950D51509B48D00DA6511 /* tsaDERUtilities.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 52FB44A91146D769006D3B0A /* SecCertificateOIDs.h in Headers */ = {isa = PBXBuildFile; fileRef = 52FB44A81146D769006D3B0A /* SecCertificateOIDs.h */; settings = {ATTRIBUTES = (); }; }; + AA31456F134B716B00133245 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA31456E134B716B00133245 /* CoreFoundation.framework */; }; + AC9ADAD3199AD6BA00BDAF54 /* kc-42-trust-revocation.c in Sources */ = {isa = PBXBuildFile; fileRef = AC9ADAD2199AD6BA00BDAF54 /* kc-42-trust-revocation.c */; }; + BE296DBF0EAC299C00FD22BE /* SecImportExport.c in Sources */ = {isa = PBXBuildFile; fileRef = BE296DBE0EAC299C00FD22BE /* SecImportExport.c */; }; + BE296DC50EAC2B5600FD22BE /* SecInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = BE296DC40EAC2B5600FD22BE /* SecInternal.h */; }; + BE50AE670F687AB900D28C54 /* TrustAdditions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE50AE650F687AB900D28C54 /* TrustAdditions.cpp */; }; + BE50AE680F687AB900D28C54 /* TrustAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = BE50AE660F687AB900D28C54 /* TrustAdditions.h */; }; + BEA830070EB17344001CA937 /* SecItemConstants.c in Sources */ = {isa = PBXBuildFile; fileRef = BEE897100A62CDD800BF88A5 /* SecItemConstants.c */; }; + BECE5141106B056C0091E644 /* TrustKeychains.h in Headers */ = {isa = PBXBuildFile; fileRef = BECE5140106B056C0091E644 /* TrustKeychains.h */; settings = {ATTRIBUTES = (); }; }; + BEE896E20A61F0BB00BF88A5 /* SecItem.h in Headers */ = {isa = PBXBuildFile; fileRef = BEE896E00A61F0BB00BF88A5 /* SecItem.h */; settings = {ATTRIBUTES = (); }; }; + BEE896E30A61F0BB00BF88A5 /* SecItemPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = BEE896E10A61F0BB00BF88A5 /* SecItemPriv.h */; settings = {ATTRIBUTES = (); }; }; + BEE896E70A61F12300BF88A5 /* SecItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BEE896E60A61F12300BF88A5 /* SecItem.cpp */; }; + C26BA9FF072580AE0049AF3C /* UnlockReferralItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C26BA9FE072580AE0049AF3C /* UnlockReferralItem.cpp */; }; + C2AA2BB4052E099D006D0211 /* Access.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B42052E099D006D0211 /* Access.cpp */; }; + C2AA2BB6052E099D006D0211 /* ACL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B44052E099D006D0211 /* ACL.cpp */; }; + C2AA2BB8052E099D006D0211 /* CCallbackMgr.cp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B46052E099D006D0211 /* CCallbackMgr.cp */; }; + C2AA2BBA052E099D006D0211 /* Certificate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B48052E099D006D0211 /* Certificate.cpp */; }; + C2AA2BBC052E099D006D0211 /* CertificateRequest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B4A052E099D006D0211 /* CertificateRequest.cpp */; }; + C2AA2BBF052E099D006D0211 /* cssmdatetime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B4D052E099D006D0211 /* cssmdatetime.cpp */; }; + C2AA2BC1052E099D006D0211 /* DLDBListCFPref.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B4F052E099D006D0211 /* DLDBListCFPref.cpp */; }; + C2AA2BC7052E099D006D0211 /* Globals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B56052E099D006D0211 /* Globals.cpp */; }; + C2AA2BC9052E099D006D0211 /* Identity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B58052E099D006D0211 /* Identity.cpp */; }; + C2AA2BCB052E099D006D0211 /* IdentityCursor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B5A052E099D006D0211 /* IdentityCursor.cpp */; }; + C2AA2BCD052E099D006D0211 /* Item.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B5C052E099D006D0211 /* Item.cpp */; }; + C2AA2BCF052E099D006D0211 /* KCCursor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B5E052E099D006D0211 /* KCCursor.cpp */; }; + C2AA2BD8052E099D006D0211 /* Keychains.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B67052E099D006D0211 /* Keychains.cpp */; }; + C2AA2BDA052E099D006D0211 /* KeyItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B69052E099D006D0211 /* KeyItem.cpp */; }; + C2AA2BDC052E099D006D0211 /* Policies.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B6B052E099D006D0211 /* Policies.cpp */; }; + C2AA2BDE052E099D006D0211 /* PolicyCursor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B6D052E099D006D0211 /* PolicyCursor.cpp */; }; + C2AA2BE0052E099D006D0211 /* PrimaryKey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B6F052E099D006D0211 /* PrimaryKey.cpp */; }; + C2AA2BE4052E099D006D0211 /* SecAccess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B74052E099D006D0211 /* SecAccess.cpp */; }; + C2AA2BE7052E099D006D0211 /* SecACL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B77052E099D006D0211 /* SecACL.cpp */; }; + C2AA2BEB052E099D006D0211 /* SecCertificate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B7B052E099D006D0211 /* SecCertificate.cpp */; }; + C2AA2BED052E099D006D0211 /* SecCertificateBundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B7D052E099D006D0211 /* SecCertificateBundle.cpp */; }; + C2AA2BF0052E099D006D0211 /* SecCertificateRequest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B80052E099D006D0211 /* SecCertificateRequest.cpp */; }; + C2AA2BF2052E099D006D0211 /* SecCFTypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B82052E099D006D0211 /* SecCFTypes.cpp */; }; + C2AA2BF6052E099D006D0211 /* SecIdentity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B86052E099D006D0211 /* SecIdentity.cpp */; }; + C2AA2BF9052E099D006D0211 /* SecIdentitySearch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B89052E099D006D0211 /* SecIdentitySearch.cpp */; }; + C2AA2BFB052E099D006D0211 /* SecKey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B8B052E099D006D0211 /* SecKey.cpp */; }; + C2AA2BFD052E099D006D0211 /* SecKeychain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B8D052E099D006D0211 /* SecKeychain.cpp */; }; + C2AA2BFF052E099D006D0211 /* SecKeychainAddIToolsPassword.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B8F052E099D006D0211 /* SecKeychainAddIToolsPassword.cpp */; }; + C2AA2C03052E099D006D0211 /* SecKeychainItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B93052E099D006D0211 /* SecKeychainItem.cpp */; }; + C2AA2C05052E099D006D0211 /* SecKeychainSearch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B95052E099D006D0211 /* SecKeychainSearch.cpp */; }; + C2AA2C08052E099D006D0211 /* SecPolicy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B98052E099D006D0211 /* SecPolicy.cpp */; }; + C2AA2C0B052E099D006D0211 /* SecPolicySearch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B9B052E099D006D0211 /* SecPolicySearch.cpp */; }; + C2AA2C0F052E099D006D0211 /* SecTrust.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B9F052E099D006D0211 /* SecTrust.cpp */; }; + C2AA2C11052E099D006D0211 /* SecTrustedApplication.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2BA1052E099D006D0211 /* SecTrustedApplication.cpp */; }; + C2AA2C1A052E099D006D0211 /* StorageManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2BAA052E099D006D0211 /* StorageManager.cpp */; }; + C2AA2C1C052E099D006D0211 /* Trust.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2BAC052E099D006D0211 /* Trust.cpp */; }; + C2AA2C1E052E099D006D0211 /* TrustedApplication.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2BAE052E099D006D0211 /* TrustedApplication.cpp */; }; + C2AA2C20052E099D006D0211 /* TrustItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2BB0052E099D006D0211 /* TrustItem.cpp */; }; + C2AA2C22052E099D006D0211 /* TrustStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2BB2052E099D006D0211 /* TrustStore.cpp */; }; + C2FD26380731CEFB0027896A /* defaultcreds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2FD26370731CEE60027896A /* defaultcreds.cpp */; }; + C429431E053B2F8B00470431 /* KCUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C429431C053B2F8B00470431 /* KCUtilities.cpp */; }; + D6095E960A94F17C0026C68B /* KCEventNotifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D6E1457B0A632A5A008AA7E8 /* KCEventNotifier.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 182BB311146F0AE6000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 182BB30C146F0AE6000BF1F3 /* libsecurity_utilities.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA2A53A0523D32800978A7B; + remoteInfo = libsecurity_utilities; + }; + 182BB340146F106C000BF1F3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 182BB30C146F0AE6000BF1F3 /* libsecurity_utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = C2C9C69D0CECBE8400B3FE07; + remoteInfo = libsecurity_utilitiesDTrace; + }; + 521FBA8B112CB465002BEF54 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 5297A586112B78BB00EAA0C0 /* libDER.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 053BA313091C00BF00A7007A; + remoteInfo = libDER; + }; + 5297A730112CB13800EAA0C0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 5297A586112B78BB00EAA0C0 /* libDER.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 053BA314091C00BF00A7007A; + remoteInfo = libDER; + }; + 5297A732112CB13800EAA0C0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 5297A586112B78BB00EAA0C0 /* libDER.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 053BA445091FE58C00A7007A; + remoteInfo = parseCert; + }; + 5297A734112CB13800EAA0C0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 5297A586112B78BB00EAA0C0 /* libDER.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 053BA46B091FE63E00A7007A; + remoteInfo = libDERUtils; + }; + 5297A736112CB13800EAA0C0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 5297A586112B78BB00EAA0C0 /* libDER.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 058F16540925135E009FA1C5; + remoteInfo = parseCrl; + }; + 52FB45D411471AD0006D3B0A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 5297A586112B78BB00EAA0C0 /* libDER.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4C96C8CE113F4132005483E8; + remoteInfo = parseTicket; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 05012D45060B94A000C044CB /* SecImportExportCrypto.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecImportExportCrypto.cpp; sourceTree = ""; }; + 05012D49060B94B200C044CB /* SecImportExportCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecImportExportCrypto.h; sourceTree = ""; }; + 051A034705D9A68C00E02A64 /* SecImportExportAgg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecImportExportAgg.cpp; sourceTree = ""; }; + 051A034F05D9A69900E02A64 /* SecImportExportAgg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecImportExportAgg.h; sourceTree = ""; }; + 051A053205DAC86400E02A64 /* SecImportExportPem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecImportExportPem.cpp; sourceTree = ""; }; + 052AF722060A3472003FEB8D /* SecWrappedKeys.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecWrappedKeys.cpp; sourceTree = ""; }; + 054F90AD05E2860E0013C1D1 /* SecImportExportUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecImportExportUtils.cpp; sourceTree = ""; }; + 054F90AF05E286180013C1D1 /* SecImportExportUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecImportExportUtils.h; sourceTree = ""; }; + 055EA6B006AC5C13005079CE /* TrustRevocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrustRevocation.cpp; sourceTree = ""; }; + 056CDA3805FD573B00820BC3 /* SecImportExportPkcs8.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecImportExportPkcs8.cpp; sourceTree = ""; }; + 056CDA5C05FD5AEB00820BC3 /* SecPkcs8Templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecPkcs8Templates.h; sourceTree = ""; }; + 056CDA6405FD5B3400820BC3 /* SecPkcs8Templates.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecPkcs8Templates.cpp; sourceTree = ""; }; + 056CDA8D05FD63C200820BC3 /* SecImportExportPkcs8.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecImportExportPkcs8.h; sourceTree = ""; }; + 058AA95805D93B4300F543ED /* SecExport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecExport.cpp; sourceTree = ""; }; + 058AA95905D93B4300F543ED /* SecImportExport.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecImportExport.h; sourceTree = ""; }; + 058AA96B05D93CDD00F543ED /* SecImport.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 30; path = SecImport.cpp; sourceTree = ""; }; + 058AA9C905D96FD200F543ED /* SecExternalRep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecExternalRep.h; sourceTree = ""; }; + 058AA9CD05D96FE600F543ED /* SecExternalRep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecExternalRep.cpp; sourceTree = ""; }; + 058AAA9105D97EAE00F543ED /* SecImportExportPem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecImportExportPem.h; sourceTree = ""; }; + 058C796F09F56CCB00DB7E98 /* SecTrustSettings.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrustSettings.h; sourceTree = ""; }; + 058C797009F56CCB00DB7E98 /* SecTrustSettingsPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrustSettingsPriv.h; sourceTree = ""; }; + 058C797509F56CFB00DB7E98 /* SecTrustSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecTrustSettings.cpp; sourceTree = ""; }; + 058C797709F56D1400DB7E98 /* TrustSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TrustSettings.cpp; sourceTree = ""; }; + 058C797809F56D1400DB7E98 /* TrustSettings.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TrustSettings.h; sourceTree = ""; }; + 058C797909F56D1400DB7E98 /* TrustSettingsSchema.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TrustSettingsSchema.h; sourceTree = ""; }; + 058C797A09F56D1400DB7E98 /* TrustSettingsUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TrustSettingsUtils.cpp; sourceTree = ""; }; + 058C797B09F56D1400DB7E98 /* TrustSettingsUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TrustSettingsUtils.h; sourceTree = ""; }; + 05A83C360AAF591100906F28 /* SecKeychainItemExtendedAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecKeychainItemExtendedAttributes.h; sourceTree = ""; }; + 05A83C7D0AAF5CEA00906F28 /* ExtendedAttribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExtendedAttribute.h; sourceTree = ""; }; + 05A83C7E0AAF5CEA00906F28 /* ExtendedAttribute.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExtendedAttribute.cpp; sourceTree = ""; }; + 05A83C870AAF5E0A00906F28 /* SecKeychainItemExtendedAttributes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecKeychainItemExtendedAttributes.cpp; sourceTree = ""; }; + 05AE95470AA748570076501C /* SecImportExportOpenSSH.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecImportExportOpenSSH.h; sourceTree = ""; }; + 05AE95480AA748570076501C /* SecImportExportOpenSSH.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecImportExportOpenSSH.cpp; sourceTree = ""; }; + 05FB016605E54A3A00A5194C /* SecNetscapeTemplates.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecNetscapeTemplates.cpp; sourceTree = ""; }; + 05FB016705E54A3A00A5194C /* SecNetscapeTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecNetscapeTemplates.h; sourceTree = ""; }; + 0CBD509716C3242200713B6C /* libsecurity_keychain_regressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurity_keychain_regressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 0CBD509816C3246D00713B6C /* kc-40-seckey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-40-seckey.c"; path = "regressions/kc-40-seckey.c"; sourceTree = ""; }; + 0CBD509916C3246D00713B6C /* kc-41-sececkey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-41-sececkey.c"; path = "regressions/kc-41-sececkey.c"; sourceTree = ""; }; + 0CBD509C16C324B100713B6C /* keychain_regressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = keychain_regressions.h; path = regressions/keychain_regressions.h; sourceTree = ""; }; + 182BB224146F063C000BF1F3 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 182BB225146F063C000BF1F3 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 182BB226146F063C000BF1F3 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 182BB227146F063C000BF1F3 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 182BB30C146F0AE6000BF1F3 /* libsecurity_utilities.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_utilities.xcodeproj; path = ../libsecurity_utilities/libsecurity_utilities.xcodeproj; sourceTree = ""; }; + 188BB53F171DD774009D22CE /* si-33-keychain-backup.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = "si-33-keychain-backup.c"; path = "regressions/si-33-keychain-backup.c"; sourceTree = ""; }; + 1B11967A062F4C1800F3B659 /* SecKeychainSearchPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKeychainSearchPriv.h; sourceTree = ""; }; + 30E17F5A062B0A25004208EB /* SecIdentitySearchPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecIdentitySearchPriv.h; path = lib/SecIdentitySearchPriv.h; sourceTree = SOURCE_ROOT; }; + 407AC2BE066661620030E07D /* SecPassword.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecPassword.h; sourceTree = ""; }; + 407AC2BF066661620030E07D /* SecPassword.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecPassword.cpp; sourceTree = ""; }; + 407AC2C2066798420030E07D /* Password.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Password.h; sourceTree = ""; }; + 407AC2C3066798420030E07D /* Password.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Password.cpp; sourceTree = ""; }; + 4885CFF611C8182D0093ECF6 /* SecRecoveryPassword.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecRecoveryPassword.c; sourceTree = ""; }; + 4885CFF711C8182D0093ECF6 /* SecRecoveryPassword.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecRecoveryPassword.h; sourceTree = ""; }; + 489C4FCB1202547600A8C58A /* SecRandom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecRandom.h; sourceTree = ""; }; + 48E66AE2120254D700E878AD /* SecRandom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecRandom.c; sourceTree = ""; }; + 48E66AE4120254FC00E878AD /* SecRandomP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecRandomP.h; sourceTree = ""; }; + 4C21181A058A75B000014C42 /* SecBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecBase.cpp; sourceTree = ""; }; + 4C5719C812FB5E9E00B31F85 /* XPCKeychainSandboxCheck.xpc */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XPCKeychainSandboxCheck.xpc; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C5719CA12FB5E9E00B31F85 /* XPCKeychainSandboxCheck-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "XPCKeychainSandboxCheck-Info.plist"; path = "xpc/XPCKeychainSandboxCheck-Info.plist"; sourceTree = ""; }; + 4C5719D812FB5F6800B31F85 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = main.c; path = xpc/main.c; sourceTree = ""; }; + 4C868429058A55A10072F261 /* MacOSErrorStrings.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MacOSErrorStrings.h; sourceTree = ""; }; + 4CA1FEBE052A3C8100F22E42 /* libsecurity_keychain.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_keychain.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CCB00430580089000981D43 /* security_keychain.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = security_keychain.exp; sourceTree = ""; }; + 4CF00660058A51180060AF78 /* SecBasePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecBasePriv.h; sourceTree = ""; }; + 4CFDC28306CD9C6A007BEE7E /* DynamicDLDBList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicDLDBList.cpp; sourceTree = ""; }; + 4CFDC28406CD9C6A007BEE7E /* DynamicDLDBList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DynamicDLDBList.h; sourceTree = ""; }; + 52008C6311496BD200E8CA78 /* SecCertificateInternalP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCertificateInternalP.h; sourceTree = ""; }; + 521DC57D1125FEE300937BF2 /* SecCertificateP.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecCertificateP.c; sourceTree = ""; }; + 521DC57E1125FEE300937BF2 /* SecCertificateP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCertificateP.h; sourceTree = ""; }; + 52200F8F14F2B88000F7F6E7 /* XPCTimeStampingService.xpc */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XPCTimeStampingService.xpc; sourceTree = BUILT_PRODUCTS_DIR; }; + 52200F9B14F2B93700F7F6E7 /* XPCTimeStampingService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "XPCTimeStampingService-Info.plist"; sourceTree = ""; }; + 5261C289112F0D570047EF8B /* SecFrameworkP.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecFrameworkP.c; sourceTree = ""; }; + 5261C2E1112F19BA0047EF8B /* debuggingP.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = debuggingP.c; sourceTree = ""; }; + 5261C30F112F1C560047EF8B /* SecBase64P.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecBase64P.c; sourceTree = ""; }; + 527067DB070246B300C5D30E /* iToolsTrustedApps.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; name = iToolsTrustedApps.plist; path = plist/iToolsTrustedApps.plist; sourceTree = SOURCE_ROOT; }; + 5297A586112B78BB00EAA0C0 /* libDER.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libDER.xcodeproj; path = libDER/libDER.xcodeproj; sourceTree = ""; }; + 52B609D814F55B6800134209 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = ../../../../../../../System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; + 52B609E114F55BFA00134209 /* timestampclient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timestampclient.h; sourceTree = ""; }; + 52B609E214F55BFA00134209 /* timestampclient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = timestampclient.m; sourceTree = ""; }; + 52B60A0614F5CA9500134209 /* main-tsa.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "main-tsa.m"; sourceTree = ""; }; + 52B88DF911DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecFDERecoveryAsymmetricCrypto.cpp; sourceTree = ""; }; + 52B88DFA11DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecFDERecoveryAsymmetricCrypto.h; sourceTree = ""; }; + 52BA735B112231C70012875E /* CertificateValues.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CertificateValues.cpp; sourceTree = ""; }; + 52BA735C112231C70012875E /* CertificateValues.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CertificateValues.h; sourceTree = ""; }; + 52C23EF71135AE5100E079D2 /* SecCertificatePrivP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCertificatePrivP.h; sourceTree = ""; }; + 52E950CC1509B47000DA6511 /* tsaDERUtilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tsaDERUtilities.c; sourceTree = ""; }; + 52E950D51509B48D00DA6511 /* tsaDERUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tsaDERUtilities.h; sourceTree = ""; }; + 52FB42C1113F056D006D3B0A /* debuggingP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debuggingP.h; sourceTree = ""; }; + 52FB44A81146D769006D3B0A /* SecCertificateOIDs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCertificateOIDs.h; sourceTree = ""; }; + AA31456E134B716B00133245 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; + AC9ADAD2199AD6BA00BDAF54 /* kc-42-trust-revocation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-42-trust-revocation.c"; path = "regressions/kc-42-trust-revocation.c"; sourceTree = ""; }; + BE296DBE0EAC299C00FD22BE /* SecImportExport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecImportExport.c; sourceTree = ""; }; + BE296DC40EAC2B5600FD22BE /* SecInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecInternal.h; sourceTree = ""; }; + BE50AE650F687AB900D28C54 /* TrustAdditions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrustAdditions.cpp; sourceTree = ""; }; + BE50AE660F687AB900D28C54 /* TrustAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrustAdditions.h; sourceTree = ""; }; + BECE5140106B056C0091E644 /* TrustKeychains.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrustKeychains.h; sourceTree = ""; }; + BEE896E00A61F0BB00BF88A5 /* SecItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecItem.h; sourceTree = ""; }; + BEE896E10A61F0BB00BF88A5 /* SecItemPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecItemPriv.h; sourceTree = ""; }; + BEE896E60A61F12300BF88A5 /* SecItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecItem.cpp; sourceTree = ""; }; + BEE897100A62CDD800BF88A5 /* SecItemConstants.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SecItemConstants.c; sourceTree = ""; }; + C26BA9FE072580AE0049AF3C /* UnlockReferralItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = UnlockReferralItem.cpp; path = lib/UnlockReferralItem.cpp; sourceTree = SOURCE_ROOT; }; + C2975B9B072580DC00AFECAD /* UnlockReferralItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = UnlockReferralItem.h; path = lib/UnlockReferralItem.h; sourceTree = SOURCE_ROOT; }; + C2AA2B42052E099D006D0211 /* Access.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Access.cpp; sourceTree = ""; }; + C2AA2B43052E099D006D0211 /* Access.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Access.h; sourceTree = ""; }; + C2AA2B44052E099D006D0211 /* ACL.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ACL.cpp; sourceTree = ""; }; + C2AA2B45052E099D006D0211 /* ACL.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ACL.h; sourceTree = ""; }; + C2AA2B46052E099D006D0211 /* CCallbackMgr.cp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CCallbackMgr.cp; sourceTree = ""; }; + C2AA2B47052E099D006D0211 /* CCallbackMgr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CCallbackMgr.h; sourceTree = ""; }; + C2AA2B48052E099D006D0211 /* Certificate.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Certificate.cpp; sourceTree = ""; }; + C2AA2B49052E099D006D0211 /* Certificate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Certificate.h; sourceTree = ""; }; + C2AA2B4A052E099D006D0211 /* CertificateRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CertificateRequest.cpp; sourceTree = ""; }; + C2AA2B4B052E099D006D0211 /* CertificateRequest.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CertificateRequest.h; sourceTree = ""; }; + C2AA2B4D052E099D006D0211 /* cssmdatetime.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmdatetime.cpp; sourceTree = ""; }; + C2AA2B4E052E099D006D0211 /* cssmdatetime.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmdatetime.h; sourceTree = ""; }; + C2AA2B4F052E099D006D0211 /* DLDBListCFPref.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DLDBListCFPref.cpp; sourceTree = ""; }; + C2AA2B50052E099D006D0211 /* DLDBListCFPref.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DLDBListCFPref.h; sourceTree = ""; }; + C2AA2B55052E099D006D0211 /* generateErrStrings.pl */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = generateErrStrings.pl; sourceTree = ""; }; + C2AA2B56052E099D006D0211 /* Globals.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Globals.cpp; sourceTree = ""; }; + C2AA2B57052E099D006D0211 /* Globals.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Globals.h; sourceTree = ""; }; + C2AA2B58052E099D006D0211 /* Identity.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Identity.cpp; sourceTree = ""; }; + C2AA2B59052E099D006D0211 /* Identity.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Identity.h; sourceTree = ""; }; + C2AA2B5A052E099D006D0211 /* IdentityCursor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = IdentityCursor.cpp; sourceTree = ""; }; + C2AA2B5B052E099D006D0211 /* IdentityCursor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = IdentityCursor.h; sourceTree = ""; }; + C2AA2B5C052E099D006D0211 /* Item.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Item.cpp; sourceTree = ""; }; + C2AA2B5D052E099D006D0211 /* Item.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Item.h; sourceTree = ""; }; + C2AA2B5E052E099D006D0211 /* KCCursor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = KCCursor.cpp; sourceTree = ""; }; + C2AA2B5F052E099D006D0211 /* KCCursor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = KCCursor.h; sourceTree = ""; }; + C2AA2B64052E099D006D0211 /* KCExceptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = KCExceptions.h; sourceTree = ""; }; + C2AA2B67052E099D006D0211 /* Keychains.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Keychains.cpp; sourceTree = ""; }; + C2AA2B68052E099D006D0211 /* Keychains.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Keychains.h; sourceTree = ""; }; + C2AA2B69052E099D006D0211 /* KeyItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = KeyItem.cpp; sourceTree = ""; }; + C2AA2B6A052E099D006D0211 /* KeyItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = KeyItem.h; sourceTree = ""; }; + C2AA2B6B052E099D006D0211 /* Policies.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Policies.cpp; sourceTree = ""; }; + C2AA2B6C052E099D006D0211 /* Policies.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Policies.h; sourceTree = ""; }; + C2AA2B6D052E099D006D0211 /* PolicyCursor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PolicyCursor.cpp; sourceTree = ""; }; + C2AA2B6E052E099D006D0211 /* PolicyCursor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PolicyCursor.h; sourceTree = ""; }; + C2AA2B6F052E099D006D0211 /* PrimaryKey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PrimaryKey.cpp; sourceTree = ""; }; + C2AA2B70052E099D006D0211 /* PrimaryKey.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PrimaryKey.h; sourceTree = ""; }; + C2AA2B74052E099D006D0211 /* SecAccess.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecAccess.cpp; sourceTree = ""; }; + C2AA2B75052E099D006D0211 /* SecAccess.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecAccess.h; sourceTree = ""; }; + C2AA2B76052E099D006D0211 /* SecAccessPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecAccessPriv.h; sourceTree = ""; }; + C2AA2B77052E099D006D0211 /* SecACL.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecACL.cpp; sourceTree = ""; }; + C2AA2B78052E099D006D0211 /* SecACL.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecACL.h; sourceTree = ""; }; + C2AA2B79052E099D006D0211 /* SecBase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecBase.h; sourceTree = ""; }; + C2AA2B7A052E099D006D0211 /* SecBridge.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecBridge.h; sourceTree = ""; }; + C2AA2B7B052E099D006D0211 /* SecCertificate.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecCertificate.cpp; sourceTree = ""; }; + C2AA2B7C052E099D006D0211 /* SecCertificate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCertificate.h; sourceTree = ""; }; + C2AA2B7D052E099D006D0211 /* SecCertificateBundle.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecCertificateBundle.cpp; sourceTree = ""; }; + C2AA2B7E052E099D006D0211 /* SecCertificateBundle.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCertificateBundle.h; sourceTree = ""; }; + C2AA2B7F052E099D006D0211 /* SecCertificatePriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCertificatePriv.h; sourceTree = ""; }; + C2AA2B80052E099D006D0211 /* SecCertificateRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecCertificateRequest.cpp; sourceTree = ""; }; + C2AA2B81052E099D006D0211 /* SecCertificateRequest.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCertificateRequest.h; sourceTree = ""; }; + C2AA2B82052E099D006D0211 /* SecCFTypes.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecCFTypes.cpp; sourceTree = ""; }; + C2AA2B83052E099D006D0211 /* SecCFTypes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCFTypes.h; sourceTree = ""; }; + C2AA2B86052E099D006D0211 /* SecIdentity.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecIdentity.cpp; sourceTree = ""; }; + C2AA2B87052E099D006D0211 /* SecIdentity.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecIdentity.h; sourceTree = ""; }; + C2AA2B88052E099D006D0211 /* SecIdentityPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecIdentityPriv.h; sourceTree = ""; }; + C2AA2B89052E099D006D0211 /* SecIdentitySearch.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecIdentitySearch.cpp; sourceTree = ""; }; + C2AA2B8A052E099D006D0211 /* SecIdentitySearch.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecIdentitySearch.h; sourceTree = ""; }; + C2AA2B8B052E099D006D0211 /* SecKey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecKey.cpp; sourceTree = ""; }; + C2AA2B8C052E099D006D0211 /* SecKey.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKey.h; sourceTree = ""; }; + C2AA2B8D052E099D006D0211 /* SecKeychain.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecKeychain.cpp; sourceTree = ""; }; + C2AA2B8E052E099D006D0211 /* SecKeychain.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKeychain.h; sourceTree = ""; }; + C2AA2B8F052E099D006D0211 /* SecKeychainAddIToolsPassword.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecKeychainAddIToolsPassword.cpp; sourceTree = ""; }; + C2AA2B93052E099D006D0211 /* SecKeychainItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecKeychainItem.cpp; sourceTree = ""; }; + C2AA2B94052E099D006D0211 /* SecKeychainItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKeychainItem.h; sourceTree = ""; }; + C2AA2B95052E099D006D0211 /* SecKeychainSearch.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecKeychainSearch.cpp; sourceTree = ""; }; + C2AA2B96052E099D006D0211 /* SecKeychainSearch.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKeychainSearch.h; sourceTree = ""; }; + C2AA2B97052E099D006D0211 /* SecKeyPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKeyPriv.h; sourceTree = ""; }; + C2AA2B98052E099D006D0211 /* SecPolicy.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecPolicy.cpp; sourceTree = ""; }; + C2AA2B99052E099D006D0211 /* SecPolicy.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecPolicy.h; sourceTree = ""; }; + C2AA2B9A052E099D006D0211 /* SecPolicyPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecPolicyPriv.h; sourceTree = ""; }; + C2AA2B9B052E099D006D0211 /* SecPolicySearch.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecPolicySearch.cpp; sourceTree = ""; }; + C2AA2B9C052E099D006D0211 /* SecPolicySearch.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecPolicySearch.h; sourceTree = ""; }; + C2AA2B9F052E099D006D0211 /* SecTrust.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecTrust.cpp; sourceTree = ""; }; + C2AA2BA0052E099D006D0211 /* SecTrust.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrust.h; sourceTree = ""; }; + C2AA2BA1052E099D006D0211 /* SecTrustedApplication.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecTrustedApplication.cpp; sourceTree = ""; }; + C2AA2BA2052E099D006D0211 /* SecTrustedApplication.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrustedApplication.h; sourceTree = ""; }; + C2AA2BA3052E099D006D0211 /* SecTrustedApplicationPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrustedApplicationPriv.h; sourceTree = ""; }; + C2AA2BA4052E099D006D0211 /* SecTrustPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrustPriv.h; sourceTree = ""; }; + C2AA2BA5052E099D006D0211 /* Security.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Security.h; sourceTree = ""; }; + C2AA2BAA052E099D006D0211 /* StorageManager.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = StorageManager.cpp; sourceTree = ""; }; + C2AA2BAB052E099D006D0211 /* StorageManager.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = StorageManager.h; sourceTree = ""; }; + C2AA2BAC052E099D006D0211 /* Trust.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Trust.cpp; sourceTree = ""; }; + C2AA2BAD052E099D006D0211 /* Trust.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Trust.h; sourceTree = ""; }; + C2AA2BAE052E099D006D0211 /* TrustedApplication.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TrustedApplication.cpp; sourceTree = ""; }; + C2AA2BAF052E099D006D0211 /* TrustedApplication.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TrustedApplication.h; sourceTree = ""; }; + C2AA2BB0052E099D006D0211 /* TrustItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TrustItem.cpp; sourceTree = ""; }; + C2AA2BB1052E099D006D0211 /* TrustItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TrustItem.h; sourceTree = ""; }; + C2AA2BB2052E099D006D0211 /* TrustStore.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TrustStore.cpp; sourceTree = ""; }; + C2AA2BB3052E099D006D0211 /* TrustStore.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TrustStore.h; sourceTree = ""; }; + C2FD262F0731CEB40027896A /* defaultcreds.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = defaultcreds.h; path = lib/defaultcreds.h; sourceTree = SOURCE_ROOT; }; + C2FD26370731CEE60027896A /* defaultcreds.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = defaultcreds.cpp; path = lib/defaultcreds.cpp; sourceTree = SOURCE_ROOT; }; + C429431C053B2F8B00470431 /* KCUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = KCUtilities.cpp; sourceTree = ""; }; + C429431D053B2F8B00470431 /* KCUtilities.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = KCUtilities.h; sourceTree = ""; }; + C4A397A1053B1D50000E1B34 /* SecKeychainPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecKeychainPriv.h; sourceTree = ""; }; + C4A397FA053B21F9000E1B34 /* SecKeychainItemPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecKeychainItemPriv.h; sourceTree = ""; }; + D6E1457B0A632A5A008AA7E8 /* KCEventNotifier.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = KCEventNotifier.cpp; sourceTree = ""; }; + D6E1457C0A632A5A008AA7E8 /* KCEventNotifier.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = KCEventNotifier.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4C5719C612FB5E9E00B31F85 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + AA31456F134B716B00133245 /* CoreFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 182BB5CD146FF72B000BF1F3 /* libDER.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 52200F8A14F2B87F00F7F6E7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 52200F8B14F2B87F00F7F6E7 /* CoreFoundation.framework in Frameworks */, + 52B609D914F55B6800134209 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 05FB014005E5436B00A5194C /* Public API */ = { + isa = PBXGroup; + children = ( + 489C4FCB1202547600A8C58A /* SecRandom.h */, + C2AA2BA5052E099D006D0211 /* Security.h */, + C2AA2B79052E099D006D0211 /* SecBase.h */, + C2AA2B75052E099D006D0211 /* SecAccess.h */, + C2AA2B76052E099D006D0211 /* SecAccessPriv.h */, + C2AA2B78052E099D006D0211 /* SecACL.h */, + 4CF00660058A51180060AF78 /* SecBasePriv.h */, + C2AA2B7C052E099D006D0211 /* SecCertificate.h */, + 52FB44A81146D769006D3B0A /* SecCertificateOIDs.h */, + C2AA2B7E052E099D006D0211 /* SecCertificateBundle.h */, + C2AA2B7F052E099D006D0211 /* SecCertificatePriv.h */, + C2AA2B81052E099D006D0211 /* SecCertificateRequest.h */, + C2AA2B87052E099D006D0211 /* SecIdentity.h */, + C2AA2B88052E099D006D0211 /* SecIdentityPriv.h */, + C2AA2B8A052E099D006D0211 /* SecIdentitySearch.h */, + 30E17F5A062B0A25004208EB /* SecIdentitySearchPriv.h */, + 058AA95905D93B4300F543ED /* SecImportExport.h */, + BEE896E00A61F0BB00BF88A5 /* SecItem.h */, + BEE896E10A61F0BB00BF88A5 /* SecItemPriv.h */, + C2AA2B8C052E099D006D0211 /* SecKey.h */, + C2AA2B97052E099D006D0211 /* SecKeyPriv.h */, + C2AA2B8E052E099D006D0211 /* SecKeychain.h */, + C4A397A1053B1D50000E1B34 /* SecKeychainPriv.h */, + C2AA2B94052E099D006D0211 /* SecKeychainItem.h */, + C4A397FA053B21F9000E1B34 /* SecKeychainItemPriv.h */, + 05A83C360AAF591100906F28 /* SecKeychainItemExtendedAttributes.h */, + C2AA2B96052E099D006D0211 /* SecKeychainSearch.h */, + 1B11967A062F4C1800F3B659 /* SecKeychainSearchPriv.h */, + 407AC2BE066661620030E07D /* SecPassword.h */, + C2AA2B99052E099D006D0211 /* SecPolicy.h */, + C2AA2B9A052E099D006D0211 /* SecPolicyPriv.h */, + C2AA2B9C052E099D006D0211 /* SecPolicySearch.h */, + C2AA2BA0052E099D006D0211 /* SecTrust.h */, + C2AA2BA4052E099D006D0211 /* SecTrustPriv.h */, + 058C796F09F56CCB00DB7E98 /* SecTrustSettings.h */, + 058C797009F56CCB00DB7E98 /* SecTrustSettingsPriv.h */, + C2AA2BA2052E099D006D0211 /* SecTrustedApplication.h */, + C2AA2BA3052E099D006D0211 /* SecTrustedApplicationPriv.h */, + 058C797909F56D1400DB7E98 /* TrustSettingsSchema.h */, + ); + name = "Public API"; + sourceTree = ""; + }; + 05FB014305E5437C00A5194C /* API Bridge */ = { + isa = PBXGroup; + children = ( + C2AA2B74052E099D006D0211 /* SecAccess.cpp */, + C2AA2B77052E099D006D0211 /* SecACL.cpp */, + 4C21181A058A75B000014C42 /* SecBase.cpp */, + C2AA2B7A052E099D006D0211 /* SecBridge.h */, + C2AA2B7B052E099D006D0211 /* SecCertificate.cpp */, + C2AA2B7D052E099D006D0211 /* SecCertificateBundle.cpp */, + C2AA2B80052E099D006D0211 /* SecCertificateRequest.cpp */, + C2AA2B86052E099D006D0211 /* SecIdentity.cpp */, + C2AA2B89052E099D006D0211 /* SecIdentitySearch.cpp */, + BEE897100A62CDD800BF88A5 /* SecItemConstants.c */, + BEE896E60A61F12300BF88A5 /* SecItem.cpp */, + C2AA2B8B052E099D006D0211 /* SecKey.cpp */, + C2AA2B8D052E099D006D0211 /* SecKeychain.cpp */, + C2AA2B93052E099D006D0211 /* SecKeychainItem.cpp */, + 05A83C870AAF5E0A00906F28 /* SecKeychainItemExtendedAttributes.cpp */, + C2AA2B95052E099D006D0211 /* SecKeychainSearch.cpp */, + 407AC2BF066661620030E07D /* SecPassword.cpp */, + C2AA2B98052E099D006D0211 /* SecPolicy.cpp */, + C2AA2B9B052E099D006D0211 /* SecPolicySearch.cpp */, + C2AA2B9F052E099D006D0211 /* SecTrust.cpp */, + C2AA2BA1052E099D006D0211 /* SecTrustedApplication.cpp */, + 058C797509F56CFB00DB7E98 /* SecTrustSettings.cpp */, + ); + name = "API Bridge"; + sourceTree = ""; + }; + 05FB014605E5438300A5194C /* API Classes */ = { + isa = PBXGroup; + children = ( + 48E66AE2120254D700E878AD /* SecRandom.c */, + 52B88DF911DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.cpp */, + 52B88DFA11DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.h */, + 4885CFF611C8182D0093ECF6 /* SecRecoveryPassword.c */, + 4885CFF711C8182D0093ECF6 /* SecRecoveryPassword.h */, + C2AA2B42052E099D006D0211 /* Access.cpp */, + C2AA2B43052E099D006D0211 /* Access.h */, + C2AA2B44052E099D006D0211 /* ACL.cpp */, + C2AA2B45052E099D006D0211 /* ACL.h */, + C2AA2B48052E099D006D0211 /* Certificate.cpp */, + C2AA2B49052E099D006D0211 /* Certificate.h */, + C2AA2B4A052E099D006D0211 /* CertificateRequest.cpp */, + C2AA2B4B052E099D006D0211 /* CertificateRequest.h */, + 52BA735B112231C70012875E /* CertificateValues.cpp */, + 52BA735C112231C70012875E /* CertificateValues.h */, + 05A83C7E0AAF5CEA00906F28 /* ExtendedAttribute.cpp */, + 05A83C7D0AAF5CEA00906F28 /* ExtendedAttribute.h */, + C2AA2B56052E099D006D0211 /* Globals.cpp */, + C2AA2B57052E099D006D0211 /* Globals.h */, + C2AA2B58052E099D006D0211 /* Identity.cpp */, + C2AA2B59052E099D006D0211 /* Identity.h */, + C2AA2B5A052E099D006D0211 /* IdentityCursor.cpp */, + C2AA2B5B052E099D006D0211 /* IdentityCursor.h */, + C2AA2B5C052E099D006D0211 /* Item.cpp */, + C2AA2B5D052E099D006D0211 /* Item.h */, + C2AA2B5E052E099D006D0211 /* KCCursor.cpp */, + C2AA2B5F052E099D006D0211 /* KCCursor.h */, + C2AA2B67052E099D006D0211 /* Keychains.cpp */, + C2AA2B68052E099D006D0211 /* Keychains.h */, + C2AA2B69052E099D006D0211 /* KeyItem.cpp */, + C2AA2B6A052E099D006D0211 /* KeyItem.h */, + 407AC2C3066798420030E07D /* Password.cpp */, + 407AC2C2066798420030E07D /* Password.h */, + C2AA2B6B052E099D006D0211 /* Policies.cpp */, + C2AA2B6C052E099D006D0211 /* Policies.h */, + C2AA2B6D052E099D006D0211 /* PolicyCursor.cpp */, + C2AA2B6E052E099D006D0211 /* PolicyCursor.h */, + C2AA2B82052E099D006D0211 /* SecCFTypes.cpp */, + C2AA2B83052E099D006D0211 /* SecCFTypes.h */, + C2AA2B8F052E099D006D0211 /* SecKeychainAddIToolsPassword.cpp */, + 527067DB070246B300C5D30E /* iToolsTrustedApps.plist */, + C2AA2BAA052E099D006D0211 /* StorageManager.cpp */, + C2AA2BAC052E099D006D0211 /* Trust.cpp */, + C2AA2BAD052E099D006D0211 /* Trust.h */, + 055EA6B006AC5C13005079CE /* TrustRevocation.cpp */, + C2AA2BAE052E099D006D0211 /* TrustedApplication.cpp */, + C2AA2BAF052E099D006D0211 /* TrustedApplication.h */, + 058C797709F56D1400DB7E98 /* TrustSettings.cpp */, + 058C797809F56D1400DB7E98 /* TrustSettings.h */, + BECE5140106B056C0091E644 /* TrustKeychains.h */, + ); + name = "API Classes"; + sourceTree = ""; + }; + 05FB014905E5438C00A5194C /* Internal */ = { + isa = PBXGroup; + children = ( + 48E66AE4120254FC00E878AD /* SecRandomP.h */, + C2AA2B46052E099D006D0211 /* CCallbackMgr.cp */, + C2AA2B47052E099D006D0211 /* CCallbackMgr.h */, + C2AA2B4D052E099D006D0211 /* cssmdatetime.cpp */, + C2AA2B4E052E099D006D0211 /* cssmdatetime.h */, + C2FD26370731CEE60027896A /* defaultcreds.cpp */, + C2FD262F0731CEB40027896A /* defaultcreds.h */, + C2AA2B4F052E099D006D0211 /* DLDBListCFPref.cpp */, + C2AA2B50052E099D006D0211 /* DLDBListCFPref.h */, + 4CFDC28306CD9C6A007BEE7E /* DynamicDLDBList.cpp */, + 4CFDC28406CD9C6A007BEE7E /* DynamicDLDBList.h */, + D6E1457B0A632A5A008AA7E8 /* KCEventNotifier.cpp */, + D6E1457C0A632A5A008AA7E8 /* KCEventNotifier.h */, + C2AA2B64052E099D006D0211 /* KCExceptions.h */, + C429431C053B2F8B00470431 /* KCUtilities.cpp */, + C429431D053B2F8B00470431 /* KCUtilities.h */, + 4C868429058A55A10072F261 /* MacOSErrorStrings.h */, + C2AA2B6F052E099D006D0211 /* PrimaryKey.cpp */, + C2AA2B70052E099D006D0211 /* PrimaryKey.h */, + BE296DC40EAC2B5600FD22BE /* SecInternal.h */, + C2AA2BAB052E099D006D0211 /* StorageManager.h */, + BE50AE650F687AB900D28C54 /* TrustAdditions.cpp */, + BE50AE660F687AB900D28C54 /* TrustAdditions.h */, + C2AA2BB0052E099D006D0211 /* TrustItem.cpp */, + C2AA2BB1052E099D006D0211 /* TrustItem.h */, + C2AA2BB2052E099D006D0211 /* TrustStore.cpp */, + C2AA2BB3052E099D006D0211 /* TrustStore.h */, + C26BA9FE072580AE0049AF3C /* UnlockReferralItem.cpp */, + C2975B9B072580DC00AFECAD /* UnlockReferralItem.h */, + 058C797A09F56D1400DB7E98 /* TrustSettingsUtils.cpp */, + 058C797B09F56D1400DB7E98 /* TrustSettingsUtils.h */, + 52FB42C1113F056D006D3B0A /* debuggingP.h */, + 52C23EF71135AE5100E079D2 /* SecCertificatePrivP.h */, + 5261C30F112F1C560047EF8B /* SecBase64P.c */, + 5261C2E1112F19BA0047EF8B /* debuggingP.c */, + 5261C289112F0D570047EF8B /* SecFrameworkP.c */, + 521DC57D1125FEE300937BF2 /* SecCertificateP.c */, + 521DC57E1125FEE300937BF2 /* SecCertificateP.h */, + 4CCB00430580089000981D43 /* security_keychain.exp */, + 52008C6311496BD200E8CA78 /* SecCertificateInternalP.h */, + C2AA2B55052E099D006D0211 /* generateErrStrings.pl */, + 52E950CC1509B47000DA6511 /* tsaDERUtilities.c */, + 52E950D51509B48D00DA6511 /* tsaDERUtilities.h */, + ); + name = Internal; + sourceTree = ""; + }; + 05FB014C05E5439100A5194C /* Import/Export */ = { + isa = PBXGroup; + children = ( + 058AA95805D93B4300F543ED /* SecExport.cpp */, + 058AA9CD05D96FE600F543ED /* SecExternalRep.cpp */, + 058AA9C905D96FD200F543ED /* SecExternalRep.h */, + 058AA96B05D93CDD00F543ED /* SecImport.cpp */, + BE296DBE0EAC299C00FD22BE /* SecImportExport.c */, + 051A034705D9A68C00E02A64 /* SecImportExportAgg.cpp */, + 051A034F05D9A69900E02A64 /* SecImportExportAgg.h */, + 05012D45060B94A000C044CB /* SecImportExportCrypto.cpp */, + 05012D49060B94B200C044CB /* SecImportExportCrypto.h */, + 05AE95480AA748570076501C /* SecImportExportOpenSSH.cpp */, + 05AE95470AA748570076501C /* SecImportExportOpenSSH.h */, + 051A053205DAC86400E02A64 /* SecImportExportPem.cpp */, + 058AAA9105D97EAE00F543ED /* SecImportExportPem.h */, + 056CDA3805FD573B00820BC3 /* SecImportExportPkcs8.cpp */, + 056CDA8D05FD63C200820BC3 /* SecImportExportPkcs8.h */, + 054F90AD05E2860E0013C1D1 /* SecImportExportUtils.cpp */, + 054F90AF05E286180013C1D1 /* SecImportExportUtils.h */, + 05FB016605E54A3A00A5194C /* SecNetscapeTemplates.cpp */, + 05FB016705E54A3A00A5194C /* SecNetscapeTemplates.h */, + 056CDA6405FD5B3400820BC3 /* SecPkcs8Templates.cpp */, + 056CDA5C05FD5AEB00820BC3 /* SecPkcs8Templates.h */, + 052AF722060A3472003FEB8D /* SecWrappedKeys.cpp */, + ); + name = Import/Export; + sourceTree = ""; + }; + 0CBD4FF916C323E800713B6C /* regressions */ = { + isa = PBXGroup; + children = ( + 0CBD509C16C324B100713B6C /* keychain_regressions.h */, + 0CBD509816C3246D00713B6C /* kc-40-seckey.c */, + 0CBD509916C3246D00713B6C /* kc-41-sececkey.c */, + AC9ADAD2199AD6BA00BDAF54 /* kc-42-trust-revocation.c */, + 188BB53F171DD774009D22CE /* si-33-keychain-backup.c */, + ); + name = regressions; + sourceTree = ""; + }; + 182BB223146F063C000BF1F3 /* config */ = { + isa = PBXGroup; + children = ( + 182BB224146F063C000BF1F3 /* base.xcconfig */, + 182BB225146F063C000BF1F3 /* debug.xcconfig */, + 182BB226146F063C000BF1F3 /* lib.xcconfig */, + 182BB227146F063C000BF1F3 /* release.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 182BB30D146F0AE6000BF1F3 /* Products */ = { + isa = PBXGroup; + children = ( + 182BB312146F0AE6000BF1F3 /* libsecurity_utilities.a */, + ); + name = Products; + sourceTree = ""; + }; + 4C5719D712FB5F3300B31F85 /* xpc */ = { + isa = PBXGroup; + children = ( + AA31456E134B716B00133245 /* CoreFoundation.framework */, + 4C5719D812FB5F6800B31F85 /* main.c */, + 4C5719CA12FB5E9E00B31F85 /* XPCKeychainSandboxCheck-Info.plist */, + ); + name = xpc; + sourceTree = ""; + }; + 4CA1FEA7052A3C3800F22E42 = { + isa = PBXGroup; + children = ( + 182BB30C146F0AE6000BF1F3 /* libsecurity_utilities.xcodeproj */, + 5297A586112B78BB00EAA0C0 /* libDER.xcodeproj */, + 0CBD4FF916C323E800713B6C /* regressions */, + C2AA2B41052E099D006D0211 /* lib */, + 182BB223146F063C000BF1F3 /* config */, + 52200F9914F2B93700F7F6E7 /* xpc-tsa */, + 4C5719D712FB5F3300B31F85 /* xpc */, + 4CA1FEBF052A3C8100F22E42 /* Products */, + ); + sourceTree = ""; + }; + 4CA1FEBF052A3C8100F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + 4CA1FEBE052A3C8100F22E42 /* libsecurity_keychain.a */, + 4C5719C812FB5E9E00B31F85 /* XPCKeychainSandboxCheck.xpc */, + 52200F8F14F2B88000F7F6E7 /* XPCTimeStampingService.xpc */, + 0CBD509716C3242200713B6C /* libsecurity_keychain_regressions.a */, + ); + name = Products; + sourceTree = ""; + }; + 52200F9914F2B93700F7F6E7 /* xpc-tsa */ = { + isa = PBXGroup; + children = ( + 52B609D814F55B6800134209 /* Foundation.framework */, + 52200F9B14F2B93700F7F6E7 /* XPCTimeStampingService-Info.plist */, + 52B60A0614F5CA9500134209 /* main-tsa.m */, + 52B609E114F55BFA00134209 /* timestampclient.h */, + 52B609E214F55BFA00134209 /* timestampclient.m */, + ); + path = "xpc-tsa"; + sourceTree = ""; + }; + 5297A72A112CB13800EAA0C0 /* Products */ = { + isa = PBXGroup; + children = ( + 5297A731112CB13800EAA0C0 /* libDER.a */, + 5297A733112CB13800EAA0C0 /* parseCert */, + 5297A735112CB13800EAA0C0 /* libDERUtils.a */, + 5297A737112CB13800EAA0C0 /* parseCrl */, + 52FB45D511471AD0006D3B0A /* parseTicket */, + ); + name = Products; + sourceTree = ""; + }; + C2AA2B41052E099D006D0211 /* lib */ = { + isa = PBXGroup; + children = ( + 05FB014305E5437C00A5194C /* API Bridge */, + 05FB014005E5436B00A5194C /* Public API */, + 05FB014605E5438300A5194C /* API Classes */, + 05FB014905E5438C00A5194C /* Internal */, + 05FB014C05E5439100A5194C /* Import/Export */, + ); + path = lib; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4CF36F5D0581375900834D11 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 05FB016905E54A3A00A5194C /* SecNetscapeTemplates.h in Headers */, + 056CDA5D05FD5AEB00820BC3 /* SecPkcs8Templates.h in Headers */, + 4CF36F650581376700834D11 /* SecAccess.h in Headers */, + 4CF36F680581376700834D11 /* SecACL.h in Headers */, + 4CF36F6A0581376700834D11 /* SecBase.h in Headers */, + 4CF36F690581376700834D11 /* SecCertificate.h in Headers */, + 4CF36F6C0581376700834D11 /* SecIdentity.h in Headers */, + 4CF36F670581376700834D11 /* SecIdentitySearch.h in Headers */, + BEE896E20A61F0BB00BF88A5 /* SecItem.h in Headers */, + 4CF36F620581376700834D11 /* SecKey.h in Headers */, + 4CF36F5E0581376700834D11 /* SecKeychain.h in Headers */, + 4CF36F630581376700834D11 /* SecKeychainItem.h in Headers */, + 4CF36F5F0581376700834D11 /* SecKeychainSearch.h in Headers */, + 4CF36F660581376700834D11 /* SecPolicy.h in Headers */, + 4CF36F600581376700834D11 /* SecPolicySearch.h in Headers */, + 4CF36F610581376700834D11 /* SecTrust.h in Headers */, + 4CF36F6B0581376700834D11 /* SecTrustedApplication.h in Headers */, + 4CF36F640581376700834D11 /* Security.h in Headers */, + 058AA95B05D93B4300F543ED /* SecImportExport.h in Headers */, + 058C797109F56CCB00DB7E98 /* SecTrustSettings.h in Headers */, + 52FB44A91146D769006D3B0A /* SecCertificateOIDs.h in Headers */, + 489C4FCC1202547600A8C58A /* SecRandom.h in Headers */, + 05AE95490AA748570076501C /* SecImportExportOpenSSH.h in Headers */, + BE296DC50EAC2B5600FD22BE /* SecInternal.h in Headers */, + BE50AE680F687AB900D28C54 /* TrustAdditions.h in Headers */, + 52B88DFC11DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.h in Headers */, + 407AC2C0066661620030E07D /* SecPassword.h in Headers */, + 4C86848C058A59430072F261 /* MacOSErrorStrings.h in Headers */, + 4CF36F720581377300834D11 /* SecAccessPriv.h in Headers */, + 4CF00661058A51180060AF78 /* SecBasePriv.h in Headers */, + 4CF36F790581377300834D11 /* SecCertificateBundle.h in Headers */, + 4CF36F760581377300834D11 /* SecCertificatePriv.h in Headers */, + 4CF36F710581377300834D11 /* SecCertificateRequest.h in Headers */, + 4CF36F740581377300834D11 /* SecIdentityPriv.h in Headers */, + 4CF36F6F0581377300834D11 /* SecKeychainItemPriv.h in Headers */, + 4CF36F730581377300834D11 /* SecKeychainPriv.h in Headers */, + 4CF36F780581377300834D11 /* SecKeyPriv.h in Headers */, + 4CF36F6E0581377300834D11 /* SecPolicyPriv.h in Headers */, + 4CF36F750581377300834D11 /* SecTrustedApplicationPriv.h in Headers */, + 4CF36F700581377300834D11 /* SecTrustPriv.h in Headers */, + 058AA9CA05D96FD200F543ED /* SecExternalRep.h in Headers */, + 058AAA9205D97EAE00F543ED /* SecImportExportPem.h in Headers */, + 051A035005D9A69900E02A64 /* SecImportExportAgg.h in Headers */, + 054F90B005E286180013C1D1 /* SecImportExportUtils.h in Headers */, + 056CDA8E05FD63C200820BC3 /* SecImportExportPkcs8.h in Headers */, + 05012D4A060B94B200C044CB /* SecImportExportCrypto.h in Headers */, + 30E17F5B062B0A25004208EB /* SecIdentitySearchPriv.h in Headers */, + 1B11967B062F4C1800F3B659 /* SecKeychainSearchPriv.h in Headers */, + 058C797209F56CCC00DB7E98 /* SecTrustSettingsPriv.h in Headers */, + 058C797D09F56D1400DB7E98 /* TrustSettings.h in Headers */, + 058C797E09F56D1400DB7E98 /* TrustSettingsSchema.h in Headers */, + 058C798009F56D1400DB7E98 /* TrustSettingsUtils.h in Headers */, + BEE896E30A61F0BB00BF88A5 /* SecItemPriv.h in Headers */, + 05A83C380AAF591100906F28 /* SecKeychainItemExtendedAttributes.h in Headers */, + BECE5141106B056C0091E644 /* TrustKeychains.h in Headers */, + 52008C6411496BD200E8CA78 /* SecCertificateInternalP.h in Headers */, + 4885CFF911C8182D0093ECF6 /* SecRecoveryPassword.h in Headers */, + 48E66AE5120254FC00E878AD /* SecRandomP.h in Headers */, + 52BA735E112231C70012875E /* CertificateValues.h in Headers */, + 521DC5801125FEE300937BF2 /* SecCertificateP.h in Headers */, + 52C23EF81135AE5100E079D2 /* SecCertificatePrivP.h in Headers */, + 52E950D61509B48D00DA6511 /* tsaDERUtilities.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 0CBD500016C3242200713B6C /* libsecurity_keychain_regressions */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0CBD509416C3242200713B6C /* Build configuration list for PBXNativeTarget "libsecurity_keychain_regressions" */; + buildPhases = ( + 0CBD504416C3242200713B6C /* Sources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libsecurity_keychain_regressions; + productName = libsecurity_keychain; + productReference = 0CBD509716C3242200713B6C /* libsecurity_keychain_regressions.a */; + productType = "com.apple.product-type.library.static"; + }; + 4C5719C712FB5E9E00B31F85 /* XPCKeychainSandboxCheck */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4C5719CF12FB5E9F00B31F85 /* Build configuration list for PBXNativeTarget "XPCKeychainSandboxCheck" */; + buildPhases = ( + 4C5719C512FB5E9E00B31F85 /* Sources */, + 4C5719C612FB5E9E00B31F85 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = XPCKeychainSandboxCheck; + productName = XPCKeychainSandboxCheck; + productReference = 4C5719C812FB5E9E00B31F85 /* XPCKeychainSandboxCheck.xpc */; + productType = "com.apple.product-type.application"; + }; + 4CA1FEBD052A3C8100F22E42 /* libsecurity_keychain */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD37C0987FCDE001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_keychain" */; + buildPhases = ( + 4CF36F5D0581375900834D11 /* Headers */, + 4CA1FEBA052A3C8100F22E42 /* Sources */, + 4CA1FEBB052A3C8100F22E42 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 182BB341146F106C000BF1F3 /* PBXTargetDependency */, + 521FBA8C112CB465002BEF54 /* PBXTargetDependency */, + ); + name = libsecurity_keychain; + productName = libsecurity_keychain; + productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_keychain.a */; + productType = "com.apple.product-type.library.static"; + }; + 52200F8714F2B87F00F7F6E7 /* XPCTimeStampingService */ = { + isa = PBXNativeTarget; + buildConfigurationList = 52200F8C14F2B87F00F7F6E7 /* Build configuration list for PBXNativeTarget "XPCTimeStampingService" */; + buildPhases = ( + 52200F8814F2B87F00F7F6E7 /* Sources */, + 52200F8A14F2B87F00F7F6E7 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = XPCTimeStampingService; + productName = XPCTimeStampingService; + productReference = 52200F8F14F2B88000F7F6E7 /* XPCTimeStampingService.xpc */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA1FEAB052A3C3800F22E42 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + }; + buildConfigurationList = C27AD3810987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_keychain" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 4CA1FEA7052A3C3800F22E42; + productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 5297A72A112CB13800EAA0C0 /* Products */; + ProjectRef = 5297A586112B78BB00EAA0C0 /* libDER.xcodeproj */; + }, + { + ProductGroup = 182BB30D146F0AE6000BF1F3 /* Products */; + ProjectRef = 182BB30C146F0AE6000BF1F3 /* libsecurity_utilities.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 4CA1FEBD052A3C8100F22E42 /* libsecurity_keychain */, + 4C5719C712FB5E9E00B31F85 /* XPCKeychainSandboxCheck */, + 52200F8714F2B87F00F7F6E7 /* XPCTimeStampingService */, + 0CBD500016C3242200713B6C /* libsecurity_keychain_regressions */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 182BB312146F0AE6000BF1F3 /* libsecurity_utilities.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_utilities.a; + remoteRef = 182BB311146F0AE6000BF1F3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 5297A731112CB13800EAA0C0 /* libDER.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libDER.a; + remoteRef = 5297A730112CB13800EAA0C0 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 5297A733112CB13800EAA0C0 /* parseCert */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = parseCert; + remoteRef = 5297A732112CB13800EAA0C0 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 5297A735112CB13800EAA0C0 /* libDERUtils.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libDERUtils.a; + remoteRef = 5297A734112CB13800EAA0C0 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 5297A737112CB13800EAA0C0 /* parseCrl */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = parseCrl; + remoteRef = 5297A736112CB13800EAA0C0 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 52FB45D511471AD0006D3B0A /* parseTicket */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = parseTicket; + remoteRef = 52FB45D411471AD0006D3B0A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXSourcesBuildPhase section */ + 0CBD504416C3242200713B6C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AC9ADAD3199AD6BA00BDAF54 /* kc-42-trust-revocation.c in Sources */, + 0CBD509B16C3246D00713B6C /* kc-41-sececkey.c in Sources */, + 188BB546171DD8B5009D22CE /* si-33-keychain-backup.c in Sources */, + 0CBD509A16C3246D00713B6C /* kc-40-seckey.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C5719C512FB5E9E00B31F85 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C5719DB12FB5F6800B31F85 /* main.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CA1FEBA052A3C8100F22E42 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C2AA2BB4052E099D006D0211 /* Access.cpp in Sources */, + C2AA2BB6052E099D006D0211 /* ACL.cpp in Sources */, + C2AA2BB8052E099D006D0211 /* CCallbackMgr.cp in Sources */, + C2AA2BBA052E099D006D0211 /* Certificate.cpp in Sources */, + C2AA2BBC052E099D006D0211 /* CertificateRequest.cpp in Sources */, + C2AA2BBF052E099D006D0211 /* cssmdatetime.cpp in Sources */, + C2FD26380731CEFB0027896A /* defaultcreds.cpp in Sources */, + C2AA2BC1052E099D006D0211 /* DLDBListCFPref.cpp in Sources */, + 4CFDC28506CD9C6A007BEE7E /* DynamicDLDBList.cpp in Sources */, + C2AA2BC7052E099D006D0211 /* Globals.cpp in Sources */, + C2AA2BC9052E099D006D0211 /* Identity.cpp in Sources */, + C2AA2BCB052E099D006D0211 /* IdentityCursor.cpp in Sources */, + C2AA2BCD052E099D006D0211 /* Item.cpp in Sources */, + D6095E960A94F17C0026C68B /* KCEventNotifier.cpp in Sources */, + C2AA2BCF052E099D006D0211 /* KCCursor.cpp in Sources */, + C429431E053B2F8B00470431 /* KCUtilities.cpp in Sources */, + C2AA2BD8052E099D006D0211 /* Keychains.cpp in Sources */, + C2AA2BDA052E099D006D0211 /* KeyItem.cpp in Sources */, + 407AC2C5066798420030E07D /* Password.cpp in Sources */, + C2AA2BDC052E099D006D0211 /* Policies.cpp in Sources */, + C2AA2BDE052E099D006D0211 /* PolicyCursor.cpp in Sources */, + C2AA2BE0052E099D006D0211 /* PrimaryKey.cpp in Sources */, + C2AA2BE4052E099D006D0211 /* SecAccess.cpp in Sources */, + C2AA2BE7052E099D006D0211 /* SecACL.cpp in Sources */, + 4C21181B058A75B000014C42 /* SecBase.cpp in Sources */, + C2AA2BEB052E099D006D0211 /* SecCertificate.cpp in Sources */, + C2AA2BED052E099D006D0211 /* SecCertificateBundle.cpp in Sources */, + C2AA2BF0052E099D006D0211 /* SecCertificateRequest.cpp in Sources */, + C2AA2BF2052E099D006D0211 /* SecCFTypes.cpp in Sources */, + C2AA2BF6052E099D006D0211 /* SecIdentity.cpp in Sources */, + C2AA2BF9052E099D006D0211 /* SecIdentitySearch.cpp in Sources */, + C2AA2BFB052E099D006D0211 /* SecKey.cpp in Sources */, + C2AA2BFD052E099D006D0211 /* SecKeychain.cpp in Sources */, + C2AA2BFF052E099D006D0211 /* SecKeychainAddIToolsPassword.cpp in Sources */, + C2AA2C03052E099D006D0211 /* SecKeychainItem.cpp in Sources */, + C2AA2C05052E099D006D0211 /* SecKeychainSearch.cpp in Sources */, + 407AC2C1066661620030E07D /* SecPassword.cpp in Sources */, + C2AA2C08052E099D006D0211 /* SecPolicy.cpp in Sources */, + C2AA2C0B052E099D006D0211 /* SecPolicySearch.cpp in Sources */, + C2AA2C0F052E099D006D0211 /* SecTrust.cpp in Sources */, + C2AA2C11052E099D006D0211 /* SecTrustedApplication.cpp in Sources */, + C2AA2C1A052E099D006D0211 /* StorageManager.cpp in Sources */, + C2AA2C1C052E099D006D0211 /* Trust.cpp in Sources */, + C2AA2C1E052E099D006D0211 /* TrustedApplication.cpp in Sources */, + C2AA2C20052E099D006D0211 /* TrustItem.cpp in Sources */, + C2AA2C22052E099D006D0211 /* TrustStore.cpp in Sources */, + 058AA95A05D93B4300F543ED /* SecExport.cpp in Sources */, + 058AA96C05D93CDD00F543ED /* SecImport.cpp in Sources */, + 058AA9CE05D96FE600F543ED /* SecExternalRep.cpp in Sources */, + 051A034805D9A68C00E02A64 /* SecImportExportAgg.cpp in Sources */, + 051A053305DAC86400E02A64 /* SecImportExportPem.cpp in Sources */, + 054F90AE05E2860E0013C1D1 /* SecImportExportUtils.cpp in Sources */, + 05FB016805E54A3A00A5194C /* SecNetscapeTemplates.cpp in Sources */, + 056CDA3905FD573B00820BC3 /* SecImportExportPkcs8.cpp in Sources */, + 056CDA6505FD5B3400820BC3 /* SecPkcs8Templates.cpp in Sources */, + 052AF723060A3472003FEB8D /* SecWrappedKeys.cpp in Sources */, + 05012D46060B94A000C044CB /* SecImportExportCrypto.cpp in Sources */, + 055EA6B106AC5C13005079CE /* TrustRevocation.cpp in Sources */, + C26BA9FF072580AE0049AF3C /* UnlockReferralItem.cpp in Sources */, + 058C797609F56CFB00DB7E98 /* SecTrustSettings.cpp in Sources */, + 058C797C09F56D1400DB7E98 /* TrustSettings.cpp in Sources */, + 058C797F09F56D1400DB7E98 /* TrustSettingsUtils.cpp in Sources */, + BEE896E70A61F12300BF88A5 /* SecItem.cpp in Sources */, + BEA830070EB17344001CA937 /* SecItemConstants.c in Sources */, + 05AE954A0AA748580076501C /* SecImportExportOpenSSH.cpp in Sources */, + 05A83C800AAF5CEA00906F28 /* ExtendedAttribute.cpp in Sources */, + 05A83C880AAF5E0A00906F28 /* SecKeychainItemExtendedAttributes.cpp in Sources */, + BE296DBF0EAC299C00FD22BE /* SecImportExport.c in Sources */, + BE50AE670F687AB900D28C54 /* TrustAdditions.cpp in Sources */, + 52BA735D112231C70012875E /* CertificateValues.cpp in Sources */, + 521DC57F1125FEE300937BF2 /* SecCertificateP.c in Sources */, + 5261C28A112F0D570047EF8B /* SecFrameworkP.c in Sources */, + 5261C310112F1C560047EF8B /* SecBase64P.c in Sources */, + 4885CFF811C8182D0093ECF6 /* SecRecoveryPassword.c in Sources */, + 52B88DFB11DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.cpp in Sources */, + 48E66AE3120254D700E878AD /* SecRandom.c in Sources */, + 52E950CD1509B47000DA6511 /* tsaDERUtilities.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 52200F8814F2B87F00F7F6E7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 52B609E314F55BFA00134209 /* timestampclient.m in Sources */, + 52B60A0714F5CA9600134209 /* main-tsa.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 182BB341146F106C000BF1F3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_utilitiesDTrace; + targetProxy = 182BB340146F106C000BF1F3 /* PBXContainerItemProxy */; + }; + 521FBA8C112CB465002BEF54 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libDER; + targetProxy = 521FBA8B112CB465002BEF54 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 0CBD509516C3242200713B6C /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB225146F063C000BF1F3 /* debug.xcconfig */; + buildSettings = { + WARNING_CFLAGS = ( + "$(inherited)", + "-Wno-error=overloaded-virtual", + ); + }; + name = Debug; + }; + 0CBD509616C3242200713B6C /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB227146F063C000BF1F3 /* release.xcconfig */; + buildSettings = { + WARNING_CFLAGS = ( + "$(inherited)", + "-Wno-error=overloaded-virtual", + ); + }; + name = Release; + }; + 4C5719CB12FB5E9F00B31F85 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB225146F063C000BF1F3 /* debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + GCC_MODEL_TUNING = G5; + INFOPLIST_FILE = "xpc/XPCKeychainSandboxCheck-Info.plist"; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; + PRODUCT_NAME = XPCKeychainSandboxCheck; + PROVISIONING_PROFILE = ""; + SKIP_INSTALL = NO; + WRAPPER_EXTENSION = xpc; + }; + name = Debug; + }; + 4C5719CE12FB5E9F00B31F85 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB227146F063C000BF1F3 /* release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + GCC_MODEL_TUNING = G5; + INFOPLIST_FILE = "xpc/XPCKeychainSandboxCheck-Info.plist"; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; + PRODUCT_NAME = XPCKeychainSandboxCheck; + PROVISIONING_PROFILE = ""; + SKIP_INSTALL = NO; + WRAPPER_EXTENSION = xpc; + }; + name = Release; + }; + 52200F8D14F2B87F00F7F6E7 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB225146F063C000BF1F3 /* debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + GCC_MODEL_TUNING = G5; + INFOPLIST_FILE = "xpc-tsa/XPCTimeStampingService-Info.plist"; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; + PRODUCT_NAME = XPCTimeStampingService; + PROVISIONING_PROFILE = ""; + SKIP_INSTALL = NO; + WRAPPER_EXTENSION = xpc; + }; + name = Debug; + }; + 52200F8E14F2B87F00F7F6E7 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB227146F063C000BF1F3 /* release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + GCC_MODEL_TUNING = G5; + INFOPLIST_FILE = "xpc-tsa/XPCTimeStampingService-Info.plist"; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; + PRODUCT_NAME = XPCTimeStampingService; + PROVISIONING_PROFILE = ""; + SKIP_INSTALL = NO; + WRAPPER_EXTENSION = xpc; + }; + name = Release; + }; + C27AD37D0987FCDE001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB225146F063C000BF1F3 /* debug.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/libDER", + ); + WARNING_CFLAGS = ( + "$(inherited)", + "-Wno-error=overloaded-virtual", + ); + }; + name = Debug; + }; + C27AD3800987FCDE001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB227146F063C000BF1F3 /* release.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/libDER", + ); + WARNING_CFLAGS = ( + "$(inherited)", + "-Wno-error=overloaded-virtual", + ); + }; + name = Release; + }; + C27AD3820987FCDE001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB226146F063C000BF1F3 /* lib.xcconfig */; + buildSettings = { + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + }; + name = Debug; + }; + C27AD3850987FCDE001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB226146F063C000BF1F3 /* lib.xcconfig */; + buildSettings = { + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 0CBD509416C3242200713B6C /* Build configuration list for PBXNativeTarget "libsecurity_keychain_regressions" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0CBD509516C3242200713B6C /* Debug */, + 0CBD509616C3242200713B6C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4C5719CF12FB5E9F00B31F85 /* Build configuration list for PBXNativeTarget "XPCKeychainSandboxCheck" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4C5719CB12FB5E9F00B31F85 /* Debug */, + 4C5719CE12FB5E9F00B31F85 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 52200F8C14F2B87F00F7F6E7 /* Build configuration list for PBXNativeTarget "XPCTimeStampingService" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 52200F8D14F2B87F00F7F6E7 /* Debug */, + 52200F8E14F2B87F00F7F6E7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD37C0987FCDE001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_keychain" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD37D0987FCDE001272E0 /* Debug */, + C27AD3800987FCDE001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD3810987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_keychain" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD3820987FCDE001272E0 /* Debug */, + C27AD3850987FCDE001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; +} diff --git a/libsecurity_keychain/plist/iToolsTrustedApps.plist b/Security/libsecurity_keychain/plist/iToolsTrustedApps.plist similarity index 100% rename from libsecurity_keychain/plist/iToolsTrustedApps.plist rename to Security/libsecurity_keychain/plist/iToolsTrustedApps.plist diff --git a/libsecurity_keychain/regressions/kc-40-seckey.c b/Security/libsecurity_keychain/regressions/kc-40-seckey.c similarity index 80% rename from libsecurity_keychain/regressions/kc-40-seckey.c rename to Security/libsecurity_keychain/regressions/kc-40-seckey.c index fdc21144..57b7bf39 100644 --- a/libsecurity_keychain/regressions/kc-40-seckey.c +++ b/Security/libsecurity_keychain/regressions/kc-40-seckey.c @@ -1,24 +1,39 @@ /* - * si-40-seckey.c - * Security - * - * Created by Michael Brouwer on 1/29/07. - * Copyright (c) 2007-2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2009,2013-2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include #include #include #include #include #include +#include #if 0 #include #include #include -#include #include #include #include @@ -473,8 +488,100 @@ static void testkeygen2(size_t keySizeInBits) { CFRelease(privd); } + +#if !TARGET_OS_IPHONE +// Only exists currently in MacOSX +typedef struct KDFVector_t { + char *password; + char *salt; + int rounds; + int alg; + int dklen; + char *expectedstr; + int expected_failure; +} KDFVector; + +static KDFVector kdfv[] = { + // Test Case PBKDF2 - HMACSHA1 http://tools.ietf.org/html/draft-josefsson-pbkdf2-test-vectors-00 + { "password", "salt", 1, 1, 160, "0c60c80f961f0e71f3a9b524af6012062fe037a6", 0 }, + { "password", "salt", 2, 1, 160, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957", 0 }, + { "password", "salt", 4096, 1, 160, "4b007901b765489abead49d926f721d065a429c1", 0 }, + { "password", "salt", 1, 0, 160, NULL, -1} // This crashed +}; + +static size_t kdfvLen = sizeof(kdfv) / sizeof(KDFVector); + +static int testSecKDF(CFStringRef password, CFDataRef salt, CFNumberRef rounds, CFDataRef alg, CFNumberRef dklen, CFDataRef expected, int expected_failure) { + CFMutableDictionaryRef parameters = CFDictionaryCreateMutable(kCFAllocatorDefault, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + int retval = 0; + + CFDictionaryAddValue(parameters, kSecAttrSalt, salt); + CFDictionaryAddValue(parameters, kSecAttrKeySizeInBits, dklen); + CFDictionaryAddValue(parameters, kSecAttrPRF, alg); + CFDictionaryAddValue(parameters, kSecAttrRounds, rounds); + + SecKeyRef derivedKey = SecKeyDeriveFromPassword(password, parameters, NULL); + if(derivedKey == NULL && expected_failure) { + ok(1, "Correctly failed to produce a key"); + goto errOut; + } else if(derivedKey == NULL) { + ok(0, "Could not generate a key when we should have"); + goto errOut; + } + ok(1, "Made a new key"); + retval = 1; + // NEEDS Fix -- ok(status = expectedEqualsComputed(expected, derivedKey), "Derived key is as expected"); +errOut: + if(parameters) CFRelease(parameters); + if(derivedKey) CFRelease(derivedKey); + return retval; +} + +static CFDataRef CFDataCreateFromHexBytes(char *s) { + if(!s) return NULL; + size_t len = strlen(s); + if(len%2) return NULL; + len /= 2; + uint8_t buf[len]; + for(size_t i=0; iexpectedstr); + CFStringRef password = CFStringCreateWithCString(NULL, kdfvec->password, kCFStringEncodingUTF8); + CFDataRef salt = CFDataCreate(NULL, (const UInt8 *)kdfvec->salt, strlen(kdfvec->salt)); + CFNumberRef rounds = CFNumberCreate(NULL, kCFNumberIntType, &kdfvec->rounds); + CFNumberRef dklen = CFNumberCreate(NULL, kCFNumberIntType, &kdfvec->dklen); + int status = 1; + + ok(testSecKDF(password, salt, rounds, kSecAttrPRFHmacAlgSHA1, dklen, expectedBytes, kdfvec->expected_failure), "Test SecKeyDeriveFromPassword PBKDF2"); + + if(expectedBytes) CFRelease(expectedBytes); + return status; +} + + +static void testkeyderivation() { + for(size_t testcase = 0; testcase < kdfvLen; testcase++) { + // diag("Test %lu\n", testcase + 1); + ok(PBKDF2Test(&kdfv[testcase]), "Successful full test of KDF Vector"); + } +} + +#else +static size_t kdfvLen = 0; // no kdf functions in Sec for iphone +#endif /* !TARGET_OS_IPHONE */ + + /* Test basic add delete update copy matching stuff. */ -#define kTestCount ((2 * kKeyGenTestCount) + kKeyGen2TestCount) +#define kTestCount ((2 * kKeyGenTestCount) + kKeyGen2TestCount + (int) (kdfvLen*3)) static void tests(void) { /* Comment out lines below for testing generating all common key sizes, @@ -487,6 +594,9 @@ static void tests(void) //testkeygen(4096); testkeygen2(1024); // lots of FAIL! +#if !TARGET_OS_IPHONE + testkeyderivation(); +#endif } int kc_40_seckey(int argc, char *const *argv) diff --git a/libsecurity_keychain/regressions/kc-41-sececkey.c b/Security/libsecurity_keychain/regressions/kc-41-sececkey.c similarity index 91% rename from libsecurity_keychain/regressions/kc-41-sececkey.c rename to Security/libsecurity_keychain/regressions/kc-41-sececkey.c index 0e6be61b..e1836650 100644 --- a/libsecurity_keychain/regressions/kc-41-sececkey.c +++ b/Security/libsecurity_keychain/regressions/kc-41-sececkey.c @@ -1,17 +1,32 @@ -// -// si-41-sececkey.c -// regressions -// -// Created by Mitch Adler on 5/20/11. -// Copyright 2011 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2011,2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + /* * si-40-seckey.c * Security * - * Created by Michael Brouwer on 1/29/07. - * Copyright (c) 2007-2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2009,2013-2014 Apple Inc. All Rights Reserved. * */ #include diff --git a/Security/libsecurity_keychain/regressions/kc-42-trust-revocation.c b/Security/libsecurity_keychain/regressions/kc-42-trust-revocation.c new file mode 100644 index 00000000..a33b30d9 --- /dev/null +++ b/Security/libsecurity_keychain/regressions/kc-42-trust-revocation.c @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +//#include + +#include "keychain_regressions.h" +#include "utilities/SecCFRelease.h" + +/* subject:/1.3.6.1.4.1.311.60.2.1.3=US/1.3.6.1.4.1.311.60.2.1.2=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 */ +/* issuer :/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)06/CN=VeriSign Class 3 Extended Validation SSL CA */ +unsigned char leaf_certificate[1548]={ + 0x30,0x82,0x06,0x08,0x30,0x82,0x04,0xF0,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x08, + 0x34,0xE4,0x53,0xD4,0x3A,0x68,0x57,0x23,0xAF,0xFB,0xB1,0x33,0xCE,0x45,0x7C,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x81, + 0xBA,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,0x3B,0x30,0x39,0x06,0x03,0x55,0x04, + 0x0B,0x13,0x32,0x54,0x65,0x72,0x6D,0x73,0x20,0x6F,0x66,0x20,0x75,0x73,0x65,0x20, + 0x61,0x74,0x20,0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x76, + 0x65,0x72,0x69,0x73,0x69,0x67,0x6E,0x2E,0x63,0x6F,0x6D,0x2F,0x72,0x70,0x61,0x20, + 0x28,0x63,0x29,0x30,0x36,0x31,0x34,0x30,0x32,0x06,0x03,0x55,0x04,0x03,0x13,0x2B, + 0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6E,0x20,0x43,0x6C,0x61,0x73,0x73,0x20,0x33, + 0x20,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x20,0x56,0x61,0x6C,0x69,0x64,0x61, + 0x74,0x69,0x6F,0x6E,0x20,0x53,0x53,0x4C,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31, + 0x34,0x30,0x34,0x31,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x31,0x35, + 0x30,0x34,0x30,0x32,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,0xBE,0xAE,0x46,0x4D,0x99,0x6E,0x6D, + 0x6C,0x35,0x4B,0x88,0x32,0x38,0xBB,0xDC,0xD0,0x09,0x95,0xD0,0x9A,0xE4,0x36,0xE7, + 0x9F,0x0A,0xB0,0xF2,0xD7,0xD2,0x30,0x62,0x03,0x1F,0xAD,0xC6,0xF4,0x6D,0x10,0x84, + 0xF7,0x79,0x1B,0xBC,0x74,0xC0,0xA8,0xE3,0x82,0xFE,0xD4,0x0A,0x93,0x2E,0x3D,0x4B, + 0x12,0x24,0xAD,0xAD,0x5F,0x5D,0xED,0x1C,0xC9,0x1C,0x6F,0x13,0x7B,0xE2,0xC1,0x25, + 0x4E,0x46,0x5F,0x4F,0x3B,0x2E,0x5A,0xCB,0xC1,0x5A,0xB4,0x82,0xCF,0xAD,0xA3,0x65, + 0xE8,0x86,0x33,0xB5,0xED,0x1D,0x78,0x99,0xA7,0xC7,0xD5,0xFA,0x10,0x2E,0xFB,0x11, + 0x4E,0x23,0x58,0x06,0x96,0x87,0x71,0x75,0x51,0x73,0x8C,0x0F,0xF4,0xCA,0x7C,0x8F, + 0x91,0x25,0x79,0x13,0xDC,0xB0,0xF0,0xDE,0x08,0x07,0x01,0x0B,0x64,0xCC,0x57,0x6A, + 0x12,0x86,0x62,0x17,0x3E,0x5D,0xB9,0x62,0x3D,0x58,0x7B,0x2A,0x6E,0xF6,0xA6,0x30, + 0x41,0x02,0xFC,0xEC,0x64,0x72,0x33,0xD5,0xD5,0x3F,0x6B,0x6D,0x97,0xF3,0xC1,0x61, + 0xBF,0x38,0x3B,0xAB,0x41,0x47,0xD4,0xC2,0x03,0xD7,0x3B,0x59,0x57,0x9D,0xE1,0xA1, + 0x2A,0xD6,0x78,0xE8,0x83,0x5D,0x3D,0xDD,0xAA,0x5D,0x17,0xFD,0x94,0xD6,0xE5,0x7A, + 0xEF,0x02,0x63,0xC6,0xA3,0xC6,0x2D,0x5B,0x33,0x08,0x8B,0xF5,0xA5,0x03,0xB4,0xFE, + 0xF2,0x1D,0xAB,0xBF,0x5E,0x9E,0xB8,0x78,0x39,0x20,0x2B,0x68,0x61,0x4F,0xE4,0x99, + 0xF2,0xAA,0xC2,0x4D,0x4B,0x48,0xCB,0x68,0xC2,0x10,0x3F,0xFA,0x9A,0xBA,0xC5,0x6A, + 0x53,0x8F,0x22,0xF3,0xD7,0xC9,0xED,0xA4,0xD5,0x02,0x03,0x01,0x00,0x01,0xA3,0x82, + 0x01,0xB6,0x30,0x82,0x01,0xB2,0x30,0x67,0x06,0x03,0x55,0x1D,0x11,0x04,0x60,0x30, + 0x5E,0x82,0x0E,0x77,0x77,0x77,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,0x0C,0x63,0x2E,0x70,0x61,0x79,0x70,0x61,0x6C,0x2E,0x63,0x6F, + 0x6D,0x82,0x0E,0x74,0x6D,0x73,0x2E,0x70,0x61,0x79,0x70,0x61,0x6C,0x2E,0x63,0x6F, + 0x6D,0x82,0x0C,0x74,0x6D,0x73,0x2E,0x65,0x62,0x61,0x79,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,0xFC,0x8A, + 0x50,0xBA,0x9E,0xB9,0x25,0x5A,0x7B,0x55,0x85,0x4F,0x95,0x00,0x63,0x8F,0xE9,0x58, + 0x6B,0x43,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,0x61,0x2E,0x73, + 0x79,0x6D,0x63,0x62,0x2E,0x63,0x6F,0x6D,0x2F,0x73,0x61,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,0x61,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,0x61,0x2E,0x73,0x79,0x6D,0x63,0x62,0x2E,0x63,0x6F, + 0x6D,0x2F,0x73,0x61,0x2E,0x63,0x72,0x74,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x76,0x08,0xAB,0x64, + 0xF6,0xF4,0x0B,0xE4,0x81,0xBD,0x59,0xB2,0x3E,0xA4,0xFC,0xF5,0x03,0x75,0x04,0x59, + 0x6A,0xB5,0xFE,0x12,0x34,0x2A,0x04,0x9C,0x89,0xCD,0xCB,0xE1,0x3C,0x6C,0x20,0x39, + 0xD4,0xEA,0x6F,0x27,0x34,0x7F,0x62,0x1C,0x45,0x72,0x11,0x39,0xC0,0x45,0xAA,0x2A, + 0x35,0x5C,0xB6,0x06,0xE3,0x08,0xA7,0x8F,0x08,0xAF,0x80,0xB2,0x10,0xCE,0xA5,0x28, + 0x5B,0x1C,0x49,0x55,0x11,0xEB,0x6B,0x2A,0x80,0xC1,0x09,0xED,0x82,0x72,0x48,0xCA, + 0x19,0x8B,0xE5,0x34,0x94,0x3C,0x50,0x26,0x77,0x6B,0x1A,0x63,0xBA,0x6F,0x63,0xD1, + 0x58,0xED,0x2B,0x1D,0xB7,0xA7,0x6E,0x04,0x25,0x99,0xC3,0x94,0x03,0x90,0xEC,0x0F, + 0x4C,0x93,0x83,0x35,0x86,0xE3,0x70,0x84,0x0D,0x3C,0xCE,0xAF,0x4E,0x80,0x4A,0xD3, + 0x91,0x3F,0x55,0x33,0x2F,0x1F,0x67,0x87,0x2F,0x09,0xA2,0x41,0xC0,0x10,0x4A,0x2C, + 0xC4,0x88,0xA0,0x6F,0x93,0x2C,0xEF,0x38,0xD2,0x61,0xC7,0xEC,0xF3,0x37,0x7D,0xC9, + 0x32,0xA5,0x5C,0x1E,0x48,0x0E,0x85,0x6C,0x47,0x2A,0x7F,0xC6,0x30,0x5E,0xC2,0xF6, + 0x2E,0xDD,0xE3,0x4D,0xAC,0xFF,0xEF,0x48,0x26,0xC7,0x51,0x74,0x47,0x32,0x46,0x0B, + 0xCD,0x7A,0x0A,0x5D,0x5B,0xC5,0x8D,0xED,0x17,0xBC,0xDE,0x09,0xBC,0xE9,0x93,0xA9, + 0x7C,0x85,0x9C,0x88,0xA6,0x83,0xBC,0xD6,0xE5,0x1F,0x05,0x10,0xDF,0xB2,0x4F,0xA2, + 0xC5,0x97,0x00,0x8B,0x57,0xC7,0x0D,0xE7,0xC7,0x57,0x57,0x87,0x7D,0x13,0x9F,0x5C, + 0x5C,0xF7,0xF3,0xCD,0x00,0x89,0x0D,0x85,0x9A,0xA2,0x70,0xDA, +}; + +/* subject:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)06/CN=VeriSign Class 3 Extended Validation SSL CA */ +/* issuer :/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 */ +unsigned char CA_certificate[1512]={ + 0x30,0x82,0x05,0xE4,0x30,0x82,0x04,0xCC,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x5B, + 0x77,0x59,0xC6,0x17,0x84,0xE1,0x5E,0xC7,0x27,0xC0,0x32,0x95,0x29,0x28,0x6B,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,0x30, + 0x36,0x31,0x31,0x30,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x31,0x36, + 0x31,0x31,0x30,0x37,0x32,0x33,0x35,0x39,0x35,0x39,0x5A,0x30,0x81,0xBA,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,0x3B,0x30,0x39,0x06,0x03,0x55,0x04,0x0B,0x13,0x32, + 0x54,0x65,0x72,0x6D,0x73,0x20,0x6F,0x66,0x20,0x75,0x73,0x65,0x20,0x61,0x74,0x20, + 0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x76,0x65,0x72,0x69, + 0x73,0x69,0x67,0x6E,0x2E,0x63,0x6F,0x6D,0x2F,0x72,0x70,0x61,0x20,0x28,0x63,0x29, + 0x30,0x36,0x31,0x34,0x30,0x32,0x06,0x03,0x55,0x04,0x03,0x13,0x2B,0x56,0x65,0x72, + 0x69,0x53,0x69,0x67,0x6E,0x20,0x43,0x6C,0x61,0x73,0x73,0x20,0x33,0x20,0x45,0x78, + 0x74,0x65,0x6E,0x64,0x65,0x64,0x20,0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F, + 0x6E,0x20,0x53,0x53,0x4C,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,0x98,0xDB,0xA0,0x55,0xEB,0x9C,0xFD, + 0x17,0x79,0xE3,0x9A,0x6E,0x14,0x1D,0xB1,0x5B,0x98,0x23,0x87,0x16,0x6E,0x87,0x76, + 0x9C,0xB5,0x38,0x3B,0xB5,0xA0,0x7A,0xB4,0x07,0x63,0x09,0x19,0xE6,0x2A,0x88,0x48, + 0xA9,0xE7,0x9D,0xB6,0x30,0x5A,0x08,0x97,0x0C,0xEC,0xAA,0xE4,0x16,0x69,0x72,0x62, + 0x23,0x9A,0xFB,0x7A,0x54,0x28,0x98,0xC5,0x0C,0x2D,0xB7,0xD7,0x22,0xB6,0xC8,0xF9, + 0x38,0x17,0xC7,0xDD,0xDA,0x31,0x46,0x9A,0x94,0x14,0x8E,0x9E,0xEE,0x78,0xA0,0xB7, + 0x22,0xD4,0x49,0x54,0x97,0x4D,0xE5,0x74,0x5B,0x92,0xBC,0xEC,0x6C,0x2C,0xDF,0xE7, + 0xC1,0xB6,0x1B,0x1A,0x55,0x6B,0x66,0x08,0x03,0x7F,0x45,0xAF,0x9A,0x33,0xF1,0x10, + 0xC0,0x6C,0x99,0x4A,0x92,0x24,0x31,0x08,0x6D,0xDD,0x02,0x3E,0x61,0x76,0x78,0x78, + 0xB6,0xED,0x7E,0x37,0xAE,0x6C,0xF3,0x89,0xE1,0xB7,0xE1,0xDC,0x15,0xCC,0xB7,0x56, + 0x9F,0x80,0xA0,0xB1,0x05,0x7F,0x4E,0x37,0x15,0xFF,0xB7,0x2F,0x1E,0x8F,0x06,0x38, + 0x3F,0x50,0xB7,0x69,0x28,0xA3,0xB5,0x66,0x5F,0x36,0x1A,0x52,0x48,0x43,0x66,0x52, + 0xDF,0xA2,0x92,0x4F,0xD3,0x18,0x60,0xBE,0xE3,0xEA,0x5E,0x19,0x71,0x05,0xBF,0x9E, + 0x1C,0x6C,0x68,0x72,0x25,0x6F,0xB3,0x7B,0x73,0xC9,0x6D,0xBD,0x12,0xFF,0x9B,0x41, + 0x32,0x5E,0xF4,0xE8,0x7E,0xC5,0x0B,0xA3,0x4C,0x64,0xD1,0x4E,0xBC,0x26,0x08,0x65, + 0xFB,0x19,0x97,0x58,0x78,0xE1,0x33,0xBF,0xED,0x68,0x3E,0xB1,0x27,0x45,0x6F,0xC0, + 0xE2,0xEC,0x97,0x69,0xF7,0x5C,0xD3,0xF7,0x51,0x02,0x03,0x01,0x00,0x01,0xA3,0x82, + 0x01,0xD2,0x30,0x82,0x01,0xCE,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04, + 0x14,0xFC,0x8A,0x50,0xBA,0x9E,0xB9,0x25,0x5A,0x7B,0x55,0x85,0x4F,0x95,0x00,0x63, + 0x8F,0xE9,0x58,0x6B,0x43,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04, + 0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x3D,0x06,0x03,0x55,0x1D,0x20, + 0x04,0x36,0x30,0x34,0x30,0x32,0x06,0x04,0x55,0x1D,0x20,0x00,0x30,0x2A,0x30,0x28, + 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1C,0x68,0x74,0x74,0x70, + 0x73,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6E, + 0x2E,0x63,0x6F,0x6D,0x2F,0x63,0x70,0x73,0x30,0x3D,0x06,0x03,0x55,0x1D,0x1F,0x04, + 0x36,0x30,0x34,0x30,0x32,0xA0,0x30,0xA0,0x2E,0x86,0x2C,0x68,0x74,0x74,0x70,0x3A, + 0x2F,0x2F,0x45,0x56,0x53,0x65,0x63,0x75,0x72,0x65,0x2D,0x63,0x72,0x6C,0x2E,0x76, + 0x65,0x72,0x69,0x73,0x69,0x67,0x6E,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,0x11,0x06,0x09,0x60,0x86,0x48,0x01,0x86, + 0xF8,0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x6D,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x01,0x0C,0x04,0x61,0x30,0x5F,0xA1,0x5D,0xA0,0x5B,0x30,0x59, + 0x30,0x57,0x30,0x55,0x16,0x09,0x69,0x6D,0x61,0x67,0x65,0x2F,0x67,0x69,0x66,0x30, + 0x21,0x30,0x1F,0x30,0x07,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x04,0x14,0x8F,0xE5, + 0xD3,0x1A,0x86,0xAC,0x8D,0x8E,0x6B,0xC3,0xCF,0x80,0x6A,0xD4,0x48,0x18,0x2C,0x7B, + 0x19,0x2E,0x30,0x25,0x16,0x23,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6C,0x6F,0x67, + 0x6F,0x2E,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6E,0x2E,0x63,0x6F,0x6D,0x2F,0x76, + 0x73,0x6C,0x6F,0x67,0x6F,0x2E,0x67,0x69,0x66,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,0x43,0x6C,0x61,0x73,0x73,0x33,0x43,0x41,0x32,0x30,0x34,0x38,0x2D, + 0x31,0x2D,0x34,0x37,0x30,0x3D,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01, + 0x04,0x31,0x30,0x2F,0x30,0x2D,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01, + 0x86,0x21,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x45,0x56,0x53,0x65,0x63,0x75,0x72, + 0x65,0x2D,0x6F,0x63,0x73,0x70,0x2E,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6E,0x2E, + 0x63,0x6F,0x6D,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,0x96,0xA2,0xFA,0x7F,0xE6,0x3D,0xED,0xD4, + 0x2B,0xCE,0xB7,0x15,0x3F,0xC0,0x72,0x03,0x5F,0x8B,0xBA,0x16,0x90,0x25,0xF7,0xC2, + 0x83,0xD8,0xC7,0x75,0x34,0x63,0x68,0x12,0x53,0x0C,0x53,0x89,0x7B,0xC9,0x56,0x09, + 0xA7,0xC3,0x36,0x44,0x4E,0x0E,0xD0,0x62,0x62,0xB3,0x86,0xFA,0xE8,0xA1,0x9B,0x34, + 0x67,0x8D,0x53,0x22,0x17,0x3E,0xFD,0xAC,0xEE,0x67,0x2E,0x43,0xE2,0x5D,0x7F,0x33, + 0x84,0xF2,0xA2,0x70,0xC0,0x6E,0x82,0x97,0xC0,0x34,0xFD,0x25,0xC6,0x23,0x7F,0xED, + 0xE6,0xB0,0xC5,0x57,0x43,0x84,0xB2,0xDE,0x2D,0xF1,0xD0,0xF6,0x48,0x1F,0x14,0x71, + 0x57,0xB2,0xAC,0x31,0xE1,0x97,0x24,0x23,0xC9,0x13,0x5D,0x74,0xE5,0x46,0xEF,0x09, + 0x7C,0x9E,0xE1,0x99,0x31,0x0A,0x08,0x79,0x1B,0x8F,0x71,0x9F,0x17,0x66,0xC8,0x38, + 0xCF,0xEE,0x8C,0x97,0xB6,0x06,0xB9,0x73,0x46,0xE4,0xD3,0x94,0xC1,0xE5,0x60,0xB5, + 0x25,0x75,0x2D,0xD9,0x69,0x31,0xEC,0xCD,0x96,0xC3,0xA3,0x76,0xFD,0xE8,0x74,0x44, + 0xAC,0x12,0xB9,0x4D,0xBF,0x51,0xE8,0xB9,0xD4,0x44,0x4E,0x27,0xCB,0xAE,0x20,0xD1, + 0x7E,0x2A,0x7C,0xB6,0x63,0x47,0x9E,0x76,0xBA,0x97,0xD0,0x16,0xE7,0x0B,0x6C,0x6D, + 0xF7,0x43,0x6F,0x33,0x0B,0x29,0x30,0x77,0xFA,0x9D,0xF9,0xF5,0x4E,0xB8,0x76,0xB3, + 0xCD,0x18,0xB4,0xF9,0x20,0xEF,0x3D,0xDB,0xE6,0xCA,0xAD,0x9B,0xD0,0x4E,0xD2,0x87, + 0xA9,0x0D,0xA6,0x44,0x73,0x50,0xDD,0x70,0x5B,0xED,0xAD,0x7E,0x4A,0xBC,0x22,0xD5, + 0xA8,0x26,0xE4,0xC2,0x85,0x20,0x0D,0xD9, +}; + + + +/* + * Note: this test requires Network connectivity! + */ + +static void tests(void) +{ + SecCertificateRef leaf_cert; + SecCertificateRef CA_cert; + + // Import certificates from byte array above + isnt(leaf_cert = SecCertificateCreateWithBytes(NULL, leaf_certificate, sizeof(leaf_certificate)), + NULL, "Leaf Cert"); + isnt(CA_cert = SecCertificateCreateWithBytes(NULL, CA_certificate, sizeof(CA_certificate)), + NULL, "CA Cert"); + + /* + * 1) Test explicit revocation with no OCSP/CRL + * Side note: cache is stored in /var/db/crls/ocspcache.db crlcache.db etc... + */ + + OSStatus status; + SecPolicyRef policy_default = SecPolicyCreateBasicX509(); + SecPolicyRef policy_revoc = SecPolicyCreateRevocation(kSecRevocationNetworkAccessDisabled); + + // Default Policies + CFMutableArrayRef DefaultPolicy = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(DefaultPolicy, policy_default); + + // Default Policies + explicit revocation + CFMutableArrayRef DefaultPolicyWithRevocation = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(DefaultPolicyWithRevocation, policy_default); + CFArrayAppendValue(DefaultPolicyWithRevocation, policy_revoc); + + // Valid chain of Cert (leaf + CA) + CFMutableArrayRef CertFullChain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(CertFullChain, leaf_cert); + CFArrayAppendValue(CertFullChain, CA_cert); + + // Chain of cert minus the issuer + CFMutableArrayRef CertMissingIssuer = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(CertMissingIssuer, leaf_cert); + + // Free Resources since all are in arrays + CFReleaseSafe(leaf_cert); + CFReleaseSafe(CA_cert); + CFReleaseSafe(policy_default); + CFReleaseSafe(policy_revoc); + + // a) First evaluate an entire EV certificate chain with default policy + // OCSP/CRL performed (online/from cache) + + // Array of policy to add explicit revocation policy + { + SecTrustRef trust = NULL; + SecTrustResultType trust_result; + + // Proceed to trust evaluation in two steps + ok_status(status = SecTrustCreateWithCertificates(CertFullChain, DefaultPolicy, &trust), + "SecTrustCreateWithCertificates"); + ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate"); + + // Check results + is_status(trust_result, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); + CFDictionaryRef TrustResultsDict = SecTrustCopyResult(trust); + CFBooleanRef ev = (CFBooleanRef)CFDictionaryGetValue(TrustResultsDict, + kSecTrustExtendedValidation); + ok(ev && CFEqual(kCFBooleanTrue, ev), "extended validation succeeded"); + + CFReleaseNull(TrustResultsDict); + CFReleaseNull(trust); + } + + // b) Set explicit revocation policy to disable network access + // and now expect EV marker to be dropped. + // Network packet logging can be used to confirm no OCSP/CRL message is sent. + { + SecTrustRef trust = NULL; + SecTrustResultType trust_result; + + // Proceed to trust evaluation in two steps + ok_status(status = SecTrustCreateWithCertificates(CertFullChain, DefaultPolicyWithRevocation, &trust), + "SecTrustCreateWithCertificates"); + ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate"); + + // Check results + is_status(trust_result, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); + CFDictionaryRef TrustResultsDict = SecTrustCopyResult(trust); + CFBooleanRef ev = (CFBooleanRef)CFDictionaryGetValue(TrustResultsDict, + kSecTrustExtendedValidation); + ok(!ev || (ev && CFEqual(kCFBooleanFalse, ev)), "Expect no extended validation because of lack of revocation"); + + CFReleaseNull(TrustResultsDict); + CFReleaseNull(trust); + } + + /* + * 2) Test retrieving of issuer being blocked + */ + + // a) Evaluate leaf EV certificate and expect success (issuer retrieved online) + { + SecTrustRef trust = NULL; + SecTrustResultType trust_result; + + // Proceed to trust evaluation in two steps + ok_status(status = SecTrustCreateWithCertificates(CertMissingIssuer, DefaultPolicy, &trust), + "SecTrustCreateWithCertificates"); + ok_status(status = SecTrustSetNetworkFetchAllowed(trust,true), "SecTrustSetNetworkFetchAllowed"); + ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate"); + + // Check results + is_status(trust_result, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); + CFDictionaryRef TrustResultsDict = SecTrustCopyResult(trust); + CFBooleanRef ev = (CFBooleanRef)CFDictionaryGetValue(TrustResultsDict, + kSecTrustExtendedValidation); + ok(ev && CFEqual(kCFBooleanTrue, ev), "extended validation succeeded"); + + CFReleaseNull(TrustResultsDict); + CFReleaseNull(trust); + } + + // b) Set SecTrustSetNetworkFetchAllowed to false which should prevent issuer cert to be fetched + // and therefore cause evaluation failure. + { + SecTrustRef trust = NULL; + SecTrustResultType trust_result; + + // Proceed to trust evaluation in two steps, forcing no network allowed + ok_status(status = SecTrustCreateWithCertificates(CertMissingIssuer, DefaultPolicy, &trust), + "SecTrustCreateWithCertificates"); + ok_status(status = SecTrustSetNetworkFetchAllowed(trust,false), "SecTrustSetNetworkFetchAllowed"); + ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate"); + + // Check results + is_status(trust_result, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultProceed"); + + CFReleaseNull(trust); + } + + // Free remaining resources + CFReleaseSafe(DefaultPolicy); + CFReleaseSafe(DefaultPolicyWithRevocation); + CFReleaseSafe(CertFullChain); + CFReleaseSafe(CertMissingIssuer); +} + +int kc_42_trust_revocation(int argc, char *const *argv) +{ + plan_tests(19); + tests(); + + return 0; +} + + diff --git a/libsecurity_keychain/regressions/keychain_regressions.h b/Security/libsecurity_keychain/regressions/keychain_regressions.h similarity index 87% rename from libsecurity_keychain/regressions/keychain_regressions.h rename to Security/libsecurity_keychain/regressions/keychain_regressions.h index 97e22794..1f9e542f 100644 --- a/libsecurity_keychain/regressions/keychain_regressions.h +++ b/Security/libsecurity_keychain/regressions/keychain_regressions.h @@ -4,6 +4,7 @@ */ #include +ONE_TEST(kc_42_trust_revocation) ONE_TEST(kc_40_seckey) ONE_TEST(kc_41_sececkey) ONE_TEST(si_33_keychain_backup) diff --git a/Security/libsecurity_keychain/regressions/si-33-keychain-backup.c b/Security/libsecurity_keychain/regressions/si-33-keychain-backup.c new file mode 100644 index 00000000..8112f864 --- /dev/null +++ b/Security/libsecurity_keychain/regressions/si-33-keychain-backup.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include + +#include "keychain_regressions.h" +#include +#include +#include +#include +#include + + +static CFDataRef create_keybag(keybag_handle_t bag_type, CFDataRef password) +{ + keybag_handle_t handle = bad_keybag_handle; + + if (aks_create_bag(NULL, 0, bag_type, &handle) == 0) { + void * keybag = NULL; + int keybag_size = 0; + if (aks_save_bag(handle, &keybag, &keybag_size) == 0) { + return CFDataCreate(kCFAllocatorDefault, keybag, keybag_size); + } + } + + return CFDataCreate(kCFAllocatorDefault, NULL, 0); +} + +/* Test low level keychain migration from device to device interface. */ +static void tests(void) +{ + int v_eighty = 80; + CFNumberRef eighty = CFNumberCreate(NULL, kCFNumberSInt32Type, &v_eighty); + const char *v_data = "test"; + CFDataRef pwdata = CFDataCreate(NULL, (UInt8 *)v_data, strlen(v_data)); + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); + CFTypeRef result = NULL; + CFDictionaryAddValue(query, kSecClass, kSecClassInternetPassword); + CFDictionaryAddValue(query, kSecAttrServer, CFSTR("members.spamcop.net")); + CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("smith")); + CFDictionaryAddValue(query, kSecAttrPort, eighty); + CFDictionaryAddValue(query, kSecAttrProtocol, kSecAttrProtocolHTTP); + CFDictionaryAddValue(query, kSecAttrAuthenticationType, kSecAttrAuthenticationTypeDefault); + CFDictionaryAddValue(query, kSecValueData, pwdata); + CFDictionaryAddValue(query, kSecAttrSynchronizable, kCFBooleanTrue); + + CFDataRef keybag = NULL, password = NULL; + + keybag = create_keybag(kAppleKeyStoreAsymmetricBackupBag, password); + + SecItemDelete(query); + + // add syncable item + ok_status(SecItemAdd(query, NULL), "add internet password"); + + ok_status(SecItemCopyMatching(query, &result), "find item we are about to destroy"); + if (result) { CFRelease(result); result = NULL; } + + CFDictionaryRef backup = NULL; + + ok_status(_SecKeychainBackupSyncable(keybag, password, NULL, &backup), "export items"); + + ok_status(SecItemDelete(query), "delete item we backed up"); + is_status(SecItemCopyMatching(query, &result), errSecItemNotFound, "find item we are about to destroy"); + if (result) { CFRelease(result); result = NULL; } + + ok_status(_SecKeychainRestoreSyncable(keybag, password, backup), "import items"); + + ok_status(SecItemCopyMatching(query, &result), "find restored item"); + if (result) { CFRelease(result); result = NULL; } + + ok_status(SecItemDelete(query), "delete restored item"); + + if (backup) { CFRelease(backup); } +} + +int si_33_keychain_backup(int argc, char *const *argv) +{ + plan_tests(8); + + + tests(); + + return 0; +} diff --git a/libsecurity_keychain/xpc-tsa/XPCTimeStampingService-Info.plist b/Security/libsecurity_keychain/xpc-tsa/XPCTimeStampingService-Info.plist similarity index 100% rename from libsecurity_keychain/xpc-tsa/XPCTimeStampingService-Info.plist rename to Security/libsecurity_keychain/xpc-tsa/XPCTimeStampingService-Info.plist diff --git a/libsecurity_keychain/xpc-tsa/main-tsa.m b/Security/libsecurity_keychain/xpc-tsa/main-tsa.m similarity index 99% rename from libsecurity_keychain/xpc-tsa/main-tsa.m rename to Security/libsecurity_keychain/xpc-tsa/main-tsa.m index 2a47b48f..f1469ffc 100644 --- a/libsecurity_keychain/xpc-tsa/main-tsa.m +++ b/Security/libsecurity_keychain/xpc-tsa/main-tsa.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/xpc-tsa/timestampclient.h b/Security/libsecurity_keychain/xpc-tsa/timestampclient.h similarity index 96% rename from libsecurity_keychain/xpc-tsa/timestampclient.h rename to Security/libsecurity_keychain/xpc-tsa/timestampclient.h index c6fe1c91..190fe925 100644 --- a/libsecurity_keychain/xpc-tsa/timestampclient.h +++ b/Security/libsecurity_keychain/xpc-tsa/timestampclient.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple, Inc. All Rights Reserved. + * Copyright (c) 2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/xpc-tsa/timestampclient.m b/Security/libsecurity_keychain/xpc-tsa/timestampclient.m similarity index 98% rename from libsecurity_keychain/xpc-tsa/timestampclient.m rename to Security/libsecurity_keychain/xpc-tsa/timestampclient.m index e545656e..becfecf5 100644 --- a/libsecurity_keychain/xpc-tsa/timestampclient.m +++ b/Security/libsecurity_keychain/xpc-tsa/timestampclient.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple, Inc. All Rights Reserved. + * Copyright (c) 2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_keychain/xpc/XPCKeychainSandboxCheck-Info.plist b/Security/libsecurity_keychain/xpc/XPCKeychainSandboxCheck-Info.plist similarity index 100% rename from libsecurity_keychain/xpc/XPCKeychainSandboxCheck-Info.plist rename to Security/libsecurity_keychain/xpc/XPCKeychainSandboxCheck-Info.plist diff --git a/Security/libsecurity_keychain/xpc/main.c b/Security/libsecurity_keychain/xpc/main.c new file mode 100644 index 00000000..ac8daed4 --- /dev/null +++ b/Security/libsecurity_keychain/xpc/main.c @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct connection_info { + xpc_connection_t peer; + int processed; + int done; +}; + +typedef typeof(SecKeychainCopyDomainSearchList) SecKeychainCopyDomainSearchListType; +SecKeychainCopyDomainSearchListType *SecKeychainCopyDomainSearchListFunctionPointer = NULL; +typedef typeof(SecKeychainGetPath) SecKeychainGetPathType; +SecKeychainGetPathType *SecKeychainGetPathFunctionPointer = NULL; + +// prior to 8723022 we have to do our own idle timeout work +#ifndef XPC_HANDLES_IDLE_TIMEOUT +int current_connections = 0; +// Number of seconds to sit with no clients +#define IDLE_WAIT_TIME 30 +#endif + +xpc_object_t keychain_prefs_path = NULL; +xpc_object_t home = NULL; + +extern xpc_object_t +xpc_create_reply_with_format(xpc_object_t original, const char * format, ...); + +static +xpc_object_t create_keychain_search_list_for(xpc_connection_t peer, SecPreferencesDomain domain) +{ + CFArrayRef keychains = NULL; + pid_t peer_pid = xpc_connection_get_pid(peer); + OSStatus status = SecKeychainCopyDomainSearchListFunctionPointer(domain, &keychains); + if (errSecSuccess != status) { + syslog(LOG_ERR, "Unable to get keychain search list (domain=%d) on behalf of %d, status=0x%lx", domain, peer_pid, (unsigned long)status); + return NULL; + } + + xpc_object_t paths = xpc_array_create(NULL, 0); + CFIndex n_keychains = CFArrayGetCount(keychains); + CFIndex i; + for(i = 0; i < n_keychains; i++) { + char path[MAXPATHLEN]; + + SecKeychainRef keychain = (SecKeychainRef)CFArrayGetValueAtIndex(keychains, i); + UInt32 length = MAXPATHLEN; + OSStatus status = SecKeychainGetPathFunctionPointer(keychain, &length, path); + if (errSecSuccess != status) { + syslog(LOG_ERR, "Unable to get path for keychain#%ld of %ld on behalf of %d, status=0x%lx", i, n_keychains, peer_pid, (unsigned long)status); + continue; + } + xpc_object_t path_as_xpc_string = xpc_string_create(path); + xpc_array_append_value(paths, path_as_xpc_string); + xpc_release(path_as_xpc_string); + } + CFRelease(keychains); + return paths; +} + +static +bool keychain_domain_needs_writes(const char *domain_name) +{ + return (0 == strcmp("kSecPreferencesDomainUser", domain_name) || 0 == strcmp("kSecPreferencesDomainDynamic", domain_name)); +} + +static +void _set_keychain_search_lists_for_domain(xpc_connection_t peer, xpc_object_t all_domains, char *domain_name, SecPreferencesDomain domain_enum) +{ + xpc_object_t keychains_for_domain = create_keychain_search_list_for(peer, domain_enum); + if (keychains_for_domain) { + xpc_dictionary_set_value(all_domains, domain_name, keychains_for_domain); + xpc_release(keychains_for_domain); + } else { + syslog(LOG_ERR, "Can't discover keychain paths for domain %s on behalf of %d", domain_name, xpc_connection_get_pid(peer)); + } +} + +#define SET_KEYCHAIN_SEARCH_LISTS_FOR_DOMAIN(peer, all_domains, domain) _set_keychain_search_lists_for_domain(peer, all_domains, #domain, domain); + +static +xpc_object_t create_keychain_search_lists(xpc_connection_t peer) +{ + xpc_object_t all_domains = xpc_dictionary_create(NULL, NULL, 0); + + SET_KEYCHAIN_SEARCH_LISTS_FOR_DOMAIN(peer, all_domains, kSecPreferencesDomainUser); + SET_KEYCHAIN_SEARCH_LISTS_FOR_DOMAIN(peer, all_domains, kSecPreferencesDomainSystem); + SET_KEYCHAIN_SEARCH_LISTS_FOR_DOMAIN(peer, all_domains, kSecPreferencesDomainCommon); + SET_KEYCHAIN_SEARCH_LISTS_FOR_DOMAIN(peer, all_domains, kSecPreferencesDomainDynamic); + + return all_domains; +} + + +static +xpc_object_t create_keychain_and_lock_paths(xpc_connection_t peer, xpc_object_t keychain_path_dict) +{ + pid_t peer_pid = xpc_connection_get_pid(peer); + char *assembly_queue_label = NULL; + asprintf(&assembly_queue_label, "assembly-for-%d", peer_pid); + if (!assembly_queue_label) { + syslog(LOG_ERR, "Unable to create assembly queue label for %d", peer_pid); + return NULL; + } + dispatch_queue_t assembly_queue = dispatch_queue_create(assembly_queue_label, 0); + free(assembly_queue_label); + if (!assembly_queue) { + syslog(LOG_ERR, "Unable to create assembly queue for %d", peer_pid); + return NULL; + } + xpc_object_t return_paths_dict = xpc_dictionary_create(NULL, NULL, 0); + + xpc_dictionary_apply(keychain_path_dict, ^(const char *keychain_domain, xpc_object_t keychain_path_array) { + xpc_object_t return_paths_array = xpc_array_create(NULL, 0); + dispatch_apply(xpc_array_get_count(keychain_path_array), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t i) { + xpc_object_t path_as_xpc_string = xpc_array_get_value(keychain_path_array, i); + dispatch_sync(assembly_queue, ^{ + xpc_array_append_value(return_paths_array, path_as_xpc_string); + }); + + if (!keychain_domain_needs_writes(keychain_domain)) { + // lock files are only to prevent write-write errors, readers don't hold locks, so they don't need the lock files + return; + } + + // figure out the base and dir + const char* path = xpc_array_get_string(keychain_path_array, i); + char* dir; + char* base; + + char buffer[PATH_MAX]; + strcpy(buffer, path); + + if (path != NULL) { + ptrdiff_t i = strlen(buffer) - 1; + while (i >= 0 && buffer[i] != '/') { + i -= 1; + } + + if (i >= 0) { + // NULL terminate the dir + buffer[i] = 0; + dir = buffer; + base = buffer + i + 1; + } else { + dir = NULL; + base = buffer; + } + } + + if (!(path && dir && base)) { + syslog(LOG_ERR, "Can't get dir or base (likely out of memory) for %s", xpc_array_get_string(keychain_path_array, i)); + return; + } + + // "network style" lock files + path_as_xpc_string = xpc_string_create_with_format("%s/lck~%s", dir, base); + dispatch_sync(assembly_queue, ^{ + xpc_array_append_value(return_paths_array, path_as_xpc_string); + }); + xpc_release(path_as_xpc_string); + + CC_SHA1_CTX sha1Context; + CC_SHA1_Init(&sha1Context); + CC_SHA1_Update(&sha1Context, base, (CC_LONG)strlen(base)); + + unsigned char sha1_result_bytes[CC_SHA1_DIGEST_LENGTH]; + + CC_SHA1_Final(sha1_result_bytes, &sha1Context); + + path_as_xpc_string = xpc_string_create_with_format("%s/.fl%02X%02X%02X%02X", dir, sha1_result_bytes[0], sha1_result_bytes[1], sha1_result_bytes[2], sha1_result_bytes[3]); + dispatch_sync(assembly_queue, ^{ + xpc_array_append_value(return_paths_array, path_as_xpc_string); + }); + }); + xpc_dictionary_set_value(return_paths_dict, keychain_domain, return_paths_array); + xpc_release(return_paths_array); + return (bool)true; + }); + + dispatch_release(assembly_queue); + return return_paths_dict; +} + +static +xpc_object_t create_one_sandbox_extension(xpc_object_t path, uint64_t extension_flags) +{ + char *sandbox_extension = NULL; + int status = sandbox_issue_fs_extension(xpc_string_get_string_ptr(path), extension_flags, &sandbox_extension); + if (0 == status && sandbox_extension) { + xpc_object_t sandbox_extension_as_xpc_string = xpc_string_create(sandbox_extension); + free(sandbox_extension); + return sandbox_extension_as_xpc_string; + } else { + syslog(LOG_ERR, "Can't get sandbox fs extension for %s, status=%d errno=%m ext=%s", xpc_string_get_string_ptr(path), status, sandbox_extension); + } + return NULL; +} + +static +xpc_object_t create_all_sandbox_extensions(xpc_object_t path_dict) +{ + xpc_object_t extensions = xpc_array_create(NULL, 0); + + xpc_object_t sandbox_extension = create_one_sandbox_extension(keychain_prefs_path, FS_EXT_FOR_PATH|FS_EXT_READ); + if (sandbox_extension) { + xpc_array_append_value(extensions, sandbox_extension); + xpc_release(sandbox_extension); + } + + xpc_dictionary_apply(path_dict, ^(const char *keychain_domain, xpc_object_t path_array) { + uint64_t extension_flags = FS_EXT_FOR_PATH|FS_EXT_READ; + if (keychain_domain_needs_writes(keychain_domain)) { + extension_flags = FS_EXT_FOR_PATH|FS_EXT_READ|FS_EXT_WRITE; + } + xpc_array_apply(path_array, ^(size_t index, xpc_object_t path) { + xpc_object_t sandbox_extension = create_one_sandbox_extension(path, extension_flags); + if (sandbox_extension) { + xpc_array_append_value(extensions, sandbox_extension); + xpc_release(sandbox_extension); + } + return (bool)true; + }); + return (bool)true; + }); + + return extensions; +} + +static +void handle_request_event(struct connection_info *info, xpc_object_t event) +{ + xpc_connection_t peer = xpc_dictionary_get_connection(event); + xpc_type_t xtype = xpc_get_type(event); + if (info->done) { + syslog(LOG_ERR, "event %p while done", event); + return; + } + if (xtype == XPC_TYPE_ERROR) { + if (event == XPC_ERROR_TERMINATION_IMMINENT) { + // launchd would like us to die, but we have open transactions. When we finish with them xpc_service_main + // will exit for us, so there is nothing for us to do here. + return; + } + + if (!info->done) { + info->done = true; + xpc_release(info->peer); +#ifndef XPC_HANDLES_IDLE_TIMEOUT + if (0 == __sync_add_and_fetch(¤t_connections, -1)) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * IDLE_WAIT_TIME), dispatch_get_main_queue(), ^(void) { + if (0 == current_connections) { + exit(0); + } + }); + } +#endif + } + if (peer == NULL && XPC_ERROR_CONNECTION_INVALID == event && 0 != info->processed) { + // this is a normal shutdown on a connection that has processed at least + // one request. Nothing intresting to log. + return; + } + syslog(LOG_ERR, "listener event error (connection %p): %s", peer, xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION)); + } else if (xtype == XPC_TYPE_DICTIONARY) { + const char *operation = xpc_dictionary_get_string(event, "op"); + if (operation && !strcmp(operation, "GrantKeychainPaths")) { + xpc_object_t keychain_paths = create_keychain_search_lists(peer); + xpc_object_t all_paths = create_keychain_and_lock_paths(peer, keychain_paths); + xpc_object_t sandbox_extensions = NULL; + if (all_paths) { + sandbox_extensions = create_all_sandbox_extensions(all_paths); + } + + xpc_object_t reply = xpc_create_reply_with_format(event, "{keychain-paths: %value, all-paths: %value, extensions: %value, keychain-home: %value}", + keychain_paths, all_paths, sandbox_extensions, home); + xpc_connection_send_message(peer, reply); + xpc_release(reply); + if (keychain_paths) { + xpc_release(keychain_paths); + } + if (all_paths) { + xpc_release(all_paths); + } + if (sandbox_extensions) { + xpc_release(sandbox_extensions); + } + if (INT32_MAX != info->processed) { + info->processed++; + } + } else { + syslog(LOG_ERR, "Unknown op=%s request from pid %d", operation, xpc_connection_get_pid(peer)); + } + } else { + syslog(LOG_ERR, "Unhandled request event=%p type=%p", event, xtype); + } +} + +static +void finalize_connection(void *not_used) +{ +#ifdef XPC_HANDLES_IDLE_TIMEOUT + xpc_transaction_end(); +#endif +} + +static +void handle_connection_event(const xpc_connection_t peer) +{ +#ifndef XPC_HANDLES_IDLE_TIMEOUT + __sync_add_and_fetch(¤t_connections, 1); +#endif + __block struct connection_info info; + info.peer = peer; + info.processed = 0; + info.done = false; + + xpc_connection_set_event_handler(peer, ^(xpc_object_t event) { + handle_request_event(&info, event); + }); + + // unlike dispatch objects xpc objects don't need a context set in order to run a finalizer. (we use our finalizer to + // end the transaction we are about to begin...this keeps xpc from idle exiting us while we have a live connection) + xpc_connection_set_finalizer_f(peer, finalize_connection); +#ifdef XPC_HANDLES_IDLE_TIMEOUT + xpc_transaction_begin(); +#endif + + // enable the peer connection to receive messages + xpc_connection_resume(peer); + xpc_retain(peer); +} + + +static const char* g_path_to_plist = "/Library/Preferences/com.apple.security.plist"; + + + +int main(int argc, const char *argv[]) +{ + char *wait4debugger = getenv("WAIT4DEBUGGER"); + if (wait4debugger && !strcasecmp("YES", wait4debugger)) { + syslog(LOG_ERR, "Waiting for debugger"); + kill(getpid(), SIGSTOP); + } + + // get the home directory + const char* home_dir = getenv("HOME"); + + if (home_dir == NULL || strlen(home_dir) == 0) { + struct passwd* pwd = getpwuid(getuid()); + home_dir = pwd->pw_dir; // look it up in directory services, sort of... + } + + size_t home_dir_length = strlen(home_dir); + size_t path_to_plist_length = strlen(g_path_to_plist); + + size_t total_length = home_dir_length + path_to_plist_length + 1; // compensate for terminating zero + if (total_length > PATH_MAX) { + // someone is spoofing us, just exit + return -1; + } + + // make storage for the real path + char buffer[total_length]; + strlcpy(buffer, home_dir, total_length); + strlcat(buffer, g_path_to_plist, total_length); + keychain_prefs_path = xpc_string_create(buffer); + home = xpc_string_create(home_dir); + + void *security_framework = dlopen("/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY); + if (security_framework) { + SecKeychainCopyDomainSearchListFunctionPointer = dlsym(security_framework, "SecKeychainCopyDomainSearchList"); + if (!SecKeychainCopyDomainSearchListFunctionPointer) { + syslog(LOG_ERR, "Can't lookup SecKeychainCopyDomainSearchList in %p: %s", security_framework, dlerror()); + return EX_OSERR; + } + SecKeychainGetPathFunctionPointer = dlsym(security_framework, "SecKeychainGetPath"); + if (!SecKeychainGetPathFunctionPointer) { + syslog(LOG_ERR, "Can't lookup SecKeychainGetPath in %p: %s", security_framework, dlerror()); + return EX_OSERR; + } + } + + xpc_main(handle_connection_event); + + return EX_OSERR; +} diff --git a/libsecurity_manifest/APPLE_LICENSE b/Security/libsecurity_manifest/APPLE_LICENSE similarity index 100% rename from libsecurity_manifest/APPLE_LICENSE rename to Security/libsecurity_manifest/APPLE_LICENSE diff --git a/libsecurity_manifest/Info-security_manifest.plist b/Security/libsecurity_manifest/Info-security_manifest.plist similarity index 100% rename from libsecurity_manifest/Info-security_manifest.plist rename to Security/libsecurity_manifest/Info-security_manifest.plist diff --git a/libsecurity_manifest/lib/AppleManifest.cpp b/Security/libsecurity_manifest/lib/AppleManifest.cpp similarity index 99% rename from libsecurity_manifest/lib/AppleManifest.cpp rename to Security/libsecurity_manifest/lib/AppleManifest.cpp index 77928324..31db9426 100644 --- a/libsecurity_manifest/lib/AppleManifest.cpp +++ b/Security/libsecurity_manifest/lib/AppleManifest.cpp @@ -9,7 +9,7 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_manifest/lib/AppleManifest.h b/Security/libsecurity_manifest/lib/AppleManifest.h similarity index 97% rename from libsecurity_manifest/lib/AppleManifest.h rename to Security/libsecurity_manifest/lib/AppleManifest.h index 4b415f4e..f6df247d 100644 --- a/libsecurity_manifest/lib/AppleManifest.h +++ b/Security/libsecurity_manifest/lib/AppleManifest.h @@ -4,7 +4,7 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_manifest/lib/Download.cpp b/Security/libsecurity_manifest/lib/Download.cpp similarity index 99% rename from libsecurity_manifest/lib/Download.cpp rename to Security/libsecurity_manifest/lib/Download.cpp index a0bd62f3..625ea5e6 100644 --- a/libsecurity_manifest/lib/Download.cpp +++ b/Security/libsecurity_manifest/lib/Download.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_manifest/lib/Download.h b/Security/libsecurity_manifest/lib/Download.h similarity index 97% rename from libsecurity_manifest/lib/Download.h rename to Security/libsecurity_manifest/lib/Download.h index 0232e9f6..5c5bc522 100644 --- a/libsecurity_manifest/lib/Download.h +++ b/Security/libsecurity_manifest/lib/Download.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_manifest/lib/Manifest.cpp b/Security/libsecurity_manifest/lib/Manifest.cpp similarity index 95% rename from libsecurity_manifest/lib/Manifest.cpp rename to Security/libsecurity_manifest/lib/Manifest.cpp index e7cc5b7b..42b75c6a 100644 --- a/libsecurity_manifest/lib/Manifest.cpp +++ b/Security/libsecurity_manifest/lib/Manifest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_manifest/lib/Manifest.h b/Security/libsecurity_manifest/lib/Manifest.h similarity index 96% rename from libsecurity_manifest/lib/Manifest.h rename to Security/libsecurity_manifest/lib/Manifest.h index 82feb11c..27ebff42 100644 --- a/libsecurity_manifest/lib/Manifest.h +++ b/Security/libsecurity_manifest/lib/Manifest.h @@ -12,7 +12,7 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_manifest/lib/ManifestInternal.cpp b/Security/libsecurity_manifest/lib/ManifestInternal.cpp similarity index 99% rename from libsecurity_manifest/lib/ManifestInternal.cpp rename to Security/libsecurity_manifest/lib/ManifestInternal.cpp index e7442d2f..2c8abdcc 100644 --- a/libsecurity_manifest/lib/ManifestInternal.cpp +++ b/Security/libsecurity_manifest/lib/ManifestInternal.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004-2006,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_manifest/lib/ManifestInternal.h b/Security/libsecurity_manifest/lib/ManifestInternal.h similarity index 99% rename from libsecurity_manifest/lib/ManifestInternal.h rename to Security/libsecurity_manifest/lib/ManifestInternal.h index c759418a..a6fcc099 100644 --- a/libsecurity_manifest/lib/ManifestInternal.h +++ b/Security/libsecurity_manifest/lib/ManifestInternal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_manifest/lib/ManifestSigner.cpp b/Security/libsecurity_manifest/lib/ManifestSigner.cpp similarity index 93% rename from libsecurity_manifest/lib/ManifestSigner.cpp rename to Security/libsecurity_manifest/lib/ManifestSigner.cpp index 8cef5b30..e05d14a5 100644 --- a/libsecurity_manifest/lib/ManifestSigner.cpp +++ b/Security/libsecurity_manifest/lib/ManifestSigner.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_manifest/lib/ManifestSigner.h b/Security/libsecurity_manifest/lib/ManifestSigner.h similarity index 95% rename from libsecurity_manifest/lib/ManifestSigner.h rename to Security/libsecurity_manifest/lib/ManifestSigner.h index 0a7f4ae9..b76c0c46 100644 --- a/libsecurity_manifest/lib/ManifestSigner.h +++ b/Security/libsecurity_manifest/lib/ManifestSigner.h @@ -4,7 +4,7 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_manifest/lib/SecManifest.cpp b/Security/libsecurity_manifest/lib/SecManifest.cpp similarity index 98% rename from libsecurity_manifest/lib/SecManifest.cpp rename to Security/libsecurity_manifest/lib/SecManifest.cpp index 3f5d2591..fb0b6bdb 100644 --- a/libsecurity_manifest/lib/SecManifest.cpp +++ b/Security/libsecurity_manifest/lib/SecManifest.cpp @@ -5,7 +5,7 @@ #include #include <../sec/Security/SecBase.h> /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_manifest/lib/SecManifest.h b/Security/libsecurity_manifest/lib/SecManifest.h similarity index 99% rename from libsecurity_manifest/lib/SecManifest.h rename to Security/libsecurity_manifest/lib/SecManifest.h index 98fbac51..55e57bdf 100644 --- a/libsecurity_manifest/lib/SecManifest.h +++ b/Security/libsecurity_manifest/lib/SecManifest.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_manifest/lib/SecureDownload.cpp b/Security/libsecurity_manifest/lib/SecureDownload.cpp similarity index 98% rename from libsecurity_manifest/lib/SecureDownload.cpp rename to Security/libsecurity_manifest/lib/SecureDownload.cpp index 4d031f18..d09e1cd8 100644 --- a/libsecurity_manifest/lib/SecureDownload.cpp +++ b/Security/libsecurity_manifest/lib/SecureDownload.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_manifest/lib/SecureDownload.h b/Security/libsecurity_manifest/lib/SecureDownload.h similarity index 99% rename from libsecurity_manifest/lib/SecureDownload.h rename to Security/libsecurity_manifest/lib/SecureDownload.h index 025346bd..13d94b9d 100644 --- a/libsecurity_manifest/lib/SecureDownload.h +++ b/Security/libsecurity_manifest/lib/SecureDownload.h @@ -6,7 +6,7 @@ extern "C" { #endif /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_manifest/lib/SecureDownloadInternal.c b/Security/libsecurity_manifest/lib/SecureDownloadInternal.c similarity index 100% rename from libsecurity_manifest/lib/SecureDownloadInternal.c rename to Security/libsecurity_manifest/lib/SecureDownloadInternal.c diff --git a/libsecurity_manifest/lib/SecureDownloadInternal.h b/Security/libsecurity_manifest/lib/SecureDownloadInternal.h similarity index 100% rename from libsecurity_manifest/lib/SecureDownloadInternal.h rename to Security/libsecurity_manifest/lib/SecureDownloadInternal.h diff --git a/libsecurity_manifest/lib/security_manifest.exp b/Security/libsecurity_manifest/lib/security_manifest.exp similarity index 95% rename from libsecurity_manifest/lib/security_manifest.exp rename to Security/libsecurity_manifest/lib/security_manifest.exp index e9628e41..af5af6be 100644 --- a/libsecurity_manifest/lib/security_manifest.exp +++ b/Security/libsecurity_manifest/lib/security_manifest.exp @@ -1,5 +1,5 @@ # -# Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. +# Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. # # @APPLE_LICENSE_HEADER_START@ # diff --git a/libsecurity_manifest/libsecurity_manifest.xcodeproj/project.pbxproj b/Security/libsecurity_manifest/libsecurity_manifest.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_manifest/libsecurity_manifest.xcodeproj/project.pbxproj rename to Security/libsecurity_manifest/libsecurity_manifest.xcodeproj/project.pbxproj diff --git a/libsecurity_mds/Info-security_mds.plist b/Security/libsecurity_mds/Info-security_mds.plist similarity index 100% rename from libsecurity_mds/Info-security_mds.plist rename to Security/libsecurity_mds/Info-security_mds.plist diff --git a/libsecurity_mds/README b/Security/libsecurity_mds/README similarity index 100% rename from libsecurity_mds/README rename to Security/libsecurity_mds/README diff --git a/libsecurity_mds/lib/MDSAttrParser.cpp b/Security/libsecurity_mds/lib/MDSAttrParser.cpp similarity index 99% rename from libsecurity_mds/lib/MDSAttrParser.cpp rename to Security/libsecurity_mds/lib/MDSAttrParser.cpp index 70892bb4..1a8a9650 100644 --- a/libsecurity_mds/lib/MDSAttrParser.cpp +++ b/Security/libsecurity_mds/lib/MDSAttrParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -22,7 +22,7 @@ Contains: Classes to parse XML plists and fill in MDS DBs with the attributes found there. - Copyright: (c) 2001 Apple Computer, Inc., all rights reserved. + Copyright (c) 2001,2011-2014 Apple Inc. All Rights Reserved. */ #include "MDSAttrParser.h" diff --git a/libsecurity_mds/lib/MDSAttrParser.h b/Security/libsecurity_mds/lib/MDSAttrParser.h similarity index 97% rename from libsecurity_mds/lib/MDSAttrParser.h rename to Security/libsecurity_mds/lib/MDSAttrParser.h index df42d2a9..16174f69 100644 --- a/libsecurity_mds/lib/MDSAttrParser.h +++ b/Security/libsecurity_mds/lib/MDSAttrParser.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -22,7 +22,7 @@ Contains: Classes to parse XML plists and fill in MDS DBs with the attributes found there. - Copyright: (c) 2001 Apple Computer, Inc., all rights reserved. + Copyright (c) 2001,2011,2014 Apple Inc. All Rights Reserved. */ #ifndef _MDS_ATTR_PARSER_H_ diff --git a/libsecurity_mds/lib/MDSAttrStrings.cpp b/Security/libsecurity_mds/lib/MDSAttrStrings.cpp similarity index 99% rename from libsecurity_mds/lib/MDSAttrStrings.cpp rename to Security/libsecurity_mds/lib/MDSAttrStrings.cpp index c94a902c..367008c8 100644 --- a/libsecurity_mds/lib/MDSAttrStrings.cpp +++ b/Security/libsecurity_mds/lib/MDSAttrStrings.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -21,7 +21,7 @@ Contains: Static tables to map attribute names to numeric values. - Copyright: (c) 2001 Apple Computer, Inc., all rights reserved. + Copyright (c) 2001,2011-2012,2014 Apple Inc. All Rights Reserved. */ #include "MDSAttrStrings.h" diff --git a/libsecurity_mds/lib/MDSAttrStrings.h b/Security/libsecurity_mds/lib/MDSAttrStrings.h similarity index 97% rename from libsecurity_mds/lib/MDSAttrStrings.h rename to Security/libsecurity_mds/lib/MDSAttrStrings.h index 36c2859e..badc642e 100644 --- a/libsecurity_mds/lib/MDSAttrStrings.h +++ b/Security/libsecurity_mds/lib/MDSAttrStrings.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -21,7 +21,7 @@ Contains: Static tables to map attribute names to numeric values. - Copyright: (c) 2001 Apple Computer, Inc., all rights reserved. + Copyright (c) 2001,2011,2014 Apple Inc. All Rights Reserved. */ #ifndef _MDS_ATTR_STRINGS_H_ diff --git a/libsecurity_mds/lib/MDSAttrUtils.cpp b/Security/libsecurity_mds/lib/MDSAttrUtils.cpp similarity index 98% rename from libsecurity_mds/lib/MDSAttrUtils.cpp rename to Security/libsecurity_mds/lib/MDSAttrUtils.cpp index 81bb41be..a47ecc4f 100644 --- a/libsecurity_mds/lib/MDSAttrUtils.cpp +++ b/Security/libsecurity_mds/lib/MDSAttrUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -21,7 +21,7 @@ Contains: Stateless functions used by MDSAttrParser. - Copyright: (c) 2001 Apple Computer, Inc., all rights reserved. + Copyright (c) 2001,2011,2014 Apple Inc. All Rights Reserved. */ #include "MDSAttrUtils.h" diff --git a/libsecurity_mds/lib/MDSAttrUtils.h b/Security/libsecurity_mds/lib/MDSAttrUtils.h similarity index 96% rename from libsecurity_mds/lib/MDSAttrUtils.h rename to Security/libsecurity_mds/lib/MDSAttrUtils.h index f244edd4..8ad06a4f 100644 --- a/libsecurity_mds/lib/MDSAttrUtils.h +++ b/Security/libsecurity_mds/lib/MDSAttrUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -21,7 +21,7 @@ Contains: Stateless functions used by MDSAttrParser. - Copyright: (c) 2001 Apple Computer, Inc., all rights reserved. + Copyright (c) 2001,2011,2014 Apple Inc. All Rights Reserved. */ #ifndef _MDS_ATTR_UTILS_H_ diff --git a/libsecurity_mds/lib/MDSDatabase.cpp b/Security/libsecurity_mds/lib/MDSDatabase.cpp similarity index 99% rename from libsecurity_mds/lib/MDSDatabase.cpp rename to Security/libsecurity_mds/lib/MDSDatabase.cpp index 0e8e24bc..fb388dae 100644 --- a/libsecurity_mds/lib/MDSDatabase.cpp +++ b/Security/libsecurity_mds/lib/MDSDatabase.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_mds/lib/MDSDatabase.h b/Security/libsecurity_mds/lib/MDSDatabase.h similarity index 98% rename from libsecurity_mds/lib/MDSDatabase.h rename to Security/libsecurity_mds/lib/MDSDatabase.h index ff9108ee..0849fe5a 100644 --- a/libsecurity_mds/lib/MDSDatabase.h +++ b/Security/libsecurity_mds/lib/MDSDatabase.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_mds/lib/MDSDictionary.cpp b/Security/libsecurity_mds/lib/MDSDictionary.cpp similarity index 99% rename from libsecurity_mds/lib/MDSDictionary.cpp rename to Security/libsecurity_mds/lib/MDSDictionary.cpp index 426f7a6c..604e0403 100644 --- a/libsecurity_mds/lib/MDSDictionary.cpp +++ b/Security/libsecurity_mds/lib/MDSDictionary.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -22,7 +22,7 @@ Contains: Internal representation of one MDS info file in the form of a CFDictionary. - Copyright: (c) 2001 Apple Computer, Inc., all rights reserved. + Copyright (c) 2001,2011-2012,2014 Apple Inc. All Rights Reserved. */ #include "MDSDictionary.h" diff --git a/libsecurity_mds/lib/MDSDictionary.h b/Security/libsecurity_mds/lib/MDSDictionary.h similarity index 96% rename from libsecurity_mds/lib/MDSDictionary.h rename to Security/libsecurity_mds/lib/MDSDictionary.h index 5f85c055..25839526 100644 --- a/libsecurity_mds/lib/MDSDictionary.h +++ b/Security/libsecurity_mds/lib/MDSDictionary.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -21,7 +21,7 @@ Contains: Internal representation of one MDS info file. - Copyright: (c) 2001 Apple Computer, Inc., all rights reserved. + Copyright (c) 2001,2011,2014 Apple Inc. All Rights Reserved. */ #ifndef _MDS_DICTIONARY_H_ diff --git a/libsecurity_mds/lib/MDSModule.cpp b/Security/libsecurity_mds/lib/MDSModule.cpp similarity index 98% rename from libsecurity_mds/lib/MDSModule.cpp rename to Security/libsecurity_mds/lib/MDSModule.cpp index 8fcb9fa2..ebf050cb 100644 --- a/libsecurity_mds/lib/MDSModule.cpp +++ b/Security/libsecurity_mds/lib/MDSModule.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_mds/lib/MDSModule.h b/Security/libsecurity_mds/lib/MDSModule.h similarity index 96% rename from libsecurity_mds/lib/MDSModule.h rename to Security/libsecurity_mds/lib/MDSModule.h index 2b3fd5c6..84c5a2d8 100644 --- a/libsecurity_mds/lib/MDSModule.h +++ b/Security/libsecurity_mds/lib/MDSModule.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_mds/lib/MDSPrefs.cpp b/Security/libsecurity_mds/lib/MDSPrefs.cpp similarity index 98% rename from libsecurity_mds/lib/MDSPrefs.cpp rename to Security/libsecurity_mds/lib/MDSPrefs.cpp index ef0af3f8..0135e6d8 100644 --- a/libsecurity_mds/lib/MDSPrefs.cpp +++ b/Security/libsecurity_mds/lib/MDSPrefs.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_mds/lib/MDSPrefs.h b/Security/libsecurity_mds/lib/MDSPrefs.h similarity index 95% rename from libsecurity_mds/lib/MDSPrefs.h rename to Security/libsecurity_mds/lib/MDSPrefs.h index 80e0f1b3..e05409ad 100644 --- a/libsecurity_mds/lib/MDSPrefs.h +++ b/Security/libsecurity_mds/lib/MDSPrefs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/Security/libsecurity_mds/lib/MDSSchema.cpp b/Security/libsecurity_mds/lib/MDSSchema.cpp new file mode 100644 index 00000000..a1260b49 --- /dev/null +++ b/Security/libsecurity_mds/lib/MDSSchema.cpp @@ -0,0 +1,823 @@ +/* + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please obtain + * a copy of the License at http://www.apple.com/publicsource and read it before + * using this file. + * + * This 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. + */ + + +// +// MDSSchema.cpp +// +// Definitions of structures which define the schema, including attributes +// and indexes, for the standard tables that are part of the MDS database. +// + +#include "MDSSchema.h" +#include +#include + +namespace Security +{ + +/* + * There appears to be a bug in AppleDatabase which prevents our assigning + * schema to the meta-tables. + */ +#define DEFINE_META_TABLES 0 + +/* indicates "no MDSNameValuePair table" in a RELATION_INFO declaration. */ +#define NO_NVP NULL + +// +// Schema for the lone table in the Object Directory Database. +// +static const CSSM_DB_ATTRIBUTE_INFO objectAttrs[] = { + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(Manifest, BLOB), + DB_ATTRIBUTE(ModuleName, STRING), + DB_ATTRIBUTE(Path, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + + /* not in the CDSA spec; denotes a plugin which is statically linked to CSSM */ + DB_ATTRIBUTE(BuiltIn, UINT32), +}; + +static const CSSM_DB_INDEX_INFO objectIndex[] = { + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING) +}; + +const RelationInfo kObjectRelation = + RELATION_INFO(MDS_OBJECT_RECORDTYPE, + objectAttrs, + NO_NVP, // no symbolic names + objectIndex); + +// +// Schema for the various tables in the CDSA Directory Database. +// + +// CSSM Relation. +static const CSSM_DB_ATTRIBUTE_INFO cssmAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(CDSAVersion, STRING), + DB_ATTRIBUTE(Vendor, STRING), + DB_ATTRIBUTE(Desc, STRING), + DB_ATTRIBUTE(NativeServices, UINT32), +}; + +static const MDSNameValuePair *cssmNvp[] = { + NULL, NULL, NULL, NULL, + MDSServiceNames +}; + +static const CSSM_DB_INDEX_INFO cssmIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING) +}; + +// KRMM Relation. +static const CSSM_DB_ATTRIBUTE_INFO krmmAttrs[] = +{ + DB_ATTRIBUTE(CSSMGuid, STRING), + DB_ATTRIBUTE(PolicyType, UINT32), + DB_ATTRIBUTE(PolicyName, STRING), + DB_ATTRIBUTE(PolicyPath, STRING), + DB_ATTRIBUTE(PolicyInfo, BLOB), + DB_ATTRIBUTE(PolicyManifest, BLOB), + /* + * This attribute is not defined in the CDSA spec. It's only here, in the schema, + * to avoid throwing exceptions when searching a DB for any records associated + * with a specified GUID - in all other schemas, a guid is specified as a + * ModuleID. + */ + DB_ATTRIBUTE(ModuleID, STRING), +}; + +static const MDSNameValuePair *krmmNvp[] = { + NULL, MDSKrPolicyTypeNames, NULL, NULL, + NULL, NULL, +}; + +static const CSSM_DB_INDEX_INFO krmmIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(CSSMGuid, STRING), + UNIQUE_INDEX_ATTRIBUTE(PolicyType, UINT32) +}; + +// EMM Relation. +static const CSSM_DB_ATTRIBUTE_INFO emmAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(Manifest, BLOB), + DB_ATTRIBUTE(ModuleName, STRING), + DB_ATTRIBUTE(Path, STRING), + DB_ATTRIBUTE(CDSAVersion, STRING), + DB_ATTRIBUTE(EMMSpecVersion, STRING), + DB_ATTRIBUTE(Desc, STRING), + DB_ATTRIBUTE(PolicyStmt, BLOB), + DB_ATTRIBUTE(EmmVersion, STRING), + DB_ATTRIBUTE(EmmVendor, STRING), + DB_ATTRIBUTE(EmmType, UINT32), // does this need a name/value table? +}; + +static const CSSM_DB_INDEX_INFO emmIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING) +}; + +// Primary EMM Service Provider Relation. +static const CSSM_DB_ATTRIBUTE_INFO emmPrimaryAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(ServiceType, UINT32), + DB_ATTRIBUTE(Manifest, BLOB), + DB_ATTRIBUTE(ModuleName, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + DB_ATTRIBUTE(Vendor, STRING), + DB_ATTRIBUTE(SampleTypes, MULTI_UINT32), + DB_ATTRIBUTE(AclSubjectTypes, MULTI_UINT32), + DB_ATTRIBUTE(AuthTags, MULTI_UINT32), + DB_ATTRIBUTE(EmmSpecVersion, STRING), +}; + +static const MDSNameValuePair *emmPrimaryNvp[] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, MDSSampleTypeNames, + MDSAclSubjectTypeNames, + MDSAclAuthTagNames, + NULL +}; + +static const CSSM_DB_INDEX_INFO emmPrimaryIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32), + UNIQUE_INDEX_ATTRIBUTE(ServiceType, UINT32) +}; + +// Common Relation. +static const CSSM_DB_ATTRIBUTE_INFO commonAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(Manifest, BLOB), + DB_ATTRIBUTE(ModuleName, STRING), + DB_ATTRIBUTE(Path, STRING), + DB_ATTRIBUTE(CDSAVersion, STRING), + DB_ATTRIBUTE(Desc, STRING), + DB_ATTRIBUTE(DynamicFlag, UINT32), + DB_ATTRIBUTE(MultiThreadFlag, UINT32), + DB_ATTRIBUTE(ServiceMask, UINT32), +}; + +static const MDSNameValuePair *commonNvp[] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + MDSServiceNames +}; + +static const CSSM_DB_INDEX_INFO commonIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING) +}; + +// CSP Primary Relation. +static const CSSM_DB_ATTRIBUTE_INFO cspPrimaryAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(Manifest, BLOB), + DB_ATTRIBUTE(ModuleName, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + DB_ATTRIBUTE(Vendor, STRING), + DB_ATTRIBUTE(CspType, UINT32), + DB_ATTRIBUTE(CspFlags, UINT32), + DB_ATTRIBUTE(CspCustomFlags, UINT32), + DB_ATTRIBUTE(UseeTags, MULTI_UINT32), + DB_ATTRIBUTE(SampleTypes, MULTI_UINT32), + DB_ATTRIBUTE(AclSubjectTypes, MULTI_UINT32), + DB_ATTRIBUTE(AuthTags, MULTI_UINT32), +}; + +static const MDSNameValuePair *cspPrimaryNvp[] = { + NULL, NULL, NULL, NULL, + NULL, NULL, + MDSCspTypeNames, + MDSCspFlagsNames, + NULL, + MDSUseeTagsNames, + MDSSampleTypeNames, + MDSAclSubjectTypeNames, + MDSAclAuthTagNames +}; + +static const CSSM_DB_INDEX_INFO cspPrimaryIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) +}; + +// CSP Capabilities Relation. +static const CSSM_DB_ATTRIBUTE_INFO cspCapabilitiesAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(UseeTag, UINT32), + DB_ATTRIBUTE(ContextType, UINT32), + DB_ATTRIBUTE(AlgType, UINT32), + DB_ATTRIBUTE(GroupId, UINT32), + DB_ATTRIBUTE(AttributeType, UINT32), + DB_ATTRIBUTE(AttributeValue, MULTI_UINT32), + DB_ATTRIBUTE(Description, STRING), +}; +static const MDSNameValuePair *cspCapabilitiesNvp[] = { + NULL, + NULL, + MDSUseeTagsNames, + MDSContextTypeNames, + MDSAlgorithmNames, + NULL, + MDSAttributeTypeNames, + NULL, + NULL +}; + +static const CSSM_DB_INDEX_INFO cspCapabilitiesIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32), + UNIQUE_INDEX_ATTRIBUTE(UseeTag, UINT32), + UNIQUE_INDEX_ATTRIBUTE(ContextType, UINT32), + UNIQUE_INDEX_ATTRIBUTE(AlgType, UINT32), + UNIQUE_INDEX_ATTRIBUTE(GroupId, UINT32), + UNIQUE_INDEX_ATTRIBUTE(AttributeType, STRING) +}; + +// special case "subschema" for parsing CSPCapabilities. These arrays correspond +// dictionaries within a CSPCapabilities info file; they are not part of +// our DB's schema. They are declared only to streamline the +// MDSAttrParser::parseCspCapabilitiesRecord function. No index info is needed. + +// top-level info, applied to the dictionary for the whole file. +static const CSSM_DB_ATTRIBUTE_INFO kAttributesCSPCapabilitiesDict1[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), +}; +const RelationInfo CSPCapabilitiesDict1RelInfo = + RELATION_INFO( + MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE, // actually a don't care + kAttributesCSPCapabilitiesDict1, + NULL, // no NVP needed + NULL); // no index + +// "Capabilities" is an array of dictionaries of these +static const CSSM_DB_ATTRIBUTE_INFO kAttributesCSPCapabilitiesDict2[] = +{ + DB_ATTRIBUTE(AlgType, UINT32), + DB_ATTRIBUTE(ContextType, UINT32), + DB_ATTRIBUTE(UseeTag, UINT32), + DB_ATTRIBUTE(Description, STRING), +}; +static const MDSNameValuePair *CSPCapabilitiesDict2Nvp[] = { + MDSAlgorithmNames, + MDSContextTypeNames, + MDSUseeTagsNames, + NULL +}; +const RelationInfo CSPCapabilitiesDict2RelInfo = + RELATION_INFO( + MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE, // actually a don't care + kAttributesCSPCapabilitiesDict2, + CSPCapabilitiesDict2Nvp, + NULL); // no index + +// Within a Capabilities array, the Attributes array is an array of +// Dictionaries of these. +static const CSSM_DB_ATTRIBUTE_INFO kAttributesCSPCapabilitiesDict3[] = +{ + DB_ATTRIBUTE(AttributeType, UINT32), + DB_ATTRIBUTE(AttributeValue, MULTI_UINT32), +}; +static const MDSNameValuePair *CSPCapabilitiesDict3Nvp[] = { + MDSAttributeTypeNames, + NULL +}; +const RelationInfo CSPCapabilitiesDict3RelInfo = + RELATION_INFO( + MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE, // actually a don't care + kAttributesCSPCapabilitiesDict3, + CSPCapabilitiesDict3Nvp, + NULL); + + + +// CSP Encapsulated Products Relation. +static const CSSM_DB_ATTRIBUTE_INFO cspEncapsulatedAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(ProductDesc, STRING), + DB_ATTRIBUTE(ProductVendor, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + DB_ATTRIBUTE(ProductFlags, UINT32), + DB_ATTRIBUTE(CustomFlags, UINT32), + DB_ATTRIBUTE(StandardDesc, STRING), + DB_ATTRIBUTE(StandardVersion, STRING), + DB_ATTRIBUTE(ReaderDesc, STRING), + DB_ATTRIBUTE(ReaderVendor, STRING), + DB_ATTRIBUTE(ReaderVersion, STRING), + DB_ATTRIBUTE(ReaderFirmwareVersion, STRING), + DB_ATTRIBUTE(ReaderFlags, UINT32), + DB_ATTRIBUTE(ReaderCustomFlags, UINT32), + DB_ATTRIBUTE(ReaderSerialNumber, STRING), +}; + +static const MDSNameValuePair *cspEncapsulatedNvp[] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, MDSCspReaderFlagsNames, NULL, NULL +}; + +static const CSSM_DB_INDEX_INFO cspEncapsulatedIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) +}; + +// CSP Smartcardinfo Relation. +static const CSSM_DB_ATTRIBUTE_INFO cspSmartCardAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(ScDesc, STRING), + DB_ATTRIBUTE(ScVendor, STRING), + DB_ATTRIBUTE(ScVersion, STRING), + DB_ATTRIBUTE(ScFirmwareVersion, STRING), + DB_ATTRIBUTE(ScFlags, UINT32), + DB_ATTRIBUTE(ScCustomFlags, UINT32), + DB_ATTRIBUTE(ScSerialNumber, STRING), +}; +static const MDSNameValuePair *cspSmartCardNvp[] = { + NULL, NULL, NULL, NULL, + NULL, NULL, MDSCspScFlagsNames, NULL, + NULL, +}; + +static const CSSM_DB_INDEX_INFO cspSmartCardIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32), + UNIQUE_INDEX_ATTRIBUTE(ScDesc, STRING), + UNIQUE_INDEX_ATTRIBUTE(ScVendor, STRING), + UNIQUE_INDEX_ATTRIBUTE(ScVersion, STRING), + UNIQUE_INDEX_ATTRIBUTE(ScFirmwareVersion, STRING), + UNIQUE_INDEX_ATTRIBUTE(ScFlags, UINT32) +}; + +// DL Primary Relation. +static const CSSM_DB_ATTRIBUTE_INFO dlPrimaryAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(Manifest, BLOB), + DB_ATTRIBUTE(ModuleName, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + DB_ATTRIBUTE(Vendor, STRING), + DB_ATTRIBUTE(DLType, UINT32), + DB_ATTRIBUTE(QueryLimitsFlag, UINT32), // a completely bogus attr; see spec + DB_ATTRIBUTE(SampleTypes, MULTI_UINT32), + DB_ATTRIBUTE(AclSubjectTypes, MULTI_UINT32), + DB_ATTRIBUTE(AuthTags, MULTI_UINT32), + DB_ATTRIBUTE(ConjunctiveOps, MULTI_UINT32), + DB_ATTRIBUTE(RelationalOps, MULTI_UINT32), +}; +static const MDSNameValuePair *dlPrimaryNvp[] = { + NULL, NULL, NULL, NULL, + NULL, NULL, MDSDlTypeNames, NULL, + MDSSampleTypeNames, + MDSAclSubjectTypeNames, + MDSAclAuthTagNames, + MDSDbConjunctiveNames, + MDSDbOperatorNames +}; +static const CSSM_DB_INDEX_INFO dlPrimaryIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) +}; + +// DL Encapsulated Products Relation. +static const CSSM_DB_ATTRIBUTE_INFO dlEncapsulatedAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(ProductDesc, STRING), + DB_ATTRIBUTE(ProductVendor, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + DB_ATTRIBUTE(ProductFlags, UINT32), + DB_ATTRIBUTE(StandardDesc, STRING), + DB_ATTRIBUTE(StandardVersion, STRING), + DB_ATTRIBUTE(Protocol, UINT32), + DB_ATTRIBUTE(RetrievalMode, UINT32), +}; + +static const MDSNameValuePair *dlEncapsulatedNvp[] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + MDSNetProtocolNames, + MDSDbRetrievalModeNames +}; + +static const CSSM_DB_INDEX_INFO dlEncapsulatedIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) +}; + +// CL Primary Relation. +static const CSSM_DB_ATTRIBUTE_INFO clPrimaryAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(Manifest, BLOB), + DB_ATTRIBUTE(ModuleName, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + DB_ATTRIBUTE(Vendor, STRING), + DB_ATTRIBUTE(CertTypeFormat, UINT32), + DB_ATTRIBUTE(CrlTypeFormat, UINT32), + DB_ATTRIBUTE(CertFieldNames, BLOB), + DB_ATTRIBUTE(BundleTypeFormat, MULTI_UINT32), + DB_ATTRIBUTE(XlationTypeFormat, MULTI_UINT32), + DB_ATTRIBUTE(TemplateFieldNames, BLOB), +}; + +static const MDSNameValuePair *clPrimaryNvp[] = { + NULL, NULL, NULL, NULL, + NULL, NULL, MDSCertTypeNames, MDSCrlTypeNames, + NULL, + MDSCertBundleTypeNames, + MDSCertTypeNames, // translation type - same as cert type - right? + NULL +}; + +static const CSSM_DB_INDEX_INFO clPrimaryIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) +}; + +// CL Encapsulated Products Relation. +static const CSSM_DB_ATTRIBUTE_INFO clEncapsulatedAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(ProductDesc, STRING), + DB_ATTRIBUTE(ProductVendor, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + DB_ATTRIBUTE(ProductFlags, UINT32), + DB_ATTRIBUTE(StandardDesc, STRING), + DB_ATTRIBUTE(StandardVersion, STRING), +}; + +static const CSSM_DB_INDEX_INFO clEncapsulatedIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) +}; + +// TP Primary Relation. +static const CSSM_DB_ATTRIBUTE_INFO tpPrimaryAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(Manifest, BLOB), + DB_ATTRIBUTE(ModuleName, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + DB_ATTRIBUTE(Vendor, STRING), + DB_ATTRIBUTE(CertTypeFormat, UINT32), + DB_ATTRIBUTE(SampleTypes, MULTI_UINT32), + DB_ATTRIBUTE(AclSubjectTypes, MULTI_UINT32), + DB_ATTRIBUTE(AuthTags, MULTI_UINT32), +}; + +static const MDSNameValuePair *tpPrimaryNvp[] = { + NULL, NULL, NULL, NULL, + NULL, NULL, + MDSCertTypeNames, + MDSSampleTypeNames, + MDSAclSubjectTypeNames, + MDSAclAuthTagNames, +}; + +static const CSSM_DB_INDEX_INFO tpPrimaryIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) +}; + +// TP Policy-OIDs Relation. +static const CSSM_DB_ATTRIBUTE_INFO tpPolicyOidsAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(OID, BLOB), + DB_ATTRIBUTE(Value, BLOB), +}; + +static const CSSM_DB_INDEX_INFO tpPolicyOidsIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32), + UNIQUE_INDEX_ATTRIBUTE(OID, BLOB) +}; + +// special case "subschema" for parsing tpPolicyOidsAttrs. These arrays correspond +// dictionaries within a tpPolicyOidsAttrs info file; they are not part of +// our DB's schema. They are declared only to streamline the +// MDSAttrParser::parseTpPolicyOidsRecord function. No index info is needed. + +// top-level info, applied to the dictionary for the whole file. +static const CSSM_DB_ATTRIBUTE_INFO tpPolicyOidsDict1[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), +}; +const RelationInfo TpPolicyOidsDict1RelInfo = + RELATION_INFO( + MDS_CDSADIR_TP_OIDS_RECORDTYPE, // actually a don't care + tpPolicyOidsDict1, + NULL, // no NVP needed + NULL); // no index + +// One element of the "Policies" array maps to one of these. +static const CSSM_DB_ATTRIBUTE_INFO tpPolicyOidsDict2[] = +{ + DB_ATTRIBUTE(OID, BLOB), + DB_ATTRIBUTE(Value, BLOB), +}; +const RelationInfo TpPolicyOidsDict2RelInfo = + RELATION_INFO( + MDS_CDSADIR_TP_OIDS_RECORDTYPE, // actually a don't care + tpPolicyOidsDict2, + NULL, // no NVP needed + NULL); // no index + +// TP Encapsulated Products Relation. +static const CSSM_DB_ATTRIBUTE_INFO tpEncapsulatedAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(ProductDesc, STRING), + DB_ATTRIBUTE(ProductVendor, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + DB_ATTRIBUTE(ProductFlags, UINT32), // vendor-specific, right? + DB_ATTRIBUTE(AuthorityRequestType, MULTI_UINT32), + DB_ATTRIBUTE(StandardDesc, STRING), + DB_ATTRIBUTE(StandardVersion, STRING), + DB_ATTRIBUTE(ProtocolDesc, STRING), + DB_ATTRIBUTE(ProtocolFlags, UINT32), + DB_ATTRIBUTE(CertClassName, STRING), + DB_ATTRIBUTE(RootCertificate, BLOB), + DB_ATTRIBUTE(RootCertTypeFormat, UINT32), +}; +static const MDSNameValuePair *tpEncapsulatedNvp[] = { + NULL, NULL, NULL, NULL, + NULL, NULL, MDSTpAuthRequestNames, NULL, + NULL, NULL, NULL, NULL, + NULL, MDSCertTypeNames +}; + +static const CSSM_DB_INDEX_INFO tpEncapsulatedIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) +}; + +#if DEFINE_META_TABLES +// MDS Schema Relations (meta) Relation. +static const CSSM_DB_ATTRIBUTE_INFO mdsSchemaRelationsAttrs[] = +{ + DB_ATTRIBUTE(RelationID, UINT32), + DB_ATTRIBUTE(RelationName, STRING), +}; + +static const CSSM_DB_INDEX_INFO mdsSchemaRelationsIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(RelationID, UINT32), +}; + +// MDS Schema Attributes (meta) Relation. +static const CSSM_DB_ATTRIBUTE_INFO mdsSchemaAttributesAttrs[] = +{ + DB_ATTRIBUTE(RelationID, UINT32), + DB_ATTRIBUTE(AttributeID, UINT32), + DB_ATTRIBUTE(AttributeNameFormat, UINT32), + DB_ATTRIBUTE(AttributeName, STRING), + DB_ATTRIBUTE(AttributeNameID, BLOB), + DB_ATTRIBUTE(AttributeFormat, UINT32), +}; + +static const CSSM_DB_INDEX_INFO mdsSchemaAttributesIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(RelationID, UINT32), + UNIQUE_INDEX_ATTRIBUTE(AttributeID, UINT32) +}; + +// MDS Schema Indexes (meta) Relation. +static const CSSM_DB_ATTRIBUTE_INFO mdsSchemaIndexesAttrs[] = +{ + DB_ATTRIBUTE(RelationID, UINT32), + DB_ATTRIBUTE(IndexID, UINT32), + DB_ATTRIBUTE(AttributeID, UINT32), + DB_ATTRIBUTE(IndexType, UINT32), + DB_ATTRIBUTE(IndexedDataLocation, UINT32), +}; + +static const CSSM_DB_INDEX_INFO mdsSchemaIndexesIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(RelationID, UINT32), + UNIQUE_INDEX_ATTRIBUTE(IndexID, UINT32) +}; + +#endif /* DEFINE_META_TABLES */ + +// AC Primary Relation. +static const CSSM_DB_ATTRIBUTE_INFO acPrimaryAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(Manifest, BLOB), + DB_ATTRIBUTE(ModuleName, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + DB_ATTRIBUTE(Vendor, STRING), +}; + +static const CSSM_DB_INDEX_INFO acPrimaryIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) +}; + +// KR Primary Relation. +static const CSSM_DB_ATTRIBUTE_INFO krPrimaryAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(Manifest, BLOB), + DB_ATTRIBUTE(ModuleName, STRING), + DB_ATTRIBUTE(CompatCSSMVersion, STRING), + DB_ATTRIBUTE(Version, STRING), + DB_ATTRIBUTE(Vendor, STRING), + DB_ATTRIBUTE(Description, STRING), + DB_ATTRIBUTE(ConfigFileLocation, STRING), +}; + +static const CSSM_DB_INDEX_INFO krPrimaryIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) +}; + +// list of all built-in schema for the CDSA Directory DB. +const RelationInfo kMDSRelationInfo[] = +{ + RELATION_INFO(MDS_CDSADIR_CSSM_RECORDTYPE, + cssmAttrs, + cssmNvp, + cssmIndex), + RELATION_INFO(MDS_CDSADIR_KRMM_RECORDTYPE, + krmmAttrs, + krmmNvp, + krmmIndex), + RELATION_INFO(MDS_CDSADIR_EMM_RECORDTYPE, + emmAttrs, + NO_NVP, // FIXME - what is the uint32 EmmType here? + emmIndex), + RELATION_INFO(MDS_CDSADIR_EMM_PRIMARY_RECORDTYPE, + emmPrimaryAttrs, + emmPrimaryNvp, + emmPrimaryIndex), + RELATION_INFO(MDS_CDSADIR_COMMON_RECORDTYPE, + commonAttrs, + commonNvp, + commonIndex), + RELATION_INFO(MDS_CDSADIR_CSP_PRIMARY_RECORDTYPE, + cspPrimaryAttrs, + cspPrimaryNvp, + cspPrimaryIndex), + RELATION_INFO(MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE, + cspCapabilitiesAttrs, + cspCapabilitiesNvp, + cspCapabilitiesIndex), + RELATION_INFO(MDS_CDSADIR_CSP_ENCAPSULATED_PRODUCT_RECORDTYPE, + cspEncapsulatedAttrs, + cspEncapsulatedNvp, + cspEncapsulatedIndex), + RELATION_INFO(MDS_CDSADIR_CSP_SC_INFO_RECORDTYPE, + cspSmartCardAttrs, + cspSmartCardNvp, + cspSmartCardIndex), + RELATION_INFO(MDS_CDSADIR_DL_PRIMARY_RECORDTYPE, + dlPrimaryAttrs, + dlPrimaryNvp, + dlPrimaryIndex), + RELATION_INFO(MDS_CDSADIR_DL_ENCAPSULATED_PRODUCT_RECORDTYPE, + dlEncapsulatedAttrs, + dlEncapsulatedNvp, + dlEncapsulatedIndex), + RELATION_INFO(MDS_CDSADIR_CL_PRIMARY_RECORDTYPE, + clPrimaryAttrs, + clPrimaryNvp, + clPrimaryIndex), + RELATION_INFO(MDS_CDSADIR_CL_ENCAPSULATED_PRODUCT_RECORDTYPE, + clEncapsulatedAttrs, + NO_NVP, // none needed + clEncapsulatedIndex), + RELATION_INFO(MDS_CDSADIR_TP_PRIMARY_RECORDTYPE, + tpPrimaryAttrs, + tpPrimaryNvp, + tpPrimaryIndex), + RELATION_INFO(MDS_CDSADIR_TP_OIDS_RECORDTYPE, + tpPolicyOidsAttrs, + NO_NVP, // none needed + tpPolicyOidsIndex), + RELATION_INFO(MDS_CDSADIR_TP_ENCAPSULATED_PRODUCT_RECORDTYPE, + tpEncapsulatedAttrs, + tpEncapsulatedNvp, + tpEncapsulatedIndex), + #if DEFINE_META_TABLES + RELATION_INFO(MDS_CDSADIR_MDS_SCHEMA_RELATIONS, + mdsSchemaRelationsAttrs, + NO_NVP, + mdsSchemaRelationsIndex), + RELATION_INFO(MDS_CDSADIR_MDS_SCHEMA_ATTRIBUTES, + mdsSchemaAttributesAttrs, + NO_NVP, + mdsSchemaAttributesIndex), + RELATION_INFO(MDS_CDSADIR_MDS_SCHEMA_INDEXES, + mdsSchemaIndexesAttrs, + NO_NVP, + mdsSchemaIndexesIndex), + #endif /* DEFINE_META_TABLES */ + RELATION_INFO(MDS_CDSADIR_AC_PRIMARY_RECORDTYPE, + acPrimaryAttrs, + NO_NVP, // none needed + acPrimaryIndex), + RELATION_INFO(MDS_CDSADIR_KR_PRIMARY_RECORDTYPE, + krPrimaryAttrs, + NO_NVP, // none needed + krPrimaryIndex) +}; + +const unsigned kNumMdsRelations = sizeof(kMDSRelationInfo) / sizeof(RelationInfo); + +// Map a CSSM_DB_RECORDTYPE to a RelationInfo *. +extern const RelationInfo *MDSRecordTypeToRelation( + CSSM_DB_RECORDTYPE recordType) +{ + const RelationInfo *relInfo = kMDSRelationInfo; + unsigned dex; + + for(dex=0; dexDataRecordType == recordType) { + return relInfo; + } + relInfo++; + } + if(recordType == MDS_OBJECT_RECORDTYPE) { + return &kObjectRelation; + } + return NULL; +} + +// same as above, based on record type as string. +extern const RelationInfo *MDSRecordTypeNameToRelation( + const char *recordTypeName) +{ + const RelationInfo *relInfo = kMDSRelationInfo; + unsigned dex; + + for(dex=0; dexrelationName)) { + return relInfo; + } + relInfo++; + } + return NULL; +} + +} // end namespace Security diff --git a/Security/libsecurity_mds/lib/MDSSchema.h b/Security/libsecurity_mds/lib/MDSSchema.h new file mode 100644 index 00000000..ba166086 --- /dev/null +++ b/Security/libsecurity_mds/lib/MDSSchema.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please obtain + * a copy of the License at http://www.apple.com/publicsource and read it before + * using this file. + * + * This 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. + */ + + +// +// MDSSchema.h +// +// Declarations of structures which define the schema, including attributes +// and indexes, for the standard tables that are part of the MDS database. +// + +#ifndef _MDSSCHEMA_H +#define _MDSSCHEMA_H + +#include +#include "MDSAttrStrings.h" + +namespace Security +{ + +// Structure used to store information which is needed to create +// a relation with indexes. The info in one of these structs maps to one +// record type in a CSSM_DBINFO - both record attribute info and index info. +// The nameValues field refers to an array of MDSNameValuePair array pointers +// which are used to convert attribute values from strings to uint32s via +// MDS_StringToUint32. The nameValues array is parallel to the AttributeInfo +// array. +struct RelationInfo { + CSSM_DB_RECORDTYPE DataRecordType; + const char *relationName; + uint32 NumberOfAttributes; + const CSSM_DB_ATTRIBUTE_INFO *AttributeInfo; + const MDSNameValuePair **nameValues; + uint32 NumberOfIndexes; + const CSSM_DB_INDEX_INFO *IndexInfo; +}; + +// Macros used to simplify declarations of attributes and indexes. + +// declare a CSSM_DB_ATTRIBUTE_INFO +#define DB_ATTRIBUTE(name, type) \ + { CSSM_DB_ATTRIBUTE_NAME_AS_STRING, \ + {(char*) #name}, \ + CSSM_DB_ATTRIBUTE_FORMAT_ ## type \ + } + +// declare a CSSM_DB_INDEX_INFO +#define UNIQUE_INDEX_ATTRIBUTE(name, type) \ + { CSSM_DB_INDEX_UNIQUE, \ + CSSM_DB_INDEX_ON_ATTRIBUTE, \ + { CSSM_DB_ATTRIBUTE_NAME_AS_STRING, \ + {(char*) #name}, \ + CSSM_DB_ATTRIBUTE_FORMAT_ ## type \ + } \ + } + +// declare a RelationInfo +#define RELATION_INFO(relationId, attributes, nameValues, indexes) \ + { relationId, \ + #relationId, \ + sizeof(attributes) / sizeof(CSSM_DB_ATTRIBUTE_INFO), \ + attributes, \ + nameValues, \ + sizeof(indexes) / sizeof(CSSM_DB_INDEX_INFO), \ + indexes } + +// Object directory DB - one built-in schema. +extern const RelationInfo kObjectRelation; + +// list of all built-in schema for the CDSA Directory DB. +extern const RelationInfo kMDSRelationInfo[]; +extern const unsigned kNumMdsRelations; // size of kMDSRelationInfo[] + +// special case "subschema" for parsing CSPCapabilities. +extern const RelationInfo CSPCapabilitiesDict1RelInfo; +extern const RelationInfo CSPCapabilitiesDict2RelInfo; +extern const RelationInfo CSPCapabilitiesDict3RelInfo; + +// special case "subschema" for parsing TPPolicyOids. +extern const RelationInfo TpPolicyOidsDict1RelInfo; +extern const RelationInfo TpPolicyOidsDict2RelInfo; + +// Map a CSSM_DB_RECORDTYPE to a RelationInfo *. +extern const RelationInfo *MDSRecordTypeToRelation( + CSSM_DB_RECORDTYPE recordType); + +// same as above, based on record type as string. +extern const RelationInfo *MDSRecordTypeNameToRelation( + const char *recordTypeName); + +} // end namespace Security + +#endif // _MDSSCHEMA_H diff --git a/libsecurity_mds/lib/MDSSession.cpp b/Security/libsecurity_mds/lib/MDSSession.cpp similarity index 99% rename from libsecurity_mds/lib/MDSSession.cpp rename to Security/libsecurity_mds/lib/MDSSession.cpp index 2c19f9b3..4216cd87 100644 --- a/libsecurity_mds/lib/MDSSession.cpp +++ b/Security/libsecurity_mds/lib/MDSSession.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_mds/lib/MDSSession.h b/Security/libsecurity_mds/lib/MDSSession.h similarity index 98% rename from libsecurity_mds/lib/MDSSession.h rename to Security/libsecurity_mds/lib/MDSSession.h index a7c2c6da..0c8718da 100644 --- a/libsecurity_mds/lib/MDSSession.h +++ b/Security/libsecurity_mds/lib/MDSSession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_mds/lib/mds.h b/Security/libsecurity_mds/lib/mds.h similarity index 97% rename from libsecurity_mds/lib/mds.h rename to Security/libsecurity_mds/lib/mds.h index b48a2162..cc75ad2e 100644 --- a/libsecurity_mds/lib/mds.h +++ b/Security/libsecurity_mds/lib/mds.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -21,7 +21,7 @@ Contains: Module Directory Services Data Types and API. - Copyright: (c) 1999-2000 Apple Computer, Inc., all rights reserved. + Copyright (c) 1999-2000,2011,2014 Apple Inc. All Rights Reserved. */ #ifndef _MDS_H_ diff --git a/libsecurity_mds/lib/mds_schema.h b/Security/libsecurity_mds/lib/mds_schema.h similarity index 98% rename from libsecurity_mds/lib/mds_schema.h rename to Security/libsecurity_mds/lib/mds_schema.h index 2c151180..663967d5 100644 --- a/libsecurity_mds/lib/mds_schema.h +++ b/Security/libsecurity_mds/lib/mds_schema.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -21,7 +21,7 @@ Contains: Module Directory Services Schema for CSSM. - Copyright: (c) 1999-2000 Apple Computer, Inc., all rights reserved. + Copyright (c) 1999-2000,2011,2014 Apple Inc. All Rights Reserved. */ #ifndef _MDS_SCHEMA_H_ diff --git a/libsecurity_mds/lib/mdsapi.cpp b/Security/libsecurity_mds/lib/mdsapi.cpp similarity index 98% rename from libsecurity_mds/lib/mdsapi.cpp rename to Security/libsecurity_mds/lib/mdsapi.cpp index 5ca45339..a23fe744 100644 --- a/libsecurity_mds/lib/mdsapi.cpp +++ b/Security/libsecurity_mds/lib/mdsapi.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -22,7 +22,7 @@ Contains: Module Directory Services Data Types and API. - Copyright: (c) 1999 Apple Computer, Inc., all rights reserved. + Copyright (c) 1999,2011,2014 Apple Inc. All Rights Reserved. This is the C API wrapper for the C++ MDS implementation. Most of this file could also be generated by the same perl script that generates the plugin diff --git a/libsecurity_mds/lib/mdspriv.h b/Security/libsecurity_mds/lib/mdspriv.h similarity index 95% rename from libsecurity_mds/lib/mdspriv.h rename to Security/libsecurity_mds/lib/mdspriv.h index eee712e5..53c13b7d 100644 --- a/libsecurity_mds/lib/mdspriv.h +++ b/Security/libsecurity_mds/lib/mdspriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_mds/lib/security_mds.exp b/Security/libsecurity_mds/lib/security_mds.exp similarity index 100% rename from libsecurity_mds/lib/security_mds.exp rename to Security/libsecurity_mds/lib/security_mds.exp diff --git a/libsecurity_mds/libsecurity_mds.xcodeproj/project.pbxproj b/Security/libsecurity_mds/libsecurity_mds.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_mds/libsecurity_mds.xcodeproj/project.pbxproj rename to Security/libsecurity_mds/libsecurity_mds.xcodeproj/project.pbxproj diff --git a/libsecurity_ocspd/Info-security_ocspd.plist b/Security/libsecurity_ocspd/Info-security_ocspd.plist similarity index 100% rename from libsecurity_ocspd/Info-security_ocspd.plist rename to Security/libsecurity_ocspd/Info-security_ocspd.plist diff --git a/libsecurity_ocspd/client/ocspdClient.cpp b/Security/libsecurity_ocspd/client/ocspdClient.cpp similarity index 93% rename from libsecurity_ocspd/client/ocspdClient.cpp rename to Security/libsecurity_ocspd/client/ocspdClient.cpp index 8c8e73a3..b7b0372a 100644 --- a/libsecurity_ocspd/client/ocspdClient.cpp +++ b/Security/libsecurity_ocspd/client/ocspdClient.cpp @@ -1,21 +1,22 @@ /* - * Copyright (c) 2002,2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000,2002,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. + * 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. * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * 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 OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. + * 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@ */ diff --git a/libsecurity_ocspd/client/ocspdClient.h b/Security/libsecurity_ocspd/client/ocspdClient.h similarity index 84% rename from libsecurity_ocspd/client/ocspdClient.h rename to Security/libsecurity_ocspd/client/ocspdClient.h index 9aba7a3a..ff6ae495 100644 --- a/libsecurity_ocspd/client/ocspdClient.h +++ b/Security/libsecurity_ocspd/client/ocspdClient.h @@ -1,21 +1,22 @@ /* - * Copyright (c) 2002,2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000,2002,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. + * 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. * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * 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 OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. + * 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@ */ diff --git a/libsecurity_ocspd/common/ocspExtensions.cpp b/Security/libsecurity_ocspd/common/ocspExtensions.cpp similarity index 98% rename from libsecurity_ocspd/common/ocspExtensions.cpp rename to Security/libsecurity_ocspd/common/ocspExtensions.cpp index e2b96951..b243bac0 100644 --- a/libsecurity_ocspd/common/ocspExtensions.cpp +++ b/Security/libsecurity_ocspd/common/ocspExtensions.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_ocspd/common/ocspExtensions.h b/Security/libsecurity_ocspd/common/ocspExtensions.h similarity index 98% rename from libsecurity_ocspd/common/ocspExtensions.h rename to Security/libsecurity_ocspd/common/ocspExtensions.h index 4e7075ac..b984c908 100644 --- a/libsecurity_ocspd/common/ocspExtensions.h +++ b/Security/libsecurity_ocspd/common/ocspExtensions.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_ocspd/common/ocspResponse.cpp b/Security/libsecurity_ocspd/common/ocspResponse.cpp similarity index 99% rename from libsecurity_ocspd/common/ocspResponse.cpp rename to Security/libsecurity_ocspd/common/ocspResponse.cpp index 05ffc186..bce02bc4 100644 --- a/libsecurity_ocspd/common/ocspResponse.cpp +++ b/Security/libsecurity_ocspd/common/ocspResponse.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_ocspd/common/ocspResponse.h b/Security/libsecurity_ocspd/common/ocspResponse.h similarity index 99% rename from libsecurity_ocspd/common/ocspResponse.h rename to Security/libsecurity_ocspd/common/ocspResponse.h index 10918779..5c0de2f6 100644 --- a/libsecurity_ocspd/common/ocspResponse.h +++ b/Security/libsecurity_ocspd/common/ocspResponse.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_ocspd/common/ocspdClient.h b/Security/libsecurity_ocspd/common/ocspdClient.h similarity index 100% rename from libsecurity_ocspd/common/ocspdClient.h rename to Security/libsecurity_ocspd/common/ocspdClient.h diff --git a/libsecurity_ocspd/common/ocspdDbSchema.cpp b/Security/libsecurity_ocspd/common/ocspdDbSchema.cpp similarity index 96% rename from libsecurity_ocspd/common/ocspdDbSchema.cpp rename to Security/libsecurity_ocspd/common/ocspdDbSchema.cpp index 70d6b43b..e6403ee5 100644 --- a/libsecurity_ocspd/common/ocspdDbSchema.cpp +++ b/Security/libsecurity_ocspd/common/ocspdDbSchema.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_ocspd/common/ocspdDbSchema.h b/Security/libsecurity_ocspd/common/ocspdDbSchema.h similarity index 98% rename from libsecurity_ocspd/common/ocspdDbSchema.h rename to Security/libsecurity_ocspd/common/ocspdDbSchema.h index c41dccd0..faca69ec 100644 --- a/libsecurity_ocspd/common/ocspdDbSchema.h +++ b/Security/libsecurity_ocspd/common/ocspdDbSchema.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_ocspd/common/ocspdDebug.h b/Security/libsecurity_ocspd/common/ocspdDebug.h similarity index 97% rename from libsecurity_ocspd/common/ocspdDebug.h rename to Security/libsecurity_ocspd/common/ocspdDebug.h index 2fee2fc3..65f5b6d3 100644 --- a/libsecurity_ocspd/common/ocspdDebug.h +++ b/Security/libsecurity_ocspd/common/ocspdDebug.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_ocspd/common/ocspdTypes.h b/Security/libsecurity_ocspd/common/ocspdTypes.h new file mode 100644 index 00000000..a632da4b --- /dev/null +++ b/Security/libsecurity_ocspd/common/ocspdTypes.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2000,2002,2011,2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _OCSPD_TYPES_H_ +#define _OCSPD_TYPES_H_ + +#include +#include + +/* Explicitly enable MIG type checking per Radar 4735696 */ +#undef __MigTypeCheck +#define __MigTypeCheck 1 + +typedef void *Data; + +/* + * Standard bootstrap name and an env var name to override it with (!NDEBUG only) + */ +#define OCSPD_BOOTSTRAP_NAME "com.apple.ocspd" +#define OCSPD_BOOTSTRAP_ENV "OCSPD_SERVER" + +#endif /* _OCSPD_TYPES_H_ */ diff --git a/libsecurity_ocspd/common/ocspdUtils.cpp b/Security/libsecurity_ocspd/common/ocspdUtils.cpp similarity index 89% rename from libsecurity_ocspd/common/ocspdUtils.cpp rename to Security/libsecurity_ocspd/common/ocspdUtils.cpp index d3280c33..cee4b180 100644 --- a/libsecurity_ocspd/common/ocspdUtils.cpp +++ b/Security/libsecurity_ocspd/common/ocspdUtils.cpp @@ -1,21 +1,22 @@ /* - * Copyright (c) 2002,2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000,2002,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. + * 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. * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * 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 OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. + * 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@ */ diff --git a/Security/libsecurity_ocspd/common/ocspdUtils.h b/Security/libsecurity_ocspd/common/ocspdUtils.h new file mode 100644 index 00000000..57691aca --- /dev/null +++ b/Security/libsecurity_ocspd/common/ocspdUtils.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2000,2002,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * ocspUtils.h - common utilities for OCSPD + */ +#ifndef _OCSPD_UTILS_H_ +#define _OCSPD_UTILS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/* + * Compare two CSSM_DATAs, return CSSM_TRUE if identical. + */ +CSSM_BOOL ocspdCompareCssmData( + const CSSM_DATA *data1, + const CSSM_DATA *data2); + +/* + * Parse a GeneralizedTime string into a CFAbsoluteTime. Returns NULL_TIME on + * parse error. Fractional parts of a second are discarded. + */ +#define NULL_TIME 0.0 + +CFAbsoluteTime genTimeToCFAbsTime( + const CSSM_DATA *strData); + +/* + * Convert CFAbsoluteTime to generalized time string, GMT format (4 digit year, + * trailing 'Z'). Caller allocated the output which is GENERAL_TIME_STRLEN bytes plus + * a NULL. + */ +#define GENERAL_TIME_STRLEN 15 /* NOT including trailing NULL */ + +void cfAbsTimeToGgenTime( + CFAbsoluteTime absTime, + char *genTime); + +#define OCSPD_MAX_DIGEST_LEN CC_SHA256_DIGEST_LENGTH + +void ocspdSha1( + const void *data, + CC_LONG len, + unsigned char *md); // allocd by caller, CC_SHA1_DIGEST_LENGTH bytes +void ocspdMD5( + const void *data, + CC_LONG len, + unsigned char *md); // allocd by caller, CC_MD5_DIGEST_LENGTH bytes +void ocspdMD4( + const void *data, + CC_LONG len, + unsigned char *md); // allocd by caller, CC_MD4_DIGEST_LENGTH bytes +void ocspdSHA256( + const void *data, + CC_LONG len, + unsigned char *md); // allocd by caller, CC_SHA256_DIGEST_LENGTH bytes + +/* + * How many items in a NULL-terminated array of pointers? + */ +unsigned ocspdArraySize( + const void **array); + +#define CFRELEASE(cf) \ + if(cf != NULL) { \ + CFRelease(cf); \ + } + +#ifdef __cplusplus +} +#endif + +#endif /* _OCSPD_UTILS_H_ */ diff --git a/libsecurity_ocspd/libsecurity_ocspd.xcodeproj/project.pbxproj b/Security/libsecurity_ocspd/libsecurity_ocspd.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_ocspd/libsecurity_ocspd.xcodeproj/project.pbxproj rename to Security/libsecurity_ocspd/libsecurity_ocspd.xcodeproj/project.pbxproj diff --git a/Security/libsecurity_ocspd/mig/mig.mk b/Security/libsecurity_ocspd/mig/mig.mk new file mode 100644 index 00000000..ecc3077d --- /dev/null +++ b/Security/libsecurity_ocspd/mig/mig.mk @@ -0,0 +1,47 @@ +# +# Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. +# +# @APPLE_LICENSE_HEADER_START@ +# +# This file contains Original Code and/or Modifications of Original Code +# as defined in and that are subject to the Apple Public Source License +# Version 2.0 (the 'License'). You may not use this file except in +# compliance with the License. Please obtain a copy of the License at +# http://www.opensource.apple.com/apsl/ and read it before using this +# file. +# +# The Original Code and all software distributed under the License are +# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +# Please see the License for the specific language governing rights and +# limitations under the License. +# +# @APPLE_LICENSE_HEADER_END@ +# +# Makefile to build MIG-generated sources and headers +# +DERIVED_SRC = $(BUILT_PRODUCTS_DIR)/derived_src/security_ocspd + +HDRS = $(DERIVED_SRC)/ocspd.h +SRCS = $(DERIVED_SRC)/ocspd_server.cpp $(DERIVED_SRC)/ocspd_client.cpp +SDKROOT := $(shell xcrun --show-sdk-path --sdk macosx.internal) + +build: $(HDRS) $(SRCS) + +install: build + +installhdrs: $(HDRS) + +installsrc: + +clean: + rm -f $(HDRS) $(SRCS) + +$(HDRS) $(SRCS): $(PROJECT_DIR)/mig/ocspd.defs + mkdir -p $(DERIVED_SRC) + xcrun mig -isysroot "$(SDKROOT)" \ + -server $(DERIVED_SRC)/ocspd_server.cpp \ + -user $(DERIVED_SRC)/ocspd_client.cpp \ + -header $(DERIVED_SRC)/ocspd.h $(PROJECT_DIR)/mig/ocspd.defs diff --git a/libsecurity_ocspd/mig/ocspd.defs b/Security/libsecurity_ocspd/mig/ocspd.defs similarity index 100% rename from libsecurity_ocspd/mig/ocspd.defs rename to Security/libsecurity_ocspd/mig/ocspd.defs diff --git a/libsecurity_pkcs12/APPLE_LICENSE b/Security/libsecurity_pkcs12/APPLE_LICENSE similarity index 100% rename from libsecurity_pkcs12/APPLE_LICENSE rename to Security/libsecurity_pkcs12/APPLE_LICENSE diff --git a/libsecurity_pkcs12/Info-security_pkcs12.plist b/Security/libsecurity_pkcs12/Info-security_pkcs12.plist similarity index 100% rename from libsecurity_pkcs12/Info-security_pkcs12.plist rename to Security/libsecurity_pkcs12/Info-security_pkcs12.plist diff --git a/libsecurity_pkcs12/lib/SecPkcs12.cpp b/Security/libsecurity_pkcs12/lib/SecPkcs12.cpp similarity index 99% rename from libsecurity_pkcs12/lib/SecPkcs12.cpp rename to Security/libsecurity_pkcs12/lib/SecPkcs12.cpp index ab4ee729..2d5e02f7 100644 --- a/libsecurity_pkcs12/lib/SecPkcs12.cpp +++ b/Security/libsecurity_pkcs12/lib/SecPkcs12.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_pkcs12/lib/SecPkcs12.h b/Security/libsecurity_pkcs12/lib/SecPkcs12.h similarity index 99% rename from libsecurity_pkcs12/lib/SecPkcs12.h rename to Security/libsecurity_pkcs12/lib/SecPkcs12.h index d0053d10..b9789744 100644 --- a/libsecurity_pkcs12/lib/SecPkcs12.h +++ b/Security/libsecurity_pkcs12/lib/SecPkcs12.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_pkcs12/lib/pkcs12BagAttrs.cpp b/Security/libsecurity_pkcs12/lib/pkcs12BagAttrs.cpp similarity index 98% rename from libsecurity_pkcs12/lib/pkcs12BagAttrs.cpp rename to Security/libsecurity_pkcs12/lib/pkcs12BagAttrs.cpp index 73c5ca72..d3f7a144 100644 --- a/libsecurity_pkcs12/lib/pkcs12BagAttrs.cpp +++ b/Security/libsecurity_pkcs12/lib/pkcs12BagAttrs.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_pkcs12/lib/pkcs12BagAttrs.h b/Security/libsecurity_pkcs12/lib/pkcs12BagAttrs.h similarity index 98% rename from libsecurity_pkcs12/lib/pkcs12BagAttrs.h rename to Security/libsecurity_pkcs12/lib/pkcs12BagAttrs.h index 7a342b03..4feb01a4 100644 --- a/libsecurity_pkcs12/lib/pkcs12BagAttrs.h +++ b/Security/libsecurity_pkcs12/lib/pkcs12BagAttrs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_pkcs12/lib/pkcs12Coder.cpp b/Security/libsecurity_pkcs12/lib/pkcs12Coder.cpp similarity index 99% rename from libsecurity_pkcs12/lib/pkcs12Coder.cpp rename to Security/libsecurity_pkcs12/lib/pkcs12Coder.cpp index 4784e7b3..c1bb44ec 100644 --- a/libsecurity_pkcs12/lib/pkcs12Coder.cpp +++ b/Security/libsecurity_pkcs12/lib/pkcs12Coder.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_pkcs12/lib/pkcs12Coder.h b/Security/libsecurity_pkcs12/lib/pkcs12Coder.h similarity index 99% rename from libsecurity_pkcs12/lib/pkcs12Coder.h rename to Security/libsecurity_pkcs12/lib/pkcs12Coder.h index b0a8177d..d867d110 100644 --- a/libsecurity_pkcs12/lib/pkcs12Coder.h +++ b/Security/libsecurity_pkcs12/lib/pkcs12Coder.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_pkcs12/lib/pkcs12Crypto.cpp b/Security/libsecurity_pkcs12/lib/pkcs12Crypto.cpp similarity index 99% rename from libsecurity_pkcs12/lib/pkcs12Crypto.cpp rename to Security/libsecurity_pkcs12/lib/pkcs12Crypto.cpp index 2bd272fb..64a7c712 100644 --- a/libsecurity_pkcs12/lib/pkcs12Crypto.cpp +++ b/Security/libsecurity_pkcs12/lib/pkcs12Crypto.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_pkcs12/lib/pkcs12Crypto.h b/Security/libsecurity_pkcs12/lib/pkcs12Crypto.h similarity index 98% rename from libsecurity_pkcs12/lib/pkcs12Crypto.h rename to Security/libsecurity_pkcs12/lib/pkcs12Crypto.h index 358c059b..7be51a92 100644 --- a/libsecurity_pkcs12/lib/pkcs12Crypto.h +++ b/Security/libsecurity_pkcs12/lib/pkcs12Crypto.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_pkcs12/lib/pkcs12Debug.h b/Security/libsecurity_pkcs12/lib/pkcs12Debug.h similarity index 96% rename from libsecurity_pkcs12/lib/pkcs12Debug.h rename to Security/libsecurity_pkcs12/lib/pkcs12Debug.h index c538de01..7e0b97cd 100644 --- a/libsecurity_pkcs12/lib/pkcs12Debug.h +++ b/Security/libsecurity_pkcs12/lib/pkcs12Debug.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_pkcs12/lib/pkcs12Decode.cpp b/Security/libsecurity_pkcs12/lib/pkcs12Decode.cpp similarity index 99% rename from libsecurity_pkcs12/lib/pkcs12Decode.cpp rename to Security/libsecurity_pkcs12/lib/pkcs12Decode.cpp index 3d19b636..9e426c1a 100644 --- a/libsecurity_pkcs12/lib/pkcs12Decode.cpp +++ b/Security/libsecurity_pkcs12/lib/pkcs12Decode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_pkcs12/lib/pkcs12Encode.cpp b/Security/libsecurity_pkcs12/lib/pkcs12Encode.cpp similarity index 99% rename from libsecurity_pkcs12/lib/pkcs12Encode.cpp rename to Security/libsecurity_pkcs12/lib/pkcs12Encode.cpp index d99c3998..7ae71623 100644 --- a/libsecurity_pkcs12/lib/pkcs12Encode.cpp +++ b/Security/libsecurity_pkcs12/lib/pkcs12Encode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_pkcs12/lib/pkcs12Keychain.cpp b/Security/libsecurity_pkcs12/lib/pkcs12Keychain.cpp similarity index 99% rename from libsecurity_pkcs12/lib/pkcs12Keychain.cpp rename to Security/libsecurity_pkcs12/lib/pkcs12Keychain.cpp index 5373fc0d..ce7a3b4f 100644 --- a/libsecurity_pkcs12/lib/pkcs12Keychain.cpp +++ b/Security/libsecurity_pkcs12/lib/pkcs12Keychain.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_pkcs12/lib/pkcs12SafeBag.cpp b/Security/libsecurity_pkcs12/lib/pkcs12SafeBag.cpp similarity index 99% rename from libsecurity_pkcs12/lib/pkcs12SafeBag.cpp rename to Security/libsecurity_pkcs12/lib/pkcs12SafeBag.cpp index 4a581311..51de12d2 100644 --- a/libsecurity_pkcs12/lib/pkcs12SafeBag.cpp +++ b/Security/libsecurity_pkcs12/lib/pkcs12SafeBag.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_pkcs12/lib/pkcs12SafeBag.h b/Security/libsecurity_pkcs12/lib/pkcs12SafeBag.h similarity index 99% rename from libsecurity_pkcs12/lib/pkcs12SafeBag.h rename to Security/libsecurity_pkcs12/lib/pkcs12SafeBag.h index 669a13b0..7e5a45fe 100644 --- a/libsecurity_pkcs12/lib/pkcs12SafeBag.h +++ b/Security/libsecurity_pkcs12/lib/pkcs12SafeBag.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_pkcs12/lib/pkcs12Templates.cpp b/Security/libsecurity_pkcs12/lib/pkcs12Templates.cpp similarity index 97% rename from libsecurity_pkcs12/lib/pkcs12Templates.cpp rename to Security/libsecurity_pkcs12/lib/pkcs12Templates.cpp index f5d29517..997dbd68 100644 --- a/libsecurity_pkcs12/lib/pkcs12Templates.cpp +++ b/Security/libsecurity_pkcs12/lib/pkcs12Templates.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -30,6 +30,10 @@ #include #include +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-const-variable" + + const SecAsn1Template NSS_P12_MacDataTemplate[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSS_P12_MacData) }, @@ -286,4 +290,4 @@ const SecAsn1Template NSS_P12_PBE_ParamsTemplate[] = { { 0 } }; - +#pragma clang diagnostic pop diff --git a/Security/libsecurity_pkcs12/lib/pkcs12Templates.h b/Security/libsecurity_pkcs12/lib/pkcs12Templates.h new file mode 100644 index 00000000..4ab54430 --- /dev/null +++ b/Security/libsecurity_pkcs12/lib/pkcs12Templates.h @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * pkcs12Templates.h + * + ******************************************************************* + * + * In a probably vain attempt to clarify the structure of a PKCS12 + * PFX, here is a high-level summary. + * + * The top level item in P12 is a PFX. + * + * PFX = { + * int version; + * ContentInfo authSafe; -- from PKCS7 + * MacData mac; -- optional, password integrity version + * } + * + * The authSafe in a PFX has two legal contentTypes in the P12 + * world, CT_Data (password integrity mode) or CT_SignedData + * (public key integrity mode). The current version of this library + * only supports password integrity mode. Thus the integrity of + * the whole authSafe item is protected by a MAC in the PFX. + * + * The authSafe.content field is a BER-encoded AuthenticatedSafe. + * + * AuthenticatedSafe = { + * SEQUENCE OF ContentInfo; + * } + * + * OK. Each ContentInfo in an AuthenticatedSafe can either be type + * CT_Data, CT_EnvData, or CT_EncryptedData. In the latter cases the + * content is decrypted to produce an encoded SafeContents; in the + * former case the content *is* an encoded SafeContents. + * + * A SafeContents is a sequence of SafeBags. + * + * Each SafeBag can be of several types: + * + * BT_KeyBag + * BT_ShroudedKeyBag + * BT_CertBag + * BT_CrlBag + * BT_SecretBag + * BT_SafeContentsBag + * + */ + +#ifndef _PKCS12_TEMPLATES_H_ +#define _PKCS12_TEMPLATES_H_ + +#include +#include /* for NSS_Attribute */ +#include +#include "pkcs7Templates.h" /* will be lib-specific place */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * MacData ::= SEQUENCE { + * mac DigestInfo, + * macSalt OCTET STRING, + * iterations INTEGER DEFAULT 1 + * } + */ +typedef struct { + NSS_P7_DigestInfo mac; + CSSM_DATA macSalt; + CSSM_DATA iterations; // optional +} NSS_P12_MacData; + +extern const SecAsn1Template NSS_P12_MacDataTemplate[]; + +/* + * PFX ::= SEQUENCE { + * version INTEGER {v3(3)}(v3,...), + * authSafe ContentInfo, + * macData MacData OPTIONAL + * } + */ + +/* + * First the top level PFX with unparsed ContentInfo.content. + */ +typedef struct { + CSSM_DATA version; + NSS_P7_RawContentInfo authSafe; + NSS_P12_MacData *macData; +} NSS_P12_RawPFX; + +extern const SecAsn1Template NSS_P12_RawPFXTemplate[]; + +/* + * And a PFX with a decoded ContentInfo.content. + */ +typedef struct { + CSSM_DATA version; + NSS_P7_DecodedContentInfo authSafe; + NSS_P12_MacData *macData; +} NSS_P12_DecodedPFX; + +extern const SecAsn1Template NSS_P12_DecodedPFXTemplate[]; + +/* + * The CSSMOID_PKCS7_Data-style ContentInfo.content of a PFX + * contains an encoded AuthenticatedSafe. + * + * AuthenticatedSafe ::= SEQUENCE OF ContentInfo + * -- Data if unencrypted + * -- EncryptedData if password-encrypted + * -- EnvelopedData if public key-encrypted + */ +typedef struct { + NSS_P7_DecodedContentInfo **info; +} NSS_P12_AuthenticatedSafe; + +extern const SecAsn1Template NSS_P12_AuthenticatedSafeTemplate[]; + +/* + * Individual BagTypes. + * Code on demand. + */ +typedef CSSM_DATA NSS_P12_KeyBag; +typedef NSS_EncryptedPrivateKeyInfo NSS_P12_ShroudedKeyBag; +typedef CSSM_DATA NSS_P12_SecretBag; +typedef CSSM_DATA NSS_P12_SafeContentsBag; + +/* + * CertBag + * + * CertBag ::= SEQUENCE { + * certId BAG-TYPE.&id ({CertTypes}), + * certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId}) + * } + * + * x509Certificate BAG-TYPE ::= + * {OCTET STRING IDENTIFIED BY {certTypes 1}} + * -- DER-encoded X.509 certificate stored in OCTET STRING + * sdsiCertificate BAG-TYPE ::= + * {IA5String IDENTIFIED BY {certTypes 2}} + * -- Base64-encoded SDSI certificate stored in IA5String + */ +typedef enum { + CT_Unknown, // --> ASN_ANY + CT_X509, + CT_SDSI, +} NSS_P12_CertBagType; + +typedef struct { + CSSM_OID bagType; + NSS_P12_CertBagType type; + CSSM_DATA certValue; +} NSS_P12_CertBag; + +extern const SecAsn1Template NSS_P12_CertBagTemplate[]; + +/* + * CRLBag + * + * CRLBag ::= SEQUENCE { + * certId BAG-TYPE.&id ({CertTypes}), + * certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId}) + * } + * + * x509Certificate BAG-TYPE ::= + * {OCTET STRING IDENTIFIED BY {certTypes 1}} + * -- DER-encoded X.509 certificate stored in OCTET STRING + * sdsiCertificate BAG-TYPE ::= + * {IA5String IDENTIFIED BY {certTypes 2}} + * -- Base64-encoded SDSI certificate stored in IA5String + */ +typedef enum { + CRT_Unknown, // --> ASN_ANY + CRT_X509, +} NSS_P12_CrlBagType; + +typedef struct { + CSSM_OID bagType; + NSS_P12_CrlBagType type; + CSSM_DATA crlValue; +} NSS_P12_CrlBag; + +extern const SecAsn1Template NSS_P12_CrlBagTemplate[]; + +/* + * BagId OIDs map to one of these for convenience. Our dynamic + * template chooser drops one of these into NSS_P12_SafeBag.type + * on decode. + */ +typedef enum { + BT_None = 0, + BT_KeyBag, + BT_ShroudedKeyBag, + BT_CertBag, + BT_CrlBag, + BT_SecretBag, + BT_SafeContentsBag +} NSS_P12_SB_Type; + +/* + * The ContentInfo.content values of each element in + * an AuthenticatedSafe map to a sequence of these - either directly + * (contentType CSSMOID_PKCS7_Data, octet string contents are + * the DER encoding of this) or indirectly (encrypted or + * shrouded, the decrypted content is the DER encoding of this). + */ +typedef struct { + CSSM_OID bagId; + NSS_P12_SB_Type type; + union { + NSS_P12_KeyBag *keyBag; + NSS_P12_ShroudedKeyBag *shroudedKeyBag; + NSS_P12_CertBag *certBag; + NSS_P12_CrlBag *crlBag; + NSS_P12_SecretBag *secretBag; + NSS_P12_SafeContentsBag *safeContentsBag; + } bagValue; + NSS_Attribute **bagAttrs; // optional +} NSS_P12_SafeBag; + +extern const SecAsn1Template NSS_P12_SafeBagTemplate[]; + +/* + * SafeContents, the contents of an element in an AuthenticatedSafe. + */ +typedef struct { + NSS_P12_SafeBag **bags; +} +NSS_P12_SafeContents; + +extern const SecAsn1Template NSS_P12_SafeContentsTemplate[]; + +/* + * PKCS12-specific algorithm parameters. + * A DER encoded version of this is the parameters value of + * a CSSM_X509_ALGORITHM_IDENTIFIER used in a + * NSS_P7_EncrContentInfo.encrAlg in P12 password privacy mode. + * + * pkcs-12PbeParams ::= SEQUENCE { + * salt OCTET STRING, + * iterations INTEGER + * } + * + * NOTE the P12 spec does place a limit on the value of iterations. + * I guess we have to assume in actual usage that it's + * restricted to (0..MAX), i.e., uint32-sized. + * + * We're also assuming that it is explicitly an unsigned value, + * so that the value bytes in the encoding of 0xff would be + * (0, 255). + */ +typedef struct { + CSSM_DATA salt; + CSSM_DATA iterations; +} NSS_P12_PBE_Params; + +extern const SecAsn1Template NSS_P12_PBE_ParamsTemplate[]; + +#ifdef __cplusplus +} +#endif + +#endif /* _PKCS12_TEMPLATES_H_ */ + diff --git a/Security/libsecurity_pkcs12/lib/pkcs12Utils.cpp b/Security/libsecurity_pkcs12/lib/pkcs12Utils.cpp new file mode 100644 index 00000000..7ad4593c --- /dev/null +++ b/Security/libsecurity_pkcs12/lib/pkcs12Utils.cpp @@ -0,0 +1,832 @@ +/* + * Copyright (c) 2003-2004,2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * pkcs12Utils.cpp + */ + +#include "pkcs12Utils.h" +#include +#include "pkcs7Templates.h" +#include "pkcs12Templates.h" +#include "pkcs12Crypto.h" +#include "pkcs12Debug.h" +#include +#include +#include +#include +#include +#include +#include +#include + +/* malloc a NULL-ed array of pointers of size num+1 */ +void **p12NssNullArray( + uint32 num, + SecNssCoder &coder) +{ + unsigned len = (num + 1) * sizeof(void *); + void **p = (void **)coder.malloc(len); + memset(p, 0, len); + return p; +} + +/* CSSM_DATA --> uint32. Returns true if OK. */ +bool p12DataToInt( + const CSSM_DATA &cdata, + uint32 &u) +{ + if((cdata.Length == 0) || (cdata.Data == NULL)) { + /* default/not present */ + u = 0; + return true; + } + CSSM_SIZE len = cdata.Length; + if(len > sizeof(uint32)) { + return false; + } + + uint32 rtn = 0; + uint8 *cp = cdata.Data; + for(uint32 i=0; i CSSM_DATA */ +void p12IntToData( + uint32 num, + CSSM_DATA &cdata, + SecNssCoder &coder) +{ + uint32 len = 0; + + if(num < 0x100) { + len = 1; + } + else if(num < 0x10000) { + len = 2; + } + else if(num < 0x1000000) { + len = 3; + } + else { + len = 4; + } + coder.allocItem(cdata, len); + uint8 *cp = &cdata.Data[len - 1]; + for(unsigned i=0; i>= 8; + } +} + +/* CFDataRef <--> CSSM_DATA */ +CFDataRef p12CssmDataToCf( + const CSSM_DATA &c) +{ + return CFDataCreate(NULL, c.Data, c.Length); +} + +void p12CfDataToCssm( + CFDataRef cf, + CSSM_DATA &c, + SecNssCoder &coder) +{ + coder.allocCopyItem(CFDataGetBytePtr(cf), + CFDataGetLength(cf), c); +} + +/* + * Attempt to convert a CFStringRef, which represents a SafeBag's + * FriendlyName, to a UTF8-encoded CSSM_DATA. The CSSM_DATA and its + * referent are allocated in the specified SecNssCoder's memory. + * No guarantee that this conversion works. If it doesn't we return + * NULL and caller must be prepared to deal with that. + */ +CSSM_DATA_PTR p12StringToUtf8( + CFStringRef cfStr, + SecNssCoder &coder) +{ + if(cfStr == NULL) { + return NULL; + } + CFIndex strLen = CFStringGetLength(cfStr); + if(strLen == 0) { + return NULL; + } + CSSM_DATA_PTR rtn = coder.mallocn(); + coder.allocItem(*rtn, strLen + 1); + if(!CFStringGetCString(cfStr, (char *)rtn->Data,strLen + 1, + kCFStringEncodingUTF8)) { + /* not convertible from native Unicode to UTF8 */ + return NULL; + } + return rtn; +} + +/* + * Enum to string mappper. + * Maybe DEBUG only. + */ +/* + * Each type of attribute has a name/value pair in a table of these: + */ +typedef struct { + unsigned value; + const char *name; +} p12NameValuePair; + +/* declare one entry in a table of p12NameValuePair */ +#define NVP(attr) {attr, #attr} + +/* the NULL entry which terminates all p12NameValuePair tables */ +#define NVP_END {0, NULL} + +static const p12NameValuePair p7CITypeNames[] = +{ + NVP(CT_None), + NVP(CT_Data), + NVP(CT_SignedData), + NVP(CT_EnvData), + NVP(CT_SignedEnvData), + NVP(CT_DigestData), + NVP(CT_EncryptedData), + NVP_END +}; + +static const p12NameValuePair p12BagTypeNames[] = +{ + NVP(BT_None), + NVP(BT_KeyBag), + NVP(BT_ShroudedKeyBag), + NVP(BT_CertBag), + NVP(BT_CrlBag), + NVP(BT_SecretBag), + NVP(BT_SafeContentsBag), + NVP_END +}; + +static const char *typeToStr( + unsigned type, + const p12NameValuePair *table) +{ + while(table->name) { + if(table->value == type) { + return table->name; + } + table++; + } + return "Unknown"; +} + +const char *p12BagTypeStr( + NSS_P12_SB_Type type) +{ + return typeToStr(type, p12BagTypeNames); +} + +const char *p7ContentInfoTypeStr( + NSS_P7_CI_Type type) +{ + return typeToStr(type, p7CITypeNames); +} + +/* + * OIDS for P12 and PKCS5 v1.5 (PBES1) encrypt and decrypt map to the following + * attributes. + */ +typedef struct { + const CSSM_OID *oid; + CSSM_ALGORITHMS keyAlg; // e.g., CSSM_ALGID_DES + CSSM_ALGORITHMS encrAlg; // e.g., CSSM_ALGID_3DES_3KEY_EDE + CSSM_ALGORITHMS pbeHashAlg; // SHA1 or MD5 + uint32 keySizeInBits; + uint32 blockSizeInBytes; // for IV, optional + CSSM_PADDING padding; // CSSM_PADDING_PKCS7, etc. + CSSM_ENCRYPT_MODE mode; // CSSM_ALGMODE_CBCPadIV8, etc. + PKCS_Which pkcs; // PW_PKCS12 (for this module) or PW_PKCS5_v1_5 +} PKCSOidInfo; + +static const PKCSOidInfo pkcsOidInfos[] = { + /* PKCS12 first, the ones this module uses */ + { + &CSSMOID_PKCS12_pbeWithSHAAnd128BitRC4, + CSSM_ALGID_RC4, + CSSM_ALGID_RC4, + CSSM_ALGID_SHA1, + 128, + 0, // RC4 is a stream cipher + CSSM_PADDING_NONE, + CSSM_ALGMODE_NONE, + PW_PKCS12 + }, + { + &CSSMOID_PKCS12_pbeWithSHAAnd40BitRC4, + CSSM_ALGID_RC4, + CSSM_ALGID_RC4, + CSSM_ALGID_SHA1, + 40, + 0, // RC4 is a stream cipher + CSSM_PADDING_NONE, + CSSM_ALGMODE_NONE, + PW_PKCS12 + }, + { + &CSSMOID_PKCS12_pbeWithSHAAnd3Key3DESCBC, + CSSM_ALGID_3DES_3KEY, + CSSM_ALGID_3DES_3KEY_EDE, + CSSM_ALGID_SHA1, + 64 * 3, + 8, + CSSM_PADDING_PKCS7, + CSSM_ALGMODE_CBCPadIV8, + PW_PKCS12 + }, + { + &CSSMOID_PKCS12_pbeWithSHAAnd2Key3DESCBC, + CSSM_ALGID_3DES_2KEY, + CSSM_ALGID_3DES_2KEY_EDE, + CSSM_ALGID_SHA1, + 64 * 2, + 8, + CSSM_PADDING_PKCS7, + CSSM_ALGMODE_CBCPadIV8, + PW_PKCS12 + }, + { + &CSSMOID_PKCS12_pbeWithSHAAnd128BitRC2CBC, + CSSM_ALGID_RC2, + CSSM_ALGID_RC2, + CSSM_ALGID_SHA1, + 128, + 8, + CSSM_PADDING_PKCS7, + CSSM_ALGMODE_CBCPadIV8, + PW_PKCS12 + }, + { + &CSSMOID_PKCS12_pbewithSHAAnd40BitRC2CBC, + CSSM_ALGID_RC2, + CSSM_ALGID_RC2, + CSSM_ALGID_SHA1, + 40, + 8, + CSSM_PADDING_PKCS7, + CSSM_ALGMODE_CBCPadIV8, + PW_PKCS12 + }, + + /* PKCS5 v1.5, used for SecImportExport module */ + { + &CSSMOID_PKCS5_pbeWithMD2AndDES, + CSSM_ALGID_DES, + CSSM_ALGID_DES, + CSSM_ALGID_MD2, + 64, + 8, + CSSM_PADDING_PKCS7, + CSSM_ALGMODE_CBCPadIV8, + PW_PKCS5_v1_5 + }, + { + &CSSMOID_PKCS5_pbeWithMD2AndRC2, + CSSM_ALGID_RC2, + CSSM_ALGID_RC2, + CSSM_ALGID_MD2, + 64, + 8, + CSSM_PADDING_PKCS7, + CSSM_ALGMODE_CBCPadIV8, + PW_PKCS5_v1_5 + }, + { + &CSSMOID_PKCS5_pbeWithMD5AndDES, + CSSM_ALGID_DES, + CSSM_ALGID_DES, + CSSM_ALGID_MD5, + 64, + 8, + CSSM_PADDING_PKCS7, + CSSM_ALGMODE_CBCPadIV8, + PW_PKCS5_v1_5 + }, + { + &CSSMOID_PKCS5_pbeWithMD5AndRC2, + CSSM_ALGID_RC2, + CSSM_ALGID_RC2, + CSSM_ALGID_MD5, + 64, + 8, + CSSM_PADDING_PKCS7, + CSSM_ALGMODE_CBCPadIV8, + PW_PKCS5_v1_5 + }, + { + &CSSMOID_PKCS5_pbeWithSHA1AndDES, + CSSM_ALGID_DES, + CSSM_ALGID_DES, + CSSM_ALGID_SHA1, + 64, + 8, + CSSM_PADDING_PKCS7, + CSSM_ALGMODE_CBCPadIV8, + PW_PKCS5_v1_5 + }, + { + &CSSMOID_PKCS5_pbeWithSHA1AndRC2, + CSSM_ALGID_RC2, + CSSM_ALGID_RC2, + CSSM_ALGID_SHA1, + 64, + 8, + CSSM_PADDING_PKCS7, + CSSM_ALGMODE_CBCPadIV8, + PW_PKCS5_v1_5 + }, + + /* finally one for PKCS5 v2.0, which has its own means of + * cooking up all the parameters */ + { + &CSSMOID_PKCS5_PBES2, + CSSM_ALGID_NONE, + CSSM_ALGID_NONE, + CSSM_ALGID_NONE, + 0, 0, 0, 0, + PW_PKCS5_v2 + } +}; + +#define NUM_PKCS_OID_INFOS (sizeof(pkcsOidInfos) / sizeof(pkcsOidInfos[1])) + +/* map an OID to the components */ +/* returns false if OID not found */ + +/* + * NOTE: as of March 8 2004 this is also used by the SecImportExport + * module...not just PKCS12! + */ +bool pkcsOidToParams( + const CSSM_OID *oid, + CSSM_ALGORITHMS &keyAlg, // e.g., CSSM_ALGID_DES + CSSM_ALGORITHMS &encrAlg, // e.g., CSSM_ALGID_3DES_3KEY_EDE + CSSM_ALGORITHMS &pbeHashAlg, // SHA1 or MD5 + uint32 &keySizeInBits, + uint32 &blockSizeInBytes, // for IV, optional + CSSM_PADDING &padding, // CSSM_PADDING_PKCS7, etc. + CSSM_ENCRYPT_MODE &mode, // CSSM_ALGMODE_CBCPadIV8, etc. + PKCS_Which &pkcs) // PW_PKCS5_v1_5 or PW_PKCS12 +{ + const PKCSOidInfo *info = pkcsOidInfos; + pkcs = PW_None; + + for(unsigned dex=0; dexoid)) { + keyAlg = info->keyAlg; + encrAlg = info->encrAlg; + pbeHashAlg = info->pbeHashAlg; + keySizeInBits = info->keySizeInBits; + blockSizeInBytes = info->blockSizeInBytes; + padding = info->padding; + mode = info->mode; + pkcs = info->pkcs; + return true; + } + info++; + } + return false; +} + +/* + * Verify MAC on an existing PFX. + */ +CSSM_RETURN p12VerifyMac( + const NSS_P12_DecodedPFX &pfx, + CSSM_CSP_HANDLE cspHand, + const CSSM_DATA *pwd, // unicode, double null terminated + const CSSM_KEY *passKey, + SecNssCoder &coder) // for temp mallocs +{ + if(pfx.macData == NULL) { + return CSSMERR_CSP_INVALID_SIGNATURE; + } + NSS_P12_MacData &macData = *pfx.macData; + NSS_P7_DigestInfo &digestInfo = macData.mac; + CSSM_OID &algOid = digestInfo.digestAlgorithm.algorithm; + CSSM_ALGORITHMS macAlg; + if(!cssmOidToAlg(&algOid, &macAlg)) { + return CSSMERR_CSP_INVALID_ALGORITHM; + } + uint32 iterCount = 0; + CSSM_DATA &citer = macData.iterations; + if(!p12DataToInt(citer, iterCount)) { + return CSSMERR_CSP_INVALID_ATTR_ROUNDS; + } + if(iterCount == 0) { + /* optional, default 1 */ + iterCount = 1; + } + + /* + * In classic fashion, the PKCS12 spec now says: + * + * When password integrity mode is used to secure a PFX PDU, + * an SHA-1 HMAC is computed on the BER-encoding of the contents + * of the content field of the authSafe field in the PFX PDU. + * + * So here we go. + */ + CSSM_DATA genMac; + CSSM_RETURN crtn = p12GenMac(cspHand, *pfx.authSafe.content.data, + macAlg, iterCount, macData.macSalt, pwd, passKey, coder, genMac); + if(crtn) { + return crtn; + } + if(nssCompareCssmData(&genMac, &digestInfo.digest)) { + return CSSM_OK; + } + else { + return CSSMERR_CSP_VERIFY_FAILED; + } +} + +/* we generate 8 random bytes of salt */ +#define P12_SALT_LEN 8 + +void p12GenSalt( + CSSM_DATA &salt, + SecNssCoder &coder) +{ + DevRandomGenerator rng; + coder.allocItem(salt, P12_SALT_LEN); + rng.random(salt.Data, P12_SALT_LEN); +} + +/* + * Generate random label string to allow associating an imported private + * key with a cert. + */ +void p12GenLabel( + CSSM_DATA &label, + SecNssCoder &coder) +{ + /* first a random uint32 */ + uint8 d[4]; + DevRandomGenerator rng; + rng.random(d, 4); + CSSM_DATA cd = {4, d}; + uint32 i; + p12DataToInt(cd, i); + + /* sprintf that into a real string */ + coder.allocItem(label, 9); + memset(label.Data, 0, 9); + sprintf((char *)label.Data, "%08X", (unsigned)i); +} + +/* NULL algorithm parameters */ + +static const uint8 nullAlg[2] = {SEC_ASN1_NULL, 0}; + +void p12NullAlgParams( + CSSM_X509_ALGORITHM_IDENTIFIER &algId) +{ + CSSM_DATA &p = algId.parameters; + p.Data = (uint8 *)nullAlg; + p.Length = 2; +} + +/* + * Free memory via specified plugin's app-level allocator + */ +void freeCssmMemory( + CSSM_HANDLE hand, + void *p) +{ + CSSM_API_MEMORY_FUNCS memFuncs; + CSSM_RETURN crtn = CSSM_GetAPIMemoryFunctions(hand, &memFuncs); + if(crtn) { + p12LogCssmError("CSSM_GetAPIMemoryFunctions", crtn); + /* oh well, leak and continue */ + return; + } + memFuncs.free_func(p, memFuncs.AllocRef); +} + +/* + * Find private key by label, modify its Label attr to be the + * hash of the associated public key. + * Also optionally re-sets the key's PrintName attribute; used to reset + * this attr from the random label we create when first unwrap it + * to the friendly name we find later after parsing attributes. + * Detection of a duplicate key when updating the key's attributes + * results in a lookup of the original key and returning it in + * foundKey. + */ +CSSM_RETURN p12SetPubKeyHash( + CSSM_CSP_HANDLE cspHand, // where the key lives + CSSM_DL_DB_HANDLE dlDbHand, // ditto + CSSM_DATA &keyLabel, // for DB lookup + CSSM_DATA_PTR newPrintName, // optional + SecNssCoder &coder, // for mallocing newLabel + CSSM_DATA &newLabel, // RETURNED with label as hash + CSSM_KEY_PTR &foundKey) // RETURNED +{ + CSSM_QUERY query; + CSSM_SELECTION_PREDICATE predicate; + CSSM_DB_UNIQUE_RECORD_PTR record = NULL; + CSSM_RETURN crtn; + CSSM_HANDLE resultHand = 0; + CSSM_DATA keyData = {0, NULL}; + CSSM_CC_HANDLE ccHand = 0; + CSSM_KEY_PTR privKey = NULL; + CSSM_DATA_PTR keyDigest = NULL; + + assert(cspHand != 0); + query.RecordType = CSSM_DL_DB_RECORD_PRIVATE_KEY; + query.Conjunctive = CSSM_DB_NONE; + query.NumSelectionPredicates = 1; + predicate.DbOperator = CSSM_DB_EQUAL; + + predicate.Attribute.Info.AttributeNameFormat = + CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + predicate.Attribute.Info.Label.AttributeName = + (char*) P12_KEY_ATTR_LABEL_AND_HASH; + predicate.Attribute.Info.AttributeFormat = + CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + /* hope this cast is OK */ + predicate.Attribute.Value = &keyLabel; + query.SelectionPredicate = &predicate; + + query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? + query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? + query.QueryFlags = CSSM_QUERY_RETURN_DATA; + + /* build Record attribute with one or two attrs */ + CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; + CSSM_DB_ATTRIBUTE_DATA attr[2]; + attr[0].Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr[0].Info.Label.AttributeName = (char*) P12_KEY_ATTR_LABEL_AND_HASH; + attr[0].Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + if(newPrintName) { + attr[1].Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr[1].Info.Label.AttributeName = (char*) P12_KEY_ATTR_PRINT_NAME; + attr[1].Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + } + recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_PRIVATE_KEY; + recordAttrs.NumberOfAttributes = newPrintName ? 2 : 1; + recordAttrs.AttributeData = attr; + + crtn = CSSM_DL_DataGetFirst(dlDbHand, + &query, + &resultHand, + &recordAttrs, + &keyData, // theData + &record); + /* abort only on success */ + if(crtn != CSSM_OK) { + p12LogCssmError("CSSM_DL_DataGetFirst", crtn); + p12ErrorLog("***p12SetPubKeyHash: can't find private key\n"); + return crtn; + } + /* subsequent errors to errOut: */ + if(keyData.Data == NULL) { + p12ErrorLog("***p12SetPubKeyHash: private key lookup failure\n"); + crtn = CSSMERR_CSSM_INTERNAL_ERROR; + goto errOut; + } + privKey = (CSSM_KEY_PTR)keyData.Data; + + /* public key hash via passthrough - works on any key, any CSP/CSPDL.... */ + /* + * Warning! This relies on the current default ACL meaning "allow this + * current app to access this private key" since we created the key. + */ + crtn = CSSM_CSP_CreatePassThroughContext(cspHand, privKey, &ccHand); + if(crtn) { + p12LogCssmError("CSSM_CSP_CreatePassThroughContext", crtn); + goto errOut; + } + crtn = CSSM_CSP_PassThrough(ccHand, + CSSM_APPLECSP_KEYDIGEST, + NULL, + (void **)&keyDigest); + if(crtn) { + p12LogCssmError("CSSM_CSP_PassThrough", crtn); + goto errOut; + } + + /* + * Replace Label attr data with hash. + * NOTE: the module which allocated this attribute data - a DL - + * was loaded and attached by out client layer, not by us. Thus + * we can't use the memory allocator functions *we* used when + * attaching to the CSP - we have to use the ones + * which the client registered with the DL. + */ + freeCssmMemory(dlDbHand.DLHandle, attr[0].Value->Data); + freeCssmMemory(dlDbHand.DLHandle, attr[0].Value); + if(newPrintName) { + freeCssmMemory(dlDbHand.DLHandle, attr[1].Value->Data); + freeCssmMemory(dlDbHand.DLHandle, attr[1].Value); + } + /* modify key attributes */ + attr[0].Value = keyDigest; + if(newPrintName) { + attr[1].Value = newPrintName; + } + crtn = CSSM_DL_DataModify(dlDbHand, + CSSM_DL_DB_RECORD_PRIVATE_KEY, + record, + &recordAttrs, + NULL, // DataToBeModified + CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + switch(crtn) { + case CSSM_OK: + /* give caller the key's new label */ + coder.allocCopyItem(*keyDigest, newLabel); + break; + default: + p12LogCssmError("CSSM_DL_DataModify", crtn); + break; + case CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA: + { + /* + * Special case: dup private key. The label we just tried to modify is + * the public key hash so we can be confident that this really is a dup. + * Delete it, look up the original, and return the original to caller. + */ + CSSM_RETURN drtn = CSSM_DL_DataDelete(dlDbHand, record); + if(drtn) { + p12LogCssmError("CSSM_DL_DataDelete on dup key", drtn); + crtn = drtn; + break; + } + + /* Free items created in last search */ + CSSM_DL_DataAbortQuery(dlDbHand, resultHand); + resultHand = 0; + CSSM_DL_FreeUniqueRecord(dlDbHand, record); + record = NULL; + + /* lookup by label as public key hash this time */ + predicate.Attribute.Value = keyDigest; + drtn = CSSM_DL_DataGetFirst(dlDbHand, + &query, + &resultHand, + NULL, // no attrs this time + &keyData, + &record); + if(drtn) { + p12LogCssmError("CSSM_DL_DataGetFirst on original key", crtn); + crtn = drtn; + break; + } + foundKey = (CSSM_KEY_PTR)keyData.Data; + /* give caller the key's actual label */ + coder.allocCopyItem(*keyDigest, newLabel); + break; + } + } + +errOut: + /* free resources */ + if(resultHand) { + CSSM_DL_DataAbortQuery(dlDbHand, resultHand); + } + if(record) { + CSSM_DL_FreeUniqueRecord(dlDbHand, record); + } + if(ccHand) { + CSSM_DeleteContext(ccHand); + } + if(privKey) { + /* key created by the CSPDL */ + CSSM_FreeKey(cspHand, NULL, privKey, CSSM_FALSE); + freeCssmMemory(dlDbHand.DLHandle, privKey); + } + if(keyDigest) { + /* mallocd by someone else's CSP */ + freeCssmMemory(cspHand, keyDigest->Data); + freeCssmMemory(cspHand, keyDigest); + } + return crtn; +} + +/* + * Given a context specified via a CSSM_CC_HANDLE, add a new + * CSSM_CONTEXT_ATTRIBUTE to the context as specified by AttributeType, + * AttributeLength, and an untyped pointer. + */ +CSSM_RETURN p12AddContextAttribute(CSSM_CC_HANDLE CCHandle, + uint32 AttributeType, + uint32 AttributeLength, + const void *AttributePtr) +{ + CSSM_CONTEXT_ATTRIBUTE newAttr; + CSSM_RETURN crtn; + + newAttr.AttributeType = AttributeType; + newAttr.AttributeLength = AttributeLength; + newAttr.Attribute.Data = (CSSM_DATA_PTR)AttributePtr; + crtn = CSSM_UpdateContextAttributes(CCHandle, 1, &newAttr); + if(crtn) { + p12LogCssmError("CSSM_UpdateContextAttributes", crtn); + } + return crtn; +} + +/* + * Find private key by specified label, delete it. + */ +CSSM_RETURN p12DeleteKey( + CSSM_DL_DB_HANDLE dlDbHand, + const CSSM_DATA &keyLabel) +{ + CSSM_QUERY query; + CSSM_SELECTION_PREDICATE predicate; + CSSM_DB_UNIQUE_RECORD_PTR record = NULL; + CSSM_RETURN crtn; + CSSM_HANDLE resultHand = 0; + + query.RecordType = CSSM_DL_DB_RECORD_PRIVATE_KEY; + query.Conjunctive = CSSM_DB_NONE; + query.NumSelectionPredicates = 1; + predicate.DbOperator = CSSM_DB_EQUAL; + + predicate.Attribute.Info.AttributeNameFormat = + CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + predicate.Attribute.Info.Label.AttributeName = + (char*) P12_KEY_ATTR_LABEL_AND_HASH; + predicate.Attribute.Info.AttributeFormat = + CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + predicate.Attribute.Value = const_cast(&keyLabel); + + query.SelectionPredicate = &predicate; + query.QueryLimits.TimeLimit = 0; + query.QueryLimits.SizeLimit = 1; + query.QueryFlags = 0; + + crtn = CSSM_DL_DataGetFirst(dlDbHand, + &query, + &resultHand, + NULL, // attrs - don't need 'em + NULL, // theData - don't need it + &record); + /* abort only on success */ + if(crtn) { + p12LogCssmError("CSSM_DL_DataGetFirst", crtn); + p12ErrorLog("***p12DeleteKey: can't find private key\n"); + return crtn; + } + + crtn = CSSM_DL_DataDelete(dlDbHand, record); + if(crtn) { + p12LogCssmError("CSSM_DL_DataDelete", crtn); + p12ErrorLog("***p12DeleteKey: can't delete private key\n"); + } + + CSSM_DL_DataAbortQuery(dlDbHand, resultHand); + CSSM_DL_FreeUniqueRecord(dlDbHand, record); + return crtn; +} + +/* convert App passphrase to array of chars used in P12 PBE */ +void p12ImportPassPhrase( + CFStringRef inPhrase, + SecNssCoder &coder, + CSSM_DATA &outPhrase) +{ + CFDataRef cfData = CFStringCreateExternalRepresentation(NULL, + inPhrase, kCFStringEncodingUTF8, 0); + if(cfData == NULL) { + p12ErrorLog("***p12ImportPassPhrase: can't convert passphrase to UTF8\n"); + MacOSError::throwMe(errSecParam); + } + CFIndex keyLen = CFDataGetLength(cfData); + coder.allocItem(outPhrase, keyLen); + memmove(outPhrase.Data, CFDataGetBytePtr(cfData), keyLen); + CFRelease(cfData); +} diff --git a/Security/libsecurity_pkcs12/lib/pkcs12Utils.h b/Security/libsecurity_pkcs12/lib/pkcs12Utils.h new file mode 100644 index 00000000..e39ebc3e --- /dev/null +++ b/Security/libsecurity_pkcs12/lib/pkcs12Utils.h @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2003-2004,2011,2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * pkcs12Utils.h + */ + +#ifndef _PKCS12_UTILS_H_ +#define _PKCS12_UTILS_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* malloc a NULL-ed array of pointers of size num+1 */ +void **p12NssNullArray( + uint32 num, + SecNssCoder &coder); + +/* CSSM_DATA --> uint32. Returns true if OK. */ +bool p12DataToInt( + const CSSM_DATA &cdata, + uint32 &u); + +/* uint32 --> CSSM_DATA */ +void p12IntToData( + uint32 num, + CSSM_DATA &cdata, + SecNssCoder &coder); + +/* CFDataRef <--> CSSM_DATA */ +CFDataRef p12CssmDataToCf( + const CSSM_DATA &c); +void p12CfDataToCssm( + CFDataRef cf, + CSSM_DATA &c, + SecNssCoder &coder); + +CSSM_DATA_PTR p12StringToUtf8( + CFStringRef cfStr, + SecNssCoder &coder); + +const char *p12BagTypeStr( + NSS_P12_SB_Type type); +const char *p7ContentInfoTypeStr( + NSS_P7_CI_Type type); + +/* map an OID to the components */ + +typedef enum { + PW_None, /* not comprehended */ + PW_PKCS5_v1_5, /* PKCS5 v1.5 */ + PW_PKCS5_v2, /* PKCS5 v2.0, not used by this module but parsed here */ + PW_PKCS12 /* PKCS12 */ +} PKCS_Which; + +/* returns false if OID not found */ +bool pkcsOidToParams( + const CSSM_OID *oid, + CSSM_ALGORITHMS &keyAlg, // e.g., CSSM_ALGID_DES + CSSM_ALGORITHMS &encrAlg, // e.g., CSSM_ALGID_3DES_3KEY_EDE + CSSM_ALGORITHMS &pbeHashAlg, // SHA1 or MD5 + uint32 &keySizeInBits, + uint32 &blockSizeInBytes, // for IV, optional + CSSM_PADDING &padding, // CSSM_PADDING_PKCS7, etc. + CSSM_ENCRYPT_MODE &mode, // CSSM_ALGMODE_CBCPadIV8, etc. + PKCS_Which &pkcs); // PW_PKCS5_v1_5 or PW_PKCS12 + +CSSM_RETURN p12VerifyMac( + const NSS_P12_DecodedPFX &pfx, + CSSM_CSP_HANDLE cspHand, + const CSSM_DATA *pwd, // unicode, double null terminated + const CSSM_KEY *passKey, + SecNssCoder &coder);// for temp mallocs + +void p12GenSalt( + CSSM_DATA &salt, + SecNssCoder &coder); + +void p12GenLabel( + CSSM_DATA &label, + SecNssCoder &coder); + +void p12NullAlgParams( + CSSM_X509_ALGORITHM_IDENTIFIER &algId); + +/* + * Free memory via specified plugin's app-level allocator + */ +void freeCssmMemory( + CSSM_HANDLE hand, + void *p); + +/* + * Though it pains me to do this, I must. We "happen to know" the + * names (in string form) of two of a key's attributes. These + * have not been published anywhere, they are hard-coded into + * the script (KeySchema.m4) which generates the KeySchema + * tables. + */ + +/* + * This one is initially the same as the "label" argument passed + * in to the CSP when creating or importing keys; it eventually + * gets munged into the hash of the associated public key ( + * in our case, by p12SetPubKeyHash()). + */ +#define P12_KEY_ATTR_LABEL_AND_HASH "Label" + +/* + * This one is the user-friendly name. + */ +#define P12_KEY_ATTR_PRINT_NAME "PrintName" + +/* + * Find private key by label, modify its Label attr to be the + * hash of the associated public key. + */ +CSSM_RETURN p12SetPubKeyHash( + CSSM_CSP_HANDLE cspHand, // where the key lives + CSSM_DL_DB_HANDLE dlDbHand, // ditto + CSSM_DATA &keyLabel, // for DB lookup + CSSM_DATA_PTR newPrintName, // optional + SecNssCoder &coder, // for mallocing newLabel + CSSM_DATA &newLabel, // RETURNED with label as hash + CSSM_KEY_PTR &foundKey); // RETURNED on dup key detect + +CSSM_RETURN p12AddContextAttribute(CSSM_CC_HANDLE CCHandle, + uint32 AttributeType, + uint32 AttributeLength, + const void *AttributePtr); + +/* + * Find private key by specified label, delete it. + */ +CSSM_RETURN p12DeleteKey( + CSSM_DL_DB_HANDLE dlDbHand, + const CSSM_DATA &keyLabel); + +/* convert App passphrase to array of chars used in P12 PBE */ +void p12ImportPassPhrase( + CFStringRef inPhrase, + SecNssCoder &coder, + CSSM_DATA &outPhrase); + +/* + * Standard error throwMes. + * P12_ENCODE_ERR only occurs on DER-encode which should never fail. + */ +#define P12_DECODE_ERR errSecUnknownFormat +#define P12_ENCODE_ERR errSecInternalComponent +#define P12_THROW_DECODE MacOSError::throwMe(P12_DECODE_ERR) +#define P12_THROW_ENCODE MacOSError::throwMe(P12_ENCODE_ERR) + +#ifdef __cplusplus +} +#endif + +#endif /* _PKCS12_UTILS_H_ */ + diff --git a/libsecurity_pkcs12/lib/pkcs7Templates.cpp b/Security/libsecurity_pkcs12/lib/pkcs7Templates.cpp similarity index 98% rename from libsecurity_pkcs12/lib/pkcs7Templates.cpp rename to Security/libsecurity_pkcs12/lib/pkcs7Templates.cpp index 683fd3d9..d2ffa5c9 100644 --- a/libsecurity_pkcs12/lib/pkcs7Templates.cpp +++ b/Security/libsecurity_pkcs12/lib/pkcs7Templates.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_pkcs12/lib/pkcs7Templates.h b/Security/libsecurity_pkcs12/lib/pkcs7Templates.h new file mode 100644 index 00000000..8abdcf8b --- /dev/null +++ b/Security/libsecurity_pkcs12/lib/pkcs7Templates.h @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * pkcs7Templates.h + */ + +#ifndef _PKCS7_TEMPLATES_H_ +#define _PKCS7_TEMPLATES_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest + * } + * + * Digest ::= OCTET STRING + */ +typedef struct { + CSSM_X509_ALGORITHM_IDENTIFIER digestAlgorithm; + CSSM_DATA digest; +} NSS_P7_DigestInfo; + +extern const SecAsn1Template NSS_P7_DigestInfoTemplate[]; + +/* + * Uninterpreted ContentInfo, with content stripped from its + * EXPLICIT CONTEXT_SPECIFIC wrapper + * + * ContentInfo ::= SEQUENCE { + * contentType ContentType, + * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL + * } + */ +typedef struct { + CSSM_OID contentType; + CSSM_DATA content; +} NSS_P7_RawContentInfo; + +extern const SecAsn1Template NSS_P7_RawContentInfoTemplate[]; + +#pragma mark ---- ContentInfo.content types ----- + +/* + * Expand beyond ASN_ANY/CSSM_DATA as needed + */ +typedef CSSM_DATA NSS_P7_SignedData; +typedef CSSM_DATA NSS_P7_EnvelData; +typedef CSSM_DATA NSS_P7_SignEnvelData; +typedef CSSM_DATA NSS_P7_DigestedData; + +/* EncryptedData */ + +/* + * EncryptedContentInfo ::= SEQUENCE { + * contentType ContentType, + * contentEncryptionAlgorithm + * ContentEncryptionAlgorithmIdentifier, + * encryptedContent + * [0] IMPLICIT EncryptedContent OPTIONAL + * } + * + * EncryptedContent ::= OCTET STRING + */ + +typedef struct { + CSSM_OID contentType; + CSSM_X509_ALGORITHM_IDENTIFIER encrAlg; + CSSM_DATA encrContent; +} NSS_P7_EncrContentInfo; + +/* + * EncryptedData ::= SEQUENCE { + * version Version, + * encryptedContentInfo EncryptedContentInfo + * } + */ +typedef struct { + CSSM_DATA version; + NSS_P7_EncrContentInfo contentInfo; +} NSS_P7_EncryptedData; + +extern const SecAsn1Template NSS_P7_EncrContentInfoTemplate[]; +extern const SecAsn1Template NSS_P7_EncryptedDataTemplate[]; +extern const SecAsn1Template NSS_P7_PtrToEncryptedDataTemplate[]; + +/* the stub templates for unimplemented contentTypes */ +#define NSS_P7_PtrToSignedDataTemplate kSecAsn1PointerToAnyTemplate +#define NSS_P7_PtrToEnvelDataTemplate kSecAsn1PointerToAnyTemplate +#define NSS_P7_PtrToSignEnvelDataTemplate kSecAsn1PointerToAnyTemplate +#define NSS_P7_PtrToDigestedDataTemplate kSecAsn1PointerToAnyTemplate + +#pragma mark ---- decoded ContentInfo ----- + +/* + * For convenience, out dynamic template chooser for ContentInfo.content + * drops one of these into the decoded struct. Thus, higher level + * code doesn't have to grunge around comparing OIDs to figure out + * what's there. + */ +typedef enum { + CT_None = 0, + CT_Data, + CT_SignedData, + CT_EnvData, + CT_SignedEnvData, + CT_DigestData, + CT_EncryptedData +} NSS_P7_CI_Type; + +/* + * Decoded ContentInfo. Decoded via SEC_ASN1_DYNAMIC per contentType. + */ +typedef struct { + CSSM_OID contentType; + NSS_P7_CI_Type type; + union { + CSSM_DATA *data; // CSSMOID_PKCS7_Data + // contents of Octet String + NSS_P7_SignedData *signedData; + // CSSMOID_PKCS7_SignedData + NSS_P7_EnvelData *envData; // CSSMOID_PKCS7_EnvelopedData + NSS_P7_SignEnvelData *signEnvelData; + // CSSMOID_PKCS7_SignedAndEnvelopedData + NSS_P7_DigestedData *digestedData; + // CSSMOID_PKCS7_DigestedData + NSS_P7_EncryptedData *encryptData; + //CSSMOID_PKCS7_EncryptedData + + } content; +} NSS_P7_DecodedContentInfo; + +extern const SecAsn1Template NSS_P7_DecodedContentInfoTemplate[]; + +#ifdef __cplusplus +} +#endif + +#endif /* _PKCS7_TEMPLATES_H_ */ + diff --git a/libsecurity_pkcs12/lib/pkcsoids.cpp b/Security/libsecurity_pkcs12/lib/pkcsoids.cpp similarity index 94% rename from libsecurity_pkcs12/lib/pkcsoids.cpp rename to Security/libsecurity_pkcs12/lib/pkcsoids.cpp index 9d600e45..4772e3dd 100644 --- a/libsecurity_pkcs12/lib/pkcsoids.cpp +++ b/Security/libsecurity_pkcs12/lib/pkcsoids.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_pkcs12/lib/pkcsoids.h b/Security/libsecurity_pkcs12/lib/pkcsoids.h similarity index 94% rename from libsecurity_pkcs12/lib/pkcsoids.h rename to Security/libsecurity_pkcs12/lib/pkcsoids.h index 01b346ee..92f786b4 100644 --- a/libsecurity_pkcs12/lib/pkcsoids.h +++ b/Security/libsecurity_pkcs12/lib/pkcsoids.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_pkcs12/libsecurity_pkcs12.xcodeproj/project.pbxproj b/Security/libsecurity_pkcs12/libsecurity_pkcs12.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_pkcs12/libsecurity_pkcs12.xcodeproj/project.pbxproj rename to Security/libsecurity_pkcs12/libsecurity_pkcs12.xcodeproj/project.pbxproj diff --git a/libsecurity_sd_cspdl/APPLE_LICENSE b/Security/libsecurity_sd_cspdl/APPLE_LICENSE similarity index 100% rename from libsecurity_sd_cspdl/APPLE_LICENSE rename to Security/libsecurity_sd_cspdl/APPLE_LICENSE diff --git a/libsecurity_sd_cspdl/Info-security_sd_cspdl.plist b/Security/libsecurity_sd_cspdl/Info-security_sd_cspdl.plist similarity index 100% rename from libsecurity_sd_cspdl/Info-security_sd_cspdl.plist rename to Security/libsecurity_sd_cspdl/Info-security_sd_cspdl.plist diff --git a/libsecurity_sd_cspdl/lib/SDCSPDLBuiltin.cpp b/Security/libsecurity_sd_cspdl/lib/SDCSPDLBuiltin.cpp similarity index 94% rename from libsecurity_sd_cspdl/lib/SDCSPDLBuiltin.cpp rename to Security/libsecurity_sd_cspdl/lib/SDCSPDLBuiltin.cpp index 19f22470..5aa521e4 100644 --- a/libsecurity_sd_cspdl/lib/SDCSPDLBuiltin.cpp +++ b/Security/libsecurity_sd_cspdl/lib/SDCSPDLBuiltin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_sd_cspdl/lib/SDCSPDLDatabase.cpp b/Security/libsecurity_sd_cspdl/lib/SDCSPDLDatabase.cpp similarity index 95% rename from libsecurity_sd_cspdl/lib/SDCSPDLDatabase.cpp rename to Security/libsecurity_sd_cspdl/lib/SDCSPDLDatabase.cpp index 32051cf8..23aef989 100644 --- a/libsecurity_sd_cspdl/lib/SDCSPDLDatabase.cpp +++ b/Security/libsecurity_sd_cspdl/lib/SDCSPDLDatabase.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_sd_cspdl/lib/SDCSPDLDatabase.h b/Security/libsecurity_sd_cspdl/lib/SDCSPDLDatabase.h similarity index 95% rename from libsecurity_sd_cspdl/lib/SDCSPDLDatabase.h rename to Security/libsecurity_sd_cspdl/lib/SDCSPDLDatabase.h index 7631e484..a4599b3b 100644 --- a/libsecurity_sd_cspdl/lib/SDCSPDLDatabase.h +++ b/Security/libsecurity_sd_cspdl/lib/SDCSPDLDatabase.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_sd_cspdl/lib/SDCSPDLPlugin.cpp b/Security/libsecurity_sd_cspdl/lib/SDCSPDLPlugin.cpp similarity index 97% rename from libsecurity_sd_cspdl/lib/SDCSPDLPlugin.cpp rename to Security/libsecurity_sd_cspdl/lib/SDCSPDLPlugin.cpp index ac8d33a9..7b37b9f8 100644 --- a/libsecurity_sd_cspdl/lib/SDCSPDLPlugin.cpp +++ b/Security/libsecurity_sd_cspdl/lib/SDCSPDLPlugin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_sd_cspdl/lib/SDCSPDLPlugin.h b/Security/libsecurity_sd_cspdl/lib/SDCSPDLPlugin.h similarity index 97% rename from libsecurity_sd_cspdl/lib/SDCSPDLPlugin.h rename to Security/libsecurity_sd_cspdl/lib/SDCSPDLPlugin.h index 9569ce90..fd88d5ac 100644 --- a/libsecurity_sd_cspdl/lib/SDCSPDLPlugin.h +++ b/Security/libsecurity_sd_cspdl/lib/SDCSPDLPlugin.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_sd_cspdl/lib/SDCSPDLSession.cpp b/Security/libsecurity_sd_cspdl/lib/SDCSPDLSession.cpp similarity index 97% rename from libsecurity_sd_cspdl/lib/SDCSPDLSession.cpp rename to Security/libsecurity_sd_cspdl/lib/SDCSPDLSession.cpp index 0c549ad8..03d4ae52 100644 --- a/libsecurity_sd_cspdl/lib/SDCSPDLSession.cpp +++ b/Security/libsecurity_sd_cspdl/lib/SDCSPDLSession.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_sd_cspdl/lib/SDCSPDLSession.h b/Security/libsecurity_sd_cspdl/lib/SDCSPDLSession.h similarity index 95% rename from libsecurity_sd_cspdl/lib/SDCSPDLSession.h rename to Security/libsecurity_sd_cspdl/lib/SDCSPDLSession.h index d19e5f50..b855d4ac 100644 --- a/libsecurity_sd_cspdl/lib/SDCSPDLSession.h +++ b/Security/libsecurity_sd_cspdl/lib/SDCSPDLSession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_sd_cspdl/lib/SDCSPSession.cpp b/Security/libsecurity_sd_cspdl/lib/SDCSPSession.cpp similarity index 99% rename from libsecurity_sd_cspdl/lib/SDCSPSession.cpp rename to Security/libsecurity_sd_cspdl/lib/SDCSPSession.cpp index dc9a5de3..3e62d12d 100644 --- a/libsecurity_sd_cspdl/lib/SDCSPSession.cpp +++ b/Security/libsecurity_sd_cspdl/lib/SDCSPSession.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004,2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2004,2008,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_sd_cspdl/lib/SDCSPSession.h b/Security/libsecurity_sd_cspdl/lib/SDCSPSession.h similarity index 98% rename from libsecurity_sd_cspdl/lib/SDCSPSession.h rename to Security/libsecurity_sd_cspdl/lib/SDCSPSession.h index de87727d..530bbd23 100644 --- a/libsecurity_sd_cspdl/lib/SDCSPSession.h +++ b/Security/libsecurity_sd_cspdl/lib/SDCSPSession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_sd_cspdl/lib/SDContext.cpp b/Security/libsecurity_sd_cspdl/lib/SDContext.cpp similarity index 99% rename from libsecurity_sd_cspdl/lib/SDContext.cpp rename to Security/libsecurity_sd_cspdl/lib/SDContext.cpp index 3eaafd8b..27881a9e 100644 --- a/libsecurity_sd_cspdl/lib/SDContext.cpp +++ b/Security/libsecurity_sd_cspdl/lib/SDContext.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_sd_cspdl/lib/SDContext.h b/Security/libsecurity_sd_cspdl/lib/SDContext.h similarity index 98% rename from libsecurity_sd_cspdl/lib/SDContext.h rename to Security/libsecurity_sd_cspdl/lib/SDContext.h index e52140e4..e15105e3 100644 --- a/libsecurity_sd_cspdl/lib/SDContext.h +++ b/Security/libsecurity_sd_cspdl/lib/SDContext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_sd_cspdl/lib/SDDLSession.cpp b/Security/libsecurity_sd_cspdl/lib/SDDLSession.cpp similarity index 99% rename from libsecurity_sd_cspdl/lib/SDDLSession.cpp rename to Security/libsecurity_sd_cspdl/lib/SDDLSession.cpp index 00a59774..a3aafbee 100644 --- a/libsecurity_sd_cspdl/lib/SDDLSession.cpp +++ b/Security/libsecurity_sd_cspdl/lib/SDDLSession.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004,2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2004,2008,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_sd_cspdl/lib/SDDLSession.h b/Security/libsecurity_sd_cspdl/lib/SDDLSession.h similarity index 99% rename from libsecurity_sd_cspdl/lib/SDDLSession.h rename to Security/libsecurity_sd_cspdl/lib/SDDLSession.h index 22b8d6ed..9297b017 100644 --- a/libsecurity_sd_cspdl/lib/SDDLSession.h +++ b/Security/libsecurity_sd_cspdl/lib/SDDLSession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004,2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2004,2008,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_sd_cspdl/lib/SDFactory.cpp b/Security/libsecurity_sd_cspdl/lib/SDFactory.cpp similarity index 97% rename from libsecurity_sd_cspdl/lib/SDFactory.cpp rename to Security/libsecurity_sd_cspdl/lib/SDFactory.cpp index dc4560e2..e187cc9b 100644 --- a/libsecurity_sd_cspdl/lib/SDFactory.cpp +++ b/Security/libsecurity_sd_cspdl/lib/SDFactory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_sd_cspdl/lib/SDFactory.h b/Security/libsecurity_sd_cspdl/lib/SDFactory.h similarity index 95% rename from libsecurity_sd_cspdl/lib/SDFactory.h rename to Security/libsecurity_sd_cspdl/lib/SDFactory.h index 71e409b9..0896de8b 100644 --- a/libsecurity_sd_cspdl/lib/SDFactory.h +++ b/Security/libsecurity_sd_cspdl/lib/SDFactory.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_sd_cspdl/lib/SDKey.cpp b/Security/libsecurity_sd_cspdl/lib/SDKey.cpp similarity index 99% rename from libsecurity_sd_cspdl/lib/SDKey.cpp rename to Security/libsecurity_sd_cspdl/lib/SDKey.cpp index a6bc5c42..09791999 100644 --- a/libsecurity_sd_cspdl/lib/SDKey.cpp +++ b/Security/libsecurity_sd_cspdl/lib/SDKey.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004,2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2004,2008,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_sd_cspdl/lib/SDKey.h b/Security/libsecurity_sd_cspdl/lib/SDKey.h similarity index 97% rename from libsecurity_sd_cspdl/lib/SDKey.h rename to Security/libsecurity_sd_cspdl/lib/SDKey.h index 2103bba2..8370bb0c 100644 --- a/libsecurity_sd_cspdl/lib/SDKey.h +++ b/Security/libsecurity_sd_cspdl/lib/SDKey.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_sd_cspdl/libsecurity_sd_cspdl.xcodeproj/project.pbxproj b/Security/libsecurity_sd_cspdl/libsecurity_sd_cspdl.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_sd_cspdl/libsecurity_sd_cspdl.xcodeproj/project.pbxproj rename to Security/libsecurity_sd_cspdl/libsecurity_sd_cspdl.xcodeproj/project.pbxproj diff --git a/libsecurity_sd_cspdl/mds/sd_cspdl_common.mdsinfo b/Security/libsecurity_sd_cspdl/mds/sd_cspdl_common.mdsinfo similarity index 100% rename from libsecurity_sd_cspdl/mds/sd_cspdl_common.mdsinfo rename to Security/libsecurity_sd_cspdl/mds/sd_cspdl_common.mdsinfo diff --git a/libsecurity_utilities/APPLE_LICENSE b/Security/libsecurity_smime/APPLE_LICENSE similarity index 100% rename from libsecurity_utilities/APPLE_LICENSE rename to Security/libsecurity_smime/APPLE_LICENSE diff --git a/libsecurity_smime/Info-security_smime.plist b/Security/libsecurity_smime/Info-security_smime.plist similarity index 100% rename from libsecurity_smime/Info-security_smime.plist rename to Security/libsecurity_smime/Info-security_smime.plist diff --git a/Security/libsecurity_smime/TODO b/Security/libsecurity_smime/TODO new file mode 100644 index 00000000..9c9564f0 --- /dev/null +++ b/Security/libsecurity_smime/TODO @@ -0,0 +1,9 @@ +cmsattr.c +cmsdecode.c +cmsdigest.c +cmsrecinfo.c +cmssigdata.c +cmssiginfo.c + +* Support NSS_CMSRecipientInfo_Encode + cmst.h and cms.h changes. diff --git a/libsecurity_smime/docs/libsecurity_smime.plist b/Security/libsecurity_smime/docs/libsecurity_smime.plist similarity index 100% rename from libsecurity_smime/docs/libsecurity_smime.plist rename to Security/libsecurity_smime/docs/libsecurity_smime.plist diff --git a/libsecurity_smime/docs/libsecurity_smime.txt b/Security/libsecurity_smime/docs/libsecurity_smime.txt similarity index 100% rename from libsecurity_smime/docs/libsecurity_smime.txt rename to Security/libsecurity_smime/docs/libsecurity_smime.txt diff --git a/Security/libsecurity_smime/lib/SecCMS.c b/Security/libsecurity_smime/lib/SecCMS.c new file mode 100644 index 00000000..bcb2552a --- /dev/null +++ b/Security/libsecurity_smime/lib/SecCMS.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + +#include +#include +#include +#include +#include +#include + + +#include + +/* Designed to match the sec submodule implementation available for iOS */ +CFArrayRef SecCMSCertificatesOnlyMessageCopyCertificates(CFDataRef message) { + SecCmsMessageRef cmsg = NULL; + SecCmsContentInfoRef cinfo; + SecCmsSignedDataRef sigd = NULL; + CFMutableArrayRef certs = NULL; + + CSSM_DATA encoded_message = { CFDataGetLength(message), (uint8_t*)CFDataGetBytePtr(message) }; + require_noerr_quiet(SecCmsMessageDecode(&encoded_message, NULL, NULL, NULL, NULL, NULL, NULL, &cmsg), out); + /* expected to be a signed data message at the top level */ + require(cinfo = SecCmsMessageContentLevel(cmsg, 0), out); + require(SecCmsContentInfoGetContentTypeTag(cinfo) == SEC_OID_PKCS7_SIGNED_DATA, out); + require(sigd = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(cinfo), out); + + /* find out about signers */ + int nsigners = SecCmsSignedDataSignerInfoCount(sigd); + require(nsigners == 0, out); + + CSSM_DATA_PTR *cert_datas = SecCmsSignedDataGetCertificateList(sigd); + certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + CSSM_DATA_PTR cert_data; + if (cert_datas) while ((cert_data = *cert_datas) != NULL) { + SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, cert_data->Data, cert_data->Length); + if (cert) { + CFArrayAppendValue(certs, cert); + CFRelease(cert); + } + cert_datas++; + } + +out: + if (cmsg) + SecCmsMessageDestroy(cmsg); + + return certs; +} + + +CFDataRef SecCMSCreateCertificatesOnlyMessageIAP(SecCertificateRef cert) +{ + static const uint8_t header[] = { + 0x30, 0x82, 0x03, 0x6d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, + 0x82, 0x03, 0x5e, 0x30, 0x82, 0x03, 0x5a, 0x02, + 0x01, 0x01, 0x31, 0x00, 0x30, 0x0b, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, + 0x01, 0xa0, 0x82, 0x03, 0x40 + }; + + static const uint8_t trailer[] = { + 0xa1, 0x00, 0x31, 0x00 + }; + + CFMutableDataRef message = NULL; + CFDataRef certdata; + const uint8_t *certbytes; + CFIndex certlen; + uint8_t *messagebytes; + uint16_t messagelen; + + certdata = SecCertificateCopyData(cert); + require(certdata, out); + + certbytes = CFDataGetBytePtr(certdata); + certlen = CFDataGetLength(certdata); + require(certlen > UINT8_MAX, out); + require(certlen < UINT16_MAX, out); + + message = CFDataCreateMutable(kCFAllocatorDefault, 0); + require(message, out); + + CFDataAppendBytes(message, header, sizeof(header)); + CFDataAppendBytes(message, certbytes, certlen); + CFDataAppendBytes(message, trailer, sizeof(trailer)); + + messagebytes = CFDataGetMutableBytePtr(message); + messagelen = CFDataGetLength(message); + + messagelen -= 4; + messagebytes[2] = messagelen >> 8; + messagebytes[3] = messagelen & 0xFF; + + messagelen -= 15; + messagebytes[17] = messagelen >> 8; + messagebytes[18] = messagelen & 0xFF; + + messagelen -= 4; + messagebytes[21] = messagelen >> 8; + messagebytes[22] = messagelen & 0xFF; + + messagelen -= 26; + messagebytes[43] = messagelen >> 8; + messagebytes[44] = messagelen & 0xFF; + +out: + if (certdata != NULL) + { + CFRelease(certdata); + } + return message; +} + + + diff --git a/Security/libsecurity_smime/lib/SecCMS.h b/Security/libsecurity_smime/lib/SecCMS.h new file mode 100644 index 00000000..574dae1b --- /dev/null +++ b/Security/libsecurity_smime/lib/SecCMS.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef libsecurity_smime_SecCMS_h +#define libsecurity_smime_SecCMS_h + +#include +#include + +/* Return an array of certificates contained in message, if message is of the + type SignedData and has no signers, return NULL otherwise. Not that if + the message is properly formed but has no certificates an empty array will + be returned. + Designed to match the sec submodule implementation available for iOS + */ +CFArrayRef SecCMSCertificatesOnlyMessageCopyCertificates(CFDataRef message); + +/* Create a degenerate PKCS#7 containing a cert or a CFArray of certs. */ +CFDataRef SecCMSCreateCertificatesOnlyMessageIAP(SecCertificateRef cert); + + +#endif diff --git a/Security/libsecurity_smime/lib/SecCmsBase.h b/Security/libsecurity_smime/lib/SecCmsBase.h new file mode 100644 index 00000000..c3c03690 --- /dev/null +++ b/Security/libsecurity_smime/lib/SecCmsBase.h @@ -0,0 +1,511 @@ +/* + * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecCmsBase.h + @Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. + + @availability 10.4 and later + @abstract Interfaces of the CMS implementation. + @discussion The functions here implement functions for encoding + and decoding Cryptographic Message Syntax (CMS) objects + as described in rfc3369. + */ + +#ifndef _SECURITY_SECCMSBASE_H_ +#define _SECURITY_SECCMSBASE_H_ 1 + +#include /* size_t */ +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + @typedef + @discussion XXX We need to remove these from the API and move them back to secoidt.h. + */ +typedef struct SECOidDataStr SECOidData; + +/*! + @typedef + @discussion XXX We might want to get rid of this alltogether. + */ +typedef CSSM_X509_ALGORITHM_IDENTIFIER SECAlgorithmID; + +/*! + @typedef + @discussion XXX This should probably move to SecKey.h + */ +typedef SecKeyRef SecSymmetricKeyRef; + +/*! + @typedef + @discussion XXX This should probably move to SecKey.h + */ +typedef SecKeyRef SecPublicKeyRef; + +/*! + @typedef + @discussion XXX This should probably move to SecKey.h + */ +typedef SecKeyRef SecPrivateKeyRef; + +/*! + @typedef + */ +typedef void(*PK11PasswordFunc)(void); + +/*! + @typedef + */ +typedef struct SecArenaPoolStr *SecArenaPoolRef; + +/*! + @typedef + */ +typedef struct SecCmsMessageStr *SecCmsMessageRef; + +/*! + @typedef + */ +typedef struct SecCmsContentInfoStr *SecCmsContentInfoRef; + +/*! + @typedef + */ +typedef struct SecCmsSignedDataStr *SecCmsSignedDataRef; + +/*! + @typedef + */ +typedef struct SecCmsSignerInfoStr *SecCmsSignerInfoRef; + +/*! + @typedef + */ +typedef struct SecCmsEnvelopedDataStr *SecCmsEnvelopedDataRef; + +/*! + @typedef + */ +typedef struct SecCmsRecipientInfoStr *SecCmsRecipientInfoRef; + +/*! + @typedef + */ +typedef struct SecCmsDigestedDataStr *SecCmsDigestedDataRef; + +/*! + @typedef + */ +typedef struct SecCmsEncryptedDataStr *SecCmsEncryptedDataRef; + +/*! + @typedef + */ +typedef struct SecCmsDecoderStr *SecCmsDecoderRef; + +/*! + @typedef + */ +typedef struct SecCmsEncoderStr *SecCmsEncoderRef; + +/*! + @typedef + */ +typedef struct SecCmsDigestContextStr *SecCmsDigestContextRef; + + +/*! + @typedef + @discussion Type of function passed to SecCmsDecode or SecCmsDecoderStart. + If specified, this is where the content bytes (only) will be "sent" as they are recovered during the decoding. + And: + Type of function passed to SecCmsEncode or SecCmsEncoderStart. + This is where the DER-encoded bytes will be "sent". + + XXX Should just combine this with SecCmsEncoderContentCallback type and use a simpler, common name. + */ +typedef void (*SecCmsContentCallback)(void *arg, const char *buf, size_t len); + +/*! + @typedef + @discussion Type of function passed to SecCmsDecode or SecCmsDecoderStart to retrieve the decryption key. This function is intended to be used for EncryptedData content info's which do not have a key available in a certificate, etc. + */ +typedef SecSymmetricKeyRef(*SecCmsGetDecryptKeyCallback)(void *arg, SECAlgorithmID *algid); + +/*! + @enum SecCmsVerificationStatus + */ +typedef enum { + SecCmsVSUnverified = 0, + SecCmsVSGoodSignature = 1, + SecCmsVSBadSignature = 2, + SecCmsVSDigestMismatch = 3, + SecCmsVSSigningCertNotFound = 4, + SecCmsVSSigningCertNotTrusted = 5, + SecCmsVSSignatureAlgorithmUnknown = 6, + SecCmsVSSignatureAlgorithmUnsupported = 7, + SecCmsVSMalformedSignature = 8, + SecCmsVSProcessingError = 9, + SecCmsVSTimestampMissing = 10, /* A timestamp was expected but was not found. */ + SecCmsVSTimestampInvalid = 11, /* The timestamp was not valid. */ + SecCmsVSTimestampNotTrusted = 12, /* The timestamp signing chain was not trusted. */ +} SecCmsVerificationStatus; + +/*! + @enum SecCmsCertChainMode + */ +typedef enum { + SecCmsCMNone = 0, + SecCmsCMCertOnly = 1, + SecCmsCMCertChain = 2, + SecCmsCMCertChainWithRoot = 3 +} SecCmsCertChainMode; + +/*! + @enum + @discussion XXX This should be replaced with SecPolicyRefs + */ +typedef enum SECCertUsageEnum { + certUsageSSLClient = 0, + certUsageSSLServer = 1, + certUsageSSLServerWithStepUp = 2, + certUsageSSLCA = 3, + certUsageEmailSigner = 4, + certUsageEmailRecipient = 5, + certUsageObjectSigner = 6, + certUsageUserCertImport = 7, + certUsageVerifyCA = 8, + certUsageProtectedObjectSigner = 9, + certUsageStatusResponder = 10, + certUsageAnyCA = 11 +} SECCertUsage; + + +/*! + @enum SECOidTag + @abstract Misc object IDs - these numbers are for convenient handling. + @discussion They are mapped into real object IDs + NOTE: the order of these entries must mach the array "oids" of SECOidData in util/secoid.c. + */ +typedef enum { + SEC_OID_UNKNOWN = 0, + SEC_OID_MD2 = 1, + SEC_OID_MD4 = 2, + SEC_OID_MD5 = 3, + SEC_OID_SHA1 = 4, + SEC_OID_RC2_CBC = 5, + SEC_OID_RC4 = 6, + SEC_OID_DES_EDE3_CBC = 7, + SEC_OID_RC5_CBC_PAD = 8, + SEC_OID_DES_ECB = 9, + SEC_OID_DES_CBC = 10, + SEC_OID_DES_OFB = 11, + SEC_OID_DES_CFB = 12, + SEC_OID_DES_MAC = 13, + SEC_OID_DES_EDE = 14, + SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE = 15, + SEC_OID_PKCS1_RSA_ENCRYPTION = 16, + SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION = 17, + SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION = 18, + SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION = 19, + SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION = 20, + SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC = 21, + SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC = 22, + SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC = 23, + SEC_OID_PKCS7 = 24, + SEC_OID_PKCS7_DATA = 25, + SEC_OID_PKCS7_SIGNED_DATA = 26, + SEC_OID_PKCS7_ENVELOPED_DATA = 27, + SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA = 28, + SEC_OID_PKCS7_DIGESTED_DATA = 29, + SEC_OID_PKCS7_ENCRYPTED_DATA = 30, + SEC_OID_PKCS9_EMAIL_ADDRESS = 31, + SEC_OID_PKCS9_UNSTRUCTURED_NAME = 32, + SEC_OID_PKCS9_CONTENT_TYPE = 33, + SEC_OID_PKCS9_MESSAGE_DIGEST = 34, + SEC_OID_PKCS9_SIGNING_TIME = 35, + SEC_OID_PKCS9_COUNTER_SIGNATURE = 36, + SEC_OID_PKCS9_CHALLENGE_PASSWORD = 37, + SEC_OID_PKCS9_UNSTRUCTURED_ADDRESS = 38, + SEC_OID_PKCS9_EXTENDED_CERTIFICATE_ATTRIBUTES = 39, + SEC_OID_PKCS9_SMIME_CAPABILITIES = 40, + SEC_OID_AVA_COMMON_NAME = 41, + SEC_OID_AVA_COUNTRY_NAME = 42, + SEC_OID_AVA_LOCALITY = 43, + SEC_OID_AVA_STATE_OR_PROVINCE = 44, + SEC_OID_AVA_ORGANIZATION_NAME = 45, + SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME = 46, + SEC_OID_AVA_DN_QUALIFIER = 47, + SEC_OID_AVA_DC = 48, + + SEC_OID_NS_TYPE_GIF = 49, + SEC_OID_NS_TYPE_JPEG = 50, + SEC_OID_NS_TYPE_URL = 51, + SEC_OID_NS_TYPE_HTML = 52, + SEC_OID_NS_TYPE_CERT_SEQUENCE = 53, + SEC_OID_MISSI_KEA_DSS_OLD = 54, + SEC_OID_MISSI_DSS_OLD = 55, + SEC_OID_MISSI_KEA_DSS = 56, + SEC_OID_MISSI_DSS = 57, + SEC_OID_MISSI_KEA = 58, + SEC_OID_MISSI_ALT_KEA = 59, + + /* Netscape private certificate extensions */ + SEC_OID_NS_CERT_EXT_NETSCAPE_OK = 60, + SEC_OID_NS_CERT_EXT_ISSUER_LOGO = 61, + SEC_OID_NS_CERT_EXT_SUBJECT_LOGO = 62, + SEC_OID_NS_CERT_EXT_CERT_TYPE = 63, + SEC_OID_NS_CERT_EXT_BASE_URL = 64, + SEC_OID_NS_CERT_EXT_REVOCATION_URL = 65, + SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL = 66, + SEC_OID_NS_CERT_EXT_CA_CRL_URL = 67, + SEC_OID_NS_CERT_EXT_CA_CERT_URL = 68, + SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL = 69, + SEC_OID_NS_CERT_EXT_CA_POLICY_URL = 70, + SEC_OID_NS_CERT_EXT_HOMEPAGE_URL = 71, + SEC_OID_NS_CERT_EXT_ENTITY_LOGO = 72, + SEC_OID_NS_CERT_EXT_USER_PICTURE = 73, + SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME = 74, + SEC_OID_NS_CERT_EXT_COMMENT = 75, + SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL = 76, + SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME = 77, + SEC_OID_NS_KEY_USAGE_GOVT_APPROVED = 78, + + /* x.509 v3 Extensions */ + SEC_OID_X509_SUBJECT_DIRECTORY_ATTR = 79, + SEC_OID_X509_SUBJECT_KEY_ID = 80, + SEC_OID_X509_KEY_USAGE = 81, + SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD = 82, + SEC_OID_X509_SUBJECT_ALT_NAME = 83, + SEC_OID_X509_ISSUER_ALT_NAME = 84, + SEC_OID_X509_BASIC_CONSTRAINTS = 85, + SEC_OID_X509_NAME_CONSTRAINTS = 86, + SEC_OID_X509_CRL_DIST_POINTS = 87, + SEC_OID_X509_CERTIFICATE_POLICIES = 88, + SEC_OID_X509_POLICY_MAPPINGS = 89, + SEC_OID_X509_POLICY_CONSTRAINTS = 90, + SEC_OID_X509_AUTH_KEY_ID = 91, + SEC_OID_X509_EXT_KEY_USAGE = 92, + SEC_OID_X509_AUTH_INFO_ACCESS = 93, + + SEC_OID_X509_CRL_NUMBER = 94, + SEC_OID_X509_REASON_CODE = 95, + SEC_OID_X509_INVALID_DATE = 96, + /* End of x.509 v3 Extensions */ + + SEC_OID_X500_RSA_ENCRYPTION = 97, + + /* alg 1485 additions */ + SEC_OID_RFC1274_UID = 98, + SEC_OID_RFC1274_MAIL = 99, + + /* PKCS 12 additions */ + SEC_OID_PKCS12 = 100, + SEC_OID_PKCS12_MODE_IDS = 101, + SEC_OID_PKCS12_ESPVK_IDS = 102, + SEC_OID_PKCS12_BAG_IDS = 103, + SEC_OID_PKCS12_CERT_BAG_IDS = 104, + SEC_OID_PKCS12_OIDS = 105, + SEC_OID_PKCS12_PBE_IDS = 106, + SEC_OID_PKCS12_SIGNATURE_IDS = 107, + SEC_OID_PKCS12_ENVELOPING_IDS = 108, + /* SEC_OID_PKCS12_OFFLINE_TRANSPORT_MODE, + SEC_OID_PKCS12_ONLINE_TRANSPORT_MODE, */ + SEC_OID_PKCS12_PKCS8_KEY_SHROUDING = 109, + SEC_OID_PKCS12_KEY_BAG_ID = 110, + SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID = 111, + SEC_OID_PKCS12_SECRET_BAG_ID = 112, + SEC_OID_PKCS12_X509_CERT_CRL_BAG = 113, + SEC_OID_PKCS12_SDSI_CERT_BAG = 114, + SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4 = 115, + SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4 = 116, + SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC = 117, + SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC = 118, + SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC = 119, + SEC_OID_PKCS12_RSA_ENCRYPTION_WITH_128_BIT_RC4 = 120, + SEC_OID_PKCS12_RSA_ENCRYPTION_WITH_40_BIT_RC4 = 121, + SEC_OID_PKCS12_RSA_ENCRYPTION_WITH_TRIPLE_DES = 122, + SEC_OID_PKCS12_RSA_SIGNATURE_WITH_SHA1_DIGEST = 123, + /* end of PKCS 12 additions */ + + /* DSA signatures */ + SEC_OID_ANSIX9_DSA_SIGNATURE = 124, + SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST = 125, + SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST = 126, + + /* Verisign OIDs */ + SEC_OID_VERISIGN_USER_NOTICES = 127, + + /* PKIX OIDs */ + SEC_OID_PKIX_CPS_POINTER_QUALIFIER = 128, + SEC_OID_PKIX_USER_NOTICE_QUALIFIER = 129, + SEC_OID_PKIX_OCSP = 130, + SEC_OID_PKIX_OCSP_BASIC_RESPONSE = 131, + SEC_OID_PKIX_OCSP_NONCE = 132, + SEC_OID_PKIX_OCSP_CRL = 133, + SEC_OID_PKIX_OCSP_RESPONSE = 134, + SEC_OID_PKIX_OCSP_NO_CHECK = 135, + SEC_OID_PKIX_OCSP_ARCHIVE_CUTOFF = 136, + SEC_OID_PKIX_OCSP_SERVICE_LOCATOR = 137, + SEC_OID_PKIX_REGCTRL_REGTOKEN = 138, + SEC_OID_PKIX_REGCTRL_AUTHENTICATOR = 139, + SEC_OID_PKIX_REGCTRL_PKIPUBINFO = 140, + SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS = 141, + SEC_OID_PKIX_REGCTRL_OLD_CERT_ID = 142, + SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY = 143, + SEC_OID_PKIX_REGINFO_UTF8_PAIRS = 144, + SEC_OID_PKIX_REGINFO_CERT_REQUEST = 145, + SEC_OID_EXT_KEY_USAGE_SERVER_AUTH = 146, + SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH = 147, + SEC_OID_EXT_KEY_USAGE_CODE_SIGN = 148, + SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT = 149, + SEC_OID_EXT_KEY_USAGE_TIME_STAMP = 150, + SEC_OID_OCSP_RESPONDER = 151, + + /* Netscape Algorithm OIDs */ + SEC_OID_NETSCAPE_SMIME_KEA = 152, + + /* Skipjack OID -- ### mwelch temporary */ + SEC_OID_FORTEZZA_SKIPJACK = 153, + + /* PKCS 12 V2 oids */ + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4 = 154, + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4 = 155, + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC = 156, + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC = 157, + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC = 158, + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC = 159, + SEC_OID_PKCS12_SAFE_CONTENTS_ID = 160, + SEC_OID_PKCS12_PKCS8_SHROUDED_KEY_BAG_ID = 161, + + SEC_OID_PKCS12_V1_KEY_BAG_ID = 162, + SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID = 163, + SEC_OID_PKCS12_V1_CERT_BAG_ID = 164, + SEC_OID_PKCS12_V1_CRL_BAG_ID = 165, + SEC_OID_PKCS12_V1_SECRET_BAG_ID = 166, + SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID = 167, + SEC_OID_PKCS9_X509_CERT = 168, + SEC_OID_PKCS9_SDSI_CERT = 169, + SEC_OID_PKCS9_X509_CRL = 170, + SEC_OID_PKCS9_FRIENDLY_NAME = 171, + SEC_OID_PKCS9_LOCAL_KEY_ID = 172, + SEC_OID_PKCS12_KEY_USAGE = 173, + + /*Diffe Helman OIDS */ + SEC_OID_X942_DIFFIE_HELMAN_KEY = 174, + + /* Netscape other name types */ + SEC_OID_NETSCAPE_NICKNAME = 175, + + /* Cert Server OIDS */ + SEC_OID_NETSCAPE_RECOVERY_REQUEST = 176, + + /* 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, + SEC_OID_CMS_RC2_KEY_WRAP = 181, + + /* SMIME attributes */ + SEC_OID_SMIME_ENCRYPTION_KEY_PREFERENCE = 182, + + /* AES OIDs */ + SEC_OID_AES_128_ECB = 183, + SEC_OID_AES_128_CBC = 184, + SEC_OID_AES_192_ECB = 185, + SEC_OID_AES_192_CBC = 186, + SEC_OID_AES_256_ECB = 187, + SEC_OID_AES_256_CBC = 188, + + SEC_OID_SDN702_DSA_SIGNATURE = 189, + + 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, + + /* 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, + + /* 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, + + /* 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_TOTAL +} SECOidTag; + +/*! + @function + @abstract Create a new SecArenaPool object. + @param chunksize Size of the chunks the pool will use to allocate its underlying storage. + @param outArena pointer to a SecArenaPoolRef to be created. + @result On success return 0 and outArena will contain a newly created SecArenaPoolRef. + @availability 10.4 and later + @updated 2004-04-23 + */ +OSStatus SecArenaPoolCreate(size_t chunksize, SecArenaPoolRef *outArena); + +/*! + @function + @abstract Free a SecArenaPool object and everything in it. + @param arena The SecArenaPool object to free. + @param zero If this is true the arena's memory will be zero filled before it is freed. + @result arena will no longer be valid and the memory used by it is returned to the malloc heap. + @availability 10.4 and later + @updated 2004-04-23 + */ +void SecArenaPoolFree(SecArenaPoolRef arena, Boolean zero); + + +#if defined(__cplusplus) +} +#endif + +#endif /* _SECURITY_SECCMSBASE_H_ */ diff --git a/Security/libsecurity_smime/lib/SecCmsContentInfo.h b/Security/libsecurity_smime/lib/SecCmsContentInfo.h new file mode 100644 index 00000000..b9f5d68e --- /dev/null +++ b/Security/libsecurity_smime/lib/SecCmsContentInfo.h @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecCmsContentInfo.h + @Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + + @availability 10.4 and later + @abstract Interfaces of the CMS implementation. + @discussion The functions here implement functions for creating and + accessing ContentInfo objects that are part of Cryptographic + Message Syntax (CMS) objects as described in rfc3369. + */ + +#ifndef _SECURITY_SECCMSCONTENTINFO_H_ +#define _SECURITY_SECCMSCONTENTINFO_H_ 1 + +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + + +/*! @functiongroup ContentInfo accessors */ +/*! + @function + @abstract Get content's contentInfo (if it exists). + @param cinfo A ContentInfo object of which we want to get the child contentInfo. + @result The child ContentInfo object, or NULL if there is none. + @discussion This function requires a ContentInfo object which is usually created by decoding and SecCmsMessage using a SecCmsDecoder. + @availability 10.4 and later + */ +extern SecCmsContentInfoRef +SecCmsContentInfoGetChildContentInfo(SecCmsContentInfoRef cinfo); + +/*! + @function + @abstract Get pointer to inner content + @discussion needs to be casted... + */ +extern void * +SecCmsContentInfoGetContent(SecCmsContentInfoRef cinfo); + +/*! + @function + @abstract Get pointer to innermost content + @discussion This is typically only called by SecCmsMessageGetContent(). + */ +extern CSSM_DATA_PTR +SecCmsContentInfoGetInnerContent(SecCmsContentInfoRef cinfo); + +/*! + @function + @abstract Find out and return the inner content type. + */ +extern SECOidTag +SecCmsContentInfoGetContentTypeTag(SecCmsContentInfoRef cinfo); + +/*! + @function + @abstract Find out and return the inner content type. + @discussion Caches pointer to lookup result for future reference. + */ +extern CSSM_OID * +SecCmsContentInfoGetContentTypeOID(SecCmsContentInfoRef cinfo); + +/*! + @function + @abstract Find out and return the content encryption algorithm tag. + */ +extern SECOidTag +SecCmsContentInfoGetContentEncAlgTag(SecCmsContentInfoRef cinfo); + +/*! + @function + @abstract Find out and return the content encryption algorithm. + @discussion Caches pointer to lookup result for future reference. + */ +extern SECAlgorithmID * +SecCmsContentInfoGetContentEncAlg(SecCmsContentInfoRef cinfo); + + +/*! @functiongroup Message construction */ +/*! + @function + @abstract Set a ContentInfos content to a Data + @param cmsg A Message object to which the cinfo object belongs. + @param cinfo A ContentInfo object of which we want set the content. + @param data A pointer to a CSSM_DATA object or NULL if data will be provided during SecCmsEncoderUpdate calls. + @param detached True if the content is to be deattched from the CMS message rather than included within it. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion This function requires a ContentInfo object which can be made by creating a SecCmsMessage object. If the call succeeds the passed in data will be owned by the reciever. The data->Data must have been allocated using the cmsg's SecArenaPool if it is present. + @availability 10.4 and later + */ +extern OSStatus +SecCmsContentInfoSetContentData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, CSSM_DATA_PTR data, Boolean detached); + +/*! + @function + @abstract Set a ContentInfos content to a SignedData. + @param cmsg A Message object to which the cinfo object belongs. + @param cinfo A ContentInfo object of which we want set the content. + @param sigd A SignedData object to set as the content of the cinfo object. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion This function requires a ContentInfo object which can be made by creating a SecCmsMessage object and a SignedData which can be made by calling SecCmsSignedDataCreate(). If the call succeeds the passed in SignedData object will be owned by the reciever. The Message object of the SignedData object must be the same as cmsg. + @availability 10.4 and later + */ +extern OSStatus +SecCmsContentInfoSetContentSignedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsSignedDataRef sigd); + +/*! + @function + @abstract Set a ContentInfos content to a EnvelopedData. + @param cmsg A Message object to which the cinfo object belongs. + @param cinfo A ContentInfo object of which we want set the content. + @param envd A EnvelopedData object to set as the content of the cinfo object. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion This function requires a ContentInfo object which can be made by creating a SecCmsMessage object and a EnvelopedData which can be made by calling SecCmsEnvelopedDataCreate(). If the call succeeds the passed in EnvelopedData object will be owned by the reciever. The Message object of the EnvelopedData object must be the same as cmsg. + @availability 10.4 and later + */ +extern OSStatus +SecCmsContentInfoSetContentEnvelopedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsEnvelopedDataRef envd); + +/*! + @function + @abstract Set a ContentInfos content to a DigestedData. + @param cmsg A Message object to which the cinfo object belongs. + @param cinfo A ContentInfo object of which we want set the content. + @param digd A DigestedData object to set as the content of the cinfo object. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion This function requires a ContentInfo object which can be made by creating a SecCmsMessage object and a DigestedData which can be made by calling SecCmsDigestedDataCreate(). If the call succeeds the passed in DigestedData object will be owned by the reciever. The Message object of the DigestedData object must be the same as cmsg. + @availability 10.4 and later + */ +extern OSStatus +SecCmsContentInfoSetContentDigestedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsDigestedDataRef digd); + +/*! + @function + @abstract Set a ContentInfos content to a EncryptedData. + @param cmsg A Message object to which the cinfo object belongs. + @param cinfo A ContentInfo object of which we want set the content. + @param encd A EncryptedData object to set as the content of the cinfo object. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion This function requires a ContentInfo object which can be made by creating a SecCmsMessage object and a EncryptedData which can be made by calling SecCmsEncryptedDataCreate(). If the call succeeds the passed in EncryptedData object will be owned by the reciever. The Message object of the EncryptedData object must be the same as cmsg. + @availability 10.4 and later + */ +extern OSStatus +SecCmsContentInfoSetContentEncryptedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsEncryptedDataRef encd); + +OSStatus +SecCmsContentInfoSetContentOther(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, CSSM_DATA_PTR data, Boolean detached, const CSSM_OID *eContentType); + +/*! + @function + */ +extern OSStatus +SecCmsContentInfoSetContentEncAlg(SecArenaPoolRef pool, SecCmsContentInfoRef cinfo, + SECOidTag bulkalgtag, CSSM_DATA_PTR parameters, int keysize); + +/*! + @function + */ +extern OSStatus +SecCmsContentInfoSetContentEncAlgID(SecArenaPoolRef pool, SecCmsContentInfoRef cinfo, + SECAlgorithmID *algid, int keysize); + +/*! + @function + */ +extern void +SecCmsContentInfoSetBulkKey(SecCmsContentInfoRef cinfo, SecSymmetricKeyRef bulkkey); + +/*! + @function + */ +extern SecSymmetricKeyRef +SecCmsContentInfoGetBulkKey(SecCmsContentInfoRef cinfo); + +/*! + @function + */ +extern int +SecCmsContentInfoGetBulkKeySize(SecCmsContentInfoRef cinfo); + + +#if defined(__cplusplus) +} +#endif + +#endif /* _SECURITY_SECCMSCONTENTINFO_H_ */ diff --git a/Security/libsecurity_smime/lib/SecCmsDecoder.h b/Security/libsecurity_smime/lib/SecCmsDecoder.h new file mode 100644 index 00000000..5ba334cf --- /dev/null +++ b/Security/libsecurity_smime/lib/SecCmsDecoder.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecCmsDecoder.h + @Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + + @availability 10.4 and later + @abstract Interfaces of the CMS implementation. + @discussion The functions here implement functions for encoding + and decoding Cryptographic Message Syntax (CMS) objects + as described in rfc3369. + */ + +#ifndef _SECURITY_SECCMSDECODER_H_ +#define _SECURITY_SECCMSDECODER_H_ 1 + +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + + +/*! @functiongroup Streaming interface */ +/*! + @function + @abstract Set up decoding of a BER-encoded CMS message. + @param arena An ArenaPool object to use for the resulting message, or NULL if new ArenaPool + should be created. + @param cb callback function for delivery of inner content inner + content will be stored in the message if cb is NULL. + @param cb_arg first argument passed to cb when it is called. + @param pwfn callback function for getting token password for + enveloped data content with a password recipient. + @param pwfn_arg first argument passed to pwfn when it is called. + @param decrypt_key_cb callback function for getting bulk key + for encryptedData content. + @param decrypt_key_cb_arg first argument passed to decrypt_key_cb + when it is called. + @param outDecoder On success will contain a pointer to a newly created SecCmsDecoder. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion Create a SecCmsDecoder(). If this function returns noErr, the caller must dispose of the returned outDecoder by calling SecCmsDecoderDestroy() or SecCmsDecoderFinish(). + @availability 10.4 and later + @updated 2004-04-05 + */ +extern OSStatus +SecCmsDecoderCreate(SecArenaPoolRef arena, + SecCmsContentCallback cb, void *cb_arg, + PK11PasswordFunc pwfn, void *pwfn_arg, + SecCmsGetDecryptKeyCallback decrypt_key_cb, void + *decrypt_key_cb_arg, + SecCmsDecoderRef *outDecoder); + +/*! + @function + @abstract Feed BER-encoded data to decoder. + @param decoder Pointer to a SecCmsDecoderContext created with SecCmsDecoderCreate(). + @param buf Pointer to bytes to be decoded. + @param len number of bytes to decode. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion If a call to this function fails the caller should call SecCmsDecoderDestroy(). + @availability 10.4 and later + */ +extern OSStatus +SecCmsDecoderUpdate(SecCmsDecoderRef decoder, const void *buf, CFIndex len); + +/*! + @function + @abstract Abort a (presumably failed) decoding process. + @param decoder Pointer to a SecCmsDecoderContext created with SecCmsDecoderCreate(). + @availability 10.4 and later + */ +extern void +SecCmsDecoderDestroy(SecCmsDecoderRef decoder); + +/*! + @function + @abstract Mark the end of inner content and finish decoding. + @param decoder Pointer to a SecCmsDecoderContext created with SecCmsDecoderCreate(). + @param outMessage On success a pointer to a SecCmsMessage containing the decoded message. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion decoder is no longer valid after this function is called. + @availability 10.4 and later + */ +extern OSStatus +SecCmsDecoderFinish(SecCmsDecoderRef decoder, SecCmsMessageRef *outMessage); + +/*! @functiongroup One shot interface */ +/*! + @function + @abstract Decode a CMS message from BER encoded data. + @discussion This function basically does the same as calling + SecCmsDecoderStart(), SecCmsDecoderUpdate() and SecCmsDecoderFinish(). + @param DERmessage Pointer to a CSSM_DATA containing the BER encoded cms + message to decode. + @param cb callback function for delivery of inner content inner + content will be stored in the message if cb is NULL. + @param cb_arg first argument passed to cb when it is called. + @param pwfn callback function for getting token password for enveloped + data content with a password recipient. + @param pwfn_arg first argument passed to pwfn when it is called. + @param decrypt_key_cb callback function for getting bulk key for encryptedData content. + @param decrypt_key_cb_arg first argument passed to decrypt_key_cb when it is called. + @param outMessage On success a pointer to a SecCmsMessage containing the decoded message. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion decoder is no longer valid after this function is called. + @availability 10.4 and later + */ +extern OSStatus +SecCmsMessageDecode(const CSSM_DATA *encodedMessage, + SecCmsContentCallback cb, void *cb_arg, + PK11PasswordFunc pwfn, void *pwfn_arg, + SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg, + SecCmsMessageRef *outMessage); + + +#if defined(__cplusplus) +} +#endif + +#endif /* _SECURITY_SECCMSDECODER_H_ */ diff --git a/Security/libsecurity_smime/lib/SecCmsDigestContext.h b/Security/libsecurity_smime/lib/SecCmsDigestContext.h new file mode 100644 index 00000000..653cf9b5 --- /dev/null +++ b/Security/libsecurity_smime/lib/SecCmsDigestContext.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecCmsDigestContext.h + @Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + + @availability 10.4 and later + @abstract Interfaces of the CMS implementation. + @discussion The functions here implement functions calculating digests. + */ + +#ifndef _SECURITY_SECCMSDIGESTCONTEXT_H_ +#define _SECURITY_SECCMSDIGESTCONTEXT_H_ 1 + +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + + +/*! + @function + @abstract Start digest calculation using all the digest algorithms in "digestalgs" in parallel. + */ +extern SecCmsDigestContextRef +SecCmsDigestContextStartMultiple(SECAlgorithmID **digestalgs); + +/*! + @function + @abstract Feed more data into the digest machine. + */ +extern void +SecCmsDigestContextUpdate(SecCmsDigestContextRef cmsdigcx, const unsigned char *data, size_t len); + +/*! + @function + @abstract Cancel digesting operation. + @discussion Cancel a DigestContext created with @link SecCmsDigestContextStartMultiple SecCmsDigestContextStartMultiple function@/link. + */ +extern void +SecCmsDigestContextCancel(SecCmsDigestContextRef cmsdigcx); + +/*! + @function + @abstract Finish the digests and put them into an array of CSSM_DATAs (allocated on arena) + */ +extern OSStatus +SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, SecArenaPoolRef arena, + CSSM_DATA_PTR **digestsp); + +#if defined(__cplusplus) +} +#endif + +#endif /* _SECURITY_SECCMSDIGESTCONTEXT_H_ */ diff --git a/Security/libsecurity_smime/lib/SecCmsDigestedData.h b/Security/libsecurity_smime/lib/SecCmsDigestedData.h new file mode 100644 index 00000000..4168aff2 --- /dev/null +++ b/Security/libsecurity_smime/lib/SecCmsDigestedData.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecCmsDigestedData.h + @Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + + @availability 10.4 and later + @abstract Interfaces of the CMS implementation. + @discussion The functions here implement functions for creating + and accessing the DigestData content type of a + Cryptographic Message Syntax (CMS) object + as described in rfc3369. + */ + +#ifndef _SECURITY_SECCMSDIGESTEDDATA_H_ +#define _SECURITY_SECCMSDIGESTEDDATA_H_ 1 + +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + + +/*! + @function + @abstract Create a digestedData object (presumably for encoding). + @discussion Version will be set by SecCmsDigestedDataEncodeBeforeStart + digestAlg is passed as parameter + contentInfo must be filled by the user + digest will be calculated while encoding + */ +extern SecCmsDigestedDataRef +SecCmsDigestedDataCreate(SecCmsMessageRef cmsg, SECAlgorithmID *digestalg); + +/*! + @function + @abstract Destroy a digestedData object. + */ +extern void +SecCmsDigestedDataDestroy(SecCmsDigestedDataRef digd); + +/*! + @function + @abstract Return pointer to digestedData object's contentInfo. + */ +extern SecCmsContentInfoRef +SecCmsDigestedDataGetContentInfo(SecCmsDigestedDataRef digd); + + +#if defined(__cplusplus) +} +#endif + +#endif /* _SECURITY_SECCMSDIGESTEDDATA_H_ */ diff --git a/Security/libsecurity_smime/lib/SecCmsEncoder.h b/Security/libsecurity_smime/lib/SecCmsEncoder.h new file mode 100644 index 00000000..681f3ae8 --- /dev/null +++ b/Security/libsecurity_smime/lib/SecCmsEncoder.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecCmsEncoder.h + @Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. + + @availability 10.4 and later + @abstract CMS message encoding + @discussion The functions here implement functions for encoding + Cryptographic Message Syntax (CMS) objects as described + in rfc3369. + A SecCmsEncoder object is used to encode CMS messages into BER. + */ + +#ifndef _SECURITY_SECCMSENCODER_H_ +#define _SECURITY_SECCMSENCODER_H_ 1 + +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + + +/*! @functiongroup Streaming interface */ +/*! + @function + @abstract Set up encoding of a CMS message. + @param outputfn callback function for delivery of BER-encoded output will + not be called if NULL. + @param outputarg first argument passed to outputfn when it is called. + @param dest If non-NULL, pointer to a CSSM_DATA that will hold the + BER-encoded output. + @param destpoolp Pool to allocate BER-encoded output in. + @param pwfn callback function for getting token password for enveloped + data content with a password recipient. + @param pwfn_arg first argument passed to pwfn when it is called. + @param encrypt_key_cb callback function for getting bulk key for encryptedData content. + @param encrypt_key_cb_arg first argument passed to encrypt_key_cb when it is + called. + @param detached_digestalgs digest algorithms in detached_digests + @param detached_digests digests from detached content (one for every element + in detached_digestalgs). + @result On success a pointer to a SecCmsMessage containing the decoded message + is returned. On failure returns NULL. Call PR_GetError() to find out what + went wrong in this case. + @availability 10.4 and later + */ +extern OSStatus +SecCmsEncoderCreate(SecCmsMessageRef cmsg, + SecCmsContentCallback outputfn, void *outputarg, + CSSM_DATA_PTR dest, SecArenaPoolRef destpoolp, + PK11PasswordFunc pwfn, void *pwfn_arg, + SecCmsGetDecryptKeyCallback encrypt_key_cb, void *encrypt_key_cb_arg, + SECAlgorithmID **detached_digestalgs, CSSM_DATA_PTR *detached_digests, + SecCmsEncoderRef *outEncoder); + +/*! + @function + @abstract Take content data delivery from the user + @param encoder encoder context + @param data content data + @param len length of content data + @result On success 0 is returned. On failure returns non zero. Call + PR_GetError() to find out what went wrong in this case. + @availability 10.4 and later + */ +extern OSStatus +SecCmsEncoderUpdate(SecCmsEncoderRef encoder, const void *data, CFIndex len); + +/*! + @function + @abstract Abort a (presumably failed) encoding process. + @param encoder Pointer to a SecCmsEncoderContext created with SecCmsEncoderCreate(). + @availability 10.4 and later + */ +extern void +SecCmsEncoderDestroy(SecCmsEncoderRef encoder); + +/*! + @function + @abstract Signal the end of data. + @discussion Walks down the chain of encoders and the finishes them from the + innermost out. + @param encoder Pointer to a SecCmsEncoder created with SecCmsEncoderCreate(). + @result On success 0 is returned. On failure returns non zero. Call + PR_GetError() to find out what went wrong in this case. + @availability 10.4 and later + */ +extern OSStatus +SecCmsEncoderFinish(SecCmsEncoderRef encoder); + +/*! @functiongroup One shot interface */ +/*! + @function + @abstract BER Encode a CMS message. + @discussion BER Encode a CMS message, with input being the plaintext message and outBer being the output, stored in arena's pool. + */ +extern OSStatus +SecCmsMessageEncode(SecCmsMessageRef cmsg, const CSSM_DATA *input, SecArenaPoolRef arena, + CSSM_DATA_PTR outBer); + +#if defined(__cplusplus) +} +#endif + +#endif /* _SECURITY_SECCMSENCODER_H_ */ diff --git a/Security/libsecurity_smime/lib/SecCmsEncryptedData.h b/Security/libsecurity_smime/lib/SecCmsEncryptedData.h new file mode 100644 index 00000000..84ada6c8 --- /dev/null +++ b/Security/libsecurity_smime/lib/SecCmsEncryptedData.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecCmsEnvelopedData.h + @Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + + @availability 10.4 and later + @abstract Interfaces of the CMS implementation. + @discussion The functions here implement functions for encoding + and decoding Cryptographic Message Syntax (CMS) objects + as described in rfc3369. + */ + +#ifndef _SECURITY_SECCMSENCRYPTEDDATA_H_ +#define _SECURITY_SECCMSENCRYPTEDDATA_H_ 1 + +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + + +/*! + @function + @abstract Create an empty EncryptedData object. + @param algorithm Specifies the bulk encryption algorithm to use. + @param keysize is the key size. + @discussion An error results in a return value of NULL and an error set. + (Retrieve specific errors via PORT_GetError()/XP_GetError().) + */ +extern SecCmsEncryptedDataRef +SecCmsEncryptedDataCreate(SecCmsMessageRef cmsg, SECOidTag algorithm, int keysize); + +/*! + @function + @abstract Destroy an encryptedData object. + */ +extern void +SecCmsEncryptedDataDestroy(SecCmsEncryptedDataRef encd); + +/*! + @function + @abstract Return pointer to an EncryptedData object's contentInfo. + */ +extern SecCmsContentInfoRef +SecCmsEncryptedDataGetContentInfo(SecCmsEncryptedDataRef encd); + + +#if defined(__cplusplus) +} +#endif + +#endif /* _SECURITY_SECCMSENCRYPTEDDATA_H_ */ diff --git a/Security/libsecurity_smime/lib/SecCmsEnvelopedData.h b/Security/libsecurity_smime/lib/SecCmsEnvelopedData.h new file mode 100644 index 00000000..d19a752a --- /dev/null +++ b/Security/libsecurity_smime/lib/SecCmsEnvelopedData.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecCmsEnvelopedData.h + @Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + + @availability 10.4 and later + @abstract Interfaces of the CMS implementation. + @discussion The functions here implement functions for encoding + and decoding Cryptographic Message Syntax (CMS) objects + as described in rfc3369. + */ + +#ifndef _SECURITY_SECCMSENVELOPEDDATA_H_ +#define _SECURITY_SECCMSENVELOPEDDATA_H_ 1 + +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + + +/*! + @function + @abstract Create an enveloped data message. + */ +extern SecCmsEnvelopedDataRef +SecCmsEnvelopedDataCreate(SecCmsMessageRef cmsg, SECOidTag algorithm, int keysize); + +/*! + @function + @abstract Destroy an enveloped data message. + */ +extern void +SecCmsEnvelopedDataDestroy(SecCmsEnvelopedDataRef edp); + +/*! + @function + @abstract Return pointer to this envelopedData's contentinfo. + */ +extern SecCmsContentInfoRef +SecCmsEnvelopedDataGetContentInfo(SecCmsEnvelopedDataRef envd); + +/*! + @function + @abstract Add a recipientinfo to the enveloped data msg. + @discussion Rip must be created on the same pool as edp - this is not enforced, though. + */ +extern OSStatus +SecCmsEnvelopedDataAddRecipient(SecCmsEnvelopedDataRef edp, SecCmsRecipientInfoRef rip); + + +#if defined(__cplusplus) +} +#endif + +#endif /* _SECURITY_SECCMSENVELOPEDDATA_H_ */ diff --git a/Security/libsecurity_smime/lib/SecCmsMessage.h b/Security/libsecurity_smime/lib/SecCmsMessage.h new file mode 100644 index 00000000..39aa7275 --- /dev/null +++ b/Security/libsecurity_smime/lib/SecCmsMessage.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecCmsMessage.h + @Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. + + @availability 10.4 and later + @abstract CMS message object interfaces + @abstract Interfaces of the CMS implementation. + @discussion A SecCmsMessage represent a Cryptographic Message + Syntax (CMS) object as described in rfc3369. + It can be encoded using a SecCmsEncoder into BER + data or obtained from a SecCmsDecoder and examined + using the functions below. + */ + +#ifndef _SECURITY_SECCMSMESSAGE_H_ +#define _SECURITY_SECCMSMESSAGE_H_ 1 + +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + + +/*! + @function + @abstract Create a CMS message object. + @param poolp Arena to allocate memory from, or NULL if new arena should + be created. + @result A pointer to a newly created SecCmsMessage. When finished using + this the caller should call SecCmsMessageDestroy(). On failure + returns NULL. In this case call PR_GetError() to find out what went + wrong. + */ +extern SecCmsMessageRef +SecCmsMessageCreate(SecArenaPoolRef poolp); + +/*! + @function + @abstract Destroy a CMS message and all of its sub-pieces. + @param cmsg Pointer to a SecCmsMessage object. + */ +extern void +SecCmsMessageDestroy(SecCmsMessageRef cmsg); + +/*! + @function + @abstract Return a copy of the given message. + @discussion The copy may be virtual or may be real -- either way, the + result needs to be passed to SecCmsMessageDestroy later (as does the + original). + @param cmsg Pointer to a SecCmsMessage object. + */ +extern SecCmsMessageRef +SecCmsMessageCopy(SecCmsMessageRef cmsg); + +/*! + @function + @abstract Return a pointer to the message's arena pool. + */ +extern SecArenaPoolRef +SecCmsMessageGetArena(SecCmsMessageRef cmsg); + +/*! + @function + @abstract Return a pointer to the top level contentInfo. + */ +extern SecCmsContentInfoRef +SecCmsMessageGetContentInfo(SecCmsMessageRef cmsg); + +/*! + @function + @abstract Return a pointer to the actual content. + @discussion In the case of those types which are encrypted, this returns the *plain* content. + In case of nested contentInfos, this descends and retrieves the innermost content. + */ +extern CSSM_DATA_PTR +SecCmsMessageGetContent(SecCmsMessageRef cmsg); + +/*! + @function + @abstract Count number of levels of CMS content objects in this message. + @discussion CMS data content objects do not count. + */ +extern int +SecCmsMessageContentLevelCount(SecCmsMessageRef cmsg); + +/*! + @function + @abstract Find content level #n. + @discussion CMS data content objects do not count. + */ +extern SecCmsContentInfoRef +SecCmsMessageContentLevel(SecCmsMessageRef cmsg, int n); + +/*! + @function + @abstract See if message contains certs along the way. + */ +extern Boolean +SecCmsMessageContainsCertsOrCrls(SecCmsMessageRef cmsg); + +/*! + @function + @abstract See if message contains a encrypted submessage. + */ +extern Boolean +SecCmsMessageIsEncrypted(SecCmsMessageRef cmsg); + +/*! + @function + @abstract See if message contains a signed submessage + @discussion If the CMS message has a SignedData with a signature (not just a SignedData) + return true; false otherwise. This can/should be called before calling + VerifySignature, which will always indicate failure if no signature is + present, but that does not mean there even was a signature! + Note that the content itself can be empty (detached content was sent + another way); it is the presence of the signature that matters. + */ +extern Boolean +SecCmsMessageIsSigned(SecCmsMessageRef cmsg); + +/*! + @function + @abstract See if content is empty. + @result Returns PR_TRUE is innermost content length is < minLen + @discussion XXX need the encrypted content length (why?) + */ +extern Boolean +SecCmsMessageIsContentEmpty(SecCmsMessageRef cmsg, unsigned int minLen); + +extern Boolean +SecCmsMessageContainsTSTInfo(SecCmsMessageRef cmsg); + +#if defined(__cplusplus) +} +#endif + +#endif /* _SECURITY_SECCMSMESSAGE_H_ */ diff --git a/Security/libsecurity_smime/lib/SecCmsRecipientInfo.h b/Security/libsecurity_smime/lib/SecCmsRecipientInfo.h new file mode 100644 index 00000000..805ec221 --- /dev/null +++ b/Security/libsecurity_smime/lib/SecCmsRecipientInfo.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecCmsRecipientInfo.h + @Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + + @availability 10.4 and later + @abstract Interfaces of the CMS implementation. + @discussion The functions here implement functions for encoding + and decoding Cryptographic Message Syntax (CMS) objects + as described in rfc3369. + */ + +#ifndef _SECURITY_SECCMSRECIPIENTINFO_H_ +#define _SECURITY_SECCMSRECIPIENTINFO_H_ 1 + +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + + +/*! + @function + @abstract Create a recipientinfo + @discussion We currently do not create KeyAgreement recipientinfos with multiple recipientEncryptedKeys + the certificate is supposed to have been verified by the caller + */ +extern SecCmsRecipientInfoRef +SecCmsRecipientInfoCreate(SecCmsMessageRef cmsg, SecCertificateRef cert); + +/*! + @function + */ +extern SecCmsRecipientInfoRef +SecCmsRecipientInfoCreateWithSubjKeyID(SecCmsMessageRef cmsg, + CSSM_DATA_PTR subjKeyID, + SecPublicKeyRef pubKey); + +/*! + @function + */ +extern SecCmsRecipientInfoRef +SecCmsRecipientInfoCreateWithSubjKeyIDFromCert(SecCmsMessageRef cmsg, + SecCertificateRef cert); + +/*! + @function + */ +extern void +SecCmsRecipientInfoDestroy(SecCmsRecipientInfoRef ri); + + +#if defined(__cplusplus) +} +#endif + +#endif /* _SECURITY_SECCMSRECIPIENTINFO_H_ */ diff --git a/Security/libsecurity_smime/lib/SecCmsSignedData.h b/Security/libsecurity_smime/lib/SecCmsSignedData.h new file mode 100644 index 00000000..e7680fa2 --- /dev/null +++ b/Security/libsecurity_smime/lib/SecCmsSignedData.h @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecCmsSignedData.h + @Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + + @availability 10.4 and later + @abstract Interfaces of the CMS implementation. + @discussion The functions here implement functions for encoding + and decoding Cryptographic Message Syntax (CMS) objects + as described in rfc3369. + */ + +#ifndef _SECURITY_SECCMSSIGNEDDATA_H_ +#define _SECURITY_SECCMSSIGNEDDATA_H_ 1 + +#include +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + @function + @abstract Create a new SecCmsSignedData object. + @param cmsg Pointer to a SecCmsMessage in which this SecCmsSignedData + should be created. + */ +extern SecCmsSignedDataRef +SecCmsSignedDataCreate(SecCmsMessageRef cmsg); + +/*! + @function + */ +extern void +SecCmsSignedDataDestroy(SecCmsSignedDataRef sigd); + +/*! + @function + @abstract Retrieve the SignedData's signer list. + */ +extern SecCmsSignerInfoRef * +SecCmsSignedDataGetSignerInfos(SecCmsSignedDataRef sigd); + +/*! + @function + */ +extern int +SecCmsSignedDataSignerInfoCount(SecCmsSignedDataRef sigd); + +/*! + @function + */ +extern SecCmsSignerInfoRef +SecCmsSignedDataGetSignerInfo(SecCmsSignedDataRef sigd, int i); + +/*! + @function + @abstract Retrieve the SignedData's digest algorithm list. + */ +extern SECAlgorithmID ** +SecCmsSignedDataGetDigestAlgs(SecCmsSignedDataRef sigd); + +/*! + @function + @abstract Return pointer to this signedData's contentinfo. + */ +extern SecCmsContentInfoRef +SecCmsSignedDataGetContentInfo(SecCmsSignedDataRef sigd); + +/*! + @function + @discussion XXX Should be obsoleted. + */ +extern OSStatus +SecCmsSignedDataImportCerts(SecCmsSignedDataRef sigd, SecKeychainRef keychain, + SECCertUsage certusage, Boolean keepcerts); + +/*! + @function + @abstract See if we have digests in place. + */ +extern Boolean +SecCmsSignedDataHasDigests(SecCmsSignedDataRef sigd); + +/*! + @function + @abstract Check the signatures. + @discussion The digests were either calculated during decoding (and are stored in the + signedData itself) or set after decoding using SecCmsSignedDataSetDigests. + + The verification checks if the signing cert is valid and has a trusted chain + for the purpose specified by "policies". + + If trustRef is NULL the cert chain is verified and the VerificationStatus is set accordingly. + Otherwise a SecTrust object is returned for the caller to evaluate using SecTrustEvaluate(). + */ +extern OSStatus +SecCmsSignedDataVerifySignerInfo(SecCmsSignedDataRef sigd, int i, SecKeychainRef keychainOrArray, + CFTypeRef policies, SecTrustRef *trustRef); + +/*! + @function + @abstract Verify the certs in a certs-only message. +*/ +extern OSStatus +SecCmsSignedDataVerifyCertsOnly(SecCmsSignedDataRef sigd, + SecKeychainRef keychainOrArray, + CFTypeRef policies); + +/*! + @function + */ +extern OSStatus +SecCmsSignedDataAddCertList(SecCmsSignedDataRef sigd, CFArrayRef certlist); + +/*! + @function + @abstract Add cert and its entire chain to the set of certs. + */ +extern OSStatus +SecCmsSignedDataAddCertChain(SecCmsSignedDataRef sigd, SecCertificateRef cert); + +/*! + @function + */ +extern OSStatus +SecCmsSignedDataAddCertificate(SecCmsSignedDataRef sigd, SecCertificateRef cert); + +/*! + @function + */ +extern Boolean +SecCmsSignedDataContainsCertsOrCrls(SecCmsSignedDataRef sigd); + +/*! + @function + @abstract Retrieve the SignedData's certificate list. + */ +extern CSSM_DATA_PTR * +SecCmsSignedDataGetCertificateList(SecCmsSignedDataRef sigd); + +/*! + @function + */ +extern OSStatus +SecCmsSignedDataAddSignerInfo(SecCmsSignedDataRef sigd, + SecCmsSignerInfoRef signerinfo); + +/*! + @function + */ +extern OSStatus +SecCmsSignedDataSetDigests(SecCmsSignedDataRef sigd, + SECAlgorithmID **digestalgs, + CSSM_DATA_PTR *digests); + +/*! + @function + @abstract Create a certs-only SignedData. + @param cert Base certificate that will be included + @param include_chain If true, include the complete cert chain for cert. + @discussion More certs and chains can be added via AddCertificate and AddCertChain. + @result An error results in a return value of NULL and an error set. + */ +extern SecCmsSignedDataRef +SecCmsSignedDataCreateCertsOnly(SecCmsMessageRef cmsg, SecCertificateRef cert, Boolean include_chain); + + +#if defined(__cplusplus) +} +#endif + +#endif /* _SECURITY_SECCMSSIGNEDDATA_H_ */ diff --git a/Security/libsecurity_smime/lib/SecCmsSignerInfo.h b/Security/libsecurity_smime/lib/SecCmsSignerInfo.h new file mode 100644 index 00000000..ebacbf12 --- /dev/null +++ b/Security/libsecurity_smime/lib/SecCmsSignerInfo.h @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecCmsSignerInfo.h + @Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. + + @availability 10.4 and later + @abstract Interfaces of the CMS implementation. + @discussion The functions here implement functions for encoding + and decoding Cryptographic Message Syntax (CMS) objects + as described in rfc3369. + */ + +#ifndef _SECURITY_SECCMSSIGNERINFO_H_ +#define _SECURITY_SECCMSSIGNERINFO_H_ 1 + +#include + +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + @function + */ +extern SecCmsSignerInfoRef +SecCmsSignerInfoCreate(SecCmsMessageRef cmsg, SecIdentityRef identity, SECOidTag digestalgtag); + +/*! + @function + */ +extern SecCmsSignerInfoRef +SecCmsSignerInfoCreateWithSubjKeyID(SecCmsMessageRef cmsg, CSSM_DATA_PTR subjKeyID, SecPublicKeyRef pubKey, SecPrivateKeyRef signingKey, SECOidTag digestalgtag); + +/*! + @function + @abstract Destroy a SignerInfo data structure. + */ +extern void +SecCmsSignerInfoDestroy(SecCmsSignerInfoRef si); + +/*! + @function + */ +extern SecCmsVerificationStatus +SecCmsSignerInfoGetVerificationStatus(SecCmsSignerInfoRef signerinfo); + +/*! + @function + */ +extern OSStatus +SecCmsSignerInfoVerifyUnAuthAttrs(SecCmsSignerInfoRef signerinfo); + +/*! + @function + */ +extern OSStatus +SecCmsSignerInfoVerifyUnAuthAttrsWithPolicy(SecCmsSignerInfoRef signerinfo,CFTypeRef timeStampPolicy); + +/*! + @function + */ +extern CSSM_DATA * +SecCmsSignerInfoGetEncDigest(SecCmsSignerInfoRef signerinfo); + +/*! + @function + */ +extern SECOidData * +SecCmsSignerInfoGetDigestAlg(SecCmsSignerInfoRef signerinfo); + +/*! + @function + */ +extern SECOidTag +SecCmsSignerInfoGetDigestAlgTag(SecCmsSignerInfoRef signerinfo); + +/*! + @function + */ +extern CFArrayRef +SecCmsSignerInfoGetCertList(SecCmsSignerInfoRef signerinfo); + +/*! + @function + */ +extern CFArrayRef +SecCmsSignerInfoGetTimestampCertList(SecCmsSignerInfoRef signerinfo); + +/*! + @function + @abstract Return the signing time, in UTCTime format, of a CMS signerInfo. + @param sinfo SignerInfo data for this signer. + @discussion Returns a pointer to XXXX (what?) + @result A return value of NULL is an error. + */ +extern OSStatus +SecCmsSignerInfoGetSigningTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *stime); + +/*! + @function + @abstract Return the timestamp time, in UTCTime format, of a CMS signerInfo. + @param sinfo SignerInfo data for this signer. + @discussion Returns a pointer to XXXX (what?) + @result A return value of NULL is an error. + */ +OSStatus +SecCmsSignerInfoGetTimestampTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *stime); + +/*! + @function + @abstract Return the timestamp time, in UTCTime format, of a CMS signerInfo. + @param sinfo SignerInfo data for this signer, timeStampPolicy the policy to verify the timestamp signer + @discussion Returns a pointer to XXXX (what?) + @result A return value of NULL is an error. + */ +OSStatus +SecCmsSignerInfoGetTimestampTimeWithPolicy(SecCmsSignerInfoRef sinfo, CFTypeRef timeStampPolicy, CFAbsoluteTime *stime); + +/*! + @function + @abstract Return the signing cert of a CMS signerInfo. + @discussion The certs in the enclosing SignedData must have been imported already. + */ +extern SecCertificateRef +SecCmsSignerInfoGetSigningCertificate(SecCmsSignerInfoRef signerinfo, SecKeychainRef keychainOrArray); + +/*! + @function + @abstract Return the common name of the signer. + @param sinfo SignerInfo data for this signer. + @discussion Returns a CFStringRef containing the common name of the signer. + @result A return value of NULL is an error. + */ +extern CFStringRef +SecCmsSignerInfoGetSignerCommonName(SecCmsSignerInfoRef sinfo); + +/*! + @function + @abstract Return the email address of the signer + @param sinfo SignerInfo data for this signer. + @discussion Returns a CFStringRef containing the name of the signer. + @result A return value of NULL is an error. + */ +extern CFStringRef +SecCmsSignerInfoGetSignerEmailAddress(SecCmsSignerInfoRef sinfo); + +/*! + @function + @abstract Add the signing time to the authenticated (i.e. signed) attributes of "signerinfo". + @discussion This is expected to be included in outgoing signed + messages for email (S/MIME) but is likely useful in other situations. + + This should only be added once; a second call will do nothing. + + XXX This will probably just shove the current time into "signerinfo" + but it will not actually get signed until the entire item is + processed for encoding. Is this (expected to be small) delay okay? + */ +extern OSStatus +SecCmsSignerInfoAddSigningTime(SecCmsSignerInfoRef signerinfo, CFAbsoluteTime t); + +/*! + @function + @abstract Add a SMIMECapabilities attribute to the authenticated (i.e. signed) attributes of "signerinfo". + @discussion This is expected to be included in outgoing signed messages for email (S/MIME). + */ +extern OSStatus +SecCmsSignerInfoAddSMIMECaps(SecCmsSignerInfoRef signerinfo); + +/*! + @function + @abstract Add a SMIMEEncryptionKeyPreferences attribute to the authenticated (i.e. signed) attributes of "signerinfo". + @discussion This is expected to be included in outgoing signed messages for email (S/MIME). + */ +OSStatus +SecCmsSignerInfoAddSMIMEEncKeyPrefs(SecCmsSignerInfoRef signerinfo, SecCertificateRef cert, SecKeychainRef keychainOrArray); + +/*! + @function + @abstract Add a SMIMEEncryptionKeyPreferences attribute to the authenticated (i.e. signed) attributes of "signerinfo", using the OID prefered by Microsoft. + @discussion This is expected to be included in outgoing signed messages for email (S/MIME), if compatibility with Microsoft mail clients is wanted. + */ +OSStatus +SecCmsSignerInfoAddMSSMIMEEncKeyPrefs(SecCmsSignerInfoRef signerinfo, SecCertificateRef cert, SecKeychainRef keychainOrArray); + +/*! + @function + @abstract Create a timestamp unsigned attribute with a TimeStampToken. + */ +OSStatus +SecCmsSignerInfoAddTimeStamp(SecCmsSignerInfoRef signerinfo, CSSM_DATA *tstoken); + +/*! + @function + @abstract Countersign a signerinfo. + */ +extern OSStatus +SecCmsSignerInfoAddCounterSignature(SecCmsSignerInfoRef signerinfo, + SECOidTag digestalg, SecIdentityRef identity); + +/*! + @function + @abstract The following needs to be done in the S/MIME layer code after signature of a signerinfo has been verified. + @param signerinfo The SecCmsSignerInfo object for which we verified the signature. + @result The preferred encryption certificate of the user who signed this message will be added to the users default Keychain and it will be marked as the preferred certificate to use when sending that person messages from now on. + */ +extern OSStatus +SecCmsSignerInfoSaveSMIMEProfile(SecCmsSignerInfoRef signerinfo); + +/*! + @function + @abstract Set cert chain inclusion mode for this signer. + */ +extern OSStatus +SecCmsSignerInfoIncludeCerts(SecCmsSignerInfoRef signerinfo, SecCmsCertChainMode cm, SECCertUsage usage); + +/*! @functiongroup CMS misc utility functions */ +/*! + @function + Convert a SecCmsVerificationStatus to a human readable string. + */ +extern const char * +SecCmsUtilVerificationStatusToString(SecCmsVerificationStatus vs); + +/* + * Preference domain and key for the Microsoft ECDSA compatibility flag. + * Default if not present is TRUE, meaning we generate ECDSA-signed messages + * which are compatible with Microsoft Entourage. FALSE means we adhere to + * the spec (RFC 3278 section 2.1.1). + */ +#define kMSCompatibilityDomain "com.apple.security.smime" +#define kMSCompatibilityMode CFSTR("MSCompatibilityMode") + +#if defined(__cplusplus) +} +#endif + +#endif /* _SECURITY_SECCMSSIGNERINFO_H_ */ diff --git a/Security/libsecurity_smime/lib/SecSMIME.h b/Security/libsecurity_smime/lib/SecSMIME.h new file mode 100644 index 00000000..7027c179 --- /dev/null +++ b/Security/libsecurity_smime/lib/SecSMIME.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecSMIME.h + @Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + + @availability 10.4 and later + @abstract S/MIME Specific routines. + @discussion Header file for routines specific to S/MIME. Keep + things that are pure pkcs7 out of here; this is for + S/MIME policy, S/MIME interoperability, etc. +*/ + +#ifndef _SECURITY_SECSMIME_H_ +#define _SECURITY_SECSMIME_H_ 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + @function + @abstract Find bulk algorithm suitable for all recipients. + */ +extern OSStatus +SecSMIMEFindBulkAlgForRecipients(SecCertificateRef *rcerts, SECOidTag *bulkalgtag, int *keysize); + + +#ifdef __cplusplus +} +#endif + +#endif /* _SECURITY_SECSMIME_H_ */ diff --git a/Security/libsecurity_smime/lib/SecSMIMEPriv.h b/Security/libsecurity_smime/lib/SecSMIMEPriv.h new file mode 100644 index 00000000..8888e49b --- /dev/null +++ b/Security/libsecurity_smime/lib/SecSMIMEPriv.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecSMIMEPriv.h + @Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + + @availability 10.4 and later + @abstract Private S/MIME Specific routines. + @discussion Header file for routines specific to S/MIME. Keep + things that are pure pkcs7 out of here; this is for + S/MIME policy, S/MIME interoperability, etc. +*/ + +#ifndef _SECURITY_SECSMIMEPRIV_H_ +#define _SECURITY_SECSMIMEPRIV_H_ 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Cipher family IDs used for configuring ciphers for export control + */ + +/* Cipher Suite "Families" */ +#define CIPHER_FAMILYID_MASK 0xFFFF0000L +#define CIPHER_FAMILYID_SMIME 0x00010000L + +/* SMIME "Cipher Suites" */ +/* + * Note that it is assumed that the cipher number itself can be used + * as a bit position in a mask, and that mask is currently 32 bits wide. + * So, if you want to add a cipher that is greater than 0033, secmime.c + * needs to be made smarter at the same time. + */ +#define SMIME_RC2_CBC_40 (CIPHER_FAMILYID_SMIME | 0001) +#define SMIME_RC2_CBC_64 (CIPHER_FAMILYID_SMIME | 0002) +#define SMIME_RC2_CBC_128 (CIPHER_FAMILYID_SMIME | 0003) +#define SMIME_DES_CBC_56 (CIPHER_FAMILYID_SMIME | 0011) +#define SMIME_DES_EDE3_168 (CIPHER_FAMILYID_SMIME | 0012) +#define SMIME_AES_CBC_128 (CIPHER_FAMILYID_SMIME | 0013) +#define SMIME_RC5PAD_64_16_40 (CIPHER_FAMILYID_SMIME | 0021) +#define SMIME_RC5PAD_64_16_64 (CIPHER_FAMILYID_SMIME | 0022) +#define SMIME_RC5PAD_64_16_128 (CIPHER_FAMILYID_SMIME | 0023) +#define SMIME_FORTEZZA (CIPHER_FAMILYID_SMIME | 0031) + + +/* + * Initialize the local recording of the user S/MIME cipher preferences. + * This function is called once for each cipher, the order being + * important (first call records greatest preference, and so on). + * When finished, it is called with a "which" of CIPHER_FAMILID_MASK. + * If the function is called again after that, it is assumed that + * the preferences are being reset, and the old preferences are + * discarded. + * + * XXX This is for a particular user, and right now the storage is + * XXX local, static. The preference should be stored elsewhere to allow + * XXX for multiple uses of one library? How does SSL handle this; + * XXX it has something similar? + * + * - The "which" values are defined in ciferfam.h (the SMIME_* values, + * for example SMIME_DES_CBC_56). + * - If "on" is non-zero then the named cipher is enabled, otherwise + * it is disabled. (It is not necessary to call the function for + * ciphers that are disabled, however, as that is the default.) + * + * If the cipher preference is successfully recorded, SECSuccess + * is returned. Otherwise SECFailure is returned. The only errors + * are due to failure allocating memory or bad parameters/calls: + * SEC_ERROR_XXX ("which" is not in the S/MIME cipher family) + * SEC_ERROR_XXX (function is being called more times than there + * are known/expected ciphers) + */ +extern OSStatus SecSMIMEEnableCipher(uint32 which, Boolean on); + +/* + * Initialize the local recording of the S/MIME policy. + * This function is called to allow/disallow a particular cipher. + * + * XXX This is for a the current module, I think, so local, static storage + * XXX is okay. Is that correct, or could multiple uses of the same + * XXX library expect to operate under different policies? + * + * - The "which" values are defined in ciferfam.h (the SMIME_* values, + * for example SMIME_DES_CBC_56). + * - If "on" is non-zero then the named cipher is enabled, otherwise + * it is disabled. + */ +extern OSStatus SecSMIMEAllowCipher(uint32 which, Boolean on); + +/* + * Does the current policy allow S/MIME decryption of this particular + * algorithm and keysize? + */ +extern Boolean SecSMIMEDecryptionAllowed(SECAlgorithmID *algid, SecSymmetricKeyRef key); + +/* + * Does the current policy allow *any* S/MIME encryption (or decryption)? + * + * This tells whether or not *any* S/MIME encryption can be done, + * according to policy. Callers may use this to do nicer user interface + * (say, greying out a checkbox so a user does not even try to encrypt + * a message when they are not allowed to) or for any reason they want + * to check whether S/MIME encryption (or decryption, for that matter) + * may be done. + * + * It takes no arguments. The return value is a simple boolean: + * PR_TRUE means encryption (or decryption) is *possible* + * (but may still fail due to other reasons, like because we cannot + * find all the necessary certs, etc.; PR_TRUE is *not* a guarantee) + * PR_FALSE means encryption (or decryption) is not permitted + * + * There are no errors from this routine. + */ +extern Boolean SecSMIMEEncryptionPossible(void); + +/* + * SecSMIMECreateSMIMECapabilities - get S/MIME capabilities attr value + * + * scans the list of allowed and enabled ciphers and construct a PKCS9-compliant + * S/MIME capabilities attribute value. + */ +extern OSStatus SecSMIMECreateSMIMECapabilities(SecArenaPoolRef pool, CSSM_DATA_PTR dest, Boolean includeFortezzaCiphers); + +/* + * SecSMIMECreateSMIMEEncKeyPrefs - create S/MIME encryption key preferences attr value + */ +extern OSStatus SecSMIMECreateSMIMEEncKeyPrefs(SecArenaPoolRef pool, CSSM_DATA_PTR dest, SecCertificateRef cert); + +/* + * SecSMIMECreateMSSMIMEEncKeyPrefs - create S/MIME encryption key preferences attr value using MS oid + */ +extern OSStatus SecSMIMECreateMSSMIMEEncKeyPrefs(SecArenaPoolRef pool, CSSM_DATA_PTR dest, SecCertificateRef cert); + +/* + * SecSMIMEGetCertFromEncryptionKeyPreference - find cert marked by EncryptionKeyPreference + * attribute + */ +extern SecCertificateRef SecSMIMEGetCertFromEncryptionKeyPreference(SecKeychainRef keychainOrArray, CSSM_DATA_PTR DERekp); + + +#ifdef __cplusplus +} +#endif + +#endif /* _SECURITY_SECSMIMEPRIV_H_ */ diff --git a/Security/libsecurity_smime/lib/cert.c b/Security/libsecurity_smime/lib/cert.c new file mode 100644 index 00000000..adf30c15 --- /dev/null +++ b/Security/libsecurity_smime/lib/cert.c @@ -0,0 +1,828 @@ +/* + * Copyright (c) 2003,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@ + */ + + +#include "cert.h" +#include "cmstpriv.h" +#include "cmslocal.h" +#include "secitem.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* for errKCDuplicateItem */ +#include + +#define CERT_DEBUG 0 +#if CERT_DEBUG +#define dprintf(args...) printf(args) +#else +#define dprintf(args...) +#endif + +/* @@@ Remove this once it's back in the appropriate header. */ +static const uint8 X509V1IssuerNameStd[] = {INTEL_X509V3_CERT_R08, 23}; +static const CSSM_OID OID_X509V1IssuerNameStd = {INTEL_X509V3_CERT_R08_LENGTH+1, (uint8 *)X509V1IssuerNameStd}; + +/* + * Normalize a Printable String. Per RFC2459 (4.1.2.4), printable strings are case + * insensitive and we're supposed to ignore leading and trailing + * whitespace, and collapse multiple whitespace characters into one. + */ +static void +CERT_NormalizeString(CSSM_DATA_PTR string) +{ + char *pD, *pCh, *pEos; + + if (!string->Length) + return; + + pD = pCh = (char *)string->Data; + pEos = pCh + string->Length - 1; + + /* Strip trailing NULL terminators */ + while(*pEos == 0) + pEos--; + + /* Remove trailing spaces */ + while(isspace(*pEos)) + pEos--; + + /* Point to one past last non-space character */ + pEos++; + + /* skip all leading whitespace */ + while(isspace(*pCh) && (pCh < pEos)) + pCh++; + + /* Eliminate multiple whitespace and convent to upper case. + * pCh points to first non-white char. + * pD still points to start of string. */ + while(pCh < pEos) + { + char ch = *pCh++; + *pD++ = toupper(ch); + if(isspace(ch)) + { + /* skip 'til next nonwhite */ + while(isspace(*pCh) && (pCh < pEos)) + pCh++; + } + } + + string->Length = pD - (char *)string->Data; +} + +/* + * Normalize an RDN. Per RFC2459 (4.1.2.4), printable strings are case + * insensitive and we're supposed to ignore leading and trailing + * whitespace, and collapse multiple whitespace characters into one. + * + * Incoming NSS_Name is assumed to be entirely within specifed coder's + * address space; we'll be munging some of that and possibly replacing + * some pointers with others allocated from the same space. + */ +void +CERT_NormalizeX509NameNSS(NSS_Name *nssName) +{ + NSS_RDN *rdn; + + for (rdn = *nssName->rdns; rdn; ++rdn) + { + NSS_ATV *attr; + for (attr = *rdn->atvs; attr; ++attr) + { + /* + * attr->value is an ASN_ANY containing an encoded + * string. We only normalize Prinatable String types. + * If we find one, decode it, normalize it, encode the + * result, and put the encoding back in attr->value. + * We temporarily "leak" the original string, which only + * has a lifetime of the incoming SecNssCoder. + */ + NSS_TaggedItem *attrVal = &attr->value; + if(attrVal->tag != SEC_ASN1_PRINTABLE_STRING) + continue; + + CERT_NormalizeString(&attrVal->item); + } + } +} + +SecCertificateRef CERT_FindCertByNicknameOrEmailAddr(SecKeychainRef keychainOrArray, char *name) +{ + SecCertificateRef certificate; + OSStatus status=SecCertificateFindByEmail(keychainOrArray,name,&certificate); + return status==noErr?certificate:NULL; +} + +SecPublicKeyRef SECKEY_CopyPublicKey(SecPublicKeyRef pubKey) +{ + CFRetain(pubKey); + return pubKey; +} + +void SECKEY_DestroyPublicKey(SecPublicKeyRef pubKey) +{ + CFRelease(pubKey); +} + +SecPublicKeyRef SECKEY_CopyPrivateKey(SecPublicKeyRef privKey) +{ + CFRetain(privKey); + return privKey; +} + +void SECKEY_DestroyPrivateKey(SecPublicKeyRef privKey) +{ + CFRelease(privKey); +} + +void CERT_DestroyCertificate(SecCertificateRef cert) +{ + CFRelease(cert); +} + +SecCertificateRef CERT_DupCertificate(SecCertificateRef cert) +{ + CFRetain(cert); + return cert; +} + +SecIdentityRef CERT_FindIdentityByUsage(SecKeychainRef keychainOrArray, + char *nickname, SECCertUsage usage, Boolean validOnly, void *proto_win) +{ + SecIdentityRef identityRef = NULL; + SecCertificateRef cert = CERT_FindCertByNicknameOrEmailAddr(keychainOrArray, nickname); + if (!cert) + return NULL; + + SecIdentityCreateWithCertificate(keychainOrArray, cert, &identityRef); + CFRelease(cert); + + return identityRef; +} + +SecCertificateRef CERT_FindUserCertByUsage(SecKeychainRef keychainOrArray, + char *nickname,SECCertUsage usage,Boolean validOnly,void *proto_win) +{ + SecItemClass itemClass = kSecCertificateItemClass; + SecKeychainSearchRef searchRef; + SecKeychainItemRef itemRef = NULL; + OSStatus status; + SecKeychainAttribute attrs[1]; + const char *serialNumber = "12345678"; + // const SecKeychainAttributeList attrList; +#if 0 + attrs[1].tag = kSecLabelItemAttr; + attrs[1].length = strlen(nickname)+1; + attrs[1].data = nickname; +#else + attrs[1].tag = kSecSerialNumberItemAttr; + attrs[1].length = (UInt32)strlen(serialNumber)+1; + attrs[1].data = (uint8 *)serialNumber; +#endif + SecKeychainAttributeList attrList = { 0, attrs }; + // 12 34 56 78 + status = SecKeychainSearchCreateFromAttributes(keychainOrArray,itemClass,&attrList,&searchRef); + if (status) + { + printf("CERT_FindUserCertByUsage: SecKeychainSearchCreateFromAttributes:%d",(int)status); + return NULL; + } + status = SecKeychainSearchCopyNext(searchRef,&itemRef); + if (status) + printf("CERT_FindUserCertByUsage: SecKeychainSearchCopyNext:%d",(int)status); + CFRelease(searchRef); + return (SecCertificateRef)itemRef; +} + +/* +startNewClass(X509Certificate) +CertType, kSecCertTypeItemAttr, "CertType", 0, NULL, UINT32) +CertEncoding, kSecCertEncodingItemAttr, "CertEncoding", 0, NULL, UINT32) +PrintName, kSecLabelItemAttr, "PrintName", 0, NULL, BLOB) +Alias, kSecAlias, "Alias", 0, NULL, BLOB) +Subject, kSecSubjectItemAttr, "Subject", 0, NULL, BLOB) +Issuer, kSecIssuerItemAttr, "Issuer", 0, NULL, BLOB) +SerialNumber, kSecSerialNumberItemAttr, "SerialNumber", 0, NULL, BLOB) +SubjectKeyIdentifier, kSecSubjectKeyIdentifierItemAttr, "SubjectKeyIdentifier", 0, NULL, BLOB) +PublicKeyHash, kSecPublicKeyHashItemAttr, "PublicKeyHash", 0, NULL, BLOB) +endNewClass() +*/ + +CFArrayRef CERT_CertChainFromCert(SecCertificateRef cert, SECCertUsage usage, Boolean includeRoot) +{ + SecPolicySearchRef searchRef = NULL; + SecPolicyRef policy = NULL; + CFArrayRef wrappedCert = NULL; + SecTrustRef trust = NULL; + CFArrayRef certChain = NULL; + CSSM_TP_APPLE_EVIDENCE_INFO *statusChain; + CFDataRef actionData = NULL; + OSStatus status = 0; + + if (!cert) + goto loser; + + status = SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_X509_BASIC, NULL, &searchRef); + if (status) + goto loser; + status = SecPolicySearchCopyNext(searchRef, &policy); + if (status) + goto loser; + + wrappedCert = CERT_CertListFromCert(cert); + status = SecTrustCreateWithCertificates(wrappedCert, policy, &trust); + if (status) + goto loser; + + /* Tell SecTrust that we don't care if any certs in the chain have expired, + nor do we want to stop when encountering a cert with a trust setting; + we always want to build the full chain. + */ + CSSM_APPLE_TP_ACTION_DATA localActionData = { + CSSM_APPLE_TP_ACTION_VERSION, + CSSM_TP_ACTION_ALLOW_EXPIRED | CSSM_TP_ACTION_ALLOW_EXPIRED_ROOT + }; + actionData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)&localActionData, sizeof(localActionData), kCFAllocatorNull); + if (!actionData) + goto loser; + + status = SecTrustSetParameters(trust, CSSM_TP_ACTION_DEFAULT, actionData); + if (status) + goto loser; + + status = SecTrustEvaluate(trust, NULL); + if (status) + goto loser; + + status = SecTrustGetResult(trust, NULL, &certChain, &statusChain); + if (status) + goto loser; + + /* We don't drop the root if there is only 1 (self signed) certificate in the chain. */ + if (!includeRoot && CFArrayGetCount(certChain) > 1) + { + CFMutableArrayRef subChain = CFArrayCreateMutableCopy(NULL, 0, certChain); + CFRelease(certChain); + certChain = subChain; + if (subChain) + CFArrayRemoveValueAtIndex(subChain, CFArrayGetCount(subChain) - 1); + } + +loser: + if (searchRef) + CFRelease(searchRef); + if (policy) + CFRelease(policy); + if (wrappedCert) + CFRelease(wrappedCert); + if (trust) + CFRelease(trust); + if (actionData) + CFRelease(actionData); + if (certChain && status) + { + CFRelease(certChain); + certChain = NULL; + } + + return certChain; +} + +CFArrayRef CERT_CertListFromCert(SecCertificateRef cert) +{ + const void *value = cert; + return cert ? CFArrayCreate(NULL, &value, 1, &kCFTypeArrayCallBacks) : NULL; +} + +CFArrayRef CERT_DupCertList(CFArrayRef oldList) +{ + CFRetain(oldList); + return oldList; +} + +// Extract a public key object from a SubjectPublicKeyInfo +SecPublicKeyRef CERT_ExtractPublicKey(SecCertificateRef cert) +{ + SecPublicKeyRef keyRef = NULL; + SecCertificateCopyPublicKey(cert,&keyRef); + return keyRef; +} + +SECStatus CERT_CheckCertUsage (SecCertificateRef cert,unsigned char usage) +{ + // abort(); + // @@@ It's all good, it's ok. + return SECSuccess; +} + +// Find a certificate in the database by a email address +// "emailAddr" is the email address to look up +SecCertificateRef CERT_FindCertByEmailAddr(SecKeychainRef keychainOrArray, char *emailAddr) +{ + abort(); + return NULL; +} + +// Find a certificate in the database by a DER encoded certificate +// "derCert" is the DER encoded certificate +SecCertificateRef CERT_FindCertByDERCert(SecKeychainRef keychainOrArray, const SECItem *derCert) +{ + // @@@ Technically this should look though keychainOrArray for a cert matching this one I guess. + SecCertificateRef cert = NULL; + OSStatus rv; + + rv = SecCertificateCreateFromData(derCert, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &cert); + if (rv && cert) + { + PORT_SetError(SEC_ERROR_NO_EMAIL_CERT); + CFRelease(cert); + cert = NULL; + } + + return cert; +} + +static int compareCssmData( + const CSSM_DATA *d1, + const CSSM_DATA *d2) +{ + if((d1 == NULL) || (d2 == NULL)) { + return 0; + } + if(d1->Length != d2->Length) { + return 0; + } + if(memcmp(d1->Data, d2->Data, d1->Length)) { + return 0; + } + return 1; +} + +// Generate a certificate key from the issuer and serialnumber, then look it up in the database. +// Return the cert if found. "issuerAndSN" is the issuer and serial number to look for +SecCertificateRef CERT_FindCertByIssuerAndSN (CFTypeRef keychainOrArray, + CSSM_DATA_PTR *rawCerts, PRArenaPool *pl, const SecCmsIssuerAndSN *issuerAndSN) +{ + SecCertificateRef certificate; + int numRawCerts = SecCmsArrayCount((void **)rawCerts); + int dex; + OSStatus ortn; + + /* + * First search the rawCerts array. + */ + for(dex=0; dexderIssuer, &issuerAndSN->derIssuer)) { + CFRelease(certificate); + continue; + } + if(!compareCssmData(&isn->serialNumber, &issuerAndSN->serialNumber)) { + CFRelease(certificate); + continue; + } + /* got it */ + dprintf("CERT_FindCertByIssuerAndSN: found cert %p\n", certificate); + return certificate; + } + + /* now search keychain(s) */ + OSStatus status = SecCertificateFindByIssuerAndSN(keychainOrArray, &issuerAndSN->derIssuer, + &issuerAndSN->serialNumber, &certificate); + if (status) + { + PORT_SetError(SEC_ERROR_NO_EMAIL_CERT); + certificate = NULL; + } + + return certificate; +} + +SecCertificateRef CERT_FindCertBySubjectKeyID (CFTypeRef keychainOrArray, + CSSM_DATA_PTR *rawCerts, const SECItem *subjKeyID) +{ + SecCertificateRef certificate; + int numRawCerts = SecCmsArrayCount((void **)rawCerts); + int dex; + OSStatus ortn; + SECItem skid; + + /* + * First search the rawCerts array. + */ + for(dex=0; dexdata. +SECStatus CERT_FindSubjectKeyIDExtension (SecCertificateRef cert, SECItem *retItem) +{ + CSSM_DATA_PTR fieldValue = NULL; + OSStatus ortn; + CSSM_X509_EXTENSION *extp; + CE_SubjectKeyID *skid; + + ortn = SecCertificateCopyFirstFieldValue(cert, &CSSMOID_SubjectKeyIdentifier, + &fieldValue); + if(ortn || (fieldValue == NULL)) { + /* this cert doesn't have that extension */ + return SECFailure; + } + extp = (CSSM_X509_EXTENSION *)fieldValue->Data; + skid = (CE_SubjectKeyID *)extp->value.parsedValue; + retItem->Data = (uint8 *)PORT_Alloc(skid->Length); + retItem->Length = skid->Length; + memmove(retItem->Data, skid->Data, retItem->Length); + SecCertificateReleaseFirstFieldValue(cert, &CSSMOID_SubjectKeyIdentifier, + fieldValue); + return SECSuccess; +} + +// Extract the issuer and serial number from a certificate +SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef cert) +{ + OSStatus status; + SecCmsIssuerAndSN *certIssuerAndSN; + CSSM_CL_HANDLE clHandle; + CSSM_DATA_PTR serialNumber = 0; + CSSM_DATA_PTR issuer = 0; + CSSM_DATA certData = {}; + CSSM_HANDLE resultsHandle = 0; + uint32 numberOfFields = 0; + CSSM_RETURN result; + void *mark; + + mark = PORT_ArenaMark(pl); + + status = SecCertificateGetCLHandle(cert, &clHandle); + if (status) + goto loser; + status = SecCertificateGetData(cert, &certData); + if (status) + goto loser; + + /* Get the issuer from the cert. */ + result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, + &OID_X509V1IssuerNameStd, &resultsHandle, &numberOfFields, &issuer); + + if (result || numberOfFields < 1) + goto loser; + result = CSSM_CL_CertAbortQuery(clHandle, resultsHandle); + if (result) + goto loser; + + + /* Get the serialNumber from the cert. */ + result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, + &CSSMOID_X509V1SerialNumber, &resultsHandle, &numberOfFields, &serialNumber); + if (result || numberOfFields < 1) + goto loser; + result = CSSM_CL_CertAbortQuery(clHandle, resultsHandle); + if (result) + goto loser; + + /* Allocate the SecCmsIssuerAndSN struct. */ + certIssuerAndSN = (SecCmsIssuerAndSN *)PORT_ArenaZAlloc (pl, sizeof(SecCmsIssuerAndSN)); + if (certIssuerAndSN == NULL) + goto loser; + + /* Copy the issuer. */ + certIssuerAndSN->derIssuer.Data = (uint8 *) PORT_ArenaAlloc(pl, issuer->Length); + if (!certIssuerAndSN->derIssuer.Data) + goto loser; + PORT_Memcpy(certIssuerAndSN->derIssuer.Data, issuer->Data, issuer->Length); + certIssuerAndSN->derIssuer.Length = issuer->Length; + + /* Copy the serialNumber. */ + certIssuerAndSN->serialNumber.Data = (uint8 *) PORT_ArenaAlloc(pl, serialNumber->Length); + if (!certIssuerAndSN->serialNumber.Data) + goto loser; + PORT_Memcpy(certIssuerAndSN->serialNumber.Data, serialNumber->Data, serialNumber->Length); + certIssuerAndSN->serialNumber.Length = serialNumber->Length; + + PORT_ArenaUnmark(pl, mark); + + CSSM_CL_FreeFieldValue(clHandle, &CSSMOID_X509V1SerialNumber, serialNumber); + CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer); + + return certIssuerAndSN; + +loser: + PORT_ArenaRelease(pl, mark); + + if (serialNumber) + CSSM_CL_FreeFieldValue(clHandle, &CSSMOID_X509V1SerialNumber, serialNumber); + if (issuer) + CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer); + + PORT_SetError(SEC_INTERNAL_ONLY); + return NULL; +} + +// import a collection of certs into the temporary or permanent cert database +SECStatus CERT_ImportCerts(SecKeychainRef keychain, SECCertUsage usage, unsigned int ncerts, + SECItem **derCerts, SecCertificateRef **retCerts, Boolean keepCerts, Boolean caOnly, char *nickname) +{ + OSStatus rv = SECFailure; + SecCertificateRef cert; + unsigned int ci; + + // @@@ Do something with caOnly and nickname + if (caOnly || nickname) + abort(); + + for (ci = 0; ci < ncerts; ++ci) + { + rv = SecCertificateCreateFromData(derCerts[ci], CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &cert); + if (rv) + break; + if (keepCerts) + { + rv = SecCertificateAddToKeychain(cert, keychain); + if (rv) + { + if (rv == errKCDuplicateItem) + rv = noErr; + else + { + CFRelease(cert); + break; + } + } + } + + if (retCerts) + { + // @@@ not yet + abort(); + } + else + CFRelease(cert); + } + + return rv; +} + +SECStatus CERT_SaveSMimeProfile(SecCertificateRef cert, SECItem *emailProfile,SECItem *profileTime) +{ + fprintf(stderr, "WARNING: CERT_SaveSMimeProfile unimplemented\n"); + return SECSuccess; +} + +// Check the hostname to make sure that it matches the shexp that +// is given in the common name of the certificate. +SECStatus CERT_VerifyCertName(SecCertificateRef cert, const char *hostname) +{ + fprintf(stderr, "WARNING: CERT_VerifyCertName unimplemented\n"); + return SECSuccess; +} + +/* +** OLD OBSOLETE FUNCTIONS with enum SECCertUsage - DO NOT USE FOR NEW CODE +** verify a certificate by checking validity times against a certain time, +** that we trust the issuer, and that the signature on the certificate is +** valid. +** "cert" the certificate to verify +** "checkSig" only check signatures if true +*/ +SECStatus +CERT_VerifyCert(SecKeychainRef keychainOrArray, SecCertificateRef cert, + const CSSM_DATA_PTR *otherCerts, /* intermediates */ + CFTypeRef policies, CFAbsoluteTime stime, SecTrustRef *trustRef) +{ + CFMutableArrayRef certificates = NULL; + SecTrustRef trust = NULL; + OSStatus rv; + int numOtherCerts = SecCmsArrayCount((void **)otherCerts); + int dex; + + /* + * Certs to evaluate: first the leaf - our cert - then all the rest we know + * about. It's OK for otherCerts to contain a copy of the leaf. + */ + certificates = CFArrayCreateMutable(NULL, numOtherCerts + 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue(certificates, cert); + for(dex=0; dex +#include +#include +#include +#include +#include "cmstpriv.h" + +/************************************************************************/ +SEC_BEGIN_PROTOS + +typedef void CERTVerifyLog; + +void CERT_NormalizeX509NameNSS(NSS_Name *nssName); + +SecIdentityRef CERT_FindIdentityByUsage(SecKeychainRef keychainOrArray, + char *nickname, SECCertUsage usage, Boolean validOnly, void *proto_win); + +SecCertificateRef CERT_FindUserCertByUsage(SecKeychainRef dbhandle, + char *nickname,SECCertUsage usage,Boolean validOnly,void *proto_win); + +// Find a certificate in the database by a email address or nickname +// "name" is the email address or nickname to look up +SecCertificateRef CERT_FindCertByNicknameOrEmailAddr(SecKeychainRef dbhandle, char *name); + +SecPublicKeyRef SECKEY_CopyPublicKey(SecPublicKeyRef pubKey); +void SECKEY_DestroyPublicKey(SecPublicKeyRef pubKey); +SecPublicKeyRef SECKEY_CopyPrivateKey(SecPublicKeyRef privKey); +void SECKEY_DestroyPrivateKey(SecPublicKeyRef privKey); +void CERT_DestroyCertificate(SecCertificateRef cert); +SecCertificateRef CERT_DupCertificate(SecCertificateRef cert); + +// from security/nss/lib/certdb/cert.h + +/* + Substitutions: + CERTCertificate * -> SecCertificateRef + SECKEYPublicKey * -> SecPublicKeyRef + CERTCertDBHandle * -> SecKeychainRef + CERT_GetDefaultCertDB -> OSStatus SecKeychainCopyDefault(SecKeychainRef *keychain); + CERTCertificateList * -> CFArrayRef +*/ + +// Generate a certificate chain from a certificate. + +CFArrayRef CERT_CertChainFromCert(SecCertificateRef cert, SECCertUsage usage,Boolean includeRoot); + +CFArrayRef CERT_CertListFromCert(SecCertificateRef cert); + +CFArrayRef CERT_DupCertList(CFArrayRef oldList); + +// Extract a public key object from a SubjectPublicKeyInfo +SecPublicKeyRef CERT_ExtractPublicKey(SecCertificateRef cert); + +SECStatus CERT_CheckCertUsage (SecCertificateRef cert,unsigned char usage); + +// Find a certificate in the database by a email address +// "emailAddr" is the email address to look up +SecCertificateRef CERT_FindCertByEmailAddr(SecKeychainRef keychainOrArray, char *emailAddr); + +// Find a certificate in the database by a DER encoded certificate +// "derCert" is the DER encoded certificate +SecCertificateRef CERT_FindCertByDERCert(SecKeychainRef keychainOrArray, const SECItem *derCert); + +// Generate a certificate key from the issuer and serialnumber, then look it up in the database. +// Return the cert if found. "issuerAndSN" is the issuer and serial number to look for +SecCertificateRef CERT_FindCertByIssuerAndSN (CFTypeRef keychainOrArray, + CSSM_DATA_PTR *rawCerts, PRArenaPool *pl, const SecCmsIssuerAndSN *issuerAndSN); + +SecCertificateRef CERT_FindCertBySubjectKeyID (CFTypeRef keychainOrArray, + CSSM_DATA_PTR *rawCerts, const SECItem *subjKeyID); + +SecIdentityRef CERT_FindIdentityByIssuerAndSN (CFTypeRef keychainOrArray, const SecCmsIssuerAndSN *issuerAndSN); + +SecIdentityRef CERT_FindIdentityBySubjectKeyID (CFTypeRef keychainOrArray, const SECItem *subjKeyID); + +// find the smime symmetric capabilities profile for a given cert +SECItem *CERT_FindSMimeProfile(SecCertificateRef cert); + +// Return the decoded value of the subjectKeyID extension. The caller should +// free up the storage allocated in retItem->data. +SECStatus CERT_FindSubjectKeyIDExtension (SecCertificateRef cert, SECItem *retItem); + +// Extract the issuer and serial number from a certificate +SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef cert); + +// import a collection of certs into the temporary or permanent cert database +SECStatus CERT_ImportCerts(SecKeychainRef keychain, SECCertUsage usage,unsigned int ncerts, + SECItem **derCerts,SecCertificateRef **retCerts, Boolean keepCerts,Boolean caOnly, char *nickname); + +SECStatus CERT_SaveSMimeProfile(SecCertificateRef cert, SECItem *emailProfile,SECItem *profileTime); + +// Check the hostname to make sure that it matches the shexp that +// is given in the common name of the certificate. +SECStatus CERT_VerifyCertName(SecCertificateRef cert, const char *hostname); + +SECStatus CERT_VerifyCert(SecKeychainRef keychainOrArray, SecCertificateRef cert, + const CSSM_DATA_PTR *otherCerts, /* intermediates */ + CFTypeRef policies, CFAbsoluteTime stime, SecTrustRef *trustRef); + +CFTypeRef CERT_PolicyForCertUsage(SECCertUsage certUsage); + +/************************************************************************/ +SEC_END_PROTOS + +#endif /* _CERT_H_ */ diff --git a/Security/libsecurity_smime/lib/cmsarray.c b/Security/libsecurity_smime/lib/cmsarray.c new file mode 100644 index 00000000..56984fed --- /dev/null +++ b/Security/libsecurity_smime/lib/cmsarray.c @@ -0,0 +1,214 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * CMS array functions. + */ + +#include "cmslocal.h" + +#include + +/* + * ARRAY FUNCTIONS + * + * In NSS, arrays are rather primitive arrays of pointers. + * Makes it easy to walk the array, but hard to count elements + * and manage the storage. + * + * This is a feeble attempt to encapsulate the functionality + * and get rid of hundreds of lines of similar code + */ + +/* + * SecCmsArrayAlloc - allocate an array in an arena + * + * This allocates space for the array of pointers + */ +void ** +SecCmsArrayAlloc(PRArenaPool *poolp, int n) +{ + return (void **)PORT_ArenaZAlloc(poolp, n * sizeof(void *)); +} + +/* + * SecCmsArrayAdd - add an element to the end of an array + * + * The array of pointers is either created (if array was empty before) or grown. + */ +OSStatus +SecCmsArrayAdd(PRArenaPool *poolp, void ***array, void *obj) +{ + void **p; + int n; + void **dest; + + PORT_Assert(array != NULL); + if (array == NULL) + return SECFailure; + + if (*array == NULL) { + dest = (void **)PORT_ArenaAlloc(poolp, 2 * sizeof(void *)); + n = 0; + } else { + n = 0; p = *array; + while (*p++) + n++; + dest = (void **)PORT_ArenaGrow (poolp, + *array, + (n + 1) * sizeof(void *), + (n + 2) * sizeof(void *)); + } + + if (dest == NULL) + return SECFailure; + + dest[n] = obj; + dest[n+1] = NULL; + *array = dest; + return SECSuccess; +} + +/* + * SecCmsArrayIsEmpty - check if array is empty + */ +Boolean +SecCmsArrayIsEmpty(void **array) +{ + return (array == NULL || array[0] == NULL); +} + +/* + * SecCmsArrayCount - count number of elements in array + */ +int +SecCmsArrayCount(void **array) +{ + int n = 0; + + if (array == NULL) + return 0; + + while (*array++ != NULL) + n++; + + return n; +} + +/* + * SecCmsArraySort - sort an array in place + * + * If "secondary" or "tertiary are not NULL, it must be arrays with the same + * number of elements as "primary". The same reordering will get applied to it. + * + * "compare" is a function that returns + * < 0 when the first element is less than the second + * = 0 when the first element is equal to the second + * > 0 when the first element is greater than the second + * to acheive ascending ordering. + */ +void +SecCmsArraySort(void **primary, int (*compare)(void *,void *), void **secondary, void **tertiary) +{ + int n, i, limit, lastxchg; + void *tmp; + + n = SecCmsArrayCount(primary); + + PORT_Assert(secondary == NULL || SecCmsArrayCount(secondary) == n); + PORT_Assert(tertiary == NULL || SecCmsArrayCount(tertiary) == n); + + if (n <= 1) /* ordering is fine */ + return; + + /* yes, ladies and gentlemen, it's BUBBLE SORT TIME! */ + limit = n - 1; + while (1) { + lastxchg = 0; + for (i = 0; i < limit; i++) { + if ((*compare)(primary[i], primary[i+1]) > 0) { + /* exchange the neighbours */ + tmp = primary[i+1]; + primary[i+1] = primary[i]; + primary[i] = tmp; + if (secondary) { /* secondary array? */ + tmp = secondary[i+1]; /* exchange there as well */ + secondary[i+1] = secondary[i]; + secondary[i] = tmp; + } + if (tertiary) { /* tertiary array? */ + tmp = tertiary[i+1]; /* exchange there as well */ + tertiary[i+1] = tertiary[i]; + tertiary[i] = tmp; + } + lastxchg = i+1; /* index of the last element bubbled up */ + } + } + if (lastxchg == 0) /* no exchanges, so array is sorted */ + break; /* we're done */ + limit = lastxchg; /* array is sorted up to [limit] */ + } +} + +#if 0 + +/* array iterator stuff... not used */ + +typedef void **SecCmsArrayIterator; + +/* iterator */ +SecCmsArrayIterator +SecCmsArrayFirst(void **array) +{ + if (array == NULL || array[0] == NULL) + return NULL; + return (SecCmsArrayIterator)&(array[0]); +} + +void * +SecCmsArrayObj(SecCmsArrayIterator iter) +{ + void **p = (void **)iter; + + return *iter; /* which is NULL if we are at the end of the array */ +} + +SecCmsArrayIterator +SecCmsArrayNext(SecCmsArrayIterator iter) +{ + void **p = (void **)iter; + + return (SecCmsArrayIterator)(p + 1); +} + +#endif diff --git a/Security/libsecurity_smime/lib/cmsasn1.c b/Security/libsecurity_smime/lib/cmsasn1.c new file mode 100644 index 00000000..6e8a3eba --- /dev/null +++ b/Security/libsecurity_smime/lib/cmsasn1.c @@ -0,0 +1,599 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * CMS ASN.1 templates + */ + +#include + +#include "cmslocal.h" + +#include "secoid.h" +#include +#include + + +extern const SecAsn1Template nss_cms_set_of_attribute_template[]; + +//SEC_ASN1_MKSUB(CERT_IssuerAndSNTemplate) +//SEC_ASN1_MKSUB(CERT_SetOfSignedCrlTemplate) +SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) +SEC_ASN1_MKSUB(kSecAsn1BitStringTemplate) +SEC_ASN1_MKSUB(kSecAsn1OctetStringTemplate) +SEC_ASN1_MKSUB(kSecAsn1PointerToOctetStringTemplate) +SEC_ASN1_MKSUB(kSecAsn1SetOfAnyTemplate) + +/* ----------------------------------------------------------------------------- + * MESSAGE + * (uses SecCmsContentInfo) + */ + +/* forward declaration */ +static const SecAsn1Template * +nss_cms_choose_content_template(void *src_or_dest, Boolean encoding, const char *buf, void *dest); + +static const SecAsn1TemplateChooserPtr nss_cms_chooser + = nss_cms_choose_content_template; + +const SecAsn1Template SecCmsMessageTemplate[] = { + { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, + 0, NULL, sizeof(SecCmsMessage) }, + { SEC_ASN1_OBJECT_ID, + offsetof(SecCmsMessage,contentInfo.contentType) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_DYNAMIC | SEC_ASN1_MAY_STREAM + | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(SecCmsMessage,contentInfo.content), + &nss_cms_chooser }, + { 0 } +}; + +#if 0 +static const SecAsn1Template NSS_PointerToCMSMessageTemplate[] = { + { SEC_ASN1_POINTER, 0, SecCmsMessageTemplate } +}; +#endif + +/* ----------------------------------------------------------------------------- + * ENCAPSULATED & ENCRYPTED CONTENTINFO + * (both use a SecCmsContentInfo) + */ +static const SecAsn1Template SecCmsEncapsulatedContentInfoTemplate[] = { + { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, + 0, NULL, sizeof(SecCmsContentInfo) }, + { SEC_ASN1_OBJECT_ID, + offsetof(SecCmsContentInfo,contentType) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | SEC_ASN1_MAY_STREAM | + SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, + offsetof(SecCmsContentInfo,rawContent), + SEC_ASN1_SUB(kSecAsn1PointerToOctetStringTemplate) }, + { 0 } +}; + +static const SecAsn1Template SecCmsEncryptedContentInfoTemplate[] = { + { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, + 0, NULL, sizeof(SecCmsContentInfo) }, + { SEC_ASN1_OBJECT_ID, + offsetof(SecCmsContentInfo,contentType) }, + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, + offsetof(SecCmsContentInfo,contentEncAlg), + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_POINTER | SEC_ASN1_MAY_STREAM | + SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, + offsetof(SecCmsContentInfo,rawContent), + SEC_ASN1_SUB(kSecAsn1OctetStringTemplate) }, + { 0 } +}; + +/* ----------------------------------------------------------------------------- + * SIGNED DATA + */ + +const SecAsn1Template SecCmsSignerInfoTemplate[]; + + +const SecAsn1Template SecCmsSignedDataTemplate[] = { + { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, + 0, NULL, sizeof(SecCmsSignedData) }, + { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT, + offsetof(SecCmsSignedData,version) }, + { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, + offsetof(SecCmsSignedData,digestAlgorithms), + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, + { SEC_ASN1_INLINE, + offsetof(SecCmsSignedData,contentInfo), + SecCmsEncapsulatedContentInfoTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_XTRN | 0, + offsetof(SecCmsSignedData,rawCerts), + SEC_ASN1_SUB(kSecAsn1SetOfAnyTemplate) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_XTRN | 1, + offsetof(SecCmsSignedData,rawCrls), + SEC_ASN1_SUB(kSecAsn1SetOfAnyTemplate) }, + { SEC_ASN1_SET_OF, + offsetof(SecCmsSignedData,signerInfos), + SecCmsSignerInfoTemplate }, + { 0 } +}; + +const SecAsn1Template NSS_PointerToCMSSignedDataTemplate[] = { + { SEC_ASN1_POINTER, 0, SecCmsSignedDataTemplate } +}; + +/* ----------------------------------------------------------------------------- + * signeridentifier + */ + +static const SecAsn1Template SecCmsSignerIdentifierTemplate[] = { + { SEC_ASN1_CHOICE, + offsetof(SecCmsSignerIdentifier,identifierType), NULL, + sizeof(SecCmsSignerIdentifier) }, + { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, + offsetof(SecCmsSignerIdentifier,id.subjectKeyID), + SEC_ASN1_SUB(kSecAsn1OctetStringTemplate) , + SecCmsRecipientIDSubjectKeyID }, + { SEC_ASN1_POINTER | SEC_ASN1_XTRN, + offsetof(SecCmsSignerIdentifier,id.issuerAndSN), + SEC_ASN1_SUB(SecCmsIssuerAndSNTemplate), + SecCmsRecipientIDIssuerSN }, + { 0 } +}; + +/* ----------------------------------------------------------------------------- + * signerinfo + */ + +const SecAsn1Template SecCmsSignerInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecCmsSignerInfo) }, + { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT, + offsetof(SecCmsSignerInfo,version) }, + { SEC_ASN1_INLINE, + offsetof(SecCmsSignerInfo,signerIdentifier), + SecCmsSignerIdentifierTemplate }, + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, + offsetof(SecCmsSignerInfo,digestAlg), + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(SecCmsSignerInfo,authAttr), + nss_cms_set_of_attribute_template }, + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, + offsetof(SecCmsSignerInfo,digestEncAlg), + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, + { SEC_ASN1_OCTET_STRING, + offsetof(SecCmsSignerInfo,encDigest) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, + offsetof(SecCmsSignerInfo,unAuthAttr), + nss_cms_set_of_attribute_template }, + { 0 } +}; + +/* ----------------------------------------------------------------------------- + * ENVELOPED DATA + */ + +static const SecAsn1Template SecCmsOriginatorInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecCmsOriginatorInfo) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_XTRN | 0, + offsetof(SecCmsOriginatorInfo,rawCerts), + SEC_ASN1_SUB(kSecAsn1SetOfAnyTemplate) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_XTRN | 1, + offsetof(SecCmsOriginatorInfo,rawCrls), + SEC_ASN1_SUB(kSecAsn1SetOfAnyTemplate) }, + { 0 } +}; + +const SecAsn1Template SecCmsRecipientInfoTemplate[]; + +const SecAsn1Template SecCmsEnvelopedDataTemplate[] = { + { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, + 0, NULL, sizeof(SecCmsEnvelopedData) }, + { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT, + offsetof(SecCmsEnvelopedData,version) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_POINTER | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(SecCmsEnvelopedData,originatorInfo), + SecCmsOriginatorInfoTemplate }, + { SEC_ASN1_SET_OF, + offsetof(SecCmsEnvelopedData,recipientInfos), + SecCmsRecipientInfoTemplate }, + { SEC_ASN1_INLINE, + offsetof(SecCmsEnvelopedData,contentInfo), + SecCmsEncryptedContentInfoTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, + offsetof(SecCmsEnvelopedData,unprotectedAttr), + nss_cms_set_of_attribute_template }, + { 0 } +}; + +const SecAsn1Template NSS_PointerToCMSEnvelopedDataTemplate[] = { + { SEC_ASN1_POINTER, 0, SecCmsEnvelopedDataTemplate } +}; + +/* here come the 15 gazillion templates for all the v3 varieties of RecipientInfo */ + +/* ----------------------------------------------------------------------------- + * key transport recipient info + */ + +static const SecAsn1Template SecCmsRecipientIdentifierTemplate[] = { + { SEC_ASN1_CHOICE, + offsetof(SecCmsRecipientIdentifier,identifierType), NULL, + sizeof(SecCmsRecipientIdentifier) }, + { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_XTRN | 0, + offsetof(SecCmsRecipientIdentifier,id.subjectKeyID), + SEC_ASN1_SUB(kSecAsn1PointerToOctetStringTemplate) , + SecCmsRecipientIDSubjectKeyID }, + { SEC_ASN1_POINTER | SEC_ASN1_XTRN, + offsetof(SecCmsRecipientIdentifier,id.issuerAndSN), + SEC_ASN1_SUB(SecCmsIssuerAndSNTemplate), + SecCmsRecipientIDIssuerSN }, + { 0 } +}; + + +static const SecAsn1Template SecCmsKeyTransRecipientInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecCmsKeyTransRecipientInfo) }, + { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT, + offsetof(SecCmsKeyTransRecipientInfo,version) }, + { SEC_ASN1_INLINE, + offsetof(SecCmsKeyTransRecipientInfo,recipientIdentifier), + SecCmsRecipientIdentifierTemplate }, + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, + offsetof(SecCmsKeyTransRecipientInfo,keyEncAlg), + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, + { SEC_ASN1_OCTET_STRING, + offsetof(SecCmsKeyTransRecipientInfo,encKey) }, + { 0 } +}; + +/* ----------------------------------------------------------------------------- + * key agreement recipient info + */ + +static const SecAsn1Template SecCmsOriginatorPublicKeyTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecCmsOriginatorPublicKey) }, + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, + offsetof(SecCmsOriginatorPublicKey,algorithmIdentifier), + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, + offsetof(SecCmsOriginatorPublicKey,publicKey), + SEC_ASN1_SUB(kSecAsn1BitStringTemplate) }, + { 0 } +}; + + +static const SecAsn1Template SecCmsOriginatorIdentifierOrKeyTemplate[] = { + { SEC_ASN1_CHOICE, + offsetof(SecCmsOriginatorIdentifierOrKey,identifierType), NULL, + sizeof(SecCmsOriginatorIdentifierOrKey) }, + { SEC_ASN1_POINTER | SEC_ASN1_XTRN, + offsetof(SecCmsOriginatorIdentifierOrKey,id.issuerAndSN), + SEC_ASN1_SUB(SecCmsIssuerAndSNTemplate), + SecCmsOriginatorIDOrKeyIssuerSN }, + { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | + /* this was tag 1 here, 2 for the next; RFC 3852 says they are 0 and 1 */ + SEC_ASN1_XTRN | 0, + offsetof(SecCmsOriginatorIdentifierOrKey,id.subjectKeyID), + kSecAsn1OctetStringTemplate, + SecCmsOriginatorIDOrKeySubjectKeyID }, + { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, + offsetof(SecCmsOriginatorIdentifierOrKey,id.originatorPublicKey), + SecCmsOriginatorPublicKeyTemplate, + SecCmsOriginatorIDOrKeyOriginatorPublicKey }, + { 0 } +}; + +const SecAsn1Template SecCmsRecipientKeyIdentifierTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecCmsRecipientKeyIdentifier) }, + { SEC_ASN1_OCTET_STRING, + offsetof(SecCmsRecipientKeyIdentifier,subjectKeyIdentifier) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_OCTET_STRING, + offsetof(SecCmsRecipientKeyIdentifier,date) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_OCTET_STRING, + offsetof(SecCmsRecipientKeyIdentifier,other) }, + { 0 } +}; + + +static const SecAsn1Template SecCmsKeyAgreeRecipientIdentifierTemplate[] = { + { SEC_ASN1_CHOICE, + offsetof(SecCmsKeyAgreeRecipientIdentifier,identifierType), NULL, + sizeof(SecCmsKeyAgreeRecipientIdentifier) }, + { SEC_ASN1_POINTER | SEC_ASN1_XTRN, + offsetof(SecCmsKeyAgreeRecipientIdentifier,id.issuerAndSN), + SEC_ASN1_SUB(SecCmsIssuerAndSNTemplate), + SecCmsKeyAgreeRecipientIDIssuerSN }, + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(SecCmsKeyAgreeRecipientIdentifier,id.recipientKeyIdentifier), + SecCmsRecipientKeyIdentifierTemplate, + SecCmsKeyAgreeRecipientIDRKeyID }, + { 0 } +}; + +static const SecAsn1Template SecCmsRecipientEncryptedKeyTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecCmsRecipientEncryptedKey) }, + { SEC_ASN1_INLINE, + offsetof(SecCmsRecipientEncryptedKey,recipientIdentifier), + SecCmsKeyAgreeRecipientIdentifierTemplate }, + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, + offsetof(SecCmsRecipientEncryptedKey,encKey), + SEC_ASN1_SUB(kSecAsn1OctetStringTemplate) }, + { 0 } +}; + +static const SecAsn1Template SecCmsKeyAgreeRecipientInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecCmsKeyAgreeRecipientInfo) }, + { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT, + offsetof(SecCmsKeyAgreeRecipientInfo,version) }, + { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(SecCmsKeyAgreeRecipientInfo,originatorIdentifierOrKey), + SecCmsOriginatorIdentifierOrKeyTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | + SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, + offsetof(SecCmsKeyAgreeRecipientInfo,ukm), + SEC_ASN1_SUB(kSecAsn1OctetStringTemplate) }, + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, + offsetof(SecCmsKeyAgreeRecipientInfo,keyEncAlg), + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, + { SEC_ASN1_SEQUENCE_OF, + offsetof(SecCmsKeyAgreeRecipientInfo,recipientEncryptedKeys), + SecCmsRecipientEncryptedKeyTemplate }, + { 0 } +}; + +/* ----------------------------------------------------------------------------- + * KEK recipient info + */ + +static const SecAsn1Template SecCmsKEKIdentifierTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecCmsKEKIdentifier) }, + { SEC_ASN1_OCTET_STRING, + offsetof(SecCmsKEKIdentifier,keyIdentifier) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_OCTET_STRING, + offsetof(SecCmsKEKIdentifier,date) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_OCTET_STRING, + offsetof(SecCmsKEKIdentifier,other) }, + { 0 } +}; + +static const SecAsn1Template SecCmsKEKRecipientInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecCmsKEKRecipientInfo) }, + { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT, + offsetof(SecCmsKEKRecipientInfo,version) }, + { SEC_ASN1_INLINE, + offsetof(SecCmsKEKRecipientInfo,kekIdentifier), + SecCmsKEKIdentifierTemplate }, + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, + offsetof(SecCmsKEKRecipientInfo,keyEncAlg), + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, + { SEC_ASN1_OCTET_STRING, + offsetof(SecCmsKEKRecipientInfo,encKey) }, + { 0 } +}; + +/* ----------------------------------------------------------------------------- + * recipient info + */ +const SecAsn1Template SecCmsRecipientInfoTemplate[] = { + { SEC_ASN1_CHOICE, + offsetof(SecCmsRecipientInfo,recipientInfoType), NULL, + sizeof(SecCmsRecipientInfo) }, + { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, + offsetof(SecCmsRecipientInfo,ri.keyAgreeRecipientInfo), + SecCmsKeyAgreeRecipientInfoTemplate, + SecCmsRecipientInfoIDKeyAgree }, + { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 2, + offsetof(SecCmsRecipientInfo,ri.kekRecipientInfo), + SecCmsKEKRecipientInfoTemplate, + SecCmsRecipientInfoIDKEK }, + { SEC_ASN1_INLINE, + offsetof(SecCmsRecipientInfo,ri.keyTransRecipientInfo), + SecCmsKeyTransRecipientInfoTemplate, + SecCmsRecipientInfoIDKeyTrans }, + { 0 } +}; + +/* ----------------------------------------------------------------------------- + * + */ + +const SecAsn1Template SecCmsDigestedDataTemplate[] = { + { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, + 0, NULL, sizeof(SecCmsDigestedData) }, + { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT, + offsetof(SecCmsDigestedData,version) }, + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, + offsetof(SecCmsDigestedData,digestAlg), + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, + { SEC_ASN1_INLINE, + offsetof(SecCmsDigestedData,contentInfo), + SecCmsEncapsulatedContentInfoTemplate }, + { SEC_ASN1_OCTET_STRING, + offsetof(SecCmsDigestedData,digest) }, + { 0 } +}; + +const SecAsn1Template NSS_PointerToCMSDigestedDataTemplate[] = { + { SEC_ASN1_POINTER, 0, SecCmsDigestedDataTemplate } +}; + +const SecAsn1Template SecCmsEncryptedDataTemplate[] = { + { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, + 0, NULL, sizeof(SecCmsEncryptedData) }, + { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT, + offsetof(SecCmsEncryptedData,version) }, + { SEC_ASN1_INLINE, + offsetof(SecCmsEncryptedData,contentInfo), + SecCmsEncryptedContentInfoTemplate }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, + offsetof(SecCmsEncryptedData,unprotectedAttr), + nss_cms_set_of_attribute_template }, + { 0 } +}; + +const SecAsn1Template NSS_PointerToCMSEncryptedDataTemplate[] = { + { SEC_ASN1_POINTER, 0, SecCmsEncryptedDataTemplate } +}; + +/* ----------------------------------------------------------------------------- + * SetOfSignedCrlTemplate + */ +const SecAsn1Template SecCmsIssuerAndSNTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecCmsIssuerAndSN) }, +#if 1 // @@@ Switch to using NSS_NameTemplate + { SEC_ASN1_ANY, + offsetof(SecCmsIssuerAndSN,derIssuer) }, +#else + { SEC_ASN1_INLINE, + offsetof(SecCmsIssuerAndSN,issuer), + NSS_NameTemplate }, +#endif + { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT, + offsetof(SecCmsIssuerAndSN,serialNumber) }, + { 0 } +}; + + +/* ----------------------------------------------------------------------------- + * FORTEZZA KEA + */ +const SecAsn1Template NSS_SMIMEKEAParamTemplateSkipjack[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecCmsSMIMEKEAParameters) }, + { SEC_ASN1_OCTET_STRING /* | SEC_ASN1_OPTIONAL */, + offsetof(SecCmsSMIMEKEAParameters,originatorKEAKey) }, + { SEC_ASN1_OCTET_STRING, + offsetof(SecCmsSMIMEKEAParameters,originatorRA) }, + { 0 } +}; + +const SecAsn1Template NSS_SMIMEKEAParamTemplateNoSkipjack[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecCmsSMIMEKEAParameters) }, + { SEC_ASN1_OCTET_STRING /* | SEC_ASN1_OPTIONAL */, + offsetof(SecCmsSMIMEKEAParameters,originatorKEAKey) }, + { SEC_ASN1_OCTET_STRING, + offsetof(SecCmsSMIMEKEAParameters,originatorRA) }, + { SEC_ASN1_OCTET_STRING | SEC_ASN1_OPTIONAL , + offsetof(SecCmsSMIMEKEAParameters,nonSkipjackIV) }, + { 0 } +}; + +const SecAsn1Template NSS_SMIMEKEAParamTemplateAllParams[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecCmsSMIMEKEAParameters) }, + { SEC_ASN1_OCTET_STRING /* | SEC_ASN1_OPTIONAL */, + offsetof(SecCmsSMIMEKEAParameters,originatorKEAKey) }, + { SEC_ASN1_OCTET_STRING, + offsetof(SecCmsSMIMEKEAParameters,originatorRA) }, + { SEC_ASN1_OCTET_STRING | SEC_ASN1_OPTIONAL , + offsetof(SecCmsSMIMEKEAParameters,nonSkipjackIV) }, + { SEC_ASN1_OCTET_STRING | SEC_ASN1_OPTIONAL , + offsetof(SecCmsSMIMEKEAParameters,bulkKeySize) }, + { 0 } +}; + +/*TODO: this should be in some header */ +const SecAsn1Template * +nss_cms_get_kea_template(SecCmsKEATemplateSelector whichTemplate); +const SecAsn1Template * +nss_cms_get_kea_template(SecCmsKEATemplateSelector whichTemplate) +{ + const SecAsn1Template *returnVal = NULL; + + switch(whichTemplate) + { + case SecCmsKEAUsesNonSkipjack: + returnVal = NSS_SMIMEKEAParamTemplateNoSkipjack; + break; + case SecCmsKEAUsesSkipjack: + returnVal = NSS_SMIMEKEAParamTemplateSkipjack; + break; + case SecCmsKEAUsesNonSkipjackWithPaddedEncKey: + default: + returnVal = NSS_SMIMEKEAParamTemplateAllParams; + break; + } + return returnVal; +} + +/* ----------------------------------------------------------------------------- + * + */ +static const SecAsn1Template * +nss_cms_choose_content_template(void *src_or_dest, Boolean encoding, const char *buf, void *dest) +{ + const SecAsn1Template *theTemplate; + SecCmsContentInfoRef cinfo; + + PORT_Assert (src_or_dest != NULL); + if (src_or_dest == NULL) + return NULL; + + cinfo = (SecCmsContentInfoRef)src_or_dest; + switch (SecCmsContentInfoGetContentTypeTag(cinfo)) { + default: + theTemplate = SEC_ASN1_GET(kSecAsn1PointerToAnyTemplate); + break; + case SEC_OID_PKCS7_DATA: + case SEC_OID_OTHER: + theTemplate = SEC_ASN1_GET(kSecAsn1PointerToOctetStringTemplate); + break; + case SEC_OID_PKCS7_SIGNED_DATA: + theTemplate = NSS_PointerToCMSSignedDataTemplate; + break; + case SEC_OID_PKCS7_ENVELOPED_DATA: + theTemplate = NSS_PointerToCMSEnvelopedDataTemplate; + break; + case SEC_OID_PKCS7_DIGESTED_DATA: + theTemplate = NSS_PointerToCMSDigestedDataTemplate; + break; + case SEC_OID_PKCS7_ENCRYPTED_DATA: + theTemplate = NSS_PointerToCMSEncryptedDataTemplate; + break; + } + return theTemplate; +} diff --git a/Security/libsecurity_smime/lib/cmsattr.c b/Security/libsecurity_smime/lib/cmsattr.c new file mode 100644 index 00000000..6165481b --- /dev/null +++ b/Security/libsecurity_smime/lib/cmsattr.c @@ -0,0 +1,450 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * CMS attributes. + */ + +#include "cmslocal.h" + +#include "secoid.h" +#include "secitem.h" + +#include +#include + +/* + * ------------------------------------------------------------------- + * XXX The following Attribute stuff really belongs elsewhere. + * The Attribute type is *not* part of CMS but rather X.501. + * But for now, since CMS is the only customer of attributes, + * we define them here. Once there is a use outside of CMS, + * then change the attribute types and functions from internal + * to external naming convention, and move them elsewhere! + */ + + +/* + * SecCmsAttributeCreate - create an attribute + * + * if value is NULL, the attribute won't have a value. It can be added later + * with SecCmsAttributeAddValue. + */ +SecCmsAttribute * +SecCmsAttributeCreate(PRArenaPool *poolp, SECOidTag oidtag, CSSM_DATA_PTR value, Boolean encoded) +{ + SecCmsAttribute *attr; + CSSM_DATA_PTR copiedvalue; + void *mark; + + PORT_Assert (poolp != NULL); + + mark = PORT_ArenaMark (poolp); + + attr = (SecCmsAttribute *)PORT_ArenaZAlloc(poolp, sizeof(SecCmsAttribute)); + if (attr == NULL) + goto loser; + + attr->typeTag = SECOID_FindOIDByTag(oidtag); + if (attr->typeTag == NULL) + goto loser; + + if (SECITEM_CopyItem(poolp, &(attr->type), &(attr->typeTag->oid)) != SECSuccess) + goto loser; + + if (value != NULL) { + if ((copiedvalue = SECITEM_AllocItem(poolp, NULL, (unsigned int)value->Length)) == NULL) + goto loser; + + if (SECITEM_CopyItem(poolp, copiedvalue, value) != SECSuccess) + goto loser; + + SecCmsArrayAdd(poolp, (void ***)&(attr->values), (void *)copiedvalue); + } + + attr->encoded = encoded; + + PORT_ArenaUnmark (poolp, mark); + + return attr; + +loser: + PORT_Assert (mark != NULL); + PORT_ArenaRelease (poolp, mark); + return NULL; +} + +/* + * SecCmsAttributeAddValue - add another value to an attribute + */ +OSStatus +SecCmsAttributeAddValue(PLArenaPool *poolp, SecCmsAttribute *attr, CSSM_DATA_PTR value) +{ + CSSM_DATA copiedvalue; + void *mark; + + PORT_Assert (poolp != NULL); + + mark = PORT_ArenaMark(poolp); + + /* XXX we need an object memory model #$%#$%! */ + if (SECITEM_CopyItem(poolp, &copiedvalue, value) != SECSuccess) + goto loser; + + if (SecCmsArrayAdd(poolp, (void ***)&(attr->values), (void *)&copiedvalue) != SECSuccess) + goto loser; + + PORT_ArenaUnmark(poolp, mark); + return SECSuccess; + +loser: + PORT_Assert (mark != NULL); + PORT_ArenaRelease (poolp, mark); + return SECFailure; +} + +/* + * SecCmsAttributeGetType - return the OID tag + */ +SECOidTag +SecCmsAttributeGetType(SecCmsAttribute *attr) +{ + SECOidData *typetag; + + typetag = SECOID_FindOID(&(attr->type)); + if (typetag == NULL) + return SEC_OID_UNKNOWN; + + return typetag->offset; +} + +/* + * SecCmsAttributeGetValue - return the first attribute value + * + * We do some sanity checking first: + * - Multiple values are *not* expected. + * - Empty values are *not* expected. + */ +CSSM_DATA_PTR +SecCmsAttributeGetValue(SecCmsAttribute *attr) +{ + CSSM_DATA_PTR value; + + if (attr == NULL) + return NULL; + + value = attr->values[0]; + + if (value == NULL || value->Data == NULL || value->Length == 0) + return NULL; + + if (attr->values[1] != NULL) + return NULL; + + return value; +} + +/* + * SecCmsAttributeCompareValue - compare the attribute's first value against data + */ +Boolean +SecCmsAttributeCompareValue(SecCmsAttribute *attr, CSSM_DATA_PTR av) +{ + CSSM_DATA_PTR value; + + if (attr == NULL) + return PR_FALSE; + + value = SecCmsAttributeGetValue(attr); + + return (value != NULL && value->Length == av->Length && + PORT_Memcmp (value->Data, av->Data, value->Length) == 0); +} + +/* + * templates and functions for separate ASN.1 encoding of attributes + * + * used in SecCmsAttributeArrayReorder + */ + +/* + * helper function for dynamic template determination of the attribute value + */ +static const SecAsn1Template * +cms_attr_choose_attr_value_template(void *src_or_dest, Boolean encoding, const char *buf, void *dest) +{ + const SecAsn1Template *theTemplate; + SecCmsAttribute *attribute; + SECOidData *oiddata; + Boolean encoded; + + PORT_Assert (src_or_dest != NULL); + if (src_or_dest == NULL) + return NULL; + + attribute = (SecCmsAttribute *)src_or_dest; + + if (encoding && attribute->encoded) + /* we're encoding, and the attribute value is already encoded. */ + return SEC_ASN1_GET(kSecAsn1AnyTemplate); + + /* get attribute's typeTag */ + oiddata = attribute->typeTag; + if (oiddata == NULL) { + oiddata = SECOID_FindOID(&attribute->type); + attribute->typeTag = oiddata; + } + + if (oiddata == NULL) { + /* still no OID tag? OID is unknown then. en/decode value as ANY. */ + encoded = PR_TRUE; + theTemplate = SEC_ASN1_GET(kSecAsn1AnyTemplate); + } else { + switch (oiddata->offset) { + case SEC_OID_PKCS9_SMIME_CAPABILITIES: + case SEC_OID_SMIME_ENCRYPTION_KEY_PREFERENCE: + /* these guys need to stay DER-encoded */ + default: + /* same goes for OIDs that are not handled here */ + encoded = PR_TRUE; + theTemplate = SEC_ASN1_GET(kSecAsn1AnyTemplate); + break; + /* otherwise choose proper template */ + case SEC_OID_PKCS9_EMAIL_ADDRESS: + case SEC_OID_RFC1274_MAIL: + case SEC_OID_PKCS9_UNSTRUCTURED_NAME: + encoded = PR_FALSE; + theTemplate = SEC_ASN1_GET(kSecAsn1IA5StringTemplate); + break; + case SEC_OID_PKCS9_CONTENT_TYPE: + encoded = PR_FALSE; + theTemplate = SEC_ASN1_GET(kSecAsn1ObjectIDTemplate); + break; + case SEC_OID_PKCS9_MESSAGE_DIGEST: + encoded = PR_FALSE; + theTemplate = SEC_ASN1_GET(kSecAsn1OctetStringTemplate); + break; + case SEC_OID_PKCS9_SIGNING_TIME: + encoded = PR_FALSE; + theTemplate = SEC_ASN1_GET(kSecAsn1UTCTimeTemplate); // @@@ This should be a choice between UTCTime and GeneralizedTime -- mb + break; + /* XXX Want other types here, too */ + } + } + + if (encoding) { + /* + * If we are encoding and we think we have an already-encoded value, + * then the code which initialized this attribute should have set + * the "encoded" property to true (and we would have returned early, + * up above). No devastating error, but that code should be fixed. + * (It could indicate that the resulting encoded bytes are wrong.) + */ + PORT_Assert (!encoded); + } else { + /* + * We are decoding; record whether the resulting value is + * still encoded or not. + */ + attribute->encoded = encoded; + } + return theTemplate; +} + +static const SecAsn1TemplateChooserPtr cms_attr_chooser + = cms_attr_choose_attr_value_template; + +const SecAsn1Template nss_cms_attribute_template[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SecCmsAttribute) }, + { SEC_ASN1_OBJECT_ID, + offsetof(SecCmsAttribute,type) }, + { SEC_ASN1_DYNAMIC | SEC_ASN1_SET_OF, + offsetof(SecCmsAttribute,values), + &cms_attr_chooser }, + { 0 } +}; + +const SecAsn1Template nss_cms_set_of_attribute_template[] = { + { SEC_ASN1_SET_OF, 0, nss_cms_attribute_template } +}; + +/* ============================================================================= + * Attribute Array methods + */ + +/* + * SecCmsAttributeArrayEncode - encode an Attribute array as SET OF Attributes + * + * If you are wondering why this routine does not reorder the attributes + * first, and might be tempted to make it do so, see the comment by the + * call to ReorderAttributes in cmsencode.c. (Or, see who else calls this + * and think long and hard about the implications of making it always + * do the reordering.) + */ +CSSM_DATA_PTR +SecCmsAttributeArrayEncode(PRArenaPool *poolp, SecCmsAttribute ***attrs, CSSM_DATA_PTR dest) +{ + return SEC_ASN1EncodeItem (poolp, dest, (void *)attrs, nss_cms_set_of_attribute_template); +} + +/* + * SecCmsAttributeArrayReorder - sort attribute array by attribute's DER encoding + * + * make sure that the order of the attributes guarantees valid DER (which must be + * in lexigraphically ascending order for a SET OF); if reordering is necessary it + * will be done in place (in attrs). + */ +OSStatus +SecCmsAttributeArrayReorder(SecCmsAttribute **attrs) +{ + return SecCmsArraySortByDER((void **)attrs, nss_cms_attribute_template, NULL); +} + +/* + * SecCmsAttributeArrayFindAttrByOidTag - look through a set of attributes and + * find one that matches the specified object ID. + * + * If "only" is true, then make sure that there is not more than one attribute + * of the same type. Otherwise, just return the first one found. (XXX Does + * anybody really want that first-found behavior? It was like that when I found it...) + */ +SecCmsAttribute * +SecCmsAttributeArrayFindAttrByOidTag(SecCmsAttribute **attrs, SECOidTag oidtag, Boolean only) +{ + SECOidData *oid; + SecCmsAttribute *attr1, *attr2; + + if (attrs == NULL) + return NULL; + + oid = SECOID_FindOIDByTag(oidtag); + if (oid == NULL) + return NULL; + + while ((attr1 = *attrs++) != NULL) { + if (attr1->type.Length == oid->oid.Length && PORT_Memcmp (attr1->type.Data, + oid->oid.Data, + oid->oid.Length) == 0) + break; + } + + if (attr1 == NULL) + return NULL; + + if (!only) + return attr1; + + while ((attr2 = *attrs++) != NULL) { + if (attr2->type.Length == oid->oid.Length && PORT_Memcmp (attr2->type.Data, + oid->oid.Data, + oid->oid.Length) == 0) + break; + } + + if (attr2 != NULL) + return NULL; + + return attr1; +} + +/* + * SecCmsAttributeArrayAddAttr - add an attribute to an + * array of attributes. + */ +OSStatus +SecCmsAttributeArrayAddAttr(PLArenaPool *poolp, SecCmsAttribute ***attrs, SecCmsAttribute *attr) +{ + SecCmsAttribute *oattr; + void *mark; + SECOidTag type; + + mark = PORT_ArenaMark(poolp); + + /* find oidtag of attr */ + type = SecCmsAttributeGetType(attr); + + /* see if we have one already */ + oattr = SecCmsAttributeArrayFindAttrByOidTag(*attrs, type, PR_FALSE); + PORT_Assert (oattr == NULL); + if (oattr != NULL) + goto loser; /* XXX or would it be better to replace it? */ + + /* no, shove it in */ + if (SecCmsArrayAdd(poolp, (void ***)attrs, (void *)attr) != SECSuccess) + goto loser; + + PORT_ArenaUnmark(poolp, mark); + return SECSuccess; + +loser: + PORT_ArenaRelease(poolp, mark); + return SECFailure; +} + +/* + * SecCmsAttributeArraySetAttr - set an attribute's value in a set of attributes + */ +OSStatus +SecCmsAttributeArraySetAttr(PLArenaPool *poolp, SecCmsAttribute ***attrs, SECOidTag type, CSSM_DATA_PTR value, Boolean encoded) +{ + SecCmsAttribute *attr; + void *mark; + + mark = PORT_ArenaMark(poolp); + + /* see if we have one already */ + attr = SecCmsAttributeArrayFindAttrByOidTag(*attrs, type, PR_FALSE); + if (attr == NULL) { + /* not found? create one! */ + attr = SecCmsAttributeCreate(poolp, type, value, encoded); + if (attr == NULL) + goto loser; + /* and add it to the list */ + if (SecCmsArrayAdd(poolp, (void ***)attrs, (void *)attr) != SECSuccess) + goto loser; + } else { + /* found, shove it in */ + /* XXX we need a decent memory model @#$#$!#!!! */ + attr->values[0] = value; + attr->encoded = encoded; + } + + PORT_ArenaUnmark (poolp, mark); + return SECSuccess; + +loser: + PORT_ArenaRelease (poolp, mark); + return SECFailure; +} + diff --git a/Security/libsecurity_smime/lib/cmscinfo.c b/Security/libsecurity_smime/lib/cmscinfo.c new file mode 100644 index 00000000..e13acbe8 --- /dev/null +++ b/Security/libsecurity_smime/lib/cmscinfo.c @@ -0,0 +1,420 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * CMS contentInfo methods. + */ + +#include + +#include +#include +#include +#include +#include + +#include "cmslocal.h" + +//#include "pk11func.h" +#include "secoid.h" +#include "secitem.h" + +#include +#include + +/* + * SecCmsContentInfoCreate - create a content info + * + * version is set in the _Finalize procedures for each content type + */ + +/* + * SecCmsContentInfoDestroy - destroy a CMS contentInfo and all of its sub-pieces. + */ +void +SecCmsContentInfoDestroy(SecCmsContentInfoRef cinfo) +{ + SECOidTag kind; + + kind = SecCmsContentInfoGetContentTypeTag(cinfo); + switch (kind) { + case SEC_OID_PKCS7_ENVELOPED_DATA: + SecCmsEnvelopedDataDestroy(cinfo->content.envelopedData); + break; + case SEC_OID_PKCS7_SIGNED_DATA: + SecCmsSignedDataDestroy(cinfo->content.signedData); + break; + case SEC_OID_PKCS7_ENCRYPTED_DATA: + SecCmsEncryptedDataDestroy(cinfo->content.encryptedData); + break; + case SEC_OID_PKCS7_DIGESTED_DATA: + SecCmsDigestedDataDestroy(cinfo->content.digestedData); + break; + default: + /* XXX Anything else that needs to be "manually" freed/destroyed? */ + break; + } + if (cinfo->digcx) { + /* must destroy digest objects */ + SecCmsDigestContextCancel(cinfo->digcx); + cinfo->digcx = NULL; + } + if (cinfo->bulkkey) + CFRelease(cinfo->bulkkey); + /* @@@ private key is only here as a workaround for 3401088. Note this *must* be released after bulkkey */ + if (cinfo->privkey) + CFRelease(cinfo->privkey); + + if (cinfo->ciphcx) { + SecCmsCipherContextDestroy(cinfo->ciphcx); + cinfo->ciphcx = NULL; + } + + /* we live in a pool, so no need to worry about storage */ +} + +/* + * SecCmsContentInfoGetChildContentInfo - get content's contentInfo (if it exists) + */ +SecCmsContentInfoRef +SecCmsContentInfoGetChildContentInfo(SecCmsContentInfoRef cinfo) +{ + void *ptr = NULL; + SecCmsContentInfoRef ccinfo = NULL; + SECOidTag tag = SecCmsContentInfoGetContentTypeTag(cinfo); + switch (tag) { + case SEC_OID_PKCS7_SIGNED_DATA: + ptr = (void *)cinfo->content.signedData; + ccinfo = &(cinfo->content.signedData->contentInfo); + break; + case SEC_OID_PKCS7_ENVELOPED_DATA: + ptr = (void *)cinfo->content.envelopedData; + ccinfo = &(cinfo->content.envelopedData->contentInfo); + break; + case SEC_OID_PKCS7_DIGESTED_DATA: + ptr = (void *)cinfo->content.digestedData; + ccinfo = &(cinfo->content.digestedData->contentInfo); + break; + case SEC_OID_PKCS7_ENCRYPTED_DATA: + ptr = (void *)cinfo->content.encryptedData; + ccinfo = &(cinfo->content.encryptedData->contentInfo); + break; + case SEC_OID_PKCS7_DATA: + case SEC_OID_OTHER: + default: + break; + } + return (ptr ? ccinfo : NULL); +} + +/* + * SecCmsContentInfoSetContent - set content type & content + */ +OSStatus +SecCmsContentInfoSetContent(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SECOidTag type, void *ptr) +{ + OSStatus rv; + + cinfo->contentTypeTag = SECOID_FindOIDByTag(type); + if (cinfo->contentTypeTag == NULL) + return paramErr; + + /* do not copy the oid, just create a reference */ + rv = SECITEM_CopyItem (cmsg->poolp, &(cinfo->contentType), &(cinfo->contentTypeTag->oid)); + if (rv != SECSuccess) + return memFullErr; + + cinfo->content.pointer = ptr; + + if (type != SEC_OID_PKCS7_DATA) { + /* as we always have some inner data, + * we need to set it to something, just to fool the encoder enough to work on it + * and get us into nss_cms_encoder_notify at that point */ + cinfo->rawContent = SECITEM_AllocItem(cmsg->poolp, NULL, 1); + if (cinfo->rawContent == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + return memFullErr; + } + } + + return noErr; +} + +/* + * SecCmsContentInfoSetContentXXXX - typesafe wrappers for SecCmsContentInfoSetContent + */ + +/* + * data == NULL -> pass in data via SecCmsEncoderUpdate + * data != NULL -> take this data + */ +OSStatus +SecCmsContentInfoSetContentData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, CSSM_DATA_PTR data, Boolean detached) +{ + if (SecCmsContentInfoSetContent(cmsg, cinfo, SEC_OID_PKCS7_DATA, (void *)data) != SECSuccess) + return PORT_GetError(); + cinfo->rawContent = (detached) ? + NULL : (data) ? + data : SECITEM_AllocItem(cmsg->poolp, NULL, 1); + return noErr; +} + +OSStatus +SecCmsContentInfoSetContentSignedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsSignedDataRef sigd) +{ + return SecCmsContentInfoSetContent(cmsg, cinfo, SEC_OID_PKCS7_SIGNED_DATA, (void *)sigd); +} + +OSStatus +SecCmsContentInfoSetContentEnvelopedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsEnvelopedDataRef envd) +{ + return SecCmsContentInfoSetContent(cmsg, cinfo, SEC_OID_PKCS7_ENVELOPED_DATA, (void *)envd); +} + +OSStatus +SecCmsContentInfoSetContentDigestedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsDigestedDataRef digd) +{ + return SecCmsContentInfoSetContent(cmsg, cinfo, SEC_OID_PKCS7_DIGESTED_DATA, (void *)digd); +} + +OSStatus +SecCmsContentInfoSetContentEncryptedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsEncryptedDataRef encd) +{ + return SecCmsContentInfoSetContent(cmsg, cinfo, SEC_OID_PKCS7_ENCRYPTED_DATA, (void *)encd); +} + +OSStatus +SecCmsContentInfoSetContentOther(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, CSSM_DATA_PTR data, Boolean detached, const CSSM_OID *eContentType) +{ + SECStatus srtn; + SECOidData *tmpOidData; + + /* just like SecCmsContentInfoSetContentData, except override the contentType and + * contentTypeTag. This OID is for encoding... */ + srtn = SECITEM_CopyItem (cmsg->poolp, &(cinfo->contentType), eContentType); + if (srtn != SECSuccess) { + return memFullErr; + } + + /* this serves up a contentTypeTag with an empty OID */ + tmpOidData = SECOID_FindOIDByTag(SEC_OID_OTHER); + /* but that's const: cook up a new one we can write to */ + cinfo->contentTypeTag = (SECOidData *)PORT_ArenaZAlloc(cmsg->poolp, sizeof(SECOidData)); + *cinfo->contentTypeTag = *tmpOidData; + /* now fill in the OID */ + srtn = SECITEM_CopyItem (cmsg->poolp, &(cinfo->contentTypeTag->oid), eContentType); + if (srtn != SECSuccess) { + return memFullErr; + } + cinfo->content.pointer = data; + cinfo->rawContent = (detached) ? + NULL : (data) ? + data : SECITEM_AllocItem(cmsg->poolp, NULL, 1); + return noErr; +} + + +/* + * SecCmsContentInfoGetContent - get pointer to inner content + * + * needs to be casted... + */ +void * +SecCmsContentInfoGetContent(SecCmsContentInfoRef cinfo) +{ + SECOidTag tag = (cinfo && cinfo->contentTypeTag) + ? cinfo->contentTypeTag->offset + : cinfo->contentType.Data ? SEC_OID_OTHER : SEC_OID_UNKNOWN; + switch (tag) { + case SEC_OID_PKCS7_DATA: + case SEC_OID_PKCS7_SIGNED_DATA: + case SEC_OID_PKCS7_ENVELOPED_DATA: + case SEC_OID_PKCS7_DIGESTED_DATA: + case SEC_OID_PKCS7_ENCRYPTED_DATA: + case SEC_OID_OTHER: + return cinfo->content.pointer; + default: + return NULL; + } +} + +/* + * SecCmsContentInfoGetInnerContent - get pointer to innermost content + * + * this is typically only called by SecCmsMessageGetContent() + */ +CSSM_DATA_PTR +SecCmsContentInfoGetInnerContent(SecCmsContentInfoRef cinfo) +{ + SECOidTag tag; + + for(;;) { + tag = SecCmsContentInfoGetContentTypeTag(cinfo); + switch (tag) { + case SEC_OID_PKCS7_DATA: + case SEC_OID_OTHER: + /* end of recursion - every message has to have a data cinfo */ + return cinfo->content.data; + case SEC_OID_PKCS7_DIGESTED_DATA: + case SEC_OID_PKCS7_ENCRYPTED_DATA: + case SEC_OID_PKCS7_ENVELOPED_DATA: + case SEC_OID_PKCS7_SIGNED_DATA: + cinfo = SecCmsContentInfoGetChildContentInfo(cinfo); + if (cinfo == NULL) { + return NULL; + } + /* else recurse */ + break; + case SEC_OID_PKCS9_ID_CT_TSTInfo: + /* end of recursion - every message has to have a data cinfo */ + return cinfo->rawContent; + default: + PORT_Assert(0); + return NULL; + } + } + /* NOT REACHED */ + return NULL; +} + +/* + * SecCmsContentInfoGetContentType{Tag,OID} - find out (saving pointer to lookup result + * for future reference) and return the inner content type. + */ +SECOidTag +SecCmsContentInfoGetContentTypeTag(SecCmsContentInfoRef cinfo) +{ + if (cinfo->contentTypeTag == NULL) + cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType)); + + if (cinfo->contentTypeTag == NULL) + return SEC_OID_OTHER; // was...SEC_OID_UNKNOWN OK? + + return cinfo->contentTypeTag->offset; +} + +CSSM_DATA_PTR +SecCmsContentInfoGetContentTypeOID(SecCmsContentInfoRef cinfo) +{ + if (cinfo->contentTypeTag == NULL) + cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType)); + + if (cinfo->contentTypeTag == NULL) { + /* if we have an OID but we just don't recognize it, return that */ + if(cinfo->contentType.Data != NULL) { + return &cinfo->contentType; + } + else { + return NULL; + } + } + return &(cinfo->contentTypeTag->oid); +} + +/* + * SecCmsContentInfoGetContentEncAlgTag - find out (saving pointer to lookup result + * for future reference) and return the content encryption algorithm tag. + */ +SECOidTag +SecCmsContentInfoGetContentEncAlgTag(SecCmsContentInfoRef cinfo) +{ + if (cinfo->contentEncAlgTag == SEC_OID_UNKNOWN) + cinfo->contentEncAlgTag = SECOID_GetAlgorithmTag(&(cinfo->contentEncAlg)); + + return cinfo->contentEncAlgTag; +} + +/* + * SecCmsContentInfoGetContentEncAlg - find out and return the content encryption algorithm tag. + */ +SECAlgorithmID * +SecCmsContentInfoGetContentEncAlg(SecCmsContentInfoRef cinfo) +{ + return &(cinfo->contentEncAlg); +} + +OSStatus +SecCmsContentInfoSetContentEncAlg(SecArenaPoolRef pool, SecCmsContentInfoRef cinfo, + SECOidTag bulkalgtag, CSSM_DATA_PTR parameters, int keysize) +{ + PLArenaPool *poolp = (PLArenaPool *)pool; + OSStatus rv; + + rv = SECOID_SetAlgorithmID(poolp, &(cinfo->contentEncAlg), bulkalgtag, parameters); + if (rv != SECSuccess) + return SECFailure; + cinfo->keysize = keysize; + return SECSuccess; +} + +OSStatus +SecCmsContentInfoSetContentEncAlgID(SecArenaPoolRef pool, SecCmsContentInfoRef cinfo, + SECAlgorithmID *algid, int keysize) +{ + PLArenaPool *poolp = (PLArenaPool *)pool; + OSStatus rv; + + rv = SECOID_CopyAlgorithmID(poolp, &(cinfo->contentEncAlg), algid); + if (rv != SECSuccess) + return SECFailure; + if (keysize >= 0) + cinfo->keysize = keysize; + return SECSuccess; +} + +void +SecCmsContentInfoSetBulkKey(SecCmsContentInfoRef cinfo, SecSymmetricKeyRef bulkkey) +{ + const CSSM_KEY *cssmKey = NULL; + + cinfo->bulkkey = bulkkey; + CFRetain(cinfo->bulkkey); + SecKeyGetCSSMKey(cinfo->bulkkey, &cssmKey); + cinfo->keysize = cssmKey ? cssmKey->KeyHeader.LogicalKeySizeInBits : 0; +} + +SecSymmetricKeyRef +SecCmsContentInfoGetBulkKey(SecCmsContentInfoRef cinfo) +{ + if (cinfo->bulkkey == NULL) + return NULL; + + CFRetain(cinfo->bulkkey); + return cinfo->bulkkey; +} + +int +SecCmsContentInfoGetBulkKeySize(SecCmsContentInfoRef cinfo) +{ + return cinfo->keysize; +} diff --git a/Security/libsecurity_smime/lib/cmscipher.c b/Security/libsecurity_smime/lib/cmscipher.c new file mode 100644 index 00000000..02ec0873 --- /dev/null +++ b/Security/libsecurity_smime/lib/cmscipher.c @@ -0,0 +1,1199 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * Encryption/decryption routines for CMS implementation, none of which are exported. + * + */ + +#include "cmslocal.h" + +#include "secoid.h" +#include +#include +#include +#include +#include +#include + +/* + * ------------------------------------------------------------------- + * Cipher stuff. + */ + +#if 0 +typedef OSStatus (*nss_cms_cipher_function) (void *, unsigned char *, unsigned int *, + unsigned int, const unsigned char *, unsigned int); +typedef OSStatus (*nss_cms_cipher_destroy) (void *, Boolean); +#endif + +#define BLOCK_SIZE 4096 + +struct SecCmsCipherContextStr { +#if 1 + CSSM_CC_HANDLE cc; /* CSP CONTEXT */ + Boolean encrypt; /* encrypt / decrypt switch */ +#else + void * cx; /* PK11 cipher context */ + nss_cms_cipher_function doit; + nss_cms_cipher_destroy destroy; + Boolean encrypt; /* encrypt / decrypt switch */ + int block_size; /* block & pad sizes for cipher */ + int pad_size; + int pending_count; /* pending data (not yet en/decrypted */ + unsigned char pending_buf[BLOCK_SIZE];/* because of blocking */ +#endif +}; + +typedef struct sec_rc2cbcParameterStr { + SECItem rc2ParameterVersion; + SECItem iv; +} sec_rc2cbcParameter; + +static const SecAsn1Template sec_rc2cbc_parameter_template[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(sec_rc2cbcParameter) }, + { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT, + offsetof(sec_rc2cbcParameter,rc2ParameterVersion) }, + { SEC_ASN1_OCTET_STRING, + offsetof(sec_rc2cbcParameter,iv) }, + { 0 } +}; + +/* +** Convert a der encoded *signed* integer into a machine integral value. +** If an underflow/overflow occurs, sets error code and returns min/max. +*/ +static long +DER_GetInteger(SECItem *it) +{ + long ival = 0; + CSSM_SIZE len = it->Length; + unsigned char *cp = it->Data; + unsigned long overflow = 0x1ffUL << (((sizeof(ival) - 1) * 8) - 1); + unsigned long ofloinit; + + if (*cp & 0x80) + ival = -1L; + ofloinit = ival & overflow; + + while (len) { + if ((ival & overflow) != ofloinit) { + PORT_SetError(SEC_ERROR_BAD_DER); + if (ival < 0) { + return LONG_MIN; + } + return LONG_MAX; + } + ival = ival << 8; + ival |= *cp++; + --len; + } + return ival; +} + +/* S/MIME picked id values to represent differnt keysizes */ +/* I do have a formula, but it ain't pretty, and it only works because you + * can always match three points to a parabola:) */ +static unsigned char rc2_map(SECItem *version) +{ + long x; + + x = DER_GetInteger(version); + + switch (x) { + case 58: return 128; + case 120: return 64; + case 160: return 40; + } + return 128; +} + +static unsigned long rc2_unmap(unsigned long x) +{ + switch (x) { + case 128: return 58; + case 64: return 120; + case 40: return 160; + } + return 58; +} + +/* default IV size in bytes */ +#define DEFAULT_IV_SIZE 8 +/* IV/block size for AES */ +#define AES_BLOCK_SIZE 16 +/* max IV size in bytes */ +#define MAX_IV_SIZE AES_BLOCK_SIZE + +static SecCmsCipherContextRef +SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorithmID *algid, Boolean encrypt) +{ + SecCmsCipherContextRef cc; + CSSM_CC_HANDLE ciphercc = 0; + SECOidData *oidData; + SECOidTag algtag; + CSSM_ALGORITHMS algorithm; + CSSM_PADDING padding = CSSM_PADDING_PKCS7; + CSSM_ENCRYPT_MODE mode; + CSSM_CSP_HANDLE cspHandle; + const CSSM_KEY *cssmKey; + OSStatus rv; + uint8 ivbuf[MAX_IV_SIZE]; + CSSM_DATA initVector = { DEFAULT_IV_SIZE, ivbuf }; + //CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_ALG_PARAMS, sizeof(CSSM_DATA_PTR) }; + + rv = SecKeyGetCSPHandle(key, &cspHandle); + if (rv) + goto loser; + rv = SecKeyGetCSSMKey(key, &cssmKey); + if (rv) + goto loser; + + // @@@ Add support for PBE based stuff + + oidData = SECOID_FindOID(&algid->algorithm); + if (!oidData) + goto loser; + algtag = oidData->offset; + algorithm = oidData->cssmAlgorithm; + if (!algorithm) + goto loser; + + switch (algtag) + { + case SEC_OID_RC2_CBC: + case SEC_OID_RC4: + case SEC_OID_DES_EDE3_CBC: + case SEC_OID_DES_EDE: + case SEC_OID_DES_CBC: + case SEC_OID_RC5_CBC_PAD: + case SEC_OID_FORTEZZA_SKIPJACK: + mode = CSSM_ALGMODE_CBCPadIV8; + break; + + /* RFC 3565 says that these sizes refer to key size, NOT block size */ + case SEC_OID_AES_128_CBC: + case SEC_OID_AES_192_CBC: + case SEC_OID_AES_256_CBC: + initVector.Length = AES_BLOCK_SIZE; + mode = CSSM_ALGMODE_CBCPadIV8; + break; + + case SEC_OID_DES_ECB: + case SEC_OID_AES_128_ECB: + case SEC_OID_AES_192_ECB: + case SEC_OID_AES_256_ECB: + mode = CSSM_ALGMODE_ECBPad; + break; + + case SEC_OID_DES_OFB: + mode = CSSM_ALGMODE_OFBPadIV8; + break; + + case SEC_OID_DES_CFB: + mode = CSSM_ALGMODE_CFBPadIV8; + break; + + default: + goto loser; + } + + if (encrypt) + { + CSSM_CC_HANDLE randomcc; + //SECItem *parameters; + + // Generate random initVector + if (CSSM_CSP_CreateRandomGenContext(cspHandle, + CSSM_ALGID_APPLE_YARROW, + NULL, /* seed*/ + initVector.Length, + &randomcc)) + goto loser; + + if (CSSM_GenerateRandom(randomcc, &initVector)) + goto loser; + CSSM_DeleteContext(randomcc); + + // Put IV into algid.parameters + switch (algtag) + { + case SEC_OID_RC4: + case SEC_OID_DES_EDE3_CBC: + case SEC_OID_DES_EDE: + case SEC_OID_DES_CBC: + case SEC_OID_AES_128_CBC: + case SEC_OID_AES_192_CBC: + case SEC_OID_AES_256_CBC: + case SEC_OID_FORTEZZA_SKIPJACK: + case SEC_OID_DES_ECB: + case SEC_OID_AES_128_ECB: + case SEC_OID_AES_192_ECB: + case SEC_OID_AES_256_ECB: + case SEC_OID_DES_OFB: + case SEC_OID_DES_CFB: + /* Just encode the initVector as an octet string. */ + if (!SEC_ASN1EncodeItem(poolp, &algid->parameters, + &initVector, kSecAsn1OctetStringTemplate)) + goto loser; + break; + + case SEC_OID_RC2_CBC: + { + sec_rc2cbcParameter rc2 = {}; + unsigned long rc2version; + SECItem *newParams; + + rc2.iv = initVector; + rc2version = rc2_unmap(cssmKey->KeyHeader.LogicalKeySizeInBits); + if (!SEC_ASN1EncodeUnsignedInteger (NULL, &(rc2.rc2ParameterVersion), + rc2version)) + goto loser; + newParams = SEC_ASN1EncodeItem (poolp, &algid->parameters, &rc2, + sec_rc2cbc_parameter_template); + PORT_Free(rc2.rc2ParameterVersion.Data); + if (newParams == NULL) + goto loser; + break; + } + case SEC_OID_RC5_CBC_PAD: + default: + // @@@ Implement rc5 params stuff. + goto loser; + break; + } + } + else + { + // Extract IV from algid.parameters + // Put IV into algid.parameters + switch (algtag) + { + case SEC_OID_RC4: + case SEC_OID_DES_EDE3_CBC: + case SEC_OID_DES_EDE: + case SEC_OID_DES_CBC: + case SEC_OID_AES_128_CBC: + case SEC_OID_AES_192_CBC: + case SEC_OID_AES_256_CBC: + case SEC_OID_FORTEZZA_SKIPJACK: + case SEC_OID_DES_ECB: + case SEC_OID_AES_128_ECB: + case SEC_OID_AES_192_ECB: + case SEC_OID_AES_256_ECB: + case SEC_OID_DES_OFB: + case SEC_OID_DES_CFB: + { + CSSM_DATA iv = {}; + /* Just decode the initVector from an octet string. */ + rv = SEC_ASN1DecodeItem(NULL, &iv, kSecAsn1OctetStringTemplate, &(algid->parameters)); + if (rv) + goto loser; + if (initVector.Length != iv.Length) { + PORT_Free(iv.Data); + goto loser; + } + memcpy(initVector.Data, iv.Data, initVector.Length); + PORT_Free(iv.Data); + break; + } + case SEC_OID_RC2_CBC: + { + sec_rc2cbcParameter rc2 = {}; + unsigned long ulEffectiveBits; + + rv = SEC_ASN1DecodeItem(NULL, &rc2 ,sec_rc2cbc_parameter_template, + &(algid->parameters)); + if (rv) + goto loser; + + if (initVector.Length != rc2.iv.Length) { + PORT_Free(rc2.iv.Data); + PORT_Free(rc2.rc2ParameterVersion.Data); + goto loser; + } + memcpy(initVector.Data, rc2.iv.Data, initVector.Length); + PORT_Free(rc2.iv.Data); + + ulEffectiveBits = rc2_map(&rc2.rc2ParameterVersion); + PORT_Free(rc2.rc2ParameterVersion.Data); + if (ulEffectiveBits != cssmKey->KeyHeader.LogicalKeySizeInBits) + goto loser; + break; + } + case SEC_OID_RC5_CBC_PAD: + default: + // @@@ Implement rc5 params stuff. + goto loser; + break; + } + } + + if (CSSM_CSP_CreateSymmetricContext(cspHandle, + algorithm, + mode, + NULL, /* accessCred */ + cssmKey, + &initVector, + padding, + NULL, /* reserved */ + &ciphercc)) + goto loser; + + if (encrypt) + rv = CSSM_EncryptDataInit(ciphercc); + else + rv = CSSM_DecryptDataInit(ciphercc); + if (rv) + goto loser; + + cc = (SecCmsCipherContextRef)PORT_ZAlloc(sizeof(SecCmsCipherContext)); + if (cc == NULL) + goto loser; + + cc->cc = ciphercc; + cc->encrypt = encrypt; + + return cc; +loser: + if (ciphercc) + CSSM_DeleteContext(ciphercc); + + return NULL; +} + +/* + * SecCmsCipherContextStartDecrypt - create a cipher context to do decryption + * based on the given bulk * encryption key and algorithm identifier (which may include an iv). + * + * XXX Once both are working, it might be nice to combine this and the + * function below (for starting up encryption) into one routine, and just + * have two simple cover functions which call it. + */ +SecCmsCipherContextRef +SecCmsCipherContextStartDecrypt(SecSymmetricKeyRef key, SECAlgorithmID *algid) +{ + return SecCmsCipherContextStart(NULL, key, algid, PR_FALSE); +#if 0 + SecCmsCipherContextRef cc; + void *ciphercx; + CK_MECHANISM_TYPE mechanism; + CSSM_DATA_PTR param; + PK11SlotInfo *slot; + SECOidTag algtag; + + algtag = SECOID_GetAlgorithmTag(algid); + + /* set param and mechanism */ + if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { + CK_MECHANISM pbeMech, cryptoMech; + CSSM_DATA_PTR pbeParams; + SEC_PKCS5KeyAndPassword *keyPwd; + + PORT_Memset(&pbeMech, 0, sizeof(CK_MECHANISM)); + PORT_Memset(&cryptoMech, 0, sizeof(CK_MECHANISM)); + + /* HACK ALERT! + * in this case, key is not actually a SecSymmetricKeyRef, but a SEC_PKCS5KeyAndPassword * + */ + keyPwd = (SEC_PKCS5KeyAndPassword *)key; + key = keyPwd->key; + + /* find correct PK11 mechanism and parameters to initialize pbeMech */ + pbeMech.mechanism = PK11_AlgtagToMechanism(algtag); + pbeParams = PK11_ParamFromAlgid(algid); + if (!pbeParams) + return NULL; + pbeMech.pParameter = pbeParams->Data; + pbeMech.ulParameterLen = pbeParams->Length; + + /* now map pbeMech to cryptoMech */ + if (PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, keyPwd->pwitem, + PR_FALSE) != CKR_OK) { + SECITEM_ZfreeItem(pbeParams, PR_TRUE); + return NULL; + } + SECITEM_ZfreeItem(pbeParams, PR_TRUE); + + /* and use it to initialize param & mechanism */ + if ((param = (CSSM_DATA_PTR)PORT_ZAlloc(sizeof(CSSM_DATA))) == NULL) + return NULL; + + param->Data = (unsigned char *)cryptoMech.pParameter; + param->Length = cryptoMech.ulParameterLen; + mechanism = cryptoMech.mechanism; + } else { + mechanism = PK11_AlgtagToMechanism(algtag); + if ((param = PK11_ParamFromAlgid(algid)) == NULL) + return NULL; + } + + cc = (SecCmsCipherContextRef)PORT_ZAlloc(sizeof(SecCmsCipherContext)); + if (cc == NULL) { + SECITEM_FreeItem(param,PR_TRUE); + return NULL; + } + + /* figure out pad and block sizes */ + cc->pad_size = PK11_GetBlockSize(mechanism, param); + slot = PK11_GetSlotFromKey(key); + cc->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : cc->pad_size; + PK11_FreeSlot(slot); + + /* create PK11 cipher context */ + ciphercx = PK11_CreateContextBySymKey(mechanism, CKA_DECRYPT, key, param); + SECITEM_FreeItem(param, PR_TRUE); + if (ciphercx == NULL) { + PORT_Free (cc); + return NULL; + } + + cc->cx = ciphercx; + cc->doit = (nss_cms_cipher_function) PK11_CipherOp; + cc->destroy = (nss_cms_cipher_destroy) PK11_DestroyContext; + cc->encrypt = PR_FALSE; + cc->pending_count = 0; + + return cc; +#endif +} + +/* + * SecCmsCipherContextStartEncrypt - create a cipher object to do encryption, + * based on the given bulk encryption key and algorithm tag. Fill in the algorithm + * identifier (which may include an iv) appropriately. + * + * XXX Once both are working, it might be nice to combine this and the + * function above (for starting up decryption) into one routine, and just + * have two simple cover functions which call it. + */ +SecCmsCipherContextRef +SecCmsCipherContextStartEncrypt(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorithmID *algid) +{ + return SecCmsCipherContextStart(poolp, key, algid, PR_TRUE); +#if 0 + SecCmsCipherContextRef cc; + void *ciphercx; + CSSM_DATA_PTR param; + OSStatus rv; + CK_MECHANISM_TYPE mechanism; + PK11SlotInfo *slot; + Boolean needToEncodeAlgid = PR_FALSE; + SECOidTag algtag = SECOID_GetAlgorithmTag(algid); + + /* set param and mechanism */ + if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { + CK_MECHANISM pbeMech, cryptoMech; + CSSM_DATA_PTR pbeParams; + SEC_PKCS5KeyAndPassword *keyPwd; + + PORT_Memset(&pbeMech, 0, sizeof(CK_MECHANISM)); + PORT_Memset(&cryptoMech, 0, sizeof(CK_MECHANISM)); + + /* HACK ALERT! + * in this case, key is not actually a SecSymmetricKeyRef, but a SEC_PKCS5KeyAndPassword * + */ + keyPwd = (SEC_PKCS5KeyAndPassword *)key; + key = keyPwd->key; + + /* find correct PK11 mechanism and parameters to initialize pbeMech */ + pbeMech.mechanism = PK11_AlgtagToMechanism(algtag); + pbeParams = PK11_ParamFromAlgid(algid); + if (!pbeParams) + return NULL; + pbeMech.pParameter = pbeParams->Data; + pbeMech.ulParameterLen = pbeParams->Length; + + /* now map pbeMech to cryptoMech */ + if (PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, keyPwd->pwitem, + PR_FALSE) != CKR_OK) { + SECITEM_ZfreeItem(pbeParams, PR_TRUE); + return NULL; + } + SECITEM_ZfreeItem(pbeParams, PR_TRUE); + + /* and use it to initialize param & mechanism */ + if ((param = (CSSM_DATA_PTR)PORT_ZAlloc(sizeof(CSSM_DATA))) == NULL) + return NULL; + + param->Data = (unsigned char *)cryptoMech.pParameter; + param->Length = cryptoMech.ulParameterLen; + mechanism = cryptoMech.mechanism; + } else { + mechanism = PK11_AlgtagToMechanism(algtag); + if ((param = PK11_GenerateNewParam(mechanism, key)) == NULL) + return NULL; + needToEncodeAlgid = PR_TRUE; + } + + cc = (SecCmsCipherContextRef)PORT_ZAlloc(sizeof(SecCmsCipherContext)); + if (cc == NULL) + return NULL; + + /* now find pad and block sizes for our mechanism */ + cc->pad_size = PK11_GetBlockSize(mechanism,param); + slot = PK11_GetSlotFromKey(key); + cc->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : cc->pad_size; + PK11_FreeSlot(slot); + + /* and here we go, creating a PK11 cipher context */ + ciphercx = PK11_CreateContextBySymKey(mechanism, CKA_ENCRYPT, key, param); + if (ciphercx == NULL) { + PORT_Free(cc); + cc = NULL; + goto loser; + } + + /* + * These are placed after the CreateContextBySymKey() because some + * mechanisms have to generate their IVs from their card (i.e. FORTEZZA). + * Don't move it from here. + * XXX is that right? the purpose of this is to get the correct algid + * containing the IVs etc. for encoding. this means we need to set this up + * BEFORE encoding the algid in the contentInfo, right? + */ + if (needToEncodeAlgid) { + rv = PK11_ParamToAlgid(algtag, param, poolp, algid); + if(rv != SECSuccess) { + PORT_Free(cc); + cc = NULL; + goto loser; + } + } + + cc->cx = ciphercx; + cc->doit = (nss_cms_cipher_function)PK11_CipherOp; + cc->destroy = (nss_cms_cipher_destroy)PK11_DestroyContext; + cc->encrypt = PR_TRUE; + cc->pending_count = 0; + +loser: + SECITEM_FreeItem(param, PR_TRUE); + + return cc; +#endif +} + +void +SecCmsCipherContextDestroy(SecCmsCipherContextRef cc) +{ + PORT_Assert(cc != NULL); + if (cc == NULL) + return; + CSSM_DeleteContext(cc->cc); + PORT_Free(cc); +} + +static unsigned int +SecCmsCipherContextLength(SecCmsCipherContextRef cc, unsigned int input_len, Boolean final, Boolean encrypt) +{ + CSSM_QUERY_SIZE_DATA dataBlockSize[2] = { { input_len, 0 }, { input_len, 0 } }; + /* Hack CDSA treats the last block as the final one. So unless we are being asked to report the final size we ask for 2 block and ignore the second (final) one. */ + OSStatus rv = CSSM_QuerySize(cc->cc, cc->encrypt, final ? 1 : 2, dataBlockSize); + if (rv) + { + PORT_SetError(rv); + return 0; + } + + return dataBlockSize[0].SizeOutputBlock; +} + +/* + * SecCmsCipherContextDecryptLength - find the output length of the next call to decrypt. + * + * cc - the cipher context + * input_len - number of bytes used as input + * final - true if this is the final chunk of data + * + * Result can be used to perform memory allocations. Note that the amount + * is exactly accurate only when not doing a block cipher or when final + * is false, otherwise it is an upper bound on the amount because until + * we see the data we do not know how many padding bytes there are + * (always between 1 and bsize). + * + * Note that this can return zero, which does not mean that the decrypt + * operation can be skipped! (It simply means that there are not enough + * bytes to make up an entire block; the bytes will be reserved until + * there are enough to encrypt/decrypt at least one block.) However, + * if zero is returned it *does* mean that no output buffer need be + * passed in to the subsequent decrypt operation, as no output bytes + * will be stored. + */ +size_t +SecCmsCipherContextDecryptLength(SecCmsCipherContextRef cc, size_t input_len, Boolean final) +{ +#if 1 + return SecCmsCipherContextLength(cc, (unsigned int)input_len, final, PR_FALSE); +#else + int blocks, block_size; + + PORT_Assert (! cc->encrypt); + + block_size = cc->block_size; + + /* + * If this is not a block cipher, then we always have the same + * number of output bytes as we had input bytes. + */ + if (block_size == 0) + return input_len; + + /* + * On the final call, we will always use up all of the pending + * bytes plus all of the input bytes, *but*, there will be padding + * at the end and we cannot predict how many bytes of padding we + * will end up removing. The amount given here is actually known + * to be at least 1 byte too long (because we know we will have + * at least 1 byte of padding), but seemed clearer/better to me. + */ + if (final) + return cc->pending_count + input_len; + + /* + * Okay, this amount is exactly what we will output on the + * next cipher operation. We will always hang onto the last + * 1 - block_size bytes for non-final operations. That is, + * we will do as many complete blocks as we can *except* the + * last block (complete or partial). (This is because until + * we know we are at the end, we cannot know when to interpret + * and removing the padding byte(s), which are guaranteed to + * be there.) + */ + blocks = (cc->pending_count + input_len - 1) / block_size; + return blocks * block_size; +#endif +} + +/* + * SecCmsCipherContextEncryptLength - find the output length of the next call to encrypt. + * + * cc - the cipher context + * input_len - number of bytes used as input + * final - true if this is the final chunk of data + * + * Result can be used to perform memory allocations. + * + * Note that this can return zero, which does not mean that the encrypt + * operation can be skipped! (It simply means that there are not enough + * bytes to make up an entire block; the bytes will be reserved until + * there are enough to encrypt/decrypt at least one block.) However, + * if zero is returned it *does* mean that no output buffer need be + * passed in to the subsequent encrypt operation, as no output bytes + * will be stored. + */ +size_t +SecCmsCipherContextEncryptLength(SecCmsCipherContextRef cc, size_t input_len, Boolean final) +{ +#if 1 + return SecCmsCipherContextLength(cc, (unsigned int)input_len, final, PR_TRUE); +#else + int blocks, block_size; + int pad_size; + + PORT_Assert (cc->encrypt); + + block_size = cc->block_size; + pad_size = cc->pad_size; + + /* + * If this is not a block cipher, then we always have the same + * number of output bytes as we had input bytes. + */ + if (block_size == 0) + return input_len; + + /* + * On the final call, we only send out what we need for + * remaining bytes plus the padding. (There is always padding, + * so even if we have an exact number of blocks as input, we + * will add another full block that is just padding.) + */ + if (final) { + if (pad_size == 0) { + return cc->pending_count + input_len; + } else { + blocks = (cc->pending_count + input_len) / pad_size; + blocks++; + return blocks*pad_size; + } + } + + /* + * Now, count the number of complete blocks of data we have. + */ + blocks = (cc->pending_count + input_len) / block_size; + + + return blocks * block_size; +#endif +} + + +static OSStatus +SecCmsCipherContextCrypt(SecCmsCipherContextRef cc, unsigned char *output, + size_t *output_len_p, size_t max_output_len, + const unsigned char *input, size_t input_len, + Boolean final, Boolean encrypt) +{ + CSSM_DATA outputBuf = { max_output_len, output }; + CSSM_SIZE bytes_output = 0; + OSStatus rv = 0; + + if (input_len) + { + CSSM_DATA inputBuf = { input_len, (uint8 *)input }; + + if (encrypt) + rv = CSSM_EncryptDataUpdate(cc->cc, &inputBuf, 1, &outputBuf, 1, &bytes_output); + else + rv = CSSM_DecryptDataUpdate(cc->cc, &inputBuf, 1, &outputBuf, 1, &bytes_output); + } + + if (!rv && final) + { + CSSM_DATA remainderBuf = { max_output_len - bytes_output, output + bytes_output }; + if (encrypt) + rv = CSSM_EncryptDataFinal(cc->cc, &remainderBuf); + else + rv = CSSM_DecryptDataFinal(cc->cc, &remainderBuf); + + bytes_output += remainderBuf.Length; + } + + if (rv) + PORT_SetError(SEC_ERROR_BAD_DATA); + else if (output_len_p) + *output_len_p = bytes_output; + + return rv; +} + +/* + * SecCmsCipherContextDecrypt - do the decryption + * + * cc - the cipher context + * output - buffer for decrypted result bytes + * output_len_p - number of bytes in output + * max_output_len - upper bound on bytes to put into output + * input - pointer to input bytes + * input_len - number of input bytes + * final - true if this is the final chunk of data + * + * Decrypts a given length of input buffer (starting at "input" and + * containing "input_len" bytes), placing the decrypted bytes in + * "output" and storing the output length in "*output_len_p". + * "cc" is the return value from SecCmsCipherStartDecrypt. + * When "final" is true, this is the last of the data to be decrypted. + * + * This is much more complicated than it sounds when the cipher is + * a block-type, meaning that the decryption function will only + * operate on whole blocks. But our caller is operating stream-wise, + * and can pass in any number of bytes. So we need to keep track + * of block boundaries. We save excess bytes between calls in "cc". + * We also need to determine which bytes are padding, and remove + * them from the output. We can only do this step when we know we + * have the final block of data. PKCS #7 specifies that the padding + * used for a block cipher is a string of bytes, each of whose value is + * the same as the length of the padding, and that all data is padded. + * (Even data that starts out with an exact multiple of blocks gets + * added to it another block, all of which is padding.) + */ +OSStatus +SecCmsCipherContextDecrypt(SecCmsCipherContextRef cc, unsigned char *output, + size_t *output_len_p, size_t max_output_len, + const unsigned char *input, size_t input_len, + Boolean final) +{ +#if 1 + return SecCmsCipherContextCrypt(cc, output, + output_len_p, max_output_len, + input, input_len, + final, PR_FALSE); +#else + int blocks, bsize, pcount, padsize; + unsigned int max_needed, ifraglen, ofraglen, output_len; + unsigned char *pbuf; + OSStatus rv; + + PORT_Assert (! cc->encrypt); + + /* + * Check that we have enough room for the output. Our caller should + * already handle this; failure is really an internal error (i.e. bug). + */ + max_needed = SecCmsCipherContextDecryptLength(cc, input_len, final); + PORT_Assert (max_output_len >= max_needed); + if (max_output_len < max_needed) { + /* PORT_SetError (XXX); */ + return SECFailure; + } + + /* + * hardware encryption does not like small decryption sizes here, so we + * allow both blocking and padding. + */ + bsize = cc->block_size; + padsize = cc->pad_size; + + /* + * When no blocking or padding work to do, we can simply call the + * cipher function and we are done. + */ + if (bsize == 0) { + return (* cc->doit) (cc->cx, output, output_len_p, max_output_len, + input, input_len); + } + + pcount = cc->pending_count; + pbuf = cc->pending_buf; + + output_len = 0; + + if (pcount) { + /* + * Try to fill in an entire block, starting with the bytes + * we already have saved away. + */ + while (input_len && pcount < bsize) { + pbuf[pcount++] = *input++; + input_len--; + } + /* + * If we have at most a whole block and this is not our last call, + * then we are done for now. (We do not try to decrypt a lone + * single block because we cannot interpret the padding bytes + * until we know we are handling the very last block of all input.) + */ + if (input_len == 0 && !final) { + cc->pending_count = pcount; + if (output_len_p) + *output_len_p = 0; + return SECSuccess; + } + /* + * Given the logic above, we expect to have a full block by now. + * If we do not, there is something wrong, either with our own + * logic or with (length of) the data given to us. + */ + if ((padsize != 0) && (pcount % padsize) != 0) { + PORT_Assert (final); + PORT_SetError (SEC_ERROR_BAD_DATA); + return SECFailure; + } + /* + * Decrypt the block. + */ + rv = (*cc->doit)(cc->cx, output, &ofraglen, max_output_len, + pbuf, pcount); + if (rv != SECSuccess) + return rv; + + /* + * For now anyway, all of our ciphers have the same number of + * bytes of output as they do input. If this ever becomes untrue, + * then SecCmsCipherContextDecryptLength needs to be made smarter! + */ + PORT_Assert(ofraglen == pcount); + + /* + * Account for the bytes now in output. + */ + max_output_len -= ofraglen; + output_len += ofraglen; + output += ofraglen; + } + + /* + * If this is our last call, we expect to have an exact number of + * blocks left to be decrypted; we will decrypt them all. + * + * If not our last call, we always save between 1 and bsize bytes + * until next time. (We must do this because we cannot be sure + * that none of the decrypted bytes are padding bytes until we + * have at least another whole block of data. You cannot tell by + * looking -- the data could be anything -- you can only tell by + * context, knowing you are looking at the last block.) We could + * decrypt a whole block now but it is easier if we just treat it + * the same way we treat partial block bytes. + */ + if (final) { + if (padsize) { + blocks = input_len / padsize; + ifraglen = blocks * padsize; + } else ifraglen = input_len; + PORT_Assert (ifraglen == input_len); + + if (ifraglen != input_len) { + PORT_SetError(SEC_ERROR_BAD_DATA); + return SECFailure; + } + } else { + blocks = (input_len - 1) / bsize; + ifraglen = blocks * bsize; + PORT_Assert (ifraglen < input_len); + + pcount = input_len - ifraglen; + PORT_Memcpy (pbuf, input + ifraglen, pcount); + cc->pending_count = pcount; + } + + if (ifraglen) { + rv = (* cc->doit)(cc->cx, output, &ofraglen, max_output_len, + input, ifraglen); + if (rv != SECSuccess) + return rv; + + /* + * For now anyway, all of our ciphers have the same number of + * bytes of output as they do input. If this ever becomes untrue, + * then sec_PKCS7DecryptLength needs to be made smarter! + */ + PORT_Assert (ifraglen == ofraglen); + if (ifraglen != ofraglen) { + PORT_SetError(SEC_ERROR_BAD_DATA); + return SECFailure; + } + + output_len += ofraglen; + } else { + ofraglen = 0; + } + + /* + * If we just did our very last block, "remove" the padding by + * adjusting the output length. + */ + if (final && (padsize != 0)) { + unsigned int padlen = *(output + ofraglen - 1); + + if (padlen == 0 || padlen > padsize) { + PORT_SetError(SEC_ERROR_BAD_DATA); + return SECFailure; + } + output_len -= padlen; + } + + PORT_Assert (output_len_p != NULL || output_len == 0); + if (output_len_p != NULL) + *output_len_p = output_len; + + return SECSuccess; +#endif +} + +/* + * SecCmsCipherContextEncrypt - do the encryption + * + * cc - the cipher context + * output - buffer for decrypted result bytes + * output_len_p - number of bytes in output + * max_output_len - upper bound on bytes to put into output + * input - pointer to input bytes + * input_len - number of input bytes + * final - true if this is the final chunk of data + * + * Encrypts a given length of input buffer (starting at "input" and + * containing "input_len" bytes), placing the encrypted bytes in + * "output" and storing the output length in "*output_len_p". + * "cc" is the return value from SecCmsCipherStartEncrypt. + * When "final" is true, this is the last of the data to be encrypted. + * + * This is much more complicated than it sounds when the cipher is + * a block-type, meaning that the encryption function will only + * operate on whole blocks. But our caller is operating stream-wise, + * and can pass in any number of bytes. So we need to keep track + * of block boundaries. We save excess bytes between calls in "cc". + * We also need to add padding bytes at the end. PKCS #7 specifies + * that the padding used for a block cipher is a string of bytes, + * each of whose value is the same as the length of the padding, + * and that all data is padded. (Even data that starts out with + * an exact multiple of blocks gets added to it another block, + * all of which is padding.) + * + * XXX I would kind of like to combine this with the function above + * which does decryption, since they have a lot in common. But the + * tricky parts about padding and filling blocks would be much + * harder to read that way, so I left them separate. At least for + * now until it is clear that they are right. + */ +OSStatus +SecCmsCipherContextEncrypt(SecCmsCipherContextRef cc, unsigned char *output, + size_t *output_len_p, size_t max_output_len, + const unsigned char *input, size_t input_len, + Boolean final) +{ +#if 1 + return SecCmsCipherContextCrypt(cc, output, + output_len_p, max_output_len, + input, input_len, + final, PR_TRUE); +#else + int blocks, bsize, padlen, pcount, padsize; + unsigned int max_needed, ifraglen, ofraglen, output_len; + unsigned char *pbuf; + OSStatus rv; + + PORT_Assert (cc->encrypt); + + /* + * Check that we have enough room for the output. Our caller should + * already handle this; failure is really an internal error (i.e. bug). + */ + max_needed = SecCmsCipherContextEncryptLength (cc, input_len, final); + PORT_Assert (max_output_len >= max_needed); + if (max_output_len < max_needed) { + /* PORT_SetError (XXX); */ + return SECFailure; + } + + bsize = cc->block_size; + padsize = cc->pad_size; + + /* + * When no blocking and padding work to do, we can simply call the + * cipher function and we are done. + */ + if (bsize == 0) { + return (*cc->doit)(cc->cx, output, output_len_p, max_output_len, + input, input_len); + } + + pcount = cc->pending_count; + pbuf = cc->pending_buf; + + output_len = 0; + + if (pcount) { + /* + * Try to fill in an entire block, starting with the bytes + * we already have saved away. + */ + while (input_len && pcount < bsize) { + pbuf[pcount++] = *input++; + input_len--; + } + /* + * If we do not have a full block and we know we will be + * called again, then we are done for now. + */ + if (pcount < bsize && !final) { + cc->pending_count = pcount; + if (output_len_p != NULL) + *output_len_p = 0; + return SECSuccess; + } + /* + * If we have a whole block available, encrypt it. + */ + if ((padsize == 0) || (pcount % padsize) == 0) { + rv = (* cc->doit) (cc->cx, output, &ofraglen, max_output_len, + pbuf, pcount); + if (rv != SECSuccess) + return rv; + + /* + * For now anyway, all of our ciphers have the same number of + * bytes of output as they do input. If this ever becomes untrue, + * then sec_PKCS7EncryptLength needs to be made smarter! + */ + PORT_Assert (ofraglen == pcount); + + /* + * Account for the bytes now in output. + */ + max_output_len -= ofraglen; + output_len += ofraglen; + output += ofraglen; + + pcount = 0; + } + } + + if (input_len) { + PORT_Assert (pcount == 0); + + blocks = input_len / bsize; + ifraglen = blocks * bsize; + + if (ifraglen) { + rv = (* cc->doit) (cc->cx, output, &ofraglen, max_output_len, + input, ifraglen); + if (rv != SECSuccess) + return rv; + + /* + * For now anyway, all of our ciphers have the same number of + * bytes of output as they do input. If this ever becomes untrue, + * then sec_PKCS7EncryptLength needs to be made smarter! + */ + PORT_Assert (ifraglen == ofraglen); + + max_output_len -= ofraglen; + output_len += ofraglen; + output += ofraglen; + } + + pcount = input_len - ifraglen; + PORT_Assert (pcount < bsize); + if (pcount) + PORT_Memcpy (pbuf, input + ifraglen, pcount); + } + + if (final) { + padlen = padsize - (pcount % padsize); + PORT_Memset (pbuf + pcount, padlen, padlen); + rv = (* cc->doit) (cc->cx, output, &ofraglen, max_output_len, + pbuf, pcount+padlen); + if (rv != SECSuccess) + return rv; + + /* + * For now anyway, all of our ciphers have the same number of + * bytes of output as they do input. If this ever becomes untrue, + * then sec_PKCS7EncryptLength needs to be made smarter! + */ + PORT_Assert (ofraglen == (pcount+padlen)); + output_len += ofraglen; + } else { + cc->pending_count = pcount; + } + + PORT_Assert (output_len_p != NULL || output_len == 0); + if (output_len_p != NULL) + *output_len_p = output_len; + + return SECSuccess; +#endif +} diff --git a/Security/libsecurity_smime/lib/cmsdecode.c b/Security/libsecurity_smime/lib/cmsdecode.c new file mode 100644 index 00000000..f9ce1257 --- /dev/null +++ b/Security/libsecurity_smime/lib/cmsdecode.c @@ -0,0 +1,728 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * CMS decoding. + */ + +#include +#include +#include +#include + +#include "cmslocal.h" + +#include "secitem.h" +#include "secoid.h" +#include +#include + +struct SecCmsDecoderStr { + SEC_ASN1DecoderContext * dcx; /* ASN.1 decoder context */ + SecCmsMessageRef cmsg; /* backpointer to the root message */ + SECOidTag type; /* type of message */ + SecCmsContent content; /* pointer to message */ + SecCmsDecoderRef childp7dcx; /* inner CMS decoder context */ + Boolean saw_contents; + int error; + SecCmsContentCallback cb; + void * cb_arg; +}; + +static void nss_cms_decoder_update_filter (void *arg, const char *data, size_t len, + int depth, SEC_ASN1EncodingPart data_kind); +static OSStatus nss_cms_before_data(SecCmsDecoderRef p7dcx); +static OSStatus nss_cms_after_data(SecCmsDecoderRef p7dcx); +static OSStatus nss_cms_after_end(SecCmsDecoderRef p7dcx); +static void nss_cms_decoder_work_data(SecCmsDecoderRef p7dcx, + const unsigned char *data, size_t len, Boolean final); + +extern const SecAsn1Template SecCmsMessageTemplate[]; + +/* + * nss_cms_decoder_notify - + * this is the driver of the decoding process. It gets called by the ASN.1 + * decoder before and after an object is decoded. + * at various points in the decoding process, we intercept to set up and do + * further processing. + */ +static void +nss_cms_decoder_notify(void *arg, Boolean before, void *dest, int depth) +{ + SecCmsDecoderRef p7dcx; + SecCmsContentInfoRef rootcinfo, cinfo; + Boolean after = !before; + + p7dcx = (SecCmsDecoderRef)arg; + rootcinfo = &(p7dcx->cmsg->contentInfo); + + /* XXX error handling: need to set p7dcx->error */ + +#ifdef CMSDEBUG + fprintf(stderr, "%6.6s, dest = %p, depth = %d\n", before ? "before" : "after", dest, depth); +#endif + + /* so what are we working on right now? */ + switch (p7dcx->type) { + case SEC_OID_UNKNOWN: + /* + * right now, we are still decoding the OUTER (root) cinfo + * As soon as we know the inner content type, set up the info, + * but NO inner decoder or filter. The root decoder handles the first + * level children by itself - only for encapsulated contents (which + * are encoded as DER inside of an OCTET STRING) we need to set up a + * child decoder... + */ + if (after && dest == &(rootcinfo->contentType)) { + p7dcx->type = SecCmsContentInfoGetContentTypeTag(rootcinfo); + p7dcx->content = rootcinfo->content; /* is this ready already ? need to alloc? */ + /* XXX yes we need to alloc -- continue here */ + } + break; + case SEC_OID_PKCS7_DATA: + case SEC_OID_OTHER: + /* this can only happen if the outermost cinfo has DATA in it */ + /* otherwise, we handle this type implicitely in the inner decoders */ + + if (before && dest == &(rootcinfo->content)) { + /* fake it to cause the filter to put the data in the right place... */ + /* we want the ASN.1 decoder to deliver the decoded bytes to us from now on */ + SEC_ASN1DecoderSetFilterProc(p7dcx->dcx, + nss_cms_decoder_update_filter, + p7dcx, + (Boolean)(p7dcx->cb != NULL)); + break; + } + + if (after && dest == &(rootcinfo->content.data)) { + /* remove the filter */ + SEC_ASN1DecoderClearFilterProc(p7dcx->dcx); + } + break; + + case SEC_OID_PKCS7_SIGNED_DATA: + case SEC_OID_PKCS7_ENVELOPED_DATA: + case SEC_OID_PKCS7_DIGESTED_DATA: + case SEC_OID_PKCS7_ENCRYPTED_DATA: + + if (before && dest == &(rootcinfo->content)) + break; /* we're not there yet */ + + if (p7dcx->content.pointer == NULL) + p7dcx->content = rootcinfo->content; + + /* get this data type's inner contentInfo */ + cinfo = SecCmsContentGetContentInfo(p7dcx->content.pointer, p7dcx->type); + + if (before && dest == &(cinfo->contentType)) { + /* at this point, set up the &%$&$ back pointer */ + /* we cannot do it later, because the content itself is optional! */ + /* please give me C++ */ + switch (p7dcx->type) { + case SEC_OID_PKCS7_SIGNED_DATA: + p7dcx->content.signedData->cmsg = p7dcx->cmsg; + break; + case SEC_OID_PKCS7_DIGESTED_DATA: + p7dcx->content.digestedData->cmsg = p7dcx->cmsg; + break; + case SEC_OID_PKCS7_ENVELOPED_DATA: + p7dcx->content.envelopedData->cmsg = p7dcx->cmsg; + break; + case SEC_OID_PKCS7_ENCRYPTED_DATA: + p7dcx->content.encryptedData->cmsg = p7dcx->cmsg; + break; + default: + PORT_Assert(0); + break; + } + } + + if (before && dest == &(cinfo->rawContent)) { + /* we want the ASN.1 decoder to deliver the decoded bytes to us from now on */ + SEC_ASN1DecoderSetFilterProc(p7dcx->dcx, nss_cms_decoder_update_filter, + p7dcx, (Boolean)(p7dcx->cb != NULL)); + + + /* we're right in front of the data */ + if (nss_cms_before_data(p7dcx) != SECSuccess) { + SEC_ASN1DecoderClearFilterProc(p7dcx->dcx); /* stop all processing */ + p7dcx->error = PORT_GetError(); + } + } + if (after && dest == &(cinfo->rawContent)) { + /* we're right after of the data */ + if (nss_cms_after_data(p7dcx) != SECSuccess) + p7dcx->error = PORT_GetError(); + + /* we don't need to see the contents anymore */ + SEC_ASN1DecoderClearFilterProc(p7dcx->dcx); + } + break; + +#if 0 /* NIH */ + case SEC_OID_PKCS7_AUTHENTICATED_DATA: +#endif + default: + /* unsupported or unknown message type - fail (more or less) gracefully */ + p7dcx->error = SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE; + break; + } +} + +/* + * nss_cms_before_data - set up the current encoder to receive data + */ +static OSStatus +nss_cms_before_data(SecCmsDecoderRef p7dcx) +{ + OSStatus rv; + SECOidTag childtype; + PLArenaPool *poolp; + SecCmsDecoderRef childp7dcx; + SecCmsContentInfoRef cinfo; + const SecAsn1Template *template; + void *mark = NULL; + size_t size; + + poolp = p7dcx->cmsg->poolp; + + /* call _Decode_BeforeData handlers */ + switch (p7dcx->type) { + case SEC_OID_PKCS7_SIGNED_DATA: + /* we're decoding a signedData, so set up the digests */ + rv = SecCmsSignedDataDecodeBeforeData(p7dcx->content.signedData); + if (rv != SECSuccess) + return SECFailure; + break; + case SEC_OID_PKCS7_DIGESTED_DATA: + /* we're encoding a digestedData, so set up the digest */ + rv = SecCmsDigestedDataDecodeBeforeData(p7dcx->content.digestedData); + if (rv != SECSuccess) + return SECFailure; + break; + case SEC_OID_PKCS7_ENVELOPED_DATA: + rv = SecCmsEnvelopedDataDecodeBeforeData(p7dcx->content.envelopedData); + if (rv != SECSuccess) + return SECFailure; + break; + case SEC_OID_PKCS7_ENCRYPTED_DATA: + rv = SecCmsEncryptedDataDecodeBeforeData(p7dcx->content.encryptedData); + if (rv != SECSuccess) + return SECFailure; + break; + default: + return SECFailure; + } + + /* ok, now we have a pointer to cinfo */ + /* find out what kind of data is encapsulated */ + + cinfo = SecCmsContentGetContentInfo(p7dcx->content.pointer, p7dcx->type); + childtype = SecCmsContentInfoGetContentTypeTag(cinfo); + + /* special case for SignedData: "unknown" child type maps to SEC_OID_OTHER */ + if((childtype == SEC_OID_UNKNOWN) && (p7dcx->type == SEC_OID_PKCS7_SIGNED_DATA)) { + childtype = SEC_OID_OTHER; + } + + if ((childtype == SEC_OID_PKCS7_DATA) || (childtype == SEC_OID_OTHER)){ + cinfo->content.data = SECITEM_AllocItem(poolp, NULL, 0); + if (cinfo->content.data == NULL) + /* set memory error */ + return SECFailure; + + p7dcx->childp7dcx = NULL; + return SECSuccess; + } + + /* set up inner decoder */ + + if ((template = SecCmsUtilGetTemplateByTypeTag(childtype)) == NULL) + return SECFailure; + + childp7dcx = (SecCmsDecoderRef)PORT_ZAlloc(sizeof(struct SecCmsDecoderStr)); + if (childp7dcx == NULL) + return SECFailure; + + mark = PORT_ArenaMark(poolp); + + /* allocate space for the stuff we're creating */ + size = SecCmsUtilGetSizeByTypeTag(childtype); + childp7dcx->content.pointer = (void *)PORT_ArenaZAlloc(poolp, size); + if (childp7dcx->content.pointer == NULL) + goto loser; + + /* Apple: link the new content to parent ContentInfo */ + cinfo->content.pointer = childp7dcx->content.pointer; + + /* start the child decoder */ + childp7dcx->dcx = SEC_ASN1DecoderStart(poolp, childp7dcx->content.pointer, template, NULL); + if (childp7dcx->dcx == NULL) + goto loser; + + /* the new decoder needs to notify, too */ + SEC_ASN1DecoderSetNotifyProc(childp7dcx->dcx, nss_cms_decoder_notify, childp7dcx); + + /* tell the parent decoder that it needs to feed us the content data */ + p7dcx->childp7dcx = childp7dcx; + + childp7dcx->type = childtype; /* our type */ + + childp7dcx->cmsg = p7dcx->cmsg; /* backpointer to root message */ + + /* should the child decoder encounter real data, it needs to give it to the caller */ + childp7dcx->cb = p7dcx->cb; + childp7dcx->cb_arg = p7dcx->cb_arg; + + /* now set up the parent to hand decoded data to the next level decoder */ + p7dcx->cb = (SecCmsContentCallback)SecCmsDecoderUpdate; + p7dcx->cb_arg = childp7dcx; + + PORT_ArenaUnmark(poolp, mark); + + return SECSuccess; + +loser: + if (mark) + PORT_ArenaRelease(poolp, mark); + if (childp7dcx) + PORT_Free(childp7dcx); + p7dcx->childp7dcx = NULL; + return SECFailure; +} + +static OSStatus +nss_cms_after_data(SecCmsDecoderRef p7dcx) +{ + PLArenaPool *poolp; + SecCmsDecoderRef childp7dcx; + OSStatus rv = SECFailure; + + poolp = p7dcx->cmsg->poolp; + + /* Handle last block. This is necessary to flush out the last bytes + * of a possibly incomplete block */ + nss_cms_decoder_work_data(p7dcx, NULL, 0, PR_TRUE); + + /* finish any "inner" decoders - there's no more data coming... */ + if (p7dcx->childp7dcx != NULL) { + childp7dcx = p7dcx->childp7dcx; + if (childp7dcx->dcx != NULL) { + if (SEC_ASN1DecoderFinish(childp7dcx->dcx) != SECSuccess) { + /* do what? free content? */ + rv = SECFailure; + } else { + rv = nss_cms_after_end(childp7dcx); + } + if (rv != SECSuccess) + goto done; + } + PORT_Free(p7dcx->childp7dcx); + p7dcx->childp7dcx = NULL; + } + + switch (p7dcx->type) { + case SEC_OID_PKCS7_SIGNED_DATA: + /* this will finish the digests and verify */ + rv = SecCmsSignedDataDecodeAfterData(p7dcx->content.signedData); + break; + case SEC_OID_PKCS7_ENVELOPED_DATA: + rv = SecCmsEnvelopedDataDecodeAfterData(p7dcx->content.envelopedData); + break; + case SEC_OID_PKCS7_DIGESTED_DATA: + rv = SecCmsDigestedDataDecodeAfterData(p7dcx->content.digestedData); + break; + case SEC_OID_PKCS7_ENCRYPTED_DATA: + rv = SecCmsEncryptedDataDecodeAfterData(p7dcx->content.encryptedData); + break; + case SEC_OID_PKCS7_DATA: + /* do nothing */ + break; + default: + rv = SECFailure; + break; + } +done: + return rv; +} + +static OSStatus +nss_cms_after_end(SecCmsDecoderRef p7dcx) +{ + OSStatus rv; + PLArenaPool *poolp; + + poolp = p7dcx->cmsg->poolp; + + switch (p7dcx->type) { + case SEC_OID_PKCS7_SIGNED_DATA: + rv = SecCmsSignedDataDecodeAfterEnd(p7dcx->content.signedData); + break; + case SEC_OID_PKCS7_ENVELOPED_DATA: + rv = SecCmsEnvelopedDataDecodeAfterEnd(p7dcx->content.envelopedData); + break; + case SEC_OID_PKCS7_DIGESTED_DATA: + rv = SecCmsDigestedDataDecodeAfterEnd(p7dcx->content.digestedData); + break; + case SEC_OID_PKCS7_ENCRYPTED_DATA: + rv = SecCmsEncryptedDataDecodeAfterEnd(p7dcx->content.encryptedData); + break; + case SEC_OID_PKCS7_DATA: + rv = SECSuccess; + break; + default: + rv = SECFailure; /* we should not have got that far... */ + break; + } + return rv; +} + +/* + * nss_cms_decoder_work_data - handle decoded data bytes. + * + * This function either decrypts the data if needed, and/or calculates digests + * on it, then either stores it or passes it on to the next level decoder. + */ +static void +nss_cms_decoder_work_data(SecCmsDecoderRef p7dcx, + const unsigned char *data, size_t len, + Boolean final) +{ + SecCmsContentInfoRef cinfo; + unsigned char *buf = NULL; + unsigned char *dest; + CSSM_SIZE offset; + OSStatus rv; + CSSM_DATA_PTR storage; + + /* + * We should really have data to process, or we should be trying + * to finish/flush the last block. (This is an overly paranoid + * check since all callers are in this file and simple inspection + * proves they do it right. But it could find a bug in future + * modifications/development, that is why it is here.) + */ + PORT_Assert ((data != NULL && len) || final); + + if (!p7dcx->content.pointer) // might be ExContent?? + return; + + cinfo = SecCmsContentGetContentInfo(p7dcx->content.pointer, p7dcx->type); + + if (cinfo->ciphcx != NULL) { + /* + * we are decrypting. + * + * XXX If we get an error, we do not want to do the digest or callback, + * but we want to keep decoding. Or maybe we want to stop decoding + * altogether if there is a callback, because obviously we are not + * sending the data back and they want to know that. + */ + + CSSM_SIZE outlen = 0; /* length of decrypted data */ + CSSM_SIZE buflen; /* length available for decrypted data */ + + /* find out about the length of decrypted data */ + buflen = SecCmsCipherContextDecryptLength(cinfo->ciphcx, len, final); + + /* + * it might happen that we did not provide enough data for a full + * block (decryption unit), and that there is no output available + */ + + /* no output available, AND no input? */ + if (buflen == 0 && len == 0) + goto loser; /* bail out */ + + /* + * have inner decoder: pass the data on (means inner content type is NOT data) + * no inner decoder: we have DATA in here: either call callback or store + */ + if (buflen != 0) { + /* there will be some output - need to make room for it */ + /* allocate buffer from the heap */ + buf = (unsigned char *)PORT_Alloc(buflen); + if (buf == NULL) { + p7dcx->error = SEC_ERROR_NO_MEMORY; + goto loser; + } + } + + /* + * decrypt incoming data + * buf can still be NULL here (and buflen == 0) here if we don't expect + * any output (see above), but we still need to call SecCmsCipherContextDecrypt to + * keep track of incoming data + */ + rv = SecCmsCipherContextDecrypt(cinfo->ciphcx, buf, &outlen, buflen, + data, len, final); + if (rv != SECSuccess) { + p7dcx->error = PORT_GetError(); + goto loser; + } + + PORT_Assert (final || outlen == buflen); + + /* swap decrypted data in */ + data = buf; + len = outlen; + } + + if (len == 0) + goto done; /* nothing more to do */ + + /* + * Update the running digests with plaintext bytes (if we need to). + */ + if (cinfo->digcx) + SecCmsDigestContextUpdate(cinfo->digcx, data, len); + + /* at this point, we have the plain decoded & decrypted data */ + /* which is either more encoded DER which we need to hand to the child decoder */ + /* or data we need to hand back to our caller */ + + /* pass the content back to our caller or */ + /* feed our freshly decrypted and decoded data into child decoder */ + if (p7dcx->cb != NULL) { + (*p7dcx->cb)(p7dcx->cb_arg, (const char *)data, len); + } +#if 1 + else +#endif + switch(SecCmsContentInfoGetContentTypeTag(cinfo)) { + default: + break; + case SEC_OID_PKCS7_DATA: + case SEC_OID_OTHER: + /* store it in "inner" data item as well */ + /* find the DATA item in the encapsulated cinfo and store it there */ + storage = cinfo->content.data; + + offset = storage->Length; + if (storage->Length == 0) { + dest = (unsigned char *)PORT_ArenaAlloc(p7dcx->cmsg->poolp, len); + } else { + dest = (unsigned char *)PORT_ArenaGrow(p7dcx->cmsg->poolp, + storage->Data, + storage->Length, + storage->Length + len); + } + if (dest == NULL) { + p7dcx->error = SEC_ERROR_NO_MEMORY; + goto loser; + } + + storage->Data = dest; + storage->Length += len; + + /* copy it in */ + PORT_Memcpy(storage->Data + offset, data, len); + } + +done: +loser: + if (buf) + PORT_Free (buf); +} + +/* + * nss_cms_decoder_update_filter - process ASN.1 data + * + * once we have set up a filter in nss_cms_decoder_notify(), + * all data processed by the ASN.1 decoder is also passed through here. + * we pass the content bytes (as opposed to length and tag bytes) on to + * nss_cms_decoder_work_data(). + */ +static void +nss_cms_decoder_update_filter (void *arg, const char *data, size_t len, + int depth, SEC_ASN1EncodingPart data_kind) +{ + SecCmsDecoderRef p7dcx; + + PORT_Assert (len); /* paranoia */ + if (len == 0) + return; + + p7dcx = (SecCmsDecoderRef)arg; + + p7dcx->saw_contents = PR_TRUE; + + /* pass on the content bytes only */ + if (data_kind == SEC_ASN1_Contents) + nss_cms_decoder_work_data(p7dcx, (const unsigned char *) data, len, PR_FALSE); +} + +/* + * SecCmsDecoderCreate - set up decoding of a BER-encoded CMS message + */ +OSStatus +SecCmsDecoderCreate(SecArenaPoolRef pool, + SecCmsContentCallback cb, void *cb_arg, + PK11PasswordFunc pwfn, void *pwfn_arg, + SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg, + SecCmsDecoderRef *outDecoder) +{ + SecCmsDecoderRef p7dcx; + SecCmsMessageRef cmsg; + OSStatus result; + + cmsg = SecCmsMessageCreate(pool); + if (cmsg == NULL) + goto loser; + + SecCmsMessageSetEncodingParams(cmsg, pwfn, pwfn_arg, decrypt_key_cb, decrypt_key_cb_arg, + NULL, NULL); + + p7dcx = (SecCmsDecoderRef)PORT_ZAlloc(sizeof(struct SecCmsDecoderStr)); + if (p7dcx == NULL) { + SecCmsMessageDestroy(cmsg); + goto loser; + } + + p7dcx->dcx = SEC_ASN1DecoderStart(cmsg->poolp, cmsg, SecCmsMessageTemplate, NULL); + if (p7dcx->dcx == NULL) { + PORT_Free (p7dcx); + SecCmsMessageDestroy(cmsg); + goto loser; + } + + SEC_ASN1DecoderSetNotifyProc (p7dcx->dcx, nss_cms_decoder_notify, p7dcx); + + p7dcx->cmsg = cmsg; + p7dcx->type = SEC_OID_UNKNOWN; + + p7dcx->cb = cb; + p7dcx->cb_arg = cb_arg; + + *outDecoder = p7dcx; + return noErr; + +loser: + result = PORT_GetError(); + return result; +} + +/* + * SecCmsDecoderUpdate - feed DER-encoded data to decoder + */ +OSStatus +SecCmsDecoderUpdate(SecCmsDecoderRef p7dcx, const void *buf, CFIndex len) +{ + if (p7dcx->dcx != NULL && p7dcx->error == 0) { /* if error is set already, don't bother */ + if (SEC_ASN1DecoderUpdate (p7dcx->dcx, buf, len) != SECSuccess) { + p7dcx->error = PORT_GetError(); + PORT_Assert (p7dcx->error); + if (p7dcx->error == 0) + p7dcx->error = -1; + } + } + + if (p7dcx->error == 0) + return 0; + + /* there has been a problem, let's finish the decoder */ + if (p7dcx->dcx != NULL) { + /* @@@ Change this to SEC_ASN1DecoderAbort()? */ + (void) SEC_ASN1DecoderFinish (p7dcx->dcx); + p7dcx->dcx = NULL; + } + PORT_SetError (p7dcx->error); + + return p7dcx->error; +} + +/* + * SecCmsDecoderDestroy - stop decoding in case of error + */ +void +SecCmsDecoderDestroy(SecCmsDecoderRef p7dcx) +{ + /* XXXX what about inner decoders? running digests? decryption? */ + /* XXXX there's a leak here! */ + SecCmsMessageDestroy(p7dcx->cmsg); + if (p7dcx->dcx) + (void)SEC_ASN1DecoderFinish(p7dcx->dcx); + PORT_Free(p7dcx); +} + +/* + * SecCmsDecoderFinish - mark the end of inner content and finish decoding + */ +OSStatus +SecCmsDecoderFinish(SecCmsDecoderRef p7dcx, SecCmsMessageRef *outMessage) +{ + SecCmsMessageRef cmsg; + OSStatus result; + + cmsg = p7dcx->cmsg; + + if (p7dcx->dcx == NULL || SEC_ASN1DecoderFinish(p7dcx->dcx) != SECSuccess || + nss_cms_after_end(p7dcx) != SECSuccess) + { + SecCmsMessageDestroy(cmsg); /* needs to get rid of pool if it's ours */ + result = PORT_GetError(); + goto loser; + } + + *outMessage = cmsg; + result = noErr; + +loser: + PORT_Free(p7dcx); + return result; +} + +OSStatus +SecCmsMessageDecode(const CSSM_DATA *encodedMessage, + SecCmsContentCallback cb, void *cb_arg, + PK11PasswordFunc pwfn, void *pwfn_arg, + SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg, + SecCmsMessageRef *outMessage) +{ + OSStatus result; + SecCmsDecoderRef decoder; + + result = SecCmsDecoderCreate(NULL, cb, cb_arg, pwfn, pwfn_arg, decrypt_key_cb, decrypt_key_cb_arg, &decoder); + if (result) + goto loser; + result = SecCmsDecoderUpdate(decoder, encodedMessage->Data, encodedMessage->Length); + if (result) { + SecCmsDecoderDestroy(decoder); + goto loser; + } + + result = SecCmsDecoderFinish(decoder, outMessage); +loser: + return result; +} + diff --git a/Security/libsecurity_smime/lib/cmsdigdata.c b/Security/libsecurity_smime/lib/cmsdigdata.c new file mode 100644 index 00000000..8fb7d5e5 --- /dev/null +++ b/Security/libsecurity_smime/lib/cmsdigdata.c @@ -0,0 +1,229 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * CMS digestedData methods. + */ + +#include + +#include +#include + +#include "cmslocal.h" + +#include "secitem.h" +#include "secoid.h" +#include +#include + +/* + * SecCmsDigestedDataCreate - create a digestedData object (presumably for encoding) + * + * version will be set by SecCmsDigestedDataEncodeBeforeStart + * digestAlg is passed as parameter + * contentInfo must be filled by the user + * digest will be calculated while encoding + */ +SecCmsDigestedDataRef +SecCmsDigestedDataCreate(SecCmsMessageRef cmsg, SECAlgorithmID *digestalg) +{ + void *mark; + SecCmsDigestedDataRef digd; + PLArenaPool *poolp; + + poolp = cmsg->poolp; + + mark = PORT_ArenaMark(poolp); + + digd = (SecCmsDigestedDataRef)PORT_ArenaZAlloc(poolp, sizeof(SecCmsDigestedData)); + if (digd == NULL) + goto loser; + + digd->cmsg = cmsg; + + if (SECOID_CopyAlgorithmID (poolp, &(digd->digestAlg), digestalg) != SECSuccess) + goto loser; + + PORT_ArenaUnmark(poolp, mark); + return digd; + +loser: + PORT_ArenaRelease(poolp, mark); + return NULL; +} + +/* + * SecCmsDigestedDataDestroy - destroy a digestedData object + */ +void +SecCmsDigestedDataDestroy(SecCmsDigestedDataRef digd) +{ + /* everything's in a pool, so don't worry about the storage */ + SecCmsContentInfoDestroy(&(digd->contentInfo)); + return; +} + +/* + * SecCmsDigestedDataGetContentInfo - return pointer to digestedData object's contentInfo + */ +SecCmsContentInfoRef +SecCmsDigestedDataGetContentInfo(SecCmsDigestedDataRef digd) +{ + return &(digd->contentInfo); +} + +/* + * SecCmsDigestedDataEncodeBeforeStart - do all the necessary things to a DigestedData + * before encoding begins. + * + * In particular: + * - set the right version number. The contentInfo's content type must be set up already. + */ +OSStatus +SecCmsDigestedDataEncodeBeforeStart(SecCmsDigestedDataRef digd) +{ + unsigned long version; + CSSM_DATA_PTR dummy; + + version = SEC_CMS_DIGESTED_DATA_VERSION_DATA; + if (SecCmsContentInfoGetContentTypeTag(&(digd->contentInfo)) != SEC_OID_PKCS7_DATA) + version = SEC_CMS_DIGESTED_DATA_VERSION_ENCAP; + + dummy = SEC_ASN1EncodeInteger(digd->cmsg->poolp, &(digd->version), version); + return (dummy == NULL) ? SECFailure : SECSuccess; +} + +/* + * SecCmsDigestedDataEncodeBeforeData - do all the necessary things to a DigestedData + * before the encapsulated data is passed through the encoder. + * + * In detail: + * - set up the digests if necessary + */ +OSStatus +SecCmsDigestedDataEncodeBeforeData(SecCmsDigestedDataRef digd) +{ + /* set up the digests */ + if (digd->digestAlg.algorithm.Length != 0 && digd->digest.Length == 0) { + /* if digest is already there, do nothing */ + digd->contentInfo.digcx = SecCmsDigestContextStartSingle(&(digd->digestAlg)); + if (digd->contentInfo.digcx == NULL) + return SECFailure; + } + return SECSuccess; +} + +/* + * SecCmsDigestedDataEncodeAfterData - do all the necessary things to a DigestedData + * after all the encapsulated data was passed through the encoder. + * + * In detail: + * - finish the digests + */ +OSStatus +SecCmsDigestedDataEncodeAfterData(SecCmsDigestedDataRef digd) +{ + OSStatus rv = SECSuccess; + /* did we have digest calculation going on? */ + if (digd->contentInfo.digcx) { + rv = SecCmsDigestContextFinishSingle(digd->contentInfo.digcx, + (SecArenaPoolRef)digd->cmsg->poolp, &(digd->digest)); + /* error has been set by SecCmsDigestContextFinishSingle */ + digd->contentInfo.digcx = NULL; + } + + return rv; +} + +/* + * SecCmsDigestedDataDecodeBeforeData - do all the necessary things to a DigestedData + * before the encapsulated data is passed through the encoder. + * + * In detail: + * - set up the digests if necessary + */ +OSStatus +SecCmsDigestedDataDecodeBeforeData(SecCmsDigestedDataRef digd) +{ + /* is there a digest algorithm yet? */ + if (digd->digestAlg.algorithm.Length == 0) + return SECFailure; + + digd->contentInfo.digcx = SecCmsDigestContextStartSingle(&(digd->digestAlg)); + if (digd->contentInfo.digcx == NULL) + return SECFailure; + + return SECSuccess; +} + +/* + * SecCmsDigestedDataDecodeAfterData - do all the necessary things to a DigestedData + * after all the encapsulated data was passed through the encoder. + * + * In detail: + * - finish the digests + */ +OSStatus +SecCmsDigestedDataDecodeAfterData(SecCmsDigestedDataRef digd) +{ + OSStatus rv = SECSuccess; + /* did we have digest calculation going on? */ + if (digd->contentInfo.digcx) { + rv = SecCmsDigestContextFinishSingle(digd->contentInfo.digcx, + (SecArenaPoolRef)digd->cmsg->poolp, &(digd->cdigest)); + /* error has been set by SecCmsDigestContextFinishSingle */ + digd->contentInfo.digcx = NULL; + } + + return rv; +} + +/* + * SecCmsDigestedDataDecodeAfterEnd - finalize a digestedData. + * + * In detail: + * - check the digests for equality + */ +OSStatus +SecCmsDigestedDataDecodeAfterEnd(SecCmsDigestedDataRef digd) +{ + /* did we have digest calculation going on? */ + if (digd->cdigest.Length != 0) { + /* XXX comparision btw digest & cdigest */ + /* XXX set status */ + /* TODO!!!! */ + } + + return SECSuccess; +} diff --git a/Security/libsecurity_smime/lib/cmsdigest.c b/Security/libsecurity_smime/lib/cmsdigest.c new file mode 100644 index 00000000..edfe98e2 --- /dev/null +++ b/Security/libsecurity_smime/lib/cmsdigest.c @@ -0,0 +1,280 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * CMS digesting. + */ + +#include "cmslocal.h" + +#include "secitem.h" +#include "secoid.h" + +#include +#include + +#include + + +struct SecCmsDigestContextStr { + Boolean saw_contents; + int digcnt; + CSSM_CC_HANDLE * digobjs; +}; + +/* + * SecCmsDigestContextStartMultiple - start digest calculation using all the + * digest algorithms in "digestalgs" in parallel. + */ +SecCmsDigestContextRef +SecCmsDigestContextStartMultiple(SECAlgorithmID **digestalgs) +{ + SecCmsDigestContextRef cmsdigcx; + CSSM_CC_HANDLE digobj; + int digcnt; + int i; + + digcnt = (digestalgs == NULL) ? 0 : SecCmsArrayCount((void **)digestalgs); + + cmsdigcx = (SecCmsDigestContextRef)PORT_Alloc(sizeof(struct SecCmsDigestContextStr)); + if (cmsdigcx == NULL) + return NULL; + + if (digcnt > 0) { + cmsdigcx->digobjs = (CSSM_CC_HANDLE *)PORT_Alloc(digcnt * sizeof(CSSM_CC_HANDLE)); + if (cmsdigcx->digobjs == NULL) + goto loser; + } + + cmsdigcx->digcnt = 0; + + /* + * Create a digest object context for each algorithm. + */ + for (i = 0; i < digcnt; i++) { + digobj = SecCmsUtilGetHashObjByAlgID(digestalgs[i]); + /* + * Skip any algorithm we do not even recognize; obviously, + * this could be a problem, but if it is critical then the + * result will just be that the signature does not verify. + * We do not necessarily want to error out here, because + * the particular algorithm may not actually be important, + * but we cannot know that until later. + */ + if (digobj) + { + CSSM_RETURN result; + result = CSSM_DigestDataInit(digobj); + if (result != CSSM_OK) + { + goto loser; + } + } + + cmsdigcx->digobjs[cmsdigcx->digcnt] = digobj; + cmsdigcx->digcnt++; + } + + cmsdigcx->saw_contents = PR_FALSE; + + return cmsdigcx; + +loser: + if (cmsdigcx) { + if (cmsdigcx->digobjs) + PORT_Free(cmsdigcx->digobjs); + } + return NULL; +} + +/* + * SecCmsDigestContextStartSingle - same as SecCmsDigestContextStartMultiple, but + * only one algorithm. + */ +SecCmsDigestContextRef +SecCmsDigestContextStartSingle(SECAlgorithmID *digestalg) +{ + SECAlgorithmID *digestalgs[] = { NULL, NULL }; /* fake array */ + + digestalgs[0] = digestalg; + return SecCmsDigestContextStartMultiple(digestalgs); +} + +/* + * SecCmsDigestContextUpdate - feed more data into the digest machine + */ +void +SecCmsDigestContextUpdate(SecCmsDigestContextRef cmsdigcx, const unsigned char *data, size_t len) +{ + CSSM_DATA dataBuf; + int i; + + dataBuf.Length = len; + dataBuf.Data = (uint8 *)data; + cmsdigcx->saw_contents = PR_TRUE; + for (i = 0; i < cmsdigcx->digcnt; i++) + if (cmsdigcx->digobjs[i]) + CSSM_DigestDataUpdate(cmsdigcx->digobjs[i], &dataBuf, 1); +} + +/* + * SecCmsDigestContextCancel - cancel digesting operation + */ +void +SecCmsDigestContextCancel(SecCmsDigestContextRef cmsdigcx) +{ + int i; + + for (i = 0; i < cmsdigcx->digcnt; i++) + if (cmsdigcx->digobjs[i]) + CSSM_DeleteContext(cmsdigcx->digobjs[i]); +} + +/* + * SecCmsDigestContextFinishMultiple - finish the digests and put them + * into an array of CSSM_DATAs (allocated on poolp) + */ +OSStatus +SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, SecArenaPoolRef poolp, + CSSM_DATA_PTR **digestsp) +{ + CSSM_CC_HANDLE digobj; + CSSM_DATA_PTR *digests, digest; + int i; + void *mark; + OSStatus rv = SECFailure; + + /* no contents? do not update digests */ + if (digestsp == NULL || !cmsdigcx->saw_contents) { + for (i = 0; i < cmsdigcx->digcnt; i++) + if (cmsdigcx->digobjs[i]) + CSSM_DeleteContext(cmsdigcx->digobjs[i]); + rv = SECSuccess; + if (digestsp) + *digestsp = NULL; + goto cleanup; + } + + mark = PORT_ArenaMark ((PLArenaPool *)poolp); + + /* allocate digest array & CSSM_DATAs on arena */ + digests = (CSSM_DATA_PTR *)PORT_ArenaAlloc((PLArenaPool *)poolp, (cmsdigcx->digcnt+1) * sizeof(CSSM_DATA_PTR)); + digest = (CSSM_DATA_PTR)PORT_ArenaZAlloc((PLArenaPool *)poolp, cmsdigcx->digcnt * sizeof(CSSM_DATA)); + if (digests == NULL || digest == NULL) { + goto loser; + } + + for (i = 0; i < cmsdigcx->digcnt; i++, digest++) { + digobj = cmsdigcx->digobjs[i]; + CSSM_QUERY_SIZE_DATA dataSize; + rv = CSSM_QuerySize(digobj, CSSM_FALSE, 1, &dataSize); + if (rv != CSSM_OK) + { + goto loser; + } + + int diglength = dataSize.SizeOutputBlock; + + if (digobj) + { + digest->Data = (unsigned char*)PORT_ArenaAlloc((PLArenaPool *)poolp, diglength); + if (digest->Data == NULL) + goto loser; + digest->Length = diglength; + rv = CSSM_DigestDataFinal(digobj, digest); + if (rv != CSSM_OK) + { + goto loser; + } + + CSSM_DeleteContext(digobj); + } + else + { + digest->Data = NULL; + digest->Length = 0; + } + + digests[i] = digest; + } + digests[i] = NULL; + *digestsp = digests; + + rv = SECSuccess; + +loser: + if (rv == SECSuccess) + PORT_ArenaUnmark((PLArenaPool *)poolp, mark); + else + PORT_ArenaRelease((PLArenaPool *)poolp, mark); + +cleanup: + if (cmsdigcx->digcnt > 0) { + PORT_Free(cmsdigcx->digobjs); + } + PORT_Free(cmsdigcx); + + return rv; +} + +/* + * SecCmsDigestContextFinishSingle - same as SecCmsDigestContextFinishMultiple, + * but for one digest. + */ +OSStatus +SecCmsDigestContextFinishSingle(SecCmsDigestContextRef cmsdigcx, SecArenaPoolRef poolp, + CSSM_DATA_PTR digest) +{ + OSStatus rv = SECFailure; + CSSM_DATA_PTR *dp; + PLArenaPool *arena = NULL; + + if ((arena = PORT_NewArena(1024)) == NULL) + goto loser; + + /* get the digests into arena, then copy the first digest into poolp */ + if (SecCmsDigestContextFinishMultiple(cmsdigcx, (SecArenaPoolRef)arena, &dp) != SECSuccess) + goto loser; + + /* now copy it into poolp */ + if (SECITEM_CopyItem((PLArenaPool *)poolp, digest, dp[0]) != SECSuccess) + goto loser; + + rv = SECSuccess; + +loser: + if (arena) + PORT_FreeArena(arena, PR_FALSE); + + return rv; +} diff --git a/Security/libsecurity_smime/lib/cmsencdata.c b/Security/libsecurity_smime/lib/cmsencdata.c new file mode 100644 index 00000000..895b5085 --- /dev/null +++ b/Security/libsecurity_smime/lib/cmsencdata.c @@ -0,0 +1,294 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * CMS encryptedData methods. + */ + +#include + +#include + +#include "cmslocal.h" + +#include "secitem.h" +#include "secoid.h" +#include +#include + +/* + * SecCmsEncryptedDataCreate - create an empty encryptedData object. + * + * "algorithm" specifies the bulk encryption algorithm to use. + * "keysize" is the key size. + * + * An error results in a return value of NULL and an error set. + * (Retrieve specific errors via PORT_GetError()/XP_GetError().) + */ +SecCmsEncryptedDataRef +SecCmsEncryptedDataCreate(SecCmsMessageRef cmsg, SECOidTag algorithm, int keysize) +{ + void *mark; + SecCmsEncryptedDataRef encd; + PLArenaPool *poolp; + SECAlgorithmID *pbe_algid; + OSStatus rv; + + poolp = cmsg->poolp; + + mark = PORT_ArenaMark(poolp); + + encd = (SecCmsEncryptedDataRef)PORT_ArenaZAlloc(poolp, sizeof(SecCmsEncryptedData)); + if (encd == NULL) + goto loser; + + encd->cmsg = cmsg; + + /* version is set in SecCmsEncryptedDataEncodeBeforeStart() */ + + switch (algorithm) { + /* XXX hmmm... hardcoded algorithms? */ + case SEC_OID_RC2_CBC: + case SEC_OID_DES_EDE3_CBC: + case SEC_OID_DES_CBC: + rv = SecCmsContentInfoSetContentEncAlg((SecArenaPoolRef)poolp, &(encd->contentInfo), algorithm, NULL, keysize); + break; + default: + /* Assume password-based-encryption. At least, try that. */ +#if 1 + // @@@ Fix me + pbe_algid = NULL; +#else + pbe_algid = PK11_CreatePBEAlgorithmID(algorithm, 1, NULL); +#endif + if (pbe_algid == NULL) { + rv = SECFailure; + break; + } + rv = SecCmsContentInfoSetContentEncAlgID((SecArenaPoolRef)poolp, &(encd->contentInfo), pbe_algid, keysize); + SECOID_DestroyAlgorithmID (pbe_algid, PR_TRUE); + break; + } + if (rv != SECSuccess) + goto loser; + + PORT_ArenaUnmark(poolp, mark); + return encd; + +loser: + PORT_ArenaRelease(poolp, mark); + return NULL; +} + +/* + * SecCmsEncryptedDataDestroy - destroy an encryptedData object + */ +void +SecCmsEncryptedDataDestroy(SecCmsEncryptedDataRef encd) +{ + /* everything's in a pool, so don't worry about the storage */ + SecCmsContentInfoDestroy(&(encd->contentInfo)); + return; +} + +/* + * SecCmsEncryptedDataGetContentInfo - return pointer to encryptedData object's contentInfo + */ +SecCmsContentInfoRef +SecCmsEncryptedDataGetContentInfo(SecCmsEncryptedDataRef encd) +{ + return &(encd->contentInfo); +} + +/* + * SecCmsEncryptedDataEncodeBeforeStart - do all the necessary things to a EncryptedData + * before encoding begins. + * + * In particular: + * - set the correct version value. + * - get the encryption key + */ +OSStatus +SecCmsEncryptedDataEncodeBeforeStart(SecCmsEncryptedDataRef encd) +{ + int version; + SecSymmetricKeyRef bulkkey = NULL; + CSSM_DATA_PTR dummy; + SecCmsContentInfoRef cinfo = &(encd->contentInfo); + + if (SecCmsArrayIsEmpty((void **)encd->unprotectedAttr)) + version = SEC_CMS_ENCRYPTED_DATA_VERSION; + else + version = SEC_CMS_ENCRYPTED_DATA_VERSION_UPATTR; + + dummy = SEC_ASN1EncodeInteger (encd->cmsg->poolp, &(encd->version), version); + if (dummy == NULL) + return SECFailure; + + /* now get content encryption key (bulk key) by using our cmsg callback */ + if (encd->cmsg->decrypt_key_cb) + bulkkey = (*encd->cmsg->decrypt_key_cb)(encd->cmsg->decrypt_key_cb_arg, + SecCmsContentInfoGetContentEncAlg(cinfo)); + if (bulkkey == NULL) + return SECFailure; + + /* store the bulk key in the contentInfo so that the encoder can find it */ + SecCmsContentInfoSetBulkKey(cinfo, bulkkey); + CFRelease(bulkkey); /* This assumes the decrypt_key_cb hands us a copy of the key --mb */ + + return SECSuccess; +} + +/* + * SecCmsEncryptedDataEncodeBeforeData - set up encryption + */ +OSStatus +SecCmsEncryptedDataEncodeBeforeData(SecCmsEncryptedDataRef encd) +{ + SecCmsContentInfoRef cinfo; + SecSymmetricKeyRef bulkkey; + SECAlgorithmID *algid; + + cinfo = &(encd->contentInfo); + + /* find bulkkey and algorithm - must have been set by SecCmsEncryptedDataEncodeBeforeStart */ + bulkkey = SecCmsContentInfoGetBulkKey(cinfo); + if (bulkkey == NULL) + return SECFailure; + algid = SecCmsContentInfoGetContentEncAlg(cinfo); + if (algid == NULL) + return SECFailure; + + /* this may modify algid (with IVs generated in a token). + * it is therefore essential that algid is a pointer to the "real" contentEncAlg, + * not just to a copy */ + cinfo->ciphcx = SecCmsCipherContextStartEncrypt(encd->cmsg->poolp, bulkkey, algid); + CFRelease(bulkkey); + if (cinfo->ciphcx == NULL) + return SECFailure; + + return SECSuccess; +} + +/* + * SecCmsEncryptedDataEncodeAfterData - finalize this encryptedData for encoding + */ +OSStatus +SecCmsEncryptedDataEncodeAfterData(SecCmsEncryptedDataRef encd) +{ + if (encd->contentInfo.ciphcx) { + SecCmsCipherContextDestroy(encd->contentInfo.ciphcx); + encd->contentInfo.ciphcx = NULL; + } + + /* nothing to do after data */ + return SECSuccess; +} + + +/* + * SecCmsEncryptedDataDecodeBeforeData - find bulk key & set up decryption + */ +OSStatus +SecCmsEncryptedDataDecodeBeforeData(SecCmsEncryptedDataRef encd) +{ + SecSymmetricKeyRef bulkkey = NULL; + SecCmsContentInfoRef cinfo; + SECAlgorithmID *bulkalg; + OSStatus rv = SECFailure; + + cinfo = &(encd->contentInfo); + + bulkalg = SecCmsContentInfoGetContentEncAlg(cinfo); + + if (encd->cmsg->decrypt_key_cb == NULL) /* no callback? no key../ */ + goto loser; + + bulkkey = (*encd->cmsg->decrypt_key_cb)(encd->cmsg->decrypt_key_cb_arg, bulkalg); + if (bulkkey == NULL) + /* no success finding a bulk key */ + goto loser; + + SecCmsContentInfoSetBulkKey(cinfo, bulkkey); + + cinfo->ciphcx = SecCmsCipherContextStartDecrypt(bulkkey, bulkalg); + if (cinfo->ciphcx == NULL) + goto loser; /* error has been set by SecCmsCipherContextStartDecrypt */ + +#if 1 + // @@@ Not done yet +#else + /* + * HACK ALERT!! + * For PKCS5 Encryption Algorithms, the bulkkey is actually a different + * structure. Therefore, we need to set the bulkkey to the actual key + * prior to freeing it. + */ + if (SEC_PKCS5IsAlgorithmPBEAlg(bulkalg)) { + SEC_PKCS5KeyAndPassword *keyPwd = (SEC_PKCS5KeyAndPassword *)bulkkey; + bulkkey = keyPwd->key; + } +#endif + + /* we are done with (this) bulkkey now. */ + CFRelease(bulkkey); + + rv = SECSuccess; + +loser: + return rv; +} + +/* + * SecCmsEncryptedDataDecodeAfterData - finish decrypting this encryptedData's content + */ +OSStatus +SecCmsEncryptedDataDecodeAfterData(SecCmsEncryptedDataRef encd) +{ + if (encd->contentInfo.ciphcx) { + SecCmsCipherContextDestroy(encd->contentInfo.ciphcx); + encd->contentInfo.ciphcx = NULL; + } + + return SECSuccess; +} + +/* + * SecCmsEncryptedDataDecodeAfterEnd - finish decoding this encryptedData + */ +OSStatus +SecCmsEncryptedDataDecodeAfterEnd(SecCmsEncryptedDataRef encd) +{ + /* apply final touches */ + return SECSuccess; +} diff --git a/Security/libsecurity_smime/lib/cmsencode.c b/Security/libsecurity_smime/lib/cmsencode.c new file mode 100644 index 00000000..cdc85699 --- /dev/null +++ b/Security/libsecurity_smime/lib/cmsencode.c @@ -0,0 +1,785 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * CMS encoding. + */ + +#include +#include +#include +#include + +#include "cmslocal.h" + +#include "secoid.h" +#include "secitem.h" + +#include +#include +#include + +struct nss_cms_encoder_output { + SecCmsContentCallback outputfn; + void *outputarg; + PLArenaPool *destpoolp; + CSSM_DATA_PTR dest; +}; + +struct SecCmsEncoderStr { + SEC_ASN1EncoderContext * ecx; /* ASN.1 encoder context */ + Boolean ecxupdated; /* true if data was handed in */ + SecCmsMessageRef cmsg; /* pointer to the root message */ + SECOidTag type; /* type tag of the current content */ + SecCmsContent content; /* pointer to current content */ + struct nss_cms_encoder_output output; /* output function */ + int error; /* error code */ + SecCmsEncoderRef childp7ecx; /* link to child encoder context */ +}; + +static OSStatus nss_cms_before_data(SecCmsEncoderRef p7ecx); +static OSStatus nss_cms_after_data(SecCmsEncoderRef p7ecx); +static OSStatus nss_cms_encoder_update(SecCmsEncoderRef p7ecx, const char *data, size_t len); +static OSStatus nss_cms_encoder_work_data(SecCmsEncoderRef p7ecx, CSSM_DATA_PTR dest, + const unsigned char *data, size_t len, + Boolean final, Boolean innermost); + +extern const SecAsn1Template SecCmsMessageTemplate[]; + +/* + * The little output function that the ASN.1 encoder calls to hand + * us bytes which we in turn hand back to our caller (via the callback + * they gave us). + */ +static void +nss_cms_encoder_out(void *arg, const char *buf, size_t len, + int depth, SEC_ASN1EncodingPart data_kind) +{ + struct nss_cms_encoder_output *output = (struct nss_cms_encoder_output *)arg; + unsigned char *dest; + CSSM_SIZE offset; + +#ifdef CMSDEBUG + int i; + + fprintf(stderr, "kind = %d, depth = %d, len = %lu\n", data_kind, depth, len); + for (i=0; i < len; i++) { + fprintf(stderr, " %02x%s", (unsigned int)buf[i] & 0xff, ((i % 16) == 15) ? "\n" : ""); + } + if ((i % 16) != 0) + fprintf(stderr, "\n"); +#endif + + if (output->outputfn != NULL) + /* call output callback with DER data */ + output->outputfn(output->outputarg, buf, len); + + if (output->dest != NULL) { + /* store DER data in CSSM_DATA */ + offset = output->dest->Length; + if (offset == 0) { + dest = (unsigned char *)PORT_ArenaAlloc(output->destpoolp, len); + } else { + dest = (unsigned char *)PORT_ArenaGrow(output->destpoolp, + output->dest->Data, + output->dest->Length, + output->dest->Length + len); + } + if (dest == NULL) + /* oops */ + return; + + output->dest->Data = dest; + output->dest->Length += len; + + /* copy it in */ + PORT_Memcpy(output->dest->Data + offset, buf, len); + } +} + +/* + * nss_cms_encoder_notify - ASN.1 encoder callback + * + * this function is called by the ASN.1 encoder before and after the encoding of + * every object. here, it is used to keep track of data structures, set up + * encryption and/or digesting and possibly set up child encoders. + */ +static void +nss_cms_encoder_notify(void *arg, Boolean before, void *dest, int depth) +{ + SecCmsEncoderRef p7ecx; + SecCmsContentInfoRef rootcinfo, cinfo; + Boolean after = !before; + PLArenaPool *poolp; + SECOidTag childtype; + CSSM_DATA_PTR item; + + p7ecx = (SecCmsEncoderRef)arg; + PORT_Assert(p7ecx != NULL); + + rootcinfo = &(p7ecx->cmsg->contentInfo); + poolp = p7ecx->cmsg->poolp; + +#ifdef CMSDEBUG + fprintf(stderr, "%6.6s, dest = %p, depth = %d\n", before ? "before" : "after", dest, depth); +#endif + + /* + * Watch for the content field, at which point we want to instruct + * the ASN.1 encoder to start taking bytes from the buffer. + */ + switch (p7ecx->type) { + default: + case SEC_OID_UNKNOWN: + /* we're still in the root message */ + if (after && dest == &(rootcinfo->contentType)) { + /* got the content type OID now - so find out the type tag */ + p7ecx->type = SecCmsContentInfoGetContentTypeTag(rootcinfo); + /* set up a pointer to our current content */ + p7ecx->content = rootcinfo->content; + } + break; + + case SEC_OID_PKCS7_DATA: + case SEC_OID_OTHER: + if (before && dest == &(rootcinfo->rawContent)) { + /* just set up encoder to grab from user - no encryption or digesting */ + if ((item = rootcinfo->content.data) != NULL) + (void)nss_cms_encoder_work_data(p7ecx, NULL, item->Data, item->Length, PR_TRUE, PR_TRUE); + else + SEC_ASN1EncoderSetTakeFromBuf(p7ecx->ecx); + SEC_ASN1EncoderClearNotifyProc(p7ecx->ecx); /* no need to get notified anymore */ + } + break; + + case SEC_OID_PKCS7_SIGNED_DATA: + case SEC_OID_PKCS7_ENVELOPED_DATA: + case SEC_OID_PKCS7_DIGESTED_DATA: + case SEC_OID_PKCS7_ENCRYPTED_DATA: + + /* when we know what the content is, we encode happily until we reach the inner content */ + cinfo = SecCmsContentGetContentInfo(p7ecx->content.pointer, p7ecx->type); + childtype = SecCmsContentInfoGetContentTypeTag(cinfo); + + if (after && dest == &(cinfo->contentType)) { + /* we're right before encoding the data (if we have some or not) */ + /* (for encrypted data, we're right before the contentEncAlg which may change */ + /* in nss_cms_before_data because of IV calculation when setting up encryption) */ + if (nss_cms_before_data(p7ecx) != SECSuccess) + p7ecx->error = PORT_GetError(); + } + if (before && dest == &(cinfo->rawContent)) { + if ( ((childtype == SEC_OID_PKCS7_DATA) || (childtype == SEC_OID_OTHER)) && + ((item = cinfo->content.data) != NULL)) + /* we have data - feed it in */ + (void)nss_cms_encoder_work_data(p7ecx, NULL, item->Data, item->Length, PR_TRUE, PR_TRUE); + else + /* else try to get it from user */ + SEC_ASN1EncoderSetTakeFromBuf(p7ecx->ecx); + } + if (after && dest == &(cinfo->rawContent)) { + if (nss_cms_after_data(p7ecx) != SECSuccess) + p7ecx->error = PORT_GetError(); + SEC_ASN1EncoderClearNotifyProc(p7ecx->ecx); /* no need to get notified anymore */ + } + break; + } +} + +/* + * nss_cms_before_data - setup the current encoder to receive data + */ +static OSStatus +nss_cms_before_data(SecCmsEncoderRef p7ecx) +{ + OSStatus rv; + SECOidTag childtype; + SecCmsContentInfoRef cinfo; + PLArenaPool *poolp; + SecCmsEncoderRef childp7ecx; + const SecAsn1Template *template; + + poolp = p7ecx->cmsg->poolp; + + /* call _Encode_BeforeData handlers */ + switch (p7ecx->type) { + case SEC_OID_PKCS7_SIGNED_DATA: + /* we're encoding a signedData, so set up the digests */ + rv = SecCmsSignedDataEncodeBeforeData(p7ecx->content.signedData); + break; + case SEC_OID_PKCS7_DIGESTED_DATA: + /* we're encoding a digestedData, so set up the digest */ + rv = SecCmsDigestedDataEncodeBeforeData(p7ecx->content.digestedData); + break; + case SEC_OID_PKCS7_ENVELOPED_DATA: + rv = SecCmsEnvelopedDataEncodeBeforeData(p7ecx->content.envelopedData); + break; + case SEC_OID_PKCS7_ENCRYPTED_DATA: + rv = SecCmsEncryptedDataEncodeBeforeData(p7ecx->content.encryptedData); + break; + default: + rv = SECFailure; + } + if (rv != SECSuccess) + return SECFailure; + + /* ok, now we have a pointer to cinfo */ + /* find out what kind of data is encapsulated */ + + cinfo = SecCmsContentGetContentInfo(p7ecx->content.pointer, p7ecx->type); + childtype = SecCmsContentInfoGetContentTypeTag(cinfo); + + switch (childtype) { + case SEC_OID_PKCS7_SIGNED_DATA: + case SEC_OID_PKCS7_ENVELOPED_DATA: + case SEC_OID_PKCS7_ENCRYPTED_DATA: + case SEC_OID_PKCS7_DIGESTED_DATA: +#if 0 + case SEC_OID_PKCS7_DATA: /* XXX here also??? maybe yes! */ +#endif + /* in these cases, we need to set up a child encoder! */ + /* create new encoder context */ + childp7ecx = PORT_ZAlloc(sizeof(struct SecCmsEncoderStr)); + if (childp7ecx == NULL) + return SECFailure; + + /* the CHILD encoder needs to hand its encoded data to the CURRENT encoder + * (which will encrypt and/or digest it) + * this needs to route back into our update function + * which finds the lowest encoding context & encrypts and computes digests */ + childp7ecx->type = childtype; + childp7ecx->content = cinfo->content; + /* use the non-recursive update function here, of course */ + childp7ecx->output.outputfn = (SecCmsContentCallback)nss_cms_encoder_update; + childp7ecx->output.outputarg = p7ecx; + childp7ecx->output.destpoolp = NULL; + childp7ecx->output.dest = NULL; + childp7ecx->cmsg = p7ecx->cmsg; + + template = SecCmsUtilGetTemplateByTypeTag(childtype); + if (template == NULL) + goto loser; /* cannot happen */ + + /* now initialize the data for encoding the first third */ + switch (childp7ecx->type) { + case SEC_OID_PKCS7_SIGNED_DATA: + rv = SecCmsSignedDataEncodeBeforeStart(cinfo->content.signedData); + break; + case SEC_OID_PKCS7_ENVELOPED_DATA: + rv = SecCmsEnvelopedDataEncodeBeforeStart(cinfo->content.envelopedData); + break; + case SEC_OID_PKCS7_DIGESTED_DATA: + rv = SecCmsDigestedDataEncodeBeforeStart(cinfo->content.digestedData); + break; + case SEC_OID_PKCS7_ENCRYPTED_DATA: + rv = SecCmsEncryptedDataEncodeBeforeStart(cinfo->content.encryptedData); + break; + case SEC_OID_PKCS7_DATA: + case SEC_OID_OTHER: + rv = SECSuccess; + break; + default: + PORT_Assert(0); + break; + } + if (rv != SECSuccess) + goto loser; + + /* + * Initialize the BER encoder. + */ + childp7ecx->ecx = SEC_ASN1EncoderStart(cinfo->content.pointer, template, + nss_cms_encoder_out, &(childp7ecx->output)); + if (childp7ecx->ecx == NULL) + goto loser; + + childp7ecx->ecxupdated = PR_FALSE; + + /* + * Indicate that we are streaming. We will be streaming until we + * get past the contents bytes. + */ + SEC_ASN1EncoderSetStreaming(childp7ecx->ecx); + + /* + * The notify function will watch for the contents field. + */ + SEC_ASN1EncoderSetNotifyProc(childp7ecx->ecx, nss_cms_encoder_notify, childp7ecx); + + /* please note that we are NOT calling SEC_ASN1EncoderUpdate here to kick off the */ + /* encoding process - we'll do that from the update function instead */ + /* otherwise we'd be encoding data from a call of the notify function of the */ + /* parent encoder (which would not work) */ + + /* this will kick off the encoding process & encode everything up to the content bytes, + * at which point the notify function sets streaming mode (and possibly creates + * another child encoder). */ + if (SEC_ASN1EncoderUpdate(childp7ecx->ecx, NULL, 0) != SECSuccess) + goto loser; + + p7ecx->childp7ecx = childp7ecx; + break; + + case SEC_OID_PKCS7_DATA: + case SEC_OID_OTHER: + p7ecx->childp7ecx = NULL; + break; + default: + /* we do not know this type */ + p7ecx->error = SEC_ERROR_BAD_DER; + break; + } + + return SECSuccess; + +loser: + if (childp7ecx) { + if (childp7ecx->ecx) + SEC_ASN1EncoderFinish(childp7ecx->ecx); + PORT_Free(childp7ecx); + } + return SECFailure; +} + +static OSStatus +nss_cms_after_data(SecCmsEncoderRef p7ecx) +{ + OSStatus rv = SECFailure; + + switch (p7ecx->type) { + case SEC_OID_PKCS7_SIGNED_DATA: + /* this will finish the digests and sign */ + rv = SecCmsSignedDataEncodeAfterData(p7ecx->content.signedData); + break; + case SEC_OID_PKCS7_ENVELOPED_DATA: + rv = SecCmsEnvelopedDataEncodeAfterData(p7ecx->content.envelopedData); + break; + case SEC_OID_PKCS7_DIGESTED_DATA: + rv = SecCmsDigestedDataEncodeAfterData(p7ecx->content.digestedData); + break; + case SEC_OID_PKCS7_ENCRYPTED_DATA: + rv = SecCmsEncryptedDataEncodeAfterData(p7ecx->content.encryptedData); + break; + case SEC_OID_PKCS7_DATA: + case SEC_OID_OTHER: + /* do nothing */ + break; + default: + rv = SECFailure; + break; + } + return rv; +} + +/* + * nss_cms_encoder_work_data - process incoming data + * + * (from the user or the next encoding layer) + * Here, we need to digest and/or encrypt, then pass it on + */ +static OSStatus +nss_cms_encoder_work_data(SecCmsEncoderRef p7ecx, CSSM_DATA_PTR dest, + const unsigned char *data, size_t len, + Boolean final, Boolean innermost) +{ + unsigned char *buf = NULL; + OSStatus rv; + SecCmsContentInfoRef cinfo; + + rv = SECSuccess; /* may as well be optimistic */ + + /* + * We should really have data to process, or we should be trying + * to finish/flush the last block. (This is an overly paranoid + * check since all callers are in this file and simple inspection + * proves they do it right. But it could find a bug in future + * modifications/development, that is why it is here.) + */ + PORT_Assert ((data != NULL && len) || final); + + /* we got data (either from the caller, or from a lower level encoder) */ + cinfo = SecCmsContentGetContentInfo(p7ecx->content.pointer, p7ecx->type); + + /* Update the running digest. */ + if (len && cinfo->digcx != NULL) + SecCmsDigestContextUpdate(cinfo->digcx, data, len); + + /* Encrypt this chunk. */ + if (cinfo->ciphcx != NULL) { + CSSM_SIZE inlen; /* length of data being encrypted */ + CSSM_SIZE outlen; /* length of encrypted data */ + CSSM_SIZE buflen; /* length available for encrypted data */ + + inlen = len; + buflen = SecCmsCipherContextEncryptLength(cinfo->ciphcx, inlen, final); + if (buflen == 0) { + /* + * No output is expected, but the input data may be buffered + * so we still have to call Encrypt. + */ + rv = SecCmsCipherContextEncrypt(cinfo->ciphcx, NULL, NULL, 0, + data, inlen, final); + if (final) { + len = 0; + goto done; + } + return rv; + } + + if (dest != NULL) + buf = (unsigned char*)PORT_ArenaAlloc(p7ecx->cmsg->poolp, buflen); + else + buf = (unsigned char*)PORT_Alloc(buflen); + + if (buf == NULL) { + rv = SECFailure; + } else { + rv = SecCmsCipherContextEncrypt(cinfo->ciphcx, buf, &outlen, buflen, + data, inlen, final); + data = buf; + len = outlen; + } + if (rv != SECSuccess) + /* encryption or malloc failed? */ + return rv; + } + + + /* + * at this point (data,len) has everything we'd like to give to the CURRENT encoder + * (which will encode it, then hand it back to the user or the parent encoder) + * We don't encode the data if we're innermost and we're told not to include the data + */ + if (p7ecx->ecx != NULL && len && (!innermost || cinfo->rawContent != NULL)) + rv = SEC_ASN1EncoderUpdate(p7ecx->ecx, (const char *)data, len); + +done: + + if (cinfo->ciphcx != NULL) { + if (dest != NULL) { + dest->Data = buf; + dest->Length = len; + } else if (buf != NULL) { + PORT_Free (buf); + } + } + return rv; +} + +/* + * nss_cms_encoder_update - deliver encoded data to the next higher level + * + * no recursion here because we REALLY want to end up at the next higher encoder! + */ +static OSStatus +nss_cms_encoder_update(SecCmsEncoderRef p7ecx, const char *data, size_t len) +{ + /* XXX Error handling needs help. Return what? Do "Finish" on failure? */ + return nss_cms_encoder_work_data (p7ecx, NULL, (const unsigned char *)data, len, PR_FALSE, PR_FALSE); +} + +/* + * SecCmsEncoderCreate - set up encoding of a CMS message + * + * "cmsg" - message to encode + * "outputfn", "outputarg" - callback function for delivery of DER-encoded output + * will not be called if NULL. + * "dest" - if non-NULL, pointer to CSSM_DATA that will hold the DER-encoded output + * "destpoolp" - pool to allocate DER-encoded output in + * "pwfn", pwfn_arg" - callback function for getting token password + * "decrypt_key_cb", "decrypt_key_cb_arg" - callback function for getting bulk key for encryptedData + * "detached_digestalgs", "detached_digests" - digests from detached content + */ +OSStatus +SecCmsEncoderCreate(SecCmsMessageRef cmsg, + SecCmsContentCallback outputfn, void *outputarg, + CSSM_DATA_PTR dest, SecArenaPoolRef destpool, + PK11PasswordFunc pwfn, void *pwfn_arg, + SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg, + SECAlgorithmID **detached_digestalgs, CSSM_DATA_PTR *detached_digests, + SecCmsEncoderRef *outEncoder) +{ + SecCmsEncoderRef p7ecx; + OSStatus result; + SecCmsContentInfoRef cinfo; + + SecCmsMessageSetEncodingParams(cmsg, pwfn, pwfn_arg, decrypt_key_cb, decrypt_key_cb_arg, + detached_digestalgs, detached_digests); + + p7ecx = (SecCmsEncoderRef)PORT_ZAlloc(sizeof(struct SecCmsEncoderStr)); + if (p7ecx == NULL) { + result = memFullErr; + goto loser; + } + + p7ecx->cmsg = cmsg; + p7ecx->output.outputfn = outputfn; + p7ecx->output.outputarg = outputarg; + p7ecx->output.dest = dest; + p7ecx->output.destpoolp = (PLArenaPool *)destpool; + p7ecx->type = SEC_OID_UNKNOWN; + + cinfo = SecCmsMessageGetContentInfo(cmsg); + + switch (SecCmsContentInfoGetContentTypeTag(cinfo)) { + case SEC_OID_PKCS7_SIGNED_DATA: + result = SecCmsSignedDataEncodeBeforeStart(cinfo->content.signedData); + break; + case SEC_OID_PKCS7_ENVELOPED_DATA: + result = SecCmsEnvelopedDataEncodeBeforeStart(cinfo->content.envelopedData); + break; + case SEC_OID_PKCS7_DIGESTED_DATA: + result = SecCmsDigestedDataEncodeBeforeStart(cinfo->content.digestedData); + break; + case SEC_OID_PKCS7_ENCRYPTED_DATA: + result = SecCmsEncryptedDataEncodeBeforeStart(cinfo->content.encryptedData); + break; + default: + /* @@@ We need a better error for unsupported message types. */ + result = paramErr; + break; + } + if (result) + goto loser; + + /* Initialize the BER encoder. + * Note that this will not encode anything until the first call to SEC_ASN1EncoderUpdate */ + p7ecx->ecx = SEC_ASN1EncoderStart(cmsg, SecCmsMessageTemplate, + nss_cms_encoder_out, &(p7ecx->output)); + if (p7ecx->ecx == NULL) { + result = PORT_GetError(); + PORT_Free (p7ecx); + goto loser; + } + p7ecx->ecxupdated = PR_FALSE; + + /* + * Indicate that we are streaming. We will be streaming until we + * get past the contents bytes. + */ + SEC_ASN1EncoderSetStreaming(p7ecx->ecx); + + /* + * The notify function will watch for the contents field. + */ + SEC_ASN1EncoderSetNotifyProc(p7ecx->ecx, nss_cms_encoder_notify, p7ecx); + + /* this will kick off the encoding process & encode everything up to the content bytes, + * at which point the notify function sets streaming mode (and possibly creates + * a child encoder). */ + if (SEC_ASN1EncoderUpdate(p7ecx->ecx, NULL, 0) != SECSuccess) { + result = PORT_GetError(); + PORT_Free (p7ecx); + goto loser; + } + + *outEncoder = p7ecx; +loser: + return result; +} + +/* + * SecCmsEncoderUpdate - take content data delivery from the user + * + * "p7ecx" - encoder context + * "data" - content data + * "len" - length of content data + * + * need to find the lowest level (and call SEC_ASN1EncoderUpdate on the way down), + * then hand the data to the work_data fn + */ +OSStatus +SecCmsEncoderUpdate(SecCmsEncoderRef p7ecx, const void *data, CFIndex len) +{ + OSStatus result; + SecCmsContentInfoRef cinfo; + SECOidTag childtype; + + if (p7ecx->error) + return p7ecx->error; + + /* hand data to the innermost decoder */ + if (p7ecx->childp7ecx) { + /* recursion here */ + result = SecCmsEncoderUpdate(p7ecx->childp7ecx, data, len); + } else { + /* we are at innermost decoder */ + /* find out about our inner content type - must be data */ + cinfo = SecCmsContentGetContentInfo(p7ecx->content.pointer, p7ecx->type); + childtype = SecCmsContentInfoGetContentTypeTag(cinfo); + if ((childtype != SEC_OID_PKCS7_DATA) && (childtype != SEC_OID_OTHER)) + return paramErr; /* @@@ Maybe come up with a better error? */ + /* and we must not have preset data */ + if (cinfo->content.data != NULL) + return paramErr; /* @@@ Maybe come up with a better error? */ + + /* hand it the data so it can encode it (let DER trickle up the chain) */ + result = nss_cms_encoder_work_data(p7ecx, NULL, (const unsigned char *)data, len, PR_FALSE, PR_TRUE); + if (result) + result = PORT_GetError(); + } + return result; +} + +/* + * SecCmsEncoderDestroy - stop all encoding + * + * we need to walk down the chain of encoders and the finish them from the innermost out + */ +void +SecCmsEncoderDestroy(SecCmsEncoderRef p7ecx) +{ + /* XXX do this right! */ + + /* + * Finish any inner decoders before us so that all the encoded data is flushed + * This basically finishes all the decoders from the innermost to the outermost. + * Finishing an inner decoder may result in data being updated to the outer decoder + * while we are already in SecCmsEncoderFinish, but that's allright. + */ + if (p7ecx->childp7ecx) + SecCmsEncoderDestroy(p7ecx->childp7ecx); /* frees p7ecx->childp7ecx */ + + /* + * On the way back up, there will be no more data (if we had an + * inner encoder, it is done now!) + * Flush out any remaining data and/or finish digests. + */ + if (nss_cms_encoder_work_data(p7ecx, NULL, NULL, 0, PR_TRUE, (p7ecx->childp7ecx == NULL))) + goto loser; + + p7ecx->childp7ecx = NULL; + + /* kick the encoder back into working mode again. + * We turn off streaming stuff (which will cause the encoder to continue + * encoding happily, now that we have all the data (like digests) ready for it). + */ + SEC_ASN1EncoderClearTakeFromBuf(p7ecx->ecx); + SEC_ASN1EncoderClearStreaming(p7ecx->ecx); + + /* now that TakeFromBuf is off, this will kick this encoder to finish encoding */ + SEC_ASN1EncoderUpdate(p7ecx->ecx, NULL, 0); + +loser: + SEC_ASN1EncoderFinish(p7ecx->ecx); + PORT_Free (p7ecx); +} + +/* + * SecCmsEncoderFinish - signal the end of data + * + * we need to walk down the chain of encoders and the finish them from the innermost out + */ +OSStatus +SecCmsEncoderFinish(SecCmsEncoderRef p7ecx) +{ + OSStatus result; + SecCmsContentInfoRef cinfo; + SECOidTag childtype; + + /* + * Finish any inner decoders before us so that all the encoded data is flushed + * This basically finishes all the decoders from the innermost to the outermost. + * Finishing an inner decoder may result in data being updated to the outer decoder + * while we are already in SecCmsEncoderFinish, but that's allright. + */ + if (p7ecx->childp7ecx) { + result = SecCmsEncoderFinish(p7ecx->childp7ecx); /* frees p7ecx->childp7ecx */ + if (result) + goto loser; + } + + /* + * On the way back up, there will be no more data (if we had an + * inner encoder, it is done now!) + * Flush out any remaining data and/or finish digests. + */ + result = nss_cms_encoder_work_data(p7ecx, NULL, NULL, 0, PR_TRUE, (p7ecx->childp7ecx == NULL)); + if (result) { + result = PORT_GetError(); + goto loser; + } + + p7ecx->childp7ecx = NULL; + + /* find out about our inner content type - must be data */ + cinfo = SecCmsContentGetContentInfo(p7ecx->content.pointer, p7ecx->type); + childtype = SecCmsContentInfoGetContentTypeTag(cinfo); + if ( ((childtype == SEC_OID_PKCS7_DATA) || (childtype == SEC_OID_OTHER)) && + (cinfo->content.data == NULL)) { + SEC_ASN1EncoderClearTakeFromBuf(p7ecx->ecx); + /* now that TakeFromBuf is off, this will kick this encoder to finish encoding */ + result = SEC_ASN1EncoderUpdate(p7ecx->ecx, NULL, 0); + if (result) + result = PORT_GetError(); + } + + SEC_ASN1EncoderClearStreaming(p7ecx->ecx); + + if (p7ecx->error && !result) + result = p7ecx->error; + +loser: + SEC_ASN1EncoderFinish(p7ecx->ecx); + PORT_Free (p7ecx); + return result; +} + +OSStatus +SecCmsMessageEncode(SecCmsMessageRef cmsg, const CSSM_DATA *input, SecArenaPoolRef arena, + CSSM_DATA_PTR outBer) +{ + SecCmsEncoderRef encoder; + OSStatus result; + + if (!cmsg || !outBer || !arena) { + result = paramErr; + goto loser; + } + + result = SecCmsEncoderCreate(cmsg, 0, 0, outBer, arena, 0, 0, 0, 0, 0, 0, &encoder); + if (result) + goto loser; + + if (input) { + result = SecCmsEncoderUpdate(encoder, input->Data, input->Length); + if (result) { + SecCmsEncoderDestroy(encoder); + goto loser; + } + } + result = SecCmsEncoderFinish(encoder); + +loser: + return result; +} diff --git a/Security/libsecurity_smime/lib/cmsenvdata.c b/Security/libsecurity_smime/lib/cmsenvdata.c new file mode 100644 index 00000000..fad65434 --- /dev/null +++ b/Security/libsecurity_smime/lib/cmsenvdata.c @@ -0,0 +1,440 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * CMS envelopedData methods. + */ + +#include + +#include +#include + +#include "cmslocal.h" + +#include "secitem.h" +#include "secoid.h" +#include "cryptohi.h" + +#include +#include +#include + +/* + * SecCmsEnvelopedDataCreate - create an enveloped data message + */ +SecCmsEnvelopedDataRef +SecCmsEnvelopedDataCreate(SecCmsMessageRef cmsg, SECOidTag algorithm, int keysize) +{ + void *mark; + SecCmsEnvelopedDataRef envd; + PLArenaPool *poolp; + OSStatus rv; + + poolp = cmsg->poolp; + + mark = PORT_ArenaMark(poolp); + + envd = (SecCmsEnvelopedDataRef)PORT_ArenaZAlloc(poolp, sizeof(SecCmsEnvelopedData)); + if (envd == NULL) + goto loser; + + envd->cmsg = cmsg; + + /* version is set in SecCmsEnvelopedDataEncodeBeforeStart() */ + + rv = SecCmsContentInfoSetContentEncAlg((SecArenaPoolRef)poolp, &(envd->contentInfo), algorithm, NULL, keysize); + if (rv != SECSuccess) + goto loser; + + PORT_ArenaUnmark(poolp, mark); + return envd; + +loser: + PORT_ArenaRelease(poolp, mark); + return NULL; +} + +/* + * SecCmsEnvelopedDataDestroy - destroy an enveloped data message + */ +void +SecCmsEnvelopedDataDestroy(SecCmsEnvelopedDataRef edp) +{ + SecCmsRecipientInfoRef *recipientinfos; + SecCmsRecipientInfoRef ri; + + if (edp == NULL) + return; + + recipientinfos = edp->recipientInfos; + if (recipientinfos == NULL) + return; + + while ((ri = *recipientinfos++) != NULL) + SecCmsRecipientInfoDestroy(ri); + + SecCmsContentInfoDestroy(&(edp->contentInfo)); + +} + +/* + * SecCmsEnvelopedDataGetContentInfo - return pointer to this envelopedData's contentinfo + */ +SecCmsContentInfoRef +SecCmsEnvelopedDataGetContentInfo(SecCmsEnvelopedDataRef envd) +{ + return &(envd->contentInfo); +} + +/* + * SecCmsEnvelopedDataAddRecipient - add a recipientinfo to the enveloped data msg + * + * rip must be created on the same pool as edp - this is not enforced, though. + */ +OSStatus +SecCmsEnvelopedDataAddRecipient(SecCmsEnvelopedDataRef edp, SecCmsRecipientInfoRef rip) +{ + void *mark; + OSStatus rv; + + /* XXX compare pools, if not same, copy rip into edp's pool */ + + PR_ASSERT(edp != NULL); + PR_ASSERT(rip != NULL); + + mark = PORT_ArenaMark(edp->cmsg->poolp); + + rv = SecCmsArrayAdd(edp->cmsg->poolp, (void ***)&(edp->recipientInfos), (void *)rip); + if (rv != SECSuccess) { + PORT_ArenaRelease(edp->cmsg->poolp, mark); + return SECFailure; + } + + PORT_ArenaUnmark (edp->cmsg->poolp, mark); + return SECSuccess; +} + +/* + * SecCmsEnvelopedDataEncodeBeforeStart - prepare this envelopedData for encoding + * + * at this point, we need + * - recipientinfos set up with recipient's certificates + * - a content encryption algorithm (if none, 3DES will be used) + * + * this function will generate a random content encryption key (aka bulk key), + * initialize the recipientinfos with certificate identification and wrap the bulk key + * using the proper algorithm for every certificiate. + * it will finally set the bulk algorithm and key so that the encode step can find it. + */ +OSStatus +SecCmsEnvelopedDataEncodeBeforeStart(SecCmsEnvelopedDataRef envd) +{ + int version; + SecCmsRecipientInfoRef *recipientinfos; + SecCmsContentInfoRef cinfo; + SecSymmetricKeyRef bulkkey = NULL; + CSSM_ALGORITHMS algorithm; + SECOidTag bulkalgtag; + //CK_MECHANISM_TYPE type; + //PK11SlotInfo *slot; + OSStatus rv; + CSSM_DATA_PTR dummy; + PLArenaPool *poolp; + extern const SecAsn1Template SecCmsRecipientInfoTemplate[]; + void *mark = NULL; + int i; + + poolp = envd->cmsg->poolp; + cinfo = &(envd->contentInfo); + + recipientinfos = envd->recipientInfos; + if (recipientinfos == NULL) { + PORT_SetError(SEC_ERROR_BAD_DATA); +#if 0 + PORT_SetErrorString("Cannot find recipientinfos to encode."); +#endif + goto loser; + } + + version = SEC_CMS_ENVELOPED_DATA_VERSION_REG; + if (envd->originatorInfo != NULL || envd->unprotectedAttr != NULL) { + version = SEC_CMS_ENVELOPED_DATA_VERSION_ADV; + } else { + for (i = 0; recipientinfos[i] != NULL; i++) { + if (SecCmsRecipientInfoGetVersion(recipientinfos[i]) != 0) { + version = SEC_CMS_ENVELOPED_DATA_VERSION_ADV; + break; + } + } + } + dummy = SEC_ASN1EncodeInteger(poolp, &(envd->version), version); + if (dummy == NULL) + goto loser; + + /* now we need to have a proper content encryption algorithm + * on the SMIME level, we would figure one out by looking at SMIME capabilities + * we cannot do that on our level, so if none is set already, we'll just go + * with one of the mandatory algorithms (3DES) */ + if ((bulkalgtag = SecCmsContentInfoGetContentEncAlgTag(cinfo)) == SEC_OID_UNKNOWN) { + rv = SecCmsContentInfoSetContentEncAlg((SecArenaPoolRef)poolp, cinfo, SEC_OID_DES_EDE3_CBC, NULL, 168); + if (rv != SECSuccess) + goto loser; + bulkalgtag = SEC_OID_DES_EDE3_CBC; + } + + algorithm = SECOID_FindyCssmAlgorithmByTag(bulkalgtag); + if (!algorithm) + goto loser; + rv = SecKeyGenerate(NULL, /* keychainRef */ + algorithm, + SecCmsContentInfoGetBulkKeySize(cinfo), + 0, /* contextHandle */ + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + CSSM_KEYATTR_EXTRACTABLE, + NULL, /* initialAccess */ + &bulkkey); + if (rv) + goto loser; + + mark = PORT_ArenaMark(poolp); + + /* Encrypt the bulk key with the public key of each recipient. */ + for (i = 0; recipientinfos[i] != NULL; i++) { + rv = SecCmsRecipientInfoWrapBulkKey(recipientinfos[i], bulkkey, bulkalgtag); + if (rv != SECSuccess) + goto loser; /* error has been set by SecCmsRecipientInfoEncryptBulkKey */ + /* could be: alg not supported etc. */ + } + + /* the recipientinfos are all finished. now sort them by DER for SET OF encoding */ + rv = SecCmsArraySortByDER((void **)envd->recipientInfos, SecCmsRecipientInfoTemplate, NULL); + if (rv != SECSuccess) + goto loser; /* error has been set by SecCmsArraySortByDER */ + + /* store the bulk key in the contentInfo so that the encoder can find it */ + SecCmsContentInfoSetBulkKey(cinfo, bulkkey); + + PORT_ArenaUnmark(poolp, mark); + + CFRelease(bulkkey); + + return SECSuccess; + +loser: + if (mark != NULL) + PORT_ArenaRelease (poolp, mark); + if (bulkkey) + CFRelease(bulkkey); + + return SECFailure; +} + +/* + * SecCmsEnvelopedDataEncodeBeforeData - set up encryption + * + * it is essential that this is called before the contentEncAlg is encoded, because + * setting up the encryption may generate IVs and thus change it! + */ +OSStatus +SecCmsEnvelopedDataEncodeBeforeData(SecCmsEnvelopedDataRef envd) +{ + SecCmsContentInfoRef cinfo; + SecSymmetricKeyRef bulkkey; + SECAlgorithmID *algid; + + cinfo = &(envd->contentInfo); + + /* find bulkkey and algorithm - must have been set by SecCmsEnvelopedDataEncodeBeforeStart */ + bulkkey = SecCmsContentInfoGetBulkKey(cinfo); + if (bulkkey == NULL) + return SECFailure; + algid = SecCmsContentInfoGetContentEncAlg(cinfo); + if (algid == NULL) + return SECFailure; + + /* this may modify algid (with IVs generated in a token). + * it is essential that algid is a pointer to the contentEncAlg data, not a + * pointer to a copy! */ + cinfo->ciphcx = SecCmsCipherContextStartEncrypt(envd->cmsg->poolp, bulkkey, algid); + CFRelease(bulkkey); + if (cinfo->ciphcx == NULL) + return SECFailure; + + return SECSuccess; +} + +/* + * SecCmsEnvelopedDataEncodeAfterData - finalize this envelopedData for encoding + */ +OSStatus +SecCmsEnvelopedDataEncodeAfterData(SecCmsEnvelopedDataRef envd) +{ + if (envd->contentInfo.ciphcx) { + SecCmsCipherContextDestroy(envd->contentInfo.ciphcx); + envd->contentInfo.ciphcx = NULL; + } + + /* nothing else to do after data */ + return SECSuccess; +} + +/* + * SecCmsEnvelopedDataDecodeBeforeData - find our recipientinfo, + * derive bulk key & set up our contentinfo + */ +OSStatus +SecCmsEnvelopedDataDecodeBeforeData(SecCmsEnvelopedDataRef envd) +{ + SecCmsRecipientInfoRef ri; + SecSymmetricKeyRef bulkkey = NULL; + SECOidTag bulkalgtag; + SECAlgorithmID *bulkalg; + OSStatus rv = SECFailure; + SecCmsContentInfoRef cinfo; + SecCmsRecipient **recipient_list = NULL; + SecCmsRecipient *recipient; + int rlIndex; + + if (SecCmsArrayCount((void **)envd->recipientInfos) == 0) { + PORT_SetError(SEC_ERROR_BAD_DATA); +#if 0 + PORT_SetErrorString("No recipient data in envelope."); +#endif + goto loser; + } + + /* look if one of OUR cert's issuerSN is on the list of recipients, and if so, */ + /* get the cert and private key for it right away */ + recipient_list = nss_cms_recipient_list_create(envd->recipientInfos); + if (recipient_list == NULL) + goto loser; + + /* what about multiple recipientInfos that match? + * especially if, for some reason, we could not produce a bulk key with the first match?! + * we could loop & feed partial recipient_list to PK11_FindCertAndKeyByRecipientList... + * maybe later... */ + rlIndex = nss_cms_FindCertAndKeyByRecipientList(recipient_list, envd->cmsg->pwfn_arg); + + /* if that fails, then we're not an intended recipient and cannot decrypt */ + if (rlIndex < 0) { + PORT_SetError(SEC_ERROR_NOT_A_RECIPIENT); +#if 0 + PORT_SetErrorString("Cannot decrypt data because proper key cannot be found."); +#endif + goto loser; + } + + recipient = recipient_list[rlIndex]; + if (!recipient->cert || !recipient->privkey) { + /* XXX should set an error code ?!? */ + goto loser; + } + /* get a pointer to "our" recipientinfo */ + ri = envd->recipientInfos[recipient->riIndex]; + + cinfo = &(envd->contentInfo); + bulkalgtag = SecCmsContentInfoGetContentEncAlgTag(cinfo); + if (bulkalgtag == SEC_OID_UNKNOWN) { + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + } else + bulkkey = SecCmsRecipientInfoUnwrapBulkKey(ri,recipient->subIndex, + recipient->cert, + recipient->privkey, + bulkalgtag); + if (bulkkey == NULL) { + /* no success finding a bulk key */ + rv = errSecDataNotAvailable; + goto loser; + } + + SecCmsContentInfoSetBulkKey(cinfo, bulkkey); + // @@@ See 3401088 for details. We need to CFRelease cinfo->bulkkey before recipient->privkey gets CFReleased. It's created with SecKeyCreateWithCSSMKey which is not safe currently. If the private key's SecKeyRef from which we extracted the CSP gets CFRelease before the builkkey does we crash. We should really fix SecKeyCreateWithCSSMKey which is a huge hack currently. To work around this we add recipient->privkey to the cinfo so it gets when cinfo is destroyed. + CFRetain(recipient->privkey); + cinfo->privkey = recipient->privkey; + + bulkalg = SecCmsContentInfoGetContentEncAlg(cinfo); + + cinfo->ciphcx = SecCmsCipherContextStartDecrypt(bulkkey, bulkalg); + if (cinfo->ciphcx == NULL) + goto loser; /* error has been set by SecCmsCipherContextStartDecrypt */ + +#if 1 + // @@@ Fix me +#else + /* + * HACK ALERT!! + * For PKCS5 Encryption Algorithms, the bulkkey is actually a different + * structure. Therefore, we need to set the bulkkey to the actual key + * prior to freeing it. + */ + if (SEC_PKCS5IsAlgorithmPBEAlg(bulkalg)) { + SEC_PKCS5KeyAndPassword *keyPwd = (SEC_PKCS5KeyAndPassword *)bulkkey; + bulkkey = keyPwd->key; + } +#endif + + rv = SECSuccess; + +loser: + if (bulkkey) + CFRelease(bulkkey); + if (recipient_list != NULL) + nss_cms_recipient_list_destroy(recipient_list); + return rv; +} + +/* + * SecCmsEnvelopedDataDecodeAfterData - finish decrypting this envelopedData's content + */ +OSStatus +SecCmsEnvelopedDataDecodeAfterData(SecCmsEnvelopedDataRef envd) +{ + if (envd && envd->contentInfo.ciphcx) { + SecCmsCipherContextDestroy(envd->contentInfo.ciphcx); + envd->contentInfo.ciphcx = NULL; + } + + return SECSuccess; +} + +/* + * SecCmsEnvelopedDataDecodeAfterEnd - finish decoding this envelopedData + */ +OSStatus +SecCmsEnvelopedDataDecodeAfterEnd(SecCmsEnvelopedDataRef envd) +{ + /* apply final touches */ + return SECSuccess; +} + diff --git a/Security/libsecurity_smime/lib/cmslocal.h b/Security/libsecurity_smime/lib/cmslocal.h new file mode 100644 index 00000000..abda2456 --- /dev/null +++ b/Security/libsecurity_smime/lib/cmslocal.h @@ -0,0 +1,346 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * Support routines for CMS implementation, none of which are exported. + * + * Do not export this file! If something in here is really needed outside + * of smime code, first try to add a CMS interface which will do it for + * you. If that has a problem, then just move out what you need, changing + * its name as appropriate! + */ + +#ifndef _CMSLOCAL_H_ +#define _CMSLOCAL_H_ + +#include "cmspriv.h" +#include "cmsreclist.h" +#include + +extern const SecAsn1Template SecCmsIssuerAndSNTemplate[]; +extern const SecAsn1Template SecCmsContentInfoTemplate[]; + +/************************************************************************/ +SEC_BEGIN_PROTOS + +/*********************************************************************** + * cmscipher.c - en/decryption routines + ***********************************************************************/ + +/* + * SecCmsCipherContextStartDecrypt - create a cipher context to do decryption + * based on the given bulk * encryption key and algorithm identifier (which may include an iv). + */ +extern SecCmsCipherContextRef +SecCmsCipherContextStartDecrypt(SecSymmetricKeyRef key, SECAlgorithmID *algid); + +/* + * SecCmsCipherContextStartEncrypt - create a cipher object to do encryption, + * based on the given bulk encryption key and algorithm tag. Fill in the algorithm + * identifier (which may include an iv) appropriately. + */ +extern SecCmsCipherContextRef +SecCmsCipherContextStartEncrypt(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorithmID *algid); + +extern void +SecCmsCipherContextDestroy(SecCmsCipherContextRef cc); + +/* + * SecCmsCipherContextDecryptLength - find the output length of the next call to decrypt. + * + * cc - the cipher context + * input_len - number of bytes used as input + * final - true if this is the final chunk of data + * + * Result can be used to perform memory allocations. Note that the amount + * is exactly accurate only when not doing a block cipher or when final + * is false, otherwise it is an upper bound on the amount because until + * we see the data we do not know how many padding bytes there are + * (always between 1 and bsize). + */ +extern size_t +SecCmsCipherContextDecryptLength(SecCmsCipherContextRef cc, size_t input_len, Boolean final); + +/* + * SecCmsCipherContextEncryptLength - find the output length of the next call to encrypt. + * + * cc - the cipher context + * input_len - number of bytes used as input + * final - true if this is the final chunk of data + * + * Result can be used to perform memory allocations. + */ +extern size_t +SecCmsCipherContextEncryptLength(SecCmsCipherContextRef cc, size_t input_len, Boolean final); + +/* + * SecCmsCipherContextDecrypt - do the decryption + * + * cc - the cipher context + * output - buffer for decrypted result bytes + * output_len_p - number of bytes in output + * max_output_len - upper bound on bytes to put into output + * input - pointer to input bytes + * input_len - number of input bytes + * final - true if this is the final chunk of data + * + * Decrypts a given length of input buffer (starting at "input" and + * containing "input_len" bytes), placing the decrypted bytes in + * "output" and storing the output length in "*output_len_p". + * "cc" is the return value from SecCmsCipherStartDecrypt. + * When "final" is true, this is the last of the data to be decrypted. + */ +extern OSStatus +SecCmsCipherContextDecrypt(SecCmsCipherContextRef cc, unsigned char *output, + size_t *output_len_p, size_t max_output_len, + const unsigned char *input, size_t input_len, + Boolean final); + +/* + * SecCmsCipherContextEncrypt - do the encryption + * + * cc - the cipher context + * output - buffer for decrypted result bytes + * output_len_p - number of bytes in output + * max_output_len - upper bound on bytes to put into output + * input - pointer to input bytes + * input_len - number of input bytes + * final - true if this is the final chunk of data + * + * Encrypts a given length of input buffer (starting at "input" and + * containing "input_len" bytes), placing the encrypted bytes in + * "output" and storing the output length in "*output_len_p". + * "cc" is the return value from SecCmsCipherStartEncrypt. + * When "final" is true, this is the last of the data to be encrypted. + */ +extern OSStatus +SecCmsCipherContextEncrypt(SecCmsCipherContextRef cc, unsigned char *output, + size_t *output_len_p, size_t max_output_len, + const unsigned char *input, size_t input_len, + Boolean final); + +/************************************************************************ + * cmspubkey.c - public key operations + ************************************************************************/ + +/* + * SecCmsUtilEncryptSymKeyRSA - wrap a symmetric key with RSA + * + * this function takes a symmetric key and encrypts it using an RSA public key + * according to PKCS#1 and RFC2633 (S/MIME) + */ +extern OSStatus +SecCmsUtilEncryptSymKeyRSA(PLArenaPool *poolp, SecCertificateRef cert, + SecSymmetricKeyRef key, + CSSM_DATA_PTR encKey); + +extern OSStatus +SecCmsUtilEncryptSymKeyRSAPubKey(PLArenaPool *poolp, + SecPublicKeyRef publickey, + SecSymmetricKeyRef bulkkey, CSSM_DATA_PTR encKey); + +/* + * SecCmsUtilDecryptSymKeyRSA - unwrap a RSA-wrapped symmetric key + * + * this function takes an RSA-wrapped symmetric key and unwraps it, returning a symmetric + * key handle. Please note that the actual unwrapped key data may not be allowed to leave + * a hardware token... + */ +extern SecSymmetricKeyRef +SecCmsUtilDecryptSymKeyRSA(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, SECOidTag bulkalgtag); + +extern OSStatus +SecCmsUtilEncryptSymKeyECDH(PLArenaPool *poolp, SecCertificateRef cert, SecSymmetricKeyRef key, + CSSM_DATA_PTR encKey, CSSM_DATA_PTR ukm, SECAlgorithmID *keyEncAlg, + CSSM_DATA_PTR originatorPubKey); + +extern SecSymmetricKeyRef +SecCmsUtilDecryptSymKeyECDH(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, CSSM_DATA_PTR ukm, + SECAlgorithmID *keyEncAlg, SECOidTag bulkalgtag, CSSM_DATA_PTR pubKey); + +#if 0 +extern OSStatus +SecCmsUtilEncryptSymKeyMISSI(PLArenaPool *poolp, SecCertificateRef cert, SecSymmetricKeyRef key, + SECOidTag symalgtag, CSSM_DATA_PTR encKey, CSSM_DATA_PTR *pparams, void *pwfn_arg); + +extern SecSymmetricKeyRef +SecCmsUtilDecryptSymKeyMISSI(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, + SECAlgorithmID *keyEncAlg, SECOidTag bulkalgtag, void *pwfn_arg); + +extern OSStatus +SecCmsUtilEncryptSymKeyESDH(PLArenaPool *poolp, SecCertificateRef cert, SecSymmetricKeyRef key, + CSSM_DATA_PTR encKey, CSSM_DATA_PTR ukm, SECAlgorithmID *keyEncAlg, + CSSM_DATA_PTR originatorPubKey); + +extern SecSymmetricKeyRef +SecCmsUtilDecryptSymKeyESDH(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, + SECAlgorithmID *keyEncAlg, SECOidTag bulkalgtag, void *pwfn_arg); +#endif + +/************************************************************************ + * cmsreclist.c - recipient list stuff + ************************************************************************/ +extern SecCmsRecipient **nss_cms_recipient_list_create(SecCmsRecipientInfoRef *recipientinfos); +extern void nss_cms_recipient_list_destroy(SecCmsRecipient **recipient_list); +extern SecCmsRecipientEncryptedKey *SecCmsRecipientEncryptedKeyCreate(PLArenaPool *poolp); + +/************************************************************************ + * cmsarray.c - misc array functions + ************************************************************************/ +/* + * SecCmsArrayAlloc - allocate an array in an arena + */ +extern void ** +SecCmsArrayAlloc(PRArenaPool *poolp, int n); + +/* + * SecCmsArrayAdd - add an element to the end of an array + */ +extern OSStatus +SecCmsArrayAdd(PRArenaPool *poolp, void ***array, void *obj); + +/* + * SecCmsArrayIsEmpty - check if array is empty + */ +extern Boolean +SecCmsArrayIsEmpty(void **array); + +/* + * SecCmsArrayCount - count number of elements in array + */ +extern int +SecCmsArrayCount(void **array); + +/* + * SecCmsArraySort - sort an array ascending, in place + * + * If "secondary" is not NULL, the same reordering gets applied to it. + * If "tertiary" is not NULL, the same reordering gets applied to it. + * "compare" is a function that returns + * < 0 when the first element is less than the second + * = 0 when the first element is equal to the second + * > 0 when the first element is greater than the second + */ +extern void +SecCmsArraySort(void **primary, int (*compare)(void *,void *), void **secondary, void **tertiary); + +/************************************************************************ + * cmsattr.c - misc attribute functions + ************************************************************************/ +/* + * SecCmsAttributeCreate - create an attribute + * + * if value is NULL, the attribute won't have a value. It can be added later + * with SecCmsAttributeAddValue. + */ +extern SecCmsAttribute * +SecCmsAttributeCreate(PRArenaPool *poolp, SECOidTag oidtag, CSSM_DATA_PTR value, Boolean encoded); + +/* + * SecCmsAttributeAddValue - add another value to an attribute + */ +extern OSStatus +SecCmsAttributeAddValue(PLArenaPool *poolp, SecCmsAttribute *attr, CSSM_DATA_PTR value); + +/* + * SecCmsAttributeGetType - return the OID tag + */ +extern SECOidTag +SecCmsAttributeGetType(SecCmsAttribute *attr); + +/* + * SecCmsAttributeGetValue - return the first attribute value + * + * We do some sanity checking first: + * - Multiple values are *not* expected. + * - Empty values are *not* expected. + */ +extern CSSM_DATA_PTR +SecCmsAttributeGetValue(SecCmsAttribute *attr); + +/* + * SecCmsAttributeCompareValue - compare the attribute's first value against data + */ +extern Boolean +SecCmsAttributeCompareValue(SecCmsAttribute *attr, CSSM_DATA_PTR av); + +/* + * SecCmsAttributeArrayEncode - encode an Attribute array as SET OF Attributes + * + * If you are wondering why this routine does not reorder the attributes + * first, and might be tempted to make it do so, see the comment by the + * call to ReorderAttributes in cmsencode.c. (Or, see who else calls this + * and think long and hard about the implications of making it always + * do the reordering.) + */ +extern CSSM_DATA_PTR +SecCmsAttributeArrayEncode(PRArenaPool *poolp, SecCmsAttribute ***attrs, CSSM_DATA_PTR dest); + +/* + * SecCmsAttributeArrayReorder - sort attribute array by attribute's DER encoding + * + * make sure that the order of the attributes guarantees valid DER (which must be + * in lexigraphically ascending order for a SET OF); if reordering is necessary it + * will be done in place (in attrs). + */ +extern OSStatus +SecCmsAttributeArrayReorder(SecCmsAttribute **attrs); + +/* + * SecCmsAttributeArrayFindAttrByOidTag - look through a set of attributes and + * find one that matches the specified object ID. + * + * If "only" is true, then make sure that there is not more than one attribute + * of the same type. Otherwise, just return the first one found. (XXX Does + * anybody really want that first-found behavior? It was like that when I found it...) + */ +extern SecCmsAttribute * +SecCmsAttributeArrayFindAttrByOidTag(SecCmsAttribute **attrs, SECOidTag oidtag, Boolean only); + +/* + * SecCmsAttributeArrayAddAttr - add an attribute to an + * array of attributes. + */ +extern OSStatus +SecCmsAttributeArrayAddAttr(PLArenaPool *poolp, SecCmsAttribute ***attrs, SecCmsAttribute *attr); + +/* + * SecCmsAttributeArraySetAttr - set an attribute's value in a set of attributes + */ +extern OSStatus +SecCmsAttributeArraySetAttr(PLArenaPool *poolp, SecCmsAttribute ***attrs, SECOidTag type, CSSM_DATA_PTR value, Boolean encoded); + +/************************************************************************/ +SEC_END_PROTOS + +#endif /* _CMSLOCAL_H_ */ diff --git a/Security/libsecurity_smime/lib/cmsmessage.c b/Security/libsecurity_smime/lib/cmsmessage.c new file mode 100644 index 00000000..816ce4af --- /dev/null +++ b/Security/libsecurity_smime/lib/cmsmessage.c @@ -0,0 +1,362 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * CMS message methods. + */ + +#include + +#include +#include + +#include "cmslocal.h" + +#include "secitem.h" +#include "secoid.h" + +#include +#include + +/* + * SecCmsMessageCreate - create a CMS message object + * + * "poolp" - arena to allocate memory from, or NULL if new arena should be created + */ +SecCmsMessageRef +SecCmsMessageCreate(SecArenaPoolRef pool) +{ + PLArenaPool *poolp = (PLArenaPool *)pool; + void *mark = NULL; + SecCmsMessageRef cmsg; + Boolean poolp_is_ours = PR_FALSE; + + if (poolp == NULL) { + poolp = PORT_NewArena (1024); /* XXX what is right value? */ + if (poolp == NULL) + return NULL; + poolp_is_ours = PR_TRUE; + } + + if (!poolp_is_ours) + mark = PORT_ArenaMark(poolp); + + cmsg = (SecCmsMessageRef)PORT_ArenaZAlloc (poolp, sizeof(SecCmsMessage)); + if (cmsg == NULL) { + if (!poolp_is_ours) { + if (mark) { + PORT_ArenaRelease(poolp, mark); + } + } else + PORT_FreeArena(poolp, PR_FALSE); + return NULL; + } + + cmsg->poolp = poolp; + cmsg->poolp_is_ours = poolp_is_ours; + cmsg->refCount = 1; + + if (mark) + PORT_ArenaUnmark(poolp, mark); + + return cmsg; +} + +/* + * SecCmsMessageSetEncodingParams - set up a CMS message object for encoding or decoding + * + * "cmsg" - message object + * "pwfn", pwfn_arg" - callback function for getting token password + * "decrypt_key_cb", "decrypt_key_cb_arg" - callback function for getting bulk key for encryptedData + * "detached_digestalgs", "detached_digests" - digests from detached content + */ +void +SecCmsMessageSetEncodingParams(SecCmsMessageRef cmsg, + PK11PasswordFunc pwfn, void *pwfn_arg, + SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg, + SECAlgorithmID **detached_digestalgs, CSSM_DATA_PTR *detached_digests) +{ +#if 0 + // @@@ Deal with password stuff. + if (pwfn) + PK11_SetPasswordFunc(pwfn); +#endif + cmsg->pwfn_arg = pwfn_arg; + cmsg->decrypt_key_cb = decrypt_key_cb; + cmsg->decrypt_key_cb_arg = decrypt_key_cb_arg; + cmsg->detached_digestalgs = detached_digestalgs; + cmsg->detached_digests = detached_digests; +} + +/* + * SecCmsMessageDestroy - destroy a CMS message and all of its sub-pieces. + */ +void +SecCmsMessageDestroy(SecCmsMessageRef cmsg) +{ + PORT_Assert (cmsg->refCount > 0); + if (cmsg->refCount <= 0) /* oops */ + return; + + cmsg->refCount--; /* thread safety? */ + if (cmsg->refCount > 0) + return; + + SecCmsContentInfoDestroy(&(cmsg->contentInfo)); + + /* if poolp is not NULL, cmsg is the owner of its arena */ + if (cmsg->poolp_is_ours) + PORT_FreeArena (cmsg->poolp, PR_FALSE); /* XXX clear it? */ +} + +/* + * SecCmsMessageCopy - return a copy of the given message. + * + * The copy may be virtual or may be real -- either way, the result needs + * to be passed to SecCmsMessageDestroy later (as does the original). + */ +SecCmsMessageRef +SecCmsMessageCopy(SecCmsMessageRef cmsg) +{ + if (cmsg == NULL) + return NULL; + + PORT_Assert (cmsg->refCount > 0); + + cmsg->refCount++; /* XXX chrisk thread safety? */ + return cmsg; +} + +/* + * SecCmsMessageGetArena - return a pointer to the message's arena pool + */ +SecArenaPoolRef +SecCmsMessageGetArena(SecCmsMessageRef cmsg) +{ + return (SecArenaPoolRef)cmsg->poolp; +} + +/* + * SecCmsMessageGetContentInfo - return a pointer to the top level contentInfo + */ +SecCmsContentInfoRef +SecCmsMessageGetContentInfo(SecCmsMessageRef cmsg) +{ + return &(cmsg->contentInfo); +} + +/* + * Return a pointer to the actual content. + * In the case of those types which are encrypted, this returns the *plain* content. + * In case of nested contentInfos, this descends and retrieves the innermost content. + */ +CSSM_DATA_PTR +SecCmsMessageGetContent(SecCmsMessageRef cmsg) +{ + /* this is a shortcut */ + SecCmsContentInfoRef cinfo = SecCmsMessageGetContentInfo(cmsg); + CSSM_DATA_PTR pItem = SecCmsContentInfoGetInnerContent(cinfo); + return pItem; +} + +/* + * SecCmsMessageContentLevelCount - count number of levels of CMS content objects in this message + * + * CMS data content objects do not count. + */ +int +SecCmsMessageContentLevelCount(SecCmsMessageRef cmsg) +{ + int count = 0; + SecCmsContentInfoRef cinfo; + + /* walk down the chain of contentinfos */ + for (cinfo = &(cmsg->contentInfo); cinfo != NULL; ) { + count++; + cinfo = SecCmsContentInfoGetChildContentInfo(cinfo); + } + return count; +} + +/* + * SecCmsMessageContentLevel - find content level #n + * + * CMS data content objects do not count. + */ +SecCmsContentInfoRef +SecCmsMessageContentLevel(SecCmsMessageRef cmsg, int n) +{ + int count = 0; + SecCmsContentInfoRef cinfo; + + /* walk down the chain of contentinfos */ + for (cinfo = &(cmsg->contentInfo); cinfo != NULL && count < n; cinfo = SecCmsContentInfoGetChildContentInfo(cinfo)) { + count++; + } + + return cinfo; +} + +/* + * SecCmsMessageContainsCertsOrCrls - see if message contains certs along the way + */ +Boolean +SecCmsMessageContainsCertsOrCrls(SecCmsMessageRef cmsg) +{ + SecCmsContentInfoRef cinfo; + + /* descend into CMS message */ + for (cinfo = &(cmsg->contentInfo); cinfo != NULL; cinfo = SecCmsContentInfoGetChildContentInfo(cinfo)) { + if (SecCmsContentInfoGetContentTypeTag(cinfo) != SEC_OID_PKCS7_SIGNED_DATA) + continue; /* next level */ + + if (SecCmsSignedDataContainsCertsOrCrls(cinfo->content.signedData)) + return PR_TRUE; + } + return PR_FALSE; +} + +/* + * SecCmsMessageIsEncrypted - see if message contains a encrypted submessage + */ +Boolean +SecCmsMessageIsEncrypted(SecCmsMessageRef cmsg) +{ + SecCmsContentInfoRef cinfo; + + /* walk down the chain of contentinfos */ + for (cinfo = &(cmsg->contentInfo); cinfo != NULL; cinfo = SecCmsContentInfoGetChildContentInfo(cinfo)) + { + switch (SecCmsContentInfoGetContentTypeTag(cinfo)) { + case SEC_OID_PKCS7_ENVELOPED_DATA: + case SEC_OID_PKCS7_ENCRYPTED_DATA: + return PR_TRUE; + default: + break; + } + } + return PR_FALSE; +} + +/* + * SecCmsMessageIsSigned - see if message contains a signed submessage + * + * If the CMS message has a SignedData with a signature (not just a SignedData) + * return true; false otherwise. This can/should be called before calling + * VerifySignature, which will always indicate failure if no signature is + * present, but that does not mean there even was a signature! + * Note that the content itself can be empty (detached content was sent + * another way); it is the presence of the signature that matters. + */ +Boolean +SecCmsMessageIsSigned(SecCmsMessageRef cmsg) +{ + SecCmsContentInfoRef cinfo; + + /* walk down the chain of contentinfos */ + for (cinfo = &(cmsg->contentInfo); cinfo != NULL; cinfo = SecCmsContentInfoGetChildContentInfo(cinfo)) + { + switch (SecCmsContentInfoGetContentTypeTag(cinfo)) { + case SEC_OID_PKCS7_SIGNED_DATA: + if (!SecCmsArrayIsEmpty((void **)cinfo->content.signedData->signerInfos)) + return PR_TRUE; + break; + default: + break; + } + } + return PR_FALSE; +} + +/* + * SecCmsMessageIsContentEmpty - see if content is empty + * + * returns PR_TRUE is innermost content length is < minLen + * XXX need the encrypted content length (why?) + */ +Boolean +SecCmsMessageIsContentEmpty(SecCmsMessageRef cmsg, unsigned int minLen) +{ + CSSM_DATA_PTR item = NULL; + + if (cmsg == NULL) + return PR_TRUE; + + item = SecCmsContentInfoGetContent(SecCmsMessageGetContentInfo(cmsg)); + + if (!item) { + return PR_TRUE; + } else if(item->Length <= minLen) { + return PR_TRUE; + } + + return PR_FALSE; +} + +/* + * SecCmsMessageContainsTSTInfo - see if message contains a TimeStamping info block + */ +Boolean +SecCmsMessageContainsTSTInfo(SecCmsMessageRef cmsg) +{ + SecCmsContentInfoRef cinfo; + + /* walk down the chain of contentinfos */ + for (cinfo = &(cmsg->contentInfo); cinfo != NULL; cinfo = SecCmsContentInfoGetChildContentInfo(cinfo)) + { + switch (SecCmsContentInfoGetContentTypeTag(cinfo)) + { + case SEC_OID_PKCS9_ID_CT_TSTInfo: + // TSTInfo is in cinfo->rawContent->Data + return PR_TRUE; + default: + break; + } + } + return PR_FALSE; +} + +void +SecCmsMessageSetTSACallback(SecCmsMessageRef cmsg, SecCmsTSACallback tsaCallback) +{ + if (cmsg) + cmsg->tsaCallback = tsaCallback; +} + +void +SecCmsMessageSetTSAContext(SecCmsMessageRef cmsg, const void *tsaContext) //CFTypeRef +{ + if (cmsg) + cmsg->tsaContext = tsaContext; +} + diff --git a/Security/libsecurity_smime/lib/cmspriv.h b/Security/libsecurity_smime/lib/cmspriv.h new file mode 100644 index 00000000..db88bb49 --- /dev/null +++ b/Security/libsecurity_smime/lib/cmspriv.h @@ -0,0 +1,510 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * Interfaces of the CMS implementation. + */ + +#ifndef _CMSPRIV_H_ +#define _CMSPRIV_H_ + +#include +#include "cmstpriv.h" + +/************************************************************************/ +SEC_BEGIN_PROTOS + + +/************************************************************************ + * cmsutil.c - CMS misc utility functions + ************************************************************************/ + + +/* + * SecCmsArraySortByDER - sort array of objects by objects' DER encoding + * + * make sure that the order of the objects guarantees valid DER (which must be + * in lexigraphically ascending order for a SET OF); if reordering is necessary it + * will be done in place (in objs). + */ +extern OSStatus +SecCmsArraySortByDER(void **objs, const SecAsn1Template *objtemplate, void **objs2); + +/* + * SecCmsUtilDERCompare - for use with SecCmsArraySort to + * sort arrays of CSSM_DATAs containing DER + */ +extern int +SecCmsUtilDERCompare(void *a, void *b); + +/* + * SecCmsAlgArrayGetIndexByAlgID - find a specific algorithm in an array of + * algorithms. + * + * algorithmArray - array of algorithm IDs + * algid - algorithmid of algorithm to pick + * + * Returns: + * An integer containing the index of the algorithm in the array or -1 if + * algorithm was not found. + */ +extern int +SecCmsAlgArrayGetIndexByAlgID(SECAlgorithmID **algorithmArray, SECAlgorithmID *algid); + +/* + * SecCmsAlgArrayGetIndexByAlgID - find a specific algorithm in an array of + * algorithms. + * + * algorithmArray - array of algorithm IDs + * algiddata - id of algorithm to pick + * + * Returns: + * An integer containing the index of the algorithm in the array or -1 if + * algorithm was not found. + */ +extern int +SecCmsAlgArrayGetIndexByAlgTag(SECAlgorithmID **algorithmArray, SECOidTag algtag); + +extern CSSM_CC_HANDLE +SecCmsUtilGetHashObjByAlgID(SECAlgorithmID *algid); + +/* + * XXX I would *really* like to not have to do this, but the current + * signing interface gives me little choice. + */ +extern SECOidTag +SecCmsUtilMakeSignatureAlgorithm(SECOidTag hashalg, SECOidTag encalg); + +extern const SecAsn1Template * +SecCmsUtilGetTemplateByTypeTag(SECOidTag type); + +extern size_t +SecCmsUtilGetSizeByTypeTag(SECOidTag type); + +extern SecCmsContentInfoRef +SecCmsContentGetContentInfo(void *msg, SECOidTag type); + +/************************************************************************ +* cmsmessage.c - CMS message methods +************************************************************************/ + +/*! +@function + @abstract Set up a CMS message object for encoding or decoding. + @discussion used internally. + @param cmsg Pointer to a SecCmsMessage object + @param pwfn callback function for getting token password for enveloped + data content with a password recipient. + @param pwfn_arg first argument passed to pwfn when it is called. + @param encrypt_key_cb callback function for getting bulk key for encryptedData content. + @param encrypt_key_cb_arg first argument passed to encrypt_key_cb when it is + called. + @param detached_digestalgs digest algorithms in detached_digests + @param detached_digests digests from detached content (one for every element + in detached_digestalgs). + */ +extern void +SecCmsMessageSetEncodingParams(SecCmsMessageRef cmsg, + PK11PasswordFunc pwfn, void *pwfn_arg, + SecCmsGetDecryptKeyCallback encrypt_key_cb, void *encrypt_key_cb_arg, + SECAlgorithmID **detached_digestalgs, CSSM_DATA_PTR *detached_digests); + +extern void +SecCmsMessageSetTSACallback(SecCmsMessageRef cmsg, SecCmsTSACallback tsaCallback); + +extern void +SecCmsMessageSetTSAContext(SecCmsMessageRef cmsg, const void *tsaContext); //CFTypeRef + +/************************************************************************ + * cmscinfo.c - CMS contentInfo methods + ************************************************************************/ + +/*! + Destroy a CMS contentInfo and all of its sub-pieces. + @param cinfo The contentInfo object to destroy. + */ +extern void +SecCmsContentInfoDestroy(SecCmsContentInfoRef cinfo); + +/* + * SecCmsContentInfoSetContent - set cinfo's content type & content to CMS object + */ +extern OSStatus +SecCmsContentInfoSetContent(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SECOidTag type, void *ptr); + + +/************************************************************************ + * cmssigdata.c - CMS signedData methods + ************************************************************************/ + +extern OSStatus +SecCmsSignedDataSetDigestValue(SecCmsSignedDataRef sigd, + SECOidTag digestalgtag, + CSSM_DATA_PTR digestdata); + +extern OSStatus +SecCmsSignedDataAddDigest(SecArenaPoolRef pool, + SecCmsSignedDataRef sigd, + SECOidTag digestalgtag, + CSSM_DATA_PTR digest); + +extern CSSM_DATA_PTR +SecCmsSignedDataGetDigestByAlgTag(SecCmsSignedDataRef sigd, SECOidTag algtag); + +extern CSSM_DATA_PTR +SecCmsSignedDataGetDigestValue(SecCmsSignedDataRef sigd, SECOidTag digestalgtag); + +/* + * SecCmsSignedDataEncodeBeforeStart - do all the necessary things to a SignedData + * before start of encoding. + * + * In detail: + * - find out about the right value to put into sigd->version + * - come up with a list of digestAlgorithms (which should be the union of the algorithms + * in the signerinfos). + * If we happen to have a pre-set list of algorithms (and digest values!), we + * check if we have all the signerinfos' algorithms. If not, this is an error. + */ +extern OSStatus +SecCmsSignedDataEncodeBeforeStart(SecCmsSignedDataRef sigd); + +extern OSStatus +SecCmsSignedDataEncodeBeforeData(SecCmsSignedDataRef sigd); + +/* + * SecCmsSignedDataEncodeAfterData - do all the necessary things to a SignedData + * after all the encapsulated data was passed through the encoder. + * + * In detail: + * - create the signatures in all the SignerInfos + * + * Please note that nothing is done to the Certificates and CRLs in the message - this + * is entirely the responsibility of our callers. + */ +extern OSStatus +SecCmsSignedDataEncodeAfterData(SecCmsSignedDataRef sigd); + +extern OSStatus +SecCmsSignedDataDecodeBeforeData(SecCmsSignedDataRef sigd); + +/* + * SecCmsSignedDataDecodeAfterData - do all the necessary things to a SignedData + * after all the encapsulated data was passed through the decoder. + */ +extern OSStatus +SecCmsSignedDataDecodeAfterData(SecCmsSignedDataRef sigd); + +/* + * SecCmsSignedDataDecodeAfterEnd - do all the necessary things to a SignedData + * after all decoding is finished. + */ +extern OSStatus +SecCmsSignedDataDecodeAfterEnd(SecCmsSignedDataRef sigd); + +/* + * Get SecCmsSignedDataRawCerts - obtain raw certs as a NULL_terminated array + * of pointers. + */ +extern OSStatus SecCmsSignedDataRawCerts(SecCmsSignedDataRef sigd, + CSSM_DATA_PTR **rawCerts); + +/************************************************************************ + * cmssiginfo.c - CMS signerInfo methods + ************************************************************************/ + +/* + * SecCmsSignerInfoSign - sign something + * + */ +extern OSStatus +SecCmsSignerInfoSign(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR digest, CSSM_DATA_PTR contentType); + +/* + * If trustRef is NULL the cert chain is verified and the VerificationStatus is set accordingly. + * Otherwise a SecTrust object is returned for the caller to evaluate using SecTrustEvaluate(). + */ +extern OSStatus +SecCmsSignerInfoVerifyCertificate(SecCmsSignerInfoRef signerinfo, SecKeychainRef keychainOrArray, + CFTypeRef policies, SecTrustRef *trustRef); + +/* + * SecCmsSignerInfoVerify - verify the signature of a single SignerInfo + * + * Just verifies the signature. The assumption is that verification of the certificate + * is done already. + */ +extern OSStatus +SecCmsSignerInfoVerify(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR digest, CSSM_DATA_PTR contentType); + +/* + * SecCmsSignerInfoVerifyWithPolicy - verify the signature of a single SignerInfo + * use the designated policy for timeStamp signer verification + * Just verifies the signature. The assumption is that verification of the certificate + * is done already. + */ +extern OSStatus +SecCmsSignerInfoVerifyWithPolicy(SecCmsSignerInfoRef signerinfo,CFTypeRef timeStampPolicy, CSSM_DATA_PTR digest, CSSM_DATA_PTR contentType); + +/* + * SecCmsSignerInfoAddAuthAttr - add an attribute to the + * authenticated (i.e. signed) attributes of "signerinfo". + */ +extern OSStatus +SecCmsSignerInfoAddAuthAttr(SecCmsSignerInfoRef signerinfo, SecCmsAttribute *attr); + +/* + * SecCmsSignerInfoAddUnauthAttr - add an attribute to the + * unauthenticated attributes of "signerinfo". + */ +extern OSStatus +SecCmsSignerInfoAddUnauthAttr(SecCmsSignerInfoRef signerinfo, SecCmsAttribute *attr); + +extern int +SecCmsSignerInfoGetVersion(SecCmsSignerInfoRef signerinfo); + +/* + * Determine whether Microsoft ECDSA compatibility mode is enabled. + * See comments in SecCmsSignerInfo.h for details. + * Implemented in siginfoUtils.cpp for access to C++ Dictionary class. + */ +extern bool +SecCmsMsEcdsaCompatMode(); + + +/************************************************************************ + * cmsenvdata.c - CMS envelopedData methods + ************************************************************************/ + +/* + * SecCmsEnvelopedDataEncodeBeforeStart - prepare this envelopedData for encoding + * + * at this point, we need + * - recipientinfos set up with recipient's certificates + * - a content encryption algorithm (if none, 3DES will be used) + * + * this function will generate a random content encryption key (aka bulk key), + * initialize the recipientinfos with certificate identification and wrap the bulk key + * using the proper algorithm for every certificiate. + * it will finally set the bulk algorithm and key so that the encode step can find it. + */ +extern OSStatus +SecCmsEnvelopedDataEncodeBeforeStart(SecCmsEnvelopedDataRef envd); + +/* + * SecCmsEnvelopedDataEncodeBeforeData - set up encryption + */ +extern OSStatus +SecCmsEnvelopedDataEncodeBeforeData(SecCmsEnvelopedDataRef envd); + +/* + * SecCmsEnvelopedDataEncodeAfterData - finalize this envelopedData for encoding + */ +extern OSStatus +SecCmsEnvelopedDataEncodeAfterData(SecCmsEnvelopedDataRef envd); + +/* + * SecCmsEnvelopedDataDecodeBeforeData - find our recipientinfo, + * derive bulk key & set up our contentinfo + */ +extern OSStatus +SecCmsEnvelopedDataDecodeBeforeData(SecCmsEnvelopedDataRef envd); + +/* + * SecCmsEnvelopedDataDecodeAfterData - finish decrypting this envelopedData's content + */ +extern OSStatus +SecCmsEnvelopedDataDecodeAfterData(SecCmsEnvelopedDataRef envd); + +/* + * SecCmsEnvelopedDataDecodeAfterEnd - finish decoding this envelopedData + */ +extern OSStatus +SecCmsEnvelopedDataDecodeAfterEnd(SecCmsEnvelopedDataRef envd); + + +/************************************************************************ + * cmsrecinfo.c - CMS recipientInfo methods + ************************************************************************/ + +extern int +SecCmsRecipientInfoGetVersion(SecCmsRecipientInfoRef ri); + +extern CSSM_DATA_PTR +SecCmsRecipientInfoGetEncryptedKey(SecCmsRecipientInfoRef ri, int subIndex); + + +extern SECOidTag +SecCmsRecipientInfoGetKeyEncryptionAlgorithmTag(SecCmsRecipientInfoRef ri); + +extern OSStatus +SecCmsRecipientInfoWrapBulkKey(SecCmsRecipientInfoRef ri, SecSymmetricKeyRef bulkkey, SECOidTag bulkalgtag); + +extern SecSymmetricKeyRef +SecCmsRecipientInfoUnwrapBulkKey(SecCmsRecipientInfoRef ri, int subIndex, + SecCertificateRef cert, SecPrivateKeyRef privkey, SECOidTag bulkalgtag); + + +/************************************************************************ + * cmsencdata.c - CMS encryptedData methods + ************************************************************************/ + +/* + * SecCmsEncryptedDataEncodeBeforeStart - do all the necessary things to a EncryptedData + * before encoding begins. + * + * In particular: + * - set the correct version value. + * - get the encryption key + */ +extern OSStatus +SecCmsEncryptedDataEncodeBeforeStart(SecCmsEncryptedDataRef encd); + +/* + * SecCmsEncryptedDataEncodeBeforeData - set up encryption + */ +extern OSStatus +SecCmsEncryptedDataEncodeBeforeData(SecCmsEncryptedDataRef encd); + +/* + * SecCmsEncryptedDataEncodeAfterData - finalize this encryptedData for encoding + */ +extern OSStatus +SecCmsEncryptedDataEncodeAfterData(SecCmsEncryptedDataRef encd); + +/* + * SecCmsEncryptedDataDecodeBeforeData - find bulk key & set up decryption + */ +extern OSStatus +SecCmsEncryptedDataDecodeBeforeData(SecCmsEncryptedDataRef encd); + +/* + * SecCmsEncryptedDataDecodeAfterData - finish decrypting this encryptedData's content + */ +extern OSStatus +SecCmsEncryptedDataDecodeAfterData(SecCmsEncryptedDataRef encd); + +/* + * SecCmsEncryptedDataDecodeAfterEnd - finish decoding this encryptedData + */ +extern OSStatus +SecCmsEncryptedDataDecodeAfterEnd(SecCmsEncryptedDataRef encd); + + +/************************************************************************ + * cmsdigdata.c - CMS encryptedData methods + ************************************************************************/ + +/* + * SecCmsDigestedDataEncodeBeforeStart - do all the necessary things to a DigestedData + * before encoding begins. + * + * In particular: + * - set the right version number. The contentInfo's content type must be set up already. + */ +extern OSStatus +SecCmsDigestedDataEncodeBeforeStart(SecCmsDigestedDataRef digd); + +/* + * SecCmsDigestedDataEncodeBeforeData - do all the necessary things to a DigestedData + * before the encapsulated data is passed through the encoder. + * + * In detail: + * - set up the digests if necessary + */ +extern OSStatus +SecCmsDigestedDataEncodeBeforeData(SecCmsDigestedDataRef digd); + +/* + * SecCmsDigestedDataEncodeAfterData - do all the necessary things to a DigestedData + * after all the encapsulated data was passed through the encoder. + * + * In detail: + * - finish the digests + */ +extern OSStatus +SecCmsDigestedDataEncodeAfterData(SecCmsDigestedDataRef digd); + +/* + * SecCmsDigestedDataDecodeBeforeData - do all the necessary things to a DigestedData + * before the encapsulated data is passed through the encoder. + * + * In detail: + * - set up the digests if necessary + */ +extern OSStatus +SecCmsDigestedDataDecodeBeforeData(SecCmsDigestedDataRef digd); + +/* + * SecCmsDigestedDataDecodeAfterData - do all the necessary things to a DigestedData + * after all the encapsulated data was passed through the encoder. + * + * In detail: + * - finish the digests + */ +extern OSStatus +SecCmsDigestedDataDecodeAfterData(SecCmsDigestedDataRef digd); + +/* + * SecCmsDigestedDataDecodeAfterEnd - finalize a digestedData. + * + * In detail: + * - check the digests for equality + */ +extern OSStatus +SecCmsDigestedDataDecodeAfterEnd(SecCmsDigestedDataRef digd); + + +/************************************************************************ + * cmsdigest.c - CMS encryptedData methods + ************************************************************************/ + +/* + * SecCmsDigestContextStartSingle - same as SecCmsDigestContextStartMultiple, but + * only one algorithm. + */ +extern SecCmsDigestContextRef +SecCmsDigestContextStartSingle(SECAlgorithmID *digestalg); + +/* + * SecCmsDigestContextFinishSingle - same as SecCmsDigestContextFinishMultiple, + * but for one digest. + */ +extern OSStatus +SecCmsDigestContextFinishSingle(SecCmsDigestContextRef cmsdigcx, SecArenaPoolRef arena, + CSSM_DATA_PTR digest); + + +/************************************************************************/ +SEC_END_PROTOS + +#endif /* _CMSPRIV_H_ */ diff --git a/Security/libsecurity_smime/lib/cmspubkey.c b/Security/libsecurity_smime/lib/cmspubkey.c new file mode 100644 index 00000000..0f4d9f42 --- /dev/null +++ b/Security/libsecurity_smime/lib/cmspubkey.c @@ -0,0 +1,1449 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * CMS public key crypto + */ + +#include "cmslocal.h" + +#include "secitem.h" +#include "secoid.h" +#include "cryptohi.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* ====== RSA ======================================================================= */ + +/* + * SecCmsUtilEncryptSymKeyRSA - wrap a symmetric key with RSA + * + * this function takes a symmetric key and encrypts it using an RSA public key + * according to PKCS#1 and RFC2633 (S/MIME) + */ +OSStatus +SecCmsUtilEncryptSymKeyRSA(PLArenaPool *poolp, SecCertificateRef cert, + SecSymmetricKeyRef bulkkey, + CSSM_DATA_PTR encKey) +{ + OSStatus rv; + SecPublicKeyRef publickey; + + rv = SecCertificateCopyPublicKey(cert,&publickey); + if (publickey == NULL) + return SECFailure; + + rv = SecCmsUtilEncryptSymKeyRSAPubKey(poolp, publickey, bulkkey, encKey); + CFRelease(publickey); + return rv; +} + +OSStatus +SecCmsUtilEncryptSymKeyRSAPubKey(PLArenaPool *poolp, + SecPublicKeyRef publickey, + SecSymmetricKeyRef bulkkey, CSSM_DATA_PTR encKey) +{ + OSStatus rv; + unsigned int data_len; + //KeyType keyType; + void *mark = NULL; + + mark = PORT_ArenaMark(poolp); + if (!mark) + goto loser; + +#if 0 + /* sanity check */ + keyType = SECKEY_GetPublicKeyType(publickey); + PORT_Assert(keyType == rsaKey); + if (keyType != rsaKey) { + goto loser; + } +#endif + /* allocate memory for the encrypted key */ + rv = SecKeyGetStrengthInBits(publickey, NULL, &data_len); + if (rv) + goto loser; + + // Convert length to bytes; + data_len >>= 2; + encKey->Data = (unsigned char*)PORT_ArenaAlloc(poolp, data_len); + encKey->Length = data_len; + if (encKey->Data == NULL) + goto loser; + + /* encrypt the key now */ + rv = WRAP_PubWrapSymKey(publickey, bulkkey, encKey); + if (rv != SECSuccess) + goto loser; + + PORT_ArenaUnmark(poolp, mark); + return SECSuccess; + +loser: + if (mark) { + PORT_ArenaRelease(poolp, mark); + } + return SECFailure; +} + +/* + * SecCmsUtilDecryptSymKeyRSA - unwrap a RSA-wrapped symmetric key + * + * this function takes an RSA-wrapped symmetric key and unwraps it, returning a symmetric + * key handle. Please note that the actual unwrapped key data may not be allowed to leave + * a hardware token... + */ +SecSymmetricKeyRef +SecCmsUtilDecryptSymKeyRSA(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, SECOidTag bulkalgtag) +{ + /* that's easy */ + return WRAP_PubUnwrapSymKey(privkey, encKey, bulkalgtag); +} + +#if 0 +// @@@ Implement Fortezza and Diffie hellman support + +/* ====== MISSI (Fortezza) ========================================================== */ + +extern const SecAsn1Template NSS_SMIMEKEAParamTemplateAllParams[]; + +OSStatus +SecCmsUtilEncryptSymKeyMISSI(PLArenaPool *poolp, SecCertificateRef cert, SecSymmetricKeyRef bulkkey, + SECOidTag symalgtag, CSSM_DATA_PTR encKey, CSSM_DATA_PTR *pparams, void *pwfn_arg) +{ + SECOidTag certalgtag; /* the certificate's encryption algorithm */ + SECOidTag encalgtag; /* the algorithm used for key exchange/agreement */ + OSStatus rv = SECFailure; + CSSM_DATA_PTR params = NULL; + OSStatus err; + SecSymmetricKeyRef tek; + SecCertificateRef ourCert; + SecPublicKeyRef ourPubKey, *publickey = NULL; + SecPrivateKeyRef ourPrivKey = NULL; + SecCmsKEATemplateSelector whichKEA = SecCmsKEAInvalid; + SecCmsSMIMEKEAParameters keaParams; + PLArenaPool *arena = NULL; + extern const SecAsn1Template *nss_cms_get_kea_template(SecCmsKEATemplateSelector whichTemplate); + const SECAlgorithmID *algid; + + /* Clear keaParams, since cleanup code checks the lengths */ + (void) memset(&keaParams, 0, sizeof(keaParams)); + + SecCertificateGetAlgorithmID(cert,&algid); + certalgtag = SECOID_GetAlgorithmTag(algid); + PORT_Assert(certalgtag == SEC_OID_MISSI_KEA_DSS_OLD || + certalgtag == SEC_OID_MISSI_KEA_DSS || + certalgtag == SEC_OID_MISSI_KEA); + +#define SMIME_FORTEZZA_RA_LENGTH 128 +#define SMIME_FORTEZZA_IV_LENGTH 24 +#define SMIME_FORTEZZA_MAX_KEY_SIZE 256 + + /* We really want to show our KEA tag as the key exchange algorithm tag. */ + encalgtag = SEC_OID_NETSCAPE_SMIME_KEA; + + /* Get the public key of the recipient. */ + publickey = CERT_ExtractPublicKey(cert); + if (publickey == NULL) goto loser; + + /* Find our own cert, and extract its keys. */ + ourCert = PK11_FindBestKEAMatch(cert, pwfn_arg); + if (ourCert == NULL) goto loser; + + arena = PORT_NewArena(1024); + if (arena == NULL) + goto loser; + + ourPubKey = CERT_ExtractPublicKey(ourCert); + if (ourPubKey == NULL) { + CERT_DestroyCertificate(ourCert); + goto loser; + } + + /* While we're here, copy the public key into the outgoing + * KEA parameters. */ + SECITEM_CopyItem(arena, &(keaParams.originatorKEAKey), &(ourPubKey->u.fortezza.KEAKey)); + SECKEY_DestroyPublicKey(ourPubKey); + ourPubKey = NULL; + + /* Extract our private key in order to derive the KEA key. */ + ourPrivKey = PK11_FindKeyByAnyCert(ourCert, pwfn_arg); + CERT_DestroyCertificate(ourCert); /* we're done with this */ + if (!ourPrivKey) + goto loser; + + /* Prepare raItem with 128 bytes (filled with zeros). */ + keaParams.originatorRA.Data = (unsigned char *)PORT_ArenaAlloc(arena,SMIME_FORTEZZA_RA_LENGTH); + keaParams.originatorRA.Length = SMIME_FORTEZZA_RA_LENGTH; + + /* Generate the TEK (token exchange key) which we use + * to wrap the bulk encryption key. (keaparams.originatorRA) will be + * filled with a random seed which we need to send to + * the recipient. (user keying material in RFC2630/DSA speak) */ + tek = PK11_PubDerive(ourPrivKey, publickey, PR_TRUE, + &keaParams.originatorRA, NULL, + CKM_KEA_KEY_DERIVE, CKM_SKIPJACK_WRAP, + CKA_WRAP, 0, pwfn_arg); + + SECKEY_DestroyPublicKey(publickey); + SECKEY_DestroyPrivateKey(ourPrivKey); + publickey = NULL; + ourPrivKey = NULL; + + if (!tek) + goto loser; + + /* allocate space for the wrapped key data */ + encKey->Data = (unsigned char *)PORT_ArenaAlloc(poolp, SMIME_FORTEZZA_MAX_KEY_SIZE); + encKey->Length = SMIME_FORTEZZA_MAX_KEY_SIZE; + + if (encKey->Data == NULL) { + CFRelease(tek); + goto loser; + } + + /* Wrap the bulk key. What we do with the resulting data + depends on whether we're using Skipjack to wrap the key. */ + switch (PK11_AlgtagToMechanism(symalgtag)) { + case CKM_SKIPJACK_CBC64: + case CKM_SKIPJACK_ECB64: + case CKM_SKIPJACK_OFB64: + case CKM_SKIPJACK_CFB64: + case CKM_SKIPJACK_CFB32: + case CKM_SKIPJACK_CFB16: + case CKM_SKIPJACK_CFB8: + /* SKIPJACK, we use the wrap mechanism because we can do it on the hardware */ + err = PK11_WrapSymKey(CKM_SKIPJACK_WRAP, NULL, tek, bulkkey, encKey); + whichKEA = SecCmsKEAUsesSkipjack; + break; + default: + /* Not SKIPJACK, we encrypt the raw key data */ + keaParams.nonSkipjackIV.Data = + (unsigned char *)PORT_ArenaAlloc(arena, SMIME_FORTEZZA_IV_LENGTH); + keaParams.nonSkipjackIV.Length = SMIME_FORTEZZA_IV_LENGTH; + err = PK11_WrapSymKey(CKM_SKIPJACK_CBC64, &keaParams.nonSkipjackIV, tek, bulkkey, encKey); + if (err != SECSuccess) + goto loser; + + if (encKey->Length != PK11_GetKeyLength(bulkkey)) { + /* The size of the encrypted key is not the same as + that of the original bulk key, presumably due to + padding. Encode and store the real size of the + bulk key. */ + if (SEC_ASN1EncodeInteger(arena, &keaParams.bulkKeySize, PK11_GetKeyLength(bulkkey)) == NULL) + err = (OSStatus)PORT_GetError(); + else + /* use full template for encoding */ + whichKEA = SecCmsKEAUsesNonSkipjackWithPaddedEncKey; + } + else + /* enc key length == bulk key length */ + whichKEA = SecCmsKEAUsesNonSkipjack; + break; + } + + CFRelease(tek); + + if (err != SECSuccess) + goto loser; + + PORT_Assert(whichKEA != SecCmsKEAInvalid); + + /* Encode the KEA parameters into the recipient info. */ + params = SEC_ASN1EncodeItem(poolp, NULL, &keaParams, nss_cms_get_kea_template(whichKEA)); + if (params == NULL) + goto loser; + + /* pass back the algorithm params */ + *pparams = params; + + rv = SECSuccess; + +loser: + if (arena) + PORT_FreeArena(arena, PR_FALSE); + if (publickey) + SECKEY_DestroyPublicKey(publickey); + if (ourPrivKey) + SECKEY_DestroyPrivateKey(ourPrivKey); + return rv; +} + +SecSymmetricKeyRef +SecCmsUtilDecryptSymKeyMISSI(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, SECAlgorithmID *keyEncAlg, SECOidTag bulkalgtag, void *pwfn_arg) +{ + /* fortezza: do a key exchange */ + OSStatus err; + CK_MECHANISM_TYPE bulkType; + SecSymmetricKeyRef tek; + SecPublicKeyRef originatorPubKey; + SecCmsSMIMEKEAParameters keaParams; + SecSymmetricKeyRef bulkkey; + int bulkLength; + + (void) memset(&keaParams, 0, sizeof(keaParams)); + + /* NOTE: this uses the SMIME v2 recipientinfo for compatibility. + All additional KEA parameters are DER-encoded in the encryption algorithm parameters */ + + /* Decode the KEA algorithm parameters. */ + err = SEC_ASN1DecodeItem(NULL, &keaParams, NSS_SMIMEKEAParamTemplateAllParams, + &(keyEncAlg->parameters)); + if (err != SECSuccess) + goto loser; + + /* get originator's public key */ + originatorPubKey = PK11_MakeKEAPubKey(keaParams.originatorKEAKey.Data, + keaParams.originatorKEAKey.Length); + if (originatorPubKey == NULL) + goto loser; + + /* Generate the TEK (token exchange key) which we use to unwrap the bulk encryption key. + The Derive function generates a shared secret and combines it with the originatorRA + data to come up with an unique session key */ + tek = PK11_PubDerive(privkey, originatorPubKey, PR_FALSE, + &keaParams.originatorRA, NULL, + CKM_KEA_KEY_DERIVE, CKM_SKIPJACK_WRAP, + CKA_WRAP, 0, pwfn_arg); + SECKEY_DestroyPublicKey(originatorPubKey); /* not needed anymore */ + if (tek == NULL) + goto loser; + + /* Now that we have the TEK, unwrap the bulk key + with which to decrypt the message. We have to + do one of two different things depending on + whether Skipjack was used for *bulk* encryption + of the message. */ + bulkType = PK11_AlgtagToMechanism(bulkalgtag); + switch (bulkType) { + case CKM_SKIPJACK_CBC64: + case CKM_SKIPJACK_ECB64: + case CKM_SKIPJACK_OFB64: + case CKM_SKIPJACK_CFB64: + case CKM_SKIPJACK_CFB32: + case CKM_SKIPJACK_CFB16: + case CKM_SKIPJACK_CFB8: + /* Skipjack is being used as the bulk encryption algorithm.*/ + /* Unwrap the bulk key. */ + bulkkey = PK11_UnwrapSymKey(tek, CKM_SKIPJACK_WRAP, NULL, + encKey, CKM_SKIPJACK_CBC64, CKA_DECRYPT, 0); + break; + default: + /* Skipjack was not used for bulk encryption of this + message. Use Skipjack CBC64, with the nonSkipjackIV + part of the KEA key parameters, to decrypt + the bulk key. If the optional parameter bulkKeySize is present, + bulk key size is different than the encrypted key size */ + if (keaParams.bulkKeySize.Length > 0) { + err = SEC_ASN1DecodeItem(NULL, &bulkLength, + SEC_ASN1_GET(SEC_IntegerTemplate), + &keaParams.bulkKeySize); + if (err != SECSuccess) + goto loser; + } + + bulkkey = PK11_UnwrapSymKey(tek, CKM_SKIPJACK_CBC64, &keaParams.nonSkipjackIV, + encKey, bulkType, CKA_DECRYPT, bulkLength); + break; + } + return bulkkey; +loser: + return NULL; +} + +/* ====== ESDH (Ephemeral-Static Diffie-Hellman) ==================================== */ + +OSStatus +SecCmsUtilEncryptSymKeyESDH(PLArenaPool *poolp, SecCertificateRef cert, SecSymmetricKeyRef key, + CSSM_DATA_PTR encKey, CSSM_DATA_PTR ukm, SECAlgorithmID *keyEncAlg, + CSSM_DATA_PTR pubKey) +{ +#if 0 /* not yet done */ + SECOidTag certalgtag; /* the certificate's encryption algorithm */ + SECOidTag encalgtag; /* the algorithm used for key exchange/agreement */ + OSStatus rv; + CSSM_DATA_PTR params = NULL; + int data_len; + OSStatus err; + SecSymmetricKeyRef tek; + SecCertificateRef ourCert; + SecPublicKeyRef ourPubKey; + SecCmsKEATemplateSelector whichKEA = SecCmsKEAInvalid; + + certalgtag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm)); + PORT_Assert(certalgtag == SEC_OID_X942_DIFFIE_HELMAN_KEY); + + /* We really want to show our KEA tag as the key exchange algorithm tag. */ + encalgtag = SEC_OID_CMS_EPHEMERAL_STATIC_DIFFIE_HELLMAN; + + /* Get the public key of the recipient. */ + publickey = CERT_ExtractPublicKey(cert); + if (publickey == NULL) goto loser; + + /* XXXX generate a DH key pair on a PKCS11 module (XXX which parameters?) */ + /* XXXX */ourCert = PK11_FindBestKEAMatch(cert, wincx); + if (ourCert == NULL) goto loser; + + arena = PORT_NewArena(1024); + if (arena == NULL) goto loser; + + /* While we're here, extract the key pair's public key data and copy it into */ + /* the outgoing parameters. */ + /* XXXX */ourPubKey = CERT_ExtractPublicKey(ourCert); + if (ourPubKey == NULL) + { + goto loser; + } + SECITEM_CopyItem(arena, pubKey, /* XXX */&(ourPubKey->u.fortezza.KEAKey)); + SECKEY_DestroyPublicKey(ourPubKey); /* we only need the private key from now on */ + ourPubKey = NULL; + + /* Extract our private key in order to derive the KEA key. */ + ourPrivKey = PK11_FindKeyByAnyCert(ourCert,wincx); + CERT_DestroyCertificate(ourCert); /* we're done with this */ + if (!ourPrivKey) goto loser; + + /* If ukm desired, prepare it - allocate enough space (filled with zeros). */ + if (ukm) { + ukm->Data = (unsigned char*)PORT_ArenaZAlloc(arena,/* XXXX */); + ukm->Length = /* XXXX */; + } + + /* Generate the KEK (key exchange key) according to RFC2631 which we use + * to wrap the bulk encryption key. */ + kek = PK11_PubDerive(ourPrivKey, publickey, PR_TRUE, + ukm, NULL, + /* XXXX */CKM_KEA_KEY_DERIVE, /* XXXX */CKM_SKIPJACK_WRAP, + CKA_WRAP, 0, wincx); + + SECKEY_DestroyPublicKey(publickey); + SECKEY_DestroyPrivateKey(ourPrivKey); + publickey = NULL; + ourPrivKey = NULL; + + if (!kek) + goto loser; + + /* allocate space for the encrypted CEK (bulk key) */ + encKey->Data = (unsigned char*)PORT_ArenaAlloc(poolp, SMIME_FORTEZZA_MAX_KEY_SIZE); + encKey->Length = SMIME_FORTEZZA_MAX_KEY_SIZE; + + if (encKey->Data == NULL) + { + CFRelease(kek); + goto loser; + } + + + /* Wrap the bulk key using CMSRC2WRAP or CMS3DESWRAP, depending on the */ + /* bulk encryption algorithm */ + switch (/* XXXX */PK11_AlgtagToMechanism(enccinfo->encalg)) + { + case /* XXXX */CKM_SKIPJACK_CFB8: + err = PK11_WrapSymKey(/* XXXX */CKM_CMS3DES_WRAP, NULL, kek, bulkkey, encKey); + whichKEA = SecCmsKEAUsesSkipjack; + break; + case /* XXXX */CKM_SKIPJACK_CFB8: + err = PK11_WrapSymKey(/* XXXX */CKM_CMSRC2_WRAP, NULL, kek, bulkkey, encKey); + whichKEA = SecCmsKEAUsesSkipjack; + break; + default: + /* XXXX what do we do here? Neither RC2 nor 3DES... */ + err = SECFailure; + /* set error */ + break; + } + + CFRelease(kek); /* we do not need the KEK anymore */ + if (err != SECSuccess) + goto loser; + + PORT_Assert(whichKEA != SecCmsKEAInvalid); + + /* see RFC2630 12.3.1.1 "keyEncryptionAlgorithm must be ..." */ + /* params is the DER encoded key wrap algorithm (with parameters!) (XXX) */ + params = SEC_ASN1EncodeItem(arena, NULL, &keaParams, sec_pkcs7_get_kea_template(whichKEA)); + if (params == NULL) + goto loser; + + /* now set keyEncAlg */ + rv = SECOID_SetAlgorithmID(poolp, keyEncAlg, SEC_OID_CMS_EPHEMERAL_STATIC_DIFFIE_HELLMAN, params); + if (rv != SECSuccess) + goto loser; + + /* XXXXXXX this is not right yet */ +loser: + if (arena) { + PORT_FreeArena(arena, PR_FALSE); + } + if (publickey) { + SECKEY_DestroyPublicKey(publickey); + } + if (ourPrivKey) { + SECKEY_DestroyPrivateKey(ourPrivKey); + } +#endif + return SECFailure; +} + +SecSymmetricKeyRef +SecCmsUtilDecryptSymKeyESDH(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, SECAlgorithmID *keyEncAlg, SECOidTag bulkalgtag, void *pwfn_arg) +{ +#if 0 /* not yet done */ + OSStatus err; + CK_MECHANISM_TYPE bulkType; + SecSymmetricKeyRef tek; + SecPublicKeyRef originatorPubKey; + SecCmsSMIMEKEAParameters keaParams; + + /* XXXX get originator's public key */ + originatorPubKey = PK11_MakeKEAPubKey(keaParams.originatorKEAKey.Data, + keaParams.originatorKEAKey.Length); + if (originatorPubKey == NULL) + goto loser; + + /* Generate the TEK (token exchange key) which we use to unwrap the bulk encryption key. + The Derive function generates a shared secret and combines it with the originatorRA + data to come up with an unique session key */ + tek = PK11_PubDerive(privkey, originatorPubKey, PR_FALSE, + &keaParams.originatorRA, NULL, + CKM_KEA_KEY_DERIVE, CKM_SKIPJACK_WRAP, + CKA_WRAP, 0, pwfn_arg); + SECKEY_DestroyPublicKey(originatorPubKey); /* not needed anymore */ + if (tek == NULL) + goto loser; + + /* Now that we have the TEK, unwrap the bulk key + with which to decrypt the message. */ + /* Skipjack is being used as the bulk encryption algorithm.*/ + /* Unwrap the bulk key. */ + bulkkey = PK11_UnwrapSymKey(tek, CKM_SKIPJACK_WRAP, NULL, + encKey, CKM_SKIPJACK_CBC64, CKA_DECRYPT, 0); + + return bulkkey; + +loser: +#endif + return NULL; +} + +#endif /* Fortezza, DIffie-Hellman */ + +#define CFRELEASE(cf) if(cf != NULL) { CFRelease(cf); } + +/* ====== ECDH (Ephemeral-Static Diffie-Hellman) ==================================== */ + +#pragma mark ---- ECDH support functions ---- + +#ifdef NDEBUG +#define CSSM_PERROR(f, r) +#define dprintf(args...) +#else +#define CSSM_PERROR(f, r) cssmPerror(f, r) +#define dprintf(args...) printf(args) +#endif + +/* Length of KeyAgreeRecipientInfo.ukm we create */ +#define UKM_LENGTH 8 + +/* KEK algorithm info we generate */ +#define ECDH_KEK_ALG_TAG SEC_OID_DES_EDE3_CBC +#define ECDH_KEK_KEY_CSSM_ALGID CSSM_ALGID_3DES_3KEY +#define ECDH_KEK_ENCR_CSSM_ALGID CSSM_ALGID_3DES_3KEY_EDE +#define ECDH_KEK_KEY_LEN_BYTES 24 +#define ECDH_KEK_IV_LEN_BYTES 8 + +#define CMS_DUMP_BUFS 0 +#if CMS_DUMP_BUFS + +static void dumpBuf( + const char *label, + const CSSM_DATA *cd) +{ + unsigned dex; + + printf("%s:\n ", label); + for(dex=0; dexLength; dex++) { + printf("%02X ", cd->Data[dex]); + if(((dex % 16) == 15) && (dex != (cd->Length - 1))) { + printf("\n "); + } + } + putchar('\n'); +} + +#else +#define dumpBuf(l, d) +#endif /* CMS_DUMP_BUFS */ + +/* + * The ECC-CMS-SharedInfo struct, as defined in RFC 3278 8.2, and the + * template for DER encoding and decoding it. + */ +typedef struct { + SECAlgorithmID algId; /* KEK alg, NULL params */ + CSSM_DATA entityUInfo; /* optional, ukm */ + CSSM_DATA suppPubInfo; /* length of KEK in bits as 4-byte integer */ +} ECC_CMS_SharedInfo; + +static const SecAsn1Template ECC_CMS_SharedInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(ECC_CMS_SharedInfo) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(ECC_CMS_SharedInfo,entityUInfo), + kSecAsn1OctetStringTemplate }, + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 2, + offsetof(ECC_CMS_SharedInfo,suppPubInfo), + kSecAsn1OctetStringTemplate }, + { 0 } +}; + +/* + * Given a context specified via a CSSM_CC_HANDLE, add a new + * CSSM_CONTEXT_ATTRIBUTE to the context as specified by AttributeType, + * AttributeLength, and an untyped pointer. + */ +/* specify either 32-bit integer or a pointer as an added attribute value */ +typedef enum { + CAT_Uint32, + CAT_Ptr +} ContextAttrType; + +static CSSM_RETURN cmsAddContextAttribute( + CSSM_CC_HANDLE CCHandle, + uint32 AttributeType, + uint32 AttributeLength, + ContextAttrType attrType, + /* specify exactly one of these */ + const void *AttributePtr, + uint32 attributeInt) +{ + CSSM_CONTEXT_ATTRIBUTE newAttr; + CSSM_RETURN crtn; + + newAttr.AttributeType = AttributeType; + newAttr.AttributeLength = AttributeLength; + if(attrType == CAT_Uint32) { + newAttr.Attribute.Uint32 = attributeInt; + } + else { + /* this is a union of a bunch of different pointers...*/ + newAttr.Attribute.Data = (CSSM_DATA_PTR)AttributePtr; + } + crtn = CSSM_UpdateContextAttributes(CCHandle, 1, &newAttr); + if(crtn) { + CSSM_PERROR("CSSM_UpdateContextAttributes", crtn); + } + return crtn; +} + +static CSSM_RETURN cmsGenRand( + CSSM_CSP_HANDLE cspHand, + CSSM_SIZE len, + uint8 *randOut) +{ + CSSM_CC_HANDLE ccHand = 0; + CSSM_DATA randData = {len, randOut}; + + CSSM_RETURN crtn = CSSM_CSP_CreateRandomGenContext(cspHand, + CSSM_ALGID_APPLE_YARROW, + NULL, /* seed*/ + len, + &ccHand); + if(crtn) { + CSSM_PERROR("CSSM_CSP_CreateRandomGenContext", crtn); + return crtn; + } + crtn = CSSM_GenerateRandom(ccHand, &randData); + CSSM_DeleteContext(ccHand); + if(crtn) { + CSSM_PERROR("CSSM_GenerateRandom", crtn); + } + return crtn; +} + +/* convert uint32 to big-endian 4 bytes */ +static void int32ToBytes( + uint32_t i, + unsigned char *b) +{ + int dex; + for(dex=3; dex>=0; dex--) { + b[dex] = i; + i >>= 8; + } +} + +/* + * NULL wrap a ref key to raw key in default format. + */ +static OSStatus cmsNullWrapKey( + CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *refKey, + CSSM_KEY_PTR rawKey) +{ + CSSM_DATA descData = {0, 0}; + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + CSSM_ACCESS_CREDENTIALS creds; + uint32 keyAttr; + + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + memset(rawKey, 0, sizeof(CSSM_KEY)); + + crtn = CSSM_CSP_CreateSymmetricContext(cspHand, + CSSM_ALGID_NONE, + CSSM_ALGMODE_NONE, + &creds, + NULL, // unwrappingKey + NULL, // initVector + CSSM_PADDING_NONE, + 0, // Params + &ccHand); + if(crtn) { + CSSM_PERROR("CSSM_CSP_CreateSymmetricContext", crtn); + return crtn; + } + + keyAttr = rawKey->KeyHeader.KeyAttr; + keyAttr &= ~(CSSM_KEYATTR_ALWAYS_SENSITIVE | CSSM_KEYATTR_NEVER_EXTRACTABLE | + CSSM_KEYATTR_MODIFIABLE); + keyAttr |= CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + crtn = CSSM_WrapKey(ccHand, + &creds, + refKey, + &descData, + rawKey); + if(crtn != CSSM_OK) { + CSSM_PERROR("CSSM_WrapKey", crtn); + } + CSSM_DeleteContext(ccHand); + return crtn; +} + +/* + * Free memory via specified plugin's app-level allocator + */ +static void cmsFreeCssmMemory( + CSSM_HANDLE hand, + void *p) +{ + CSSM_API_MEMORY_FUNCS memFuncs; + CSSM_RETURN crtn = CSSM_GetAPIMemoryFunctions(hand, &memFuncs); + if(crtn) { + return; + } + memFuncs.free_func(p, memFuncs.AllocRef); +} + +/* + * Given an OID tag, return key size and mode. + * NOTE: ciphers with variable key sizes, like RC2, RC4, and RC5 cannot + * be used here because the message does not contain a key size + * indication. + */ +static OSStatus encrAlgInfo( + SECOidTag oidTag, + uint32 *keySizeBits, /* RETURNED */ + CSSM_ENCRYPT_MODE *mode) /* RETURNED */ +{ + *keySizeBits = 64; /* default */ + *mode = CSSM_ALGMODE_CBCPadIV8; /* default */ + + switch(oidTag) { + case SEC_OID_RC2_CBC: + case SEC_OID_RC4: + case SEC_OID_RC5_CBC_PAD: + dprintf("encrAlgInfo: key size unknowable\n"); + return errSecDataNotAvailable; + + case SEC_OID_DES_EDE3_CBC: + *keySizeBits = 192; + break; + case SEC_OID_DES_EDE: + /* Not sure about this; SecCmsCipherContextStart() treats this + * like SEC_OID_DES_EDE3_CBC... */ + case SEC_OID_DES_ECB: + *mode = CSSM_ALGMODE_ECB; + break; + case SEC_OID_DES_CBC: + *mode = CSSM_ALGMODE_CBC; + break; + case SEC_OID_AES_128_CBC: + *keySizeBits = 128; + break; + case SEC_OID_AES_192_CBC: + *keySizeBits = 192; + break; + case SEC_OID_AES_256_CBC: + *keySizeBits = 256; + break; + case SEC_OID_AES_128_ECB: + *keySizeBits = 128; + *mode = CSSM_ALGMODE_ECB; + break; + case SEC_OID_AES_192_ECB: + *keySizeBits = 192; + *mode = CSSM_ALGMODE_ECB; + break; + case SEC_OID_AES_256_ECB: + *keySizeBits = 256; + *mode = CSSM_ALGMODE_ECB; + break; + case SEC_OID_DES_OFB: + *mode = CSSM_ALGMODE_OFB; + break; + case SEC_OID_DES_CFB: + *mode = CSSM_ALGMODE_CFB; + break; + default: + dprintf("encrAlgInfo: unknown alg tag (%d)\n", (int)oidTag); + return errSecDataNotAvailable; + } + return noErr; +} + +#pragma mark ---- ECDH CEK key wrap ---- + +/* + * Encrypt bulk encryption key (a.k.a. content encryption key, CEK) using ECDH + */ +OSStatus +SecCmsUtilEncryptSymKeyECDH( + PLArenaPool *poolp, + SecCertificateRef cert, /* recipient's cert */ + SecSymmetricKeyRef key, /* bulk key */ + /* remaining fields RETURNED */ + CSSM_DATA_PTR encKey, /* encrypted key --> recipientEncryptedKeys[0].EncryptedKey */ + CSSM_DATA_PTR ukm, /* random UKM --> KeyAgreeRecipientInfo.ukm */ + SECAlgorithmID *keyEncAlg, /* alg := dhSinglePass-stdDH-sha1kdf-scheme + * params := another encoded AlgId, with the KEK alg and IV */ + CSSM_DATA_PTR pubKey) /* our pub key as ECPoint --> + * KeyAgreeRecipientInfo.originator.OriginatorPublicKey */ +{ + OSStatus rv = noErr; + CSSM_KEY ourPrivKeyCssm; + CSSM_KEY ourPubKeyCssm; + SecKeyRef theirPubKeyRef = NULL; + CSSM_KEY_PTR theirPubKeyCssm = NULL; + const CSSM_KEY *cekCssmRef = NULL; + uint32 ecdhKeySizeBits; + CSSM_CSP_HANDLE rawCspHand = SecCspHandleForAlgorithm(CSSM_ALGID_ECDH); + CSSM_CC_HANDLE ccHand = 0; + CSSM_RETURN crtn; + CSSM_DATA keyLabel = {8, (uint8 *)"tempKey"}; + SECAlgorithmID kekAlgId; + uint8 iv[ECDH_KEK_IV_LEN_BYTES]; + CSSM_DATA ivData = {ECDH_KEK_IV_LEN_BYTES, iv}; + SECOidData *kekOid; + ECC_CMS_SharedInfo sharedInfo; + CSSM_DATA sharedInfoEnc = {0, NULL}; + uint8 nullData[2] = {SEC_ASN1_NULL, 0}; + uint8 keyLenAsBytes[4]; + CSSM_KEY kekDerive; + CSSM_DATA certData; + CSSM_CL_HANDLE clHand; + CSSM_ACCESS_CREDENTIALS creds; + CSSM_DATA paramData = {0, NULL}; + CSSM_KEY cekCssm; + CSSM_CSP_HANDLE refCspHand; + CSSM_SIZE bytesEncrypted; + CSSM_DATA remData = {0, NULL}; + CSSM_DATA ctext = {0, NULL}; + CSSM_X509_SUBJECT_PUBLIC_KEY_INFO subjPubKey; + + if(rawCspHand == 0) { + return internalComponentErr; + } + + memset(&ourPrivKeyCssm, 0, sizeof(CSSM_KEY)); + memset(&ourPubKeyCssm, 0, sizeof(CSSM_KEY)); + memset(&cekCssm, 0, sizeof(CSSM_KEY)); + memset(&kekDerive, 0, sizeof(kekDerive)); + + encKey->Data = NULL; + encKey->Length = 0; + + /* + * Create our ECDH key pair matching the recipient's key. + * Get the public key in "read-only" OCTET_STRING format, which + * is the ECPoint we put in + * KeyAgreeRecipientInfo.originator.OriginatorPublicKey. + */ + rv = SecCertificateGetData(cert, &certData); + if(rv) { + CSSM_PERROR("SecCertificateGetData", rv); + return rv; + } + rv = SecCertificateGetCLHandle(cert, &clHand); + if(rv) { + CSSM_PERROR("SecCertificateGetCLHandle", rv); + return rv; + } + rv = CSSM_CL_CertGetKeyInfo(clHand, &certData, &theirPubKeyCssm); + if(rv) { + CSSM_PERROR("CSSM_CL_CertGetKeyInfo", rv); + return rv; + } + + /* + * Verify the EC curve of the recipient's public key. It's in the + * public key's AlgId.parameters as an OID. The key we were + * given is in CSSM_X509_SUBJECT_PUBLIC_KEY_INFO form. + */ + memset(&subjPubKey, 0, sizeof(subjPubKey)); + if(SEC_ASN1DecodeItem(poolp, &subjPubKey, kSecAsn1SubjectPublicKeyInfoTemplate, + &theirPubKeyCssm->KeyData)) { + dprintf("SecCmsUtilEncryptSymKeyECDH: error decoding SubjPubKey\n"); + /* oh well, keep going */ + } + else { + if(subjPubKey.algorithm.parameters.Data != NULL) { + CSSM_DATA curveOid; + if(SEC_ASN1DecodeItem(poolp, &curveOid, kSecAsn1ObjectIDTemplate, + &subjPubKey.algorithm.parameters)) { + dprintf("SecCmsUtilEncryptSymKeyECDH: error decoding curveOid\n"); + /* oh well, keep going */ + } + else { + /* We have the curve OID. Any other errors are fatal. */ + SECOidTag oidTag = SECOID_FindOIDTag(&curveOid); + switch(oidTag) { + case SEC_OID_SECP_256_R1: + case SEC_OID_SECP_384_R1: + case SEC_OID_SECP_521_R1: + break; + default: + dprintf("SecCmsUtilEncryptSymKeyECDH: unsupported curveOid\n"); + rv = CSSMERR_CSP_INVALID_KEY; + goto loser; + } + } + } + } + + ecdhKeySizeBits = theirPubKeyCssm->KeyHeader.LogicalKeySizeInBits; + crtn = CSSM_CSP_CreateKeyGenContext(rawCspHand, + CSSM_ALGID_ECDSA, + ecdhKeySizeBits, + NULL, // Seed + NULL, // Salt + NULL, // StartDate + NULL, // EndDate + NULL, // Params + &ccHand); + if(crtn) { + CSSM_PERROR("CSSM_CSP_CreateKeyGenContext", crtn); + rv = crtn; + goto loser; + } + crtn = cmsAddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT, + sizeof(uint32), + CAT_Uint32, + NULL, + CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING); + if(crtn) { + CSSM_PERROR("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn); + rv = crtn; + goto loser; + } + + crtn = CSSM_GenerateKeyPair(ccHand, + CSSM_KEYUSE_DERIVE, + CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, + &keyLabel, + &ourPubKeyCssm, + CSSM_KEYUSE_DERIVE, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE, + &keyLabel, + NULL, // CredAndAclEntry + &ourPrivKeyCssm); + CSSM_DeleteContext(ccHand); + ccHand = 0; + if(crtn) { + CSSM_PERROR("CSSM_GenerateKeyPair", crtn); + rv = crtn; + goto loser; + } + pubKey->Length = ourPubKeyCssm.KeyData.Length; + pubKey->Data = (uint8 *)PORT_ArenaAlloc(poolp, pubKey->Length); + memmove(pubKey->Data, ourPubKeyCssm.KeyData.Data, pubKey->Length); + dumpBuf("sender's public key", pubKey); + + /* + * Cook up random UKM + */ + ukm->Data = (uint8 *)PORT_ArenaAlloc(poolp, UKM_LENGTH); + ukm->Length = UKM_LENGTH; + crtn = cmsGenRand(rawCspHand, UKM_LENGTH, ukm->Data); + if(crtn) { + goto loser; + } + dumpBuf("sender UKM", ukm); + + /* + * OK, we have to set up a weird SECAlgorithmID. + * algorithm = dhSinglePass-stdDH-sha1kdf-scheme + * params = an encoded SECAlgorithmID representing the KEK algorithm, with + * algorithm = whatever we pick + * parameters = IV as octet string (though I haven't seen that specified + * anywhere; it's how the CEK IV is encoded) + * + * First, the 8-byte random IV, encoded as octet string + */ + crtn = cmsGenRand(rawCspHand, ECDH_KEK_IV_LEN_BYTES, iv); + if(crtn) { + goto loser; + } + dumpBuf("sender IV", &ivData); + + memset(&kekAlgId, 0, sizeof(kekAlgId)); + if (!SEC_ASN1EncodeItem(poolp, &kekAlgId.parameters, + &ivData, kSecAsn1OctetStringTemplate)) { + rv = internalComponentErr; + goto loser; + } + + /* Drop in the KEK OID and encode the whole thing */ + kekOid = SECOID_FindOIDByTag(ECDH_KEK_ALG_TAG); + if(kekOid == NULL) { + dprintf("SecCmsUtilEncryptSymKeyECDH: OID screwup\n"); + rv = internalComponentErr; + goto loser; + } + kekAlgId.algorithm = kekOid->oid; + memset(keyEncAlg, 0, sizeof(*keyEncAlg)); + if (!SEC_ASN1EncodeItem(poolp, &keyEncAlg->parameters, + &kekAlgId, SECOID_AlgorithmIDTemplate)) { + rv = internalComponentErr; + goto loser; + } + kekOid = SECOID_FindOIDByTag(SEC_OID_DH_SINGLE_STD_SHA1KDF); + if(kekOid == NULL) { + dprintf("SecCmsUtilEncryptSymKeyECDH: OID screwup\n"); + rv = internalComponentErr; + goto loser; + } + keyEncAlg->algorithm = kekOid->oid; + + /* + * Now in order to derive the KEK proper, we have to create a + * ECC-CMS-SharedInfo, which does not appear in the message, and DER + * encode that struct, the result of which is used as the + * SharedInfo value in the KEK key derive. + */ + memset(&sharedInfo, 0, sizeof(sharedInfo)); + kekOid = SECOID_FindOIDByTag(ECDH_KEK_ALG_TAG); + sharedInfo.algId.algorithm = kekOid->oid; + sharedInfo.algId.parameters.Data = nullData; + sharedInfo.algId.parameters.Length = 2; + sharedInfo.entityUInfo = *ukm; + int32ToBytes(ECDH_KEK_KEY_LEN_BYTES << 3, keyLenAsBytes); + sharedInfo.suppPubInfo.Length = 4; + sharedInfo.suppPubInfo.Data = keyLenAsBytes; + if (!SEC_ASN1EncodeItem(poolp, &sharedInfoEnc, + &sharedInfo, ECC_CMS_SharedInfoTemplate)) { + rv = internalComponentErr; + goto loser; + } + dumpBuf("sender encoded SharedInfo", &sharedInfoEnc); + + /* + * Since we're using the raw CSP here, we can provide the "other" public + * key as an actual CSSM_KEY. When unwrapping, we won't be able to do that + * since we'll be using our private key obtained from a SecIdentityRef. + */ + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + crtn = CSSM_CSP_CreateDeriveKeyContext(rawCspHand, + CSSM_ALGID_ECDH_X963_KDF, + ECDH_KEK_KEY_CSSM_ALGID, // algorithm of the KEK + ECDH_KEK_KEY_LEN_BYTES * 8, + &creds, + &ourPrivKeyCssm, // BaseKey + 0, // IterationCount + &sharedInfoEnc, // Salt + 0, // Seed + &ccHand); + if(crtn) { + CSSM_PERROR("CSSM_CSP_CreateDeriveKeyContext", crtn); + rv = crtn; + goto loser; + } + + /* add recipient's pub key as a context attr */ + crtn = cmsAddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PUBLIC_KEY, + sizeof(CSSM_KEY), + CAT_Ptr, + (void *)theirPubKeyCssm, + 0); + if(crtn) { + rv = crtn; + goto loser; + } + + /* Derive the KEK */ + crtn = CSSM_DeriveKey(ccHand, + ¶mData, + CSSM_KEYUSE_ANY, + CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, + &keyLabel, + NULL, // cread/acl + &kekDerive); + if(crtn) { + CSSM_PERROR("CSSM_DeriveKey", crtn); + rv = crtn; + goto loser; + } + CSSM_DeleteContext(ccHand); + ccHand = 0; + + /* + * Obtain the raw CEK bits. + */ + rv = SecKeyGetCSSMKey(key, &cekCssmRef); + if(rv) { + CSSM_PERROR("SecKeyGetCSSMKey", rv); + goto loser; + } + rv = SecKeyGetCSPHandle(key, &refCspHand); + if(rv) { + CSSM_PERROR("SecKeyGetCSPHandle", rv); + goto loser; + } + rv = cmsNullWrapKey(refCspHand, cekCssmRef, &cekCssm); + if(rv) { + goto loser; + } + + /* + * Finally, encrypt the raw CEK bits with the KEK we just derived + */ + crtn = CSSM_CSP_CreateSymmetricContext(rawCspHand, + ECDH_KEK_ENCR_CSSM_ALGID, + CSSM_ALGMODE_CBCPadIV8, + NULL, // access cred + &kekDerive, + &ivData, // InitVector + CSSM_PADDING_PKCS7, + NULL, // Params + &ccHand); + if(rv) { + CSSM_PERROR("CSSM_CSP_CreateSymmetricContext", rv); + goto loser; + } + rv = CSSM_EncryptData(ccHand, + &cekCssm.KeyData, + 1, + &ctext, + 1, + &bytesEncrypted, + &remData); + if(rv) { + CSSM_PERROR("CSSM_EncryptData", rv); + goto loser; + } + encKey->Data = PORT_ArenaAlloc(poolp, bytesEncrypted); + encKey->Length = bytesEncrypted; + memmove(encKey->Data, ctext.Data, ctext.Length); + if(bytesEncrypted != ctext.Length) { + memmove(encKey->Data + ctext.Length, remData.Data, remData.Length); + } + dumpBuf("sender encKey", encKey); + +loser: + if(ccHand) { + CSSM_DeleteContext(ccHand); + } + CFRELEASE(theirPubKeyRef); + if(ourPubKeyCssm.KeyData.Data) { + CSSM_FreeKey(rawCspHand, NULL, &ourPubKeyCssm, CSSM_FALSE); + } + if(ourPrivKeyCssm.KeyData.Data) { + CSSM_FreeKey(rawCspHand, NULL, &ourPrivKeyCssm, CSSM_FALSE); + } + if(ctext.Data) { + cmsFreeCssmMemory(rawCspHand, ctext.Data); + } + if(remData.Data) { + cmsFreeCssmMemory(rawCspHand, remData.Data); + } + if(cekCssm.KeyData.Data) { + CSSM_FreeKey(refCspHand, NULL, &cekCssm, CSSM_FALSE); + } + if(kekDerive.KeyData.Data) { + CSSM_FreeKey(rawCspHand, NULL, &kekDerive, CSSM_FALSE); + } + if(theirPubKeyCssm) { + /* Allocated by CL */ + cmsFreeCssmMemory(clHand, theirPubKeyCssm->KeyData.Data); + cmsFreeCssmMemory(clHand, theirPubKeyCssm); + } + return rv; +} + +#pragma mark ---- ECDH CEK key unwrap ---- + +SecSymmetricKeyRef +SecCmsUtilDecryptSymKeyECDH( + SecPrivateKeyRef privkey, /* our private key */ + CSSM_DATA_PTR encKey, /* encrypted CEK */ + CSSM_DATA_PTR ukm, /* random UKM from KeyAgreeRecipientInfo.ukm */ + SECAlgorithmID *keyEncAlg, /* alg := dhSinglePass-stdDH-sha1kdf-scheme + * params := another encoded AlgId, with the KEK alg and IV */ + SECOidTag bulkalgtag, /* algorithm of returned key */ + CSSM_DATA_PTR pubKey) /* sender's pub key as ECPoint from + * KeyAgreeRecipientInfo.originator.OriginatorPublicKey */ + +{ + SecSymmetricKeyRef outKey = NULL; + OSStatus rv = noErr; + const CSSM_KEY *ourPrivKeyCssm; + PLArenaPool *pool = NULL; + SECAlgorithmID keyAlgParam; + SECOidData *kekOid = NULL; + CSSM_DATA iv = {0, NULL}; + ECC_CMS_SharedInfo sharedInfo; + CSSM_DATA sharedInfoEnc = {0, NULL}; + uint8 nullData[2] = {SEC_ASN1_NULL, 0}; + uint8 keyLenAsBytes[4]; + CSSM_ENCRYPT_MODE kekMode; + uint32 kekSizeBits; + CSSM_KEY kekDerive; + CSSM_RETURN crtn; + CSSM_ACCESS_CREDENTIALS creds; + CSSM_CSP_HANDLE refCspHand; + CSSM_CC_HANDLE ccHand = 0; + CSSM_DATA keyLabel = {8, (uint8 *)"tempKey"}; + const CSSM_ACCESS_CREDENTIALS *accessCred; + CSSM_KEY wrappedKey; + CSSM_KEY unwrappedKey; + CSSM_ALGORITHMS bulkAlg; + CSSM_DATA descriptiveData = {0, NULL}; + + dumpBuf("receiver encKey", encKey); + + memset(&kekDerive, 0, sizeof(kekDerive)); + + /* our private key in CSSM form */ + rv = SecKeyGetCSSMKey(privkey, &ourPrivKeyCssm); + if(rv) { + CSSM_PERROR("SecKeyGetCSSMKey", rv); + goto loser; + } + + /* + * Decode keyEncAlg.params to get KEK algorithm and IV + */ + pool = PORT_NewArena(1024); + if(pool == NULL) { + goto loser; + } + memset(&keyAlgParam, 0, sizeof(keyAlgParam)); + if(SEC_ASN1DecodeItem(pool, &keyAlgParam, SECOID_AlgorithmIDTemplate, + &keyEncAlg->parameters)) { + dprintf("SecCmsUtilDecryptSymKeyECDH: error decoding keyAlgParams\n"); + goto loser; + } + kekOid = SECOID_FindOID(&keyAlgParam.algorithm); + if(kekOid == NULL) { + dprintf("SecCmsUtilDecryptSymKeyECDH: unknown KEK enc OID\n"); + goto loser; + } + rv = encrAlgInfo(kekOid->offset, &kekSizeBits, &kekMode); + if(rv) { + goto loser; + } + /* IV is OCTET STRING in the alg params */ + if(SEC_ASN1DecodeItem(pool, &iv, kSecAsn1OctetStringTemplate, + &keyAlgParam.parameters)) { + /* + * Not sure here - is it legal to have no IV? I haven't seen this + * addressed in any spec. Maybe we should condition the behavior + * here on the KEK algorithm. + */ + dprintf("SecCmsUtilDecryptSymKeyECDH: no KEK IV\n"); + goto loser; + } + + /* + * Now in order to derive the KEK proper, we have to create a + * ECC-CMS-SharedInfo, which does not appear in the message, and DER + * encode that struct, the result of which is used as the + * SharedInfo value in the KEK key derive. + */ + memset(&sharedInfo, 0, sizeof(sharedInfo)); + sharedInfo.algId.algorithm = kekOid->oid; + sharedInfo.algId.parameters.Data = nullData; + sharedInfo.algId.parameters.Length = 2; + sharedInfo.entityUInfo = *ukm; + int32ToBytes(kekSizeBits, keyLenAsBytes); + sharedInfo.suppPubInfo.Length = 4; + sharedInfo.suppPubInfo.Data = keyLenAsBytes; + if (!SEC_ASN1EncodeItem(pool, &sharedInfoEnc, + &sharedInfo, ECC_CMS_SharedInfoTemplate)) { + rv = internalComponentErr; + goto loser; + } + dumpBuf("receiver encoded SharedInfo", &sharedInfoEnc); + dumpBuf("receiver IV", &iv); + dumpBuf("receiver UKM", ukm); + dumpBuf("sender's public key", pubKey); + + /* + * Using the Sec-layer CSPDL, "other's" public key specified as ECPOint param. Which + * is fortunate because that's what we have... + */ + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + rv = SecKeyGetCSPHandle(privkey, &refCspHand); + if(rv) { + CSSM_PERROR("SecKeyGetCSPHandle", rv); + goto loser; + } + rv = SecKeyGetCredentials(privkey, + CSSM_ACL_AUTHORIZATION_DERIVE, + kSecCredentialTypeDefault, + &accessCred); + if (rv) { + CSSM_PERROR("SecKeyGetCredentials", rv); + goto loser; + } + crtn = CSSM_CSP_CreateDeriveKeyContext(refCspHand, + CSSM_ALGID_ECDH_X963_KDF, + kekOid->cssmAlgorithm, // algorithm of the KEK + kekSizeBits, + &creds, + ourPrivKeyCssm, // BaseKey + 0, // IterationCount + &sharedInfoEnc, // Salt + 0, // Seed + &ccHand); + if(crtn) { + CSSM_PERROR("CSSM_CSP_CreateDeriveKeyContext", crtn); + goto loser; + } + crtn = CSSM_DeriveKey(ccHand, + pubKey, // param + CSSM_KEYUSE_ANY, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE, + &keyLabel, + NULL, // cred/acl + &kekDerive); + CSSM_DeleteContext(ccHand); + ccHand = 0; + if(crtn) { + CSSM_PERROR("CSSM_DeriveKey", crtn); + goto loser; + } + + /* + * Decrypt the encrypted key bits with the KEK key. + */ + crtn = CSSM_CSP_CreateSymmetricContext(refCspHand, + kekOid->cssmAlgorithm, + kekMode, + NULL, // access cred + &kekDerive, + &iv, // InitVector + /* FIXME is this variable too? */ + CSSM_PADDING_PKCS7, + NULL, // Params + &ccHand); + if(rv) { + CSSM_PERROR("CSSM_CSP_CreateSymmetricContext", rv); + goto loser; + } + + memset(&wrappedKey, 0, sizeof(CSSM_KEY)); + memset(&unwrappedKey, 0, sizeof(CSSM_KEY)); + + bulkAlg = SECOID_FindyCssmAlgorithmByTag(bulkalgtag); + if(bulkAlg == CSSM_ALGID_NONE) { + dprintf("SecCmsUtilDecryptSymKeyECDH: unknown bulk alg\n"); + goto loser; + } + + wrappedKey.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; + wrappedKey.KeyHeader.BlobType = CSSM_KEYBLOB_WRAPPED; + wrappedKey.KeyHeader.Format = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7; + wrappedKey.KeyHeader.AlgorithmId = bulkAlg; + wrappedKey.KeyHeader.KeyClass = CSSM_KEYCLASS_SESSION_KEY; + wrappedKey.KeyHeader.WrapAlgorithmId = kekOid->cssmAlgorithm; + wrappedKey.KeyHeader.WrapMode = CSSM_ALGMODE_NONE; + wrappedKey.KeyData = *encKey; + + crtn = CSSM_UnwrapKey(ccHand, + NULL, /* publicKey */ + &wrappedKey, + CSSM_KEYUSE_DECRYPT, + CSSM_KEYATTR_EXTRACTABLE, + &keyLabel, + NULL, /* rcc */ + &unwrappedKey, + &descriptiveData); + CSSM_DeleteContext(ccHand); + ccHand = 0; + if(crtn) { + CSSM_PERROR("CSSM_UnwrapKey", crtn); + goto loser; + } + rv = SecKeyCreateWithCSSMKey(&unwrappedKey, &outKey); + if (rv) { + CSSM_PERROR("SecKeyCreateWithCSSMKey", rv); + } + +loser: + if(pool != NULL) { + PORT_FreeArena(pool, PR_FALSE); + } + if(kekDerive.KeyData.Data) { + CSSM_FreeKey(refCspHand, NULL, &kekDerive, CSSM_FALSE); + } + if(outKey == NULL) { + PORT_SetError(SEC_ERROR_NO_KEY); + } + return outKey; +} + + + diff --git a/Security/libsecurity_smime/lib/cmsrecinfo.c b/Security/libsecurity_smime/lib/cmsrecinfo.c new file mode 100644 index 00000000..dbecfbef --- /dev/null +++ b/Security/libsecurity_smime/lib/cmsrecinfo.c @@ -0,0 +1,704 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * CMS recipientInfo methods. + */ + +#include "cmslocal.h" + +#include "cert.h" +#include "secitem.h" +#include "secoid.h" + +#include +#include +#include +#include +#include + +static Boolean +nss_cmsrecipientinfo_usessubjectkeyid(SecCmsRecipientInfoRef ri) +{ + if (ri->recipientInfoType == SecCmsRecipientInfoIDKeyTrans) { + SecCmsRecipientIdentifier *rid; + rid = &ri->ri.keyTransRecipientInfo.recipientIdentifier; + if (rid->identifierType == SecCmsRecipientIDSubjectKeyID) { + return PR_TRUE; + } + } + return PR_FALSE; +} + + +static SecCmsRecipientInfoRef +nss_cmsrecipientinfo_create(SecCmsMessageRef cmsg, SecCmsRecipientIDSelector type, + SecCertificateRef cert, SecPublicKeyRef pubKey, + CSSM_DATA_PTR subjKeyID) +{ + SecCmsRecipientInfoRef ri; + void *mark; + SECOidTag certalgtag; + OSStatus rv = SECSuccess; + SecCmsRecipientEncryptedKey *rek; + SecCmsOriginatorIdentifierOrKey *oiok; + unsigned long version; + CSSM_DATA_PTR dummy; + PLArenaPool *poolp; + const SECAlgorithmID *algid; + SecCmsRecipientIdentifier *rid; + + poolp = cmsg->poolp; + + mark = PORT_ArenaMark(poolp); + + ri = (SecCmsRecipientInfoRef)PORT_ArenaZAlloc(poolp, sizeof(SecCmsRecipientInfo)); + if (ri == NULL) + goto loser; + + ri->cmsg = cmsg; + if (type == SecCmsRecipientIDIssuerSN) + { + ri->cert = CERT_DupCertificate(cert); + if (ri->cert == NULL) + goto loser; + rv = SecCertificateGetAlgorithmID(cert,&algid); + } else { + PORT_Assert(pubKey); + rv = SecKeyGetAlgorithmID(pubKey,&algid); + } + + certalgtag = SECOID_GetAlgorithmTag(algid); + + rid = &ri->ri.keyTransRecipientInfo.recipientIdentifier; + switch (certalgtag) { + case SEC_OID_PKCS1_RSA_ENCRYPTION: + ri->recipientInfoType = SecCmsRecipientInfoIDKeyTrans; + rid->identifierType = type; + if (type == SecCmsRecipientIDIssuerSN) { + rid->id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert); + if (rid->id.issuerAndSN == NULL) { + break; + } + } else if (type == SecCmsRecipientIDSubjectKeyID){ + SecCmsKeyTransRecipientInfoEx *riExtra; + + rid->id.subjectKeyID = PORT_ArenaNew(poolp, CSSM_DATA); + if (rid->id.subjectKeyID == NULL) { + rv = SECFailure; + PORT_SetError(SEC_ERROR_NO_MEMORY); + break; + } + SECITEM_CopyItem(poolp, rid->id.subjectKeyID, subjKeyID); + if (rid->id.subjectKeyID->Data == NULL) { + rv = SECFailure; + PORT_SetError(SEC_ERROR_NO_MEMORY); + break; + } + riExtra = &ri->ri.keyTransRecipientInfoEx; + riExtra->version = 0; + riExtra->pubKey = SECKEY_CopyPublicKey(pubKey); + if (riExtra->pubKey == NULL) { + rv = SECFailure; + PORT_SetError(SEC_ERROR_NO_MEMORY); + break; + } + } else { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + rv = SECFailure; + } + break; + case SEC_OID_MISSI_KEA_DSS_OLD: + case SEC_OID_MISSI_KEA_DSS: + case SEC_OID_MISSI_KEA: + PORT_Assert(type != SecCmsRecipientIDSubjectKeyID); + if (type == SecCmsRecipientIDSubjectKeyID) { + rv = SECFailure; + break; + } + /* backward compatibility - this is not really a keytrans operation */ + ri->recipientInfoType = SecCmsRecipientInfoIDKeyTrans; + /* hardcoded issuerSN choice for now */ + ri->ri.keyTransRecipientInfo.recipientIdentifier.identifierType = SecCmsRecipientIDIssuerSN; + ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert); + if (ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN == NULL) { + rv = SECFailure; + break; + } + break; + case SEC_OID_X942_DIFFIE_HELMAN_KEY: /* dh-public-number */ + PORT_Assert(type != SecCmsRecipientIDSubjectKeyID); + if (type == SecCmsRecipientIDSubjectKeyID) { + rv = SECFailure; + break; + } + /* a key agreement op */ + ri->recipientInfoType = SecCmsRecipientInfoIDKeyAgree; + + if (ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN == NULL) { + rv = SECFailure; + break; + } + /* we do not support the case where multiple recipients + * share the same KeyAgreeRecipientInfo and have multiple RecipientEncryptedKeys + * in this case, we would need to walk all the recipientInfos, take the + * ones that do KeyAgreement algorithms and join them, algorithm by algorithm + * Then, we'd generate ONE ukm and OriginatorIdentifierOrKey */ + + /* only epheremal-static Diffie-Hellman is supported for now + * this is the only form of key agreement that provides potential anonymity + * of the sender, plus we do not have to include certs in the message */ + + /* force single recipientEncryptedKey for now */ + if ((rek = SecCmsRecipientEncryptedKeyCreate(poolp)) == NULL) { + rv = SECFailure; + break; + } + + /* hardcoded IssuerSN choice for now */ + rek->recipientIdentifier.identifierType = SecCmsKeyAgreeRecipientIDIssuerSN; + if ((rek->recipientIdentifier.id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert)) == NULL) { + rv = SECFailure; + break; + } + + oiok = &(ri->ri.keyAgreeRecipientInfo.originatorIdentifierOrKey); + + /* see RFC2630 12.3.1.1 */ + oiok->identifierType = SecCmsOriginatorIDOrKeyOriginatorPublicKey; + + rv = SecCmsArrayAdd(poolp, (void ***)&ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys, + (void *)rek); + + break; + + case SEC_OID_EC_PUBLIC_KEY: + /* ephemeral-static ECDH - issuerAndSN, OriginatorPublicKey only */ + PORT_Assert(type != SecCmsRecipientIDSubjectKeyID); + if (type == SecCmsRecipientIDSubjectKeyID) { + rv = SECFailure; + break; + } + /* a key agreement op */ + ri->recipientInfoType = SecCmsRecipientInfoIDKeyAgree; + ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert); + if (ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN == NULL) { + rv = SECFailure; + break; + } + /* we do not support the case where multiple recipients + * share the same KeyAgreeRecipientInfo and have multiple RecipientEncryptedKeys + * in this case, we would need to walk all the recipientInfos, take the + * ones that do KeyAgreement algorithms and join them, algorithm by algorithm + * Then, we'd generate ONE ukm and OriginatorIdentifierOrKey */ + + /* force single recipientEncryptedKey for now */ + if ((rek = SecCmsRecipientEncryptedKeyCreate(poolp)) == NULL) { + rv = SECFailure; + break; + } + + /* hardcoded IssuerSN choice for now */ + rek->recipientIdentifier.identifierType = SecCmsKeyAgreeRecipientIDIssuerSN; + if ((rek->recipientIdentifier.id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert)) == NULL) { + rv = SECFailure; + break; + } + + oiok = &(ri->ri.keyAgreeRecipientInfo.originatorIdentifierOrKey); + + /* see RFC 3278 3.1.1 */ + oiok->identifierType = SecCmsOriginatorIDOrKeyOriginatorPublicKey; + + rv = SecCmsArrayAdd(poolp, (void ***)&ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys, + (void *)rek); + + break; + + default: + /* other algorithms not supported yet */ + /* NOTE that we do not support any KEK algorithm */ + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + rv = SECFailure; + break; + } + + if (rv == SECFailure) + goto loser; + + /* set version */ + switch (ri->recipientInfoType) { + case SecCmsRecipientInfoIDKeyTrans: + if (ri->ri.keyTransRecipientInfo.recipientIdentifier.identifierType == SecCmsRecipientIDIssuerSN) + version = SEC_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_ISSUERSN; + else + version = SEC_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_SUBJKEY; + dummy = SEC_ASN1EncodeInteger(poolp, &(ri->ri.keyTransRecipientInfo.version), version); + if (dummy == NULL) + goto loser; + break; + case SecCmsRecipientInfoIDKeyAgree: + dummy = SEC_ASN1EncodeInteger(poolp, &(ri->ri.keyAgreeRecipientInfo.version), + SEC_CMS_KEYAGREE_RECIPIENT_INFO_VERSION); + if (dummy == NULL) + goto loser; + break; + case SecCmsRecipientInfoIDKEK: + /* NOTE: this cannot happen as long as we do not support any KEK algorithm */ + dummy = SEC_ASN1EncodeInteger(poolp, &(ri->ri.kekRecipientInfo.version), + SEC_CMS_KEK_RECIPIENT_INFO_VERSION); + if (dummy == NULL) + goto loser; + break; + + } + + PORT_ArenaUnmark (poolp, mark); +#if 0 + if (freeSpki) + SECKEY_DestroySubjectPublicKeyInfo(freeSpki); +#endif + return ri; + +loser: +#if 0 + if (freeSpki) + SECKEY_DestroySubjectPublicKeyInfo(freeSpki); +#endif + PORT_ArenaRelease (poolp, mark); + return NULL; +} + +/* + * SecCmsRecipientInfoCreate - create a recipientinfo + * + * we currently do not create KeyAgreement recipientinfos with multiple + * recipientEncryptedKeys the certificate is supposed to have been + * verified by the caller + */ +SecCmsRecipientInfoRef +SecCmsRecipientInfoCreate(SecCmsMessageRef cmsg, SecCertificateRef cert) +{ + return nss_cmsrecipientinfo_create(cmsg, SecCmsRecipientIDIssuerSN, cert, + NULL, NULL); +} + +SecCmsRecipientInfoRef +SecCmsRecipientInfoCreateWithSubjKeyID(SecCmsMessageRef cmsg, + CSSM_DATA_PTR subjKeyID, + SecPublicKeyRef pubKey) +{ + return nss_cmsrecipientinfo_create(cmsg, SecCmsRecipientIDSubjectKeyID, + NULL, pubKey, subjKeyID); +} + +SecCmsRecipientInfoRef +SecCmsRecipientInfoCreateWithSubjKeyIDFromCert(SecCmsMessageRef cmsg, + SecCertificateRef cert) +{ + SecPublicKeyRef pubKey = NULL; + CSSM_DATA subjKeyID = {0, NULL}; + SecCmsRecipientInfoRef retVal = NULL; + + if (!cmsg || !cert) { + return NULL; + } + pubKey = CERT_ExtractPublicKey(cert); + if (!pubKey) { + goto done; + } + if (CERT_FindSubjectKeyIDExtension(cert, &subjKeyID) != SECSuccess || + subjKeyID.Data == NULL) { + goto done; + } + retVal = SecCmsRecipientInfoCreateWithSubjKeyID(cmsg, &subjKeyID, pubKey); +done: + if (pubKey) + SECKEY_DestroyPublicKey(pubKey); + + if (subjKeyID.Data) + SECITEM_FreeItem(&subjKeyID, PR_FALSE); + + return retVal; +} + +void +SecCmsRecipientInfoDestroy(SecCmsRecipientInfoRef ri) +{ + /* version was allocated on the pool, so no need to destroy it */ + /* issuerAndSN was allocated on the pool, so no need to destroy it */ + if (ri->cert != NULL) + CERT_DestroyCertificate(ri->cert); + + if (nss_cmsrecipientinfo_usessubjectkeyid(ri)) { + SecCmsKeyTransRecipientInfoEx *extra; + extra = &ri->ri.keyTransRecipientInfoEx; + if (extra->pubKey) + SECKEY_DestroyPublicKey(extra->pubKey); + } + + /* recipientInfo structure itself was allocated on the pool, so no need to destroy it */ + /* we're done. */ +} + +int +SecCmsRecipientInfoGetVersion(SecCmsRecipientInfoRef ri) +{ + unsigned long version; + CSSM_DATA_PTR versionitem = NULL; + + switch (ri->recipientInfoType) { + case SecCmsRecipientInfoIDKeyTrans: + /* ignore subIndex */ + versionitem = &(ri->ri.keyTransRecipientInfo.version); + break; + case SecCmsRecipientInfoIDKEK: + /* ignore subIndex */ + versionitem = &(ri->ri.kekRecipientInfo.version); + break; + case SecCmsRecipientInfoIDKeyAgree: + versionitem = &(ri->ri.keyAgreeRecipientInfo.version); + break; + } + + PORT_Assert(versionitem); + if (versionitem == NULL) + return 0; + + /* always take apart the CSSM_DATA */ + if (SEC_ASN1DecodeInteger(versionitem, &version) != SECSuccess) + return 0; + else + return (int)version; +} + +CSSM_DATA_PTR +SecCmsRecipientInfoGetEncryptedKey(SecCmsRecipientInfoRef ri, int subIndex) +{ + CSSM_DATA_PTR enckey = NULL; + + switch (ri->recipientInfoType) { + case SecCmsRecipientInfoIDKeyTrans: + /* ignore subIndex */ + enckey = &(ri->ri.keyTransRecipientInfo.encKey); + break; + case SecCmsRecipientInfoIDKEK: + /* ignore subIndex */ + enckey = &(ri->ri.kekRecipientInfo.encKey); + break; + case SecCmsRecipientInfoIDKeyAgree: + enckey = &(ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[subIndex]->encKey); + break; + } + return enckey; +} + + +SECOidTag +SecCmsRecipientInfoGetKeyEncryptionAlgorithmTag(SecCmsRecipientInfoRef ri) +{ + SECOidTag encalgtag = SEC_OID_UNKNOWN; /* an invalid encryption alg */ + + switch (ri->recipientInfoType) { + case SecCmsRecipientInfoIDKeyTrans: + encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.keyTransRecipientInfo.keyEncAlg)); + break; + case SecCmsRecipientInfoIDKeyAgree: + encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.keyAgreeRecipientInfo.keyEncAlg)); + break; + case SecCmsRecipientInfoIDKEK: + encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.kekRecipientInfo.keyEncAlg)); + break; + } + return encalgtag; +} + +OSStatus +SecCmsRecipientInfoWrapBulkKey(SecCmsRecipientInfoRef ri, SecSymmetricKeyRef bulkkey, + SECOidTag bulkalgtag) +{ + SecCertificateRef cert; + SECOidTag certalgtag; + OSStatus rv = SECSuccess; +#if 0 + CSSM_DATA_PTR params = NULL; +#endif /* 0 */ + SecCmsRecipientEncryptedKey *rek; + SecCmsOriginatorIdentifierOrKey *oiok; + const SECAlgorithmID *algid; + PLArenaPool *poolp; + SecCmsKeyTransRecipientInfoEx *extra = NULL; + Boolean usesSubjKeyID; + uint8 nullData[2] = {SEC_ASN1_NULL, 0}; + SECItem nullItem; + SecCmsKeyAgreeRecipientInfo *kari; + + poolp = ri->cmsg->poolp; + cert = ri->cert; + usesSubjKeyID = nss_cmsrecipientinfo_usessubjectkeyid(ri); + if (cert) { + rv = SecCertificateGetAlgorithmID(cert,&algid); + if (rv) + return SECFailure; + certalgtag = SECOID_GetAlgorithmTag(algid); + } else if (usesSubjKeyID) { + extra = &ri->ri.keyTransRecipientInfoEx; + /* sanity check */ + PORT_Assert(extra->pubKey); + if (!extra->pubKey) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = SecKeyGetAlgorithmID(extra->pubKey,&algid); + if (rv) + return SECFailure; + certalgtag = SECOID_GetAlgorithmTag(algid); + } else { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + /* XXX set ri->recipientInfoType to the proper value here */ + /* or should we look if it's been set already ? */ + + certalgtag = SECOID_GetAlgorithmTag(algid); + switch (certalgtag) { + case SEC_OID_PKCS1_RSA_ENCRYPTION: + /* wrap the symkey */ + if (cert) { + rv = SecCmsUtilEncryptSymKeyRSA(poolp, cert, bulkkey, + &ri->ri.keyTransRecipientInfo.encKey); + if (rv != SECSuccess) + break; + } else if (usesSubjKeyID) { + PORT_Assert(extra != NULL); + rv = SecCmsUtilEncryptSymKeyRSAPubKey(poolp, extra->pubKey, + bulkkey, &ri->ri.keyTransRecipientInfo.encKey); + if (rv != SECSuccess) + break; + } + + rv = SECOID_SetAlgorithmID(poolp, &(ri->ri.keyTransRecipientInfo.keyEncAlg), certalgtag, NULL); + break; +#if 0 + case SEC_OID_MISSI_KEA_DSS_OLD: + case SEC_OID_MISSI_KEA_DSS: + case SEC_OID_MISSI_KEA: + rv = SecCmsUtilEncryptSymKeyMISSI(poolp, cert, bulkkey, + bulkalgtag, + &ri->ri.keyTransRecipientInfo.encKey, + ¶ms, ri->cmsg->pwfn_arg); + if (rv != SECSuccess) + break; + + /* here, we DO need to pass the params to the wrap function because, with + * RSA, there is no funny stuff going on with generation of IV vectors or so */ + rv = SECOID_SetAlgorithmID(poolp, &(ri->ri.keyTransRecipientInfo.keyEncAlg), certalgtag, params); + break; + case SEC_OID_X942_DIFFIE_HELMAN_KEY: /* dh-public-number */ + rek = ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[0]; + if (rek == NULL) { + rv = SECFailure; + break; + } + + oiok = &(ri->ri.keyAgreeRecipientInfo.originatorIdentifierOrKey); + PORT_Assert(oiok->identifierType == SecCmsOriginatorIDOrKeyOriginatorPublicKey); + + /* see RFC2630 12.3.1.1 */ + if (SECOID_SetAlgorithmID(poolp, &oiok->id.originatorPublicKey.algorithmIdentifier, + SEC_OID_X942_DIFFIE_HELMAN_KEY, NULL) != SECSuccess) { + rv = SECFailure; + break; + } + + /* this will generate a key pair, compute the shared secret, */ + /* derive a key and ukm for the keyEncAlg out of it, encrypt the bulk key with */ + /* the keyEncAlg, set encKey, keyEncAlg, publicKey etc. */ + rv = SecCmsUtilEncryptSymKeyESDH(poolp, cert, bulkkey, + &rek->encKey, + &ri->ri.keyAgreeRecipientInfo.ukm, + &ri->ri.keyAgreeRecipientInfo.keyEncAlg, + &oiok->id.originatorPublicKey.publicKey); + + break; +#endif /* 0 */ + + case SEC_OID_EC_PUBLIC_KEY: + /* These were set up in nss_cmsrecipientinfo_create() */ + kari = &ri->ri.keyAgreeRecipientInfo; + rek = kari->recipientEncryptedKeys[0]; + if (rek == NULL) { + rv = SECFailure; + break; + } + + oiok = &(kari->originatorIdentifierOrKey); + PORT_Assert(oiok->identifierType == SecCmsOriginatorIDOrKeyOriginatorPublicKey); + + /* + * RFC 3278 3.1.1 says this AlgId must contain NULL params which is contrary to + * any other use of the SEC_OID_EC_PUBLIC_KEY OID. So we provide one + * explicitly instead of mucking up the login in SECOID_SetAlgorithmID(). + */ + nullItem.Data = nullData; + nullItem.Length = 2; + if (SECOID_SetAlgorithmID(poolp, &oiok->id.originatorPublicKey.algorithmIdentifier, + SEC_OID_EC_PUBLIC_KEY, &nullItem) != SECSuccess) { + rv = SECFailure; + break; + } + + /* this will generate a key pair, compute the shared secret, */ + /* derive a key and ukm for the keyEncAlg out of it, encrypt the bulk key with */ + /* the keyEncAlg, set encKey, keyEncAlg, publicKey etc. */ + rv = SecCmsUtilEncryptSymKeyECDH(poolp, cert, bulkkey, + &rek->encKey, + &kari->ukm, + &kari->keyEncAlg, + &oiok->id.originatorPublicKey.publicKey); + /* this is a BIT STRING */ + oiok->id.originatorPublicKey.publicKey.Length <<= 3; + break; + + default: + /* other algorithms not supported yet */ + /* NOTE that we do not support any KEK algorithm */ + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + rv = SECFailure; + break; + } +#if 0 + if (freeSpki) + SECKEY_DestroySubjectPublicKeyInfo(freeSpki); +#endif + + return rv; +} + +#ifdef NDEBUG +#define dprintf(args...) +#else +#define dprintf(args...) printf(args) +#endif + +SecSymmetricKeyRef +SecCmsRecipientInfoUnwrapBulkKey(SecCmsRecipientInfoRef ri, int subIndex, + SecCertificateRef cert, SecPrivateKeyRef privkey, SECOidTag bulkalgtag) +{ + SecSymmetricKeyRef bulkkey = NULL; + SECAlgorithmID *encalg; + SECOidTag encalgtag; + CSSM_DATA_PTR enckey; + int error; + + ri->cert = CERT_DupCertificate(cert); + /* mark the recipientInfo so we can find it later */ + + switch (ri->recipientInfoType) { + case SecCmsRecipientInfoIDKeyTrans: + encalg = &(ri->ri.keyTransRecipientInfo.keyEncAlg); + encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.keyTransRecipientInfo.keyEncAlg)); + enckey = &(ri->ri.keyTransRecipientInfo.encKey); /* ignore subIndex */ + switch (encalgtag) { + case SEC_OID_PKCS1_RSA_ENCRYPTION: + /* RSA encryption algorithm: */ + /* get the symmetric (bulk) key by unwrapping it using our private key */ + bulkkey = SecCmsUtilDecryptSymKeyRSA(privkey, enckey, bulkalgtag); + break; +#if 0 + case SEC_OID_NETSCAPE_SMIME_KEA: + /* FORTEZZA key exchange algorithm */ + /* the supplemental data is in the parameters of encalg */ + bulkkey = SecCmsUtilDecryptSymKeyMISSI(privkey, enckey, encalg, bulkalgtag, ri->cmsg->pwfn_arg); + break; +#endif /* 0 */ + default: + error = SEC_ERROR_UNSUPPORTED_KEYALG; + goto loser; + } + break; + case SecCmsRecipientInfoIDKeyAgree: + encalg = &(ri->ri.keyAgreeRecipientInfo.keyEncAlg); + encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.keyAgreeRecipientInfo.keyEncAlg)); + enckey = &(ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[subIndex]->encKey); + switch (encalgtag) { + case SEC_OID_X942_DIFFIE_HELMAN_KEY: + /* Diffie-Helman key exchange */ + /* XXX not yet implemented */ + /* XXX problem: SEC_OID_X942_DIFFIE_HELMAN_KEY points to a PKCS3 mechanism! */ + /* we support ephemeral-static DH only, so if the recipientinfo */ + /* has originator stuff in it, we punt (or do we? shouldn't be that hard...) */ + /* first, we derive the KEK (a symkey!) using a Derive operation, then we get the */ + /* content encryption key using a Unwrap op */ + /* the derive operation has to generate the key using the algorithm in RFC2631 */ + error = SEC_ERROR_UNSUPPORTED_KEYALG; + break; + case SEC_OID_DH_SINGLE_STD_SHA1KDF: + { + /* ephemeral-static ECDH */ + SecCmsKeyAgreeRecipientInfo *kari = &ri->ri.keyAgreeRecipientInfo; + SecCmsOriginatorIdentifierOrKey *oiok = &kari->originatorIdentifierOrKey; + if(oiok->identifierType != SecCmsOriginatorIDOrKeyOriginatorPublicKey) { + dprintf("SEC_OID_EC_PUBLIC_KEY unwrap key: bad oiok.id\n"); + goto loser; + } + SecCmsOriginatorPublicKey *opk = &oiok->id.originatorPublicKey; + /* FIXME - verify opk->algorithmIdentifier here? */ + CSSM_DATA senderPubKey = opk->publicKey; + /* Bit string, convert here */ + senderPubKey.Length = (senderPubKey.Length + 7) >> 3; + CSSM_DATA_PTR ukm = &kari->ukm; + bulkkey = SecCmsUtilDecryptSymKeyECDH(privkey, enckey, ukm, encalg, bulkalgtag, &senderPubKey); + break; + } + default: + error = SEC_ERROR_UNSUPPORTED_KEYALG; + goto loser; + } + break; + case SecCmsRecipientInfoIDKEK: + encalg = &(ri->ri.kekRecipientInfo.keyEncAlg); + encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.kekRecipientInfo.keyEncAlg)); + enckey = &(ri->ri.kekRecipientInfo.encKey); + /* not supported yet */ + error = SEC_ERROR_UNSUPPORTED_KEYALG; + goto loser; + break; + } + /* XXXX continue here */ + return bulkkey; + +loser: + return NULL; +} diff --git a/Security/libsecurity_smime/lib/cmsreclist.c b/Security/libsecurity_smime/lib/cmsreclist.c new file mode 100644 index 00000000..15f0942d --- /dev/null +++ b/Security/libsecurity_smime/lib/cmsreclist.c @@ -0,0 +1,237 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "cmslocal.h" + +#include "cert.h" +#include "secitem.h" +#include "secoid.h" + +#include +#include +#include + +static int +nss_cms_recipients_traverse(SecCmsRecipientInfoRef *recipientinfos, SecCmsRecipient **recipient_list) +{ + int count = 0; + int rlindex = 0; + int i, j; + SecCmsRecipient *rle; + SecCmsRecipientInfoRef ri; + SecCmsRecipientEncryptedKey *rek; + + for (i = 0; recipientinfos[i] != NULL; i++) { + ri = recipientinfos[i]; + switch (ri->recipientInfoType) { + case SecCmsRecipientInfoIDKeyTrans: + if (recipient_list) { + /* alloc one & fill it out */ + rle = (SecCmsRecipient *)PORT_ZAlloc(sizeof(SecCmsRecipient)); + if (rle == NULL) + return -1; + + rle->riIndex = i; + rle->subIndex = -1; + switch (ri->ri.keyTransRecipientInfo.recipientIdentifier.identifierType) { + case SecCmsRecipientIDIssuerSN: + rle->kind = RLIssuerSN; + rle->id.issuerAndSN = ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN; + break; + case SecCmsRecipientIDSubjectKeyID: + rle->kind = RLSubjKeyID; + rle->id.subjectKeyID = ri->ri.keyTransRecipientInfo.recipientIdentifier.id.subjectKeyID; + break; + } + recipient_list[rlindex++] = rle; + } else { + count++; + } + break; + case SecCmsRecipientInfoIDKeyAgree: + if (ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys == NULL) + break; + for (j=0; ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[j] != NULL; j++) { + if (recipient_list) { + rek = ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[j]; + /* alloc one & fill it out */ + rle = (SecCmsRecipient *)PORT_ZAlloc(sizeof(SecCmsRecipient)); + if (rle == NULL) + return -1; + + rle->riIndex = i; + rle->subIndex = j; + switch (rek->recipientIdentifier.identifierType) { + case SecCmsKeyAgreeRecipientIDIssuerSN: + rle->kind = RLIssuerSN; + rle->id.issuerAndSN = rek->recipientIdentifier.id.issuerAndSN; + break; + case SecCmsKeyAgreeRecipientIDRKeyID: + rle->kind = RLSubjKeyID; + rle->id.subjectKeyID = rek->recipientIdentifier.id.recipientKeyIdentifier.subjectKeyIdentifier; + break; + } + recipient_list[rlindex++] = rle; + } else { + count++; + } + } + break; + case SecCmsRecipientInfoIDKEK: + /* KEK is not implemented */ + break; + } + } + /* if we have a recipient list, we return on success (-1, above, on failure) */ + /* otherwise, we return the count. */ + if (recipient_list) { + recipient_list[rlindex] = NULL; + return 0; + } else { + return count; + } +} + +SecCmsRecipient ** +nss_cms_recipient_list_create(SecCmsRecipientInfoRef *recipientinfos) +{ + int count, rv; + SecCmsRecipient **recipient_list; + + /* count the number of recipient identifiers */ + count = nss_cms_recipients_traverse(recipientinfos, NULL); + if (count <= 0) { + /* no recipients? */ + PORT_SetError(SEC_ERROR_BAD_DATA); +#if 0 + PORT_SetErrorString("Cannot find recipient data in envelope."); +#endif + return NULL; + } + + /* allocate an array of pointers */ + recipient_list = (SecCmsRecipient **) + PORT_ZAlloc((count + 1) * sizeof(SecCmsRecipient *)); + if (recipient_list == NULL) + return NULL; + + /* now fill in the recipient_list */ + rv = nss_cms_recipients_traverse(recipientinfos, recipient_list); + if (rv < 0) { + nss_cms_recipient_list_destroy(recipient_list); + return NULL; + } + return recipient_list; +} + +void +nss_cms_recipient_list_destroy(SecCmsRecipient **recipient_list) +{ + int i; + SecCmsRecipient *recipient; + + for (i=0; recipient_list[i] != NULL; i++) { + recipient = recipient_list[i]; + if (recipient->cert) + CFRelease(recipient->cert); + if (recipient->privkey) + CFRelease(recipient->privkey); +#if 0 + // @@@ Eliminate slot stuff. + if (recipient->slot) + PK11_FreeSlot(recipient->slot); +#endif + PORT_Free(recipient); + } + PORT_Free(recipient_list); +} + +SecCmsRecipientEncryptedKey * +SecCmsRecipientEncryptedKeyCreate(PLArenaPool *poolp) +{ + return (SecCmsRecipientEncryptedKey *)PORT_ArenaZAlloc(poolp, sizeof(SecCmsRecipientEncryptedKey)); +} + + +int +nss_cms_FindCertAndKeyByRecipientList(SecCmsRecipient **recipient_list, void *wincx) +{ + SecCmsRecipient *recipient = NULL; + SecCertificateRef cert = NULL; + SecPrivateKeyRef privKey = NULL; + SecIdentityRef identity = NULL; + CFTypeRef keychainOrArray = NULL; // @@@ The caller should be able to pass this in somehow. + int index; + + for (index = 0; recipient_list[index] != NULL; ++index) + { + recipient = recipient_list[index]; + + switch (recipient->kind) + { + case RLIssuerSN: + identity = CERT_FindIdentityByIssuerAndSN(keychainOrArray, recipient->id.issuerAndSN); + break; + case RLSubjKeyID: + identity = CERT_FindIdentityBySubjectKeyID(keychainOrArray, recipient->id.subjectKeyID); + break; + } + + if (identity) + break; + } + + if (!recipient) + goto loser; + + if (SecIdentityCopyCertificate(identity, &cert)) + goto loser; + if (SecIdentityCopyPrivateKey(identity, &privKey)) + goto loser; + CFRelease(identity); + + recipient->cert = cert; + recipient->privkey = privKey; + + return index; + +loser: + if (identity) + CFRelease(identity); + if (cert) + CFRelease(cert); + if (privKey) + CFRelease(privKey); + + return -1; +} diff --git a/Security/libsecurity_smime/lib/cmsreclist.h b/Security/libsecurity_smime/lib/cmsreclist.h new file mode 100644 index 00000000..38d0dc2c --- /dev/null +++ b/Security/libsecurity_smime/lib/cmsreclist.h @@ -0,0 +1,57 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#ifndef _CMSRECLIST_H +#define _CMSRECLIST_H + +struct SecCmsRecipientStr { + int riIndex; /* this recipient's index in recipientInfo array */ + int subIndex; /* index into recipientEncryptedKeys */ + /* (only in SecCmsKeyAgreeRecipientInfoStr) */ + enum {RLIssuerSN=0, RLSubjKeyID=1} kind; /* for conversion recipientinfos -> recipientlist */ + union { + SecCmsIssuerAndSN * issuerAndSN; + CSSM_DATA_PTR subjectKeyID; + } id; + + /* result data (filled out for each recipient that's us) */ + SecCertificateRef cert; + SecPrivateKeyRef privkey; + //PK11SlotInfo * slot; +}; + +typedef struct SecCmsRecipientStr SecCmsRecipient; + +int nss_cms_FindCertAndKeyByRecipientList(SecCmsRecipient **recipient_list, void *wincx); + +#endif /* _CMSRECLIST_H */ diff --git a/Security/libsecurity_smime/lib/cmssigdata.c b/Security/libsecurity_smime/lib/cmssigdata.c new file mode 100644 index 00000000..2abc2313 --- /dev/null +++ b/Security/libsecurity_smime/lib/cmssigdata.c @@ -0,0 +1,1192 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * CMS signedData methods. + */ + +#include + +#include +#include +#include + +#include "cmslocal.h" + +#include "cert.h" +#include "secitem.h" +#include "secoid.h" +#include "tsaTemplates.h" + +#include +#include +#include +#include +#include +#include + +#ifndef NDEBUG +#define SIGDATA_DEBUG 1 +#endif + +#if SIGDATA_DEBUG +#define dprintf(args...) printf(args) +#else +#define dprintf(args...) +#endif + +SecCmsSignedDataRef +SecCmsSignedDataCreate(SecCmsMessageRef cmsg) +{ + void *mark; + SecCmsSignedDataRef sigd; + PLArenaPool *poolp; + + poolp = cmsg->poolp; + + mark = PORT_ArenaMark(poolp); + + sigd = (SecCmsSignedDataRef)PORT_ArenaZAlloc (poolp, sizeof(SecCmsSignedData)); + if (sigd == NULL) + goto loser; + + sigd->cmsg = cmsg; + + /* signerInfos, certs, certlists, crls are all empty */ + /* version is set in SecCmsSignedDataFinalize() */ + + PORT_ArenaUnmark(poolp, mark); + return sigd; + +loser: + PORT_ArenaRelease(poolp, mark); + return NULL; +} + +void +SecCmsSignedDataDestroy(SecCmsSignedDataRef sigd) +{ + SecCmsSignerInfoRef *signerinfos, si; + + if (sigd == NULL) + return; + + if (sigd->certs != NULL) + CFRelease(sigd->certs); + + signerinfos = sigd->signerInfos; + if (signerinfos != NULL) { + while ((si = *signerinfos++) != NULL) + SecCmsSignerInfoDestroy(si); + } + + /* everything's in a pool, so don't worry about the storage */ + SecCmsContentInfoDestroy(&(sigd->contentInfo)); +} + +/* + * SecCmsSignedDataEncodeBeforeStart - do all the necessary things to a SignedData + * before start of encoding. + * + * In detail: + * - find out about the right value to put into sigd->version + * - come up with a list of digestAlgorithms (which should be the union of the algorithms + * in the signerinfos). + * If we happen to have a pre-set list of algorithms (and digest values!), we + * check if we have all the signerinfos' algorithms. If not, this is an error. + */ +OSStatus +SecCmsSignedDataEncodeBeforeStart(SecCmsSignedDataRef sigd) +{ + SecCmsSignerInfoRef signerinfo; + SECOidTag digestalgtag; + CSSM_DATA_PTR dummy; + int version; + OSStatus rv; + Boolean haveDigests = PR_FALSE; + int n, i; + PLArenaPool *poolp; + + poolp = sigd->cmsg->poolp; + + /* we assume that we have precomputed digests if there is a list of algorithms, and */ + /* a chunk of data for each of those algorithms */ + if (sigd->digestAlgorithms != NULL && sigd->digests != NULL) { + for (i=0; sigd->digestAlgorithms[i] != NULL; i++) { + if (sigd->digests[i] == NULL) + break; + } + if (sigd->digestAlgorithms[i] == NULL) /* reached the end of the array? */ + haveDigests = PR_TRUE; /* yes: we must have all the digests */ + } + + version = SEC_CMS_SIGNED_DATA_VERSION_BASIC; + + /* RFC2630 5.1 "version is the syntax version number..." */ + if (SecCmsContentInfoGetContentTypeTag(&(sigd->contentInfo)) != SEC_OID_PKCS7_DATA) + version = SEC_CMS_SIGNED_DATA_VERSION_EXT; + + /* prepare all the SignerInfos (there may be none) */ + for (i=0; i < SecCmsSignedDataSignerInfoCount(sigd); i++) { + signerinfo = SecCmsSignedDataGetSignerInfo(sigd, i); + + /* RFC2630 5.1 "version is the syntax version number..." */ + if (SecCmsSignerInfoGetVersion(signerinfo) != SEC_CMS_SIGNER_INFO_VERSION_ISSUERSN) + version = SEC_CMS_SIGNED_DATA_VERSION_EXT; + + /* collect digestAlgorithms from SignerInfos */ + /* (we need to know which algorithms we have when the content comes in) */ + /* do not overwrite any existing digestAlgorithms (and digest) */ + digestalgtag = SecCmsSignerInfoGetDigestAlgTag(signerinfo); + + n = SecCmsAlgArrayGetIndexByAlgTag(sigd->digestAlgorithms, digestalgtag); + if (n < 0 && haveDigests) { + /* oops, there is a digestalg we do not have a digest for */ + /* but we were supposed to have all the digests already... */ + goto loser; + } else if (n < 0) { + /* add the digestAlgorithm & a NULL digest */ + rv = SecCmsSignedDataAddDigest((SecArenaPoolRef)poolp, sigd, digestalgtag, NULL); + if (rv != SECSuccess) + goto loser; + } else { + /* found it, nothing to do */ + } + } + + dummy = SEC_ASN1EncodeInteger(poolp, &(sigd->version), (long)version); + if (dummy == NULL) + return SECFailure; + + /* this is a SET OF, so we need to sort them guys */ + rv = SecCmsArraySortByDER((void **)sigd->digestAlgorithms, + SEC_ASN1_GET(SECOID_AlgorithmIDTemplate), + (void **)sigd->digests); + if (rv != SECSuccess) + return SECFailure; + + return SECSuccess; + +loser: + return SECFailure; +} + +OSStatus +SecCmsSignedDataEncodeBeforeData(SecCmsSignedDataRef sigd) +{ + /* set up the digests */ + if (sigd->digestAlgorithms != NULL) { + sigd->contentInfo.digcx = SecCmsDigestContextStartMultiple(sigd->digestAlgorithms); + if (sigd->contentInfo.digcx == NULL) + return SECFailure; + } + return SECSuccess; +} + +#include +#include "tsaSupport.h" +#include "tsaSupportPriv.h" +#include "tsaTemplates.h" +#include + +extern const SecAsn1Template kSecAsn1TSATSTInfoTemplate; + +OSStatus createTSAMessageImprint(SecCmsSignedDataRef signedData, CSSM_DATA_PTR encDigest, + SecAsn1TSAMessageImprint *messageImprint) +{ + // Calculate hash of encDigest and put in messageImprint.hashedMessage + // We pass in encDigest, since in the verification case, it comes from a different signedData + + OSStatus status = SECFailure; + + require(signedData && messageImprint, xit); + + SECAlgorithmID **digestAlgorithms = SecCmsSignedDataGetDigestAlgs(signedData); + require(digestAlgorithms, xit); + + SecCmsDigestContextRef digcx = SecCmsDigestContextStartMultiple(digestAlgorithms); + require(digcx, xit); + require(encDigest, xit); + + SecCmsSignerInfoRef signerinfo = SecCmsSignedDataGetSignerInfo(signedData, 0); // NB - assume 1 signer only! + messageImprint->hashAlgorithm = signerinfo->digestAlg; + + SecCmsDigestContextUpdate(digcx, encDigest->Data, encDigest->Length); + + require_noerr(SecCmsDigestContextFinishSingle(digcx, (SecArenaPoolRef)signedData->cmsg->poolp, + &messageImprint->hashedMessage), xit); + + status = SECSuccess; +xit: + return status; +} + +#include + +#ifndef NDEBUG +static OSStatus decodeDERUTF8String(const CSSM_DATA_PTR content, char *statusstr, size_t strsz) +{ + // The statusString should use kSecAsn1SequenceOfUTF8StringTemplate, but doesn't + OSStatus status = SECFailure; + SecAsn1CoderRef coder = NULL; + CSSM_DATA statusString; + size_t len = 0; + + require(content && statusstr, xit); + + require_noerr(SecAsn1CoderCreate(&coder), xit); + require_noerr(SecAsn1Decode(coder, content->Data, content->Length, kSecAsn1UTF8StringTemplate, &statusString), xit); + status = 0; + len = (statusString.Length < strsz)?(int)statusString.Length:strsz; + if (statusstr && statusString.Data) + strncpy(statusstr, (const char *)statusString.Data, len); + +xit: + if (coder) + SecAsn1CoderRelease(coder); + return status; +} +#endif + +static OSStatus validateTSAResponseAndAddTimeStamp(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR tsaResponse, + uint64_t expectedNonce) +{ + OSStatus status = SECFailure; + SecAsn1CoderRef coder = NULL; + SecAsn1TimeStampRespDER respDER = {{{0}},}; + SecAsn1TSAPKIStatusInfo *tsastatus = NULL; + int respstatus = -1; +#ifndef NDEBUG + int failinfo = -1; +#endif + + require_action(tsaResponse && tsaResponse->Data && tsaResponse->Length, xit, status = errSecTimestampMissing); + + require_noerr(SecAsn1CoderCreate(&coder), xit); + require_noerr(SecTSAResponseCopyDEREncoding(coder, tsaResponse, &respDER), xit); + +#ifndef NDEBUG + tsaWriteFileX("/tmp/tsa-timeStampToken.der", respDER.timeStampTokenDER.Data, respDER.timeStampTokenDER.Length); +#endif + + tsastatus = (SecAsn1TSAPKIStatusInfo *)&respDER.status; + require_action(tsastatus->status.Data, xit, status = errSecTimestampBadDataFormat); + respstatus = (int)tsaDER_ToInt(&tsastatus->status); + +#ifndef NDEBUG + char buf[80]={0,}; + if (tsastatus->failInfo.Data) // e.g. FI_BadRequest + failinfo = (int)tsaDER_ToInt(&tsastatus->failInfo); + + if (tsastatus->statusString.Data && tsastatus->statusString.Length) + { + OSStatus strrx = decodeDERUTF8String(&tsastatus->statusString, buf, sizeof(buf)); + dprintf("decodeDERUTF8String status: %d\n", (int)strrx); + } + + dprintf("validateTSAResponse: status: %d, failinfo: %d, %s\n", respstatus, failinfo, buf); +#endif + + switch (respstatus) + { + case PKIS_Granted: + case PKIS_GrantedWithMods: // Success + status = noErr; + break; + case PKIS_Rejection: + status = errSecTimestampRejection; + break; + case PKIS_Waiting: + status = errSecTimestampWaiting; + break; + case PKIS_RevocationWarning: + status = errSecTimestampRevocationWarning; + break; + case PKIS_RevocationNotification: + status = errSecTimestampRevocationNotification; + break; + default: + status = errSecTimestampSystemFailure; + break; + } + require_noerr(status, xit); + + // If we succeeded, then we must have a TimeStampToken + + require_action(respDER.timeStampTokenDER.Data && respDER.timeStampTokenDER.Length, xit, status = errSecTimestampBadDataFormat); + + dprintf("timestamp full expected nonce: %lld\n", expectedNonce); + + /* + The bytes in respDER are a full CMS message, which we need to check now for validity. + The code for this is essentially the same code taht is done during a timestamp + verify, except that we also need to check the nonce. + */ + require_noerr(status = decodeTimeStampToken(signerinfo, &respDER.timeStampTokenDER, NULL, expectedNonce), xit); + + status = SecCmsSignerInfoAddTimeStamp(signerinfo, &respDER.timeStampTokenDER); + +xit: + if (coder) + SecAsn1CoderRelease(coder); + return status; +} + +static OSStatus getRandomNonce(uint64_t *nonce) +{ + return nonce ? CCRandomCopyBytes(kCCRandomDevRandom, (void *)nonce, sizeof(*nonce)) : SECFailure; +} + +static OSStatus remapTimestampError(OSStatus inStatus) +{ + /* + Since communicating with the timestamp server is perhaps an unexpected + dependency on the network, map unknown errors into something to indicate + that signing without a timestamp may be a workaround. In particular, the + private CFURL errors (see CFNetworkErrorsPriv.i) + + kCFURLErrorTimedOut = -1001, + kCFURLErrorNotConnectedToInternet = -1009, + + are remapped to errSecTimestampServiceNotAvailable. + */ + + switch (inStatus) + { + case errSecTimestampMissing: + case errSecTimestampInvalid: + case errSecTimestampNotTrusted: + case errSecTimestampServiceNotAvailable: + case errSecTimestampBadAlg: + case errSecTimestampBadRequest: + case errSecTimestampBadDataFormat: + case errSecTimestampTimeNotAvailable: + case errSecTimestampUnacceptedPolicy: + case errSecTimestampUnacceptedExtension: + case errSecTimestampAddInfoNotAvailable: + case errSecTimestampSystemFailure: + case errSecSigningTimeMissing: + case errSecTimestampRejection: + case errSecTimestampWaiting: + case errSecTimestampRevocationWarning: + case errSecTimestampRevocationNotification: + return inStatus; + default: + return errSecTimestampServiceNotAvailable; + } + return errSecTimestampServiceNotAvailable; +} + +/* + * SecCmsSignedDataEncodeAfterData - do all the necessary things to a SignedData + * after all the encapsulated data was passed through the encoder. + * + * In detail: + * - create the signatures in all the SignerInfos + * + * Please note that nothing is done to the Certificates and CRLs in the message - this + * is entirely the responsibility of our callers. + */ +OSStatus +SecCmsSignedDataEncodeAfterData(SecCmsSignedDataRef sigd) +{ + SecCmsSignerInfoRef *signerinfos, signerinfo; + SecCmsContentInfoRef cinfo; + SECOidTag digestalgtag; + OSStatus ret = SECFailure; + OSStatus rv; + CSSM_DATA_PTR contentType; + int certcount; + int i, ci, n, rci, si; + PLArenaPool *poolp; + CFArrayRef certlist; + extern const SecAsn1Template SecCmsSignerInfoTemplate[]; + + poolp = sigd->cmsg->poolp; + cinfo = &(sigd->contentInfo); + + /* did we have digest calculation going on? */ + if (cinfo->digcx) { + rv = SecCmsDigestContextFinishMultiple(cinfo->digcx, (SecArenaPoolRef)poolp, &(sigd->digests)); + if (rv != SECSuccess) + goto loser; /* error has been set by SecCmsDigestContextFinishMultiple */ + cinfo->digcx = NULL; + } + + signerinfos = sigd->signerInfos; + certcount = 0; + + /* prepare all the SignerInfos (there may be none) */ + for (i=0; i < SecCmsSignedDataSignerInfoCount(sigd); i++) { + signerinfo = SecCmsSignedDataGetSignerInfo(sigd, i); + + /* find correct digest for this signerinfo */ + digestalgtag = SecCmsSignerInfoGetDigestAlgTag(signerinfo); + n = SecCmsAlgArrayGetIndexByAlgTag(sigd->digestAlgorithms, digestalgtag); + if (n < 0 || sigd->digests == NULL || sigd->digests[n] == NULL) { + /* oops - digest not found */ + PORT_SetError(SEC_ERROR_DIGEST_NOT_FOUND); + goto loser; + } + + /* XXX if our content is anything else but data, we need to force the + * presence of signed attributes (RFC2630 5.3 "signedAttributes is a + * collection...") */ + + /* pass contentType here as we want a contentType attribute */ + if ((contentType = SecCmsContentInfoGetContentTypeOID(cinfo)) == NULL) + goto loser; + + /* sign the thing */ + rv = SecCmsSignerInfoSign(signerinfo, sigd->digests[n], contentType); + if (rv != SECSuccess) + goto loser; + + /* while we're at it, count number of certs in certLists */ + certlist = SecCmsSignerInfoGetCertList(signerinfo); + if (certlist) + certcount += CFArrayGetCount(certlist); + } + + /* Now we can get a timestamp, since we have all the digests */ + + // We force the setting of a callback, since this is the most usual case + if (!sigd->cmsg->tsaCallback) + SecCmsMessageSetTSACallback(sigd->cmsg, (SecCmsTSACallback)SecCmsTSADefaultCallback); + + if (sigd->cmsg->tsaCallback && sigd->cmsg->tsaContext) + { + CSSM_DATA tsaResponse = {0,}; + SecAsn1TSAMessageImprint messageImprint = {{{0},},{0,}}; + // Add nonce support for timestamping client + + uint64_t nonce = 0; + + require_noerr(getRandomNonce(&nonce), tsxit); + dprintf("SecCmsSignedDataSignerInfoCount: %d\n", SecCmsSignedDataSignerInfoCount(sigd)); + + // Calculate hash of encDigest and put in messageImprint.hashedMessage + SecCmsSignerInfoRef signerinfo = SecCmsSignedDataGetSignerInfo(sigd, 0); // NB - assume 1 signer only! + CSSM_DATA *encDigest = SecCmsSignerInfoGetEncDigest(signerinfo); + require_noerr(createTSAMessageImprint(sigd, encDigest, &messageImprint), tsxit); + + // Callback to fire up XPC service to talk to TimeStamping server, etc. + require_noerr(rv =(*sigd->cmsg->tsaCallback)(sigd->cmsg->tsaContext, &messageImprint, + nonce, &tsaResponse), tsxit); + + require_noerr(rv = validateTSAResponseAndAddTimeStamp(signerinfo, &tsaResponse, nonce), tsxit); + + /* + It is likely that every occurrence of "goto loser" in this file should + also do a PORT_SetError. Since it is not clear what might depend on this + behavior, we just do this in the timestamping case. + */ +tsxit: + if (rv) + { + dprintf("Original timestamp error: %d\n", (int)rv); + rv = remapTimestampError(rv); + PORT_SetError(rv); + goto loser; + } + } + + /* this is a SET OF, so we need to sort them guys */ + rv = SecCmsArraySortByDER((void **)signerinfos, SecCmsSignerInfoTemplate, NULL); + if (rv != SECSuccess) + goto loser; + + /* + * now prepare certs & crls + */ + + /* count the rest of the certs */ + if (sigd->certs != NULL) + certcount += CFArrayGetCount(sigd->certs); + + if (certcount == 0) { + sigd->rawCerts = NULL; + } else { + /* + * Combine all of the certs and cert chains into rawcerts. + * Note: certcount is an upper bound; we may not need that many slots + * but we will allocate anyway to avoid having to do another pass. + * (The temporary space saving is not worth it.) + * + * XXX ARGH - this NEEDS to be fixed. need to come up with a decent + * SetOfDERcertficates implementation + */ + sigd->rawCerts = (CSSM_DATA_PTR *)PORT_ArenaAlloc(poolp, (certcount + 1) * sizeof(CSSM_DATA_PTR)); + if (sigd->rawCerts == NULL) + return SECFailure; + + /* + * XXX Want to check for duplicates and not add *any* cert that is + * already in the set. This will be more important when we start + * dealing with larger sets of certs, dual-key certs (signing and + * encryption), etc. For the time being we can slide by... + * + * XXX ARGH - this NEEDS to be fixed. need to come up with a decent + * SetOfDERcertficates implementation + */ + rci = 0; + if (signerinfos != NULL) { + for (si = 0; signerinfos[si] != NULL; si++) { + signerinfo = signerinfos[si]; + for (ci = 0; ci < CFArrayGetCount(signerinfo->certList); ci++) { + sigd->rawCerts[rci] = PORT_ArenaZAlloc(poolp, sizeof(CSSM_DATA)); + SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(signerinfo->certList, ci); + SecCertificateGetData(cert, sigd->rawCerts[rci++]); + } + } + } + + if (sigd->certs != NULL) { + for (ci = 0; ci < CFArrayGetCount(sigd->certs); ci++) { + sigd->rawCerts[rci] = PORT_ArenaZAlloc(poolp, sizeof(CSSM_DATA)); + SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(sigd->certs, ci); + SecCertificateGetData(cert, sigd->rawCerts[rci++]); + } + } + + sigd->rawCerts[rci] = NULL; + + /* this is a SET OF, so we need to sort them guys - we have the DER already, though */ + SecCmsArraySort((void **)sigd->rawCerts, SecCmsUtilDERCompare, NULL, NULL); + } + + ret = SECSuccess; + +loser: + + dprintf("SecCmsSignedDataEncodeAfterData: ret: %ld, rv: %ld\n", (long)ret, (long)rv); + return ret; +} + +OSStatus +SecCmsSignedDataDecodeBeforeData(SecCmsSignedDataRef sigd) +{ + /* set up the digests */ + if (sigd->digestAlgorithms != NULL && sigd->digests == NULL) { + /* if digests are already there, do nothing */ + sigd->contentInfo.digcx = SecCmsDigestContextStartMultiple(sigd->digestAlgorithms); + if (sigd->contentInfo.digcx == NULL) + return SECFailure; + } + return SECSuccess; +} + +/* + * SecCmsSignedDataDecodeAfterData - do all the necessary things to a SignedData + * after all the encapsulated data was passed through the decoder. + */ +OSStatus +SecCmsSignedDataDecodeAfterData(SecCmsSignedDataRef sigd) +{ + /* did we have digest calculation going on? */ + if (sigd->contentInfo.digcx) { + if (SecCmsDigestContextFinishMultiple(sigd->contentInfo.digcx, (SecArenaPoolRef)sigd->cmsg->poolp, &(sigd->digests)) != SECSuccess) + return SECFailure; /* error has been set by SecCmsDigestContextFinishMultiple */ + sigd->contentInfo.digcx = NULL; + } + return SECSuccess; +} + +/* + * SecCmsSignedDataDecodeAfterEnd - do all the necessary things to a SignedData + * after all decoding is finished. + */ +OSStatus +SecCmsSignedDataDecodeAfterEnd(SecCmsSignedDataRef sigd) +{ + SecCmsSignerInfoRef *signerinfos; + int i; + + signerinfos = sigd->signerInfos; + + /* set cmsg and sigd backpointers for all the signerinfos */ + if (signerinfos) { + for (i = 0; signerinfos[i] != NULL; i++) { + signerinfos[i]->cmsg = sigd->cmsg; + signerinfos[i]->sigd = sigd; + } + } + + return SECSuccess; +} + +/* + * SecCmsSignedDataGetSignerInfos - retrieve the SignedData's signer list + */ +SecCmsSignerInfoRef * +SecCmsSignedDataGetSignerInfos(SecCmsSignedDataRef sigd) +{ + return sigd->signerInfos; +} + +int +SecCmsSignedDataSignerInfoCount(SecCmsSignedDataRef sigd) +{ + return SecCmsArrayCount((void **)sigd->signerInfos); +} + +SecCmsSignerInfoRef +SecCmsSignedDataGetSignerInfo(SecCmsSignedDataRef sigd, int i) +{ + return sigd->signerInfos[i]; +} + +/* + * SecCmsSignedDataGetDigestAlgs - retrieve the SignedData's digest algorithm list + */ +SECAlgorithmID ** +SecCmsSignedDataGetDigestAlgs(SecCmsSignedDataRef sigd) +{ + return sigd->digestAlgorithms; +} + +/* + * SecCmsSignedDataGetContentInfo - return pointer to this signedData's contentinfo + */ +SecCmsContentInfoRef +SecCmsSignedDataGetContentInfo(SecCmsSignedDataRef sigd) +{ + return &(sigd->contentInfo); +} + +/* + * SecCmsSignedDataGetCertificateList - retrieve the SignedData's certificate list + */ +CSSM_DATA_PTR * +SecCmsSignedDataGetCertificateList(SecCmsSignedDataRef sigd) +{ + return sigd->rawCerts; +} + +OSStatus +SecCmsSignedDataImportCerts(SecCmsSignedDataRef sigd, SecKeychainRef keychain, + SECCertUsage certusage, Boolean keepcerts) +{ + int certcount; + OSStatus rv; + int i; + + certcount = SecCmsArrayCount((void **)sigd->rawCerts); + + rv = CERT_ImportCerts(keychain, certusage, certcount, sigd->rawCerts, NULL, + keepcerts, PR_FALSE, NULL); + + /* XXX CRL handling */ + + if (sigd->signerInfos != NULL) { + /* fill in all signerinfo's certs */ + for (i = 0; sigd->signerInfos[i] != NULL; i++) + (void)SecCmsSignerInfoGetSigningCertificate(sigd->signerInfos[i], keychain); + } + + return rv; +} + +/* + * XXX the digests need to be passed in BETWEEN the decoding and the verification in case + * of external signatures! + */ + +/* + * SecCmsSignedDataVerifySignerInfo - check the signatures. + * + * The digests were either calculated during decoding (and are stored in the + * signedData itself) or set after decoding using SecCmsSignedDataSetDigests. + * + * The verification checks if the signing cert is valid and has a trusted chain + * for the purpose specified by "policies". + * + * If trustRef is NULL the cert chain is verified and the VerificationStatus is set accordingly. + * Otherwise a SecTrust object is returned for the caller to evaluate using SecTrustEvaluate(). + */ +OSStatus +SecCmsSignedDataVerifySignerInfo(SecCmsSignedDataRef sigd, int i, + SecKeychainRef keychainOrArray, CFTypeRef policies, SecTrustRef *trustRef) +{ + SecCmsSignerInfoRef signerinfo; + SecCmsContentInfoRef cinfo; + SECOidData *algiddata; + CSSM_DATA_PTR contentType, digest; + OSStatus status, status2; + + cinfo = &(sigd->contentInfo); + + signerinfo = sigd->signerInfos[i]; + + /* Signature or digest level verificationStatus errors should supercede + certificate level errors, so check the digest and signature first. */ + + /* Find digest and contentType for signerinfo */ + algiddata = SecCmsSignerInfoGetDigestAlg(signerinfo); + if (algiddata == NULL) { + return errSecInternalError; // shouldn't have happened, this is likely due to corrupted data + } + + digest = SecCmsSignedDataGetDigestByAlgTag(sigd, algiddata->offset); + if(digest == NULL) { + /* + * No digests; this probably had detached content the caller has to + * deal with. + * FIXME: need some error return for this (as well as many + * other places in this library). + */ + return errSecDataNotAvailable; + } + contentType = SecCmsContentInfoGetContentTypeOID(cinfo); + + /* verify signature */ + CFTypeRef timeStampPolicies=SecPolicyCreateAppleTimeStampingAndRevocationPolicies(policies); + status = SecCmsSignerInfoVerifyWithPolicy(signerinfo, timeStampPolicies, digest, contentType); + CFReleaseSafe(timeStampPolicies); + + /* Now verify the certificate. We do this even if the signature failed to verify so we can + return a trustRef to the caller for display purposes. */ + status2 = SecCmsSignerInfoVerifyCertificate(signerinfo, keychainOrArray, + policies, trustRef); + dprintf("SecCmsSignedDataVerifySignerInfo: status %d status2 %d\n", (int) status, (int)status2); + /* The error from SecCmsSignerInfoVerify() supercedes error from SecCmsSignerInfoVerifyCertificate(). */ + if (status) + return status; + + return status2; +} + +/* + * SecCmsSignedDataVerifyCertsOnly - verify the certs in a certs-only message + */ +OSStatus +SecCmsSignedDataVerifyCertsOnly(SecCmsSignedDataRef sigd, + SecKeychainRef keychainOrArray, + CFTypeRef policies) +{ + SecCertificateRef cert; + OSStatus rv = SECSuccess; + int i; + int count; + + if (!sigd || !keychainOrArray || !sigd->rawCerts) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + count = SecCmsArrayCount((void**)sigd->rawCerts); + for (i=0; i < count; i++) { + if (sigd->certs && CFArrayGetCount(sigd->certs) > i) { + cert = (SecCertificateRef)CFArrayGetValueAtIndex(sigd->certs, i); + CFRetain(cert); + } else { + cert = CERT_FindCertByDERCert(keychainOrArray, sigd->rawCerts[i]); + if (!cert) { + rv = SECFailure; + break; + } + } + rv |= CERT_VerifyCert(keychainOrArray, cert, sigd->rawCerts, + policies, CFAbsoluteTimeGetCurrent(), NULL); + CFRelease(cert); + } + + return rv; +} + +/* + * SecCmsSignedDataHasDigests - see if we have digests in place + */ +Boolean +SecCmsSignedDataHasDigests(SecCmsSignedDataRef sigd) +{ + return (sigd->digests != NULL); +} + +OSStatus +SecCmsSignedDataAddCertList(SecCmsSignedDataRef sigd, CFArrayRef certlist) +{ + PORT_Assert(certlist != NULL); + + if (certlist == NULL) + return SECFailure; + + if (!sigd->certs) + sigd->certs = CFArrayCreateMutableCopy(NULL, 0, certlist); + else + { + CFRange certlistRange = { 0, CFArrayGetCount(certlist) }; + CFArrayAppendArray(sigd->certs, certlist, certlistRange); + } + + return SECSuccess; +} + +/* + * SecCmsSignedDataAddCertChain - add cert and its entire chain to the set of certs + */ +OSStatus +SecCmsSignedDataAddCertChain(SecCmsSignedDataRef sigd, SecCertificateRef cert) +{ + CFArrayRef certlist; + SECCertUsage usage; + OSStatus rv; + + usage = certUsageEmailSigner; + + /* do not include root */ + certlist = CERT_CertChainFromCert(cert, usage, PR_FALSE); + if (certlist == NULL) + return SECFailure; + + rv = SecCmsSignedDataAddCertList(sigd, certlist); + CFRelease(certlist); + + return rv; +} + +OSStatus +SecCmsSignedDataAddCertificate(SecCmsSignedDataRef sigd, SecCertificateRef cert) +{ + PORT_Assert(cert != NULL); + + if (cert == NULL) + return SECFailure; + + if (!sigd->certs) + sigd->certs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + + CFArrayAppendValue(sigd->certs, cert); + + return SECSuccess; +} + +Boolean +SecCmsSignedDataContainsCertsOrCrls(SecCmsSignedDataRef sigd) +{ + if (sigd->rawCerts != NULL && sigd->rawCerts[0] != NULL) + return PR_TRUE; + else if (sigd->rawCrls != NULL && sigd->rawCrls[0] != NULL) + return PR_TRUE; + else + return PR_FALSE; +} + +OSStatus +SecCmsSignedDataAddSignerInfo(SecCmsSignedDataRef sigd, + SecCmsSignerInfoRef signerinfo) +{ + void *mark; + OSStatus rv; + SECOidTag digestalgtag; + PLArenaPool *poolp; + + poolp = sigd->cmsg->poolp; + + mark = PORT_ArenaMark(poolp); + + /* add signerinfo */ + rv = SecCmsArrayAdd(poolp, (void ***)&(sigd->signerInfos), (void *)signerinfo); + if (rv != SECSuccess) + goto loser; + + signerinfo->sigd = sigd; + + /* + * add empty digest + * Empty because we don't have it yet. Either it gets created during encoding + * (if the data is present) or has to be set externally. + * XXX maybe pass it in optionally? + */ + digestalgtag = SecCmsSignerInfoGetDigestAlgTag(signerinfo); + rv = SecCmsSignedDataSetDigestValue(sigd, digestalgtag, NULL); + if (rv != SECSuccess) + goto loser; + + /* + * The last thing to get consistency would be adding the digest. + */ + + PORT_ArenaUnmark(poolp, mark); + return SECSuccess; + +loser: + PORT_ArenaRelease (poolp, mark); + return SECFailure; +} + +CSSM_DATA_PTR +SecCmsSignedDataGetDigestByAlgTag(SecCmsSignedDataRef sigd, SECOidTag algtag) +{ + int idx; + + if(sigd->digests == NULL) { + return NULL; + } + idx = SecCmsAlgArrayGetIndexByAlgTag(sigd->digestAlgorithms, algtag); + return sigd->digests[idx]; +} + +/* + * SecCmsSignedDataSetDigests - set a signedData's digests member + * + * "digestalgs" - array of digest algorithm IDs + * "digests" - array of digests corresponding to the digest algorithms + */ +OSStatus +SecCmsSignedDataSetDigests(SecCmsSignedDataRef sigd, + SECAlgorithmID **digestalgs, + CSSM_DATA_PTR *digests) +{ + int cnt, i, idx; + + if (sigd->digestAlgorithms == NULL) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + /* we assume that the digests array is just not there yet */ + PORT_Assert(sigd->digests == NULL); + if (sigd->digests != NULL) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + + /* now allocate one (same size as digestAlgorithms) */ + cnt = SecCmsArrayCount((void **)sigd->digestAlgorithms); + sigd->digests = PORT_ArenaZAlloc(sigd->cmsg->poolp, (cnt + 1) * sizeof(CSSM_DATA_PTR)); + if (sigd->digests == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + return SECFailure; + } + + for (i = 0; sigd->digestAlgorithms[i] != NULL; i++) { + /* try to find the sigd's i'th digest algorithm in the array we passed in */ + idx = SecCmsAlgArrayGetIndexByAlgID(digestalgs, sigd->digestAlgorithms[i]); + if (idx < 0) { + PORT_SetError(SEC_ERROR_DIGEST_NOT_FOUND); + return SECFailure; + } + + /* found it - now set it */ + if ((sigd->digests[i] = SECITEM_AllocItem(sigd->cmsg->poolp, NULL, 0)) == NULL || + SECITEM_CopyItem(sigd->cmsg->poolp, sigd->digests[i], digests[idx]) != SECSuccess) + { + PORT_SetError(SEC_ERROR_NO_MEMORY); + return SECFailure; + } + } + return SECSuccess; +} + +OSStatus +SecCmsSignedDataSetDigestValue(SecCmsSignedDataRef sigd, + SECOidTag digestalgtag, + CSSM_DATA_PTR digestdata) +{ + CSSM_DATA_PTR digest = NULL; + PLArenaPool *poolp; + void *mark; + int n, cnt; + + poolp = sigd->cmsg->poolp; + + mark = PORT_ArenaMark(poolp); + + + if (digestdata) { + digest = (CSSM_DATA_PTR) PORT_ArenaZAlloc(poolp,sizeof(CSSM_DATA)); + + /* copy digestdata item to arena (in case we have it and are not only making room) */ + if (SECITEM_CopyItem(poolp, digest, digestdata) != SECSuccess) + goto loser; + } + + /* now allocate one (same size as digestAlgorithms) */ + if (sigd->digests == NULL) { + cnt = SecCmsArrayCount((void **)sigd->digestAlgorithms); + sigd->digests = PORT_ArenaZAlloc(sigd->cmsg->poolp, (cnt + 1) * sizeof(CSSM_DATA_PTR)); + if (sigd->digests == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + return SECFailure; + } + } + + n = -1; + if (sigd->digestAlgorithms != NULL) + n = SecCmsAlgArrayGetIndexByAlgTag(sigd->digestAlgorithms, digestalgtag); + + /* if not found, add a digest */ + if (n < 0) { + if (SecCmsSignedDataAddDigest((SecArenaPoolRef)poolp, sigd, digestalgtag, digest) != SECSuccess) + goto loser; + } else { + /* replace NULL pointer with digest item (and leak previous value) */ + sigd->digests[n] = digest; + } + + PORT_ArenaUnmark(poolp, mark); + return SECSuccess; + +loser: + PORT_ArenaRelease(poolp, mark); + return SECFailure; +} + +OSStatus +SecCmsSignedDataAddDigest(SecArenaPoolRef pool, + SecCmsSignedDataRef sigd, + SECOidTag digestalgtag, + CSSM_DATA_PTR digest) +{ + PRArenaPool *poolp = (PRArenaPool *)pool; + SECAlgorithmID *digestalg; + void *mark; + + mark = PORT_ArenaMark(poolp); + + digestalg = PORT_ArenaZAlloc(poolp, sizeof(SECAlgorithmID)); + if (digestalg == NULL) + goto loser; + + if (SECOID_SetAlgorithmID (poolp, digestalg, digestalgtag, NULL) != SECSuccess) /* no params */ + goto loser; + + if (SecCmsArrayAdd(poolp, (void ***)&(sigd->digestAlgorithms), (void *)digestalg) != SECSuccess || + /* even if digest is NULL, add dummy to have same-size array */ + SecCmsArrayAdd(poolp, (void ***)&(sigd->digests), (void *)digest) != SECSuccess) + { + goto loser; + } + + PORT_ArenaUnmark(poolp, mark); + return SECSuccess; + +loser: + PORT_ArenaRelease(poolp, mark); + return SECFailure; +} + +CSSM_DATA_PTR +SecCmsSignedDataGetDigestValue(SecCmsSignedDataRef sigd, SECOidTag digestalgtag) +{ + int n; + + if (sigd->digestAlgorithms == NULL) + return NULL; + + n = SecCmsAlgArrayGetIndexByAlgTag(sigd->digestAlgorithms, digestalgtag); + + return (n < 0) ? NULL : sigd->digests[n]; +} + +/* ============================================================================= + * Misc. utility functions + */ + +/* + * SecCmsSignedDataCreateCertsOnly - create a certs-only SignedData. + * + * cert - base certificates that will be included + * include_chain - if true, include the complete cert chain for cert + * + * More certs and chains can be added via AddCertificate and AddCertChain. + * + * An error results in a return value of NULL and an error set. + * + * XXXX CRLs + */ +SecCmsSignedDataRef +SecCmsSignedDataCreateCertsOnly(SecCmsMessageRef cmsg, SecCertificateRef cert, Boolean include_chain) +{ + SecCmsSignedDataRef sigd; + void *mark; + PLArenaPool *poolp; + OSStatus rv; + + poolp = cmsg->poolp; + mark = PORT_ArenaMark(poolp); + + sigd = SecCmsSignedDataCreate(cmsg); + if (sigd == NULL) + goto loser; + + /* no signerinfos, thus no digestAlgorithms */ + + /* but certs */ + if (include_chain) { + rv = SecCmsSignedDataAddCertChain(sigd, cert); + } else { + rv = SecCmsSignedDataAddCertificate(sigd, cert); + } + if (rv != SECSuccess) + goto loser; + + /* RFC2630 5.2 sez: + * In the degenerate case where there are no signers, the + * EncapsulatedContentInfo value being "signed" is irrelevant. In this + * case, the content type within the EncapsulatedContentInfo value being + * "signed" should be id-data (as defined in section 4), and the content + * field of the EncapsulatedContentInfo value should be omitted. + */ + rv = SecCmsContentInfoSetContentData(cmsg, &(sigd->contentInfo), NULL, PR_TRUE); + if (rv != SECSuccess) + goto loser; + + PORT_ArenaUnmark(poolp, mark); + return sigd; + +loser: + if (sigd) + SecCmsSignedDataDestroy(sigd); + PORT_ArenaRelease(poolp, mark); + return NULL; +} + +/* + * Get SecCmsSignedDataRawCerts - obtain raw certs as a NULL_terminated array + * of pointers. + */ +extern OSStatus SecCmsSignedDataRawCerts(SecCmsSignedDataRef sigd, + CSSM_DATA_PTR **rawCerts) +{ + *rawCerts = sigd->rawCerts; + return noErr; +} + +/* TODO: + * SecCmsSignerInfoGetReceiptRequest() + * SecCmsSignedDataHasReceiptRequest() + * easy way to iterate over signers + */ + diff --git a/Security/libsecurity_smime/lib/cmssiginfo.c b/Security/libsecurity_smime/lib/cmssiginfo.c new file mode 100644 index 00000000..1913239b --- /dev/null +++ b/Security/libsecurity_smime/lib/cmssiginfo.c @@ -0,0 +1,1429 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * CMS signerInfo methods. + */ + +#include +#include "SecSMIMEPriv.h" + +#include "cmslocal.h" + +#include "cert.h" +#include "secitem.h" +#include "secoid.h" +#include "cryptohi.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tsaSupport.h" +#include "tsaSupportPriv.h" + +#define HIDIGIT(v) (((v) / 10) + '0') +#define LODIGIT(v) (((v) % 10) + '0') + +#define ISDIGIT(dig) (((dig) >= '0') && ((dig) <= '9')) +#define CAPTURE(var,p,label) \ +{ \ + if (!ISDIGIT((p)[0]) || !ISDIGIT((p)[1])) goto label; \ + (var) = ((p)[0] - '0') * 10 + ((p)[1] - '0'); \ +} + +#ifndef NDEBUG +#define SIGINFO_DEBUG 1 +#endif + +#if SIGINFO_DEBUG +#define dprintf(args...) printf(args) +#else +#define dprintf(args...) +#endif + +#if RELEASECOUNTDEBUG +#define dprintfRC(args...) dprintf(args) +#else +#define dprintfRC(args...) +#endif + +static OSStatus +DER_UTCTimeToCFDate(const CSSM_DATA_PTR utcTime, CFAbsoluteTime *date) +{ + CFGregorianDate gdate; + char *string = (char *)utcTime->Data; + long year, month, mday, hour, minute, second, hourOff, minOff; + CFTimeZoneRef timeZone; + + /* Verify time is formatted properly and capture information */ + second = 0; + hourOff = 0; + minOff = 0; + CAPTURE(year,string+0,loser); + if (year < 50) { + /* ASSUME that year # is in the 2000's, not the 1900's */ + year += 100; + } + CAPTURE(month,string+2,loser); + if ((month == 0) || (month > 12)) goto loser; + CAPTURE(mday,string+4,loser); + if ((mday == 0) || (mday > 31)) goto loser; + CAPTURE(hour,string+6,loser); + if (hour > 23) goto loser; + CAPTURE(minute,string+8,loser); + if (minute > 59) goto loser; + if (ISDIGIT(string[10])) { + CAPTURE(second,string+10,loser); + if (second > 59) goto loser; + string += 2; + } + if (string[10] == '+') { + CAPTURE(hourOff,string+11,loser); + if (hourOff > 23) goto loser; + CAPTURE(minOff,string+13,loser); + if (minOff > 59) goto loser; + } else if (string[10] == '-') { + CAPTURE(hourOff,string+11,loser); + if (hourOff > 23) goto loser; + hourOff = -hourOff; + CAPTURE(minOff,string+13,loser); + if (minOff > 59) goto loser; + minOff = -minOff; + } else if (string[10] != 'Z') { + goto loser; + } + + gdate.year = (SInt32)(year + 1900); + gdate.month = month; + gdate.day = mday; + gdate.hour = hour; + gdate.minute = minute; + gdate.second = second; + + if (hourOff == 0 && minOff == 0) + timeZone = NULL; /* GMT */ + else + { + timeZone = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, (hourOff * 60 + minOff) * 60); + } + + *date = CFGregorianDateGetAbsoluteTime(gdate, timeZone); + if (timeZone) + CFRelease(timeZone); + + return SECSuccess; + +loser: + return SECFailure; +} + +static OSStatus +DER_CFDateToUTCTime(CFAbsoluteTime date, CSSM_DATA_PTR utcTime) +{ + CFGregorianDate gdate = CFAbsoluteTimeGetGregorianDate(date, NULL /* GMT */); + unsigned char *d; + SInt8 second; + + utcTime->Length = 13; + utcTime->Data = d = PORT_Alloc(13); + if (!utcTime->Data) + return SECFailure; + + /* UTC time does not handle the years before 1950 */ + if (gdate.year < 1950) + return SECFailure; + + /* remove the century since it's added to the year by the + CFAbsoluteTimeGetGregorianDate routine, but is not needed for UTC time */ + gdate.year %= 100; + second = gdate.second + 0.5; + + d[0] = HIDIGIT(gdate.year); + d[1] = LODIGIT(gdate.year); + d[2] = HIDIGIT(gdate.month); + d[3] = LODIGIT(gdate.month); + d[4] = HIDIGIT(gdate.day); + d[5] = LODIGIT(gdate.day); + d[6] = HIDIGIT(gdate.hour); + d[7] = LODIGIT(gdate.hour); + d[8] = HIDIGIT(gdate.minute); + d[9] = LODIGIT(gdate.minute); + d[10] = HIDIGIT(second); + d[11] = LODIGIT(second); + d[12] = 'Z'; + return SECSuccess; +} + +/* ============================================================================= + * SIGNERINFO + */ +SecCmsSignerInfoRef +nss_cmssignerinfo_create(SecCmsMessageRef cmsg, SecCmsSignerIDSelector type, SecCertificateRef cert, CSSM_DATA_PTR subjKeyID, SecPublicKeyRef pubKey, SecPrivateKeyRef signingKey, SECOidTag digestalgtag); + +SecCmsSignerInfoRef +SecCmsSignerInfoCreateWithSubjKeyID(SecCmsMessageRef cmsg, CSSM_DATA_PTR subjKeyID, SecPublicKeyRef pubKey, SecPrivateKeyRef signingKey, SECOidTag digestalgtag) +{ + return nss_cmssignerinfo_create(cmsg, SecCmsSignerIDSubjectKeyID, NULL, subjKeyID, pubKey, signingKey, digestalgtag); +} + +SecCmsSignerInfoRef +SecCmsSignerInfoCreate(SecCmsMessageRef cmsg, SecIdentityRef identity, SECOidTag digestalgtag) +{ + SecCmsSignerInfoRef signerInfo = NULL; + SecCertificateRef cert = NULL; + SecPrivateKeyRef signingKey = NULL; + + if (SecIdentityCopyCertificate(identity, &cert)) + goto loser; + if (SecIdentityCopyPrivateKey(identity, &signingKey)) + goto loser; + + signerInfo = nss_cmssignerinfo_create(cmsg, SecCmsSignerIDIssuerSN, cert, NULL, NULL, signingKey, digestalgtag); + +loser: + if (cert) + CFRelease(cert); + if (signingKey) + CFRelease(signingKey); + + return signerInfo; +} + +SecCmsSignerInfoRef +nss_cmssignerinfo_create(SecCmsMessageRef cmsg, SecCmsSignerIDSelector type, SecCertificateRef cert, CSSM_DATA_PTR subjKeyID, SecPublicKeyRef pubKey, SecPrivateKeyRef signingKey, SECOidTag digestalgtag) +{ + void *mark; + SecCmsSignerInfoRef signerinfo; + int version; + PLArenaPool *poolp; + + poolp = cmsg->poolp; + + mark = PORT_ArenaMark(poolp); + + signerinfo = (SecCmsSignerInfoRef)PORT_ArenaZAlloc(poolp, sizeof(SecCmsSignerInfo)); + if (signerinfo == NULL) { + PORT_ArenaRelease(poolp, mark); + return NULL; + } + + + signerinfo->cmsg = cmsg; + + switch(type) { + case SecCmsSignerIDIssuerSN: + signerinfo->signerIdentifier.identifierType = SecCmsSignerIDIssuerSN; + if ((signerinfo->cert = CERT_DupCertificate(cert)) == NULL) + goto loser; + if ((signerinfo->signerIdentifier.id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert)) == NULL) + goto loser; + dprintfRC("nss_cmssignerinfo_create: SecCmsSignerIDIssuerSN: cert.rc %d\n", + (int)CFGetRetainCount(signerinfo->cert)); + break; + case SecCmsSignerIDSubjectKeyID: + signerinfo->signerIdentifier.identifierType = SecCmsSignerIDSubjectKeyID; + PORT_Assert(subjKeyID); + if (!subjKeyID) + goto loser; + signerinfo->signerIdentifier.id.subjectKeyID = PORT_ArenaNew(poolp, CSSM_DATA); + SECITEM_CopyItem(poolp, signerinfo->signerIdentifier.id.subjectKeyID, + subjKeyID); + signerinfo->pubKey = SECKEY_CopyPublicKey(pubKey); + if (!signerinfo->pubKey) + goto loser; + break; + default: + goto loser; + } + + if (!signingKey) + goto loser; + + signerinfo->signingKey = SECKEY_CopyPrivateKey(signingKey); + if (!signerinfo->signingKey) + goto loser; + + /* set version right now */ + version = SEC_CMS_SIGNER_INFO_VERSION_ISSUERSN; + /* RFC2630 5.3 "version is the syntax version number. If the .... " */ + if (signerinfo->signerIdentifier.identifierType == SecCmsSignerIDSubjectKeyID) + version = SEC_CMS_SIGNER_INFO_VERSION_SUBJKEY; + (void)SEC_ASN1EncodeInteger(poolp, &(signerinfo->version), (long)version); + + if (SECOID_SetAlgorithmID(poolp, &signerinfo->digestAlg, digestalgtag, NULL) != SECSuccess) + goto loser; + + PORT_ArenaUnmark(poolp, mark); + return signerinfo; + +loser: + PORT_ArenaRelease(poolp, mark); + return NULL; +} + +/* + * SecCmsSignerInfoDestroy - destroy a SignerInfo data structure + */ +void +SecCmsSignerInfoDestroy(SecCmsSignerInfoRef si) +{ + if (si->cert != NULL) { + dprintfRC("SecCmsSignerInfoDestroy top: certp %p cert.rc %d\n", + si->cert, (int)CFGetRetainCount(si->cert)); + CERT_DestroyCertificate(si->cert); + } + if (si->certList != NULL) { + dprintfRC("SecCmsSignerInfoDestroy top: certList.rc %d\n", + (int)CFGetRetainCount(si->certList)); + CFRelease(si->certList); + } + if (si->timestampCertList != NULL) { + dprintfRC("SecCmsSignerInfoDestroy top: timestampCertList.rc %d\n", + (int)CFGetRetainCount(si->timestampCertList)); + CFRelease(si->timestampCertList); + } + /* XXX storage ??? */ +} + +/* + * SecCmsSignerInfoSign - sign something + * + */ +OSStatus +SecCmsSignerInfoSign(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR digest, CSSM_DATA_PTR contentType) +{ + SecCertificateRef cert; + SecPrivateKeyRef privkey = NULL; + SECOidTag digestalgtag; + SECOidTag pubkAlgTag; + CSSM_DATA signature = { 0 }; + OSStatus rv; + PLArenaPool *poolp, *tmppoolp; + const SECAlgorithmID *algID; + SECAlgorithmID freeAlgID; + //CERTSubjectPublicKeyInfo *spki; + + PORT_Assert (digest != NULL); + + poolp = signerinfo->cmsg->poolp; + + switch (signerinfo->signerIdentifier.identifierType) { + case SecCmsSignerIDIssuerSN: + privkey = signerinfo->signingKey; + signerinfo->signingKey = NULL; + cert = signerinfo->cert; + if (SecCertificateGetAlgorithmID(cert,&algID)) { + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + goto loser; + } + break; + case SecCmsSignerIDSubjectKeyID: + privkey = signerinfo->signingKey; + signerinfo->signingKey = NULL; +#if 0 + spki = SECKEY_CreateSubjectPublicKeyInfo(signerinfo->pubKey); + SECKEY_DestroyPublicKey(signerinfo->pubKey); + signerinfo->pubKey = NULL; + SECOID_CopyAlgorithmID(NULL, &freeAlgID, &spki->algorithm); + SECKEY_DestroySubjectPublicKeyInfo(spki); + algID = &freeAlgID; +#else + if (SecKeyGetAlgorithmID(signerinfo->pubKey,&algID)) { + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + goto loser; + } + CFRelease(signerinfo->pubKey); + signerinfo->pubKey = NULL; +#endif + break; + default: + PORT_SetError(SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE); + goto loser; + } + digestalgtag = SecCmsSignerInfoGetDigestAlgTag(signerinfo); + /* + * XXX I think there should be a cert-level interface for this, + * so that I do not have to know about subjectPublicKeyInfo... + */ + pubkAlgTag = SECOID_GetAlgorithmTag(algID); + if (signerinfo->signerIdentifier.identifierType == SecCmsSignerIDSubjectKeyID) { + SECOID_DestroyAlgorithmID(&freeAlgID, PR_FALSE); + } + +#if 0 + // @@@ Not yet + /* Fortezza MISSI have weird signature formats. + * Map them to standard DSA formats + */ + pubkAlgTag = PK11_FortezzaMapSig(pubkAlgTag); +#endif + + if (signerinfo->authAttr != NULL) { + CSSM_DATA encoded_attrs; + + /* find and fill in the message digest attribute. */ + rv = SecCmsAttributeArraySetAttr(poolp, &(signerinfo->authAttr), + SEC_OID_PKCS9_MESSAGE_DIGEST, digest, PR_FALSE); + if (rv != SECSuccess) + goto loser; + + if (contentType != NULL) { + /* if the caller wants us to, find and fill in the content type attribute. */ + rv = SecCmsAttributeArraySetAttr(poolp, &(signerinfo->authAttr), + SEC_OID_PKCS9_CONTENT_TYPE, contentType, PR_FALSE); + if (rv != SECSuccess) + goto loser; + } + + if ((tmppoolp = PORT_NewArena (1024)) == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + /* + * Before encoding, reorder the attributes so that when they + * are encoded, they will be conforming DER, which is required + * to have a specific order and that is what must be used for + * the hash/signature. We do this here, rather than building + * it into EncodeAttributes, because we do not want to do + * such reordering on incoming messages (which also uses + * EncodeAttributes) or our old signatures (and other "broken" + * implementations) will not verify. So, we want to guarantee + * that we send out good DER encodings of attributes, but not + * to expect to receive them. + */ + if (SecCmsAttributeArrayReorder(signerinfo->authAttr) != SECSuccess) + goto loser; + + encoded_attrs.Data = NULL; + encoded_attrs.Length = 0; + if (SecCmsAttributeArrayEncode(tmppoolp, &(signerinfo->authAttr), + &encoded_attrs) == NULL) + goto loser; + + rv = SEC_SignData(&signature, encoded_attrs.Data, (int)encoded_attrs.Length, + privkey, digestalgtag, pubkAlgTag); + PORT_FreeArena(tmppoolp, PR_FALSE); /* awkward memory management :-( */ + } else { + rv = SGN_Digest(privkey, digestalgtag, pubkAlgTag, &signature, digest); + } + SECKEY_DestroyPrivateKey(privkey); + privkey = NULL; + + if (rv != SECSuccess) + goto loser; + + if (SECITEM_CopyItem(poolp, &(signerinfo->encDigest), &signature) + != SECSuccess) + goto loser; + + SECITEM_FreeItem(&signature, PR_FALSE); + + if(pubkAlgTag == SEC_OID_EC_PUBLIC_KEY) { + /* + * RFC 3278 section section 2.1.1 states that the signatureAlgorithm + * field contains the full ecdsa-with-SHA1 OID, not plain old ecPublicKey + * as would appear in other forms of signed datas. However Microsoft doesn't + * do this, it puts ecPublicKey there, and if we put ecdsa-with-SHA1 there, + * MS can't verify - presumably because it takes the digest of the digest + * before feeding it to ECDSA. + * We handle this with a preference; default if it's not there is + * "Microsoft compatibility mode". + */ + if(!SecCmsMsEcdsaCompatMode()) { + pubkAlgTag = SEC_OID_ECDSA_WithSHA1; + } + /* else violating the spec for compatibility */ + } + + if (SECOID_SetAlgorithmID(poolp, &(signerinfo->digestEncAlg), pubkAlgTag, + NULL) != SECSuccess) + goto loser; + + return SECSuccess; + +loser: + if (signature.Length != 0) + SECITEM_FreeItem (&signature, PR_FALSE); + if (privkey) + SECKEY_DestroyPrivateKey(privkey); + if((algID != NULL) & (algID != &freeAlgID)) { + /* this is dicey - this was actually mallocd by either SecCertificate or + * by SecKey...it all boils down to a free() in the end though. */ + SECOID_DestroyAlgorithmID((SECAlgorithmID *)algID, PR_FALSE); + } + return SECFailure; +} + +OSStatus +SecCmsSignerInfoVerifyCertificate(SecCmsSignerInfoRef signerinfo, SecKeychainRef keychainOrArray, + CFTypeRef policies, SecTrustRef *trustRef) +{ + SecCertificateRef cert; + CFAbsoluteTime stime; + OSStatus rv; + CSSM_DATA_PTR *otherCerts; + + if ((cert = SecCmsSignerInfoGetSigningCertificate(signerinfo, keychainOrArray)) == NULL) { + dprintf("SecCmsSignerInfoVerifyCertificate: no signing cert\n"); + signerinfo->verificationStatus = SecCmsVSSigningCertNotFound; + return SECFailure; + } + + /* + * Get and convert the signing time; if available, it will be used + * both on the cert verification and for importing the sender + * email profile. + */ + CFTypeRef timeStampPolicies=SecPolicyCreateAppleTimeStampingAndRevocationPolicies(policies); + if (SecCmsSignerInfoGetTimestampTimeWithPolicy(signerinfo, timeStampPolicies, &stime) != SECSuccess) + if (SecCmsSignerInfoGetSigningTime(signerinfo, &stime) != SECSuccess) + stime = CFAbsoluteTimeGetCurrent(); + CFReleaseSafe(timeStampPolicies); + + rv = SecCmsSignedDataRawCerts(signerinfo->sigd, &otherCerts); + if(rv) { + return rv; + } + rv = CERT_VerifyCert(keychainOrArray, cert, otherCerts, policies, stime, trustRef); + dprintfRC("SecCmsSignerInfoVerifyCertificate after vfy: certp %p cert.rc %d\n", + cert, (int)CFGetRetainCount(cert)); + if (rv || !trustRef) + { + if (PORT_GetError() == SEC_ERROR_UNTRUSTED_CERT) + { + /* Signature or digest level verificationStatus errors should supercede certificate level errors, so only change the verificationStatus if the status was GoodSignature. */ + if (signerinfo->verificationStatus == SecCmsVSGoodSignature) + signerinfo->verificationStatus = SecCmsVSSigningCertNotTrusted; + } + } + /* FIXME isn't this leaking the cert? */ + dprintf("SecCmsSignerInfoVerifyCertificate: CertVerify rtn %d\n", (int)rv); + return rv; +} + +static void debugShowSigningCertificate(SecCmsSignerInfoRef signerinfo) +{ +#if SIGINFO_DEBUG + CFStringRef cn = SecCmsSignerInfoGetSignerCommonName(signerinfo); + if (cn) + { + char *ccn = cfStringToChar(cn); + if (ccn) + { + dprintf("SecCmsSignerInfoVerify: cn: %s\n", ccn); + free(ccn); + } + CFRelease(cn); + } +#endif +} + +/* + * SecCmsSignerInfoVerify - verify the signature of a single SignerInfo + * + * Just verifies the signature. The assumption is that verification of the certificate + * is done already. + */ +OSStatus +SecCmsSignerInfoVerify(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR digest, CSSM_DATA_PTR contentType) +{ + return SecCmsSignerInfoVerifyWithPolicy(signerinfo,NULL, digest,contentType); +} + +OSStatus +SecCmsSignerInfoVerifyWithPolicy(SecCmsSignerInfoRef signerinfo,CFTypeRef timeStampPolicy, CSSM_DATA_PTR digest, CSSM_DATA_PTR contentType) +{ + SecPublicKeyRef publickey = NULL; + SecCmsAttribute *attr; + CSSM_DATA encoded_attrs; + SecCertificateRef cert; + SecCmsVerificationStatus vs = SecCmsVSUnverified; + PLArenaPool *poolp; + SECOidTag digestAlgTag, digestEncAlgTag; + + if (signerinfo == NULL) + return SECFailure; + + /* SecCmsSignerInfoGetSigningCertificate will fail if 2nd parm is NULL and */ + /* cert has not been verified */ + if ((cert = SecCmsSignerInfoGetSigningCertificate(signerinfo, NULL)) == NULL) { + dprintf("SecCmsSignerInfoVerify: no signing cert\n"); + vs = SecCmsVSSigningCertNotFound; + goto loser; + } + + dprintfRC("SecCmsSignerInfoVerify top: cert %p cert.rc %d\n", cert, (int)CFGetRetainCount(cert)); + + debugShowSigningCertificate(signerinfo); + + if (SecCertificateCopyPublicKey(cert, &publickey)) { + vs = SecCmsVSProcessingError; + goto loser; + } + + digestAlgTag = SECOID_GetAlgorithmTag(&(signerinfo->digestAlg)); + digestEncAlgTag = SECOID_GetAlgorithmTag(&(signerinfo->digestEncAlg)); + + /* + * Gross hack necessitated by RFC 3278 section 2.1.1, which states + * that the signature algorithm (here, digestEncAlg) contains ecdsa_with-SHA1, + * *not* (as in all other algorithms) the raw signature algorithm, e.g. + * pkcs1RSAEncryption. + */ + if(digestEncAlgTag == SEC_OID_ECDSA_WithSHA1) { + digestEncAlgTag = SEC_OID_EC_PUBLIC_KEY; + } + + if (!SecCmsArrayIsEmpty((void **)signerinfo->authAttr)) { + if (contentType) { + /* + * Check content type + * + * RFC2630 sez that if there are any authenticated attributes, + * then there must be one for content type which matches the + * content type of the content being signed, and there must + * be one for message digest which matches our message digest. + * So check these things first. + */ + if ((attr = SecCmsAttributeArrayFindAttrByOidTag(signerinfo->authAttr, + SEC_OID_PKCS9_CONTENT_TYPE, PR_TRUE)) == NULL) + { + vs = SecCmsVSMalformedSignature; + goto loser; + } + + if (SecCmsAttributeCompareValue(attr, contentType) == PR_FALSE) { + vs = SecCmsVSMalformedSignature; + goto loser; + } + } + + /* + * Check digest + */ + if ((attr = SecCmsAttributeArrayFindAttrByOidTag(signerinfo->authAttr, SEC_OID_PKCS9_MESSAGE_DIGEST, PR_TRUE)) == NULL) + { + vs = SecCmsVSMalformedSignature; + goto loser; + } + if (SecCmsAttributeCompareValue(attr, digest) == PR_FALSE) { + vs = SecCmsVSDigestMismatch; + goto loser; + } + + if ((poolp = PORT_NewArena (1024)) == NULL) { + vs = SecCmsVSProcessingError; + goto loser; + } + + /* + * Check signature + * + * The signature is based on a digest of the DER-encoded authenticated + * attributes. So, first we encode and then we digest/verify. + * we trust the decoder to have the attributes in the right (sorted) order + */ + encoded_attrs.Data = NULL; + encoded_attrs.Length = 0; + + if (SecCmsAttributeArrayEncode(poolp, &(signerinfo->authAttr), &encoded_attrs) == NULL || + encoded_attrs.Data == NULL || encoded_attrs.Length == 0) + { + vs = SecCmsVSProcessingError; + goto loser; + } + + vs = (VFY_VerifyData (encoded_attrs.Data, (int)encoded_attrs.Length, + publickey, &(signerinfo->encDigest), + digestAlgTag, digestEncAlgTag, + signerinfo->cmsg->pwfn_arg) != SECSuccess) ? SecCmsVSBadSignature : SecCmsVSGoodSignature; + + dprintf("VFY_VerifyData (authenticated attributes): %s\n", + (vs == SecCmsVSGoodSignature)?"SecCmsVSGoodSignature":"SecCmsVSBadSignature"); + + PORT_FreeArena(poolp, PR_FALSE); /* awkward memory management :-( */ + + } else { + CSSM_DATA_PTR sig; + + /* No authenticated attributes. The signature is based on the plain message digest. */ + sig = &(signerinfo->encDigest); + if (sig->Length == 0) + goto loser; + + vs = (VFY_VerifyDigest(digest, publickey, sig, + digestAlgTag, digestEncAlgTag, + signerinfo->cmsg->pwfn_arg) != SECSuccess) ? SecCmsVSBadSignature : SecCmsVSGoodSignature; + + dprintf("VFY_VerifyData (plain message digest): %s\n", + (vs == SecCmsVSGoodSignature)?"SecCmsVSGoodSignature":"SecCmsVSBadSignature"); + } + + if (!SecCmsArrayIsEmpty((void **)signerinfo->unAuthAttr)) + { + dprintf("found an unAuthAttr\n"); + OSStatus rux = SecCmsSignerInfoVerifyUnAuthAttrsWithPolicy(signerinfo,timeStampPolicy); + dprintf("SecCmsSignerInfoVerifyUnAuthAttrs Status: %ld\n", (long)rux); + if (rux) + goto loser; + } + + if (vs == SecCmsVSBadSignature) { + /* + * XXX Change the generic error into our specific one, because + * in that case we get a better explanation out of the Security + * Advisor. This is really a bug in our error strings (the + * "generic" error has a lousy/wrong message associated with it + * which assumes the signature verification was done for the + * purposes of checking the issuer signature on a certificate) + * but this is at least an easy workaround and/or in the + * Security Advisor, which specifically checks for the error + * SEC_ERROR_PKCS7_BAD_SIGNATURE and gives more explanation + * in that case but does not similarly check for + * SEC_ERROR_BAD_SIGNATURE. It probably should, but then would + * probably say the wrong thing in the case that it *was* the + * certificate signature check that failed during the cert + * verification done above. Our error handling is really a mess. + */ + if (PORT_GetError() == SEC_ERROR_BAD_SIGNATURE) + PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE); + } + + if (publickey != NULL) + CFRelease(publickey); + + signerinfo->verificationStatus = vs; + dprintfRC("SecCmsSignerInfoVerify end: cerp %p cert.rc %d\n", + cert, (int)CFGetRetainCount(cert)); + + dprintf("verificationStatus: %d\n", vs); + + return (vs == SecCmsVSGoodSignature) ? SECSuccess : SECFailure; + +loser: + if (publickey != NULL) + SECKEY_DestroyPublicKey (publickey); + + dprintf("verificationStatus2: %d\n", vs); + signerinfo->verificationStatus = vs; + + PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE); + return SECFailure; +} + +OSStatus +SecCmsSignerInfoVerifyUnAuthAttrs(SecCmsSignerInfoRef signerinfo) { + return SecCmsSignerInfoVerifyUnAuthAttrsWithPolicy(signerinfo, NULL); +} + +OSStatus +SecCmsSignerInfoVerifyUnAuthAttrsWithPolicy(SecCmsSignerInfoRef signerinfo,CFTypeRef timeStampPolicy) +{ + /* + unAuthAttr is an array of attributes; we expect to + see just one: the timestamp blob. If we have an unAuthAttr, + but don't see a timestamp, return an error since we have + no other cases where this would be present. + */ + + SecCmsAttribute *attr = NULL; + OSStatus status = SECFailure; + + require(signerinfo, xit); + attr = SecCmsAttributeArrayFindAttrByOidTag(signerinfo->unAuthAttr, + SEC_OID_PKCS9_TIMESTAMP_TOKEN, PR_TRUE); + if (attr == NULL) + { + status = errSecTimestampMissing; + goto xit; + } + + dprintf("found an id-ct-TSTInfo\n"); + // Don't check the nonce in this case + status = decodeTimeStampTokenWithPolicy(signerinfo, timeStampPolicy, (attr->values)[0], &signerinfo->encDigest, 0); +xit: + return status; +} + +CSSM_DATA * +SecCmsSignerInfoGetEncDigest(SecCmsSignerInfoRef signerinfo) +{ + return &signerinfo->encDigest; +} + +SecCmsVerificationStatus +SecCmsSignerInfoGetVerificationStatus(SecCmsSignerInfoRef signerinfo) +{ + return signerinfo->verificationStatus; +} + +SECOidData * +SecCmsSignerInfoGetDigestAlg(SecCmsSignerInfoRef signerinfo) +{ + return SECOID_FindOID (&(signerinfo->digestAlg.algorithm)); +} + +SECOidTag +SecCmsSignerInfoGetDigestAlgTag(SecCmsSignerInfoRef signerinfo) +{ + SECOidData *algdata; + + algdata = SECOID_FindOID (&(signerinfo->digestAlg.algorithm)); + if (algdata != NULL) + return algdata->offset; + else + return SEC_OID_UNKNOWN; +} + +CFArrayRef +SecCmsSignerInfoGetCertList(SecCmsSignerInfoRef signerinfo) +{ + dprintfRC("SecCmsSignerInfoGetCertList: certList.rc %d\n", + (int)CFGetRetainCount(signerinfo->certList)); + return signerinfo->certList; +} + +CFArrayRef +SecCmsSignerInfoGetTimestampCertList(SecCmsSignerInfoRef signerinfo) +{ + dprintfRC("SecCmsSignerInfoGetCertList: timestampCertList.rc %d\n", + (int)CFGetRetainCount(signerinfo->timestampCertList)); + return signerinfo->timestampCertList; +} + + + +int +SecCmsSignerInfoGetVersion(SecCmsSignerInfoRef signerinfo) +{ + unsigned long version; + + /* always take apart the CSSM_DATA */ + if (SEC_ASN1DecodeInteger(&(signerinfo->version), &version) != SECSuccess) + return 0; + else + return (int)version; +} + +/* + * SecCmsSignerInfoGetSigningTime - return the signing time, + * in UTCTime format, of a CMS signerInfo. + * + * sinfo - signerInfo data for this signer + * + * Returns a pointer to XXXX (what?) + * A return value of NULL is an error. + */ +OSStatus +SecCmsSignerInfoGetSigningTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *stime) +{ + SecCmsAttribute *attr; + CSSM_DATA_PTR value; + + if (sinfo == NULL) + return paramErr; + + if (sinfo->signingTime != 0) { + *stime = sinfo->signingTime; /* cached copy */ + return SECSuccess; + } + + attr = SecCmsAttributeArrayFindAttrByOidTag(sinfo->authAttr, SEC_OID_PKCS9_SIGNING_TIME, PR_TRUE); + /* XXXX multi-valued attributes NIH */ + if (attr == NULL || (value = SecCmsAttributeGetValue(attr)) == NULL) + return errSecSigningTimeMissing; + if (DER_UTCTimeToCFDate(value, stime) != SECSuccess) + return errSecSigningTimeMissing; + sinfo->signingTime = *stime; /* make cached copy */ + return SECSuccess; +} + +OSStatus +SecCmsSignerInfoGetTimestampTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *stime) +{ + return SecCmsSignerInfoGetTimestampTimeWithPolicy(sinfo, NULL, stime); +} + +OSStatus +SecCmsSignerInfoGetTimestampTimeWithPolicy(SecCmsSignerInfoRef sinfo, CFTypeRef timeStampPolicy, CFAbsoluteTime *stime) +{ + OSStatus status = paramErr; + + require(sinfo && stime, xit); + + if (sinfo->timestampTime != 0) + { + *stime = sinfo->timestampTime; /* cached copy */ + return noErr; + } + + // A bit heavyweight if haven't already called verify + status = SecCmsSignerInfoVerifyUnAuthAttrsWithPolicy(sinfo,timeStampPolicy); + *stime = sinfo->timestampTime; +xit: + return status; +} + +/* + * Return the signing cert of a CMS signerInfo. + * + * the certs in the enclosing SignedData must have been imported already + */ +SecCertificateRef +SecCmsSignerInfoGetSigningCertificate(SecCmsSignerInfoRef signerinfo, SecKeychainRef keychainOrArray) +{ + SecCertificateRef cert; + SecCmsSignerIdentifier *sid; + OSStatus ortn; + CSSM_DATA_PTR *rawCerts; + + if (signerinfo->cert != NULL) { + dprintfRC("SecCmsSignerInfoGetSigningCertificate top: cert %p cert.rc %d\n", + signerinfo->cert, (int)CFGetRetainCount(signerinfo->cert)); + return signerinfo->cert; + } + ortn = SecCmsSignedDataRawCerts(signerinfo->sigd, &rawCerts); + if(ortn) { + return NULL; + } + dprintf("SecCmsSignerInfoGetSigningCertificate: numRawCerts %d\n", + SecCmsArrayCount((void **)rawCerts)); + + /* + * This cert will also need to be freed, but since we save it + * in signerinfo for later, we do not want to destroy it when + * we leave this function -- we let the clean-up of the entire + * cinfo structure later do the destroy of this cert. + */ + sid = &signerinfo->signerIdentifier; + switch (sid->identifierType) { + case SecCmsSignerIDIssuerSN: + cert = CERT_FindCertByIssuerAndSN(keychainOrArray, rawCerts, signerinfo->cmsg->poolp, + sid->id.issuerAndSN); + break; + case SecCmsSignerIDSubjectKeyID: + cert = CERT_FindCertBySubjectKeyID(keychainOrArray, rawCerts, sid->id.subjectKeyID); + break; + default: + cert = NULL; + break; + } + + /* cert can be NULL at that point */ + signerinfo->cert = cert; /* earmark it */ + dprintfRC("SecCmsSignerInfoGetSigningCertificate end: certp %p cert.rc %d\n", + signerinfo->cert, (int)CFGetRetainCount(signerinfo->cert)); + + return cert; +} + +/* + * SecCmsSignerInfoGetSignerCommonName - return the common name of the signer + * + * sinfo - signerInfo data for this signer + * + * Returns a CFStringRef containing the common name of the signer. + * A return value of NULL is an error. + */ +CFStringRef +SecCmsSignerInfoGetSignerCommonName(SecCmsSignerInfoRef sinfo) +{ + SecCertificateRef signercert; + CFStringRef commonName = NULL; + + /* will fail if cert is not verified */ + if ((signercert = SecCmsSignerInfoGetSigningCertificate(sinfo, NULL)) == NULL) + return NULL; + + SecCertificateCopyCommonName(signercert, &commonName); + + return commonName; +} + +/* + * SecCmsSignerInfoGetSignerEmailAddress - return the email address of the signer + * + * sinfo - signerInfo data for this signer + * + * Returns a CFStringRef containing the name of the signer. + * A return value of NULL is an error. + */ +CFStringRef +SecCmsSignerInfoGetSignerEmailAddress(SecCmsSignerInfoRef sinfo) +{ + SecCertificateRef signercert; + CFStringRef emailAddress = NULL; + + if ((signercert = SecCmsSignerInfoGetSigningCertificate(sinfo, NULL)) == NULL) + return NULL; + + SecCertificateGetEmailAddress(signercert, &emailAddress); + + return emailAddress; +} + + +/* + * SecCmsSignerInfoAddAuthAttr - add an attribute to the + * authenticated (i.e. signed) attributes of "signerinfo". + */ +OSStatus +SecCmsSignerInfoAddAuthAttr(SecCmsSignerInfoRef signerinfo, SecCmsAttribute *attr) +{ + return SecCmsAttributeArrayAddAttr(signerinfo->cmsg->poolp, &(signerinfo->authAttr), attr); +} + +/* + * SecCmsSignerInfoAddUnauthAttr - add an attribute to the + * unauthenticated attributes of "signerinfo". + */ +OSStatus +SecCmsSignerInfoAddUnauthAttr(SecCmsSignerInfoRef signerinfo, SecCmsAttribute *attr) +{ + return SecCmsAttributeArrayAddAttr(signerinfo->cmsg->poolp, &(signerinfo->unAuthAttr), attr); +} + +/* + * SecCmsSignerInfoAddSigningTime - add the signing time to the + * authenticated (i.e. signed) attributes of "signerinfo". + * + * This is expected to be included in outgoing signed + * messages for email (S/MIME) but is likely useful in other situations. + * + * This should only be added once; a second call will do nothing. + * + * XXX This will probably just shove the current time into "signerinfo" + * but it will not actually get signed until the entire item is + * processed for encoding. Is this (expected to be small) delay okay? + */ +OSStatus +SecCmsSignerInfoAddSigningTime(SecCmsSignerInfoRef signerinfo, CFAbsoluteTime t) +{ + SecCmsAttribute *attr; + CSSM_DATA stime; + void *mark; + PLArenaPool *poolp; + + poolp = signerinfo->cmsg->poolp; + + mark = PORT_ArenaMark(poolp); + + /* create new signing time attribute */ + if (DER_CFDateToUTCTime(t, &stime) != SECSuccess) + goto loser; + + if ((attr = SecCmsAttributeCreate(poolp, SEC_OID_PKCS9_SIGNING_TIME, &stime, PR_FALSE)) == NULL) { + SECITEM_FreeItem (&stime, PR_FALSE); + goto loser; + } + + SECITEM_FreeItem (&stime, PR_FALSE); + + if (SecCmsSignerInfoAddAuthAttr(signerinfo, attr) != SECSuccess) + goto loser; + + PORT_ArenaUnmark (poolp, mark); + + return SECSuccess; + +loser: + PORT_ArenaRelease (poolp, mark); + return SECFailure; +} + +/* + * SecCmsSignerInfoAddSMIMECaps - add a SMIMECapabilities attribute to the + * authenticated (i.e. signed) attributes of "signerinfo". + * + * This is expected to be included in outgoing signed + * messages for email (S/MIME). + */ +OSStatus +SecCmsSignerInfoAddSMIMECaps(SecCmsSignerInfoRef signerinfo) +{ + SecCmsAttribute *attr; + CSSM_DATA_PTR smimecaps = NULL; + void *mark; + PLArenaPool *poolp; + + poolp = signerinfo->cmsg->poolp; + + mark = PORT_ArenaMark(poolp); + + smimecaps = SECITEM_AllocItem(poolp, NULL, 0); + if (smimecaps == NULL) + goto loser; + + /* create new signing time attribute */ +#if 1 + // @@@ We don't do Fortezza yet. + if (SecSMIMECreateSMIMECapabilities((SecArenaPoolRef)poolp, smimecaps, PR_FALSE) != SECSuccess) +#else + if (SecSMIMECreateSMIMECapabilities(poolp, smimecaps, + PK11_FortezzaHasKEA(signerinfo->cert)) != SECSuccess) +#endif + goto loser; + + if ((attr = SecCmsAttributeCreate(poolp, SEC_OID_PKCS9_SMIME_CAPABILITIES, smimecaps, PR_TRUE)) == NULL) + goto loser; + + if (SecCmsSignerInfoAddAuthAttr(signerinfo, attr) != SECSuccess) + goto loser; + + PORT_ArenaUnmark (poolp, mark); + return SECSuccess; + +loser: + PORT_ArenaRelease (poolp, mark); + return SECFailure; +} + +/* + * SecCmsSignerInfoAddSMIMEEncKeyPrefs - add a SMIMEEncryptionKeyPreferences attribute to the + * authenticated (i.e. signed) attributes of "signerinfo". + * + * This is expected to be included in outgoing signed messages for email (S/MIME). + */ +OSStatus +SecCmsSignerInfoAddSMIMEEncKeyPrefs(SecCmsSignerInfoRef signerinfo, SecCertificateRef cert, SecKeychainRef keychainOrArray) +{ + SecCmsAttribute *attr; + CSSM_DATA_PTR smimeekp = NULL; + void *mark; + PLArenaPool *poolp; + +#if 0 + CFTypeRef policy; + + /* verify this cert for encryption */ + policy = CERT_PolicyForCertUsage(certUsageEmailRecipient); + if (CERT_VerifyCert(keychainOrArray, cert, policy, CFAbsoluteTimeGetCurrent(), NULL) != SECSuccess) { + CFRelease(policy); + return SECFailure; + } + CFRelease(policy); +#endif + + poolp = signerinfo->cmsg->poolp; + mark = PORT_ArenaMark(poolp); + + smimeekp = SECITEM_AllocItem(poolp, NULL, 0); + if (smimeekp == NULL) + goto loser; + + /* create new signing time attribute */ + if (SecSMIMECreateSMIMEEncKeyPrefs((SecArenaPoolRef)poolp, smimeekp, cert) != SECSuccess) + goto loser; + + if ((attr = SecCmsAttributeCreate(poolp, SEC_OID_SMIME_ENCRYPTION_KEY_PREFERENCE, smimeekp, PR_TRUE)) == NULL) + goto loser; + + if (SecCmsSignerInfoAddAuthAttr(signerinfo, attr) != SECSuccess) + goto loser; + + PORT_ArenaUnmark (poolp, mark); + return SECSuccess; + +loser: + PORT_ArenaRelease (poolp, mark); + return SECFailure; +} + +/* + * SecCmsSignerInfoAddMSSMIMEEncKeyPrefs - add a SMIMEEncryptionKeyPreferences attribute to the + * authenticated (i.e. signed) attributes of "signerinfo", using the OID prefered by Microsoft. + * + * This is expected to be included in outgoing signed messages for email (S/MIME), + * if compatibility with Microsoft mail clients is wanted. + */ +OSStatus +SecCmsSignerInfoAddMSSMIMEEncKeyPrefs(SecCmsSignerInfoRef signerinfo, SecCertificateRef cert, SecKeychainRef keychainOrArray) +{ + SecCmsAttribute *attr; + CSSM_DATA_PTR smimeekp = NULL; + void *mark; + PLArenaPool *poolp; + +#if 0 + CFTypeRef policy; + + /* verify this cert for encryption */ + policy = CERT_PolicyForCertUsage(certUsageEmailRecipient); + if (CERT_VerifyCert(keychainOrArray, cert, policy, CFAbsoluteTimeGetCurrent(), NULL) != SECSuccess) { + CFRelease(policy); + return SECFailure; + } + CFRelease(policy); +#endif + + poolp = signerinfo->cmsg->poolp; + mark = PORT_ArenaMark(poolp); + + smimeekp = SECITEM_AllocItem(poolp, NULL, 0); + if (smimeekp == NULL) + goto loser; + + /* create new signing time attribute */ + if (SecSMIMECreateMSSMIMEEncKeyPrefs((SecArenaPoolRef)poolp, smimeekp, cert) != SECSuccess) + goto loser; + + if ((attr = SecCmsAttributeCreate(poolp, SEC_OID_MS_SMIME_ENCRYPTION_KEY_PREFERENCE, smimeekp, PR_TRUE)) == NULL) + goto loser; + + if (SecCmsSignerInfoAddAuthAttr(signerinfo, attr) != SECSuccess) + goto loser; + + PORT_ArenaUnmark (poolp, mark); + return SECSuccess; + +loser: + PORT_ArenaRelease (poolp, mark); + return SECFailure; +} + +/* + * SecCmsSignerInfoAddTimeStamp - add time stamp to the + * unauthenticated (i.e. unsigned) attributes of "signerinfo". + * + * This will initially be used for time stamping signed applications + * by using a Time Stamping Authority. It may also be included in outgoing signed + * messages for email (S/MIME), and may be useful in other situations. + * + * This should only be added once; a second call will do nothing. + * + */ + +/* +Countersignature attribute values have ASN.1 type Countersignature: + Countersignature ::= SignerInfo + Countersignature values have the same meaning as SignerInfo values + for ordinary signatures, except that: + 1. The signedAttributes field MUST NOT contain a content-type + attribute; there is no content type for countersignatures. + 2. The signedAttributes field MUST contain a message-digest + attribute if it contains any other attributes. + 3. The input to the message-digesting process is the contents octets + of the DER encoding of the signatureValue field of the SignerInfo + value with which the attribute is associated. +*/ + +/*! + @function + @abstract Create a timestamp unsigned attribute with a TimeStampToken. +*/ + +OSStatus +SecCmsSignerInfoAddTimeStamp(SecCmsSignerInfoRef signerinfo, CSSM_DATA *tstoken) +{ + SecCmsAttribute *attr; + PLArenaPool *poolp = signerinfo->cmsg->poolp; + void *mark = PORT_ArenaMark(poolp); + + // We have already encoded this ourselves, so last param is PR_TRUE + if ((attr = SecCmsAttributeCreate(poolp, SEC_OID_PKCS9_TIMESTAMP_TOKEN, tstoken, PR_TRUE)) == NULL) + goto loser; + + if (SecCmsSignerInfoAddUnauthAttr(signerinfo, attr) != SECSuccess) + goto loser; + + PORT_ArenaUnmark (poolp, mark); + + return SECSuccess; + +loser: + PORT_ArenaRelease (poolp, mark); + return SECFailure; +} + +/* + * SecCmsSignerInfoAddCounterSignature - countersign a signerinfo + * + * 1. digest the DER-encoded signature value of the original signerinfo + * 2. create new signerinfo with correct version, sid, digestAlg + * 3. add message-digest authAttr, but NO content-type + * 4. sign the authAttrs + * 5. DER-encode the new signerInfo + * 6. add the whole thing to original signerInfo's unAuthAttrs + * as a SEC_OID_PKCS9_COUNTER_SIGNATURE attribute + * + * XXXX give back the new signerinfo? + */ +OSStatus +SecCmsSignerInfoAddCounterSignature(SecCmsSignerInfoRef signerinfo, + SECOidTag digestalg, SecIdentityRef identity) +{ + /* XXXX TBD XXXX */ + return SECFailure; +} + +/* + * XXXX the following needs to be done in the S/MIME layer code + * after signature of a signerinfo is verified + */ +OSStatus +SecCmsSignerInfoSaveSMIMEProfile(SecCmsSignerInfoRef signerinfo) +{ + SecCertificateRef cert = NULL; + CSSM_DATA_PTR profile = NULL; + SecCmsAttribute *attr; + CSSM_DATA_PTR utc_stime = NULL; + CSSM_DATA_PTR ekp; + int save_error; + OSStatus rv; + Boolean must_free_cert = PR_FALSE; + OSStatus status; + SecKeychainRef keychainOrArray; + + status = SecKeychainCopyDefault(&keychainOrArray); + + /* sanity check - see if verification status is ok (unverified does not count...) */ + if (signerinfo->verificationStatus != SecCmsVSGoodSignature) + return SECFailure; + + /* find preferred encryption cert */ + if (!SecCmsArrayIsEmpty((void **)signerinfo->authAttr) && + (attr = SecCmsAttributeArrayFindAttrByOidTag(signerinfo->authAttr, + SEC_OID_SMIME_ENCRYPTION_KEY_PREFERENCE, PR_TRUE)) != NULL) + { /* we have a SMIME_ENCRYPTION_KEY_PREFERENCE attribute! */ + ekp = SecCmsAttributeGetValue(attr); + if (ekp == NULL) + return SECFailure; + + /* we assume that all certs coming with the message have been imported to the */ + /* temporary database */ + cert = SecSMIMEGetCertFromEncryptionKeyPreference(keychainOrArray, ekp); + if (cert == NULL) + return SECFailure; + must_free_cert = PR_TRUE; + } + + if (cert == NULL) { + /* no preferred cert found? + * find the cert the signerinfo is signed with instead */ + CFStringRef emailAddress=NULL; + + cert = SecCmsSignerInfoGetSigningCertificate(signerinfo, keychainOrArray); + if (cert == NULL) + return SECFailure; + if (SecCertificateGetEmailAddress(cert,&emailAddress)) + return SECFailure; + } + + /* verify this cert for encryption (has been verified for signing so far) */ /* don't verify this cert for encryption. It may just be a signing cert. + * that's OK, we can still save the S/MIME profile. The encryption cert + * should have already been saved */ +#ifdef notdef + if (CERT_VerifyCert(keychainOrArray, cert, certUsageEmailRecipient, CFAbsoluteTimeGetCurrent(), NULL) != SECSuccess) { + if (must_free_cert) + CERT_DestroyCertificate(cert); + return SECFailure; + } +#endif + + /* XXX store encryption cert permanently? */ + + /* + * Remember the current error set because we do not care about + * anything set by the functions we are about to call. + */ + save_error = PORT_GetError(); + + if (!SecCmsArrayIsEmpty((void **)signerinfo->authAttr)) { + attr = SecCmsAttributeArrayFindAttrByOidTag(signerinfo->authAttr, + SEC_OID_PKCS9_SMIME_CAPABILITIES, + PR_TRUE); + profile = SecCmsAttributeGetValue(attr); + attr = SecCmsAttributeArrayFindAttrByOidTag(signerinfo->authAttr, + SEC_OID_PKCS9_SIGNING_TIME, + PR_TRUE); + utc_stime = SecCmsAttributeGetValue(attr); + } + + rv = CERT_SaveSMimeProfile (cert, profile, utc_stime); + if (must_free_cert) + CERT_DestroyCertificate(cert); + + /* + * Restore the saved error in case the calls above set a new + * one that we do not actually care about. + */ + PORT_SetError (save_error); + + return rv; +} + +/* + * SecCmsSignerInfoIncludeCerts - set cert chain inclusion mode for this signer + */ +OSStatus +SecCmsSignerInfoIncludeCerts(SecCmsSignerInfoRef signerinfo, SecCmsCertChainMode cm, SECCertUsage usage) +{ + if (signerinfo->cert == NULL) + return SECFailure; + + /* don't leak if we get called twice */ + if (signerinfo->certList != NULL) { + CFRelease(signerinfo->certList); + signerinfo->certList = NULL; + } + + switch (cm) { + case SecCmsCMNone: + signerinfo->certList = NULL; + break; + case SecCmsCMCertOnly: + signerinfo->certList = CERT_CertListFromCert(signerinfo->cert); + break; + case SecCmsCMCertChain: + signerinfo->certList = CERT_CertChainFromCert(signerinfo->cert, usage, PR_FALSE); + break; + case SecCmsCMCertChainWithRoot: + signerinfo->certList = CERT_CertChainFromCert(signerinfo->cert, usage, PR_TRUE); + break; + } + + if (cm != SecCmsCMNone && signerinfo->certList == NULL) + return SECFailure; + + return SECSuccess; +} diff --git a/Security/libsecurity_smime/lib/cmstpriv.h b/Security/libsecurity_smime/lib/cmstpriv.h new file mode 100644 index 00000000..f2d10f49 --- /dev/null +++ b/Security/libsecurity_smime/lib/cmstpriv.h @@ -0,0 +1,502 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * Header for CMS types. + */ + +#ifndef _CMSTPRIV_H_ +#define _CMSTPRIV_H_ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +/* rjr: PKCS #11 cert handling (pk11cert.c) does use SecCmsRecipientInfo's. + * This is because when we search the recipient list for the cert and key we + * want, we need to invert the order of the loops we used to have. The old + * loops were: + * + * For each recipient { + * find_cert = PK11_Find_AllCert(recipient->issuerSN); + * [which unrolls to... ] + * For each slot { + * Log into slot; + * search slot for cert; + * } + * } + * + * the new loop searchs all the recipients at once on a slot. this allows + * PKCS #11 to order slots in such a way that logout slots don't get checked + * if we can find the cert on a logged in slot. This eliminates lots of + * spurious password prompts when smart cards are installed... so why this + * comment? If you make SecCmsRecipientInfo completely opaque, you need + * to provide a non-opaque list of issuerSN's (the only field PKCS#11 needs + * and fix up pk11cert.c first. NOTE: Only S/MIME calls this special PKCS #11 + * function. + */ + +typedef struct SecCmsContentInfoStr SecCmsContentInfo; +typedef struct SecCmsMessageStr SecCmsMessage; +typedef struct SecCmsSignedDataStr SecCmsSignedData; +typedef struct SecCmsSignerInfoStr SecCmsSignerInfo; +typedef struct SecCmsEnvelopedDataStr SecCmsEnvelopedData; +typedef struct SecCmsRecipientInfoStr SecCmsRecipientInfo; +typedef struct SecCmsDigestedDataStr SecCmsDigestedData; +typedef struct SecCmsEncryptedDataStr SecCmsEncryptedData; + +typedef struct SecCmsIssuerAndSNStr SecCmsIssuerAndSN; +typedef struct SecCmsOriginatorInfoStr SecCmsOriginatorInfo; +typedef struct SecCmsAttributeStr SecCmsAttribute; + +typedef union SecCmsContentUnion SecCmsContent; +typedef struct SecCmsSignerIdentifierStr SecCmsSignerIdentifier; + +typedef struct SecCmsSMIMEKEAParametersStr SecCmsSMIMEKEAParameters; + +typedef struct SecCmsCipherContextStr SecCmsCipherContext; +typedef struct SecCmsCipherContextStr *SecCmsCipherContextRef; + +/* ============================================================================= + * ENCAPSULATED CONTENTINFO & CONTENTINFO + */ + +union SecCmsContentUnion { + /* either unstructured */ + CSSM_DATA_PTR data; + /* or structured data */ + SecCmsDigestedDataRef digestedData; + SecCmsEncryptedDataRef encryptedData; + SecCmsEnvelopedDataRef envelopedData; + SecCmsSignedDataRef signedData; + /* or anonymous pointer to something */ + void * pointer; +}; + +struct SecCmsContentInfoStr { + CSSM_DATA contentType; + SecCmsContent content; + /* --------- local; not part of encoding --------- */ + SECOidData * contentTypeTag; + + /* additional info for encryptedData and envelopedData */ + /* we waste this space for signedData and digestedData. sue me. */ + + SECAlgorithmID contentEncAlg; + CSSM_DATA_PTR rawContent; /* encrypted DER, optional */ + /* XXXX bytes not encrypted, but encoded? */ + /* --------- local; not part of encoding --------- */ + SecSymmetricKeyRef bulkkey; /* bulk encryption key */ + int keysize; /* size of bulk encryption key + * (only used by creation code) */ + SECOidTag contentEncAlgTag; /* oid tag of encryption algorithm + * (only used by creation code) */ + SecCmsCipherContextRef ciphcx; /* context for en/decryption going on */ + SecCmsDigestContextRef digcx; /* context for digesting going on */ + SecPrivateKeyRef privkey; /* @@@ private key is only here as a workaround for 3401088 */ +}; + +/* ============================================================================= + * MESSAGE + */ + +/*! + @typedef + @discussion Type of function called inside SecCmsSignedDataEncodeAfterData to + fire up XPC service to talk to TimeStamping server, etc. + @param context Typically a CFDictionary with URL, etc. + @param messageImprint a SecAsn1TSAMessageImprint with the algorithm and hash value + @param tstoken The returned TimeStampToken + */ +typedef OSStatus (*SecCmsTSACallback)(const void *context, void *messageImprint, uint64_t nonce, CSSM_DATA *tstoken); + +struct SecCmsMessageStr { + SecCmsContentInfo contentInfo; /* "outer" cinfo */ + /* --------- local; not part of encoding --------- */ + PLArenaPool * poolp; + Boolean poolp_is_ours; + int refCount; + /* properties of the "inner" data */ + SECAlgorithmID ** detached_digestalgs; + CSSM_DATA_PTR * detached_digests; + void * pwfn_arg; + SecCmsGetDecryptKeyCallback decrypt_key_cb; + void * decrypt_key_cb_arg; + + /* Fields for Time Stamping */ + SecCmsTSACallback tsaCallback; + CFTypeRef tsaContext; +}; + +/* ============================================================================= + * SIGNEDDATA + */ + +struct SecCmsSignedDataStr { + CSSM_DATA version; + SECAlgorithmID ** digestAlgorithms; + SecCmsContentInfo contentInfo; + CSSM_DATA_PTR * rawCerts; + CSSM_DATA_PTR * rawCrls; + SecCmsSignerInfoRef * signerInfos; + /* --------- local; not part of encoding --------- */ + SecCmsMessageRef cmsg; /* back pointer to message */ + CSSM_DATA_PTR * digests; + CFMutableArrayRef certs; +}; +#define SEC_CMS_SIGNED_DATA_VERSION_BASIC 1 /* what we *create* */ +#define SEC_CMS_SIGNED_DATA_VERSION_EXT 3 /* what we *create* */ + +typedef enum { + SecCmsSignerIDIssuerSN = 0, + SecCmsSignerIDSubjectKeyID = 1 +} SecCmsSignerIDSelector; + +struct SecCmsSignerIdentifierStr { + SecCmsSignerIDSelector identifierType; + union { + SecCmsIssuerAndSN *issuerAndSN; + CSSM_DATA_PTR subjectKeyID; + } id; +}; + +struct SecCmsIssuerAndSNStr { + NSS_Name issuer; + CSSM_DATA serialNumber; + /* --------- local; not part of encoding --------- */ + CSSM_DATA derIssuer; +}; + +struct SecCmsSignerInfoStr { + CSSM_DATA version; + SecCmsSignerIdentifier signerIdentifier; + SECAlgorithmID digestAlg; + SecCmsAttribute ** authAttr; + SECAlgorithmID digestEncAlg; + CSSM_DATA encDigest; + SecCmsAttribute ** unAuthAttr; + /* --------- local; not part of encoding --------- */ + SecCmsMessageRef cmsg; /* back pointer to message */ + SecCmsSignedDataRef sigd; /* back pointer to SignedData */ + SecCertificateRef cert; + CFArrayRef certList; + CFAbsoluteTime signingTime; + SecCmsVerificationStatus verificationStatus; + SecPrivateKeyRef signingKey; /* Used if we're using subjKeyID*/ + SecPublicKeyRef pubKey; + CFAbsoluteTime timestampTime; + CFAbsoluteTime tsaLeafNotBefore; /* Start date for Timestamp Authority leaf */ + CFAbsoluteTime tsaLeafNotAfter; /* Expiration date for Timestamp Authority leaf */ + CFMutableArrayRef timestampCertList; +}; +#define SEC_CMS_SIGNER_INFO_VERSION_ISSUERSN 1 /* what we *create* */ +#define SEC_CMS_SIGNER_INFO_VERSION_SUBJKEY 3 /* what we *create* */ + +/* ============================================================================= + * ENVELOPED DATA + */ +struct SecCmsEnvelopedDataStr { + CSSM_DATA version; + SecCmsOriginatorInfo * originatorInfo; /* optional */ + SecCmsRecipientInfoRef * recipientInfos; + SecCmsContentInfo contentInfo; + SecCmsAttribute ** unprotectedAttr; + /* --------- local; not part of encoding --------- */ + SecCmsMessageRef cmsg; /* back pointer to message */ +}; +#define SEC_CMS_ENVELOPED_DATA_VERSION_REG 0 /* what we *create* */ +#define SEC_CMS_ENVELOPED_DATA_VERSION_ADV 2 /* what we *create* */ + +struct SecCmsOriginatorInfoStr { + CSSM_DATA_PTR * rawCerts; + CSSM_DATA_PTR * rawCrls; + /* --------- local; not part of encoding --------- */ + SecCertificateRef * certs; +}; + +/* ----------------------------------------------------------------------------- + * key transport recipient info + */ +typedef enum { + SecCmsRecipientIDIssuerSN = 0, + SecCmsRecipientIDSubjectKeyID = 1 +} SecCmsRecipientIDSelector; + +struct SecCmsRecipientIdentifierStr { + SecCmsRecipientIDSelector identifierType; + union { + SecCmsIssuerAndSN *issuerAndSN; + CSSM_DATA_PTR subjectKeyID; + } id; +}; +typedef struct SecCmsRecipientIdentifierStr SecCmsRecipientIdentifier; + +struct SecCmsKeyTransRecipientInfoStr { + CSSM_DATA version; + SecCmsRecipientIdentifier recipientIdentifier; + SECAlgorithmID keyEncAlg; + CSSM_DATA encKey; +}; +typedef struct SecCmsKeyTransRecipientInfoStr SecCmsKeyTransRecipientInfo; + +/* + * View comments before SecCmsRecipientInfoStr for purpose of this + * structure. + */ +struct SecCmsKeyTransRecipientInfoExStr { + SecCmsKeyTransRecipientInfo recipientInfo; + int version; /* version of this structure (0) */ + SecPublicKeyRef pubKey; +}; + +typedef struct SecCmsKeyTransRecipientInfoExStr SecCmsKeyTransRecipientInfoEx; + +#define SEC_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_ISSUERSN 0 /* what we *create* */ +#define SEC_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_SUBJKEY 2 /* what we *create* */ + +/* ----------------------------------------------------------------------------- + * key agreement recipient info + */ +struct SecCmsOriginatorPublicKeyStr { + SECAlgorithmID algorithmIdentifier; + CSSM_DATA publicKey; /* bit string! */ +}; +typedef struct SecCmsOriginatorPublicKeyStr SecCmsOriginatorPublicKey; + +typedef enum { + SecCmsOriginatorIDOrKeyIssuerSN = 0, + SecCmsOriginatorIDOrKeySubjectKeyID = 1, + SecCmsOriginatorIDOrKeyOriginatorPublicKey = 2 +} SecCmsOriginatorIDOrKeySelector; + +struct SecCmsOriginatorIdentifierOrKeyStr { + SecCmsOriginatorIDOrKeySelector identifierType; + union { + SecCmsIssuerAndSN *issuerAndSN; /* static-static */ + CSSM_DATA subjectKeyID; /* static-static */ + SecCmsOriginatorPublicKey originatorPublicKey; /* ephemeral-static */ + } id; +}; +typedef struct SecCmsOriginatorIdentifierOrKeyStr SecCmsOriginatorIdentifierOrKey; + +struct SecCmsRecipientKeyIdentifierStr { + CSSM_DATA_PTR subjectKeyIdentifier; + CSSM_DATA_PTR date; /* optional */ + CSSM_DATA_PTR other; /* optional */ +}; +typedef struct SecCmsRecipientKeyIdentifierStr SecCmsRecipientKeyIdentifier; + +typedef enum { + SecCmsKeyAgreeRecipientIDIssuerSN = 0, + SecCmsKeyAgreeRecipientIDRKeyID = 1 +} SecCmsKeyAgreeRecipientIDSelector; + +struct SecCmsKeyAgreeRecipientIdentifierStr { + SecCmsKeyAgreeRecipientIDSelector identifierType; + union { + SecCmsIssuerAndSN *issuerAndSN; + SecCmsRecipientKeyIdentifier recipientKeyIdentifier; + } id; +}; +typedef struct SecCmsKeyAgreeRecipientIdentifierStr SecCmsKeyAgreeRecipientIdentifier; + +struct SecCmsRecipientEncryptedKeyStr { + SecCmsKeyAgreeRecipientIdentifier recipientIdentifier; + CSSM_DATA encKey; +}; +typedef struct SecCmsRecipientEncryptedKeyStr SecCmsRecipientEncryptedKey; + +struct SecCmsKeyAgreeRecipientInfoStr { + CSSM_DATA version; + SecCmsOriginatorIdentifierOrKey originatorIdentifierOrKey; + CSSM_DATA ukm; /* optional */ + SECAlgorithmID keyEncAlg; + SecCmsRecipientEncryptedKey ** recipientEncryptedKeys; +}; +typedef struct SecCmsKeyAgreeRecipientInfoStr SecCmsKeyAgreeRecipientInfo; + +#define SEC_CMS_KEYAGREE_RECIPIENT_INFO_VERSION 3 /* what we *create* */ + +/* ----------------------------------------------------------------------------- + * KEK recipient info + */ +struct SecCmsKEKIdentifierStr { + CSSM_DATA keyIdentifier; + CSSM_DATA_PTR date; /* optional */ + CSSM_DATA_PTR other; /* optional */ +}; +typedef struct SecCmsKEKIdentifierStr SecCmsKEKIdentifier; + +struct SecCmsKEKRecipientInfoStr { + CSSM_DATA version; + SecCmsKEKIdentifier kekIdentifier; + SECAlgorithmID keyEncAlg; + CSSM_DATA encKey; +}; +typedef struct SecCmsKEKRecipientInfoStr SecCmsKEKRecipientInfo; + +#define SEC_CMS_KEK_RECIPIENT_INFO_VERSION 4 /* what we *create* */ + +/* ----------------------------------------------------------------------------- + * recipient info + */ + +typedef enum { + SecCmsRecipientInfoIDKeyTrans = 0, + SecCmsRecipientInfoIDKeyAgree = 1, + SecCmsRecipientInfoIDKEK = 2 +} SecCmsRecipientInfoIDSelector; + +/* + * In order to preserve backwards binary compatibility when implementing + * creation of Recipient Info's that uses subjectKeyID in the + * keyTransRecipientInfo we need to stash a public key pointer in this + * structure somewhere. We figured out that SecCmsKeyTransRecipientInfo + * is the smallest member of the ri union. We're in luck since that's + * the very structure that would need to use the public key. So we created + * a new structure SecCmsKeyTransRecipientInfoEx which has a member + * SecCmsKeyTransRecipientInfo as the first member followed by a version + * and a public key pointer. This way we can keep backwards compatibility + * without changing the size of this structure. + * + * BTW, size of structure: + * SecCmsKeyTransRecipientInfo: 9 ints, 4 pointers + * SecCmsKeyAgreeRecipientInfo: 12 ints, 8 pointers + * SecCmsKEKRecipientInfo: 10 ints, 7 pointers + * + * The new structure: + * SecCmsKeyTransRecipientInfoEx: sizeof(SecCmsKeyTransRecipientInfo) + + * 1 int, 1 pointer + */ + +struct SecCmsRecipientInfoStr { + SecCmsRecipientInfoIDSelector recipientInfoType; + union { + SecCmsKeyTransRecipientInfo keyTransRecipientInfo; + SecCmsKeyAgreeRecipientInfo keyAgreeRecipientInfo; + SecCmsKEKRecipientInfo kekRecipientInfo; + SecCmsKeyTransRecipientInfoEx keyTransRecipientInfoEx; + } ri; + /* --------- local; not part of encoding --------- */ + SecCmsMessageRef cmsg; /* back pointer to message */ + SecCertificateRef cert; /* recipient's certificate */ +}; + +/* ============================================================================= + * DIGESTED DATA + */ +struct SecCmsDigestedDataStr { + CSSM_DATA version; + SECAlgorithmID digestAlg; + SecCmsContentInfo contentInfo; + CSSM_DATA digest; + /* --------- local; not part of encoding --------- */ + SecCmsMessageRef cmsg; /* back pointer */ + CSSM_DATA cdigest; /* calculated digest */ +}; +#define SEC_CMS_DIGESTED_DATA_VERSION_DATA 0 /* what we *create* */ +#define SEC_CMS_DIGESTED_DATA_VERSION_ENCAP 2 /* what we *create* */ + +/* ============================================================================= + * ENCRYPTED DATA + */ +struct SecCmsEncryptedDataStr { + CSSM_DATA version; + SecCmsContentInfo contentInfo; + SecCmsAttribute ** unprotectedAttr; /* optional */ + /* --------- local; not part of encoding --------- */ + SecCmsMessageRef cmsg; /* back pointer */ +}; +#define SEC_CMS_ENCRYPTED_DATA_VERSION 0 /* what we *create* */ +#define SEC_CMS_ENCRYPTED_DATA_VERSION_UPATTR 2 /* what we *create* */ + +/* ============================================================================= + * FORTEZZA KEA + */ + +/* An enumerated type used to select templates based on the encryption + scenario and data specifics. */ +typedef enum { + SecCmsKEAInvalid = -1, + SecCmsKEAUsesSkipjack = 0, + SecCmsKEAUsesNonSkipjack = 1, + SecCmsKEAUsesNonSkipjackWithPaddedEncKey = 2 +} SecCmsKEATemplateSelector; + +/* ### mwelch - S/MIME KEA parameters. These don't really fit here, + but I cannot think of a more appropriate place at this time. */ +struct SecCmsSMIMEKEAParametersStr { + CSSM_DATA originatorKEAKey; /* sender KEA key (encrypted?) */ + CSSM_DATA originatorRA; /* random number generated by sender */ + CSSM_DATA nonSkipjackIV; /* init'n vector for SkipjackCBC64 + decryption of KEA key if Skipjack + is not the bulk algorithm used on + the message */ + CSSM_DATA bulkKeySize; /* if Skipjack is not the bulk + algorithm used on the message, + and the size of the bulk encryption + key is not the same as that of + originatorKEAKey (due to padding + perhaps), this field will contain + the real size of the bulk encryption + key. */ +}; + +/* + * ***************************************************************************** + * ***************************************************************************** + * ***************************************************************************** + */ + +/* + * See comment above about this type not really belonging to CMS. + */ +struct SecCmsAttributeStr { + /* The following fields make up an encoded Attribute: */ + CSSM_DATA type; + CSSM_DATA_PTR * values; /* data may or may not be encoded */ + /* The following fields are not part of an encoded Attribute: */ + SECOidData * typeTag; + Boolean encoded; /* when true, values are encoded */ +}; + + +#endif /* _CMSTPRIV_H_ */ diff --git a/Security/libsecurity_smime/lib/cmsutil.c b/Security/libsecurity_smime/lib/cmsutil.c new file mode 100644 index 00000000..020460cf --- /dev/null +++ b/Security/libsecurity_smime/lib/cmsutil.c @@ -0,0 +1,412 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * CMS miscellaneous utility functions. + */ + +#include /* @@@ Remove this when we move the Encoder method. */ +#include +#include "cmslocal.h" + +#include "secitem.h" +#include "secoid.h" +#include "cryptohi.h" + +#include +#include +#include +#include +#include + + +/* + * SecCmsArraySortByDER - sort array of objects by objects' DER encoding + * + * make sure that the order of the objects guarantees valid DER (which must be + * in lexigraphically ascending order for a SET OF); if reordering is necessary it + * will be done in place (in objs). + */ +OSStatus +SecCmsArraySortByDER(void **objs, const SecAsn1Template *objtemplate, void **objs2) +{ + PRArenaPool *poolp; + int num_objs; + CSSM_DATA_PTR *enc_objs; + OSStatus rv = SECFailure; + int i; + + if (objs == NULL) /* already sorted */ + return SECSuccess; + + num_objs = SecCmsArrayCount((void **)objs); + if (num_objs == 0 || num_objs == 1) /* already sorted. */ + return SECSuccess; + + poolp = PORT_NewArena (1024); /* arena for temporaries */ + if (poolp == NULL) + return SECFailure; /* no memory; nothing we can do... */ + + /* + * Allocate arrays to hold the individual encodings which we will use + * for comparisons and the reordered attributes as they are sorted. + */ + enc_objs = (CSSM_DATA_PTR *)PORT_ArenaZAlloc(poolp, (num_objs + 1) * sizeof(CSSM_DATA_PTR)); + if (enc_objs == NULL) + goto loser; + + /* DER encode each individual object. */ + for (i = 0; i < num_objs; i++) { + enc_objs[i] = SEC_ASN1EncodeItem(poolp, NULL, objs[i], objtemplate); + if (enc_objs[i] == NULL) + goto loser; + } + enc_objs[num_objs] = NULL; + + /* now compare and sort objs by the order of enc_objs */ + SecCmsArraySort((void **)enc_objs, SecCmsUtilDERCompare, objs, objs2); + + rv = SECSuccess; + +loser: + PORT_FreeArena (poolp, PR_FALSE); + return rv; +} + +/* + * SecCmsUtilDERCompare - for use with SecCmsArraySort to + * sort arrays of CSSM_DATAs containing DER + */ +int +SecCmsUtilDERCompare(void *a, void *b) +{ + CSSM_DATA_PTR der1 = (CSSM_DATA_PTR)a; + CSSM_DATA_PTR der2 = (CSSM_DATA_PTR)b; + int j; + + /* + * Find the lowest (lexigraphically) encoding. One that is + * shorter than all the rest is known to be "less" because each + * attribute is of the same type (a SEQUENCE) and so thus the + * first octet of each is the same, and the second octet is + * the length (or the length of the length with the high bit + * set, followed by the length, which also works out to always + * order the shorter first). Two (or more) that have the + * same length need to be compared byte by byte until a mismatch + * is found. + */ + if (der1->Length != der2->Length) + return (der1->Length < der2->Length) ? -1 : 1; + + for (j = 0; j < der1->Length; j++) { + if (der1->Data[j] == der2->Data[j]) + continue; + return (der1->Data[j] < der2->Data[j]) ? -1 : 1; + } + return 0; +} + +/* + * SecCmsAlgArrayGetIndexByAlgID - find a specific algorithm in an array of + * algorithms. + * + * algorithmArray - array of algorithm IDs + * algid - algorithmid of algorithm to pick + * + * Returns: + * An integer containing the index of the algorithm in the array or -1 if + * algorithm was not found. + */ +int +SecCmsAlgArrayGetIndexByAlgID(SECAlgorithmID **algorithmArray, SECAlgorithmID *algid) +{ + int i; + + if (algorithmArray == NULL || algorithmArray[0] == NULL) + return -1; + + for (i = 0; algorithmArray[i] != NULL; i++) { + if (SECOID_CompareAlgorithmID(algorithmArray[i], algid) == SECEqual) + break; /* bingo */ + } + + if (algorithmArray[i] == NULL) + return -1; /* not found */ + + return i; +} + +/* + * SecCmsAlgArrayGetIndexByAlgTag - find a specific algorithm in an array of + * algorithms. + * + * algorithmArray - array of algorithm IDs + * algtag - algorithm tag of algorithm to pick + * + * Returns: + * An integer containing the index of the algorithm in the array or -1 if + * algorithm was not found. + */ +int +SecCmsAlgArrayGetIndexByAlgTag(SECAlgorithmID **algorithmArray, + SECOidTag algtag) +{ + SECOidData *algid; + int i = -1; + + if (algorithmArray == NULL || algorithmArray[0] == NULL) + return i; + +#ifdef ORDER_N_SQUARED + for (i = 0; algorithmArray[i] != NULL; i++) { + algid = SECOID_FindOID(&(algorithmArray[i]->algorithm)); + if (algid->offset == algtag) + break; /* bingo */ + } +#else + algid = SECOID_FindOIDByTag(algtag); + if (!algid) + return i; + for (i = 0; algorithmArray[i] != NULL; i++) { + if (SECITEM_ItemsAreEqual(&algorithmArray[i]->algorithm, &algid->oid)) + break; /* bingo */ + } +#endif + + if (algorithmArray[i] == NULL) + return -1; /* not found */ + + return i; +} + +CSSM_CC_HANDLE +SecCmsUtilGetHashObjByAlgID(SECAlgorithmID *algid) +{ + SECOidData *oidData = SECOID_FindOID(&(algid->algorithm)); + if (oidData) + { + CSSM_ALGORITHMS alg = oidData->cssmAlgorithm; + if (alg) + { + CSSM_CC_HANDLE digobj; + CSSM_CSP_HANDLE cspHandle = SecCspHandleForAlgorithm(alg); + + if (!CSSM_CSP_CreateDigestContext(cspHandle, alg, &digobj)) + return digobj; + } + } + + return 0; +} + +/* + * XXX I would *really* like to not have to do this, but the current + * signing interface gives me little choice. + */ +SECOidTag +SecCmsUtilMakeSignatureAlgorithm(SECOidTag hashalg, SECOidTag encalg) +{ + switch (encalg) { + case SEC_OID_PKCS1_RSA_ENCRYPTION: + switch (hashalg) { + case SEC_OID_MD2: + return SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION; + case SEC_OID_MD5: + return SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION; + case SEC_OID_SHA1: + return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; + case SEC_OID_SHA256: + return SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; + case SEC_OID_SHA384: + return SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; + case SEC_OID_SHA512: + return SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; + default: + return SEC_OID_UNKNOWN; + } + case SEC_OID_ANSIX9_DSA_SIGNATURE: + case SEC_OID_MISSI_KEA_DSS: + case SEC_OID_MISSI_DSS: + switch (hashalg) { + case SEC_OID_SHA1: + return SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST; + default: + return SEC_OID_UNKNOWN; + } + case SEC_OID_EC_PUBLIC_KEY: + switch(hashalg) { + /* + * Note this is only used when signing and verifying signed attributes, + * In which case we really do want the combined ECDSA_WithSHA1 alg... + */ + case SEC_OID_SHA1: + return SEC_OID_ECDSA_WithSHA1; + default: + return SEC_OID_UNKNOWN; + } + default: + break; + } + + return encalg; /* maybe it is already the right algid */ +} + +const SecAsn1Template * +SecCmsUtilGetTemplateByTypeTag(SECOidTag type) +{ + const SecAsn1Template *template; + extern const SecAsn1Template SecCmsSignedDataTemplate[]; + extern const SecAsn1Template SecCmsEnvelopedDataTemplate[]; + extern const SecAsn1Template SecCmsEncryptedDataTemplate[]; + extern const SecAsn1Template SecCmsDigestedDataTemplate[]; + + switch (type) { + case SEC_OID_PKCS7_SIGNED_DATA: + template = SecCmsSignedDataTemplate; + break; + case SEC_OID_PKCS7_ENVELOPED_DATA: + template = SecCmsEnvelopedDataTemplate; + break; + case SEC_OID_PKCS7_ENCRYPTED_DATA: + template = SecCmsEncryptedDataTemplate; + break; + case SEC_OID_PKCS7_DIGESTED_DATA: + template = SecCmsDigestedDataTemplate; + break; + default: + case SEC_OID_PKCS7_DATA: + case SEC_OID_OTHER: + template = NULL; + break; + } + return template; +} + +size_t +SecCmsUtilGetSizeByTypeTag(SECOidTag type) +{ + size_t size; + + switch (type) { + case SEC_OID_PKCS7_SIGNED_DATA: + size = sizeof(SecCmsSignedData); + break; + case SEC_OID_PKCS7_ENVELOPED_DATA: + size = sizeof(SecCmsEnvelopedData); + break; + case SEC_OID_PKCS7_ENCRYPTED_DATA: + size = sizeof(SecCmsEncryptedData); + break; + case SEC_OID_PKCS7_DIGESTED_DATA: + size = sizeof(SecCmsDigestedData); + break; + default: + case SEC_OID_PKCS7_DATA: + size = 0; + break; + } + return size; +} + +SecCmsContentInfoRef +SecCmsContentGetContentInfo(void *msg, SECOidTag type) +{ + SecCmsContent c; + SecCmsContentInfoRef cinfo; + + if (!msg) + return NULL; + c.pointer = msg; + switch (type) { + case SEC_OID_PKCS7_SIGNED_DATA: + cinfo = &(c.signedData->contentInfo); + break; + case SEC_OID_PKCS7_ENVELOPED_DATA: + cinfo = &(c.envelopedData->contentInfo); + break; + case SEC_OID_PKCS7_ENCRYPTED_DATA: + cinfo = &(c.encryptedData->contentInfo); + break; + case SEC_OID_PKCS7_DIGESTED_DATA: + cinfo = &(c.digestedData->contentInfo); + break; + default: + cinfo = NULL; + } + return cinfo; +} + +// @@@ Return CFStringRef and do localization. +const char * +SecCmsUtilVerificationStatusToString(SecCmsVerificationStatus vs) +{ + switch (vs) { + case SecCmsVSUnverified: return "Unverified"; + case SecCmsVSGoodSignature: return "GoodSignature"; + case SecCmsVSBadSignature: return "BadSignature"; + case SecCmsVSDigestMismatch: return "DigestMismatch"; + case SecCmsVSSigningCertNotFound: return "SigningCertNotFound"; + case SecCmsVSSigningCertNotTrusted: return "SigningCertNotTrusted"; + case SecCmsVSSignatureAlgorithmUnknown: return "SignatureAlgorithmUnknown"; + case SecCmsVSSignatureAlgorithmUnsupported: return "SignatureAlgorithmUnsupported"; + case SecCmsVSMalformedSignature: return "MalformedSignature"; + case SecCmsVSProcessingError: return "ProcessingError"; + default: return "Unknown"; + } +} + +OSStatus +SecArenaPoolCreate(size_t chunksize, SecArenaPoolRef *outArena) +{ + OSStatus status; + + if (!outArena) { + status = paramErr; + goto loser; + } + + *outArena = (SecArenaPoolRef)PORT_NewArena(chunksize); + if (*outArena) + status = 0; + else + status = PORT_GetError(); + +loser: + return status; +} + +void +SecArenaPoolFree(SecArenaPoolRef arena, Boolean zero) +{ + PORT_FreeArena((PLArenaPool *)arena, zero); +} diff --git a/Security/libsecurity_smime/lib/cryptohi.c b/Security/libsecurity_smime/lib/cryptohi.c new file mode 100644 index 00000000..d80963c0 --- /dev/null +++ b/Security/libsecurity_smime/lib/cryptohi.c @@ -0,0 +1,552 @@ +/* + * crypto.h - public data structures and prototypes for the crypto library + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "cryptohi.h" + +#include "secoid.h" +#include "cmspriv.h" +#include +#include +#include +#include +#include + +static CSSM_CSP_HANDLE gCsp = 0; +static char gCssmInitialized = 0; + +/* @@@ Ugly hack casting, but the extra argument at the end will be ignored. */ +static CSSM_API_MEMORY_FUNCS memFuncs = +{ + (CSSM_MALLOC)malloc, + (CSSM_FREE)free, + (CSSM_REALLOC)realloc, + (CSSM_CALLOC)calloc, + NULL +}; + +/* + * + * SecCspHandleForAlgorithm + * @@@ This function should get more parameters like keysize and operation required and use mds. + * + */ +CSSM_CSP_HANDLE +SecCspHandleForAlgorithm(CSSM_ALGORITHMS algorithm) +{ + + if (!gCsp) + { + CSSM_VERSION version = { 2, 0 }; + CSSM_RETURN rv; + + if (!gCssmInitialized) + { + CSSM_GUID myGuid = { 0xFADE, 0, 0, { 1, 2, 3, 4, 5, 6, 7, 0 } }; + CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE; + + rv = CSSM_Init (&version, CSSM_PRIVILEGE_SCOPE_NONE, &myGuid, CSSM_KEY_HIERARCHY_NONE, &pvcPolicy, NULL); + if (rv) + goto loser; + gCssmInitialized = 1; + } + + rv = CSSM_ModuleLoad(&gGuidAppleCSP, CSSM_KEY_HIERARCHY_NONE, NULL, NULL); + if (rv) + goto loser; + rv = CSSM_ModuleAttach(&gGuidAppleCSP, &version, &memFuncs, 0, CSSM_SERVICE_CSP, 0, CSSM_KEY_HIERARCHY_NONE, NULL, 0, NULL, &gCsp); + } + +loser: + return gCsp; +} + +CSSM_ALGORITHMS +SECOID_FindyCssmAlgorithmByTag(SECOidTag algTag) +{ + const SECOidData *oidData = SECOID_FindOIDByTag(algTag); + return oidData ? oidData->cssmAlgorithm : CSSM_ALGID_NONE; +} + +static SECStatus SEC_CssmRtnToSECStatus(CSSM_RETURN rv) +{ + CSSM_RETURN crtn = CSSM_ERRCODE(rv); + switch(crtn) { + case CSSM_ERRCODE_USER_CANCELED: + case CSSM_ERRCODE_OPERATION_AUTH_DENIED: + case CSSM_ERRCODE_OBJECT_USE_AUTH_DENIED: + return SEC_ERROR_USER_CANCELLED; + case CSSM_ERRCODE_NO_USER_INTERACTION: + return SEC_ERROR_NO_USER_INTERACTION; + case CSSMERR_CSP_KEY_USAGE_INCORRECT: + return SEC_ERROR_INADEQUATE_KEY_USAGE; + default: + fprintf(stderr, "CSSM_SignData returned: %08X\n", (uint32_t)rv); + return SEC_ERROR_LIBRARY_FAILURE; + } +} + +SECStatus +SEC_SignData(SECItem *result, unsigned char *buf, int len, + SecPrivateKeyRef pk, SECOidTag digAlgTag, SECOidTag sigAlgTag) +{ + const CSSM_ACCESS_CREDENTIALS *accessCred; + CSSM_ALGORITHMS algorithm; + CSSM_CC_HANDLE cc = 0; + CSSM_CSP_HANDLE csp; + OSStatus rv; + CSSM_DATA dataBuf = { (uint32)len, (uint8 *)buf }; + CSSM_DATA sig = {}; + const CSSM_KEY *key; + + algorithm = SECOID_FindyCssmAlgorithmByTag(SecCmsUtilMakeSignatureAlgorithm(digAlgTag, sigAlgTag)); + if (!algorithm) + { + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + rv = SECFailure; + goto loser; + } + + rv = SecKeyGetCSPHandle(pk, &csp); + if (rv) { + PORT_SetError(SEC_ERROR_BAD_KEY); + goto loser; + } + rv = SecKeyGetCSSMKey(pk, &key); + if (rv) { + PORT_SetError(SEC_ERROR_BAD_KEY); + goto loser; + } + rv = SecKeyGetCredentials(pk, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault, &accessCred); + if (rv) { + PORT_SetError(SEC_ERROR_BAD_KEY); + goto loser; + } + + rv = CSSM_CSP_CreateSignatureContext(csp, algorithm, accessCred, key, &cc); + if (rv) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + rv = CSSM_SignData(cc, &dataBuf, 1, CSSM_ALGID_NONE, &sig); + if (rv) { + SECErrorCodes code = SEC_CssmRtnToSECStatus(rv); + PORT_SetError(code); + goto loser; + } + + result->Length = sig.Length; + result->Data = sig.Data; + +loser: + if (cc) + CSSM_DeleteContext(cc); + + return rv; +} + +SECStatus +SGN_Digest(SecPrivateKeyRef pk, SECOidTag digAlgTag, SECOidTag sigAlgTag, SECItem *result, SECItem *digest) +{ + const CSSM_ACCESS_CREDENTIALS *accessCred; + CSSM_ALGORITHMS digalg, sigalg; + CSSM_CC_HANDLE cc = 0; + CSSM_CSP_HANDLE csp; + const CSSM_KEY *key; + CSSM_DATA sig = {}; + OSStatus rv; + + digalg = SECOID_FindyCssmAlgorithmByTag(digAlgTag); + sigalg = SECOID_FindyCssmAlgorithmByTag(sigAlgTag); + if (!digalg || !sigalg) + { + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + rv = SECFailure; + goto loser; + } + + rv = SecKeyGetCSPHandle(pk, &csp); + if (rv) { + PORT_SetError(SEC_ERROR_BAD_KEY); + goto loser; + } + rv = SecKeyGetCSSMKey(pk, &key); + if (rv) { + PORT_SetError(SEC_ERROR_BAD_KEY); + goto loser; + } + rv = SecKeyGetCredentials(pk, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault, &accessCred); + if (rv) { + PORT_SetError(SEC_ERROR_BAD_KEY); + goto loser; + } + + rv = CSSM_CSP_CreateSignatureContext(csp, sigalg, accessCred, key, &cc); + if (rv) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto loser; + } + + rv = CSSM_SignData(cc, digest, 1, digalg, &sig); + if (rv) { + SECErrorCodes code = SEC_CssmRtnToSECStatus(rv); + PORT_SetError(code); + goto loser; + } + + result->Length = sig.Length; + result->Data = sig.Data; + +loser: + if (cc) + CSSM_DeleteContext(cc); + + return rv; +} + +SECStatus +VFY_VerifyData(unsigned char *buf, int len, + SecPublicKeyRef pk, SECItem *sig, + SECOidTag digAlgTag, SECOidTag sigAlgTag, void *wincx) +{ + SECOidTag algTag; + CSSM_ALGORITHMS algorithm; + CSSM_CC_HANDLE cc = 0; + CSSM_CSP_HANDLE csp; + OSStatus rv = SECFailure; + CSSM_DATA dataBuf = { (uint32)len, (uint8 *)buf }; + const CSSM_KEY *key; + + algTag = SecCmsUtilMakeSignatureAlgorithm(digAlgTag, sigAlgTag); + algorithm = SECOID_FindyCssmAlgorithmByTag(algTag); + if (!algorithm) + { + rv = algTag == SEC_OID_UNKNOWN ? SecCmsVSSignatureAlgorithmUnknown : SecCmsVSSignatureAlgorithmUnsupported; + goto loser; + } + + rv = SecKeyGetCSPHandle(pk, &csp); + if (rv) + goto loser; + rv = SecKeyGetCSSMKey(pk, &key); + if (rv) + goto loser; + + rv = CSSM_CSP_CreateSignatureContext(csp, algorithm, NULL, key, &cc); + if (rv) + goto loser; + + rv = CSSM_VerifyData(cc, &dataBuf, 1, CSSM_ALGID_NONE, sig); + +loser: + if (cc) + CSSM_DeleteContext(cc); + + return rv; +} + +SECStatus +VFY_VerifyDigest(SECItem *digest, SecPublicKeyRef pk, + SECItem *sig, SECOidTag digAlgTag, SECOidTag sigAlgTag, void *wincx) +{ + CSSM_ALGORITHMS sigalg, digalg; + CSSM_CC_HANDLE cc = 0; + CSSM_CSP_HANDLE csp; + const CSSM_KEY *key; + OSStatus rv; + + digalg = SECOID_FindyCssmAlgorithmByTag(digAlgTag); + sigalg = SECOID_FindyCssmAlgorithmByTag(sigAlgTag); + if (!digalg || !sigalg) + { + rv = digAlgTag == SEC_OID_UNKNOWN || sigAlgTag == SEC_OID_UNKNOWN ? SecCmsVSSignatureAlgorithmUnknown : SecCmsVSSignatureAlgorithmUnsupported; + goto loser; + } + + rv = SecKeyGetCSPHandle(pk, &csp); + if (rv) + goto loser; + rv = SecKeyGetCSSMKey(pk, &key); + if (rv) + goto loser; + + rv = CSSM_CSP_CreateSignatureContext(csp, sigalg, NULL, key, &cc); + if (rv) + goto loser; + + rv = CSSM_VerifyData(cc, digest, 1, digalg, sig); + +loser: + if (cc) + CSSM_DeleteContext(cc); + + return rv; +} + +SECStatus +WRAP_PubWrapSymKey(SecPublicKeyRef publickey, + SecSymmetricKeyRef bulkkey, + CSSM_DATA_PTR encKey) +{ + CSSM_WRAP_KEY wrappedKey = {}; + //CSSM_WRAP_KEY wrappedPk = {} + //CSSM_KEY upk = {}; + CSSM_CC_HANDLE cc = 0; + CSSM_CSP_HANDLE pkCsp, bkCsp; + const CSSM_KEY *pk, *bk, *pubkey; + OSStatus rv; + CSSM_ACCESS_CREDENTIALS accessCred = {}; + + rv = SecKeyGetCSPHandle(publickey, &pkCsp); + if (rv) + goto loser; + rv = SecKeyGetCSSMKey(publickey, &pk); + if (rv) + goto loser; + + rv = SecKeyGetCSPHandle(bulkkey, &bkCsp); + if (rv) + goto loser; + rv = SecKeyGetCSSMKey(bulkkey, &bk); + if (rv) + goto loser; + +#if 1 + pubkey = pk; +#else + /* We need to get the publickey out of it's pkCsp and into the bkCsp so we can operate with it. */ + + /* Make a NULL wrap symmetric context to extract the public key from pkCsp. */ + rv = CSSM_CSP_CreateSymmetricContext(pkCsp, + CSSM_ALGID_NONE, + CSSM_MODE_NONE, + NULL, /* accessCred */ + NULL, /* key */ + NULL, /* iv */ + CSSM_PADDING_NONE, + NULL, /* reserved */ + &cc); + if (rv) + goto loser; + rv = CSSM_WrapKey(cc, + NULL /* accessCred */, + pk, + NULL /* descriptiveData */, + &wrappedPk); + CSSM_DeleteContext(cc); + cc = 0; + + /* Make a NULL unwrap symmetric context to import the public key into bkCsp. */ + rv = CSSM_CSP_CreateSymmetricContext(bkCsp, + CSSM_ALGID_NONE, + CSSM_MODE_NONE, + NULL, /* accessCred */ + NULL, /* key */ + NULL, /* iv */ + CSSM_PADDING_NONE, + NULL, /* reserved */ + &cc); + if (rv) + goto loser; + rv = CSSM_UnwrapKey(cc, NULL, &wrappedPk, usage, attr, NULL /* label */, NULL /* rcc */, &upk, NULL /* descriptiveData */); + CSSM_DeleteContext(cc); + cc = 0; + + pubkey = &upk; +#endif + + rv = CSSM_CSP_CreateAsymmetricContext(bkCsp, + pubkey->KeyHeader.AlgorithmId, + &accessCred, + pubkey, + CSSM_PADDING_PKCS1, + &cc); + if (rv) + goto loser; + + { + /* Set the wrapped key format to indicate we want just the raw bits encrypted. */ + CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT, sizeof(uint32) }; + contextAttribute.Attribute.Uint32 = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7; + rv = CSSM_UpdateContextAttributes(cc, 1, &contextAttribute); + if (rv) + goto loser; + } + + { + /* Set the mode to CSSM_ALGMODE_PKCS1_EME_V15. */ + CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_MODE, sizeof(uint32) }; + contextAttribute.Attribute.Uint32 = CSSM_ALGMODE_NONE; /* CSSM_ALGMODE_PKCS1_EME_V15 */ + rv = CSSM_UpdateContextAttributes(cc, 1, &contextAttribute); + if (rv) + goto loser; + } + + { + // @@@ Stick in an empty initVector to work around a csp bug. + CSSM_DATA initVector = {}; + CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_INIT_VECTOR, sizeof(CSSM_DATA_PTR) }; + contextAttribute.Attribute.Data = &initVector; + rv = CSSM_UpdateContextAttributes(cc, 1, &contextAttribute); + if (rv) + goto loser; + } + + rv = CSSM_WrapKey(cc, + &accessCred, + bk, + NULL, /* descriptiveData */ + &wrappedKey); + if (rv) + goto loser; + + // @@@ Fix leaks! + if (encKey->Length < wrappedKey.KeyData.Length) + abort(); + encKey->Length = wrappedKey.KeyData.Length; + memcpy(encKey->Data, wrappedKey.KeyData.Data, encKey->Length); + CSSM_FreeKey(bkCsp, NULL /* credentials */, &wrappedKey, FALSE); + +loser: + if (cc) + CSSM_DeleteContext(cc); + + return rv; +} + +SecSymmetricKeyRef +WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, SECOidTag bulkalgtag) +{ + SecSymmetricKeyRef bulkkey = NULL; + CSSM_WRAP_KEY wrappedKey = {}; + CSSM_CC_HANDLE cc = 0; + CSSM_CSP_HANDLE pkCsp; + const CSSM_KEY *pk; + CSSM_KEY unwrappedKey = {}; + const CSSM_ACCESS_CREDENTIALS *accessCred; + CSSM_DATA descriptiveData = {}; + CSSM_ALGORITHMS bulkalg; + OSStatus rv; + + rv = SecKeyGetCSPHandle(privkey, &pkCsp); + if (rv) + goto loser; + rv = SecKeyGetCSSMKey(privkey, &pk); + if (rv) + goto loser; + rv = SecKeyGetCredentials(privkey, + CSSM_ACL_AUTHORIZATION_DECRYPT, /* @@@ Should be UNWRAP */ + kSecCredentialTypeDefault, + &accessCred); + if (rv) + goto loser; + + bulkalg = SECOID_FindyCssmAlgorithmByTag(bulkalgtag); + if (!bulkalg) + { + rv = SEC_ERROR_INVALID_ALGORITHM; + goto loser; + } + + rv = CSSM_CSP_CreateAsymmetricContext(pkCsp, + pk->KeyHeader.AlgorithmId, + accessCred, + pk, + CSSM_PADDING_PKCS1, + &cc); + if (rv) + goto loser; + + { + // @@@ Stick in an empty initvector to work around a csp bug. + CSSM_DATA initVector = {}; + CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_INIT_VECTOR, sizeof(CSSM_DATA_PTR) }; + contextAttribute.Attribute.Data = &initVector; + rv = CSSM_UpdateContextAttributes(cc, 1, &contextAttribute); + if (rv) + goto loser; + } + + wrappedKey.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; + wrappedKey.KeyHeader.BlobType = CSSM_KEYBLOB_WRAPPED; + wrappedKey.KeyHeader.Format = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7; + wrappedKey.KeyHeader.AlgorithmId = bulkalg; + wrappedKey.KeyHeader.KeyClass = CSSM_KEYCLASS_SESSION_KEY; + wrappedKey.KeyHeader.WrapAlgorithmId = pk->KeyHeader.AlgorithmId; + wrappedKey.KeyHeader.WrapMode = CSSM_ALGMODE_NONE; /* CSSM_ALGMODE_PKCS1_EME_V15 */ + wrappedKey.KeyData = *encKey; + + rv = CSSM_UnwrapKey(cc, + NULL, /* publicKey */ + &wrappedKey, + CSSM_KEYUSE_DECRYPT, + CSSM_KEYATTR_EXTRACTABLE /* | CSSM_KEYATTR_RETURN_DATA */, + NULL, /* keyLabel */ + NULL, /* rcc */ + &unwrappedKey, + &descriptiveData); + if (rv) { + SECErrorCodes code; + if (CSSM_ERRCODE(rv) == CSSM_ERRCODE_USER_CANCELED + || CSSM_ERRCODE(rv) == CSSM_ERRCODE_OPERATION_AUTH_DENIED + || CSSM_ERRCODE(rv) == CSSM_ERRCODE_OBJECT_USE_AUTH_DENIED) + code = SEC_ERROR_USER_CANCELLED; + else if (CSSM_ERRCODE(rv) == CSSM_ERRCODE_NO_USER_INTERACTION + || rv == CSSMERR_CSP_KEY_USAGE_INCORRECT) + code = SEC_ERROR_INADEQUATE_KEY_USAGE; + else + { + fprintf(stderr, "CSSM_UnwrapKey returned: %08X\n", (uint32_t)rv); + code = SEC_ERROR_LIBRARY_FAILURE; + } + + PORT_SetError(code); + goto loser; + } + + // @@@ Export this key from the csp/dl and import it to the standard csp + rv = SecKeyCreateWithCSSMKey(&unwrappedKey, &bulkkey); + if (rv) + goto loser; + +loser: + if (rv) + PORT_SetError(rv); + + if (cc) + CSSM_DeleteContext(cc); + + return bulkkey; +} diff --git a/Security/libsecurity_smime/lib/cryptohi.h b/Security/libsecurity_smime/lib/cryptohi.h new file mode 100644 index 00000000..f140c4ca --- /dev/null +++ b/Security/libsecurity_smime/lib/cryptohi.h @@ -0,0 +1,143 @@ +/* + * crypto.h - public data structures and prototypes for the crypto library + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#ifndef _CRYPTOHI_H_ +#define _CRYPTOHI_H_ + +#include +#include + + +SEC_BEGIN_PROTOS + + +/****************************************/ +/* +** DER encode/decode DSA signatures +*/ + +/* ANSI X9.57 defines DSA signatures as DER encoded data. Our DSA code (and + * most of the rest of the world) just generates 40 bytes of raw data. These + * functions convert between formats. + */ +//extern SECStatus DSAU_EncodeDerSig(SECItem *dest, SECItem *src); +//extern SECItem *DSAU_DecodeDerSig(SECItem *item); + +/* + * Return a csp handle able to deal with algorithm + */ +extern CSSM_CSP_HANDLE SecCspHandleForAlgorithm(CSSM_ALGORITHMS algorithm); + +/* + * Return a CSSM_ALGORITHMS for a given SECOidTag or 0 if there is none + */ +extern CSSM_ALGORITHMS SECOID_FindyCssmAlgorithmByTag(SECOidTag algTag); + + +/****************************************/ +/* +** Signature creation operations +*/ + +/* +** Sign a single block of data using private key encryption and given +** signature/hash algorithm. +** "result" the final signature data (memory is allocated) +** "buf" the input data to sign +** "len" the amount of data to sign +** "pk" the private key to encrypt with +** "algid" the signature/hash algorithm to sign with +** (must be compatible with the key type). +*/ +extern SECStatus SEC_SignData(SECItem *result, unsigned char *buf, int len, + SecPrivateKeyRef pk, SECOidTag digAlgTag, SECOidTag sigAlgTag); + +/* +** Sign a pre-digested block of data using private key encryption, encoding +** The given signature/hash algorithm. +** "result" the final signature data (memory is allocated) +** "digest" the digest to sign +** "pk" the private key to encrypt with +** "algtag" The algorithm tag to encode (need for RSA only) +*/ +extern SECStatus SGN_Digest(SecPrivateKeyRef privKey, + SECOidTag digAlgTag, SECOidTag sigAlgTag, SECItem *result, SECItem *digest); + +/****************************************/ +/* +** Signature verification operations +*/ + + +/* +** Verify the signature on a block of data for which we already have +** the digest. The signature data is an RSA private key encrypted +** block of data formatted according to PKCS#1. +** "dig" the digest +** "key" the public key to check the signature with +** "sig" the encrypted signature data +** "algid" specifies the signing algorithm to use. This must match +** the key type. +**/ +extern SECStatus VFY_VerifyDigest(SECItem *dig, SecPublicKeyRef key, + SECItem *sig, SECOidTag digAlgTag, SECOidTag sigAlgTag, void *wincx); + +/* +** Verify the signature on a block of data. The signature data is an RSA +** private key encrypted block of data formatted according to PKCS#1. +** "buf" the input data +** "len" the length of the input data +** "key" the public key to check the signature with +** "sig" the encrypted signature data +** "algid" specifies the signing algorithm to use. This must match +** the key type. +*/ +extern SECStatus VFY_VerifyData(unsigned char *buf, int len, + SecPublicKeyRef key, SECItem *sig, + SECOidTag digAlgTag, SECOidTag sigAlgTag, void *wincx); + + + +extern SECStatus WRAP_PubWrapSymKey(SecPublicKeyRef publickey, + SecSymmetricKeyRef bulkkey, + CSSM_DATA_PTR encKey); + + +extern SecSymmetricKeyRef WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, SECOidTag bulkalgtag); + + +SEC_END_PROTOS + +#endif /* _CRYPTOHI_H_ */ diff --git a/Security/libsecurity_smime/lib/plhash.c b/Security/libsecurity_smime/lib/plhash.c new file mode 100644 index 00000000..e7524460 --- /dev/null +++ b/Security/libsecurity_smime/lib/plhash.c @@ -0,0 +1,538 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Portable Runtime (NSPR). + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * PL hash table package. + */ +#include "plhash.h" +#include +#include +#include +#include +#include +#include + +/* Compute the number of buckets in ht */ +#define NBUCKETS(ht) (1 << (PL_HASH_BITS - (ht)->shift)) + +/* The smallest table has 16 buckets */ +#define MINBUCKETSLOG2 4 +#define MINBUCKETS (1 << MINBUCKETSLOG2) + +/* Compute the maximum entries given n buckets that we will tolerate, ~90% */ +#define OVERLOADED(n) ((n) - ((n) >> 3)) + +/* Compute the number of entries below which we shrink the table by half */ +#define UNDERLOADED(n) (((n) > MINBUCKETS) ? ((n) >> 2) : 0) + +/* +** Stubs for default hash allocator ops. +*/ +static void * PR_CALLBACK +DefaultAllocTable(void *pool, PRSize size) +{ +#if defined(XP_MAC) +#pragma unused (pool) +#endif + + return PR_MALLOC(size); +} + +static void PR_CALLBACK +DefaultFreeTable(void *pool, void *item) +{ +#if defined(XP_MAC) +#pragma unused (pool) +#endif + + PR_Free(item); +} + +static PLHashEntry * PR_CALLBACK +DefaultAllocEntry(void *pool, const void *key) +{ +#if defined(XP_MAC) +#pragma unused (pool,key) +#endif + + return PR_NEW(PLHashEntry); +} + +static void PR_CALLBACK +DefaultFreeEntry(void *pool, PLHashEntry *he, PRUintn flag) +{ +#if defined(XP_MAC) +#pragma unused (pool) +#endif + + if (flag == HT_FREE_ENTRY) + PR_Free(he); +} + +static PLHashAllocOps defaultHashAllocOps = { + DefaultAllocTable, DefaultFreeTable, + DefaultAllocEntry, DefaultFreeEntry +}; + +PR_IMPLEMENT(PLHashTable *) +PL_NewHashTable(PRUint32 n, PLHashFunction keyHash, + PLHashComparator keyCompare, PLHashComparator valueCompare, + const PLHashAllocOps *allocOps, void *allocPriv) +{ + PLHashTable *ht; + PRSize nb; + + if (n <= MINBUCKETS) { + n = MINBUCKETSLOG2; + } else { + n = PR_CeilingLog2(n); + if ((PRInt32)n < 0) + return 0; + } + + if (!allocOps) allocOps = &defaultHashAllocOps; + + ht = (PLHashTable*)((*allocOps->allocTable)(allocPriv, sizeof *ht)); + if (!ht) + return 0; + memset(ht, 0, sizeof *ht); + ht->shift = PL_HASH_BITS - n; + n = 1 << n; +#if defined(WIN16) + if (n > 16000) { + (*allocOps->freeTable)(allocPriv, ht); + return 0; + } +#endif /* WIN16 */ + nb = n * sizeof(PLHashEntry *); + ht->buckets = (PLHashEntry**)((*allocOps->allocTable)(allocPriv, nb)); + if (!ht->buckets) { + (*allocOps->freeTable)(allocPriv, ht); + return 0; + } + memset(ht->buckets, 0, nb); + + ht->keyHash = keyHash; + ht->keyCompare = keyCompare; + ht->valueCompare = valueCompare; + ht->allocOps = allocOps; + ht->allocPriv = allocPriv; + return ht; +} + +PR_IMPLEMENT(void) +PL_HashTableDestroy(PLHashTable *ht) +{ + PRUint32 i, n; + PLHashEntry *he, *next; + const PLHashAllocOps *allocOps = ht->allocOps; + void *allocPriv = ht->allocPriv; + + n = NBUCKETS(ht); + for (i = 0; i < n; i++) { + for (he = ht->buckets[i]; he; he = next) { + next = he->next; + (*allocOps->freeEntry)(allocPriv, he, HT_FREE_ENTRY); + } + } +#ifdef DEBUG + memset(ht->buckets, 0xDB, n * sizeof ht->buckets[0]); +#endif + (*allocOps->freeTable)(allocPriv, ht->buckets); +#ifdef DEBUG + memset(ht, 0xDB, sizeof *ht); +#endif + (*allocOps->freeTable)(allocPriv, ht); +} + +/* +** Multiplicative hash, from Knuth 6.4. +*/ +#define GOLDEN_RATIO 0x9E3779B9U + +PR_IMPLEMENT(PLHashEntry **) +PL_HashTableRawLookup(PLHashTable *ht, PLHashNumber keyHash, const void *key) +{ + PLHashEntry *he, **hep, **hep0; + PLHashNumber h; + +#ifdef HASHMETER + ht->nlookups++; +#endif + h = keyHash * GOLDEN_RATIO; + h >>= ht->shift; + hep = hep0 = &ht->buckets[h]; + while ((he = *hep) != 0) { + if (he->keyHash == keyHash && (*ht->keyCompare)(key, he->key)) { + /* Move to front of chain if not already there */ + if (hep != hep0) { + *hep = he->next; + he->next = *hep0; + *hep0 = he; + } + return hep0; + } + hep = &he->next; +#ifdef HASHMETER + ht->nsteps++; +#endif + } + return hep; +} + +/* +** Same as PL_HashTableRawLookup but doesn't reorder the hash entries. +*/ +PR_IMPLEMENT(PLHashEntry **) +PL_HashTableRawLookupConst(PLHashTable *ht, PLHashNumber keyHash, + const void *key) +{ + PLHashEntry *he, **hep; + PLHashNumber h; + +#ifdef HASHMETER + ht->nlookups++; +#endif + h = keyHash * GOLDEN_RATIO; + h >>= ht->shift; + hep = &ht->buckets[h]; + while ((he = *hep) != 0) { + if (he->keyHash == keyHash && (*ht->keyCompare)(key, he->key)) { + break; + } + hep = &he->next; +#ifdef HASHMETER + ht->nsteps++; +#endif + } + return hep; +} + +PR_IMPLEMENT(PLHashEntry *) +PL_HashTableRawAdd(PLHashTable *ht, PLHashEntry **hep, + PLHashNumber keyHash, const void *key, void *value) +{ + PRUint32 i, n; + PLHashEntry *he, *next, **oldbuckets; + PRSize nb; + + /* Grow the table if it is overloaded */ + n = NBUCKETS(ht); + if (ht->nentries >= OVERLOADED(n)) { + oldbuckets = ht->buckets; +#if defined(WIN16) + if (2 * n > 16000) + return 0; +#endif /* WIN16 */ + nb = 2 * n * sizeof(PLHashEntry *); + ht->buckets = (PLHashEntry**) + ((*ht->allocOps->allocTable)(ht->allocPriv, nb)); + if (!ht->buckets) { + ht->buckets = oldbuckets; + return 0; + } + memset(ht->buckets, 0, nb); +#ifdef HASHMETER + ht->ngrows++; +#endif + ht->shift--; + + for (i = 0; i < n; i++) { + for (he = oldbuckets[i]; he; he = next) { + next = he->next; + hep = PL_HashTableRawLookup(ht, he->keyHash, he->key); + PR_ASSERT(*hep == 0); + he->next = 0; + *hep = he; + } + } +#ifdef DEBUG + memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]); +#endif + (*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets); + hep = PL_HashTableRawLookup(ht, keyHash, key); + } + + /* Make a new key value entry */ + he = (*ht->allocOps->allocEntry)(ht->allocPriv, key); + if (!he) + return 0; + he->keyHash = keyHash; + he->key = key; + he->value = value; + he->next = *hep; + *hep = he; + ht->nentries++; + return he; +} + +PR_IMPLEMENT(PLHashEntry *) +PL_HashTableAdd(PLHashTable *ht, const void *key, void *value) +{ + PLHashNumber keyHash; + PLHashEntry *he, **hep; + + keyHash = (*ht->keyHash)(key); + hep = PL_HashTableRawLookup(ht, keyHash, key); + if ((he = *hep) != 0) { + /* Hit; see if values match */ + if ((*ht->valueCompare)(he->value, value)) { + /* key,value pair is already present in table */ + return he; + } + if (he->value) + (*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_VALUE); + he->value = value; + return he; + } + return PL_HashTableRawAdd(ht, hep, keyHash, key, value); +} + +PR_IMPLEMENT(void) +PL_HashTableRawRemove(PLHashTable *ht, PLHashEntry **hep, PLHashEntry *he) +{ + PRUint32 i, n; + PLHashEntry *next, **oldbuckets; + PRSize nb; + + *hep = he->next; + (*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_ENTRY); + + /* Shrink table if it's underloaded */ + n = NBUCKETS(ht); + if (--ht->nentries < UNDERLOADED(n)) { + oldbuckets = ht->buckets; + nb = n * sizeof(PLHashEntry*) / 2; + ht->buckets = (PLHashEntry**)( + (*ht->allocOps->allocTable)(ht->allocPriv, nb)); + if (!ht->buckets) { + ht->buckets = oldbuckets; + return; + } + memset(ht->buckets, 0, nb); +#ifdef HASHMETER + ht->nshrinks++; +#endif + ht->shift++; + + for (i = 0; i < n; i++) { + for (he = oldbuckets[i]; he; he = next) { + next = he->next; + hep = PL_HashTableRawLookup(ht, he->keyHash, he->key); + PR_ASSERT(*hep == 0); + he->next = 0; + *hep = he; + } + } +#ifdef DEBUG + memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]); +#endif + (*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets); + } +} + +PR_IMPLEMENT(Boolean) +PL_HashTableRemove(PLHashTable *ht, const void *key) +{ + PLHashNumber keyHash; + PLHashEntry *he, **hep; + + keyHash = (*ht->keyHash)(key); + hep = PL_HashTableRawLookup(ht, keyHash, key); + if ((he = *hep) == 0) + return PR_FALSE; + + /* Hit; remove element */ + PL_HashTableRawRemove(ht, hep, he); + return PR_TRUE; +} + +PR_IMPLEMENT(void *) +PL_HashTableLookup(PLHashTable *ht, const void *key) +{ + PLHashNumber keyHash; + PLHashEntry *he, **hep; + + keyHash = (*ht->keyHash)(key); + hep = PL_HashTableRawLookup(ht, keyHash, key); + if ((he = *hep) != 0) { + return he->value; + } + return 0; +} + +/* +** Same as PL_HashTableLookup but doesn't reorder the hash entries. +*/ +PR_IMPLEMENT(void *) +PL_HashTableLookupConst(PLHashTable *ht, const void *key) +{ + PLHashNumber keyHash; + PLHashEntry *he, **hep; + + keyHash = (*ht->keyHash)(key); + hep = PL_HashTableRawLookupConst(ht, keyHash, key); + if ((he = *hep) != 0) { + return he->value; + } + return 0; +} + +/* +** Iterate over the entries in the hash table calling func for each +** entry found. Stop if "f" says to (return value & PR_ENUMERATE_STOP). +** Return a count of the number of elements scanned. +*/ +PR_IMPLEMENT(int) +PL_HashTableEnumerateEntries(PLHashTable *ht, PLHashEnumerator f, void *arg) +{ + PLHashEntry *he, **hep; + PRUint32 i, nbuckets; + int rv, n = 0; + PLHashEntry *todo = 0; + + nbuckets = NBUCKETS(ht); + for (i = 0; i < nbuckets; i++) { + hep = &ht->buckets[i]; + while ((he = *hep) != 0) { + rv = (*f)(he, n, arg); + n++; + if (rv & (HT_ENUMERATE_REMOVE | HT_ENUMERATE_UNHASH)) { + *hep = he->next; + if (rv & HT_ENUMERATE_REMOVE) { + he->next = todo; + todo = he; + } + } else { + hep = &he->next; + } + if (rv & HT_ENUMERATE_STOP) { + goto out; + } + } + } + +out: + hep = &todo; + while ((he = *hep) != 0) { + PL_HashTableRawRemove(ht, hep, he); + } + return n; +} + +#ifdef HASHMETER +#include +#include + +PR_IMPLEMENT(void) +PL_HashTableDumpMeter(PLHashTable *ht, PLHashEnumerator dump, FILE *fp) +{ + double mean, variance; + PRUint32 nchains, nbuckets; + PRUint32 i, n, maxChain, maxChainLen; + PLHashEntry *he; + + variance = 0; + nchains = 0; + maxChainLen = 0; + nbuckets = NBUCKETS(ht); + for (i = 0; i < nbuckets; i++) { + he = ht->buckets[i]; + if (!he) + continue; + nchains++; + for (n = 0; he; he = he->next) + n++; + variance += n * n; + if (n > maxChainLen) { + maxChainLen = n; + maxChain = i; + } + } + mean = (double)ht->nentries / nchains; + variance = fabs(variance / nchains - mean * mean); + + fprintf(fp, "\nHash table statistics:\n"); + fprintf(fp, " number of lookups: %u\n", ht->nlookups); + fprintf(fp, " number of entries: %u\n", ht->nentries); + fprintf(fp, " number of grows: %u\n", ht->ngrows); + fprintf(fp, " number of shrinks: %u\n", ht->nshrinks); + fprintf(fp, " mean steps per hash: %g\n", (double)ht->nsteps + / ht->nlookups); + fprintf(fp, "mean hash chain length: %g\n", mean); + fprintf(fp, " standard deviation: %g\n", sqrt(variance)); + fprintf(fp, " max hash chain length: %u\n", maxChainLen); + fprintf(fp, " max hash chain: [%u]\n", maxChain); + + for (he = ht->buckets[maxChain], i = 0; he; he = he->next, i++) + if ((*dump)(he, i, fp) != HT_ENUMERATE_NEXT) + break; +} +#endif /* HASHMETER */ + +PR_IMPLEMENT(int) +PL_HashTableDump(PLHashTable *ht, PLHashEnumerator dump, FILE *fp) +{ + int count; + + count = PL_HashTableEnumerateEntries(ht, dump, fp); +#ifdef HASHMETER + PL_HashTableDumpMeter(ht, dump, fp); +#endif + return count; +} + +PR_IMPLEMENT(PLHashNumber) +PL_HashString(const void *key) +{ + PLHashNumber h; + const PRUint8 *s; + + h = 0; + for (s = (const PRUint8*)key; *s; s++) + h = (h >> 28) ^ (h << 4) ^ *s; + return h; +} + +PR_IMPLEMENT(int) +PL_CompareStrings(const void *v1, const void *v2) +{ + return strcmp((const char*)v1, (const char*)v2) == 0; +} + +PR_IMPLEMENT(int) +PL_CompareValues(const void *v1, const void *v2) +{ + return v1 == v2; +} diff --git a/Security/libsecurity_smime/lib/plhash.h b/Security/libsecurity_smime/lib/plhash.h new file mode 100644 index 00000000..1b5aec9c --- /dev/null +++ b/Security/libsecurity_smime/lib/plhash.h @@ -0,0 +1,164 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Portable Runtime (NSPR). + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#ifndef plhash_h___ +#define plhash_h___ +/* + * API to portable hash table code. + */ +#include +#include +// @@@ for Boolean +#include + +PR_BEGIN_EXTERN_C + +typedef struct PLHashEntry PLHashEntry; +typedef struct PLHashTable PLHashTable; +typedef PRUint32 PLHashNumber; +#define PL_HASH_BITS 32 /* Number of bits in PLHashNumber */ +typedef PLHashNumber (PR_CALLBACK *PLHashFunction)(const void *key); +typedef PRIntn (PR_CALLBACK *PLHashComparator)(const void *v1, const void *v2); + +#if defined(XP_OS2_VACPP) && defined(VACPP_FLIP) /* for nsSpaceManager.cpp */ +PR_END_EXTERN_C /* and nsHTMLDocument.cpp */ +#endif +typedef PRIntn (PR_CALLBACK *PLHashEnumerator)(PLHashEntry *he, PRIntn i, void *arg); + +#if defined(XP_OS2_VACPP) && defined(VACPP_FLIP) +PR_BEGIN_EXTERN_C +#endif + +/* Flag bits in PLHashEnumerator's return value */ +#define HT_ENUMERATE_NEXT 0 /* continue enumerating entries */ +#define HT_ENUMERATE_STOP 1 /* stop enumerating entries */ +#define HT_ENUMERATE_REMOVE 2 /* remove and free the current entry */ +#define HT_ENUMERATE_UNHASH 4 /* just unhash the current entry */ + +typedef struct PLHashAllocOps { + void * (PR_CALLBACK *allocTable)(void *pool, PRSize size); + void (PR_CALLBACK *freeTable)(void *pool, void *item); + PLHashEntry * (PR_CALLBACK *allocEntry)(void *pool, const void *key); + void (PR_CALLBACK *freeEntry)(void *pool, PLHashEntry *he, PRUintn flag); +} PLHashAllocOps; + +#define HT_FREE_VALUE 0 /* just free the entry's value */ +#define HT_FREE_ENTRY 1 /* free value and entire entry */ + +struct PLHashEntry { + PLHashEntry *next; /* hash chain linkage */ + PLHashNumber keyHash; /* key hash function result */ + const void *key; /* ptr to opaque key */ + void *value; /* ptr to opaque value */ +}; + +struct PLHashTable { + PLHashEntry **buckets; /* vector of hash buckets */ + PRUint32 nentries; /* number of entries in table */ + PRUint32 shift; /* multiplicative hash shift */ + PLHashFunction keyHash; /* key hash function */ + PLHashComparator keyCompare; /* key comparison function */ + PLHashComparator valueCompare; /* value comparison function */ + const PLHashAllocOps *allocOps; /* allocation operations */ + void *allocPriv; /* allocation private data */ +#ifdef HASHMETER + PRUint32 nlookups; /* total number of lookups */ + PRUint32 nsteps; /* number of hash chains traversed */ + PRUint32 ngrows; /* number of table expansions */ + PRUint32 nshrinks; /* number of table contractions */ +#endif +}; + +/* + * Create a new hash table. + * If allocOps is null, use default allocator ops built on top of malloc(). + */ +PR_EXTERN(PLHashTable *) +PL_NewHashTable(PRUint32 numBuckets, PLHashFunction keyHash, + PLHashComparator keyCompare, PLHashComparator valueCompare, + const PLHashAllocOps *allocOps, void *allocPriv); + +PR_EXTERN(void) +PL_HashTableDestroy(PLHashTable *ht); + +/* Higher level access methods */ +PR_EXTERN(PLHashEntry *) +PL_HashTableAdd(PLHashTable *ht, const void *key, void *value); + +PR_EXTERN(Boolean) +PL_HashTableRemove(PLHashTable *ht, const void *key); + +PR_EXTERN(void *) +PL_HashTableLookup(PLHashTable *ht, const void *key); + +PR_EXTERN(void *) +PL_HashTableLookupConst(PLHashTable *ht, const void *key); + +PR_EXTERN(PRIntn) +PL_HashTableEnumerateEntries(PLHashTable *ht, PLHashEnumerator f, void *arg); + +/* General-purpose C string hash function. */ +PR_EXTERN(PLHashNumber) +PL_HashString(const void *key); + +/* Compare strings using strcmp(), return true if equal. */ +PR_EXTERN(PRIntn) +PL_CompareStrings(const void *v1, const void *v2); + +/* Stub function just returns v1 == v2 */ +PR_EXTERN(PRIntn) +PL_CompareValues(const void *v1, const void *v2); + +/* Low level access methods */ +PR_EXTERN(PLHashEntry **) +PL_HashTableRawLookup(PLHashTable *ht, PLHashNumber keyHash, const void *key); + +PR_EXTERN(PLHashEntry **) +PL_HashTableRawLookupConst(PLHashTable *ht, PLHashNumber keyHash, + const void *key); + +PR_EXTERN(PLHashEntry *) +PL_HashTableRawAdd(PLHashTable *ht, PLHashEntry **hep, PLHashNumber keyHash, + const void *key, void *value); + +PR_EXTERN(void) +PL_HashTableRawRemove(PLHashTable *ht, PLHashEntry **hep, PLHashEntry *he); + +/* This can be trivially implemented using PL_HashTableEnumerateEntries. */ +PR_EXTERN(PRIntn) +PL_HashTableDump(PLHashTable *ht, PLHashEnumerator dump, FILE *fp); + +PR_END_EXTERN_C + +#endif /* plhash_h___ */ diff --git a/Security/libsecurity_smime/lib/secalgid.c b/Security/libsecurity_smime/lib/secalgid.c new file mode 100644 index 00000000..623b7f9f --- /dev/null +++ b/Security/libsecurity_smime/lib/secalgid.c @@ -0,0 +1,172 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "secoid.h" +#include "secitem.h" +#include +#include + +const SecAsn1Template SECOID_AlgorithmIDTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SECAlgorithmID) }, + { SEC_ASN1_OBJECT_ID, + offsetof(SECAlgorithmID,algorithm), }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY, + offsetof(SECAlgorithmID,parameters), }, + { 0 } +}; + +SECOidTag +SECOID_GetAlgorithmTag(const SECAlgorithmID *id) +{ + if (id == NULL || id->algorithm.Data == NULL) + return SEC_OID_UNKNOWN; + + return SECOID_FindOIDTag (&(id->algorithm)); +} + +SECStatus +SECOID_SetAlgorithmID(PRArenaPool *arena, SECAlgorithmID *id, SECOidTag which, + SECItem *params) +{ + SECOidData *oiddata; + Boolean add_null_param; + + oiddata = SECOID_FindOIDByTag(which); + if ( !oiddata ) + { + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + return SECFailure; + } + + if (SECITEM_CopyItem(arena, &id->algorithm, &oiddata->oid)) + return SECFailure; + + switch (which) + { + case SEC_OID_MD2: + case SEC_OID_MD4: + case SEC_OID_MD5: + case SEC_OID_SHA1: + case SEC_OID_SHA256: + case SEC_OID_SHA384: + case SEC_OID_SHA512: + case SEC_OID_PKCS1_RSA_ENCRYPTION: + case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION: + case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION: + case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: + case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: + case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION: + case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION: + case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION: + add_null_param = PR_TRUE; + break; + default: + add_null_param = PR_FALSE; + break; + } + + if (params) { + /* + * I am specifically *not* enforcing the following assertion + * (by following it up with an error and a return of failure) + * because I do not want to introduce any change in the current + * behavior. But I do want for us to notice if the following is + * ever true, because I do not think it should be so and probably + * signifies an error/bug somewhere. + * This assertion removed Sep 9 2008 by dmitch, we really do need + * to be able to do this for an odd SEC_OID_EC_PUBLIC_KEY case. + * + PORT_Assert(!add_null_param || (params->Length == 2 + && params->Data[0] == SEC_ASN1_NULL + && params->Data[1] == 0)); + */ + if (SECITEM_CopyItem(arena, &id->parameters, params)) { + return SECFailure; + } + } else { + /* + * Again, this is not considered an error. But if we assume + * that nobody tries to set the parameters field themselves + * (but always uses this routine to do that), then we should + * not hit the following assertion. Unless they forgot to zero + * the structure, which could also be a bad (and wrong) thing. + */ + PORT_Assert(id->parameters.Data == NULL); + + if (add_null_param) { + (void) SECITEM_AllocItem(arena, &id->parameters, 2); + if (id->parameters.Data == NULL) { + return SECFailure; + } + id->parameters.Data[0] = SEC_ASN1_NULL; + id->parameters.Data[1] = 0; + } + } + + return SECSuccess; +} + +SECStatus +SECOID_CopyAlgorithmID(PRArenaPool *arena, SECAlgorithmID *to, const SECAlgorithmID *from) +{ + SECStatus rv; + + rv = SECITEM_CopyItem(arena, &to->algorithm, &from->algorithm); + if (rv) return rv; + rv = SECITEM_CopyItem(arena, &to->parameters, &from->parameters); + return rv; +} + +void SECOID_DestroyAlgorithmID(SECAlgorithmID *algid, Boolean freeit) +{ + SECITEM_FreeItem(&algid->parameters, PR_FALSE); + SECITEM_FreeItem(&algid->algorithm, PR_FALSE); + if(freeit == PR_TRUE) + PORT_Free(algid); +} + +SECComparison +SECOID_CompareAlgorithmID(const SECAlgorithmID *a, const SECAlgorithmID *b) +{ + SECComparison rv; + + rv = SECITEM_CompareItem(&a->algorithm, &b->algorithm); + if (rv) return rv; + rv = SECITEM_CompareItem(&a->parameters, &b->parameters); + return rv; +} + +/* This functions simply returns the address of the above-declared template. */ +SEC_ASN1_CHOOSER_IMPLEMENT(SECOID_AlgorithmIDTemplate) + diff --git a/libsecurity_smime/lib/secitem.c b/Security/libsecurity_smime/lib/secitem.c similarity index 100% rename from libsecurity_smime/lib/secitem.c rename to Security/libsecurity_smime/lib/secitem.c diff --git a/libsecurity_smime/lib/secitem.h b/Security/libsecurity_smime/lib/secitem.h similarity index 100% rename from libsecurity_smime/lib/secitem.h rename to Security/libsecurity_smime/lib/secitem.h diff --git a/Security/libsecurity_smime/lib/secoid.c b/Security/libsecurity_smime/lib/secoid.c new file mode 100644 index 00000000..ac33842a --- /dev/null +++ b/Security/libsecurity_smime/lib/secoid.c @@ -0,0 +1,1490 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "secoid.h" +#include "secitem.h" +#include "plhash.h" + +#include +#include +#include + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-const-variable" + +/* MISSI Mosaic Object ID space */ +#define USGOV 0x60, 0x86, 0x48, 0x01, 0x65 +#define MISSI USGOV, 0x02, 0x01, 0x01 +#define MISSI_OLD_KEA_DSS MISSI, 0x0c +#define MISSI_OLD_DSS MISSI, 0x02 +#define MISSI_KEA_DSS MISSI, 0x14 +#define MISSI_DSS MISSI, 0x13 +#define MISSI_KEA MISSI, 0x0a +#define MISSI_ALT_KEA MISSI, 0x16 + +#define NISTALGS USGOV, 3, 4 +#define AES NISTALGS, 1 +#define SHAXXX NISTALGS, 2 + +/** + ** The Netscape OID space is allocated by Terry Hayes. If you need + ** a piece of the space, contact him at thayes@netscape.com. + **/ + +/* Netscape Communications Corporation Object ID space */ +/* { 2 16 840 1 113730 } */ +#define NETSCAPE_OID 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42 +#define NETSCAPE_CERT_EXT NETSCAPE_OID, 0x01 +#define NETSCAPE_DATA_TYPE NETSCAPE_OID, 0x02 +/* netscape directory oid - owned by Mark Smith (mcs@netscape.com) */ +#define NETSCAPE_DIRECTORY NETSCAPE_OID, 0x03 +#define NETSCAPE_POLICY NETSCAPE_OID, 0x04 +#define NETSCAPE_CERT_SERVER NETSCAPE_OID, 0x05 +#define NETSCAPE_ALGS NETSCAPE_OID, 0x06 /* algorithm OIDs */ +#define NETSCAPE_NAME_COMPONENTS NETSCAPE_OID, 0x07 + +#define NETSCAPE_CERT_EXT_AIA NETSCAPE_CERT_EXT, 0x10 +#define NETSCAPE_CERT_SERVER_CRMF NETSCAPE_CERT_SERVER, 0x01 + +/* these are old and should go away soon */ +#define OLD_NETSCAPE 0x60, 0x86, 0x48, 0xd8, 0x6a +#define NS_CERT_EXT OLD_NETSCAPE, 0x01 +#define NS_FILE_TYPE OLD_NETSCAPE, 0x02 +#define NS_IMAGE_TYPE OLD_NETSCAPE, 0x03 + +/* RSA OID name space */ +#define RSADSI 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d +#define PKCS RSADSI, 0x01 +#define DIGEST RSADSI, 0x02 +#define CIPHER RSADSI, 0x03 +#define PKCS1 PKCS, 0x01 +#define PKCS5 PKCS, 0x05 +#define PKCS7 PKCS, 0x07 +#define PKCS9 PKCS, 0x09 +#define PKCS12 PKCS, 0x0c + +/* Fortezza algorithm OID space: { 2 16 840 1 101 2 1 1 } */ +/* ### mwelch -- Is this just for algorithms, or all of Fortezza? */ +#define FORTEZZA_ALG 0x60, 0x86, 0x48, 0x01, 0x65, 0x02, 0x01, 0x01 + +/* Other OID name spaces */ +#define ALGORITHM 0x2b, 0x0e, 0x03, 0x02 +#define X500 0x55 +#define X520_ATTRIBUTE_TYPE X500, 0x04 +#define X500_ALG X500, 0x08 +#define X500_ALG_ENCRYPTION X500_ALG, 0x01 + +/** X.509 v3 Extension OID + ** {joint-iso-ccitt (2) ds(5) 29} + **/ +#define ID_CE_OID X500, 0x1d + +#define RFC1274_ATTR_TYPE 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x1 +/* #define RFC2247_ATTR_TYPE 0x09, 0x92, 0x26, 0xf5, 0x98, 0x1e, 0x64, 0x1 this is WRONG! */ + +/* PKCS #12 name spaces */ +#define PKCS12_MODE_IDS PKCS12, 0x01 +#define PKCS12_ESPVK_IDS PKCS12, 0x02 +#define PKCS12_BAG_IDS PKCS12, 0x03 +#define PKCS12_CERT_BAG_IDS PKCS12, 0x04 +#define PKCS12_OIDS PKCS12, 0x05 +#define PKCS12_PBE_IDS PKCS12_OIDS, 0x01 +#define PKCS12_ENVELOPING_IDS PKCS12_OIDS, 0x02 +#define PKCS12_SIGNATURE_IDS PKCS12_OIDS, 0x03 +#define PKCS12_V2_PBE_IDS PKCS12, 0x01 +#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 +#define PKCS12_V1_BAG_IDS PKCS12_VERSION1, 1 + +/* for DSA algorithm */ +/* { iso(1) member-body(2) us(840) x9-57(10040) x9algorithm(4) } */ +#define ANSI_X9_ALGORITHM 0x2a, 0x86, 0x48, 0xce, 0x38, 0x4 + +/* for DH algorithm */ +/* { iso(1) member-body(2) us(840) x9-57(10046) number-type(2) } */ +/* need real OID person to look at this, copied the above line + * and added 6 to second to last value (and changed '4' to '2' */ +#define ANSI_X942_ALGORITHM 0x2a, 0x86, 0x48, 0xce, 0x3e, 0x2 + +#define VERISIGN 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x45 + +#define PKIX 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07 +#define PKIX_CERT_EXTENSIONS PKIX, 1 +#define PKIX_POLICY_QUALIFIERS PKIX, 2 +#define PKIX_KEY_USAGE PKIX, 3 +#define PKIX_ACCESS_DESCRIPTION PKIX, 0x30 +#define PKIX_OCSP PKIX_ACCESS_DESCRIPTION, 1 + +#define PKIX_ID_PKIP PKIX, 5 +#define PKIX_ID_REGCTRL PKIX_ID_PKIP, 1 +#define PKIX_ID_REGINFO PKIX_ID_PKIP, 2 + +/* Microsoft Object ID space */ +/* { 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 + +/* 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 + +#define CONST_OID static const unsigned char + +CONST_OID md2[] = { DIGEST, 0x02 }; +CONST_OID md4[] = { DIGEST, 0x04 }; +CONST_OID md5[] = { DIGEST, 0x05 }; + +CONST_OID rc2cbc[] = { CIPHER, 0x02 }; +CONST_OID rc4[] = { CIPHER, 0x04 }; +CONST_OID desede3cbc[] = { CIPHER, 0x07 }; +CONST_OID rc5cbcpad[] = { CIPHER, 0x09 }; + +CONST_OID desecb[] = { ALGORITHM, 0x06 }; +CONST_OID descbc[] = { ALGORITHM, 0x07 }; +CONST_OID desofb[] = { ALGORITHM, 0x08 }; +CONST_OID descfb[] = { ALGORITHM, 0x09 }; +CONST_OID desmac[] = { ALGORITHM, 0x0a }; +CONST_OID sdn702DSASignature[] = { ALGORITHM, 0x0c }; +CONST_OID isoSHAWithRSASignature[] = { ALGORITHM, 0x0f }; +CONST_OID desede[] = { ALGORITHM, 0x11 }; +CONST_OID sha1[] = { ALGORITHM, 0x1a }; +CONST_OID bogusDSASignaturewithSHA1Digest[] = { ALGORITHM, 0x1b }; + +CONST_OID pkcs1RSAEncryption[] = { PKCS1, 0x01 }; +CONST_OID pkcs1MD2WithRSAEncryption[] = { PKCS1, 0x02 }; +CONST_OID pkcs1MD4WithRSAEncryption[] = { PKCS1, 0x03 }; +CONST_OID pkcs1MD5WithRSAEncryption[] = { PKCS1, 0x04 }; +CONST_OID pkcs1SHA1WithRSAEncryption[] = { PKCS1, 0x05 }; +CONST_OID pkcs1SHA256WithRSAEncryption[] = { PKCS1, 11 }; +CONST_OID pkcs1SHA384WithRSAEncryption[] = { PKCS1, 12 }; +CONST_OID pkcs1SHA512WithRSAEncryption[] = { PKCS1, 13 }; + +CONST_OID pkcs5PbeWithMD2AndDEScbc[] = { PKCS5, 0x01 }; +CONST_OID pkcs5PbeWithMD5AndDEScbc[] = { PKCS5, 0x03 }; +CONST_OID pkcs5PbeWithSha1AndDEScbc[] = { PKCS5, 0x0a }; + +CONST_OID pkcs7[] = { PKCS7 }; +CONST_OID pkcs7Data[] = { PKCS7, 0x01 }; +CONST_OID pkcs7SignedData[] = { PKCS7, 0x02 }; +CONST_OID pkcs7EnvelopedData[] = { PKCS7, 0x03 }; +CONST_OID pkcs7SignedEnvelopedData[] = { PKCS7, 0x04 }; +CONST_OID pkcs7DigestedData[] = { PKCS7, 0x05 }; +CONST_OID pkcs7EncryptedData[] = { PKCS7, 0x06 }; + +CONST_OID pkcs9EmailAddress[] = { PKCS9, 0x01 }; +CONST_OID pkcs9UnstructuredName[] = { PKCS9, 0x02 }; +CONST_OID pkcs9ContentType[] = { PKCS9, 0x03 }; +CONST_OID pkcs9MessageDigest[] = { PKCS9, 0x04 }; +CONST_OID pkcs9SigningTime[] = { PKCS9, 0x05 }; +CONST_OID pkcs9CounterSignature[] = { PKCS9, 0x06 }; +CONST_OID pkcs9ChallengePassword[] = { PKCS9, 0x07 }; +CONST_OID pkcs9UnstructuredAddress[] = { PKCS9, 0x08 }; +CONST_OID pkcs9ExtendedCertificateAttributes[] = { PKCS9, 0x09 }; +CONST_OID pkcs9SMIMECapabilities[] = { PKCS9, 15 }; +CONST_OID pkcs9FriendlyName[] = { PKCS9, 20 }; +CONST_OID pkcs9LocalKeyID[] = { PKCS9, 21 }; + +CONST_OID pkcs9X509Certificate[] = { PKCS9_CERT_TYPES, 1 }; +CONST_OID pkcs9SDSICertificate[] = { PKCS9_CERT_TYPES, 2 }; +CONST_OID pkcs9X509CRL[] = { PKCS9_CRL_TYPES, 1 }; + +/* RFC2630 (CMS) OIDs */ +CONST_OID cmsESDH[] = { PKCS9_SMIME_ALGS, 5 }; +CONST_OID cms3DESwrap[] = { PKCS9_SMIME_ALGS, 6 }; +CONST_OID cmsRC2wrap[] = { PKCS9_SMIME_ALGS, 7 }; + +/* RFC2633 SMIME message attributes */ +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 }; +CONST_OID x520StateOrProvinceName[] = { X520_ATTRIBUTE_TYPE, 8 }; +CONST_OID x520OrgName[] = { X520_ATTRIBUTE_TYPE, 10 }; +CONST_OID x520OrgUnitName[] = { X520_ATTRIBUTE_TYPE, 11 }; +CONST_OID x520DnQualifier[] = { X520_ATTRIBUTE_TYPE, 46 }; + +CONST_OID nsTypeGIF[] = { NETSCAPE_DATA_TYPE, 0x01 }; +CONST_OID nsTypeJPEG[] = { NETSCAPE_DATA_TYPE, 0x02 }; +CONST_OID nsTypeURL[] = { NETSCAPE_DATA_TYPE, 0x03 }; +CONST_OID nsTypeHTML[] = { NETSCAPE_DATA_TYPE, 0x04 }; +CONST_OID nsTypeCertSeq[] = { NETSCAPE_DATA_TYPE, 0x05 }; + +CONST_OID missiCertKEADSSOld[] = { MISSI_OLD_KEA_DSS }; +CONST_OID missiCertDSSOld[] = { MISSI_OLD_DSS }; +CONST_OID missiCertKEADSS[] = { MISSI_KEA_DSS }; +CONST_OID missiCertDSS[] = { MISSI_DSS }; +CONST_OID missiCertKEA[] = { MISSI_KEA }; +CONST_OID missiCertAltKEA[] = { MISSI_ALT_KEA }; +CONST_OID x500RSAEncryption[] = { X500_ALG_ENCRYPTION, 0x01 }; + +/* added for alg 1485 */ +CONST_OID rfc1274Uid[] = { RFC1274_ATTR_TYPE, 1 }; +CONST_OID rfc1274Mail[] = { RFC1274_ATTR_TYPE, 3 }; +CONST_OID rfc2247DomainComponent[] = { RFC1274_ATTR_TYPE, 25 }; + +/* Netscape private certificate extensions */ +CONST_OID nsCertExtNetscapeOK[] = { NS_CERT_EXT, 1 }; +CONST_OID nsCertExtIssuerLogo[] = { NS_CERT_EXT, 2 }; +CONST_OID nsCertExtSubjectLogo[] = { NS_CERT_EXT, 3 }; +CONST_OID nsExtCertType[] = { NETSCAPE_CERT_EXT, 0x01 }; +CONST_OID nsExtBaseURL[] = { NETSCAPE_CERT_EXT, 0x02 }; +CONST_OID nsExtRevocationURL[] = { NETSCAPE_CERT_EXT, 0x03 }; +CONST_OID nsExtCARevocationURL[] = { NETSCAPE_CERT_EXT, 0x04 }; +CONST_OID nsExtCACRLURL[] = { NETSCAPE_CERT_EXT, 0x05 }; +CONST_OID nsExtCACertURL[] = { NETSCAPE_CERT_EXT, 0x06 }; +CONST_OID nsExtCertRenewalURL[] = { NETSCAPE_CERT_EXT, 0x07 }; +CONST_OID nsExtCAPolicyURL[] = { NETSCAPE_CERT_EXT, 0x08 }; +CONST_OID nsExtHomepageURL[] = { NETSCAPE_CERT_EXT, 0x09 }; +CONST_OID nsExtEntityLogo[] = { NETSCAPE_CERT_EXT, 0x0a }; +CONST_OID nsExtUserPicture[] = { NETSCAPE_CERT_EXT, 0x0b }; +CONST_OID nsExtSSLServerName[] = { NETSCAPE_CERT_EXT, 0x0c }; +CONST_OID nsExtComment[] = { NETSCAPE_CERT_EXT, 0x0d }; + +/* the following 2 extensions are defined for and used by Cartman(NSM) */ +CONST_OID nsExtLostPasswordURL[] = { NETSCAPE_CERT_EXT, 0x0e }; +CONST_OID nsExtCertRenewalTime[] = { NETSCAPE_CERT_EXT, 0x0f }; + +CONST_OID nsExtAIACertRenewal[] = { NETSCAPE_CERT_EXT_AIA, 0x01 }; +CONST_OID nsExtCertScopeOfUse[] = { NETSCAPE_CERT_EXT, 0x11 }; +/* Reserved Netscape (2 16 840 1 113730 1 18) = { NETSCAPE_CERT_EXT, 0x12 }; */ + +/* Netscape policy values */ +CONST_OID nsKeyUsageGovtApproved[] = { NETSCAPE_POLICY, 0x01 }; + +/* Netscape other name types */ +CONST_OID netscapeNickname[] = { NETSCAPE_NAME_COMPONENTS, 0x01}; +/* Reserved Netscape REF605437 + (2 16 840 1 113730 7 2) = { NETSCAPE_NAME_COMPONENTS, 0x02 }; */ + +/* OIDs needed for cert server */ +CONST_OID netscapeRecoveryRequest[] = { NETSCAPE_CERT_SERVER_CRMF, 0x01 }; + + +/* Standard x.509 v3 Certificate Extensions */ +CONST_OID x509SubjectDirectoryAttr[] = { ID_CE_OID, 9 }; +CONST_OID x509SubjectKeyID[] = { ID_CE_OID, 14 }; +CONST_OID x509KeyUsage[] = { ID_CE_OID, 15 }; +CONST_OID x509PrivateKeyUsagePeriod[] = { ID_CE_OID, 16 }; +CONST_OID x509SubjectAltName[] = { ID_CE_OID, 17 }; +CONST_OID x509IssuerAltName[] = { ID_CE_OID, 18 }; +CONST_OID x509BasicConstraints[] = { ID_CE_OID, 19 }; +CONST_OID x509NameConstraints[] = { ID_CE_OID, 30 }; +CONST_OID x509CRLDistPoints[] = { ID_CE_OID, 31 }; +CONST_OID x509CertificatePolicies[] = { ID_CE_OID, 32 }; +CONST_OID x509PolicyMappings[] = { ID_CE_OID, 33 }; +CONST_OID x509PolicyConstraints[] = { ID_CE_OID, 34 }; +CONST_OID x509AuthKeyID[] = { ID_CE_OID, 35 }; +CONST_OID x509ExtKeyUsage[] = { ID_CE_OID, 37 }; +CONST_OID x509AuthInfoAccess[] = { PKIX_CERT_EXTENSIONS, 1 }; + +/* Standard x.509 v3 CRL Extensions */ +CONST_OID x509CrlNumber[] = { ID_CE_OID, 20}; +CONST_OID x509ReasonCode[] = { ID_CE_OID, 21}; +CONST_OID x509InvalidDate[] = { ID_CE_OID, 24}; + +/* pkcs 12 additions */ +CONST_OID pkcs12[] = { PKCS12 }; +CONST_OID pkcs12ModeIDs[] = { PKCS12_MODE_IDS }; +CONST_OID pkcs12ESPVKIDs[] = { PKCS12_ESPVK_IDS }; +CONST_OID pkcs12BagIDs[] = { PKCS12_BAG_IDS }; +CONST_OID pkcs12CertBagIDs[] = { PKCS12_CERT_BAG_IDS }; +CONST_OID pkcs12OIDs[] = { PKCS12_OIDS }; +CONST_OID pkcs12PBEIDs[] = { PKCS12_PBE_IDS }; +CONST_OID pkcs12EnvelopingIDs[] = { PKCS12_ENVELOPING_IDS }; +CONST_OID pkcs12SignatureIDs[] = { PKCS12_SIGNATURE_IDS }; +CONST_OID pkcs12PKCS8KeyShrouding[] = { PKCS12_ESPVK_IDS, 0x01 }; +CONST_OID pkcs12KeyBagID[] = { PKCS12_BAG_IDS, 0x01 }; +CONST_OID pkcs12CertAndCRLBagID[] = { PKCS12_BAG_IDS, 0x02 }; +CONST_OID pkcs12SecretBagID[] = { PKCS12_BAG_IDS, 0x03 }; +CONST_OID pkcs12X509CertCRLBag[] = { PKCS12_CERT_BAG_IDS, 0x01 }; +CONST_OID pkcs12SDSICertBag[] = { PKCS12_CERT_BAG_IDS, 0x02 }; +CONST_OID pkcs12PBEWithSha1And128BitRC4[] = { PKCS12_PBE_IDS, 0x01 }; +CONST_OID pkcs12PBEWithSha1And40BitRC4[] = { PKCS12_PBE_IDS, 0x02 }; +CONST_OID pkcs12PBEWithSha1AndTripleDESCBC[] = { PKCS12_PBE_IDS, 0x03 }; +CONST_OID pkcs12PBEWithSha1And128BitRC2CBC[] = { PKCS12_PBE_IDS, 0x04 }; +CONST_OID pkcs12PBEWithSha1And40BitRC2CBC[] = { PKCS12_PBE_IDS, 0x05 }; +CONST_OID pkcs12RSAEncryptionWith128BitRC4[] = { PKCS12_ENVELOPING_IDS, 0x01 }; +CONST_OID pkcs12RSAEncryptionWith40BitRC4[] = { PKCS12_ENVELOPING_IDS, 0x02 }; +CONST_OID pkcs12RSAEncryptionWithTripleDES[] = { PKCS12_ENVELOPING_IDS, 0x03 }; +CONST_OID pkcs12RSASignatureWithSHA1Digest[] = { PKCS12_SIGNATURE_IDS, 0x01 }; + +/* pkcs 12 version 1.0 ids */ +CONST_OID pkcs12V2PBEWithSha1And128BitRC4[] = { PKCS12_V2_PBE_IDS, 0x01 }; +CONST_OID pkcs12V2PBEWithSha1And40BitRC4[] = { PKCS12_V2_PBE_IDS, 0x02 }; +CONST_OID pkcs12V2PBEWithSha1And3KeyTripleDEScbc[]= { PKCS12_V2_PBE_IDS, 0x03 }; +CONST_OID pkcs12V2PBEWithSha1And2KeyTripleDEScbc[]= { PKCS12_V2_PBE_IDS, 0x04 }; +CONST_OID pkcs12V2PBEWithSha1And128BitRC2cbc[] = { PKCS12_V2_PBE_IDS, 0x05 }; +CONST_OID pkcs12V2PBEWithSha1And40BitRC2cbc[] = { PKCS12_V2_PBE_IDS, 0x06 }; + +CONST_OID pkcs12SafeContentsID[] = { PKCS12_BAG_IDS, 0x04 }; +CONST_OID pkcs12PKCS8ShroudedKeyBagID[] = { PKCS12_BAG_IDS, 0x05 }; + +CONST_OID pkcs12V1KeyBag[] = { PKCS12_V1_BAG_IDS, 0x01 }; +CONST_OID pkcs12V1PKCS8ShroudedKeyBag[] = { PKCS12_V1_BAG_IDS, 0x02 }; +CONST_OID pkcs12V1CertBag[] = { PKCS12_V1_BAG_IDS, 0x03 }; +CONST_OID pkcs12V1CRLBag[] = { PKCS12_V1_BAG_IDS, 0x04 }; +CONST_OID pkcs12V1SecretBag[] = { PKCS12_V1_BAG_IDS, 0x05 }; +CONST_OID pkcs12V1SafeContentsBag[] = { PKCS12_V1_BAG_IDS, 0x06 }; + +CONST_OID pkcs12KeyUsageAttr[] = { 2, 5, 29, 15 }; + +CONST_OID ansix9DSASignature[] = { ANSI_X9_ALGORITHM, 0x01 }; +CONST_OID ansix9DSASignaturewithSHA1Digest[] = { ANSI_X9_ALGORITHM, 0x03 }; + +/* verisign OIDs */ +CONST_OID verisignUserNotices[] = { VERISIGN, 1, 7, 1, 1 }; + +/* pkix OIDs */ +CONST_OID pkixCPSPointerQualifier[] = { PKIX_POLICY_QUALIFIERS, 1 }; +CONST_OID pkixUserNoticeQualifier[] = { PKIX_POLICY_QUALIFIERS, 2 }; + +CONST_OID pkixOCSP[] = { PKIX_OCSP }; +CONST_OID pkixOCSPBasicResponse[] = { PKIX_OCSP, 1 }; +CONST_OID pkixOCSPNonce[] = { PKIX_OCSP, 2 }; +CONST_OID pkixOCSPCRL[] = { PKIX_OCSP, 3 }; +CONST_OID pkixOCSPResponse[] = { PKIX_OCSP, 4 }; +CONST_OID pkixOCSPNoCheck[] = { PKIX_OCSP, 5 }; +CONST_OID pkixOCSPArchiveCutoff[] = { PKIX_OCSP, 6 }; +CONST_OID pkixOCSPServiceLocator[] = { PKIX_OCSP, 7 }; + +CONST_OID pkixRegCtrlRegToken[] = { PKIX_ID_REGCTRL, 1}; +CONST_OID pkixRegCtrlAuthenticator[] = { PKIX_ID_REGCTRL, 2}; +CONST_OID pkixRegCtrlPKIPubInfo[] = { PKIX_ID_REGCTRL, 3}; +CONST_OID pkixRegCtrlPKIArchOptions[] = { PKIX_ID_REGCTRL, 4}; +CONST_OID pkixRegCtrlOldCertID[] = { PKIX_ID_REGCTRL, 5}; +CONST_OID pkixRegCtrlProtEncKey[] = { PKIX_ID_REGCTRL, 6}; +CONST_OID pkixRegInfoUTF8Pairs[] = { PKIX_ID_REGINFO, 1}; +CONST_OID pkixRegInfoCertReq[] = { PKIX_ID_REGINFO, 2}; + +CONST_OID pkixExtendedKeyUsageServerAuth[] = { PKIX_KEY_USAGE, 1 }; +CONST_OID pkixExtendedKeyUsageClientAuth[] = { PKIX_KEY_USAGE, 2 }; +CONST_OID pkixExtendedKeyUsageCodeSign[] = { PKIX_KEY_USAGE, 3 }; +CONST_OID pkixExtendedKeyUsageEMailProtect[] = { PKIX_KEY_USAGE, 4 }; +CONST_OID pkixExtendedKeyUsageTimeStamp[] = { PKIX_KEY_USAGE, 8 }; +CONST_OID pkixOCSPResponderExtendedKeyUsage[] = { PKIX_KEY_USAGE, 9 }; + +/* OIDs for Netscape defined algorithms */ +CONST_OID netscapeSMimeKEA[] = { NETSCAPE_ALGS, 0x01 }; + +/* Fortezza algorithm OIDs */ +CONST_OID skipjackCBC[] = { FORTEZZA_ALG, 0x04 }; +CONST_OID dhPublicKey[] = { ANSI_X942_ALGORITHM, 0x1 }; + +CONST_OID aes128_ECB[] = { AES, 1 }; +CONST_OID aes128_CBC[] = { AES, 2 }; +#ifdef DEFINE_ALL_AES_CIPHERS +CONST_OID aes128_OFB[] = { AES, 3 }; +CONST_OID aes128_CFB[] = { AES, 4 }; +#endif +CONST_OID aes128_KEY_WRAP[] = { AES, 5 }; + +CONST_OID aes192_ECB[] = { AES, 21 }; +CONST_OID aes192_CBC[] = { AES, 22 }; +#ifdef DEFINE_ALL_AES_CIPHERS +CONST_OID aes192_OFB[] = { AES, 23 }; +CONST_OID aes192_CFB[] = { AES, 24 }; +#endif +CONST_OID aes192_KEY_WRAP[] = { AES, 25 }; + +CONST_OID aes256_ECB[] = { AES, 41 }; +CONST_OID aes256_CBC[] = { AES, 42 }; +#ifdef DEFINE_ALL_AES_CIPHERS +CONST_OID aes256_OFB[] = { AES, 43 }; +CONST_OID aes256_CFB[] = { AES, 44 }; +#endif +CONST_OID aes256_KEY_WRAP[] = { AES, 45 }; + +CONST_OID sha256[] = { SHAXXX, 1 }; +CONST_OID sha384[] = { SHAXXX, 2 }; +CONST_OID sha512[] = { SHAXXX, 3 }; + +CONST_OID ecdsaWithSHA1[] = { ANSI_X9_62_SIG_TYPE, 1 }; +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 }; + +/* a special case: always associated with a caller-specified OID */ +CONST_OID noOid[] = { 0 }; + +#define OI(x) { sizeof x, (uint8 *)x } +#ifndef SECOID_NO_STRINGS +#define OD(oid,tag,desc,mech,ext) { OI(oid), tag, desc, mech, ext } +#else +#define OD(oid,tag,desc,mech,ext) { OI(oid), tag, 0, mech, ext } +#endif + +/* + * NOTE: the order of these entries must mach the SECOidTag enum in secoidt.h! + */ +const static SECOidData oids[] = { + { { 0, NULL }, SEC_OID_UNKNOWN, + "Unknown OID", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION }, + OD( md2, SEC_OID_MD2, "MD2", CSSM_ALGID_MD2, INVALID_CERT_EXTENSION ), + OD( md4, SEC_OID_MD4, + "MD4", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( md5, SEC_OID_MD5, "MD5", CSSM_ALGID_MD5, INVALID_CERT_EXTENSION ), + OD( sha1, SEC_OID_SHA1, "SHA-1", CSSM_ALGID_SHA1, INVALID_CERT_EXTENSION ), + OD( rc2cbc, SEC_OID_RC2_CBC, + "RC2-CBC", CSSM_ALGID_RC2, INVALID_CERT_EXTENSION ), + OD( rc4, SEC_OID_RC4, "RC4", CSSM_ALGID_RC4, INVALID_CERT_EXTENSION ), + OD( desede3cbc, SEC_OID_DES_EDE3_CBC, + "DES-EDE3-CBC", CSSM_ALGID_3DES_3KEY_EDE, INVALID_CERT_EXTENSION ), + OD( rc5cbcpad, SEC_OID_RC5_CBC_PAD, + "RC5-CBCPad", CSSM_ALGID_RC5, INVALID_CERT_EXTENSION ), + OD( desecb, SEC_OID_DES_ECB, + "DES-ECB", CSSM_ALGID_DES, INVALID_CERT_EXTENSION ), + OD( descbc, SEC_OID_DES_CBC, + "DES-CBC", CSSM_ALGID_DES, INVALID_CERT_EXTENSION ), + OD( desofb, SEC_OID_DES_OFB, + "DES-OFB", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( descfb, SEC_OID_DES_CFB, + "DES-CFB", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( desmac, SEC_OID_DES_MAC, + "DES-MAC", CSSM_ALGID_DES, INVALID_CERT_EXTENSION ), + OD( desede, SEC_OID_DES_EDE, + "DES-EDE", CSSM_ALGID_3DES_3KEY_EDE, INVALID_CERT_EXTENSION ), + OD( isoSHAWithRSASignature, SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE, + "ISO SHA with RSA Signature", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs1RSAEncryption, SEC_OID_PKCS1_RSA_ENCRYPTION, + "PKCS #1 RSA Encryption", CSSM_ALGID_RSA, INVALID_CERT_EXTENSION ), + + /* the following Signing CSSM_ALGORITHMS should get new CKM_ values when + * values for CKM_RSA_WITH_MDX and CKM_RSA_WITH_SHA_1 get defined in + * PKCS #11. + */ + OD( pkcs1MD2WithRSAEncryption, SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION, + "PKCS #1 MD2 With RSA Encryption", CSSM_ALGID_MD2WithRSA, + INVALID_CERT_EXTENSION ), + OD( pkcs1MD4WithRSAEncryption, SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION, + "PKCS #1 MD4 With RSA Encryption", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs1MD5WithRSAEncryption, SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, + "PKCS #1 MD5 With RSA Encryption", CSSM_ALGID_MD5WithRSA, + INVALID_CERT_EXTENSION ), + OD( pkcs1SHA1WithRSAEncryption, SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION, + "PKCS #1 SHA-1 With RSA Encryption", CSSM_ALGID_SHA1WithRSA, + INVALID_CERT_EXTENSION ), + + OD( pkcs5PbeWithMD2AndDEScbc, SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC, + "PKCS #5 Password Based Encryption with MD2 and DES CBC", + CSSM_ALGID_PKCS5_PBKDF1_MD2, INVALID_CERT_EXTENSION ), + OD( pkcs5PbeWithMD5AndDEScbc, SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC, + "PKCS #5 Password Based Encryption with MD5 and DES CBC", + CSSM_ALGID_PKCS5_PBKDF1_MD5, INVALID_CERT_EXTENSION ), + OD( pkcs5PbeWithSha1AndDEScbc, SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC, + "PKCS #5 Password Based Encryption with SHA1 and DES CBC", + CSSM_ALGID_PKCS5_PBKDF1_SHA1, INVALID_CERT_EXTENSION ), + OD( pkcs7, SEC_OID_PKCS7, + "PKCS #7", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs7Data, SEC_OID_PKCS7_DATA, + "PKCS #7 Data", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs7SignedData, SEC_OID_PKCS7_SIGNED_DATA, + "PKCS #7 Signed Data", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs7EnvelopedData, SEC_OID_PKCS7_ENVELOPED_DATA, + "PKCS #7 Enveloped Data", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs7SignedEnvelopedData, SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA, + "PKCS #7 Signed And Enveloped Data", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs7DigestedData, SEC_OID_PKCS7_DIGESTED_DATA, + "PKCS #7 Digested Data", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs7EncryptedData, SEC_OID_PKCS7_ENCRYPTED_DATA, + "PKCS #7 Encrypted Data", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs9EmailAddress, SEC_OID_PKCS9_EMAIL_ADDRESS, + "PKCS #9 Email Address", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs9UnstructuredName, SEC_OID_PKCS9_UNSTRUCTURED_NAME, + "PKCS #9 Unstructured Name", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs9ContentType, SEC_OID_PKCS9_CONTENT_TYPE, + "PKCS #9 Content Type", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs9MessageDigest, SEC_OID_PKCS9_MESSAGE_DIGEST, + "PKCS #9 Message Digest", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs9SigningTime, SEC_OID_PKCS9_SIGNING_TIME, + "PKCS #9 Signing Time", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs9CounterSignature, SEC_OID_PKCS9_COUNTER_SIGNATURE, + "PKCS #9 Counter Signature", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs9ChallengePassword, SEC_OID_PKCS9_CHALLENGE_PASSWORD, + "PKCS #9 Challenge Password", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs9UnstructuredAddress, SEC_OID_PKCS9_UNSTRUCTURED_ADDRESS, + "PKCS #9 Unstructured Address", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs9ExtendedCertificateAttributes, + SEC_OID_PKCS9_EXTENDED_CERTIFICATE_ATTRIBUTES, + "PKCS #9 Extended Certificate Attributes", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs9SMIMECapabilities, SEC_OID_PKCS9_SMIME_CAPABILITIES, + "PKCS #9 S/MIME Capabilities", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( x520CommonName, SEC_OID_AVA_COMMON_NAME, + "X520 Common Name", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( x520CountryName, SEC_OID_AVA_COUNTRY_NAME, + "X520 Country Name", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( x520LocalityName, SEC_OID_AVA_LOCALITY, + "X520 Locality Name", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( x520StateOrProvinceName, SEC_OID_AVA_STATE_OR_PROVINCE, + "X520 State Or Province Name", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( x520OrgName, SEC_OID_AVA_ORGANIZATION_NAME, + "X520 Organization Name", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( x520OrgUnitName, SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME, + "X520 Organizational Unit Name", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( x520DnQualifier, SEC_OID_AVA_DN_QUALIFIER, + "X520 DN Qualifier", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( rfc2247DomainComponent, SEC_OID_AVA_DC, + "RFC 2247 Domain Component", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + + OD( nsTypeGIF, SEC_OID_NS_TYPE_GIF, + "GIF", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( nsTypeJPEG, SEC_OID_NS_TYPE_JPEG, + "JPEG", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( nsTypeURL, SEC_OID_NS_TYPE_URL, + "URL", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( nsTypeHTML, SEC_OID_NS_TYPE_HTML, + "HTML", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( nsTypeCertSeq, SEC_OID_NS_TYPE_CERT_SEQUENCE, + "Certificate Sequence", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( missiCertKEADSSOld, SEC_OID_MISSI_KEA_DSS_OLD, + "MISSI KEA and DSS Algorithm (Old)", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( missiCertDSSOld, SEC_OID_MISSI_DSS_OLD, + "MISSI DSS Algorithm (Old)", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( missiCertKEADSS, SEC_OID_MISSI_KEA_DSS, + "MISSI KEA and DSS Algorithm", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( missiCertDSS, SEC_OID_MISSI_DSS, + "MISSI DSS Algorithm", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( missiCertKEA, SEC_OID_MISSI_KEA, + "MISSI KEA Algorithm", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( missiCertAltKEA, SEC_OID_MISSI_ALT_KEA, + "MISSI Alternate KEA Algorithm", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + + /* Netscape private extensions */ + OD( nsCertExtNetscapeOK, SEC_OID_NS_CERT_EXT_NETSCAPE_OK, + "Netscape says this cert is OK", + CSSM_ALGID_NONE, UNSUPPORTED_CERT_EXTENSION ), + OD( nsCertExtIssuerLogo, SEC_OID_NS_CERT_EXT_ISSUER_LOGO, + "Certificate Issuer Logo", + CSSM_ALGID_NONE, UNSUPPORTED_CERT_EXTENSION ), + OD( nsCertExtSubjectLogo, SEC_OID_NS_CERT_EXT_SUBJECT_LOGO, + "Certificate Subject Logo", + CSSM_ALGID_NONE, UNSUPPORTED_CERT_EXTENSION ), + OD( nsExtCertType, SEC_OID_NS_CERT_EXT_CERT_TYPE, + "Certificate Type", + CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + OD( nsExtBaseURL, SEC_OID_NS_CERT_EXT_BASE_URL, + "Certificate Extension Base URL", + CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + OD( nsExtRevocationURL, SEC_OID_NS_CERT_EXT_REVOCATION_URL, + "Certificate Revocation URL", + CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + OD( nsExtCARevocationURL, SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL, + "Certificate Authority Revocation URL", + CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + OD( nsExtCACRLURL, SEC_OID_NS_CERT_EXT_CA_CRL_URL, + "Certificate Authority CRL Download URL", + CSSM_ALGID_NONE, UNSUPPORTED_CERT_EXTENSION ), + OD( nsExtCACertURL, SEC_OID_NS_CERT_EXT_CA_CERT_URL, + "Certificate Authority Certificate Download URL", + CSSM_ALGID_NONE, UNSUPPORTED_CERT_EXTENSION ), + OD( nsExtCertRenewalURL, SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL, + "Certificate Renewal URL", + CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + OD( nsExtCAPolicyURL, SEC_OID_NS_CERT_EXT_CA_POLICY_URL, + "Certificate Authority Policy URL", + CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + OD( nsExtHomepageURL, SEC_OID_NS_CERT_EXT_HOMEPAGE_URL, + "Certificate Homepage URL", + CSSM_ALGID_NONE, UNSUPPORTED_CERT_EXTENSION ), + OD( nsExtEntityLogo, SEC_OID_NS_CERT_EXT_ENTITY_LOGO, + "Certificate Entity Logo", + CSSM_ALGID_NONE, UNSUPPORTED_CERT_EXTENSION ), + OD( nsExtUserPicture, SEC_OID_NS_CERT_EXT_USER_PICTURE, + "Certificate User Picture", + CSSM_ALGID_NONE, UNSUPPORTED_CERT_EXTENSION ), + OD( nsExtSSLServerName, SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME, + "Certificate SSL Server Name", + CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + OD( nsExtComment, SEC_OID_NS_CERT_EXT_COMMENT, + "Certificate Comment", + CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + OD( nsExtLostPasswordURL, SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL, + "Lost Password URL", + CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + OD( nsExtCertRenewalTime, SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME, + "Certificate Renewal Time", + CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + OD( nsKeyUsageGovtApproved, SEC_OID_NS_KEY_USAGE_GOVT_APPROVED, + "Strong Crypto Export Approved", + CSSM_ALGID_NONE, UNSUPPORTED_CERT_EXTENSION ), + + + /* x.509 v3 certificate extensions */ + OD( x509SubjectDirectoryAttr, SEC_OID_X509_SUBJECT_DIRECTORY_ATTR, + "Certificate Subject Directory Attributes", + CSSM_ALGID_NONE, UNSUPPORTED_CERT_EXTENSION), + OD( x509SubjectKeyID, SEC_OID_X509_SUBJECT_KEY_ID, + "Certificate Subject Key ID", + CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + OD( x509KeyUsage, SEC_OID_X509_KEY_USAGE, + "Certificate Key Usage", + CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + OD( x509PrivateKeyUsagePeriod, SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD, + "Certificate Private Key Usage Period", + CSSM_ALGID_NONE, UNSUPPORTED_CERT_EXTENSION ), + OD( x509SubjectAltName, SEC_OID_X509_SUBJECT_ALT_NAME, + "Certificate Subject Alt Name", + CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + OD( x509IssuerAltName, SEC_OID_X509_ISSUER_ALT_NAME, + "Certificate Issuer Alt Name", + CSSM_ALGID_NONE, UNSUPPORTED_CERT_EXTENSION ), + OD( x509BasicConstraints, SEC_OID_X509_BASIC_CONSTRAINTS, + "Certificate Basic Constraints", + CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + OD( x509NameConstraints, SEC_OID_X509_NAME_CONSTRAINTS, + "Certificate Name Constraints", + CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + OD( x509CRLDistPoints, SEC_OID_X509_CRL_DIST_POINTS, + "CRL Distribution Points", + CSSM_ALGID_NONE, UNSUPPORTED_CERT_EXTENSION ), + OD( x509CertificatePolicies, SEC_OID_X509_CERTIFICATE_POLICIES, + "Certificate Policies", + CSSM_ALGID_NONE, UNSUPPORTED_CERT_EXTENSION ), + OD( x509PolicyMappings, SEC_OID_X509_POLICY_MAPPINGS, + "Certificate Policy Mappings", + CSSM_ALGID_NONE, UNSUPPORTED_CERT_EXTENSION ), + OD( x509PolicyConstraints, SEC_OID_X509_POLICY_CONSTRAINTS, + "Certificate Policy Constraints", + CSSM_ALGID_NONE, UNSUPPORTED_CERT_EXTENSION ), + OD( x509AuthKeyID, SEC_OID_X509_AUTH_KEY_ID, + "Certificate Authority Key Identifier", + CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + OD( x509ExtKeyUsage, SEC_OID_X509_EXT_KEY_USAGE, + "Extended Key Usage", + CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + OD( x509AuthInfoAccess, SEC_OID_X509_AUTH_INFO_ACCESS, + "Authority Information Access", + CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + + /* x.509 v3 CRL extensions */ + OD( x509CrlNumber, SEC_OID_X509_CRL_NUMBER, + "CRL Number", CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + OD( x509ReasonCode, SEC_OID_X509_REASON_CODE, + "CRL reason code", CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + OD( x509InvalidDate, SEC_OID_X509_INVALID_DATE, + "Invalid Date", CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + + OD( x500RSAEncryption, SEC_OID_X500_RSA_ENCRYPTION, + "X500 RSA Encryption", CSSM_ALGID_RSA, INVALID_CERT_EXTENSION ), + + /* added for alg 1485 */ + OD( rfc1274Uid, SEC_OID_RFC1274_UID, + "RFC1274 User Id", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( rfc1274Mail, SEC_OID_RFC1274_MAIL, + "RFC1274 E-mail Address", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + + /* pkcs 12 additions */ + OD( pkcs12, SEC_OID_PKCS12, + "PKCS #12", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12ModeIDs, SEC_OID_PKCS12_MODE_IDS, + "PKCS #12 Mode IDs", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12ESPVKIDs, SEC_OID_PKCS12_ESPVK_IDS, + "PKCS #12 ESPVK IDs", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12BagIDs, SEC_OID_PKCS12_BAG_IDS, + "PKCS #12 Bag IDs", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12CertBagIDs, SEC_OID_PKCS12_CERT_BAG_IDS, + "PKCS #12 Cert Bag IDs", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12OIDs, SEC_OID_PKCS12_OIDS, + "PKCS #12 OIDs", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12PBEIDs, SEC_OID_PKCS12_PBE_IDS, + "PKCS #12 PBE IDs", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12SignatureIDs, SEC_OID_PKCS12_SIGNATURE_IDS, + "PKCS #12 Signature IDs", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12EnvelopingIDs, SEC_OID_PKCS12_ENVELOPING_IDS, + "PKCS #12 Enveloping IDs", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12PKCS8KeyShrouding, SEC_OID_PKCS12_PKCS8_KEY_SHROUDING, + "PKCS #12 Key Shrouding", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12KeyBagID, SEC_OID_PKCS12_KEY_BAG_ID, + "PKCS #12 Key Bag ID", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12CertAndCRLBagID, SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID, + "PKCS #12 Cert And CRL Bag ID", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12SecretBagID, SEC_OID_PKCS12_SECRET_BAG_ID, + "PKCS #12 Secret Bag ID", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12X509CertCRLBag, SEC_OID_PKCS12_X509_CERT_CRL_BAG, + "PKCS #12 X509 Cert CRL Bag", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12SDSICertBag, SEC_OID_PKCS12_SDSI_CERT_BAG, + "PKCS #12 SDSI Cert Bag", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12PBEWithSha1And128BitRC4, + SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4, + "PKCS #12 PBE With Sha1 and 128 Bit RC4", + CSSM_ALGID_PKCS12_SHA1_PBE, INVALID_CERT_EXTENSION ), + OD( pkcs12PBEWithSha1And40BitRC4, + SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4, + "PKCS #12 PBE With Sha1 and 40 Bit RC4", + CSSM_ALGID_PKCS12_SHA1_PBE, INVALID_CERT_EXTENSION ), + OD( pkcs12PBEWithSha1AndTripleDESCBC, + SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC, + "PKCS #12 PBE With Sha1 and Triple DES CBC", + CSSM_ALGID_PKCS12_SHA1_PBE, INVALID_CERT_EXTENSION ), + OD( pkcs12PBEWithSha1And128BitRC2CBC, + SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC, + "PKCS #12 PBE With Sha1 and 128 Bit RC2 CBC", + CSSM_ALGID_PKCS12_SHA1_PBE, INVALID_CERT_EXTENSION ), + OD( pkcs12PBEWithSha1And40BitRC2CBC, + SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC, + "PKCS #12 PBE With Sha1 and 40 Bit RC2 CBC", + CSSM_ALGID_PKCS12_SHA1_PBE, INVALID_CERT_EXTENSION ), + OD( pkcs12RSAEncryptionWith128BitRC4, + SEC_OID_PKCS12_RSA_ENCRYPTION_WITH_128_BIT_RC4, + "PKCS #12 RSA Encryption with 128 Bit RC4", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12RSAEncryptionWith40BitRC4, + SEC_OID_PKCS12_RSA_ENCRYPTION_WITH_40_BIT_RC4, + "PKCS #12 RSA Encryption with 40 Bit RC4", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12RSAEncryptionWithTripleDES, + SEC_OID_PKCS12_RSA_ENCRYPTION_WITH_TRIPLE_DES, + "PKCS #12 RSA Encryption with Triple DES", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12RSASignatureWithSHA1Digest, + SEC_OID_PKCS12_RSA_SIGNATURE_WITH_SHA1_DIGEST, + "PKCS #12 RSA Encryption with Triple DES", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + + /* DSA signatures */ + OD( ansix9DSASignature, SEC_OID_ANSIX9_DSA_SIGNATURE, + "ANSI X9.57 DSA Signature", CSSM_ALGID_DSA, INVALID_CERT_EXTENSION ), + OD( ansix9DSASignaturewithSHA1Digest, + SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST, + "ANSI X9.57 DSA Signature with SHA1 Digest", + CSSM_ALGID_SHA1WithDSA, INVALID_CERT_EXTENSION ), + OD( bogusDSASignaturewithSHA1Digest, + SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST, + "FORTEZZA DSA Signature with SHA1 Digest", + CSSM_ALGID_SHA1WithDSA, INVALID_CERT_EXTENSION ), + + /* verisign oids */ + OD( verisignUserNotices, SEC_OID_VERISIGN_USER_NOTICES, + "Verisign User Notices", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + + /* pkix oids */ + OD( pkixCPSPointerQualifier, SEC_OID_PKIX_CPS_POINTER_QUALIFIER, + "PKIX CPS Pointer Qualifier", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkixUserNoticeQualifier, SEC_OID_PKIX_USER_NOTICE_QUALIFIER, + "PKIX User Notice Qualifier", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + + OD( pkixOCSP, SEC_OID_PKIX_OCSP, + "PKIX Online Certificate Status Protocol", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkixOCSPBasicResponse, SEC_OID_PKIX_OCSP_BASIC_RESPONSE, + "OCSP Basic Response", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkixOCSPNonce, SEC_OID_PKIX_OCSP_NONCE, + "OCSP Nonce Extension", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkixOCSPCRL, SEC_OID_PKIX_OCSP_CRL, + "OCSP CRL Reference Extension", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkixOCSPResponse, SEC_OID_PKIX_OCSP_RESPONSE, + "OCSP Response Types Extension", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkixOCSPNoCheck, SEC_OID_PKIX_OCSP_NO_CHECK, + "OCSP No Check Extension", + CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), + OD( pkixOCSPArchiveCutoff, SEC_OID_PKIX_OCSP_ARCHIVE_CUTOFF, + "OCSP Archive Cutoff Extension", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkixOCSPServiceLocator, SEC_OID_PKIX_OCSP_SERVICE_LOCATOR, + "OCSP Service Locator Extension", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + + OD( pkixRegCtrlRegToken, SEC_OID_PKIX_REGCTRL_REGTOKEN, + "PKIX CRMF Registration Control, Registration Token", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkixRegCtrlAuthenticator, SEC_OID_PKIX_REGCTRL_AUTHENTICATOR, + "PKIX CRMF Registration Control, Registration Authenticator", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkixRegCtrlPKIPubInfo, SEC_OID_PKIX_REGCTRL_PKIPUBINFO, + "PKIX CRMF Registration Control, PKI Publication Info", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), + OD( pkixRegCtrlPKIArchOptions, + SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS, + "PKIX CRMF Registration Control, PKI Archive Options", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), + OD( pkixRegCtrlOldCertID, SEC_OID_PKIX_REGCTRL_OLD_CERT_ID, + "PKIX CRMF Registration Control, Old Certificate ID", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), + OD( pkixRegCtrlProtEncKey, SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY, + "PKIX CRMF Registration Control, Protocol Encryption Key", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), + OD( pkixRegInfoUTF8Pairs, SEC_OID_PKIX_REGINFO_UTF8_PAIRS, + "PKIX CRMF Registration Info, UTF8 Pairs", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), + OD( pkixRegInfoCertReq, SEC_OID_PKIX_REGINFO_CERT_REQUEST, + "PKIX CRMF Registration Info, Certificate Request", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), + OD( pkixExtendedKeyUsageServerAuth, + SEC_OID_EXT_KEY_USAGE_SERVER_AUTH, + "TLS Web Server Authentication Certificate", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), + OD( pkixExtendedKeyUsageClientAuth, + SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH, + "TLS Web Client Authentication Certificate", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), + OD( pkixExtendedKeyUsageCodeSign, SEC_OID_EXT_KEY_USAGE_CODE_SIGN, + "Code Signing Certificate", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), + OD( pkixExtendedKeyUsageEMailProtect, + SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT, + "E-Mail Protection Certificate", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), + OD( pkixExtendedKeyUsageTimeStamp, + SEC_OID_EXT_KEY_USAGE_TIME_STAMP, + "Time Stamping Certifcate", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), + OD( pkixOCSPResponderExtendedKeyUsage, SEC_OID_OCSP_RESPONDER, + "OCSP Responder Certificate", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), + + /* Netscape Algorithm OIDs */ + + OD( netscapeSMimeKEA, SEC_OID_NETSCAPE_SMIME_KEA, + "Netscape S/MIME KEA", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + + /* Skipjack OID -- ### mwelch temporary */ + OD( skipjackCBC, SEC_OID_FORTEZZA_SKIPJACK, + "Skipjack CBC64", CSSM_ALGID_SKIPJACK, INVALID_CERT_EXTENSION ), + + /* pkcs12 v2 oids */ + OD( pkcs12V2PBEWithSha1And128BitRC4, + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4, + "PKCS12 V2 PBE With SHA1 And 128 Bit RC4", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12V2PBEWithSha1And40BitRC4, + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4, + "PKCS12 V2 PBE With SHA1 And 40 Bit RC4", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12V2PBEWithSha1And3KeyTripleDEScbc, + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC, + "PKCS12 V2 PBE With SHA1 And 3KEY Triple DES-cbc", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12V2PBEWithSha1And2KeyTripleDEScbc, + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC, + "PKCS12 V2 PBE With SHA1 And 2KEY Triple DES-cbc", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12V2PBEWithSha1And128BitRC2cbc, + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC, + "PKCS12 V2 PBE With SHA1 And 128 Bit RC2 CBC", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12V2PBEWithSha1And40BitRC2cbc, + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC, + "PKCS12 V2 PBE With SHA1 And 40 Bit RC2 CBC", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12SafeContentsID, SEC_OID_PKCS12_SAFE_CONTENTS_ID, + "PKCS #12 Safe Contents ID", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12PKCS8ShroudedKeyBagID, + SEC_OID_PKCS12_PKCS8_SHROUDED_KEY_BAG_ID, + "PKCS #12 Safe Contents ID", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12V1KeyBag, SEC_OID_PKCS12_V1_KEY_BAG_ID, + "PKCS #12 V1 Key Bag", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12V1PKCS8ShroudedKeyBag, + SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID, + "PKCS #12 V1 PKCS8 Shrouded Key Bag", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12V1CertBag, SEC_OID_PKCS12_V1_CERT_BAG_ID, + "PKCS #12 V1 Cert Bag", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12V1CRLBag, SEC_OID_PKCS12_V1_CRL_BAG_ID, + "PKCS #12 V1 CRL Bag", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12V1SecretBag, SEC_OID_PKCS12_V1_SECRET_BAG_ID, + "PKCS #12 V1 Secret Bag", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12V1SafeContentsBag, SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID, + "PKCS #12 V1 Safe Contents Bag", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + + OD( pkcs9X509Certificate, SEC_OID_PKCS9_X509_CERT, + "PKCS #9 X509 Certificate", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs9SDSICertificate, SEC_OID_PKCS9_SDSI_CERT, + "PKCS #9 SDSI Certificate", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs9X509CRL, SEC_OID_PKCS9_X509_CRL, + "PKCS #9 X509 CRL", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs9FriendlyName, SEC_OID_PKCS9_FRIENDLY_NAME, + "PKCS #9 Friendly Name", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs9LocalKeyID, SEC_OID_PKCS9_LOCAL_KEY_ID, + "PKCS #9 Local Key ID", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( pkcs12KeyUsageAttr, SEC_OID_PKCS12_KEY_USAGE, + "PKCS 12 Key Usage", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( dhPublicKey, SEC_OID_X942_DIFFIE_HELMAN_KEY, + "Diffie-Helman Public Key", CSSM_ALGID_DH, + INVALID_CERT_EXTENSION ), + OD( netscapeNickname, SEC_OID_NETSCAPE_NICKNAME, + "Netscape Nickname", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + + /* Cert Server specific OIDs */ + OD( netscapeRecoveryRequest, SEC_OID_NETSCAPE_RECOVERY_REQUEST, + "Recovery Request OID", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + + OD( nsExtAIACertRenewal, SEC_OID_CERT_RENEWAL_LOCATOR, + "Certificate Renewal Locator OID", CSSM_ALGID_NONE, + INVALID_CERT_EXTENSION ), + + OD( nsExtCertScopeOfUse, SEC_OID_NS_CERT_EXT_SCOPE_OF_USE, + "Certificate Scope-of-Use Extension", CSSM_ALGID_NONE, + SUPPORTED_CERT_EXTENSION ), + + /* CMS stuff */ + OD( cmsESDH, SEC_OID_CMS_EPHEMERAL_STATIC_DIFFIE_HELLMAN, + "Ephemeral-Static Diffie-Hellman", CSSM_ALGID_NONE /* XXX */, + INVALID_CERT_EXTENSION ), + OD( cms3DESwrap, SEC_OID_CMS_3DES_KEY_WRAP, + "CMS 3DES Key Wrap", CSSM_ALGID_NONE /* XXX */, + INVALID_CERT_EXTENSION ), + OD( cmsRC2wrap, SEC_OID_CMS_RC2_KEY_WRAP, + "CMS RC2 Key Wrap", CSSM_ALGID_NONE /* XXX */, + INVALID_CERT_EXTENSION ), + OD( smimeEncryptionKeyPreference, SEC_OID_SMIME_ENCRYPTION_KEY_PREFERENCE, + "S/MIME Encryption Key Preference", + CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + + /* AES algorithm OIDs */ + OD( aes128_ECB, SEC_OID_AES_128_ECB, + "AES-128-ECB", CSSM_ALGID_AES, INVALID_CERT_EXTENSION ), + OD( aes128_CBC, SEC_OID_AES_128_CBC, + "AES-128-CBC", CSSM_ALGID_AES, INVALID_CERT_EXTENSION ), + OD( aes192_ECB, SEC_OID_AES_192_ECB, + "AES-192-ECB", CSSM_ALGID_AES, INVALID_CERT_EXTENSION ), + OD( aes192_CBC, SEC_OID_AES_192_CBC, + "AES-192-CBC", CSSM_ALGID_AES, INVALID_CERT_EXTENSION ), + OD( aes256_ECB, SEC_OID_AES_256_ECB, + "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 ), + + OD( ms_smimeEncryptionKeyPreference, + SEC_OID_MS_SMIME_ENCRYPTION_KEY_PREFERENCE, + "Microsoft S/MIME Encryption Key Preference", + 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), + + OD( pkcs1SHA256WithRSAEncryption, SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION, + "PKCS #1 SHA-256 With RSA Encryption", CSSM_ALGID_SHA256WithRSA, + INVALID_CERT_EXTENSION ), + OD( pkcs1SHA384WithRSAEncryption, SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION, + "PKCS #1 SHA-384 With RSA Encryption", CSSM_ALGID_SHA384WithRSA, + INVALID_CERT_EXTENSION ), + OD( pkcs1SHA512WithRSAEncryption, SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION, + "PKCS #1 SHA-512 With RSA Encryption", CSSM_ALGID_SHA512WithRSA, + INVALID_CERT_EXTENSION ), + + OD( aes128_KEY_WRAP, SEC_OID_AES_128_KEY_WRAP, + "AES-128 Key Wrap", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), + OD( aes192_KEY_WRAP, SEC_OID_AES_192_KEY_WRAP, + "AES-192 Key Wrap", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), + OD( aes256_KEY_WRAP, SEC_OID_AES_256_KEY_WRAP, + "AES-256 Key Wrap", 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_ECDSA, + INVALID_CERT_EXTENSION ), + OD( ecdsaWithSHA1, SEC_OID_ECDSA_WithSHA1, + "SHA-1 With ECDSA", CSSM_ALGID_SHA1WithECDSA, + INVALID_CERT_EXTENSION ), + OD( dhSinglePassStdDHsha1kdf, SEC_OID_DH_SINGLE_STD_SHA1KDF, + "ECDH With SHA1 KDF", CSSM_ALGID_ECDH_X963_KDF, + 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 ), + +}; + +/* + * now the dynamic table. The dynamic table gets build at init time. + * and gets modified if the user loads new crypto modules. + */ + +static PLHashTable *oid_d_hash = 0; +static SECOidData **secoidDynamicTable = NULL; +static int secoidDynamicTableSize = 0; +static int secoidLastDynamicEntry = 0; +static int secoidLastHashEntry = 0; + +/* + * A mutex to protect creation and writing of all three hash tables in + * this module, and reading of the dynamic table. + */ +static pthread_mutex_t oid_hash_mutex = PTHREAD_MUTEX_INITIALIZER; + +/* caller holds oid_hash_mutex */ +static SECStatus +secoid_DynamicRehash(void) +{ + SECOidData *oid; + PLHashEntry *entry; + int i; + int last = secoidLastDynamicEntry; + + if (!oid_d_hash) { + oid_d_hash = PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare, + PL_CompareValues, NULL, NULL); + } + + + if ( !oid_d_hash ) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return(SECFailure); + } + + for ( i = secoidLastHashEntry; i < last; i++ ) { + oid = secoidDynamicTable[i]; + + entry = PL_HashTableAdd( oid_d_hash, &oid->oid, oid ); + if ( entry == NULL ) { + return(SECFailure); + } + } + secoidLastHashEntry = last; + return(SECSuccess); +} + + + +/* + * Lookup a Dynamic OID. Dynamic OID's still change slowly, so it's + * cheaper to rehash the table when it changes than it is to do the loop + * each time. + */ +static SECOidData * +secoid_FindDynamic(const SECItem *key) { + SECOidData *ret = NULL; + + pthread_mutex_lock(&oid_hash_mutex); + /* subsequent errors to loser: */ + if (secoidDynamicTable == NULL) { + /* PORT_SetError! */ + goto loser; + } + if (secoidLastHashEntry != secoidLastDynamicEntry) { + SECStatus rv = secoid_DynamicRehash(); + if ( rv != SECSuccess ) { + goto loser; + } + } + ret = (SECOidData *)PL_HashTableLookup (oid_d_hash, key); +loser: + pthread_mutex_unlock(&oid_hash_mutex); + return ret; + +} + +static SECOidData * +secoid_FindDynamicByTag(SECOidTag tagnum) +{ + int tagNumDiff; + SECOidData *rtn = NULL; + + if (tagnum < SEC_OID_TOTAL) { + return NULL; + } + + pthread_mutex_lock(&oid_hash_mutex); + /* subsequent errors to loser: */ + + if (secoidDynamicTable == NULL) { + goto loser; + } + + tagNumDiff = tagnum - SEC_OID_TOTAL; + if (tagNumDiff >= secoidLastDynamicEntry) { + goto loser; + } + + rtn = secoidDynamicTable[tagNumDiff]; +loser: + pthread_mutex_unlock(&oid_hash_mutex); + return rtn; +} + +#if 0 +SECStatus +SECOID_AddEntry(SECItem *oid, char *description, CSSM_ALGORITHMS cssmAlgorithm) { + SECOidData *oiddp; + int last; + int tableSize; + int next; + SECOidData **newTable; + SECOidData **oldTable = NULL; + SECStatus srtn = SECFailure; + + if (oid == NULL) { + return SECFailure; + } + + pthread_mutex_lock(&oid_hash_mutex); + /* subsequent errors to loser: */ + + oiddp = (SECOidData *)PORT_Alloc(sizeof(SECOidData)); + last = secoidLastDynamicEntry; + tableSize = secoidDynamicTableSize; + next = last++; + newTable = secoidDynamicTable; + + /* fill in oid structure */ + if (SECITEM_CopyItem(NULL,&oiddp->oid,oid) != SECSuccess) { + PORT_Free(oiddp); + goto loser; + } + oiddp->offset = (SECOidTag)(next + SEC_OID_TOTAL); + /* may we should just reference the copy passed to us? */ + oiddp->desc = PORT_Strdup(description); + oiddp->cssmAlgorithm = cssmAlgorithm; + + + if (last > tableSize) { + int oldTableSize = tableSize; + tableSize += 10; + oldTable = newTable; + newTable = (SECOidData **)PORT_ZAlloc(sizeof(SECOidData *)*tableSize); + if (newTable == NULL) { + PORT_Free(oiddp->oid.Data); + PORT_Free(oiddp); + goto loser; + } + PORT_Memcpy(newTable,oldTable,sizeof(SECOidData *)*oldTableSize); + PORT_Free(oldTable); + } + + newTable[next] = oiddp; + secoidDynamicTable = newTable; + secoidDynamicTableSize = tableSize; + secoidLastDynamicEntry = last; + srtn = SECSuccess; +loser: + pthread_mutex_unlock(&oid_hash_mutex); + return srtn; +} +#endif + + +/* normal static table processing */ + +/* creation and writes to these hash tables is protected by oid_hash_mutex */ +static PLHashTable *oidhash = NULL; +static PLHashTable *oidmechhash = NULL; + +static PLHashNumber +secoid_HashNumber(const void *key) +{ + intptr_t keyint = (intptr_t)key; + // XXX/gh revisit this + keyint ^= (keyint >> 8); + keyint ^= (keyint << 8); + return (PLHashNumber) keyint; +} + +/* caller holds oid_hash_mutex */ +static SECStatus +InitOIDHash(void) +{ + PLHashEntry *entry; + const SECOidData *oid; + int i; + + oidhash = PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare, + PL_CompareValues, NULL, NULL); + oidmechhash = PL_NewHashTable(0, secoid_HashNumber, PL_CompareValues, + PL_CompareValues, NULL, NULL); + + if ( !oidhash || !oidmechhash) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + PORT_Assert(0); /*This function should never fail. */ + return(SECFailure); + } + + for ( i = 0; i < ( sizeof(oids) / sizeof(SECOidData) ); i++ ) { + oid = &oids[i]; + + PORT_Assert ( oid->offset == i ); + + entry = PL_HashTableAdd( oidhash, &oid->oid, (void *)oid ); + if ( entry == NULL ) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + PORT_Assert(0); /*This function should never fail. */ + return(SECFailure); + } + + if ( oid->cssmAlgorithm != CSSM_ALGID_NONE ) { + intptr_t algorithm = oid->cssmAlgorithm; + entry = PL_HashTableAdd( oidmechhash, + (void *)algorithm, (void *)oid ); + if ( entry == NULL ) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + PORT_Assert(0); /* This function should never fail. */ + return(SECFailure); + } + } + } + + PORT_Assert (i == SEC_OID_TOTAL); + + return(SECSuccess); +} + +SECOidData * +SECOID_FindOIDByCssmAlgorithm(CSSM_ALGORITHMS cssmAlgorithm) +{ + SECOidData *ret; + int rv; + + pthread_mutex_lock(&oid_hash_mutex); + if ( !oidhash ) { + rv = InitOIDHash(); + if ( rv != SECSuccess ) { + pthread_mutex_unlock(&oid_hash_mutex); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return NULL; + } + } + pthread_mutex_unlock(&oid_hash_mutex); + intptr_t algorithm = cssmAlgorithm; + ret = PL_HashTableLookupConst ( oidmechhash, (void *)algorithm); + if ( ret == NULL ) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + } + + return (ret); +} + +SECOidData * +SECOID_FindOID(const SECItem *oid) +{ + SECOidData *ret; + int rv; + + pthread_mutex_lock(&oid_hash_mutex); + if ( !oidhash ) { + rv = InitOIDHash(); + if ( rv != SECSuccess ) { + pthread_mutex_unlock(&oid_hash_mutex); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return NULL; + } + } + pthread_mutex_unlock(&oid_hash_mutex); + + ret = PL_HashTableLookupConst ( oidhash, oid ); + if ( ret == NULL ) { + ret = secoid_FindDynamic(oid); + if (ret == NULL) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + } + } + + return(ret); +} + +SECOidTag +SECOID_FindOIDTag(const SECItem *oid) +{ + SECOidData *oiddata; + + oiddata = SECOID_FindOID (oid); + if (oiddata == NULL) + return SEC_OID_UNKNOWN; + + return oiddata->offset; +} + +/* This really should return const. */ +SECOidData * +SECOID_FindOIDByTag(SECOidTag tagnum) +{ + + if (tagnum >= SEC_OID_TOTAL) { + return secoid_FindDynamicByTag(tagnum); + } + + PORT_Assert((unsigned int)tagnum < (sizeof(oids) / sizeof(SECOidData))); + return (SECOidData *)(&oids[tagnum]); +} + +Boolean SECOID_KnownCertExtenOID (const SECItem *extenOid) +{ + SECOidData * oidData; + + oidData = SECOID_FindOID (extenOid); + if (oidData == (SECOidData *)NULL) + return (PR_FALSE); + return ((oidData->supportedExtension == SUPPORTED_CERT_EXTENSION) ? + PR_TRUE : PR_FALSE); +} + + +const char * +SECOID_FindOIDTagDescription(SECOidTag tagnum) +{ + const SECOidData *oidData = SECOID_FindOIDByTag(tagnum); + return oidData ? oidData->desc : 0; +} + +/* + * free up the oid tables. + */ +SECStatus +SECOID_Shutdown(void) +{ + int i; + + pthread_mutex_lock(&oid_hash_mutex); + if (oidhash) { + PL_HashTableDestroy(oidhash); + oidhash = NULL; + } + if (oidmechhash) { + PL_HashTableDestroy(oidmechhash); + oidmechhash = NULL; + } + if (oid_d_hash) { + PL_HashTableDestroy(oid_d_hash); + oid_d_hash = NULL; + } + if (secoidDynamicTable) { + for (i=0; i < secoidLastDynamicEntry; i++) { + PORT_Free(secoidDynamicTable[i]); + } + PORT_Free(secoidDynamicTable); + secoidDynamicTable = NULL; + secoidDynamicTableSize = 0; + secoidLastDynamicEntry = 0; + secoidLastHashEntry = 0; + } + pthread_mutex_unlock(&oid_hash_mutex); + return SECSuccess; +} + +#pragma clang diagnostic pop diff --git a/Security/libsecurity_smime/lib/secoid.h b/Security/libsecurity_smime/lib/secoid.h new file mode 100644 index 00000000..c7088d89 --- /dev/null +++ b/Security/libsecurity_smime/lib/secoid.h @@ -0,0 +1,118 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#ifndef _SECOID_H_ +#define _SECOID_H_ +/* + * secoid.h - public data structures and prototypes for ASN.1 OID functions + */ + +#include +#include +#include + +#include + +SEC_BEGIN_PROTOS + +extern const SecAsn1Template SECOID_AlgorithmIDTemplate[]; + +/* This functions simply returns the address of the above-declared template. */ +SEC_ASN1_CHOOSER_DECLARE(SECOID_AlgorithmIDTemplate) + +/* + * OID handling routines + */ +extern SECOidData *SECOID_FindOID(const SECItem *oid); +extern SECOidTag SECOID_FindOIDTag(const SECItem *oid); +extern SECOidData *SECOID_FindOIDByTag(SECOidTag tagnum); +extern SECOidData *SECOID_FindOIDByCssmAlgorithm(CSSM_ALGORITHMS cssmAlgorithm); + +/****************************************/ +/* +** Algorithm id handling operations +*/ + +/* +** Fill in an algorithm-ID object given a tag and some parameters. +** "aid" where the DER encoded algorithm info is stored (memory +** is allocated) +** "tag" the tag defining the algorithm (SEC_OID_*) +** "params" if not NULL, the parameters to go with the algorithm +*/ +extern SECStatus SECOID_SetAlgorithmID(PRArenaPool *arena, SECAlgorithmID *aid, + SECOidTag tag, SECItem *params); + +/* +** Copy the "src" object to "dest". Memory is allocated in "dest" for +** each of the appropriate sub-objects. Memory in "dest" is not freed +** before memory is allocated (use SECOID_DestroyAlgorithmID(dest, PR_FALSE) +** to do that). +*/ +extern SECStatus SECOID_CopyAlgorithmID(PRArenaPool *arena, SECAlgorithmID *dest, + const SECAlgorithmID *src); + +/* +** Get the SEC_OID_* tag for the given algorithm-id object. +*/ +extern SECOidTag SECOID_GetAlgorithmTag(const SECAlgorithmID *aid); + +/* +** Destroy an algorithm-id object. +** "aid" the certificate-request to destroy +** "freeit" if PR_TRUE then free the object as well as its sub-objects +*/ +extern void SECOID_DestroyAlgorithmID(SECAlgorithmID *aid, Boolean freeit); + +/* +** Compare two algorithm-id objects, returning the difference between +** them. +*/ +extern SECComparison SECOID_CompareAlgorithmID(const SECAlgorithmID *a, + const SECAlgorithmID *b); + +extern Boolean SECOID_KnownCertExtenOID (const SECItem *extenOid); + +/* Given a SEC_OID_* tag, return a string describing it. + */ +extern const char *SECOID_FindOIDTagDescription(SECOidTag tagnum); + +/* + * free up the oid data structures. + */ +extern SECStatus SECOID_Shutdown(void); + + +SEC_END_PROTOS + +#endif /* _SECOID_H_ */ diff --git a/Security/libsecurity_smime/lib/secoidt.h b/Security/libsecurity_smime/lib/secoidt.h new file mode 100644 index 00000000..f882ed95 --- /dev/null +++ b/Security/libsecurity_smime/lib/secoidt.h @@ -0,0 +1,61 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#ifndef _SECOIDT_H_ +#define _SECOIDT_H_ +/* + * secoidt.h - public data structures for ASN.1 OID functions + */ + +#include + +#include + +typedef enum { + INVALID_CERT_EXTENSION = 0, + UNSUPPORTED_CERT_EXTENSION = 1, + SUPPORTED_CERT_EXTENSION = 2 +} SECSupportExtenTag; + +struct SECOidDataStr { + SECItem oid; + SECOidTag offset; + const char * desc; + CSSM_ALGORITHMS cssmAlgorithm; + SECSupportExtenTag supportedExtension; + /* only used for x.509 v3 extensions, so + that we can print the names of those + extensions that we don't even support */ +}; + +#endif /* _SECOIDT_H_ */ diff --git a/Security/libsecurity_smime/lib/security_smime.exp b/Security/libsecurity_smime/lib/security_smime.exp new file mode 100644 index 00000000..bfbea85a --- /dev/null +++ b/Security/libsecurity_smime/lib/security_smime.exp @@ -0,0 +1,133 @@ +# +# Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. +# +# @APPLE_LICENSE_HEADER_START@ +# +# This file contains Original Code and/or Modifications of Original Code +# as defined in and that are subject to the Apple Public Source License +# Version 2.0 (the 'License'). You may not use this file except in +# compliance with the License. Please obtain a copy of the License at +# http://www.opensource.apple.com/apsl/ and read it before using this +# file. +# +# The Original Code and all software distributed under the License are +# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +# Please see the License for the specific language governing rights and +# limitations under the License. +# +# @APPLE_LICENSE_HEADER_END@ +# +_SecArenaPoolCreate +_SecArenaPoolFree +_SecCmsContentInfoGetBulkKey +_SecCmsContentInfoGetBulkKeySize +_SecCmsContentInfoGetChildContentInfo +_SecCmsContentInfoGetContent +_SecCmsContentInfoGetContentEncAlg +_SecCmsContentInfoGetContentEncAlgTag +_SecCmsContentInfoGetContentTypeOID +_SecCmsContentInfoGetContentTypeTag +_SecCmsContentInfoGetInnerContent +_SecCmsContentInfoSetBulkKey +_SecCmsContentInfoSetContentData +_SecCmsContentInfoSetContentDigestedData +_SecCmsContentInfoSetContentEncAlg +_SecCmsContentInfoSetContentEncAlgID +_SecCmsContentInfoSetContentEncryptedData +_SecCmsContentInfoSetContentEnvelopedData +_SecCmsContentInfoSetContentSignedData +_SecCmsContentInfoSetContentOther +_SecCmsDecoderCreate +_SecCmsDecoderDestroy +_SecCmsDecoderFinish +_SecCmsDecoderUpdate +_SecCmsDigestContextCancel +_SecCmsDigestContextFinishMultiple +_SecCmsDigestContextStartMultiple +_SecCmsDigestContextUpdate +_SecCmsDigestedDataCreate +_SecCmsDigestedDataDestroy +_SecCmsDigestedDataGetContentInfo +_SecCmsEncoderCreate +_SecCmsEncoderDestroy +_SecCmsEncoderFinish +_SecCmsEncoderUpdate +_SecCmsEncryptedDataCreate +_SecCmsEncryptedDataDestroy +_SecCmsEncryptedDataGetContentInfo +_SecCmsEnvelopedDataAddRecipient +_SecCmsEnvelopedDataCreate +_SecCmsEnvelopedDataDestroy +_SecCmsEnvelopedDataGetContentInfo +_SecCmsMessageContainsCertsOrCrls +_SecCmsMessageContentLevel +_SecCmsMessageContentLevelCount +_SecCmsMessageCopy +_SecCmsMessageCreate +_SecCmsMessageDecode +_SecCmsMessageDestroy +_SecCmsMessageEncode +_SecCmsMessageGetArena +_SecCmsMessageGetContent +_SecCmsMessageGetContentInfo +_SecCmsMessageIsContentEmpty +_SecCmsMessageIsEncrypted +_SecCmsMessageIsSigned +_SecCmsMessageContainsTSTInfo +_SecCmsMessageSetTSACallback +_SecCmsMessageSetTSAContext +_SecCmsTSAGetDefaultContext +_SecCmsTSADefaultCallback +_kTSAContextKeyURL +_kTSAContextKeyNoCerts +_kTSADebugContextKeyBadReq +_kTSADebugContextKeyBadNonce +_SecTSAResponseCopyDEREncoding +_SecCmsRecipientInfoCreate +_SecCmsRecipientInfoCreateWithSubjKeyID +_SecCmsRecipientInfoCreateWithSubjKeyIDFromCert +_SecCmsRecipientInfoDestroy +_SecCmsSignedDataAddCertChain +_SecCmsSignedDataAddCertList +_SecCmsSignedDataAddCertificate +_SecCmsSignedDataAddSignerInfo +_SecCmsSignedDataContainsCertsOrCrls +_SecCmsSignedDataCreate +_SecCmsSignedDataCreateCertsOnly +_SecCmsSignedDataDestroy +_SecCmsSignedDataGetCertificateList +_SecCmsSignedDataGetContentInfo +_SecCmsSignedDataGetDigestAlgs +_SecCmsSignedDataGetSignerInfo +_SecCmsSignedDataGetSignerInfos +_SecCmsSignedDataHasDigests +_SecCmsSignedDataImportCerts +_SecCmsSignedDataSetDigests +_SecCmsSignedDataSignerInfoCount +_SecCmsSignedDataVerifyCertsOnly +_SecCmsSignedDataVerifySignerInfo +_SecCmsSignerInfoAddCounterSignature +_SecCmsSignerInfoAddMSSMIMEEncKeyPrefs +_SecCmsSignerInfoAddSMIMECaps +_SecCmsSignerInfoAddSMIMEEncKeyPrefs +_SecCmsSignerInfoAddSigningTime +_SecCmsSignerInfoCreate +_SecCmsSignerInfoCreateWithSubjKeyID +_SecCmsSignerInfoDestroy +_SecCmsSignerInfoGetCertList +_SecCmsSignerInfoGetDigestAlg +_SecCmsSignerInfoGetDigestAlgTag +_SecCmsSignerInfoGetSignerCommonName +_SecCmsSignerInfoGetSignerEmailAddress +_SecCmsSignerInfoGetSigningCertificate +_SecCmsSignerInfoGetSigningTime +_SecCmsSignerInfoGetTimestampTime +_SecCmsSignerInfoGetVerificationStatus +_SecCmsSignerInfoGetEncDigest +_SecCmsSignerInfoIncludeCerts +_SecCmsSignerInfoSaveSMIMEProfile +_SecCmsUtilVerificationStatusToString +_SecSMIMEFindBulkAlgForRecipients diff --git a/libsecurity_smime/lib/siginfoUtils.cpp b/Security/libsecurity_smime/lib/siginfoUtils.cpp similarity index 97% rename from libsecurity_smime/lib/siginfoUtils.cpp rename to Security/libsecurity_smime/lib/siginfoUtils.cpp index 394d900d..ea7ae8fb 100644 --- a/libsecurity_smime/lib/siginfoUtils.cpp +++ b/Security/libsecurity_smime/lib/siginfoUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2008,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_smime/lib/smimeutil.c b/Security/libsecurity_smime/lib/smimeutil.c new file mode 100644 index 00000000..eacec1a0 --- /dev/null +++ b/Security/libsecurity_smime/lib/smimeutil.c @@ -0,0 +1,802 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * Stuff specific to S/MIME policy and interoperability. + */ + +#include "cmslocal.h" + +#include "secoid.h" +#include "secitem.h" +#include "cert.h" +#include "SecSMIMEPriv.h" + +#include +#include +#include +#include + +SEC_ASN1_MKSUB(CERT_IssuerAndSNTemplate) +SEC_ASN1_MKSUB(SEC_OctetStringTemplate) +SEC_ASN1_CHOOSER_DECLARE(CERT_IssuerAndSNTemplate) + +/* various integer's ASN.1 encoding */ +static unsigned char asn1_int40[] = { SEC_ASN1_INTEGER, 0x01, 0x28 }; +static unsigned char asn1_int64[] = { SEC_ASN1_INTEGER, 0x01, 0x40 }; +static unsigned char asn1_int128[] = { SEC_ASN1_INTEGER, 0x02, 0x00, 0x80 }; + +/* RC2 algorithm parameters (used in smime_cipher_map) */ +static CSSM_DATA param_int40 = { sizeof(asn1_int40), asn1_int40 }; +static CSSM_DATA param_int64 = { sizeof(asn1_int64), asn1_int64 }; +static CSSM_DATA param_int128 = { sizeof(asn1_int128), asn1_int128 }; + +/* + * XXX Would like the "parameters" field to be a CSSM_DATA_PTR , but the + * encoder is having trouble with optional pointers to an ANY. Maybe + * once that is fixed, can change this back... + */ +typedef struct { + CSSM_DATA capabilityID; + CSSM_DATA parameters; + long cipher; /* optimization */ +} NSSSMIMECapability; + +static const SecAsn1Template NSSSMIMECapabilityTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(NSSSMIMECapability) }, + { SEC_ASN1_OBJECT_ID, + offsetof(NSSSMIMECapability,capabilityID), }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY, + offsetof(NSSSMIMECapability,parameters), }, + { 0, } +}; + +static const SecAsn1Template NSSSMIMECapabilitiesTemplate[] = { + { SEC_ASN1_SEQUENCE_OF, 0, NSSSMIMECapabilityTemplate } +}; + +/* + * NSSSMIMEEncryptionKeyPreference - if we find one of these, it needs to prompt us + * to store this and only this certificate permanently for the sender email address. + */ +typedef enum { + NSSSMIMEEncryptionKeyPref_IssuerSN, + NSSSMIMEEncryptionKeyPref_RKeyID, + NSSSMIMEEncryptionKeyPref_SubjectKeyID +} NSSSMIMEEncryptionKeyPrefSelector; + +typedef struct { + NSSSMIMEEncryptionKeyPrefSelector selector; + union { + SecCmsIssuerAndSN *issuerAndSN; + SecCmsRecipientKeyIdentifier *recipientKeyID; + CSSM_DATA_PTR subjectKeyID; + } id; +} NSSSMIMEEncryptionKeyPreference; + +extern const SecAsn1Template SecCmsRecipientKeyIdentifierTemplate[]; + +static const SecAsn1Template smime_encryptionkeypref_template[] = { + { SEC_ASN1_CHOICE, + offsetof(NSSSMIMEEncryptionKeyPreference,selector), NULL, + sizeof(NSSSMIMEEncryptionKeyPreference) }, + { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, + offsetof(NSSSMIMEEncryptionKeyPreference,id.issuerAndSN), + SEC_ASN1_SUB(SecCmsIssuerAndSNTemplate), + NSSSMIMEEncryptionKeyPref_IssuerSN }, + { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | 1, + offsetof(NSSSMIMEEncryptionKeyPreference,id.recipientKeyID), + SecCmsRecipientKeyIdentifierTemplate, + NSSSMIMEEncryptionKeyPref_IssuerSN }, + { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2, + offsetof(NSSSMIMEEncryptionKeyPreference,id.subjectKeyID), + SEC_ASN1_SUB(kSecAsn1OctetStringTemplate), + NSSSMIMEEncryptionKeyPref_SubjectKeyID }, + { 0, } +}; + +/* smime_cipher_map - map of SMIME symmetric "ciphers" to algtag & parameters */ +typedef struct { + unsigned long cipher; + SECOidTag algtag; + CSSM_DATA_PTR parms; + Boolean enabled; /* in the user's preferences */ + Boolean allowed; /* per export policy */ +} smime_cipher_map_entry; + +/* global: list of supported SMIME symmetric ciphers, ordered roughly by increasing strength */ +static smime_cipher_map_entry smime_cipher_map[] = { +/* cipher algtag parms enabled allowed */ +/* ---------------------------------------------------------------------------------- */ + { SMIME_RC2_CBC_40, SEC_OID_RC2_CBC, ¶m_int40, PR_TRUE, PR_TRUE }, + { SMIME_DES_CBC_56, SEC_OID_DES_CBC, NULL, PR_TRUE, PR_TRUE }, + { SMIME_RC2_CBC_64, SEC_OID_RC2_CBC, ¶m_int64, PR_TRUE, PR_TRUE }, + { SMIME_RC2_CBC_128, SEC_OID_RC2_CBC, ¶m_int128, PR_TRUE, PR_TRUE }, + { SMIME_DES_EDE3_168, SEC_OID_DES_EDE3_CBC, NULL, PR_TRUE, PR_TRUE }, + { SMIME_AES_CBC_128, SEC_OID_AES_128_CBC, NULL, PR_TRUE, PR_TRUE }, + { SMIME_FORTEZZA, SEC_OID_FORTEZZA_SKIPJACK, NULL, PR_TRUE, PR_TRUE } +}; +static const int smime_cipher_map_count = sizeof(smime_cipher_map) / sizeof(smime_cipher_map_entry); + +/* + * smime_mapi_by_cipher - find index into smime_cipher_map by cipher + */ +static int +smime_mapi_by_cipher(unsigned long cipher) +{ + int i; + + for (i = 0; i < smime_cipher_map_count; i++) { + if (smime_cipher_map[i].cipher == cipher) + return i; /* bingo */ + } + return -1; /* should not happen if we're consistent, right? */ +} + +/* + * NSS_SMIME_EnableCipher - this function locally records the user's preference + */ +OSStatus +SecSMIMEEnableCipher(uint32 which, Boolean on) +{ + unsigned long mask; + int mapi; + + mask = which & CIPHER_FAMILYID_MASK; + + PORT_Assert (mask == CIPHER_FAMILYID_SMIME); + if (mask != CIPHER_FAMILYID_SMIME) + /* XXX set an error! */ + return SECFailure; + + mapi = smime_mapi_by_cipher(which); + if (mapi < 0) + /* XXX set an error */ + return SECFailure; + + /* do we try to turn on a forbidden cipher? */ + if (!smime_cipher_map[mapi].allowed && on) { + PORT_SetError (SEC_ERROR_BAD_EXPORT_ALGORITHM); + return SECFailure; + } + + if (smime_cipher_map[mapi].enabled != on) + smime_cipher_map[mapi].enabled = on; + + return SECSuccess; +} + + +/* + * this function locally records the export policy + */ +OSStatus +SecSMIMEAllowCipher(uint32 which, Boolean on) +{ + unsigned long mask; + int mapi; + + mask = which & CIPHER_FAMILYID_MASK; + + PORT_Assert (mask == CIPHER_FAMILYID_SMIME); + if (mask != CIPHER_FAMILYID_SMIME) + /* XXX set an error! */ + return SECFailure; + + mapi = smime_mapi_by_cipher(which); + if (mapi < 0) + /* XXX set an error */ + return SECFailure; + + if (smime_cipher_map[mapi].allowed != on) + smime_cipher_map[mapi].allowed = on; + + return SECSuccess; +} + +/* + * Based on the given algorithm (including its parameters, in some cases!) + * and the given key (may or may not be inspected, depending on the + * algorithm), find the appropriate policy algorithm specification + * and return it. If no match can be made, -1 is returned. + */ +static OSStatus +nss_smime_get_cipher_for_alg_and_key(SECAlgorithmID *algid, SecSymmetricKeyRef key, unsigned long *cipher) +{ + SECOidTag algtag; + unsigned int keylen_bits; + unsigned long c; + + algtag = SECOID_GetAlgorithmTag(algid); + switch (algtag) { + case SEC_OID_RC2_CBC: + if (SecKeyGetStrengthInBits(key, algid, &keylen_bits)) + return SECFailure; + switch (keylen_bits) { + case 40: + c = SMIME_RC2_CBC_40; + break; + case 64: + c = SMIME_RC2_CBC_64; + break; + case 128: + c = SMIME_RC2_CBC_128; + break; + default: + return SECFailure; + } + break; + case SEC_OID_DES_CBC: + c = SMIME_DES_CBC_56; + break; + case SEC_OID_DES_EDE3_CBC: + c = SMIME_DES_EDE3_168; + break; + case SEC_OID_AES_128_CBC: + c = SMIME_AES_CBC_128; + break; + case SEC_OID_FORTEZZA_SKIPJACK: + c = SMIME_FORTEZZA; + break; + default: + return SECFailure; + } + *cipher = c; + return SECSuccess; +} + +static Boolean +nss_smime_cipher_allowed(unsigned long which) +{ + int mapi; + + mapi = smime_mapi_by_cipher(which); + if (mapi < 0) + return PR_FALSE; + return smime_cipher_map[mapi].allowed; +} + +Boolean +SecSMIMEDecryptionAllowed(SECAlgorithmID *algid, SecSymmetricKeyRef key) +{ + unsigned long which; + + if (nss_smime_get_cipher_for_alg_and_key(algid, key, &which) != SECSuccess) + return PR_FALSE; + + return nss_smime_cipher_allowed(which); +} + + +/* + * NSS_SMIME_EncryptionPossible - check if any encryption is allowed + * + * This tells whether or not *any* S/MIME encryption can be done, + * according to policy. Callers may use this to do nicer user interface + * (say, greying out a checkbox so a user does not even try to encrypt + * a message when they are not allowed to) or for any reason they want + * to check whether S/MIME encryption (or decryption, for that matter) + * may be done. + * + * It takes no arguments. The return value is a simple boolean: + * PR_TRUE means encryption (or decryption) is *possible* + * (but may still fail due to other reasons, like because we cannot + * find all the necessary certs, etc.; PR_TRUE is *not* a guarantee) + * PR_FALSE means encryption (or decryption) is not permitted + * + * There are no errors from this routine. + */ +Boolean +SecSMIMEEncryptionPossible(void) +{ + int i; + + for (i = 0; i < smime_cipher_map_count; i++) { + if (smime_cipher_map[i].allowed) + return PR_TRUE; + } + return PR_FALSE; +} + + +static unsigned long +nss_SMIME_FindCipherForSMIMECap(NSSSMIMECapability *cap) +{ + int i; + SECOidTag capIDTag; + + /* we need the OIDTag here */ + capIDTag = SECOID_FindOIDTag(&(cap->capabilityID)); + + /* go over all the SMIME ciphers we know and see if we find a match */ + for (i = 0; i < smime_cipher_map_count; i++) { + if (smime_cipher_map[i].algtag != capIDTag) + continue; + /* + * XXX If SECITEM_CompareItem allowed NULLs as arguments (comparing + * 2 NULLs as equal and NULL and non-NULL as not equal), we could + * use that here instead of all of the following comparison code. + */ + if (cap->parameters.Data == NULL && smime_cipher_map[i].parms == NULL) + break; /* both empty: bingo */ + + if (cap->parameters.Data != NULL && smime_cipher_map[i].parms != NULL && + cap->parameters.Length == smime_cipher_map[i].parms->Length && + PORT_Memcmp (cap->parameters.Data, smime_cipher_map[i].parms->Data, + cap->parameters.Length) == 0) + { + break; /* both not empty, same length & equal content: bingo */ + } + } + + if (i == smime_cipher_map_count) + return 0; /* no match found */ + else + return smime_cipher_map[i].cipher; /* match found, point to cipher */ +} + +/* + * smime_choose_cipher - choose a cipher that works for all the recipients + * + * "scert" - sender's certificate + * "rcerts" - recipient's certificates + */ +static long +smime_choose_cipher(SecCertificateRef scert, SecCertificateRef *rcerts) +{ + PRArenaPool *poolp; + long cipher; + long chosen_cipher; + int *cipher_abilities; + int *cipher_votes; + int weak_mapi; + int strong_mapi; + int rcount, mapi, max, i; +#if 1 + // @@@ We Don't support Fortezza yet. + Boolean scert_is_fortezza = PR_FALSE; +#else + Boolean scert_is_fortezza = (scert == NULL) ? PR_FALSE : PK11_FortezzaHasKEA(scert); +#endif + + chosen_cipher = SMIME_RC2_CBC_40; /* the default, LCD */ + weak_mapi = smime_mapi_by_cipher(chosen_cipher); + + poolp = PORT_NewArena (1024); /* XXX what is right value? */ + if (poolp == NULL) + goto done; + + cipher_abilities = (int *)PORT_ArenaZAlloc(poolp, smime_cipher_map_count * sizeof(int)); + cipher_votes = (int *)PORT_ArenaZAlloc(poolp, smime_cipher_map_count * sizeof(int)); + if (cipher_votes == NULL || cipher_abilities == NULL) + goto done; + + /* If the user has the Fortezza preference turned on, make + * that the strong cipher. Otherwise, use triple-DES. */ + strong_mapi = smime_mapi_by_cipher (SMIME_DES_EDE3_168); + if (scert_is_fortezza) { + mapi = smime_mapi_by_cipher(SMIME_FORTEZZA); + if (mapi >= 0 && smime_cipher_map[mapi].enabled) + strong_mapi = mapi; + } + + /* walk all the recipient's certs */ + for (rcount = 0; rcerts[rcount] != NULL; rcount++) { + CSSM_DATA_PTR profile; + NSSSMIMECapability **caps; + int pref; + + /* the first cipher that matches in the user's SMIME profile gets + * "smime_cipher_map_count" votes; the next one gets "smime_cipher_map_count" - 1 + * and so on. If every cipher matches, the last one gets 1 (one) vote */ + pref = smime_cipher_map_count; + + /* find recipient's SMIME profile */ + profile = CERT_FindSMimeProfile(rcerts[rcount]); + + if (profile != NULL && profile->Data != NULL && profile->Length > 0) { + /* we have a profile (still DER-encoded) */ + caps = NULL; + /* decode it */ + if (SEC_ASN1DecodeItem(poolp, &caps, NSSSMIMECapabilitiesTemplate, profile) == SECSuccess && + caps != NULL) + { + /* walk the SMIME capabilities for this recipient */ + for (i = 0; caps[i] != NULL; i++) { + cipher = nss_SMIME_FindCipherForSMIMECap(caps[i]); + mapi = smime_mapi_by_cipher(cipher); + if (mapi >= 0) { + /* found the cipher */ + cipher_abilities[mapi]++; + cipher_votes[mapi] += pref; + --pref; + } + } + } + } else { + /* no profile found - so we can only assume that the user can do + * the mandatory algorithms which is RC2-40 (weak crypto) and 3DES (strong crypto) */ + SecPublicKeyRef key; + unsigned int pklen_bits; + + /* + * if recipient's public key length is > 512, vote for a strong cipher + * please not that the side effect of this is that if only one recipient + * has an export-level public key, the strong cipher is disabled. + * + * XXX This is probably only good for RSA keys. What I would + * really like is a function to just say; Is the public key in + * this cert an export-length key? Then I would not have to + * know things like the value 512, or the kind of key, or what + * a subjectPublicKeyInfo is, etc. + */ + key = CERT_ExtractPublicKey(rcerts[rcount]); + pklen_bits = 0; + if (key != NULL) { + SecKeyGetStrengthInBits(key, NULL, &pklen_bits); + SECKEY_DestroyPublicKey (key); + } + + if (pklen_bits > 512) { + /* cast votes for the strong algorithm */ + cipher_abilities[strong_mapi]++; + cipher_votes[strong_mapi] += pref; + pref--; + } + + /* always cast (possibly less) votes for the weak algorithm */ + cipher_abilities[weak_mapi]++; + cipher_votes[weak_mapi] += pref; + } + if (profile != NULL) + SECITEM_FreeItem(profile, PR_TRUE); + } + + /* find cipher that is agreeable by all recipients and that has the most votes */ + max = 0; + for (mapi = 0; mapi < smime_cipher_map_count; mapi++) { + /* if not all of the recipients can do this, forget it */ + if (cipher_abilities[mapi] != rcount) + continue; + /* if cipher is not enabled or not allowed by policy, forget it */ + if (!smime_cipher_map[mapi].enabled || !smime_cipher_map[mapi].allowed) + continue; + /* if we're not doing fortezza, but the cipher is fortezza, forget it */ + if (!scert_is_fortezza && (smime_cipher_map[mapi].cipher == SMIME_FORTEZZA)) + continue; + /* now see if this one has more votes than the last best one */ + if (cipher_votes[mapi] >= max) { + /* if equal number of votes, prefer the ones further down in the list */ + /* with the expectation that these are higher rated ciphers */ + chosen_cipher = smime_cipher_map[mapi].cipher; + max = cipher_votes[mapi]; + } + } + /* if no common cipher was found, chosen_cipher stays at the default */ + +done: + if (poolp != NULL) + PORT_FreeArena (poolp, PR_FALSE); + + return chosen_cipher; +} + +/* + * XXX This is a hack for now to satisfy our current interface. + * Eventually, with more parameters needing to be specified, just + * looking up the keysize is not going to be sufficient. + */ +static int +smime_keysize_by_cipher (unsigned long which) +{ + int keysize; + + switch (which) { + case SMIME_RC2_CBC_40: + keysize = 40; + break; + case SMIME_RC2_CBC_64: + keysize = 64; + break; + case SMIME_RC2_CBC_128: + case SMIME_AES_CBC_128: + keysize = 128; + break; + case SMIME_DES_CBC_56: + keysize = 64; + break; + case SMIME_DES_EDE3_168: + keysize = 192; + break; + case SMIME_FORTEZZA: + /* + * This is special; since the key size is fixed, we actually + * want to *avoid* specifying a key size. + */ + keysize = 0; + break; + default: + keysize = -1; + break; + } + + return keysize; +} + +/* + * SecSMIMEFindBulkAlgForRecipients - find bulk algorithm suitable for all recipients + * + * it would be great for UI purposes if there would be a way to find out which recipients + * prevented a strong cipher from being used... + */ +OSStatus +SecSMIMEFindBulkAlgForRecipients(SecCertificateRef *rcerts, SECOidTag *bulkalgtag, int *keysize) +{ + unsigned long cipher; + int mapi; + + cipher = smime_choose_cipher(NULL, rcerts); + mapi = smime_mapi_by_cipher(cipher); + + *bulkalgtag = smime_cipher_map[mapi].algtag; + *keysize = smime_keysize_by_cipher(smime_cipher_map[mapi].cipher); + + return SECSuccess; +} + +/* + * SecSMIMECreateSMIMECapabilities - get S/MIME capabilities for this instance of NSS + * + * scans the list of allowed and enabled ciphers and construct a PKCS9-compliant + * S/MIME capabilities attribute value. + * + * XXX Please note that, in contradiction to RFC2633 2.5.2, the capabilities only include + * symmetric ciphers, NO signature algorithms or key encipherment algorithms. + * + * "poolp" - arena pool to create the S/MIME capabilities data on + * "dest" - CSSM_DATA to put the data in + * "includeFortezzaCiphers" - PR_TRUE if fortezza ciphers should be included + */ +OSStatus +SecSMIMECreateSMIMECapabilities(SecArenaPoolRef pool, CSSM_DATA_PTR dest, Boolean includeFortezzaCiphers) +{ + PLArenaPool *poolp = (PLArenaPool *)pool; + NSSSMIMECapability *cap; + NSSSMIMECapability **smime_capabilities; + smime_cipher_map_entry *map; + SECOidData *oiddata; + CSSM_DATA_PTR dummy; + int i, capIndex; + + /* if we have an old NSSSMIMECapability array, we'll reuse it (has the right size) */ + /* smime_cipher_map_count + 1 is an upper bound - we might end up with less */ + smime_capabilities = (NSSSMIMECapability **)PORT_ZAlloc((smime_cipher_map_count + 1) + * sizeof(NSSSMIMECapability *)); + if (smime_capabilities == NULL) + return SECFailure; + + capIndex = 0; + + /* Add all the symmetric ciphers + * We walk the cipher list backwards, as it is ordered by increasing strength, + * we prefer the stronger cipher over a weaker one, and we have to list the + * preferred algorithm first */ + for (i = smime_cipher_map_count - 1; i >= 0; i--) { + /* Find the corresponding entry in the cipher map. */ + map = &(smime_cipher_map[i]); + if (!map->enabled) + continue; + + /* If we're using a non-Fortezza cert, only advertise non-Fortezza + capabilities. (We advertise all capabilities if we have a + Fortezza cert.) */ + if ((!includeFortezzaCiphers) && (map->cipher == SMIME_FORTEZZA)) + continue; + + /* get next SMIME capability */ + cap = (NSSSMIMECapability *)PORT_ZAlloc(sizeof(NSSSMIMECapability)); + if (cap == NULL) + break; + smime_capabilities[capIndex++] = cap; + + oiddata = SECOID_FindOIDByTag(map->algtag); + if (oiddata == NULL) + break; + + cap->capabilityID.Data = oiddata->oid.Data; + cap->capabilityID.Length = oiddata->oid.Length; + cap->parameters.Data = map->parms ? map->parms->Data : NULL; + cap->parameters.Length = map->parms ? map->parms->Length : 0; + cap->cipher = smime_cipher_map[i].cipher; + } + + /* XXX add signature algorithms */ + /* XXX add key encipherment algorithms */ + + smime_capabilities[capIndex] = NULL; /* last one - now encode */ + dummy = SEC_ASN1EncodeItem(poolp, dest, &smime_capabilities, NSSSMIMECapabilitiesTemplate); + + /* now that we have the proper encoded SMIMECapabilities (or not), + * free the work data */ + for (i = 0; smime_capabilities[i] != NULL; i++) + PORT_Free(smime_capabilities[i]); + PORT_Free(smime_capabilities); + + return (dummy == NULL) ? SECFailure : SECSuccess; +} + +/* + * SecSMIMECreateSMIMEEncKeyPrefs - create S/MIME encryption key preferences attr value + * + * "poolp" - arena pool to create the attr value on + * "dest" - CSSM_DATA to put the data in + * "cert" - certificate that should be marked as preferred encryption key + * cert is expected to have been verified for EmailRecipient usage. + */ +OSStatus +SecSMIMECreateSMIMEEncKeyPrefs(SecArenaPoolRef pool, CSSM_DATA_PTR dest, SecCertificateRef cert) +{ + PLArenaPool *poolp = (PLArenaPool *)pool; + NSSSMIMEEncryptionKeyPreference ekp; + CSSM_DATA_PTR dummy = NULL; + PLArenaPool *tmppoolp = NULL; + + if (cert == NULL) + goto loser; + + tmppoolp = PORT_NewArena(1024); + if (tmppoolp == NULL) + goto loser; + + /* XXX hardcoded IssuerSN choice for now */ + ekp.selector = NSSSMIMEEncryptionKeyPref_IssuerSN; + ekp.id.issuerAndSN = CERT_GetCertIssuerAndSN(tmppoolp, cert); + if (ekp.id.issuerAndSN == NULL) + goto loser; + + dummy = SEC_ASN1EncodeItem(poolp, dest, &ekp, smime_encryptionkeypref_template); + +loser: + if (tmppoolp) PORT_FreeArena(tmppoolp, PR_FALSE); + + return (dummy == NULL) ? SECFailure : SECSuccess; +} + +/* + * SecSMIMECreateSMIMEEncKeyPrefs - create S/MIME encryption key preferences attr value using MS oid + * + * "poolp" - arena pool to create the attr value on + * "dest" - CSSM_DATA to put the data in + * "cert" - certificate that should be marked as preferred encryption key + * cert is expected to have been verified for EmailRecipient usage. + */ +OSStatus +SecSMIMECreateMSSMIMEEncKeyPrefs(SecArenaPoolRef pool, CSSM_DATA_PTR dest, SecCertificateRef cert) +{ + PLArenaPool *poolp = (PLArenaPool *)pool; + CSSM_DATA_PTR dummy = NULL; + PLArenaPool *tmppoolp = NULL; + SecCmsIssuerAndSN *isn; + + if (cert == NULL) + goto loser; + + tmppoolp = PORT_NewArena(1024); + if (tmppoolp == NULL) + goto loser; + + isn = CERT_GetCertIssuerAndSN(tmppoolp, cert); + if (isn == NULL) + goto loser; + + dummy = SEC_ASN1EncodeItem(poolp, dest, isn, SEC_ASN1_GET(SecCmsIssuerAndSNTemplate)); + +loser: + if (tmppoolp) PORT_FreeArena(tmppoolp, PR_FALSE); + + return (dummy == NULL) ? SECFailure : SECSuccess; +} + +/* + * SecSMIMEGetCertFromEncryptionKeyPreference - + * find cert marked by EncryptionKeyPreference attribute + * + * "keychainOrArray" - handle for the cert database to look in + * "DERekp" - DER-encoded value of S/MIME Encryption Key Preference attribute + * + * if certificate is supposed to be found among the message's included certificates, + * they are assumed to have been imported already. + */ +SecCertificateRef +SecSMIMEGetCertFromEncryptionKeyPreference(SecKeychainRef keychainOrArray, CSSM_DATA_PTR DERekp) +{ + PLArenaPool *tmppoolp = NULL; + SecCertificateRef cert = NULL; + NSSSMIMEEncryptionKeyPreference ekp; + + tmppoolp = PORT_NewArena(1024); + if (tmppoolp == NULL) + return NULL; + + /* decode DERekp */ + if (SEC_ASN1DecodeItem(tmppoolp, &ekp, smime_encryptionkeypref_template, DERekp) != SECSuccess) + goto loser; + + /* find cert */ + switch (ekp.selector) { + case NSSSMIMEEncryptionKeyPref_IssuerSN: + cert = CERT_FindCertByIssuerAndSN(keychainOrArray, NULL, NULL, ekp.id.issuerAndSN); + break; + case NSSSMIMEEncryptionKeyPref_RKeyID: + case NSSSMIMEEncryptionKeyPref_SubjectKeyID: + /* XXX not supported yet - we need to be able to look up certs by SubjectKeyID */ + break; + default: + PORT_Assert(0); + } +loser: + if (tmppoolp) PORT_FreeArena(tmppoolp, PR_FALSE); + + return cert; +} + +#if 0 +extern const char __nss_smime_rcsid[]; +extern const char __nss_smime_sccsid[]; +#endif + +#if 0 /* -- unused */ +Boolean +NSSSMIME_VersionCheck(const char *importedVersion) +{ +#if 1 + return PR_TRUE; +#else + /* + * This is the secret handshake algorithm. + * + * This release has a simple version compatibility + * check algorithm. This release is not backward + * compatible with previous major releases. It is + * not compatible with future major, minor, or + * patch releases. + */ + volatile char c; /* force a reference that won't get optimized away */ + + c = __nss_smime_rcsid[0] + __nss_smime_sccsid[0]; + + return NSS_VersionCheck(importedVersion); +#endif +} +#endif diff --git a/Security/libsecurity_smime/lib/testcms b/Security/libsecurity_smime/lib/testcms new file mode 100755 index 00000000..69e0613d --- /dev/null +++ b/Security/libsecurity_smime/lib/testcms @@ -0,0 +1,43 @@ +#!/bin/zsh + +test -x ${SECURITY:=~/build/security} || unset SECURITY +SECURITY=${SECURITY?must specify the full path to the security command} +TMPDIR=/tmp/smime-$$ +NAME=mb@apple.com + +mkdir $TMPDIR +cd $TMPDIR + +$SECURITY cms -O -r $NAME -o content +$SECURITY cms -D -i content -o /dev/null +$SECURITY cms -D -h 0 -n -i content + +$SECURITY cms -S -N $NAME -Y NONE -i content -o signed +$SECURITY cms -D -i signed -o signed.out +$SECURITY cms -D -h 0 -n -i signed +cmp content signed.out + +$SECURITY cms -S -N $NAME -Y NONE -G -i content -o signed+date +$SECURITY cms -D -i signed+date -o signed+date.out +$SECURITY cms -D -h 0 -n -i signed+date +cmp content signed+date.out + +$SECURITY cms -S -N $NAME -G -P -i content -o signed+smime +$SECURITY cms -D -i signed+smime -o signed+smime.out +$SECURITY cms -D -h 0 -n -i signed+smime +cmp content signed+smime.out + +$SECURITY cms -S -N $NAME -T -Y NONE -i content -o signed+detached +$SECURITY cms -D -c content -i signed+detached -o signed+detached.out +$SECURITY cms -D -h 0 -n -c content -i signed+detached +cmp content signed+detached.out + +$SECURITY cms -S -N $NAME -T -G -P -i content -o signed+detached+smime +$SECURITY cms -D -c content -i signed+detached+smime -o signed+detached+smime.out +$SECURITY cms -D -h 0 -n -c content -i signed+detached+smime +cmp content signed+detached+smime.out + +$SECURITY cms -E -r $NAME -i content -o encrypted +$SECURITY cms -D -i encrypted -o encrypted.out +$SECURITY cms -D -h 0 -n -i encrypted +cmp content encrypted.out diff --git a/libsecurity_smime/lib/tsaSupport.c b/Security/libsecurity_smime/lib/tsaSupport.c similarity index 98% rename from libsecurity_smime/lib/tsaSupport.c rename to Security/libsecurity_smime/lib/tsaSupport.c index e894fc74..a92e956b 100644 --- a/libsecurity_smime/lib/tsaSupport.c +++ b/Security/libsecurity_smime/lib/tsaSupport.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ * * tsaSupport.c - ASN1 templates Time Stamping Authority requests and responses @@ -47,6 +47,7 @@ #include #include #include +#include #include "tsaSupport.h" #include "tsaSupportPriv.h" @@ -1008,16 +1009,19 @@ static const char *trustResultTypeString(SecTrustResultType trustResultType) } #endif -static OSStatus verifySigners(SecCmsSignedDataRef signedData, int numberOfSigners) +static OSStatus verifySigners(SecCmsSignedDataRef signedData, int numberOfSigners, CFTypeRef timeStampPolicy) { // See Bubble up SecTrustEvaluate of timestamp response to high level callers // Also Properly handle revocation information of timestamping certificate - SecPolicyRef policy = NULL; + CFTypeRef policy = CFRetainSafe(timeStampPolicy); int result=errSecInternalError; int rx; - require(policy = SecPolicyCreateWithOID(kSecPolicyAppleTimeStamping), xit); + if (!policy) { + require(policy = SecPolicyCreateWithOID(kSecPolicyAppleTimeStamping), xit); + } + int jx; for (jx = 0; jx < numberOfSigners; ++jx) { @@ -1230,6 +1234,11 @@ xit: */ OSStatus decodeTimeStampToken(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR inData, CSSM_DATA_PTR encDigest, uint64_t expectedNonce) +{ + return decodeTimeStampTokenWithPolicy(signerinfo, NULL, inData, encDigest, expectedNonce); +} + +OSStatus decodeTimeStampTokenWithPolicy(SecCmsSignerInfoRef signerinfo, CFTypeRef timeStampPolicy, CSSM_DATA_PTR inData, CSSM_DATA_PTR encDigest, uint64_t expectedNonce) { /* We update signerinfo with timestamp and tsa certificate chain. @@ -1342,7 +1351,7 @@ OSStatus decodeTimeStampToken(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR inDa int numberOfSigners = SecCmsSignedDataSignerInfoCount (signedData); - result = verifySigners(signedData, numberOfSigners); + result = verifySigners(signedData, numberOfSigners, timeStampPolicy); if (result) dtprintf("verifySigners failed: %ld\n", (long)result); // warning diff --git a/libsecurity_smime/lib/tsaSupport.h b/Security/libsecurity_smime/lib/tsaSupport.h similarity index 96% rename from libsecurity_smime/lib/tsaSupport.h rename to Security/libsecurity_smime/lib/tsaSupport.h index bbea6e1c..9ccbd6e6 100644 --- a/libsecurity_smime/lib/tsaSupport.h +++ b/Security/libsecurity_smime/lib/tsaSupport.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_smime/lib/tsaSupportPriv.h b/Security/libsecurity_smime/lib/tsaSupportPriv.h similarity index 90% rename from libsecurity_smime/lib/tsaSupportPriv.h rename to Security/libsecurity_smime/lib/tsaSupportPriv.h index 3f954d27..985df045 100644 --- a/libsecurity_smime/lib/tsaSupportPriv.h +++ b/Security/libsecurity_smime/lib/tsaSupportPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -41,6 +41,7 @@ extern const CFStringRef kTSADebugContextKeyBadNonce; // CFBooleanRef OSStatus SecTSAResponseCopyDEREncoding(SecAsn1CoderRef coder, const CSSM_DATA *tsaResponse, SecAsn1TimeStampRespDER *respDER); OSStatus decodeTimeStampToken(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR inData, CSSM_DATA_PTR encDigest, uint64_t expectedNonce); +OSStatus decodeTimeStampTokenWithPolicy(SecCmsSignerInfoRef signerinfo, CFTypeRef timeStampPolicy, CSSM_DATA_PTR inData, CSSM_DATA_PTR encDigest, uint64_t expectedNonce); OSStatus createTSAMessageImprint(SecCmsSignedDataRef signedData, CSSM_DATA_PTR encDigest, SecAsn1TSAMessageImprint *messageImprint); #ifndef NDEBUG diff --git a/libsecurity_smime/lib/tsaTemplates.c b/Security/libsecurity_smime/lib/tsaTemplates.c similarity index 96% rename from libsecurity_smime/lib/tsaTemplates.c rename to Security/libsecurity_smime/lib/tsaTemplates.c index 787158de..22068473 100644 --- a/libsecurity_smime/lib/tsaTemplates.c +++ b/Security/libsecurity_smime/lib/tsaTemplates.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. - * + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code @@ -31,18 +31,21 @@ #include "tsaTemplates.h" #include "cmslocal.h" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-const-variable" + // *** from CMSEncoder.cpp typedef struct { CSSM_OID contentType; - CSSM_DATA content; + CSSM_DATA content; } SimpleContentInfo; // SecCmsContentInfoTemplate static const SecAsn1Template cmsSimpleContentInfoTemplate[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SimpleContentInfo) }, { SEC_ASN1_OBJECT_ID, offsetof(SimpleContentInfo, contentType) }, - { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, + { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, offsetof(SimpleContentInfo, content), kSecAsn1AnyTemplate }, { 0, } @@ -122,7 +125,7 @@ const SecAsn1Template kSecAsn1TSATimeStampReqTemplate[] = { offsetof(SecAsn1TSATimeStampReq,reqPolicy) }, { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, offsetof(SecAsn1TSATimeStampReq, nonce) }, - { SEC_ASN1_BOOLEAN | SEC_ASN1_OPTIONAL, + { SEC_ASN1_BOOLEAN | SEC_ASN1_OPTIONAL, offsetof(SecAsn1TSATimeStampReq, certReq) }, { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, offsetof(SecAsn1TSATimeStampReq, extensions), @@ -136,7 +139,7 @@ const SecAsn1Template kSecAsn1TSATimeStampReqTemplate[] = { -- text encoded as UTF-8 String (note: each UTF8String SHOULD -- include an RFC 1766 language tag to indicate the language -- of the contained text) } - + See e.g. kSecAsn1SequenceOfUTF8StringTemplate */ @@ -218,7 +221,7 @@ const SecAsn1Template kSecAsn1TSATimeStampRespTemplateDER[] = { millis [0] INTEGER (1..999) OPTIONAL, micros [1] INTEGER (1..999) OPTIONAL } */ - + const SecAsn1Template kSecAsn1TSATSTInfoTemplate[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SecAsn1TSATSTInfo) }, @@ -235,7 +238,7 @@ const SecAsn1Template kSecAsn1TSATSTInfoTemplate[] = { { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL, offsetof(SecAsn1TSATSTInfo,accuracy), kSecAsn1TSAAccuracyTemplate }, - { SEC_ASN1_BOOLEAN | SEC_ASN1_OPTIONAL, + { SEC_ASN1_BOOLEAN | SEC_ASN1_OPTIONAL, offsetof(SecAsn1TSATSTInfo, ordering) }, { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, offsetof(SecAsn1TSATSTInfo, nonce) }, @@ -249,4 +252,4 @@ const SecAsn1Template kSecAsn1TSATSTInfoTemplate[] = { { 0 } }; - +#pragma clang diagnostic pop diff --git a/libsecurity_smime/lib/tsaTemplates.h b/Security/libsecurity_smime/lib/tsaTemplates.h similarity index 98% rename from libsecurity_smime/lib/tsaTemplates.h rename to Security/libsecurity_smime/lib/tsaTemplates.h index 098e36f3..5fd1e061 100644 --- a/libsecurity_smime/lib/tsaTemplates.h +++ b/Security/libsecurity_smime/lib/tsaTemplates.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_smime/libsecurity_smime.xcodeproj/project.pbxproj b/Security/libsecurity_smime/libsecurity_smime.xcodeproj/project.pbxproj new file mode 100644 index 00000000..9718aebc --- /dev/null +++ b/Security/libsecurity_smime/libsecurity_smime.xcodeproj/project.pbxproj @@ -0,0 +1,648 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + 0540498B0A37699A0035F195 /* Copy Open Source Docs */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 054049900A3769AC0035F195 /* Build configuration list for PBXAggregateTarget "Copy Open Source Docs" */; + buildPhases = ( + 0540498A0A37699A0035F195 /* CopyFiles */, + 054049A10A376A130035F195 /* CopyFiles */, + ); + dependencies = ( + ); + name = "Copy Open Source Docs"; + productName = "Copy Open Source Docs"; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 0540498E0A3769AC0035F195 /* libsecurity_smime.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0540498C0A3769AC0035F195 /* libsecurity_smime.plist */; }; + 054049990A376A010035F195 /* libsecurity_smime.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0540498D0A3769AC0035F195 /* libsecurity_smime.txt */; }; + 0588CB2A0E7084880069D232 /* siginfoUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0588CB290E7084880069D232 /* siginfoUtils.cpp */; }; + 4C14208F0415845900CA2E66 /* cmsdigdata.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F803E9FC5B00A80181 /* cmsdigdata.c */; }; + 4C27421103E9FC6700A80181 /* cmsarray.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F203E9FC5B00A80181 /* cmsarray.c */; }; + 4C27421303E9FC6900A80181 /* cmsasn1.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F303E9FC5B00A80181 /* cmsasn1.c */; }; + 4C27421403E9FC6A00A80181 /* cmsattr.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F403E9FC5B00A80181 /* cmsattr.c */; }; + 4C27421503E9FC6C00A80181 /* cmscinfo.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F503E9FC5B00A80181 /* cmscinfo.c */; }; + 4C27421703E9FC6D00A80181 /* cmsdecode.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F703E9FC5B00A80181 /* cmsdecode.c */; }; + 4C27421B03E9FC7000A80181 /* cmsencode.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741FB03E9FC5B00A80181 /* cmsencode.c */; }; + 4C27421D03E9FC7100A80181 /* cmslocal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C2741FD03E9FC5B00A80181 /* cmslocal.h */; }; + 4C27421E03E9FC7200A80181 /* cmsmessage.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741FE03E9FC5B00A80181 /* cmsmessage.c */; }; + 4C27422103E9FC7500A80181 /* cmsreclist.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C27420103E9FC5B00A80181 /* cmsreclist.c */; }; + 4C27422203E9FC7600A80181 /* cmsreclist.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C27420203E9FC5B00A80181 /* cmsreclist.h */; }; + 4C424BE8063F28F600E9831A /* SecSMIMEPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C424BE7063F28F600E9831A /* SecSMIMEPriv.h */; }; + 4C6CA861040308C700CA2E66 /* cmssigdata.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C27420303E9FC5B00A80181 /* cmssigdata.c */; }; + 4C7183480637153700230DDE /* SecSMIME.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7183470637153700230DDE /* SecSMIME.h */; settings = {ATTRIBUTES = (); }; }; + 4C8E166F0438EEE700CA2E66 /* secoid.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C8E166C0438EEE700CA2E66 /* secoid.c */; }; + 4C8E16700438EEE700CA2E66 /* secoid.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C8E166D0438EEE700CA2E66 /* secoid.h */; }; + 4C8E16740438EF5700CA2E66 /* plhash.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C8E16720438EF5700CA2E66 /* plhash.c */; }; + 4C8E16750438EF5700CA2E66 /* plhash.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C8E16730438EF5700CA2E66 /* plhash.h */; }; + 4C8E16790438EFD700CA2E66 /* secitem.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C8E16770438EFD700CA2E66 /* secitem.c */; }; + 4C8E167A0438EFD700CA2E66 /* secitem.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C8E16780438EFD700CA2E66 /* secitem.h */; }; + 4CA51CE00420246F00CA2E66 /* cryptohi.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CA51CDF0420246F00CA2E66 /* cryptohi.h */; }; + 4CB42E340421212D00CA2E66 /* cryptohi.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CB42E330421212D00CA2E66 /* cryptohi.c */; }; + 4CB6AADA040DA84D00CA2E66 /* secalgid.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CB6AAD9040DA84D00CA2E66 /* secalgid.c */; }; + 4CCC260E0635F1A200CBF0D4 /* SecCmsBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26030635F1A100CBF0D4 /* SecCmsBase.h */; settings = {ATTRIBUTES = (); }; }; + 4CCC260F0635F1A200CBF0D4 /* SecCmsContentInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26040635F1A100CBF0D4 /* SecCmsContentInfo.h */; settings = {ATTRIBUTES = (); }; }; + 4CCC26100635F1A200CBF0D4 /* SecCmsDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26050635F1A100CBF0D4 /* SecCmsDecoder.h */; settings = {ATTRIBUTES = (); }; }; + 4CCC26110635F1A200CBF0D4 /* SecCmsDigestContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26060635F1A100CBF0D4 /* SecCmsDigestContext.h */; settings = {ATTRIBUTES = (); }; }; + 4CCC26120635F1A200CBF0D4 /* SecCmsDigestedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26070635F1A100CBF0D4 /* SecCmsDigestedData.h */; settings = {ATTRIBUTES = (); }; }; + 4CCC26130635F1A200CBF0D4 /* SecCmsEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26080635F1A100CBF0D4 /* SecCmsEncoder.h */; settings = {ATTRIBUTES = (); }; }; + 4CCC26140635F1A200CBF0D4 /* SecCmsEnvelopedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26090635F1A100CBF0D4 /* SecCmsEnvelopedData.h */; settings = {ATTRIBUTES = (); }; }; + 4CCC26150635F1A200CBF0D4 /* SecCmsMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC260A0635F1A100CBF0D4 /* SecCmsMessage.h */; settings = {ATTRIBUTES = (); }; }; + 4CCC26160635F1A200CBF0D4 /* SecCmsRecipientInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC260B0635F1A100CBF0D4 /* SecCmsRecipientInfo.h */; settings = {ATTRIBUTES = (); }; }; + 4CCC26170635F1A200CBF0D4 /* SecCmsSignedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC260C0635F1A100CBF0D4 /* SecCmsSignedData.h */; settings = {ATTRIBUTES = (); }; }; + 4CCC26180635F1A200CBF0D4 /* SecCmsSignerInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC260D0635F1A100CBF0D4 /* SecCmsSignerInfo.h */; settings = {ATTRIBUTES = (); }; }; + 4CDA0D5E04200AD600CA2E66 /* cmscipher.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F603E9FC5B00A80181 /* cmscipher.c */; }; + 4CDA0D6004200AD800CA2E66 /* cmsencdata.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741FA03E9FC5B00A80181 /* cmsencdata.c */; }; + 4CDA0D6104200AD800CA2E66 /* cmsdigest.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F903E9FC5B00A80181 /* cmsdigest.c */; }; + 4CDA0D6204200AD900CA2E66 /* cmsenvdata.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741FC03E9FC5B00A80181 /* cmsenvdata.c */; }; + 4CDA0D6304200ADD00CA2E66 /* cmspubkey.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741FF03E9FC5B00A80181 /* cmspubkey.c */; }; + 4CDA0D6404200ADD00CA2E66 /* cmsrecinfo.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C27420003E9FC5B00A80181 /* cmsrecinfo.c */; }; + 4CDA0D6504200ADF00CA2E66 /* cmsutil.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6D72BC0410298900CA2E66 /* cmsutil.c */; }; + 4CDA0D6604200AE000CA2E66 /* cmssiginfo.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C27420403E9FC5B00A80181 /* cmssiginfo.c */; }; + 4CDA0D6704200B0F00CA2E66 /* smimeutil.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C27420F03E9FC5B00A80181 /* smimeutil.c */; }; + 4CEC5CDF042A721300CA2E66 /* cmspriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CEC5CDE042A721300CA2E66 /* cmspriv.h */; }; + 4CEC5CE1042A722000CA2E66 /* cmstpriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CEC5CE0042A722000CA2E66 /* cmstpriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4CEDC82106371B1700B7E254 /* SecCmsEncryptedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CEDC82006371B1700B7E254 /* SecCmsEncryptedData.h */; settings = {ATTRIBUTES = (); }; }; + 5232A822150AD71A00E6BB48 /* tsaSupportPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 5232A821150AD71A00E6BB48 /* tsaSupportPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 52B609D514F4665700134209 /* tsaTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = 52B609D314F4665700134209 /* tsaTemplates.c */; }; + 52B609D614F4665700134209 /* tsaTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B609D414F4665700134209 /* tsaTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 52D7A24A15092A0600CF48F7 /* tsaSupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 52D7A24915092A0600CF48F7 /* tsaSupport.c */; }; + 52D7A24D15094B8B00CF48F7 /* tsaSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 52D7A24C15092AAD00CF48F7 /* tsaSupport.h */; settings = {ATTRIBUTES = (Private, ); }; }; + AC62F5F418B4358B00704BBD /* smime-cms-test.c in Sources */ = {isa = PBXBuildFile; fileRef = ACBEE91018B420BC0021712D /* smime-cms-test.c */; }; + ACA9CE4A18BC4543005AD855 /* SecCMS.h in Headers */ = {isa = PBXBuildFile; fileRef = ACBEE90D18B415B60021712D /* SecCMS.h */; }; + ACBEE90C18B403470021712D /* SecCMS.c in Sources */ = {isa = PBXBuildFile; fileRef = ACBEE90B18B403470021712D /* SecCMS.c */; }; + ACBEE90E18B415B60021712D /* SecCMS.h in Headers */ = {isa = PBXBuildFile; fileRef = ACBEE90D18B415B60021712D /* SecCMS.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F64399010420118A01CA2DCC /* cert.h in Headers */ = {isa = PBXBuildFile; fileRef = F64398FF0420118A01CA2DCC /* cert.h */; }; + F64399020420118A01CA2DCC /* cert.c in Sources */ = {isa = PBXBuildFile; fileRef = F64399000420118A01CA2DCC /* cert.c */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 0540499A0A376A090035F195 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C2741E803E9FBAF00A80181 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0540498B0A37699A0035F195; + remoteInfo = "Copy Open Source Docs"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 0540498A0A37699A0035F195 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/local/OpenSourceVersions/; + dstSubfolderSpec = 0; + files = ( + 0540498E0A3769AC0035F195 /* libsecurity_smime.plist in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 054049A10A376A130035F195 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/local/OpenSourceLicenses/; + dstSubfolderSpec = 0; + files = ( + 054049990A376A010035F195 /* libsecurity_smime.txt in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0540498C0A3769AC0035F195 /* libsecurity_smime.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; path = libsecurity_smime.plist; sourceTree = ""; }; + 0540498D0A3769AC0035F195 /* libsecurity_smime.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = libsecurity_smime.txt; sourceTree = ""; }; + 0588CB290E7084880069D232 /* siginfoUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = siginfoUtils.cpp; sourceTree = ""; }; + 182BB39E146F1A68000BF1F3 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 182BB39F146F1A68000BF1F3 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 182BB3A0146F1A68000BF1F3 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 182BB3A1146F1A68000BF1F3 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 4C21887E0635F4D300E64E02 /* security_smime.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = security_smime.exp; sourceTree = ""; }; + 4C2741F203E9FC5B00A80181 /* cmsarray.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmsarray.c; sourceTree = ""; tabWidth = 8; }; + 4C2741F303E9FC5B00A80181 /* cmsasn1.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmsasn1.c; sourceTree = ""; tabWidth = 8; }; + 4C2741F403E9FC5B00A80181 /* cmsattr.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmsattr.c; sourceTree = ""; tabWidth = 8; }; + 4C2741F503E9FC5B00A80181 /* cmscinfo.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmscinfo.c; sourceTree = ""; tabWidth = 8; }; + 4C2741F603E9FC5B00A80181 /* cmscipher.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmscipher.c; sourceTree = ""; tabWidth = 8; }; + 4C2741F703E9FC5B00A80181 /* cmsdecode.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmsdecode.c; sourceTree = ""; tabWidth = 8; }; + 4C2741F803E9FC5B00A80181 /* cmsdigdata.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmsdigdata.c; sourceTree = ""; tabWidth = 8; }; + 4C2741F903E9FC5B00A80181 /* cmsdigest.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmsdigest.c; sourceTree = ""; tabWidth = 8; }; + 4C2741FA03E9FC5B00A80181 /* cmsencdata.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmsencdata.c; sourceTree = ""; tabWidth = 8; }; + 4C2741FB03E9FC5B00A80181 /* cmsencode.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmsencode.c; sourceTree = ""; tabWidth = 8; }; + 4C2741FC03E9FC5B00A80181 /* cmsenvdata.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmsenvdata.c; sourceTree = ""; tabWidth = 8; }; + 4C2741FD03E9FC5B00A80181 /* cmslocal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cmslocal.h; sourceTree = ""; tabWidth = 8; }; + 4C2741FE03E9FC5B00A80181 /* cmsmessage.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmsmessage.c; sourceTree = ""; tabWidth = 8; }; + 4C2741FF03E9FC5B00A80181 /* cmspubkey.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmspubkey.c; sourceTree = ""; tabWidth = 8; }; + 4C27420003E9FC5B00A80181 /* cmsrecinfo.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmsrecinfo.c; sourceTree = ""; tabWidth = 8; }; + 4C27420103E9FC5B00A80181 /* cmsreclist.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmsreclist.c; sourceTree = ""; tabWidth = 8; }; + 4C27420203E9FC5B00A80181 /* cmsreclist.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cmsreclist.h; sourceTree = ""; tabWidth = 8; }; + 4C27420303E9FC5B00A80181 /* cmssigdata.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmssigdata.c; sourceTree = ""; tabWidth = 8; }; + 4C27420403E9FC5B00A80181 /* cmssiginfo.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmssiginfo.c; sourceTree = ""; tabWidth = 8; }; + 4C27420F03E9FC5B00A80181 /* smimeutil.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = smimeutil.c; sourceTree = ""; tabWidth = 8; }; + 4C424BE7063F28F600E9831A /* SecSMIMEPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecSMIMEPriv.h; sourceTree = ""; }; + 4C6D72BC0410298900CA2E66 /* cmsutil.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmsutil.c; sourceTree = ""; tabWidth = 8; }; + 4C7183470637153700230DDE /* SecSMIME.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecSMIME.h; sourceTree = ""; }; + 4C817F8405ED4D7A007975E6 /* libsecurity_smime.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurity_smime.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C8E166C0438EEE700CA2E66 /* secoid.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = secoid.c; sourceTree = ""; }; + 4C8E166D0438EEE700CA2E66 /* secoid.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = secoid.h; sourceTree = ""; }; + 4C8E166E0438EEE700CA2E66 /* secoidt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = secoidt.h; sourceTree = ""; }; + 4C8E16720438EF5700CA2E66 /* plhash.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = plhash.c; sourceTree = ""; }; + 4C8E16730438EF5700CA2E66 /* plhash.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = plhash.h; sourceTree = ""; }; + 4C8E16770438EFD700CA2E66 /* secitem.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = secitem.c; sourceTree = ""; }; + 4C8E16780438EFD700CA2E66 /* secitem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = secitem.h; sourceTree = ""; }; + 4CA51CDF0420246F00CA2E66 /* cryptohi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cryptohi.h; sourceTree = ""; tabWidth = 8; }; + 4CB42E330421212D00CA2E66 /* cryptohi.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cryptohi.c; sourceTree = ""; tabWidth = 8; }; + 4CB6AAD9040DA84D00CA2E66 /* secalgid.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = secalgid.c; sourceTree = ""; }; + 4CCC26030635F1A100CBF0D4 /* SecCmsBase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsBase.h; sourceTree = ""; }; + 4CCC26040635F1A100CBF0D4 /* SecCmsContentInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsContentInfo.h; sourceTree = ""; }; + 4CCC26050635F1A100CBF0D4 /* SecCmsDecoder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsDecoder.h; sourceTree = ""; }; + 4CCC26060635F1A100CBF0D4 /* SecCmsDigestContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsDigestContext.h; sourceTree = ""; }; + 4CCC26070635F1A100CBF0D4 /* SecCmsDigestedData.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsDigestedData.h; sourceTree = ""; }; + 4CCC26080635F1A100CBF0D4 /* SecCmsEncoder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsEncoder.h; sourceTree = ""; }; + 4CCC26090635F1A100CBF0D4 /* SecCmsEnvelopedData.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsEnvelopedData.h; sourceTree = ""; }; + 4CCC260A0635F1A100CBF0D4 /* SecCmsMessage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsMessage.h; sourceTree = ""; }; + 4CCC260B0635F1A100CBF0D4 /* SecCmsRecipientInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsRecipientInfo.h; sourceTree = ""; }; + 4CCC260C0635F1A100CBF0D4 /* SecCmsSignedData.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsSignedData.h; sourceTree = ""; }; + 4CCC260D0635F1A100CBF0D4 /* SecCmsSignerInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsSignerInfo.h; sourceTree = ""; }; + 4CEC5CDE042A721300CA2E66 /* cmspriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cmspriv.h; sourceTree = ""; }; + 4CEC5CE0042A722000CA2E66 /* cmstpriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cmstpriv.h; sourceTree = ""; }; + 4CEDC82006371B1700B7E254 /* SecCmsEncryptedData.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsEncryptedData.h; sourceTree = ""; }; + 5232A821150AD71A00E6BB48 /* tsaSupportPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tsaSupportPriv.h; sourceTree = ""; }; + 52B609D314F4665700134209 /* tsaTemplates.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tsaTemplates.c; sourceTree = ""; }; + 52B609D414F4665700134209 /* tsaTemplates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tsaTemplates.h; sourceTree = ""; }; + 52D7A24915092A0600CF48F7 /* tsaSupport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tsaSupport.c; sourceTree = ""; }; + 52D7A24C15092AAD00CF48F7 /* tsaSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = tsaSupport.h; sourceTree = ""; }; + AC62F5F018B4356A00704BBD /* libsecurity_smime_regressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurity_smime_regressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; + ACBEE90B18B403470021712D /* SecCMS.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecCMS.c; sourceTree = ""; }; + ACBEE90D18B415B60021712D /* SecCMS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCMS.h; sourceTree = ""; }; + ACBEE91018B420BC0021712D /* smime-cms-test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "smime-cms-test.c"; sourceTree = ""; }; + ACBEE91318B421890021712D /* smime_regressions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = smime_regressions.h; sourceTree = ""; }; + F64398FF0420118A01CA2DCC /* cert.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cert.h; sourceTree = ""; tabWidth = 8; }; + F64399000420118A01CA2DCC /* cert.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cert.c; sourceTree = ""; tabWidth = 8; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4C2741EB03E9FBF700A80181 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AC62F5ED18B4356A00704BBD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 054049870A3769830035F195 /* docs */ = { + isa = PBXGroup; + children = ( + 0540498D0A3769AC0035F195 /* libsecurity_smime.txt */, + 0540498C0A3769AC0035F195 /* libsecurity_smime.plist */, + ); + path = docs; + sourceTree = ""; + }; + 182BB39D146F1A68000BF1F3 /* config */ = { + isa = PBXGroup; + children = ( + 182BB39E146F1A68000BF1F3 /* base.xcconfig */, + 182BB39F146F1A68000BF1F3 /* debug.xcconfig */, + 182BB3A0146F1A68000BF1F3 /* lib.xcconfig */, + 182BB3A1146F1A68000BF1F3 /* release.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 4C2741E403E9FBAF00A80181 = { + isa = PBXGroup; + children = ( + ACBEE90F18B41FB80021712D /* regressions */, + 4C2741F003E9FC2100A80181 /* lib */, + 182BB39D146F1A68000BF1F3 /* config */, + 054049870A3769830035F195 /* docs */, + 4C2741EF03E9FBF700A80181 /* Products */, + ); + sourceTree = ""; + }; + 4C2741EF03E9FBF700A80181 /* Products */ = { + isa = PBXGroup; + children = ( + 4C817F8405ED4D7A007975E6 /* libsecurity_smime.a */, + AC62F5F018B4356A00704BBD /* libsecurity_smime_regressions.a */, + ); + name = Products; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4C2741F003E9FC2100A80181 /* lib */ = { + isa = PBXGroup; + children = ( + 5232A821150AD71A00E6BB48 /* tsaSupportPriv.h */, + 52D7A24915092A0600CF48F7 /* tsaSupport.c */, + 52D7A24C15092AAD00CF48F7 /* tsaSupport.h */, + 52B609D314F4665700134209 /* tsaTemplates.c */, + 52B609D414F4665700134209 /* tsaTemplates.h */, + 0588CB290E7084880069D232 /* siginfoUtils.cpp */, + F64399000420118A01CA2DCC /* cert.c */, + F64398FF0420118A01CA2DCC /* cert.h */, + 4C2741F203E9FC5B00A80181 /* cmsarray.c */, + 4C2741F303E9FC5B00A80181 /* cmsasn1.c */, + 4C2741F403E9FC5B00A80181 /* cmsattr.c */, + 4C2741F503E9FC5B00A80181 /* cmscinfo.c */, + 4C2741F603E9FC5B00A80181 /* cmscipher.c */, + 4C2741F703E9FC5B00A80181 /* cmsdecode.c */, + 4C2741F803E9FC5B00A80181 /* cmsdigdata.c */, + 4C2741F903E9FC5B00A80181 /* cmsdigest.c */, + 4C2741FA03E9FC5B00A80181 /* cmsencdata.c */, + 4C2741FB03E9FC5B00A80181 /* cmsencode.c */, + 4C2741FC03E9FC5B00A80181 /* cmsenvdata.c */, + 4C2741FD03E9FC5B00A80181 /* cmslocal.h */, + 4C2741FE03E9FC5B00A80181 /* cmsmessage.c */, + 4CEC5CDE042A721300CA2E66 /* cmspriv.h */, + 4C2741FF03E9FC5B00A80181 /* cmspubkey.c */, + 4C27420003E9FC5B00A80181 /* cmsrecinfo.c */, + 4C27420103E9FC5B00A80181 /* cmsreclist.c */, + 4C27420203E9FC5B00A80181 /* cmsreclist.h */, + 4C27420303E9FC5B00A80181 /* cmssigdata.c */, + 4C27420403E9FC5B00A80181 /* cmssiginfo.c */, + 4CEC5CE0042A722000CA2E66 /* cmstpriv.h */, + 4C6D72BC0410298900CA2E66 /* cmsutil.c */, + 4CB42E330421212D00CA2E66 /* cryptohi.c */, + 4CA51CDF0420246F00CA2E66 /* cryptohi.h */, + 4C8E16720438EF5700CA2E66 /* plhash.c */, + 4C8E16730438EF5700CA2E66 /* plhash.h */, + 4CB6AAD9040DA84D00CA2E66 /* secalgid.c */, + 4CCC26030635F1A100CBF0D4 /* SecCmsBase.h */, + 4CCC26040635F1A100CBF0D4 /* SecCmsContentInfo.h */, + 4CCC26050635F1A100CBF0D4 /* SecCmsDecoder.h */, + 4CCC26060635F1A100CBF0D4 /* SecCmsDigestContext.h */, + 4CCC26070635F1A100CBF0D4 /* SecCmsDigestedData.h */, + 4CCC26080635F1A100CBF0D4 /* SecCmsEncoder.h */, + 4CEDC82006371B1700B7E254 /* SecCmsEncryptedData.h */, + 4CCC26090635F1A100CBF0D4 /* SecCmsEnvelopedData.h */, + 4CCC260A0635F1A100CBF0D4 /* SecCmsMessage.h */, + 4CCC260B0635F1A100CBF0D4 /* SecCmsRecipientInfo.h */, + 4CCC260C0635F1A100CBF0D4 /* SecCmsSignedData.h */, + 4CCC260D0635F1A100CBF0D4 /* SecCmsSignerInfo.h */, + 4C8E16770438EFD700CA2E66 /* secitem.c */, + 4C8E16780438EFD700CA2E66 /* secitem.h */, + 4C8E166C0438EEE700CA2E66 /* secoid.c */, + 4C8E166D0438EEE700CA2E66 /* secoid.h */, + 4C8E166E0438EEE700CA2E66 /* secoidt.h */, + 4C7183470637153700230DDE /* SecSMIME.h */, + 4C424BE7063F28F600E9831A /* SecSMIMEPriv.h */, + 4C21887E0635F4D300E64E02 /* security_smime.exp */, + 4C27420F03E9FC5B00A80181 /* smimeutil.c */, + ACBEE90B18B403470021712D /* SecCMS.c */, + ACBEE90D18B415B60021712D /* SecCMS.h */, + ); + path = lib; + sourceTree = ""; + }; + ACBEE90F18B41FB80021712D /* regressions */ = { + isa = PBXGroup; + children = ( + ACBEE91018B420BC0021712D /* smime-cms-test.c */, + ACBEE91318B421890021712D /* smime_regressions.h */, + ); + path = regressions; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4C2741E903E9FBF700A80181 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + F64399010420118A01CA2DCC /* cert.h in Headers */, + 4C27421D03E9FC7100A80181 /* cmslocal.h in Headers */, + 4CEC5CDF042A721300CA2E66 /* cmspriv.h in Headers */, + 4C27422203E9FC7600A80181 /* cmsreclist.h in Headers */, + 4CEC5CE1042A722000CA2E66 /* cmstpriv.h in Headers */, + 4CA51CE00420246F00CA2E66 /* cryptohi.h in Headers */, + 4C8E16750438EF5700CA2E66 /* plhash.h in Headers */, + 4CCC260E0635F1A200CBF0D4 /* SecCmsBase.h in Headers */, + 4CCC260F0635F1A200CBF0D4 /* SecCmsContentInfo.h in Headers */, + 4CCC26100635F1A200CBF0D4 /* SecCmsDecoder.h in Headers */, + 4CCC26110635F1A200CBF0D4 /* SecCmsDigestContext.h in Headers */, + 4CCC26120635F1A200CBF0D4 /* SecCmsDigestedData.h in Headers */, + 4CCC26130635F1A200CBF0D4 /* SecCmsEncoder.h in Headers */, + 4CEDC82106371B1700B7E254 /* SecCmsEncryptedData.h in Headers */, + 4CCC26140635F1A200CBF0D4 /* SecCmsEnvelopedData.h in Headers */, + 4CCC26150635F1A200CBF0D4 /* SecCmsMessage.h in Headers */, + 4CCC26160635F1A200CBF0D4 /* SecCmsRecipientInfo.h in Headers */, + 4CCC26170635F1A200CBF0D4 /* SecCmsSignedData.h in Headers */, + 4CCC26180635F1A200CBF0D4 /* SecCmsSignerInfo.h in Headers */, + 4C7183480637153700230DDE /* SecSMIME.h in Headers */, + 4C8E167A0438EFD700CA2E66 /* secitem.h in Headers */, + 4C8E16700438EEE700CA2E66 /* secoid.h in Headers */, + 4C424BE8063F28F600E9831A /* SecSMIMEPriv.h in Headers */, + 52B609D614F4665700134209 /* tsaTemplates.h in Headers */, + 52D7A24D15094B8B00CF48F7 /* tsaSupport.h in Headers */, + ACBEE90E18B415B60021712D /* SecCMS.h in Headers */, + 5232A822150AD71A00E6BB48 /* tsaSupportPriv.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AC62F5EE18B4356A00704BBD /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ACA9CE4A18BC4543005AD855 /* SecCMS.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 4C2741ED03E9FBF700A80181 /* libsecurity_smime */ = { + isa = PBXNativeTarget; + buildConfigurationList = C23B0CD309A298C100B7FCED /* Build configuration list for PBXNativeTarget "libsecurity_smime" */; + buildPhases = ( + 4C2741E903E9FBF700A80181 /* Headers */, + 4C2741EA03E9FBF700A80181 /* Sources */, + 4C2741EB03E9FBF700A80181 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 0540499B0A376A090035F195 /* PBXTargetDependency */, + ); + name = libsecurity_smime; + productInstallPath = /usr/local/lib; + productName = libSecurityNssSmime.a; + productReference = 4C817F8405ED4D7A007975E6 /* libsecurity_smime.a */; + productType = "com.apple.product-type.library.static"; + }; + AC62F5EF18B4356A00704BBD /* libsecurity_smime_regressions */ = { + isa = PBXNativeTarget; + buildConfigurationList = AC62F5F318B4356A00704BBD /* Build configuration list for PBXNativeTarget "libsecurity_smime_regressions" */; + buildPhases = ( + AC62F5EC18B4356A00704BBD /* Sources */, + AC62F5ED18B4356A00704BBD /* Frameworks */, + AC62F5EE18B4356A00704BBD /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libsecurity_smime_regressions; + productName = libsecurity_smime_regressions; + productReference = AC62F5F018B4356A00704BBD /* libsecurity_smime_regressions.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4C2741E803E9FBAF00A80181 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = C23B0CD909A298C100B7FCED /* Build configuration list for PBXProject "libsecurity_smime" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 4C2741E403E9FBAF00A80181; + productRefGroup = 4C2741EF03E9FBF700A80181 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4C2741ED03E9FBF700A80181 /* libsecurity_smime */, + 0540498B0A37699A0035F195 /* Copy Open Source Docs */, + AC62F5EF18B4356A00704BBD /* libsecurity_smime_regressions */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 4C2741EA03E9FBF700A80181 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F64399020420118A01CA2DCC /* cert.c in Sources */, + 4C27421103E9FC6700A80181 /* cmsarray.c in Sources */, + 4C27421303E9FC6900A80181 /* cmsasn1.c in Sources */, + 4C27421403E9FC6A00A80181 /* cmsattr.c in Sources */, + 4C27421503E9FC6C00A80181 /* cmscinfo.c in Sources */, + 4CDA0D5E04200AD600CA2E66 /* cmscipher.c in Sources */, + ACBEE90C18B403470021712D /* SecCMS.c in Sources */, + 4C27421703E9FC6D00A80181 /* cmsdecode.c in Sources */, + 4C14208F0415845900CA2E66 /* cmsdigdata.c in Sources */, + 4CDA0D6104200AD800CA2E66 /* cmsdigest.c in Sources */, + 4CDA0D6004200AD800CA2E66 /* cmsencdata.c in Sources */, + 4C27421B03E9FC7000A80181 /* cmsencode.c in Sources */, + 4CDA0D6204200AD900CA2E66 /* cmsenvdata.c in Sources */, + 4C27421E03E9FC7200A80181 /* cmsmessage.c in Sources */, + 4CDA0D6304200ADD00CA2E66 /* cmspubkey.c in Sources */, + 4CDA0D6404200ADD00CA2E66 /* cmsrecinfo.c in Sources */, + 4C27422103E9FC7500A80181 /* cmsreclist.c in Sources */, + 4C6CA861040308C700CA2E66 /* cmssigdata.c in Sources */, + 4CDA0D6604200AE000CA2E66 /* cmssiginfo.c in Sources */, + 4CDA0D6504200ADF00CA2E66 /* cmsutil.c in Sources */, + 4CB42E340421212D00CA2E66 /* cryptohi.c in Sources */, + 4C8E16740438EF5700CA2E66 /* plhash.c in Sources */, + 4CB6AADA040DA84D00CA2E66 /* secalgid.c in Sources */, + 4C8E16790438EFD700CA2E66 /* secitem.c in Sources */, + 4C8E166F0438EEE700CA2E66 /* secoid.c in Sources */, + 4CDA0D6704200B0F00CA2E66 /* smimeutil.c in Sources */, + 0588CB2A0E7084880069D232 /* siginfoUtils.cpp in Sources */, + 52B609D514F4665700134209 /* tsaTemplates.c in Sources */, + 52D7A24A15092A0600CF48F7 /* tsaSupport.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AC62F5EC18B4356A00704BBD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AC62F5F418B4358B00704BBD /* smime-cms-test.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 0540499B0A376A090035F195 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0540498B0A37699A0035F195 /* Copy Open Source Docs */; + targetProxy = 0540499A0A376A090035F195 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 054049910A3769AC0035F195 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + 054049950A3769AC0035F195 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; + AC62F5F118B4356A00704BBD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + EXECUTABLE_PREFIX = ""; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + AC62F5F218B4356A00704BBD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + EXECUTABLE_PREFIX = ""; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + C23B0CD409A298C100B7FCED /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB39F146F1A68000BF1F3 /* debug.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C23B0CD809A298C100B7FCED /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB3A1146F1A68000BF1F3 /* release.xcconfig */; + buildSettings = { + }; + name = Release; + }; + C23B0CDA09A298C100B7FCED /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB3A0146F1A68000BF1F3 /* lib.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C23B0CDE09A298C100B7FCED /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 182BB3A0146F1A68000BF1F3 /* lib.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 054049900A3769AC0035F195 /* Build configuration list for PBXAggregateTarget "Copy Open Source Docs" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 054049910A3769AC0035F195 /* Debug */, + 054049950A3769AC0035F195 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + AC62F5F318B4356A00704BBD /* Build configuration list for PBXNativeTarget "libsecurity_smime_regressions" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AC62F5F118B4356A00704BBD /* Debug */, + AC62F5F218B4356A00704BBD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C23B0CD309A298C100B7FCED /* Build configuration list for PBXNativeTarget "libsecurity_smime" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C23B0CD409A298C100B7FCED /* Debug */, + C23B0CD809A298C100B7FCED /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C23B0CD909A298C100B7FCED /* Build configuration list for PBXProject "libsecurity_smime" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C23B0CDA09A298C100B7FCED /* Debug */, + C23B0CDE09A298C100B7FCED /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4C2741E803E9FBAF00A80181 /* Project object */; +} diff --git a/Security/libsecurity_smime/regressions/smime-cms-test.c b/Security/libsecurity_smime/regressions/smime-cms-test.c new file mode 100644 index 00000000..7d743c59 --- /dev/null +++ b/Security/libsecurity_smime/regressions/smime-cms-test.c @@ -0,0 +1,524 @@ +/* + * Copyright (c) 2008-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +int smime_cms_test(int argc, char *const *argv); + +/* + Bag Attributes +friendlyName: uranusLeaf +localKeyID: 46 E0 8A 05 63 4D 17 3F CA A4 AA B6 5A DA CF BA 84 22 7C 23 +subject=/CN=uranusLeaf/emailAddress=uranus@uranus.com +issuer=/CN=plutoCA/emailAddress=pluto@pluto.com + */ +static const uint8_t _c1[] = { + 0x30, 0x82, 0x02, 0xe0, 0x30, 0x82, 0x01, 0xc8, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, + 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x30, 0x32, 0x31, + 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x07, 0x70, 0x6c, 0x75, 0x74, 0x6f, 0x43, + 0x41, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, + 0x0c, 0x0f, 0x70, 0x6c, 0x75, 0x74, 0x6f, 0x40, + 0x70, 0x6c, 0x75, 0x74, 0x6f, 0x2e, 0x63, 0x6f, + 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x35, 0x31, + 0x32, 0x31, 0x37, 0x30, 0x30, 0x30, 0x34, 0x32, + 0x35, 0x5a, 0x17, 0x0d, 0x30, 0x36, 0x31, 0x32, + 0x31, 0x37, 0x30, 0x30, 0x30, 0x34, 0x32, 0x35, + 0x5a, 0x30, 0x37, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0a, 0x75, 0x72, + 0x61, 0x6e, 0x75, 0x73, 0x4c, 0x65, 0x61, 0x66, + 0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x0c, + 0x11, 0x75, 0x72, 0x61, 0x6e, 0x75, 0x73, 0x40, + 0x75, 0x72, 0x61, 0x6e, 0x75, 0x73, 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, 0xa6, 0x82, 0x8e, 0xc6, 0x7e, + 0xc9, 0x8c, 0x99, 0x6f, 0xb0, 0x62, 0x32, 0x35, + 0xe7, 0xdb, 0xff, 0x34, 0x84, 0xdc, 0x72, 0xa8, + 0xef, 0x22, 0x6f, 0x93, 0x63, 0x64, 0x80, 0x80, + 0x5d, 0x50, 0x7e, 0xb4, 0x2e, 0x1b, 0x93, 0x93, + 0x49, 0xca, 0xae, 0xcd, 0x34, 0x44, 0x4b, 0xd7, + 0xfa, 0x9f, 0x3c, 0xfc, 0x9e, 0x65, 0xa9, 0xfb, + 0x5e, 0x5d, 0x18, 0xa3, 0xf8, 0xb0, 0x08, 0xac, + 0x8f, 0xfd, 0x03, 0xcb, 0xbd, 0x7f, 0xa0, 0x2a, + 0xa6, 0xea, 0xca, 0xa3, 0x24, 0xef, 0x7c, 0xc3, + 0xeb, 0x95, 0xcb, 0x90, 0x3f, 0x5e, 0xde, 0x78, + 0xf2, 0x3d, 0x32, 0x72, 0xdb, 0x33, 0x6e, 0x9b, + 0x52, 0x9f, 0x0c, 0x60, 0x4a, 0x24, 0xa1, 0xf6, + 0x3b, 0x80, 0xbd, 0xa1, 0xdc, 0x40, 0x03, 0xe7, + 0xa0, 0x59, 0x1f, 0xdb, 0xb4, 0xed, 0x57, 0xdc, + 0x74, 0x0d, 0x99, 0x5a, 0x12, 0x74, 0x64, 0xaa, + 0xb6, 0xa5, 0x96, 0x75, 0xf9, 0x42, 0x43, 0xe2, + 0x52, 0xc2, 0x57, 0x23, 0x75, 0xd7, 0xa9, 0x4f, + 0x07, 0x32, 0x99, 0xbd, 0x3d, 0x44, 0xbd, 0x04, + 0x62, 0xe5, 0xb7, 0x2c, 0x0c, 0x11, 0xc5, 0xb2, + 0x2e, 0xc4, 0x12, 0x1d, 0x7f, 0x42, 0x1e, 0x71, + 0xaf, 0x39, 0x2b, 0x78, 0x47, 0x92, 0x23, 0x44, + 0xef, 0xe3, 0xc1, 0x47, 0x69, 0x5a, 0xf1, 0x48, + 0xaa, 0x37, 0xa4, 0x94, 0x6b, 0x96, 0xe5, 0x4b, + 0xfd, 0x05, 0xc7, 0x9c, 0xcc, 0x38, 0xd1, 0x47, + 0x85, 0x60, 0x7f, 0xef, 0xe9, 0x2e, 0x25, 0x08, + 0xf8, 0x7d, 0x98, 0xdd, 0x6c, 0xeb, 0x4a, 0x32, + 0x33, 0x44, 0x0b, 0x61, 0xb3, 0xf9, 0xae, 0x26, + 0x41, 0xb5, 0x38, 0xdb, 0xcf, 0x13, 0x72, 0x23, + 0x5b, 0x66, 0x20, 0x86, 0x4d, 0x24, 0xc2, 0xd4, + 0x94, 0xde, 0xe3, 0x24, 0xb7, 0xcd, 0x75, 0x9e, + 0x1d, 0x9f, 0xbc, 0xd0, 0x60, 0x34, 0x7d, 0xf8, + 0xcb, 0x41, 0x39, 0x02, 0x03, 0x01, 0x00, 0x01, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, + 0x82, 0x01, 0x01, 0x00, 0x17, 0xa5, 0x22, 0xed, + 0xb8, 0x3e, 0x1f, 0x11, 0x99, 0xc5, 0xba, 0x28, + 0x3e, 0x7e, 0xa6, 0xeb, 0x02, 0x81, 0x06, 0xa1, + 0xc6, 0x80, 0xb9, 0x7e, 0x5c, 0x5a, 0x63, 0xe0, + 0x8d, 0xeb, 0xd0, 0xec, 0x9c, 0x3a, 0x94, 0x64, + 0x7c, 0x13, 0x54, 0x0d, 0xd6, 0xe3, 0x27, 0x88, + 0xa6, 0xd2, 0x4b, 0x36, 0xdd, 0x2e, 0xfa, 0x94, + 0xe5, 0x03, 0x27, 0xc9, 0xa6, 0x31, 0x02, 0xea, + 0x40, 0x77, 0x2e, 0x93, 0xc4, 0x4d, 0xe2, 0x70, + 0xe2, 0x67, 0x1c, 0xa8, 0x0d, 0xcd, 0x1a, 0x72, + 0x86, 0x2c, 0xea, 0xdc, 0x7f, 0x8c, 0x49, 0x2c, + 0xe7, 0x99, 0x13, 0xda, 0x3f, 0x58, 0x9e, 0xf5, + 0x4d, 0x3c, 0x8c, 0x1c, 0xed, 0x85, 0xa7, 0xe2, + 0xae, 0xda, 0x5f, 0xbe, 0x36, 0x1c, 0x9f, 0x5a, + 0xa0, 0xdc, 0x2a, 0xc0, 0xee, 0x71, 0x07, 0x26, + 0x8b, 0xe8, 0x8a, 0xf8, 0x2d, 0x36, 0x78, 0xc9, + 0x79, 0xfa, 0xbe, 0x98, 0x59, 0x95, 0x12, 0x24, + 0xf1, 0xda, 0x20, 0xc7, 0x78, 0xf9, 0x7c, 0x6a, + 0x24, 0x43, 0x82, 0xa8, 0x0f, 0xb1, 0x7d, 0x94, + 0xaa, 0x30, 0x35, 0xe5, 0x69, 0xdc, 0x0a, 0x0e, + 0xaf, 0x10, 0x5e, 0x1a, 0x81, 0x50, 0x5c, 0x7e, + 0x24, 0xb3, 0x07, 0x65, 0x4b, 0xc1, 0x7e, 0xc6, + 0x38, 0xdb, 0xd3, 0x6a, 0xf0, 0xd8, 0x85, 0x61, + 0x9a, 0x9f, 0xfe, 0x02, 0x46, 0x29, 0xb2, 0x9a, + 0xe2, 0x04, 0xe7, 0x72, 0xcc, 0x87, 0x46, 0xba, + 0x7d, 0xa8, 0xf9, 0xd0, 0x0f, 0x29, 0xfc, 0xfd, + 0xd1, 0xd0, 0x7f, 0x36, 0xc1, 0xd8, 0x7d, 0x88, + 0x03, 0x62, 0xf5, 0x8c, 0x00, 0xb5, 0xc2, 0x81, + 0x44, 0x67, 0x58, 0x11, 0xb4, 0x3a, 0xbb, 0xd1, + 0x8c, 0x94, 0x20, 0x60, 0xea, 0xa0, 0xac, 0xc1, + 0xf1, 0x08, 0x54, 0xb8, 0xf6, 0x5e, 0xac, 0xf1, + 0xec, 0x78, 0x69, 0x9d, 0x7e, 0x4d, 0x06, 0x3b, + 0x9b, 0x78, 0x78, 0x10 +}; + +/* A certs only cms message. */ +static UInt8 certsOnlyMsg[] = { + 0x30, 0x82, 0x04, 0xdc, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, + 0x82, 0x04, 0xcd, 0x30, 0x82, 0x04, 0xc9, 0x02, + 0x01, 0x01, 0x31, 0x00, 0x30, 0x0b, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, + 0x01, 0xa0, 0x82, 0x04, 0xb1, 0x30, 0x82, 0x04, + 0xad, 0x30, 0x82, 0x03, 0x95, 0xa0, 0x03, 0x02, + 0x01, 0x02, 0x02, 0x10, 0x4e, 0x2d, 0x47, 0x54, + 0xcd, 0xbb, 0x8e, 0x98, 0x42, 0xdb, 0x18, 0x9e, + 0x3a, 0xca, 0x80, 0xcc, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x05, 0x05, 0x00, 0x30, 0x57, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, + 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x63, + 0x6f, 0x6d, 0x31, 0x15, 0x30, 0x13, 0x06, 0x0a, + 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, + 0x01, 0x19, 0x16, 0x05, 0x61, 0x70, 0x70, 0x6c, + 0x65, 0x31, 0x17, 0x30, 0x15, 0x06, 0x0a, 0x09, + 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, + 0x19, 0x16, 0x07, 0x63, 0x61, 0x6c, 0x6c, 0x69, + 0x65, 0x39, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x07, 0x63, 0x61, 0x6c, + 0x6c, 0x69, 0x65, 0x39, 0x30, 0x1e, 0x17, 0x0d, + 0x30, 0x34, 0x30, 0x32, 0x32, 0x34, 0x31, 0x39, + 0x31, 0x35, 0x35, 0x37, 0x5a, 0x17, 0x0d, 0x30, + 0x39, 0x30, 0x32, 0x32, 0x34, 0x31, 0x39, 0x32, + 0x35, 0x30, 0x31, 0x5a, 0x30, 0x57, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, + 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, + 0x63, 0x6f, 0x6d, 0x31, 0x15, 0x30, 0x13, 0x06, + 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, + 0x64, 0x01, 0x19, 0x16, 0x05, 0x61, 0x70, 0x70, + 0x6c, 0x65, 0x31, 0x17, 0x30, 0x15, 0x06, 0x0a, + 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, + 0x01, 0x19, 0x16, 0x07, 0x63, 0x61, 0x6c, 0x6c, + 0x69, 0x65, 0x39, 0x31, 0x10, 0x30, 0x0e, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x07, 0x63, 0x61, + 0x6c, 0x6c, 0x69, 0x65, 0x39, 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, 0x9d, 0xbf, + 0x50, 0x9c, 0x42, 0xea, 0xad, 0xfa, 0xb7, 0x3e, + 0x22, 0xcf, 0xc5, 0xba, 0xd3, 0x3a, 0xe8, 0x62, + 0xb5, 0x62, 0x3d, 0x1e, 0xcf, 0xec, 0x52, 0x48, + 0x51, 0xa0, 0xef, 0x20, 0xf2, 0x7b, 0xb2, 0x57, + 0x25, 0x86, 0xd7, 0x15, 0xd8, 0xc6, 0x1a, 0x5f, + 0x95, 0xe0, 0x35, 0x97, 0x23, 0x7c, 0xc6, 0x88, + 0x11, 0x1c, 0x8d, 0x8d, 0x7d, 0xf0, 0xc0, 0xbd, + 0x71, 0x49, 0xbd, 0x9e, 0x51, 0x02, 0x3c, 0x70, + 0xd7, 0xaa, 0xd2, 0x80, 0xb4, 0xda, 0xb0, 0x3b, + 0x42, 0x16, 0x50, 0xc6, 0x1b, 0x17, 0x29, 0xd6, + 0xbe, 0x40, 0xce, 0x3c, 0x54, 0xaf, 0xf5, 0x29, + 0xc6, 0x12, 0x47, 0xc4, 0x96, 0x85, 0x46, 0xaa, + 0xf1, 0x76, 0xd1, 0x76, 0x22, 0xd3, 0x45, 0xf7, + 0x71, 0xea, 0x4b, 0x42, 0x7b, 0x97, 0x39, 0x02, + 0x2c, 0x6d, 0x36, 0x2a, 0x80, 0xaa, 0x01, 0x58, + 0xbc, 0x52, 0xa2, 0xa4, 0xc4, 0x3c, 0xe8, 0xcd, + 0xb2, 0xb8, 0x4a, 0xd3, 0x4e, 0x06, 0xcc, 0x52, + 0x0f, 0x5e, 0xd2, 0xe9, 0xe9, 0xb8, 0xe6, 0x79, + 0xe3, 0x91, 0x24, 0x72, 0x44, 0x65, 0x3c, 0xfe, + 0x01, 0x69, 0x70, 0x0a, 0xce, 0xd1, 0x9a, 0xd1, + 0x3f, 0x77, 0xa6, 0x78, 0x04, 0x9b, 0x7b, 0x14, + 0x37, 0x71, 0x3d, 0x4b, 0x56, 0xe9, 0xc3, 0xf6, + 0x58, 0x16, 0x0c, 0x10, 0x86, 0x5b, 0xbd, 0x93, + 0xc0, 0xf5, 0xb8, 0xbb, 0x78, 0xcf, 0xf3, 0xb2, + 0xaa, 0xaf, 0xc4, 0x0c, 0x66, 0x13, 0x1d, 0xce, + 0x98, 0x4e, 0x99, 0x93, 0xb6, 0xf7, 0xe0, 0x73, + 0xb6, 0x74, 0x55, 0xcf, 0x83, 0x1d, 0x8d, 0x68, + 0xcf, 0x59, 0x5e, 0x1b, 0x3e, 0xb5, 0x5a, 0x71, + 0x36, 0x07, 0xb6, 0xfa, 0xc4, 0x6f, 0xe5, 0x7b, + 0x69, 0x09, 0xe7, 0xe5, 0xce, 0x8a, 0x1c, 0xfa, + 0x5c, 0xdc, 0x5d, 0x18, 0xf4, 0x5a, 0x5b, 0x0d, + 0x37, 0x44, 0x56, 0x9e, 0xe9, 0x95, 0x02, 0x03, + 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x73, 0x30, + 0x82, 0x01, 0x6f, 0x30, 0x0b, 0x06, 0x03, 0x55, + 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, + 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, + 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, + 0x04, 0x16, 0x04, 0x14, 0x6c, 0xde, 0x50, 0x56, + 0x01, 0x34, 0xdc, 0x26, 0xec, 0x85, 0xdf, 0xf7, + 0x32, 0x67, 0x68, 0x08, 0x04, 0xa0, 0xa8, 0xcd, + 0x30, 0x82, 0x01, 0x1c, 0x06, 0x03, 0x55, 0x1d, + 0x1f, 0x04, 0x82, 0x01, 0x13, 0x30, 0x82, 0x01, + 0x0f, 0x30, 0x82, 0x01, 0x0b, 0xa0, 0x82, 0x01, + 0x07, 0xa0, 0x82, 0x01, 0x03, 0x86, 0x81, 0xbf, + 0x6c, 0x64, 0x61, 0x70, 0x3a, 0x2f, 0x2f, 0x2f, + 0x43, 0x4e, 0x3d, 0x63, 0x61, 0x6c, 0x6c, 0x69, + 0x65, 0x39, 0x2c, 0x43, 0x4e, 0x3d, 0x63, 0x68, + 0x72, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x2d, 0x6d, + 0x74, 0x33, 0x71, 0x66, 0x6f, 0x2c, 0x43, 0x4e, + 0x3d, 0x43, 0x44, 0x50, 0x2c, 0x43, 0x4e, 0x3d, + 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x25, 0x32, + 0x30, 0x4b, 0x65, 0x79, 0x25, 0x32, 0x30, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2c, + 0x43, 0x4e, 0x3d, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x2c, 0x43, 0x4e, 0x3d, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x44, 0x43, 0x3d, + 0x63, 0x61, 0x6c, 0x6c, 0x69, 0x65, 0x39, 0x2c, + 0x44, 0x43, 0x3d, 0x61, 0x70, 0x70, 0x6c, 0x65, + 0x2c, 0x44, 0x43, 0x3d, 0x63, 0x6f, 0x6d, 0x3f, + 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, + 0x74, 0x3f, 0x62, 0x61, 0x73, 0x65, 0x3f, 0x6f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, + 0x73, 0x73, 0x3d, 0x63, 0x52, 0x4c, 0x44, 0x69, + 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, + 0x6f, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x86, + 0x3f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, + 0x63, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6f, 0x70, + 0x2d, 0x6d, 0x74, 0x33, 0x71, 0x66, 0x6f, 0x2e, + 0x63, 0x61, 0x6c, 0x6c, 0x69, 0x65, 0x39, 0x2e, + 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x43, 0x65, 0x72, 0x74, 0x45, 0x6e, + 0x72, 0x6f, 0x6c, 0x6c, 0x2f, 0x63, 0x61, 0x6c, + 0x6c, 0x69, 0x65, 0x39, 0x2e, 0x63, 0x72, 0x6c, + 0x30, 0x10, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, + 0x01, 0x82, 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, + 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, + 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x9d, 0xba, + 0x9a, 0xeb, 0x1d, 0x78, 0x99, 0x93, 0xc6, 0x2c, + 0x36, 0x16, 0xa0, 0x15, 0x18, 0xe8, 0x20, 0x2e, + 0xb2, 0x0a, 0x8c, 0x02, 0x2e, 0x69, 0xe3, 0x9c, + 0x03, 0x26, 0x56, 0x41, 0xdd, 0x5a, 0xe1, 0x49, + 0x38, 0x5d, 0xf8, 0x1d, 0x09, 0x57, 0x22, 0xad, + 0xd9, 0xf4, 0x47, 0xa4, 0x0a, 0x46, 0xd7, 0x13, + 0xda, 0x08, 0xa1, 0x2c, 0xff, 0xb3, 0xbd, 0x07, + 0xfa, 0x95, 0x98, 0x0f, 0x53, 0x40, 0x79, 0xb2, + 0xf7, 0x85, 0x67, 0xf6, 0x37, 0x7f, 0xec, 0x21, + 0xf6, 0xb4, 0x6c, 0xda, 0x93, 0x03, 0x32, 0x74, + 0x5a, 0xa8, 0x81, 0x86, 0x10, 0xb7, 0x55, 0x11, + 0xe7, 0x53, 0xc3, 0x0a, 0x7e, 0x47, 0xba, 0xf5, + 0x8a, 0xaa, 0xab, 0x02, 0xc2, 0x01, 0xd6, 0x5b, + 0xb2, 0x96, 0xa9, 0x04, 0xda, 0xc2, 0x83, 0xb5, + 0x09, 0x54, 0x69, 0x67, 0xd2, 0x3a, 0x13, 0x6a, + 0x6c, 0xce, 0xc0, 0x64, 0x92, 0xb5, 0xda, 0x48, + 0x1c, 0x07, 0x15, 0xfb, 0xdd, 0x5f, 0xb6, 0x66, + 0x4c, 0x89, 0x44, 0xa0, 0x5c, 0x22, 0x41, 0x3d, + 0x5f, 0x21, 0x97, 0xa9, 0x0f, 0x58, 0xe9, 0xf8, + 0x16, 0x5e, 0xd9, 0x1e, 0x9d, 0x99, 0x0a, 0x9c, + 0xf3, 0x8b, 0x35, 0x3d, 0x0e, 0xc1, 0x10, 0x13, + 0x77, 0xcf, 0x4d, 0x4c, 0x85, 0xb4, 0x66, 0x27, + 0xa8, 0x79, 0x8f, 0xa4, 0x9f, 0x5f, 0x1f, 0xe9, + 0xe6, 0x39, 0xc0, 0xcf, 0x3d, 0x4a, 0x17, 0x3f, + 0x0b, 0xbf, 0x35, 0xe7, 0xe4, 0x47, 0x66, 0x4d, + 0x1e, 0xbc, 0x58, 0xf5, 0x62, 0xf8, 0x31, 0x02, + 0x84, 0xfb, 0x52, 0x39, 0x26, 0x92, 0xc3, 0xff, + 0x2a, 0x0a, 0x8e, 0x76, 0x66, 0xbc, 0x94, 0x38, + 0xe2, 0x28, 0x19, 0xcd, 0x40, 0xde, 0x88, 0xdd, + 0xfe, 0xf1, 0xdd, 0x62, 0xf4, 0xb5, 0x58, 0xf6, + 0x30, 0x22, 0xc3, 0x94, 0xed, 0xd2, 0x0a, 0x9a, + 0x71, 0x14, 0xd4, 0xed, 0x70, 0x94, 0x31, 0x00 +}; + +// X.509 IPACCG2 Test Certificate Valid Class 87 device, cms format +const uint8_t gkIPACCG2DevCertClass87 [] = +{ + 0x30, 0x82, 0x03, 0x8a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x07, 0x02, 0xa0, 0x82, 0x03, 0x7b, 0x30, 0x82, 0x03, 0x77, 0x02, + 0x01, 0x01, 0x31, 0x00, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x03, 0x5d, 0x30, 0x82, 0x03, + 0x59, 0x30, 0x82, 0x02, 0x41, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0f, + 0x33, 0x33, 0xaa, 0x13, 0x02, 0x07, 0xaa, 0x87, 0xaa, 0x00, 0x01, 0xaa, + 0x00, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x83, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, + 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, + 0x03, 0x55, 0x04, 0x0b, 0x13, 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, + 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2e, 0x41, 0x70, + 0x70, 0x6c, 0x65, 0x20, 0x69, 0x50, 0x6f, 0x64, 0x20, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, + 0x31, 0x33, 0x30, 0x32, 0x30, 0x37, 0x30, 0x31, 0x32, 0x33, 0x31, 0x30, + 0x5a, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x32, 0x30, 0x37, 0x30, 0x31, 0x32, + 0x33, 0x31, 0x30, 0x5a, 0x30, 0x70, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, + 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, + 0x0b, 0x13, 0x16, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x69, 0x50, 0x6f, + 0x64, 0x20, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x69, 0x65, + 0x73, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x14, 0x22, + 0x49, 0x50, 0x41, 0x5f, 0x33, 0x33, 0x33, 0x33, 0x41, 0x41, 0x31, 0x33, + 0x30, 0x32, 0x30, 0x37, 0x41, 0x41, 0x38, 0x37, 0x41, 0x41, 0x30, 0x30, + 0x30, 0x31, 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 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, 0xbc, 0xa8, 0x7b, 0xa8, 0xdb, 0x0c, 0xb8, 0x6e, 0x3a, + 0x1d, 0x57, 0x8c, 0x3a, 0x8c, 0x91, 0xe7, 0x0e, 0x86, 0xc8, 0xe8, 0xd8, + 0x41, 0xfe, 0x30, 0xd4, 0x77, 0x8c, 0x81, 0xb8, 0x5e, 0x6c, 0x79, 0x29, + 0xff, 0x57, 0x50, 0x41, 0x0b, 0x2e, 0x7f, 0x64, 0xa5, 0xc5, 0xc6, 0x2a, + 0x7e, 0x49, 0xdf, 0x65, 0x19, 0x5d, 0x6d, 0x0e, 0x7c, 0xc4, 0xb8, 0xb3, + 0x1a, 0x59, 0x00, 0x86, 0xa6, 0xde, 0xc3, 0x98, 0x80, 0x20, 0x0e, 0xf1, + 0xb3, 0x21, 0x1f, 0x68, 0x33, 0xe4, 0x2c, 0xd3, 0x8b, 0x7a, 0x24, 0x55, + 0xb5, 0xb3, 0x42, 0xa3, 0x2a, 0x40, 0x7c, 0xe4, 0xda, 0x32, 0xb3, 0x41, + 0xa0, 0x74, 0xe7, 0xfd, 0x97, 0x0c, 0xbe, 0x6f, 0xe3, 0xfd, 0xb9, 0x14, + 0x89, 0x50, 0xc5, 0xb3, 0x22, 0xcf, 0x47, 0xc7, 0x2e, 0x3b, 0xe3, 0x80, + 0x13, 0xac, 0x08, 0xe5, 0x3c, 0xe9, 0xbc, 0x56, 0x5f, 0x3b, 0xb9, 0x02, + 0x03, 0x01, 0x00, 0x01, 0xa3, 0x60, 0x30, 0x5e, 0x30, 0x0e, 0x06, 0x03, + 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x03, 0xb8, + 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, + 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, + 0x14, 0x09, 0xa5, 0x78, 0x7d, 0xfe, 0x2b, 0x75, 0x6d, 0x3f, 0xf4, 0x2b, + 0xa2, 0xa2, 0x96, 0xc8, 0x50, 0x16, 0xf7, 0x8b, 0x9f, 0x30, 0x1f, 0x06, + 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xff, 0x4b, + 0x1a, 0x43, 0x9a, 0xf5, 0x19, 0x96, 0xab, 0x18, 0x00, 0x2b, 0x61, 0xc9, + 0xee, 0x40, 0x9d, 0x8e, 0xc7, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, + 0x01, 0x00, 0x6b, 0xbb, 0x91, 0x97, 0xcd, 0x17, 0xc5, 0x1b, 0x10, 0xbf, + 0x29, 0x2d, 0x69, 0xeb, 0xd0, 0x96, 0x32, 0x4f, 0x89, 0x64, 0x82, 0x96, + 0x52, 0x59, 0x73, 0x15, 0x6b, 0x5d, 0x01, 0xa7, 0x90, 0x34, 0xd7, 0xc0, + 0x46, 0xc3, 0xfc, 0x27, 0xf0, 0x68, 0xfe, 0xf8, 0x54, 0x76, 0xf8, 0x61, + 0xc9, 0x91, 0xf8, 0x7d, 0x96, 0x1f, 0x14, 0x7c, 0x09, 0x27, 0xf9, 0x16, + 0x34, 0x15, 0x19, 0xa8, 0xb3, 0xd0, 0x0f, 0xf3, 0x16, 0xe1, 0xb0, 0x2e, + 0x70, 0xfe, 0xee, 0x3a, 0xbc, 0x3d, 0x4e, 0x07, 0x86, 0x89, 0x1c, 0xdb, + 0xe3, 0x2e, 0xc8, 0x66, 0x6a, 0x10, 0x82, 0x13, 0x8f, 0xf0, 0x75, 0xfa, + 0x6a, 0x25, 0x9d, 0xdb, 0x83, 0x66, 0xb1, 0xae, 0x72, 0x25, 0x03, 0x01, + 0x2b, 0x74, 0x8b, 0xbb, 0x37, 0xee, 0x92, 0x17, 0x81, 0xb3, 0x9a, 0xd3, + 0x7b, 0xfc, 0x0c, 0x35, 0xe8, 0xd5, 0x2c, 0xdb, 0x3e, 0x83, 0x9d, 0x05, + 0x3e, 0x40, 0x18, 0xb0, 0xe6, 0xcf, 0x18, 0x2d, 0x85, 0x96, 0x3f, 0x80, + 0xcd, 0xff, 0xb5, 0x71, 0xcf, 0xb2, 0x54, 0xab, 0xd3, 0xea, 0x24, 0x86, + 0xd0, 0xb8, 0xc6, 0x84, 0x75, 0xfa, 0x5e, 0xbf, 0xee, 0x3a, 0xde, 0x2b, + 0xdf, 0x05, 0x19, 0xf4, 0x1c, 0x02, 0x2f, 0x7f, 0x46, 0xbd, 0x58, 0x0f, + 0x8a, 0xb6, 0xdf, 0x84, 0xe5, 0xa3, 0x3d, 0x22, 0xf4, 0xff, 0x4a, 0x1a, + 0x87, 0x1c, 0xa9, 0x0f, 0x73, 0x62, 0x96, 0x96, 0x27, 0x5a, 0x1d, 0x4e, + 0xfa, 0x1f, 0xa5, 0xf4, 0x08, 0xbf, 0x09, 0x66, 0xde, 0xee, 0x8c, 0xd1, + 0x57, 0xaf, 0x13, 0xf2, 0x51, 0x93, 0x0b, 0xa9, 0x39, 0x94, 0x71, 0xbc, + 0x05, 0xa7, 0xa0, 0xda, 0xfa, 0x65, 0x7d, 0x23, 0xa8, 0xb2, 0xa0, 0x89, + 0x86, 0x1f, 0xd2, 0x57, 0xd8, 0x1b, 0x22, 0x69, 0x8b, 0x48, 0x94, 0x5a, + 0x5b, 0xaf, 0x92, 0xd9, 0xb6, 0x77, 0xa1, 0x00, 0x31, 0x00 +}; // gkIPACCG2DevCertClass87 [] + +// Concatenated blob of 2 DER certificat +const uint8_t TestDoubleCerts [] = +{ + 0x30, 0x82, 0x01, 0xbe, 0x30, 0x82, 0x01, 0x27, 0x02, 0x01, 0x01, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, + 0x05, 0x00, 0x30, 0x25, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1a, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x54, + 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x20, + 0x28, 0x52, 0x53, 0x41, 0x29, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, + 0x32, 0x32, 0x30, 0x30, 0x30, 0x34, 0x36, 0x33, 0x36, 0x5a, 0x17, 0x0d, + 0x31, 0x34, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x34, 0x36, 0x33, 0x36, + 0x5a, 0x30, 0x2a, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x1f, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x54, 0x65, + 0x73, 0x74, 0x73, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x43, + 0x65, 0x72, 0x74, 0x20, 0x28, 0x52, 0x53, 0x41, 0x29, 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, 0xc8, 0x22, 0x8a, 0x23, 0x42, 0x66, 0x0d, 0x48, 0x64, 0x30, + 0xf2, 0xe9, 0xa2, 0x2f, 0xdf, 0x55, 0x5b, 0xb9, 0xb8, 0xe4, 0xe7, 0xb3, + 0xfb, 0x10, 0x63, 0x38, 0x7f, 0x57, 0x55, 0x6a, 0xe8, 0x08, 0xb9, 0x8b, + 0x70, 0x80, 0x15, 0x3b, 0x4e, 0xdb, 0x0c, 0xa3, 0xc5, 0x0b, 0xdf, 0x28, + 0xd3, 0x9a, 0x39, 0xb6, 0xca, 0x1d, 0x7b, 0x5f, 0x7b, 0x0c, 0x58, 0x87, + 0x3d, 0x81, 0xc7, 0xfd, 0x54, 0x3c, 0x0a, 0x60, 0xa2, 0x16, 0xf3, 0x35, + 0x29, 0x62, 0x40, 0xb2, 0x17, 0x09, 0x5a, 0x9a, 0x81, 0xa7, 0xb3, 0x4f, + 0x8d, 0x73, 0x3d, 0xe6, 0xbc, 0x53, 0x25, 0x2c, 0x43, 0x07, 0x4b, 0xda, + 0x0d, 0x73, 0x1b, 0x84, 0x32, 0x85, 0x9e, 0x60, 0xfe, 0xe0, 0xdb, 0x1c, + 0xf2, 0x4a, 0xed, 0x1b, 0xe9, 0xbc, 0xbc, 0xdd, 0x38, 0xe9, 0x62, 0x16, + 0xcb, 0x74, 0x2a, 0xa8, 0xe8, 0xbb, 0x74, 0x19, 0x56, 0xfd, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x4a, 0xde, + 0xd1, 0x1d, 0xc6, 0xaf, 0xc4, 0xe0, 0x12, 0x0b, 0xb8, 0xd7, 0xc8, 0xaf, + 0xe9, 0x90, 0x6f, 0x53, 0x15, 0xaa, 0xd1, 0xd5, 0x54, 0x4f, 0x62, 0xb8, + 0xc7, 0xfc, 0x68, 0x97, 0x3c, 0xdb, 0xca, 0x75, 0x4f, 0xb8, 0x52, 0xe7, + 0x77, 0xe2, 0x18, 0x78, 0x11, 0x74, 0xd7, 0x2e, 0xf5, 0xc6, 0xc8, 0x00, + 0x1d, 0xa1, 0x9c, 0xdd, 0xc7, 0x01, 0xb1, 0x34, 0x7a, 0x48, 0x8a, 0x2c, + 0x34, 0x7e, 0x43, 0x56, 0x50, 0xc2, 0xf1, 0x7c, 0x02, 0x5e, 0xd7, 0x16, + 0xae, 0xea, 0x31, 0x70, 0x54, 0xd9, 0xad, 0x15, 0xcd, 0xc7, 0x07, 0x99, + 0x30, 0x0a, 0xff, 0xdb, 0x7a, 0x72, 0xf6, 0x89, 0x51, 0x01, 0x81, 0x3b, + 0x97, 0x46, 0x99, 0x8a, 0x52, 0x42, 0xaf, 0x63, 0xa2, 0x1d, 0xc0, 0xae, + 0x09, 0xa6, 0x6c, 0x7c, 0x7f, 0x93, 0xc7, 0xd0, 0x18, 0x97, 0x6b, 0x59, + 0xa9, 0x23, 0x84, 0x65, 0xf9, 0xfd, 0x30, 0x82, 0x01, 0xbf, 0x30, 0x82, + 0x01, 0x28, 0x02, 0x02, 0x03, 0xe9, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x25, 0x31, + 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1a, 0x53, 0x65, + 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x20, 0x28, 0x52, 0x53, 0x41, 0x29, + 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x32, 0x32, 0x31, 0x31, 0x37, + 0x34, 0x38, 0x32, 0x39, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x33, 0x32, + 0x33, 0x31, 0x37, 0x34, 0x38, 0x32, 0x39, 0x5a, 0x30, 0x2a, 0x31, 0x28, + 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1f, 0x53, 0x65, 0x63, + 0x75, 0x72, 0x69, 0x74, 0x79, 0x54, 0x65, 0x73, 0x74, 0x73, 0x20, 0x43, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x20, 0x28, + 0x52, 0x53, 0x41, 0x29, 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, 0xd0, 0x4a, 0x1a, + 0x4d, 0xd7, 0x53, 0x22, 0xcf, 0xd3, 0xf3, 0x40, 0x9e, 0x14, 0xb5, 0x60, + 0xca, 0xcf, 0x2b, 0xd6, 0x48, 0x82, 0x6c, 0x15, 0x8f, 0xd8, 0xfb, 0xd1, + 0x38, 0x9a, 0x80, 0x3a, 0xcf, 0x03, 0xc6, 0xcd, 0x30, 0xc3, 0xe2, 0xa6, + 0x95, 0x23, 0x4f, 0xba, 0x1a, 0x6d, 0x78, 0x25, 0xd5, 0x63, 0x21, 0xe3, + 0x0f, 0x82, 0xfc, 0xcd, 0x84, 0xb0, 0xf5, 0xd2, 0xa6, 0x8c, 0x61, 0x26, + 0x7c, 0x50, 0x1a, 0x8b, 0xb0, 0x2c, 0x14, 0xaf, 0xf9, 0xb1, 0xb8, 0x96, + 0x72, 0x37, 0x67, 0x50, 0x57, 0x5b, 0x9f, 0xa2, 0x68, 0x04, 0x9b, 0x53, + 0x42, 0x1f, 0x24, 0xc3, 0x5d, 0x57, 0x66, 0x48, 0x2b, 0xe7, 0xd5, 0xf4, + 0x33, 0x84, 0xb3, 0x4a, 0x71, 0x6d, 0x69, 0xc1, 0xc4, 0x97, 0x22, 0x20, + 0xf6, 0x4e, 0x83, 0xda, 0x69, 0x6e, 0x07, 0x3c, 0x8b, 0xa3, 0xe4, 0x38, + 0x89, 0x64, 0x41, 0x25, 0x49, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, + 0x00, 0x03, 0x81, 0x81, 0x00, 0x9c, 0x2d, 0xe5, 0x32, 0x6b, 0x41, 0xaf, + 0x37, 0x30, 0x61, 0xd8, 0xf5, 0x0e, 0x7b, 0x3b, 0x57, 0x42, 0x08, 0x5c, + 0x28, 0x42, 0x7c, 0x1f, 0x40, 0xe9, 0xfc, 0xd4, 0x4b, 0x5c, 0x56, 0x83, + 0xb2, 0x85, 0x67, 0x11, 0x6c, 0x7a, 0x16, 0x16, 0x3f, 0xd6, 0xe0, 0xe9, + 0x89, 0xa5, 0xd9, 0xdc, 0x91, 0x34, 0xb9, 0x83, 0x71, 0xee, 0x69, 0xe1, + 0x7b, 0x4a, 0x4f, 0x1c, 0x1e, 0x7f, 0x74, 0x7c, 0xb6, 0x1c, 0xf3, 0xca, + 0xf8, 0xe7, 0x67, 0xbc, 0x73, 0xfc, 0xfa, 0x5e, 0x98, 0x52, 0xe3, 0x43, + 0x77, 0x32, 0xad, 0xcf, 0x81, 0x6f, 0xf4, 0xba, 0x61, 0x37, 0xff, 0xa7, + 0xf3, 0xfe, 0xf6, 0x67, 0x44, 0x41, 0x2e, 0x56, 0x91, 0x25, 0x8c, 0xc3, + 0xea, 0x9c, 0x85, 0xc9, 0x32, 0xde, 0xa9, 0x62, 0xcb, 0x3c, 0xb7, 0xbd, + 0x8d, 0x16, 0xec, 0xcf, 0x52, 0x17, 0xc8, 0x47, 0x99, 0x94, 0xe1, 0x4c, + 0x39 +}; // Test with 2certs [] + + +/* Basic processing of input */ +static void tests(void) +{ + CFArrayRef certs = NULL; + CFDataRef message; + + // Premade message containing one certificate blob + message = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, + certsOnlyMsg, sizeof(certsOnlyMsg), kCFAllocatorNull); + ok(certs = SecCMSCertificatesOnlyMessageCopyCertificates(message), + "SecCMSCertificatesOnlyMessageCopyCertificates"); + is(CFArrayGetCount(certs), 1, "certificate count is 1"); + CFReleaseNull(message); + + // Premade message containing one certificate blob + message = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, + gkIPACCG2DevCertClass87, sizeof(gkIPACCG2DevCertClass87), kCFAllocatorNull); + ok(certs = SecCMSCertificatesOnlyMessageCopyCertificates(message), + "SecCMSCertificatesOnlyMessageCopyCertificates"); + is(CFArrayGetCount(certs), 1, "certificate count is 1"); + CFReleaseNull(message); + + + SecCertificateRef another_cert = NULL; + + // Process a single raw certificate and make it a message + isnt(another_cert = SecCertificateCreateWithBytes(NULL, _c1, sizeof(_c1)), + NULL, "create certificate"); + ok(message = SecCMSCreateCertificatesOnlyMessageIAP(another_cert), "create iAP specific cert only message (1cert)"); + ok(certs = SecCMSCertificatesOnlyMessageCopyCertificates(message), + "SecCMSCertificatesOnlyMessageCopyCertificates"); + is(CFArrayGetCount(certs), 1, "certificate count is 1"); + + // Process two raw certificates (concatenated DER blobs) and make it a message + isnt(another_cert = SecCertificateCreateWithBytes(NULL, TestDoubleCerts, sizeof(TestDoubleCerts)), + NULL, "create certificate"); + ok(message = SecCMSCreateCertificatesOnlyMessageIAP(another_cert), "create iAP specific cert only message (2certs)"); + ok(certs = SecCMSCertificatesOnlyMessageCopyCertificates(message), + "SecCMSCertificatesOnlyMessageCopyCertificates"); + is(CFArrayGetCount(certs), 2, "certificate count is 2"); + + // Clean up + CFReleaseNull(another_cert); + CFReleaseNull(message); + + CFReleaseNull(certs); +} + + +int smime_cms_test(int argc, char *const *argv) +{ + plan_tests(12); + + tests(); + + return 0; +} diff --git a/Security/libsecurity_smime/regressions/smime_regressions.h b/Security/libsecurity_smime/regressions/smime_regressions.h new file mode 100644 index 00000000..2d4d93c6 --- /dev/null +++ b/Security/libsecurity_smime/regressions/smime_regressions.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + + +#include + +ONE_TEST(smime_cms_test) + diff --git a/libsecurity_ssl/Info-security_ssl.plist b/Security/libsecurity_ssl/Info-security_ssl.plist similarity index 100% rename from libsecurity_ssl/Info-security_ssl.plist rename to Security/libsecurity_ssl/Info-security_ssl.plist diff --git a/libsecurity_ssl/README b/Security/libsecurity_ssl/README similarity index 100% rename from libsecurity_ssl/README rename to Security/libsecurity_ssl/README diff --git a/libsecurity_ssl/Security b/Security/libsecurity_ssl/Security similarity index 100% rename from libsecurity_ssl/Security rename to Security/libsecurity_ssl/Security diff --git a/Security/libsecurity_ssl/config/base.xcconfig b/Security/libsecurity_ssl/config/base.xcconfig new file mode 100644 index 00000000..b6aaf1bc --- /dev/null +++ b/Security/libsecurity_ssl/config/base.xcconfig @@ -0,0 +1,16 @@ +CODE_SIGN_IDENTITY = -; +GCC_VERSION = com.apple.compilers.llvm.clang.1_0 +DEBUG_INFORMATION_FORMAT = dwarf-with-dsym +CURRENT_PROJECT_VERSION = $(RC_ProjectSourceVersion) +VERSIONING_SYSTEM = apple-generic; +DEAD_CODE_STRIPPING = YES; + +ARCHS = $(ARCHS_STANDARD_32_64_BIT) + +// Debug symbols should be on obviously +GCC_GENERATE_DEBUGGING_SYMBOLS = YES +COPY_PHASE_STRIP = NO +STRIP_STYLE = debugging +STRIP_INSTALLED_PRODUCT = NO + +WARNING_CFLAGS = -Wglobal-constructors -Wno-deprecated-declarations $(inherited) diff --git a/libsecurity_ssl/config/debug.xcconfig b/Security/libsecurity_ssl/config/debug.xcconfig similarity index 100% rename from libsecurity_ssl/config/debug.xcconfig rename to Security/libsecurity_ssl/config/debug.xcconfig diff --git a/libsecurity_ssl/config/kext.xcconfig b/Security/libsecurity_ssl/config/kext.xcconfig similarity index 100% rename from libsecurity_ssl/config/kext.xcconfig rename to Security/libsecurity_ssl/config/kext.xcconfig diff --git a/Security/libsecurity_ssl/config/lib.xcconfig b/Security/libsecurity_ssl/config/lib.xcconfig new file mode 100644 index 00000000..700aa696 --- /dev/null +++ b/Security/libsecurity_ssl/config/lib.xcconfig @@ -0,0 +1,30 @@ +#include "base.xcconfig" + +PRODUCT_NAME = $(TARGET_NAME) +EXECUTABLE_PREFIX = + +CODE_SIGN_IDENTITY = + +HEADER_SEARCH_PATHS[sdk=macosx*] = $(PROJECT_DIR) $(PROJECT_DIR)/../regressions $(PROJECT_DIR)/../include $(BUILT_PRODUCTS_DIR)/derived_src $(PROJECT_DIR)/../utilities $(PROJECT_DIR)/../libsecurity_keychain/ $(PROJECT_DIR)/../libsecurity_keychain/libDER $(BUILT_PRODUCTS_DIR) $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers $(inherited) + +HEADER_SEARCH_PATHS[sdk=iphone*] = $(PROJECT_DIR) $(PROJECT_DIR)/../regressions $(PROJECT_DIR)/../utilities $(PROJECT_DIR)/../libsecurity_asn1 $(PROJECT_DIR)/../libsecurity_keychain/libDER $(PROJECT_DIR)/../sec $(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include $(inherited) + +SKIP_INSTALL = YES + +ALWAYS_SEARCH_USER_PATHS = YES + +GCC_C_LANGUAGE_STANDARD = gnu99 + +WARNING_CFLAGS = $(inherited) -Wno-error=#warnings -Wall -Wno-four-char-constants -Wno-unknown-pragmas + +GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO + +GCC_SYMBOLS_PRIVATE_EXTERN = NO +GCC_WARN_64_TO_32_BIT_CONVERSION = YES +GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES +GCC_WARN_ABOUT_RETURN_TYPE = YES +GCC_WARN_UNUSED_VARIABLE = YES + +SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator + +GCC_PREPROCESSOR_DEFINITIONS[sdk=iphonesimulator*] = INDIGO=1 $(inherited) diff --git a/libsecurity_ssl/config/release.xcconfig b/Security/libsecurity_ssl/config/release.xcconfig similarity index 100% rename from libsecurity_ssl/config/release.xcconfig rename to Security/libsecurity_ssl/config/release.xcconfig diff --git a/Security/libsecurity_ssl/config/tests.xcconfig b/Security/libsecurity_ssl/config/tests.xcconfig new file mode 100644 index 00000000..21233a21 --- /dev/null +++ b/Security/libsecurity_ssl/config/tests.xcconfig @@ -0,0 +1,31 @@ +#include "base.xcconfig" + +PRODUCT_NAME = $(TARGET_NAME) +EXECUTABLE_PREFIX = + +CODE_SIGN_IDENTITY = + +GCC_C_LANGUAGE_STANDARD = gnu99 + +WARNING_CFLAGS = -Wmost -Wno-four-char-constants -Wno-unknown-pragmas $(inherited) + +GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO + +GCC_SYMBOLS_PRIVATE_EXTERN = NO +GCC_WARN_64_TO_32_BIT_CONVERSION = YES +GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES +GCC_WARN_ABOUT_RETURN_TYPE = YES +GCC_WARN_UNUSED_VARIABLE = YES + +SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator + +GCC_PREPROCESSOR_DEFINITIONS[sdk=iphonesimulator*] = INDIGO=1 $(inherited) + +#include "/AppleInternal/XcodeConfig/SimulatorSupport.xcconfig" + +// Set INSTALL_PATH_ACTUAL to whatever INSTALL_PATH would normally be +INSTALL_PATH_ACTUAL = /usr/local/bin + +// Set INSTALL_PATH[sdk=macosx*] when SimulatorSupport.xcconfig is unavailable +INSTALL_PATH[sdk=macosx*] = $(INSTALL_PATH_ACTUAL) + diff --git a/libsecurity_ssl/dtlsEcho/README b/Security/libsecurity_ssl/dtlsEcho/README similarity index 100% rename from libsecurity_ssl/dtlsEcho/README rename to Security/libsecurity_ssl/dtlsEcho/README diff --git a/libsecurity_ssl/dtlsEcho/dtlsEchoClient.c b/Security/libsecurity_ssl/dtlsEcho/dtlsEchoClient.c similarity index 86% rename from libsecurity_ssl/dtlsEcho/dtlsEchoClient.c rename to Security/libsecurity_ssl/dtlsEcho/dtlsEchoClient.c index f8f0bfc0..304df3b7 100644 --- a/libsecurity_ssl/dtlsEcho/dtlsEchoClient.c +++ b/Security/libsecurity_ssl/dtlsEcho/dtlsEchoClient.c @@ -1,12 +1,27 @@ /* - * dtlsEchoClient.c - * Security - * - * Created by Fabrice Gautier on 1/31/11. - * Copyright 2011 Apple, Inc. All rights reserved. + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include #include @@ -219,7 +234,7 @@ int main(int argc, char **argv) return ortn; } - ortn = SSLSetMaxDatagramRecordSize(ctx, 600); + ortn = SSLSetMaxDatagramRecordSize(ctx, 400); if(ortn) { printSslErrStr("SSLSetMaxDatagramRecordSize", ortn); return ortn; diff --git a/libsecurity_ssl/dtlsEcho/dtlsEchoServer.c b/Security/libsecurity_ssl/dtlsEcho/dtlsEchoServer.c similarity index 87% rename from libsecurity_ssl/dtlsEcho/dtlsEchoServer.c rename to Security/libsecurity_ssl/dtlsEcho/dtlsEchoServer.c index 5108f7e0..53aeb383 100644 --- a/libsecurity_ssl/dtlsEcho/dtlsEchoServer.c +++ b/Security/libsecurity_ssl/dtlsEcho/dtlsEchoServer.c @@ -1,12 +1,27 @@ /* - * dtlsEchoServer.c - * Security - * - * Created by Fabrice Gautier on 1/31/11. - * Copyright 2011 Apple, Inc. All rights reserved. + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include #include @@ -239,7 +254,7 @@ int main(int argc, char **argv) return ortn; } - ortn = SSLSetMaxDatagramRecordSize(ctx, 600); + ortn = SSLSetMaxDatagramRecordSize(ctx, 400); if(ortn) { printSslErrStr("SSLSetMaxDatagramRecordSize", ortn); return ortn; diff --git a/libsecurity_ssl/lib/CipherSuite.h b/Security/libsecurity_ssl/lib/CipherSuite.h similarity index 99% rename from libsecurity_ssl/lib/CipherSuite.h rename to Security/libsecurity_ssl/lib/CipherSuite.h index 8c578d61..6344d1ed 100644 --- a/libsecurity_ssl/lib/CipherSuite.h +++ b/Security/libsecurity_ssl/lib/CipherSuite.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2002,2005-2007,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2002,2005-2007,2010-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/ModuleAttacher.h b/Security/libsecurity_ssl/lib/ModuleAttacher.h similarity index 100% rename from libsecurity_ssl/lib/ModuleAttacher.h rename to Security/libsecurity_ssl/lib/ModuleAttacher.h diff --git a/Security/libsecurity_ssl/lib/SSLRecordInternal.c b/Security/libsecurity_ssl/lib/SSLRecordInternal.c new file mode 100644 index 00000000..42d0f931 --- /dev/null +++ b/Security/libsecurity_ssl/lib/SSLRecordInternal.c @@ -0,0 +1,418 @@ +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* THIS FILE CONTAINS KERNEL CODE */ + +#include "sslBuildFlags.h" +#include "SSLRecordInternal.h" +#include "sslDebug.h" +#include "cipherSpecs.h" +#include "symCipher.h" +#include "sslUtils.h" +#include "tls_record_internal.h" + +#include +#include + +#include +#include + +/* Maximum encrypted record size, defined in TLS 1.2 RFC, section 6.2.3 */ +#define DEFAULT_BUFFER_SIZE (16384 + 2048) + + +/* + * Redirect SSLBuffer-based I/O call to user-supplied I/O. + */ +static +int sslIoRead(SSLBuffer buf, + size_t *actualLength, + struct SSLRecordInternalContext *ctx) +{ + size_t dataLength = buf.length; + int ortn; + + *actualLength = 0; + ortn = (ctx->read)(ctx->ioRef, + buf.data, + &dataLength); + *actualLength = dataLength; + + sslLogRecordIo("sslIoRead: [%p] req %4lu actual %4lu status %d", + ctx, buf.length, dataLength, (int)ortn); + + return ortn; +} + +static +int sslIoWrite(SSLBuffer buf, + size_t *actualLength, + struct SSLRecordInternalContext *ctx) +{ + size_t dataLength = buf.length; + int ortn; + + *actualLength = 0; + ortn = (ctx->write)(ctx->ioRef, + buf.data, + &dataLength); + *actualLength = dataLength; + + sslLogRecordIo("sslIoWrite: [%p] req %4lu actual %4lu status %d", + ctx, buf.length, dataLength, (int)ortn); + + return ortn; +} + +/* Entry points to Record Layer */ + +static int SSLRecordReadInternal(SSLRecordContextRef ref, SSLRecord *rec) +{ + struct SSLRecordInternalContext *ctx = ref; + + int err; + size_t len, contentLen; + SSLBuffer readData; + + size_t head=tls_record_get_header_size(ctx->filter); + + if (ctx->amountRead < head) + { + readData.length = head - ctx->amountRead; + readData.data = ctx->partialReadBuffer.data + ctx->amountRead; + len = readData.length; + err = sslIoRead(readData, &len, ctx); + if(err != 0) + { + switch(err) { + case errSSLRecordWouldBlock: + ctx->amountRead += len; + break; + default: + /* Any other error but errSSLWouldBlock is translated to errSSLRecordClosedAbort */ + err = errSSLRecordClosedAbort; + break; + } + return err; + } + ctx->amountRead += len; + + check(ctx->amountRead == head); + } + + + tls_buffer header; + header.data=ctx->partialReadBuffer.data; + header.length=head; + + uint8_t content_type; + + tls_record_parse_header(ctx->filter, header, &contentLen, &content_type); + + if(content_type&0x80) { + // Looks like SSL2 record, reset expectations. + head = 2; + err=tls_record_parse_ssl2_header(ctx->filter, header, &contentLen, &content_type); + if(err!=0) return errSSLRecordUnexpectedRecord; + } + + check(ctx->partialReadBuffer.length>=head+contentLen); + + if(head+contentLen>ctx->partialReadBuffer.length) + return errSSLRecordRecordOverflow; + + if (ctx->amountRead < head + contentLen) + { readData.length = head + contentLen - ctx->amountRead; + readData.data = ctx->partialReadBuffer.data + ctx->amountRead; + len = readData.length; + err = sslIoRead(readData, &len, ctx); + if(err != 0) + { if (err == errSSLRecordWouldBlock) + ctx->amountRead += len; + return err; + } + ctx->amountRead += len; + } + + check(ctx->amountRead == head + contentLen); + + tls_buffer record; + record.data = ctx->partialReadBuffer.data; + record.length = ctx->amountRead; + + rec->contentType = content_type; + + ctx->amountRead = 0; /* We've used all the data in the cache */ + + if(content_type==tls_record_type_SSL2) { + /* Just copy the SSL2 record, dont decrypt since this is only for SSL2 Client Hello */ + return SSLCopyBuffer(&record, &rec->contents); + } else { + size_t sz = tls_record_decrypted_size(ctx->filter, record.length); + + /* There was an underflow - For TLS, we return errSSLRecordClosedAbort for historical reason - see ssl-44-crashes test */ + if(sz==0) { + sslErrorLog("underflow in SSLReadRecordInternal"); + if(ctx->dtls) { + // For DTLS, we should just drop it. + return errSSLRecordUnexpectedRecord; + } else { + // For TLS, we are going to close the connection. + return errSSLRecordClosedAbort; + } + } + + /* Allocate a buffer for the plaintext */ + if ((err = SSLAllocBuffer(&rec->contents, sz))) + { + return err; + } + + return tls_record_decrypt(ctx->filter, record, &rec->contents, NULL); + } +} + +static int SSLRecordWriteInternal(SSLRecordContextRef ref, SSLRecord rec) +{ + int err; + struct SSLRecordInternalContext *ctx = ref; + WaitingRecord *queue, *out; + tls_buffer data; + tls_buffer content; + size_t len; + + err = errSSLRecordInternal; /* FIXME: allocation error */ + len=tls_record_encrypted_size(ctx->filter, rec.contentType, rec.contents.length); + + require((out = (WaitingRecord *)sslMalloc(offsetof(WaitingRecord, data) + len)), fail); + out->next = NULL; + out->sent = 0; + out->length = len; + + data.data=&out->data[0]; + data.length=out->length; + + content.data = rec.contents.data; + content.length = rec.contents.length; + + require_noerr((err=tls_record_encrypt(ctx->filter, content, rec.contentType, &data)), fail); + + out->length = data.length; // This should not be needed if tls_record_encrypted_size works properly. + + /* Enqueue the record to be written from the idle loop */ + if (ctx->recordWriteQueue == 0) + ctx->recordWriteQueue = out; + else + { queue = ctx->recordWriteQueue; + while (queue->next != 0) + queue = queue->next; + queue->next = out; + } + + return 0; +fail: + if(out) + sslFree(out); + return err; +} + +/* Record Layer Entry Points */ + +static int +SSLRollbackInternalRecordLayerWriteCipher(SSLRecordContextRef ref) +{ + struct SSLRecordInternalContext *ctx = ref; + return tls_record_rollback_write_cipher(ctx->filter); +} + +static int +SSLAdvanceInternalRecordLayerWriteCipher(SSLRecordContextRef ref) +{ + struct SSLRecordInternalContext *ctx = ref; + return tls_record_advance_write_cipher(ctx->filter); +} + +static int +SSLAdvanceInternalRecordLayerReadCipher(SSLRecordContextRef ref) +{ + struct SSLRecordInternalContext *ctx = ref; + return tls_record_advance_read_cipher(ctx->filter); +} + +static int +SSLInitInternalRecordLayerPendingCiphers(SSLRecordContextRef ref, uint16_t selectedCipher, bool isServer, SSLBuffer key) +{ + struct SSLRecordInternalContext *ctx = ref; + return tls_record_init_pending_ciphers(ctx->filter, selectedCipher, isServer, key); +} + +static int +SSLSetInternalRecordLayerProtocolVersion(SSLRecordContextRef ref, SSLProtocolVersion negVersion) +{ + struct SSLRecordInternalContext *ctx = ref; + return tls_record_set_protocol_version(ctx->filter, negVersion); +} + +static int +SSLRecordFreeInternal(SSLRecordContextRef ref, SSLRecord rec) +{ + return SSLFreeBuffer(&rec.contents); +} + +static int +SSLRecordServiceWriteQueueInternal(SSLRecordContextRef ref) +{ + int err = 0, werr = 0; + size_t written = 0; + SSLBuffer buf; + WaitingRecord *rec; + struct SSLRecordInternalContext *ctx= ref; + + while (!werr && ((rec = ctx->recordWriteQueue) != 0)) + { buf.data = rec->data + rec->sent; + buf.length = rec->length - rec->sent; + werr = sslIoWrite(buf, &written, ctx); + rec->sent += written; + if (rec->sent >= rec->length) + { + check(rec->sent == rec->length); + check(err == 0); + ctx->recordWriteQueue = rec->next; + sslFree(rec); + } + if (err) { + check_noerr(err); + return err; + } + } + + return werr; +} + +static int +SSLRecordSetOption(SSLRecordContextRef ref, SSLRecordOption option, bool value) +{ + struct SSLRecordInternalContext *ctx = (struct SSLRecordInternalContext *)ref; + switch (option) { + case kSSLRecordOptionSendOneByteRecord: + return tls_record_set_record_splitting(ctx->filter, value); + break; + default: + return 0; + break; + } +} + +/***** Internal Record Layer APIs *****/ + +#include +#define CCRNGSTATE ccDRBGGetRngState() + +SSLRecordContextRef +SSLCreateInternalRecordLayer(bool dtls) +{ + struct SSLRecordInternalContext *ctx; + + ctx = sslMalloc(sizeof(struct SSLRecordInternalContext)); + if(ctx==NULL) + return NULL; + + memset(ctx, 0, sizeof(struct SSLRecordInternalContext)); + + ctx->dtls = dtls; + require((ctx->filter=tls_record_create(dtls, CCRNGSTATE)), fail); + require_noerr(SSLAllocBuffer(&ctx->partialReadBuffer, + DEFAULT_BUFFER_SIZE), fail); + + return ctx; + +fail: + if(ctx->filter) + tls_record_destroy(ctx->filter); + sslFree(ctx); + return NULL; +} + +int +SSLSetInternalRecordLayerIOFuncs( + SSLRecordContextRef ref, + SSLIOReadFunc readFunc, + SSLIOWriteFunc writeFunc) +{ + struct SSLRecordInternalContext *ctx = ref; + + ctx->read = readFunc; + ctx->write = writeFunc; + + return 0; +} + +int +SSLSetInternalRecordLayerConnection( + SSLRecordContextRef ref, + SSLIOConnectionRef ioRef) +{ + struct SSLRecordInternalContext *ctx = ref; + + ctx->ioRef = ioRef; + + return 0; +} + +void +SSLDestroyInternalRecordLayer(SSLRecordContextRef ref) +{ + struct SSLRecordInternalContext *ctx = ref; + WaitingRecord *waitRecord, *next; + + /* RecordContext cleanup : */ + SSLFreeBuffer(&ctx->partialReadBuffer); + waitRecord = ctx->recordWriteQueue; + while (waitRecord) + { next = waitRecord->next; + sslFree(waitRecord); + waitRecord = next; + } + + if(ctx->filter) + tls_record_destroy(ctx->filter); + + sslFree(ctx); + +} + +struct SSLRecordFuncs SSLRecordLayerInternal = +{ + .read = SSLRecordReadInternal, + .write = SSLRecordWriteInternal, + .initPendingCiphers = SSLInitInternalRecordLayerPendingCiphers, + .advanceWriteCipher = SSLAdvanceInternalRecordLayerWriteCipher, + .advanceReadCipher = SSLAdvanceInternalRecordLayerReadCipher, + .rollbackWriteCipher = SSLRollbackInternalRecordLayerWriteCipher, + .setProtocolVersion = SSLSetInternalRecordLayerProtocolVersion, + .free = SSLRecordFreeInternal, + .serviceWriteQueue = SSLRecordServiceWriteQueueInternal, + .setOption = SSLRecordSetOption, +}; + diff --git a/Security/libsecurity_ssl/lib/SSLRecordInternal.h b/Security/libsecurity_ssl/lib/SSLRecordInternal.h new file mode 100644 index 00000000..d5615fec --- /dev/null +++ b/Security/libsecurity_ssl/lib/SSLRecordInternal.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 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@ + */ + + + +/* This header should be kernel compatible */ + +#ifndef _SSLRECORDINTERNAL_H_ +#define _SSLRECORDINTERNAL_H_ 1 + +#include +#include +#include + +#include "sslTypes.h" + +typedef void * SSLIOConnectionRef; + +typedef int +(*SSLIOReadFunc) (SSLIOConnectionRef connection, + void *data, /* owned by + * caller, data + * RETURNED */ + size_t *dataLength); /* IN/OUT */ +typedef int +(*SSLIOWriteFunc) (SSLIOConnectionRef connection, + const void *data, + size_t *dataLength); /* IN/OUT */ + + +/* Record layer creation functions, called from the SSLContext layer */ + +SSLRecordContextRef +SSLCreateInternalRecordLayer(bool dtls); + +int +SSLSetInternalRecordLayerIOFuncs( + SSLRecordContextRef ctx, + SSLIOReadFunc readFunc, + SSLIOWriteFunc writeFunc); + +int +SSLSetInternalRecordLayerConnection( + SSLRecordContextRef ctx, + SSLIOConnectionRef ioRef); + +void +SSLDestroyInternalRecordLayer(SSLRecordContextRef ctx); + + +extern struct SSLRecordFuncs SSLRecordLayerInternal; + +#endif diff --git a/libsecurity_ssl/lib/SecureTransport.h b/Security/libsecurity_ssl/lib/SecureTransport.h similarity index 99% rename from libsecurity_ssl/lib/SecureTransport.h rename to Security/libsecurity_ssl/lib/SecureTransport.h index e0a5cf48..d592227d 100644 --- a/libsecurity_ssl/lib/SecureTransport.h +++ b/Security/libsecurity_ssl/lib/SecureTransport.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2002,2005-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2002,2005-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -131,10 +131,10 @@ typedef enum { */ kSSLSessionOptionSendOneByteRecord, /* - * Allow/Disallow server identity change on renegotiation. Disallow by default - * to avoid Triple Handshake attack. + * Enable fallback countermeasures. Use this option when retyring a SSL connection + * with a lower protocol version because of failure to connect. */ - kSSLSessionOptionAllowServerIdentityChange, + kSSLSessionOptionFallback = 6, } SSLSessionOption; @@ -198,7 +198,6 @@ typedef OSStatus const void *data, size_t *dataLength); /* IN/OUT */ - /************************************************* *** OSStatus values unique to SecureTransport *** *************************************************/ diff --git a/libsecurity_ssl/lib/SecureTransportPriv.h b/Security/libsecurity_ssl/lib/SecureTransportPriv.h similarity index 93% rename from libsecurity_ssl/lib/SecureTransportPriv.h rename to Security/libsecurity_ssl/lib/SecureTransportPriv.h index 01035afc..76565d49 100644 --- a/libsecurity_ssl/lib/SecureTransportPriv.h +++ b/Security/libsecurity_ssl/lib/SecureTransportPriv.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -35,7 +35,7 @@ extern "C" { #endif -#include "sslTypes.h" +#include /* Create an SSL Context with an external record layer - eg: kernel accelerated layer */ SSLContextRef @@ -394,6 +394,7 @@ extern OSStatus SSLGetNegotiatedClientAuthType( SSLContextRef ctx, SSLClientAuthenticationType *authType); /* RETURNED */ + /* * Obtain the number of supported_signature_algorithms specified by * the server in its Certificate Request message. @@ -750,6 +751,54 @@ SSLNewDatagramContext (Boolean isServer, +/* + * NPN support. + * + * If used, must be by client and server before SSLHandshake() + * + * Client: if set the client will announce NPN extension in the + * ClientHello, and the a callback will provide the server list, at + * that time the client needs to call SSLSetNPNData() in the callback + * to provide to the server the support mechanism. + * + * Server: the callback will tell the server that the client supports + * NPN and at that time, the server needs to set the supported NPN + * types with SSLSetNPNData(). + */ +typedef void +(*SSLNPNFunc) (SSLContextRef ctx, + void *info, /* info pointer provided by SSLSetNPNFunc */ + const void *npnData, + size_t npnDataLength); + + +void +SSLSetNPNFunc (SSLContextRef context, + SSLNPNFunc npnFunc, + void *info) + __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); + +/* + * For servers, this is the data that is announced. + * For clients, this is the picked data in the npnFunc callback. + * + * Return an error on out of memory and if buffer it too large + */ +OSStatus +SSLSetNPNData (SSLContextRef context, + const void *data, + size_t length) + __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); + +/* + * For servers, return client provided npn data if sent + */ +const void * +SSLGetNPNData (SSLContextRef context, + size_t *length) + __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); + + #ifdef __cplusplus } #endif diff --git a/libsecurity_ssl/lib/appleCdsa.h b/Security/libsecurity_ssl/lib/appleCdsa.h similarity index 98% rename from libsecurity_ssl/lib/appleCdsa.h rename to Security/libsecurity_ssl/lib/appleCdsa.h index 587a2bbc..d8d1a222 100644 --- a/libsecurity_ssl/lib/appleCdsa.h +++ b/Security/libsecurity_ssl/lib/appleCdsa.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2007,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/appleSession.c b/Security/libsecurity_ssl/lib/appleSession.c similarity index 98% rename from libsecurity_ssl/lib/appleSession.c rename to Security/libsecurity_ssl/lib/appleSession.c index 4ef22b4f..941a473b 100644 --- a/libsecurity_ssl/lib/appleSession.c +++ b/Security/libsecurity_ssl/lib/appleSession.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2008,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2008,2010-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -312,8 +312,8 @@ static OSStatus SessionCacheLookupEntry( return errSSLSessionNotFound; } - /* alloc/copy sessionData from existing entry (caller must free) */ - return SSLCopyBuffer(&entry->mSessionData, sessionData); + /* alloc/copy sessionData from existing entry (caller must free) */ + return SSLCopyBuffer(&entry->mSessionData, sessionData); } static OSStatus SessionCacheDeleteEntry( @@ -405,7 +405,7 @@ OSStatus sslAddSession ( /* * Given an opaque sessionKey, alloc & retrieve associated sessionData. */ -OSStatus sslGetSession ( +OSStatus sslCopySession ( const SSLBuffer sessionKey, SSLBuffer *sessionData) { diff --git a/libsecurity_ssl/lib/appleSession.h b/Security/libsecurity_ssl/lib/appleSession.h similarity index 91% rename from libsecurity_ssl/lib/appleSession.h rename to Security/libsecurity_ssl/lib/appleSession.h index 37e05b19..fd87cd62 100644 --- a/libsecurity_ssl/lib/appleSession.h +++ b/Security/libsecurity_ssl/lib/appleSession.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2007,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -39,7 +39,7 @@ extern OSStatus sslAddSession ( const SSLBuffer sessionData, uint32_t timeToLive); /* optional time-to-live in seconds; 0 ==> default */ -extern OSStatus sslGetSession ( +extern OSStatus sslCopySession ( const SSLBuffer sessionKey, SSLBuffer *sessionData); diff --git a/libsecurity_ssl/lib/cipherSpecs.c b/Security/libsecurity_ssl/lib/cipherSpecs.c similarity index 99% rename from libsecurity_ssl/lib/cipherSpecs.c rename to Security/libsecurity_ssl/lib/cipherSpecs.c index 0daa945b..0a86b1be 100644 --- a/libsecurity_ssl/lib/cipherSpecs.c +++ b/Security/libsecurity_ssl/lib/cipherSpecs.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/cipherSpecs.h b/Security/libsecurity_ssl/lib/cipherSpecs.h similarity index 97% rename from libsecurity_ssl/lib/cipherSpecs.h rename to Security/libsecurity_ssl/lib/cipherSpecs.h index 4e51a81e..83ee5c8b 100644 --- a/libsecurity_ssl/lib/cipherSpecs.h +++ b/Security/libsecurity_ssl/lib/cipherSpecs.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2007,2010-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/cryptType.h b/Security/libsecurity_ssl/lib/cryptType.h similarity index 95% rename from libsecurity_ssl/lib/cryptType.h rename to Security/libsecurity_ssl/lib/cryptType.h index 5424a69a..0f70942a 100644 --- a/libsecurity_ssl/lib/cryptType.h +++ b/Security/libsecurity_ssl/lib/cryptType.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2008,2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2008,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/Security/libsecurity_ssl/lib/secCrypto.c b/Security/libsecurity_ssl/lib/secCrypto.c new file mode 100644 index 00000000..1b636e9e --- /dev/null +++ b/Security/libsecurity_ssl/lib/secCrypto.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + */ + +/* + * secCrypto.c - interface between SSL and SecKey/SecDH interfaces. + */ + +#include "secCrypto.h" + +#include +#include +#include + +/* Private Key operations */ +static +SecAsn1Oid oidForSSLHash(SSL_HashAlgorithm hash) +{ + switch (hash) { + case SSL_HashAlgorithmSHA1: + return CSSMOID_SHA1WithRSA; + case SSL_HashAlgorithmSHA256: + return CSSMOID_SHA256WithRSA; + case SSL_HashAlgorithmSHA384: + return CSSMOID_SHA384WithRSA; + default: + break; + } + // Internal error + assert(0); + // This guarantee failure down the line + return CSSMOID_MD5WithRSA; +} + +static +int mySSLPrivKeyRSA_sign(void *key, SSL_HashAlgorithm hash, const uint8_t *plaintext, size_t plaintextLen, uint8_t *sig, size_t *sigLen) +{ + SecKeyRef keyRef = key; + + if(hash == SSL_HashAlgorithmNone) { + return SecKeyRawSign(keyRef, kSecPaddingPKCS1, plaintext, plaintextLen, sig, sigLen); + } else { + SecAsn1AlgId algId; + algId.algorithm = oidForSSLHash(hash); + return SecKeySignDigest(keyRef, &algId, plaintext, plaintextLen, sig, sigLen); + } +} + +static +int mySSLPrivKeyRSA_decrypt(void *key, const uint8_t *ciphertext, size_t ciphertextLen, uint8_t *plaintext, size_t *plaintextLen) +{ + SecKeyRef keyRef = key; + + return SecKeyDecrypt(keyRef, kSecPaddingPKCS1, ciphertext, ciphertextLen, plaintext, plaintextLen); +} + + + diff --git a/libsecurity_ssl/lib/securetransport++.cpp b/Security/libsecurity_ssl/lib/securetransport++.cpp similarity index 99% rename from libsecurity_ssl/lib/securetransport++.cpp rename to Security/libsecurity_ssl/lib/securetransport++.cpp index 4f18d590..f8bc197f 100644 --- a/libsecurity_ssl/lib/securetransport++.cpp +++ b/Security/libsecurity_ssl/lib/securetransport++.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2005-2007,2010-2013 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_ssl/lib/securetransport++.h b/Security/libsecurity_ssl/lib/securetransport++.h similarity index 100% rename from libsecurity_ssl/lib/securetransport++.h rename to Security/libsecurity_ssl/lib/securetransport++.h diff --git a/libsecurity_ssl/lib/security_ssl.exp b/Security/libsecurity_ssl/lib/security_ssl.exp similarity index 99% rename from libsecurity_ssl/lib/security_ssl.exp rename to Security/libsecurity_ssl/lib/security_ssl.exp index c434036a..59efa128 100644 --- a/libsecurity_ssl/lib/security_ssl.exp +++ b/Security/libsecurity_ssl/lib/security_ssl.exp @@ -88,3 +88,4 @@ _SSLSetECDSACurves _SSLGetNumberOfClientAuthTypes _SSLGetClientAuthTypes _SSLGetNegotiatedClientAuthType + diff --git a/libsecurity_ssl/lib/ssl.h b/Security/libsecurity_ssl/lib/ssl.h similarity index 93% rename from libsecurity_ssl/lib/ssl.h rename to Security/libsecurity_ssl/lib/ssl.h index c9987a3e..782269cf 100644 --- a/libsecurity_ssl/lib/ssl.h +++ b/Security/libsecurity_ssl/lib/ssl.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2007,2010-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/sslAlertMessage.h b/Security/libsecurity_ssl/lib/sslAlertMessage.h similarity index 96% rename from libsecurity_ssl/lib/sslAlertMessage.h rename to Security/libsecurity_ssl/lib/sslAlertMessage.h index 7b50b0eb..c8fdf219 100644 --- a/libsecurity_ssl/lib/sslAlertMessage.h +++ b/Security/libsecurity_ssl/lib/sslAlertMessage.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2000-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2005-2007,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/sslBER.c b/Security/libsecurity_ssl/lib/sslBER.c similarity index 99% rename from libsecurity_ssl/lib/sslBER.c rename to Security/libsecurity_ssl/lib/sslBER.c index 63fc1616..df9b39fc 100644 --- a/libsecurity_ssl/lib/sslBER.c +++ b/Security/libsecurity_ssl/lib/sslBER.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2007,2010-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/sslBER.h b/Security/libsecurity_ssl/lib/sslBER.h similarity index 96% rename from libsecurity_ssl/lib/sslBER.h rename to Security/libsecurity_ssl/lib/sslBER.h index 01ed025a..355b5804 100644 --- a/libsecurity_ssl/lib/sslBER.h +++ b/Security/libsecurity_ssl/lib/sslBER.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2007,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/sslBuildFlags.h b/Security/libsecurity_ssl/lib/sslBuildFlags.h similarity index 96% rename from libsecurity_ssl/lib/sslBuildFlags.h rename to Security/libsecurity_ssl/lib/sslBuildFlags.h index da857cd5..b17519b1 100644 --- a/libsecurity_ssl/lib/sslBuildFlags.h +++ b/Security/libsecurity_ssl/lib/sslBuildFlags.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2008,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2008,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/Security/libsecurity_ssl/lib/sslCipherSpecs.c b/Security/libsecurity_ssl/lib/sslCipherSpecs.c new file mode 100644 index 00000000..1d0627e9 --- /dev/null +++ b/Security/libsecurity_ssl/lib/sslCipherSpecs.c @@ -0,0 +1,529 @@ +/* + * Copyright (c) 1999-2001,2005-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@ + */ + +/* + * cipherSpecs.c - SSLCipherSpec declarations + */ + +#include "sslBuildFlags.h" +#include "sslContext.h" +#include "sslCipherSpecs.h" +#include "sslDebug.h" +#include "sslMemory.h" +#include "sslDebug.h" +#include "sslUtils.h" +#include "sslPriv.h" + +#include + +#include +#include +#include + +#include + + +/* SecureTransport needs it's own copy of KnownCipherSuites for now, there is a copy in coreTLS, + that is exported, but it actually should only included the "default" not the supported */ + +#define ENABLE_ECDH 1 +#define ENABLE_AES_GCM 0 +#define ENABLE_PSK 1 + +static const uint16_t STKnownCipherSuites[] = { +#if ENABLE_AES_GCM + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, +#endif + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, +#if ENABLE_AES_GCM + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, +#endif + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, +#if ENABLE_ECDH +#if ENABLE_AES_GCM + TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, + TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, +#endif + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, + TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, +#if ENABLE_AES_GCM + TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, +#endif + TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, + TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, + TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, + TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, + TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, +#endif + +#if ENABLE_AES_GCM + TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, +#endif // ENABLE_AES_GCM + TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + TLS_DHE_RSA_WITH_AES_128_CBC_SHA, + SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, + +#if ENABLE_AES_GCM + TLS_RSA_WITH_AES_256_GCM_SHA384, + TLS_RSA_WITH_AES_128_GCM_SHA256, +#endif + TLS_RSA_WITH_AES_256_CBC_SHA256, + TLS_RSA_WITH_AES_128_CBC_SHA256, + TLS_RSA_WITH_AES_256_CBC_SHA, + TLS_RSA_WITH_AES_128_CBC_SHA, + SSL_RSA_WITH_3DES_EDE_CBC_SHA, + +#if ENABLE_RC4 + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + TLS_ECDHE_RSA_WITH_RC4_128_SHA, + TLS_ECDH_ECDSA_WITH_RC4_128_SHA, + TLS_ECDH_RSA_WITH_RC4_128_SHA, + SSL_RSA_WITH_RC4_128_SHA, + SSL_RSA_WITH_RC4_128_MD5, +#endif + + + /* Unsafe ciphersuites */ + +#if ENABLE_AES_GCM + TLS_DH_anon_WITH_AES_256_GCM_SHA384, + TLS_DH_anon_WITH_AES_128_GCM_SHA256, +#endif + TLS_DH_anon_WITH_AES_128_CBC_SHA256, + TLS_DH_anon_WITH_AES_256_CBC_SHA256, + TLS_DH_anon_WITH_AES_128_CBC_SHA, + TLS_DH_anon_WITH_AES_256_CBC_SHA, + SSL_DH_anon_WITH_RC4_128_MD5, + SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, + + TLS_ECDHE_ECDSA_WITH_NULL_SHA, + TLS_ECDHE_RSA_WITH_NULL_SHA, +#if ENABLE_ECDH + TLS_ECDH_ECDSA_WITH_NULL_SHA, + TLS_ECDH_RSA_WITH_NULL_SHA, +#endif + +#if ENABLE_PSK + TLS_PSK_WITH_AES_256_CBC_SHA384, + TLS_PSK_WITH_AES_128_CBC_SHA256, + TLS_PSK_WITH_AES_256_CBC_SHA, + TLS_PSK_WITH_AES_128_CBC_SHA, + TLS_PSK_WITH_RC4_128_SHA, + TLS_PSK_WITH_3DES_EDE_CBC_SHA, + TLS_PSK_WITH_NULL_SHA384, + TLS_PSK_WITH_NULL_SHA256, + TLS_PSK_WITH_NULL_SHA, +#endif + + TLS_RSA_WITH_NULL_SHA256, + SSL_RSA_WITH_NULL_SHA, + SSL_RSA_WITH_NULL_MD5 + +}; + +static const unsigned STCipherSuiteCount = sizeof(STKnownCipherSuites)/sizeof(STKnownCipherSuites[0]); + + +/* + * Build ctx->validCipherSpecs as a copy of KnownCipherSpecs, assuming that + * validCipherSpecs is currently not valid (i.e., SSLSetEnabledCiphers() has + * not been called). + */ +OSStatus sslBuildCipherSuiteArray(SSLContext *ctx) +{ + size_t size; + unsigned dex; + + assert(ctx != NULL); + assert(ctx->validCipherSuites == NULL); + + ctx->numValidCipherSuites = STCipherSuiteCount; + size = STCipherSuiteCount * sizeof(uint16_t); + ctx->validCipherSuites = (uint16_t *)sslMalloc(size); + if(ctx->validCipherSuites == NULL) { + ctx->numValidCipherSuites = 0; + return errSecAllocate; + } + + /* + * Trim out inappropriate ciphers: + * -- trim anonymous ciphers if !ctx->anonCipherEnable + * -- trim ECDSA ciphers for server side if appropriate + * -- trim ECDSA ciphers if TLSv1 disable or SSLv2 enabled (since + * we MUST do the Client Hello extensions to make these ciphers + * work reliably) + * -- trim Stream ciphers if DTLSv1 enable + * -- trim CBC ciphers when doing SSLv3 fallback + */ + uint16_t *dst = ctx->validCipherSuites; + const uint16_t *src = STKnownCipherSuites; + + bool trimECDSA = false; + if((ctx->protocolSide==kSSLServerSide) && !SSL_ECDSA_SERVER) { + trimECDSA = true; + } + if(ctx->minProtocolVersion == SSL_Version_2_0 + || ctx->maxProtocolVersion == SSL_Version_3_0) { + /* We trim ECDSA cipher suites if SSL2 is enabled or + The maximum allowed protocol is SSL3. Note that this + won't trim ECDSA cipherspecs for DTLS which should be + the right thing to do here. */ + trimECDSA = true; + } + + /* trim Stream Ciphers for DTLS */ + bool trimRC4 = ctx->isDTLS; + + /* trim CBC cipher when doing SSLv3 only fallback */ + bool trimCBC = (ctx->protocolSide==kSSLClientSide) + && (ctx->maxProtocolVersion == SSL_Version_3_0) + && ctx->fallbackEnabled; + + bool trimDHE = (ctx->protocolSide==kSSLServerSide) && + !ctx->dhParamsEncoded.length; + + for(dex=0; dexnumValidCipherSuites--; + src++; + continue; + } + else { + break; + } + default: + break; + } + if(!ctx->anonCipherEnable) { + /* trim out the anonymous (and null-auth-cipher) ciphers */ + if(mac == HA_Null) { + /* skip this one */ + ctx->numValidCipherSuites--; + src++; + continue; + } + switch(kem) { + case SSL_DH_anon: + case SSL_DH_anon_EXPORT: + case SSL_ECDH_anon: + /* skip this one */ + ctx->numValidCipherSuites--; + src++; + continue; + default: + break; + } + } + if(ctx->falseStartEnabled) { + switch(kem){ + case SSL_ECDHE_ECDSA: + case SSL_ECDHE_RSA: + case SSL_DHE_RSA: + case SSL_DHE_DSS: + /* Ok for false start */ + break; + default: + /* Not ok, skip */ + ctx->numValidCipherSuites--; + src++; + continue; + } + switch(cipher) { + case SSL_CipherAlgorithmAES_128_CBC: + case SSL_CipherAlgorithmAES_128_GCM: + case SSL_CipherAlgorithmAES_256_CBC: + case SSL_CipherAlgorithmAES_256_GCM: + case SSL_CipherAlgorithmRC4_128: + /* Ok for false start */ + break; + default: + /* Not ok, skip*/ + ctx->numValidCipherSuites--; + src++; + continue; + } + } + + /* This will skip the simple DES cipher suites, but not the NULL cipher ones */ + if (keySize == 8) + { + /* skip this one */ + ctx->numValidCipherSuites--; + src++; + continue; + } + + /* Trim PSK ciphersuites, they need to be enabled explicitely */ + if (kem==TLS_PSK) { + ctx->numValidCipherSuites--; + src++; + continue; + } + + if (trimDHE) { + switch(kem) { + case SSL_DHE_DSS: + case SSL_DHE_DSS_EXPORT: + case SSL_DHE_RSA: + case SSL_DHE_RSA_EXPORT: + /* skip this one */ + ctx->numValidCipherSuites--; + src++; + continue; + default: + break; + } + } + + if (trimRC4 && (cipher==SSL_CipherAlgorithmRC4_128)) { + ctx->numValidCipherSuites--; + src++; + continue; + } + + if(trimCBC) { + switch (cipher) { + case SSL_CipherAlgorithmAES_128_CBC: + case SSL_CipherAlgorithmAES_256_CBC: + case SSL_CipherAlgorithm3DES_CBC: + ctx->numValidCipherSuites--; + src++; + continue; + default: + break; + } + } + + if(cipher==SSL_CipherAlgorithmNull) { + ctx->numValidCipherSuites--; + src++; + continue; + } + + /* This one is good to go */ + *dst++ = *src++; + } + + // sslAnalyzeCipherSpecs(ctx); + + tls_handshake_set_ciphersuites(ctx->hdsk, ctx->validCipherSuites, ctx->numValidCipherSuites); + + return errSecSuccess; +} + + +/* + * Convert an array of SSLCipherSuites (which is always KnownCipherSpecs) + * to an array of SSLCipherSuites. + */ +static OSStatus +cipherSuitesToCipherSuites( + size_t numCipherSuites, + const uint16_t *cipherSuites, + SSLCipherSuite *ciphers, /* RETURNED */ + size_t *numCiphers) /* IN/OUT */ +{ + size_t i; + if(*numCiphers < numCipherSuites) { + return errSSLBufferOverflow; + } + + /* NOTE: this is required to go from uint16_t to SSLCipherSuite + which is either 32 or 16 bits, depending on the platform */ + for(i=0;ivalidCipherSuites = (uint16_t *)sslMalloc(size); + if(ctx->validCipherSuites == NULL) { + ctx->numValidCipherSuites = 0; + return errSecAllocate; + } + + /* + * Run thru caller's specs, keep only the supported ones. + */ + for(callerDex=0; callerDexvalidCipherSuites[foundCiphers] = STKnownCipherSuites[tableDex]; + foundCiphers++; + break; + } + } + } + + if(foundCiphers==0) { + /* caller specified only unsupported ciphersuites */ + sslFree(ctx->validCipherSuites); + ctx->validCipherSuites = NULL; + return errSSLBadCipherSuite; + } + + /* success */ + ctx->numValidCipherSuites = foundCiphers; + + tls_handshake_set_ciphersuites(ctx->hdsk, ctx->validCipherSuites, ctx->numValidCipherSuites); + + return errSecSuccess; +} + +/* + * Determine number and values of all of the SSLCipherSuites currently enabled. + * Caller allocates output buffer for SSLGetEnabledCiphers() and passes in + * its size in *numCiphers. If supplied buffer is too small, errSSLBufferOverflow + * will be returned. + */ +OSStatus +SSLGetNumberEnabledCiphers (SSLContextRef ctx, + size_t *numCiphers) +{ + if((ctx == NULL) || (numCiphers == NULL)) { + return errSecParam; + } + if(ctx->validCipherSuites == NULL) { + /* hasn't been set; use default */ + *numCiphers = STCipherSuiteCount; + } + else { + /* caller set via SSLSetEnabledCiphers */ + *numCiphers = ctx->numValidCipherSuites; + } + return errSecSuccess; +} + +OSStatus +SSLGetEnabledCiphers (SSLContextRef ctx, + SSLCipherSuite *ciphers, /* RETURNED */ + size_t *numCiphers) /* IN/OUT */ +{ + if((ctx == NULL) || (ciphers == NULL) || (numCiphers == NULL)) { + return errSecParam; + } + if(ctx->validCipherSuites == NULL) { + /* hasn't been set; use default */ + return cipherSuitesToCipherSuites(STCipherSuiteCount, + STKnownCipherSuites, + ciphers, + numCiphers); + } + else { + /* use the ones specified in SSLSetEnabledCiphers() */ + return cipherSuitesToCipherSuites(ctx->numValidCipherSuites, + ctx->validCipherSuites, + ciphers, + numCiphers); + } +} diff --git a/libsecurity_ssl/lib/sslCipherSpecs.h b/Security/libsecurity_ssl/lib/sslCipherSpecs.h similarity index 94% rename from libsecurity_ssl/lib/sslCipherSpecs.h rename to Security/libsecurity_ssl/lib/sslCipherSpecs.h index 724d9d17..f25863a0 100644 --- a/libsecurity_ssl/lib/sslCipherSpecs.h +++ b/Security/libsecurity_ssl/lib/sslCipherSpecs.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2007,2010-2011 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2007,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/sslContext.c b/Security/libsecurity_ssl/lib/sslContext.c similarity index 81% rename from libsecurity_ssl/lib/sslContext.c rename to Security/libsecurity_ssl/lib/sslContext.c index cc74aa16..826fdaf2 100644 --- a/libsecurity_ssl/lib/sslContext.c +++ b/Security/libsecurity_ssl/lib/sslContext.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -40,6 +40,8 @@ #include "sslMemory.h" #include "sslUtils.h" +#include "tlsCallbacks.h" + #include #include #include @@ -49,6 +51,7 @@ #include #include #include "utilities/SecCFRelease.h" +#include "utilities/SecCFWrappers.h" #include #include @@ -69,7 +72,7 @@ static void sslFreeDnList( dn = ctx->acceptableDNList; while (dn) { - SSLFreeBuffer(&dn->derDN); + SSLFreeBuffer(&dn->derDN); nextDN = dn->next; sslFree(dn); dn = nextDN; @@ -81,16 +84,17 @@ static void sslFreeDnList( Boolean sslIsSessionActive(const SSLContext *ctx) { assert(ctx != NULL); + + switch(ctx->state) { case SSL_HdskStateUninit: - case SSL_HdskStateServerUninit: - case SSL_HdskStateClientUninit: case SSL_HdskStateGracefulClose: case SSL_HdskStateErrorClose: return false; default: return true; } + } /* @@ -113,22 +117,14 @@ Boolean sslIsSessionActive(const SSLContext *ctx) #define MIN_ALLOWED_DTLS_MTU 64 /* this ensure than there will be no integer underflow when calculating max write size */ -static CFTypeID kSSLContextTypeID; int kSplitDefaultValue; -bool kAllowServerIdentityChangeDefaultValue; - -static void _sslContextDestroy(CFTypeRef arg); -static Boolean _sslContextEqual(CFTypeRef a, CFTypeRef b); -static CFHashCode _sslContextHash(CFTypeRef arg); -static CFStringRef _sslContextDescribe(CFTypeRef arg); static void _SSLContextReadDefault() { /* 0 = disabled, 1 = split every write, 2 = split second and subsequent writes */ - /* Enabled by default, this make cause some interop issues, see and */ + /* Enabled by default, this may cause some interop issues, see and */ const int defaultSplitDefaultValue = 2; - //To change: - //sudo defaults write /Library/Preferences/com.apple.security SSLWriteSplit -int 0 + CFTypeRef value = (CFTypeRef)CFPreferencesCopyValue(CFSTR("SSLWriteSplit"), CFSTR("com.apple.security"), kCFPreferencesAnyUser, @@ -148,60 +144,9 @@ static void _SSLContextReadDefault() else { kSplitDefaultValue = defaultSplitDefaultValue; } - - - /* 0 = disallowed, 1 = allowed */ - /* Disallowed by default */ - const bool defaultValue = false; - //To change: - //sudo defaults write /Library/Preferences/com.apple.security SSLAllowServerIdentityChange -bool YES - value = (CFTypeRef)CFPreferencesCopyValue(CFSTR("SSLAllowServerIdentityChange"), - CFSTR("com.apple.security"), - kCFPreferencesAnyUser, - kCFPreferencesCurrentHost); - if (value) { - if (CFGetTypeID(value) == CFBooleanGetTypeID()) - kAllowServerIdentityChangeDefaultValue = CFBooleanGetValue((CFBooleanRef)value); - else if (CFGetTypeID(value) == CFNumberGetTypeID()) { - int localValue; - if (!CFNumberGetValue((CFNumberRef)value, kCFNumberIntType, &localValue)) { - kAllowServerIdentityChangeDefaultValue = defaultValue; - } else { - kAllowServerIdentityChangeDefaultValue = localValue; - } - } - CFRelease(value); - } - else { - kAllowServerIdentityChangeDefaultValue = defaultValue; - } -} - -static void _SSLContextRegisterClass() -{ - static const CFRuntimeClass kSSLContextRegisterClass = { - 0, /* version */ - "SSLContext", /* class name */ - NULL, /* init */ - NULL, /* copy */ - _sslContextDestroy, /* dealloc */ - _sslContextEqual, /* equal */ - _sslContextHash, /* hash */ - NULL, /* copyFormattingDesc */ - _sslContextDescribe /* copyDebugDesc */ - }; - - kSSLContextTypeID = _CFRuntimeRegisterClass(&kSSLContextRegisterClass); -} - -CFTypeID -SSLContextGetTypeID(void) -{ - static pthread_once_t sOnce = PTHREAD_ONCE_INIT; - pthread_once(&sOnce, _SSLContextRegisterClass); - return kSSLContextTypeID; } +CFGiblisWithHashFor(SSLContext) OSStatus SSLNewContext (Boolean isServer, @@ -222,18 +167,21 @@ SSLNewContext (Boolean isServer, SSLContextRef SSLCreateContext(CFAllocatorRef alloc, SSLProtocolSide protocolSide, SSLConnectionType connectionType) { SSLContextRef ctx; + SSLRecordContextRef recCtx; ctx = SSLCreateContextWithRecordFuncs(alloc, protocolSide, connectionType, &SSLRecordLayerInternal); - + if(ctx==NULL) return NULL; - - ctx->recCtx = SSLCreateInternalRecordLayer(connectionType); - if(ctx->recCtx==NULL) { + + recCtx = SSLCreateInternalRecordLayer(connectionType); + if(recCtx==NULL) { CFRelease(ctx); return NULL; } - + + SSLSetRecordContext(ctx, recCtx); + return ctx; } @@ -249,50 +197,33 @@ SSLContextRef SSLCreateContextWithRecordFuncs(CFAllocatorRef alloc, SSLProtocolS /* subsequent errors to errOut: */ memset(((uint8_t*) ctx) + sizeof(CFRuntimeBase), 0, sizeof(SSLContext) - sizeof(CFRuntimeBase)); - ctx->state = SSL_HdskStateUninit; - ctx->timeout_duration = DEFAULT_DTLS_TIMEOUT; - ctx->clientCertState = kSSLClientCertNone; - - ctx->minProtocolVersion = MINIMUM_STREAM_VERSION; - ctx->maxProtocolVersion = MAXIMUM_STREAM_VERSION; - - ctx->isDTLS = false; - ctx->dtlsCookie.data = NULL; - ctx->dtlsCookie.length = 0; - ctx->hdskMessageSeq = 0; - ctx->hdskMessageSeqNext = 0; - ctx->mtu = DEFAULT_DTLS_MTU; - - ctx->negProtocolVersion = SSL_Version_Undetermined; + ctx->hdsk = tls_handshake_create(connectionType==kSSLDatagramType, protocolSide==kSSLServerSide); - ctx->protocolSide = protocolSide; - /* Default value so we can send and receive hello msgs */ - ctx->sslTslCalls = &Ssl3Callouts; - ctx->recFuncs = recFuncs; + tls_handshake_set_callbacks(ctx->hdsk, + &tls_handshake_callbacks, + ctx); - /* Initialize the cipher state to NULL_WITH_NULL_NULL */ - ctx->selectedCipher = TLS_NULL_WITH_NULL_NULL; - InitCipherSpecParams(ctx); + ctx->isDTLS = (connectionType==kSSLDatagramType); - /* this gets init'd on first call to SSLHandshake() */ - ctx->validCipherSuites = NULL; - ctx->numValidCipherSuites = 0; -#if ENABLE_SSLV2 - ctx->numValidNonSSLv2Suites = 0; -#endif + ctx->state = SSL_HdskStateUninit; + ctx->timeout_duration = DEFAULT_DTLS_TIMEOUT; + ctx->mtu = DEFAULT_DTLS_MTU; - ctx->peerDomainName = NULL; - ctx->peerDomainNameLen = 0; + if(ctx->isDTLS) { + ctx->minProtocolVersion = MINIMUM_DATAGRAM_VERSION; + ctx->maxProtocolVersion = MAXIMUM_DATAGRAM_VERSION; + } else { + ctx->minProtocolVersion = MINIMUM_STREAM_VERSION; + ctx->maxProtocolVersion = MAXIMUM_STREAM_VERSION; + } + tls_handshake_set_min_protocol_version(ctx->hdsk, ctx->minProtocolVersion); + tls_handshake_set_max_protocol_version(ctx->hdsk, ctx->maxProtocolVersion); -#ifdef USE_CDSA_CRYPTO - /* attach to CSP, CL, TP */ - serr = attachToAll(ctx); - if(serr) { - goto errOut; - } -#endif /* USE_CDSA_CRYPTO */ + ctx->negProtocolVersion = SSL_Version_Undetermined; + ctx->protocolSide = protocolSide; + ctx->recFuncs = recFuncs; /* Initial cert verify state: verify with default system roots */ ctx->enableCertVerify = true; @@ -303,8 +234,8 @@ SSLContextRef SSLCreateContextWithRecordFuncs(CFAllocatorRef alloc, SSLProtocolS /* Default for sending one-byte app data record is DISABLED */ ctx->oneByteRecordEnable = false; - /* Default for allowing server identity change on renegotiation is FALSE */ - ctx->allowServerIdentityChange = false; + /* Dont enable fallback behavior by default */ + ctx->fallbackEnabled = false; /* Consult global system preference for default behavior: * 0 = disabled, 1 = split every write, 2 = split second and subsequent writes @@ -314,8 +245,6 @@ SSLContextRef SSLCreateContextWithRecordFuncs(CFAllocatorRef alloc, SSLProtocolS pthread_once(&sReadDefault, _SSLContextReadDefault); if (kSplitDefaultValue > 0) ctx->oneByteRecordEnable = true; - if (kAllowServerIdentityChangeDefaultValue>0) - ctx->allowServerIdentityChange = true; /* default for anonymous ciphers is DISABLED */ ctx->anonCipherEnable = false; @@ -327,27 +256,8 @@ SSLContextRef SSLCreateContextWithRecordFuncs(CFAllocatorRef alloc, SSLProtocolS ctx->signalCertRequest = false; ctx->signalClientAuth = false; - /* - * Initial/default set of ECDH curves - */ - ctx->ecdhNumCurves = SSL_ECDSA_NUM_CURVES; - ctx->ecdhCurves[0] = SSL_Curve_secp256r1; - ctx->ecdhCurves[1] = SSL_Curve_secp384r1; - ctx->ecdhCurves[2] = SSL_Curve_secp521r1; - - ctx->ecdhPeerCurve = SSL_Curve_None; /* until we negotiate one */ ctx->negAuthType = SSLClientAuthNone; /* ditto */ - ctx->messageWriteQueue = NULL; - - if(connectionType==kSSLDatagramType) { - ctx->minProtocolVersion = MINIMUM_DATAGRAM_VERSION; - ctx->maxProtocolVersion = MAXIMUM_DATAGRAM_VERSION; - ctx->isDTLS = true; - } - - ctx->secure_renegotiation = false; - if (serr != errSecSuccess) { CFRelease(ctx); ctx = NULL; @@ -382,7 +292,7 @@ SSLDisposeContext (SSLContextRef context) return errSecSuccess; } -CF_RETURNS_RETAINED CFStringRef _sslContextDescribe(CFTypeRef arg) +CFStringRef SSLContextCopyDescription(CFTypeRef arg) { SSLContext* ctx = (SSLContext*) arg; @@ -394,133 +304,53 @@ CF_RETURNS_RETAINED CFStringRef _sslContextDescribe(CFTypeRef arg) } } -Boolean _sslContextEqual(CFTypeRef a, CFTypeRef b) +Boolean SSLContextCompare(CFTypeRef a, CFTypeRef b) { return a == b; } -CFHashCode _sslContextHash(CFTypeRef arg) +CFHashCode SSLContextHash(CFTypeRef arg) { return (CFHashCode) arg; } -void _sslContextDestroy(CFTypeRef arg) +void SSLContextDestroy(CFTypeRef arg) { SSLContext* ctx = (SSLContext*) arg; -#if USE_SSLCERTIFICATE - sslDeleteCertificateChain(ctx->localCert, ctx); - sslDeleteCertificateChain(ctx->encryptCert, ctx); - sslDeleteCertificateChain(ctx->peerCert, ctx); - ctx->localCert = ctx->encryptCert = ctx->peerCert = NULL; -#else - CFReleaseNull(ctx->localCert); - CFReleaseNull(ctx->encryptCert); - CFReleaseNull(ctx->peerCert); - CFReleaseNull(ctx->trustedCerts); -#endif - - /* Free the last handshake message flight */ - SSLResetFlight(ctx); - - if(ctx->peerSecTrust) { - CFRelease(ctx->peerSecTrust); - ctx->peerSecTrust = NULL; - } - SSLFreeBuffer(&ctx->sessionTicket); - - #if APPLE_DH - SSLFreeBuffer(&ctx->dhParamsEncoded); -#ifdef USE_CDSA_CRYPTO - sslFreeKey(ctx->cspHand, &ctx->dhPrivate, NULL); -#else - if (ctx->secDHContext) - SecDHDestroy(ctx->secDHContext); -#endif /* !USE_CDSA_CRYPTO */ - SSLFreeBuffer(&ctx->dhPeerPublic); - SSLFreeBuffer(&ctx->dhExchangePublic); - #endif /* APPLE_DH */ - - SSLFreeBuffer(&ctx->ecdhPeerPublic); - SSLFreeBuffer(&ctx->ecdhExchangePublic); -#if USE_CDSA_CRYPTO - if(ctx->ecdhPrivCspHand == ctx->cspHand) { - sslFreeKey(ctx->ecdhPrivCspHand, &ctx->ecdhPrivate, NULL); - } - /* else we got this key from a SecKeyRef, no free needed */ -#endif + /* destroy the coreTLS handshake object */ + tls_handshake_destroy(ctx->hdsk); /* Only destroy if we were using the internal record layer */ if(ctx->recFuncs==&SSLRecordLayerInternal) SSLDestroyInternalRecordLayer(ctx->recCtx); - CloseHash(&SSLHashSHA1, &ctx->shaState); - CloseHash(&SSLHashMD5, &ctx->md5State); - CloseHash(&SSLHashSHA256, &ctx->sha256State); - CloseHash(&SSLHashSHA384, &ctx->sha512State); - + SSLFreeBuffer(&ctx->sessionTicket); SSLFreeBuffer(&ctx->sessionID); SSLFreeBuffer(&ctx->peerID); SSLFreeBuffer(&ctx->resumableSession); - SSLFreeBuffer(&ctx->preMasterSecret); - SSLFreeBuffer(&ctx->fragmentedMessageCache); SSLFreeBuffer(&ctx->receivedDataBuffer); - if(ctx->peerDomainName) { - sslFree(ctx->peerDomainName); - ctx->peerDomainName = NULL; - ctx->peerDomainNameLen = 0; - } - sslFree(ctx->validCipherSuites); ctx->validCipherSuites = NULL; ctx->numValidCipherSuites = 0; -#if USE_CDSA_CRYPTO - /* - * NOTE: currently, all public keys come from the CL via CSSM_CL_CertGetKeyInfo. - * We really don't know what CSP the CL used to generate a public key (in fact, - * it uses the raw CSP only to get LogicalKeySizeInBits, but we can't know - * that). Thus using e.g. signingKeyCsp (or any other CSP) to free - * signingPubKey is not tecnically accurate. However, our public keys - * are all raw keys, and all Apple CSPs dispose of raw keys in the same - * way. - */ - sslFreeKey(ctx->cspHand, &ctx->signingPubKey, NULL); - sslFreeKey(ctx->cspHand, &ctx->encryptPubKey, NULL); - sslFreeKey(ctx->peerPubKeyCsp, &ctx->peerPubKey, NULL); - - if(ctx->signingPrivKeyRef) { - CFRelease(ctx->signingPrivKeyRef); - } - if(ctx->encryptPrivKeyRef) { - CFRelease(ctx->encryptPrivKeyRef); - } - if(ctx->trustedCerts) { - CFRelease(ctx->trustedCerts); - } - detachFromAll(ctx); -#else - sslFreePubKey(&ctx->signingPubKey); - sslFreePubKey(&ctx->encryptPubKey); - sslFreePubKey(&ctx->peerPubKey); - sslFreePrivKey(&ctx->signingPrivKeyRef); - sslFreePrivKey(&ctx->encryptPrivKeyRef); -#endif /* USE_CDSA_CRYPTO */ CFReleaseSafe(ctx->acceptableCAs); CFReleaseSafe(ctx->trustedLeafCerts); - CFReleaseSafe(ctx->localCertArray); - CFReleaseSafe(ctx->encryptCertArray); + CFReleaseSafe(ctx->localCertArray); CFReleaseSafe(ctx->encryptCertArray); - if(ctx->clientAuthTypes) { - sslFree(ctx->clientAuthTypes); - } - if(ctx->serverSigAlgs != NULL) { - sslFree(ctx->serverSigAlgs); - } - if(ctx->clientSigAlgs != NULL) { - sslFree(ctx->clientSigAlgs); - } + CFReleaseSafe(ctx->encryptCertArray); + CFReleaseSafe(ctx->peerCert); + CFReleaseSafe(ctx->trustedCerts); + CFReleaseSafe(ctx->peerSecTrust); + + sslFreePrivKey(&ctx->signingPrivKeyRef); + sslFreePrivKey(&ctx->encryptPrivKeyRef); + + sslFree(ctx->localCert); + sslFree(ctx->encryptCert); + + sslFreeDnList(ctx); SSLFreeBuffer(&ctx->ownVerifyData); @@ -529,6 +359,8 @@ void _sslContextDestroy(CFTypeRef arg) SSLFreeBuffer(&ctx->pskIdentity); SSLFreeBuffer(&ctx->pskSharedSecret); + SSLFreeBuffer(&ctx->dhParamsEncoded); + memset(((uint8_t*) ctx) + sizeof(CFRuntimeBase), 0, sizeof(SSLContext) - sizeof(CFRuntimeBase)); sslCleanupSession(); @@ -549,8 +381,6 @@ SSLGetSessionState (SSLContextRef context, *state = rtnState; switch(context->state) { case SSL_HdskStateUninit: - case SSL_HdskStateServerUninit: - case SSL_HdskStateClientUninit: rtnState = kSSLIdle; break; case SSL_HdskStateGracefulClose: @@ -560,16 +390,12 @@ SSLGetSessionState (SSLContextRef context, case SSL_HdskStateNoNotifyClose: rtnState = kSSLAborted; break; - case SSL_HdskStateServerReady: - case SSL_HdskStateClientReady: + case SSL_HdskStateReady: rtnState = kSSLConnected; break; - default: - assert((context->state >= SSL_HdskStateServerHello) && - (context->state <= SSL_HdskStateFinished)); + case SSL_HdskStatePending: rtnState = kSSLHandshake; break; - } *state = rtnState; return errSecSuccess; @@ -603,15 +429,19 @@ SSLSetSessionOption (SSLContextRef context, context->enableCertVerify = !value; break; case kSSLSessionOptionSendOneByteRecord: + /* Only call the record layer function if the value changed */ + if(value != context->oneByteRecordEnable) + context->recFuncs->setOption(context->recCtx, kSSLRecordOptionSendOneByteRecord, value); context->oneByteRecordEnable = value; break; case kSSLSessionOptionFalseStart: context->falseStartEnabled = value; break; - case kSSLSessionOptionAllowServerIdentityChange: - context->allowServerIdentityChange = value; + case kSSLSessionOptionFallback: + tls_handshake_set_fallback(context->hdsk, value); + context->fallbackEnabled = value; break; - default: + default: return errSecParam; } @@ -710,8 +540,8 @@ static int IOWrite(SSLIOConnectionRef connection, } -OSStatus -SSLSetIOFuncs (SSLContextRef ctx, +OSStatus +SSLSetIOFuncs (SSLContextRef ctx, SSLReadFunc readFunc, SSLWriteFunc writeFunc) { @@ -734,6 +564,64 @@ SSLSetIOFuncs (SSLContextRef ctx, return SSLSetInternalRecordLayerIOFuncs(ctx->recCtx, IORead, IOWrite); } +void +SSLSetNPNFunc(SSLContextRef context, + SSLNPNFunc npnFunc, + void *info) +{ + if (context == NULL) { + return; + } + if (sslIsSessionActive(context)) { + return; + } + context->npnFunc = npnFunc; + context->npnFuncInfo = info; + if(context->protocolSide==kSSLClientSide) { + tls_handshake_set_npn_enable(context->hdsk, npnFunc!=NULL); + } +} + +OSStatus +SSLSetNPNData(SSLContextRef context, + const void *data, + size_t length) +{ + if (context == NULL || data == NULL || length == 0) { + return errSecParam; + } + + if (length > 255) { + return errSecParam; + } + + tls_buffer npn_data; + + npn_data.data = (uint8_t *)data; + npn_data.length = length; + + return tls_handshake_set_npn_data(context->hdsk, npn_data); +} + +const void * +SSLGetNPNData(SSLContextRef context, + size_t *length) +{ + if (context == NULL || length == NULL) + return NULL; + + const tls_buffer *npn_data; + + npn_data = tls_handshake_get_peer_npn_data(context->hdsk); + + if(npn_data) { + *length = npn_data->length; + return npn_data->data; + } else { + return NULL; + } +} + OSStatus SSLSetConnection (SSLContextRef ctx, SSLConnectionRef connection) @@ -781,19 +669,11 @@ SSLSetPeerDomainName (SSLContextRef ctx, return errSecBadReq; } - /* free possible existing name */ - if(ctx->peerDomainName) { - sslFree(ctx->peerDomainName); - } - - /* copy in */ - ctx->peerDomainName = (char *)sslMalloc(peerNameLen); - if(ctx->peerDomainName == NULL) { - return errSecAllocate; - } - memmove(ctx->peerDomainName, peerName, peerNameLen); - ctx->peerDomainNameLen = peerNameLen; - return errSecSuccess; + if(ctx->protocolSide == kSSLClientSide) { + return tls_handshake_set_peer_hostname(ctx->hdsk, peerName, peerNameLen); + } else { + return 0; // This should probably return an error, but historically didnt. + } } /* @@ -806,8 +686,9 @@ SSLGetPeerDomainNameLength (SSLContextRef ctx, if(ctx == NULL) { return errSecParam; } - *peerNameLen = ctx->peerDomainNameLen; - return errSecSuccess; + const char *hostname; + + return tls_handshake_get_peer_hostname(ctx->hdsk, &hostname, peerNameLen); } OSStatus @@ -815,15 +696,26 @@ SSLGetPeerDomainName (SSLContextRef ctx, char *peerName, // returned here size_t *peerNameLen) // IN/OUT { + const char *hostname; + size_t len; + + int err; + if(ctx == NULL) { return errSecParam; } - if(*peerNameLen < ctx->peerDomainNameLen) { - return errSSLBufferOverflow; - } - memmove(peerName, ctx->peerDomainName, ctx->peerDomainNameLen); - *peerNameLen = ctx->peerDomainNameLen; - return errSecSuccess; + + err=tls_handshake_get_peer_hostname(ctx->hdsk, &hostname, &len); + + if(err) { + return err; + } else if(*peerNameLenisDTLS) return errSecParam; - if(maxSize < MIN_ALLOWED_DTLS_MTU) return errSecParam; - ctx->mtu = maxSize; + tls_handshake_set_mtu(ctx->hdsk, maxSize); return errSecSuccess; } @@ -913,10 +804,16 @@ SSLGetDatagramWriteSize (SSLContextRef ctx, size_t max_fragment_size = ctx->mtu-13; /* 13 = dtls record header */ +#warning SecureTransport: SSLGetDatagramWriteSize is wrong, need hookup with coreTLS +#if 0 SSLCipherSpecParams *currCipher = &ctx->selectedCipherSpecParams; size_t blockSize = currCipher->blockSize; size_t macSize = currCipher->macSize; +#else + size_t blockSize = 16; + size_t macSize = 32; +#endif if (blockSize > 0) { /* max_fragment_size must be a multiple of blocksize */ @@ -987,6 +884,9 @@ SSLSetProtocolVersionMin (SSLContextRef ctx, } ctx->minProtocolVersion = version; + tls_handshake_set_min_protocol_version(ctx->hdsk, ctx->minProtocolVersion); + tls_handshake_set_max_protocol_version(ctx->hdsk, ctx->maxProtocolVersion); + return errSecSuccess; } @@ -1021,6 +921,9 @@ SSLSetProtocolVersionMax (SSLContextRef ctx, } ctx->maxProtocolVersion = version; + tls_handshake_set_min_protocol_version(ctx->hdsk, ctx->minProtocolVersion); + tls_handshake_set_max_protocol_version(ctx->hdsk, ctx->maxProtocolVersion); + return errSecSuccess; } @@ -1105,6 +1008,9 @@ SSLSetProtocolVersionEnabled(SSLContextRef ctx, } } + tls_handshake_set_min_protocol_version(ctx->hdsk, ctx->minProtocolVersion); + tls_handshake_set_max_protocol_version(ctx->hdsk, ctx->maxProtocolVersion); + return errSecSuccess; } @@ -1192,6 +1098,9 @@ SSLSetProtocolVersion (SSLContextRef ctx, return errSecParam; } + tls_handshake_set_min_protocol_version(ctx->hdsk, ctx->minProtocolVersion); + tls_handshake_set_max_protocol_version(ctx->hdsk, ctx->maxProtocolVersion); + return errSecSuccess; } @@ -1363,9 +1272,14 @@ static OSStatus sslDefaultSystemRoots( CFArrayRef *systemRoots) // created and RETURNED { + const char *hostname; + size_t len; + + tls_handshake_get_peer_hostname(ctx->hdsk, &hostname, &len); + return SecTrustSettingsCopyQualifiedCerts(&CSSMOID_APPLE_TP_SSL, - ctx->peerDomainName, - (uint32_t)ctx->peerDomainNameLen, + hostname, + (uint32_t)len, (ctx->protocolSide == kSSLServerSide) ? /* server verifies, client encrypts */ CSSM_KEYUSE_VERIFY : CSSM_KEYUSE_ENCRYPT, @@ -1521,11 +1435,11 @@ SSLSetClientSideAuthenticate (SSLContext *ctx, ctx->clientAuth = auth; switch(auth) { case kNeverAuthenticate: - ctx->tryClientAuth = false; + tls_handshake_set_client_auth(ctx->hdsk, false); break; case kAlwaysAuthenticate: case kTryAuthenticate: - ctx->tryClientAuth = true; + tls_handshake_set_client_auth(ctx->hdsk, true); break; } return errSecSuccess; @@ -1574,6 +1488,7 @@ SSLSetCertificate (SSLContextRef ctx, { return errSecBadReq; } + CFReleaseNull(ctx->localCertArray); /* changing the client cert invalidates negotiated auth type */ ctx->negAuthType = SSLClientAuthNone; @@ -1583,15 +1498,14 @@ SSLSetCertificate (SSLContextRef ctx, OSStatus ortn = parseIncomingCerts(ctx, certRefs, &ctx->localCert, - &ctx->signingPubKey, - &ctx->signingPrivKeyRef, - &ctx->ourSignerAlg); - if(ortn == errSecSuccess) { + &ctx->signingPrivKeyRef); + if(ortn == errSecSuccess) { ctx->localCertArray = certRefs; CFRetain(certRefs); - /* client cert was changed, must update auth type */ - ortn = SSLUpdateNegotiatedClientAuthType(ctx); - } + if(ctx->protocolSide==kSSLClientSide) + SSLUpdateNegotiatedClientAuthType(ctx); + tls_handshake_set_identity(ctx->hdsk, ctx->localCert, ctx->signingPrivKeyRef); + } return ortn; } @@ -1613,12 +1527,10 @@ SSLSetEncryptionCertificate (SSLContextRef ctx, return errSecBadReq; } CFReleaseNull(ctx->encryptCertArray); - OSStatus ortn = parseIncomingCerts(ctx, + OSStatus ortn = parseIncomingCerts(ctx, certRefs, &ctx->encryptCert, - &ctx->encryptPubKey, - &ctx->encryptPrivKeyRef, - NULL); /* Signer alg */ + &ctx->encryptPrivKeyRef); if(ortn == errSecSuccess) { ctx->encryptCertArray = certRefs; CFRetain(certRefs); @@ -1670,6 +1582,7 @@ SSLSetPeerID (SSLContext *ctx, if(serr) { return serr; } + tls_handshake_set_resumption(ctx->hdsk, true); memmove(ctx->peerID.data, peerID, peerIDLen); return errSecSuccess; } @@ -1691,10 +1604,13 @@ SSLGetNegotiatedCipher (SSLContextRef ctx, if(ctx == NULL) { return errSecParam; } - if(!sslIsSessionActive(ctx)) { + + if(!sslIsSessionActive(ctx)) { return errSecBadReq; } - *cipherSuite = (SSLCipherSuite)ctx->selectedCipher; + + *cipherSuite = (SSLCipherSuite)tls_handshake_get_negotiated_cipherspec(ctx->hdsk); + return errSecSuccess; } @@ -1726,6 +1642,9 @@ SSLAddDistinguishedName( memcpy(dn->derDN.data, derDN, derDNLen); dn->next = ctx->acceptableDNList; ctx->acceptableDNList = dn; + + tls_handshake_set_acceptable_dn_list(ctx->hdsk, dn); + return errSecSuccess; } @@ -1862,17 +1781,23 @@ SSLCopyDistinguishedNames (SSLContextRef ctx, CFArrayRef *names) { CFMutableArrayRef outArray = NULL; - DNListElem *dn; + const DNListElem *dn; if((ctx == NULL) || (names == NULL)) { return errSecParam; } - if(ctx->acceptableDNList == NULL) { + if(ctx->protocolSide==kSSLServerSide) { + dn = ctx->acceptableDNList; + } else { + dn = tls_handshake_get_peer_acceptable_dn_list(ctx->hdsk); // ctx->acceptableDNList; + } + + if(dn == NULL) { *names = NULL; return errSecSuccess; } outArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - dn = ctx->acceptableDNList; + while (dn) { CFDataRef cfDn = CFDataCreate(NULL, dn->derDN.data, dn->derDN.length); CFArrayAppendValue(outArray, cfDn); @@ -1899,58 +1824,6 @@ sslCopyPeerCertificates (SSLContextRef ctx, return errSecParam; } -#ifdef USE_SSLCERTIFICATE - uint32 numCerts; - CFMutableArrayRef ca; - CFIndex i; - SecCertificateRef cfd; - OSStatus ortn; - CSSM_DATA certData; - SSLCertificate *scert; - - *certs = NULL; - - /* - * Copy peerCert, a chain of SSLCertificates, to a CFArray of - * CFDataRefs, each of which is one DER-encoded cert. - */ - numCerts = SSLGetCertificateChainLength(ctx->peerCert); - if(numCerts == 0) { - return errSecSuccess; - } - ca = CFArrayCreateMutable(kCFAllocatorDefault, - (CFIndex)numCerts, &kCFTypeArrayCallBacks); - if(ca == NULL) { - return errSecAllocate; - } - - /* - * Caller gets leaf cert first, the opposite of the way we store them. - */ - scert = ctx->peerCert; - for(i=0; (unsigned)iderCert, &certData); - ortn = SecCertificateCreateFromData(&certData, - CSSM_CERT_X_509v3, - CSSM_CERT_ENCODING_DER, - &cfd); - if(ortn) { - CFRelease(ca); - return ortn; - } - /* insert at head of array */ - CFArrayInsertValueAtIndex(ca, 0, cfd); - if(!legacy) { - /* skip for legacy SSLGetPeerCertificates() */ - CFRelease(cfd); - } - scert = scert->next; - } - *certs = ca; - -#else if (!ctx->peerCert) { *certs = NULL; return errSecBadReq; @@ -1968,7 +1841,6 @@ sslCopyPeerCertificates (SSLContextRef ctx, CFRetain(CFArrayGetValueAtIndex(ca, ix)); } } -#endif return errSecSuccess; } @@ -2013,10 +1885,6 @@ OSStatus SSLSetDiffieHellmanParams( return errSecBadReq; } SSLFreeBuffer(&ctx->dhParamsEncoded); -#if !USE_CDSA_CRYPTO - if (ctx->secDHContext) - SecDHDestroy(ctx->secDHContext); -#endif OSStatus ortn; ortn = SSLCopyBufferFromData(dhParams, dhParamsLen, @@ -2081,6 +1949,9 @@ SSLCopyPeerTrust( /* Create a SecTrustRef if this was a resumed session and we didn't have one yet. */ + if (!ctx->peerCert) { + ctx->peerCert = tls_get_peer_certs(tls_handshake_get_peer_certificates(ctx->hdsk)); + } if (!ctx->peerSecTrust && ctx->peerCert) { status = sslCreateSecTrust(ctx, ctx->peerCert, true, &ctx->peerSecTrust); @@ -2120,12 +1991,7 @@ OSStatus SSLInternalMasterSecret( if((ctx == NULL) || (secret == NULL) || (secretSize == NULL)) { return errSecParam; } - if(*secretSize < SSL_MASTER_SECRET_SIZE) { - return errSecParam; - } - memmove(secret, ctx->masterSecret, SSL_MASTER_SECRET_SIZE); - *secretSize = SSL_MASTER_SECRET_SIZE; - return errSecSuccess; + return tls_handshake_internal_master_secret(ctx->hdsk, secret, secretSize); } OSStatus SSLInternalServerRandom( @@ -2136,12 +2002,7 @@ OSStatus SSLInternalServerRandom( if((ctx == NULL) || (randBuf == NULL) || (randSize == NULL)) { return errSecParam; } - if(*randSize < SSL_CLIENT_SRVR_RAND_SIZE) { - return errSecParam; - } - memmove(randBuf, ctx->serverRandom, SSL_CLIENT_SRVR_RAND_SIZE); - *randSize = SSL_CLIENT_SRVR_RAND_SIZE; - return errSecSuccess; + return tls_handshake_internal_server_random(ctx->hdsk, randBuf, randSize); } OSStatus SSLInternalClientRandom( @@ -2152,12 +2013,7 @@ OSStatus SSLInternalClientRandom( if((ctx == NULL) || (randBuf == NULL) || (randSize == NULL)) { return errSecParam; } - if(*randSize < SSL_CLIENT_SRVR_RAND_SIZE) { - return errSecParam; - } - memmove(randBuf, ctx->clientRandom, SSL_CLIENT_SRVR_RAND_SIZE); - *randSize = SSL_CLIENT_SRVR_RAND_SIZE; - return errSecSuccess; + return tls_handshake_internal_client_random(ctx->hdsk, randBuf, randSize); } /* This is used by EAP 802.1x */ @@ -2167,16 +2023,16 @@ OSStatus SSLGetCipherSizes( size_t *symmetricKeySize, size_t *ivSize) { - const SSLCipherSpecParams *currCipher; - - if((ctx == NULL) || (digestSize == NULL) || + if((ctx == NULL) || (digestSize == NULL) || (symmetricKeySize == NULL) || (ivSize == NULL)) { return errSecParam; } - currCipher = &ctx->selectedCipherSpecParams; - *digestSize = currCipher->macSize; - *symmetricKeySize = currCipher->keySize; - *ivSize = currCipher->ivSize; + + SSLCipherSuite cipher=tls_handshake_get_negotiated_cipherspec(ctx->hdsk); + + *digestSize = sslCipherSuiteGetMacSize(cipher); + *symmetricKeySize = sslCipherSuiteGetSymmetricCipherKeySize(cipher); + *ivSize = sslCipherSuiteGetSymmetricCipherBlockIvSize(cipher); return errSecSuccess; } @@ -2192,20 +2048,24 @@ SSLGetResumableSessionInfo( (*sessionIDLength < MAX_SESSION_ID_LENGTH)) { return errSecParam; } - if(ctx->sessionMatch) { + + SSLBuffer localSessionID; + bool sessionMatch = tls_handshake_get_session_match(ctx->hdsk, &localSessionID); + + if(sessionMatch) { *sessionWasResumed = true; - if(ctx->sessionID.length > *sessionIDLength) { + if(localSessionID.length > *sessionIDLength) { /* really should never happen - means ID > 32 */ return errSecParam; } - if(ctx->sessionID.length) { + if(localSessionID.length) { /* * Note PAC-based session resumption can result in sessionMatch * with no sessionID */ - memmove(sessionID, ctx->sessionID.data, ctx->sessionID.length); + memmove(sessionID, localSessionID.data, localSessionID.length); } - *sessionIDLength = ctx->sessionID.length; + *sessionIDLength = localSessionID.length; } else { *sessionWasResumed = false; @@ -2267,6 +2127,17 @@ SSLSetSessionCacheTimeout( return errSecSuccess; } + +static +void tls_handshake_master_secret_function(const void *arg, /* opaque to coreTLS; app-specific */ + void *secret, /* mallocd by caller, SSL_MASTER_SECRET_SIZE */ + size_t *secretLength) +{ + SSLContextRef ctx = (SSLContextRef) arg; + ctx->masterSecretCallback(ctx, ctx->masterSecretArg, secret, secretLength); +} + + /* * Register a callback for obtaining the master_secret when performing * PAC-based session resumption. @@ -2280,9 +2151,11 @@ SSLInternalSetMasterSecretFunction( if(ctx == NULL) { return errSecParam; } - ctx->masterSecretCallback = mFunc; - ctx->masterSecretArg = arg; - return errSecSuccess; + + ctx->masterSecretArg = arg; + ctx->masterSecretCallback = mFunc; + + return tls_handshake_internal_set_master_secret_function(ctx->hdsk, &tls_handshake_master_secret_function, ctx); } /* @@ -2310,14 +2183,10 @@ OSStatus SSLInternalSetSessionTicket( /* can't do this with an active session */ return errSecBadReq; } - if(ticketLength > 0xffff) { - /* extension data encoded with a 2-byte length! */ - return errSecParam; - } - SSLFreeBuffer(&ctx->sessionTicket); - return SSLCopyBufferFromData(ticket, ticketLength, &ctx->sessionTicket); + return tls_handshake_internal_set_session_ticket(ctx->hdsk, ticket, ticketLength); } + /* * ECDSA curve accessors. */ @@ -2333,10 +2202,11 @@ OSStatus SSLGetNegotiatedCurve( if((ctx == NULL) || (namedCurve == NULL)) { return errSecParam; } - if(ctx->ecdhPeerCurve == SSL_Curve_None) { + unsigned int curve = tls_handshake_get_negotiated_curve(ctx->hdsk); + if(curve == SSL_Curve_None) { return errSecParam; } - *namedCurve = ctx->ecdhPeerCurve; + *namedCurve = curve; return errSecSuccess; } @@ -2385,15 +2255,25 @@ OSStatus SSLSetECDSACurves( if((ctx == NULL) || (namedCurves == NULL) || (numCurves == 0)) { return errSecParam; } - if(numCurves > SSL_ECDSA_NUM_CURVES) { - return errSecParam; - } if(sslIsSessionActive(ctx)) { /* can't do this with an active session */ return errSecBadReq; } - memmove(ctx->ecdhCurves, namedCurves, (numCurves * sizeof(SSL_ECDSA_NamedCurve))); + + size_t size = numCurves * sizeof(uint16_t); + ctx->ecdhCurves = (uint16_t *)sslMalloc(size); + if(ctx->ecdhCurves == NULL) { + ctx->ecdhNumCurves = 0; + return errSecAllocate; + } + + for (unsigned i=0; iecdhCurves[i] = namedCurves[i]; + } + ctx->ecdhNumCurves = numCurves; + + tls_handshake_set_curves(ctx->hdsk, ctx->ecdhCurves, ctx->ecdhNumCurves); return errSecSuccess; } @@ -2447,7 +2327,9 @@ OSStatus SSLGetNegotiatedClientAuthType( if(ctx == NULL) { return errSecParam; } + *authType = ctx->negAuthType; + return errSecSuccess; } @@ -2467,6 +2349,7 @@ OSStatus SSLUpdateNegotiatedClientAuthType( if(ctx == NULL) { return errSecParam; } + assert(ctx->protocolSide==kSSLClientSide); /* * See if we have a signing cert that matches one of the * allowed auth types. The x509Requested flag indicates "we @@ -2475,7 +2358,9 @@ OSStatus SSLUpdateNegotiatedClientAuthType( ctx->x509Requested = 0; ctx->negAuthType = SSLClientAuthNone; if(ctx->signingPrivKeyRef != NULL) { - CFIndex ourKeyAlg = sslPubKeyGetAlgorithmID(ctx->signingPubKey); + CFIndex ourKeyAlg = sslPrivKeyGetAlgorithmID((SecKeyRef)tls_private_key_get_context(ctx->signingPrivKeyRef)); + assert(ourKeyAlg==kSecRSAAlgorithmID); /* We don't suport anything else */ + unsigned i; for(i=0; inumAuthTypes; i++) { switch(ctx->clientAuthTypes[i]) { @@ -2485,6 +2370,8 @@ OSStatus SSLUpdateNegotiatedClientAuthType( ctx->negAuthType = SSLClientAuth_RSASign; } break; +#if 0 +// The code below is hopelessly broken: ctx->ourSignerAlg is never set #if SSL_ENABLE_ECDSA_SIGN_AUTH case SSLClientAuth_ECDSASign: #endif @@ -2507,6 +2394,7 @@ OSStatus SSLUpdateNegotiatedClientAuthType( } break; #endif +#endif default: /* None others supported */ break; @@ -2518,6 +2406,8 @@ OSStatus SSLUpdateNegotiatedClientAuthType( } /* parsing authTypes */ } /* we have a signing key */ + tls_handshake_set_client_auth_type(ctx->hdsk, ctx->negAuthType); + return errSecSuccess; } @@ -2525,25 +2415,33 @@ OSStatus SSLGetNumberOfSignatureAlgorithms( SSLContextRef ctx, unsigned *numSigAlgs) { - if((ctx == NULL) || (ctx->clientCertState == kSSLClientCertNone)) { + if(ctx == NULL){ return errSecParam; } - *numSigAlgs = ctx->numServerSigAlgs; + + tls_handshake_get_peer_signature_algorithms(ctx->hdsk, numSigAlgs); return errSecSuccess; } +_Static_assert(sizeof(SSLSignatureAndHashAlgorithm)==sizeof(tls_signature_and_hash_algorithm), + "SSLSignatureAndHashAlgorithm and tls_signature_and_hash_algorithm do not match"); + OSStatus SSLGetSignatureAlgorithms( SSLContextRef ctx, SSLSignatureAndHashAlgorithm *sigAlgs, /* RETURNED */ unsigned *numSigAlgs) /* IN/OUT */ { - if((ctx == NULL) || (ctx->clientCertState == kSSLClientCertNone)) { + if(ctx == NULL) { return errSecParam; } - memmove(sigAlgs, ctx->serverSigAlgs, - ctx->numServerSigAlgs * sizeof(SSLSignatureAndHashAlgorithm)); - *numSigAlgs = ctx->numServerSigAlgs; - return errSecSuccess; + + unsigned numPeerSigAlgs; + const tls_signature_and_hash_algorithm *peerAlgs = tls_handshake_get_peer_signature_algorithms(ctx->hdsk, &numPeerSigAlgs); + + memmove(sigAlgs, peerAlgs, + numPeerSigAlgs * sizeof(SSLSignatureAndHashAlgorithm)); + *numSigAlgs = numPeerSigAlgs; + return errSecSuccess; } /* PSK SPIs */ @@ -2559,6 +2457,8 @@ OSStatus SSLSetPSKSharedSecret(SSLContextRef ctx, if(SSLCopyBufferFromData(secret, secretLen, &ctx->pskSharedSecret)) return errSecAllocate; + tls_handshake_set_psk_secret(ctx->hdsk, &ctx->pskSharedSecret); + return errSecSuccess; } @@ -2574,6 +2474,8 @@ OSStatus SSLSetPSKIdentity(SSLContextRef ctx, if(SSLCopyBufferFromData(pskIdentity, pskIdentityLen, &ctx->pskIdentity)) return errSecAllocate; + tls_handshake_set_psk_identity(ctx->hdsk, &ctx->pskIdentity); + return errSecSuccess; } @@ -2586,40 +2488,27 @@ OSStatus SSLGetPSKIdentity(SSLContextRef ctx, *pskIdentity=ctx->pskIdentity.data; *pskIdentityLen=ctx->pskIdentity.length; + return errSecSuccess; } - -#ifdef USE_SSLCERTIFICATE - -size_t -SSLGetCertificateChainLength(const SSLCertificate *c) +OSStatus SSLInternal_PRF( + SSLContext *ctx, + const void *vsecret, + size_t secretLen, + const void *label, // optional, NULL implies that seed contains + // the label + size_t labelLen, + const void *seed, + size_t seedLen, + void *vout, // mallocd by caller, length >= outLen + size_t outLen) { - size_t rtn = 0; - - while (c) - { - rtn++; - c = c->next; - } - return rtn; + return tls_handshake_internal_prf(ctx->hdsk, + vsecret, secretLen, + label, labelLen, + seed, seedLen, + vout, outLen); } -OSStatus sslDeleteCertificateChain( - SSLCertificate *certs, - SSLContext *ctx) -{ - SSLCertificate *cert; - SSLCertificate *nextCert; - assert(ctx != NULL); - cert=certs; - while(cert != NULL) { - nextCert = cert->next; - SSLFreeBuffer(&cert->derCert); - sslFree(cert); - cert = nextCert; - } - return errSecSuccess; -} -#endif /* USE_SSLCERTIFICATE */ diff --git a/Security/libsecurity_ssl/lib/sslContext.h b/Security/libsecurity_ssl/lib/sslContext.h new file mode 100644 index 00000000..1c06afac --- /dev/null +++ b/Security/libsecurity_ssl/lib/sslContext.h @@ -0,0 +1,286 @@ +/* + * Copyright (c) 1999-2001,2005-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@ + */ + +/* + * sslContext.h - Private SSL typedefs: SSLContext and its components + */ + +#ifndef _SSLCONTEXT_H_ +#define _SSLCONTEXT_H_ 1 + +#include "SecureTransport.h" +#include "sslBuildFlags.h" + +#include +#include +#include + +#ifdef USE_CDSA_CRYPTO +#include +#else +#if TARGET_OS_IPHONE +#include +#include +#else +#include "../sec/Security/SecDH.h" // hack to get SecDH. +// typedef struct OpaqueSecDHContext *SecDHContext; +#endif +#include +#endif + +#include +#include + +#include "sslPriv.h" +#include "tls_ssl.h" +#include "sslDigests.h" +#include "sslRecord.h" +#include "cipherSpecs.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ SSLReadFunc read; + SSLWriteFunc write; + SSLConnectionRef ioRef; +} IOContext; + +//FIXME should not need this. +typedef enum +{ + SSL_HdskStateUninit = 0, /* No Handshake yet */ + SSL_HdskStatePending, /* Handshake in Progress */ + SSL_HdskStateReady, /* Handshake is done */ + SSL_HdskStateGracefulClose, + SSL_HdskStateErrorClose, + SSL_HdskStateNoNotifyClose, /* server disconnected with no + * notify msg */ +} SSLHandshakeState; + +#define SSLChangeHdskState(ctx, newState) { ctx->state=newState; } + +struct SSLContext +{ + CFRuntimeBase _base; + IOContext ioCtx; + + + const struct SSLRecordFuncs *recFuncs; + SSLRecordContextRef recCtx; + + tls_handshake_t hdsk; + + int readCipher_ready; + int writeCipher_ready; + + SSLHandshakeState state; + + /* + * Prior to successful protocol negotiation, negProtocolVersion + * is SSL_Version_Undetermined. Subsequent to successful + * negotiation, negProtocolVersion contains the actual over-the-wire + * protocol value. + * + * The Boolean versionEnable flags are set by + * SSLSetProtocolVersionEnabled or SSLSetProtocolVersion and + * remain invariant once negotiation has started. If there + * were a large number of these and/or we were adding new + * protocol versions on a regular basis, we'd probably want + * to implement these as a word of flags. For now, in the + * real world, this is the most straightforward implementation. + */ + SSLProtocolVersion negProtocolVersion; /* negotiated */ + SSLProtocolVersion clientReqProtocol; /* requested by client in hello msg */ + SSLProtocolVersion minProtocolVersion; + SSLProtocolVersion maxProtocolVersion; + Boolean isDTLS; /* if this is a Datagram Context */ + SSLProtocolSide protocolSide; /* ConnectionEnd enum { server, client } in rfc5246. */ + + SSLBuffer dtlsCookie; /* DTLS ClientHello cookie */ + + + uint16_t selectedCipher; /* currently selected */ + + + tls_private_key_t signingPrivKeyRef; /* our private signing key */ + + tls_private_key_t encryptPrivKeyRef; /* our private encrypt key, for + * server-initiated key exchange */ + + + /* Server DH Parameters */ + SSLBuffer dhParamsEncoded; /* PKCS3 encoded blob - prime + generator */ + + /* + * Various cert chains. + * For all three, the root is the last in the chain. + */ + SSLCertificate *localCert; + SSLCertificate *encryptCert; + CFArrayRef peerCert; + + /* + * The arrays we are given via SSLSetCertificate() and SSLSetEncryptionCertificate(). + * We keep them here, refcounted, solely for the associated getters. + */ + CFArrayRef localCertArray; + CFArrayRef encryptCertArray; + + /* peer certs as SecTrustRef */ + SecTrustRef peerSecTrust; + + CFMutableArrayRef trustedCerts; + Boolean trustedCertsOnly; + + /* + * trusted leaf certs as specified in SSLSetTrustedLeafCertificates() + */ + CFArrayRef trustedLeafCerts; + + Boolean allowExpiredCerts; + Boolean allowExpiredRoots; + Boolean enableCertVerify; + + SSLBuffer sessionID; + SSLBuffer peerID; + SSLBuffer resumableSession; /* We keep a copy for now - but eventually this should go away if we get refcounted SSLBuffers */ + + uint16_t *validCipherSuites; /* context's valid suites */ + unsigned numValidCipherSuites; /* size of validCipherSuites */ + + + uint16_t *ecdhCurves; + unsigned ecdhNumCurves; + + /* server-side only */ + SSLAuthenticate clientAuth; /* kNeverAuthenticate, etc. */ + //Boolean tryClientAuth; + + /* client and server */ + SSLClientCertificateState clientCertState; + + DNListElem *acceptableDNList; /* client and server */ + CFMutableArrayRef acceptableCAs; /* server only - SecCertificateRefs */ + + bool certRequested; + bool certSent; + bool certReceived; + bool x509Requested; + + unsigned sessionMatch; + + + /* Transport layer fields */ + SSLBuffer receivedDataBuffer; + size_t receivedDataPos; + + Boolean allowAnyRoot; // don't require known roots + Boolean sentFatalAlert; // this session terminated by fatal alert + Boolean rsaBlindingEnable; + Boolean oneByteRecordEnable; /* enable 1/n-1 data splitting for TLSv1 and SSLv3 */ + + /* optional session cache timeout (in seconds) override - 0 means default */ + uint32_t sessionCacheTimeout; + + /* optional SessionTicket */ + SSLBuffer sessionTicket; + + /* optional callback to obtain master secret, with its opaque arg */ + SSLInternalMasterSecretFunction masterSecretCallback; + const void *masterSecretArg; + + #if SSL_PAC_SERVER_ENABLE + /* server PAC resume sets serverRandom early to allow for secret acquisition */ + uint8_t serverRandomValid; + #endif + + Boolean anonCipherEnable; + + /* optional switches to enable additional returns from SSLHandshake */ + Boolean breakOnServerAuth; + Boolean breakOnCertRequest; + Boolean breakOnClientAuth; + Boolean signalServerAuth; + Boolean signalCertRequest; + Boolean signalClientAuth; + + /* true iff ECDSA/ECDH ciphers are configured */ + Boolean ecdsaEnable; + + /* List of peer-specified supported_signature_algorithms */ + unsigned numPeerSigAlgs; + const tls_signature_and_hash_algorithm *peerSigAlgs; + + /* List of server-specified client auth types */ + unsigned numAuthTypes; + const tls_client_auth_type *clientAuthTypes; + + /* client auth type actually negotiated */ + tls_client_auth_type negAuthType; + + /* Timeout for DTLS retransmit */ + CFAbsoluteTime timeout_deadline; + CFAbsoluteTime timeout_duration; + size_t mtu; + + /* RFC 5746: Secure renegotiation */ + Boolean secure_renegotiation; + Boolean secure_renegotiation_received; + SSLBuffer ownVerifyData; + SSLBuffer peerVerifyData; + + /* RFC 4279: TLS PSK */ + SSLBuffer pskSharedSecret; + SSLBuffer pskIdentity; + + /* TLS False Start */ + Boolean falseStartEnabled; //FalseStart enabled (by API call) + /* Fallback behavior */ + Boolean fallbackEnabled; // Fallback behavior enabled. + /* NPN */ + SSLNPNFunc npnFunc; + void *npnFuncInfo; +}; + +OSStatus SSLUpdateNegotiatedClientAuthType(SSLContextRef ctx); + +Boolean sslIsSessionActive(const SSLContext *ctx); + +static inline bool sslVersionIsLikeTls12(SSLContext *ctx) +{ + check(ctx->negProtocolVersion!=SSL_Version_Undetermined); + return ctx->isDTLS ? ctx->negProtocolVersion > DTLS_Version_1_0 : ctx->negProtocolVersion >= TLS_Version_1_2; +} + +/* This is implemented in tls_callbacks.c */ + int sslGetSessionID(SSLContext *myCtx, SSLBuffer *sessionID); + +#ifdef __cplusplus +} +#endif + +#endif /* _SSLCONTEXT_H_ */ diff --git a/Security/libsecurity_ssl/lib/sslCrypto.c b/Security/libsecurity_ssl/lib/sslCrypto.c new file mode 100644 index 00000000..07457375 --- /dev/null +++ b/Security/libsecurity_ssl/lib/sslCrypto.c @@ -0,0 +1,569 @@ +/* + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + */ + +/* + * sslCrypto.c - interface between SSL and crypto libraries + */ + +#include "sslCrypto.h" +#include "sslContext.h" +#include "sslMemory.h" +#include "sslUtils.h" +#include "sslDebug.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include "utilities/SecCFRelease.h" + +#if TARGET_OS_IPHONE +#include +#include +#endif + +/* + * Get algorithm id for a SSLPubKey object. + */ +CFIndex sslPubKeyGetAlgorithmID(SecKeyRef pubKey) +{ +#if TARGET_OS_IPHONE + return SecKeyGetAlgorithmID(pubKey); +#else + return SecKeyGetAlgorithmId(pubKey); +#endif +} + +/* + * Get algorithm id for a SSLPrivKey object. + */ +CFIndex sslPrivKeyGetAlgorithmID(SecKeyRef privKey) +{ +#if TARGET_OS_IPHONE + return SecKeyGetAlgorithmID(privKey); +#else + return SecKeyGetAlgorithmId(privKey); +#endif +} + + +OSStatus +sslCreateSecTrust( + SSLContext *ctx, + CFArrayRef certChain, + bool arePeerCerts, + SecTrustRef *pTrust) /* RETURNED */ +{ + OSStatus status = errSecAllocate; + CFStringRef peerDomainName = NULL; + CFTypeRef policies = NULL; + SecTrustRef trust = NULL; + const char *peerDomainNameData = NULL; + size_t peerDomainNameLen = 0; + + if(ctx->protocolSide==kSSLClientSide) { + tls_handshake_get_peer_hostname(ctx->hdsk, &peerDomainNameData, &peerDomainNameLen); + } + + if (CFArrayGetCount(certChain) == 0) { + status = errSSLBadCert; + goto errOut; + } + + if (arePeerCerts) { + if (peerDomainNameLen && peerDomainNameData) { + CFIndex len = peerDomainNameLen; + if (peerDomainNameData[len - 1] == 0) { + len--; + //secwarning("peerDomainName is zero terminated!"); + } + /* @@@ Double check that this is the correct encoding. */ + require(peerDomainName = CFStringCreateWithBytes(kCFAllocatorDefault, + (const UInt8 *)peerDomainNameData, len, + kCFStringEncodingUTF8, false), errOut); + } + } + /* If we are the client, our peer certificates must satisfy the + ssl server policy. */ + bool server = ctx->protocolSide == kSSLClientSide; + require(policies = SecPolicyCreateSSL(server, peerDomainName), errOut); + + require_noerr(status = SecTrustCreateWithCertificates(certChain, policies, + &trust), errOut); + + /* If we have trustedAnchors we set them here. */ + if (ctx->trustedCerts) { + require_noerr(status = SecTrustSetAnchorCertificates(trust, + ctx->trustedCerts), errOut); + require_noerr(status = SecTrustSetAnchorCertificatesOnly(trust, + ctx->trustedCertsOnly), errOut); + } + + status = errSecSuccess; + +errOut: + CFReleaseSafe(peerDomainName); + CFReleaseSafe(policies); + + *pTrust = trust; + + return status; +} + +/* Return the first certificate reference from the supplied array + * whose data matches the given certificate, or NULL if none match. + */ +static +SecCertificateRef +sslGetMatchingCertInArray( + SecCertificateRef certRef, + CFArrayRef certArray) +{ + SecCertificateRef matchedCert = NULL; + + if (certRef == NULL || certArray == NULL) { + return NULL; + } + + CFDataRef certData = SecCertificateCopyData(certRef); + if (certData) { + CFIndex idx, count = CFArrayGetCount(certArray); + for(idx=0; idxtrustedCerts. + * + * If arePeerCerts is true, host name verification is enabled and we + * save the resulting SecTrustRef in ctx->peerSecTrust. Otherwise + * we're just validating our own certs; no host name checking and + * peerSecTrust is transient. + */ +static OSStatus sslVerifyCertChain( + SSLContext *ctx, + CFArrayRef certChain, + bool arePeerCerts) +{ + OSStatus status; + SecTrustRef trust = NULL; + + assert(certChain); + + if (arePeerCerts) { + /* renegotiate - start with a new SecTrustRef */ + CFReleaseNull(ctx->peerSecTrust); + } + + status = sslCreateSecTrust(ctx, certChain, arePeerCerts, &trust); + + if (!ctx->enableCertVerify) { + /* trivial case, this is caller's responsibility */ + status = errSecSuccess; + goto errOut; + } + + SecTrustResultType secTrustResult; + require_noerr(status = SecTrustEvaluate(trust, &secTrustResult), errOut); + switch (secTrustResult) { + case kSecTrustResultUnspecified: + /* cert chain valid, no special UserTrust assignments */ + case kSecTrustResultProceed: + /* cert chain valid AND user explicitly trusts this */ + status = errSecSuccess; + break; + case kSecTrustResultDeny: + case kSecTrustResultConfirm: + case kSecTrustResultRecoverableTrustFailure: + default: + if(ctx->allowAnyRoot) { + sslErrorLog("***Warning: accepting unverified cert chain\n"); + status = errSecSuccess; + } + else { + /* + * If the caller provided a list of trusted leaf certs, check them here + */ + if(ctx->trustedLeafCerts) { + if (sslGetMatchingCertInArray((SecCertificateRef)CFArrayGetValueAtIndex(certChain, 0), + ctx->trustedLeafCerts)) { + status = errSecSuccess; + goto errOut; + } + } + status = errSSLXCertChainInvalid; + } + /* Do we really need to return things like: + errSSLNoRootCert + errSSLUnknownRootCert + errSSLCertExpired + errSSLCertNotYetValid + errSSLHostNameMismatch + for our client to see what went wrong, or should we just always + return + errSSLXCertChainInvalid + when something is wrong? */ + break; + } + +errOut: + if (arePeerCerts) + ctx->peerSecTrust = trust; + else + CFReleaseSafe(trust); + + return status; +} + +/* Extract public SecKeyRef from Certificate Chain */ +static +int sslCopyPeerPubKey(const SSLCertificate *certchain, + SecKeyRef *pubKey) +{ + int err; + check(pubKey); + SecTrustRef trust = NULL; + const SSLCertificate *cert; + CFMutableArrayRef certArray = NULL; + CFDataRef certData = NULL; + SecCertificateRef cfCert = NULL; + + err = errSSLInternal; + + certArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + cert = certchain; + while(cert) { + require((certData = CFDataCreate(kCFAllocatorDefault, cert->derCert.data, cert->derCert.length)), out); + require((cfCert = SecCertificateCreateWithData(kCFAllocatorDefault, certData)), out); + CFArrayAppendValue(certArray, cfCert); + CFReleaseNull(cfCert); + CFReleaseNull(certData); + cert=cert->next; + } + + require_noerr((err=SecTrustCreateWithCertificates(certArray, NULL, &trust)), out); + SecKeyRef key = SecTrustCopyPublicKey(trust); + require_action(key, out, err=-9808); // errSSLBadCert + + *pubKey = key; + + err = errSecSuccess; + +out: + CFReleaseSafe(certData); + CFReleaseSafe(cfCert); + CFReleaseSafe(trust); + CFReleaseSafe(certArray); + + return err; +} + +/* Extract the pubkey from a cert chain, and send it to the tls_handshake context */ +static int tls_set_peer_pubkey(tls_handshake_t hdsk, const SSLCertificate *certchain) +{ + int err; + CFIndex algId; + SecKeyRef pubkey = NULL; + CFDataRef modulus = NULL; + CFDataRef exponent = NULL; + CFDataRef ecpubdata = NULL; + +#if 0 + { /* dump certs */ + int i=0; + int j; + const SSLCertificate *tmp = certchain; + while(tmp) { + printf("cert%d[] = {", i); + for(j=0; jderCert.length; j++) { + if((j&0xf)==0) + printf("\n"); + printf("0x%02x, ", tmp->derCert.data[j]); + } + printf("}\n"); + tmp=tmp->next; + i++; + } + } +#endif + + require_noerr((err=sslCopyPeerPubKey(certchain, &pubkey)), errOut); + +#if TARGET_OS_IPHONE + algId = SecKeyGetAlgorithmID(pubkey); +#else + algId = SecKeyGetAlgorithmId(pubkey); +#endif + + err = errSSLCrypto; + + switch(algId) { + case kSecRSAAlgorithmID: + { + require((modulus = SecKeyCopyModulus(pubkey)), errOut); + require((exponent = SecKeyCopyExponent(pubkey)), errOut); + + tls_buffer mod; + tls_buffer exp; + + mod.data = (uint8_t *)CFDataGetBytePtr(modulus); + mod.length = CFDataGetLength(modulus); + + exp.data = (uint8_t *)CFDataGetBytePtr(exponent); + exp.length = CFDataGetLength(exponent); + + err = tls_handshake_set_peer_rsa_public_key(hdsk, &mod, &exp); + break; + } + case kSecECDSAAlgorithmID: + { + tls_named_curve curve = SecECKeyGetNamedCurve(pubkey); + require((ecpubdata = SecECKeyCopyPublicBits(pubkey)), errOut); + + tls_buffer pubdata; + pubdata.data = (uint8_t *)CFDataGetBytePtr(ecpubdata); + pubdata.length = CFDataGetLength(ecpubdata); + + err = tls_handshake_set_peer_ec_public_key(hdsk, curve, &pubdata); + + break; + } + default: + break; + } + +errOut: + CFReleaseSafe(pubkey); + CFReleaseSafe(modulus); + CFReleaseSafe(exponent); + CFReleaseSafe(ecpubdata); + + return err; +} + +/* Convert cert in DER format into an CFArray of SecCertificateRef */ +CFArrayRef +tls_get_peer_certs(const SSLCertificate *certs) +{ + const SSLCertificate *cert; + + CFMutableArrayRef certArray = NULL; + CFDataRef certData = NULL; + SecCertificateRef cfCert = NULL; + + certArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + require(certArray, out); + cert = certs; + while(cert) { + require((certData = CFDataCreate(kCFAllocatorDefault, cert->derCert.data, cert->derCert.length)), out); + require((cfCert = SecCertificateCreateWithData(kCFAllocatorDefault, certData)), out); + CFArrayAppendValue(certArray, cfCert); + CFReleaseNull(cfCert); + CFReleaseNull(certData); + cert=cert->next; + } + + return certArray; + +out: + CFReleaseNull(cfCert); + CFReleaseNull(certData); + CFReleaseNull(certArray); + return NULL; +} + +int +tls_verify_peer_cert(SSLContext *ctx) +{ + int err; + const SSLCertificate *certs; + + certs = tls_handshake_get_peer_certificates(ctx->hdsk); + CFReleaseNull(ctx->peerCert); + ctx->peerCert = tls_get_peer_certs(certs); + + err = sslVerifyCertChain(ctx, ctx->peerCert, true); + tls_handshake_trust_t trust; + switch (err) { + case errSecSuccess: + trust = tls_handshake_trust_ok; + break; + case errSSLUnknownRootCert: + case errSSLNoRootCert: + trust = tls_handshake_trust_unknown_root; + break; + case errSSLCertExpired: + case errSSLCertNotYetValid: + trust = tls_handshake_trust_cert_expired; + break; + case errSSLXCertChainInvalid: + default: + trust = tls_handshake_trust_cert_invalid; + break; + } + + tls_handshake_set_peer_trust(ctx->hdsk, trust); + + if(err) + goto out; + + /* Set the public key */ + tls_set_peer_pubkey(ctx->hdsk, certs); + + /* Now that cert verification is done, update context state */ + /* (this code was formerly in SSLProcessHandshakeMessage, */ + /* directly after the return from SSLProcessCertificate) */ + if(ctx->protocolSide == kSSLServerSide) { + /* + * Schedule return to the caller to verify the client's identity. + * Note that an error during processing will cause early + * termination of the handshake. + */ + if (ctx->breakOnClientAuth) { + err = errSSLClientAuthCompleted; + } + } else { + /* + * Schedule return to the caller to verify the server's identity. + * Note that an error during processing will cause early + * termination of the handshake. + */ + if (ctx->breakOnServerAuth) { + err = errSSLServerAuthCompleted; + } + } + +out: + + return err; +} + +/* + * After ciphersuite negotiation is complete, verify that we have + * the capability of actually performing the selected cipher. + * Currently we just verify that we have a cert and private signing + * key, if needed, and that the signing key's algorithm matches the + * expected key exchange method. + * + * This is currently called from FindCipherSpec(), after it sets + * ctx->selectedCipherSpec to a (supposedly) valid value, and from + * sslBuildCipherSpecArray(), in server mode (pre-negotiation) only. + */ + +#if 0 +OSStatus sslVerifySelectedCipher(SSLContext *ctx) +{ + + if(ctx->protocolSide == kSSLClientSide) { + return errSecSuccess; + } +#if SSL_PAC_SERVER_ENABLE + if((ctx->masterSecretCallback != NULL) && + (ctx->sessionTicket.data != NULL)) { + /* EAP via PAC resumption; we can do it */ + return errSecSuccess; + } +#endif /* SSL_PAC_SERVER_ENABLE */ + + CFIndex requireAlg; + switch (ctx->selectedCipherSpecParams.keyExchangeMethod) { + case SSL_RSA: + case SSL_RSA_EXPORT: + case SSL_DH_RSA: + case SSL_DH_RSA_EXPORT: + case SSL_DHE_RSA: + case SSL_DHE_RSA_EXPORT: + requireAlg = kSecRSAAlgorithmID; + break; + case SSL_DHE_DSS: + case SSL_DHE_DSS_EXPORT: + case SSL_DH_DSS: + case SSL_DH_DSS_EXPORT: + requireAlg = kSecDSAAlgorithmID; + break; + case SSL_DH_anon: + case SSL_DH_anon_EXPORT: + case TLS_PSK: + requireAlg = kSecNullAlgorithmID; /* no signing key */ + break; + /* + * When SSL_ECDSA_SERVER is true and we support ECDSA on the server side, + * we'll need to add some logic here... + */ +#if SSL_ECDSA_SERVER + case SSL_ECDHE_ECDSA: + case SSL_ECDHE_RSA: + case SSL_ECDH_ECDSA: + case SSL_ECDH_RSA: + case SSL_ECDH_anon: + requireAlg = kSecECDSAAlgorithmID; + break; +#endif + + default: + /* needs update per cipherSpecs.c */ + assert(0); + sslErrorLog("sslVerifySelectedCipher: unknown key exchange method\n"); + return errSSLInternal; + } + + if(requireAlg == kSecNullAlgorithmID) { + return errSecSuccess; + } + + /* private signing key required */ + if(ctx->signingPrivKeyRef == NULL) { + sslErrorLog("sslVerifySelectedCipher: no signing key\n"); + return errSSLBadConfiguration; + } + + /* Check the alg of our signing key. */ + CFIndex keyAlg = sslPrivKeyGetAlgorithmID(ctx->signingPrivKeyRef); + if (requireAlg != keyAlg) { + sslErrorLog("sslVerifySelectedCipher: signing key alg mismatch\n"); + return errSSLBadConfiguration; + } + + return errSecSuccess; +} + +#endif diff --git a/Security/libsecurity_ssl/lib/sslCrypto.h b/Security/libsecurity_ssl/lib/sslCrypto.h new file mode 100644 index 00000000..f5a4c1b2 --- /dev/null +++ b/Security/libsecurity_ssl/lib/sslCrypto.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2006-2008,2010-2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * sslCrypto.h - interface between SSL and crypto libraries + */ + +#ifndef _SSL_CRYPTO_H_ +#define _SSL_CRYPTO_H_ 1 + +#include "ssl.h" +#include "sslContext.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef NDEBUG +extern void stPrintCdsaError(const char *op, OSStatus crtn); +#else +#define stPrintCdsaError(o, cr) +#endif + +/* + * Get algorithm id for a SSLPubKey object. + */ +CFIndex sslPubKeyGetAlgorithmID(SecKeyRef pubKey); + +/* + * Get algorithm id for a SSLPrivKey object. + */ +CFIndex sslPrivKeyGetAlgorithmID(SecKeyRef privKey); + +/* + * Create a new SecTrust object and return it. + */ +OSStatus +sslCreateSecTrust( + SSLContext *ctx, + CFArrayRef certChain, + bool arePeerCerts, + SecTrustRef *trust); /* RETURNED */ + +OSStatus sslVerifySelectedCipher( + SSLContext *ctx); + +/* Convert DER certs to SecCertificateRefs */ +CFArrayRef tls_get_peer_certs(const SSLCertificate *certs); + +/* + * Verify the peer cert chain. + */ +int tls_verify_peer_cert(SSLContext *ctx); + + +# +#ifdef __cplusplus +} +#endif + + +#endif /* _SSL_CRYPTO_H_ */ diff --git a/libsecurity_ssl/lib/sslDebug.h b/Security/libsecurity_ssl/lib/sslDebug.h similarity index 97% rename from libsecurity_ssl/lib/sslDebug.h rename to Security/libsecurity_ssl/lib/sslDebug.h index 4923eec2..b42e4c01 100644 --- a/libsecurity_ssl/lib/sslDebug.h +++ b/Security/libsecurity_ssl/lib/sslDebug.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2000-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2005-2007,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/sslDigests.c b/Security/libsecurity_ssl/lib/sslDigests.c similarity index 96% rename from libsecurity_ssl/lib/sslDigests.c rename to Security/libsecurity_ssl/lib/sslDigests.c index 9531f5b9..45ba61fd 100644 --- a/libsecurity_ssl/lib/sslDigests.c +++ b/Security/libsecurity_ssl/lib/sslDigests.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2000-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2005-2007,2010-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/sslDigests.h b/Security/libsecurity_ssl/lib/sslDigests.h similarity index 93% rename from libsecurity_ssl/lib/sslDigests.h rename to Security/libsecurity_ssl/lib/sslDigests.h index e2994951..203bc56b 100644 --- a/libsecurity_ssl/lib/sslDigests.h +++ b/Security/libsecurity_ssl/lib/sslDigests.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2007,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/sslHandshake.h b/Security/libsecurity_ssl/lib/sslHandshake.h similarity index 94% rename from libsecurity_ssl/lib/sslHandshake.h rename to Security/libsecurity_ssl/lib/sslHandshake.h index 2a36f166..dd296557 100644 --- a/libsecurity_ssl/lib/sslHandshake.h +++ b/Security/libsecurity_ssl/lib/sslHandshake.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2005-2007,2010-2013 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). @@ -41,7 +41,8 @@ typedef enum SSL_HdskServerHelloDone = 14, SSL_HdskCertVerify = 15, SSL_HdskClientKeyExchange = 16, - SSL_HdskFinished = 20 + SSL_HdskFinished = 20, + SSL_HdskNPNEncryptedExtension = 67 } SSLHandshakeType; /* Hello Extensions per RFC 3546 */ @@ -68,7 +69,13 @@ typedef enum * This one is suggested but not formally defined in * I.D.salowey-tls-ticket-07 */ - SSL_HE_SessionTicket = 35 + SSL_HE_SessionTicket = 35, + + /* + * NPN support for SPDY + * WARNING: This is NOT an extension registered with the IANA + */ + SSL_HE_NPN = 13172 } SSLHelloExtensionType; /* SSL_HE_ServerName NameType values */ @@ -206,6 +213,8 @@ OSStatus SSLProcessFinished(SSLBuffer message, SSLContext *ctx); OSStatus SSLEncodeServerHelloDone(SSLRecord *helloDone, SSLContext *ctx); OSStatus SSLProcessServerHelloDone(SSLBuffer message, SSLContext *ctx); OSStatus SSLCalculateFinishedMessage(SSLBuffer finished, SSLBuffer shaMsgState, SSLBuffer md5MsgState, UInt32 senderID, SSLContext *ctx); +OSStatus SSLEncodeNPNEncryptedExtensionMessage(SSLRecord *rec, SSLContext *ctx); +OSStatus SSLProcessEncryptedExtension(SSLBuffer message, SSLContext *ctx); #ifdef __cplusplus } diff --git a/Security/libsecurity_ssl/lib/sslKeychain.c b/Security/libsecurity_ssl/lib/sslKeychain.c new file mode 100644 index 00000000..93dcee17 --- /dev/null +++ b/Security/libsecurity_ssl/lib/sslKeychain.c @@ -0,0 +1,236 @@ +/* + * Copyright (c) 1999-2001,2005-2008,2010-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * sslKeychain.c - Apple Keychain routines + */ + +#include "ssl.h" +#include "sslContext.h" +#include "sslMemory.h" + +#include "sslCrypto.h" +#include +#include +#include +#include +#include +#include +#include "utilities/SecCFRelease.h" + +#include "sslDebug.h" +#include "sslKeychain.h" +#include "sslUtils.h" +#include +#include + + +#include +#include +#include +#include + +#if TARGET_OS_IPHONE +#include +#endif + +/* Private Key operations */ +static +SecAsn1Oid oidForSSLHash(SSL_HashAlgorithm hash) +{ + switch (hash) { + case tls_hash_algorithm_SHA1: + return CSSMOID_SHA1WithRSA; + case tls_hash_algorithm_SHA256: + return CSSMOID_SHA256WithRSA; + case tls_hash_algorithm_SHA384: + return CSSMOID_SHA384WithRSA; + default: + break; + } + // Internal error + assert(0); + // This guarantee failure down the line + return CSSMOID_MD5WithRSA; +} + +static +int mySSLPrivKeyRSA_sign(void *key, tls_hash_algorithm hash, const uint8_t *plaintext, size_t plaintextLen, uint8_t *sig, size_t *sigLen) +{ + SecKeyRef keyRef = key; + + if(hash == tls_hash_algorithm_None) { + return SecKeyRawSign(keyRef, kSecPaddingPKCS1, plaintext, plaintextLen, sig, sigLen); + } else { + SecAsn1AlgId algId; + algId.algorithm = oidForSSLHash(hash); + return SecKeySignDigest(keyRef, &algId, plaintext, plaintextLen, sig, sigLen); + } +} + +static +int mySSLPrivKeyRSA_decrypt(void *key, const uint8_t *ciphertext, size_t ciphertextLen, uint8_t *plaintext, size_t *plaintextLen) +{ + SecKeyRef keyRef = key; + + return SecKeyDecrypt(keyRef, kSecPaddingPKCS1, ciphertext, ciphertextLen, plaintext, plaintextLen); +} + +void sslFreePrivKey(tls_private_key_t *sslPrivKey) +{ + assert(sslPrivKey); + + if(*sslPrivKey) { + CFReleaseSafe(tls_private_key_get_context(*sslPrivKey)); + tls_private_key_destroy(*sslPrivKey); + *sslPrivKey = NULL; + } +} + +OSStatus +parseIncomingCerts( + SSLContext *ctx, + CFArrayRef certs, + SSLCertificate **destCertChain, /* &ctx->{localCertChain,encryptCertChain} */ + tls_private_key_t *sslPrivKey) /* &ctx->signingPrivKeyRef, etc. */ +{ + OSStatus ortn; + CFIndex ix, numCerts; + SecIdentityRef identity; + SSLCertificate *certChain = NULL; /* Retained */ + SecCertificateRef leafCert = NULL; /* Retained */ + SecKeyRef privKey = NULL; /* Retained */ + + assert(ctx != NULL); + assert(destCertChain != NULL); /* though its referent may be NULL */ + assert(sslPrivKey != NULL); + + if (certs == NULL) { + sslErrorLog("parseIncomingCerts: NULL incoming cert array\n"); + ortn = errSSLBadCert; + goto errOut; + } + numCerts = CFArrayGetCount(certs); + if (numCerts == 0) { + sslErrorLog("parseIncomingCerts: empty incoming cert array\n"); + ortn = errSSLBadCert; + goto errOut; + } + + certChain=sslMalloc(numCerts*sizeof(SSLCertificate)); + if (!certChain) { + ortn = errSecAllocate; + goto errOut; + } + + /* + * Certs[0] is an SecIdentityRef from which we extract subject cert, + * privKey, pubKey. + * + * 1. ensure the first element is a SecIdentityRef. + */ + identity = (SecIdentityRef)CFArrayGetValueAtIndex(certs, 0); + if (identity == NULL) { + sslErrorLog("parseIncomingCerts: bad cert array (1)\n"); + ortn = errSecParam; + goto errOut; + } + if (CFGetTypeID(identity) != SecIdentityGetTypeID()) { + sslErrorLog("parseIncomingCerts: bad cert array (2)\n"); + ortn = errSecParam; + goto errOut; + } + + /* + * 2. Extract cert, keys and convert to local format. + */ + ortn = SecIdentityCopyCertificate(identity, &leafCert); + if (ortn) { + sslErrorLog("parseIncomingCerts: bad cert array (3)\n"); + goto errOut; + } + + /* Fetch private key from identity */ + ortn = SecIdentityCopyPrivateKey(identity, &privKey); + if (ortn) { + sslErrorLog("parseIncomingCerts: SecIdentityCopyPrivateKey err %d\n", + (int)ortn); + goto errOut; + } + + /* Convert the input array of SecIdentityRef at the start to an array of + all certificates. */ + + certChain[0].derCert.data = (uint8_t *)SecCertificateGetBytePtr(leafCert); + certChain[0].derCert.length = SecCertificateGetLength(leafCert); + certChain[0].next = NULL; + + for (ix = 1; ix < numCerts; ++ix) { + SecCertificateRef intermediate = + (SecCertificateRef)CFArrayGetValueAtIndex(certs, ix); + if (intermediate == NULL) { + sslErrorLog("parseIncomingCerts: bad cert array (5)\n"); + ortn = errSecParam; + goto errOut; + } + if (CFGetTypeID(intermediate) != SecCertificateGetTypeID()) { + sslErrorLog("parseIncomingCerts: bad cert array (6)\n"); + ortn = errSecParam; + goto errOut; + } + + certChain[ix].derCert.data = (uint8_t *)SecCertificateGetBytePtr(intermediate); + certChain[ix].derCert.length = SecCertificateGetLength(intermediate); + certChain[ix].next = NULL; + certChain[ix-1].next = &certChain[ix]; + + } + + if(sslPrivKeyGetAlgorithmID(privKey)!=kSecRSAAlgorithmID) { + ortn = errSecParam; + goto errOut; + } + + sslFreePrivKey(sslPrivKey); + *sslPrivKey = tls_private_key_rsa_create(privKey, SecKeyGetBlockSize(privKey), mySSLPrivKeyRSA_sign, mySSLPrivKeyRSA_decrypt); + if(*sslPrivKey) + ortn = errSecSuccess; + else + ortn = errSecAllocate; + + /* SUCCESS */ +errOut: + CFReleaseSafe(leafCert); + + sslFree(*destCertChain); + + if (ortn) { + free(certChain); + CFReleaseSafe(privKey); + *destCertChain = NULL; + } else { + *destCertChain = certChain; + } + + return ortn; +} diff --git a/Security/libsecurity_ssl/lib/sslKeychain.h b/Security/libsecurity_ssl/lib/sslKeychain.h new file mode 100644 index 00000000..ec4c4792 --- /dev/null +++ b/Security/libsecurity_ssl/lib/sslKeychain.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1999-2001,2005-2007,2010-2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * sslKeychain.h - Apple Keychain routines + */ + +#ifndef _SSL_KEYCHAIN_H_ +#define _SSL_KEYCHAIN_H_ + + +#include "sslContext.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Free the tls_private_key_t struct and associated SecKeyRef context that were created by parseIncomingCerts */ +void sslFreePrivKey(tls_private_key_t *sslPrivKey); + +/* Create a tls_private_key_t struct and SSLCertificate list, from a CFArray */ +OSStatus +parseIncomingCerts( + SSLContext *ctx, + CFArrayRef certs, + SSLCertificate **destCertChain,/* &ctx->{localCertChain,encryptCertChain} */ + tls_private_key_t *privKeyRef); /* &ctx->signingPrivKeyRef, etc. */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SSL_KEYCHAIN_H_ */ diff --git a/libsecurity_ssl/lib/sslMemory.c b/Security/libsecurity_ssl/lib/sslMemory.c similarity index 98% rename from libsecurity_ssl/lib/sslMemory.c rename to Security/libsecurity_ssl/lib/sslMemory.c index 5e88deae..831b8861 100644 --- a/libsecurity_ssl/lib/sslMemory.c +++ b/Security/libsecurity_ssl/lib/sslMemory.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2007,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/sslMemory.h b/Security/libsecurity_ssl/lib/sslMemory.h similarity index 95% rename from libsecurity_ssl/lib/sslMemory.h rename to Security/libsecurity_ssl/lib/sslMemory.h index 132670e8..563090a1 100644 --- a/libsecurity_ssl/lib/sslMemory.h +++ b/Security/libsecurity_ssl/lib/sslMemory.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2007,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/sslNullCipher.c b/Security/libsecurity_ssl/lib/sslNullCipher.c similarity index 94% rename from libsecurity_ssl/lib/sslNullCipher.c rename to Security/libsecurity_ssl/lib/sslNullCipher.c index 8c5bfa60..7c4cc7ad 100644 --- a/libsecurity_ssl/lib/sslNullCipher.c +++ b/Security/libsecurity_ssl/lib/sslNullCipher.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2000-2001,2005-2008,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2005-2008,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/sslPriv.h b/Security/libsecurity_ssl/lib/sslPriv.h similarity index 93% rename from libsecurity_ssl/lib/sslPriv.h rename to Security/libsecurity_ssl/lib/sslPriv.h index 444726ba..57edb371 100644 --- a/libsecurity_ssl/lib/sslPriv.h +++ b/Security/libsecurity_ssl/lib/sslPriv.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2008,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2008,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/sslRand.c b/Security/libsecurity_ssl/lib/sslRand.c similarity index 95% rename from libsecurity_ssl/lib/sslRand.c rename to Security/libsecurity_ssl/lib/sslRand.c index 0c221c07..7ddbab64 100644 --- a/libsecurity_ssl/lib/sslRand.c +++ b/Security/libsecurity_ssl/lib/sslRand.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2008,2010-2011 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2008,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/sslRand.h b/Security/libsecurity_ssl/lib/sslRand.h similarity index 91% rename from libsecurity_ssl/lib/sslRand.h rename to Security/libsecurity_ssl/lib/sslRand.h index f2f15440..1753d655 100644 --- a/libsecurity_ssl/lib/sslRand.h +++ b/Security/libsecurity_ssl/lib/sslRand.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2000-2001,2005-2007,2010-2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2005-2007,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/Security/libsecurity_ssl/lib/sslRecord.c b/Security/libsecurity_ssl/lib/sslRecord.c new file mode 100644 index 00000000..55ea3ade --- /dev/null +++ b/Security/libsecurity_ssl/lib/sslRecord.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 1999-2001,2005-2007,2010-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * sslRecord.c - Encryption, decryption and MACing of data +*/ + +#include +#include "ssl.h" +#include "sslRecord.h" +#include "sslMemory.h" +#include "sslContext.h" +#include "sslAlertMessage.h" +#include "sslDebug.h" +#include "sslUtils.h" +#include "sslDigests.h" +#include "SSLRecordInternal.h" + +#include +#include + +#include + +/* + * Lots of servers fail to provide closure alerts when they disconnect. + * For now we'll just accept it as long as it occurs on a clean record boundary + * (and the handshake is complete). + */ +#define SSL_ALLOW_UNNOTICED_DISCONNECT 1 + + +static OSStatus errorTranslate(int recordErr) +{ + switch(recordErr) { + case errSecSuccess: + return errSecSuccess; + case errSSLRecordInternal: + return errSSLInternal; + case errSSLRecordWouldBlock: + return errSSLWouldBlock; + case errSSLRecordProtocol: + return errSSLProtocol; + case errSSLRecordNegotiation: + return errSSLNegotiation; + case errSSLRecordClosedAbort: + return errSSLClosedAbort; + case errSSLRecordConnectionRefused: + return errSSLConnectionRefused; + case errSSLRecordDecryptionFail: + return errSSLDecryptionFail; + case errSSLRecordBadRecordMac: + return errSSLBadRecordMac; + case errSSLRecordRecordOverflow: + return errSSLRecordOverflow; + case errSSLRecordUnexpectedRecord: + return errSSLUnexpectedRecord; + default: + sslErrorLog("unknown error code returned in sslErrorTranslate: %d\n", recordErr); + return recordErr; + } +} + +/* SSLWriteRecord + * Attempt to encrypt and queue an SSL record. + */ +OSStatus +SSLWriteRecord(SSLRecord rec, SSLContext *ctx) +{ + OSStatus err; + + err=errorTranslate(ctx->recFuncs->write(ctx->recCtx, rec)); + + switch(err) { + case errSecSuccess: + break; + default: + sslErrorLog("unexpected error code returned in SSLWriteRecord: %d\n", (int)err); + break; + } + + return err; +} + +/* SSLFreeRecord + * Free a record returned by SSLReadRecord. + */ +OSStatus +SSLFreeRecord(SSLRecord rec, SSLContext *ctx) +{ + return ctx->recFuncs->free(ctx->recCtx, rec); +} + +/* SSLReadRecord + * Attempt to read & decrypt an SSL record. + * Record content should be freed using SSLFreeRecord + */ +OSStatus +SSLReadRecord(SSLRecord *rec, SSLContext *ctx) +{ + return errorTranslate(ctx->recFuncs->read(ctx->recCtx, rec)); +} + +OSStatus SSLServiceWriteQueue(SSLContext *ctx) +{ + return errorTranslate(ctx->recFuncs->serviceWriteQueue(ctx->recCtx)); +} diff --git a/libsecurity_ssl/lib/sslRecord.h b/Security/libsecurity_ssl/lib/sslRecord.h similarity index 93% rename from libsecurity_ssl/lib/sslRecord.h rename to Security/libsecurity_ssl/lib/sslRecord.h index 6f468074..8cc6ccbf 100644 --- a/libsecurity_ssl/lib/sslRecord.h +++ b/Security/libsecurity_ssl/lib/sslRecord.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2000-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2005-2007,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/sslSession.c b/Security/libsecurity_ssl/lib/sslSession.c similarity index 95% rename from libsecurity_ssl/lib/sslSession.c rename to Security/libsecurity_ssl/lib/sslSession.c index 5d527f5c..61166182 100644 --- a/libsecurity_ssl/lib/sslSession.c +++ b/Security/libsecurity_ssl/lib/sslSession.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2000-2001,2005-2008,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2005-2008,2010-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -58,8 +58,8 @@ typedef struct OSStatus SSLAddSessionData(const SSLContext *ctx) { OSStatus err; - size_t sessionIDLen; - SSLBuffer sessionID; + size_t sessionDataLen; + SSLBuffer sessionData; ResumableSession *session; size_t certCount; #ifdef USE_SSLCERTIFICATE @@ -74,13 +74,13 @@ SSLAddSessionData(const SSLContext *ctx) if (ctx->peerID.data == 0) return errSSLSessionNotFound; - sessionIDLen = offsetof(ResumableSession, certs); + sessionDataLen = offsetof(ResumableSession, certs); #ifdef USE_SSLCERTIFICATE cert = ctx->peerCert; certCount = 0; while (cert) { ++certCount; - sessionIDLen += 4 + cert->derCert.length; + sessionDataLen += 4 + cert->derCert.length; cert = cert->next; } #else @@ -106,8 +106,8 @@ SSLAddSessionData(const SSLContext *ctx) session->sessionIDLen = ctx->sessionID.length; memcpy(session->sessionID, ctx->sessionID.data, session->sessionIDLen); session->protocolVersion = ctx->negProtocolVersion; - session->cipherSuite = ctx->selectedCipher; - memcpy(session->masterSecret, ctx->masterSecret, 48); + session->cipherSuite = tls_handshake_get_cipherspec(ctx->hdsk); + memcpy(session->masterSecret, tls_handshake_get_master_secret(ctx->hdsk), 48); session->certCount = certCount; session->padding = 0; @@ -295,7 +295,7 @@ SSLInstallSessionFromData(const SSLBuffer sessionData, SSLContext *ctx) if ((err = FindCipherSpec(ctx)) != 0) { return err; } - memcpy(ctx->masterSecret, session->masterSecret, 48); + memcpy(tls_handshake_get->masterSecret, session->masterSecret, 48); storedCertProgress = session->certs; certCount = session->certCount; diff --git a/libsecurity_ssl/lib/sslSession.h b/Security/libsecurity_ssl/lib/sslSession.h similarity index 94% rename from libsecurity_ssl/lib/sslSession.h rename to Security/libsecurity_ssl/lib/sslSession.h index b809aa2b..c443d75d 100644 --- a/libsecurity_ssl/lib/sslSession.h +++ b/Security/libsecurity_ssl/lib/sslSession.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2000-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2005-2007,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/Security/libsecurity_ssl/lib/sslTransport.c b/Security/libsecurity_ssl/lib/sslTransport.c new file mode 100644 index 00000000..c7627b3c --- /dev/null +++ b/Security/libsecurity_ssl/lib/sslTransport.c @@ -0,0 +1,450 @@ +/* + * Copyright (c) 1999-2001,2005-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@ + */ + +/* + * sslTransport.c - SSL transport layer + */ + +#include "ssl.h" +#include "sslMemory.h" +#include "sslContext.h" +#include "sslRecord.h" +#include "sslAlertMessage.h" +#include "sslSession.h" +#include "sslDebug.h" +#include "sslCipherSpecs.h" +#include "sslUtils.h" + +#include +#include + +#include + +#ifndef NDEBUG +static inline void sslIoTrace( + SSLContext *ctx, + const char *op, + size_t req, + size_t moved, + OSStatus stat) +{ + sslLogRecordIo("[%p] ===%s: req %4lu moved %4lu status %d", + ctx, op, req, moved, (int)stat); +} +#else +#define sslIoTrace(ctx, op, req, moved, stat) +#endif /* NDEBUG */ + +extern int kSplitDefaultValue; + +static OSStatus SSLProcessProtocolMessage(SSLRecord *rec, SSLContext *ctx); +static OSStatus SSLHandshakeProceed(SSLContext *ctx); +//static OSStatus SSLInitConnection(SSLContext *ctx); + +OSStatus +SSLWrite( + SSLContext *ctx, + const void * data, + size_t dataLength, + size_t *bytesWritten) /* RETURNED */ +{ + OSStatus err; + SSLRecord rec; + size_t dataLen, processed; + + sslLogRecordIo("[%p] SSLWrite top", ctx); + if((ctx == NULL) || (bytesWritten == NULL)) { + return errSecParam; + } + dataLen = dataLength; + processed = 0; /* Initialize in case we return with errSSLWouldBlock */ + *bytesWritten = 0; + + switch(ctx->state) { + case SSL_HdskStateGracefulClose: + err = errSSLClosedGraceful; + goto abort; + case SSL_HdskStateErrorClose: + err = errSSLClosedAbort; + goto abort; + case SSL_HdskStateReady: + break; + case SSL_HdskStateUninit: + /* not ready for I/O, and handshake not in progress */ + sslIoTrace(ctx, "SSLWrite(1)", dataLength, 0, errSecBadReq); + return errSecBadReq; + default: + /* handshake in progress or done. Will call SSLHandshakeProceed below if necessary */ + break; + } + + /* First, we have to wait until the session is ready to send data, + so the encryption keys and such have been established. */ + err = errSecSuccess; + while (!(ctx->writeCipher_ready)) + { if ((err = SSLHandshakeProceed(ctx)) != 0) + goto exit; + } + + /* Attempt to empty the write queue before queueing more data */ + if ((err = SSLServiceWriteQueue(ctx)) != 0) + goto abort; + + processed = 0; + + /* Skip empty writes, fragmentation is done at the coreTLS layer */ + if(dataLen) { + rec.contentType = SSL_RecordTypeAppData; + rec.protocolVersion = ctx->negProtocolVersion; + rec.contents.data = ((uint8_t *)data) + processed; + rec.contents.length = dataLen; + if ((err = SSLWriteRecord(rec, ctx)) != 0) + goto exit; + processed += rec.contents.length; + } + + /* All the data has been advanced to the write queue */ + *bytesWritten = processed; + if ((err = SSLServiceWriteQueue(ctx)) == 0) { + err = errSecSuccess; + } +exit: + switch(err) { + case errSecSuccess: + case errSSLWouldBlock: + case errSSLUnexpectedRecord: + case errSSLServerAuthCompleted: /* == errSSLClientAuthCompleted */ + case errSSLClientCertRequested: + case errSSLClosedGraceful: + break; + default: + sslErrorLog("SSLWrite: going to state errorClose due to err %d\n", + (int)err); + SSLChangeHdskState(ctx, SSL_HdskStateErrorClose); + break; + } +abort: + sslIoTrace(ctx, "SSLWrite(2)", dataLength, *bytesWritten, err); + return err; +} + +OSStatus +SSLRead ( + SSLContext *ctx, + void * data, + size_t dataLength, + size_t *processed) /* RETURNED */ +{ + OSStatus err; + uint8_t *charPtr; + size_t bufSize, remaining, count; + SSLRecord rec; + + sslLogRecordIo("[%p] SSLRead top (dataLength=%ld)", ctx, dataLength); + if((ctx == NULL) || (data == NULL) || (processed == NULL)) { + return errSecParam; + } + bufSize = dataLength; + *processed = 0; /* Initialize in case we return with errSSLWouldBlock */ + +readRetry: + /* first handle cases in which we know we're finished */ + switch(ctx->state) { + case SSL_HdskStateGracefulClose: + err = errSSLClosedGraceful; + goto abort; + case SSL_HdskStateErrorClose: + err = errSSLClosedAbort; + goto abort; + case SSL_HdskStateNoNotifyClose: + err = errSSLClosedNoNotify; + goto abort; + default: + break; + } + + /* First, we have to wait until the session is ready to receive data, + so the encryption keys and such have been established. */ + err = errSecSuccess; + while (ctx->readCipher_ready == 0) { + if ((err = SSLHandshakeProceed(ctx)) != 0) { + goto exit; + } + } + + /* Attempt to service the write queue */ + if ((err = SSLServiceWriteQueue(ctx)) != 0) { + if (err != errSSLWouldBlock) { + goto exit; + } + err = errSecSuccess; /* Write blocking shouldn't stop attempts to read */ + } + + remaining = bufSize; + charPtr = (uint8_t *)data; + if (ctx->receivedDataBuffer.data) + { count = ctx->receivedDataBuffer.length - ctx->receivedDataPos; + if (count > bufSize) + count = bufSize; + memcpy(data, ctx->receivedDataBuffer.data + ctx->receivedDataPos, count); + remaining -= count; + charPtr += count; + *processed += count; + ctx->receivedDataPos += count; + } + + assert(ctx->receivedDataPos <= ctx->receivedDataBuffer.length); + assert(*processed + remaining == bufSize); + assert(charPtr == ((uint8_t *)data) + *processed); + + if (ctx->receivedDataBuffer.data != 0 && + ctx->receivedDataPos >= ctx->receivedDataBuffer.length) + { SSLFreeBuffer(&ctx->receivedDataBuffer); + ctx->receivedDataBuffer.data = 0; + ctx->receivedDataPos = 0; + } + + /* + * This while statement causes a hang when using nonblocking low-level I/O! + while (remaining > 0 && ctx->state != SSL_HdskStateGracefulClose) + ..what we really have to do is just return as soon as we read one + record. A performance hit in the nonblocking case, but that is + the only way this code can work in both modes... + */ + if (remaining > 0 && ctx->state != SSL_HdskStateGracefulClose) + { assert(ctx->receivedDataBuffer.data == 0); + if ((err = SSLReadRecord(&rec, ctx)) != 0) { + goto exit; + } + if (rec.contentType == SSL_RecordTypeAppData || + rec.contentType == SSL_RecordTypeV2_0) + { if (rec.contents.length <= remaining) + { memcpy(charPtr, rec.contents.data, rec.contents.length); + remaining -= rec.contents.length; + charPtr += rec.contents.length; + *processed += rec.contents.length; + { + if ((err = SSLFreeRecord(rec, ctx))) { + goto exit; + } + } + } + else + { memcpy(charPtr, rec.contents.data, remaining); + charPtr += remaining; + *processed += remaining; + ctx->receivedDataBuffer = rec.contents; + ctx->receivedDataPos = remaining; + remaining = 0; + } + } + else { + if ((err = SSLProcessProtocolMessage(&rec, ctx)) != 0) { + /* This may not make much sense, but this is required so that we + process the write queue. This replicate exactly the behavior + before the coreTLS adoption */ + if(err == errSSLClosedGraceful) { + err = SSLClose(ctx); + } else { + goto exit; + } + } + if ((err = SSLFreeRecord(rec, ctx))) { + goto exit; + } + } + } + + err = errSecSuccess; + +exit: + /* test for renegotiate: loop until something useful happens */ + if(((err == errSecSuccess) && (*processed == 0) && dataLength) || (err == errSSLUnexpectedRecord)) { + sslLogNegotiateDebug("SSLRead recursion"); + goto readRetry; + } + /* shut down on serious errors */ + switch(err) { + case errSecSuccess: + case errSSLWouldBlock: + case errSSLUnexpectedRecord: + case errSSLServerAuthCompleted: /* == errSSLClientAuthCompleted */ + case errSSLClientCertRequested: + case errSSLClosedGraceful: + case errSSLClosedNoNotify: + break; + default: + sslErrorLog("SSLRead: going to state errorClose due to err %d\n", + (int)err); + SSLChangeHdskState(ctx, SSL_HdskStateErrorClose); + break; + } +abort: + sslIoTrace(ctx, "SSLRead returns", dataLength, *processed, err); + return err; +} + +#if SSL_DEBUG +#include "sslCrypto.h" +#endif + +OSStatus +SSLHandshake(SSLContext *ctx) +{ + OSStatus err; + + if(ctx == NULL) { + return errSecParam; + } + if (ctx->state == SSL_HdskStateGracefulClose) + return errSSLClosedGraceful; + if (ctx->state == SSL_HdskStateErrorClose) + return errSSLClosedAbort; + + if(ctx->validCipherSuites == NULL) { + /* build list of legal cipherSpecs */ + err = sslBuildCipherSuiteArray(ctx); + if(err) { + return err; + } + } + + err = errSecSuccess; + + if(ctx->isDTLS && ctx->timeout_deadline) { + CFAbsoluteTime current = CFAbsoluteTimeGetCurrent(); + + if (ctx->timeout_deadlinehdsk); + if(err) { + return err; + } + } + } + + while (ctx->readCipher_ready == 0 || ctx->writeCipher_ready == 0) + { + err = SSLHandshakeProceed(ctx); + if((err != 0) && (err != errSSLUnexpectedRecord)) + return err; + } + + /* one more flush at completion of successful handshake */ + if ((err = SSLServiceWriteQueue(ctx)) != 0) { + return err; + } + + return errSecSuccess; +} + + +static OSStatus +SSLHandshakeProceed(SSLContext *ctx) +{ + OSStatus err; + + + if(ctx->state==SSL_HdskStateUninit) { + /* If we are the client, we start the negotiation */ + if(ctx->protocolSide == kSSLClientSide) { + err = tls_handshake_negotiate(ctx->hdsk, &ctx->peerID); + if(err) + return err; + } + SSLChangeHdskState(ctx, SSL_HdskStatePending); + } + + if ((err = tls_handshake_continue(ctx->hdsk)) != 0) + return err; + + if ((err = SSLServiceWriteQueue(ctx)) != 0) + return err; + + SSLRecord rec; + + err = SSLReadRecord(&rec, ctx); + + if(!err) { + sslDebugLog("%p going to process a record (rec.len=%zd, ct=%d)\n", ctx, rec.contents.length, rec.contentType); + err = tls_handshake_process(ctx->hdsk, rec.contents, rec.contentType); + sslDebugLog("%p processed a record (rec.len=%zd, ct=%d, err=%d)\n", ctx, rec.contents.length, rec.contentType, (int)err); + SSLFreeRecord(rec, ctx); + } else if(err!=errSSLWouldBlock) { + sslDebugLog("%p Read error err=%d\n\n", ctx, (int)err); + } + + return err; +} + +static OSStatus +SSLProcessProtocolMessage(SSLRecord *rec, SSLContext *ctx) +{ + return tls_handshake_process(ctx->hdsk, rec->contents, rec->contentType); +} + +OSStatus +SSLClose(SSLContext *ctx) +{ + OSStatus err = errSecSuccess; + + sslHdskStateDebug("SSLClose"); + if(ctx == NULL) { + return errSecParam; + } + + err = tls_handshake_close(ctx->hdsk); + + if (err == 0) + err = SSLServiceWriteQueue(ctx); + + SSLChangeHdskState(ctx, SSL_HdskStateGracefulClose); + if (err == errSecIO) + err = errSecSuccess; /* Ignore errors related to closed streams */ + return err; +} + +/* + * Determine how much data the client can be guaranteed to + * obtain via SSLRead() without blocking or causing any low-level + * read operations to occur. + * + * Implemented here because the relevant info in SSLContext (receivedDataBuffer + * and receivedDataPos) are only used in this file. + */ +OSStatus +SSLGetBufferedReadSize(SSLContextRef ctx, + size_t *bufSize) /* RETURNED */ +{ + if(ctx == NULL) { + return errSecParam; + } + if(ctx->receivedDataBuffer.data == NULL) { + *bufSize = 0; + } + else { + assert(ctx->receivedDataBuffer.length >= ctx->receivedDataPos); + *bufSize = ctx->receivedDataBuffer.length - ctx->receivedDataPos; + } + return errSecSuccess; +} diff --git a/libsecurity_ssl/lib/sslTypes.h b/Security/libsecurity_ssl/lib/sslTypes.h similarity index 89% rename from libsecurity_ssl/lib/sslTypes.h rename to Security/libsecurity_ssl/lib/sslTypes.h index 33fb5902..d3a56ba8 100644 --- a/libsecurity_ssl/lib/sslTypes.h +++ b/Security/libsecurity_ssl/lib/sslTypes.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2011 Apple Inc. All Rights Reserved. + * Copyright (c) 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, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -34,6 +34,8 @@ #include #include +#include + enum { errSSLRecordInternal = -10000, errSSLRecordWouldBlock = -10001, @@ -74,15 +76,22 @@ enum SSL_RecordTypeV3_Largest = 23 }; +typedef enum +{ + kSSLRecordOptionSendOneByteRecord = 0, +} SSLRecordOption; /* * This is the buffer type used internally. */ -typedef struct +typedef tls_buffer SSLBuffer; + +/* +struct { size_t length; uint8_t *data; } SSLBuffer; - +*/ typedef struct { @@ -136,9 +145,14 @@ typedef int typedef int (*SSLRecordServiceWriteQueueFunc) (SSLRecordContextRef ref); +typedef int +(*SSLRecordSetOptionFunc) (SSLRecordContextRef ref, + SSLRecordOption option, + bool value); struct SSLRecordFuncs -{ SSLRecordReadFunc read; +{ + SSLRecordReadFunc read; SSLRecordWriteFunc write; SSLRecordInitPendingCiphersFunc initPendingCiphers; SSLRecordAdvanceWriteCipherFunc advanceWriteCipher; @@ -147,6 +161,7 @@ struct SSLRecordFuncs SSLRecordSetProtocolVersionFunc setProtocolVersion; SSLRecordFreeFunc free; SSLRecordServiceWriteQueueFunc serviceWriteQueue; + SSLRecordSetOptionFunc setOption; }; #endif /* _SSLTYPES_H_ */ diff --git a/libsecurity_ssl/lib/sslUtils.c b/Security/libsecurity_ssl/lib/sslUtils.c similarity index 97% rename from libsecurity_ssl/lib/sslUtils.c rename to Security/libsecurity_ssl/lib/sslUtils.c index 5a262596..0390dc78 100644 --- a/libsecurity_ssl/lib/sslUtils.c +++ b/Security/libsecurity_ssl/lib/sslUtils.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2008,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2008,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/sslUtils.h b/Security/libsecurity_ssl/lib/sslUtils.h similarity index 95% rename from libsecurity_ssl/lib/sslUtils.h rename to Security/libsecurity_ssl/lib/sslUtils.h index 40501aa6..992b6ffd 100644 --- a/libsecurity_ssl/lib/sslUtils.h +++ b/Security/libsecurity_ssl/lib/sslUtils.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2000-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2005-2007,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/symCipher.c b/Security/libsecurity_ssl/lib/symCipher.c similarity index 99% rename from libsecurity_ssl/lib/symCipher.c rename to Security/libsecurity_ssl/lib/symCipher.c index aab1ec05..5907da7f 100644 --- a/libsecurity_ssl/lib/symCipher.c +++ b/Security/libsecurity_ssl/lib/symCipher.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2008,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2008,2010-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/symCipher.h b/Security/libsecurity_ssl/lib/symCipher.h similarity index 98% rename from libsecurity_ssl/lib/symCipher.h rename to Security/libsecurity_ssl/lib/symCipher.h index 7fb0f61c..01016edf 100644 --- a/libsecurity_ssl/lib/symCipher.h +++ b/Security/libsecurity_ssl/lib/symCipher.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2008,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2008,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/symCipherParams.c b/Security/libsecurity_ssl/lib/symCipherParams.c similarity index 96% rename from libsecurity_ssl/lib/symCipherParams.c rename to Security/libsecurity_ssl/lib/symCipherParams.c index 1dfa43b7..688cf7b3 100644 --- a/libsecurity_ssl/lib/symCipherParams.c +++ b/Security/libsecurity_ssl/lib/symCipherParams.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2008,2010-2011 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2008,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/Security/libsecurity_ssl/lib/tlsCallbacks.c b/Security/libsecurity_ssl/lib/tlsCallbacks.c new file mode 100644 index 00000000..a8c09103 --- /dev/null +++ b/Security/libsecurity_ssl/lib/tlsCallbacks.c @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include "tlsCallbacks.h" +#include "sslContext.h" +#include "sslCrypto.h" +#include "sslDebug.h" +#include "appleSession.h" +#include +#include +#include "utilities/SecCFRelease.h" + + +static +int tls_handshake_write_callback(tls_handshake_ctx_t ctx, const SSLBuffer data, uint8_t content_type) +{ + SSLContext *myCtx = (SSLContext *)ctx; + sslDebugLog("%p (rec.len=%zd, ct=%d, d[0]=%d)\n", myCtx, data.length, content_type, data.data[0]); + + SSLRecord rec; + + rec.contents=data; + rec.contentType=content_type; + + return myCtx->recFuncs->write(myCtx->recCtx,rec); +} + + +static int +tls_handshake_message_callback(tls_handshake_ctx_t ctx, tls_handshake_message_t event) +{ + SSLContext *myCtx = (SSLContext *)ctx; + const tls_buffer *npn_data; + + sslDebugLog("%p, message = %d\n", ctx, event); + + switch(event) { + case tls_handshake_message_certificate_request: + assert(myCtx->protocolSide == kSSLClientSide); + // Need to call this here, in case SetCertificate was already called. + myCtx->clientCertState = kSSLClientCertRequested; + myCtx->clientAuthTypes = tls_handshake_get_peer_acceptable_client_auth_type(myCtx->hdsk, &myCtx->numAuthTypes); + SSLUpdateNegotiatedClientAuthType(myCtx); + if (myCtx->breakOnCertRequest && (myCtx->localCert==NULL)) + { + myCtx->signalCertRequest = true; + return errSSLClientCertRequested; + } + break; + case tls_handshake_message_client_hello: + myCtx->peerSigAlgs = tls_handshake_get_peer_signature_algorithms(myCtx->hdsk, &myCtx->numPeerSigAlgs); + break; + case tls_handshake_message_server_hello: + npn_data = tls_handshake_get_peer_npn_data(myCtx->hdsk); + if(npn_data) + myCtx->npnFunc(myCtx, myCtx->npnFuncInfo, npn_data->data, npn_data->length); + myCtx->peerSigAlgs = tls_handshake_get_peer_signature_algorithms(myCtx->hdsk, &myCtx->numPeerSigAlgs); + break; + case tls_handshake_message_certificate: + return tls_verify_peer_cert(myCtx); + case tls_handshake_message_NPN_encrypted_extension: + npn_data = tls_handshake_get_peer_npn_data(myCtx->hdsk); + if(npn_data) + myCtx->npnFunc(myCtx, myCtx->npnFuncInfo, npn_data->data, npn_data->length); + break; + default: + break; + } + + return 0; +} + +static void +tls_handshake_ready_callback(tls_handshake_ctx_t ctx, bool write, bool ready) +{ + SSLContext *myCtx = (SSLContext *)ctx; + + sslDebugLog("%p %s ready=%d\n", myCtx, write?"write":"read", ready); + + if(write) { + myCtx->writeCipher_ready=ready?1:0; + } else { + myCtx->readCipher_ready=ready?1:0; + if(ready) { + SSLChangeHdskState(myCtx, SSL_HdskStateReady); + } else { + SSLChangeHdskState(myCtx, SSL_HdskStatePending); + } + } +} + +static int +tls_handshake_set_retransmit_timer_callback(tls_handshake_ctx_t ctx, int attempt) +{ + SSLContext *myCtx = (SSLContext *)ctx; + + sslDebugLog("%p attempt=%d\n", ctx, attempt); + + if(attempt) { + myCtx->timeout_deadline = CFAbsoluteTimeGetCurrent()+((1<<(attempt-1))*myCtx->timeout_duration); + } else { + myCtx->timeout_deadline = 0; // cancel the timeout + } + return 0; +} + +static int +tls_handshake_init_pending_cipher_callback(tls_handshake_ctx_t ctx, + uint16_t selectedCipher, + bool server, + SSLBuffer key) +{ + sslDebugLog("%p, cipher=%04x, server=%d\n", ctx, selectedCipher, server); + SSLContext *myCtx = (SSLContext *)ctx; + return myCtx->recFuncs->initPendingCiphers(myCtx->recCtx, selectedCipher, server, key); +} + +static int +tls_handshake_advance_write_callback(tls_handshake_ctx_t ctx) +{ + SSLContext *myCtx = (SSLContext *)ctx; + sslDebugLog("%p\n", myCtx); + //FIXME: need to filter on cipher too - require missing coretls ciphersuite header */ + bool split = (myCtx->oneByteRecordEnable && (myCtx->negProtocolVersion<=TLS_Version_1_0)); + myCtx->recFuncs->setOption(myCtx->recCtx, kSSLRecordOptionSendOneByteRecord, split); + return myCtx->recFuncs->advanceWriteCipher(myCtx->recCtx); +} + +static +int tls_handshake_rollback_write_callback(tls_handshake_ctx_t ctx) +{ + SSLContext *myCtx = (SSLContext *)ctx; + sslDebugLog("%p\n", myCtx); + return myCtx->recFuncs->rollbackWriteCipher(myCtx->recCtx); +} + +static +int tls_handshake_advance_read_cipher_callback(tls_handshake_ctx_t ctx) +{ + SSLContext *myCtx = (SSLContext *)ctx; + sslDebugLog("%p\n", myCtx); + return myCtx->recFuncs->advanceReadCipher(myCtx->recCtx); +} + +static +int tls_handshake_set_protocol_version_callback(tls_handshake_ctx_t ctx, + tls_protocol_version protocolVersion) +{ + SSLContext *myCtx = (SSLContext *)ctx; + //printf("%s: %p, pv=%04x\n", __FUNCTION__, ctx, protocolVersion); + myCtx->negProtocolVersion = protocolVersion; + return myCtx->recFuncs->setProtocolVersion(myCtx->recCtx, protocolVersion); +} + +static int +tls_handshake_save_session_data_callback(tls_handshake_ctx_t ctx, SSLBuffer sessionKey, SSLBuffer sessionData) +{ + sslDebugLog("%s: %p, key len=%zd, k[0]=%02x, data len=%zd\n", __FUNCTION__, (SSLContext *)ctx, sessionKey.length, sessionKey.data[0], sessionData.length); + return sslAddSession(sessionKey, sessionData, 0); +} + +static int +tls_handshake_load_session_data_callback(tls_handshake_ctx_t ctx, SSLBuffer sessionKey, SSLBuffer *sessionData) +{ + SSLContext *myCtx = (SSLContext *)ctx; + int err; + + SSLFreeBuffer(&myCtx->resumableSession); + err = sslCopySession(sessionKey, &myCtx->resumableSession); + + sslDebugLog("%p, key len=%zd, data len=%zd, err=%d\n", ctx, sessionKey.length, sessionData->length, err); + + *sessionData = myCtx->resumableSession; + + return err; +} + +static int +tls_handshake_delete_session_data_callback(tls_handshake_ctx_t ctx, SSLBuffer sessionKey) +{ + sslDebugLog("%p, key len=%zd k[0]=%02x\n", ctx, sessionKey.length, sessionKey.data[0]); + return sslDeleteSession(sessionKey); +} + +static int +tls_handshake_delete_all_sessions_callback(tls_handshake_ctx_t ctx) +{ + sslDebugLog("%p\n", ctx); + + return sslCleanupSession(); +} + +tls_handshake_callbacks_t tls_handshake_callbacks = { + .write = tls_handshake_write_callback, + .message = tls_handshake_message_callback, + .ready = tls_handshake_ready_callback, + .set_retransmit_timer = tls_handshake_set_retransmit_timer_callback, + .save_session_data = tls_handshake_save_session_data_callback, + .load_session_data = tls_handshake_load_session_data_callback, + .delete_session_data = tls_handshake_delete_session_data_callback, + .delete_all_sessions = tls_handshake_delete_all_sessions_callback, + .init_pending_cipher = tls_handshake_init_pending_cipher_callback, + .advance_write_cipher = tls_handshake_advance_write_callback, + .rollback_write_cipher = tls_handshake_rollback_write_callback, + .advance_read_cipher = tls_handshake_advance_read_cipher_callback, + .set_protocol_version = tls_handshake_set_protocol_version_callback, +}; + + diff --git a/Security/libsecurity_ssl/lib/tlsCallbacks.h b/Security/libsecurity_ssl/lib/tlsCallbacks.h new file mode 100644 index 00000000..edb30c82 --- /dev/null +++ b/Security/libsecurity_ssl/lib/tlsCallbacks.h @@ -0,0 +1,32 @@ +/* + * 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@ + */ + + +#ifndef __SECURITY_TLSCALLBACKS_H__ +#define __SECURITY_TLSCALLBACKS_H__ 1 + +#include + +extern tls_handshake_callbacks_t tls_handshake_callbacks; + +#endif diff --git a/libsecurity_ssl/lib/tls_digest.c b/Security/libsecurity_ssl/lib/tls_digest.c similarity index 99% rename from libsecurity_ssl/lib/tls_digest.c rename to Security/libsecurity_ssl/lib/tls_digest.c index 5d975425..56369e22 100644 --- a/libsecurity_ssl/lib/tls_digest.c +++ b/Security/libsecurity_ssl/lib/tls_digest.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2000-2001,2005-2007,2010-2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2005-2007,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/tls_digest.h b/Security/libsecurity_ssl/lib/tls_digest.h similarity index 96% rename from libsecurity_ssl/lib/tls_digest.h rename to Security/libsecurity_ssl/lib/tls_digest.h index b89e8471..0c88fcf1 100644 --- a/libsecurity_ssl/lib/tls_digest.h +++ b/Security/libsecurity_ssl/lib/tls_digest.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2007,2010-2011 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2001,2005-2007,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/tls_hashhmac.c b/Security/libsecurity_ssl/lib/tls_hashhmac.c similarity index 93% rename from libsecurity_ssl/lib/tls_hashhmac.c rename to Security/libsecurity_ssl/lib/tls_hashhmac.c index 37062986..26e7ce8c 100644 --- a/libsecurity_ssl/lib/tls_hashhmac.c +++ b/Security/libsecurity_ssl/lib/tls_hashhmac.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002,2005-2008,2010-2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2002,2005-2008,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/tls_hashhmac.h b/Security/libsecurity_ssl/lib/tls_hashhmac.h similarity index 95% rename from libsecurity_ssl/lib/tls_hashhmac.h rename to Security/libsecurity_ssl/lib/tls_hashhmac.h index 18ea9cc5..d0532e09 100644 --- a/libsecurity_ssl/lib/tls_hashhmac.h +++ b/Security/libsecurity_ssl/lib/tls_hashhmac.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002,2005-2007,2010-2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2002,2005-2007,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/tls_hmac.c b/Security/libsecurity_ssl/lib/tls_hmac.c similarity index 98% rename from libsecurity_ssl/lib/tls_hmac.c rename to Security/libsecurity_ssl/lib/tls_hmac.c index cb20a9e5..11662d8d 100644 --- a/libsecurity_ssl/lib/tls_hmac.c +++ b/Security/libsecurity_ssl/lib/tls_hmac.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002,2005-2008,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2002,2005-2008,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/lib/tls_hmac.h b/Security/libsecurity_ssl/lib/tls_hmac.h similarity index 96% rename from libsecurity_ssl/lib/tls_hmac.h rename to Security/libsecurity_ssl/lib/tls_hmac.h index c581b913..156923c5 100644 --- a/libsecurity_ssl/lib/tls_hmac.h +++ b/Security/libsecurity_ssl/lib/tls_hmac.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002,2005-2007,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2002,2005-2007,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/Security/libsecurity_ssl/lib/tls_record_internal.h b/Security/libsecurity_ssl/lib/tls_record_internal.h new file mode 100644 index 00000000..3f650840 --- /dev/null +++ b/Security/libsecurity_ssl/lib/tls_record_internal.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2002,2005-2007,2010-2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * tls_record.h - Declarations of record layer callout struct to provide indirect calls to + * SSLv3 and TLS routines. + */ + +#ifndef _TLS_RECORD_INTERNAL_H_ +#define _TLS_RECORD_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// #include "sslRecord.h" + +#include "sslTypes.h" +#include "cryptType.h" +#include "sslMemory.h" +#include "SSLRecordInternal.h" + +#include + +struct SSLRecordInternalContext; + +typedef struct WaitingRecord +{ struct WaitingRecord *next; + size_t sent; + /* + * These two fields replace a dynamically allocated SSLBuffer; + * the payload to write is contained in the variable-length + * array data[]. + */ + size_t length; + uint8_t data[1]; +} WaitingRecord; + + +struct SSLRecordInternalContext +{ + tls_record_t filter; + bool dtls; + + /* I/O */ + SSLIOReadFunc read; + SSLIOWriteFunc write; + SSLIOConnectionRef ioRef; + + /* buffering */ + SSLBuffer partialReadBuffer; + size_t amountRead; + + WaitingRecord *recordWriteQueue; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _TLS_SSL_H_ */ diff --git a/libsecurity_ssl/lib/tls_ssl.h b/Security/libsecurity_ssl/lib/tls_ssl.h similarity index 96% rename from libsecurity_ssl/lib/tls_ssl.h rename to Security/libsecurity_ssl/lib/tls_ssl.h index aa6f8aae..a2a1013c 100644 --- a/libsecurity_ssl/lib/tls_ssl.h +++ b/Security/libsecurity_ssl/lib/tls_ssl.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002,2005-2007,2010-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2002,2005-2007,2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/Security/libsecurity_ssl/libsecurity_ssl.xcodeproj/project.pbxproj b/Security/libsecurity_ssl/libsecurity_ssl.xcodeproj/project.pbxproj new file mode 100644 index 00000000..7fb87d53 --- /dev/null +++ b/Security/libsecurity_ssl/libsecurity_ssl.xcodeproj/project.pbxproj @@ -0,0 +1,938 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + 0C6C633A15D1BD4800BC68CD /* dtlsEcho */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 0C6C633B15D1BD4800BC68CD /* Build configuration list for PBXAggregateTarget "dtlsEcho" */; + buildPhases = ( + ); + dependencies = ( + 0C6C633F15D1BD4D00BC68CD /* PBXTargetDependency */, + 0C6C634115D1BD4E00BC68CD /* PBXTargetDependency */, + ); + name = dtlsEcho; + productName = dtlsEcho; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 0C03D65917DFD8C00087643B /* sslCipherSpecs.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA413615C75863002AEC4C /* sslCipherSpecs.c */; }; + 0C03D65B17DFE67E0087643B /* tlsCallbacks.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C03D65A17DFE67E0087643B /* tlsCallbacks.c */; }; + 0C0E0467162C9DF0009F7C71 /* ssl-46-SSLGetSupportedCiphers.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C0E0466162C9DF0009F7C71 /* ssl-46-SSLGetSupportedCiphers.c */; }; + 0C0E046A162CA288009F7C71 /* ssl_regressions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C0E0469162CA288009F7C71 /* ssl_regressions.h */; }; + 0C0F140B191AC0A200481BA2 /* ssl-50-server.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C0F140A191AC0A200481BA2 /* ssl-50-server.c */; }; + 0C1C92F315C8AC81007D377B /* cipherSpecs.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CAFF4020534D89900303760 /* cipherSpecs.h */; }; + 0C1C92F415C8AC81007D377B /* sslTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA413C15C75863002AEC4C /* sslTypes.h */; settings = {ATTRIBUTES = (); }; }; + 0C1C92F515C8AC81007D377B /* cryptType.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CAFF4040534D89900303760 /* cryptType.h */; }; + 0C1C930015C8AC81007D377B /* sslMemory.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CAFF4270534D89900303760 /* sslMemory.h */; }; + 0C1C930515C8AC81007D377B /* symCipher.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CAFF4320534D89900303760 /* symCipher.h */; }; + 0C1C930615C8AC81007D377B /* tls_hmac.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CAFF4350534D89900303760 /* tls_hmac.h */; }; + 0C1C930815C8AC81007D377B /* CipherSuite.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CAFF4030534D89900303760 /* CipherSuite.h */; settings = {ATTRIBUTES = (); }; }; + 0C1C931015C8AC81007D377B /* tls_digest.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA413F15C75863002AEC4C /* tls_digest.h */; }; + 0C1C931115C8AC81007D377B /* tls_hashhmac.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA414115C75863002AEC4C /* tls_hashhmac.h */; }; + 0C1C931215C8AC81007D377B /* tls_record_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA414215C75863002AEC4C /* tls_record_internal.h */; }; + 0C1C931615C8AC81007D377B /* cipherSpecs.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4010534D89900303760 /* cipherSpecs.c */; }; + 0C1C932415C8AC81007D377B /* sslMemory.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4260534D89900303760 /* sslMemory.c */; }; + 0C1C932515C8AC81007D377B /* sslNullCipher.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4280534D89900303760 /* sslNullCipher.c */; }; + 0C1C932915C8AC81007D377B /* sslUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF42F0534D89900303760 /* sslUtils.c */; }; + 0C1C932A15C8AC81007D377B /* symCipher.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4310534D89900303760 /* symCipher.c */; }; + 0C1C932C15C8AC81007D377B /* tls_hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4340534D89900303760 /* tls_hmac.c */; }; + 0C1C933015C8AC81007D377B /* sslRand.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA413815C75863002AEC4C /* sslRand.c */; }; + 0C1C933115C8AC81007D377B /* SSLRecordInternal.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA413A15C75863002AEC4C /* SSLRecordInternal.c */; }; + 0C1C933215C8AC81007D377B /* symCipherParams.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA413D15C75863002AEC4C /* symCipherParams.c */; }; + 0C1C933315C8AC81007D377B /* tls_digest.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA413E15C75863002AEC4C /* tls_digest.c */; }; + 0C1C933415C8AC81007D377B /* tls_hashhmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA414015C75863002AEC4C /* tls_hashhmac.c */; }; + 0C1C933B15C8AFB8007D377B /* SSLRecordInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA413B15C75863002AEC4C /* SSLRecordInternal.h */; }; + 0C1F06F7189B1F0600E65030 /* sslMemory.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4260534D89900303760 /* sslMemory.c */; }; + 0C6C633515D1BB4F00BC68CD /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C6C633315D1BB3300BC68CD /* Security.framework */; }; + 0C6C633615D1BB6000BC68CD /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C6C633315D1BB3300BC68CD /* Security.framework */; }; + 0C6C633815D1BB7100BC68CD /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C6C633715D1BB7100BC68CD /* CoreFoundation.framework */; }; + 0C6C633915D1BBAA00BC68CD /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C6C633715D1BB7100BC68CD /* CoreFoundation.framework */; }; + 0C6C634315D1BDCF00BC68CD /* ssl-utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C6C634215D1BDCF00BC68CD /* ssl-utils.c */; }; + 0C6C634515D1BE3900BC68CD /* ssl-utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C6C634415D1BE3900BC68CD /* ssl-utils.h */; }; + 0C6C641F15D5840700BC68CD /* cert-1.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C6C641C15D5840700BC68CD /* cert-1.h */; }; + 0C6C642015D5840700BC68CD /* identity-1.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C6C641D15D5840700BC68CD /* identity-1.h */; }; + 0C6C642115D5840700BC68CD /* privkey-1.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C6C641E15D5840700BC68CD /* privkey-1.h */; }; + 0C6C642315D5938E00BC68CD /* ssl-utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C6C634215D1BDCF00BC68CD /* ssl-utils.c */; }; + 0C6C642415D5939A00BC68CD /* ssl-utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C6C634215D1BDCF00BC68CD /* ssl-utils.c */; }; + 0C80AB1317E9025B008F7F5B /* sslCrypto.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C80AB1217E9025B008F7F5B /* sslCrypto.c */; }; + 0CA9800617E3925A00205D87 /* sslKeychain.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4230534D89900303760 /* sslKeychain.c */; }; + 0CA9800917E7734000205D87 /* appleSession.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF3FF0534D89900303760 /* appleSession.c */; }; + 0CA9803417E7899B00205D87 /* SSLRecordInternal.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA413A15C75863002AEC4C /* SSLRecordInternal.c */; }; + 0CB3EC4818AEDB6B00647921 /* ssl-48-split.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CB3EC4718AEDB6B00647921 /* ssl-48-split.c */; }; + 0CCA416F15C89EA3002AEC4C /* ClientCert_ecc_ecc.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA415E15C89EA3002AEC4C /* ClientCert_ecc_ecc.h */; }; + 0CCA417015C89EA3002AEC4C /* ClientCert_ecc_rsa.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA415F15C89EA3002AEC4C /* ClientCert_ecc_rsa.h */; }; + 0CCA417115C89EA3002AEC4C /* ClientCert_rsa_ecc.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA416015C89EA3002AEC4C /* ClientCert_rsa_ecc.h */; }; + 0CCA417215C89EA3002AEC4C /* ClientCert_rsa_rsa.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA416115C89EA3002AEC4C /* ClientCert_rsa_rsa.h */; }; + 0CCA417315C89EA3002AEC4C /* ClientKey_ecc.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA416215C89EA3002AEC4C /* ClientKey_ecc.h */; }; + 0CCA417415C89EA3002AEC4C /* ClientKey_rsa.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA416315C89EA3002AEC4C /* ClientKey_rsa.h */; }; + 0CCA417515C89EA3002AEC4C /* SECG_ecc-secp256r1-client_cert.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA416415C89EA3002AEC4C /* SECG_ecc-secp256r1-client_cert.h */; }; + 0CCA417615C89EA3002AEC4C /* SECG_ecc-secp256r1-client_key.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA416515C89EA3002AEC4C /* SECG_ecc-secp256r1-client_key.h */; }; + 0CCA417715C89EA3002AEC4C /* SECG_ecc_rsa-secp256r1-client_cert.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA416615C89EA3002AEC4C /* SECG_ecc_rsa-secp256r1-client_cert.h */; }; + 0CCA417815C89EA3002AEC4C /* SECG_ecc_rsa-secp256r1-client_key.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA416715C89EA3002AEC4C /* SECG_ecc_rsa-secp256r1-client_key.h */; }; + 0CCA417915C89EA3002AEC4C /* ssl-39-echo.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA416815C89EA3002AEC4C /* ssl-39-echo.c */; }; + 0CCA417A15C89EA3002AEC4C /* ssl-40-clientauth.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA416915C89EA3002AEC4C /* ssl-40-clientauth.c */; }; + 0CCA417B15C89EA3002AEC4C /* ssl-41-clientauth.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA416A15C89EA3002AEC4C /* ssl-41-clientauth.c */; }; + 0CCA417C15C89EA3002AEC4C /* ssl-42-ciphers.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA416B15C89EA3002AEC4C /* ssl-42-ciphers.c */; }; + 0CCA417D15C89EA3002AEC4C /* ssl-43-ciphers.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA416C15C89EA3002AEC4C /* ssl-43-ciphers.c */; }; + 0CCA417E15C89EA3002AEC4C /* ssl-45-tls12.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA416D15C89EA3002AEC4C /* ssl-45-tls12.c */; }; + 0CCA42E115C8A3D9002AEC4C /* dtlsEchoClient.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA42C115C8A34E002AEC4C /* dtlsEchoClient.c */; }; + 0CCA42E215C8A3DE002AEC4C /* dtlsEchoServer.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA42C215C8A34E002AEC4C /* dtlsEchoServer.c */; }; + 0CCA42EC15C8A71A002AEC4C /* sslAppUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA42EA15C8A71A002AEC4C /* sslAppUtils.cpp */; }; + 0CCA42ED15C8A71A002AEC4C /* sslAppUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA42EA15C8A71A002AEC4C /* sslAppUtils.cpp */; }; + 0CCF28B8166D5F5000AFA37C /* ssl-47-falsestart.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCF28B7166D5F5000AFA37C /* ssl-47-falsestart.c */; }; + 0CDDC9A7195CD44400E93A27 /* ssl-51-state.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CDDC9A6195CD44400E93A27 /* ssl-51-state.c */; }; + 0CEA459418CF71B700BD32A9 /* ssl-49-sni.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CEA459218CF71AE00BD32A9 /* ssl-49-sni.c */; }; + 4CAFF4540534D89900303760 /* sslContext.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF41A0534D89900303760 /* sslContext.c */; }; + 4CAFF4640534D89900303760 /* sslRecord.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF42A0534D89900303760 /* sslRecord.c */; }; + 4CAFF4680534D89900303760 /* sslTransport.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF42E0534D89900303760 /* sslTransport.c */; }; + 4CAFF4690534D89900303760 /* sslUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF42F0534D89900303760 /* sslUtils.c */; }; + AAB589F216CACE540071FE64 /* ssl-44-crashes.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CC954F0161A62AE005D3D4A /* ssl-44-crashes.c */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 0C6C633E15D1BD4D00BC68CD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0CCA42C815C8A387002AEC4C; + remoteInfo = dtlsEchoClient; + }; + 0C6C634015D1BD4E00BC68CD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0CCA42D615C8A395002AEC4C; + remoteInfo = dtlsEchoServer; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 0CCA42C715C8A387002AEC4C /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 0CCA42D515C8A395002AEC4C /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0C03D65A17DFE67E0087643B /* tlsCallbacks.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tlsCallbacks.c; sourceTree = ""; }; + 0C03D65C17DFE6E20087643B /* tlsCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tlsCallbacks.h; sourceTree = ""; }; + 0C0E0466162C9DF0009F7C71 /* ssl-46-SSLGetSupportedCiphers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-46-SSLGetSupportedCiphers.c"; sourceTree = ""; }; + 0C0E0469162CA288009F7C71 /* ssl_regressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ssl_regressions.h; sourceTree = ""; }; + 0C0F140A191AC0A200481BA2 /* ssl-50-server.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-50-server.c"; sourceTree = ""; }; + 0C1C92ED15C8AC52007D377B /* kext.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = kext.xcconfig; sourceTree = ""; }; + 0C1C933A15C8AC81007D377B /* libsecurity_ssl_kext.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurity_ssl_kext.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 0C6C633315D1BB3300BC68CD /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Security.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 0C6C633715D1BB7100BC68CD /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + 0C6C634215D1BDCF00BC68CD /* ssl-utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-utils.c"; sourceTree = ""; }; + 0C6C634415D1BE3900BC68CD /* ssl-utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ssl-utils.h"; sourceTree = ""; }; + 0C6C641C15D5840700BC68CD /* cert-1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "cert-1.h"; sourceTree = ""; }; + 0C6C641D15D5840700BC68CD /* identity-1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "identity-1.h"; sourceTree = ""; }; + 0C6C641E15D5840700BC68CD /* privkey-1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "privkey-1.h"; sourceTree = ""; }; + 0C80AB1217E9025B008F7F5B /* sslCrypto.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sslCrypto.c; sourceTree = ""; }; + 0C85738D15DAB34C0038DFD7 /* tests.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = tests.xcconfig; sourceTree = ""; }; + 0CB3EC4718AEDB6B00647921 /* ssl-48-split.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-48-split.c"; sourceTree = ""; }; + 0CC954F0161A62AE005D3D4A /* ssl-44-crashes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-44-crashes.c"; sourceTree = ""; }; + 0CCA413415C75863002AEC4C /* SecureTransportPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecureTransportPriv.h; path = ../lib/SecureTransportPriv.h; sourceTree = ""; }; + 0CCA413615C75863002AEC4C /* sslCipherSpecs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sslCipherSpecs.c; sourceTree = ""; }; + 0CCA413715C75863002AEC4C /* sslCipherSpecs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sslCipherSpecs.h; sourceTree = ""; }; + 0CCA413815C75863002AEC4C /* sslRand.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sslRand.c; sourceTree = ""; }; + 0CCA413915C75863002AEC4C /* sslRand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sslRand.h; sourceTree = ""; }; + 0CCA413A15C75863002AEC4C /* SSLRecordInternal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SSLRecordInternal.c; sourceTree = ""; }; + 0CCA413B15C75863002AEC4C /* SSLRecordInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSLRecordInternal.h; sourceTree = ""; }; + 0CCA413C15C75863002AEC4C /* sslTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sslTypes.h; path = ../lib/sslTypes.h; sourceTree = ""; }; + 0CCA413D15C75863002AEC4C /* symCipherParams.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = symCipherParams.c; sourceTree = ""; }; + 0CCA413E15C75863002AEC4C /* tls_digest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tls_digest.c; sourceTree = ""; }; + 0CCA413F15C75863002AEC4C /* tls_digest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tls_digest.h; sourceTree = ""; }; + 0CCA414015C75863002AEC4C /* tls_hashhmac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tls_hashhmac.c; sourceTree = ""; }; + 0CCA414115C75863002AEC4C /* tls_hashhmac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tls_hashhmac.h; sourceTree = ""; }; + 0CCA414215C75863002AEC4C /* tls_record_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tls_record_internal.h; sourceTree = ""; }; + 0CCA415915C89E8B002AEC4C /* libsecurity_ssl_regressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurity_ssl_regressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 0CCA415E15C89EA3002AEC4C /* ClientCert_ecc_ecc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientCert_ecc_ecc.h; sourceTree = ""; }; + 0CCA415F15C89EA3002AEC4C /* ClientCert_ecc_rsa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientCert_ecc_rsa.h; sourceTree = ""; }; + 0CCA416015C89EA3002AEC4C /* ClientCert_rsa_ecc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientCert_rsa_ecc.h; sourceTree = ""; }; + 0CCA416115C89EA3002AEC4C /* ClientCert_rsa_rsa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientCert_rsa_rsa.h; sourceTree = ""; }; + 0CCA416215C89EA3002AEC4C /* ClientKey_ecc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientKey_ecc.h; sourceTree = ""; }; + 0CCA416315C89EA3002AEC4C /* ClientKey_rsa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientKey_rsa.h; sourceTree = ""; }; + 0CCA416415C89EA3002AEC4C /* SECG_ecc-secp256r1-client_cert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SECG_ecc-secp256r1-client_cert.h"; sourceTree = ""; }; + 0CCA416515C89EA3002AEC4C /* SECG_ecc-secp256r1-client_key.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SECG_ecc-secp256r1-client_key.h"; sourceTree = ""; }; + 0CCA416615C89EA3002AEC4C /* SECG_ecc_rsa-secp256r1-client_cert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SECG_ecc_rsa-secp256r1-client_cert.h"; sourceTree = ""; }; + 0CCA416715C89EA3002AEC4C /* SECG_ecc_rsa-secp256r1-client_key.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SECG_ecc_rsa-secp256r1-client_key.h"; sourceTree = ""; }; + 0CCA416815C89EA3002AEC4C /* ssl-39-echo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-39-echo.c"; sourceTree = ""; }; + 0CCA416915C89EA3002AEC4C /* ssl-40-clientauth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-40-clientauth.c"; sourceTree = ""; }; + 0CCA416A15C89EA3002AEC4C /* ssl-41-clientauth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-41-clientauth.c"; sourceTree = ""; }; + 0CCA416B15C89EA3002AEC4C /* ssl-42-ciphers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-42-ciphers.c"; sourceTree = ""; }; + 0CCA416C15C89EA3002AEC4C /* ssl-43-ciphers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-43-ciphers.c"; sourceTree = ""; }; + 0CCA416D15C89EA3002AEC4C /* ssl-45-tls12.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-45-tls12.c"; sourceTree = ""; }; + 0CCA42C115C8A34E002AEC4C /* dtlsEchoClient.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dtlsEchoClient.c; sourceTree = ""; }; + 0CCA42C215C8A34E002AEC4C /* dtlsEchoServer.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dtlsEchoServer.c; sourceTree = ""; }; + 0CCA42C315C8A34E002AEC4C /* README */ = {isa = PBXFileReference; lastKnownFileType = text; path = README; sourceTree = ""; }; + 0CCA42C915C8A387002AEC4C /* dtlsEchoClient */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dtlsEchoClient; sourceTree = BUILT_PRODUCTS_DIR; }; + 0CCA42D715C8A395002AEC4C /* dtlsEchoServer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dtlsEchoServer; sourceTree = BUILT_PRODUCTS_DIR; }; + 0CCA42EA15C8A71A002AEC4C /* sslAppUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sslAppUtils.cpp; path = sslViewer/sslAppUtils.cpp; sourceTree = SOURCE_ROOT; }; + 0CCA42EB15C8A71A002AEC4C /* sslAppUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sslAppUtils.h; path = sslViewer/sslAppUtils.h; sourceTree = SOURCE_ROOT; }; + 0CCF28B7166D5F5000AFA37C /* ssl-47-falsestart.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-47-falsestart.c"; sourceTree = ""; }; + 0CDDC9A6195CD44400E93A27 /* ssl-51-state.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-51-state.c"; sourceTree = ""; }; + 0CEA459218CF71AE00BD32A9 /* ssl-49-sni.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-49-sni.c"; sourceTree = ""; }; + 4CA1FEBE052A3C8100F22E42 /* libsecurity_ssl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_ssl.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CAFF3FE0534D89900303760 /* appleCdsa.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = appleCdsa.h; sourceTree = ""; }; + 4CAFF3FF0534D89900303760 /* appleSession.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = appleSession.c; sourceTree = ""; }; + 4CAFF4000534D89900303760 /* appleSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = appleSession.h; sourceTree = ""; }; + 4CAFF4010534D89900303760 /* cipherSpecs.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cipherSpecs.c; sourceTree = ""; }; + 4CAFF4020534D89900303760 /* cipherSpecs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cipherSpecs.h; sourceTree = ""; }; + 4CAFF4030534D89900303760 /* CipherSuite.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CipherSuite.h; sourceTree = ""; }; + 4CAFF4040534D89900303760 /* cryptType.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cryptType.h; sourceTree = ""; }; + 4CAFF4060534D89900303760 /* ModuleAttacher.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ModuleAttacher.h; sourceTree = ""; }; + 4CAFF4070534D89900303760 /* securetransport++.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = "securetransport++.cpp"; sourceTree = ""; }; + 4CAFF4080534D89900303760 /* securetransport++.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "securetransport++.h"; sourceTree = ""; }; + 4CAFF4090534D89900303760 /* SecureTransport.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecureTransport.h; sourceTree = ""; }; + 4CAFF40B0534D89900303760 /* ssl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ssl.h; sourceTree = ""; }; + 4CAFF4130534D89900303760 /* sslAlertMessage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslAlertMessage.h; sourceTree = ""; }; + 4CAFF4140534D89900303760 /* sslBER.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslBER.c; sourceTree = ""; }; + 4CAFF4150534D89900303760 /* sslBER.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslBER.h; sourceTree = ""; }; + 4CAFF4170534D89900303760 /* sslBuildFlags.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslBuildFlags.h; sourceTree = ""; }; + 4CAFF41A0534D89900303760 /* sslContext.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslContext.c; sourceTree = ""; }; + 4CAFF41B0534D89900303760 /* sslContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslContext.h; sourceTree = ""; }; + 4CAFF41C0534D89900303760 /* sslDebug.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslDebug.h; sourceTree = ""; }; + 4CAFF41D0534D89900303760 /* sslDigests.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslDigests.c; sourceTree = ""; }; + 4CAFF41E0534D89900303760 /* sslDigests.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslDigests.h; sourceTree = ""; }; + 4CAFF4200534D89900303760 /* sslHandshake.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslHandshake.h; sourceTree = ""; }; + 4CAFF4230534D89900303760 /* sslKeychain.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslKeychain.c; sourceTree = ""; }; + 4CAFF4240534D89900303760 /* sslKeychain.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslKeychain.h; sourceTree = ""; }; + 4CAFF4260534D89900303760 /* sslMemory.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslMemory.c; sourceTree = ""; }; + 4CAFF4270534D89900303760 /* sslMemory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslMemory.h; sourceTree = ""; }; + 4CAFF4280534D89900303760 /* sslNullCipher.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslNullCipher.c; sourceTree = ""; }; + 4CAFF4290534D89900303760 /* sslPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslPriv.h; sourceTree = ""; }; + 4CAFF42A0534D89900303760 /* sslRecord.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslRecord.c; sourceTree = ""; }; + 4CAFF42B0534D89900303760 /* sslRecord.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslRecord.h; sourceTree = ""; }; + 4CAFF42C0534D89900303760 /* sslSession.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslSession.c; sourceTree = ""; }; + 4CAFF42D0534D89900303760 /* sslSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslSession.h; sourceTree = ""; }; + 4CAFF42E0534D89900303760 /* sslTransport.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslTransport.c; sourceTree = ""; }; + 4CAFF42F0534D89900303760 /* sslUtils.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslUtils.c; sourceTree = ""; }; + 4CAFF4300534D89900303760 /* sslUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslUtils.h; sourceTree = ""; }; + 4CAFF4310534D89900303760 /* symCipher.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = symCipher.c; sourceTree = ""; }; + 4CAFF4320534D89900303760 /* symCipher.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = symCipher.h; sourceTree = ""; }; + 4CAFF4340534D89900303760 /* tls_hmac.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = tls_hmac.c; sourceTree = ""; }; + 4CAFF4350534D89900303760 /* tls_hmac.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tls_hmac.h; sourceTree = ""; }; + 4CAFF4360534D89900303760 /* tls_ssl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tls_ssl.h; sourceTree = ""; }; + 4CCBFE3C057FF16800981D43 /* security_ssl.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = security_ssl.exp; sourceTree = ""; }; + BE6A959C14E3700A00C158E0 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + BE6A959D14E3700A00C158E0 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + BE6A959E14E3700A00C158E0 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + BE6A959F14E3700A00C158E0 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + BEB382AB14EC84A0003C055B /* secCrypto.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = secCrypto.c; sourceTree = ""; }; + BEB382AE14EC84AC003C055B /* sslCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sslCrypto.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 0C1C933615C8AC81007D377B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0CCA415615C89E8B002AEC4C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0CCA42C615C8A387002AEC4C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C6C633815D1BB7100BC68CD /* CoreFoundation.framework in Frameworks */, + 0C6C633515D1BB4F00BC68CD /* Security.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0CCA42D415C8A395002AEC4C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C6C633915D1BBAA00BC68CD /* CoreFoundation.framework in Frameworks */, + 0C6C633615D1BB6000BC68CD /* Security.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 050651C7056A83F3008AD683 /* Apple Custom */ = { + isa = PBXGroup; + children = ( + 4CAFF3FF0534D89900303760 /* appleSession.c */, + 4CAFF4230534D89900303760 /* sslKeychain.c */, + ); + name = "Apple Custom"; + sourceTree = ""; + }; + 050651C8056A8404008AD683 /* SSL Core */ = { + isa = PBXGroup; + children = ( + 0CCA413A15C75863002AEC4C /* SSLRecordInternal.c */, + 0CCA413615C75863002AEC4C /* sslCipherSpecs.c */, + 4CAFF41A0534D89900303760 /* sslContext.c */, + 4CAFF42A0534D89900303760 /* sslRecord.c */, + 4CAFF42C0534D89900303760 /* sslSession.c */, + 4CAFF42E0534D89900303760 /* sslTransport.c */, + 0C03D65A17DFE67E0087643B /* tlsCallbacks.c */, + 0C03D65C17DFE6E20087643B /* tlsCallbacks.h */, + ); + name = "SSL Core"; + sourceTree = ""; + }; + 050651C9056A840E008AD683 /* Private Headers */ = { + isa = PBXGroup; + children = ( + 0CCA413C15C75863002AEC4C /* sslTypes.h */, + 0CCA413415C75863002AEC4C /* SecureTransportPriv.h */, + ); + name = "Private Headers"; + path = ../Security; + sourceTree = ""; + }; + 050651CA056A8415008AD683 /* Public Headers */ = { + isa = PBXGroup; + children = ( + 4CAFF4030534D89900303760 /* CipherSuite.h */, + 4CAFF4090534D89900303760 /* SecureTransport.h */, + ); + name = "Public Headers"; + path = ../Security; + sourceTree = ""; + }; + 050651CB056A841C008AD683 /* Crypto */ = { + isa = PBXGroup; + children = ( + 4CAFF4010534D89900303760 /* cipherSpecs.c */, + 0CCA413D15C75863002AEC4C /* symCipherParams.c */, + 0CCA413815C75863002AEC4C /* sslRand.c */, + BEB382AB14EC84A0003C055B /* secCrypto.c */, + 0C80AB1217E9025B008F7F5B /* sslCrypto.c */, + 4CAFF41D0534D89900303760 /* sslDigests.c */, + 4CAFF4280534D89900303760 /* sslNullCipher.c */, + 4CAFF4310534D89900303760 /* symCipher.c */, + 0CCA413E15C75863002AEC4C /* tls_digest.c */, + 0CCA414015C75863002AEC4C /* tls_hashhmac.c */, + 4CAFF4340534D89900303760 /* tls_hmac.c */, + ); + name = Crypto; + sourceTree = ""; + }; + 050651CC056A8421008AD683 /* Misc. */ = { + isa = PBXGroup; + children = ( + 4CAFF4140534D89900303760 /* sslBER.c */, + 4CAFF4260534D89900303760 /* sslMemory.c */, + 4CAFF42F0534D89900303760 /* sslUtils.c */, + ); + name = Misc.; + sourceTree = ""; + }; + 050651CD056A8427008AD683 /* C++ Interface */ = { + isa = PBXGroup; + children = ( + 4CAFF4070534D89900303760 /* securetransport++.cpp */, + 4CAFF4080534D89900303760 /* securetransport++.h */, + ); + name = "C++ Interface"; + sourceTree = ""; + }; + 0CCA415D15C89EA3002AEC4C /* regressions */ = { + isa = PBXGroup; + children = ( + 0C6C641C15D5840700BC68CD /* cert-1.h */, + 0C6C641D15D5840700BC68CD /* identity-1.h */, + 0C6C641E15D5840700BC68CD /* privkey-1.h */, + 0CCA415E15C89EA3002AEC4C /* ClientCert_ecc_ecc.h */, + 0CCA415F15C89EA3002AEC4C /* ClientCert_ecc_rsa.h */, + 0CCA416015C89EA3002AEC4C /* ClientCert_rsa_ecc.h */, + 0CCA416115C89EA3002AEC4C /* ClientCert_rsa_rsa.h */, + 0CCA416215C89EA3002AEC4C /* ClientKey_ecc.h */, + 0CCA416315C89EA3002AEC4C /* ClientKey_rsa.h */, + 0CCA416415C89EA3002AEC4C /* SECG_ecc-secp256r1-client_cert.h */, + 0CCA416515C89EA3002AEC4C /* SECG_ecc-secp256r1-client_key.h */, + 0CCA416615C89EA3002AEC4C /* SECG_ecc_rsa-secp256r1-client_cert.h */, + 0CCA416715C89EA3002AEC4C /* SECG_ecc_rsa-secp256r1-client_key.h */, + 0CCA416815C89EA3002AEC4C /* ssl-39-echo.c */, + 0CCA416915C89EA3002AEC4C /* ssl-40-clientauth.c */, + 0CCA416A15C89EA3002AEC4C /* ssl-41-clientauth.c */, + 0CCA416B15C89EA3002AEC4C /* ssl-42-ciphers.c */, + 0CCA416C15C89EA3002AEC4C /* ssl-43-ciphers.c */, + 0CC954F0161A62AE005D3D4A /* ssl-44-crashes.c */, + 0CCA416D15C89EA3002AEC4C /* ssl-45-tls12.c */, + 0C0E0466162C9DF0009F7C71 /* ssl-46-SSLGetSupportedCiphers.c */, + 0CCF28B7166D5F5000AFA37C /* ssl-47-falsestart.c */, + 0CB3EC4718AEDB6B00647921 /* ssl-48-split.c */, + 0CEA459218CF71AE00BD32A9 /* ssl-49-sni.c */, + 0C0F140A191AC0A200481BA2 /* ssl-50-server.c */, + 0CDDC9A6195CD44400E93A27 /* ssl-51-state.c */, + 0C6C634215D1BDCF00BC68CD /* ssl-utils.c */, + 0C6C634415D1BE3900BC68CD /* ssl-utils.h */, + 0C0E0469162CA288009F7C71 /* ssl_regressions.h */, + ); + path = regressions; + sourceTree = ""; + }; + 0CCA42C015C8A34E002AEC4C /* dtlsEcho */ = { + isa = PBXGroup; + children = ( + 0CCA42EA15C8A71A002AEC4C /* sslAppUtils.cpp */, + 0CCA42EB15C8A71A002AEC4C /* sslAppUtils.h */, + 0CCA42C115C8A34E002AEC4C /* dtlsEchoClient.c */, + 0CCA42C215C8A34E002AEC4C /* dtlsEchoServer.c */, + 0CCA42C315C8A34E002AEC4C /* README */, + ); + path = dtlsEcho; + sourceTree = ""; + }; + 4CA1FEA7052A3C3800F22E42 = { + isa = PBXGroup; + children = ( + 0C6C633715D1BB7100BC68CD /* CoreFoundation.framework */, + 0C6C633315D1BB3300BC68CD /* Security.framework */, + 0CCA42C015C8A34E002AEC4C /* dtlsEcho */, + 0CCA415D15C89EA3002AEC4C /* regressions */, + BE6A959B14E3700A00C158E0 /* config */, + 4CAFF3FC0534D89900303760 /* lib */, + 4CA1FEBF052A3C8100F22E42 /* Products */, + ); + sourceTree = ""; + }; + 4CA1FEBF052A3C8100F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + 4CA1FEBE052A3C8100F22E42 /* libsecurity_ssl.a */, + 0CCA415915C89E8B002AEC4C /* libsecurity_ssl_regressions.a */, + 0CCA42C915C8A387002AEC4C /* dtlsEchoClient */, + 0CCA42D715C8A395002AEC4C /* dtlsEchoServer */, + 0C1C933A15C8AC81007D377B /* libsecurity_ssl_kext.a */, + ); + name = Products; + sourceTree = ""; + }; + 4CAFF3FC0534D89900303760 /* lib */ = { + isa = PBXGroup; + children = ( + 050651C7056A83F3008AD683 /* Apple Custom */, + 050651C8056A8404008AD683 /* SSL Core */, + 050651CA056A8415008AD683 /* Public Headers */, + 050651C9056A840E008AD683 /* Private Headers */, + BE967B0314E9F622002A348A /* Project Headers */, + 050651CB056A841C008AD683 /* Crypto */, + 050651CC056A8421008AD683 /* Misc. */, + 050651CD056A8427008AD683 /* C++ Interface */, + 4CCBFE3C057FF16800981D43 /* security_ssl.exp */, + ); + path = lib; + sourceTree = ""; + }; + BE6A959B14E3700A00C158E0 /* config */ = { + isa = PBXGroup; + children = ( + BE6A959C14E3700A00C158E0 /* base.xcconfig */, + BE6A959D14E3700A00C158E0 /* debug.xcconfig */, + 0C1C92ED15C8AC52007D377B /* kext.xcconfig */, + BE6A959E14E3700A00C158E0 /* lib.xcconfig */, + BE6A959F14E3700A00C158E0 /* release.xcconfig */, + 0C85738D15DAB34C0038DFD7 /* tests.xcconfig */, + ); + path = config; + sourceTree = ""; + }; + BE967B0314E9F622002A348A /* Project Headers */ = { + isa = PBXGroup; + children = ( + 0CCA413715C75863002AEC4C /* sslCipherSpecs.h */, + 0CCA413B15C75863002AEC4C /* SSLRecordInternal.h */, + 0CCA413915C75863002AEC4C /* sslRand.h */, + 0CCA413F15C75863002AEC4C /* tls_digest.h */, + 0CCA414115C75863002AEC4C /* tls_hashhmac.h */, + 0CCA414215C75863002AEC4C /* tls_record_internal.h */, + 4CAFF3FE0534D89900303760 /* appleCdsa.h */, + 4CAFF4000534D89900303760 /* appleSession.h */, + 4CAFF4020534D89900303760 /* cipherSpecs.h */, + 4CAFF4040534D89900303760 /* cryptType.h */, + 4CAFF4060534D89900303760 /* ModuleAttacher.h */, + 4CAFF40B0534D89900303760 /* ssl.h */, + 4CAFF4130534D89900303760 /* sslAlertMessage.h */, + 4CAFF4150534D89900303760 /* sslBER.h */, + 4CAFF4170534D89900303760 /* sslBuildFlags.h */, + 4CAFF41B0534D89900303760 /* sslContext.h */, + BEB382AE14EC84AC003C055B /* sslCrypto.h */, + 4CAFF41C0534D89900303760 /* sslDebug.h */, + 4CAFF41E0534D89900303760 /* sslDigests.h */, + 4CAFF4200534D89900303760 /* sslHandshake.h */, + 4CAFF4240534D89900303760 /* sslKeychain.h */, + 4CAFF4270534D89900303760 /* sslMemory.h */, + 4CAFF4290534D89900303760 /* sslPriv.h */, + 4CAFF42B0534D89900303760 /* sslRecord.h */, + 4CAFF42D0534D89900303760 /* sslSession.h */, + 4CAFF4300534D89900303760 /* sslUtils.h */, + 4CAFF4320534D89900303760 /* symCipher.h */, + 4CAFF4350534D89900303760 /* tls_hmac.h */, + 4CAFF4360534D89900303760 /* tls_ssl.h */, + ); + name = "Project Headers"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 0C1C92F015C8AC81007D377B /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C1C933B15C8AFB8007D377B /* SSLRecordInternal.h in Headers */, + 0C1C92F315C8AC81007D377B /* cipherSpecs.h in Headers */, + 0C1C92F515C8AC81007D377B /* cryptType.h in Headers */, + 0C1C930815C8AC81007D377B /* CipherSuite.h in Headers */, + 0C1C92F415C8AC81007D377B /* sslTypes.h in Headers */, + 0C1C930015C8AC81007D377B /* sslMemory.h in Headers */, + 0C1C930515C8AC81007D377B /* symCipher.h in Headers */, + 0C1C930615C8AC81007D377B /* tls_hmac.h in Headers */, + 0C1C931015C8AC81007D377B /* tls_digest.h in Headers */, + 0C1C931115C8AC81007D377B /* tls_hashhmac.h in Headers */, + 0C1C931215C8AC81007D377B /* tls_record_internal.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0CCA415715C89E8B002AEC4C /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0CCA416F15C89EA3002AEC4C /* ClientCert_ecc_ecc.h in Headers */, + 0CCA417015C89EA3002AEC4C /* ClientCert_ecc_rsa.h in Headers */, + 0CCA417115C89EA3002AEC4C /* ClientCert_rsa_ecc.h in Headers */, + 0CCA417215C89EA3002AEC4C /* ClientCert_rsa_rsa.h in Headers */, + 0CCA417315C89EA3002AEC4C /* ClientKey_ecc.h in Headers */, + 0CCA417415C89EA3002AEC4C /* ClientKey_rsa.h in Headers */, + 0CCA417515C89EA3002AEC4C /* SECG_ecc-secp256r1-client_cert.h in Headers */, + 0CCA417615C89EA3002AEC4C /* SECG_ecc-secp256r1-client_key.h in Headers */, + 0CCA417715C89EA3002AEC4C /* SECG_ecc_rsa-secp256r1-client_cert.h in Headers */, + 0CCA417815C89EA3002AEC4C /* SECG_ecc_rsa-secp256r1-client_key.h in Headers */, + 0C6C634515D1BE3900BC68CD /* ssl-utils.h in Headers */, + 0C6C641F15D5840700BC68CD /* cert-1.h in Headers */, + 0C6C642015D5840700BC68CD /* identity-1.h in Headers */, + 0C6C642115D5840700BC68CD /* privkey-1.h in Headers */, + 0C0E046A162CA288009F7C71 /* ssl_regressions.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 0C1C92EF15C8AC81007D377B /* libsecurity_ssl_kext */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0C1C933715C8AC81007D377B /* Build configuration list for PBXNativeTarget "libsecurity_ssl_kext" */; + buildPhases = ( + 0C1C92F015C8AC81007D377B /* Headers */, + 0C1C931315C8AC81007D377B /* Sources */, + 0C1C933615C8AC81007D377B /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libsecurity_ssl_kext; + productName = libsecurity_ssl; + productReference = 0C1C933A15C8AC81007D377B /* libsecurity_ssl_kext.a */; + productType = "com.apple.product-type.library.static"; + }; + 0CCA415815C89E8B002AEC4C /* libsecurity_ssl_regressions */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0CCA415A15C89E8B002AEC4C /* Build configuration list for PBXNativeTarget "libsecurity_ssl_regressions" */; + buildPhases = ( + 0CCA415515C89E8B002AEC4C /* Sources */, + 0CCA415615C89E8B002AEC4C /* Frameworks */, + 0CCA415715C89E8B002AEC4C /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libsecurity_ssl_regressions; + productName = libsecurity_ssl_regressions; + productReference = 0CCA415915C89E8B002AEC4C /* libsecurity_ssl_regressions.a */; + productType = "com.apple.product-type.library.static"; + }; + 0CCA42C815C8A387002AEC4C /* dtlsEchoClient */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0CCA42D015C8A387002AEC4C /* Build configuration list for PBXNativeTarget "dtlsEchoClient" */; + buildPhases = ( + 0CCA42C515C8A387002AEC4C /* Sources */, + 0CCA42C615C8A387002AEC4C /* Frameworks */, + 0CCA42C715C8A387002AEC4C /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = dtlsEchoClient; + productName = dtlsEchoClient; + productReference = 0CCA42C915C8A387002AEC4C /* dtlsEchoClient */; + productType = "com.apple.product-type.tool"; + }; + 0CCA42D615C8A395002AEC4C /* dtlsEchoServer */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0CCA42DE15C8A395002AEC4C /* Build configuration list for PBXNativeTarget "dtlsEchoServer" */; + buildPhases = ( + 0CCA42D315C8A395002AEC4C /* Sources */, + 0CCA42D415C8A395002AEC4C /* Frameworks */, + 0CCA42D515C8A395002AEC4C /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = dtlsEchoServer; + productName = dtlsEchoServer; + productReference = 0CCA42D715C8A395002AEC4C /* dtlsEchoServer */; + productType = "com.apple.product-type.tool"; + }; + 4CA1FEBD052A3C8100F22E42 /* libsecurity_ssl */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD4000987FCDF001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_ssl" */; + buildPhases = ( + 4CA1FEBA052A3C8100F22E42 /* Sources */, + 4CA1FEBB052A3C8100F22E42 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libsecurity_ssl; + productName = libsecurity_ssl; + productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_ssl.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA1FEAB052A3C3800F22E42 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0600; + }; + buildConfigurationList = C27AD4040987FCDF001272E0 /* Build configuration list for PBXProject "libsecurity_ssl" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 4CA1FEA7052A3C3800F22E42; + productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4CA1FEBD052A3C8100F22E42 /* libsecurity_ssl */, + 0C1C92EF15C8AC81007D377B /* libsecurity_ssl_kext */, + 0CCA415815C89E8B002AEC4C /* libsecurity_ssl_regressions */, + 0CCA42C815C8A387002AEC4C /* dtlsEchoClient */, + 0CCA42D615C8A395002AEC4C /* dtlsEchoServer */, + 0C6C633A15D1BD4800BC68CD /* dtlsEcho */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 0C1C931315C8AC81007D377B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C1C931615C8AC81007D377B /* cipherSpecs.c in Sources */, + 0C1C932415C8AC81007D377B /* sslMemory.c in Sources */, + 0C1C932515C8AC81007D377B /* sslNullCipher.c in Sources */, + 0C1C932915C8AC81007D377B /* sslUtils.c in Sources */, + 0C1C932A15C8AC81007D377B /* symCipher.c in Sources */, + 0C1C933015C8AC81007D377B /* sslRand.c in Sources */, + 0C1C933115C8AC81007D377B /* SSLRecordInternal.c in Sources */, + 0C1C933215C8AC81007D377B /* symCipherParams.c in Sources */, + 0C1C933315C8AC81007D377B /* tls_digest.c in Sources */, + 0C1C932C15C8AC81007D377B /* tls_hmac.c in Sources */, + 0C1C933415C8AC81007D377B /* tls_hashhmac.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0CCA415515C89E8B002AEC4C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0CCA417915C89EA3002AEC4C /* ssl-39-echo.c in Sources */, + 0CB3EC4818AEDB6B00647921 /* ssl-48-split.c in Sources */, + 0CCA417A15C89EA3002AEC4C /* ssl-40-clientauth.c in Sources */, + 0CCA417B15C89EA3002AEC4C /* ssl-41-clientauth.c in Sources */, + 0CCA417C15C89EA3002AEC4C /* ssl-42-ciphers.c in Sources */, + 0CCA417D15C89EA3002AEC4C /* ssl-43-ciphers.c in Sources */, + AAB589F216CACE540071FE64 /* ssl-44-crashes.c in Sources */, + 0CCA417E15C89EA3002AEC4C /* ssl-45-tls12.c in Sources */, + 0CEA459418CF71B700BD32A9 /* ssl-49-sni.c in Sources */, + 0CCF28B8166D5F5000AFA37C /* ssl-47-falsestart.c in Sources */, + 0CDDC9A7195CD44400E93A27 /* ssl-51-state.c in Sources */, + 0C6C634315D1BDCF00BC68CD /* ssl-utils.c in Sources */, + 0C0E0467162C9DF0009F7C71 /* ssl-46-SSLGetSupportedCiphers.c in Sources */, + 0C0F140B191AC0A200481BA2 /* ssl-50-server.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0CCA42C515C8A387002AEC4C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C6C642315D5938E00BC68CD /* ssl-utils.c in Sources */, + 0CCA42E115C8A3D9002AEC4C /* dtlsEchoClient.c in Sources */, + 0CCA42EC15C8A71A002AEC4C /* sslAppUtils.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0CCA42D315C8A395002AEC4C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C6C642415D5939A00BC68CD /* ssl-utils.c in Sources */, + 0CCA42E215C8A3DE002AEC4C /* dtlsEchoServer.c in Sources */, + 0CCA42ED15C8A71A002AEC4C /* sslAppUtils.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CA1FEBA052A3C8100F22E42 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C1F06F7189B1F0600E65030 /* sslMemory.c in Sources */, + 0C80AB1317E9025B008F7F5B /* sslCrypto.c in Sources */, + 0CA9803417E7899B00205D87 /* SSLRecordInternal.c in Sources */, + 0CA9800917E7734000205D87 /* appleSession.c in Sources */, + 0CA9800617E3925A00205D87 /* sslKeychain.c in Sources */, + 0C03D65917DFD8C00087643B /* sslCipherSpecs.c in Sources */, + 4CAFF4540534D89900303760 /* sslContext.c in Sources */, + 0C03D65B17DFE67E0087643B /* tlsCallbacks.c in Sources */, + 4CAFF4640534D89900303760 /* sslRecord.c in Sources */, + 4CAFF4680534D89900303760 /* sslTransport.c in Sources */, + 4CAFF4690534D89900303760 /* sslUtils.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 0C6C633F15D1BD4D00BC68CD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0CCA42C815C8A387002AEC4C /* dtlsEchoClient */; + targetProxy = 0C6C633E15D1BD4D00BC68CD /* PBXContainerItemProxy */; + }; + 0C6C634115D1BD4E00BC68CD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0CCA42D615C8A395002AEC4C /* dtlsEchoServer */; + targetProxy = 0C6C634015D1BD4E00BC68CD /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 0C1C933815C8AC81007D377B /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0C1C92ED15C8AC52007D377B /* kext.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Debug; + }; + 0C1C933915C8AC81007D377B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0C1C92ED15C8AC52007D377B /* kext.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Release; + }; + 0C6C633C15D1BD4800BC68CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 0C6C633D15D1BD4800BC68CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 0CCA415B15C89E8B002AEC4C /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BE6A959E14E3700A00C158E0 /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Debug; + }; + 0CCA415C15C89E8B002AEC4C /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BE6A959E14E3700A00C158E0 /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Release; + }; + 0CCA42D115C8A387002AEC4C /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0C85738D15DAB34C0038DFD7 /* tests.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + 0CCA42D215C8A387002AEC4C /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0C85738D15DAB34C0038DFD7 /* tests.xcconfig */; + buildSettings = { + }; + name = Release; + }; + 0CCA42DF15C8A395002AEC4C /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0C85738D15DAB34C0038DFD7 /* tests.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + 0CCA42E015C8A395002AEC4C /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0C85738D15DAB34C0038DFD7 /* tests.xcconfig */; + buildSettings = { + }; + name = Release; + }; + C27AD4010987FCDF001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BE6A959E14E3700A00C158E0 /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Debug; + }; + C27AD4030987FCDF001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BE6A959E14E3700A00C158E0 /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Release; + }; + C27AD4050987FCDF001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BE6A959D14E3700A00C158E0 /* debug.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD4070987FCDF001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BE6A959F14E3700A00C158E0 /* release.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 0C1C933715C8AC81007D377B /* Build configuration list for PBXNativeTarget "libsecurity_ssl_kext" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0C1C933815C8AC81007D377B /* Debug */, + 0C1C933915C8AC81007D377B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0C6C633B15D1BD4800BC68CD /* Build configuration list for PBXAggregateTarget "dtlsEcho" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0C6C633C15D1BD4800BC68CD /* Debug */, + 0C6C633D15D1BD4800BC68CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0CCA415A15C89E8B002AEC4C /* Build configuration list for PBXNativeTarget "libsecurity_ssl_regressions" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0CCA415B15C89E8B002AEC4C /* Debug */, + 0CCA415C15C89E8B002AEC4C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0CCA42D015C8A387002AEC4C /* Build configuration list for PBXNativeTarget "dtlsEchoClient" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0CCA42D115C8A387002AEC4C /* Debug */, + 0CCA42D215C8A387002AEC4C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0CCA42DE15C8A395002AEC4C /* Build configuration list for PBXNativeTarget "dtlsEchoServer" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0CCA42DF15C8A395002AEC4C /* Debug */, + 0CCA42E015C8A395002AEC4C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD4000987FCDF001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_ssl" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD4010987FCDF001272E0 /* Debug */, + C27AD4030987FCDF001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD4040987FCDF001272E0 /* Build configuration list for PBXProject "libsecurity_ssl" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD4050987FCDF001272E0 /* Debug */, + C27AD4070987FCDF001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; +} diff --git a/libsecurity_ssl/regressions/ClientCert_ecc_ecc.h b/Security/libsecurity_ssl/regressions/ClientCert_ecc_ecc.h similarity index 100% rename from libsecurity_ssl/regressions/ClientCert_ecc_ecc.h rename to Security/libsecurity_ssl/regressions/ClientCert_ecc_ecc.h diff --git a/libsecurity_ssl/regressions/ClientCert_ecc_rsa.h b/Security/libsecurity_ssl/regressions/ClientCert_ecc_rsa.h similarity index 100% rename from libsecurity_ssl/regressions/ClientCert_ecc_rsa.h rename to Security/libsecurity_ssl/regressions/ClientCert_ecc_rsa.h diff --git a/libsecurity_ssl/regressions/ClientCert_rsa_ecc.h b/Security/libsecurity_ssl/regressions/ClientCert_rsa_ecc.h similarity index 100% rename from libsecurity_ssl/regressions/ClientCert_rsa_ecc.h rename to Security/libsecurity_ssl/regressions/ClientCert_rsa_ecc.h diff --git a/libsecurity_ssl/regressions/ClientCert_rsa_rsa.h b/Security/libsecurity_ssl/regressions/ClientCert_rsa_rsa.h similarity index 100% rename from libsecurity_ssl/regressions/ClientCert_rsa_rsa.h rename to Security/libsecurity_ssl/regressions/ClientCert_rsa_rsa.h diff --git a/libsecurity_ssl/regressions/ClientKey_ecc.h b/Security/libsecurity_ssl/regressions/ClientKey_ecc.h similarity index 100% rename from libsecurity_ssl/regressions/ClientKey_ecc.h rename to Security/libsecurity_ssl/regressions/ClientKey_ecc.h diff --git a/libsecurity_ssl/regressions/ClientKey_rsa.h b/Security/libsecurity_ssl/regressions/ClientKey_rsa.h similarity index 100% rename from libsecurity_ssl/regressions/ClientKey_rsa.h rename to Security/libsecurity_ssl/regressions/ClientKey_rsa.h diff --git a/libsecurity_ssl/regressions/SECG_ecc-secp256r1-client_cert.h b/Security/libsecurity_ssl/regressions/SECG_ecc-secp256r1-client_cert.h similarity index 100% rename from libsecurity_ssl/regressions/SECG_ecc-secp256r1-client_cert.h rename to Security/libsecurity_ssl/regressions/SECG_ecc-secp256r1-client_cert.h diff --git a/libsecurity_ssl/regressions/SECG_ecc-secp256r1-client_key.h b/Security/libsecurity_ssl/regressions/SECG_ecc-secp256r1-client_key.h similarity index 100% rename from libsecurity_ssl/regressions/SECG_ecc-secp256r1-client_key.h rename to Security/libsecurity_ssl/regressions/SECG_ecc-secp256r1-client_key.h diff --git a/libsecurity_ssl/regressions/SECG_ecc_rsa-secp256r1-client_cert.h b/Security/libsecurity_ssl/regressions/SECG_ecc_rsa-secp256r1-client_cert.h similarity index 100% rename from libsecurity_ssl/regressions/SECG_ecc_rsa-secp256r1-client_cert.h rename to Security/libsecurity_ssl/regressions/SECG_ecc_rsa-secp256r1-client_cert.h diff --git a/libsecurity_ssl/regressions/SECG_ecc_rsa-secp256r1-client_key.h b/Security/libsecurity_ssl/regressions/SECG_ecc_rsa-secp256r1-client_key.h similarity index 100% rename from libsecurity_ssl/regressions/SECG_ecc_rsa-secp256r1-client_key.h rename to Security/libsecurity_ssl/regressions/SECG_ecc_rsa-secp256r1-client_key.h diff --git a/libsecurity_ssl/regressions/cert-1.h b/Security/libsecurity_ssl/regressions/cert-1.h similarity index 100% rename from libsecurity_ssl/regressions/cert-1.h rename to Security/libsecurity_ssl/regressions/cert-1.h diff --git a/libsecurity_ssl/regressions/gencerts.sh b/Security/libsecurity_ssl/regressions/gencerts.sh similarity index 100% rename from libsecurity_ssl/regressions/gencerts.sh rename to Security/libsecurity_ssl/regressions/gencerts.sh diff --git a/libsecurity_ssl/regressions/identity-1.h b/Security/libsecurity_ssl/regressions/identity-1.h similarity index 100% rename from libsecurity_ssl/regressions/identity-1.h rename to Security/libsecurity_ssl/regressions/identity-1.h diff --git a/libsecurity_ssl/regressions/privkey-1.h b/Security/libsecurity_ssl/regressions/privkey-1.h similarity index 100% rename from libsecurity_ssl/regressions/privkey-1.h rename to Security/libsecurity_ssl/regressions/privkey-1.h diff --git a/libsecurity_ssl/regressions/ssl-39-echo.c b/Security/libsecurity_ssl/regressions/ssl-39-echo.c similarity index 99% rename from libsecurity_ssl/regressions/ssl-39-echo.c rename to Security/libsecurity_ssl/regressions/ssl-39-echo.c index c11de67f..10fa94f6 100644 --- a/libsecurity_ssl/regressions/ssl-39-echo.c +++ b/Security/libsecurity_ssl/regressions/ssl-39-echo.c @@ -41,7 +41,7 @@ can be looked up in ciphers(1). All SSL_DH_* and TLS_DH_* are disabled because neither openssl nor - securetranport support them: + securetransport support them: SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA, SSL_DH_DSS_WITH_DES_CBC_SHA, SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA, SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DH_RSA_WITH_DES_CBC_SHA, SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA, diff --git a/libsecurity_ssl/regressions/ssl-40-clientauth.c b/Security/libsecurity_ssl/regressions/ssl-40-clientauth.c similarity index 99% rename from libsecurity_ssl/regressions/ssl-40-clientauth.c rename to Security/libsecurity_ssl/regressions/ssl-40-clientauth.c index 5ad1f004..8c70dcfc 100644 --- a/libsecurity_ssl/regressions/ssl-40-clientauth.c +++ b/Security/libsecurity_ssl/regressions/ssl-40-clientauth.c @@ -2,7 +2,7 @@ * ssl-40-clientauth.c * Security * - * Copyright (c) 2008-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-2010,2012-2013 Apple Inc. All Rights Reserved. * */ @@ -295,7 +295,7 @@ static const uint8_t _k1[] = { 0x34, 0x7c, 0xd4, 0x9d, 0xff, 0xad, 0xee, 0x69 }; -static const uint8_t _k1_digest[] = { +__unused static const uint8_t _k1_digest[] = { 0x46, 0xE0, 0x8A, 0x05, 0x63, 0x4D, 0x17, 0x3F, 0xCA, 0xA4, 0xAA, 0xB6, 0x5A, 0xDA, 0xCF, 0xBA, 0x84, 0x22, 0x7C, 0x23 diff --git a/libsecurity_ssl/regressions/ssl-41-clientauth.c b/Security/libsecurity_ssl/regressions/ssl-41-clientauth.c similarity index 98% rename from libsecurity_ssl/regressions/ssl-41-clientauth.c rename to Security/libsecurity_ssl/regressions/ssl-41-clientauth.c index 8a86d076..b9f63642 100644 --- a/libsecurity_ssl/regressions/ssl-41-clientauth.c +++ b/Security/libsecurity_ssl/regressions/ssl-41-clientauth.c @@ -2,7 +2,7 @@ * ssl-40-clientauth.c * Security * - * Copyright (c) 2008-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-2010,2012-2014 Apple Inc. All Rights Reserved. * */ @@ -132,6 +132,9 @@ friendlyName: uranusLeaf localKeyID: 46 E0 8A 05 63 4D 17 3F CA A4 AA B6 5A DA CF BA 84 22 7C 23 Key Attributes: */ + +#if TARGET_OS_IPHONE +/* we use _k1 on iPhone */ static const uint8_t _k1[] = { 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa6, 0x82, 0x8e, 0xc6, @@ -283,8 +286,11 @@ static const uint8_t _k1[] = { 0xa9, 0xf6, 0x9b, 0x67, 0x6a, 0x87, 0x74, 0x36, 0x34, 0x7c, 0xd4, 0x9d, 0xff, 0xad, 0xee, 0x69 }; +#else + /* don’t use _k1 */ +#endif -static const uint8_t _k1_digest[] = { +__unused static const uint8_t _k1_digest[] = { 0x46, 0xE0, 0x8A, 0x05, 0x63, 0x4D, 0x17, 0x3F, 0xCA, 0xA4, 0xAA, 0xB6, 0x5A, 0xDA, 0xCF, 0xBA, 0x84, 0x22, 0x7C, 0x23 diff --git a/libsecurity_ssl/regressions/ssl-42-ciphers.c b/Security/libsecurity_ssl/regressions/ssl-42-ciphers.c similarity index 76% rename from libsecurity_ssl/regressions/ssl-42-ciphers.c rename to Security/libsecurity_ssl/regressions/ssl-42-ciphers.c index 9804e783..e2f442dd 100644 --- a/libsecurity_ssl/regressions/ssl-42-ciphers.c +++ b/Security/libsecurity_ssl/regressions/ssl-42-ciphers.c @@ -42,7 +42,7 @@ can be looked up in ciphers(1). All SSL_DH_* and TLS_DH_* are disabled because neither openssl nor - securetranport support them: + securetransport support them: SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA, SSL_DH_DSS_WITH_DES_CBC_SHA, SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA, SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DH_RSA_WITH_DES_CBC_SHA, SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA, @@ -70,48 +70,53 @@ */ typedef struct _CipherSuiteName { - SSLCipherSuite cipher; - const char *name; - bool dh_anonymous; + SSLCipherSuite cipher; + const char *name; + bool dh_anonymous; + bool dtls; } CipherSuiteName; -#define CIPHER(cipher, dh_anonymous) { cipher, #cipher, dh_anonymous }, +#define CIPHER(cipher, dh_anonymous, dtls) { cipher, #cipher, dh_anonymous, dtls}, static const CipherSuiteName ciphers[] = { //SSL_NULL_WITH_NULL_NULL, unsupported - CIPHER(SSL_RSA_WITH_NULL_SHA, false) - CIPHER(SSL_RSA_WITH_NULL_MD5, false) - CIPHER(TLS_RSA_WITH_NULL_SHA256, false) - - CIPHER(SSL_RSA_WITH_RC4_128_MD5, false) - CIPHER(SSL_RSA_WITH_RC4_128_SHA, false) - CIPHER(SSL_RSA_WITH_3DES_EDE_CBC_SHA, false) - - CIPHER(SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, false) - CIPHER(SSL_DH_anon_WITH_RC4_128_MD5, true) - CIPHER(SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, true) - CIPHER(TLS_DHE_RSA_WITH_AES_128_CBC_SHA, false) - CIPHER(TLS_DH_anon_WITH_AES_128_CBC_SHA, true) - CIPHER(TLS_DHE_RSA_WITH_AES_256_CBC_SHA, false) - CIPHER(TLS_DH_anon_WITH_AES_256_CBC_SHA, true) - - CIPHER(TLS_RSA_WITH_AES_128_CBC_SHA, false) - CIPHER(TLS_RSA_WITH_AES_256_CBC_SHA, false) - - - CIPHER(TLS_PSK_WITH_AES_128_CBC_SHA, true) - CIPHER(TLS_PSK_WITH_AES_256_CBC_SHA384, true) - CIPHER(TLS_PSK_WITH_AES_128_CBC_SHA256, true) - CIPHER(TLS_PSK_WITH_AES_256_CBC_SHA, true) - CIPHER(TLS_PSK_WITH_AES_128_CBC_SHA, true) - CIPHER(TLS_PSK_WITH_RC4_128_SHA, true) - CIPHER(TLS_PSK_WITH_3DES_EDE_CBC_SHA, true) - CIPHER(TLS_PSK_WITH_NULL_SHA384, true) - CIPHER(TLS_PSK_WITH_NULL_SHA256, true) - CIPHER(TLS_PSK_WITH_NULL_SHA, true) + CIPHER(SSL_RSA_WITH_NULL_SHA, false, true) + CIPHER(SSL_RSA_WITH_NULL_MD5, false, true) + CIPHER(TLS_RSA_WITH_NULL_SHA256, false, true) + + CIPHER(SSL_RSA_WITH_3DES_EDE_CBC_SHA, false, true) + + CIPHER(SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, false, true) + CIPHER(SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, true, true) + CIPHER(TLS_DHE_RSA_WITH_AES_128_CBC_SHA, false, true) + CIPHER(TLS_DH_anon_WITH_AES_128_CBC_SHA, true, true) + CIPHER(TLS_DHE_RSA_WITH_AES_256_CBC_SHA, false, true) + CIPHER(TLS_DH_anon_WITH_AES_256_CBC_SHA, true, true) + + CIPHER(TLS_RSA_WITH_AES_128_CBC_SHA, false, true) + CIPHER(TLS_RSA_WITH_AES_256_CBC_SHA, false, true) + +#if 1 + CIPHER(TLS_PSK_WITH_AES_128_CBC_SHA, true, true) + CIPHER(TLS_PSK_WITH_AES_256_CBC_SHA384, true, true) + CIPHER(TLS_PSK_WITH_AES_128_CBC_SHA256, true, true) + CIPHER(TLS_PSK_WITH_AES_256_CBC_SHA, true, true) + CIPHER(TLS_PSK_WITH_AES_128_CBC_SHA, true, true) + CIPHER(TLS_PSK_WITH_3DES_EDE_CBC_SHA, true, true) + CIPHER(TLS_PSK_WITH_NULL_SHA384, true, true) + CIPHER(TLS_PSK_WITH_NULL_SHA256, true, true) + CIPHER(TLS_PSK_WITH_NULL_SHA, true, true) +#endif + + // Put all the RC4 ciphers at the end: no DTLS for them. + CIPHER(SSL_RSA_WITH_RC4_128_MD5, false, false) + CIPHER(SSL_RSA_WITH_RC4_128_SHA, false, false) + CIPHER(SSL_DH_anon_WITH_RC4_128_MD5, true, false) + CIPHER(TLS_PSK_WITH_RC4_128_SHA, true, false) #if 0 + // ECDH and ECDHE not supported on server yet CIPHER(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, false) CIPHER(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, false) @@ -131,22 +136,11 @@ static const CipherSuiteName ciphers[] = { #endif #if 0 + // GCM not supported yet CIPHER(TLS_RSA_WITH_AES_256_GCM_SHA384, false) CIPHER(TLS_RSA_WITH_AES_128_GCM_SHA256, false) #endif -/* Export ciphers are disabled */ -#if 0 - CIPHER(SSL_RSA_EXPORT_WITH_RC4_40_MD5, false) - CIPHER(SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, false) - CIPHER(SSL_RSA_WITH_DES_CBC_SHA, false) - CIPHER(SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, false) - CIPHER(SSL_DHE_RSA_WITH_DES_CBC_SHA, false) - CIPHER(SSL_DH_anon_EXPORT_WITH_RC4_40_MD5, true) - CIPHER(SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA, true) - CIPHER(SSL_DH_anon_WITH_DES_CBC_SHA, true) -#endif - { -1 } }; @@ -302,13 +296,14 @@ static OSStatus SocketRead(SSLConnectionRef conn, void *data, size_t *length) ssize_t ret; do { ret = read((int)conn, ptr, len); - } while ((ret < 0) && (errno == EAGAIN || errno == EINTR)); + } while ((ret < 0) && (errno == EINPROGRESS || errno == EAGAIN || errno == EINTR)); if (ret > 0) { len -= ret; ptr += ret; + } else { + printf("read error(%d): ret=%zd, errno=%d\n", (int)conn, ret, errno); + return -errno; } - else - return -36; } while (len > 0); *length = *length - len; @@ -387,6 +382,49 @@ out: return NULL; } +static bool check_peer_cert(SSLContextRef ctx, const ssl_test_handle *ssl, SecTrustRef *trust) +{ + /* verify peer cert chain */ + require_noerr(SSLCopyPeerTrust(ctx, trust), out); + SecTrustResultType trust_result = 0; + /* this won't verify without setting up a trusted anchor */ + require_noerr(SecTrustEvaluate(*trust, &trust_result), out); + + CFIndex n_certs = SecTrustGetCertificateCount(*trust); + /* fprintf(stderr, "%ld certs; trust_eval: %d\n", n_certs, trust_result); */ + + CFMutableArrayRef peer_cert_array = + CFArrayCreateMutable(NULL, n_certs, &kCFTypeArrayCallBacks); + CFMutableArrayRef orig_peer_cert_array = + CFArrayCreateMutableCopy(NULL, n_certs, ssl->certs); + while (n_certs--) + CFArrayInsertValueAtIndex(peer_cert_array, 0, + SecTrustGetCertificateAtIndex(*trust, n_certs)); + + SecIdentityRef ident = + (SecIdentityRef)CFArrayGetValueAtIndex(orig_peer_cert_array, 0); + SecCertificateRef peer_cert = NULL; + require_noerr(SecIdentityCopyCertificate(ident, &peer_cert), out); + CFArraySetValueAtIndex(orig_peer_cert_array, 0, peer_cert); + CFRelease(peer_cert); + + require(CFEqual(orig_peer_cert_array, peer_cert_array), out); + CFRelease(orig_peer_cert_array); + CFRelease(peer_cert_array); + + /* + CFStringRef cert_name = SecCertificateCopySubjectSummary(cert); + char cert_name_buffer[1024]; + require(CFStringGetFileSystemRepresentation(cert_name, + cert_name_buffer, sizeof(cert_name_buffer)), out); + fprintf(stderr, "cert name: %s\n", cert_name_buffer); + CFRelease(trust); + */ + return true; +out: + return false; +} + static void *securetransport_ssl_thread(void *arg) { OSStatus ortn; @@ -394,56 +432,28 @@ static void *securetransport_ssl_thread(void *arg) SSLContextRef ctx = ssl->st; SecTrustRef trust = NULL; bool got_server_auth = false, got_client_cert_req = false; + SSLSessionState ssl_state; pthread_setname_np(ssl->is_server?"server thread":"client thread"); + require_noerr(ortn=SSLGetSessionState(ctx,&ssl_state), out); + require_action(ssl_state==kSSLIdle, out, ortn = -1); + //uint64_t start = mach_absolute_time(); do { ortn = SSLHandshake(ctx); + require_noerr(SSLGetSessionState(ctx,&ssl_state), out); if (ortn == errSSLPeerAuthCompleted) { + require_action(ssl_state==kSSLHandshake, out, ortn = -1); require_string(!got_server_auth, out, "second server auth"); require_string(!got_client_cert_req, out, "got client cert req before server auth"); got_server_auth = true; require_string(!trust, out, "Got errSSLServerAuthCompleted twice?"); - /* verify peer cert chain */ - require_noerr(SSLCopyPeerTrust(ctx, &trust), out); - SecTrustResultType trust_result = 0; - /* this won't verify without setting up a trusted anchor */ - require_noerr(SecTrustEvaluate(trust, &trust_result), out); - - CFIndex n_certs = SecTrustGetCertificateCount(trust); - /*fprintf(stderr, "%ld certs; trust_eval: %d\n", n_certs, trust_result); */ - - CFMutableArrayRef peer_cert_array = - CFArrayCreateMutable(NULL, n_certs, &kCFTypeArrayCallBacks); - CFMutableArrayRef orig_peer_cert_array = - CFArrayCreateMutableCopy(NULL, n_certs, ssl->certs); - while (n_certs--) - CFArrayInsertValueAtIndex(peer_cert_array, 0, - SecTrustGetCertificateAtIndex(trust, n_certs)); - - SecIdentityRef ident = - (SecIdentityRef)CFArrayGetValueAtIndex(orig_peer_cert_array, 0); - SecCertificateRef peer_cert = NULL; - require_noerr(SecIdentityCopyCertificate(ident, &peer_cert), out); - CFArraySetValueAtIndex(orig_peer_cert_array, 0, peer_cert); - CFRelease(peer_cert); - - require(CFEqual(orig_peer_cert_array, peer_cert_array), out); - CFRelease(orig_peer_cert_array); - CFRelease(peer_cert_array); - - /* - CFStringRef cert_name = SecCertificateCopySubjectSummary(cert); - char cert_name_buffer[1024]; - require(CFStringGetFileSystemRepresentation(cert_name, - cert_name_buffer, sizeof(cert_name_buffer)), out); - fprintf(stderr, "cert name: %s\n", cert_name_buffer); - CFRelease(trust); - */ + require_string(check_peer_cert(ctx, ssl, &trust), out, "Certificate check failed"); } else if (ortn == errSSLClientCertRequested) { + require_action(ssl_state==kSSLHandshake, out, ortn = -1); require_string(!got_client_cert_req, out, "second client cert req"); require_string(got_server_auth, out, "didn't get server auth first"); got_client_cert_req = true; @@ -459,6 +469,8 @@ static void *securetransport_ssl_thread(void *arg) require_string(ssl->client_side_auth, out, "errSSLClientCertRequested in run not testing that"); require_noerr(SSLSetCertificate(ctx, ssl->certs), out); + } else if (ortn == errSSLWouldBlock) { + require_action(ssl_state==kSSLHandshake, out, ortn = -1); } } while (ortn == errSSLWouldBlock || ortn == errSSLServerAuthCompleted @@ -466,11 +478,18 @@ static void *securetransport_ssl_thread(void *arg) require_noerr_action_quiet(ortn, out, fprintf(stderr, "Fell out of SSLHandshake with error: %d\n", (int)ortn)); + require_action(ssl_state==kSSLConnected, out, ortn = -1); + if (!ssl->is_server && !ssl->dh_anonymous && !ssl->is_session_resume) { require_string(got_server_auth, out, "never got server auth"); if (ssl->client_side_auth) require_string(got_client_cert_req, out, "never got client cert req"); } + + if (!ssl->is_server && !ssl->dh_anonymous && ssl->is_session_resume) { + require_string(!got_server_auth, out, "got server auth during resumption??"); + require_string(check_peer_cert(ctx, ssl, &trust), out, "Certificate check failed (resumption case)"); + } //uint64_t elapsed = mach_absolute_time() - start; //fprintf(stderr, "setr elapsed: %lld\n", elapsed); @@ -496,21 +515,40 @@ static void *securetransport_ssl_thread(void *arg) // if (sessionWasResumed) fprintf(stderr, "st resumed session\n"); //hexdump(session_id_data, session_id_length); - unsigned char ibuf[4096], obuf[4096]; - size_t len; - if (ssl->is_server) { - SecRandomCopyBytes(kSecRandomDefault, sizeof(obuf), obuf); - require_noerr_quiet(ortn = SSLWrite(ctx, obuf, sizeof(obuf), &len), out); - require_action_quiet(len == sizeof(obuf), out, ortn = -1); - } - require_noerr_quiet(ortn = SSLRead(ctx, ibuf, sizeof(ibuf), &len), out); - require_action_quiet(len == sizeof(ibuf), out, ortn = -1); +#define BUFSIZE (8*1024) + unsigned char ibuf[BUFSIZE], obuf[BUFSIZE]; - if (ssl->is_server) { - require_noerr(memcmp(ibuf, obuf, sizeof(ibuf)), out); - } else { - require_noerr_quiet(ortn = SSLWrite(ctx, ibuf, sizeof(ibuf), &len), out); - require_action_quiet(len == sizeof(ibuf), out, ortn = -1); + for(int i=0; i<10; i++) { + size_t len; + if (ssl->is_server) { + memset(obuf, i, BUFSIZE); + // SecRandomCopyBytes(kSecRandomDefault, sizeof(obuf), obuf); + require_noerr(ortn = SSLWrite(ctx, obuf, BUFSIZE, &len), out); + require_action(len == BUFSIZE, out, ortn = -1); + + require_noerr(ortn = SSLWrite(ctx, obuf, 0, &len), out); + require_action(len == 0, out, ortn = -1); + } + + len=0; + while(lenis_server) { + require_noerr(memcmp(ibuf, obuf, BUFSIZE), out); + } else { + require_noerr(ortn = SSLWrite(ctx, ibuf, BUFSIZE, &len), out); + require_action(len == BUFSIZE, out, ortn = -1); + } } out: @@ -565,7 +603,7 @@ tests(void) for (l = 0; l<2; l++) { #endif SKIP:{ - //skip("Session resumption tests do not work at this point", 1, l != 1); + skip("This ciphersuite is not supported for DTLS", 1, !d || ciphers[i].dtls); int sp[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) exit(errno); diff --git a/libsecurity_ssl/regressions/ssl-43-ciphers.c b/Security/libsecurity_ssl/regressions/ssl-43-ciphers.c similarity index 92% rename from libsecurity_ssl/regressions/ssl-43-ciphers.c rename to Security/libsecurity_ssl/regressions/ssl-43-ciphers.c index 1030a281..4db1db75 100644 --- a/libsecurity_ssl/regressions/ssl-43-ciphers.c +++ b/Security/libsecurity_ssl/regressions/ssl-43-ciphers.c @@ -1,10 +1,26 @@ -// -// ssl-43-ciphers.c -// regressions -// -// Created by Fabrice Gautier on 6/7/11. -// Copyright 2011 Apple, Inc. All rights reserved. -// +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include #include @@ -52,7 +68,7 @@ can be looked up in ciphers(1). All SSL_DH_* and TLS_DH_* are disabled because neither openssl nor - securetranport support them: + securetransport support them: SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA, SSL_DH_DSS_WITH_DES_CBC_SHA, SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA, SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DH_RSA_WITH_DES_CBC_SHA, SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA, @@ -74,7 +90,9 @@ */ #define OPENSSL_SERVER "ariadne.apple.com" +//#define OPENSSL_SERVER "kuip.apple.com" #define GNUTLS_SERVER "ariadne.apple.com" +//#define GNUTLS_SERVER "kuip.apple.com" static struct { const char *host; @@ -84,13 +102,12 @@ static struct { } servers[] = { { OPENSSL_SERVER, 4000, 0, false}, //openssl s_server w/o client side auth { GNUTLS_SERVER, 5000, 1, false}, // gnutls-serv w/o client side auth - { "www.mikestoolbox.org", 442, 2, false}, // mike's w/o client side auth -// { "tls.secg.org", 40022, 3, false}, // secg ecc server w/o client side auth - This server generate DH params we dont support. - +// { "www.mikestoolbox.org", 442, 2, false}, // mike's w/o client side auth +// { "tls.secg.org", 40022, 3, false}, // secg ecc server w/o client side auth - This server generate DH params we didnt support, but this should be fixed now { OPENSSL_SERVER, 4010, 0, true}, //openssl s_server w/ client side auth { GNUTLS_SERVER, 5010, 1, true}, // gnutls-serv w/ client side auth - { "www.mikestoolbox.net", 442, 2, true}, // mike's w/ client side auth -// { "tls.secg.org", 8442, 3}, //secg ecc server w/ client side auth +// { "www.mikestoolbox.net", 442, 2, true}, // mike's w/ client side auth +// { "tls.secg.org", 8442, 3}, //secg ecc server w/ client side auth }; int nservers = sizeof(servers)/sizeof(servers[0]); @@ -188,7 +205,7 @@ const CipherSuiteName ciphers[] = { CIPHER(3, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, {0, 0, 0, 1}, false) #endif -#if 0 +#if 1 CIPHER(1, TLS_PSK_WITH_RC4_128_SHA, {1, 1, 0, 0}, true) CIPHER(1, TLS_PSK_WITH_3DES_EDE_CBC_SHA, {1, 1, 0, 0}, true) CIPHER(1, TLS_PSK_WITH_AES_128_CBC_SHA, {1, 1, 0, 0}, true) @@ -236,7 +253,7 @@ const CipherSuiteName ciphers[] = { CIPHER(SSL_DH_anon_WITH_DES_CBC_SHA, true, false, true, true) #endif - +#if 0 /* "Any" cipher suite - test the default configuration */ {0, SSL_NO_SUCH_CIPHERSUITE, "Any cipher 1", {1, 1, 1, 1}, false}, {0, SSL_NO_SUCH_CIPHERSUITE, "Any cipher 2", {2, 2, 0, 0}, false}, @@ -244,7 +261,7 @@ const CipherSuiteName ciphers[] = { // Those servers wont talk SSL3.0 because they have EC certs {1, SSL_NO_SUCH_CIPHERSUITE, "Any cipher 3", {3, 3, 0, 0}, false}, {1, SSL_NO_SUCH_CIPHERSUITE, "Any cipher 4", {4, 4, 0, 0}, false}, - +#endif { -1, -1, NULL, } }; @@ -437,9 +454,9 @@ static SSLContextRef make_ssl_ref(bool server, bool client_side_auth, bool dh_an require_noerr(SSLSetIOFuncs(ctx, (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out); require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)sock), out); - // static const char *peer_domain_name = "localhost"; - // require_noerr(SSLSetPeerDomainName(ctx, peer_domain_name, - // strlen(peer_domain_name)), out); + //static const char *peer_domain_name = "localhost"; + //require_noerr(SSLSetPeerDomainName(ctx, peer_domain_name, + // strlen(peer_domain_name)), out); if (!dh_anonymous) { @@ -631,7 +648,7 @@ tests(void) int i; int p, pr; - for (p=0; p @@ -55,9 +71,9 @@ typedef struct { #pragma mark SecureTransport support #if 0 -static void hexdump(const uint8_t *bytes, size_t len) { +static void hexdump(const char *s, const uint8_t *bytes, size_t len) { size_t ix; - printf("socket write(%p, %lu)\n", bytes, len); + printf("socket %s(%p, %lu)\n", s, bytes, len); for (ix = 0; ix < len; ++ix) { if (!(ix % 16)) printf("\n"); @@ -66,7 +82,7 @@ static void hexdump(const uint8_t *bytes, size_t len) { printf("\n"); } #else -#define hexdump(bytes, len) +#define hexdump(string, bytes, len) #endif static OSStatus SocketWrite(SSLConnectionRef h, const void *data, size_t *length) @@ -78,7 +94,7 @@ static OSStatus SocketWrite(SSLConnectionRef h, const void *data, size_t *length do { ssize_t ret; do { - hexdump(ptr, len); + hexdump("write", ptr, len); ret = write((int)conn, ptr, len); } while ((ret < 0) && (errno == EAGAIN || errno == EINTR)); if (ret > 0) { @@ -269,8 +285,8 @@ tests(void) ok(!server_err, "Server error = %d", server_err); - /* test i=0 should cause errSSLClosedAbort, 1 & 2 should cause errSSLBadRecordMac */ - ok(client_err==(i?errSSLBadRecordMac:errSSLClosedAbort), "Client error = %d", client_err); + /* tests 0/1 should cause errSSLClosedAbort, 2 should cause errSSLBadRecordMac */ + ok(client_err==((i==2)?errSSLBadRecordMac:errSSLClosedAbort), "Client error = %d", client_err); out: free(client); diff --git a/libsecurity_ssl/regressions/ssl-45-tls12.c b/Security/libsecurity_ssl/regressions/ssl-45-tls12.c similarity index 88% rename from libsecurity_ssl/regressions/ssl-45-tls12.c rename to Security/libsecurity_ssl/regressions/ssl-45-tls12.c index 1e97e89b..d6d69a9c 100644 --- a/libsecurity_ssl/regressions/ssl-45-tls12.c +++ b/Security/libsecurity_ssl/regressions/ssl-45-tls12.c @@ -1,10 +1,26 @@ -// -// ssl-43-ciphers.c -// regressions -// -// Created by Fabrice Gautier on 6/7/11. -// Copyright 2011 Apple, Inc. All rights reserved. -// +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include #include @@ -253,7 +269,6 @@ ssl_test_handle_create(int comm, SSLProtocol maxprot) return handle; } - struct s_server { char *host; int port; @@ -262,7 +277,7 @@ struct s_server { /* Good tls 1.2 servers */ {"encrypted.google.com", 443, kTLSProtocol12 }, {"www.amazon.com",443, kTLSProtocol12 }, - {"www.mikestoolbox.org",443, kTLSProtocol12 }, + //{"www.mikestoolbox.org",443, kTLSProtocol12 }, /* servers with issues */ {"vpp.visa.co.uk", 443, kTLSProtocol12 }, // Doesnt like SSL 3.0 in initial record layer version {"imap.softbank.jp",993, kTLSProtocol1 }, // softbank imap server, there are multiple servers behind this, one of them is not able to handle downgrading to TLS 1.2 properly (126.240.66.17). @@ -297,6 +312,7 @@ tests(void) r=securetransport(client); ok(!r, "handshake failed with err=%ld - %s:%d (try %d)", (long)r, servers[p].host, servers[p].port, loops); + free(client); close(s); } } } diff --git a/libsecurity_ssl/regressions/ssl-46-SSLGetSupportedCiphers.c b/Security/libsecurity_ssl/regressions/ssl-46-SSLGetSupportedCiphers.c similarity index 91% rename from libsecurity_ssl/regressions/ssl-46-SSLGetSupportedCiphers.c rename to Security/libsecurity_ssl/regressions/ssl-46-SSLGetSupportedCiphers.c index 94daab83..4c0e02b0 100644 --- a/libsecurity_ssl/regressions/ssl-46-SSLGetSupportedCiphers.c +++ b/Security/libsecurity_ssl/regressions/ssl-46-SSLGetSupportedCiphers.c @@ -1,10 +1,26 @@ -// -// ssl-46-SSLGetSupportedCiphers.c -// libsecurity_ssl -// -// Created by Fabrice Gautier on 10/15/12. -// -// +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include #include diff --git a/libsecurity_ssl/regressions/ssl-47-falsestart.c b/Security/libsecurity_ssl/regressions/ssl-47-falsestart.c similarity index 88% rename from libsecurity_ssl/regressions/ssl-47-falsestart.c rename to Security/libsecurity_ssl/regressions/ssl-47-falsestart.c index 6b6c61c0..90e7d6c2 100644 --- a/libsecurity_ssl/regressions/ssl-47-falsestart.c +++ b/Security/libsecurity_ssl/regressions/ssl-47-falsestart.c @@ -1,10 +1,26 @@ -// -// ssl-46-falsestart.c -// regressions -// -// Created by Fabrice Gautier on 6/7/11. -// Copyright 2011 Apple, Inc. All rights reserved. -// +/* + * Copyright (c) 2011,2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include #include @@ -235,7 +251,6 @@ static OSStatus securetransport(ssl_test_handle * ssl) /* this won't verify without setting up a trusted anchor */ require_noerr(SecTrustEvaluate(trust, &trust_result), out); } - } while(ortn == errSSLWouldBlock || ortn == errSSLServerAuthCompleted); //fprintf(stderr, "\nHTTP Request Sent\n"); @@ -266,8 +281,6 @@ out: return ortn; } - - static ssl_test_handle * ssl_test_handle_create(int comm, SSLProtocol maxprot, Boolean false_start) { @@ -288,7 +301,7 @@ struct s_server { /* Good tls 1.2 servers */ {"encrypted.google.com", 443, kTLSProtocol12 }, {"www.amazon.com",443, kTLSProtocol12 }, - {"www.mikestoolbox.org",443, kTLSProtocol12 }, + //{"www.mikestoolbox.org",443, kTLSProtocol12 }, }; #define NSERVERS (int)(sizeof(servers)/sizeof(servers[0])) @@ -321,6 +334,7 @@ tests(void) ok(!r, "handshake failed with err=%ld - %s:%d (try %d), false start=%d", (long)r, servers[p].host, servers[p].port, loops, fs); close(s); + free(client); } } } } diff --git a/Security/libsecurity_ssl/regressions/ssl-48-split.c b/Security/libsecurity_ssl/regressions/ssl-48-split.c new file mode 100644 index 00000000..940628d3 --- /dev/null +++ b/Security/libsecurity_ssl/regressions/ssl-48-split.c @@ -0,0 +1,357 @@ +// +// ssl-48-crashes.c +// libsecurity_ssl +// +// + + +#include +#include +#include +#include +#include + +#include + +#include +#include /* SSLSetOption */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#if TARGET_OS_IPHONE +#include +#endif + +#include "ssl_regressions.h" +#include "ssl-utils.h" + +#include + + +typedef struct { + SSLContextRef st; + bool is_server; + int comm; + CFArrayRef certs; + int write_counter; + tls_stream_parser_t parser; + size_t write_size; +} ssl_test_handle; + + +#pragma mark - +#pragma mark SecureTransport support + +#if 0 +static void hexdump(const char *s, const uint8_t *bytes, size_t len) { + size_t ix; + printf("socket %s(%p, %lu)\n", s, bytes, len); + for (ix = 0; ix < len; ++ix) { + if (!(ix % 16)) + printf("\n"); + printf("%02X ", bytes[ix]); + } + printf("\n"); +} +#else +#define hexdump(string, bytes, len) +#endif + +static OSStatus SocketWrite(SSLConnectionRef h, const void *data, size_t *length) +{ + ssl_test_handle *handle =(ssl_test_handle *)h; + int conn = handle->comm; + size_t len = *length; + uint8_t *ptr = (uint8_t *)data; + + if(handle->is_server) { + //printf("SocketWrite: server write len=%zd\n", len); + + tls_buffer buffer; + buffer.data = ptr; + buffer.length = len; + tls_stream_parser_parse(handle->parser, buffer); + } + + do { + ssize_t ret; + do { + hexdump("write", ptr, len); + ret = write((int)conn, ptr, len); + } while ((ret < 0) && (errno == EAGAIN || errno == EINTR)); + if (ret > 0) { + len -= ret; + ptr += ret; + } + else + return -36; + } while (len > 0); + + *length = *length - len; + return errSecSuccess; +} + +static OSStatus SocketRead(SSLConnectionRef h, void *data, size_t *length) +{ + const ssl_test_handle *handle=h; + int conn = handle->comm; + size_t len = *length; + uint8_t *ptr = (uint8_t *)data; + + + do { + ssize_t ret; + do { + ret = read((int)conn, ptr, len); + } while ((ret < 0) && (errno == EAGAIN || errno == EINTR)); + if (ret > 0) { + len -= ret; + ptr += ret; + } + else + return -36; + } while (len > 0); + + if(len!=0) + printf("Something went wrong here... len=%d\n", (int)len); + + *length = *length - len; + return errSecSuccess; +} + +static int process(tls_stream_parser_ctx_t ctx, tls_buffer record) +{ + ssl_test_handle *handle = (ssl_test_handle *)ctx; + + // printf("processing record len=%zd, type=%d\n", record.length, record.data[0]); + if(record.data[0]==tls_record_type_AppData) { + handle->write_counter++; + // printf("record count = %d\n", handle->write_counter); + } + + return 0; +} + + +static void *securetransport_ssl_thread(void *arg) +{ + OSStatus ortn; + ssl_test_handle * ssl = (ssl_test_handle *)arg; + SSLContextRef ctx = ssl->st; + bool got_server_auth = false; + + //uint64_t start = mach_absolute_time(); + do { + ortn = SSLHandshake(ctx); + + if (ortn == errSSLServerAuthCompleted) + { + require_string(!got_server_auth, out, "second server auth"); + got_server_auth = true; + } + } while (ortn == errSSLWouldBlock + || ortn == errSSLServerAuthCompleted); + + require_noerr_action_quiet(ortn, out, + fprintf(stderr, "Fell out of SSLHandshake with error: %d\n", (int)ortn)); + + unsigned char ibuf[90000], obuf[45000]; + + if (ssl->is_server) { + size_t len; + SecRandomCopyBytes(kSecRandomDefault, ssl->write_size, obuf); + require_noerr(ortn = SSLWrite(ctx, obuf, ssl->write_size, &len), out); + require_action(len == ssl->write_size, out, ortn = -1); + require_noerr(ortn = SSLWrite(ctx, obuf, ssl->write_size, &len), out); + require_action(len == ssl->write_size, out, ortn = -1); + } else { + size_t len = ssl->write_size*2; + size_t olen; + unsigned char *p = ibuf; + while (len) { + require_noerr(ortn = SSLRead(ctx, p, len, &olen), out); + len -= olen; + p += olen; + } + } + +out: + SSLClose(ctx); + CFRelease(ctx); + close(ssl->comm); + pthread_exit((void *)(intptr_t)ortn); + return NULL; +} + +static void +ssl_test_handle_destroy(ssl_test_handle *handle) +{ + if(handle) { + if(handle->parser) tls_stream_parser_destroy(handle->parser); + free(handle); + } +} + +static ssl_test_handle * +ssl_test_handle_create(bool server, int comm, CFArrayRef certs) +{ + ssl_test_handle *handle = calloc(1, sizeof(ssl_test_handle)); + SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, server?kSSLServerSide:kSSLClientSide, kSSLStreamType); + + require(handle, out); + require(ctx, out); + + require_noerr(SSLSetIOFuncs(ctx, + (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out); + require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)handle), out); + + if (server) + require_noerr(SSLSetCertificate(ctx, certs), out); + + require_noerr(SSLSetSessionOption(ctx, + kSSLSessionOptionBreakOnServerAuth, true), out); + + /* Tell SecureTransport to not check certs itself: it will break out of the + handshake to let us take care of it instead. */ + require_noerr(SSLSetEnableCertVerify(ctx, false), out); + + handle->is_server = server; + handle->comm = comm; + handle->certs = certs; + handle->st = ctx; + handle->write_counter = 0; + handle->parser = tls_stream_parser_create(handle, process); + + return handle; + +out: + if (handle) free(handle); + if (ctx) CFRelease(ctx); + return NULL; +} + +static SSLCipherSuite ciphers[] = { + TLS_RSA_WITH_AES_128_CBC_SHA, + //FIXME: re-enable this test when its fixed. + //TLS_RSA_WITH_RC4_128_SHA, +}; +static int nciphers = sizeof(ciphers)/sizeof(ciphers[0]); + +static SSLProtocolVersion versions[] = { + kSSLProtocol3, + kTLSProtocol1, + kTLSProtocol11, + kTLSProtocol12, +}; +static int nversions = sizeof(versions)/sizeof(versions[0]); + +// { write size, expected count when nosplit, expected count when split } +static size_t wsizes[][3] = { + { 1, 2, 2 }, + { 2, 2, 3 }, + { 3, 2, 3 }, + { 4, 2, 3 }, + { 16384, 2, 3 }, + { 16385, 4, 4 }, + { 16386, 4, 6 }, + { 16387, 4, 7 }, + { 16388, 4, 7 }, + { 32768, 4, 7 }, + { 32769, 6, 7 }, + { 32770, 6, 8 }, + { 32771, 6, 10 }, + { 32772, 6, 11 }, + { 32773, 6, 11 }, +}; +static int nwsizes = sizeof(wsizes)/sizeof(wsizes[0]); + +static void +tests(void) +{ + pthread_t client_thread, server_thread; + CFArrayRef server_certs = server_chain(); + ok(server_certs, "got server certs"); + + int i,j,k,s; + + for(i=0; iwrite_size = wsizes[k][0]; + client->write_size = wsizes[k][0]; + + require(client, out); + require(server, out); + + require_noerr(SSLSetProtocolVersionMax(client->st, versions[j]), out); + require_noerr(SSLSetEnabledCiphers(client->st, &ciphers[i], 1), out); + if(s) { + // s=0: default (should be enabled) + // s=1: explicit enable + // s=2: expliciti disable + require_noerr(SSLSetSessionOption(server->st, kSSLSessionOptionSendOneByteRecord, (s==1)?true:false), out); + } + // printf("**** Test Case: i=%d, j=%d, k=%d (%zd), s=%d ****\n", i, j, k, wsizes[k][0], s); + + pthread_create(&client_thread, NULL, securetransport_ssl_thread, client); + pthread_create(&server_thread, NULL, securetransport_ssl_thread, server); + + int server_err, client_err; + pthread_join(client_thread, (void*)&client_err); + pthread_join(server_thread, (void*)&server_err); + + ok(!server_err, "Server error = %d", server_err); + ok(!client_err, "Client error = %d", client_err); + + /* one byte split is expected only for AES when using TLS 1.0 or lower, and when not disabled */ + bool expected_split = (i==0) && (s!=2) && (versions[j]<=kTLSProtocol1); + int expected_count = (int)(expected_split ? wsizes[k][2]: wsizes[k][1]); + + is(server->write_counter, expected_count, "wrong number of data records"); + + // fprintf(stderr, "Server write counter = %d, expected %d\n", server->write_counter, expected_count); + +out: + ssl_test_handle_destroy(client); + ssl_test_handle_destroy(server); + + } + CFReleaseNull(server_certs); +} + +int ssl_48_split(int argc, char *const *argv) +{ + + plan_tests(1 + nciphers*nversions*nwsizes*3 * 3); + + + tests(); + + return 0; +} diff --git a/Security/libsecurity_ssl/regressions/ssl-49-sni.c b/Security/libsecurity_ssl/regressions/ssl-49-sni.c new file mode 100644 index 00000000..9018e625 --- /dev/null +++ b/Security/libsecurity_ssl/regressions/ssl-49-sni.c @@ -0,0 +1,273 @@ +// +// ssl-49-sni.c +// libsecurity_ssl +// +// + + +#include +#include +#include +#include +#include + +#include + +#include +#include /* SSLSetOption */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#if TARGET_OS_IPHONE +#include +#endif + +#include "ssl_regressions.h" +#include "ssl-utils.h" + +#include +#include +#include + +/* extern struct ccrng_state *ccDRBGGetRngState(); */ +#include +#define CCRNGSTATE ccDRBGGetRngState() + + +typedef struct { + SSLContextRef st; + tls_stream_parser_t parser; + tls_record_t record; + tls_handshake_t hdsk; +} ssl_test_handle; + + +#pragma mark - +#pragma mark SecureTransport support + +#if 0 +static void hexdump(const char *s, const uint8_t *bytes, size_t len) { + size_t ix; + printf("socket %s(%p, %lu)\n", s, bytes, len); + for (ix = 0; ix < len; ++ix) { + if (!(ix % 16)) + printf("\n"); + printf("%02X ", bytes[ix]); + } + printf("\n"); +} +#else +#define hexdump(string, bytes, len) +#endif + +static OSStatus SocketWrite(SSLConnectionRef h, const void *data, size_t *length) +{ + ssl_test_handle *handle =(ssl_test_handle *)h; + + size_t len = *length; + uint8_t *ptr = (uint8_t *)data; + + tls_buffer buffer; + buffer.data = ptr; + buffer.length = len; + return tls_stream_parser_parse(handle->parser, buffer); +} + +static OSStatus SocketRead(SSLConnectionRef h, void *data, size_t *length) +{ + return -36; +} + +static int process(tls_stream_parser_ctx_t ctx, tls_buffer record) +{ + ssl_test_handle *h = (ssl_test_handle *)ctx; + tls_buffer decrypted; + uint8_t ct; + int err; + + decrypted.length = tls_record_decrypted_size(h->record, record.length); + decrypted.data = malloc(decrypted.length); + + require_action(decrypted.data, errOut, err=ENOMEM); + require_noerr((err=tls_record_decrypt(h->record, record, &decrypted, &ct)), errOut); + err=tls_handshake_process(h->hdsk, decrypted, ct); + +errOut: + return err; +} + + +static int +tls_handshake_message_callback(tls_handshake_ctx_t ctx, tls_handshake_message_t event) +{ + int err = 0; + + switch(event) { + case tls_handshake_message_client_hello: + err = -1234; + break; + default: + err = -1; + break; + } + + return err; +} + +static int +tls_handshake_set_protocol_version(tls_handshake_ctx_t ctx, tls_protocol_version protocolVersion) +{ + return 0; +} + +static int +tls_handshake_write(tls_handshake_ctx_t ctx, const tls_buffer data, uint8_t content_type) +{ + return -36; +} + +static int +tls_handshake_set_retransmit_timer(tls_handshake_ctx_t ctx, int attempt) +{ + return -1; +} + + +static +tls_handshake_callbacks_t tls_handshake_callbacks = { + .message = tls_handshake_message_callback, + .set_protocol_version = tls_handshake_set_protocol_version, + .write = tls_handshake_write, + .set_retransmit_timer = tls_handshake_set_retransmit_timer, +}; + + +static void +ssl_test_handle_destroy(ssl_test_handle *handle) +{ + if(handle) { + if(handle->parser) tls_stream_parser_destroy(handle->parser); + if(handle->record) tls_record_destroy(handle->record); + if(handle->hdsk) tls_handshake_destroy(handle->hdsk); + if(handle->st) CFRelease(handle->st); + free(handle); + } +} + +static uint16_t ciphers[] = { + TLS_RSA_WITH_AES_128_CBC_SHA, + //FIXME: re-enable this test when its fixed. + //TLS_RSA_WITH_RC4_128_SHA, +}; +static int nciphers = sizeof(ciphers)/sizeof(ciphers[0]); + + +static ssl_test_handle * +ssl_test_handle_create(bool server) +{ + ssl_test_handle *handle = calloc(1, sizeof(ssl_test_handle)); + SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, server?kSSLServerSide:kSSLClientSide, kSSLStreamType); + + require(handle, out); + require(ctx, out); + + require_noerr(SSLSetIOFuncs(ctx, + (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out); + require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)handle), out); + + require_noerr(SSLSetSessionOption(ctx, + kSSLSessionOptionBreakOnServerAuth, true), out); + + /* Tell SecureTransport to not check certs itself: it will break out of the + handshake to let us take care of it instead. */ + require_noerr(SSLSetEnableCertVerify(ctx, false), out); + + handle->st = ctx; + handle->parser = tls_stream_parser_create(handle, process); + handle->record = tls_record_create(false, CCRNGSTATE); + handle->hdsk = tls_handshake_create(false, true); // server. + tls_handshake_set_ciphersuites(handle->hdsk, ciphers, nciphers); + + tls_handshake_set_callbacks(handle->hdsk, &tls_handshake_callbacks, handle); + + return handle; + +out: + if (handle) free(handle); + if (ctx) CFRelease(ctx); + return NULL; +} + +static SSLProtocolVersion versions[] = { + kSSLProtocol3, + kTLSProtocol1, + kTLSProtocol11, + kTLSProtocol12, +}; +static int nversions = sizeof(versions)/sizeof(versions[0]); + +static char peername[] = "peername"; + +static void +tests(void) +{ + int j; + OSStatus ortn; + + for(j=0; jst, versions[j]), out); + require_noerr(SSLSetPeerDomainName(client->st, peername, sizeof(peername)), out); + + ortn = SSLHandshake(client->st); + + ok(ortn==-1234, "Unexpected Handshake exit code"); + + sni = tls_handshake_get_sni_hostname(client->hdsk); + + if(versions[j]==kSSLProtocol3) { + ok(sni==NULL || sni->data==NULL,"Unexpected SNI"); + } else { + ok(sni!=NULL && sni->data!=NULL && + sni->length == sizeof(peername) && + (memcmp(sni->data, peername, sizeof(peername))==0), + "SNI does not match"); + } + +out: + ssl_test_handle_destroy(client); + + } +} + +int ssl_49_sni(int argc, char *const *argv) +{ + + plan_tests(8); + + + tests(); + + return 0; +} diff --git a/Security/libsecurity_ssl/regressions/ssl-50-server.c b/Security/libsecurity_ssl/regressions/ssl-50-server.c new file mode 100644 index 00000000..513079b6 --- /dev/null +++ b/Security/libsecurity_ssl/regressions/ssl-50-server.c @@ -0,0 +1,266 @@ + +#include +#include +#include +#include +#include + +#include + +#include +#include /* SSLSetOption */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#if TARGET_OS_IPHONE +#include +#endif + +#include "ssl_regressions.h" +#include "ssl-utils.h" + +typedef struct { + SSLContextRef st; + int comm; + CFArrayRef certs; +} ssl_test_handle; + + +// MARK: - +// MARK: SecureTransport support + +#if 0 +static void hexdump(const uint8_t *bytes, size_t len) { + size_t ix; + printf("socket write(%p, %lu)\n", bytes, len); + for (ix = 0; ix < len; ++ix) { + if (!(ix % 16)) + printf("\n"); + printf("%02X ", bytes[ix]); + } + printf("\n"); +} +#else +#define hexdump(bytes, len) +#endif + + +/* Listen to on port */ +static int SocketListen(int port) +{ + struct sockaddr_in sa; + int sock; + int val = 1; + + if ((sock=socket(AF_INET, SOCK_STREAM, 0))==-1) { + perror("socket"); + return -errno; + } + + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&val, sizeof(val)); + + memset((char *) &sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_port = htons(port); + sa.sin_addr.s_addr = htonl(INADDR_ANY); + + if(bind (sock, (struct sockaddr *)&sa, sizeof(sa))==-1) + { + perror("bind"); + return -errno; + } + + if(listen(sock, 5)==-1) + { + perror("listen"); + return -errno; + } + + return sock; +} + + +static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length) +{ + size_t len = *length; + uint8_t *ptr = (uint8_t *)data; + + do { + ssize_t ret; + do { + hexdump(ptr, len); + ret = write((int)conn, ptr, len); + } while ((ret < 0) && (errno == EAGAIN || errno == EINTR)); + if (ret > 0) { + len -= ret; + ptr += ret; + } + else + return -36; + } while (len > 0); + + *length = *length - len; + return errSecSuccess; +} + +static OSStatus SocketRead(SSLConnectionRef conn, void *data, size_t *length) +{ + size_t len = *length; + uint8_t *ptr = (uint8_t *)data; + + do { + ssize_t ret; + do { + ret = read((int)conn, ptr, len); + } while ((ret < 0) && (errno == EINPROGRESS || errno == EAGAIN || errno == EINTR)); + if (ret > 0) { + len -= ret; + ptr += ret; + } else { + printf("read error(%d): ret=%zd, errno=%d\n", (int)conn, ret, errno); + return -errno; + } + } while (len > 0); + + *length = *length - len; + return errSecSuccess; +} + + +static SSLContextRef make_ssl_ref(bool server, int sock, CFArrayRef certs) +{ + SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, server?kSSLServerSide:kSSLClientSide, kSSLStreamType); + require(ctx, out); + + require_noerr(SSLSetIOFuncs(ctx, (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out); + require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)sock), out); + require_noerr(SSLSetCertificate(ctx, certs), out); + + return ctx; +out: + if (ctx) + CFRelease(ctx); + return NULL; +} + + +static ssl_test_handle * +ssl_test_handle_create(int comm, CFArrayRef certs) +{ + ssl_test_handle *handle = calloc(1, sizeof(ssl_test_handle)); + if (handle) { + handle->comm = comm; + handle->certs = certs; + handle->st = make_ssl_ref(true, comm, certs); + } + return handle; +} + +static void *securetransport_ssl_thread(void *arg) +{ + OSStatus ortn; + int sock = (int)arg; + + int socket = accept(sock, NULL, NULL); + + CFArrayRef server_certs = server_chain(); + ssl_test_handle * ssl = ssl_test_handle_create(socket, server_certs); + SSLContextRef ctx = ssl->st; + + pthread_setname_np("server thread"); + + //uint64_t start = mach_absolute_time(); + do { + ortn = SSLHandshake(ctx); + } while (ortn == errSSLWouldBlock); + + require_noerr_action_quiet(ortn, out, + fprintf(stderr, "Fell out of SSLHandshake with error: %d\n", (int)ortn)); + + //uint64_t elapsed = mach_absolute_time() - start; + //fprintf(stderr, "setr elapsed: %lld\n", elapsed); + + /* + SSLProtocol proto = kSSLProtocolUnknown; + require_noerr_quiet(SSLGetNegotiatedProtocolVersion(ctx, &proto), out); */ + + SSLCipherSuite cipherSuite; + require_noerr_quiet(ortn = SSLGetNegotiatedCipher(ctx, &cipherSuite), out); + //fprintf(stderr, "st negotiated %s\n", sslcipher_itoa(cipherSuite)); + + +out: + CFRelease(server_certs); + + SSLClose(ctx); + CFRelease(ctx); + if(ssl) { + close(ssl->comm); + free(ssl); + } + pthread_exit((void *)(intptr_t)ortn); + return NULL; +} + + + +static void +tests(void) +{ + pthread_t server_thread; + int socket; + + socket = SocketListen(4443); + + ok(socket>=0, "SocketListen failed"); + if(socket<0) { + return; + } + //fprintf(stderr, "session_id: %d\n", session_id); + + pthread_create(&server_thread, NULL, securetransport_ssl_thread, socket); + + system("/usr/bin/openssl s_client -msg -debug -connect localhost:4443"); + + int server_err; + pthread_join(server_thread, (void*)&server_err); + + ok(!server_err, "Server thread failed err=%d", server_err); +} + +int ssl_50_server(int argc, char *const *argv) +{ + + plan_tests(1 + 1 /*cert*/); + + + tests(); + + return 0; +} diff --git a/Security/libsecurity_ssl/regressions/ssl-51-state.c b/Security/libsecurity_ssl/regressions/ssl-51-state.c new file mode 100644 index 00000000..e9e9c26d --- /dev/null +++ b/Security/libsecurity_ssl/regressions/ssl-51-state.c @@ -0,0 +1,503 @@ +// +// ssl-51-state.c +// libsecurity_ssl +// + +#include +#include +#include +#include +#include + +#include + +#include +#include /* SSLSetOption */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#if TARGET_OS_IPHONE +#include +#endif + +#include "ssl_regressions.h" +#include "ssl-utils.h" + +#include +#include +#include + +#include + + +#define test_printf(x...) + +/* extern struct ccrng_state *ccDRBGGetRngState(); */ +#include +#define CCRNGSTATE ccDRBGGetRngState() + +struct RecQueueItem { + STAILQ_ENTRY(RecQueueItem) next; /* link to next queued entry or NULL */ + tls_buffer record; + size_t offset; /* byte reads from this one */ +}; + +typedef struct { + SSLContextRef st; + tls_stream_parser_t parser; + tls_record_t record; + tls_handshake_t hdsk; + STAILQ_HEAD(, RecQueueItem) rec_queue; // coretls server queue packet in this queue + int ready_count; +} ssl_test_handle; + + +static +int tls_buffer_alloc(tls_buffer *buf, size_t length) +{ + buf->data = malloc(length); + if(!buf->data) return -ENOMEM; + buf->length = length; + return 0; +} + +static +int tls_buffer_free(tls_buffer *buf) +{ + free(buf->data); + buf->data = NULL; + buf->length = 0; + return 0; +} + +#pragma mark - +#pragma mark SecureTransport support + +#if 0 +static void hexdump(const char *s, const uint8_t *bytes, size_t len) { + size_t ix; + printf("socket %s(%p, %lu)\n", s, bytes, len); + for (ix = 0; ix < len; ++ix) { + if (!(ix % 16)) + printf("\n"); + printf("%02X ", bytes[ix]); + } + printf("\n"); +} +#else +#define hexdump(string, bytes, len) +#endif + +static OSStatus SocketWrite(SSLConnectionRef h, const void *data, size_t *length) +{ + ssl_test_handle *handle =(ssl_test_handle *)h; + + size_t len = *length; + uint8_t *ptr = (uint8_t *)data; + + tls_buffer buffer; + buffer.data = ptr; + buffer.length = len; + return tls_stream_parser_parse(handle->parser, buffer); +} + +static OSStatus SocketRead(SSLConnectionRef h, void *data, size_t *length) +{ + ssl_test_handle *handle =(ssl_test_handle *)h; + + test_printf("%s: %p requesting len=%zd\n", __FUNCTION__, h, *length); + + struct RecQueueItem *item = STAILQ_FIRST(&handle->rec_queue); + + if(item==NULL) { + test_printf("%s: %p no data available\n", __FUNCTION__, h); + return errSSLWouldBlock; + } + + size_t avail = item->record.length - item->offset; + + test_printf("%s: %p %zd bytes available in %p\n", __FUNCTION__, h, avail, item); + + if(avail > *length) { + memcpy(data, item->record.data+item->offset, *length); + item->offset += *length; + } else { + memcpy(data, item->record.data+item->offset, avail); + *length = avail; + STAILQ_REMOVE_HEAD(&handle->rec_queue, next); + tls_buffer_free(&item->record); + free(item); + } + + test_printf("%s: %p %zd bytes read\n", __FUNCTION__, h, *length); + + + return 0; +} + +static int process(tls_stream_parser_ctx_t ctx, tls_buffer record) +{ + ssl_test_handle *h = (ssl_test_handle *)ctx; + tls_buffer decrypted; + uint8_t ct; + int err; + + test_printf("%s: %p processing %zd bytes\n", __FUNCTION__, ctx, record.length); + + + decrypted.length = tls_record_decrypted_size(h->record, record.length); + decrypted.data = malloc(decrypted.length); + + require_action(decrypted.data, errOut, err=-ENOMEM); + require_noerr((err=tls_record_decrypt(h->record, record, &decrypted, &ct)), errOut); + + test_printf("%s: %p decrypted %zd bytes, ct=%d\n", __FUNCTION__, ctx, decrypted.length, ct); + + err=tls_handshake_process(h->hdsk, decrypted, ct); + + test_printf("%s: %p processed, err=%d\n", __FUNCTION__, ctx, err); + +errOut: + return err; +} + +static int +tls_handshake_write_callback(tls_handshake_ctx_t ctx, const tls_buffer data, uint8_t content_type) +{ + int err = 0; + ssl_test_handle *handle = (ssl_test_handle *)ctx; + + test_printf("%s: %p writing data ct=%d, len=%zd\n", __FUNCTION__, ctx, content_type, data.length); + + struct RecQueueItem *item = malloc(sizeof(struct RecQueueItem)); + require_action(item, errOut, err=-ENOMEM); + + err=tls_buffer_alloc(&item->record, tls_record_encrypted_size(handle->record, content_type, data.length)); + require_noerr(err, errOut); + + err=tls_record_encrypt(handle->record, data, content_type, &item->record); + require_noerr(err, errOut); + + item->offset = 0; + + test_printf("%s: %p queing %zd encrypted bytes, item=%p\n", __FUNCTION__, ctx, item->record.length, item); + + STAILQ_INSERT_TAIL(&handle->rec_queue, item, next); + + return 0; + +errOut: + if(item) { + tls_buffer_free(&item->record); + free(item); + } + return err; +} + + +static int +tls_handshake_message_callback(tls_handshake_ctx_t ctx, tls_handshake_message_t event) +{ + ssl_test_handle __unused *handle = (ssl_test_handle *)ctx; + + test_printf("%s: %p event = %d\n", __FUNCTION__, handle, event); + + int err = 0; + + return err; +} + + + +static uint8_t appdata[] = "appdata"; + +tls_buffer appdata_buffer = { + .data = appdata, + .length = sizeof(appdata), +}; + + +static void +tls_handshake_ready_callback(tls_handshake_ctx_t ctx, bool write, bool ready) +{ + ssl_test_handle *handle = (ssl_test_handle *)ctx; + + test_printf("%s: %p %s ready=%d\n", __FUNCTION__, handle, write?"write":"read", ready); + + if(ready) { + if(write) { + if(handle->ready_count == 0) { + tls_handshake_request_renegotiation(handle->hdsk); + } else { + tls_handshake_write_callback(ctx, appdata_buffer, tls_record_type_AppData); + } + handle->ready_count++;; + } + } +} + +static int +tls_handshake_set_retransmit_timer_callback(tls_handshake_ctx_t ctx, int attempt) +{ + ssl_test_handle __unused *handle = (ssl_test_handle *)ctx; + + test_printf("%s: %p attempt = %d\n", __FUNCTION__, handle, attempt); + + return -1; +} + +static +int mySSLRecordInitPendingCiphersFunc(tls_handshake_ctx_t ref, + uint16_t selectedCipher, + bool server, + tls_buffer key) +{ + ssl_test_handle *handle = (ssl_test_handle *)ref; + + test_printf("%s: %p, cipher=%04x, server=%d\n", __FUNCTION__, ref, selectedCipher, server); + return tls_record_init_pending_ciphers(handle->record, selectedCipher, server, key); +} + +static +int mySSLRecordAdvanceWriteCipherFunc(tls_handshake_ctx_t ref) +{ + ssl_test_handle *handle = (ssl_test_handle *)ref; + test_printf("%s: %p\n", __FUNCTION__, ref); + return tls_record_advance_write_cipher(handle->record); +} + +static +int mySSLRecordRollbackWriteCipherFunc(tls_handshake_ctx_t ref) +{ + ssl_test_handle *handle = (ssl_test_handle *)ref; + test_printf("%s: %p\n", __FUNCTION__, ref); + return tls_record_rollback_write_cipher(handle->record); +} + +static +int mySSLRecordAdvanceReadCipherFunc(tls_handshake_ctx_t ref) +{ + ssl_test_handle *handle = (ssl_test_handle *)ref; + test_printf("%s: %p\n", __FUNCTION__, ref); + return tls_record_advance_read_cipher(handle->record); +} + +static +int mySSLRecordSetProtocolVersionFunc(tls_handshake_ctx_t ref, + tls_protocol_version protocolVersion) +{ + ssl_test_handle *handle = (ssl_test_handle *)ref; + test_printf("%s: %p, version=%04x\n", __FUNCTION__, ref, protocolVersion); + return tls_record_set_protocol_version(handle->record, protocolVersion); +} + + +static int +tls_handshake_save_session_data_callback(tls_handshake_ctx_t ctx, tls_buffer sessionKey, tls_buffer sessionData) +{ + ssl_test_handle __unused *handle = (ssl_test_handle *)ctx; + + test_printf("%s: %p\n", __FUNCTION__, handle); + + return -1; +} + +static int +tls_handshake_load_session_data_callback(tls_handshake_ctx_t ctx, tls_buffer sessionKey, tls_buffer *sessionData) +{ + ssl_test_handle __unused *handle = (ssl_test_handle *)ctx; + + test_printf("%s: %p\n", __FUNCTION__, handle); + + return -1; +} + +static int +tls_handshake_delete_session_data_callback(tls_handshake_ctx_t ctx, tls_buffer sessionKey) +{ + ssl_test_handle __unused *handle = (ssl_test_handle *)ctx; + + test_printf("%s: %p\n", __FUNCTION__, handle); + + return -1; +} + +static int +tls_handshake_delete_all_sessions_callback(tls_handshake_ctx_t ctx) +{ + ssl_test_handle __unused *handle = (ssl_test_handle *)ctx; + + test_printf("%s: %p\n", __FUNCTION__, handle); + + return -1; +} + +/* TLS callbacks */ +tls_handshake_callbacks_t tls_handshake_callbacks = { + .write = tls_handshake_write_callback, + .message = tls_handshake_message_callback, + .ready = tls_handshake_ready_callback, + .set_retransmit_timer = tls_handshake_set_retransmit_timer_callback, + .init_pending_cipher = mySSLRecordInitPendingCiphersFunc, + .advance_write_cipher = mySSLRecordAdvanceWriteCipherFunc, + .rollback_write_cipher = mySSLRecordRollbackWriteCipherFunc, + .advance_read_cipher = mySSLRecordAdvanceReadCipherFunc, + .set_protocol_version = mySSLRecordSetProtocolVersionFunc, + .load_session_data = tls_handshake_load_session_data_callback, + .save_session_data = tls_handshake_save_session_data_callback, + .delete_session_data = tls_handshake_delete_session_data_callback, + .delete_all_sessions = tls_handshake_delete_all_sessions_callback, +}; + + +static void +ssl_test_handle_destroy(ssl_test_handle *handle) +{ + if(handle) { + if(handle->parser) tls_stream_parser_destroy(handle->parser); + if(handle->record) tls_record_destroy(handle->record); + if(handle->hdsk) tls_handshake_destroy(handle->hdsk); + if(handle->st) CFRelease(handle->st); + free(handle); + } +} + +static uint16_t ciphers[] = { + TLS_PSK_WITH_AES_128_CBC_SHA, +}; +static int nciphers = sizeof(ciphers)/sizeof(ciphers[0]); + +static SSLCipherSuite ciphersuites[] = { + TLS_PSK_WITH_AES_128_CBC_SHA, +}; +static int nciphersuites = sizeof(ciphersuites)/sizeof(ciphersuites[0]); + + + +static uint8_t shared_secret[] = "secret"; + +tls_buffer psk_secret = { + .data = shared_secret, + .length = sizeof(shared_secret), +}; + +static ssl_test_handle * +ssl_test_handle_create(bool server) +{ + ssl_test_handle *handle = calloc(1, sizeof(ssl_test_handle)); + SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, server?kSSLServerSide:kSSLClientSide, kSSLStreamType); + + require(handle, out); + require(ctx, out); + + require_noerr(SSLSetIOFuncs(ctx, (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out); + require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)handle), out); + require_noerr(SSLSetSessionOption(ctx, kSSLSessionOptionBreakOnServerAuth, true), out); + require_noerr(SSLSetEnabledCiphers(ctx, ciphersuites, nciphersuites), out); + require_noerr(SSLSetPSKSharedSecret(ctx, shared_secret, sizeof(shared_secret)), out); + + handle->st = ctx; + handle->parser = tls_stream_parser_create(handle, process); + handle->record = tls_record_create(false, CCRNGSTATE); + handle->hdsk = tls_handshake_create(false, true); // server. + + require_noerr(tls_handshake_set_ciphersuites(handle->hdsk, ciphers, nciphers), out); + require_noerr(tls_handshake_set_callbacks(handle->hdsk, &tls_handshake_callbacks, handle), out); + require_noerr(tls_handshake_set_psk_secret(handle->hdsk, &psk_secret), out); + require_noerr(tls_handshake_set_renegotiation(handle->hdsk, true), out); + + // Initialize the record queue + STAILQ_INIT(&handle->rec_queue); + + return handle; + +out: + if (handle) free(handle); + if (ctx) CFRelease(ctx); + return NULL; +} + +static void +tests(void) +{ + OSStatus ortn; + + ssl_test_handle *client; + SSLSessionState state; + + client = ssl_test_handle_create(false); + + require_action(client, out, ortn = -1); + + ortn = SSLGetSessionState(client->st, &state); + require_noerr(ortn, out); + is(state, kSSLIdle, "State should be Idle"); + + do { + ortn = SSLHandshake(client->st); + + require_noerr(ortn = SSLGetSessionState(client->st, &state), out); + test_printf("SSLHandshake returned err=%d\n", (int)ortn); + + if (ortn == errSSLPeerAuthCompleted || ortn == errSSLWouldBlock) + { + require_action(state==kSSLHandshake, out, ortn = -1); + } + + } while(ortn==errSSLWouldBlock || + ortn==errSSLPeerAuthCompleted); + + + is(ortn, 0, "Unexpected SSLHandshake exit code"); + is(state, kSSLConnected, "State should be Connected"); + + uint8_t buffer[128]; + size_t available = 0; + + test_printf("Initial handshake done\n"); + + do { + ortn = SSLRead(client->st, buffer, sizeof(buffer), &available); + require_noerr(ortn = SSLGetSessionState(client->st, &state), out); + + test_printf("SSLRead returned err=%d, avail=%zd\n", (int)ortn, available); + if (ortn == errSSLPeerAuthCompleted) + { + require_action(state==kSSLHandshake, out, ortn = -1); + } + + } while(available==0); + + is(ortn, 0, "Unexpected SSLRead exit code"); + is(state, kSSLConnected, "State should be Connected"); + + +out: + is(ortn, 0, "Final result is non zero"); + ssl_test_handle_destroy(client); + +} + +int ssl_51_state(int argc, char *const *argv) +{ + + plan_tests(6); + + tests(); + + return 0; +} diff --git a/Security/libsecurity_ssl/regressions/ssl-utils.c b/Security/libsecurity_ssl/regressions/ssl-utils.c new file mode 100644 index 00000000..4970e1a7 --- /dev/null +++ b/Security/libsecurity_ssl/regressions/ssl-utils.c @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include + +#include "ssl-utils.h" + +#if TARGET_OS_IPHONE + +#include +#include +#include +#include + +#include "privkey-1.h" +#include "cert-1.h" + +static +CFArrayRef chain_from_der(const unsigned char *pkey_der, size_t pkey_der_len, const unsigned char *cert_der, size_t cert_der_len) +{ + SecKeyRef pkey = NULL; + SecCertificateRef cert = NULL; + SecIdentityRef ident = NULL; + CFArrayRef items = NULL; + + require(pkey = SecKeyCreateRSAPrivateKey(kCFAllocatorDefault, pkey_der, pkey_der_len, kSecKeyEncodingPkcs1), errOut); + require(cert = SecCertificateCreateWithBytes(kCFAllocatorDefault, cert_der, cert_der_len), errOut); + require(ident = SecIdentityCreate(kCFAllocatorDefault, cert, pkey), errOut); + require(items = CFArrayCreate(kCFAllocatorDefault, (const void **)&ident, 1, &kCFTypeArrayCallBacks), errOut); + +errOut: + CFReleaseSafe(pkey); + CFReleaseSafe(cert); + CFReleaseSafe(ident); + return items; +} + +#else + +#include "identity-1.h" +#define P12_PASSWORD "password" + +static +CFArrayRef chain_from_p12(const unsigned char *p12_data, size_t p12_len) +{ + char keychain_path[] = "/tmp/keychain.XXXXXX"; + + SecKeychainRef keychain = NULL; + CFArrayRef list = NULL; + CFDataRef data = NULL; + + SecExternalFormat format=kSecFormatPKCS12; + SecExternalItemType type=kSecItemTypeAggregate; + SecItemImportExportFlags flags=0; + SecKeyImportExportParameters params = {0,}; + CFArrayRef out = NULL; + + require_noerr(SecKeychainCopyDomainSearchList(kSecPreferencesDomainUser, &list), errOut); + require(mktemp(keychain_path), errOut); + require_noerr(SecKeychainCreate (keychain_path, strlen(P12_PASSWORD), P12_PASSWORD, + FALSE, NULL, &keychain), errOut); + require_noerr(SecKeychainSetDomainSearchList(kSecPreferencesDomainUser, list), errOut); // restores the previous search list + require(data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, p12_data, p12_len, kCFAllocatorNull), errOut); + + + params.passphrase=CFSTR("password"); + params.keyAttributes = CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_SENSITIVE; + + require_noerr(SecKeychainItemImport(data, CFSTR(".p12"), &format, &type, flags, + ¶ms, keychain, &out), errOut); + +errOut: + CFReleaseSafe(data); + CFReleaseSafe(keychain); + CFReleaseSafe(list); + + return out; +} + +#endif + +CFArrayRef server_chain(void) +{ +#if TARGET_OS_IPHONE + return chain_from_der(privkey_1_der, privkey_1_der_len, cert_1_der, cert_1_der_len); +#else + return chain_from_p12(identity_1_p12, identity_1_p12_len); +#endif +} + +CFArrayRef client_chain(void) +{ +#if TARGET_OS_IPHONE + return chain_from_der(privkey_1_der, privkey_1_der_len, cert_1_der, cert_1_der_len); +#else + return chain_from_p12(identity_1_p12, identity_1_p12_len); +#endif +} + +const char *ciphersuite_name(SSLCipherSuite cs) +{ + +#define C(x) case x: return #x; + switch (cs) { + + /* TLS 1.2 addenda, RFC 5246 */ + + /* Initial state. */ + C(TLS_NULL_WITH_NULL_NULL) + + /* Server provided RSA certificate for key exchange. */ + C(TLS_RSA_WITH_NULL_MD5) + C(TLS_RSA_WITH_NULL_SHA) + C(TLS_RSA_WITH_RC4_128_MD5) + C(TLS_RSA_WITH_RC4_128_SHA) + C(TLS_RSA_WITH_3DES_EDE_CBC_SHA) + C(TLS_RSA_WITH_AES_128_CBC_SHA) + C(TLS_RSA_WITH_AES_256_CBC_SHA) + C(TLS_RSA_WITH_NULL_SHA256) + C(TLS_RSA_WITH_AES_128_CBC_SHA256) + C(TLS_RSA_WITH_AES_256_CBC_SHA256) + + /* Server-authenticated (and optionally client-authenticated) Diffie-Hellman. */ + C(TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA) + C(TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA) + C(TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA) + C(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) + C(TLS_DH_DSS_WITH_AES_128_CBC_SHA) + C(TLS_DH_RSA_WITH_AES_128_CBC_SHA) + C(TLS_DHE_DSS_WITH_AES_128_CBC_SHA) + C(TLS_DHE_RSA_WITH_AES_128_CBC_SHA) + C(TLS_DH_DSS_WITH_AES_256_CBC_SHA) + C(TLS_DH_RSA_WITH_AES_256_CBC_SHA) + C(TLS_DHE_DSS_WITH_AES_256_CBC_SHA) + C(TLS_DHE_RSA_WITH_AES_256_CBC_SHA) + C(TLS_DH_DSS_WITH_AES_128_CBC_SHA256) + C(TLS_DH_RSA_WITH_AES_128_CBC_SHA256) + C(TLS_DHE_DSS_WITH_AES_128_CBC_SHA256) + C(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) + C(TLS_DH_DSS_WITH_AES_256_CBC_SHA256) + C(TLS_DH_RSA_WITH_AES_256_CBC_SHA256) + C(TLS_DHE_DSS_WITH_AES_256_CBC_SHA256) + C(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) + + /* Completely anonymous Diffie-Hellman */ + C(TLS_DH_anon_WITH_RC4_128_MD5) + C(TLS_DH_anon_WITH_3DES_EDE_CBC_SHA) + C(TLS_DH_anon_WITH_AES_128_CBC_SHA) + C(TLS_DH_anon_WITH_AES_256_CBC_SHA) + C(TLS_DH_anon_WITH_AES_128_CBC_SHA256) + C(TLS_DH_anon_WITH_AES_256_CBC_SHA256) + + /* Addenda from rfc 5288 AES Galois Counter Mode (GCM) Cipher Suites + for TLS. */ + C(TLS_RSA_WITH_AES_128_GCM_SHA256) + C(TLS_RSA_WITH_AES_256_GCM_SHA384) + C(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) + C(TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) + C(TLS_DH_RSA_WITH_AES_128_GCM_SHA256) + C(TLS_DH_RSA_WITH_AES_256_GCM_SHA384) + C(TLS_DHE_DSS_WITH_AES_128_GCM_SHA256) + C(TLS_DHE_DSS_WITH_AES_256_GCM_SHA384) + C(TLS_DH_DSS_WITH_AES_128_GCM_SHA256) + C(TLS_DH_DSS_WITH_AES_256_GCM_SHA384) + C(TLS_DH_anon_WITH_AES_128_GCM_SHA256) + C(TLS_DH_anon_WITH_AES_256_GCM_SHA384) + + /* ECDSA addenda, RFC 4492 */ + C(TLS_ECDH_ECDSA_WITH_NULL_SHA) + C(TLS_ECDH_ECDSA_WITH_RC4_128_SHA) + C(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA) + C(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA) + C(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA) + C(TLS_ECDHE_ECDSA_WITH_NULL_SHA) + C(TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) + C(TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA) + C(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) + C(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) + C(TLS_ECDH_RSA_WITH_NULL_SHA) + C(TLS_ECDH_RSA_WITH_RC4_128_SHA) + C(TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA) + C(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA) + C(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA) + C(TLS_ECDHE_RSA_WITH_NULL_SHA) + C(TLS_ECDHE_RSA_WITH_RC4_128_SHA) + C(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) + C(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) + C(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) + C(TLS_ECDH_anon_WITH_NULL_SHA) + C(TLS_ECDH_anon_WITH_RC4_128_SHA) + C(TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA) + C(TLS_ECDH_anon_WITH_AES_128_CBC_SHA) + C(TLS_ECDH_anon_WITH_AES_256_CBC_SHA) + + /* Addenda from rfc 5289 Elliptic Curve Cipher Suites with + HMAC SHA-256/384. */ + C(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) + C(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384) + C(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256) + C(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384) + C(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) + C(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) + C(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256) + C(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384) + + /* Addenda from rfc 5289 Elliptic Curve Cipher Suites with + SHA-256/384 and AES Galois Counter Mode (GCM) */ + C(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) + C(TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) + C(TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256) + C(TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384) + C(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) + C(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) + C(TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256) + C(TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384) + + /* RFC 5746 - Secure Renegotiation */ + C(TLS_EMPTY_RENEGOTIATION_INFO_SCSV) + + /* + * Tags for SSL 2 cipher kinds which are not specified + * for SSL 3. + */ + C(SSL_RSA_WITH_RC2_CBC_MD5) + C(SSL_RSA_WITH_IDEA_CBC_MD5) + C(SSL_RSA_WITH_DES_CBC_MD5) + C(SSL_RSA_WITH_3DES_EDE_CBC_MD5) + C(SSL_NO_SUCH_CIPHERSUITE) + + C(SSL_RSA_EXPORT_WITH_RC4_40_MD5) + C(SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5) + C(SSL_RSA_WITH_IDEA_CBC_SHA) + C(SSL_RSA_EXPORT_WITH_DES40_CBC_SHA) + C(SSL_RSA_WITH_DES_CBC_SHA) + C(SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA) + C(SSL_DH_DSS_WITH_DES_CBC_SHA) + C(SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA) + C(SSL_DH_RSA_WITH_DES_CBC_SHA) + C(SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA) + C(SSL_DHE_DSS_WITH_DES_CBC_SHA) + C(SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA) + C(SSL_DHE_RSA_WITH_DES_CBC_SHA) + C(SSL_DH_anon_EXPORT_WITH_RC4_40_MD5) + C(SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA) + C(SSL_DH_anon_WITH_DES_CBC_SHA) + C(SSL_FORTEZZA_DMS_WITH_NULL_SHA) + C(SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA) + + + default: + return "Unknown Ciphersuite"; + } + +} diff --git a/Security/libsecurity_ssl/regressions/ssl-utils.h b/Security/libsecurity_ssl/regressions/ssl-utils.h new file mode 100644 index 00000000..df57c694 --- /dev/null +++ b/Security/libsecurity_ssl/regressions/ssl-utils.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef __SSL_UTILS_H__ +#define __SSL_UTILS_H__ + +#include + +#define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) { CFRelease(_cf); } } +#define CFReleaseNull(CF) { CFTypeRef _cf = (CF); if (_cf) { (CF) = NULL; CFRelease(_cf); } } + +CFArrayRef server_chain(void); +CFArrayRef client_chain(void); + +const char *ciphersuite_name(SSLCipherSuite cs); + +#endif diff --git a/Security/libsecurity_ssl/regressions/ssl_regressions.h b/Security/libsecurity_ssl/regressions/ssl_regressions.h new file mode 100644 index 00000000..39bb18b5 --- /dev/null +++ b/Security/libsecurity_ssl/regressions/ssl_regressions.h @@ -0,0 +1,31 @@ +#include + +DISABLED_ONE_TEST(ssl_39_echo) + +#if TARGET_OS_IPHONE + +ONE_TEST(ssl_40_clientauth) +ONE_TEST(ssl_41_clientauth) + +#else + +DISABLED_ONE_TEST(ssl_40_clientauth) +DISABLED_ONE_TEST(ssl_41_clientauth) + +#endif + +ONE_TEST(ssl_42_ciphers) + +OFF_ONE_TEST(ssl_43_ciphers) + +ONE_TEST(ssl_44_crashes) +ONE_TEST(ssl_45_tls12) +ONE_TEST(ssl_46_SSLGetSupportedCiphers) +ONE_TEST(ssl_47_falsestart) +ONE_TEST(ssl_48_split) +// This one require a version of coreTLS that support SNI server side. (> coreTLS-17 ?) +OFF_ONE_TEST(ssl_49_sni) +OFF_ONE_TEST(ssl_50_server) + +ONE_TEST(ssl_51_state) + diff --git a/libsecurity_ssl/security_ssl b/Security/libsecurity_ssl/security_ssl similarity index 100% rename from libsecurity_ssl/security_ssl rename to Security/libsecurity_ssl/security_ssl diff --git a/Security/libsecurity_ssl/sslViewer/fileIo.c b/Security/libsecurity_ssl/sslViewer/fileIo.c new file mode 100644 index 00000000..802de34e --- /dev/null +++ b/Security/libsecurity_ssl/sslViewer/fileIo.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2001-2003,2006-2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * fileIo.c - simple file read/write utilities + */ + +#include +#include +#include +#include +#include +#include +#include +#include "fileIo.h" + +int writeFile( + const char *fileName, + const unsigned char *bytes, + unsigned numBytes) +{ + int rtn; + int fd; + + fd = open(fileName, O_RDWR | O_CREAT | O_TRUNC, 0600); + if(fd < 0) { + return errno; + } + rtn = lseek(fd, 0, SEEK_SET); + if(rtn < 0) { + return errno; + } + rtn = write(fd, bytes, (size_t)numBytes); + if(rtn != (int)numBytes) { + if(rtn >= 0) { + printf("writeFile: short write\n"); + } + rtn = EIO; + } + else { + rtn = 0; + } + close(fd); + return rtn; +} + +/* + * Read entire file. + */ +int readFile( + const char *fileName, + unsigned char **bytes, // mallocd and returned + unsigned *numBytes) // returned +{ + int rtn; + int fd; + unsigned char *buf; + struct stat sb; + unsigned size; + + *numBytes = 0; + *bytes = NULL; + fd = open(fileName, O_RDONLY, 0); + if(fd < 0) { + return errno; + } + rtn = fstat(fd, &sb); + if(rtn) { + goto errOut; + } + size = sb.st_size; + buf = malloc(size); + if(buf == NULL) { + rtn = ENOMEM; + goto errOut; + } + rtn = lseek(fd, 0, SEEK_SET); + if(rtn < 0) { + goto errOut; + } + rtn = read(fd, buf, (size_t)size); + if(rtn != (int)size) { + if(rtn >= 0) { + printf("readFile: short read\n"); + } + rtn = EIO; + } + else { + rtn = 0; + *bytes = buf; + *numBytes = size; + } +errOut: + close(fd); + return rtn; +} diff --git a/Security/libsecurity_ssl/sslViewer/fileIo.h b/Security/libsecurity_ssl/sslViewer/fileIo.h new file mode 100644 index 00000000..51e93287 --- /dev/null +++ b/Security/libsecurity_ssl/sslViewer/fileIo.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2001-2003,2006-2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * fileIo.h - simple file read/write utilities + */ + +#ifdef __cplusplus +extern "C" { +#endif + +int readFile( + const char *fileName, + unsigned char **bytes, // mallocd and returned + unsigned *numBytes); // returned + +int writeFile( + const char *fileName, + const unsigned char *bytes, + unsigned numBytes); + +#ifdef __cplusplus +} +#endif diff --git a/Security/libsecurity_ssl/sslViewer/ioSock.c b/Security/libsecurity_ssl/sslViewer/ioSock.c new file mode 100644 index 00000000..3c9b12db --- /dev/null +++ b/Security/libsecurity_ssl/sslViewer/ioSock.c @@ -0,0 +1,502 @@ +/* + * Copyright (c) 2006-2008,2010-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * ioSock.c - socket-based I/O routines for use with Secure Transport + */ + +#include "ioSock.h" +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* debugging for this module */ +#define SSL_OT_DEBUG 1 + +/* log errors to stdout */ +#define SSL_OT_ERRLOG 1 + +/* trace all low-level network I/O */ +#define SSL_OT_IO_TRACE 0 + +/* if SSL_OT_IO_TRACE, only log non-zero length transfers */ +#define SSL_OT_IO_TRACE_NZ 1 + +/* pause after each I/O (only meaningful if SSL_OT_IO_TRACE == 1) */ +#define SSL_OT_IO_PAUSE 0 + +/* print a stream of dots while I/O pending */ +#define SSL_OT_DOT 1 + +/* dump some bytes of each I/O (only meaningful if SSL_OT_IO_TRACE == 1) */ +#define SSL_OT_IO_DUMP 0 +#define SSL_OT_IO_DUMP_SIZE 256 + +/* indicate errSSLWouldBlock with a '.' */ +#define SSL_DISPL_WOULD_BLOCK 0 + +/* general, not-too-verbose debugging */ +#if SSL_OT_DEBUG +#define dprintf(s) printf s +#else +#define dprintf(s) +#endif + +/* errors --> stdout */ +#if SSL_OT_ERRLOG +#define eprintf(s) printf s +#else +#define eprintf(s) +#endif + +/* trace completion of every r/w */ +#if SSL_OT_IO_TRACE +static void tprintf( + const char *str, + UInt32 req, + UInt32 act, + const UInt8 *buf) +{ + #if SSL_OT_IO_TRACE_NZ + if(act == 0) { + return; + } + #endif + printf("%s(%u): moved (%u) bytes\n", str, (unsigned)req, (unsigned)act); + #if SSL_OT_IO_DUMP + { + unsigned i; + + for(i=0; i= (SSL_OT_IO_DUMP_SIZE - 1)) { + break; + } + } + printf("\n"); + } + #endif + #if SSL_OT_IO_PAUSE + { + char instr[20]; + printf("CR to continue: "); + gets(instr); + } + #endif +} + +#else +#define tprintf(str, req, act, buf) +#endif /* SSL_OT_IO_TRACE */ + +/* + * If SSL_OT_DOT, output a '.' every so often while waiting for + * connection. This gives user a chance to do something else with the + * UI. + */ + +#if SSL_OT_DOT + +static time_t lastTime = (time_t)0; +#define TIME_INTERVAL 3 + +static void outputDot() +{ + time_t thisTime = time(0); + + if((thisTime - lastTime) >= TIME_INTERVAL) { + printf("."); fflush(stdout); + lastTime = thisTime; + } +} +#else +#define outputDot() +#endif + + +/* + * One-time only init. + */ +void initSslOt(void) +{ + +} + +/* + * Connect to server. + */ +#define GETHOST_RETRIES 3 + +OSStatus MakeServerConnection( + const char *hostName, + int port, + int nonBlocking, // 0 or 1 + otSocket *socketNo, // RETURNED + PeerSpec *peer) // RETURNED +{ + struct sockaddr_in addr; + struct hostent *ent; + struct in_addr host; + int sock = 0; + + *socketNo = 0; + if (hostName[0] >= '0' && hostName[0] <= '9') + { + host.s_addr = inet_addr(hostName); + } + else { + unsigned dex; + /* seeing a lot of soft failures here that I really don't want to track down */ + for(dex=0; dexh_addr, sizeof(struct in_addr)); + } + sock = socket(AF_INET, SOCK_STREAM, 0); + addr.sin_addr = host; + addr.sin_port = htons((u_short)port); + + addr.sin_family = AF_INET; + if (connect(sock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) != 0) + { printf("connect returned error\n"); + return errSecIO; + } + + if(nonBlocking) { + /* OK to do this after connect? */ + int rtn = fcntl(sock, F_SETFL, O_NONBLOCK); + if(rtn == -1) { + perror("fctnl(O_NONBLOCK)"); + return errSecIO; + } + } + + peer->ipAddr = addr.sin_addr.s_addr; + peer->port = htons((u_short)port); + *socketNo = (otSocket)sock; + return errSecSuccess; +} + +/* + * Set up an otSocket to listen for client connections. Call once, then + * use multiple AcceptClientConnection calls. + */ +OSStatus ListenForClients( + int port, + int nonBlocking, // 0 or 1 + otSocket *socketNo) // RETURNED +{ + struct sockaddr_in addr; + struct hostent *ent; + int len; + int sock; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if(sock < 1) { + perror("socket"); + return errSecIO; + } + + int reuse = 1; + int err = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); + if (err != 0) { + perror("setsockopt"); + return err; + } + + ent = gethostbyname("localhost"); + if (!ent) { + perror("gethostbyname"); + return errSecIO; + } + memcpy(&addr.sin_addr, ent->h_addr, sizeof(struct in_addr)); + + addr.sin_port = htons((u_short)port); + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_family = AF_INET; + len = sizeof(struct sockaddr_in); + if (bind(sock, (struct sockaddr *) &addr, len)) { + int theErr = errno; + perror("bind"); + if(theErr == EADDRINUSE) { + return errSecOpWr; + } + else { + return errSecIO; + } + } + if(nonBlocking) { + int rtn = fcntl(sock, F_SETFL, O_NONBLOCK); + if(rtn == -1) { + perror("fctnl(O_NONBLOCK)"); + return errSecIO; + } + } + + for(;;) { + int rtn = listen(sock, 1); + switch(rtn) { + case 0: + *socketNo = (otSocket)sock; + rtn = errSecSuccess; + break; + case EWOULDBLOCK: + continue; + default: + perror("listen"); + rtn = errSecIO; + break; + } + return rtn; + } + /* NOT REACHED */ + return 0; +} + +/* + * Accept a client connection. + */ + +/* + * Currently we always get back a different peer port number on successive + * connections, no matter what the client is doing. To test for resumable + * session support, force peer port = 0. + */ +#define FORCE_ACCEPT_PEER_PORT_ZERO 1 + +OSStatus AcceptClientConnection( + otSocket listenSock, // obtained from ListenForClients + otSocket *acceptSock, // RETURNED + PeerSpec *peer) // RETURNED +{ + struct sockaddr_in addr; + int sock; + socklen_t len; + + len = sizeof(struct sockaddr_in); + do { + sock = accept((int)listenSock, (struct sockaddr *) &addr, &len); + if (sock < 0) { + if(errno == EAGAIN) { + /* nonblocking, no connection yet */ + continue; + } + else { + perror("accept"); + return errSecIO; + } + } + else { + break; + } + } while(1); + *acceptSock = (otSocket)sock; + peer->ipAddr = addr.sin_addr.s_addr; + #if FORCE_ACCEPT_PEER_PORT_ZERO + peer->port = 0; + #else + peer->port = ntohs(addr.sin_port); + #endif + return errSecSuccess; +} + +/* + * Shut down a connection. + */ +void endpointShutdown( + otSocket sock) +{ + close((int)sock); +} + +/* + * R/W. Called out from SSL. + */ +OSStatus SocketRead( + SSLConnectionRef connection, + void *data, /* owned by + * caller, data + * RETURNED */ + size_t *dataLength) /* IN/OUT */ +{ + UInt32 bytesToGo = *dataLength; + UInt32 initLen = bytesToGo; + UInt8 *currData = (UInt8 *)data; + int sock = (int)((long)connection); + OSStatus rtn = errSecSuccess; + UInt32 bytesRead; + ssize_t rrtn; + + *dataLength = 0; + + for(;;) { + bytesRead = 0; + /* paranoid check, ensure errno is getting written */ + errno = -555; + rrtn = recv(sock, currData, bytesToGo, 0); + if (rrtn <= 0) { + if(rrtn == 0) { + /* closed, EOF */ + rtn = errSSLClosedGraceful; + break; + } + int theErr = errno; + switch(theErr) { + case ENOENT: + /* + * Undocumented but I definitely see this. + * Non-blocking sockets only. Definitely retriable + * just like an EAGAIN. + */ + dprintf(("SocketRead RETRYING on ENOENT, rrtn %d\n", + (int)rrtn)); + /* normal... */ + //rtn = errSSLWouldBlock; + /* ...for temp testing.... */ + rtn = errSecIO; + break; + case ECONNRESET: + /* explicit peer abort */ + rtn = errSSLClosedAbort; + break; + case EAGAIN: + /* nonblocking, no data */ + rtn = errSSLWouldBlock; + break; + default: + dprintf(("SocketRead: read(%u) error %d, rrtn %d\n", + (unsigned)bytesToGo, theErr, (int)rrtn)); + rtn = errSecIO; + break; + } + /* in any case, we're done with this call if rrtn <= 0 */ + break; + } + bytesRead = rrtn; + bytesToGo -= bytesRead; + currData += bytesRead; + + if(bytesToGo == 0) { + /* filled buffer with incoming data, done */ + break; + } + } + *dataLength = initLen - bytesToGo; + tprintf("SocketRead", initLen, *dataLength, (UInt8 *)data); + + #if SSL_OT_DOT || (SSL_OT_DEBUG && !SSL_OT_IO_TRACE) + if((rtn == 0) && (*dataLength == 0)) { + /* keep UI alive */ + outputDot(); + } + #endif + #if SSL_DISPL_WOULD_BLOCK + if(rtn == errSSLWouldBlock) { + printf("."); fflush(stdout); + } + #endif + return rtn; +} + +int oneAtATime = 0; + +OSStatus SocketWrite( + SSLConnectionRef connection, + const void *data, + size_t *dataLength) /* IN/OUT */ +{ + size_t bytesSent = 0; + int sock = (int)((long)connection); + int length; + size_t dataLen = *dataLength; + const UInt8 *dataPtr = (UInt8 *)data; + OSStatus ortn; + + if(oneAtATime && (*dataLength > 1)) { + size_t i; + size_t outLen; + size_t thisMove; + + outLen = 0; + for(i=0; i 0) && + ( (bytesSent += length) < dataLen) ); + + if(length <= 0) { + int theErr = errno; + switch(theErr) { + case EAGAIN: + ortn = errSSLWouldBlock; break; + case EPIPE: + ortn = errSSLClosedAbort; break; + default: + dprintf(("SocketWrite: write(%u) error %d\n", + (unsigned)(dataLen - bytesSent), theErr)); + ortn = errSecIO; + break; + } + } + else { + ortn = errSecSuccess; + } + tprintf("SocketWrite", dataLen, bytesSent, dataPtr); + *dataLength = bytesSent; + return ortn; +} diff --git a/Security/libsecurity_ssl/sslViewer/ioSock.h b/Security/libsecurity_ssl/sslViewer/ioSock.h new file mode 100644 index 00000000..1faf47b4 --- /dev/null +++ b/Security/libsecurity_ssl/sslViewer/ioSock.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2006-2008,2010-2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * ioSock.h - socket-based I/O routines for use with Secure Transport + */ + +#ifndef _IO_SOCK_H_ +#define _IO_SOCK_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Opaque reference to an Open Transport connection. + */ +typedef int otSocket; + +/* + * info about a peer returned from MakeServerConnection() and + * AcceptClientConnection(). + */ +typedef struct +{ UInt32 ipAddr; + int port; +} PeerSpec; + +/* + * Ont-time only init. + */ +void initSslOt(void); + +/* + * Connect to server. + */ +extern OSStatus MakeServerConnection( + const char *hostName, + int port, + int nonBlocking, // 0 or 1 + otSocket *socketNo, // RETURNED + PeerSpec *peer); // RETURNED + +/* + * Set up an otSocket to listen for client connections. Call once, then + * use multiple AcceptClientConnection calls. + */ +OSStatus ListenForClients( + int port, + int nonBlocking, // 0 or 1 + otSocket *socketNo); // RETURNED + +/* + * Accept a client connection. Call endpointShutdown() for each successful; + * return from this function. + */ +OSStatus AcceptClientConnection( + otSocket listenSock, // obtained from ListenForClients + otSocket *acceptSock, // RETURNED + PeerSpec *peer); // RETURNED + +/* + * Shut down a connection. + */ +void endpointShutdown( + otSocket socket); + +/* + * R/W. Called out from SSL. + */ +OSStatus SocketRead( + SSLConnectionRef connection, + void *data, /* owned by + * caller, data + * RETURNED */ + size_t *dataLength); /* IN/OUT */ + +OSStatus SocketWrite( + SSLConnectionRef connection, + const void *data, + size_t *dataLength); /* IN/OUT */ + +#ifdef __cplusplus +} +#endif + +#endif /* _IO_SOCK_H_ */ diff --git a/libsecurity_ssl/sslViewer/printCert.c b/Security/libsecurity_ssl/sslViewer/printCert.c similarity index 98% rename from libsecurity_ssl/sslViewer/printCert.c rename to Security/libsecurity_ssl/sslViewer/printCert.c index 002a7379..9857fe0a 100644 --- a/libsecurity_ssl/sslViewer/printCert.c +++ b/Security/libsecurity_ssl/sslViewer/printCert.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2003-2008,2011-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2008,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurity_ssl/sslViewer/printCert.h b/Security/libsecurity_ssl/sslViewer/printCert.h similarity index 94% rename from libsecurity_ssl/sslViewer/printCert.h rename to Security/libsecurity_ssl/sslViewer/printCert.h index 3b35df4b..38a8ab65 100644 --- a/libsecurity_ssl/sslViewer/printCert.h +++ b/Security/libsecurity_ssl/sslViewer/printCert.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2003-2008,2011-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2008,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/Security/libsecurity_ssl/sslViewer/sslAppUtils.cpp b/Security/libsecurity_ssl/sslViewer/sslAppUtils.cpp new file mode 100644 index 00000000..a4bcc823 --- /dev/null +++ b/Security/libsecurity_ssl/sslViewer/sslAppUtils.cpp @@ -0,0 +1,1650 @@ +/* + * Copyright (c) 2006-2008,2010-2014 Apple Inc. All Rights Reserved. + */ + +#include "sslAppUtils.h" +#include "fileIo.h" +#include +#include +#include +#include + +#include +#include +#include +#include + +#define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) CFRelease(_cf); } + +const char *sslGetCipherSuiteString(SSLCipherSuite cs) +{ + static char noSuite[40]; + + switch (cs) { + /* TLS cipher suites, RFC 2246 */ + case SSL_NULL_WITH_NULL_NULL: return "TLS_NULL_WITH_NULL_NULL"; + case SSL_RSA_WITH_NULL_MD5: return "TLS_RSA_WITH_NULL_MD5"; + case SSL_RSA_WITH_NULL_SHA: return "TLS_RSA_WITH_NULL_SHA"; + case SSL_RSA_EXPORT_WITH_RC4_40_MD5: return "TLS_RSA_EXPORT_WITH_RC4_40_MD5"; + case SSL_RSA_WITH_RC4_128_MD5: return "TLS_RSA_WITH_RC4_128_MD5"; + case SSL_RSA_WITH_RC4_128_SHA: return "TLS_RSA_WITH_RC4_128_SHA"; + case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: return "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5"; + case SSL_RSA_WITH_IDEA_CBC_SHA: return "TLS_RSA_WITH_IDEA_CBC_SHA"; + case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: return "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA"; + case SSL_RSA_WITH_DES_CBC_SHA: return "TLS_RSA_WITH_DES_CBC_SHA"; + case SSL_RSA_WITH_3DES_EDE_CBC_SHA: return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; + case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: return "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"; + case SSL_DH_DSS_WITH_DES_CBC_SHA: return "TLS_DH_DSS_WITH_DES_CBC_SHA"; + case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA: return "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"; + case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: return "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"; + case SSL_DH_RSA_WITH_DES_CBC_SHA: return "TLS_DH_RSA_WITH_DES_CBC_SHA"; + case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA: return "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"; + case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: return "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"; + case SSL_DHE_DSS_WITH_DES_CBC_SHA: return "TLS_DHE_DSS_WITH_DES_CBC_SHA"; + case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA: return "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; + case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: return "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"; + case SSL_DHE_RSA_WITH_DES_CBC_SHA: return "TLS_DHE_RSA_WITH_DES_CBC_SHA"; + case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: return "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; + case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: return "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5"; + case SSL_DH_anon_WITH_RC4_128_MD5: return "TLS_DH_anon_WITH_RC4_128_MD5"; + case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: return "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA"; + case SSL_DH_anon_WITH_DES_CBC_SHA: return "TLS_DH_anon_WITH_DES_CBC_SHA"; + case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; + + /* SSLv3 Fortezza cipher suites, from NSS */ + case SSL_FORTEZZA_DMS_WITH_NULL_SHA: return "SSL_FORTEZZA_DMS_WITH_NULL_SHA"; + case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA:return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA"; + + /* TLS addenda using AES-CBC, RFC 3268 */ + case TLS_RSA_WITH_AES_128_CBC_SHA: return "TLS_RSA_WITH_AES_128_CBC_SHA"; + case TLS_DH_DSS_WITH_AES_128_CBC_SHA: return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; + case TLS_DH_RSA_WITH_AES_128_CBC_SHA: return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; + case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; + case TLS_DH_anon_WITH_AES_128_CBC_SHA: return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; + case TLS_RSA_WITH_AES_256_CBC_SHA: return "TLS_RSA_WITH_AES_256_CBC_SHA"; + case TLS_DH_DSS_WITH_AES_256_CBC_SHA: return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; + case TLS_DH_RSA_WITH_AES_256_CBC_SHA: return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; + case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; + case TLS_DH_anon_WITH_AES_256_CBC_SHA: return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; + + /* ECDSA addenda, RFC 4492 */ + case TLS_ECDH_ECDSA_WITH_NULL_SHA: return "TLS_ECDH_ECDSA_WITH_NULL_SHA"; + case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"; + case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"; + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"; + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"; + case TLS_ECDHE_ECDSA_WITH_NULL_SHA: return "TLS_ECDHE_ECDSA_WITH_NULL_SHA"; + case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"; + case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"; + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"; + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"; + case TLS_ECDH_RSA_WITH_NULL_SHA: return "TLS_ECDH_RSA_WITH_NULL_SHA"; + case TLS_ECDH_RSA_WITH_RC4_128_SHA: return "TLS_ECDH_RSA_WITH_RC4_128_SHA"; + case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"; + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"; + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"; + case TLS_ECDHE_RSA_WITH_NULL_SHA: return "TLS_ECDHE_RSA_WITH_NULL_SHA"; + case TLS_ECDHE_RSA_WITH_RC4_128_SHA: return "TLS_ECDHE_RSA_WITH_RC4_128_SHA"; + case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"; + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"; + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"; + case TLS_ECDH_anon_WITH_NULL_SHA: return "TLS_ECDH_anon_WITH_NULL_SHA"; + case TLS_ECDH_anon_WITH_RC4_128_SHA: return "TLS_ECDH_anon_WITH_RC4_128_SHA"; + case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA: return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"; + case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"; + case TLS_ECDH_anon_WITH_AES_256_CBC_SHA: return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"; + + /* TLS 1.2 addenda, RFC 5246 */ + case TLS_RSA_WITH_AES_128_CBC_SHA256: return "TLS_RSA_WITH_AES_128_CBC_SHA256"; + case TLS_RSA_WITH_AES_256_CBC_SHA256: return "TLS_RSA_WITH_AES_256_CBC_SHA256"; + case TLS_DH_DSS_WITH_AES_128_CBC_SHA256: return "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"; + case TLS_DH_RSA_WITH_AES_128_CBC_SHA256: return "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"; + case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"; + case TLS_DH_DSS_WITH_AES_256_CBC_SHA256: return "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"; + case TLS_DH_RSA_WITH_AES_256_CBC_SHA256: return "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"; + case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"; + case TLS_DH_anon_WITH_AES_128_CBC_SHA256: return "TLS_DH_anon_WITH_AES_128_CBC_SHA256"; + case TLS_DH_anon_WITH_AES_256_CBC_SHA256: return "TLS_DH_anon_WITH_AES_256_CBC_SHA256"; + + /* TLS addenda using AES-GCM, RFC 5288 */ + case TLS_RSA_WITH_AES_128_GCM_SHA256: return "TLS_RSA_WITH_AES_128_GCM_SHA256"; + case TLS_RSA_WITH_AES_256_GCM_SHA384: return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"; + case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"; + case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"; + case TLS_DH_RSA_WITH_AES_128_GCM_SHA256: return "TLS_DH_RSA_WITH_AES_128_GCM_SHA256"; + case TLS_DH_RSA_WITH_AES_256_GCM_SHA384: return "TLS_DH_RSA_WITH_AES_256_GCM_SHA384"; + case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: return "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"; + case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: return "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"; + case TLS_DH_DSS_WITH_AES_128_GCM_SHA256: return "TLS_DH_DSS_WITH_AES_128_GCM_SHA256"; + case TLS_DH_DSS_WITH_AES_256_GCM_SHA384: return "TLS_DH_DSS_WITH_AES_256_GCM_SHA384"; + case TLS_DH_anon_WITH_AES_128_GCM_SHA256: return "TLS_DH_anon_WITH_AES_128_GCM_SHA256"; + case TLS_DH_anon_WITH_AES_256_GCM_SHA384: return "TLS_DH_anon_WITH_AES_256_GCM_SHA384"; + + /* ECDSA addenda, RFC 5289 */ + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"; + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"; + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"; + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"; + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"; + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"; + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"; + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"; + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"; + case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"; + case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"; + case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"; + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"; + case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"; + case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"; + case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"; + + /* + * Tags for SSL 2 cipher kinds which are not specified for SSL 3. + */ + case SSL_RSA_WITH_RC2_CBC_MD5: return "TLS_RSA_WITH_RC2_CBC_MD5"; + case SSL_RSA_WITH_IDEA_CBC_MD5: return "TLS_RSA_WITH_IDEA_CBC_MD5"; + case SSL_RSA_WITH_DES_CBC_MD5: return "TLS_RSA_WITH_DES_CBC_MD5"; + case SSL_RSA_WITH_3DES_EDE_CBC_MD5: return "TLS_RSA_WITH_3DES_EDE_CBC_MD5"; + case SSL_NO_SUCH_CIPHERSUITE: return "SSL_NO_SUCH_CIPHERSUITE"; + + default: + sprintf(noSuite, "Unknown (0x%04X)", (unsigned)cs); + return noSuite; + } +} + +/* + * Given a SSLProtocolVersion - typically from SSLGetProtocolVersion - + * return a string representation. + */ +const char *sslGetProtocolVersionString(SSLProtocol prot) +{ + static char noProt[20]; + + switch(prot) { + case kSSLProtocolUnknown: return "kSSLProtocolUnknown"; + case kSSLProtocol2: return "kSSLProtocol2"; + case kSSLProtocol3: return "kSSLProtocol3"; + case kSSLProtocol3Only: return "kSSLProtocol3Only"; + case kTLSProtocol1: return "kTLSProtocol1"; + case kTLSProtocol1Only: return "kTLSProtocol1Only"; + case kTLSProtocol11: return "kTLSProtocol11"; + case kTLSProtocol12: return "kTLSProtocol12"; + default: + sprintf(noProt, "Unknown (%d)", (unsigned)prot); + return noProt; + } +} + +/* + * Return string representation of SecureTransport-related OSStatus. + */ +const char *sslGetSSLErrString(OSStatus err) +{ + static char errSecSuccessStr[20]; + + switch(err) { + case errSecSuccess: return "errSecSuccess"; + case errSecAllocate: return "errSecAllocate"; + case errSecParam: return "errSecParam"; + case errSecUnimplemented: return "errSecUnimplemented"; + case errSecIO: return "errSecIO"; + case errSecBadReq: return "errSecBadReq"; + /* SSL errors */ + case errSSLProtocol: return "errSSLProtocol"; + case errSSLNegotiation: return "errSSLNegotiation"; + case errSSLFatalAlert: return "errSSLFatalAlert"; + case errSSLWouldBlock: return "errSSLWouldBlock"; + case errSSLSessionNotFound: return "errSSLSessionNotFound"; + case errSSLClosedGraceful: return "errSSLClosedGraceful"; + case errSSLClosedAbort: return "errSSLClosedAbort"; + case errSSLXCertChainInvalid: return "errSSLXCertChainInvalid"; + case errSSLBadCert: return "errSSLBadCert"; + case errSSLCrypto: return "errSSLCrypto"; + case errSSLInternal: return "errSSLInternal"; + case errSSLModuleAttach: return "errSSLModuleAttach"; + case errSSLUnknownRootCert: return "errSSLUnknownRootCert"; + case errSSLNoRootCert: return "errSSLNoRootCert"; + case errSSLCertExpired: return "errSSLCertExpired"; + case errSSLCertNotYetValid: return "errSSLCertNotYetValid"; + case errSSLClosedNoNotify: return "errSSLClosedNoNotify"; + case errSSLBufferOverflow: return "errSSLBufferOverflow"; + case errSSLBadCipherSuite: return "errSSLBadCipherSuite"; + /* TLS/Panther addenda */ + case errSSLPeerUnexpectedMsg: return "errSSLPeerUnexpectedMsg"; + case errSSLPeerBadRecordMac: return "errSSLPeerBadRecordMac"; + case errSSLPeerDecryptionFail: return "errSSLPeerDecryptionFail"; + case errSSLPeerRecordOverflow: return "errSSLPeerRecordOverflow"; + case errSSLPeerDecompressFail: return "errSSLPeerDecompressFail"; + case errSSLPeerHandshakeFail: return "errSSLPeerHandshakeFail"; + case errSSLPeerBadCert: return "errSSLPeerBadCert"; + case errSSLPeerUnsupportedCert: return "errSSLPeerUnsupportedCert"; + case errSSLPeerCertRevoked: return "errSSLPeerCertRevoked"; + case errSSLPeerCertExpired: return "errSSLPeerCertExpired"; + case errSSLPeerCertUnknown: return "errSSLPeerCertUnknown"; + case errSSLIllegalParam: return "errSSLIllegalParam"; + case errSSLPeerUnknownCA: return "errSSLPeerUnknownCA"; + case errSSLPeerAccessDenied: return "errSSLPeerAccessDenied"; + case errSSLPeerDecodeError: return "errSSLPeerDecodeError"; + case errSSLPeerDecryptError: return "errSSLPeerDecryptError"; + case errSSLPeerExportRestriction: return "errSSLPeerExportRestriction"; + case errSSLPeerProtocolVersion: return "errSSLPeerProtocolVersion"; + case errSSLPeerInsufficientSecurity:return "errSSLPeerInsufficientSecurity"; + case errSSLPeerInternalError: return "errSSLPeerInternalError"; + case errSSLPeerUserCancelled: return "errSSLPeerUserCancelled"; + case errSSLPeerNoRenegotiation: return "errSSLPeerNoRenegotiation"; + case errSSLHostNameMismatch: return "errSSLHostNameMismatch"; + case errSSLConnectionRefused: return "errSSLConnectionRefused"; + case errSSLDecryptionFail: return "errSSLDecryptionFail"; + case errSSLBadRecordMac: return "errSSLBadRecordMac"; + case errSSLRecordOverflow: return "errSSLRecordOverflow"; + case errSSLBadConfiguration: return "errSSLBadConfiguration"; + + /* some from the Sec layer */ + case errSecNotAvailable: return "errSecNotAvailable"; + case errSecDuplicateItem: return "errSecDuplicateItem"; + case errSecItemNotFound: return "errSecItemNotFound"; +#if !TARGET_OS_IPHONE + case errSecReadOnly: return "errSecReadOnly"; + case errSecAuthFailed: return "errSecAuthFailed"; + case errSecNoSuchKeychain: return "errSecNoSuchKeychain"; + case errSecInvalidKeychain: return "errSecInvalidKeychain"; + case errSecNoSuchAttr: return "errSecNoSuchAttr"; + case errSecInvalidItemRef: return "errSecInvalidItemRef"; + case errSecInvalidSearchRef: return "errSecInvalidSearchRef"; + case errSecNoSuchClass: return "errSecNoSuchClass"; + case errSecNoDefaultKeychain: return "errSecNoDefaultKeychain"; + case errSecWrongSecVersion: return "errSecWrongSecVersion"; + case errSecInvalidTrustSettings: return "errSecInvalidTrustSettings"; + case errSecNoTrustSettings: return "errSecNoTrustSettings"; +#endif + default: +#if 0 + if (err < (CSSM_BASE_ERROR + + (CSSM_ERRORCODE_MODULE_EXTENT * 8))) + { + /* assume CSSM error */ + return cssmErrToStr(err); + } + else +#endif + { + sprintf(errSecSuccessStr, "Unknown (%d)", (unsigned)err); + return errSecSuccessStr; + } + } +} + +void printSslErrStr( + const char *op, + OSStatus err) +{ + printf("*** %s: %s\n", op, sslGetSSLErrString(err)); +} + +const char *sslGetClientCertStateString(SSLClientCertificateState state) +{ + static char noState[20]; + + switch(state) { + case kSSLClientCertNone: return "ClientCertNone"; + case kSSLClientCertRequested: return "CertRequested"; + case kSSLClientCertSent: return "ClientCertSent"; + case kSSLClientCertRejected: return "ClientCertRejected"; + default: + sprintf(noState, "Unknown (%d)", (unsigned)state); + return noState; + } + +} + +const char *sslGetClientAuthTypeString(SSLClientAuthenticationType authType) +{ + static char noType[20]; + + switch(authType) { + case SSLClientAuthNone: return "None"; + case SSLClientAuth_RSASign: return "RSASign"; + case SSLClientAuth_DSSSign: return "DSSSign"; + case SSLClientAuth_RSAFixedDH: return "RSAFixedDH"; + case SSLClientAuth_DSS_FixedDH: return "DSS_FixedDH"; + case SSLClientAuth_ECDSASign: return "ECDSASign"; + case SSLClientAuth_RSAFixedECDH: return "RSAFixedECDH"; + case SSLClientAuth_ECDSAFixedECDH: return "ECDSAFixedECDH"; + default: + sprintf(noType, "Unknown (%d)", (unsigned)authType); + return noType; + } +} + +/* + * Convert a keychain name (which may be NULL) into the CFArrayRef required + * by SSLSetCertificate. This is a bare-bones example of this operation, + * since it requires and assumes that there is exactly one SecIdentity + * in the keychain - i.e., there is exactly one matching cert/private key + * pair. A real world server would probably search a keychain for a SecIdentity + * matching some specific criteria. + */ +CFArrayRef getSslCerts( + const char *kcName, // may be NULL, i.e., use default + bool encryptOnly, + bool completeCertChain, + const char *anchorFile, // optional trusted anchor + SecKeychainRef *pKcRef) // RETURNED +{ +#if 0 + SecKeychainRef kcRef = nil; + OSStatus ortn; + + *pKcRef = nil; + + /* pick a keychain */ + if(kcName) { + ortn = SecKeychainOpen(kcName, &kcRef); + if(ortn) { + printf("SecKeychainOpen returned %d.\n", (int)ortn); + printf("Cannot open keychain at %s. Aborting.\n", kcName); + return NULL; + } + } + else { + /* use default keychain */ + ortn = SecKeychainCopyDefault(&kcRef); + if(ortn) { + printf("SecKeychainCopyDefault returned %d; aborting.\n", (int)ortn); + return nil; + } + } + *pKcRef = kcRef; + return sslKcRefToCertArray(kcRef, encryptOnly, completeCertChain, anchorFile); +#elif TARGET_OS_IOS + SecCertificateRef cert = NULL; + SecIdentityRef identity = NULL; + CFMutableArrayRef certificates = NULL, result = NULL; + CFMutableDictionaryRef certQuery = NULL, keyQuery = NULL, keyResult = NULL; + SecTrustRef trust = NULL; + SecKeyRef key = NULL; + CFTypeRef pkdigest = NULL; + + // Find the first private key in the keychain and return both its + // attributes and a ref to it. + require(keyQuery = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut); + CFDictionaryAddValue(keyQuery, kSecClass, kSecClassKey); + CFDictionaryAddValue(keyQuery, kSecAttrKeyClass, kSecAttrKeyClassPrivate); + CFDictionaryAddValue(keyQuery, kSecReturnRef, kCFBooleanTrue); + CFDictionaryAddValue(keyQuery, kSecReturnAttributes, kCFBooleanTrue); + require_noerr(SecItemCopyMatching(keyQuery, (CFTypeRef *)&keyResult), + errOut); + require(key = (SecKeyRef)CFDictionaryGetValue(keyResult, kSecValueRef), + errOut); + require(pkdigest = CFDictionaryGetValue(keyResult, kSecAttrApplicationLabel), + errOut); + + // Find the first certificate that has the same public key hash as the + // returned private key and return it as a ref. + require(certQuery = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut); + CFDictionaryAddValue(certQuery, kSecClass, kSecClassCertificate); + CFDictionaryAddValue(certQuery, kSecAttrPublicKeyHash, pkdigest); + CFDictionaryAddValue(certQuery, kSecReturnRef, kCFBooleanTrue); + require_noerr(SecItemCopyMatching(certQuery, (CFTypeRef *)&cert), errOut); + + // Create an identity from the key and certificate. + require(identity = SecIdentityCreate(NULL, cert, key), errOut); + + // Build a (partial) certificate chain from cert + require(certificates = CFArrayCreateMutable(NULL, 0, + &kCFTypeArrayCallBacks), errOut); + CFArrayAppendValue(certificates, cert); + require_noerr(SecTrustCreateWithCertificates(certificates, NULL, &trust), + errOut); + SecTrustResultType tresult; + require_noerr(SecTrustEvaluate(trust, &tresult), errOut); + + CFIndex certCount, ix; + // We need at least 1 certificate + require(certCount = SecTrustGetCertificateCount(trust), errOut); + + // Build a result where element 0 is the identity and the other elements + // are the certs in the chain starting at the first intermediate up to the + // anchor, if we found one, or as far as we were able to build the chain + // if not. + require(result = CFArrayCreateMutable(NULL, certCount, &kCFTypeArrayCallBacks), + errOut); + + // We are commited to returning a result now, so do not use require below + // this line without setting result to NULL again. + CFArrayAppendValue(result, identity); + for (ix = 1; ix < certCount; ++ix) { + CFArrayAppendValue(result, SecTrustGetCertificateAtIndex(trust, ix)); + } + +errOut: + CFReleaseSafe(trust); + CFReleaseSafe(certificates); + CFReleaseSafe(identity); + CFReleaseSafe(cert); + CFReleaseSafe(certQuery); + CFReleaseSafe(keyResult); + CFReleaseSafe(keyQuery); + + return result; + +#else /* !TARGET_OS_IOS */ + SecIdentityRef identity = NULL; + CFMutableDictionaryRef query = NULL; + CFArrayRef items = NULL; + require(query = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut); + CFDictionaryAddValue(query, kSecClass, kSecClassIdentity); + CFDictionaryAddValue(query, kSecReturnRef, kCFBooleanTrue); + require_noerr(SecItemCopyMatching(query, (CFTypeRef *)&identity), errOut); + + items = CFArrayCreate(kCFAllocatorDefault, + (const void **)&identity, 1, &kCFTypeArrayCallBacks); + +errOut: + CFReleaseSafe(identity); + CFReleaseSafe(query); + + return items; + +#endif + +} + +#if 0 +/* + * Determine if specified SecCertificateRef is a self-signed cert. + * We do this by comparing the subject and issuerr names; no cryptographic + * verification is performed. + * + * Returns true if the cert appears to be a root. + */ +static bool isCertRefRoot( + SecCertificateRef certRef) +{ + bool brtn = false; +#if 0 + /* just search for the two attrs we want */ + UInt32 tags[2] = {kSecSubjectItemAttr, kSecIssuerItemAttr}; + SecKeychainAttributeInfo attrInfo; + attrInfo.count = 2; + attrInfo.tag = tags; + attrInfo.format = NULL; + SecKeychainAttributeList *attrList = NULL; + SecKeychainAttribute *attr1 = NULL; + SecKeychainAttribute *attr2 = NULL; + + OSStatus ortn = SecKeychainItemCopyAttributesAndData( + (SecKeychainItemRef)certRef, + &attrInfo, + NULL, // itemClass + &attrList, + NULL, // length - don't need the data + NULL); // outData + if(ortn) { + cssmPerror("SecKeychainItemCopyAttributesAndData", ortn); + /* may want to be a bit more robust here, but this should + * never happen */ + return false; + } + /* subsequent errors to errOut: */ + + if((attrList == NULL) || (attrList->count != 2)) { + printf("***Unexpected result fetching label attr\n"); + goto errOut; + } + + /* rootness is just byte-for-byte compare of the two names */ + attr1 = &attrList->attr[0]; + attr2 = &attrList->attr[1]; + if(attr1->length == attr2->length) { + if(memcmp(attr1->data, attr2->data, attr1->length) == 0) { + brtn = true; + } + } +errOut: + SecKeychainItemFreeAttributesAndData(attrList, NULL); +#endif + return brtn; +} +#endif + +#if 0 +/* + * Given a SecIdentityRef, do our best to construct a complete, ordered, and + * verified cert chain, returning the result in a CFArrayRef. The result is + * suitable for use when calling SSLSetCertificate(). + */ +OSStatus sslCompleteCertChain( + SecIdentityRef identity, + SecCertificateRef trustedAnchor, // optional additional trusted anchor + bool includeRoot, // include the root in outArray + CFArrayRef *outArray) // created and RETURNED +{ + CFMutableArrayRef certArray; + SecTrustRef secTrust = NULL; + SecPolicyRef policy = NULL; + SecPolicySearchRef policySearch = NULL; + SecTrustResultType secTrustResult; + CSSM_TP_APPLE_EVIDENCE_INFO *dummyEv; // not used + CFArrayRef certChain = NULL; // constructed chain + CFIndex numResCerts; + + certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(certArray, identity); + + /* + * Case 1: identity is a root; we're done. Note that this case + * overrides the includeRoot argument. + */ + SecCertificateRef certRef; + OSStatus ortn = SecIdentityCopyCertificate(identity, &certRef); + if(ortn) { + /* should never happen */ + cssmPerror("SecIdentityCopyCertificate", ortn); + return ortn; + } + bool isRoot = isCertRefRoot(certRef); + if(isRoot) { + *outArray = certArray; + CFRelease(certRef); + return errSecSuccess; + } + + /* + * Now use SecTrust to get a complete cert chain, using all of the + * user's keychains to look for intermediate certs. + * NOTE this does NOT handle root certs which are not in the system + * root cert DB. (The above case, where the identity is a root cert, does.) + */ + CFMutableArrayRef subjCerts = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks); + CFArraySetValueAtIndex(subjCerts, 0, certRef); + + /* the array owns the subject cert ref now */ + CFRelease(certRef); + + /* Get a SecPolicyRef for generic X509 cert chain verification */ + ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3, + &CSSMOID_APPLE_X509_BASIC, + NULL, // value + &policySearch); + if(ortn) { + cssmPerror("SecPolicySearchCreate", ortn); + goto errOut; + } + ortn = SecPolicySearchCopyNext(policySearch, &policy); + if(ortn) { + cssmPerror("SecPolicySearchCopyNext", ortn); + goto errOut; + } + + /* build a SecTrustRef for specified policy and certs */ + ortn = SecTrustCreateWithCertificates(subjCerts, + policy, &secTrust); + if(ortn) { + cssmPerror("SecTrustCreateWithCertificates", ortn); + goto errOut; + } + + if(trustedAnchor) { + /* + * Tell SecTrust to trust this one in addition to the current + * trusted system-wide anchors. + */ + CFMutableArrayRef newAnchors; + CFArrayRef currAnchors; + + ortn = SecTrustCopyAnchorCertificates(&currAnchors); + if(ortn) { + /* should never happen */ + cssmPerror("SecTrustCopyAnchorCertificates", ortn); + goto errOut; + } + newAnchors = CFArrayCreateMutableCopy(NULL, + CFArrayGetCount(currAnchors) + 1, + currAnchors); + CFRelease(currAnchors); + CFArrayAppendValue(newAnchors, trustedAnchor); + ortn = SecTrustSetAnchorCertificates(secTrust, newAnchors); + CFRelease(newAnchors); + if(ortn) { + cssmPerror("SecTrustSetAnchorCertificates", ortn); + goto errOut; + } + } + /* evaluate: GO */ + ortn = SecTrustEvaluate(secTrust, &secTrustResult); + if(ortn) { + cssmPerror("SecTrustEvaluate", ortn); + goto errOut; + } + switch(secTrustResult) { + case kSecTrustResultUnspecified: + /* cert chain valid, no special UserTrust assignments */ + case kSecTrustResultProceed: + /* cert chain valid AND user explicitly trusts this */ + break; + default: + /* + * Cert chain construction failed. + * Just go with the single subject cert we were given. + */ + printf("***Warning: could not construct completed cert chain\n"); + ortn = errSecSuccess; + goto errOut; + } + + /* get resulting constructed cert chain */ + ortn = SecTrustGetResult(secTrust, &secTrustResult, &certChain, &dummyEv); + if(ortn) { + cssmPerror("SecTrustEvaluate", ortn); + goto errOut; + } + + /* + * Copy certs from constructed chain to our result array, skipping + * the leaf (which is already there, as a SecIdentityRef) and possibly + * a root. + */ + numResCerts = CFArrayGetCount(certChain); + if(numResCerts < 2) { + /* + * Can't happen: if subject was a root, we'd already have returned. + * If chain doesn't verify to a root, we'd have bailed after + * SecTrustEvaluate(). + */ + printf("***sslCompleteCertChain screwup: numResCerts %d\n", + (int)numResCerts); + ortn = errSecSuccess; + goto errOut; + } + if(!includeRoot) { + /* skip the last (root) cert) */ + numResCerts--; + } + for(CFIndex dex=1; dexacceptedProts) { + printf(" Allowed SSL versions : %s\n", params->acceptedProts); + } + else { + printf(" Attempted SSL version : %s\n", + sslGetProtocolVersionString(params->tryVersion)); + } + printf(" Result : %s\n", sslGetSSLErrString(params->ortn)); + printf(" Negotiated SSL version : %s\n", + sslGetProtocolVersionString(params->negVersion)); + printf(" Negotiated CipherSuite : %s\n", + sslGetCipherSuiteString(params->negCipher)); + if(params->certState != kSSLClientCertNone) { + printf(" Client Cert State : %s\n", + sslGetClientCertStateString(params->certState)); + } +} +#endif + +/* print a '.' every few seconds to keep UI alive while connecting */ +static CFAbsoluteTime lastTime = (CFAbsoluteTime)0.0; +#define TIME_INTERVAL 3.0 + +void sslOutputDot() +{ + CFAbsoluteTime thisTime = CFAbsoluteTimeGetCurrent(); + + // throttle down. + usleep(1000); + + if(lastTime == 0.0) { + /* avoid printing first time thru */ + lastTime = thisTime; + return; + } + if((thisTime - lastTime) >= TIME_INTERVAL) { + printf("."); fflush(stdout); + lastTime = thisTime; + } +} + +#if 0 +/* main server pthread body */ +static void *sslServerThread(void *arg) +{ + SslAppTestParams *testParams = (SslAppTestParams *)arg; + OSStatus status; + + status = sslAppServe(testParams); + pthread_exit((void*)status); + /* NOT REACHED */ + return (void *)status; +} + +/* + * Run one session, with the server in a separate thread. + * On entry, serverParams->port is the port we attempt to run on; + * the server thread may overwrite that with a different port if it's + * unable to open the port we specify. Whatever is left in + * serverParams->port is what's used for the client side. + */ +#define CLIENT_WAIT_SECONDS 1 +int sslRunSession( + SslAppTestParams*serverParams, + SslAppTestParams *clientParams, + const char *testDesc) +{ + pthread_t serverPthread; + OSStatus clientRtn; + void *serverRtn; + + if(testDesc && !clientParams->quiet) { + printf("===== %s =====\n", testDesc); + } + + if(pthread_mutex_init(&serverParams->pthreadMutex, NULL)) { + printf("***Error initializing mutex; aborting.\n"); + return -1; + } + if(pthread_cond_init(&serverParams->pthreadCond, NULL)) { + printf("***Error initializing pthreadCond; aborting.\n"); + return -1; + } + serverParams->serverReady = false; // server sets true + + int result = pthread_create(&serverPthread, NULL, + sslServerThread, serverParams); + if(result) { + printf("***Error starting up server thread; aborting.\n"); + return result; + } + + /* wait for server to set up a socket we can connect to */ + if(pthread_mutex_lock(&serverParams->pthreadMutex)) { + printf("***Error acquiring server lock; aborting.\n"); + return -1; + } + while(!serverParams->serverReady) { + if(pthread_cond_wait(&serverParams->pthreadCond, &serverParams->pthreadMutex)) { + printf("***Error waiting server thread; aborting.\n"); + return -1; + } + } + pthread_mutex_unlock(&serverParams->pthreadMutex); + pthread_cond_destroy(&serverParams->pthreadCond); + pthread_mutex_destroy(&serverParams->pthreadMutex); + + clientParams->port = serverParams->port; + clientRtn = sslAppClient(clientParams); + /* server doesn't shut down its socket until it sees this */ + serverParams->clientDone = 1; + result = pthread_join(serverPthread, &serverRtn); + if(result) { + printf("***pthread_join returned %d, aborting\n", result); + return result; + } + + if(serverParams->verbose) { + sslShowResult("server", serverParams); + } + if(clientParams->verbose) { + sslShowResult("client", clientParams); + } + + /* verify results */ + int ourRtn = 0; + ourRtn += sslVerifyRtn("server", serverParams->expectRtn, serverParams->ortn); + ourRtn += sslVerifyRtn("client", clientParams->expectRtn, clientParams->ortn); + ourRtn += sslVerifyProtVers("server", serverParams->expectVersion, + serverParams->negVersion); + ourRtn += sslVerifyProtVers("client", clientParams->expectVersion, + clientParams->negVersion); + ourRtn += sslVerifyClientCertState("server", serverParams->expectCertState, + serverParams->certState); + ourRtn += sslVerifyClientCertState("client", clientParams->expectCertState, + clientParams->certState); + if(serverParams->ortn == errSecSuccess) { + ourRtn += sslVerifyCipher("server", serverParams->expectCipher, + serverParams->negCipher); + } + if(clientParams->ortn == errSecSuccess) { + ourRtn += sslVerifyCipher("client", clientParams->expectCipher, + clientParams->negCipher); + } + return ourRtn; +} + +/* + * Add all of the roots in a given KC to SSL ctx's trusted anchors. + */ +OSStatus sslAddTrustedRoots( + SSLContextRef ctx, + SecKeychainRef keychain, + bool *foundOne) // RETURNED, true if we found + // at least one root cert +{ + OSStatus ortn; + SecCertificateRef secCert; + SecKeychainSearchRef srch; + + *foundOne = false; + ortn = SecKeychainSearchCreateFromAttributes(keychain, + kSecCertificateItemClass, + NULL, // any attrs + &srch); + if(ortn) { + printSslErrStr("SecKeychainSearchCreateFromAttributes", ortn); + return ortn; + } + + /* + * Only use root certs. Not an error if we don't find any. + */ + do { + ortn = SecKeychainSearchCopyNext(srch, + (SecKeychainItemRef *)&secCert); + if(ortn) { + break; + } + + /* see if it's a root */ + if(!isCertRoot(secCert)) { + continue; + } + + /* Tell Secure Transport to trust this one. */ + ortn = addTrustedSecCert(ctx, secCert, false); + if(ortn) { + /* fatal */ + printSslErrStr("addTrustedSecCert", ortn); + return ortn; + } + CFRelease(secCert); + *foundOne = true; + } while(ortn == errSecSuccess); + CFRelease(srch); + return errSecSuccess; +} + +/* + * Wrapper for sslIdentPicker, with optional trusted anchor specified as a filename. + */ +OSStatus sslIdentityPicker( + SecKeychainRef kcRef, // NULL means use default list + const char *trustedAnchor, // optional additional trusted anchor + bool includeRoot, // true --> root is appended to outArray + // false --> root not included + CFArrayRef *outArray) // created and RETURNED +{ + SecCertificateRef trustedCert = NULL; + OSStatus ortn; + + if(trustedAnchor) { + ortn = sslReadAnchor(trustedAnchor, &trustedCert); + if(ortn) { + printf("***Error reading %s. sslIdentityPicker proceeding with no anchor.\n", + trustedAnchor); + trustedCert = NULL; + } + } + ortn = sslIdentPicker(kcRef, trustedCert, includeRoot, outArray); + if(trustedCert) { + CFRelease(trustedCert); + } + return ortn; +} + +/* + * Given a keychain name, convert it into a full path using the "SSL regression + * test suite algorithm". The Sec layer by default locates root root's keychains + * in different places depending on whether we're actually logged in as root + * or running via e.g. cron, so we force the location of root keychains to + * a hard-coded path. User keychain names we leave alone. + */ +void sslKeychainPath( + const char *kcName, + char *kcPath) // allocd by caller, MAXPATHLEN +{ + if(kcName[0] == '\0') { + kcPath[0] = '\0'; + } + else if(geteuid() == 0) { + /* root */ + sprintf(kcPath, "/Library/Keychains/%s", kcName); + } + else { + /* user, leave alone */ + strcpy(kcPath, kcName); + } +} + +/* Verify presence of required file. Returns nonzero if not found. */ +int sslCheckFile(const char *path) +{ + struct stat sb; + + if(stat(path, &sb)) { + printf("***Can't find file %s.\n", path); + printf(" Try running in the build directory, perhaps after running the\n" + " makeLocalCert script.\n"); + return 1; + } + return 0; +} + +#endif + +/* Stringify a SSL_ECDSA_NamedCurve */ +extern const char *sslCurveString( + SSL_ECDSA_NamedCurve namedCurve) +{ + static char unk[100]; + + switch(namedCurve) { + case SSL_Curve_None: return "Curve_None"; + case SSL_Curve_secp256r1: return "secp256r1"; + case SSL_Curve_secp384r1: return "secp384r1"; + case SSL_Curve_secp521r1: return "secp521r1"; + default: + sprintf(unk, "Unknown <%d>", (int)namedCurve); + return unk; + } +} diff --git a/Security/libsecurity_ssl/sslViewer/sslAppUtils.h b/Security/libsecurity_ssl/sslViewer/sslAppUtils.h new file mode 100644 index 00000000..5448105e --- /dev/null +++ b/Security/libsecurity_ssl/sslViewer/sslAppUtils.h @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2006-2008,2010-2012,2014 Apple Inc. All Rights Reserved. + */ + +#ifndef _SSLS_APP_UTILS_H_ +#define _SSLS_APP_UTILS_H_ 1 + +#include +#include +#include +#include +#include + +#include + +#if TARGET_OS_IPHONE +typedef void *SecKeychainRef; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +const char *sslGetCipherSuiteString(SSLCipherSuite cs); +const char *sslGetProtocolVersionString(SSLProtocol prot); +const char *sslGetSSLErrString(OSStatus err); +void printSslErrStr(const char *op, OSStatus err); +const char *sslGetClientCertStateString(SSLClientCertificateState state); +const char *sslGetClientAuthTypeString(SSLClientAuthenticationType authType); + +CFArrayRef getSslCerts( + const char *kcName, // may be NULL, i.e., use default + bool encryptOnly, + bool completeCertChain, + const char *anchorFile, // optional trusted anchor + SecKeychainRef *pKcRef); // RETURNED +OSStatus sslCompleteCertChain( + SecIdentityRef identity, + SecCertificateRef trustedAnchor, // optional additional trusted anchor + bool includeRoot, // include the root in outArray +// const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL + CFArrayRef *outArray); // created and RETURNED +CFArrayRef sslKcRefToCertArray( + SecKeychainRef kcRef, + bool encryptOnly, + bool completeCertChain, +// const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL policy to complete + const char *trustedAnchorFile); + +OSStatus addTrustedSecCert( + SSLContextRef ctx, + SecCertificateRef secCert, + bool replaceAnchors); +OSStatus sslReadAnchor( + const char *anchorFile, + SecCertificateRef *certRef); +OSStatus sslAddTrustedRoot( + SSLContextRef ctx, + const char *anchorFile, + bool replaceAnchors); + +/* + * Assume incoming identity contains a root (e.g., created by + * certtool) and add that cert to ST's trusted anchors. This + * enables ST's verify of the incoming chain to succeed without + * a kludgy "AllowAnyRoot" specification. + */ +OSStatus addIdentityAsTrustedRoot( + SSLContextRef ctx, + CFArrayRef identArray); + +OSStatus sslAddTrustedRoots( + SSLContextRef ctx, + SecKeychainRef keychain, + bool *foundOne); + +void sslOutputDot(); + +/* + * Lists of SSLCipherSuites used in sslSetCipherRestrictions. + */ +extern const SSLCipherSuite suites40[]; +extern const SSLCipherSuite suitesDES[]; +extern const SSLCipherSuite suitesDES40[]; +extern const SSLCipherSuite suites3DES[]; +extern const SSLCipherSuite suitesRC4[]; +extern const SSLCipherSuite suitesRC4_40[]; +extern const SSLCipherSuite suitesRC2[]; +extern const SSLCipherSuite suitesAES128[]; +extern const SSLCipherSuite suitesAES256[]; +extern const SSLCipherSuite suitesDH[]; +extern const SSLCipherSuite suitesDHAnon[]; +extern const SSLCipherSuite suitesDH_RSA[]; +extern const SSLCipherSuite suitesDH_DSS[]; +extern const SSLCipherSuite suites_SHA1[]; +extern const SSLCipherSuite suites_MD5[]; +extern const SSLCipherSuite suites_ECDHE[]; +extern const SSLCipherSuite suites_ECDH[]; + +/* + * Given an SSLContextRef and an array of SSLCipherSuites, terminated by + * SSL_NO_SUCH_CIPHERSUITE, select those SSLCipherSuites which the library + * supports and do a SSLSetEnabledCiphers() specifying those. + */ +OSStatus sslSetEnabledCiphers( + SSLContextRef ctx, + const SSLCipherSuite *ciphers); + +/* + * Specify restricted sets of cipherspecs and protocols. + */ +OSStatus sslSetCipherRestrictions( + SSLContextRef ctx, + char cipherRestrict); + +#ifndef SPHINX +OSStatus sslSetProtocols( + SSLContextRef ctx, + const char *acceptedProts, + SSLProtocol tryVersion); // only used if acceptedProts NULL +#endif + +int sslVerifyRtn( + const char *whichSide, // "client" or "server" + OSStatus expectRtn, + OSStatus gotRtn); +int sslVerifyProtVers( + const char *whichSide, // "client" or "server" + SSLProtocol expectProt, + SSLProtocol gotProt); +int sslVerifyClientCertState( + const char *whichSide, // "client" or "server" + SSLClientCertificateState expectState, + SSLClientCertificateState gotState); +int sslVerifyCipher( + const char *whichSide, // "client" or "server" + SSLCipherSuite expectCipher, + SSLCipherSuite gotCipher); + + +/* + * Wrapper for sslIdentPicker, with optional trusted anchor specified as a filename. + */ +OSStatus sslIdentityPicker( + SecKeychainRef kcRef, // NULL means use default list + const char *trustedAnchor, // optional additional trusted anchor + bool includeRoot, // true --> root is appended to outArray + // false --> root not included +// const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL + CFArrayRef *outArray); // created and RETURNED + +void sslKeychainPath( + const char *kcName, + char *kcPath); // allocd by caller, MAXPATHLEN + +/* Verify presence of required file. Returns nonzero if not found. */ +int sslCheckFile(const char *path); + +/* Stringify a SSL_ECDSA_NamedCurve */ +extern const char *sslCurveString( + SSL_ECDSA_NamedCurve namedCurve); + +#ifdef __cplusplus +} +#endif + +#endif /* _SSLS_APP_UTILS_H_ */ diff --git a/libsecurity_ssl/sslViewer/sslServer.1 b/Security/libsecurity_ssl/sslViewer/sslServer.1 similarity index 100% rename from libsecurity_ssl/sslViewer/sslServer.1 rename to Security/libsecurity_ssl/sslViewer/sslServer.1 diff --git a/Security/libsecurity_ssl/sslViewer/sslServer.cpp b/Security/libsecurity_ssl/sslViewer/sslServer.cpp new file mode 100644 index 00000000..c8fe63e3 --- /dev/null +++ b/Security/libsecurity_ssl/sslViewer/sslServer.cpp @@ -0,0 +1,1061 @@ +/* + * Copyright (c) 2008-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * Trivial SSL server example, using SecureTransport / OS X version. + * + */ + +#include +#include +#include "sslAppUtils.h" +#include "ioSock.h" +#include "fileIo.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include "printCert.h" + +#if NO_SERVER +#include +#endif + +/* Set true when PR-3074739 is merged to TOT */ +#define SET_DH_PARAMS_ENABLE 1 + +/* true when using SSLCopyPeerCertificates() per Radar 3311892 */ +#define USE_COPY_PEER_CERTS 1 + +/* + * Defaults, overridable by user. + */ +#define SERVER_MESSAGE "HTTP/1.0 200 OK\015\012Content-Type: text/html\015\012\015\012" \ + "SecureTransport Test Server" \ + "

Secure connection established.

" \ + "Message from the 'sslServer' sample application.\015\012" \ + "\015\012" + +/* For ease of debugging, pick a non-privileged port */ +#define DEFAULT_PORT 1200 +// #define DEFAULT_PORT 443 + +#define DEFAULT_HOST "localhost" + +#define DEFAULT_KC "certkc" + +static void usage(char **argv) +{ + printf("Usage: %s [option ...]\n", argv[0]); + printf("Options:\n"); + printf(" P=port Port to listen on; default is %d\n", DEFAULT_PORT); + printf(" k=keychain Contains server cert and keys.\n"); + printf(" y=keychain Encryption-only cert and keys.\n"); + printf(" e Allow Expired Certs\n"); + printf(" r Allow any root cert\n"); + printf(" E Allow Expired Roots\n"); + printf(" x Disable Cert Verification\n"); + printf(" f=fileBase Write Peer Certs to fileBase*\n"); + printf(" c Display peer certs\n"); + printf(" d Display received data\n"); + printf(" C=cipherSuite (e=40-bit d=DES D=40-bit DES 3=3DES 4=RC4 $=40-bit RC4\n" + " 2=RC2 a=AES128 A=AES256 h=DH H=Anon DH r=DHE/RSA s=DH/DSS\n" + " n=RSA/NULL\n"); + printf(" 2 SSLv2 only (default is best fit)\n"); + printf(" 3 SSLv3 only (default is best fit)\n"); + printf(" t TLSv1 only (default is best fit)\n"); + printf(" o TLSv1, SSLv3 use kSSLProtocol__X__Only\n"); + printf(" g={prot...} Specify legal protocols; prot = any combo of [23t]\n"); + printf(" T=[nrsj] Verify client cert state = " + "none/requested/sent/rejected\n"); + printf(" R Disable resumable session support\n"); + printf(" i=timeout Session cache timeout\n"); + printf(" u=[nat] Authentication: n=never; a=always; t=try\n"); + printf(" b Non-blocking I/O\n"); + printf(" a fileNmae Add fileName to list of trusted roots\n"); + printf(" A fileName fileName is ONLY trusted root\n"); + printf(" U filename Add filename to acceptable DNList (multiple times OK)\n"); + printf(" D filename Diffie-Hellman parameters from filename\n"); + printf(" z=password Unlock server keychain with password.\n"); + printf(" H Do SecIdentityRef search instead of specific keychain\n"); + printf(" M Complete cert chain (default assumes that our identity is root)\n"); + printf(" 4 Disable anonymous ciphers\n"); + printf(" p Pause after each phase\n"); + printf(" l[=loops] Loop, performing multiple transactions\n"); + printf(" q Quiet/diagnostic mode (site names and errors only)\n"); + printf(" h Help\n"); + exit(1); +} + +/* snag a copy of current connection's peer certs so we can + * examine them later after the connection is closed */ +static OSStatus copyPeerCerts( + SSLContext *ctx, + CFArrayRef *peerCerts) // mallocd & RETURNED +{ + #if USE_COPY_PEER_CERTS + OSStatus ortn = SSLCopyPeerCertificates(ctx, peerCerts); + #else + OSStatus ortn = SSLGetPeerCertificates(ctx, peerCerts); + #endif + if(ortn) { + printf("***Error obtaining peer certs: %s\n", + sslGetSSLErrString(ortn)); + } + return ortn; +} + +/* free the cert array obtained via SSLGetPeerCertificates() */ +static void freePeerCerts( + CFArrayRef peerCerts) +{ + if(peerCerts == NULL) { + return; + } + + #if USE_COPY_PEER_CERTS + + /* Voila! Problem fixed. */ + CFRelease(peerCerts); + return; + + #else + + CFIndex numCerts; + SecCertificateRef certData; + CFIndex i; + + numCerts = CFArrayGetCount(peerCerts); + for(i=0; i", ((unsigned)c) & 0xff); + } + break; + } + + } + printf("\n"); +} + +static void doPause(const char *prompt) { + if(prompt) { + printf("%s. ", prompt); + } + fpurge(stdin); + printf("Continue (n/anything)? "); + char c = getchar(); + if(c == 'n') { + exit(0); + } +} + +/* + * Perform one SSL diagnostic server-side session. Returns nonzero on error. + * Normally no output to stdout except initial "waiting for connection" message, + * unless there is a really screwed up error (i.e., something not directly related + * to the SSL connection). + */ +#define RCV_BUF_SIZE 256 + +static OSStatus sslServe( + otSocket listenSock, + unsigned short portNum, + SSLProtocol tryVersion, // only used if acceptedProts NULL + const char *acceptedProts, + CFArrayRef serverCerts, // required + char *password, // optional + CFArrayRef encryptServerCerts, // optional + bool allowExpired, + bool allowAnyRoot, + bool allowExpiredRoot, + bool disableCertVerify, + char *anchorFile, + bool replaceAnchors, + char cipherRestrict, // '2', 'd'. etc...'\0' for no + // restriction + SSLAuthenticate authenticate, + unsigned char *dhParams, // optional D-H parameters + unsigned dhParamsLen, + CFArrayRef acceptableDNList, // optional + bool resumableEnable, + uint32_t sessionCacheTimeout,// optional + bool disableAnonCiphers, + bool silent, // no stdout + bool pause, + SSLProtocol *negVersion, // RETURNED + SSLCipherSuite *negCipher, // RETURNED + SSLClientCertificateState *certState, // RETURNED + Boolean *sessionWasResumed, // RETURNED + unsigned char *sessionID, // mallocd by caller, RETURNED + size_t *sessionIDLength, // RETURNED + CFArrayRef *peerCerts, // mallocd & RETURNED + char **argv) +{ + otSocket acceptSock; + PeerSpec peerId; + OSStatus ortn; + SSLContextRef ctx = NULL; + size_t length; + uint8_t rcvBuf[RCV_BUF_SIZE]; + const char *outMsg = SERVER_MESSAGE; + + *negVersion = kSSLProtocolUnknown; + *negCipher = SSL_NULL_WITH_NULL_NULL; + *peerCerts = NULL; + + #if IGNORE_SIGPIPE + signal(SIGPIPE, sigpipe); + #endif + + /* first wait for a connection */ + if(!silent) { + printf("Waiting for client connection on port %u...", portNum); + fflush(stdout); + } + ortn = AcceptClientConnection(listenSock, &acceptSock, &peerId); + if(ortn) { + printf("AcceptClientConnection returned %d; aborting\n", (int)ortn); + return ortn; + } + + /* + * Set up a SecureTransport session. + * First the standard calls. + */ + ortn = SSLNewContext(true, &ctx); + if(ortn) { + printSslErrStr("SSLNewContext", ortn); + goto cleanup; + } + ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite); + if(ortn) { + printSslErrStr("SSLSetIOFuncs", ortn); + goto cleanup; + } + ortn = SSLSetConnection(ctx, (SSLConnectionRef)acceptSock); + if(ortn) { + printSslErrStr("SSLSetConnection", ortn); + goto cleanup; + } + + /* have to do these options befor setting server certs */ + if(allowExpired) { + ortn = SSLSetAllowsExpiredCerts(ctx, true); + if(ortn) { + printSslErrStr("SSLSetAllowExpiredCerts", ortn); + goto cleanup; + } + } + if(allowAnyRoot) { + ortn = SSLSetAllowsAnyRoot(ctx, true); + if(ortn) { + printSslErrStr("SSLSetAllowAnyRoot", ortn); + goto cleanup; + } + } + + if(anchorFile) { + ortn = sslAddTrustedRoot(ctx, anchorFile, replaceAnchors); + if(ortn) { + printf("***Error obtaining anchor file %s\n", anchorFile); + goto cleanup; + } + } + if(serverCerts != NULL) { + if(anchorFile == NULL) { + /* no specific anchors, so assume we want to trust this one */ + ortn = addIdentityAsTrustedRoot(ctx, serverCerts); + if(ortn) { + goto cleanup; + } + } + ortn = SSLSetCertificate(ctx, serverCerts); + if(ortn) { + printSslErrStr("SSLSetCertificate", ortn); + goto cleanup; + } + } + if(encryptServerCerts) { + ortn = SSLSetEncryptionCertificate(ctx, encryptServerCerts); + if(ortn) { + printSslErrStr("SSLSetEncryptionCertificate", ortn); + goto cleanup; + } + } + if(allowExpiredRoot) { + ortn = SSLSetAllowsExpiredRoots(ctx, true); + if(ortn) { + printSslErrStr("SSLSetAllowsExpiredRoots", ortn); + goto cleanup; + } + } + if(disableCertVerify) { + ortn = SSLSetEnableCertVerify(ctx, false); + if(ortn) { + printSslErrStr("SSLSetEnableCertVerify", ortn); + goto cleanup; + } + } + + /* + * SecureTransport options. + */ + if(acceptedProts) { + ortn = SSLSetProtocolVersionEnabled(ctx, kSSLProtocolAll, false); + if(ortn) { + printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn); + goto cleanup; + } + for(const char *cp = acceptedProts; *cp; cp++) { + SSLProtocol prot = kSSLProtocolUnknown; + switch(*cp) { + case '2': + prot = kSSLProtocol2; + break; + case '3': + prot = kSSLProtocol3; + break; + case 't': + prot = kTLSProtocol1; + break; + default: + usage(argv); + } + ortn = SSLSetProtocolVersionEnabled(ctx, prot, true); + if(ortn) { + printSslErrStr("SSLSetProtocolVersionEnabled", ortn); + goto cleanup; + } + } + } + else { + ortn = SSLSetProtocolVersion(ctx, tryVersion); + if(ortn) { + printSslErrStr("SSLSetProtocolVersion", ortn); + goto cleanup; + } + } + if(resumableEnable) { + ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec)); + if(ortn) { + printSslErrStr("SSLSetPeerID", ortn); + goto cleanup; + } + } + if(cipherRestrict != '\0') { + ortn = sslSetCipherRestrictions(ctx, cipherRestrict); + if(ortn) { + goto cleanup; + } + } + if(authenticate != kNeverAuthenticate) { + ortn = SSLSetClientSideAuthenticate(ctx, authenticate); + if(ortn) { + printSslErrStr("SSLSetClientSideAuthenticate", ortn); + goto cleanup; + } + } + if(dhParams) { + ortn = SSLSetDiffieHellmanParams(ctx, dhParams, dhParamsLen); + if(ortn) { + printSslErrStr("SSLSetDiffieHellmanParams", ortn); + goto cleanup; + } + } + if(sessionCacheTimeout) { + ortn = SSLSetSessionCacheTimeout(ctx, sessionCacheTimeout); + if(ortn) { + printSslErrStr("SSLSetSessionCacheTimeout", ortn); + goto cleanup; + } + } + if(disableAnonCiphers) { + ortn = SSLSetAllowAnonymousCiphers(ctx, false); + if(ortn) { + printSslErrStr("SSLSetAllowAnonymousCiphers", ortn); + goto cleanup; + } + /* quickie test of the getter */ + Boolean e; + ortn = SSLGetAllowAnonymousCiphers(ctx, &e); + if(ortn) { + printSslErrStr("SSLGetAllowAnonymousCiphers", ortn); + goto cleanup; + } + if(e) { + printf("***SSLGetAllowAnonymousCiphers() returned true; expected false\n"); + ortn = errSecIO; + goto cleanup; + } + } +/* XXX/cs + if(acceptableDNList) { + ortn = SSLSetCertificateAuthorities(ctx, acceptableDNList, TRUE); + if(ortn) { + printSslErrStr("SSLSetCertificateAuthorities", ortn); + goto cleanup; + } + } +*/ + /* end options */ + + if(pause) { + doPause("SSLContext initialized"); + } + + /* Perform SSL/TLS handshake */ + do + { ortn = SSLHandshake(ctx); + if((ortn == errSSLWouldBlock) && !silent) { + /* keep UI responsive */ + sslOutputDot(); + } + } while (ortn == errSSLWouldBlock); + + /* this works even if handshake failed due to cert chain invalid */ + copyPeerCerts(ctx, peerCerts); + + SSLGetClientCertificateState(ctx, certState); + SSLGetNegotiatedCipher(ctx, negCipher); + SSLGetNegotiatedProtocolVersion(ctx, negVersion); + *sessionIDLength = MAX_SESSION_ID_LENGTH; + SSLGetResumableSessionInfo(ctx, sessionWasResumed, sessionID, + sessionIDLength); + + if(!silent) { + printf("\n"); + } + if(ortn) { + goto cleanup; + } + if(pause) { + doPause("SSLContext handshake complete"); + } + + /* wait for one complete line or user says they've had enough */ + while(ortn == errSecSuccess) { + length = sizeof(rcvBuf); + ortn = SSLRead(ctx, rcvBuf, length, &length); + if(length == 0) { + /* keep UI responsive */ + sslOutputDot(); + } + else { + /* print what we have */ + printf("client request: "); + dumpAscii(rcvBuf, length); + } + if(pause) { + /* allow user to bail */ + char resp; + + fpurge(stdin); + printf("\nMore client request (y/anything): "); + resp = getchar(); + if(resp != 'y') { + break; + } + } + + /* poor person's line completion scan */ + for(unsigned i=0; i SSLSetProtocolVersionEnabled + bool quiet = false; + bool resumableEnable = true; + bool pause = false; + char *keyChainName = NULL; + char *encryptKeyChainName = NULL; + int loops = 1; + SSLAuthenticate authenticate = kNeverAuthenticate; + bool nonBlocking = false; + bool allowExpiredRoot = false; + bool disableCertVerify = false; + char *anchorFile = NULL; + bool replaceAnchors = false; + bool vfyCertState = false; + SSLClientCertificateState expectCertState = kSSLClientCertNone; + char *password = NULL; + char *dhParamsFile = NULL; + unsigned char *dhParams = NULL; + unsigned dhParamsLen = 0; + bool doIdSearch = false; + bool completeCertChain = false; + uint32_t sessionCacheTimeout = 0; + bool disableAnonCiphers = false; + CFMutableArrayRef acceptableDNList = NULL; + + for(arg=1; arg loop forever */ + loops = 0; + break; + } + else if(argp[1] != '=') { + usage(argv); + } + loops = atoi(&argp[2]); + break; + default: + usage(argv); + } + } + +#if NO_SERVER +# if DEBUG + securityd_init(); +# endif +#endif + + /* get server cert and optional encryption cert as CFArrayRef */ + if(keyChainName) { + serverCerts = getSslCerts(keyChainName, false, completeCertChain, + anchorFile, &serverKc); + if(serverCerts == nil) { + exit(1); + } + } + else +#if 0 + if(doIdSearch) { + OSStatus ortn = sslIdentityPicker(NULL, anchorFile, true, NULL, &serverCerts); + if(ortn) { + printf("***IdentitySearch failure; aborting.\n"); + exit(1); + } + } + if(password) { + OSStatus ortn = SecKeychainUnlock(serverKc, strlen(password), password, true); + if(ortn) { + printf("SecKeychainUnlock returned %d\n", (int)ortn); + /* oh well */ + } + } + if(encryptKeyChainName) { + encryptCerts = getSslCerts(encryptKeyChainName, true, completeCertChain, + anchorFile, &encryptKc); + if(encryptCerts == nil) { + exit(1); + } + } +#endif + if(protXOnly) { + switch(attemptProt) { + case kTLSProtocol1: + attemptProt = kTLSProtocol1Only; + break; + case kSSLProtocol3: + attemptProt = kSSLProtocol3Only; + break; + default: + break; + } + } +#if 0 + if(dhParamsFile) { + int r = cspReadFile(dhParamsFile, &dhParams, &dhParamsLen); + if(r) { + printf("***Error reading diffie-hellman params from %s; aborting\n", + dhParamsFile); + } + } +#endif + + /* one-time only server port setup */ + err = ListenForClients(portNum, nonBlocking, &listenSock); + if(err) { + printf("ListenForClients returned %d; aborting\n", (int)err); + exit(1); + } + + for(loopNum=1; ; loopNum++) { + err = sslServe(listenSock, + portNum, + attemptProt, + acceptedProts, + serverCerts, + password, + encryptCerts, + allowExpired, + allowAnyRoot, + allowExpiredRoot, + disableCertVerify, + anchorFile, + replaceAnchors, + cipherRestrict, + authenticate, + dhParams, + dhParamsLen, + acceptableDNList, + resumableEnable, + sessionCacheTimeout, + disableAnonCiphers, + quiet, + pause, + &negVersion, + &negCipher, + &certState, + &sessionWasResumed, + sessionID, + &sessionIDLength, + &peerCerts, + argv); + if(err) { + errCount++; + } + if(!quiet) { + SSLProtocol tryProt = attemptProt; + showSSLResult(tryProt, + acceptedProts, + err, + negVersion, + negCipher, + sessionWasResumed, + sessionID, + sessionIDLength, + peerCerts, + displayCerts, + certState, + fileBase ? fullFileBase : NULL); + } + errCount += verifyClientCertState(vfyCertState, expectCertState, + certState); + freePeerCerts(peerCerts); + if(loops && (loopNum == loops)) { + break; + } + }; + + endpointShutdown(listenSock); + + if(serverKc) { + CFRelease(serverKc); + } + if(encryptKc) { + CFRelease(encryptKc); + } + return errCount; + +} + + diff --git a/libsecurity_ssl/sslViewer/sslViewer.1 b/Security/libsecurity_ssl/sslViewer/sslViewer.1 similarity index 100% rename from libsecurity_ssl/sslViewer/sslViewer.1 rename to Security/libsecurity_ssl/sslViewer/sslViewer.1 diff --git a/libsecurity_ssl/sslViewer/sslViewer.cpp b/Security/libsecurity_ssl/sslViewer/sslViewer.cpp similarity index 99% rename from libsecurity_ssl/sslViewer/sslViewer.cpp rename to Security/libsecurity_ssl/sslViewer/sslViewer.cpp index 2ec660ed..eca0ed36 100644 --- a/libsecurity_ssl/sslViewer/sslViewer.cpp +++ b/Security/libsecurity_ssl/sslViewer/sslViewer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2013 Apple Inc. All Rights Reserved. * * SSL viewer tool, Secure Transport. */ diff --git a/libsecurity_ssl/sslViewer/sslViewer.xcodeproj/project.pbxproj b/Security/libsecurity_ssl/sslViewer/sslViewer.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_ssl/sslViewer/sslViewer.xcodeproj/project.pbxproj rename to Security/libsecurity_ssl/sslViewer/sslViewer.xcodeproj/project.pbxproj diff --git a/libsecurity_transform/100-sha2.m b/Security/libsecurity_transform/100-sha2.m similarity index 89% rename from libsecurity_transform/100-sha2.m rename to Security/libsecurity_transform/100-sha2.m index 500d4308..ec9d3c9c 100644 --- a/libsecurity_transform/100-sha2.m +++ b/Security/libsecurity_transform/100-sha2.m @@ -1,13 +1,28 @@ /* - * 100-sha2.c - * libsecurity_transform - * - * Created by JOsborne on 2/20/10. - * Copyright 2010 Apple. All rights reserved. + * Copyright (c) 2010-2011,2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include "SecTransform.h" #include "SecCustomTransform.h" #include "SecDigestTransform.h" @@ -334,4 +349,4 @@ int main(int argc, char *argv[]) { return 0; } -*/ \ No newline at end of file +*/ diff --git a/libsecurity_transform/Configurations/libsecurity_transform.Default.xcconfig b/Security/libsecurity_transform/Configurations/libsecurity_transform.Default.xcconfig similarity index 100% rename from libsecurity_transform/Configurations/libsecurity_transform.Default.xcconfig rename to Security/libsecurity_transform/Configurations/libsecurity_transform.Default.xcconfig diff --git a/libsecurity_transform/Configurations/libsecurity_transform_Deployment.xcconfig b/Security/libsecurity_transform/Configurations/libsecurity_transform_Deployment.xcconfig similarity index 100% rename from libsecurity_transform/Configurations/libsecurity_transform_Deployment.xcconfig rename to Security/libsecurity_transform/Configurations/libsecurity_transform_Deployment.xcconfig diff --git a/libsecurity_transform/Configurations/libsecurity_transform_Development.xcconfig b/Security/libsecurity_transform/Configurations/libsecurity_transform_Development.xcconfig similarity index 100% rename from libsecurity_transform/Configurations/libsecurity_transform_Development.xcconfig rename to Security/libsecurity_transform/Configurations/libsecurity_transform_Development.xcconfig diff --git a/libsecurity_transform/Configurations/libsecurity_transform_core.xcconfig b/Security/libsecurity_transform/Configurations/libsecurity_transform_core.xcconfig similarity index 100% rename from libsecurity_transform/Configurations/libsecurity_transform_core.xcconfig rename to Security/libsecurity_transform/Configurations/libsecurity_transform_core.xcconfig diff --git a/libsecurity_transform/Configurations/security_transform_Default.xcconfig b/Security/libsecurity_transform/Configurations/security_transform_Default.xcconfig similarity index 100% rename from libsecurity_transform/Configurations/security_transform_Default.xcconfig rename to Security/libsecurity_transform/Configurations/security_transform_Default.xcconfig diff --git a/libsecurity_transform/Configurations/security_transform_Deployment.xcconfig b/Security/libsecurity_transform/Configurations/security_transform_Deployment.xcconfig similarity index 100% rename from libsecurity_transform/Configurations/security_transform_Deployment.xcconfig rename to Security/libsecurity_transform/Configurations/security_transform_Deployment.xcconfig diff --git a/libsecurity_transform/Configurations/security_transform_Development.xcconfig b/Security/libsecurity_transform/Configurations/security_transform_Development.xcconfig similarity index 100% rename from libsecurity_transform/Configurations/security_transform_Development.xcconfig rename to Security/libsecurity_transform/Configurations/security_transform_Development.xcconfig diff --git a/libsecurity_transform/Info-security_transform.plist b/Security/libsecurity_transform/Info-security_transform.plist similarity index 100% rename from libsecurity_transform/Info-security_transform.plist rename to Security/libsecurity_transform/Info-security_transform.plist diff --git a/libsecurity_transform/NSData+HexString.h b/Security/libsecurity_transform/NSData+HexString.h similarity index 75% rename from libsecurity_transform/NSData+HexString.h rename to Security/libsecurity_transform/NSData+HexString.h index 1fa9094a..99f17345 100644 --- a/libsecurity_transform/NSData+HexString.h +++ b/Security/libsecurity_transform/NSData+HexString.h @@ -2,7 +2,7 @@ // NSData+HexString.h // libsecurity_transform // -// Copyright (c) 2011 Apple, Inc. All rights reserved. +// Copyright (c) 2011 Apple Inc. All Rights Reserved. // #import diff --git a/libsecurity_transform/NSData+HexString.m b/Security/libsecurity_transform/NSData+HexString.m similarity index 88% rename from libsecurity_transform/NSData+HexString.m rename to Security/libsecurity_transform/NSData+HexString.m index 2a0d2c8c..b68c90df 100644 --- a/libsecurity_transform/NSData+HexString.m +++ b/Security/libsecurity_transform/NSData+HexString.m @@ -2,7 +2,7 @@ // NSData+HexString.m // libsecurity_transform // -// Copyright (c) 2011 Apple, Inc. All rights reserved. +// Copyright (c) 2011,2014 Apple Inc. All Rights Reserved. // #import "NSData+HexString.h" @@ -22,7 +22,7 @@ buf[1] = [hex characterAtIndex:i+1]; char *b2 = NULL; *bp++ = strtol(buf, &b2, 16); - NSAssert(b2 == buf + 2, @"String should be all hex digits: %@ (bad digit around %d)", hex, i); + NSAssert(b2 == buf + 2, @"String should be all hex digits: %@ (bad digit around %ld)", hex, i); } return [NSData dataWithBytesNoCopy:bytes length:[hex length]/2 freeWhenDone:YES]; diff --git a/Security/libsecurity_transform/custom.h b/Security/libsecurity_transform/custom.h new file mode 100644 index 00000000..fc5a9464 --- /dev/null +++ b/Security/libsecurity_transform/custom.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2010-2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#import + + +@interface custom : SenTestCase { + +} + +@end diff --git a/libsecurity_transform/custom.mm b/Security/libsecurity_transform/custom.mm similarity index 97% rename from libsecurity_transform/custom.mm rename to Security/libsecurity_transform/custom.mm index d9db09c9..496048c2 100644 --- a/libsecurity_transform/custom.mm +++ b/Security/libsecurity_transform/custom.mm @@ -1,10 +1,26 @@ -// -// custom.m -// libsecurity_transform -// -// Created by JOsborne on 2/18/10. -// Copyright 2010 Apple. All rights reserved. -// +/* + * Copyright (c) 2010 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #import "SecTransform.h" @@ -36,6 +52,9 @@ #include #include #import "NSData+HexString.h" +#include +#include +#include // compatibility layer struct SecTransformCreateBlockParameters { @@ -94,7 +113,7 @@ static SecTransformInstanceBlock block_for_custom_transform(CFStringRef name, Se // Sort of a bridge from the old Custom SPI to the new API, but is also // useful when you REALLY need to access stack locals as __block variables, // but don't need multithreading, or generic internalizing. -SecTransformRef custom_transform(CFStringRef base_name, SecTransformCreateBlock cb) +static SecTransformRef custom_transform(CFStringRef base_name, SecTransformCreateBlock cb) { static int ct_cnt = 0; static dispatch_queue_t cnt_q = dispatch_queue_create("com.apple.security.custom_trasnform-cnt", 0); @@ -126,7 +145,7 @@ SecTransformRef custom_transform(CFStringRef base_name, SecTransformCreateBlock #define STAssertErrorHas(err, rx, msg...) STAssertTrue(ErrorHas(err, rx), ##msg); -BOOL ErrorHas(NSError *error, NSString *rx) { +static BOOL ErrorHas(NSError *error, NSString *rx) { if (!error) { return NO; } @@ -159,7 +178,7 @@ static SecTransformInstanceBlock DelayTransformBlock(CFStringRef name, { long long n; CFNumberGetValue((CFNumberRef)value, kCFNumberLongLongType, &n); - usleep(n / NSEC_PER_USEC); + usleep((useconds_t)(n / NSEC_PER_USEC)); } return value; @@ -170,7 +189,7 @@ static SecTransformInstanceBlock DelayTransformBlock(CFStringRef name, return Block_copy(instanceBlock); } -SecTransformRef delay_transform(long long nsec) { +static SecTransformRef delay_transform(long long nsec) { CFStringRef name = CFSTR("com.apple.security.unit-test.delay"); @@ -312,13 +331,13 @@ void BufferStream::SplitString(const char*& a, const char*& b) struct stat st; stat(name, &st); - char* rBuffer = (char*) malloc(st.st_size); + char* rBuffer = (char*) malloc((size_t)st.st_size); FILE* f = fopen(name, "r"); - fread(rBuffer, 1, st.st_size, f); + fread(rBuffer, 1, (size_t)st.st_size, f); fclose(f); // set up our output parser - BufferStream bStream(rBuffer, st.st_size); + BufferStream bStream(rBuffer, (size_t)st.st_size); const char* s = bStream.GetNextString(); bool didError = true; @@ -378,7 +397,7 @@ void BufferStream::SplitString(const char*& a, const char*& b) // dump to our output file // make a file name for the leaks output FILE* f = fopen(name, "w"); - fwrite(rBuffer, 1, st.st_size, f); + fwrite(rBuffer, 1, (size_t)st.st_size, f); fclose(f); } else @@ -505,7 +524,7 @@ static SecTransformInstanceBlock nopInstance(CFStringRef name, SecTransformRef n -(void)test_manyregister { dispatch_apply(4000, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^(size_t i) { - NSString *name = [NSString stringWithFormat:@"many%dregister", i]; + NSString *name = [NSString stringWithFormat:@"many%luregister", i]; CFErrorRef err = NULL; BOOL ok = SecTransformRegister((CFStringRef)name, nopInstance, &err); STAssertTrue(ok, @"register not ok"); @@ -522,7 +541,7 @@ static SecTransformInstanceBlock nopInstance(CFStringRef name, SecTransformRef n // NOTE: "mktemp" isn't as safe as you might think...but this is test code and doesn't have to be, but // if you copy it elsewhere you may well need to rewrite it. (use mkstemp) mktemp(kcfname); - OSStatus status = SecKeychainCreate(kcfname, strlen(passwd), passwd, NO, NULL, &tmp_keychain); + OSStatus status = SecKeychainCreate(kcfname, (UInt32)strlen(passwd), passwd, NO, NULL, &tmp_keychain); STAssertTrue(status == 0, @"Expected to make keychain, but got error 0x%x", status); const char *pem_key_bytes[] = { @@ -614,7 +633,7 @@ static SecTransformInstanceBlock nopInstance(CFStringRef name, SecTransformRef n // NOTE: "mktemp" isn't as safe as you might think...but this is test code and doesn't have to be, but // if you copy it elsewhere you may well need to rewrite it. (use mkstemp) mktemp(kcfname); - OSStatus status = SecKeychainCreate(kcfname, strlen(passwd), passwd, NO, NULL, &tmp_keychain); + OSStatus status = SecKeychainCreate(kcfname, (UInt32)strlen(passwd), passwd, NO, NULL, &tmp_keychain); STAssertTrue(status == 0, @"Expected to make keychain, but got error 0x%x", status); const char *pem_key_bytes[] = { @@ -1118,7 +1137,7 @@ static SecTransformInstanceBlock nopInstance(CFStringRef name, SecTransformRef n for (int j = 0; j < max_cycles; j++) { NSLog(@"Cycle %d", j); for (i = 0; i < sizeof(tests)/sizeof(KAT); i++) { - NSLog(@"test#%d %@ L(IN)=%lu, L(OUT)=%lu", i, tests[i].label, [tests[i].message length], [tests[i].encryptedMessage length]); + NSLog(@"test#%d %@ L(IN)=%lu, L(OUT)=%lu", i, tests[i].label, (unsigned long)[tests[i].message length], (unsigned long)[tests[i].encryptedMessage length]); CFErrorRef err = NULL; SecTransformRef encryptor = SecEncryptTransformCreate(tests[i].keys.pubKey, &err); @@ -2031,9 +2050,9 @@ static SecTransformInstanceBlock KnownProblemPlumbing(CFStringRef name, -(void)testExecuteBlock { unsigned char *raw_data = (unsigned char *)"Just some bytes, you know"; - NSData *empty = [NSData dataWithBytes:NULL length:0]; + //NSData *empty = [NSData dataWithBytes:NULL length:0]; NSData *data = [NSData dataWithBytes:raw_data length:strlen((const char *)raw_data)]; - NSUInteger ecnt = [empty retainCount]; + //NSUInteger ecnt = [empty retainCount]; SecTransformRef zt = SecEncodeTransformCreate(kSecZLibEncoding, NULL); SecTransformSetAttribute(zt, kSecTransformInputAttributeName, data, NULL); @@ -2043,9 +2062,9 @@ static SecTransformInstanceBlock KnownProblemPlumbing(CFStringRef name, __block BOOL ran_block = NO; SecTransformExecuteAsync(zt, q, ^(CFTypeRef message, CFErrorRef error, Boolean isFinal) { - if ([empty length]) { - NSLog(@"Empty data not so empty"); - } +// if ([empty length]) { +// NSLog(@"Empty data not so empty"); +// } STAssertTrue(dispatch_get_current_queue() == q, @"block dispatched to proper queue"); if (!ran_block) { @@ -2058,7 +2077,7 @@ static SecTransformInstanceBlock KnownProblemPlumbing(CFStringRef name, } }); - STAssertTrue(ecnt < [empty retainCount], @"SecTransformExecute retained block"); + //STAssertTrue(ecnt < [empty retainCount], @"SecTransformExecute retained block"); dispatch_sync(q_sync, ^{ }); STAssertTrue(ran_block, @"Block executed"); @@ -2311,7 +2330,7 @@ static SecTransformInstanceBlock CustomExternalization(CFStringRef name, ^(CFTypeRef d) { CFTypeRef internalizeResult = NULL; - id testObj = (id)d; + //id testObj = (id)d; //STAssertNotNil(testObj, @"Internalize did NOT get a dictionary!"); @@ -2328,7 +2347,7 @@ static SecTransformInstanceBlock CustomExternalization(CFStringRef name, // STAssertTrue(numResult, @"Could not get the version number from the CFNumberRef"); if (numResult) { - float knownVersion = 1.0; + //float knownVersion = 1.0; // STAssertTrue(knownVersion == versionNumber, @"Versions do not Match!"); } } @@ -2437,7 +2456,7 @@ static SecTransformInstanceBlock TestString(CFStringRef name, } } -CFNumberRef MakeNumber1(long n) +static CFNumberRef MakeNumber1(long n) { return CFNumberCreate(NULL, kCFNumberLongType, &n); } @@ -2571,7 +2590,7 @@ static SecTransformInstanceBlock CountTransformTest(CFStringRef name, return Block_copy(instanceBlock); } -SecTransformRef count_transform(int n) { +static SecTransformRef count_transform(int n) { CFStringRef name = CFSTR("com.apple.security.unit-test.count"); static dispatch_once_t once; @@ -3646,7 +3665,7 @@ static SecTransformInstanceBlock RoundTripCheck(CFStringRef name, return Block_copy(instanceBlock); } -BOOL RoundTrip(CFStringRef fname, SecTransformRef in, SecTransformRef out, BOOL share) +static BOOL RoundTrip(CFStringRef fname, SecTransformRef in, SecTransformRef out, BOOL share) { static dispatch_once_t once; CFStringRef name = CFSTR("com.apple.examples.cmp"); @@ -3926,9 +3945,9 @@ static SecTransformInstanceBlock CycleCheckTest(CFStringRef name, if (r) { CFNumberRef z = (CFNumberRef)[NSNumber numberWithInt:0]; - int n = CFArrayGetCountOfValue((CFArrayRef)r, CFRangeMake(0, CFArrayGetCount((CFArrayRef)r)), z); + CFIndex n = CFArrayGetCountOfValue((CFArrayRef)r, CFRangeMake(0, CFArrayGetCount((CFArrayRef)r)), z); // There should be six zeros in the xor->feedback chain from 0 to 19. - STAssertEquals(n, 6, @"There should be six zeros in %@", r); + STAssertEquals(n, (CFIndex) 6, @"There should be six zeros in %@", r); } CFRelease(r); @@ -4105,12 +4124,12 @@ static SecTransformInstanceBlock CycleCheckTest(CFStringRef name, const char raw_data1[] = "Not uuencoded\n"; CFDataRef data0 = CFDataCreate(NULL, (const UInt8*)raw_data0, strlen(raw_data0)); CFDataRef data1 = CFDataCreate(NULL, (const UInt8*)raw_data1, strlen(raw_data1)); - SecTransformSetAttribute(dt, kSecTransformInputAttributeName, data0, NULL); - - CFDataRef decoded_data = (CFDataRef)SecTransformExecute(dt, &error); - STAssertNotNil((NSData *)decoded_data, @"Got a decode result"); - STAssertEqualObjects((NSData *)decoded_data, (NSData *)data1, @"Proper decode results"); - + SecTransformSetAttribute(dt, kSecTransformInputAttributeName, data0, NULL); + + CFDataRef decoded_data = (CFDataRef)SecTransformExecute(dt, &error); + STAssertNotNil((NSData *)decoded_data, @"Got a decode result"); + STAssertEqualObjects((NSData *)decoded_data, (NSData *)data1, @"Proper decode results"); + SecTransformRef et = SecEncodeTransformCreate(kSecBase64Encoding, NULL); STAssertNotNil((id)et, @"Got encoder"); @@ -4120,7 +4139,43 @@ static SecTransformInstanceBlock CycleCheckTest(CFStringRef name, STAssertNotNil((NSData *)encoded_data, @"Got an encode result"); STAssertEqualObjects((NSData *)encoded_data, (NSData *)data0, @"Proper encode results"); - + + // Negative testing, assume the following struct + // struct __CFData { + // CFRuntimeBase _base; + // CFIndex _length; /* number of bytes */ + // CFIndex _capacity; /* maximum number of bytes */ + // CFAllocatorRef _bytesDeallocator; /* used only for immutable; if NULL, no deallocation */ + // uint8_t *_bytes; /* compaction: direct access to _bytes is only valid when data is not inline */ + // }; + SecTransformRef et_neg = SecEncodeTransformCreate(kSecBase64Encoding, NULL); + STAssertNotNil((id)et_neg, @"Got encoder for negative testing"); + + CFIndex *data1_length=(CFIndex*)((unsigned char *)data1 + sizeof(CFRuntimeBase)); + CFIndex data1_backup=*data1_length; + if (sizeof(CFIndex)==8) + { + *data1_length=0x5ffffffffffffff7; + } + else if (sizeof(CFIndex)==4) + { + *data1_length=0x5ffffff7; + } + else + { + STAssertTrue(false, @"Test error, representation of CFIndex not supported. Sizeof(CFIndex)=%d. Only support 4 or 8",sizeof(CFIndex)); + } + STAssertTrue(CFDataGetLength(data1)==*data1_length, @"Length not properly set - test bug - reads %lu expect %lu",CFDataGetLength(data1),*data1_length); + SecTransformSetAttribute(et_neg, kSecTransformInputAttributeName, data1, NULL); + CFDataRef encoded_data2 = (CFDataRef)SecTransformExecute(et_neg, &error); + STAssertNil((id)encoded_data2, @"No encoded data for negative testing"); + STAssertNotNil((id)error, @"Got error for negative testing"); + *data1_length=data1_backup; + if (error!=NULL) + { + STAssertTrue((CFErrorGetCode(error)==kSecTransformErrorInvalidLength), + @"Error for invalid length, got %lu expect %lu",CFErrorGetCode(error),kSecTransformErrorInvalidLength); + } // XXX also for general testing we want a "RandomChunkSizer" that copies INPUT to OUTPUT, but makes random size chunks (incl 0) as it goes. SecTransformRef dt2 = SecDecodeTransformCreate(kSecBase64Encoding, NULL); @@ -4132,6 +4187,9 @@ static SecTransformInstanceBlock CycleCheckTest(CFStringRef name, CFRelease(et2); CFRelease(dt2); + CFRelease(et); + CFRelease(et_neg); + CFRelease(dt); } static SecTransformInstanceBlock ErrorResultsTest(CFStringRef name, @@ -4293,7 +4351,7 @@ static SecTransformInstanceBlock ErrorResultsTest(CFStringRef name, // NOTE: "mktemp" isn't as safe as you might think...but this is test code and doesn't have to be, but // if you copy it elsewhere you may well need to rewrite it. (use mkstemp) mktemp(kcfname); - gp_status = SecKeychainCreate(kcfname, strlen(passwd), passwd, NO, NULL, &tmp_keychain); + gp_status = SecKeychainCreate(kcfname, (UInt32) strlen(passwd), passwd, NO, NULL, &tmp_keychain); STAssertTrue(gp_status == 0, @"SecKeychainCreate (gp_status=0x%x)", gp_status); gp_status = SecKeyCreatePair(tmp_keychain, CSSM_ALGID_DSA, 512, NULL, CSSM_KEYUSE_VERIFY|CSSM_KEYUSE_ENCRYPT|CSSM_KEYUSE_WRAP, @@ -4632,6 +4690,7 @@ static BOOL keyWithBytes(CFDataRef keyData, SecKeyRef* key, CFTypeRef keyClass) } -(void)testVerifyWithKeyFromBytes { + /* static const uint8_t original_pubKeyData[] = { 0x30, 0x48, 0x02, 0x41, 0x00, 0xd1, 0x4d, 0x1c, 0xe6, 0xbd, 0xd6, 0x8c, 0x4b, 0x77, 0x1e, 0x9f, @@ -4639,7 +4698,7 @@ static BOOL keyWithBytes(CFDataRef keyData, SecKeyRef* key, CFTypeRef keyClass) 0x3c, 0x7f, 0x98, 0xe0, 0xed, 0x49, 0xf5, 0x44, 0xb1, 0x87, 0xa8, 0xf6, 0x7f, 0x55, 0xc0, 0x39, 0xf0, 0xe7, 0xcc, 0x9c, 0x84, 0xde, 0x7d, 0x9a, 0x87, 0x38, 0xf2, 0x4b, 0x11, 0x6f, 0x63, 0x90, 0xfc, 0x72, 0x2c, 0x86, 0xa3, 0x02, 0x03, 0x01, 0x00, 0x01 - }; + }; */ // openssl genrsa -out /tmp/rsa512.pem // openssl rsa -inform PEM -in /tmp/rsa512.pem -outform DER -out /tmp/rsa512.der @@ -4757,7 +4816,7 @@ static BOOL keyWithBytes(CFDataRef keyData, SecKeyRef* key, CFTypeRef keyClass) // decoder each. Exports and attributes are hooked up so execution results in a CFData // with the same contents as input_data. "self" is used by the STAssert macros. // The various transforms are assigned names: G1, G2, G3, E64, EZLIB, DZLIB, D64. -SecTransformRef build_nested_groups(id self, CFDataRef input_data) { +static SecTransformRef build_nested_groups(id self, CFDataRef input_data) { SecGroupTransformRef outer = SecTransformCreateGroupTransform(); SecGroupTransformRef g1 = SecTransformCreateGroupTransform(); SecGroupTransformRef g2 = SecTransformCreateGroupTransform(); @@ -4954,7 +5013,7 @@ SecTransformRef build_nested_groups(id self, CFDataRef input_data) { STAssertEqualObjects((id)output2, (id)original, @"Output2 and original should match"); } -NSString *CopyLeakLine() +static NSString *CopyLeakLine() { static char os_build[16]; static dispatch_once_t get_os_build_once; diff --git a/libsecurity_transform/lib/CEncryptDecrypt.c b/Security/libsecurity_transform/lib/CEncryptDecrypt.c similarity index 100% rename from libsecurity_transform/lib/CEncryptDecrypt.c rename to Security/libsecurity_transform/lib/CEncryptDecrypt.c diff --git a/libsecurity_transform/lib/CoreFoundationBasics.cpp b/Security/libsecurity_transform/lib/CoreFoundationBasics.cpp similarity index 100% rename from libsecurity_transform/lib/CoreFoundationBasics.cpp rename to Security/libsecurity_transform/lib/CoreFoundationBasics.cpp diff --git a/libsecurity_transform/lib/CoreFoundationBasics.h b/Security/libsecurity_transform/lib/CoreFoundationBasics.h similarity index 100% rename from libsecurity_transform/lib/CoreFoundationBasics.h rename to Security/libsecurity_transform/lib/CoreFoundationBasics.h diff --git a/libsecurity_transform/lib/Digest.cpp b/Security/libsecurity_transform/lib/Digest.cpp similarity index 100% rename from libsecurity_transform/lib/Digest.cpp rename to Security/libsecurity_transform/lib/Digest.cpp diff --git a/libsecurity_transform/lib/Digest.h b/Security/libsecurity_transform/lib/Digest.h similarity index 100% rename from libsecurity_transform/lib/Digest.h rename to Security/libsecurity_transform/lib/Digest.h diff --git a/libsecurity_transform/lib/Digest_block.c b/Security/libsecurity_transform/lib/Digest_block.c similarity index 77% rename from libsecurity_transform/lib/Digest_block.c rename to Security/libsecurity_transform/lib/Digest_block.c index cf444698..968aae4e 100644 --- a/libsecurity_transform/lib/Digest_block.c +++ b/Security/libsecurity_transform/lib/Digest_block.c @@ -1,12 +1,27 @@ /* - * Digest_block.cpp - * libsecurity_transform - * - * Created by JOsborne on 2/20/10. - * Copyright 2010 Apple. All rights reserved. + * Copyright (c) 2010-2011,2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include "Digest_block.h" #include "SecCustomTransform.h" #include diff --git a/Security/libsecurity_transform/lib/Digest_block.h b/Security/libsecurity_transform/lib/Digest_block.h new file mode 100644 index 00000000..9ab977f9 --- /dev/null +++ b/Security/libsecurity_transform/lib/Digest_block.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2010-2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + diff --git a/libsecurity_transform/lib/EncodeDecodeTransforms.c b/Security/libsecurity_transform/lib/EncodeDecodeTransforms.c similarity index 96% rename from libsecurity_transform/lib/EncodeDecodeTransforms.c rename to Security/libsecurity_transform/lib/EncodeDecodeTransforms.c index eaeb08cc..413d7ec9 100644 --- a/libsecurity_transform/lib/EncodeDecodeTransforms.c +++ b/Security/libsecurity_transform/lib/EncodeDecodeTransforms.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -634,17 +634,36 @@ static SecTransformInstanceBlock EncodeTransform(CFStringRef name, const unsigned char *in = d ? CFDataGetBytePtr(d) : NULL; CFIndex n_chunks = in_len / in_chunk_size + 3; CFIndex buf_len = n_chunks * out_chunk_size; - if (target_line_length) + CFIndex line_len=0; + + if (target_line_length) { - buf_len += (n_chunks * out_chunk_size) / target_line_length; - } + line_len=(n_chunks * out_chunk_size) / target_line_length; + } + if ( (in_len<0) + || (leftover_cnt<0) +#if __LLP64__ + || (n_chunks > LONG_LONG_MAX/out_chunk_size) + || (buf_len > LONG_LONG_MAX-line_len) +#else + || (n_chunks > LONG_MAX/out_chunk_size) + || (buf_len > LONG_MAX-line_len) +#endif + || (buf_len+line_len= leftover_cnt)) { CFIndex copy_len = in_chunk_size - leftover_cnt; copy_len = (copy_len > in_len) ? in_len : copy_len; diff --git a/libsecurity_transform/lib/EncryptTransform.cpp b/Security/libsecurity_transform/lib/EncryptTransform.cpp similarity index 96% rename from libsecurity_transform/lib/EncryptTransform.cpp rename to Security/libsecurity_transform/lib/EncryptTransform.cpp index fc2f94cf..c6617513 100644 --- a/libsecurity_transform/lib/EncryptTransform.cpp +++ b/Security/libsecurity_transform/lib/EncryptTransform.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. - * + * Copyright (c) 2010-2014 Apple Inc. All Rights Reserved. + * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code @@ -49,8 +49,8 @@ dispatch_queue_t EncryptDecryptBase::serializerTransformStartingExecution; method: EncryptDecryptBase (Constructor) description: Initialize a new instance of a EncryptDecryptBase class -------------------------------------------------------------------------- */ -EncryptDecryptBase::EncryptDecryptBase(CFStringRef type) : -Transform(type), +EncryptDecryptBase::EncryptDecryptBase(CFStringRef type) : +Transform(type), m_cssm_padding(CSSM_PADDING_NONE), m_mode(CSSM_ALGMODE_CBCPadIV8), m_cssm_key(NULL), @@ -108,13 +108,13 @@ EncryptDecryptBase::~EncryptDecryptBase() description: Initialize an instance of the base encrypt/decrypt transform -------------------------------------------------------------------------- */ bool EncryptDecryptBase::InitializeObject(SecKeyRef key, CFErrorRef *error) -{ +{ SetAttributeNoCallback(kSecEncryptKey, key); if (error) { *error = NULL; } - + return true; } @@ -131,7 +131,7 @@ CFErrorRef EncryptDecryptBase::SerializedTransformStartingExecution() { return CreateSecTransformErrorRef(kSecTransformErrorAttributeNotFound, "The attribute %@ was not found.", kSecEncryptKey); } - + OSStatus err = errSecSuccess; err = SecKeyGetCSSMKey(key, (const CSSM_KEY **)&m_cssm_key); if (errSecSuccess != err) @@ -141,7 +141,7 @@ CFErrorRef EncryptDecryptBase::SerializedTransformStartingExecution() CFRelease(result); return retValue; } - + CSSM_CSP_HANDLE csp; err = SecKeyGetCSPHandle(key, &csp); if (errSecSuccess != err) @@ -151,20 +151,20 @@ CFErrorRef EncryptDecryptBase::SerializedTransformStartingExecution() CFRelease(result); return retValue; } - + CSSM_ALGORITHMS keyAlg = m_cssm_key->KeyHeader.AlgorithmId; - + m_cssm_padding = CSSM_PADDING_NONE; CFStringRef paddingStr = (CFStringRef) GetAttribute(kSecPaddingKey); CFStringRef modeStr = (CFStringRef) GetAttribute (kSecEncryptionMode); CFDataRef ivData = (CFDataRef) GetAttribute(kSecIVKey); - + Boolean hasPadding = (paddingStr != NULL); Boolean hasMode = (modeStr != NULL); Boolean hasIVData = (ivData != NULL); - Boolean isSymetrical = (m_cssm_key->KeyHeader.KeyClass == CSSM_KEYCLASS_SESSION_KEY); - - + Boolean isSymmetrical = (m_cssm_key->KeyHeader.KeyClass == CSSM_KEYCLASS_SESSION_KEY); + + if (!hasPadding) { if (CSSM_ALGID_RSA == keyAlg || CSSM_ALGID_ECDSA == keyAlg) @@ -191,7 +191,7 @@ CFErrorRef EncryptDecryptBase::SerializedTransformStartingExecution() } } } - + if (!hasMode) { m_mode = (CSSM_PADDING_NONE == m_cssm_padding) ? CSSM_ALGMODE_CBC_IV8 : CSSM_ALGMODE_CBCPadIV8; @@ -200,10 +200,24 @@ CFErrorRef EncryptDecryptBase::SerializedTransformStartingExecution() { m_mode = ConvertEncryptModeStringToEnum(modeStr, (CSSM_PADDING_NONE != m_cssm_padding)); } - - + + CSSM_RETURN crtn = CSSM_OK; - if (isSymetrical) + CSSM_ACCESS_CREDENTIALS creds; + CSSM_ACCESS_CREDENTIALS* credPtr = NULL; + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + + err = SecKeyGetCredentials(key, + (m_forEncryption) ? CSSM_ACL_AUTHORIZATION_ENCRYPT : CSSM_ACL_AUTHORIZATION_DECRYPT, + kSecCredentialTypeDefault, + (const CSSM_ACCESS_CREDENTIALS **)&credPtr); + if (errSecSuccess != err) + { + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + credPtr = &creds; + } + + if (isSymmetrical) { CSSM_DATA initVector; if (hasIVData) @@ -217,11 +231,11 @@ CFErrorRef EncryptDecryptBase::SerializedTransformStartingExecution() initVector.Data = (uint8 *)malloc(initVector.Length); initVector.Data = gKeySalt.Data; } - - crtn = CSSM_CSP_CreateSymmetricContext(csp, keyAlg, m_mode, NULL, m_cssm_key, - &initVector, m_cssm_padding, NULL, &m_handle); - - // Need better error here + + crtn = CSSM_CSP_CreateSymmetricContext(csp, keyAlg, m_mode, credPtr, m_cssm_key, + &initVector, m_cssm_padding, NULL, &m_handle); + + // Need better error here if (crtn != CSSM_OK) { CFStringRef result = SecCopyErrorMessageString(crtn, NULL); @@ -229,28 +243,12 @@ CFErrorRef EncryptDecryptBase::SerializedTransformStartingExecution() CFRelease(result); return retValue; } - } else { - CSSM_ACCESS_CREDENTIALS creds; - CSSM_ACCESS_CREDENTIALS* credPtr = NULL; - memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); - - err = SecKeyGetCredentials(key, - (m_forEncryption) ? CSSM_ACL_AUTHORIZATION_ENCRYPT : CSSM_ACL_AUTHORIZATION_DECRYPT, - kSecCredentialTypeDefault, - (const CSSM_ACCESS_CREDENTIALS **)&credPtr); - - if (errSecSuccess != err) - { - memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); - credPtr = &creds; - } - - - crtn = CSSM_CSP_CreateAsymmetricContext(csp, keyAlg, credPtr, m_cssm_key, m_cssm_padding, &m_handle); - // Need better error here + crtn = CSSM_CSP_CreateAsymmetricContext(csp, keyAlg, credPtr, m_cssm_key, m_cssm_padding, &m_handle); + + // Need better error here if (crtn != CSSM_OK) { CFStringRef result = SecCopyErrorMessageString(crtn, NULL); @@ -259,10 +257,10 @@ CFErrorRef EncryptDecryptBase::SerializedTransformStartingExecution() return retValue; } } - + // Encryption crtn = (m_forEncryption) ? CSSM_EncryptDataInit(m_handle) : CSSM_DecryptDataInit(m_handle); - // Need better error here + // Need better error here if (crtn != CSSM_OK) { CFStringRef result = SecCopyErrorMessageString(crtn, NULL); @@ -270,9 +268,9 @@ CFErrorRef EncryptDecryptBase::SerializedTransformStartingExecution() CFRelease(result); return retValue; } - - - return result; + + + return result; } /* -------------------------------------------------------------------------- @@ -285,13 +283,13 @@ CFErrorRef EncryptDecryptBase::SerializedTransformStartingExecution() -------------------------------------------------------------------------- */ CFErrorRef EncryptDecryptBase::TransformStartingExecution() { - + dispatch_once(&serializerSetUp, ^{ serializerTransformStartingExecution = dispatch_queue_create("com.apple.security.EncryptDecrypt.key-setup", NULL); }); - + __block CFErrorRef result = NULL; // Assume all is well - + dispatch_sync(serializerTransformStartingExecution, ^{ result = SerializedTransformStartingExecution(); }); @@ -316,7 +314,7 @@ void EncryptDecryptBase::SendCSSMError(CSSM_RETURN retCode) CFStringRef errorString = SecCopyErrorMessageString(retCode, NULL); CFErrorRef errorRef = CreateGenericErrorRef(kCFErrorDomainOSStatus, retCode, "%@", errorString); CFRelease(errorString); - + SendAttribute(kSecTransformOutputAttributeName, errorRef); CFRelease(errorRef); } @@ -326,11 +324,11 @@ void xor_bytes(UInt8 *dst, const UInt8 *src1, const UInt8 *src2, CFIndex length) void xor_bytes(UInt8 *dst, const UInt8 *src1, const UInt8 *src2, CFIndex length) { // NOTE: this can be made faster, but see if we already have a faster version somewhere first. - + // _mm_xor_ps would be nice here // failing that, getting to an aligned boundry and switching to uint64_t // would be good. - + while (length--) { *dst++ = *src1++ ^ *src2++; } @@ -357,15 +355,15 @@ CFDataRef EncryptDecryptBase::remove_oaep_padding(CFDataRef encodedMessage) // but CDSA leaves that responsability to us (we did ask it for "no padding" after all). // (use extraPaddingLength = 0 when using a layer that does strip that byte) const int extraPaddingLength = 1; - + // The numbered steps below correspond to RSA Laboratories' RSAES-OAEP Encryption Scheme // document's numbered steps. - + // NOTE: we omit step 1: "If the length of P is greater than the input limitation for the hash // function (2^61 − 1 octets for SHA-1) then output ‘‘decoding error’’ and stop."; we don't have // ready access to the input limits of the hash functions, and in the real world we won't be // seeing messages that long anyway. - + // (2) If emLen < 2hLen + 1, output ‘‘decoding error’’ and stop. hashAlgo = (CFStringRef)this->GetAttribute(kSecOAEPMGF1DigestAlgorithmAttributeName); if (hashAlgo == NULL) { @@ -380,7 +378,7 @@ CFDataRef EncryptDecryptBase::remove_oaep_padding(CFDataRef encodedMessage) // octets. maskedSeed = CFDataCreateWithBytesNoCopy(NULL, CFDataGetBytePtr(encodedMessage) +extraPaddingLength, hLen, kCFAllocatorNull); maskedDB = CFDataCreateWithBytesNoCopy(NULL, CFDataGetBytePtr(encodedMessage) + hLen +extraPaddingLength, CFDataGetLength(encodedMessage) - hLen -extraPaddingLength, kCFAllocatorNull); - + // (4) Let seedMask = MGF(maskedDB, hLen). mgf_maskedDB = SecCreateMaskGenerationFunctionTransform(hashAlgo, hLen, &error); if (!mgf_maskedDB) { @@ -394,7 +392,7 @@ CFDataRef EncryptDecryptBase::remove_oaep_padding(CFDataRef encodedMessage) goto out; } (void)transforms_assume(hLen == CFDataGetLength(seedMask)); - + // (5) Let seed = maskedSeed ⊕ seedMask. raw_seed = (UInt8*)malloc(hLen); xor_bytes(raw_seed, CFDataGetBytePtr(maskedSeed), CFDataGetBytePtr(seedMask), hLen); @@ -416,11 +414,11 @@ CFDataRef EncryptDecryptBase::remove_oaep_padding(CFDataRef encodedMessage) if (!dbMask) { goto out; } - + // (7) Let DB = maskedDB ⊕ dbMask. raw_DB = (UInt8*)malloc(CFDataGetLength(dbMask)); xor_bytes(raw_DB, CFDataGetBytePtr(maskedDB), CFDataGetBytePtr(dbMask), CFDataGetLength(dbMask)); - + // (8) Let pHash = Hash(P), an octet string of length hLen. hash = SecDigestTransformCreate(hashAlgo, 0, &error); if (!hash) { @@ -438,14 +436,14 @@ CFDataRef EncryptDecryptBase::remove_oaep_padding(CFDataRef encodedMessage) if (!SecTransformSetAttribute(hash, kSecTransformInputAttributeName, EncodingParameters, &error)) { goto out; } - + pHash = (CFDataRef)transforms_assume(SecTransformExecute(hash, &error)); if (!pHash) { goto out; } (void)transforms_assume(hLen == CFDataGetLength(pHash)); - + // (9) Separate DB into an octet string pHash’ consisting of the first hLen octets of DB, a // (possibly empty) octet string PS consisting of consecutive zero octets following pHash’, // and a message M as If there is no 01 octet to separate PS from M , output ‘‘decoding error’’ and stop. @@ -460,7 +458,7 @@ CFDataRef EncryptDecryptBase::remove_oaep_padding(CFDataRef encodedMessage) // (10) If pHash’ does not equal pHash, output ‘‘decoding error’’ and stop. goto out; } - + out: if (!message) { if (!error) { @@ -468,7 +466,7 @@ out: } SetAttributeNoCallback(kSecTransformOutputAttributeName, error); } - + // Release eveything except: // hashAlgo (obtained via get) // message (return value) @@ -485,7 +483,7 @@ out: CFSafeRelease(EncodingParameters); // raw_seed is free'd via CFData, addr01 was never allocated, so raw_DB is our lot free(raw_DB); - + // (11) Output M. return message; #endif @@ -499,14 +497,14 @@ CFDataRef EncryptDecryptBase::apply_oaep_padding(CFDataRef dataValue) { #if 1 // MGF1 w/ SHA1 assumed here - + CFErrorRef error = NULL; int hLen = Digest::LengthForType(kSecDigestSHA1); CFNumberRef desired_message_length_cf = (CFNumberRef)this->GetAttribute(kSecOAEPMessageLengthAttributeName); int desired_message_length = 0; CSSM_QUERY_SIZE_DATA RSA_size; CFDataRef EM = NULL; - + if (desired_message_length_cf) { CFNumberGetValue(desired_message_length_cf, kCFNumberIntType, &desired_message_length); } else { @@ -545,7 +543,7 @@ CFDataRef EncryptDecryptBase::apply_oaep_padding(CFDataRef dataValue) // (2^61 − 1 octets for SHA-1) then output ‘‘parameter string too long’’ and stop. // We don't have ready access to the input limit of the hash functions, and in the real world // we won't be seeing a message that long anyway. - + // (2) If mLen > emLen − 2hLen − 1, output ‘‘message too long’’ and stop. hashAlgo = (CFStringRef)this->GetAttribute(kSecOAEPMGF1DigestAlgorithmAttributeName); if (hashAlgo == NULL) { @@ -575,7 +573,7 @@ CFDataRef EncryptDecryptBase::apply_oaep_padding(CFDataRef dataValue) error = CreateSecTransformErrorRef(kSecTransformErrorInvalidLength, "Your message is too long for your message length, it needs to be %d bytes shorter, or you need to adjust the kSecOAEPMessageLengthAttributeName attribute", -padLen); goto out; } - + // (3) Generate an octet string PS consisting of emLen − mLen − 2hLen − 1 zero octets. The length of PS may be 0. raw_padZeros = (UInt8*)calloc(padLen, 1); if (!raw_padZeros) { @@ -588,7 +586,7 @@ CFDataRef EncryptDecryptBase::apply_oaep_padding(CFDataRef dataValue) error = GetNoMemoryErrorAndRetain(); goto out; } - + // (4) Let pHash = Hash(P), an octet string of length hLen. hash = SecDigestTransformCreate(hashAlgo, 0, &error); if (!hash) { @@ -607,13 +605,13 @@ CFDataRef EncryptDecryptBase::apply_oaep_padding(CFDataRef dataValue) if (!SecTransformSetAttribute(hash, kSecTransformInputAttributeName, EncodingParameters, &error)) { goto out; } - + padHash = (CFDataRef)transforms_assume(SecTransformExecute(hash, &error)); if (!padHash) { goto out; } (void)transforms_assume(hLen == CFDataGetLength(padHash)); - + // (5) Concatenate pHash,PS, the message M, and other padding to form a data block DB as DB = pHash∥PS∥01∥M. dataBlob = CFDataCreateMutable(NULL, CFDataGetLength(padHash) + padLen + 1 + CFDataGetLength(dataValue)); if (!dataBlob) { @@ -624,7 +622,7 @@ CFDataRef EncryptDecryptBase::apply_oaep_padding(CFDataRef dataValue) CFDataAppendBytes(dataBlob, raw_padZeros, padLen); CFDataAppendBytes(dataBlob, (UInt8*)"\01", 1); CFDataAppendBytes(dataBlob, CFDataGetBytePtr(dataValue), CFDataGetLength(dataValue)); - + // (6) Generate a random octet string seed of length hLen. seed = (CFDataRef)this->GetAttribute(CFSTR("FixedSeedForOAEPTesting")); raw_seed = NULL; @@ -645,7 +643,7 @@ CFDataRef EncryptDecryptBase::apply_oaep_padding(CFDataRef dataValue) error = GetNoMemoryErrorAndRetain(); } } - + // (7) Let dbMask = MGF (seed, emLen − hLen). mgf_dbMask = transforms_assume(SecCreateMaskGenerationFunctionTransform(hashAlgo, desired_message_length - hLen, &error)); if (!mgf_dbMask) { @@ -655,7 +653,7 @@ CFDataRef EncryptDecryptBase::apply_oaep_padding(CFDataRef dataValue) goto out; } dbMask = (CFDataRef)SecTransformExecute(mgf_dbMask, &error); - + // (8) Let maskedDB = DB ⊕ dbMask. // NOTE: we do some allocations above...you know, we should be able to malloc ONE buffer of the // proper size. @@ -671,7 +669,7 @@ CFDataRef EncryptDecryptBase::apply_oaep_padding(CFDataRef dataValue) error = GetNoMemoryErrorAndRetain(); goto out; } - + // (9) Let seedMask = MGF(maskedDB, hLen). mgf_seedMask = transforms_assume(SecCreateMaskGenerationFunctionTransform(hashAlgo, hLen, &error)); if (!mgf_seedMask) { @@ -684,7 +682,7 @@ CFDataRef EncryptDecryptBase::apply_oaep_padding(CFDataRef dataValue) if (!seedMask) { goto out; } - + // (10) Let maskedSeed = seed ⊕ seedMask raw_maskedSeed = (UInt8 *)malloc(hLen); if (!raw_maskedSeed) { @@ -692,7 +690,7 @@ CFDataRef EncryptDecryptBase::apply_oaep_padding(CFDataRef dataValue) goto out; } xor_bytes(raw_maskedSeed, raw_seed, CFDataGetBytePtr(seedMask), hLen); - + // (11) Let EM = maskedSeed∥maskedDB (if we didn't have to pushback the NULL we could do this without physically concatanating) // (figure out amount of leading zero padding we need) RSA_size.SizeInputBlock = hLen + CFDataGetLength(maskedDB); @@ -708,7 +706,7 @@ CFDataRef EncryptDecryptBase::apply_oaep_padding(CFDataRef dataValue) while(paddingNeeded--) { CFDataAppendBytes(EM, (UInt8*)"", 1); } - + CFDataAppendBytes(EM, raw_maskedSeed, hLen); CFDataAppendBytes(EM, raw_maskedDB, CFDataGetLength(maskedDB)); out: @@ -716,7 +714,7 @@ out: SetAttributeNoCallback(kSecTransformOutputAttributeName, error); (void)transforms_assume_zero(EM); } - + CFSafeRelease(seed); // via get?? CFSafeRelease(dbMask); CFSafeRelease(maskedDB); @@ -732,7 +730,7 @@ out: CFSafeRelease(hash); // raw_* are all freed by their associated CFDatas, except raw_maskedSeed free(raw_maskedSeed); - + // (12) Output EM. return EM; #endif @@ -749,7 +747,7 @@ void EncryptDecryptBase::AttributeChanged(SecTransformAttributeRef ah, CFTypeRef { return; // we only deal with input } - + if (value != NULL) { CFTypeID valueType = CFGetTypeID(value); @@ -761,14 +759,14 @@ void EncryptDecryptBase::AttributeChanged(SecTransformAttributeRef ah, CFTypeRef SetAttributeNoCallback(kSecTransformOutputAttributeName, error); return; } - + if (m_forEncryption && m_accumulator) { CFDataRef d = (CFDataRef)value; CFDataAppendBytes(m_accumulator, CFDataGetBytePtr(d), CFDataGetLength(d)); return; } } - + if (m_forEncryption && m_accumulator) { (void)transforms_assume_zero(value); value = m_accumulator; @@ -777,7 +775,7 @@ void EncryptDecryptBase::AttributeChanged(SecTransformAttributeRef ah, CFTypeRef CFSafeRelease(value); }); this->Pushback(inputAH, NULL); - + if (m_oaep_padding) { value = apply_oaep_padding((CFDataRef)value); dispatch_async(this->mDispatchQueue, ^{ @@ -785,24 +783,24 @@ void EncryptDecryptBase::AttributeChanged(SecTransformAttributeRef ah, CFTypeRef }); } } - + // add the input to our cryptor CFDataRef valueRef = (CFDataRef) value; CSSM_RETURN crtn = CSSM_OK; Boolean inFinal = FALSE; - + if (valueRef != NULL) { // Convert to A CSSM_DATA CSSM_DATA dataStruct; dataStruct.Length = CFDataGetLength(valueRef); dataStruct.Data = const_cast(CFDataGetBytePtr(valueRef)); - + CSSM_DATA intermediateDataStruct; memset(&intermediateDataStruct, 0, sizeof(intermediateDataStruct)); - + CSSM_SIZE bytesProcessed = 0; - + if (m_forEncryption) { crtn = CSSM_EncryptDataUpdate(m_handle, @@ -821,21 +819,21 @@ void EncryptDecryptBase::AttributeChanged(SecTransformAttributeRef ah, CFTypeRef 1, &bytesProcessed); } - + if (CSSM_OK != crtn) { SendCSSMError(crtn); return; } - - + + if (intermediateDataStruct.Length > 0) { if (NULL == m_processedData) { m_processedData = CFDataCreateMutable(kCFAllocatorDefault, 0); } - + CFDataAppendBytes(m_processedData, intermediateDataStruct.Data, bytesProcessed); free(intermediateDataStruct.Data); } @@ -843,13 +841,13 @@ void EncryptDecryptBase::AttributeChanged(SecTransformAttributeRef ah, CFTypeRef else { // Finalize - + inFinal = TRUE; CSSM_DATA remData; memset(&remData, 0, sizeof(remData)); - + crtn = (m_forEncryption) ? CSSM_EncryptDataFinal(m_handle, &remData) : CSSM_DecryptDataFinal(m_handle, &remData); - + if (CSSM_OK == crtn) { if (m_forEncryption == false && m_accumulator) { @@ -862,14 +860,14 @@ void EncryptDecryptBase::AttributeChanged(SecTransformAttributeRef ah, CFTypeRef { m_processedData = CFDataCreateMutable(kCFAllocatorDefault, 0); } - + if (remData.Length > 0) { - CFDataAppendBytes(m_processedData, remData.Data, remData.Length); + CFDataAppendBytes(m_processedData, remData.Data, remData.Length); } } } - + free(remData.Data); if (CSSM_OK != crtn) @@ -877,15 +875,15 @@ void EncryptDecryptBase::AttributeChanged(SecTransformAttributeRef ah, CFTypeRef SendCSSMError(crtn); return; } - } - + } + if (NULL != m_processedData) { SendAttribute(kSecTransformOutputAttributeName, m_processedData); CFRelease(m_processedData); m_processedData = NULL; } - + if (inFinal) { if (m_oaep_padding && m_forEncryption == false) { @@ -895,8 +893,8 @@ void EncryptDecryptBase::AttributeChanged(SecTransformAttributeRef ah, CFTypeRef } SendAttribute(kSecTransformOutputAttributeName, NULL); } - - + + } /* -------------------------------------------------------------------------- @@ -914,17 +912,17 @@ CFDictionaryRef EncryptDecryptBase::CopyState() { CFDictionaryAddValue(state, kSecPaddingKey, paddingStr); } - + if (NULL != modeStr) { CFDictionaryAddValue(state, kSecEncryptionMode, modeStr); } - + if (NULL != ivData) { CFDictionaryAddValue(state, kSecIVKey, ivData); } - + return state; } @@ -938,26 +936,26 @@ void EncryptDecryptBase::RestoreState(CFDictionaryRef state) { return; } - + CFStringRef paddingStr = (CFStringRef)CFDictionaryGetValue(state, kSecPaddingKey); CFStringRef modeStr = (CFStringRef)CFDictionaryGetValue(state, kSecEncryptionMode); CFDataRef ivData = (CFDataRef)CFDictionaryGetValue(state, kSecIVKey); - + if (NULL != paddingStr) { SetAttribute(kSecPaddingKey, paddingStr); } - + if (NULL != modeStr) { SetAttribute(kSecEncryptionMode, modeStr); } - + if (NULL != ivData) { SetAttribute(kSecIVKey, ivData); } - + } /* -------------------------------------------------------------------------- @@ -1005,9 +1003,9 @@ public: /* -------------------------------------------------------------------------- method: EncryptTransformFactory (Constructor) - description: + description: -------------------------------------------------------------------------- */ -EncryptTransformFactory::EncryptTransformFactory() : +EncryptTransformFactory::EncryptTransformFactory() : TransformFactory(kEncryptTransformType) {} @@ -1073,9 +1071,9 @@ public: /* -------------------------------------------------------------------------- method: DecryptTransformFactory (Constructor) - description: + description: -------------------------------------------------------------------------- */ -DecryptTransformFactory::DecryptTransformFactory() : +DecryptTransformFactory::DecryptTransformFactory() : TransformFactory(kDecryptTransformType) {} diff --git a/libsecurity_transform/lib/EncryptTransform.h b/Security/libsecurity_transform/lib/EncryptTransform.h similarity index 98% rename from libsecurity_transform/lib/EncryptTransform.h rename to Security/libsecurity_transform/lib/EncryptTransform.h index 3bbd221b..69b429c7 100644 --- a/libsecurity_transform/lib/EncryptTransform.h +++ b/Security/libsecurity_transform/lib/EncryptTransform.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_transform/lib/EncryptTransformUtilities.cpp b/Security/libsecurity_transform/lib/EncryptTransformUtilities.cpp similarity index 98% rename from libsecurity_transform/lib/EncryptTransformUtilities.cpp rename to Security/libsecurity_transform/lib/EncryptTransformUtilities.cpp index fab7f50a..0ddeabcf 100644 --- a/libsecurity_transform/lib/EncryptTransformUtilities.cpp +++ b/Security/libsecurity_transform/lib/EncryptTransformUtilities.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_transform/lib/EncryptTransformUtilities.h b/Security/libsecurity_transform/lib/EncryptTransformUtilities.h similarity index 98% rename from libsecurity_transform/lib/EncryptTransformUtilities.h rename to Security/libsecurity_transform/lib/EncryptTransformUtilities.h index da79d6b5..11f3cbe4 100644 --- a/libsecurity_transform/lib/EncryptTransformUtilities.h +++ b/Security/libsecurity_transform/lib/EncryptTransformUtilities.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_transform/lib/GroupTransform.cpp b/Security/libsecurity_transform/lib/GroupTransform.cpp similarity index 99% rename from libsecurity_transform/lib/GroupTransform.cpp rename to Security/libsecurity_transform/lib/GroupTransform.cpp index a23345c3..08ecf8ce 100644 --- a/libsecurity_transform/lib/GroupTransform.cpp +++ b/Security/libsecurity_transform/lib/GroupTransform.cpp @@ -401,7 +401,7 @@ void GroupTransform::RecurseForAllNodes(dispatch_group_t group, CFErrorRef *err_ __block CFErrorRef *err = err_; void (^set_error)(CFErrorRef new_err) = ^(CFErrorRef new_err) { if (new_err) { - if (!OSAtomicCompareAndSwapPtrBarrier(NULL, new_err, (void**)err)) { + if (!OSAtomicCompareAndSwapPtrBarrier(NULL, (void *)new_err, (void**)err)) { CFRelease(new_err); } } diff --git a/libsecurity_transform/lib/GroupTransform.h b/Security/libsecurity_transform/lib/GroupTransform.h similarity index 100% rename from libsecurity_transform/lib/GroupTransform.h rename to Security/libsecurity_transform/lib/GroupTransform.h diff --git a/libsecurity_transform/lib/LinkedList.cpp b/Security/libsecurity_transform/lib/LinkedList.cpp similarity index 100% rename from libsecurity_transform/lib/LinkedList.cpp rename to Security/libsecurity_transform/lib/LinkedList.cpp diff --git a/libsecurity_transform/lib/LinkedList.h b/Security/libsecurity_transform/lib/LinkedList.h similarity index 100% rename from libsecurity_transform/lib/LinkedList.h rename to Security/libsecurity_transform/lib/LinkedList.h diff --git a/libsecurity_transform/lib/Monitor.cpp b/Security/libsecurity_transform/lib/Monitor.cpp similarity index 100% rename from libsecurity_transform/lib/Monitor.cpp rename to Security/libsecurity_transform/lib/Monitor.cpp diff --git a/libsecurity_transform/lib/Monitor.h b/Security/libsecurity_transform/lib/Monitor.h similarity index 100% rename from libsecurity_transform/lib/Monitor.h rename to Security/libsecurity_transform/lib/Monitor.h diff --git a/libsecurity_transform/lib/NullTransform.cpp b/Security/libsecurity_transform/lib/NullTransform.cpp similarity index 100% rename from libsecurity_transform/lib/NullTransform.cpp rename to Security/libsecurity_transform/lib/NullTransform.cpp diff --git a/libsecurity_transform/lib/NullTransform.h b/Security/libsecurity_transform/lib/NullTransform.h similarity index 100% rename from libsecurity_transform/lib/NullTransform.h rename to Security/libsecurity_transform/lib/NullTransform.h diff --git a/libsecurity_transform/lib/SecCollectTransform.cpp b/Security/libsecurity_transform/lib/SecCollectTransform.cpp similarity index 99% rename from libsecurity_transform/lib/SecCollectTransform.cpp rename to Security/libsecurity_transform/lib/SecCollectTransform.cpp index de160bae..6cc471dc 100644 --- a/libsecurity_transform/lib/SecCollectTransform.cpp +++ b/Security/libsecurity_transform/lib/SecCollectTransform.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_transform/lib/SecCollectTransform.h b/Security/libsecurity_transform/lib/SecCollectTransform.h similarity index 96% rename from libsecurity_transform/lib/SecCollectTransform.h rename to Security/libsecurity_transform/lib/SecCollectTransform.h index 93660b23..593ec40c 100644 --- a/libsecurity_transform/lib/SecCollectTransform.h +++ b/Security/libsecurity_transform/lib/SecCollectTransform.h @@ -2,7 +2,7 @@ #define __SECCOLLECTTRANSFORM_H__ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_transform/lib/SecCustomTransform.cpp b/Security/libsecurity_transform/lib/SecCustomTransform.cpp similarity index 97% rename from libsecurity_transform/lib/SecCustomTransform.cpp rename to Security/libsecurity_transform/lib/SecCustomTransform.cpp index 7becb85c..e8a243e8 100644 --- a/libsecurity_transform/lib/SecCustomTransform.cpp +++ b/Security/libsecurity_transform/lib/SecCustomTransform.cpp @@ -1,12 +1,27 @@ /* - * SecCustomTransform.cpp - * libsecurity_transform - * - * Created by JOsborne on 2/18/10. - * Copyright 2010 Apple. All rights reserved. + * Copyright (c) 2010-2012,2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include "SecCustomTransform.h" #include "SecTransformValidator.h" @@ -1124,4 +1139,4 @@ CFTypeRef SecTransformPushbackAttribute(SecTransformImplementationRef ref, } return ref->pushback(attribute, value); -} \ No newline at end of file +} diff --git a/libsecurity_transform/lib/SecCustomTransform.h b/Security/libsecurity_transform/lib/SecCustomTransform.h similarity index 99% rename from libsecurity_transform/lib/SecCustomTransform.h rename to Security/libsecurity_transform/lib/SecCustomTransform.h index ff903733..95e807e6 100644 --- a/libsecurity_transform/lib/SecCustomTransform.h +++ b/Security/libsecurity_transform/lib/SecCustomTransform.h @@ -1,14 +1,15 @@ /* - * Copyright © 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -16,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@ */ @@ -54,7 +55,7 @@ CF_EXTERN_C_BEGIN // // CaesarXform.c // -// Copyright 2010 Apple Inc. All rights reserved. +// Copyright (c) 2010-2011,2014 Apple Inc. All Rights Reserved. // // diff --git a/libsecurity_transform/lib/SecDecodeTransform.h b/Security/libsecurity_transform/lib/SecDecodeTransform.h similarity index 97% rename from libsecurity_transform/lib/SecDecodeTransform.h rename to Security/libsecurity_transform/lib/SecDecodeTransform.h index b6c04504..45f823e0 100644 --- a/libsecurity_transform/lib/SecDecodeTransform.h +++ b/Security/libsecurity_transform/lib/SecDecodeTransform.h @@ -2,7 +2,7 @@ #define __SECDECODETRANSFORM_H__ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_transform/lib/SecDigestTransform.cpp b/Security/libsecurity_transform/lib/SecDigestTransform.cpp similarity index 100% rename from libsecurity_transform/lib/SecDigestTransform.cpp rename to Security/libsecurity_transform/lib/SecDigestTransform.cpp diff --git a/libsecurity_transform/lib/SecDigestTransform.h b/Security/libsecurity_transform/lib/SecDigestTransform.h similarity index 98% rename from libsecurity_transform/lib/SecDigestTransform.h rename to Security/libsecurity_transform/lib/SecDigestTransform.h index 50914e51..3c838c11 100644 --- a/libsecurity_transform/lib/SecDigestTransform.h +++ b/Security/libsecurity_transform/lib/SecDigestTransform.h @@ -3,7 +3,7 @@ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_transform/lib/SecEncodeTransform.h b/Security/libsecurity_transform/lib/SecEncodeTransform.h similarity index 98% rename from libsecurity_transform/lib/SecEncodeTransform.h rename to Security/libsecurity_transform/lib/SecEncodeTransform.h index 23a7d515..73963fbc 100644 --- a/libsecurity_transform/lib/SecEncodeTransform.h +++ b/Security/libsecurity_transform/lib/SecEncodeTransform.h @@ -2,7 +2,7 @@ #define __SECENCODETRANSFORM_H__ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_transform/lib/SecEncryptTransform.cpp b/Security/libsecurity_transform/lib/SecEncryptTransform.cpp similarity index 98% rename from libsecurity_transform/lib/SecEncryptTransform.cpp rename to Security/libsecurity_transform/lib/SecEncryptTransform.cpp index 0d5c4c5d..6779bd29 100644 --- a/libsecurity_transform/lib/SecEncryptTransform.cpp +++ b/Security/libsecurity_transform/lib/SecEncryptTransform.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_transform/lib/SecEncryptTransform.h b/Security/libsecurity_transform/lib/SecEncryptTransform.h similarity index 90% rename from libsecurity_transform/lib/SecEncryptTransform.h rename to Security/libsecurity_transform/lib/SecEncryptTransform.h index ed825f93..5e83138c 100644 --- a/libsecurity_transform/lib/SecEncryptTransform.h +++ b/Security/libsecurity_transform/lib/SecEncryptTransform.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2011,2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -51,12 +51,13 @@ extern "C" { /*! Indicates that PKCS7 padding will be used when encrypting or decrypting. */ extern CFStringRef kSecPaddingPKCS7Key; /*! Indicates that PKCS7 padding will be used when encrypting or decrypting. */ - extern CFStringRef kSecPaddingOAEPKey; + extern CFStringRef kSecPaddingOAEPKey + __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_NA); /*! Indicates that no mode will be used when encrypting or decrypting. */ extern CFStringRef kSecModeNoneKey; /*! Indicates that ECB mode will be used when encrypting or decrypting. */ extern CFStringRef kSecModeECBKey; - /*! Indicates that CBC mode will be used when encrypting or decrypting. */ + /*! Indicates that CBC mode will be used when encrypting or decrypting. */ extern CFStringRef kSecModeCBCKey; /*! Indicates that CFB mode will be used when encrypting or decrypting. */ extern CFStringRef kSecModeCFBKey; @@ -104,7 +105,8 @@ extern "C" { and a specific messages size is desired. If unset the minimum padding will be added. It is ignored when the padding mode is not OAEP. */ - extern CFStringRef kSecOAEPMessageLengthAttributeName; + extern CFStringRef kSecOAEPMessageLengthAttributeName + __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_NA); /*! @abstract Specifies the OAEP encoding paramaters @@ -113,7 +115,8 @@ extern "C" { If unset a zero length CFDataRef is used. It is ignored by non OAEP padding modes. */ - extern CFStringRef kSecOAEPEncodingParametersAttributeName; + extern CFStringRef kSecOAEPEncodingParametersAttributeName + __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_NA); /*! @abstract Specifies the OAEP MGF1 digest algorithm. @@ -121,7 +124,8 @@ extern "C" { This should be set to a digest algorithm when the padding is set to OAEP. If unset SHA1 is used. It is ifnored by non OAEP padding modes. */ - extern CFStringRef kSecOAEPMGF1DigestAlgorithmAttributeName; + extern CFStringRef kSecOAEPMGF1DigestAlgorithmAttributeName + __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_NA); /*! diff --git a/Security/libsecurity_transform/lib/SecExternalSourceTransform.cpp b/Security/libsecurity_transform/lib/SecExternalSourceTransform.cpp new file mode 100644 index 00000000..c9571c80 --- /dev/null +++ b/Security/libsecurity_transform/lib/SecExternalSourceTransform.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2010-2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include "SecTransform.h" +#include "SecCustomTransform.h" +#include "SecExternalSourceTransform.h" +#include + +CFStringRef external_source_name = CFSTR("com.apple.security.external_source"); + +static SecTransformInstanceBlock SecExternalSourceTransformCreateBlock(CFStringRef name, SecTransformRef newTransform, SecTransformImplementationRef ref) +{ + return Block_copy(^{ + SecTransformCustomSetAttribute(ref, kSecTransformInputAttributeName, kSecTransformMetaAttributeRequired, kCFBooleanFalse); + + SecTransformAttributeRef out = SecTranformCustomGetAttribute(ref, kSecTransformOutputAttributeName, kSecTransformMetaAttributeRef); + + SecTransformSetAttributeAction(ref, kSecTransformActionAttributeNotification, kSecTransformInputAttributeName, ^(SecTransformAttributeRef attribute, CFTypeRef value) { + SecTransformCustomSetAttribute(ref, out, kSecTransformMetaAttributeValue, value); + return (CFTypeRef)NULL; + }); + + return (CFErrorRef)NULL; + }); +} + +SecTransformRef SecExternalSourceTransformCreate(CFErrorRef* error) +{ + static dispatch_once_t once; + dispatch_once(&once, ^{ + SecTransformRegister(external_source_name, SecExternalSourceTransformCreateBlock, error); + }); + + return SecTransformCreate(external_source_name, error); +} diff --git a/libsecurity_transform/lib/SecExternalSourceTransform.h b/Security/libsecurity_transform/lib/SecExternalSourceTransform.h similarity index 97% rename from libsecurity_transform/lib/SecExternalSourceTransform.h rename to Security/libsecurity_transform/lib/SecExternalSourceTransform.h index fda6e049..181b347f 100644 --- a/libsecurity_transform/lib/SecExternalSourceTransform.h +++ b/Security/libsecurity_transform/lib/SecExternalSourceTransform.h @@ -2,7 +2,7 @@ #define __SECEXTERNALSOURCETRANSFORM_H__ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_transform/lib/SecGroupTransform.cpp b/Security/libsecurity_transform/lib/SecGroupTransform.cpp new file mode 100644 index 00000000..6beefdfe --- /dev/null +++ b/Security/libsecurity_transform/lib/SecGroupTransform.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010-2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include "SecGroupTransform.h" +#include "SecTransformInternal.h" +#include "GroupTransform.h" + +SecTransformRef SecGroupTransformFindLastTransform(SecGroupTransformRef groupTransform) +{ + GroupTransform* gt = (GroupTransform*) CoreFoundationHolder::ObjectFromCFType(groupTransform); + return gt->FindLastTransform(); +} + + + +SecTransformRef SecGroupTransformFindMonitor(SecGroupTransformRef groupTransform) +{ + GroupTransform* gt = (GroupTransform*) CoreFoundationHolder::ObjectFromCFType(groupTransform); + return gt->FindMonitor(); +} + + + +bool SecGroupTransformHasMember(SecGroupTransformRef groupTransform, SecTransformRef transform) +{ + GroupTransform* gt = (GroupTransform*) CoreFoundationHolder::ObjectFromCFType(groupTransform); + return gt->HasMember(transform); +} + + diff --git a/libsecurity_transform/lib/SecGroupTransform.h b/Security/libsecurity_transform/lib/SecGroupTransform.h similarity index 100% rename from libsecurity_transform/lib/SecGroupTransform.h rename to Security/libsecurity_transform/lib/SecGroupTransform.h diff --git a/libsecurity_transform/lib/SecMaskGenerationFunctionTransform.c b/Security/libsecurity_transform/lib/SecMaskGenerationFunctionTransform.c similarity index 88% rename from libsecurity_transform/lib/SecMaskGenerationFunctionTransform.c rename to Security/libsecurity_transform/lib/SecMaskGenerationFunctionTransform.c index cf10704b..8cbb1197 100644 --- a/libsecurity_transform/lib/SecMaskGenerationFunctionTransform.c +++ b/Security/libsecurity_transform/lib/SecMaskGenerationFunctionTransform.c @@ -1,10 +1,26 @@ -// -// SecMaskGenerationFunctionTransform.c -// libsecurity_transform -// -// Created by Josh Osborne on 10/6/11. -// Copyright 2011 Apple. All rights reserved. -// +/* + * Copyright (c) 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@ + */ + #include #include @@ -159,4 +175,4 @@ SecTransformRef SecCreateMaskGenerationFunctionTransform(CFStringRef hashType, i } return ret; -} \ No newline at end of file +} diff --git a/libsecurity_transform/lib/SecMaskGenerationFunctionTransform.h b/Security/libsecurity_transform/lib/SecMaskGenerationFunctionTransform.h similarity index 100% rename from libsecurity_transform/lib/SecMaskGenerationFunctionTransform.h rename to Security/libsecurity_transform/lib/SecMaskGenerationFunctionTransform.h diff --git a/libsecurity_transform/lib/SecNullTransform.cpp b/Security/libsecurity_transform/lib/SecNullTransform.cpp similarity index 100% rename from libsecurity_transform/lib/SecNullTransform.cpp rename to Security/libsecurity_transform/lib/SecNullTransform.cpp diff --git a/libsecurity_transform/lib/SecNullTransform.h b/Security/libsecurity_transform/lib/SecNullTransform.h similarity index 100% rename from libsecurity_transform/lib/SecNullTransform.h rename to Security/libsecurity_transform/lib/SecNullTransform.h diff --git a/libsecurity_transform/lib/SecReadTransform.h b/Security/libsecurity_transform/lib/SecReadTransform.h similarity index 100% rename from libsecurity_transform/lib/SecReadTransform.h rename to Security/libsecurity_transform/lib/SecReadTransform.h diff --git a/libsecurity_transform/lib/SecSignVerifyTransform.c b/Security/libsecurity_transform/lib/SecSignVerifyTransform.c similarity index 96% rename from libsecurity_transform/lib/SecSignVerifyTransform.c rename to Security/libsecurity_transform/lib/SecSignVerifyTransform.c index e44e798a..37fbcb25 100644 --- a/libsecurity_transform/lib/SecSignVerifyTransform.c +++ b/Security/libsecurity_transform/lib/SecSignVerifyTransform.c @@ -1,12 +1,27 @@ /* - * SecSignVerifyTransform.c - * libsecurity_transform - * - * Created by JOsborne on 3/11/10. - * Copyright 2010 Apple. All rights reserved. + * Copyright (c) 2010-2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include "SecSignVerifyTransform.h" #include "SecCustomTransform.h" #include "Utilities.h" diff --git a/libsecurity_transform/lib/SecSignVerifyTransform.h b/Security/libsecurity_transform/lib/SecSignVerifyTransform.h similarity index 98% rename from libsecurity_transform/lib/SecSignVerifyTransform.h rename to Security/libsecurity_transform/lib/SecSignVerifyTransform.h index 414a72f4..509a4c74 100644 --- a/libsecurity_transform/lib/SecSignVerifyTransform.h +++ b/Security/libsecurity_transform/lib/SecSignVerifyTransform.h @@ -3,7 +3,7 @@ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_transform/lib/SecTransform.cpp b/Security/libsecurity_transform/lib/SecTransform.cpp similarity index 94% rename from libsecurity_transform/lib/SecTransform.cpp rename to Security/libsecurity_transform/lib/SecTransform.cpp index cf7b04b3..958d0974 100644 --- a/libsecurity_transform/lib/SecTransform.cpp +++ b/Security/libsecurity_transform/lib/SecTransform.cpp @@ -20,16 +20,16 @@ const CFStringRef kSecTransformTransformName = CFSTR("NAME"); //const CFStringRef kSecTransformErrorTransform = CFSTR("TRANSFORM"); const CFStringRef kSecTransformErrorDomain = CFSTR("com.apple.security.transforms.error"); const CFStringRef kSecTransformAbortAttributeName = CFSTR("ABORT"); - + CFErrorRef SecTransformConnectTransformsInternal(SecGroupTransformRef groupRef, - SecTransformRef sourceTransformRef, + SecTransformRef sourceTransformRef, CFStringRef sourceAttributeName, - SecTransformRef destinationTransformRef, + SecTransformRef destinationTransformRef, CFStringRef destinationAttributeName) { Transform* destination = (Transform*) CoreFoundationHolder::ObjectFromCFType(destinationTransformRef); Transform* source = (Transform*) CoreFoundationHolder::ObjectFromCFType(sourceTransformRef); - + GroupTransform* group = (GroupTransform*) CoreFoundationHolder::ObjectFromCFType(groupRef); CFErrorRef temp = source->Connect(group, destination, destinationAttributeName, sourceAttributeName); return temp; @@ -62,31 +62,31 @@ SecGroupTransformRef SecTransformConnectTransforms(SecTransformRef sourceTransfo { *error = CreateSecTransformErrorRef(kSecTransformErrorMissingParameter, "Group must not be NULL."); } - + return NULL; } - + if (destinationAttributeName == NULL) { destinationAttributeName = kSecTransformInputAttributeName; } - + if (sourceAttributeName == NULL) { sourceAttributeName = kSecTransformOutputAttributeName; } - + GroupTransform* gtr = (GroupTransform*) CoreFoundationHolder::ObjectFromCFType(group); - - CFErrorRef temp = SecTransformConnectTransformsInternal(gtr->GetCFObject(), + + CFErrorRef temp = SecTransformConnectTransformsInternal(gtr->GetCFObject(), sourceTransformRef, sourceAttributeName, destinationTransformRef, destinationAttributeName); - + if (error) { *error = temp; } - + if (temp) // an error happened? { return NULL; @@ -96,7 +96,7 @@ SecGroupTransformRef SecTransformConnectTransforms(SecTransformRef sourceTransfo return group; } } - + Boolean SecTransformSetAttribute(SecTransformRef transformRef, @@ -106,14 +106,14 @@ Boolean SecTransformSetAttribute(SecTransformRef transformRef, { Boolean result = false; // Guilty until proven Transform* transform = (Transform*) CoreFoundationHolder::ObjectFromCFType(transformRef); - + if (CFGetTypeID(transformRef) == GroupTransform::GetCFTypeID() && !transform->getAH(key, false)) { if (error) { *error = CreateSecTransformErrorRef(kSecTransformOperationNotSupportedOnGroup, "SecTransformSetAttribute on non-exported attribute: %@ (exported attributes are: %@).", key, transform->GetAllAH()); } - + return result; } @@ -125,10 +125,10 @@ Boolean SecTransformSetAttribute(SecTransformRef transformRef, // XXX: "a parameter"? It has one: NULL. What it requires is a non-NULL value. *error = CreateSecTransformErrorRef(kSecTransformInvalidArgument, "ABORT requires a parameter."); } - + return result; } - + CFErrorRef temp = transform->ExternalSetAttribute(key, value); result = (temp == NULL); if (error) @@ -165,12 +165,14 @@ CFTypeRef SecTransformGetAttribute(SecTransformRef transformRef, } - +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" static inline GroupTransform* MakeGroupTransformFromTransformRef(SecTransformRef tr) { GroupTransform* gt = (GroupTransform*) CoreFoundationHolder::ObjectFromCFType(tr); return gt; } +#pragma clang diagnostic pop static CFTypeRef InternalSecTransformExecute(SecTransformRef transformRef, CFErrorRef* errorRef, @@ -179,9 +181,9 @@ static CFTypeRef InternalSecTransformExecute(SecTransformRef transformRef, { if (NULL == transformRef || (deliveryBlock && !deliveryQueue)) { - CFErrorRef localError = CFErrorCreate(kCFAllocatorDefault, kSecTransformErrorDomain, + CFErrorRef localError = CFErrorCreate(kCFAllocatorDefault, kSecTransformErrorDomain, kSecTransformInvalidArgument, NULL); - + if (NULL != errorRef) { *errorRef = localError; @@ -190,17 +192,17 @@ static CFTypeRef InternalSecTransformExecute(SecTransformRef transformRef, { CFRelease(localError); } - + return (CFTypeRef)NULL; } - + // if our transform is a group, connect to its first member instead if (CFGetTypeID(transformRef) == GroupTransform::GetCFTypeID()) { GroupTransform* gtsrc = (GroupTransform*) CoreFoundationHolder::ObjectFromCFType(transformRef); transformRef = gtsrc->GetAnyMember(); } - + Transform* transform = (Transform*) CoreFoundationHolder::ObjectFromCFType(transformRef); return transform->Execute(deliveryQueue, deliveryBlock, errorRef); } @@ -215,9 +217,9 @@ CFTypeRef SecTransformExecute(SecTransformRef transformRef, CFErrorRef* errorRef } return NULL; } - + Transform* transform = (Transform*) CoreFoundationHolder::ObjectFromCFType(transformRef); - + // transform->Execute will check this, but by then we have attached a collector which causes all manner of issues. if (transform->mIsActive) { @@ -227,13 +229,13 @@ CFTypeRef SecTransformExecute(SecTransformRef transformRef, CFErrorRef* errorRef } return NULL; } - + SecTransformRef collectTransform = transforms_assume(SecCreateCollectTransform(errorRef)); SecGroupTransformRef theGroup = NULL; Boolean releaseTheGroup = false; GroupTransform* myGroup = NULL; Boolean needConnection = true; - + // Sniff the type of the transformRef to see if it is a group if (SecGroupTransformGetTypeID() == CFGetTypeID(transformRef)) { @@ -242,9 +244,9 @@ CFTypeRef SecTransformExecute(SecTransformRef transformRef, CFErrorRef* errorRef else { // Ok TransformRef is a TransformRef so get's it group - + myGroup = transform->mGroup; - + if (NULL == myGroup) { theGroup = SecTransformCreateGroupTransform(); @@ -254,46 +256,46 @@ CFTypeRef SecTransformExecute(SecTransformRef transformRef, CFErrorRef* errorRef { *errorRef = GetNoMemoryErrorAndRetain(); } - + return (CFTypeRef)NULL; - + } - - releaseTheGroup = true; - - SecGroupTransformRef connectResult = - SecTransformConnectTransforms(transformRef, + + releaseTheGroup = true; + + SecGroupTransformRef connectResult = + SecTransformConnectTransforms(transformRef, kSecTransformOutputAttributeName, - collectTransform, + collectTransform, kSecTransformInputAttributeName, theGroup, errorRef); - + if (NULL == connectResult) { return (CFTypeRef)NULL; } - + needConnection = false; - + } - else + else { theGroup = (SecGroupTransformRef)myGroup->GetCFObject(); } } - + if (NULL == theGroup || (SecGroupTransformGetTypeID() != CFGetTypeID(theGroup))) { if (NULL != errorRef) { *errorRef = GetNoMemoryErrorAndRetain(); } - + return (CFTypeRef)NULL; } - - + + if (needConnection) { // Connect the collectTransform to the group @@ -304,19 +306,19 @@ CFTypeRef SecTransformExecute(SecTransformRef transformRef, CFErrorRef* errorRef { *errorRef = GetNoMemoryErrorAndRetain(); } - + return (CFTypeRef)NULL; } - - SecTransformRef outputTransform = myGroup->FindLastTransform(); - - SecGroupTransformRef connectResult = - SecTransformConnectTransforms(outputTransform, + + SecTransformRef outputTransform = myGroup->FindLastTransform(); + + SecGroupTransformRef connectResult = + SecTransformConnectTransforms(outputTransform, kSecTransformOutputAttributeName, - collectTransform, + collectTransform, kSecTransformInputAttributeName, myGroup->GetCFObject(), errorRef); - + if (NULL == connectResult) { CFRelease(collectTransform); @@ -327,7 +329,7 @@ CFTypeRef SecTransformExecute(SecTransformRef transformRef, CFErrorRef* errorRef return (CFTypeRef)NULL; } } - + __block CFTypeRef myResult = NULL; dispatch_semaphore_t mySem = dispatch_semaphore_create(0L); dispatch_queue_t myQueue = dispatch_queue_create("com.apple.security.sectransfrom.SecTransformExecute", NULL); @@ -340,64 +342,64 @@ CFTypeRef SecTransformExecute(SecTransformRef transformRef, CFErrorRef* errorRef CFRetain(error); *errorRef = error; } - + if (NULL != myResult) { CFRelease(myResult); myResult = NULL; } } - + if (NULL != message) { myResult = message; CFRetain(myResult); } - + if (isFinal) { dispatch_semaphore_signal(mySem); } }; - + SecTransformExecuteAsync(theGroup, myQueue, myBlock); dispatch_semaphore_wait(mySem, DISPATCH_TIME_FOREVER); dispatch_release(mySem); dispatch_release(myQueue); - + if (releaseTheGroup) { CFRelease(theGroup); theGroup = NULL; } CFRelease(collectTransform); - - return myResult; + + return myResult; } void SecTransformExecuteAsync(SecTransformRef transformRef, dispatch_queue_t deliveryQueue, - SecMessageBlock deliveryBlock) + SecMessageBlock deliveryBlock) { CFErrorRef localError = NULL; InternalSecTransformExecute(transformRef, &localError, deliveryQueue, deliveryBlock); - + // if we got an error (usually a transform startup error), we must deliver it if (localError != NULL) { // The monitor treats a NULL queue as running on it's own queue, which from an appication's point of view is // the same as a default global queue. Chances are there is no monitor at this point, so it is best to just use the // global queue for this. - dispatch_queue_t effectiveQueue = deliveryQueue ? deliveryQueue : dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL); + dispatch_queue_t effectiveQueue = deliveryQueue ? deliveryQueue : dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL); dispatch_async(effectiveQueue, ^{ deliveryBlock(NULL, localError, true); }); } } -CFDictionaryRef SecTransformCopyExternalRepresentation(SecTransformRef transformRef) -{ - +CFDictionaryRef SecTransformCopyExternalRepresentation(SecTransformRef transformRef) +{ + Transform* tr = (Transform*) CoreFoundationHolder::ObjectFromCFType(transformRef); return tr->Externalize(NULL); } @@ -414,13 +416,13 @@ CFStringRef SecTransformDotForDebugging(SecTransformRef transformRef) SecTransformRef SecTransformCreateFromExternalRepresentation( CFDictionaryRef dictionary, - CFErrorRef *error) + CFErrorRef *error) { // The incoming dictionary consists of a list of transforms and // a list of connections. We start by making the individual // transforms and storing them in a dictionary so that we can // efficiently make connections - + CFArrayRef transforms = (CFArrayRef) CFDictionaryGetValue(dictionary, EXTERN_TRANSFORM_TRANSFORM_ARRAY); if (transforms == NULL) { @@ -428,7 +430,7 @@ SecTransformRef SecTransformCreateFromExternalRepresentation( *error = CreateSecTransformErrorRef(kSecTransformErrorInvalidInputDictionary, "%@ is missing from the dictionary. The dictionary is malformed.", EXTERN_TRANSFORM_TRANSFORM_ARRAY); return NULL; } - + CFArrayRef connections = (CFArrayRef) CFDictionaryGetValue(dictionary, EXTERN_TRANSFORM_CONNECTION_ARRAY); if (connections == NULL) { @@ -439,54 +441,54 @@ SecTransformRef SecTransformCreateFromExternalRepresentation( CFMutableDictionaryRef transformHolder = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFTypeRefHolder _(transformHolder); - + CFIndex numTransforms = CFArrayGetCount(transforms); CFIndex n; - + SecTransformRef aTransform; - + for (n = 0; n < numTransforms; ++n) { // get the basic info we need CFDictionaryRef xTransform = (CFDictionaryRef) CFArrayGetValueAtIndex(transforms, n); - + CFStringRef xName = (CFStringRef) CFDictionaryGetValue(xTransform, EXTERN_TRANSFORM_NAME); - + CFStringRef xType = (CFStringRef) CFDictionaryGetValue(xTransform, EXTERN_TRANSFORM_TYPE); - + // reconstruct the transform aTransform = TransformFactory::MakeTransformWithType(xType, error); SecTransformSetAttribute(aTransform, kSecTransformTransformName, xName, NULL); - + // restore the transform state Transform* tr = (Transform*) CoreFoundationHolder::ObjectFromCFType(aTransform); - tr->RestoreState((CFDictionaryRef) CFDictionaryGetValue(xTransform, EXTERN_TRANSFORM_STATE)); + tr->RestoreState((CFDictionaryRef) CFDictionaryGetValue(xTransform, EXTERN_TRANSFORM_STATE)); tr->SetCustomExternalData((CFDictionaryRef) CFDictionaryGetValue(xTransform, EXTERN_TRANSFORM_CUSTOM_EXPORTS_DICTIONARY)); - + CFIndex cnt = CFDictionaryGetCount(transformHolder); - + // add the transform to the dictionary CFDictionaryAddValue(transformHolder, xName, aTransform); - - if (CFDictionaryGetCount(transformHolder) <= cnt) + + if (CFDictionaryGetCount(transformHolder) <= cnt) { - if (error) + if (error) { - *error = CreateSecTransformErrorRef(kSecTransformErrorInvalidInputDictionary, + *error = CreateSecTransformErrorRef(kSecTransformErrorInvalidInputDictionary, "Out of memory, or damaged input dictonary (duplicate label %@?)", xName); } return NULL; } } - + CFIndex numConnections = CFArrayGetCount(connections); if (numConnections == 0) { return aTransform; } - + SecGroupTransformRef gt = SecTransformCreateGroupTransform(); - + for (n = 0; n < numConnections; ++n) { CFDictionaryRef connection = (CFDictionaryRef) CFArrayGetValueAtIndex(connections, n); @@ -494,7 +496,7 @@ SecTransformRef SecTransformCreateFromExternalRepresentation( CFStringRef fromAttribute = (CFStringRef) CFDictionaryGetValue(connection, EXTERN_TRANSFORM_FROM_ATTRIBUTE); CFStringRef toTransformName = (CFStringRef) CFDictionaryGetValue(connection, EXTERN_TRANSFORM_TO_NAME); CFStringRef toAttribute = (CFStringRef) CFDictionaryGetValue(connection, EXTERN_TRANSFORM_TO_ATTRIBUTE); - + SecTransformRef fromTransform = (SecTransformRef) CFDictionaryGetValue(transformHolder, fromTransformName); if (!fromTransform) { if (error) { @@ -509,10 +511,10 @@ SecTransformRef SecTransformCreateFromExternalRepresentation( } return NULL; } - + aTransform = SecTransformConnectTransforms(fromTransform, fromAttribute, toTransform, toAttribute, gt, error); } - + return gt; } @@ -522,7 +524,7 @@ SecTransformRef SecTransformFindByName(SecTransformRef transform, CFStringRef na { Transform *t = (Transform*)CoreFoundationHolder::ObjectFromCFType(transform); GroupTransform *g = t->GetRootGroup(); - + if (g) { return g->FindByName(name); } else { diff --git a/libsecurity_transform/lib/SecTransform.h b/Security/libsecurity_transform/lib/SecTransform.h similarity index 99% rename from libsecurity_transform/lib/SecTransform.h rename to Security/libsecurity_transform/lib/SecTransform.h index 48891a3d..22574456 100644 --- a/libsecurity_transform/lib/SecTransform.h +++ b/Security/libsecurity_transform/lib/SecTransform.h @@ -1,5 +1,5 @@ /* - * Copyright © 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_transform/lib/SecTransformInternal.h b/Security/libsecurity_transform/lib/SecTransformInternal.h similarity index 100% rename from libsecurity_transform/lib/SecTransformInternal.h rename to Security/libsecurity_transform/lib/SecTransformInternal.h diff --git a/libsecurity_transform/lib/SecTransformReadTransform.cpp b/Security/libsecurity_transform/lib/SecTransformReadTransform.cpp similarity index 100% rename from libsecurity_transform/lib/SecTransformReadTransform.cpp rename to Security/libsecurity_transform/lib/SecTransformReadTransform.cpp diff --git a/libsecurity_transform/lib/SecTransformReadTransform.h b/Security/libsecurity_transform/lib/SecTransformReadTransform.h similarity index 97% rename from libsecurity_transform/lib/SecTransformReadTransform.h rename to Security/libsecurity_transform/lib/SecTransformReadTransform.h index 7128238b..e18a5db6 100644 --- a/libsecurity_transform/lib/SecTransformReadTransform.h +++ b/Security/libsecurity_transform/lib/SecTransformReadTransform.h @@ -1,5 +1,5 @@ /* - * Copyright © 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_transform/lib/SecTransformValidator.h b/Security/libsecurity_transform/lib/SecTransformValidator.h similarity index 96% rename from libsecurity_transform/lib/SecTransformValidator.h rename to Security/libsecurity_transform/lib/SecTransformValidator.h index f2bac81f..2d06bed6 100644 --- a/libsecurity_transform/lib/SecTransformValidator.h +++ b/Security/libsecurity_transform/lib/SecTransformValidator.h @@ -1,5 +1,5 @@ /* - * Copyright © 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_transform/lib/SingleShotSource.cpp b/Security/libsecurity_transform/lib/SingleShotSource.cpp similarity index 100% rename from libsecurity_transform/lib/SingleShotSource.cpp rename to Security/libsecurity_transform/lib/SingleShotSource.cpp diff --git a/libsecurity_transform/lib/SingleShotSource.h b/Security/libsecurity_transform/lib/SingleShotSource.h similarity index 100% rename from libsecurity_transform/lib/SingleShotSource.h rename to Security/libsecurity_transform/lib/SingleShotSource.h diff --git a/libsecurity_transform/lib/Source.cpp b/Security/libsecurity_transform/lib/Source.cpp similarity index 100% rename from libsecurity_transform/lib/Source.cpp rename to Security/libsecurity_transform/lib/Source.cpp diff --git a/libsecurity_transform/lib/Source.h b/Security/libsecurity_transform/lib/Source.h similarity index 100% rename from libsecurity_transform/lib/Source.h rename to Security/libsecurity_transform/lib/Source.h diff --git a/libsecurity_transform/lib/StreamSource.cpp b/Security/libsecurity_transform/lib/StreamSource.cpp similarity index 100% rename from libsecurity_transform/lib/StreamSource.cpp rename to Security/libsecurity_transform/lib/StreamSource.cpp diff --git a/libsecurity_transform/lib/StreamSource.h b/Security/libsecurity_transform/lib/StreamSource.h similarity index 100% rename from libsecurity_transform/lib/StreamSource.h rename to Security/libsecurity_transform/lib/StreamSource.h diff --git a/libsecurity_transform/lib/Transform.cpp b/Security/libsecurity_transform/lib/Transform.cpp similarity index 99% rename from libsecurity_transform/lib/Transform.cpp rename to Security/libsecurity_transform/lib/Transform.cpp index 5ec84b8e..20db57fa 100644 --- a/libsecurity_transform/lib/Transform.cpp +++ b/Security/libsecurity_transform/lib/Transform.cpp @@ -619,7 +619,7 @@ void Transform::AbortJustThisTransform(CFErrorRef abortErr) Boolean wasActive = mIsActive; - if (OSAtomicCompareAndSwapPtr(NULL, abortErr, (void**)&mAbortError)) { + if (OSAtomicCompareAndSwapPtr(NULL, (void *)abortErr, (void**)&mAbortError)) { // send an abort message to the attribute so that it can shut down // note that this bypasses the normal processes. The message sent is a notification // that things aren't working well any more, the transform cannot make any other assumption. diff --git a/libsecurity_transform/lib/Transform.h b/Security/libsecurity_transform/lib/Transform.h similarity index 100% rename from libsecurity_transform/lib/Transform.h rename to Security/libsecurity_transform/lib/Transform.h diff --git a/libsecurity_transform/lib/TransformFactory.cpp b/Security/libsecurity_transform/lib/TransformFactory.cpp similarity index 100% rename from libsecurity_transform/lib/TransformFactory.cpp rename to Security/libsecurity_transform/lib/TransformFactory.cpp diff --git a/libsecurity_transform/lib/TransformFactory.h b/Security/libsecurity_transform/lib/TransformFactory.h similarity index 100% rename from libsecurity_transform/lib/TransformFactory.h rename to Security/libsecurity_transform/lib/TransformFactory.h diff --git a/libsecurity_transform/lib/Utilities.cpp b/Security/libsecurity_transform/lib/Utilities.cpp similarity index 75% rename from libsecurity_transform/lib/Utilities.cpp rename to Security/libsecurity_transform/lib/Utilities.cpp index 094cc334..2d396a56 100644 --- a/libsecurity_transform/lib/Utilities.cpp +++ b/Security/libsecurity_transform/lib/Utilities.cpp @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include "Utilities.h" #include "SecTransform.h" #include diff --git a/libsecurity_transform/lib/Utilities.h b/Security/libsecurity_transform/lib/Utilities.h similarity index 100% rename from libsecurity_transform/lib/Utilities.h rename to Security/libsecurity_transform/lib/Utilities.h diff --git a/libsecurity_transform/lib/c++utils.cpp b/Security/libsecurity_transform/lib/c++utils.cpp similarity index 100% rename from libsecurity_transform/lib/c++utils.cpp rename to Security/libsecurity_transform/lib/c++utils.cpp diff --git a/libsecurity_transform/lib/c++utils.h b/Security/libsecurity_transform/lib/c++utils.h similarity index 100% rename from libsecurity_transform/lib/c++utils.h rename to Security/libsecurity_transform/lib/c++utils.h diff --git a/libsecurity_transform/lib/misc.c b/Security/libsecurity_transform/lib/misc.c similarity index 81% rename from libsecurity_transform/lib/misc.c rename to Security/libsecurity_transform/lib/misc.c index 91a9f730..54ac7848 100644 --- a/libsecurity_transform/lib/misc.c +++ b/Security/libsecurity_transform/lib/misc.c @@ -1,12 +1,27 @@ /* - * misc.c - * libsecurity_transform - * - * Created by JOsborne on 3/14/10. - * Copyright 2010 Apple. All rights reserved. + * Copyright (c) 2010-2012,2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include "misc.h" @@ -143,4 +158,4 @@ void graphviz(FILE *f, SecTransformRef tr) { CFfprintf(f, "}\n"); CFfprintf(f, "\n/*\n%@\n/*\n", d); -} \ No newline at end of file +} diff --git a/Security/libsecurity_transform/lib/misc.h b/Security/libsecurity_transform/lib/misc.h new file mode 100644 index 00000000..9750393d --- /dev/null +++ b/Security/libsecurity_transform/lib/misc.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010-2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef __INCLUDED_TRANSFORMS_MISC_H__ +#define __INCLUDED_TRANSFORMS_MISC_H__ + +#include +#include "SecTransform.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + CFErrorRef fancy_error(CFStringRef domain, CFIndex code, CFStringRef description); + extern void graphviz(FILE *f, SecTransformRef tr); + extern void CFfprintf(FILE *f, const char *format, ...); + CFErrorRef GetNoMemoryError(); + CFErrorRef GetNoMemoryErrorAndRetain(); + void CFSafeRelease(CFTypeRef object); + + // NOTE: the return may or allocate a fair bit more space then it needs. + // Use it for short lived conversions (or strdup the result). + extern char *utf8(CFStringRef s); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libsecurity_transform/lib/security_transform.exp b/Security/libsecurity_transform/lib/security_transform.exp similarity index 100% rename from libsecurity_transform/lib/security_transform.exp rename to Security/libsecurity_transform/lib/security_transform.exp diff --git a/Security/libsecurity_transform/libsecurity_transform.xcodeproj/project.pbxproj b/Security/libsecurity_transform/libsecurity_transform.xcodeproj/project.pbxproj new file mode 100644 index 00000000..2cb2e6a3 --- /dev/null +++ b/Security/libsecurity_transform/libsecurity_transform.xcodeproj/project.pbxproj @@ -0,0 +1,869 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 18C5A961148442000010EF34 /* libsecurity_transform.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CA1FEBE052A3C8100F22E42 /* libsecurity_transform.a */; }; + 18C5A964148443F00010EF34 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18C5A963148443F00010EF34 /* SenTestingKit.framework */; }; + 18C5A9661484440D0010EF34 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18C5A9651484440D0010EF34 /* Foundation.framework */; }; + 4C010B9B121AE9960094CB72 /* speed-test.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4C010B9A121AE9960094CB72 /* speed-test.mm */; }; + 4C010BBB121AECF10094CB72 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D16D6FB114EA1000096BD75 /* Security.framework */; }; + 4C010C52121B00350094CB72 /* SecExternalSourceTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C010C4B121AFCA70094CB72 /* SecExternalSourceTransform.h */; }; + 4C010C53121B00440094CB72 /* SecExternalSourceTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C010C4C121AFCA70094CB72 /* SecExternalSourceTransform.cpp */; }; + 4C0113511468693100E4F866 /* SecMaskGenerationFunctionTransform.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C01134F1468693100E4F866 /* SecMaskGenerationFunctionTransform.c */; }; + 4C0113521468693100E4F866 /* SecMaskGenerationFunctionTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0113501468693100E4F866 /* SecMaskGenerationFunctionTransform.h */; settings = {ATTRIBUTES = (); }; }; + 4C01135C14686F2600E4F866 /* NSData+HexString.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C01135A14686F2600E4F866 /* NSData+HexString.m */; }; + 4C27A37814F2DCB4007FCA66 /* CEncryptDecrypt.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C27A37714F2DCB4007FCA66 /* CEncryptDecrypt.c */; }; + 4C6E5966116D4E3E00A70E8F /* misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6E5964116D4E3E00A70E8F /* misc.c */; }; + 4C6E5967116D4E3E00A70E8F /* misc.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6E5965116D4E3E00A70E8F /* misc.h */; }; + 4C73822D112DCC4800EA003B /* SecCustomTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C73822B112DCC4800EA003B /* SecCustomTransform.h */; settings = {ATTRIBUTES = (); }; }; + 4C73822E112DCC4800EA003B /* SecCustomTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C73822C112DCC4800EA003B /* SecCustomTransform.cpp */; }; + 4C8174341133031E007F84D6 /* libsecurity_transform.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CA1FEBE052A3C8100F22E42 /* libsecurity_transform.a */; }; + 4CB89E62124D5667004DEC20 /* SecTransformValidator.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CB89E61124D5667004DEC20 /* SecTransformValidator.h */; settings = {ATTRIBUTES = (); }; }; + 4CC4A8B21264D22300075C8F /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D16D6FB114EA1000096BD75 /* Security.framework */; }; + 4CD6A669113F41990094F287 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CD6A668113F41990094F287 /* libz.dylib */; }; + 4CD87F501130A49400A98C5E /* 100-sha2.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CD87F3D1130A34700A98C5E /* 100-sha2.m */; }; + 4CDF6DCC113C4E9E00C64234 /* EncodeDecodeTransforms.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CDF6DC9113C4E9E00C64234 /* EncodeDecodeTransforms.c */; }; + 4CDF6DCD113C4E9E00C64234 /* SecDecodeTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CDF6DCA113C4E9E00C64234 /* SecDecodeTransform.h */; settings = {ATTRIBUTES = (); }; }; + 4CDF6DCE113C4E9E00C64234 /* SecEncodeTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CDF6DCB113C4E9E00C64234 /* SecEncodeTransform.h */; settings = {ATTRIBUTES = (); }; }; + 5DCAD5B711F0E099003F2E7A /* SecCollectTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5DCAD5B511F0E099003F2E7A /* SecCollectTransform.cpp */; }; + 5DCAD5B811F0E099003F2E7A /* SecCollectTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DCAD5B611F0E099003F2E7A /* SecCollectTransform.h */; }; + 5DD2E91E114E9044007429E7 /* EncryptTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DD2E91C114E9044007429E7 /* EncryptTransform.h */; }; + 5DD2E91F114E9044007429E7 /* EncryptTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5DD2E91D114E9044007429E7 /* EncryptTransform.cpp */; }; + 5DD2E925114E9094007429E7 /* EncryptTransformUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DD2E923114E9094007429E7 /* EncryptTransformUtilities.h */; }; + 5DD2E926114E9094007429E7 /* EncryptTransformUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5DD2E924114E9094007429E7 /* EncryptTransformUtilities.cpp */; }; + 5DD2E929114E90E2007429E7 /* SecEncryptTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DD2E927114E90E2007429E7 /* SecEncryptTransform.h */; settings = {ATTRIBUTES = (); }; }; + 5DD2E92A114E90E2007429E7 /* SecEncryptTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5DD2E928114E90E2007429E7 /* SecEncryptTransform.cpp */; }; + 5DD2E938114E91CC007429E7 /* SecSignVerifyTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DD2E936114E91CC007429E7 /* SecSignVerifyTransform.h */; settings = {ATTRIBUTES = (); }; }; + 5DD2E939114E91CC007429E7 /* SecSignVerifyTransform.c in Sources */ = {isa = PBXBuildFile; fileRef = 5DD2E937114E91CC007429E7 /* SecSignVerifyTransform.c */; }; + 5DD2E9B5114E986D007429E7 /* custom.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5DD2E96E114E95B1007429E7 /* custom.mm */; }; + AA068646138C420C0059E73E /* SecReadTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA068645138C420C0059E73E /* SecReadTransform.h */; settings = {ATTRIBUTES = (); }; }; + AA068EDF1174AB350002E9E0 /* GroupTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA068EDB1174AB350002E9E0 /* GroupTransform.cpp */; }; + AA068EE01174AB350002E9E0 /* GroupTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA068EDC1174AB350002E9E0 /* GroupTransform.h */; }; + AA068EE11174AB350002E9E0 /* SecGroupTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA068EDD1174AB350002E9E0 /* SecGroupTransform.cpp */; }; + AA068EE21174AB350002E9E0 /* SecGroupTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA068EDE1174AB350002E9E0 /* SecGroupTransform.h */; }; + AA068EEE1174ABB20002E9E0 /* SecTransformInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = AA068EED1174ABB20002E9E0 /* SecTransformInternal.h */; settings = {ATTRIBUTES = (); }; }; + AA957FCB122C571E00181BE1 /* SecTransformReadTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA957FCA122C571E00181BE1 /* SecTransformReadTransform.h */; settings = {ATTRIBUTES = (); }; }; + AA957FD5122C57AF00181BE1 /* SecTransformReadTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA957FD4122C57AF00181BE1 /* SecTransformReadTransform.cpp */; }; + AA9781A91175475500699E38 /* c++utils.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9781A71175475500699E38 /* c++utils.h */; }; + AA9781AA1175475500699E38 /* c++utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9781A81175475500699E38 /* c++utils.cpp */; }; + AA9E1C221117966F00380F0D /* CoreFoundationBasics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C051117966F00380F0D /* CoreFoundationBasics.cpp */; }; + AA9E1C231117966F00380F0D /* CoreFoundationBasics.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C061117966F00380F0D /* CoreFoundationBasics.h */; }; + AA9E1C241117966F00380F0D /* Digest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C071117966F00380F0D /* Digest.cpp */; }; + AA9E1C251117966F00380F0D /* Digest.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C081117966F00380F0D /* Digest.h */; }; + AA9E1C261117966F00380F0D /* LinkedList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C091117966F00380F0D /* LinkedList.cpp */; }; + AA9E1C271117966F00380F0D /* LinkedList.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C0A1117966F00380F0D /* LinkedList.h */; }; + AA9E1C281117966F00380F0D /* Monitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C0B1117966F00380F0D /* Monitor.cpp */; }; + AA9E1C291117966F00380F0D /* Monitor.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C0C1117966F00380F0D /* Monitor.h */; }; + AA9E1C2A1117966F00380F0D /* NullTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C0D1117966F00380F0D /* NullTransform.cpp */; }; + AA9E1C2B1117966F00380F0D /* NullTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C0E1117966F00380F0D /* NullTransform.h */; }; + AA9E1C2C1117966F00380F0D /* SecDigestTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C0F1117966F00380F0D /* SecDigestTransform.cpp */; }; + AA9E1C2D1117966F00380F0D /* SecDigestTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C101117966F00380F0D /* SecDigestTransform.h */; settings = {ATTRIBUTES = (); }; }; + AA9E1C2E1117966F00380F0D /* SecNullTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C111117966F00380F0D /* SecNullTransform.cpp */; }; + AA9E1C2F1117966F00380F0D /* SecNullTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C121117966F00380F0D /* SecNullTransform.h */; settings = {ATTRIBUTES = (); }; }; + AA9E1C301117966F00380F0D /* SecTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C131117966F00380F0D /* SecTransform.cpp */; }; + AA9E1C311117966F00380F0D /* SecTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C141117966F00380F0D /* SecTransform.h */; settings = {ATTRIBUTES = (); }; }; + AA9E1C331117966F00380F0D /* SingleShotSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C161117966F00380F0D /* SingleShotSource.cpp */; }; + AA9E1C341117966F00380F0D /* SingleShotSource.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C171117966F00380F0D /* SingleShotSource.h */; }; + AA9E1C351117966F00380F0D /* Source.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C181117966F00380F0D /* Source.cpp */; }; + AA9E1C361117966F00380F0D /* Source.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C191117966F00380F0D /* Source.h */; }; + AA9E1C371117966F00380F0D /* StreamSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C1A1117966F00380F0D /* StreamSource.cpp */; }; + AA9E1C381117966F00380F0D /* StreamSource.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C1B1117966F00380F0D /* StreamSource.h */; }; + AA9E1C391117966F00380F0D /* Transform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C1C1117966F00380F0D /* Transform.cpp */; }; + AA9E1C3A1117966F00380F0D /* Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C1D1117966F00380F0D /* Transform.h */; }; + AA9E1C3B1117966F00380F0D /* TransformFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C1E1117966F00380F0D /* TransformFactory.cpp */; }; + AA9E1C3C1117966F00380F0D /* TransformFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C1F1117966F00380F0D /* TransformFactory.h */; }; + AA9E1C3D1117966F00380F0D /* Utilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C201117966F00380F0D /* Utilities.cpp */; }; + AA9E1C3E1117966F00380F0D /* Utilities.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C211117966F00380F0D /* Utilities.h */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 4C010B90121AE9070094CB72 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_transform; + }; + 4C817255112F030F007F84D6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_transform; + }; + 4CD87FFF1131E0F500A98C5E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_transform; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 18BBC7391471F6DF00F2B224 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 18BBC73A1471F6DF00F2B224 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 18BBC73B1471F6DF00F2B224 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 18BBC73C1471F6DF00F2B224 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 18BBC73D1471F6DF00F2B224 /* security.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = security.xcconfig; sourceTree = ""; }; + 18C5A963148443F00010EF34 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; + 18C5A9651484440D0010EF34 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 4C010B87121AE8DF0094CB72 /* input-speed-test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "input-speed-test"; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C010B99121AE9960094CB72 /* speed-test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "speed-test.h"; path = "misc/speed-test.h"; sourceTree = ""; }; + 4C010B9A121AE9960094CB72 /* speed-test.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "speed-test.mm"; path = "misc/speed-test.mm"; sourceTree = ""; }; + 4C010BBE121AED340094CB72 /* libc++.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libc++.dylib"; path = "usr/lib/libc++.dylib"; sourceTree = SDKROOT; }; + 4C010C4B121AFCA70094CB72 /* SecExternalSourceTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecExternalSourceTransform.h; sourceTree = ""; }; + 4C010C4C121AFCA70094CB72 /* SecExternalSourceTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecExternalSourceTransform.cpp; sourceTree = ""; }; + 4C01134F1468693100E4F866 /* SecMaskGenerationFunctionTransform.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecMaskGenerationFunctionTransform.c; sourceTree = ""; }; + 4C0113501468693100E4F866 /* SecMaskGenerationFunctionTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecMaskGenerationFunctionTransform.h; sourceTree = ""; }; + 4C01135A14686F2600E4F866 /* NSData+HexString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+HexString.m"; sourceTree = ""; }; + 4C01135B14686F2600E4F866 /* NSData+HexString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+HexString.h"; sourceTree = ""; }; + 4C27A37414F2D66C007FCA66 /* libcorecrypto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcorecrypto.dylib; path = usr/lib/system/libcorecrypto.dylib; sourceTree = SDKROOT; }; + 4C27A37714F2DCB4007FCA66 /* CEncryptDecrypt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CEncryptDecrypt.c; sourceTree = ""; }; + 4C6E5964116D4E3E00A70E8F /* misc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = misc.c; sourceTree = ""; }; + 4C6E5965116D4E3E00A70E8F /* misc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = misc.h; sourceTree = ""; }; + 4C73822B112DCC4800EA003B /* SecCustomTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCustomTransform.h; sourceTree = ""; }; + 4C73822C112DCC4800EA003B /* SecCustomTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SecCustomTransform.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4C738257112DF65200EA003B /* unit-tests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "unit-tests.octest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C738258112DF65200EA003B /* unit-tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "unit-tests-Info.plist"; sourceTree = ""; }; + 4C738260112DF68900EA003B /* custom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = custom.h; sourceTree = ""; }; + 4CA1FEBE052A3C8100F22E42 /* libsecurity_transform.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_transform.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CB89E61124D5667004DEC20 /* SecTransformValidator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTransformValidator.h; sourceTree = ""; }; + 4CBCBEB61130A2D700CC18E9 /* 100-sha2 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "100-sha2"; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CBCBEB81130A2D800CC18E9 /* Info-security_transform.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-security_transform.plist"; sourceTree = ""; }; + 4CD6A668113F41990094F287 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; + 4CD87F3D1130A34700A98C5E /* 100-sha2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "100-sha2.m"; sourceTree = ""; }; + 4CDF6DC9113C4E9E00C64234 /* EncodeDecodeTransforms.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = EncodeDecodeTransforms.c; sourceTree = ""; }; + 4CDF6DCA113C4E9E00C64234 /* SecDecodeTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecDecodeTransform.h; sourceTree = ""; }; + 4CDF6DCB113C4E9E00C64234 /* SecEncodeTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecEncodeTransform.h; sourceTree = ""; }; + 5D16D6FB114EA1000096BD75 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 5DCAD5B511F0E099003F2E7A /* SecCollectTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecCollectTransform.cpp; sourceTree = ""; }; + 5DCAD5B611F0E099003F2E7A /* SecCollectTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCollectTransform.h; sourceTree = ""; }; + 5DD2E91C114E9044007429E7 /* EncryptTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = EncryptTransform.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 5DD2E91D114E9044007429E7 /* EncryptTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = EncryptTransform.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 5DD2E923114E9094007429E7 /* EncryptTransformUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EncryptTransformUtilities.h; sourceTree = ""; }; + 5DD2E924114E9094007429E7 /* EncryptTransformUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EncryptTransformUtilities.cpp; sourceTree = ""; }; + 5DD2E927114E90E2007429E7 /* SecEncryptTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecEncryptTransform.h; sourceTree = ""; }; + 5DD2E928114E90E2007429E7 /* SecEncryptTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecEncryptTransform.cpp; sourceTree = ""; }; + 5DD2E936114E91CC007429E7 /* SecSignVerifyTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecSignVerifyTransform.h; sourceTree = ""; }; + 5DD2E937114E91CC007429E7 /* SecSignVerifyTransform.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecSignVerifyTransform.c; sourceTree = ""; }; + 5DD2E96E114E95B1007429E7 /* custom.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = custom.mm; sourceTree = ""; }; + AA068645138C420C0059E73E /* SecReadTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecReadTransform.h; sourceTree = ""; }; + AA068648138C42520059E73E /* SecReadTransform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecReadTransform.h; sourceTree = ""; }; + AA068EDB1174AB350002E9E0 /* GroupTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GroupTransform.cpp; sourceTree = ""; }; + AA068EDC1174AB350002E9E0 /* GroupTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GroupTransform.h; sourceTree = ""; }; + AA068EDD1174AB350002E9E0 /* SecGroupTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecGroupTransform.cpp; sourceTree = ""; }; + AA068EDE1174AB350002E9E0 /* SecGroupTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecGroupTransform.h; sourceTree = ""; }; + AA068EED1174ABB20002E9E0 /* SecTransformInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTransformInternal.h; sourceTree = ""; }; + AA957FCA122C571E00181BE1 /* SecTransformReadTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTransformReadTransform.h; sourceTree = ""; }; + AA957FD4122C57AF00181BE1 /* SecTransformReadTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecTransformReadTransform.cpp; sourceTree = ""; }; + AA9781A71175475500699E38 /* c++utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "c++utils.h"; sourceTree = ""; }; + AA9781A81175475500699E38 /* c++utils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "c++utils.cpp"; sourceTree = ""; }; + AA9E1C051117966F00380F0D /* CoreFoundationBasics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CoreFoundationBasics.cpp; sourceTree = ""; }; + AA9E1C061117966F00380F0D /* CoreFoundationBasics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoreFoundationBasics.h; sourceTree = ""; }; + AA9E1C071117966F00380F0D /* Digest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Digest.cpp; sourceTree = ""; }; + AA9E1C081117966F00380F0D /* Digest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Digest.h; sourceTree = ""; }; + AA9E1C091117966F00380F0D /* LinkedList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LinkedList.cpp; sourceTree = ""; }; + AA9E1C0A1117966F00380F0D /* LinkedList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinkedList.h; sourceTree = ""; }; + AA9E1C0B1117966F00380F0D /* Monitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Monitor.cpp; sourceTree = ""; }; + AA9E1C0C1117966F00380F0D /* Monitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Monitor.h; sourceTree = ""; }; + AA9E1C0D1117966F00380F0D /* NullTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NullTransform.cpp; sourceTree = ""; }; + AA9E1C0E1117966F00380F0D /* NullTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NullTransform.h; sourceTree = ""; }; + AA9E1C0F1117966F00380F0D /* SecDigestTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecDigestTransform.cpp; sourceTree = ""; }; + AA9E1C101117966F00380F0D /* SecDigestTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecDigestTransform.h; sourceTree = ""; }; + AA9E1C111117966F00380F0D /* SecNullTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecNullTransform.cpp; sourceTree = ""; }; + AA9E1C121117966F00380F0D /* SecNullTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecNullTransform.h; sourceTree = ""; }; + AA9E1C131117966F00380F0D /* SecTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecTransform.cpp; sourceTree = ""; }; + AA9E1C141117966F00380F0D /* SecTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTransform.h; sourceTree = ""; }; + AA9E1C161117966F00380F0D /* SingleShotSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SingleShotSource.cpp; sourceTree = ""; }; + AA9E1C171117966F00380F0D /* SingleShotSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SingleShotSource.h; sourceTree = ""; }; + AA9E1C181117966F00380F0D /* Source.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Source.cpp; sourceTree = ""; }; + AA9E1C191117966F00380F0D /* Source.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Source.h; sourceTree = ""; }; + AA9E1C1A1117966F00380F0D /* StreamSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StreamSource.cpp; sourceTree = ""; }; + AA9E1C1B1117966F00380F0D /* StreamSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StreamSource.h; sourceTree = ""; }; + AA9E1C1C1117966F00380F0D /* Transform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = Transform.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + AA9E1C1D1117966F00380F0D /* Transform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = Transform.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + AA9E1C1E1117966F00380F0D /* TransformFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TransformFactory.cpp; sourceTree = ""; }; + AA9E1C1F1117966F00380F0D /* TransformFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TransformFactory.h; sourceTree = ""; }; + AA9E1C201117966F00380F0D /* Utilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Utilities.cpp; sourceTree = ""; }; + AA9E1C211117966F00380F0D /* Utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utilities.h; sourceTree = ""; }; + AA9E1C9A1117A4A800380F0D /* security_transform.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; name = security_transform.exp; path = lib/security_transform.exp; sourceTree = ""; }; + AA9E1CAD1117A6E000380F0D /* libsecurity_transform_Development.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = libsecurity_transform_Development.xcconfig; sourceTree = ""; }; + AA9E1CAE1117A6F200380F0D /* libsecurity_transform_Deployment.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = libsecurity_transform_Deployment.xcconfig; sourceTree = ""; }; + AA9E1CAF1117A70300380F0D /* libsecurity_transform.Default.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = libsecurity_transform.Default.xcconfig; sourceTree = ""; }; + AA9E1CB01117A78C00380F0D /* security_transform_Development.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = security_transform_Development.xcconfig; sourceTree = ""; }; + AA9E1CB11117A7A300380F0D /* security_transform_Deployment.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = security_transform_Deployment.xcconfig; sourceTree = ""; }; + AA9E1CB21117A7BA00380F0D /* security_transform_Default.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = security_transform_Default.xcconfig; sourceTree = ""; }; + AACAD86B11628E700070BA52 /* libsecurity_transform_core.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = libsecurity_transform_core.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4C010B85121AE8DF0094CB72 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C010BBB121AECF10094CB72 /* Security.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C738254112DF65200EA003B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 18C5A9661484440D0010EF34 /* Foundation.framework in Frameworks */, + 18C5A964148443F00010EF34 /* SenTestingKit.framework in Frameworks */, + 18C5A961148442000010EF34 /* libsecurity_transform.a in Frameworks */, + 4CD6A669113F41990094F287 /* libz.dylib in Frameworks */, + 4CC4A8B21264D22300075C8F /* Security.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CBCBEB41130A2D700CC18E9 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C8174341133031E007F84D6 /* libsecurity_transform.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 18BBC7381471F6DF00F2B224 /* config */ = { + isa = PBXGroup; + children = ( + 18BBC7391471F6DF00F2B224 /* base.xcconfig */, + 18BBC73A1471F6DF00F2B224 /* debug.xcconfig */, + 18BBC73B1471F6DF00F2B224 /* lib.xcconfig */, + 18BBC73C1471F6DF00F2B224 /* release.xcconfig */, + 18BBC73D1471F6DF00F2B224 /* security.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 4C73825F112DF66700EA003B /* unit-tests */ = { + isa = PBXGroup; + children = ( + 4C01135A14686F2600E4F866 /* NSData+HexString.m */, + 4C01135B14686F2600E4F866 /* NSData+HexString.h */, + 4C738260112DF68900EA003B /* custom.h */, + 5DD2E96E114E95B1007429E7 /* custom.mm */, + ); + name = "unit-tests"; + sourceTree = ""; + }; + 4CA1FEA7052A3C3800F22E42 = { + isa = PBXGroup; + children = ( + 18C5A9651484440D0010EF34 /* Foundation.framework */, + 18C5A963148443F00010EF34 /* SenTestingKit.framework */, + 18BBC7381471F6DF00F2B224 /* config */, + 4C27A37414F2D66C007FCA66 /* libcorecrypto.dylib */, + 4C010BBE121AED340094CB72 /* libc++.dylib */, + 4CD6A668113F41990094F287 /* libz.dylib */, + 4C73825F112DF66700EA003B /* unit-tests */, + 4CBCBEB01130A2AB00CC18E9 /* misc-tests */, + AA9E1CA31117A67D00380F0D /* Configurations */, + AA9E1C9A1117A4A800380F0D /* security_transform.exp */, + 4CAFF3FC0534D89900303760 /* lib */, + 4CA1FEBF052A3C8100F22E42 /* Products */, + 4C738258112DF65200EA003B /* unit-tests-Info.plist */, + 4CBCBEB81130A2D800CC18E9 /* Info-security_transform.plist */, + 5D16D6FB114EA1000096BD75 /* Security.framework */, + ); + sourceTree = ""; + }; + 4CA1FEBF052A3C8100F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + 4CA1FEBE052A3C8100F22E42 /* libsecurity_transform.a */, + 4C738257112DF65200EA003B /* unit-tests.octest */, + 4CBCBEB61130A2D700CC18E9 /* 100-sha2 */, + 4C010B87121AE8DF0094CB72 /* input-speed-test */, + ); + name = Products; + sourceTree = ""; + }; + 4CAFF3FC0534D89900303760 /* lib */ = { + isa = PBXGroup; + children = ( + 4C01134F1468693100E4F866 /* SecMaskGenerationFunctionTransform.c */, + 4C0113501468693100E4F866 /* SecMaskGenerationFunctionTransform.h */, + AA068645138C420C0059E73E /* SecReadTransform.h */, + 5DCAD5B511F0E099003F2E7A /* SecCollectTransform.cpp */, + 5DCAD5B611F0E099003F2E7A /* SecCollectTransform.h */, + AA9781A71175475500699E38 /* c++utils.h */, + AA9781A81175475500699E38 /* c++utils.cpp */, + AA9E1C051117966F00380F0D /* CoreFoundationBasics.cpp */, + AA9E1C061117966F00380F0D /* CoreFoundationBasics.h */, + AA9E1C071117966F00380F0D /* Digest.cpp */, + AA9E1C081117966F00380F0D /* Digest.h */, + 4CDF6DC9113C4E9E00C64234 /* EncodeDecodeTransforms.c */, + 5DD2E91C114E9044007429E7 /* EncryptTransform.h */, + 5DD2E91D114E9044007429E7 /* EncryptTransform.cpp */, + 4C27A37714F2DCB4007FCA66 /* CEncryptDecrypt.c */, + 5DD2E923114E9094007429E7 /* EncryptTransformUtilities.h */, + 5DD2E924114E9094007429E7 /* EncryptTransformUtilities.cpp */, + AA068EDB1174AB350002E9E0 /* GroupTransform.cpp */, + AA068EDC1174AB350002E9E0 /* GroupTransform.h */, + AA9E1C091117966F00380F0D /* LinkedList.cpp */, + AA9E1C0A1117966F00380F0D /* LinkedList.h */, + 4C6E5964116D4E3E00A70E8F /* misc.c */, + 4C6E5965116D4E3E00A70E8F /* misc.h */, + AA9E1C0B1117966F00380F0D /* Monitor.cpp */, + AA9E1C0C1117966F00380F0D /* Monitor.h */, + AA9E1C0D1117966F00380F0D /* NullTransform.cpp */, + AA9E1C0E1117966F00380F0D /* NullTransform.h */, + 4C73822B112DCC4800EA003B /* SecCustomTransform.h */, + 4C73822C112DCC4800EA003B /* SecCustomTransform.cpp */, + 4CDF6DCA113C4E9E00C64234 /* SecDecodeTransform.h */, + AA9E1C0F1117966F00380F0D /* SecDigestTransform.cpp */, + AA9E1C101117966F00380F0D /* SecDigestTransform.h */, + 5DD2E927114E90E2007429E7 /* SecEncryptTransform.h */, + 4CDF6DCB113C4E9E00C64234 /* SecEncodeTransform.h */, + 5DD2E928114E90E2007429E7 /* SecEncryptTransform.cpp */, + AA068EDD1174AB350002E9E0 /* SecGroupTransform.cpp */, + AA068EDE1174AB350002E9E0 /* SecGroupTransform.h */, + AA9E1C111117966F00380F0D /* SecNullTransform.cpp */, + 5DD2E936114E91CC007429E7 /* SecSignVerifyTransform.h */, + 5DD2E937114E91CC007429E7 /* SecSignVerifyTransform.c */, + AA9E1C121117966F00380F0D /* SecNullTransform.h */, + AA9E1C131117966F00380F0D /* SecTransform.cpp */, + AA9E1C141117966F00380F0D /* SecTransform.h */, + AA068EED1174ABB20002E9E0 /* SecTransformInternal.h */, + AA9E1C161117966F00380F0D /* SingleShotSource.cpp */, + AA9E1C171117966F00380F0D /* SingleShotSource.h */, + AA9E1C181117966F00380F0D /* Source.cpp */, + AA9E1C191117966F00380F0D /* Source.h */, + AA9E1C1A1117966F00380F0D /* StreamSource.cpp */, + AA9E1C1B1117966F00380F0D /* StreamSource.h */, + AA9E1C1C1117966F00380F0D /* Transform.cpp */, + AA9E1C1D1117966F00380F0D /* Transform.h */, + AA9E1C1E1117966F00380F0D /* TransformFactory.cpp */, + AA9E1C1F1117966F00380F0D /* TransformFactory.h */, + AA9E1C201117966F00380F0D /* Utilities.cpp */, + AA9E1C211117966F00380F0D /* Utilities.h */, + 4C010C4B121AFCA70094CB72 /* SecExternalSourceTransform.h */, + 4C010C4C121AFCA70094CB72 /* SecExternalSourceTransform.cpp */, + AA957FCA122C571E00181BE1 /* SecTransformReadTransform.h */, + AA957FD4122C57AF00181BE1 /* SecTransformReadTransform.cpp */, + 4CB89E61124D5667004DEC20 /* SecTransformValidator.h */, + AA068648138C42520059E73E /* SecReadTransform.h */, + ); + path = lib; + sourceTree = ""; + }; + 4CBCBEB01130A2AB00CC18E9 /* misc-tests */ = { + isa = PBXGroup; + children = ( + 4CD87F3D1130A34700A98C5E /* 100-sha2.m */, + 4C010B99121AE9960094CB72 /* speed-test.h */, + 4C010B9A121AE9960094CB72 /* speed-test.mm */, + ); + name = "misc-tests"; + sourceTree = ""; + }; + AA9E1CA31117A67D00380F0D /* Configurations */ = { + isa = PBXGroup; + children = ( + AACAD86B11628E700070BA52 /* libsecurity_transform_core.xcconfig */, + AA9E1CAD1117A6E000380F0D /* libsecurity_transform_Development.xcconfig */, + AA9E1CAE1117A6F200380F0D /* libsecurity_transform_Deployment.xcconfig */, + AA9E1CAF1117A70300380F0D /* libsecurity_transform.Default.xcconfig */, + AA9E1CB01117A78C00380F0D /* security_transform_Development.xcconfig */, + AA9E1CB11117A7A300380F0D /* security_transform_Deployment.xcconfig */, + AA9E1CB21117A7BA00380F0D /* security_transform_Default.xcconfig */, + ); + path = Configurations; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4CA1FEB9052A3C8100F22E42 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + AA9E1C2D1117966F00380F0D /* SecDigestTransform.h in Headers */, + AA068646138C420C0059E73E /* SecReadTransform.h in Headers */, + AA9E1C311117966F00380F0D /* SecTransform.h in Headers */, + 4C73822D112DCC4800EA003B /* SecCustomTransform.h in Headers */, + 4CDF6DCD113C4E9E00C64234 /* SecDecodeTransform.h in Headers */, + 4CDF6DCE113C4E9E00C64234 /* SecEncodeTransform.h in Headers */, + 5DD2E929114E90E2007429E7 /* SecEncryptTransform.h in Headers */, + 5DD2E938114E91CC007429E7 /* SecSignVerifyTransform.h in Headers */, + AA957FCB122C571E00181BE1 /* SecTransformReadTransform.h in Headers */, + AA9E1C231117966F00380F0D /* CoreFoundationBasics.h in Headers */, + AA9E1C251117966F00380F0D /* Digest.h in Headers */, + 4CB89E62124D5667004DEC20 /* SecTransformValidator.h in Headers */, + AA9E1C2F1117966F00380F0D /* SecNullTransform.h in Headers */, + AA068EEE1174ABB20002E9E0 /* SecTransformInternal.h in Headers */, + AA9E1C271117966F00380F0D /* LinkedList.h in Headers */, + AA9E1C291117966F00380F0D /* Monitor.h in Headers */, + AA9E1C2B1117966F00380F0D /* NullTransform.h in Headers */, + AA9E1C341117966F00380F0D /* SingleShotSource.h in Headers */, + AA9E1C361117966F00380F0D /* Source.h in Headers */, + AA9E1C381117966F00380F0D /* StreamSource.h in Headers */, + AA9E1C3A1117966F00380F0D /* Transform.h in Headers */, + AA9E1C3C1117966F00380F0D /* TransformFactory.h in Headers */, + AA9E1C3E1117966F00380F0D /* Utilities.h in Headers */, + 4C0113521468693100E4F866 /* SecMaskGenerationFunctionTransform.h in Headers */, + 5DD2E91E114E9044007429E7 /* EncryptTransform.h in Headers */, + 5DD2E925114E9094007429E7 /* EncryptTransformUtilities.h in Headers */, + 4C6E5967116D4E3E00A70E8F /* misc.h in Headers */, + AA068EE01174AB350002E9E0 /* GroupTransform.h in Headers */, + AA068EE21174AB350002E9E0 /* SecGroupTransform.h in Headers */, + AA9781A91175475500699E38 /* c++utils.h in Headers */, + 5DCAD5B811F0E099003F2E7A /* SecCollectTransform.h in Headers */, + 4C010C52121B00350094CB72 /* SecExternalSourceTransform.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 4C010B86121AE8DF0094CB72 /* input-speed-test */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4C010B97121AE9340094CB72 /* Build configuration list for PBXNativeTarget "input-speed-test" */; + buildPhases = ( + 4C010B84121AE8DF0094CB72 /* Sources */, + 4C010B85121AE8DF0094CB72 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 4C010B91121AE9070094CB72 /* PBXTargetDependency */, + ); + name = "input-speed-test"; + productName = "input-speed-test"; + productReference = 4C010B87121AE8DF0094CB72 /* input-speed-test */; + productType = "com.apple.product-type.tool"; + }; + 4C738256112DF65200EA003B /* unit-tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4C73825C112DF65400EA003B /* Build configuration list for PBXNativeTarget "unit-tests" */; + buildPhases = ( + 4C738252112DF65200EA003B /* Resources */, + 4C738253112DF65200EA003B /* Sources */, + 4C738254112DF65200EA003B /* Frameworks */, + 4C738255112DF65200EA003B /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 4C817256112F030F007F84D6 /* PBXTargetDependency */, + ); + name = "unit-tests"; + productName = "unit-tests"; + productReference = 4C738257112DF65200EA003B /* unit-tests.octest */; + productType = "com.apple.product-type.bundle.ocunit-test"; + }; + 4CA1FEBD052A3C8100F22E42 /* libsecurity_transform */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD4000987FCDF001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_transform" */; + buildPhases = ( + 4CA1FEB9052A3C8100F22E42 /* Headers */, + 4CA1FEBA052A3C8100F22E42 /* Sources */, + 4CA1FEBB052A3C8100F22E42 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libsecurity_transform; + productName = libsecurity_transform; + productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_transform.a */; + productType = "com.apple.product-type.library.static"; + }; + 4CBCBEB51130A2D700CC18E9 /* 100-sha2 */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4CBCBEBC1130A2DB00CC18E9 /* Build configuration list for PBXNativeTarget "100-sha2" */; + buildPhases = ( + 4CBCBEB31130A2D700CC18E9 /* Sources */, + 4CBCBEB41130A2D700CC18E9 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 4CD880001131E0F500A98C5E /* PBXTargetDependency */, + ); + name = "100-sha2"; + productName = "100-sha2"; + productReference = 4CBCBEB61130A2D700CC18E9 /* 100-sha2 */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA1FEAB052A3C3800F22E42 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + }; + buildConfigurationList = C27AD4040987FCDF001272E0 /* Build configuration list for PBXProject "libsecurity_transform" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 4CA1FEA7052A3C3800F22E42; + productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4CA1FEBD052A3C8100F22E42 /* libsecurity_transform */, + 4C738256112DF65200EA003B /* unit-tests */, + 4CBCBEB51130A2D700CC18E9 /* 100-sha2 */, + 4C010B86121AE8DF0094CB72 /* input-speed-test */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 4C738252112DF65200EA003B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 4C738255112DF65200EA003B /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 4C010B84121AE8DF0094CB72 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C010B9B121AE9960094CB72 /* speed-test.mm in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C738253112DF65200EA003B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5DD2E9B5114E986D007429E7 /* custom.mm in Sources */, + 4C01135C14686F2600E4F866 /* NSData+HexString.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CA1FEBA052A3C8100F22E42 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AA9E1C221117966F00380F0D /* CoreFoundationBasics.cpp in Sources */, + AA9E1C241117966F00380F0D /* Digest.cpp in Sources */, + AA9E1C261117966F00380F0D /* LinkedList.cpp in Sources */, + AA9E1C281117966F00380F0D /* Monitor.cpp in Sources */, + AA9E1C2A1117966F00380F0D /* NullTransform.cpp in Sources */, + AA9E1C2C1117966F00380F0D /* SecDigestTransform.cpp in Sources */, + AA9E1C2E1117966F00380F0D /* SecNullTransform.cpp in Sources */, + AA9E1C301117966F00380F0D /* SecTransform.cpp in Sources */, + AA9E1C331117966F00380F0D /* SingleShotSource.cpp in Sources */, + AA9E1C351117966F00380F0D /* Source.cpp in Sources */, + AA9E1C371117966F00380F0D /* StreamSource.cpp in Sources */, + AA9E1C391117966F00380F0D /* Transform.cpp in Sources */, + AA9E1C3B1117966F00380F0D /* TransformFactory.cpp in Sources */, + AA9E1C3D1117966F00380F0D /* Utilities.cpp in Sources */, + 4C73822E112DCC4800EA003B /* SecCustomTransform.cpp in Sources */, + 4CDF6DCC113C4E9E00C64234 /* EncodeDecodeTransforms.c in Sources */, + 5DD2E91F114E9044007429E7 /* EncryptTransform.cpp in Sources */, + 5DD2E926114E9094007429E7 /* EncryptTransformUtilities.cpp in Sources */, + 5DD2E92A114E90E2007429E7 /* SecEncryptTransform.cpp in Sources */, + 5DD2E939114E91CC007429E7 /* SecSignVerifyTransform.c in Sources */, + 4C6E5966116D4E3E00A70E8F /* misc.c in Sources */, + AA068EDF1174AB350002E9E0 /* GroupTransform.cpp in Sources */, + AA068EE11174AB350002E9E0 /* SecGroupTransform.cpp in Sources */, + AA9781AA1175475500699E38 /* c++utils.cpp in Sources */, + 5DCAD5B711F0E099003F2E7A /* SecCollectTransform.cpp in Sources */, + 4C010C53121B00440094CB72 /* SecExternalSourceTransform.cpp in Sources */, + AA957FD5122C57AF00181BE1 /* SecTransformReadTransform.cpp in Sources */, + 4C0113511468693100E4F866 /* SecMaskGenerationFunctionTransform.c in Sources */, + 4C27A37814F2DCB4007FCA66 /* CEncryptDecrypt.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CBCBEB31130A2D700CC18E9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4CD87F501130A49400A98C5E /* 100-sha2.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 4C010B91121AE9070094CB72 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4CA1FEBD052A3C8100F22E42 /* libsecurity_transform */; + targetProxy = 4C010B90121AE9070094CB72 /* PBXContainerItemProxy */; + }; + 4C817256112F030F007F84D6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4CA1FEBD052A3C8100F22E42 /* libsecurity_transform */; + targetProxy = 4C817255112F030F007F84D6 /* PBXContainerItemProxy */; + }; + 4CD880001131E0F500A98C5E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4CA1FEBD052A3C8100F22E42 /* libsecurity_transform */; + targetProxy = 4CD87FFF1131E0F500A98C5E /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 4C010B89121AE8DF0094CB72 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + COPY_PHASE_STRIP = NO; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INSTALL_PATH = /usr/local/bin; + OTHER_LDFLAGS = ( + "-lz", + "-framework", + Foundation, + "-framework", + AppKit, + ); + PRODUCT_NAME = "input-speed-test"; + }; + name = Debug; + }; + 4C010B8B121AE8DF0094CB72 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INSTALL_PATH = /usr/local/bin; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + ); + PRODUCT_NAME = "input-speed-test"; + }; + name = Release; + }; + 4C738259112DF65400EA003B /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18BBC73B1471F6DF00F2B224 /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(DEVELOPER_FRAMEWORKS_DIR)", + ); + INFOPLIST_FILE = "unit-tests-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /usr/lib/system, + ); + PRODUCT_NAME = "unit-tests"; + WRAPPER_EXTENSION = octest; + }; + name = Debug; + }; + 4C73825B112DF65400EA003B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18BBC73B1471F6DF00F2B224 /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(DEVELOPER_FRAMEWORKS_DIR)", + ); + INFOPLIST_FILE = "unit-tests-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /usr/lib/system, + ); + PRODUCT_NAME = "unit-tests"; + WRAPPER_EXTENSION = octest; + }; + name = Release; + }; + 4CBCBEB91130A2DB00CC18E9 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INSTALL_PATH = /usr/local/bin; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + "-lstdc++", + ); + PRODUCT_NAME = "100-sha2"; + }; + name = Debug; + }; + 4CBCBEBB1130A2DB00CC18E9 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + GCC_MODEL_TUNING = G5; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + INSTALL_PATH = /usr/local/bin; + OTHER_LDFLAGS = ( + "-framework", + Foundation, + "-framework", + AppKit, + "-lstdc++", + ); + PRODUCT_NAME = "100-sha2"; + }; + name = Release; + }; + C27AD4010987FCDF001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18BBC73B1471F6DF00F2B224 /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /usr/lib/system, + ); + OTHER_CFLAGS = ( + "$(inherited)", + "-DCOM_APPLE_SECURITY_SANE_INCLUDES", + ); + WARNING_CFLAGS = ( + "$(inherited)", + "-Wno-error=overloaded-virtual", + ); + }; + name = Debug; + }; + C27AD4030987FCDF001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18BBC73B1471F6DF00F2B224 /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /usr/lib/system, + ); + OTHER_CFLAGS = ( + "$(inherited)", + "-DCOM_APPLE_SECURITY_SANE_INCLUDES", + ); + WARNING_CFLAGS = ( + "$(inherited)", + "-Wno-error=overloaded-virtual", + ); + }; + name = Release; + }; + C27AD4050987FCDF001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18BBC73A1471F6DF00F2B224 /* debug.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD4070987FCDF001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18BBC73C1471F6DF00F2B224 /* release.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4C010B97121AE9340094CB72 /* Build configuration list for PBXNativeTarget "input-speed-test" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4C010B89121AE8DF0094CB72 /* Debug */, + 4C010B8B121AE8DF0094CB72 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4C73825C112DF65400EA003B /* Build configuration list for PBXNativeTarget "unit-tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4C738259112DF65400EA003B /* Debug */, + 4C73825B112DF65400EA003B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4CBCBEBC1130A2DB00CC18E9 /* Build configuration list for PBXNativeTarget "100-sha2" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4CBCBEB91130A2DB00CC18E9 /* Debug */, + 4CBCBEBB1130A2DB00CC18E9 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD4000987FCDF001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_transform" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD4010987FCDF001272E0 /* Debug */, + C27AD4030987FCDF001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD4040987FCDF001272E0 /* Build configuration list for PBXProject "libsecurity_transform" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD4050987FCDF001272E0 /* Debug */, + C27AD4070987FCDF001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; +} diff --git a/libsecurity_transform/misc/base32alpha2vals b/Security/libsecurity_transform/misc/base32alpha2vals similarity index 100% rename from libsecurity_transform/misc/base32alpha2vals rename to Security/libsecurity_transform/misc/base32alpha2vals diff --git a/Security/libsecurity_transform/misc/speed-test.h b/Security/libsecurity_transform/misc/speed-test.h new file mode 100644 index 00000000..422739d0 --- /dev/null +++ b/Security/libsecurity_transform/misc/speed-test.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2010-2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#import + + +@interface speed_test : NSObject { + +} + +@end diff --git a/Security/libsecurity_transform/misc/speed-test.mm b/Security/libsecurity_transform/misc/speed-test.mm new file mode 100644 index 00000000..b33aea64 --- /dev/null +++ b/Security/libsecurity_transform/misc/speed-test.mm @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2010 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#import "speed-test.h" +#include "SecTransform.h" +#include "SecExternalSourceTransform.h" +#include "SecNullTransform.h" +#include + +@implementation speed_test + +@end + +UInt8 zeros[1024]; + +typedef void (^push_block_t)(CFDataRef d); + +void timed_test(NSString *name, float seconds, SecTransformRef tr, push_block_t push) { + __block int num_out = 0; + __block int num_in = 0; + __block int timeout_out = -1; + __block int timeout_in = -1; + volatile __block bool done; + static CFDataRef z = CFDataCreateWithBytesNoCopy(NULL, zeros, sizeof(zeros), NULL); + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, static_cast(seconds * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ + done = true; + timeout_out = num_out; + timeout_in = num_in; + }); + + dispatch_group_t dg = dispatch_group_create(); + dispatch_group_enter(dg); + + dispatch_queue_t q = dispatch_queue_create("counter", NULL); + + SecTransformExecuteAsync(tr, q, ^(CFTypeRef message, CFErrorRef error, Boolean isFinal) { + if (message) { + num_out++; + } + if (error) { + NSLog(@"Error %@ while running %@", error, name); + } + if (isFinal) { + dispatch_group_leave(dg); + } + }); + + while (!done) { + push(z); + num_in++; + } + push(NULL); + dispatch_group_wait(dg, DISPATCH_TIME_FOREVER); + NSString *m = [NSString stringWithFormat:@"%@ %d in, %d out times in %f seconds, %d stragglers\n", name, timeout_in, timeout_out, seconds, num_out - timeout_out]; + [m writeToFile:@"/dev/stdout" atomically:NO encoding:NSUTF8StringEncoding error:NULL]; +} + +int main(int argc, char *argv[]) { + NSAutoreleasePool *ap = [[NSAutoreleasePool alloc] init]; + float seconds = 5.0; + + { + SecTransformRef x = SecExternalSourceTransformCreate(NULL); + //SecTransformRef t = SecEncodeTransformCreate(kSecBase64Encoding, NULL); + SecTransformRef t = SecNullTransformCreate(); + SecTransformRef g = SecTransformCreateGroupTransform(); + assert(x && t && g); + SecTransformConnectTransforms(x, kSecTransformOutputAttributeName, t, kSecTransformInputAttributeName, g, NULL); + + timed_test(@"external source", seconds, t, ^(CFDataRef d){ + SecExternalSourceSetValue(x, d, NULL); + }); + + } + + // This second test has issues with the stock transform framwork -- it don't think the graph is valid (missing input) + { + //SecTransformRef t = SecEncodeTransformCreate(kSecBase64Encoding, NULL); + SecTransformRef t = SecNullTransformCreate(); + assert(t); + + timed_test(@"set INPUT", seconds, t, ^(CFDataRef d){ + SecTransformSetAttribute(t, kSecTransformInputAttributeName, d, NULL); + }); + } +} diff --git a/libsecurity_transform/unit-tests-Info.plist b/Security/libsecurity_transform/unit-tests-Info.plist similarity index 100% rename from libsecurity_transform/unit-tests-Info.plist rename to Security/libsecurity_transform/unit-tests-Info.plist diff --git a/libsecurityd/APPLE_LICENSE b/Security/libsecurity_utilities/APPLE_LICENSE similarity index 100% rename from libsecurityd/APPLE_LICENSE rename to Security/libsecurity_utilities/APPLE_LICENSE diff --git a/libsecurity_utilities/Info-security_utilities.plist b/Security/libsecurity_utilities/Info-security_utilities.plist similarity index 100% rename from libsecurity_utilities/Info-security_utilities.plist rename to Security/libsecurity_utilities/Info-security_utilities.plist diff --git a/libsecurity_utilities/lib/adornments.cpp b/Security/libsecurity_utilities/lib/adornments.cpp similarity index 97% rename from libsecurity_utilities/lib/adornments.cpp rename to Security/libsecurity_utilities/lib/adornments.cpp index b8bc3ee6..76c22796 100644 --- a/libsecurity_utilities/lib/adornments.cpp +++ b/Security/libsecurity_utilities/lib/adornments.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/adornments.h b/Security/libsecurity_utilities/lib/adornments.h similarity index 98% rename from libsecurity_utilities/lib/adornments.h rename to Security/libsecurity_utilities/lib/adornments.h index e2c8d89c..bd5dccfa 100644 --- a/libsecurity_utilities/lib/adornments.h +++ b/Security/libsecurity_utilities/lib/adornments.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/alloc.cpp b/Security/libsecurity_utilities/lib/alloc.cpp similarity index 98% rename from libsecurity_utilities/lib/alloc.cpp rename to Security/libsecurity_utilities/lib/alloc.cpp index 52359410..61992434 100644 --- a/libsecurity_utilities/lib/alloc.cpp +++ b/Security/libsecurity_utilities/lib/alloc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/alloc.h b/Security/libsecurity_utilities/lib/alloc.h similarity index 99% rename from libsecurity_utilities/lib/alloc.h rename to Security/libsecurity_utilities/lib/alloc.h index 2f227768..83403e01 100644 --- a/libsecurity_utilities/lib/alloc.h +++ b/Security/libsecurity_utilities/lib/alloc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/blob.cpp b/Security/libsecurity_utilities/lib/blob.cpp similarity index 98% rename from libsecurity_utilities/lib/blob.cpp rename to Security/libsecurity_utilities/lib/blob.cpp index 04be864e..0d649b76 100644 --- a/libsecurity_utilities/lib/blob.cpp +++ b/Security/libsecurity_utilities/lib/blob.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/blob.h b/Security/libsecurity_utilities/lib/blob.h similarity index 99% rename from libsecurity_utilities/lib/blob.h rename to Security/libsecurity_utilities/lib/blob.h index a3bfb203..d35d4525 100644 --- a/libsecurity_utilities/lib/blob.h +++ b/Security/libsecurity_utilities/lib/blob.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/bufferfifo.cpp b/Security/libsecurity_utilities/lib/bufferfifo.cpp similarity index 97% rename from libsecurity_utilities/lib/bufferfifo.cpp rename to Security/libsecurity_utilities/lib/bufferfifo.cpp index 567bb7e0..23b60117 100644 --- a/libsecurity_utilities/lib/bufferfifo.cpp +++ b/Security/libsecurity_utilities/lib/bufferfifo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/bufferfifo.h b/Security/libsecurity_utilities/lib/bufferfifo.h similarity index 97% rename from libsecurity_utilities/lib/bufferfifo.h rename to Security/libsecurity_utilities/lib/bufferfifo.h index a0547b45..f2666981 100644 --- a/libsecurity_utilities/lib/bufferfifo.h +++ b/Security/libsecurity_utilities/lib/bufferfifo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/buffers.cpp b/Security/libsecurity_utilities/lib/buffers.cpp similarity index 97% rename from libsecurity_utilities/lib/buffers.cpp rename to Security/libsecurity_utilities/lib/buffers.cpp index acfec8c8..d9856ffc 100644 --- a/libsecurity_utilities/lib/buffers.cpp +++ b/Security/libsecurity_utilities/lib/buffers.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/buffers.h b/Security/libsecurity_utilities/lib/buffers.h similarity index 98% rename from libsecurity_utilities/lib/buffers.h rename to Security/libsecurity_utilities/lib/buffers.h index 65a0eefb..afbb4190 100644 --- a/libsecurity_utilities/lib/buffers.h +++ b/Security/libsecurity_utilities/lib/buffers.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/ccaudit.cpp b/Security/libsecurity_utilities/lib/ccaudit.cpp similarity index 98% rename from libsecurity_utilities/lib/ccaudit.cpp rename to Security/libsecurity_utilities/lib/ccaudit.cpp index 014c85e0..ecde313a 100644 --- a/libsecurity_utilities/lib/ccaudit.cpp +++ b/Security/libsecurity_utilities/lib/ccaudit.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/Security/libsecurity_utilities/lib/ccaudit.h b/Security/libsecurity_utilities/lib/ccaudit.h new file mode 100644 index 00000000..13719d83 --- /dev/null +++ b/Security/libsecurity_utilities/lib/ccaudit.h @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please obtain + * a copy of the License at http://www.apple.com/publicsource and read it before + * using this file. + * + * This 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. + */ + + +#ifndef _H_CCAUDIT +#define _H_CCAUDIT + +#include +#include // audit_token_t +#include // au_tid_t, etc. +#include // AUE_NULL + +namespace Security { +namespace CommonCriteria { + +class AuditToken; + + +/* + * For the most part, we won't have a machine ID to initialize the + * au_tid_t's machine field. There's no machine ID in the audit token, + * for example, since MIG is localhost-only. + */ +class TerminalId: public PodWrapper +{ + public: + TerminalId(); + TerminalId(const TerminalId &t) { set(t); } + TerminalId(const au_tid_t &tid) { set(tid); } + ~TerminalId() { } + + void set(const au_tid_t &tid) { port = tid.port; machine = tid.machine; } +}; + +/* + * audit_token_t provides all the info required for Common Criteria-mandated + * auditing. It's defined in . Its values are filled + * in by the kernel during a Mach RPC and it should be treated as read-only + * thereafter. + */ +class AuditToken { + public: + AuditToken(const audit_token_t &token); + ~AuditToken() { } + + audit_token_t auditToken() const { return mAuditToken; } + uid_t auditId() const { return mAuditId; } + uid_t euid() const { return mEuid; } + gid_t egid() const { return mEgid; } + uid_t ruid() const { return mRuid; } + gid_t rgid() const { return mRgid; } + pid_t pid() const { return mPid; } + au_asid_t sessionId() const { return mSessionId; } + const au_tid_t &terminalId() const { return mTerminalId; } + + private: + audit_token_t mAuditToken; + uid_t mAuditId; + uid_t mEuid; + gid_t mEgid; + uid_t mRuid; + gid_t mRgid; + pid_t mPid; // of client + au_asid_t mSessionId; + TerminalId mTerminalId; +}; + + +/* + * The (new) audit information structure + */ +class AuditInfo : public PodWrapper { +public: + void get(); + void get(au_asid_t session); + void getPid(pid_t pid); + void set(); + void create(uint64_t flags, uid_t auid = AU_DEFAUDITID); + + uid_t uid() const { return this->ai_auid; } + uint64_t flags() const { return this->ai_flags; } + au_asid_t sessionId() const { return this->ai_asid; } + + static AuditInfo current() { AuditInfo info; info.get(); return info; } +}; + + +// XXX/gh 3926739 +// +// NB: Qualify all uses of these names with the namespace (CommonCriteria). +// Existing source code already follows this convention. +enum ExternalErrors +{ + errNone = 0, + errInvalidCredential = 1111, // try to make easier to find in log + errUserCanceled, + errTooManyTries, + errAuthDenied, // "Auth" --> authorization; named to + // avoid conflict with the C symbol + // errAuthorizationDenied already in + // use + errEndOfExternalErrors // sentry/placeholder +}; + + + +class AuditMask +{ + public: + AuditMask(unsigned int s = AUE_NULL, unsigned int f = AUE_NULL) + { + mMask.am_success = s; mMask.am_failure = f; + } + ~AuditMask() { } + const au_mask_t &get(void) const { return mMask; } + + private: + au_mask_t mMask; +}; + + +// audit session state for the current process; only used by Server +class AuditSession +{ + public: + AuditSession(au_id_t auid, au_asid_t sid) + : mAuditId(auid), mSessionId(sid) { } + ~AuditSession() { } + + // set audit info for this process in kernel + void registerSession(void); + + void auditId(au_id_t auid) { mAuditId = auid; } + void eventMask(AuditMask &mask) { mEventMask = mask; } + void terminalId(TerminalId &tid) { mTerminalId = tid; } + void sessionId(au_asid_t sid) { mSessionId = sid; } + + au_id_t auditId(void) { return mAuditId; } + AuditMask &eventMask(void) { return mEventMask; } + TerminalId &terminalId(void) { return mTerminalId; } + au_asid_t sessionId(void) { return mSessionId; } + + private: + au_id_t mAuditId; + AuditMask mEventMask; + TerminalId mTerminalId; + au_asid_t mSessionId; +}; + +// +// For submitting audit records. Not general-purpose: no ability to +// submit arbitrary BSM tokens, for example. However, the SecurityServer +// has only limited auditing requirements under Common Criteria. +// +class AuditRecord +{ + public: + AuditRecord(const AuditToken &auditToken) + : mAuditToken(auditToken) { } + AuditRecord(const audit_token_t &auditToken) + : mAuditToken(auditToken) { } + ~AuditRecord() { } + + // returnCode == 0 --> success; nonzero returnCode --> failure + void submit(const short event_code, const int returnCode, + const char *msg = NULL); + + private: + AuditToken mAuditToken; +}; + +} // end namespace CommonCriteria +} // end namespace Security + +#endif // _H_CCAUDIT diff --git a/libsecurity_utilities/lib/cfclass.cpp b/Security/libsecurity_utilities/lib/cfclass.cpp similarity index 98% rename from libsecurity_utilities/lib/cfclass.cpp rename to Security/libsecurity_utilities/lib/cfclass.cpp index d635ca44..75244e0c 100644 --- a/libsecurity_utilities/lib/cfclass.cpp +++ b/Security/libsecurity_utilities/lib/cfclass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/cfclass.h b/Security/libsecurity_utilities/lib/cfclass.h similarity index 96% rename from libsecurity_utilities/lib/cfclass.h rename to Security/libsecurity_utilities/lib/cfclass.h index 9d1113a7..6203f112 100644 --- a/libsecurity_utilities/lib/cfclass.h +++ b/Security/libsecurity_utilities/lib/cfclass.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/cfmach++.cpp b/Security/libsecurity_utilities/lib/cfmach++.cpp similarity index 97% rename from libsecurity_utilities/lib/cfmach++.cpp rename to Security/libsecurity_utilities/lib/cfmach++.cpp index 16993be1..db6676df 100644 --- a/libsecurity_utilities/lib/cfmach++.cpp +++ b/Security/libsecurity_utilities/lib/cfmach++.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/cfmach++.h b/Security/libsecurity_utilities/lib/cfmach++.h similarity index 96% rename from libsecurity_utilities/lib/cfmach++.h rename to Security/libsecurity_utilities/lib/cfmach++.h index cc51f43e..da89a5a3 100644 --- a/libsecurity_utilities/lib/cfmach++.h +++ b/Security/libsecurity_utilities/lib/cfmach++.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/cfmunge.cpp b/Security/libsecurity_utilities/lib/cfmunge.cpp similarity index 99% rename from libsecurity_utilities/lib/cfmunge.cpp rename to Security/libsecurity_utilities/lib/cfmunge.cpp index 478835fe..d2c6a4dc 100644 --- a/libsecurity_utilities/lib/cfmunge.cpp +++ b/Security/libsecurity_utilities/lib/cfmunge.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/cfmunge.h b/Security/libsecurity_utilities/lib/cfmunge.h similarity index 98% rename from libsecurity_utilities/lib/cfmunge.h rename to Security/libsecurity_utilities/lib/cfmunge.h index 4d38a2c3..2b13d326 100644 --- a/libsecurity_utilities/lib/cfmunge.h +++ b/Security/libsecurity_utilities/lib/cfmunge.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/cfutilities.cpp b/Security/libsecurity_utilities/lib/cfutilities.cpp similarity index 93% rename from libsecurity_utilities/lib/cfutilities.cpp rename to Security/libsecurity_utilities/lib/cfutilities.cpp index 5bc5378d..b6660006 100644 --- a/libsecurity_utilities/lib/cfutilities.cpp +++ b/Security/libsecurity_utilities/lib/cfutilities.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -48,22 +48,12 @@ CFEmptyArray::CFEmptyArray() // CFURLRef makeCFURL(const char *s, bool isDirectory, CFURLRef base) { - CFStringRef ss = CFStringCreateWithCStringNoCopy(NULL, s, kCFStringEncodingUTF8, kCFAllocatorNull); - CFURLRef returnValue = NULL; - if (base) - { - returnValue = CFURLCreateWithFileSystemPathRelativeToBase(NULL, - ss, kCFURLPOSIXPathStyle, isDirectory, base); - } + return CFURLCreateWithFileSystemPathRelativeToBase(NULL, + CFTempString(s), kCFURLPOSIXPathStyle, isDirectory, base); else - { - returnValue = CFURLCreateWithFileSystemPath(NULL, - ss, kCFURLPOSIXPathStyle, isDirectory); - } - - CFRelease(ss); - return returnValue; + return CFURLCreateWithFileSystemPath(NULL, + CFTempString(s), kCFURLPOSIXPathStyle, isDirectory); } CFURLRef makeCFURL(CFStringRef s, bool isDirectory, CFURLRef base) diff --git a/libsecurity_utilities/lib/cfutilities.h b/Security/libsecurity_utilities/lib/cfutilities.h similarity index 99% rename from libsecurity_utilities/lib/cfutilities.h rename to Security/libsecurity_utilities/lib/cfutilities.h index 4481f170..c69af028 100644 --- a/libsecurity_utilities/lib/cfutilities.h +++ b/Security/libsecurity_utilities/lib/cfutilities.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/coderepository.cpp b/Security/libsecurity_utilities/lib/coderepository.cpp similarity index 97% rename from libsecurity_utilities/lib/coderepository.cpp rename to Security/libsecurity_utilities/lib/coderepository.cpp index 976d838d..bc18eec4 100644 --- a/libsecurity_utilities/lib/coderepository.cpp +++ b/Security/libsecurity_utilities/lib/coderepository.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/coderepository.h b/Security/libsecurity_utilities/lib/coderepository.h similarity index 98% rename from libsecurity_utilities/lib/coderepository.h rename to Security/libsecurity_utilities/lib/coderepository.h index 97ed45fd..400dcf73 100644 --- a/libsecurity_utilities/lib/coderepository.h +++ b/Security/libsecurity_utilities/lib/coderepository.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/crc.c b/Security/libsecurity_utilities/lib/crc.c similarity index 100% rename from libsecurity_utilities/lib/crc.c rename to Security/libsecurity_utilities/lib/crc.c diff --git a/libsecurity_utilities/lib/crc.h b/Security/libsecurity_utilities/lib/crc.h similarity index 100% rename from libsecurity_utilities/lib/crc.h rename to Security/libsecurity_utilities/lib/crc.h diff --git a/libsecurity_utilities/lib/daemon.cpp b/Security/libsecurity_utilities/lib/daemon.cpp similarity index 97% rename from libsecurity_utilities/lib/daemon.cpp rename to Security/libsecurity_utilities/lib/daemon.cpp index c5b6642e..fc8c15e4 100644 --- a/libsecurity_utilities/lib/daemon.cpp +++ b/Security/libsecurity_utilities/lib/daemon.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/daemon.h b/Security/libsecurity_utilities/lib/daemon.h similarity index 95% rename from libsecurity_utilities/lib/daemon.h rename to Security/libsecurity_utilities/lib/daemon.h index 80abfd29..6e51747d 100644 --- a/libsecurity_utilities/lib/daemon.h +++ b/Security/libsecurity_utilities/lib/daemon.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/debugging.cpp b/Security/libsecurity_utilities/lib/debugging.cpp similarity index 99% rename from libsecurity_utilities/lib/debugging.cpp rename to Security/libsecurity_utilities/lib/debugging.cpp index bf43e180..5f5fa108 100644 --- a/libsecurity_utilities/lib/debugging.cpp +++ b/Security/libsecurity_utilities/lib/debugging.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_utilities/lib/debugging.h b/Security/libsecurity_utilities/lib/debugging.h new file mode 100644 index 00000000..36b25377 --- /dev/null +++ b/Security/libsecurity_utilities/lib/debugging.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +// +// debugging - non-trivial debug support +// +#ifndef _H_DEBUGGING +#define _H_DEBUGGING + + +#include + +#ifdef __cplusplus + +#include +#include +#include + +namespace Security { +namespace Debug { + + +// +// Debug-dumping functions always exist. They may be stubs depending on build options. +// +bool dumping(const char *scope); +void dump(const char *format, ...) __attribute((format(printf,1,2))); +void dumpData(const void *data, size_t length); +void dumpData(const char *title, const void *data, size_t length); +template inline void dumpData(const Data &obj) +{ dumpData(obj.data(), obj.length()); } +template inline void dumpData(const char *title, const Data &obj) +{ dumpData(title, obj.data(), obj.length()); } + + +// +// The following functions perform runtime recovery of type names. +// This is meant for debugging ONLY. Don't even THINK of depending +// on this for program correctness. For all you know, we may replace +// all those names with "XXX" tomorrow. +// +string makeTypeName(const type_info &info); + +template +string typeName(const Object &obj) +{ + return makeTypeName(typeid(obj)); +} + +template +string typeName() +{ + return makeTypeName(typeid(Object)); +} + + +// +// We are still conditionally emitting debug-dumping code +// +#undef DEBUGGING +#if !defined(NDEBUG) +# define DEBUGGING 1 +# define DEBUGDUMP 1 +#else //NDEBUG +# define DEBUGGING 0 +#endif //NDEBUG + +#if defined(DEBUGDUMP) +# define IFDUMP(code) code +# define IFDUMPING(scope,code) if (Debug::dumping(scope)) code; else /* no */ +#else +# define IFDUMP(code) /* no-op */ +# define IFDUMPING(scope,code) /* no-op */ +#endif + + +// +// We have some very, very old customers who call old debug facilities. +// Dummy them out for now. +// +inline bool debugging(const char *scope) DEPRECATED_ATTRIBUTE; +inline void debug(const char *scope, const char *format, ...) DEPRECATED_ATTRIBUTE; +inline void vdebug(const char *scope, const char *format, va_list args) DEPRECATED_ATTRIBUTE; + +inline bool debugging(const char *scope) { return false; } +inline void debug(const char *scope, const char *format, ...) { } +inline void vdebug(const char *scope, const char *format, va_list args) { } + + + + + +} // end namespace Debug +} // end namespace Security + +// leak debug() into the global namespace because URLAccess et al rely on that +using Security::Debug::debug; + +#else //__cplusplus + +#include + +#endif //__cplusplus + +#include + + +#endif //_H_DEBUGGING diff --git a/libsecurity_utilities/lib/debugging_internal.cpp b/Security/libsecurity_utilities/lib/debugging_internal.cpp similarity index 96% rename from libsecurity_utilities/lib/debugging_internal.cpp rename to Security/libsecurity_utilities/lib/debugging_internal.cpp index dc720607..83d2624c 100644 --- a/libsecurity_utilities/lib/debugging_internal.cpp +++ b/Security/libsecurity_utilities/lib/debugging_internal.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_utilities/lib/debugging_internal.h b/Security/libsecurity_utilities/lib/debugging_internal.h new file mode 100644 index 00000000..f4e7cb85 --- /dev/null +++ b/Security/libsecurity_utilities/lib/debugging_internal.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef libsecurity_utilities_debugging_internal_h +#define libsecurity_utilities_debugging_internal_h + + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +// +// Include DTrace static probe definitions +// +typedef const void *DTException; + +#include + +// +// The debug-log macro is now unconditionally emitted as a DTrace static probe point. +// + +void secdebug_internal(const char* scope, const char* format, ...); + +#define secdebug(scope, format...) secdebug_internal(scope, format) +#define secdebugf(scope, __msg) SECURITY_DEBUG_LOG((char *)(scope), (__msg)) + +// +// The old secdelay() macro is also emitted as a DTrace probe (use destructive actions to handle this). +// Secdelay() should be considered a legacy feature; just put a secdebug at the intended delay point. +// +#define secdelay(file) SECURITY_DEBUG_DELAY((char *)(file)) + + +#ifdef __cplusplus +}; +#endif // __cplusplus + +#endif diff --git a/libsecurity_utilities/lib/debugsupport.h b/Security/libsecurity_utilities/lib/debugsupport.h similarity index 98% rename from libsecurity_utilities/lib/debugsupport.h rename to Security/libsecurity_utilities/lib/debugsupport.h index bf2be9da..1d52fee3 100644 --- a/libsecurity_utilities/lib/debugsupport.h +++ b/Security/libsecurity_utilities/lib/debugsupport.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/devrandom.cpp b/Security/libsecurity_utilities/lib/devrandom.cpp similarity index 97% rename from libsecurity_utilities/lib/devrandom.cpp rename to Security/libsecurity_utilities/lib/devrandom.cpp index 86c05bc8..f08c2d97 100644 --- a/libsecurity_utilities/lib/devrandom.cpp +++ b/Security/libsecurity_utilities/lib/devrandom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/devrandom.h b/Security/libsecurity_utilities/lib/devrandom.h similarity index 96% rename from libsecurity_utilities/lib/devrandom.h rename to Security/libsecurity_utilities/lib/devrandom.h index 1d564140..adf38e6a 100644 --- a/libsecurity_utilities/lib/devrandom.h +++ b/Security/libsecurity_utilities/lib/devrandom.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/dtrace.mk b/Security/libsecurity_utilities/lib/dtrace.mk similarity index 100% rename from libsecurity_utilities/lib/dtrace.mk rename to Security/libsecurity_utilities/lib/dtrace.mk diff --git a/libsecurity_utilities/lib/dyld_cache_format.h b/Security/libsecurity_utilities/lib/dyld_cache_format.h similarity index 97% rename from libsecurity_utilities/lib/dyld_cache_format.h rename to Security/libsecurity_utilities/lib/dyld_cache_format.h index b322e381..0456197b 100644 --- a/libsecurity_utilities/lib/dyld_cache_format.h +++ b/Security/libsecurity_utilities/lib/dyld_cache_format.h @@ -1,6 +1,6 @@ /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- * - * Copyright (c) 2006-2009 Apple Inc. All rights reserved. + * Copyright (c) 2006-2009,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/dyldcache.cpp b/Security/libsecurity_utilities/lib/dyldcache.cpp similarity index 98% rename from libsecurity_utilities/lib/dyldcache.cpp rename to Security/libsecurity_utilities/lib/dyldcache.cpp index 267e52d8..ee67f261 100644 --- a/libsecurity_utilities/lib/dyldcache.cpp +++ b/Security/libsecurity_utilities/lib/dyldcache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2009,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/dyldcache.h b/Security/libsecurity_utilities/lib/dyldcache.h similarity index 98% rename from libsecurity_utilities/lib/dyldcache.h rename to Security/libsecurity_utilities/lib/dyldcache.h index c1e1ced4..4ff0a87a 100644 --- a/libsecurity_utilities/lib/dyldcache.h +++ b/Security/libsecurity_utilities/lib/dyldcache.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2009,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/endian.cpp b/Security/libsecurity_utilities/lib/endian.cpp similarity index 94% rename from libsecurity_utilities/lib/endian.cpp rename to Security/libsecurity_utilities/lib/endian.cpp index 0ac37f55..bfa6bcb3 100644 --- a/libsecurity_utilities/lib/endian.cpp +++ b/Security/libsecurity_utilities/lib/endian.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/endian.h b/Security/libsecurity_utilities/lib/endian.h similarity index 98% rename from libsecurity_utilities/lib/endian.h rename to Security/libsecurity_utilities/lib/endian.h index c004658b..5f96a103 100644 --- a/libsecurity_utilities/lib/endian.h +++ b/Security/libsecurity_utilities/lib/endian.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/errors.cpp b/Security/libsecurity_utilities/lib/errors.cpp similarity index 98% rename from libsecurity_utilities/lib/errors.cpp rename to Security/libsecurity_utilities/lib/errors.cpp index 58529775..57695adb 100644 --- a/libsecurity_utilities/lib/errors.cpp +++ b/Security/libsecurity_utilities/lib/errors.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/errors.h b/Security/libsecurity_utilities/lib/errors.h similarity index 98% rename from libsecurity_utilities/lib/errors.h rename to Security/libsecurity_utilities/lib/errors.h index 9208379a..6ff8ac45 100644 --- a/libsecurity_utilities/lib/errors.h +++ b/Security/libsecurity_utilities/lib/errors.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/exports b/Security/libsecurity_utilities/lib/exports similarity index 100% rename from libsecurity_utilities/lib/exports rename to Security/libsecurity_utilities/lib/exports diff --git a/libsecurity_utilities/lib/fdmover.cpp b/Security/libsecurity_utilities/lib/fdmover.cpp similarity index 97% rename from libsecurity_utilities/lib/fdmover.cpp rename to Security/libsecurity_utilities/lib/fdmover.cpp index 4e1713f8..0c20a8b7 100644 --- a/libsecurity_utilities/lib/fdmover.cpp +++ b/Security/libsecurity_utilities/lib/fdmover.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/fdmover.h b/Security/libsecurity_utilities/lib/fdmover.h similarity index 97% rename from libsecurity_utilities/lib/fdmover.h rename to Security/libsecurity_utilities/lib/fdmover.h index 9702b501..1116d4aa 100644 --- a/libsecurity_utilities/lib/fdmover.h +++ b/Security/libsecurity_utilities/lib/fdmover.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/fdsel.cpp b/Security/libsecurity_utilities/lib/fdsel.cpp similarity index 97% rename from libsecurity_utilities/lib/fdsel.cpp rename to Security/libsecurity_utilities/lib/fdsel.cpp index 56c4e044..3ea8f59e 100644 --- a/libsecurity_utilities/lib/fdsel.cpp +++ b/Security/libsecurity_utilities/lib/fdsel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/fdsel.h b/Security/libsecurity_utilities/lib/fdsel.h similarity index 97% rename from libsecurity_utilities/lib/fdsel.h rename to Security/libsecurity_utilities/lib/fdsel.h index 87056b1c..0ea54d4e 100644 --- a/libsecurity_utilities/lib/fdsel.h +++ b/Security/libsecurity_utilities/lib/fdsel.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/globalizer.cpp b/Security/libsecurity_utilities/lib/globalizer.cpp similarity index 97% rename from libsecurity_utilities/lib/globalizer.cpp rename to Security/libsecurity_utilities/lib/globalizer.cpp index c9ea7649..df5af3bc 100644 --- a/libsecurity_utilities/lib/globalizer.cpp +++ b/Security/libsecurity_utilities/lib/globalizer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/globalizer.h b/Security/libsecurity_utilities/lib/globalizer.h similarity index 98% rename from libsecurity_utilities/lib/globalizer.h rename to Security/libsecurity_utilities/lib/globalizer.h index 8a7e91a1..66480469 100644 --- a/libsecurity_utilities/lib/globalizer.h +++ b/Security/libsecurity_utilities/lib/globalizer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/hashing.cpp b/Security/libsecurity_utilities/lib/hashing.cpp similarity index 95% rename from libsecurity_utilities/lib/hashing.cpp rename to Security/libsecurity_utilities/lib/hashing.cpp index 5ce7b6fb..f900ca7f 100644 --- a/libsecurity_utilities/lib/hashing.cpp +++ b/Security/libsecurity_utilities/lib/hashing.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2005-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/hashing.h b/Security/libsecurity_utilities/lib/hashing.h similarity index 99% rename from libsecurity_utilities/lib/hashing.h rename to Security/libsecurity_utilities/lib/hashing.h index e931bd56..4188f5ff 100644 --- a/libsecurity_utilities/lib/hashing.h +++ b/Security/libsecurity_utilities/lib/hashing.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2005-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/headermap.cpp b/Security/libsecurity_utilities/lib/headermap.cpp similarity index 98% rename from libsecurity_utilities/lib/headermap.cpp rename to Security/libsecurity_utilities/lib/headermap.cpp index 80e8ce0d..8f6eebeb 100644 --- a/libsecurity_utilities/lib/headermap.cpp +++ b/Security/libsecurity_utilities/lib/headermap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/headermap.h b/Security/libsecurity_utilities/lib/headermap.h similarity index 97% rename from libsecurity_utilities/lib/headermap.h rename to Security/libsecurity_utilities/lib/headermap.h index 08355543..f989e92a 100644 --- a/libsecurity_utilities/lib/headermap.h +++ b/Security/libsecurity_utilities/lib/headermap.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/hosts.cpp b/Security/libsecurity_utilities/lib/hosts.cpp similarity index 98% rename from libsecurity_utilities/lib/hosts.cpp rename to Security/libsecurity_utilities/lib/hosts.cpp index 849f7bb6..2d15a909 100644 --- a/libsecurity_utilities/lib/hosts.cpp +++ b/Security/libsecurity_utilities/lib/hosts.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/hosts.h b/Security/libsecurity_utilities/lib/hosts.h similarity index 97% rename from libsecurity_utilities/lib/hosts.h rename to Security/libsecurity_utilities/lib/hosts.h index 8af78217..75d4b1ab 100644 --- a/libsecurity_utilities/lib/hosts.h +++ b/Security/libsecurity_utilities/lib/hosts.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/inetreply.cpp b/Security/libsecurity_utilities/lib/inetreply.cpp similarity index 97% rename from libsecurity_utilities/lib/inetreply.cpp rename to Security/libsecurity_utilities/lib/inetreply.cpp index 94ddb30e..1eaf8765 100644 --- a/libsecurity_utilities/lib/inetreply.cpp +++ b/Security/libsecurity_utilities/lib/inetreply.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/inetreply.h b/Security/libsecurity_utilities/lib/inetreply.h similarity index 97% rename from libsecurity_utilities/lib/inetreply.h rename to Security/libsecurity_utilities/lib/inetreply.h index 6d196790..014210eb 100644 --- a/libsecurity_utilities/lib/inetreply.h +++ b/Security/libsecurity_utilities/lib/inetreply.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/iodevices.cpp b/Security/libsecurity_utilities/lib/iodevices.cpp similarity index 99% rename from libsecurity_utilities/lib/iodevices.cpp rename to Security/libsecurity_utilities/lib/iodevices.cpp index f079ead5..28633d3e 100644 --- a/libsecurity_utilities/lib/iodevices.cpp +++ b/Security/libsecurity_utilities/lib/iodevices.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2007 Apple, Inc. All Rights Reserved. + * Copyright (c) 2004-2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/iodevices.h b/Security/libsecurity_utilities/lib/iodevices.h similarity index 98% rename from libsecurity_utilities/lib/iodevices.h rename to Security/libsecurity_utilities/lib/iodevices.h index b4da6d48..d0b04958 100644 --- a/libsecurity_utilities/lib/iodevices.h +++ b/Security/libsecurity_utilities/lib/iodevices.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/ip++.cpp b/Security/libsecurity_utilities/lib/ip++.cpp similarity index 99% rename from libsecurity_utilities/lib/ip++.cpp rename to Security/libsecurity_utilities/lib/ip++.cpp index cb152499..b589c11f 100644 --- a/libsecurity_utilities/lib/ip++.cpp +++ b/Security/libsecurity_utilities/lib/ip++.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/ip++.h b/Security/libsecurity_utilities/lib/ip++.h similarity index 99% rename from libsecurity_utilities/lib/ip++.h rename to Security/libsecurity_utilities/lib/ip++.h index 39cb3f8f..306c4ab6 100644 --- a/libsecurity_utilities/lib/ip++.h +++ b/Security/libsecurity_utilities/lib/ip++.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/kq++.cpp b/Security/libsecurity_utilities/lib/kq++.cpp similarity index 96% rename from libsecurity_utilities/lib/kq++.cpp rename to Security/libsecurity_utilities/lib/kq++.cpp index db221e9a..4267c778 100644 --- a/libsecurity_utilities/lib/kq++.cpp +++ b/Security/libsecurity_utilities/lib/kq++.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2009,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/kq++.h b/Security/libsecurity_utilities/lib/kq++.h similarity index 97% rename from libsecurity_utilities/lib/kq++.h rename to Security/libsecurity_utilities/lib/kq++.h index f9f3065e..c27eb376 100644 --- a/libsecurity_utilities/lib/kq++.h +++ b/Security/libsecurity_utilities/lib/kq++.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2009,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/ktracecodes.h b/Security/libsecurity_utilities/lib/ktracecodes.h similarity index 99% rename from libsecurity_utilities/lib/ktracecodes.h rename to Security/libsecurity_utilities/lib/ktracecodes.h index e967dbaf..415277ac 100644 --- a/libsecurity_utilities/lib/ktracecodes.h +++ b/Security/libsecurity_utilities/lib/ktracecodes.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/logging.cpp b/Security/libsecurity_utilities/lib/logging.cpp similarity index 97% rename from libsecurity_utilities/lib/logging.cpp rename to Security/libsecurity_utilities/lib/logging.cpp index 0aa8d63b..25c2ba94 100644 --- a/libsecurity_utilities/lib/logging.cpp +++ b/Security/libsecurity_utilities/lib/logging.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/logging.h b/Security/libsecurity_utilities/lib/logging.h similarity index 95% rename from libsecurity_utilities/lib/logging.h rename to Security/libsecurity_utilities/lib/logging.h index 507b5c89..678c4834 100644 --- a/libsecurity_utilities/lib/logging.h +++ b/Security/libsecurity_utilities/lib/logging.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/mach++.cpp b/Security/libsecurity_utilities/lib/mach++.cpp similarity index 99% rename from libsecurity_utilities/lib/mach++.cpp rename to Security/libsecurity_utilities/lib/mach++.cpp index c663d4c0..f0ba24b7 100644 --- a/libsecurity_utilities/lib/mach++.cpp +++ b/Security/libsecurity_utilities/lib/mach++.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/mach++.h b/Security/libsecurity_utilities/lib/mach++.h similarity index 99% rename from libsecurity_utilities/lib/mach++.h rename to Security/libsecurity_utilities/lib/mach++.h index 57356828..f87b4a3c 100644 --- a/libsecurity_utilities/lib/mach++.h +++ b/Security/libsecurity_utilities/lib/mach++.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/mach_notify.c b/Security/libsecurity_utilities/lib/mach_notify.c similarity index 99% rename from libsecurity_utilities/lib/mach_notify.c rename to Security/libsecurity_utilities/lib/mach_notify.c index d0fc9cea..41c162a9 100644 --- a/libsecurity_utilities/lib/mach_notify.c +++ b/Security/libsecurity_utilities/lib/mach_notify.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2002,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2001-2002,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/mach_notify.h b/Security/libsecurity_utilities/lib/mach_notify.h similarity index 98% rename from libsecurity_utilities/lib/mach_notify.h rename to Security/libsecurity_utilities/lib/mach_notify.h index cb3daa52..86853c6b 100644 --- a/libsecurity_utilities/lib/mach_notify.h +++ b/Security/libsecurity_utilities/lib/mach_notify.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/macho++.cpp b/Security/libsecurity_utilities/lib/macho++.cpp similarity index 98% rename from libsecurity_utilities/lib/macho++.cpp rename to Security/libsecurity_utilities/lib/macho++.cpp index ff26e594..cfd448ab 100644 --- a/libsecurity_utilities/lib/macho++.cpp +++ b/Security/libsecurity_utilities/lib/macho++.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2013 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -337,6 +337,10 @@ const section *MachOBase::findSection(const char *segname, const char *sectname) if (const segment_command *seg = findSegment(segname)) { if (is64()) { const segment_command_64 *seg64 = reinterpret_cast(seg); + // As a sanity check, if the reported number of sections is not consistent + // with the reported size, return NULL + if (sizeof(*seg64) + (seg64->nsects * sizeof(section_64)) > seg64->cmdsize) + return NULL; const section_64 *sect = increment(seg64 + 1, 0); for (unsigned n = flip(seg64->nsects); n > 0; n--, sect++) { if (!strcmp(sect->sectname, sectname)) @@ -462,6 +466,10 @@ Universal::Universal(FileDesc fd, size_t offset /* = 0 */, size_t length /* = 0 // we are content to fail. // mArchCount = ntohl(header.nfat_arch); + + if (mArchCount > MAX_ARCH_COUNT) + UnixError::throwMe(ENOEXEC); + size_t archSize = sizeof(fat_arch) * (mArchCount + 1); mArchList = (fat_arch *)malloc(archSize); if (!mArchList) diff --git a/libsecurity_utilities/lib/macho++.h b/Security/libsecurity_utilities/lib/macho++.h similarity index 99% rename from libsecurity_utilities/lib/macho++.h rename to Security/libsecurity_utilities/lib/macho++.h index 4cfc6ba1..093cc5b4 100644 --- a/libsecurity_utilities/lib/macho++.h +++ b/Security/libsecurity_utilities/lib/macho++.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -205,14 +205,14 @@ public: // return a set of architectures contained typedef std::set Architectures; void architectures(Architectures &archs) const; - + bool isUniversal() const { return mArchList != NULL; } Architecture bestNativeArch() const; const size_t lengthOfSlice(size_t offset) const; - + size_t offset() const { return mBase; } size_t length() const { return mLength; } - + bool isSuspicious() const; public: diff --git a/libsecurity_utilities/lib/machrunloopserver.cpp b/Security/libsecurity_utilities/lib/machrunloopserver.cpp similarity index 97% rename from libsecurity_utilities/lib/machrunloopserver.cpp rename to Security/libsecurity_utilities/lib/machrunloopserver.cpp index a4cb1284..38021594 100644 --- a/libsecurity_utilities/lib/machrunloopserver.cpp +++ b/Security/libsecurity_utilities/lib/machrunloopserver.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/machrunloopserver.h b/Security/libsecurity_utilities/lib/machrunloopserver.h similarity index 96% rename from libsecurity_utilities/lib/machrunloopserver.h rename to Security/libsecurity_utilities/lib/machrunloopserver.h index da7f656d..c5df09e9 100644 --- a/libsecurity_utilities/lib/machrunloopserver.h +++ b/Security/libsecurity_utilities/lib/machrunloopserver.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/machserver.cpp b/Security/libsecurity_utilities/lib/machserver.cpp similarity index 99% rename from libsecurity_utilities/lib/machserver.cpp rename to Security/libsecurity_utilities/lib/machserver.cpp index c036e617..82434ef2 100644 --- a/libsecurity_utilities/lib/machserver.cpp +++ b/Security/libsecurity_utilities/lib/machserver.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2007,2011-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/machserver.h b/Security/libsecurity_utilities/lib/machserver.h similarity index 99% rename from libsecurity_utilities/lib/machserver.h rename to Security/libsecurity_utilities/lib/machserver.h index d1a9bc46..972aa9de 100644 --- a/libsecurity_utilities/lib/machserver.h +++ b/Security/libsecurity_utilities/lib/machserver.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2007,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/memstreams.h b/Security/libsecurity_utilities/lib/memstreams.h similarity index 98% rename from libsecurity_utilities/lib/memstreams.h rename to Security/libsecurity_utilities/lib/memstreams.h index bef8d462..0c7ac496 100644 --- a/libsecurity_utilities/lib/memstreams.h +++ b/Security/libsecurity_utilities/lib/memstreams.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/memutils.h b/Security/libsecurity_utilities/lib/memutils.h similarity index 98% rename from libsecurity_utilities/lib/memutils.h rename to Security/libsecurity_utilities/lib/memutils.h index be9369c4..035aee1c 100644 --- a/libsecurity_utilities/lib/memutils.h +++ b/Security/libsecurity_utilities/lib/memutils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/muscle++.cpp b/Security/libsecurity_utilities/lib/muscle++.cpp similarity index 98% rename from libsecurity_utilities/lib/muscle++.cpp rename to Security/libsecurity_utilities/lib/muscle++.cpp index a50a4cbd..d1841472 100644 --- a/libsecurity_utilities/lib/muscle++.cpp +++ b/Security/libsecurity_utilities/lib/muscle++.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/muscle++.h b/Security/libsecurity_utilities/lib/muscle++.h similarity index 98% rename from libsecurity_utilities/lib/muscle++.h rename to Security/libsecurity_utilities/lib/muscle++.h index e79eaf6f..f1a2f2f7 100644 --- a/libsecurity_utilities/lib/muscle++.h +++ b/Security/libsecurity_utilities/lib/muscle++.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/osxcode.cpp b/Security/libsecurity_utilities/lib/osxcode.cpp similarity index 99% rename from libsecurity_utilities/lib/osxcode.cpp rename to Security/libsecurity_utilities/lib/osxcode.cpp index f1b10f75..51c01007 100644 --- a/libsecurity_utilities/lib/osxcode.cpp +++ b/Security/libsecurity_utilities/lib/osxcode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_utilities/lib/osxcode.h b/Security/libsecurity_utilities/lib/osxcode.h similarity index 98% rename from libsecurity_utilities/lib/osxcode.h rename to Security/libsecurity_utilities/lib/osxcode.h index 849c4fdd..664fd101 100644 --- a/libsecurity_utilities/lib/osxcode.h +++ b/Security/libsecurity_utilities/lib/osxcode.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). diff --git a/libsecurity_utilities/lib/pcsc++.cpp b/Security/libsecurity_utilities/lib/pcsc++.cpp similarity index 98% rename from libsecurity_utilities/lib/pcsc++.cpp rename to Security/libsecurity_utilities/lib/pcsc++.cpp index c0d6a16a..0a79de0e 100644 --- a/libsecurity_utilities/lib/pcsc++.cpp +++ b/Security/libsecurity_utilities/lib/pcsc++.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -223,8 +223,6 @@ void Session::listReaders(vector &readers, const char *groups) // void Session::statusChange(ReaderState *readers, unsigned int nReaders, long timeout) { - if (nReaders == 0) - return; // no readers, no foul check(::SCardGetStatusChange(mContext, (uint32_t)timeout, readers, nReaders)); } diff --git a/libsecurity_utilities/lib/pcsc++.h b/Security/libsecurity_utilities/lib/pcsc++.h similarity index 98% rename from libsecurity_utilities/lib/pcsc++.h rename to Security/libsecurity_utilities/lib/pcsc++.h index 40d13953..66ba4b4a 100644 --- a/libsecurity_utilities/lib/pcsc++.h +++ b/Security/libsecurity_utilities/lib/pcsc++.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/powerwatch.cpp b/Security/libsecurity_utilities/lib/powerwatch.cpp similarity index 99% rename from libsecurity_utilities/lib/powerwatch.cpp rename to Security/libsecurity_utilities/lib/powerwatch.cpp index 9c197af2..f4e9e42f 100644 --- a/libsecurity_utilities/lib/powerwatch.cpp +++ b/Security/libsecurity_utilities/lib/powerwatch.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/powerwatch.h b/Security/libsecurity_utilities/lib/powerwatch.h similarity index 97% rename from libsecurity_utilities/lib/powerwatch.h rename to Security/libsecurity_utilities/lib/powerwatch.h index cfde5fe3..d93eac5a 100644 --- a/libsecurity_utilities/lib/powerwatch.h +++ b/Security/libsecurity_utilities/lib/powerwatch.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/refcount.h b/Security/libsecurity_utilities/lib/refcount.h similarity index 97% rename from libsecurity_utilities/lib/refcount.h rename to Security/libsecurity_utilities/lib/refcount.h index e68cf718..677376c5 100644 --- a/libsecurity_utilities/lib/refcount.h +++ b/Security/libsecurity_utilities/lib/refcount.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,7 +23,6 @@ /* - Based on code donated by Perry Kiehtreiber */ #ifndef _SECURITY_REFCOUNT_H_ #define _SECURITY_REFCOUNT_H_ diff --git a/libsecurity_utilities/lib/seccfobject.cpp b/Security/libsecurity_utilities/lib/seccfobject.cpp similarity index 98% rename from libsecurity_utilities/lib/seccfobject.cpp rename to Security/libsecurity_utilities/lib/seccfobject.cpp index 43b716b7..142a2730 100644 --- a/libsecurity_utilities/lib/seccfobject.cpp +++ b/Security/libsecurity_utilities/lib/seccfobject.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/seccfobject.h b/Security/libsecurity_utilities/lib/seccfobject.h similarity index 98% rename from libsecurity_utilities/lib/seccfobject.h rename to Security/libsecurity_utilities/lib/seccfobject.h index 311a202d..2717d755 100644 --- a/libsecurity_utilities/lib/seccfobject.h +++ b/Security/libsecurity_utilities/lib/seccfobject.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/security_utilities.d b/Security/libsecurity_utilities/lib/security_utilities.d similarity index 100% rename from libsecurity_utilities/lib/security_utilities.d rename to Security/libsecurity_utilities/lib/security_utilities.d diff --git a/libsecurity_utilities/lib/security_utilities.h b/Security/libsecurity_utilities/lib/security_utilities.h similarity index 97% rename from libsecurity_utilities/lib/security_utilities.h rename to Security/libsecurity_utilities/lib/security_utilities.h index b0569ed5..37ccc776 100644 --- a/libsecurity_utilities/lib/security_utilities.h +++ b/Security/libsecurity_utilities/lib/security_utilities.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/selector.cpp b/Security/libsecurity_utilities/lib/selector.cpp similarity index 98% rename from libsecurity_utilities/lib/selector.cpp rename to Security/libsecurity_utilities/lib/selector.cpp index d636ac7e..e3f115a7 100644 --- a/libsecurity_utilities/lib/selector.cpp +++ b/Security/libsecurity_utilities/lib/selector.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/selector.h b/Security/libsecurity_utilities/lib/selector.h similarity index 98% rename from libsecurity_utilities/lib/selector.h rename to Security/libsecurity_utilities/lib/selector.h index 81803c2a..88ca753f 100644 --- a/libsecurity_utilities/lib/selector.h +++ b/Security/libsecurity_utilities/lib/selector.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/simpleprefs.cpp b/Security/libsecurity_utilities/lib/simpleprefs.cpp similarity index 99% rename from libsecurity_utilities/lib/simpleprefs.cpp rename to Security/libsecurity_utilities/lib/simpleprefs.cpp index 08395326..105f20b7 100644 --- a/libsecurity_utilities/lib/simpleprefs.cpp +++ b/Security/libsecurity_utilities/lib/simpleprefs.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/simpleprefs.h b/Security/libsecurity_utilities/lib/simpleprefs.h similarity index 98% rename from libsecurity_utilities/lib/simpleprefs.h rename to Security/libsecurity_utilities/lib/simpleprefs.h index d091dfc5..87d7f645 100644 --- a/libsecurity_utilities/lib/simpleprefs.h +++ b/Security/libsecurity_utilities/lib/simpleprefs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/socks++.cpp b/Security/libsecurity_utilities/lib/socks++.cpp similarity index 98% rename from libsecurity_utilities/lib/socks++.cpp rename to Security/libsecurity_utilities/lib/socks++.cpp index 96d42292..0ab7d50c 100644 --- a/libsecurity_utilities/lib/socks++.cpp +++ b/Security/libsecurity_utilities/lib/socks++.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/socks++.h b/Security/libsecurity_utilities/lib/socks++.h similarity index 99% rename from libsecurity_utilities/lib/socks++.h rename to Security/libsecurity_utilities/lib/socks++.h index e885fec2..ffd49a95 100644 --- a/libsecurity_utilities/lib/socks++.h +++ b/Security/libsecurity_utilities/lib/socks++.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/socks++4.cpp b/Security/libsecurity_utilities/lib/socks++4.cpp similarity index 98% rename from libsecurity_utilities/lib/socks++4.cpp rename to Security/libsecurity_utilities/lib/socks++4.cpp index 3b9f9ab7..1f6908b0 100644 --- a/libsecurity_utilities/lib/socks++4.cpp +++ b/Security/libsecurity_utilities/lib/socks++4.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/socks++4.h b/Security/libsecurity_utilities/lib/socks++4.h similarity index 97% rename from libsecurity_utilities/lib/socks++4.h rename to Security/libsecurity_utilities/lib/socks++4.h index 45c48a27..8a82af8e 100644 --- a/libsecurity_utilities/lib/socks++4.h +++ b/Security/libsecurity_utilities/lib/socks++4.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/socks++5.cpp b/Security/libsecurity_utilities/lib/socks++5.cpp similarity index 98% rename from libsecurity_utilities/lib/socks++5.cpp rename to Security/libsecurity_utilities/lib/socks++5.cpp index 280f1549..0aa6cc31 100644 --- a/libsecurity_utilities/lib/socks++5.cpp +++ b/Security/libsecurity_utilities/lib/socks++5.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/socks++5.h b/Security/libsecurity_utilities/lib/socks++5.h similarity index 98% rename from libsecurity_utilities/lib/socks++5.h rename to Security/libsecurity_utilities/lib/socks++5.h index 0c6bbb03..5bcb9129 100644 --- a/libsecurity_utilities/lib/socks++5.h +++ b/Security/libsecurity_utilities/lib/socks++5.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/sqlite++.cpp b/Security/libsecurity_utilities/lib/sqlite++.cpp similarity index 99% rename from libsecurity_utilities/lib/sqlite++.cpp rename to Security/libsecurity_utilities/lib/sqlite++.cpp index e5744d93..03c9233e 100644 --- a/libsecurity_utilities/lib/sqlite++.cpp +++ b/Security/libsecurity_utilities/lib/sqlite++.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2008,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/sqlite++.h b/Security/libsecurity_utilities/lib/sqlite++.h similarity index 99% rename from libsecurity_utilities/lib/sqlite++.h rename to Security/libsecurity_utilities/lib/sqlite++.h index 1b3894f7..888fcc8e 100644 --- a/libsecurity_utilities/lib/sqlite++.h +++ b/Security/libsecurity_utilities/lib/sqlite++.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2008,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/streams.cpp b/Security/libsecurity_utilities/lib/streams.cpp similarity index 97% rename from libsecurity_utilities/lib/streams.cpp rename to Security/libsecurity_utilities/lib/streams.cpp index fb459d7c..2a37b98c 100644 --- a/libsecurity_utilities/lib/streams.cpp +++ b/Security/libsecurity_utilities/lib/streams.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/streams.h b/Security/libsecurity_utilities/lib/streams.h similarity index 98% rename from libsecurity_utilities/lib/streams.h rename to Security/libsecurity_utilities/lib/streams.h index ea29ddc3..0d2036d7 100644 --- a/libsecurity_utilities/lib/streams.h +++ b/Security/libsecurity_utilities/lib/streams.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/superblob.cpp b/Security/libsecurity_utilities/lib/superblob.cpp similarity index 100% rename from libsecurity_utilities/lib/superblob.cpp rename to Security/libsecurity_utilities/lib/superblob.cpp diff --git a/libsecurity_utilities/lib/superblob.h b/Security/libsecurity_utilities/lib/superblob.h similarity index 100% rename from libsecurity_utilities/lib/superblob.h rename to Security/libsecurity_utilities/lib/superblob.h diff --git a/libsecurity_utilities/lib/threading.cpp b/Security/libsecurity_utilities/lib/threading.cpp similarity index 98% rename from libsecurity_utilities/lib/threading.cpp rename to Security/libsecurity_utilities/lib/threading.cpp index 0d387181..9e0bed64 100644 --- a/libsecurity_utilities/lib/threading.cpp +++ b/Security/libsecurity_utilities/lib/threading.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/threading.h b/Security/libsecurity_utilities/lib/threading.h similarity index 99% rename from libsecurity_utilities/lib/threading.h rename to Security/libsecurity_utilities/lib/threading.h index 41570305..a903dc10 100644 --- a/libsecurity_utilities/lib/threading.h +++ b/Security/libsecurity_utilities/lib/threading.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/threading_internal.h b/Security/libsecurity_utilities/lib/threading_internal.h similarity index 98% rename from libsecurity_utilities/lib/threading_internal.h rename to Security/libsecurity_utilities/lib/threading_internal.h index b3b6854f..dc7af307 100644 --- a/libsecurity_utilities/lib/threading_internal.h +++ b/Security/libsecurity_utilities/lib/threading_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/timeflow.cpp b/Security/libsecurity_utilities/lib/timeflow.cpp similarity index 97% rename from libsecurity_utilities/lib/timeflow.cpp rename to Security/libsecurity_utilities/lib/timeflow.cpp index 0f1963f1..b8c70448 100644 --- a/libsecurity_utilities/lib/timeflow.cpp +++ b/Security/libsecurity_utilities/lib/timeflow.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/timeflow.h b/Security/libsecurity_utilities/lib/timeflow.h similarity index 98% rename from libsecurity_utilities/lib/timeflow.h rename to Security/libsecurity_utilities/lib/timeflow.h index 1d008f83..1669bfcb 100644 --- a/libsecurity_utilities/lib/timeflow.h +++ b/Security/libsecurity_utilities/lib/timeflow.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/tqueue.cpp b/Security/libsecurity_utilities/lib/tqueue.cpp similarity index 94% rename from libsecurity_utilities/lib/tqueue.cpp rename to Security/libsecurity_utilities/lib/tqueue.cpp index 2b216806..08fae25a 100644 --- a/libsecurity_utilities/lib/tqueue.cpp +++ b/Security/libsecurity_utilities/lib/tqueue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/tqueue.h b/Security/libsecurity_utilities/lib/tqueue.h similarity index 98% rename from libsecurity_utilities/lib/tqueue.h rename to Security/libsecurity_utilities/lib/tqueue.h index fe716f03..571061c8 100644 --- a/libsecurity_utilities/lib/tqueue.h +++ b/Security/libsecurity_utilities/lib/tqueue.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/trackingallocator.cpp b/Security/libsecurity_utilities/lib/trackingallocator.cpp similarity index 97% rename from libsecurity_utilities/lib/trackingallocator.cpp rename to Security/libsecurity_utilities/lib/trackingallocator.cpp index c2075501..33650037 100644 --- a/libsecurity_utilities/lib/trackingallocator.cpp +++ b/Security/libsecurity_utilities/lib/trackingallocator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/trackingallocator.h b/Security/libsecurity_utilities/lib/trackingallocator.h similarity index 96% rename from libsecurity_utilities/lib/trackingallocator.h rename to Security/libsecurity_utilities/lib/trackingallocator.h index 80a9df46..01e2ccce 100644 --- a/libsecurity_utilities/lib/trackingallocator.h +++ b/Security/libsecurity_utilities/lib/trackingallocator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/transactions.cpp b/Security/libsecurity_utilities/lib/transactions.cpp similarity index 95% rename from libsecurity_utilities/lib/transactions.cpp rename to Security/libsecurity_utilities/lib/transactions.cpp index 1dc6d60d..be165b5a 100644 --- a/libsecurity_utilities/lib/transactions.cpp +++ b/Security/libsecurity_utilities/lib/transactions.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/transactions.h b/Security/libsecurity_utilities/lib/transactions.h similarity index 97% rename from libsecurity_utilities/lib/transactions.h rename to Security/libsecurity_utilities/lib/transactions.h index 95cec2ca..dc236a5b 100644 --- a/libsecurity_utilities/lib/transactions.h +++ b/Security/libsecurity_utilities/lib/transactions.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/typedvalue.cpp b/Security/libsecurity_utilities/lib/typedvalue.cpp similarity index 94% rename from libsecurity_utilities/lib/typedvalue.cpp rename to Security/libsecurity_utilities/lib/typedvalue.cpp index ff3899ae..2864be1f 100644 --- a/libsecurity_utilities/lib/typedvalue.cpp +++ b/Security/libsecurity_utilities/lib/typedvalue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/typedvalue.h b/Security/libsecurity_utilities/lib/typedvalue.h similarity index 97% rename from libsecurity_utilities/lib/typedvalue.h rename to Security/libsecurity_utilities/lib/typedvalue.h index dc1f775a..5f7d2298 100644 --- a/libsecurity_utilities/lib/typedvalue.h +++ b/Security/libsecurity_utilities/lib/typedvalue.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/unix++.cpp b/Security/libsecurity_utilities/lib/unix++.cpp similarity index 99% rename from libsecurity_utilities/lib/unix++.cpp rename to Security/libsecurity_utilities/lib/unix++.cpp index 57bc9c9d..d00dee77 100644 --- a/libsecurity_utilities/lib/unix++.cpp +++ b/Security/libsecurity_utilities/lib/unix++.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -352,7 +352,6 @@ bool FileDesc::isPlainFile(const std::string &path) return (st1.st_ino == st2.st_ino && S_ISREG(st2.st_mode)); } - // // Stat support // diff --git a/libsecurity_utilities/lib/unix++.h b/Security/libsecurity_utilities/lib/unix++.h similarity index 99% rename from libsecurity_utilities/lib/unix++.h rename to Security/libsecurity_utilities/lib/unix++.h index f9dbe92f..c7e098b9 100644 --- a/libsecurity_utilities/lib/unix++.h +++ b/Security/libsecurity_utilities/lib/unix++.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/unixchild.cpp b/Security/libsecurity_utilities/lib/unixchild.cpp similarity index 99% rename from libsecurity_utilities/lib/unixchild.cpp rename to Security/libsecurity_utilities/lib/unixchild.cpp index c65ee5a9..0cb3d918 100644 --- a/libsecurity_utilities/lib/unixchild.cpp +++ b/Security/libsecurity_utilities/lib/unixchild.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/unixchild.h b/Security/libsecurity_utilities/lib/unixchild.h similarity index 98% rename from libsecurity_utilities/lib/unixchild.h rename to Security/libsecurity_utilities/lib/unixchild.h index b9ff5a51..46e8048b 100644 --- a/libsecurity_utilities/lib/unixchild.h +++ b/Security/libsecurity_utilities/lib/unixchild.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/url.cpp b/Security/libsecurity_utilities/lib/url.cpp similarity index 98% rename from libsecurity_utilities/lib/url.cpp rename to Security/libsecurity_utilities/lib/url.cpp index 8fbf93db..86f7eeb1 100644 --- a/libsecurity_utilities/lib/url.cpp +++ b/Security/libsecurity_utilities/lib/url.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/url.h b/Security/libsecurity_utilities/lib/url.h similarity index 96% rename from libsecurity_utilities/lib/url.h rename to Security/libsecurity_utilities/lib/url.h index 72d74c97..d038a903 100644 --- a/libsecurity_utilities/lib/url.h +++ b/Security/libsecurity_utilities/lib/url.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002,2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2002,2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/utilities.cpp b/Security/libsecurity_utilities/lib/utilities.cpp similarity index 98% rename from libsecurity_utilities/lib/utilities.cpp rename to Security/libsecurity_utilities/lib/utilities.cpp index 8fc50818..d1598c28 100644 --- a/libsecurity_utilities/lib/utilities.cpp +++ b/Security/libsecurity_utilities/lib/utilities.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurity_utilities/lib/utilities.h b/Security/libsecurity_utilities/lib/utilities.h new file mode 100644 index 00000000..2bd28d56 --- /dev/null +++ b/Security/libsecurity_utilities/lib/utilities.h @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* + * cssm utilities + */ +#ifndef _H_UTILITIES +#define _H_UTILITIES + +#include +#include +#include +#include +#include +#include + +namespace Security +{ + +// +// Elementary debugging support. +// #include for more debugging facilities. +// +#define IFDEBUG(it) IFELSEDEBUG(it,) +#define IFNDEBUG(it) IFELSEDEBUG(,it) + +#if defined(NDEBUG) + +# define safe_cast static_cast +# define safer_cast static_cast + +# define IFELSEDEBUG(d,nd) nd + +#else + +template +inline Derived safer_cast(Base &base) +{ + return dynamic_cast(base); +} + +template +inline Derived safe_cast(Base *base) +{ + if (base == NULL) + return NULL; // okay to cast NULL to NULL + Derived p = dynamic_cast(base); + assert(p); + return p; +} + +# define IFELSEDEBUG(d,nd) d + +#endif //NDEBUG + + +// +// Place this into your class definition if you don't want it to be copyable +// or asignable. This will not prohibit allocation on the stack or in static +// memory, but it will make anything derived from it, and anything containing +// it, fixed-once-created. A proper object, I suppose. +// +#define NOCOPY(Type) \ + private: Type(const Type &) DEPRECATED_IN_MAC_OS_X_VERSION_10_0_AND_LATER; \ + void operator = (const Type &) DEPRECATED_IN_MAC_OS_X_VERSION_10_0_AND_LATER; + + +// +// Helpers for memory pointer validation +// +#define MY_CSSM_ERRCODE_INVALID_POINTER 0x0004 +template +inline T &Required(T *ptr, OSStatus err = MY_CSSM_ERRCODE_INVALID_POINTER) +{ + if (ptr == NULL) + MacOSError::throwMe(err); + return *ptr; +} + +// specialization for void * (just check for non-null; don't return a void & :-) +inline void Required(void *ptr, OSStatus err = MY_CSSM_ERRCODE_INVALID_POINTER) +{ + if (ptr == NULL) + MacOSError::throwMe(err); +} + + +// +// Tools to build POD wrapper classes +// +template +class PodWrapper : public POD { +public: + // pure typecasts + static Wrapper * &overlayVar(POD * &data) + { return reinterpret_cast(data); } + static const Wrapper * &overlayVar(const POD * &data) + { return reinterpret_cast(data); } + + static Wrapper *overlay(POD *data) + { return static_cast(data); } + static const Wrapper *overlay(const POD *data) + { return static_cast(data); } + static Wrapper &overlay(POD &data) + { return static_cast(data); } + static const Wrapper &overlay(const POD &data) + { return static_cast(data); } + + // optional/required forms + static Wrapper &required(POD *data) + { return overlay(Required(data)); } + static const Wrapper &required(const POD *data) + { return overlay(Required(data)); } + static Wrapper *optional(POD *data) + { return overlay(data); } + static const Wrapper *optional(const POD *data) + { return overlay(data); } + + // general helpers for all PodWrappers + void clearPod() + { memset(static_cast(this), 0, sizeof(POD)); } + + void assignPod(const POD &source) + { static_cast(*this) = source; } +}; + + +// +// Template builder support +// +template +struct Nonconst { + typedef T Type; +}; + +template +struct Nonconst { + typedef U Type; +}; + +template +struct Nonconst { + typedef U *Type; +}; + +// cast away pointed-to constness +template +typename Nonconst::Type unconst_cast(T obj) +{ + return const_cast::Type>(obj); +} + +template +typename Nonconst::Type &unconst_ref_cast(T &obj) +{ + return const_cast::Type &>(obj); +} + + +// Help with container of something->pointer cleanup +template +static inline void for_each_delete(In first, In last) +{ + while (first != last) + delete *(first++); +} + +// Help with map of something->pointer cleanup +template +static inline void for_each_map_delete(In first, In last) +{ + while (first != last) + delete (first++)->second; +} + +// versions of copy that project to pair elements +template +inline OutIterator copy_first(InIterator first, InIterator last, OutIterator out) +{ + while (first != last) + *out++ = (first++)->first; + return out; +} + +template +inline OutIterator copy_second(InIterator first, InIterator last, OutIterator out) +{ + while (first != last) + *out++ = (first++)->second; + return out; +} + + +// simple safe re-entry blocker +class RecursionBlock { +public: + RecursionBlock() : mActive(false) { } + ~RecursionBlock() { assert(!mActive); } + +public: + class Once { + public: + Once(RecursionBlock &rb) : block(rb), mActive(false) { } + ~Once() { block.mActive &= !mActive; } + bool operator () () + { if (block.mActive) return true; mActive = block.mActive = true; return false; } + + RecursionBlock █ + + private: + bool mActive; + }; + friend class Once; + +private: + bool mActive; +}; + +// Quick and dirty template for a (temporary) array of something +// Usage example auto_array anArray(20); +template +class auto_array +{ +public: + auto_array() : mArray(NULL) {} + auto_array(size_t inSize) : mArray(new T[inSize]) {} + ~auto_array() { if (mArray) delete[] mArray; } + T &operator[](size_t inIndex) { return mArray[inIndex]; } + void allocate(size_t inSize) { if (mArray) delete[] mArray; mArray = new T[inSize]; } + T *get() { return mArray; } + T *release() { T *anArray = mArray; mArray = NULL; return anArray; } +private: + T *mArray; +}; + +// Template for a vector-like class that takes a c-array as it's +// underlying storage without making a copy. +template +class constVector +{ + NOCOPY(constVector<_Tp>) +public: + typedef _Tp value_type; + typedef const value_type* const_pointer; + typedef const value_type* const_iterator; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + typedef std::reverse_iterator const_reverse_iterator; +public: + const_iterator begin() const { return _M_start; } + const_iterator end() const { return _M_finish; } + + const_reverse_iterator rbegin() const + { return const_reverse_iterator(end()); } + const_reverse_iterator rend() const + { return const_reverse_iterator(begin()); } + + size_type size() const + { return size_type(end() - begin()); } + bool empty() const + { return begin() == end(); } + + const_reference operator[](size_type __n) const { return *(begin() + __n); } + + // "at" will eventually have range checking, once we have the + // infrastructure to be able to throw stl range errors. + const_reference at(size_type n) const { return (*this)[n]; } + + constVector(size_type __n, const _Tp* __value) + : _M_start(__value), _M_finish(__value + __n) + {} + + constVector() : _M_start(NULL), _M_finish(NULL) {} + + void overlay(size_type __n, const _Tp* __value) { + _M_start = __value; + _M_finish = __value + __n; + } + + const_reference front() const { return *begin(); } + const_reference back() const { return *(end() - 1); } +private: + const _Tp *_M_start; + const _Tp *_M_finish; +}; + +char *cached_realpath(const char * file_name, char * resolved_name); + +} // end namespace Security + + +#endif //_H_UTILITIES diff --git a/libsecurity_utilities/lib/utility_config.h b/Security/libsecurity_utilities/lib/utility_config.h similarity index 97% rename from libsecurity_utilities/lib/utility_config.h rename to Security/libsecurity_utilities/lib/utility_config.h index cf8ca88e..7919078e 100644 --- a/libsecurity_utilities/lib/utility_config.h +++ b/Security/libsecurity_utilities/lib/utility_config.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/vproc++.cpp b/Security/libsecurity_utilities/lib/vproc++.cpp similarity index 95% rename from libsecurity_utilities/lib/vproc++.cpp rename to Security/libsecurity_utilities/lib/vproc++.cpp index 500575f8..7dd41bd8 100644 --- a/libsecurity_utilities/lib/vproc++.cpp +++ b/Security/libsecurity_utilities/lib/vproc++.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2008,2011,2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/lib/vproc++.h b/Security/libsecurity_utilities/lib/vproc++.h similarity index 96% rename from libsecurity_utilities/lib/vproc++.h rename to Security/libsecurity_utilities/lib/vproc++.h index 3e7816a4..8dcef402 100644 --- a/libsecurity_utilities/lib/vproc++.h +++ b/Security/libsecurity_utilities/lib/vproc++.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2008,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurity_utilities/libsecurity_utilities.xcodeproj/project.pbxproj b/Security/libsecurity_utilities/libsecurity_utilities.xcodeproj/project.pbxproj similarity index 100% rename from libsecurity_utilities/libsecurity_utilities.xcodeproj/project.pbxproj rename to Security/libsecurity_utilities/libsecurity_utilities.xcodeproj/project.pbxproj diff --git a/Security/libsecurityd/APPLE_LICENSE b/Security/libsecurityd/APPLE_LICENSE new file mode 100644 index 00000000..71fe6fd7 --- /dev/null +++ b/Security/libsecurityd/APPLE_LICENSE @@ -0,0 +1,335 @@ +APPLE PUBLIC SOURCE LICENSE +Version 2.0 - August 6, 2003 + +Please read this License carefully before downloading this software. By +downloading or using this software, you are agreeing to be bound by the terms +of this License. If you do not or cannot agree to the terms of this License, +please do not download or use the software. + +Apple Note: In January 2007, Apple changed its corporate name from "Apple +Computer, Inc." to "Apple Inc." This change has been reflected below and +copyright years updated, but no other changes have been made to the APSL 2.0. + +1. General; Definitions. This License applies to any program or other +work which Apple Inc. ("Apple") makes publicly available and which contains a +notice placed by Apple identifying such program or work as "Original Code" and +stating that it is subject to the terms of this Apple Public Source License +version 2.0 ("License"). As used in this License: + +1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is the +grantor of rights, (i) claims of patents that are now or hereafter acquired, +owned by or assigned to Apple and (ii) that cover subject matter contained in +the Original Code, but only to the extent necessary to use, reproduce and/or +distribute the Original Code without infringement; and (b) in the case where +You are the grantor of rights, (i) claims of patents that are now or hereafter +acquired, owned by or assigned to You and (ii) that cover subject matter in +Your Modifications, taken alone or in combination with Original Code. + +1.2 "Contributor" means any person or entity that creates or contributes to +the creation of Modifications. + +1.3 "Covered Code" means the Original Code, Modifications, the combination +of Original Code and any Modifications, and/or any respective portions thereof. + +1.4 "Externally Deploy" means: (a) to sublicense, distribute or otherwise +make Covered Code available, directly or indirectly, to anyone other than You; +and/or (b) to use Covered Code, alone or as part of a Larger Work, in any way +to provide a service, including but not limited to delivery of content, through +electronic communication with a client other than You. + +1.5 "Larger Work" means a work which combines Covered Code or portions +thereof with code not governed by the terms of this License. + +1.6 "Modifications" mean any addition to, deletion from, and/or change to, +the substance and/or structure of the Original Code, any previous +Modifications, the combination of Original Code and any previous Modifications, +and/or any respective portions thereof. When code is released as a series of +files, a Modification is: (a) any addition to or deletion from the contents of +a file containing Covered Code; and/or (b) any new file or other representation +of computer program statements that contains any part of Covered Code. + +1.7 "Original Code" means (a) the Source Code of a program or other work as +originally made available by Apple under this License, including the Source +Code of any updates or upgrades to such programs or works made available by +Apple under this License, and that has been expressly identified by Apple as +such in the header file(s) of such work; and (b) the object code compiled from +such Source Code and originally made available by Apple under this License + +1.8 "Source Code" means the human readable form of a program or other work +that is suitable for making modifications to it, including all modules it +contains, plus any associated interface definition files, scripts used to +control compilation and installation of an executable (object code). + +1.9 "You" or "Your" means an individual or a legal entity exercising rights +under this License. For legal entities, "You" or "Your" includes any entity +which controls, is controlled by, or is under common control with, You, where +"control" means (a) the power, direct or indirect, to cause the direction or +management of such entity, whether by contract or otherwise, or (b) ownership +of fifty percent (50%) or more of the outstanding shares or beneficial +ownership of such entity. + +2. Permitted Uses; Conditions & Restrictions. Subject to the terms and +conditions of this License, Apple hereby grants You, effective on the date You +accept this License and download the Original Code, a world-wide, royalty-free, +non-exclusive license, to the extent of Apple's Applicable Patent Rights and +copyrights covering the Original Code, to do the following: + +2.1 Unmodified Code. You may use, reproduce, display, perform, internally +distribute within Your organization, and Externally Deploy verbatim, unmodified +copies of the Original Code, for commercial or non-commercial purposes, +provided that in each instance: + +(a) You must retain and reproduce in all copies of Original Code the +copyright and other proprietary notices and disclaimers of Apple as they appear +in the Original Code, and keep intact all notices in the Original Code that +refer to this License; and + +(b) You must include a copy of this License with every copy of Source Code +of Covered Code and documentation You distribute or Externally Deploy, and You +may not offer or impose any terms on such Source Code that alter or restrict +this License or the recipients' rights hereunder, except as permitted under +Section 6. + +2.2 Modified Code. You may modify Covered Code and use, reproduce, +display, perform, internally distribute within Your organization, and +Externally Deploy Your Modifications and Covered Code, for commercial or +non-commercial purposes, provided that in each instance You also meet all of +these conditions: + +(a) You must satisfy all the conditions of Section 2.1 with respect to the +Source Code of the Covered Code; + +(b) You must duplicate, to the extent it does not already exist, the notice +in Exhibit A in each file of the Source Code of all Your Modifications, and +cause the modified files to carry prominent notices stating that You changed +the files and the date of any change; and + +(c) If You Externally Deploy Your Modifications, You must make Source Code +of all Your Externally Deployed Modifications either available to those to whom +You have Externally Deployed Your Modifications, or publicly available. Source +Code of Your Externally Deployed Modifications must be released under the terms +set forth in this License, including the license grants set forth in Section 3 +below, for as long as you Externally Deploy the Covered Code or twelve (12) +months from the date of initial External Deployment, whichever is longer. You +should preferably distribute the Source Code of Your Externally Deployed +Modifications electronically (e.g. download from a web site). + +2.3 Distribution of Executable Versions. In addition, if You Externally +Deploy Covered Code (Original Code and/or Modifications) in object code, +executable form only, You must include a prominent notice, in the code itself +as well as in related documentation, stating that Source Code of the Covered +Code is available under the terms of this License with information on how and +where to obtain such Source Code. + +2.4 Third Party Rights. You expressly acknowledge and agree that although +Apple and each Contributor grants the licenses to their respective portions of +the Covered Code set forth herein, no assurances are provided by Apple or any +Contributor that the Covered Code does not infringe the patent or other +intellectual property rights of any other entity. Apple and each Contributor +disclaim any liability to You for claims brought by any other entity based on +infringement of intellectual property rights or otherwise. As a condition to +exercising the rights and licenses granted hereunder, You hereby assume sole +responsibility to secure any other intellectual property rights needed, if any. +For example, if a third party patent license is required to allow You to +distribute the Covered Code, it is Your responsibility to acquire that license +before distributing the Covered Code. + +3. Your Grants. In consideration of, and as a condition to, the licenses +granted to You under this License, You hereby grant to any person or entity +receiving or distributing Covered Code under this License a non-exclusive, +royalty-free, perpetual, irrevocable license, under Your Applicable Patent +Rights and other intellectual property rights (other than patent) owned or +controlled by You, to use, reproduce, display, perform, modify, sublicense, +distribute and Externally Deploy Your Modifications of the same scope and +extent as Apple's licenses under Sections 2.1 and 2.2 above. + +4. Larger Works. You may create a Larger Work by combining Covered Code +with other code not governed by the terms of this License and distribute the +Larger Work as a single product. In each such instance, You must make sure the +requirements of this License are fulfilled for the Covered Code or any portion +thereof. + +5. Limitations on Patent License. Except as expressly stated in Section +2, no other patent rights, express or implied, are granted by Apple herein. +Modifications and/or Larger Works may require additional patent licenses from +Apple which Apple may grant in its sole discretion. + +6. Additional Terms. You may choose to offer, and to charge a fee for, +warranty, support, indemnity or liability obligations and/or other rights +consistent with the scope of the license granted herein ("Additional Terms") to +one or more recipients of Covered Code. However, You may do so only on Your own +behalf and as Your sole responsibility, and not on behalf of Apple or any +Contributor. You must obtain the recipient's agreement that any such Additional +Terms are offered by You alone, and You hereby agree to indemnify, defend and +hold Apple and every Contributor harmless for any liability incurred by or +claims asserted against Apple or such Contributor by reason of any such +Additional Terms. + +7. Versions of the License. Apple may publish revised and/or new versions +of this License from time to time. Each version will be given a distinguishing +version number. Once Original Code has been published under a particular +version of this License, You may continue to use it under the terms of that +version. You may also choose to use such Original Code under the terms of any +subsequent version of this License published by Apple. No one other than Apple +has the right to modify the terms applicable to Covered Code created under this +License. + +8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in +part pre-release, untested, or not fully tested works. The Covered Code may +contain errors that could cause failures or loss of data, and may be incomplete +or contain inaccuracies. You expressly acknowledge and agree that use of the +Covered Code, or any portion thereof, is at Your sole and entire risk. THE +COVERED CODE IS PROVIDED "AS IS" AND WITHOUT WARRANTY, UPGRADES OR SUPPORT OF +ANY KIND AND APPLE AND APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" +FOR THE PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM +ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF MERCHANTABILITY, OF +SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY, OF +QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. APPLE AND EACH +CONTRIBUTOR DOES NOT WARRANT AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE +COVERED CODE, THAT THE FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR +REQUIREMENTS, THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR +ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO ORAL OR +WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE AUTHORIZED +REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. You acknowledge +that the Covered Code is not intended for use in the operation of nuclear +facilities, aircraft navigation, communication systems, or air traffic control +machines in which case the failure of the Covered Code could lead to death, +personal injury, or severe physical or environmental damage. + +9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO +EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO THIS LICENSE OR +YOUR USE OR INABILITY TO USE THE COVERED CODE, OR ANY PORTION THEREOF, WHETHER +UNDER A THEORY OF CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE), PRODUCTS +LIABILITY OR OTHERWISE, EVEN IF APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF +THE POSSIBILITY OF SUCH DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL +PURPOSE OF ANY REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF +LIABILITY OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT +APPLY TO YOU. In no event shall Apple's total liability to You for all damages +(other than as may be required by applicable law) under this License exceed the +amount of fifty dollars ($50.00). + +10. Trademarks. This License does not grant any rights to use the +trademarks or trade names "Apple", "Mac", "Mac OS", "QuickTime", "QuickTime +Streaming Server" or any other trademarks, service marks, logos or trade names +belonging to Apple (collectively "Apple Marks") or to any trademark, service +mark, logo or trade name belonging to any Contributor. You agree not to use +any Apple Marks in or as part of the name of products derived from the Original +Code or to endorse or promote products derived from the Original Code other +than as expressly permitted by and in strict compliance at all times with +Apple's third party trademark usage guidelines which are posted at +http://www.apple.com/legal/guidelinesfor3rdparties.html. + +11. Ownership. Subject to the licenses granted under this License, each +Contributor retains all rights, title and interest in and to any Modifications +made by such Contributor. Apple retains all rights, title and interest in and +to the Original Code and any Modifications made by or on behalf of Apple +("Apple Modifications"), and such Apple Modifications will not be automatically +subject to this License. Apple may, at its sole discretion, choose to license +such Apple Modifications under this License, or on different terms from those +contained in this License or may choose not to license them at all. + +12. Termination. + +12.1 Termination. This License and the rights granted hereunder will +terminate: + +(a) automatically without notice from Apple if You fail to comply with any +term(s) of this License and fail to cure such breach within 30 days of becoming +aware of such breach; +(b) immediately in the event of the circumstances described in Section +13.5(b); or +(c) automatically without notice from Apple if You, at any time during the +term of this License, commence an action for patent infringement against Apple; +provided that Apple did not first commence an action for patent infringement +against You in that instance. + +12.2 Effect of Termination. Upon termination, You agree to immediately stop +any further use, reproduction, modification, sublicensing and distribution of +the Covered Code. All sublicenses to the Covered Code which have been properly +granted prior to termination shall survive any termination of this License. +Provisions which, by their nature, should remain in effect beyond the +termination of this License shall survive, including but not limited to +Sections 3, 5, 8, 9, 10, 11, 12.2 and 13. No party will be liable to any other +for compensation, indemnity or damages of any sort solely as a result of +terminating this License in accordance with its terms, and termination of this +License will be without prejudice to any other right or remedy of any party. + +13. Miscellaneous. + +13.1 Government End Users. The Covered Code is a "commercial item" as +defined in FAR 2.101. Government software and technical data rights in the +Covered Code include only those rights customarily provided to the public as +defined in this License. This customary commercial license in technical data +and software is provided in accordance with FAR 12.211 (Technical Data) and +12.212 (Computer Software) and, for Department of Defense purchases, DFAR +252.227-7015 (Technical Data -- Commercial Items) and 227.7202-3 (Rights in +Commercial Computer Software or Computer Software Documentation). Accordingly, +all U.S. Government End Users acquire Covered Code with only those rights set +forth herein. + +13.2 Relationship of Parties. This License will not be construed as +creating an agency, partnership, joint venture or any other form of legal +association between or among You, Apple or any Contributor, and You will not +represent to the contrary, whether expressly, by implication, appearance or +otherwise. + +13.3 Independent Development. Nothing in this License will impair Apple's +right to acquire, license, develop, have others develop for it, market and/or +distribute technology or products that perform the same or similar functions +as, or otherwise compete with, Modifications, Larger Works, technology or +products that You may develop, produce, market or distribute. + +13.4 Waiver; Construction. Failure by Apple or any Contributor to enforce +any provision of this License will not be deemed a waiver of future enforcement +of that or any other provision. Any law or regulation which provides that the +language of a contract shall be construed against the drafter will not apply to +this License. + +13.5 Severability. (a) If for any reason a court of competent jurisdiction +finds any provision of this License, or portion thereof, to be unenforceable, +that provision of the License will be enforced to the maximum extent +permissible so as to effect the economic benefits and intent of the parties, +and the remainder of this License will continue in full force and effect. (b) +Notwithstanding the foregoing, if applicable law prohibits or restricts You +from fully and/or specifically complying with Sections 2 and/or 3 or prevents +the enforceability of either of those Sections, this License will immediately +terminate and You must immediately discontinue any use of the Covered Code and +destroy all copies of it that are in your possession or control. + +13.6 Dispute Resolution. Any litigation or other dispute resolution between +You and Apple relating to this License shall take place in the Northern +District of California, and You and Apple hereby consent to the personal +jurisdiction of, and venue in, the state and federal courts within that +District with respect to this License. The application of the United Nations +Convention on Contracts for the International Sale of Goods is expressly +excluded. + +13.7 Entire Agreement; Governing Law. This License constitutes the entire +agreement between the parties with respect to the subject matter hereof. This +License shall be governed by the laws of the United States and the State of +California, except that body of California law concerning conflicts of law. + +Where You are located in the province of Quebec, Canada, the following clause +applies: The parties hereby confirm that they have requested that this License +and all related documents be drafted in English. Les parties ont exigé que le +présent contrat et tous les documents connexes soient rédigés en anglais. + +EXHIBIT A. + +"Portions Copyright (c) 1999-2007 Apple Inc. All Rights Reserved. + +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." + diff --git a/libsecurityd/Info-securityd_client.plist b/Security/libsecurityd/Info-securityd_client.plist similarity index 100% rename from libsecurityd/Info-securityd_client.plist rename to Security/libsecurityd/Info-securityd_client.plist diff --git a/libsecurityd/Info-securityd_server.plist b/Security/libsecurityd/Info-securityd_server.plist similarity index 100% rename from libsecurityd/Info-securityd_server.plist rename to Security/libsecurityd/Info-securityd_server.plist diff --git a/libsecurityd/lib/SharedMemoryClient.cpp b/Security/libsecurityd/lib/SharedMemoryClient.cpp similarity index 100% rename from libsecurityd/lib/SharedMemoryClient.cpp rename to Security/libsecurityd/lib/SharedMemoryClient.cpp diff --git a/libsecurityd/lib/SharedMemoryClient.h b/Security/libsecurityd/lib/SharedMemoryClient.h similarity index 100% rename from libsecurityd/lib/SharedMemoryClient.h rename to Security/libsecurityd/lib/SharedMemoryClient.h diff --git a/Security/libsecurityd/lib/SharedMemoryCommon.h b/Security/libsecurityd/lib/SharedMemoryCommon.h new file mode 100644 index 00000000..227993f0 --- /dev/null +++ b/Security/libsecurityd/lib/SharedMemoryCommon.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef __SHARED_MEMORY_COMMON__ +#define __SHARED_MEMORY_COMMON__ + + + +#include + +const unsigned kSegmentSize = 4096; +const unsigned kNumberOfSegments = 8; +const unsigned kSharedMemoryPoolSize = kSegmentSize * kNumberOfSegments; + +const unsigned kBytesWrittenOffset = 0; +const unsigned kBytesWrittenLength = 4; +const unsigned kPoolAvailableForData = kSharedMemoryPoolSize - kBytesWrittenLength; + +typedef u_int32_t SegmentOffsetType; + +#define SECURITY_MESSAGES_NAME "SecurityMessages" + +#endif diff --git a/libsecurityd/lib/dictionary.cpp b/Security/libsecurityd/lib/dictionary.cpp similarity index 99% rename from libsecurityd/lib/dictionary.cpp rename to Security/libsecurityd/lib/dictionary.cpp index f79ea20e..9b26f58c 100644 --- a/libsecurityd/lib/dictionary.cpp +++ b/Security/libsecurityd/lib/dictionary.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/dictionary.h b/Security/libsecurityd/lib/dictionary.h similarity index 96% rename from libsecurityd/lib/dictionary.h rename to Security/libsecurityd/lib/dictionary.h index eecdd567..adc04c38 100644 --- a/libsecurityd/lib/dictionary.h +++ b/Security/libsecurityd/lib/dictionary.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2003-2004,2006,2011-2013 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2006,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/libsecurityd/lib/eventlistener.cpp b/Security/libsecurityd/lib/eventlistener.cpp similarity index 98% rename from libsecurityd/lib/eventlistener.cpp rename to Security/libsecurityd/lib/eventlistener.cpp index f3f47d45..93a3c93f 100644 --- a/libsecurityd/lib/eventlistener.cpp +++ b/Security/libsecurityd/lib/eventlistener.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/eventlistener.h b/Security/libsecurityd/lib/eventlistener.h similarity index 96% rename from libsecurityd/lib/eventlistener.h rename to Security/libsecurityd/lib/eventlistener.h index 4872a18a..2faf7ef9 100644 --- a/libsecurityd/lib/eventlistener.h +++ b/Security/libsecurityd/lib/eventlistener.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/handletypes.h b/Security/libsecurityd/lib/handletypes.h similarity index 97% rename from libsecurityd/lib/handletypes.h rename to Security/libsecurityd/lib/handletypes.h index 85650785..6ee10a0d 100644 --- a/libsecurityd/lib/handletypes.h +++ b/Security/libsecurityd/lib/handletypes.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2008,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/sec_xdr.c b/Security/libsecurityd/lib/sec_xdr.c similarity index 99% rename from libsecurityd/lib/sec_xdr.c rename to Security/libsecurityd/lib/sec_xdr.c index e82f6374..54869b04 100644 --- a/libsecurityd/lib/sec_xdr.c +++ b/Security/libsecurityd/lib/sec_xdr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/sec_xdr.h b/Security/libsecurityd/lib/sec_xdr.h similarity index 97% rename from libsecurityd/lib/sec_xdr.h rename to Security/libsecurityd/lib/sec_xdr.h index fd726cd8..c1db2438 100644 --- a/libsecurityd/lib/sec_xdr.h +++ b/Security/libsecurityd/lib/sec_xdr.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/sec_xdr_array.c b/Security/libsecurityd/lib/sec_xdr_array.c similarity index 98% rename from libsecurityd/lib/sec_xdr_array.c rename to Security/libsecurityd/lib/sec_xdr_array.c index e5ec1ade..8d81b797 100644 --- a/libsecurityd/lib/sec_xdr_array.c +++ b/Security/libsecurityd/lib/sec_xdr_array.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2006,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/sec_xdr_reference.c b/Security/libsecurityd/lib/sec_xdr_reference.c similarity index 98% rename from libsecurityd/lib/sec_xdr_reference.c rename to Security/libsecurityd/lib/sec_xdr_reference.c index ab5b4c40..176e67a9 100644 --- a/libsecurityd/lib/sec_xdr_reference.c +++ b/Security/libsecurityd/lib/sec_xdr_reference.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2006,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/sec_xdr_sizeof.c b/Security/libsecurityd/lib/sec_xdr_sizeof.c similarity index 98% rename from libsecurityd/lib/sec_xdr_sizeof.c rename to Security/libsecurityd/lib/sec_xdr_sizeof.c index 2788e5d2..1d876101 100644 --- a/libsecurityd/lib/sec_xdr_sizeof.c +++ b/Security/libsecurityd/lib/sec_xdr_sizeof.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2006,2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/sec_xdrmem.c b/Security/libsecurityd/lib/sec_xdrmem.c similarity index 99% rename from libsecurityd/lib/sec_xdrmem.c rename to Security/libsecurityd/lib/sec_xdrmem.c index 29e88cb2..d9d8d2bd 100644 --- a/libsecurityd/lib/sec_xdrmem.c +++ b/Security/libsecurityd/lib/sec_xdrmem.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/ss_types.h b/Security/libsecurityd/lib/ss_types.h similarity index 97% rename from libsecurityd/lib/ss_types.h rename to Security/libsecurityd/lib/ss_types.h index 77c41e75..12af810b 100644 --- a/libsecurityd/lib/ss_types.h +++ b/Security/libsecurityd/lib/ss_types.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/ssblob.cpp b/Security/libsecurityd/lib/ssblob.cpp similarity index 96% rename from libsecurityd/lib/ssblob.cpp rename to Security/libsecurityd/lib/ssblob.cpp index 017cd11f..2a47bd26 100644 --- a/libsecurityd/lib/ssblob.cpp +++ b/Security/libsecurityd/lib/ssblob.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/ssblob.h b/Security/libsecurityd/lib/ssblob.h similarity index 98% rename from libsecurityd/lib/ssblob.h rename to Security/libsecurityd/lib/ssblob.h index ed408560..d05f2b73 100644 --- a/libsecurityd/lib/ssblob.h +++ b/Security/libsecurityd/lib/ssblob.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/ssclient.cpp b/Security/libsecurityd/lib/ssclient.cpp similarity index 99% rename from libsecurityd/lib/ssclient.cpp rename to Security/libsecurityd/lib/ssclient.cpp index c0dd89b2..37951004 100644 --- a/libsecurityd/lib/ssclient.cpp +++ b/Security/libsecurityd/lib/ssclient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2008,2011,2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/ssclient.h b/Security/libsecurityd/lib/ssclient.h similarity index 99% rename from libsecurityd/lib/ssclient.h rename to Security/libsecurityd/lib/ssclient.h index c4f1e219..43835294 100644 --- a/libsecurityd/lib/ssclient.h +++ b/Security/libsecurityd/lib/ssclient.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2008,2011-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/sscommon.h b/Security/libsecurityd/lib/sscommon.h similarity index 97% rename from libsecurityd/lib/sscommon.h rename to Security/libsecurityd/lib/sscommon.h index eda99e24..e0710366 100644 --- a/libsecurityd/lib/sscommon.h +++ b/Security/libsecurityd/lib/sscommon.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006-2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006-2008,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/ssnotify.h b/Security/libsecurityd/lib/ssnotify.h similarity index 98% rename from libsecurityd/lib/ssnotify.h rename to Security/libsecurityd/lib/ssnotify.h index 9039eace..b0d9bed4 100644 --- a/libsecurityd/lib/ssnotify.h +++ b/Security/libsecurityd/lib/ssnotify.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/sstransit.cpp b/Security/libsecurityd/lib/sstransit.cpp similarity index 98% rename from libsecurityd/lib/sstransit.cpp rename to Security/libsecurityd/lib/sstransit.cpp index e0ec2919..d84cc2e9 100644 --- a/libsecurityd/lib/sstransit.cpp +++ b/Security/libsecurityd/lib/sstransit.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/sstransit.h b/Security/libsecurityd/lib/sstransit.h similarity index 98% rename from libsecurityd/lib/sstransit.h rename to Security/libsecurityd/lib/sstransit.h index 34671e94..1881c7ef 100644 --- a/libsecurityd/lib/sstransit.h +++ b/Security/libsecurityd/lib/sstransit.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/libsecurityd/lib/transition.cpp b/Security/libsecurityd/lib/transition.cpp new file mode 100644 index 00000000..66088ac8 --- /dev/null +++ b/Security/libsecurityd/lib/transition.cpp @@ -0,0 +1,1066 @@ +/* + * Copyright (c) 2000-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@ + */ + + +// +// transition - SecurityServer client library transition code. +// +// These are the functions that implement CssmClient methods in terms of +// MIG IPC client calls, plus their supporting machinery. +// +// WARNING! HERE BE DRAGONS! +// This code involves moderately arcane magic including (but not limited to) +// dancing macros paired off with self-maintaining stack objects. Don't take +// anything for granted! Be very afraid of ALL-CAPS names. Your best bet is +// probably to stick with the existing patterns. +// +// Dragons, the sequel. You just don't go killing of that kind of prose, so +// we'll continue the saga here with a bit of an update. In transitioning +// into securityd there are a couple of steps. The current setup is there +// to allow Security.framework to have 32 and 64 bit clients and either +// big or little endian. Data is packaged up as hand-generated XDR, which +// means it's also in network byte-order. +// +// CSSM_HANDLEs have remained longs in the 64 bit transition to keep the +// optimization option open to allow cssm modules to hand back pointers as +// handles. Since we don't identify the client, handles across ipc will +// remain 32 bit. Handles you see here are passed out by securityd, and +// are clipped and expanded in this layer (high bits always zero). +// +#include "sstransit.h" +#include + +#include +#include +#include + +namespace Security { +namespace SecurityServer { + +using MachPlusPlus::check; +using MachPlusPlus::VMGuard; + +// +// Common database interface +// +void ClientSession::authenticateDb(DbHandle db, CSSM_DB_ACCESS_TYPE type, + const AccessCredentials *cred) +{ + // XXX/cs Leave it up to DatabaseAccessCredentials to rewrite it for now + DatabaseAccessCredentials creds(cred, internalAllocator); + CopyIn copy(creds.value(), reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); + IPC(ucsp_client_authenticateDb(UCSP_ARGS, db, type, copy.data(), copy.length())); +} + + +void ClientSession::releaseDb(DbHandle db) +{ + IPC(ucsp_client_releaseDb(UCSP_ARGS, db)); +} + + +// +// External database interface +// +DbHandle ClientSession::openToken(uint32 ssid, const AccessCredentials *cred, + const char *name) +{ + DbHandle db; + DatabaseAccessCredentials creds(cred, internalAllocator); + CopyIn copycreds(creds.value(), reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); + + IPC(ucsp_client_openToken(UCSP_ARGS, ssid, name ? name : "", copycreds.data(), copycreds.length(), &db)); + + return db; +} + + +RecordHandle ClientSession::insertRecord(DbHandle db, + CSSM_DB_RECORDTYPE recordType, + const CssmDbRecordAttributeData *attributes, + const CssmData *data) +{ + RecordHandle record; + CopyIn db_record_attr_data(attributes, reinterpret_cast(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA)); + + IPC(ucsp_client_insertRecord(UCSP_ARGS, db, recordType, db_record_attr_data.data(), (mach_msg_type_number_t)db_record_attr_data.length(), OPTIONALDATA(data), &record)); + + return record; +} + + +void ClientSession::deleteRecord(DbHandle db, RecordHandle record) +{ + IPC(ucsp_client_deleteRecord(UCSP_ARGS, db, record)); +} + + +void ClientSession::modifyRecord(DbHandle db, RecordHandle &record, + CSSM_DB_RECORDTYPE recordType, + const CssmDbRecordAttributeData *attributes, + const CssmData *data, + CSSM_DB_MODIFY_MODE modifyMode) +{ + CopyIn db_record_attr_data(attributes, reinterpret_cast(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA)); + + IPC(ucsp_client_modifyRecord(UCSP_ARGS, db, &record, recordType, db_record_attr_data.data(), (mach_msg_type_number_t)db_record_attr_data.length(), + data != NULL, OPTIONALDATA(data), modifyMode)); +} + +static +void copy_back_attribute_return_data(CssmDbRecordAttributeData *dest_attrs, CssmDbRecordAttributeData *source_attrs, Allocator &returnAllocator) +{ + assert(dest_attrs->size() == source_attrs->size()); + // global (per-record) fields + dest_attrs->recordType(source_attrs->recordType()); + dest_attrs->semanticInformation(source_attrs->semanticInformation()); + + // transfer data values (but not infos, which we keep in the original vector) + for (uint32 n = 0; n < dest_attrs->size(); n++) + dest_attrs->at(n).copyValues(source_attrs->at(n), returnAllocator); +} + +RecordHandle ClientSession::findFirst(DbHandle db, + const CssmQuery &inQuery, + SearchHandle &hSearch, + CssmDbRecordAttributeData *attributes, + CssmData *data, KeyHandle &hKey) +{ + CopyIn query(&inQuery, reinterpret_cast(xdr_CSSM_QUERY)); + CopyIn in_attr(attributes, reinterpret_cast(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA)); + void *out_attr_data = NULL, *out_data = NULL; + mach_msg_size_t out_attr_length = 0, out_data_length = 0; + RecordHandle ipcHRecord = 0; + + IPC(ucsp_client_findFirst(UCSP_ARGS, db, + query.data(), query.length(), in_attr.data(), in_attr.length(), + &out_attr_data, &out_attr_length, (data != NULL), &out_data, &out_data_length, + &hKey, &hSearch, &ipcHRecord)); + + if (ipcHRecord != 0) + { + CopyOut out_attrs(out_attr_data, out_attr_length, reinterpret_cast(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR), true); + copy_back_attribute_return_data(attributes, reinterpret_cast(out_attrs.data()), returnAllocator); + } + + // decode data from server as cssm_data or cssm_key (get data on keys returns cssm_key in data) + CopyOut possible_key_in_data(out_data, out_data_length, reinterpret_cast(xdr_CSSM_POSSIBLY_KEY_IN_DATA_PTR), true, data); + + return ipcHRecord; +} + + +RecordHandle ClientSession::findNext(SearchHandle hSearch, + CssmDbRecordAttributeData *attributes, + CssmData *data, KeyHandle &hKey) +{ + CopyIn in_attr(attributes, reinterpret_cast(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA)); + void *out_attr_data = NULL, *out_data = NULL; + mach_msg_size_t out_attr_length = 0, out_data_length = 0; + //DataOutput out_data(data, returnAllocator); + RecordHandle ipcHRecord = 0; + + IPC(ucsp_client_findNext(UCSP_ARGS, hSearch, + in_attr.data(), in_attr.length(), &out_attr_data, &out_attr_length, + (data != NULL), &out_data, &out_data_length, &hKey, &ipcHRecord)); + + if (ipcHRecord != 0) + { + CopyOut out_attrs(out_attr_data, out_attr_length, reinterpret_cast(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR), true); + copy_back_attribute_return_data(attributes, reinterpret_cast(out_attrs.data()), returnAllocator); + } + + // decode data from server as cssm_data or cssm_key (get data on keys returns cssm_key in data) + CopyOut possible_key_in_data(out_data, out_data_length, reinterpret_cast(xdr_CSSM_POSSIBLY_KEY_IN_DATA_PTR), true, data); + + return ipcHRecord; +} + + +void ClientSession::findRecordHandle(RecordHandle hRecord, + CssmDbRecordAttributeData *attributes, + CssmData *data, KeyHandle &hKey) +{ + CopyIn in_attr(attributes, reinterpret_cast(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA)); + void *out_attr_data = NULL, *out_data = NULL; + mach_msg_size_t out_attr_length = 0, out_data_length = 0; + IPC(ucsp_client_findRecordHandle(UCSP_ARGS, hRecord, + in_attr.data(), in_attr.length(), &out_attr_data, &out_attr_length, + data != NULL, &out_data, &out_data_length, &hKey)); + + if (hRecord != 0) + { + CopyOut out_attrs(out_attr_data, out_attr_length, reinterpret_cast(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR), true); + copy_back_attribute_return_data(attributes, reinterpret_cast(out_attrs.data()), returnAllocator); + } + + // decode data from server as cssm_data or cssm_key (get data on keys returns cssm_key in data) + CopyOut possible_key_in_data(out_data, out_data_length, reinterpret_cast(xdr_CSSM_POSSIBLY_KEY_IN_DATA_PTR), true, data); +} + + +void ClientSession::releaseSearch(SearchHandle searchHandle) +{ + IPC(ucsp_client_releaseSearch(UCSP_ARGS, searchHandle)); +} + + +void ClientSession::releaseRecord(RecordHandle record) +{ + IPC(ucsp_client_releaseRecord(UCSP_ARGS, record)); +} + +void ClientSession::getDbName(DbHandle db, string &name) +{ + char result[PATH_MAX]; + + IPC(ucsp_client_getDbName(UCSP_ARGS, db, result)); + + name = result; +} + +void ClientSession::setDbName(DbHandle db, const string &name) +{ + IPC(ucsp_client_setDbName(UCSP_ARGS, db, name.c_str())); +} + + +// +// Internal database management +// +DbHandle ClientSession::createDb(const DLDbIdentifier &dbId, + const AccessCredentials *cred, const AclEntryInput *owner, + const DBParameters ¶ms) +{ + DatabaseAccessCredentials creds(cred, internalAllocator); + CopyIn copycreds(creds.value(), reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); + CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); + // XXX/64 make xdr routines translate directly between dldbident and flat rep + DataWalkers::DLDbFlatIdentifier ident(dbId); + CopyIn id(&ident, reinterpret_cast(xdr_DLDbFlatIdentifier)); + DbHandle db; + + IPC(ucsp_client_createDb(UCSP_ARGS, &db, id.data(), id.length(), copycreds.data(), copycreds.length(), proto.data(), proto.length(), params)); + + return db; +} + +DbHandle ClientSession::recodeDbForSync(DbHandle dbToClone, + DbHandle srcDb) +{ + DbHandle newDb; + + IPC(ucsp_client_recodeDbForSync(UCSP_ARGS, dbToClone, srcDb, &newDb)); + + return newDb; +} + +DbHandle ClientSession::authenticateDbsForSync(const CssmData &dbHandleArray, + const CssmData &agentData) +{ + DbHandle newDb; + + IPC(ucsp_client_authenticateDbsForSync(UCSP_ARGS, DATA(dbHandleArray), DATA(agentData), &newDb)); + + return newDb; +} + +void ClientSession::commitDbForSync(DbHandle srcDb, DbHandle cloneDb, + CssmData &blob, Allocator &alloc) +{ + DataOutput outBlob(blob, alloc); + IPC(ucsp_client_commitDbForSync(UCSP_ARGS, srcDb, cloneDb, DATA_OUT(outBlob))); +} + +DbHandle ClientSession::decodeDb(const DLDbIdentifier &dbId, + const AccessCredentials *cred, const CssmData &blob) +{ + // XXX/64 fold into one translation + DatabaseAccessCredentials credentials(cred, internalAllocator); + CopyIn creds(credentials.value(), reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); + // XXX/64 fold into one translation + DataWalkers::DLDbFlatIdentifier ident(dbId); + CopyIn id(&ident, reinterpret_cast(xdr_DLDbFlatIdentifier)); + DbHandle db; + + IPC(ucsp_client_decodeDb(UCSP_ARGS, &db, id.data(), id.length(), creds.data(), creds.length(), DATA(blob))); + + return db; +} + +void ClientSession::encodeDb(DbHandle db, CssmData &blob, Allocator &alloc) +{ + DataOutput outBlob(blob, alloc); + IPC(ucsp_client_encodeDb(UCSP_ARGS, db, DATA_OUT(outBlob))); +} + +void ClientSession::setDbParameters(DbHandle db, const DBParameters ¶ms) +{ + IPC(ucsp_client_setDbParameters(UCSP_ARGS, db, params)); +} + +void ClientSession::getDbParameters(DbHandle db, DBParameters ¶ms) +{ + IPC(ucsp_client_getDbParameters(UCSP_ARGS, db, ¶ms)); +} + +void ClientSession::changePassphrase(DbHandle db, const AccessCredentials *cred) +{ + CopyIn creds(cred, reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); + IPC(ucsp_client_changePassphrase(UCSP_ARGS, db, creds.data(), creds.length())); +} + + +void ClientSession::lock(DbHandle db) +{ + IPC(ucsp_client_authenticateDb(UCSP_ARGS, db, CSSM_DB_ACCESS_RESET, NULL, 0)); +//@@@VIRTUAL IPC(ucsp_client_lockDb(UCSP_ARGS, db)); +} + +void ClientSession::lockAll (bool forSleep) +{ + IPC(ucsp_client_lockAll (UCSP_ARGS, forSleep)); +} + +void ClientSession::unlock(DbHandle db) +{ + IPC(ucsp_client_unlockDb(UCSP_ARGS, db)); +} + +void ClientSession::unlock(DbHandle db, const CssmData &passphrase) +{ + IPC(ucsp_client_unlockDbWithPassphrase(UCSP_ARGS, db, DATA(passphrase))); +} + +void ClientSession::stashDb(DbHandle db) +{ + IPC(ucsp_client_stashDb(UCSP_ARGS, db)); +} + +void ClientSession::stashDbCheck(DbHandle db) +{ + IPC(ucsp_client_stashDbCheck(UCSP_ARGS, db)); +} + +bool ClientSession::isLocked(DbHandle db) +{ + boolean_t locked; + IPC(ucsp_client_isLocked(UCSP_ARGS, db, &locked)); + return locked; +} + +void ClientSession::verifyKeyStorePassphrase(uint32_t retries) +{ + IPC(ucsp_client_verifyKeyStorePassphrase(UCSP_ARGS, retries)); +} + +void ClientSession::resetKeyStorePassphrase(const CssmData &passphrase) +{ + IPC(ucsp_client_resetKeyStorePassphrase(UCSP_ARGS, DATA(passphrase))); +} + +void ClientSession::changeKeyStorePassphrase() +{ + IPC(ucsp_client_changeKeyStorePassphrase(UCSP_ARGS)); +} + +// +// Key control +// +void ClientSession::encodeKey(KeyHandle key, CssmData &blob, + KeyUID *uid, Allocator &alloc) +{ + // Not really used as output + DataOutput oBlob(blob, alloc); + void *uidp; + mach_msg_type_number_t uidLength; + + IPC(ucsp_client_encodeKey(UCSP_ARGS, key, oBlob.data(), oBlob.length(), + (uid != NULL), &uidp, &uidLength)); + + // return key uid if requested + if (uid) { + assert(uidLength == sizeof(KeyUID)); + memcpy(uid, uidp, sizeof(KeyUID)); + } +} + +KeyHandle ClientSession::decodeKey(DbHandle db, const CssmData &blob, CssmKey::Header &header) +{ + KeyHandle key; + void *keyHeaderData; + mach_msg_type_number_t keyHeaderDataLength; + + IPC(ucsp_client_decodeKey(UCSP_ARGS, &key, &keyHeaderData, &keyHeaderDataLength, db, blob.data(), (mach_msg_type_number_t)blob.length())); + + CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast(xdr_CSSM_KEYHEADER_PTR), true); + header = *static_cast(reinterpret_cast(wrappedKeyHeaderXDR.data())); + + return key; +} + +// keychain synchronization +void ClientSession::recodeKey(DbHandle oldDb, KeyHandle key, DbHandle newDb, + CssmData &blob) +{ + DataOutput outBlob(blob, returnAllocator); + IPC(ucsp_client_recodeKey(UCSP_ARGS, oldDb, key, newDb, DATA_OUT(outBlob))); +} + +void ClientSession::releaseKey(KeyHandle key) +{ + IPC(ucsp_client_releaseKey(UCSP_ARGS, key)); +} + + +CssmKeySize ClientSession::queryKeySizeInBits(KeyHandle key) +{ + CssmKeySize length; + IPC(ucsp_client_queryKeySizeInBits(UCSP_ARGS, key, &length)); + return length; +} + + +uint32 ClientSession::getOutputSize(const Context &context, KeyHandle key, + uint32 inputSize, bool encrypt) +{ + CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); + uint32 outputSize; + + IPC(ucsp_client_getOutputSize(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, inputSize, encrypt, &outputSize)); + return outputSize; +} + + +// +// Random number generation. +// This interfaces to the secure RNG inside the SecurityServer; it does not access +// a PRNG in its CSP. If you need a reproducible PRNG, attach a local CSP and use it. +// Note that this function does not allocate a buffer; it always fills the buffer provided. +// +void ClientSession::generateRandom(const Security::Context &context, CssmData &data, Allocator &alloc) +{ + CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); + DataOutput result(data, alloc); + + IPC(ucsp_client_generateRandom(UCSP_ARGS, 0, ctxcopy.data(), ctxcopy.length(), DATA_OUT(result))); +} + + +// +// Signatures and MACs +// +void ClientSession::generateSignature(const Context &context, KeyHandle key, + const CssmData &data, CssmData &signature, Allocator &alloc, CSSM_ALGORITHMS signOnlyAlgorithm) +{ + CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); + DataOutput sig(signature, alloc); + + IPCKEY(ucsp_client_generateSignature(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, signOnlyAlgorithm, + DATA(data), DATA_OUT(sig)), + key, CSSM_ACL_AUTHORIZATION_SIGN); +} + +void ClientSession::verifySignature(const Context &context, KeyHandle key, + const CssmData &data, const CssmData &signature, CSSM_ALGORITHMS verifyOnlyAlgorithm) +{ + CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); + + IPC(ucsp_client_verifySignature(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, verifyOnlyAlgorithm, DATA(data), DATA(signature))); +} + + +void ClientSession::generateMac(const Context &context, KeyHandle key, + const CssmData &data, CssmData &signature, Allocator &alloc) +{ + CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); + DataOutput sig(signature, alloc); + + IPCKEY(ucsp_client_generateMac(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, DATA(data), DATA_OUT(sig)), + key, CSSM_ACL_AUTHORIZATION_MAC); +} + +void ClientSession::verifyMac(const Context &context, KeyHandle key, + const CssmData &data, const CssmData &signature) +{ + CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); + + IPCKEY(ucsp_client_verifyMac(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, + DATA(data), DATA(signature)), + key, CSSM_ACL_AUTHORIZATION_MAC); +} + + +// +// Encryption/Decryption +// + +void ClientSession::encrypt(const Context &context, KeyHandle key, + const CssmData &clear, CssmData &cipher, Allocator &alloc) +{ + CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); + DataOutput cipherOut(cipher, alloc); + IPCKEY(ucsp_client_encrypt(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, DATA(clear), DATA_OUT(cipherOut)), + key, CSSM_ACL_AUTHORIZATION_ENCRYPT); +} + +void ClientSession::decrypt(const Context &context, KeyHandle key, + const CssmData &cipher, CssmData &clear, Allocator &alloc) +{ + CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); + DataOutput clearOut(clear, alloc); + + IPCKEY(ucsp_client_decrypt(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, DATA(cipher), DATA_OUT(clearOut)), + key, CSSM_ACL_AUTHORIZATION_DECRYPT); +} + + +// +// Key generation +// +void ClientSession::generateKey(DbHandle db, const Context &context, uint32 keyUsage, uint32 keyAttr, + const AccessCredentials *cred, const AclEntryInput *owner, + KeyHandle &newKey, CssmKey::Header &newHeader) +{ + CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); + CopyIn creds(cred, reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); + CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); + void *keyHeaderData; + mach_msg_type_number_t keyHeaderDataLength; + + IPC(ucsp_client_generateKey(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), + creds.data(), creds.length(), proto.data(), proto.length(), + keyUsage, keyAttr, &newKey, &keyHeaderData, &keyHeaderDataLength)); + + CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast(xdr_CSSM_KEYHEADER_PTR), true); + newHeader = *static_cast(reinterpret_cast(wrappedKeyHeaderXDR.data())); +} + +void ClientSession::generateKey(DbHandle db, const Context &context, + uint32 pubKeyUsage, uint32 pubKeyAttr, + uint32 privKeyUsage, uint32 privKeyAttr, + const AccessCredentials *cred, const AclEntryInput *owner, + KeyHandle &pubKey, CssmKey::Header &pubHeader, + KeyHandle &privKey, CssmKey::Header &privHeader) +{ + CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); + CopyIn creds(cred, reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); + CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); + void *pubKeyHeaderData, *privKeyHeaderData; + mach_msg_type_number_t pubKeyHeaderDataLength, privKeyHeaderDataLength; + + IPC(ucsp_client_generateKeyPair(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), + creds.data(), creds.length(), proto.data(), proto.length(), + pubKeyUsage, pubKeyAttr, privKeyUsage, privKeyAttr, + &pubKey, &pubKeyHeaderData, &pubKeyHeaderDataLength, + &privKey, &privKeyHeaderData, &privKeyHeaderDataLength)); + + CopyOut wrappedPubKeyHeaderXDR(pubKeyHeaderData, pubKeyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast(xdr_CSSM_KEYHEADER_PTR), true); + pubHeader = *static_cast(reinterpret_cast(wrappedPubKeyHeaderXDR.data())); + CopyOut wrappedPrivKeyHeaderXDR(privKeyHeaderData, privKeyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast(xdr_CSSM_KEYHEADER_PTR), true); + privHeader = *static_cast(reinterpret_cast(wrappedPrivKeyHeaderXDR.data())); + +} + + +// +// Key derivation +// This is a bit strained; the incoming 'param' value may have structure, +// and we use a synthetic CssmDeriveData structure (with ad-hoc walker) to +// handle that. Param also is input/output, which is always a pain (not to mention +// ill-defined by the CDSA standard). +// +// If you're here because an algorithm of yours requires structured parameter +// input, go to security_cdsa_utilities/cssmwalkers.h and add a case to the +// CssmDeriveData walker. +// +void ClientSession::deriveKey(DbHandle db, const Context &context, KeyHandle baseKey, + CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, CssmData ¶m, + const AccessCredentials *cred, const AclEntryInput *owner, + KeyHandle &newKey, CssmKey::Header &newHeader, Allocator &allocator) +{ + CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); + CopyIn creds(cred, reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); + CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); + CSSM_DERIVE_DATA inParamForm = { context.algorithm(), param }; + CopyIn inParam(&inParamForm, reinterpret_cast(xdr_CSSM_DERIVE_DATA)); + + try + { + DataOutput paramOutput(param, allocator); + void *keyHeaderData; + mach_msg_type_number_t keyHeaderDataLength; + + IPCKEY(ucsp_client_deriveKey(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), baseKey, + creds.data(), creds.length(), proto.data(), proto.length(), + inParam.data(), inParam.length(), DATA_OUT(paramOutput), + usage, attrs, &newKey, &keyHeaderData, &keyHeaderDataLength), + baseKey, CSSM_ACL_AUTHORIZATION_DERIVE); + + CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast(xdr_CSSM_KEYHEADER_PTR), true); + newHeader = *static_cast(reinterpret_cast(wrappedKeyHeaderXDR.data())); + } + catch (CssmError& e) + { + // filter out errors for CSSM_ALGID_PKCS5_PBKDF2 + if (context.algorithm() != CSSM_ALGID_PKCS5_PBKDF2 && e.error != CSSMERR_CSP_OUTPUT_LENGTH_ERROR) + { + throw; + } + } +} + + +// +// Digest generation +// +void ClientSession::getKeyDigest(KeyHandle key, CssmData &digest, Allocator &allocator) +{ + DataOutput dig(digest, allocator); + IPC(ucsp_client_getKeyDigest(UCSP_ARGS, key, DATA_OUT(dig))); +} + + +// +// Key wrapping and unwrapping +// +void ClientSession::wrapKey(const Context &context, KeyHandle wrappingKey, + KeyHandle keyToBeWrapped, const AccessCredentials *cred, + const CssmData *descriptiveData, CssmWrappedKey &wrappedKey, Allocator &alloc) +{ + CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); + CopyIn creds(cred, reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); + void *keyData; + mach_msg_type_number_t keyDataLength; + + IPCKEY(ucsp_client_wrapKey(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), wrappingKey, + creds.data(), creds.length(), + keyToBeWrapped, OPTIONALDATA(descriptiveData), + &keyData, &keyDataLength), + keyToBeWrapped, + context.algorithm() == CSSM_ALGID_NONE + ? CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR : CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED); + + CopyOut wrappedKeyXDR(keyData, keyDataLength + sizeof(CSSM_KEY), reinterpret_cast(xdr_CSSM_KEY_PTR), true); + CssmWrappedKey *wrappedKeyIPC = reinterpret_cast(wrappedKeyXDR.data()); + wrappedKey.header() = wrappedKeyIPC->header(); + wrappedKey.keyData() = CssmData(alloc.malloc(wrappedKeyIPC->keyData().length()), wrappedKeyIPC->keyData().length()); + memcpy(wrappedKey.keyData().data(), wrappedKeyIPC->keyData(), wrappedKeyIPC->keyData().length()); +} + +void ClientSession::unwrapKey(DbHandle db, const Context &context, KeyHandle key, + KeyHandle publicKey, const CssmWrappedKey &wrappedKey, + uint32 usage, uint32 attr, + const AccessCredentials *cred, const AclEntryInput *acl, + CssmData &descriptiveData, + KeyHandle &newKey, CssmKey::Header &newHeader, Allocator &alloc) +{ + CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); + DataOutput descriptor(descriptiveData, alloc); + CopyIn creds(cred, reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); + CopyIn proto(acl ? &acl->proto() : NULL, reinterpret_cast(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); + CopyIn wrappedKeyXDR(&wrappedKey, reinterpret_cast(xdr_CSSM_KEY)); + void *keyHeaderData; + mach_msg_type_number_t keyHeaderDataLength; + + IPCKEY(ucsp_client_unwrapKey(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), key, + creds.data(), creds.length(), proto.data(), proto.length(), + publicKey, wrappedKeyXDR.data(), wrappedKeyXDR.length(), usage, attr, DATA_OUT(descriptor), + &newKey, &keyHeaderData, &keyHeaderDataLength), + key, CSSM_ACL_AUTHORIZATION_DECRYPT); + + CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast(xdr_CSSM_KEYHEADER_PTR), true); + newHeader = *static_cast(reinterpret_cast(wrappedKeyHeaderXDR.data())); +} + + +// +// ACL management +// +void ClientSession::getAcl(AclKind kind, GenericHandle key, const char *tag, + uint32 &infoCount, AclEntryInfo * &infoArray, Allocator &alloc) +{ + uint32 count; + void* info; mach_msg_type_number_t infoLength; + IPC(ucsp_client_getAcl(UCSP_ARGS, kind, key, + (tag != NULL), tag ? tag : "", + &count, &info, &infoLength)); + + CSSM_ACL_ENTRY_INFO_ARRAY_PTR aclsArray; + if (!::copyout_chunked(info, infoLength, reinterpret_cast(xdr_CSSM_ACL_ENTRY_INFO_ARRAY_PTR), reinterpret_cast(&aclsArray))) + CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR); + + infoCount = aclsArray->count; + infoArray = reinterpret_cast(aclsArray->acls); + free(aclsArray); +} + +void ClientSession::changeAcl(AclKind kind, GenericHandle key, const AccessCredentials &cred, + const AclEdit &edit) +{ + CopyIn creds(&cred, reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); + //@@@ ignoring callback + CopyIn newEntry(edit.newEntry(), reinterpret_cast(xdr_CSSM_ACL_ENTRY_INPUT)); + + IPCKEY(ucsp_client_changeAcl(UCSP_ARGS, kind, key, creds.data(), creds.length(), + edit.mode(), toIPCHandle(edit.handle()), newEntry.data(), newEntry.length()), + key, CSSM_ACL_AUTHORIZATION_CHANGE_ACL); +} + +void ClientSession::getOwner(AclKind kind, GenericHandle key, AclOwnerPrototype &owner, + Allocator &alloc) +{ + void* proto; mach_msg_type_number_t protoLength; + IPC(ucsp_client_getOwner(UCSP_ARGS, kind, key, &proto, &protoLength)); + + CSSM_ACL_OWNER_PROTOTYPE_PTR tmpOwner; + if (!::copyout_chunked(proto, protoLength, reinterpret_cast(xdr_CSSM_ACL_OWNER_PROTOTYPE_PTR), reinterpret_cast(&tmpOwner))) + CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR); + owner = *static_cast(tmpOwner); + free(tmpOwner); +} + +void ClientSession::changeOwner(AclKind kind, GenericHandle key, + const AccessCredentials &cred, const AclOwnerPrototype &proto) +{ + CopyIn creds(&cred, reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); + CopyIn protos(&proto, reinterpret_cast(xdr_CSSM_ACL_OWNER_PROTOTYPE)); + IPCKEY(ucsp_client_setOwner(UCSP_ARGS, kind, key, creds.data(), creds.length(), protos.data(), protos.length()), + key, CSSM_ACL_AUTHORIZATION_CHANGE_OWNER); +} + + +void ClientSession::getKeyAcl(DbHandle db, const char *tag, + uint32 &count, AclEntryInfo * &info, Allocator &alloc) +{ getAcl(keyAcl, db, tag, count, info, alloc); } + +void ClientSession::changeKeyAcl(DbHandle db, const AccessCredentials &cred, + const AclEdit &edit) +{ changeAcl(keyAcl, db, cred, edit); } + +void ClientSession::getKeyOwner(DbHandle db, AclOwnerPrototype &owner, Allocator &alloc) +{ getOwner(keyAcl, db, owner, alloc); } + +void ClientSession::changeKeyOwner(DbHandle db, const AccessCredentials &cred, + const AclOwnerPrototype &edit) +{ changeOwner(keyAcl, db, cred, edit); } + +void ClientSession::getDbAcl(DbHandle db, const char *tag, + uint32 &count, AclEntryInfo * &info, Allocator &alloc) +{ getAcl(dbAcl, db, tag, count, info, alloc); } + +void ClientSession::changeDbAcl(DbHandle db, const AccessCredentials &cred, + const AclEdit &edit) +{ changeAcl(dbAcl, db, cred, edit); } + +void ClientSession::getDbOwner(DbHandle db, AclOwnerPrototype &owner, Allocator &alloc) +{ getOwner(dbAcl, db, owner, alloc); } + +void ClientSession::changeDbOwner(DbHandle db, const AccessCredentials &cred, + const AclOwnerPrototype &edit) +{ changeOwner(dbAcl, db, cred, edit); } + + +// +// Database key management +// +void ClientSession::extractMasterKey(DbHandle db, const Context &context, DbHandle sourceDb, + uint32 keyUsage, uint32 keyAttr, + const AccessCredentials *cred, const AclEntryInput *owner, + KeyHandle &newKey, CssmKey::Header &newHeader, Allocator &alloc) +{ + CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); + CopyIn creds(cred, reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); + CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); + void *keyHeaderData; + mach_msg_type_number_t keyHeaderDataLength; + + IPC(ucsp_client_extractMasterKey(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), sourceDb, + creds.data(), creds.length(), proto.data(), proto.length(), + keyUsage, keyAttr, &newKey, &keyHeaderData, &keyHeaderDataLength)); + + CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast(xdr_CSSM_KEYHEADER_PTR), true); + newHeader = *static_cast(reinterpret_cast(wrappedKeyHeaderXDR.data())); +} + + +// +// Authorization subsystem entry +// +void ClientSession::authCreate(const AuthorizationItemSet *rights, + const AuthorizationItemSet *environment, AuthorizationFlags flags, + AuthorizationBlob &result) +{ + void *rightSet = NULL; mach_msg_size_t rightSet_size = 0; + void *environ = NULL; mach_msg_size_t environ_size = 0; + + if ((rights && + !copyin_AuthorizationItemSet(rights, &rightSet, &rightSet_size)) || + (environment && + !copyin_AuthorizationItemSet(environment, &environ, &environ_size))) + CssmError::throwMe(errAuthorizationInternal); + + activate(); + IPCSTART(ucsp_client_authorizationCreate(UCSP_ARGS, + rightSet, rightSet_size, + flags, + environ, environ_size, + &result)); + + free(rightSet); + free(environ); + + if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) + CssmError::throwMe(errAuthorizationInteractionNotAllowed); + IPCEND_CHECK; +} + +void ClientSession::authRelease(const AuthorizationBlob &auth, + AuthorizationFlags flags) +{ + activate(); + IPCSTART(ucsp_client_authorizationRelease(UCSP_ARGS, auth, flags)); + if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) + CssmError::throwMe(errAuthorizationInteractionNotAllowed); + IPCEND_CHECK; +} + +void ClientSession::authCopyRights(const AuthorizationBlob &auth, + const AuthorizationItemSet *rights, const AuthorizationItemSet *environment, + AuthorizationFlags flags, + AuthorizationItemSet **grantedRights) +{ + void *rightSet = NULL; mach_msg_size_t rightSet_size = 0; + void *environ = NULL; mach_msg_size_t environ_size = 0; + void *result = NULL; mach_msg_type_number_t resultLength = 0; + + if ((rights && !copyin_AuthorizationItemSet(rights, &rightSet, &rightSet_size)) || + (environment && !copyin_AuthorizationItemSet(environment, &environ, &environ_size))) + CssmError::throwMe(errAuthorizationInternal); // allocation error probably + + activate(); + IPCSTART(ucsp_client_authorizationCopyRights(UCSP_ARGS, + auth, + rightSet, rightSet_size, + flags | (grantedRights ? 0 : kAuthorizationFlagNoData), + environ, environ_size, + &result, &resultLength)); + + free(rightSet); + free(environ); + + // XXX/cs return error when copyout returns false + if (rcode == CSSM_OK && grantedRights) + copyout_AuthorizationItemSet(result, resultLength, grantedRights); + + if (result) + mig_deallocate(reinterpret_cast(result), resultLength); + if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) + CssmError::throwMe(errAuthorizationInteractionNotAllowed); + IPCEND_CHECK; +} + +void ClientSession::authCopyInfo(const AuthorizationBlob &auth, + const char *tag, + AuthorizationItemSet * &info) +{ + if (tag == NULL) + tag = ""; + else if (tag[0] == '\0') + MacOSError::throwMe(errAuthorizationInvalidTag); + + activate(); + void *result; mach_msg_type_number_t resultLength; + IPCSTART(ucsp_client_authorizationCopyInfo(UCSP_ARGS, auth, tag, &result, &resultLength)); + + // XXX/cs return error when copyout returns false + if (rcode == CSSM_OK) + copyout_AuthorizationItemSet(result, resultLength, &info); + + if (result) + mig_deallocate(reinterpret_cast(result), resultLength); + + if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) + CssmError::throwMe(errAuthorizationInteractionNotAllowed); + IPCEND_CHECK; +} + +void ClientSession::authExternalize(const AuthorizationBlob &auth, + AuthorizationExternalForm &extForm) +{ + activate(); + IPCSTART(ucsp_client_authorizationExternalize(UCSP_ARGS, auth, &extForm)); + if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) + CssmError::throwMe(errAuthorizationInteractionNotAllowed); + IPCEND_CHECK; +} + +void ClientSession::authInternalize(const AuthorizationExternalForm &extForm, + AuthorizationBlob &auth) +{ + activate(); + IPCSTART(ucsp_client_authorizationInternalize(UCSP_ARGS, extForm, &auth)); + if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) + CssmError::throwMe(errAuthorizationInteractionNotAllowed); + IPCEND_CHECK; +} + + +// +// Push user preferences from an app in user space to securityd +// +void ClientSession::setSessionUserPrefs(SecuritySessionId sessionId, uint32_t userPreferencesLength, const void *userPreferences) +{ + IPC(ucsp_client_setSessionUserPrefs(UCSP_ARGS, sessionId, const_cast(userPreferences), userPreferencesLength)); +} + + +void ClientSession::postNotification(NotificationDomain domain, NotificationEvent event, const CssmData &data) +{ + uint32 seq = ++mGlobal().thread().notifySeq; +#if !defined(NDEBUG) + if (getenv("NOTIFYJITTER")) { + // artificially reverse odd/even sequences to test securityd's jitter buffer + seq += 2 * (seq % 2) - 1; + secdebug("notify", "POSTING FAKE SEQUENCE %d NOTIFICATION", seq); + } +#endif //NDEBUG + secdebug("notify", "posting domain 0x%x event %d sequence %d", + domain, event, seq); + IPC(ucsp_client_postNotification(UCSP_ARGS, domain, event, DATA(data), seq)); +} + +// +// authorizationdbGet/Set/Remove +// +void ClientSession::authorizationdbGet(const AuthorizationString rightname, CssmData &rightDefinition, Allocator &alloc) +{ + DataOutput definition(rightDefinition, alloc); + activate(); + IPCSTART(ucsp_client_authorizationdbGet(UCSP_ARGS, rightname, DATA_OUT(definition))); + if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) + CssmError::throwMe(errAuthorizationInteractionNotAllowed); + IPCEND_CHECK; +} + +void ClientSession::authorizationdbSet(const AuthorizationBlob &auth, const AuthorizationString rightname, uint32_t rightDefinitionLength, const void *rightDefinition) +{ + // @@@ DATA_IN in transition.cpp is not const void * + activate(); + IPCSTART(ucsp_client_authorizationdbSet(UCSP_ARGS, auth, rightname, const_cast(rightDefinition), rightDefinitionLength)); + if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) + CssmError::throwMe(errAuthorizationInteractionNotAllowed); + IPCEND_CHECK; +} + +void ClientSession::authorizationdbRemove(const AuthorizationBlob &auth, const AuthorizationString rightname) +{ + activate(); + IPCSTART(ucsp_client_authorizationdbRemove(UCSP_ARGS, auth, rightname)); + if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) + CssmError::throwMe(errAuthorizationInteractionNotAllowed); + IPCEND_CHECK; +} + + +// +// Miscellaneous administrative calls +// +void ClientSession::addCodeEquivalence(const CssmData &oldHash, const CssmData &newHash, + const char *name, bool forSystem /* = false */) +{ + IPC(ucsp_client_addCodeEquivalence(UCSP_ARGS, DATA(oldHash), DATA(newHash), + name, forSystem)); +} + +void ClientSession::removeCodeEquivalence(const CssmData &hash, const char *name, bool forSystem /* = false */) +{ + IPC(ucsp_client_removeCodeEquivalence(UCSP_ARGS, DATA(hash), name, forSystem)); +} + +void ClientSession::setAlternateSystemRoot(const char *path) +{ + IPC(ucsp_client_setAlternateSystemRoot(UCSP_ARGS, path)); +} + + +// +// Code Signing related +// +void ClientSession::registerHosting(mach_port_t hostingPort, SecCSFlags flags) +{ + IPC(ucsp_client_registerHosting(UCSP_ARGS, hostingPort, flags)); +} + +mach_port_t ClientSession::hostingPort(pid_t pid) +{ + mach_port_t result; + IPC(ucsp_client_hostingPort(UCSP_ARGS, pid, &result)); + return result; +} + +SecGuestRef ClientSession::createGuest(SecGuestRef host, + uint32_t status, const char *path, const CssmData &cdhash, const CssmData &attributes, SecCSFlags flags) +{ + SecGuestRef newGuest; + IPC(ucsp_client_createGuest(UCSP_ARGS, host, status, path, DATA(cdhash), DATA(attributes), flags, &newGuest)); + if (flags & kSecCSDedicatedHost) { + secdebug("ssclient", "setting dedicated guest to 0x%x (was 0x%x)", + mDedicatedGuest, newGuest); + mDedicatedGuest = newGuest; + } + return newGuest; +} + +void ClientSession::setGuestStatus(SecGuestRef guest, uint32 status, const CssmData &attributes) +{ + IPC(ucsp_client_setGuestStatus(UCSP_ARGS, guest, status, DATA(attributes))); +} + +void ClientSession::removeGuest(SecGuestRef host, SecGuestRef guest) +{ + IPC(ucsp_client_removeGuest(UCSP_ARGS, host, guest)); +} + +void ClientSession::selectGuest(SecGuestRef newGuest) +{ + if (mDedicatedGuest) { + secdebug("ssclient", "ignoring selectGuest(0x%x) because dedicated guest=0x%x", + newGuest, mDedicatedGuest); + } else { + secdebug("ssclient", "switching to guest 0x%x", newGuest); + mGlobal().thread().currentGuest = newGuest; + } +} + +SecGuestRef ClientSession::selectedGuest() const +{ + if (mDedicatedGuest) + return mDedicatedGuest; + else + return mGlobal().thread().currentGuest; +} + + +} // end namespace SecurityServer +} // end namespace Security diff --git a/libsecurityd/lib/ucsp_types.h b/Security/libsecurityd/lib/ucsp_types.h similarity index 95% rename from libsecurityd/lib/ucsp_types.h rename to Security/libsecurityd/lib/ucsp_types.h index 95722af1..5f7aa2f1 100644 --- a/libsecurityd/lib/ucsp_types.h +++ b/Security/libsecurityd/lib/ucsp_types.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2007,2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/xdr_auth.c b/Security/libsecurityd/lib/xdr_auth.c similarity index 97% rename from libsecurityd/lib/xdr_auth.c rename to Security/libsecurityd/lib/xdr_auth.c index b04a69c3..69ac9335 100644 --- a/libsecurityd/lib/xdr_auth.c +++ b/Security/libsecurityd/lib/xdr_auth.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/xdr_auth.h b/Security/libsecurityd/lib/xdr_auth.h similarity index 95% rename from libsecurityd/lib/xdr_auth.h rename to Security/libsecurityd/lib/xdr_auth.h index 11effdcb..b1643246 100644 --- a/libsecurityd/lib/xdr_auth.h +++ b/Security/libsecurityd/lib/xdr_auth.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/xdr_cssm.c b/Security/libsecurityd/lib/xdr_cssm.c similarity index 99% rename from libsecurityd/lib/xdr_cssm.c rename to Security/libsecurityd/lib/xdr_cssm.c index a7a8cc8b..e8a4b976 100644 --- a/libsecurityd/lib/xdr_cssm.c +++ b/Security/libsecurityd/lib/xdr_cssm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2008,2011-2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/xdr_cssm.h b/Security/libsecurityd/lib/xdr_cssm.h similarity index 99% rename from libsecurityd/lib/xdr_cssm.h rename to Security/libsecurityd/lib/xdr_cssm.h index 32384d9b..ebeba27a 100644 --- a/libsecurityd/lib/xdr_cssm.h +++ b/Security/libsecurityd/lib/xdr_cssm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/xdr_dldb.cpp b/Security/libsecurityd/lib/xdr_dldb.cpp similarity index 96% rename from libsecurityd/lib/xdr_dldb.cpp rename to Security/libsecurityd/lib/xdr_dldb.cpp index be66b9d7..eb8ffa11 100644 --- a/libsecurityd/lib/xdr_dldb.cpp +++ b/Security/libsecurityd/lib/xdr_dldb.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/lib/xdr_dldb.h b/Security/libsecurityd/lib/xdr_dldb.h similarity index 97% rename from libsecurityd/lib/xdr_dldb.h rename to Security/libsecurityd/lib/xdr_dldb.h index 65e0f604..d1dd0e03 100644 --- a/libsecurityd/lib/xdr_dldb.h +++ b/Security/libsecurityd/lib/xdr_dldb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2006,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/libsecurityd/libsecurityd.xcodeproj/project.pbxproj b/Security/libsecurityd/libsecurityd.xcodeproj/project.pbxproj similarity index 100% rename from libsecurityd/libsecurityd.xcodeproj/project.pbxproj rename to Security/libsecurityd/libsecurityd.xcodeproj/project.pbxproj diff --git a/libsecurityd/mig/cshosting.defs b/Security/libsecurityd/mig/cshosting.defs similarity index 97% rename from libsecurityd/mig/cshosting.defs rename to Security/libsecurityd/mig/cshosting.defs index f4353e30..7d4b45df 100644 --- a/libsecurityd/mig/cshosting.defs +++ b/Security/libsecurityd/mig/cshosting.defs @@ -1,5 +1,5 @@ // -// Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. +// Copyright (c) 2006,2011,2014 Apple Inc. All Rights Reserved. // // @APPLE_LICENSE_HEADER_START@ // diff --git a/Security/libsecurityd/mig/mig.mk b/Security/libsecurityd/mig/mig.mk new file mode 100644 index 00000000..4c6ad3cd --- /dev/null +++ b/Security/libsecurityd/mig/mig.mk @@ -0,0 +1,67 @@ +# +# Copyright (c) 2003-2004,2006-2007,2011,2014 Apple Inc. All Rights Reserved. +# +# @APPLE_LICENSE_HEADER_START@ +# +# This file contains Original Code and/or Modifications of Original Code +# as defined in and that are subject to the Apple Public Source License +# Version 2.0 (the 'License'). You may not use this file except in +# compliance with the License. Please obtain a copy of the License at +# http://www.opensource.apple.com/apsl/ and read it before using this +# file. +# +# The Original Code and all software distributed under the License are +# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +# Please see the License for the specific language governing rights and +# limitations under the License. +# +# @APPLE_LICENSE_HEADER_END@ +# +# Makefile to build MIG-generated sources and headers +# +DERIVED_SRC = $(BUILT_PRODUCTS_DIR)/derived_src/securityd_client + +HDRS = $(DERIVED_SRC)/ucsp.h $(DERIVED_SRC)/ucspNotify.h $(DERIVED_SRC)/cshosting.h +SRCS = $(DERIVED_SRC)/ucspServer.cpp $(DERIVED_SRC)/ucspClient.cpp \ + $(DERIVED_SRC)/ucspClientC.c \ + $(DERIVED_SRC)/ucspNotifyReceiver.cpp $(DERIVED_SRC)/ucspNotifySender.cpp \ + $(DERIVED_SRC)/cshostingServer.cpp $(DERIVED_SRC)/cshostingClient.cpp +INCLUDES = $(PROJECT_DIR)/mig/ss_types.defs +SDKROOT := $(shell xcrun --show-sdk-path --sdk macosx.internal) +build: $(HDRS) $(SRCS) + +install: build + +installhdrs: $(HDRS) + +installsrc: + +clean: + rm -f $(HDRS) $(SRCS) + +$(DERIVED_SRC)/ucsp.h $(DERIVED_SRC)/ucspServer.cpp $(DERIVED_SRC)/ucspClient.cpp: $(PROJECT_DIR)/mig/ucsp.defs $(INCLUDES) + mkdir -p $(DERIVED_SRC) + xcrun mig -isysroot "$(SDKROOT)" \ + -server $(DERIVED_SRC)/ucspServer.cpp \ + -user $(DERIVED_SRC)/ucspClient.cpp \ + -header $(DERIVED_SRC)/ucsp.h $(PROJECT_DIR)/mig/ucsp.defs + +$(DERIVED_SRC)/ucspClientC.c: $(DERIVED_SRC)/ucspClient.cpp + cp $(DERIVED_SRC)/ucspClient.cpp $(DERIVED_SRC)/ucspClientC.c + +$(DERIVED_SRC)/ucspNotify.h $(DERIVED_SRC)/ucspNotifyReceiver.cpp $(DERIVED_SRC)/ucspNotifySender.cpp: $(PROJECT_DIR)/mig/ucspNotify.defs $(INCLUDES) + mkdir -p $(DERIVED_SRC) + xcrun mig -isysroot "$(SDKROOT)" \ + -server $(DERIVED_SRC)/ucspNotifyReceiver.cpp \ + -user $(DERIVED_SRC)/ucspNotifySender.cpp \ + -header $(DERIVED_SRC)/ucspNotify.h $(PROJECT_DIR)/mig/ucspNotify.defs + +$(DERIVED_SRC)/cshosting.h $(DERIVED_SRC)/cshostingServer.cpp $(DERIVED_SRC)/cshostingClient.cpp: $(PROJECT_DIR)/mig/cshosting.defs $(INCLUDES) + mkdir -p $(DERIVED_SRC) + xcrun mig -isysroot "$(SDKROOT)" \ + -server $(DERIVED_SRC)/cshostingServer.cpp \ + -user $(DERIVED_SRC)/cshostingClient.cpp \ + -header $(DERIVED_SRC)/cshosting.h $(PROJECT_DIR)/mig/cshosting.defs diff --git a/libsecurityd/mig/ss_types.defs b/Security/libsecurityd/mig/ss_types.defs similarity index 98% rename from libsecurityd/mig/ss_types.defs rename to Security/libsecurityd/mig/ss_types.defs index 515928d4..3eba6c92 100644 --- a/libsecurityd/mig/ss_types.defs +++ b/Security/libsecurityd/mig/ss_types.defs @@ -1,5 +1,5 @@ // -// Copyright (c) 2004,2006-2007 Apple Inc. All Rights Reserved. +// Copyright (c) 2004,2006-2007,2011 Apple Inc. All Rights Reserved. // // @APPLE_LICENSE_HEADER_START@ // diff --git a/libsecurityd/mig/ucsp.defs b/Security/libsecurityd/mig/ucsp.defs similarity index 99% rename from libsecurityd/mig/ucsp.defs rename to Security/libsecurityd/mig/ucsp.defs index a0fdaf11..d2d70334 100644 --- a/libsecurityd/mig/ucsp.defs +++ b/Security/libsecurityd/mig/ucsp.defs @@ -1,5 +1,5 @@ // -// Copyright (c) 2001-2007 Apple Inc. All Rights Reserved. +// Copyright (c) 2001-2007,2011-2013 Apple Inc. All Rights Reserved. // // @APPLE_LICENSE_HEADER_START@ // diff --git a/libsecurityd/mig/ucspNotify.defs b/Security/libsecurityd/mig/ucspNotify.defs similarity index 96% rename from libsecurityd/mig/ucspNotify.defs rename to Security/libsecurityd/mig/ucspNotify.defs index 7b6dd149..ac61db94 100644 --- a/libsecurityd/mig/ucspNotify.defs +++ b/Security/libsecurityd/mig/ucspNotify.defs @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2004,2006 Apple Computer, Inc. All Rights Reserved. +// Copyright (c) 2002-2004,2006,2011,2014 Apple Inc. All Rights Reserved. // // @APPLE_LICENSE_HEADER_START@ // diff --git a/regressions/README b/Security/regressions/README similarity index 100% rename from regressions/README rename to Security/regressions/README diff --git a/regressions/inc/IPC/Run3.pm b/Security/regressions/inc/IPC/Run3.pm similarity index 100% rename from regressions/inc/IPC/Run3.pm rename to Security/regressions/inc/IPC/Run3.pm diff --git a/regressions/inc/MyHarness.pm b/Security/regressions/inc/MyHarness.pm similarity index 100% rename from regressions/inc/MyHarness.pm rename to Security/regressions/inc/MyHarness.pm diff --git a/Security/regressions/regressions.xcodeproj/project.pbxproj b/Security/regressions/regressions.xcodeproj/project.pbxproj new file mode 100644 index 00000000..ceecb024 --- /dev/null +++ b/Security/regressions/regressions.xcodeproj/project.pbxproj @@ -0,0 +1,351 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 4CC92AB915A3B19D00C6D578 /* testlist_end.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92AB815A3B19D00C6D578 /* testlist_end.h */; settings = {ATTRIBUTES = (); }; }; + 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 */; }; + 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 = (); }; }; + E723A61013DA18C50075AAC1 /* testenv.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C25A6C512271FAF0050C2BD /* testenv.h */; settings = {ATTRIBUTES = (); }; }; + E723A61113DA18C50075AAC1 /* testmore.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C25A6C912271FAF0050C2BD /* testmore.h */; settings = {ATTRIBUTES = (); }; }; + E723A61213DA18C50075AAC1 /* testcert.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C25A6CB12271FAF0050C2BD /* testcert.h */; settings = {ATTRIBUTES = (); }; }; + E723A61313DA18C50075AAC1 /* testpolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = E76CA47B13D8D5CB001B6A11 /* testpolicy.h */; settings = {ATTRIBUTES = (); }; }; + E76CA47913D8D5B4001B6A11 /* testpolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = E76CA47813D8D5B4001B6A11 /* testpolicy.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 0C25A68F12271FAF0050C2BD /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; + 0C25A69212271FAF0050C2BD /* Run3.pm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = Run3.pm; sourceTree = ""; }; + 0C25A69312271FAF0050C2BD /* MyHarness.pm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = MyHarness.pm; sourceTree = ""; }; + 0C25A6C012271FAF0050C2BD /* security.pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = security.pl; sourceTree = ""; }; + 0C25A6C312271FAF0050C2BD /* testcpp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testcpp.h; sourceTree = ""; }; + 0C25A6C412271FAF0050C2BD /* testenv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testenv.c; sourceTree = ""; }; + 0C25A6C512271FAF0050C2BD /* testenv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testenv.h; sourceTree = ""; }; + 0C25A6C812271FAF0050C2BD /* testmore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testmore.c; sourceTree = ""; }; + 0C25A6C912271FAF0050C2BD /* testmore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testmore.h; sourceTree = ""; }; + 0C25A6CA12271FAF0050C2BD /* testcert.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testcert.c; sourceTree = ""; }; + 0C25A6CB12271FAF0050C2BD /* testcert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testcert.h; sourceTree = ""; }; + 0C25A6CE12271FAF0050C2BD /* run_tests.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = run_tests.sh; sourceTree = ""; }; + 4CC92AB715A3B19100C6D578 /* testlist_begin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = testlist_begin.h; sourceTree = ""; }; + 4CC92AB815A3B19D00C6D578 /* testlist_end.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testlist_end.h; sourceTree = ""; }; + 4CC92ABB15A3B51100C6D578 /* test_regressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = test_regressions.h; sourceTree = ""; }; + 4CC92B1615A3BD1E00C6D578 /* test-00-test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "test-00-test.c"; sourceTree = ""; }; + E710C6FE133192E900F85568 /* libregressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libregressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; + E76CA47813D8D5B4001B6A11 /* testpolicy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = testpolicy.m; sourceTree = ""; }; + E76CA47B13D8D5CB001B6A11 /* testpolicy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testpolicy.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + E710C6FB133192E900F85568 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 05441E5C08A971C700F0EC5A = { + isa = PBXGroup; + children = ( + 0C25A68F12271FAF0050C2BD /* README */, + 0C25A69012271FAF0050C2BD /* inc */, + 0C25A6BF12271FAF0050C2BD /* t */, + 0C25A6C112271FAF0050C2BD /* test */, + E710C6FE133192E900F85568 /* libregressions.a */, + ); + sourceTree = ""; + }; + 0C25A69012271FAF0050C2BD /* inc */ = { + isa = PBXGroup; + children = ( + 0C25A69112271FAF0050C2BD /* IPC */, + 0C25A69312271FAF0050C2BD /* MyHarness.pm */, + ); + path = inc; + sourceTree = ""; + }; + 0C25A69112271FAF0050C2BD /* IPC */ = { + isa = PBXGroup; + children = ( + 0C25A69212271FAF0050C2BD /* Run3.pm */, + ); + path = IPC; + sourceTree = ""; + }; + 0C25A6BF12271FAF0050C2BD /* t */ = { + isa = PBXGroup; + children = ( + 0C25A6C012271FAF0050C2BD /* security.pl */, + ); + path = t; + sourceTree = ""; + }; + 0C25A6C112271FAF0050C2BD /* test */ = { + isa = PBXGroup; + children = ( + 4CC92B1615A3BD1E00C6D578 /* test-00-test.c */, + 4CC92ABB15A3B51100C6D578 /* test_regressions.h */, + 4CC92AB715A3B19100C6D578 /* testlist_begin.h */, + 4CC92AB815A3B19D00C6D578 /* testlist_end.h */, + 0C25A6C312271FAF0050C2BD /* testcpp.h */, + 0C25A6C412271FAF0050C2BD /* testenv.c */, + 0C25A6C512271FAF0050C2BD /* testenv.h */, + 0C25A6C812271FAF0050C2BD /* testmore.c */, + 0C25A6C912271FAF0050C2BD /* testmore.h */, + 0C25A6CA12271FAF0050C2BD /* testcert.c */, + 0C25A6CB12271FAF0050C2BD /* testcert.h */, + E76CA47B13D8D5CB001B6A11 /* testpolicy.h */, + E76CA47813D8D5B4001B6A11 /* testpolicy.m */, + 0C25A6CE12271FAF0050C2BD /* run_tests.sh */, + ); + path = test; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + E710C6FC133192E900F85568 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + E723A61113DA18C50075AAC1 /* testmore.h in Headers */, + 4CC92ABC15A3B51100C6D578 /* test_regressions.h in Headers */, + 4CC92ABD15A3B8FB00C6D578 /* testlist_begin.h in Headers */, + 4CC92AB915A3B19D00C6D578 /* testlist_end.h in Headers */, + E723A61213DA18C50075AAC1 /* testcert.h in Headers */, + E723A60F13DA18C50075AAC1 /* testcpp.h in Headers */, + E723A61013DA18C50075AAC1 /* testenv.h in Headers */, + E723A61313DA18C50075AAC1 /* testpolicy.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + E710C6FD133192E900F85568 /* regressions */ = { + isa = PBXNativeTarget; + buildConfigurationList = E710C703133192E900F85568 /* Build configuration list for PBXNativeTarget "regressions" */; + buildPhases = ( + E710C6FA133192E900F85568 /* Sources */, + E710C6FB133192E900F85568 /* Frameworks */, + E710C6FC133192E900F85568 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = regressions; + productName = regressions; + productReference = E710C6FE133192E900F85568 /* libregressions.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 05441E6008A971C700F0EC5A /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0600; + }; + buildConfigurationList = 4CD81AFC09BE1FD3000A9641 /* Build configuration list for PBXProject "regressions" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 05441E5C08A971C700F0EC5A; + productRefGroup = 05441E5C08A971C700F0EC5A; + projectDirPath = ""; + projectRoot = ""; + targets = ( + E710C6FD133192E900F85568 /* regressions */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + E710C6FA133192E900F85568 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E710C7371331938000F85568 /* testenv.c in Sources */, + E710C7381331938000F85568 /* testmore.c in Sources */, + E710C7391331938000F85568 /* testcert.c in Sources */, + E76CA47913D8D5B4001B6A11 /* testpolicy.m in Sources */, + 4CC92B1715A3BD1E00C6D578 /* test-00-test.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 792E01860CBC0E6E007C00A0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + CLANG_STATIC_ANALYZER_MODE = deep; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; + "GCC_PREPROCESSOR_DEFINITIONS[sdk=iphoneos*]" = ( + "DEBUG=1", + "NO_SERVER=1", + ); + "GCC_PREPROCESSOR_DEFINITIONS[sdk=iphonesimulator*]" = ( + "DEBUG=1", + "NO_SERVER=1", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = NO; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_VALUE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/../utilities", + "$(PROJECT_DIR)/../sec", + "$(PROJECT_DIR)/../libDER", + "$(PROJECT_DIR)/..", + "$(PROJECT_DIR)", + "$(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include", + ); + OTHER_CFLAGS = ( + "-fconstant-cfstrings", + "-fno-inline", + ); + "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( + "$(OTHER_LDFLAGS)", + "-framework", + MobileKeyBag, + ); + RUN_CLANG_STATIC_ANALYZER = YES; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-unused-parameter", + "-Wno-missing-field-initializers", + "-Wglobal-constructors", + "-Wno-deprecated-declarations", + "$(inherited)", + ); + }; + name = Debug; + }; + 792E01870CBC0E6E007C00A0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + CLANG_STATIC_ANALYZER_MODE = deep; + COPY_PHASE_STRIP = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_OPTIMIZATION_LEVEL = s; + GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1"; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_VALUE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/../utilities", + "$(PROJECT_DIR)/../sec", + "$(PROJECT_DIR)/../libDER", + "$(PROJECT_DIR)/..", + "$(PROJECT_DIR)", + "$(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include", + ); + OTHER_CFLAGS = "-fconstant-cfstrings"; + RUN_CLANG_STATIC_ANALYZER = YES; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-unused-parameter", + "-Wno-missing-field-initializers", + "-Wglobal-constructors", + "-Wno-deprecated-declarations", + "$(inherited)", + ); + }; + name = Release; + }; + E710C704133192E900F85568 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + E710C705133192E900F85568 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4CD81AFC09BE1FD3000A9641 /* Build configuration list for PBXProject "regressions" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 792E01860CBC0E6E007C00A0 /* Debug */, + 792E01870CBC0E6E007C00A0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E710C703133192E900F85568 /* Build configuration list for PBXNativeTarget "regressions" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E710C704133192E900F85568 /* Debug */, + E710C705133192E900F85568 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 05441E6008A971C700F0EC5A /* Project object */; +} diff --git a/Security/regressions/t/security.pl b/Security/regressions/t/security.pl new file mode 100755 index 00000000..6176229d --- /dev/null +++ b/Security/regressions/t/security.pl @@ -0,0 +1,68 @@ +#!/usr/bin/perl -w +# +# Copyright (c) 2006-2007,2012 Apple Inc. All Rights Reserved. +# + +my $pid = $$; + +END { + return unless $$ == $pid; + rm_test($_) for @TOCLEAN; +} + +use strict; +use Test::More; +use IPC::Run3; + +sub plan_security { + + unless (1) { + plan skip_all => "security not installed"; + exit; + }; + plan @_; +} + +use Carp; +our @TOCLEAN; +END { + return unless $$ == $pid; + $SIG{__WARN__} = sub { 1 }; + cleanup_test($_) for @TOCLEAN; +} + +our $output = ''; + +sub build_test { + my $xd = "/tmp/test-$pid"; + my $security = 'security'; + $ENV{HOME} = $xd; + push @TOCLEAN, [$xd, $security]; + return ($xd, $security); +} + +sub rm_test { + my ($xd, $security) = @{+shift}; + #rmtree [$xd]; +} + +sub cleanup_test { + return unless $ENV{TEST_VERBOSE}; + my ($xd, $security) = @{+shift}; +} + +sub is_output { + my ($security, $cmd, $arg, $expected, $test) = @_; + $output = ''; + run3([$security, $cmd, @$arg], \undef, \$output, \$output); +# open(STDOUT, ">&STDERR") || die "couldn't dup strerr: $!"; +# open(my $out, '-|', $security, $cmd, @$arg); +# while (<$out>) { $output .= $_; } + + my $cmp = (grep {ref ($_) eq 'Regexp'} @$expected) + ? \&is_deeply_like : \&is_deeply; + @_ = ([sort split (/\r?\n/, $output)], [sort @$expected], $test || join(' ', $cmd, @$arg)); + goto &$cmp; +} + +1; diff --git a/regressions/test/test-00-test.c b/Security/regressions/test/test-00-test.c similarity index 90% rename from regressions/test/test-00-test.c rename to Security/regressions/test/test-00-test.c index bc0ffa87..5b9e58e7 100644 --- a/regressions/test/test-00-test.c +++ b/Security/regressions/test/test-00-test.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2012,2014 Apple Inc. All Rights Reserved. */ #include @@ -19,6 +19,7 @@ int test_00_test(int argc, char *const *argv) diag("ok bad not good today"); } rv &= ok(1, "ok ok"); + (void) rv; #if 0 SKIP: { skip("is bad will fail", 1, 0); diff --git a/regressions/test/test_regressions.h b/Security/regressions/test/test_regressions.h similarity index 100% rename from regressions/test/test_regressions.h rename to Security/regressions/test/test_regressions.h diff --git a/regressions/test/testcert.c b/Security/regressions/test/testcert.c similarity index 96% rename from regressions/test/testcert.c rename to Security/regressions/test/testcert.c index 3a709225..79365167 100644 --- a/regressions/test/testcert.c +++ b/Security/regressions/test/testcert.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2009,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, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ * * testcert.c @@ -38,18 +38,19 @@ #include "testcert.h" -static inline CFMutableArrayRef maa(CFMutableArrayRef array, CFTypeRef a) { +static inline CF_RETURNS_RETAINED CFMutableArrayRef maa(CFMutableArrayRef array CF_CONSUMED, CFTypeRef a CF_CONSUMED) { CFMutableArrayRef ma = array; if (!ma) ma = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); if (ma) { CFArrayAppendValue(ma, a); - CFRelease(a); } + CFRelease(a); return ma; } +CF_RETURNS_RETAINED CFArrayRef test_cert_string_to_subject(CFStringRef subject) { CFMutableArrayRef subject_array = NULL; diff --git a/regressions/test/testcert.h b/Security/regressions/test/testcert.h similarity index 94% rename from regressions/test/testcert.h rename to Security/regressions/test/testcert.h index 15d1740b..0babe8db 100644 --- a/regressions/test/testcert.h +++ b/Security/regressions/test/testcert.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2009,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, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ * * testcert.h @@ -40,4 +40,5 @@ test_cert_issue_certificate(SecIdentityRef ca_identity, SecKeyRef public_key, CFStringRef subject, unsigned int serial_no, unsigned int key_usage); +CF_RETURNS_RETAINED CFArrayRef test_cert_string_to_subject(CFStringRef subject); diff --git a/Security/regressions/test/testcpp.h b/Security/regressions/test/testcpp.h new file mode 100644 index 00000000..883d65d8 --- /dev/null +++ b/Security/regressions/test/testcpp.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2005-2007,2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + * + * testcpp.h + */ + +#ifndef _TESTCPP_H_ +#define _TESTCPP_H_ 1 + +#include "testmore.h" + +#ifdef __cplusplus + +#define no_throw(THIS, TESTNAME) \ +({ \ + bool _this; \ + try { THIS; _this = true; } catch (...) { _this = false; } \ + test_ok(_this, TESTNAME, test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# got: \n" \ + "# expected: \n"); \ +}) +#define does_throw(THIS, TESTNAME) \ +({ \ + bool _this; \ + try { THIS; _this = false; } catch (...) { _this = true; } \ + test_ok(_this, TESTNAME, test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# got: \n" \ + "# expected: \n"); \ +}) +#define is_throw(THIS, CLASS, METHOD, VALUE, TESTNAME) \ +({ \ + bool _this; \ + try \ + { \ + THIS; \ + _this = test_ok(false, TESTNAME, test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# got: \n" \ + "# expected: %s.%s == %s\n", \ + #CLASS, #METHOD, #VALUE); \ + } \ + catch (const CLASS &_exception) \ + { \ + _this = test_ok(_exception.METHOD == (VALUE), TESTNAME, \ + test_directive, test_reason, __FILE__, __LINE__, \ + "# got: %d\n" \ + "# expected: %s.%s == %s\n", \ + _exception.METHOD, #CLASS, #METHOD, #VALUE); \ + } \ + catch (...) \ + { \ + _this = test_ok(false, TESTNAME, test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# got: \n" \ + "# expected: %s.%s == %s\n", \ + #CLASS, #METHOD, #VALUE); \ + } \ + _this; \ +}) +#endif /* __cplusplus */ + +#endif /* !_TESTCPP_H_ */ diff --git a/Security/regressions/test/testenv.c b/Security/regressions/test/testenv.c new file mode 100644 index 00000000..1f972d86 --- /dev/null +++ b/Security/regressions/test/testenv.c @@ -0,0 +1,345 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "testmore.h" +#include "testenv.h" + +#include +#include +#include + + +int test_strict_bats = 1; +int test_verbose = 0; +int test_onebatstest = 0; + +#ifdef NO_SERVER +#include + +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) +{ + 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); +} +#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); +} + +static int tests_run_index(int i, 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", testlist[i].name); + else + fprintf(stdout, "[BEGIN] %s\n", testlist[i].name); + run_one_test(&testlist[i], argc, argv); + if(testlist[i].failed_tests) { + fprintf(stdout, "[FAIL] %s\n", testlist[i].name); + } else { + fprintf(stdout, "[PASS] %s\n", testlist[i].name); + if (test_verbose) + fprintf(stdout, "(%lu ms)\n", testlist[i].duration); + } + return testlist[i].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_index(i, argc, argv); + optind = curroptind; + } + } + + return failcount; +} + +int +tests_begin(int argc, char * const *argv) +{ + const char *testcase = NULL; + bool initialized = false; + bool print_security_logs = false; + int testix = -1; + int failcount = 0; + int ch; + int loop = 0; + int list = 0; + + // 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': + 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 (print_security_logs) { + add_security_log_handler(^(int level, CFStringRef scope, const char *function, const char *file, int line, CFStringRef message) { + time_t now = time(NULL); + char *date = ctime(&now); + date[19] = '\0'; + CFStringRef logStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, + CFSTR("%s %@ %s %@\n"), date + 4, + scope ? scope : CFSTR(""), function, message); + CFShow(logStr); + CFReleaseSafe(logStr); + }); + } + + 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_index(testix, argc, argv); + testix = -1; + } + } + if (!list) { + if (!test_onebatstest) { + fprintf(stdout, "[%s] %s\n", failcount ? "FAIL" : "PASS", progname); + } + fprintf(stdout, "[SUMMARY]\n"); + } + int sub_tests = 0; + if (failcount) { + fprintf(stdout, "Test name failed total\n"); + fprintf(stdout, "================================================================\n"); + } + for (int i = 0; testlist[i].name; ++i) { + if (!testlist[i].off) { + sub_tests += testlist[i].sub_tests; + if (testlist[i].failed_tests) { + fprintf(stdout, "%-50s %6d %6d\n", testlist[i].name, testlist[i].failed_tests, testlist[i].sub_tests); + } else if (list) { + fprintf(stdout, "%s\n", testlist[i].name); + } + } + } + if (failcount) + fprintf(stdout, "================================================================\n"); + if (!list) + fprintf(stdout, "Total failcount: %6d %6d\n", failcount, sub_tests); + 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/Security/regressions/test/testenv.h b/Security/regressions/test/testenv.h new file mode 100644 index 00000000..0eedd40b --- /dev/null +++ b/Security/regressions/test/testenv.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2005-2007,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@ + * + * testenv.h + */ + +#ifndef _TESTENV_H_ +#define _TESTENV_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int test_strict_bats; +extern int test_verbose; + +int tests_begin(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* !_TESTENV_H_ */ diff --git a/regressions/test/testlist_begin.h b/Security/regressions/test/testlist_begin.h similarity index 100% rename from regressions/test/testlist_begin.h rename to Security/regressions/test/testlist_begin.h diff --git a/regressions/test/testlist_end.h b/Security/regressions/test/testlist_end.h similarity index 100% rename from regressions/test/testlist_end.h rename to Security/regressions/test/testlist_end.h diff --git a/Security/regressions/test/testmore.c b/Security/regressions/test/testmore.c new file mode 100644 index 00000000..c632fe7e --- /dev/null +++ b/Security/regressions/test/testmore.c @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2005-2007,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@ + * + * testmore.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "testmore.h" +#include "testenv.h" + +static int test_num = 0; +static int test_fails = 0; +static int test_cases = 0; +static const char *test_plan_file; +static int test_plan_line=0; + +const char *test_directive = NULL; +const char *test_reason = NULL; + +static void fprint_string(FILE *file, CFStringRef string) { + UInt8 buf[256]; + CFRange range = { .location = 0 }; + range.length = CFStringGetLength(string); + while (range.length > 0) { + CFIndex bytesUsed = 0; + CFIndex converted = CFStringGetBytes(string, range, kCFStringEncodingUTF8, 0, false, buf, sizeof(buf), &bytesUsed); + fwrite(buf, 1, bytesUsed, file); + range.length -= converted; + range.location += converted; + } +} + +static void cffprint(FILE *file, CFStringRef fmt, ...) CF_FORMAT_FUNCTION(2,0); + +static void cffprint_v(FILE *file, CFStringRef fmt, va_list args); +static void cffprint_c_v(FILE *file, const char *fmt, va_list args); + +static void cffprint_v(FILE *file, CFStringRef fmt, va_list args) { + CFStringRef line = CFStringCreateWithFormatAndArguments(NULL, NULL, fmt, args); + fprint_string(file, line); + CFRelease(line); +} + +static void cffprint_c_v(FILE *file, const char *fmt, va_list args) { + CFStringRef cffmt = CFStringCreateWithCString(kCFAllocatorDefault, fmt, kCFStringEncodingUTF8); + cffprint_v(file, cffmt, args); + CFRelease(cffmt); +} + +static void cffprint(FILE *file, CFStringRef fmt, ...) { + va_list args; + va_start(args, fmt); + cffprint_v(file, fmt, args); + va_end(args); +} + +void test_skip(const char *reason, int how_many, int unless) +{ + if (unless) + return; + + int done; + for (done = 0; done < how_many; ++done) + test_ok(1, NULL, "skip", reason, __FILE__, __LINE__, NULL); +} + +void test_bail_out(const char *reason, const char *file, unsigned line) +{ + fprintf(stdout, "[FAIL] BAIL OUT! (%s at line %u) %s\n", file, line, reason); + fflush(stdout); + exit(255); +} + +void test_plan_skip_all(const char *reason) +{ + if (test_num < test_cases) + { + test_skip(reason, test_cases - test_num, 0); + } +} + +static int test_plan_exit(void) +{ + int status = 0; + fflush(stderr); + + if (!test_num) + { + if (test_cases) + { + fprintf(stdout, "[BEGIN] plan_tests\nNo tests run!\n[WARN] plan_tests\n"); + status = 1; + } + else + { + fprintf(stdout, "[BEGIN] plan_tests\nLooks like your test died before it could output anything.\n[FAIL] plan_tests\n"); + status = 1; + } + } + else if (test_num < test_cases) + { + fprintf(stdout, "[BEGIN] plan_tests\nLooks like you planned %d tests but only ran %d.\n[WARN] plan_tests\n", + test_cases, test_num); + } + else if (test_num > test_cases) + { + fprintf(stdout, "[BEGIN] plan_tests\nLooks like you planned %d tests but ran %d.\n[WARN] plan_tests\n", + test_cases, test_num); + } + if (test_fails) + { + fprintf(stdout, "Failed %d tests of %d.\n", test_fails, test_num); + status = test_fails; + } + fflush(stdout); + + /* reset the test plan */ + test_num = 0; + test_fails = 0; + test_cases = 0; + + return status; +} + +void test_plan_tests(int count, const char *file, unsigned line) +{ +#if 0 + if (atexit(test_plan_exit) < 0) + { + fprintf(stdout, "failed to setup atexit handler: %s\n", + strerror(errno)); + fflush(stdout); + exit(255); + } +#endif + + if (test_cases) + { + fprintf(stdout, + "[FAIL] You tried to plan twice!\n"); + + fflush(stdout); + exit(255); + } + else + { + if (!count) + { + fprintf(stdout, "[BEGIN] plan_tests\nYou said to run 0 tests! " + "You've got to run something.\n[WARN] plan_tests\n"); + fflush(stdout); + } + + test_plan_file=file; + test_plan_line=line; + + test_cases = count; + } +} + +int +test_diag(const char *directive, const char *reason, + const char *file, unsigned line, const char *fmt, ...) +{ + int is_todo = directive && !strcmp(directive, "TODO"); + va_list args; + + va_start(args, fmt); + + if (is_todo) + { + fputs("# ", stdout); + if (fmt) + vprintf(fmt, args); + fputs("\n", stdout); + fflush(stdout); + } + else + { + fputs("# ", stdout); + if (fmt) + vfprintf(stdout, fmt, args); + fputs("\n", stdout); + fflush(stdout); + } + + va_end(args); + + return 1; +} + +int +test_ok(int passed, __attribute((cf_consumed)) CFStringRef description, const char *directive, + const char *reason, const char *file, unsigned line, + const char *fmt, ...) +{ + int is_todo = !passed && directive && !strcmp(directive, "TODO"); + int is_setup = directive && !is_todo && !strcmp(directive, "SETUP"); + + if (is_setup) + { + if (!passed) + { + fflush(stderr); + fprintf(stdout, "[BEGIN] SETUP\n"); + if (fmt) { + va_list args; + va_start(args, fmt); + cffprint_c_v(stdout, fmt, args); + va_end(args); + } + cffprint(stdout, CFSTR("[WARN] SETUP%s%@%s%s\n"), + description ? " - " : "", + description ? description : CFSTR(""), + reason ? " - " : "", + reason ? reason : ""); + fflush(stdout); + } + } + else + { + if (!test_cases) + { + atexit((void(*)(void))test_plan_exit); + fprintf(stdout, "[FAIL] You tried to run a test without a plan! " + "Gotta have a plan. at %s line %u\n", file, line); + fflush(stdout); + exit(255); + } + + ++test_num; + if (!passed && !is_todo) + ++test_fails; + + /* We only print this when a test fail, unless verbose is enabled */ + if ((!passed && !is_todo) || test_verbose > 0) { + fflush(stderr); + if (test_strict_bats) { + cffprint(stdout, CFSTR("[BEGIN] %d%s%@\n"), + test_num, + description ? " - " : "", + description ? description : CFSTR("")); + } + if (is_todo && passed) { + fprintf(stdout, "%s:%d: warning: Unexpectedly passed (TODO) test\n", file, line); + } else if (is_todo && !passed) { + /* Enable this to output TODO as warning */ + fprintf(stdout, "%s:%d: ok: Failed (TODO) test\n", file, line); + } else if (!passed) { + fprintf(stdout, "%s:%d: error: Failed test\n", file, line); + } + if (fmt) { + va_list args; + va_start(args, fmt); + cffprint_c_v(stdout, fmt, args); + va_end(args); + } + cffprint(stdout, CFSTR("[%s] %d%s%@%s%s%s%s\n"), passed ? (is_todo ? "WARN" : "PASS") : (is_todo ? "PASS" : "FAIL"), + test_num, + description ? " - " : "", + description ? description : CFSTR(""), + directive ? " # " : "", + directive ? directive : "", + reason ? " " : "", + reason ? reason : ""); + fflush(stdout); + } + } + + if (description) + CFRelease(description); + + return passed; +} + + +const char * +sec_errstr(int err) +{ +#if 1 + static int bufnum = 0; + static char buf[2][20]; + bufnum = bufnum ? 0 : 1; + sprintf(buf[bufnum], "0x%X", err); + return buf[bufnum]; +#else /* !1 */ + if (err >= errSecErrnoBase && err <= errSecErrnoLimit) + return strerror(err - 100000); + +#ifdef MAC_OS_X_VERSION_10_4 + /* AvailabilityMacros.h would only define this if we are on a + Tiger or later machine. */ + extern const char *cssmErrorString(long); + return cssmErrorString(err); +#else /* !defined(MAC_OS_X_VERSION_10_4) */ + extern const char *_ZN8Security15cssmErrorStringEl(long); + return _ZN8Security15cssmErrorStringEl(err); +#endif /* MAC_OS_X_VERSION_10_4 */ +#endif /* !1 */ +} + +/* run one test, described by test, return info in test struct */ +int run_one_test(struct one_test_s *test, int argc, char * const *argv) +{ + struct timeval start, stop; + + if(test->entry==NULL) { + fprintf(stdout, "%s:%d: error, no entry\n", __FILE__, __LINE__); + return -1; + } + + 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); + test->failed_tests=test_fails; + + return test_plan_exit(); + }; diff --git a/Security/regressions/test/testmore.h b/Security/regressions/test/testmore.h new file mode 100644 index 00000000..2a239423 --- /dev/null +++ b/Security/regressions/test/testmore.h @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2005-2007,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@ + * + * testmore.h + */ + +#ifndef _TESTMORE_H_ +#define _TESTMORE_H_ 1 + +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Macros to be used in testlist.h style headers. */ +#define ONE_TEST(x) int x(int argc, char *const *argv); +#define DISABLED_ONE_TEST(x) ONE_TEST(x) +#define OFF_ONE_TEST(x) ONE_TEST(x) + +typedef int (*one_test_entry)(int argc, char *const *argv); + +#define ONE_TEST_ENTRY(x) int x(int argc, char *const *argv) + +struct one_test_s { + char *name; /* test name */ + one_test_entry entry; /* entry point */ + int off; /* off by default */ + int sub_tests; /* number of subtests */ + int failed_tests; /* number of failed tests*/ + unsigned long duration; /* test duration in msecs */ + /* add more later: timing, etc... */ +}; + +extern struct one_test_s testlist[]; + +int run_one_test(struct one_test_s *test, int argc, char * const *argv); + +/* this test harnes rely on shadowing for TODO, SKIP and SETUP blocks */ +#pragma GCC diagnostic ignored "-Wshadow" + +#define test_create_description(TESTNAME, ...) \ + CFStringCreateWithFormat(NULL, NULL, CFSTR(TESTNAME), ## __VA_ARGS__) + +#define ok(THIS, ...) \ +({ \ + bool is_ok = !!(THIS); \ + test_ok(is_ok, test_create_description(__VA_ARGS__), test_directive, \ + test_reason, __FILE__, __LINE__, NULL); \ +}) +#define is(THIS, THAT, ...) \ +({ \ + __typeof__(THIS) _this = (THIS); \ + __typeof__(THAT) _that = (THAT); \ + test_ok((_this == _that), test_create_description(__VA_ARGS__), \ + test_directive, test_reason, __FILE__, __LINE__, \ + "# got: '%d'\n" \ + "# expected: '%d'\n", \ + _this, _that); \ +}) +#define isnt(THIS, THAT, ...) \ + cmp_ok((THIS), !=, (THAT), __VA_ARGS__) +#define diag(MSG, ARGS...) \ + test_diag(test_directive, test_reason, __FILE__, __LINE__, MSG, ## ARGS) +#define cmp_ok(THIS, OP, THAT, ...) \ +({ \ + __typeof__(THIS) _this = (THIS); \ + __typeof__(THAT) _that = (THAT); \ + test_ok((_this OP _that), test_create_description(__VA_ARGS__), \ + test_directive, test_reason, __FILE__, __LINE__, \ + "# '%d'\n" \ + "# " #OP "\n" \ + "# '%d'\n", \ + _this, _that); \ +}) +#define eq_string(THIS, THAT, ...) \ +({ \ + const char *_this = (THIS); \ + const char *_that = (THAT); \ + test_ok(!strcmp(_this, _that), test_create_description(__VA_ARGS__), \ + test_directive, test_reason, __FILE__, __LINE__, \ + "# '%s'\n" \ + "# eq\n" \ + "# '%s'\n", \ + _this, _that); \ +}) +#define eq_stringn(THIS, THISLEN, THAT, THATLEN, ...) \ +({ \ + __typeof__(THISLEN) _thislen = (THISLEN); \ + __typeof__(THATLEN) _thatlen = (THATLEN); \ + const char *_this = (THIS); \ + const char *_that = (THAT); \ + test_ok(_thislen == _thatlen && !strncmp(_this, _that, _thislen), \ + test_create_description(__VA_ARGS__), test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# '%.*s'\n" \ + "# eq\n" \ + "# '%.*s'\n", \ + (int)_thislen, _this, (int)_thatlen, _that); \ +}) +#define eq_cf(THIS, THAT, ...) \ +({ \ + CFTypeRef _this = (THIS); \ + CFTypeRef _that = (THAT); \ + test_ok(CFEqualSafe(_this, _that), test_create_description(__VA_ARGS__), test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# '%@'\n" \ + "# eq\n" \ + "# '%@'\n", \ + _this, _that); \ +}) + +#define like(THIS, REGEXP, ...) like_not_yet_implemented() +#define unlike(THIS, REGEXP, ...) unlike_not_yet_implemented() +#define is_deeply(STRUCT1, STRUCT2, ...) is_deeply_not_yet_implemented() +#define TODO switch(0) default +#define SKIP switch(0) default +#define SETUP switch(0) default +#define todo(REASON) const char *test_directive __attribute__((unused)) = "TODO", \ + *test_reason __attribute__((unused)) = (REASON) +#define skip(WHY, HOW_MANY, UNLESS) if (!(UNLESS)) \ + { test_skip((WHY), (HOW_MANY), 0); break; } +#define setup(REASON) const char *test_directive = "SETUP", \ + *test_reason = (REASON) +#define pass(...) ok(1, __VA_ARGS__) +#define fail(...) ok(0, __VA_ARGS__) +#define BAIL_OUT(WHY) test_bail_out(WHY, __FILE__, __LINE__) +#define plan_skip_all(REASON) test_plan_skip_all(REASON) +#define plan_tests(COUNT) test_plan_tests(COUNT, __FILE__, __LINE__) + +#define ok_status(THIS, ...) \ +({ \ + OSStatus _this = (THIS); \ + test_ok(!_this, test_create_description(__VA_ARGS__), \ + test_directive, test_reason, __FILE__, __LINE__, \ + "# status: %s(%" PRId32 ")\n", \ + sec_errstr(_this), _this); \ +}) +#define is_status(THIS, THAT, ...) \ +({ \ + OSStatus _this = (THIS); \ + OSStatus _that = (THAT); \ + test_ok(_this == _that, test_create_description(__VA_ARGS__), \ + test_directive, test_reason, __FILE__, __LINE__, \ + "# got: %s(%" PRId32 ")\n" \ + "# expected: %s(%" PRId32 ")\n", \ + sec_errstr(_this), _this, sec_errstr(_that), _that); \ +}) +#define ok_unix(THIS, ...) \ +({ \ + int _this = (THIS) < 0 ? errno : 0; \ + test_ok(!_this, test_create_description(__VA_ARGS__), \ + test_directive, test_reason, __FILE__, __LINE__, \ + "# got: %s(%d)\n", \ + strerror(_this), _this); \ +}) +#define is_unix(THIS, THAT, ...) \ +({ \ + int _result = (THIS); \ + int _this = _result < 0 ? errno : 0; \ + int _that = (THAT); \ + _that && _result < 0 \ + ? test_ok(_this == _that, test_create_description(__VA_ARGS__), \ + test_directive, test_reason, __FILE__, __LINE__, \ + "# got: %s(%d)\n" \ + "# expected: %s(%d)\n", \ + strerror(_this), _this, strerror(_that), _that) \ + : test_ok(_this == _that, test_create_description(__VA_ARGS__), \ + test_directive, test_reason, __FILE__, __LINE__, \ + "# got: %d\n" \ + "# expected errno: %s(%d)\n", \ + _result, strerror(_that), _that); \ +}) + + +extern const char *test_directive; +extern const char *test_reason; + +void test_bail_out(const char *reason, const char *file, unsigned line); +int test_diag(const char *directive, const char *reason, + const char *file, unsigned line, const char *fmt, ...); +int test_ok(int passed, __attribute((cf_consumed)) CFStringRef description, const char *directive, + const char *reason, const char *file, unsigned line, const char *fmt, ...); +void test_plan_skip_all(const char *reason); +void test_plan_tests(int count, const char *file, unsigned line); +void test_skip(const char *reason, int how_many, int unless); + +const char *sec_errstr(int err); + +__END_DECLS + +#endif /* !_TESTMORE_H_ */ diff --git a/Security/regressions/test/testpolicy.h b/Security/regressions/test/testpolicy.h new file mode 100644 index 00000000..c0c4d9ea --- /dev/null +++ b/Security/regressions/test/testpolicy.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 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@ + */ + + +#ifndef regressions_testpolicy_h +#define regressions_testpolicy_h + +#include +#include + + +void runCertificateTestForDirectory(SecPolicyRef policy, CFStringRef resourceSubDirectory, CFDateRef date); + + +#endif diff --git a/regressions/test/testpolicy.m b/Security/regressions/test/testpolicy.m similarity index 82% rename from regressions/test/testpolicy.m rename to Security/regressions/test/testpolicy.m index 5b5a7ff0..a7e6234a 100644 --- a/regressions/test/testpolicy.m +++ b/Security/regressions/test/testpolicy.m @@ -1,10 +1,26 @@ -// -// testpolicy.cpp -// regressions -// -// Created by Mitch Adler on 7/21/11. -// Copyright (c) 2011 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include "testpolicy.h" @@ -14,6 +30,7 @@ #include #include +#include #include #include #include @@ -26,7 +43,7 @@ #include "testmore.h" /* - * Copyright (c) 2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. */ #include @@ -43,14 +60,9 @@ #include "testmore.h" /* Those tests were originally written around that date. */ -CFGregorianDate frozenTime = { - .year = 2011, - .month = 9, - .day = 1, - .hour = 0, - .minute = 0, - .second = 0, -}; +CFGiblisGetSingleton(CFDateRef, GetFrozenTime, frozenTime, ^{ + *frozenTime = CFDateCreateForGregorianZuluDay(NULL, 2011, 9, 1); +}); static void runOneLeafTest(SecPolicyRef policy, NSArray* anchors, @@ -58,7 +70,7 @@ static void runOneLeafTest(SecPolicyRef policy, NSString* path, bool expectedResult, NSObject* expectations, - CFGregorianDate *date) + CFDateRef date) { NSString* fileName = [path lastPathComponent]; const char *reason = NULL; @@ -118,9 +130,7 @@ static void runOneLeafTest(SecPolicyRef policy, if ([anchors count]) SecTrustSetAnchorCertificates(trustRef, (CFArrayRef)anchors); - CFDateRef dateRef = CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(date?*date:frozenTime, NULL)); - SecTrustSetVerifyDate(trustRef, dateRef); - CFRelease(dateRef); + SecTrustSetVerifyDate(trustRef, date ? date : GetFrozenTime()); SecTrustResultType evalRes = 0; //NSLog(@"Evaluating: %@",certRef); @@ -158,7 +168,7 @@ static void runCertificateTestFor(SecPolicyRef policy, NSArray* intermediates, NSMutableArray* leafPaths, NSDictionary* expect, - CFGregorianDate *date) + CFDateRef date) { /* Sort the tests by name. */ [leafPaths sortUsingSelector:@selector(compare:)]; @@ -169,7 +179,7 @@ static void runCertificateTestFor(SecPolicyRef policy, } } -void runCertificateTestForDirectory(SecPolicyRef policy, CFStringRef resourceSubDirectory, CFGregorianDate *date) +void runCertificateTestForDirectory(SecPolicyRef policy, CFStringRef resourceSubDirectory, CFDateRef date) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSMutableArray* allRoots = [NSMutableArray array]; diff --git a/sec/CloudKeychainProxy/CloudKeychainProxy.1 b/Security/sec/CloudKeychainProxy/CloudKeychainProxy.1 similarity index 100% rename from sec/CloudKeychainProxy/CloudKeychainProxy.1 rename to Security/sec/CloudKeychainProxy/CloudKeychainProxy.1 diff --git a/sec/SOSCircle/CKBridge/CKClient.c b/Security/sec/SOSCircle/CKBridge/CKClient.c similarity index 99% rename from sec/SOSCircle/CKBridge/CKClient.c rename to Security/sec/SOSCircle/CKBridge/CKClient.c index 0c937ddf..f452dfb2 100644 --- a/sec/SOSCircle/CKBridge/CKClient.c +++ b/Security/sec/SOSCircle/CKBridge/CKClient.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/sec/SOSCircle/CKBridge/CKClient.h b/Security/sec/SOSCircle/CKBridge/CKClient.h similarity index 97% rename from sec/SOSCircle/CKBridge/CKClient.h rename to Security/sec/SOSCircle/CKBridge/CKClient.h index 761f367f..84f3475e 100644 --- a/sec/SOSCircle/CKBridge/CKClient.h +++ b/Security/sec/SOSCircle/CKBridge/CKClient.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/sec/SOSCircle/CKBridge/SOSCloudKeychainClient.c b/Security/sec/SOSCircle/CKBridge/SOSCloudKeychainClient.c new file mode 100644 index 00000000..be94e89d --- /dev/null +++ b/Security/sec/SOSCircle/CKBridge/SOSCloudKeychainClient.c @@ -0,0 +1,682 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + SOSCloudTransport.c - Implementation of the transport layer from CKBridge to SOSAccount/SOSCircle + These are the exported functions from CloudKeychainProxy +*/ + +/* + This XPC service is essentially just a proxy to iCloud KVS, which exists since + the main security code cannot link against Foundation. + + See sendTSARequestWithXPC in tsaSupport.c for how to call the service + + The client of an XPC service does not get connection events, nor does it + need to deal with transactions. +*/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "SOSCloudKeychainConstants.h" +#include "SOSCloudKeychainClient.h" + +static CFStringRef sErrorDomain = CFSTR("com.apple.security.sos.transport.error"); + +#define SOSCKCSCOPE "sync" + +// MARK: ---------- SOSCloudTransport ---------- + +/* SOSCloudTransport, a statically initialized transport singleton. */ +static SOSCloudTransportRef sTransport = NULL; + +static SOSCloudTransportRef SOSCloudTransportCreateXPCTransport(void); + +void SOSCloudKeychainSetTransport(SOSCloudTransportRef transport) { + sTransport = transport; +} + +/* Return the singleton cloud transport instance. */ +static SOSCloudTransportRef SOSCloudTransportDefaultTransport(void) +{ + static dispatch_once_t sTransportOnce; + dispatch_once(&sTransportOnce, ^{ + if (!sTransport) + SOSCloudKeychainSetTransport(SOSCloudTransportCreateXPCTransport()); + }); + return sTransport; +} + + +// MARK: ----- utilities ----- + +static CFErrorRef makeError(CFIndex which) +{ + CFDictionaryRef userInfo = NULL; + return CFErrorCreate(kCFAllocatorDefault, sErrorDomain, which, userInfo); +} + +// MARK: ----- DEBUG Utilities ----- + +//------------------------------------------------------------------------------------------------ +// DEBUG only +//------------------------------------------------------------------------------------------------ + +static void describeXPCObject(char *prefix, xpc_object_t object) +{ +//#ifndef NDEBUG + // This is useful for debugging. + if (object) + { + char *desc = xpc_copy_description(object); + secdebug(SOSCKCSCOPE, "%s%s\n", prefix, desc); + free(desc); + } + else + secdebug(SOSCKCSCOPE, "%s\n", prefix); +//#endif +} + +static void describeXPCType(char *prefix, xpc_type_t xtype) +{ + // Add others as necessary, e.g. XPC_TYPE_DOUBLE +#ifndef NDEBUG + // This is useful for debugging. + char msg[256]={0,}; + if (XPC_TYPE_CONNECTION == xtype) + strcpy(msg, "XPC_TYPE_CONNECTION"); + else if (XPC_TYPE_ERROR == xtype) + strcpy(msg, "XPC_TYPE_ERROR"); + else if (XPC_TYPE_DICTIONARY == xtype) + strcpy(msg, "XPC_TYPE_DICTIONARY"); + else + strcpy(msg, ""); + + secdebug(SOSCKCSCOPE, "%s type:%s\n", prefix, msg); +#endif +} + +// MARK: ---------- SOSXPCCloudTransport ---------- + +typedef struct SOSXPCCloudTransport *SOSXPCCloudTransportRef; +struct SOSXPCCloudTransport +{ + struct SOSCloudTransport transport; + xpc_connection_t serviceConnection; + dispatch_queue_t xpc_queue; +}; + +static bool xpc_event_filter(const xpc_connection_t peer, xpc_object_t event, CFErrorRef *error) +{ + // return true if the type is XPC_TYPE_DICTIONARY (and therefore something more to process) + secdebug(SOSCKCSCOPE, "handle_connection_event\n"); + xpc_type_t xtype = xpc_get_type(event); + describeXPCType("handle_xpc_event", xtype); + if (XPC_TYPE_CONNECTION == xtype) + { + secdebug(SOSCKCSCOPE, "handle_xpc_event: XPC_TYPE_CONNECTION (unexpected)"); + // The client of an XPC service does not get connection events + // For now, we log this and keep going + describeXPCObject("handle_xpc_event: XPC_TYPE_CONNECTION, obj : ", event); +#if 0 + if (error) + *error = makeError(kSOSOUnexpectedConnectionEvent); // FIX + assert(true); +#endif + } + else + if (XPC_TYPE_ERROR == xtype) + { +#ifndef NDEBUG + const char *estr = xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION); +#endif + secdebug(SOSCKCSCOPE, "default: xpc error: %s\n", estr); +#if 0 // just log for now + CFStringRef errStr = CFStringCreateWithCString(kCFAllocatorDefault, estr, kCFStringEncodingUTF8); + CFMutableDictionaryRef userInfo = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (errStr) + CFDictionaryAddValue(userInfo, kCFErrorLocalizedDescriptionKey, errStr); + if (error) + *error = CFErrorCreate(kCFAllocatorDefault, sErrorDomain, kSOSOXPCErrorEvent, userInfo); + CFReleaseSafe(errStr); + CFReleaseSafe(userInfo); +#endif + } + else + if (XPC_TYPE_DICTIONARY == xtype) + { + secdebug(SOSCKCSCOPE, "received dictionary event %p\n", event); + return true; + } + else + { + secdebug(SOSCKCSCOPE, "default: unexpected connection event %p\n", event); + describeXPCObject("handle_xpc_event: obj : ", event); + if (error) + *error = makeError(kSOSOUnexpectedXPCEvent); + } + return false; +} + +static void SOSXPCCloudTransportInit(SOSXPCCloudTransportRef transport) +{ + secdebug(SOSCKCSCOPE, "initXPCConnection\n"); + + transport->xpc_queue = dispatch_queue_create(xpcServiceName, DISPATCH_QUEUE_SERIAL); + + transport->serviceConnection = xpc_connection_create_mach_service(xpcServiceName, transport->xpc_queue, 0); + + secdebug(SOSCKCSCOPE, "serviceConnection: %p\n", transport->serviceConnection); + + xpc_connection_set_event_handler(transport->serviceConnection, ^(xpc_object_t event) + { + secdebug(SOSCKCSCOPE, "xpc_connection_set_event_handler\n"); + }); + + xpc_connection_resume(transport->serviceConnection); + xpc_retain(transport->serviceConnection); +} + +static void talkWithKVS(SOSXPCCloudTransportRef transport, xpc_object_t message, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + CFErrorRef connectionError = NULL; + require_action(transport->serviceConnection, xit, connectionError = makeError(kSOSConnectionNotOpen)); + require_action(message, xit, connectionError = makeError(kSOSObjectNotFoundError)); + dispatch_retain(processQueue); + + xpc_connection_send_message_with_reply(transport->serviceConnection, message, transport->xpc_queue, ^(xpc_object_t reply) + { + CFErrorRef serverError = NULL; + CFTypeRef object = NULL; + if (xpc_event_filter(transport->serviceConnection, reply, &serverError) && reply) + { + describeXPCObject("getValuesFromKVS: reply : ", reply); + if (serverError) + secerror("Error from xpc_event_filter: %@", serverError); + xpc_object_t xrv = xpc_dictionary_get_value(reply, kMessageKeyValue); + if (xrv) + { + describeXPCObject("talkWithKVS: xrv: ", xrv); + /* + * The given XPC object must be one that was previously returned by + * _CFXPCCreateXPCMessageWithCFObject(). + */ + object = _CFXPCCreateCFObjectFromXPCObject(xrv); // CF object is retained; release in callback + secnotice("talkwithkvs", "converted CF object: %@", object); + } + else + secerror("missing value reply"); + + xpc_object_t xerror = xpc_dictionary_get_value(reply, kMessageKeyError); + if (xerror) + serverError = SecCreateCFErrorWithXPCObject(xerror); // use SecCFCreateErrorWithFormat? + } + dispatch_async(processQueue, ^{ + if (replyBlock) + replyBlock(object, serverError); + CFReleaseSafe(object); + if (serverError) + { + secerror("callback error: %@", serverError); + CFReleaseSafe(serverError); + } + dispatch_release(processQueue); + }); + }); + return; + +xit: + secerror("talkWithKVS error: %@", connectionError); + dispatch_async(processQueue, ^{ + if (replyBlock) + replyBlock(NULL, connectionError); + CFReleaseSafe(connectionError); + dispatch_release(processQueue); + }); +} + +// MARK: ---------- SOSXPCCloudTransport Client Calls ---------- + +/* Concrete function backend implementations. */ +static void SOSCloudTransportSetItemsChangedBlock(SOSCloudTransportRef transport, + CloudItemsChangedBlock itemsChangedBlock) { + if (transport->itemsChangedBlock != itemsChangedBlock) + { + secnotice(SOSCKCSCOPE, "Changing itemsChangedBlock"); + if (transport->itemsChangedBlock) + Block_release(transport->itemsChangedBlock); + transport->itemsChangedBlock = Block_copy(itemsChangedBlock); + } +} + +/* Virtual function backend implementations. */ +static void SOSCloudTransportPut(SOSCloudTransportRef transport, CFDictionaryRef values, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; + secdebug(SOSCKCSCOPE, "%@", values); + CFErrorRef error = NULL; + xpc_object_t message = NULL; + xpc_object_t xobject = NULL; + require_action(values, xit, error = makeError(kSOSObjectNotFoundError)); + + message = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion); + xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationPUTDictionary); + + xobject = _CFXPCCreateXPCObjectFromCFObject(values); + require_action(xobject, xit, error = makeError(kSOSObjectCantBeConvertedToXPCObject)); + xpc_dictionary_set_value(message, kMessageKeyValue, xobject); + xpc_release(xobject); + + talkWithKVS(xpcTransport, message, processQueue, replyBlock); + xpc_release(message); + return; + +xit: + if (replyBlock) + replyBlock(NULL, error); + CFReleaseSafe(error); +} + +/* Get from KVS */ +static void SOSCloudTransportGet(SOSCloudTransportRef transport, CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; + secdebug(SOSCKCSCOPE, "%@", keysToGet); + CFErrorRef error = NULL; + xpc_object_t xkeysOfInterest = xpc_dictionary_create(NULL, NULL, 0); + xpc_object_t xkeysToGet = keysToGet ? _CFXPCCreateXPCObjectFromCFObject(keysToGet) : xpc_null_create(); + + require_action(xkeysToGet, xit, error = makeError(kSOSObjectNotFoundError)); + + if (keysToGet) // don't add if nulll; will call getall + xpc_dictionary_set_value(xkeysOfInterest, kMessageKeyKeysToGet, xkeysToGet); + + xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion); + xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationGETv2); + xpc_dictionary_set_value(message, kMessageKeyValue, xkeysOfInterest); + + talkWithKVS(xpcTransport, message, processQueue, replyBlock); + xpc_release(xkeysToGet); + xpc_release(xkeysOfInterest); + xpc_release(message); + return; + +xit: + if(xkeysOfInterest) + xpc_release(xkeysOfInterest); + if(xkeysToGet) + xpc_release(xkeysToGet); + if (replyBlock) + replyBlock(NULL, error); + CFReleaseSafe(error); +} + +// +// Handles NULL by seting xpc_null. +static void SecXPCDictionarySetCFObject(xpc_object_t xdict, const char *key, CFTypeRef object) +{ + xpc_object_t xpc_obj = object ? _CFXPCCreateXPCObjectFromCFObject(object) : xpc_null_create(); + xpc_dictionary_set_value(xdict, key, xpc_obj); + xpc_release(xpc_obj); +} + +static bool SOSCloudTransportUpdateKeys(SOSCloudTransportRef transport, + CFDictionaryRef keys, + CFErrorRef *error) +{ + __block bool success = true; + dispatch_queue_t processQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + + CloudKeychainReplyBlock replyBlock = ^(CFDictionaryRef returnedValues, CFErrorRef returnedError) + { + if (returnedError) { + success = false; + if (error) { + *error = returnedError; + CFRetain(*error); + } + } + CFReleaseSafe(returnedError); + }; + + SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; + + xpc_object_t xkeysOfInterest = xpc_dictionary_create(NULL, NULL, 0); + SecXPCDictionarySetCFObject(xkeysOfInterest, kMessageAllKeys, keys); + + xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion); + xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationRegisterKeys); + xpc_dictionary_set_value(message, kMessageKeyValue, xkeysOfInterest); + + talkWithKVS(xpcTransport, message, processQueue, replyBlock); + xpc_release(message); + xpc_release(xkeysOfInterest); + + return success; +} + +static void SOSCloudTransportGetAll(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + secdebug(SOSCKCSCOPE, "start"); + SOSCloudTransportGet(transport, NULL, processQueue, replyBlock); +} + +static void SOSCloudTransportSync(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; + secdebug(SOSCKCSCOPE, "start"); + xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion); + xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationSynchronize); + talkWithKVS(xpcTransport, message, processQueue, replyBlock); + xpc_release(message); +} + +static void SOSCloudTransportSyncAndWait(SOSCloudTransportRef transport, CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; + secdebug(SOSCKCSCOPE, "%@", keysToGet); + secnotice(SOSCKCSCOPE, "%s XPC request to CKD: %s", kWAIT2MINID, kOperationSynchronizeAndWait); + xpc_object_t xkeysOfInterest = xpc_dictionary_create(NULL, NULL, 0); + + xpc_object_t xkeysToRegister = keysToGet ? _CFXPCCreateXPCObjectFromCFObject(keysToGet) : xpc_null_create(); + xpc_dictionary_set_value(xkeysOfInterest, kMessageKeyKeysToGet, xkeysToRegister); + xpc_release(xkeysToRegister); + xkeysToRegister = NULL; + + xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion); + xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationSynchronizeAndWait); + xpc_dictionary_set_value(message, kMessageKeyValue, xkeysOfInterest); + xpc_release(xkeysOfInterest); + xkeysOfInterest = NULL; + + talkWithKVS(xpcTransport, message, processQueue, replyBlock); + xpc_release(message); +} + +static void SOSCloudTransportClearAll(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; + secdebug(SOSCKCSCOPE, "start"); + xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion); + xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationClearStore); + talkWithKVS(xpcTransport, message, processQueue, replyBlock); + xpc_release(message); +} + +static void SOSCloudTransportRemoveObjectForKey(SOSCloudTransportRef transport, CFStringRef keyToRemove, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; + secdebug(SOSCKCSCOPE, "start"); + CFErrorRef error = NULL; + xpc_object_t message = NULL; + xpc_object_t xkeytoremove = NULL; + + require_action(keyToRemove, xit, error = makeError(kSOSObjectNotFoundError)); + + message = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion); + xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationRemoveObjectForKey); + + xkeytoremove = _CFXPCCreateXPCObjectFromCFObject(keyToRemove); + require_action(xkeytoremove, xit, error = makeError(kSOSObjectCantBeConvertedToXPCObject)); + xpc_dictionary_set_value(message, kMessageKeyKey, xkeytoremove); + xpc_release(xkeytoremove); + + talkWithKVS(xpcTransport, message, processQueue, replyBlock); + xpc_release(message); + return; + +xit: + if(xkeytoremove) + xpc_release(xkeytoremove); + if(message) + xpc_release(message); + if (replyBlock) + replyBlock(NULL, error); + CFReleaseSafe(error); +} +static void SOSCloudTransportLocalNotification(SOSCloudTransportRef transport, CFStringRef messageToUser, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; + secdebug(SOSCKCSCOPE, "start"); + xpc_object_t xLocalNotificationDict = xpc_dictionary_create(NULL, NULL, 0); + char *headerKey = CFStringToCString(kCFUserNotificationAlertHeaderKey); + char *message = CFStringToCString(messageToUser); + xpc_dictionary_set_string(xLocalNotificationDict, headerKey, message); + + xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion); + xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationUILocalNotification); + xpc_dictionary_set_value (xpcmessage, kMessageKeyValue, xLocalNotificationDict); + xpc_release(xLocalNotificationDict); + + talkWithKVS(xpcTransport, xpcmessage, processQueue, replyBlock); + + free(headerKey); + free(message); + xpc_release(xpcmessage); +} + +static void SOSCloudTransportRequestSyncWithAllPeers(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + secdebug(SOSCKCSCOPE, "start"); + SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; + + xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion); + xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationRequestSyncWithAllPeers); + + talkWithKVS(xpcTransport, xpcmessage, processQueue, replyBlock); + + xpc_release(xpcmessage); +} + +static void SOSCloudTransportRequestEnsurePeerRegistration(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + secdebug(SOSCKCSCOPE, "start"); + SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; + + xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion); + xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationRequestEnsurePeerRegistration); + + talkWithKVS(xpcTransport, xpcmessage, processQueue, replyBlock); + + xpc_release(xpcmessage); +} + +static void SOSCloudTransportFlush(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + secdebug(SOSCKCSCOPE, "start"); + SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; + + xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion); + xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationFlush); + + talkWithKVS(xpcTransport, xpcmessage, processQueue, replyBlock); + + xpc_release(xpcmessage); +} + +static SOSCloudTransportRef SOSCloudTransportCreateXPCTransport(void) +{ + SOSXPCCloudTransportRef st; + st = calloc(1, sizeof(*st)); + st->transport.put = SOSCloudTransportPut; + st->transport.updateKeys = SOSCloudTransportUpdateKeys; + st->transport.get = SOSCloudTransportGet; + st->transport.getAll = SOSCloudTransportGetAll; + st->transport.synchronize = SOSCloudTransportSync; + st->transport.synchronizeAndWait = SOSCloudTransportSyncAndWait; + st->transport.clearAll = SOSCloudTransportClearAll; + st->transport.removeObjectForKey = SOSCloudTransportRemoveObjectForKey; + st->transport.localNotification = SOSCloudTransportLocalNotification; + st->transport.requestSyncWithAllPeers = SOSCloudTransportRequestSyncWithAllPeers; + st->transport.requestEnsurePeerRegistration = SOSCloudTransportRequestEnsurePeerRegistration; + st->transport.flush = SOSCloudTransportFlush; + st->transport.itemsChangedBlock = Block_copy(^CFArrayRef(CFDictionaryRef changes) { + secerror("Calling default itemsChangedBlock - fatal: %@", changes); + assert(false); + return NULL; + }); + SOSXPCCloudTransportInit(st); + return &st->transport; +} + +// MARK: ---------- SOSCloudKeychain concrete client APIs ---------- +void SOSCloudKeychainSetItemsChangedBlock(CloudItemsChangedBlock itemsChangedBlock) +{ + secdebug(SOSCKCSCOPE, "start"); + SOSCloudTransportSetItemsChangedBlock(SOSCloudTransportDefaultTransport(), + itemsChangedBlock); +} + +// MARK: ---------- SOSCloudKeychain virtual client APIs ---------- + +void SOSCloudKeychainPutObjectsInCloud(CFDictionaryRef objects, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); + if (cTransportRef) + cTransportRef->put(cTransportRef, objects, processQueue, replyBlock); +} + +bool SOSCloudKeychainUpdateKeys(CFDictionaryRef keys, + CFErrorRef *error) +{ + SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); + if (cTransportRef) + return cTransportRef->updateKeys(cTransportRef, keys, error); + + return false; +} + +CF_RETURNS_RETAINED CFArrayRef SOSCloudKeychainHandleUpdateKeyParameter(CFDictionaryRef updates) +{ + CFArrayRef result = NULL; + SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); + if (cTransportRef->itemsChangedBlock) + result = ((CloudItemsChangedBlock)cTransportRef->itemsChangedBlock)(updates); + return result; + +} +CF_RETURNS_RETAINED CFArrayRef SOSCloudKeychainHandleUpdateCircle(CFDictionaryRef updates) +{ + CFArrayRef result = NULL; + SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); + if (cTransportRef->itemsChangedBlock) + result = ((CloudItemsChangedBlock)cTransportRef->itemsChangedBlock)(updates); + return result; +} + +CF_RETURNS_RETAINED CFArrayRef SOSCloudKeychainHandleUpdateMessage(CFDictionaryRef updates) +{ + CFArrayRef result = NULL; + SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); + if (cTransportRef->itemsChangedBlock) + result = ((CloudItemsChangedBlock)cTransportRef->itemsChangedBlock)(updates); + return result; +} + + +void SOSCloudKeychainGetObjectsFromCloud(CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); + if (cTransportRef) + cTransportRef->get(cTransportRef, keysToGet, processQueue, replyBlock); +} + +void SOSCloudKeychainGetAllObjectsFromCloud(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); + if (cTransportRef) + cTransportRef->getAll(cTransportRef, processQueue, replyBlock); +} + +void SOSCloudKeychainSynchronizeAndWait(CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); + if (cTransportRef) + cTransportRef->synchronizeAndWait(cTransportRef, keysToGet, processQueue, replyBlock); +} + +//DEBUG ONLY +void SOSCloudKeychainSynchronize(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); + if (cTransportRef) + cTransportRef->synchronize(cTransportRef, processQueue, replyBlock); +} + +//DEBUG ONLY +void SOSCloudKeychainClearAll(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); + if (cTransportRef) + cTransportRef->clearAll(cTransportRef, processQueue, replyBlock); +} + +void SOSCloudKeychainRemoveObjectForKey(CFStringRef keyToRemove, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); + if (cTransportRef) + cTransportRef->removeObjectForKey(cTransportRef, keyToRemove, processQueue, replyBlock); +} + +void SOSCloudKeychainRequestSyncWithAllPeers(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); + if (cTransportRef) + cTransportRef->requestSyncWithAllPeers(cTransportRef, processQueue, replyBlock); +} + +void SOSCloudKeychainRequestEnsurePeerRegistration(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); + if (cTransportRef) + cTransportRef->requestEnsurePeerRegistration(cTransportRef, processQueue, replyBlock); +} + +void SOSCloudKeychainFlush(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) +{ + SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); + if (cTransportRef) + cTransportRef->flush(cTransportRef, processQueue, replyBlock); +} diff --git a/Security/sec/SOSCircle/CKBridge/SOSCloudKeychainClient.h b/Security/sec/SOSCircle/CKBridge/SOSCloudKeychainClient.h new file mode 100644 index 00000000..a4cf5332 --- /dev/null +++ b/Security/sec/SOSCircle/CKBridge/SOSCloudKeychainClient.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* + * SOSCloudKeychainClient.h - Implementation of the transport layer from CKBridge to SOSAccount/SOSCircle + */ + +/*! + @header SOSCloudKeychainClient + The functions provided in SOSCloudTransport.h provide an interface + from CKBridge to SOSAccount/SOSCircle + */ + +#ifndef _SOSCLOUDKEYCHAINCLIENT_H_ +#define _SOSCLOUDKEYCHAINCLIENT_H_ + +#include +#include +#include +#include + +__BEGIN_DECLS + + +// MARK: ---------- SOSCloudTransport ---------- + +enum +{ + kSOSObjectMallocFailed = 1, + kAddDuplicateEntry, + kSOSObjectNotFoundError = 1, + kSOSObjectCantBeConvertedToXPCObject, + kSOSOUnexpectedConnectionEvent, + kSOSOXPCErrorEvent, + kSOSOUnexpectedXPCEvent, + kSOSConnectionNotOpen +}; + +typedef CFArrayRef (^CloudItemsChangedBlock)(CFDictionaryRef values); +typedef void (^CloudKeychainReplyBlock)(CFDictionaryRef returnedValues, CFErrorRef error); + +/* SOSCloudTransport protocol. */ +typedef struct SOSCloudTransport *SOSCloudTransportRef; +struct SOSCloudTransport +{ + void (*put)(SOSCloudTransportRef transport, CFDictionaryRef valuesToPut, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); + bool (*updateKeys)(SOSCloudTransportRef transport, CFDictionaryRef keys, CFErrorRef *error); + + + // Debug calls + void (*get)(SOSCloudTransportRef transport, CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); + void (*getAll)(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); + void (*synchronize)(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); + void (*synchronizeAndWait)(SOSCloudTransportRef transport, CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); + + void (*clearAll)(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); + void (*removeObjectForKey)(SOSCloudTransportRef transport, CFStringRef keyToRemove, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); + void (*localNotification)(SOSCloudTransportRef transport, CFStringRef messageToUser, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); + void (*requestSyncWithAllPeers)(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); + void (*requestEnsurePeerRegistration)(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); + void (*flush)(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); + + const void *itemsChangedBlock; +}; + +/* Call this function before calling any other function in this header to provide + an alternate transport, the default transport talks to CloudKeychainProxy via xpc. */ +void SOSCloudKeychainSetTransport(SOSCloudTransportRef transport); + + +bool SOSCloudKeychainUpdateKeys(CFDictionaryRef keys, + CFErrorRef *error); +void SOSCloudKeychainUnRegisterKeys(CFArrayRef keysToUnregister, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); + +void SOSCloudKeychainPutObjectsInCloud(CFDictionaryRef objects, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); + +void SOSCloudKeychainSetItemsChangedBlock(CloudItemsChangedBlock itemsChangedBlock); + +CF_RETURNS_RETAINED CFArrayRef SOSCloudKeychainHandleUpdateKeyParameter(CFDictionaryRef updates); +CF_RETURNS_RETAINED CFArrayRef SOSCloudKeychainHandleUpdateCircle(CFDictionaryRef updates); +CF_RETURNS_RETAINED CFArrayRef SOSCloudKeychainHandleUpdateMessage(CFDictionaryRef updates); +void SOSCloudKeychainSynchronizeAndWait(CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); + +// Debug only? + +void SOSCloudKeychainGetObjectsFromCloud(CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); +void SOSCloudKeychainSynchronize(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); +void SOSCloudKeychainClearAll(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); +void SOSCloudKeychainRemoveObjectForKey(CFStringRef keyToRemove, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); +void SOSCloudKeychainGetAllObjectsFromCloud(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); + +void SOSCloudKeychainRequestSyncWithAllPeers(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); +void SOSCloudKeychainRequestEnsurePeerRegistration(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); + +void SOSCloudKeychainFlush(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); + + +__END_DECLS + +#endif /* !_SOSCLOUDKEYCHAINCLIENT_H_ */ + diff --git a/sec/SOSCircle/CKBridge/SOSCloudKeychainConstants.c b/Security/sec/SOSCircle/CKBridge/SOSCloudKeychainConstants.c similarity index 85% rename from sec/SOSCircle/CKBridge/SOSCloudKeychainConstants.c rename to Security/sec/SOSCircle/CKBridge/SOSCloudKeychainConstants.c index 291fb501..fcd66a7c 100644 --- a/sec/SOSCircle/CKBridge/SOSCloudKeychainConstants.c +++ b/Security/sec/SOSCircle/CKBridge/SOSCloudKeychainConstants.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -51,30 +51,38 @@ const char *kMessageKeyGetNewKeysOnly = "GetNewKeysOnly"; const char *kMessageKeyKeysToGet = "KeysToGet"; const char *kMessageKeyKeysRequireFirstUnlock = "KeysRequireFirstUnlock"; const char *kMessageKeyKeysRequiresUnlocked = "KeysRequiresUnlocked"; -const char *kMessageKeyClientIdentifier = "ClientIdentifier"; const char *kMessageKeyNotificationFlags = "NotificationFlags"; +/* parameters within the dictionary */ +const char *kMessageAlwaysKeys = "AlwaysKeys"; +const char *kMessageFirstUnlocked = "FirstUnlockKeys"; +const char *kMessageUnlocked = "UnlockedKeys"; + +const char *kMessageContext = "Context"; +const char *kMessageAllKeys = "AllKeys"; +const char *kMessageKeyParameter = "KeyParameter"; +const char *kMessageCircle = "Circle"; +const char *kMessageMessage = "Message"; + const char *kMessageOperationItemChanged = "ItemChanged"; const char *kOperationClearStore = "ClearStore"; const char *kOperationSynchronize = "Synchronize"; const char *kOperationSynchronizeAndWait = "SynchronizeAndWait"; +const char *kOperationFlush = "Flush"; + const char *kOperationPUTDictionary = "PUTDictionary"; const char *kOperationGETv2 = "GETv2"; const char *kOperationRemoveObjectForKey = "RemoveObjectForKey"; -const char *kOperationRegisterKeysAndGet = "RegisterKeysAndGet"; -const char *kOperationUnregisterKeys = "UnregisterKeys"; +const char *kOperationRegisterKeys = "RegisterKeys"; const char *kOperationUILocalNotification = "UILocalNotification"; -const char *kOperationSetParams = "SetParams"; const char *kOperationRequestSyncWithAllPeers = "requestSyncWithAllPeers"; +const char *kOperationRequestEnsurePeerRegistration = "requestEnsurePeerRegistration"; -const CFStringRef kParamCallbackMethod = CFSTR("CallbackMethod"); -const CFStringRef kParamCallbackMethodSecurityd = CFSTR("CallbackMethodSecurityd"); -const CFStringRef kParamCallbackMethodXPC = CFSTR("CallbackMethodXPC"); /* The values for the KVS notification and KVS Store ID must be identical to the values diff --git a/sec/SOSCircle/CKBridge/SOSCloudKeychainConstants.h b/Security/sec/SOSCircle/CKBridge/SOSCloudKeychainConstants.h similarity index 80% rename from sec/SOSCircle/CKBridge/SOSCloudKeychainConstants.h rename to Security/sec/SOSCircle/CKBridge/SOSCloudKeychainConstants.h index ad6ad609..9e71c6df 100644 --- a/sec/SOSCircle/CKBridge/SOSCloudKeychainConstants.h +++ b/Security/sec/SOSCircle/CKBridge/SOSCloudKeychainConstants.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -45,29 +45,38 @@ extern const char *kMessageOperationItemChanged; extern const char *kOperationRemoveObjectForKey; extern const char *kMessageKeyNotificationFlags; +extern const char *kMessageContext; +extern const char *kMessageKeyParameter; +extern const char *kMessageCircle; +extern const char *kMessageMessage; + +extern const char *kMessageAlwaysKeys; +extern const char *kMessageFirstUnlocked; +extern const char *kMessageUnlocked; +extern const char *kMessageAllKeys; + + extern const char *kOperationClearStore; extern const char *kOperationSynchronize; extern const char *kOperationSynchronizeAndWait; extern const char *kOperationPUTDictionary; extern const char *kOperationGETv2; -extern const char *kOperationRegisterKeysAndGet; -extern const char *kOperationUnregisterKeys; -extern const char *kMessageKeyClientIdentifier; +extern const char *kOperationRegisterKeys; extern const uint64_t kCKDXPCVersion; - extern const char *kOperationUILocalNotification; -extern const char *kOperationSetParams; -extern const char *kOperationRequestSyncWithAllPeers; -extern const CFStringRef kParamCallbackMethod; -extern const CFStringRef kParamCallbackMethodSecurityd; -extern const CFStringRef kParamCallbackMethodXPC; +extern const char *kOperationFlush; + +extern const char *kOperationRequestSyncWithAllPeers; +extern const char *kOperationRequestEnsurePeerRegistration; extern const char * const kCloudKeychainStorechangeChangeNotification; extern const char *kNotifyTokenForceUpdate; +#define kWAIT2MINID "EFRESH" + __END_DECLS #endif /* _CKDXPC_CONSTANTS_H_ */ diff --git a/sec/SOSCircle/CKBridge/SOSCloudTransport.c b/Security/sec/SOSCircle/CKBridge/SOSCloudTransport.c similarity index 99% rename from sec/SOSCircle/CKBridge/SOSCloudTransport.c rename to Security/sec/SOSCircle/CKBridge/SOSCloudTransport.c index 973179ad..5faf9fe3 100644 --- a/sec/SOSCircle/CKBridge/SOSCloudTransport.c +++ b/Security/sec/SOSCircle/CKBridge/SOSCloudTransport.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/sec/SOSCircle/CKBridge/SOSCloudTransport.h b/Security/sec/SOSCircle/CKBridge/SOSCloudTransport.h similarity index 97% rename from sec/SOSCircle/CKBridge/SOSCloudTransport.h rename to Security/sec/SOSCircle/CKBridge/SOSCloudTransport.h index 477d12bf..8a9631b8 100644 --- a/sec/SOSCircle/CKBridge/SOSCloudTransport.h +++ b/Security/sec/SOSCircle/CKBridge/SOSCloudTransport.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.h b/Security/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.h new file mode 100644 index 00000000..a5a9d66a --- /dev/null +++ b/Security/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +// +// CKDKVSProxy.h +// ckd-xpc + +#import +#import +#import + +#import + +#import "SOSCloudKeychainConstants.h" +#import "SOSCloudKeychainClient.h" + +#define XPROXYSCOPE "proxy" + +@interface UbiqitousKVSProxy : NSObject +{ + id currentiCloudToken; + CloudItemsChangedBlock itemsChangedCallback; + int callbackMethod; +} + +@property (retain, nonatomic) NSDictionary *keyParameterKeys; +@property (retain, nonatomic) NSDictionary *circleKeys; +@property (retain, nonatomic) NSDictionary *messageKeys; + +@property (retain, nonatomic) NSMutableSet *alwaysKeys; +@property (retain, nonatomic) NSMutableSet *firstUnlockKeys; +@property (retain, nonatomic) NSMutableSet *unlockedKeys; +@property (retain, nonatomic) NSMutableSet *pendingKeys; +@property (retain, nonatomic) NSMutableSet *shadowPendingKeys; +@property (atomic) bool syncWithPeersPending; +@property (atomic) bool shadowSyncWithPeersPending; +@property (atomic) bool inCallout; +@property (atomic) bool oldInCallout; +@property (atomic) bool unlockedSinceBoot; +@property (atomic) bool isLocked; +@property (atomic) bool seenKVSStoreChange; +@property (atomic) bool ensurePeerRegistration; +@property (atomic) bool shadowEnsurePeerRegistration; +@property (atomic) dispatch_time_t nextFreshnessTime; + +@property (atomic) dispatch_source_t syncTimer; +@property (atomic) bool syncTimerScheduled; +@property (atomic) dispatch_time_t deadline; +@property (atomic) dispatch_time_t lastSyncTime; +@property (atomic) dispatch_queue_t calloutQueue; +@property (atomic) dispatch_queue_t freshParamsQueue; + ++ (UbiqitousKVSProxy *) sharedKVSProxy; +- (NSString *)description; +- (id)init; +- (void)streamEvent:(xpc_object_t)notification; +- (void)setItemsChangedBlock:(CloudItemsChangedBlock)itemsChangedBlock; + +- (void)setObject:(id)obj forKey:(id)key; +- (id)get:(id)key; +- (NSDictionary *)getAll; +- (void)requestSynchronization:(bool)force; +- (void)waitForSynchronization:(NSArray *)keys handler:(void (^)(NSDictionary *values, NSError *err))handler; +- (void)clearStore; +- (void)setObjectsFromDictionary:(NSDictionary *)values; +- (void)removeObjectForKey:(NSString *)keyToRemove; +- (void)processAllItems; +- (void)requestSyncWithAllPeers; +- (void)requestEnsurePeerRegistration; + +- (NSUbiquitousKeyValueStore *)cloudStore; + +-(void)registerAtTimeKeys:(NSDictionary*)keyparms; + +- (NSSet*) keysForCurrentLockState; +- (void) intersectWithCurrentLockState: (NSMutableSet*) set; + +- (NSMutableSet*) pendKeysAndGetNewlyPended: (NSSet*) keysToPend; + +- (NSMutableSet*) pendingKeysForCurrentLockState; +- (NSMutableSet*) pendKeysAndGetPendingForCurrentLockState: (NSSet*) startingSet; + +- (void) processPendingKeysForCurrentLockState; + +- (void)registerKeys: (NSDictionary*)keys; + +- (NSDictionary *)localNotification:(NSDictionary *)localNotificationDict outFlags:(int64_t *)outFlags; + +- (void)processKeyChangedEvent:(NSDictionary *)keysChangedInCloud; +- (NSMutableDictionary *)copyValues:(NSSet *)keysOfInterest; + +- (void) doAfterFlush: (dispatch_block_t) block; + +- (void) calloutWith: (void(^)(NSSet *pending, bool syncWithPeersPending, bool ensurePeerRegistration, dispatch_queue_t queue, void(^done)(NSSet *handledKeys, bool handledSyncWithPeers, bool handledEnsurePeerRegistration))) callout; +- (void) sendKeysCallout: (NSSet *(^)(NSSet* pending, NSError **error)) handleKeys; + + + +@end diff --git a/Security/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.m b/Security/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.m new file mode 100644 index 00000000..2f02cd7f --- /dev/null +++ b/Security/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.m @@ -0,0 +1,1058 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +// +// CKDKVSProxy.m +// ckd-xpc +// + +#import +#import +#import +#import + +#import +#import +#import +#import + +#import "CKDKVSProxy.h" +#import "CKDPersistentState.h" +#import "CKDUserInteraction.h" + +#import "SOSARCDefines.h" + +#include +#include +#include + +#include "SOSCloudKeychainConstants.h" + +#include +#include + +/* + The total space available in your app’s iCloud key-value storage is 1 MB. + The maximum number of keys you can specify is 1024, and the size limit for + each value associated with a key is 1 MB. So, for example, if you store a + single large value of 1 MB for a single key, that consumes your total + available storage. If you store 1 KB of data for each key, you can use + 1,000 key-value pairs. + */ + +static const char *kStreamName = "com.apple.notifyd.matching"; + +static NSString *kKeyKeyParameterKeys = @"KeyParameterKeys"; +static NSString *kKeyCircleKeys = @"CircleKeys"; +static NSString *kKeyMessageKeys = @"MessageKeys"; + + +static NSString *kKeyAlwaysKeys = @"AlwaysKeys"; +static NSString *kKeyFirstUnlockKeys = @"FirstUnlockKeys"; +static NSString *kKeyUnlockedKeys = @"UnlockedKeys"; +static NSString *kKeyPendingKeys = @"PendingKeys"; +static NSString *kKeyUnsentChangedKeys = @"unsentChangedKeys"; +static NSString *kKeyUnlockNotificationRequested = @"unlockNotificationRequested"; +static NSString *kKeySyncWithPeersPending = @"SyncWithPeersPending"; +static NSString *kKeyEnsurePeerRegistration = @"EnsurePeerRegistration"; + +enum +{ + kCallbackMethodSecurityd = 0, + kCallbackMethodXPC = 1, +}; + +static const int64_t kMinSyncDelay = (NSEC_PER_MSEC * 500); // 500ms minimum delay before a syncWithAllPeers call. +static const int64_t kMaxSyncDelay = (NSEC_PER_SEC * 5); // 5s maximun delay for a given request +static const int64_t kMinSyncInterval = (NSEC_PER_SEC * 15); // 15s minimum time between successive syncWithAllPeers calls. +static const int64_t kSyncTimerLeeway = (NSEC_PER_MSEC * 250); // 250ms leeway for sync events. + +@interface NSUbiquitousKeyValueStore (NSUbiquitousKeyValueStore_PrivateZ) +- (void) _synchronizeWithCompletionHandler:(void (^)(NSError *error))completionHandler; + +/* + // SPI For Security + - (void) synchronizeWithCompletionHandler:(void (^)(NSError *error))completionHandler; + */ + +@end + +@implementation UbiqitousKVSProxy + + +- (void)persistState +{ + [SOSPersistentState setRegisteredKeys:[self exportKeyInterests]]; +} + ++ (UbiqitousKVSProxy *) sharedKVSProxy +{ + static UbiqitousKVSProxy *sharedKVSProxy; + if (!sharedKVSProxy) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedKVSProxy = [[self alloc] init]; + }); + } + return sharedKVSProxy; +} + +- (id)init +{ + if (self = [super init]) + { + secnotice("event", "%@ start", self); + + _calloutQueue = dispatch_queue_create("CKDCallout", DISPATCH_QUEUE_SERIAL); + _freshParamsQueue = dispatch_queue_create("CKDFresh", DISPATCH_QUEUE_SERIAL); + _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, ^{ + [self timerFired]; + }); + dispatch_resume(_syncTimer); + + [[NSNotificationCenter defaultCenter] + addObserver: self + selector: @selector (iCloudAccountAvailabilityChanged:) + name: NSUbiquityIdentityDidChangeNotification + object: nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(cloudChanged:) + name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification + object:nil]; + + [self importKeyInterests: [SOSPersistentState registeredKeys]]; + + // Register for lock state changes + xpc_set_event_stream_handler(kStreamName, dispatch_get_main_queue(), + ^(xpc_object_t notification){ + [self streamEvent:notification]; + }); + + [self updateUnlockedSinceBoot]; + [self updateIsLocked]; + if (!_isLocked) + [self keybagDidUnlock]; + + secdebug(XPROXYSCOPE, "%@ done", self); + } + return self; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"<%s%s%s%s%s%s%s%s%s%s%s>", + _isLocked ? "L" : "U", + _unlockedSinceBoot ? "B" : "-", + _seenKVSStoreChange ? "K" : "-", + _syncTimerScheduled ? "T" : "-", + _syncWithPeersPending ? "s" : "-", + _ensurePeerRegistration ? "e" : "-", + [_pendingKeys count] ? "p" : "-", + _inCallout ? "C" : "-", + _shadowSyncWithPeersPending ? "S" : "-", + _shadowEnsurePeerRegistration ? "E" : "-", + [_shadowPendingKeys count] ? "P" : "-"]; +} + +- (void)processAllItems +{ + NSDictionary *allItems = [self getAll]; + if (allItems) + { + secnotice("event", "%@ sending: %@", self, [[allItems allKeys] componentsJoinedByString: @" "]); + [self processKeyChangedEvent:allItems]; + } + else + secdebug(XPROXYSCOPE, "%@ No items in KVS", self); +} + +- (void)setItemsChangedBlock:(CloudItemsChangedBlock)itemsChangedBlock +{ + self->itemsChangedCallback = itemsChangedBlock; +} + +- (void)dealloc +{ + secdebug(XPROXYSCOPE, "%@", self); + [[NSNotificationCenter defaultCenter] removeObserver:self + name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification object:nil]; + + [[NSNotificationCenter defaultCenter] removeObserver:self + name:NSUbiquityIdentityDidChangeNotification object:nil]; +} + +// MARK: ----- Client Interface ----- + +- (void)setObject:(id)obj forKey:(id)key +{ + secdebug("keytrace", "%@ key: %@, obj: %@", self, key, obj); + NSUbiquitousKeyValueStore *store = [self cloudStore]; + if (store) + { + id value = [store objectForKey:key]; + if (value) + secdebug("keytrace", "%@ Current value (before set) for key %@ is: %@", self, key, value); + else + secdebug("keytrace", "%@ No current value for key %@", self, key); + } + else + secdebug("keytrace", "Can't get store"); + + [[self cloudStore] setObject:obj forKey:key]; + [self requestSynchronization:NO]; +} + +- (void)setObjectsFromDictionary:(NSDictionary *)values +{ + secdebug(XPROXYSCOPE, "%@ start: %lu values to put", self, (unsigned long)[values count]); + + NSUbiquitousKeyValueStore *store = [self cloudStore]; + if (store && values) + { + [values enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) + { + if (obj == NULL || obj == [NSNull null]) + [store removeObjectForKey:key]; + else + [store setObject:obj forKey:key]; + }]; + + [self requestSynchronization:NO]; + } + else + secdebug(XPROXYSCOPE, "%@ NULL? store: %@, values: %@", self, store, values); +} + +- (void)requestSynchronization:(bool)force +{ + if (force) + { + secdebug(XPROXYSCOPE, "%@ synchronize (forced)", self); + [[self cloudStore] synchronize]; + } + else + { + secdebug(XPROXYSCOPE, "%@ synchronize (soon)", self); + [[self cloudStore] synchronize]; + } +} + +- (NSUbiquitousKeyValueStore *)cloudStore +{ + NSUbiquitousKeyValueStore *iCloudStore = [NSUbiquitousKeyValueStore defaultStore]; + if (!iCloudStore) { + secerror("%s %@ NO NSUbiquitousKeyValueStore defaultStore", kWAIT2MINID, self); + } + return iCloudStore; +} + +/* + Only call out to syncdefaultsd once every 5 seconds, since parameters can't change that + fast and callers expect synchonicity. + + Since we don't actually get the values for the keys, just store off a timestamp. +*/ + +// try to synchronize asap, and invoke the handler on completion to take incoming changes. + + +- (void)waitForSynchronization:(NSArray *)keys handler:(void (^)(NSDictionary *values, NSError *err))handler +{ + if (!keys) + { + NSError *err = [NSError errorWithDomain:(NSString *)NSPOSIXErrorDomain code:(NSInteger)ENOPROTOOPT userInfo:nil]; + secerrorq("%s RETURNING TO securityd: %@ param error; calling handler", kWAIT2MINID, self); + handler(@{}, err); + return; + } + + NSUbiquitousKeyValueStore * store = [self cloudStore]; + + secnoticeq("fresh", "%s Requesting freshness", kWAIT2MINID); + dispatch_async(_freshParamsQueue, ^{ + // _freshParamsQueue + __block NSError *failure = NULL; + __block dispatch_time_t next_time = _nextFreshnessTime; + dispatch_time_t now = dispatch_time(DISPATCH_TIME_NOW, 0); + if (now > next_time) { + dispatch_semaphore_t freshSemaphore = dispatch_semaphore_create(0); + secnoticeq("fresh", "%s CALLING OUT TO syncdefaultsd SWCH: %@", kWAIT2MINID, self); + [store synchronizeWithCompletionHandler:^(NSError *error) { + if (error) { + failure = error; + secerrorq("%s RETURNING FROM syncdefaultsd SWCH: %@: %@", kWAIT2MINID, self, error); + } else { + secnoticeq("fresh", "%s RETURNING FROM syncdefaultsd SWCH: %@", kWAIT2MINID, self); + + [store synchronize]; // Per olivier in , sync before getting values + secnoticeq("fresh", "%s RETURNING FROM syncdefaultsd SYNC: %@", kWAIT2MINID, self); + + // This hysteresis balances between failing to notice parameters from remote devices and + // pestering synceddefaultsd with clients many repeated requests to do freshness. + const uint64_t delayBeforeCallingAgainInSeconds = 5ull * NSEC_PER_SEC; + next_time = dispatch_time(DISPATCH_TIME_NOW, delayBeforeCallingAgainInSeconds); + } + dispatch_semaphore_signal(freshSemaphore); + }]; + dispatch_semaphore_wait(freshSemaphore, DISPATCH_TIME_FOREVER); + } + + dispatch_async(dispatch_get_main_queue(), ^{ + _nextFreshnessTime = next_time; + + if (failure) + handler(@{}, failure); + else + handler([self copyValues:[NSSet setWithArray:keys]], NULL); + }); + + }); +} + +- (void)removeObjectForKey:(NSString *)keyToRemove +{ + [[self cloudStore] removeObjectForKey:keyToRemove]; +} + +- (void)clearStore +{ + secdebug(XPROXYSCOPE, "%@ clearStore", self); + NSDictionary *dict = [[self cloudStore] dictionaryRepresentation]; + NSArray *allKeys = [dict allKeys]; + NSMutableArray* nullKeys = [NSMutableArray array]; + + _alwaysKeys = [NSMutableSet setWithArray:nullKeys]; + _firstUnlockKeys = [NSMutableSet setWithArray:nullKeys]; + _unlockedKeys = [NSMutableSet setWithArray:nullKeys]; + _keyParameterKeys = @{}; + _circleKeys = @{}; + _messageKeys = @{}; + + [allKeys enumerateObjectsUsingBlock:^(id key, NSUInteger idx, BOOL *stop) + { + secdebug(XPROXYSCOPE, "%@ Clearing value for key %@", self, key); + [[self cloudStore] removeObjectForKey:(NSString *)key]; + }]; + + [self requestSynchronization:YES]; +} + + +// +// MARK: ----- KVS key lists ----- +// + +- (id)get:(id)key +{ + return [[self cloudStore] objectForKey:key]; +} + +- (NSDictionary *)getAll +{ + return [[self cloudStore] dictionaryRepresentation]; +} + +- (NSDictionary*) exportKeyInterests +{ + return @{ kKeyAlwaysKeys:[_alwaysKeys allObjects], + kKeyFirstUnlockKeys:[_firstUnlockKeys allObjects], + kKeyUnlockedKeys:[_unlockedKeys allObjects], + +#if 0 + kKeyKeyParameterKeys: _keyParameterKeys, + kKeyMessageKeys : _messageKeys, + kKeyCircleKeys : _circleKeys, +#endif + kKeyPendingKeys:[_pendingKeys allObjects], + kKeySyncWithPeersPending:[NSNumber numberWithBool:_syncWithPeersPending], + kKeyEnsurePeerRegistration:[NSNumber numberWithBool:_ensurePeerRegistration] + }; +} + +- (void) importKeyInterests: (NSDictionary*) interests +{ + _alwaysKeys = [NSMutableSet setWithArray: interests[kKeyAlwaysKeys]]; + _firstUnlockKeys = [NSMutableSet setWithArray: interests[kKeyFirstUnlockKeys]]; + _unlockedKeys = [NSMutableSet setWithArray: interests[kKeyUnlockedKeys]]; + + _pendingKeys = [NSMutableSet setWithArray: interests[kKeyPendingKeys]]; + _syncWithPeersPending = [interests[kKeySyncWithPeersPending] boolValue]; + _ensurePeerRegistration = [interests[kKeyEnsurePeerRegistration] boolValue]; +} + +- (NSMutableSet *)copyAllKeys +{ + NSMutableSet *allKeys = [NSMutableSet setWithSet: _alwaysKeys]; + [allKeys unionSet: _firstUnlockKeys]; + [allKeys unionSet: _unlockedKeys]; + return allKeys; +} + +-(void)registerAtTimeKeys:(NSDictionary*)keyparms +{ + NSArray *alwaysArray = [keyparms valueForKey: kKeyAlwaysKeys]; + NSArray *firstUnlockedKeysArray = [keyparms valueForKey: kKeyFirstUnlockKeys]; + NSArray *whenUnlockedKeysArray = [keyparms valueForKey: kKeyUnlockedKeys]; + + if(alwaysArray) + [_alwaysKeys unionSet: [NSMutableSet setWithArray: alwaysArray]]; + if(firstUnlockedKeysArray) + [_firstUnlockKeys unionSet: [NSMutableSet setWithArray: firstUnlockedKeysArray]]; + if(whenUnlockedKeysArray) + [_unlockedKeys unionSet: [NSMutableSet setWithArray: whenUnlockedKeysArray]]; +} + + +- (void)registerKeys: (NSDictionary*)keys +{ + secdebug(XPROXYSCOPE, "registerKeys: keys: %@", keys); + + NSMutableSet *allOldKeys = [self copyAllKeys]; + + NSDictionary *keyparms = [keys valueForKey: [NSString stringWithUTF8String: kMessageKeyParameter]]; + NSDictionary *circles = [keys valueForKey: [NSString stringWithUTF8String: kMessageCircle]]; + NSDictionary *messages = [keys valueForKey: [NSString stringWithUTF8String: kMessageMessage]]; + + _alwaysKeys = [NSMutableSet set]; + _firstUnlockKeys = [NSMutableSet set]; + _unlockedKeys = [NSMutableSet set]; + + _keyParameterKeys = keyparms; + _circleKeys = circles; + _messageKeys = messages; + + [self registerAtTimeKeys: _keyParameterKeys]; + [self registerAtTimeKeys: _circleKeys]; + [self registerAtTimeKeys: _messageKeys]; + + NSMutableSet *allNewKeys = [self copyAllKeys]; + + // Make sure keys we no longer care about are not pending + [_pendingKeys intersectSet:allNewKeys]; + if (_shadowPendingKeys) { + [_shadowPendingKeys intersectSet:allNewKeys]; + } + + // All new keys only is new keys (remove old keys) + [allNewKeys minusSet:allOldKeys]; + + // Mark new keys pending, they're new! + NSMutableSet *newKeysForCurrentLockState = [self pendKeysAndGetNewlyPended:allNewKeys]; + + [self persistState]; // Before we might call out, save our state so we recover if we crash + + [self intersectWithCurrentLockState: newKeysForCurrentLockState]; + // TODO: Don't processPendingKeysForCurrentLockState if none of the new keys have values. + if ([newKeysForCurrentLockState count] != 0) { + [self processPendingKeysForCurrentLockState]; + } +} + +- (NSDictionary *)localNotification:(NSDictionary *)localNotificationDict outFlags:(int64_t *)outFlags +{ + __block bool done = false; + __block int64_t returnedFlags = 0; + __block NSDictionary *responses = NULL; + typedef bool (^CKDUserInteractionBlock) (CFDictionaryRef responses); + + CKDUserInteraction *cui = [CKDUserInteraction sharedInstance]; + [cui requestShowNotification:localNotificationDict completion:^ bool (CFDictionaryRef userResponses, int64_t flags) + { + responses = [NSDictionary dictionaryWithDictionary:(__bridge NSDictionary *)userResponses]; + returnedFlags = flags; + secdebug(XPROXYSCOPE, "%@ requestShowNotification: dict: %@, flags: %#llx", self, responses, returnedFlags); + done = true; + return true; + }]; + + // TODO: replace with e.g. dispatch calls to wait, or semaphore + while (!done) + sleep(1); + if (outFlags) + { + secdebug(XPROXYSCOPE, "%@ outFlags: %#llx", self, returnedFlags); + *outFlags = returnedFlags; + } + return responses; +} + +- (void)saveToUbiquitousStore +{ + [self requestSynchronization:NO]; +} + +// MARK: ----- Event Handling ----- + +- (void)streamEvent:(xpc_object_t)notification +{ +#if (!TARGET_IPHONE_SIMULATOR) + const char *notificationName = xpc_dictionary_get_string(notification, "Notification"); + if (!notificationName) { + } else if (strcmp(notificationName, kUserKeybagStateChangeNotification)==0) { + return [self keybagStateChange]; + } else if (strcmp(notificationName, kCloudKeychainStorechangeChangeNotification)==0) { + return [self kvsStoreChange]; + } else if (strcmp(notificationName, kNotifyTokenForceUpdate)==0) { + // DEBUG -- Possibly remove in future + return [self processAllItems]; + } + const char *eventName = xpc_dictionary_get_string(notification, "XPCEventName"); + char *desc = xpc_copy_description(notification); + secerror("%@ event: %s name: %s desc: %s", self, eventName, notificationName, desc); + if (desc) + free((void *)desc); +#endif +} + +- (void)iCloudAccountAvailabilityChanged:(NSNotification*)notification +{ + /* + Continuing this example, you’d then implement an iCloudAccountAvailabilityChanged: method that would: + + Call the ubiquityIdentityToken method and store its return value. + Compare the new value to the previous value, to find out if the user logged out of their account or + logged in to a different account. If the previously-used account is now unavailable, save the current + state locally as needed, empty your iCloud-related data caches, and refresh all iCloud-related user interface elements. + */ + id previCloudToken = currentiCloudToken; + currentiCloudToken = [[NSFileManager defaultManager] ubiquityIdentityToken]; + if (previCloudToken != currentiCloudToken) + secnotice("event", "%@ iCloud account changed!", self); + else + secnotice("event", "%@ %@", self, notification); +} + +- (void)cloudChanged:(NSNotification*)notification +{ + /* + Posted when the value of one or more keys in the local key-value store + changed due to incoming data pushed from iCloud. This notification is + sent only upon a change received from iCloud; it is not sent when your + app sets a value. + + The user info dictionary can contain the reason for the notification as + well as a list of which values changed, as follows: + + The value of the NSUbiquitousKeyValueStoreChangeReasonKey key, when + present, indicates why the key-value store changed. Its value is one of + the constants in "Change Reason Values." + + The value of the NSUbiquitousKeyValueStoreChangedKeysKey, when present, + is an array of strings, each the name of a key whose value changed. The + notification object is the NSUbiquitousKeyValueStore object whose contents + changed. + + NSUbiquitousKeyValueStoreInitialSyncChange is only posted if there is any + local value that has been overwritten by a distant value. If there is no + conflict between the local and the distant values when doing the initial + sync (e.g. if the cloud has no data stored or the client has not stored + any data yet), you'll never see that notification. + + NSUbiquitousKeyValueStoreInitialSyncChange implies an initial round trip + with server but initial round trip with server does not imply + NSUbiquitousKeyValueStoreInitialSyncChange. + */ + + secdebug(XPROXYSCOPE, "%@ cloudChanged notification: %@", self, notification); + + NSDictionary *userInfo = [notification userInfo]; + NSNumber *reason = [userInfo objectForKey:NSUbiquitousKeyValueStoreChangeReasonKey]; + if (reason) switch ([reason integerValue]) { + case NSUbiquitousKeyValueStoreInitialSyncChange: + case NSUbiquitousKeyValueStoreServerChange: + { + _seenKVSStoreChange = YES; + NSSet *keysChangedInCloud = [NSSet setWithArray:[userInfo objectForKey:NSUbiquitousKeyValueStoreChangedKeysKey]]; + NSSet *keysOfInterestThatChanged = [self pendKeysAndGetPendingForCurrentLockState:keysChangedInCloud]; + NSMutableDictionary *changedValues = [self copyValues:keysOfInterestThatChanged]; + if ([reason integerValue] == NSUbiquitousKeyValueStoreInitialSyncChange) + changedValues[(__bridge NSString*)kSOSKVSInitialSyncKey] = @"true"; + + secnotice("event", "%@ keysChangedInCloud: %@ keysOfInterest: %@", self, [[keysChangedInCloud allObjects] componentsJoinedByString: @" "], [[changedValues allKeys] componentsJoinedByString: @" "]); + if ([changedValues count]) + [self processKeyChangedEvent:changedValues]; + break; + } + case NSUbiquitousKeyValueStoreQuotaViolationChange: + seccritical("%@ event received NSUbiquitousKeyValueStoreQuotaViolationChange", self); + break; + case NSUbiquitousKeyValueStoreAccountChange: + // The primary account changed. We do not get this for password changes on the same account + secnotice("event", "%@ NSUbiquitousKeyValueStoreAccountChange", self); + NSDictionary *changedValues = @{ (__bridge NSString*)kSOSKVSAccountChangedKey: @"true" }; + [self processKeyChangedEvent:changedValues]; + break; + } +} + +- (void) doAfterFlush: (dispatch_block_t) block +{ + // Flush any pending communication to Securityd. + + dispatch_async(_calloutQueue, block); +} + +- (void) calloutWith: (void(^)(NSSet *pending, bool syncWithPeersPending, bool ensurePeerRegistration, dispatch_queue_t queue, void(^done)(NSSet *handledKeys, bool handledSyncWithPeers, bool handledEnsurePeerRegistration))) callout +{ + // In CKDKVSProxy's serial queue + dispatch_queue_t ckdkvsproxy_queue = dispatch_get_main_queue(); + + _oldInCallout = YES; + + // dispatch_get_global_queue - well-known global concurrent queue + // dispatch_get_main_queue - default queue that is bound to the main thread + xpc_transaction_begin(); + dispatch_async(_calloutQueue, ^{ + __block NSSet *myPending; + __block bool mySyncWithPeersPending; + __block bool myEnsurePeerRegistration; + __block bool wasLocked; + dispatch_sync(ckdkvsproxy_queue, ^{ + myPending = [_pendingKeys copy]; + mySyncWithPeersPending = _syncWithPeersPending; + myEnsurePeerRegistration = _ensurePeerRegistration; + wasLocked = _isLocked; + + _inCallout = YES; + if (!_oldInCallout) + secnotice("deaf", ">>>>>>>>>>> WTFBBQ _oldInCallout is NO and we're heading in to the callout!"); + + _shadowPendingKeys = [NSMutableSet set]; + _shadowSyncWithPeersPending = NO; + }); + + callout(myPending, mySyncWithPeersPending, myEnsurePeerRegistration, ckdkvsproxy_queue, ^(NSSet *handledKeys, bool handledSyncWithPeers, bool handledEnsurePeerRegistration) { + secdebug("event", "%@ %s%s before callout handled: %s%s", self, mySyncWithPeersPending ? "S" : "s", myEnsurePeerRegistration ? "E" : "e", handledSyncWithPeers ? "S" : "s", handledEnsurePeerRegistration ? "E" : "e"); + + // In CKDKVSProxy's serial queue + _inCallout = NO; + _oldInCallout = NO; + + // Update ensurePeerRegistration + _ensurePeerRegistration = ((myEnsurePeerRegistration && !handledEnsurePeerRegistration) || _shadowEnsurePeerRegistration); + + _shadowEnsurePeerRegistration = NO; + + if(_ensurePeerRegistration && !_isLocked) + [self doEnsurePeerRegistration]; + + // Update SyncWithPeers stuff. + _syncWithPeersPending = ((mySyncWithPeersPending && (!handledSyncWithPeers)) || _shadowSyncWithPeersPending); + + _shadowSyncWithPeersPending = NO; + if (handledSyncWithPeers) + _lastSyncTime = dispatch_time(DISPATCH_TIME_NOW, 0); + + // Update pendingKeys and handle them + [_pendingKeys minusSet: handledKeys]; + bool hadShadowPendingKeys = [_shadowPendingKeys count]; + NSSet *filteredKeys = [self pendKeysAndGetPendingForCurrentLockState:_shadowPendingKeys]; + _shadowPendingKeys = nil; + + // Write state to disk + [self persistState]; + + // Handle shadow pended stuff + if (_syncWithPeersPending && !_isLocked) + [self scheduleSyncRequestTimer]; + /* We don't want to call processKeyChangedEvent if we failed to + handle pending keys and the device didn't unlock nor receive + any kvs changes while we were in our callout. + Doing so will lead to securityd and CloudKeychainProxy + talking to each other forever in a tight loop if securityd + repeatedly returns an error processing the same message. + Instead we leave any old pending keys until the next event. */ + if (hadShadowPendingKeys || (!_isLocked && wasLocked)) + [self processKeyChangedEvent:[self copyValues:filteredKeys]]; + xpc_transaction_end(); + }); + }); +} + +- (void) sendKeysCallout: (NSSet *(^)(NSSet* pending, NSError** error)) handleKeys { + [self calloutWith: ^(NSSet *pending, bool syncWithPeersPending, bool ensurePeerRegistration, dispatch_queue_t queue, void(^done)(NSSet *, bool, bool)) { + NSError* error = NULL; + + NSSet * handled = handleKeys(pending, &error); + + dispatch_async(queue, ^{ + if (!handled) { + secerror("%@ ensurePeerRegistration failed: %@", self, error); + } + + done(handled, NO, NO); + }); + }]; +} + +- (void) doEnsurePeerRegistration +{ + [self calloutWith:^(NSSet *pending, bool syncWithPeersPending, bool ensurePeerRegistration, dispatch_queue_t queue, void(^done)(NSSet *, bool, bool)) { + CFErrorRef error = NULL; + bool handledEnsurePeerRegistration = SOSCCProcessEnsurePeerRegistration(&error); + secerror("%@ ensurePeerRegistration called, %@ (%@)", self, handledEnsurePeerRegistration ? @"success" : @"failure", error); + dispatch_async(queue, ^{ + if (!handledEnsurePeerRegistration) { + secerror("%@ ensurePeerRegistration failed: %@", self, error); + } + + done(nil, NO, handledEnsurePeerRegistration); + CFReleaseSafe(error); + }); + }]; +} + +- (void) doSyncWithAllPeers +{ + [self calloutWith:^(NSSet *pending, bool syncWithPeersPending, bool ensurePeerRegistration, dispatch_queue_t queue, void(^done)(NSSet *, bool, bool)) { + CFErrorRef error = NULL; + SyncWithAllPeersReason reason = SOSCCProcessSyncWithAllPeers(&error); + dispatch_async(queue, ^{ + bool handledSyncWithPeers = NO; + if (reason == kSyncWithAllPeersSuccess) { + handledSyncWithPeers = YES; + secnotice("event", "%@ syncWithAllPeers succeeded", self); + } else if (reason == kSyncWithAllPeersLocked) { + secnotice("event", "%@ syncWithAllPeers attempted while locked - waiting for unlock", self); + handledSyncWithPeers = NO; + [self updateIsLocked]; + } else if (reason == kSyncWithAllPeersOtherFail) { + // Pretend we handled syncWithPeers, by pushing out the _lastSyncTime + // This will cause us to wait for kMinSyncInterval seconds before + // retrying, so we don't spam securityd if sync is failing + secerror("%@ syncWithAllPeers %@, rescheduling timer", self, error); + _lastSyncTime = dispatch_time(DISPATCH_TIME_NOW, 0); + } else { + secerror("%@ syncWithAllPeers %@, unknown reason: %d", self, error, reason); + } + + done(nil, handledSyncWithPeers, false); + CFReleaseSafe(error); + }); + }]; +} + +- (void)timerFired +{ + secnotice("event", "%@ syncWithPeersPending: %d inCallout: %d isLocked: %d", self, _syncWithPeersPending, _inCallout, _isLocked); + _syncTimerScheduled = NO; + if (_syncWithPeersPending && !_inCallout && !_isLocked) + [self doSyncWithAllPeers]; +} + +- (dispatch_time_t) nextSyncTime +{ + dispatch_time_t nextSync = dispatch_time(DISPATCH_TIME_NOW, kMinSyncDelay); + + // Don't sync again unless we waited at least kMinSyncInterval + if (_lastSyncTime) { + dispatch_time_t soonest = dispatch_time(_lastSyncTime, kMinSyncInterval); + if (nextSync < soonest || _deadline < soonest) { + secdebug("timer", "%@ backing off", self); + return soonest; + } + } + + // Don't delay more than kMaxSyncDelay after the first request. + if (nextSync > _deadline) { + secdebug("timer", "%@ hit deadline", self); + return _deadline; + } + + // Bump the timer by kMinSyncDelay + if (_syncTimerScheduled) + secdebug("timer", "%@ bumped timer", self); + else + secdebug("timer", "%@ scheduled timer", self); + + return nextSync; +} + +- (void)scheduleSyncRequestTimer +{ + dispatch_source_set_timer(_syncTimer, [self nextSyncTime], DISPATCH_TIME_FOREVER, kSyncTimerLeeway); + _syncTimerScheduled = YES; +} + +- (void)requestSyncWithAllPeers // secd calling SOSCCSyncWithAllPeers invokes this +{ +#if !defined(NDEBUG) + NSString *desc = [self description]; +#endif + + if (!_syncWithPeersPending || (_inCallout && !_shadowSyncWithPeersPending)) + _deadline = dispatch_time(DISPATCH_TIME_NOW, kMaxSyncDelay); + + if (!_syncWithPeersPending) { + _syncWithPeersPending = YES; + [self persistState]; + } + + if (_inCallout) + _shadowSyncWithPeersPending = YES; + else if (!_isLocked) + [self scheduleSyncRequestTimer]; + + secdebug("event", "%@ %@", desc, self); +} + +- (void)requestEnsurePeerRegistration // secd calling SOSCCSyncWithAllPeers invokes this +{ +#if !defined(NDEBUG) + NSString *desc = [self description]; +#endif + + if (_inCallout) { + _shadowEnsurePeerRegistration = YES; + } else { + _ensurePeerRegistration = YES; + if (!_isLocked) + [self doEnsurePeerRegistration]; + [self persistState]; + } + + secdebug("event", "%@ %@", desc, self); +} + + +- (BOOL) updateUnlockedSinceBoot +{ + CFErrorRef aksError = NULL; + if (!SecAKSGetHasBeenUnlocked(&_unlockedSinceBoot, &aksError)) { + secerror("%@ Got error from SecAKSGetHasBeenUnlocked: %@", self, aksError); + CFReleaseSafe(aksError); + return NO; + } + return YES; +} + +- (BOOL) updateIsLocked +{ + CFErrorRef aksError = NULL; + if (!SecAKSGetIsLocked(&_isLocked, &aksError)) { + secerror("%@ Got error querying lock state: %@", self, aksError); + CFReleaseSafe(aksError); + return NO; + } + if (!_isLocked) + _unlockedSinceBoot = YES; + return YES; +} + +- (void) keybagStateChange +{ + BOOL wasLocked = _isLocked; + if ([self updateIsLocked]) { + if (wasLocked == _isLocked) + secdebug("event", "%@ still %s ignoring", self, _isLocked ? "locked" : "unlocked"); + else if (_isLocked) + [self keybagDidLock]; + else + [self keybagDidUnlock]; + } +} + +- (void) keybagDidLock +{ + secnotice("event", "%@", self); +} + +- (void) keybagDidUnlock +{ + secnotice("event", "%@", self); + if (_ensurePeerRegistration) { + [self doEnsurePeerRegistration]; + } + + // First send changed keys to securityd so it can proccess updates + [self processPendingKeysForCurrentLockState]; + + // Then, tickle securityd to perform a sync if needed. + if (_syncWithPeersPending && !_syncTimerScheduled) { + [self doSyncWithAllPeers]; + } +} + +- (void) kvsStoreChange { + if (!_seenKVSStoreChange) { + _seenKVSStoreChange = YES; // Only do this once + secnotice("event", "%@ received darwin notification before first NSNotification", self); + // TODO This might not be needed if we always get the NSNotification + // deleived even if we were launched due to a kvsStoreChange + // Send all keys for current lock state to securityd so it can proccess them + [self pendKeysAndGetNewlyPended: [self copyAllKeys]]; + [self processPendingKeysForCurrentLockState]; + } else { + secdebug("event", "%@ ignored, waiting for NSNotification", self); + } +} + +// +// MARK: ----- Key Filtering ----- +// + +- (NSSet*) keysForCurrentLockState +{ + secdebug("keytrace", "%@ Filtering: unlockedSinceBoot: %d\n unlocked: %d\n, _keysOfInterest: %@", self, (int) _unlockedSinceBoot, (int) !_isLocked, [self exportKeyInterests]); + + NSMutableSet *currentStateKeys = [NSMutableSet setWithSet: _alwaysKeys]; + if (_unlockedSinceBoot) + [currentStateKeys unionSet: _firstUnlockKeys]; + + if (!_isLocked) + [currentStateKeys unionSet: _unlockedKeys]; + + return currentStateKeys; +} + +- (NSMutableSet*) pendKeysAndGetNewlyPended: (NSSet*) keysToPend +{ + NSMutableSet *newlyPendedKeys = [keysToPend mutableCopy]; + [newlyPendedKeys minusSet: _pendingKeys]; + if (_shadowPendingKeys) { + [newlyPendedKeys minusSet: _shadowPendingKeys]; + } + + [_pendingKeys unionSet:keysToPend]; + if (_shadowPendingKeys) { + [_shadowPendingKeys unionSet:keysToPend]; + } + + return newlyPendedKeys; +} + +- (void) intersectWithCurrentLockState: (NSMutableSet*) set +{ + [set intersectSet: [self keysForCurrentLockState]]; +} + +- (NSMutableSet*) pendingKeysForCurrentLockState +{ + NSMutableSet * result = [_pendingKeys mutableCopy]; + [self intersectWithCurrentLockState:result]; + return result; +} + +- (NSMutableSet*) pendKeysAndGetPendingForCurrentLockState: (NSSet*) startingSet +{ + [self pendKeysAndGetNewlyPended: startingSet]; + + return [self pendingKeysForCurrentLockState]; +} + +- (NSMutableDictionary *)copyValues:(NSSet*)keysOfInterest +{ + // Grab values from KVS. + NSUbiquitousKeyValueStore *store = [self cloudStore]; + NSMutableDictionary *changedValues = [NSMutableDictionary dictionaryWithCapacity:0]; + [keysOfInterest enumerateObjectsUsingBlock:^(id obj, BOOL *stop) + { + NSString* key = (NSString*) obj; + id objval = [store objectForKey:key]; + if (!objval) objval = [NSNull null]; + + [changedValues setObject:objval forKey:key]; + secdebug(XPROXYSCOPE, "%@ storeChanged updated value for %@", self, key); + }]; + return changedValues; +} + +/* + During RegisterKeys, separate keys-of-interest into three disjoint sets: + - keys that we always want to be notified about; this means we can get the + value at any time + - keys that require the device to have been unlocked at least once + - keys that require the device to be unlocked now + + Typically, the sets of keys will be: + + - Dk: alwaysKeys + - Ck: firstUnlock + - Ak: unlocked + + The caller is responsible for making sure that the keys in e.g. alwaysKeys are + values that can be handled at any time (that is, not when unlocked) + + Each time we get a notification from ubiquity that keys have changed, we need to + see if anything of interest changed. If we don't care, then done. + + For each key-of-interest that changed, we either notify the client that things + changed, or add it to a pendingNotifications list. If the notification to the + client fails, also add it to the pendingNotifications list. This pending list + should be written to persistent storage and consulted any time we either get an + item changed notification, or get a stream event signalling a change in lock state. + + We can notify the client either through XPC if a connection is set up, or call a + routine in securityd to launch it. + + */ + +- (void)processKeyChangedEvent:(NSDictionary *)changedValues +{ + NSMutableDictionary* filtered = [NSMutableDictionary dictionary]; + + NSMutableArray* nullKeys = [NSMutableArray array]; + // Remove nulls because we don't want them in securityd. + [changedValues enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + if (obj == [NSNull null]) + [nullKeys addObject:key]; + else{ + filtered[key] = obj; + } + }]; + if ([nullKeys count]) + [_pendingKeys minusSet: [NSSet setWithArray: nullKeys]]; + + if([filtered count] != 0 ){ + [self sendKeysCallout:^NSSet *(NSSet *pending, NSError** error) { + CFErrorRef cf_error = NULL; + NSArray* handledMessage = (__bridge_transfer NSArray*) _SecKeychainSyncUpdateMessage((__bridge CFDictionaryRef)filtered, &cf_error); + NSError *updateError = (__bridge_transfer NSError*)cf_error; + if (error) + *error = updateError; + + secnotice("keytrace", "%@ misc handled: %@ null: %@ pending: %@", self, + [handledMessage componentsJoinedByString: @" "], + [nullKeys componentsJoinedByString: @" "], + [[_pendingKeys allObjects] componentsJoinedByString: @" "]); + + return handledMessage ? [NSSet setWithArray: handledMessage] : nil; + }]; + } else { + secnotice("keytrace", "null: %@ pending: %@", + [nullKeys componentsJoinedByString: @" "], + [[_pendingKeys allObjects] componentsJoinedByString: @" "]); + } +} + +- (void) processPendingKeysForCurrentLockState +{ + [self processKeyChangedEvent: [self copyValues: [self pendingKeysForCurrentLockState]]]; +} + +@end + + diff --git a/sec/SOSCircle/CloudKeychainProxy/CKDPersistentState.h b/Security/sec/SOSCircle/CloudKeychainProxy/CKDPersistentState.h similarity index 95% rename from sec/SOSCircle/CloudKeychainProxy/CKDPersistentState.h rename to Security/sec/SOSCircle/CloudKeychainProxy/CKDPersistentState.h index 4609f015..110226cc 100644 --- a/sec/SOSCircle/CloudKeychainProxy/CKDPersistentState.h +++ b/Security/sec/SOSCircle/CloudKeychainProxy/CKDPersistentState.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/sec/SOSCircle/CloudKeychainProxy/CKDPersistentState.m b/Security/sec/SOSCircle/CloudKeychainProxy/CKDPersistentState.m similarity index 98% rename from sec/SOSCircle/CloudKeychainProxy/CKDPersistentState.m rename to Security/sec/SOSCircle/CloudKeychainProxy/CKDPersistentState.m index ad0f6166..3d3ae139 100644 --- a/sec/SOSCircle/CloudKeychainProxy/CKDPersistentState.m +++ b/Security/sec/SOSCircle/CloudKeychainProxy/CKDPersistentState.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/sec/SOSCircle/CloudKeychainProxy/CKDUserInteraction.h b/Security/sec/SOSCircle/CloudKeychainProxy/CKDUserInteraction.h similarity index 94% rename from sec/SOSCircle/CloudKeychainProxy/CKDUserInteraction.h rename to Security/sec/SOSCircle/CloudKeychainProxy/CKDUserInteraction.h index 350d567c..bd520ca9 100644 --- a/sec/SOSCircle/CloudKeychainProxy/CKDUserInteraction.h +++ b/Security/sec/SOSCircle/CloudKeychainProxy/CKDUserInteraction.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2012-2013 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/sec/SOSCircle/CloudKeychainProxy/CKDUserInteraction.m b/Security/sec/SOSCircle/CloudKeychainProxy/CKDUserInteraction.m similarity index 98% rename from sec/SOSCircle/CloudKeychainProxy/CKDUserInteraction.m rename to Security/sec/SOSCircle/CloudKeychainProxy/CKDUserInteraction.m index 34b0c5e3..58e9175e 100644 --- a/sec/SOSCircle/CloudKeychainProxy/CKDUserInteraction.m +++ b/Security/sec/SOSCircle/CloudKeychainProxy/CKDUserInteraction.m @@ -1,15 +1,15 @@ /* - * Copyright (c) 2012-2013 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/sec/SOSCircle/CloudKeychainProxy/ckdmain.m b/Security/sec/SOSCircle/CloudKeychainProxy/ckdmain.m similarity index 92% rename from sec/SOSCircle/CloudKeychainProxy/ckdmain.m rename to Security/sec/SOSCircle/CloudKeychainProxy/ckdmain.m index 7cb90de1..3871a9c1 100644 --- a/sec/SOSCircle/CloudKeychainProxy/ckdmain.m +++ b/Security/sec/SOSCircle/CloudKeychainProxy/ckdmain.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -25,8 +25,6 @@ // main.m // ckd-xpc // -// Created by John Hurley on 7/19/12. -// Copyright (c) 2012 John Hurley. All rights reserved. // /* diff --git a/Security/sec/SOSCircle/CloudKeychainProxy/cloudkeychain.entitlements.plist b/Security/sec/SOSCircle/CloudKeychainProxy/cloudkeychain.entitlements.plist new file mode 100644 index 00000000..46c70ef7 --- /dev/null +++ b/Security/sec/SOSCircle/CloudKeychainProxy/cloudkeychain.entitlements.plist @@ -0,0 +1,19 @@ + + + + + keychain-sync-updates + + application-identifier + com.apple.security.cloudkeychainproxy3 + sync-keychain + + keychain-access-groups + + sync + * + + com.apple.developer.ubiquity-kvstore-identifier + com.apple.security.cloudkeychainproxy3 + + diff --git a/Security/sec/SOSCircle/CloudKeychainProxy/cloudkeychainproxy.m b/Security/sec/SOSCircle/CloudKeychainProxy/cloudkeychainproxy.m new file mode 100644 index 00000000..23eea930 --- /dev/null +++ b/Security/sec/SOSCircle/CloudKeychainProxy/cloudkeychainproxy.m @@ -0,0 +1,465 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +// +// main.m +// ckd-xpc +// +// + +/* + This XPC service is essentially just a proxy to iCloud KVS, which exists since + the main security code cannot link against Foundation. + + See sendTSARequestWithXPC in tsaSupport.c for how to call the service + + send message to app with xpc_connection_send_message + + For now, build this with: + + ~rc/bin/buildit . --rootsDirectory=/var/tmp -noverify -offline -target CloudKeychainProxy + + and install or upgrade with: + + darwinup install /var/tmp/sec.roots/sec~dst + darwinup upgrade /var/tmp/sec.roots/sec~dst + + You must use darwinup during development to update system caches +*/ + +//------------------------------------------------------------------------------------------------ + +#include + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#include +#include + +#import "SOSCloudKeychainConstants.h" +#import "CKDKVSProxy.h" + +void finalize_connection(void *not_used); +void handle_connection_event(const xpc_connection_t peer); +static void cloudkeychainproxy_peer_dictionary_handler(const xpc_connection_t peer, xpc_object_t event); + +static bool operation_put_dictionary(xpc_object_t event); +static bool operation_get_v2(xpc_object_t event); + +int ckdproxymain(int argc, const char *argv[]); + +#define PROXYXPCSCOPE "xpcproxy" + +static void describeXPCObject(char *prefix, xpc_object_t object) +{ +//#ifndef NDEBUG + // This is useful for debugging. + if (object) + { + char *desc = xpc_copy_description(object); + secdebug(PROXYXPCSCOPE, "%s%s\n", prefix, desc); + free(desc); + } + else + secdebug(PROXYXPCSCOPE, "%s\n", prefix); + +//#endif +} + +static void cloudkeychainproxy_peer_dictionary_handler(const xpc_connection_t peer, xpc_object_t event) +{ + bool result = false; + int err = 0; + + require_action_string(xpc_get_type(event) == XPC_TYPE_DICTIONARY, xit, err = -51, "expected XPC_TYPE_DICTIONARY"); + + const char *operation = xpc_dictionary_get_string(event, kMessageKeyOperation); + require_action(operation, xit, result = false); + + // Check protocol version + uint64_t version = xpc_dictionary_get_uint64(event, kMessageKeyVersion); + secdebug(PROXYXPCSCOPE, "Reply version: %lld\n", version); + require_action(version == kCKDXPCVersion, xit, result = false); + + // Operations + secdebug(PROXYXPCSCOPE, "Handling %s operation", operation); + + + if (operation && !strcmp(operation, kOperationPUTDictionary)) + { + operation_put_dictionary(event); + } + else if (operation && !strcmp(operation, kOperationGETv2)) + { + operation_get_v2(event); + } + else if (operation && !strcmp(operation, kOperationClearStore)) + { + [[UbiqitousKVSProxy sharedKVSProxy] clearStore]; + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + if (replyMessage) // Caller wanted an ACK, so give one + { + xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); + xpc_connection_send_message(peer, replyMessage); + } + } + else if (operation && !strcmp(operation, kOperationRemoveObjectForKey)) + { + const char *keyToRemove = xpc_dictionary_get_string(event, kMessageKeyKey); + [[UbiqitousKVSProxy sharedKVSProxy] removeObjectForKey:[NSString stringWithCString:keyToRemove encoding:NSUTF8StringEncoding]]; + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + if (replyMessage) // Caller wanted an ACK, so give one + { + xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); + xpc_connection_send_message(peer, replyMessage); + } + } + else if (operation && !strcmp(operation, kOperationSynchronize)) + { + [[UbiqitousKVSProxy sharedKVSProxy] requestSynchronization:YES]; + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + if (replyMessage) // Caller wanted an ACK, so give one + { + xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); + xpc_connection_send_message(peer, replyMessage); + } + } + else if (operation && !strcmp(operation, kOperationSynchronizeAndWait)) + { + xpc_object_t xkeysToGetDict = xpc_dictionary_get_value(event, kMessageKeyValue); + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + xpc_object_t xkeys = xpc_dictionary_get_value(xkeysToGetDict, kMessageKeyKeysToGet); + NSArray *keysToGet = (__bridge_transfer NSArray *)(_CFXPCCreateCFObjectFromXPCObject(xkeys)); + secnotice(XPROXYSCOPE, "%s XPC request: %s", kWAIT2MINID, kOperationSynchronizeAndWait); + + [[UbiqitousKVSProxy sharedKVSProxy] waitForSynchronization:keysToGet + handler:^(NSDictionary *values, NSError *err) { + if (replyMessage) // Caller wanted an ACK, so give one + { + secnotice(PROXYXPCSCOPE, "%s Result from [[UbiqitousKVSProxy sharedKVSProxy] waitForSynchronization:]: %@", kWAIT2MINID, err); + xpc_object_t xobject = values ? _CFXPCCreateXPCObjectFromCFObject((__bridge CFTypeRef)(values)) : xpc_null_create(); + xpc_dictionary_set_value(replyMessage, kMessageKeyValue, xobject); + if (err) + { + xpc_object_t xerrobj = SecCreateXPCObjectWithCFError((__bridge CFErrorRef)(err)); + xpc_dictionary_set_value(replyMessage, kMessageKeyError, xerrobj); + } + xpc_connection_send_message(peer, replyMessage); + } + else { + secerror("%s XPC request: %s - No replyMessage: %@", kWAIT2MINID, kOperationSynchronizeAndWait, err); + } + }]; + } + else if (operation && !strcmp(operation, kOperationRegisterKeys)) + { + xpc_object_t xkeysToRegisterDict = xpc_dictionary_get_value(event, kMessageKeyValue); + // describeXPCObject("xkeysToRegister: ", xkeysToRegisterDict); + + // KTR = keysToRegister + xpc_object_t xKTRallkeys = xpc_dictionary_get_value(xkeysToRegisterDict, kMessageAllKeys); + + NSDictionary *KTRallkeys = (__bridge_transfer NSDictionary *)(_CFXPCCreateCFObjectFromXPCObject(xKTRallkeys)); + + [[UbiqitousKVSProxy sharedKVSProxy] registerKeys: KTRallkeys]; + + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); + xpc_connection_send_message(peer, replyMessage); + + secdebug(PROXYXPCSCOPE, "RegisterKeys message sent"); + } + else if (operation && !strcmp(operation, kOperationUILocalNotification)) + { + xpc_object_t xLocalNotificationDict = xpc_dictionary_get_value(event, kMessageKeyValue); + // describeXPCObject("xLocalNotificationDict: ", xLocalNotificationDict); + NSDictionary *localNotificationDict = (__bridge_transfer NSDictionary *)(_CFXPCCreateCFObjectFromXPCObject(xLocalNotificationDict)); + int64_t outFlags = 0; + id object = [[UbiqitousKVSProxy sharedKVSProxy] localNotification:localNotificationDict outFlags:&outFlags]; + secdebug(PROXYXPCSCOPE, "Result from [[UbiqitousKVSProxy sharedKVSProxy] localNotification:]: %@", object); + xpc_object_t xobject = object ? _CFXPCCreateXPCObjectFromCFObject((__bridge CFTypeRef)(object)) : xpc_null_create(); + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + xpc_dictionary_set_int64(xobject, kMessageKeyNotificationFlags, outFlags); + xpc_dictionary_set_value(replyMessage, kMessageKeyValue, xobject); + xpc_connection_send_message(peer, replyMessage); + secdebug(PROXYXPCSCOPE, "localNotification reply sent"); + } + else if (operation && !strcmp(operation, kOperationRequestSyncWithAllPeers)) + { + [[UbiqitousKVSProxy sharedKVSProxy] requestSyncWithAllPeers]; + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + if (replyMessage) // Caller wanted an ACK, so give one + { + xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); + xpc_connection_send_message(peer, replyMessage); + } + secdebug(PROXYXPCSCOPE, "RequestSyncWithAllPeers reply sent"); + } + else if (operation && !strcmp(operation, kOperationRequestEnsurePeerRegistration)) + { + [[UbiqitousKVSProxy sharedKVSProxy] requestEnsurePeerRegistration]; + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + if (replyMessage) // Caller wanted an ACK, so give one + { + xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); + xpc_connection_send_message(peer, replyMessage); + } + secdebug(PROXYXPCSCOPE, "RequestEnsurePeerRegistration reply sent"); + } + else if (operation && !strcmp(operation, kOperationFlush)) + { + [[UbiqitousKVSProxy sharedKVSProxy] doAfterFlush:^{ + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + if (replyMessage) // Caller wanted an ACK, so give one + { + xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); + xpc_connection_send_message(peer, replyMessage); + } + secdebug(PROXYXPCSCOPE, "flush reply sent"); + }]; + } + else + { + char *description = xpc_copy_description(event); + secdebug(PROXYXPCSCOPE, "Unknown op=%s request from pid %d: %s", operation, xpc_connection_get_pid(peer), description); + free(description); + } + result = true; +xit: + if (!result) + describeXPCObject("handle_operation fail: ", event); +} + +void finalize_connection(void *not_used) +{ + secdebug(PROXYXPCSCOPE, "finalize_connection"); + [[UbiqitousKVSProxy sharedKVSProxy] requestSynchronization:YES]; + xpc_transaction_end(); +} + +static bool operation_put_dictionary(xpc_object_t event) +{ + // PUT a set of objects into the KVS store. Return false if error + + describeXPCObject("operation_put_dictionary event: ", event); + xpc_object_t xvalue = xpc_dictionary_get_value(event, kMessageKeyValue); + if (!xvalue) + return false; + + CFTypeRef cfvalue = _CFXPCCreateCFObjectFromXPCObject(xvalue); + if (cfvalue && (CFGetTypeID(cfvalue)==CFDictionaryGetTypeID())) + { + [[UbiqitousKVSProxy sharedKVSProxy] setObjectsFromDictionary:(__bridge NSDictionary *)cfvalue]; + CFReleaseSafe(cfvalue); + return true; + } + else{ + describeXPCObject("operation_put_dictionary unable to convert to CF: ", xvalue); + CFReleaseSafe(cfvalue); + } + return false; +} + +static bool operation_get_v2(xpc_object_t event) +{ + // GET a set of objects from the KVS store. Return false if error + describeXPCObject("operation_get_v2 event: ", event); + xpc_connection_t peer = xpc_dictionary_get_remote_connection(event); + describeXPCObject("operation_get_v2: peer: ", peer); + + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + if (!replyMessage) + { + secdebug(PROXYXPCSCOPE, "can't create replyMessage"); + assert(true); //must have a reply handler + return false; + } + xpc_object_t returnedValues = xpc_dictionary_create(NULL, NULL, 0); + if (!returnedValues) + { + secdebug(PROXYXPCSCOPE, "can't create returnedValues"); + assert(true); // must have a spot for the returned values + return false; + } + + xpc_object_t xvalue = xpc_dictionary_get_value(event, kMessageKeyValue); + if (!xvalue) + { + secdebug(PROXYXPCSCOPE, "missing \"value\" key"); + return false; + } + + xpc_object_t xkeystoget = xpc_dictionary_get_value(xvalue, kMessageKeyKeysToGet); + if (xkeystoget) + { + secdebug(PROXYXPCSCOPE, "got xkeystoget"); + CFTypeRef keystoget = _CFXPCCreateCFObjectFromXPCObject(xkeystoget); + if (!keystoget || (CFGetTypeID(keystoget)!=CFArrayGetTypeID())) // not "getAll", this is an error of some kind + { + secdebug(PROXYXPCSCOPE, "can't convert keystoget or is not an array"); + CFReleaseSafe(keystoget); + return false; + } + + [(__bridge NSArray *)keystoget enumerateObjectsUsingBlock: ^ (id obj, NSUInteger idx, BOOL *stop) + { + NSString *key = (NSString *)obj; + id object = [[UbiqitousKVSProxy sharedKVSProxy] get:key]; + secdebug(PROXYXPCSCOPE, "[UbiqitousKVSProxy sharedKVSProxy] get: key: %@, object: %@", key, object); + xpc_object_t xobject = object ? _CFXPCCreateXPCObjectFromCFObject((__bridge CFTypeRef)object) : xpc_null_create(); + xpc_dictionary_set_value(returnedValues, [key UTF8String], xobject); + describeXPCObject("operation_get_v2: value from kvs: ", xobject); + }]; + } + else // get all values from kvs + { + secdebug(PROXYXPCSCOPE, "get all values from kvs"); + NSDictionary *all = [[UbiqitousKVSProxy sharedKVSProxy] getAll]; + [all enumerateKeysAndObjectsUsingBlock: ^ (id key, id obj, BOOL *stop) + { + xpc_object_t xobject = obj ? _CFXPCCreateXPCObjectFromCFObject((__bridge CFTypeRef)obj) : xpc_null_create(); + xpc_dictionary_set_value(returnedValues, [(NSString *)key UTF8String], xobject); + }]; + } + + xpc_dictionary_set_uint64(replyMessage, kMessageKeyVersion, kCKDXPCVersion); + xpc_dictionary_set_value(replyMessage, kMessageKeyValue, returnedValues); + xpc_connection_send_message(peer, replyMessage); + + return true; +} + +static void initializeProxyObjectWithConnection(const xpc_connection_t connection) +{ + [[UbiqitousKVSProxy sharedKVSProxy] setItemsChangedBlock:^CFArrayRef(CFDictionaryRef values) + { + secdebug(PROXYXPCSCOPE, "UbiqitousKVSProxy called back"); + xpc_object_t xobj = _CFXPCCreateXPCObjectFromCFObject(values); + xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion); + xpc_dictionary_set_string(message, kMessageKeyOperation, kMessageOperationItemChanged); + xpc_dictionary_set_value(message, kMessageKeyValue, xobj?xobj:xpc_null_create()); + xpc_connection_send_message(connection, message); // Send message; don't wait for a reply + return NULL; + }]; +} + +static void cloudkeychainproxy_peer_event_handler(xpc_connection_t peer, xpc_object_t event) +{ + describeXPCObject("peer: ", peer); + xpc_type_t type = xpc_get_type(event); + if (type == XPC_TYPE_ERROR) { + if (event == XPC_ERROR_CONNECTION_INVALID) { + // The client process on the other end of the connection has either + // crashed or cancelled the connection. After receiving this error, + // the connection is in an invalid state, and you do not need to + // call xpc_connection_cancel(). Just tear down any associated state + // here. + } else if (event == XPC_ERROR_TERMINATION_IMMINENT) { + // Handle per-connection termination cleanup. + } + } else { + assert(type == XPC_TYPE_DICTIONARY); + // Handle the message. + // describeXPCObject("dictionary:", event); + dispatch_async(dispatch_get_main_queue(), ^{ + cloudkeychainproxy_peer_dictionary_handler(peer, event); + }); + } +} + +static void cloudkeychainproxy_event_handler(xpc_connection_t peer) +{ + // By defaults, new connections will target the default dispatch + // concurrent queue. + + if (xpc_get_type(peer) != XPC_TYPE_CONNECTION) + { + secdebug(PROXYXPCSCOPE, "expected XPC_TYPE_CONNECTION"); + return; + } + initializeProxyObjectWithConnection(peer); + xpc_connection_set_event_handler(peer, ^(xpc_object_t event) + { + cloudkeychainproxy_peer_event_handler(peer, event); + }); + + // This will tell the connection to begin listening for events. If you + // have some other initialization that must be done asynchronously, then + // you can defer this call until after that initialization is done. + xpc_connection_resume(peer); +} + +static void diagnostics(int argc, const char *argv[]) +{ + @autoreleasepool + { + NSDictionary *all = [[UbiqitousKVSProxy sharedKVSProxy] getAll]; + NSLog(@"All: %@",all); + } +} + +int ckdproxymain(int argc, const char *argv[]) +{ + secdebug(PROXYXPCSCOPE, "Starting CloudKeychainProxy"); + char *wait4debugger = getenv("WAIT4DEBUGGER"); + + if (wait4debugger && !strcasecmp("YES", wait4debugger)) + { + syslog(LOG_ERR, "Waiting for debugger"); + kill(getpid(), SIGTSTP); + } + + if (argc > 1) { + diagnostics(argc, argv); + return 0; + } + + // DISPATCH_TARGET_QUEUE_DEFAULT + xpc_connection_t listener = xpc_connection_create_mach_service(xpcServiceName, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER); + xpc_connection_set_event_handler(listener, ^(xpc_object_t object){ cloudkeychainproxy_event_handler(object); }); + + [UbiqitousKVSProxy sharedKVSProxy]; + + // It looks to me like there is insufficient locking to allow a request to come in on the XPC connection while doing the initial all items. + // Therefore I'm leaving the XPC connection suspended until that has time to process. + xpc_connection_resume(listener); + + @autoreleasepool + { + secdebug(PROXYXPCSCOPE, "Starting mainRunLoop"); + NSRunLoop *runLoop = [NSRunLoop mainRunLoop]; + [runLoop run]; + } + + secdebug(PROXYXPCSCOPE, "Exiting CloudKeychainProxy"); + + return EXIT_FAILURE; +} diff --git a/Security/sec/SOSCircle/CloudKeychainProxy/en.lproj/InfoPlist.strings b/Security/sec/SOSCircle/CloudKeychainProxy/en.lproj/InfoPlist.strings new file mode 100644 index 00000000..477b28ff --- /dev/null +++ b/Security/sec/SOSCircle/CloudKeychainProxy/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/Security/sec/SOSCircle/CloudKeychainProxy/scripts/PhoneTerms2.applescript b/Security/sec/SOSCircle/CloudKeychainProxy/scripts/PhoneTerms2.applescript new file mode 100644 index 00000000..79ecbefa --- /dev/null +++ b/Security/sec/SOSCircle/CloudKeychainProxy/scripts/PhoneTerms2.applescript @@ -0,0 +1,126 @@ +global verticalPos +global needVerticalAdjust +global desiredInitialVerticalOffset + +on makenewTab given theme:themeName + tell application "Terminal" + activate + tell application "System Events" to keystroke "t" using command down + repeat while contents of selected tab of front window starts with linefeed + delay 0.01 + end repeat + set current settings of selected tab of front window to first settings set whose name is themeName + end tell +end makenewTab + +on newPhoneTerm for phoneColor by phonePort + set horizontalOffset to 50 + set height to 180 + set width to 1800 + tell application "Terminal" + activate + if phoneColor is equal to "Red" then + set currentTheme to "Red Sands" + else if phoneColor is equal to "Green" then + set currentTheme to "Grass" + else if phoneColor is equal to "Beige" then + set currentTheme to "Novel" + else if phoneColor is equal to "Black" then + set currentTheme to "Pro" + else if phoneColor is equal to "Cyan" then + set currentTheme to "Cyan" + else if phoneColor is equal to "Orange" then + set currentTheme to "Orange" + else if phoneColor is equal to "Beige" then + set currentTheme to "Novel" + else + set currentTheme to "Ocean" + end if + + -- make a new window with the execution of a trivial command + do script "clear" + + -- load up the window id of the window we just created + -- set window_id to id of first window whose frontmost is true + set targetWindow to front window + -- Put it on the right hand screen first + set position of targetWindow to {horizontalOffset, 0} + set position of targetWindow to {horizontalOffset, verticalPos} + set size of targetWindow to {width, height} + set position of targetWindow to {horizontalOffset, verticalPos} + set pos to position of targetWindow + if needVerticalAdjust and ((item 2 of pos) is not equal to verticalPos) then + set needVerticalAdjust to false + set verticalPos to (item 2 of pos) + desiredInitialVerticalOffset + set position of targetWindow to {horizontalOffset, verticalPos} + end if + set verticalPos to verticalPos + height + 15 + + set current settings of selected tab of targetWindow to first settings set whose name is currentTheme + + + -- make tabs 2, 3, 4, 5 + repeat with i from 1 to 4 + makenewTab of me given theme:currentTheme + end repeat + + -- for each of the five tabs we've now made + repeat with i from 1 to 5 + + -- build the command, then execute it + if i is less than 5 then + set myuser to "root" + else + set myuser to "mobile" + end if + if (i = 1) then + set shcmd to "syslog -w" + else if (i = 2) then + set shcmd to "ls -1t /var/mobile/Library/Logs/CrashReporter/DiagnosticLogs/security.log.\\*Z \\| head -1 \\| xargs tail -100000F" + else if (i = 3) then + set shcmd to "ls -1t /var/mobile/Library/Logs/CrashReporter/DiagnosticLogs/security.log.\\*Z \\| head -1 \\| xargs tail -100000F \\| egrep \"'(event|keytrace|peer|coder|engine){}|'\"" + else if (i = 4) then + set shcmd to "security item -q class=inet,sync=1 \\| grep acct \\| tail -3" + else if (i = 5) then + set shcmd to "" + -- for c in inet genp keys; do for t in "" ,tomb=1; do security item class=$c,sync=1$t; done; done | grep agrp | wc -l + else + set shcmd to "" + end if + set custom title of tab i of targetWindow to phoneColor & " " & myuser & " " & phonePort + set cmd to "~/bin/sshauser " & "--retry " & phonePort & " " & myuser & " " & shcmd + do script cmd in tab i of targetWindow + + end repeat + + end tell + + +end newPhoneTerm + +-- +-- main code +-- + +set desiredInitialVerticalOffset to 10 +set verticalPos to -10000 +set needVerticalAdjust to true + +newPhoneTerm of me for "Red" by 11022 +newPhoneTerm of me for "Blue" by 12022 +-- newPhoneTerm of me for "Green" by 12022 +-- newPhoneTerm of me for "Cyan" by 13022 +-- newPhoneTerm of me for "Orange" by 15022 +-- newPhoneTerm of me for "Beige" by 16022 +-- newPhoneTerm of me for "Black" by 21022 + +-- # Config file for ssh +-- #UDID 79003b34516ba80b620e3d947e7da96e033bed48 johnsrediphone 10022 +-- #UDID 96476595e5d0ef7496e8ff852aedf4725647960b johnsblueiphone 11022 +-- #UDID b674745cb6d2a1616a065cddae7207f91980e95d johnsgreentouch 12022 +-- #UDID a489e67286bc2a509ef74cda67fc6696e2e1a192 johnscyanmini 13022 +-- #UDID df86edbd280fd986f1cfae1517e65acbac7188cd johnsyellowmini 14022 +-- #UDID 16d4c2e0a63083ec16e3f2ed4f21755b12deb900 johnsorangemini 15022 +-- #UDID 8b2aa30e1ead1c7c303c363216bfe44f1cb21ce6 johnsbeigeipad 16022 +-- #UDID f80b8fbf11ca6b8d692f10e9ea29dea1e57fcbdf johnswhiteipad 17022 + diff --git a/sec/SOSCircle/CloudKeychainProxy/scripts/PhoneTerms2.scpt b/Security/sec/SOSCircle/CloudKeychainProxy/scripts/PhoneTerms2.scpt similarity index 100% rename from sec/SOSCircle/CloudKeychainProxy/scripts/PhoneTerms2.scpt rename to Security/sec/SOSCircle/CloudKeychainProxy/scripts/PhoneTerms2.scpt diff --git a/sec/SOSCircle/CloudKeychainProxy/scripts/install_on_devices b/Security/sec/SOSCircle/CloudKeychainProxy/scripts/install_on_devices similarity index 75% rename from sec/SOSCircle/CloudKeychainProxy/scripts/install_on_devices rename to Security/sec/SOSCircle/CloudKeychainProxy/scripts/install_on_devices index 53c710af..dfab4c7e 100755 --- a/sec/SOSCircle/CloudKeychainProxy/scripts/install_on_devices +++ b/Security/sec/SOSCircle/CloudKeychainProxy/scripts/install_on_devices @@ -7,6 +7,7 @@ sshopts=(-o CheckHostIP=no -o StrictHostKeyChecking=no -o NoHostAuthenticationFo locations=(`mobdev list | awk '/UDID/ { gsub(/^(.*location ID = )+|(,.*)+$/, ""); print}'`) +mysrcdir=`pwd` port_offset=20000 symdir="/var/mobile/secsyms" @@ -26,6 +27,10 @@ do ssh $sshopts -p $sshport root@localhost << END /bin/hostname /sbin/mount -uw / +mkdir -p /var/mobile/syms +mkdir -p /var/mobile/srcs +rm -rf /var/mobile/syms/* +rm -rf /var/mobile/srcs/* /usr/local/bin/darwinup install "/var/mobile/`basename $roots`" | grep -v '^ /' /usr/local/bin/darwinup uninstall superseded > /dev/null 2>&1 || true touch /System/Library/Caches/com.apple.xpcd/xpcd_cache.dylib @@ -33,7 +38,13 @@ touch /System/Library/Caches/com.apple.xpcd/xpcd_cache.dylib /bin/launchctl stop com.apple.securityd /bin/launchctl stop com.apple.security.cloudkeychainproxy3 /bin/launchctl stop com.apple.security.CircleJoinRequest +tar -xzvf "/var/mobile/`basename $syms`" -C /var/mobile/syms >/dev/null +tar -xzvf "/var/mobile/`basename $srcs`" -C /var/mobile/srcs >/dev/null END kill -HUP %% done + +echo "in lldb: settings set target.source-map ""$mysrcdir"" /var/mobile/srcs/" +echo "in lldb: add-dsym /var/mobile/syms/securityd.dSYM" + diff --git a/Security/sec/SOSCircle/CloudKeychainProxy/scripts/kcstatus b/Security/sec/SOSCircle/CloudKeychainProxy/scripts/kcstatus new file mode 100644 index 00000000..475e6e2e --- /dev/null +++ b/Security/sec/SOSCircle/CloudKeychainProxy/scripts/kcstatus @@ -0,0 +1,6 @@ +#/bin/sh + +security item -q class=inet,sync=1 | grep acct | tail -3 +security item -q class=genp,sync=1 | grep acct | tail -3 +security item -q class=genp,sync=1 2>/dev/null | grep agrp > tmpkccount && security item -q class=inet,sync=1 2>/dev/null | grep agrp >> tmpkccount && echo "Syncable items: "`wc -l tmpkccount | awk '{print $1}'` + diff --git a/Security/sec/SOSCircle/CloudKeychainProxy/scripts/sosbuildroot b/Security/sec/SOSCircle/CloudKeychainProxy/scripts/sosbuildroot new file mode 100755 index 00000000..9ee0d614 --- /dev/null +++ b/Security/sec/SOSCircle/CloudKeychainProxy/scripts/sosbuildroot @@ -0,0 +1 @@ +#!/bin/zsh -e diff --git a/sec/SOSCircle/CloudKeychainProxy/scripts/soscopy b/Security/sec/SOSCircle/CloudKeychainProxy/scripts/soscopy similarity index 100% rename from sec/SOSCircle/CloudKeychainProxy/scripts/soscopy rename to Security/sec/SOSCircle/CloudKeychainProxy/scripts/soscopy diff --git a/sec/SOSCircle/CloudKeychainProxy/scripts/soscopysshkeys b/Security/sec/SOSCircle/CloudKeychainProxy/scripts/soscopysshkeys similarity index 100% rename from sec/SOSCircle/CloudKeychainProxy/scripts/soscopysshkeys rename to Security/sec/SOSCircle/CloudKeychainProxy/scripts/soscopysshkeys diff --git a/sec/SOSCircle/CloudKeychainProxy/scripts/sosinstallroot b/Security/sec/SOSCircle/CloudKeychainProxy/scripts/sosinstallroot similarity index 100% rename from sec/SOSCircle/CloudKeychainProxy/scripts/sosinstallroot rename to Security/sec/SOSCircle/CloudKeychainProxy/scripts/sosinstallroot diff --git a/sec/SOSCircle/CloudKeychainProxy/scripts/sosreset b/Security/sec/SOSCircle/CloudKeychainProxy/scripts/sosreset similarity index 100% rename from sec/SOSCircle/CloudKeychainProxy/scripts/sosreset rename to Security/sec/SOSCircle/CloudKeychainProxy/scripts/sosreset diff --git a/Security/sec/SOSCircle/CloudKeychainProxy/scripts/tweak b/Security/sec/SOSCircle/CloudKeychainProxy/scripts/tweak new file mode 100755 index 00000000..bdd6cb5d --- /dev/null +++ b/Security/sec/SOSCircle/CloudKeychainProxy/scripts/tweak @@ -0,0 +1,131 @@ +#!/bin/sh + +generateCreditCards=0 +generateAutofill=0 +helpme=0 +generateConflict=0 +clearAllItems=0 + +usage() { + echo 'Usage: Generate random credit card entries (-c) or autofill (-a). Both can be specified. x will generate a conflict item, K to clear all' + exit 2 +} + +args=`getopt cahxK $*` +test $? -eq 0 || usage +set -- $args +for i +do + case "$i" + in + -c) + generateCreditCards=1; + shift;; + -a) + generateAutofill=1; + shift;; + -x) + generateConflict=1; + shift;; + -K) + clearAllItems=1; + shift;; + -h) + helpme=1 + shift; break;; + --) + shift; break;; + esac +done + +test "$helpme" -ne 0 && usage + +if [ $generateCreditCards -eq 0 -a $generateAutofill -eq 0 -a $generateConflict -eq 0 ] +then + generateCreditCards=1 +fi + +# end of option processing + +# Set expiration date +exp=`date "+%Y-%m-%dT%H:%M:%SZ"` + +# Make up a credit card number +amexcc=`echo $((RANDOM%372711122299888+372711122299111))` +visacc=`echo $((RANDOM%4888123456789888+4888123456789111))` +mccc=`echo $((RANDOM%5523123456789888+5523123456789111))` +cclist=($amexcc $visacc $mccc) + +idx=`echo $((RANDOM%3+0))` + +cctypes=("American Express" "Visa" "Master Card") +ccnumber=${cclist[idx]} + +ccholders=("Sam" "Ella" "Alice" "Bob" "Mallory" "Eve") +cardholderName=${ccholders[$RANDOM % ${#ccholders[@]} ]} +cardholderName=`hostname | head -c 18` +cardholderShortName=`hostname | head -c 8` + +cardnamestring="$cardholderShortName""’s ""${cctypes[idx]}" + +cat < ccdata.plist + + + + + CardNameUIString + $cardnamestring + CardNumber + $ccnumber + CardholderName + $cardholderName + ExpirationDate + $exp + + +EOF + +plutil -convert binary1 -o ccdata.bin ccdata.plist + +# debug output +cat ccdata.plist + +uid=`uuidgen` + +# Create a random credit card item in the keychain + +if [ $generateCreditCards -ne 0 ] +then + security item -v -a -f ccdata.bin class=genp,sync=1,acct="$uid",agrp="com.apple.safari.credit-cards",icmt="This keychain item is used by Safari to automatically fill credit card information in web forms.",type=7477,pdmn=ak,svce="SafariCreditCardEntries",labl="Safari Credit Card Entry: $cardnamestring" + if [ "$?" -ne "0" ]; then + echo "credit card item add failed; is the device locked? " + fi +fi + +if [ $generateAutofill -ne 0 ] +then + `echo $((RANDOM%9999)) > tweakpw` + email=${ccholders[$RANDOM % ${#ccholders[@]} ]} + security item -v -a -f tweakpw class=inet,acct="$email@gmail.com",agrp="com.apple.cfnetwork",atyp=form,desc="Web form password",labl="accounts.google.com ($email@gmail.com)",pdmn=ak,port=0,ptcl=htps,srvr=accounts.google.com,type=7477,sync=1 + if [ "$?" -ne "0" ]; then + echo "autofill item add failed; is the device locked? " + fi +fi + +if [ $generateConflict -ne 0 ] +then + `echo "1234" > tweakpw` + email="conflict" + security item -v -a -f tweakpw class=inet,acct="$email@gmail.com",agrp="com.apple.cfnetwork",atyp=form,desc="Web form password",labl="accounts.google.com ($email@gmail.com)",pdmn=ak,port=0,ptcl=htps,srvr=accounts.google.com,type=7477,sync=1 + if [ "$?" -ne "0" ]; then + echo "conflict item add failed; is the device locked? " + fi +fi + +if [ $clearAllItems -ne 0 ] +then + echo "Deleting all tweak inet and genp items" + security item -D class=genp,type=7477,sync=1,pdmn=ak,svce="SafariCreditCardEntries" + security item -D class=inet,type=7477,ptcl=htps,srvr=accounts.google.com,sync=1 +fi + diff --git a/Security/sec/SOSCircle/Empty.c b/Security/sec/SOSCircle/Empty.c new file mode 100644 index 00000000..e69de29b diff --git a/Security/sec/SOSCircle/Regressions/CKDKeyValueStore.h b/Security/sec/SOSCircle/Regressions/CKDKeyValueStore.h new file mode 100644 index 00000000..a6bdcd09 --- /dev/null +++ b/Security/sec/SOSCircle/Regressions/CKDKeyValueStore.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#import +//#import "CKDKVSProxy.h" +#import "SOSCloudKeychainConstants.h" +#import "SOSCloudKeychainClient.h" + +extern CFStringRef kCKDKVSRemoteStoreID; +extern CFStringRef kCKDAWSRemoteStoreID; + +//--- protocol --- + +@protocol CKDKVSDelegate + +@required + +- (id)objectForKey:(NSString *)aKey; +- (void)setObject:(id)anObject forKey:(NSString *)aKey; +- (void)removeObjectForKey:(NSString *)aKey; + +- (NSDictionary *)dictionaryRepresentation; + +- (BOOL)synchronize; + +@optional +- (BOOL)isLocalKVS; +// DEBUG +- (void)setDictionaryRepresentation:(NSMutableDictionary *)initialValue; +- (void)clearPersistentStores; + +@end + +//--- interface --- + +@interface CKDKeyValueStore : NSObject +{ + BOOL localKVS; + BOOL persistStore; + CloudItemsChangedBlock itemsChangedCallback; +} + +@property (retain) id delegate; +@property (retain) NSString *identifier; +@property (retain) NSString *path; + +- (BOOL)synchronize; ++ (CKDKeyValueStore *)defaultStore:(NSString *)identifier itemsChangedBlock:(CloudItemsChangedBlock)itemsChangedBlock; +- (id)initWithIdentifier:(NSString *)xidentifier itemsChangedBlock:(CloudItemsChangedBlock)itemsChangedBlock; + ++ (CFStringRef)remoteStoreID; + +- (id)initWithItemsChangedBlock:(CloudItemsChangedBlock)itemsChangedBlock; +- (void)cloudChanged:(NSNotification*)notification; + +@end + +@interface CKDKeyValueStoreCollection : NSObject +{ + dispatch_queue_t syncrequestqueue; + NSMutableDictionary *store; +} +@property (retain) NSMutableDictionary *collection; + ++ (id)sharedInstance; ++ (id )defaultStore:(NSString *)identifier itemsChangedBlock:(CloudItemsChangedBlock)itemsChangedBlock; ++ (void)enqueueWrite:(id)anObject forKey:(NSString *)aKey from:(NSString *)identifier; ++ (id)enqueueWithReply:(NSString *)aKey; ++ (BOOL)enqueueSyncWithReply; ++ (void)postItemChangedNotification:(NSString *)keyThatChanged from:(NSString *)identifier; ++ (void)postItemsChangedNotification:(NSArray *)keysThatChanged from:(NSString *)identifier; + +@end diff --git a/sec/SOSCircle/Regressions/CKDKeyValueStore.m b/Security/sec/SOSCircle/Regressions/CKDKeyValueStore.m similarity index 99% rename from sec/SOSCircle/Regressions/CKDKeyValueStore.m rename to Security/sec/SOSCircle/Regressions/CKDKeyValueStore.m index 6839443d..cf4f24a5 100644 --- a/sec/SOSCircle/Regressions/CKDKeyValueStore.m +++ b/Security/sec/SOSCircle/Regressions/CKDKeyValueStore.m @@ -1,15 +1,15 @@ /* - * Copyright (c) 2012-2013 Apple, Inc. All Rights Reserved. + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/sec/SOSCircle/Regressions/SOSCircle_regressions.h b/Security/sec/SOSCircle/Regressions/SOSCircle_regressions.h similarity index 76% rename from sec/SOSCircle/Regressions/SOSCircle_regressions.h rename to Security/sec/SOSCircle/Regressions/SOSCircle_regressions.h index e96e7ae9..adc87119 100644 --- a/sec/SOSCircle/Regressions/SOSCircle_regressions.h +++ b/Security/sec/SOSCircle/Regressions/SOSCircle_regressions.h @@ -6,27 +6,24 @@ ONE_TEST(sc_20_keynames) ONE_TEST(sc_30_peerinfo) +ONE_TEST(sc_31_peerinfo) ONE_TEST(sc_40_circle) OFF_ONE_TEST(sc_41_cloudcircle) // This is destructive to the cloud state +ONE_TEST(sc_42_circlegencount) +ONE_TEST(sc_45_digestvector) +OFF_ONE_TEST(sc_50_message) OFF_ONE_TEST(sc_51_persistentEC) - -#ifdef NO_SERVER -ONE_TEST(sc_60_peer) -ONE_TEST(sc_70_engine) -ONE_TEST(sc_75_circle_engine) -#else OFF_ONE_TEST(sc_60_peer) +#ifdef NO_SERVER OFF_ONE_TEST(sc_70_engine) OFF_ONE_TEST(sc_75_circle_engine) +#else +OFF_ONE_TEST(sc_70_engine) +ONE_TEST(sc_75_circle_engine) #endif OFF_ONE_TEST(sc_90_ckdclient) OFF_ONE_TEST(sc_95_ckd2client) -OFF_ONE_TEST(sc_100_devicecircle) -OFF_ONE_TEST(sc_101_accountsync) -OFF_ONE_TEST(sc_102_cfusernotification) OFF_ONE_TEST(sc_103_syncupdate) -OFF_ONE_TEST(sc_120_cloudcircle) ONE_TEST(sc_130_resignationticket) - diff --git a/sec/SOSCircle/Regressions/SOSRegressionUtilities.c b/Security/sec/SOSCircle/Regressions/SOSRegressionUtilities.c similarity index 89% rename from sec/SOSCircle/Regressions/SOSRegressionUtilities.c rename to Security/sec/SOSCircle/Regressions/SOSRegressionUtilities.c index 6c7729d9..fff8b343 100644 --- a/sec/SOSCircle/Regressions/SOSRegressionUtilities.c +++ b/Security/sec/SOSCircle/Regressions/SOSRegressionUtilities.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -122,13 +122,15 @@ void registerForKVSNotifications(const void *observer, CFStringRef name, CFNotif CFNotificationCenterAddObserver(center, observer, callBack, name, NULL, suspensionBehavior); } -void testPutObjectInCloudAndSync(CFStringRef key, CFTypeRef object, CFErrorRef *error, dispatch_group_t dgroup, dispatch_queue_t processQueue) +bool testPutObjectInCloudAndSync(CFStringRef key, CFTypeRef object, CFErrorRef *error, dispatch_group_t dgroup, dispatch_queue_t processQueue) { - testPutObjectInCloud(key, object, error, dgroup, processQueue); + bool result = testPutObjectInCloud(key, object, error, dgroup, processQueue); testSynchronize(processQueue, dgroup); + + return result; } -void testPutObjectInCloud(CFStringRef key, CFTypeRef object, CFErrorRef *error, dispatch_group_t dgroup, dispatch_queue_t processQueue) +bool testPutObjectInCloud(CFStringRef key, CFTypeRef object, CFErrorRef *error, dispatch_group_t dgroup, dispatch_queue_t processQueue) { secerror("testPutObjectInCloud: key: %@, %@", key, object); CFDictionaryRef objects = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, key, object, NULL); @@ -146,7 +148,9 @@ void testPutObjectInCloud(CFStringRef key, CFTypeRef object, CFErrorRef *error, dispatch_group_leave(dgroup); }); CFRelease(objects); - } + } + + return true; } CFTypeRef testGetObjectFromCloud(CFStringRef key, dispatch_queue_t processQueue, dispatch_group_t dgroup) @@ -234,41 +238,6 @@ CFTypeRef testGetObjectsFromCloud(CFArrayRef keysToGet, dispatch_queue_t process return object; } -bool testRegisterKeys(CFArrayRef keysToRegister, dispatch_queue_t processQueue, dispatch_group_t dgroup) -{ - __block bool result = false; - - dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0); - dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds); - - dispatch_group_enter(dgroup); - SOSCloudKeychainRegisterKeysAndGet(keysToRegister, processQueue, - ^ (CFDictionaryRef returnedValues, CFErrorRef error) - { - secerror("testRegisterKeys returned: %@", returnedValues); - if (error) - { - secerror("testRegisterKeys returned: %@", error); - CFRelease(error); - } - dispatch_group_leave(dgroup); - result = true; - dispatch_semaphore_signal(waitSemaphore); - }, - ^ (CFDictionaryRef returnedValues) - { - secerror("testRegisterKeys returned: %@", returnedValues); - dispatch_group_leave(dgroup); - result = true; - dispatch_semaphore_signal(waitSemaphore); - }); - - dispatch_semaphore_wait(waitSemaphore, finishTime); - dispatch_release(waitSemaphore); -// printTimeNow("finished registerKeysForKVS"); - return result; -} - bool testSynchronize(dispatch_queue_t processQueue, dispatch_group_t dgroup) { __block bool result = false; @@ -405,13 +374,12 @@ static int getHardwareAddress(const char *interfaceName, size_t maxLenAllowed, s struct if_msghdr *ifm; struct sockaddr_dl *sdl; char *buf; - int result; + int result = -1; size_t buffSize; int mib[6] = {CTL_NET, AF_ROUTE, 0, AF_INET, NET_RT_IFLIST, 0 }; buf = 0; *outActualLength = 0; - result = -1; // see how much space is needed require_noerr(result = sysctl(mib, 6, NULL, &buffSize, NULL, 0), xit); diff --git a/sec/SOSCircle/Regressions/SOSRegressionUtilities.h b/Security/sec/SOSCircle/Regressions/SOSRegressionUtilities.h similarity index 89% rename from sec/SOSCircle/Regressions/SOSRegressionUtilities.h rename to Security/sec/SOSCircle/Regressions/SOSRegressionUtilities.h index 10875944..645ecc37 100644 --- a/sec/SOSCircle/Regressions/SOSRegressionUtilities.h +++ b/Security/sec/SOSCircle/Regressions/SOSRegressionUtilities.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -45,14 +45,13 @@ bool XPCServiceInstalled(void); void registerForKVSNotifications(const void *observer, CFStringRef name, CFNotificationCallback callBack); void unregisterFromKVSNotifications(const void *observer); -void testPutObjectInCloudAndSync(CFStringRef key, CFTypeRef object, CFErrorRef *error, dispatch_group_t dgroup, dispatch_queue_t processQueue); -void testPutObjectInCloud(CFStringRef key, CFTypeRef object, CFErrorRef *error, dispatch_group_t dgroup, dispatch_queue_t processQueue); +bool testPutObjectInCloudAndSync(CFStringRef key, CFTypeRef object, CFErrorRef *error, dispatch_group_t dgroup, dispatch_queue_t processQueue); +bool testPutObjectInCloud(CFStringRef key, CFTypeRef object, CFErrorRef *error, dispatch_group_t dgroup, dispatch_queue_t processQueue); CFTypeRef testGetObjectFromCloud(CFStringRef key, dispatch_queue_t processQueue, dispatch_group_t dgroup); CFTypeRef testGetObjectsFromCloud(CFArrayRef keys, dispatch_queue_t processQueue, dispatch_group_t dgroup); bool testSynchronize(dispatch_queue_t processQueue, dispatch_group_t dgroup); -bool testRegisterKeys(CFArrayRef keysToRegister, dispatch_queue_t processQueue, dispatch_group_t dgroup); bool testClearAll(dispatch_queue_t processQueue, dispatch_group_t dgroup); // diff --git a/Security/sec/SOSCircle/Regressions/SOSTestDataSource.c b/Security/sec/SOSCircle/Regressions/SOSTestDataSource.c new file mode 100644 index 00000000..1fa5289e --- /dev/null +++ b/Security/sec/SOSCircle/Regressions/SOSTestDataSource.c @@ -0,0 +1,507 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include "SOSTestDataSource.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +CFStringRef sSOSDataSourceErrorDomain = CFSTR("com.apple.datasource"); + +typedef struct SOSTestDataSource *SOSTestDataSourceRef; + +struct SOSTestDataSource { + struct SOSDataSource ds; + unsigned gm_count; + unsigned cm_count; + unsigned co_count; + CFMutableDictionaryRef d2database; + CFMutableDictionaryRef p2database; + CFMutableDictionaryRef statedb; + uint8_t manifest_digest[SOSDigestSize]; + bool clean; + + struct SOSDigestVector removals; + struct SOSDigestVector additions; + SOSDataSourceNotifyBlock notifyBlock; +}; + +typedef struct SOSTestDataSourceFactory *SOSTestDataSourceFactoryRef; + +struct SOSTestDataSourceFactory { + struct SOSDataSourceFactory dsf; + CFMutableDictionaryRef data_sources; +}; + + +/* DataSource protocol. */ +static SOSManifestRef copy_manifest(SOSDataSourceRef data_source, CFErrorRef *error) { + struct SOSTestDataSource *ds = (struct SOSTestDataSource *)data_source; + ds->cm_count++; + __block struct SOSDigestVector dv = SOSDigestVectorInit; + CFDictionaryForEach(ds->d2database, ^(const void *key, const void *value) { + SOSDigestVectorAppend(&dv, CFDataGetBytePtr((CFDataRef)key)); + }); + SOSDigestVectorSort(&dv); + SOSManifestRef manifest = SOSManifestCreateWithDigestVector(&dv, error); + SOSDigestVectorFree(&dv); + ccdigest(ccsha1_di(), SOSManifestGetSize(manifest), SOSManifestGetBytePtr(manifest), ds->manifest_digest); + ds->clean = true; + + return manifest; +} + +static bool foreach_object(SOSDataSourceRef data_source, SOSManifestRef manifest, CFErrorRef *error, void (^handle_object)(CFDataRef key, SOSObjectRef object, bool *stop)) { + struct SOSTestDataSource *ds = (struct SOSTestDataSource *)data_source; + ds->co_count++; + __block bool result = true; + SOSManifestForEach(manifest, ^(CFDataRef key, bool *stop) { + handle_object(key, (SOSObjectRef)CFDictionaryGetValue(ds->d2database, key), stop); + }); + return result; +} + +static bool dispose(SOSDataSourceRef data_source, CFErrorRef *error) { + struct SOSTestDataSource *ds = (struct SOSTestDataSource *)data_source; + CFReleaseSafe(ds->d2database); + CFReleaseSafe(ds->p2database); + CFReleaseSafe(ds->statedb); + free(ds); + return true; +} + +static SOSObjectRef createWithPropertyList(CFDictionaryRef plist, CFErrorRef *error) { + return (SOSObjectRef)CFDictionaryCreateCopy(kCFAllocatorDefault, plist); +} + +static CFDataRef SOSObjectCopyDER(SOSObjectRef object, CFErrorRef *error) { + CFDictionaryRef dict = (CFDictionaryRef)object; + size_t size = der_sizeof_plist(dict, error); + CFMutableDataRef data = CFDataCreateMutable(0, size); + if (data) { + CFDataSetLength(data, size); + uint8_t *der = (uint8_t *)CFDataGetMutableBytePtr(data); + uint8_t *der_end = der + size; + der_end = der_encode_plist(dict, error, der, der_end); + assert(der_end == der); + (void)der_end; + } else if (error && *error == NULL) { + *error = CFErrorCreate(0, sSOSDataSourceErrorDomain, kSOSDataSourceObjectMallocFailed, NULL); + } + return data; +} + +static CFDataRef ccdigest_copy_data(const struct ccdigest_info *di, size_t len, + const void *data, CFErrorRef *error) { + CFMutableDataRef digest = CFDataCreateMutable(0, di->output_size); + if (digest) { + CFDataSetLength(digest, di->output_size); + ccdigest(di, len, data, CFDataGetMutableBytePtr(digest)); + } else if (error && *error == NULL) { + *error = CFErrorCreate(0, sSOSDataSourceErrorDomain, kSOSDataSourceObjectMallocFailed, NULL); + } + return digest; +} + +static CFDataRef copyDigest(SOSObjectRef object, CFErrorRef *error) { + CFMutableDictionaryRef ocopy = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, (CFDictionaryRef)object); + CFDictionaryRemoveValue(ocopy, kSecClass); + CFDataRef der = SOSObjectCopyDER((SOSObjectRef)ocopy, error); + CFRelease(ocopy); + CFDataRef digest = NULL; + if (der) { + digest = ccdigest_copy_data(ccsha1_di(), CFDataGetLength(der), CFDataGetBytePtr(der), error); + CFRelease(der); + } + return digest; +} + +static CFDataRef copyPrimaryKey(SOSObjectRef object, CFErrorRef *error) { + CFMutableDictionaryRef ocopy = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFTypeRef pkNames[] = { + CFSTR("acct"), + CFSTR("agrp"), + CFSTR("svce"), + CFSTR("sync"), + CFSTR("sdmn"), + CFSTR("srvr"), + CFSTR("ptcl"), + CFSTR("atyp"), + CFSTR("port"), + CFSTR("path"), + CFSTR("ctyp"), + CFSTR("issr"), + CFSTR("slnr"), + CFSTR("kcls"), + CFSTR("klbl"), + CFSTR("atag"), + CFSTR("crtr"), + CFSTR("type"), + CFSTR("bsiz"), + CFSTR("esiz"), + CFSTR("sdat"), + CFSTR("edat"), + }; + CFSetRef pkAttrs = CFSetCreate(kCFAllocatorDefault, pkNames, array_size(pkNames), &kCFTypeSetCallBacks); + CFDictionaryForEach((CFDictionaryRef)object, ^(const void *key, const void *value) { + if (CFSetContainsValue(pkAttrs, key)) + CFDictionaryAddValue(ocopy, key, value); + }); + CFRelease(pkAttrs); + CFDataRef der = SOSObjectCopyDER((SOSObjectRef)ocopy, error); + CFRelease(ocopy); + CFDataRef digest = NULL; + if (der) { + digest = ccdigest_copy_data(ccsha1_di(), CFDataGetLength(der), CFDataGetBytePtr(der), error); + CFRelease(der); + } + return digest; +} + +static CFDictionaryRef copyPropertyList(SOSObjectRef object, CFErrorRef *error) { + return (CFDictionaryRef) CFRetain(object); +} + +// Return the newest object +static SOSObjectRef copyMergedObject(SOSObjectRef object1, SOSObjectRef object2, CFErrorRef *error) { + CFDictionaryRef dict1 = (CFDictionaryRef)object1; + CFDictionaryRef dict2 = (CFDictionaryRef)object2; + SOSObjectRef result = NULL; + CFDateRef m1, m2; + m1 = CFDictionaryGetValue(dict1, kSecAttrModificationDate); + m2 = CFDictionaryGetValue(dict2, kSecAttrModificationDate); + switch (CFDateCompare(m1, m2, NULL)) { + case kCFCompareGreaterThan: + result = (SOSObjectRef)dict1; + break; + case kCFCompareLessThan: + result = (SOSObjectRef)dict2; + break; + case kCFCompareEqualTo: + { + // Return the item with the smallest digest. + CFDataRef digest1 = copyDigest(object1, error); + CFDataRef digest2 = copyDigest(object2, error); + if (digest1 && digest2) switch (CFDataCompare(digest1, digest2)) { + case kCFCompareGreaterThan: + case kCFCompareEqualTo: + result = (SOSObjectRef)dict2; + break; + case kCFCompareLessThan: + result = (SOSObjectRef)dict1; + break; + } + CFReleaseSafe(digest2); + CFReleaseSafe(digest1); + break; + } + } + CFRetainSafe(result); + return result; +} + +static SOSMergeResult mergeObject(SOSTransactionRef txn, SOSObjectRef object, SOSObjectRef *createdObject, CFErrorRef *error) { + SOSTestDataSourceRef ds = (SOSTestDataSourceRef)txn; + SOSMergeResult mr = kSOSMergeFailure; + CFDataRef pk = copyPrimaryKey(object, error); + if (!pk) return mr; + SOSObjectRef myObject = (SOSObjectRef)CFDictionaryGetValue(ds->p2database, pk); + if (myObject) { + SOSObjectRef merged = copyMergedObject(object, myObject, error); + if (CFEqualSafe(merged, myObject)) { + mr = kSOSMergeLocalObject; + } else if (CFEqualSafe(merged, object)) { + mr = kSOSMergePeersObject; + } else { + if (createdObject) { + *createdObject = merged; + merged = NULL; + } + mr = kSOSMergeCreatedObject; + } + if (mr != kSOSMergeLocalObject) { + CFDataRef myKey = copyDigest(myObject, error); + CFDictionaryRemoveValue(ds->d2database, myKey); + SOSDigestVectorAppend(&ds->removals, CFDataGetBytePtr(myKey)); + CFReleaseSafe(myKey); + CFDataRef key = copyDigest(merged, error); + CFDictionarySetValue(ds->d2database, key, merged); + SOSDigestVectorAppend(&ds->additions, CFDataGetBytePtr(key)); + CFReleaseSafe(key); + CFDictionarySetValue(ds->p2database, pk, merged); + } + CFReleaseSafe(merged); + } else { + SOSTestDataSourceAddObject((SOSDataSourceRef)ds, object, error); + mr = kSOSMergePeersObject; + } + CFReleaseSafe(pk); + return mr; +} + +static CFStringRef dsGetName(SOSDataSourceRef ds) { + return CFSTR("The sky is made of butterflies"); +} + +static void dsSetNotifyPhaseBlock(SOSDataSourceRef ds, SOSDataSourceNotifyBlock notifyBlock) { + ((SOSTestDataSourceRef)ds)->notifyBlock = Block_copy(notifyBlock); +} + +static CFDataRef dsCopyStateWithKey(SOSDataSourceRef ds, CFStringRef key, CFStringRef pdmn, CFErrorRef *error) { + SOSTestDataSourceRef tds = (SOSTestDataSourceRef)ds; + CFStringRef dbkey = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@-%@"), pdmn, key); + CFDataRef state = CFDictionaryGetValue(tds->statedb, dbkey); + CFReleaseSafe(dbkey); + return CFRetainSafe(state); +} + +static bool dsWith(SOSDataSourceRef ds, CFErrorRef *error, SOSDataSourceTransactionSource source, void(^transaction)(SOSTransactionRef txn, bool *commit)) { + SOSTestDataSourceRef tds = (SOSTestDataSourceRef)ds; + bool commit = true; + transaction((SOSTransactionRef)ds, &commit); + if (commit && ((SOSTestDataSourceRef)ds)->notifyBlock && (tds->removals.count || tds->additions.count)) { + ((SOSTestDataSourceRef)ds)->notifyBlock(ds, (SOSTransactionRef)ds, kSOSDataSourceTransactionWillCommit, source, &tds->removals, &tds->additions); + SOSDigestVectorFree(&tds->removals); + SOSDigestVectorFree(&tds->additions); + } + return true; +} + +static bool dsSetStateWithKey(SOSDataSourceRef ds, SOSTransactionRef txn, CFStringRef pdmn, CFStringRef key, CFDataRef state, CFErrorRef *error) { + SOSTestDataSourceRef tds = (SOSTestDataSourceRef)ds; + CFStringRef dbkey = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@-%@"), pdmn, key); + CFDictionarySetValue(tds->statedb, dbkey, state); + CFReleaseSafe(dbkey); + return true; +} + +static bool dsRestoreObject(SOSTransactionRef txn, uint64_t handle, CFDictionaryRef item, CFErrorRef *error) { + // TODO: Just call merge, probably doesn't belong in protocol at all + assert(false); + return true; +} + +static CFDictionaryRef objectCopyBackup(SOSObjectRef object, uint64_t handle, CFErrorRef *error) { + // OMG We failed without an error. + assert(false); + return NULL; +} + +SOSDataSourceRef SOSTestDataSourceCreate(void) { + SOSTestDataSourceRef ds = calloc(1, sizeof(struct SOSTestDataSource)); + + ds->ds.engine = NULL; + ds->ds.dsGetName = dsGetName; + ds->ds.dsSetNotifyPhaseBlock = dsSetNotifyPhaseBlock; + ds->ds.dsCopyManifest = copy_manifest; + ds->ds.dsForEachObject = foreach_object; + ds->ds.dsCopyStateWithKey = dsCopyStateWithKey; + ds->ds.dsWith = dsWith; + ds->ds.dsRelease = dispose; + + ds->ds.dsMergeObject = mergeObject; + ds->ds.dsSetStateWithKey = dsSetStateWithKey; + ds->ds.dsRestoreObject = dsRestoreObject; + + ds->ds.objectCopyDigest = copyDigest; + ds->ds.objectCopyPrimaryKey = copyPrimaryKey; + ds->ds.objectCreateWithPropertyList = createWithPropertyList; + ds->ds.objectCopyPropertyList = copyPropertyList; + ds->ds.objectCopyBackup = objectCopyBackup; + + ds->d2database = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + ds->p2database = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + ds->statedb = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + ds->clean = false; + + return (SOSDataSourceRef)ds; +} + +static CFArrayRef SOSTestDataSourceFactoryCopyNames(SOSDataSourceFactoryRef factory) +{ + SOSTestDataSourceFactoryRef dsf = (SOSTestDataSourceFactoryRef) factory; + CFMutableArrayRef result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + + CFDictionaryForEach(dsf->data_sources, ^(const void*key, const void*value) { CFArrayAppendValue(result, key); }); + + return result; +} + +static SOSDataSourceRef SOSTestDataSourceFactoryCreateDataSource(SOSDataSourceFactoryRef factory, CFStringRef dataSourceName, CFErrorRef *error) +{ + SOSTestDataSourceFactoryRef dsf = (SOSTestDataSourceFactoryRef) factory; + + return (SOSDataSourceRef) CFDictionaryGetValue(dsf->data_sources, dataSourceName); +} + +static void SOSTestDataSourceFactoryDispose(SOSDataSourceFactoryRef factory) +{ + SOSTestDataSourceFactoryRef dsf = (SOSTestDataSourceFactoryRef) factory; + + CFReleaseNull(dsf->data_sources); + free(dsf); +} + +SOSDataSourceFactoryRef SOSTestDataSourceFactoryCreate() { + SOSTestDataSourceFactoryRef dsf = calloc(1, sizeof(struct SOSTestDataSourceFactory)); + + dsf->dsf.copy_names = SOSTestDataSourceFactoryCopyNames; + dsf->dsf.create_datasource = SOSTestDataSourceFactoryCreateDataSource; + dsf->dsf.release = SOSTestDataSourceFactoryDispose; + dsf->data_sources = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, NULL); + + return &(dsf->dsf); +} + +static bool do_nothing(SOSDataSourceRef ds, CFErrorRef *error) { + return true; +} + +void SOSTestDataSourceFactoryAddDataSource(SOSDataSourceFactoryRef factory, CFStringRef name, SOSDataSourceRef ds) +{ + SOSTestDataSourceFactoryRef dsf = (SOSTestDataSourceFactoryRef) factory; + + // TODO This hack sucks. It leaks now. + ds->dsRelease = do_nothing; + + CFDictionarySetValue(dsf->data_sources, name, ds); + +} + +SOSMergeResult SOSTestDataSourceAddObject(SOSDataSourceRef data_source, SOSObjectRef object, CFErrorRef *error) { + struct SOSTestDataSource *ds = (struct SOSTestDataSource *)data_source; + bool result = false; + CFDataRef key = copyDigest(object, error); + CFDataRef pk = copyPrimaryKey(object, error); + if (key && pk) { + SOSObjectRef myObject = (SOSObjectRef)CFDictionaryGetValue(ds->p2database, pk); + SOSObjectRef merged = NULL; + if (myObject) { + merged = copyMergedObject(object, myObject, error); + } else { + merged = object; + CFRetain(merged); + } + if (merged) { + result = true; + if (!CFEqualSafe(merged, myObject)) { + if (myObject) { + CFDataRef myKey = copyDigest(myObject, error); + CFDictionaryRemoveValue(ds->d2database, myKey); + SOSDigestVectorAppend(&ds->removals, CFDataGetBytePtr(myKey)); + CFReleaseSafe(myKey); + } + CFDictionarySetValue(ds->d2database, key, merged); + CFDictionarySetValue(ds->p2database, pk, merged); + SOSDigestVectorAppend(&ds->additions, CFDataGetBytePtr(key)); + ds->clean = false; + } + CFRelease(merged); + } + } + CFReleaseSafe(pk); + CFReleaseSafe(key); + return result; +} + +bool SOSTestDataSourceDeleteObject(SOSDataSourceRef data_source, CFDataRef key, CFErrorRef *error) { + //struct SOSTestDataSource *ds = (struct SOSTestDataSource *)data_source; + return false; +} + +CFMutableDictionaryRef SOSTestDataSourceGetDatabase(SOSDataSourceRef data_source) { + struct SOSTestDataSource *ds = (struct SOSTestDataSource *)data_source; + return ds->d2database; +} + +// This works for any datasource, not just the test one, but it's only used in testcases, so it's here for now. +SOSObjectRef SOSDataSourceCreateGenericItemWithData(SOSDataSourceRef ds, CFStringRef account, CFStringRef service, bool is_tomb, CFDataRef data) { + int32_t value = 0; + CFNumberRef zero = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value); + value = 1; + CFNumberRef one = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value); + CFAbsoluteTime timestamp = 3700000; + CFDateRef now = CFDateCreate(kCFAllocatorDefault, timestamp); + CFDictionaryRef dict = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecClass, kSecClassGenericPassword, + kSecAttrSynchronizable, one, + kSecAttrTombstone, is_tomb ? one : zero, + kSecAttrAccount, account, + kSecAttrService, service, + kSecAttrCreationDate, now, + kSecAttrModificationDate, now, + kSecAttrAccessGroup, CFSTR("test"), + kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked, + !is_tomb && data ? kSecValueData : NULL,data, + NULL); + CFRelease(one); + CFRelease(zero); + CFReleaseSafe(now); + CFErrorRef localError = NULL; + SOSObjectRef object = ds->objectCreateWithPropertyList(dict, &localError); + if (!object) { + secerror("createWithPropertyList: %@ failed: %@", dict, localError); + CFRelease(localError); + } + CFRelease(dict); + return object; +} + +SOSObjectRef SOSDataSourceCreateGenericItem(SOSDataSourceRef ds, CFStringRef account, CFStringRef service) { + return SOSDataSourceCreateGenericItemWithData(ds, account, service, false, NULL); +} + +SOSObjectRef SOSDataSourceCopyObject(SOSDataSourceRef ds, SOSObjectRef match, CFErrorRef *error) +{ + __block SOSObjectRef result = NULL; + + CFDataRef digest = SOSObjectCopyDigest(ds, match, error); + SOSManifestRef manifest = NULL; + + require(digest, exit); + manifest = SOSManifestCreateWithData(digest, error); + + SOSDataSourceForEachObject(ds, manifest, error, ^void (CFDataRef key, SOSObjectRef object, bool *stop) { + if (object == NULL) { + if (error && !*error) { + SecCFCreateErrorWithFormat(kSOSDataSourceObjectNotFoundError, sSOSDataSourceErrorDomain, NULL, error, 0, CFSTR("key %@ not in database"), key); + } + } else if (result == NULL) { + result = CFRetainSafe(object); + } + }); + +exit: + CFReleaseNull(manifest); + CFReleaseNull(digest); + return result; +} diff --git a/Security/sec/SOSCircle/Regressions/SOSTestDataSource.h b/Security/sec/SOSCircle/Regressions/SOSTestDataSource.h new file mode 100644 index 00000000..d103613d --- /dev/null +++ b/Security/sec/SOSCircle/Regressions/SOSTestDataSource.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef _SEC_SOSTestDataSource_H_ +#define _SEC_SOSTestDataSource_H_ + +#include + +extern CFStringRef sSOSDataSourceErrorDomain; + +enum { + kSOSDataSourceObjectMallocFailed = 1, + kSOSDataSourceAddDuplicateEntry, + kSOSDataSourceObjectNotFoundError, + kSOSDataSourceAccountCreationFailed, +}; + +// +// MARK: Data Source Functions +// +SOSDataSourceRef SOSTestDataSourceCreate(void); + +CFMutableDictionaryRef SOSTestDataSourceGetDatabase(SOSDataSourceRef data_source); + +SOSMergeResult SOSTestDataSourceAddObject(SOSDataSourceRef data_source, SOSObjectRef object, CFErrorRef *error); +bool SOSTestDataSourceDeleteObject(SOSDataSourceRef data_source, CFDataRef key, CFErrorRef *error); + +// +// MARK: Data Source Factory Functions +// + +SOSDataSourceFactoryRef SOSTestDataSourceFactoryCreate(void); +void SOSTestDataSourceFactoryAddDataSource(SOSDataSourceFactoryRef factory, CFStringRef name, SOSDataSourceRef ds); + +SOSObjectRef SOSDataSourceCreateGenericItemWithData(SOSDataSourceRef ds, CFStringRef account, CFStringRef service, bool is_tomb, CFDataRef data); +SOSObjectRef SOSDataSourceCreateGenericItem(SOSDataSourceRef ds, CFStringRef account, CFStringRef service); + +SOSObjectRef SOSDataSourceCopyObject(SOSDataSourceRef ds, SOSObjectRef match, CFErrorRef *error); + +#endif /* _SEC_SOSTestDataSource_H_ */ diff --git a/Security/sec/SOSCircle/Regressions/SOSTestDevice.c b/Security/sec/SOSCircle/Regressions/SOSTestDevice.c new file mode 100644 index 00000000..e8aa5e2b --- /dev/null +++ b/Security/sec/SOSCircle/Regressions/SOSTestDevice.c @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +// Test syncing between SecItemDataSource and SOSTestDataSource + +#include "SOSTestDevice.h" +#include "SOSTestDataSource.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +CFStringRef SOSMessageCopyDigestHex(SOSMessageRef message) { + uint8_t digest[CCSHA1_OUTPUT_SIZE]; + // TODO: Pass in real sequenceNumber. + CFDataRef msgData = SOSMessageCreateData(message, 0, NULL); + if (!msgData) return NULL; + ccdigest(ccsha1_di(), CFDataGetLength(msgData), CFDataGetBytePtr(msgData), digest); + CFMutableStringRef hex = CFStringCreateMutable(0, 2 * sizeof(digest)); + for (unsigned int ix = 0; ix < sizeof(digest); ++ix) { + CFStringAppendFormat(hex, 0, CFSTR("%02X"), digest[ix]); + } + CFReleaseSafe(msgData); + return hex; +} + +static void SOSTestDeviceDestroy(CFTypeRef cf) { + SOSTestDeviceRef td = (SOSTestDeviceRef)cf; + CFReleaseSafe(td->peers); + if (td->ds) + SOSDataSourceRelease(td->ds, NULL); + if (td->dsf) + td->dsf->release(td->dsf); + CFReleaseSafe(td->db); +} + +CFStringRef SOSTestDeviceGetID(SOSTestDeviceRef td) { + CFStringRef engineID = NULL; + SOSEngineRef engine = SOSDataSourceGetSharedEngine(td->ds, NULL); + if (engine) + engineID = SOSEngineGetMyID(engine); + return engineID; +} + +void SOSTestDeviceForEachPeerID(SOSTestDeviceRef td, void(^peerBlock)(CFStringRef peerID, bool *stop)) { + SOSPeerRef peer; + bool stop = false; + CFArrayForEachC(td->peers, peer) { + peerBlock(SOSPeerGetID(peer), &stop); + if (stop) + break; + } +} + +static CFStringRef SOSTestDeviceCopyDescription(CFTypeRef cf) { + SOSTestDeviceRef td = (SOSTestDeviceRef)cf; + CFMutableStringRef result = CFStringCreateMutable(kCFAllocatorDefault, 0); + CFStringAppendFormat(result, NULL, CFSTR("ds->engine); + SOSTestDeviceForEachPeerID(td, ^(CFStringRef peerID, bool *stop) { + SOSPeerRef peer = SOSPeerCreateWithEngine(td->ds->engine, peerID); + CFStringAppendFormat(result, NULL, CFSTR("\n%@"), peer); + CFReleaseSafe(peer); + }); + CFStringAppendFormat(result, NULL, CFSTR(">")); + return result; +} + +CFGiblisFor(SOSTestDevice) + +static SOSTestDeviceRef SOSTestDeviceCreateInternal(CFAllocatorRef allocator, CFStringRef engineID) { + SOSTestDeviceRef td = CFTypeAllocate(SOSTestDevice, struct __OpaqueSOSTestDevice, allocator); + td->peers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + return td; +} + +SOSTestDeviceRef SOSTestDeviceCreateWithDb(CFAllocatorRef allocator, CFStringRef engineID, SecDbRef db) { + setup("create device"); + SOSTestDeviceRef td = SOSTestDeviceCreateInternal(allocator, engineID); + CFRetainAssign(td->db, db); + td->dsf = SecItemDataSourceFactoryGetShared(td->db); + CFArrayRef ds_names = td->dsf->copy_names(td->dsf); + CFErrorRef error = NULL; + if (ds_names && CFArrayGetCount(ds_names) > 0) { + CFStringRef sname = CFArrayGetValueAtIndex(ds_names, 0); + ok (td->ds = td->dsf->create_datasource(td->dsf, sname, &error), "%@ create datasource \"%@\" [error: %@]", engineID, sname, error); + CFReleaseNull(error); + } + CFReleaseNull(ds_names); + assert(td->ds); // Shut up static analyzer and test generally run in debug mode anyway + if (td->ds) + SOSEngineCircleChanged(SOSDataSourceGetSharedEngine(td->ds, NULL), engineID, NULL, NULL); + return td; +} + +SOSTestDeviceRef SOSTestDeviceCreateWithDbNamed(CFAllocatorRef allocator, CFStringRef engineID, CFStringRef dbName) { + CFURLRef url = SecCopyURLForFileInKeychainDirectory(dbName); + CFStringRef path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); + SecDbRef db = SecKeychainDbCreate(path); + SOSTestDeviceRef td = SOSTestDeviceCreateWithDb(allocator, engineID, db); + CFReleaseSafe(db); + CFReleaseSafe(path); + CFReleaseSafe(url); + return td; +} + +SOSTestDeviceRef SOSTestDeviceCreateWithTestDataSource(CFAllocatorRef allocator, CFStringRef engineID) { + setup("create device"); + SOSTestDeviceRef td = SOSTestDeviceCreateInternal(allocator, engineID); + + td->ds = SOSTestDataSourceCreate(); + CFErrorRef error = NULL; + ok(td->ds->engine = SOSEngineCreate(td->ds, &error), "create engine: %@", error); + SOSEngineCircleChanged(td->ds->engine, engineID, NULL, NULL); + CFReleaseNull(error); + return td; +} + +SOSTestDeviceRef SOSTestDeviceSetPeerIDs(SOSTestDeviceRef td, CFArrayRef peerIDs, CFIndex version) { + setup("create device"); + CFStringRef engineID = SOSTestDeviceGetID(td); + CFStringRef peerID; + CFMutableArrayRef trustedPeersIDs = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFErrorRef error = NULL; + CFArrayForEachC(peerIDs, peerID) { + if (isString(peerID) && !CFEqualSafe(peerID, engineID)) { + SOSPeerRef peer; + ok(peer = SOSPeerCreateSimple(td->ds->engine, peerID, version, &error), "create peer: %@", error); + CFReleaseNull(error); + CFArrayAppendValue(td->peers, peer); + CFArrayAppendValue(trustedPeersIDs, peerID); + } + } + + SOSEngineCircleChanged(td->ds->engine, engineID, trustedPeersIDs, NULL); + CFArrayForEachC(trustedPeersIDs, peerID) { + ok(SOSEnginePeerDidConnect(td->ds->engine, peerID, &error), "tell %@ %@ connected: %@", engineID, peerID, error); + CFReleaseNull(error); + } + CFReleaseSafe(trustedPeersIDs); + return td; +} + +CFDataRef SOSTestDeviceCreateMessage(SOSTestDeviceRef td, CFStringRef peerID) { + setup("create message"); + CFErrorRef error = NULL; + SOSEnginePeerMessageSentBlock sent = NULL; + CFDataRef msgData; + ok(msgData = SOSEngineCreateMessageToSyncToPeer(td->ds->engine, peerID, &sent, &error), + "create message to %@: %@", peerID, error); + if (sent) + sent(true); + + return msgData; +} + +#if 0 +CFDictionaryRef SOSTestDeviceCreateMessages(SOSTestDeviceRef td) { + CFTypeRef peer = NULL; + CFMutableDictionaryRef messages = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFArrayForEachC(td->peers, peer) { + CFStringRef peerID = SOSPeerGetID((SOSPeerRef)peer); + CFDataRef msg = SOSTestDeviceCreateMessage(td, peerID); + if (msg) { + CFDictionaryAddValue(messages, peerID, msg); + CFRelease(msg); + } + } + return messages; +} +#endif + +bool SOSTestDeviceHandleMessage(SOSTestDeviceRef td, CFStringRef peerID, CFDataRef msgData) { + setup("handle message"); + if (!msgData) return false; + CFErrorRef error = NULL; + bool handled; + SOSMessageRef message; + + ok(message = SOSMessageCreateWithData(kCFAllocatorDefault, msgData, &error), "decode message %@: %@", msgData, error); + CFReleaseNull(error); + pass("handeling %@->%@ %@", peerID, SOSEngineGetMyID(SOSDataSourceGetSharedEngine(td->ds, &error)), message); + ok(handled = SOSEngineHandleMessage(SOSDataSourceGetSharedEngine(td->ds, &error), peerID, msgData, &error), + "handled from %@ %@: %@", peerID, message, error); + CFReleaseNull(error); + + CFReleaseNull(message); + return handled; +} + +void SOSTestDeviceAddGenericItem(SOSTestDeviceRef td, CFStringRef account, CFStringRef server) { + __block CFErrorRef error = NULL; + if (!SOSDataSourceWithAPI(td->ds, true, &error, ^(SOSTransactionRef txn, bool *commit) { + SOSObjectRef object = SOSDataSourceCreateGenericItem(td->ds, account, server); + ok(SOSDataSourceMergeObject(td->ds, txn, object, NULL, &error), "%@ added API object %@", SOSTestDeviceGetID(td), error ? (CFTypeRef)error : (CFTypeRef)CFSTR("ok")); + CFReleaseSafe(object); + CFReleaseNull(error); + })) + fail("ds transaction %@", error); + CFReleaseNull(error); +} + +void SOSTestDeviceAddRemoteGenericItem(SOSTestDeviceRef td, CFStringRef account, CFStringRef server) { + __block CFErrorRef error = NULL; + if (!SOSDataSourceWithAPI(td->ds, false, &error, ^(SOSTransactionRef txn, bool *commit) { + SOSObjectRef object = SOSDataSourceCreateGenericItem(td->ds, account, server); + ok(SOSDataSourceMergeObject(td->ds, txn, object, NULL, &error), "%@ added remote object %@", SOSTestDeviceGetID(td), error ? (CFTypeRef)error : (CFTypeRef)CFSTR("ok")); + CFReleaseSafe(object); + CFReleaseNull(error); + })) + fail("ds transaction %@", error); + CFReleaseNull(error); +} + +bool SOSTestDeviceAddGenericItems(SOSTestDeviceRef td, CFIndex count, CFStringRef account, CFStringRef server) { + __block bool didAdd = false; + __block CFErrorRef error = NULL; + if (!SOSDataSourceWithAPI(td->ds, true, &error, ^(SOSTransactionRef txn, bool *commit) { + bool success = true; + CFIndex ix = 0; + for (; success && ix < count; ++ix) { + CFStringRef accountStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@%" PRIdCFIndex), account, ix); + SOSObjectRef object = SOSDataSourceCreateGenericItem(td->ds, accountStr, server); + success = SOSDataSourceMergeObject(td->ds, txn, object, NULL, &error); + CFReleaseSafe(object); + } + ok(success, "%@ added %" PRIdCFIndex " API objects %@", SOSTestDeviceGetID(td), ix, error ? (CFTypeRef)error : (CFTypeRef)CFSTR("ok")); + didAdd = success && ix == count; + CFReleaseNull(error); + })) + fail("ds transaction %@", error); + CFReleaseNull(error); + return didAdd; +} + +CFMutableDictionaryRef SOSTestDeviceListCreate(bool realDb, CFIndex version, CFArrayRef deviceIDs) { + CFMutableDictionaryRef testDevices = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFStringRef deviceID; + CFArrayForEachC(deviceIDs, deviceID) { + SOSTestDeviceRef device; + if (!realDb) + device = SOSTestDeviceCreateWithTestDataSource(kCFAllocatorDefault, deviceID); + else + device = SOSTestDeviceCreateWithDbNamed(kCFAllocatorDefault, deviceID, deviceID); + SOSTestDeviceSetPeerIDs(device, deviceIDs, version); + CFDictionarySetValue(testDevices, deviceID, device); + CFReleaseSafe(device); + } + CFDictionarySetValue(testDevices, CFSTR("@devicesIDs"), deviceIDs); + return testDevices; +} + +void SOSTestDeviceListSync(const char *name, const char *test_directive, const char *test_reason, CFMutableDictionaryRef testDevices, bool(^pre)(SOSTestDeviceRef source, SOSTestDeviceRef dest), bool(^post)(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message)) { + CFArrayRef deviceIDs = (CFArrayRef)CFDictionaryGetValue(testDevices, CFSTR("@devicesIDs")); + const CFIndex edgeCount = CFArrayGetCount(deviceIDs) * (CFArrayGetCount(deviceIDs) - 1); + CFIndex deviceIX = 0; + __block CFIndex noMsgSentCount = 0; + __block CFIndex msgSentSinceLastChangeCount = 0; + __block bool done = false; + do { + CFStringRef sourceID = (CFStringRef)CFArrayGetValueAtIndex(deviceIDs, deviceIX++); + if (deviceIX >= CFArrayGetCount(deviceIDs)) + deviceIX = 0; + + SOSTestDeviceRef source = (SOSTestDeviceRef)CFDictionaryGetValue(testDevices, sourceID); + SOSTestDeviceForEachPeerID(source, ^(CFStringRef destID, bool *stop) { + SOSTestDeviceRef dest = (SOSTestDeviceRef)CFDictionaryGetValue(testDevices, destID); + if (dest) { + if (pre) { + if (pre(source, dest)) + msgSentSinceLastChangeCount = 0; + } + CFDataRef msg = SOSTestDeviceCreateMessage(source, destID); + SOSMessageRef message = NULL; + bool handled = false; + msgSentSinceLastChangeCount++; + if (msg && CFDataGetLength(msg) > 0) { + handled = SOSTestDeviceHandleMessage(dest, sourceID, msg); + if (handled) { + noMsgSentCount = 0; + } + + CFErrorRef error = NULL; + message = SOSMessageCreateWithData(kCFAllocatorDefault, msg, &error); + ok(handled, "%s %@->%@ %@", name, sourceID, destID, message); + CFReleaseNull(error); + } else { + SOSManifestRef sourceManifest = SOSEngineCopyManifest(SOSDataSourceGetSharedEngine(source->ds, NULL), NULL); + pass("%s %@->%@ done L:%@", name, sourceID, destID, sourceManifest); + CFReleaseSafe(sourceManifest); + noMsgSentCount++; + //msgSentSinceLastChangeCount = 0; + } + CFReleaseSafe(msg); + if (post) { + if (post(source, dest, message)) + msgSentSinceLastChangeCount = 0; + } + CFReleaseNull(message); + } + if (noMsgSentCount >= edgeCount) { + *stop = done = true; + } else if (msgSentSinceLastChangeCount >= 9 * edgeCount + 1) { + fail("%s %" PRIdCFIndex" peers never stopped syncing %" PRIdCFIndex" messages since last change", name, CFArrayGetCount(deviceIDs), msgSentSinceLastChangeCount); + *stop = done = true; + } + }); + } while (!done); +} + +bool SOSTestDeviceListInSync(const char *name, const char *test_directive, const char *test_reason, CFMutableDictionaryRef testDevices) { + bool inSync = true; + CFArrayRef deviceIDs = (CFArrayRef)CFDictionaryGetValue(testDevices, CFSTR("@devicesIDs")); + CFStringRef sourceID = NULL; + SOSManifestRef sourceManifest = NULL; + CFStringRef currentID; + CFArrayForEachC(deviceIDs, currentID) { + SOSTestDeviceRef source = (SOSTestDeviceRef)CFDictionaryGetValue(testDevices, currentID); + SOSManifestRef manifest = SOSEngineCopyManifest(SOSDataSourceGetSharedEngine(source->ds, NULL), NULL); + if (!sourceManifest) { + sourceManifest = CFRetainSafe(manifest); + sourceID = currentID; + } else if (!CFEqual(manifest, sourceManifest)) { + fail("%s %@ manifest %@ != %@ manifest %@", name, currentID, manifest, sourceID, sourceManifest); + inSync = false; + } + CFReleaseSafe(manifest); + } + CFReleaseSafe(sourceManifest); + if (inSync) + pass("%s all peers in sync", name); + return inSync; +} + +void SOSTestDeviceListTestSync(const char *name, const char *test_directive, const char *test_reason, CFIndex version, bool use_db, + bool(^pre)(SOSTestDeviceRef source, SOSTestDeviceRef dest), + bool(^post)(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message), ...) { + va_list args; + va_start(args, post); + // Optionally prefix each peer with name to make them more unique. + CFArrayRef deviceIDs = CFArrayCreateForVC(kCFAllocatorDefault, &kCFTypeArrayCallBacks, args); + CFMutableDictionaryRef testDevices = SOSTestDeviceListCreate(use_db, version, deviceIDs); + CFReleaseSafe(deviceIDs); + SOSTestDeviceListSync(name, test_directive, test_reason, testDevices, pre, post); + SOSTestDeviceListInSync(name, test_directive, test_reason, testDevices); + CFReleaseSafe(testDevices); +} diff --git a/Security/sec/SOSCircle/Regressions/SOSTestDevice.h b/Security/sec/SOSCircle/Regressions/SOSTestDevice.h new file mode 100644 index 00000000..8af4e172 --- /dev/null +++ b/Security/sec/SOSCircle/Regressions/SOSTestDevice.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include + +typedef struct __OpaqueSOSTestDevice *SOSTestDeviceRef; + +struct __OpaqueSOSTestDevice { + CFRuntimeBase _base; + SecDbRef db; + SOSDataSourceFactoryRef dsf; + SOSDataSourceRef ds; + CFMutableArrayRef peers; +}; + +CFStringRef SOSMessageCopyDigestHex(SOSMessageRef message); + +CFStringRef SOSTestDeviceGetID(SOSTestDeviceRef td); +void SOSTestDeviceForEachPeerID(SOSTestDeviceRef td, void(^peerBlock)(CFStringRef peerID, bool *stop)); +SOSTestDeviceRef SOSTestDeviceCreateWithDb(CFAllocatorRef allocator, CFStringRef engineID, SecDbRef db); +SOSTestDeviceRef SOSTestDeviceCreateWithDbNamed(CFAllocatorRef allocator, CFStringRef engineID, CFStringRef dbName); +SOSTestDeviceRef SOSTestDeviceCreateWithTestDataSource(CFAllocatorRef allocator, CFStringRef engineID); +SOSTestDeviceRef SOSTestDeviceSetPeerIDs(SOSTestDeviceRef td, CFArrayRef peerIDs, CFIndex version); + +CFDataRef SOSTestDeviceCreateMessage(SOSTestDeviceRef td, CFStringRef peerID); + +bool SOSTestDeviceHandleMessage(SOSTestDeviceRef td, CFStringRef peerID, CFDataRef msgData); + +void SOSTestDeviceAddGenericItem(SOSTestDeviceRef td, CFStringRef account, CFStringRef server); +void SOSTestDeviceAddRemoteGenericItem(SOSTestDeviceRef td, CFStringRef account, CFStringRef server); +bool SOSTestDeviceAddGenericItems(SOSTestDeviceRef td, CFIndex count, CFStringRef account, CFStringRef server); + +CFMutableDictionaryRef SOSTestDeviceListCreate(bool realDb, CFIndex version, CFArrayRef deviceIDs); + +void SOSTestDeviceListSync(const char *name, const char *test_directive, const char *test_reason, CFMutableDictionaryRef testDevices, bool(^pre)(SOSTestDeviceRef source, SOSTestDeviceRef dest), bool(^post)(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message)); + +bool SOSTestDeviceListInSync(const char *name, const char *test_directive, const char *test_reason, CFMutableDictionaryRef testDevices); + +void SOSTestDeviceListTestSync(const char *name, const char *test_directive, const char *test_reason, CFIndex version, bool use_db, + bool(^pre)(SOSTestDeviceRef source, SOSTestDeviceRef dest), + bool(^post)(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message), ...); diff --git a/sec/SOSCircle/Regressions/sc-103-syncupdate.c b/Security/sec/SOSCircle/Regressions/sc-103-syncupdate.c similarity index 82% rename from sec/SOSCircle/Regressions/sc-103-syncupdate.c rename to Security/sec/SOSCircle/Regressions/sc-103-syncupdate.c index 48e26de7..84e41ffc 100644 --- a/sec/SOSCircle/Regressions/sc-103-syncupdate.c +++ b/Security/sec/SOSCircle/Regressions/sc-103-syncupdate.c @@ -1,10 +1,26 @@ -// -// sc-103-syncupdate.c -// sec -// -// Created by John Hurley on 9/6/12. -// -// +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + // Run on 2 devices: // /AppleInternal/Applications/SecurityTests.app/SecurityTests sc_103_syncupdate -v -- -i alice @@ -37,16 +53,19 @@ #include "SOSCircle_regressions.h" #include "SOSRegressionUtilities.h" -#include "SOSCloudKeychainConstants.h" +#include #define xsecdebug(format...) secerror(format) static dispatch_group_t sDispatchGroup = NULL; -static const uint64_t putTestInterval = 10ull * NSEC_PER_SEC; +__unused static const uint64_t putTestInterval = 10ull * NSEC_PER_SEC; static const uint64_t leeway = 1ull * NSEC_PER_SEC; -static const uint64_t syncInterval = 60ull * NSEC_PER_SEC; // seconds -static const uint64_t putDelay = 10ull * NSEC_PER_SEC; // seconds; should probably be longer than syncedefaultsd latency (6 sec) + +__unused static const uint64_t syncInterval = 60ull * NSEC_PER_SEC; // seconds + +__unused static const uint64_t putDelay = 10ull * NSEC_PER_SEC; // seconds; should probably be longer than syncedefaultsd latency (6 sec) + static const uint64_t exitDelay = 180ull * NSEC_PER_SEC; // seconds static dispatch_queue_t requestqueue; diff --git a/sec/SOSCircle/Regressions/sc-130-resignationticket.c b/Security/sec/SOSCircle/Regressions/sc-130-resignationticket.c similarity index 77% rename from sec/SOSCircle/Regressions/sc-130-resignationticket.c rename to Security/sec/SOSCircle/Regressions/sc-130-resignationticket.c index ec7bf3bc..cd41d680 100644 --- a/sec/SOSCircle/Regressions/sc-130-resignationticket.c +++ b/Security/sec/SOSCircle/Regressions/sc-130-resignationticket.c @@ -1,10 +1,26 @@ -// -// sc-130-resignationticket.c -// sec -// -// Created by Richard Murphy on 5/1/13. -// -// +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include #include @@ -105,7 +121,7 @@ static void tests(void) #endif } -static int kTestTestCount = 20; +static int kTestTestCount = 8; int sc_130_resignationticket(int argc, char *const *argv) { diff --git a/Security/sec/SOSCircle/Regressions/sc-131-transport.c b/Security/sec/SOSCircle/Regressions/sc-131-transport.c new file mode 100644 index 00000000..d3c43177 --- /dev/null +++ b/Security/sec/SOSCircle/Regressions/sc-131-transport.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include + +#include +#include + +#include "SOSCircle_regressions.h" + +#include "SOSRegressionUtilities.h" + +static void tests(void){ + printf("HI~!~\n"); + /* pick the vtable for objects at compile time */ +} + + +int sc_131_transport(int argc, char *const *argv) +{ + plan_tests(0); + + tests(); + + return 0; +} diff --git a/sec/SOSCircle/Regressions/sc-20-keynames.c b/Security/sec/SOSCircle/Regressions/sc-20-keynames.c similarity index 79% rename from sec/SOSCircle/Regressions/sc-20-keynames.c rename to Security/sec/SOSCircle/Regressions/sc-20-keynames.c index 1c3f781e..a2bda0af 100644 --- a/sec/SOSCircle/Regressions/sc-20-keynames.c +++ b/Security/sec/SOSCircle/Regressions/sc-20-keynames.c @@ -1,12 +1,28 @@ /* - * sc-20-keynames.c - * - * Created by Mitch Adler on 1/25/121. - * Copyright 2012 Apple Inc. All rights reserved. + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include #include #include @@ -15,7 +31,7 @@ #include #include #include - +#include #include #include @@ -32,8 +48,6 @@ static int kTestTestCount = 15; static void tests(void) { SecKeyRef publicKey = NULL; - SecKeyRef signingKey = NULL; - GenerateECPair(256, &publicKey, &signingKey); CFErrorRef error = NULL; SOSCircleRef circle = SOSCircleCreate(NULL, CFSTR("Test Circle"), &error); @@ -91,7 +105,6 @@ static void tests(void) SOSPeerInfoGetPeerID(pi), retirement_peer_id); CFReleaseNull(publicKey); - CFReleaseNull(signingKey); CFReleaseNull(circle); CFReleaseNull(error); CFReleaseNull(pi); diff --git a/Security/sec/SOSCircle/Regressions/sc-30-peerinfo.c b/Security/sec/SOSCircle/Regressions/sc-30-peerinfo.c new file mode 100644 index 00000000..04c5fc54 --- /dev/null +++ b/Security/sec/SOSCircle/Regressions/sc-30-peerinfo.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include "SOSCircle_regressions.h" + +#include "SOSRegressionUtilities.h" + +#if TARGET_OS_IPHONE +#include +#endif + +static int kTestTestCount = 11; +static void tests(void) +{ + SecKeyRef signingKey = NULL; + SOSFullPeerInfoRef fpi = SOSCreateFullPeerInfoFromName(CFSTR("Test Peer"), &signingKey, NULL); + SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(fpi); + CFRetainSafe(pi); + + ok(NULL != pi, "info creation"); + + uint8_t buffer[4096]; + + const uint8_t *buffer_p = SOSPeerInfoEncodeToDER(pi, NULL, buffer, buffer + sizeof(buffer)); + + ok(buffer_p != NULL, "encode"); + + SOSPeerInfoRef pi2 = SOSPeerInfoCreateFromDER(NULL, NULL, &buffer_p, buffer + sizeof(buffer)); + + SKIP: + { + skip("Decode failed", 1, ok(NULL != pi2, "Decode")); + ok(CFEqual(pi, pi2), "Decode matches"); + } + + buffer_p = SOSFullPeerInfoEncodeToDER(fpi, NULL, buffer, buffer + sizeof(buffer)); + + ok(buffer_p != NULL, "Full peer encode"); + + SOSFullPeerInfoRef fpi2 = SOSFullPeerInfoCreateFromDER(kCFAllocatorDefault, NULL, &buffer_p, buffer + sizeof(buffer)); + + SKIP: + { + skip("Full Peer Decode failed", 1, ok(fpi2, "Full peer inflated")); + + ok(CFEqual(fpi, fpi2), "Full peer inflate matches"); + } + + +// Application ticket time. + CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); + CFErrorRef error = NULL; + + CFDataRef parameters = SOSUserKeyCreateGenerateParameters(&error); + ok(parameters, "No parameters!"); + ok(error == NULL, "Error: (%@)", error); + CFReleaseNull(error); + + SecKeyRef user_privkey = SOSUserKeygen(cfpassword, parameters, &error); + CFReleaseSafe(cfpassword); + CFReleaseNull(parameters); + SecKeyRef user_pubkey = SecKeyCreatePublicFromPrivate(user_privkey); + + ok(SOSFullPeerInfoPromoteToApplication(fpi, user_privkey, &error), "Promote to Application"); + ok(SOSPeerInfoApplicationVerify(SOSFullPeerInfoGetPeerInfo(fpi), user_pubkey, &error), "Promote to Application"); + + + CFReleaseNull(user_privkey); + CFReleaseNull(user_pubkey); + + CFReleaseNull(signingKey); + CFReleaseNull(pi); + CFReleaseNull(pi2); + CFReleaseNull(fpi); + CFReleaseNull(fpi2); +} + +int sc_30_peerinfo(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/Security/sec/SOSCircle/Regressions/sc-31-peerinfo-simplefuzz.c b/Security/sec/SOSCircle/Regressions/sc-31-peerinfo-simplefuzz.c new file mode 100644 index 00000000..6111f98c --- /dev/null +++ b/Security/sec/SOSCircle/Regressions/sc-31-peerinfo-simplefuzz.c @@ -0,0 +1,83 @@ +/* + * sc-31-peerinfo.c + * + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + */ + + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include "SOSCircle_regressions.h" + +#include "SOSRegressionUtilities.h" + +#if TARGET_OS_IPHONE +#include +#endif + +static unsigned long kTestCount = 2; +static unsigned long kTestFuzzerCount = 20000; + +static void tests(void) +{ + SecKeyRef signingKey = NULL; + SOSFullPeerInfoRef fpi = SOSCreateFullPeerInfoFromName(CFSTR("Test Peer"), &signingKey, NULL); + SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(fpi); + unsigned long count; + + CFRetainSafe(pi); + + ok(NULL != pi, "info creation"); + + uint8_t buffer[4096]; + + const uint8_t *buffer_p = SOSPeerInfoEncodeToDER(pi, NULL, buffer, buffer + sizeof(buffer)); + + ok(buffer_p != NULL, "encode"); + + size_t length = (buffer + sizeof(buffer)) - buffer_p; + + uint8_t buffer2[length]; + if(buffer_p == NULL) goto errOut; + + for (count = 0; count < kTestFuzzerCount; count++) { + memcpy(buffer2, buffer_p, length); + + const uint8_t *startp = buffer2; + + buffer2[arc4random_uniform((u_int32_t)length)] = arc4random() & 0xff; + + SOSPeerInfoRef pi2 = SOSPeerInfoCreateFromDER(NULL, NULL, &startp, buffer2 + length); + CFReleaseNull(pi2); + ok(1, "fuzz"); + } + +errOut: + CFReleaseNull(signingKey); + CFReleaseNull(pi); +} + +int sc_31_peerinfo(int argc, char *const *argv) +{ + plan_tests((int)(kTestCount + kTestFuzzerCount)); + + tests(); + + return 0; +} diff --git a/Security/sec/SOSCircle/Regressions/sc-40-circle.c b/Security/sec/SOSCircle/Regressions/sc-40-circle.c new file mode 100644 index 00000000..06c544eb --- /dev/null +++ b/Security/sec/SOSCircle/Regressions/sc-40-circle.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include + +#include "SOSCircle_regressions.h" + +#include "SOSRegressionUtilities.h" + +static int kTestTestCount = 18; +static void tests(void) +{ + SOSCircleRef circle = SOSCircleCreate(NULL, CFSTR("TEST DOMAIN"), NULL); + + ok(NULL != circle, "Circle creation"); + + ok(0 == SOSCircleCountPeers(circle), "Zero peers"); + + //SecKeyRef publicKey = NULL; + SecKeyRef dev_a_key = NULL; + SecKeyRef dev_b_key = NULL; + CFErrorRef error = NULL; + CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); + + ok(cfpassword, "no password"); + + CFDataRef parameters = SOSUserKeyCreateGenerateParameters(&error); + ok(parameters, "No parameters!"); + ok(error == NULL, "Error: (%@)", error); + CFReleaseNull(error); + + SecKeyRef user_privkey = SOSUserKeygen(cfpassword, parameters, &error); + CFReleaseNull(parameters); + + SOSFullPeerInfoRef peer_a_full_info = SOSCreateFullPeerInfoFromName(CFSTR("Peer A"), &dev_a_key, NULL); + + SOSFullPeerInfoRef peer_b_full_info = SOSCreateFullPeerInfoFromName(CFSTR("Peer B"), &dev_b_key, NULL); + + ok(SOSCircleRequestAdmission(circle, user_privkey, peer_a_full_info, NULL)); + ok(SOSCircleRequestAdmission(circle, user_privkey, peer_a_full_info, NULL)); + ok(SOSCircleRequestAdmission(circle, user_privkey, peer_a_full_info, NULL)); + + ok(SOSCircleAcceptRequest(circle, user_privkey, peer_a_full_info, SOSFullPeerInfoGetPeerInfo(peer_a_full_info), NULL)); + + ok(!SOSCircleRequestAdmission(circle, user_privkey, peer_a_full_info, NULL)); + ok(SOSCircleRequestAdmission(circle, user_privkey, peer_b_full_info, NULL)); + + ok(SOSCircleCountPeers(circle) == 1, "Peer count"); + + size_t size = SOSCircleGetDEREncodedSize(circle, &error); + uint8_t buffer[size]; + uint8_t* start = SOSCircleEncodeToDER(circle, &error, buffer, buffer + sizeof(buffer)); + + ok(start, "successful encoding"); + ok(start == buffer, "Used whole buffer"); + + const uint8_t *der = buffer; + SOSCircleRef inflated = SOSCircleCreateFromDER(NULL, &error, &der, buffer + sizeof(buffer)); + + ok(inflated, "inflated"); + ok(CFEqualSafe(inflated, circle), "Compares"); + + + ok(SOSCircleRemovePeer(circle, user_privkey, peer_a_full_info, SOSFullPeerInfoGetPeerInfo(peer_a_full_info), NULL)); + ok(SOSCircleCountPeers(circle) == 0, "Peer count"); + + CFReleaseNull(dev_a_key); + CFReleaseNull(cfpassword); +} + +int sc_40_circle(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/Security/sec/SOSCircle/Regressions/sc-41-cloudcircle.c b/Security/sec/SOSCircle/Regressions/sc-41-cloudcircle.c new file mode 100644 index 00000000..764da1f1 --- /dev/null +++ b/Security/sec/SOSCircle/Regressions/sc-41-cloudcircle.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include "SOSCircle_regressions.h" + +#include "SOSRegressionUtilities.h" + +#include +#include + +static const int kSOSCCTestCount = 6; // # of "ok"s in "tests" below +static int kTestTestCount = kSOSCCTestCount; +static void tests(void) +{ + CFErrorRef error = NULL; + CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); + + ok(SOSCCSetUserCredentials(CFSTR("foo1"), cfpassword, &error), "Added Creds (%@)", error); + CFReleaseNull(error); + CFReleaseNull(cfpassword); + + ok(SOSCCThisDeviceIsInCircle(&error) == kSOSCCCircleAbsent, "Circle Absent (%@)", error); + CFReleaseNull(error); + ok(SOSCCResetToOffering(&error), "SOSCCOfferPotentialCircle (%@)", error); + CFReleaseNull(error); + + ok(SOSCCThisDeviceIsInCircle(&error) == kSOSCCInCircle, "Circle Absent (%@)", error); + CFReleaseNull(error); + ok(SOSCCRemoveThisDeviceFromCircle(&error), "Leaving (%@)", error); + CFReleaseNull(error); + + ok(SOSCCThisDeviceIsInCircle(&error) == kSOSCCCircleAbsent, "Circle Absent (%@)", error); + CFReleaseNull(error); +} + +int sc_41_cloudcircle(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/Security/sec/SOSCircle/Regressions/sc-42-circlegencount.c b/Security/sec/SOSCircle/Regressions/sc-42-circlegencount.c new file mode 100644 index 00000000..34e83410 --- /dev/null +++ b/Security/sec/SOSCircle/Regressions/sc-42-circlegencount.c @@ -0,0 +1,67 @@ +// +// sc-42-circlegencount.c +// sec +// +// Created by Richard Murphy on 9/10/14. +// +// + + + + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include + +#include "SOSCircle_regressions.h" + +#include "SOSRegressionUtilities.h" + +static int kTestTestCount = 5; +static void tests(void) +{ + uint64_t beginvalue; + uint64_t incvalue; + + SOSCircleRef circle = SOSCircleCreate(NULL, CFSTR("TEST DOMAIN"), NULL); + + ok(NULL != circle, "Circle creation"); + + ok(0 == SOSCircleCountPeers(circle), "Zero peers"); + + ok(0 != (beginvalue = SOSCircleGetGenerationSint(circle))); // New circles should never be 0 + + SOSCircleGenerationSetValue(circle, 0); + + ok(0 == SOSCircleGetGenerationSint(circle)); // Know we're starting out with a zero value (forced) + + SOSCircleGenerationIncrement(circle); + + ok(beginvalue < (incvalue = SOSCircleGetGenerationSint(circle))); // incremented value should be greater than where we began + + CFReleaseNull(circle); +} + +int sc_42_circlegencount(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/Security/sec/SOSCircle/Regressions/sc-45-digestvector.c b/Security/sec/SOSCircle/Regressions/sc-45-digestvector.c new file mode 100644 index 00000000..57a10f90 --- /dev/null +++ b/Security/sec/SOSCircle/Regressions/sc-45-digestvector.c @@ -0,0 +1,157 @@ +/* + * 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 "SOSCircle_regressions.h" + +#include + +#include +#include + +static int kTestTestCount = 15; + +static void testNullDigestVector(void) +{ + struct SOSDigestVector dv = SOSDigestVectorInit; + is(dv.count, (size_t)0, "count is 0"); + is(dv.capacity, (size_t)0, "capacity is 0"); + ok(!dv.unsorted, "unsorted is false"); +} + +static CFStringRef dvCopyString(const struct SOSDigestVector *dv) +{ + CFMutableStringRef desc = CFStringCreateMutable(kCFAllocatorDefault, 0); + SOSDigestVectorApplySorted(dv, ^(const uint8_t *digest, bool *stop) { + char buf[2] = {}; + buf[0] = digest[0]; + CFStringAppendCString(desc, buf, kCFStringEncodingUTF8); + }); + return desc; +} + +static void testIntersectUnionDigestVector(void) +{ + struct SOSDigestVector dv1 = SOSDigestVectorInit; + struct SOSDigestVector dv2 = SOSDigestVectorInit; + struct SOSDigestVector dvu = SOSDigestVectorInit; + SOSDigestVectorAppend(&dv1, (void *)"a "); + SOSDigestVectorAppend(&dv1, (void *)"b "); + SOSDigestVectorAppend(&dv1, (void *)"d "); + SOSDigestVectorAppend(&dv1, (void *)"f "); + SOSDigestVectorAppend(&dv1, (void *)"h "); + + SOSDigestVectorAppend(&dv2, (void *)"c "); + SOSDigestVectorAppend(&dv2, (void *)"d "); + SOSDigestVectorAppend(&dv2, (void *)"e "); + SOSDigestVectorAppend(&dv2, (void *)"f "); + SOSDigestVectorAppend(&dv2, (void *)"g "); + + SOSDigestVectorAppend(&dvu, (void *)"a "); + SOSDigestVectorAppend(&dvu, (void *)"b "); + SOSDigestVectorAppend(&dvu, (void *)"b "); + SOSDigestVectorAppend(&dvu, (void *)"b "); + SOSDigestVectorAppend(&dvu, (void *)"b "); + SOSDigestVectorAppend(&dvu, (void *)"c "); + SOSDigestVectorAppend(&dvu, (void *)"d "); + SOSDigestVectorAppend(&dvu, (void *)"f "); + SOSDigestVectorAppend(&dvu, (void *)"h "); + + SOSDigestVectorAppend(&dvu, (void *)"c "); + SOSDigestVectorAppend(&dvu, (void *)"d "); + SOSDigestVectorAppend(&dvu, (void *)"e "); + SOSDigestVectorAppend(&dvu, (void *)"f "); + SOSDigestVectorAppend(&dvu, (void *)"g "); + + struct SOSDigestVector dvintersect = SOSDigestVectorInit; + SOSDigestVectorIntersectSorted(&dv1, &dv2, &dvintersect); + CFStringRef desc = dvCopyString(&dvintersect); + ok(CFEqual(CFSTR("df"), desc), "intersection is %@", desc); + CFReleaseNull(desc); + + struct SOSDigestVector dvunion = SOSDigestVectorInit; + SOSDigestVectorUnionSorted(&dv1, &dv2, &dvunion); + desc = dvCopyString(&dvunion); + ok(CFEqual(CFSTR("abcdefgh"), desc), "union is %@", desc); + CFReleaseNull(desc); + + struct SOSDigestVector dvdels = SOSDigestVectorInit; + struct SOSDigestVector dvadds = SOSDigestVectorInit; + SOSDigestVectorDiffSorted(&dv1, &dv2, &dvdels, &dvadds); + desc = dvCopyString(&dvdels); + ok(CFEqual(CFSTR("abh"), desc), "dels is %@", desc); + CFReleaseNull(desc); + desc = dvCopyString(&dvadds); + ok(CFEqual(CFSTR("ceg"), desc), "adds is %@", desc); + CFReleaseNull(desc); + + CFErrorRef localError = NULL; + struct SOSDigestVector dvpatched = SOSDigestVectorInit; + ok(SOSDigestVectorPatch(&dv1, &dvdels, &dvadds, &dvpatched, &localError), "patch : %@", localError); + CFReleaseNull(localError); + desc = dvCopyString(&dvpatched); + ok(CFEqual(CFSTR("cdefg"), desc), "patched dv1 - dels + adds is %@, should be: %@", desc, CFSTR("cdefg")); + CFReleaseNull(desc); + + SOSDigestVectorFree(&dvpatched); + ok(SOSDigestVectorPatch(&dv2, &dvadds, &dvdels, &dvpatched, &localError), "patch : %@", localError); + CFReleaseNull(localError); + desc = dvCopyString(&dvpatched); + ok(CFEqual(CFSTR("abdfh"), desc), "patched dv2 - adds + dels is is %@, should be: %@", desc, CFSTR("abdfh")); + CFReleaseNull(desc); + + SOSDigestVectorAppend(&dvadds, (void *)"c "); + SOSDigestVectorFree(&dvpatched); + SOSDigestVectorUniqueSorted(&dvadds); + ok(SOSDigestVectorPatch(&dv2, &dvadds, &dvdels, &dvpatched, &localError), "patch failed: %@", localError); + CFReleaseNull(localError); + desc = dvCopyString(&dvpatched); + ok(CFEqual(CFSTR("abdfh"), desc), "patched dv2 - adds + dels is is %@, should be: %@", desc, CFSTR("abdfh")); + CFReleaseNull(desc); + + SOSDigestVectorUniqueSorted(&dvu); + desc = dvCopyString(&dvu); + ok(CFEqual(CFSTR("abcdefgh"), desc), "uniqued dvu is %@, should be: %@", desc, CFSTR("abcdefgh")); + CFReleaseNull(desc); + + // This operation should be idempotent + SOSDigestVectorUniqueSorted(&dvu); + desc = dvCopyString(&dvu); + ok(CFEqual(CFSTR("abcdefgh"), desc), "uniqued dvu is %@, should be: %@", desc, CFSTR("abcdefgh")); + CFReleaseNull(desc); +} + +static void tests(void) +{ + testNullDigestVector(); + testIntersectUnionDigestVector(); +} + +int sc_45_digestvector(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/Security/sec/SOSCircle/Regressions/sc-50-message.c b/Security/sec/SOSCircle/Regressions/sc-50-message.c new file mode 100644 index 00000000..7aa347e8 --- /dev/null +++ b/Security/sec/SOSCircle/Regressions/sc-50-message.c @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include + +#include "SOSCircle_regressions.h" + +#include +#include +#include +#include + +static int kTestTestCount = 68; + +static void testNullMessage(uint64_t msgid) +{ + SOSMessageRef sentMessage = NULL; + SOSMessageRef rcvdMessage = NULL; + SOSManifestRef sender = NULL; + CFErrorRef error = NULL; + CFDataRef data = NULL; + + // Encode + ok(sender = SOSManifestCreateWithBytes(NULL, 0, &error), "empty sender manifest create: %@", error); + CFReleaseNull(error); + ok(sentMessage = SOSMessageCreateWithManifests(kCFAllocatorDefault, sender, NULL, NULL, false, &error), "sentMessage create: %@", error); + CFReleaseNull(error); + ok(data = SOSMessageCreateData(sentMessage, msgid, &error), "sentMessage data create: %@", error); + CFReleaseNull(error); + + // Decode + ok(rcvdMessage = SOSMessageCreateWithData(kCFAllocatorDefault, data, &error), "rcvdMessage create: %@", error); + CFReleaseNull(error); + __block size_t numObjects = 0; + SOSMessageWithObjects(sentMessage, &error, ^(CFDataRef object, bool *stop) { + numObjects++; + }); + ok(numObjects == 0, "no objects"); + + // Check if we got what we started with + ok(sentMessage && rcvdMessage && CFEqual(sentMessage, rcvdMessage), "sent %@ == rcvd %@", sentMessage, rcvdMessage); + + CFReleaseNull(data); + CFReleaseNull(sentMessage); + CFReleaseNull(rcvdMessage); + CFReleaseNull(sender); +} + +__unused static void testFlaggedMessage(uint64_t msgid, SOSMessageFlags flags) +{ + SOSMessageRef sentMessage = NULL; + SOSMessageRef rcvdMessage = NULL; + SOSManifestRef sender = NULL; + CFErrorRef error = NULL; + CFDataRef data = NULL; + + ok(sender = SOSManifestCreateWithBytes(NULL, 0, &error), "empty sender manifest create: %@", error); + CFReleaseNull(error); + ok(sentMessage = SOSMessageCreateWithManifests(kCFAllocatorDefault, sender, NULL, NULL, false, &error), "sentMessage create: %@", error); + CFReleaseNull(error); + SOSMessageSetFlags(sentMessage, flags); + ok(data = SOSMessageCreateData(sentMessage, msgid, &error), "sentMessage data create: %@", error); + CFReleaseNull(error); + + // Decode + ok(rcvdMessage = SOSMessageCreateWithData(kCFAllocatorDefault, data, &error), "rcvdMessage create: %@", error); + CFReleaseNull(error); + __block size_t numObjects = 0; + SOSMessageWithObjects(sentMessage, &error, ^(CFDataRef object, bool *stop) { + numObjects++; + }); + ok(numObjects == 0, "no objects"); + + is(SOSMessageGetFlags(sentMessage), flags, "flags match after roundtrip"); + ok(sentMessage && rcvdMessage && CFEqual(sentMessage, rcvdMessage), "sent %@ == rcvd %@", sentMessage, rcvdMessage); + + CFReleaseNull(data); + CFReleaseNull(sentMessage); + CFReleaseNull(rcvdMessage); + CFReleaseNull(sender); +} + +__unused static void testDeltaManifestMessage(uint64_t msgid) +{ + SOSMessageRef sentMessage = NULL; + SOSMessageRef rcvdMessage = NULL; + SOSManifestRef sender = NULL; + SOSManifestRef proposed = NULL; + SOSManifestRef base = NULL; + CFErrorRef error = NULL; + CFDataRef data = NULL; + + struct SOSDigestVector dv = SOSDigestVectorInit; + SOSDigestVectorAppend(&dv, (const uint8_t *)"sha1 hash that is 20 bytes long or so and stuff"); + SOSDigestVectorAppend(&dv, (const uint8_t *)"sha1 hash that was 23 bytes long or so and stuff"); + SOSDigestVectorSort(&dv); + base = SOSManifestCreateWithBytes((const uint8_t *)dv.digest, dv.count * SOSDigestSize, &error); + SOSDigestVectorAppend(&dv, (const uint8_t *)"so much more is good to see here is another one for me"); + SOSDigestVectorAppend(&dv, (const uint8_t *)"sha1 hash that was 23 bytes long or so and stuff!"); + SOSDigestVectorAppend(&dv, (const uint8_t *)"so much for is good to see here is another one for me"); + SOSDigestVectorSort(&dv); + if (msgid) + proposed = SOSManifestCreateWithBytes((const uint8_t *)dv.digest, dv.count * SOSDigestSize, &error); + + CFReleaseNull(error); + ok(sentMessage = SOSMessageCreateWithManifests(kCFAllocatorDefault, proposed, base, proposed, true, &error), "sentMessage create: %@", error); + CFReleaseNull(error); + ok(data = SOSMessageCreateData(sentMessage, msgid, &error), "sentMessage data create: %@ .. %@", error, sentMessage); + CFReleaseNull(error); + + // Decode + ok(rcvdMessage = SOSMessageCreateWithData(kCFAllocatorDefault, data, &error), "rcvdMessage create: %@", error); + CFReleaseNull(error); + __block size_t numObjects = 0; + SOSMessageWithObjects(sentMessage, &error, ^(CFDataRef object, bool *stop) { + numObjects++; + }); + ok(numObjects == 0, "no objects"); + + ok(sentMessage && rcvdMessage && CFEqual(sentMessage, rcvdMessage), "sent %@ == rcvd %@", sentMessage, rcvdMessage); + + CFReleaseNull(data); + CFReleaseNull(sentMessage); + CFReleaseNull(rcvdMessage); + CFReleaseNull(sender); +} + +static CFDataRef testCopyAddedObject(SOSMessageRef message, CFPropertyListRef plist) +{ + CFErrorRef error = NULL; + CFDataRef der; + ok(der = kc_plist_copy_der(plist, &error), "copy der: %@", error); + CFReleaseNull(error); + ok(SOSMessageAppendObject(message, der, &error), "likes object: %@", error); + CFReleaseNull(error); + return der; +} + +__unused static void testObjectsMessage(uint64_t msgid) +{ + SOSMessageRef sentMessage = NULL; + SOSMessageRef rcvdMessage = NULL; + SOSManifestRef sender = NULL; + SOSManifestRef proposed = NULL; + SOSManifestRef base = NULL; + CFErrorRef error = NULL; + CFDataRef data = NULL; + + struct SOSDigestVector dv1 = SOSDigestVectorInit; + struct SOSDigestVector dv2 = SOSDigestVectorInit; + SOSDigestVectorAppend(&dv1, (const uint8_t *)"sha1 hash that is 20 bytes long or so and stuff"); + SOSDigestVectorAppend(&dv2, (const uint8_t *)"sha1 hash that was 23 bytes long or so and stuff"); + SOSDigestVectorAppend(&dv1, (const uint8_t *)"so much more is good to see here is another one for me"); + SOSDigestVectorAppend(&dv2, (const uint8_t *)"so much more is good to see here is another one for me"); + SOSDigestVectorAppend(&dv1, (const uint8_t *)"sha1 hash that was 23 bytes long or so and stuff"); + SOSDigestVectorAppend(&dv1, (const uint8_t *)"sha1 hash that was 23 bytes long or so and stuff!"); + SOSDigestVectorAppend(&dv2, (const uint8_t *)"so much for is good to see here is another one for me"); + SOSDigestVectorSort(&dv1); + SOSDigestVectorSort(&dv2); + base = SOSManifestCreateWithBytes((const uint8_t *)dv1.digest, dv1.count * SOSDigestSize, &error); + if (msgid) + proposed = SOSManifestCreateWithBytes((const uint8_t *)dv2.digest, dv2.count * SOSDigestSize, &error); + CFReleaseNull(error); + ok(sentMessage = SOSMessageCreateWithManifests(kCFAllocatorDefault, proposed, base, proposed, true, &error), "sentMessage create: %@", error); + CFDataRef O0, O1, O2, O3; + CFDataRef o0 = CFDataCreate(kCFAllocatorDefault, NULL, 0); + O0 = testCopyAddedObject(sentMessage, o0); + CFDataRef o1 = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)"test", 4); + O1 = testCopyAddedObject(sentMessage, o1); + CFDataRef o2 = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)"what an object", 14); + O2 = testCopyAddedObject(sentMessage, o2); + CFDataRef o3 = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)"This one even has shiny stripe.", 31); + O3 = testCopyAddedObject(sentMessage, o3); + ok(data = SOSMessageCreateData(sentMessage, msgid, &error), "sentMessage data create: %@ .. %@", error, sentMessage); + CFReleaseNull(error); + + // Decode + ok(rcvdMessage = SOSMessageCreateWithData(kCFAllocatorDefault, data, &error), "rcvdMessage create: %@", error); + CFReleaseNull(error); + __block size_t numObjects = 0; + __block bool f0, f1, f2, f3; + f0 = f1 = f2 = f3 = false; + SOSMessageWithObjects(rcvdMessage, &error, ^(CFDataRef object, bool *stop) { + if (CFEqualSafe(object, O0)) f0 = true; + if (CFEqualSafe(object, O1)) f1 = true; + if (CFEqualSafe(object, O2)) f2 = true; + if (CFEqualSafe(object, O3)) f3 = true; + numObjects++; + }); + ok(f0, "got O0"); + ok(f1, "got O1"); + ok(f2, "got O2"); + ok(f3, "got O3"); + + ok(sentMessage && rcvdMessage && CFEqual(sentMessage, rcvdMessage), "sent %@ == rcvd %@", sentMessage, rcvdMessage); + + CFReleaseNull(o0); + CFReleaseNull(o1); + CFReleaseNull(o2); + CFReleaseNull(o3); + CFReleaseNull(O0); + CFReleaseNull(O1); + CFReleaseNull(O2); + CFReleaseNull(O3); + CFReleaseNull(data); + CFReleaseNull(sentMessage); + CFReleaseNull(rcvdMessage); + CFReleaseNull(sender); +} + +static void tests(void) +{ + + + testNullMessage(0); // v0 + +#if 0 + todo("V2 doesn't work"); + TODO: { + uint64_t msgid = 0; + testNullMessage(++msgid); // v2 + testFlaggedMessage(++msgid, 0x865); + testFlaggedMessage(++msgid, 0xdeadbeef); + testDeltaManifestMessage(0); + testDeltaManifestMessage(++msgid); + testObjectsMessage(0); + testObjectsMessage(++msgid); + } +#endif +} + +int sc_50_message(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/sec/SOSCircle/Regressions/sc-51-persistentEC.c b/Security/sec/SOSCircle/Regressions/sc-51-persistentEC.c similarity index 95% rename from sec/SOSCircle/Regressions/sc-51-persistentEC.c rename to Security/sec/SOSCircle/Regressions/sc-51-persistentEC.c index bfb2e4f9..5bb49134 100644 --- a/sec/SOSCircle/Regressions/sc-51-persistentEC.c +++ b/Security/sec/SOSCircle/Regressions/sc-51-persistentEC.c @@ -2,7 +2,7 @@ * sc-51-persistentEC.c * Security * - * Copyright (c) 2008-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-2010,2012-2014 Apple Inc. All Rights Reserved. * */ @@ -51,7 +51,7 @@ static SecKeyRef GeneratePermanentFullECKey(int keySize, CFStringRef name) static void tests(void) { CFStringRef ourAccountName = CFSTR("LjzZ2JteIrnHoHWf5hYb1WGqjI"); - CFStringRef circleName = CFSTR("ak"); + CFStringRef circleName = kSecAttrAccessibleWhenUnlocked; CFStringRef keyName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("ID for %@-%@"), ourAccountName, circleName); const int keySize = 256; diff --git a/Security/sec/SOSCircle/Regressions/sc-60-peer.c b/Security/sec/SOSCircle/Regressions/sc-60-peer.c new file mode 100644 index 00000000..2b444057 --- /dev/null +++ b/Security/sec/SOSCircle/Regressions/sc-60-peer.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + +#include "SOSCircle_regressions.h" + +#include + +#include + +#include + +#include + +static int kTestTestCount = 13; + +static void tests(void) +{ +#if 0 + const unsigned kSOSPeerVersion = 0; + + CFErrorRef error = NULL; + SOSPeerRef peer; + + /* Create peer test. */ + CFStringRef peer_id = CFSTR("peer 60"); + + __block unsigned msg_count = 0; + uint8_t msg_digest_buffer[CCSHA256_OUTPUT_SIZE]; + uint8_t *msg_digest = msg_digest_buffer; + + SOSPeerSendBlock sendBlock = ^bool (CFDataRef message, CFErrorRef *error) { + size_t msglen = CFDataGetLength(message); + const uint8_t *msg = CFDataGetBytePtr(message); + const struct ccdigest_info *sha256 = ccsha256_di(); + if (msg_count++ == 0) { + /* message n=0 */ + ccdigest(sha256, msglen, msg, msg_digest); + } else { + /* message n=n+1 */ + ccdigest_di_decl(sha256, sha256_ctx); + ccdigest_init(sha256, sha256_ctx); + ccdigest_update(sha256, sha256_ctx, sizeof(msg_digest_buffer), msg_digest); + ccdigest_update(sha256, sha256_ctx, msglen, msg); + ccdigest_final(sha256, sha256_ctx, msg_digest); + } + size_t encmaxlen = SecBase64Encode(msg, msglen, NULL, 0); + CFMutableDataRef encoded = CFDataCreateMutable(NULL, encmaxlen); + CFDataSetLength(encoded, encmaxlen); + SecBase64Result rc; + char *enc = (char *)CFDataGetMutableBytePtr(encoded); +#ifndef NDEBUG + size_t enclen = +#endif + SecBase64Encode2(msg, msglen, + enc, + encmaxlen, kSecB64_F_LINE_LEN_USE_PARAM, + 64, &rc); + assert(enclen < INT32_MAX); + +// printf("=== BEGIN SOSMESSAGE ===\n%.*s\n=== END SOSMESSAGE ===\n", (int)enclen, enc); + + CFRelease(encoded); + return true; + }; + + + ok(peer = SOSPeerCreateSimple(peer_id, kSOSPeerVersion, &error), + "create peer: %@", error); + CFReleaseNull(error); + + /* Send a test message. */ + is((int)msg_count, 0, "no message sent yet"); + size_t msglen = 10; + uint8_t msg[msglen]; + memcpy(msg, "0123456789", msglen); + CFDataRef message = CFDataCreate(NULL, msg, msglen); + ok(SOSPeerSendMessage(peer, message, &error, sendBlock), + "send message to peer: %@", error); + CFReleaseNull(error); + is((int)msg_count, 1, "We sent %d/1 messages", msg_count); + CFRelease(message); + + /* Check the peer's version. */ + is(SOSPeerGetVersion(peer), kSOSPeerVersion, "version is correct"); + + //SOSPeerManifestType mfType = kSOSPeerProposedManifest; + SOSPeerManifestType mfType = kSOSPeerConfirmedManifest; + /* Get the peer's manifest. */ + SOSManifestRef manifest = SOSPeerGetManifest(peer, mfType, &error); + ok(manifest == NULL, "No manifest yet for this peer: %@", error); + CFReleaseNull(error); + + /* Get the peer's manifest digest. */ + CFDataRef digest = SOSManifestGetDigest(manifest, &error); + ok(digest == NULL, "No digest yet for this peer's manifest: %@", error); + CFReleaseNull(error); + + ok(manifest = SOSManifestCreateWithBytes(NULL, 0, &error), "Create empty manifest: %@", error); + CFReleaseNull(error); + ok(SOSPeerSetManifest(peer, mfType, manifest, &error), "Set empty manifest on peer: %@", error); + CFReleaseNull(error); + + /* Get the peer's empty manifest digest. */ + digest = SOSManifestGetDigest(manifest, &error); + ok(digest, "Got a digest: %@ this peer's manifest: %@", digest, error); + CFReleaseNull(error); + + /* Clean up. */ + CFReleaseSafe(peer); + + SOSPeerRef reinflated_peer = NULL; + ok(reinflated_peer = SOSPeerCreateSimple(peer_id, kSOSPeerVersion, &error), + "create peer: %@", error); + CFReleaseNull(error); + + manifest = SOSPeerGetManifest(reinflated_peer, mfType, &error); + ok(manifest != NULL, "Got NULL manifest after reinflate (%@)", error); + CFDataRef digestAfterReinflate = SOSManifestGetDigest(manifest, &error); + ok(digestAfterReinflate != NULL, "Got NULL digest after reinflate (%@)", error); + ok(digestAfterReinflate && CFEqual(digest, digestAfterReinflate), "Compare digest after reinflate, before: %@ after: %@", digest, digestAfterReinflate); + CFReleaseNull(error); + + CFReleaseSafe(reinflated_peer); +#endif +} + +int sc_60_peer(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/sec/SOSCircle/Regressions/sc-70-engine.c b/Security/sec/SOSCircle/Regressions/sc-70-engine.c similarity index 90% rename from sec/SOSCircle/Regressions/sc-70-engine.c rename to Security/sec/SOSCircle/Regressions/sc-70-engine.c index b845e759..59991a9e 100644 --- a/sec/SOSCircle/Regressions/sc-70-engine.c +++ b/Security/sec/SOSCircle/Regressions/sc-70-engine.c @@ -1,11 +1,26 @@ -// -// sc-70-engine.c -// sec -// -// Created by Michael Brouwer on 8/2/12. -// Copyright 2012 Apple Inc. All rights reserved. -// -// +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include #include @@ -19,8 +34,10 @@ #include #include "SOSTestDataSource.h" -#include "SOSTestTransport.h" +#if 1 +static int kTestTestCount = 0; +#else static int kTestTestCount = 61; static void tests(void) @@ -68,7 +85,7 @@ static void tests(void) /* Create peer test. */ CFStringRef peer_id = CFSTR("peer 70"); SOSPeerRef peer; - ok(peer = SOSPeerCreateSimple(peer_id, kSOSPeerVersion, &error, sendBlock), + ok(peer = SOSPeerCreateSimple(peer_id, kSOSPeerVersion, &error), "create peer: %@", error); CFReleaseNull(error); @@ -92,6 +109,8 @@ static void tests(void) message = CFDataCreate(NULL, NULL, 0); ok(false == SOSEngineHandleMessage(engine, peer, message, &error), "handle empty message: %@", error); + ok(false == SOSPeerSendMessageIfNeeded(engine, peer, &error, sendBlock), + "send response: %@", error); CFReleaseNull(error); CFReleaseNull(message); /* Make sure the engine did not yet send a response to the peer. */ @@ -156,7 +175,7 @@ static void tests(void) CFReleaseNull(error); /* Clean up. */ - SOSPeerDispose(peer); + CFReleaseSafe(peer); SOSEngineDispose(engine); } @@ -218,8 +237,6 @@ static void testsync(const char *name, void (^aliceInit)(SOSDataSourceRef ds), v aliceInit(aliceDataSource); bobInit(bobDataSource); - /* Start syncing by making alice send the first message. */ - ok(SOSEngineSyncWithPeer(aliceEngine, bobPeer, false, &error), "tell Alice sync with peer Bob"); CFDataRef message; va_list msgs; @@ -232,28 +249,26 @@ static void testsync(const char *name, void (^aliceInit)(SOSDataSourceRef ds), v msg_index++; /* We are expecting a message and msg is it's digest. */ if (message) { - CFStringRef messageDesc = SOSMessageCopyDescription(message); CFStringRef messageDigestStr = SOSMessageCopyDigestHex(message); if (msg) { bool handeled = SOSEngineHandleMessage(alice ? aliceEngine : bobEngine, alice ? bobPeer : alicePeer, message, &error); if (!CFEqual(messageDigestStr, msg)) { if (handeled) { - fail("%s %s received message [%d] digest %@ != %@ %@", name, alice ? "Alice" : "Bob", msg_index, messageDigestStr, msg, messageDesc); + fail("%s %s received message [%d] digest %@ != %@ %@", name, alice ? "Alice" : "Bob", msg_index, messageDigestStr, msg, message); } else { - fail("%s %s failed to handle message [%d] digest %@ != %@ %@: %@", name, alice ? "Alice" : "Bob", msg_index, messageDigestStr, msg, messageDesc, error); + fail("%s %s failed to handle message [%d] digest %@ != %@ %@: %@", name, alice ? "Alice" : "Bob", msg_index, messageDigestStr, msg, message, error); CFReleaseNull(error); } } else if (handeled) { - pass("%s %s handled message [%d] %@", name, alice ? "Alice" : "Bob", msg_index, messageDesc); + pass("%s %s handled message [%d] %@", name, alice ? "Alice" : "Bob", msg_index, message); } else { - fail("%s %s failed to handle message [%d] %@: %@", name, alice ? "Alice" : "Bob", msg_index, messageDesc, error); + fail("%s %s failed to handle message [%d] %@: %@", name, alice ? "Alice" : "Bob", msg_index, message, error); CFReleaseNull(error); } } else { - fail("%s %s sent extra message [%d] with digest %@: %@", name, alice ? "Bob" : "Alice", msg_index, messageDigestStr, messageDesc); + fail("%s %s sent extra message [%d] with digest %@: %@", name, alice ? "Bob" : "Alice", msg_index, messageDigestStr, message); } CFRelease(messageDigestStr); - CFRelease(messageDesc); CFRelease(message); } else { if (msg) { @@ -273,15 +288,19 @@ static void testsync(const char *name, void (^aliceInit)(SOSDataSourceRef ds), v va_end(msgs); + + + SOSEngineDispose(aliceEngine); // Also disposes aliceDataSource - SOSPeerDispose(alicePeer); + CFReleaseSafe(alicePeer); CFReleaseSafe(aliceID); SOSEngineDispose(bobEngine); // Also disposes bobDataSource - SOSPeerDispose(bobPeer); + CFReleaseSafe(bobPeer); CFReleaseSafe(bobID); } +#if 0 static void synctests(void) { // Sync between 2 empty dataSources testsync("empty", @@ -356,13 +375,17 @@ static void synctests(void) { NULL); } +#endif + +#endif int sc_70_engine(int argc, char *const *argv) { plan_tests(kTestTestCount); - tests(); - synctests(); + //tests(); + //synctests(); + //testsync(NULL, NULL, NULL, NULL); return 0; } diff --git a/Security/sec/SOSCircle/Regressions/sc-75-circle-engine.c b/Security/sec/SOSCircle/Regressions/sc-75-circle-engine.c new file mode 100644 index 00000000..df4879ba --- /dev/null +++ b/Security/sec/SOSCircle/Regressions/sc-75-circle-engine.c @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include + +#include "SOSCircle_regressions.h" + +#include + +#include + +#include + +#include + +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "SOSCircle_regressions.h" +#include "SOSRegressionUtilities.h" +#include "SOSTestDataSource.h" + +#include +#include + +#ifndef SEC_CONST_DECL +#define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); +#endif + +#include + + +// MARK: ----- Constants ----- + +static CFStringRef circleKey = CFSTR("Circle"); + +static int kTestTestCount = 68; + +static bool withEngine(SOSCircleRef circle, SOSDataSourceFactoryRef factory, bool readOnly, CFErrorRef *error, bool (^action)(SOSEngineRef engine, CFErrorRef *block_error)) { + bool success = false; + SOSDataSourceRef ds = NULL; + SOSEngineRef engine = NULL; + + ds = factory->create_datasource(factory, SOSCircleGetName(circle), error); + require_quiet(ds, exit); + + engine = SOSEngineCreate(ds, error); // Hand off DS to engine. + ds = NULL; + require_quiet(engine, exit); + + success = action(engine, error); + +exit: + if (engine) + SOSEngineDispose(engine); + + return success; +} + +static bool SOSCircleSyncWithPeer(SOSAccountRef account ,SOSFullPeerInfoRef myRef, SOSCircleRef circle, SOSDataSourceFactoryRef factory, + SOSPeerInfoRef peerInfo, CFErrorRef *error) +{ + return withEngine(circle, factory, true, error, ^bool(SOSEngineRef engine, CFErrorRef *block_error) { + SOSPeerRef peer = SOSPeerCreate(engine, peerInfo, block_error); + if (!peer) return false; + + CFMutableDictionaryRef circleToPeerIDs = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFMutableArrayRef peer_ids = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFArrayAppendValue(peer_ids, SOSPeerGetID(peer)); + CFDictionaryAddValue(circleToPeerIDs, SOSCircleGetName(circle), peer_ids); + + SOSTransportMessageRef transport = (SOSTransportMessageRef)CFDictionaryGetValue(SOSAccountGetMessageTransports(account), SOSCircleGetName(circle)); + + bool result = SOSTransportMessageSyncWithPeers(transport, circleToPeerIDs, error); + CFReleaseSafe(peer); + return result; + }); +} + +static bool SOSCircleHandlePeerMessage(SOSAccountRef account, SOSCircleRef circle, SOSFullPeerInfoRef myRef, SOSDataSourceFactoryRef factory, + SOSPeerInfoRef peerInfo, CFDataRef message, CFErrorRef *error) { + + return withEngine(circle, factory, true, error, ^bool(SOSEngineRef engine, CFErrorRef *block_error) { + CFDataRef decodedMessage = NULL; + SOSPeerRef peer = SOSPeerCreate(engine, peerInfo, block_error); + if (!peer) return false; + CFDictionaryRef message_transports = (CFDictionaryRef)SOSAccountGetMessageTransports(account); + SOSTransportMessageRef transport = (SOSTransportMessageRef)CFDictionaryGetValue(message_transports, SOSCircleGetName(circle)); + bool result = SOSTransportMessageHandlePeerMessage(transport, SOSPeerGetID(peer), message, error); + + CFReleaseSafe(peer); + CFReleaseNull(decodedMessage); + return result; + }); +} + + + +static void tests() +{ + CFErrorRef error = NULL; + + CFStringRef aliceID = CFSTR("Alice"); + CFStringRef bobID = CFSTR("Bob"); // not really remote, just another client on same machine + + SecKeyRef alice_key = NULL; + SecKeyRef bob_key = NULL; + + CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); + + CFDataRef parameters = SOSUserKeyCreateGenerateParameters(&error); + ok(parameters, "No parameters!"); + ok(error == NULL, "Error: (%@)", error); + CFReleaseNull(error); + + SecKeyRef user_privkey = SOSUserKeygen(cfpassword, parameters, &error); + CFReleaseNull(parameters); + CFReleaseSafe(cfpassword); + + CFStringRef circleName = CFSTR("Woot Circle"); + SOSAccountRef alice_account = CreateAccountForLocalChanges(CFSTR("Alice"), circleName); + SOSAccountRef bob_account = CreateAccountForLocalChanges(CFSTR("Bob"), circleName); + + + SOSFullPeerInfoRef alice_full_peer_info = SOSCreateFullPeerInfoFromName(aliceID, &alice_key, &error); + SOSPeerInfoRef alice_peer_info = SOSFullPeerInfoGetPeerInfo(alice_full_peer_info); + + SOSFullPeerInfoRef bob_full_peer_info = SOSCreateFullPeerInfoFromName(bobID, &bob_key, &error); + SOSPeerInfoRef bob_peer_info = SOSFullPeerInfoGetPeerInfo(bob_full_peer_info); + + SOSCircleRef aliceCircle = SOSCircleCreate(kCFAllocatorDefault, circleName, &error); + + ok(SOSCircleRequestAdmission(aliceCircle, user_privkey, alice_full_peer_info, &error)); + ok(SOSCircleAcceptRequests(aliceCircle, user_privkey, alice_full_peer_info, NULL)); + ok(SOSCircleRequestAdmission(aliceCircle, user_privkey, bob_full_peer_info, &error), "requested admission"); + ok(SOSCircleAcceptRequests(aliceCircle, user_privkey, bob_full_peer_info, &error), "accepted them all!"); + + alice_peer_info = SOSFullPeerInfoGetPeerInfo(alice_full_peer_info); + bob_peer_info = SOSFullPeerInfoGetPeerInfo(bob_full_peer_info); + + CFDataRef aliceCircleEncoded; + ok(aliceCircleEncoded = SOSCircleCopyEncodedData(aliceCircle, kCFAllocatorDefault, &error), "encode alice circle: %@", error); + CFReleaseNull(error); + SOSCircleRef bobCircle; + ok(bobCircle = SOSCircleCreateFromData(0, aliceCircleEncoded, &error), "decode bobCircle: %@", error); + CFReleaseNull(aliceCircleEncoded); + CFReleaseNull(error); + + SOSTransportMessageRef alice_message_transport = (SOSTransportMessageRef)CFDictionaryGetValue(SOSAccountGetMessageTransports(alice_account), circleName); + SOSTransportMessageRef bob_message_transport = (SOSTransportMessageRef)CFDictionaryGetValue(bob_account->message_transports, circleName); + + ok(SOSPeerCoderInitializeForPeer(alice_message_transport, alice_full_peer_info, bob_peer_info, NULL)); + ok(SOSPeerCoderInitializeForPeer(bob_message_transport, bob_full_peer_info, alice_peer_info, NULL)); + + SOSDataSourceFactoryRef aliceDsf = alice_account->factory; + SOSDataSourceFactoryRef bobDsf = bob_account->factory; + + /* Test passing peer messages to the engine. */ + CFDataRef message; + + ok(SOSCircleSyncWithPeer(alice_account, alice_full_peer_info, aliceCircle, aliceDsf, bob_peer_info, &error), "Start sync [error %@]", error); + CFReleaseNull(error); + + ok(CFDictionaryGetCount(SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)alice_message_transport)) != 0, "Alice sent message"); + CFDictionaryRef changes = SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)alice_message_transport); + CFDictionaryRef peer_dict = CFDictionaryGetValue(changes, circleName); + message = CFDictionaryGetValue(peer_dict, SOSPeerInfoGetPeerID(bob_peer_info)); + is(SOSCircleHandlePeerMessage(bob_account, bobCircle, bob_full_peer_info, bobDsf, alice_peer_info, message, &error), true, + "Bob accepted message: %@", error); + + is(SOSCircleSyncWithPeer(bob_account, bob_full_peer_info, bobCircle, bobDsf, alice_peer_info, &error), true, "Bob sent response"); + CFReleaseNull(error); + +#if 1 + ok(CFDictionaryGetCount(SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)bob_message_transport)) != 0, "we got a message from Bob"); + changes = SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)bob_message_transport); + peer_dict = CFDictionaryGetValue(changes, circleName); + message = CFDictionaryGetValue(peer_dict, SOSPeerInfoGetPeerID(alice_peer_info)); + + ok(SOSCircleHandlePeerMessage(alice_account, aliceCircle, alice_full_peer_info, aliceDsf, bob_peer_info, message, &error), + "Alice accepted message: %@", error); + + ok(CFDictionaryGetCount(SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)alice_message_transport)) != 0, "we got a reply from Alice"); + changes = SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)alice_message_transport); + peer_dict = CFDictionaryGetValue(changes, circleName); + message = CFDictionaryGetValue(peer_dict, SOSPeerInfoGetPeerID(bob_peer_info)); + ok(SOSCircleHandlePeerMessage(bob_account, bobCircle, bob_full_peer_info, bobDsf, alice_peer_info, message, &error), + "Bob accepted message: %@", error); +#endif + +#if 0 + SOSDataSourceRef aliceDs = aliceDsf->create_datasource(aliceDsf, circleName, NULL); + ok(CFDictionaryGetCount(SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)bob_message_transport)) == 0, "we got no message from Bob"); + + SOSObjectRef object = SOSDataSourceCreateGenericItem(aliceDs, CFSTR("75_circle_engine_account"), CFSTR("test service")); + ok(SOSTestDataSourceAddObject(aliceDs, object, &error), "add empty object to datasource: %@", error); + CFReleaseNull(error); + CFReleaseNull(object); + + ok(SOSCircleSyncWithPeer(alice_account, alice_full_peer_info, aliceCircle, aliceDsf, bob_peer_info, &error), "Restart sync [error %@]", error); + CFReleaseNull(error); + + ok(CFDictionaryGetCount(SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)alice_message_transport)) != 0, "Alice started again"); + changes = SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)alice_message_transport); + peer_dict = CFDictionaryGetValue(changes, circleName); + message = CFDictionaryGetValue(peer_dict, SOSPeerInfoGetPeerID(bob_peer_info)); + + is(SOSCircleHandlePeerMessage(bob_account, bobCircle, bob_full_peer_info, bobDsf, alice_peer_info, message, &error), true, + "bob accepted %@", message); + CFReleaseNull(error); +#endif + +#if 1 + bool alice = true; + int max_loops = 50; + changes = SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)alice_message_transport); + while (max_loops-- && (CFDictionaryGetCount(changes) != 0)) { + peer_dict = CFDictionaryGetValue(changes, circleName); + message = CFDictionaryGetValue(peer_dict, SOSPeerInfoGetPeerID(bob_peer_info)); + if (alice) { + ok(SOSCircleHandlePeerMessage(alice_account, aliceCircle, alice_full_peer_info, aliceDsf, bob_peer_info, message, &error), + "alice accepted %@: %@", message, error); + } else { + ok(SOSCircleHandlePeerMessage(bob_account, bobCircle, bob_full_peer_info, bobDsf, alice_peer_info, message, &error), + "bob accepted %@: %@", message, error); + } + alice = !alice; + } +#endif + + CFReleaseNull(aliceCircle); + CFReleaseNull(bobCircle); + + CFReleaseNull(alice_peer_info); + CFReleaseNull(bob_peer_info); + + aliceDsf->release(aliceDsf); + bobDsf->release(bobDsf); + + SOSUnregisterAllTransportMessages(); + SOSUnregisterAllTransportCircles(); + SOSUnregisterAllTransportKeyParameters(); + CFArrayRemoveAllValues(key_transports); + CFArrayRemoveAllValues(circle_transports); + CFArrayRemoveAllValues(message_transports); +} + +// MARK: ----- start of all tests ----- + +int sc_75_circle_engine(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/sec/SOSCircle/Regressions/sc-90-ckdclient.c b/Security/sec/SOSCircle/Regressions/sc-90-ckdclient.c similarity index 85% rename from sec/SOSCircle/Regressions/sc-90-ckdclient.c rename to Security/sec/SOSCircle/Regressions/sc-90-ckdclient.c index ed56ca43..65a0676c 100644 --- a/sec/SOSCircle/Regressions/sc-90-ckdclient.c +++ b/Security/sec/SOSCircle/Regressions/sc-90-ckdclient.c @@ -1,10 +1,26 @@ -// -// sc-90-ckdclient.c -// sec -// -// Created by John Hurley on 9/6/12. -// -// +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include @@ -111,7 +127,7 @@ static bool postIDTimestamp(dispatch_queue_t theq, dispatch_group_t dgroup) } -static const int kbasicKVSTestsCount = 10; +static const int kbasicKVSTestsCount = 9; static void basicKVSTests(dispatch_group_t dgroup) { dispatch_queue_t generalq = dispatch_queue_create("general", DISPATCH_QUEUE_SERIAL); @@ -136,8 +152,7 @@ static void basicKVSTests(dispatch_group_t dgroup) ok(testPostGet(kTestKeyString, CFSTR("test string"), generalq, dgroup), "testPostGet for CFStringRef"); ok(testPostGet(kTestKeyData, testData, generalq, dgroup), "testPostGet for CFDataRef"); ok(testPostGet(kTestKeyArray, testArray, generalq, dgroup), "testPostGet for CFDataRef"); - ok(testRegisterKeys(circleKeys, generalq, dgroup), "test register keys"); - + ok(postIDTimestamp(generalq, dgroup), "testPostGet for %@", kTestKeyIDTimestamp); // Synchronize one more time before exit diff --git a/sec/SOSCircle/Regressions/sc-95-ckd2client.c b/Security/sec/SOSCircle/Regressions/sc-95-ckd2client.c similarity index 82% rename from sec/SOSCircle/Regressions/sc-95-ckd2client.c rename to Security/sec/SOSCircle/Regressions/sc-95-ckd2client.c index aea9fd43..60815f12 100644 --- a/sec/SOSCircle/Regressions/sc-95-ckd2client.c +++ b/Security/sec/SOSCircle/Regressions/sc-95-ckd2client.c @@ -1,10 +1,26 @@ -// -// sc-90-ckdclient.c -// sec -// -// Created by John Hurley on 9/6/12. -// -// +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include diff --git a/sec/SOSCircle/Regressions/sc-kvstool.m b/Security/sec/SOSCircle/Regressions/sc-kvstool.m similarity index 90% rename from sec/SOSCircle/Regressions/sc-kvstool.m rename to Security/sec/SOSCircle/Regressions/sc-kvstool.m index f5789706..63660dee 100644 --- a/sec/SOSCircle/Regressions/sc-kvstool.m +++ b/Security/sec/SOSCircle/Regressions/sc-kvstool.m @@ -1,10 +1,26 @@ -// -// sc-kvstool.c -// sec -// -// Created by John Hurley 11/01/12. -// Copyright 2012 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + // Run on a device: @@ -158,11 +174,11 @@ static void dumpCircleInfo() CFArrayRef peerInfos = NULL; int idx; - NSArray *ccmsgs = @[@"ParamErr", @"Error", @"InCircle", @"NotInCircle", @"RequestPending", @"CircleAbsent" ]; + NSArray *ccmsgs = @[@"Error", @"InCircle", @"NotInCircle", @"RequestPending", @"CircleAbsent"]; SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(&error); pass("ccstatus: %d, error: %@", ccstatus, error); - idx = ccstatus-kSOSCCParamErr; + idx = ccstatus-kSOSCCError; if (0<=idx && idx<(int)[ccmsgs count]) pass("ccstatus: %d (%@)", ccstatus, ccmsgs[idx]); diff --git a/Security/sec/SOSCircle/SOSARCDefines.h b/Security/sec/SOSCircle/SOSARCDefines.h new file mode 100644 index 00000000..53bb76c6 --- /dev/null +++ b/Security/sec/SOSCircle/SOSARCDefines.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef sec_SOSARCDefines_h +#define sec_SOSARCDefines_h + +#ifndef __has_feature +#define __has_feature(x) 0 +#endif +#ifndef __has_extension +#define __has_extension __has_feature // Compatibility with pre-3.0 compilers. +#endif + +#if __has_feature(objc_arc) && __clang_major__ >= 3 +#define ARC_ENABLED 1 +#endif // __has_feature(objc_arc) + +#if !ARC_ENABLED || !defined(__clang__) || __clang_major__ < 3 + +#ifndef __bridge +#define __bridge +#endif +#ifndef __bridge_retained +#define __bridge_retained +#endif +#ifndef __bridge_transfer +#define __bridge_transfer +#endif +#ifndef __autoreleasing +#define __autoreleasing +#endif +#ifndef __strong +#define __strong +#endif +#ifndef __weak +#define __weak +#endif +#ifndef __unsafe_unretained +#define __unsafe_unretained +#endif + +#endif // __clang_major__ < 3 + +#endif diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSAccount.c b/Security/sec/SOSCircle/SecureObjectSync/SOSAccount.c new file mode 100644 index 00000000..4a601f47 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSAccount.c @@ -0,0 +1,1026 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + */ + +/* + * SOSAccount.c - Implementation of the secure object syncing account. + * An account contains a SOSCircle for each protection domain synced. + */ + +#include "SOSAccountPriv.h" +#include +#include +#include +#include +#include +#include +#include +#include + +CFGiblisWithCompareFor(SOSAccount); + + +bool SOSAccountEnsureFactoryCircles(SOSAccountRef a) +{ + bool result = false; + if (a) + { + require(a->factory, xit); + CFArrayRef circle_names = a->factory->copy_names(a->factory); + require(circle_names, xit); + CFArrayForEach(circle_names, ^(const void*name) { + if (isString(name)) + SOSAccountEnsureCircle(a, (CFStringRef)name, NULL); + }); + + CFReleaseNull(circle_names); + result = true; + } +xit: + return result; +} + + +SOSAccountRef SOSAccountCreateBasic(CFAllocatorRef allocator, + CFDictionaryRef gestalt, + SOSDataSourceFactoryRef factory) { + SOSAccountRef a = CFTypeAllocate(SOSAccount, struct __OpaqueSOSAccount, allocator); + + a->queue = dispatch_queue_create("Account Queue", DISPATCH_QUEUE_SERIAL); + + a->gestalt = CFRetainSafe(gestalt); + + a->circles = CFDictionaryCreateMutableForCFTypes(allocator); + a->circle_identities = CFDictionaryCreateMutableForCFTypes(allocator); + + a->factory = factory; // We adopt the factory. kthanksbai. + + a->change_blocks = CFArrayCreateMutableForCFTypes(allocator); + + a->departure_code = kSOSNeverAppliedToCircle; + + a->key_transport = (SOSTransportKeyParameterRef)SOSTransportKeyParameterKVSCreate(a, NULL); + a->circle_transports = CFDictionaryCreateMutableForCFTypes(allocator); + a->message_transports = CFDictionaryCreateMutableForCFTypes(allocator); + + return a; +} + + + + +bool SOSAccountUpdateGestalt(SOSAccountRef account, CFDictionaryRef new_gestalt) +{ + if (CFEqual(new_gestalt, account->gestalt)) + return false; + SOSAccountForEachKnownCircle(account, NULL, NULL, ^(SOSCircleRef circle, SOSFullPeerInfoRef full_peer) { + if (SOSFullPeerInfoUpdateGestalt(full_peer, new_gestalt, NULL)) { + SOSAccountModifyCircle(account, SOSCircleGetName(circle), + NULL, ^(SOSCircleRef circle_to_change) { + return SOSCircleUpdatePeerInfo(circle_to_change, SOSFullPeerInfoGetPeerInfo(full_peer)); + }); + }; + }); + + CFRetainAssign(account->gestalt, new_gestalt); + return true; +} + +SOSAccountRef SOSAccountCreate(CFAllocatorRef allocator, + CFDictionaryRef gestalt, + SOSDataSourceFactoryRef factory) { + SOSAccountRef a = SOSAccountCreateBasic(allocator, gestalt, factory); + + a->retired_peers = CFDictionaryCreateMutableForCFTypes(allocator); + + SOSAccountEnsureFactoryCircles(a); + + return a; +} + +static void SOSAccountDestroy(CFTypeRef aObj) { + SOSAccountRef a = (SOSAccountRef) aObj; + + // We don't own the factory, meerly have a reference to the singleton + // don't free it. + // a->factory + + CFReleaseNull(a->gestalt); + CFReleaseNull(a->circle_identities); + CFReleaseNull(a->circles); + CFReleaseNull(a->retired_peers); + + a->user_public_trusted = false; + CFReleaseNull(a->user_public); + CFReleaseNull(a->user_key_parameters); + + SOSAccountPurgePrivateCredential(a); + CFReleaseNull(a->previous_public); + + a->departure_code = kSOSNeverAppliedToCircle; + CFReleaseNull(a->message_transports); + CFReleaseNull(a->key_transport); + CFReleaseNull(a->circle_transports); + dispatch_release(a->queue); +} + +void SOSAccountSetToNew(SOSAccountRef a) { + CFAllocatorRef allocator = CFGetAllocator(a); + CFReleaseNull(a->circle_identities); + CFReleaseNull(a->circles); + CFReleaseNull(a->retired_peers); + + CFReleaseNull(a->user_key_parameters); + CFReleaseNull(a->user_public); + CFReleaseNull(a->previous_public); + CFReleaseNull(a->_user_private); + + CFReleaseNull(a->key_transport); + CFReleaseNull(a->circle_transports); + CFReleaseNull(a->message_transports); + + a->user_public_trusted = false; + a->departure_code = kSOSNeverAppliedToCircle; + a->user_private_timer = 0; + a->lock_notification_token = 0; + + // keeping gestalt; + // keeping factory; + // Live Notification + // change_blocks; + // update_interest_block; + // update_block; + + a->circles = CFDictionaryCreateMutableForCFTypes(allocator); + a->circle_identities = CFDictionaryCreateMutableForCFTypes(allocator); + a->retired_peers = CFDictionaryCreateMutableForCFTypes(allocator); + + a->key_transport = (SOSTransportKeyParameterRef)SOSTransportKeyParameterKVSCreate(a, NULL); + a->circle_transports = (CFMutableDictionaryRef)CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + a->message_transports = (CFMutableDictionaryRef)CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + + SOSAccountEnsureFactoryCircles(a); +} + + +static CFStringRef SOSAccountCopyDescription(CFTypeRef aObj) { + SOSAccountRef a = (SOSAccountRef) aObj; + + return CFStringCreateWithFormat(NULL, NULL, CFSTR(""), a, a->gestalt, a->circles, a->circle_identities); +} + +static Boolean SOSAccountCompare(CFTypeRef lhs, CFTypeRef rhs) +{ + SOSAccountRef laccount = (SOSAccountRef) lhs; + SOSAccountRef raccount = (SOSAccountRef) rhs; + + return CFEqual(laccount->gestalt, raccount->gestalt) + && CFEqual(laccount->circles, raccount->circles) + && CFEqual(laccount->circle_identities, raccount->circle_identities); + // ??? retired_peers +} + +dispatch_queue_t SOSAccountGetQueue(SOSAccountRef account) { + return account->queue; +} + +CFDictionaryRef SOSAccountGetMessageTransports(SOSAccountRef account){ + return account->message_transports; +} + + +void SOSAccountSetUserPublicTrustedForTesting(SOSAccountRef account){ + account->user_public_trusted = true; +} + +CFArrayRef SOSAccountCopyAccountIdentityPeerInfos(SOSAccountRef account, CFAllocatorRef allocator, CFErrorRef* error) +{ + CFMutableArrayRef result = CFArrayCreateMutableForCFTypes(allocator); + + CFDictionaryForEach(account->circle_identities, ^(const void *key, const void *value) { + SOSFullPeerInfoRef fpi = (SOSFullPeerInfoRef) value; + + CFArrayAppendValue(result, SOSFullPeerInfoGetPeerInfo(fpi)); + }); + + return result; +} + +static bool SOSAccountThisDeviceCanSyncWithCircle(SOSAccountRef account, SOSCircleRef circle) { + CFErrorRef error = NULL; + SOSFullPeerInfoRef myfpi = SOSAccountGetMyFullPeerInCircleNamedIfPresent(account, SOSCircleGetName(circle), &error); + SOSPeerInfoRef mypi = SOSFullPeerInfoGetPeerInfo(myfpi); + CFStringRef myPeerID = SOSPeerInfoGetPeerID(mypi); + return SOSCircleHasPeerWithID(circle, myPeerID, &error); +} + +static bool SOSAccountIsThisPeerIDMe(SOSAccountRef account, CFStringRef circleName, CFStringRef peerID) { + CFErrorRef error = NULL; + SOSFullPeerInfoRef myfpi = SOSAccountGetMyFullPeerInCircleNamedIfPresent(account, circleName, &error); + if (!myfpi) { + return false; + } + SOSPeerInfoRef mypi = SOSFullPeerInfoGetPeerInfo(myfpi); + CFStringRef myPeerID = SOSPeerInfoGetPeerID(mypi); + return CFEqualSafe(myPeerID, peerID); +} + +bool SOSAccountSyncWithAllPeers(SOSAccountRef account, CFErrorRef *error) +{ + __block bool result = true; + + SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { + + if (SOSAccountThisDeviceCanSyncWithCircle(account, circle)) { + CFStringRef circleName = SOSCircleGetName(circle); + SOSTransportMessageRef thisPeerTransport = (SOSTransportMessageRef)CFDictionaryGetValue(account->message_transports, SOSCircleGetName(circle)); +; + CFMutableDictionaryRef circleToPeerIDs = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + + SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { + // Figure out transport for peer; for now we always use KVS + CFStringRef peerID = SOSPeerInfoGetPeerID(peer); + if (!SOSAccountIsThisPeerIDMe(account, circleName, peerID)) { + CFArrayAppendValue(CFDictionaryEnsureCFArrayAndGetCurrentValue(circleToPeerIDs, circleName), peerID); + } + }); + + result &= SOSTransportMessageSyncWithPeers(thisPeerTransport, circleToPeerIDs, error); + + CFReleaseNull(circleToPeerIDs); + } + }); + + // Tell each transport to sync with its collection of peers we know we should sync with. + + + if (result) + SetCloudKeychainTraceValueForKey(kCloudKeychainNumberOfTimesSyncedWithPeers, 1); + + + return result; +} + +bool SOSAccountCleanupAfterPeer(SOSAccountRef account, size_t seconds, SOSCircleRef circle, + SOSPeerInfoRef cleanupPeer, CFErrorRef* error) +{ + bool success = false; + if(!SOSAccountIsMyPeerActiveInCircle(account, circle, NULL)) return true; + + SOSPeerInfoRef myPeerInfo = SOSAccountGetMyPeerInCircle(account, circle, error); + require(myPeerInfo, xit); + + CFStringRef cleanupPeerID = SOSPeerInfoGetPeerID(cleanupPeer); + CFStringRef circle_name = SOSCircleGetName(circle); + + if (CFEqual(cleanupPeerID, SOSPeerInfoGetPeerID(myPeerInfo))) { + CFErrorRef destroyError = NULL; + if (!SOSAccountDestroyCirclePeerInfo(account, circle, &destroyError)) { + secerror("Unable to destroy peer info: %@", destroyError); + } + CFReleaseSafe(destroyError); + + account->departure_code = kSOSWithdrewMembership; + + return true; + } + + CFMutableDictionaryRef circleToPeerIDs = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFArrayAppendValue(CFDictionaryEnsureCFArrayAndGetCurrentValue(circleToPeerIDs, circle_name), cleanupPeerID); + + + CFErrorRef localError = NULL; + SOSTransportMessageRef tMessage = (SOSTransportMessageRef)CFDictionaryGetValue(account->message_transports, SOSCircleGetName(circle)); + if (!SOSTransportMessageCleanupAfterPeerMessages(tMessage, circleToPeerIDs, &localError)) { + secnotice("account", "Failed to cleanup after peer %@ messages: %@", cleanupPeerID, localError); + } + CFReleaseNull(localError); + SOSTransportCircleRef tCircle = (SOSTransportCircleRef)CFDictionaryGetValue(account->circle_transports, SOSCircleGetName(circle)); + if(SOSPeerInfoRetireRetirementTicket(seconds, cleanupPeer)) { + if (!SOSTransportCircleExpireRetirementRecords(tCircle, circleToPeerIDs, &localError)) { + secnotice("account", "Failed to cleanup after peer %@ retirement: %@", cleanupPeerID, localError); + } + } + CFReleaseNull(localError); + + CFReleaseNull(circleToPeerIDs); + +xit: + return success; +} + +bool SOSAccountCleanupRetirementTickets(SOSAccountRef account, size_t seconds, CFErrorRef* error) { + CFMutableDictionaryRef retirements_to_remove = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionaryRef original_retired_peers = account->retired_peers; + __block bool success = true; + account->retired_peers = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + + CFDictionaryForEach(original_retired_peers, ^(const void *key, const void *value) { + if (isString(key) && isDictionary(value)) { + CFStringRef circle_name = key; + __block CFMutableDictionaryRef still_active_circle_retirements = NULL; + CFDictionaryForEach((CFMutableDictionaryRef) value, ^(const void *key, const void *value) { + if (isString(key) && isData(value)) { + CFStringRef retired_peer_id = (CFStringRef) key; + SOSPeerInfoRef retired_peer = SOSPeerInfoCreateFromData(kCFAllocatorDefault, NULL, (CFDataRef) value); + if (retired_peer && SOSPeerInfoIsRetirementTicket(retired_peer) && CFEqual(retired_peer_id, SOSPeerInfoGetPeerID(retired_peer))) { + // He's a retired peer all right, if he's active or not yet expired we keep a record of his retirement. + // if not, clear any recordings of his retirement from our transport. + if (SOSAccountIsActivePeerInCircleNamed(account, circle_name, retired_peer_id, NULL) || + !SOSPeerInfoRetireRetirementTicket(seconds, retired_peer)) { + // He's still around or not expired. Keep record. + if (still_active_circle_retirements == NULL) { + still_active_circle_retirements = CFDictionaryEnsureCFDictionaryAndGetCurrentValue(account->retired_peers, circle_name); + } + CFDictionarySetValue(still_active_circle_retirements, retired_peer_id, value); + } else { + CFMutableArrayRef retirements = CFDictionaryEnsureCFArrayAndGetCurrentValue(retirements_to_remove, circle_name); + CFArrayAppendValue(retirements, retired_peer_id); + } + } + CFReleaseNull(retired_peer); + } + }); + + SOSTransportCircleRef tCircle = (SOSTransportCircleRef)CFDictionaryGetValue(account->circle_transports, circle_name); + success &= SOSTransportCircleExpireRetirementRecords(tCircle, retirements_to_remove, error); + } + }); + + CFReleaseNull(original_retired_peers); + CFReleaseNull(retirements_to_remove); + + return success; +} + +bool SOSAccountScanForRetired(SOSAccountRef account, SOSCircleRef circle, CFErrorRef *error) { + __block CFMutableDictionaryRef circle_retirees = (CFMutableDictionaryRef) CFDictionaryGetValue(account->retired_peers, SOSCircleGetName(circle)); + + SOSCircleForEachRetiredPeer(circle, ^(SOSPeerInfoRef peer) { + CFStringRef peer_id = SOSPeerInfoGetPeerID(peer); + if(!circle_retirees || !CFDictionaryGetValueIfPresent(circle_retirees, peer_id, NULL)) { + if (!circle_retirees) { + circle_retirees = CFDictionaryEnsureCFDictionaryAndGetCurrentValue(account->retired_peers, SOSCircleGetName(circle)); + } + CFDataRef value = SOSPeerInfoCopyEncodedData(peer, NULL, NULL); + if(value) { + CFDictionarySetValue(circle_retirees, peer_id, value); + SOSAccountCleanupAfterPeer(account, RETIREMENT_FINALIZATION_SECONDS, circle, peer, error); + } + CFReleaseSafe(value); + } + }); + return true; +} + +SOSCircleRef SOSAccountCloneCircleWithRetirement(SOSAccountRef account, SOSCircleRef starting_circle, CFErrorRef *error) { + CFStringRef circle_to_mod = SOSCircleGetName(starting_circle); + + SOSCircleRef new_circle = SOSCircleCopyCircle(NULL, starting_circle, error); + if(!new_circle) return NULL; + + CFDictionaryRef circle_retirements = CFDictionaryGetValue(account->retired_peers, circle_to_mod); + + if (isDictionary(circle_retirements)) { + CFDictionaryForEach(circle_retirements, ^(const void* id, const void* value) { + if (isData(value)) { + SOSPeerInfoRef pi = SOSPeerInfoCreateFromData(NULL, error, (CFDataRef) value); + if (pi && CFEqualSafe(id, SOSPeerInfoGetPeerID(pi))) { + SOSCircleUpdatePeerInfo(new_circle, pi); + } + CFReleaseSafe(pi); + } + }); + } + + if(SOSCircleCountPeers(new_circle) == 0) { + SOSCircleResetToEmpty(new_circle, NULL); + } + + return new_circle; +} + +// +// MARK: Circle Membership change notificaion +// + +void SOSAccountAddChangeBlock(SOSAccountRef a, SOSAccountCircleMembershipChangeBlock changeBlock) { + CFArrayAppendValue(a->change_blocks, changeBlock); +} + +void SOSAccountRemoveChangeBlock(SOSAccountRef a, SOSAccountCircleMembershipChangeBlock changeBlock) { + CFArrayRemoveAllValue(a->change_blocks, changeBlock); +} + +void SOSAccountAddSyncablePeerBlock(SOSAccountRef a, CFStringRef ds_name, SOSAccountSyncablePeersBlock changeBlock) { + if (!changeBlock) return; + + CFRetainSafe(ds_name); + SOSAccountCircleMembershipChangeBlock block_to_register = ^void (SOSCircleRef new_circle, + CFSetRef added_peers, CFSetRef removed_peers, + CFSetRef added_applicants, CFSetRef removed_applicants) { + + if (!CFEqualSafe(SOSCircleGetName(new_circle), ds_name)) + return; + + SOSPeerInfoRef myPi = SOSAccountGetMyPeerInCircle(a, new_circle, NULL); + CFStringRef myPi_id = myPi ? SOSPeerInfoGetPeerID(myPi) : NULL; + + CFMutableArrayRef peer_ids = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFMutableArrayRef added_ids = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFMutableArrayRef removed_ids = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + + if (SOSCircleHasPeer(new_circle, myPi, NULL)) { + SOSCircleForEachPeer(new_circle, ^(SOSPeerInfoRef peer) { + CFArrayAppendValueIfNot(peer_ids, SOSPeerInfoGetPeerID(peer), myPi_id); + }); + + CFSetForEach(added_peers, ^(const void *value) { + CFArrayAppendValueIfNot(added_ids, SOSPeerInfoGetPeerID((SOSPeerInfoRef) value), myPi_id); + }); + + CFSetForEach(removed_peers, ^(const void *value) { + CFArrayAppendValueIfNot(removed_ids, SOSPeerInfoGetPeerID((SOSPeerInfoRef) value), myPi_id); + }); + } + + if (CFArrayGetCount(peer_ids) || CFSetContainsValue(removed_peers, myPi)) + changeBlock(peer_ids, added_ids, removed_ids); + + CFReleaseSafe(peer_ids); + CFReleaseSafe(added_ids); + CFReleaseSafe(removed_ids); + }; + + CFRetainSafe(changeBlock); + SOSAccountAddChangeBlock(a, Block_copy(block_to_register)); + + CFSetRef empty = CFSetCreateMutableForSOSPeerInfosByID(kCFAllocatorDefault); + SOSCircleRef circle = (SOSCircleRef) CFDictionaryGetValue(a->circles, ds_name); + if (circle) { + block_to_register(circle, empty, empty, empty, empty); + } + CFReleaseSafe(empty); +} + + +bool sosAccountLeaveCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error) { + SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircle(account, circle, NULL); + if(!fpi) return false; + CFErrorRef localError = NULL; + SOSPeerInfoRef retire_peer = SOSFullPeerInfoPromoteToRetiredAndCopy(fpi, &localError); + CFStringRef retire_id = SOSPeerInfoGetPeerID(retire_peer); + + // Account should move away from a dictionary of KVS keys to a Circle -> Peer -> Retirement ticket storage soonish. + CFStringRef retire_key = SOSRetirementKeyCreateWithCircleAndPeer(circle, retire_id); + CFDataRef retire_value = NULL; + bool retval = false; + bool writeCircle = false; + + // Create a Retirement Ticket and store it in the retired_peers of the account. + require_action_quiet(retire_peer, errout, secerror("Create ticket failed for peer %@: %@", fpi, localError)); + retire_value = SOSPeerInfoCopyEncodedData(retire_peer, NULL, &localError); + require_action_quiet(retire_value, errout, secerror("Failed to encode retirement peer %@: %@", retire_peer, localError)); + + // See if we need to repost the circle we could either be an applicant or a peer already in the circle + if(SOSCircleHasApplicant(circle, retire_peer, NULL)) { + // Remove our application if we have one. + SOSCircleWithdrawRequest(circle, retire_peer, NULL); + writeCircle = true; + } else if (SOSCircleHasPeer(circle, retire_peer, NULL)) { + if (SOSCircleUpdatePeerInfo(circle, retire_peer)) { + CFErrorRef cleanupError = NULL; + if (!SOSAccountCleanupAfterPeer(account, RETIREMENT_FINALIZATION_SECONDS, circle, retire_peer, &cleanupError)) + secerror("Error cleanup up after peer (%@): %@", retire_peer, cleanupError); + CFReleaseSafe(cleanupError); + } + writeCircle = true; + } + + // Store the retirement record locally. + CFDictionarySetValue(account->retired_peers, retire_key, retire_value); + + // Write retirement to Transport + SOSTransportCircleRef tCircle = (SOSTransportCircleRef)CFDictionaryGetValue(account->circle_transports, SOSCircleGetName(circle)); + SOSTransportCirclePostRetirement(tCircle, SOSCircleGetName(circle), retire_id, retire_value, NULL); // TODO: Handle errors? + + // Kill peer key but don't return error if we can't. + if(!SOSAccountDestroyCirclePeerInfo(account, circle, &localError)) + secerror("Couldn't purge key for peer %@ on retirement: %@", fpi, localError); + + if (writeCircle) { + CFDataRef circle_data = SOSCircleCopyEncodedData(circle, kCFAllocatorDefault, error); + + if (circle_data) { + SOSTransportCirclePostCircle(tCircle, SOSCircleGetName(circle), circle_data, NULL); // TODO: Handle errors? + } + CFReleaseNull(circle_data); + } + retval = true; + +errout: + CFReleaseNull(localError); + CFReleaseNull(retire_peer); + CFReleaseNull(retire_key); + CFReleaseNull(retire_value); + return retval; +} + +/* + NSUbiquitousKeyValueStoreInitialSyncChange is only posted if there is any + local value that has been overwritten by a distant value. If there is no + conflict between the local and the distant values when doing the initial + sync (e.g. if the cloud has no data stored or the client has not stored + any data yet), you'll never see that notification. + + NSUbiquitousKeyValueStoreInitialSyncChange implies an initial round trip + with server but initial round trip with server does not imply + NSUbiquitousKeyValueStoreInitialSyncChange. + */ + + +// +// MARK: Status summary +// + +static SOSCCStatus SOSCCCircleStatus(SOSCircleRef circle) { + if (SOSCircleCountPeers(circle) == 0) + return kSOSCCCircleAbsent; + + return kSOSCCNotInCircle; +} + +static SOSCCStatus SOSCCThisDeviceStatusInCircle(SOSCircleRef circle, SOSPeerInfoRef this_peer) { + if (SOSCircleCountPeers(circle) == 0) + return kSOSCCCircleAbsent; + + if (SOSCircleHasPeer(circle, this_peer, NULL)) + return kSOSCCInCircle; + + if (SOSCircleHasApplicant(circle, this_peer, NULL)) + return kSOSCCRequestPending; + + return kSOSCCNotInCircle; +} + +static SOSCCStatus UnionStatus(SOSCCStatus accumulated_status, SOSCCStatus additional_circle_status) { + switch (additional_circle_status) { + case kSOSCCInCircle: + return accumulated_status; + case kSOSCCRequestPending: + return (accumulated_status == kSOSCCInCircle) ? + kSOSCCRequestPending : + accumulated_status; + case kSOSCCNotInCircle: + return (accumulated_status == kSOSCCInCircle || + accumulated_status == kSOSCCRequestPending) ? + kSOSCCNotInCircle : + accumulated_status; + case kSOSCCCircleAbsent: + return (accumulated_status == kSOSCCInCircle || + accumulated_status == kSOSCCRequestPending || + accumulated_status == kSOSCCNotInCircle) ? + kSOSCCCircleAbsent : + accumulated_status; + default: + return additional_circle_status; + }; + +} + +SOSCCStatus SOSAccountIsInCircles(SOSAccountRef account, CFErrorRef* error) { + if (!SOSAccountHasPublicKey(account, error)) { + return kSOSCCError; + } + + __block bool set_once = false; + __block SOSCCStatus status = kSOSCCInCircle; + + SOSAccountForEachKnownCircle(account, ^(CFStringRef name) { + set_once = true; + status = UnionStatus(status, kSOSCCNotInCircle); + }, ^(SOSCircleRef circle) { + set_once = true; + status = UnionStatus(status, SOSCCCircleStatus(circle)); + }, ^(SOSCircleRef circle, SOSFullPeerInfoRef full_peer) { + set_once = true; + SOSCCStatus circle_status = SOSCCThisDeviceStatusInCircle(circle, SOSFullPeerInfoGetPeerInfo(full_peer)); + status = UnionStatus(status, circle_status); + }); + + if (!set_once) + status = kSOSCCCircleAbsent; + + return status; +} + +// +// MARK: Account Reset Circles +// + +static bool SOSAccountResetThisCircleToOffering(SOSAccountRef account, SOSCircleRef circle, SecKeyRef user_key, CFErrorRef *error) { + SOSFullPeerInfoRef myCirclePeer = SOSAccountGetMyFullPeerInCircle(account, circle, error); + if (!myCirclePeer) + return false; + + SOSAccountModifyCircle(account, SOSCircleGetName(circle), error, ^(SOSCircleRef circle) { + bool result = false; + SOSFullPeerInfoRef cloud_identity = NULL; + CFErrorRef localError = NULL; + + require_quiet(SOSCircleResetToOffering(circle, user_key, myCirclePeer, &localError), err_out); + + { + 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); + } + + account->departure_code = kSOSNeverLeftCircle; + require_quiet(SOSCircleRequestAdmission(circle, user_key, cloud_identity, &localError), err_out); + require_quiet(SOSCircleAcceptRequest(circle, user_key, myCirclePeer, SOSFullPeerInfoGetPeerInfo(cloud_identity), &localError), err_out); + result = true; + SOSAccountPublishCloudParameters(account, 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); + CFReleaseNull(cloud_identity); + return result; + }); + + return true; +} + + +bool SOSAccountResetToOffering(SOSAccountRef account, CFErrorRef* error) { + SecKeyRef user_key = SOSAccountGetPrivateCredential(account, error); + if (!user_key) + return false; + + __block bool result = true; + + SOSAccountForEachKnownCircle(account, ^(CFStringRef name) { + SOSCircleRef circle = SOSCircleCreate(NULL, name, NULL); + if (circle) + CFDictionaryAddValue(account->circles, name, circle); + + SOSAccountResetThisCircleToOffering(account, circle, user_key, error); + }, ^(SOSCircleRef circle) { + SOSAccountResetThisCircleToOffering(account, circle, user_key, error); + }, ^(SOSCircleRef circle, SOSFullPeerInfoRef full_peer) { + SOSAccountResetThisCircleToOffering(account, circle, user_key, error); + }); + + return result; +} + +bool SOSAccountResetToEmpty(SOSAccountRef account, CFErrorRef* error) { + if (!SOSAccountHasPublicKey(account, error)) + return false; + + __block bool result = true; + SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { + SOSAccountModifyCircle(account, SOSCircleGetName(circle), error, ^(SOSCircleRef circle) { + if (!SOSCircleResetToEmpty(circle, error)) + { + secerror("error: %@", *error); + result = false; + } + account->departure_code = kSOSWithdrewMembership; + return result; + }); + }); + + return result; +} + + +// +// MARK: Joining +// + +static bool SOSAccountJoinThisCircle(SOSAccountRef account, SecKeyRef user_key, + SOSCircleRef circle, bool use_cloud_peer, CFErrorRef* error) { + __block bool result = false; + __block SOSFullPeerInfoRef cloud_full_peer = NULL; + + SOSFullPeerInfoRef myCirclePeer = SOSAccountGetMyFullPeerInCircle(account, circle, error); + + require_action_quiet(myCirclePeer, fail, + SOSCreateErrorWithFormat(kSOSErrorPeerNotFound, NULL, error, NULL, CFSTR("Can't find/create peer for circle: %@"), circle)); + if (use_cloud_peer) { + cloud_full_peer = SOSCircleGetiCloudFullPeerInfoRef(circle); + } + + if (SOSCircleCountPeers(circle) == 0) { + result = SOSAccountResetThisCircleToOffering(account, circle, user_key, error); + } else { + SOSAccountModifyCircle(account, SOSCircleGetName(circle), error, ^(SOSCircleRef circle) { + result = SOSCircleRequestAdmission(circle, user_key, myCirclePeer, error); + account->departure_code = kSOSNeverLeftCircle; + if(result && cloud_full_peer) { + CFErrorRef localError = NULL; + CFStringRef cloudid = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(cloud_full_peer)); + require_quiet(cloudid, finish); + require_quiet(SOSCircleHasActivePeerWithID(circle, cloudid, &localError), finish); + require_quiet(SOSCircleAcceptRequest(circle, user_key, cloud_full_peer, SOSFullPeerInfoGetPeerInfo(myCirclePeer), &localError), finish); + finish: + if (localError){ + secerror("Failed to join with cloud identity: %@", localError); + CFReleaseNull(localError); + } + } + return result; + }); + } + +fail: + CFReleaseNull(cloud_full_peer); + return result; +} + +static bool SOSAccountJoinCircles_internal(SOSAccountRef account, bool use_cloud_identity, CFErrorRef* error) { + SecKeyRef user_key = SOSAccountGetPrivateCredential(account, error); + if (!user_key) + return false; + + __block bool success = true; + + SOSAccountForEachKnownCircle(account, ^(CFStringRef name) { // Incompatible + success = false; + SOSCreateError(kSOSErrorIncompatibleCircle, CFSTR("Incompatible circle"), NULL, error); + }, ^(SOSCircleRef circle) { //no peer + success = SOSAccountJoinThisCircle(account, user_key, circle, use_cloud_identity, error) && success; + }, ^(SOSCircleRef circle, SOSFullPeerInfoRef full_peer) { // Have Peer + SOSPeerInfoRef myPeer = SOSFullPeerInfoGetPeerInfo(full_peer); + if(SOSCircleHasPeer(circle, myPeer, NULL)) goto already_present; + if(SOSCircleHasApplicant(circle, myPeer, NULL)) goto already_applied; + if(SOSCircleHasRejectedApplicant(circle, myPeer, NULL)) { + SOSCircleRemoveRejectedPeer(circle, myPeer, NULL); + } + + secerror("Resetting my peer (ID: %@) for circle '%@' during application", SOSPeerInfoGetPeerID(myPeer), SOSCircleGetName(circle)); + CFErrorRef localError = NULL; + if (!SOSAccountDestroyCirclePeerInfo(account, circle, &localError)) { + secerror("Failed to destroy peer (%@) during application, error=%@", myPeer, localError); + CFReleaseNull(localError); + } + already_applied: + success = SOSAccountJoinThisCircle(account, user_key, circle, use_cloud_identity, error) && success; + return; + already_present: + success = true; + return; + }); + + if(success) account->departure_code = kSOSNeverLeftCircle; + return success; +} + +bool SOSAccountJoinCircles(SOSAccountRef account, CFErrorRef* error) { + return SOSAccountJoinCircles_internal(account, false, error); +} + +CFStringRef SOSAccountGetDeviceID(SOSAccountRef account, CFErrorRef *error){ + __block CFStringRef result = NULL; + __block CFStringRef temp = NULL; + SOSAccountForEachKnownCircle(account, NULL, NULL, ^(SOSCircleRef circle, SOSFullPeerInfoRef myCirclePeer) { + SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircle(account, circle, error); + if(fpi){ + SOSPeerInfoRef myPeer = SOSFullPeerInfoGetPeerInfo(fpi); + if(myPeer){ + temp = SOSPeerInfoGetDeviceID(myPeer); + if(!isNull(temp)){ + result = CFStringCreateCopy(kCFAllocatorDefault, temp); + } + } + else{ + secnotice("circle", "Could not acquire my peer info in circle: %@", SOSCircleGetName(circle)); + } + } + else{ + secnotice("circle", "Could not acquire my full peer info in circle: %@", SOSCircleGetName(circle)); + } + }); + return result; +} + +bool SOSAccountSetMyDSID(SOSAccountRef account, CFStringRef IDS, CFErrorRef* error){ + __block bool result = false; + + SOSAccountForEachKnownCircle(account, NULL, NULL, ^(SOSCircleRef circle, SOSFullPeerInfoRef myCirclePeer) { + SOSAccountModifyCircle(account, SOSCircleGetName(circle), error, ^(SOSCircleRef circle) { + SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircle(account, circle, error); + if(fpi){ + SOSPeerInfoRef myPeer = SOSFullPeerInfoGetPeerInfo(fpi); + if(myPeer){ + SOSPeerInfoSetDeviceID(myPeer, IDS); + result = true; + } + else{ + secnotice("circle", "Could not acquire my peer info in circle: %@", SOSCircleGetName(circle)); + result = false; + } + } + else{ + secnotice("circle", "Could not acquire my full peer info in circle: %@", SOSCircleGetName(circle)); + result = false; + } + return result; + }); + }); + return result; + +} +bool SOSAccountJoinCirclesAfterRestore(SOSAccountRef account, CFErrorRef* error) { + return SOSAccountJoinCircles_internal(account, true, error); +} + + +bool SOSAccountLeaveCircles(SOSAccountRef account, CFErrorRef* error) +{ + __block bool result = true; + SOSAccountForEachKnownCircle(account, NULL, NULL, ^(SOSCircleRef circle, SOSFullPeerInfoRef myCirclePeer) { + SOSAccountModifyCircle(account, SOSCircleGetName(circle), error, ^(SOSCircleRef circle) { + result = sosAccountLeaveCircle(account, circle, error); // TODO: What about multiple errors! + return result; + }); + }); + + account->departure_code = kSOSWithdrewMembership; + return result; +} + +bool SOSAccountBail(SOSAccountRef account, uint64_t limit_in_seconds, CFErrorRef* error) { + dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_group_t group = dispatch_group_create(); + __block bool result = false; + secnotice("circle", "Attempting to leave circle - best effort - in %llu seconds\n", limit_in_seconds); + // Add a task to the group + dispatch_group_async(group, queue, ^{ + SOSAccountForEachKnownCircle(account, NULL, NULL, ^(SOSCircleRef circle, SOSFullPeerInfoRef myCirclePeer) { + SOSAccountModifyCircle(account, SOSCircleGetName(circle), error, ^(SOSCircleRef circle) { + result = sosAccountLeaveCircle(account, circle, error); // TODO: What about multiple errors! + return result; + }); + }); + + account->departure_code = kSOSWithdrewMembership; + }); + dispatch_time_t milestone = dispatch_time(DISPATCH_TIME_NOW, limit_in_seconds * NSEC_PER_SEC); + + dispatch_group_wait(group, milestone); + dispatch_release(group); + return result; +} + + +// +// MARK: Application +// + +static void for_each_applicant_in_each_circle(SOSAccountRef account, CFArrayRef peer_infos, + bool (^action)(SOSCircleRef circle, SOSFullPeerInfoRef myCirclePeer, SOSPeerInfoRef peer)) { + + SOSAccountForEachKnownCircle(account, NULL, NULL, ^(SOSCircleRef circle, SOSFullPeerInfoRef full_peer) { + SOSPeerInfoRef me = SOSFullPeerInfoGetPeerInfo(full_peer); + CFErrorRef peer_error = NULL; + if (SOSCircleHasPeer(circle, me, &peer_error)) { + CFArrayForEach(peer_infos, ^(const void *value) { + SOSPeerInfoRef peer = (SOSPeerInfoRef) value; + if (SOSCircleHasApplicant(circle, peer, NULL)) { + SOSAccountModifyCircle(account, SOSCircleGetName(circle), NULL, ^(SOSCircleRef circle) { + return action(circle, full_peer, peer); + }); + } + }); + } + if (peer_error) + secerror("Got error in SOSCircleHasPeer: %@", peer_error); + CFReleaseSafe(peer_error); // TODO: We should be accumulating errors here. + }); +} + +bool SOSAccountAcceptApplicants(SOSAccountRef account, CFArrayRef applicants, CFErrorRef* error) { + SecKeyRef user_key = SOSAccountGetPrivateCredential(account, error); + if (!user_key) + return false; + + __block bool success = true; + __block int64_t num_peers = 0; + + for_each_applicant_in_each_circle(account, applicants, ^(SOSCircleRef circle, SOSFullPeerInfoRef myCirclePeer, SOSPeerInfoRef peer) { + bool accepted = SOSCircleAcceptRequest(circle, user_key, myCirclePeer, peer, error); + if (!accepted) + success = false; + else + num_peers = MAX(num_peers, SOSCircleCountPeers(circle)); + return accepted; + }); + + return success; +} + +bool SOSAccountRejectApplicants(SOSAccountRef account, CFArrayRef applicants, CFErrorRef* error) { + __block bool success = true; + __block int64_t num_peers = 0; + + for_each_applicant_in_each_circle(account, applicants, ^(SOSCircleRef circle, SOSFullPeerInfoRef myCirclePeer, SOSPeerInfoRef peer) { + bool rejected = SOSCircleRejectRequest(circle, myCirclePeer, peer, error); + if (!rejected) + success = false; + else + num_peers = MAX(num_peers, SOSCircleCountPeers(circle)); + return rejected; + }); + + return success; +} + + + +CFStringRef SOSAccountCopyIncompatibilityInfo(SOSAccountRef account, CFErrorRef* error) { + return CFSTR("We're compatible, go away"); +} + +enum DepartureReason SOSAccountGetLastDepartureReason(SOSAccountRef account, CFErrorRef* error) { + return account->departure_code; +} + + +CFArrayRef SOSAccountCopyGeneration(SOSAccountRef account, CFErrorRef *error) { + if (!SOSAccountHasPublicKey(account, error)) + return NULL; + CFMutableArrayRef generations = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + + SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { + CFNumberRef generation = (CFNumberRef)SOSCircleGetGeneration(circle); + CFArrayAppendValue(generations, SOSCircleGetName(circle)); + CFArrayAppendValue(generations, generation); + }); + + return generations; + +} + +bool SOSValidateUserPublic(SOSAccountRef account, CFErrorRef *error) { + if (!SOSAccountHasPublicKey(account, error)) + return NULL; + + return account->user_public_trusted; +} + + +bool SOSAccountEnsurePeerRegistration(SOSAccountRef account, CFErrorRef *error) { + __block bool result = true; + + secnotice("updates", "Ensuring peer registration."); + + SOSAccountForEachKnownCircle(account, ^(CFStringRef name) { + }, ^(SOSCircleRef circle) { + }, ^(SOSCircleRef circle, SOSFullPeerInfoRef full_peer) { + SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircle(account, circle, error); + SOSPeerInfoRef me = SOSFullPeerInfoGetPeerInfo(fpi); + CFMutableArrayRef trusted_peer_ids = NULL; + CFMutableArrayRef untrusted_peer_ids = NULL; + CFStringRef my_id = NULL; + if (SOSCircleHasPeer(circle, me, NULL)) { + my_id = SOSPeerInfoGetPeerID(me); + trusted_peer_ids = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + untrusted_peer_ids = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { + CFMutableArrayRef arrayToAddTo = SOSPeerInfoApplicationVerify(peer, account->user_public, NULL) ? trusted_peer_ids : untrusted_peer_ids; + + CFArrayAppendValueIfNot(arrayToAddTo, SOSPeerInfoGetPeerID(peer), my_id); + }); + } + + SOSEngineRef engine = SOSDataSourceFactoryGetEngineForDataSourceName(account->factory, SOSCircleGetName(circle), NULL); + if (engine) + SOSEngineCircleChanged(engine, my_id, trusted_peer_ids, untrusted_peer_ids); + + CFReleaseNull(trusted_peer_ids); + CFReleaseNull(untrusted_peer_ids); + + SOSTransportMessageRef transport = (SOSTransportMessageRef)CFDictionaryGetValue(account->message_transports, SOSCircleGetName(circle)); + SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { + if (!CFEqualSafe(me, peer)) { + CFErrorRef localError = NULL; + SOSPeerCoderInitializeForPeer(transport, full_peer, peer, &localError); + if (localError) + secnotice("updates", "can't initialize transport for peer %@ with %@ (%@)", peer, full_peer, localError); + CFReleaseSafe(localError); + } + }); + }); + + return result; +} diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSAccount.h b/Security/sec/SOSCircle/SecureObjectSync/SOSAccount.h new file mode 100644 index 00000000..2b4a32ef --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSAccount.h @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/*! + @header SOSAccount.h + The functions provided in SOSCircle.h provide an interface to a + secure object syncing circle for a single class + */ + +#ifndef _SOSACCOUNT_H_ +#define _SOSACCOUNT_H_ + +/* Forward declarations of SOS types. */ +typedef struct __OpaqueSOSAccount *SOSAccountRef; + + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +__BEGIN_DECLS + +#define RETIREMENT_FINALIZATION_SECONDS (24*60*60) + + +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); + +SOSAccountRef SOSAccountGetShared(void); +SOSAccountRef SOSAccountCreate(CFAllocatorRef allocator, + CFDictionaryRef gestalt, + SOSDataSourceFactoryRef factory); +SOSAccountRef SOSAccountCreateBasic(CFAllocatorRef allocator, + CFDictionaryRef gestalt, + SOSDataSourceFactoryRef factory); + +// +// MARK: Persistent Encode decode +// + +SOSAccountRef SOSAccountCreateFromDER(CFAllocatorRef allocator, SOSDataSourceFactoryRef factory, + CFErrorRef* error, + const uint8_t** der_p, const uint8_t *der_end); + +SOSAccountRef SOSAccountCreateFromDER_V3(CFAllocatorRef allocator, + SOSDataSourceFactoryRef factory, + CFErrorRef* error, + const uint8_t** der_p, const uint8_t *der_end); + +SOSAccountRef SOSAccountCreateFromData(CFAllocatorRef allocator, CFDataRef circleData, + SOSDataSourceFactoryRef factory, + CFErrorRef* error); + +size_t SOSAccountGetDEREncodedSize(SOSAccountRef cir, CFErrorRef *error); +uint8_t* SOSAccountEncodeToDER(SOSAccountRef cir, CFErrorRef* error, const uint8_t* der, uint8_t* der_end); +size_t SOSAccountGetDEREncodedSize_V3(SOSAccountRef cir, CFErrorRef *error); +uint8_t* SOSAccountEncodeToDER_V3(SOSAccountRef cir, CFErrorRef* error, const uint8_t* der, uint8_t* der_end); +CFDataRef SOSAccountCopyEncodedData(SOSAccountRef circle, CFAllocatorRef allocator, CFErrorRef *error); +// +//MARK: IDS Device ID +CFStringRef SOSAccountGetDeviceID(SOSAccountRef account, CFErrorRef *error); +bool SOSAccountSetMyDSID(SOSAccountRef account, CFStringRef IDS, CFErrorRef* errror); + +// +// +// MARK: Local Peer finding +// +SOSPeerInfoRef SOSAccountGetMyPeerInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error); +SOSPeerInfoRef SOSAccountGetMyPeerInCircleNamed(SOSAccountRef account, CFStringRef circle, CFErrorRef* error); + +SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error); +SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircleNamed(SOSAccountRef account, CFStringRef name, CFErrorRef *error); + +// +// MARK: Credential management +// + +SecKeyRef SOSAccountGetPrivateCredential(SOSAccountRef account, CFErrorRef* error); +void SOSAccountPurgePrivateCredential(SOSAccountRef account); + +bool SOSAccountTryUserCredentials(SOSAccountRef account, + CFStringRef user_account, CFDataRef user_password, + CFErrorRef *error); + +bool SOSAccountAssertUserCredentials(SOSAccountRef account, + CFStringRef user_account, CFDataRef user_password, + CFErrorRef *error); + + +// +// MARK: Circle management +// +int SOSAccountCountCircles(SOSAccountRef a); + +void SOSAccountForEachCircle(SOSAccountRef account, void (^process)(SOSCircleRef circle)); + +SOSCircleRef SOSAccountFindCircle(SOSAccountRef a, CFStringRef name, CFErrorRef *error); +SOSCircleRef SOSAccountEnsureCircle(SOSAccountRef a, CFStringRef name, CFErrorRef *error); + +bool SOSAccountUpdateCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef *error); +void SOSTransportEachMessage(SOSAccountRef account, CFDictionaryRef updates, CFErrorRef *error); + + +SOSCCStatus SOSAccountIsInCircles(SOSAccountRef account, CFErrorRef* error); +bool SOSAccountJoinCircles(SOSAccountRef account, CFErrorRef* error); +bool SOSAccountJoinCirclesAfterRestore(SOSAccountRef account, CFErrorRef* error); +bool SOSAccountLeaveCircles(SOSAccountRef account,CFErrorRef* error); +bool SOSAccountBail(SOSAccountRef account, uint64_t limit_in_seconds, CFErrorRef* error); +bool SOSAccountAcceptApplicants(SOSAccountRef account, CFArrayRef applicants, CFErrorRef* error); +bool SOSAccountRejectApplicants(SOSAccountRef account, CFArrayRef applicants, CFErrorRef* error); + +bool SOSAccountResetToOffering(SOSAccountRef account, CFErrorRef* error); +bool SOSAccountResetToEmpty(SOSAccountRef account, CFErrorRef* error); +bool SOSValidateUserPublic(SOSAccountRef account, CFErrorRef* error); + +CFArrayRef SOSAccountCopyApplicants(SOSAccountRef account, CFErrorRef *error); +CFArrayRef SOSAccountCopyGeneration(SOSAccountRef account, CFErrorRef *error); +CFArrayRef SOSAccountCopyValidPeers(SOSAccountRef account, CFErrorRef *error); +CFArrayRef SOSAccountCopyNotValidPeers(SOSAccountRef account, CFErrorRef *error); +CFArrayRef SOSAccountCopyRetired(SOSAccountRef account, CFErrorRef *error); +CFArrayRef SOSAccountCopyPeers(SOSAccountRef account, CFErrorRef *error); +CFArrayRef SOSAccountCopyActivePeers(SOSAccountRef account, CFErrorRef *error); +CFArrayRef SOSAccountCopyActiveValidPeers(SOSAccountRef account, CFErrorRef *error); +CFArrayRef SOSAccountCopyConcurringPeers(SOSAccountRef account, CFErrorRef *error); + +CFArrayRef SOSAccountCopyAccountIdentityPeerInfos(SOSAccountRef account, CFAllocatorRef allocator, CFErrorRef* error); +bool SOSAccountIsAccountIdentity(SOSAccountRef account, SOSPeerInfoRef peer_info, CFErrorRef *error); + +enum DepartureReason SOSAccountGetLastDepartureReason(SOSAccountRef account, CFErrorRef* error); + +// +// MARK: Change blocks +// +void SOSAccountAddChangeBlock(SOSAccountRef a, SOSAccountCircleMembershipChangeBlock changeBlock); +void SOSAccountRemoveChangeBlock(SOSAccountRef a, SOSAccountCircleMembershipChangeBlock changeBlock); + +void SOSAccountAddSyncablePeerBlock(SOSAccountRef a, + CFStringRef ds_name, + SOSAccountSyncablePeersBlock changeBlock); + +// +// MARK: Local device gestalt change. +// +bool SOSAccountUpdateGestalt(SOSAccountRef account, CFDictionaryRef new_gestalt); + +bool SOSAccountHandleParametersChange(SOSAccountRef account, CFDataRef updates, CFErrorRef *error); + +bool SOSAccountSyncWithPeer(SOSAccountRef account, SOSCircleRef circle, SOSPeerInfoRef thisPeer, bool* didSendData, CFErrorRef* error); +bool SOSAccountSyncWithAllPeers(SOSAccountRef account, CFErrorRef *error); + +bool SOSAccountCleanupAfterPeer(SOSAccountRef account, size_t seconds, SOSCircleRef circle, + SOSPeerInfoRef cleanupPeer, CFErrorRef* error); + +bool SOSAccountCleanupRetirementTickets(SOSAccountRef account, size_t seconds, CFErrorRef* error); + +bool SOSAccountScanForRetired(SOSAccountRef account, SOSCircleRef circle, CFErrorRef *error); + +SOSCircleRef SOSAccountCloneCircleWithRetirement(SOSAccountRef account, SOSCircleRef starting_circle, CFErrorRef *error); + +// +// MARK: Version incompatibility Functions +// +CFStringRef SOSAccountCopyIncompatibilityInfo(SOSAccountRef account, CFErrorRef* error); + +// +// MARK: Private functions +// + + +dispatch_queue_t SOSAccountGetQueue(SOSAccountRef account); + +typedef bool (^SOSAccountSendBlock)(CFStringRef key, CFDataRef message, CFErrorRef *error); + +// +// MARK: Utility functions +// + +CFStringRef SOSInterestListCopyDescription(CFArrayRef interests); + + +__END_DECLS + +#endif /* !_SOSACCOUNT_H_ */ diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSAccountCircles.c b/Security/sec/SOSCircle/SecureObjectSync/SOSAccountCircles.c new file mode 100644 index 00000000..47cba02a --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSAccountCircles.c @@ -0,0 +1,170 @@ +// +// SOSAccountCircles.c +// sec +// + +#include "SOSAccountPriv.h" +#include +#include +#include +#include + +void SOSAccountForEachCircle(SOSAccountRef account, void (^process)(SOSCircleRef circle)) +{ + CFDictionaryForEach(account->circles, ^(const void* key, const void* value) { + assert(value); + process((SOSCircleRef)value); + }); +} + + +void SOSAccountForEachKnownCircle(SOSAccountRef account, + void (^handle_incompatible)(CFStringRef name), + void (^handle_no_peer)(SOSCircleRef circle), + void (^handle_peer)(SOSCircleRef circle, SOSFullPeerInfoRef full_peer)) { + CFDictionaryForEach(account->circles, ^(const void *key, const void *value) { + if (isNull(value)) { + if (handle_incompatible) + handle_incompatible((CFStringRef)key); + } else { + SOSCircleRef circle = (SOSCircleRef) value; + CFRetainSafe(circle); + SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircleNamedIfPresent(account, SOSCircleGetName(circle), NULL); + if (!fpi) { + if (handle_no_peer) + handle_no_peer(circle); + } else { + CFRetainSafe(fpi); + if (handle_peer) + handle_peer(circle, fpi); + CFReleaseSafe(fpi); + } + CFReleaseSafe(circle); + } + }); +} + +// +// MARK: Circle management +// + +int SOSAccountCountCircles(SOSAccountRef a) { + assert(a); + assert(a->circle_identities); + assert(a->circles); + return (int)CFDictionaryGetCount(a->circles); +} + + + +SOSCircleRef SOSAccountFindCircle(SOSAccountRef a, CFStringRef name, CFErrorRef *error) +{ + CFTypeRef entry = CFDictionaryGetValue(a->circles, name); + + require_action_quiet(!isNull(entry), fail, + SOSCreateError(kSOSErrorIncompatibleCircle, CFSTR("Incompatible circle in KVS"), NULL, error)); + + require_action_quiet(entry, fail, + SOSCreateError(kSOSErrorNoCircle, CFSTR("No circle found"), NULL, error)); + + + return (SOSCircleRef) entry; + +fail: + return NULL; +} + + +static bool SOSAccountInflateTransportsForCircle(SOSAccountRef account, CFStringRef circleName, CFErrorRef *error){ + bool success = false; + SOSTransportKeyParameterRef tKey = NULL; + SOSTransportCircleRef tCircle = NULL; + SOSTransportMessageRef tMessage = NULL; + SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircleNamed(account, circleName, error); + require_quiet(fpi, fail); + SOSPeerInfoRef myPeer = SOSFullPeerInfoGetPeerInfo(fpi); + require_quiet(myPeer, fail); + CFStringRef type = SOSPeerInfoGetTransportType(myPeer); + if(CFStringCompare(type, CFSTR("KVS"), 0) == kCFCompareEqualTo){ + tKey = (SOSTransportKeyParameterRef)SOSTransportKeyParameterKVSCreate(account, error); + tCircle = (SOSTransportCircleRef)SOSTransportCircleKVSCreate(account, circleName, error); + tMessage = (SOSTransportMessageRef)SOSTransportMessageKVSCreate(account, circleName, error); + require_quiet(tKey, fail); + require_quiet(tCircle, fail); + require_quiet(tMessage, fail); + + CFRetainAssign(account->key_transport, (SOSTransportKeyParameterRef)tKey); + CFDictionarySetValue(account->circle_transports, circleName, tCircle); + CFDictionarySetValue(account->message_transports, circleName, tMessage); + } + + success = true; +fail: + CFReleaseNull(tKey); + CFReleaseNull(tCircle); + CFReleaseNull(tMessage); + return success; +} + +SOSCircleRef SOSAccountEnsureCircle(SOSAccountRef a, CFStringRef name, CFErrorRef *error) +{ + CFErrorRef localError = NULL; + + SOSCircleRef circle = SOSAccountFindCircle(a, name, &localError); + + require_action_quiet(circle || !isSOSErrorCoded(localError, kSOSErrorIncompatibleCircle), fail, + if (error) { *error = localError; localError = NULL; }); + + if(NULL == circle){ + circle = SOSCircleCreate(NULL, name, NULL); + if (circle){ + CFDictionaryAddValue(a->circles, name, circle); + CFRelease(circle); + circle = SOSAccountFindCircle(a, name, &localError); + } + + SOSUpdateKeyInterest(); + } + + require_quiet(SOSAccountInflateTransportsForCircle(a, name, error), fail); + +fail: + CFReleaseNull(localError); + return circle; +} + + +bool SOSAccountUpdateCircleFromRemote(SOSAccountRef account, SOSCircleRef newCircle, CFErrorRef *error) +{ + return SOSAccountHandleUpdateCircle(account, newCircle, false, error); +} + +bool SOSAccountUpdateCircle(SOSAccountRef account, SOSCircleRef newCircle, CFErrorRef *error) +{ + return SOSAccountHandleUpdateCircle(account, newCircle, true, error); +} + +bool SOSAccountModifyCircle(SOSAccountRef account, + CFStringRef circleName, + CFErrorRef* error, + bool (^action)(SOSCircleRef circle)) +{ + bool success = false; + + SOSCircleRef circle = NULL; + SOSCircleRef accountCircle = SOSAccountFindCircle(account, circleName, error); + require_quiet(accountCircle, fail); + + circle = SOSCircleCopyCircle(kCFAllocatorDefault, accountCircle, error); + require_quiet(circle, fail); + + success = true; + require_quiet(action(circle), fail); + + success = SOSAccountUpdateCircle(account, circle, error); + +fail: + CFReleaseSafe(circle); + return success; +} + diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSAccountCloudParameters.c b/Security/sec/SOSCircle/SecureObjectSync/SOSAccountCloudParameters.c new file mode 100644 index 00000000..98c3826d --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSAccountCloudParameters.c @@ -0,0 +1,85 @@ +// +// AccountCloudParameters.c +// sec +// + +#include "SOSAccountPriv.h" +#include +// +// Cloud Paramters encode/decode +// + +static size_t der_sizeof_cloud_parameters(SecKeyRef publicKey, CFDataRef paramters, CFErrorRef* error) +{ + size_t public_key_size = der_sizeof_public_bytes(publicKey, error); + size_t parameters_size = der_sizeof_data_or_null(paramters, error); + + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, public_key_size + parameters_size); +} + +static uint8_t* der_encode_cloud_parameters(SecKeyRef publicKey, CFDataRef paramters, CFErrorRef* error, + const uint8_t* der, uint8_t* der_end) +{ + uint8_t* original_der_end = der_end; + + return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, original_der_end, der, + der_encode_public_bytes(publicKey, error, der, + der_encode_data_or_null(paramters, error, der, der_end))); +} + +static const uint8_t* der_decode_cloud_parameters(CFAllocatorRef allocator, + CFIndex algorithmID, SecKeyRef* publicKey, + CFDataRef *parameters, + CFErrorRef* error, + const uint8_t* der, const uint8_t* der_end) +{ + const uint8_t *sequence_end; + der = ccder_decode_sequence_tl(&sequence_end, der, der_end); + der = der_decode_public_bytes(allocator, algorithmID, publicKey, error, der, sequence_end); + der = der_decode_data_or_null(allocator, parameters, error, der, sequence_end); + + return der; +} + + +bool SOSAccountPublishCloudParameters(SOSAccountRef account, CFErrorRef* error){ + bool success = false; + CFIndex cloud_der_len = der_sizeof_cloud_parameters( + account->user_public, + account->user_key_parameters, + error); + CFMutableDataRef cloudParameters = + CFDataCreateMutableWithScratch(kCFAllocatorDefault, cloud_der_len); + + if (der_encode_cloud_parameters(account->user_public, account->user_key_parameters, error, + CFDataGetMutableBytePtr(cloudParameters), + CFDataGetMutablePastEndPtr(cloudParameters)) != NULL) { + + CFErrorRef changeError = NULL; + if (SOSTrasnportKeyParameterPublishCloudParameters(account->key_transport, cloudParameters, error)) { + success = true; + } else { + SOSCreateErrorWithFormat(kSOSErrorSendFailure, changeError, error, NULL, + CFSTR("update parameters key failed [%@]"), cloudParameters); + } + CFReleaseSafe(changeError); + } else { + SOSCreateError(kSOSErrorEncodeFailure, CFSTR("Encoding parameters failed"), NULL, error); + } + + CFReleaseNull(cloudParameters); + + return success; +} + +bool SOSAccountRetrieveCloudParameters(SOSAccountRef account, SecKeyRef *newKey, + CFDataRef derparms, + CFDataRef *newParameters, CFErrorRef* error) { + const uint8_t *parse_end = der_decode_cloud_parameters(kCFAllocatorDefault, kSecECDSAAlgorithmID, + newKey, newParameters, error, + CFDataGetBytePtr(derparms), CFDataGetPastEndPtr(derparms)); + + if (parse_end == CFDataGetPastEndPtr(derparms)) return true; + return false; +} + diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSAccountCredentials.c b/Security/sec/SOSCircle/SecureObjectSync/SOSAccountCredentials.c new file mode 100644 index 00000000..ac0368d4 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSAccountCredentials.c @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include "SOSAccountPriv.h" +#include "SOSPeerInfoCollections.h" +#include "SOSTransport.h" + +// +// MARK: User Credential management +// + +void SOSAccountSetPreviousPublic(SOSAccountRef account) { + CFReleaseNull(account->previous_public); + account->previous_public = account->user_public; + CFRetain(account->previous_public); +} + +static void SOSAccountRemoveInvalidApplications(SOSAccountRef account, SOSCircleRef circle) +{ + CFMutableSetRef peersToRemove = CFSetCreateMutableForSOSPeerInfosByID(kCFAllocatorDefault); + SOSCircleForEachApplicant(circle, ^(SOSPeerInfoRef peer) { + if (!SOSPeerInfoApplicationVerify(peer, account->user_public, NULL)) + CFSetAddValue(peersToRemove, peer); + }); + + CFSetForEach(peersToRemove, ^(const void *value) { + SOSPeerInfoRef peer = (SOSPeerInfoRef) value; + + SOSCircleWithdrawRequest(circle, peer, NULL); + }); +} + +static void SOSAccountGenerationSignatureUpdate(SOSAccountRef account, SecKeyRef privKey) { + + SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { + SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircle(account, circle, NULL); + if(SOSCircleHasPeer(circle, SOSFullPeerInfoGetPeerInfo(fpi), NULL) && + !SOSCircleVerify(circle, account->user_public, NULL)) { + SOSAccountModifyCircle(account, SOSCircleGetName(circle), NULL, ^(SOSCircleRef circle) { + SOSAccountRemoveInvalidApplications(account, circle); // We might be updating our signatures so remove, but don't reject applicants + + SOSFullPeerInfoRef cloud_fpi = SOSCircleGetiCloudFullPeerInfoRef(circle); + require_quiet(cloud_fpi != NULL, gen_sign); + require_quiet(SOSFullPeerInfoUpgradeSignatures(cloud_fpi, privKey, NULL), gen_sign); + if(!SOSCircleUpdatePeerInfo(circle, SOSFullPeerInfoGetPeerInfo(cloud_fpi))) { + } + gen_sign: // finally generation sign this. + SOSCircleGenerationUpdate(circle, privKey, fpi, NULL); + account->departure_code = kSOSNeverLeftCircle; + return (bool) true; + }); + } + }); +} + + +/* this one is meant to be local - not published over KVS. */ +static void SOSAccountPeerSignatureUpdate(SOSAccountRef account, SecKeyRef privKey) { + SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { + SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircle(account, circle, NULL); + if (fpi) + SOSFullPeerInfoUpgradeSignatures(fpi, privKey, NULL); + }); +} + + +void SOSAccountPurgePrivateCredential(SOSAccountRef account) +{ + CFReleaseNull(account->_user_private); + if (account->user_private_timer) { + dispatch_source_cancel(account->user_private_timer); + dispatch_release(account->user_private_timer); + account->user_private_timer = NULL; + xpc_transaction_end(); + } + if (account->lock_notification_token) { + notify_cancel(account->lock_notification_token); + account->lock_notification_token = 0; + } +} + + +static void SOSAccountSetTrustedUserPublicKey(SOSAccountRef account, bool public_was_trusted, SecKeyRef privKey) +{ + if (!privKey) return; + SecKeyRef publicKey = SecKeyCreatePublicFromPrivate(privKey); + + if (account->user_public && account->user_public_trusted && CFEqual(publicKey, account->user_public)) return; + + if(public_was_trusted && account->user_public) { + CFReleaseNull(account->previous_public); + account->previous_public = account->user_public; + CFRetain(account->previous_public); + } + + CFReleaseNull(account->user_public); + account->user_public = publicKey; + account->user_public_trusted = true; + + if(!account->previous_public) { + account->previous_public = account->user_public; + CFRetain(account->previous_public); + } + + secnotice("trust", "trusting new public key: %@", account->user_public); +} + + +static void SOSAccountSetPrivateCredential(SOSAccountRef account, SecKeyRef private) { + if (!private) + return SOSAccountPurgePrivateCredential(account); + + CFRetain(private); + CFReleaseSafe(account->_user_private); + account->_user_private = private; + + bool resume_timer = false; + if (!account->user_private_timer) { + xpc_transaction_begin(); + resume_timer = true; + account->user_private_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, account->queue); + dispatch_source_set_event_handler(account->user_private_timer, ^{ + SOSAccountPurgePrivateCredential(account); + }); + + notify_register_dispatch(kUserKeybagStateChangeNotification, &account->lock_notification_token, account->queue, ^(int token) { + bool locked = false; + CFErrorRef lockCheckError = NULL; + + if (!SecAKSGetIsLocked(&locked, &lockCheckError)) { + secerror("Checking for locked after change failed: %@", lockCheckError); + } + + if (locked) { + SOSAccountPurgePrivateCredential(account); + } + }); + } + + // (Re)set the timer's fire time to now + 120 seconds with a 5 second fuzz factor. + dispatch_time_t purgeTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * 60 * NSEC_PER_SEC)); + dispatch_source_set_timer(account->user_private_timer, purgeTime, DISPATCH_TIME_FOREVER, (int64_t)(5 * NSEC_PER_SEC)); + if (resume_timer) + dispatch_resume(account->user_private_timer); +} + +SecKeyRef SOSAccountGetPrivateCredential(SOSAccountRef account, CFErrorRef* error) +{ + if (account->_user_private == NULL) { + SOSCreateError(kSOSErrorPrivateKeyAbsent, CFSTR("Private Key not available - failed to prompt user recently"), NULL, error); + } + return account->_user_private; +} + +bool SOSAccountHasPublicKey(SOSAccountRef account, CFErrorRef* error) +{ + if (account->user_public == NULL || account->user_public_trusted == false) { + SOSCreateError(kSOSErrorPublicKeyAbsent, CFSTR("Public Key not available - failed to register before call"), NULL, error); + return false; + } + + return true; +} + +bool SOSAccountAssertUserCredentials(SOSAccountRef account, CFStringRef user_account __unused, CFDataRef user_password, CFErrorRef *error) +{ + bool public_was_trusted = account->user_public_trusted; + account->user_public_trusted = false; + SecKeyRef user_private = NULL; + + if (account->user_public && account->user_key_parameters) { + // We have an untrusted public key – see if our generation makes the same key: + // if so we trust it and we have the private key. + // if not we still don't trust it. + require_quiet(user_private = SOSUserKeygen(user_password, account->user_key_parameters, error), exit); + SecKeyRef public_candidate = SecKeyCreatePublicFromPrivate(user_private); + if (!CFEqualSafe(account->user_public, public_candidate)) { + secnotice("trust", "Public keys don't match: calculated: %@, expected: %@", + account->user_public, public_candidate); + debugDumpUserParameters(CFSTR("params"), account->user_key_parameters); + CFReleaseNull(user_private); + } else { + SOSAccountPeerSignatureUpdate(account, user_private); + SOSAccountSetTrustedUserPublicKey(account, public_was_trusted, user_private); + } + CFReleaseSafe(public_candidate); + } + + if (!account->user_public_trusted) { + // We may or may not have parameters here. + // In any case we tried using them and they didn't match + // So forget all that and start again, assume we're the first to push anything useful. + + CFReleaseNull(account->user_key_parameters); + account->user_key_parameters = SOSUserKeyCreateGenerateParameters(error); + require_quiet(user_private = SOSUserKeygen(user_password, account->user_key_parameters, error), exit); + + SOSAccountPeerSignatureUpdate(account, user_private); + SOSAccountSetTrustedUserPublicKey(account, public_was_trusted, user_private); + + CFErrorRef publishError = NULL; + if (!SOSAccountPublishCloudParameters(account, &publishError)) + secerror("Failed to publish new cloud parameters: %@", publishError); + CFReleaseSafe(publishError); + } + + SOSAccountGenerationSignatureUpdate(account, user_private); + SOSAccountSetPrivateCredential(account, user_private); +exit: + SOSUpdateKeyInterest(); + + CFReleaseSafe(user_private); + + return account->user_public_trusted; +} + + +bool SOSAccountTryUserCredentials(SOSAccountRef account, CFStringRef user_account __unused, CFDataRef user_password, CFErrorRef *error) +{ + bool success = false; + + if (!SOSAccountHasPublicKey(account, error)) + return false; + + if (account->user_key_parameters) { + SecKeyRef new_key = SOSUserKeygen(user_password, account->user_key_parameters, error); + if (new_key) { + SecKeyRef new_public_key = SecKeyCreatePublicFromPrivate(new_key); + + if (CFEqualSafe(new_public_key, account->user_public)) { + SOSAccountSetPrivateCredential(account, new_key); + success = true; + } else { + SOSCreateError(kSOSErrorWrongPassword, CFSTR("Password passed in incorrect: ▇█████▇▇██"), NULL, error); + } + CFReleaseSafe(new_public_key); + CFReleaseSafe(new_key); + } + } else { + SOSCreateError(kSOSErrorProcessingFailure, CFSTR("Have public key but no parameters??"), NULL, error); + } + + return success; +} diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSAccountDer.c b/Security/sec/SOSCircle/SecureObjectSync/SOSAccountDer.c new file mode 100644 index 00000000..fc41dcd8 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSAccountDer.c @@ -0,0 +1,153 @@ +/* + * 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 "SOSAccountPriv.h" + +// +// DER Encoding utilities +// + +// +// Encodes data or a zero length data +// +size_t der_sizeof_data_or_null(CFDataRef data, CFErrorRef* error) +{ + if (data) { + return der_sizeof_data(data, error); + } else { + return der_sizeof_null(kCFNull, error); + } +} + +uint8_t* der_encode_data_or_null(CFDataRef data, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) +{ + if (data) { + return der_encode_data(data, error, der, der_end); + } else { + return der_encode_null(kCFNull, error, der, der_end); + } +} + + +const uint8_t* der_decode_data_or_null(CFAllocatorRef allocator, CFDataRef* data, + CFErrorRef* error, + const uint8_t* der, const uint8_t* der_end) +{ + CFTypeRef value = NULL; + der = der_decode_plist(allocator, 0, &value, error, der, der_end); + if (value && CFGetTypeID(value) != CFDataGetTypeID()) { + CFReleaseNull(value); + } + if (data) { + *data = value; + } + return der; +} + + +// +// Mark: public_bytes encode/decode +// + +size_t der_sizeof_public_bytes(SecKeyRef publicKey, CFErrorRef* error) +{ + CFDataRef publicData = NULL; + + if (publicKey) + SecKeyCopyPublicBytes(publicKey, &publicData); + + size_t size = der_sizeof_data_or_null(publicData, error); + + CFReleaseNull(publicData); + + return size; +} + +uint8_t* der_encode_public_bytes(SecKeyRef publicKey, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) +{ + CFDataRef publicData = NULL; + + if (publicKey) + SecKeyCopyPublicBytes(publicKey, &publicData); + + uint8_t *result = der_encode_data_or_null(publicData, error, der, der_end); + + CFReleaseNull(publicData); + + return result; +} + +const uint8_t* der_decode_public_bytes(CFAllocatorRef allocator, CFIndex algorithmID, SecKeyRef* publicKey, CFErrorRef* error, const uint8_t* der, const uint8_t* der_end) +{ + CFDataRef dataFound = NULL; + der = der_decode_data_or_null(allocator, &dataFound, error, der, der_end); + + if (der && dataFound && publicKey) { + *publicKey = SecKeyCreateFromPublicData(allocator, algorithmID, dataFound); + } + CFReleaseNull(dataFound); + + return der; +} + + + + +// +// bool encoding/decoding +// + + +const uint8_t* ccder_decode_bool(bool* boolean, const uint8_t* der, const uint8_t *der_end) +{ + if (NULL == der) + return NULL; + + size_t payload_size = 0; + const uint8_t *payload = ccder_decode_tl(CCDER_BOOLEAN, &payload_size, der, der_end); + + if (NULL == payload || (der_end - payload) < 1 || payload_size != 1) { + return NULL; + } + + if (boolean) + *boolean = (*payload != 0); + + return payload + payload_size; +} + + +size_t ccder_sizeof_bool(bool value __unused, CFErrorRef *error) +{ + return ccder_sizeof(CCDER_BOOLEAN, 1); +} + + +uint8_t* ccder_encode_bool(bool value, const uint8_t *der, uint8_t *der_end) +{ + uint8_t value_byte = value; + + return ccder_encode_tl(CCDER_BOOLEAN, 1, der, + ccder_encode_body(1, &value_byte, der, der_end)); +} diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSAccountFullPeerInfo.c b/Security/sec/SOSCircle/SecureObjectSync/SOSAccountFullPeerInfo.c new file mode 100644 index 00000000..45d2cf43 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSAccountFullPeerInfo.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include "SOSAccountPriv.h" + +static CFStringRef kicloud_identity_name = CFSTR("Cloud Identity"); + + +SOSFullPeerInfoRef CopyCloudKeychainIdentity(SOSPeerInfoRef cloudPeer, CFErrorRef *error) { + return SOSFullPeerInfoCreateCloudIdentity(NULL, cloudPeer, error); +} + + +SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircleNamedIfPresent(SOSAccountRef account, CFStringRef name, CFErrorRef *error) { + if (CFDictionaryGetValue(account->circles, name) == NULL) { + SOSCreateErrorWithFormat(kSOSErrorNoCircle, NULL, error, NULL, CFSTR("No circle named '%@'"), name); + return NULL; + } + + return (SOSFullPeerInfoRef) CFDictionaryGetValue(account->circle_identities, name); +} + + + +static SecKeyRef GeneratePermanentFullECKey_internal(int keySize, CFStringRef name, CFTypeRef accessibility, CFBooleanRef sync, CFErrorRef* error) +{ + SecKeyRef full_key = NULL; + + CFNumberRef key_size_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &keySize); + + CFDictionaryRef priv_key_attrs = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecAttrIsPermanent, kCFBooleanTrue, + NULL); + + CFDictionaryRef keygen_parameters = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecAttrKeyType, kSecAttrKeyTypeEC, + kSecAttrKeySizeInBits, key_size_num, + kSecPrivateKeyAttrs, priv_key_attrs, + kSecAttrAccessible, accessibility, + kSecAttrAccessGroup, kSOSInternalAccessGroup, + kSecAttrLabel, name, + kSecAttrSynchronizable, sync, + kSecUseTombstones, kCFBooleanTrue, + NULL); + + CFReleaseNull(priv_key_attrs); + + CFReleaseNull(key_size_num); + OSStatus status = SecKeyGeneratePair(keygen_parameters, NULL, &full_key); + CFReleaseNull(keygen_parameters); + + if (status) + secerror("status: %ld", (long)status); + if (status != errSecSuccess && error != NULL && *error == NULL) { + *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus, status, NULL); + } + + return full_key; +} + +static SecKeyRef GeneratePermanentFullECKey(int keySize, CFStringRef name, CFErrorRef* error) { + return GeneratePermanentFullECKey_internal(keySize, name, kSecAttrAccessibleWhenUnlockedThisDeviceOnly, kCFBooleanFalse, error); +} + +static SecKeyRef GeneratePermanentFullECKeyForCloudIdentity(int keySize, CFStringRef name, CFErrorRef* error) { + return GeneratePermanentFullECKey_internal(keySize, name, kSecAttrAccessibleWhenUnlocked, kCFBooleanTrue, error); +} + + +bool SOSAccountIsAccountIdentity(SOSAccountRef account, SOSPeerInfoRef peer_info, CFErrorRef *error) +{ + __block bool matches = false; + CFDictionaryForEach(account->circle_identities, ^(const void *key, const void *value) { + if (!matches) { + matches = CFEqual(peer_info, SOSFullPeerInfoGetPeerInfo((SOSFullPeerInfoRef) value)); + } + }); + + return matches; +} + + + +SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircleNamed(SOSAccountRef account, CFStringRef name, CFErrorRef *error) { + if (CFDictionaryGetValue(account->circles, name) == NULL) { + SOSCreateErrorWithFormat(kSOSErrorNoCircle, NULL, error, NULL, CFSTR("No circle named '%@'"), name); + return NULL; + } + SOSFullPeerInfoRef circle_full_peer_info = (SOSFullPeerInfoRef) CFDictionaryGetValue(account->circle_identities, name); + + + if (circle_full_peer_info == NULL) { + CFStringRef keyName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("ID for %@-%@"), SOSPeerGestaltGetName(account->gestalt), name); + SecKeyRef full_key = GeneratePermanentFullECKey(256, keyName, error); + CFReleaseNull(keyName); + + if (full_key) { + circle_full_peer_info = SOSFullPeerInfoCreate(kCFAllocatorDefault, account->gestalt, full_key, error); + + CFReleaseNull(full_key); + + if (!circle_full_peer_info) { + secerror("Can't make FullPeerInfo for %@-%@ (%@) - is AKS ok?", SOSPeerGestaltGetName(account->gestalt), name, error ? (void*)*error : (void*)CFSTR("-")); + return circle_full_peer_info; + } + + CFDictionarySetValue(account->circle_identities, name, circle_full_peer_info); + CFReleaseNull(circle_full_peer_info); + circle_full_peer_info = (SOSFullPeerInfoRef) CFDictionaryGetValue(account->circle_identities, name); + } + else + secerror("No full_key: %@:", error ? *error : NULL); + } + + return circle_full_peer_info; +} + + +SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error) { + return SOSAccountGetMyFullPeerInCircleNamed(account, SOSCircleGetName(circle), error); +} + + +SOSPeerInfoRef GenerateNewCloudIdentityPeerInfo(CFErrorRef *error) { + SecKeyRef cloud_key = GeneratePermanentFullECKeyForCloudIdentity(256, kicloud_identity_name, error); + SOSPeerInfoRef cloud_peer = NULL; + CFDictionaryRef query = NULL; + CFDictionaryRef change = NULL; + CFStringRef new_name = NULL; + + CFDictionaryRef gestalt = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kPIUserDefinedDeviceName, CFSTR("iCloud"), + NULL); + require_action_quiet(gestalt, fail, SecError(errSecAllocate, error, CFSTR("Can't allocate gestalt"))); + + cloud_peer = SOSPeerInfoCreateCloudIdentity(kCFAllocatorDefault, gestalt, cloud_key, error); + + require(cloud_peer, fail); + + query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecClass, kSecClassKey, + kSecAttrSynchronizable,kCFBooleanTrue, + kSecUseTombstones, kCFBooleanTrue, + kSecValueRef, cloud_key, + NULL); + + new_name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, + CFSTR("Cloud Identity - '%@'"), SOSPeerInfoGetPeerID(cloud_peer)); + + change = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecAttrLabel, new_name, + NULL); + + SecError(SecItemUpdate(query, change), error, CFSTR("Couldn't update name")); + +fail: + CFReleaseNull(new_name); + CFReleaseNull(query); + CFReleaseNull(change); + CFReleaseNull(gestalt); + CFReleaseNull(cloud_key); + + return cloud_peer; +} diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSAccountPeers.c b/Security/sec/SOSCircle/SecureObjectSync/SOSAccountPeers.c new file mode 100644 index 00000000..d0e0ca03 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSAccountPeers.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include "SOSAccountPriv.h" +#include + + +bool SOSAccountDestroyCirclePeerInfoNamed(SOSAccountRef account, CFStringRef name, CFErrorRef* error) { + if (CFDictionaryGetValue(account->circles, name) == NULL) { + SOSCreateErrorWithFormat(kSOSErrorNoCircle, NULL, error, NULL, CFSTR("No circle named '%@'"), name); + return false; + } + + SOSFullPeerInfoRef circle_full_peer_info = (SOSFullPeerInfoRef) CFDictionaryGetValue(account->circle_identities, name); + + if (circle_full_peer_info) { + SOSFullPeerInfoPurgePersistentKey(circle_full_peer_info, NULL); + } + + CFDictionaryRemoveValue(account->circle_identities, name); + + return true; +} + +bool SOSAccountDestroyCirclePeerInfo(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error) { + return SOSAccountDestroyCirclePeerInfoNamed(account, SOSCircleGetName(circle), error); +} + +SOSPeerInfoRef SOSAccountGetMyPeerInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error) { + SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircleNamed(account, SOSCircleGetName(circle), error); + + return fpi ? SOSFullPeerInfoGetPeerInfo(fpi) : NULL; +} + +SOSPeerInfoRef SOSAccountGetMyPeerInCircleNamed(SOSAccountRef account, CFStringRef name, CFErrorRef *error) +{ + SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircleNamed(account, name, error); + + return fpi ? SOSFullPeerInfoGetPeerInfo(fpi) : NULL; +} + + +bool SOSAccountIsActivePeerInCircleNamed(SOSAccountRef account, CFStringRef circle_name, CFStringRef peerid, CFErrorRef* error) { + SOSCircleRef circle = SOSAccountFindCircle(account, circle_name, error); + if(!circle) return false; + return SOSCircleHasActivePeerWithID(circle, peerid, error); +} + +bool SOSAccountIsMyPeerActiveInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error) { + SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircleNamedIfPresent(account, SOSCircleGetName(circle), NULL); + if(!fpi) return false; + return SOSCircleHasActivePeer(circle, SOSFullPeerInfoGetPeerInfo(fpi), error); +} + +bool SOSAccountIsMyPeerActiveInCircleNamed(SOSAccountRef account, CFStringRef circle_name, CFErrorRef* error) { + SOSFullPeerInfoRef myfpi = SOSAccountGetMyFullPeerInCircleNamedIfPresent(account, circle_name, NULL); + if(!myfpi) return false; + SOSPeerInfoRef mypi = SOSFullPeerInfoGetPeerInfo(myfpi); + if(!mypi) return false; + CFStringRef peerid = SOSPeerInfoGetPeerID(mypi); + if (!peerid) return false; + return SOSAccountIsActivePeerInCircleNamed(account, circle_name, peerid, error); +} + + +// +// MARK: Peer Querying +// +static CFArrayRef SOSAccountCopySortedPeerArray(SOSAccountRef account, + CFErrorRef *error, + void (^action)(SOSCircleRef circle, CFMutableArrayRef appendPeersTo)) { + if (!SOSAccountHasPublicKey(account, error)) + return NULL; + + CFMutableArrayRef peers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + + SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { + action(circle, peers); + }); + + CFArrayOfSOSPeerInfosSortByID(peers); + + return peers; +} + + +CFArrayRef SOSAccountCopyNotValidPeers(SOSAccountRef account, CFErrorRef *error) { + return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) { + SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { + if(!SOSPeerInfoApplicationVerify(peer, account->user_public, NULL)) { + CFArrayAppendValue(appendPeersTo, peer); + } + }); + }); +} + + +CFArrayRef SOSAccountCopyValidPeers(SOSAccountRef account, CFErrorRef *error) { + return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) { + SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { + if(SOSPeerInfoApplicationVerify(peer, account->user_public, NULL)) { + CFArrayAppendValue(appendPeersTo, peer); + } + }); + }); +} + + +CFArrayRef SOSAccountCopyRetired(SOSAccountRef account, CFErrorRef *error) { + return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) { + SOSCircleForEachRetiredPeer(circle, ^(SOSPeerInfoRef peer) { + CFArrayAppendValue(appendPeersTo, peer); + }); + }); +} + +CFArrayRef SOSAccountCopyApplicants(SOSAccountRef account, CFErrorRef *error) { + return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) { + SOSCircleForEachApplicant(circle, ^(SOSPeerInfoRef peer) { + CFArrayAppendValue(appendPeersTo, peer); + }); + }); +} + +CFArrayRef SOSAccountCopyPeers(SOSAccountRef account, CFErrorRef *error) { + return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) { + SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { + CFArrayAppendValue(appendPeersTo, peer); + }); + }); +} + +CFArrayRef SOSAccountCopyActivePeers(SOSAccountRef account, CFErrorRef *error) { + return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) { + SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { + CFArrayAppendValue(appendPeersTo, peer); + }); + }); +} + +CFArrayRef SOSAccountCopyActiveValidPeers(SOSAccountRef account, CFErrorRef *error) { + return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) { + SOSCircleForEachActiveValidPeer(circle, account->user_public, ^(SOSPeerInfoRef peer) { + CFArrayAppendValue(appendPeersTo, peer); + }); + }); +} + +CFArrayRef SOSAccountCopyConcurringPeers(SOSAccountRef account, CFErrorRef *error) +{ + return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) { + SOSCircleAppendConcurringPeers(circle, appendPeersTo, NULL); + }); +} diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSAccountPersistence.c b/Security/sec/SOSCircle/SecureObjectSync/SOSAccountPersistence.c new file mode 100644 index 00000000..c9eaa4f3 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSAccountPersistence.c @@ -0,0 +1,709 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include +#include +#include +#include "SOSAccountPriv.h" + +#include +#include + +SOSAccountRef SOSAccountCreateFromDER_V1(CFAllocatorRef allocator, + SOSDataSourceFactoryRef factory, + CFErrorRef* error, + const uint8_t** der_p, const uint8_t *der_end) +{ + SOSAccountRef account = NULL; + + const uint8_t *sequence_end; + *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); + + { + CFDictionaryRef decoded_gestalt = NULL; + *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, + *der_p, der_end); + + if (*der_p == 0) + return NULL; + + account = SOSAccountCreateBasic(allocator, decoded_gestalt, factory); + CFReleaseNull(decoded_gestalt); + } + + CFArrayRef array = NULL; + *der_p = der_decode_array(kCFAllocatorDefault, 0, &array, error, *der_p, sequence_end); + + *der_p = ccder_decode_bool(&account->user_public_trusted, *der_p, sequence_end); + *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->user_public, error, *der_p, sequence_end); + *der_p = der_decode_data_or_null(kCFAllocatorDefault, &account->user_key_parameters, error, *der_p, sequence_end); + *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *) &account->retired_peers, error, *der_p, sequence_end); + if (*der_p != sequence_end) + *der_p = NULL; + + __block bool success = true; + + require_quiet(array && *der_p, fail); + + CFArrayForEach(array, ^(const void *value) { + if (success) { + if (isString(value)) { + CFDictionaryAddValue(account->circles, value, kCFNull); + } else { + CFDataRef circleData = NULL; + CFDataRef fullPeerInfoData = NULL; + + if (isData(value)) { + circleData = (CFDataRef) value; + } else if (isArray(value)) { + CFArrayRef pair = (CFArrayRef) value; + + CFTypeRef circleObject = CFArrayGetValueAtIndex(pair, 0); + CFTypeRef fullPeerInfoObject = CFArrayGetValueAtIndex(pair, 1); + + if (CFArrayGetCount(pair) == 2 && isData(circleObject) && isData(fullPeerInfoObject)) { + circleData = (CFDataRef) circleObject; + fullPeerInfoData = (CFDataRef) fullPeerInfoObject; + } + } + + if (circleData) { + SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, circleData, error); + require_action_quiet(circle, fail, success = false); + + CFStringRef circleName = SOSCircleGetName(circle); + CFDictionaryAddValue(account->circles, circleName, circle); + + if (fullPeerInfoData) { + SOSFullPeerInfoRef full_peer = SOSFullPeerInfoCreateFromData(kCFAllocatorDefault, fullPeerInfoData, error); + require_action_quiet(full_peer, fail, success = false); + + CFDictionaryAddValue(account->circle_identities, circleName, full_peer); + CFReleaseNull(full_peer); + } + fail: + CFReleaseNull(circle); + } + } + } + }); + CFReleaseNull(array); + + require_quiet(success, fail); + require_action_quiet(SOSAccountEnsureFactoryCircles(account), fail, + SOSCreateError(kSOSErrorBadFormat, CFSTR("Cannot EnsureFactoryCircles"), (error != NULL) ? *error : NULL, error)); + + return account; + +fail: + // Create a default error if we don't have one: + SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Account DER"), NULL, error); + CFReleaseNull(account); + return NULL; +} + +SOSAccountRef SOSAccountCreateFromDER_V2(CFAllocatorRef allocator, + SOSDataSourceFactoryRef factory, + CFErrorRef* error, + const uint8_t** der_p, const uint8_t *der_end) +{ + SOSAccountRef account = NULL; + const uint8_t *dersave = *der_p; + const uint8_t *derend = der_end; + + const uint8_t *sequence_end; + *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); + + { + CFDictionaryRef decoded_gestalt = NULL; + *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, + *der_p, der_end); + + if (*der_p == 0) + return NULL; + + account = SOSAccountCreateBasic(allocator, decoded_gestalt, factory); + CFReleaseNull(decoded_gestalt); + } + + CFArrayRef array = NULL; + *der_p = der_decode_array(kCFAllocatorDefault, 0, &array, error, *der_p, sequence_end); + + uint64_t tmp_departure_code = kSOSNeverAppliedToCircle; + *der_p = ccder_decode_uint64(&tmp_departure_code, *der_p, sequence_end); + *der_p = ccder_decode_bool(&account->user_public_trusted, *der_p, sequence_end); + *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->user_public, error, *der_p, sequence_end); + *der_p = der_decode_data_or_null(kCFAllocatorDefault, &account->user_key_parameters, error, *der_p, sequence_end); + *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *) &account->retired_peers, error, *der_p, sequence_end); + if (*der_p != sequence_end) + *der_p = NULL; + account->departure_code = (enum DepartureReason) tmp_departure_code; + + __block bool success = true; + + require_quiet(array && *der_p, fail); + + CFArrayForEach(array, ^(const void *value) { + if (success) { + if (isString(value)) { + CFDictionaryAddValue(account->circles, value, kCFNull); + } else { + CFDataRef circleData = NULL; + CFDataRef fullPeerInfoData = NULL; + + if (isData(value)) { + circleData = (CFDataRef) value; + } else if (isArray(value)) { + CFArrayRef pair = (CFArrayRef) value; + + CFTypeRef circleObject = CFArrayGetValueAtIndex(pair, 0); + CFTypeRef fullPeerInfoObject = CFArrayGetValueAtIndex(pair, 1); + + if (CFArrayGetCount(pair) == 2 && isData(circleObject) && isData(fullPeerInfoObject)) { + circleData = (CFDataRef) circleObject; + fullPeerInfoData = (CFDataRef) fullPeerInfoObject; + } + } + + if (circleData) { + SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, circleData, error); + require_action_quiet(circle, fail, success = false); + + CFStringRef circleName = SOSCircleGetName(circle); + CFDictionaryAddValue(account->circles, circleName, circle); + + if (fullPeerInfoData) { + SOSFullPeerInfoRef full_peer = SOSFullPeerInfoCreateFromData(kCFAllocatorDefault, fullPeerInfoData, error); + require_action_quiet(full_peer, fail, success = false); + + CFDictionaryAddValue(account->circle_identities, circleName, full_peer); + CFReleaseSafe(full_peer); + } + fail: + CFReleaseNull(circle); + } + } + } + }); + CFReleaseNull(array); + + require_quiet(success, fail); + require_action_quiet(SOSAccountEnsureFactoryCircles(account), fail, + SOSCreateError(kSOSErrorBadFormat, CFSTR("Cannot EnsureFactoryCircles"), (error != NULL) ? *error : NULL, error)); + + return account; + +fail: + // Create a default error if we don't have one: + account->factory = NULL; // give the factory back. + CFReleaseNull(account); + // Try the der inflater from the previous release. + account = SOSAccountCreateFromDER_V1(allocator, factory, error, &dersave, derend); + if(account) account->departure_code = kSOSNeverAppliedToCircle; + return account; +} + +static void SOSAccountConvertKVSDictionaryToRetirementDictionary(SOSAccountRef account) +{ + CFMutableDictionaryRef old_retired_peers = account->retired_peers; + account->retired_peers = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + + CFDictionaryForEach(old_retired_peers, ^(const void *key, const void *value) { + if (isDictionary(value)) { + CFDictionaryAddValue(account->retired_peers, key, value); + } else if (isString(key) && isData(value)) { + CFDataRef retired_peer_data = (CFDataRef) value; + CFStringRef circle_name = NULL; + CFStringRef retired_peer_id = NULL; + + if (kRetirementKey == SOSKVSKeyGetKeyTypeAndParse(key, &circle_name, &retired_peer_id, NULL)) { + CFMutableDictionaryRef circle_retirees = CFDictionaryEnsureCFDictionaryAndGetCurrentValue(account->retired_peers, circle_name); + + CFDictionarySetValue(circle_retirees, retired_peer_id, retired_peer_data); + } + + CFReleaseSafe(circle_name); + CFReleaseSafe(retired_peer_id); + } + }); + CFReleaseSafe(old_retired_peers); +} + + +#define CURRENT_ACCOUNT_PERSISTENT_VERSION 6 + +SOSAccountRef SOSAccountCreateFromDER(CFAllocatorRef allocator, + SOSDataSourceFactoryRef factory, + CFErrorRef* error, + const uint8_t** der_p, const uint8_t *der_end) +{ + SOSAccountRef account = NULL; +#if UPGRADE_FROM_PREVIOUS_VERSION + const uint8_t *dersave = *der_p; + const uint8_t *derend = der_end; +#endif + uint64_t version = 0; + + const uint8_t *sequence_end; + *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); + *der_p = ccder_decode_uint64(&version, *der_p, sequence_end); + if(!(*der_p) || version < CURRENT_ACCOUNT_PERSISTENT_VERSION) { +#if UPGRADE_FROM_PREVIOUS_VERSION + return SOSAccountCreateFromDER_V3(allocator, factory, error, &dersave, derend); +#else + return NULL; +#endif + } + + { + CFDictionaryRef decoded_gestalt = NULL; + *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, + *der_p, der_end); + + if (*der_p == 0) + return NULL; + + account = SOSAccountCreateBasic(allocator, decoded_gestalt, factory); + CFReleaseNull(decoded_gestalt); + } + + CFArrayRef array = NULL; + *der_p = der_decode_array(kCFAllocatorDefault, 0, &array, error, *der_p, sequence_end); + + uint64_t tmp_departure_code = kSOSNeverAppliedToCircle; + *der_p = ccder_decode_uint64(&tmp_departure_code, *der_p, sequence_end); + *der_p = ccder_decode_bool(&account->user_public_trusted, *der_p, sequence_end); + *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->user_public, error, *der_p, sequence_end); + *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->previous_public, error, *der_p, sequence_end); + *der_p = der_decode_data_or_null(kCFAllocatorDefault, &account->user_key_parameters, error, *der_p, sequence_end); + *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *) &account->retired_peers, error, *der_p, sequence_end); + if (*der_p != sequence_end) + *der_p = NULL; + account->departure_code = (enum DepartureReason) tmp_departure_code; + + __block bool success = true; + + require_quiet(array && *der_p, fail); + + CFArrayForEach(array, ^(const void *value) { + if (success) { + if (isString(value)) { + CFDictionaryAddValue(account->circles, value, kCFNull); + } else { + CFDataRef circleData = NULL; + CFDataRef fullPeerInfoData = NULL; + + if (isData(value)) { + circleData = (CFDataRef) value; + } else if (isArray(value)) { + CFArrayRef pair = (CFArrayRef) value; + + CFTypeRef circleObject = CFArrayGetValueAtIndex(pair, 0); + CFTypeRef fullPeerInfoObject = CFArrayGetValueAtIndex(pair, 1); + + if (CFArrayGetCount(pair) == 2 && isData(circleObject) && isData(fullPeerInfoObject)) { + circleData = (CFDataRef) circleObject; + fullPeerInfoData = (CFDataRef) fullPeerInfoObject; + } + } + + if (circleData) { + SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, circleData, error); + require_action_quiet(circle, fail, success = false); + + CFStringRef circleName = SOSCircleGetName(circle); + CFDictionaryAddValue(account->circles, circleName, circle); + + if (fullPeerInfoData) { + SOSFullPeerInfoRef full_peer = SOSFullPeerInfoCreateFromData(kCFAllocatorDefault, fullPeerInfoData, error); + require_action_quiet(full_peer, fail, success = false); + + CFDictionaryAddValue(account->circle_identities, circleName, full_peer); + CFReleaseNull(full_peer); + } + fail: + CFReleaseNull(circle); + } + } + } + }); + CFReleaseNull(array); + + require_quiet(success, fail); + require_action_quiet(SOSAccountEnsureFactoryCircles(account), fail, + SOSCreateError(kSOSErrorBadFormat, CFSTR("Cannot EnsureFactoryCircles"), (error != NULL) ? *error : NULL, error)); + + SOSAccountConvertKVSDictionaryToRetirementDictionary(account); + + return account; + +fail: + account->factory = NULL; // give the factory back. + CFReleaseNull(account); + return NULL; +} + + +SOSAccountRef SOSAccountCreateFromDER_V3(CFAllocatorRef allocator, + SOSDataSourceFactoryRef factory, + CFErrorRef* error, + const uint8_t** der_p, const uint8_t *der_end) +{ + SOSAccountRef account = NULL; + uint64_t version = 0; + + const uint8_t *sequence_end; + *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); + *der_p = ccder_decode_uint64(&version, *der_p, sequence_end); + if(!(*der_p) || version != 3) { + // In this case we want to silently fail so that an account gets newly created. + return NULL; + } + + { + CFDictionaryRef decoded_gestalt = NULL; + *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, + *der_p, der_end); + + if (*der_p == 0) + return NULL; + + account = SOSAccountCreateBasic(allocator, decoded_gestalt, factory); + CFReleaseNull(decoded_gestalt); + } + + CFArrayRef array = NULL; + *der_p = der_decode_array(kCFAllocatorDefault, 0, &array, error, *der_p, sequence_end); + + uint64_t tmp_departure_code = kSOSNeverAppliedToCircle; + *der_p = ccder_decode_uint64(&tmp_departure_code, *der_p, sequence_end); + *der_p = ccder_decode_bool(&account->user_public_trusted, *der_p, sequence_end); + *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->user_public, error, *der_p, sequence_end); + *der_p = der_decode_data_or_null(kCFAllocatorDefault, &account->user_key_parameters, error, *der_p, sequence_end); + *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *) &account->retired_peers, error, *der_p, sequence_end); + if (*der_p != sequence_end) + *der_p = NULL; + account->departure_code = (enum DepartureReason) tmp_departure_code; + + __block bool success = true; + + require_quiet(array && *der_p, fail); + + CFArrayForEach(array, ^(const void *value) { + if (success) { + if (isString(value)) { + CFDictionaryAddValue(account->circles, value, kCFNull); + } else { + CFDataRef circleData = NULL; + CFDataRef fullPeerInfoData = NULL; + + if (isData(value)) { + circleData = (CFDataRef) value; + } else if (isArray(value)) { + CFArrayRef pair = (CFArrayRef) value; + + CFTypeRef circleObject = CFArrayGetValueAtIndex(pair, 0); + CFTypeRef fullPeerInfoObject = CFArrayGetValueAtIndex(pair, 1); + + if (CFArrayGetCount(pair) == 2 && isData(circleObject) && isData(fullPeerInfoObject)) { + circleData = (CFDataRef) circleObject; + fullPeerInfoData = (CFDataRef) fullPeerInfoObject; + } + } + + if (circleData) { + SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, circleData, error); + require_action_quiet(circle, fail, success = false); + + CFStringRef circleName = SOSCircleGetName(circle); + CFDictionaryAddValue(account->circles, circleName, circle); + + if (fullPeerInfoData) { + SOSFullPeerInfoRef full_peer = SOSFullPeerInfoCreateFromData(kCFAllocatorDefault, fullPeerInfoData, error); + require_action_quiet(full_peer, fail, success = false); + + CFDictionaryAddValue(account->circle_identities, circleName, full_peer); + CFReleaseNull(full_peer); + } + fail: + CFReleaseNull(circle); + } + } + } + }); + CFReleaseNull(array); + + require_quiet(success, fail); + require_action_quiet(SOSAccountEnsureFactoryCircles(account), fail, + SOSCreateError(kSOSErrorBadFormat, CFSTR("Cannot EnsureFactoryCircles"), (error != NULL) ? *error : NULL, error)); + + SOSAccountConvertKVSDictionaryToRetirementDictionary(account); + + return account; + +fail: + // Create a default error if we don't have one: + account->factory = NULL; // give the factory back. + CFReleaseNull(account); + // Don't try the der inflater from the previous release. + // account = SOSAccountCreateFromDER_V2(allocator, transport, factory, error, &dersave, derend); + if(account) account->departure_code = kSOSNeverAppliedToCircle; + return account; +} + +SOSAccountRef SOSAccountCreateFromData(CFAllocatorRef allocator, CFDataRef circleData, + SOSDataSourceFactoryRef factory, + CFErrorRef* error) +{ + size_t size = CFDataGetLength(circleData); + const uint8_t *der = CFDataGetBytePtr(circleData); + SOSAccountRef account = SOSAccountCreateFromDER(allocator, factory, + error, + &der, der + size); + return account; +} + +static CFMutableArrayRef SOSAccountCopyCircleArrayToEncode(SOSAccountRef account) +{ + CFMutableArrayRef arrayToEncode = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + + CFDictionaryForEach(account->circles, ^(const void *key, const void *value) { + if (isNull(value)) { + CFArrayAppendValue(arrayToEncode, key); // Encode the name of the circle that's out of date. + } else { + SOSCircleRef circle = (SOSCircleRef) value; + CFDataRef encodedCircle = SOSCircleCopyEncodedData(circle, kCFAllocatorDefault, NULL); + CFTypeRef arrayEntry = encodedCircle; + CFRetainSafe(arrayEntry); + + SOSFullPeerInfoRef full_peer = (SOSFullPeerInfoRef) CFDictionaryGetValue(account->circle_identities, key); + + if (full_peer) { + CFDataRef encodedPeer = SOSFullPeerInfoCopyEncodedData(full_peer, kCFAllocatorDefault, NULL); + CFTypeRef originalArrayEntry = arrayEntry; + arrayEntry = CFArrayCreateForCFTypes(kCFAllocatorDefault, encodedCircle, encodedPeer, NULL); + + CFReleaseSafe(originalArrayEntry); + CFReleaseNull(encodedPeer); + } + + CFArrayAppendValue(arrayToEncode, arrayEntry); + + CFReleaseSafe(arrayEntry); + CFReleaseNull(encodedCircle); + } + + }); + + return arrayToEncode; +} + +size_t SOSAccountGetDEREncodedSize(SOSAccountRef account, CFErrorRef *error) +{ + size_t sequence_size = 0; + CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); + uint64_t version = CURRENT_ACCOUNT_PERSISTENT_VERSION; + + require_quiet(accumulate_size(&sequence_size, ccder_sizeof_uint64(version)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->gestalt, error)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_array(arrayToEncode, error)), fail); + require_quiet(accumulate_size(&sequence_size, ccder_sizeof_uint64(account->departure_code)), fail); + require_quiet(accumulate_size(&sequence_size, ccder_sizeof_bool(account->user_public_trusted, error)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account->user_public, error)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account->previous_public, error)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_data_or_null(account->user_key_parameters, error)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->retired_peers, error)), fail); + + CFReleaseNull(arrayToEncode); + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, sequence_size); + +fail: + CFReleaseNull(arrayToEncode); + SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error); + return 0; +} + +uint8_t* SOSAccountEncodeToDER(SOSAccountRef account, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) +{ + CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); + uint64_t version = CURRENT_ACCOUNT_PERSISTENT_VERSION; + der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + ccder_encode_uint64(version, der, + der_encode_dictionary(account->gestalt, error, der, + der_encode_array(arrayToEncode, error, der, + ccder_encode_uint64(account->departure_code, der, + ccder_encode_bool(account->user_public_trusted, der, + der_encode_public_bytes(account->user_public, error, der, + der_encode_public_bytes(account->previous_public, error, der, + der_encode_data_or_null(account->user_key_parameters, error, der, + der_encode_dictionary(account->retired_peers, error, der, der_end)))))))))); + + CFReleaseNull(arrayToEncode); + + return der_end; +} + + + +size_t SOSAccountGetDEREncodedSize_V3(SOSAccountRef account, CFErrorRef *error) +{ + size_t sequence_size = 0; + CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); + uint64_t version = CURRENT_ACCOUNT_PERSISTENT_VERSION; + + require_quiet(accumulate_size(&sequence_size, ccder_sizeof_uint64(version)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->gestalt, error)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_array(arrayToEncode, error)), fail); + require_quiet(accumulate_size(&sequence_size, ccder_sizeof_uint64(account->departure_code)), fail); + require_quiet(accumulate_size(&sequence_size, ccder_sizeof_bool(account->user_public_trusted, error)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account->user_public, error)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_data_or_null(account->user_key_parameters, error)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->retired_peers, error)), fail); + + CFReleaseNull(arrayToEncode); + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, sequence_size); + +fail: + CFReleaseNull(arrayToEncode); + SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error); + return 0; +} + +uint8_t* SOSAccountEncodeToDER_V3(SOSAccountRef account, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) +{ + CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); + uint64_t version = 3; + der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + ccder_encode_uint64(version, der, + der_encode_dictionary(account->gestalt, error, der, + der_encode_array(arrayToEncode, error, der, + ccder_encode_uint64(account->departure_code, der, + ccder_encode_bool(account->user_public_trusted, der, + der_encode_public_bytes(account->user_public, error, der, + der_encode_data_or_null(account->user_key_parameters, error, der, + der_encode_dictionary(account->retired_peers, error, der, der_end))))))))); + + CFReleaseNull(arrayToEncode); + + return der_end; +} + +/* Original V2 encoders */ + +size_t SOSAccountGetDEREncodedSize_V2(SOSAccountRef account, CFErrorRef *error) +{ + size_t sequence_size = 0; + CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); + + require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->gestalt, error)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_array(arrayToEncode, error)), fail); + require_quiet(accumulate_size(&sequence_size, ccder_sizeof_uint64(account->departure_code)), fail); + require_quiet(accumulate_size(&sequence_size, ccder_sizeof_bool(account->user_public_trusted, error)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account->user_public, error)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_data_or_null(account->user_key_parameters, error)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->retired_peers, error)), fail); + + CFReleaseNull(arrayToEncode); + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, sequence_size); + +fail: + CFReleaseNull(arrayToEncode); + SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error); + return 0; +} + +uint8_t* SOSAccountEncodeToDER_V2(SOSAccountRef account, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) +{ + CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); + + der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + der_encode_dictionary(account->gestalt, error, der, + der_encode_array(arrayToEncode, error, der, + ccder_encode_uint64(account->departure_code, der, + ccder_encode_bool(account->user_public_trusted, der, + der_encode_public_bytes(account->user_public, error, der, + der_encode_data_or_null(account->user_key_parameters, error, der, + der_encode_dictionary(account->retired_peers, error, der, der_end)))))))); + + CFReleaseNull(arrayToEncode); + + return der_end; +} + + +/* Original V1 encoders */ + + +size_t SOSAccountGetDEREncodedSize_V1(SOSAccountRef account, CFErrorRef *error) +{ + size_t sequence_size = 0; + CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); + + require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->gestalt, error)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_array(arrayToEncode, error)), fail); + require_quiet(accumulate_size(&sequence_size, ccder_sizeof_bool(account->user_public_trusted, error)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account->user_public, error)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_data_or_null(account->user_key_parameters, error)), fail); + require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->retired_peers, error)), fail); + + CFReleaseNull(arrayToEncode); + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, sequence_size); + +fail: + CFReleaseNull(arrayToEncode); + SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error); + return 0; +} + +uint8_t* SOSAccountEncodeToDER_V1(SOSAccountRef account, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) +{ + CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); + + der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + der_encode_dictionary(account->gestalt, error, der, + der_encode_array(arrayToEncode, error, der, + ccder_encode_bool(account->user_public_trusted, der, + der_encode_public_bytes(account->user_public, error, der, + der_encode_data_or_null(account->user_key_parameters, error, der, + der_encode_dictionary(account->retired_peers, error, der, der_end))))))); + + CFReleaseNull(arrayToEncode); + + return der_end; +} + +/************************/ + +CFDataRef SOSAccountCopyEncodedData(SOSAccountRef account, CFAllocatorRef allocator, CFErrorRef *error) +{ + size_t size = SOSAccountGetDEREncodedSize(account, error); + if (size == 0) + return NULL; + uint8_t buffer[size]; + uint8_t* start = SOSAccountEncodeToDER(account, error, buffer, buffer + sizeof(buffer)); + CFDataRef result = CFDataCreate(kCFAllocatorDefault, start, size); + return result; +} + diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSAccountPriv.h b/Security/sec/SOSCircle/SecureObjectSync/SOSAccountPriv.h new file mode 100644 index 00000000..91d84a14 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSAccountPriv.h @@ -0,0 +1,293 @@ +// +// SOSAccountPriv.h +// sec +// + +#ifndef sec_SOSAccountPriv_h +#define sec_SOSAccountPriv_h + +#include "SOSAccount.h" + +#include +#include +#include +#include +#include + + +#include + +#include +#include +#include + +#include +#include + +#import + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct __OpaqueSOSAccount { + CFRuntimeBase _base; + + dispatch_queue_t queue; + + CFDictionaryRef gestalt; + + CFMutableDictionaryRef circle_identities; + CFMutableDictionaryRef circles; + CFMutableDictionaryRef retired_peers; + + bool user_public_trusted; + CFDataRef user_key_parameters; + SecKeyRef user_public; + SecKeyRef previous_public; + enum DepartureReason departure_code; + + // Non-persistent data + + SOSDataSourceFactoryRef factory; + SecKeyRef _user_private; + dispatch_source_t user_private_timer; + int lock_notification_token; + + SOSTransportKeyParameterRef key_transport; + CFMutableDictionaryRef circle_transports; + CFMutableDictionaryRef message_transports; + + // Live Notification + CFMutableArrayRef change_blocks; +}; + +SOSAccountRef SOSAccountCreateBasic(CFAllocatorRef allocator, + CFDictionaryRef gestalt, + SOSDataSourceFactoryRef factory); + +bool SOSAccountEnsureFactoryCircles(SOSAccountRef a); + +void SOSAccountSetToNew(SOSAccountRef a); + +void SOSAccountForEachKnownCircle(SOSAccountRef account, + void (^handle_incompatible)(CFStringRef name), + void (^handle_no_peer)(SOSCircleRef circle), + void (^handle_peer)(SOSCircleRef circle, SOSFullPeerInfoRef full_peer)); + +bool SOSAccountIsMyPeerActiveInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error); +bool SOSAccountIsMyPeerActiveInCircleNamed(SOSAccountRef account, CFStringRef circle_name, CFErrorRef* error); + +// DER Stuff + + +size_t der_sizeof_data_or_null(CFDataRef data, CFErrorRef* error); + +uint8_t* der_encode_data_or_null(CFDataRef data, CFErrorRef* error, const uint8_t* der, uint8_t* der_end); + +const uint8_t* der_decode_data_or_null(CFAllocatorRef allocator, CFDataRef* data, + CFErrorRef* error, + const uint8_t* der, const uint8_t* der_end); + +size_t der_sizeof_public_bytes(SecKeyRef publicKey, CFErrorRef* error); + +uint8_t* der_encode_public_bytes(SecKeyRef publicKey, CFErrorRef* error, const uint8_t* der, uint8_t* der_end); + +const uint8_t* der_decode_public_bytes(CFAllocatorRef allocator, CFIndex algorithmID, SecKeyRef* publicKey, CFErrorRef* error, const uint8_t* der, const uint8_t* der_end); + +const uint8_t* ccder_decode_bool(bool* boolean, const uint8_t* der, const uint8_t *der_end); + +size_t ccder_sizeof_bool(bool value __unused, CFErrorRef *error); + +uint8_t* ccder_encode_bool(bool value, const uint8_t *der, uint8_t *der_end); + +// Persistence + + +SOSAccountRef SOSAccountCreateFromDER_V1(CFAllocatorRef allocator, + SOSDataSourceFactoryRef factory, + CFErrorRef* error, + const uint8_t** der_p, const uint8_t *der_end); + +SOSAccountRef SOSAccountCreateFromDER_V2(CFAllocatorRef allocator, + SOSDataSourceFactoryRef factory, + CFErrorRef* error, + const uint8_t** der_p, const uint8_t *der_end); + +SOSAccountRef SOSAccountCreateFromDER_V3(CFAllocatorRef allocator, + SOSDataSourceFactoryRef factory, + CFErrorRef* error, + const uint8_t** der_p, const uint8_t *der_end); + +SOSAccountRef SOSAccountCreateFromDER(CFAllocatorRef allocator, + SOSDataSourceFactoryRef factory, + CFErrorRef* error, + const uint8_t** der_p, const uint8_t *der_end); + +SOSAccountRef SOSAccountCreateFromData(CFAllocatorRef allocator, CFDataRef circleData, + SOSDataSourceFactoryRef factory, + CFErrorRef* error); + +size_t SOSAccountGetDEREncodedSize(SOSAccountRef account, CFErrorRef *error); + +uint8_t* SOSAccountEncodeToDER(SOSAccountRef account, CFErrorRef* error, const uint8_t* der, uint8_t* der_end); + +size_t SOSAccountGetDEREncodedSize_V3(SOSAccountRef account, CFErrorRef *error); + +uint8_t* SOSAccountEncodeToDER_V3(SOSAccountRef account, CFErrorRef* error, const uint8_t* der, uint8_t* der_end); + +size_t SOSAccountGetDEREncodedSize_V2(SOSAccountRef account, CFErrorRef *error); + +uint8_t* SOSAccountEncodeToDER_V2(SOSAccountRef account, CFErrorRef* error, const uint8_t* der, uint8_t* der_end); + +size_t SOSAccountGetDEREncodedSize_V1(SOSAccountRef account, CFErrorRef *error); + +uint8_t* SOSAccountEncodeToDER_V1(SOSAccountRef account, CFErrorRef* error, const uint8_t* der, uint8_t* der_end); + +CFDataRef SOSAccountCopyEncodedData(SOSAccountRef account, CFAllocatorRef allocator, CFErrorRef *error); + +// Update + +bool SOSAccountHandleCircleMessage(SOSAccountRef account, + CFStringRef circleName, CFDataRef encodedCircleMessage, CFErrorRef *error); + +void SOSAccountRecordRetiredPeerInCircleNamed(SOSAccountRef account, CFStringRef circleName, SOSPeerInfoRef retiree); + + +bool SOSAccountHandleUpdateCircle(SOSAccountRef account, + SOSCircleRef prospective_circle, + bool writeUpdate, + CFErrorRef *error); + +// Circles + +void SOSAccountForEachKnownCircle(SOSAccountRef account, + void (^handle_incompatible)(CFStringRef name), + void (^handle_no_peer)(SOSCircleRef circle), + void (^handle_peer)(SOSCircleRef circle, SOSFullPeerInfoRef full_peer)); + +int SOSAccountCountCircles(SOSAccountRef a); + +SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircleNamed(SOSAccountRef account, CFStringRef name, CFErrorRef *error); + +bool SOSAccountDestroyCirclePeerInfoNamed(SOSAccountRef account, CFStringRef name, CFErrorRef* error); + +bool SOSAccountDestroyCirclePeerInfo(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error); + +SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error); + +SOSPeerInfoRef SOSAccountGetMyPeerInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error); + +SOSPeerInfoRef SOSAccountGetMyPeerInCircleNamed(SOSAccountRef account, CFStringRef name, CFErrorRef *error); + +bool SOSAccountIsActivePeerInCircleNamed(SOSAccountRef account, CFStringRef circle_name, CFStringRef peerid, CFErrorRef* error); + +bool SOSAccountIsMyPeerActiveInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error); + +SOSCircleRef SOSAccountFindCircle(SOSAccountRef a, CFStringRef name, CFErrorRef *error); + +SOSCircleRef SOSAccountEnsureCircle(SOSAccountRef a, CFStringRef name, CFErrorRef *error); + +bool SOSAccountUpdateCircleFromRemote(SOSAccountRef account, SOSCircleRef newCircle, CFErrorRef *error); + +bool SOSAccountUpdateCircle(SOSAccountRef account, SOSCircleRef newCircle, CFErrorRef *error); + +bool SOSAccountModifyCircle(SOSAccountRef account, + CFStringRef circleName, + CFErrorRef* error, + bool (^action)(SOSCircleRef circle)); + +SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircleNamedIfPresent(SOSAccountRef account, CFStringRef name, CFErrorRef *error); + +void AppendCircleKeyName(CFMutableArrayRef array, CFStringRef name); + +CFStringRef SOSInterestListCopyDescription(CFArrayRef interests); + + +// Peers and PeerInfos +bool SOSAccountDestroyCirclePeerInfoNamed(SOSAccountRef account, CFStringRef name, CFErrorRef* error); + +bool SOSAccountDestroyCirclePeerInfo(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error); + +SOSPeerInfoRef SOSAccountGetMyPeerInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error); + +SOSPeerInfoRef SOSAccountGetMyPeerInCircleNamed(SOSAccountRef account, CFStringRef name, CFErrorRef *error); + +bool SOSAccountIsActivePeerInCircleNamed(SOSAccountRef account, CFStringRef circle_name, CFStringRef peerid, CFErrorRef* error); + +bool SOSAccountIsMyPeerActiveInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error); + +// FullPeerInfos - including Cloud Identity +SOSFullPeerInfoRef CopyCloudKeychainIdentity(SOSPeerInfoRef cloudPeer, CFErrorRef *error); + +SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircleNamedIfPresent(SOSAccountRef account, CFStringRef name, CFErrorRef *error); + +bool SOSAccountIsAccountIdentity(SOSAccountRef account, SOSPeerInfoRef peer_info, CFErrorRef *error); + +SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircleNamed(SOSAccountRef account, CFStringRef name, CFErrorRef *error); + +SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error); + +SOSPeerInfoRef GenerateNewCloudIdentityPeerInfo(CFErrorRef *error); + +// Credentials +bool SOSAccountHasPublicKey(SOSAccountRef account, CFErrorRef* error); +void SOSAccountSetPreviousPublic(SOSAccountRef account); +bool SOSAccountPublishCloudParameters(SOSAccountRef account, CFErrorRef* error); +bool SOSAccountRetrieveCloudParameters(SOSAccountRef account, SecKeyRef *newKey, + CFDataRef derparms, + CFDataRef *newParameters, CFErrorRef* error); + +//Testing +void SOSAccountSetUserPublicTrustedForTesting(SOSAccountRef account); +CFDictionaryRef SOSAccountGetMessageTransports(SOSAccountRef account); +// Utility + + +static inline void CFArrayAppendValueIfNot(CFMutableArrayRef array, CFTypeRef value, CFTypeRef excludedValue) +{ + if (!CFEqualSafe(value, excludedValue)) + CFArrayAppendValue(array, value); +} + +static inline CFMutableDictionaryRef CFDictionaryEnsureCFDictionaryAndGetCurrentValue(CFMutableDictionaryRef dict, CFTypeRef key) +{ + CFMutableDictionaryRef result = (CFMutableDictionaryRef) CFDictionaryGetValue(dict, key); + + if (!isDictionary(result)) { + result = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionarySetValue(dict, key, result); + CFReleaseSafe(result); + } + + return result; +} + +static inline CFMutableArrayRef CFDictionaryEnsureCFArrayAndGetCurrentValue(CFMutableDictionaryRef dict, CFTypeRef key) +{ + CFMutableArrayRef result = (CFMutableArrayRef) CFDictionaryGetValue(dict, key); + + if (!isArray(result)) { + result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionarySetValue(dict, key, result); + CFReleaseSafe(result); + } + + return result; +} + +bool sosAccountLeaveCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error); + +bool SOSAccountEnsurePeerRegistration(SOSAccountRef account, CFErrorRef *error); + +#endif diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSAccountUpdate.c b/Security/sec/SOSCircle/SecureObjectSync/SOSAccountUpdate.c new file mode 100644 index 00000000..ad7cae8e --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSAccountUpdate.c @@ -0,0 +1,479 @@ +// +// SOSAccountUpdate.c +// sec +// + +#include "SOSAccountPriv.h" +#include +#include +#include +#include + +static void DifferenceAndCall(CFSetRef old_members, CFSetRef new_members, void (^updatedCircle)(CFSetRef additions, CFSetRef removals)) +{ + CFMutableSetRef additions = CFSetCreateMutableCopy(kCFAllocatorDefault, 0, new_members); + CFMutableSetRef removals = CFSetCreateMutableCopy(kCFAllocatorDefault, 0, old_members); + + + CFSetForEach(old_members, ^(const void * value) { + CFSetRemoveValue(additions, value); + }); + + CFSetForEach(new_members, ^(const void * value) { + CFSetRemoveValue(removals, value); + }); + + updatedCircle(additions, removals); + + CFReleaseSafe(additions); + CFReleaseSafe(removals); +} + +static void SOSAccountNotifyEngines(SOSAccountRef account, SOSCircleRef new_circle, + CFSetRef added_peers, CFSetRef removed_peers, + CFSetRef added_applicants, CFSetRef removed_applicants) +{ + SOSPeerInfoRef myPi = SOSAccountGetMyPeerInCircle(account, new_circle, NULL); + CFStringRef myPi_id = NULL; + CFMutableArrayRef trusted_peer_ids = NULL; + CFMutableArrayRef untrusted_peer_ids = NULL; + + if (myPi && SOSCircleHasPeer(new_circle, myPi, NULL)) { + myPi_id = SOSPeerInfoGetPeerID(myPi); + trusted_peer_ids = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + untrusted_peer_ids = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + SOSCircleForEachPeer(new_circle, ^(SOSPeerInfoRef peer) { + CFMutableArrayRef arrayToAddTo = SOSPeerInfoApplicationVerify(peer, account->user_public, NULL) ? trusted_peer_ids : untrusted_peer_ids; + CFArrayAppendValue(arrayToAddTo, SOSPeerInfoGetPeerID(peer)); + }); + } + + CFArrayRef dsNames = account->factory->copy_names(account->factory); + CFStringRef dsName = NULL; + CFArrayForEachC(dsNames, dsName) { + SOSEngineRef engine = SOSDataSourceFactoryGetEngineForDataSourceName(account->factory, dsName, NULL); + if (engine) + SOSEngineCircleChanged(engine, myPi_id, trusted_peer_ids, untrusted_peer_ids); + } + CFReleaseSafe(dsNames); + CFReleaseNull(trusted_peer_ids); + CFReleaseNull(untrusted_peer_ids); +} + +static void SOSAccountNotifyOfChange(SOSAccountRef account, SOSCircleRef oldCircle, SOSCircleRef newCircle) +{ + CFMutableSetRef old_members = SOSCircleCopyPeers(oldCircle, kCFAllocatorDefault); + CFMutableSetRef new_members = SOSCircleCopyPeers(newCircle, kCFAllocatorDefault); + + CFMutableSetRef old_applicants = SOSCircleCopyApplicants(oldCircle, kCFAllocatorDefault); + CFMutableSetRef new_applicants = SOSCircleCopyApplicants(newCircle, kCFAllocatorDefault); + + DifferenceAndCall(old_members, new_members, ^(CFSetRef added_members, CFSetRef removed_members) { + DifferenceAndCall(old_applicants, new_applicants, ^(CFSetRef added_applicants, CFSetRef removed_applicants) { + SOSAccountNotifyEngines(account, newCircle, added_members, removed_members, added_applicants, removed_applicants); + CFArrayForEach(account->change_blocks, ^(const void * notificationBlock) { + ((SOSAccountCircleMembershipChangeBlock) notificationBlock)(newCircle, added_members, removed_members, added_applicants, removed_applicants); + }); + }); + }); + + CFReleaseNull(old_applicants); + CFReleaseNull(new_applicants); + + CFReleaseNull(old_members); + CFReleaseNull(new_members); +} + +void SOSAccountRecordRetiredPeerInCircleNamed(SOSAccountRef account, CFStringRef circleName, SOSPeerInfoRef retiree) +{ + // Replace Peer with RetiredPeer, if were a peer. + SOSAccountModifyCircle(account, circleName, NULL, ^(SOSCircleRef circle) { + SOSPeerInfoRef me = SOSAccountGetMyPeerInCircleNamed(account, circleName, NULL); + if(!me || !SOSCircleHasActivePeer(circle, me, NULL)) return (bool) false; + + bool updated = SOSCircleUpdatePeerInfo(circle, retiree); + if (updated) { + CFErrorRef cleanupError = NULL; + if (!SOSAccountCleanupAfterPeer(account, RETIREMENT_FINALIZATION_SECONDS, circle, retiree, &cleanupError)) + secerror("Error cleanup up after peer (%@): %@", retiree, cleanupError); + CFReleaseSafe(cleanupError); + } + return updated; + }); +} + +static SOSCircleRef SOSAccountCreateCircleFrom(CFStringRef circleName, CFTypeRef value, CFErrorRef *error) { + if (value && !isData(value) && !isNull(value)) { + secnotice("circleCreat", "Value provided not appropriate for a circle"); + CFStringRef description = CFCopyTypeIDDescription(CFGetTypeID(value)); + SOSCreateErrorWithFormat(kSOSErrorUnexpectedType, NULL, error, NULL, + CFSTR("Expected data or NULL got %@"), description); + CFReleaseSafe(description); + return NULL; + } + + SOSCircleRef circle = NULL; + if (!value || isNull(value)) { + secnotice("circleCreat", "No circle found in data: %@", value); + circle = NULL; + } else { + circle = SOSCircleCreateFromData(NULL, (CFDataRef) value, error); + if (circle) { + CFStringRef name = SOSCircleGetName(circle); + if (!CFEqualSafe(name, circleName)) { + secnotice("circleCreat", "Expected circle named %@, got %@", circleName, name); + SOSCreateErrorWithFormat(kSOSErrorNameMismatch, NULL, error, NULL, + CFSTR("Expected circle named %@, got %@"), circleName, name); + CFReleaseNull(circle); + } + } else { + secnotice("circleCreat", "SOSCircleCreateFromData returned NULL."); + } + } + return circle; +} + +bool SOSAccountHandleCircleMessage(SOSAccountRef account, + CFStringRef circleName, CFDataRef encodedCircleMessage, CFErrorRef *error) { + bool success = false; + CFErrorRef localError = NULL; + SOSCircleRef circle = SOSAccountCreateCircleFrom(circleName, encodedCircleMessage, &localError); + if (circle) { + success = SOSAccountUpdateCircleFromRemote(account, circle, &localError); + CFReleaseSafe(circle); + } else { + secerror("NULL circle found, ignoring ..."); + success = true; // don't pend this NULL thing. + } + + if (!success) { + if (isSOSErrorCoded(localError, kSOSErrorIncompatibleCircle)) { + secerror("Incompatible circle found, abandoning membership: %@", circleName); + SOSAccountDestroyCirclePeerInfoNamed(account, circleName, NULL); + CFDictionarySetValue(account->circles, circleName, kCFNull); + } + + if (error) { + *error = localError; + localError = NULL; + } + + } + + CFReleaseNull(localError); + + return success; +} + +bool SOSAccountHandleParametersChange(SOSAccountRef account, CFDataRef parameters, CFErrorRef *error){ + + SecKeyRef newKey = NULL; + CFDataRef newParameters = NULL; + bool success = false; + + if(SOSAccountRetrieveCloudParameters(account, &newKey, parameters, &newParameters, error)) { + if (CFEqualSafe(account->user_public, newKey)) { + secnotice("updates", "Got same public key sent our way. Ignoring."); + success = true; + } else if (CFEqualSafe(account->previous_public, newKey)) { + secnotice("updates", "Got previous public key repeated. Ignoring."); + success = true; + } else { + CFReleaseNull(account->user_public); + SOSAccountPurgePrivateCredential(account); + CFReleaseNull(account->user_key_parameters); + + account->user_public_trusted = false; + + account->user_public = newKey; + newKey = NULL; + + account->user_key_parameters = newParameters; + newParameters = NULL; + + secnotice("updates", "Got new parameters for public key: %@", account->user_public); + debugDumpUserParameters(CFSTR("params"), account->user_key_parameters); + + SOSUpdateKeyInterest(); + + success = true; + } + } + + CFReleaseNull(newKey); + CFReleaseNull(newParameters); + + return success; +} + +static inline bool SOSAccountHasLeft(SOSAccountRef account) { + switch(account->departure_code) { + case kSOSWithdrewMembership: /* Fallthrough */ + case kSOSMembershipRevoked: /* Fallthrough */ + case kSOSLeftUntrustedCircle: + return true; + case kSOSNeverAppliedToCircle: /* Fallthrough */ + case kSOSNeverLeftCircle: /* Fallthrough */ + default: + return false; + } +} + +static const char *concordstring[] = { + "kSOSConcordanceTrusted", + "kSOSConcordanceGenOld", // kSOSErrorReplay + "kSOSConcordanceNoUserSig", // kSOSErrorBadSignature + "kSOSConcordanceNoUserKey", // kSOSErrorNoKey + "kSOSConcordanceNoPeer", // kSOSErrorPeerNotFound + "kSOSConcordanceBadUserSig", // kSOSErrorBadSignature + "kSOSConcordanceBadPeerSig", // kSOSErrorBadSignature + "kSOSConcordanceNoPeerSig", + "kSOSConcordanceWeSigned", +}; + +bool SOSAccountHandleUpdateCircle(SOSAccountRef account, SOSCircleRef prospective_circle, bool writeUpdate, CFErrorRef *error) +{ + bool success = true; + bool haveOldCircle = true; + const char *local_remote = writeUpdate ? "local": "remote"; + + secnotice("signing", "start:[%s] %@", local_remote, prospective_circle); + if (!account->user_public || !account->user_public_trusted) { + SOSCreateError(kSOSErrorPublicKeyAbsent, CFSTR("Can't handle updates with no trusted public key here"), NULL, error); + return false; + } + + if (!prospective_circle) { + secerror("##### Can't update to a NULL circle ######"); + return false; // Can't update one we don't have. + } + + CFStringRef newCircleName = SOSCircleGetName(prospective_circle); + SOSCircleRef oldCircle = (SOSCircleRef) CFDictionaryGetValue(account->circles, newCircleName); + SOSCircleRef emptyCircle = NULL; + + if(oldCircle == NULL) { + SOSCreateErrorWithFormat(kSOSErrorIncompatibleCircle, NULL, error, NULL, CFSTR("Current Entry is NULL; rejecting %@"), prospective_circle); + secerror("##### Can't replace circle - we don't care about %@ ######", prospective_circle); + return false; + } + if (CFGetTypeID(oldCircle) != SOSCircleGetTypeID()) { + secdebug("badcircle", ">>>>>>>>>>>>>>> Non-Circle Circle found <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); + // We don't know what is in our table, likely it was kCFNull indicating we didn't + // understand a circle that came by. We seem to like this one lets make our entry be empty circle + emptyCircle = SOSCircleCreate(kCFAllocatorDefault, newCircleName, NULL); + oldCircle = emptyCircle; + haveOldCircle = false; + // And we're paranoid, drop our old peer info if for some reason we didn't before. + // SOSAccountDestroyCirclePeerInfo(account, oldCircle, NULL); + } + + SOSFullPeerInfoRef me_full = SOSAccountGetMyFullPeerInCircle(account, oldCircle, NULL); + SOSPeerInfoRef me = SOSFullPeerInfoGetPeerInfo(me_full); + + SOSTransportCircleRef transport = (SOSTransportCircleRef)CFDictionaryGetValue(account->circle_transports, SOSCircleGetName(prospective_circle)); + + SOSAccountScanForRetired(account, prospective_circle, error); + SOSCircleRef newCircle = SOSAccountCloneCircleWithRetirement(account, prospective_circle, error); + if(!newCircle) return false; + + if (me && SOSCircleUpdatePeerInfo(newCircle, me)) { + writeUpdate = true; // If we update our peer in the new circle we should write it if we accept it. + } + + typedef enum { + accept, + countersign, + leave, + revert, + ignore + } circle_action_t; + + static const char *actionstring[] = { + "accept", "countersign", "leave", "revert", "ignore", + }; + + circle_action_t circle_action = ignore; + enum DepartureReason leave_reason = kSOSNeverLeftCircle; + + SecKeyRef old_circle_key = NULL; + if(SOSCircleVerify(oldCircle, account->user_public, NULL)) old_circle_key = account->user_public; + else if(account->previous_public && SOSCircleVerify(oldCircle, account->previous_public, NULL)) old_circle_key = account->previous_public; + bool userTrustedOldCircle = (old_circle_key != NULL) && haveOldCircle; + + SOSConcordanceStatus concstat = + SOSCircleConcordanceTrust(oldCircle, newCircle, + old_circle_key, account->user_public, + me, error); + + CFStringRef concStr = NULL; + switch(concstat) { + case kSOSConcordanceTrusted: + circle_action = countersign; + concStr = CFSTR("Trusted"); + break; + case kSOSConcordanceGenOld: + circle_action = userTrustedOldCircle ? revert : ignore; + concStr = CFSTR("Generation Old"); + break; + case kSOSConcordanceBadUserSig: + case kSOSConcordanceBadPeerSig: + circle_action = userTrustedOldCircle ? revert : accept; + concStr = CFSTR("Bad Signature"); + break; + case kSOSConcordanceNoUserSig: + circle_action = userTrustedOldCircle ? revert : accept; + concStr = CFSTR("No User Signature"); + break; + case kSOSConcordanceNoPeerSig: + circle_action = accept; // We might like this one eventually but don't countersign. + concStr = CFSTR("No trusted peer signature"); + secerror("##### No trusted peer signature found, accepting hoping for concordance later %@", newCircle); + break; + case kSOSConcordanceNoPeer: + circle_action = leave; + leave_reason = kSOSLeftUntrustedCircle; + concStr = CFSTR("No trusted peer left"); + break; + case kSOSConcordanceNoUserKey: + secerror("##### No User Public Key Available, this shouldn't ever happen!!!"); + abort(); + break; + default: + secerror("##### Bad Error Return from ConcordanceTrust"); + abort(); + break; + } + + secnotice("signing", "Decided on action [%s] based on concordance state [%s] and [%s] circle.", actionstring[circle_action], concordstring[concstat], userTrustedOldCircle ? "trusted" : "untrusted"); + + SOSCircleRef circleToPush = NULL; + + if (circle_action == leave) { + circle_action = ignore; + + if (me && SOSCircleHasPeer(oldCircle, me, NULL)) { + if (sosAccountLeaveCircle(account, newCircle, error)) { + account->departure_code = leave_reason; + circleToPush = newCircle; + circle_action = accept; + me = NULL; + me_full = NULL; + } + } + else { + // We are not in this circle, but we need to update account with it, since we got it from cloud + secnotice("updatecircle", "We are not in this circle, but we need to update account with it"); + circle_action = accept; + } + } + + if (circle_action == countersign) { + if (me && SOSCircleHasPeer(newCircle, me, NULL) && !SOSCircleVerifyPeerSigned(newCircle, me, NULL)) { + CFErrorRef signing_error = NULL; + + if (me_full && SOSCircleConcordanceSign(newCircle, me_full, &signing_error)) { + circleToPush = newCircle; + secnotice("signing", "Concurred with: %@", newCircle); + } else { + secerror("Failed to concurrence sign, error: %@ Old: %@ New: %@", signing_error, oldCircle, newCircle); + success = false; + } + CFReleaseSafe(signing_error); + } + circle_action = accept; + } + + if (circle_action == accept) { + if (me && SOSCircleHasActivePeer(oldCircle, me, NULL) && !SOSCircleHasPeer(newCircle, me, NULL)) { + // Don't destroy evidence of other code determining reason for leaving. + if(!SOSAccountHasLeft(account)) account->departure_code = kSOSMembershipRevoked; + } + + if (me + && SOSCircleHasActivePeer(oldCircle, me, NULL) + && !(SOSCircleCountPeers(oldCircle) == 1 && SOSCircleHasPeer(oldCircle, me, NULL)) // If it was our offering, don't change ID to avoid ghosts + && !SOSCircleHasPeer(newCircle, me, NULL) && !SOSCircleHasApplicant(newCircle, me, NULL)) { + secnotice("circle", "Purging my peer (ID: %@) for circle '%@'!!!", SOSPeerInfoGetPeerID(me), SOSCircleGetName(oldCircle)); + SOSAccountDestroyCirclePeerInfo(account, oldCircle, NULL); + me = NULL; + me_full = NULL; + } + + if (me && SOSCircleHasRejectedApplicant(newCircle, me, NULL)) { + SOSPeerInfoRef reject = SOSCircleCopyRejectedApplicant(newCircle, me, NULL); + if(CFEqualSafe(reject, me) && SOSPeerInfoApplicationVerify(me, account->user_public, NULL)) { + secnotice("circle", "Rejected, Purging my applicant peer (ID: %@) for circle '%@'", SOSPeerInfoGetPeerID(me), SOSCircleGetName(oldCircle)); + SOSAccountDestroyCirclePeerInfo(account, oldCircle, NULL); + me = NULL; + me_full = NULL; + } else { + SOSCircleRequestReadmission(newCircle, account->user_public, me_full, NULL); + writeUpdate = true; + } + } + + CFRetain(oldCircle); // About to replace the oldCircle + CFDictionarySetValue(account->circles, newCircleName, newCircle); + SOSAccountSetPreviousPublic(account); + + secnotice("signing", "%@, Accepting circle: %@", concStr, newCircle); + + if (me_full && account->user_public_trusted + && SOSCircleHasApplicant(oldCircle, me, NULL) + && SOSCircleCountPeers(newCircle) > 0 + && !SOSCircleHasPeer(newCircle, me, NULL) && !SOSCircleHasApplicant(newCircle, me, NULL)) { + // We weren't rejected (above would have set me to NULL. + // We were applying and we weren't accepted. + // Our application is declared lost, let us reapply. + + if (SOSCircleRequestReadmission(newCircle, account->user_public, me_full, NULL)) + writeUpdate = true; + } + + if (me && SOSCircleHasActivePeer(oldCircle, me, NULL)) { + SOSAccountCleanupRetirementTickets(account, RETIREMENT_FINALIZATION_SECONDS, NULL); + } + + SOSAccountNotifyOfChange(account, oldCircle, newCircle); + + CFReleaseNull(oldCircle); + + if (writeUpdate) + circleToPush = newCircle; + SOSUpdateKeyInterest(); + } + + /* + * In the revert section we'll guard the KVS idea of circles by rejecting "bad" new circles + * and pushing our current view of the circle (oldCircle). We'll only do this if we actually + * are a member of oldCircle - never for an empty circle. + */ + + if (circle_action == revert) { + if(haveOldCircle && me && SOSCircleHasActivePeer(oldCircle, me, NULL)) { + secnotice("signing", "%@, Rejecting: %@ re-publishing %@", concStr, newCircle, oldCircle); + circleToPush = oldCircle; + } else { + secnotice("canary", "%@, Rejecting: %@ Have no old circle - would reset", concStr, newCircle); + } + } + + + if (circleToPush != NULL) { + secnotice("circleUpdate", "Pushing:[%s] %@", local_remote, circleToPush); + CFDataRef circle_data = SOSCircleCopyEncodedData(circleToPush, kCFAllocatorDefault, error); + if (circle_data) { + success &= SOSTransportCirclePostCircle(transport, SOSCircleGetName(circleToPush), circle_data, error); + } else { + success = false; + } + CFReleaseNull(circle_data); + + success = (success && SOSTransportCircleFlushChanges(transport, error)); + } + + CFReleaseSafe(newCircle); + CFReleaseNull(emptyCircle); + return success; +} diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSCircle.c b/Security/sec/SOSCircle/SecureObjectSync/SOSCircle.c new file mode 100644 index 00000000..ff085161 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSCircle.c @@ -0,0 +1,1261 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* + * SOSCircle.c - Implementation of the secure object syncing transport + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +//#include "ckdUtilities.h" + +#include +#include + +#include +#include +#include + +#include +#include + +enum { + kOnlyCompatibleVersion = 1, // Sometime in the future this name will be improved to reflect history. + + kAlwaysIncompatibleVersion = UINT64_MAX, +}; + +struct __OpaqueSOSCircle { + CFRuntimeBase _base; + + CFStringRef name; + CFNumberRef generation; + CFMutableSetRef peers; + CFMutableSetRef applicants; + CFMutableSetRef rejected_applicants; + + CFMutableDictionaryRef signatures; +}; + +CFGiblisWithCompareFor(SOSCircle); + +SOSCircleRef SOSCircleCreate(CFAllocatorRef allocator, CFStringRef name, CFErrorRef *error) { + SOSCircleRef c = CFTypeAllocate(SOSCircle, struct __OpaqueSOSCircle, allocator); + int64_t gen = 1; + + assert(name); + + c->name = CFStringCreateCopy(allocator, name); + c->generation = CFNumberCreate(allocator, kCFNumberSInt64Type, &gen); + c->peers = CFSetCreateMutableForSOSPeerInfosByID(allocator); + c->applicants = CFSetCreateMutableForSOSPeerInfosByID(allocator); + c->rejected_applicants = CFSetCreateMutableForSOSPeerInfosByID(allocator); + c->signatures = CFDictionaryCreateMutableForCFTypes(allocator); + + return c; +} + +static CFNumberRef SOSCircleGenerationCopy(CFNumberRef generation) { + int64_t value; + CFAllocatorRef allocator = CFGetAllocator(generation); + CFNumberGetValue(generation, kCFNumberSInt64Type, &value); + return CFNumberCreate(allocator, kCFNumberSInt64Type, &value); +} + +static CFMutableSetRef CFSetOfPeerInfoDeepCopy(CFAllocatorRef allocator, CFSetRef peerInfoSet) +{ + __block CFMutableSetRef result = CFSetCreateMutableForSOSPeerInfosByID(allocator); + CFSetForEach(peerInfoSet, ^(const void *value) { + SOSPeerInfoRef pi = (SOSPeerInfoRef) value; + CFErrorRef localError = NULL; + SOSPeerInfoRef copiedPeer = SOSPeerInfoCreateCopy(allocator, pi, &localError); + if (copiedPeer) { + CFSetAddValue(result, copiedPeer); + } else { + secerror("Failed to copy peer: %@ (%@)", pi, localError); + } + CFReleaseSafe(copiedPeer); + CFReleaseSafe(localError); + }); + return result; +} + +SOSCircleRef SOSCircleCopyCircle(CFAllocatorRef allocator, SOSCircleRef otherCircle, CFErrorRef *error) +{ + SOSCircleRef c = CFTypeAllocate(SOSCircle, struct __OpaqueSOSCircle, allocator); + + assert(otherCircle); + c->name = CFStringCreateCopy(allocator, otherCircle->name); + c->generation = SOSCircleGenerationCopy(otherCircle->generation); + + c->peers = CFSetOfPeerInfoDeepCopy(allocator, otherCircle->peers); + c->applicants = CFSetOfPeerInfoDeepCopy(allocator, otherCircle->applicants); + c->rejected_applicants = CFSetOfPeerInfoDeepCopy(allocator, otherCircle->rejected_applicants); + + c->signatures = CFDictionaryCreateMutableCopy(allocator, 0, otherCircle->signatures); + + return c; +} + +static inline +void SOSCircleAssertStable(SOSCircleRef circle) +{ + assert(circle); + assert(circle->name); + assert(circle->generation); + assert(circle->peers); + assert(circle->applicants); + assert(circle->rejected_applicants); + assert(circle->signatures); +} + +static inline +SOSCircleRef SOSCircleConvertAndAssertStable(CFTypeRef circleAsType) +{ + if (CFGetTypeID(circleAsType) != SOSCircleGetTypeID()) + return NULL; + + SOSCircleRef circle = (SOSCircleRef) circleAsType; + + SOSCircleAssertStable(circle); + + return circle; +} + +static Boolean SOSCircleCompare(CFTypeRef lhs, CFTypeRef rhs) { + if (CFGetTypeID(lhs) != SOSCircleGetTypeID() + || CFGetTypeID(rhs) != SOSCircleGetTypeID()) + return false; + + SOSCircleRef left = SOSCircleConvertAndAssertStable(lhs); + SOSCircleRef right = SOSCircleConvertAndAssertStable(rhs); + + // TODO: we should be doing set equality for peers and applicants. + return NULL != left && NULL != right + && CFEqualSafe(left->generation, right->generation) + && SOSPeerInfoSetContainsIdenticalPeers(left->peers, right->peers) + && SOSPeerInfoSetContainsIdenticalPeers(left->applicants, right->applicants) + && SOSPeerInfoSetContainsIdenticalPeers(left->rejected_applicants, right->rejected_applicants) + && CFEqualSafe(left->signatures, right->signatures); +} + +static CFMutableArrayRef CFSetCopyValuesCFArray(CFSetRef set) +{ + CFIndex count = CFSetGetCount(set); + + CFMutableArrayRef result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + if (count > 0) { + const void * values[count]; + CFSetGetValues(set, values); + for (int current = 0; current < count; ++current) { + CFArrayAppendValue(result, values[current]); + } + } + + return result; +} + +static bool SOSCircleDigestArray(const struct ccdigest_info *di, CFMutableArrayRef array, void *hash_result, CFErrorRef *error) +{ + __block bool success = true; + ccdigest_di_decl(di, array_digest); + const void * a_digest = array_digest; + + ccdigest_init(di, array_digest); + CFArraySortValues(array, CFRangeMake(0, CFArrayGetCount(array)), SOSPeerInfoCompareByID, SOSPeerCmpPubKeyHash); + CFArrayForEach(array, ^(const void *peer) { + if (!SOSPeerInfoUpdateDigestWithPublicKeyBytes((SOSPeerInfoRef)peer, di, a_digest, error)) + success = false; + }); + ccdigest_final(di, array_digest, hash_result); + + return success; +} + +static bool SOSCircleDigestSet(const struct ccdigest_info *di, CFMutableSetRef set, void *hash_result, CFErrorRef *error) +{ + CFMutableArrayRef values = CFSetCopyValuesCFArray(set); + + bool result = SOSCircleDigestArray(di, values, hash_result, error); + + CFReleaseSafe(values); + + return result; +} + + +static bool SOSCircleHash(const struct ccdigest_info *di, SOSCircleRef circle, void *hash_result, CFErrorRef *error) { + ccdigest_di_decl(di, circle_digest); + ccdigest_init(di, circle_digest); + int64_t gen = SOSCircleGetGenerationSint(circle); + ccdigest_update(di, circle_digest, sizeof(gen), &gen); + + SOSCircleDigestSet(di, circle->peers, hash_result, error); + ccdigest_update(di, circle_digest, di->output_size, hash_result); + ccdigest_final(di, circle_digest, hash_result); + return true; +} + +static bool SOSCircleSetSignature(SOSCircleRef circle, SecKeyRef pubkey, CFDataRef signature, CFErrorRef *error) { + bool result = false; + + CFStringRef pubKeyID = SOSCopyIDOfKey(pubkey, error); + require_quiet(pubKeyID, fail); + CFDictionarySetValue(circle->signatures, pubKeyID, signature); + result = true; + +fail: + CFReleaseSafe(pubKeyID); + return result; +} + +static bool SOSCircleRemoveSignatures(SOSCircleRef circle, CFErrorRef *error) { + CFDictionaryRemoveAllValues(circle->signatures); + return true; +} + +static CFDataRef SOSCircleGetSignature(SOSCircleRef circle, SecKeyRef pubkey, CFErrorRef *error) { + CFStringRef pubKeyID = SOSCopyIDOfKey(pubkey, error); + CFDataRef result = NULL; + require_quiet(pubKeyID, fail); + + CFTypeRef value = (CFDataRef)CFDictionaryGetValue(circle->signatures, pubKeyID); + + if (isData(value)) result = (CFDataRef) value; + +fail: + CFReleaseSafe(pubKeyID); + return result; +} + +bool SOSCircleSign(SOSCircleRef circle, SecKeyRef privKey, CFErrorRef *error) { + if (!privKey) return false; // Really assertion but not always true for now. + CFAllocatorRef allocator = CFGetAllocator(circle); + uint8_t tmp[4096]; + size_t tmplen = 4096; + const struct ccdigest_info *di = ccsha256_di(); + uint8_t hash_result[di->output_size]; + + SOSCircleHash(di, circle, hash_result, error); + OSStatus stat = SecKeyRawSign(privKey, kSecPaddingNone, hash_result, di->output_size, tmp, &tmplen); + if(stat) { + // TODO - Create a CFErrorRef; + secerror("Bad Circle SecKeyRawSign, stat: %ld", (long)stat); + SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Circle SecKeyRawSign"), (error != NULL) ? *error : NULL, error); + return false; + }; + CFDataRef signature = CFDataCreate(allocator, tmp, tmplen); + SecKeyRef publicKey = SecKeyCreatePublicFromPrivate(privKey); + SOSCircleSetSignature(circle, publicKey, signature, error); + CFReleaseNull(publicKey); + CFRelease(signature); + return true; +} + +bool SOSCircleVerifySignatureExists(SOSCircleRef circle, SecKeyRef pubKey, CFErrorRef *error) { + if(!pubKey) { + // TODO ErrorRef + secerror("SOSCircleVerifySignatureExists no pubKey"); + SOSCreateError(kSOSErrorBadFormat, CFSTR("SOSCircleVerifySignatureExists no pubKey"), (error != NULL) ? *error : NULL, error); + return false; + } + CFDataRef signature = SOSCircleGetSignature(circle, pubKey, error); + return NULL != signature; +} + +bool SOSCircleVerify(SOSCircleRef circle, SecKeyRef pubKey, CFErrorRef *error) { + const struct ccdigest_info *di = ccsha256_di(); + uint8_t hash_result[di->output_size]; + + SOSCircleHash(di, circle, hash_result, error); + + CFDataRef signature = SOSCircleGetSignature(circle, pubKey, error); + if(!signature) return false; + + return SecKeyRawVerify(pubKey, kSecPaddingNone, hash_result, di->output_size, + CFDataGetBytePtr(signature), CFDataGetLength(signature)) == errSecSuccess; +} + +bool SOSCircleVerifyPeerSigned(SOSCircleRef circle, SOSPeerInfoRef peer, CFErrorRef *error) { + SecKeyRef pub_key = SOSPeerInfoCopyPubKey(peer); + bool result = SOSCircleVerify(circle, pub_key, error); + CFReleaseSafe(pub_key); + return result; +} + +static void CFSetRemoveAllPassing(CFMutableSetRef set, bool (^test)(const void *) ){ + CFMutableArrayRef toBeRemoved = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL); + + CFSetForEach(set, ^(const void *value) { + if (test(value)) + CFArrayAppendValue(toBeRemoved, value); + }); + + CFArrayForEach(toBeRemoved, ^(const void *value) { + CFSetRemoveValue(set, value); + }); + CFReleaseNull(toBeRemoved); +} + +static void SOSCircleRejectNonValidApplicants(SOSCircleRef circle, SecKeyRef pubkey) { + CFMutableSetRef applicants = SOSCircleCopyApplicants(circle, NULL); + CFSetForEach(applicants, ^(const void *value) { + SOSPeerInfoRef pi = (SOSPeerInfoRef) value; + if(!SOSPeerInfoApplicationVerify(pi, pubkey, NULL)) { + CFSetRemoveValue(circle->applicants, pi); + CFSetSetValue(circle->rejected_applicants, pi); + } + }); + CFReleaseNull(applicants); +} + +static SOSPeerInfoRef SOSCircleCopyPeerInfo(SOSCircleRef circle, CFStringRef peer_id, CFErrorRef *error) { + __block SOSPeerInfoRef result = NULL; + + CFSetForEach(circle->peers, ^(const void *value) { + if (result == NULL) { + SOSPeerInfoRef tpi = (SOSPeerInfoRef)value; + if (CFEqual(SOSPeerInfoGetPeerID(tpi), peer_id)) + result = tpi; + } + }); + + CFRetainSafe(result); + return result; +} + +static bool SOSCircleUpgradePeerInfo(SOSCircleRef circle, SecKeyRef user_approver, SOSFullPeerInfoRef peerinfo) { + bool retval = false; + SecKeyRef userPubKey = SecKeyCreatePublicFromPrivate(user_approver); + SOSPeerInfoRef fpi_pi = SOSFullPeerInfoGetPeerInfo(peerinfo); + SOSPeerInfoRef pi = SOSCircleCopyPeerInfo(circle, SOSPeerInfoGetPeerID(fpi_pi), NULL); + require_quiet(pi, out); + require_quiet(SOSPeerInfoApplicationVerify(pi, userPubKey, NULL), re_sign); + CFReleaseNull(userPubKey); + CFReleaseNull(pi); + return true; + +re_sign: + secerror("SOSCircleGenerationSign: Upgraded peer's Application Signature"); + SecKeyRef device_key = SOSFullPeerInfoCopyDeviceKey(peerinfo, NULL); + require_quiet(device_key, out); + SOSPeerInfoRef new_pi = SOSPeerInfoCopyAsApplication(pi, user_approver, device_key, NULL); + if(SOSCircleUpdatePeerInfo(circle, new_pi)) + retval = true; + CFReleaseNull(new_pi); + CFReleaseNull(device_key); +out: + CFReleaseNull(userPubKey); + CFReleaseNull(pi); + return retval; +} + +bool SOSCircleGenerationSign(SOSCircleRef circle, SecKeyRef user_approver, SOSFullPeerInfoRef peerinfo, CFErrorRef *error) { + SecKeyRef ourKey = SOSFullPeerInfoCopyDeviceKey(peerinfo, error); + SecKeyRef publicKey = NULL; + require_quiet(ourKey, fail); + + // Check if we're using an invalid peerinfo for this op. There are cases where we might not be "upgraded". + require_quiet(SOSCircleUpgradePeerInfo(circle, user_approver, peerinfo), fail); + SOSCircleRemoveRetired(circle, error); // Prune off retirees since we're signing this one + CFSetRemoveAllValues(circle->rejected_applicants); // Dump rejects so we clean them up sometime. + publicKey = SecKeyCreatePublicFromPrivate(user_approver); + SOSCircleRejectNonValidApplicants(circle, publicKey); + SOSCircleGenerationIncrement(circle); + require_quiet(SOSCircleRemoveSignatures(circle, error), fail); + require_quiet(SOSCircleSign(circle, user_approver, error), fail); + require_quiet(SOSCircleSign(circle, ourKey, error), fail); + + CFReleaseNull(ourKey); + CFReleaseNull(publicKey); + return true; + +fail: + CFReleaseNull(ourKey); + CFReleaseNull(publicKey); + return false; +} + +bool SOSCircleGenerationUpdate(SOSCircleRef circle, SecKeyRef user_approver, SOSFullPeerInfoRef peerinfo, CFErrorRef *error) { + + return SOSCircleGenerationSign(circle, user_approver, peerinfo, error); + +#if 0 + bool success = false; + + SecKeyRef ourKey = SOSFullPeerInfoCopyDeviceKey(peerinfo, error); + require_quiet(ourKey, fail); + + require_quiet(SOSCircleSign(circle, user_approver, error), fail); + require_quiet(SOSCircleSign(circle, ourKey, error), fail); + + success = true; + +fail: + CFReleaseNull(ourKey); + return success; +#endif +} + +bool SOSCircleConcordanceSign(SOSCircleRef circle, SOSFullPeerInfoRef peerinfo, CFErrorRef *error) { + bool success = false; + SecKeyRef ourKey = SOSFullPeerInfoCopyDeviceKey(peerinfo, error); + require_quiet(ourKey, exit); + + success = SOSCircleSign(circle, ourKey, error); + +exit: + CFReleaseNull(ourKey); + return success; +} + +static inline SOSConcordanceStatus CheckPeerStatus(SOSCircleRef circle, SOSPeerInfoRef peer, SecKeyRef user_public_key, CFErrorRef *error) { + SOSConcordanceStatus result = kSOSConcordanceNoPeer; + SecKeyRef pubKey = SOSPeerInfoCopyPubKey(peer); + + require_action_quiet(SOSCircleHasActiveValidPeer(circle, peer, user_public_key, error), exit, result = kSOSConcordanceNoPeer); + require_action_quiet(SOSCircleVerifySignatureExists(circle, pubKey, error), exit, result = kSOSConcordanceNoPeerSig); + require_action_quiet(SOSCircleVerify(circle, pubKey, error), exit, result = kSOSConcordanceBadPeerSig); + + result = kSOSConcordanceTrusted; + +exit: + CFReleaseNull(pubKey); + return result; +} + +static inline SOSConcordanceStatus CombineStatus(SOSConcordanceStatus status1, SOSConcordanceStatus status2) +{ + if (status1 == kSOSConcordanceTrusted || status2 == kSOSConcordanceTrusted) + return kSOSConcordanceTrusted; + + if (status1 == kSOSConcordanceBadPeerSig || status2 == kSOSConcordanceBadPeerSig) + return kSOSConcordanceBadPeerSig; + + if (status1 == kSOSConcordanceNoPeerSig || status2 == kSOSConcordanceNoPeerSig) + return kSOSConcordanceNoPeerSig; + + return status1; +} + +static inline bool SOSCircleIsEmpty(SOSCircleRef circle) { + return SOSCircleCountPeers(circle) == 0; +} + +static inline bool SOSCircleIsOffering(SOSCircleRef circle) { + return SOSCircleCountPeers(circle) == 1; +} + +__unused static inline bool SOSCircleIsResignOffering(SOSCircleRef circle, SecKeyRef pubkey) { + return SOSCircleCountActiveValidPeers(circle, pubkey) == 1; +} + +static inline SOSConcordanceStatus GetSignersStatus(SOSCircleRef signers_circle, SOSCircleRef status_circle, + SecKeyRef user_pubKey, SOSPeerInfoRef exclude, CFErrorRef *error) { + CFStringRef excluded_id = exclude ? SOSPeerInfoGetPeerID(exclude) : NULL; + + __block SOSConcordanceStatus status = kSOSConcordanceNoPeer; + SOSCircleForEachActivePeer(signers_circle, ^(SOSPeerInfoRef peer) { + SOSConcordanceStatus peerStatus = CheckPeerStatus(status_circle, peer, user_pubKey, error); + + if (peerStatus == kSOSConcordanceNoPeerSig && + (CFEqualSafe(SOSPeerInfoGetPeerID(peer), excluded_id) || SOSPeerInfoIsCloudIdentity(peer))) + peerStatus = kSOSConcordanceNoPeer; + + status = CombineStatus(status, peerStatus); // TODO: Use multiple error gathering. + }); + + return status; +} + +static inline bool isOlderGeneration(SOSCircleRef current, SOSCircleRef proposed) { + return CFNumberCompare(current->generation, proposed->generation, NULL) == kCFCompareGreaterThan; +} + +bool SOSCircleSharedTrustedPeers(SOSCircleRef current, SOSCircleRef proposed, SOSPeerInfoRef me) { + __block bool retval = false; + SOSCircleForEachPeer(current, ^(SOSPeerInfoRef peer) { + if(!CFEqual(me, peer) && SOSCircleHasPeer(proposed, peer, NULL)) retval = true; + }); + return retval; +} + +static void SOSCircleUpgradePeersByCircle(SOSCircleRef known_circle, SOSCircleRef proposed_circle) { + SOSCircleForEachPeer(known_circle, ^(SOSPeerInfoRef known_peer) { + SOSPeerInfoRef proposed_peer = SOSCircleCopyPeerInfo(proposed_circle, SOSPeerInfoGetPeerID(known_peer), NULL); + if(proposed_peer && CFEqualSafe(proposed_peer, known_peer) != 0) { + SOSCircleUpdatePeerInfo(known_circle, proposed_peer); + } + }); +} + +SOSConcordanceStatus SOSCircleConcordanceTrust(SOSCircleRef known_circle, SOSCircleRef proposed_circle, + SecKeyRef known_pubkey, SecKeyRef user_pubkey, + SOSPeerInfoRef exclude, CFErrorRef *error) { + if(user_pubkey == NULL) { + SOSCreateError(kSOSErrorPublicKeyAbsent, CFSTR("Concordance with no public key"), NULL, error); + return kSOSConcordanceNoUserKey; //TODO: - needs to return an error + } + + if (SOSCircleIsEmpty(proposed_circle)) { + return kSOSConcordanceTrusted; + } + + if(!SOSCircleVerifySignatureExists(proposed_circle, user_pubkey, error)) { + SOSCreateError(kSOSErrorBadSignature, CFSTR("No public signature"), (error != NULL) ? *error : NULL, error); + return kSOSConcordanceNoUserSig; + } + + if(!SOSCircleVerify(proposed_circle, user_pubkey, error)) { + SOSCreateError(kSOSErrorBadSignature, CFSTR("Bad public signature"), (error != NULL) ? *error : NULL, error); + return kSOSConcordanceBadUserSig; + } + + if (SOSCircleIsEmpty(known_circle) || SOSCircleIsOffering(proposed_circle)) { + return GetSignersStatus(proposed_circle, proposed_circle, user_pubkey, NULL, error); + } + + if(isOlderGeneration(known_circle, proposed_circle)) { + SOSCreateError(kSOSErrorReplay, CFSTR("Bad generation"), NULL, error); + return kSOSConcordanceGenOld; + } + + + if(!SOSCircleVerify(known_circle, user_pubkey, error)) { + SOSCircleUpgradePeersByCircle(known_circle, proposed_circle); + } + + if(known_pubkey == NULL) known_pubkey = user_pubkey; + if(!SOSCircleVerify(known_circle, known_pubkey, error)) known_pubkey = user_pubkey; + return GetSignersStatus(known_circle, proposed_circle, known_pubkey, exclude, error); +} + + +static const uint8_t* der_decode_mutable_dictionary(CFAllocatorRef allocator, CFOptionFlags mutability, + CFMutableDictionaryRef* dictionary, CFErrorRef *error, + const uint8_t* der, const uint8_t *der_end) +{ + CFDictionaryRef theDict; + const uint8_t* result = der_decode_dictionary(allocator, mutability, &theDict, error, der, der_end); + + if (result != NULL) + *dictionary = (CFMutableDictionaryRef)theDict; + + return result; +} + + +SOSCircleRef SOSCircleCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error, + const uint8_t** der_p, const uint8_t *der_end) { + SOSCircleRef cir = CFTypeAllocate(SOSCircle, struct __OpaqueSOSCircle, allocator); + + const uint8_t *sequence_end; + + cir->name = NULL; + cir->generation = NULL; + cir->peers = NULL; + cir->applicants = NULL; + cir->rejected_applicants = NULL; + cir->signatures = NULL; + + *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); + require_action_quiet(sequence_end != NULL, fail, + SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Circle DER"), (error != NULL) ? *error : NULL, error)); + + // Version first. + uint64_t version = 0; + *der_p = ccder_decode_uint64(&version, *der_p, der_end); + + require_action_quiet(version == kOnlyCompatibleVersion, fail, + SOSCreateError(kSOSErrorIncompatibleCircle, CFSTR("Bad Circle Version"), NULL, error)); + + *der_p = der_decode_string(allocator, 0, &cir->name, error, *der_p, sequence_end); + *der_p = der_decode_number(allocator, 0, &cir->generation, error, *der_p, sequence_end); + + cir->peers = SOSPeerInfoSetCreateFromArrayDER(allocator, &kSOSPeerSetCallbacks, error, der_p, sequence_end); + cir->applicants = SOSPeerInfoSetCreateFromArrayDER(allocator, &kSOSPeerSetCallbacks, error, der_p, sequence_end); + cir->rejected_applicants = SOSPeerInfoSetCreateFromArrayDER(allocator, &kSOSPeerSetCallbacks, error, der_p, sequence_end); + + *der_p = der_decode_mutable_dictionary(allocator, kCFPropertyListMutableContainersAndLeaves, + &cir->signatures, error, *der_p, sequence_end); + + require_action_quiet(*der_p == sequence_end, fail, + SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Circle DER"), (error != NULL) ? *error : NULL, error)); + + return cir; + +fail: + CFReleaseNull(cir); + return NULL; +} + +SOSCircleRef SOSCircleCreateFromData(CFAllocatorRef allocator, CFDataRef circleData, CFErrorRef *error) +{ + size_t size = CFDataGetLength(circleData); + const uint8_t *der = CFDataGetBytePtr(circleData); + SOSCircleRef inflated = SOSCircleCreateFromDER(allocator, error, &der, der + size); + return inflated; +} + +size_t SOSCircleGetDEREncodedSize(SOSCircleRef cir, CFErrorRef *error) { + SOSCircleAssertStable(cir); + size_t total_payload = 0; + + require_quiet(accumulate_size(&total_payload, ccder_sizeof_uint64(kOnlyCompatibleVersion)), fail); + require_quiet(accumulate_size(&total_payload, der_sizeof_string(cir->name, error)), fail); + require_quiet(accumulate_size(&total_payload, der_sizeof_number(cir->generation, error)), fail); + require_quiet(accumulate_size(&total_payload, SOSPeerInfoSetGetDEREncodedArraySize(cir->peers, error)), fail); + require_quiet(accumulate_size(&total_payload, SOSPeerInfoSetGetDEREncodedArraySize(cir->applicants, error)), fail); + require_quiet(accumulate_size(&total_payload, SOSPeerInfoSetGetDEREncodedArraySize(cir->rejected_applicants, error)), fail); + require_quiet(accumulate_size(&total_payload, der_sizeof_dictionary((CFDictionaryRef) cir->signatures, error)), fail); + + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, total_payload); + +fail: + SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error); + return 0; +} + +uint8_t* SOSCircleEncodeToDER(SOSCircleRef cir, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) { + SOSCircleAssertStable(cir); + + return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + ccder_encode_uint64(kOnlyCompatibleVersion, der, + der_encode_string(cir->name, error, der, + der_encode_number(cir->generation, error, der, + SOSPeerInfoSetEncodeToArrayDER(cir->peers, error, der, + SOSPeerInfoSetEncodeToArrayDER(cir->applicants, error, der, + SOSPeerInfoSetEncodeToArrayDER(cir->rejected_applicants, error, der, + der_encode_dictionary((CFDictionaryRef) cir->signatures, error, der, der_end)))))))); +} + +CFDataRef SOSCircleCreateIncompatibleCircleDER(CFErrorRef* error) +{ + size_t total_payload = 0; + size_t encoded_size = 0; + uint8_t* der = 0; + uint8_t* der_end = 0; + CFMutableDataRef result = NULL; + + require_quiet(accumulate_size(&total_payload, ccder_sizeof_uint64(kAlwaysIncompatibleVersion)), fail); + + encoded_size = ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, total_payload); + + result = CFDataCreateMutableWithScratch(kCFAllocatorDefault, encoded_size); + + der = CFDataGetMutableBytePtr(result); + der_end = der + CFDataGetLength(result); + + der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + ccder_encode_uint64(kAlwaysIncompatibleVersion, der, der_end)); + +fail: + if (der == NULL || der != der_end) + CFReleaseNull(result); + + return result; +} + + +CFDataRef SOSCircleCopyEncodedData(SOSCircleRef circle, CFAllocatorRef allocator, CFErrorRef *error) +{ + size_t size = SOSCircleGetDEREncodedSize(circle, error); + if (size == 0) + return NULL; + uint8_t buffer[size]; + uint8_t* start = SOSCircleEncodeToDER(circle, error, buffer, buffer + sizeof(buffer)); + CFDataRef result = CFDataCreate(kCFAllocatorDefault, start, size); + return result; +} + +static void SOSCircleDestroy(CFTypeRef aObj) { + SOSCircleRef c = (SOSCircleRef) aObj; + + CFReleaseNull(c->name); + CFReleaseNull(c->generation); + CFReleaseNull(c->peers); + CFReleaseNull(c->applicants); + CFReleaseNull(c->rejected_applicants); + CFReleaseNull(c->signatures); +} + +static CFStringRef SOSCircleCopyDescription(CFTypeRef aObj) { + SOSCircleRef c = (SOSCircleRef) aObj; + + SOSCircleAssertStable(c); + + + CFMutableStringRef description = CFStringCreateMutable(kCFAllocatorDefault, 0); + CFStringAppendFormat(description, NULL, CFSTR("name); + + __block CFStringRef separator = CFSTR(""); + SOSCircleForEachPeer(c, ^(SOSPeerInfoRef peer) { + CFStringRef sig = NULL; + if (SOSCircleVerifyPeerSigned(c, peer, NULL)) { + sig = CFSTR("√"); + } else { + SecKeyRef pub_key = SOSPeerInfoCopyPubKey(peer); + CFDataRef signature = SOSCircleGetSignature(c, pub_key, NULL); + sig = (signature == NULL) ? CFSTR("-") : CFSTR("?"); + CFReleaseNull(pub_key); + } + + CFStringAppendFormat(description, NULL, CFSTR("%@%@ %@"), separator, peer, sig); + separator = CFSTR(","); + }); + + CFStringAppend(description, CFSTR("], A:[")); + separator = CFSTR(""); + SOSCircleForEachApplicant(c, ^(SOSPeerInfoRef peer) { + CFStringAppendFormat(description, NULL, CFSTR("%@%@"), separator, peer); + separator = CFSTR(","); + }); + + CFStringAppend(description, CFSTR("], R:[")); + separator = CFSTR(""); + CFSetForEach(c->rejected_applicants, ^(const void *value) { + SOSPeerInfoRef peer = (SOSPeerInfoRef) value; + CFStringAppendFormat(description, NULL, CFSTR("%@%@"), separator, peer); + separator = CFSTR(","); + }); + CFStringAppend(description, CFSTR("]>")); + + return description; +} + +CFStringRef SOSCircleGetName(SOSCircleRef circle) { + assert(circle); + assert(circle->name); + return circle->name; +} + +const char *SOSCircleGetNameC(SOSCircleRef circle) { + CFStringRef name = SOSCircleGetName(circle); + if (!name) + return strdup(""); + return CFStringToCString(name); +} + +CFNumberRef SOSCircleGetGeneration(SOSCircleRef circle) { + assert(circle); + assert(circle->generation); + return circle->generation; +} + +int64_t SOSCircleGetGenerationSint(SOSCircleRef circle) { + CFNumberRef gen = SOSCircleGetGeneration(circle); + int64_t value; + if(!gen) return 0; + CFNumberGetValue(gen, kCFNumberSInt64Type, &value); + return value; +} + +void SOSCircleGenerationSetValue(SOSCircleRef circle, int64_t value) +{ + CFAllocatorRef allocator = CFGetAllocator(circle->generation); + CFAssignRetained(circle->generation, CFNumberCreate(allocator, kCFNumberSInt64Type, &value)); +} + + +static int64_t GenerationSetHighBits(int64_t value, int32_t high_31) +{ + value &= 0xFFFFFFFF; // Keep the low 32 bits. + value |= ((int64_t) high_31) << 32; + + return value; +} + + +void SOSCircleGenerationIncrement(SOSCircleRef circle) { + int64_t value = SOSCircleGetGenerationSint(circle); + + if ((value >> 32) == 0) { + uint32_t seconds = CFAbsoluteTimeGetCurrent(); // seconds + value = GenerationSetHighBits(value, (seconds >> 1)); + } + + value++; + + SOSCircleGenerationSetValue(circle, value); +} + +int SOSCircleCountPeers(SOSCircleRef circle) { + SOSCircleAssertStable(circle); + __block int count = 0; + SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { + ++count; + }); + return count; +} + +int SOSCircleCountActivePeers(SOSCircleRef circle) { + SOSCircleAssertStable(circle); + __block int count = 0; + SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { + ++count; + }); + return count; +} + +int SOSCircleCountActiveValidPeers(SOSCircleRef circle, SecKeyRef pubkey) { + SOSCircleAssertStable(circle); + __block int count = 0; + SOSCircleForEachActiveValidPeer(circle, pubkey, ^(SOSPeerInfoRef peer) { + ++count; + }); + return count; +} + +int SOSCircleCountRetiredPeers(SOSCircleRef circle) { + SOSCircleAssertStable(circle); + __block int count = 0; + SOSCircleForEachRetiredPeer(circle, ^(SOSPeerInfoRef peer) { + ++count; + }); + return count; +} + +int SOSCircleCountApplicants(SOSCircleRef circle) { + SOSCircleAssertStable(circle); + + return (int)CFSetGetCount(circle->applicants); +} + +bool SOSCircleHasApplicant(SOSCircleRef circle, SOSPeerInfoRef peerInfo, CFErrorRef *error) { + SOSCircleAssertStable(circle); + + return CFSetContainsValue(circle->applicants, peerInfo); +} + +CFMutableSetRef SOSCircleCopyApplicants(SOSCircleRef circle, CFAllocatorRef allocator) { + SOSCircleAssertStable(circle); + + return CFSetCreateMutableCopy(allocator, 0, circle->applicants); +} + +int SOSCircleCountRejectedApplicants(SOSCircleRef circle) { + SOSCircleAssertStable(circle); + + return (int)CFSetGetCount(circle->rejected_applicants); +} + +bool SOSCircleHasRejectedApplicant(SOSCircleRef circle, SOSPeerInfoRef peerInfo, CFErrorRef *error) { + SOSCircleAssertStable(circle); + return CFSetContainsValue(circle->rejected_applicants, peerInfo); +} + +SOSPeerInfoRef SOSCircleCopyRejectedApplicant(SOSCircleRef circle, SOSPeerInfoRef peerInfo, CFErrorRef *error) { + SOSCircleAssertStable(circle); + return CFRetainSafe((SOSPeerInfoRef)CFSetGetValue(circle->rejected_applicants, peerInfo)); +} + +CFMutableArrayRef SOSCircleCopyRejectedApplicants(SOSCircleRef circle, CFAllocatorRef allocator) { + SOSCircleAssertStable(circle); + + return CFSetCopyValuesCFArray(circle->rejected_applicants); +} + + +bool SOSCircleHasPeerWithID(SOSCircleRef circle, CFStringRef peerid, CFErrorRef *error) { + SOSCircleAssertStable(circle); + __block bool found = false; + SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { + if(peerid && peer && CFEqualSafe(peerid, SOSPeerInfoGetPeerID(peer))) found = true; + }); + return found; +} + +SOSPeerInfoRef SOSCircleCopyPeerWithID(SOSCircleRef circle, CFStringRef peerid, CFErrorRef *error) { + SOSCircleAssertStable(circle); + __block SOSPeerInfoRef found = false; + SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { + if(peerid && peer && CFEqualSafe(peerid, SOSPeerInfoGetPeerID(peer))) found = peer; + }); + return found; +} + +bool SOSCircleHasPeer(SOSCircleRef circle, SOSPeerInfoRef peerInfo, CFErrorRef *error) { + return SOSCircleHasPeerWithID(circle, SOSPeerInfoGetPeerID(peerInfo), error); +} + +bool SOSCircleHasActivePeerWithID(SOSCircleRef circle, CFStringRef peerid, CFErrorRef *error) { + SOSCircleAssertStable(circle); + __block bool found = false; + SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { + if(peerid && peer && CFEqualSafe(peerid, SOSPeerInfoGetPeerID(peer))) found = true; + }); + return found; +} + +bool SOSCircleHasActivePeer(SOSCircleRef circle, SOSPeerInfoRef peerInfo, CFErrorRef *error) { + if(!peerInfo) return false; + return SOSCircleHasActivePeerWithID(circle, SOSPeerInfoGetPeerID(peerInfo), error); +} + +bool SOSCircleHasActiveValidPeerWithID(SOSCircleRef circle, CFStringRef peerid, SecKeyRef user_public_key, CFErrorRef *error) { + SOSCircleAssertStable(circle); + __block bool found = false; + SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { + if(peerid && peer && CFEqualSafe(peerid, SOSPeerInfoGetPeerID(peer)) && SOSPeerInfoApplicationVerify(peer, user_public_key, NULL)) found = true; + }); + return found; +} + +bool SOSCircleHasActiveValidPeer(SOSCircleRef circle, SOSPeerInfoRef peerInfo, SecKeyRef user_public_key, CFErrorRef *error) { + if(!peerInfo) return false; + return SOSCircleHasActiveValidPeerWithID(circle, SOSPeerInfoGetPeerID(peerInfo), user_public_key, error); +} + + +bool SOSCircleResetToEmpty(SOSCircleRef circle, CFErrorRef *error) { + CFSetRemoveAllValues(circle->applicants); + CFSetRemoveAllValues(circle->rejected_applicants); + CFSetRemoveAllValues(circle->peers); + CFDictionaryRemoveAllValues(circle->signatures); + + int64_t old_value = SOSCircleGetGenerationSint(circle); + + SOSCircleGenerationSetValue(circle, 0); + SOSCircleGenerationIncrement(circle); // Increment to get high bits set. + + int64_t new_value = SOSCircleGetGenerationSint(circle); + + if (new_value <= old_value) { + int64_t new_new_value = GenerationSetHighBits(new_value, (old_value >> 32) + 1); + SOSCircleGenerationSetValue(circle, new_new_value); + } + + return true; +} + +bool SOSCircleResetToOffering(SOSCircleRef circle, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error){ + + return SOSCircleResetToEmpty(circle, error) + && SOSCircleRequestAdmission(circle, user_privkey, requestor, error) + && SOSCircleAcceptRequest(circle, user_privkey, requestor, SOSFullPeerInfoGetPeerInfo(requestor), error); +} + +bool SOSCircleRemoveRetired(SOSCircleRef circle, CFErrorRef *error) { + CFSetRemoveAllPassing(circle->peers, ^ bool (const void *element) { + SOSPeerInfoRef peer = (SOSPeerInfoRef) element; + + return SOSPeerInfoIsRetirementTicket(peer); + }); + + return true; +} + +static bool SOSCircleRecordAdmissionRequest(SOSCircleRef circle, SecKeyRef user_pubkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) { + SOSCircleAssertStable(circle); + + SOSPeerInfoRef requestorPeerInfo = SOSFullPeerInfoGetPeerInfo(requestor); + bool isPeer = SOSCircleHasPeer(circle, SOSFullPeerInfoGetPeerInfo(requestor), error); + + require_action_quiet(!isPeer, fail, SOSCreateError(kSOSErrorAlreadyPeer, CFSTR("Cannot request admission when already a peer"), NULL, error)); + + CFSetRemoveValue(circle->rejected_applicants, requestorPeerInfo); // We remove from rejected list, in case? + CFSetSetValue(circle->applicants, requestorPeerInfo); + + return true; + +fail: + return false; + +} + +bool SOSCircleRequestReadmission(SOSCircleRef circle, SecKeyRef user_pubkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) { + bool success = false; + + SOSPeerInfoRef peer = SOSFullPeerInfoGetPeerInfo(requestor); + require_quiet(SOSPeerInfoApplicationVerify(peer, user_pubkey, error), fail); + success = SOSCircleRecordAdmissionRequest(circle, user_pubkey, requestor, error); +fail: + return success; +} + +bool SOSCircleRequestAdmission(SOSCircleRef circle, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) { + bool success = false; + + SecKeyRef user_pubkey = SecKeyCreatePublicFromPrivate(user_privkey); + require_action_quiet(user_pubkey, fail, SOSCreateError(kSOSErrorBadKey, CFSTR("No public key for key"), NULL, error)); + + require(SOSFullPeerInfoPromoteToApplication(requestor, user_privkey, error), fail); + + success = SOSCircleRecordAdmissionRequest(circle, user_pubkey, requestor, error); +fail: + CFReleaseNull(user_pubkey); + return success; +} + + +bool SOSCircleUpdatePeerInfo(SOSCircleRef circle, SOSPeerInfoRef replacement_peer_info) { + if(!replacement_peer_info) return false; + CFTypeRef old = CFSetGetValue(circle->peers, replacement_peer_info); + bool replace = old && !CFEqualSafe(old, replacement_peer_info); + if (replace) + CFSetReplaceValue(circle->peers, replacement_peer_info); + + return replace; +} + +bool SOSCircleRemovePeer(SOSCircleRef circle, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, SOSPeerInfoRef peer_to_remove, CFErrorRef *error) { + SOSPeerInfoRef requestor_peer_info = SOSFullPeerInfoGetPeerInfo(requestor); + + if (SOSCircleHasApplicant(circle, peer_to_remove, error)) { + return SOSCircleRejectRequest(circle, requestor, peer_to_remove, error); + } + + if (!SOSCircleHasPeer(circle, requestor_peer_info, error)) { + SOSCreateError(kSOSErrorAlreadyPeer, CFSTR("Must be peer to remove peer"), NULL, error); + return false; + } + + CFSetRemoveValue(circle->peers, peer_to_remove); + + SOSCircleGenerationSign(circle, user_privkey, requestor, error); + + return true; +} + +bool SOSCircleAcceptRequest(SOSCircleRef circle, SecKeyRef user_privkey, SOSFullPeerInfoRef device_approver, SOSPeerInfoRef peerInfo, CFErrorRef *error) { + SOSCircleAssertStable(circle); + + SecKeyRef publicKey = NULL; + bool result = false; + + require_action_quiet(CFSetContainsValue(circle->applicants, peerInfo), fail, + SOSCreateError(kSOSErrorNotApplicant, CFSTR("Cannot accept non-applicant"), NULL, error)); + + publicKey = SecKeyCreatePublicFromPrivate(user_privkey); + require_quiet(SOSPeerInfoApplicationVerify(peerInfo, publicKey, error), fail); + + CFSetRemoveValue(circle->applicants, peerInfo); + CFSetSetValue(circle->peers, peerInfo); + + result = SOSCircleGenerationSign(circle, user_privkey, device_approver, error); + secnotice("circle", "Accepted %@", peerInfo); + +fail: + CFReleaseNull(publicKey); + return result; +} + +bool SOSCircleWithdrawRequest(SOSCircleRef circle, SOSPeerInfoRef peerInfo, CFErrorRef *error) { + SOSCircleAssertStable(circle); + + CFSetRemoveValue(circle->applicants, peerInfo); + + return true; +} + +bool SOSCircleRemoveRejectedPeer(SOSCircleRef circle, SOSPeerInfoRef peerInfo, CFErrorRef *error) { + SOSCircleAssertStable(circle); + + CFSetRemoveValue(circle->rejected_applicants, peerInfo); + + return true; +} + + +bool SOSCircleRejectRequest(SOSCircleRef circle, SOSFullPeerInfoRef device_rejector, + SOSPeerInfoRef peerInfo, CFErrorRef *error) { + SOSCircleAssertStable(circle); + + if (CFEqual(SOSPeerInfoGetPeerID(peerInfo), SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(device_rejector)))) + return SOSCircleWithdrawRequest(circle, peerInfo, error); + + if (!CFSetContainsValue(circle->applicants, peerInfo)) { + SOSCreateError(kSOSErrorNotApplicant, CFSTR("Cannot reject non-applicant"), NULL, error); + return false; + } + + CFSetRemoveValue(circle->applicants, peerInfo); + CFSetSetValue(circle->rejected_applicants, peerInfo); + + // TODO: Maybe we sign the rejection with device_rejector. + + return true; +} + +bool SOSCircleAcceptRequests(SOSCircleRef circle, SecKeyRef user_privkey, SOSFullPeerInfoRef device_approver, + CFErrorRef *error) { + // Returns true if we accepted someone and therefore have to post the circle back to KVS + __block bool result = false; + + SOSCircleForEachApplicant(circle, ^(SOSPeerInfoRef peer) { + if (!SOSCircleAcceptRequest(circle, user_privkey, device_approver, peer, error)) + printf("error in SOSCircleAcceptRequest\n"); + else { + secnotice("circle", "Accepted peer: %@", peer); + result = true; + } + }); + + if (result) { + SOSCircleGenerationSign(circle, user_privkey, device_approver, error); + secnotice("circle", "Countersigned accepted requests"); + } + + return result; +} + +bool SOSCirclePeerSigUpdate(SOSCircleRef circle, SecKeyRef userPrivKey, SOSFullPeerInfoRef fpi, + CFErrorRef *error) { + // Returns true if we accepted someone and therefore have to post the circle back to KVS + __block bool result = false; + SecKeyRef userPubKey = SecKeyCreatePublicFromPrivate(userPrivKey); + + // We're going to remove any applicants using a mismatched user key. + SOSCircleForEachApplicant(circle, ^(SOSPeerInfoRef peer) { + if(!SOSPeerInfoApplicationVerify(peer, userPubKey, NULL)) { + if(!SOSCircleRejectRequest(circle, fpi, peer, NULL)) { + // do we care? + } + } + }); + + result = SOSCircleUpdatePeerInfo(circle, SOSFullPeerInfoGetPeerInfo(fpi)); + + if (result) { + SOSCircleGenerationSign(circle, userPrivKey, fpi, error); + secnotice("circle", "Generation signed updated signatures on peerinfo"); + } + + return result; +} + +static inline void SOSCircleForEachPeerMatching(SOSCircleRef circle, + void (^action)(SOSPeerInfoRef peer), + bool (^condition)(SOSPeerInfoRef peer)) { + CFSetForEach(circle->peers, ^(const void *value) { + SOSPeerInfoRef peer = (SOSPeerInfoRef) value; + if (condition(peer)) + action(peer); + }); +} + +static inline bool isHiddenPeer(SOSPeerInfoRef peer) { + return SOSPeerInfoIsRetirementTicket(peer) || SOSPeerInfoIsCloudIdentity(peer); +} + +void SOSCircleForEachPeer(SOSCircleRef circle, void (^action)(SOSPeerInfoRef peer)) { + SOSCircleForEachPeerMatching(circle, action, ^bool(SOSPeerInfoRef peer) { + return !isHiddenPeer(peer); + }); +} + +void SOSCircleForEachRetiredPeer(SOSCircleRef circle, void (^action)(SOSPeerInfoRef peer)) { + SOSCircleForEachPeerMatching(circle, action, ^bool(SOSPeerInfoRef peer) { + return SOSPeerInfoIsRetirementTicket(peer); + }); +} + +void SOSCircleForEachActivePeer(SOSCircleRef circle, void (^action)(SOSPeerInfoRef peer)) { + SOSCircleForEachPeerMatching(circle, action, ^bool(SOSPeerInfoRef peer) { + return true; + }); +} + +void SOSCircleForEachActiveValidPeer(SOSCircleRef circle, SecKeyRef user_public_key, void (^action)(SOSPeerInfoRef peer)) { + SOSCircleForEachPeerMatching(circle, action, ^bool(SOSPeerInfoRef peer) { + return SOSPeerInfoApplicationVerify(peer, user_public_key, NULL); + }); +} + +void SOSCircleForEachApplicant(SOSCircleRef circle, void (^action)(SOSPeerInfoRef peer)) { + CFSetForEach(circle->applicants, ^(const void*value) { action((SOSPeerInfoRef) value); } ); +} + + +CFMutableSetRef SOSCircleCopyPeers(SOSCircleRef circle, CFAllocatorRef allocator) { + SOSCircleAssertStable(circle); + + CFMutableSetRef result = CFSetCreateMutableForSOSPeerInfosByID(allocator); + + SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { + CFSetAddValue(result, peer); + }); + + return result; +} + +bool SOSCircleAppendConcurringPeers(SOSCircleRef circle, CFMutableArrayRef appendHere, CFErrorRef *error) { + SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { + CFErrorRef localError = NULL; + if (SOSCircleVerifyPeerSigned(circle, peer, &localError)) { + CFArrayAppendValue(appendHere, peer); + } else if (error != NULL) { + secerror("Error checking concurrence: %@", localError); + } + CFReleaseNull(localError); + }); + + return true; +} + +CFMutableArrayRef SOSCircleCopyConcurringPeers(SOSCircleRef circle, CFErrorRef* error) { + SOSCircleAssertStable(circle); + + CFMutableArrayRef concurringPeers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + + if (!SOSCircleAppendConcurringPeers(circle, concurringPeers, error)) + CFReleaseNull(concurringPeers); + + return concurringPeers; +} + +SOSFullPeerInfoRef SOSCircleGetiCloudFullPeerInfoRef(SOSCircleRef circle) { + __block SOSFullPeerInfoRef cloud_full_peer = NULL; + SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { + if (SOSPeerInfoIsCloudIdentity(peer)) { + if (cloud_full_peer == NULL) { + CFErrorRef localError = NULL; + cloud_full_peer = SOSFullPeerInfoCreateCloudIdentity(kCFAllocatorDefault, peer, &localError); + + if (localError) { + secerror("Found cloud peer in circle but can't make full peer: %@", localError); + CFReleaseNull(localError); + } + + } else { + secerror("More than one cloud identity found in circle: %@", circle); + } + } + }); + return cloud_full_peer; +} diff --git a/sec/SOSCircle/SecureObjectSync/SOSCircle.h b/Security/sec/SOSCircle/SecureObjectSync/SOSCircle.h similarity index 77% rename from sec/SOSCircle/SecureObjectSync/SOSCircle.h rename to Security/sec/SOSCircle/SecureObjectSync/SOSCircle.h index a87e8829..84fc7b72 100644 --- a/sec/SOSCircle/SecureObjectSync/SOSCircle.h +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSCircle.h @@ -1,8 +1,27 @@ /* - * Created by Michael Brouwer on 6/22/12. - * Copyright 2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + /*! @header SOSCircle.h The functions provided in SOSCircle.h provide an interface to a @@ -15,23 +34,12 @@ #include #include #include -#include #include __BEGIN_DECLS typedef struct __OpaqueSOSCircle *SOSCircleRef; -/* SOSDataSourceFactory protocol (non opaque). */ -typedef struct SOSDataSourceFactory *SOSDataSourceFactoryRef; - -struct SOSDataSourceFactory { - CFArrayRef (*copy_names)(SOSDataSourceFactoryRef factory); - SOSDataSourceRef (*create_datasource)(SOSDataSourceFactoryRef factory, CFStringRef dataSourceName, bool readOnly, CFErrorRef *error); - void (*release)(SOSDataSourceFactoryRef factory); -}; - - CFTypeID SOSCircleGetTypeID(); SOSCircleRef SOSCircleCreate(CFAllocatorRef allocator, CFStringRef circleName, CFErrorRef *error); @@ -47,6 +55,7 @@ bool SOSCircleVerify(SOSCircleRef circle, SecKeyRef pubkey, CFErrorRef *error); bool SOSCircleVerifyPeerSigned(SOSCircleRef circle, SOSPeerInfoRef peer, CFErrorRef *error); bool SOSCircleGenerationSign(SOSCircleRef circle, SecKeyRef user_approver, SOSFullPeerInfoRef peerinfo, CFErrorRef *error); +bool SOSCircleGenerationUpdate(SOSCircleRef circle, SecKeyRef user_approver, SOSFullPeerInfoRef peerinfo, CFErrorRef *error); size_t SOSCircleGetDEREncodedSize(SOSCircleRef cir, CFErrorRef *error); uint8_t* SOSCircleEncodeToDER(SOSCircleRef cir, CFErrorRef* error, const uint8_t* der, uint8_t* der_end); @@ -54,7 +63,7 @@ CFDataRef SOSCircleCopyEncodedData(SOSCircleRef circle, CFAllocatorRef allocator int SOSCircleCountApplicants(SOSCircleRef circle); bool SOSCircleHasApplicant(SOSCircleRef circle, SOSPeerInfoRef peerInfo, CFErrorRef *error); -CFMutableArrayRef SOSCircleCopyApplicants(SOSCircleRef c, CFAllocatorRef allocator); +CFMutableSetRef SOSCircleCopyApplicants(SOSCircleRef c, CFAllocatorRef allocator); void SOSCircleForEachApplicant(SOSCircleRef circle, void (^action)(SOSPeerInfoRef peer)); int SOSCircleCountRejectedApplicants(SOSCircleRef circle); @@ -65,12 +74,15 @@ CFMutableArrayRef SOSCircleCopyRejectedApplicants(SOSCircleRef c, CFAllocatorRef CFStringRef SOSCircleGetName(SOSCircleRef circle); const char *SOSCircleGetNameC(SOSCircleRef circle); +void SOSCircleGenerationSetValue(SOSCircleRef circle, int64_t value); CFNumberRef SOSCircleGetGeneration(SOSCircleRef circle); int64_t SOSCircleGetGenerationSint(SOSCircleRef circle); void SOSCircleGenerationIncrement(SOSCircleRef circle); -CFMutableArrayRef SOSCircleCopyPeers(SOSCircleRef circle, CFAllocatorRef allocator); +CFMutableSetRef SOSCircleCopyPeers(SOSCircleRef circle, CFAllocatorRef allocator); +bool SOSCircleAppendConcurringPeers(SOSCircleRef circle, CFMutableArrayRef appendHere, CFErrorRef *error); CFMutableArrayRef SOSCircleCopyConcurringPeers(SOSCircleRef circle, CFErrorRef* error); +SOSPeerInfoRef SOSCircleCopyPeerWithID(SOSCircleRef circle, CFStringRef peerid, CFErrorRef *error); int SOSCircleCountPeers(SOSCircleRef circle); int SOSCircleCountActivePeers(SOSCircleRef circle); @@ -86,6 +98,8 @@ bool SOSCircleHasPeerWithID(SOSCircleRef circle, CFStringRef peerid, CFErrorRef bool SOSCircleHasPeer(SOSCircleRef circle, SOSPeerInfoRef peerInfo, CFErrorRef *error); bool SOSCircleHasActivePeerWithID(SOSCircleRef circle, CFStringRef peerid, CFErrorRef *error); bool SOSCircleHasActivePeer(SOSCircleRef circle, SOSPeerInfoRef peerInfo, CFErrorRef *error); +bool SOSCircleHasActiveValidPeerWithID(SOSCircleRef circle, CFStringRef peerid, SecKeyRef user_public_key, CFErrorRef *error); +bool SOSCircleHasActiveValidPeer(SOSCircleRef circle, SOSPeerInfoRef peerInfo, SecKeyRef user_public_key, CFErrorRef *error); bool SOSCircleResetToOffering(SOSCircleRef circle, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error); bool SOSCircleResetToEmpty(SOSCircleRef circle, CFErrorRef *error); @@ -106,23 +120,12 @@ bool SOSCircleUpdatePeerInfo(SOSCircleRef circle, SOSPeerInfoRef replacement_pee bool SOSCircleRemovePeer(SOSCircleRef circle, SecKeyRef user_privkey, SOSFullPeerInfoRef device_approver, SOSPeerInfoRef peerInfo, CFErrorRef *error); -CFIndex SOSCircleRemoveRetired(SOSCircleRef circle, CFErrorRef *error); +bool SOSCircleRemoveRetired(SOSCircleRef circle, CFErrorRef *error); bool SOSCircleAcceptRequests(SOSCircleRef circle, SecKeyRef user_privkey, SOSFullPeerInfoRef device_approver, CFErrorRef *error); -SOSPeerInfoRef SOSCircleCopyPeerInfo(SOSCircleRef circle, CFStringRef peer_id, CFErrorRef *error); - // Stuff above this line is really SOSCircleInfo below the line is the active SOSCircle functionality -bool SOSCircleSyncWithPeer(SOSFullPeerInfoRef myRef, SOSCircleRef circle, - SOSDataSourceFactoryRef factory, - SOSPeerSendBlock sendBlock, CFStringRef peer_id, - CFErrorRef *error); - -bool SOSCircleHandlePeerMessage(SOSCircleRef circle, SOSFullPeerInfoRef myRef, SOSDataSourceFactoryRef factory, - SOSPeerSendBlock sendBlock, CFStringRef peer_id, - CFDataRef message, CFErrorRef *error); - SOSFullPeerInfoRef SOSCircleGetiCloudFullPeerInfoRef(SOSCircleRef circle); bool SOSCircleConcordanceSign(SOSCircleRef circle, SOSFullPeerInfoRef peerinfo, CFErrorRef *error); diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.c b/Security/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.c new file mode 100644 index 00000000..daf8adff --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.c @@ -0,0 +1,556 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +// +// SOSCloudCircle.m +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include + +#include +#define MINIMIZE_INCLUDES MINIMIZE_INCLUDES +#include +#include + +#include "SOSRegressionUtilities.h" + + +const char * kSOSCCCircleChangedNotification = "com.apple.security.secureobjectsync.circlechanged"; + +#define do_if_registered(sdp, ...) if (gSecurityd && gSecurityd->sdp) { return gSecurityd->sdp(__VA_ARGS__); } + +static bool xpc_dictionary_entry_is_type(xpc_object_t dictionary, const char *key, xpc_type_t type) +{ + xpc_object_t value = xpc_dictionary_get_value(dictionary, key); + + return value && (xpc_get_type(value) == type); +} + +SOSCCStatus SOSCCThisDeviceIsInCircle(CFErrorRef *error) +{ + static int counter = 0; + if(counter++ > 5) secerror("SOSCCThisDeviceIsInCircle!! %d\n", counter); + sec_trace_enter_api(NULL); + sec_trace_return_api(SOSCCStatus, ^{ + SOSCCStatus result = kSOSCCError; + + do_if_registered(soscc_ThisDeviceIsInCircle, error); + + xpc_object_t message = securityd_create_message(kSecXPCOpDeviceInCircle, error); + if (message) { + xpc_object_t response = securityd_message_with_reply_sync(message, error); + + if (response && xpc_dictionary_entry_is_type(response, kSecXPCKeyResult, XPC_TYPE_INT64)) { + result = (SOSCCStatus) xpc_dictionary_get_int64(response, kSecXPCKeyResult); + } else { + result = kSOSCCError; + } + + if (result < 0) { + if (response && securityd_message_no_error(response, error)) + { + char *desc = xpc_copy_description(response); + SecCFCreateErrorWithFormat(0, sSecXPCErrorDomain, NULL, error, NULL, CFSTR("Remote error occurred/no info: %s"), desc); + free((void *)desc); + } + } + if(response) + xpc_release(response); + if(message) + xpc_release(message); + } + + + return result; + }, CFSTR("SOSCCStatus=%d")) +} + +static CFStringRef simple_cfstring_error_request(enum SecXPCOperation op, CFErrorRef* error) +{ + __block CFStringRef result = NULL; + + secdebug("sosops","enter - operation: %d", op); + securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) { + const char *c_string = xpc_dictionary_get_string(response, kSecXPCKeyResult); + + if (c_string) { + result = CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8*)c_string, strlen(c_string), kCFStringEncodingUTF8, false); + } + + return c_string != NULL; + }); + return result; +} + +static bool simple_bool_error_request(enum SecXPCOperation op, CFErrorRef* error) +{ + __block bool result = false; + + secdebug("sosops","enter - operation: %d", op); + securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) { + result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); + return result; + }); + return result; +} + +static CFArrayRef simple_array_error_request(enum SecXPCOperation op, CFErrorRef* error) +{ + __block CFArrayRef result = false; + + 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); + result = _CFXPCCreateCFObjectFromXPCObject(temp_result); + return result != NULL; + }); + return result; +} + +static int simple_int_error_request(enum SecXPCOperation op, CFErrorRef* error) +{ + __block int result = 0; + + secdebug("sosops","enter - operation: %d", op); + securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) { + int64_t temp_result = xpc_dictionary_get_int64(response, kSecXPCKeyResult); + if ((temp_result >= INT32_MIN) && (temp_result <= INT32_MAX)) { + result = (int)temp_result; + } + return result; + }); + return result; +} + +static CFArrayRef array_of_info_error_request(enum SecXPCOperation op, CFErrorRef* error) +{ + __block CFArrayRef result = NULL; + + secdebug("sosops","enter - operation: %d", op); + securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) { + xpc_object_t encoded_array = xpc_dictionary_get_value(response, kSecXPCKeyResult); + if (response && (NULL != encoded_array)) { + result = CreateArrayOfPeerInfoWithXPCObject(encoded_array, error); + } + return result != NULL; + }); + + return result; +} + +static bool info_array_to_bool_error_request(enum SecXPCOperation op, CFArrayRef peer_infos, CFErrorRef* error) +{ + __block bool result = false; + + secdebug("sosops", "enter - operation: %d", op); + securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { + xpc_object_t encoded_peers = CreateXPCObjectWithArrayOfPeerInfo(peer_infos, error); + if (encoded_peers) + xpc_dictionary_set_value(message, kSecXPCKeyPeerInfos, encoded_peers); + return encoded_peers != NULL; + }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { + result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); + return result; + }); + return result; +} + +static bool uint64_t_to_bool_error_request(enum SecXPCOperation op, + uint64_t number, + CFErrorRef* error) +{ + __block bool result = false; + + securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { + xpc_dictionary_set_uint64(message, kSecXPCLimitInMinutes, number); + return true; + }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { + result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); + return result; + }); + + return result; +} + +bool SOSCCRequestToJoinCircle(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_RequestToJoinCircle, error); + + return simple_bool_error_request(kSecXPCOpRequestToJoin, error); + }, NULL) +} + +bool SOSCCRequestToJoinCircleAfterRestore(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_RequestToJoinCircleAfterRestore, error); + + return simple_bool_error_request(kSecXPCOpRequestToJoinAfterRestore, error); + }, NULL) +} + +bool SOSCCRequestEnsureFreshParameters(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_RequestEnsureFreshParameters, error); + + return simple_bool_error_request(kSecXPCOpRequestEnsureFreshParameters, error); + }, NULL) +} + +bool SOSCCResetToOffering(CFErrorRef* error) +{ + secwarning("SOSCCResetToOffering called"); + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_ResetToOffering, error); + + return simple_bool_error_request(kSecXPCOpResetToOffering, error); + }, NULL) +} + +bool SOSCCResetToEmpty(CFErrorRef* error) +{ + secwarning("SOSCCResetToEmpty called"); + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_ResetToEmpty, error); + + return simple_bool_error_request(kSecXPCOpResetToEmpty, error); + }, NULL) +} + +bool SOSCCRemoveThisDeviceFromCircle(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_RemoveThisDeviceFromCircle, error); + + return simple_bool_error_request(kSecXPCOpRemoveThisDeviceFromCircle, error); + }, NULL) +} + +bool SOSCCBailFromCircle_BestEffort(uint64_t limit_in_seconds, CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_BailFromCircle, limit_in_seconds, error); + + return uint64_t_to_bool_error_request(kSecXPCOpBailFromCircle, limit_in_seconds, error); + }, NULL) +} + +bool SOSCCSignedOut(bool immediate, CFErrorRef* error) +{ + uint64_t limit = strtoul(optarg, NULL, 10); + + if(immediate) + return SOSCCRemoveThisDeviceFromCircle(error); + else + return SOSCCBailFromCircle_BestEffort(limit, error); + +} + +CFArrayRef SOSCCCopyPeerPeerInfo(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_api(CFArrayRef, ^{ + do_if_registered(soscc_CopyPeerInfo, error); + + return array_of_info_error_request(kSecXPCOpCopyPeerPeerInfo, error); + }, CFSTR("return=%@")); +} + +CFArrayRef SOSCCCopyConcurringPeerPeerInfo(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_api(CFArrayRef, ^{ + do_if_registered(soscc_CopyConcurringPeerInfo, error); + + return array_of_info_error_request(kSecXPCOpCopyConcurringPeerPeerInfo, error); + }, CFSTR("return=%@")); +} + +CFArrayRef SOSCCCopyGenerationPeerInfo(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_api(CFArrayRef, ^{ + do_if_registered(soscc_CopyGenerationPeerInfo, error); + + return simple_array_error_request(kSecXPCOpCopyGenerationPeerInfo, error); + }, CFSTR("return=%@")); +} + +CFArrayRef SOSCCCopyApplicantPeerInfo(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_api(CFArrayRef, ^{ + do_if_registered(soscc_CopyApplicantPeerInfo, error); + + return array_of_info_error_request(kSecXPCOpCopyApplicantPeerInfo, error); + }, CFSTR("return=%@")); +} +bool SOSCCValidateUserPublic(CFErrorRef* error){ + sec_trace_enter_api(NULL); + sec_trace_return_api(bool, ^{ + do_if_registered(soscc_ValidateUserPublic, error); + + return simple_bool_error_request(kSecXPCOpValidateUserPublic, error); + }, NULL); +} + +CFArrayRef SOSCCCopyValidPeerPeerInfo(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_api(CFArrayRef, ^{ + do_if_registered(soscc_CopyValidPeerPeerInfo, error); + + return array_of_info_error_request(kSecXPCOpCopyValidPeerPeerInfo, error); + }, CFSTR("return=%@")); +} + +CFArrayRef SOSCCCopyNotValidPeerPeerInfo(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_api(CFArrayRef, ^{ + do_if_registered(soscc_CopyNotValidPeerPeerInfo, error); + + return array_of_info_error_request(kSecXPCOpCopyNotValidPeerPeerInfo, error); + }, CFSTR("return=%@")); +} + +CFArrayRef SOSCCCopyRetirementPeerInfo(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_api(CFArrayRef, ^{ + do_if_registered(soscc_CopyRetirementPeerInfo, error); + + return array_of_info_error_request(kSecXPCOpCopyRetirementPeerInfo, error); + }, CFSTR("return=%@")); +} + +bool SOSCCAcceptApplicants(CFArrayRef applicants, CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_AcceptApplicants, applicants, error); + + return info_array_to_bool_error_request(kSecXPCOpAcceptApplicants, applicants, error); + }, NULL) +} + +bool SOSCCRejectApplicants(CFArrayRef applicants, CFErrorRef *error) +{ + sec_trace_enter_api(CFSTR("applicants=%@"), applicants); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_RejectApplicants, applicants, error); + + return info_array_to_bool_error_request(kSecXPCOpRejectApplicants, applicants, error); + }, NULL) +} + +static bool label_and_password_to_bool_error_request(enum SecXPCOperation op, + CFStringRef user_label, CFDataRef user_password, + CFErrorRef* error) +{ + __block bool result = false; + + securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { + CFStringPerformWithCString(user_label, ^(const char *utf8Str) { + xpc_dictionary_set_string(message, kSecXPCKeyUserLabel, utf8Str); + }); + xpc_dictionary_set_data(message, kSecXPCKeyUserPassword, CFDataGetBytePtr(user_password), CFDataGetLength(user_password)); + return true; + }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { + result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); + return result; + }); + + return result; +} + +static bool deviceid_to_bool_error_request(enum SecXPCOperation op, + CFStringRef IDS, + CFErrorRef* error) +{ + __block bool result = false; + + securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { + CFStringPerformWithCString(IDS, ^(const char *utf8Str) { + xpc_dictionary_set_string(message, kSecXPCKeyDeviceID, utf8Str); + }); + return true; + }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { + result = xpc_dictionary_get_bool(response, kSecXPCKeyDeviceID); + return result; + }); + + return result; +} + +bool SOSCCRegisterUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error) +{ + secerror("SOSCCRegisterUserCredentials - calling SOSCCSetUserCredentials!! %@\n", user_label); + return SOSCCSetUserCredentials(user_label, user_password, error); +} + +bool SOSCCSetUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error) +{ + secerror("SOSCCSetUserCredentials!! %@\n", user_label); + sec_trace_enter_api(CFSTR("user_label=%@"), user_label); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_SetUserCredentials, user_label, user_password, error); + + return label_and_password_to_bool_error_request(kSecXPCOpSetUserCredentials, user_label, user_password, error); + }, NULL) +} +bool SOSCCSetDeviceID(CFStringRef IDS, CFErrorRef* error) +{ + secerror("SOSCCSetDeviceID!! %@\n", IDS); + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_SetDeviceID, IDS, error); + return deviceid_to_bool_error_request(kSecXPCOpSetDeviceID, IDS, error); + }, NULL) +} +bool SOSCCTryUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error) +{ + sec_trace_enter_api(CFSTR("user_label=%@"), user_label); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_TryUserCredentials, user_label, user_password, error); + + return label_and_password_to_bool_error_request(kSecXPCOpTryUserCredentials, user_label, user_password, error); + }, NULL) +} + + +bool SOSCCCanAuthenticate(CFErrorRef* error) { + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_CanAuthenticate, error); + + return simple_bool_error_request(kSecXPCOpCanAuthenticate, error); + }, NULL) +} + +bool SOSCCPurgeUserCredentials(CFErrorRef* error) { + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_PurgeUserCredentials, error); + + return simple_bool_error_request(kSecXPCOpPurgeUserCredentials, error); + }, NULL) +} + +enum DepartureReason SOSCCGetLastDepartureReason(CFErrorRef *error) { + sec_trace_enter_api(NULL); + sec_trace_return_api(enum DepartureReason, ^{ + do_if_registered(soscc_GetLastDepartureReason, error); + + return (enum DepartureReason) simple_int_error_request(kSecXPCOpGetLastDepartureReason, error); + }, NULL) +} + +CFStringRef SOSCCCopyIncompatibilityInfo(CFErrorRef* error) { + sec_trace_enter_api(NULL); + sec_trace_return_api(CFStringRef, ^{ + do_if_registered(soscc_CopyIncompatibilityInfo, error); + + return simple_cfstring_error_request(kSecXPCOpCopyIncompatibilityInfo, error); + }, NULL) +} + +CFStringRef SOSCCRequestDeviceID(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_api(CFStringRef, ^{ + do_if_registered(soscc_RequestDeviceID, error); + CFStringRef deviceID = simple_cfstring_error_request(kSecXPCOpRequestDeviceID, error); + return deviceID; + }, NULL) +} + +bool SOSCCProcessEnsurePeerRegistration(CFErrorRef* error){ + secnotice("updates", "enter SOSCCProcessEnsurePeerRegistration"); + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_EnsurePeerRegistration, error); + + return simple_bool_error_request(soscc_EnsurePeerRegistration_id, error); + }, NULL) +} + + +SyncWithAllPeersReason SOSCCProcessSyncWithAllPeers(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_api(SyncWithAllPeersReason, ^{ + do_if_registered(soscc_ProcessSyncWithAllPeers, error); + + return (SyncWithAllPeersReason) simple_int_error_request(kSecXPCOpProcessSyncWithAllPeers, error); + }, NULL) +} + +CFStringRef SOSCCGetStatusDescription(SOSCCStatus status) +{ + switch (status) { + case kSOSCCInCircle: + return CFSTR("InCircle"); + case kSOSCCNotInCircle: + return CFSTR("NotInCircle"); + case kSOSCCRequestPending: + return CFSTR("RequestPending"); + case kSOSCCCircleAbsent: + return CFSTR("CircleAbsent"); + case kSOSCCError: + return CFSTR("InternalError"); + default: + return CFSTR("Unknown Status (%d)"); + }; +} diff --git a/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.h b/Security/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.h similarity index 78% rename from sec/SOSCircle/SecureObjectSync/SOSCloudCircle.h rename to Security/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.h index 32457bfa..5b666e36 100644 --- a/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.h +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -64,10 +64,6 @@ enum { kSOSCCRequestPending = 2, kSOSCCCircleAbsent = 3, kSOSCCError = -1, - -// Never being used, were a bad idea, have clients leaving here deprecated. - kSOSCCParamErr __attribute__((deprecated)) = -2, - kSOSCCMemoryErr __attribute__((deprecated)) = -3 }; typedef int SOSCCStatus; @@ -102,6 +98,20 @@ bool SOSCCSetUserCredentials(CFStringRef user_label, CFDataRef user_password, CF bool SOSCCTryUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error); +/*! + @function SOSCCRequestDeviceID + @abstract Retrieves this device's IDS device ID + @param error What went wrong if we returned false + */ +CFStringRef SOSCCRequestDeviceID(CFErrorRef* error); + +/*! + @function SOSCCSetDeviceID + @abstract Sets this device's IDS device ID + @param IDS The ID to set + @param error What went wrong if we returned false + */ +bool SOSCCSetDeviceID(CFStringRef IDS, CFErrorRef* error); /*! @function SOSCCRegisterUserCredentials @@ -144,6 +154,14 @@ bool SOSCCRequestToJoinCircle(CFErrorRef* error); */ bool SOSCCRequestToJoinCircleAfterRestore(CFErrorRef* error); +/*! + @function SOSCCRequestEnsureFreshParameters + @abstract function to help debug problems with EnsureFreshParameters + @param error What went wrong if we tried to refresh parameters + @result true if we successfully retrieved fresh parameters. False if we failed. +*/ +bool SOSCCRequestEnsureFreshParameters(CFErrorRef* error); + /*! @function SOSCCResetToOffering @abstract Resets the cloud to offer this device's circle. @@ -181,6 +199,18 @@ bool SOSCCRemoveThisDeviceFromCircle(CFErrorRef* error); */ bool SOSCCBailFromCircle_BestEffort(uint64_t limit_in_seconds, CFErrorRef* error); +/*! + @function SOSCCSignedOut + @abstract Attempts to publish a retirement ticket for the current device. + @param immediate If we should remove the device immediately or to leave the circle with best effort. + @param error What went wrong trying to remove ourselves. + @result true if we posted the ticket. False if there was an error. + @discussion This attempts to post a retirement ticket that should + result in other devices removing this device from the circle. It does so + with a 5 second timeout or immediately. + */ +bool SOSCCSignedOut(bool immediate, CFErrorRef* error); + /*! @function SOSCCCopyApplicantPeerInfo @abstract Get the list of peers wishing admittance. @@ -189,6 +219,46 @@ bool SOSCCBailFromCircle_BestEffort(uint64_t limit_in_seconds, CFErrorRef* error */ CFArrayRef SOSCCCopyApplicantPeerInfo(CFErrorRef* error); +/*! + @function SOSCCCopyGenerationPeerInfo + @abstract Get the list of generation count per circle. + @param error What went wrong. + @result Array of Circle generation counts. + */ +CFArrayRef SOSCCCopyGenerationPeerInfo(CFErrorRef* error); + +/*! + @function SOSCCCopyValidPeerPeerInfo + @abstract Get the list of valid peers. + @param error What went wrong. + @result Array of PeerInfos for applying valid peers. + */ +CFArrayRef SOSCCCopyValidPeerPeerInfo(CFErrorRef* error); + +/*! + @function SOSCCValidateUserPublic + @abstract Validate whether the account's user public key is trustworthy. + @param error What went wrong. + @result true if the user public key is trusted, false if not. + */ +bool SOSCCValidateUserPublic(CFErrorRef *error); + +/*! + @function SOSCCCopyNotValidPeerPeerInfo + @abstract Get the list of not valid peers. + @param error What went wrong. + @result Array of PeerInfos for non-valid peers. + */ +CFArrayRef SOSCCCopyNotValidPeerPeerInfo(CFErrorRef* error); + +/*! + @function SOSCCCopyRetirementPeerInfo + @abstract Get the list of retired peers. + @param error What went wrong. + @result Array of PeerInfos for retired peers. + */ +CFArrayRef SOSCCCopyRetirementPeerInfo(CFErrorRef* error); + /*! @function SOSCCAcceptApplicants @abstract Accepts the applicants into the circle (requires that we recently had the user enter the credentials). diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSCloudCircleInternal.h b/Security/sec/SOSCircle/SecureObjectSync/SOSCloudCircleInternal.h new file mode 100644 index 00000000..e39539c0 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSCloudCircleInternal.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef _SECURITY_SOSCLOUDCIRCLEINTERNAL_H_ +#define _SECURITY_SOSCLOUDCIRCLEINTERNAL_H_ + +#include +#include +#include + +__BEGIN_DECLS + +CFArrayRef SOSCCCopyConcurringPeerPeerInfo(CFErrorRef* error); + +bool SOSCCPurgeUserCredentials(CFErrorRef* error); + +CFStringRef SOSCCGetStatusDescription(SOSCCStatus status); +SecKeyRef SOSCCGetUserPrivKey(CFErrorRef *error); +SecKeyRef SOSCCGetUserPubKey(CFErrorRef *error); + +/*! + @function SOSCCProcessSyncWithAllPeers + @abstract Returns the information (string, hopefully URL) that will lead to an explanation of why you have an incompatible circle. + @param error What went wrong if we returned NULL. + */ + +SyncWithAllPeersReason SOSCCProcessSyncWithAllPeers(CFErrorRef* error); + +bool SOSCCProcessEnsurePeerRegistration(CFErrorRef* error); + +__END_DECLS + +#endif diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSCoder.c b/Security/sec/SOSCircle/SecureObjectSync/SOSCoder.c new file mode 100644 index 00000000..bbd2d33b --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSCoder.c @@ -0,0 +1,552 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "AssertMacros.h" + +struct __OpaqueSOSCoder { + CFStringRef peer_id; + SecOTRSessionRef sessRef; + bool waitingForDataPacket; + CFDataRef pendingResponse; +}; + +static const char *SOSCoderString(SOSCoderStatus coderStatus) { + switch (coderStatus) { + case kSOSCoderDataReturned: return "DataReturned"; + case kSOSCoderNegotiating: return "Negotiating"; + case kSOSCoderNegotiationCompleted: return "NegotiationCompleted"; + case kSOSCoderFailure: return "Failure"; + case kSOSCoderStaleEvent: return "StaleEvent"; + default: return "StatusUnknown"; + } +} + +/* + static void logRawCoderMessage(const uint8_t* der, uint8_t* der_end, bool encoding) +{ +#ifndef NDEBUG + CFStringRef hexMessage = NULL; + if (der && der_end) { + CFIndex length = der_end - der; + CFDataRef message = CFDataCreate(kCFAllocatorDefault, der, length); + hexMessage = CFDataCopyHexString(message); + secnoticeq("coder", "%s RAW [%ld] %@", encoding ? "encode" : "decode", length, hexMessage); + CFReleaseSafe(message); + } + CFReleaseSafe(hexMessage); +#endif +} +*/ + +static size_t der_sizeof_bool(bool value) { + return ccder_sizeof(CCDER_BOOLEAN, 1); +} + +static uint8_t* der_encode_bool(bool value, const uint8_t *der, uint8_t *der_end) { + uint8_t valueByte = value; + return ccder_encode_tl(CCDER_BOOLEAN, 1, der, + ccder_encode_body(1, &valueByte, der, der_end)); +} + +static const uint8_t* der_decode_bool(bool *value, const uint8_t *der, const uint8_t *der_end) { + size_t payload_size = 0; + + der = ccder_decode_tl(CCDER_BOOLEAN, &payload_size, der, der_end); + + if (payload_size != 1) { + der = NULL; + } + + if (der != NULL) { + *value = (*der != 0); + der++; + } + + return der; +} + +static CFMutableDataRef sessSerialized(SOSCoderRef coder, CFErrorRef *error) { + CFMutableDataRef otr_state = NULL; + + if(!coder || !coder->sessRef) { + SOSCreateErrorWithFormat(kSOSErrorUnexpectedType, NULL, error, 0, CFSTR("No session reference.")); + return NULL; + } + + if ((otr_state = CFDataCreateMutable(NULL, 0)) == NULL) { + SOSCreateErrorWithFormat(kSOSErrorAllocationFailure, NULL, error, 0, CFSTR("Mutable Data allocation failed.")); + return NULL; + } + + if (errSecSuccess != SecOTRSAppendSerialization(coder->sessRef, otr_state)) { + SOSCreateErrorWithFormat(kSOSErrorEncodeFailure, NULL, error, 0, CFSTR("Append Serialization failed.")); + CFReleaseSafe(otr_state); + return NULL; + } + + return otr_state; + +} + +static size_t der_sizeof_optional_data(CFDataRef data) { + return data ? der_sizeof_data(data, NULL) : 0; +} + +static uint8_t* der_encode_optional_data(CFDataRef data, CFErrorRef *error, const uint8_t* der, uint8_t* der_end) { + return data ? der_encode_data(data, error, der, der_end) : der_end; +} + + + +static size_t SOSCoderGetDEREncodedSize(SOSCoderRef coder, CFErrorRef *error) { + size_t encoded_size = 0; + CFMutableDataRef otr_state = sessSerialized(coder, error); + + if (otr_state) { + size_t data_size = der_sizeof_data(otr_state, error); + size_t waiting_size = der_sizeof_bool(coder->waitingForDataPacket); + size_t pending_size = der_sizeof_optional_data(coder->pendingResponse); + + if ((data_size != 0) && (waiting_size != 0)) + { + encoded_size = ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, data_size + waiting_size + pending_size); + } + CFReleaseSafe(otr_state); + } + return encoded_size; +} + + +static uint8_t* SOSCoderEncodeToDER(SOSCoderRef coder, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) { + if(!der_end) return NULL; + uint8_t* result = NULL; + CFMutableDataRef otr_state = sessSerialized(coder, error); + + if(otr_state) { + result = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + der_encode_data(otr_state, error, der, + der_encode_bool(coder->waitingForDataPacket, der, + der_encode_optional_data(coder->pendingResponse, error, der, der_end)))); + CFReleaseSafe(otr_state); + } + return result; +} + + +CFDataRef SOSCoderCopyDER(SOSCoderRef coder, CFErrorRef* error) { + CFMutableDataRef encoded = NULL; + size_t encoded_size = SOSCoderGetDEREncodedSize(coder, error); + + if (encoded_size > 0) { + encoded = CFDataCreateMutable(NULL, encoded_size); + if (encoded) { + CFDataSetLength(encoded, encoded_size); + uint8_t * der = CFDataGetMutableBytePtr(encoded); + uint8_t * der_end = der + encoded_size; + if (!SOSCoderEncodeToDER(coder, error, der, der_end)) { + CFReleaseNull(encoded); + encoded = NULL; + } + } + } + return encoded; +} + +SOSCoderRef SOSCoderCreateFromData(CFDataRef exportedData, CFErrorRef *error) { + + SOSCoderRef p = calloc(1, sizeof(struct __OpaqueSOSCoder)); + + const uint8_t *der = CFDataGetBytePtr(exportedData); + const uint8_t *der_end = der + CFDataGetLength(exportedData); + + CFDataRef otr_data = NULL; + + ccder_tag tag; + require(ccder_decode_tag(&tag, der, der_end),fail); + + switch (tag) { + case CCDER_OCTET_STRING: // TODO: this code is safe to delete? + { + der = der_decode_data(kCFAllocatorDefault, 0, &otr_data, error, der, der_end); + p->waitingForDataPacket = false; + } + break; + + case CCDER_CONSTRUCTED_SEQUENCE: + { + const uint8_t *sequence_end = NULL; + der = ccder_decode_sequence_tl(&sequence_end, der, der_end); + + require_action_quiet(sequence_end == der_end, fail, SecCFDERCreateError(kSOSErrorDecodeFailure, CFSTR("Extra data in SOS coder"), NULL, error)); + + der = der_decode_data(kCFAllocatorDefault, 0, &otr_data, error, der, sequence_end); + der = der_decode_bool(&p->waitingForDataPacket, der, sequence_end); + if (der != sequence_end) { // optionally a pending response + der = der_decode_data(kCFAllocatorDefault, 0, &p->pendingResponse, error, der, sequence_end); + } + } + break; + + default: + SecCFDERCreateError(kSOSErrorDecodeFailure, CFSTR("Unsupported SOS Coder DER"), NULL, error); + goto fail; + } + + require(der, fail); + + p->sessRef = SecOTRSessionCreateFromData(NULL, otr_data); + require(p->sessRef, fail); + + CFReleaseSafe(otr_data); + return p; + +fail: + SOSCoderDispose(p); + CFReleaseSafe(otr_data); + return NULL; +} + + +SOSCoderRef SOSCoderCreate(SOSPeerInfoRef peerInfo, SOSFullPeerInfoRef myPeerInfo, CFErrorRef *error) { + CFAllocatorRef allocator = CFGetAllocator(peerInfo); + + SOSCoderRef coder = calloc(1, sizeof(struct __OpaqueSOSCoder)); + CFErrorRef localError = NULL; + + SecOTRFullIdentityRef myRef = NULL; + SecOTRPublicIdentityRef peerRef = NULL; + SecKeyRef privateKey = NULL; + SecKeyRef publicKey = NULL; + + if (myPeerInfo && peerInfo) { + privateKey = SOSFullPeerInfoCopyDeviceKey(myPeerInfo, &localError); + require_quiet(privateKey, errOut); + + myRef = SecOTRFullIdentityCreateFromSecKeyRef(allocator, privateKey, &localError); + require_quiet(myRef, errOut); + + CFReleaseNull(privateKey); + + publicKey = SOSPeerInfoCopyPubKey(peerInfo); + + peerRef = SecOTRPublicIdentityCreateFromSecKeyRef(allocator, publicKey, &localError); + require_quiet(peerRef, errOut); + + coder->sessRef = SecOTRSessionCreateFromID(allocator, myRef, peerRef); + + require(coder->sessRef, errOut); + + coder->waitingForDataPacket = false; + coder->pendingResponse = NULL; + + CFReleaseNull(publicKey); + CFReleaseNull(privateKey); + CFReleaseNull(myRef); + CFReleaseNull(peerRef); + } else { + secnotice("coder", "NULL Coder requested, no transport security"); + } + + SOSCoderStart(coder, NULL); + + return coder; + +errOut: + secerror("Coder create failed: %@\n", localError ? localError : (CFTypeRef)CFSTR("No local error in SOSCoderCreate")); + secerror("Coder create failed: %@\n", error ? *error : (CFTypeRef)CFSTR("WTF NULL?")); + CFReleaseNull(myRef); + CFReleaseNull(peerRef); + CFReleaseNull(publicKey); + CFReleaseNull(privateKey); + + free(coder); + return NULL; +} + +void SOSCoderDispose(SOSCoderRef coder) +{ + if (coder) { + CFReleaseNull(coder->sessRef); + CFReleaseNull(coder->pendingResponse); + CFReleaseNull(coder->peer_id); + free(coder); + } + coder = NULL; +} + +void SOSCoderReset(SOSCoderRef coder) +{ + SecOTRSessionReset(coder->sessRef); + coder->waitingForDataPacket = false; + CFReleaseNull(coder->pendingResponse); +} + +CFDataRef SOSCoderCopyPendingResponse(SOSCoderRef coder) +{ + return CFRetainSafe(coder->pendingResponse); +} + +void SOSCoderConsumeResponse(SOSCoderRef coder) +{ + CFReleaseNull(coder->pendingResponse); +} + +static bool SOSOTRSAppendStartPacket(SecOTRSessionRef session, CFMutableDataRef appendPacket, CFErrorRef *error) { + OSStatus otrStatus = SecOTRSAppendStartPacket(session, appendPacket); + if (otrStatus != errSecSuccess) { + SOSCreateErrorWithFormat(kSOSErrorEncodeFailure, (error != NULL) ? *error : NULL, error, NULL, CFSTR("append start packet returned: %" PRIdOSStatus), otrStatus); + } + return otrStatus == errSecSuccess; +} + +// Start OTR negotiation if we haven't already done so. +SOSCoderStatus +SOSCoderStart(SOSCoderRef coder, CFErrorRef *error) { + CFMutableStringRef action = CFStringCreateMutable(kCFAllocatorDefault, 0); + CFStringRef beginState = NULL; + SOSCoderStatus result = kSOSCoderFailure; + CFMutableDataRef startPacket = NULL; + + require_action_quiet(coder->sessRef, coderFailure, CFStringAppend(action, CFSTR("*** no otr session ***"))); + beginState = CFCopyDescription(coder->sessRef); + require_action_quiet(!coder->waitingForDataPacket, negotiatingOut, CFStringAppend(action, CFSTR("waiting for peer to send first data packet"))); + require_action_quiet(!SecOTRSGetIsReadyForMessages(coder->sessRef), coderFailure, CFStringAppend(action, CFSTR("otr session ready")); + result = kSOSCoderDataReturned); + require_action_quiet(SecOTRSGetIsIdle(coder->sessRef), negotiatingOut, CFStringAppend(action, CFSTR("otr negotiating already"))); + require_action_quiet(startPacket = CFDataCreateMutable(kCFAllocatorDefault, 0), coderFailure, SOSCreateError(kSOSErrorAllocationFailure, CFSTR("alloc failed"), NULL, error)); + require_quiet(SOSOTRSAppendStartPacket(coder->sessRef, startPacket, error), coderFailure); + CFRetainAssign(coder->pendingResponse, startPacket); + +negotiatingOut: + result = kSOSCoderNegotiating; +coderFailure: + // Uber state log + if (result == kSOSCoderFailure && error && *error) + CFStringAppendFormat(action, NULL, CFSTR(" %@"), *error); + secnotice("coder", "%@ %s %@ %@ returned %s", beginState, + SecOTRPacketTypeString(startPacket), action, coder->sessRef, SOSCoderString(result)); + CFReleaseNull(startPacket); + CFReleaseSafe(beginState); + CFRelease(action); + + return result; + +} + +SOSCoderStatus +SOSCoderResendDH(SOSCoderRef coder, CFErrorRef *error) { + if(coder->sessRef == NULL) return kSOSCoderDataReturned; + CFMutableDataRef startPacket = CFDataCreateMutable(kCFAllocatorDefault, 0); + SOSCoderStatus result = kSOSCoderFailure; + require_noerr_quiet(SecOTRSAppendRestartPacket(coder->sessRef, startPacket), exit); + secnotice("coder", "Resending OTR Start %@", startPacket); + CFRetainAssign(coder->pendingResponse, startPacket); + result = kSOSCoderNegotiating; +exit: + CFReleaseNull(startPacket); + return result; +} + + +static SOSCoderStatus nullCoder(CFDataRef from, CFMutableDataRef *to) { + *to = CFDataCreateMutableCopy(NULL, CFDataGetLength(from), from); + return kSOSCoderDataReturned; +} + +SOSCoderStatus SOSCoderUnwrap(SOSCoderRef coder, CFDataRef codedMessage, CFMutableDataRef *message, + CFStringRef clientId, CFErrorRef *error) { + if(codedMessage == NULL) return kSOSCoderDataReturned; + if(coder->sessRef == NULL) return nullCoder(codedMessage, message); + CFMutableStringRef action = CFStringCreateMutable(kCFAllocatorDefault, 0); + /* This should be the "normal" case. We just use OTR to unwrap the received message. */ + SOSCoderStatus result = kSOSCoderFailure; + + CFStringRef beginState = CFCopyDescription(coder->sessRef); + enum SecOTRSMessageKind kind = SecOTRSGetMessageKind(coder->sessRef, codedMessage); + + switch (kind) { + case kOTRNegotiationPacket: { + /* If we're in here we haven't completed negotiating a session. Use SecOTRSProcessPacket() to go through + the negotiation steps and immediately send a reply back if necessary using the sendBlock. This + assumes the sendBlock is still available. + */ + CFMutableDataRef response = CFDataCreateMutable(kCFAllocatorDefault, 0); + OSStatus ppstatus = errSecSuccess; + if (response) { + switch (ppstatus = SecOTRSProcessPacket(coder->sessRef, codedMessage, response)) { + case errSecSuccess: + if (CFDataGetLength(response) > 1) { + CFStringAppendFormat(action, NULL, CFSTR("Sending OTR Response %s"), SecOTRPacketTypeString(response)); + CFRetainAssign(coder->pendingResponse, response); + result = kSOSCoderNegotiating; + if (SecOTRSGetIsReadyForMessages(coder->sessRef)) { + CFStringAppend(action, CFSTR(" begin waiting for data packet")); + coder->waitingForDataPacket = true; + } + } else if(!SecOTRSGetIsReadyForMessages(coder->sessRef)) { + CFStringAppend(action, CFSTR("stuck?")); + result = kSOSCoderNegotiating; + } else { + CFStringAppend(action, CFSTR("completed negotiation")); + result = kSOSCoderNegotiationCompleted; + coder->waitingForDataPacket = false; + } + break; + case errSecDecode: + CFStringAppend(action, CFSTR("resending dh")); + result = SOSCoderResendDH(coder, error); + break; + default: + SOSCreateErrorWithFormat(kSOSErrorEncodeFailure, (error != NULL) ? *error : NULL, error, NULL, CFSTR("%@ Cannot negotiate session (%ld)"), clientId, (long)ppstatus); + result = kSOSCoderFailure; + break; + }; + } else { + SOSCreateErrorWithFormat(kSOSErrorAllocationFailure, (error != NULL) ? *error : NULL, error, NULL, CFSTR("%@ Cannot allocate CFData"), clientId); + result = kSOSCoderFailure; + } + + CFReleaseNull(response); + + break; + } + + case kOTRDataPacket: + if(!SecOTRSGetIsReadyForMessages(coder->sessRef)) { + CFStringAppend(action, CFSTR("not ready, resending DH packet")); + SetCloudKeychainTraceValueForKey(kCloudKeychainNumberOfTimesSyncFailed, 1); + CFStringAppend(action, CFSTR("not ready for data; resending dh")); + result = SOSCoderResendDH(coder, error); + } else { + if (coder->waitingForDataPacket) { + CFStringAppend(action, CFSTR("got data packet we were waiting for ")); + coder->waitingForDataPacket = false; + } + CFMutableDataRef exposed = CFDataCreateMutable(0, 0); + OSStatus otrResult = SecOTRSVerifyAndExposeMessage(coder->sessRef, codedMessage, exposed); + CFStringAppend(action, CFSTR("verify and expose message")); + if (otrResult) { + if (otrResult == errSecOTRTooOld) { + CFStringAppend(action, CFSTR(" too old")); + result = kSOSCoderStaleEvent; + } else { + SecError(otrResult, error, CFSTR("%@ Cannot expose message: %" PRIdOSStatus), clientId, otrResult); + secerror("%@ Decode OTR Protected Packet: %@", clientId, error ? *error : NULL); + result = kSOSCoderFailure; + } + } else { + CFStringAppend(action, CFSTR("decoded OTR protected packet")); + *message = exposed; + exposed = NULL; + result = kSOSCoderDataReturned; + } + CFReleaseNull(exposed); + } + break; + + default: + secerror("%@ Unknown packet type: %@", clientId, codedMessage); + SOSCreateError(kSOSErrorDecodeFailure, CFSTR("Unknown packet type"), (error != NULL) ? *error : NULL, error); + result = kSOSCoderFailure; + break; + }; + + // Uber state log + if (result == kSOSCoderFailure && error && *error) + CFStringAppendFormat(action, NULL, CFSTR(" %@"), *error); + secnotice("coder", "%@ %@ %s %@ %@ returned %s", clientId, beginState, + SecOTRPacketTypeString(codedMessage), action, coder->sessRef, SOSCoderString(result)); + CFReleaseSafe(beginState); + CFRelease(action); + + return result; +} + + +SOSCoderStatus SOSCoderWrap(SOSCoderRef coder, CFDataRef message, CFMutableDataRef *codedMessage, CFStringRef clientId, CFErrorRef *error) { + CFMutableStringRef action = CFStringCreateMutable(kCFAllocatorDefault, 0); + SOSCoderStatus result = kSOSCoderDataReturned; + CFStringRef beginState = NULL; + CFMutableDataRef encoded = NULL; + OSStatus otrStatus = 0; + + require_action_quiet(coder->sessRef, errOut, + CFStringAppend(action, CFSTR("*** using null coder ***")); + result = nullCoder(message, codedMessage)); + beginState = CFCopyDescription(coder->sessRef); + require_action_quiet(SecOTRSGetIsReadyForMessages(coder->sessRef), errOut, + CFStringAppend(action, CFSTR("not ready")); + result = kSOSCoderNegotiating); + require_action_quiet(!coder->waitingForDataPacket, errOut, + CFStringAppend(action, CFSTR("waiting for peer to send data packet first")); + result = kSOSCoderNegotiating); + require_action_quiet(encoded = CFDataCreateMutable(kCFAllocatorDefault, 0), errOut, + SOSCreateErrorWithFormat(kSOSErrorAllocationFailure, NULL, error, NULL, CFSTR("%@ alloc failed"), clientId); + result = kSOSCoderFailure); + require_noerr_action_quiet(otrStatus = SecOTRSSignAndProtectMessage(coder->sessRef, message, encoded), errOut, + SOSCreateErrorWithFormat(kSOSErrorEncodeFailure, (error != NULL) ? *error : NULL, error, NULL, CFSTR("%@ cannot protect message: %" PRIdOSStatus), clientId, otrStatus); + CFReleaseNull(encoded); + result = kSOSCoderFailure); + *codedMessage = encoded; + +errOut: + // Uber state log + if (result == kSOSCoderFailure && error && *error) + CFStringAppendFormat(action, NULL, CFSTR(" %@"), *error); + secnotice("coder", "%@ %@ %s %@ %@ returned %s", clientId, beginState, + SecOTRPacketTypeString(encoded), action, coder->sessRef, SOSCoderString(result)); + CFReleaseSafe(beginState); + CFRelease(action); + + return result; +} + +bool SOSCoderCanWrap(SOSCoderRef coder) { + return coder->sessRef && SecOTRSGetIsReadyForMessages(coder->sessRef) && !coder->waitingForDataPacket; +} diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSCoder.h b/Security/sec/SOSCircle/SecureObjectSync/SOSCoder.h new file mode 100644 index 00000000..b39378e9 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSCoder.h @@ -0,0 +1,72 @@ +/* + * 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@ + */ + + +#ifndef _SEC_SOSCODER_H_ +#define _SEC_SOSCODER_H_ + + +#include +#include + +typedef struct __OpaqueSOSCoder *SOSCoderRef; +typedef bool (^SOSPeerSendBlock)(CFDataRef message, CFErrorRef *error); + +enum { + kSOSCoderDataReturned = 0, + kSOSCoderNegotiating = 1, + kSOSCoderNegotiationCompleted = 2, + kSOSCoderFailure = 3, + kSOSCoderStaleEvent = 4, +}; +typedef uint32_t SOSCoderStatus; + +SOSCoderRef SOSCoderCreate(SOSPeerInfoRef peerInfo, SOSFullPeerInfoRef myPeerInfo, CFErrorRef *error); +SOSCoderRef SOSCoderCreateFromData(CFDataRef exportedData, CFErrorRef *error); + +void SOSCoderDispose(SOSCoderRef coder); + +CFDataRef SOSCoderCopyDER(SOSCoderRef coder, CFErrorRef* error); + +SOSCoderStatus +SOSCoderStart(SOSCoderRef coder, CFErrorRef *error); + +SOSCoderStatus +SOSCoderResendDH(SOSCoderRef coder, CFErrorRef *error); + +void SOSCoderPersistState(CFStringRef peer_id, SOSCoderRef coder); + +SOSCoderStatus SOSCoderUnwrap(SOSCoderRef coder, CFDataRef codedMessage, CFMutableDataRef *message, + CFStringRef clientId, CFErrorRef *error); + +SOSCoderStatus SOSCoderWrap(SOSCoderRef coder, CFDataRef message, CFMutableDataRef *codedMessage, CFStringRef clientId, CFErrorRef *error); + +bool SOSCoderCanWrap(SOSCoderRef coder); + +void SOSCoderReset(SOSCoderRef coder); + +CFDataRef SOSCoderCopyPendingResponse(SOSCoderRef coder); +void SOSCoderConsumeResponse(SOSCoderRef coder); + + +#endif // _SEC_SOSCODER_H_ diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSDataSource.h b/Security/sec/SOSCircle/SecureObjectSync/SOSDataSource.h new file mode 100644 index 00000000..a23a1389 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSDataSource.h @@ -0,0 +1,228 @@ +/* + * 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@ + */ + + +/*! + @header SOSDataSource.h + The functions provided in SOSDataSource.h provide the protocol to a + secure object syncing data source. This is something than can produce + manifests and manifest digests and query objects by digest and merge + objects into the data source. + */ + +#ifndef _SEC_SOSDATASOURCE_H_ +#define _SEC_SOSDATASOURCE_H_ + +#include +#include + +__BEGIN_DECLS + +/* SOSDataSource protocol (non opaque). */ +typedef struct SOSDataSourceFactory *SOSDataSourceFactoryRef; +typedef struct SOSDataSource *SOSDataSourceRef; +typedef struct __OpaqueSOSEngine *SOSEngineRef; +typedef struct __OpaqueSOSObject *SOSObjectRef; +typedef struct __OpaqueSOSTransaction *SOSTransactionRef; + +// +// MARK: - SOSDataSourceFactory protocol +// +struct SOSDataSourceFactory { + CFArrayRef (*copy_names)(SOSDataSourceFactoryRef factory); + SOSDataSourceRef (*create_datasource)(SOSDataSourceFactoryRef factory, CFStringRef dataSourceName, CFErrorRef *error); + void (*release)(SOSDataSourceFactoryRef factory); +}; + +// +// MARK: - SOSDataSource protocol +// + +/* Implement this if you want to create a new type of sync client. + Currently we support keychains, but the engine should scale to + entire filesystems. */ +enum SOSMergeResult { + kSOSMergeFailure = 0, // CFErrorRef returned, no error returned in any other case + kSOSMergeLocalObject, // We choose the current object in the dataSource the manifest is still valid. + kSOSMergePeersObject, // We chose the peers object over our own, manifest is now dirty. + kSOSMergeCreatedObject, // *createdObject is returned and should be released +}; +typedef CFIndex SOSMergeResult; + +// +// MARK: - SOSDataSource struct +// + +// +// MARK: SOSDataSourceTransactionType +// +enum SOSDataSourceTransactionType { + kSOSDataSourceNoneTransactionType = 0, + kSOSDataSourceImmediateTransactionType, + kSOSDataSourceExclusiveTransactionType, + kSOSDataSourceNormalTransactionType, + kSOSDataSourceExclusiveRemoteTransactionType, +}; +typedef CFOptionFlags SOSDataSourceTransactionType; + +enum SOSDataSourceTransactionPhase { + kSOSDataSourceTransactionDidRollback = 0, // A transaction just got rolled back + kSOSDataSourceTransactionWillCommit, // A transaction is about to commit. + kSOSDataSourceTransactionDidCommit, // A transnaction sucessfully committed. +}; +typedef CFOptionFlags SOSDataSourceTransactionPhase; + +enum SOSDataSourceTransactionSource { + kSOSDataSourceSOSTransaction, // A remotely initated transaction. + kSOSDataSourceAPITransaction, // A user initated transaction. +}; +typedef CFOptionFlags SOSDataSourceTransactionSource; + +typedef void (^SOSDataSourceNotifyBlock)(SOSDataSourceRef ds, SOSTransactionRef txn, SOSDataSourceTransactionPhase phase, SOSDataSourceTransactionSource source, struct SOSDigestVector *removals, struct SOSDigestVector *additions); + +struct SOSDataSource { + // SOSEngine - every datasource has an engine that is notified of changes + // to the datasource. + SOSEngineRef engine; + + // General SOSDataSource methods + CFStringRef (*dsGetName)(SOSDataSourceRef ds); + void (*dsSetNotifyPhaseBlock)(SOSDataSourceRef ds, SOSDataSourceNotifyBlock notifyBlock); + SOSManifestRef (*dsCopyManifest)(SOSDataSourceRef ds, CFErrorRef *error); + bool (*dsForEachObject)(SOSDataSourceRef ds, SOSManifestRef manifest, CFErrorRef *error, void (^handleObject)(CFDataRef key, SOSObjectRef object, bool *stop)); + CFDataRef (*dsCopyStateWithKey)(SOSDataSourceRef ds, CFStringRef key, CFStringRef pdmn, CFErrorRef *error); + bool (*dsWith)(SOSDataSourceRef ds, CFErrorRef *error, SOSDataSourceTransactionSource source, void(^transaction)(SOSTransactionRef txn, bool *commit)); + bool (*dsRelease)(SOSDataSourceRef ds, CFErrorRef *error); // Destructor + + // SOSTransaction methods, writes to a dataSource require a transaction. + SOSMergeResult (*dsMergeObject)(SOSTransactionRef txn, SOSObjectRef object, SOSObjectRef *createdObject, CFErrorRef *error); + bool (*dsSetStateWithKey)(SOSDataSourceRef ds, SOSTransactionRef txn, CFStringRef pdmn, CFStringRef key, CFDataRef state, CFErrorRef *error); + bool (*dsRestoreObject)(SOSTransactionRef txn, uint64_t handle, CFDictionaryRef item, CFErrorRef *error); + + // 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); +}; + +// +// MARK: - SOSDataSource protocol implementation +// +static inline SOSEngineRef SOSDataSourceGetSharedEngine(SOSDataSourceRef ds, CFErrorRef *error) { + return ds->engine; +} + +static inline CFStringRef SOSDataSourceGetName(SOSDataSourceRef ds) { + return ds->dsGetName(ds); +} + +static inline void SOSDataSourceSetNotifyPhaseBlock(SOSDataSourceRef ds, SOSDataSourceNotifyBlock notifyBlock) { + ds->dsSetNotifyPhaseBlock(ds, notifyBlock); +} + +static inline SOSManifestRef SOSDataSourceCopyManifest(SOSDataSourceRef ds, CFErrorRef *error) { + return ds->dsCopyManifest(ds, error); +} + +static inline bool SOSDataSourceForEachObject(SOSDataSourceRef ds, SOSManifestRef manifest, CFErrorRef *error, void (^handleObject)(CFDataRef digest, SOSObjectRef object, bool *stop)) { + return ds->dsForEachObject(ds, manifest, error, handleObject); +} + +static inline bool SOSDataSourceWith(SOSDataSourceRef ds, CFErrorRef *error, + void(^transaction)(SOSTransactionRef txn, bool *commit)) { + return ds->dsWith(ds, error, kSOSDataSourceSOSTransaction, transaction); +} + +static inline bool SOSDataSourceWithAPI(SOSDataSourceRef ds, bool isAPI, CFErrorRef *error, + void(^transaction)(SOSTransactionRef txn, bool *commit)) { + return ds->dsWith(ds, error, isAPI ? kSOSDataSourceAPITransaction : kSOSDataSourceSOSTransaction, transaction); +} + +static inline CFDataRef SOSDataSourceCopyStateWithKey(SOSDataSourceRef ds, CFStringRef key, CFStringRef pdmn, CFErrorRef *error) +{ + return ds->dsCopyStateWithKey(ds, key, pdmn, error); +} + +static inline bool SOSDataSourceRelease(SOSDataSourceRef ds, CFErrorRef *error) { + return !ds || ds->dsRelease(ds, error); +} + +// +// MARK: - SOSTransaction +// +static inline SOSMergeResult SOSDataSourceMergeObject(SOSDataSourceRef ds, SOSTransactionRef txn, SOSObjectRef peersObject, SOSObjectRef *createdObject, CFErrorRef *error) { + return ds->dsMergeObject(txn, peersObject, createdObject, error); +} + +static inline bool SOSDataSourceSetStateWithKey(SOSDataSourceRef ds, SOSTransactionRef txn, CFStringRef key, CFStringRef pdmn, CFDataRef state, CFErrorRef *error) +{ + return ds->dsSetStateWithKey(ds, txn, key, pdmn, state, error); +} + + +// +// MARK: - SOSObject methods +// +static inline CFDataRef SOSObjectCopyDigest(SOSDataSourceRef ds, SOSObjectRef object, CFErrorRef *error) { + 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); +} + +static inline CFDictionaryRef SOSObjectCopyPropertyList(SOSDataSourceRef ds, SOSObjectRef object, CFErrorRef *error) { + return ds->objectCopyPropertyList(object, error); +} + +static inline CFDictionaryRef SOSObjectCopyBackup(SOSDataSourceRef ds, SOSObjectRef object, uint64_t handle, CFErrorRef *error) { + return ds->objectCopyBackup(object, handle, error); +} + +static inline bool SOSObjectRestoreObject(SOSDataSourceRef ds, SOSTransactionRef txn, uint64_t handle, CFDictionaryRef item, CFErrorRef *error) { + return ds->dsRestoreObject(txn, handle, item, error); +} + + +// +// MARK: SOSDataSourceFactory helpers +// + +static inline SOSEngineRef SOSDataSourceFactoryGetEngineForDataSourceName(SOSDataSourceFactoryRef factory, CFStringRef dataSourceName, CFErrorRef *error) +{ + SOSDataSourceRef ds = factory->create_datasource(factory, dataSourceName, error); + SOSEngineRef engine = ds ? SOSDataSourceGetSharedEngine(ds, error) : (SOSEngineRef) NULL; + SOSDataSourceRelease(ds, NULL); // TODO: Log this error?! + + return engine; +} + +__END_DECLS + +#endif /* !_SEC_SOSDATASOURCE_H_ */ diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSDigestVector.c b/Security/sec/SOSCircle/SecureObjectSync/SOSDigestVector.c new file mode 100644 index 00000000..c8e1d7d2 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSDigestVector.c @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include +#include +#include +#include +#include + +CFStringRef kSOSDigestVectorErrorDomain = CFSTR("com.apple.security.sos.digestvector.error"); + +/* SOSDigestVector code. */ + +#define VECTOR_GROW(vector, count, capacity) \ +do { \ + if ((count) > capacity) { \ + capacity = ((capacity) + 16) * 3 / 2; \ + if (capacity < (count)) \ + capacity = (count); \ + vector = reallocf((vector), sizeof(*(vector)) * capacity); \ + } \ +} while (0) + +static void SOSDigestVectorEnsureCapacity(struct SOSDigestVector *dv, size_t count) { + VECTOR_GROW(dv->digest, count, dv->capacity); +} + +void SOSDigestVectorReplaceAtIndex(struct SOSDigestVector *dv, size_t ix, const uint8_t *digest) +{ + SOSDigestVectorEnsureCapacity(dv, ix + 1); + memcpy(dv->digest[ix], digest, SOSDigestSize); + dv->unsorted = true; +} + +static void SOSDigestVectorAppendOrdered(struct SOSDigestVector *dv, const uint8_t *digest) +{ + SOSDigestVectorEnsureCapacity(dv, dv->count + 1); + memcpy(dv->digest[dv->count++], digest, SOSDigestSize); +} + +void SOSDigestVectorAppend(struct SOSDigestVector *dv, const uint8_t *digest) +{ + SOSDigestVectorAppendOrdered(dv, digest); + dv->unsorted = true; +} + +static int SOSDigestCompare(const void *a, const void *b) +{ + return memcmp(a, b, SOSDigestSize); +} + +void SOSDigestVectorSort(struct SOSDigestVector *dv) +{ + if (dv->unsorted) { + qsort(dv->digest, dv->count, sizeof(*dv->digest), SOSDigestCompare); + dv->unsorted = false; + } +} + +void SOSDigestVectorUniqueSorted(struct SOSDigestVector *dv) +{ + // Uniqify in place + // TODO: This is really inefficient because of all the memcpys + if (dv->unsorted) + SOSDigestVectorSort(dv); + + int idx = 0, odx = 1; + uint8_t *prevDigest = dv->digest[0]; + for (idx = 1; idx < (int)dv->count; idx++) + { + if (SOSDigestCompare(prevDigest, dv->digest[idx])) { // this element is not the same as previous one + SOSDigestVectorReplaceAtIndex(dv, odx, dv->digest[idx]); + prevDigest = dv->digest[odx]; + ++odx; + } + } + dv->count = odx; +} + +void SOSDigestVectorSwap(struct SOSDigestVector *dva, struct SOSDigestVector *dvb) +{ + struct SOSDigestVector dv; + dv = *dva; + *dva = *dvb; + *dvb = dv; +} + +bool SOSDigestVectorContainsSorted(const struct SOSDigestVector *dv, const uint8_t *digest) +{ + return SOSDigestVectorIndexOfSorted(dv, digest) != (size_t)-1; +} + +bool SOSDigestVectorContains(struct SOSDigestVector *dv, const uint8_t *digest) +{ + if (dv->unsorted) + SOSDigestVectorSort(dv); + return SOSDigestVectorContainsSorted(dv, digest); +} + +size_t SOSDigestVectorIndexOfSorted(const struct SOSDigestVector *dv, const uint8_t *digest) +{ + const void *pos = bsearch(digest, dv->digest, dv->count, sizeof(*dv->digest), SOSDigestCompare); + return pos ? ((size_t)(pos - (void *)dv->digest)) / SOSDigestSize : ((size_t)-1); +} + +size_t SOSDigestVectorIndexOf(struct SOSDigestVector *dv, const uint8_t *digest) +{ + if (dv->unsorted) + SOSDigestVectorSort(dv); + return SOSDigestVectorIndexOfSorted(dv, digest); +} + +void SOSDigestVectorFree(struct SOSDigestVector *dv) +{ + free(dv->digest); + dv->digest = NULL; + dv->count = 0; + dv->capacity = 0; + dv->unsorted = false; +} + +void SOSDigestVectorApplySorted(const struct SOSDigestVector *dv, SOSDigestVectorApplyBlock with) +{ + bool stop = false; + for (size_t ix = 0; !stop && ix < dv->count; ++ix) { + with(dv->digest[ix], &stop); + } +} + +void SOSDigestVectorApply(struct SOSDigestVector *dv, SOSDigestVectorApplyBlock with) +{ + if (dv->unsorted) + SOSDigestVectorSort(dv); + SOSDigestVectorApplySorted(dv, with); +} + +// TODO: Check for NDEBUG to disable skip dupes are release time. +//#define SOSDVSKIPDUPES 0 +#define SOSDVSKIPDUPES 1 + +#if SOSDVSKIPDUPES +#define SOSDVINCRIX(dv,ix) (SOSDigestVectorIncrementAndSkipDupes(dv,ix)) +#else +#define SOSDVINCRIX(dv,ix) (ix + 1) +#endif + +static size_t SOSDigestVectorIncrementAndSkipDupes(const struct SOSDigestVector *dv, const size_t ix) { + size_t new_ix = ix; + if (new_ix < dv->count) { + while (++new_ix < dv->count) { + int delta = SOSDigestCompare(dv->digest[ix], dv->digest[new_ix]); + assert(delta <= 0); + if (delta != 0) + break; + } + } + return new_ix; +} + +void SOSDigestVectorAppendMultipleOrdered(struct SOSDigestVector *dv, + size_t count, const uint8_t *digests) { +#if SOSDVSKIPDUPES + size_t ix = 0; + while (ix < count) { + SOSDigestVectorAppendOrdered(dv, digests + (ix * SOSDigestSize)); + ix = SOSDVINCRIX(dv, ix); + } +#else + if (count) { + SOSDigestVectorEnsureCapacity(dv, dv->count + count); + memcpy(dv->digest[dv->count], digests, count * SOSDigestSize); + dv->count += count; + } +#endif +} + +void SOSDigestVectorIntersectSorted(const struct SOSDigestVector *dv1, const struct SOSDigestVector *dv2, + struct SOSDigestVector *dvintersect) +{ + /* dvintersect should be empty to start. */ + assert(dvintersect->count == 0); + size_t i1 = 0, i2 = 0; + while (i1 < dv1->count && i2 < dv2->count) { + int delta = SOSDigestCompare(dv1->digest[i1], dv2->digest[i2]); + if (delta == 0) { + SOSDigestVectorAppendOrdered(dvintersect, dv1->digest[i1]); + i1 = SOSDVINCRIX(dv1, i1); + i2 = SOSDVINCRIX(dv2, i2); + } else if (delta < 0) { + i1 = SOSDVINCRIX(dv1, i1); + } else { + i2 = SOSDVINCRIX(dv2, i2); + } + } +} + +void SOSDigestVectorUnionSorted(const struct SOSDigestVector *dv1, const struct SOSDigestVector *dv2, + struct SOSDigestVector *dvunion) +{ + /* dvunion should be empty to start. */ + assert(dvunion->count == 0); + size_t i1 = 0, i2 = 0; + while (i1 < dv1->count && i2 < dv2->count) { + int delta = SOSDigestCompare(dv1->digest[i1], dv2->digest[i2]); + if (delta == 0) { + SOSDigestVectorAppendOrdered(dvunion, dv1->digest[i1]); + i1 = SOSDVINCRIX(dv1, i1); + i2 = SOSDVINCRIX(dv2, i2); + } else if (delta < 0) { + SOSDigestVectorAppendOrdered(dvunion, dv1->digest[i1]); + i1 = SOSDVINCRIX(dv1, i1); + } else { + SOSDigestVectorAppendOrdered(dvunion, dv2->digest[i2]); + i2 = SOSDVINCRIX(dv2, i2); + } + } + SOSDigestVectorAppendMultipleOrdered(dvunion, dv1->count - i1, dv1->digest[i1]); + SOSDigestVectorAppendMultipleOrdered(dvunion, dv2->count - i2, dv2->digest[i2]); +} + +void SOSDigestVectorDiffSorted(const struct SOSDigestVector *dv1, const struct SOSDigestVector *dv2, + struct SOSDigestVector *dv1_2, struct SOSDigestVector *dv2_1) +{ + /* dv1_2 and dv2_1 should be empty to start. */ + assert(dv1_2->count == 0); + assert(dv2_1->count == 0); + + size_t i1 = 0, i2 = 0; + while (i1 < dv1->count && i2 < dv2->count) { + int delta = SOSDigestCompare(dv1->digest[i1], dv2->digest[i2]); + if (delta == 0) { + i1 = SOSDVINCRIX(dv1, i1); + i2 = SOSDVINCRIX(dv2, i2); + } else if (delta < 0) { + SOSDigestVectorAppendOrdered(dv1_2, dv1->digest[i1]); + i1 = SOSDVINCRIX(dv1, i1); + } else { + SOSDigestVectorAppendOrdered(dv2_1, dv2->digest[i2]); + i2 = SOSDVINCRIX(dv2, i2); + } + } + SOSDigestVectorAppendMultipleOrdered(dv1_2, dv1->count - i1, dv1->digest[i1]); + SOSDigestVectorAppendMultipleOrdered(dv2_1, dv2->count - i2, dv2->digest[i2]); +} + +void SOSDigestVectorDiff(struct SOSDigestVector *dv1, struct SOSDigestVector *dv2, + struct SOSDigestVector *dv1_2, struct SOSDigestVector *dv2_1) +{ + if (dv1->unsorted) SOSDigestVectorSort(dv1); + if (dv2->unsorted) SOSDigestVectorSort(dv2); + SOSDigestVectorDiffSorted(dv1, dv2, dv1_2, dv2_1); +} + +/* + If A and B are sets, then the relative complement of A in B, also termed the set-theoretic difference of B and A, + is the set of elements in B, but not in A. The relative complement of A in B is denoted B ∖ A according to the ISO 31-11 standard + sometimes written B − A + + The common case for us will be Removals\Additions + */ + +static void SOSDigestVectorAppendComplementAtIndex(size_t a_ix, const struct SOSDigestVector *dvA, size_t b_ix, const struct SOSDigestVector *dvB, + struct SOSDigestVector *dvcomplement) +{ + assert(a_ix <= dvA->count && b_ix <= dvB->count); + while (a_ix < dvA->count && b_ix < dvB->count) { + int delta = SOSDigestCompare(dvA->digest[a_ix], dvB->digest[b_ix]); + if (delta == 0) { + a_ix = SOSDVINCRIX(dvA, a_ix); + b_ix = SOSDVINCRIX(dvB, b_ix); + } else if (delta < 0) { + a_ix = SOSDVINCRIX(dvA, a_ix); + } else { + SOSDigestVectorAppendOrdered(dvcomplement, dvB->digest[b_ix]); + b_ix = SOSDVINCRIX(dvB, b_ix); + } + } + SOSDigestVectorAppendMultipleOrdered(dvcomplement, dvB->count - b_ix, dvB->digest[b_ix]); +} + + +void SOSDigestVectorComplementSorted(const struct SOSDigestVector *dvA, const struct SOSDigestVector *dvB, + struct SOSDigestVector *dvcomplement) +{ + /* dvcomplement should be empty to start. */ + assert(dvcomplement->count == 0); + assert(!dvA->unsorted); + assert(!dvB->unsorted); + + SOSDigestVectorAppendComplementAtIndex(0, dvA, 0, dvB, dvcomplement); +} + + +/* + For each item in base + + one way to do would be to define SOSDigestVectorComplementSorted + + For removals, if removal value is less than base, increment until GEQ + */ +bool SOSDigestVectorPatchSorted(const struct SOSDigestVector *base, const struct SOSDigestVector *removals, + const struct SOSDigestVector *additions, struct SOSDigestVector *dv, + CFErrorRef *error) +{ + /* dv should be empty to start. */ + assert(dv->count == 0); + assert(!base->unsorted); + assert(!removals->unsorted); + assert(!additions->unsorted); + + size_t i1 = 0, i2 = 0, i3 = 0; + while (i1 < base->count && i2 < additions->count) { + // Pick the smaller of base->digest[i1] and additions->digest[i2] as a + // candidate to be put into the output vector. If udelta positive, addition is smaller + int udelta = SOSDigestCompare(base->digest[i1], additions->digest[i2]); + const uint8_t *candidate = udelta < 0 ? base->digest[i1] : additions->digest[i2]; + + // ddelta > 0 means rem > candidate + int ddelta = 1; + while (i3 < removals->count) { + ddelta = SOSDigestCompare(removals->digest[i3], candidate); + if (ddelta < 0) { + i3 = SOSDVINCRIX(removals, i3); + } else { + if (ddelta == 0) + i3 = SOSDVINCRIX(removals, i3); + break; + } + } + if (ddelta > 0) + SOSDigestVectorAppendOrdered(dv, candidate); + + // Point to next (different) candidate + if (udelta == 0) { + i1 = SOSDVINCRIX(base, i1); + i2 = SOSDVINCRIX(additions, i2); + } else if (udelta < 0) { + i1 = SOSDVINCRIX(base, i1); + } else { + i2 = SOSDVINCRIX(additions, i2); + } + } + SOSDigestVectorAppendComplementAtIndex(i3, removals, i1, base, dv); + SOSDigestVectorAppendComplementAtIndex(i3, removals, i2, additions, dv); + + return true; +} + +bool SOSDigestVectorPatch(struct SOSDigestVector *base, struct SOSDigestVector *removals, + struct SOSDigestVector *additions, struct SOSDigestVector *dv, + CFErrorRef *error) +{ + if (base->unsorted) SOSDigestVectorSort(base); + if (removals->unsorted) SOSDigestVectorSort(removals); + if (additions->unsorted) SOSDigestVectorSort(additions); + return SOSDigestVectorPatchSorted(base, removals, additions, dv, error); +} diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSDigestVector.h b/Security/sec/SOSCircle/SecureObjectSync/SOSDigestVector.h new file mode 100644 index 00000000..78dc6681 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSDigestVector.h @@ -0,0 +1,96 @@ +/* + * 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@ + */ + + +/*! + @header SOSDigestVector.h + The functions provided in SOSDigestVector.h provide an interface doing + cheap appending, lazy sorting and delta math on sorted arrays of same + sized objects. + */ + +#ifndef _SEC_SOSDIGESTVECTOR_H_ +#define _SEC_SOSDIGESTVECTOR_H_ + +#include +#include + +__BEGIN_DECLS + +enum { + kSOSDigestVectorRemovalsLeftError = 1, + kSOSDigestVectorUnorderedAddError = 2, +}; + +extern CFStringRef kSOSDigestVectorErrorDomain; + +#define SOSDigestSize ((size_t)CCSHA1_OUTPUT_SIZE) + +#define SOSDigestVectorInit { .digest = NULL, .count = 0, .capacity = 0, .unsorted = false } + +struct SOSDigestVector { + uint8_t (*digest)[SOSDigestSize]; + size_t count; + size_t capacity; + bool unsorted; +}; + +typedef void (^SOSDigestVectorApplyBlock)(const uint8_t digest[SOSDigestSize], bool *stop); + +/* SOSDigestVector. */ +void SOSDigestVectorAppend(struct SOSDigestVector *dv, const uint8_t *digest); +void SOSDigestVectorAppendMultipleOrdered(struct SOSDigestVector *dv, size_t count, + const uint8_t *digests); +void SOSDigestVectorSort(struct SOSDigestVector *dv); +void SOSDigestVectorSwap(struct SOSDigestVector *dva, struct SOSDigestVector *dvb); +size_t SOSDigestVectorIndexOf(struct SOSDigestVector *dv, const uint8_t *digest); +size_t SOSDigestVectorIndexOfSorted(const struct SOSDigestVector *dv, const uint8_t *digest); +bool SOSDigestVectorContains(struct SOSDigestVector *dv, const uint8_t *digest); +bool SOSDigestVectorContainsSorted(const struct SOSDigestVector *dv, const uint8_t *digest); +void SOSDigestVectorReplaceAtIndex(struct SOSDigestVector *dv, size_t ix, const uint8_t *digest); +void SOSDigestVectorFree(struct SOSDigestVector *dv); + +void SOSDigestVectorApply(struct SOSDigestVector *dv, SOSDigestVectorApplyBlock with); +void SOSDigestVectorApplySorted(const struct SOSDigestVector *dv, SOSDigestVectorApplyBlock with); +void SOSDigestVectorIntersectSorted(const struct SOSDigestVector *dv1, const struct SOSDigestVector *dv2, + struct SOSDigestVector *dvintersect); +void SOSDigestVectorUnionSorted(const struct SOSDigestVector *dv1, const struct SOSDigestVector *dv2, + struct SOSDigestVector *dvunion); +void SOSDigestVectorUniqueSorted(struct SOSDigestVector *dv); + +void SOSDigestVectorDiffSorted(const struct SOSDigestVector *dv1, const struct SOSDigestVector *dv2, + struct SOSDigestVector *dv1_2, struct SOSDigestVector *dv2_1); +void SOSDigestVectorDiff(struct SOSDigestVector *dv1, struct SOSDigestVector *dv2, + struct SOSDigestVector *dv1_2, struct SOSDigestVector *dv2_1); +void SOSDigestVectorComplementSorted(const struct SOSDigestVector *dvA, const struct SOSDigestVector *dvB, + struct SOSDigestVector *dvcomplement); +bool SOSDigestVectorPatchSorted(const struct SOSDigestVector *base, const struct SOSDigestVector *removals, + const struct SOSDigestVector *additions, struct SOSDigestVector *dv, + CFErrorRef *error); +bool SOSDigestVectorPatch(struct SOSDigestVector *base, struct SOSDigestVector *removals, + struct SOSDigestVector *additions, struct SOSDigestVector *dv, + CFErrorRef *error); + +__END_DECLS + +#endif /* !_SEC_SOSDIGESTVECTOR_H_ */ diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSEngine.c b/Security/sec/SOSCircle/SecureObjectSync/SOSEngine.c new file mode 100644 index 00000000..3ae44455 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSEngine.c @@ -0,0 +1,1087 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* + * SOSEngine.c - Implementation of a secure object syncing engine + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // TODO: We can't leave this here. +#include // TODO: We can't leave this here. +#include // TODO: We can't leave this here. +#include // TODO: We can't leave this here. +#include + +// +// MARK: SOSEngine The Keychain database with syncable keychain support. +// + +// Key in dataSource for general engine state file. +// This file only has digest entries in it, no manifests. +static const CFStringRef kSOSEngineState = CFSTR("engine-state"); + +// Keys in state dictionary +static CFStringRef kSOSPeerCoderKey = CFSTR("coder"); +static CFStringRef kSOSEngineManifestCacheKey = CFSTR("manifestCache"); +static CFStringRef kSOSEnginePeerStateKey = CFSTR("peerState"); +static CFStringRef kSOSEnginePeerIDsKey = CFSTR("peerIDs"); +static CFStringRef kSOSEngineIDKey = CFSTR("id"); + +/* SOSEngine implementation. */ +struct __OpaqueSOSEngine { + CFRuntimeBase _base; + SOSDataSourceRef dataSource; + CFStringRef myID; // My peerID in the circle + SOSManifestRef manifest; // Explicitly not in cache since it's not persisted? + // We need to address the issues of corrupt keychain items + SOSManifestRef unreadble; // Possibly by having a set of unreadble items, to which we + // add any corrupted items in the db that have yet to be deleted. + // This happens if we notce corruption during a (read only) query. + // We would also perma-subtract unreadable from manifest whenever + // anyone asked for manifest. This result would be cached in + // The manifestCache below, so we just need a key into the cache + CFDataRef localMinusUnreadableDigest; // or a digest (CFDataRef of the right size). + + CFMutableDictionaryRef manifestCache; // digest -> ( refcount, manifest ) + CFMutableDictionaryRef peerState; // peerId -> mutable array of digests + CFArrayRef peerIDs; + + dispatch_queue_t queue; +}; + +static bool SOSEngineLoad(SOSEngineRef engine, CFErrorRef *error); + + +static CFStringRef SOSPeerIDArrayCreateString(CFArrayRef peerIDs) { + return peerIDs ? CFStringCreateByCombiningStrings(kCFAllocatorDefault, peerIDs, CFSTR(" ")) : CFSTR(""); + } + +static CFStringRef SOSEngineCopyFormattingDesc(CFTypeRef cf, CFDictionaryRef formatOptions) { + SOSEngineRef engine = (SOSEngineRef)cf; + CFStringRef tpDesc = SOSPeerIDArrayCreateString(engine->peerIDs); + CFStringRef desc = CFStringCreateWithFormat(kCFAllocatorDefault, formatOptions, CFSTR(""), engine->myID, tpDesc, engine->manifestCache ? (int)CFDictionaryGetCount(engine->manifestCache) : 0, engine->peerState ? (int)CFDictionaryGetCount(engine->peerState) : 0); + CFReleaseSafe(tpDesc); + return desc; + } + +static CFStringRef SOSEngineCopyDebugDesc(CFTypeRef cf) { + return SOSEngineCopyFormattingDesc(cf, NULL); + } + +static dispatch_queue_t sEngineQueue; +static CFDictionaryRef sEngineMap; + +CFGiblisWithFunctions(SOSEngine, NULL, NULL, NULL, NULL, NULL, SOSEngineCopyFormattingDesc, SOSEngineCopyDebugDesc, NULL, NULL, ^{ + sEngineQueue = dispatch_queue_create("SOSEngine queue", DISPATCH_QUEUE_SERIAL); + sEngineMap = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); +}); + +#define _LOG_RAW_MESSAGES 0 +void logRawMessage(CFDataRef message, bool sending, uint64_t seqno) +{ +#if _LOG_RAW_MESSAGES + CFStringRef hexMessage = NULL; + if (message) { + hexMessage = CFDataCopyHexString(message); + if (sending) + secnoticeq("engine", "%s RAW%1d %@", sending ? "send" : "recv", seqno?2:0, hexMessage); + else + secnoticeq("engine", "%s RAWx %@", sending ? "send" : "recv", hexMessage); // we don't know vers of received msg here + } + CFReleaseSafe(hexMessage); +#endif +} +// +// Peer state layout. WRONG! It's an array now +// The peer state is an array. +// The first element of the array is a dictionary with any number of keys and +// values in it (for future expansion) such as changing the digest size or type +// or remebering boolean flags for a peers sake. +// The next three are special in that they are manifest digests with special +// meaning and rules as to how they are treated (These are dynamically updated +// based on database activity so they have a fully history of all changes made +// to the local db. The first is the manifest representing the pendingObjects +// to send to the other peer. This is normally only ever appending to, and in +// particular with transactions originating from the Keychain API that affect +// syncable items will need to add the new objects digests to the pendingObjects list +// while adding the digests of any tombstones encountered to the extra list. + +CFStringRef SOSEngineGetMyID(SOSEngineRef engine) { + // TODO: this should not be needed + return engine->myID; +} + +// TEMPORARY: Get the list of IDs for cleanup, this shouldn't be used instead it should iterate KVS. +CFArrayRef SOSEngineGetPeerIDs(SOSEngineRef engine) { + return engine->peerIDs; +} + +SOSManifestRef SOSEngineGetManifestForDigest(SOSEngineRef engine, CFDataRef digest) { + if (!engine->manifestCache || !digest) return NULL; + SOSManifestRef manifest = (SOSManifestRef)CFDictionaryGetValue(engine->manifestCache, digest); + if (!manifest) return NULL; + if (CFGetTypeID(manifest) != SOSManifestGetTypeID()) { + secerror("dropping corrupt manifest for %@ from cache", digest); + CFDictionaryRemoveValue(engine->manifestCache, digest); + return NULL; + } + + return manifest; +} + +void SOSEngineAddManifest(SOSEngineRef engine, SOSManifestRef manifest) { + CFDataRef digest = SOSManifestGetDigest(manifest, NULL); + if (digest) { + if (!engine->manifestCache) + engine->manifestCache = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionaryAddValue(engine->manifestCache, digest, manifest); + } +} + +CFDataRef SOSEnginePatchRecordAndCopyDigest(SOSEngineRef engine, SOSManifestRef base, SOSManifestRef removals, SOSManifestRef additions, CFErrorRef *error) { + CFDataRef digest = NULL; + SOSManifestRef manifest = SOSManifestCreateWithPatch(base, removals, additions, error); + if (manifest) { + SOSEngineAddManifest(engine, manifest); + digest = CFRetainSafe(SOSManifestGetDigest(manifest, NULL)); + } + CFReleaseSafe(manifest); + return digest; +} + +static bool SOSEngineHandleManifestUpdates(SOSEngineRef engine, SOSDataSourceTransactionSource source, SOSManifestRef removals, SOSManifestRef additions, CFErrorRef *error) { + __block struct SOSDigestVector mdInCache = SOSDigestVectorInit; + struct SOSDigestVector mdInUse = SOSDigestVectorInit; + struct SOSDigestVector mdUnused = SOSDigestVectorInit; + struct SOSDigestVector mdMissing = SOSDigestVectorInit; + CFStringRef peerID = NULL; + bool ok = true; + + require_quiet(engine->peerState, exit); // Not a failure no work to do + + if(engine->peerIDs){ + CFArrayForEachC(engine->peerIDs, peerID) { + SOSPeerRef peer = SOSPeerCreateWithEngine(engine, peerID); + if (removals || additions) + ok &= SOSPeerDataSourceWillCommit(peer, source, removals, additions, error); + SOSPeerMarkDigestsInUse(peer, &mdInUse); + CFReleaseSafe(peer); + } + } + if(engine->manifestCache){ + CFDictionaryForEach(engine->manifestCache, ^(const void *key, const void *value) { + CFDataRef digest = (CFDataRef)key; + if (isData(digest)) + SOSDigestVectorAppend(&mdInCache, CFDataGetBytePtr(digest)); + }); + + // Delete unused manifests. + SOSDigestVectorDiff(&mdInCache, &mdInUse, &mdUnused, &mdMissing); + SOSManifestRef unused = SOSManifestCreateWithDigestVector(&mdUnused, NULL); + SOSManifestForEach(unused, ^(CFDataRef digest, bool *stop) { + if (digest) + CFDictionaryRemoveValue(engine->manifestCache, digest); + }); + CFReleaseSafe(unused); + } + // Delete unused peerState + if (engine->peerState && engine->peerIDs) { + CFMutableDictionaryRef newPeerState = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFArrayForEachC(engine->peerIDs, peerID) { + CFTypeRef value = CFDictionaryGetValue(engine->peerState, peerID); + if (value) + CFDictionarySetValue(newPeerState, peerID, value); + } + CFDictionaryForEach(engine->peerState, ^(const void *key, const void *value) { + if(isDictionary(value) && !CFDictionaryContainsKey(newPeerState, key)){ + CFMutableDictionaryRef untrustedStuff = (CFMutableDictionaryRef)value; + CFDataRef untrustedCoder = (CFDataRef)CFDictionaryGetValue(untrustedStuff, kSOSPeerCoderKey); + if(untrustedCoder){ + CFMutableDictionaryRef untrustedDict = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, kSOSPeerCoderKey, untrustedCoder, NULL); + CFDictionarySetValue(newPeerState, key, untrustedDict); + CFReleaseNull(untrustedDict); + } + } + }); + CFReleaseSafe(engine->peerState); + engine->peerState = newPeerState; + } + +exit: + SOSDigestVectorFree(&mdInCache); + SOSDigestVectorFree(&mdInUse); + SOSDigestVectorFree(&mdUnused); + SOSDigestVectorFree(&mdMissing); + return ok; +} + +static CFDataRef SOSEngineCopyState(SOSEngineRef engine, CFErrorRef *error) { + CFDataRef der = NULL; + CFMutableDictionaryRef state = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + if (engine->myID) CFDictionarySetValue(state, kSOSEngineIDKey, engine->myID); + if (engine->peerIDs) CFDictionarySetValue(state, kSOSEnginePeerIDsKey, engine->peerIDs); + if (engine->peerState) CFDictionarySetValue(state, kSOSEnginePeerStateKey, engine->peerState); + if (engine->manifestCache) { + CFMutableDictionaryRef mfc = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionarySetValue(state, kSOSEngineManifestCacheKey, mfc); + CFDictionaryForEach(engine->manifestCache, ^(const void *key, const void *value) { + SOSManifestRef mf = (SOSManifestRef)value; + if (mf && (CFGetTypeID(mf) == SOSManifestGetTypeID())) + CFDictionarySetValue(mfc, key, SOSManifestGetData(mf)); + }); + CFReleaseSafe(mfc); + } + der = kc_plist_copy_der(state, error); + CFReleaseSafe(state); + secnotice("engine", "%@", engine); + return der; +} + +static bool SOSEngineSave(SOSEngineRef engine, SOSTransactionRef txn, CFErrorRef *error) { + CFDataRef derState = SOSEngineCopyState(engine, error); + bool ok = derState && SOSDataSourceSetStateWithKey(engine->dataSource, txn, kSOSEngineState, kSecAttrAccessibleAlways, derState, error); + CFReleaseSafe(derState); + return ok; +} + +static bool SOSEngineUpdateLocalManifest_locked(SOSEngineRef engine, SOSDataSourceTransactionSource source, SOSManifestRef removals, SOSManifestRef additions, CFErrorRef *error) { + bool ok = true; + if (engine->manifest) { + SOSManifestRef updatedManifest = SOSManifestCreateWithPatch(engine->manifest, removals, additions, error); + if (updatedManifest) + CFAssignRetained(engine->manifest, updatedManifest); + + // Update Peer Manifests. -- Shouldn't this be deferred until we apply our toAdd and toDel to the local manifest? + ok &= SOSEngineHandleManifestUpdates(engine, source, removals, additions, error); + } + return ok; +} + +static bool SOSEngineUpdateChanges(SOSEngineRef engine, SOSTransactionRef txn, SOSDataSourceTransactionPhase phase, SOSDataSourceTransactionSource source, SOSManifestRef removals, SOSManifestRef additions, CFErrorRef *error) +{ + secnotice("engine", "%s %s dels:%@ adds:%@", phase == kSOSDataSourceTransactionWillCommit ? "will-commit" : phase == kSOSDataSourceTransactionDidCommit ? "did-commit" : "did-rollback", source == kSOSDataSourceSOSTransaction ? "sos" : "api", removals, additions); + bool ok = true; + switch (phase) { + case kSOSDataSourceTransactionDidRollback: + ok &= SOSEngineLoad(engine, error); + break; + case kSOSDataSourceTransactionWillCommit: { + ok &= SOSEngineUpdateLocalManifest_locked(engine, source, removals, additions, error); + // Write SOSEngine and SOSPeer state to disk if dirty + ok &= SOSEngineSave(engine, txn, error); + break; + } + case kSOSDataSourceTransactionDidCommit: + break; + } + return ok; +} + +static void SOSEngineSetTrustedPeers(SOSEngineRef engine, CFStringRef myPeerID, CFArrayRef trustedPeers) { + const bool wasInCircle = engine->myID; + const bool isInCircle = myPeerID; + const bool inCircleChanged = wasInCircle != isInCircle; + + CFStringRef peerID = NULL; + CFRetainAssign(engine->myID, myPeerID); + + if(trustedPeers != NULL && CFArrayGetCount(trustedPeers) != 0){ + CFReleaseNull(engine->peerIDs); + engine->peerIDs = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFArrayForEachC(trustedPeers, peerID){ + CFArrayAppendValue((CFMutableArrayRef)engine->peerIDs, peerID); + }; + } + else{ + engine->peerIDs = NULL; + } + // If we entered a circle of more than 2 or our last peer left we need to do stuff + if (inCircleChanged) { + if (isInCircle) { + CFErrorRef dsError = NULL; + if (!(engine->manifest = SOSDataSourceCopyManifest(engine->dataSource, &dsError))) { + secerror("failed to load manifest from datasource: %@", dsError); + CFReleaseNull(dsError); + } + SOSDataSourceSetNotifyPhaseBlock(engine->dataSource, ^(SOSDataSourceRef ds, SOSTransactionRef txn, SOSDataSourceTransactionPhase phase, SOSDataSourceTransactionSource source, struct SOSDigestVector *removals, struct SOSDigestVector *additions) { + SOSManifestRef mfdel = SOSManifestCreateWithDigestVector(removals, NULL); + SOSManifestRef mfadd = SOSManifestCreateWithDigestVector(additions, NULL); + dispatch_block_t processUpdates = ^{ + CFErrorRef localError = NULL; + if (!SOSEngineUpdateChanges(engine, txn, phase, source, mfdel, mfadd, &localError)) { + secerror("updateChanged failed: %@", localError); + } + CFReleaseSafe(localError); + CFReleaseSafe(mfdel); + CFReleaseSafe(mfadd); + }; + + if (source == kSOSDataSourceSOSTransaction) { + processUpdates(); + } else { + // WARNING: This will deadlock the engine if you call a + // SecItem API function while holding the engine lock! + // However making this async right now isn't safe yet either + // Due to some code in the enginer using Get v/s copy to + // access some of the values that would be modified + // asynchronously here since the engine is coded as if + // running on a serial queue. + dispatch_sync(engine->queue, processUpdates); + } + }); + } else { + SOSDataSourceSetNotifyPhaseBlock(engine->dataSource, ^(SOSDataSourceRef ds, SOSTransactionRef txn, SOSDataSourceTransactionPhase phase, SOSDataSourceTransactionSource source, struct SOSDigestVector *removals, struct SOSDigestVector *additions) { + secnoticeq("engine", "No peers to notify"); // TODO: DEBUG - remove this + }); + CFReleaseNull(engine->manifest); + } + } +} + +static bool SOSEngineSetState(SOSEngineRef engine, CFDataRef state, CFErrorRef *error) { + bool ok = true; + if (state) { + CFMutableDictionaryRef dict = NULL; + const uint8_t *der = CFDataGetBytePtr(state); + const uint8_t *der_end = der + CFDataGetLength(state); + der = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *)&dict, error, der, der_end); + if (der && der != der_end) { + ok = SOSErrorCreate(kSOSErrorDecodeFailure, error, NULL, CFSTR("trailing %td bytes at end of state"), der_end - der); + } + if (ok) { + SOSEngineSetTrustedPeers(engine, (CFStringRef)CFDictionaryGetValue(dict, kSOSEngineIDKey), + (CFArrayRef)CFDictionaryGetValue(dict, kSOSEnginePeerIDsKey)); + CFRetainAssign(engine->peerState, (CFMutableDictionaryRef)CFDictionaryGetValue(dict, kSOSEnginePeerStateKey)); + + CFReleaseNull(engine->manifestCache); + CFMutableDictionaryRef mfc = (CFMutableDictionaryRef)CFDictionaryGetValue(dict, kSOSEngineManifestCacheKey); + if (mfc) { + engine->manifestCache = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionaryForEach(mfc, ^(const void *key, const void *value) { + CFDataRef data = (CFDataRef)value; + if (isData(data)) { + SOSManifestRef mf = SOSManifestCreateWithData(data, NULL); + if (mf) + CFDictionarySetValue(engine->manifestCache, key, mf); + CFReleaseSafe(mf); + } + }); + } + } + CFReleaseNull(dict); + } + secnotice("engine", "%@", engine); + return ok; +} + +static bool SOSEngineLoad(SOSEngineRef engine, CFErrorRef *error) { + CFDataRef state = SOSDataSourceCopyStateWithKey(engine->dataSource, kSOSEngineState, kSecAttrAccessibleAlways, error); + bool ok = state && SOSEngineSetState(engine, state, error); + CFReleaseSafe(state); + return ok; +} + +static void CFArraySubtract(CFMutableArrayRef from, CFArrayRef remove) { + if (remove) { + CFArrayForEach(remove, ^(const void *value) { + CFArrayRemoveAllValue(from, value); + }); + } +} + +static CFMutableArrayRef CFArrayCreateDifference(CFAllocatorRef alloc, CFArrayRef set, CFArrayRef remove) { + CFMutableArrayRef result; + if (!set) { + result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + } else { + result = CFArrayCreateMutableCopy(alloc, 0, set); + + if (remove) + CFArraySubtract(result, remove); + } + + return result; +} + +void SOSEngineCircleChanged_locked(SOSEngineRef engine, CFStringRef myPeerID, CFArrayRef trustedPeers, CFArrayRef untrustedPeers) { + CFMutableArrayRef addedPeers = CFArrayCreateDifference(kCFAllocatorDefault, trustedPeers, engine->peerIDs); + CFMutableArrayRef deletedPeers = CFArrayCreateDifference(kCFAllocatorDefault, engine->peerIDs, trustedPeers); + + CFStringRef tpDesc = SOSPeerIDArrayCreateString(trustedPeers); + CFStringRef apDesc = SOSPeerIDArrayCreateString(addedPeers); + CFStringRef dpDesc = SOSPeerIDArrayCreateString(deletedPeers); + secnotice("engine", "trusted %@ added %@ removed %@", tpDesc, apDesc, dpDesc); + CFReleaseSafe(dpDesc); + CFReleaseSafe(apDesc); + CFReleaseSafe(tpDesc); + + SOSEngineSetTrustedPeers(engine, myPeerID, trustedPeers); + + // Remove any cached state for peers we no longer use but keep coders alive + if (deletedPeers && CFArrayGetCount(deletedPeers) && engine->peerState) { + CFStringRef peerID = NULL; + CFArrayForEachC(deletedPeers, peerID) { + CFMutableDictionaryRef peer_data = (CFMutableDictionaryRef) CFDictionaryGetValue(engine->peerState, peerID); + CFDataRef coder_data = isDictionary(peer_data) ? (CFDataRef) CFDictionaryGetValue(peer_data, kSOSPeerCoderKey) : NULL; + + if(isData(coder_data) && + untrustedPeers && CFArrayContainsValue(untrustedPeers, CFRangeMake(0, CFArrayGetCount(untrustedPeers)), peerID)) { + CFRetainSafe(coder_data); + CFDictionaryRemoveAllValues(peer_data); + CFDictionaryAddValue(peer_data, kSOSPeerCoderKey, coder_data); + CFReleaseSafe(coder_data); + } else { + CFDictionaryRemoveValue(engine->peerState, peerID); + } + } + // Run though all peers and only cache manifests for peers we still have + // TODO: Factor out gc from SOSEngineHandleManifestUpdates and just call that + SOSEngineHandleManifestUpdates(engine, kSOSDataSourceSOSTransaction, NULL, NULL, NULL); + } + + CFReleaseNull(addedPeers); + CFReleaseNull(deletedPeers); + +} + +#if 0 +static SOSManifestRef SOSEngineCopyCleanManifest(SOSEngineRef engine, CFErrorRef *error) { + SOSManifestRef localMinusUnreadable; + } +#endif + +// Initialize the engine if a load fails. Basically this is our first time setup +static bool SOSEngineInit(SOSEngineRef engine, CFErrorRef *error) { + bool ok = true; + secnotice("engine", "new engine for datasource named %@", SOSDataSourceGetName(engine->dataSource)); + return ok; +} + +// Called by our DataSource in its constructor +SOSEngineRef SOSEngineCreate(SOSDataSourceRef dataSource, CFErrorRef *error) { + SOSEngineRef engine = NULL; + engine = CFTypeAllocate(SOSEngine, struct __OpaqueSOSEngine, kCFAllocatorDefault); + engine->dataSource = dataSource; + engine->queue = dispatch_queue_create("engine", DISPATCH_QUEUE_SERIAL); + CFErrorRef engineError = NULL; + if (!SOSEngineLoad(engine, &engineError)) { + secwarning("engine failed load state starting with nothing %@", engineError); + CFReleaseNull(engineError); + if (!SOSEngineInit(engine, error)) { + secerror("engine failed to initialze %@ giving up", engineError); + } + } + return engine; +} + + +// +// MARK: SOSEngine API +// + +void SOSEngineDispose(SOSEngineRef engine) { + // NOOP Engines stick around forever to monitor dataSource changes. +} + +static SOSManifestRef SOSEngineCopyManifest_locked(SOSEngineRef engine, CFErrorRef *error) { + return CFRetainSafe(engine->manifest); +} + +/* Handle incoming message from peer p. Return false if there was an error, true otherwise. */ +static bool SOSEngineHandleMessage_locked(SOSEngineRef engine, CFStringRef peerID, SOSMessageRef message, + SOSTransactionRef txn, bool *commit, bool *somethingChanged, CFErrorRef *error) { + SOSPeerRef peer = SOSPeerCreateWithEngine(engine, peerID); + CFStringRef peerDesc = NULL; + SOSManifestRef localManifest = NULL; + SOSManifestRef allAdditions = NULL; + SOSManifestRef confirmed = NULL; + SOSManifestRef base = NULL; + SOSManifestRef confirmedRemovals = NULL, confirmedAdditions = NULL; + __block struct SOSDigestVector receivedObjects = SOSDigestVectorInit; + + // Check for unknown criticial extensions in the message, and handle + // any other extensions we support + __block bool ok = true; + __block struct SOSDigestVector dvadd = SOSDigestVectorInit; + + require_action_quiet(peer, exit, ok = SOSErrorCreate(errSecParam, error, NULL, CFSTR("Couldn't create peer with Engine for %@"), peerID)); + peerDesc = CFCopyDescription(peer); + + SOSMessageWithExtensions(message, true, ^(CFDataRef oid, bool isCritical, CFDataRef extension, bool *stop) { + // OMFG a Critical extension what shall I do! + ok = SOSErrorCreate(kSOSErrorNotReady, error, NULL, CFSTR("Unknown criticial extension in peer message")); + *stop = true; + }); + require_quiet(ok, exit); + + // Merge Objects from the message into our DataSource. + // Should we move the transaction to the SOSAccount level? + require_quiet(ok &= SOSMessageWithSOSObjects(message, engine->dataSource, error, ^(SOSObjectRef peersObject, bool *stop) { + CFDataRef digest = SOSObjectCopyDigest(engine->dataSource, peersObject, error); + if (!digest) { + *stop = true; + *commit = false; + secerror("%@ peer sent bad object: %@, rolling back changes", SOSPeerGetID(peer), error ? *error : NULL); + return; + } + SOSDigestVectorAppend(&receivedObjects, CFDataGetBytePtr(digest)); + SOSMergeResult mr = SOSDataSourceMergeObject(engine->dataSource, txn, peersObject, NULL, error); + // TODO: If the mr is kSOSMergeLocalObject most of the time (or all of the time), + // consider asking the peer to stop sending us objects, and send it objects instead. + ok &= (mr != kSOSMergeFailure); + if (!ok) { + *stop = true; + *commit = false; + // TODO: Might want to change to warning since the race of us locking after ckd sends us a message could cause db locked errors here. + secerror("%@ SOSDataSourceMergeObject failed %@ rolling back changes", SOSPeerGetID(peer), error ? *error : NULL); + } else if (mr==kSOSMergePeersObject || mr==kSOSMergeCreatedObject) { + *somethingChanged = true; + } else { + // mr == kSOSMergeLocalObject + // Ensure localObject is in local manifest (possible corruption) by posting an update when we are done. + SOSDigestVectorAppend(&dvadd, CFDataGetBytePtr(digest)); + } + CFReleaseSafe(digest); + }), exit); + struct SOSDigestVector dvunion = SOSDigestVectorInit; + SOSDigestVectorSort(&receivedObjects); + SOSDigestVectorUnionSorted(SOSManifestGetDigestVector(SOSMessageGetAdditions(message)), &receivedObjects, &dvunion); + allAdditions = SOSManifestCreateWithDigestVector(&dvunion, error); + SOSDigestVectorFree(&receivedObjects); + SOSDigestVectorFree(&dvunion); + + if (dvadd.count) { + // Ensure any objects that we received and have localally already are actually in our local manifest + SOSManifestRef mfadd = SOSManifestCreateWithDigestVector(&dvadd, error); + SOSDigestVectorFree(&dvadd); + SOSEngineUpdateLocalManifest_locked(engine, kSOSDataSourceSOSTransaction, NULL, mfadd, error); + CFReleaseSafe(mfadd); + } + + // ---- Don't use local or peer manifests from above this line, since commiting the SOSDataSourceWith transaction might change them --- + + // Take a snapshot of our dataSource's local manifest. + require_quiet(ok = localManifest = SOSEngineCopyManifest_locked(engine, error), exit); + + CFDataRef baseDigest = SOSMessageGetBaseDigest(message); + CFDataRef proposedDigest = SOSMessageGetProposedDigest(message); + +#if 0 + // I believe this is no longer needed now that we have eliminated extra, + // Since this is handeled below once we get a confirmed manifest from our + // peer. + + // If we just received a L00 reset pendingObjects to localManifest + if (!baseDigest && !proposedDigest) { + SOSPeerSetPendingObjects(peer, localManifest); + secnotice("engine", "SOSPeerSetPendingObjects: %@", localManifest); + } +#endif + + base = CFRetainSafe(SOSEngineGetManifestForDigest(engine, baseDigest)); + confirmed = CFRetainSafe(SOSEngineGetManifestForDigest(engine, SOSMessageGetSenderDigest(message))); + if (!confirmed) { + if (SOSManifestGetCount(SOSMessageGetRemovals(message)) || SOSManifestGetCount(allAdditions)) { + confirmed = SOSManifestCreateWithPatch(base, SOSMessageGetRemovals(message), allAdditions, error); + if (!confirmed) { + confirmedRemovals = CFRetainSafe(SOSMessageGetRemovals(message)); + confirmedAdditions = CFRetainSafe(allAdditions); + } + } else if (baseDigest) { + confirmed = CFRetainSafe(base); + secerror("Protocol error send L00 - figure out later base: %@", base); + } + } + secnotice("engine", "Confirmed: %@ base: %@", confirmed, base); + if (confirmed) + ok &= SOSManifestDiff(SOSPeerGetConfirmedManifest(peer), confirmed, &confirmedRemovals, &confirmedAdditions, error); + if (confirmedRemovals || confirmedAdditions) + ok &= SOSPeerDidReceiveRemovalsAndAdditions(peer, confirmedRemovals, confirmedAdditions, localManifest, error); + SOSPeerSetConfirmedManifest(peer, confirmed); + + // ---- SendObjects and extra->pendingObjects promotion dance ---- + + // The first block of code below sets peer.sendObjects to true when we receive a L00 and the second block + // moves extra to pendingObjects once we receive a confirmed manifest in or after the L00. + if (!baseDigest && !proposedDigest) { + SOSPeerSetSendObjects(peer, true); + } + + // TODO: should this not depend on SOSPeerSendObjects?: + if (confirmed /* && SOSPeerSendObjects(peer)*/) { + SOSManifestRef allExtra = NULL; + ok &= SOSManifestDiff(confirmed, localManifest, NULL, &allExtra, error); + secnotice("engine", "%@ confirmed %@ setting O:%@", SOSPeerGetID(peer), confirmed, allExtra); + SOSPeerSetPendingObjects(peer, allExtra); + CFReleaseSafe(allExtra); + } + +exit: + secnoticeq("engine", "recv %@ %@", SOSPeerGetID(peer), message); + secnoticeq("peer", "recv %@ -> %@", peerDesc, peer); + + CFReleaseNull(base); + CFReleaseSafe(confirmed); + CFReleaseSafe(localManifest); + CFReleaseSafe(peerDesc); + CFReleaseSafe(allAdditions); + CFReleaseSafe(confirmedRemovals); + CFReleaseSafe(confirmedAdditions); + CFReleaseSafe(peer); + return ok; +} + +static CFDataRef SOSEngineCopyObjectDER(SOSEngineRef engine, SOSObjectRef object, CFErrorRef *error) { + CFDataRef der = NULL; + CFDictionaryRef plist = SOSObjectCopyPropertyList(engine->dataSource, object, error); + if (plist) { + der = kc_plist_copy_der(plist, error); + CFRelease(plist); + } + return der; + } + +static CFDataRef SOSEngineCreateMessage_locked(SOSEngineRef engine, SOSPeerRef peer, + CFErrorRef *error, SOSEnginePeerMessageSentBlock *sent) { + SOSManifestRef local = SOSEngineCopyManifest_locked(engine, error); + __block SOSMessageRef message = SOSMessageCreate(kCFAllocatorDefault, SOSPeerGetMessageVersion(peer), error); + SOSManifestRef confirmed = SOSPeerGetConfirmedManifest(peer); + SOSManifestRef pendingObjects = SOSPeerGetPendingObjects(peer); + SOSManifestRef objectsSent = NULL; + SOSManifestRef proposed = NULL; + SOSManifestRef allMissing = NULL; + SOSManifestRef allExtra = NULL; + SOSManifestRef extra = NULL; + SOSManifestRef excessPending = NULL; + SOSManifestRef missing = NULL; + SOSManifestRef deleted = SOSPeerGetPendingDeletes(peer); + SOSManifestRef excessDeleted = NULL; + CFDataRef result = NULL; + bool ok; + + ok = SOSManifestDiff(confirmed, local, &allMissing, &allExtra, error); + ok = ok && SOSManifestDiff(allExtra, pendingObjects, &extra, &excessPending, error); + if (SOSManifestGetCount(excessPending)) { + secerror("%@ ASSERTION FAILURE excess pendingObjects: %@", peer, excessPending); + // Remove excessPending from pendingObjects since they are either + // already in confirmed or not in local, either way there is no point + // keeping them in pendingObjects. + + pendingObjects = SOSManifestCreateComplement(excessPending, pendingObjects, error); + SOSPeerSetPendingObjects(peer, pendingObjects); + CFReleaseSafe(pendingObjects); + ok = false; + } + ok = ok && SOSManifestDiff(allMissing, deleted, &missing, &excessDeleted, error); + if (SOSManifestGetCount(excessDeleted)) { + secerror("%@ ASSERTION FAILURE excess deleted: %@", peer, excessDeleted); + ok = false; + } + (void)ok; // Dead store + CFReleaseNull(allExtra); + CFReleaseNull(excessPending); + CFReleaseNull(allMissing); + CFReleaseNull(excessDeleted); + + // Send state for peer 7T0M+TD+A7HZ0frC5oHZnmdR0G: [LCP][os] P: 0, E: 0, M: 0 + secnoticeq("engine", "Send state for peer %@: [%s%s%s][%s%s] P: %zu, E: %zu, M: %zu", SOSPeerGetID(peer), + local ? "L":"l", + confirmed ? "C":"0", + pendingObjects ? "P":"0", + SOSPeerSendObjects(peer) ? "O":"o", + SOSPeerMustSendMessage(peer) ? "S":"s", + SOSManifestGetCount(pendingObjects), + SOSManifestGetCount(extra), + SOSManifestGetCount(missing) + ); + + if (confirmed) { + // TODO: Because of not letting things terminate while we have extra left + // we might send objects when we didn't need to, but there is always an + // extra roundtrip required for objects that we assume the other peer + // should have already. + // TODO: If there are extra objects left, calling this function is not + // idempotent we should check if pending is what we are about to send and not send anything in this case. + if (SOSManifestGetCount(pendingObjects) == 0 && SOSManifestGetCount(extra) == 0) + SOSPeerSetSendObjects(peer, false); + + if (CFEqualSafe(local, SOSPeerGetProposedManifest(peer)) && !SOSPeerMustSendMessage(peer)) { + bool send = false; + if (CFEqual(confirmed, local)) { + secnoticeq("engine", "synced %@", peer); + } else if (SOSManifestGetCount(pendingObjects) == 0 /* TODO: No entries moved from extra to pendingObjects. */ + && SOSManifestGetCount(missing) == 0) { + secnoticeq("engine", "waiting %@", peer); + } else { + send = true; + } + if (!send) { + CFReleaseSafe(local); + CFReleaseSafe(message); + CFReleaseNull(extra); + CFReleaseNull(missing); + return CFDataCreate(kCFAllocatorDefault, NULL, 0); + } + } + + if (SOSManifestGetCount(pendingObjects)) { + // If we have additions and we need to send objects send them. + __block size_t objectsSize = 0; + __block struct SOSDigestVector dv = SOSDigestVectorInit; + __block struct SOSDigestVector dvdel = SOSDigestVectorInit; + if (!SOSDataSourceForEachObject(engine->dataSource, pendingObjects, error, ^void(CFDataRef key, SOSObjectRef object, bool *stop) { + CFErrorRef localError = NULL; + CFDataRef digest = NULL; + CFDataRef der = NULL; + if (!object) { + const uint8_t *d = CFDataGetBytePtr(key); + secerrorq("%@ object %02X%02X%02X%02X dropping from manifest: not found in datasource", + SOSPeerGetID(peer), d[0], d[1], d[2], d[3]); + SOSDigestVectorAppend(&dvdel, CFDataGetBytePtr(key)); + } else if (!(der = SOSEngineCopyObjectDER(engine, object, &localError)) + || !(digest = SOSObjectCopyDigest(engine->dataSource, object, &localError))) { + if (SecErrorGetOSStatus(localError) == errSecDecode) { + // Decode error, we need to drop these objects from our manifests + const uint8_t *d = CFDataGetBytePtr(key); + secerrorq("%@ object %02X%02X%02X%02X dropping from manifest: %@", + SOSPeerGetID(peer), d[0], d[1], d[2], d[3], localError); + SOSDigestVectorAppend(&dvdel, CFDataGetBytePtr(key)); + CFRelease(localError); + } else { + // Stop iterating and propagate out all other errors. + const uint8_t *d = CFDataGetBytePtr(key); + secwarning("%@ object %02X%02X%02X%02X in SOSDataSourceForEachObject: %@", + SOSPeerGetID(peer), d[0], d[1], d[2], d[3], localError); + *stop = true; + CFErrorPropagate(localError, error); + CFReleaseNull(message); + } + } else { + if (!CFEqual(key, digest)) { + const uint8_t *d = CFDataGetBytePtr(key); + const uint8_t *e = CFDataGetBytePtr(digest); + secwarning("@ object %02X%02X%02X%02X is really %02X%02X%02X%02X dropping from local manifest", d[0], d[1], d[2], d[3], e[0], e[1], e[2], e[3]); + SOSDigestVectorAppend(&dvdel, CFDataGetBytePtr(key)); + } + + size_t objectLen = (size_t)CFDataGetLength(der); + if (SOSMessageAppendObject(message, der, &localError)) { + SOSDigestVectorAppend(&dv, CFDataGetBytePtr(digest)); + } else { + const uint8_t *d = CFDataGetBytePtr(digest); + CFStringRef hexder = CFDataCopyHexString(der); + secerrorq("%@ object %02X%02X%02X%02X der: %@ dropping from manifest: %@", + SOSPeerGetID(peer), d[0], d[1], d[2], d[3], hexder, localError); + CFReleaseNull(hexder); + CFReleaseNull(message); + // Since we can't send these objects let's assume they are bad too? + SOSDigestVectorAppend(&dvdel, CFDataGetBytePtr(digest)); + } + objectsSize += objectLen; + if (objectsSize > kSOSMessageMaxObjectsSize) + *stop = true; + } + CFReleaseSafe(der); + CFReleaseSafe(digest); + })) { + CFReleaseNull(message); + } + if (dv.count) + objectsSent = SOSManifestCreateWithDigestVector(&dv, error); + if (dvdel.count) { + CFErrorRef localError = NULL; + SOSManifestRef mfdel = SOSManifestCreateWithDigestVector(&dvdel, error); + SOSDigestVectorFree(&dvdel); + if (!SOSEngineUpdateLocalManifest_locked(engine, kSOSDataSourceSOSTransaction, mfdel, NULL, &localError)) + secerror("SOSEngineUpdateLocalManifest deleting: %@ failed: %@", mfdel, localError); + CFReleaseSafe(localError); + CFReleaseSafe(mfdel); + CFAssignRetained(local, SOSEngineCopyManifest_locked(engine, error)); + } + SOSDigestVectorFree(&dv); + } + } else { + // If we have no confirmed manifest, we want all pendedObjects going out as a manifest + objectsSent = CFRetainSafe(pendingObjects); + } + + if (confirmed || SOSManifestGetCount(missing) || SOSManifestGetCount(extra) || objectsSent) { + SOSManifestRef allExtra = SOSManifestCreateUnion(extra, objectsSent, error); + proposed = SOSManifestCreateWithPatch(confirmed, missing, allExtra, error); + CFReleaseNull(allExtra); + } + + if (!SOSMessageSetManifests(message, local, confirmed, proposed, proposed, confirmed ? objectsSent : NULL, error)) + CFReleaseNull(message); + + CFReleaseNull(objectsSent); + + if (message) { + result = SOSMessageCreateData(message, SOSPeerNextSequenceNumber(peer), error); + } + + if (result) { + // Capture the peer in our block (SOSEnginePeerMessageSentBlock) + CFRetainSafe(peer); + *sent = Block_copy(^(bool success) { + dispatch_async(engine->queue, ^{ + if (success) { + if (!confirmed && !proposed) { + SOSPeerSetSendObjects(peer, true); + secnotice("engine", "SOSPeerSetSendObjects(true) L:%@", local); + } + SOSPeerAddLocalManifest(peer, local); + SOSPeerAddProposedManifest(peer, proposed); + secnoticeq("engine", "send %@ %@", SOSPeerGetID(peer), message); + } else { + secerror("%@ failed to send %@", SOSPeerGetID(peer), message); + } + CFReleaseSafe(peer); + CFReleaseSafe(local); + CFReleaseSafe(proposed); + CFReleaseSafe(message); + }); + }); + } else { + CFReleaseSafe(local); + CFReleaseSafe(proposed); + CFReleaseSafe(message); + } + CFReleaseNull(extra); + CFReleaseNull(missing); + if (error && *error) + secerror("%@ error in send: %@", SOSPeerGetID(peer), *error); + + return result; +} + +static CFDataRef SOSEngineCreateMessageToSyncToPeer_locked(SOSEngineRef engine, CFStringRef peerID, SOSEnginePeerMessageSentBlock *sentBlock, CFErrorRef *error) +{ + SOSPeerRef peer = SOSPeerCreateWithEngine(engine, peerID); + CFDataRef message = SOSEngineCreateMessage_locked(engine, peer, error, sentBlock); + CFReleaseSafe(peer); + + return message; +} + +bool SOSEngineHandleMessage(SOSEngineRef engine, CFStringRef peerID, + CFDataRef raw_message, CFErrorRef *error) +{ + __block bool result = false; + __block bool somethingChanged = false; + SOSMessageRef message = SOSMessageCreateWithData(kCFAllocatorDefault, raw_message, error); + result = message && SOSDataSourceWith(engine->dataSource, error, ^(SOSTransactionRef txn, bool *commit) { + result = SOSEngineHandleMessage_locked(engine, peerID, message, txn, commit, &somethingChanged, error); + }); + CFReleaseSafe(message); + if (somethingChanged) + SecKeychainChanged(false); + return result; +} + +// --- Called from off the queue, need to move to on the queue + +static void SOSEngineDoOnQueue(SOSEngineRef engine, dispatch_block_t action) +{ + dispatch_sync(engine->queue, action); +} + +void SOSEngineCircleChanged(SOSEngineRef engine, CFStringRef myPeerID, CFArrayRef trustedPeers, CFArrayRef untrustedPeers) { + SOSEngineDoOnQueue(engine, ^{ + SOSEngineCircleChanged_locked(engine, myPeerID, trustedPeers, untrustedPeers); + }); + + __block CFErrorRef localError = NULL; + SOSDataSourceWith(engine->dataSource, &localError, ^(SOSTransactionRef txn, bool *commit) { + SOSEngineDoOnQueue(engine, ^{ + *commit = SOSEngineSave(engine, txn, &localError); + }); + }); + if (localError) + secerror("failed to save engine state: %@", localError); + CFReleaseSafe(localError); + +} + +SOSManifestRef SOSEngineCopyManifest(SOSEngineRef engine, CFErrorRef *error) { + __block SOSManifestRef result = NULL; + SOSEngineDoOnQueue(engine, ^{ + result = SOSEngineCopyManifest_locked(engine, error); + }); + return result; +} + +bool SOSEngineUpdateLocalManifest(SOSEngineRef engine, SOSDataSourceTransactionSource source, struct SOSDigestVector *removals, struct SOSDigestVector *additions, CFErrorRef *error) { + __block bool result = true; + SOSManifestRef mfdel = SOSManifestCreateWithDigestVector(removals, error); + SOSManifestRef mfadd = SOSManifestCreateWithDigestVector(additions, error); + SOSEngineDoOnQueue(engine, ^{ + // Safe to run async if needed... + result = SOSEngineUpdateLocalManifest_locked(engine, source, mfdel, mfadd, error); + CFReleaseSafe(mfdel); + CFReleaseSafe(mfadd); + }); + return result; +} + +static bool SOSEngineSetCoderData_locked(SOSEngineRef engine, CFStringRef peer_id, CFDataRef data, CFErrorRef *error) { + CFMutableDictionaryRef state = NULL; + if (data) { + if (!engine->peerState) { + engine->peerState = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + state = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + } + else{ + state = (CFMutableDictionaryRef)CFDictionaryGetValue(engine->peerState, peer_id); + if(!state) + state = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + } + CFDictionarySetValue(state, kSOSPeerCoderKey, data); + CFDictionarySetValue(engine->peerState, peer_id, state); + + }else if (engine->peerState) { + if(CFDictionaryContainsKey(engine->peerState, peer_id)){ + CFMutableDictionaryRef state = (CFMutableDictionaryRef)CFDictionaryGetValue(engine->peerState, peer_id); + if(CFDictionaryContainsKey(state, kSOSPeerCoderKey)) + CFDictionaryRemoveValue(state, kSOSPeerCoderKey); + } + if (CFDictionaryGetCount(engine->peerState) == 0) { + CFReleaseNull(engine->peerState); + } + } + return true; +} + +bool SOSEngineSetCoderData(SOSEngineRef engine, CFStringRef peer_id, CFDataRef data, CFErrorRef *error) { + __block bool result = false; + + SOSDataSourceWith(engine->dataSource, error, ^(SOSTransactionRef txn, bool *commit) { + dispatch_sync(engine->queue, ^{ + result = SOSEngineSetCoderData_locked(engine, peer_id, data, error); + }); + }); + + return true; +} + +static CFDataRef SOSEngineGetCoderData_locked(SOSEngineRef engine, CFStringRef peer_id) { + // TODO: probably remove these secnotices + CFDataRef result = NULL; + CFMutableDictionaryRef peerState = NULL; + + if (!engine->peerState) + secdebug("engine", "No engine coderData"); + else + peerState = (CFMutableDictionaryRef)CFDictionaryGetValue(engine->peerState, peer_id); + if (!peerState) + secdebug("engine", "No peerState for peer %@", peer_id); + else{ + result = CFDictionaryGetValue(peerState, kSOSPeerCoderKey); + if(!result) + secdebug("engine", "No coder data for peer %@", peer_id); + } + return result; +} + + +CFDataRef SOSEngineGetCoderData(SOSEngineRef engine, CFStringRef peer_id) { + __block CFDataRef result = NULL; + SOSDataSourceWith(engine->dataSource, NULL, ^(SOSTransactionRef txn, bool *commit) { + dispatch_sync(engine->queue, ^{ + result = SOSEngineGetCoderData_locked(engine, peer_id); + }); + }); + + return result; +} + +// +// Peer state layout. WRONG! It's an array now +// The peer state is an array. +// The first element of the array is a dictionary with any number of keys and +// values in it (for future expansion) such as changing the digest size or type +// or remebering boolean flags for a peers sake. +// The next three are special in that they are manifest digests with special +// meaning and rules as to how they are treated (These are dynamically updated +// based on database activity so they have a fully history of all changes made +// to the local db. The first is the manifest representing the pendingObjects +// to send to the other peer. This is normally only ever appending to, and in +// particular with transactions originating from the Keychain API that affect +// syncable items will need to add the new objects digests to the pendingObjects list +// while adding the digests of any tombstones encountered to the extra list. + +CFMutableDictionaryRef SOSEngineGetPeerState(SOSEngineRef engine, CFStringRef peerID) { + CFMutableDictionaryRef peerState = NULL; + if (engine->peerState) + peerState = (CFMutableDictionaryRef)CFDictionaryGetValue(engine->peerState, peerID); + else + engine->peerState = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + if (!peerState) { + peerState = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionaryAddValue(engine->peerState, peerID, peerState); + CFReleaseSafe(peerState); + } + return peerState; +} + +CFDataRef SOSEngineCreateMessageToSyncToPeer(SOSEngineRef engine, CFStringRef peerID, SOSEnginePeerMessageSentBlock *sentBlock, CFErrorRef *error) { + __block CFDataRef result = NULL; + SOSEngineDoOnQueue(engine, ^{ + result = SOSEngineCreateMessageToSyncToPeer_locked(engine, peerID, sentBlock, error); + }); + return result; +} + +bool SOSEnginePeerDidConnect(SOSEngineRef engine, CFStringRef peerID, CFErrorRef *error) { + __block bool result = true; + result &= SOSDataSourceWith(engine->dataSource, error, ^(SOSTransactionRef txn, bool *commit) { + dispatch_sync(engine->queue, ^{ + SOSPeerRef peer = SOSPeerCreateWithEngine(engine, peerID); + if (!peer) { + result = SOSErrorCreate(kSOSErrorPeerNotFound, error, NULL, CFSTR("Engine has no peer for %@"), peerID); + } else { + SOSPeerDidConnect(peer); + result = SOSEngineSave(engine, txn, error); + CFReleaseSafe(peer); + } + }); + }); + + return result; +} diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSEngine.h b/Security/sec/SOSCircle/SecureObjectSync/SOSEngine.h new file mode 100644 index 00000000..b098d8ca --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSEngine.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/*! + @header SOSEngine.h - Manifest managent engine and decision making for + object syncing protocol. + */ + +#ifndef _SEC_SOSENGINE_H_ +#define _SEC_SOSENGINE_H_ + +#include +#include +#include + +__BEGIN_DECLS + +enum { + kSOSEngineInvalidMessageError = 1, + kSOSEngineInternalError = 2, +}; + +typedef struct __OpaqueSOSPeer *SOSPeerRef; + +typedef void (^SOSEnginePeerMessageSentBlock)(bool success); + +//Remove me! +void SOSEngineCircleChanged_locked(SOSEngineRef engine, CFStringRef myPeerID, CFArrayRef trustedPeers, CFArrayRef untrustedPeers); + + +// Return a new engine instance for a given data source. +SOSEngineRef SOSEngineCreate(SOSDataSourceRef dataSource, CFErrorRef *error); + +// Return a snapshot of the current manifest of the engines data source. +SOSManifestRef SOSEngineCopyManifest(SOSEngineRef engine, CFErrorRef *error); + +// Remove removals and add additions to the (cached) local manifest, and update all peers accordingly +bool SOSEngineUpdateLocalManifest(SOSEngineRef engine, SOSDataSourceTransactionSource source, struct SOSDigestVector *removals, struct SOSDigestVector *additions, CFErrorRef *error); + +// Store manifest indexed by it's own digest. Can be retrieved with SOSEngineGetManifestForDigest() +void SOSEngineAddManifest(SOSEngineRef engine, SOSManifestRef manifest); + +// Retrive a digest stored with SOSEngineAddManifest() +SOSManifestRef SOSEngineGetManifestForDigest(SOSEngineRef engine, CFDataRef digest); + +// Return the digest for a patched manifest (which is stored in the cache already). +CFDataRef SOSEnginePatchRecordAndCopyDigest(SOSEngineRef engine, SOSManifestRef base, SOSManifestRef removals, SOSManifestRef additions, CFErrorRef *error); + +//Set/Get coders +bool SOSEngineSetCoderData(SOSEngineRef engine, CFStringRef peer_id, CFDataRef data, CFErrorRef *error); +CFDataRef SOSEngineGetCoderData(SOSEngineRef engine, CFStringRef peer_id); + +//Get peer state +CFMutableDictionaryRef SOSEngineGetPeerState(SOSEngineRef engine, CFStringRef peerID); + +// Dispose of an engine when it's no longer needed. +void SOSEngineDispose(SOSEngineRef engine); + +// Handle incoming message from a remote peer. +bool SOSEngineHandleMessage(SOSEngineRef engine, CFStringRef peerID, + CFDataRef message, CFErrorRef *error); + +void SOSEngineCircleChanged(SOSEngineRef engine, CFStringRef myPeerID, CFArrayRef trustedPeers, CFArrayRef untrustedPeers); + +// Return a message to be sent for the current state. Returns NULL on errors, +// return a zero length CFDataRef if there is nothing to send. +// If *ProposedManifest is set the caller is responsible for updating their +// proposed manifest upon successful transmission of the message. +CFDataRef SOSEngineCreateMessageToSyncToPeer(SOSEngineRef engine, CFStringRef peerID, SOSEnginePeerMessageSentBlock *sentBlock, CFErrorRef *error); + +CFStringRef SOSEngineGetMyID(SOSEngineRef engine); +bool SOSEnginePeerDidConnect(SOSEngineRef engine, CFStringRef peerID, CFErrorRef *error); + +void logRawMessage(CFDataRef message, bool sending, uint64_t seqno); + +// TODO: TEMPORARY: Get the list of IDs for cleanup, this shouldn't be used instead transport should iterate KVS. +CFArrayRef SOSEngineGetPeerIDs(SOSEngineRef engine); + +__END_DECLS + +#endif /* !_SEC_SOSENGINE_H_ */ diff --git a/sec/SOSCircle/SecureObjectSync/SOSExports.exp-in b/Security/sec/SOSCircle/SecureObjectSync/SOSExports.exp-in similarity index 76% rename from sec/SOSCircle/SecureObjectSync/SOSExports.exp-in rename to Security/sec/SOSCircle/SecureObjectSync/SOSExports.exp-in index b3c970f2..58988ddc 100644 --- a/sec/SOSCircle/SecureObjectSync/SOSExports.exp-in +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSExports.exp-in @@ -14,6 +14,11 @@ _SOSCCGetLastDepartureReason _SOSCCGetStatusDescription _SOSCCPurgeUserCredentials _SOSCCCopyApplicantPeerInfo +_SOSCCCopyGenerationPeerInfo +_SOSCCCopyValidPeerPeerInfo +_SOSCCValidateUserPublic +_SOSCCCopyNotValidPeerPeerInfo +_SOSCCCopyRetirementPeerInfo _SOSCCCopyConcurringPeerPeerInfo _SOSCCCopyIncompatibilityInfo _SOSCCCopyPeerPeerInfo @@ -22,18 +27,22 @@ _SOSCCSetUserCredentials _SOSCCTryUserCredentials _SOSCCRemoveThisDeviceFromCircle _SOSCCBailFromCircle_BestEffort +_SOSCCSignedOut _SOSCCRequestToJoinCircle _SOSCCRequestToJoinCircleAfterRestore +_SOSCCRequestEnsureFreshParameters _SOSCCResetToEmpty _SOSCCResetToOffering _SOSCCThisDeviceIsInCircle _SOSCloudKeychainClearAll _SOSCloudKeychainPutObjectsInCloud -_SOSCloudKeychainRegisterKeysAndGet +_SOSCloudKeychainUpdateKeys _SOSCloudKeychainSetItemsChangedBlock _SOSPeerInfoGetPeerDeviceType _SOSPeerInfoGetPeerID _SOSPeerInfoGetPeerName +_SOSCCRequestDeviceID +_SOSCCSetDeviceID _SecCreateCFErrorWithXPCObject _SecCreateXPCObjectWithCFError @@ -41,9 +50,15 @@ _SOSCircleCreateFromData _SOSCloudKeychainGetAllObjectsFromCloud _SOSCloudKeychainGetObjectsFromCloud _SOSCloudKeychainSynchronizeAndWait + +_SOSCircleGenerationSetValue +_SOSCircleGenerationIncrement +_SOSCircleGetGenerationSint + _SOSKVSKeyGetKeyType _SOSCCProcessSyncWithAllPeers +_SOSCCProcessEnsurePeerRegistration #if !(TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) diff --git a/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.c b/Security/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.c similarity index 88% rename from sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.c rename to Security/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.c index b7b67829..a293c10f 100644 --- a/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.c +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.c @@ -1,10 +1,26 @@ -// -// SOSFullPeerInfo.c -// sec -// -// Created by Mitch Adler on 10/26/12. -// -// +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include @@ -123,6 +139,7 @@ exit: SOSFullPeerInfoRef SOSFullPeerInfoCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error, const uint8_t** der_p, const uint8_t *der_end) { SOSFullPeerInfoRef fpi = CFTypeAllocate(SOSFullPeerInfo, struct __OpaqueSOSFullPeerInfo, allocator); + SecKeyRef device_key = NULL; const uint8_t *sequence_end; @@ -132,12 +149,18 @@ SOSFullPeerInfoRef SOSFullPeerInfoCreateFromDER(CFAllocatorRef allocator, CFErro require_quiet(fpi->peer_info != NULL, fail); *der_p = der_decode_data(allocator, kCFPropertyListImmutable, &fpi->key_ref, error, *der_p, sequence_end); - require_quiet(*der_p != NULL, fail); + + OSStatus result = SecKeyFindWithPersistentRef(fpi->key_ref, &device_key); + require_quiet(result == errSecSuccess, fail); + require_quiet(*der_p != NULL, fail); + + CFReleaseNull(device_key); return fpi; fail: CFReleaseNull(fpi); + CFReleaseNull(device_key); return NULL; } @@ -223,6 +246,7 @@ bool SOSFullPeerInfoPurgePersistentKey(SOSFullPeerInfoRef fullPeer, CFErrorRef* NULL); SecItemDelete(query); CFReleaseNull(query); + CFReleaseNull(fullPeer->key_ref); return true; } @@ -236,7 +260,7 @@ SecKeyRef SOSFullPeerInfoCopyDeviceKey(SOSFullPeerInfoRef fullPeer, CFErrorRef* { SecKeyRef device_key = NULL; - require(fullPeer->key_ref, fail); + require(fullPeer && fullPeer->key_ref, fail); OSStatus result = SecKeyFindWithPersistentRef(fullPeer->key_ref, &device_key); diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.h b/Security/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.h new file mode 100644 index 00000000..38f582e6 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef _SOSFULLPEERINFO_H_ +#define _SOSFULLPEERINFO_H_ + +#include +#include +#include +#include + +__BEGIN_DECLS + +typedef struct __OpaqueSOSFullPeerInfo *SOSFullPeerInfoRef; + +enum { + kSOSFullPeerVersion = 1, +}; + +SOSFullPeerInfoRef SOSFullPeerInfoCreate(CFAllocatorRef allocator, CFDictionaryRef gestalt, SecKeyRef signingKey, CFErrorRef *error); + +SOSFullPeerInfoRef SOSFullPeerInfoCreateCloudIdentity(CFAllocatorRef allocator, SOSPeerInfoRef peer, CFErrorRef* error); + +SOSPeerInfoRef SOSFullPeerInfoGetPeerInfo(SOSFullPeerInfoRef fullPeer); +SecKeyRef SOSFullPeerInfoCopyDeviceKey(SOSFullPeerInfoRef fullPeer, CFErrorRef* error); + +bool SOSFullPeerInfoPurgePersistentKey(SOSFullPeerInfoRef peer, CFErrorRef* error); + +SOSPeerInfoRef SOSFullPeerInfoPromoteToRetiredAndCopy(SOSFullPeerInfoRef peer, CFErrorRef *error); + +bool SOSFullPeerInfoValidate(SOSFullPeerInfoRef peer, CFErrorRef* error); + +bool SOSFullPeerInfoUpdateGestalt(SOSFullPeerInfoRef peer, CFDictionaryRef gestalt, CFErrorRef* error); + +bool SOSFullPeerInfoPromoteToApplication(SOSFullPeerInfoRef fpi, SecKeyRef user_key, CFErrorRef *error); + +bool SOSFullPeerInfoUpgradeSignatures(SOSFullPeerInfoRef fpi, SecKeyRef user_key, CFErrorRef *error); + +// +// DER Import Export +// +SOSFullPeerInfoRef SOSFullPeerInfoCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error, + const uint8_t** der_p, const uint8_t *der_end); + +SOSFullPeerInfoRef SOSFullPeerInfoCreateFromData(CFAllocatorRef allocator, CFDataRef fullPeerData, CFErrorRef *error); + +size_t SOSFullPeerInfoGetDEREncodedSize(SOSFullPeerInfoRef peer, CFErrorRef *error); +uint8_t* SOSFullPeerInfoEncodeToDER(SOSFullPeerInfoRef peer, CFErrorRef* error, + const uint8_t* der, uint8_t* der_end); + +CFDataRef SOSFullPeerInfoCopyEncodedData(SOSFullPeerInfoRef peer, CFAllocatorRef allocator, CFErrorRef *error); + +__END_DECLS + +#endif diff --git a/sec/SOSCircle/SecureObjectSync/SOSInternal.c b/Security/sec/SOSCircle/SecureObjectSync/SOSInternal.c similarity index 77% rename from sec/SOSCircle/SecureObjectSync/SOSInternal.c rename to Security/sec/SOSCircle/SecureObjectSync/SOSInternal.c index 7311df80..5ccd08de 100644 --- a/sec/SOSCircle/SecureObjectSync/SOSInternal.c +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSInternal.c @@ -1,16 +1,31 @@ -// -// SOSInternal.c -// sec -// -// Created by Mitch Adler on 7/18/12. -// -// +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include #include #include -#include - +#include #include "utilities/SecCFError.h" #include "utilities/SecCFRelease.h" #include "utilities/SecCFWrappers.h" @@ -30,6 +45,17 @@ CFStringRef kSOSErrorDomain = CFSTR("com.apple.security.sos.error"); +bool SOSErrorCreate(CFIndex errorCode, CFErrorRef *error, CFDictionaryRef formatOptions, CFStringRef format, ...) { + if (!errorCode) return true; + if (error && !*error) { + va_list va; + va_start(va, format); + SecCFCreateErrorWithFormatAndArguments(errorCode, kSOSErrorDomain, NULL, error, formatOptions, format, va); + va_end(va); + } + return false; +} + bool SOSCreateError(CFIndex errorCode, CFStringRef descriptionString, CFErrorRef previousError, CFErrorRef *newError) { SOSCreateErrorWithFormat(errorCode, previousError, newError, NULL, CFSTR("%@"), descriptionString); return true; @@ -45,8 +71,7 @@ bool SOSCreateErrorWithFormat(CFIndex errorCode, CFErrorRef previousError, CFErr } bool SOSCreateErrorWithFormatAndArguments(CFIndex errorCode, CFErrorRef previousError, CFErrorRef *newError, - CFDictionaryRef formatOptions, CFStringRef format, va_list args) -{ + CFDictionaryRef formatOptions, CFStringRef format, va_list args) { SecCFCreateErrorWithFormatAndArguments(errorCode, kSOSErrorDomain, previousError, newError, formatOptions, format, args); return true; } @@ -87,7 +112,7 @@ OSStatus GeneratePermanentECPair(int keySize, SecKeyRef* public, SecKeyRef *full static CFStringRef SOSCircleCopyDescriptionFromData(CFDataRef data) { - CFErrorRef error; + CFErrorRef error = NULL; CFStringRef result = NULL; SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, data, &error); @@ -113,7 +138,7 @@ CFStringRef SOSChangesCopyDescription(CFDictionaryRef changes, bool is_sender) value_description = SOSCircleCopyDescriptionFromData(value_data); break; case kMessageKey: - value_description = SOSMessageCopyDescription(value_data); + value_description = CFCopyDescription(value_data); break; default: break; diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSInternal.h b/Security/sec/SOSCircle/SecureObjectSync/SOSInternal.h new file mode 100644 index 00000000..8defc8b9 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSInternal.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef _SOSINTERNAL_H_ +#define _SOSINTERNAL_H_ + +#include + +#include + +#include + +#include + +__BEGIN_DECLS + +enum { + // Public errors are first (See SOSCloudCircle) + + kSOSErrorFirstPrivateError = 1024, + + kSOSErrorAllocationFailure = 1024, + kSOSErrorEncodeFailure = 1025, + kSOSErrorNameMismatch = 1026, + kSOSErrorSendFailure = 1027, + kSOSErrorProcessingFailure = 1028, + kSOSErrorDecodeFailure = 1029, + + kSOSErrorAlreadyPeer = 1030, + kSOSErrorNotApplicant = 1031, + kSOSErrorPeerNotFound = 1032, + + kSOSErrorNoKey = 1033, + kSOSErrorBadKey = 1034, + kSOSErrorBadFormat = 1035, + kSOSErrorNoCircleName = 1036, + kSOSErrorNoCircle = 1037, + kSOSErrorBadSignature = 1038, + kSOSErrorReplay = 1039, + + kSOSErrorUnexpectedType = 1040, + + kSOSErrorUnsupported = 1041 +}; + +// Returns false unless errorCode is 0. +bool SOSErrorCreate(CFIndex errorCode, CFErrorRef *error, CFDictionaryRef formatOptions, CFStringRef descriptionString, ...); + +bool SOSCreateError(CFIndex errorCode, CFStringRef descriptionString, CFErrorRef previousError, CFErrorRef *newError); + +bool SOSCreateErrorWithFormat(CFIndex errorCode, CFErrorRef previousError, CFErrorRef *newError, + CFDictionaryRef formatOptions, CFStringRef formatString, ...) + CF_FORMAT_FUNCTION(5,6); + +bool SOSCreateErrorWithFormatAndArguments(CFIndex errorCode, CFErrorRef previousError, CFErrorRef *newError, + 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); +} + + +// +// Utility Functions +// +OSStatus GenerateECPair(int keySize, SecKeyRef* public, SecKeyRef *full); +OSStatus GeneratePermanentECPair(int keySize, SecKeyRef* public, SecKeyRef *full); + +CFStringRef SOSChangesCopyDescription(CFDictionaryRef changes, bool is_sender); + +CFStringRef SOSCopyIDOfKey(SecKeyRef key, CFErrorRef *error); + +// +// Der encoding accumulation +// +static inline bool accumulate_size(size_t *accumulator, size_t size) { + *accumulator += size; + return size != 0; +} + +__END_DECLS + +#endif diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSKVSKeys.c b/Security/sec/SOSCircle/SecureObjectSync/SOSKVSKeys.c new file mode 100644 index 00000000..73801711 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSKVSKeys.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include + + +void AppendCircleKeyName(CFMutableArrayRef array, CFStringRef name) { + CFStringRef circle_key = SOSCircleKeyCreateWithName(name, NULL); + CFArrayAppendValue(array, circle_key); + CFReleaseNull(circle_key); +} + +// +// +// MARK: KVS Keys +// TODO: Handle '|' and "¬" in other strings. +// +const CFStringRef kSOSKVSKeyParametersKey = CFSTR(">KeyParameters"); +const CFStringRef kSOSKVSInitialSyncKey = CFSTR("^InitialSync"); +const CFStringRef kSOSKVSAccountChangedKey = CFSTR("^AccountChanged"); + +const CFStringRef sWarningPrefix = CFSTR("!"); +const CFStringRef sAncientCirclePrefix = CFSTR("@"); +const CFStringRef sCirclePrefix = CFSTR("o"); +const CFStringRef sRetirementPrefix = CFSTR("-"); +const CFStringRef sCircleSeparator = CFSTR("|"); +const CFStringRef sFromToSeparator = CFSTR(":"); + +static CFStringRef copyStringEndingIn(CFMutableStringRef in, CFStringRef token) { + if(token == NULL) return CFStringCreateCopy(NULL, in); + CFRange tokenAt = CFStringFind(in, token, 0); + if(tokenAt.location == kCFNotFound) return NULL; + CFStringRef retval = CFStringCreateWithSubstring(NULL, in, CFRangeMake(0, tokenAt.location)); + CFStringDelete(in, CFRangeMake(0, tokenAt.location+1)); + return retval; +} + +SOSKVSKeyType SOSKVSKeyGetKeyTypeAndParse(CFStringRef key, CFStringRef *circle, CFStringRef *from, CFStringRef *to) +{ + SOSKVSKeyType retval = kUnknownKey; + + if(CFStringHasPrefix(key, sCirclePrefix)) retval = kCircleKey; + else if(CFStringHasPrefix(key, sRetirementPrefix)) retval = kRetirementKey; + else if(CFStringHasPrefix(key, kSOSKVSKeyParametersKey)) retval = kParametersKey; + else if(CFStringHasPrefix(key, kSOSKVSInitialSyncKey)) retval = kInitialSyncKey; + else if(CFStringHasPrefix(key, kSOSKVSAccountChangedKey)) retval = kAccountChangedKey; + else retval = kMessageKey; + + switch(retval) { + case kCircleKey: + if (circle) { + CFRange fromRange = CFRangeMake(1, CFStringGetLength(key)-1); + *circle = CFStringCreateWithSubstring(NULL, key, fromRange); + } + break; + case kMessageKey: { + CFStringRef mCircle = NULL; + CFStringRef mFrom = NULL; + CFStringRef mTo = NULL; + CFMutableStringRef keycopy = CFStringCreateMutableCopy(NULL, 128, key); + + if( ((mCircle = copyStringEndingIn(keycopy, sCircleSeparator)) != NULL) && + ((mFrom = copyStringEndingIn(keycopy, sFromToSeparator)) != NULL) && + (CFStringGetLength(mFrom) > 0) ) { + mTo = copyStringEndingIn(keycopy, NULL); + if (circle && mCircle) *circle = CFStringCreateCopy(NULL, mCircle); + if (from && mFrom) *from = CFStringCreateCopy(NULL, mFrom); + if (to && mTo) *to = CFStringCreateCopy(NULL, mTo); + } else { + retval = kUnknownKey; + } + CFReleaseNull(mCircle); + CFReleaseNull(mFrom); + CFReleaseNull(mTo); + CFReleaseNull(keycopy); + } + break; + case kRetirementKey: { + CFStringRef mCircle = NULL; + CFStringRef mPeer = NULL; + CFMutableStringRef keycopy = CFStringCreateMutableCopy(NULL, 128, key); + CFStringDelete(keycopy, CFRangeMake(0, 1)); + if( ((mCircle = copyStringEndingIn(keycopy, sCircleSeparator)) != NULL) && + ((mPeer = copyStringEndingIn(keycopy, NULL)) != NULL)) { + if (circle) *circle = CFStringCreateCopy(NULL, mCircle); + if (from) *from = CFStringCreateCopy(NULL, mPeer); + } else { + retval = kUnknownKey; + } + // TODO - Update our circle + CFReleaseNull(mCircle); + CFReleaseNull(mPeer); + CFReleaseNull(keycopy); + } + break; + case kAccountChangedKey: + case kParametersKey: + case kInitialSyncKey: + case kUnknownKey: + break; + } + + return retval; +} + + +SOSKVSKeyType SOSKVSKeyGetKeyType(CFStringRef key) +{ + return SOSKVSKeyGetKeyTypeAndParse(key, NULL, NULL, NULL); +} + +CFStringRef SOSCircleKeyCreateWithCircle(SOSCircleRef circle, CFErrorRef *error) +{ + return SOSCircleKeyCreateWithName(SOSCircleGetName(circle), error); +} + + +CFStringRef SOSCircleKeyCreateWithName(CFStringRef circleName, CFErrorRef *error) +{ + if(!circleName) return NULL; + return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), sCirclePrefix, circleName); +} + +CFStringRef SOSCircleKeyCopyCircleName(CFStringRef key, CFErrorRef *error) +{ + CFStringRef circleName = NULL; + + if (kCircleKey != SOSKVSKeyGetKeyTypeAndParse(key, &circleName, NULL, NULL)) { + SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find circle name in key '%@'"), key); + + CFReleaseNull(circleName); + } + + return circleName; +} + +CFStringRef SOSMessageKeyCopyCircleName(CFStringRef key, CFErrorRef *error) +{ + CFStringRef circleName = NULL; + + if (SOSKVSKeyGetKeyTypeAndParse(key, &circleName, NULL, NULL) != kMessageKey) { + SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find circle name in key '%@'"), key); + + CFReleaseNull(circleName); + } + return circleName; +} + +CFStringRef SOSMessageKeyCopyFromPeerName(CFStringRef messageKey, CFErrorRef *error) +{ + CFStringRef fromPeer = NULL; + + if (SOSKVSKeyGetKeyTypeAndParse(messageKey, NULL, &fromPeer, NULL) != kMessageKey) { + SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find from peer in key '%@'"), messageKey); + + CFReleaseNull(fromPeer); + } + return fromPeer; +} + +CFStringRef SOSMessageKeyCreateWithCircleNameAndPeerNames(CFStringRef circleName, CFStringRef from_peer_name, CFStringRef to_peer_name) +{ + return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@%@"), + circleName, sCircleSeparator, from_peer_name, sFromToSeparator, to_peer_name); +} + +CFStringRef SOSMessageKeyCreateWithCircleAndPeerNames(SOSCircleRef circle, CFStringRef from_peer_name, CFStringRef to_peer_name) +{ + return SOSMessageKeyCreateWithCircleNameAndPeerNames(SOSCircleGetName(circle), from_peer_name, to_peer_name); +} + +CFStringRef SOSMessageKeyCreateWithCircleAndPeerInfos(SOSCircleRef circle, SOSPeerInfoRef from_peer, SOSPeerInfoRef to_peer) +{ + return SOSMessageKeyCreateWithCircleAndPeerNames(circle, SOSPeerInfoGetPeerID(from_peer), SOSPeerInfoGetPeerID(to_peer)); +} + +CFStringRef SOSMessageKeyCreateFromPeerToTransport(SOSTransportMessageKVSRef transport, CFStringRef peer_name) { + CFErrorRef error = NULL; + SOSEngineRef engine = SOSTransportMessageGetEngine((SOSTransportMessageRef)transport); + + CFStringRef circleName = SOSTransportMessageKVSGetCircleName(transport); + CFStringRef my_id = SOSEngineGetMyID(engine); + + CFStringRef result = SOSMessageKeyCreateWithCircleNameAndPeerNames(circleName, peer_name, my_id); + CFReleaseSafe(error); + return result; +} + +CFStringRef SOSMessageKeyCreateFromTransportToPeer(SOSTransportMessageKVSRef transport, CFStringRef peer_name) { + CFErrorRef error = NULL; + SOSEngineRef engine = SOSTransportMessageGetEngine((SOSTransportMessageRef)transport); + + CFStringRef circleName = SOSTransportMessageKVSGetCircleName(transport); + CFStringRef my_id = SOSEngineGetMyID(engine); + + CFStringRef result = SOSMessageKeyCreateWithCircleNameAndPeerNames(circleName, my_id, peer_name); + CFReleaseSafe(error); + return result; +} + +CFStringRef SOSRetirementKeyCreateWithCircleNameAndPeer(CFStringRef circle_name, CFStringRef retirement_peer_name) +{ + return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@"), + sRetirementPrefix, circle_name, sCircleSeparator, retirement_peer_name); +} + +CFStringRef SOSRetirementKeyCreateWithCircleAndPeer(SOSCircleRef circle, CFStringRef retirement_peer_name) +{ + return SOSRetirementKeyCreateWithCircleNameAndPeer(SOSCircleGetName(circle), retirement_peer_name); +} + diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSKVSKeys.h b/Security/sec/SOSCircle/SecureObjectSync/SOSKVSKeys.h new file mode 100644 index 00000000..d79c4a81 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSKVSKeys.h @@ -0,0 +1,50 @@ + + +#ifndef SOSKVSKEYS_H +#define SOSKVSKEYS_H + +#include "SOSCircle.h" +#include +#include + +// +// MARK: Key formation +// + +typedef enum { + kCircleKey, + kMessageKey, + kParametersKey, + kInitialSyncKey, + kRetirementKey, + kAccountChangedKey, + kUnknownKey, +} SOSKVSKeyType; + +extern const CFStringRef kSOSKVSKeyParametersKey; +extern const CFStringRef kSOSKVSInitialSyncKey; +extern const CFStringRef kSOSKVSAccountChangedKey; +extern const CFStringRef sCirclePrefix; +extern const CFStringRef sRetirementPrefix; + + +SOSKVSKeyType SOSKVSKeyGetKeyType(CFStringRef key); +SOSKVSKeyType SOSKVSKeyGetKeyTypeAndParse(CFStringRef key, CFStringRef *circle, CFStringRef *from, CFStringRef *to); + +CFStringRef SOSCircleKeyCreateWithCircle(SOSCircleRef circle, CFErrorRef *error); +CFStringRef SOSCircleKeyCreateWithName(CFStringRef name, CFErrorRef *error); +CFStringRef SOSCircleKeyCopyCircleName(CFStringRef key, CFErrorRef *error); +CFStringRef SOSMessageKeyCreateWithCircleNameAndPeerNames(CFStringRef circleName, CFStringRef from_peer_name, CFStringRef to_peer_name); + +CFStringRef SOSMessageKeyCopyCircleName(CFStringRef key, CFErrorRef *error); +CFStringRef SOSMessageKeyCopyFromPeerName(CFStringRef messageKey, CFErrorRef *error); +CFStringRef SOSMessageKeyCreateWithCircleAndPeerNames(SOSCircleRef circle, CFStringRef from_peer_name, CFStringRef to_peer_name); +CFStringRef SOSMessageKeyCreateWithCircleAndPeerInfos(SOSCircleRef circle, SOSPeerInfoRef from_peer, SOSPeerInfoRef to_peer); + +CFStringRef SOSRetirementKeyCreateWithCircleNameAndPeer(CFStringRef circle_name, CFStringRef retirement_peer_name); +CFStringRef SOSRetirementKeyCreateWithCircleAndPeer(SOSCircleRef circle, CFStringRef retirement_peer_name); + +CFStringRef SOSMessageKeyCreateFromTransportToPeer(SOSTransportMessageKVSRef transport, CFStringRef peer_name); +CFStringRef SOSMessageKeyCreateFromPeerToTransport(SOSTransportMessageKVSRef transport, CFStringRef peer_name); + +#endif diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSManifest.c b/Security/sec/SOSCircle/SecureObjectSync/SOSManifest.c new file mode 100644 index 00000000..0e0aee28 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSManifest.c @@ -0,0 +1,228 @@ +/* + * 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@ + */ + + +/* + * SOSManifest.c - Manifest object and some manipulation around it + */ + +#include +#include +#include +#include + +#include // for kc_copy_sha1, which needs to move to utilities + +CFStringRef kSOSManifestErrorDomain = CFSTR("com.apple.security.sos.manifest.error"); + +/* SOSManifest implementation. */ +struct __OpaqueSOSManifest { + CFRuntimeBase _base; + CFDataRef digest; + CFDataRef digestVector; + struct SOSDigestVector dv; +}; + +CFGiblisWithCompareFor(SOSManifest) + +static void SOSManifestDestroy(CFTypeRef cf) { + SOSManifestRef mf = (SOSManifestRef)cf; + CFReleaseSafe(mf->digest); + CFReleaseSafe(mf->digestVector); +} + +static Boolean SOSManifestCompare(CFTypeRef cf1, CFTypeRef cf2) { + SOSManifestRef mf1 = (SOSManifestRef)cf1; + SOSManifestRef mf2 = (SOSManifestRef)cf2; + return CFEqualSafe(SOSManifestGetDigest(mf1, NULL), SOSManifestGetDigest(mf2, NULL)); +} + +SOSManifestRef SOSManifestCreateWithData(CFDataRef data, CFErrorRef *error) +{ + SOSManifestRef manifest = CFTypeAllocate(SOSManifest, struct __OpaqueSOSManifest, kCFAllocatorDefault); + if (!manifest) + SecCFCreateErrorWithFormat(kSOSManifestCreateError, kSOSManifestErrorDomain, NULL, error, NULL, CFSTR("Failed to create manifest")); + else if (data) + manifest->digestVector = CFDataCreateCopy(kCFAllocatorDefault, data); + else + manifest->digestVector = CFDataCreate(kCFAllocatorDefault, NULL, 0); + + assert(!manifest || manifest->digestVector != NULL); + return manifest; +} + +SOSManifestRef SOSManifestCreateWithBytes(const uint8_t *bytes, size_t len, + CFErrorRef *error) { + CFDataRef data = CFDataCreate(kCFAllocatorDefault, bytes, (CFIndex)len); + SOSManifestRef manifest = SOSManifestCreateWithData(data, error); + CFReleaseSafe(data); + return manifest; +} + +size_t SOSManifestGetSize(SOSManifestRef m) { + return m ? (size_t)CFDataGetLength(m->digestVector) : 0; +} + +size_t SOSManifestGetCount(SOSManifestRef m) { + return m ? SOSManifestGetSize(m) / SOSDigestSize : 0; +} + +const uint8_t *SOSManifestGetBytePtr(SOSManifestRef m) { + return m ? CFDataGetBytePtr(m->digestVector) : NULL; +} + +CFDataRef SOSManifestGetData(SOSManifestRef m) { + return m ? m->digestVector : NULL; +} + +const struct SOSDigestVector *SOSManifestGetDigestVector(SOSManifestRef manifest) { + if (!manifest) { + static struct SOSDigestVector nulldv = SOSDigestVectorInit; + return &nulldv; + } + manifest->dv.capacity = manifest->dv.count = SOSManifestGetCount(manifest); + manifest->dv.digest = (void *)SOSManifestGetBytePtr(manifest); + manifest->dv.unsorted = false; + return &manifest->dv; +} + +bool SOSManifestDiff(SOSManifestRef a, SOSManifestRef b, + SOSManifestRef *a_minus_b, SOSManifestRef *b_minus_a, + CFErrorRef *error) { + bool result = true; + struct SOSDigestVector dvab = SOSDigestVectorInit, dvba = SOSDigestVectorInit; + SOSDigestVectorDiffSorted(SOSManifestGetDigestVector(a), SOSManifestGetDigestVector(b), &dvab, &dvba); + if (a_minus_b) { + *a_minus_b = SOSManifestCreateWithDigestVector(&dvab, error); + if (!*a_minus_b) + result = false; + } + if (b_minus_a) { + *b_minus_a = SOSManifestCreateWithDigestVector(&dvba, error); + if (!*b_minus_a) + result = false; + } + SOSDigestVectorFree(&dvab); + SOSDigestVectorFree(&dvba); + return result; +} + + +SOSManifestRef SOSManifestCreateWithDigestVector(struct SOSDigestVector *dv, CFErrorRef *error) { + if (!dv) return NULL; + if (dv->unsorted) SOSDigestVectorSort(dv); + return SOSManifestCreateWithBytes((const uint8_t *)dv->digest, dv->count * SOSDigestSize, error); +} + +SOSManifestRef SOSManifestCreateWithPatch(SOSManifestRef base, + SOSManifestRef removals, + SOSManifestRef additions, + CFErrorRef *error) { + struct SOSDigestVector dvresult = SOSDigestVectorInit; + SOSManifestRef result; + if (SOSDigestVectorPatchSorted(SOSManifestGetDigestVector(base), SOSManifestGetDigestVector(removals), + SOSManifestGetDigestVector(additions), &dvresult, error)) { + result = SOSManifestCreateWithDigestVector(&dvresult, error); + } else { + result = NULL; + } + SOSDigestVectorFree(&dvresult); + return result; +} + +// This is the set of elements in m2, but not in m1. +SOSManifestRef SOSManifestCreateComplement(SOSManifestRef m1, + SOSManifestRef m2, + CFErrorRef *error) { + // m2 \ emptySet => m2 + if (SOSManifestGetCount(m1) == 0) + return CFRetainSafe(m2); + + struct SOSDigestVector dvresult = SOSDigestVectorInit; + SOSManifestRef result; + SOSDigestVectorComplementSorted(SOSManifestGetDigestVector(m1), SOSManifestGetDigestVector(m2), &dvresult); + result = SOSManifestCreateWithDigestVector(&dvresult, error); + SOSDigestVectorFree(&dvresult); + return result; +} + +SOSManifestRef SOSManifestCreateIntersection(SOSManifestRef m1, + SOSManifestRef m2, + CFErrorRef *error) { + struct SOSDigestVector dvresult = SOSDigestVectorInit; + SOSManifestRef result; + SOSDigestVectorIntersectSorted(SOSManifestGetDigestVector(m1), SOSManifestGetDigestVector(m2), &dvresult); + result = SOSManifestCreateWithDigestVector(&dvresult, error); + SOSDigestVectorFree(&dvresult); + return result; +} + +SOSManifestRef SOSManifestCreateUnion(SOSManifestRef m1, + SOSManifestRef m2, + CFErrorRef *error) { + struct SOSDigestVector dvresult = SOSDigestVectorInit; + SOSManifestRef result; + SOSDigestVectorUnionSorted(SOSManifestGetDigestVector(m1), SOSManifestGetDigestVector(m2), &dvresult); + result = SOSManifestCreateWithDigestVector(&dvresult, error); + SOSDigestVectorFree(&dvresult); + return result; +} + +void SOSManifestForEach(SOSManifestRef m, void(^block)(CFDataRef e, bool *stop)) { + CFDataRef e; + const uint8_t *p, *q; + bool stop = false; + for (p = SOSManifestGetBytePtr(m), q = p + SOSManifestGetSize(m); + !stop && p + SOSDigestSize <= q; p += SOSDigestSize) { + e = CFDataCreateWithBytesNoCopy(0, p, SOSDigestSize, kCFAllocatorNull); + if (e) { + block(e, &stop); + CFRelease(e); + } + } +} + +CFDataRef SOSManifestGetDigest(SOSManifestRef m, CFErrorRef *error) { + if (!m) return NULL; + if (!m->digest) + m->digest = kc_copy_sha1(SOSManifestGetSize(m), SOSManifestGetBytePtr(m), error); + return m->digest; +} + +static CFStringRef SOSManifestCopyDescription(CFTypeRef cf) { + SOSManifestRef m = (SOSManifestRef)cf; + CFMutableStringRef desc = CFStringCreateMutable(0, 0); + CFStringAppendFormat(desc, NULL, CFSTR("<[%zu]"), SOSManifestGetCount(m)); + __block size_t maxEntries = 8; + SOSManifestForEach(m, ^(CFDataRef e, bool *stop) { + const uint8_t *d = CFDataGetBytePtr(e); + CFStringAppendFormat(desc, NULL, CFSTR(" %02X%02X%02X%02X"), d[0], d[1], d[2], d[3]); + if (!--maxEntries) { + CFStringAppend(desc, CFSTR("...")); + *stop = true; + } + }); + CFStringAppend(desc, CFSTR(">")); + + return desc; +} diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSManifest.h b/Security/sec/SOSCircle/SecureObjectSync/SOSManifest.h new file mode 100644 index 00000000..32b88f49 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSManifest.h @@ -0,0 +1,101 @@ +/* + * 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@ + */ + + +/*! + @header SOSManifest.h + The functions provided in SOSTransport.h provide an interface to the + secure object syncing transport + */ + +#ifndef _SEC_SOSMANIFEST_H_ +#define _SEC_SOSMANIFEST_H_ + +#include +#include +#include + +__BEGIN_DECLS + +enum { + kSOSManifestUnsortedError = 1, + kSOSManifestCreateError = 2, +}; + +extern CFStringRef kSOSManifestErrorDomain; + +/* SOSObject. */ + +/* Forward declarations of SOS types. */ +typedef struct __OpaqueSOSManifest *SOSManifestRef; +struct SOSDigestVector; + +/* SOSManifest. */ +CFTypeID SOSManifestGetTypeID(void); + +SOSManifestRef SOSManifestCreateWithBytes(const uint8_t *bytes, size_t len, + CFErrorRef *error); +SOSManifestRef SOSManifestCreateWithDigestVector(struct SOSDigestVector *dv, CFErrorRef *error); +SOSManifestRef SOSManifestCreateWithData(CFDataRef data, CFErrorRef *error); + +size_t SOSManifestGetSize(SOSManifestRef m); + +size_t SOSManifestGetCount(SOSManifestRef m); + +const uint8_t *SOSManifestGetBytePtr(SOSManifestRef m); + +CFDataRef SOSManifestGetData(SOSManifestRef m); + +const struct SOSDigestVector *SOSManifestGetDigestVector(SOSManifestRef manifest); + +bool SOSManifestDiff(SOSManifestRef a, SOSManifestRef b, + SOSManifestRef *a_minus_b, SOSManifestRef *b_minus_a, + CFErrorRef *error); + +SOSManifestRef SOSManifestCreateWithPatch(SOSManifestRef base, + SOSManifestRef removals, + SOSManifestRef additions, + CFErrorRef *error); + +// Returns the set of elements in B that are not in A. +// This is the relative complement of A in B (B\A), sometimes written B − A +SOSManifestRef SOSManifestCreateComplement(SOSManifestRef A, + SOSManifestRef B, + CFErrorRef *error); + +SOSManifestRef SOSManifestCreateIntersection(SOSManifestRef m1, + SOSManifestRef m2, + CFErrorRef *error); + + +SOSManifestRef SOSManifestCreateUnion(SOSManifestRef m1, + SOSManifestRef m2, + CFErrorRef *error); + +void SOSManifestForEach(SOSManifestRef m, void(^block)(CFDataRef e, bool *stop)); + +CFDataRef SOSManifestGetDigest(SOSManifestRef m, CFErrorRef *error); + +__END_DECLS + +#endif /* !_SEC_SOSMANIFEST_H_ */ diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSMessage.c b/Security/sec/SOSCircle/SecureObjectSync/SOSMessage.c new file mode 100644 index 00000000..d5e69d1c --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSMessage.c @@ -0,0 +1,1183 @@ +/* + * 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@ + */ + + +/* + * SOSMessage.c - Creation and decoding of SOSMessage objects. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// TODO: This is a layer violation, we need a better way to do this +// Currently it's only used for logging. +#include + +#if defined(SOSMessageFormatSpecification) && 0 + +-- Secure Object Syncing Peer to Peer Message format ASN.1 definition +-- Everything MUST be DER encoded unless otherwise noted. These exceptions +-- Allow us to stream messages on a streamy network, without loading more +-- than one object into memory at once. + +SOSMessage := SEQUENCE { + CHOICE { + v0 V0-MESSAGE-BODY-CLASS + v2 SOSV2MessageBody + } +} + +-- v0 Message + +V0-MESSAGE-BODY-CLASS ::= CLASS + { + &messageType INTEGER (manifestDigest, manifest, manifestDeltaAndObjects) + &version INTEGER OPTIONAL default v0 + &Type + } + WITH SYNTAX {&Type IDENTIFIED BY &messageType} + +ManifestDigest ::= OCTECT STRING (length 20) + +Manifest ::= OCTECT STRING -- (length 20 * number of entries) + +manifestDigestBody ::= + { ManifestDigest IDENTIFIED BY {manifestDigest}} + +manifestBody ::= + { Manifest IDENTIFIED BY {manifest}} + + manifestDeltaAndObjectsBody ::= + { ManifestDeltaAndObjects IDENTIFIED BY {manifestDeltaAndObjects}} + +SOSV1MessageBody ::= MESSAGE-BODY-CLASS + +ManifestDeltaAndObjects ::= SEQUENCE { + manfestDigest ManifestDigest + removals Manifest + additions Manifest + addedObjects SEQUENCE OF SOSObject +} + +-- v2 Message + +SOSMessageBody := { + -- top level SEQUENCE may be Constructed, indefinite-length BER encoded + header SOSMessageHeader, + deltas [0] IMPLICIT SOSManifestDeltas OPTIONAL, + extensions [1] IMPLICIT SOSExtensions OPTIONAL, + objects [2] IMPLICIT SEQUENCE OF SOSObject OPTIONAL + -- [2] IMPLICIT SEQUENCE OF SOSObject may be Constructed, + -- indefinite-length BER encoded -- } + +SOSMessageHeader ::= SEQUENCE { + version [0] IMPLICIT SOSMessageVersion DEFAULT v2, + creationTime GeneralizedTime OPTIONAL, + -- When this message was created by the sender for tracking latency + sequenceNumber SOSSequenceNumber OPTIONAL, + -- Message Sequence Number for tracking packet loss in transport + digestTypes SOSDigestTypes OPTIONAL, + -- Determines the size and format of each SOSManifestDigest and the + -- elements of each SOSManifest. + -- We send the intersection our desired SOSDigestTypes and our peers + -- last received SOSDigestType. If we never received a message from our + -- peer we send our entire desired set and set the digestTypesProposed + -- messageFlag. + -- If the intersection is the empty set we fallback to sha1 + -- Each digest and manifest entry is constructed by appending the + -- agreed upon digests in the order they are listed in the DER encoded + -- digestTypes. + messageFlags BIT STRING { + getObjects (0), + joinRequest (1), + partial (2), + digestTypesProposed (3), + -- This is a partial update and might not contain accurate manifest deltas (check this against spec --mb), only objects + clearGetObjects (4), -- WIP mb ignore + -- Stop sending me objects for this delta update, I will send you mine instead if you give me a full manifest delta + didClearGetObjectsSinceLastDelta (5) -- WIP mb ignore + -- clearGetObjects was set during this delta update, do not + -- set it again (STICKY until either peer clears delta) -- } + skipHello (6) -- Respond with at least a manifest + senderDigest SOSManifestDigest, + -- The senders manifest digest at the time of sending this message. + baseDigest [0] IMPLICIT SOSManifestDigest, + -- What this message is based on, if it contains deltas. If missing we assume the empty set + proposedDigest [1] IMPLICIT SOSManifestDigest, + -- What the receiver should have after patching baseDigest with + -- additions and removals -- } + +SOSMessageVersion ::= INTEGER { v0(0), v2(2), v3(3) } + +SOSSequenceNumber ::= INTEGER + +-- Note this is not implemented in v2 it only supports sha1 +SOSDigestTypes ::= SEQUENCE { + messageFlags BIT STRING { + sha1(0) -- implied if SOSDigestTypes is not present + sha224(1) + sha256(2) + sha384(3) + sha512(4) + digestAlgorithms SET OF AlgorithmIdentifier + -- Same as AlgorithmIdentifier from X.509 -- } } + +SOSManifestDeltas ::= SEQUENCE { + removals SOSManifest + additions SOSManifest } + +SOSExtensions ::= SEQUENCE SIZE (1..MAX) OF SOSExtension + +SOSExtension ::= SEQUENCE { + extnID OBJECT IDENTIFIER, + critical BOOLEAN DEFAULT FALSE, + extnValue OCTET STRING } + +SOSManifest ::= OCTET STRING + -- DER encoding is sorted and ready to merge. + -- All SOSDigest entries in a SOSManifest /must/ be the same size + -- As the negotiated SOSManifestEntry. Se comment in SOSMessageBody + -- on digestTypes + +SOSManifestDigest ::= OCTET STRING + +SOSObject ::= SEQUENCE { + [0] conflict OCTECT STRING OPTIONAL + [1] change OCTECT STRING OPTIONAL + object SecDictionary } + +SecDictionary ::= SET of SecKVPair + +SecKVPair ::= SEQUENCE { + key UTF8String + value Value } + +SecValue ::= CHOICE { + bool Boolean + number INTEGER + string UTF8String + data OCTECT STRING + date GENERAL TIME + dictionary Object + array Array } + +SecArray ::= SEQUENCE of SecValue + +-- For reference: +AlgorithmIdentifier ::= SEQUENCE { +algorithm OBJECT IDENTIFIER, +parameters ANY DEFINED BY algorithm OPTIONAL } +-- contains a value of the type +-- registered for use with the +-- algorithm object identifier value + +#endif // defined(SOSMessageFormatSpecification) && 0 + + +#if 0 +static inline bool SecMallocOk(const void *ptr) { + if (ptr) return true; + + return false; +} +#endif +#if 0 +static void appendObjects(CFMutableStringRef desc, CFArrayRef objects) { + __block bool needComma = false; + CFArrayForEach(objects, ^(const void *value) { + if (needComma) + CFStringAppend(desc, CFSTR(",")); + else + needComma = true; + + SecItemServerAppendItemDescription(desc, value); + }); +} +#endif + + + +// +// MARK: SOSMessage implementation. +// + +// Legacy v1 message type numbers +enum SOSMessageType { + SOSManifestInvalidMessageType = 0, + SOSManifestDigestMessageType = 1, + SOSManifestMessageType = 2, + SOSManifestDeltaAndObjectsMessageType = 3, +}; + +struct __OpaqueSOSMessage { + CFRuntimeBase _base; + + CFDataRef der; + const uint8_t *objectsDer; + size_t objectsLen; + + CFDataRef senderDigest; + CFDataRef baseDigest; + CFDataRef proposedDigest; + SOSManifestRef removals; + SOSManifestRef additions; + + CFMutableArrayRef objects; + + SOSMessageFlags flags; + uint64_t sequenceNumber; + CFAbsoluteTime creationTime; + uint64_t version; // Message version (currently always 2) + bool indefiniteLength; // If set to true the top SEQUENCE and the OBJECTS SEQUENCE are written indefinite length. +}; + +CFGiblisWithCompareFor(SOSMessage) + +static Boolean SOSMessageCompare(CFTypeRef cf1, CFTypeRef cf2) { + SOSMessageRef M = (SOSMessageRef)cf1; + SOSMessageRef P = (SOSMessageRef)cf2; + if (M->flags != P->flags) return false; + if (M->sequenceNumber != P->sequenceNumber) return false; + if (M->creationTime != P->creationTime) return false; + //if (!CFEqualSafe(M->der, P->der)) return false; + if (!CFEqualSafe(M->senderDigest, P->senderDigest)) return false; + if (!CFEqualSafe(M->baseDigest, P->baseDigest)) return false; + if (!CFEqualSafe(M->proposedDigest, P->proposedDigest)) return false; + if (!CFEqualSafe(M->removals, P->removals)) return false; + if (!CFEqualSafe(M->additions, P->additions)) return false; + + // TODO Compare Objects if present. + + return true; +} + +static void SOSMessageDestroy(CFTypeRef cf) { + SOSMessageRef message = (SOSMessageRef)cf; + CFReleaseNull(message->der); + CFReleaseNull(message->senderDigest); + CFReleaseNull(message->baseDigest); + CFReleaseNull(message->proposedDigest); + CFReleaseNull(message->additions); + CFReleaseNull(message->removals); + CFReleaseNull(message->objects); +} + +// TODO: Remove this layer violation! +#include + +static uint64_t SOSMessageInferType(SOSMessageRef message, CFErrorRef *error); + +static CFStringRef SOSMessageCopyDescription(CFTypeRef cf) { + SOSMessageRef message = (SOSMessageRef)cf; + static const uint8_t zero[4] = {}; + const uint8_t *S = message->senderDigest ? CFDataGetBytePtr(message->senderDigest) : zero; + const uint8_t *B = message->baseDigest ? CFDataGetBytePtr(message->baseDigest) : zero; + const uint8_t *P = message->proposedDigest ? CFDataGetBytePtr(message->proposedDigest) : zero; + CFDateRef creationDate = CFDateCreate(CFGetAllocator(message), message->creationTime); + + CFMutableStringRef objects = CFStringCreateMutable(kCFAllocatorDefault, 0); + + // TODO: Remove this layer violation! + SOSDataSourceFactoryRef dsf = SecItemDataSourceFactoryGetDefault(); + SOSDataSourceRef ds = dsf->create_datasource(dsf, kSecAttrAccessibleWhenUnlocked, NULL); + + __block size_t maxEntries = 16; + CFStringAppendFormat(objects, NULL, CFSTR("{[%zu]"), SOSMessageCountObjects(message)); + SOSMessageWithSOSObjects(message, ds, NULL, ^(SOSObjectRef object, bool *stop) { + CFDataRef digest = SOSObjectCopyDigest(ds, object, NULL); + const uint8_t *O = CFDataGetBytePtr(digest); + CFStringAppendFormat(objects, NULL, CFSTR(" %02X%02X%02X%02X"), O[0],O[1],O[2],O[3]); + CFReleaseSafe(digest); + if (!--maxEntries) { + CFStringAppend(objects, CFSTR("...")); + *stop = true; + } + }); + CFStringAppend(objects, CFSTR("}")); + + CFStringRef desc; + if (message->version == 0) { + switch (SOSMessageInferType(message, NULL)) { + case SOSManifestInvalidMessageType: + desc = CFStringCreateWithFormat(CFGetAllocator(message), NULL, CFSTR(""), message->sequenceNumber); + break; + case SOSManifestDigestMessageType: + desc = CFStringCreateWithFormat(CFGetAllocator(message), NULL, CFSTR(""), message->sequenceNumber, S[0],S[1],S[2],S[3]); + break; + case SOSManifestMessageType: + desc = CFStringCreateWithFormat(CFGetAllocator(message), NULL, CFSTR(""), message->sequenceNumber, message->additions); + break; + case SOSManifestDeltaAndObjectsMessageType: + desc = CFStringCreateWithFormat(CFGetAllocator(message), NULL, CFSTR("sequenceNumber, + B[0],B[1],B[2],B[3], + message->removals, message->additions, + objects); + break; + } + } else { + desc = CFStringCreateWithFormat + (CFGetAllocator(message), NULL, CFSTR(""), + message->sequenceNumber, + creationDate, + S[0],S[1],S[2],S[3], + B[0],B[1],B[2],B[3], + P[0],P[1],P[2],P[3], + message->removals, message->additions, + objects, + (message->flags & kSOSMessageGetObjects) ? "G" : "g", + (message->flags & kSOSMessageJoinRequest) ? "J" : "j", + (message->flags & kSOSMessagePartial) ? "P" : "p", + (message->flags & kSOSMessageDigestTypesProposed) ? "D" : "d", + (message->flags & kSOSMessageClearGetObjects) ? "K" : "k", + (message->flags & kSOSMessageDidClearGetObjectsSinceLastDelta) ? "Z" : "z", + (message->flags & kSOSMessageSkipHello) ? "H" : "h"); + } + CFReleaseSafe(creationDate); + CFReleaseSafe(objects); + return desc; +} + +// +// MARK: SOSMessage encoding +// + +// Create an SOSMessage ready to be encoded. +SOSMessageRef SOSMessageCreate(CFAllocatorRef allocator, uint64_t version, CFErrorRef *error) { + SOSMessageRef message = CFTypeAllocate(SOSMessage, struct __OpaqueSOSMessage, allocator); + message->version = version; + return message; +} + +// TODO: Remove me this is for testing only, tests should use the real thing. +SOSMessageRef SOSMessageCreateWithManifests(CFAllocatorRef allocator, SOSManifestRef sender, + SOSManifestRef base, SOSManifestRef proposed, + bool includeManifestDeltas, CFErrorRef *error) { + SOSMessageRef message = SOSMessageCreate(allocator, kEngineMessageProtocolVersion, error); + if (!SOSMessageSetManifests(message, sender, base, proposed, includeManifestDeltas, NULL, error)) + CFReleaseNull(message); + return message; +} + +bool SOSMessageSetManifests(SOSMessageRef message, SOSManifestRef sender, + SOSManifestRef base, SOSManifestRef proposed, + bool includeManifestDeltas, SOSManifestRef objectsSent, + CFErrorRef *error) { + if (!message) return true; + bool ok = true; + // TODO: Check at v2 encoding time + // if (!sender) return (SOSMessageRef)SOSErrorCreate(kSOSErrorProcessingFailure, error, NULL, CFSTR("no sender manifest specified for SOSMessage")); + message->baseDigest = CFRetainSafe(SOSManifestGetDigest(base, NULL)); + message->proposedDigest = CFRetainSafe(SOSManifestGetDigest(proposed, NULL)); + message->senderDigest = CFRetainSafe(SOSManifestGetDigest(sender, NULL)); + if (includeManifestDeltas) { + SOSManifestRef additions = NULL; + ok = SOSManifestDiff(base, proposed, &message->removals, &additions, error); + if (message->version == 0) { + message->additions = additions; + } else { + message->additions = SOSManifestCreateComplement(objectsSent, additions, error); + CFReleaseSafe(additions); + } + } + return ok; +} + +void SOSMessageSetFlags(SOSMessageRef message, SOSMessageFlags flags) { + message->flags = flags; +} + +// Add an extension to this message +void SOSMessageAddExtension(SOSMessageRef message, CFDataRef oid, bool isCritical, CFDataRef extension) { + // TODO: Implement + secerror("not implemented yet!"); +} + +static bool SecMessageIsObjectValid(CFDataRef object, CFErrorRef *error) { + const uint8_t *der = CFDataGetBytePtr(object); + const uint8_t *der_end = der + CFDataGetLength(object); + ccder_tag tag = 0; + size_t len = 0; + der = ccder_decode_tag(&tag, der, der_end); + if (!der ) + return SOSErrorCreate(kSOSErrorBadFormat, error, NULL, CFSTR("Invalid DER, no tag found")); + if (tag == CCDER_EOL) + return SOSErrorCreate(kSOSErrorBadFormat, error, NULL, CFSTR("Object has EOL tag")); + der = ccder_decode_len(&len, der, der_end); + if (!der) + return SOSErrorCreate(kSOSErrorBadFormat, error, NULL, CFSTR("Object with tag %lu has no valid DER length"), tag); + der += len; + if (der_end - der) + return SOSErrorCreate(kSOSErrorBadFormat, error, NULL, CFSTR("Object has %td trailing unused bytes"), der_end - der); + return true; +} + +bool SOSMessageAppendObject(SOSMessageRef message, CFDataRef object, CFErrorRef *error) { + if (!SecMessageIsObjectValid(object, error)) return false; + if (!message->objects) + message->objects = CFArrayCreateMutableForCFTypes(CFGetAllocator(message)); + if (message->objects) + CFArrayAppendValue(message->objects, object); + return true; +} + +static CC_NONNULL_ALL +size_t ccder_sizeof_bit_string(cc_size n, const cc_unit *s) { + return ccder_sizeof(CCDER_BIT_STRING, ccn_sizeof(ccn_bitlen(n, s)) + 1); +} + +static CC_NONNULL_ALL +uint8_t *ccder_encode_bit_string(cc_size n, const cc_unit *s, const uint8_t *der, uint8_t *der_end) { + size_t bits = ccn_bitlen(n, s); + size_t out_size = ccn_sizeof(bits) + 1; + der_end = ccder_encode_body_nocopy(out_size, der, der_end); + if (der_end) + ccn_write_uint_padded(n, s, out_size, der_end); + return ccder_encode_tl(CCDER_BIT_STRING, out_size, der, der_end); +} + + +static CC_NONNULL_ALL +size_t der_sizeof_implicit_data(ccder_tag tag, CFDataRef data) { + if (!data) + return 0; + return ccder_sizeof_implicit_raw_octet_string(tag, CFDataGetLength(data)); +} + + +static CC_NONNULL_ALL +uint8_t *der_encode_implicit_data(ccder_tag tag, CFDataRef data, const uint8_t *der, uint8_t *der_end) { + if (!data) + return der_end; + return ccder_encode_implicit_raw_octet_string(tag, CFDataGetLength(data), CFDataGetBytePtr(data), der, der_end); +} + +static size_t der_sizeof_message_header(SOSMessageRef message, CFErrorRef *error) { + if (!message->senderDigest) { + // TODO: Create Error. + return 0; + } + cc_unit flags[1]; + flags[0] = (cc_unit)message->flags; // TODO Fix cast or something + + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, + der_sizeof_generalizedtime(message->creationTime, error) + + ccder_sizeof_uint64(message->sequenceNumber) + + ccder_sizeof_bit_string(array_size(flags), flags) + + der_sizeof_implicit_data(CCDER_OCTET_STRING, message->senderDigest) + + der_sizeof_implicit_data(0 | CCDER_CONTEXT_SPECIFIC, message->baseDigest) + + der_sizeof_implicit_data(1 | CCDER_CONTEXT_SPECIFIC, message->proposedDigest)); +} + +static uint8_t *der_encode_message_header(SOSMessageRef message, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { + if (!message->senderDigest) { + // TODO: Create Error. + return NULL; + } + cc_unit flags[1]; + flags[0] = (cc_unit)message->flags; // TODO Fix cast or something + return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + der_encode_generalizedtime(message->creationTime, error, der, + ccder_encode_uint64(message->sequenceNumber, der, + ccder_encode_bit_string(array_size(flags), flags, der, + der_encode_implicit_data(CCDER_OCTET_STRING, message->senderDigest, der, + der_encode_implicit_data(0 | CCDER_CONTEXT_SPECIFIC, message->baseDigest, der, + der_encode_implicit_data(1 | CCDER_CONTEXT_SPECIFIC, message->proposedDigest, der, der_end))))))); +} + +static size_t der_sizeof_deltas(SOSMessageRef message) { + if (!message->additions && !message->removals) return 0; + if (message->version == 0) { + return ccder_sizeof(CCDER_OCTET_STRING, SOSManifestGetSize(message->removals))+ + ccder_sizeof(CCDER_OCTET_STRING, SOSManifestGetSize(message->additions)); + } else { + return ccder_sizeof(0 | CCDER_CONTEXT_SPECIFIC | CCDER_CONSTRUCTED, + ccder_sizeof(CCDER_OCTET_STRING, SOSManifestGetSize(message->removals))+ + ccder_sizeof(CCDER_OCTET_STRING, SOSManifestGetSize(message->additions))); + } +} + +static uint8_t *der_encode_deltas(SOSMessageRef message, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { + if (!message->additions && !message->removals) return der_end; + if (message->version == 0) { + return der_encode_implicit_data(CCDER_OCTET_STRING, SOSManifestGetData(message->removals), der, + der_encode_implicit_data(CCDER_OCTET_STRING, SOSManifestGetData(message->additions), der, der_end)); + } else { + return ccder_encode_constructed_tl(0 | CCDER_CONTEXT_SPECIFIC | CCDER_CONSTRUCTED, der_end, der, + der_encode_implicit_data(CCDER_OCTET_STRING, SOSManifestGetData(message->removals), der, + der_encode_implicit_data(CCDER_OCTET_STRING, SOSManifestGetData(message->additions), der, der_end))); + } +} + +static size_t der_sizeof_extensions(SOSMessageRef message) { + // We don't support any yet. + return 0; +} + +static uint8_t *der_encode_extensions(SOSMessageRef message, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { + // We don't support any yet. + return der_end; +} + +static size_t der_sizeof_objects(SOSMessageRef message) { + size_t len = 0; + if (message->objects) { + CFDataRef data; + CFArrayForEachC(message->objects, data) { + len += (size_t)CFDataGetLength(data); + } + } else if (message->version != 0) + return 0; + + if (message->indefiniteLength) + return len + 4; + else + return ccder_sizeof(2 | CCDER_CONTEXT_SPECIFIC | CCDER_CONSTRUCTED, len); +} + +static uint8_t *der_encode_objects(SOSMessageRef message, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { + if (!message->objects && message->version != 0) return der_end; + const uint8_t *original_der_end = der_end; + if (message->indefiniteLength) + der_end = ccder_encode_tl(CCDER_EOL, 0, der, der_end); + + for (CFIndex position = (message->objects ? CFArrayGetCount(message->objects) : 0) - 1; position >= 0; --position) { + CFDataRef object = CFArrayGetValueAtIndex(message->objects, position); + der_end = ccder_encode_body(CFDataGetLength(object), CFDataGetBytePtr(object), der, der_end); + } + if (message->indefiniteLength) { + return ccder_encode_tag(2 | CCDER_CONTEXT_SPECIFIC | CCDER_CONSTRUCTED, der, + ccder_encode_len(0, der, der_end)); + } else { + ccder_tag otag = message->version == 0 ? CCDER_CONSTRUCTED_SEQUENCE : 2 | CCDER_CONTEXT_SPECIFIC | CCDER_CONSTRUCTED; + return ccder_encode_constructed_tl(otag, original_der_end, der, der_end); + } +} + +static size_t der_sizeof_v2_message(SOSMessageRef message, CFErrorRef *error) { + size_t body_size = (der_sizeof_message_header(message, error) + + der_sizeof_deltas(message) + + der_sizeof_extensions(message) + + der_sizeof_objects(message)); + if (message->indefiniteLength) + return body_size + 4; + else + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, body_size); +} + + +static uint8_t *der_encode_v2_message(SOSMessageRef message, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { + const uint8_t *original_der_end = der_end; + if (message->indefiniteLength) + der_end = ccder_encode_tl(CCDER_EOL, 0, der, der_end); + + der_end = der_encode_message_header(message, error, der, + der_encode_deltas(message, error, der, + der_encode_extensions(message, error, der, + der_encode_objects(message, error, der, der_end)))); + + if (message->indefiniteLength) { + return ccder_encode_tag(CCDER_CONSTRUCTED_SEQUENCE, der, + ccder_encode_len(0, der, der_end)); + } else { + return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, original_der_end, der, der_end); + } +} + +//------------------------------------------------------------------------------------------------------------------------------------ +// V1 support +//------------------------------------------------------------------------------------------------------------------------------------ + +/* ManifestDigest message */ +static size_t der_sizeof_manifest_digest_message(SOSMessageRef message, CFErrorRef *error) { + if (!message->senderDigest || CFDataGetLength(message->senderDigest) != SOSDigestSize) { + SOSErrorCreate(kSOSErrorProcessingFailure, error, NULL, CFSTR("digest length mismatch")); + return 0; + } + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, + (ccder_sizeof_uint64(SOSManifestDigestMessageType) + + ccder_sizeof_raw_octet_string(SOSDigestSize))); +} + +static uint8_t *der_encode_manifest_digest_message(SOSMessageRef message, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { + return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + ccder_encode_uint64(SOSManifestDigestMessageType, der, + ccder_encode_raw_octet_string(SOSDigestSize, CFDataGetBytePtr(message->senderDigest), der, der_end))); +} + +/* Manifest message */ +static size_t der_sizeof_manifest_message(SOSMessageRef message, CFErrorRef *error) { + if (!message->additions) { + SOSErrorCreate(kSOSErrorProcessingFailure, error, NULL, CFSTR("no manifest for manifest message")); + return 0; + } + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, + (ccder_sizeof_uint64(SOSManifestMessageType) + + der_sizeof_implicit_data(CCDER_OCTET_STRING, SOSManifestGetData(message->additions)))); +} + +static uint8_t *der_encode_manifest_message(SOSMessageRef message, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { + return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + ccder_encode_uint64(SOSManifestMessageType, der, + der_encode_implicit_data(CCDER_OCTET_STRING, SOSManifestGetData(message->additions), der, der_end))); +} + +/* ManifestDeltaAndObjects message */ +static size_t der_sizeof_manifest_and_objects_message(SOSMessageRef message, CFErrorRef *error) { + if (!message->baseDigest || CFDataGetLength(message->baseDigest) != SOSDigestSize) { + SOSErrorCreate(kSOSErrorProcessingFailure, error, NULL, CFSTR("digest length mismatch")); + return 0; + } + + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, + (ccder_sizeof_uint64(SOSManifestDeltaAndObjectsMessageType) + + ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, + (ccder_sizeof_raw_octet_string(SOSDigestSize) + + der_sizeof_implicit_data(CCDER_OCTET_STRING, SOSManifestGetData(message->removals)) + + der_sizeof_implicit_data(CCDER_OCTET_STRING, SOSManifestGetData(message->additions)) + + der_sizeof_objects(message))))); +} + +static uint8_t *der_encode_manifest_and_objects_message(SOSMessageRef message, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { + return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + ccder_encode_uint64(SOSManifestDeltaAndObjectsMessageType, der, + ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + ccder_encode_raw_octet_string(SOSDigestSize, CFDataGetBytePtr(message->baseDigest), der, + der_encode_implicit_data(CCDER_OCTET_STRING, SOSManifestGetData(message->removals), der, + der_encode_implicit_data(CCDER_OCTET_STRING, SOSManifestGetData(message->additions), der, + der_encode_objects(message, error, der, der_end))))))); +} + +static uint64_t SOSMessageInferType(SOSMessageRef message, CFErrorRef *error) { + if (message->baseDigest) { + // TODO: Assert that we don't have senderDigest or proposedDigest + if (SOSManifestGetCount(message->removals) || SOSManifestGetCount(message->additions) || SOSMessageCountObjects(message)) { + return SOSManifestDeltaAndObjectsMessageType; + } else { + // NOTE: If we force a SOSManifestDeltaAndObjectsMessageType instead then + // true v0 peers will overwrite their last objects message to us. However this + // implements the current v0 behaviour + return SOSManifestDigestMessageType; + } + } else if (message->additions) { + // TODO: Assert that we don't have senderDigest, proposedDigest, additions, removals or objects + return SOSManifestMessageType; + } else if (message->senderDigest) { + // TODO: Assert that we don't have proposedDigest, removals or objects + return SOSManifestDigestMessageType; + } + // TODO: Create error. + return SOSManifestInvalidMessageType; +} + +static size_t der_sizeof_message(SOSMessageRef message, uint64_t messageType, CFErrorRef *error) { + switch (messageType) { + case SOSManifestInvalidMessageType: + return der_sizeof_v2_message(message, error); + case SOSManifestDigestMessageType: + return der_sizeof_manifest_digest_message(message, error); + case SOSManifestMessageType: + return der_sizeof_manifest_message(message, error); + case SOSManifestDeltaAndObjectsMessageType: + return der_sizeof_manifest_and_objects_message(message, error); + } + return 0; +} + +static uint8_t *der_encode_message(SOSMessageRef message, uint64_t messageType, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { + switch (messageType) { + case SOSManifestInvalidMessageType: + return der_encode_v2_message(message, error, der, der_end); + case SOSManifestDigestMessageType: + return der_encode_manifest_digest_message(message, error, der, der_end); + case SOSManifestMessageType: + return der_encode_manifest_message(message, error, der, der_end); + case SOSManifestDeltaAndObjectsMessageType: + return der_encode_manifest_and_objects_message(message, error, der, der_end); + } + return der_end; +} + +// Encode an SOSMessage, calls addObject callback and appends returned objects +// one by one, until addObject returns NULL. +CFDataRef SOSMessageCreateData(SOSMessageRef message, uint64_t sequenceNumber, CFErrorRef *error) { + // Version 2 message have sequence numbers, version 0 messages do not. + uint64_t messageType = SOSManifestInvalidMessageType; + message->sequenceNumber = sequenceNumber; + if (message->version == 0) { + message->indefiniteLength = false; + messageType = SOSMessageInferType(message, error); + if (!messageType) { + // Propagate error + return NULL; + } + } else { + message->creationTime = floor(CFAbsoluteTimeGetCurrent()); + } + size_t der_size = der_sizeof_message(message, messageType, error); + CFMutableDataRef data = CFDataCreateMutable(NULL, der_size); + if (data == NULL) { + // TODO Error. + return NULL; + } + CFDataSetLength(data, der_size); + uint8_t *der_end = CFDataGetMutableBytePtr(data); + const uint8_t *der = der_end; + der_end += der_size; + + der_end = der_encode_message(message, messageType, error, der, der_end); + if (der != der_end) { + secwarning("internal error %td bytes unused in der buffer", der_end - der); + } + return data; +} + +// +// MARK: SOSMessage decoding +// + +#define CCBER_LEN_INDEFINITE ((size_t)-1) + +// Decode BER length field. Sets *lenp to ccber_indefinite_len if this is an indefinite length encoded object. +// Behaves like ccder_decode_len in every other way. +static CC_NONNULL((1, 3)) +const uint8_t *ccber_decode_len(size_t *lenp, const uint8_t *der, const uint8_t *der_end) { + if (der && der < der_end) { + if (*der == 0x80) { + der++; + *lenp = CCBER_LEN_INDEFINITE; + } + else + der = ccder_decode_len(lenp, der, der_end); + } + return der; +} + +static const uint8_t *der_decode_generalizedtime(CFAbsoluteTime *at, CFErrorRef *error, const uint8_t *der, const uint8_t *der_end) { + const uint8_t *times_end = NULL; + der = ccder_decode_constructed_tl(CCDER_GENERALIZED_TIME, ×_end, der, der_end); + der = der_decode_generalizedtime_body(at, error, der, times_end); + if (times_end != der) { + secwarning("internal error %td bytes unused in generalizedtime DER buffer", times_end - der); + } + return der; +} + +static const uint8_t *der_decode_optional_generalizedtime(CFAbsoluteTime *at, CFErrorRef *error, const uint8_t *der, const uint8_t *der_end) { + const uint8_t *times_end = der_decode_generalizedtime(at, error, der, der_end); + return times_end ? times_end : der; +} + +static CC_NONNULL((2, 4)) +const uint8_t *ccder_decode_implicit_uint64(ccder_tag expected_tag, uint64_t* r, const uint8_t *der, const uint8_t *der_end) { + size_t len; + der = ccder_decode_tl(expected_tag, &len, der, der_end); + if (der && len && (*der & 0x80) != 0x80) { + if (!r || (ccn_read_uint(ccn_nof_size(sizeof(*r)), (cc_unit*)r, len, der) >= 0)) + return der + len; + } + return NULL; +} + +static const uint8_t *ccder_decode_optional_implicit_uint64(ccder_tag expected_tag, uint64_t *value, const uint8_t *der, const uint8_t *der_end) { + const uint8_t *ui64_end = ccder_decode_implicit_uint64(expected_tag, value, der, der_end); + return ui64_end ? ui64_end : der; +} + + +static const uint8_t *ccder_decode_optional_uint64(uint64_t *value, const uint8_t *der, const uint8_t *der_end) { + const uint8_t *ui64_end = ccder_decode_uint64(value, der, der_end); + return ui64_end ? ui64_end : der; +} + +static const uint8_t *ccder_decode_digest_types(SOSMessageRef message, const uint8_t *der, const uint8_t *der_end) { + const uint8_t *dt_end; + der = ccder_decode_sequence_tl(&dt_end, der, der_end); + if (!der) return NULL; + // Skip over digestType body for now. + // TODO: Support DigestType + return dt_end; +} + +static const uint8_t *ccder_decode_optional_digest_types(SOSMessageRef message, const uint8_t *der, const uint8_t *der_end) { + const uint8_t *dt_end = ccder_decode_digest_types(message, der, der_end); + return dt_end ? dt_end : der; +} + +static const uint8_t *ccder_decode_bit_string(cc_size n, size_t *r_bitlen, cc_unit *r, const uint8_t *der, const uint8_t *der_end) { + size_t len; + const uint8_t *body = ccder_decode_tl(CCDER_BIT_STRING, &len, der, der_end); + if (!body || len < 1) + return NULL; + + if (r_bitlen) *r_bitlen = (len - 1) * 8 - (body[0] & 7); + ccn_read_uint(1, r, len - 1, body + 1); + return body + len; +} + +static const uint8_t *der_decode_implicit_data(ccder_tag expected_tag, CFDataRef *data, const uint8_t *der, const uint8_t *der_end) { + size_t len = 0; + der = ccder_decode_tl(expected_tag, &len, der, der_end); + if (der && data) { + *data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, der, len, kCFAllocatorNull); + if (*data) + der += len; + else + der = NULL; + } + return der; +} + +static const uint8_t *der_decode_optional_implicit_data(ccder_tag expected_tag, CFDataRef *data, const uint8_t *der, const uint8_t *der_end) { + const uint8_t *data_end = der_decode_implicit_data(expected_tag, data, der, der_end); + return data_end ? data_end : der; +} + +static const uint8_t *der_decode_deltas_body(SOSMessageRef message, CFErrorRef *error, const uint8_t *der, const uint8_t *der_end) { + CFDataRef removals = NULL, additions = NULL; + der = der_decode_implicit_data(CCDER_OCTET_STRING, &removals, der, der_end); + der = der_decode_implicit_data(CCDER_OCTET_STRING, &additions, der, der_end); + if (der) { + message->removals = SOSManifestCreateWithData(removals, error); + message->additions = SOSManifestCreateWithData(additions, error); + if (!message->removals || !message->additions) { + CFReleaseNull(message->removals); + CFReleaseNull(message->additions); + der = NULL; + } + } + CFReleaseSafe(removals); + CFReleaseSafe(additions); + + return der; +} + +static const uint8_t *der_decode_deltas(SOSMessageRef message, CFErrorRef *error, const uint8_t *der, const uint8_t *der_end) { + const uint8_t *deltas_end = NULL; + der = ccder_decode_constructed_tl(0 | CCDER_CONTEXT_SPECIFIC | CCDER_CONSTRUCTED, &deltas_end, der, der_end); + return der_decode_deltas_body(message, error, der, deltas_end); +} + +static const uint8_t *der_decode_optional_deltas(SOSMessageRef message, const uint8_t *der, const uint8_t *der_end) { + const uint8_t *seq_end = der_decode_deltas(message, NULL, der, der_end); + return seq_end ? seq_end : der; +} + +static const uint8_t *der_decode_extensions(SOSMessageRef message, CFErrorRef *error, const uint8_t *der, const uint8_t *der_end) { + const uint8_t *extensions_end; + der = ccder_decode_constructed_tl(1 | CCDER_CONTEXT_SPECIFIC | CCDER_CONSTRUCTED, &extensions_end, der, der_end); + if (!der) return NULL; + // Skip over extensions for now. + return extensions_end; +} + +static const uint8_t *der_decode_optional_extensions(SOSMessageRef message, CFErrorRef *error, const uint8_t *der, const uint8_t *der_end) { + const uint8_t *extensions_end = der_decode_extensions(message, NULL, der, der_end); + return extensions_end ? extensions_end : der; +} + +static const uint8_t *der_foreach_objects(size_t length, const uint8_t *der, const uint8_t *der_end, CFErrorRef *error, void(^withObject)(CFDataRef object, bool *stop)) { + bool stop = false; + ccder_tag tag; + // Look ahead at the tag + while (!stop && ccder_decode_tag(&tag, der, der_end) && tag != CCDER_EOL) { + const uint8_t *object_end = NULL; + if (!ccder_decode_constructed_tl(tag, &object_end, der, der_end)) { + SOSErrorCreate(kSOSErrorDecodeFailure, error, NULL, CFSTR("failed to decode object header")); + return NULL; + } + if (withObject) { + CFDataRef object = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, der, object_end - der, kCFAllocatorNull); + withObject(object, &stop); + CFReleaseSafe(object); + } + der = object_end; + } + if (length == CCBER_LEN_INDEFINITE) { + size_t len = 0; + der = ccder_decode_tl(CCDER_EOL, &len, der, der_end); + if (len != 0) { + secwarning("%td length ", der_end - der); + } + } + if (!stop && der != der_end) + secwarning("%td trailing bytes after objects DER", der_end - der); + + return der; +} + +static const uint8_t *der_decode_objects(SOSMessageRef message, CFErrorRef *error, const uint8_t *der, const uint8_t *der_end) { + ccder_tag tag = 0; + size_t objects_len = 0; + der = ccder_decode_tag(&tag, der, der_end); + if (tag != (2 | CCDER_CONTEXT_SPECIFIC | CCDER_CONSTRUCTED)) return NULL; + der = ccber_decode_len(&objects_len, der, der_end); + if (objects_len != CCBER_LEN_INDEFINITE && der_end - der != (ptrdiff_t)objects_len) { + secwarning("%td trailing bytes after SOSMessage DER", (der_end - der) - (ptrdiff_t)objects_len); + } + // Remember a pointer into message->der where objects starts. + message->objectsDer = der; + message->objectsLen = objects_len; + + return der + objects_len; +} + +static const uint8_t *der_decode_optional_objects(SOSMessageRef message, CFErrorRef *error, const uint8_t *der, const uint8_t *der_end) { + const uint8_t *seq_end = der_decode_objects(message, NULL, der, der_end); + return seq_end ? seq_end : der; +} + +#if 0 +// Move to ccder and possibly refactor ccder_decode_constructed_tl to call this. +#ifdef CCDER_DECODE_CONSTRUCTED_LEN_SPECIFIER +CCDER_DECODE_CONSTRUCTED_LEN_SPECIFIER +#endif +inline CC_NONNULL((1, 3)) +const uint8_t * +ccder_decode_constructed_len(const uint8_t **body_end, + const uint8_t *der, const uint8_t *der_end) { + size_t len; + der = ccder_decode_len(&len, der, der_end); + *body_end = der + len; + return der; +} +#endif + +static const uint8_t *der_decode_message_header(SOSMessageRef message, CFErrorRef *error, const uint8_t *der, const uint8_t *der_end) { + cc_unit flags[1] = {}; + der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &der_end, der, der_end); + message->version = 2; + der = ccder_decode_optional_implicit_uint64(0 | CCDER_CONTEXT_SPECIFIC, &message->version, der, der_end); + der = der_decode_optional_generalizedtime(&message->creationTime, error, der, der_end); + der = ccder_decode_optional_uint64(&message->sequenceNumber, der, der_end); + der = ccder_decode_optional_digest_types(message, der, der_end); + der = ccder_decode_bit_string(array_size(flags), NULL, flags, der, der_end); + message->flags = flags[0]; + + der = der_decode_implicit_data(CCDER_OCTET_STRING, &message->senderDigest, der, der_end); + der = der_decode_optional_implicit_data(0 | CCDER_CONTEXT_SPECIFIC, &message->baseDigest, der, der_end); + der = der_decode_optional_implicit_data(1 | CCDER_CONTEXT_SPECIFIC, &message->proposedDigest, der, der_end); + return der; +} + +static const uint8_t * +der_decode_manifest_and_objects_message(SOSMessageRef message, + CFErrorRef *error, const uint8_t *der, + const uint8_t *der_end) { + size_t objects_len = 0; + const uint8_t *body_end; + der = ccder_decode_sequence_tl(&body_end, der, der_end); + if (body_end != der_end) { + SOSErrorCreate(kSOSEngineInvalidMessageError, error, NULL, CFSTR("Trailing garbage at end of message")); + return NULL; + } + der = der_decode_implicit_data(CCDER_OCTET_STRING, &message->baseDigest, der, body_end); + der = der_decode_deltas_body(message, error, der, body_end); + // Remember a pointer into message->der where objects starts. + der = message->objectsDer = ccder_decode_tl(CCDER_CONSTRUCTED_SEQUENCE, &objects_len, der, body_end); + message->objectsLen = objects_len; + + return der ? der + objects_len : NULL; +} + +static const uint8_t *der_decode_v0_message_body(SOSMessageRef message, CFErrorRef *error, const uint8_t *der, const uint8_t *der_end) { + uint64_t messageType = 0; + der = ccder_decode_uint64(&messageType, der, der_end); + if (der) switch (messageType) { + case SOSManifestDigestMessageType: + { + der = der_decode_implicit_data(CCDER_OCTET_STRING, &message->senderDigest, der, der_end); + break; + } + case SOSManifestMessageType: + { + CFDataRef manifestBody = NULL; + der = der_decode_implicit_data(CCDER_OCTET_STRING, &manifestBody, der, der_end); + if (!der) return NULL; + if (der != der_end) { + secwarning("%td trailing bytes after deltas DER", der_end - der); + } + message->additions = SOSManifestCreateWithData(manifestBody, error); + CFReleaseSafe(manifestBody); + break; + } + case SOSManifestDeltaAndObjectsMessageType: + { + der = der_decode_manifest_and_objects_message(message, error, der, der_end); + break; + } + default: + SOSErrorCreate(kSOSEngineInvalidMessageError, error, NULL, CFSTR("Invalid message type %llu"), messageType); + break; + } + return der; +} + +static const uint8_t *der_decode_message(SOSMessageRef message, CFErrorRef *error, const uint8_t *der, const uint8_t *der_end) { + ccder_tag tag = 0; + size_t body_len = 0; + + der = ccder_decode_tag(&tag, der, der_end); + if (tag != CCDER_CONSTRUCTED_SEQUENCE) return NULL; + der = ccber_decode_len(&body_len, der, der_end); + if (der && body_len && body_len != CCBER_LEN_INDEFINITE && (der_end - der) != (ptrdiff_t)body_len) { + secwarning("%td trailing bytes after SOSMessage DER", (der_end - der) - (ptrdiff_t)body_len); + der_end = der + body_len; + } + + if (ccder_decode_tag(&tag, der, der_end)) switch (tag) { + case CCDER_INTEGER: // v0 + if (body_len == CCBER_LEN_INDEFINITE) + der = NULL; // Not supported for v0 messages + else + der = der_decode_v0_message_body(message, error, der, der_end); + break; + case CCDER_CONSTRUCTED_SEQUENCE: //v2 + der = der_decode_message_header(message, error, der, der_end); + der = der_decode_optional_deltas(message, der, der_end); + der = der_decode_optional_extensions(message, error, der, der_end); + der = der_decode_optional_objects(message, error, der, der_end); + break; + } + return der; +} + +// Decode a SOSMessage +SOSMessageRef SOSMessageCreateWithData(CFAllocatorRef allocator, CFDataRef derData, CFErrorRef *error) { + if (!derData) + return (SOSMessageRef)SOSErrorCreate(kSOSErrorDecodeFailure, error, NULL, CFSTR("NULL data => no SOSMessage")); + SOSMessageRef message = CFTypeAllocate(SOSMessage, struct __OpaqueSOSMessage, allocator); + if (!message) + return (SOSMessageRef)SOSErrorCreate(kSOSErrorAllocationFailure, error, NULL, CFSTR("failed to alloc SOSMessage")); + message->der = CFRetainSafe(derData); + const uint8_t *der = CFDataGetBytePtr(derData); + const uint8_t *der_end = der + CFDataGetLength(derData); + der = der_decode_message(message, error, der, der_end); + if (der != der_end) { + if (error && !*error) + SOSErrorCreate(kSOSErrorDecodeFailure, error, NULL, CFSTR("SOSMessage DER decoding failure %td bytes left"), der_end - der); + return CFReleaseSafe(message); + } + return message; +} + +// Read values from a decoded messgage + +CFDataRef SOSMessageGetBaseDigest(SOSMessageRef message) { + return message->baseDigest; +} + +CFDataRef SOSMessageGetProposedDigest(SOSMessageRef message) { + return message->proposedDigest; +} + +CFDataRef SOSMessageGetSenderDigest(SOSMessageRef message) { + return message->senderDigest; +} + +SOSMessageFlags SOSMessageGetFlags(SOSMessageRef message) { + return message->flags; +} + +uint64_t SOSMessageGetSequenceNumber(SOSMessageRef message) { + return message->sequenceNumber; +} + +SOSManifestRef SOSMessageGetRemovals(SOSMessageRef message) { + return message->removals; +} + +SOSManifestRef SOSMessageGetAdditions(SOSMessageRef message) { + return message->additions; +} + +// Iterate though the extensions in a decoded SOSMessage. If criticalOnly is +// true all non critical extensions are skipped. +void SOSMessageWithExtensions(SOSMessageRef message, bool criticalOnly, void(^withExtension)(CFDataRef oid, bool isCritical, CFDataRef extension, bool *stop)) { + // TODO +} + +size_t SOSMessageCountObjects(SOSMessageRef message) { + if (message->objects) + return CFArrayGetCount(message->objects); + if (!message->objectsDer) + return 0; + const uint8_t *der = CFDataGetBytePtr(message->der); + const uint8_t *der_end = der + CFDataGetLength(message->der); + __block size_t count = 0; + der_foreach_objects(message->objectsLen, message->objectsDer, der_end, NULL, ^(CFDataRef object, bool *stop){ ++count; }); + return count; +} + +// Iterate though the objects in a decoded SOSMessage. +bool SOSMessageWithObjects(SOSMessageRef message, CFErrorRef *error, + void(^withObject)(CFDataRef object, bool *stop)) { + if (message->objects) { + CFDataRef object; + CFArrayForEachC(message->objects, object) { + bool stop = false; + withObject(object, &stop); + if (stop) + break; + } + return true; + } + if (!message->objectsDer) + return true; + const uint8_t *der = CFDataGetBytePtr(message->der); + const uint8_t *der_end = der + CFDataGetLength(message->der); + return der_foreach_objects(message->objectsLen, message->objectsDer, der_end, error, withObject); +} + +bool SOSMessageWithSOSObjects(SOSMessageRef message, SOSDataSourceRef dataSource, CFErrorRef *error, + void(^withObject)(SOSObjectRef object, bool *stop)) { + return SOSMessageWithObjects(message, error, ^(CFDataRef object, bool *stop) { + CFDictionaryRef plist = NULL; + const uint8_t *der = CFDataGetBytePtr(object); + const uint8_t *der_end = der + CFDataGetLength(object); + der = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &plist, error, der, der_end); + if (der) { + SOSObjectRef peersObject = SOSObjectCreateWithPropertyList(dataSource, plist, error); + withObject(peersObject, stop); + CFReleaseSafe(peersObject); + } + CFReleaseSafe(plist); + }); +} diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSMessage.h b/Security/sec/SOSCircle/SecureObjectSync/SOSMessage.h new file mode 100644 index 00000000..82a21459 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSMessage.h @@ -0,0 +1,137 @@ +/* + * 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@ + */ + + +/*! + @header SOSMessage.h + This provides interfaces to the encoding and decoding of peer to peer + messages in the Secure Object Syncing protocol. + SOSMessageRef is a CFTypeRef. + */ + +#ifndef _SEC_SOSMESSAGE_H_ +#define _SEC_SOSMESSAGE_H_ + +#include +#include + +__BEGIN_DECLS + +enum SOSMessageFlags { + kSOSMessageGetObjects = (0), + kSOSMessageJoinRequest = (1), + kSOSMessagePartial = (2), + kSOSMessageDigestTypesProposed = (3), + kSOSMessageClearGetObjects = (4), + kSOSMessageDidClearGetObjectsSinceLastDelta = (5), + kSOSMessageSkipHello = (6), +}; +typedef uint64_t SOSMessageFlags; + +enum SOSDigestTypes { + kSOSDigestTypeSHA1 = (0), + kSOSDigestTypeDefault = kSOSDigestTypeSHA1, + kSOSDigestTypeSHA224 = (1), + kSOSDigestTypeSHA256 = (2), + kSOSDigestTypeSHA384 = (3), + kSOSDigestTypeSHA512 = (4), +}; +typedef uint64_t SOSDigestTypes; + +/* SOSMessage interface. */ +typedef struct __OpaqueSOSMessage *SOSMessageRef; + +//#define kSOSMessageMaxObjectsSize (8192) +#define kSOSMessageMaxObjectsSize (65536) + +#define kEngineMessageProtocolVersion 2 + +// +// MARK: SOSMessage encoding +// + +// Create an SOSMessage ready to be encoded. +SOSMessageRef SOSMessageCreate(CFAllocatorRef allocator, uint64_t version, CFErrorRef *error); + +SOSMessageRef SOSMessageCreateWithManifests(CFAllocatorRef allocator, SOSManifestRef sender, + SOSManifestRef base, SOSManifestRef proposed, + bool includeManifestDeltas, CFErrorRef *error); + +bool SOSMessageSetManifests(SOSMessageRef message, SOSManifestRef sender, + SOSManifestRef base, SOSManifestRef proposed, + bool includeManifestDeltas, SOSManifestRef objectsSent, + CFErrorRef *error); + + +// Add an extension to this message +void SOSMessageAddExtension(SOSMessageRef message, CFDataRef oid, bool isCritical, CFDataRef extension); + +bool SOSMessageAppendObject(SOSMessageRef message, CFDataRef object, CFErrorRef *error); + +void SOSMessageSetFlags(SOSMessageRef message, SOSMessageFlags flags); + +// Encode an SOSMessage, calls addObject callback and appends returned objects +// one by one, until addObject returns NULL. +CFDataRef SOSMessageCreateData(SOSMessageRef message, uint64_t sequenceNumber, CFErrorRef *error); + +// +// MARK: SOSMessage decoding +// + +// Decode a SOSMessage +SOSMessageRef SOSMessageCreateWithData(CFAllocatorRef allocator, CFDataRef derData, CFErrorRef *error); + +// Read values from a decoded messgage + +CFDataRef SOSMessageGetBaseDigest(SOSMessageRef message); + +CFDataRef SOSMessageGetProposedDigest(SOSMessageRef message); + +CFDataRef SOSMessageGetSenderDigest(SOSMessageRef message); + +SOSMessageFlags SOSMessageGetFlags(SOSMessageRef message); + +uint64_t SOSMessageGetSequenceNumber(SOSMessageRef message); + +SOSManifestRef SOSMessageGetRemovals(SOSMessageRef message); + +SOSManifestRef SOSMessageGetAdditions(SOSMessageRef message); + +// Iterate though the extensions in a decoded SOSMessage. If criticalOnly is +// true all non critical extensions are skipped. +void SOSMessageWithExtensions(SOSMessageRef message, bool criticalOnly, + void(^withExtension)(CFDataRef oid, bool isCritical, + CFDataRef extension, bool *stop)); + +size_t SOSMessageCountObjects(SOSMessageRef message); + +// Iterate though the objects in a decoded SOSMessage. +bool SOSMessageWithObjects(SOSMessageRef message, CFErrorRef *error, + void(^withObject)(CFDataRef object, bool *stop)); + +bool SOSMessageWithSOSObjects(SOSMessageRef message, SOSDataSourceRef dataSource, CFErrorRef *error, + void(^withObject)(SOSObjectRef object, bool *stop)); + +__END_DECLS + +#endif /* _SEC_SOSMESSAGE_H_ */ diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSPeer.c b/Security/sec/SOSCircle/SecureObjectSync/SOSPeer.c new file mode 100644 index 00000000..07f10cb7 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSPeer.c @@ -0,0 +1,498 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* + * SOSPeer.c - Implementation of a secure object syncing peer + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include + +// +// 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"); + +// +// MARK: SOSPeerState (dictionary keys) +// + +// PeerState dictionary keys +static CFStringRef kSOSPeerSendObjectsKey = CFSTR("send-objects"); // bool +static CFStringRef kSOSPeerMustSendMessageKey = CFSTR("must-send"); // bool +static CFStringRef kSOSPeerPendingObjectsKey = CFSTR("pending-objects"); // digest +static CFStringRef kSOSPeerPendingDeletesKey = CFSTR("pending-deletes"); // digest +static CFStringRef kSOSPeerConfirmedManifestKey = CFSTR("confirmed-manifest"); //digest +static CFStringRef kSOSPeerProposedManifestKey = CFSTR("pending-manifest"); // array of digests +static CFStringRef kSOSPeerLocalManifestKey = CFSTR("local-manifest"); // array of digests +static CFStringRef kSOSPeerVersionKey = CFSTR("version"); // int + +enum { + kSOSPeerMaxManifestWindowDepth = 4 +}; + +// +// MARK: - SOSPeer +// + +struct __OpaqueSOSPeer { + CFRuntimeBase _base; + SOSEngineRef engine; + + SOSCoderRef coder; + CFStringRef peer_id; + CFIndex version; + uint64_t sequenceNumber; + bool mustSendMessage; +}; + +CFGiblisWithCompareFor(SOSPeer) + +static CFStringRef SOSManifestCreateOptionalDescriptionWithLabel(SOSManifestRef manifest, CFStringRef label) { + if (!manifest) return CFSTR(" - "); + //return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@[%zu]"), label, SOSManifestGetCount(manifest)); + return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR(" %@%@"), label, manifest); +} + +static CFMutableDictionaryRef SOSPeerGetState(SOSPeerRef peer) { + return SOSEngineGetPeerState(peer->engine, peer->peer_id); +} + +static CFStringRef SOSPeerCreateManifestArrayDescriptionWithKey(SOSPeerRef peer, CFStringRef key, CFStringRef label) { + CFMutableArrayRef digests = (CFMutableArrayRef)CFDictionaryGetValue(SOSPeerGetState(peer), key); + CFIndex count = digests ? CFArrayGetCount(digests) : 0; + if (count == 0) return CFSTR(" - "); + CFDataRef digest = CFArrayGetValueAtIndex(digests, 0); + return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR(" %@[%" PRIdCFIndex "]%@"), label, count, SOSEngineGetManifestForDigest(peer->engine, digest)); +} + +static CFStringRef SOSPeerCopyDescription(CFTypeRef cf) { + SOSPeerRef peer = (SOSPeerRef)cf; + if(peer){ + CFStringRef po = SOSManifestCreateOptionalDescriptionWithLabel(SOSPeerGetPendingObjects(peer), CFSTR("O")); + CFStringRef de = SOSManifestCreateOptionalDescriptionWithLabel(SOSPeerGetPendingDeletes(peer), CFSTR("D")); + CFStringRef co = SOSManifestCreateOptionalDescriptionWithLabel(SOSPeerGetConfirmedManifest(peer), CFSTR("C")); + CFStringRef pe = SOSPeerCreateManifestArrayDescriptionWithKey(peer, kSOSPeerProposedManifestKey, CFSTR("P")); + CFStringRef lo = SOSPeerCreateManifestArrayDescriptionWithKey(peer, kSOSPeerLocalManifestKey, CFSTR("L")); + CFStringRef desc = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("<%@ %s%s%@%@%@%@%@>"), + SOSPeerGetID(peer), + SOSPeerMustSendMessage(peer) ? "F" : "f", + SOSPeerSendObjects(peer) ? "S" : "s", + po, de, co, pe, lo); + CFReleaseSafe(lo); + CFReleaseSafe(pe); + CFReleaseSafe(co); + CFReleaseSafe(de); + CFReleaseSafe(po); + + return desc; + } + else + return CFSTR("NULL"); +} + +static Boolean SOSPeerCompare(CFTypeRef cfA, CFTypeRef cfB) +{ + SOSPeerRef peerA = (SOSPeerRef)cfA, peerB = (SOSPeerRef)cfB; + // Use mainly to see if peerB is actually this device (peerA) + return CFStringCompare(SOSPeerGetID(peerA), SOSPeerGetID(peerB), 0) == kCFCompareEqualTo; +} + +static CFMutableArrayRef SOSPeerGetDigestsWithKey(SOSPeerRef peer, CFStringRef key) { + CFMutableDictionaryRef peerState = SOSPeerGetState(peer); + CFMutableArrayRef digests = (CFMutableArrayRef)CFDictionaryGetValue(peerState, key); + if (!digests) { + digests = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionarySetValue(peerState, key, digests); + CFReleaseSafe(digests); + } + return digests; +} + +static void SOSPeerStateSetDigestForKey(CFMutableDictionaryRef peerState, CFStringRef key, CFDataRef digest) { + if (digest) + CFDictionarySetValue(peerState, key, digest); + else + CFDictionaryRemoveValue(peerState, key); +} + +static void SOSPeerAddManifestWithKey(SOSPeerRef peer, CFStringRef key, SOSManifestRef manifest) { + CFMutableArrayRef digests = SOSPeerGetDigestsWithKey(peer, key); + CFDataRef digest = SOSManifestGetDigest(manifest, NULL); + if (digest) { + CFIndex count = CFArrayGetCount(digests); + SOSEngineAddManifest(peer->engine, manifest); + CFIndex ixOfDigest = CFArrayGetFirstIndexOfValue(digests, CFRangeMake(0, count), digest); + if (ixOfDigest != 0) { + if (ixOfDigest != kCFNotFound) { + CFArrayRemoveValueAtIndex(digests, ixOfDigest); + } else { + while (count >= kSOSPeerMaxManifestWindowDepth) + CFArrayRemoveValueAtIndex(digests, --count); + } + + CFArrayInsertValueAtIndex(digests, 0, digest); + } + } else { + // pending == NULL => nothing clear history + CFArrayRemoveAllValues(digests); + } +} + +static SOSPeerRef SOSPeerCreate_Internal(SOSEngineRef engine, CFDictionaryRef persisted, CFStringRef theirPeerID, CFIndex version, CFErrorRef *error) { + SOSPeerRef p = CFTypeAllocate(SOSPeer, struct __OpaqueSOSPeer, kCFAllocatorDefault); + p->engine = engine; + p->peer_id = CFRetainSafe(theirPeerID); + p->version = version; + + if (persisted) { + CFDictionaryRef peer_dict = (CFDictionaryRef) persisted; + + int64_t sequenceNumber; + CFNumberRef seqNo = CFDictionaryGetValue(peer_dict, kSOSPeerSequenceNumberKey); + if (seqNo) { + CFNumberGetValue(seqNo, kCFNumberSInt64Type, &sequenceNumber); + p->sequenceNumber = sequenceNumber; + } + CFNumberRef version = CFDictionaryGetValue(peer_dict, kSOSPeerVersionKey); + if (version) + CFNumberGetValue(version, kCFNumberCFIndexType, &p->version); + } + + return p; +} + +SOSPeerRef SOSPeerCreateWithEngine(SOSEngineRef engine, CFStringRef peer_id) { + CFMutableDictionaryRef state = SOSEngineGetPeerState(engine, peer_id); + return SOSPeerCreate_Internal(engine, state, peer_id, 0, NULL); +} + +static bool SOSPeerPersistData(SOSPeerRef peer, CFErrorRef *error) +{ + CFMutableDictionaryRef data_dict = SOSPeerGetState(peer); + + int64_t sequenceNumber = peer->sequenceNumber; + CFNumberRef seqNo = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &sequenceNumber); + CFDictionarySetValue(data_dict, kSOSPeerSequenceNumberKey, seqNo); + CFReleaseNull(seqNo); + CFDictionarySetValue(data_dict, kSOSPeerMustSendMessageKey, peer->mustSendMessage ? kCFBooleanTrue : kCFBooleanFalse); + if (peer->version) { + CFNumberRef version = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &peer->version); + CFDictionarySetValue(data_dict, kSOSPeerVersionKey, version); + CFReleaseSafe(version); + } + return true; +} + +SOSPeerRef SOSPeerCreate(SOSEngineRef engine, SOSPeerInfoRef peerInfo, + CFErrorRef *error) { + if (peerInfo == NULL) { + SOSCreateError(kSOSErrorUnsupported, CFSTR("Can't create peer without their peer info!"), NULL, error); + return NULL; + } + + CFStringRef peer_id = SOSPeerInfoGetPeerID(peerInfo); + CFDictionaryRef persisted = SOSEngineGetPeerState(engine, peer_id); + SOSPeerRef peer = SOSPeerCreate_Internal(engine, + persisted, + peer_id, + SOSPeerInfoGetVersion(peerInfo), + error); + if (peer) + SOSPeerPersistData(peer, error); + return peer; +} + +SOSPeerRef SOSPeerCreateSimple(SOSEngineRef engine, CFStringRef peer_id, CFIndex version, CFErrorRef *error) { + + CFDictionaryRef persisted = SOSEngineGetPeerState(engine, peer_id); + SOSPeerRef peer = SOSPeerCreate_Internal(engine, persisted, peer_id, version, error); + if (peer) + SOSPeerPersistData(peer, error); + return peer; +} + +static void SOSPeerDestroy(CFTypeRef cf) { + SOSPeerRef peer = (SOSPeerRef)cf; + SOSPeerPersistData(peer, NULL); + CFReleaseSafe(peer->peer_id); +} + +void SOSPeerDidConnect(SOSPeerRef peer) { + SOSPeerSetMustSendMessage(peer, true); + SOSPeerSetProposedManifest(peer, SOSPeerGetConfirmedManifest(peer)); +} + +CFIndex SOSPeerGetVersion(SOSPeerRef peer) { + return peer->version; +} + +CFStringRef SOSPeerGetID(SOSPeerRef peer) { + return peer->peer_id; +} + +SOSEngineRef SOSPeerGetEngine(SOSPeerRef peer){ + return peer->engine; +} +SOSCoderRef SOSPeerGetCoder(SOSPeerRef peer){ + return peer->coder; +} +void SOSPeerSetCoder(SOSPeerRef peer, SOSCoderRef coder){ + peer->coder = coder; +} + +uint64_t SOSPeerNextSequenceNumber(SOSPeerRef peer) { + return ++peer->sequenceNumber; +} + +uint64_t SOSPeerGetMessageVersion(SOSPeerRef peer) { + return SOSPeerGetVersion(peer); + +} + +bool SOSPeerMustSendMessage(SOSPeerRef peer) { + CFBooleanRef must = CFDictionaryGetValue(SOSPeerGetState(peer), kSOSPeerMustSendMessageKey); + return must && CFBooleanGetValue(must); +} + +void SOSPeerSetMustSendMessage(SOSPeerRef peer, bool sendMessage) { + CFDictionarySetValue(SOSPeerGetState(peer), kSOSPeerMustSendMessageKey, sendMessage ? kCFBooleanTrue : kCFBooleanFalse); +} + +bool SOSPeerSendObjects(SOSPeerRef peer) { + CFBooleanRef send = CFDictionaryGetValue(SOSPeerGetState(peer), kSOSPeerSendObjectsKey); + return send && CFBooleanGetValue(send); +} + +void SOSPeerSetSendObjects(SOSPeerRef peer, bool sendObjects) { + CFDictionarySetValue(SOSPeerGetState(peer), kSOSPeerSendObjectsKey, sendObjects ? kCFBooleanTrue : kCFBooleanFalse); +} + +SOSManifestRef SOSPeerGetProposedManifest(SOSPeerRef peer) { + CFDataRef digest = NULL; + CFMutableArrayRef proposedDigests = (CFMutableArrayRef)CFDictionaryGetValue(SOSPeerGetState(peer), kSOSPeerProposedManifestKey); + if (proposedDigests && CFArrayGetCount(proposedDigests) > 0) + digest = CFArrayGetValueAtIndex(proposedDigests, 0); + return SOSEngineGetManifestForDigest(peer->engine, digest); +} + +#if 0 +static SOSManifestRef SOSPeerGetLocalManifest(SOSPeerRef peer) { + CFDataRef digest = NULL; + CFMutableArrayRef localDigests = (CFMutableArrayRef)CFDictionaryGetValue(SOSPeerGetState(peer), kSOSPeerLocalManifestKey); + if (localDigests && CFArrayGetCount(localDigests) > 0) + digest = CFArrayGetValueAtIndex(localDigests, 0); + return SOSEngineGetManifestForDigest(peer->engine, digest); +} +#endif + +SOSManifestRef SOSPeerGetConfirmedManifest(SOSPeerRef peer) { + return SOSEngineGetManifestForDigest(peer->engine, CFDictionaryGetValue(SOSPeerGetState(peer), kSOSPeerConfirmedManifestKey)); +} + +void SOSPeerSetConfirmedManifest(SOSPeerRef peer, SOSManifestRef confirmed) { + SOSEngineAddManifest(peer->engine, confirmed); + SOSPeerStateSetDigestForKey(SOSPeerGetState(peer), kSOSPeerConfirmedManifestKey, SOSManifestGetDigest(confirmed, NULL)); + + // TODO: Clear only expired pending and local manifests from the array - this clears them all + // To do so we'd have to track the messageIds we sent to our peer and when we proposed a particular manifest. + // Then we simply remove the entires from messages older that the one we are confirming now + //CFArrayRemoveAllValues(SOSPeerGetDigestsWithKey(peer, kSOSPeerProposedManifestKey)); + //CFArrayRemoveAllValues(SOSPeerGetDigestsWithKey(peer, kSOSPeerLocalManifestKey)); +} + +void SOSPeerAddProposedManifest(SOSPeerRef peer, SOSManifestRef pending) { + SOSPeerAddManifestWithKey(peer, kSOSPeerProposedManifestKey, pending); +} + +void SOSPeerSetProposedManifest(SOSPeerRef peer, SOSManifestRef pending) { + SOSEngineAddManifest(peer->engine, pending); + CFMutableArrayRef proposedDigests = SOSPeerGetDigestsWithKey(peer, kSOSPeerProposedManifestKey); + CFArrayRemoveAllValues(proposedDigests); + if (pending) + CFArrayAppendValue(proposedDigests, SOSManifestGetDigest(pending, NULL)); +} + +void SOSPeerAddLocalManifest(SOSPeerRef peer, SOSManifestRef local) { + SOSPeerAddManifestWithKey(peer, kSOSPeerLocalManifestKey, local); +} + +SOSManifestRef SOSPeerGetPendingObjects(SOSPeerRef peer) { + return SOSEngineGetManifestForDigest(peer->engine, CFDictionaryGetValue(SOSPeerGetState(peer), kSOSPeerPendingObjectsKey)); +} + +void SOSPeerSetPendingObjects(SOSPeerRef peer, SOSManifestRef pendingObjects) { + SOSEngineAddManifest(peer->engine, pendingObjects); + SOSPeerStateSetDigestForKey(SOSPeerGetState(peer), kSOSPeerPendingObjectsKey, SOSManifestGetDigest(pendingObjects, NULL)); +} + +SOSManifestRef SOSPeerGetPendingDeletes(SOSPeerRef peer) { + return SOSEngineGetManifestForDigest(peer->engine, CFDictionaryGetValue(SOSPeerGetState(peer), kSOSPeerPendingDeletesKey)); +} + +void SOSPeerSetPendingDeletes(SOSPeerRef peer, SOSManifestRef pendingDeletes) { + SOSEngineAddManifest(peer->engine, pendingDeletes); + SOSPeerStateSetDigestForKey(SOSPeerGetState(peer), kSOSPeerPendingDeletesKey, SOSManifestGetDigest(pendingDeletes, NULL)); +} + +static void SOSMarkDigestInUse(struct SOSDigestVector *mdInUse, CFDataRef digest) { + if (!isData(digest)) return; + SOSDigestVectorAppend(mdInUse, CFDataGetBytePtr(digest)); +} + +static void SOSMarkDigestsInUse(struct SOSDigestVector *mdInUse, CFArrayRef digests) { + if (!isArray(digests)) return; + CFDataRef digest = NULL; + CFArrayForEachC(digests, digest) { + SOSMarkDigestInUse(mdInUse, digest); + } +} + +// Add all digests we are using to mdInUse +void SOSPeerMarkDigestsInUse(SOSPeerRef peer, struct SOSDigestVector *mdInUse) { + CFMutableDictionaryRef peerState = SOSPeerGetState(peer); + SOSMarkDigestInUse(mdInUse, CFDictionaryGetValue(peerState, kSOSPeerPendingObjectsKey)); + SOSMarkDigestInUse(mdInUse, CFDictionaryGetValue(peerState, kSOSPeerPendingDeletesKey)); + SOSMarkDigestInUse(mdInUse, CFDictionaryGetValue(peerState, kSOSPeerConfirmedManifestKey)); + SOSMarkDigestsInUse(mdInUse, CFDictionaryGetValue(peerState, kSOSPeerLocalManifestKey)); + SOSMarkDigestsInUse(mdInUse, CFDictionaryGetValue(peerState, kSOSPeerProposedManifestKey)); +} + + +// absentFromRemote +// AbsentLocally +// additionsFromRemote +// original intent was that digests only got added to pendingObjects. We only know for sure if it is something added locally via api call + + +bool SOSPeerDidReceiveRemovalsAndAdditions(SOSPeerRef peer, SOSManifestRef absentFromRemote, SOSManifestRef additionsFromRemote, + SOSManifestRef local, CFErrorRef *error) { + // We assume that incoming manifests are all sorted, and absentFromRemote is disjoint from additionsFromRemote + bool ok = true; + SOSManifestRef remoteRemovals = NULL, sharedRemovals = NULL, sharedAdditions = NULL, remoteAdditions = NULL; + CFDataRef pendingObjectsDigest, pendingDeletesDigest; + + // TODO: Simplyfy -- a lot. + ok = ok && (remoteRemovals = SOSManifestCreateIntersection(absentFromRemote, local, error)); // remoteRemovals = absentFromRemote local + ok = ok && (sharedRemovals = SOSManifestCreateComplement(remoteRemovals, absentFromRemote, error)); // sharedRemovals = absentFromRemote - remoteRemovals + ok = ok && (sharedAdditions = SOSManifestCreateIntersection(additionsFromRemote, local, error)); // sharedAdditions = additionsFromRemote local + ok = ok && (remoteAdditions = SOSManifestCreateComplement(sharedAdditions, additionsFromRemote, error)); // remoteAdditions = additionsFromRemote - sharedAdditions + + secnotice("peer", "%@ R:%@ A:%@ C:%@ D:%@ O:%@", peer, absentFromRemote, additionsFromRemote, SOSPeerGetConfirmedManifest(peer), SOSPeerGetPendingDeletes(peer), SOSPeerGetPendingObjects(peer)); + + // TODO: Does the value of SOSPeerSendObjects() matter here? + pendingObjectsDigest = SOSEnginePatchRecordAndCopyDigest(peer->engine, SOSPeerGetPendingObjects(peer), sharedAdditions, NULL, error); // PO = PO - sharedAdditions + pendingDeletesDigest = SOSEnginePatchRecordAndCopyDigest(peer->engine, SOSPeerGetPendingDeletes(peer), sharedRemovals, NULL, error); // D = D - sharedRemovals + + CFMutableDictionaryRef peerState = SOSPeerGetState(peer); + SOSPeerStateSetDigestForKey(peerState, kSOSPeerPendingObjectsKey, pendingObjectsDigest); + SOSPeerStateSetDigestForKey(peerState, kSOSPeerPendingDeletesKey, pendingDeletesDigest); + + CFReleaseSafe(pendingDeletesDigest); + CFReleaseSafe(pendingObjectsDigest); + CFReleaseSafe(remoteRemovals); + CFReleaseSafe(sharedRemovals); + CFReleaseSafe(sharedAdditions); + CFReleaseSafe(remoteAdditions); + + secnotice("peer", "%@ C:%@ D:%@ O:%@", peer, SOSPeerGetConfirmedManifest(peer), SOSPeerGetPendingDeletes(peer), SOSPeerGetPendingObjects(peer)); + + return ok; +} + +bool SOSPeerDidReceiveConfirmedManifest(SOSPeerRef peer, SOSManifestRef confirmed, SOSManifestRef local, CFErrorRef *error) { + bool ok = true; + if (!confirmed) return ok; + SOSManifestRef confirmedRemovals = NULL, confirmedAdditions = NULL; + + // confirmedAdditions = confirmed - previous_confirmed, confirmedRemovals = previous_confirmed - confirmed + ok &= SOSManifestDiff(SOSPeerGetConfirmedManifest(peer), confirmed, &confirmedRemovals, &confirmedAdditions, error); + ok &= SOSPeerDidReceiveRemovalsAndAdditions(peer, confirmedRemovals, confirmedAdditions, local, error); + + CFReleaseSafe(confirmedRemovals); + CFReleaseSafe(confirmedAdditions); + return ok; +} + +bool SOSPeerDataSourceWillCommit(SOSPeerRef peer, SOSDataSourceTransactionSource source, SOSManifestRef removals, SOSManifestRef additions, CFErrorRef *error) { + SOSManifestRef unconfirmedAdditions = NULL; + CFDataRef pendingObjectsDigest, pendingDeletesDigest = NULL; + + secnotice("peer", "%@ R:%@ A:%@ C:%@ D:%@ O:%@", peer, removals, additions, SOSPeerGetConfirmedManifest(peer), SOSPeerGetPendingDeletes(peer), SOSPeerGetPendingObjects(peer)); + + // Remove confirmed from additions + // TODO: Add require and check for error + unconfirmedAdditions = SOSManifestCreateComplement(SOSPeerGetConfirmedManifest(peer), additions, error); + secnotice("peer", "%@ UA: %@ source: %s", peer, unconfirmedAdditions, source == kSOSDataSourceSOSTransaction ? "sos" : "api"); + + pendingObjectsDigest = SOSEnginePatchRecordAndCopyDigest(peer->engine, SOSPeerGetPendingObjects(peer), removals, source == kSOSDataSourceAPITransaction ? unconfirmedAdditions : NULL, error); + // TODO: Figure out how to update pendingDeletes... + //pendingDeletesDigest = SOSEnginePatchRecordAndCopyDigest(peer->engine, SOSPeerGetPendingDeletes(peer), removals, NULL, error); + + CFMutableDictionaryRef peerState = SOSPeerGetState(peer); + + SOSPeerStateSetDigestForKey(peerState, kSOSPeerPendingObjectsKey, pendingObjectsDigest); + SOSPeerStateSetDigestForKey(peerState, kSOSPeerPendingDeletesKey, pendingDeletesDigest); + + CFReleaseSafe(pendingDeletesDigest); + CFReleaseSafe(pendingObjectsDigest); + CFReleaseSafe(unconfirmedAdditions); + + secnotice("peer", "%@ C:%@ D:%@ P:%@", peer, SOSPeerGetConfirmedManifest(peer), SOSPeerGetPendingDeletes(peer), SOSPeerGetPendingObjects(peer)); + + return true; +} + diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSPeer.h b/Security/sec/SOSCircle/SecureObjectSync/SOSPeer.h new file mode 100644 index 00000000..21568963 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSPeer.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/*! + @header SOSPeer + The functions provided in SOSPeer provide an interface to a + secure object syncing peer in a circle + */ + +#ifndef _SOSPEER_H_ +#define _SOSPEER_H_ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Constructor called by Engine */ +SOSPeerRef SOSPeerCreateWithEngine(SOSEngineRef engine, CFStringRef peer_id); +void SOSPeerMarkDigestsInUse(SOSPeerRef peer, struct SOSDigestVector *mdInUse); +bool SOSPeerDidReceiveRemovalsAndAdditions(SOSPeerRef peer, SOSManifestRef absentFromRemote, SOSManifestRef additionsFromRemote, + SOSManifestRef local, CFErrorRef *error); +bool SOSPeerDidReceiveConfirmedManifest(SOSPeerRef peer, SOSManifestRef confirmed, SOSManifestRef local, CFErrorRef *error); +bool SOSPeerDataSourceWillCommit(SOSPeerRef peer, SOSDataSourceTransactionSource source, SOSManifestRef removals, SOSManifestRef additions, CFErrorRef *error); + +/* Constructor called by Account */ +SOSPeerRef SOSPeerCreate(SOSEngineRef engine, SOSPeerInfoRef peerInfo, CFErrorRef *error); + +/* For testing, doesn't OTR encode and uses static ID for self */ +SOSPeerRef SOSPeerCreateSimple(SOSEngineRef engine, CFStringRef peer_id, CFIndex version, CFErrorRef *error); + +// +// +// + +CFIndex SOSPeerGetVersion(SOSPeerRef peer); +CFStringRef SOSPeerGetID(SOSPeerRef peer); +bool SOSPeersEqual(SOSPeerRef peerA, SOSPeerRef peerB); +SOSCoderRef SOSPeerGetCoder(SOSPeerRef peer); +void SOSPeerSetCoder(SOSPeerRef peer, SOSCoderRef coder); + +uint64_t SOSPeerNextSequenceNumber(SOSPeerRef peer); +uint64_t SOSPeerGetMessageVersion(SOSPeerRef peer); + +// +// MARK: State tracking helpers +// + +#if 0 +bool SOSPeerJoinRequest(SOSPeerRef peer); +void SOSPeerSetJoinRequest(SOSPeerRef peer, bool joinRequest); + +bool SOSPeerShouldRequestObjects(SOSPeerRef peer); +void SOSPeerSetShouldRequestObjects(SOSPeerRef peer, bool requestObjects); + +bool SOSPeerSkipHello(SOSPeerRef peer); +void SOSPeerSetSkipHello(SOSPeerRef peer, bool skipHello); + +// The last manifestDigest peer received couldn't be matched to a known manifest +bool SOSPeerReceivedUnknownManifest(SOSPeerRef peer); +void SOSPeerSetReceivedUnknownManifest(SOSPeerRef peer, bool unknownManifest); +#endif + + +// Return true if the peer is ready to transmit data. +void SOSPeerDidConnect(SOSPeerRef peer); +bool SOSPeerMustSendMessage(SOSPeerRef peer); +void SOSPeerSetMustSendMessage(SOSPeerRef peer, bool must); + +bool SOSPeerSendObjects(SOSPeerRef peer); +void SOSPeerSetSendObjects(SOSPeerRef peer, bool sendObjects); +SOSEngineRef SOSPeerGetEngine(SOSPeerRef peer); + +SOSManifestRef SOSPeerGetProposedManifest(SOSPeerRef peer); +SOSManifestRef SOSPeerGetConfirmedManifest(SOSPeerRef peer); +void SOSPeerSetConfirmedManifest(SOSPeerRef peer, SOSManifestRef confirmed); +void SOSPeerAddProposedManifest(SOSPeerRef peer, SOSManifestRef pending); +void SOSPeerSetProposedManifest(SOSPeerRef peer, SOSManifestRef pending); +void SOSPeerAddLocalManifest(SOSPeerRef peer, SOSManifestRef local); +SOSManifestRef SOSPeerGetPendingObjects(SOSPeerRef peer); +void SOSPeerSetPendingObjects(SOSPeerRef peer, SOSManifestRef pendingObjects); +SOSManifestRef SOSPeerGetPendingDeletes(SOSPeerRef peer); +void SOSPeerSetPendingDeletes(SOSPeerRef peer, SOSManifestRef pendingDeletes); + +SOSManifestRef SOSPeerGetPendingObjects(SOSPeerRef peer); + +__END_DECLS + +#endif /* !_SOSPEER_H_ */ diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.c b/Security/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.c new file mode 100644 index 00000000..07732224 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.c @@ -0,0 +1,160 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include "SOSInternal.h" + +static CFStringRef kSOSPeerCoderKey = CFSTR("coder"); + +bool SOSPeerCoderInitializeForPeer(SOSTransportMessageRef transport, SOSFullPeerInfoRef myPeerInfo, SOSPeerInfoRef peerInfo, CFErrorRef *error){ + CFErrorRef coderError = NULL; + + CFStringRef peer_id = SOSPeerInfoGetPeerID(peerInfo); + SOSCoderRef coder = NULL; + CFDataRef coderData = NULL; + bool haveGoodCoder = false; + CFMutableDictionaryRef peerState = SOSEngineGetPeerState(SOSTransportMessageGetEngine(transport), peer_id); + + if(peerState){ + coderData = CFDictionaryGetValue(peerState, kSOSPeerCoderKey); + if(coderData){ + coder = SOSCoderCreateFromData(coderData, &coderError); + if (!coder) { + secerror("Found data but couldn't make coder for %@: %@", peer_id, coderError); + } + haveGoodCoder = coder; + SOSCoderDispose(coder); + coder = NULL; + } + } + + if (!haveGoodCoder) { + secnotice("peer", "New coder for id %@.", peer_id); + CFReleaseNull(coder); + coder = SOSCoderCreate(peerInfo, myPeerInfo, error); + if (coder) { + coderData = SOSCoderCopyDER(coder, error); + if(coderData){ + if(!(haveGoodCoder = SOSEngineSetCoderData(SOSTransportMessageGetEngine(transport), peer_id, coderData, error))){ + secerror("SOSPeerCoderInitializeForPeer, Could not save coder data"); + } + } + CFReleaseNull(coderData); + SOSCoderDispose(coder); + } else { + secerror("Couldn't make coder for %@", peer_id); + } + } + CFReleaseNull(coderError); + return haveGoodCoder; +} + +void SOSPeerCoderConsume(SOSEnginePeerMessageSentBlock *sent, bool ok){ + if (*sent) + (*sent)(ok); +} + +enum SOSCoderUnwrapStatus SOSPeerHandleCoderMessage(SOSPeerRef peer, CFStringRef peer_id, CFDataRef codedMessage, CFDataRef *decodedMessage, CFErrorRef *error){ + + enum SOSCoderUnwrapStatus result = SOSCoderUnwrapError; + CFMutableDataRef localDecodedMessage = NULL; + + SOSCoderStatus coderStatus = kSOSCoderDataReturned; + CFDataRef coderData = SOSEngineGetCoderData(SOSPeerGetEngine(peer), SOSPeerGetID(peer)); + require_quiet(coderData, fail); + SOSCoderRef coder = SOSCoderCreateFromData(coderData, error); + require(coder, fail); + 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("engine", "%@ engine negotiating", peer_id); + break; + case kSOSCoderNegotiationCompleted: + if(SOSEnginePeerDidConnect(SOSPeerGetEngine(peer), peer_id, error)) + result = SOSCoderUnwrapHandled; + secnotice("engine", "%@ engine negotiation complete", peer_id); + break; + case kSOSCoderFailure: // Probably restart coder + secnotice("engine", "%@ engine 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. + secnotice("engine", "%@ engine stale event ignored", peer_id); + break; + default: + assert(false); + break; + } + if(decodedMessage) + *decodedMessage = CFRetainSafe(localDecodedMessage); + CFReleaseNull(localDecodedMessage); + + coderData = SOSCoderCopyDER(coder, error); + if(!SOSEngineSetCoderData(SOSPeerGetEngine(peer), peer_id, coderData, error)){ + secerror("SOSTransportMessageSendMessageIfNeeded, Could not save peer state"); + } + CFReleaseNull(coderData); + SOSCoderDispose(coder); + } + + CFReleaseNull(localError); +fail: + return result; + +} + +bool SOSPeerCoderSendMessageIfNeeded(SOSPeerRef peer, CFDataRef *message_to_send, CFStringRef circle_id, CFStringRef peer_id, SOSEnginePeerMessageSentBlock *sent, CFErrorRef *error){ + SOSCoderRef coder = SOSPeerGetCoder(peer); + + bool ok = false; + require_quiet(coder, fail); + + if (SOSCoderCanWrap(coder)) { + secnotice("transport", "%@ Coder can wrap, getting message from engine", peer_id); + CFMutableDataRef codedMessage = NULL; + CFDataRef message = SOSEngineCreateMessageToSyncToPeer(SOSPeerGetEngine(peer), 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); + secnotice("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; + } + +fail: + return ok; +} diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.h b/Security/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.h new file mode 100644 index 00000000..3f6df1a3 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.h @@ -0,0 +1,23 @@ + +#ifndef SOSTransportCoder_h +#define SOSTransportCoder_h +#include +#include + +enum SOSCoderUnwrapStatus{ + SOSCoderUnwrapError = 0, + SOSCoderUnwrapDecoded = 1, + SOSCoderUnwrapHandled = 2 +}; + +bool SOSPeerCoderSendMessageIfNeeded(SOSPeerRef peer, CFDataRef *message_to_send, CFStringRef circle_id, CFStringRef peer_id, SOSEnginePeerMessageSentBlock *sent, CFErrorRef *error); + +enum SOSCoderUnwrapStatus SOSPeerHandleCoderMessage(SOSPeerRef peer, CFStringRef peer_id, CFDataRef codedMessage, CFDataRef *decodedMessage, CFErrorRef *error); + +bool SOSPeerCoderInitializeForPeer(SOSTransportMessageRef transport, SOSFullPeerInfoRef myPeerInfo, SOSPeerInfoRef peerInfo, CFErrorRef *error); + +bool SOSPeerSendMessageIfNeeded(SOSPeerRef peer, CFDataRef *message, CFDataRef *message_to_send, SOSCoderRef *coder, CFStringRef circle_id, CFStringRef peer_id, SOSEnginePeerMessageSentBlock *sent, CFErrorRef *error); + +void SOSPeerCoderConsume(SOSEnginePeerMessageSentBlock *sent, bool ok); + +#endif diff --git a/sec/SOSCircle/SecureObjectSync/SOSPeerInfo.c b/Security/sec/SOSCircle/SecureObjectSync/SOSPeerInfo.c similarity index 82% rename from sec/SOSCircle/SecureObjectSync/SOSPeerInfo.c rename to Security/sec/SOSCircle/SecureObjectSync/SOSPeerInfo.c index 14738b2e..d4db2ae9 100644 --- a/sec/SOSCircle/SecureObjectSync/SOSPeerInfo.c +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSPeerInfo.c @@ -1,10 +1,26 @@ -// -// SOSPeerInfo.c -// sec -// -// Created by Mitch Adler on 7/19/12. -// -// +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include #include @@ -16,8 +32,6 @@ #include #include -#include "Imported/SecuritydXPC.h" - #include #include @@ -50,6 +64,7 @@ #include #include #include +#include #if 0//TARGET_OS_MAC // TODO: this function is the only one that causes secd to need to link against Security.framework on OSX @@ -70,12 +85,16 @@ struct __OpaqueSOSPeerInfo { CFDictionaryRef gestalt; CFStringRef id; CFIndex version; + + CFStringRef transportType; + CFStringRef deviceID; }; CFGiblisWithHashFor(SOSPeerInfo); CFStringRef kPIUserDefinedDeviceName = CFSTR("ComputerName"); CFStringRef kPIDeviceModelName = CFSTR("ModelName"); +CFStringRef kPIMessageProtocolVersion = CFSTR("MessageProtocolVersion"); // Description Dictionary Entries static CFStringRef sPublicKeyKey = CFSTR("PublicSigningKey"); @@ -94,6 +113,8 @@ CFStringRef kSOSPeerInfoNameKey = CFSTR("SOSPeerInfoName"); SecKeyRef SOSPeerInfoCopyPubKey(SOSPeerInfoRef peer) { CFDataRef pubKeyBytes = CFDictionaryGetValue(peer->description, sPublicKeyKey); + if (pubKeyBytes == NULL) + return NULL; CFAllocatorRef allocator = CFGetAllocator(peer); SecKeyRef pubKey = SecKeyCreateFromPublicData(allocator, kSecECDSAAlgorithmID, pubKeyBytes); return pubKey; @@ -155,11 +176,16 @@ static bool SOSPeerInfoVerify(SOSPeerInfoRef peer, CFErrorRef *error) { uint8_t hbuf[di->output_size]; SecKeyRef pubKey = SOSPeerInfoCopyPubKey(peer); - require_quiet(pubKey, error_out); + require_action_quiet(pubKey, error_out, + SOSErrorCreate(kSOSErrorNoKey, error, NULL, + CFSTR("Couldn't find pub key for %@"), peer)); require_quiet(SOSDescriptionHash(peer, di, hbuf, error), error_out); - - result = sosVerifyHash(pubKey, di, hbuf, peer->signature); + + require_action_quiet(sosVerifyHash(pubKey, di, hbuf, peer->signature), error_out, + SOSErrorCreate(kSOSErrorBadSignature, error, NULL, + CFSTR("Signature didn't verify for %@"), peer)); + result = true; error_out: CFReleaseNull(pubKey); @@ -171,8 +197,8 @@ static SOSPeerInfoRef SOSPeerInfoCreate_Internal(CFAllocatorRef allocator, CFDic pi->gestalt = gestalt; CFRetain(pi->gestalt); - pi->version = kSOSPeerVersion; - + pi->version = SOSPeerInfoGetPeerProtocolVersion(pi); + pi->transportType = CFStringCreateCopy(kCFAllocatorDefault, CFSTR("KVS")); CFDataRef publicBytes = NULL; CFNumberRef versionNumber = NULL; @@ -201,6 +227,22 @@ static SOSPeerInfoRef SOSPeerInfoCreate_Internal(CFAllocatorRef allocator, CFDic NULL); description_modifier(pi->description); + CFStringRef deviceName = CFDictionaryGetValue(pi->gestalt, kPIUserDefinedDeviceName); + CFStringRef modelName = CFDictionaryGetValue(pi->gestalt, kPIDeviceModelName); + CFStringRef ID = pi->id; + CFMutableStringRef description = CFStringCreateMutableCopy(kCFAllocatorDefault, CFStringGetLength(deviceName), deviceName); + if(modelName){ + CFStringAppend(description, CFSTR(", ")); + CFStringAppend(description, modelName); + } + if(ID){ + CFStringAppend(description, CFSTR(", ")); + CFStringAppend(description, ID); + } + + pi->deviceID = CFStringCreateCopy(kCFAllocatorDefault, description); + CFReleaseNull(description); + pi->id = SOSCopyIDOfKey(publicKey, error); CFReleaseNull(publicKey); @@ -237,7 +279,8 @@ SOSPeerInfoRef SOSPeerInfoCreateCopy(CFAllocatorRef allocator, SOSPeerInfoRef to pi->gestalt = CFDictionaryCreateCopy(allocator, toCopy->gestalt); pi->id = CFStringCreateCopy(allocator, toCopy->id); - + pi->transportType = CFStringCreateCopy(allocator, toCopy->transportType); + pi->deviceID = CFStringCreateCopy(kCFAllocatorDefault, toCopy->deviceID); pi->version = toCopy->version; return pi; @@ -275,7 +318,7 @@ SOSPeerInfoRef SOSPeerInfoCreateFromDER(CFAllocatorRef allocator, CFErrorRef* er pi->gestalt = NULL; pi->version = 0; // TODO: Encode this in the DER - + pi->transportType = CFStringCreateCopy(kCFAllocatorDefault, CFSTR("KVS")); *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); *der_p = der_decode_plist(allocator, kCFPropertyListImmutable, &pl, error, *der_p, sequence_end); *der_p = der_decode_data(allocator, kCFPropertyListImmutable, &pi->signature, error, *der_p, sequence_end); @@ -300,13 +343,26 @@ SOSPeerInfoRef SOSPeerInfoCreateFromDER(CFAllocatorRef allocator, CFErrorRef* er CFNumberRef versionNumber = CFDictionaryGetValue(pi->description, sVersionKey); if (versionNumber) { + if (CFGetTypeID(versionNumber) != CFNumberGetTypeID()) { + CFStringRef description = CFCopyTypeIDDescription(CFGetTypeID(versionNumber)); + SOSCreateErrorWithFormat(kSOSErrorUnexpectedType, NULL, error, NULL, + CFSTR("Expected (version) number got %@"), description); + CFReleaseSafe(description); + goto fail; + } CFNumberGetValue(versionNumber, kCFNumberCFIndexType, &pi->version); } CFDictionaryRef gestalt = CFDictionaryGetValue(pi->description, sGestaltKey); - + + if (gestalt == NULL) { + SOSCreateErrorWithFormat(kSOSErrorUnexpectedType, NULL, error, NULL, + CFSTR("gestalt key missing")); + goto fail; + } + if (!isDictionary(gestalt)) { - CFStringRef description = CFCopyTypeIDDescription(CFGetTypeID(pl)); + CFStringRef description = CFCopyTypeIDDescription(CFGetTypeID(gestalt)); SOSCreateErrorWithFormat(kSOSErrorUnexpectedType, NULL, error, NULL, CFSTR("Expected dictionary got %@"), description); CFReleaseSafe(description); @@ -328,6 +384,22 @@ SOSPeerInfoRef SOSPeerInfoCreateFromDER(CFAllocatorRef allocator, CFErrorRef* er secerror("Can't validate PeerInfo: %@", *error); goto fail; } + + CFStringRef deviceName = CFDictionaryGetValue(pi->gestalt, kPIUserDefinedDeviceName); + CFStringRef modelName = CFDictionaryGetValue(pi->gestalt, kPIDeviceModelName); + CFStringRef ID = pi->id; + CFMutableStringRef description = CFStringCreateMutableCopy(kCFAllocatorDefault, CFStringGetLength(deviceName), deviceName); + if(modelName){ + CFStringAppend(description, CFSTR(", ")); + CFStringAppend(description, modelName); + } + if(ID){ + CFStringAppend(description, CFSTR(", ")); + CFStringAppend(description, ID); + } + + pi->deviceID = CFStringCreateCopy(kCFAllocatorDefault, description); + CFReleaseNull(description); CFReleaseNull(pubKey); return pi; @@ -354,6 +426,7 @@ static void SOSPeerInfoDestroy(CFTypeRef aObj) { CFReleaseNull(pi->signature); CFReleaseNull(pi->gestalt); CFReleaseNull(pi->id); + CFReleaseNull(pi->deviceID); } static Boolean SOSPeerInfoCompare(CFTypeRef lhs, CFTypeRef rhs) { @@ -390,13 +463,15 @@ static CFHashCode SOSPeerInfoHash(CFTypeRef cf) { static CFStringRef SOSPeerInfoCopyDescription(CFTypeRef aObj) { SOSPeerInfoRef pi = (SOSPeerInfoRef) aObj; - - return CFStringCreateWithFormat(NULL, NULL, CFSTR(""), + CFIndex version = SOSPeerInfoGetPeerProtocolVersion(pi); + + return CFStringCreateWithFormat(NULL, NULL, CFSTR(""), pi, + SOSPeerInfoIsRetirementTicket(pi) ? "R" : "-", CFDictionaryGetValue(pi->gestalt, kPIUserDefinedDeviceName), - SOSPeerInfoIsRetirementTicket(pi) ? " [retired]" : "", CFDictionaryGetValue(pi->gestalt, kPIDeviceModelName), - pi->id); + pi->id, + version); } CFDictionaryRef SOSPeerInfoCopyPeerGestalt(SOSPeerInfoRef pi) { @@ -404,6 +479,19 @@ CFDictionaryRef SOSPeerInfoCopyPeerGestalt(SOSPeerInfoRef pi) { return pi->gestalt; } +CFStringRef SOSPeerInfoGetTransportType(SOSPeerInfoRef peer){ + return peer->transportType; +} + +CFStringRef SOSPeerInfoGetDeviceID(SOSPeerInfoRef peer){ + return peer->deviceID; +} + +void SOSPeerInfoSetDeviceID(SOSPeerInfoRef peer, CFStringRef IDS){ + CFReleaseNull(peer->deviceID); + peer->deviceID = CFStringCreateCopy(kCFAllocatorDefault, IDS); +} + CFStringRef SOSPeerInfoGetPeerName(SOSPeerInfoRef peer) { return SOSPeerInfoLookupGestaltValue(peer, kPIUserDefinedDeviceName); } @@ -412,6 +500,14 @@ CFStringRef SOSPeerInfoGetPeerDeviceType(SOSPeerInfoRef peer) { return SOSPeerInfoLookupGestaltValue(peer, kPIDeviceModelName); } +CFIndex SOSPeerInfoGetPeerProtocolVersion(SOSPeerInfoRef peer) { + CFIndex version = 0; + CFTypeRef val = SOSPeerInfoLookupGestaltValue(peer, kPIMessageProtocolVersion); + if (val && CFGetTypeID(val) == CFNumberGetTypeID()) + CFNumberGetValue(val, kCFNumberCFIndexType, &version); + return version; +} + CFTypeRef SOSPeerInfoLookupGestaltValue(SOSPeerInfoRef pi, CFStringRef key) { return CFDictionaryGetValue(pi->gestalt, key); } @@ -487,7 +583,7 @@ static bool sospeer_application_hash(SOSPeerInfoRef pi, const struct ccdigest_in SOSPeerInfoRef SOSPeerInfoCopyAsApplication(SOSPeerInfoRef original, SecKeyRef userkey, SecKeyRef peerkey, CFErrorRef *error) { SOSPeerInfoRef result = NULL; SOSPeerInfoRef pi = SOSPeerInfoCreateCopy(kCFAllocatorDefault, original, error); - + pi->transportType = CFStringCreateCopy(kCFAllocatorDefault, CFSTR("KVS")); const struct ccdigest_info *di = ccsha256_di(); uint8_t hbuf[di->output_size]; CFDataRef usersig = NULL; @@ -586,125 +682,6 @@ CFDataRef SOSPeerInfoCopyEncodedData(SOSPeerInfoRef peer, CFAllocatorRef allocat } -// -// PeerInfoArray encoding decoding -// - -CFMutableArrayRef SOSPeerInfoArrayCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error, - const uint8_t** der_p, const uint8_t *der_end) { - CFMutableArrayRef pia = CFArrayCreateMutableForCFTypes(allocator); - - const uint8_t *sequence_end; - - *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); - - require_action(*der_p, fail, SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Peer Info Array Sequence Header"), NULL, error)); - - while (sequence_end != *der_p) { - SOSPeerInfoRef pi = SOSPeerInfoCreateFromDER(allocator, error, der_p, sequence_end); - - if (pi == NULL || *der_p == NULL) { - SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Peer Info Array DER"), (error != NULL ? *error : NULL), error); - CFReleaseNull(pi); - goto fail; - } - - CFArrayAppendValue(pia, pi); - CFReleaseSafe(pi); - } - - if (!pia) - *der_p = NULL; - return pia; - -fail: - CFReleaseNull(pia); - *der_p = NULL; - return NULL; -} - -size_t SOSPeerInfoArrayGetDEREncodedSize(CFArrayRef pia, CFErrorRef *error) { - size_t array_size = 0; - - for(CFIndex count = CFArrayGetCount(pia); - count > 0; - --count) { - SOSPeerInfoRef pi = (SOSPeerInfoRef) CFArrayGetValueAtIndex(pia, count - 1); - - if (CFGetTypeID(pi) != SOSPeerInfoGetTypeID()) { - SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Non SOSPeerInfo in array"), (error != NULL ? *error : NULL), error); - return 0; - } - - size_t pi_size = SOSPeerInfoGetDEREncodedSize(pi, error); - - if (pi_size == 0) { - SOSCreateError(kSOSErrorEncodeFailure, CFSTR("Bad DER size"), (error != NULL ? *error : NULL), error); - return 0; - } - - array_size += pi_size; - } - - - return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, - array_size); -} - -uint8_t* SOSPeerInfoArrayEncodeToDER(CFArrayRef pia, CFErrorRef* error, const uint8_t* der, uint8_t* der_end_param) { - - uint8_t* const sequence_end = der_end_param; - __block uint8_t* der_end = der_end_param; - - CFArrayForEachReverse(pia, ^(const void *value) { - SOSPeerInfoRef pi = (SOSPeerInfoRef) value; - if (CFGetTypeID(pi) != SOSPeerInfoGetTypeID()) { - SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Non SOSPeerInfo in array"), NULL, error); - der_end = NULL; // Indicate error and continue. - } - if (der_end) - der_end = SOSPeerInfoEncodeToDER(pi, error, der, der_end); - }); - - if (der_end == NULL) - return NULL; - - return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, sequence_end, der, der_end); -} - - -CFArrayRef CreateArrayOfPeerInfoWithXPCObject(xpc_object_t peerArray, CFErrorRef* error) { - if (!peerArray) { - SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedNull, sSecXPCErrorDomain, NULL, error, NULL, CFSTR("Unexpected Null Array to encode")); - return NULL; - } - - if (xpc_get_type(peerArray) != XPC_TYPE_DATA) { - SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, error, NULL, CFSTR("Array of peer info not array, got %@"), peerArray); - return NULL; - } - - const uint8_t* der = xpc_data_get_bytes_ptr(peerArray); - const uint8_t* der_end = der + xpc_data_get_length(peerArray); - - return SOSPeerInfoArrayCreateFromDER(kCFAllocatorDefault, error, &der, der_end); -} - -xpc_object_t CreateXPCObjectWithArrayOfPeerInfo(CFArrayRef array, CFErrorRef *error) { - size_t data_size = SOSPeerInfoArrayGetDEREncodedSize(array, error); - if (data_size == 0) - return NULL; - uint8_t *data = (uint8_t *)malloc(data_size); - if (!data) return NULL; - - xpc_object_t result = NULL; - if (SOSPeerInfoArrayEncodeToDER(array, error, data, data + data_size)) - result = xpc_data_create(data, data_size); - - free(data); - return result; -} - // // Gestalt helpers // diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSPeerInfo.h b/Security/sec/SOSCircle/SecureObjectSync/SOSPeerInfo.h new file mode 100644 index 00000000..cdd3edeb --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSPeerInfo.h @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef _SOSPEERINFO_H_ +#define _SOSPEERINFO_H_ + +#include +#include +#include +#include + +__BEGIN_DECLS + +typedef struct __OpaqueSOSPeerInfo *SOSPeerInfoRef; + +enum { + kSOSPeerVersion = 2, +}; + + +enum { + SOSPeerCmpPubKeyHash = 0, + SOSPeerCmpName = 1, +}; +typedef uint32_t SOSPeerInfoCmpSelect; + +CFTypeID SOSPeerInfoGetTypeID(void); + +static inline bool isSOSPeerInfo(CFTypeRef obj) { + return obj && (CFGetTypeID(obj) == SOSPeerInfoGetTypeID()); +} + +SOSPeerInfoRef SOSPeerInfoCreate(CFAllocatorRef allocator, CFDictionaryRef gestalt, SecKeyRef signingKey, CFErrorRef* error); + +SOSPeerInfoRef SOSPeerInfoCreateCloudIdentity(CFAllocatorRef allocator, CFDictionaryRef gestalt, SecKeyRef signingKey, CFErrorRef* error); + +SOSPeerInfoRef SOSPeerInfoCreateCopy(CFAllocatorRef allocator, SOSPeerInfoRef toCopy, CFErrorRef* error); +SOSPeerInfoRef SOSPeerInfoCopyWithGestaltUpdate(CFAllocatorRef allocator, SOSPeerInfoRef toCopy, CFDictionaryRef gestalt, SecKeyRef signingKey, CFErrorRef* error); +SOSPeerInfoRef SOSPeerInfoCopyAsApplication(SOSPeerInfoRef pi, SecKeyRef userkey, SecKeyRef peerkey, CFErrorRef *error); + +bool SOSPeerInfoUpdateDigestWithPublicKeyBytes(SOSPeerInfoRef peer, const struct ccdigest_info *di, + ccdigest_ctx_t ctx, CFErrorRef *error); +bool SOSPeerInfoUpdateDigestWithDescription(SOSPeerInfoRef peer, const struct ccdigest_info *di, + ccdigest_ctx_t ctx, CFErrorRef *error); + + +bool SOSPeerInfoApplicationVerify(SOSPeerInfoRef pi, SecKeyRef userkey, CFErrorRef *error); + +CF_RETURNS_RETAINED CFDateRef SOSPeerInfoGetApplicationDate(SOSPeerInfoRef pi); + +// +// DER Import Export +// +SOSPeerInfoRef SOSPeerInfoCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error, + const uint8_t** der_p, const uint8_t *der_end); + +SOSPeerInfoRef SOSPeerInfoCreateFromData(CFAllocatorRef allocator, CFErrorRef* error, + CFDataRef peerinfo_data); + +size_t SOSPeerInfoGetDEREncodedSize(SOSPeerInfoRef peer, CFErrorRef *error); +uint8_t* SOSPeerInfoEncodeToDER(SOSPeerInfoRef peer, CFErrorRef* error, + const uint8_t* der, uint8_t* der_end); + +CFDataRef SOSPeerInfoCopyEncodedData(SOSPeerInfoRef peer, CFAllocatorRef allocator, CFErrorRef *error); + +// +// Gestalt info about the peer. It was fetched by the implementation on the other side. +// probably has what you're looking for.. +// +CFTypeRef SOSPeerInfoLookupGestaltValue(SOSPeerInfoRef pi, CFStringRef key); +CFDictionaryRef SOSPeerInfoCopyPeerGestalt(SOSPeerInfoRef pi); + +// +// Syntactic Sugar for some commone ones, might get deprectated at this level. +// +CFStringRef SOSPeerInfoGetTransportType(SOSPeerInfoRef peer); +CFStringRef SOSPeerInfoGetPeerName(SOSPeerInfoRef peer); +CFStringRef SOSPeerInfoGetPeerDeviceType(SOSPeerInfoRef peer); +CFIndex SOSPeerInfoGetPeerProtocolVersion(SOSPeerInfoRef peer); + +// IDSs device ID +CFStringRef SOSPeerInfoGetDeviceID(SOSPeerInfoRef peer); +void SOSPeerInfoSetDeviceID(SOSPeerInfoRef peer, CFStringRef IDS); + +// Stringified ID for this peer, not human readable. +CFStringRef SOSPeerInfoGetPeerID(SOSPeerInfoRef peer); + +CFIndex SOSPeerInfoGetVersion(SOSPeerInfoRef peer); + +// +// Peer Info Gestalt Helpers +// +CFStringRef SOSPeerGestaltGetName(CFDictionaryRef gestalt); + +// These are Mobile Gestalt questions. Not all Gestalt questions are carried. +CFTypeRef SOSPeerGestaltGetAnswer(CFDictionaryRef gestalt, CFStringRef question); + +SecKeyRef SOSPeerInfoCopyPubKey(SOSPeerInfoRef peer); + +CFComparisonResult SOSPeerInfoCompareByID(const void *val1, const void *val2, void *context); + +SOSPeerInfoRef SOSPeerInfoCreateRetirementTicket(CFAllocatorRef allocator, SecKeyRef privKey, SOSPeerInfoRef peer, CFErrorRef *error); + +CFStringRef SOSPeerInfoInspectRetirementTicket(SOSPeerInfoRef pi, CFErrorRef *error); + +bool SOSPeerInfoRetireRetirementTicket(size_t max_days, SOSPeerInfoRef pi); + +CF_RETURNS_RETAINED CFDateRef SOSPeerInfoGetRetirementDate(SOSPeerInfoRef pi); + +bool SOSPeerInfoIsRetirementTicket(SOSPeerInfoRef pi); + +bool SOSPeerInfoIsCloudIdentity(SOSPeerInfoRef pi); + +SOSPeerInfoRef SOSPeerInfoUpgradeSignatures(CFAllocatorRef allocator, SecKeyRef privKey, SecKeyRef perKey, SOSPeerInfoRef peer, CFErrorRef *error); + +__END_DECLS + +#endif diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSPeerInfoCollections.c b/Security/sec/SOSCircle/SecureObjectSync/SOSPeerInfoCollections.c new file mode 100644 index 00000000..8760f002 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSPeerInfoCollections.c @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + +#include +#include +#include +#include +#include +#include +#include + +// +// PeerInfoSetby ID handling +// + +// +// +// CFSetRetainCallback +// + +static Boolean SOSPeerInfoIDEqual(const void *value1, const void *value2) +{ + SOSPeerInfoRef peer1 = (SOSPeerInfoRef) value1; + SOSPeerInfoRef peer2 = (SOSPeerInfoRef) value2; + + return CFEqual(SOSPeerInfoGetPeerID(peer1), SOSPeerInfoGetPeerID(peer2)); +} + +static CFHashCode SOSPeerInfoIDHash(const void *value) +{ + return CFHash(SOSPeerInfoGetPeerID((SOSPeerInfoRef) value)); +} + +bool SOSPeerInfoSetContainsIdenticalPeers(CFSetRef set1, CFSetRef set2){ + + __block bool result = true; + + if(!CFEqualSafe(set1, set2)) + return false; + + CFSetForEach(set1, ^(const void *value) { + SOSPeerInfoRef peer1 = (SOSPeerInfoRef)value; + SOSPeerInfoRef peer2 = (SOSPeerInfoRef)CFSetGetValue(set2, peer1); + result &= CFEqualSafe(peer1, peer2); + }); + return result; +} +const CFSetCallBacks kSOSPeerSetCallbacks = {0, SecCFRetainForCollection, SecCFReleaseForCollection, CFCopyDescription, SOSPeerInfoIDEqual, SOSPeerInfoIDHash}; + +CFMutableSetRef CFSetCreateMutableForSOSPeerInfosByID(CFAllocatorRef allocator) +{ + return CFSetCreateMutable(allocator, 0, &kSOSPeerSetCallbacks); +} + + +// +// CFArray of Peer Info handling +// + +void CFArrayOfSOSPeerInfosSortByID(CFMutableArrayRef peerInfoArray) +{ + CFArraySortValues(peerInfoArray, CFRangeMake(0, CFArrayGetCount(peerInfoArray)), SOSPeerInfoCompareByID, NULL); +} + + +// +// PeerInfoArray encoding decoding +// + +CFMutableArrayRef SOSPeerInfoArrayCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error, + const uint8_t** der_p, const uint8_t *der_end) { + CFMutableArrayRef pia = CFArrayCreateMutableForCFTypes(allocator); + + const uint8_t *sequence_end; + + *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); + + require_action(*der_p, fail, SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Peer Info Array Sequence Header"), NULL, error)); + + while (sequence_end != *der_p) { + SOSPeerInfoRef pi = SOSPeerInfoCreateFromDER(allocator, error, der_p, sequence_end); + + if (pi == NULL || *der_p == NULL) { + SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Peer Info Array DER"), (error != NULL ? *error : NULL), error); + CFReleaseNull(pi); + goto fail; + } + + CFArrayAppendValue(pia, pi); + CFReleaseSafe(pi); + } + + if (!pia) + *der_p = NULL; + return pia; + +fail: + CFReleaseNull(pia); + *der_p = NULL; + return NULL; +} + +size_t SOSPeerInfoArrayGetDEREncodedSize(CFArrayRef pia, CFErrorRef *error) { + __block size_t array_size = 0; + __block bool fail = false; + + CFArrayForEach(pia, ^(const void *value) { + if (isSOSPeerInfo(value)) { + SOSPeerInfoRef pi = (SOSPeerInfoRef) value; + size_t pi_size = SOSPeerInfoGetDEREncodedSize(pi, error); + + fail = (pi_size == 0); + array_size += pi_size; + } else { + SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Non SOSPeerInfo in array"), (error != NULL ? *error : NULL), error); + fail = true; + } + }); + + return fail ? 0 : ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, array_size); +} + +uint8_t* SOSPeerInfoArrayEncodeToDER(CFArrayRef pia, CFErrorRef* error, const uint8_t* der, uint8_t* der_end_param) { + + uint8_t* const sequence_end = der_end_param; + __block uint8_t* der_end = der_end_param; + + CFArrayForEachReverse(pia, ^(const void *value) { + SOSPeerInfoRef pi = (SOSPeerInfoRef) value; + if (CFGetTypeID(pi) != SOSPeerInfoGetTypeID()) { + SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Non SOSPeerInfo in array"), NULL, error); + der_end = NULL; // Indicate error and continue. + } + if (der_end) + der_end = SOSPeerInfoEncodeToDER(pi, error, der, der_end); + }); + + if (der_end == NULL) + return NULL; + + return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, sequence_end, der, der_end); +} + + +CFMutableSetRef SOSPeerInfoSetCreateFromArrayDER(CFAllocatorRef allocator, const CFSetCallBacks *callbacks, CFErrorRef* error, + const uint8_t** der_p, const uint8_t *der_end) { + CFMutableSetRef result = NULL; + + CFArrayRef peers = SOSPeerInfoArrayCreateFromDER(allocator, error, der_p, der_end); + + if (peers) { + result = CFSetCreateMutable(allocator, 0, callbacks); + CFSetSetValues(result, peers); + } + + CFReleaseNull(peers); + return result; +} + +size_t SOSPeerInfoSetGetDEREncodedArraySize(CFSetRef pia, CFErrorRef *error) { + __block size_t array_size = 0; + __block bool fail = false; + + CFSetForEach(pia, ^(const void *value) { + if (isSOSPeerInfo(value)) { + SOSPeerInfoRef pi = (SOSPeerInfoRef) value; + size_t pi_size = SOSPeerInfoGetDEREncodedSize(pi, error); + + fail = (pi_size == 0); + array_size += pi_size; + } else { + SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Non SOSPeerInfo in array"), (error != NULL ? *error : NULL), error); + fail = true; + } + }); + + return fail ? 0 : ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, array_size); +} + +uint8_t* SOSPeerInfoSetEncodeToArrayDER(CFSetRef pis, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) { + CFArrayRef pia = CFSetCopyValues(pis); + + uint8_t* result = SOSPeerInfoArrayEncodeToDER(pia, error, der, der_end); + + CFReleaseNull(pia); + + return result; +} + + + +CFArrayRef CreateArrayOfPeerInfoWithXPCObject(xpc_object_t peerArray, CFErrorRef* error) { + if (!peerArray) { + SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedNull, sSecXPCErrorDomain, NULL, error, NULL, CFSTR("Unexpected Null Array to encode")); + return NULL; + } + + if (xpc_get_type(peerArray) != XPC_TYPE_DATA) { + SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, error, NULL, CFSTR("Array of peer info not array, got %@"), peerArray); + return NULL; + } + + const uint8_t* der = xpc_data_get_bytes_ptr(peerArray); + const uint8_t* der_end = der + xpc_data_get_length(peerArray); + + return SOSPeerInfoArrayCreateFromDER(kCFAllocatorDefault, error, &der, der_end); +} + +xpc_object_t CreateXPCObjectWithArrayOfPeerInfo(CFArrayRef array, CFErrorRef *error) { + size_t data_size = SOSPeerInfoArrayGetDEREncodedSize(array, error); + if (data_size == 0) + return NULL; + uint8_t *data = (uint8_t *)malloc(data_size); + if (!data) return NULL; + + xpc_object_t result = NULL; + if (SOSPeerInfoArrayEncodeToDER(array, error, data, data + data_size)) + result = xpc_data_create(data, data_size); + + free(data); + return result; +} diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSPeerInfoCollections.h b/Security/sec/SOSCircle/SecureObjectSync/SOSPeerInfoCollections.h new file mode 100644 index 00000000..2d0499fc --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSPeerInfoCollections.h @@ -0,0 +1,64 @@ +/* + * 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@ + */ + + +#ifndef __SOSPEERINFOCOLLECTIONS__ +#define __SOSPEERINFOCOLLECTIONS__ + +#include +#include + +// +// CFSet of PeerInfos by ID. +// +bool SOSPeerInfoSetContainsIdenticalPeers(CFSetRef set1, CFSetRef set2); +const CFSetCallBacks kSOSPeerSetCallbacks; +CFMutableSetRef CFSetCreateMutableForSOSPeerInfosByID(CFAllocatorRef allocator); + +// +// CFArray of Peer Info handling +// + +void CFArrayOfSOSPeerInfosSortByID(CFMutableArrayRef peerInfoArray); + +// +// Peer Info Array Persistence +// + +CFMutableArrayRef SOSPeerInfoArrayCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error, + const uint8_t** der_p, const uint8_t *der_end); +size_t SOSPeerInfoArrayGetDEREncodedSize(CFArrayRef pia, CFErrorRef *error); +uint8_t* SOSPeerInfoArrayEncodeToDER(CFArrayRef pia, CFErrorRef* error, const uint8_t* der, uint8_t* der_end); + + + +CFMutableSetRef SOSPeerInfoSetCreateFromArrayDER(CFAllocatorRef allocator, const CFSetCallBacks *callbacks, CFErrorRef* error, + const uint8_t** der_p, const uint8_t *der_end); +size_t SOSPeerInfoSetGetDEREncodedArraySize(CFSetRef pia, CFErrorRef *error); +uint8_t* SOSPeerInfoSetEncodeToArrayDER(CFSetRef pia, CFErrorRef* error, const uint8_t* der, uint8_t* der_end); + + +CFArrayRef CreateArrayOfPeerInfoWithXPCObject(xpc_object_t peerArray, CFErrorRef* error); +xpc_object_t CreateXPCObjectWithArrayOfPeerInfo(CFArrayRef array, CFErrorRef *error); + +#endif diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSPeerInfoInternal.h b/Security/sec/SOSCircle/SecureObjectSync/SOSPeerInfoInternal.h new file mode 100644 index 00000000..550588a4 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSPeerInfoInternal.h @@ -0,0 +1,33 @@ +/* + * 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@ + */ + + +#ifndef sec_SOSPeerInfoInternal_h +#define sec_SOSPeerInfoInternal_h + +CFStringRef kPIUserDefinedDeviceName; +CFStringRef kPIDeviceModelName; +CFStringRef kPIMessageProtocolVersion; + + +#endif diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSTransport.c b/Security/sec/SOSCircle/SecureObjectSync/SOSTransport.c new file mode 100644 index 00000000..478a22a4 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSTransport.c @@ -0,0 +1,437 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +CFStringRef kKeyParameter = CFSTR("KeyParameter"); +CFStringRef kCircle = CFSTR("Circle"); +CFStringRef kMessage = CFSTR("Message"); +CFStringRef kAlwaysKeys = CFSTR("AlwaysKeys"); +CFStringRef kFirstUnlocked = CFSTR("FirstUnlockKeys"); +CFStringRef kUnlocked = CFSTR("UnlockedKeys"); + + + +CFStringRef SOSInterestListCopyDescription(CFArrayRef interests) +{ + CFMutableStringRef description = CFStringCreateMutable(kCFAllocatorDefault, 0); + CFStringAppendFormat(description, NULL, CFSTR("")); + + return description; +} + + +// +// MARK: Key Interest Processing +// + +CFGiblisGetSingleton(CFMutableArrayRef, SOSGetTransportMessages, sTransportMessages, ^{ + *sTransportMessages = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL); +}); + +CFGiblisGetSingleton(CFMutableArrayRef, SOSGetTransportKeyParameters, sTransportKeyParameters, ^{ + *sTransportKeyParameters = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL); +}); + +CFGiblisGetSingleton(CFMutableArrayRef, SOSGetTransportCircles, sTransportCircles, ^{ + *sTransportCircles = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL); +}); + + +void SOSRegisterTransportMessage(SOSTransportMessageRef additional) { + CFArrayAppendValue(SOSGetTransportMessages(), additional); +} + +void SOSUnregisterTransportMessage(SOSTransportMessageRef removal) { + CFArrayRemoveAllValue(SOSGetTransportMessages(), removal); +} + +void SOSUnregisterAllTransportMessages() { + CFArrayRemoveAllValues(SOSGetTransportMessages()); +} + +void SOSRegisterTransportCircle(SOSTransportCircleRef additional) { + CFArrayAppendValue(SOSGetTransportCircles(), additional); +} + +void SOSUnregisterTransportCircle(SOSTransportCircleRef removal) { + CFArrayRemoveAllValue(SOSGetTransportCircles(), removal); +} + +void SOSUnregisterAllTransportCircles() { + CFArrayRemoveAllValues(SOSGetTransportCircles()); +} + +void SOSRegisterTransportKeyParameter(SOSTransportKeyParameterRef additional) { + CFArrayAppendValue(SOSGetTransportKeyParameters(), additional); +} + +void SOSUnregisterTransportKeyParameter(SOSTransportKeyParameterRef removal) { + CFArrayRemoveAllValue(SOSGetTransportKeyParameters(), removal); +} + +void SOSUnregisterAllTransportKeyParameters() { + CFArrayRemoveAllValues(SOSGetTransportKeyParameters()); +} + +// +// Should we be dispatching back to our queue to handle later +// +void SOSUpdateKeyInterest(void) +{ + CFMutableArrayRef alwaysKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFMutableArrayRef afterFirstUnlockKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFMutableArrayRef whenUnlockedKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFMutableDictionaryRef keyDict = CFDictionaryCreateMutableForCFTypes (kCFAllocatorDefault); + + CFArrayForEach(SOSGetTransportKeyParameters(), ^(const void *value) { + SOSTransportKeyParameterKVSRef tkvs = (SOSTransportKeyParameterKVSRef) value; + CFErrorRef localError = NULL; + + if (!SOSTransportKeyParameterKVSAppendKeyInterests(tkvs, alwaysKeys, afterFirstUnlockKeys, whenUnlockedKeys, &localError)) { + secerror("Error getting key parameters interests %@", localError); + } + CFReleaseNull(localError); + }); + CFMutableDictionaryRef keyParamsDict = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionarySetValue(keyParamsDict, kAlwaysKeys, alwaysKeys); + CFDictionarySetValue(keyParamsDict, kFirstUnlocked, afterFirstUnlockKeys); + CFDictionarySetValue(keyParamsDict, kUnlocked, whenUnlockedKeys); + CFDictionarySetValue(keyDict, kKeyParameter, keyParamsDict); + CFErrorRef updateError = NULL; + CFReleaseNull(alwaysKeys); + CFReleaseNull(afterFirstUnlockKeys); + CFReleaseNull(whenUnlockedKeys); + alwaysKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + afterFirstUnlockKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + whenUnlockedKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + + CFArrayForEach(SOSGetTransportCircles(), ^(const void *value) { + SOSTransportCircleKVSRef tkvs = (SOSTransportCircleKVSRef) value; + CFErrorRef localError = NULL; + + if(!SOSTransportCircleKVSAppendKeyInterest(tkvs, alwaysKeys, afterFirstUnlockKeys, whenUnlockedKeys, &localError)){ + secerror("Error getting circle interests %@", localError); + } + CFReleaseNull(localError); + + }); + CFMutableDictionaryRef circleDict = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionarySetValue(circleDict, kAlwaysKeys, alwaysKeys); + CFDictionarySetValue(circleDict, kFirstUnlocked, afterFirstUnlockKeys); + CFDictionarySetValue(circleDict, kUnlocked, whenUnlockedKeys); + CFDictionarySetValue(keyDict, kCircle, circleDict); + + CFReleaseNull(alwaysKeys); + CFReleaseNull(afterFirstUnlockKeys); + CFReleaseNull(whenUnlockedKeys); + alwaysKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + afterFirstUnlockKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + whenUnlockedKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + + CFArrayForEach(SOSGetTransportMessages(), ^(const void *value) { + SOSTransportMessageKVSRef tkvs = (SOSTransportMessageKVSRef) value; + CFErrorRef localError = NULL; + + if(!SOSTransportMessageKVSAppendKeyInterest(tkvs, alwaysKeys, afterFirstUnlockKeys, whenUnlockedKeys, &localError)){ + secerror("Error getting message interests %@", localError); + } + CFReleaseNull(localError); + + }); + + CFMutableDictionaryRef messageDict = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionarySetValue(messageDict, kAlwaysKeys, alwaysKeys); + CFDictionarySetValue(messageDict, kFirstUnlocked, afterFirstUnlockKeys); + CFDictionarySetValue(messageDict, kUnlocked, whenUnlockedKeys); + CFDictionarySetValue(keyDict, kMessage, messageDict); + + CFReleaseNull(alwaysKeys); + CFReleaseNull(afterFirstUnlockKeys); + CFReleaseNull(whenUnlockedKeys); + alwaysKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + afterFirstUnlockKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + whenUnlockedKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + + + if (!SOSCloudKeychainUpdateKeys(keyDict, &updateError)) + { + secerror("Error updating keys: %@", updateError); + // TODO: propagate error(s) to callers. + } else { + if (CFArrayGetCount(whenUnlockedKeys) == 0) { + secnotice("sync", "Unlocked keys were empty!"); + } + // This leaks 3 CFStringRefs in DEBUG builds. + CFStringRef alwaysKeysDesc = SOSInterestListCopyDescription(alwaysKeys); + CFStringRef afterFirstUnlockKeysDesc = SOSInterestListCopyDescription(afterFirstUnlockKeys); + CFStringRef unlockedKeysDesc = SOSInterestListCopyDescription(whenUnlockedKeys); + secdebug("sync", "Updating interest: always: %@,\nfirstUnlock: %@,\nunlockedKeys: %@", + alwaysKeysDesc, + afterFirstUnlockKeysDesc, + unlockedKeysDesc); + CFReleaseNull(alwaysKeysDesc); + CFReleaseNull(afterFirstUnlockKeysDesc); + CFReleaseNull(unlockedKeysDesc); + } + + CFReleaseNull(updateError); + CFReleaseNull(alwaysKeys); + CFReleaseNull(afterFirstUnlockKeys); + CFReleaseNull(whenUnlockedKeys); + CFReleaseNull(keyParamsDict); + CFReleaseNull(circleDict); + CFReleaseNull(messageDict); + CFReleaseNull(keyDict); +} + + +static void showWhatWasHandled(CFDictionaryRef updates, CFMutableArrayRef handledKeys) { + + CFMutableStringRef updateStr = CFStringCreateMutable(kCFAllocatorDefault, 0); + CFMutableStringRef handledKeysStr = CFStringCreateMutable(kCFAllocatorDefault, 0); + + CFDictionaryForEach(updates, ^(const void *key, const void *value) { + if (isString(key)) { + CFStringAppendFormat(updateStr, NULL, CFSTR("%@ "), (CFStringRef)key); + } + }); + CFArrayForEach(handledKeys, ^(const void *value) { + if (isString(value)) { + CFStringAppendFormat(handledKeysStr, NULL, CFSTR("%@ "), (CFStringRef)value); + } + }); + secnotice("updates", "Updates [%ld]: %@\n", CFDictionaryGetCount(updates), updateStr); + secnotice("updates", "Handled [%ld]: %@\n", CFArrayGetCount(handledKeys), handledKeysStr); + // secnotice("updates", "Updates: %@\n", updates); + // secnotice("updates", "Handled: %@\n", handledKeys); + + CFReleaseSafe(updateStr); + CFReleaseSafe(handledKeysStr); +} + +CF_RETURNS_RETAINED +CFMutableArrayRef SOSTransportDispatchMessages(SOSAccountRef account, CFDictionaryRef updates, CFErrorRef *error){ + + CFMutableArrayRef handledKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + + if(CFDictionaryContainsKey(updates, kSOSKVSAccountChangedKey)){ + // While changing accounts we may modify the key params array. To avoid stepping on ourselves we + // copy the list for iteration. + CFArrayRef originalKeyParams = CFArrayCreateCopy(kCFAllocatorDefault, SOSGetTransportKeyParameters()); + CFArrayForEach(originalKeyParams, ^(const void *value) { + SOSTransportKeyParameterRef tkvs = (SOSTransportKeyParameterRef) value; + if( (SOSTransportKeyParameterGetAccount((SOSTransportKeyParameterRef)value), account)){ + SOSTransportKeyParameterHandleNewAccount(tkvs); + } + }); + CFReleaseNull(originalKeyParams); + CFArrayAppendValue(handledKeys, kSOSKVSAccountChangedKey); + } + + // Iterate through keys in updates. Perform circle change update. + // Then instantiate circles and engines and peers for all peers that + // are receiving a message in updates. + CFMutableDictionaryRef circle_peer_messages_table = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFMutableDictionaryRef circle_circle_messages_table = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFMutableDictionaryRef circle_retirement_messages_table = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + __block CFDataRef newParameters = NULL; + __block bool initial_sync = false; + __block bool new_account = false; + + CFDictionaryForEach(updates, ^(const void *key, const void *value) { + CFErrorRef localError = NULL; + CFStringRef circle_name = NULL; + CFStringRef from_name = NULL; + CFStringRef to_name = NULL; + switch (SOSKVSKeyGetKeyTypeAndParse(key, &circle_name, &from_name, &to_name)) { + case kCircleKey: + CFDictionarySetValue(circle_circle_messages_table, circle_name, value); + break; + case kInitialSyncKey: + initial_sync = true; + break; + case kParametersKey: + if (isData(value)) { + newParameters = (CFDataRef) CFRetainSafe(value); + } + break; + case kMessageKey: { + CFMutableDictionaryRef circle_messages = CFDictionaryEnsureCFDictionaryAndGetCurrentValue(circle_peer_messages_table, circle_name); + CFDictionarySetValue(circle_messages, from_name, value); + break; + } + case kRetirementKey: { + CFMutableDictionaryRef circle_retirements = CFDictionaryEnsureCFDictionaryAndGetCurrentValue(circle_retirement_messages_table, circle_name); + CFDictionarySetValue(circle_retirements, from_name, value); + break; + } + case kAccountChangedKey: + new_account = true; + break; + + case kUnknownKey: + secnotice("updates", "Unknown key '%@', ignoring", key); + break; + + } + + CFReleaseNull(circle_name); + CFReleaseNull(from_name); + CFReleaseNull(to_name); + + if (error && *error) + secerror("Peer message processing error for: %@ -> %@ (%@)", key, value, *error); + if (localError) + secerror("Peer message local processing error for: %@ -> %@ (%@)", key, value, localError); + + CFReleaseNull(localError); + }); + + + if (newParameters) { + CFArrayForEach(SOSGetTransportKeyParameters(), ^(const void *value) { + SOSTransportKeyParameterRef tkvs = (SOSTransportKeyParameterRef) value; + CFErrorRef localError = NULL; + if(CFEqualSafe(SOSTransportKeyParameterGetAccount(tkvs), account)){ + if(!SOSTransportKeyParameterHandleKeyParameterChanges(tkvs, newParameters, localError)) + secerror("Transport failed to handle new key parameters: %@", localError); + } + }); + CFArrayAppendValue(handledKeys, kSOSKVSKeyParametersKey); + } + CFReleaseNull(newParameters); + + if(initial_sync){ + CFArrayAppendValue(handledKeys, kSOSKVSInitialSyncKey); + } + + + if(CFDictionaryGetCount(circle_retirement_messages_table)) { + CFArrayForEach(SOSGetTransportCircles(), ^(const void *value) { + SOSTransportCircleRef tkvs = (SOSTransportCircleRef) value; + if(CFEqualSafe(SOSTransportCircleGetAccount((SOSTransportCircleRef)value), account)){ + CFErrorRef localError = NULL; + CFDictionaryRef handledRetirementKeys = SOSTransportCircleHandleRetirementMessages(tkvs, circle_retirement_messages_table, error); + if(handledRetirementKeys == NULL){ + secerror("Transport failed to handle retirement messages: %@", localError); + } else { + CFDictionaryForEach(handledRetirementKeys, ^(const void *key, const void *value) { + CFStringRef circle_name = (CFStringRef)key; + CFArrayRef handledPeerIDs = (CFArrayRef)value; + CFArrayForEach(handledPeerIDs, ^(const void *value) { + CFStringRef peer_id = (CFStringRef)value; + CFStringRef keyHandled = SOSRetirementKeyCreateWithCircleNameAndPeer(circle_name, peer_id); + CFArrayAppendValue(handledKeys, keyHandled); + CFReleaseNull(keyHandled); + }); + }); + } + CFReleaseNull(handledRetirementKeys); + CFReleaseNull(localError); + } + }); + } + + if(CFDictionaryGetCount(circle_circle_messages_table)) { + CFArrayForEach(SOSGetTransportCircles(), ^(const void *value) { + SOSTransportCircleRef tkvs = (SOSTransportCircleRef) value; + if(CFEqualSafe(SOSTransportCircleGetAccount((SOSTransportCircleRef)value), account)){ + CFArrayRef handleCircleMessages = SOSTransportCircleHandleCircleMessages(tkvs, circle_circle_messages_table, error); + CFErrorRef localError = NULL; + if(handleCircleMessages == NULL){ + secerror("Transport failed to handle circle messages: %@", localError); + } else if(CFArrayGetCount(handleCircleMessages) == 0) { + if(CFDictionaryGetCount(circle_circle_messages_table) != 0) { + secerror("Transport failed to process all circle messages: (%ld/%ld) %@", + CFArrayGetCount(handleCircleMessages), + CFDictionaryGetCount(circle_circle_messages_table), localError); + } else { + secnotice("circle", "Transport handled no circle messages"); + } + } else { + CFArrayForEach(handleCircleMessages, ^(const void *value) { + CFStringRef keyHandled = SOSCircleKeyCreateWithName((CFStringRef)value, error); + CFArrayAppendValue(handledKeys, keyHandled); + CFReleaseNull(keyHandled); + }); + } + CFReleaseNull(localError); + + if (!SOSTransportCircleFlushChanges(tkvs, &localError)) + secerror("error flushing changes: %@", localError); + + CFReleaseNull(localError); + CFReleaseNull(handleCircleMessages); + } + + }); + } + // TODO: These should all produce circle -> messageTypeHandled messages + // That probably needs to wait for separation of transport types. + if(CFDictionaryGetCount(circle_peer_messages_table)) { + CFArrayForEach(SOSGetTransportMessages(), ^(const void *value) { + SOSTransportMessageRef tkvs = (SOSTransportMessageRef) value; + if(CFEqualSafe(SOSTransportMessageGetAccount((SOSTransportMessageRef)value), account)){ + CFErrorRef handleMessagesError = NULL; + CFDictionaryRef handledPeers = SOSTransportMessageHandleMessages(tkvs, circle_peer_messages_table, &handleMessagesError); + + if (handledPeers) { + // We need to look for and send responses. + + CFErrorRef syncError = NULL; + if (!SOSTransportMessageSyncWithPeers((SOSTransportMessageRef)tkvs, handledPeers, &syncError)) { + secerror("Sync with peers failed: %@", syncError); + } + + CFDictionaryForEach(handledPeers, ^(const void *key, const void *value) { + if (isString(key) && isArray(value)) { + CFArrayForEach(value, ^(const void *value) { + if (isString(value)) { + CFStringRef peerID = (CFStringRef) value; + + CFStringRef kvsHandledKey = SOSMessageKeyCreateFromPeerToTransport((SOSTransportMessageKVSRef)tkvs, peerID); + CFArrayAppendValue(handledKeys, kvsHandledKey); + CFReleaseSafe(kvsHandledKey); + } + }); + } + }); + + CFErrorRef flushError = NULL; + if (!SOSTransportMessageFlushChanges((SOSTransportMessageRef)tkvs, &flushError)) { + secerror("Flush failed: %@", flushError); + } + } + else { + secerror("Didn't handle? : %@", handleMessagesError); + } + CFReleaseNull(handledPeers); + CFReleaseNull(handleMessagesError); + } + }); + } + CFReleaseNull(circle_retirement_messages_table); + CFReleaseNull(circle_circle_messages_table); + CFReleaseNull(circle_peer_messages_table); + + + + showWhatWasHandled(updates, handledKeys); + + return handledKeys; +} + + diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSTransport.h b/Security/sec/SOSCircle/SecureObjectSync/SOSTransport.h new file mode 100644 index 00000000..c0868baa --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSTransport.h @@ -0,0 +1,26 @@ + + +#ifndef SOSTransport_h +#define SOSTransport_h +#include +#include +#include + +CF_RETURNS_RETAINED CFMutableArrayRef SOSTransportDispatchMessages(SOSAccountRef account, CFDictionaryRef updates, CFErrorRef *error); + +void SOSRegisterTransportMessage(SOSTransportMessageRef additional); +void SOSUnregisterTransportMessage(SOSTransportMessageRef removal); + +void SOSRegisterTransportCircle(SOSTransportCircleRef additional); +void SOSUnregisterTransportCircle(SOSTransportCircleRef removal); + +void SOSRegisterTransportKeyParameter(SOSTransportKeyParameterRef additional); +void SOSUnregisterTransportKeyParameter(SOSTransportKeyParameterRef removal); +void SOSUnregisterAllTransportMessages(void); +void SOSUnregisterAllTransportCircles(void); +void SOSUnregisterAllTransportKeyParameters(void); + + +void SOSUpdateKeyInterest(void); + +#endif diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSTransportCircle.c b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportCircle.c new file mode 100644 index 00000000..13abb72b --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportCircle.c @@ -0,0 +1,76 @@ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +CFGiblisWithCompareFor(SOSTransportCircle); + +SOSTransportCircleRef SOSTransportCircleCreateForSubclass(size_t size, SOSAccountRef account, CFErrorRef *error) +{ + SOSTransportCircleRef tpt = CFTypeAllocateWithSpace(SOSTransportCircle, size, kCFAllocatorDefault); + tpt->account = CFRetainSafe(account); + return tpt; +} + +static CFStringRef SOSTransportCircleCopyDescription(CFTypeRef aObj) { + SOSTransportCircleRef t = (SOSTransportCircleRef) aObj; + + return CFStringCreateWithFormat(NULL, NULL, CFSTR(""), t); +} + +static void SOSTransportCircleDestroy(CFTypeRef aObj) { + SOSTransportCircleRef transport = (SOSTransportCircleRef) aObj; + if(transport->destroy) + transport->destroy(transport); + CFReleaseNull(transport->account); +} + +static CFHashCode SOSTransportCircleHash(CFTypeRef obj) +{ + return (intptr_t) obj; +} + +static Boolean SOSTransportCircleCompare(CFTypeRef lhs, CFTypeRef rhs) +{ + return SOSTransportCircleHash(lhs) == SOSTransportCircleHash(rhs); +} + +SOSAccountRef SOSTransportCircleGetAccount(SOSTransportCircleRef transport){ + return transport->account; +} + +bool SOSTransportCircleFlushChanges(SOSTransportCircleRef transport, CFErrorRef *error) { + return transport->flushChanges(transport, error); +} + +bool SOSTransportCirclePostCircle(SOSTransportCircleRef transport, CFStringRef circleName, CFDataRef circle_data, CFErrorRef *error) { + return transport->postCircle(transport, circleName, circle_data, error); +} +CF_RETURNS_RETAINED +CFDictionaryRef SOSTransportCircleHandleRetirementMessages(SOSTransportCircleRef transport, CFMutableDictionaryRef circle_retirement_messages_table, CFErrorRef *error) { + return transport->handleRetirementMessages(transport, circle_retirement_messages_table, error); +} + +CF_RETURNS_RETAINED +CFArrayRef SOSTransportCircleHandleCircleMessages(SOSTransportCircleRef transport, CFMutableDictionaryRef circle_circle_messages_table, CFErrorRef *error) { + return transport->handleCircleMessages(transport, circle_circle_messages_table, error); +} + +bool SOSTransportCirclePostRetirement(SOSTransportCircleRef transport, CFStringRef circleName, CFStringRef peer_id, CFDataRef retirement_data, CFErrorRef *error) { + return transport->postRetirement(transport, circleName, peer_id, retirement_data, error); +} + +bool SOSTransportCircleExpireRetirementRecords(SOSTransportCircleRef transport, CFDictionaryRef retirements, CFErrorRef *error){ + return transport->expireRetirementRecords(transport, retirements, error); +} + + diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSTransportCircle.h b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportCircle.h new file mode 100644 index 00000000..dc6eae9b --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportCircle.h @@ -0,0 +1,45 @@ + +#ifndef SOSTransportCircle_h +#define SOSTransportCircle_h + +#include +#include +#include + +typedef struct __OpaqueSOSTransportCircle * SOSTransportCircleRef; + +struct __OpaqueSOSTransportCircle { + CFRuntimeBase _base; + SOSAccountRef account; + + CFStringRef (*copyDescription)(SOSTransportCircleRef transport); + void (*destroy)(SOSTransportCircleRef transport); + + bool (*postRetirement)(SOSTransportCircleRef transport, CFStringRef circleName, CFStringRef peer_id, CFDataRef retirement_data, CFErrorRef *error); + bool (*expireRetirementRecords)(SOSTransportCircleRef transport, CFDictionaryRef retirements, CFErrorRef *error); + bool (*flushChanges)(SOSTransportCircleRef transport, CFErrorRef *error); + bool (*postCircle)(SOSTransportCircleRef transport, CFStringRef circleName, CFDataRef circle_data, CFErrorRef *error); + CFDictionaryRef (*handleRetirementMessages)(SOSTransportCircleRef transport, CFMutableDictionaryRef circle_retirement_messages_table, CFErrorRef *error); + CFArrayRef (*handleCircleMessages)(SOSTransportCircleRef transport, CFMutableDictionaryRef circle_circle_messages_table, CFErrorRef *error); + +}; + +SOSTransportCircleRef SOSTransportCircleCreateForSubclass(size_t size, SOSAccountRef account, CFErrorRef *error); + +bool SOSTransportCirclePostCircle(SOSTransportCircleRef transport, CFStringRef circleName, CFDataRef circle_data, CFErrorRef *error); + +bool SOSTransportCirclePostRetirement(SOSTransportCircleRef transport, CFStringRef circleName, CFStringRef peer_id, CFDataRef retirement_data, CFErrorRef *error); + +bool SOSTransportCircleExpireRetirementRecords(SOSTransportCircleRef transport, CFDictionaryRef retirements, CFErrorRef *error); + +bool SOSTransportCircleFlushChanges(SOSTransportCircleRef transport, CFErrorRef *error); + + +SOSAccountRef SOSTransportCircleGetAccount(SOSTransportCircleRef transport); +CF_RETURNS_RETAINED CFDictionaryRef SOSTransportCircleHandleRetirementMessages(SOSTransportCircleRef transport, CFMutableDictionaryRef circle_retirement_messages_table, CFErrorRef *error); + + +CF_RETURNS_RETAINED CFArrayRef SOSTransportCircleHandleCircleMessages(SOSTransportCircleRef transport, CFMutableDictionaryRef circle_circle_messages_table, CFErrorRef *error); + + +#endif diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSTransportCircleKVS.c b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportCircleKVS.c new file mode 100644 index 00000000..fd726f03 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportCircleKVS.c @@ -0,0 +1,249 @@ +// +// SOSTransportCircleKVS.c +// sec +// +#include +#include +#include +#include +#include +#include +#include +#include + +static bool SOSTransportCircleKVSUpdateRetirementRecords(SOSTransportCircleKVSRef transport, CFDictionaryRef updates, CFErrorRef* error); +static bool SOSTransportCircleKVSUpdateKVS(SOSTransportCircleRef transport, CFDictionaryRef changes, CFErrorRef *error); +static bool expireRetirementRecords(SOSTransportCircleRef transport, CFDictionaryRef retirements, CFErrorRef *error); +static CFArrayRef handleCircleMessages(SOSTransportCircleRef transport, CFMutableDictionaryRef circle_circle_messages_table, CFErrorRef *error); +static void destroy(SOSTransportCircleRef transport); +static bool postCircle(SOSTransportCircleRef transport, CFStringRef circleName, CFDataRef circle_data, CFErrorRef *error); +static CFDictionaryRef handleRetirementMessages(SOSTransportCircleRef transport, CFMutableDictionaryRef circle_retirement_messages_table, CFErrorRef *error); +static inline bool postRetirement(SOSTransportCircleRef transport, CFStringRef circleName, CFStringRef peer_id, CFDataRef retirement_data, CFErrorRef *error); +static inline bool flushChanges(SOSTransportCircleRef transport, CFErrorRef *error); + + +struct __OpaqueSOSTransportCircleKVS{ + struct __OpaqueSOSTransportCircle c; + CFMutableDictionaryRef pending_changes; + CFStringRef circleName; +}; + + +SOSTransportCircleKVSRef SOSTransportCircleKVSCreate(SOSAccountRef account, CFStringRef circleName, CFErrorRef *error){ + SOSTransportCircleKVSRef t = (SOSTransportCircleKVSRef) SOSTransportCircleCreateForSubclass(sizeof(struct __OpaqueSOSTransportCircleKVS) - sizeof(CFRuntimeBase), account, error); + if(t){ + t->circleName = CFRetainSafe(circleName); + t->c.expireRetirementRecords = expireRetirementRecords; + t->c.postCircle = postCircle; + t->c.postRetirement = postRetirement; + t->c.flushChanges = flushChanges; + t->pending_changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + t->c.handleRetirementMessages = handleRetirementMessages; + t->c.handleCircleMessages = handleCircleMessages; + t->c.destroy = destroy; + SOSRegisterTransportCircle((SOSTransportCircleRef)t); + } + return t; +} + +static CFStringRef SOSTransportCircleKVSGetCircleName(SOSTransportCircleKVSRef transport){ + return transport->circleName; +} + +static void destroy(SOSTransportCircleRef transport){ + SOSTransportCircleKVSRef tkvs = (SOSTransportCircleKVSRef)transport; + CFReleaseNull(tkvs->pending_changes); + CFReleaseNull(tkvs->circleName); + + SOSUnregisterTransportCircle((SOSTransportCircleRef)tkvs); +} + +bool SOSTransportCircleKVSSendPendingChanges(SOSTransportCircleKVSRef transport, CFErrorRef *error) { + CFErrorRef changeError = NULL; + + if (transport->pending_changes == NULL || CFDictionaryGetCount(transport->pending_changes) == 0) { + CFReleaseNull(transport->pending_changes); + return true; + } + + bool success = SOSTransportCircleKVSUpdateKVS((SOSTransportCircleRef)transport, transport->pending_changes, &changeError); + if (success) { + CFDictionaryRemoveAllValues(transport->pending_changes); + } else { + SOSCreateErrorWithFormat(kSOSErrorSendFailure, changeError, error, NULL, + CFSTR("Send changes block failed [%@]"), transport->pending_changes); + } + + return success; +} + +void SOSTransportCircleKVSAddToPendingChanges(SOSTransportCircleKVSRef transport, CFStringRef message_key, CFDataRef message_data){ + + if (transport->pending_changes == NULL) { + transport->pending_changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + } + if (message_data == NULL) { + CFDictionarySetValue(transport->pending_changes, message_key, kCFNull); + } else { + CFDictionarySetValue(transport->pending_changes, message_key, message_data); + } +} + +static bool expireRetirementRecords(SOSTransportCircleRef transport, CFDictionaryRef retirements, CFErrorRef *error) { + + bool success = true; + CFMutableDictionaryRef keysToWrite = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + + CFDictionaryForEach(retirements, ^(const void *key, const void *value) { + if (isString(key) && isArray(value)) { + CFStringRef circle_name = (CFStringRef) key; + CFArrayRef retirees = (CFArrayRef) value; + + CFArrayForEach(retirees, ^(const void *value) { + if (isString(value)) { + CFStringRef retiree_id = (CFStringRef) value; + + CFStringRef kvsKey = SOSRetirementKeyCreateWithCircleNameAndPeer(circle_name, retiree_id); + + CFDictionaryAddValue(keysToWrite, kvsKey, kCFNull); + + CFReleaseSafe(kvsKey); + } + }); + } + }); + + if(CFDictionaryGetCount(keysToWrite)) { + success = SOSTransportCircleKVSUpdateRetirementRecords((SOSTransportCircleKVSRef)transport, keysToWrite, error); + } + CFReleaseNull(keysToWrite); + + return success; +} + +static bool SOSTransportCircleKVSUpdateRetirementRecords(SOSTransportCircleKVSRef transport, CFDictionaryRef updates, CFErrorRef* error){ + CFErrorRef updateError = NULL; + bool success = false; + if (SOSTransportCircleKVSUpdateKVS((SOSTransportCircleRef)transport, updates, &updateError)){ + success = true; + } else { + SOSCreateErrorWithFormat(kSOSErrorSendFailure, updateError, error, NULL, + CFSTR("update parameters key failed [%@]"), updates); + } + return success; +} + +static inline bool postRetirement(SOSTransportCircleRef transport, CFStringRef circleName, CFStringRef peer_id, CFDataRef retirement_data, CFErrorRef *error) +{ + CFStringRef retirement_key = SOSRetirementKeyCreateWithCircleNameAndPeer(circleName, peer_id); + if (retirement_key) + SOSTransportCircleKVSAddToPendingChanges((SOSTransportCircleKVSRef)transport, retirement_key, retirement_data); + + CFReleaseNull(retirement_key); + return true; +} + +static inline bool flushChanges(SOSTransportCircleRef transport, CFErrorRef *error) +{ + SOSTransportCircleKVSRef tkvs = (SOSTransportCircleKVSRef) transport; + + return SOSTransportCircleKVSSendPendingChanges(tkvs, error); +} + +static bool postCircle(SOSTransportCircleRef transport, CFStringRef circleName, CFDataRef circle_data, CFErrorRef *error){ + SOSTransportCircleKVSRef tkvs = (SOSTransportCircleKVSRef)transport; + CFStringRef circle_key = SOSCircleKeyCreateWithName(circleName, error); + if (circle_key) + SOSTransportCircleKVSAddToPendingChanges(tkvs, circle_key, circle_data); + CFReleaseNull(circle_key); + + return true; +} + +static CFDictionaryRef handleRetirementMessages(SOSTransportCircleRef transport, CFMutableDictionaryRef circle_retirement_messages_table, CFErrorRef *error){ + SOSAccountRef account = SOSTransportCircleGetAccount(transport); + CFMutableDictionaryRef handledRetirementMessages = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionaryForEach(circle_retirement_messages_table, ^(const void *key, const void *value) { + if (isString(key) && isDictionary(value)) { + CFStringRef circle_name = (CFStringRef) key; + + CFDictionaryRef retirment_dictionary = (CFDictionaryRef) value; + CFDictionaryForEach(retirment_dictionary, ^(const void *key, const void *value) { + if(isData(value)) { + SOSPeerInfoRef pi = SOSPeerInfoCreateFromData(NULL, error, (CFDataRef) value); + if(pi && CFEqual(key, SOSPeerInfoGetPeerID(pi)) && SOSPeerInfoInspectRetirementTicket(pi, error)) { + CFMutableDictionaryRef circle_retirements = CFDictionaryEnsureCFDictionaryAndGetCurrentValue(account->retired_peers, circle_name); + CFDictionarySetValue(circle_retirements, key, value); + + SOSAccountRecordRetiredPeerInCircleNamed(account, circle_name, pi); + + CFMutableArrayRef handledRetirementIDs = CFDictionaryEnsureCFArrayAndGetCurrentValue(handledRetirementMessages, circle_name); + CFArrayAppendValue(handledRetirementIDs, SOSPeerInfoGetPeerID(pi)); + } + CFReleaseSafe(pi); + } + }); + } + }); + return handledRetirementMessages; +} + +static CFArrayRef handleCircleMessages(SOSTransportCircleRef transport, CFMutableDictionaryRef circle_circle_messages_table, CFErrorRef *error){ + CFMutableArrayRef handledKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionaryForEach(circle_circle_messages_table, ^(const void *key, const void *value) { + CFErrorRef circleMessageError = NULL; + if (!SOSAccountHandleCircleMessage(SOSTransportCircleGetAccount(transport), key, value, &circleMessageError)) { + secerror("Error handling circle message %@ (%@): %@", key, value, circleMessageError); + } + else{ + CFStringRef circle_id = (CFStringRef) key; + CFArrayAppendValue(handledKeys, circle_id); + } + CFReleaseNull(circleMessageError); + }); + + return handledKeys; +} + +bool SOSTransportCircleKVSAppendKeyInterest(SOSTransportCircleKVSRef transport, CFMutableArrayRef alwaysKeys, CFMutableArrayRef afterFirstUnlockKeys, CFMutableArrayRef unlockedKeys, CFErrorRef *error){ + + CFStringRef circle_name = NULL; + CFStringRef circle_key = NULL; + + if(SOSAccountHasPublicKey(SOSTransportCircleGetAccount((SOSTransportCircleRef)transport), NULL)){ + require_quiet(circle_name = SOSTransportCircleKVSGetCircleName(transport), fail); + require_quiet(circle_key = SOSCircleKeyCreateWithName(circle_name, error), fail); + + SOSAccountRef account = SOSTransportCircleGetAccount((SOSTransportCircleRef)transport); + require_quiet(account, fail); + SOSCircleRef circle = SOSAccountFindCircle(account, circle_name, error); + require_quiet(circle, fail); + + SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { + CFStringRef retirement_key = SOSRetirementKeyCreateWithCircleNameAndPeer(circle_name, SOSPeerInfoGetPeerID(peer)); + CFArrayAppendValue(alwaysKeys, retirement_key); + CFReleaseNull(retirement_key); + }); + + CFArrayAppendValue(alwaysKeys, circle_key); + + CFReleaseNull(circle_key); + } + return true; + +fail: + CFReleaseNull(circle_key); + return false; +} + +static bool SOSTransportCircleKVSUpdateKVS(SOSTransportCircleRef transport, CFDictionaryRef changes, CFErrorRef *error){ + CloudKeychainReplyBlock log_error = ^(CFDictionaryRef returnedValues __unused, CFErrorRef error) { + if (error) { + secerror("Error putting: %@", error); + CFReleaseSafe(error); + } + }; + + SOSCloudKeychainPutObjectsInCloud(changes, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), log_error); + return true; +} diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSTransportCircleKVS.h b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportCircleKVS.h new file mode 100644 index 00000000..eaf16d1c --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportCircleKVS.h @@ -0,0 +1,19 @@ + + +#ifndef sec_SOSTransportCircleKVS_h +#define sec_SOSTransportCircleKVS_h + +#include + +typedef struct __OpaqueSOSTransportCircleKVS * SOSTransportCircleKVSRef; + +SOSTransportCircleKVSRef SOSTransportCircleKVSCreate(SOSAccountRef account, CFStringRef circleName, CFErrorRef *error); +SOSTransportKeyParameterRef SOSTransportKeyParameterCreateForSubclass(size_t size, SOSAccountRef account, CFErrorRef *error); + +bool SOSTransportCircleKVSAppendKeyInterest(SOSTransportCircleKVSRef transport, CFMutableArrayRef alwaysKeys, CFMutableArrayRef afterFirstUnlockKeys, CFMutableArrayRef unlockedKeys, CFErrorRef *error); + +void SOSTransportCircleKVSAddToPendingChanges(SOSTransportCircleKVSRef transport, CFStringRef message_key, CFDataRef message_data); +bool SOSTransportCircleKVSSendPendingChanges(SOSTransportCircleKVSRef transport, CFErrorRef *error); + + +#endif diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSTransportCoder.c b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportCoder.c new file mode 100644 index 00000000..fe9a2e4a --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportCoder.c @@ -0,0 +1,221 @@ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + + +// For now transport (the abstract class) consumes the Transport data in engine to hold +// coder state. +static SOSCoderRef SOSTransportMessageCopyPeerCoder(SOSTransportMessageRef transport, CFStringRef peer_id){ + SOSCoderRef coder = NULL; + + CFDataRef coderData = SOSEngineGetTransportData(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 = SOSEngineSetTransportData(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 = SOSEngineGetTransportData(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); + coder = SOSCoderCreate(peerInfo, myPeerInfo, 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. + secnotice("transport", "%@ transport stale event ignored", peer_id); + break; + 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; + +} + +#warning 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)) { + secnotice("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); + secnotice("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/Security/sec/SOSCircle/SecureObjectSync/SOSTransportCoder.h b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportCoder.h new file mode 100644 index 00000000..5dd5e252 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportCoder.h @@ -0,0 +1,19 @@ + +#ifndef SOSTransportCoder_h +#define SOSTransportCoder_h +#include +#include + +enum SOSCoderUnwrapStatus{ + SOSCoderUnwrapError = 0, + SOSCoderUnwrapDecoded = 1, + SOSCoderUnwrapHandled = 2 +}; + +enum SOSCoderUnwrapStatus SOSTransportMessageHandleCoderMessage(SOSTransportMessageRef transport, CFStringRef peer_id, CFDataRef codedMessage, CFDataRef *decodedMessage, CFErrorRef *error); + +bool SOSTransportMessageSavePeerCoderData(SOSTransportMessageRef transport, SOSCoderRef coder, CFStringRef peer_id, CFErrorRef *error); + + + +#endif diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSTransportKeyParameter.c b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportKeyParameter.c new file mode 100644 index 00000000..ece0dcd0 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportKeyParameter.c @@ -0,0 +1,62 @@ + +#include +#include +#include +#include + +#include +#include +#include + +CFGiblisWithCompareFor(SOSTransportKeyParameter); + +SOSTransportKeyParameterRef SOSTransportKeyParameterCreateForSubclass(size_t size, SOSAccountRef account, CFErrorRef *error) +{ + SOSTransportKeyParameterRef tpt = CFTypeAllocateWithSpace(SOSTransportKeyParameter, size, kCFAllocatorDefault); + tpt->account = CFRetainSafe(account); + return tpt; +} + +bool SOSTransportKeyParameterHandleNewAccount(SOSTransportKeyParameterRef transport){ + return transport->setToNewAccount(transport); +} + +static CFStringRef SOSTransportKeyParameterCopyDescription(CFTypeRef aObj) { + SOSTransportKeyParameterRef t = (SOSTransportKeyParameterRef) aObj; + + return CFStringCreateWithFormat(NULL, NULL, CFSTR(""), t); +} + +static void SOSTransportKeyParameterDestroy(CFTypeRef aObj) { + SOSTransportKeyParameterRef transport = (SOSTransportKeyParameterRef) aObj; + + if(transport->destroy) + transport->destroy(transport); + + CFReleaseNull(transport->account); + +} + +bool SOSTransportKeyParameterHandleKeyParameterChanges(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef error){ + return transport->handleKeyParameterChanges(transport, data, error); +} + + +static CFHashCode SOSTransportKeyParameterHash(CFTypeRef obj) +{ + return (intptr_t) obj; +} + +static Boolean SOSTransportKeyParameterCompare(CFTypeRef lhs, CFTypeRef rhs) +{ + return SOSTransportKeyParameterHash(lhs) == SOSTransportKeyParameterHash(rhs); +} + + +bool SOSTrasnportKeyParameterPublishCloudParameters(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef* error) { + return transport->publishCloudParameters(transport, data, error); +} + +SOSAccountRef SOSTransportKeyParameterGetAccount(SOSTransportKeyParameterRef transport){ + return transport->account; +} diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSTransportKeyParameter.h b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportKeyParameter.h new file mode 100644 index 00000000..64d8ed4a --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportKeyParameter.h @@ -0,0 +1,34 @@ + +#ifndef SOSTransportKeyParameter_h +#define SOSTransportKeyParameter_h + +#include +#include +#include + +typedef struct __OpaqueSOSTransportKeyParameter * SOSTransportKeyParameterRef; + +struct __OpaqueSOSTransportKeyParameter { + CFRuntimeBase _base; + SOSAccountRef account; + /* Connections from CF land to vtable land */ + CFStringRef (*copyDescription)(SOSTransportKeyParameterRef object); + void (*destroy)(SOSTransportKeyParameterRef object); + + + // TODO: Make this take broader parameters and assemble the key parameters blob? + bool (*publishCloudParameters)(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef* error); + bool (*handleKeyParameterChanges)(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef error); + bool (*setToNewAccount)(SOSTransportKeyParameterRef transport); +}; + +bool SOSTrasnportKeyParameterPublishCloudParameters(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef* error); + +bool SOSTrasnportKeyParameterPublishCloudParameters(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef* error); +SOSTransportKeyParameterRef SOSTransportKeyParameterCreateForSubclass(size_t size, SOSAccountRef account, CFErrorRef *error); +bool SOSTransportKeyParameterHandleKeyParameterChanges(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef error); +bool SOSTransportKeyParameterHandleNewAccount(SOSTransportKeyParameterRef transport); + +SOSAccountRef SOSTransportKeyParameterGetAccount(SOSTransportKeyParameterRef transport); + +#endif diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSTransportKeyParameterKVS.c b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportKeyParameterKVS.c new file mode 100644 index 00000000..2c9e88cd --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportKeyParameterKVS.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include +#include +#include + +static bool SOSTransportKeyParameterKVSPublishCloudParameters(SOSTransportKeyParameterKVSRef transport, CFDataRef newParameters, CFErrorRef *error); +static bool publishCloudParameters(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef* error); +static bool SOSTransportKeyParameterKVSUpdateKVS(CFDictionaryRef changes, CFErrorRef *error); +static void destroy(SOSTransportKeyParameterRef transport); + +struct __OpaqueSOSTransportKeyParameterKVS{ + struct __OpaqueSOSTransportKeyParameter k; +}; + +static bool handleKeyParameterChanges(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef error){ + SOSAccountRef account = transport->account; + return SOSAccountHandleParametersChange(account, data, &error); + +} + +static bool setToNewAccount(SOSTransportKeyParameterRef transport){ + SOSAccountRef account = transport->account; + SOSAccountSetToNew(account); + return true; +} + +SOSTransportKeyParameterKVSRef SOSTransportKeyParameterKVSCreate(SOSAccountRef account, CFErrorRef *error) { + SOSTransportKeyParameterKVSRef tkvs = (SOSTransportKeyParameterKVSRef) SOSTransportKeyParameterCreateForSubclass(sizeof(struct __OpaqueSOSTransportKeyParameterKVS) - sizeof(CFRuntimeBase), account, error); + if(tkvs){ + tkvs->k.publishCloudParameters = publishCloudParameters; + tkvs->k.handleKeyParameterChanges = handleKeyParameterChanges; + tkvs->k.setToNewAccount = setToNewAccount; + tkvs->k.destroy = destroy; + SOSRegisterTransportKeyParameter((SOSTransportKeyParameterRef)tkvs); + } + return tkvs; +} + +static void destroy(SOSTransportKeyParameterRef transport){ + SOSUnregisterTransportKeyParameter(transport); +} + +bool SOSTransportKeyParameterKVSHandleCloudParameterChange(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef* error){ + SOSTransportKeyParameterKVSRef tkvs = (SOSTransportKeyParameterKVSRef)transport; + SOSAccountRef account = tkvs->k.account; + + return SOSAccountHandleParametersChange(account, data, error); +} + + +bool SOSTransportKeyParameterKVSAppendKeyInterests(SOSTransportKeyParameterKVSRef transport, CFMutableArrayRef alwaysKeys, CFMutableArrayRef afterFirstUnlockKeys, CFMutableArrayRef unlockedKeys, CFErrorRef*error){ + + CFArrayAppendValue(alwaysKeys, kSOSKVSKeyParametersKey); + + return true; +} + +static bool publishCloudParameters(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef* error) +{ + return SOSTransportKeyParameterKVSPublishCloudParameters((SOSTransportKeyParameterKVSRef)transport, data, error); +} + +static bool SOSTransportKeyParameterKVSUpdateKVS(CFDictionaryRef changes, CFErrorRef *error){ + CloudKeychainReplyBlock log_error = ^(CFDictionaryRef returnedValues __unused, CFErrorRef error) { + if (error) { + secerror("Error putting: %@", error); + CFReleaseSafe(error); + } + }; + + SOSCloudKeychainPutObjectsInCloud(changes, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), log_error); + return true; +} + +static bool SOSTransportKeyParameterKVSPublishCloudParameters(SOSTransportKeyParameterKVSRef transport, CFDataRef newParameters, CFErrorRef *error) +{ + CFDictionaryRef changes = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSOSKVSKeyParametersKey, newParameters, + NULL); + + bool success = SOSTransportKeyParameterKVSUpdateKVS(changes, error); + + CFReleaseNull(changes); + + return success; +} diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSTransportKeyParameterKVS.h b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportKeyParameterKVS.h new file mode 100644 index 00000000..7e9b6bea --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportKeyParameterKVS.h @@ -0,0 +1,16 @@ + +#ifndef sec_SOSTransportKeyParameterKVS_h +#define sec_SOSTransportKeyParameterKVS_h + + +typedef struct __OpaqueSOSTransportKeyParameterKVS *SOSTransportKeyParameterKVSRef; + +bool SOSTransportKeyParameterKVSHandleCloudParameterChange(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef* error); +bool SOSTransportKeyParameterKVSAppendKeyInterests(SOSTransportKeyParameterKVSRef transport, CFMutableArrayRef alwaysKeys, CFMutableArrayRef afterFirstUnlockKeys, CFMutableArrayRef unlockedKeys, CFErrorRef *error); +SOSTransportKeyParameterKVSRef SOSTransportKeyParameterKVSCreate(SOSAccountRef account, CFErrorRef *error); +bool SOSTransportKeyParameterHandleKeyParameterChanges(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef error); + +bool SOSTransportKeyParameterHandleNewAccount(SOSTransportKeyParameterRef transport); + +#endif + diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSTransportMessage.c b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportMessage.c new file mode 100644 index 00000000..2130e61e --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportMessage.c @@ -0,0 +1,172 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +CFGiblisWithHashFor(SOSTransportMessage); + +SOSTransportMessageRef SOSTransportMessageCreateForSubclass(size_t size, + SOSAccountRef account, CFStringRef circleName, + CFErrorRef *error) +{ + SOSTransportMessageRef tpt = CFTypeAllocateWithSpace(SOSTransportMessage, size, kCFAllocatorDefault); + + SOSEngineRef engine = SOSDataSourceFactoryGetEngineForDataSourceName(account->factory, circleName, error); + + tpt->engine = CFRetainSafe(engine); + tpt->account = CFRetainSafe(account); + return tpt; +} + + +static CFStringRef SOSTransportMessageCopyDescription(CFTypeRef aObj){ + SOSTransportMessageRef t = (SOSTransportMessageRef) aObj; + + return t->copyDescription ? t->copyDescription(t) + : CFStringCreateWithFormat(NULL, NULL, CFSTR(""), t); +} + +static void SOSTransportMessageDestroy(CFTypeRef aObj){ + SOSTransportMessageRef transport = (SOSTransportMessageRef) aObj; + + if (transport->destroy) + transport->destroy(transport); + + CFReleaseSafe(transport->engine); +} + +SOSAccountRef SOSTransportMessageGetAccount(SOSTransportMessageRef transport){ + return transport->account; +} + +static CFHashCode SOSTransportMessageHash(CFTypeRef obj){ + return (intptr_t) obj; +} + +static Boolean SOSTransportMessageCompare(CFTypeRef lhs, CFTypeRef rhs){ + return SOSTransportMessageHash(lhs) == SOSTransportMessageHash(rhs); +} + +bool SOSTransportMessageSendMessages(SOSTransportMessageRef transport, CFDictionaryRef circle_messages, CFErrorRef *error) { + return transport->sendMessages(transport, circle_messages, error); +} + +bool SOSTransportMessageFlushChanges(SOSTransportMessageRef transport, CFErrorRef *error){ + return transport->flushChanges(transport, error); +} + +bool SOSTransportMessageSyncWithPeers(SOSTransportMessageRef transport, CFDictionaryRef circleToPeerIDs, CFErrorRef *error){ + return transport->syncWithPeers(transport, circleToPeerIDs, error); +} + +bool SOSTransportMessageCleanupAfterPeerMessages(SOSTransportMessageRef transport, CFDictionaryRef circleToPeerIDs, CFErrorRef* error){ + return transport->cleanupAfterPeerMessages(transport, circleToPeerIDs, error); +} + +CF_RETURNS_RETAINED +CFDictionaryRef SOSTransportMessageHandleMessages(SOSTransportMessageRef transport, CFMutableDictionaryRef circle_peer_messages_table, CFErrorRef *error){ + return transport->handleMessages(transport, circle_peer_messages_table, error); +} + +SOSEngineRef SOSTransportMessageGetEngine(SOSTransportMessageRef transport){ + return transport->engine; +} + + +bool SOSTransportMessageHandlePeerMessage(SOSTransportMessageRef transport, CFStringRef peer_id, CFDataRef codedMessage, CFErrorRef *error){ + + CFDataRef decodedMessage = NULL; + bool result = false; + + SOSPeerRef peer = SOSPeerCreateWithEngine(SOSTransportMessageGetEngine(transport), peer_id); + + enum SOSCoderUnwrapStatus uwstatus = SOSPeerHandleCoderMessage(peer, peer_id, codedMessage, &decodedMessage, error); + + if (uwstatus == SOSCoderUnwrapDecoded) { + result = SOSEngineHandleMessage(SOSTransportMessageGetEngine(transport), peer_id, decodedMessage, error); + } else { + result = uwstatus != SOSCoderUnwrapError; + } + CFReleaseNull(decodedMessage); + CFReleaseNull(peer); + return result; +} + +bool SOSTransportMessageSendMessageIfNeeded(SOSTransportMessageRef transport, CFStringRef circle_id, CFStringRef peer_id, CFErrorRef *error) { + + SOSEnginePeerMessageSentBlock sent = NULL; + CFDataRef message_to_send = NULL; + bool ok = false; + SOSPeerRef peer = SOSPeerCreateWithEngine(SOSTransportMessageGetEngine(transport), peer_id); + CFDataRef coderData = SOSEngineGetCoderData(SOSTransportMessageGetEngine(transport), peer_id); + require(coderData, fail); + + SOSCoderRef coder = SOSCoderCreateFromData(coderData, error); + require(coder, fail); + SOSPeerSetCoder(peer, coder); + + ok = SOSPeerCoderSendMessageIfNeeded(peer, &message_to_send, circle_id, peer_id, &sent, error); + coder = SOSPeerGetCoder(peer); + + 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); + + SOSPeerCoderConsume(&sent, ok); + + CFReleaseSafe(peer_dict); + CFReleaseSafe(circle_peers); + } + + + Block_release(sent); + + + CFReleaseSafe(message_to_send); + + coderData = SOSCoderCopyDER(coder, error); + + if(!SOSEngineSetCoderData(SOSTransportMessageGetEngine(transport), peer_id, coderData, error)){ + secerror("SOSTransportMessageSendMessageIfNeeded, Could not save peer state"); + } + CFReleaseNull(coderData); + + if (coder) + SOSCoderDispose(coder); + +fail: + CFReleaseNull(peer); + return ok; +} + +bool SOSTransportMessageSendMessagesIfNeeded(SOSTransportMessageRef transport, CFStringRef circle_id, CFArrayRef handledPeers, CFErrorRef *error) { + CFArrayForEach(handledPeers, ^(const void *value) { + if (isString(value)) { + CFStringRef peer_id = (CFStringRef) value; + CFErrorRef sendError = NULL; + + if (!SOSTransportMessageSendMessageIfNeeded(transport, circle_id, peer_id, &sendError)) { + secerror("Error sending message in circle %@ to peer %@ (%@)", circle_id, peer_id, sendError); + }; + + CFReleaseNull(sendError); + } + }); + + return true; +} + + + + diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSTransportMessage.h b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportMessage.h new file mode 100644 index 00000000..4535b51d --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportMessage.h @@ -0,0 +1,51 @@ + +#ifndef SOSTransportMessage_h +#define SOSTransportMessage_h + +#include +#include + +typedef struct __OpaqueSOSTransportMessage *SOSTransportMessageRef; + +struct __OpaqueSOSTransportMessage { + CFRuntimeBase _base; + SOSEngineRef engine; + SOSAccountRef account; + + /* Connections from CF land to vtable land */ + CFStringRef (*copyDescription)(SOSTransportMessageRef object); + void (*destroy)(SOSTransportMessageRef object); + + /* send message operations */ + bool (*syncWithPeers)(SOSTransportMessageRef transport, CFDictionaryRef circleToPeerIDs, CFErrorRef *error); + bool (*cleanupAfterPeerMessages)(SOSTransportMessageRef transport, CFDictionaryRef circleToPeerIDs, CFErrorRef* error); + bool (*sendMessages)(SOSTransportMessageRef transport, CFDictionaryRef circle_messages, CFErrorRef *error); + bool (*flushChanges)(SOSTransportMessageRef transport, CFErrorRef *error); + CFDictionaryRef (*handleMessages)(SOSTransportMessageRef transport, CFMutableDictionaryRef circle_peer_messages_table, CFErrorRef *error); +}; + +SOSTransportMessageRef SOSTransportMessageCreateForSubclass(size_t size,SOSAccountRef account, CFStringRef circleName, CFErrorRef *error); +bool SOSTransportMessageHandlePeerMessage(SOSTransportMessageRef transport, CFStringRef peer_id, CFDataRef codedMessage, CFErrorRef *error); + +typedef bool (^SOSTransportSendToPeerBlock)(SOSTransportMessageRef transport, CFStringRef peerID, CFDataRef message, SOSEnginePeerMessageSentBlock sentBlock); + +SOSEngineRef SOSTransportMessageGetEngine(SOSTransportMessageRef transport); + +SOSAccountRef SOSTransportMessageGetAccount(SOSTransportMessageRef transport); + +bool SOSTransportMessageCleanupAfterPeerMessages(SOSTransportMessageRef transport, CFDictionaryRef circleToPeerIDs, CFErrorRef* error); + +bool SOSTransportMessageSendMessagesIfNeeded(SOSTransportMessageRef transport, CFStringRef circle_id, CFArrayRef handledPeers, CFErrorRef *error); + +bool SOSTransportMessageSendMessages(SOSTransportMessageRef transport, CFDictionaryRef circle_messages, CFErrorRef *error); +bool SOSTransportMessageFlushChanges(SOSTransportMessageRef transport, CFErrorRef *error); + + +SOSTransportMessageRef SOSTransportMessageCreateForSubclass(size_t size, + SOSAccountRef account, CFStringRef circleName, + CFErrorRef *error); +CF_RETURNS_RETAINED +CFDictionaryRef SOSTransportMessageHandleMessages(SOSTransportMessageRef transport, CFMutableDictionaryRef circle_peer_messages_table, CFErrorRef *error); + + +#endif diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSTransportMessageKVS.c b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportMessageKVS.c new file mode 100644 index 00000000..f591c5dd --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportMessageKVS.c @@ -0,0 +1,249 @@ +#include +#include +#include +#include + +#include +#include +#include +#include + +struct __OpaqueSOSTransportMessageKVS { + struct __OpaqueSOSTransportMessage m; + + CFStringRef circleName; + CFMutableDictionaryRef pending_changes; + +}; + +// +// V-table implementation forward declarations +// +static bool sendToPeer(SOSTransportMessageRef transport, CFStringRef circleName, CFStringRef peerID, CFDataRef message, CFErrorRef *error); +static bool syncWithPeers(SOSTransportMessageRef transport, CFDictionaryRef circleToPeerIDs, CFErrorRef *error); +static bool sendMessages(SOSTransportMessageRef transport, CFDictionaryRef circleToPeersToMessage, CFErrorRef *error); +static bool cleanupAfterPeer(SOSTransportMessageRef transport, CFDictionaryRef circle_to_peer_ids, CFErrorRef *error); +static void destroy(SOSTransportMessageRef transport); +static CF_RETURNS_RETAINED +CFDictionaryRef handleMessages(SOSTransportMessageRef transport, CFMutableDictionaryRef circle_peer_messages_table, CFErrorRef *error); + +static bool flushChanges(SOSTransportMessageRef transport, CFErrorRef *error); + + +CFStringRef SOSTransportMessageKVSGetCircleName(SOSTransportMessageKVSRef transport){ + return transport->circleName; +} + +SOSTransportMessageKVSRef SOSTransportMessageKVSCreate(SOSAccountRef account, CFStringRef circleName, CFErrorRef *error){ + SOSTransportMessageKVSRef tkvs = (SOSTransportMessageKVSRef) SOSTransportMessageCreateForSubclass(sizeof(struct __OpaqueSOSTransportMessageKVS) - sizeof(CFRuntimeBase), account, circleName, error); + + if (tkvs) { + // Fill in vtable: + tkvs->m.sendMessages = sendMessages; + tkvs->m.syncWithPeers = syncWithPeers; + tkvs->m.flushChanges = flushChanges; + tkvs->m.cleanupAfterPeerMessages = cleanupAfterPeer; + tkvs->m.destroy = destroy; + tkvs->m.handleMessages = handleMessages; + // Initialize ourselves + tkvs->pending_changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + tkvs->circleName = CFRetainSafe(circleName); + SOSRegisterTransportMessage((SOSTransportMessageRef)tkvs); + } + + return tkvs; +} +bool SOSTransportMessageKVSAppendKeyInterest(SOSTransportMessageKVSRef transport, CFMutableArrayRef alwaysKeys, CFMutableArrayRef afterFirstUnlockKeys, CFMutableArrayRef unlockedKeys, CFErrorRef *localError){ + SOSEngineRef engine = SOSTransportMessageGetEngine((SOSTransportMessageRef)transport); + require_quiet(engine, fail); + CFArrayRef peer_ids = SOSEngineGetPeerIDs(engine); + if(peer_ids){ + CFArrayForEach(peer_ids, ^(const void *value) { + CFStringRef peerMessage = SOSMessageKeyCreateFromPeerToTransport(transport, value); + CFArrayAppendValue(unlockedKeys, peerMessage); + CFReleaseNull(peerMessage); + }); + } + return true; +fail: + return false; +} +static void destroy(SOSTransportMessageRef transport){ + SOSTransportMessageKVSRef tkvs = (SOSTransportMessageKVSRef)transport; + CFReleaseNull(tkvs->circleName); + CFReleaseNull(tkvs->pending_changes); + SOSUnregisterTransportMessage((SOSTransportMessageRef)tkvs); + +} + +static bool SOSTransportMessageKVSUpdateKVS(SOSTransportMessageKVSRef transport, CFDictionaryRef changes, CFErrorRef *error){ + CloudKeychainReplyBlock log_error = ^(CFDictionaryRef returnedValues __unused, CFErrorRef error) { + if (error) { + secerror("Error putting: %@", error); + CFReleaseSafe(error); + } + }; + + SOSCloudKeychainPutObjectsInCloud(changes, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), log_error); + return true; +} + +static bool SOSTransportMessageKVSSendPendingChanges(SOSTransportMessageKVSRef transport, CFErrorRef *error) { + CFErrorRef changeError = NULL; + + if (transport->pending_changes == NULL || CFDictionaryGetCount(transport->pending_changes) == 0) { + CFReleaseNull(transport->pending_changes); + return true; + } + + bool success = SOSTransportMessageKVSUpdateKVS(transport, transport->pending_changes, &changeError); + if (success) { + CFDictionaryRemoveAllValues(transport->pending_changes); + } else { + SOSCreateErrorWithFormat(kSOSErrorSendFailure, changeError, error, NULL, + CFSTR("Send changes block failed [%@]"), transport->pending_changes); + } + + return success; +} + +static void SOSTransportMessageKVSAddToPendingChanges(SOSTransportMessageKVSRef transport, CFStringRef message_key, CFDataRef message_data){ + if (transport->pending_changes == NULL) { + transport->pending_changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + } + if (message_data == NULL) { + CFDictionarySetValue(transport->pending_changes, message_key, kCFNull); + } else { + CFDictionarySetValue(transport->pending_changes, message_key, message_data); + } +} + +static bool SOSTransportMessageKVSCleanupAfterPeerMessages(SOSTransportMessageKVSRef transport, CFDictionaryRef circle_to_peer_ids, CFErrorRef *error) +{ + CFArrayRef enginePeers = SOSEngineGetPeerIDs(SOSTransportMessageGetEngine((SOSTransportMessageRef)transport)); + + CFDictionaryForEach(circle_to_peer_ids, ^(const void *key, const void *value) { + if (isString(key) && isArray(value)) { + CFStringRef circle_name = (CFStringRef) key; + CFArrayRef peers_to_cleanup_after = (CFArrayRef) value; + + CFArrayForEach(peers_to_cleanup_after, ^(const void *value) { + if (isString(value)) { + CFStringRef cleanup_id = (CFStringRef) value; + // TODO: Since the enginePeers list is not authorative (the Account is) this could inadvertently clean up active peers or leave behind stale peers + if (enginePeers) CFArrayForEach(enginePeers, ^(const void *value) { + if (isString(value)) { + CFStringRef in_circle_id = (CFStringRef) value; + + CFStringRef kvsKey = SOSMessageKeyCreateWithCircleNameAndPeerNames(circle_name, cleanup_id, in_circle_id); + SOSTransportMessageKVSAddToPendingChanges(transport, kvsKey, NULL); + CFReleaseSafe(kvsKey); + + kvsKey = SOSMessageKeyCreateWithCircleNameAndPeerNames(circle_name, in_circle_id, cleanup_id); + SOSTransportMessageKVSAddToPendingChanges(transport, kvsKey, NULL); + CFReleaseSafe(kvsKey); + } + }); + + } + }); + } + }); + + return SOSTransportMessageFlushChanges((SOSTransportMessageRef)transport, error); +} + +static CF_RETURNS_RETAINED +CFDictionaryRef handleMessages(SOSTransportMessageRef transport, CFMutableDictionaryRef circle_peer_messages_table, CFErrorRef *error) { + SOSTransportMessageKVSRef tpt = (SOSTransportMessageKVSRef)transport; + CFMutableDictionaryRef handled = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionaryRef peerToMessage = CFDictionaryGetValue(circle_peer_messages_table, tpt->circleName); + CFMutableArrayRef handled_peers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionaryAddValue(handled, tpt->circleName, handled_peers); + + if(peerToMessage){ + CFDictionaryForEach(peerToMessage, ^(const void *key, const void *value) { + CFStringRef peer_id = (CFStringRef) key; + CFDataRef peer_message = (CFDataRef) value; + CFErrorRef localError = NULL; + + if (SOSTransportMessageHandlePeerMessage(transport, peer_id, peer_message, &localError)) { + CFArrayAppendValue(handled_peers, key); + } else { + secdebug("transport", "%@ KVSTransport handle message failed: %@", peer_id, localError); + } + CFReleaseNull(localError); + }); + } + CFReleaseNull(handled_peers); + + return handled; +} + + +static bool sendToPeer(SOSTransportMessageRef transport, CFStringRef circleName, CFStringRef peerID, CFDataRef message, CFErrorRef *error) { + SOSTransportMessageKVSRef kvsTransport = (SOSTransportMessageKVSRef) transport; + bool result = true; + CFStringRef message_to_peer_key = SOSMessageKeyCreateFromTransportToPeer(kvsTransport, peerID); + CFDictionaryRef a_message_to_a_peer = CFDictionaryCreateForCFTypes(NULL, message_to_peer_key, message, NULL); + + if (!SOSTransportMessageKVSUpdateKVS(kvsTransport, a_message_to_a_peer, error)) { + secerror("Sync with peers failed to send to %@ [%@], %@", peerID, a_message_to_a_peer, *error); + result = false; + } + CFReleaseNull(a_message_to_a_peer); + CFReleaseNull(message_to_peer_key); + + return result; +} + +static bool syncWithPeers(SOSTransportMessageRef transport, CFDictionaryRef circleToPeerIDs, CFErrorRef *error){ + // Each entry is keyed by circle name and contains a list of peerIDs + + __block bool result = true; + + CFDictionaryForEach(circleToPeerIDs, ^(const void *key, const void *value) { + if (isString(key) && isArray(value)) { + CFStringRef circleName = (CFStringRef) key; + CFArrayForEach(value, ^(const void *value) { + if (isString(value)) { + CFStringRef peerID = (CFStringRef) value; + result &= SOSTransportMessageSendMessageIfNeeded(transport, circleName, peerID, error); + } + }); + } + }); + + return result; +} + +static bool sendMessages(SOSTransportMessageRef transport, CFDictionaryRef circleToPeersToMessage, CFErrorRef *error) { + __block bool result = true; + + 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) && isData(value)) { + CFStringRef peerID = (CFStringRef) key; + CFDataRef message = (CFDataRef) value; + bool rx = sendToPeer(transport, circleName, peerID, message, error); + result &= rx; + } + }); + } + }); + + return true; +} + +static bool flushChanges(SOSTransportMessageRef transport, CFErrorRef *error) +{ + return SOSTransportMessageKVSSendPendingChanges((SOSTransportMessageKVSRef) transport, error); +} + +static bool cleanupAfterPeer(SOSTransportMessageRef transport, CFDictionaryRef circle_to_peer_ids, CFErrorRef *error) +{ + return SOSTransportMessageKVSCleanupAfterPeerMessages((SOSTransportMessageKVSRef) transport, circle_to_peer_ids, error); +} + diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSTransportMessageKVS.h b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportMessageKVS.h new file mode 100644 index 00000000..42f5cd50 --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSTransportMessageKVS.h @@ -0,0 +1,28 @@ + + +#ifndef sec_SOSTransportMessageKVS_h +#define sec_SOSTransportMessageKVS_h +#include + +// +// KVS Stuff +// + +typedef struct __OpaqueSOSTransportMessageKVS *SOSTransportMessageKVSRef; + +SOSTransportMessageKVSRef SOSTransportMessageKVSCreate(SOSAccountRef account, CFStringRef circleName, CFErrorRef *error); + +CFStringRef SOSTransportMessageKVSGetCircleName(SOSTransportMessageKVSRef transport); + + +// +// Key interests +// + +bool SOSTransportMessageSyncWithPeers(SOSTransportMessageRef transport, CFDictionaryRef circleToPeerIDs, CFErrorRef *error); + +bool SOSTransportMessageKVSAppendKeyInterest(SOSTransportMessageKVSRef transport, CFMutableArrayRef alwaysKeys, CFMutableArrayRef afterFirstUnlockKeys, CFMutableArrayRef unlockedKeys, CFErrorRef *localError); + +bool SOSTransportMessageSendMessageIfNeeded(SOSTransportMessageRef transport, CFStringRef circle_id, CFStringRef peer_id, CFErrorRef *error); + +#endif diff --git a/sec/SOSCircle/SecureObjectSync/SOSUserKeygen.c b/Security/sec/SOSCircle/SecureObjectSync/SOSUserKeygen.c similarity index 91% rename from sec/SOSCircle/SecureObjectSync/SOSUserKeygen.c rename to Security/sec/SOSCircle/SecureObjectSync/SOSUserKeygen.c index c8f0a28d..e4587cf3 100644 --- a/sec/SOSCircle/SecureObjectSync/SOSUserKeygen.c +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSUserKeygen.c @@ -1,10 +1,26 @@ -// -// SOSUserKeygen.c -// sec -// -// Created by Richard Murphy on 2/21/13. -// -// +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include #include diff --git a/Security/sec/SOSCircle/SecureObjectSync/SOSUserKeygen.h b/Security/sec/SOSCircle/SecureObjectSync/SOSUserKeygen.h new file mode 100644 index 00000000..4dab3ada --- /dev/null +++ b/Security/sec/SOSCircle/SecureObjectSync/SOSUserKeygen.h @@ -0,0 +1,35 @@ +/* + * 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@ + */ + + +#ifndef sec_SOSUserKeygen_h +#define sec_SOSUserKeygen_h +#include +#include + +CFDataRef SOSUserKeyCreateGenerateParameters(CFErrorRef *error); +SecKeyRef SOSUserKeygen(CFDataRef password, CFDataRef parameters, CFErrorRef *error); + +void debugDumpUserParameters(CFStringRef message, CFDataRef parameters); + +#endif diff --git a/Security/sec/SOSCircle/Tool/SOSCommands.h b/Security/sec/SOSCircle/Tool/SOSCommands.h new file mode 100644 index 00000000..073b311a --- /dev/null +++ b/Security/sec/SOSCircle/Tool/SOSCommands.h @@ -0,0 +1,52 @@ +/* + * 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 + +SECURITY_COMMAND("sync", keychain_sync, + "[options]\n" + " -e Enable Keychain Syncing (join/create circle)\n" + " -d Disable Keychain Syncing\n" + " -a Accept all applicants\n" + " -r Reject all applicants\n" + " -i Info\n" + " -k Pend all registered kvs keys\n" + " -s Schedule sync with all peers\n" + " -E Ensure Fresh Parameters\n" + " -R Reset\n" + " -O ResetToOffering\n" + " -q Sign out of Circle\n" + " -C Clear all values from KVS\n" + " -p Retrieve IDS Device ID\n" + " -g Set IDS Device ID\n" + " -P [label:]password Set password (optionally for a given label) for sync\n" + " -D [itemName] Dump contents of KVS\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" + " -U Purge private key material cache\n" + " -D [itemName] Dump contents of KVS\n" + " -W itemNames sync and dump\n", + " -X [limit] Best effort bail from circle in limit seconds\n" + "Keychain Syncing controls." ) + diff --git a/Security/sec/SOSCircle/Tool/keychain_sync.c b/Security/sec/SOSCircle/Tool/keychain_sync.c new file mode 100644 index 00000000..ba90f9f4 --- /dev/null +++ b/Security/sec/SOSCircle/Tool/keychain_sync.c @@ -0,0 +1,579 @@ +/* + * Copyright (c) 2003-2007,2009-2010,2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * keychain_add.c + */ + + +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include + +#include "SOSCommands.h" + +#define printmsg(format, ...) _printcfmsg(stdout, format, __VA_ARGS__) +#define printerr(format, ...) _printcfmsg(stderr, format, __VA_ARGS__) + +static void _printcfmsg(FILE *ff, CFStringRef format, ...) +{ + va_list args; + va_start(args, format); + CFStringRef message = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, format, args); + va_end(args); + CFStringPerformWithCString(message, ^(const char *utf8String) { fprintf(ff, utf8String, ""); }); + CFRelease(message); +} + +static bool clearAllKVS(CFErrorRef *error) +{ + __block bool result = false; + const uint64_t maxTimeToWaitInSeconds = 30ull * NSEC_PER_SEC; + dispatch_queue_t processQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0); + dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds); + + SOSCloudKeychainClearAll(processQueue, ^(CFDictionaryRef returnedValues, CFErrorRef cerror) + { + result = (cerror != NULL); + dispatch_semaphore_signal(waitSemaphore); + }); + + dispatch_semaphore_wait(waitSemaphore, finishTime); + dispatch_release(waitSemaphore); + + return result; +} + +static const char *getSOSCCStatusDescription(SOSCCStatus ccstatus) +{ + switch (ccstatus) + { + case kSOSCCInCircle: return "In Circle"; + case kSOSCCNotInCircle: return "Not in Circle"; + case kSOSCCRequestPending: return "Request pending"; + case kSOSCCCircleAbsent: return "Circle absent"; + case kSOSCCError: return "Circle error"; + + default: + return ""; + break; + } +} + +static void dumpCircleInfo() +{ + CFErrorRef error = NULL; + CFArrayRef peerPeerInfos = NULL; + CFArrayRef applicants = NULL; + CFArrayRef retirees = NULL; + CFArrayRef peerInfos = NULL; + CFArrayRef generations = NULL; + bool is_user_public_trusted = false; + __block int count = 0; + + SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(&error); + printmsg(CFSTR("ccstatus: %s (%d), error: %@\n"), getSOSCCStatusDescription(ccstatus), ccstatus, error); + + if(ccstatus == kSOSCCError) { + printmsg(CFSTR("End of Dump - unable to proceed due to ccstatus -\n\t%s\n"), getSOSCCStatusDescription(ccstatus)); + return; + } + + 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%@"),CFSTR("\n")); + + // Now look at current peers + peerPeerInfos = SOSCCCopyValidPeerPeerInfo(&error); + + if (peerPeerInfos) + { + printmsg(CFSTR("Valid Peers: %ld, error: %@\n"), (long)CFArrayGetCount(peerPeerInfos), error); + CFArrayForEach(peerPeerInfos, ^(const void *value) { + SOSPeerInfoRef peer = (SOSPeerInfoRef)value; + CFStringRef peerName = SOSPeerInfoGetPeerName(peer); + printmsg(CFSTR("Valid Peer: %@ (%@)\n"), peerName, peer); + }); + } + else + printmsg(CFSTR("No peers, error: %@\n"), error); + + CFReleaseNull(peerPeerInfos); + peerPeerInfos = SOSCCCopyNotValidPeerPeerInfo(&error); + + if (peerPeerInfos) + { + printmsg(CFSTR("Non Valid Peers: %ld, error: %@\n"), (long)CFArrayGetCount(peerPeerInfos), error); + CFArrayForEach(peerPeerInfos, ^(const void *value) { + SOSPeerInfoRef peer = (SOSPeerInfoRef)value; + CFStringRef peerName = SOSPeerInfoGetPeerName(peer); + printmsg(CFSTR("Not Valid Peer: %@ (%@)\n"), peerName, peer); + }); + } + CFReleaseNull(peerPeerInfos); + + applicants = SOSCCCopyApplicantPeerInfo(&error); + if (applicants) + { + printmsg(CFSTR("Applicants: %ld, error: %@\n"), (long)CFArrayGetCount(applicants), error); + CFArrayForEach(applicants, ^(const void *value) { + SOSPeerInfoRef peer = (SOSPeerInfoRef)value; + CFStringRef peerName = SOSPeerInfoGetPeerName(peer); + printmsg(CFSTR("Applicant: %@ (%@)\n"), peerName, peer); + }); + } + else + printmsg(CFSTR("No applicants, error: %@\n"), error); + CFReleaseNull(applicants); + + + peerInfos = SOSCCCopyConcurringPeerPeerInfo(&error); + if (peerInfos) + { + printmsg(CFSTR("Concurring Peers: %ld, error: %@\n"), (long)CFArrayGetCount(peerInfos), error); + CFArrayForEach(peerInfos, ^(const void *value) { + SOSPeerInfoRef peer = (SOSPeerInfoRef)value; + CFStringRef peerName = SOSPeerInfoGetPeerName(peer); + printmsg(CFSTR("Concurr: %@ (%@)\n"), peerName, peer); + }); + } + else + printmsg(CFSTR("No concurring peers, error: %@\n"), error); + + CFReleaseNull(peerInfos); + retirees = SOSCCCopyRetirementPeerInfo(&error); + if (retirees) + { + printmsg(CFSTR("Retired Peers: %ld, error: %@\n"), (long)CFArrayGetCount(retirees), error); + CFArrayForEach(retirees, ^(const void *value) { + SOSPeerInfoRef peer = (SOSPeerInfoRef)value; + CFStringRef peerName = SOSPeerInfoGetPeerName(peer); + printmsg(CFSTR("Retiree: %@ (%@)\n"), peerName, peer); + }); + } + else + printmsg(CFSTR("No retired peers, error: %@\n"), error); + CFReleaseNull(retirees); + + generations = SOSCCCopyGenerationPeerInfo(&error); + if(generations) + { + CFArrayForEach(generations, ^(const void *value) { + count++; + if(count%2 != 0) + printmsg(CFSTR("Circle name: %@, "),value); + + if(count%2 == 0) + printmsg(CFSTR("Generation Count: %@\n"), value); + }); + } + else + printmsg(CFSTR("No generation count: %@\n"), error); + CFReleaseNull(generations); +} + +static bool requestToJoinCircle(CFErrorRef *error) +{ + // Set the visual state of switch based on membership in circle + bool hadError = false; + SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(error); + + switch (ccstatus) + { + case kSOSCCCircleAbsent: + hadError = !SOSCCResetToOffering(error); + break; + case kSOSCCNotInCircle: + hadError = !SOSCCRequestToJoinCircle(error); + break; + default: + printerr(CFSTR("Request to join circle with bad status: %@ (%d)\n"), SOSCCGetStatusDescription(ccstatus), ccstatus); + break; + } + return hadError; +} + +static bool setPassword(char *labelAndPassword, CFErrorRef *err) +{ + char *last = NULL; + char *token0 = strtok_r(labelAndPassword, ":", &last); + char *token1 = strtok_r(NULL, "", &last); + CFStringRef label = token1 ? CFStringCreateWithCString(NULL, token0, kCFStringEncodingUTF8) : CFSTR("security command line tool"); + char *password_token = token1 ? token1 : token0; + password_token = password_token ? password_token : ""; + CFDataRef password = CFDataCreate(NULL, (const UInt8*) password_token, strlen(password_token)); + bool returned = !SOSCCSetUserCredentials(label, password, err); + CFRelease(label); + CFRelease(password); + return returned; +} + +static bool tryPassword(char *labelAndPassword, CFErrorRef *err) +{ + char *last = NULL; + char *token0 = strtok_r(labelAndPassword, ":", &last); + char *token1 = strtok_r(NULL, "", &last); + CFStringRef label = token1 ? CFStringCreateWithCString(NULL, token0, kCFStringEncodingUTF8) : CFSTR("security command line tool"); + char *password_token = token1 ? token1 : token0; + password_token = password_token ? password_token : ""; + CFDataRef password = CFDataCreate(NULL, (const UInt8*) password_token, strlen(password_token)); + bool returned = !SOSCCTryUserCredentials(label, password, err); + CFRelease(label); + CFRelease(password); + return returned; +} + +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) + { + secerror("SOSCloudKeychainGetObjectsFromCloud returned: %@", returnedValues); + object = returnedValues; + if (object) + CFRetain(object); + if (error) + { + secerror("SOSCloudKeychainGetObjectsFromCloud returned error: %@", error); + // CFRelease(*error); + } + dispatch_group_leave(dgroup); + secerror("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 void displayCircles(CFTypeRef objects) +{ + // SOSCCCopyApplicantPeerInfo doesn't display all info, e.g. in the case where we are not in circle + CFDictionaryForEach(objects, ^(const void *key, const void *value) { + if (SOSKVSKeyGetKeyType(key) == kCircleKey) + { + CFErrorRef localError = NULL; + if (isData(value)) + { + SOSCircleRef circle = SOSCircleCreateFromData(NULL, (CFDataRef) value, &localError); + printmsg(CFSTR("circle: %@ %@"), key, circle); + CFReleaseSafe(circle); + } + else + printmsg(CFSTR("non-circle: %@ %@"), key, value); + } + }); +} + +static bool dumpKVS(char *itemName, CFErrorRef *err) +{ + CFArrayRef keysToGet = NULL; + if (itemName) + { + CFStringRef itemStr = CFStringCreateWithCString(kCFAllocatorDefault, itemName, kCFStringEncodingUTF8); + printf("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); + printmsg(CFSTR(" : %@\n"), objects); + if (objects) + displayCircles(objects); + printf("\n"); + return false; +} + +static bool syncAndWait(char *itemName, CFErrorRef *err) +{ + CFArrayRef keysToGet = NULL; + __block CFTypeRef objects = NULL; + if (!itemName) + { + fprintf(stderr, "No item keys supplied\n"); + return false; + } + + CFStringRef itemStr = CFStringCreateWithCString(kCFAllocatorDefault, itemName, kCFStringEncodingUTF8); + printf("Retrieving %s from KVS\n", itemName); + keysToGet = CFArrayCreateForCFTypes(kCFAllocatorDefault, itemStr, NULL); + CFReleaseSafe(itemStr); + + dispatch_queue_t generalq = dispatch_queue_create("general", DISPATCH_QUEUE_SERIAL); + + 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); + + CloudKeychainReplyBlock replyBlock = ^ (CFDictionaryRef returnedValues, CFErrorRef error) + { + secerror("SOSCloudKeychainSynchronizeAndWait returned: %@", returnedValues); + if (error) + secerror("SOSCloudKeychainSynchronizeAndWait returned error: %@", error); + objects = returnedValues; + if (objects) + CFRetain(objects); + secerror("SOSCloudKeychainGetObjectsFromCloud block exit: %@", objects); + dispatch_semaphore_signal(waitSemaphore); + }; + + SOSCloudKeychainSynchronizeAndWait(keysToGet, generalq, replyBlock); + + dispatch_semaphore_wait(waitSemaphore, finishTime); + dispatch_release(waitSemaphore); + + CFReleaseSafe(keysToGet); + printmsg(CFSTR(" : %@\n"), objects); + if (objects) + displayCircles(objects); + printf("\n"); + return false; +} + +// enable, disable, accept, reject, status, Reset, Clear +int +keychain_sync(int argc, char * const *argv) +{ + /* + " -e Enable Keychain Syncing (join/create circle)\n" + " -d Disable Keychain Syncing\n" + " -a Accept all applicants\n" + " -r Reject all applicants\n" + " -i Info\n" + " -k Pend all registered kvs keys\n" + " -s Schedule sync with all peers\n" + " -E Ensure Fresh Parameters\n" + " -R Reset\n" + " -O ResetToOffering\n" + " -q Sign out of Circle\n" + " -C Clear all values from KVS\n" + " -P [label:]password Set password (optionally for a given label) for sync\n" + " -D [itemName] Dump contents of KVS\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" + " -U Purge private key material cache\n" + " -D [itemName] Dump contents of KVS\n" + " -W itemNames sync and dump\n" + " -X [limit] Best effort bail from circle in limit seconds\n" + " -p Retrieve IDS Device ID\n" + " -g Set IDS Device ID\n" + */ + int ch, result = 0; + CFErrorRef error = NULL; + bool hadError = false; + + while ((ch = getopt(argc, argv, "pedakrisEROChP:T:DW:UX:g:q:")) != -1) + { + switch (ch) + { + case 'q': + { + printf("Signing out of circle\n"); + bool immediately = false; + CFStringRef leaveImmediately = CFStringCreateWithCString(kCFAllocatorDefault, (char *)optarg, kCFStringEncodingUTF8); + if(CFStringCompare(CFSTR("true"), leaveImmediately, 0) == 0){ + immediately = true; + } + else if(CFStringCompare(CFSTR("false"), leaveImmediately, 0) == 0){ + immediately = false; + } + else{ + printf("Please provide a \"true\" or \"false\" whether you'd like to leave the circle immediately\n"); + } + hadError = !SOSCCSignedOut(immediately, &error); + } + break; + case 'p': + { + printf("Grabbing DS ID\n"); + CFStringRef deviceID = SOSCCRequestDeviceID(&error); + if(error){ + hadError = true; + break; + } + if(!isNull(deviceID)){ + const char* id = CFStringGetCStringPtr(deviceID, kCFStringEncodingUTF8); + if(id) + printf("IDS Device ID: %s\n", id); + else + printf("IDS Device ID is null!\n"); + } + } + break; + case 'g': + { + CFStringRef deviceID = CFStringCreateWithCString(kCFAllocatorDefault, (char *)optarg, kCFStringEncodingUTF8); + printf("Setting DS ID: %s\n", optarg); + hadError = SOSCCSetDeviceID(deviceID, &error); + CFReleaseNull(deviceID); + } + break; + case 'e': + printf("Keychain syncing is being turned ON\n"); + hadError = requestToJoinCircle(&error); + break; + case 'd': + printf("Keychain syncing is being turned OFF\n"); + hadError = !SOSCCRemoveThisDeviceFromCircle(&error); + break; + case 'a': + { + CFArrayRef applicants = SOSCCCopyApplicantPeerInfo(NULL); + if (applicants) + { + hadError = !SOSCCAcceptApplicants(applicants, &error); + CFRelease(applicants); + } + else + fprintf(stderr, "No applicants to accept\n"); + } + break; + case 'r': + { + CFArrayRef applicants = SOSCCCopyApplicantPeerInfo(NULL); + if (applicants) + { + hadError = !SOSCCRejectApplicants(applicants, &error); + CFRelease(applicants); + } + else + fprintf(stderr, "No applicants to reject\n"); + } + break; + case 'i': + dumpCircleInfo(); + break; + case 'k': + notify_post("com.apple.security.cloudkeychain.forceupdate"); + break; + case 's': + //SOSCloudKeychainRequestSyncWithAllPeers(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); + break; + case 'E': + { + printf("Ensuring Fresh Parameters\n"); + bool result = SOSCCRequestEnsureFreshParameters(&error); + if(error){ + hadError = true; + break; + } + if(result){ + printf("Refreshed Parameters Ensured!\n"); + } + else{ + printf("Problem trying to ensure fresh parameters\n"); + } + } + break; + case 'R': + hadError = !SOSCCResetToEmpty(&error); + break; + case 'O': + hadError = !SOSCCResetToOffering(&error); + break; + case 'C': + hadError = clearAllKVS(&error); + break; + case 'P': + hadError = setPassword(optarg, &error); + break; + case 'T': + hadError = tryPassword(optarg, &error); + break; + case 'X': + { + uint64_t limit = strtoul(optarg, NULL, 10); + hadError = !SOSCCBailFromCircle_BestEffort(limit, &error); + } + break; + case 'U': + hadError = !SOSCCPurgeUserCredentials(&error); + break; + case 'D': + hadError = dumpKVS(optarg, &error); + break; + case 'W': + hadError = syncAndWait(optarg, &error); + break; + case '?': + default: + return 2; /* Return 2 triggers usage message. */ + } + } + + //argc -= optind; + //argv += optind; + +// if (argc == 0) +// return 2; + + if (hadError) + printerr(CFSTR("Error: %@\n"), error); + + // sec_perror("SecItemAdd", result); + + return result; +} diff --git a/Security/sec/SOSCircle/osxshim.c b/Security/sec/SOSCircle/osxshim.c new file mode 100644 index 00000000..9d19a197 --- /dev/null +++ b/Security/sec/SOSCircle/osxshim.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include + +typedef void *SOSDataSourceFactoryRef; +//typedef void *SOSAccountRef; + +// XXX Need to plumb these from security to secd. If we can. + +typedef SOSDataSourceFactoryRef (^AccountDataSourceFactoryBlock)(); + +bool SOSKeychainAccountSetFactoryForAccount(AccountDataSourceFactoryBlock factory); + +bool SOSKeychainAccountSetFactoryForAccount(AccountDataSourceFactoryBlock factory) +{ + return false; +} + +#if 0 +SOSAccountRef SOSKeychainAccountGetSharedAccount(void); + +SOSAccountRef SOSKeychainAccountGetSharedAccount(void) +{ + return (void*)0; +} +#endif + +typedef struct _OpaqueFakeSecAccessControlRef *SecAccessControlRef; + +CFTypeRef kSecAttrAccessControl = CFSTR("accc"); + +extern SecAccessControlRef SecAccessControlCreateFromData(CFAllocatorRef allocator, CFDataRef data, CFErrorRef *error); +extern CFDataRef SecAccessControlCopyData(SecAccessControlRef access_control); + +SecAccessControlRef SecAccessControlCreateFromData(CFAllocatorRef allocator, CFDataRef data, CFErrorRef *error) { + return NULL; +} + +/*! Creates Access control instance from data serialized by SecAccessControlCopyData(). */ +CFDataRef SecAccessControlCopyData(SecAccessControlRef access_control) { + return NULL; +} diff --git a/Security/sec/Security/AppleBaselineEscrowCertificates.h b/Security/sec/Security/AppleBaselineEscrowCertificates.h new file mode 100644 index 00000000..56a9b6cf --- /dev/null +++ b/Security/sec/Security/AppleBaselineEscrowCertificates.h @@ -0,0 +1,178 @@ +/* + * 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@ + */ + + +#ifndef sec_AppleBaselineEscrowCertificates_h +#define sec_AppleBaselineEscrowCertificates_h + +struct RootRecord +{ + size_t _length; + UInt8* _bytes; +}; + +/* ========================================================================== + Production Escrow Certificates + ========================================================================== */ + + +static const UInt8 kBaseLineEscrowRootGM[] = { + 0x30,0x82,0x03,0xd0,0x30,0x82,0x02,0xb8,0xa0,0x03,0x02,0x01,0x02,0x02,0x01,0x64, + 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x30, + 0x79,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,0x04,0x05,0x13,0x03,0x31,0x30,0x30,0x31, + 0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11, + 0x06,0x03,0x55,0x04,0x0a,0x13,0x0a,0x41,0x70,0x70,0x6c,0x65,0x20,0x49,0x6e,0x63, + 0x2e,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0b,0x13,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,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,0x33, + 0x30,0x38,0x30,0x32,0x32,0x33,0x32,0x34,0x34,0x34,0x5a,0x17,0x0d,0x32,0x33,0x30, + 0x38,0x30,0x32,0x32,0x33,0x32,0x34,0x34,0x34,0x5a,0x30,0x79,0x31,0x0c,0x30,0x0a, + 0x06,0x03,0x55,0x04,0x05,0x13,0x03,0x31,0x30,0x30,0x31,0x0b,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0a, + 0x13,0x0a,0x41,0x70,0x70,0x6c,0x65,0x20,0x49,0x6e,0x63,0x2e,0x31,0x26,0x30,0x24, + 0x06,0x03,0x55,0x04,0x0b,0x13,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,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,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48, + 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01, + 0x0a,0x02,0x82,0x01,0x01,0x00,0xd0,0xa3,0xf4,0x56,0x7d,0x3f,0x46,0x31,0xd2,0x56, + 0xa0,0xdf,0x42,0xa0,0x29,0x83,0x1e,0xb9,0x82,0xb5,0xa5,0xff,0x3e,0xde,0xb5,0x0f, + 0x4a,0x8a,0x28,0x60,0xcf,0x75,0xb4,0xa0,0x70,0x7c,0xf5,0xe2,0x94,0xf3,0x22,0x02, + 0xc8,0x81,0xce,0x34,0xc7,0x66,0x6a,0x18,0xaa,0xb4,0xfd,0x6d,0xb0,0x0b,0xdd,0x4a, + 0xdd,0xcf,0xe0,0x08,0x1b,0x1c,0xa6,0xdb,0xba,0xb2,0xc1,0xa4,0x10,0x5f,0x35,0x4f, + 0x8b,0x8b,0x7a,0xa3,0xdb,0x3c,0xf6,0x54,0x95,0x42,0xad,0x2a,0x3b,0xfe,0x06,0x8c, + 0xe1,0x92,0xf1,0x60,0x97,0x58,0x1b,0xd9,0x8f,0xbe,0xfb,0x46,0x4c,0x29,0x5c,0x1c, + 0xf0,0x20,0xb6,0x2b,0xa5,0x12,0x09,0x9b,0x28,0x41,0x34,0x97,0x9f,0xf3,0x88,0x4b, + 0x69,0x72,0xea,0x3a,0x27,0xb0,0x50,0x1d,0x88,0x29,0x0d,0xbb,0xed,0x04,0xa2,0x11, + 0xcf,0x0c,0x5b,0x65,0x61,0x35,0xbd,0xf2,0x0d,0xfc,0xe2,0xb9,0x20,0xd3,0xb7,0x03, + 0x70,0x39,0xd5,0xe0,0x86,0x7c,0x04,0xcc,0xc9,0xa1,0x85,0xb4,0x9b,0xbc,0x88,0x4e, + 0xd7,0xad,0x5c,0xff,0x2c,0x0d,0x80,0x8e,0x51,0x39,0x20,0x8b,0xaf,0x1e,0x46,0x95, + 0xfa,0x0d,0x1b,0xd2,0xbf,0x80,0xe0,0x9f,0x6d,0x4a,0xf5,0x31,0x67,0x18,0x11,0xa5, + 0x63,0x27,0x08,0xee,0xd9,0x07,0x29,0xd0,0xd4,0x36,0x91,0x5b,0xfb,0x4a,0x0b,0x07, + 0xd1,0x0d,0x79,0x16,0x6e,0x16,0x02,0x23,0x80,0xc6,0x15,0x07,0x6d,0xa0,0x06,0xb6, + 0x45,0x90,0xb0,0xae,0xa4,0xad,0x0e,0x75,0x04,0x2b,0x2b,0x78,0xf1,0x57,0x84,0x23, + 0x87,0x24,0xec,0x58,0xc4,0xf1,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,0x01,0x06, + 0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e,0x04,0x16,0x04,0x14,0xfd,0x78,0x96,0x53,0x80, + 0xd6,0xf6,0xdc,0xa6,0xc3,0x59,0x06,0x38,0xed,0x79,0x3e,0x8f,0x50,0x1b,0x50,0x30, + 0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xfd,0x78,0x96,0x53, + 0x80,0xd6,0xf6,0xdc,0xa6,0xc3,0x59,0x06,0x38,0xed,0x79,0x3e,0x8f,0x50,0x1b,0x50, + 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03, + 0x82,0x01,0x01,0x00,0x71,0x15,0xca,0x87,0xd0,0x2d,0xb5,0x18,0xd5,0x35,0x7a,0xcd, + 0xdf,0x62,0x28,0xf0,0x0b,0x63,0x4d,0x4e,0x02,0xba,0x3d,0xb8,0xb4,0x37,0xea,0xb0, + 0x93,0x93,0xab,0x1c,0xfd,0x9f,0xe8,0x72,0xbf,0xf3,0xdb,0xe6,0xad,0x16,0xfe,0x71, + 0x61,0xa8,0x5a,0xd0,0x58,0x0f,0x65,0x7a,0x57,0x7a,0xe0,0x34,0x80,0x8e,0xbb,0x41, + 0x01,0xe7,0xb0,0x3b,0xf7,0x2b,0x3a,0x6d,0x44,0x2a,0x3a,0x04,0x52,0xfa,0x2b,0x7b, + 0x3b,0x21,0xdd,0x0c,0x70,0x3d,0xfb,0x45,0xc6,0x79,0x68,0x62,0xe2,0x89,0xb8,0x25, + 0xee,0x63,0x76,0x02,0xb2,0x22,0xe9,0x53,0x85,0x68,0x3e,0x75,0xb6,0x0b,0x65,0xe9, + 0x1c,0xba,0x84,0x93,0xb0,0x8a,0xef,0xb5,0x1a,0x12,0xe4,0x8f,0xae,0xd5,0x5c,0xa1, + 0x05,0x4a,0x01,0xbc,0x6f,0xf9,0x58,0x5e,0xf7,0x04,0x61,0xee,0xf5,0xc6,0xa0,0x1b, + 0x44,0x2e,0x5a,0x3a,0x59,0xa1,0xb3,0xb0,0xf4,0xb6,0xcb,0xe0,0x6c,0x2b,0x59,0x8a, + 0xfb,0x6a,0xe0,0xa2,0x57,0x09,0x79,0xc1,0xdd,0xfb,0x84,0x86,0xeb,0x66,0x29,0x73, + 0xae,0xbf,0x58,0xae,0x47,0x4d,0x48,0x37,0xd6,0xb1,0x8c,0x5f,0x26,0x5f,0xb5,0x26, + 0x07,0x0b,0x85,0xb7,0x36,0x37,0x14,0xcf,0x5e,0x55,0xa5,0x3c,0xf3,0x1e,0x79,0x50, + 0xbb,0x85,0x3b,0xb2,0x94,0x68,0xb0,0x25,0x4f,0x75,0xec,0xf0,0xf9,0xc0,0x5a,0x2d, + 0xe5,0xed,0x67,0xcd,0x88,0x55,0xa0,0x42,0xde,0x78,0xbc,0xfe,0x30,0xb1,0x62,0x2d, + 0xe1,0xfd,0xec,0x75,0x03,0xa6,0x1f,0x7c,0xc4,0x3a,0x4a,0x59,0xfe,0x77,0xc3,0x99, + 0x96,0x87,0x44,0xc3, +}; + +static const UInt8 kBaseLinePCSEscrowRootGM[] = { + 0x30,0x82,0x03,0xD8,0x30,0x82,0x02,0xC0,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x64, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30, + 0x7D,0x31,0x0C,0x30,0x0A,0x06,0x03,0x55,0x04,0x05,0x13,0x03,0x31,0x30,0x30,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11, + 0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, + 0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,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,0x23,0x30,0x21,0x06,0x03,0x55, + 0x04,0x03,0x13,0x1A,0x45,0x66,0x66,0x61,0x63,0x65,0x61,0x62,0x6C,0x65,0x20,0x53, + 0x65,0x72,0x76,0x69,0x63,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x1E, + 0x17,0x0D,0x31,0x34,0x30,0x37,0x32,0x38,0x32,0x31,0x30,0x33,0x35,0x32,0x5A,0x17, + 0x0D,0x32,0x34,0x30,0x37,0x32,0x38,0x32,0x31,0x30,0x33,0x35,0x32,0x5A,0x30,0x7D, + 0x31,0x0C,0x30,0x0A,0x06,0x03,0x55,0x04,0x05,0x13,0x03,0x31,0x30,0x30,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06, + 0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E, + 0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,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,0x23,0x30,0x21,0x06,0x03,0x55,0x04, + 0x03,0x13,0x1A,0x45,0x66,0x66,0x61,0x63,0x65,0x61,0x62,0x6C,0x65,0x20,0x53,0x65, + 0x72,0x76,0x69,0x63,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,0xC0,0x55, + 0xCC,0x74,0xCF,0x49,0xE9,0xEC,0x9A,0x76,0x17,0x30,0x12,0x40,0x7D,0xC1,0x69,0x98, + 0x97,0x2C,0xA7,0xC0,0xD6,0xF4,0x9A,0x1D,0xC2,0x46,0x75,0xB6,0xAD,0x81,0xE2,0x2F, + 0x65,0xF1,0xAF,0xF6,0xBA,0xBD,0xC1,0x44,0x37,0x93,0xB8,0x92,0x2A,0x83,0xCC,0xE3, + 0x6F,0xFD,0x95,0xAA,0x86,0xAE,0x4D,0x62,0x98,0xBC,0xE6,0x90,0x40,0x5B,0x5A,0x2E, + 0x65,0x0C,0xFF,0x07,0xB9,0x79,0xC4,0x2E,0x2E,0x72,0x80,0xE3,0xB9,0x98,0x08,0xE9, + 0x3B,0x79,0x3B,0x46,0x99,0xD7,0xB9,0xDF,0x1F,0xC4,0x0D,0x49,0xB9,0x78,0x39,0xAF, + 0x7F,0xF5,0xDC,0x9C,0xEE,0xC1,0xB0,0x90,0x70,0x97,0xD6,0xE7,0x49,0x0C,0x11,0x19, + 0xE9,0xDD,0xEA,0x38,0x30,0xB9,0x1D,0xF4,0xD7,0xFF,0xBB,0xFC,0x6B,0x49,0xFC,0x69, + 0xE8,0x05,0x8E,0x96,0x14,0x87,0x62,0xD6,0x82,0x2F,0xA2,0x97,0xB5,0x4A,0x80,0x46, + 0x43,0xF5,0xF2,0x1B,0x94,0xBF,0xFE,0x48,0x8B,0x7F,0x4D,0xD6,0x3D,0x3E,0x64,0xBE, + 0x09,0x7C,0x9E,0x24,0x80,0xDE,0xAB,0xC9,0x17,0x91,0xAC,0x60,0x06,0x98,0x9C,0xCB, + 0xAD,0x04,0x41,0x1F,0x7F,0xE5,0xC2,0x08,0xD5,0x80,0xD7,0x63,0xF1,0x5C,0x60,0xA2, + 0xE5,0xAD,0x5F,0x6E,0xBC,0x3A,0xC4,0x9F,0x4D,0xE4,0x65,0xA3,0xF2,0x18,0x0B,0x1A, + 0x2D,0xB4,0x64,0x3D,0x53,0x5A,0x14,0xF6,0x26,0x92,0x13,0x23,0x83,0x33,0xBE,0xE0, + 0xA4,0x43,0xFC,0x79,0xA0,0x91,0xFB,0x1C,0x17,0xF0,0x87,0xE5,0x8C,0x68,0xF2,0xCF, + 0xAE,0x3B,0xC5,0xD5,0xD2,0x58,0x8E,0xFB,0x29,0x53,0xFE,0x9E,0xDE,0x4F,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,0x01,0x06,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04, + 0x16,0x04,0x14,0x64,0x0B,0xE4,0x72,0x73,0x5C,0x54,0xB2,0x58,0x59,0xAE,0x42,0xDF, + 0x2B,0xB7,0xBA,0xB9,0xEB,0x86,0xAE,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18, + 0x30,0x16,0x80,0x14,0x64,0x0B,0xE4,0x72,0x73,0x5C,0x54,0xB2,0x58,0x59,0xAE,0x42, + 0xDF,0x2B,0xB7,0xBA,0xB9,0xEB,0x86,0xAE,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x79,0xF4,0x22,0xC9, + 0x6C,0x25,0x64,0x2D,0x8E,0x91,0x53,0x7B,0xFB,0xA7,0xD2,0x0C,0xAD,0xDC,0xA9,0x83, + 0x90,0x75,0x16,0x98,0xC1,0x2C,0xFE,0x7C,0x16,0xCE,0x2A,0xA0,0xB8,0x8A,0xF6,0xDB, + 0x3E,0x2D,0x6C,0x5D,0x61,0x41,0x10,0xBB,0x02,0xBA,0x51,0x5B,0x42,0x62,0x18,0x9F, + 0xC4,0x25,0xF3,0x24,0xCC,0x1D,0xD2,0xFF,0x47,0xB2,0x14,0x9E,0x6A,0x31,0xA3,0xA7, + 0xB1,0x0C,0x7E,0x55,0xCE,0xC4,0x9E,0xA6,0x0A,0x06,0x9B,0x50,0x40,0x04,0x13,0xA0, + 0xC7,0x4D,0x37,0xD9,0x85,0xCF,0xB2,0xD9,0x16,0x38,0x4B,0xA3,0xA5,0x3E,0xDC,0x06, + 0x0D,0xE0,0xB1,0x13,0x7C,0x8B,0x79,0x1F,0x67,0xD8,0xBA,0xB4,0x58,0x9C,0x84,0x18, + 0xE4,0xED,0x22,0x17,0x41,0xA9,0x3B,0x88,0xD5,0x55,0x54,0x5F,0x33,0x4D,0xE2,0xBD, + 0xBE,0x66,0x46,0x59,0xC0,0x60,0xC5,0xB2,0x7A,0xF6,0xCA,0xCD,0xB9,0x2D,0xBD,0x50, + 0xB3,0xD6,0x18,0xD5,0x1F,0xFA,0x42,0x30,0x4C,0x10,0xFB,0x12,0xA9,0x9A,0x0E,0x39, + 0xFA,0x77,0xB6,0x82,0x53,0xF3,0x35,0x74,0xB5,0x10,0x5A,0x22,0xAE,0x17,0x25,0xD1, + 0x09,0xB9,0x71,0x08,0xA1,0xFA,0x2D,0xB9,0xEA,0x8C,0xC5,0xAC,0x31,0x6C,0x45,0x46, + 0x2E,0x11,0x2D,0x75,0x07,0x88,0x39,0xA3,0x14,0x08,0xA6,0xBF,0x7B,0x2C,0x26,0xAE, + 0x28,0xE9,0x1D,0x6C,0xFF,0xAC,0x99,0x53,0x44,0x91,0x26,0x2E,0x82,0x1A,0x11,0x66, + 0xB5,0x9C,0xEF,0x9E,0xC1,0x52,0x8F,0xCE,0x12,0xF3,0x88,0x86,0x06,0xF0,0xE8,0x62, + 0x69,0x12,0x04,0x6D,0x2B,0x75,0x83,0xE1,0x12,0xFC,0x3E,0xF1, +}; + + +static struct RootRecord kBaseLineEscrowRootRecord = {sizeof(kBaseLineEscrowRootGM), (UInt8*)kBaseLineEscrowRootGM}; +static struct RootRecord* kBaseLineEscrowRoots[] = {&kBaseLineEscrowRootRecord}; +static const int kNumberOfBaseLineEscrowRoots = (int)(sizeof(kBaseLineEscrowRoots)/sizeof(kBaseLineEscrowRoots[0])); + +static struct RootRecord kBaseLinePCSEscrowRootRecord = {sizeof(kBaseLinePCSEscrowRootGM), (UInt8*)kBaseLinePCSEscrowRootGM}; +static struct RootRecord* kBaseLinePCSEscrowRoots[] = {&kBaseLinePCSEscrowRootRecord}; +static const int kNumberOfBaseLinePCSEscrowRoots = (int)(sizeof(kBaseLinePCSEscrowRoots)/sizeof(kBaseLinePCSEscrowRoots[0])); + +#endif diff --git a/sec/Security/AuthorizationStatus.h b/Security/sec/Security/AuthorizationStatus.h similarity index 100% rename from sec/Security/AuthorizationStatus.h rename to Security/sec/Security/AuthorizationStatus.h diff --git a/Security/sec/Security/Regressions/Security_regressions.h b/Security/sec/Security/Regressions/Security_regressions.h new file mode 100644 index 00000000..87884aaf --- /dev/null +++ b/Security/sec/Security/Regressions/Security_regressions.h @@ -0,0 +1,99 @@ +/* To add a test: + 1) add it here + 2) Add it as command line argument for SecurityTest.app in the Release and Debug schemes + */ +#include + +ONE_TEST(pbkdf2_00_hmac_sha1) +ONE_TEST(spbkdf_00_hmac_sha1) + +ONE_TEST(si_00_find_nothing) +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_14_dateparse) +ONE_TEST(si_15_certificate) +ONE_TEST(si_16_ec_certificate) +ONE_TEST(si_20_sectrust_activation) +ONE_TEST(si_20_sectrust) +ONE_TEST(si_21_sectrust_asr) +ONE_TEST(si_22_sectrust_iap) +ONE_TEST(si_23_sectrust_ocsp) +ONE_TEST(si_24_sectrust_itms) +ONE_TEST(si_24_sectrust_nist) +ONE_TEST(si_24_sectrust_otatasking) +ONE_TEST(si_24_sectrust_mobileasset) +ONE_TEST(si_24_sectrust_diginotar) +ONE_TEST(si_24_sectrust_appleid) +ONE_TEST(si_24_sectrust_digicert_malaysia) +ONE_TEST(si_24_sectrust_shoebox) +ONE_TEST(si_25_sectrust_ipsec_eap) +ONE_TEST(si_26_applicationsigning) +ONE_TEST(si_27_sectrust_exceptions) +ONE_TEST(si_28_sectrustsettings) +ONE_TEST(si_29_sectrust_codesigning) +DISABLED_ONE_TEST(si_30_keychain_upgrade) //obsolete, needs updating +DISABLED_ONE_TEST(si_31_keychain_bad) +DISABLED_ONE_TEST(si_31_keychain_unreadable) +ONE_TEST(si_33_keychain_backup) +ONE_TEST(si_40_seckey) +ONE_TEST(si_40_seckey_custom) +ONE_TEST(si_41_sececkey) +ONE_TEST(si_42_identity) +ONE_TEST(si_43_persistent) +ONE_TEST(si_50_secrandom) +ONE_TEST(si_60_cms) +DISABLED_ONE_TEST(si_61_pkcs12) +ONE_TEST(si_62_csr) +ONE_TEST(si_63_scep) +ONE_TEST(si_64_ossl_cms) +ONE_TEST(si_65_cms_cert_policy) +ONE_TEST(si_66_smime) +ONE_TEST(si_67_sectrust_blacklist) +ONE_TEST(si_68_secmatchissuer) +ONE_TEST(si_69_keydesc) +ONE_TEST(si_70_sectrust_unified) +ONE_TEST(si_71_mobile_store_policy) +ONE_TEST(si_72_syncableitems) +ONE_TEST(si_73_secpasswordgenerate) +#if TARGET_OS_IPHONE +ONE_TEST(si_74_OTA_PKI_Signer) +ONE_TEST(si_75_AppleIDRecordSigning) +#if TARGET_IPHONE_SIMULATOR +OFF_ONE_TEST(si_76_shared_credentials) +#else +ONE_TEST(si_76_shared_credentials) +#endif +ONE_TEST(si_77_SecAccessControl) +ONE_TEST(si_79_smp_cert_policy) +#else +DISABLED_ONE_TEST(si_74_OTA_PKI_Signer) +DISABLED_ONE_TEST(si_75_AppleIDRecordSigning) +DISABLED_ONE_TEST(si_76_shared_credentials) +DISABLED_ONE_TEST(si_77_SecAccessControl) +DISABLED_ONE_TEST(si_79_smp_cert_policy) +#endif +ONE_TEST(si_78_query_attrs) +ONE_TEST(si_80_empty_data) +#if TARGET_IPHONE_SIMULATOR +OFF_ONE_TEST(si_81_item_acl_stress) +#else +ONE_TEST(si_81_item_acl_stress) +#endif +ONE_TEST(si_81_sectrust_server_auth) + +ONE_TEST(vmdh_40) +ONE_TEST(vmdh_41_example) +ONE_TEST(vmdh_42_example2) + +ONE_TEST(otr_00_identity) +ONE_TEST(otr_30_negotiation) +ONE_TEST(otr_otrdh) +ONE_TEST(otr_packetdata) + +#if TARGET_OS_IPHONE +ONE_TEST(so_01_serverencryption) +#else +DISABLED_ONE_TEST(so_01_serverencryption) +#endif diff --git a/sec/Security/Regressions/crypto/pbkdf2-00-hmac-sha1.c b/Security/sec/Security/Regressions/crypto/pbkdf2-00-hmac-sha1.c similarity index 98% rename from sec/Security/Regressions/crypto/pbkdf2-00-hmac-sha1.c rename to Security/sec/Security/Regressions/crypto/pbkdf2-00-hmac-sha1.c index 6b7901f4..80c243df 100644 --- a/sec/Security/Regressions/crypto/pbkdf2-00-hmac-sha1.c +++ b/Security/sec/Security/Regressions/crypto/pbkdf2-00-hmac-sha1.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010,2012 Apple Inc. All Rights Reserved. */ #include diff --git a/sec/Security/Regressions/crypto/spbkdf-00-hmac-sha1.c b/Security/sec/Security/Regressions/crypto/spbkdf-00-hmac-sha1.c similarity index 99% rename from sec/Security/Regressions/crypto/spbkdf-00-hmac-sha1.c rename to Security/sec/Security/Regressions/crypto/spbkdf-00-hmac-sha1.c index 25641aea..8bd80a02 100644 --- a/sec/Security/Regressions/crypto/spbkdf-00-hmac-sha1.c +++ b/Security/sec/Security/Regressions/crypto/spbkdf-00-hmac-sha1.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010,2012 Apple Inc. All Rights Reserved. */ #include diff --git a/sec/Security/Regressions/otr/otr-00-identity.c b/Security/sec/Security/Regressions/otr/otr-00-identity.c similarity index 89% rename from sec/Security/Regressions/otr/otr-00-identity.c rename to Security/sec/Security/Regressions/otr/otr-00-identity.c index 87872715..382791d5 100644 --- a/sec/Security/Regressions/otr/otr-00-identity.c +++ b/Security/sec/Security/Regressions/otr/otr-00-identity.c @@ -1,12 +1,27 @@ /* - * mp-00-identity.c - * regressions - * - * Created by Mitch Adler on 2/3/11. - * Copyright 2011 Apple Inc. All rights reserved. + * Copyright (c) 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@ */ + #include #include "Security_regressions.h" diff --git a/sec/Security/Regressions/otr/otr-30-negotiation.c b/Security/sec/Security/Regressions/otr/otr-30-negotiation.c similarity index 80% rename from sec/Security/Regressions/otr/otr-30-negotiation.c rename to Security/sec/Security/Regressions/otr/otr-30-negotiation.c index 0f844395..5b09d0e5 100644 --- a/sec/Security/Regressions/otr/otr-30-negotiation.c +++ b/Security/sec/Security/Regressions/otr/otr-30-negotiation.c @@ -1,10 +1,26 @@ -// -// otr-30-negotiation.c -// regressions -// -// Created by Mitch Adler on 6/7/11. -// Copyright 2011 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include "Security_regressions.h" @@ -88,6 +104,8 @@ static void sendMessages(int howMany, SecOTRSessionRef *bobSession, SecOTRSessio && 0 == memcmp(CFDataGetBytePtr(rawBobToAlice), CFDataGetBytePtr(aliceDecode), (size_t)CFDataGetLength(rawBobToAlice)), "reply matched"); CFReleaseNull(rawAliceToBob); + CFReleaseNull(rawBobToAlice); + CFReleaseNull(protectedBobToAlice); CFReleaseNull(protectedAliceToBob); CFReleaseNull(aliceDecode); @@ -103,9 +121,12 @@ static void sendMessages(int howMany, SecOTRSessionRef *bobSession, SecOTRSessio #define kNegotiateTestCount (14 + sendMessagesCount(5) \ + 2 + sendMessagesCount(1) \ - + 1 + sendMessagesCount(1)) -static void negotiate(SecOTRSessionRef* aliceSession, SecOTRSessionRef* bobSession, bool serialize) + + 1 + sendMessagesCount(1) \ + + sendMessagesCount(3)) +static void negotiate(SecOTRSessionRef* aliceSession, SecOTRSessionRef* bobSession, bool serialize, bool textMode, bool compact) { + const int kEmptyMessageSize = textMode ? 6 : 0; + // Step 1: Create a start packet for each side of the transaction CFMutableDataRef bobStartPacket = CFDataCreateMutable(kCFAllocatorDefault, 0); @@ -200,11 +221,14 @@ static void negotiate(SecOTRSessionRef* aliceSession, SecOTRSessionRef* bobSessi ok_status(SecOTRSProcessPacket(*aliceSession, bobSigResponse, aliceFinalResponse), "Bob Final Sig failed"); + is(kEmptyMessageSize, CFDataGetLength(aliceFinalResponse), "Alice had nothing left to say"); + CFReleaseNull(aliceFinalResponse); + CFReleaseNull(bobSigResponse); + if (serialize) serializeAndDeserialize(aliceSession); - is(6, CFDataGetLength(bobFinalResponse), "Alice had nothing left to say"); - is(6, CFDataGetLength(bobFinalResponse), "Bob had nothing left to say"); + is(kEmptyMessageSize, CFDataGetLength(bobFinalResponse), "Bob had nothing left to say"); ok(SecOTRSGetIsReadyForMessages(*bobSession), "Bob is ready"); ok(SecOTRSGetIsReadyForMessages(*aliceSession), "Alice is ready"); @@ -220,13 +244,18 @@ static void negotiate(SecOTRSessionRef* aliceSession, SecOTRSessionRef* bobSessi ok_status(SecOTRSSignAndProtectMessage(*aliceSession, rawAliceToBob, protectedAliceToBob), "encode message"); + + const OSStatus expectedError = compact ? errSecAuthFailed : errSecOTRTooOld; + sendMessages(1, bobSession, aliceSession, serialize); - ok(errSecOTRTooOld ==SecOTRSVerifyAndExposeMessage(*bobSession, protectedAliceToBob, bobDecode), "Decode old message"); + is(SecOTRSVerifyAndExposeMessage(*bobSession, protectedAliceToBob, bobDecode), expectedError, "Decode old message"); sendMessages(1, bobSession, aliceSession, serialize); - ok(errSecOTRTooOld == SecOTRSVerifyAndExposeMessage(*bobSession, protectedAliceToBob, bobDecode), "Fail to decode excessively old message"); + is(SecOTRSVerifyAndExposeMessage(*bobSession, protectedAliceToBob, bobDecode), expectedError, "Decode excessively old message"); + + sendMessages(3, bobSession, aliceSession, serialize); CFReleaseNull(rawAliceToBob); CFReleaseNull(protectedAliceToBob); @@ -234,7 +263,7 @@ static void negotiate(SecOTRSessionRef* aliceSession, SecOTRSessionRef* bobSessi } -#define kTestTestCount (7 + kNegotiateTestCount) +#define kTestTestCount (9 + kNegotiateTestCount * 2) static void tests() { @@ -267,6 +296,12 @@ static void tests() ok(aliceSession, "create alice session"); ok(bobSession, "create bob session"); + SecOTRSessionRef aliceCompactSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, aliceID, bobPublicID, kSecOTRUseAppleCustomMessageFormat); + SecOTRSessionRef bobCompactSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, bobID, alicePublicID, kSecOTRUseAppleCustomMessageFormat); + + ok(aliceCompactSession, "create alice compact session"); + ok(bobCompactSession, "create bob compact session"); + // Release the IDs, sessions shouldn't need us to retain them for them. CFReleaseNull(aliceID); CFReleaseNull(bobID); @@ -274,7 +309,9 @@ static void tests() CFReleaseNull(alicePublicID); CFReleaseNull(bobPublicID); - negotiate(&aliceSession, &bobSession, true); + negotiate(&aliceSession, &bobSession, true, true, false); + + negotiate(&aliceCompactSession, &bobCompactSession, true, false, true); /* cleanup keychain */ ok(SecOTRFIPurgeAllFromKeychain(&testError),"cleanup keychain"); diff --git a/Security/sec/Security/Regressions/otr/otr-otrdh.c b/Security/sec/Security/Regressions/otr/otr-otrdh.c new file mode 100644 index 00000000..b2bde0c9 --- /dev/null +++ b/Security/sec/Security/Regressions/otr/otr-otrdh.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 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@ + */ + + +#include "Security_regressions.h" + +#include +#include + +int otr_otrdh(int argc, char *const * argv) +{ + plan_tests(4); + + SecOTRFullDHKeyRef aliceFull = SecOTRFullDHKCreate(kCFAllocatorDefault); + SecOTRPublicDHKeyRef alicePublic = SecOTRPublicDHKCreateFromFullKey(kCFAllocatorDefault, aliceFull); + + SecOTRFullDHKeyRef bobFull = SecOTRFullDHKCreate(kCFAllocatorDefault); + SecOTRPublicDHKeyRef bobPublic = SecOTRPublicDHKCreateFromFullKey(kCFAllocatorDefault, bobFull); + + uint8_t aliceMessageKeys[2][kOTRMessageKeyBytes]; + uint8_t aliceMacKeys[2][kOTRMessageMacKeyBytes]; + + SecOTRDHKGenerateOTRKeys(aliceFull, bobPublic, + aliceMessageKeys[0], aliceMacKeys[0], + aliceMessageKeys[1], aliceMacKeys[1]); + + uint8_t bobMessageKeys[2][kOTRMessageKeyBytes]; + uint8_t bobMacKeys[2][kOTRMessageMacKeyBytes]; + + SecOTRDHKGenerateOTRKeys(bobFull, alicePublic, + bobMessageKeys[0], bobMacKeys[0], + bobMessageKeys[1], bobMacKeys[1]); + + + ok(0 == memcmp(aliceMessageKeys[0], bobMessageKeys[1], sizeof(aliceMessageKeys[0])), "Mac Keys don't match!!"); + ok(0 == memcmp(aliceMessageKeys[1], bobMessageKeys[0], sizeof(aliceMessageKeys[1])), "Mac Keys don't match!!"); + ok(0 == memcmp(aliceMacKeys[0], bobMacKeys[1], sizeof(aliceMacKeys[0])), "Mac Keys don't match!!"); + ok(0 == memcmp(aliceMacKeys[1], bobMacKeys[0], sizeof(aliceMacKeys[1])), "Mac Keys don't match!!"); + + return 0; +} diff --git a/Security/sec/Security/Regressions/otr/otr-packetdata.c b/Security/sec/Security/Regressions/otr/otr-packetdata.c new file mode 100644 index 00000000..f4e1753d --- /dev/null +++ b/Security/sec/Security/Regressions/otr/otr-packetdata.c @@ -0,0 +1,283 @@ +/* + * Copyright (c) 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@ + */ + + +#include +#include "SecOTRPacketData.h" + +#include + +#include "security_regressions.h" + +static bool CFDataMatches(CFDataRef data, size_t amount, const uint8_t* bytes) +{ + if ((size_t) CFDataGetLength(data) != amount) + return false; + + return 0 == memcmp(CFDataGetBytePtr(data), bytes, amount); + +} + + +static void testAppendShort() +{ + CFMutableDataRef result = CFDataCreateMutable(kCFAllocatorDefault, 0); + + const uint8_t firstResult[] = { 1, 2 }; + AppendShort(result, 0x0102); + ok(CFDataMatches(result, sizeof(firstResult), firstResult), "Didn't insert correctly"); + + const uint8_t secondResult[] = { 1, 2, 3, 4}; + AppendShort(result, 0x0304); + ok(CFDataMatches(result, sizeof(secondResult), secondResult), "Didn't append!"); + + CFRelease(result); + + result = CFDataCreateMutable(kCFAllocatorDefault, 0); + + const uint8_t thirdResult[] = { 0, 0 }; + AppendShort(result, 0x0); + ok(CFDataMatches(result, sizeof(thirdResult), thirdResult), "Didn't insert zero"); + + CFRelease(result); + + result = CFDataCreateMutable(kCFAllocatorDefault, 0); + + const uint8_t fourthResult[] = { 0xFF, 0xFF}; + AppendShort(result, 0xFFFF); + ok(CFDataMatches(result, sizeof(fourthResult), fourthResult), "Didn't insert 0xFFFFFFFF"); + + CFRelease(result); +} + +static void testAppendLong() +{ + CFMutableDataRef result = CFDataCreateMutable(kCFAllocatorDefault, 0); + + const uint8_t firstResult[] = { 1, 2, 3, 4 }; + AppendLong(result, 0x01020304); + ok(CFDataMatches(result, sizeof(firstResult), firstResult), "Didn't insert correctly"); + + const uint8_t secondResult[] = { 1, 2, 3, 4, 5, 6, 7, 8}; + AppendLong(result, 0x05060708); + ok(CFDataMatches(result, sizeof(secondResult), secondResult), "Didn't append!"); + + CFRelease(result); + + result = CFDataCreateMutable(kCFAllocatorDefault, 0); + + const uint8_t thirdResult[] = { 0, 0, 0, 0 }; + AppendLong(result, 0x0); + ok(CFDataMatches(result, sizeof(thirdResult), thirdResult), "Didn't insert zero"); + + CFRelease(result); + + result = CFDataCreateMutable(kCFAllocatorDefault, 0); + + const uint8_t fourthResult[] = { 0xFF, 0xFF, 0xFF, 0xFF }; + AppendLong(result, 0xFFFFFFFF); + ok(CFDataMatches(result, sizeof(fourthResult), fourthResult), "Didn't insert 0xFFFFFFFF"); + + CFRelease(result); +} + +static void testAppendLongLong() +{ + CFMutableDataRef result = CFDataCreateMutable(kCFAllocatorDefault, 0); + + const uint8_t firstResult[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + AppendLongLong(result, 0x0102030405060708); + ok(CFDataMatches(result, sizeof(firstResult), firstResult), "insert correctly"); + + const uint8_t secondResult[] = { 1, 2, 3, 4, 5, 6, 7, 8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10}; + AppendLongLong(result, 0x090A0B0C0D0E0F10); + ok(CFDataMatches(result, sizeof(secondResult), secondResult), "append!"); + + CFRelease(result); + + result = CFDataCreateMutable(kCFAllocatorDefault, 0); + + const uint8_t thirdResult[] = { 0, 0, 0, 0, 0, 0, 0, 0}; + AppendLongLong(result, 0x0); + ok(CFDataMatches(result, sizeof(thirdResult), thirdResult), "insert zero"); + + CFRelease(result); + + result = CFDataCreateMutable(kCFAllocatorDefault, 0); + + const uint8_t fourthResult[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + AppendLongLong(result, 0xFFFFFFFFFFFFFFFF); + ok(CFDataMatches(result, sizeof(fourthResult), fourthResult), "insert 0xFFFFFFFFFFFFFFF"); + + CFRelease(result); +} + +static void testAppendLongLongCompact() +{ + CFMutableDataRef result = CFDataCreateMutable(kCFAllocatorDefault, 0); + + const uint64_t firstValue = 0x000001FC07F; + const uint8_t firstResult[] = { 0xFF,0x80,0x7F }; + AppendLongLongCompact(result, firstValue); + ok(CFDataMatches(result, sizeof(firstResult), firstResult), "insert correctly"); + + uint64_t readback; + const uint8_t *readPtr = firstResult; + size_t size = sizeof(firstResult); + ReadLongLongCompact(&readPtr, &size, &readback); + + is(readback, firstValue, "read back"); + + const uint8_t secondResult[] = { 0xFF,0x80,0x7F, 0x82, 0x80, 0x81, 0x80, 0xff, 0x80, 0x7f }; + AppendLongLongCompact(result, 0x800101FC07F); + ok(CFDataMatches(result, sizeof(secondResult), secondResult), "append!"); + + CFRelease(result); + + result = CFDataCreateMutable(kCFAllocatorDefault, 0); + + const uint8_t thirdResult[] = { 0 }; + AppendLongLongCompact(result, 0x0); + ok(CFDataMatches(result, sizeof(thirdResult), thirdResult), "insert zero"); + + readPtr = thirdResult; + size = sizeof(thirdResult); + ReadLongLongCompact(&readPtr, &size, &readback); + is(readback, 0ULL, "read back"); + + CFRelease(result); + + result = CFDataCreateMutable(kCFAllocatorDefault, 0); + + const uint8_t fourthResult[] = { 0x81, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F }; + AppendLongLongCompact(result, 0xFFFFFFFFFFFFFFFF); + ok(CFDataMatches(result, sizeof(fourthResult), fourthResult), "insert 0xFFFFFFFFFFFFFFF"); + + readPtr = fourthResult; + size = sizeof(fourthResult); + ReadLongLongCompact(&readPtr, &size, &readback); + is(readback, 0xFFFFFFFFFFFFFFFF, "read back"); + + CFRelease(result); +} + +static void testAppendData() +{ + CFMutableDataRef result = CFDataCreateMutable(kCFAllocatorDefault, 0); + + const uint8_t firstResult[] = { 0, 0, 0, 4, 1, 2, 3, 4 }; + AppendDATA(result, sizeof(firstResult) - 4, firstResult + 4); + ok(CFDataMatches(result, sizeof(firstResult), firstResult), "Didn't insert correctly"); + + const uint8_t secondResult[] = { 0, 0, 0, 4, 1, 2, 3, 4, 0, 0, 0, 1, 0 }; + AppendDATA(result, sizeof(secondResult) - 12, secondResult + 12); + ok(CFDataMatches(result, sizeof(secondResult), secondResult), "Didn't append!"); + + CFRelease(result); + + result = CFDataCreateMutable(kCFAllocatorDefault, 0); + + const uint8_t thirdResult[] = { 0, 0, 0, 2, 0, 0 }; + AppendDATA(result, sizeof(thirdResult) - 4, thirdResult + 4); + ok(CFDataMatches(result, sizeof(thirdResult), thirdResult), "Didn't insert correctly"); + + CFRelease(result); + + result = CFDataCreateMutable(kCFAllocatorDefault, 0); + + const uint8_t fourthResult[] = { 0, 0, 0, 5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + AppendDATA(result, sizeof(fourthResult) - 4, fourthResult + 4); + ok(CFDataMatches(result, sizeof(fourthResult), fourthResult), "Didn't insert correctly"); + + CFRelease(result); +} + + +static void testAppendMPI() +{ + const size_t kUnitBufferN = 1024; + cc_unit unitBuffer[1024]; + + CFMutableDataRef result = CFDataCreateMutable(kCFAllocatorDefault, 0); + + const uint8_t firstResult[] = { 0, 0, 0, 2, 1, 2 }; + ccn_read_uint(kUnitBufferN, unitBuffer, sizeof(firstResult) - 4, firstResult + 4); + AppendMPI(result, kUnitBufferN, unitBuffer); + + ok(CFDataMatches(result, sizeof(firstResult), firstResult), "Didn't insert zero"); + + const uint8_t secondResult[] = { 0, 0, 0, 2, 1, 2, 0, 0, 0, 3, 5, 6, 7 }; + ccn_read_uint(kUnitBufferN, unitBuffer, sizeof(secondResult) - 10, secondResult + 10); + AppendMPI(result, kUnitBufferN, unitBuffer); + + ok(CFDataMatches(result, sizeof(secondResult), secondResult), "Didn't append zero"); + + CFRelease(result); + + result = CFDataCreateMutable(kCFAllocatorDefault, 0); + + const uint8_t thirdResult[] = { 0, 0, 0, 1, 1 }; + ccn_read_uint(kUnitBufferN, unitBuffer, sizeof(thirdResult) - 4, thirdResult + 4); + AppendMPI(result, kUnitBufferN, unitBuffer); + + ok(CFDataMatches(result, sizeof(thirdResult), thirdResult), "Didn't insert zero"); + + CFRelease(result); + + result = CFDataCreateMutable(kCFAllocatorDefault, 0); + + const uint8_t fourthResult[] = { 0, 0, 0, 7, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }; + ccn_read_uint(kUnitBufferN, unitBuffer, sizeof(fourthResult) - 4, fourthResult + 4); + AppendMPI(result, kUnitBufferN, unitBuffer); + + ok(CFDataMatches(result, sizeof(fourthResult), fourthResult), "Didn't insert zero"); + + CFRelease(result); + + result = CFDataCreateMutable(kCFAllocatorDefault, 0); + + const uint8_t paddedData[] = { 0, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA }; + const uint8_t shortenedResult[] = { 0, 0, 0, 5, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA }; + ccn_read_uint(kUnitBufferN, unitBuffer, sizeof(paddedData), paddedData); + AppendMPI(result, kUnitBufferN, unitBuffer); + + ok(CFDataMatches(result, sizeof(shortenedResult), shortenedResult), "Didn't insert zero"); + + CFRelease(result); + +} + +int otr_packetdata(int argc, char *const * argv) +{ + plan_tests(28); + + testAppendShort(); + testAppendLong(); + testAppendLongLong(); + testAppendLongLongCompact(); + testAppendData(); + testAppendMPI(); + + return 0; +} + diff --git a/sec/Security/Regressions/secitem/si-00-find-nothing.c b/Security/sec/Security/Regressions/secitem/si-00-find-nothing.c similarity index 92% rename from sec/Security/Regressions/secitem/si-00-find-nothing.c rename to Security/sec/Security/Regressions/secitem/si-00-find-nothing.c index 64884126..4b813641 100644 --- a/sec/Security/Regressions/secitem/si-00-find-nothing.c +++ b/Security/sec/Security/Regressions/secitem/si-00-find-nothing.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007,2009-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2009-2010,2012-2013 Apple Inc. All Rights Reserved. */ #include diff --git a/sec/Security/Regressions/secitem/si-05-add.c b/Security/sec/Security/Regressions/secitem/si-05-add.c similarity index 93% rename from sec/Security/Regressions/secitem/si-05-add.c rename to Security/sec/Security/Regressions/secitem/si-05-add.c index 3e38f803..49f05793 100644 --- a/sec/Security/Regressions/secitem/si-05-add.c +++ b/Security/sec/Security/Regressions/secitem/si-05-add.c @@ -1,12 +1,27 @@ /* - * si-05-add.c - * Security - * - * Created by Michael Brouwer on 12/6/08. - * Copyright (c) 2008-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-2010,2012-2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include #include #include diff --git a/sec/Security/Regressions/secitem/si-10-find-internet.c b/Security/sec/Security/Regressions/secitem/si-10-find-internet.c similarity index 98% rename from sec/Security/Regressions/secitem/si-10-find-internet.c rename to Security/sec/Security/Regressions/secitem/si-10-find-internet.c index e58c8108..da40bfcf 100644 --- a/sec/Security/Regressions/secitem/si-10-find-internet.c +++ b/Security/sec/Security/Regressions/secitem/si-10-find-internet.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2010,2012-2013 Apple Inc. All Rights Reserved. */ #include diff --git a/sec/Security/Regressions/secitem/si-11-update-data.c b/Security/sec/Security/Regressions/secitem/si-11-update-data.c similarity index 97% rename from sec/Security/Regressions/secitem/si-11-update-data.c rename to Security/sec/Security/Regressions/secitem/si-11-update-data.c index 840a3f69..b1a4f1a8 100644 --- a/sec/Security/Regressions/secitem/si-11-update-data.c +++ b/Security/sec/Security/Regressions/secitem/si-11-update-data.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2010,2012-2013 Apple Inc. All Rights Reserved. */ #include diff --git a/sec/Security/Regressions/secitem/si-12-item-stress.c b/Security/sec/Security/Regressions/secitem/si-12-item-stress.c similarity index 94% rename from sec/Security/Regressions/secitem/si-12-item-stress.c rename to Security/sec/Security/Regressions/secitem/si-12-item-stress.c index 5e75be7f..d93aaefc 100644 --- a/sec/Security/Regressions/secitem/si-12-item-stress.c +++ b/Security/sec/Security/Regressions/secitem/si-12-item-stress.c @@ -1,11 +1,26 @@ -// -// si-12-item-stress.c -// sec -// -// Created by Michael Brouwer on 8/1/13. -// Copyright (c) 2013 Apple Inc. All Rights Reserved. -// -// +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include #include @@ -324,6 +339,7 @@ static void tests(void) CFDictionarySetValue(item, kSecAttrSynchronizable, kCFBooleanTrue); ok_status(SecItemAdd(item, NULL), "add sync"); + // No tombstones by default per rdar://14680869, so explicitly add one CFDictionarySetValue(item, kSecUseTombstones, kCFBooleanTrue); ok_status(SecItemDelete(item), "delete sync"); diff --git a/sec/Security/Regressions/secitem/si-14-dateparse.c b/Security/sec/Security/Regressions/secitem/si-14-dateparse.c similarity index 85% rename from sec/Security/Regressions/secitem/si-14-dateparse.c rename to Security/sec/Security/Regressions/secitem/si-14-dateparse.c index ef2eca01..3c575785 100644 --- a/sec/Security/Regressions/secitem/si-14-dateparse.c +++ b/Security/sec/Security/Regressions/secitem/si-14-dateparse.c @@ -1,10 +1,26 @@ -// -// si-14-dateparse.c -// regressions -// -// Created by Michael Brouwer on 5/5/11. -// Copyright 2011 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include @@ -17,8 +33,6 @@ #include "Security_regressions.h" -#define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) CFRelease(_cf); } - #define dateparse(TTYPE, DATE) SecAbsoluteTimeFromDateContent(ASN1_ ## TTYPE ## _TIME, (const uint8_t *)DATE, sizeof(DATE) - 1); \ #define dateequals(TTYPE, DATE, EXPECTED) do { \ diff --git a/sec/Security/Regressions/secitem/si-15-certificate.c b/Security/sec/Security/Regressions/secitem/si-15-certificate.c similarity index 99% rename from sec/Security/Regressions/secitem/si-15-certificate.c rename to Security/sec/Security/Regressions/secitem/si-15-certificate.c index 5bffe1d1..6bdbbc58 100644 --- a/sec/Security/Regressions/secitem/si-15-certificate.c +++ b/Security/sec/Security/Regressions/secitem/si-15-certificate.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-2010,2012 Apple Inc. All Rights Reserved. */ #include diff --git a/sec/Security/Regressions/secitem/si-16-ec-certificate.c b/Security/sec/Security/Regressions/secitem/si-16-ec-certificate.c similarity index 98% rename from sec/Security/Regressions/secitem/si-16-ec-certificate.c rename to Security/sec/Security/Regressions/secitem/si-16-ec-certificate.c index 8db44a33..370c6b5c 100644 --- a/sec/Security/Regressions/secitem/si-16-ec-certificate.c +++ b/Security/sec/Security/Regressions/secitem/si-16-ec-certificate.c @@ -1,15 +1,30 @@ /* - * si-16-ec-certificate.c - * Security - * - * Created by Michael Brouwer on 4/16/10. - * Copyright 2010 Apple Inc. All rights reserved. + * Copyright (c) 2010,2012,2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010,2012,2014 Apple Inc. All Rights Reserved. */ #include diff --git a/sec/Security/Regressions/secitem/si-20-sectrust-activation.c b/Security/sec/Security/Regressions/secitem/si-20-sectrust-activation.c similarity index 99% rename from sec/Security/Regressions/secitem/si-20-sectrust-activation.c rename to Security/sec/Security/Regressions/secitem/si-20-sectrust-activation.c index c6642e88..01b29ccb 100644 --- a/sec/Security/Regressions/secitem/si-20-sectrust-activation.c +++ b/Security/sec/Security/Regressions/secitem/si-20-sectrust-activation.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2010,2012-2013 Apple Inc. All Rights Reserved. */ #include diff --git a/Security/sec/Security/Regressions/secitem/si-20-sectrust.c b/Security/sec/Security/Regressions/secitem/si-20-sectrust.c new file mode 100644 index 00000000..931e4fa7 --- /dev/null +++ b/Security/sec/Security/Regressions/secitem/si-20-sectrust.c @@ -0,0 +1,902 @@ +/* + * Copyright (c) 2006-2010,2012-2014 Apple Inc. All Rights Reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Security_regressions.h" + +/* + Serial Number: + 45:a8:3a:4a:79:4d:0c:2d:71:20:12:5a:7c:82:c0:af + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=Terms of use at https://www.verisign.com/rpa (c)06, CN=VeriSign Class 3 Extended Validation SSL SGC CA + Validity + Not Before: May 5 00:00:00 2014 GMT + Not After : May 4 23:59:59 2016 GMT + Subject: 1.3.6.1.4.1.311.60.2.1.3=US/1.3.6.1.4.1.311.60.2.1.2=California/businessCategory=Private Organization/serialNumber=C0806592, C=US/postalCode=95014, ST=California, L=Cupertino/street=1 Infinite Loop, O=Apple Inc., OU=GNCS Traffic Management, CN=secure1.store.apple.com + */ +static const uint8_t _c0[] = { + 0x30,0x82,0x05,0xFF,0x30,0x82,0x04,0xE7,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x45, + 0xA8,0x3A,0x4A,0x79,0x4D,0x0C,0x2D,0x71,0x20,0x12,0x5A,0x7C,0x82,0xC0,0xAF,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x81, + 0xBE,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,0x3B,0x30,0x39,0x06,0x03,0x55,0x04, + 0x0B,0x13,0x32,0x54,0x65,0x72,0x6D,0x73,0x20,0x6F,0x66,0x20,0x75,0x73,0x65,0x20, + 0x61,0x74,0x20,0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x76, + 0x65,0x72,0x69,0x73,0x69,0x67,0x6E,0x2E,0x63,0x6F,0x6D,0x2F,0x72,0x70,0x61,0x20, + 0x28,0x63,0x29,0x30,0x36,0x31,0x38,0x30,0x36,0x06,0x03,0x55,0x04,0x03,0x13,0x2F, + 0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6E,0x20,0x43,0x6C,0x61,0x73,0x73,0x20,0x33, + 0x20,0x45,0x78,0x74,0x65,0x6E,0x64,0x65,0x64,0x20,0x56,0x61,0x6C,0x69,0x64,0x61, + 0x74,0x69,0x6F,0x6E,0x20,0x53,0x53,0x4C,0x20,0x53,0x47,0x43,0x20,0x43,0x41,0x30, + 0x1E,0x17,0x0D,0x31,0x34,0x30,0x35,0x30,0x35,0x30,0x30,0x30,0x30,0x30,0x30,0x5A, + 0x17,0x0D,0x31,0x36,0x30,0x35,0x30,0x34,0x32,0x33,0x35,0x39,0x35,0x39,0x5A,0x30, + 0x82,0x01,0x1D,0x31,0x13,0x30,0x11,0x06,0x0B,0x2B,0x06,0x01,0x04,0x01,0x82,0x37, + 0x3C,0x02,0x01,0x03,0x13,0x02,0x55,0x53,0x31,0x1B,0x30,0x19,0x06,0x0B,0x2B,0x06, + 0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x02,0x13,0x0A,0x43,0x61,0x6C,0x69,0x66, + 0x6F,0x72,0x6E,0x69,0x61,0x31,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,0x11,0x30,0x0F,0x06,0x03,0x55,0x04,0x05,0x13,0x08,0x43, + 0x30,0x38,0x30,0x36,0x35,0x39,0x32,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06, + 0x13,0x02,0x55,0x53,0x31,0x0E,0x30,0x0C,0x06,0x03,0x55,0x04,0x11,0x14,0x05,0x39, + 0x35,0x30,0x31,0x34,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,0x14,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x18,0x30, + 0x16,0x06,0x03,0x55,0x04,0x09,0x14,0x0F,0x31,0x20,0x49,0x6E,0x66,0x69,0x6E,0x69, + 0x74,0x65,0x20,0x4C,0x6F,0x6F,0x70,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A, + 0x14,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x20,0x30,0x1E, + 0x06,0x03,0x55,0x04,0x0B,0x14,0x17,0x47,0x4E,0x43,0x53,0x20,0x54,0x72,0x61,0x66, + 0x66,0x69,0x63,0x20,0x4D,0x61,0x6E,0x61,0x67,0x65,0x6D,0x65,0x6E,0x74,0x31,0x20, + 0x30,0x1E,0x06,0x03,0x55,0x04,0x03,0x14,0x17,0x73,0x65,0x63,0x75,0x72,0x65,0x31, + 0x2E,0x73,0x74,0x6F,0x72,0x65,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, + 0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, + 0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01, + 0x00,0x97,0x1D,0x2E,0x6C,0x69,0x78,0x01,0x17,0xB2,0x6D,0x17,0x50,0x26,0xAE,0x25, + 0xAA,0x30,0x81,0xB8,0xD6,0xDC,0x46,0x67,0x90,0x24,0xC2,0x23,0x50,0x33,0x74,0x5A, + 0x71,0x7F,0x6D,0xC0,0xEE,0x15,0x58,0x64,0x57,0xEF,0xE9,0x02,0xAB,0xB6,0x93,0xA3, + 0x6B,0xFE,0xA9,0xD6,0x53,0x07,0x19,0x08,0xC5,0xC5,0x9D,0x8E,0x4D,0xE8,0x00,0xE8, + 0x49,0x2B,0x70,0x17,0x46,0xE8,0xAF,0xA1,0x2E,0x85,0x5F,0xA7,0x06,0x58,0xBF,0x64, + 0x0B,0xF5,0xD3,0xD4,0xF8,0x6B,0xAA,0x6C,0x8E,0x5F,0xE7,0x12,0x86,0x58,0x9A,0xFC, + 0xDB,0x44,0x9E,0x39,0xA9,0x78,0xE9,0x2D,0x5C,0xE2,0x8A,0x87,0x19,0xB6,0xB3,0xD5, + 0xB6,0x19,0xD0,0x97,0x1B,0xA3,0xE2,0xF6,0x04,0xCE,0xC6,0xEB,0xC3,0xC9,0x50,0x55, + 0x57,0xE5,0xE1,0x0B,0xCB,0x31,0x2A,0x4A,0x3E,0xC9,0xFC,0x87,0xC4,0x44,0x7D,0x5A, + 0x74,0x4D,0x51,0xAD,0xCA,0xD6,0x04,0x2C,0x3B,0x4B,0xE1,0x0F,0x31,0x71,0x00,0xEF, + 0x18,0x66,0x87,0x7E,0xAD,0x0A,0x68,0x23,0x81,0x8F,0x72,0xED,0x8E,0x5A,0xD1,0xD7, + 0x4E,0xBB,0x5E,0x38,0x20,0x48,0x77,0x69,0x19,0x55,0x33,0xC9,0x77,0x2A,0x8B,0xBF, + 0xEB,0xB7,0xF4,0xEB,0x2E,0x00,0x58,0x3C,0x86,0xDB,0x4D,0x95,0xB9,0x93,0x9C,0x78, + 0x39,0xDA,0x4C,0xAA,0xA3,0xB5,0xA6,0xA0,0xBA,0xBC,0x28,0xDB,0xE7,0x9F,0x2A,0x36, + 0x40,0x68,0xBC,0x22,0x3D,0xA9,0x4C,0xFC,0x62,0xCA,0x2C,0x61,0xE0,0x30,0xA4,0xAC, + 0x82,0x63,0xE2,0xE5,0xF0,0xEA,0x32,0x96,0x7B,0xB9,0xDC,0x3A,0x2D,0x1A,0x99,0x28, + 0x47,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01,0x95,0x30,0x82,0x01,0x91,0x30,0x3B, + 0x06,0x03,0x55,0x1D,0x11,0x04,0x34,0x30,0x32,0x82,0x17,0x73,0x65,0x63,0x75,0x72, + 0x65,0x32,0x2E,0x73,0x74,0x6F,0x72,0x65,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63, + 0x6F,0x6D,0x82,0x17,0x73,0x65,0x63,0x75,0x72,0x65,0x31,0x2E,0x73,0x74,0x6F,0x72, + 0x65,0x2E,0x61,0x70,0x70,0x6C,0x65,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,0x28,0x06,0x03,0x55,0x1D,0x25,0x04,0x21,0x30, + 0x1F,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x06,0x08,0x2B,0x06,0x01, + 0x05,0x05,0x07,0x03,0x02,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x04,0x01, + 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,0x4E,0x43,0xC8,0x1D,0x76,0xEF,0x37,0x53,0x7A,0x4F,0xF2, + 0x58,0x6F,0x94,0xF3,0x38,0xE2,0xD5,0xBD,0xDF,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,0x62,0x2E,0x73,0x79,0x6D,0x63,0x62,0x2E,0x63,0x6F,0x6D,0x2F, + 0x73,0x62,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,0x62,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,0x62,0x2E,0x73, + 0x79,0x6D,0x63,0x62,0x2E,0x63,0x6F,0x6D,0x2F,0x73,0x62,0x2E,0x63,0x72,0x74,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82, + 0x01,0x01,0x00,0xA4,0x6A,0x52,0x42,0x67,0x97,0x00,0x8D,0xBF,0xB1,0x3D,0x4C,0x80, + 0xFD,0x92,0xAB,0x34,0x95,0x89,0x3D,0x2D,0xEF,0x18,0xB9,0x1A,0x5F,0x86,0x52,0x59, + 0x09,0xCF,0x22,0xBF,0x4A,0xC1,0x27,0xEF,0x4C,0xB5,0xF2,0xD8,0xAD,0xB6,0xAA,0x97, + 0x0D,0xF1,0x43,0xED,0x15,0x08,0x68,0xBD,0x55,0xE3,0x71,0xA6,0x92,0x10,0x5F,0x20, + 0xC9,0x15,0xD1,0x0C,0xE4,0x24,0xE6,0x1C,0xC2,0xCF,0x19,0x5C,0x0B,0xDE,0x6B,0x34, + 0xA1,0xF1,0x18,0x0C,0x27,0x74,0xEA,0x2C,0xEA,0xB0,0x04,0x1C,0x20,0x87,0xD1,0x7A, + 0x8B,0x82,0xB7,0x31,0xD9,0x33,0xDE,0x7C,0x96,0xD1,0x6F,0x40,0x9F,0xDC,0x7C,0x9D, + 0x3D,0x09,0xCB,0x93,0xCC,0x6D,0xBE,0xE1,0x1C,0xD8,0x7D,0x66,0x70,0xAF,0x86,0x93, + 0x86,0xCA,0x77,0x83,0xB6,0xCA,0x86,0xDB,0x83,0xFC,0x6A,0x5C,0xCF,0x93,0x0C,0x1D, + 0x55,0x1C,0xD9,0xBB,0xFD,0x8E,0xE6,0x2E,0xC8,0x13,0x1C,0x27,0x3F,0x73,0x4F,0x19, + 0x49,0x40,0xB6,0x75,0x71,0x5B,0x02,0xCA,0x16,0x62,0x56,0x6A,0x6A,0xA8,0x37,0x97, + 0x67,0x9D,0xD5,0x24,0x34,0x77,0x46,0x3F,0xCA,0xBD,0x02,0x5C,0xDA,0xD8,0x0A,0x29, + 0x72,0xB1,0xBA,0x38,0x04,0xC3,0xA5,0xEF,0xAF,0x30,0x80,0x03,0x66,0xF9,0x96,0x44, + 0x3D,0x1C,0x8C,0x87,0x64,0x37,0xF3,0xAF,0x62,0xAD,0xF8,0xE5,0x53,0x9F,0x7A,0x70, + 0xDA,0x8C,0x00,0x9C,0x13,0xDF,0x7F,0xC4,0x0C,0xE9,0x72,0xA3,0x72,0x39,0x97,0xF5, + 0xE1,0x38,0x12,0xF3,0xAB,0x9D,0xC2,0xAB,0xE3,0xED,0xD8,0x43,0x9A,0xAC,0x1E,0x7A, + 0xB7,0x0A,0x3F, +}; + +static const uint8_t _c0_serial[] = { + 0x45, 0xA8, 0x3A, 0x4A, 0x79, 0x4D, 0x0C, 0x2d, + 0x71, 0x20, 0x12, 0x5A, 0x7C, 0x82, 0xC0, 0xAF +}; + +/* + Serial Number: + 2c:48:dd:93:0d:f5:59:8e:f9:3c:99:54:7a:60:ed:43 + Signature Algorithm: sha1WithRSAEncryption + Issuer: 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 + Validity + Not Before: Nov 8 00:00:00 2006 GMT + Not After : Nov 7 23:59:59 2016 GMT + Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=Terms of use at https://www.verisign.com/rpa (c)06, CN=VeriSign Class 3 Extended Validation SSL SGC CA + */ +static const uint8_t _c1[] = { + 0x30,0x82,0x06,0x1E,0x30,0x82,0x05,0x06,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x2C, + 0x48,0xDD,0x93,0x0D,0xF5,0x59,0x8E,0xF9,0x3C,0x99,0x54,0x7A,0x60,0xED,0x43,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,0x30, + 0x36,0x31,0x31,0x30,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x31,0x36, + 0x31,0x31,0x30,0x37,0x32,0x33,0x35,0x39,0x35,0x39,0x5A,0x30,0x81,0xBE,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,0x3B,0x30,0x39,0x06,0x03,0x55,0x04,0x0B,0x13,0x32, + 0x54,0x65,0x72,0x6D,0x73,0x20,0x6F,0x66,0x20,0x75,0x73,0x65,0x20,0x61,0x74,0x20, + 0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x76,0x65,0x72,0x69, + 0x73,0x69,0x67,0x6E,0x2E,0x63,0x6F,0x6D,0x2F,0x72,0x70,0x61,0x20,0x28,0x63,0x29, + 0x30,0x36,0x31,0x38,0x30,0x36,0x06,0x03,0x55,0x04,0x03,0x13,0x2F,0x56,0x65,0x72, + 0x69,0x53,0x69,0x67,0x6E,0x20,0x43,0x6C,0x61,0x73,0x73,0x20,0x33,0x20,0x45,0x78, + 0x74,0x65,0x6E,0x64,0x65,0x64,0x20,0x56,0x61,0x6C,0x69,0x64,0x61,0x74,0x69,0x6F, + 0x6E,0x20,0x53,0x53,0x4C,0x20,0x53,0x47,0x43,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,0xBD,0x56,0x88, + 0xBA,0x88,0x34,0x64,0x64,0xCF,0xCD,0xCA,0xB0,0xEE,0xE7,0x19,0x73,0xC5,0x72,0xD9, + 0xBB,0x45,0xBC,0xB5,0xA8,0xFF,0x83,0xBE,0x1C,0x03,0xDB,0xED,0x89,0xB7,0x2E,0x10, + 0x1A,0x25,0xBC,0x55,0xCA,0x41,0xA1,0x9F,0x0B,0xCF,0x19,0x5E,0x70,0xB9,0x5E,0x39, + 0x4B,0x9E,0x31,0x1C,0x5F,0x87,0xAE,0x2A,0xAA,0xA8,0x2B,0xA2,0x1B,0x3B,0x10,0x23, + 0x5F,0x13,0xB1,0xDD,0x08,0x8C,0x4E,0x14,0xDA,0x83,0x81,0xE3,0xB5,0x8C,0xE3,0x68, + 0xED,0x24,0x67,0xCE,0x56,0xB6,0xAC,0x9B,0x73,0x96,0x44,0xDB,0x8A,0x8C,0xB3,0xD6, + 0xF0,0x71,0x93,0x8E,0xDB,0x71,0x54,0x4A,0xEB,0x73,0x59,0x6A,0x8F,0x70,0x51,0x2C, + 0x03,0x9F,0x97,0xD1,0xCC,0x11,0x7A,0xBC,0x62,0x0D,0x95,0x2A,0xC9,0x1C,0x75,0x57, + 0xE9,0xF5,0xC7,0xEA,0xBA,0x84,0x35,0xCB,0xC7,0x85,0x5A,0x7E,0xE4,0x4D,0xE1,0x11, + 0x97,0x7D,0x0E,0x20,0x34,0x45,0xDB,0xF1,0xA2,0x09,0xEB,0xEB,0x3D,0x9E,0xB8,0x96, + 0x43,0x5E,0x34,0x4B,0x08,0x25,0x1E,0x43,0x1A,0xA2,0xD9,0xB7,0x8A,0x01,0x34,0x3D, + 0xC3,0xF8,0xE5,0xAF,0x4F,0x8C,0xFF,0xCD,0x65,0xF0,0x23,0x4E,0xC5,0x97,0xB3,0x5C, + 0xDA,0x90,0x1C,0x82,0x85,0x0D,0x06,0x0D,0xC1,0x22,0xB6,0x7B,0x28,0xA4,0x03,0xC3, + 0x4C,0x53,0xD1,0x58,0xBC,0x72,0xBC,0x08,0x39,0xFC,0xA0,0x76,0xA8,0xA8,0xE9,0x4B, + 0x6E,0x88,0x3D,0xE3,0xB3,0x31,0x25,0x8C,0x73,0x29,0x48,0x0E,0x32,0x79,0x06,0xED, + 0x3D,0x43,0xF4,0xF6,0xE4,0xE9,0xFC,0x7D,0xBE,0x8E,0x08,0xD5,0x1F,0x02,0x03,0x01, + 0x00,0x01,0xA3,0x82,0x02,0x08,0x30,0x82,0x02,0x04,0x30,0x1D,0x06,0x03,0x55,0x1D, + 0x0E,0x04,0x16,0x04,0x14,0x4E,0x43,0xC8,0x1D,0x76,0xEF,0x37,0x53,0x7A,0x4F,0xF2, + 0x58,0x6F,0x94,0xF3,0x38,0xE2,0xD5,0xBD,0xDF,0x30,0x12,0x06,0x03,0x55,0x1D,0x13, + 0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x3D,0x06, + 0x03,0x55,0x1D,0x20,0x04,0x36,0x30,0x34,0x30,0x32,0x06,0x04,0x55,0x1D,0x20,0x00, + 0x30,0x2A,0x30,0x28,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1C, + 0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x76,0x65,0x72,0x69, + 0x73,0x69,0x67,0x6E,0x2E,0x63,0x6F,0x6D,0x2F,0x63,0x70,0x73,0x30,0x3D,0x06,0x03, + 0x55,0x1D,0x1F,0x04,0x36,0x30,0x34,0x30,0x32,0xA0,0x30,0xA0,0x2E,0x86,0x2C,0x68, + 0x74,0x74,0x70,0x3A,0x2F,0x2F,0x45,0x56,0x53,0x65,0x63,0x75,0x72,0x65,0x2D,0x63, + 0x72,0x6C,0x2E,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6E,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,0x11,0x06,0x09,0x60, + 0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x6D, + 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x0C,0x04,0x61,0x30,0x5F,0xA1,0x5D, + 0xA0,0x5B,0x30,0x59,0x30,0x57,0x30,0x55,0x16,0x09,0x69,0x6D,0x61,0x67,0x65,0x2F, + 0x67,0x69,0x66,0x30,0x21,0x30,0x1F,0x30,0x07,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A, + 0x04,0x14,0x8F,0xE5,0xD3,0x1A,0x86,0xAC,0x8D,0x8E,0x6B,0xC3,0xCF,0x80,0x6A,0xD4, + 0x48,0x18,0x2C,0x7B,0x19,0x2E,0x30,0x25,0x16,0x23,0x68,0x74,0x74,0x70,0x3A,0x2F, + 0x2F,0x6C,0x6F,0x67,0x6F,0x2E,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6E,0x2E,0x63, + 0x6F,0x6D,0x2F,0x76,0x73,0x6C,0x6F,0x67,0x6F,0x2E,0x67,0x69,0x66,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,0x43,0x6C,0x61,0x73,0x73,0x33,0x43,0x41,0x32, + 0x30,0x34,0x38,0x2D,0x31,0x2D,0x34,0x38,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,0x3D,0x06,0x08,0x2B,0x06,0x01, + 0x05,0x05,0x07,0x01,0x01,0x04,0x31,0x30,0x2F,0x30,0x2D,0x06,0x08,0x2B,0x06,0x01, + 0x05,0x05,0x07,0x30,0x01,0x86,0x21,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x45,0x56, + 0x53,0x65,0x63,0x75,0x72,0x65,0x2D,0x6F,0x63,0x73,0x70,0x2E,0x76,0x65,0x72,0x69, + 0x73,0x69,0x67,0x6E,0x2E,0x63,0x6F,0x6D,0x30,0x34,0x06,0x03,0x55,0x1D,0x25,0x04, + 0x2D,0x30,0x2B,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x04,0x01,0x06,0x0A, + 0x60,0x86,0x48,0x01,0x86,0xF8,0x45,0x01,0x08,0x01,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x03,0x01,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x0D, + 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01, + 0x01,0x00,0x27,0x74,0xA6,0x34,0xEA,0x1D,0x9D,0xE1,0x53,0xD6,0x1C,0x9D,0x0C,0xA7, + 0x5B,0x4C,0xA9,0x67,0xF2,0xF0,0x32,0xB7,0x01,0x0F,0xFB,0x42,0x18,0x38,0xDE,0xE4, + 0xEE,0x49,0xC8,0x13,0xC9,0x0B,0xEC,0x04,0xC3,0x40,0x71,0x18,0x72,0x76,0x43,0x02, + 0x23,0x5D,0xAB,0x7B,0xC8,0x48,0x14,0x1A,0xC8,0x7B,0x1D,0xFC,0xF6,0x0A,0x9F,0x36, + 0xA1,0xD2,0x09,0x73,0x71,0x66,0x96,0x75,0x51,0x34,0xBF,0x99,0x30,0x51,0x67,0x9D, + 0x54,0xB7,0x26,0x45,0xAC,0x73,0x08,0x23,0x86,0x26,0x99,0x71,0xF4,0x8E,0xD7,0xEA, + 0x39,0x9B,0x06,0x09,0x23,0xBF,0x62,0xDD,0xA8,0xC4,0xB6,0x7D,0xA4,0x89,0x07,0x3E, + 0xF3,0x6D,0xAE,0x40,0x59,0x50,0x79,0x97,0x37,0x3D,0x32,0x78,0x7D,0xB2,0x63,0x4B, + 0xF9,0xEA,0x08,0x69,0x0E,0x13,0xED,0xE8,0xCF,0xBB,0xAC,0x05,0x86,0xCA,0x22,0xCF, + 0x88,0x62,0x5D,0x3C,0x22,0x49,0xD8,0x63,0xD5,0x24,0xA6,0xBD,0xEF,0x5C,0xE3,0xCC, + 0x20,0x3B,0x22,0xEA,0xFC,0x44,0xC6,0xA8,0xE5,0x1F,0xE1,0x86,0xCD,0x0C,0x4D,0x8F, + 0x93,0x53,0xD9,0x7F,0xEE,0xA1,0x08,0xA7,0xB3,0x30,0x96,0x49,0x70,0x6E,0xA3,0x6C, + 0x3D,0xD0,0x63,0xEF,0x25,0x66,0x63,0xCC,0xAA,0xB7,0x18,0x17,0x4E,0xEA,0x70,0x76, + 0xF6,0xBA,0x42,0xA6,0x80,0x37,0x09,0x4E,0x9F,0x66,0x88,0x2E,0x6B,0x33,0x66,0xC8, + 0xC0,0x71,0xA4,0x41,0xEB,0x5A,0xE3,0xFC,0x14,0x2E,0x4B,0x88,0xFD,0xAE,0x6E,0x5B, + 0x65,0xE9,0x27,0xE4,0xBF,0xE4,0xB0,0x23,0xC1,0xB2,0x7D,0x5B,0x62,0x25,0xD7,0x3E, + 0x10,0xD4, +}; + + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc/OU=Internet Operations/CN=xedge2.apple.com + issuer :/C=US/O=Entrust.net/OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Secure Server Certification Authority */ +const uint8_t xedge2_certificate[1385]={ +0x30,0x82,0x05,0x65,0x30,0x82,0x04,0xCE,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x46, +0x9C,0xDF,0x96,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05, +0x05,0x00,0x30,0x81,0xC3,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, +0x55,0x53,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x13,0x0B,0x45,0x6E,0x74, +0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x31,0x3B,0x30,0x39,0x06,0x03,0x55,0x04, +0x0B,0x13,0x32,0x77,0x77,0x77,0x2E,0x65,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E, +0x65,0x74,0x2F,0x43,0x50,0x53,0x20,0x69,0x6E,0x63,0x6F,0x72,0x70,0x2E,0x20,0x62, +0x79,0x20,0x72,0x65,0x66,0x2E,0x20,0x28,0x6C,0x69,0x6D,0x69,0x74,0x73,0x20,0x6C, +0x69,0x61,0x62,0x2E,0x29,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x0B,0x13,0x1C, +0x28,0x63,0x29,0x20,0x31,0x39,0x39,0x39,0x20,0x45,0x6E,0x74,0x72,0x75,0x73,0x74, +0x2E,0x6E,0x65,0x74,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65,0x64,0x31,0x3A,0x30,0x38, +0x06,0x03,0x55,0x04,0x03,0x13,0x31,0x45,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E, +0x65,0x74,0x20,0x53,0x65,0x63,0x75,0x72,0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72, +0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, +0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x1E,0x17,0x0D,0x30,0x38,0x30,0x31, +0x32,0x39,0x31,0x38,0x33,0x33,0x31,0x33,0x5A,0x17,0x0D,0x31,0x30,0x30,0x31,0x32, +0x38,0x31,0x39,0x30,0x33,0x31,0x32,0x5A,0x30,0x81,0x83,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,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x0A,0x13,0x09,0x41,0x70,0x70,0x6C, +0x65,0x20,0x49,0x6E,0x63,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04,0x0B,0x13,0x13, +0x49,0x6E,0x74,0x65,0x72,0x6E,0x65,0x74,0x20,0x4F,0x70,0x65,0x72,0x61,0x74,0x69, +0x6F,0x6E,0x73,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x03,0x13,0x10,0x78,0x65, +0x64,0x67,0x65,0x32,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,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,0xC7,0xF3,0xA1,0x0E,0x0E, +0xA4,0xDF,0xC5,0x3F,0x24,0x87,0xC3,0x6E,0xE7,0xD0,0x7C,0x2B,0x5A,0x1C,0xF3,0x67, +0x6C,0x6B,0x56,0x0A,0x95,0xC9,0xE5,0x13,0x28,0x6E,0x16,0x9D,0x4F,0xB1,0x76,0xFB, +0x7D,0x42,0x5B,0x2A,0x7C,0xCC,0x97,0x75,0xAA,0xA6,0xA9,0xDE,0xB2,0xEC,0xEF,0xE2, +0xAB,0x40,0xAE,0x9A,0x23,0xF0,0x6A,0x10,0xB3,0x75,0x27,0xF0,0xF4,0x7D,0x08,0x67, +0x8F,0xCE,0x41,0x24,0x74,0xAA,0x37,0xB6,0xC1,0x32,0x61,0xCF,0x7D,0x1C,0x21,0xCD, +0xCF,0x7C,0x9E,0xE2,0x48,0x03,0x7E,0x78,0xB3,0x86,0x3D,0x06,0x6B,0x39,0xEC,0xC8, +0x73,0x68,0xDB,0xE7,0x5B,0x97,0xF4,0xF9,0xA3,0xE7,0xFB,0x81,0x2E,0x4D,0x0B,0x3F, +0xA9,0xCA,0xDE,0x32,0x26,0xF3,0xF0,0x97,0x72,0x65,0xAB,0x02,0x03,0x01,0x00,0x01, +0xA3,0x82,0x02,0xA2,0x30,0x82,0x02,0x9E,0x30,0x0B,0x06,0x03,0x55,0x1D,0x0F,0x04, +0x04,0x03,0x02,0x05,0xA0,0x30,0x2B,0x06,0x03,0x55,0x1D,0x10,0x04,0x24,0x30,0x22, +0x80,0x0F,0x32,0x30,0x30,0x38,0x30,0x31,0x32,0x39,0x31,0x38,0x33,0x33,0x31,0x33, +0x5A,0x81,0x0F,0x32,0x30,0x31,0x30,0x30,0x31,0x32,0x38,0x31,0x39,0x30,0x33,0x31, +0x32,0x5A,0x30,0x11,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x01,0x04, +0x04,0x03,0x02,0x06,0x40,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A, +0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x82,0x01,0x68,0x06,0x03, +0x55,0x1D,0x20,0x04,0x82,0x01,0x5F,0x30,0x82,0x01,0x5B,0x30,0x82,0x01,0x57,0x06, +0x09,0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x4B,0x02,0x30,0x82,0x01,0x48,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,0x65,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E, +0x65,0x74,0x2F,0x63,0x70,0x73,0x30,0x82,0x01,0x1C,0x06,0x08,0x2B,0x06,0x01,0x05, +0x05,0x07,0x02,0x02,0x30,0x82,0x01,0x0E,0x1A,0x82,0x01,0x0A,0x54,0x68,0x65,0x20, +0x45,0x6E,0x74,0x72,0x75,0x73,0x74,0x20,0x53,0x53,0x4C,0x20,0x57,0x65,0x62,0x20, +0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61, +0x74,0x69,0x6F,0x6E,0x20,0x50,0x72,0x61,0x63,0x74,0x69,0x63,0x65,0x20,0x53,0x74, +0x61,0x74,0x65,0x6D,0x65,0x6E,0x74,0x20,0x28,0x43,0x50,0x53,0x29,0x20,0x61,0x76, +0x61,0x69,0x6C,0x61,0x62,0x6C,0x65,0x20,0x61,0x74,0x20,0x77,0x77,0x77,0x2E,0x65, +0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x2F,0x63,0x70,0x73,0x20,0x20, +0x69,0x73,0x20,0x68,0x65,0x72,0x65,0x62,0x79,0x20,0x69,0x6E,0x63,0x6F,0x72,0x70, +0x6F,0x72,0x61,0x74,0x65,0x64,0x20,0x69,0x6E,0x74,0x6F,0x20,0x79,0x6F,0x75,0x72, +0x20,0x75,0x73,0x65,0x20,0x6F,0x72,0x20,0x72,0x65,0x6C,0x69,0x61,0x6E,0x63,0x65, +0x20,0x6F,0x6E,0x20,0x74,0x68,0x69,0x73,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69, +0x63,0x61,0x74,0x65,0x2E,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x43,0x50,0x53,0x20, +0x63,0x6F,0x6E,0x74,0x61,0x69,0x6E,0x73,0x20,0x6C,0x69,0x6D,0x69,0x74,0x61,0x74, +0x69,0x6F,0x6E,0x73,0x20,0x6F,0x6E,0x20,0x77,0x61,0x72,0x72,0x61,0x6E,0x74,0x69, +0x65,0x73,0x20,0x61,0x6E,0x64,0x20,0x6C,0x69,0x61,0x62,0x69,0x6C,0x69,0x74,0x69, +0x65,0x73,0x2E,0x20,0x43,0x6F,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x28,0x63, +0x29,0x20,0x32,0x30,0x30,0x32,0x20,0x45,0x6E,0x74,0x72,0x75,0x73,0x74,0x20,0x4C, +0x69,0x6D,0x69,0x74,0x65,0x64,0x30,0x33,0x06,0x03,0x55,0x1D,0x1F,0x04,0x2C,0x30, +0x2A,0x30,0x28,0xA0,0x26,0xA0,0x24,0x86,0x22,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, +0x63,0x72,0x6C,0x2E,0x65,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x2F, +0x73,0x65,0x72,0x76,0x65,0x72,0x31,0x2E,0x63,0x72,0x6C,0x30,0x33,0x06,0x08,0x2B, +0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x27,0x30,0x25,0x30,0x23,0x06,0x08,0x2B, +0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x17,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, +0x6F,0x63,0x73,0x70,0x2E,0x65,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74, +0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xF0,0x17,0x62, +0x13,0x55,0x3D,0xB3,0xFF,0x0A,0x00,0x6B,0xFB,0x50,0x84,0x97,0xF3,0xED,0x62,0xD0, +0x1A,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x2D,0xEF,0xD9,0xAF, +0x1A,0x89,0x40,0x53,0x75,0x48,0x26,0x59,0x2F,0xEC,0x11,0x18,0xC0,0xD1,0x7A,0x34, +0x30,0x09,0x06,0x03,0x55,0x1D,0x13,0x04,0x02,0x30,0x00,0x30,0x19,0x06,0x09,0x2A, +0x86,0x48,0x86,0xF6,0x7D,0x07,0x41,0x00,0x04,0x0C,0x30,0x0A,0x1B,0x04,0x56,0x37, +0x2E,0x31,0x03,0x02,0x03,0x28,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, +0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0x77,0x33,0x2A,0x69,0x45,0x5A,0xB2, +0xF5,0x74,0xF7,0xDF,0xC7,0x08,0x85,0x86,0x88,0x98,0x41,0x7F,0x57,0x49,0x01,0xBA, +0x13,0x21,0x40,0xD0,0x0A,0x5C,0xA7,0x37,0xDF,0xB3,0x7E,0xF8,0xED,0x04,0x63,0xC3, +0xE8,0x0F,0xA0,0xE5,0xC4,0x4F,0x3A,0x90,0xE4,0x87,0x5F,0xEC,0xDB,0x65,0x8B,0x6E, +0x88,0x6E,0x6E,0xE4,0xBC,0x6A,0x7E,0x37,0x47,0x04,0xFF,0x09,0xC6,0x70,0xE1,0x65, +0x8F,0xE3,0xE9,0x60,0xEB,0xE8,0x8E,0x29,0xAE,0xF9,0x81,0xCA,0x9A,0x97,0x3C,0x6F, +0x7C,0xFA,0xA8,0x49,0xB4,0x33,0x76,0x9C,0x65,0x92,0x12,0xF6,0x7F,0x6A,0x62,0x84, +0x29,0x5F,0x14,0x26,0x6E,0x07,0x6F,0x5C,0xB5,0x7C,0x21,0x64,0x7C,0xD9,0x93,0xF4, +0x9C,0xC8,0xE7,0xEC,0xC6,0xAC,0x13,0xC4,0xF0 +}; + +const uint8_t entrust1024RootCA[1244]={ + 0x30,0x82,0x04,0xD8,0x30,0x82,0x04,0x41,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x37, + 0x4A,0xD2,0x43,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05, + 0x05,0x00,0x30,0x81,0xC3,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x13,0x0B,0x45,0x6E,0x74, + 0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x31,0x3B,0x30,0x39,0x06,0x03,0x55,0x04, + 0x0B,0x13,0x32,0x77,0x77,0x77,0x2E,0x65,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E, + 0x65,0x74,0x2F,0x43,0x50,0x53,0x20,0x69,0x6E,0x63,0x6F,0x72,0x70,0x2E,0x20,0x62, + 0x79,0x20,0x72,0x65,0x66,0x2E,0x20,0x28,0x6C,0x69,0x6D,0x69,0x74,0x73,0x20,0x6C, + 0x69,0x61,0x62,0x2E,0x29,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x0B,0x13,0x1C, + 0x28,0x63,0x29,0x20,0x31,0x39,0x39,0x39,0x20,0x45,0x6E,0x74,0x72,0x75,0x73,0x74, + 0x2E,0x6E,0x65,0x74,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65,0x64,0x31,0x3A,0x30,0x38, + 0x06,0x03,0x55,0x04,0x03,0x13,0x31,0x45,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E, + 0x65,0x74,0x20,0x53,0x65,0x63,0x75,0x72,0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72, + 0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, + 0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x1E,0x17,0x0D,0x39,0x39,0x30,0x35, + 0x32,0x35,0x31,0x36,0x30,0x39,0x34,0x30,0x5A,0x17,0x0D,0x31,0x39,0x30,0x35,0x32, + 0x35,0x31,0x36,0x33,0x39,0x34,0x30,0x5A,0x30,0x81,0xC3,0x31,0x0B,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04, + 0x0A,0x13,0x0B,0x45,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x31,0x3B, + 0x30,0x39,0x06,0x03,0x55,0x04,0x0B,0x13,0x32,0x77,0x77,0x77,0x2E,0x65,0x6E,0x74, + 0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x2F,0x43,0x50,0x53,0x20,0x69,0x6E,0x63, + 0x6F,0x72,0x70,0x2E,0x20,0x62,0x79,0x20,0x72,0x65,0x66,0x2E,0x20,0x28,0x6C,0x69, + 0x6D,0x69,0x74,0x73,0x20,0x6C,0x69,0x61,0x62,0x2E,0x29,0x31,0x25,0x30,0x23,0x06, + 0x03,0x55,0x04,0x0B,0x13,0x1C,0x28,0x63,0x29,0x20,0x31,0x39,0x39,0x39,0x20,0x45, + 0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x20,0x4C,0x69,0x6D,0x69,0x74, + 0x65,0x64,0x31,0x3A,0x30,0x38,0x06,0x03,0x55,0x04,0x03,0x13,0x31,0x45,0x6E,0x74, + 0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x20,0x53,0x65,0x63,0x75,0x72,0x65,0x20, + 0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61, + 0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x81, + 0x9D,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00, + 0x03,0x81,0x8B,0x00,0x30,0x81,0x87,0x02,0x81,0x81,0x00,0xCD,0x28,0x83,0x34,0x54, + 0x1B,0x89,0xF3,0x0F,0xAF,0x37,0x91,0x31,0xFF,0xAF,0x31,0x60,0xC9,0xA8,0xE8,0xB2, + 0x10,0x68,0xED,0x9F,0xE7,0x93,0x36,0xF1,0x0A,0x64,0xBB,0x47,0xF5,0x04,0x17,0x3F, + 0x23,0x47,0x4D,0xC5,0x27,0x19,0x81,0x26,0x0C,0x54,0x72,0x0D,0x88,0x2D,0xD9,0x1F, + 0x9A,0x12,0x9F,0xBC,0xB3,0x71,0xD3,0x80,0x19,0x3F,0x47,0x66,0x7B,0x8C,0x35,0x28, + 0xD2,0xB9,0x0A,0xDF,0x24,0xDA,0x9C,0xD6,0x50,0x79,0x81,0x7A,0x5A,0xD3,0x37,0xF7, + 0xC2,0x4A,0xD8,0x29,0x92,0x26,0x64,0xD1,0xE4,0x98,0x6C,0x3A,0x00,0x8A,0xF5,0x34, + 0x9B,0x65,0xF8,0xED,0xE3,0x10,0xFF,0xFD,0xB8,0x49,0x58,0xDC,0xA0,0xDE,0x82,0x39, + 0x6B,0x81,0xB1,0x16,0x19,0x61,0xB9,0x54,0xB6,0xE6,0x43,0x02,0x01,0x03,0xA3,0x82, + 0x01,0xD7,0x30,0x82,0x01,0xD3,0x30,0x11,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xF8, + 0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x00,0x07,0x30,0x82,0x01,0x19,0x06,0x03,0x55, + 0x1D,0x1F,0x04,0x82,0x01,0x10,0x30,0x82,0x01,0x0C,0x30,0x81,0xDE,0xA0,0x81,0xDB, + 0xA0,0x81,0xD8,0xA4,0x81,0xD5,0x30,0x81,0xD2,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x13, + 0x0B,0x45,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x31,0x3B,0x30,0x39, + 0x06,0x03,0x55,0x04,0x0B,0x13,0x32,0x77,0x77,0x77,0x2E,0x65,0x6E,0x74,0x72,0x75, + 0x73,0x74,0x2E,0x6E,0x65,0x74,0x2F,0x43,0x50,0x53,0x20,0x69,0x6E,0x63,0x6F,0x72, + 0x70,0x2E,0x20,0x62,0x79,0x20,0x72,0x65,0x66,0x2E,0x20,0x28,0x6C,0x69,0x6D,0x69, + 0x74,0x73,0x20,0x6C,0x69,0x61,0x62,0x2E,0x29,0x31,0x25,0x30,0x23,0x06,0x03,0x55, + 0x04,0x0B,0x13,0x1C,0x28,0x63,0x29,0x20,0x31,0x39,0x39,0x39,0x20,0x45,0x6E,0x74, + 0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65,0x64, + 0x31,0x3A,0x30,0x38,0x06,0x03,0x55,0x04,0x03,0x13,0x31,0x45,0x6E,0x74,0x72,0x75, + 0x73,0x74,0x2E,0x6E,0x65,0x74,0x20,0x53,0x65,0x63,0x75,0x72,0x65,0x20,0x53,0x65, + 0x72,0x76,0x65,0x72,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,0x0D,0x30,0x0B, + 0x06,0x03,0x55,0x04,0x03,0x13,0x04,0x43,0x52,0x4C,0x31,0x30,0x29,0xA0,0x27,0xA0, + 0x25,0x86,0x23,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x65,0x6E, + 0x74,0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x2F,0x43,0x52,0x4C,0x2F,0x6E,0x65, + 0x74,0x31,0x2E,0x63,0x72,0x6C,0x30,0x2B,0x06,0x03,0x55,0x1D,0x10,0x04,0x24,0x30, + 0x22,0x80,0x0F,0x31,0x39,0x39,0x39,0x30,0x35,0x32,0x35,0x31,0x36,0x30,0x39,0x34, + 0x30,0x5A,0x81,0x0F,0x32,0x30,0x31,0x39,0x30,0x35,0x32,0x35,0x31,0x36,0x30,0x39, + 0x34,0x30,0x5A,0x30,0x0B,0x06,0x03,0x55,0x1D,0x0F,0x04,0x04,0x03,0x02,0x01,0x06, + 0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xF0,0x17,0x62, + 0x13,0x55,0x3D,0xB3,0xFF,0x0A,0x00,0x6B,0xFB,0x50,0x84,0x97,0xF3,0xED,0x62,0xD0, + 0x1A,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xF0,0x17,0x62,0x13, + 0x55,0x3D,0xB3,0xFF,0x0A,0x00,0x6B,0xFB,0x50,0x84,0x97,0xF3,0xED,0x62,0xD0,0x1A, + 0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x19, + 0x06,0x09,0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x41,0x00,0x04,0x0C,0x30,0x0A,0x1B, + 0x04,0x56,0x34,0x2E,0x30,0x03,0x02,0x04,0x90,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0x90,0xDC,0x30,0x02, + 0xFA,0x64,0x74,0xC2,0xA7,0x0A,0xA5,0x7C,0x21,0x8D,0x34,0x17,0xA8,0xFB,0x47,0x0E, + 0xFF,0x25,0x7C,0x8D,0x13,0x0A,0xFB,0xE4,0x98,0xB5,0xEF,0x8C,0xF8,0xC5,0x10,0x0D, + 0xF7,0x92,0xBE,0xF1,0xC3,0xD5,0xD5,0x95,0x6A,0x04,0xBB,0x2C,0xCE,0x26,0x36,0x65, + 0xC8,0x31,0xC6,0xE7,0xEE,0x3F,0xE3,0x57,0x75,0x84,0x7A,0x11,0xEF,0x46,0x4F,0x18, + 0xF4,0xD3,0x98,0xBB,0xA8,0x87,0x32,0xBA,0x72,0xF6,0x3C,0xE2,0x3D,0x9F,0xD7,0x1D, + 0xD9,0xC3,0x60,0x43,0x8C,0x58,0x0E,0x22,0x96,0x2F,0x62,0xA3,0x2C,0x1F,0xBA,0xAD, + 0x05,0xEF,0xAB,0x32,0x78,0x87,0xA0,0x54,0x73,0x19,0xB5,0x5C,0x05,0xF9,0x52,0x3E, + 0x6D,0x2D,0x45,0x0B,0xF7,0x0A,0x93,0xEA,0xED,0x06,0xF9,0xB2, +}; + + +/* subject:/CN=garthc2.apple.com/O=Apple Inc./OU=DTS/ST=California/C=US/L=Cupertino/emailAddress=gcummings@apple.com + issuer :/CN=garthc2.apple.com/O=Apple Inc./OU=DTS/ST=California/C=US/L=Cupertino/emailAddress=gcummings@apple.com */ +const uint8_t garthc2_certificate[730]={ +0x30,0x82,0x02,0xD6,0x30,0x82,0x02,0x3F,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x01, +0x30,0x0B,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x30,0x81,0x99, +0x31,0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x03,0x0C,0x11,0x67,0x61,0x72,0x74,0x68, +0x63,0x32,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x31,0x13,0x30,0x11, +0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, +0x2E,0x31,0x0C,0x30,0x0A,0x06,0x03,0x55,0x04,0x0B,0x0C,0x03,0x44,0x54,0x53,0x31, +0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F, +0x72,0x6E,0x69,0x61,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, +0x53,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65, +0x72,0x74,0x69,0x6E,0x6F,0x31,0x22,0x30,0x20,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, +0x0D,0x01,0x09,0x01,0x16,0x13,0x67,0x63,0x75,0x6D,0x6D,0x69,0x6E,0x67,0x73,0x40, +0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x1E,0x17,0x0D,0x30,0x39,0x30, +0x37,0x31,0x36,0x32,0x32,0x34,0x39,0x31,0x30,0x5A,0x17,0x0D,0x31,0x30,0x30,0x37, +0x31,0x36,0x32,0x32,0x34,0x39,0x31,0x30,0x5A,0x30,0x81,0x99,0x31,0x1A,0x30,0x18, +0x06,0x03,0x55,0x04,0x03,0x0C,0x11,0x67,0x61,0x72,0x74,0x68,0x63,0x32,0x2E,0x61, +0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, +0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0C,0x30, +0x0A,0x06,0x03,0x55,0x04,0x0B,0x0C,0x03,0x44,0x54,0x53,0x31,0x13,0x30,0x11,0x06, +0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61, +0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x12,0x30, +0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E, +0x6F,0x31,0x22,0x30,0x20,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x01, +0x16,0x13,0x67,0x63,0x75,0x6D,0x6D,0x69,0x6E,0x67,0x73,0x40,0x61,0x70,0x70,0x6C, +0x65,0x2E,0x63,0x6F,0x6D,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,0xCF,0x30,0xD9,0x9D,0x9C,0xD5,0x6F,0xCB,0xB1,0xD1,0xC2,0x73,0xE2,0xB4, +0x06,0xC3,0x16,0x6D,0x0E,0x68,0x40,0x5E,0x92,0xFC,0xD9,0x14,0xD2,0x5E,0x21,0x50, +0x66,0x41,0x96,0x3A,0x76,0x26,0xF6,0x6C,0x3C,0xA2,0xD4,0x84,0x91,0x09,0x2E,0x23, +0x2D,0x07,0x38,0x48,0x58,0x31,0xE5,0x00,0x08,0xB1,0x6C,0x5D,0x39,0x50,0x30,0xF7, +0x68,0x12,0x99,0xB5,0x4C,0x86,0x1E,0xA5,0xF4,0x0C,0xCB,0xCB,0x25,0xB0,0x7C,0x6A, +0xFE,0x28,0xD4,0x34,0xA5,0xD2,0x94,0x5E,0xBE,0x5F,0xC1,0x61,0xAE,0xB5,0xD2,0xD2, +0x18,0x34,0x07,0x02,0xA8,0x56,0xAC,0x55,0x4D,0x87,0x56,0x8A,0xBA,0x1B,0x17,0x26, +0x11,0x9B,0xF8,0x88,0xD1,0x4F,0x94,0x03,0x01,0xCC,0x01,0xE7,0x0B,0x9B,0x14,0x43, +0x25,0xFB,0x02,0x03,0x01,0x00,0x01,0xA3,0x2E,0x30,0x2C,0x30,0x0B,0x06,0x03,0x55, +0x1D,0x0F,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,0x02,0x06,0x08,0x2B, +0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, +0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0x9D,0x8A,0x8A,0x9F,0xA5,0x36, +0xA2,0xE6,0x1D,0xA9,0xF1,0x10,0xDF,0xC8,0xFC,0x1A,0x2B,0xA0,0x01,0x07,0x58,0xA4, +0xD0,0x41,0xE1,0x32,0xD8,0xA9,0x84,0x9E,0xF3,0xE2,0xDE,0x48,0xD3,0x03,0xD7,0xC9, +0x40,0x58,0x5A,0x91,0x85,0x70,0xF6,0xC7,0x34,0x90,0x3C,0x1B,0x06,0x8F,0x0C,0xEE, +0xDD,0x79,0x14,0x42,0x72,0x4F,0x41,0xF9,0xB0,0xEC,0x04,0x9F,0xD6,0x75,0x68,0x06, +0xA0,0xEA,0x11,0x0C,0xE9,0x16,0x2F,0x9E,0x23,0xFA,0x5D,0xC2,0x02,0x92,0x2A,0xDD, +0xE8,0xBD,0xA1,0x8F,0x33,0x96,0x84,0xFA,0xFD,0x3C,0x70,0xD4,0x9D,0x43,0xA4,0xA0, +0xE9,0xF4,0x49,0xB2,0xF4,0xCB,0x9F,0x43,0x87,0x04,0x8D,0xD0,0xEA,0xAC,0x21,0x24, +0x2C,0x4C,0x36,0x5C,0x34,0x8C,0x61,0xA4,0xF4,0xB8, +}; + +const uint8_t prt_forest_fi_certificate[1797] = { + 0x30, 0x82, 0x07, 0x01, 0x30, 0x82, 0x05, 0xe9, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x11, 0x00, 0xfa, 0x69, 0x1a, 0xa7, 0xbf, 0x1b, 0x93, 0xbe, + 0x97, 0x11, 0xb0, 0xfe, 0xfc, 0xa8, 0x8d, 0x8c, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, + 0x39, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x46, 0x49, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, + 0x06, 0x53, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x31, 0x19, 0x30, 0x17, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x53, 0x6f, 0x6e, 0x65, 0x72, 0x61, + 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x32, 0x20, 0x43, 0x41, 0x30, 0x1e, + 0x17, 0x0d, 0x31, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x39, 0x33, 0x39, + 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x31, 0x31, 0x33, 0x30, 0x30, + 0x39, 0x33, 0x39, 0x33, 0x33, 0x5a, 0x30, 0x57, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x46, 0x49, 0x31, 0x16, 0x30, + 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0d, 0x50, 0x52, 0x54, 0x2d, + 0x46, 0x6f, 0x72, 0x65, 0x73, 0x74, 0x20, 0x4f, 0x79, 0x31, 0x16, 0x30, + 0x14, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x0d, 0x54, 0x69, 0x65, 0x74, + 0x6f, 0x68, 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x74, 0x6f, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x2a, 0x2e, 0x70, 0x72, + 0x74, 0x2d, 0x66, 0x6f, 0x72, 0x65, 0x73, 0x74, 0x2e, 0x66, 0x69, 0x30, + 0x82, 0x04, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x04, 0x0f, 0x00, 0x30, + 0x82, 0x04, 0x0a, 0x02, 0x82, 0x04, 0x01, 0x00, 0xbc, 0x62, 0x25, 0x57, + 0xbc, 0x71, 0xb8, 0xa9, 0x5b, 0x0e, 0x04, 0xbc, 0xc4, 0x0e, 0xf1, 0x0e, + 0x1f, 0x20, 0xd2, 0xf4, 0x4f, 0x23, 0xfe, 0x14, 0x54, 0x34, 0x81, 0xd3, + 0x5b, 0xdd, 0x74, 0xed, 0xa1, 0xbe, 0x91, 0x99, 0x9d, 0x02, 0xb9, 0x36, + 0x70, 0x43, 0x5d, 0x73, 0xa6, 0xe5, 0x70, 0x7b, 0x0e, 0x0c, 0x3f, 0x33, + 0xbb, 0x71, 0xd6, 0xd4, 0x22, 0xb0, 0xeb, 0xf5, 0x6e, 0x07, 0x7c, 0xe7, + 0xc7, 0xd1, 0x20, 0x64, 0x72, 0x4e, 0xae, 0x5e, 0xae, 0xaf, 0x08, 0xfb, + 0x7d, 0x6d, 0xdb, 0x69, 0x5a, 0x31, 0x73, 0x7d, 0xbd, 0x53, 0xcb, 0x04, + 0x69, 0x6d, 0x74, 0x56, 0x6c, 0xbc, 0x84, 0xa6, 0x01, 0x39, 0x37, 0x0c, + 0xb9, 0x5c, 0x2e, 0x78, 0x50, 0x3a, 0x8d, 0x1f, 0xa2, 0x33, 0xf1, 0xd2, + 0xc2, 0x87, 0x51, 0xf4, 0x92, 0xc3, 0xa7, 0xaa, 0xc8, 0x36, 0x51, 0x1c, + 0xfb, 0x77, 0xbf, 0xcf, 0x24, 0x11, 0xfe, 0xf4, 0x11, 0x2f, 0x5c, 0xdf, + 0x26, 0xf6, 0xb9, 0x15, 0xc1, 0x46, 0x75, 0x83, 0x40, 0x77, 0xa4, 0x83, + 0x74, 0xce, 0xc0, 0x29, 0x31, 0xd3, 0xd8, 0x68, 0xfa, 0x2e, 0xcc, 0x15, + 0x2c, 0x59, 0x5c, 0xa7, 0x96, 0x65, 0x8f, 0x34, 0x87, 0x29, 0x22, 0x1d, + 0xde, 0x65, 0xc7, 0x1c, 0x5c, 0xd8, 0x33, 0x22, 0xf7, 0x93, 0xd9, 0xcd, + 0x96, 0x76, 0x22, 0xab, 0x75, 0x18, 0x04, 0xe7, 0x65, 0x2a, 0xeb, 0x42, + 0x75, 0x17, 0x13, 0x12, 0x00, 0xe3, 0xf4, 0xd9, 0xde, 0xd1, 0x9f, 0x1c, + 0x61, 0xee, 0xf6, 0xb9, 0xf9, 0x50, 0xb3, 0x1b, 0x79, 0x77, 0x38, 0x3c, + 0x6a, 0xcc, 0xa0, 0x1d, 0xe4, 0xd7, 0x43, 0xca, 0x8b, 0x22, 0xbf, 0x77, + 0x33, 0xea, 0xaa, 0x01, 0xcf, 0x1e, 0xd0, 0x0d, 0x04, 0x2b, 0xec, 0x42, + 0x7b, 0xec, 0x53, 0xed, 0xc7, 0x4f, 0x0c, 0xac, 0x29, 0xb7, 0x8b, 0x92, + 0x14, 0x3f, 0x9b, 0xc6, 0xd8, 0xa1, 0x30, 0x4d, 0x5a, 0x07, 0x0e, 0x1e, + 0x80, 0x5f, 0x38, 0x66, 0x4d, 0xc1, 0xad, 0x2f, 0xee, 0xae, 0x94, 0x50, + 0x8e, 0x38, 0x2a, 0x00, 0x80, 0xe2, 0xc4, 0x43, 0x2e, 0xd5, 0xcd, 0xca, + 0x3f, 0x3d, 0xcb, 0x35, 0x13, 0x96, 0xd2, 0xdc, 0x0e, 0xe7, 0x45, 0x57, + 0x4b, 0x8f, 0xee, 0xa1, 0xce, 0xe6, 0x57, 0x52, 0xcd, 0xd0, 0x82, 0xca, + 0x3b, 0x87, 0xf4, 0x22, 0xff, 0x81, 0x4b, 0xf5, 0xa3, 0xda, 0xc5, 0xb6, + 0x67, 0xb8, 0xf4, 0xaf, 0xff, 0x8d, 0x4e, 0x80, 0xb5, 0x22, 0x80, 0x3c, + 0x70, 0xe4, 0xa0, 0xae, 0xdc, 0xcf, 0x44, 0xff, 0x00, 0x98, 0x3f, 0x19, + 0x7b, 0x4c, 0x3d, 0xd8, 0xa5, 0xd8, 0xe0, 0x05, 0x73, 0x54, 0x06, 0x0c, + 0x4d, 0x50, 0xf8, 0xd8, 0x85, 0x0b, 0xa8, 0x49, 0xaa, 0x97, 0x87, 0x3b, + 0x32, 0xe8, 0x58, 0x22, 0xee, 0x34, 0x1c, 0x9f, 0xe3, 0x18, 0xba, 0x93, + 0x43, 0xea, 0xb7, 0x78, 0x35, 0xa2, 0xb5, 0x1e, 0x19, 0x16, 0x3b, 0xb3, + 0xf5, 0x12, 0xe8, 0x26, 0x62, 0x2d, 0xd7, 0x45, 0xc3, 0xa4, 0x4b, 0xda, + 0x38, 0x48, 0x00, 0x3f, 0x68, 0x62, 0xa2, 0x83, 0x9d, 0x32, 0x76, 0x27, + 0x40, 0x5d, 0x0e, 0x75, 0xb1, 0x08, 0xdb, 0x58, 0xfa, 0x20, 0x62, 0xf1, + 0x3f, 0xbd, 0x86, 0x2f, 0x7c, 0x07, 0x01, 0x14, 0x1d, 0x19, 0x61, 0xee, + 0x0a, 0x85, 0xbf, 0xc7, 0x4f, 0x4a, 0x06, 0xc0, 0xaf, 0x44, 0x5d, 0x6f, + 0xc3, 0x53, 0x23, 0xcb, 0xdf, 0x40, 0x7a, 0x18, 0xa1, 0x34, 0x80, 0x18, + 0x86, 0xfe, 0xe3, 0x87, 0xce, 0x30, 0x53, 0x33, 0x1c, 0x45, 0x4a, 0xb4, + 0xe1, 0x8c, 0x9b, 0x4b, 0xf5, 0x2c, 0x7c, 0x13, 0x56, 0x37, 0x8a, 0x94, + 0x24, 0xdb, 0x3a, 0x4b, 0x80, 0xb1, 0x26, 0x57, 0x5a, 0x75, 0x1c, 0x44, + 0xc5, 0xf7, 0x67, 0xb4, 0x61, 0x87, 0xe8, 0x2e, 0xd9, 0xe1, 0xb9, 0x45, + 0xcc, 0xdc, 0xdf, 0x3b, 0x8c, 0xce, 0xd0, 0x46, 0x6b, 0x87, 0xb5, 0xa9, + 0xfe, 0x35, 0x87, 0xe0, 0xca, 0xc6, 0x7d, 0xc8, 0x86, 0xc2, 0xfe, 0x89, + 0xec, 0xa9, 0x86, 0x33, 0x81, 0xdc, 0x41, 0xb3, 0xe7, 0xc4, 0x82, 0x3a, + 0x81, 0x05, 0xbd, 0x8b, 0x92, 0xb2, 0x6a, 0x2c, 0x3c, 0xca, 0xd0, 0x22, + 0xff, 0xc8, 0x8f, 0xf0, 0x5f, 0x0e, 0xfb, 0x0b, 0x36, 0x64, 0x6a, 0x12, + 0x77, 0x2d, 0x8a, 0x38, 0xde, 0x7d, 0xed, 0xc9, 0xa7, 0xc1, 0x85, 0x41, + 0xa2, 0x7b, 0xa5, 0xdc, 0x30, 0x96, 0xda, 0xf8, 0xb3, 0xc8, 0x21, 0x56, + 0x3c, 0xdb, 0xe4, 0x8c, 0xb0, 0xfb, 0xec, 0x0e, 0x58, 0x49, 0x3c, 0x75, + 0x3c, 0xc2, 0x41, 0xbd, 0xc0, 0x81, 0x37, 0xc7, 0x69, 0x5a, 0x41, 0x86, + 0x18, 0xe9, 0x41, 0x7f, 0xba, 0xff, 0xc3, 0x52, 0x56, 0xf9, 0x7c, 0x60, + 0x14, 0xf9, 0x66, 0x4c, 0x60, 0xb6, 0x3e, 0x23, 0xcd, 0xd1, 0x2d, 0x4f, + 0x43, 0x97, 0xea, 0xa3, 0x37, 0xa4, 0x2a, 0xa7, 0x81, 0x49, 0x90, 0xe3, + 0xb6, 0x12, 0x1b, 0xac, 0x78, 0x57, 0x20, 0x51, 0xb4, 0x16, 0x5e, 0x58, + 0x61, 0x0f, 0x1e, 0x35, 0xbc, 0x3f, 0x44, 0xc2, 0x85, 0xa5, 0x61, 0x8a, + 0x0a, 0x7c, 0x2e, 0xb0, 0x11, 0x12, 0xc6, 0xc0, 0xc8, 0xcb, 0xd8, 0x13, + 0xc3, 0x58, 0xf1, 0xcd, 0x06, 0x5f, 0x90, 0xa5, 0xd7, 0x74, 0xbc, 0x1a, + 0x9c, 0xdc, 0xab, 0xde, 0xea, 0x36, 0x67, 0x41, 0x4f, 0x62, 0x86, 0xc6, + 0xfe, 0x63, 0x14, 0x83, 0x11, 0xab, 0xfb, 0x61, 0x38, 0x11, 0xce, 0x01, + 0xe8, 0xee, 0x3a, 0x21, 0xbc, 0xaa, 0x4b, 0xb0, 0x8f, 0x2f, 0xcf, 0x58, + 0xe6, 0x55, 0x61, 0x38, 0xa7, 0xc3, 0xaa, 0x3b, 0xb0, 0x8c, 0xf4, 0x82, + 0xa0, 0x96, 0xc4, 0x13, 0x4a, 0xc0, 0xc8, 0x93, 0xb7, 0x3d, 0x28, 0x05, + 0xb9, 0xc8, 0x4c, 0xe8, 0x57, 0xda, 0x56, 0x8b, 0xda, 0x27, 0xab, 0xbf, + 0x7e, 0x66, 0x43, 0xdc, 0x57, 0x09, 0xdc, 0x88, 0x8e, 0xfb, 0xa7, 0x63, + 0x41, 0xfb, 0xf1, 0x67, 0xb5, 0xe1, 0x84, 0x5d, 0x1d, 0xe3, 0xb4, 0xc6, + 0x40, 0x97, 0xf8, 0x4d, 0xfc, 0x00, 0xcd, 0x56, 0xc2, 0xab, 0xff, 0x49, + 0x93, 0xff, 0x46, 0x56, 0x9b, 0xee, 0x6d, 0xa0, 0x5d, 0xf4, 0x78, 0x36, + 0x0e, 0xf6, 0xc9, 0x9c, 0x79, 0x89, 0xf9, 0x9c, 0xa7, 0x3e, 0xa0, 0x8d, + 0x62, 0x7c, 0xdc, 0x83, 0x0a, 0xfc, 0x46, 0x96, 0x31, 0xd3, 0x56, 0xc6, + 0xea, 0x7f, 0x1d, 0xaa, 0x49, 0xd1, 0x8b, 0x54, 0xa2, 0x6e, 0x59, 0x8c, + 0x2a, 0xec, 0x3a, 0xd7, 0xda, 0xd2, 0xc1, 0xfc, 0x1d, 0x78, 0x55, 0xce, + 0xd8, 0x0c, 0x1d, 0x7e, 0x99, 0xf8, 0x5e, 0x3c, 0x2d, 0xec, 0x63, 0xe2, + 0xda, 0xa1, 0x68, 0x6f, 0x28, 0x2e, 0xb4, 0xef, 0x07, 0xc4, 0xa8, 0x65, + 0xc7, 0xfd, 0x6b, 0x0f, 0x83, 0x23, 0xf8, 0xc2, 0xc9, 0x55, 0xfa, 0xa4, + 0xa8, 0x6a, 0xab, 0x12, 0xf4, 0x89, 0x42, 0x26, 0x72, 0xd1, 0x82, 0x2f, + 0x62, 0x14, 0xb6, 0x04, 0x23, 0x20, 0xb6, 0xd4, 0xef, 0x59, 0x8a, 0x40, + 0x43, 0xd7, 0x72, 0xe0, 0x5b, 0x0c, 0xb0, 0x73, 0x6f, 0x6a, 0x87, 0xc1, + 0x82, 0x50, 0x20, 0xdb, 0xaa, 0xf8, 0x8d, 0x70, 0xb6, 0x39, 0x46, 0xe0, + 0x68, 0xc4, 0xab, 0xea, 0xd1, 0x31, 0xad, 0xf7, 0x05, 0xfb, 0x3a, 0x3c, + 0x2e, 0x66, 0x4f, 0xc6, 0x0d, 0xf9, 0xb8, 0x29, 0xec, 0xdc, 0xfc, 0x81, + 0x56, 0x2b, 0xb0, 0xad, 0xd2, 0x12, 0x8f, 0x69, 0x70, 0x18, 0x27, 0x16, + 0xf9, 0xf0, 0x40, 0x93, 0xef, 0x6b, 0x95, 0x96, 0xcd, 0x5f, 0xe9, 0x5a, + 0x7b, 0xad, 0x7f, 0x98, 0xa7, 0x6a, 0xe5, 0x17, 0xeb, 0xc3, 0xdd, 0xc9, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xe5, 0x30, 0x81, 0xe2, 0x30, + 0x13, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x0c, 0x30, 0x0a, 0x80, 0x08, + 0x4a, 0xa0, 0xaa, 0x58, 0x84, 0xd3, 0x5e, 0x3c, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x1d, 0x20, 0x04, 0x12, 0x30, 0x10, 0x30, 0x0e, 0x06, 0x0c, 0x2b, + 0x06, 0x01, 0x04, 0x01, 0x82, 0x0f, 0x02, 0x03, 0x01, 0x01, 0x02, 0x30, + 0x72, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x6b, 0x30, 0x69, 0x30, 0x67, + 0xa0, 0x65, 0xa0, 0x63, 0x86, 0x61, 0x6c, 0x64, 0x61, 0x70, 0x3a, 0x2f, + 0x2f, 0x31, 0x39, 0x34, 0x2e, 0x32, 0x35, 0x32, 0x2e, 0x31, 0x32, 0x34, + 0x2e, 0x32, 0x34, 0x31, 0x3a, 0x33, 0x38, 0x39, 0x2f, 0x63, 0x6e, 0x3d, + 0x53, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x25, 0x32, 0x30, 0x43, 0x6c, 0x61, + 0x73, 0x73, 0x32, 0x25, 0x32, 0x30, 0x43, 0x41, 0x2c, 0x6f, 0x3d, 0x53, + 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x2c, 0x63, 0x3d, 0x46, 0x49, 0x3f, 0x63, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x72, 0x65, + 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6c, 0x69, 0x73, 0x74, + 0x3b, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 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, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, + 0x14, 0x85, 0xc2, 0x31, 0x35, 0x4f, 0x93, 0x92, 0x9d, 0x8a, 0xbc, 0x32, + 0x7d, 0x1b, 0xf0, 0xaa, 0x96, 0xb1, 0x03, 0x86, 0x71, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x03, 0x82, 0x01, 0x01, 0x00, 0x00, 0x9e, 0x75, 0x2b, 0x95, 0x6a, 0x96, + 0x12, 0x24, 0xd5, 0x04, 0x6c, 0x34, 0x0a, 0x58, 0x5a, 0x7d, 0x59, 0xb9, + 0x03, 0x23, 0x13, 0xc3, 0xf5, 0x24, 0x57, 0x33, 0x8d, 0xca, 0x5f, 0xd8, + 0x26, 0xff, 0x64, 0x46, 0x13, 0x40, 0xe5, 0x04, 0xb2, 0xba, 0x92, 0xa5, + 0xa6, 0xa3, 0xd9, 0x2b, 0xff, 0x05, 0xef, 0xce, 0x3c, 0x28, 0xe8, 0x1b, + 0xa3, 0x10, 0x8a, 0xdd, 0x3d, 0x3a, 0x0a, 0xe1, 0x07, 0x3c, 0xb4, 0xf6, + 0xbb, 0xeb, 0xb5, 0xf2, 0x05, 0xe8, 0xd7, 0x16, 0x3e, 0xe5, 0x15, 0x49, + 0xdf, 0x8d, 0x34, 0xb8, 0x1b, 0xd4, 0xf2, 0x65, 0xa0, 0x70, 0x80, 0xd0, + 0xbf, 0xa5, 0x74, 0x5d, 0xfb, 0xd4, 0x52, 0x3b, 0x54, 0xca, 0x32, 0xba, + 0xf7, 0xe3, 0x90, 0xa5, 0xa8, 0xad, 0xd0, 0xe5, 0x5d, 0x18, 0x18, 0x87, + 0x60, 0xb0, 0xf3, 0xf9, 0x62, 0x20, 0x77, 0xaa, 0x0f, 0xdd, 0x16, 0x4c, + 0x01, 0x3a, 0xb1, 0x1f, 0x85, 0x7e, 0x01, 0x04, 0x5f, 0xf1, 0x37, 0x36, + 0xe3, 0x3a, 0xc1, 0xa3, 0x7c, 0x33, 0xca, 0xce, 0x0b, 0xb9, 0x34, 0xe2, + 0xe1, 0xe6, 0xed, 0x24, 0xc1, 0xc3, 0xc7, 0x74, 0x8f, 0x22, 0x2c, 0x6e, + 0xcb, 0x5c, 0x7a, 0x61, 0x99, 0xde, 0xea, 0x13, 0xe1, 0xa8, 0xa1, 0x94, + 0xd0, 0x85, 0x65, 0x65, 0xed, 0x97, 0x14, 0x6e, 0x97, 0xc9, 0xcf, 0x34, + 0x7c, 0xf2, 0x68, 0xeb, 0xc2, 0x7d, 0x03, 0x53, 0xf5, 0xdb, 0xa1, 0x11, + 0x8d, 0xda, 0xcc, 0x26, 0x13, 0xaa, 0x43, 0x76, 0x04, 0x9b, 0x85, 0x89, + 0xc3, 0x29, 0xd8, 0xb5, 0x54, 0x81, 0x09, 0xf5, 0x18, 0x52, 0xa5, 0x38, + 0x4a, 0x00, 0xc6, 0x1d, 0x4d, 0x5a, 0x15, 0xa0, 0xfd, 0xf7, 0x58, 0x27, + 0xcd, 0x6b, 0x56, 0x6b, 0xee, 0x7d, 0x73, 0xd3, 0xfd, 0x6c, 0xb6, 0xb1, + 0x3b, 0xbd, 0xbf, 0x5b, 0x4a, 0x6c, 0xd3, 0x1c, 0x47 +}; + +/* Test basic add delete update copy matching stuff. */ +static void tests(void) +{ + SecTrustRef trust; + SecCertificateRef cert0, cert1; + isnt(cert0 = SecCertificateCreateWithBytes(NULL, _c0, sizeof(_c0)), + NULL, "create cert0"); + isnt(cert1 = SecCertificateCreateWithBytes(NULL, _c1, sizeof(_c1)), + NULL, "create cert1"); + const void *v_certs[] = { + cert0, + cert1 + }; + SecPolicyRef policy = SecPolicyCreateSSL(false, NULL); + CFArrayRef certs = CFArrayCreate(NULL, v_certs, + array_size(v_certs), NULL); + + /* SecTrustCreateWithCertificates failures. */ + is_status(SecTrustCreateWithCertificates(kCFBooleanTrue, policy, &trust), + errSecParam, "create trust with boolean instead of cert"); + is_status(SecTrustCreateWithCertificates(cert0, kCFBooleanTrue, &trust), + errSecParam, "create trust with boolean instead of policy"); + + /* SecTrustCreateWithCertificates using array of certs. */ + ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust"); + + /* NOTE: prior to @@ -538,6 +538,13 @@ static void tests(void) NULL, "create leaf0"); isnt(leaf1 = SecCertificateCreateWithBytes(NULL, _leaf1, sizeof(_leaf1)), NULL, "create leaf1"); + { + // temporarily grab some stack space and fill it with 0xFF; + // when we exit this scope, the stack pointer should shrink but leave the memory filled. + // this tests for a stack overflow bug inside SecPolicyCreateiAP (rdar://16056248) + char buf[2048]; + memset(buf, 0xFF, sizeof(buf)); + } SecPolicyRef policy = SecPolicyCreateiAP(); const void *v_anchors[] = { iAP1CA, diff --git a/sec/Security/Regressions/secitem/si-23-sectrust-ocsp-wwdr.c b/Security/sec/Security/Regressions/secitem/si-23-sectrust-ocsp-wwdr.c similarity index 99% rename from sec/Security/Regressions/secitem/si-23-sectrust-ocsp-wwdr.c rename to Security/sec/Security/Regressions/secitem/si-23-sectrust-ocsp-wwdr.c index e8ac8870..0e75226d 100644 --- a/sec/Security/Regressions/secitem/si-23-sectrust-ocsp-wwdr.c +++ b/Security/sec/Security/Regressions/secitem/si-23-sectrust-ocsp-wwdr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ #include diff --git a/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.c b/Security/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.c similarity index 97% rename from sec/Security/Regressions/secitem/si-23-sectrust-ocsp.c rename to Security/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.c index 3fa8e421..d29dff66 100644 --- a/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.c +++ b/Security/sec/Security/Regressions/secitem/si-23-sectrust-ocsp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2009,2012-2014 Apple Inc. All Rights Reserved. */ #include @@ -9,7 +9,13 @@ #include #include #include +#include +#include +#include +#include +#include #include +#include #include "Security_regressions.h" @@ -766,8 +772,54 @@ static void test_aia(void) { CFReleaseSafe(jan1st2009); } +static int ping_host(char *host_name){ + + struct sockaddr_in pin; + struct hostent *nlp_host; + int sd; + int port; + + port=80; + + while ((nlp_host=gethostbyname(host_name))==0){ + printf("Resolve Error!\n"); + } + + bzero(&pin,sizeof(pin)); + pin.sin_family=AF_INET; + pin.sin_addr.s_addr=htonl(INADDR_ANY); + pin.sin_addr.s_addr=((struct in_addr *)(nlp_host->h_addr))->s_addr; + pin.sin_port=htons(port); + + sd=socket(AF_INET,SOCK_STREAM,0); + + if (connect(sd,(struct sockaddr*)&pin,sizeof(pin))==-1){ + close(sd); + return 0; + } + else{ + close(sd); + return 1; + } +} + + int si_23_sectrust_ocsp(int argc, char *const *argv) { + char *hosts[] = { + "EVSecure-ocsp.verisign.com", + "EVIntl-ocsp.verisign.com", + "EVIntl-aia.verisign.com", + "ocsp.comodoca.com", + "crt.comodoca.com" + }; + + int host_cnt = 0; + for (host_cnt = 0; host_cnt < 5; host_cnt ++) + if(!ping_host(hosts[host_cnt])){ + printf("Accessing specific server failed, checked the network!\n"); + return 0; + } plan_tests(39); tests(); diff --git a/sec/Security/Regressions/secitem/si-24-sectrust-appleid.c b/Security/sec/Security/Regressions/secitem/si-24-sectrust-appleid.c similarity index 88% rename from sec/Security/Regressions/secitem/si-24-sectrust-appleid.c rename to Security/sec/Security/Regressions/secitem/si-24-sectrust-appleid.c index 04632801..d956007b 100644 --- a/sec/Security/Regressions/secitem/si-24-sectrust-appleid.c +++ b/Security/sec/Security/Regressions/secitem/si-24-sectrust-appleid.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. */ #include diff --git a/sec/Security/Regressions/secitem/si-24-sectrust-digicert-malaysia.c b/Security/sec/Security/Regressions/secitem/si-24-sectrust-digicert-malaysia.c similarity index 89% rename from sec/Security/Regressions/secitem/si-24-sectrust-digicert-malaysia.c rename to Security/sec/Security/Regressions/secitem/si-24-sectrust-digicert-malaysia.c index 59dcd342..b11f28a7 100644 --- a/sec/Security/Regressions/secitem/si-24-sectrust-digicert-malaysia.c +++ b/Security/sec/Security/Regressions/secitem/si-24-sectrust-digicert-malaysia.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. */ #include diff --git a/sec/Security/Regressions/secitem/si-24-sectrust-diginotar.c b/Security/sec/Security/Regressions/secitem/si-24-sectrust-diginotar.c similarity index 91% rename from sec/Security/Regressions/secitem/si-24-sectrust-diginotar.c rename to Security/sec/Security/Regressions/secitem/si-24-sectrust-diginotar.c index 7b1ae2cb..95a6b35b 100644 --- a/sec/Security/Regressions/secitem/si-24-sectrust-diginotar.c +++ b/Security/sec/Security/Regressions/secitem/si-24-sectrust-diginotar.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. */ #include diff --git a/sec/Security/Regressions/secitem/si-24-sectrust-itms.c b/Security/sec/Security/Regressions/secitem/si-24-sectrust-itms.c similarity index 99% rename from sec/Security/Regressions/secitem/si-24-sectrust-itms.c rename to Security/sec/Security/Regressions/secitem/si-24-sectrust-itms.c index 4533ca7c..7f96dbfa 100644 --- a/sec/Security/Regressions/secitem/si-24-sectrust-itms.c +++ b/Security/sec/Security/Regressions/secitem/si-24-sectrust-itms.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2010,2012,2014 Apple Inc. All Rights Reserved. */ #include @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -139,11 +140,7 @@ static void tests(void) ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set iTMS anchor for evaluation"); /* it'll have just expired */ - CFTimeZoneRef tz = CFTimeZoneCreateWithName(NULL, CFSTR("GMT"), true); - CFGregorianDate date_check = { 2008, 11, 7, 22, 0, 0 }; - CFAbsoluteTime atime = CFGregorianDateGetAbsoluteTime(date_check, tz); - CFRelease(tz); - CFDateRef date = CFDateCreate(NULL, atime); + CFDateRef date = CFDateCreateForGregorianZuluMoment(NULL, 2008, 11, 7, 22, 0, 0); ok_status(SecTrustSetVerifyDate(trust, date), "set date"); CFReleaseSafe(date); diff --git a/sec/Security/Regressions/secitem/si-24-sectrust-mobileasset.c b/Security/sec/Security/Regressions/secitem/si-24-sectrust-mobileasset.c similarity index 88% rename from sec/Security/Regressions/secitem/si-24-sectrust-mobileasset.c rename to Security/sec/Security/Regressions/secitem/si-24-sectrust-mobileasset.c index d0dab9bf..819a797f 100644 --- a/sec/Security/Regressions/secitem/si-24-sectrust-mobileasset.c +++ b/Security/sec/Security/Regressions/secitem/si-24-sectrust-mobileasset.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. */ #include diff --git a/sec/Security/Regressions/secitem/si-24-sectrust-nist.c b/Security/sec/Security/Regressions/secitem/si-24-sectrust-nist.c similarity index 88% rename from sec/Security/Regressions/secitem/si-24-sectrust-nist.c rename to Security/sec/Security/Regressions/secitem/si-24-sectrust-nist.c index 55f38c43..aea1a460 100644 --- a/sec/Security/Regressions/secitem/si-24-sectrust-nist.c +++ b/Security/sec/Security/Regressions/secitem/si-24-sectrust-nist.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. */ #include diff --git a/sec/Security/Regressions/secitem/si-24-sectrust-otatasking.c b/Security/sec/Security/Regressions/secitem/si-24-sectrust-otatasking.c similarity index 88% rename from sec/Security/Regressions/secitem/si-24-sectrust-otatasking.c rename to Security/sec/Security/Regressions/secitem/si-24-sectrust-otatasking.c index 26247afb..f7d0ffcc 100644 --- a/sec/Security/Regressions/secitem/si-24-sectrust-otatasking.c +++ b/Security/sec/Security/Regressions/secitem/si-24-sectrust-otatasking.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. */ #include diff --git a/sec/Security/Regressions/secitem/si-24-sectrust-shoebox.c b/Security/sec/Security/Regressions/secitem/si-24-sectrust-shoebox.c similarity index 97% rename from sec/Security/Regressions/secitem/si-24-sectrust-shoebox.c rename to Security/sec/Security/Regressions/secitem/si-24-sectrust-shoebox.c index 5e887ee1..73a15b9d 100644 --- a/sec/Security/Regressions/secitem/si-24-sectrust-shoebox.c +++ b/Security/sec/Security/Regressions/secitem/si-24-sectrust-shoebox.c @@ -1,7 +1,27 @@ /* - * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include #include #include @@ -12,6 +32,7 @@ #include #include +#include #include #include "Security_regressions.h" @@ -851,7 +872,6 @@ static void test_sig_verification(void) static void tests(void) { /* Aug 1st 2012. */ - CFGregorianDate g_date = { 2012, 8, 1, 12, 0, 0 }; // Aug 1 2012 12:00 PM CFDateRef date; CFArrayRef policies; SecPolicyRef policy; @@ -879,8 +899,7 @@ static void tests(void) "create trust"); CFRelease(policies); policies = NULL; - isnt(date = CFDateCreate(kCFAllocatorDefault, - CFGregorianDateGetAbsoluteTime(g_date, NULL)), + isnt(date = CFDateCreateForGregorianZuluMoment(NULL, 2012, 8, 1, 12, 0, 0), NULL, "create verify date"); ok_status(SecTrustSetVerifyDate(trust, date), "set date"); CFReleaseSafe(date); @@ -901,9 +920,8 @@ static void tests(void) "create trust"); CFRelease(policies); policies = NULL; - isnt(date = CFDateCreate(kCFAllocatorDefault, - CFGregorianDateGetAbsoluteTime(g_date, NULL)), - NULL, "create verify date"); + isnt(date = CFDateCreateForGregorianZuluMoment(NULL, 2012, 8, 1, 12, 0, 0), + NULL, "create verify date"); ok_status(SecTrustSetVerifyDate(trust, date), "set date"); CFReleaseNull(date); date = NULL; @@ -923,9 +941,8 @@ static void tests(void) "create trust"); CFRelease(policies); policies = NULL; - isnt(date = CFDateCreate(kCFAllocatorDefault, - CFGregorianDateGetAbsoluteTime(g_date, NULL)), - NULL, "create verify date"); + isnt(date = CFDateCreateForGregorianZuluMoment(NULL, 2012, 8, 1, 12, 0, 0), + NULL, "create verify date"); ok_status(SecTrustSetVerifyDate(trust, date), "set date"); CFReleaseNull(date); date = NULL; @@ -937,27 +954,21 @@ static void tests(void) test_sig_verification(); - CFGregorianDate whenWritten = { - .year = 2012, - .month = 5, - .day = 10, - .hour = 0, - .minute = 0, - .second = 0, - }; + CFDateRef whenWritten = CFDateCreateForGregorianZuluDay(NULL, 2012, 5, 10); SecPolicyRef shoeboxPolicy = SecPolicyCreatePassbookCardSigner(CFSTR("com.apple.testcard"), CFSTR("A1B2C3D4E5")); /* Run the tests. */ - runCertificateTestForDirectory(shoeboxPolicy, CFSTR("Shoebox"), &whenWritten); - + runCertificateTestForDirectory(shoeboxPolicy, CFSTR("Shoebox"), whenWritten); + + CFReleaseSafe(whenWritten); CFReleaseSafe(shoeboxPolicy); } int si_24_sectrust_shoebox(int argc, char *const *argv) { - plan_tests(31); + plan_tests(30); tests(); diff --git a/sec/Security/Regressions/secitem/si-25-sectrust-ipsec-eap.c b/Security/sec/Security/Regressions/secitem/si-25-sectrust-ipsec-eap.c similarity index 98% rename from sec/Security/Regressions/secitem/si-25-sectrust-ipsec-eap.c rename to Security/sec/Security/Regressions/secitem/si-25-sectrust-ipsec-eap.c index d5630645..40b221d1 100644 --- a/sec/Security/Regressions/secitem/si-25-sectrust-ipsec-eap.c +++ b/Security/sec/Security/Regressions/secitem/si-25-sectrust-ipsec-eap.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-2010,2012-2014 Apple Inc. All Rights Reserved. * */ @@ -10,6 +10,7 @@ #include #include #include +#include #include "Security_regressions.h" @@ -643,10 +644,8 @@ static void tests(void) ok_status(SecTrustCreateWithCertificates(leaf_certs, policy, &trust), "create trust for leaf"); CFTimeZoneRef tz = CFTimeZoneCreateWithName(NULL, CFSTR("CET"), true); - CFGregorianDate date_check = { 2009, 12, 1, 19, 10, 0 }; - CFAbsoluteTime atime = CFGregorianDateGetAbsoluteTime(date_check, tz); + CFDateRef date = CFDateCreateForGregorianMoment(NULL, tz, 2009, 12, 1, 19, 10, 0); CFReleaseNull(tz); - CFDateRef date = CFDateCreate(NULL, atime); ok_status(SecTrustSetVerifyDate(trust, date), "set date"); ok_status(SecTrustSetAnchorCertificates(trust, anchor_certs), "set anchor"); @@ -668,12 +667,10 @@ static void tests(void) isnt(policy = SecPolicyCreateEAP(true, valid_hosts), NULL, "create eap policy instance"); ok_status(SecTrustCreateWithCertificates(leaf_certs, policy, &trust), "create trust for leaf"); - + CFTimeZoneRef tz = CFTimeZoneCreateWithName(NULL, CFSTR("CET"), true); - CFGregorianDate date_check = { 2009, 12, 1, 19, 10, 0 }; - CFAbsoluteTime atime = CFGregorianDateGetAbsoluteTime(date_check, tz); + CFDateRef date = CFDateCreateForGregorianMoment(NULL, tz, 2009, 12, 1, 19, 10, 0); CFReleaseNull(tz); - CFDateRef date = CFDateCreate(NULL, atime); ok_status(SecTrustSetVerifyDate(trust, date), "set date"); ok_status(SecTrustSetAnchorCertificates(trust, anchor_certs), "set anchor"); @@ -706,10 +703,8 @@ static void tests(void) ok_status(SecTrustCreateWithCertificates(leaf_certs, policy, &trust), "create trust for leaf"); tz = CFTimeZoneCreateWithName(NULL, CFSTR("CET"), true); - CFGregorianDate date_check_too = { 2009, 3, 11, 19, 10, 0 }; - atime = CFGregorianDateGetAbsoluteTime(date_check_too, tz); + date = CFDateCreateForGregorianMoment(NULL, tz, 2009, 3, 11, 19, 10, 0); CFReleaseNull(tz); - date = CFDateCreate(NULL, atime); ok_status(SecTrustSetVerifyDate(trust, date), "set date"); ok_status(SecTrustSetAnchorCertificates(trust, anchor_certs), "set anchor"); diff --git a/sec/Security/Regressions/secitem/si-26-applicationsigning.c b/Security/sec/Security/Regressions/secitem/si-26-applicationsigning.c similarity index 99% rename from sec/Security/Regressions/secitem/si-26-applicationsigning.c rename to Security/sec/Security/Regressions/secitem/si-26-applicationsigning.c index fbbaeb1d..9e31866c 100644 --- a/sec/Security/Regressions/secitem/si-26-applicationsigning.c +++ b/Security/sec/Security/Regressions/secitem/si-26-applicationsigning.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007,2009-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2007,2009-2010,2012 Apple Inc. All Rights Reserved. */ #include diff --git a/sec/Security/Regressions/secitem/si-27-sectrust-exceptions.c b/Security/sec/Security/Regressions/secitem/si-27-sectrust-exceptions.c similarity index 99% rename from sec/Security/Regressions/secitem/si-27-sectrust-exceptions.c rename to Security/sec/Security/Regressions/secitem/si-27-sectrust-exceptions.c index 75fdafaa..5bab0267 100644 --- a/sec/Security/Regressions/secitem/si-27-sectrust-exceptions.c +++ b/Security/sec/Security/Regressions/secitem/si-27-sectrust-exceptions.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2010,2012-2014 Apple Inc. All Rights Reserved. */ #include @@ -166,7 +166,7 @@ static const uint8_t _c0[] = { 0x43, 0xfc, 0xb3, 0x10, 0xb7, 0x27 }; -static const uint8_t _c0_serial[] = { +__unused static const uint8_t _c0_serial[] = { 0x44, 0x50, 0xE6, 0x23, 0xF5, 0x7E, 0x73, 0x4F, 0xF8, 0x5C, 0x1D, 0xEE, 0xFB, 0x97, 0x6C, 0x86 }; diff --git a/sec/Security/Regressions/secitem/si-28-sectrustsettings.c b/Security/sec/Security/Regressions/secitem/si-28-sectrustsettings.c similarity index 99% rename from sec/Security/Regressions/secitem/si-28-sectrustsettings.c rename to Security/sec/Security/Regressions/secitem/si-28-sectrustsettings.c index 02957bb2..4e1a9d2d 100644 --- a/sec/Security/Regressions/secitem/si-28-sectrustsettings.c +++ b/Security/sec/Security/Regressions/secitem/si-28-sectrustsettings.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-2010,2012 Apple Inc. All Rights Reserved. */ #include diff --git a/sec/Security/Regressions/secitem/si-29-sectrust-codesigning.c b/Security/sec/Security/Regressions/secitem/si-29-sectrust-codesigning.c similarity index 99% rename from sec/Security/Regressions/secitem/si-29-sectrust-codesigning.c rename to Security/sec/Security/Regressions/secitem/si-29-sectrust-codesigning.c index 18e634f3..257aa110 100644 --- a/sec/Security/Regressions/secitem/si-29-sectrust-codesigning.c +++ b/Security/sec/Security/Regressions/secitem/si-29-sectrust-codesigning.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2010,2012-2013 Apple Inc. All Rights Reserved. */ #include diff --git a/sec/Security/Regressions/secitem/si-30-keychain-upgrade.c b/Security/sec/Security/Regressions/secitem/si-30-keychain-upgrade.c similarity index 87% rename from sec/Security/Regressions/secitem/si-30-keychain-upgrade.c rename to Security/sec/Security/Regressions/secitem/si-30-keychain-upgrade.c index d7e08903..3816cc9b 100644 --- a/sec/Security/Regressions/secitem/si-30-keychain-upgrade.c +++ b/Security/sec/Security/Regressions/secitem/si-30-keychain-upgrade.c @@ -1,12 +1,27 @@ /* - * si-30-keychain-upgrade.c - * Security - * - * Created by Michael Brouwer on 4/29/08. - * Copyright (c) 2008,2010 Apple Inc.. All Rights Reserved. + * Copyright (c) 2008,2010,2012-2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include #include #include @@ -19,7 +34,7 @@ #include #include "Security_regressions.h" -#include "SecItemServer.h" +#include /* TODO: This test needs to be updated. It was originally created to test upgrades from DB prior to the introduction of versionning, circa 2008. We don't support upgrading from that old of keychain, but this test should be upgraded to test upgrades from v5 to v6 keychain, or more current diff --git a/sec/Security/Regressions/secitem/si-31-keychain-bad.c b/Security/sec/Security/Regressions/secitem/si-31-keychain-bad.c similarity index 77% rename from sec/Security/Regressions/secitem/si-31-keychain-bad.c rename to Security/sec/Security/Regressions/secitem/si-31-keychain-bad.c index e3d17c52..c2df5411 100644 --- a/sec/Security/Regressions/secitem/si-31-keychain-bad.c +++ b/Security/sec/Security/Regressions/secitem/si-31-keychain-bad.c @@ -1,12 +1,27 @@ /* - * si-31-keychain-bad.c - * Security - * - * Created by Michael Brouwer on 5/23/08. - * Copyright (c) 2008,2010 Apple Inc.. All Rights Reserved. + * Copyright (c) 2008,2010,2012-2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include #include #include diff --git a/Security/sec/Security/Regressions/secitem/si-31-keychain-unreadable.c b/Security/sec/Security/Regressions/secitem/si-31-keychain-unreadable.c new file mode 100644 index 00000000..10c845ad --- /dev/null +++ b/Security/sec/Security/Regressions/secitem/si-31-keychain-unreadable.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2008-2010,2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "Security_regressions.h" + +#ifdef NO_SERVER +static void ensureKeychainExists(void) { + CFDictionaryRef query = CFDictionaryCreate(0, &kSecClass, &kSecClassInternetPassword, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFTypeRef results = NULL; + is_status(SecItemCopyMatching(query, &results), errSecItemNotFound, "expected nothing got %@", results); + CFReleaseNull(query); + CFReleaseNull(results); +} +#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) +{ +#ifndef NO_SERVER + plan_skip_all("No testing against server."); +#else + const char *home_dir = getenv("HOME"); + char keychain_dir[1000]; + char keychain_name[1000]; + sprintf(keychain_dir, "%s/Library/Keychains", home_dir); + sprintf(keychain_name, "%s/keychain-2-debug.db", keychain_dir); + + ensureKeychainExists(); + int fd; + ok_unix(fd = open(keychain_name, O_RDWR | O_CREAT | O_TRUNC, 0644), + "create keychain file '%s'", keychain_name); + ok_unix(fchmod(fd, 0), " keychain file '%s'", keychain_name); + ok_unix(close(fd), "close keychain file '%s'", keychain_name); + + kc_dbhandle_reset(); + + int v_eighty = 80; + CFNumberRef eighty = CFNumberCreate(NULL, kCFNumberSInt32Type, &v_eighty); + 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("members.spamcop.net")); + CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("smith")); + CFDictionaryAddValue(query, kSecAttrPort, eighty); + CFDictionaryAddValue(query, kSecAttrProtocol, kSecAttrProtocolHTTP); + CFDictionaryAddValue(query, kSecAttrAuthenticationType, kSecAttrAuthenticationTypeDefault); + CFDictionaryAddValue(query, kSecValueData, pwdata); + ok_status(SecItemAdd(query, NULL), "add internet password"); + is_status(SecItemAdd(query, NULL), errSecDuplicateItem, + "add internet password again"); + + ok_status(SecItemCopyMatching(query, NULL), "Found the item we added"); + + ok_status(SecItemDelete(query),"Deleted the item we added"); + + CFReleaseSafe(eighty); + CFReleaseSafe(pwdata); + CFReleaseSafe(query); +#endif +} + +int si_31_keychain_unreadable(int argc, char *const *argv) +{ + plan_tests(8); + tests(); + + return 0; +} diff --git a/Security/sec/Security/Regressions/secitem/si-33-keychain-backup.c b/Security/sec/Security/Regressions/secitem/si-33-keychain-backup.c new file mode 100644 index 00000000..b7bf620c --- /dev/null +++ b/Security/sec/Security/Regressions/secitem/si-33-keychain-backup.c @@ -0,0 +1,523 @@ +/* + * Copyright (c) 2010,2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + +#if TARGET_OS_EMBEDDED && !TARGET_IPHONE_SIMULATOR +#define USE_KEYSTORE 1 +#else /* No AppleKeyStore.kext on this OS. */ +#define USE_KEYSTORE 0 +#endif + + +#include +#include +#include +#include +#include +#include + +#if USE_KEYSTORE +#include +#include +#endif + +#include +#include +#include +#include +#include + +#include "../Security_regressions.h" + +struct test_persistent_s { + CFTypeRef persist[2]; + CFDictionaryRef query; + CFDictionaryRef query1; + CFDictionaryRef query2; + CFMutableDictionaryRef query3; + CFMutableDictionaryRef query4; +}; + +static void test_persistent(struct test_persistent_s *p) +{ + int v_eighty = 80; + 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, + kSecReturnPersistentRef, + kSecValueData + }; + const void *values[] = { + kSecClassInternetPassword, + CFSTR("zuigt.nl"), + CFSTR("frtnbf"), + eighty, + CFSTR("http"), + CFSTR("dflt"), + kCFBooleanTrue, + pwdata + }; + CFDictionaryRef item = CFDictionaryCreate(NULL, keys, values, + array_size(keys), &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + p->persist[0] = NULL; + // NUKE anything we might have left around from a previous test run so we don't crash. + SecItemDelete(item); + ok_status(SecItemAdd(item, &p->persist[0]), "add internet password"); + CFTypeRef results = NULL; + CFTypeRef results2 = NULL; + SKIP: { + skip("no persistent ref", 6, ok(p->persist[0], "got back persistent ref")); + + /* Create a dict with all attrs except the data. */ + keys[(array_size(keys)) - 2] = kSecReturnAttributes; + p->query = CFDictionaryCreate(NULL, keys, values, + (array_size(keys)) - 1, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + ok_status(SecItemCopyMatching(p->query, &results), "find internet password by attr"); + + const void *keys_persist[] = { + kSecReturnAttributes, + kSecValuePersistentRef + }; + const void *values_persist[] = { + kCFBooleanTrue, + p->persist[0] + }; + p->query2 = CFDictionaryCreate(NULL, keys_persist, values_persist, + (array_size(keys_persist)), &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + ok_status(SecItemCopyMatching(p->query2, &results2), "find internet password by persistent ref"); + ok(CFEqual(results, results2 ? results2 : CFSTR("")), "same item (attributes)"); + + CFReleaseNull(results); + CFReleaseNull(results2); + + ok_status(SecItemDelete(p->query), "delete internet password"); + + ok_status(!SecItemCopyMatching(p->query, &results), + "don't find internet password by attributes"); + ok(!results, "no results"); + } + + /* clean up left over from aborted run */ + if (results) { + CFDictionaryRef cleanup = CFDictionaryCreate(NULL, &kSecValuePersistentRef, + &results, 1, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + SecItemDelete(cleanup); + CFRelease(results); + CFRelease(cleanup); + } + + ok_status(!SecItemCopyMatching(p->query2, &results2), + "don't find internet password by persistent ref anymore"); + ok(!results2, "no results"); + + CFReleaseNull(p->persist[0]); + + /* Add a new item and get it's persitant ref. */ + ok_status(SecItemAdd(item, &p->persist[0]), "add internet password"); + p->persist[1] = NULL; + CFMutableDictionaryRef item2 = CFDictionaryCreateMutableCopy(NULL, 0, item); + CFDictionarySetValue(item2, kSecAttrAccount, CFSTR("johndoe-bu")); + // NUKE anything we might have left around from a previous test run so we don't crash. + SecItemDelete(item2); + ok_status(SecItemAdd(item2, &p->persist[1]), "add second internet password"); + CFMutableDictionaryRef update = NULL; + CFStringRef server = NULL; +SKIP: { + skip("no persistent ref", 3, ok(p->persist[0], "got back persistent ref from first internet password")); + + is(CFGetTypeID(p->persist[0]), CFDataGetTypeID(), "result is a CFData"); + p->query3 = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue(p->query3, kSecValuePersistentRef, p->persist[0]); + update = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); + CFDictionaryAddValue(update, kSecAttrServer, CFSTR("zuigt.com")); + ok_status(SecItemUpdate(p->query3, update), "update via persitant ref"); + + /* Verify that the update really worked. */ + CFDictionaryAddValue(p->query3, kSecReturnAttributes, kCFBooleanTrue); + ok_status(SecItemCopyMatching(p->query3, &results2), "find updated internet password by persistent ref"); + server = CFDictionaryGetValue(results2, kSecAttrServer); + ok(CFEqual(server, CFSTR("zuigt.com")), "verify attribute was modified by update"); + CFReleaseNull(results2); + CFDictionaryRemoveValue(p->query3, kSecReturnAttributes); +} + +SKIP: { + skip("no persistent ref", 2, ok(p->persist[1], "got back persistent ref")); + + /* Verify that item2 wasn't affected by the update. */ + p->query4 = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue(p->query4, kSecValuePersistentRef, p->persist[1]); + CFDictionaryAddValue(p->query4, kSecReturnAttributes, kCFBooleanTrue); + ok_status(SecItemCopyMatching(p->query4, &results2), "find non updated internet password by persistent ref"); + server = CFDictionaryGetValue(results2, kSecAttrServer); + ok(CFEqual(server, CFSTR("zuigt.nl")), "verify second items attribute was not modified by update"); + CFReleaseNull(results2); +} + + /* Delete the item via persitant ref. */ + ok_status(SecItemDelete(p->query3), "delete via persitant ref"); + is_status(SecItemCopyMatching(p->query3, &results2), errSecItemNotFound, + "don't find deleted internet password by persistent ref"); + CFReleaseNull(results2); + ok_status(SecItemCopyMatching(p->query4, &results2), + "find non deleted internet password by persistent ref"); + CFReleaseNull(results2); + + CFReleaseNull(update); + CFReleaseNull(item); + CFReleaseNull(item2); + CFReleaseNull(eighty); + CFReleaseNull(pwdata); +} + +static void test_persistent2(struct test_persistent_s *p) +{ + CFTypeRef results = NULL; + CFTypeRef results2 = NULL; + + ok_status(!SecItemCopyMatching(p->query, &results), + "don't find internet password by attributes"); + ok(!results, "no results"); + + ok_status(!SecItemCopyMatching(p->query2, &results2), + "don't find internet password by persistent ref anymore"); + ok(!results2, "no results"); + + SKIP:{ + ok_status(SecItemCopyMatching(p->query4, &results2), "find non updated internet password by persistent ref"); + skip("non updated internet password by persistent ref NOT FOUND!", 2, results2); + ok(results2, "non updated internet password not found"); + CFStringRef server = CFDictionaryGetValue(results2, kSecAttrServer); + ok(CFEqual(server, CFSTR("zuigt.nl")), "verify second items attribute was not modified by update"); + CFReleaseNull(results2); + } + + is_status(SecItemCopyMatching(p->query3, &results2), errSecItemNotFound, + "don't find deleted internet password by persistent ref"); + CFReleaseNull(results2); + ok_status(SecItemCopyMatching(p->query4, &results2), + "find non deleted internet password by persistent ref"); + CFReleaseNull(results2); + + ok_status(SecItemDelete(p->query4),"Deleted internet password by persistent ref"); + + CFRelease(p->query); + CFRelease(p->query2); + CFRelease(p->query3); + CFRelease(p->query4); + CFReleaseNull(p->persist[0]); + CFReleaseNull(p->persist[1]); +} + +static CFMutableDictionaryRef test_create_lockdown_identity_query(void) { + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); + CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword); + CFDictionaryAddValue(query, kSecAttrAccessGroup, CFSTR("lockdown-identities")); + return query; +} + +static CFMutableDictionaryRef test_create_managedconfiguration_query(void) { + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); + CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword); + CFDictionaryAddValue(query, kSecAttrService, CFSTR("com.apple.managedconfiguration")); + CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("Public")); + CFDictionaryAddValue(query, kSecAttrAccessGroup, CFSTR("apple")); + return query; +} + +static void test_add_lockdown_identity_items(void) { + CFMutableDictionaryRef query = test_create_lockdown_identity_query(); + const char *v_data = "lockdown identity data (which should be a cert + key)"; + CFDataRef pwdata = CFDataCreate(NULL, (UInt8 *)v_data, strlen(v_data)); + CFDictionaryAddValue(query, kSecValueData, pwdata); + ok_status(SecItemAdd(query, NULL), "test_add_lockdown_identity_items"); + CFReleaseSafe(pwdata); + CFReleaseSafe(query); +} + +static void test_remove_lockdown_identity_items(void) { + CFMutableDictionaryRef query = test_create_lockdown_identity_query(); + ok_status(SecItemDelete(query), "test_remove_lockdown_identity_items"); + CFReleaseSafe(query); +} + +static void test_no_find_lockdown_identity_item(void) { + CFMutableDictionaryRef query = test_create_lockdown_identity_query(); + is_status(SecItemCopyMatching(query, NULL), errSecItemNotFound, + "test_no_find_lockdown_identity_item"); + CFReleaseSafe(query); +} + +static void test_add_managedconfiguration_item(void) { + CFMutableDictionaryRef query = test_create_managedconfiguration_query(); + const char *v_data = "public managedconfiguration password history data"; + CFDataRef pwdata = CFDataCreate(NULL, (UInt8 *)v_data, strlen(v_data)); + CFDictionaryAddValue(query, kSecValueData, pwdata); + ok_status(SecItemAdd(query, NULL), "test_add_managedconfiguration_item"); + CFReleaseSafe(pwdata); + CFReleaseSafe(query); +} + +static void test_find_managedconfiguration_item(void) { + CFMutableDictionaryRef query = test_create_managedconfiguration_query(); + ok_status(SecItemCopyMatching(query, NULL), "test_find_managedconfiguration_item"); + ok_status(SecItemDelete(query), "test_find_managedconfiguration_item (deleted)"); + CFReleaseSafe(query); +} + +#if USE_KEYSTORE +static io_connect_t connect_to_keystore(void) +{ + io_registry_entry_t apple_key_bag_service; + kern_return_t result; + io_connect_t keystore = MACH_PORT_NULL; + + apple_key_bag_service = IOServiceGetMatchingService(kIOMasterPortDefault, + IOServiceMatching(kAppleKeyStoreServiceName)); + + if (apple_key_bag_service == IO_OBJECT_NULL) { + fprintf(stderr, "Failed to get service.\n"); + return keystore; + } + + result = IOServiceOpen(apple_key_bag_service, mach_task_self(), 0, &keystore); + if (KERN_SUCCESS != result) + fprintf(stderr, "Failed to open keystore\n"); + + if (keystore != MACH_PORT_NULL) { + IOReturn kernResult = IOConnectCallMethod(keystore, + kAppleKeyStoreUserClientOpen, NULL, 0, NULL, 0, NULL, NULL, + NULL, NULL); + if (kernResult) { + fprintf(stderr, "Failed to open AppleKeyStore: %x\n", kernResult); + } + } + return keystore; +} + +static CFDataRef create_keybag(keybag_handle_t bag_type, CFDataRef password) +{ + uint64_t inputs[] = { bag_type }; + uint64_t outputs[] = {0}; + uint32_t num_inputs = array_size(inputs); + uint32_t num_outputs = array_size(outputs); + IOReturn kernResult; + + io_connect_t keystore; + + unsigned char keybagdata[4096]; //Is that big enough? + size_t keybagsize=sizeof(keybagdata); + + keystore=connect_to_keystore(); + + kernResult = IOConnectCallMethod(keystore, + kAppleKeyStoreKeyBagCreate, + inputs, num_inputs, NULL, 0, + outputs, &num_outputs, NULL, 0); + + if (kernResult) { + fprintf(stderr, "kAppleKeyStoreKeyBagCreate: 0x%x\n", kernResult); + return NULL; + } + + /* Copy out keybag */ + inputs[0]=outputs[0]; + num_inputs=1; + + kernResult = IOConnectCallMethod(keystore, + kAppleKeyStoreKeyBagCopy, + inputs, num_inputs, NULL, 0, + NULL, 0, keybagdata, &keybagsize); + + if (kernResult) { + fprintf(stderr, "kAppleKeyStoreKeyBagCopy: 0x%x\n", kernResult); + return NULL; + } + + return CFDataCreate(kCFAllocatorDefault, keybagdata, keybagsize); +} +#endif + +/* Test low level keychain migration from device to device interface. */ +static void tests(void) +{ + int v_eighty = 80; + CFNumberRef eighty = CFNumberCreate(NULL, kCFNumberSInt32Type, &v_eighty); + 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("members.spamcop.net")); + CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("smith")); + CFDictionaryAddValue(query, kSecAttrPort, eighty); + CFDictionaryAddValue(query, kSecAttrProtocol, kSecAttrProtocolHTTP); + CFDictionaryAddValue(query, kSecAttrAuthenticationType, kSecAttrAuthenticationTypeDefault); + CFDictionaryAddValue(query, kSecValueData, pwdata); + // NUKE anything we might have left around from a previous test run so we don't crash. + SecItemDelete(query); + ok_status(SecItemAdd(query, NULL), "add internet password"); + is_status(SecItemAdd(query, NULL), errSecDuplicateItem, + "add internet password again"); + + ok_status(SecItemCopyMatching(query, NULL), "Found the item we added"); + + struct test_persistent_s p = {}; + test_persistent(&p); + + CFDataRef backup = NULL, keybag = NULL, password = NULL; + + test_add_lockdown_identity_items(); + +#if USE_KEYSTORE + keybag = create_keybag(kAppleKeyStoreBackupBag, password); +#else + keybag = CFDataCreate(kCFAllocatorDefault, NULL, 0); +#endif + + ok(backup = _SecKeychainCopyBackup(keybag, password), + "_SecKeychainCopyBackup"); + + test_add_managedconfiguration_item(); + test_remove_lockdown_identity_items(); + + ok_status(_SecKeychainRestoreBackup(backup, keybag, password), + "_SecKeychainRestoreBackup"); + CFReleaseSafe(backup); + + test_no_find_lockdown_identity_item(); + test_find_managedconfiguration_item(); + + ok_status(SecItemCopyMatching(query, NULL), + "Found the item we added after restore"); + + test_persistent2(&p); + +#if USE_KEYSTORE + CFReleaseNull(keybag); + keybag = create_keybag(kAppleKeyStoreOTABackupBag, password); +#endif + + ok(backup = _SecKeychainCopyBackup(keybag, password), + "_SecKeychainCopyBackup"); + ok_status(_SecKeychainRestoreBackup(backup, keybag, password), + "_SecKeychainRestoreBackup"); + ok_status(SecItemCopyMatching(query, NULL), + "Found the item we added after restore"); + CFReleaseNull(backup); + + // force tombstone to be added, since it's not the default behavior per rdar://14680869 + CFDictionaryAddValue(query, kSecUseTombstones, kCFBooleanTrue); + + ok_status(SecItemDelete(query), "Deleted item we added"); + +#if USE_KEYSTORE + CFReleaseNull(keybag); + keybag = create_keybag(kAppleKeyStoreOTABackupBag /* use truthiness bag once it's there */, password); +#endif + + // add syncable item + CFDictionaryAddValue(query, kSecAttrSynchronizable, kCFBooleanTrue); + ok_status(SecItemAdd(query, NULL), "add internet password"); + + // and non-syncable item + test_add_managedconfiguration_item(); + + CFDictionaryRef syncableBackup = NULL; + + CFErrorRef error = NULL; + CFDictionaryRef scratch = NULL; + SKIP: { + skip("skipping syncable backup tests", 7, + ok_status(_SecKeychainBackupSyncable(keybag, password, NULL, &syncableBackup), "export items")); + + // TODO: add item, call SecServerCopyTruthInTheCloud again + + // CFShow(syncableBackup); + + // find and delete + skip("skipping syncable backup tests", 6, + ok_status(SecItemCopyMatching(query, NULL), "find item we are about to destroy")); + + skip("skipping syncable backup tests", 5, + ok_status(SecItemDelete(query), "delete item we backed up")); + + // ensure we added a tombstone + CFDictionaryAddValue(query, kSecAttrTombstone, kCFBooleanTrue); + skip("skipping syncable backup tests", 4, + ok_status(SecItemCopyMatching(query, NULL), "find tombstone for item we deleted")); + CFDictionaryRemoveValue(query, kSecAttrTombstone); + + test_find_managedconfiguration_item(); // <- 2 tests here + + // TODO: add a different new item - delete what's not in the syncableBackup? + + // Do another backup after some changes + skip("skipping syncable backup tests", 1, + ok_status(_SecKeychainBackupSyncable(keybag, password, syncableBackup, &scratch), "export items after changes")); + + skip("skipping syncable backup tests", 0, + ok_status(_SecKeychainRestoreSyncable(keybag, password, syncableBackup), "import items")); + } + CFReleaseNull(scratch); + CFReleaseNull(error); + + // non-syncable item should (still) be gone -> add should work + test_add_managedconfiguration_item(); + test_find_managedconfiguration_item(); + + // syncable item should have not been restored, because the tombstone was newer than the item in the backup -> copy matching should fail + is_status(errSecItemNotFound, SecItemCopyMatching(query, NULL), + "find restored item"); + is_status(errSecItemNotFound, SecItemDelete(query), "delete restored item"); + + CFReleaseSafe(syncableBackup); + CFReleaseSafe(keybag); + CFReleaseSafe(eighty); + CFReleaseSafe(pwdata); + CFReleaseSafe(query); +} + +int si_33_keychain_backup(int argc, char *const *argv) +{ + plan_tests(64); + + tests(); + + return 0; +} diff --git a/Security/sec/Security/Regressions/secitem/si-40-seckey-custom.c b/Security/sec/Security/Regressions/secitem/si-40-seckey-custom.c new file mode 100644 index 00000000..50dd5aa8 --- /dev/null +++ b/Security/sec/Security/Regressions/secitem/si-40-seckey-custom.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2007-2008,2010,2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include + +#include "Security_regressions.h" + +#define CFReleaseNull(CF) { CFTypeRef _cf = (CF); if (_cf) { (CF) = NULL; CFRelease(_cf); } } + +static SecKeyRef customKey; +static SecKeyRef initedCustomKey; + +static OSStatus CustomKeyInit(SecKeyRef key, const uint8_t *key_data, + CFIndex key_len, SecKeyEncoding encoding) +{ + ok(key, "CustomKeyInit"); + ok(key && key->key == NULL, "key->key is NULL"); + initedCustomKey = key; + return errSecSuccess; +} + +static void CustomKeyDestroy(SecKeyRef key) +{ + is(customKey, key, "CustomKeyDestroy"); +} + +static OSStatus CustomKeyRawSign(SecKeyRef key, SecPadding padding, + const uint8_t *dataToSign, size_t dataToSignLen, + uint8_t *sig, size_t *sigLen) +{ + is(customKey, key, "CustomKeyRawSign"); + return errSecSuccess; +} + +static OSStatus CustomKeyRawVerify( + SecKeyRef key, SecPadding padding, const uint8_t *signedData, + size_t signedDataLen, const uint8_t *sig, size_t sigLen) +{ + is(customKey, key, "CustomKeyRawVerify"); + return errSecSuccess; +} + +static OSStatus CustomKeyEncrypt(SecKeyRef key, SecPadding padding, + const uint8_t *plainText, size_t plainTextLen, + uint8_t *cipherText, size_t *cipherTextLen) +{ + is(customKey, key, "CustomKeyEncrypt"); + return errSecSuccess; +} + +static OSStatus CustomKeyDecrypt(SecKeyRef key, SecPadding padding, + const uint8_t *cipherText, size_t cipherTextLen, + uint8_t *plainText, size_t *plainTextLen) +{ + is(customKey, key, "CustomKeyDecrypt"); + return errSecSuccess; +} + +static OSStatus CustomKeyCompute(SecKeyRef key, + const uint8_t *pub_key, size_t pub_key_len, + uint8_t *computed_key, size_t *computed_key_len) +{ + is(customKey, key, "CustomKeyCompute"); + return errSecSuccess; +} + +static size_t CustomKeyBlockSize(SecKeyRef key) +{ + is(customKey, key, "CustomKeyBlockSize"); + return 42; +} + +static CFDictionaryRef CustomKeyCopyAttributeDictionary(SecKeyRef key) +{ + is(customKey, key, "CustomKeyCopyAttributeDictionary"); + CFDictionaryRef dict = CFDictionaryCreate(kCFAllocatorDefault, NULL, NULL, + 0, NULL, NULL); + return dict; +} + +static CFStringRef CustomKeyCopyDescribe(SecKeyRef key) +{ + return CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), key->key_class->name); +} + + +SecKeyDescriptor kCustomKeyDescriptor_version0 = { + 0, + "CustomKeyVersion0", + 0, /* extraBytes */ + CustomKeyInit, + CustomKeyDestroy, + CustomKeyRawSign, + CustomKeyRawVerify, + CustomKeyEncrypt, + CustomKeyDecrypt, + CustomKeyCompute, + CustomKeyBlockSize, + CustomKeyCopyAttributeDictionary, + CustomKeyCopyDescribe, + (void *)abort, + (void *)abort, + (void *)abort, + (void *)abort, +}; + +SecKeyDescriptor kCustomKeyDescriptor_version1 = { + 1, + "CustomKeyVersion1", + 0, /* extraBytes */ + CustomKeyInit, + CustomKeyDestroy, + CustomKeyRawSign, + CustomKeyRawVerify, + CustomKeyEncrypt, + CustomKeyDecrypt, + CustomKeyCompute, + CustomKeyBlockSize, + CustomKeyCopyAttributeDictionary, + CustomKeyCopyDescribe, + NULL, + (void *)abort, + (void *)abort, + (void *)abort, +}; + +SecKeyDescriptor kCustomKeyDescriptor_version2 = { + 2, + "CustomKeyVersion2", + 0, /* extraBytes */ + CustomKeyInit, + CustomKeyDestroy, + CustomKeyRawSign, + CustomKeyRawVerify, + CustomKeyEncrypt, + CustomKeyDecrypt, + CustomKeyCompute, + CustomKeyBlockSize, + CustomKeyCopyAttributeDictionary, + CustomKeyCopyDescribe, + NULL, + NULL, + (void *)abort, + (void *)abort, +}; + +SecKeyDescriptor kCustomKeyDescriptor_version3 = { + 3, + "CustomKeyVersion3", + 0, /* extraBytes */ + CustomKeyInit, + CustomKeyDestroy, + CustomKeyRawSign, + CustomKeyRawVerify, + CustomKeyEncrypt, + CustomKeyDecrypt, + CustomKeyCompute, + CustomKeyBlockSize, + CustomKeyCopyAttributeDictionary, + CustomKeyCopyDescribe, + NULL, + NULL, + NULL, + NULL, +}; + +/* Test basic add delete update copy matching stuff. */ +static void tests(SecKeyDescriptor *descriptor) +{ + const uint8_t *keyData = (const uint8_t *)"abc"; + CFIndex keyDataLength = 3; + SecKeyEncoding encoding = kSecKeyEncodingRaw; + ok(customKey = SecKeyCreate(kCFAllocatorDefault, + descriptor, keyData, keyDataLength, encoding), + "create custom key"); + is(customKey, initedCustomKey, "CustomKeyInit got the right key"); + + SecPadding padding = kSecPaddingPKCS1; + const uint8_t *src = NULL; + size_t srcLen = 3; + uint8_t *dst = NULL; + size_t dstLen = 3; + + ok_status(SecKeyDecrypt(customKey, padding, src, srcLen, dst, &dstLen), + "SecKeyDecrypt"); + ok_status(SecKeyEncrypt(customKey, padding, src, srcLen, dst, &dstLen), + "SecKeyEncrypt"); + ok_status(SecKeyRawSign(customKey, padding, src, srcLen, dst, &dstLen), + "SecKeyRawSign"); + ok_status(SecKeyRawVerify(customKey, padding, src, srcLen, dst, dstLen), + "SecKeyRawVerify"); + is(SecKeyGetSize(customKey, kSecKeyKeySizeInBits), (size_t)42*8, "SecKeyGetSize"); + + CFDictionaryRef attrDict = NULL; + ok(attrDict = SecKeyCopyAttributeDictionary(customKey), + "SecKeyCopyAttributeDictionary"); + CFReleaseNull(attrDict); + + CFDataRef pubdata = NULL; + ok(SecKeyCopyPublicBytes(customKey, &pubdata) != 0, "SecKeyCopyPublicBytes"); + CFReleaseNull(pubdata); + + CFDataRef wrapped; + wrapped = _SecKeyCopyWrapKey(customKey, kSecKeyWrapPublicKeyPGP, pubdata, NULL, NULL, NULL); + ok(wrapped == NULL, "_SecKeyCopyWrapKey"); + CFReleaseNull(wrapped); + + wrapped = _SecKeyCopyUnwrapKey(customKey, kSecKeyWrapPublicKeyPGP, pubdata, NULL, NULL, NULL); + ok(wrapped == NULL, "_SecKeyCopyUnwrapKey"); + CFReleaseNull(wrapped); + + //ok(SecKeyGeneratePair(customKey, ), "SecKeyGeneratePair"); + ok(SecKeyGetTypeID() != 0, "SecKeyGetTypeID works"); + + if (customKey) { + CFRelease(customKey); + customKey = NULL; + } +} + +int si_40_seckey_custom(int argc, char *const *argv) +{ + plan_tests(21 * 4); + + tests(&kCustomKeyDescriptor_version0); + tests(&kCustomKeyDescriptor_version1); + tests(&kCustomKeyDescriptor_version2); + tests(&kCustomKeyDescriptor_version3); + + return 0; +} diff --git a/sec/Security/Regressions/secitem/si-40-seckey.c b/Security/sec/Security/Regressions/secitem/si-40-seckey.c similarity index 93% rename from sec/Security/Regressions/secitem/si-40-seckey.c rename to Security/sec/Security/Regressions/secitem/si-40-seckey.c index aef3a8fb..1644000c 100644 --- a/sec/Security/Regressions/secitem/si-40-seckey.c +++ b/Security/sec/Security/Regressions/secitem/si-40-seckey.c @@ -1,12 +1,27 @@ /* - * si-40-seckey.c - * Security - * - * Created by Michael Brouwer on 1/29/07. - * Copyright (c) 2007-2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2009,2012-2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include #include #include @@ -161,7 +176,8 @@ static void testkeygen(size_t keySizeInBits) { size_t keySizeInBytes = (keySizeInBits + 7) / 8; CFNumberRef kzib; - kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keySizeInBits); + int32_t iKeySizeInBits = (int32_t) keySizeInBits; + kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &iKeySizeInBits); CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeRSA); CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib); @@ -346,7 +362,8 @@ static void testkeygen2(size_t keySizeInBits) { CFDictionaryAddValue(pubd, kSecAttrLabel, publicName); CFDictionaryAddValue(privd, kSecAttrLabel, privateName); - kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keySizeInBits); + int32_t iKeySizeInBits = (int32_t) keySizeInBits; + kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &iKeySizeInBits); CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeRSA); CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib); diff --git a/Security/sec/Security/Regressions/secitem/si-41-sececkey.c b/Security/sec/Security/Regressions/secitem/si-41-sececkey.c new file mode 100644 index 00000000..55842390 --- /dev/null +++ b/Security/sec/Security/Regressions/secitem/si-41-sececkey.c @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* + * si-40-seckey.c + * Security + * + * Copyright (c) 2007-2009,2012-2014 Apple Inc. All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Security_regressions.h" + +static void testdigestandsignalg(SecKeyRef privKey, SecKeyRef pubKey, const SecAsn1AlgId *algId) { + uint8_t dataToDigest[256] = {0,}; + size_t dataToDigestLen = sizeof(dataToDigest); + size_t sigLen = SecKeyGetSize(privKey, kSecKeySignatureSize); + uint8_t sig[sigLen]; + + DERItem oid; + oid.length = algId->algorithm.Length; + oid.data = algId->algorithm.Data; + + /* Get the oid in decimal for display purposes. */ + CFStringRef oidStr = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, &oid); + char oidBuf[40]; + CFStringGetCString(oidStr, oidBuf, sizeof(oidBuf), kCFStringEncodingUTF8); + CFRelease(oidStr); + +SKIP: { + OSStatus status; + + /* Time to sign. */ + ok_status(status = SecKeyDigestAndSign(privKey, algId, dataToDigest, dataToDigestLen, + sig, &sigLen), + "digest and sign %s with %ld bit RSA key", oidBuf, sigLen * 8); + + skip("SecKeyDigestAndSign failed", 3, status == errSecSuccess); + + /* Verify the signature we just made. */ + ok_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen, + sig, sigLen), "digest and verify"); + /* Invalidate the signature. */ + sig[0] ^= 0xff; + is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen, + sig, sigLen), errSSLCrypto, "digest and verify bad sig"); + sig[0] ^= 0xff; + dataToDigest[0] ^= 0xff; + is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen, + sig, sigLen), errSSLCrypto, "digest and verify bad digest"); +} +} + +static void testdigestandsign(SecKeyRef privKey, SecKeyRef pubKey) { + static const SecAsn1Oid *oids[] = { + &CSSMOID_ECDSA_WithSHA1, +#if 0 + &CSSMOID_ECDSA_WithSHA224, + &CSSMOID_ECDSA_WithSHA256, + &CSSMOID_ECDSA_WithSHA384, + &CSSMOID_ECDSA_WithSHA512, +#endif + }; + + uint32_t ix; + SecAsn1AlgId algId = {}; + for (ix = 0; ix < array_size(oids); ++ix) { + if (oids[ix]) { + algId.algorithm = *oids[ix]; + } else { + algId.algorithm.Length = 0; + algId.algorithm.Data = NULL; + } + + testdigestandsignalg(privKey, pubKey, &algId); + } +} + +static void testkeygen(size_t keySizeInBits) { + SecKeyRef pubKey = NULL, privKey = NULL; + size_t keySizeInBytes = (keySizeInBits + 7) / 8; + CFNumberRef kzib; + int32_t keysz32 = (int32_t)keySizeInBits; + + kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); + CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); + CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeEC); + CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib); + + OSStatus status; + ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), + "Generate %ld bit (%ld byte) EC keypair", keySizeInBits, + keySizeInBytes); + CFRelease(kzib); + CFRelease(kgp); + +SKIP: { + skip("keygen failed", 8, status == errSecSuccess); + ok(pubKey, "pubkey returned"); + ok(privKey, "privKey returned"); + is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok"); + is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok"); + + /* Sign something. */ + uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, }; + uint8_t sig[8+2*keySizeInBytes]; + size_t sigLen = sizeof(sig); + ok_status(SecKeyRawSign(privKey, kSecPaddingNone, + something, sizeof(something), sig, &sigLen), "sign something"); + ok_status(SecKeyRawVerify(pubKey, kSecPaddingNone, + something, sizeof(something), sig, sigLen), "verify sig on something"); + + testdigestandsign(privKey, pubKey); + + const void *privkeys[] = { + kSecValueRef + }; + const void *privvalues[] = { + privKey + }; + CFDictionaryRef privitem = CFDictionaryCreate(NULL, privkeys, privvalues, + array_size(privkeys), NULL, NULL); + ok_status(SecItemAdd(privitem, NULL), "add private key"); + ok_status(SecItemDelete(privitem), "delete public key"); + CFReleaseNull(privitem); + + const void *pubkeys[] = { + kSecValueRef + }; + const void *pubvalues[] = { + pubKey + }; + CFDictionaryRef pubitem = CFDictionaryCreate(NULL, pubkeys, pubvalues, + array_size(pubkeys), NULL, NULL); + ok_status(SecItemAdd(pubitem, NULL), "add public key"); + ok_status(SecItemDelete(pubitem), "delete public key"); + CFReleaseNull(pubitem); + + /* Cleanup. */ + CFReleaseNull(pubKey); + CFReleaseNull(privKey); +} +} + + +static void testkeygen2(size_t keySizeInBits) { + SecKeyRef pubKey = NULL, privKey = NULL; + size_t keySizeInBytes = (keySizeInBits + 7) / 8; + CFNumberRef kzib; + int32_t keysz32 = (int32_t)keySizeInBits; + + CFUUIDRef ourUUID = CFUUIDCreate(kCFAllocatorDefault); + CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, ourUUID); + CFMutableStringRef publicName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString); + CFMutableStringRef privateName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString); + + CFReleaseNull(ourUUID); + CFReleaseNull(uuidString); + + CFStringAppend(publicName, CFSTR("-Public-41")); + CFStringAppend(privateName, CFSTR("-Private-41")); + + CFMutableDictionaryRef pubd = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, + kSecAttrLabel, publicName, + NULL); + CFMutableDictionaryRef privd = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, + kSecAttrLabel, privateName, + NULL); + + kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); + CFDictionaryRef kgp = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecAttrKeyType, kSecAttrKeyTypeEC, + kSecAttrKeySizeInBits, kzib, + kSecAttrIsPermanent, kCFBooleanTrue, + kSecPublicKeyAttrs, pubd, + kSecPrivateKeyAttrs, privd, + NULL); + + CFReleaseNull(kzib); + + OSStatus status; + ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), + "Generate %ld bit (%ld byte) persistent RSA keypair", + keySizeInBits, keySizeInBytes); + + CFReleaseNull(kgp); + +SKIP: { + skip("keygen failed", 8, status == errSecSuccess); + ok(pubKey, "pubkey returned"); + ok(privKey, "privKey returned"); + is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok"); + is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok"); + + SecKeyRef pubKey2, privKey2; + CFDictionaryAddValue(pubd, kSecClass, kSecClassKey); + CFDictionaryAddValue(pubd, kSecReturnRef, kCFBooleanTrue); + CFDictionaryAddValue(privd, kSecClass, kSecClassKey); + CFDictionaryAddValue(privd, kSecReturnRef, kCFBooleanTrue); + CFDictionaryAddValue(privd, kSecAttrCanSign, kCFBooleanTrue); + ok_status(SecItemCopyMatching(pubd, (CFTypeRef *)&pubKey2), + "retrieve pub key by label"); + ok(pubKey2, "got valid object"); + ok_status(SecItemCopyMatching(privd, (CFTypeRef *)&privKey2), + "retrieve priv key by label and kSecAttrCanSign"); + ok(privKey2, "got valid object"); + + /* Sign something. */ + uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, }; + size_t sigLen = SecKeyGetSize(privKey2, kSecKeySignatureSize); + uint8_t sig[sigLen]; + ok_status(SecKeyRawSign(privKey2, kSecPaddingPKCS1, + something, sizeof(something), sig, &sigLen), "sign something"); + ok_status(SecKeyRawVerify(pubKey2, kSecPaddingPKCS1, + something, sizeof(something), sig, sigLen), "verify sig on something"); + + /* Cleanup. */ + CFReleaseNull(pubKey2); + CFReleaseNull(privKey2); +} + + /* delete from keychain - note: do it before releasing publicName and privateName + because pubd and privd have no retain/release callbacks */ + ok_status(SecItemDelete(pubd), "delete generated pub key"); + ok_status(SecItemDelete(privd), "delete generated priv key"); + + /* Cleanup. */ + CFReleaseNull(pubKey); + CFReleaseNull(privKey); + + CFReleaseNull(publicName); + CFReleaseNull(privateName); + + CFReleaseNull(pubd); + CFReleaseNull(privd); +} + +static void testkeywrap(unsigned long keySizeInBits, CFTypeRef alg) +{ + SecKeyRef pubKey = NULL, privKey = NULL; + size_t keySizeInBytes = (keySizeInBits + 7) / 8; + CFNumberRef kzib; + int32_t keysz32 = (int32_t)keySizeInBits; + + CFUUIDRef ourUUID = CFUUIDCreate(kCFAllocatorDefault); + CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, ourUUID); + CFMutableStringRef publicName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString); + CFMutableStringRef privateName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString); + + CFReleaseNull(ourUUID); + CFReleaseNull(uuidString); + + CFStringAppend(publicName, CFSTR("-Public-41")); + CFStringAppend(privateName, CFSTR("-Private-41")); + + CFDictionaryRef pubd = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecAttrLabel, publicName, + NULL); + CFDictionaryRef privd = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecAttrLabel, privateName, + NULL); + + CFReleaseNull(publicName); + CFReleaseNull(privateName); + + kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); + CFDictionaryRef kgp = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecAttrKeyType, kSecAttrKeyTypeEC, + kSecAttrKeySizeInBits, kzib, + kSecAttrIsPermanent, kCFBooleanFalse, + kSecPublicKeyAttrs, pubd, + kSecPrivateKeyAttrs, privd, + NULL); + CFReleaseNull(pubd); + CFReleaseNull(privd); + CFReleaseNull(kzib); + + OSStatus status; + ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), + "Generate %ld bit (%ld byte) persistent RSA keypair (status = %d)", + keySizeInBits, keySizeInBytes, (int)status); + CFReleaseNull(kgp); + + CFErrorRef localError; + + CFDataRef secret = CFDataCreate(NULL, (void *)"0123456789012345", 16); + ok(secret, "secret"); + + CFDataRef fp = CFDataCreate(NULL, (void *)"01234567890123456789", 20); + ok(fp, "fingerprint"); + + + int8_t sym_alg_data = 8; + CFNumberRef symalg = CFNumberCreate(NULL, kCFNumberSInt8Type, &sym_alg_data); + CFDictionaryRef param = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + _kSecKeyWrapPGPWrapAlg, alg, + _kSecKeyWrapPGPSymAlg, symalg, + _kSecKeyWrapPGPFingerprint, fp, + NULL); + + CFDataRef wrapped = _SecKeyCopyWrapKey(pubKey, kSecKeyWrapPublicKeyPGP, secret, param, NULL, &localError); + ok(wrapped, "wrap key: %@", localError); + + CFDataRef unwrapped = _SecKeyCopyUnwrapKey(privKey, kSecKeyWrapPublicKeyPGP, wrapped, param, NULL, &localError); + ok(unwrapped, "unwrap key: %@", localError); + + CFReleaseNull(symalg); + + ok(CFEqual(unwrapped, secret), "keys still same"); + + CFReleaseNull(fp); + CFReleaseNull(secret); + CFReleaseNull(unwrapped); + CFReleaseNull(wrapped); + CFReleaseNull(param); + CFReleaseNull(privKey); + CFReleaseNull(pubKey); +} + + + + +/* Test basic add delete update copy matching stuff. */ +static void tests(void) +{ + testkeygen(192); + testkeygen(224); + testkeygen(256); + testkeygen(384); + testkeygen(521); + + testkeygen2(192); + testkeygen2(224); + testkeygen2(256); + testkeygen2(384); + testkeygen2(521); + + testkeywrap(256, _kSecKeyWrapRFC6637WrapDigestSHA256KekAES128); + testkeywrap(521, _kSecKeyWrapRFC6637WrapDigestSHA256KekAES128); + testkeywrap(256, _kSecKeyWrapRFC6637WrapDigestSHA512KekAES256); + testkeywrap(521, _kSecKeyWrapRFC6637WrapDigestSHA512KekAES256); + +} + +int si_41_sececkey(int argc, char *const *argv) +{ + plan_tests(164); + + tests(); + + return 0; +} diff --git a/sec/Security/Regressions/secitem/si-42-identity.c b/Security/sec/Security/Regressions/secitem/si-42-identity.c similarity index 97% rename from sec/Security/Regressions/secitem/si-42-identity.c rename to Security/sec/Security/Regressions/secitem/si-42-identity.c index 1841e8de..6f9c39ff 100644 --- a/sec/Security/Regressions/secitem/si-42-identity.c +++ b/Security/sec/Security/Regressions/secitem/si-42-identity.c @@ -1,12 +1,27 @@ /* - * si-42-secidentity.c - * Security - * - * Created by Michael Brouwer on 1/29/07. - * Copyright (c) 2007-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2010,2012-2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include #include #include diff --git a/sec/Security/Regressions/secitem/si-43-persistent.c b/Security/sec/Security/Regressions/secitem/si-43-persistent.c similarity index 98% rename from sec/Security/Regressions/secitem/si-43-persistent.c rename to Security/sec/Security/Regressions/secitem/si-43-persistent.c index e96dbfe0..0a2bc1e9 100644 --- a/sec/Security/Regressions/secitem/si-43-persistent.c +++ b/Security/sec/Security/Regressions/secitem/si-43-persistent.c @@ -2,7 +2,7 @@ * si-43-persistent.c * Security * - * Copyright (c) 2008-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-2010,2012-2013 Apple Inc. All Rights Reserved. * */ diff --git a/Security/sec/Security/Regressions/secitem/si-50-secrandom.c b/Security/sec/Security/Regressions/secitem/si-50-secrandom.c new file mode 100644 index 00000000..c7bebf89 --- /dev/null +++ b/Security/sec/Security/Regressions/secitem/si-50-secrandom.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2007-2008,2010,2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include +#include +#include + +#include "Security_regressions.h" + +/* Test basic add delete update copy matching stuff. */ +static void tests(void) +{ + UInt8 bytes[4096] = {}; + CFIndex size = 42; + UInt8 *p = bytes + 23; + ok_status(SecRandomCopyBytes(kSecRandomDefault, size, p), "generate some random bytes"); +} + +int si_50_secrandom(int argc, char *const *argv) +{ + plan_tests(1); + + + tests(); + + return 0; +} diff --git a/sec/Security/Regressions/secitem/si-60-cms.c b/Security/sec/Security/Regressions/secitem/si-60-cms.c similarity index 99% rename from sec/Security/Regressions/secitem/si-60-cms.c rename to Security/sec/Security/Regressions/secitem/si-60-cms.c index 44bab4e8..2ca7eec3 100644 --- a/sec/Security/Regressions/secitem/si-60-cms.c +++ b/Security/sec/Security/Regressions/secitem/si-60-cms.c @@ -1,12 +1,27 @@ /* - * si-60-cms.c - * Security - * - * Created by Michael Brouwer on 2/21/08 - * Copyright (c) 2008-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-2010,2012-2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include #include #include @@ -1609,7 +1624,7 @@ static unsigned char scep_ca[] = { static unsigned int scep_ca_len = 505; #include -static inline void write_data(const char * path, CFDataRef data) +__unused static inline void write_data(const char * path, CFDataRef data) { int data_file = open(path, O_CREAT|O_WRONLY|O_TRUNC, 0644); write(data_file, CFDataGetBytePtr(data), CFDataGetLength(data)); diff --git a/sec/Security/Regressions/secitem/si-61-pkcs12.c b/Security/sec/Security/Regressions/secitem/si-61-pkcs12.c similarity index 97% rename from sec/Security/Regressions/secitem/si-61-pkcs12.c rename to Security/sec/Security/Regressions/secitem/si-61-pkcs12.c index d06e83aa..ab17bd10 100644 --- a/sec/Security/Regressions/secitem/si-61-pkcs12.c +++ b/Security/sec/Security/Regressions/secitem/si-61-pkcs12.c @@ -1,12 +1,27 @@ /* - * si-61-pkcs12.c - * Security - * - * Created by Conrad Sauerwald on 3/19/08. - * Copyright (c) 2008-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-2010,2012-2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include #include diff --git a/sec/Security/Regressions/secitem/si-62-csr.c b/Security/sec/Security/Regressions/secitem/si-62-csr.c similarity index 91% rename from sec/Security/Regressions/secitem/si-62-csr.c rename to Security/sec/Security/Regressions/secitem/si-62-csr.c index 39ed55c7..459f0012 100644 --- a/sec/Security/Regressions/secitem/si-62-csr.c +++ b/Security/sec/Security/Regressions/secitem/si-62-csr.c @@ -1,12 +1,27 @@ /* - * si-62-csr.c - * Security - * - * Created by Conrad Sauerwald on 5/7/08. - * Copyright (c) 2008-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-2010,2012-2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include #include #include @@ -25,7 +40,7 @@ #include "Security_regressions.h" #include -static inline void write_data(const char * path, CFDataRef data) +__unused static inline void write_data(const char * path, CFDataRef data) { int data_file = open(path, O_CREAT|O_WRONLY|O_TRUNC, 0644); write(data_file, CFDataGetBytePtr(data), CFDataGetLength(data)); diff --git a/sec/Security/Regressions/secitem/si-63-scep.c b/Security/sec/Security/Regressions/secitem/si-63-scep.c similarity index 98% rename from sec/Security/Regressions/secitem/si-63-scep.c rename to Security/sec/Security/Regressions/secitem/si-63-scep.c index 04a4f886..e59051fd 100644 --- a/sec/Security/Regressions/secitem/si-63-scep.c +++ b/Security/sec/Security/Regressions/secitem/si-63-scep.c @@ -1,11 +1,26 @@ /* - * si-60-cms.c - * Security - * - * Created by Michael Brouwer on 2/21/08 - * Copyright (c) 2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2008,2012-2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include #include #include @@ -965,14 +980,15 @@ static unsigned int bmw_scep_pkt_len = 5661; #include "si-63-scep/getcacert-mdesqa.h" #include -static inline void write_data(const char * path, CFDataRef data) +__unused static inline void write_data(const char * path, CFDataRef data) { int data_file = open(path, O_CREAT|O_WRONLY|O_TRUNC, 0644); write(data_file, CFDataGetBytePtr(data), CFDataGetLength(data)); close(data_file); } -static inline CFMutableArrayRef maa(CFMutableArrayRef array, CFTypeRef a) { + +__unused static inline CFMutableArrayRef maa(CFMutableArrayRef array, CFTypeRef a) { CFMutableArrayRef ma = array; if (!ma) CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); @@ -983,7 +999,6 @@ static inline CFMutableArrayRef maa(CFMutableArrayRef array, CFTypeRef a) { return ma; } - /* Test basic add delete update copy matching stuff. */ static void tests(void) { @@ -1182,9 +1197,12 @@ static void tests(void) ok_status(SecItemDelete(identity_add), "delete encryption identity from keychain"); CFReleaseSafe(identity_add); - CFRelease(self_signed_identity); - CFRelease(retry_get_cert_initial); - CFRelease(server_error); + CFReleaseSafe(self_signed_identity); + CFReleaseSafe(retry_get_cert_initial); + CFReleaseSafe(server_error); + CFReleaseSafe(pended_request); + CFReleaseSafe(issued_certs); + CFReleaseSafe(error_dict); } int si_63_scep(int argc, char *const *argv) diff --git a/sec/Security/Regressions/secitem/si-63-scep.h b/Security/sec/Security/Regressions/secitem/si-63-scep.h similarity index 100% rename from sec/Security/Regressions/secitem/si-63-scep.h rename to Security/sec/Security/Regressions/secitem/si-63-scep.h diff --git a/sec/Security/Regressions/secitem/si-63-scep/getcacert-mdes.h b/Security/sec/Security/Regressions/secitem/si-63-scep/getcacert-mdes.h similarity index 100% rename from sec/Security/Regressions/secitem/si-63-scep/getcacert-mdes.h rename to Security/sec/Security/Regressions/secitem/si-63-scep/getcacert-mdes.h diff --git a/sec/Security/Regressions/secitem/si-63-scep/getcacert-mdesqa.h b/Security/sec/Security/Regressions/secitem/si-63-scep/getcacert-mdesqa.h similarity index 100% rename from sec/Security/Regressions/secitem/si-63-scep/getcacert-mdesqa.h rename to Security/sec/Security/Regressions/secitem/si-63-scep/getcacert-mdesqa.h diff --git a/sec/Security/Regressions/secitem/si-64-ossl-cms.c b/Security/sec/Security/Regressions/secitem/si-64-ossl-cms.c similarity index 85% rename from sec/Security/Regressions/secitem/si-64-ossl-cms.c rename to Security/sec/Security/Regressions/secitem/si-64-ossl-cms.c index bcf008f8..8c3fd1e4 100644 --- a/sec/Security/Regressions/secitem/si-64-ossl-cms.c +++ b/Security/sec/Security/Regressions/secitem/si-64-ossl-cms.c @@ -1,11 +1,26 @@ /* - * si-64-ossl-cms.c - * Security - * - * Created by on 9/28/09. - * Copyright 2009 Apple Inc. All rights reserved. + * Copyright (c) 2009,2012-2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include "si-64-ossl-cms/attached_no_data_signed_data.h" #include "si-64-ossl-cms/attached_signed_data.h" #include "si-64-ossl-cms/detached_content.h" @@ -117,7 +132,7 @@ attached empty: */ #include -static inline void write_data(const char * path, CFDataRef data) +__unused static inline void write_data(const char * path, CFDataRef data) { int data_file = open(path, O_CREAT|O_WRONLY|O_TRUNC, 0644); write(data_file, CFDataGetBytePtr(data), CFDataGetLength(data)); diff --git a/sec/Security/Regressions/secitem/si-64-ossl-cms/attached_no_data_signed_data.h b/Security/sec/Security/Regressions/secitem/si-64-ossl-cms/attached_no_data_signed_data.h similarity index 100% rename from sec/Security/Regressions/secitem/si-64-ossl-cms/attached_no_data_signed_data.h rename to Security/sec/Security/Regressions/secitem/si-64-ossl-cms/attached_no_data_signed_data.h diff --git a/sec/Security/Regressions/secitem/si-64-ossl-cms/attached_signed_data.h b/Security/sec/Security/Regressions/secitem/si-64-ossl-cms/attached_signed_data.h similarity index 100% rename from sec/Security/Regressions/secitem/si-64-ossl-cms/attached_signed_data.h rename to Security/sec/Security/Regressions/secitem/si-64-ossl-cms/attached_signed_data.h diff --git a/sec/Security/Regressions/secitem/si-64-ossl-cms/detached_content.h b/Security/sec/Security/Regressions/secitem/si-64-ossl-cms/detached_content.h similarity index 100% rename from sec/Security/Regressions/secitem/si-64-ossl-cms/detached_content.h rename to Security/sec/Security/Regressions/secitem/si-64-ossl-cms/detached_content.h diff --git a/sec/Security/Regressions/secitem/si-64-ossl-cms/detached_signed_data.h b/Security/sec/Security/Regressions/secitem/si-64-ossl-cms/detached_signed_data.h similarity index 100% rename from sec/Security/Regressions/secitem/si-64-ossl-cms/detached_signed_data.h rename to Security/sec/Security/Regressions/secitem/si-64-ossl-cms/detached_signed_data.h diff --git a/sec/Security/Regressions/secitem/si-64-ossl-cms/privkey.h b/Security/sec/Security/Regressions/secitem/si-64-ossl-cms/privkey.h similarity index 100% rename from sec/Security/Regressions/secitem/si-64-ossl-cms/privkey.h rename to Security/sec/Security/Regressions/secitem/si-64-ossl-cms/privkey.h diff --git a/sec/Security/Regressions/secitem/si-64-ossl-cms/signer.h b/Security/sec/Security/Regressions/secitem/si-64-ossl-cms/signer.h similarity index 100% rename from sec/Security/Regressions/secitem/si-64-ossl-cms/signer.h rename to Security/sec/Security/Regressions/secitem/si-64-ossl-cms/signer.h diff --git a/sec/Security/Regressions/secitem/si-65-cms-cert-policy.c b/Security/sec/Security/Regressions/secitem/si-65-cms-cert-policy.c similarity index 94% rename from sec/Security/Regressions/secitem/si-65-cms-cert-policy.c rename to Security/sec/Security/Regressions/secitem/si-65-cms-cert-policy.c index 3a155285..3a27b583 100644 --- a/sec/Security/Regressions/secitem/si-65-cms-cert-policy.c +++ b/Security/sec/Security/Regressions/secitem/si-65-cms-cert-policy.c @@ -1,11 +1,26 @@ /* - * si-65-cms-cert-policy.c - * regressions - * - * Created by Conrad Sauerwald on 9/28/10. - * Copyright 2010 Apple Inc. All rights reserved. + * Copyright (c) 2010,2012,2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include #include #include diff --git a/sec/Security/Regressions/secitem/si-66-smime.c b/Security/sec/Security/Regressions/secitem/si-66-smime.c similarity index 99% rename from sec/Security/Regressions/secitem/si-66-smime.c rename to Security/sec/Security/Regressions/secitem/si-66-smime.c index 4ea447f7..f5964951 100644 --- a/sec/Security/Regressions/secitem/si-66-smime.c +++ b/Security/sec/Security/Regressions/secitem/si-66-smime.c @@ -1,11 +1,26 @@ /* - * si-66-smime.c - * regressions - * - * Created by Conrad Sauerwald on 9/28/10. - * Copyright 2010 Apple Inc. All rights reserved. + * Copyright (c) 2010,2012-2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include #include #include @@ -2453,6 +2468,7 @@ static void tests(void) int data_file = open("/var/tmp/smime", O_CREAT|O_WRONLY|O_TRUNC, 0644); write(data_file, CFDataGetBytePtr(signed_data), CFDataGetLength(signed_data)); close(data_file); + CFReleaseNull(signed_data); CFReleaseNull(smime_cert); @@ -2499,6 +2515,8 @@ static void tests(void) int data_file = open("/var/tmp/smime", O_CREAT|O_WRONLY|O_TRUNC, 0644); write(data_file, CFDataGetBytePtr(data), CFDataGetLength(data)); close(data_file); +#else + CFReleaseNull(data); #endif msg = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, smime_skid, smime_skid_len, kCFAllocatorNull); diff --git a/sec/Security/Regressions/secitem/si-66-smime/signed-receipt.h b/Security/sec/Security/Regressions/secitem/si-66-smime/signed-receipt.h similarity index 100% rename from sec/Security/Regressions/secitem/si-66-smime/signed-receipt.h rename to Security/sec/Security/Regressions/secitem/si-66-smime/signed-receipt.h diff --git a/Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist.c b/Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist.c new file mode 100644 index 00000000..132d1970 --- /dev/null +++ b/Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "si-67-sectrust-blacklist/Global Trustee.cer.h" +#include "si-67-sectrust-blacklist/login.yahoo.com.1.cer.h" +#include "si-67-sectrust-blacklist/UTN-USERFirst-Hardware.cer.h" +#include "si-67-sectrust-blacklist/login.yahoo.com.2.cer.h" +#include "si-67-sectrust-blacklist/addons.mozilla.org.cer.h" +#include "si-67-sectrust-blacklist/login.yahoo.com.cer.h" +#include "si-67-sectrust-blacklist/login.live.com.cer.h" +#include "si-67-sectrust-blacklist/mail.google.com.cer.h" +#include "si-67-sectrust-blacklist/login.skype.com.cer.h" +#include "si-67-sectrust-blacklist/www.google.com.cer.h" + +#include "Security_regressions.h" + +static void validate_one_cert(uint8_t *data, size_t len, int chain_length, SecTrustResultType trust_result) +{ + SecTrustRef trust; + SecCertificateRef cert; + SecPolicyRef policy = SecPolicyCreateSSL(false, NULL); + CFArrayRef certs; + + isnt(cert = SecCertificateCreateWithBytes(NULL, data, len), + NULL, "create cert"); + certs = CFArrayCreate(NULL, (const void **)&cert, 1, NULL); + ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), + "create trust with single cert"); + //CFDateRef date = CFDateCreate(NULL, 1301008576); + //ok_status(SecTrustSetVerifyDate(trust, date), "set date"); + //CFRelease(date); + + SecTrustResultType trustResult; + ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); + is(SecTrustGetCertificateCount(trust), chain_length, "cert count"); + is_status(trustResult, trust_result, "correct trustResult"); + CFRelease(trust); + CFRelease(policy); + CFRelease(certs); + CFRelease(cert); +} + +static void tests(void) +{ + validate_one_cert(Global_Trustee_cer, sizeof(Global_Trustee_cer), 3, kSecTrustResultFatalTrustFailure); + validate_one_cert(login_yahoo_com_1_cer, sizeof(login_yahoo_com_1_cer), 3, kSecTrustResultFatalTrustFailure); + /* this is the root, which isn't ok for ssl and fails here, but at the + same time it proves that kSecTrustResultFatalTrustFailure isn't + returned for policy failures that aren't blacklisting */ + validate_one_cert(login_yahoo_com_2_cer, sizeof(login_yahoo_com_2_cer), 3, kSecTrustResultFatalTrustFailure); + validate_one_cert(addons_mozilla_org_cer, sizeof(addons_mozilla_org_cer), 3, kSecTrustResultFatalTrustFailure); + validate_one_cert(login_yahoo_com_cer, sizeof(login_yahoo_com_cer), 3, kSecTrustResultFatalTrustFailure); + validate_one_cert(login_live_com_cer, sizeof(login_live_com_cer), 3, kSecTrustResultFatalTrustFailure); + validate_one_cert(mail_google_com_cer, sizeof(mail_google_com_cer), 3, kSecTrustResultFatalTrustFailure); + validate_one_cert(login_skype_com_cer, sizeof(login_skype_com_cer), 3, kSecTrustResultFatalTrustFailure); + validate_one_cert(www_google_com_cer, sizeof(www_google_com_cer), 3, kSecTrustResultFatalTrustFailure); +} + +static int ping_host(char *host_name){ + + struct sockaddr_in pin; + struct hostent *nlp_host; + int sd; + int port; + + port=80; + + while ((nlp_host=gethostbyname(host_name))==0){ + printf("Resolve Error!\n"); + } + + bzero(&pin,sizeof(pin)); + pin.sin_family=AF_INET; + pin.sin_addr.s_addr=htonl(INADDR_ANY); + pin.sin_addr.s_addr=((struct in_addr *)(nlp_host->h_addr))->s_addr; + pin.sin_port=htons(port); + + sd=socket(AF_INET,SOCK_STREAM,0); + + if (connect(sd,(struct sockaddr*)&pin,sizeof(pin))==-1){ + close(sd); + return 0; + } + else{ + close(sd); + return 1; + } +} + +int si_67_sectrust_blacklist(int argc, char *const *argv) +{ + char *hosts[] = { + "EVSecure-ocsp.verisign.com", + "EVIntl-ocsp.verisign.com", + "EVIntl-aia.verisign.com", + "ocsp.comodoca.com", + "crt.comodoca.com", + }; + + int host_cnt = 0; + for (host_cnt = 0; host_cnt < 5; host_cnt ++) + if(ping_host(hosts[host_cnt]) == 0){ + printf("Ping specific server failed, check the network!\n"); + return 0; + } + plan_tests(45); + + tests(); + + return 0; +} diff --git a/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/Global Trustee.cer.h b/Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/Global Trustee.cer.h similarity index 100% rename from sec/Security/Regressions/secitem/si-67-sectrust-blacklist/Global Trustee.cer.h rename to Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/Global Trustee.cer.h diff --git a/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/UTN-USERFirst-Hardware.cer.h b/Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/UTN-USERFirst-Hardware.cer.h similarity index 100% rename from sec/Security/Regressions/secitem/si-67-sectrust-blacklist/UTN-USERFirst-Hardware.cer.h rename to Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/UTN-USERFirst-Hardware.cer.h diff --git a/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/addons.mozilla.org.cer.h b/Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/addons.mozilla.org.cer.h similarity index 100% rename from sec/Security/Regressions/secitem/si-67-sectrust-blacklist/addons.mozilla.org.cer.h rename to Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/addons.mozilla.org.cer.h diff --git a/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/login.live.com.cer.h b/Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/login.live.com.cer.h similarity index 100% rename from sec/Security/Regressions/secitem/si-67-sectrust-blacklist/login.live.com.cer.h rename to Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/login.live.com.cer.h diff --git a/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/login.skype.com.cer.h b/Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/login.skype.com.cer.h similarity index 100% rename from sec/Security/Regressions/secitem/si-67-sectrust-blacklist/login.skype.com.cer.h rename to Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/login.skype.com.cer.h diff --git a/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/login.yahoo.com.1.cer.h b/Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/login.yahoo.com.1.cer.h similarity index 100% rename from sec/Security/Regressions/secitem/si-67-sectrust-blacklist/login.yahoo.com.1.cer.h rename to Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/login.yahoo.com.1.cer.h diff --git a/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/login.yahoo.com.2.cer.h b/Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/login.yahoo.com.2.cer.h similarity index 100% rename from sec/Security/Regressions/secitem/si-67-sectrust-blacklist/login.yahoo.com.2.cer.h rename to Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/login.yahoo.com.2.cer.h diff --git a/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/login.yahoo.com.cer.h b/Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/login.yahoo.com.cer.h similarity index 100% rename from sec/Security/Regressions/secitem/si-67-sectrust-blacklist/login.yahoo.com.cer.h rename to Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/login.yahoo.com.cer.h diff --git a/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/mail.google.com.cer.h b/Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/mail.google.com.cer.h similarity index 100% rename from sec/Security/Regressions/secitem/si-67-sectrust-blacklist/mail.google.com.cer.h rename to Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/mail.google.com.cer.h diff --git a/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/www.google.com.cer.h b/Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/www.google.com.cer.h similarity index 100% rename from sec/Security/Regressions/secitem/si-67-sectrust-blacklist/www.google.com.cer.h rename to Security/sec/Security/Regressions/secitem/si-67-sectrust-blacklist/www.google.com.cer.h diff --git a/sec/Security/Regressions/secitem/si-68-secmatchissuer.c b/Security/sec/Security/Regressions/secitem/si-68-secmatchissuer.c similarity index 89% rename from sec/Security/Regressions/secitem/si-68-secmatchissuer.c rename to Security/sec/Security/Regressions/secitem/si-68-secmatchissuer.c index 093b3b4f..550d55ce 100644 --- a/sec/Security/Regressions/secitem/si-68-secmatchissuer.c +++ b/Security/sec/Security/Regressions/secitem/si-68-secmatchissuer.c @@ -1,9 +1,31 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + // // si-68-secmatchissuer.c // regressions // -// Created by Conrad Sauerwald on 6/18/12. // // #include diff --git a/sec/Security/Regressions/secitem/si-69-keydesc.c b/Security/sec/Security/Regressions/secitem/si-69-keydesc.c similarity index 79% rename from sec/Security/Regressions/secitem/si-69-keydesc.c rename to Security/sec/Security/Regressions/secitem/si-69-keydesc.c index 8a508beb..a30f5581 100644 --- a/sec/Security/Regressions/secitem/si-69-keydesc.c +++ b/Security/sec/Security/Regressions/secitem/si-69-keydesc.c @@ -1,10 +1,26 @@ -// -// si-69-keydesc.c -// Regressions -// -// Created by Michelle Olofson on 1/28/13. -// -// +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include #include @@ -39,9 +55,9 @@ unsigned char ecPubKey[] = { 0x04, 0x01, 0x41, 0x34, 0x87, 0xfd, 0xe1, 0x51, 0x5d, 0x29, 0x12, 0x07, 0xc2, 0x57, 0x54, 0x19, 0xd2, 0xd9, 0x18, 0x95, 0x07, 0x17, 0x8a, 0xf7, 0x2d, 0x2b, 0xf9, 0xbc, 0xe6, 0x1b, 0xe7, 0x81, 0x35, 0x13, 0x5f, 0x1d, 0xfa, 0xed, 0x7e, 0x70, 0x2b, 0xcd, 0x01, 0xa0, 0xaa, 0x7f, 0xe4, 0x0f, 0x4e, 0x19, 0x56, 0xb0, 0x15, 0xfb, 0xd8, 0xc9, 0xe7, 0x48, 0xcf, 0xc7, 0x5e, 0xe8, 0xcc, 0x74, 0x34, 0x61, 0xa5, 0x01, 0x02, 0x67, 0x03, 0x16, 0xce, 0x3d, 0x31, 0x37, 0x9c, 0x0b, 0x03, 0x65, 0x94, 0xaa, 0xd0, 0x1d, 0xa9, 0x5a, 0xe3, 0x0a, 0xf9, 0x82, 0xef, 0x43, 0x75, 0x5b, 0x46, 0x52, 0x6c, 0x0a, 0x02, 0x3f, 0xc3, 0xd3, 0x42, 0x0d, 0xa7, 0x90, 0x8c, 0x4b, 0x15, 0x88, 0x89, 0x24, 0xed, 0x91, 0x0a, 0xa1, 0x20, 0x0d, 0x82, 0xed, 0x87, 0x8c, 0x98, 0x8e, 0xbe, 0xbc, 0xa3, 0xa7, 0xca, 0x50, 0x2d, 0x71, 0x73 }; -const char *rsaKeyDescription = " +#include +#include +#include +#include + +#include "Security_regressions.h" +#include + +/* This is a minimal test case to ensure that the functionality of + * TLF: SecTrust Unification is present + * and working. Needs to be expanded and split up into separate + * test case files in the future. + */ + +/* SecPolicy: new in 7.0 */ +//CFDictionaryRef SecPolicyCopyProperties(SecPolicyRef policyRef) +//OSStatus SecTrustSetPolicies(SecTrustRef trust, CFTypeRef policies) /* (this was SPI in 6.0) */ +//SecPolicyRef SecPolicyCreateRevocation(CFIndex revocationFlags) +//SecPolicyRef SecPolicyCreateWithProperties(CFTypeRef policyIdentifier, CFDictionaryRef properties) + +/* SecTrust new in 7.0 */ +//OSStatus SecTrustCopyPolicies(SecTrustRef trust, CFArrayRef *policies) +//OSStatus SecTrustSetNetworkFetchAllowed(SecTrustRef trust, Boolean allowFetch) +//OSStatus SecTrustGetNetworkFetchAllowed(SecTrustRef trust, Boolean *allowFetch) +//OSStatus SecTrustCopyCustomAnchorCertificates(SecTrustRef trust, CFArrayRef *anchors) +//CFDictionaryRef SecTrustCopyResult(SecTrustRef trust) +//OSStatus SecTrustSetOCSPResponse(SecTrustRef trust, CFTypeRef responseData) + + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc/OU=Internet Operations/CN=xedge2.apple.com + issuer :/C=US/O=Entrust.net/OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Secure Server Certification Authority */ +const uint8_t xedge2_cert[1385]={ +0x30,0x82,0x05,0x65,0x30,0x82,0x04,0xCE,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x46, +0x9C,0xDF,0x96,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05, +0x05,0x00,0x30,0x81,0xC3,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, +0x55,0x53,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x13,0x0B,0x45,0x6E,0x74, +0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x31,0x3B,0x30,0x39,0x06,0x03,0x55,0x04, +0x0B,0x13,0x32,0x77,0x77,0x77,0x2E,0x65,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E, +0x65,0x74,0x2F,0x43,0x50,0x53,0x20,0x69,0x6E,0x63,0x6F,0x72,0x70,0x2E,0x20,0x62, +0x79,0x20,0x72,0x65,0x66,0x2E,0x20,0x28,0x6C,0x69,0x6D,0x69,0x74,0x73,0x20,0x6C, +0x69,0x61,0x62,0x2E,0x29,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x0B,0x13,0x1C, +0x28,0x63,0x29,0x20,0x31,0x39,0x39,0x39,0x20,0x45,0x6E,0x74,0x72,0x75,0x73,0x74, +0x2E,0x6E,0x65,0x74,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65,0x64,0x31,0x3A,0x30,0x38, +0x06,0x03,0x55,0x04,0x03,0x13,0x31,0x45,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E, +0x65,0x74,0x20,0x53,0x65,0x63,0x75,0x72,0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72, +0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, +0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x1E,0x17,0x0D,0x30,0x38,0x30,0x31, +0x32,0x39,0x31,0x38,0x33,0x33,0x31,0x33,0x5A,0x17,0x0D,0x31,0x30,0x30,0x31,0x32, +0x38,0x31,0x39,0x30,0x33,0x31,0x32,0x5A,0x30,0x81,0x83,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,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x0A,0x13,0x09,0x41,0x70,0x70,0x6C, +0x65,0x20,0x49,0x6E,0x63,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04,0x0B,0x13,0x13, +0x49,0x6E,0x74,0x65,0x72,0x6E,0x65,0x74,0x20,0x4F,0x70,0x65,0x72,0x61,0x74,0x69, +0x6F,0x6E,0x73,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x03,0x13,0x10,0x78,0x65, +0x64,0x67,0x65,0x32,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,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,0xC7,0xF3,0xA1,0x0E,0x0E, +0xA4,0xDF,0xC5,0x3F,0x24,0x87,0xC3,0x6E,0xE7,0xD0,0x7C,0x2B,0x5A,0x1C,0xF3,0x67, +0x6C,0x6B,0x56,0x0A,0x95,0xC9,0xE5,0x13,0x28,0x6E,0x16,0x9D,0x4F,0xB1,0x76,0xFB, +0x7D,0x42,0x5B,0x2A,0x7C,0xCC,0x97,0x75,0xAA,0xA6,0xA9,0xDE,0xB2,0xEC,0xEF,0xE2, +0xAB,0x40,0xAE,0x9A,0x23,0xF0,0x6A,0x10,0xB3,0x75,0x27,0xF0,0xF4,0x7D,0x08,0x67, +0x8F,0xCE,0x41,0x24,0x74,0xAA,0x37,0xB6,0xC1,0x32,0x61,0xCF,0x7D,0x1C,0x21,0xCD, +0xCF,0x7C,0x9E,0xE2,0x48,0x03,0x7E,0x78,0xB3,0x86,0x3D,0x06,0x6B,0x39,0xEC,0xC8, +0x73,0x68,0xDB,0xE7,0x5B,0x97,0xF4,0xF9,0xA3,0xE7,0xFB,0x81,0x2E,0x4D,0x0B,0x3F, +0xA9,0xCA,0xDE,0x32,0x26,0xF3,0xF0,0x97,0x72,0x65,0xAB,0x02,0x03,0x01,0x00,0x01, +0xA3,0x82,0x02,0xA2,0x30,0x82,0x02,0x9E,0x30,0x0B,0x06,0x03,0x55,0x1D,0x0F,0x04, +0x04,0x03,0x02,0x05,0xA0,0x30,0x2B,0x06,0x03,0x55,0x1D,0x10,0x04,0x24,0x30,0x22, +0x80,0x0F,0x32,0x30,0x30,0x38,0x30,0x31,0x32,0x39,0x31,0x38,0x33,0x33,0x31,0x33, +0x5A,0x81,0x0F,0x32,0x30,0x31,0x30,0x30,0x31,0x32,0x38,0x31,0x39,0x30,0x33,0x31, +0x32,0x5A,0x30,0x11,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x01,0x04, +0x04,0x03,0x02,0x06,0x40,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A, +0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x82,0x01,0x68,0x06,0x03, +0x55,0x1D,0x20,0x04,0x82,0x01,0x5F,0x30,0x82,0x01,0x5B,0x30,0x82,0x01,0x57,0x06, +0x09,0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x4B,0x02,0x30,0x82,0x01,0x48,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,0x65,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E, +0x65,0x74,0x2F,0x63,0x70,0x73,0x30,0x82,0x01,0x1C,0x06,0x08,0x2B,0x06,0x01,0x05, +0x05,0x07,0x02,0x02,0x30,0x82,0x01,0x0E,0x1A,0x82,0x01,0x0A,0x54,0x68,0x65,0x20, +0x45,0x6E,0x74,0x72,0x75,0x73,0x74,0x20,0x53,0x53,0x4C,0x20,0x57,0x65,0x62,0x20, +0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61, +0x74,0x69,0x6F,0x6E,0x20,0x50,0x72,0x61,0x63,0x74,0x69,0x63,0x65,0x20,0x53,0x74, +0x61,0x74,0x65,0x6D,0x65,0x6E,0x74,0x20,0x28,0x43,0x50,0x53,0x29,0x20,0x61,0x76, +0x61,0x69,0x6C,0x61,0x62,0x6C,0x65,0x20,0x61,0x74,0x20,0x77,0x77,0x77,0x2E,0x65, +0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x2F,0x63,0x70,0x73,0x20,0x20, +0x69,0x73,0x20,0x68,0x65,0x72,0x65,0x62,0x79,0x20,0x69,0x6E,0x63,0x6F,0x72,0x70, +0x6F,0x72,0x61,0x74,0x65,0x64,0x20,0x69,0x6E,0x74,0x6F,0x20,0x79,0x6F,0x75,0x72, +0x20,0x75,0x73,0x65,0x20,0x6F,0x72,0x20,0x72,0x65,0x6C,0x69,0x61,0x6E,0x63,0x65, +0x20,0x6F,0x6E,0x20,0x74,0x68,0x69,0x73,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69, +0x63,0x61,0x74,0x65,0x2E,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x43,0x50,0x53,0x20, +0x63,0x6F,0x6E,0x74,0x61,0x69,0x6E,0x73,0x20,0x6C,0x69,0x6D,0x69,0x74,0x61,0x74, +0x69,0x6F,0x6E,0x73,0x20,0x6F,0x6E,0x20,0x77,0x61,0x72,0x72,0x61,0x6E,0x74,0x69, +0x65,0x73,0x20,0x61,0x6E,0x64,0x20,0x6C,0x69,0x61,0x62,0x69,0x6C,0x69,0x74,0x69, +0x65,0x73,0x2E,0x20,0x43,0x6F,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x28,0x63, +0x29,0x20,0x32,0x30,0x30,0x32,0x20,0x45,0x6E,0x74,0x72,0x75,0x73,0x74,0x20,0x4C, +0x69,0x6D,0x69,0x74,0x65,0x64,0x30,0x33,0x06,0x03,0x55,0x1D,0x1F,0x04,0x2C,0x30, +0x2A,0x30,0x28,0xA0,0x26,0xA0,0x24,0x86,0x22,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, +0x63,0x72,0x6C,0x2E,0x65,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x2F, +0x73,0x65,0x72,0x76,0x65,0x72,0x31,0x2E,0x63,0x72,0x6C,0x30,0x33,0x06,0x08,0x2B, +0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x27,0x30,0x25,0x30,0x23,0x06,0x08,0x2B, +0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x17,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, +0x6F,0x63,0x73,0x70,0x2E,0x65,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74, +0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xF0,0x17,0x62, +0x13,0x55,0x3D,0xB3,0xFF,0x0A,0x00,0x6B,0xFB,0x50,0x84,0x97,0xF3,0xED,0x62,0xD0, +0x1A,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x2D,0xEF,0xD9,0xAF, +0x1A,0x89,0x40,0x53,0x75,0x48,0x26,0x59,0x2F,0xEC,0x11,0x18,0xC0,0xD1,0x7A,0x34, +0x30,0x09,0x06,0x03,0x55,0x1D,0x13,0x04,0x02,0x30,0x00,0x30,0x19,0x06,0x09,0x2A, +0x86,0x48,0x86,0xF6,0x7D,0x07,0x41,0x00,0x04,0x0C,0x30,0x0A,0x1B,0x04,0x56,0x37, +0x2E,0x31,0x03,0x02,0x03,0x28,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, +0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0x77,0x33,0x2A,0x69,0x45,0x5A,0xB2, +0xF5,0x74,0xF7,0xDF,0xC7,0x08,0x85,0x86,0x88,0x98,0x41,0x7F,0x57,0x49,0x01,0xBA, +0x13,0x21,0x40,0xD0,0x0A,0x5C,0xA7,0x37,0xDF,0xB3,0x7E,0xF8,0xED,0x04,0x63,0xC3, +0xE8,0x0F,0xA0,0xE5,0xC4,0x4F,0x3A,0x90,0xE4,0x87,0x5F,0xEC,0xDB,0x65,0x8B,0x6E, +0x88,0x6E,0x6E,0xE4,0xBC,0x6A,0x7E,0x37,0x47,0x04,0xFF,0x09,0xC6,0x70,0xE1,0x65, +0x8F,0xE3,0xE9,0x60,0xEB,0xE8,0x8E,0x29,0xAE,0xF9,0x81,0xCA,0x9A,0x97,0x3C,0x6F, +0x7C,0xFA,0xA8,0x49,0xB4,0x33,0x76,0x9C,0x65,0x92,0x12,0xF6,0x7F,0x6A,0x62,0x84, +0x29,0x5F,0x14,0x26,0x6E,0x07,0x6F,0x5C,0xB5,0x7C,0x21,0x64,0x7C,0xD9,0x93,0xF4, +0x9C,0xC8,0xE7,0xEC,0xC6,0xAC,0x13,0xC4,0xF0 +}; + +const uint8_t _entrust1024RootCA[1244]={ + 0x30,0x82,0x04,0xD8,0x30,0x82,0x04,0x41,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x37, + 0x4A,0xD2,0x43,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05, + 0x05,0x00,0x30,0x81,0xC3,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x13,0x0B,0x45,0x6E,0x74, + 0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x31,0x3B,0x30,0x39,0x06,0x03,0x55,0x04, + 0x0B,0x13,0x32,0x77,0x77,0x77,0x2E,0x65,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E, + 0x65,0x74,0x2F,0x43,0x50,0x53,0x20,0x69,0x6E,0x63,0x6F,0x72,0x70,0x2E,0x20,0x62, + 0x79,0x20,0x72,0x65,0x66,0x2E,0x20,0x28,0x6C,0x69,0x6D,0x69,0x74,0x73,0x20,0x6C, + 0x69,0x61,0x62,0x2E,0x29,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x0B,0x13,0x1C, + 0x28,0x63,0x29,0x20,0x31,0x39,0x39,0x39,0x20,0x45,0x6E,0x74,0x72,0x75,0x73,0x74, + 0x2E,0x6E,0x65,0x74,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65,0x64,0x31,0x3A,0x30,0x38, + 0x06,0x03,0x55,0x04,0x03,0x13,0x31,0x45,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E, + 0x65,0x74,0x20,0x53,0x65,0x63,0x75,0x72,0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72, + 0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, + 0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x1E,0x17,0x0D,0x39,0x39,0x30,0x35, + 0x32,0x35,0x31,0x36,0x30,0x39,0x34,0x30,0x5A,0x17,0x0D,0x31,0x39,0x30,0x35,0x32, + 0x35,0x31,0x36,0x33,0x39,0x34,0x30,0x5A,0x30,0x81,0xC3,0x31,0x0B,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04, + 0x0A,0x13,0x0B,0x45,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x31,0x3B, + 0x30,0x39,0x06,0x03,0x55,0x04,0x0B,0x13,0x32,0x77,0x77,0x77,0x2E,0x65,0x6E,0x74, + 0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x2F,0x43,0x50,0x53,0x20,0x69,0x6E,0x63, + 0x6F,0x72,0x70,0x2E,0x20,0x62,0x79,0x20,0x72,0x65,0x66,0x2E,0x20,0x28,0x6C,0x69, + 0x6D,0x69,0x74,0x73,0x20,0x6C,0x69,0x61,0x62,0x2E,0x29,0x31,0x25,0x30,0x23,0x06, + 0x03,0x55,0x04,0x0B,0x13,0x1C,0x28,0x63,0x29,0x20,0x31,0x39,0x39,0x39,0x20,0x45, + 0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x20,0x4C,0x69,0x6D,0x69,0x74, + 0x65,0x64,0x31,0x3A,0x30,0x38,0x06,0x03,0x55,0x04,0x03,0x13,0x31,0x45,0x6E,0x74, + 0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x20,0x53,0x65,0x63,0x75,0x72,0x65,0x20, + 0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61, + 0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x81, + 0x9D,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00, + 0x03,0x81,0x8B,0x00,0x30,0x81,0x87,0x02,0x81,0x81,0x00,0xCD,0x28,0x83,0x34,0x54, + 0x1B,0x89,0xF3,0x0F,0xAF,0x37,0x91,0x31,0xFF,0xAF,0x31,0x60,0xC9,0xA8,0xE8,0xB2, + 0x10,0x68,0xED,0x9F,0xE7,0x93,0x36,0xF1,0x0A,0x64,0xBB,0x47,0xF5,0x04,0x17,0x3F, + 0x23,0x47,0x4D,0xC5,0x27,0x19,0x81,0x26,0x0C,0x54,0x72,0x0D,0x88,0x2D,0xD9,0x1F, + 0x9A,0x12,0x9F,0xBC,0xB3,0x71,0xD3,0x80,0x19,0x3F,0x47,0x66,0x7B,0x8C,0x35,0x28, + 0xD2,0xB9,0x0A,0xDF,0x24,0xDA,0x9C,0xD6,0x50,0x79,0x81,0x7A,0x5A,0xD3,0x37,0xF7, + 0xC2,0x4A,0xD8,0x29,0x92,0x26,0x64,0xD1,0xE4,0x98,0x6C,0x3A,0x00,0x8A,0xF5,0x34, + 0x9B,0x65,0xF8,0xED,0xE3,0x10,0xFF,0xFD,0xB8,0x49,0x58,0xDC,0xA0,0xDE,0x82,0x39, + 0x6B,0x81,0xB1,0x16,0x19,0x61,0xB9,0x54,0xB6,0xE6,0x43,0x02,0x01,0x03,0xA3,0x82, + 0x01,0xD7,0x30,0x82,0x01,0xD3,0x30,0x11,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xF8, + 0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x00,0x07,0x30,0x82,0x01,0x19,0x06,0x03,0x55, + 0x1D,0x1F,0x04,0x82,0x01,0x10,0x30,0x82,0x01,0x0C,0x30,0x81,0xDE,0xA0,0x81,0xDB, + 0xA0,0x81,0xD8,0xA4,0x81,0xD5,0x30,0x81,0xD2,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x13, + 0x0B,0x45,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x31,0x3B,0x30,0x39, + 0x06,0x03,0x55,0x04,0x0B,0x13,0x32,0x77,0x77,0x77,0x2E,0x65,0x6E,0x74,0x72,0x75, + 0x73,0x74,0x2E,0x6E,0x65,0x74,0x2F,0x43,0x50,0x53,0x20,0x69,0x6E,0x63,0x6F,0x72, + 0x70,0x2E,0x20,0x62,0x79,0x20,0x72,0x65,0x66,0x2E,0x20,0x28,0x6C,0x69,0x6D,0x69, + 0x74,0x73,0x20,0x6C,0x69,0x61,0x62,0x2E,0x29,0x31,0x25,0x30,0x23,0x06,0x03,0x55, + 0x04,0x0B,0x13,0x1C,0x28,0x63,0x29,0x20,0x31,0x39,0x39,0x39,0x20,0x45,0x6E,0x74, + 0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65,0x64, + 0x31,0x3A,0x30,0x38,0x06,0x03,0x55,0x04,0x03,0x13,0x31,0x45,0x6E,0x74,0x72,0x75, + 0x73,0x74,0x2E,0x6E,0x65,0x74,0x20,0x53,0x65,0x63,0x75,0x72,0x65,0x20,0x53,0x65, + 0x72,0x76,0x65,0x72,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,0x0D,0x30,0x0B, + 0x06,0x03,0x55,0x04,0x03,0x13,0x04,0x43,0x52,0x4C,0x31,0x30,0x29,0xA0,0x27,0xA0, + 0x25,0x86,0x23,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x65,0x6E, + 0x74,0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x2F,0x43,0x52,0x4C,0x2F,0x6E,0x65, + 0x74,0x31,0x2E,0x63,0x72,0x6C,0x30,0x2B,0x06,0x03,0x55,0x1D,0x10,0x04,0x24,0x30, + 0x22,0x80,0x0F,0x31,0x39,0x39,0x39,0x30,0x35,0x32,0x35,0x31,0x36,0x30,0x39,0x34, + 0x30,0x5A,0x81,0x0F,0x32,0x30,0x31,0x39,0x30,0x35,0x32,0x35,0x31,0x36,0x30,0x39, + 0x34,0x30,0x5A,0x30,0x0B,0x06,0x03,0x55,0x1D,0x0F,0x04,0x04,0x03,0x02,0x01,0x06, + 0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xF0,0x17,0x62, + 0x13,0x55,0x3D,0xB3,0xFF,0x0A,0x00,0x6B,0xFB,0x50,0x84,0x97,0xF3,0xED,0x62,0xD0, + 0x1A,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xF0,0x17,0x62,0x13, + 0x55,0x3D,0xB3,0xFF,0x0A,0x00,0x6B,0xFB,0x50,0x84,0x97,0xF3,0xED,0x62,0xD0,0x1A, + 0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x19, + 0x06,0x09,0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x41,0x00,0x04,0x0C,0x30,0x0A,0x1B, + 0x04,0x56,0x34,0x2E,0x30,0x03,0x02,0x04,0x90,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0x90,0xDC,0x30,0x02, + 0xFA,0x64,0x74,0xC2,0xA7,0x0A,0xA5,0x7C,0x21,0x8D,0x34,0x17,0xA8,0xFB,0x47,0x0E, + 0xFF,0x25,0x7C,0x8D,0x13,0x0A,0xFB,0xE4,0x98,0xB5,0xEF,0x8C,0xF8,0xC5,0x10,0x0D, + 0xF7,0x92,0xBE,0xF1,0xC3,0xD5,0xD5,0x95,0x6A,0x04,0xBB,0x2C,0xCE,0x26,0x36,0x65, + 0xC8,0x31,0xC6,0xE7,0xEE,0x3F,0xE3,0x57,0x75,0x84,0x7A,0x11,0xEF,0x46,0x4F,0x18, + 0xF4,0xD3,0x98,0xBB,0xA8,0x87,0x32,0xBA,0x72,0xF6,0x3C,0xE2,0x3D,0x9F,0xD7,0x1D, + 0xD9,0xC3,0x60,0x43,0x8C,0x58,0x0E,0x22,0x96,0x2F,0x62,0xA3,0x2C,0x1F,0xBA,0xAD, + 0x05,0xEF,0xAB,0x32,0x78,0x87,0xA0,0x54,0x73,0x19,0xB5,0x5C,0x05,0xF9,0x52,0x3E, + 0x6D,0x2D,0x45,0x0B,0xF7,0x0A,0x93,0xEA,0xED,0x06,0xF9,0xB2, +}; + + +static void tests(void) +{ + SecTrustResultType trustResult; + SecTrustRef trust = NULL; + SecPolicyRef policy = NULL; + CFArrayRef certs = NULL; + CFDateRef date = NULL; + + const void *cert_xedge2; + isnt(cert_xedge2 = SecCertificateCreateWithBytes(NULL, xedge2_cert, + sizeof(xedge2_cert)), NULL, "create cert_xedge2"); + certs = CFArrayCreate(NULL, &cert_xedge2, 1, NULL); + + bool server = true; + policy = SecPolicyCreateSSL(server, CFSTR("xedge.apple.com")); // deliberate hostname mismatch + ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), + "create trust for ssl server xedge.apple.com"); + CFReleaseSafe(certs); + date = CFDateCreate(NULL, 252288000.0); /* Jan 1st 2009 */ + ok_status(SecTrustSetVerifyDate(trust, date), "set trust date to Jan 1st 2009"); + + /* This test uses a root which is no longer in our trust store, + * so we need explicitly set it as a trusted anchor + */ + SecCertificateRef _root; + isnt(_root = SecCertificateCreateWithBytes(NULL, _entrust1024RootCA, sizeof(_entrust1024RootCA)), + NULL, "create root"); + const void *v_roots[] = { _root }; + CFArrayRef _anchors; + isnt(_anchors = CFArrayCreate(NULL, v_roots, array_size(v_roots), NULL), + NULL, "create anchors"); + SecTrustSetAnchorCertificates(trust, _anchors); + + ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate xedge trust"); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure, + "trust is kSecTrustResultRecoverableTrustFailure (hostname mismatch)"); + + /* Test SecPolicyCreateRevocation */ + { + /* FIXME need to do more than just call the function, but it's a start */ + SecPolicyRef revocation = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod); + isnt(revocation, NULL, "create revocation policy"); + CFReleaseSafe(revocation); + } + + /* Test SecTrustCopyPolicies */ + { + CFArrayRef policies = NULL; + ok_status(SecTrustCopyPolicies(trust, &policies), "copy policies"); + is((policies && (CFArrayGetCount(policies) > 0)), true, "non-empty policies"); + CFReleaseSafe(policies); + } + + /* Test SecTrustSetNetworkFetchAllowed */ + { + Boolean curAllow, allow; + ok_status(SecTrustGetNetworkFetchAllowed(trust, &curAllow)); + allow = !curAllow; /* flip it and see if the setting sticks */ + ok_status(SecTrustSetNetworkFetchAllowed(trust, allow)); + ok_status(SecTrustGetNetworkFetchAllowed(trust, &curAllow)); + is((allow == curAllow), true, "network fetch toggle"); + } + + /* Test setting OCSP response data */ + { + CFDataRef resp = (CFDataRef) CFDataCreateMutable(NULL, 0); + /* FIXME: use actual OCSPResponse DER blob */ + CFDataIncreaseLength((CFMutableDataRef)resp, 64); /* arbitrary length, zero-filled data */ + + is_status(SecTrustSetOCSPResponse(NULL, resp), errSecParam, "SecTrustSetOCSPResponse param 1 check OK"); + is_status(SecTrustSetOCSPResponse(trust, NULL), errSecSuccess, "SecTrustSetOCSPResponse param 2 check OK"); + is_status(SecTrustSetOCSPResponse(trust, resp), errSecSuccess, "SecTrustSetOCSPResponse OK"); + CFReleaseSafe(resp); + } + + /* Test creation of a policy via SecPolicyCreateWithProperties */ + CFReleaseNull(policy); + { + const void *keys[] = { kSecPolicyName, kSecPolicyClient }; + const void *values[] = { CFSTR("xedge2.apple.com"), kCFBooleanFalse }; + CFDictionaryRef properties = CFDictionaryCreate(NULL, keys, values, + array_size(keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + policy = SecPolicyCreateWithProperties(kSecPolicyAppleSSL, properties); + isnt(policy, NULL, "SecPolicyCreateWithProperties"); + CFReleaseSafe(properties); + } + + /* Test introspection of a policy's properties via SecPolicyCopyProperties */ + { + CFDictionaryRef properties = NULL; + isnt(properties = SecPolicyCopyProperties(policy), NULL, "copy policy properties"); + CFTypeRef value = NULL; + is(CFDictionaryGetValueIfPresent(properties, kSecPolicyName, (const void **)&value) && + kCFCompareEqualTo == CFStringCompare((CFStringRef)value, CFSTR("xedge2.apple.com"), 0), + true, "has policy name"); + is(CFDictionaryGetValueIfPresent(properties, kSecPolicyOid, (const void **)&value) && + CFEqual(value, kSecPolicyAppleSSL) , true, "has SSL policy"); + CFReleaseSafe(properties); + } + /* Test setting new policy on a trust via SecTrustSetPolicies */ + ok_status(SecTrustSetPolicies(trust, policy)); + /* Evaluation should now succeed, since our new policy has the correct hostname */ + ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate xedge2 trust"); + is_status(trustResult, kSecTrustResultUnspecified, + "trust is kSecTrustResultUnspecified"); + + /* Make sure we can get the results */ + { + CFDictionaryRef results = NULL; + SecTrustResultType anotherResult = kSecTrustResultInvalid; + ok_status(SecTrustGetTrustResult(trust, &anotherResult), "get trust result"); + is_status(trustResult, anotherResult, "trust is kSecTrustResultUnspecified"); + + isnt(results = SecTrustCopyResult(trust), NULL, "copy trust results"); + CFReleaseSafe(results); + } + + CFReleaseSafe(trust); + CFReleaseSafe(policy); + CFReleaseSafe(date); + CFReleaseSafe(cert_xedge2); + + CFReleaseSafe(_root); + CFReleaseSafe(_anchors); +} + +int si_70_sectrust_unified(int argc, char *const *argv) +{ + plan_tests(27); + tests(); + + return 0; +} diff --git a/Security/sec/Security/Regressions/secitem/si-71-mobile-store-policy.c b/Security/sec/Security/Regressions/secitem/si-71-mobile-store-policy.c new file mode 100644 index 00000000..f7314c5e --- /dev/null +++ b/Security/sec/Security/Regressions/secitem/si-71-mobile-store-policy.c @@ -0,0 +1,575 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Security_regressions.h" + +//#if defined(NO_SERVER) && NO_SERVER == 1 + +__unused static const uint8_t kDemoContentSigningCert[] = { + 0x30, 0x82, 0x04, 0x1a, 0x30, 0x82, 0x03, 0x02, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x47, + 0x62, 0x58, 0xaa, 0x2c, 0xdd, 0x90, 0xc1, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x87, 0x31, 0x3b, 0x30, 0x39, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x32, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, + 0x20, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x32, 0x20, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, + 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x36, 0x30, 0x34, 0x32, 0x31, 0x34, 0x37, 0x31, 0x37, + 0x5a, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x36, 0x30, 0x33, 0x32, 0x31, 0x34, 0x37, 0x31, 0x37, 0x5a, + 0x30, 0x53, 0x31, 0x1d, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x14, 0x44, 0x65, 0x6d, + 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, + 0x67, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x07, 0x43, 0x6f, 0x72, 0x65, + 0x20, 0x4f, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, + 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 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, 0xaf, 0x2a, 0xac, 0x4b, 0x91, 0x1e, 0x4d, 0x9f, 0x1d, 0x23, + 0xf3, 0xff, 0x1c, 0xbe, 0x87, 0xbe, 0x3e, 0x2a, 0x0f, 0x35, 0xf4, 0xad, 0x80, 0x01, 0xc3, 0xf6, + 0x6b, 0x12, 0xc4, 0xfa, 0x0f, 0xf5, 0xbc, 0xc0, 0x79, 0x76, 0xad, 0x77, 0xb1, 0x8d, 0xdc, 0xe7, + 0xa0, 0x8a, 0xe0, 0x6a, 0xa3, 0xdb, 0x24, 0xb6, 0x0b, 0xa5, 0x29, 0x13, 0xe0, 0xd4, 0x96, 0xc7, + 0x1e, 0xee, 0x9b, 0x56, 0x63, 0xdd, 0xab, 0x9b, 0x4e, 0x7d, 0x09, 0xa7, 0x3f, 0xf9, 0xec, 0x96, + 0xcb, 0x88, 0x62, 0x91, 0xfe, 0xb8, 0x10, 0xe4, 0x40, 0x10, 0xb5, 0x34, 0x8a, 0x8e, 0x9a, 0x28, + 0x16, 0xc3, 0x8e, 0x06, 0xda, 0x32, 0x04, 0x64, 0x60, 0x3b, 0xae, 0x70, 0x24, 0xb0, 0xcc, 0x6c, + 0x76, 0x69, 0xb3, 0x52, 0x8f, 0x9c, 0x7a, 0xfb, 0x68, 0x55, 0x88, 0x2f, 0xd8, 0x18, 0xe0, 0x51, + 0x43, 0xdb, 0x91, 0x9f, 0x10, 0xcf, 0xd8, 0x93, 0x6e, 0x5d, 0xef, 0x90, 0xac, 0x47, 0x56, 0xf7, + 0x32, 0xd3, 0xf0, 0xb4, 0x9d, 0x68, 0x94, 0xdd, 0x4f, 0xf9, 0x5a, 0xb4, 0x9a, 0x81, 0xf8, 0xef, + 0xae, 0xd8, 0x27, 0x4d, 0xec, 0xc5, 0x7d, 0xc2, 0xfe, 0x80, 0x23, 0x4d, 0x13, 0xc9, 0x90, 0x5a, + 0x91, 0x86, 0x30, 0x42, 0x7d, 0x38, 0xda, 0x17, 0xa8, 0x46, 0x3e, 0x76, 0x8c, 0xca, 0x5e, 0x20, + 0x1d, 0x3b, 0x85, 0xda, 0x87, 0x9d, 0xf1, 0xc7, 0x1d, 0x3c, 0x13, 0x4a, 0x56, 0xd4, 0x23, 0x52, + 0x96, 0x6b, 0xb8, 0x99, 0x79, 0x03, 0x88, 0xbd, 0xf0, 0xf2, 0x28, 0x79, 0x1b, 0xe7, 0x8e, 0xfc, + 0xd0, 0x30, 0xf3, 0x0b, 0x3e, 0x15, 0xff, 0x20, 0x5c, 0x42, 0x67, 0x7e, 0x0e, 0x52, 0x86, 0x50, + 0xa0, 0x36, 0xb8, 0xc3, 0xee, 0x3d, 0xd8, 0xd6, 0x77, 0x15, 0xb7, 0x8f, 0xed, 0xf6, 0x42, 0xe4, + 0xfc, 0x52, 0xf6, 0x45, 0x67, 0x41, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xbc, 0x30, 0x81, + 0xb9, 0x30, 0x3e, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x32, 0x30, + 0x30, 0x30, 0x2e, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x22, 0x68, + 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x30, 0x34, 0x2d, 0x61, 0x73, 0x69, 0x30, + 0x32, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x55, 0xac, 0xda, 0x4b, + 0xad, 0xf1, 0xe8, 0xe4, 0x2f, 0x72, 0xc2, 0x02, 0x2b, 0xaa, 0x01, 0x23, 0x9c, 0x96, 0x86, 0xdb, + 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, 0x12, 0x75, 0x7c, 0x47, 0x92, + 0xfd, 0x83, 0xe3, 0xbe, 0x2e, 0xfc, 0x59, 0x7f, 0x67, 0x43, 0x81, 0x35, 0x10, 0x45, 0xec, 0x30, + 0x19, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x01, 0x01, 0xff, 0x04, 0x0f, 0x30, 0x0d, 0x30, 0x0b, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, 0x0c, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, + 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x27, 0x50, + 0xf8, 0x85, 0xe0, 0x6a, 0xf6, 0x74, 0x26, 0xcb, 0x5a, 0x23, 0xef, 0xd8, 0x32, 0xa0, 0x87, 0xf0, + 0x01, 0x29, 0x1c, 0x64, 0x84, 0x9e, 0xc6, 0x3b, 0xd7, 0x9e, 0x40, 0x8b, 0x0a, 0x8c, 0x9d, 0xd5, + 0x9b, 0x77, 0xc6, 0x5c, 0xe6, 0x52, 0xfb, 0x5b, 0x41, 0x2b, 0xbb, 0x8c, 0x24, 0xd5, 0xaf, 0xa1, + 0xab, 0x2b, 0xda, 0x3e, 0x11, 0x6b, 0x51, 0xe5, 0xc8, 0xb9, 0xf7, 0x1b, 0x0c, 0x89, 0x6e, 0x29, + 0x1a, 0x88, 0x24, 0xf9, 0x03, 0x2d, 0x46, 0x14, 0x07, 0xff, 0x3f, 0xd2, 0x2b, 0x87, 0x9b, 0xdb, + 0x5c, 0x06, 0x4a, 0x20, 0x4d, 0xf6, 0x33, 0xb1, 0x06, 0x93, 0x87, 0x27, 0x5c, 0x93, 0xca, 0xf6, + 0x81, 0x79, 0x71, 0x82, 0x1b, 0x88, 0x1d, 0x5a, 0x67, 0xc6, 0x2c, 0xd7, 0x68, 0x69, 0xbb, 0x07, + 0x1d, 0x12, 0xae, 0x78, 0x4c, 0xfa, 0x4e, 0xc5, 0x80, 0x5c, 0x2d, 0xd4, 0xb0, 0xcf, 0x71, 0x64, + 0x9e, 0xf8, 0xf3, 0x99, 0xd4, 0xd9, 0xdb, 0xbf, 0xd7, 0xb8, 0x97, 0x24, 0x3f, 0x34, 0x19, 0x52, + 0x73, 0xac, 0xca, 0x31, 0xac, 0x0d, 0xb5, 0x72, 0x11, 0x2d, 0x03, 0x7b, 0xce, 0xf6, 0x1e, 0x84, + 0x09, 0x3b, 0x47, 0xa0, 0x6a, 0xd6, 0x54, 0x60, 0x6d, 0x76, 0x6d, 0x02, 0xbb, 0xa8, 0x69, 0xa8, + 0x58, 0xb5, 0xe2, 0x34, 0xdb, 0x8d, 0xb2, 0x96, 0x17, 0x47, 0x6d, 0xbc, 0xe9, 0xc6, 0xc9, 0xae, + 0xc0, 0x54, 0xcf, 0x98, 0xc9, 0xea, 0x92, 0x69, 0x7f, 0x92, 0x82, 0x19, 0x63, 0x45, 0x5b, 0xeb, + 0x85, 0x0b, 0xaa, 0x7e, 0x4a, 0x77, 0xb4, 0xf9, 0x45, 0xe8, 0x0e, 0x1e, 0x1f, 0xab, 0x1c, 0x86, + 0x59, 0xa8, 0x82, 0x1e, 0x73, 0x86, 0x44, 0xfc, 0x67, 0x2a, 0x71, 0xeb, 0xb9, 0x9e, 0xd0, 0x28, + 0xd7, 0xb1, 0xef, 0xa3, 0x8c, 0x0d, 0x18, 0xd4, 0x8c, 0x1c, 0xb3, 0x0e, 0xba, 0x30 +}; + +__unused static const uint8_t kTestDemoContentSigningCert[] = { + 0x30, 0x82, 0x04, 0x20, 0x30, 0x82, 0x03, 0x08, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x75, + 0x93, 0x8a, 0xaa, 0xe6, 0x6e, 0x3c, 0x5a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x87, 0x31, 0x3b, 0x30, 0x39, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x32, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, + 0x20, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x32, 0x20, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, + 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x36, 0x30, 0x34, 0x30, 0x30, 0x30, 0x32, 0x35, 0x32, + 0x5a, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x36, 0x30, 0x33, 0x30, 0x30, 0x30, 0x32, 0x35, 0x32, 0x5a, + 0x30, 0x58, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x19, 0x54, 0x65, 0x73, + 0x74, 0x20, 0x44, 0x65, 0x6d, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x53, + 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, + 0x07, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x4f, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 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, 0xac, 0xc5, 0x87, 0x0d, 0x3b, + 0x14, 0xba, 0x87, 0x63, 0x3d, 0xc9, 0x8d, 0xc1, 0x3a, 0xa9, 0x71, 0x14, 0x30, 0x6b, 0x64, 0x58, + 0x35, 0xb2, 0xff, 0xcf, 0xe1, 0xe1, 0x5c, 0xa8, 0x5d, 0x99, 0xed, 0x11, 0x53, 0xf5, 0x6f, 0x92, + 0x39, 0x28, 0x5a, 0x0f, 0x76, 0x86, 0x40, 0x44, 0x6a, 0x7b, 0x23, 0x05, 0x50, 0xfd, 0x1b, 0x29, + 0xd9, 0x83, 0xfe, 0x0b, 0x65, 0xc6, 0x35, 0x8c, 0x69, 0x4e, 0x93, 0xa3, 0x32, 0x74, 0x18, 0xd4, + 0x06, 0xaf, 0xe5, 0x74, 0xb9, 0x63, 0x89, 0x41, 0x25, 0x2f, 0x15, 0xb6, 0x71, 0x45, 0x02, 0x5e, + 0x71, 0x11, 0xec, 0xea, 0xb8, 0x3a, 0x3d, 0xf2, 0x87, 0x2b, 0x71, 0xb8, 0x7e, 0xc8, 0xc7, 0x06, + 0x12, 0x87, 0x21, 0x61, 0x2f, 0xeb, 0x33, 0x44, 0xe1, 0x3e, 0xa7, 0x77, 0x6a, 0xfe, 0x5d, 0xee, + 0x4c, 0x77, 0x57, 0x74, 0xf7, 0x64, 0x2b, 0x6f, 0x12, 0x1b, 0x0e, 0xec, 0x49, 0x41, 0x81, 0x93, + 0x6b, 0xf9, 0x3b, 0x4e, 0x83, 0x53, 0xd7, 0x05, 0xe0, 0x29, 0x78, 0xf2, 0xd3, 0xe5, 0x81, 0x6f, + 0x47, 0xd1, 0xc8, 0xae, 0xb3, 0x22, 0xa9, 0x29, 0x61, 0xe2, 0x36, 0x26, 0xb9, 0x0d, 0x9d, 0x23, + 0x90, 0x45, 0x8b, 0x42, 0xbc, 0x8b, 0x60, 0xd5, 0xd2, 0x56, 0xc6, 0x09, 0xfd, 0x45, 0xff, 0x8c, + 0x54, 0x69, 0x74, 0x81, 0x90, 0x7a, 0x31, 0x6f, 0xf0, 0x16, 0x4c, 0xef, 0x1c, 0xa9, 0x97, 0xc9, + 0x4e, 0xfe, 0x7d, 0x87, 0x7a, 0x47, 0x3f, 0xa5, 0xc8, 0x20, 0xd3, 0x4a, 0xe2, 0xf3, 0xf6, 0x3a, + 0xf1, 0xef, 0x24, 0x5e, 0x35, 0xc8, 0xdf, 0x7b, 0x12, 0xda, 0xcc, 0xef, 0xbb, 0xf2, 0xfa, 0x28, + 0xf6, 0x38, 0x57, 0xcf, 0x41, 0xd6, 0x43, 0x21, 0x62, 0xc6, 0xa3, 0x3f, 0xf5, 0xd1, 0x86, 0x41, + 0x42, 0xb6, 0x69, 0xca, 0xb0, 0x8a, 0xba, 0xba, 0xbe, 0x97, 0x85, 0x02, 0x03, 0x01, 0x00, 0x01, + 0xa3, 0x81, 0xbd, 0x30, 0x81, 0xba, 0x30, 0x3e, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x01, 0x01, 0x04, 0x32, 0x30, 0x30, 0x30, 0x2e, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x30, 0x01, 0x86, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, + 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x30, 0x34, + 0x2d, 0x61, 0x73, 0x69, 0x30, 0x33, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, + 0x14, 0x0a, 0x8f, 0x13, 0x24, 0x0d, 0xc4, 0xe4, 0xe7, 0x97, 0x65, 0x35, 0xc8, 0x19, 0x91, 0x38, + 0x28, 0xce, 0x9b, 0x50, 0xdb, 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, + 0x12, 0x75, 0x7c, 0x47, 0x92, 0xfd, 0x83, 0xe3, 0xbe, 0x2e, 0xfc, 0x59, 0x7f, 0x67, 0x43, 0x81, + 0x35, 0x10, 0x45, 0xec, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x01, 0x01, 0xff, 0x04, 0x10, + 0x30, 0x0e, 0x30, 0x0c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, 0x0c, 0x01, + 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, + 0x82, 0x01, 0x01, 0x00, 0x59, 0x19, 0xdd, 0x6c, 0xf5, 0xb6, 0xf9, 0x93, 0x69, 0xe5, 0xcd, 0x64, + 0x5c, 0x4c, 0xaa, 0xd8, 0x86, 0x44, 0x6b, 0xca, 0x48, 0x6f, 0x2b, 0x15, 0x8f, 0xef, 0x1a, 0x5c, + 0xc9, 0xb2, 0x5b, 0x51, 0xee, 0xae, 0xf8, 0xeb, 0x7e, 0x05, 0x4a, 0xa1, 0x27, 0xd3, 0x15, 0x41, + 0xa1, 0x2c, 0x7e, 0x81, 0x96, 0xa8, 0xba, 0x8d, 0x1c, 0xc0, 0x0a, 0xce, 0xfd, 0x4b, 0xbc, 0x56, + 0x80, 0xe8, 0xf1, 0x04, 0x05, 0xd9, 0x17, 0x3d, 0x29, 0x6d, 0x99, 0xf5, 0xcc, 0x3a, 0x80, 0x7c, + 0x03, 0xb0, 0x8a, 0x4e, 0x2c, 0xdb, 0x24, 0x42, 0xa7, 0xa6, 0x8b, 0x2e, 0xff, 0x9c, 0xec, 0xce, + 0xe0, 0x0f, 0xd3, 0x5c, 0x0a, 0xed, 0x35, 0x14, 0xd0, 0x33, 0x76, 0xe0, 0x46, 0x09, 0x35, 0x54, + 0x40, 0x9b, 0x56, 0x8a, 0x45, 0x17, 0xa7, 0x50, 0x95, 0x5c, 0x9f, 0x5e, 0x95, 0x26, 0x89, 0xfe, + 0x79, 0xc6, 0x01, 0x3b, 0xf9, 0x64, 0x83, 0x28, 0x2b, 0x2d, 0x24, 0xbd, 0xb8, 0x4a, 0xca, 0x9a, + 0xba, 0x59, 0x5f, 0x72, 0xdd, 0x90, 0xcc, 0x4c, 0xed, 0x49, 0xf6, 0x11, 0x10, 0x7c, 0x34, 0x86, + 0x3f, 0x3e, 0x9a, 0xc0, 0xe6, 0xda, 0xf0, 0x6d, 0xb0, 0xd2, 0xf0, 0x46, 0x1e, 0x33, 0x53, 0x4a, + 0x5c, 0xd3, 0xdc, 0x9b, 0x74, 0x3d, 0x3e, 0x85, 0x9c, 0x19, 0xca, 0xb5, 0x26, 0xd5, 0xda, 0x22, + 0x7d, 0x52, 0xe6, 0x8c, 0x95, 0xd8, 0x30, 0x61, 0xf5, 0x3e, 0x05, 0x40, 0xe5, 0xd0, 0xcb, 0x91, + 0x28, 0x17, 0x4c, 0xf3, 0xf8, 0x06, 0x4c, 0x71, 0x80, 0xe0, 0x7c, 0x11, 0x7b, 0x00, 0xed, 0xe6, + 0x93, 0x8c, 0x12, 0x9e, 0xcc, 0x65, 0x5a, 0xb6, 0x61, 0x21, 0xe0, 0x0f, 0x3a, 0x8e, 0xcf, 0x12, + 0xea, 0x16, 0xbb, 0x91, 0x7e, 0x6c, 0x11, 0xb2, 0x29, 0x8a, 0x41, 0x46, 0xc3, 0xae, 0xd9, 0xf7, + 0x15, 0xe8, 0xaa, 0x86 +}; + +__unused static const uint8_t kMobileIntermediate[] = { + 0x30, 0x82, 0x04, 0x13, 0x30, 0x82, 0x02, 0xfb, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x60, + 0x25, 0x4e, 0x56, 0x81, 0x16, 0xcf, 0xf1, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x62, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, + 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x13, 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, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0d, 0x41, 0x70, 0x70, + 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, + 0x30, 0x39, 0x31, 0x33, 0x32, 0x32, 0x33, 0x35, 0x33, 0x37, 0x5a, 0x17, 0x0d, 0x32, 0x37, 0x30, + 0x39, 0x31, 0x33, 0x32, 0x32, 0x33, 0x35, 0x33, 0x37, 0x5a, 0x30, 0x81, 0x87, 0x31, 0x3b, 0x30, + 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x32, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x53, 0x79, + 0x73, 0x74, 0x65, 0x6d, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, + 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, + 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 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, 0x9e, 0x48, 0xf6, 0x8f, 0xab, 0x1b, 0x89, 0xa5, 0x9f, 0x34, 0x47, + 0xb6, 0x38, 0x30, 0xa7, 0xb0, 0x62, 0xa4, 0x99, 0x84, 0x2a, 0x74, 0x4b, 0x47, 0x5b, 0x66, 0x35, + 0x69, 0xfe, 0x97, 0x01, 0x64, 0x18, 0x9d, 0x0a, 0xf8, 0xd7, 0x33, 0x2a, 0x64, 0xd8, 0xbc, 0x03, + 0x4f, 0xcd, 0x4d, 0x80, 0x90, 0xd2, 0xc3, 0xc5, 0xd1, 0x8c, 0xc1, 0x73, 0xf6, 0x5a, 0x50, 0x70, + 0xcd, 0xe0, 0x94, 0x35, 0x82, 0xc4, 0x59, 0xca, 0xba, 0xa9, 0x94, 0xbd, 0x88, 0x36, 0x7a, 0x32, + 0xdf, 0x08, 0x29, 0xe0, 0x9c, 0x19, 0x1c, 0x68, 0x02, 0x60, 0x87, 0xfc, 0x2e, 0x8a, 0x3c, 0x37, + 0x4d, 0x7c, 0x81, 0xbb, 0x6c, 0x6f, 0x72, 0x45, 0xf5, 0xb3, 0x96, 0x66, 0x5e, 0xab, 0x97, 0x54, + 0x50, 0x03, 0xc0, 0x41, 0xfc, 0xb5, 0xa8, 0xf7, 0x78, 0xde, 0x4c, 0x9a, 0x67, 0xf4, 0x4d, 0x27, + 0x54, 0x9e, 0xc8, 0x75, 0xea, 0x8c, 0x76, 0xc1, 0xb5, 0x79, 0xe3, 0x60, 0xce, 0x98, 0x21, 0x38, + 0x7b, 0x9a, 0x53, 0xe8, 0x57, 0x69, 0x13, 0xf0, 0xf0, 0x86, 0x91, 0x2e, 0xad, 0x75, 0xb9, 0x53, + 0x4a, 0x30, 0xf6, 0x6d, 0x96, 0x8e, 0x5e, 0xe7, 0xe9, 0xa5, 0x16, 0xe7, 0xb4, 0x5b, 0xe7, 0xe9, + 0x6e, 0x4f, 0xe7, 0x38, 0xda, 0x53, 0x39, 0x60, 0x0e, 0xfd, 0xd0, 0x0b, 0x19, 0x52, 0x5d, 0x79, + 0x3a, 0x5d, 0x7b, 0x0d, 0x19, 0x91, 0x72, 0x94, 0x0e, 0x03, 0xa6, 0x14, 0xca, 0xdd, 0x7a, 0x27, + 0xed, 0x22, 0x21, 0xeb, 0x67, 0x01, 0xc0, 0x98, 0x4f, 0xf7, 0x78, 0x81, 0x34, 0xfb, 0x08, 0x48, + 0xb6, 0xec, 0xa4, 0xdb, 0x60, 0xd3, 0x9d, 0xa7, 0x46, 0x6c, 0x50, 0xa6, 0x14, 0x4a, 0x30, 0xee, + 0x77, 0x87, 0x64, 0xb6, 0xb2, 0xb4, 0x92, 0xfc, 0x45, 0xb3, 0x80, 0x59, 0xbd, 0x85, 0x9c, 0x2f, + 0xd1, 0xd7, 0x59, 0xe3, 0x0f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa6, 0x30, 0x81, 0xa3, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x12, 0x75, 0x7c, 0x47, 0x92, + 0xfd, 0x83, 0xe3, 0xbe, 0x2e, 0xfc, 0x59, 0x7f, 0x67, 0x43, 0x81, 0x35, 0x10, 0x45, 0xec, 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, 0x2b, 0xd0, 0x69, + 0x47, 0x94, 0x76, 0x09, 0xfe, 0xf4, 0x6b, 0x8d, 0x2e, 0x40, 0xa6, 0xf7, 0x47, 0x4d, 0x7f, 0x08, + 0x5e, 0x30, 0x2e, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x27, 0x30, 0x25, 0x30, 0x23, 0xa0, 0x21, + 0xa0, 0x1f, 0x86, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x61, + 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 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, 0x0a, 0x04, + 0x02, 0x05, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, + 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xaa, 0x3d, 0x38, 0x8a, 0x96, 0x9b, 0xc7, 0x94, 0x97, + 0x3d, 0x3e, 0x5b, 0x1f, 0x09, 0x43, 0xe1, 0x1a, 0x6e, 0x6a, 0x4d, 0xd6, 0x38, 0xbb, 0x8a, 0x6d, + 0x00, 0xc9, 0x93, 0xdc, 0x3e, 0xa2, 0xc3, 0x2a, 0x97, 0xc1, 0x4f, 0x07, 0xa0, 0xa3, 0x14, 0x6c, + 0xd9, 0x0b, 0x9a, 0xcd, 0xb1, 0xcf, 0x7c, 0xc0, 0x67, 0x75, 0x12, 0xee, 0x2e, 0xb0, 0x28, 0x17, + 0x18, 0x7e, 0x73, 0x3d, 0xb4, 0x04, 0x91, 0x39, 0x7c, 0x37, 0xfb, 0xbd, 0x34, 0x01, 0xa0, 0xde, + 0x77, 0xa7, 0x5b, 0xb6, 0x47, 0x8e, 0x73, 0x3a, 0x8f, 0x7b, 0x63, 0x58, 0xc4, 0xa3, 0x6d, 0x19, + 0x4d, 0x9d, 0x9e, 0xd6, 0x3e, 0xbe, 0x18, 0x53, 0xe9, 0x30, 0x4d, 0xd2, 0xad, 0xef, 0x4b, 0xf6, + 0xa4, 0x84, 0xcf, 0x25, 0xfc, 0xea, 0x0d, 0x33, 0x58, 0x51, 0x00, 0xe2, 0x4b, 0xfe, 0x74, 0xd9, + 0x47, 0x13, 0x9e, 0xa7, 0xd7, 0x37, 0x6a, 0xea, 0x27, 0x0c, 0x6c, 0x7e, 0x8a, 0x93, 0xee, 0x60, + 0x10, 0x30, 0x1b, 0xf5, 0x59, 0x2a, 0x14, 0x4f, 0xd8, 0x7f, 0xe7, 0xb0, 0xe6, 0x3d, 0xfe, 0x72, + 0xe0, 0xc8, 0x52, 0x21, 0x15, 0x37, 0x18, 0x59, 0xd4, 0x7c, 0x5c, 0x8d, 0x55, 0x0b, 0x9b, 0xfb, + 0x3a, 0x75, 0x0f, 0xf6, 0x06, 0x29, 0xb6, 0xc2, 0x7f, 0x8d, 0x95, 0xce, 0x68, 0x77, 0x73, 0xae, + 0xde, 0x81, 0xfa, 0xce, 0x09, 0x72, 0xb1, 0x6c, 0xce, 0xe4, 0x94, 0x9e, 0x85, 0xf8, 0xdc, 0xba, + 0xc4, 0x5f, 0x77, 0xe9, 0x9e, 0x03, 0x99, 0x34, 0x8d, 0xcc, 0xdc, 0x9f, 0x56, 0x98, 0xed, 0x28, + 0xed, 0x06, 0x56, 0x80, 0xea, 0x52, 0x3a, 0x95, 0xc4, 0x64, 0x8f, 0x0c, 0xd9, 0x57, 0xbd, 0xc2, + 0xa9, 0x8d, 0xa0, 0x3a, 0xe2, 0x6c, 0x5a, 0x2a, 0x7b, 0xda, 0xf6, 0x81, 0x1a, 0x03, 0x17, 0x6b, + 0x0c, 0x0c, 0xda, 0xbd, 0x8e, 0x23, 0x06 + +}; + +// Escrow Service Key F98EB04C6AA62F4022709406305387C61415DDD770A24039C1415F24BF918803 +static const uint8_t kEscrowLeafCert[] = { + 0x30, 0x82, 0x04, 0x07, 0x30, 0x82, 0x02, 0xef, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x05, 0x00, + 0x9b, 0x6e, 0xef, 0x8d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x0b, 0x05, 0x00, 0x30, 0x79, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x03, + 0x31, 0x30, 0x30, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, + 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 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, 0x33, 0x30, 0x38, 0x30, 0x32, 0x32, 0x33, 0x32, 0x34, 0x34, 0x38, 0x5a, 0x17, + 0x0d, 0x31, 0x35, 0x30, 0x38, 0x30, 0x32, 0x32, 0x33, 0x32, 0x34, 0x34, 0x38, 0x5a, 0x30, 0x81, + 0x9b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x02, 0x43, 0x41, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, + 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x03, 0x45, 0x54, 0x53, 0x31, 0x5c, + 0x30, 0x5a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x53, 0x45, 0x73, 0x63, 0x72, 0x6f, 0x77, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x39, 0x42, 0x36, 0x45, + 0x45, 0x46, 0x38, 0x44, 0x37, 0x42, 0x33, 0x43, 0x34, 0x39, 0x31, 0x32, 0x46, 0x35, 0x35, 0x35, + 0x32, 0x32, 0x32, 0x32, 0x42, 0x42, 0x34, 0x31, 0x44, 0x38, 0x34, 0x43, 0x43, 0x31, 0x39, 0x43, + 0x33, 0x35, 0x37, 0x37, 0x32, 0x35, 0x41, 0x36, 0x43, 0x35, 0x46, 0x34, 0x45, 0x35, 0x43, 0x43, + 0x36, 0x30, 0x37, 0x41, 0x32, 0x44, 0x37, 0x32, 0x31, 0x35, 0x41, 0x43, 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, 0xc7, 0x51, + 0xf1, 0x3f, 0x9a, 0x5d, 0xd7, 0xc1, 0x03, 0x42, 0x30, 0x84, 0xdb, 0xbc, 0x6c, 0x00, 0x6c, 0xcc, + 0x57, 0x97, 0xaf, 0xfe, 0x9e, 0xa0, 0x06, 0x9f, 0xe8, 0xa9, 0x59, 0xe1, 0xf8, 0xed, 0x23, 0x05, + 0x57, 0xe3, 0xd8, 0xdf, 0xf8, 0x31, 0x80, 0x8b, 0x31, 0x08, 0x2a, 0xc3, 0x7b, 0x16, 0xba, 0x27, + 0x84, 0x4e, 0xbb, 0x55, 0x5b, 0xd2, 0xda, 0x2d, 0xea, 0xda, 0x5c, 0xf0, 0x21, 0x58, 0x63, 0x74, + 0xa9, 0x90, 0x99, 0xbe, 0x87, 0x19, 0x7d, 0x87, 0xfc, 0xcb, 0xb6, 0xc9, 0x39, 0x51, 0x6a, 0xa7, + 0x81, 0x05, 0x50, 0x2d, 0xa2, 0x10, 0x6d, 0x58, 0xa5, 0x62, 0x29, 0x53, 0xce, 0xa6, 0x53, 0xad, + 0x3f, 0x50, 0xda, 0x1a, 0x1e, 0x2c, 0xe3, 0xae, 0x24, 0x88, 0xa5, 0x4c, 0xa3, 0x3a, 0xe1, 0xc6, + 0xa9, 0xcf, 0xb5, 0x53, 0x30, 0xbf, 0x7b, 0xea, 0x77, 0x21, 0x24, 0xfd, 0x91, 0x4c, 0x6f, 0x60, + 0x9f, 0x78, 0xf9, 0xed, 0x84, 0xe5, 0xee, 0xab, 0x07, 0xc5, 0x34, 0xa9, 0xe2, 0x0a, 0xf5, 0xf5, + 0xfa, 0x66, 0x75, 0xc8, 0x3e, 0x9c, 0xdd, 0xea, 0x60, 0xf0, 0x83, 0x03, 0x19, 0x08, 0xa4, 0x85, + 0xb0, 0xf3, 0xb1, 0xf1, 0x7a, 0x3d, 0xb4, 0xc8, 0xdd, 0x25, 0x5a, 0x1b, 0xf5, 0xa0, 0x78, 0xf9, + 0xbb, 0x08, 0x27, 0x6f, 0xa9, 0xf9, 0x17, 0xe8, 0xcb, 0x01, 0xa3, 0x5a, 0xd0, 0x67, 0xfb, 0xb7, + 0xef, 0xb7, 0x5c, 0x20, 0x94, 0x17, 0x5d, 0x46, 0xbd, 0xd2, 0xfe, 0xb6, 0x68, 0x88, 0x9f, 0xa6, + 0x0b, 0x97, 0x0f, 0x2e, 0x10, 0x23, 0x52, 0x9e, 0x69, 0x8b, 0xf4, 0x80, 0x83, 0x0e, 0x5b, 0x04, + 0xfc, 0x4e, 0xa1, 0x32, 0x44, 0x8a, 0x63, 0x3e, 0x3b, 0x0b, 0x70, 0x15, 0xd4, 0x17, 0xc1, 0xbe, + 0xbb, 0x01, 0x37, 0xe8, 0xfb, 0x58, 0x8b, 0x3d, 0xec, 0xc4, 0x47, 0x82, 0xe5, 0x02, 0x03, 0x01, + 0x00, 0x01, 0xa3, 0x73, 0x30, 0x71, 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, 0x20, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb7, + 0x34, 0x54, 0x7b, 0x16, 0x2a, 0x38, 0x22, 0xd5, 0x79, 0x7b, 0xbf, 0x5c, 0x62, 0x16, 0x59, 0xc5, + 0x53, 0x9f, 0xac, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0xfd, 0x78, 0x96, 0x53, 0x80, 0xd6, 0xf6, 0xdc, 0xa6, 0xc3, 0x59, 0x06, 0x38, 0xed, 0x79, 0x3e, + 0x8f, 0x50, 0x1b, 0x50, 0x30, 0x11, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x06, + 0x17, 0x01, 0x04, 0x03, 0x02, 0x01, 0x0a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x01, 0x41, 0x68, 0xd9, 0xd5, + 0xb5, 0xbe, 0x2d, 0xa1, 0xe7, 0x52, 0x28, 0x2c, 0x4f, 0xe7, 0x43, 0x39, 0x4d, 0x1f, 0xeb, 0x09, + 0xd9, 0xc7, 0xca, 0x6f, 0x63, 0x60, 0x7f, 0x7c, 0xb5, 0x7c, 0x5e, 0x4b, 0xab, 0xd5, 0x8b, 0x34, + 0x5b, 0x50, 0xda, 0x3e, 0x37, 0xa8, 0x26, 0xf5, 0xdb, 0x76, 0xc4, 0x4a, 0x48, 0x09, 0xcf, 0x04, + 0x0a, 0x17, 0x6c, 0x8d, 0x3c, 0x6e, 0x1e, 0x41, 0xfc, 0xef, 0x45, 0xbd, 0x72, 0x59, 0x5e, 0x10, + 0x61, 0x4e, 0xad, 0x0e, 0xe4, 0x76, 0x3c, 0xf7, 0x87, 0xef, 0x54, 0xdd, 0x61, 0xe9, 0x91, 0x0f, + 0x7e, 0x52, 0xd6, 0x9e, 0x02, 0xd7, 0xb6, 0xcc, 0xa4, 0x9e, 0x7d, 0xba, 0x5f, 0xb4, 0x40, 0xc9, + 0xe6, 0x95, 0x61, 0xae, 0xb9, 0x89, 0xba, 0x25, 0x1b, 0xb6, 0xde, 0x08, 0x7f, 0x88, 0xef, 0x7c, + 0x59, 0x4d, 0x73, 0xc7, 0xf5, 0x07, 0x94, 0x13, 0x7b, 0xfc, 0x9f, 0x75, 0x0d, 0x1a, 0x69, 0xf0, + 0x51, 0x36, 0x1e, 0x46, 0x76, 0xc8, 0x27, 0x4e, 0x65, 0x58, 0x66, 0x41, 0x5e, 0x9d, 0xfe, 0xf1, + 0x10, 0xd5, 0x3c, 0x5b, 0xea, 0xcd, 0x96, 0x37, 0x4d, 0x76, 0x88, 0x60, 0xfb, 0x3f, 0xb2, 0x7a, + 0x00, 0xb4, 0xe0, 0xb6, 0xb9, 0x76, 0x6e, 0x02, 0xb6, 0xf7, 0x8d, 0x8b, 0x3a, 0x5c, 0xde, 0x4e, + 0xb9, 0xa4, 0x05, 0xc6, 0x14, 0xa6, 0x3f, 0x6c, 0xbd, 0xfd, 0xee, 0x0b, 0xf5, 0x5c, 0x27, 0x56, + 0xc5, 0x48, 0x55, 0x78, 0x72, 0xdc, 0xca, 0x95, 0xb7, 0x02, 0xb2, 0xdc, 0x4e, 0xbd, 0xe2, 0x78, + 0x87, 0xcc, 0xb5, 0xb0, 0x7c, 0x22, 0x52, 0xc1, 0xb0, 0x5a, 0x09, 0x9d, 0xb6, 0xbe, 0xe7, 0x4b, + 0xa2, 0x0e, 0x20, 0x43, 0x28, 0x77, 0x88, 0x1f, 0xd6, 0xa4, 0xb9, 0x56, 0xd0, 0xd0, 0xa6, 0x0f, + 0xa3, 0xef, 0x2e, 0xb7, 0x1d, 0x40, 0x61, 0xf8, 0xb9, 0x17, 0x4c, +}; + +static const uint8_t kPCSEscrowLeafCert[] = { + 0x30,0x82,0x04,0x0E,0x30,0x82,0x02,0xF6,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x5B, + 0x57,0x9E,0xA2,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B, + 0x05,0x00,0x30,0x7D,0x31,0x0C,0x30,0x0A,0x06,0x03,0x55,0x04,0x05,0x13,0x03,0x31, + 0x30,0x30,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20, + 0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,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,0x23,0x30,0x21, + 0x06,0x03,0x55,0x04,0x03,0x13,0x1A,0x45,0x66,0x66,0x61,0x63,0x65,0x61,0x62,0x6C, + 0x65,0x20,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43, + 0x41,0x30,0x1E,0x17,0x0D,0x31,0x34,0x30,0x37,0x32,0x39,0x30,0x30,0x31,0x31,0x34, + 0x33,0x5A,0x17,0x0D,0x31,0x36,0x30,0x37,0x32,0x39,0x30,0x30,0x31,0x31,0x34,0x33, + 0x5A,0x30,0x81,0x9F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x13,0x02,0x43,0x41,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x0C,0x30,0x0A,0x06,0x03,0x55,0x04,0x0B,0x13,0x03,0x45,0x54, + 0x53,0x31,0x60,0x30,0x5E,0x06,0x03,0x55,0x04,0x03,0x13,0x57,0x45,0x66,0x66,0x61, + 0x63,0x65,0x61,0x62,0x6C,0x65,0x20,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x20,0x4B, + 0x65,0x79,0x20,0x35,0x42,0x35,0x37,0x39,0x45,0x41,0x32,0x36,0x34,0x41,0x39,0x36, + 0x36,0x39,0x37,0x42,0x41,0x38,0x31,0x33,0x34,0x35,0x34,0x44,0x32,0x45,0x38,0x43, + 0x46,0x37,0x44,0x42,0x31,0x34,0x30,0x33,0x37,0x43,0x30,0x43,0x45,0x44,0x32,0x34, + 0x33,0x43,0x42,0x37,0x46,0x45,0x33,0x31,0x33,0x38,0x33,0x42,0x34,0x35,0x38,0x34, + 0x33,0x30,0x42,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,0xAD,0x92,0x86,0x08,0xFF,0x27,0xF1,0xCC,0xB6,0x57,0x41, + 0xC9,0x1F,0x05,0xC2,0xC7,0xC5,0xFB,0x8C,0xE3,0xEE,0xBC,0xE0,0x07,0xA4,0x58,0xE0, + 0x9E,0x81,0x19,0xF9,0x81,0xDF,0xD6,0x1B,0x65,0x23,0x0E,0xAC,0x2A,0xB6,0x3F,0x32, + 0x66,0xBF,0x9E,0xF4,0x0D,0xEA,0xE8,0xE9,0x5E,0xCF,0xB6,0x84,0x61,0x03,0x26,0x92, + 0xC5,0xAC,0xB2,0x54,0xE0,0x5B,0x22,0x88,0xFB,0x9B,0x6F,0xEF,0xFE,0xC1,0x40,0x27, + 0xF3,0x35,0xF2,0xC4,0x4C,0xB1,0xB4,0x57,0x2D,0xE7,0xF0,0x26,0xC0,0xE8,0x5F,0x02, + 0x13,0x33,0x53,0x5F,0xC8,0x5B,0x6B,0x14,0x5B,0x37,0x2F,0x24,0xD6,0x39,0x0C,0x7C, + 0x0D,0x8E,0x4A,0x73,0x33,0xAF,0xA1,0x78,0x6F,0xE0,0xD8,0x42,0x40,0x33,0x58,0x12, + 0x76,0xFF,0xF2,0x1E,0xAE,0x0B,0x80,0x3F,0x63,0x52,0xED,0xCA,0x33,0x3A,0x8B,0x19, + 0x37,0xFF,0xAC,0xFF,0x4D,0xBF,0xD1,0x9D,0x55,0xD1,0x2A,0x17,0x28,0x0E,0x6B,0xC8, + 0x12,0xBF,0x79,0x22,0x6B,0x8F,0x3C,0x3B,0x5C,0xC7,0x66,0xA8,0x9C,0x65,0x68,0xB4, + 0x4B,0x37,0xCE,0xC9,0x2A,0x7E,0x36,0x6A,0x7A,0x76,0x5D,0x47,0x26,0xDE,0x70,0xC8, + 0xE5,0x6B,0xA1,0xC5,0xC8,0xBC,0xCF,0xD2,0x78,0xAF,0xDE,0x9A,0xF4,0x49,0xC7,0xFC, + 0x78,0xF2,0x37,0xC1,0xD1,0x40,0xFA,0x30,0x4C,0x96,0xC2,0x16,0xEC,0xEB,0xE0,0x33, + 0x94,0xE1,0x83,0xE8,0xF9,0xD6,0x58,0xEE,0xEE,0x7D,0x49,0x38,0xC7,0xD6,0x15,0xE6, + 0x00,0x7F,0x40,0x37,0x03,0x3F,0xF3,0x5F,0x38,0x63,0x93,0x87,0xF1,0xE2,0xB7,0x8C, + 0xFF,0x21,0x68,0x7B,0x02,0x03,0x01,0x00,0x01,0xA3,0x73,0x30,0x71,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,0x20,0x30,0x1D,0x06,0x03,0x55, + 0x1D,0x0E,0x04,0x16,0x04,0x14,0x3F,0x94,0xA6,0xB9,0xB6,0xAE,0x43,0xDA,0x66,0xF3, + 0xD3,0x38,0xF0,0xD0,0x96,0x59,0x79,0x1B,0x0A,0xC1,0x30,0x1F,0x06,0x03,0x55,0x1D, + 0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x64,0x0B,0xE4,0x72,0x73,0x5C,0x54,0xB2,0x58, + 0x59,0xAE,0x42,0xDF,0x2B,0xB7,0xBA,0xB9,0xEB,0x86,0xAE,0x30,0x11,0x06,0x0A,0x2A, + 0x86,0x48,0x86,0xF7,0x63,0x64,0x06,0x17,0x01,0x04,0x03,0x02,0x01,0x0A,0x30,0x0D, + 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01, + 0x01,0x00,0x83,0x4B,0x3D,0x4E,0xE0,0x17,0xB5,0x95,0xAE,0x90,0xA4,0xE0,0x41,0x01, + 0x5B,0x1A,0x1D,0x69,0x83,0xA9,0xA0,0xD8,0x58,0xCD,0x57,0xB8,0x8B,0x1D,0x00,0xD2, + 0xB4,0x27,0x65,0x34,0x83,0xAD,0x5B,0xCF,0xA8,0x2F,0xFC,0x6C,0x08,0x1B,0x2B,0x12, + 0x93,0xE5,0x68,0xE3,0x85,0xFA,0x87,0x28,0x31,0x7E,0x18,0xA9,0xB9,0xEF,0xF4,0xE3, + 0x1C,0x24,0x83,0xE6,0x01,0xDA,0x56,0x49,0x52,0xA1,0xBC,0x56,0xE4,0xFC,0xA6,0xAF, + 0xC7,0x8D,0xD8,0x41,0xD3,0xA8,0x10,0x99,0x0F,0xEE,0x93,0xF1,0x58,0x4C,0x43,0x8B, + 0x31,0xF8,0xA8,0x04,0xFD,0x88,0x7E,0x0C,0x0C,0xA6,0xB9,0x3C,0xEC,0x9B,0xCD,0x99, + 0xF5,0x38,0x35,0x76,0x63,0xBC,0x23,0x9A,0x8F,0xA3,0x0B,0xE2,0x8E,0x55,0xEF,0x71, + 0xD8,0x87,0xA8,0x62,0x2B,0x35,0x32,0x24,0x6C,0xEE,0x95,0x5C,0x74,0xB2,0x1B,0x8F, + 0xEF,0x4C,0x45,0x03,0x0B,0x35,0x97,0x7D,0x43,0x7F,0x1D,0x3E,0xB9,0xE9,0x9D,0xF1, + 0x96,0x3B,0x91,0xA6,0xDF,0x52,0x00,0xB3,0xC5,0xDC,0xD3,0x29,0xAC,0x17,0xE1,0x73, + 0xA9,0x15,0x14,0xBD,0x1E,0x4F,0x9F,0x09,0xF8,0x84,0xF8,0xB6,0x9C,0xFD,0xCD,0x09, + 0x6D,0xDD,0x39,0xC7,0x15,0x58,0x86,0xE8,0x6B,0x47,0x4F,0x5D,0x84,0x29,0x56,0x81, + 0xF1,0x7C,0x09,0xA5,0x50,0x5C,0x4B,0xD9,0xFF,0xDF,0xA5,0xA9,0x6E,0xFF,0x14,0x9F, + 0xE4,0x4C,0xE7,0xAA,0x83,0xEA,0x30,0xB4,0x0D,0x8D,0xF7,0x36,0x4B,0x8D,0x38,0xDC, + 0xF5,0xA9,0xCF,0x3F,0x85,0x6A,0xC3,0x7A,0x53,0x86,0x18,0x5D,0x4B,0x93,0x1A,0x0E, + 0x50,0x5D, +}; + + +#if 0 +static inline void test_mobile(void) +{ + SecCertificateRef aCert = NULL; + SecCertificateRef intermediateCert = NULL; + SecCertificateRef rootCert = NULL; + SecTrustResultType trustResult = kSecTrustResultUnspecified; + SecPolicyRef policy = NULL; + CFArrayRef certs = NULL; + SecTrustRef trust = NULL; + + isnt(aCert = SecCertificateCreateWithBytes(NULL, kDemoContentSigningCert, sizeof(kDemoContentSigningCert)), + NULL, "create aCert from kDemoContentSigningCert"); + + isnt(intermediateCert = SecCertificateCreateWithBytes(NULL, kMobileIntermediate, sizeof(kMobileIntermediate)), + NULL, "create intermediate from kMobileIntermediate"); + + SecCertificateRef refs[] = {aCert, intermediateCert}; + certs = CFArrayCreate(NULL, (const void **)refs, 2, NULL); + + isnt(policy = SecPolicyCreateMobileStoreSigner(), + NULL, "create mobile policy"); + + ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), + "create trust for mobile store test cert"); + + ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate mobile store trust"); + + is_status(trustResult, kSecTrustResultUnspecified, + "trust is kSecTrustResultRecoverableTrustFailure"); + + CFReleaseSafe(trust); + CFReleaseSafe(policy); + CFReleaseSafe(aCert); + + isnt(aCert = SecCertificateCreateWithBytes(NULL, kTestDemoContentSigningCert, sizeof(kTestDemoContentSigningCert)), + NULL, "create aCert from kDemoContentSigningCert"); + + isnt(policy = SecPolicyCreateTestMobileStoreSigner(), + NULL, "create Test mobile policy"); + + ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), + "create trust for mobile store test cert"); + + ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate test mobile store trust"); + + is_status(trustResult, kSecTrustResultUnspecified, + "trust is kSecTrustResultRecoverableTrustFailure"); + + CFReleaseSafe(trust); + CFReleaseSafe(policy); + CFReleaseSafe(aCert); + CFReleaseSafe(certs); + CFReleaseSafe(intermediateCert); + CFReleaseSafe(rootCert); + +} +#endif // 0 + +static void test_escrow_with_anchor_roots(CFArrayRef anchors) +{ + SecCertificateRef escrowLeafCert = NULL; + SecTrustResultType trustResult = kSecTrustResultUnspecified; + SecPolicyRef policy = NULL; + CFArrayRef certs = NULL; + SecTrustRef trust = NULL; + + isnt(escrowLeafCert = SecCertificateCreateWithBytes(NULL, kEscrowLeafCert, sizeof(kEscrowLeafCert)), + NULL, "could not create aCert from kEscrowLeafCert"); + + certs = CFArrayCreate(NULL, (const void **)&escrowLeafCert, 1, NULL); + + isnt(policy = SecPolicyCreateWithProperties(kSecPolicyAppleEscrowService, NULL), + NULL, "could not create Escrow policy for GM Escrow Leaf cert"); + + ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), + "could not create trust for escrow service test GM Escrow Leaf cert"); + + SecTrustSetAnchorCertificates(trust, anchors); + + ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate escrow service trust for GM Escrow Leaf cert"); + + is_status(trustResult, kSecTrustResultUnspecified, + "trust is not kSecTrustResultUnspecified for GM Escrow Leaf cert"); + + CFReleaseSafe(trust); + CFReleaseSafe(policy); + CFReleaseSafe(certs); + CFReleaseSafe(escrowLeafCert); + +} + +static void test_pcs_escrow_with_anchor_roots(CFArrayRef anchors) +{ + SecCertificateRef leafCert = NULL; + SecTrustResultType trustResult = kSecTrustResultUnspecified; + SecPolicyRef policy = NULL; + CFArrayRef certs = NULL; + SecTrustRef trust = NULL; + + isnt(leafCert = SecCertificateCreateWithBytes(NULL, kPCSEscrowLeafCert, sizeof(kPCSEscrowLeafCert)), + NULL, "could not create leafCert from kPCSEscrowLeafCert"); + + certs = CFArrayCreate(NULL, (const void **)&leafCert, 1, NULL); + + isnt(policy = SecPolicyCreateWithProperties(kSecPolicyApplePCSEscrowService, NULL), + NULL, "could not create PCS Escrow policy for GM PCS Escrow Leaf cert"); + + ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), + "could not create trust for PCS escrow service test GM PCS Escrow Leaf cert"); + + SecTrustSetAnchorCertificates(trust, anchors); + + ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate PCS escrow service trust for GM PCS Escrow Leaf cert"); + + is_status(trustResult, kSecTrustResultUnspecified, + "trust is not kSecTrustResultUnspecified for GM PCS Escrow Leaf cert"); + + CFReleaseSafe(trust); + CFReleaseSafe(policy); + CFReleaseSafe(certs); + CFReleaseSafe(leafCert); + +} +static inline void test_escrow() +{ + CFArrayRef anchors = NULL; + isnt(anchors = SecCertificateCopyEscrowRoots(kSecCertificateProductionEscrowRoot), NULL, "unable to get production anchors"); + test_escrow_with_anchor_roots(anchors); + CFReleaseSafe(anchors); +} + +static inline void test_pcs_escrow() +{ + CFArrayRef anchors = NULL; + isnt(anchors = SecCertificateCopyEscrowRoots(kSecCertificateProductionPCSEscrowRoot), NULL, "unable to get production PCS roots"); + test_pcs_escrow_with_anchor_roots(anchors); + CFReleaseSafe(anchors); +} + +static inline void test_escrow_roots() +{ + CFArrayRef baselineRoots = NULL; + isnt(baselineRoots = SecCertificateCopyEscrowRoots(kSecCertificateBaselineEscrowRoot), NULL, "unable to get baseline roots"); + ok(baselineRoots && CFArrayGetCount(baselineRoots) > 0, "baseline roots array empty"); + CFReleaseSafe(baselineRoots); + + CFArrayRef productionRoots = NULL; + isnt(productionRoots = SecCertificateCopyEscrowRoots(kSecCertificateProductionEscrowRoot), NULL, "unable to get production roots"); + ok(productionRoots && CFArrayGetCount(productionRoots) > 0, "production roots array empty"); + CFReleaseSafe(productionRoots); + + CFArrayRef baselinePCSRoots = NULL; + isnt(baselinePCSRoots = SecCertificateCopyEscrowRoots(kSecCertificateBaselinePCSEscrowRoot), NULL, "unable to get baseline PCS roots"); + ok(baselinePCSRoots && CFArrayGetCount(baselinePCSRoots) > 0, "baseline PCS roots array empty"); + CFReleaseSafe(baselinePCSRoots); + + CFArrayRef productionPCSRoots = NULL; + isnt(productionPCSRoots = SecCertificateCopyEscrowRoots(kSecCertificateProductionPCSEscrowRoot), NULL, "unable to get production PCS roots"); + ok(productionPCSRoots && CFArrayGetCount(productionPCSRoots) > 0, "production PCS roots array empty"); + CFReleaseSafe(productionPCSRoots); +} + +static void tests(void) +{ + test_escrow(); + test_pcs_escrow(); + test_escrow_roots(); +} + +//#endif /* defined(NO_SERVER) && NO_SERVER == 1 */ + +int si_71_mobile_store_policy(int argc, char *const *argv) +{ +//#if defined(NO_SERVER) && NO_SERVER == 1 + + plan_tests(20); + + tests(); + +//#endif + + return 0; +} diff --git a/sec/Security/Regressions/secitem/si-72-syncableitems.c b/Security/sec/Security/Regressions/secitem/si-72-syncableitems.c similarity index 84% rename from sec/Security/Regressions/secitem/si-72-syncableitems.c rename to Security/sec/Security/Regressions/secitem/si-72-syncableitems.c index b55e3fee..f8067051 100644 --- a/sec/Security/Regressions/secitem/si-72-syncableitems.c +++ b/Security/sec/Security/Regressions/secitem/si-72-syncableitems.c @@ -1,9 +1,31 @@ +/* + * 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@ + */ + // // si-72-syncableitems.c // regressions // -// Created by Ken McLeod on 5/18/13. // // #include diff --git a/sec/Security/Regressions/secitem/si-73-secpasswordgenerate.c b/Security/sec/Security/Regressions/secitem/si-73-secpasswordgenerate.c similarity index 93% rename from sec/Security/Regressions/secitem/si-73-secpasswordgenerate.c rename to Security/sec/Security/Regressions/secitem/si-73-secpasswordgenerate.c index 30e79f75..65f8130d 100644 --- a/sec/Security/Regressions/secitem/si-73-secpasswordgenerate.c +++ b/Security/sec/Security/Regressions/secitem/si-73-secpasswordgenerate.c @@ -897,23 +897,23 @@ static void tests(void) password = CFSTR("654321"); isnt(false, SecPasswordIsPasswordWeak(password)); CFRelease(password); - + password = CFSTR("A"); isnt(false, SecPasswordIsPasswordWeak(password)); CFRelease(password); - + password = CFSTR("password"); isnt(true, SecPasswordIsPasswordWeak(password)); CFRelease(password); - + password = CFSTR("password1"); isnt(true, SecPasswordIsPasswordWeak(password)); CFRelease(password); - + password = CFSTR("P@ssw0rd"); isnt(true, SecPasswordIsPasswordWeak(password)); CFRelease(password); - + password = CFSTR("facebook!{}"); isnt(true, SecPasswordIsPasswordWeak(password)); CFRelease(password); @@ -921,11 +921,92 @@ static void tests(void) password = CFSTR("12345678"); isnt(false, SecPasswordIsPasswordWeak(password)); CFRelease(password); + + bool isSimple = false; + + password = CFSTR("Apple1?"); + is(false, SecPasswordIsPasswordWeak2(isSimple, password)); + CFRelease(password); + + password = CFSTR("Singhal190"); + is(false, SecPasswordIsPasswordWeak2(isSimple, password)); + CFRelease(password); + + password = CFSTR("1Hollow2"); + is(false, SecPasswordIsPasswordWeak2(isSimple, password)); + CFRelease(password); + + password = CFSTR("1Hollow/"); + is(false, SecPasswordIsPasswordWeak2(isSimple, password)); + CFRelease(password); + + password = CFSTR("baj/paj1"); + is(false, SecPasswordIsPasswordWeak2(isSimple, password)); + CFRelease(password); + + password = CFSTR("Zaxs1009?"); + is(false, SecPasswordIsPasswordWeak2(isSimple, password)); + CFRelease(password); + + password = CFSTR("6666"); + is(true, SecPasswordIsPasswordWeak2(isSimple, password)); + CFRelease(password); + + password = CFSTR("1235"); + is(false, SecPasswordIsPasswordWeak2(isSimple, password)); + CFRelease(password); + + isSimple = true; + password = CFSTR("6666"); + is(true, SecPasswordIsPasswordWeak2(isSimple, password)); + CFRelease(password); + + password = CFSTR("1235"); + is(false, SecPasswordIsPasswordWeak2(isSimple, password)); + CFRelease(password); + + isSimple = false; + password = CFSTR("123456"); + is(true, SecPasswordIsPasswordWeak2(isSimple, password)); + CFRelease(password); + + password = CFSTR("654321"); + is(true, SecPasswordIsPasswordWeak2(isSimple, password)); + CFRelease(password); + + password = CFSTR("1577326"); + is(false, SecPasswordIsPasswordWeak2(isSimple, password)); + CFRelease(password); + + password = CFSTR("A"); + is(true, SecPasswordIsPasswordWeak2(isSimple, password)); + CFRelease(password); + + password = CFSTR("password"); + is(false, SecPasswordIsPasswordWeak2(isSimple, password)); + CFRelease(password); + + password = CFSTR("password1"); + is(false, SecPasswordIsPasswordWeak2(isSimple, password)); + CFRelease(password); + + password = CFSTR("P@ssw0rd"); + is(false, SecPasswordIsPasswordWeak2(isSimple, password)); + CFRelease(password); + + password = CFSTR("facebook!{}"); + is(false, SecPasswordIsPasswordWeak2(isSimple, password)); + CFRelease(password); + + password = CFSTR("12345678"); + is(true, SecPasswordIsPasswordWeak2(isSimple, password)); + CFRelease(password); + } int si_73_secpasswordgenerate(int argc, char *const *argv) { - plan_tests(279); + plan_tests(298); tests(); return 0; diff --git a/sec/Security/Regressions/secitem/si-74-OTAPKISigner.c b/Security/sec/Security/Regressions/secitem/si-74-OTAPKISigner.c similarity index 98% rename from sec/Security/Regressions/secitem/si-74-OTAPKISigner.c rename to Security/sec/Security/Regressions/secitem/si-74-OTAPKISigner.c index 2bf3ee88..b555e4d4 100644 --- a/sec/Security/Regressions/secitem/si-74-OTAPKISigner.c +++ b/Security/sec/Security/Regressions/secitem/si-74-OTAPKISigner.c @@ -1,12 +1,27 @@ /* - * si-74-OTAPKISigner.c - * Security - * - * Created by James Murphy on 07/02/13. - * Copyright (c) 2013 Apple Inc. All Rights Reserved. + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include #include #include @@ -969,7 +984,9 @@ static void test_OTA_PKI() CFReleaseSafe(payload); CFReleaseSafe(manifestRef); CFReleaseSafe(base_manifest_data); - CFReleaseSafe(base_manifestRef); + CFReleaseSafe(base_manifestRef); + + CFReleaseSafe(apple_pki_settings_root_certificate_authority_cert_data); } diff --git a/sec/Security/Regressions/secitem/si-75-AppleIDRecordSigning.c b/Security/sec/Security/Regressions/secitem/si-75-AppleIDRecordSigning.c similarity index 94% rename from sec/Security/Regressions/secitem/si-75-AppleIDRecordSigning.c rename to Security/sec/Security/Regressions/secitem/si-75-AppleIDRecordSigning.c index a6c88098..7deca91b 100644 --- a/sec/Security/Regressions/secitem/si-75-AppleIDRecordSigning.c +++ b/Security/sec/Security/Regressions/secitem/si-75-AppleIDRecordSigning.c @@ -1,10 +1,26 @@ -// -// si-75-AppleIDRecordSigning.c -// sec -// -// Created by local on 7/31/13. -// -// +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include #include @@ -222,6 +238,8 @@ static void tests(void) CFReleaseSafe(policy); CFReleaseSafe(certs); CFReleaseSafe(appleid_record_signing_cert); + CFReleaseSafe(appleid_intermediate_cert_data); + CFReleaseSafe(appleid_record_signing_cert_data); } diff --git a/Security/sec/Security/Regressions/secitem/si-76-shared-credentials.c b/Security/sec/Security/Regressions/secitem/si-76-shared-credentials.c new file mode 100644 index 00000000..047d70d1 --- /dev/null +++ b/Security/sec/Security/Regressions/secitem/si-76-shared-credentials.c @@ -0,0 +1,163 @@ +// +// si-76-shared-credentials.c +// sec +// + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Security_regressions.h" + +#define WAIT_WHILE(X) { while ((X)) { (void)CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, TRUE); } } + +static bool expected_failure(OSStatus status) +{ + return ((status == errSecMissingEntitlement) || + (status == errSecBadReq)); +} + +static void tests(void) +{ + // look up our entry for localhost + CFStringRef acct1 = CFSTR("local"); + CFStringRef acct2 = CFSTR("admin"); + CFStringRef fqdn = CFSTR("localhost"); + CFStringRef not_my_fqdn = CFSTR("store.apple.com"); // something we aren't entitled to share + __block bool adding; + __block bool requesting; + __block bool deleting; + +// UInt8 buf[6] = { 'l', 'o', 'c', 'a', 'l', '\0' }; +// CFDataRef cred = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)&buf, sizeof(buf)); + CFStringRef cred = CFStringCreateCopy(kCFAllocatorDefault, CFSTR("local")); + + // should get denied if we request a fqdn which is not in our entitlement + requesting = true; + SecRequestSharedWebCredential(not_my_fqdn, NULL, ^void (CFArrayRef credentials, CFErrorRef error) { + OSStatus status = (OSStatus)((error) ? CFErrorGetCode(error) : errSecSuccess); + is(status == errSecItemNotFound || expected_failure(status), true, "fqdn not entitled"); + is(CFArrayGetCount(credentials) > 0, false, "returned credential array == 0"); + requesting = false; + }); + WAIT_WHILE(requesting); + + // add (or update) credentials for two different accounts on the same server + adding = true; + SecAddSharedWebCredential(fqdn, acct1, cred, ^void (CFErrorRef error) { + OSStatus status = (OSStatus)((error) ? CFErrorGetCode(error) : errSecSuccess); + // TODO: need a proper teamID-enabled application identifier to succeed; expect auth failure + if (status == errSecAuthFailed || expected_failure(status)) { status = errSecSuccess; } + ok_status(status); + adding = false; + }); + WAIT_WHILE(adding); + + adding = true; + SecAddSharedWebCredential(fqdn, acct2, cred, ^void (CFErrorRef error) { + OSStatus status = (OSStatus)((error) ? CFErrorGetCode(error) : errSecSuccess); + // TODO: need a proper teamID-enabled application identifier to succeed; expect auth failure + if (status == errSecAuthFailed || expected_failure(status)) { status = errSecSuccess; } + ok_status(status); + adding = false; + }); + WAIT_WHILE(adding); + + // look up credential with specific account + requesting = true; + SecRequestSharedWebCredential(fqdn, acct1, ^void (CFArrayRef credentials, CFErrorRef error) { + OSStatus status = (OSStatus)((error) ? CFErrorGetCode(error) : errSecSuccess); + // TODO: need a proper teamID-enabled application identifier to succeed; expect no items + bool notFound = false; + if (status == errSecItemNotFound || expected_failure(status)) { + status = errSecSuccess; notFound = true; + } + ok_status(status); + + // should find only one credential if a specific account is provided + CFIndex credentialCount = CFArrayGetCount(credentials); + // TODO: need a proper teamID-enabled application identifier to succeed; expect 0 items + if (credentialCount == 0 && notFound) { credentialCount = 1; } + is(credentialCount == 1, true, "returned credentials == 1"); + requesting = false; + }); + WAIT_WHILE(requesting); + + // look up credential with NULL account parameter + requesting = true; + SecRequestSharedWebCredential(fqdn, NULL, ^void (CFArrayRef credentials, CFErrorRef error) { + OSStatus status = (OSStatus)((error) ? CFErrorGetCode(error) : errSecSuccess); + // TODO: need a proper teamID-enabled application identifier to succeed; expect auth failure + bool notFound = false; + if (status == errSecItemNotFound || expected_failure(status)) { + status = errSecSuccess; notFound = true; + } + ok_status(status); + + // should find only one credential if no account is provided + // (since UI dialog only permits one credential to be selected) + CFIndex credentialCount = CFArrayGetCount(credentials); + // TODO: need a proper teamID-enabled application identifier to succeed + if (credentialCount == 0 && notFound) { credentialCount = 1; } + is(credentialCount == 1, true, "returned credentials == 1"); + requesting = false; + }); + WAIT_WHILE(requesting); + + // pass NULL to delete our credentials + deleting = true; + SecAddSharedWebCredential(fqdn, acct1, NULL, ^void (CFErrorRef error) { + OSStatus status = (OSStatus)((error) ? CFErrorGetCode(error) : errSecSuccess); + // TODO: need a proper teamID-enabled application identifier to succeed; expect auth failure + if (status == errSecAuthFailed || expected_failure(status)) { status = errSecSuccess; } + ok_status(status); + deleting = false; + }); + WAIT_WHILE(deleting); + + deleting = true; + SecAddSharedWebCredential(fqdn, acct2, NULL, ^void (CFErrorRef error) { + OSStatus status = (OSStatus)((error) ? CFErrorGetCode(error) : errSecSuccess); + // TODO: need a proper teamID-enabled application identifier to succeed; expect auth failure + if (status == errSecAuthFailed || expected_failure(status)) { status = errSecSuccess; } + ok_status(status); + deleting = false; + }); + WAIT_WHILE(deleting); + + // look up credentials again; should find nothing this time + requesting = true; + SecRequestSharedWebCredential(fqdn, NULL, ^void (CFArrayRef credentials, CFErrorRef error) { + OSStatus status = (OSStatus)((error) ? CFErrorGetCode(error) : errSecSuccess); + // TODO: need a proper teamID-enabled application identifier to succeed; expect auth failure + if (status == errSecAuthFailed || expected_failure(status)) { status = errSecItemNotFound; } + is_status(status, errSecItemNotFound); + is(CFArrayGetCount(credentials) > 0, false, "returned credential array == 0"); + requesting = false; + }); + WAIT_WHILE(requesting); + + CFRelease(cred); +} + +int si_76_shared_credentials(int argc, char *const *argv) +{ + plan_tests(12); + tests(); + return 0; +} diff --git a/Security/sec/Security/Regressions/secitem/si-78-query-attrs.c b/Security/sec/Security/Regressions/secitem/si-78-query-attrs.c new file mode 100644 index 00000000..912c5af1 --- /dev/null +++ b/Security/sec/Security/Regressions/secitem/si-78-query-attrs.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2006-2010,2014 Apple Inc. All Rights Reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "Security_regressions.h" + +/* Test regression from REGRESSION (Security-1601?): Preferences crashes when trying to view Safari > Saved Credit Cards (SecItemCopyMatching returns empty dictionaries when kSecReturnAttributes is not true) */ + +static void tests(void) +{ + /* + security item -g class=genp agrp=com.apple.safari.credit-cards sync=1 + acct : 3B1ED3EC-A558-43F0-B337-6E891000466B + agrp : com.apple.safari.credit-cards + cdat : 2014-01-24 22:58:17 +0000 + icmt : This keychain item is used by Safari to automatically fill credit card information in web forms. + labl : Safari Credit Card Entry: + mdat : 2014-03-31 05:22:53 +0000 + pdmn : ak + svce : SafariCreditCardEntries + sync : 1 + tomb : 0 + v_Data : 62706C6973743030D30102030405065E43617264686F6C6465724E616D655F1010436172644E616D655549537472696E675A436172644E756D6265725B4D69747A2050657474656C505F101031323334353637383938373636353535080F1E313C4849000000000000010100000000000000070000000000000000000000000000005C + + We actually use altered data and attributes to not mess up with real CreditCard data when running tests on system + where data exist. + */ + static const uint8_t vdata[] = { + 0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30, 0xd3, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x5e, 0x43, 0x61, 0x72, 0x64, 0x68, 0x6f, 0x6c, 0x64, + 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x5f, 0x10, 0x10, 0x43, 0x61, 0x72, + 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x55, 0x49, 0x53, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x5a, 0x43, 0x61, 0x72, 0x64, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, + 0x5b, 0x4d, 0x69, 0x74, 0x7a, 0x20, 0x50, 0x65, 0x74, 0x74, 0x65, 0x6c, + 0x50, 0x5f, 0x10, 0x10, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x38, 0x37, 0x36, 0x36, 0x35, 0x35, 0x35, 0x08, 0x0f, 0x1e, 0x31, + 0x3c, 0x48, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c + }; + CFDataRef data = CFDataCreate(NULL, vdata, sizeof(vdata)); + CFDictionaryRef item = CFDictionaryCreateForCFTypes(NULL, + kSecClass, kSecClassGenericPassword, + kSecAttrAccount, CFSTR("3B1ED3EC-A558-43F0-B337-6E891000466B-test"), + kSecAttrService, CFSTR("SafariCreditCardEntries-test"), + kSecValueData, data, + NULL); + ok_status(SecItemAdd(item, NULL), "add generic password"); + + /* + agrp = "com.apple.safari.credit-cards"; + class = genp; + "m_Limit" = "m_LimitAll"; + "r_Data" = 1; + "r_PersistentRef" = 1; + svce = SafariCreditCardEntries; + */ + CFDictionaryRef query = CFDictionaryCreateForCFTypes(NULL, + kSecClass, kSecClassGenericPassword, + kSecAttrService, CFSTR("SafariCreditCardEntries-test"), + kSecMatchLimit, kSecMatchLimitAll, + kSecReturnData, kCFBooleanTrue, + kSecReturnPersistentRef, kCFBooleanTrue, + NULL); + CFTypeRef result; + ok_status(SecItemCopyMatching(query, &result), "query generic password"); + ok(isArray(result) && CFArrayGetCount(result) == 1, "return 1-sized array of results"); + CFDictionaryRef row = CFArrayGetValueAtIndex(result, 0); + ok(isDictionary(row), "array row is dictionary"); + ok(isData(CFDictionaryGetValue(row, kSecValuePersistentRef)), "result contains valid persistentref"); + ok(isData(CFDictionaryGetValue(row, kSecValueData)), "result contains data"); + ok(CFEqual(CFDictionaryGetValue(row, kSecValueData), data), "returned data are correct"); + + CFRelease(result); + CFRelease(query); + query = CFDictionaryCreateForCFTypes(NULL, + kSecClass, kSecClassGenericPassword, + kSecAttrService, CFSTR("SafariCreditCardEntries-test"), + kSecMatchLimit, kSecMatchLimitAll, + kSecReturnData, kCFBooleanTrue, + NULL); + ok_status(SecItemCopyMatching(query, &result), "query generic password"); + ok(isArray(result) && CFArrayGetCount(result) == 1, "return 1-sized array of results"); + row = CFArrayGetValueAtIndex(result, 0); + ok(isData(row), "result contains data"); + ok(CFEqual(row, data), "returned data are correct"); + + CFRelease(result); + CFRelease(query); + query = CFDictionaryCreateForCFTypes(NULL, + kSecClass, kSecClassGenericPassword, + kSecAttrService, CFSTR("SafariCreditCardEntries-test"), + kSecMatchLimit, kSecMatchLimitAll, + kSecReturnPersistentRef, kCFBooleanTrue, + NULL); + ok_status(SecItemCopyMatching(query, &result), "query generic password"); + ok(isArray(result) && CFArrayGetCount(result) == 1, "return 1-sized array of results"); + row = CFArrayGetValueAtIndex(result, 0); + ok(isData(row), "result contains data"); + + CFRelease(query); + query = CFDictionaryCreateForCFTypes(NULL, + kSecClass, kSecClassGenericPassword, + kSecAttrService, CFSTR("SafariCreditCardEntries-test"), + NULL); + ok_status(SecItemDelete(query), "delete testing item"); + + CFRelease(query); + CFRelease(data); + CFRelease(item); +} + +int si_78_query_attrs(int argc, char *const *argv) +{ + plan_tests(15); + + tests(); + + return 0; +} diff --git a/Security/sec/Security/Regressions/secitem/si-79-smp-cert-policy.c b/Security/sec/Security/Regressions/secitem/si-79-smp-cert-policy.c new file mode 100644 index 00000000..f0f0d916 --- /dev/null +++ b/Security/sec/Security/Regressions/secitem/si-79-smp-cert-policy.c @@ -0,0 +1,410 @@ +/* + * si-79-smp-cert-policy.c + * Security + * + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Security_regressions.h" + +#if TARGET_OS_IPHONE + +static const UInt8 kTestAppleRootCAECCCert[] = { + 0x30,0x82,0x02,0x27,0x30,0x82,0x01,0xCD,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x59, + 0xD1,0xEC,0x10,0x92,0x41,0xC7,0xC4,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x04,0x03,0x02,0x30,0x67,0x31,0x21,0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x0C,0x18, + 0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20, + 0x43,0x41,0x20,0x2D,0x20,0x45,0x43,0x43,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,0x34,0x30,0x31,0x33,0x31,0x32,0x31,0x34,0x36,0x34,0x36,0x5A,0x17,0x0D,0x33, + 0x34,0x30,0x31,0x32,0x36,0x32,0x31,0x34,0x36,0x34,0x36,0x5A,0x30,0x67,0x31,0x21, + 0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x0C,0x18,0x54,0x65,0x73,0x74,0x20,0x41,0x70, + 0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x20,0x2D,0x20,0x45,0x43, + 0x43,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,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D, + 0x02,0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00,0x04, + 0x7B,0x38,0x10,0xD0,0x0A,0xA3,0x1B,0x7C,0x1D,0x24,0xFB,0x39,0xD6,0x6B,0x1C,0x0A, + 0x97,0x48,0x30,0xFF,0x4C,0x70,0x49,0x3D,0x21,0x66,0x4F,0xF5,0x89,0x00,0xAF,0x93, + 0xEF,0x74,0x9A,0xE8,0x4C,0x27,0x3D,0xBE,0x95,0x50,0x52,0x3D,0x53,0x90,0xF3,0x32, + 0xAB,0x83,0xB6,0x5E,0x73,0xC8,0xE7,0x17,0x8B,0x18,0x09,0x93,0x9F,0x97,0xD5,0x16, + 0xA3,0x63,0x30,0x61,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xD2, + 0x47,0xE2,0xC5,0x34,0x71,0xC6,0x10,0x8D,0x93,0xEE,0x04,0x43,0x1F,0xE1,0x1B,0x0F, + 0xE1,0xCD,0x11,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,0xD2,0x47,0xE2,0xC5,0x34,0x71,0xC6,0x10,0x8D,0x93,0xEE,0x04,0x43,0x1F,0xE1, + 0x1B,0x0F,0xE1,0xCD,0x11,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04, + 0x04,0x03,0x02,0x01,0x06,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03, + 0x02,0x03,0x48,0x00,0x30,0x45,0x02,0x21,0x00,0xDC,0x06,0x2B,0x72,0x87,0x20,0xEC, + 0xF7,0xDC,0xC8,0xF2,0xF8,0x89,0x0A,0x57,0x63,0x9A,0x92,0x4A,0x84,0x6E,0xDD,0x17, + 0x50,0xEE,0x6F,0x01,0x4C,0xA1,0xA0,0x74,0xD1,0x02,0x20,0x1F,0x35,0x7A,0xB5,0x0B, + 0x79,0x80,0xD4,0x9C,0x9F,0x31,0xDC,0x36,0x1C,0xC6,0xFD,0x65,0x72,0x40,0x67,0xBA, + 0xFC,0x6F,0x59,0x5E,0xEF,0xEA,0x5E,0x87,0xAC,0x30,0x0D, +}; + +static const UInt8 kTestAppleSystemIntegrationCAECCCert[] = { + 0x30,0x82,0x02,0xD8,0x30,0x82,0x02,0x7F,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x63, + 0x70,0x58,0xB8,0xE5,0xC6,0x5A,0x1E,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x04,0x03,0x02,0x30,0x67,0x31,0x21,0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x0C,0x18, + 0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20, + 0x43,0x41,0x20,0x2D,0x20,0x45,0x43,0x43,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,0x34,0x30,0x32,0x30,0x36,0x31,0x36,0x32,0x36,0x34,0x37,0x5A,0x17,0x0D,0x32, + 0x34,0x30,0x32,0x30,0x34,0x31,0x36,0x32,0x36,0x34,0x37,0x5A,0x30,0x75,0x31,0x2F, + 0x30,0x2D,0x06,0x03,0x55,0x04,0x03,0x0C,0x26,0x54,0x65,0x73,0x74,0x20,0x41,0x70, + 0x70,0x6C,0x65,0x20,0x53,0x79,0x73,0x74,0x65,0x6D,0x20,0x49,0x6E,0x74,0x65,0x67, + 0x72,0x61,0x74,0x69,0x6F,0x6E,0x20,0x43,0x41,0x20,0x2D,0x20,0x45,0x43,0x43,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,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01, + 0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00,0x04,0x51,0xB4, + 0x48,0x6D,0x6B,0xB1,0xD2,0x48,0xE0,0x04,0x32,0x5E,0xA2,0x91,0xFF,0x86,0x21,0xE2, + 0x20,0x09,0xCE,0x46,0x7E,0xC2,0x10,0xAA,0x20,0x8A,0x47,0xF4,0x59,0x71,0xC2,0x69, + 0xBD,0xFE,0xF4,0xB8,0xEC,0xCB,0xDF,0x45,0x06,0x9B,0x64,0x3A,0x98,0x60,0x08,0x16, + 0xB8,0x87,0xF4,0x9E,0x6E,0xC5,0xBF,0x14,0xA9,0xB0,0x40,0x6B,0xD1,0x0B,0xA3,0x82, + 0x01,0x05,0x30,0x82,0x01,0x01,0x30,0x54,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x01,0x01,0x04,0x48,0x30,0x46,0x30,0x44,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x30,0x01,0x86,0x38,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2D, + 0x75,0x61,0x74,0x2E,0x63,0x6F,0x72,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63, + 0x6F,0x6D,0x2F,0x6F,0x63,0x73,0x70,0x30,0x34,0x2D,0x74,0x65,0x73,0x74,0x61,0x70, + 0x70,0x6C,0x65,0x72,0x6F,0x6F,0x74,0x63,0x61,0x65,0x63,0x63,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xA3,0x46,0x13,0xFE,0x94,0x7F,0xE0,0xA2,0x8F, + 0x16,0xF0,0xF8,0x1E,0x9B,0x8B,0x14,0x84,0x70,0x59,0xF9,0x30,0x12,0x06,0x03,0x55, + 0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30, + 0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xD2,0x47,0xE2,0xC5, + 0x34,0x71,0xC6,0x10,0x8D,0x93,0xEE,0x04,0x43,0x1F,0xE1,0x1B,0x0F,0xE1,0xCD,0x11, + 0x30,0x45,0x06,0x03,0x55,0x1D,0x1F,0x04,0x3E,0x30,0x3C,0x30,0x3A,0xA0,0x38,0xA0, + 0x36,0x86,0x34,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2D,0x75,0x61, + 0x74,0x2E,0x63,0x6F,0x72,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, + 0x2F,0x74,0x65,0x73,0x74,0x61,0x70,0x70,0x6C,0x65,0x72,0x6F,0x6F,0x74,0x63,0x61, + 0x65,0x63,0x63,0x2E,0x63,0x72,0x6C,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01, + 0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x04,0x03,0x02,0x03,0x47,0x00,0x30,0x44,0x02,0x20,0x6A,0x68,0x3F,0x95,0xCA,0x35, + 0xD2,0xB6,0x46,0xF5,0x34,0xA2,0xF4,0x1A,0x8C,0x15,0x6D,0xC6,0x7E,0x88,0x95,0x9E, + 0x55,0x8E,0x8F,0x78,0x65,0x9D,0x5B,0x70,0x63,0x45,0x02,0x20,0x1B,0x45,0x91,0x33, + 0xF1,0x6E,0x7B,0xC1,0x0D,0x2E,0xF0,0x33,0xB3,0xFF,0xC3,0x1F,0xAC,0x6F,0xAB,0xFC, + 0x67,0xB6,0x1B,0x57,0xAF,0x88,0xA6,0xCF,0xA7,0x4F,0x20,0x06, +}; + +static const UInt8 kTestSMPCert[] = { + 0x30,0x82,0x02,0xC4,0x30,0x82,0x02,0x6B,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x4B, + 0x62,0x72,0xF1,0xCD,0xCE,0xBA,0x8D,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x04,0x03,0x02,0x30,0x75,0x31,0x2F,0x30,0x2D,0x06,0x03,0x55,0x04,0x03,0x0C,0x26, + 0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x53,0x79,0x73,0x74,0x65, + 0x6D,0x20,0x49,0x6E,0x74,0x65,0x67,0x72,0x61,0x74,0x69,0x6F,0x6E,0x20,0x43,0x41, + 0x20,0x2D,0x20,0x45,0x43,0x43,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,0x34, + 0x30,0x32,0x30,0x36,0x31,0x36,0x34,0x35,0x35,0x35,0x5A,0x17,0x0D,0x31,0x36,0x30, + 0x32,0x30,0x36,0x31,0x36,0x34,0x35,0x35,0x35,0x5A,0x30,0x70,0x31,0x32,0x30,0x30, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x29,0x54,0x65,0x73,0x74,0x20,0x45,0x43,0x43,0x20, + 0x43,0x72,0x79,0x70,0x74,0x6F,0x20,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x20, + 0x45,0x6E,0x63,0x69,0x70,0x68,0x65,0x72,0x6D,0x65,0x6E,0x74,0x20,0x55,0x43,0x35, + 0x31,0x18,0x30,0x16,0x06,0x03,0x55,0x04,0x0B,0x0C,0x0F,0x43,0x72,0x79,0x70,0x74, + 0x6F,0x20,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x59,0x30,0x13, + 0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x03,0x01,0x07,0x03,0x42,0x00,0x04,0xAC,0xB8,0x3A,0x1B,0x4E,0x15,0x87,0xDD,0xCF, + 0xCD,0x21,0x30,0x23,0x28,0xF2,0x86,0x10,0x28,0x7C,0xF3,0x65,0x39,0xCD,0xFD,0x30, + 0xB5,0x61,0x71,0xE0,0x59,0x20,0xB7,0xC0,0x59,0x24,0xF9,0x7F,0x75,0xBB,0xD5,0x30, + 0xC0,0x25,0x52,0xE2,0x13,0xF1,0x0B,0x4D,0x50,0xC4,0x46,0x57,0x6A,0x13,0x69,0xC9, + 0x82,0x8A,0xA9,0x21,0x24,0xD5,0x92,0xA3,0x81,0xE9,0x30,0x81,0xE6,0x30,0x4E,0x06, + 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x42,0x30,0x40,0x30,0x3E,0x06, + 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x32,0x68,0x74,0x74,0x70,0x3A, + 0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2D,0x75,0x61,0x74,0x2E,0x63,0x6F,0x72,0x70,0x2E, + 0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x6F,0x63,0x73,0x70,0x30,0x34, + 0x2D,0x74,0x65,0x73,0x74,0x61,0x73,0x69,0x63,0x61,0x65,0x63,0x63,0x30,0x1D,0x06, + 0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x73,0x0B,0x8A,0xF4,0xFA,0xA2,0xC9,0x6F, + 0xAC,0x2E,0x9C,0xCC,0xE9,0xFE,0xBD,0xA6,0xE2,0xF0,0xC0,0xFF,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,0xA3,0x46,0x13,0xFE,0x94,0x7F,0xE0,0xA2,0x8F, + 0x16,0xF0,0xF8,0x1E,0x9B,0x8B,0x14,0x84,0x70,0x59,0xF9,0x30,0x36,0x06,0x03,0x55, + 0x1D,0x1F,0x04,0x2F,0x30,0x2D,0x30,0x2B,0xA0,0x29,0xA0,0x27,0x86,0x25,0x68,0x74, + 0x74,0x70,0x3A,0x2F,0x2F,0x75,0x61,0x74,0x2D,0x63,0x72,0x6C,0x2E,0x61,0x70,0x70, + 0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x61,0x73,0x69,0x63,0x61,0x65,0x63,0x63,0x2E, + 0x63,0x72,0x6C,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03, + 0x02,0x03,0x28,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,0x03, + 0x47,0x00,0x30,0x44,0x02,0x20,0x60,0x56,0xC6,0x37,0xB9,0x8B,0x58,0x05,0xF0,0x89, + 0x61,0x61,0xA4,0xB8,0x83,0x5F,0x9E,0xCF,0x6E,0x21,0x6E,0xEF,0xA1,0x89,0x5C,0xB5, + 0x2E,0x6E,0xE1,0x10,0x46,0x4F,0x02,0x20,0x07,0x8D,0xA5,0xD0,0xC8,0x85,0x31,0xF0, + 0x4B,0x2C,0xB5,0x1B,0x96,0xC4,0x5D,0x86,0x85,0xF8,0x1A,0x3A,0x37,0x6B,0xEC,0xD0, + 0x7F,0x45,0x88,0x35,0xD0,0x75,0xDC,0xA2, +}; + +static const UInt8 kAppleSystemIntegrationCAG3Cert[]={ + 0x30,0x82,0x02,0xEB,0x30,0x82,0x02,0x70,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x61, + 0x5A,0xA1,0xA9,0x73,0x3C,0xEB,0x81,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x04,0x03,0x02,0x30,0x67,0x31,0x1B,0x30,0x19,0x06,0x03,0x55,0x04,0x03,0x0C,0x12, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x20,0x2D,0x20, + 0x47,0x33,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E, + 0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D, + 0x31,0x34,0x30,0x35,0x30,0x36,0x32,0x33,0x34,0x35,0x31,0x30,0x5A,0x17,0x0D,0x32, + 0x39,0x30,0x35,0x30,0x36,0x32,0x33,0x34,0x35,0x31,0x30,0x5A,0x30,0x75,0x31,0x29, + 0x30,0x27,0x06,0x03,0x55,0x04,0x03,0x0C,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x53, + 0x79,0x73,0x74,0x65,0x6D,0x20,0x49,0x6E,0x74,0x65,0x67,0x72,0x61,0x74,0x69,0x6F, + 0x6E,0x20,0x43,0x41,0x20,0x2D,0x20,0x47,0x33,0x31,0x26,0x30,0x24,0x06,0x03,0x55, + 0x04,0x0B,0x0C,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66, + 0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74, + 0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C, + 0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01, + 0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00,0x04,0xD1,0x57, + 0x4C,0x8E,0x38,0xD5,0xF7,0x36,0x28,0x54,0x7D,0x16,0x1A,0xE4,0xF0,0x4F,0x1E,0xB2, + 0xA8,0xC0,0x2F,0x1F,0xE2,0x26,0x69,0x76,0xDF,0x36,0xAB,0xDC,0xED,0xAF,0xA6,0x92, + 0xF2,0x5A,0x4E,0xAF,0x29,0x84,0xAC,0xF1,0x86,0x15,0x04,0x43,0xFA,0x83,0x03,0x03, + 0x58,0xF6,0x5E,0x8F,0xC2,0x22,0x29,0x28,0xF2,0x06,0x18,0x09,0x30,0x79,0xA3,0x81, + 0xF7,0x30,0x81,0xF4,0x30,0x46,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01, + 0x04,0x3A,0x30,0x38,0x30,0x36,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01, + 0x86,0x2A,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E,0x61,0x70, + 0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x6F,0x63,0x73,0x70,0x30,0x34,0x2D,0x61, + 0x70,0x70,0x6C,0x65,0x72,0x6F,0x6F,0x74,0x63,0x61,0x67,0x33,0x30,0x1D,0x06,0x03, + 0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x26,0x5D,0xAF,0x92,0x3C,0x20,0x98,0x18,0x35, + 0xBE,0x98,0x50,0xA6,0x01,0x5E,0xA7,0xE9,0x21,0x2D,0x79,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,0xBB,0xB0,0xDE,0xA1,0x58,0x33,0x88, + 0x9A,0xA4,0x8A,0x99,0xDE,0xBE,0xBD,0xEB,0xAF,0xDA,0xCB,0x24,0xAB,0x30,0x37,0x06, + 0x03,0x55,0x1D,0x1F,0x04,0x30,0x30,0x2E,0x30,0x2C,0xA0,0x2A,0xA0,0x28,0x86,0x26, + 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x61,0x70,0x70,0x6C,0x65, + 0x2E,0x63,0x6F,0x6D,0x2F,0x61,0x70,0x70,0x6C,0x65,0x72,0x6F,0x6F,0x74,0x63,0x61, + 0x67,0x33,0x2E,0x63,0x72,0x6C,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF, + 0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x10,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63, + 0x64,0x06,0x02,0x0D,0x04,0x02,0x05,0x00,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE, + 0x3D,0x04,0x03,0x02,0x03,0x69,0x00,0x30,0x66,0x02,0x31,0x00,0xD6,0xB2,0xC3,0xB3, + 0x3D,0xE3,0x30,0xE4,0x7A,0x24,0x62,0x35,0xDA,0xF0,0xB9,0xDC,0x3B,0x66,0x94,0x40, + 0xBA,0x8D,0x43,0xC4,0x2A,0xF5,0xE3,0xA1,0x4A,0x7C,0xD5,0x87,0x24,0xCC,0xEA,0x49, + 0x0E,0xEE,0xAA,0xE4,0x72,0x0D,0x63,0x4F,0x03,0x07,0x6C,0x63,0x02,0x31,0x00,0xFF, + 0xDF,0x24,0x7E,0xA8,0x28,0x02,0x55,0xBF,0xEB,0x8D,0x72,0x1D,0xC9,0x27,0x82,0xA1, + 0x0D,0xB7,0xD5,0x0F,0xAA,0xF2,0xFF,0x49,0xFA,0x3F,0xA4,0xED,0x44,0xEE,0x53,0x76, + 0x89,0x18,0x0A,0x64,0xC6,0x96,0x00,0x47,0x9D,0x40,0x04,0xEF,0x5A,0xAA,0x07, +}; + +static const UInt8 kProdSMPCert[]={ + 0x30,0x82,0x02,0xC6,0x30,0x82,0x02,0x6D,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x52, + 0x6F,0x62,0xEF,0x7A,0x0F,0x39,0x08,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x04,0x03,0x02,0x30,0x75,0x31,0x29,0x30,0x27,0x06,0x03,0x55,0x04,0x03,0x0C,0x20, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x53,0x79,0x73,0x74,0x65,0x6D,0x20,0x49,0x6E,0x74, + 0x65,0x67,0x72,0x61,0x74,0x69,0x6F,0x6E,0x20,0x43,0x41,0x20,0x2D,0x20,0x47,0x33, + 0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, + 0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30, + 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D,0x31,0x34, + 0x30,0x35,0x30,0x38,0x30,0x31,0x32,0x31,0x31,0x34,0x5A,0x17,0x0D,0x31,0x36,0x30, + 0x36,0x30,0x36,0x30,0x31,0x32,0x31,0x31,0x34,0x5A,0x30,0x6C,0x31,0x32,0x30,0x30, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x29,0x65,0x63,0x63,0x2D,0x63,0x72,0x79,0x70,0x74, + 0x6F,0x2D,0x73,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x2D,0x65,0x6E,0x63,0x69,0x70, + 0x68,0x65,0x72,0x6D,0x65,0x6E,0x74,0x5F,0x55,0x43,0x35,0x2D,0x50,0x52,0x4F,0x44, + 0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0B,0x0C,0x0B,0x69,0x4F,0x53,0x20,0x53, + 0x79,0x73,0x74,0x65,0x6D,0x73,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C, + 0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06, + 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86, + 0x48,0xCE,0x3D,0x02,0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03, + 0x42,0x00,0x04,0xBC,0x09,0xB9,0xBA,0x02,0xDA,0x80,0x3F,0x60,0xCC,0xE0,0xEB,0xC6, + 0x16,0x76,0xDE,0x7F,0x40,0x7A,0x52,0x34,0xB8,0x22,0x65,0xB8,0x7A,0x08,0x22,0xD1, + 0x6F,0xF4,0x5A,0x0F,0x69,0xE2,0x31,0x7F,0x83,0x60,0x04,0x0A,0xBF,0x80,0xF7,0x8D, + 0xEB,0x40,0x15,0x84,0xBE,0x65,0x70,0x41,0x22,0xEE,0x63,0x0B,0x04,0x5E,0xB3,0x4F, + 0xD7,0x73,0x0E,0xA3,0x81,0xEF,0x30,0x81,0xEC,0x30,0x45,0x06,0x08,0x2B,0x06,0x01, + 0x05,0x05,0x07,0x01,0x01,0x04,0x39,0x30,0x37,0x30,0x35,0x06,0x08,0x2B,0x06,0x01, + 0x05,0x05,0x07,0x30,0x01,0x86,0x29,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63, + 0x73,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x6F,0x63,0x73, + 0x70,0x30,0x34,0x2D,0x61,0x70,0x70,0x6C,0x65,0x73,0x69,0x63,0x61,0x33,0x30,0x31, + 0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xD2,0xFD,0x1F,0xDD,0x61, + 0xA8,0xE4,0x0E,0x78,0xBD,0xDB,0x60,0xB9,0xCC,0x7A,0x3F,0x46,0x8B,0xF5,0xA4,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,0x26,0x5D,0xAF,0x92,0x3C,0x20, + 0x98,0x18,0x35,0xBE,0x98,0x50,0xA6,0x01,0x5E,0xA7,0xE9,0x21,0x2D,0x79,0x30,0x34, + 0x06,0x03,0x55,0x1D,0x1F,0x04,0x2D,0x30,0x2B,0x30,0x29,0xA0,0x27,0xA0,0x25,0x86, + 0x23,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x61,0x70,0x70,0x6C, + 0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x61,0x70,0x70,0x6C,0x65,0x73,0x69,0x63,0x61,0x33, + 0x2E,0x63,0x72,0x6C,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04, + 0x03,0x02,0x03,0x28,0x30,0x0F,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06, + 0x1E,0x04,0x02,0x05,0x00,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03, + 0x02,0x03,0x47,0x00,0x30,0x44,0x02,0x20,0x33,0x1F,0xB7,0xC0,0x93,0x22,0x9C,0x71, + 0xD8,0x62,0xF1,0x7B,0x72,0xDC,0x97,0x63,0xDF,0xD1,0x3B,0xBF,0xD7,0x8C,0xB0,0xE7, + 0xE0,0xC1,0x6B,0x26,0x6A,0xC4,0xF0,0x14,0x02,0x20,0x20,0xD7,0xD7,0xD1,0x7B,0xAD, + 0x90,0x83,0x23,0xEA,0x34,0x1E,0x0C,0x8F,0x90,0xAB,0x97,0xB1,0x2D,0x06,0xE3,0x30, + 0x56,0x29,0x20,0x94,0x74,0x36,0xFD,0x1B,0x9C,0xD5, +}; + +static void test_smp_cert_policy() +{ + CFDateRef date=NULL; + CFArrayRef policies=NULL; + SecPolicyRef policy=NULL; + SecTrustRef trust=NULL; + SecCertificateRef testCert0=NULL, testCert1=NULL, testRoot=NULL; + SecCertificateRef prodCert0=NULL, prodCert1=NULL; + CFMutableArrayRef testCerts=NULL, prodCerts=NULL; + SecTrustResultType trustResult; + CFIndex chainLen; + + /* Test hierarchy */ + isnt(testCert0 = SecCertificateCreateWithBytes(NULL, kTestSMPCert, sizeof(kTestSMPCert)), + NULL, "create testCert0"); + isnt(testCert1 = SecCertificateCreateWithBytes(NULL, kTestAppleSystemIntegrationCAECCCert, sizeof(kTestAppleSystemIntegrationCAECCCert)), + NULL, "create testCert1"); + isnt(testRoot = SecCertificateCreateWithBytes(NULL, kTestAppleRootCAECCCert, sizeof(kTestAppleRootCAECCCert)), + NULL, "create testRoot"); + + isnt(testCerts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create test cert array"); + CFArrayAppendValue(testCerts, testCert0); + CFArrayAppendValue(testCerts, testCert1); + + /* Production hierarchy */ + isnt(prodCert0 = SecCertificateCreateWithBytes(NULL, kProdSMPCert, sizeof(kProdSMPCert)), + NULL, "create prodCert0"); + isnt(prodCert1 = SecCertificateCreateWithBytes(NULL, kAppleSystemIntegrationCAG3Cert, sizeof(kAppleSystemIntegrationCAG3Cert)), + NULL, "create prodCert1"); + + isnt(prodCerts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create prod cert array"); + CFArrayAppendValue(prodCerts, prodCert0); + CFArrayAppendValue(prodCerts, prodCert1); + + + /* Case 1: production policy with production certs (should succeed) */ + isnt(policy = SecPolicyCreateAppleSMPEncryption(), NULL, "create policy"); + policies = CFArrayCreate(NULL, (const void **)&policy, 1, &kCFTypeArrayCallBacks); + CFRelease(policy); + policy = NULL; + ok_status(SecTrustCreateWithCertificates(prodCerts, policies, &trust), + "create trust"); + CFRelease(policies); + policies = NULL; + isnt(date = CFDateCreateForGregorianZuluMoment(NULL, 2014, 4, 11, 12, 0, 0), + NULL, "create verify date"); + //%%% policy currently doesn't care about expiration dates + //ok_status(SecTrustSetVerifyDate(trust, date), "set date"); + CFReleaseSafe(date); + date = NULL; + ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); + ok(trustResult == kSecTrustResultUnspecified, "trustResult 4 expected (got %d)", + (int)trustResult); + chainLen = SecTrustGetCertificateCount(trust); + ok(chainLen == 3, "chain length 3 expected (got %d)", (int)chainLen); + CFRelease(trust); + trust = NULL; + + /* Case 2: test policy with test certs (should succeed) */ + isnt(policy = SecPolicyCreateTestAppleSMPEncryption(), NULL, "create policy"); + policies = CFArrayCreate(NULL, (const void **)&policy, 1, &kCFTypeArrayCallBacks); + CFRelease(policy); + policy = NULL; + ok_status(SecTrustCreateWithCertificates(testCerts, policies, &trust), + "create trust"); + CFRelease(policies); + policies = NULL; + isnt(date = CFDateCreateForGregorianZuluMoment(NULL, 2014, 4, 11, 12, 0, 0), + NULL, "create verify date"); + //%%% policy currently doesn't care about expiration dates + //ok_status(SecTrustSetVerifyDate(trust, date), "set date"); + CFReleaseSafe(date); + date = NULL; + + ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); + ok(trustResult == kSecTrustResultUnspecified, "trustResult 4 expected (got %d)", + (int)trustResult); + chainLen = SecTrustGetCertificateCount(trust); + ok(chainLen == 3, "chain length 3 expected (got %d)", (int)chainLen); + CFRelease(trust); + trust = NULL; + + /* Case 3: production policy with test certs (should fail) */ + isnt(policy = SecPolicyCreateAppleSMPEncryption(), NULL, "create policy"); + policies = CFArrayCreate(NULL, (const void **)&policy, 1, &kCFTypeArrayCallBacks); + CFRelease(policy); + policy = NULL; + ok_status(SecTrustCreateWithCertificates(testCerts, policies, &trust), + "create trust"); + CFRelease(policies); + policies = NULL; + isnt(date = CFDateCreateForGregorianZuluMoment(NULL, 2014, 4, 11, 12, 0, 0), + NULL, "create verify date"); + //%%% policy currently doesn't care about expiration dates + //ok_status(SecTrustSetVerifyDate(trust, date), "set date"); + CFReleaseSafe(date); + date = NULL; + ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); + ok(trustResult == kSecTrustResultRecoverableTrustFailure, "trustResult 5 expected (got %d)", + (int)trustResult); + CFRelease(trust); + trust = NULL; + + /* Case 4: test policy with production certs (should fail) */ + isnt(policy = SecPolicyCreateTestAppleSMPEncryption(), NULL, "create policy"); + policies = CFArrayCreate(NULL, (const void **)&policy, 1, &kCFTypeArrayCallBacks); + CFRelease(policy); + policy = NULL; + ok_status(SecTrustCreateWithCertificates(prodCerts, policies, &trust), + "create trust"); + CFRelease(policies); + policies = NULL; + isnt(date = CFDateCreateForGregorianZuluMoment(NULL, 2014, 4, 11, 12, 0, 0), + NULL, "create verify date"); + //%%% policy currently doesn't care about expiration dates + //ok_status(SecTrustSetVerifyDate(trust, date), "set date"); + CFReleaseSafe(date); + date = NULL; + ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); + ok(trustResult == kSecTrustResultRecoverableTrustFailure, "trustResult 5 expected (got %d)", + (int)trustResult); + CFRelease(trust); + trust = NULL; + + CFReleaseSafe(testCert0); + CFReleaseSafe(testCert1); + CFReleaseSafe(testRoot); + CFReleaseSafe(prodCert0); + CFReleaseSafe(prodCert1); + + CFReleaseSafe(testCerts); + CFReleaseSafe(prodCerts); +} + +static void tests(void) +{ + test_smp_cert_policy(); +} + +int si_79_smp_cert_policy(int argc, char *const *argv) +{ + plan_tests(29); + + tests(); + + return 0; +} + +#endif diff --git a/Security/sec/Security/Regressions/secitem/si-80-empty-data.c b/Security/sec/Security/Regressions/secitem/si-80-empty-data.c new file mode 100644 index 00000000..a0d4170e --- /dev/null +++ b/Security/sec/Security/Regressions/secitem/si-80-empty-data.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "Security_regressions.h" + +static void tests(void) +{ + CFDictionaryRef item = CFDictionaryCreateForCFTypes(NULL, + kSecClass, kSecClassGenericPassword, + kSecAttrAccount, CFSTR("empty-data-account-test"), + kSecAttrService, CFSTR("empty-data-svce-test"), + NULL); + ok_status(SecItemAdd(item, NULL), "add generic password"); + + CFDictionaryRef query = CFDictionaryCreateForCFTypes(NULL, + kSecClass, kSecClassGenericPassword, + kSecAttrService, CFSTR("empty-data-svce-test"), + kSecMatchLimit, kSecMatchLimitAll, + kSecReturnData, kCFBooleanTrue, + kSecReturnAttributes, kCFBooleanTrue, + NULL); + CFTypeRef result; + ok_status(SecItemCopyMatching(query, &result), "query generic password"); + ok(isArray(result) && CFArrayGetCount(result) == 1, "return 1-sized array of results"); + CFDictionaryRef row = CFArrayGetValueAtIndex(result, 0); + ok(isDictionary(row), "array row is dictionary"); + ok(CFDictionaryGetValue(row, kSecValueData) == NULL, "result contains no data"); + ok(CFEqual(CFDictionaryGetValue(row, kSecAttrService), CFSTR("empty-data-svce-test")), "svce attribute is returned"); + ok(CFEqual(CFDictionaryGetValue(row, kSecAttrAccount), CFSTR("empty-data-account-test")), "account attribute is returned"); + + CFRelease(result); + CFRelease(query); + query = CFDictionaryCreateForCFTypes(NULL, + kSecClass, kSecClassGenericPassword, + kSecAttrService, CFSTR("empty-data-svce-test"), + NULL); + ok_status(SecItemDelete(query), "delete testing item"); + + CFRelease(query); + CFRelease(item); +} + +int si_80_empty_data(int argc, char *const *argv) +{ + plan_tests(8); + + tests(); + + return 0; +} diff --git a/Security/sec/Security/Regressions/secitem/si-81-item-acl-stress.c b/Security/sec/Security/Regressions/secitem/si-81-item-acl-stress.c new file mode 100644 index 00000000..64990cb2 --- /dev/null +++ b/Security/sec/Security/Regressions/secitem/si-81-item-acl-stress.c @@ -0,0 +1,287 @@ +// +// si-81-item-acl.c +// sec +// +// Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. +// +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Security_regressions.h" + +#if TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_IPHONE_SIMULATOR) +#define USE_KEYSTORE 1 +#elif TARGET_OS_EMBEDDED && !TARGET_IPHONE_SIMULATOR +#define USE_KEYSTORE 1 +#else /* no keystore on this platform */ +#define USE_KEYSTORE 0 +#endif + +#if USE_KEYSTORE +#include +#endif + +enum ItemAttrType { + kBoolItemAttr, + kNumberItemAttr, + kStringItemAttr, + kDataItemAttr, + kBlobItemAttr, + kDateItemAttr, + kAccessabilityItemAttr, + kAccessGroupItemAttr, +}; + +static void WithEachString(void(^each)(CFStringRef attr, enum ItemAttrType atype), ...) { + va_list ap; + va_start(ap, each); + CFStringRef attr; + while((attr = va_arg(ap, CFStringRef)) != NULL) { + enum ItemAttrType atype = va_arg(ap, enum ItemAttrType); + each(attr, atype); + } + va_end(ap); +} + +static void ItemForEachPKAttr(CFMutableDictionaryRef item, void(^each)(CFStringRef attr, enum ItemAttrType atype)) { + CFStringRef iclass = CFDictionaryGetValue(item, kSecClass); + if (!iclass) { + return; + } else if (CFEqual(iclass, kSecClassGenericPassword)) { + WithEachString(each, + kSecAttrAccessGroup, kAccessGroupItemAttr, + kSecAttrAccount, kStringItemAttr, + kSecAttrService, kStringItemAttr, + kSecAttrSynchronizable, kBoolItemAttr, + NULL); + } else if (CFEqual(iclass, kSecClassInternetPassword)) { + WithEachString(each, + kSecAttrAccessGroup, kAccessGroupItemAttr, + kSecAttrAccount, kStringItemAttr, + kSecAttrSecurityDomain, kStringItemAttr, + kSecAttrServer, kStringItemAttr, + kSecAttrProtocol, kNumberItemAttr, + kSecAttrAuthenticationType, kNumberItemAttr, + kSecAttrPort, kNumberItemAttr, + kSecAttrPath, kStringItemAttr, + kSecAttrSynchronizable, kBoolItemAttr, + NULL); + } else if (CFEqual(iclass, kSecClassCertificate)) { + WithEachString(each, + kSecAttrAccessGroup, kAccessGroupItemAttr, + kSecAttrCertificateType, kNumberItemAttr, + kSecAttrIssuer, kDataItemAttr, + kSecAttrSerialNumber, kDataItemAttr, + kSecAttrSynchronizable, kBoolItemAttr, + NULL); + } else if (CFEqual(iclass, kSecClassKey)) { + WithEachString(each, + kSecAttrAccessGroup, kAccessGroupItemAttr, + kSecAttrKeyClass, kStringItemAttr, // kNumberItemAttr on replies + kSecAttrApplicationLabel, kDataItemAttr, + kSecAttrApplicationTag, kDataItemAttr, + kSecAttrKeyType, kNumberItemAttr, + kSecAttrKeySizeInBits, kNumberItemAttr, + kSecAttrEffectiveKeySize, kNumberItemAttr, + kSecAttrStartDate, kDateItemAttr, + kSecAttrEndDate, kDateItemAttr, + kSecAttrSynchronizable, kBoolItemAttr, + NULL); + } else if (CFEqual(iclass, kSecClassIdentity)) { + WithEachString(each, + kSecAttrAccessGroup, kAccessGroupItemAttr, + kSecAttrCertificateType, kNumberItemAttr, + kSecAttrIssuer, kDataItemAttr, + kSecAttrSerialNumber, kDataItemAttr, + kSecAttrSynchronizable, kBoolItemAttr, + kSecAttrKeyClass, kStringItemAttr, // kNumberItemAttr on replies + kSecAttrApplicationLabel, kDataItemAttr, + kSecAttrApplicationTag, kDataItemAttr, + kSecAttrKeyType, kNumberItemAttr, + kSecAttrKeySizeInBits, kNumberItemAttr, + kSecAttrEffectiveKeySize, kNumberItemAttr, + kSecAttrStartDate, kDateItemAttr, + kSecAttrEndDate, kDateItemAttr, + kSecAttrSynchronizable, kBoolItemAttr, + NULL); + } +} + +static CFMutableDictionaryRef ItemCreate(int num) { + CFStringRef iclass = NULL; + switch (num % 4) { + case 0: + iclass = kSecClassInternetPassword; + break; + case 1: + iclass = kSecClassGenericPassword; + break; + case 2: + iclass = kSecClassKey; + break; + case 3: + iclass = kSecClassCertificate; + break; + } + return CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, kSecClass, iclass, NULL); +} + +static void tests(bool isPasscodeSet) +{ + SecAccessControlRef aclRef = SecAccessControlCreate(kCFAllocatorDefault, NULL); + ok(aclRef, "Create SecAccessControlRef"); + ok(SecAccessControlSetProtection(aclRef, kSecAttrAccessibleWhenUnlocked, NULL), "Set protection"); + ok(SecAccessControlAddConstraintForOperation(aclRef, kAKSKeyOpDecrypt, kCFBooleanTrue, NULL), "Set operation decrypt to true"); + ok(SecAccessControlAddConstraintForOperation(aclRef, kAKSKeyOpDelete, kCFBooleanTrue, NULL), "Set operation delete to true"); + + SecAccessControlRef invalidAclRef = SecAccessControlCreate(kCFAllocatorDefault, NULL); + ok(invalidAclRef, "Create invalid SecAccessControlRef"); + ok(SecAccessControlSetProtection(invalidAclRef, kSecAttrAccessibleWhenUnlocked, NULL), "Set protection"); + CFTypeRef constraint = SecAccessConstraintCreatePolicy(CFSTR("invalidPolicy"), NULL); + ok(constraint, "Create invalid constraint"); + ok(SecAccessControlAddConstraintForOperation(invalidAclRef, kAKSKeyOpDecrypt, constraint, NULL), "Add invalid constraint"); + CFReleaseSafe(constraint); + + SecAccessControlRef aclWithUIRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenUnlocked, kSecAccessControlUserPresence, NULL); + ok(invalidAclRef, "Create SecAccessControlRef which require UI interaction"); + + + for (int num = 0 ; num < 8; ++num) { + CFMutableDictionaryRef item = ItemCreate(num); + ItemForEachPKAttr(item, ^(CFStringRef attr, enum ItemAttrType atype) { + CFTypeRef value = NULL; + switch (atype) { + case kBoolItemAttr: + value = (num % 2 == 0 ? kCFBooleanTrue : kCFBooleanFalse); + CFRetain(value); + break; + case kNumberItemAttr: + value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &num); + break; + case kStringItemAttr: + case kBlobItemAttr: + value = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("string-%d"), num); + break; + case kDataItemAttr: + { + char buf[10]; + int len = snprintf(buf, sizeof(buf), "data-%d", num); + value = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)buf, len); + break; + } + case kDateItemAttr: + value = NULL; // Don't mess with dates on create. + break; + case kAccessabilityItemAttr: + { + CFStringRef accessabilites[] = { + kSecAttrAccessibleWhenUnlocked, + kSecAttrAccessibleAfterFirstUnlock, + kSecAttrAccessibleAlways, + kSecAttrAccessibleWhenUnlockedThisDeviceOnly, + kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, + kSecAttrAccessibleAlwaysThisDeviceOnly, + }; + value = accessabilites[num % array_size(accessabilites)]; + break; + } + case kAccessGroupItemAttr: + { + CFStringRef accessGroups[] = { + NULL, +#if 0 +#if NO_SERVER + CFSTR("test"), + CFSTR("apple"), + CFSTR("lockdown-identities"), +#else + CFSTR("sync"), +#endif + CFSTR("com.apple.security.sos"), // Secd internally uses this + + CFSTR("com.apple.security.regressions"), // SecurityTestApp is in this group. +#endif + }; + value = accessGroups[num % array_size(accessGroups)]; + break; + } + } + if (value) + CFDictionarySetValue(item, attr, value); + CFReleaseSafe(value); + }); + + CFDictionarySetValue(item, kSecAttrSynchronizable, kCFBooleanFalse); + CFDictionarySetValue(item, kSecAttrAccessControl, invalidAclRef); + is_status(SecItemAdd(item, NULL), errSecParam, "do not add local with invalid acl"); + is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "do not find after add failed"); + + CFDictionarySetValue(item, kSecAttrAccessControl, aclRef); + 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"); + + 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(isPasscodeSet) { + CFDictionarySetValue(item, kSecAttrAccessControl, aclWithUIRef); + CFDictionarySetValue(item, kSecUseNoAuthenticationUI, kCFBooleanTrue); + ok_status(SecItemAdd(item, NULL), "add local - acl with authentication UI"); + is_status(SecItemCopyMatching(item, NULL), errSecInteractionNotAllowed, "find local - acl with authentication UI"); + ok_status(SecItemDelete(item), "delete local - acl with authentication UI"); + is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "do not find after delete local - acl with authentication UI"); + } + + CFRelease(item); + } + + CFReleaseSafe(aclRef); + CFReleaseSafe(invalidAclRef); + CFReleaseSafe(aclWithUIRef); +} + +int si_81_item_acl_stress(int argc, char *const *argv) +{ +#if USE_KEYSTORE + CFErrorRef error = NULL; + SecAccessControlRef aclRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenUnlocked, kSecAccessControlUserPresence, NULL); + CFTypeRef authRef = VRCreateNewReferenceWithACMContext(NULL, NULL); + CFDataRef aclData = SecAccessControlCopyData(aclRef); + VRValidateACL(authRef, aclData, &error); + + bool isPasscodeSet = true; + if(error && CFEqual(CFErrorGetDomain(error), CFSTR(kLAErrorDomain)) && CFErrorGetCode(error) == kLAErrorPasscodeNotSet) + isPasscodeSet = false; + + CFReleaseSafe(aclRef); + CFReleaseSafe(aclData); + CFReleaseSafe(authRef); + CFReleaseSafe(error); +#else + bool isPasscodeSet = false; +#endif + + plan_tests(isPasscodeSet?105:73); + + tests(isPasscodeSet); + + return 0; +} diff --git a/Security/sec/Security/Regressions/secitem/si-81-sectrust-server-auth.c b/Security/sec/Security/Regressions/secitem/si-81-sectrust-server-auth.c new file mode 100644 index 00000000..beb47510 --- /dev/null +++ b/Security/sec/Security/Regressions/secitem/si-81-sectrust-server-auth.c @@ -0,0 +1,557 @@ +/* + * si-81-sectrust-server-auth.c + * Security + * + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Security_regressions.h" + + +static const UInt8 kTestAppleVPNLeafCert[] = { + 0x30,0x82,0x04,0x55,0x30,0x82,0x03,0x3D,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x1F, + 0xF4,0x7D,0xBF,0x19,0x70,0x2F,0xE4,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x6E,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04, + 0x03,0x0C,0x1F,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x6F,0x72,0x70,0x6F,0x72,0x61, + 0x74,0x65,0x20,0x56,0x50,0x4E,0x20,0x43,0x6C,0x69,0x65,0x6E,0x74,0x20,0x43,0x41, + 0x20,0x31,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,0x34,0x30,0x37,0x30,0x37, + 0x32,0x30,0x33,0x38,0x35,0x33,0x5A,0x17,0x0D,0x31,0x34,0x31,0x30,0x30,0x35,0x32, + 0x30,0x33,0x38,0x35,0x33,0x5A,0x30,0x61,0x31,0x5F,0x30,0x5D,0x06,0x03,0x55,0x04, + 0x03,0x0C,0x56,0x63,0x6F,0x6D,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x69,0x73,0x74, + 0x2E,0x64,0x73,0x2E,0x61,0x70,0x70,0x6C,0x65,0x63,0x6F,0x6E,0x6E,0x65,0x63,0x74, + 0x32,0x2E,0x70,0x72,0x6F,0x64,0x75,0x63,0x74,0x69,0x6F,0x6E,0x2E,0x76,0x70,0x6E, + 0x2E,0x38,0x46,0x32,0x42,0x33,0x41,0x44,0x43,0x44,0x37,0x32,0x45,0x44,0x32,0x45, + 0x41,0x30,0x38,0x44,0x44,0x43,0x32,0x36,0x41,0x44,0x30,0x32,0x35,0x35,0x41,0x39, + 0x38,0x33,0x42,0x31,0x44,0x45,0x42,0x45,0x42,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,0xE1,0xA1,0xCB,0x69,0x00,0x88, + 0x06,0x3A,0x7C,0xE3,0x29,0x1F,0x1C,0x32,0x22,0xD2,0x71,0xFA,0x06,0xED,0xC0,0x16, + 0x41,0x80,0x4C,0x82,0xA5,0x98,0x98,0x02,0xCE,0xB3,0x7D,0xC9,0x89,0x8D,0x91,0xDE, + 0x61,0x34,0xCB,0xB9,0x24,0xA8,0xA4,0x4F,0x7F,0x07,0x09,0x80,0x6A,0xAB,0x0C,0x3C, + 0xBC,0xD5,0xDA,0xAB,0xD1,0x69,0x47,0x7C,0x1F,0x93,0x4E,0xF0,0x44,0x50,0x54,0x91, + 0x85,0xB6,0x67,0x53,0x35,0x45,0x60,0x92,0xD8,0xDA,0x20,0xBC,0x7E,0x3E,0xA5,0xA0, + 0xD7,0x2B,0x62,0x78,0x94,0xA4,0x97,0x74,0x07,0xAA,0x7A,0x91,0xFC,0xF4,0xFA,0x50, + 0x8E,0x24,0x6D,0x2E,0x64,0x01,0x23,0x6D,0x16,0xA2,0x5A,0x18,0xFB,0x82,0xAB,0x7E, + 0x19,0xE9,0x7F,0x1E,0xEE,0x4C,0x0A,0xEA,0xD5,0xE4,0xE7,0x29,0xE5,0xA1,0x52,0xAD, + 0xED,0xD9,0xE9,0x56,0xA1,0xFC,0xD8,0x9D,0x89,0xC9,0x31,0x3F,0x98,0xE6,0xBD,0xAF, + 0x5B,0x6E,0xCC,0x43,0x0B,0xD9,0x55,0xC7,0x8A,0x1A,0x36,0x1A,0xE7,0x1B,0x46,0xD5, + 0xF8,0x90,0xD9,0x68,0x2E,0x29,0xBE,0xED,0xE0,0x15,0x2A,0x5F,0x8F,0xBA,0x4C,0x32, + 0x99,0xF5,0x83,0x85,0x74,0x8E,0x4A,0x69,0xC6,0x0E,0x3F,0x35,0x1C,0xD8,0x8F,0xB6, + 0x28,0x94,0x68,0xF5,0x65,0x33,0x12,0xE6,0x8D,0x9D,0x8F,0x99,0x71,0xFC,0xAA,0x2B, + 0xF8,0x79,0xFD,0x89,0x66,0x0E,0xDC,0x17,0xF4,0x73,0xFD,0x11,0x2A,0x8A,0xC5,0x90, + 0x8C,0xC3,0x33,0x48,0x02,0x19,0x2D,0x86,0xD7,0xED,0xD8,0x4D,0xF4,0x21,0xB0,0x1D, + 0xB8,0x3B,0xCC,0x7A,0xBA,0x10,0x9C,0x32,0x95,0x7D,0x02,0x03,0x01,0x00,0x01,0xA3, + 0x82,0x01,0x02,0x30,0x81,0xFF,0x30,0x4B,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x01,0x01,0x04,0x3F,0x30,0x3D,0x30,0x3B,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x30,0x01,0x86,0x2F,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F,0x63,0x73,0x70,0x2E, + 0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x6F,0x63,0x73,0x70,0x30,0x31, + 0x2D,0x63,0x6F,0x72,0x70,0x76,0x70,0x6E,0x63,0x6C,0x69,0x65,0x6E,0x74,0x63,0x61, + 0x31,0x30,0x31,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x9D,0x04, + 0x52,0xAB,0xBA,0x68,0x49,0x05,0x7E,0x09,0xE8,0x74,0x00,0x30,0x87,0xAF,0x16,0xF0, + 0xD5,0x9D,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,0xA9,0x85,0xE3, + 0x5B,0xDB,0xFF,0xFC,0x2D,0x7F,0x80,0x04,0xAA,0xF0,0xDA,0xAD,0x37,0x78,0x82,0xA3, + 0xE0,0x30,0x3A,0x06,0x03,0x55,0x1D,0x1F,0x04,0x33,0x30,0x31,0x30,0x2F,0xA0,0x2D, + 0xA0,0x2B,0x86,0x29,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x61, + 0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x63,0x6F,0x72,0x70,0x76,0x70,0x6E, + 0x63,0x6C,0x69,0x65,0x6E,0x74,0x63,0x61,0x31,0x2E,0x63,0x72,0x6C,0x30,0x0E,0x06, + 0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x16,0x06, + 0x03,0x55,0x1D,0x25,0x01,0x01,0xFF,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01, + 0x05,0x05,0x07,0x03,0x02,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, + 0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x11,0x76,0x58,0xDA,0x13,0xD2,0x3F, + 0x8E,0x4F,0xA0,0xAE,0x38,0xE5,0x74,0x85,0x94,0x60,0x3F,0xD7,0x30,0xBD,0x56,0x65, + 0xCB,0x28,0xD9,0x5B,0xCF,0x7E,0xEB,0x49,0x03,0x6A,0x6E,0xFB,0x17,0xC7,0xEA,0x3F, + 0x04,0xCF,0xC1,0xA2,0xFC,0x7C,0x8F,0xC0,0x19,0x79,0xF1,0xD5,0x07,0xF5,0x83,0xA4, + 0x33,0x6A,0xBC,0x0F,0x24,0x8E,0xA0,0x63,0xD3,0x00,0xA0,0xD8,0x08,0x92,0x21,0xB6, + 0x5B,0x56,0xE2,0x79,0x58,0xF2,0x3F,0x0F,0x98,0xC1,0x69,0xB6,0x10,0xA3,0x8C,0xA4, + 0xE4,0xEE,0x50,0xF6,0x52,0x5D,0x84,0x48,0x69,0x59,0x6D,0x21,0x7F,0xFB,0x1B,0xA3, + 0x21,0xBA,0xAE,0xCC,0x0A,0xD2,0xB4,0xBF,0xAA,0x7D,0x63,0xEE,0x74,0x9C,0x62,0x21, + 0xCB,0x93,0x14,0x7F,0x8E,0x38,0xD9,0x1D,0xF0,0x77,0xB1,0x77,0x92,0xE8,0xFE,0xFE, + 0xAE,0x6D,0xAF,0x5A,0x6F,0xE8,0xBC,0x4E,0xAC,0xAF,0xDF,0xF1,0xE1,0x4C,0x2A,0x26, + 0x9A,0xA1,0xD7,0x35,0xFD,0xE7,0x2B,0xBD,0x40,0xBB,0xE1,0x2A,0xEA,0xB0,0xEF,0xEF, + 0xE8,0x40,0x29,0xB7,0xDC,0xA2,0xC5,0x68,0x01,0xEB,0xBE,0x19,0x3F,0x22,0xFF,0x2D, + 0x43,0x2D,0xBA,0xB3,0x33,0xCF,0xDD,0xD7,0xBC,0x4B,0xEC,0x44,0x47,0x74,0x78,0x39, + 0x59,0xE3,0xC7,0x5A,0x9A,0x65,0xCD,0xFF,0xE5,0x80,0x63,0xEF,0xCB,0x8A,0xA4,0xF6, + 0x69,0xFF,0x65,0x26,0xA5,0xDA,0x53,0xBE,0x03,0xF6,0x81,0x52,0x2A,0x2C,0x71,0x59, + 0x7B,0x2A,0x4A,0xE1,0x9A,0x2A,0x52,0xEE,0x7A,0x48,0x80,0x86,0xD0,0x9D,0x66,0xB5, + 0xD3,0xE7,0xAC,0x03,0x14,0x04,0x4F,0xC6,0x65, +}; + +static const UInt8 kTestAppleVPNCACert[] = { + 0x30,0x82,0x04,0x44,0x30,0x82,0x03,0x2C,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x0E, + 0x74,0x07,0xCA,0x6E,0x0B,0xA3,0x20,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x66,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04, + 0x03,0x0C,0x17,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x6F,0x72,0x70,0x6F,0x72,0x61, + 0x74,0x65,0x20,0x52,0x6F,0x6F,0x74,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,0x34,0x30,0x33,0x31,0x39,0x30,0x30,0x30,0x30,0x35,0x30,0x5A,0x17, + 0x0D,0x32,0x39,0x30,0x33,0x31,0x39,0x30,0x30,0x30,0x30,0x35,0x30,0x5A,0x30,0x6E, + 0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x03,0x0C,0x1F,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x43,0x6F,0x72,0x70,0x6F,0x72,0x61,0x74,0x65,0x20,0x56,0x50,0x4E,0x20,0x43, + 0x6C,0x69,0x65,0x6E,0x74,0x20,0x43,0x41,0x20,0x31,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,0xA4, + 0xBF,0xFE,0x2F,0x4D,0x46,0x90,0x89,0x1C,0x89,0xDF,0x4E,0x70,0x02,0x73,0x9F,0x2A, + 0x10,0xFA,0x72,0x60,0xEE,0x99,0x16,0xE8,0x05,0xB7,0x7D,0x73,0x96,0x03,0x6A,0x46, + 0x7F,0x2E,0xAE,0xC9,0x42,0xF1,0x05,0xAA,0x64,0xED,0x4B,0xF8,0xE7,0xAF,0x2D,0x16, + 0xB2,0xC2,0x4F,0x52,0x31,0xEE,0x9E,0xCC,0x23,0x7E,0x40,0xA2,0x7B,0xCE,0x89,0xD8, + 0x0F,0xE4,0xB8,0x27,0x50,0x33,0xB3,0x24,0x01,0x61,0xB1,0xD5,0x81,0x7A,0x75,0x1F, + 0xFF,0x3C,0x99,0x79,0x9D,0x7A,0x17,0x44,0x1A,0xC0,0xD2,0xF4,0x64,0x69,0x2C,0x9C, + 0x75,0x22,0xC8,0x51,0x0D,0xD7,0xB6,0x8D,0x9B,0xF6,0x13,0x9F,0xA8,0xC1,0x0F,0xC0, + 0x4A,0x5A,0x83,0x98,0x01,0x4C,0x04,0xDF,0xCD,0x74,0xC5,0x4C,0x3D,0x72,0x05,0x41, + 0xCA,0x64,0x17,0xED,0x63,0x1C,0x8A,0xCE,0x93,0x05,0x18,0xF7,0xD8,0x35,0x75,0xD0, + 0x7D,0x03,0x57,0xE7,0x15,0x20,0xC1,0x1A,0x02,0xAD,0x94,0x91,0x06,0x88,0xAF,0xCB, + 0x41,0x24,0xF1,0xBB,0x17,0xC3,0x73,0x4A,0x63,0x08,0xE0,0xAF,0x14,0xCA,0x03,0x8C, + 0xC9,0xA5,0xDC,0x5C,0xE3,0x7F,0xF6,0x33,0x99,0x07,0xD2,0xA5,0x15,0xEB,0x70,0xB7, + 0x3E,0x5D,0xD5,0x50,0x81,0x9C,0xE3,0x7C,0x3B,0x21,0x98,0xB3,0xE2,0xF3,0x00,0x8D, + 0xBE,0x68,0xDD,0x9B,0xFC,0x87,0xBF,0xF0,0x01,0x58,0x53,0xAC,0x2B,0x01,0xE9,0x81, + 0xB4,0x49,0x4A,0x02,0x98,0xC3,0x5B,0x92,0xFD,0x0B,0x9C,0xDC,0x56,0x96,0x5B,0x3B, + 0x02,0x81,0x1F,0x00,0xC2,0x2C,0xF0,0x1C,0xB9,0x38,0x20,0xE7,0x51,0x90,0x91,0x02, + 0x03,0x01,0x00,0x01,0xA3,0x81,0xED,0x30,0x81,0xEA,0x30,0x41,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x35,0x30,0x33,0x30,0x31,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x25,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x6F, + 0x63,0x73,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x6F,0x63, + 0x73,0x70,0x30,0x34,0x2D,0x63,0x6F,0x72,0x70,0x72,0x6F,0x6F,0x74,0x30,0x1D,0x06, + 0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xA9,0x85,0xE3,0x5B,0xDB,0xFF,0xFC,0x2D, + 0x7F,0x80,0x04,0xAA,0xF0,0xDA,0xAD,0x37,0x78,0x82,0xA3,0xE0,0x30,0x0F,0x06,0x03, + 0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x1F,0x06, + 0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x35,0x20,0x26,0xCE,0x85,0xBE, + 0x49,0x26,0x20,0x01,0xDD,0xC8,0xEE,0xFF,0x3D,0x68,0xC8,0xD0,0xDF,0xF5,0x30,0x32, + 0x06,0x03,0x55,0x1D,0x1F,0x04,0x2B,0x30,0x29,0x30,0x27,0xA0,0x25,0xA0,0x23,0x86, + 0x21,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x61,0x70,0x70,0x6C, + 0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x63,0x6F,0x72,0x70,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,0x18,0x05, + 0x04,0x02,0x05,0x00,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, + 0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x38,0x50,0xD1,0x41,0x40,0xAD,0x98,0x12, + 0xB6,0xB5,0x7A,0xC6,0x42,0xD7,0x40,0x25,0x2A,0xDB,0x7C,0xEA,0x84,0xA8,0x21,0xCE, + 0xA9,0xBE,0x26,0x0D,0x10,0xFD,0xFE,0x9C,0x8D,0x8A,0xA5,0xA6,0x3C,0x44,0xDA,0xF1, + 0xD1,0x05,0xEF,0xB3,0x17,0x8F,0x21,0x88,0x3B,0xF8,0x48,0x5B,0xE3,0xF6,0xC1,0x1B, + 0x6C,0xE4,0xD0,0xF7,0xD2,0xA1,0xF9,0x89,0xFA,0x71,0x12,0x4F,0x90,0x95,0x73,0x89, + 0xE9,0xD8,0xB5,0xBD,0x4B,0xF6,0x39,0x9D,0x97,0xFB,0x1C,0x5C,0x46,0x48,0x83,0x13, + 0x02,0xBF,0xA5,0xB1,0x74,0xD9,0x8A,0x41,0xA4,0x80,0x1E,0xD4,0xA6,0xC5,0x2C,0xD3, + 0x42,0xEF,0x17,0x8B,0xB0,0xFB,0x49,0x12,0x60,0x29,0x35,0xA6,0xAF,0x23,0x04,0xF1, + 0x26,0x8A,0x84,0x81,0x54,0x16,0x62,0x7B,0xBD,0xCE,0x09,0x39,0x3C,0x74,0x05,0xF4, + 0x75,0xE8,0x8A,0x77,0x13,0x07,0x93,0xB8,0x95,0x8E,0xD5,0x29,0x3E,0x17,0x6D,0x1B, + 0xA0,0xCB,0x4A,0xBB,0x33,0x28,0x06,0xCA,0x76,0x20,0x6F,0x07,0x32,0x04,0xE3,0xD9, + 0xD2,0x89,0xAE,0xD7,0x17,0x16,0x4A,0x4E,0x80,0xD6,0x9F,0x1F,0x75,0x6E,0x7C,0xCF, + 0x17,0xCE,0xD7,0x5E,0x5E,0x7B,0x55,0xC2,0x0D,0xCA,0xE2,0xEB,0x87,0x60,0xAC,0x32, + 0x31,0x1E,0x9F,0xF0,0x77,0xA3,0x28,0x6A,0x34,0xD0,0xF9,0xEE,0x47,0x6D,0xE6,0x1E, + 0x8A,0x87,0x82,0x49,0x72,0xBA,0x09,0x3B,0xB9,0x3B,0xF9,0xA4,0xEC,0x9B,0x5F,0x6B, + 0xEE,0xC1,0x6E,0xAC,0xC5,0x45,0xF4,0x44,0x8B,0x9B,0x27,0xBB,0xA4,0xBE,0x8D,0x74, + 0xE1,0x5D,0x4A,0xA2,0x35,0x4D,0xC8,0x42, +}; + +static const UInt8 kTestAppleCorpCACert[] = { + 0x30,0x82,0x03,0xB1,0x30,0x82,0x02,0x99,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x14, + 0x99,0x6B,0x4A,0x6A,0xE4,0x40,0xA0,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x66,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04, + 0x03,0x0C,0x17,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x6F,0x72,0x70,0x6F,0x72,0x61, + 0x74,0x65,0x20,0x52,0x6F,0x6F,0x74,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,0x33,0x30,0x37,0x31,0x36,0x31,0x39,0x32,0x30,0x34,0x35,0x5A,0x17, + 0x0D,0x32,0x39,0x30,0x37,0x31,0x37,0x31,0x39,0x32,0x30,0x34,0x35,0x5A,0x30,0x66, + 0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x03,0x0C,0x17,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x43,0x6F,0x72,0x70,0x6F,0x72,0x61,0x74,0x65,0x20,0x52,0x6F,0x6F,0x74,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,0xB5,0x3B,0xE3,0x9F,0x6A,0x1D,0x0E,0x46,0x51, + 0x1E,0xD0,0xB5,0x17,0x6B,0x06,0x4B,0x92,0xAF,0x38,0x10,0x25,0xA1,0xEE,0x1E,0x4E, + 0xEF,0x19,0xE0,0x73,0xB5,0x37,0x33,0x72,0x21,0x21,0xCB,0x62,0x4A,0x3D,0xA9,0x68, + 0xD8,0x07,0xB4,0xEB,0x8D,0x0A,0xDB,0x30,0x33,0x21,0x2F,0x6F,0xD3,0xF7,0x5D,0xCE, + 0x20,0x0A,0x04,0xDB,0xFF,0xBF,0x75,0x08,0x42,0x3F,0x3E,0xD8,0xC8,0xEF,0xA4,0xF8, + 0x56,0x7B,0x13,0x64,0x6B,0xF3,0xA2,0x38,0x10,0xFA,0xEE,0x9D,0x83,0x93,0x1D,0xFB, + 0xEF,0x13,0x6C,0x38,0x49,0xDD,0xEB,0x71,0xA6,0x92,0x58,0x04,0xDE,0x01,0x41,0x2B, + 0x99,0x5E,0xBD,0x24,0x3F,0x69,0xA8,0x44,0xF2,0xAA,0x01,0x78,0xB9,0x38,0x06,0x10, + 0x77,0x36,0xF8,0xF2,0xA3,0x3E,0xD9,0x5F,0xEA,0xF5,0x8B,0x6A,0xA6,0x5F,0xE6,0x51, + 0xD0,0x9B,0x50,0xA0,0x1E,0xF5,0x85,0x9E,0x49,0x50,0x4A,0x61,0x78,0xDA,0x29,0xA7, + 0x33,0x72,0x8B,0x83,0xEE,0x7B,0xA7,0x79,0x4E,0x8E,0x02,0x6F,0x9D,0x25,0x97,0x26, + 0x86,0x0C,0x82,0xC5,0x8C,0x16,0x7E,0x49,0x61,0xFD,0xFF,0x1A,0xA0,0x0D,0x28,0xE1, + 0x68,0xF5,0xAE,0x85,0x72,0xF3,0xAB,0xE0,0x74,0x75,0xCC,0x57,0x64,0x3C,0x2C,0x55, + 0x05,0xC9,0x8D,0xAA,0xB3,0xEC,0xC8,0x62,0x88,0x15,0x2A,0xC4,0x59,0x60,0x37,0xC1, + 0xED,0x6B,0xCE,0xE9,0xCA,0xAF,0xB0,0xA5,0x45,0xBA,0xFF,0x16,0x32,0xAA,0x92,0x86, + 0xD9,0xB9,0xA1,0x13,0x75,0x95,0x9B,0x97,0x5C,0x2D,0xB5,0x12,0xCA,0x6B,0x6B,0x39, + 0xD6,0x9B,0x4B,0x34,0x47,0xAB,0x35,0x02,0x03,0x01,0x00,0x01,0xA3,0x63,0x30,0x61, + 0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x35,0x20,0x26,0xCE,0x85, + 0xBE,0x49,0x26,0x20,0x01,0xDD,0xC8,0xEE,0xFF,0x3D,0x68,0xC8,0xD0,0xDF,0xF5,0x30, + 0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF, + 0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x35,0x20,0x26, + 0xCE,0x85,0xBE,0x49,0x26,0x20,0x01,0xDD,0xC8,0xEE,0xFF,0x3D,0x68,0xC8,0xD0,0xDF, + 0xF5,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,0x0B,0x05,0x00, + 0x03,0x82,0x01,0x01,0x00,0x73,0x02,0x4A,0xA6,0x77,0x02,0xA7,0xE1,0xCB,0x52,0x97, + 0x9D,0x89,0x11,0xA0,0x8F,0xBC,0xF3,0x8F,0x14,0x01,0x29,0xF3,0xA5,0x45,0x17,0x06, + 0xF8,0x04,0xF2,0x6D,0xD5,0xC3,0x77,0xB8,0x00,0xC2,0x0A,0x1A,0x09,0x32,0x36,0x36, + 0x69,0xC1,0x2A,0xF0,0x44,0x37,0xBC,0x7E,0x5F,0x15,0xF7,0x08,0x9C,0x19,0x27,0x1D, + 0x70,0x4F,0xDC,0x17,0x94,0x3C,0xBB,0x24,0xB4,0xE6,0xFC,0x71,0x9A,0xD4,0xCF,0x2C, + 0x12,0xBA,0xF0,0xB6,0x8F,0x78,0x99,0xAA,0x8C,0x17,0x7E,0x94,0x0C,0x6A,0x37,0x5B, + 0x35,0x91,0x52,0xFA,0x64,0xA3,0x33,0x34,0x99,0x37,0x00,0x3C,0xB4,0x4E,0x6E,0x63, + 0xED,0xC3,0x1D,0x37,0x5B,0x45,0xB4,0xDF,0x82,0xCD,0xFE,0xAA,0x92,0x64,0xC8,0x2F, + 0xD6,0x2D,0x2E,0xB1,0xED,0x6A,0x04,0xF1,0xC2,0x48,0x8D,0x4B,0xB4,0x84,0x39,0xA3, + 0x31,0x4D,0xF6,0x63,0xB4,0xC3,0x6E,0xA1,0xA5,0x2F,0xD2,0x1E,0xB0,0xC6,0x0C,0xD1, + 0x04,0x3A,0x31,0xBC,0x87,0x49,0xF8,0x26,0x0B,0xD3,0x0C,0x08,0x29,0xBB,0x9F,0x4D, + 0x08,0xF0,0x9C,0x11,0xD3,0xA5,0x2C,0x8D,0x98,0xB1,0x1B,0xB1,0x57,0xD3,0x69,0xAE, + 0x9E,0x2D,0xD5,0x64,0x38,0x58,0xC9,0xB2,0x84,0x04,0xAB,0x10,0x1D,0xCA,0x6B,0x29, + 0xA5,0xAB,0xCC,0xFE,0xBB,0x74,0xF4,0x35,0x03,0x8F,0x65,0x2A,0x0B,0xBB,0xC7,0x17, + 0x6A,0x49,0x34,0x83,0x30,0x92,0x8D,0xD7,0xAE,0x95,0xD0,0xD7,0x23,0xA7,0xE3,0x29, + 0x09,0xA1,0xB1,0x34,0xC3,0x95,0x49,0xC3,0xA4,0xF1,0x36,0x00,0x09,0xD3,0xA4,0x09, + 0xAD,0xF2,0x5C,0x97,0xB2, +}; + + +static const UInt8 kTestAppleServerAuthCACert[] = { + 0x30,0x82,0x03,0xF8,0x30,0x82,0x02,0xE0,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x23, + 0x69,0x74,0x04,0xAD,0xCB,0x83,0x14,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x62,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03, + 0x55,0x04,0x0B,0x13,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,0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x03,0x13,0x0D,0x41,0x70,0x70, + 0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x34, + 0x30,0x33,0x30,0x38,0x30,0x31,0x35,0x33,0x30,0x34,0x5A,0x17,0x0D,0x32,0x39,0x30, + 0x33,0x30,0x38,0x30,0x31,0x35,0x33,0x30,0x34,0x5A,0x30,0x6D,0x31,0x27,0x30,0x25, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x1E,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,0xB9,0x26,0x16,0xB0,0xCB,0x87, + 0xAB,0x71,0x15,0x92,0x8E,0xDF,0xAA,0x3E,0xE1,0x80,0xD7,0x53,0xBA,0xA4,0x60,0xCC, + 0x7C,0x85,0x72,0xF7,0x30,0x7C,0x09,0x4F,0x57,0x0D,0x4A,0xFF,0xE1,0x5E,0xC9,0x4B, + 0x50,0x13,0x02,0x64,0xB1,0xBD,0x39,0x35,0xD1,0xD7,0x04,0x51,0xC1,0x18,0xFA,0x22, + 0xFA,0xAE,0xDF,0x98,0x18,0xD6,0xBF,0x4E,0x4D,0x43,0x10,0xFA,0x25,0x88,0x9F,0xD3, + 0x40,0x85,0x76,0xE5,0x22,0x81,0xB6,0x54,0x45,0x73,0x9A,0x8B,0xE3,0x9C,0x48,0x1A, + 0x86,0x7A,0xC3,0x51,0xE2,0xDA,0x95,0xF8,0xA4,0x7D,0xDB,0x30,0xDE,0x6C,0x0E,0xC4, + 0xC5,0xF5,0x6C,0x98,0xE7,0xA6,0xFA,0x57,0x20,0x1D,0x19,0x73,0x7A,0x0E,0xCD,0x63, + 0x0F,0xB7,0x27,0x88,0x2E,0xE1,0x9A,0x68,0x82,0xB8,0x40,0x6C,0x63,0x16,0x24,0x66, + 0x2B,0xE7,0xB2,0xE2,0x54,0x7D,0xE7,0x88,0x39,0xA2,0x1B,0x81,0x3E,0x02,0xD3,0x39, + 0xD8,0x97,0x77,0x4A,0x32,0x0C,0xD6,0x0A,0x0A,0xB3,0x04,0x9B,0xF1,0x72,0x6F,0x63, + 0xA8,0x15,0x1E,0x6C,0x37,0xE8,0x0F,0xDB,0x53,0x90,0xD6,0x29,0x5C,0xBC,0x6A,0x57, + 0x9B,0x46,0x78,0x0A,0x3E,0x24,0xEA,0x9A,0x3F,0xA1,0xD8,0x3F,0xF5,0xDB,0x6E,0xA8, + 0x6C,0x82,0xB5,0xDD,0x99,0x38,0xEC,0x92,0x56,0x94,0xA6,0xC5,0x73,0x26,0xD1,0xAE, + 0x08,0xB2,0xC6,0x52,0xE7,0x8E,0x76,0x4B,0x89,0xB8,0x54,0x0F,0x6E,0xE0,0xD9,0x42, + 0xDB,0x2A,0x65,0x87,0x46,0x14,0xBB,0x96,0xB8,0x57,0xBB,0x51,0xE6,0x84,0x13,0xF7, + 0x0D,0xA1,0xB6,0x89,0xAC,0x7C,0xD1,0x21,0x74,0xAB,0x02,0x03,0x01,0x00,0x01,0xA3, + 0x81,0xA6,0x30,0x81,0xA3,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14, + 0x2C,0xC5,0x6D,0x52,0xDD,0x31,0xEF,0x8C,0xEC,0x08,0x81,0xED,0xDF,0xDC,0xCA,0x43, + 0x00,0x45,0x01,0xD0,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,0x2B,0xD0,0x69,0x47,0x94,0x76,0x09,0xFE,0xF4,0x6B,0x8D,0x2E,0x40,0xA6, + 0xF7,0x47,0x4D,0x7F,0x08,0x5E,0x30,0x2E,0x06,0x03,0x55,0x1D,0x1F,0x04,0x27,0x30, + 0x25,0x30,0x23,0xA0,0x21,0xA0,0x1F,0x86,0x1D,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, + 0x63,0x72,0x6C,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,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,0x23,0xF1,0x06,0x7E, + 0x50,0x41,0x81,0xA2,0x5E,0xD3,0x70,0xA4,0x49,0x91,0xAF,0xD8,0xCC,0x67,0x8C,0xA1, + 0x25,0x7D,0xC4,0x9A,0x93,0x39,0x2F,0xD8,0x69,0xFB,0x1B,0x41,0x5B,0x44,0xD7,0xD9, + 0x6B,0xCB,0x3B,0x25,0x09,0x1A,0xF2,0xF4,0xE3,0xC7,0x9C,0xE8,0xB0,0x5B,0xF0,0xDF, + 0xDD,0x22,0x25,0x11,0x15,0x93,0xB9,0x49,0x5E,0xDA,0x0C,0x66,0x7A,0x5E,0xD7,0x6F, + 0xF0,0x63,0xD4,0x65,0x8C,0xC4,0x7A,0x54,0x7D,0x56,0x4F,0x65,0x9A,0xFD,0xDA,0xC4, + 0xB2,0xC8,0xB0,0xB8,0xA1,0xCB,0x7D,0xE0,0x47,0xA8,0x40,0x15,0xB8,0x16,0x19,0xED, + 0x5B,0x61,0x8E,0xDF,0xAA,0xD0,0xCD,0xD2,0x3A,0xC0,0x7E,0x3A,0x9F,0x22,0x4E,0xDF, + 0xDF,0xF4,0x4E,0x1A,0xCD,0x93,0xFF,0xD0,0xF0,0x45,0x55,0x64,0x33,0x3E,0xD4,0xE5, + 0xDA,0x68,0xA0,0x13,0x8A,0x76,0x30,0x27,0xD4,0xBF,0xF8,0x1E,0x76,0xF6,0xF9,0xC3, + 0x00,0xEF,0xB1,0x83,0xEA,0x53,0x6D,0x5C,0x35,0xC7,0x0D,0x07,0x01,0xBA,0xF8,0x61, + 0xB9,0xFE,0xC5,0x9A,0x6B,0x43,0x61,0x81,0x03,0xEB,0xBA,0x5F,0x70,0x9D,0xE8,0x6F, + 0x94,0x24,0x4B,0xDC,0xCE,0x92,0xA8,0x2E,0xA2,0x35,0x3C,0xE3,0x49,0xE0,0x16,0x77, + 0xA2,0xDC,0x6B,0xB9,0x8D,0x18,0x42,0xB9,0x36,0x96,0x43,0x32,0xC6,0xCB,0x76,0x99, + 0x35,0x36,0xD8,0x56,0xC6,0x98,0x5D,0xC3,0x6F,0xA5,0x7E,0x95,0xC2,0xD5,0x7A,0x0A, + 0x02,0x20,0x66,0x78,0x92,0xF2,0x67,0xA4,0x23,0x0D,0xE8,0x09,0xBD,0xCC,0x21,0x31, + 0x10,0xA0,0xBD,0xBE,0xB5,0xDD,0x4C,0xDD,0x46,0x03,0x99,0x99, +}; + +static const UInt8 kTestAppleServerAuthLeafCert[] = { + 0x30,0x82,0x04,0x09,0x30,0x82,0x02,0xF1,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x16, + 0x18,0xA0,0xD4,0x51,0xA2,0x9E,0x3B,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x6D,0x31,0x27,0x30,0x25,0x06,0x03,0x55,0x04, + 0x03,0x0C,0x1E,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,0x34,0x30,0x33,0x31,0x39,0x32, + 0x33,0x34,0x36,0x32,0x38,0x5A,0x17,0x0D,0x31,0x35,0x30,0x34,0x31,0x38,0x32,0x33, + 0x34,0x36,0x32,0x38,0x5A,0x30,0x50,0x31,0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x03, + 0x0C,0x11,0x74,0x65,0x73,0x74,0x2E,0x6E,0x6F,0x73,0x75,0x63,0x68,0x64,0x6F,0x6D, + 0x61,0x69,0x6E,0x31,0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x0B,0x0C,0x07,0x43,0x6F, + 0x72,0x65,0x20,0x4F,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,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,0x1C,0xEF,0xB4,0x53,0x87,0x41,0x75, + 0x73,0x4E,0xDA,0xB3,0xAB,0x82,0x30,0x19,0x37,0x9D,0x29,0x2E,0x95,0xD2,0x2A,0x43, + 0x9C,0x1B,0x39,0xD4,0xBA,0xCD,0xAD,0x82,0xE4,0xBC,0x6F,0xA1,0x94,0x1C,0x75,0xBB, + 0xCD,0x21,0x95,0x1C,0x7B,0x13,0x92,0x13,0x4F,0x19,0xDE,0x1A,0x98,0x6D,0xA3,0xD4, + 0xC2,0x6F,0xCC,0xB6,0x4F,0xF1,0x3E,0xCA,0x09,0xC3,0x76,0xA4,0xB9,0x34,0xF5,0x41, + 0x67,0x78,0x3E,0xC5,0x9B,0x22,0xE1,0xC9,0x9B,0x2D,0x93,0x27,0x21,0x3A,0x55,0x0E, + 0xDF,0x3A,0x07,0xB4,0x52,0xC8,0x34,0x94,0x13,0x0F,0x8B,0x2E,0xAE,0x62,0x4B,0xA5, + 0xFC,0xD2,0x3C,0x41,0x53,0x62,0x8A,0xF7,0x26,0xD7,0xE4,0x23,0xF0,0x85,0xEA,0xBA, + 0x01,0x1E,0x88,0x18,0xEC,0xC9,0x45,0xC9,0xA1,0x03,0xCF,0x3A,0x1E,0xDC,0x82,0x1A, + 0xC5,0x99,0x93,0xC6,0x55,0xA8,0x06,0xDA,0xBB,0x29,0xDC,0x23,0x82,0xA6,0x5D,0x03, + 0x44,0xA6,0xF2,0xD9,0x4C,0xC0,0x32,0x82,0x41,0x9C,0xC8,0x86,0x58,0xDE,0xF3,0x53, + 0x6B,0xF7,0x5E,0x4B,0xFB,0x2F,0x81,0x3D,0x18,0xA0,0xBC,0xA3,0x6A,0x18,0x21,0xD3, + 0xC5,0xFA,0x93,0xCA,0xE6,0x02,0x8C,0x1D,0xE2,0xDC,0x8F,0x19,0xC6,0xB4,0xF9,0x91, + 0xF0,0x0E,0xEB,0x55,0xF1,0x8F,0x73,0x78,0x9D,0xFA,0x30,0x84,0x4D,0xAD,0x56,0x1C, + 0x39,0xA0,0x47,0x83,0x5F,0x7F,0x6B,0x67,0x5E,0xA3,0xCC,0xE8,0xA5,0xE9,0x8F,0x47, + 0x56,0x7A,0xA2,0x32,0x47,0xBB,0x94,0x47,0xD7,0x95,0xCD,0x20,0x2D,0x2F,0x07,0xF0, + 0xCA,0x14,0x87,0xE7,0xA9,0xE0,0x3D,0xED,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xC9, + 0x30,0x81,0xC6,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x1D,0x04, + 0xFD,0x64,0x9B,0x64,0x95,0x70,0x6F,0x4C,0x0E,0x47,0x51,0xE7,0xBC,0xE2,0x28,0xC4, + 0xE9,0x43,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,0x2C,0xC5,0x6D, + 0x52,0xDD,0x31,0xEF,0x8C,0xEC,0x08,0x81,0xED,0xDF,0xDC,0xCA,0x43,0x00,0x45,0x01, + 0xD0,0x30,0x3C,0x06,0x03,0x55,0x1D,0x1F,0x04,0x35,0x30,0x33,0x30,0x31,0xA0,0x2F, + 0xA0,0x2D,0x86,0x2B,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2E,0x61, + 0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,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,0x07,0x80,0x30, + 0x16,0x06,0x03,0x55,0x1D,0x25,0x01,0x01,0xFF,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B, + 0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x10,0x06,0x0A,0x2A,0x86,0x48,0x86,0xF7, + 0x63,0x64,0x06,0x1B,0x01,0x04,0x02,0x05,0x00,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x0E,0x66,0xD7, + 0x3C,0x7B,0xB1,0x93,0xAB,0x83,0x2D,0x9F,0xC1,0x10,0x3E,0x78,0x1D,0x24,0x81,0x17, + 0x7E,0x94,0x83,0xA3,0x46,0x73,0xF4,0xD0,0xAA,0xA7,0x9F,0x3C,0xF8,0x18,0xCF,0x8C, + 0x50,0x11,0x67,0x94,0x55,0xD9,0x35,0x1A,0x35,0xA6,0x31,0xDD,0x51,0x18,0xD4,0x65, + 0xB7,0x7A,0x47,0xBB,0xC5,0xA5,0xC4,0xA5,0x5A,0x0D,0x20,0x76,0xF6,0xAB,0x2D,0x36, + 0x81,0xDA,0x43,0xE4,0xAC,0x5F,0xC5,0xA5,0x28,0x9F,0x1E,0x29,0x41,0x5D,0xD1,0x51, + 0x0F,0xD5,0x5B,0x28,0x87,0x20,0x0C,0x9F,0x2E,0x95,0xA1,0xFD,0x42,0xBD,0xAE,0x25, + 0x3F,0x53,0x92,0x95,0xD3,0xB4,0x49,0xBE,0xA8,0xB2,0x29,0x7F,0x99,0x35,0xEE,0x81, + 0x2A,0x4D,0xB5,0x00,0x64,0xCB,0xEA,0xBB,0x11,0xAC,0xBC,0x1C,0x04,0xF3,0x83,0x79, + 0x8D,0xBD,0x68,0x81,0xBF,0x25,0xBA,0x54,0xAB,0xC0,0x1E,0x75,0x8E,0x4E,0xE1,0xBF, + 0x29,0x1B,0xA7,0x2F,0xFD,0x91,0x64,0xEE,0xA0,0x96,0xD4,0xAB,0xED,0x6F,0x77,0x3A, + 0x87,0xE6,0x44,0xF6,0xAF,0xD2,0x7D,0x0D,0xBB,0x77,0x20,0xF4,0x1D,0x2E,0xA9,0x74, + 0x7B,0x8E,0xF6,0x34,0xA4,0x37,0x82,0x25,0x77,0x82,0x44,0x74,0xF9,0xAB,0xC6,0x62, + 0x1D,0xDF,0x34,0xBB,0x1C,0x09,0x30,0xD7,0x0F,0xAC,0xDA,0x9E,0x6F,0x30,0xAF,0xD6, + 0xC1,0x82,0x85,0x48,0xCB,0xBA,0xBE,0x6A,0x7E,0x44,0x32,0x43,0x65,0x48,0x5B,0x53, + 0x45,0xAD,0xC3,0x5D,0x22,0x89,0x40,0x36,0xE9,0xC4,0x86,0xFF,0x74,0x09,0x34,0x27, + 0x14,0x36,0x61,0x84,0x37,0x18,0xE2,0x9F,0xD5,0x69,0xE2,0x38,0xDF, +}; + + +static void test_apple_server_auth_policy() +{ + CFDateRef date=NULL; + CFArrayRef policies=NULL; + SecPolicyRef policy=NULL; + SecTrustRef trust=NULL; + SecCertificateRef cert0=NULL, cert1=NULL; + CFMutableArrayRef certs=NULL; + SecTrustResultType trustResult; + CFIndex chainLen; + + isnt(cert0 = SecCertificateCreateWithBytes(NULL, kTestAppleServerAuthLeafCert, sizeof(kTestAppleServerAuthLeafCert)), + NULL, "create cert0"); + isnt(cert1 = SecCertificateCreateWithBytes(NULL, kTestAppleServerAuthCACert, sizeof(kTestAppleServerAuthCACert)), + NULL, "create cert1"); + // these chain to the Apple Root CA so it is not provided + + isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array"); + CFArrayAppendValue(certs, cert0); + CFArrayAppendValue(certs, cert1); + + /* Case 1: success */ + isnt(policy = SecPolicyCreateAppleSSLService(CFSTR("test.nosuchdomain")), NULL, "create policy"); + policies = CFArrayCreate(NULL, (const void **)&policy, 1, &kCFTypeArrayCallBacks); + CFRelease(policy); + policy = NULL; + ok_status(SecTrustCreateWithCertificates(certs, policies, &trust), "create trust"); + CFRelease(policies); + policies = NULL; + isnt(date = CFDateCreateForGregorianZuluMoment(NULL, 2014, 7, 20, 12, 0, 0), + NULL, "create verify date"); + ok_status(SecTrustSetVerifyDate(trust, date), "set date"); + CFReleaseSafe(date); + date = NULL; + ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); + ok(trustResult == kSecTrustResultUnspecified, "trustResult 4 expected (got %d)", + (int)trustResult); + chainLen = SecTrustGetCertificateCount(trust); + ok(chainLen == 3, "chain length 3 expected (got %d)", (int)chainLen); + CFRelease(trust); + trust = NULL; + + CFReleaseSafe(cert0); + CFReleaseSafe(cert1); + CFReleaseSafe(certs); +} + +static void test_apple_corp_ca_policy() +{ + CFDateRef date=NULL; + CFArrayRef policies=NULL; + SecPolicyRef policy=NULL; + SecTrustRef trust=NULL; + SecCertificateRef cert0=NULL, cert1=NULL, cert2=NULL; + CFMutableArrayRef certs=NULL, servers=NULL, anchors=NULL; + + SecTrustResultType trustResult; + CFIndex chainLen; + + isnt(cert0 = SecCertificateCreateWithBytes(NULL, kTestAppleVPNLeafCert, sizeof(kTestAppleVPNLeafCert)), + NULL, "create cert0"); + isnt(cert1 = SecCertificateCreateWithBytes(NULL, kTestAppleVPNCACert, sizeof(kTestAppleVPNCACert)), + NULL, "create cert1"); + isnt(cert2 = SecCertificateCreateWithBytes(NULL, kTestAppleCorpCACert, sizeof(kTestAppleCorpCACert)), + NULL, "create cert2"); + + isnt(certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array"); + CFArrayAppendValue(certs, cert0); + CFArrayAppendValue(certs, cert1); + CFArrayAppendValue(certs, cert2); + isnt(anchors = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create anchors array"); + CFArrayAppendValue(anchors, cert2); + + /* Case 1: SSL server */ + isnt(policy = SecPolicyCreateSSL(true, CFSTR("com.apple.ist.ds.appleconnect2.production.vpn.8F2B3ADCD72ED2EA08DDC26AD0255A983B1DEBEB")), NULL, "create policy"); + policies = CFArrayCreate(NULL, (const void **)&policy, 1, &kCFTypeArrayCallBacks); + CFRelease(policy); + policy = NULL; + ok_status(SecTrustCreateWithCertificates(certs, policies, &trust), "create trust"); + CFRelease(policies); + policies = NULL; + isnt(date = CFDateCreateForGregorianZuluMoment(NULL, 2014, 7, 20, 12, 0, 0), + NULL, "create verify date"); + ok_status(SecTrustSetVerifyDate(trust, date), "set date"); + CFReleaseSafe(date); + date = NULL; + ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set anchors"); + ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); + ok(trustResult == kSecTrustResultRecoverableTrustFailure, "trustResult 5 expected (got %d)", + (int)trustResult); + chainLen = SecTrustGetCertificateCount(trust); + ok(chainLen == 3, "chain length 3 expected (got %d)", (int)chainLen); + CFRelease(trust); + trust = NULL; + + /* Case 2: SSL client */ + isnt(policy = SecPolicyCreateSSL(false, NULL), NULL, "create policy"); + policies = CFArrayCreate(NULL, (const void **)&policy, 1, &kCFTypeArrayCallBacks); + CFRelease(policy); + policy = NULL; + ok_status(SecTrustCreateWithCertificates(certs, policies, &trust), "create trust"); + CFRelease(policies); + policies = NULL; + isnt(date = CFDateCreateForGregorianZuluMoment(NULL, 2014, 7, 20, 12, 0, 0), + NULL, "create verify date"); + ok_status(SecTrustSetVerifyDate(trust, date), "set date"); + CFReleaseSafe(date); + date = NULL; + ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set anchors"); + ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); + ok(trustResult == kSecTrustResultUnspecified, "trustResult 4 expected (got %d)", + (int)trustResult); + chainLen = SecTrustGetCertificateCount(trust); + ok(chainLen == 3, "chain length 3 expected (got %d)", (int)chainLen); + CFRelease(trust); + trust = NULL; + + /* Case 3: EAP */ + isnt(servers = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks), NULL, "create cert array"); + CFArrayAppendValue(servers, CFSTR("com.apple.ist.ds.appleconnect2.production.vpn.8F2B3ADCD72ED2EA08DDC26AD0255A983B1DEBEB")); + isnt(policy = SecPolicyCreateEAP(true, servers), NULL, "create policy"); + policies = CFArrayCreate(NULL, (const void **)&policy, 1, &kCFTypeArrayCallBacks); + CFRelease(policy); + policy = NULL; + ok_status(SecTrustCreateWithCertificates(certs, policies, &trust), "create trust"); + CFRelease(policies); + policies = NULL; + isnt(date = CFDateCreateForGregorianZuluMoment(NULL, 2014, 7, 20, 12, 0, 0), + NULL, "create verify date"); + ok_status(SecTrustSetVerifyDate(trust, date), "set date"); + CFReleaseSafe(date); + date = NULL; + ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set anchors"); + ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); + ok(trustResult == kSecTrustResultUnspecified, "trustResult 4 expected (got %d)", + (int)trustResult); + chainLen = SecTrustGetCertificateCount(trust); + ok(chainLen == 3, "chain length 3 expected (got %d)", (int)chainLen); + CFRelease(trust); + trust = NULL; + + /* Case 4: IPsec */ + isnt(policy = SecPolicyCreateIPSec(false, NULL), NULL, "create policy"); + policies = CFArrayCreate(NULL, (const void **)&policy, 1, &kCFTypeArrayCallBacks); + CFRelease(policy); + policy = NULL; + ok_status(SecTrustCreateWithCertificates(certs, policies, &trust), "create trust"); + CFRelease(policies); + policies = NULL; + isnt(date = CFDateCreateForGregorianZuluMoment(NULL, 2014, 7, 20, 12, 0, 0), + NULL, "create verify date"); + ok_status(SecTrustSetVerifyDate(trust, date), "set date"); + CFReleaseSafe(date); + date = NULL; + ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set anchors"); + ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); + ok(trustResult == kSecTrustResultUnspecified, "trustResult 4 expected (got %d)", + (int)trustResult); + chainLen = SecTrustGetCertificateCount(trust); + ok(chainLen == 3, "chain length 3 expected (got %d)", (int)chainLen); + CFRelease(trust); + trust = NULL; + + CFReleaseSafe(cert0); + CFReleaseSafe(cert1); + CFReleaseSafe(cert2); + CFReleaseSafe(certs); + CFReleaseSafe(servers); + CFReleaseSafe(anchors); +} + +static void tests(void) +{ + test_apple_server_auth_policy(); + test_apple_corp_ca_policy(); +} + +int si_81_sectrust_server_auth(int argc, char *const *argv) +{ + plan_tests(48); + + tests(); + + return 0; +} diff --git a/Security/sec/Security/Regressions/secitem/si_77_SecAccessControl.c b/Security/sec/Security/Regressions/secitem/si_77_SecAccessControl.c new file mode 100644 index 00000000..efc112f2 --- /dev/null +++ b/Security/sec/Security/Regressions/secitem/si_77_SecAccessControl.c @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "Security_regressions.h" + +static CFTypeRef kSecAccessControlKeyProtection = CFSTR("prot"); + +// TODO: Use real name of this policy from SCred/AppleCredentialManager +CFTypeRef kSecAccessControlPolicyUserPresent = CFSTR("DeviceOwnerAuthenticated"); + +static void tests(void) +{ + CFAllocatorRef allocator = kCFAllocatorDefault; + CFTypeRef protection = kSecAttrAccessibleAlways; + SecAccessControlCreateFlags flags = kSecAccessControlUserPresence; + CFErrorRef error = NULL; + + // Simple API tests: + + // 1: ACL with protection only + SecAccessControlRef acl = SecAccessControlCreateWithFlags(allocator, protection, 0, &error); + ok(acl != NULL, "SecAccessControlCreateWithFlags: %@", error); + CFReleaseNull(error); + CFReleaseNull(acl); + + // 2: ACL with flags only (not allowed) + acl = SecAccessControlCreateWithFlags(allocator, NULL, flags, &error); + ok(acl == NULL, "SecAccessControlCreateWithFlags"); + CFReleaseNull(error); + CFReleaseNull(acl); + + // 3: ACL with protection and flags + acl = SecAccessControlCreateWithFlags(allocator, protection, flags, &error); + ok(acl != NULL, "SecAccessControlCreateWithFlags: %@", error); + CFReleaseNull(error); + + // Extended API tests: + + // 4: Check created ACL + CFTypeRef aclProtection = SecAccessControlGetProtection(acl); + is(aclProtection, protection, "SecAccessControlGetProtection"); + + SecAccessConstraintRef aclConstraint = SecAccessControlGetConstraint(acl, kAKSKeyOpDecrypt); + // 5: Check created ACL + ok(aclConstraint != NULL && isDictionary(aclConstraint), "SecAccessControlGetConstraint"); + // 6: Check created ACL + eq_string(CFDictionaryGetValue(aclConstraint, kAKSKeyAclConstraintPolicy), kSecAccessControlPolicyUserPresent, "SecAccessControlGetConstraint"); + + CFReleaseNull(acl); + + // Simple SPI tests: + + // 7: Empty ACL + acl = SecAccessControlCreate(allocator, &error); + ok(acl != NULL, "SecAccessControlCreate: %@", error); + CFReleaseNull(error); + + // 8: ACL protection + bool result = SecAccessControlSetProtection(acl, protection, &error); + ok(result, "SecAccessControlSetProtection: %@", error); + CFReleaseNull(error); + + aclProtection = SecAccessControlGetProtection(acl); + // 9: ACL protection + is(aclProtection, protection, "SecAccessControlGetProtection"); + + // 10: Policy constraint + SecAccessConstraintRef policy = SecAccessConstraintCreatePolicy(kSecAccessControlPolicyUserPresent, &error); + ok(policy != NULL, "SecAccessConstraintCreatePolicy: %@", error); + // 11: Policy constraint + ok(isDictionary(policy), "SecAccessConstraintCreatePolicy"); + // 12: Policy constraint + is(CFDictionaryGetValue(policy, kAKSKeyAclConstraintPolicy), kSecAccessControlPolicyUserPresent, "SecAccessConstraintCreatePolicy"); + CFReleaseNull(error); + CFReleaseNull(policy); + + // 13: Passcode constraint + SecAccessConstraintRef passcode = SecAccessConstraintCreatePasscode(true); + ok(passcode != NULL && isDictionary(passcode), "SecAccessConstraintCreatePasscode"); + // 14: Passcode constraint + is(CFDictionaryGetValue(passcode, kAKSKeyAclConstraintUserPasscode), kCFBooleanTrue, "SecAccessConstraintCreatePasscode"); +// CFReleaseNull(passcode); passcode will be used in later tests + + // 15: TouchID constraint + CFUUIDRef uuid = CFUUIDCreate(allocator); + CFStringRef uuidString = CFUUIDCreateString(allocator, uuid); + CFDataRef uuidData = CFStringCreateExternalRepresentation(allocator, uuidString, kCFStringEncodingUTF8, 0); + SecAccessConstraintRef touchID = SecAccessConstraintCreateTouchID(uuidData, &error); + ok(touchID != NULL, "SecAccessConstraintCreateTouchID: %@", error); + // 16: TouchID constraint + ok(isDictionary(touchID), "SecAccessConstraintCreateTouchID"); + // 17: TouchID constraint + is(CFDictionaryGetValue(touchID, kAKSKeyAclConstraintBio), uuidData, "SecAccessConstraintCreateTouchID"); + CFReleaseNull(error); + CFReleaseNull(touchID); + CFReleaseNull(uuidData); + CFReleaseNull(uuidString); + CFReleaseNull(uuid); + + touchID = SecAccessConstraintCreateTouchID(NULL, &error); + // 18: TouchID constraint + ok(touchID != NULL, "SecAccessConstraintCreateTouchID: %@", error); + // 19: TouchID constraint + ok(isDictionary(touchID), "SecAccessConstraintCreateTouchID"); + // 20: TouchID constraint + is(CFDictionaryGetValue(touchID, kAKSKeyAclConstraintBio), kCFBooleanTrue, "SecAccessConstraintCreateTouchID"); + CFReleaseNull(error); + // CFReleaseNull(touchID); touchID will be used in later tests + + // 21: KofN constraint + CFTypeRef constraints_array[] = { passcode, touchID }; + CFArrayRef constraintsArray = CFArrayCreate(allocator, constraints_array, array_size(constraints_array), &kCFTypeArrayCallBacks); + SecAccessConstraintRef kofn = SecAccessConstraintCreateKofN(1, constraintsArray, &error); + ok(kofn != NULL, "SecAccessConstraintCreateKofN: %@", error); + // 22: KofN constraint + ok(isDictionary(kofn), "SecAccessConstraintCreateKofN"); + CFTypeRef kofnConstraint = CFDictionaryGetValue(kofn, kAKSKeyAclConstraintKofN); + // 23: KofN constraint + ok(kofnConstraint != NULL && isDictionary(kofnConstraint), "SecAccessConstraintCreateKofN"); + CFNumberRef required = CFNumberCreateWithCFIndex(allocator, 1); + // 24: KofN constraint + is(CFDictionaryGetValue(kofnConstraint, kAKSKeyAclParamKofN), required, "SecAccessConstraintCreateKofN"); + // 25: KofN constraint + is(CFDictionaryGetValue(kofnConstraint, kAKSKeyAclConstraintBio), kCFBooleanTrue, "SecAccessConstraintCreateKofN"); + // 26: KofN constraint + is(CFDictionaryGetValue(kofnConstraint, kAKSKeyAclConstraintUserPasscode), kCFBooleanTrue, "SecAccessConstraintCreateKofN"); + CFReleaseNull(error); + CFReleaseNull(kofn); + CFReleaseNull(required); + CFReleaseNull(constraintsArray); + CFReleaseNull(passcode); + + // 27: Set constraint option + CFTypeRef accesss_groups_array[] = { CFSTR("wheel"), CFSTR("staff") }; + CFArrayRef accessGroupsArray = CFArrayCreate(allocator, accesss_groups_array, array_size(accesss_groups_array), &kCFTypeArrayCallBacks); + result = SecAccessConstraintSetOption(touchID, kAKSKeyAclConstraintAccessGroups, accessGroupsArray, &error); + ok(result, "SecAccessConstraintSetOption: %@", error); + // 28: Set constraint option + is(CFDictionaryGetValue(touchID, kAKSKeyAclConstraintAccessGroups), accessGroupsArray, "SecAccessConstraintSetOption"); + CFReleaseNull(error); + // CFReleaseNull(accessGroupsArray); accessGroupsArray will be used in later tests + + // 29: Add ACL constraint for operation + result = SecAccessControlAddConstraintForOperation(acl, kAKSKeyOpDecrypt, touchID, &error); + ok(result, "SecAccessControlAddConstraintForOperation: %@", error); + CFReleaseNull(error); + + // 30: Get ACL operation constraint + SecAccessConstraintRef constraint = SecAccessControlGetConstraint(acl, kAKSKeyOpDecrypt); + is(constraint, touchID, "SecAccessControlGetConstraint"); + CFReleaseNull(touchID); + + // 31: Add ACL constraint for operation (kCFBooleanTrue) + result = SecAccessControlAddConstraintForOperation(acl, kAKSKeyOpDecrypt, kCFBooleanTrue, &error); + ok(result, "SecAccessControlAddConstraintForOperation: %@", error); + CFReleaseNull(error); + + // 32: Get ACL operation constraint (kCFBooleanTrue) + constraint = SecAccessControlGetConstraint(acl, kAKSKeyOpDecrypt); + is(constraint, kCFBooleanTrue, "SecAccessControlGetConstraint"); + + // 33: ACL access groups + SecAccessControlSetAccessGroups(acl, accessGroupsArray); + CFArrayRef aclAccessGroups = SecAccessControlGetAccessGroups(acl, kAKSKeyOpDecrypt); + is(aclAccessGroups, accessGroupsArray, "SecAccessControlGetAccessGroups"); + + // 34: Get ACL constraints + CFDictionaryRef constraints = SecAccessControlGetConstraints(acl); + ok(constraints != NULL && isDictionary(constraints), "SecAccessControlGetConstraints"); + // 35: Get ACL constraints + is(CFDictionaryGetValue(constraints, kAKSKeyOpDecrypt), kCFBooleanTrue, "SecAccessControlGetConstraints"); + // 36: Get ACL constraints + is(CFDictionaryGetValue(constraints, kAKSKeyAccessGroups), accessGroupsArray, "SecAccessControlGetConstraints"); + CFReleaseNull(accessGroupsArray); + + // 37: Remove ACL operation constraint + SecAccessControlRemoveConstraintForOperation(acl, kAKSKeyOpDecrypt); +SKIP: { + // All constraints are removed so any operation should be allowed. + constraint = SecAccessControlGetConstraint(acl, kAKSKeyOpDecrypt); + skip("ACL access groups are considered as a constraint which blocks ACL operations", 1, constraint == kCFBooleanTrue); + is(constraint, kCFBooleanTrue, "SecAccessControlRemoveConstraintForOperation"); + } + + // 38: ACL export and import + CFDataRef aclData = SecAccessControlCopyData(acl); + ok(aclData != NULL, "SecAccessControlCopyData"); + + SecAccessControlRef aclCopy = SecAccessControlCreateFromData(allocator, aclData, &error); + // 39: ACL export and import + ok(aclCopy != NULL, "SecAccessControlCopyData: %@", error); + // 40: ACL export and import + ok(CFEqual(aclCopy, acl), "SecAccessControlCopyData"); + CFReleaseNull(error); + CFReleaseNull(aclCopy); + CFReleaseNull(aclData); + + // Extended SPI tests: + + // 41: kAKSKeyDefaultOpAcl + result = SecAccessControlAddConstraintForOperation(acl, kAKSKeyOpDefaultAcl, kCFBooleanTrue, &error); + ok(result, "SecAccessControlAddConstraintForOperation: %@", error); + constraint = SecAccessControlGetConstraint(acl, kAKSKeyOpDecrypt); + // 42: kAKSKeyDefaultOpAcl + is(constraint, kCFBooleanTrue, "SecAccessControlRemoveConstraintForOperation"); + CFReleaseNull(error); + + CFReleaseNull(acl); +} + +int si_77_SecAccessControl(int argc, char *const *argv) +{ + plan_tests(42); + + tests(); + + return 0; +} diff --git a/sec/Security/Regressions/vmdh/vmdh-40.c b/Security/sec/Security/Regressions/vmdh/vmdh-40.c similarity index 96% rename from sec/Security/Regressions/vmdh/vmdh-40.c rename to Security/sec/Security/Regressions/vmdh/vmdh-40.c index 7fc741fc..0d3f9a68 100644 --- a/sec/Security/Regressions/vmdh/vmdh-40.c +++ b/Security/sec/Security/Regressions/vmdh/vmdh-40.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2012 Apple Inc. All Rights Reserved. */ #include diff --git a/sec/Security/Regressions/vmdh/vmdh-41-example.c b/Security/sec/Security/Regressions/vmdh/vmdh-41-example.c similarity index 96% rename from sec/Security/Regressions/vmdh/vmdh-41-example.c rename to Security/sec/Security/Regressions/vmdh/vmdh-41-example.c index c56d4e07..03943d00 100644 --- a/sec/Security/Regressions/vmdh/vmdh-41-example.c +++ b/Security/sec/Security/Regressions/vmdh/vmdh-41-example.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2008,2010,2012,2014 Apple Inc. All Rights Reserved. */ #include @@ -56,7 +56,7 @@ static const uint8_t client_priv[] = { 0xB1, 0xD2, 0x3B, 0x24, 0xF3, 0x30, 0x0B, 0x61, }; -static const uint8_t client_pub[] = { +__unused static const uint8_t client_pub[] = { 0x73, 0x00, 0x67, 0x2E, 0x71, 0x38, 0x55, 0x6A, 0x9C, 0xA4, 0x1E, 0x7A, 0x53, 0x3A, 0x22, 0xD8, 0xF0, 0x37, 0xBD, 0x57, 0x9F, 0x4A, 0xD1, 0xD1, @@ -67,7 +67,7 @@ static const uint8_t client_pub[] = { 0xA8, 0x69, 0xBE, 0x72, 0x54, 0x0C, 0x63, 0xDD, }; -static const uint8_t server_priv[] = { +__unused static const uint8_t server_priv[] = { 0x7A, 0x20, 0x70, 0x42, 0xF2, 0x19, 0x0F, 0x54, 0xA4, 0xD6, 0x45, 0x85, 0xFF, 0xE3, 0x4F, 0x95, 0x77, 0x4E, 0x05, 0xA9, 0xCF, 0x60, 0xFA, 0x54, diff --git a/sec/Security/Regressions/vmdh/vmdh-42-example2.c b/Security/sec/Security/Regressions/vmdh/vmdh-42-example2.c similarity index 97% rename from sec/Security/Regressions/vmdh/vmdh-42-example2.c rename to Security/sec/Security/Regressions/vmdh/vmdh-42-example2.c index 5e35b37b..102b113e 100644 --- a/sec/Security/Regressions/vmdh/vmdh-42-example2.c +++ b/Security/sec/Security/Regressions/vmdh/vmdh-42-example2.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2008,2010,2012,2014 Apple Inc. All Rights Reserved. */ #include @@ -56,7 +56,7 @@ static const uint8_t client_priv[] = { 0x0e, 0x02, 0x6e, 0x69, 0x6c, 0xca, 0x2a, 0x95 }; -static const uint8_t client_pub[] = { +__unused static const uint8_t client_pub[] = { 0x15, 0xDF, 0x17, 0x6E, 0xB4, 0x95, 0xA7, 0x92, 0x41, 0xB6, 0xF1, 0x93, 0x19, 0xDB, 0x34, 0xF1, 0xE0, 0x0D, 0x62, 0xCD, 0x55, 0xC7, 0x0B, 0x27, diff --git a/Security/sec/Security/SecAccessControl.c b/Security/sec/Security/SecAccessControl.c new file mode 100644 index 00000000..357c0b29 --- /dev/null +++ b/Security/sec/Security/SecAccessControl.c @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * SecAccessControl.c - CoreFoundation based access control object + */ + +#include +#include +#include +#include +#include +#include +#include + +#if TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_IPHONE_SIMULATOR) +#define USE_KEYSTORE 1 +#elif TARGET_OS_EMBEDDED && !TARGET_IPHONE_SIMULATOR +#define USE_KEYSTORE 1 +#else /* no keystore on this platform */ +#define USE_KEYSTORE 0 +#endif + +#include + +static CFTypeRef kSecAccessControlKeyProtection = CFSTR("prot"); + +// TODO: Use real name of this policy from SCred/AppleCredentialManager +CFTypeRef kSecAccessControlPolicyUserPresent = CFSTR("DeviceOwnerAuthenticated"); + +struct __SecAccessControl { + CFRuntimeBase _base; + CFMutableDictionaryRef dict; +}; + +static CFStringRef SecAccessControlCopyDescription(CFTypeRef cf) { + SecAccessControlRef access_control = (SecAccessControlRef)cf; + return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR(""), access_control); +} + +static Boolean SecAccessControlCompare(CFTypeRef lhs, CFTypeRef rhs) { + SecAccessControlRef laccess_control = (SecAccessControlRef)lhs; + SecAccessControlRef raccess_control = (SecAccessControlRef)rhs; + return (laccess_control == raccess_control) || CFEqual(laccess_control->dict, raccess_control->dict); +} + +static void SecAccessControlDestroy(CFTypeRef cf) { + SecAccessControlRef access_control = (SecAccessControlRef)cf; + CFReleaseSafe(access_control->dict); +} + +CFGiblisWithCompareFor(SecAccessControl); + +SecAccessControlRef SecAccessControlCreate(CFAllocatorRef allocator, CFErrorRef *error) { + SecAccessControlRef access_control = CFTypeAllocate(SecAccessControl, struct __SecAccessControl, allocator); + if (!access_control) { + SecError(errSecAllocate, error, CFSTR("allocate memory for SecAccessControl")); + return NULL; + } + + access_control->dict = CFDictionaryCreateMutableForCFTypes(allocator); + return access_control; +} + + +SecAccessControlRef SecAccessControlCreateWithFlags(CFAllocatorRef allocator, CFTypeRef protection, + SecAccessControlCreateFlags flags, CFErrorRef *error) { + SecAccessControlRef access_control = NULL; + CFTypeRef constraint = NULL; + + require_quiet(access_control = SecAccessControlCreate(allocator, error), errOut); + + if (!SecAccessControlSetProtection(access_control, protection, error)) + goto errOut; + + if (flags & kSecAccessControlUserPresence) { + require_quiet(constraint = SecAccessConstraintCreatePolicy(kSecAccessControlPolicyUserPresent, error), errOut); + require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpDecrypt, + constraint, error), errOut); + CFReleaseNull(constraint); + require_quiet(SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpDelete, kCFBooleanTrue, error), errOut); + } + + return access_control; + +errOut: + CFReleaseSafe(access_control); + CFReleaseSafe(constraint); + return NULL; +} + +CFTypeRef SecAccessControlGetProtection(SecAccessControlRef access_control) { + return CFDictionaryGetValue(access_control->dict, kSecAccessControlKeyProtection); +} + +static bool checkItemInArray(CFTypeRef item, const CFTypeRef *values, CFIndex count, CFStringRef errMessage, CFErrorRef *error) { + for (CFIndex i = 0; i < count; i++) { + if (CFEqualSafe(item, values[i])) { + return true; + } + } + return SecError(errSecParam, error, errMessage, item); +} + +#define CheckItemInArray(item, values, msg) \ +{ \ + const CFTypeRef vals[] = values; \ + if (!checkItemInArray(item, vals, sizeof(vals)/sizeof(*vals), CFSTR(msg), error)) { \ + return false; \ + } \ +} + +#define ItemArray(...) { __VA_ARGS__ } + + +bool SecAccessControlSetProtection(SecAccessControlRef access_control, CFTypeRef protection, CFErrorRef *error) { + // Verify protection type. + CheckItemInArray(protection, ItemArray(kSecAttrAccessibleAlways, kSecAttrAccessibleAfterFirstUnlock, + kSecAttrAccessibleWhenUnlocked, kSecAttrAccessibleAlwaysThisDeviceOnly, + kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, + kSecAttrAccessibleWhenUnlockedThisDeviceOnly, + kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly), + "SecAccessControl: invalid protection %@"); + + // Protection valid, use it. + CFDictionarySetValue(access_control->dict, kSecAccessControlKeyProtection, protection); + return true; +} + +SecAccessConstraintRef SecAccessConstraintCreatePolicy(CFTypeRef policy, CFErrorRef *error) { + return CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, kAKSKeyAclConstraintPolicy, policy, NULL); +} + +SecAccessConstraintRef SecAccessConstraintCreatePasscode(bool systemPasscode) { + return CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, kAKSKeyAclConstraintUserPasscode, kCFBooleanTrue, NULL); +} + +SecAccessConstraintRef SecAccessConstraintCreateTouchID(CFDataRef uuid, CFErrorRef *error) { + return CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, kAKSKeyAclConstraintBio, + uuid ? uuid : (const void *)kCFBooleanTrue, NULL); +} + +SecAccessConstraintRef SecAccessConstraintCreateKofN(size_t numRequired, CFArrayRef constraints, CFErrorRef *error) { + CFNumberRef k = CFNumberCreateWithCFIndex(kCFAllocatorDefault, numRequired); + CFMutableDictionaryRef kofn = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, kAKSKeyAclParamKofN, k, NULL); + CFRelease(k); + + /* Populate kofn dictionary with constraint keys from the array. note that for now we just ignore any additional + constraint parameters, but we might err-out if some parameter is found, since we cannot propagate parameteres + into k-of-n dictionary. */ + const CFTypeRef keysToCopy[] = { kAKSKeyAclConstraintBio, kAKSKeyAclConstraintPolicy, + kAKSKeyAclConstraintUserPasscode }; + SecAccessConstraintRef constraint; + CFArrayForEachC(constraints, constraint) { + require_quiet(isDictionary(constraint), errOut); + bool found = false; + for (CFIndex i = 0; i < (CFIndex)(sizeof(keysToCopy) / sizeof(keysToCopy[0])); i++) { + CFTypeRef value = CFDictionaryGetValue(constraint, keysToCopy[i]); + if (value) { + CFDictionarySetValue(kofn, keysToCopy[i], value); + found = true; + break; + } + } + require_quiet(found, errOut); + } + + constraint = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, kAKSKeyAclConstraintKofN, kofn, NULL); + CFRelease(kofn); + return constraint; + +errOut: + SecError(errSecParam, error, CFSTR("SecAccessControl: invalid constraint for k-of-n")); + CFReleaseSafe(kofn); + return NULL; +} + +bool SecAccessConstraintSetOption(SecAccessConstraintRef constraint, CFTypeRef option, CFTypeRef value, CFErrorRef *error) { + CheckItemInArray(option, ItemArray(kAKSKeyAclConstraintAccessGroups, kAKSKeyAclParamCredentialMaxAge), + "SecAccessControl: invalid constraint option %@"); + CFDictionarySetValue((CFMutableDictionaryRef)constraint, option, value); + return true; +} + +bool SecAccessControlAddConstraintForOperation(SecAccessControlRef access_control, CFTypeRef operation, CFTypeRef constraint, CFErrorRef *error) { + CheckItemInArray(operation, ItemArray(kAKSKeyOpEncrypt, kAKSKeyOpDecrypt, + kAKSKeyOpSync, kAKSKeyOpDefaultAcl, kAKSKeyOpDelete), + "SecAccessControl: invalid operation %@"); + if (!isDictionary(constraint) && !CFEqual(constraint, kCFBooleanTrue) && !CFEqual(constraint, kCFBooleanFalse) ) { + return SecError(errSecParam, error, CFSTR("invalid constraint")); + } + + CFMutableDictionaryRef ops = (CFMutableDictionaryRef)CFDictionaryGetValue(access_control->dict, kAKSKeyAcl); + if (!ops) { + ops = CFDictionaryCreateMutableForCFTypes(CFGetAllocator(access_control)); + CFDictionarySetValue(access_control->dict, kAKSKeyAcl, ops); + } + CFDictionarySetValue(ops, operation, constraint); + return true; +} + +void SecAccessControlRemoveConstraintForOperation(SecAccessControlRef access_control, CFTypeRef operation) { + CFMutableDictionaryRef ops = (CFMutableDictionaryRef)CFDictionaryGetValue(access_control->dict, kAKSKeyAcl); + if (ops) + CFDictionaryRemoveValue(ops, operation); +} + +SecAccessConstraintRef SecAccessControlGetConstraint(SecAccessControlRef access_control, CFTypeRef operation) { + CFMutableDictionaryRef ops = (CFMutableDictionaryRef)CFDictionaryGetValue(access_control->dict, kAKSKeyAcl); + if (!ops || CFDictionaryGetCount(ops) == 0) + // No ACL is present, this means that everything is allowed. + return kCFBooleanTrue; + + SecAccessConstraintRef constraint = CFDictionaryGetValue(ops, operation); + if (!constraint) { + constraint = CFDictionaryGetValue(ops, kAKSKeyOpDefaultAcl); + } + return constraint; +} + +CFDictionaryRef SecAccessControlGetConstraints(SecAccessControlRef access_control) { + return CFDictionaryGetValue(access_control->dict, kAKSKeyAcl); +} + +void SecAccessControlSetConstraints(SecAccessControlRef access_control, CFDictionaryRef constraints) { + CFMutableDictionaryRef mutableConstraints = CFDictionaryCreateMutableCopy(NULL, 0, constraints); + CFDictionarySetValue(access_control->dict, kAKSKeyAcl, mutableConstraints); + CFReleaseSafe(mutableConstraints); +} + +void SecAccessControlSetAccessGroups(SecAccessControlRef access_control, CFArrayRef access_groups) { + CFMutableDictionaryRef ops = (CFMutableDictionaryRef)CFDictionaryGetValue(access_control->dict, kAKSKeyAcl); + if (!ops) { + ops = CFDictionaryCreateMutableForCFTypes(CFGetAllocator(access_control)); + CFDictionarySetValue(access_control->dict, kAKSKeyAcl, ops); + } + CFDictionarySetValue(ops, kAKSKeyAccessGroups, access_groups); +} + +CFArrayRef SecAccessControlGetAccessGroups(SecAccessControlRef access_control, CFTypeRef operation) { + CFMutableDictionaryRef ops = (CFMutableDictionaryRef)CFDictionaryGetValue(access_control->dict, kAKSKeyAcl); + if (!ops) + return NULL; + + CFArrayRef access_groups = NULL; + SecAccessConstraintRef constraint = CFDictionaryGetValue(ops, operation); + if (!constraint) { + constraint = CFDictionaryGetValue(ops, kAKSKeyOpDefaultAcl); + } + if (constraint && isDictionary(constraint)) { + access_groups = CFDictionaryGetValue(constraint, kAKSKeyAclConstraintAccessGroups); + } + if (!access_groups) { + access_groups = CFDictionaryGetValue(ops, kAKSKeyAccessGroups); + } + return access_groups; +} + +CFDataRef SecAccessControlCopyData(SecAccessControlRef access_control) { + size_t len = der_sizeof_plist(access_control->dict, NULL); + CFMutableDataRef encoded = CFDataCreateMutable(0, len); + CFDataSetLength(encoded, len); + uint8_t *der_end = CFDataGetMutableBytePtr(encoded); + const uint8_t *der = der_end; + der_end += len; + der_end = der_encode_plist(access_control->dict, NULL, der, der_end); + if (!der_end) { + CFReleaseNull(encoded); + } + return encoded; +} + +SecAccessControlRef SecAccessControlCreateFromData(CFAllocatorRef allocator, CFDataRef data, CFErrorRef *error) { + SecAccessControlRef access_control; + require_quiet(access_control = SecAccessControlCreate(allocator, error), errOut); + + CFPropertyListRef plist; + const uint8_t *der = CFDataGetBytePtr(data); + const uint8_t *der_end = der + CFDataGetLength(data); + require_quiet(der = der_decode_plist(0, kCFPropertyListMutableContainers, &plist, error, der, der_end), errOut); + if (der != der_end) { + SecError(errSecDecode, error, CFSTR("trailing garbage at end of SecAccessControl data")); + goto errOut; + } + + CFReleaseSafe(access_control->dict); + access_control->dict = (CFMutableDictionaryRef)plist; + return access_control; + +errOut: + CFReleaseSafe(access_control); + return NULL; +} diff --git a/Security/sec/Security/SecAccessControl.h b/Security/sec/Security/SecAccessControl.h new file mode 100644 index 00000000..e91e1d92 --- /dev/null +++ b/Security/sec/Security/SecAccessControl.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecAccessControl + SecAccessControl defines access rights for items. + */ + +#ifndef _SECURITY_SECACCESSCONTROL_H_ +#define _SECURITY_SECACCESSCONTROL_H_ + +#include +#include + +__BEGIN_DECLS + +/*! + @function SecAccessControlGetTypeID + @abstract Returns the type identifier of SecAccessControl instances. + @result The CFTypeID of SecAccessControl instances. + */ +CFTypeID SecAccessControlGetTypeID(void) +__OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); + +typedef CF_OPTIONS(CFIndex, SecAccessControlCreateFlags) { + kSecAccessControlUserPresence = 1 << 0, +} __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); + +/*! + @function SecAccessControlCreateWithFlags + @abstract Creates new access control object based on protection type and additional flags. + @param allocator Allocator to be used by this instance. + @param protection Protection class to be used for the item. One of kSecAttrAccessible constants. + @param flags + @param error Additional error information filled in case of failure. + @result Newly created access control object. + */ +SecAccessControlRef SecAccessControlCreateWithFlags(CFAllocatorRef allocator, CFTypeRef protection, + SecAccessControlCreateFlags flags, CFErrorRef *error) +__OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); + +__END_DECLS + +#endif // _SECURITY_SECACCESSCONTROL_H_ diff --git a/Security/sec/Security/SecAccessControlExports.exp-in b/Security/sec/Security/SecAccessControlExports.exp-in new file mode 100644 index 00000000..aa90fe2b --- /dev/null +++ b/Security/sec/Security/SecAccessControlExports.exp-in @@ -0,0 +1,28 @@ +// SecAccessControlExports.exp-in +// sec +// + +_SecAccessConstraintCreateKofN +_SecAccessConstraintCreatePasscode +_SecAccessConstraintCreatePolicy +_SecAccessConstraintCreateTouchID +_SecAccessConstraintSetOption +_SecAccessControlAddConstraintForOperation +_SecAccessControlCopyData +_SecAccessControlCreate +_SecAccessControlCreateFromData +_SecAccessControlCreateWithFlags +_SecAccessControlGetAccessGroups +_SecAccessControlGetConstraint +_SecAccessControlGetConstraints +_SecAccessControlGetProtection +_SecAccessControlGetTypeID +_SecAccessControlRemoveConstraintForOperation +_SecAccessControlSetAccessGroups +_SecAccessControlSetProtection +_SecAccessControlSetConstraints + +_kSecAttrAccessControl +_kSecUseCredentialReference +_kSecUseOperationPrompt +_kSecUseNoAuthenticationUI diff --git a/Security/sec/Security/SecAccessControlPriv.h b/Security/sec/Security/SecAccessControlPriv.h new file mode 100644 index 00000000..4e088cbc --- /dev/null +++ b/Security/sec/Security/SecAccessControlPriv.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecAccessControlPriv + SecAccessControl defines access rights for items. + */ + +#ifndef _SECURITY_SECACCESSCONTROLPRIV_H_ +#define _SECURITY_SECACCESSCONTROLPRIV_H_ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/*! Creates new empty access control object. */ +SecAccessControlRef SecAccessControlCreate(CFAllocatorRef allocator, CFErrorRef *error); + +// Protection, currently only kSecAttrAccessible* constants are allowed. In future, another probable protection type might be CTK key object ID. +CFTypeRef SecAccessControlGetProtection(SecAccessControlRef access_control); +bool SecAccessControlSetProtection(SecAccessControlRef access_control, CFTypeRef protection, CFErrorRef *error); + +/*! Represents constraint of the operation. */ +typedef CFTypeRef SecAccessConstraintRef; + +/*! Creates constraint based on specified policy. + @param policy Identification of policy to be used. + */ +SecAccessConstraintRef SecAccessConstraintCreatePolicy(CFTypeRef policy, CFErrorRef *error); + +/*! Creates constraint which requires passcode verification. + @param systemPasscode If true, system passcode (device-specific) will be used, otehrwise application-specific passcode will be used. + */ +SecAccessConstraintRef SecAccessConstraintCreatePasscode(bool systemPasscode); + +/*! Creates constraint which requires TouchID verification. + @param uuid Identification of finger to be verified, or NULL if any enrolled finger can be used for verification. + */ +SecAccessConstraintRef SecAccessConstraintCreateTouchID(CFDataRef uuid, CFErrorRef *error); + +/*! Creates constraint composed of other constraints. + @param numRequired Number of constraints required to be satisfied in order to consider overal constraint satisfied. + @param constraints Array of constraints to be chosen from. + */ +SecAccessConstraintRef SecAccessConstraintCreateKofN(size_t numRequired, CFArrayRef constraints, CFErrorRef *error); + +/*! Sets additional option on the constraint. */ +bool SecAccessConstraintSetOption(SecAccessConstraintRef constraint, CFTypeRef option, CFTypeRef value, CFErrorRef *error); + +/*! Adds new constraint for specified operation. + @param access_control Instance of access control object to add constraint to. + @param operation Operation type. + @param constraint Constraint object, created by one of SecAccessControlConstraintCreate() functions or kCFBooleanTrue + meaning that operation will be always allowed. + */ +bool SecAccessControlAddConstraintForOperation(SecAccessControlRef access_control, CFTypeRef operation, + SecAccessConstraintRef constraint, CFErrorRef *error); + +/*! Removes constraint for specified operation. Does nothing if no constraint exist for specified operation. + @param access_control Instance of access control object to remove constraint from. + @param operation Operation type. + */ +void SecAccessControlRemoveConstraintForOperation(SecAccessControlRef access_control, CFTypeRef operation); + +/*! Sets or removes default access groups for access control object. + @param access_control Instance of access control object to set default access group to. + @param access_groups Set of access groups used if constraint does not contain specific access group. + */ +void SecAccessControlSetAccessGroups(SecAccessControlRef access_control, CFArrayRef access_groups); + +/*! Retrieves set of access group which applies for specified operation. + @param access_control Instance of access control object to query. + @param operation Operation type. + @return Set of access groups valid for specified operation, or NULL if no applicable access group was specified. + */ +CFArrayRef SecAccessControlGetAccessGroups(SecAccessControlRef access_control, CFTypeRef operation); + +/*! Retrieves dictionary with constraint applicable for specified operation. + @param access_control Instance of access control object to query. + @param operation Operation type. + @return Dictionary or kCFBooleanTrue representing constraint applied for requested operation. If the operation + is not allowed at all, NULL is returned. + */ +SecAccessConstraintRef SecAccessControlGetConstraint(SecAccessControlRef access_control, CFTypeRef operation); + +/*! Retrieves dictionary with constraints keyed by operations (i.e. the ACL part of access control object). + @return Dictionary with all constraints keyed by operation types. Returns NULL if no operations are constrained. + */ +CFDictionaryRef SecAccessControlGetConstraints(SecAccessControlRef access_control); + +/*! Sets dictionary with constraints for access control object. + @param access_control Instance of access control object to set default access group to. + @param constraints Constraint with all constraints. + */ +void SecAccessControlSetConstraints(SecAccessControlRef access_control, CFDictionaryRef constraints); + +/*! Creates Access control instance from data serialized by SecAccessControlCopyData(). */ +SecAccessControlRef SecAccessControlCreateFromData(CFAllocatorRef allocator, CFDataRef data, CFErrorRef *error); + +/*! Serializes all access control object into binary data form. */ +CFDataRef SecAccessControlCopyData(SecAccessControlRef access_control); + +__END_DECLS + +#endif // _SECURITY_SECACCESSCONTROLPRIV_H_ diff --git a/Security/sec/Security/SecBase.h b/Security/sec/Security/SecBase.h new file mode 100644 index 00000000..642ec2cf --- /dev/null +++ b/Security/sec/Security/SecBase.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2000-2009,2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecBase + SecBase contains common declarations for the Security functions. +*/ + +#ifndef _SECURITY_SECBASE_H_ +#define _SECURITY_SECBASE_H_ + +#include +#include + +#if defined(__clang__) +#define SEC_DEPRECATED_ATTRIBUTE DEPRECATED_ATTRIBUTE +#else +#define SEC_DEPRECATED_ATTRIBUTE +#endif + +__BEGIN_DECLS + +/*! + @typedef SecCertificateRef + @abstract CFType representing a X.509 certificate. + See SecCertificate.h for details. +*/ +typedef struct __SecCertificate *SecCertificateRef; + +/*! + @typedef SecIdentityRef + @abstract CFType representing an identity, which contains + a SecKeyRef and an associated SecCertificateRef. See + SecIdentity.h for details. +*/ +typedef struct __SecIdentity *SecIdentityRef; + +/*! + @typedef SecKeyRef + @abstract CFType representing a cryptographic key. See + SecKey.h for details. +*/ +typedef struct __SecKey *SecKeyRef; + +/*! + @typedef SecPolicyRef + @abstract CFType representing a X.509 certificate trust policy. + See SecPolicy.h for details. +*/ +typedef struct __SecPolicy *SecPolicyRef; + +/*! + @typedef SecAccessControl + @abstract CFType representing access control for an item. + SecAccessControl.h for details. +*/ +typedef struct __SecAccessControl *SecAccessControlRef; + +/*********************************************** + *** OSStatus values unique to Security APIs *** + ***********************************************/ + +/* + Note: the comments that appear after these errors are used to create + SecErrorMessages.strings. The comments must not be multi-line, and + should be in a form meaningful to an end user. If a different or + additional comment is needed, it can be put in the header doc format, + or on a line that does not start with errZZZ. +*/ + +enum +{ + errSecSuccess = 0, /* No error. */ + errSecUnimplemented = -4, /* Function or operation not implemented. */ + errSecIO = -36, /*I/O error (bummers)*/ + errSecOpWr = -49, /*file already open with with write permission*/ + errSecParam = -50, /* One or more parameters passed to a function where not valid. */ + errSecAllocate = -108, /* Failed to allocate memory. */ + errSecUserCanceled = -128, /* User canceled the operation. */ + errSecBadReq = -909, /* Bad parameter or invalid state for operation. */ + errSecInternalComponent = -2070, + errSecNotAvailable = -25291, /* No keychain is available. You may need to restart your computer. */ + errSecDuplicateItem = -25299, /* The specified item already exists in the keychain. */ + errSecItemNotFound = -25300, /* The specified item could not be found in the keychain. */ + errSecInteractionNotAllowed = -25308, /* User interaction is not allowed. */ + errSecDecode = -26275, /* Unable to decode the provided data. */ + errSecAuthFailed = -25293, /* The user name or passphrase you entered is not correct. */ +}; + +__END_DECLS + +#endif /* !_SECURITY_SECBASE_H_ */ diff --git a/sec/Security/SecBase64.c b/Security/sec/Security/SecBase64.c similarity index 100% rename from sec/Security/SecBase64.c rename to Security/sec/Security/SecBase64.c diff --git a/sec/Security/SecBase64.h b/Security/sec/Security/SecBase64.h similarity index 100% rename from sec/Security/SecBase64.h rename to Security/sec/Security/SecBase64.h diff --git a/Security/sec/Security/SecBasePriv.h b/Security/sec/Security/SecBasePriv.h new file mode 100644 index 00000000..ae6e2f7f --- /dev/null +++ b/Security/sec/Security/SecBasePriv.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2008-2009,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@ + */ + +/*! + @header SecBasePriv + SecBasePriv contains private error codes from the Security framework. +*/ + +#ifndef _SECURITY_SECBASEPRIV_H_ +#define _SECURITY_SECBASEPRIV_H_ + +#include + +__BEGIN_DECLS + +/******************************************************* + *** Private OSStatus values unique to Security APIs *** + *******************************************************/ + +/* + Note: the comments that appear after these errors are used to create SecErrorMessages.strings. + The comments must not be multi-line, and should be in a form meaningful to an end user. If + a different or additional comment is needed, it can be put in the header doc format, or on a + line that does not start with errZZZ. +*/ + +enum +{ + errSecReadOnly = -25292, /* This keychain cannot be modified. */ + errSecNoSuchKeychain = -25294, /* The specified keychain could not be found. */ + errSecInvalidKeychain = -25295, /* The specified keychain is not a valid keychain file. */ + errSecDuplicateKeychain = -25296, /* A keychain with the same name already exists. */ + errSecDuplicateCallback = -25297, /* The specified callback function is already installed. */ + errSecInvalidCallback = -25298, /* The specified callback function is not valid. */ + errSecBufferTooSmall = -25301, /* There is not enough memory available to use the specified item. */ + errSecDataTooLarge = -25302, /* This item contains information which is too large or in a format that cannot be displayed. */ + errSecNoSuchAttr = errSecParam, // -25303, /* The specified attribute does not exist. */ + errSecInvalidItemRef = -25304, /* The specified item is no longer valid. It may have been deleted from the keychain. */ + errSecInvalidSearchRef = -25305, /* Unable to search the current keychain. */ + errSecNoSuchClass = errSecParam, // -25306, /* The specified item does not appear to be a valid keychain item. */ + errSecNoDefaultKeychain = -25307, /* A default keychain could not be found. */ + errSecReadOnlyAttr = -25309, /* The specified attribute could not be modified. */ + errSecWrongSecVersion = -25310, /* This keychain was created by a different version of the system software and cannot be opened. */ + errSecKeySizeNotAllowed = errSecParam, // -25311, /* This item specifies a key size which is too large. */ + errSecNoStorageModule = -25312, /* A required component (data storage module) could not be loaded. You may need to restart your computer. */ + errSecNoCertificateModule = -25313, /* A required component (certificate module) could not be loaded. You may need to restart your computer. */ + errSecNoPolicyModule = -25314, /* A required component (policy module) could not be loaded. You may need to restart your computer. */ + errSecInteractionRequired = -25315, /* User interaction is required, but is currently not allowed. */ + errSecDataNotAvailable = -25316, /* The contents of this item cannot be retrieved. */ + errSecDataNotModifiable = -25317, /* The contents of this item cannot be modified. */ + errSecCreateChainFailed = -25318, /* One or more certificates required to validate this certificate cannot be found. */ + errSecACLNotSimple = -25240, /* The specified access control list is not in standard (simple) form. */ + errSecInvalidTrustSetting = -25242, /* The specified trust setting is invalid. */ + errSecNoAccessForItem = -25243, /* The specified item has no access control. */ + errSecInvalidOwnerEdit = -25244, /* Invalid attempt to change the owner of this item. */ + errSecInvalidPrefsDomain = -25319, /* The specified preferences domain is not valid. */ + errSecTrustNotAvailable = -25245, /* No trust results are available. */ + errSecUnsupportedFormat = -25256, /* Import/Export format unsupported. */ + errSecUnknownFormat = -25257, /* Unknown format in import. */ + errSecKeyIsSensitive = -25258, /* Key material must be wrapped for export. */ + errSecMultiplePrivKeys = -25259, /* An attempt was made to import multiple private keys. */ + errSecPassphraseRequired = -25260, /* Passphrase is required for import/export. */ + errSecInvalidPasswordRef = -25261, /* The password reference was invalid. */ + errSecInvalidTrustSettings = -25262, /* The Trust Settings record was corrupted. */ + errSecNoTrustSettings = -25263, /* No Trust Settings were found. */ + errSecPkcs12VerifyFailure = -25264, /* MAC verification failed during PKCS12 import. */ + errSecInvalidCertificate = errSecDecode, // -26265, /* This certificate could not be decoded. */ + errSecNotSigner = -26267, /* A certificate was not signed by its proposed parent. */ + errSecPolicyDenied = -26270, /* The certificate chain was not trusted due to a policy not accepting it. */ + errSecInvalidKey = errSecDecode, // -26274, /* The provided key material was not valid. */ + errSecInternal = -26276, /* An internal error occured in the Security framework. */ + errSecUnsupportedAlgorithm = errSecUnimplemented, // -26268, /* An unsupported algorithm was encountered. */ + errSecUnsupportedOperation = errSecUnimplemented, // -26271, /* The operation you requested is not supported by this key. */ + errSecUnsupportedPadding = errSecParam, // -26273, /* The padding you requested is not supported. */ + errSecItemInvalidKey = errSecParam, // -34000, /* A string key in dictionary is not one of the supported keys. */ + errSecItemInvalidKeyType = errSecParam, // -34001, /* A key in a dictionary is neither a CFStringRef nor a CFNumberRef. */ + errSecItemInvalidValue = errSecParam, // -34002, /* A value in a dictionary is an invalid (or unsupported) CF type. */ + errSecItemClassMissing = errSecParam, // -34003, /* No kSecItemClass key was specified in a dictionary. */ + errSecItemMatchUnsupported = errSecParam, // -34004, /* The caller passed one or more kSecMatch keys to a function which does not support matches. */ + errSecUseItemListUnsupported = errSecParam, // -34005, /* The caller passed in a kSecUseItemList key to a function which does not support it. */ + errSecUseKeychainUnsupported = errSecParam, // -34006, /* The caller passed in a kSecUseKeychain key to a function which does not support it. */ + errSecUseKeychainListUnsupported = errSecParam, // -34007, /* The caller passed in a kSecUseKeychainList key to a function which does not support it. */ + errSecReturnDataUnsupported = errSecParam, // -34008, /* The caller passed in a kSecReturnData key to a function which does not support it. */ + errSecReturnAttributesUnsupported = errSecParam, // -34009, /* The caller passed in a kSecReturnAttributes key to a function which does not support it. */ + errSecReturnRefUnsupported = errSecParam, // -34010, /* The caller passed in a kSecReturnRef key to a function which does not support it. */ + errSecReturnPersistentRefUnsupported = errSecParam, // -34010, /* The caller passed in a kSecReturnPersistentRef key to a function which does not support it. */ + errSecValueRefUnsupported = errSecParam, // -34012, /* The caller passed in a kSecValueRef key to a function which does not support it. */ + errSecValuePersistentRefUnsupported = errSecParam, // -34013, /* The caller passed in a kSecValuePersistentRef key to a function which does not support it. */ + errSecReturnMissingPointer = errSecParam, // -34014, /* The caller passed asked for something to be returned but did not pass in a result pointer. */ + errSecMatchLimitUnsupported = errSecParam, // -34015, /* The caller passed in a kSecMatchLimit key to a call which does not support limits. */ + errSecItemIllegalQuery = errSecParam, // -34016, /* The caller passed in a query which contained too many keys. */ + errSecWaitForCallback = -34017, /* This operation is incomplete, until the callback is invoked (not an error). */ + errSecMissingEntitlement = -34018, /* Internal error when a required entitlement isn't present. */ + errSecUpgradePending = -34019, /* Error returned if keychain database needs a schema migration but the device is locked, clients should wait for a device unlock notification and retry the command. */ + + errSecMPSignatureInvalid = -25327, /* Signature invalid on MP message */ + errSecOTRTooOld = -25328, /* Message is too old to use */ + errSecOTRIDTooNew = -25329, /* Key ID is too new to use! Message from the future? */ + +}; + + +__END_DECLS + +#endif /* !_SECURITY_SECBASEPRIV_H_ */ diff --git a/Security/sec/Security/SecCMS.c b/Security/sec/Security/SecCMS.c new file mode 100644 index 00000000..e6307a5c --- /dev/null +++ b/Security/sec/Security/SecCMS.c @@ -0,0 +1,696 @@ +/* + * Copyright (c) 2008-2010,2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + */ + +/* + * signed_data.c + * Security + * + * + */ +#include + +#include +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) +#define ENABLE_CMS 0 +#else +#define ENABLE_CMS 1 +#endif + +#if ENABLE_CMS +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "SecCMS.h" +#include + + +#include +#include +#include +#include +#include +#include + +CFTypeRef kSecCMSBulkEncryptionAlgorithm = CFSTR("kSecCMSBulkEncryptionAlgorithm"); +CFTypeRef kSecCMSSignDigest = CFSTR("kSecCMSSignDigest"); +CFTypeRef kSecCMSSignDetached = CFSTR("kSecCMSSignDetached"); +CFTypeRef kSecCMSSignHashAlgorithm = CFSTR("kSecCMSSignHashAlgorithm"); +CFTypeRef kSecCMSEncryptionAlgorithmDESCBC = CFSTR("kSecCMSEncryptionAlgorithmDESCBC"); +CFTypeRef kSecCMSEncryptionAlgorithmAESCBC = CFSTR("kSecCMSEncryptionAlgorithmAESCBC"); +CFTypeRef kSecCMSHashingAlgorithmMD5 = CFSTR("kSecCMSHashingAlgorithmMD5"); +CFTypeRef kSecCMSCertChainMode = CFSTR("kSecCMSCertChainMode"); +CFTypeRef kSecCMSCertChainModeNone = CFSTR("0"); +CFTypeRef kSecCMSAdditionalCerts = CFSTR("kSecCMSAdditionalCerts"); +CFTypeRef kSecCMSSignedAttributes = CFSTR("kSecCMSSignedAttributes"); +CFTypeRef kSecCMSSignDate = CFSTR("kSecCMSSignDate"); +CFTypeRef kSecCMSAllCerts = CFSTR("kSecCMSAllCerts"); + +OSStatus SecCMSCreateEnvelopedData(CFTypeRef recipient_or_cfarray_thereof, + CFDictionaryRef params, CFDataRef data, CFMutableDataRef enveloped_data) +{ + SecCmsMessageRef cmsg = NULL; + SecCmsContentInfoRef cinfo; + SecCmsEnvelopedDataRef envd = NULL; + SECOidTag algorithmTag = SEC_OID_DES_EDE3_CBC; + int keySize = 192; + OSStatus status = errSecParam; + + if (params) { + CFStringRef algorithm_name = CFDictionaryGetValue(params, kSecCMSBulkEncryptionAlgorithm); + if (algorithm_name) { + if (CFEqual(kSecCMSEncryptionAlgorithmDESCBC, algorithm_name)) { + algorithmTag = SEC_OID_DES_CBC; + keySize = 64; + } else if (CFEqual(kSecCMSEncryptionAlgorithmAESCBC, algorithm_name)) { + algorithmTag = SEC_OID_AES_128_CBC; + keySize = 128; + } + } + } + + require(cmsg = SecCmsMessageCreate(), out); + require(envd = SecCmsEnvelopedDataCreate(cmsg, algorithmTag, keySize), out); + require(cinfo = SecCmsMessageGetContentInfo(cmsg), out); + require_noerr(SecCmsContentInfoSetContentEnvelopedData(cinfo, envd), out); + require(cinfo = SecCmsEnvelopedDataGetContentInfo(envd), out); + require_noerr(SecCmsContentInfoSetContentData(cinfo, NULL, false), out); + // == wrapper of: require(SECSuccess == SecCmsContentInfoSetContent(cinfo, SEC_OID_PKCS7_DATA, NULL), out); + + if (CFGetTypeID(recipient_or_cfarray_thereof) == CFArrayGetTypeID()) { + CFIndex dex, numCerts = CFArrayGetCount(recipient_or_cfarray_thereof); + for(dex=0; dexrecipientInfos; + while (!used_recipient && *rinfo) { + used_recipient = (*rinfo)->cert; + rinfo++; + } + require_quiet(2 == SecCmsMessageContentLevelCount(cmsg), out); + require_quiet(cinfo = SecCmsMessageContentLevel(cmsg, 1), out); + require_quiet(SecCmsContentInfoGetContentTypeTag(cinfo) == SEC_OID_PKCS7_DATA, out); + const SecAsn1Item *content = SecCmsMessageGetContent(cmsg); + if (content) + CFDataAppendBytes(data, content->Data, content->Length); + if (recipient) { + CFRetainSafe(used_recipient); + *recipient = used_recipient; + } + status = errSecSuccess; +out: + if (cmsg) SecCmsMessageDestroy(cmsg); + return status; +} + +static SecCmsAttribute * +make_attr(PLArenaPool *poolp, SecAsn1Item *type, SecAsn1Item *value, bool encoded) +{ + SecAsn1Item * copiedvalue; + SecCmsAttribute *attr = (SecCmsAttribute *)PORT_ArenaZAlloc(poolp, sizeof(SecCmsAttribute)); + if (attr == NULL) + goto loser; + + if (SECITEM_CopyItem(poolp, &(attr->type), type) != SECSuccess) + goto loser; + + if (value != NULL) { + if ((copiedvalue = SECITEM_AllocItem(poolp, NULL, value->Length)) == NULL) + goto loser; + + if (SECITEM_CopyItem(poolp, copiedvalue, value) != SECSuccess) + goto loser; + + SecCmsArrayAdd(poolp, (void ***)&(attr->values), (void *)copiedvalue); + } + + attr->encoded = encoded; + +loser: + return attr; +} + +static void +signerinfo_add_auth_attr(SecCmsSignerInfoRef signerinfo, /*SECOidTag oidtag*/ + SecAsn1Item *oid, SecAsn1Item *value, bool encoded) +{ + PLArenaPool *poolp = signerinfo->signedData->contentInfo.cmsg->poolp; + PORT_Assert (poolp != NULL); + void *mark = PORT_ArenaMark (poolp); + + SecCmsAttribute *attr = make_attr(poolp, oid, value, encoded); + if (!attr || SecCmsAttributeArrayAddAttr(poolp, &(signerinfo->authAttr), attr) != SECSuccess) + goto loser; + + PORT_ArenaUnmark (poolp, mark); + return; + +loser: + PORT_Assert (mark != NULL); + PORT_ArenaRelease (poolp, mark); + return; +} + +static void sign_all_attributes(const void *key, const void *value, void *context) +{ + SecAsn1Item oid = { CFDataGetLength(key), (uint8_t*)CFDataGetBytePtr(key) }, + oid_value = { CFDataGetLength(value), (uint8_t*)CFDataGetBytePtr(value) }; + + signerinfo_add_auth_attr((SecCmsSignerInfoRef)context, &oid, &oid_value, true); +} + +#if 0 +static void enveloped_data_add_unprotected_attr(SecCmsEnvelopedDataRef envd, + SecAsn1Item *oid, SecAsn1Item *value, bool encoded) +{ + PLArenaPool *poolp = envd->contentInfo.cmsg->poolp; + PORT_Assert (poolp != NULL); + void *mark = PORT_ArenaMark (poolp); + SecCmsAttribute *attr = make_attr(poolp, oid, value, encoded); + + if (!attr || SecCmsAttributeArrayAddAttr( + poolp, + &(envd->unprotectedAttr), attr) != SECSuccess) + goto loser; + + PORT_ArenaUnmark (poolp, mark); + return; + +loser: + PORT_Assert (mark != NULL); + PORT_ArenaRelease (poolp, mark); + return; + +} +#endif + +static OSStatus SecCMSSignDataOrDigestAndAttributes(SecIdentityRef identity, + CFDataRef data, bool detached, bool data_is_digest, SECOidTag sign_algorithm, + CFMutableDataRef signed_data, CFDictionaryRef signed_attributes, SecCmsCertChainMode chainMode, CFArrayRef additional_certs) +{ + SecCmsMessageRef cmsg = NULL; + SecCmsContentInfoRef cinfo; + SecCmsSignedDataRef sigd = NULL; + SecCmsSignerInfoRef signerinfo; + OSStatus status = errSecParam; + + require(!data_is_digest || detached /* if digest, must be detached */, out); + + require(cmsg = SecCmsMessageCreate(), out); + require(sigd = SecCmsSignedDataCreate(cmsg), out); + require(cinfo = SecCmsMessageGetContentInfo(cmsg), out); + require_noerr(SecCmsContentInfoSetContentSignedData(cinfo, sigd), out); + require(cinfo = SecCmsSignedDataGetContentInfo(sigd), out); + require_noerr(SecCmsContentInfoSetContentData(cinfo, NULL, detached), out); + require(signerinfo = SecCmsSignerInfoCreate(sigd, identity, sign_algorithm), out); + if (additional_certs) + require_noerr(SecCmsSignedDataAddCertList(sigd, additional_certs), out); + require_noerr(SecCmsSignerInfoIncludeCerts(signerinfo, chainMode, certUsageAnyCA), out); + require_noerr(SecCmsSignerInfoAddSigningTime(signerinfo, CFAbsoluteTimeGetCurrent()), out); + + if (signed_attributes) + CFDictionaryApplyFunction(signed_attributes, sign_all_attributes, signerinfo); + + SecAsn1Item input = {}; + if (data) { + input.Length = CFDataGetLength(data); + input.Data = (uint8_t*)CFDataGetBytePtr(data); + } + if (data_is_digest) { + require_noerr(SecCmsSignedDataSetDigestValue(sigd, sign_algorithm, &input), out); + require_noerr(SecCmsMessageEncode(cmsg, NULL, signed_data), out); + } + else + require_noerr(SecCmsMessageEncode(cmsg, (data && input.Length) ? &input : NULL, signed_data), out); + + status = errSecSuccess; +out: + if (cmsg) SecCmsMessageDestroy(cmsg); + return status; +} + +OSStatus SecCMSSignDataAndAttributes(SecIdentityRef identity, CFDataRef data, bool detached, + CFMutableDataRef signed_data, CFDictionaryRef signed_attributes) +{ + return SecCMSSignDataOrDigestAndAttributes(identity, data, detached, false, SEC_OID_SHA1, + signed_data, signed_attributes, SecCmsCMCertChain, NULL); +} + +OSStatus SecCMSSignDigestAndAttributes(SecIdentityRef identity, CFDataRef digest, + CFMutableDataRef signed_data, CFDictionaryRef signed_attributes) +{ + return SecCMSSignDataOrDigestAndAttributes(identity, digest, true, true, SEC_OID_SHA1, + signed_data, signed_attributes, SecCmsCMCertChain, NULL); +} + + +OSStatus SecCMSCreateSignedData(SecIdentityRef identity, CFDataRef data, + CFDictionaryRef parameters, CFDictionaryRef signed_attributes, + CFMutableDataRef signed_data) +{ + bool is_digest = false, is_detached = false; + CFStringRef algorithm_name = NULL; + SecCmsCertChainMode chain_mode = SecCmsCMCertChain; + CFArrayRef additional_certs = NULL; + + if (parameters) { + is_digest = CFDictionaryGetValueIfPresent(parameters, + kSecCMSSignDigest, NULL); + is_detached = CFDictionaryGetValueIfPresent(parameters, + kSecCMSSignDetached, NULL); + algorithm_name = CFDictionaryGetValue(parameters, + kSecCMSSignHashAlgorithm); + + CFTypeRef chain_mode_param = CFDictionaryGetValue(parameters, kSecCMSCertChainMode); + if (chain_mode_param && (CFGetTypeID(chain_mode_param) == CFStringGetTypeID())) + chain_mode = CFStringGetIntValue(chain_mode_param); + + CFTypeRef additional_certs_param = CFDictionaryGetValue(parameters, kSecCMSAdditionalCerts); + if (additional_certs_param && (CFGetTypeID(additional_certs_param) == CFArrayGetTypeID())) + additional_certs = (CFArrayRef)additional_certs_param; + } + + SECOidTag algorithm = SEC_OID_SHA1; + if (algorithm_name) { + if (CFEqual(kSecCMSHashingAlgorithmMD5, algorithm_name)) { + algorithm = SEC_OID_MD5; + } else { + algorithm = SEC_OID_UNKNOWN; + } + + } + + return SecCMSSignDataOrDigestAndAttributes(identity, data, + is_detached, is_digest, algorithm, + signed_data, signed_attributes, chain_mode, additional_certs); +} + + +static CFMutableArrayRef copy_signed_attribute_values(SecCmsAttribute *attr) +{ + CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + SecAsn1Item **item = attr->values; + if (item) while (*item) { + CFDataRef asn1data = CFDataCreate(kCFAllocatorDefault, (*item)->Data, (*item)->Length); + if (asn1data) { + CFArrayAppendValue(array, asn1data); + CFRelease(asn1data); + } + item++; + } + return array; +} + +static OSStatus SecCMSVerifySignedData_internal(CFDataRef message, CFDataRef detached_contents, + CFTypeRef policy, SecTrustRef *trustref, CFArrayRef additional_certs, + CFDataRef *attached_contents, CFDictionaryRef *signed_attributes) +{ + SecCmsMessageRef cmsg = NULL; + SecCmsContentInfoRef cinfo; + SecCmsSignedDataRef sigd = NULL; + OSStatus status = errSecParam; + + SecAsn1Item encoded_message = { CFDataGetLength(message), (uint8_t*)CFDataGetBytePtr(message) }; + require_noerr_action_quiet(SecCmsMessageDecode(&encoded_message, NULL, NULL, NULL, NULL, NULL, NULL, &cmsg), + out, status = errSecDecode); + /* expected to be a signed data message at the top level */ + require_quiet(cinfo = SecCmsMessageContentLevel(cmsg, 0), out); + require_quiet(SecCmsContentInfoGetContentTypeTag(cinfo) == SEC_OID_PKCS7_SIGNED_DATA, out); + require_quiet(sigd = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(cinfo), out); + + if (detached_contents) + { + require_quiet(!SecCmsSignedDataHasDigests(sigd), out); + SECAlgorithmID **digestalgs = SecCmsSignedDataGetDigestAlgs(sigd); + SecCmsDigestContextRef digcx = SecCmsDigestContextStartMultiple(digestalgs); + SecCmsDigestContextUpdate(digcx, CFDataGetBytePtr(detached_contents), CFDataGetLength(detached_contents)); + SecCmsSignedDataSetDigestContext(sigd, digcx); + SecCmsDigestContextDestroy(digcx); + } + + if (additional_certs) + require_noerr_quiet(SecCmsSignedDataAddCertList(sigd, additional_certs), out); + + if (policy) { /* if no policy is given skip verification */ + /* find out about signers */ + int nsigners = SecCmsSignedDataSignerInfoCount(sigd); + require_quiet(nsigners == 1, out); + require_noerr_action_quiet(SecCmsSignedDataVerifySignerInfo(sigd, 0, NULL, policy, trustref), + out, status = errSecAuthFailed); + } + + #if 0 + if (nsigners > 1) + trustrefs = CFArrayCreateMutable(kCFAllocatorDefault, nsigners, &kCFTypeArrayCallBacks); + + int j; + for (j = 0; j < nsigners; j++) + { + SecTrustRef trustRef; + require_noerr_action_quiet(SecCmsSignedDataVerifySignerInfo(sigd, j, NULL, policy, &trustRef), + out, status = errSecAuthFailed); + if ((j == 0) && (nsigners == 1)) + *trustref_or_cfarray_thereof = trustRef; + else { + CFArrayAppendValue(trustrefs, trustRef); + CFRelease(trustRef); + } + } + *trustref_or_cfarray_thereof = trustrefs; + trustrefs = NULL; +#endif + + status = errSecSuccess; + + if (attached_contents) { + const SecAsn1Item *content = SecCmsMessageGetContent(cmsg); + if (content) + *attached_contents = CFDataCreate(kCFAllocatorDefault, content->Data, content->Length); + else + *attached_contents = NULL; + } + + if (signed_attributes) { + CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, + 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + require_quiet(attrs, out); + SecCmsAttribute **signed_attrs = sigd->signerInfos[0]->authAttr; + if (signed_attrs) while (*signed_attrs) { + CFDataRef type = CFDataCreate(kCFAllocatorDefault, (*signed_attrs)->type.Data, (*signed_attrs)->type.Length); + if (type) { + CFMutableArrayRef attr = copy_signed_attribute_values(*signed_attrs); + if (attr) { + CFMutableArrayRef existing_attrs = (CFMutableArrayRef)CFDictionaryGetValue(attrs, type); + if (existing_attrs) { + CFIndex count = CFArrayGetCount(attr); + if (count) + CFArrayAppendArray(existing_attrs, attr, CFRangeMake(0, count)); + } else + CFDictionarySetValue(attrs, type, attr); + CFRelease(attr); + } + CFRelease(type); + } + signed_attrs++; + } + CFMutableArrayRef certs = NULL; + + SecAsn1Item **cert_datas = SecCmsSignedDataGetCertificateList(sigd); + certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + SecAsn1Item *cert_data; + if (cert_datas) while ((cert_data = *cert_datas) != NULL) { + SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, cert_data->Data, cert_data->Length); + if (cert) { + CFArrayAppendValue(certs, cert); + CFRelease(cert); + } + cert_datas++; + } + + CFDictionaryAddValue(attrs, kSecCMSAllCerts, certs); + + /* Add "cooked" values separately */ + CFAbsoluteTime signing_time; + if (errSecSuccess == SecCmsSignerInfoGetSigningTime(sigd->signerInfos[0], &signing_time)) { + CFDateRef signing_date = CFDateCreate(kCFAllocatorDefault, signing_time); + if (signing_date){ + CFDictionarySetValue(attrs, kSecCMSSignDate, signing_date); + CFReleaseSafe(signing_date); + } + } + + *signed_attributes = attrs; + CFReleaseSafe(certs); + } + + +out: + if (cmsg) SecCmsMessageDestroy(cmsg); + return status; +} + +OSStatus SecCMSVerifyCopyDataAndAttributes(CFDataRef message, CFDataRef detached_contents, + CFTypeRef policy, SecTrustRef *trustref, + CFDataRef *attached_contents, CFDictionaryRef *signed_attributes) +{ + OSStatus status = SecCMSVerifySignedData_internal(message, detached_contents, policy, trustref, NULL, attached_contents, signed_attributes); + + return status; +} + +OSStatus SecCMSVerifySignedData(CFDataRef message, CFDataRef detached_contents, + CFTypeRef policy, SecTrustRef *trustref, CFArrayRef additional_certificates, + CFDataRef *attached_contents, CFDictionaryRef *message_attributes) +{ + CFDictionaryRef signed_attributes = NULL; + OSStatus status = SecCMSVerifySignedData_internal(message, detached_contents, policy, trustref, additional_certificates, attached_contents, &signed_attributes); + if (!status && signed_attributes && message_attributes) { + *message_attributes = CFDictionaryCreate(kCFAllocatorDefault, &kSecCMSSignedAttributes, (const void **)&signed_attributes, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + } + CFReleaseSafe(signed_attributes); + + return status; +} + +OSStatus SecCMSVerify(CFDataRef message, CFDataRef detached_contents, + CFTypeRef policy, SecTrustRef *trustref, + CFDataRef *attached_contents) { + return SecCMSVerifySignedData_internal(message, detached_contents, policy, trustref, NULL, attached_contents, NULL); +} + +CFArrayRef SecCMSCertificatesOnlyMessageCopyCertificates(CFDataRef message) { + SecCmsMessageRef cmsg = NULL; + SecCmsContentInfoRef cinfo; + SecCmsSignedDataRef sigd = NULL; + CFMutableArrayRef certs = NULL; + + SecAsn1Item encoded_message = { CFDataGetLength(message), (uint8_t*)CFDataGetBytePtr(message) }; + require_noerr_quiet(SecCmsMessageDecode(&encoded_message, NULL, NULL, NULL, NULL, NULL, NULL, &cmsg), out); + /* expected to be a signed data message at the top level */ + require(cinfo = SecCmsMessageContentLevel(cmsg, 0), out); + require(SecCmsContentInfoGetContentTypeTag(cinfo) == SEC_OID_PKCS7_SIGNED_DATA, out); + require(sigd = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(cinfo), out); + + /* find out about signers */ + int nsigners = SecCmsSignedDataSignerInfoCount(sigd); + require(nsigners == 0, out); + + SecAsn1Item **cert_datas = SecCmsSignedDataGetCertificateList(sigd); + certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + SecAsn1Item *cert_data; + if (cert_datas) while ((cert_data = *cert_datas) != NULL) { + SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, cert_data->Data, cert_data->Length); + if (cert) { + CFArrayAppendValue(certs, cert); + CFRelease(cert); + } + cert_datas++; + } + +out: + if (cmsg) + SecCmsMessageDestroy(cmsg); + + return certs; +} + + +extern const SecAsn1Template SecCmsMessageTemplate[]; + +CFDataRef SecCMSCreateCertificatesOnlyMessage(CFTypeRef cert_or_array_thereof) { + OSStatus status = errSecParam; + SecCmsMessageRef cmsg = NULL; + SecCmsContentInfoRef cinfo; + SecCmsSignedDataRef sigd = NULL; + CFMutableDataRef cert_only_signed_data = NULL; + CFArrayRef cert_array = NULL; + CFIndex cert_array_count = 0; + SecCertificateRef cert = NULL; + + require(cert_or_array_thereof, out); + + require(cmsg = SecCmsMessageCreate(), out); + require(sigd = SecCmsSignedDataCreate(cmsg), out); + require_noerr(SecCmsContentInfoSetContentData(&(sigd->contentInfo), NULL, PR_TRUE), out); + require(cinfo = SecCmsMessageGetContentInfo(cmsg), out); + require_noerr(SecCmsContentInfoSetContentSignedData(cinfo, sigd), out); + long version = SEC_CMS_SIGNED_DATA_VERSION_BASIC; + require(SEC_ASN1EncodeInteger(cmsg->poolp, &(sigd->version), version), out); + + if (CFGetTypeID(cert_or_array_thereof) == SecCertificateGetTypeID()) { + cert_array = CFArrayCreate(kCFAllocatorDefault, &cert_or_array_thereof, 1, &kCFTypeArrayCallBacks); + } else if (CFGetTypeID(cert_or_array_thereof) == CFArrayGetTypeID()) { + cert_array = CFArrayCreateCopy(kCFAllocatorDefault, (CFArrayRef)cert_or_array_thereof); + } + + require(cert_array, out); + cert_array_count = CFArrayGetCount(cert_array); + require(cert_array_count > 0, out); + + sigd->rawCerts = (SecAsn1Item * *)PORT_ArenaAlloc(cmsg->poolp, (cert_array_count + 1) * sizeof(SecAsn1Item *)); + require(sigd->rawCerts, out); + CFIndex ix; + for (ix = 0; ix < cert_array_count; ix++) { + cert = (SecCertificateRef)CFArrayGetValueAtIndex(cert_array, ix); + require(cert, out); + + sigd->rawCerts[ix] = PORT_ArenaZAlloc(cmsg->poolp, sizeof(SecAsn1Item)); + SecAsn1Item cert_data = { SecCertificateGetLength(cert), + (uint8_t *)SecCertificateGetBytePtr(cert) }; + *(sigd->rawCerts[ix]) = cert_data; + } + sigd->rawCerts[ix] = NULL; + + /* this is a SET OF, so we need to sort them guys - we have the DER already, though */ + if (cert_array_count > 1) + SecCmsArraySort((void **)sigd->rawCerts, SecCmsUtilDERCompare, NULL, NULL); + + cert_only_signed_data = CFDataCreateMutable(kCFAllocatorDefault, 0); + SecAsn1Item cert_only_signed_data_item = {}; + require_quiet(SEC_ASN1EncodeItem(cmsg->poolp, &cert_only_signed_data_item, + cmsg, SecCmsMessageTemplate), out); + CFDataAppendBytes(cert_only_signed_data, cert_only_signed_data_item.Data, + cert_only_signed_data_item.Length); + + status = errSecSuccess; +out: + CFReleaseSafe(cert_array); + if (status) CFReleaseSafe(cert_only_signed_data); + if (cmsg) SecCmsMessageDestroy(cmsg); + return cert_only_signed_data; +} + +CFDataRef SecCMSCreateCertificatesOnlyMessageIAP(SecCertificateRef cert) +{ + static const uint8_t header[] = { + 0x30, 0x82, 0x03, 0x6d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, + 0x82, 0x03, 0x5e, 0x30, 0x82, 0x03, 0x5a, 0x02, + 0x01, 0x01, 0x31, 0x00, 0x30, 0x0b, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, + 0x01, 0xa0, 0x82, 0x03, 0x40 + }; + + static const uint8_t trailer[] = { + 0xa1, 0x00, 0x31, 0x00 + }; + + CFMutableDataRef message = NULL; + CFDataRef certdata; + const uint8_t *certbytes; + CFIndex certlen; + uint8_t *messagebytes; + uint16_t messagelen; + + certdata = SecCertificateCopyData(cert); + require(certdata, out); + + certbytes = CFDataGetBytePtr(certdata); + certlen = CFDataGetLength(certdata); + require(certlen > UINT8_MAX, out); + require(certlen < UINT16_MAX, out); + + message = CFDataCreateMutable(kCFAllocatorDefault, 0); + require(message, out); + + CFDataAppendBytes(message, header, sizeof(header)); + CFDataAppendBytes(message, certbytes, certlen); + CFDataAppendBytes(message, trailer, sizeof(trailer)); + + messagebytes = CFDataGetMutableBytePtr(message); + messagelen = CFDataGetLength(message); + + messagelen -= 4; + messagebytes[2] = messagelen >> 8; + messagebytes[3] = messagelen & 0xFF; + + messagelen -= 15; + messagebytes[17] = messagelen >> 8; + messagebytes[18] = messagelen & 0xFF; + + messagelen -= 4; + messagebytes[21] = messagelen >> 8; + messagebytes[22] = messagelen & 0xFF; + + messagelen -= 26; + messagebytes[43] = messagelen >> 8; + messagebytes[44] = messagelen & 0xFF; + +out: + CFReleaseSafe(certdata); + return message; +} + +#endif /* ENABLE_CMS */ + diff --git a/Security/sec/Security/SecCMS.h b/Security/sec/Security/SecCMS.h new file mode 100644 index 00000000..780fca54 --- /dev/null +++ b/Security/sec/Security/SecCMS.h @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2008-2010,2012-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@ + */ + +/*! + @header SecCMS +*/ + +#include +#include +#include +#include + +#ifndef _SECURITY_SECCMS_H_ +#define _SECURITY_SECCMS_H_ + +__BEGIN_DECLS + +extern const void * kSecCMSBulkEncryptionAlgorithm; +extern const void * kSecCMSSignDigest; +extern const void * kSecCMSSignDetached; +extern const void * kSecCMSSignHashAlgorithm; +extern const void * kSecCMSCertChainMode; +extern const void * kSecCMSAdditionalCerts; +extern const void * kSecCMSSignedAttributes; +extern const void * kSecCMSSignDate; +extern const void * kSecCMSAllCerts; + +extern const void * kSecCMSEncryptionAlgorithmDESCBC; +extern const void * kSecCMSEncryptionAlgorithmAESCBC; +extern const void * kSecCMSHashingAlgorithmMD5; +extern const void * kSecCMSCertChainModeNone; + +/*! + @function SecCMSVerifyCopyDataAndAttributes + @abstract verify a signed data cms blob. + @param message the cms message to be parsed + @param detached_contents to pass detached contents (optional) + @param policy specifies policy or array thereof should be used (optional). + if none is passed the blob will **not** be verified and only + the attached contents will be returned. + @param trustref (output/optional) if specified, the trust chain built during + verification will not be evaluated but returned to the caller to do so. + @param attached_contents (output/optional) return a copy of the attached + contents. + @param signed_attributes (output/optional) return a copy of the signed + attributes as a CFDictionary from oids (CFData) to values + (CFArray of CFData). + @result A result code. See "Security Error Codes" (SecBase.h). + errSecDecode not a CMS message we can parse, + errSecAuthFailed bad signature, or untrusted signer if caller doesn't + ask for trustref, + errSecParam garbage in, garbage out. +*/ +OSStatus SecCMSVerifyCopyDataAndAttributes(CFDataRef message, CFDataRef detached_contents, + CFTypeRef policy, SecTrustRef *trustref, + CFDataRef *attached_contents, CFDictionaryRef *signed_attributes); + +/*! + @function SecCMSVerify + @abstract same as SecCMSVerifyCopyDataAndAttributes, for binary compatibility. +*/ +OSStatus SecCMSVerify(CFDataRef message, CFDataRef detached_contents, + CFTypeRef policy, SecTrustRef *trustref, CFDataRef *attached_contents); + + +/* Return an array of certificates contained in message, if message is of the + type SignedData and has no signers, return NULL otherwise. Not that if + the message is properly formed but has no certificates an empty array will + be returned. */ +CFArrayRef SecCMSCertificatesOnlyMessageCopyCertificates(CFDataRef message); + +/* Create a degenerate PKCS#7 containing a cert or a CFArray of certs. */ +CFDataRef SecCMSCreateCertificatesOnlyMessage(CFTypeRef cert_or_array_thereof); +CFDataRef SecCMSCreateCertificatesOnlyMessageIAP(SecCertificateRef cert); + +/*! + @function SecCMSSignDataAndAttributes + @abstract create a signed data cms blob. + @param identity signer + @param data message to be signed + @param detached sign detached or not + @param signed_data (output) return signed message. + @param signed_attributes (input/optional) signed attributes to insert + as a CFDictionary from oids (CFData) to value (CFData). + @result A result code. See "Security Error Codes" (SecBase.h). + errSecParam garbage in, garbage out. +*/ +OSStatus SecCMSSignDataAndAttributes(SecIdentityRef identity, CFDataRef data, + bool detached, CFMutableDataRef signed_data, CFDictionaryRef signed_attributes); + +/*! + @function SecCMSSignDigestAndAttributes + @abstract create a detached signed data cms blob for a SHA-1 hash. + @param identity signer + @param digest SHA-1 digest of message to be signed + @param signed_data (output) return signed message. + @param signed_attributes (input/optional) signed attributes to insert + as a CFDictionary from oids (CFData) to value (CFData). + @result A result code. See "Security Error Codes" (SecBase.h). + errSecParam garbage in, garbage out. +*/ +OSStatus SecCMSSignDigestAndAttributes(SecIdentityRef identity, CFDataRef digest, + CFMutableDataRef signed_data, CFDictionaryRef signed_attributes); + +/*! + @function SecCMSCreateSignedData + @abstract create a signed data cms blob. + @param identity signer + @param data SHA-1 digest or message to be signed + @param parameters (input/optional) specify algorithm, detached, digest + @param signed_attributes (input/optional) signed attributes to insert + as a CFDictionary from oids (CFData) to value (CFData). + @param signed_data (output) return signed message. + @result A result code. See "Security Error Codes" (SecBase.h). + errSecParam garbage in, garbage out. +*/ +OSStatus SecCMSCreateSignedData(SecIdentityRef identity, CFDataRef data, + CFDictionaryRef parameters, CFDictionaryRef signed_attributes, + CFMutableDataRef signed_data); + +/*! + @function SecCMSCreateEnvelopedData + @abstract create a enveloped cms blob for recipients + @param recipients SecCertificateRef for each recipient + @param params CFDictionaryRef with encryption parameters + @param data Data to be encrypted + @param enveloped_data (output) return enveloped message. + @result A result code. See "Security Error Codes" (SecBase.h). + errSecParam garbage in, garbage out. +*/ +OSStatus SecCMSCreateEnvelopedData(CFTypeRef recipient_or_cfarray_thereof, + CFDictionaryRef params, CFDataRef data, CFMutableDataRef enveloped_data); + + +/*! + @function SecCMSDecryptEnvelopedData + @abstract open an enveloped cms blob. expects recipients identity in keychain. + @param message Eveloped message + @param data (output) return decrypted message. + @param recipient (output/optional) return addressed recipient + @result A result code. See "Security Error Codes" (SecBase.h). + errSecParam garbage in, garbage out. +*/ +OSStatus SecCMSDecryptEnvelopedData(CFDataRef message, + CFMutableDataRef data, SecCertificateRef *recipient); + +OSStatus SecCMSVerifySignedData(CFDataRef message, CFDataRef detached_contents, + CFTypeRef policy, SecTrustRef *trustref, CFArrayRef additional_certificates, + CFDataRef *attached_contents, CFDictionaryRef *message_attributes); + +__END_DECLS + +#endif /* !_SECURITY_SECCMS_H_ */ diff --git a/sec/Security/SecCertificate.c b/Security/sec/Security/SecCertificate.c similarity index 98% rename from sec/Security/SecCertificate.c rename to Security/sec/Security/SecCertificate.c index 6067db94..058ba35f 100644 --- a/sec/Security/SecCertificate.c +++ b/Security/sec/Security/SecCertificate.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include @@ -67,7 +66,7 @@ #include #include "SecBase64.h" #include "AppleBaselineEscrowCertificates.h" -#include "securityd_client.h" +#include typedef struct SecCertificateExtension { DERItem extnID; @@ -198,6 +197,7 @@ struct __SecCertificate { #define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); SEC_CONST_DECL (kSecCertificateProductionEscrowKey, "ProductionEscrowKey"); +SEC_CONST_DECL (kSecCertificateProductionPCSEscrowKey, "ProductionPCSEscrowKey"); SEC_CONST_DECL (kSecCertificateEscrowFileName, "AppleESCertificates"); /* Public Constants for property list keys. */ @@ -221,19 +221,15 @@ SEC_CONST_DECL (kSecPropertyTypeDate, "date"); typedef void (*SecCertificateExtensionParser)(SecCertificateRef certificate, const SecCertificateExtension *extn); -/* CFRuntime registration data. */ -static pthread_once_t kSecCertificateRegisterClass = PTHREAD_ONCE_INIT; -static CFTypeID kSecCertificateTypeID = _kCFRuntimeNotATypeID; - /* Mapping from extension OIDs (as a DERItem *) to SecCertificateExtensionParser extension parsing routines. */ -static CFDictionaryRef gExtensionParsers; +static CFDictionaryRef sExtensionParsers; /* Forward declarations of static functions. */ static CFStringRef SecCertificateDescribe(CFTypeRef cf); static void SecCertificateDestroy(CFTypeRef cf); static bool derDateGetAbsoluteTime(const DERItem *dateChoice, - CFAbsoluteTime *absTime); + CFAbsoluteTime *absTime) __attribute__((__nonnull__)); /* Static functions. */ static CF_RETURNS_RETAINED CFStringRef SecCertificateDescribe(CFTypeRef cf) { @@ -736,7 +732,7 @@ static void SecCEPCertificatePolicies(SecCertificateRef certificate, } require_quiet(drtn == DR_EndOfSequence, badDER); policies = (SecCEPolicyInformation *)malloc(sizeof(SecCEPolicyInformation) - * policy_count); + * (policy_count > 0 ? policy_count : 1)); DERDecodeSeqInit(&extn->extnValue, &tag, &piSeq); DERSize policy_ix = 0; while ((drtn = DERDecodeSeqNext(&piSeq, &piContent)) == DR_Success) { @@ -818,13 +814,14 @@ static void SecCEPPolicyMappings(SecCertificateRef certificate, DERTag tag; DERSequence pmSeq; CFMutableDictionaryRef mappings = NULL; + CFDataRef idp = NULL, sdp = NULL; DERReturn drtn = DERDecodeSeqInit(&extn->extnValue, &tag, &pmSeq); require_noerr_quiet(drtn, badDER); require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); DERDecodedInfo pmContent; require_quiet(mappings = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), - badDER);; + badDER); while ((drtn = DERDecodeSeqNext(&pmSeq, &pmContent)) == DR_Success) { require_quiet(pmContent.tag == ASN1_CONSTR_SEQUENCE, badDER); DERPolicyMapping pm; @@ -833,7 +830,6 @@ static void SecCEPPolicyMappings(SecCertificateRef certificate, DERPolicyMappingItemSpecs, &pm, sizeof(pm)); require_noerr_quiet(drtn, badDER); - CFDataRef idp, sdp; require_quiet(idp = CFDataCreate(kCFAllocatorDefault, pm.issuerDomainPolicy.data, pm.issuerDomainPolicy.length), badDER); require_quiet(sdp = CFDataCreate(kCFAllocatorDefault, @@ -848,11 +844,15 @@ static void SecCEPPolicyMappings(SecCertificateRef certificate, CFDictionarySetValue(mappings, idp, sdps); CFRelease(sdps); } + CFReleaseNull(idp); + CFReleaseNull(sdp); } require_quiet(drtn == DR_EndOfSequence, badDER); certificate->_policyMappings = mappings; return; badDER: + CFReleaseSafe(idp); + CFReleaseSafe(sdp); CFReleaseSafe(mappings); certificate->_policyMappings = NULL; secwarning("Invalid CertificatePolicies Extension"); @@ -1117,23 +1117,9 @@ static const CFDictionaryKeyCallBacks SecDERItemKeyCallBacks = { SecDERItemHash /* hash */ }; -static void SecCertificateRegisterClass(void) { - static const CFRuntimeClass kSecCertificateClass = { - 0, /* version */ - "SecCertificate", /* class name */ - NULL, /* init */ - NULL, /* copy */ - SecCertificateDestroy, /* dealloc */ - SecCertificateEqual, /* equal */ - SecCertificateHash, /* hash */ - NULL, /* copyFormattingDesc */ - SecCertificateDescribe /* copyDebugDesc */ - }; - - kSecCertificateTypeID = _CFRuntimeRegisterClass(&kSecCertificateClass); - +static void SecCertificateInitializeExtensionParsers(void) { /* Build a dictionary that maps from extension OIDs to callback functions - which can parse the extension of the type given. */ + which can parse the extension of the type given. */ static const void *extnOIDs[] = { &oidSubjectKeyIdentifier, &oidKeyUsage, @@ -1174,11 +1160,15 @@ static void SecCertificateRegisterClass(void) { SecCEPEntrustVersInfo, SecCEPEscrowMarker, }; - gExtensionParsers = CFDictionaryCreate(kCFAllocatorDefault, extnOIDs, - extnParsers, array_size(extnOIDs), - &SecDERItemKeyCallBacks, NULL); + sExtensionParsers = CFDictionaryCreate(kCFAllocatorDefault, extnOIDs, + extnParsers, array_size(extnOIDs), + &SecDERItemKeyCallBacks, NULL); } +CFGiblisWithFunctions(SecCertificate, NULL, NULL, SecCertificateDestroy, SecCertificateEqual, SecCertificateHash, NULL, SecCertificateDescribe, NULL, NULL, ^{ + SecCertificateInitializeExtensionParsers(); +}) + /* Given the contents of an X.501 Name return the contents of a normalized X.501 name. */ CFDataRef createNormalizedX501Name(CFAllocatorRef allocator, @@ -1210,6 +1200,8 @@ CFDataRef createNormalizedX501Name(CFAllocatorRef allocator, DERSequence atvSeq; drtn = DERDecodeSeqContentInit(&rdn.content, &atvSeq); + require_quiet(drtn == DR_Success, badDER); + DERDecodedInfo atv; /* Always points to tag of current atv sequence. */ const DERByte *atvTag = atvSeq.nextItem; @@ -1303,6 +1295,7 @@ CFDataRef createNormalizedX501Name(CFAllocatorRef allocator, DERSize newValueTLLength = valueTLLength - 1; drtn = DEREncodeLength(valueContentLength, base + valueTagLocation + 1, &newValueTLLength); + require(drtn == DR_Success, badDER); /* Add the length of the tag back in. */ newValueTLLength++; CFIndex valueLLDiff = valueTLLength - newValueTLLength; @@ -1321,6 +1314,7 @@ CFDataRef createNormalizedX501Name(CFAllocatorRef allocator, DERSize newATVTLLength = atvTLLength - 1; drtn = DEREncodeLength(atvContentLength, base + atvTagLocation + 1, &newATVTLLength); + require(drtn == DR_Success, badDER); /* Add the length of the tag back in. */ newATVTLLength++; CFIndex atvLLDiff = atvTLLength - newATVTLLength; @@ -1340,6 +1334,7 @@ CFDataRef createNormalizedX501Name(CFAllocatorRef allocator, DERSize newRDNTLLength = rdnTLLength - 1; drtn = DEREncodeLength(rdnContentLength, base + rdnTagLocation + 1, &newRDNTLLength); + require_quiet(drtn == DR_Success, badDER); /* Add the length of the tag back in. */ newRDNTLLength++; CFIndex rdnLLDiff = rdnTLLength - newRDNTLLength; @@ -1357,6 +1352,7 @@ CFDataRef createNormalizedX501Name(CFAllocatorRef allocator, this slide. */ atvTagLocation -= rdnLLDiff; } + (void) lengthDiff; // No next object, silence analyzer } } atvTagLocation += atvTLLength + atvContentLength; @@ -1554,7 +1550,7 @@ static bool SecCertificateParse(SecCertificateRef certificate) require_quiet(extensionCount < 10000, badCert); certificate->_extensionCount = extensionCount; certificate->_extensions = - malloc(sizeof(SecCertificateExtension) * extensionCount); + malloc(sizeof(SecCertificateExtension) * (extensionCount > 0 ? extensionCount : 1)); CFIndex ix = 0; drtn = DERDecodeSeqInit(&tbsCert.extensions, &tag, &derSeq); @@ -1577,7 +1573,7 @@ static bool SecCertificateParse(SecCertificateRef certificate) SecCertificateExtensionParser parser = (SecCertificateExtensionParser)CFDictionaryGetValue( - gExtensionParsers, &certificate->_extensions[ix].extnID); + sExtensionParsers, &certificate->_extensions[ix].extnID); if (parser) { /* Invoke the parser. */ parser(certificate, &certificate->_extensions[ix]); @@ -1599,15 +1595,11 @@ badCert: /* Public API functions. */ -CFTypeID SecCertificateGetTypeID(void) { - pthread_once(&kSecCertificateRegisterClass, SecCertificateRegisterClass); - return kSecCertificateTypeID; -} - SecCertificateRef SecCertificateCreateWithBytes(CFAllocatorRef allocator, const UInt8 *der_bytes, CFIndex der_length) { - check(der_bytes); - check(der_length); + if (der_bytes == NULL) return NULL; + if (der_length == 0) return NULL; + CFIndex size = sizeof(struct __SecCertificate) + der_length; SecCertificateRef result = (SecCertificateRef)_CFRuntimeCreateInstance( allocator, SecCertificateGetTypeID(), size - sizeof(CFRuntimeBase), 0); @@ -1877,7 +1869,8 @@ static inline int parseDecimalPair(const DERByte **p) { absTime. Return false otherwise. */ CFAbsoluteTime SecAbsoluteTimeFromDateContent(DERTag tag, const uint8_t *bytes, size_t length) { - check(bytes); + if (bytes == NULL) + return NULL_TIME; if (length == 0) return NULL_TIME; @@ -1996,8 +1989,8 @@ CFAbsoluteTime SecAbsoluteTimeFromDateContent(DERTag tag, const uint8_t *bytes, return absTime - timeZoneOffset; } -static bool derDateContentGetAbsoluteTime(DERTag tag, const DERItem *date, - CFAbsoluteTime *pabsTime) { +__attribute__((__nonnull__)) static bool derDateContentGetAbsoluteTime(DERTag tag, const DERItem *date, + CFAbsoluteTime *pabsTime) { CFAbsoluteTime absTime = SecAbsoluteTimeFromDateContent(tag, date->data, date->length); if (absTime == NULL_TIME) @@ -2010,12 +2003,10 @@ static bool derDateContentGetAbsoluteTime(DERTag tag, const DERItem *date, /* Decode a choice of UTCTime or GeneralizedTime to a CFAbsoluteTime. Return true if the date was valid and properly decoded, also return the result in absTime. Return false otherwise. */ -static bool derDateGetAbsoluteTime(const DERItem *dateChoice, +__attribute__((__nonnull__)) static bool derDateGetAbsoluteTime(const DERItem *dateChoice, CFAbsoluteTime *absTime) { - check(dateChoice); - check(absTime); - if (dateChoice->length == 0) - return false; + if (dateChoice == NULL || dateChoice->length == 0) return false; + if (absTime == NULL) return false; DERDecodedInfo decoded; if (DERDecodeItem(dateChoice, &decoded)) @@ -2658,8 +2649,10 @@ static void appendOtherNameContentProperty(CFMutableArrayRef properties, localizedLabel, value_string); else appendUnparsedProperty(properties, label, localizedLabel, &on.value); - CFRelease(label); - CFRelease(localizedLabel); + + CFReleaseSafe(value_string); + CFReleaseSafe(label); + CFReleaseSafe(localizedLabel); return; badDER: appendInvalidProperty(properties, SEC_OTHER_NAME_KEY, otherNameContent); @@ -3294,8 +3287,11 @@ static void appendExtension(CFMutableArrayRef parent, const DERItem *extnID = &extn->extnID, *extnValue = &extn->extnValue; + CFStringRef label = NULL; + CFStringRef localizedLabel = NULL; appendBoolProperty(properties, SEC_CRITICAL_KEY, extn->critical); + require_quiet(extnID, xit); #if 1 bool handeled = true; @@ -3427,15 +3423,14 @@ static void appendExtension(CFMutableArrayRef parent, appendUnparsedProperty(properties, SEC_DATA_KEY, NULL, extnValue); } #endif - CFStringRef label = SecDERItemCopyOIDDecimalRepresentation(allocator, - extnID); - CFStringRef localizedLabel = copyLocalizedOidDescription(allocator, - extnID); - appendProperty(parent, kSecPropertyTypeSection, label, localizedLabel, - properties); - CFRelease(localizedLabel); - CFRelease(label); - CFRelease(properties); + label = SecDERItemCopyOIDDecimalRepresentation(allocator, extnID); + localizedLabel = copyLocalizedOidDescription(allocator, extnID); + appendProperty(parent, kSecPropertyTypeSection, label, localizedLabel, properties); + +xit: + CFReleaseSafe(localizedLabel); + CFReleaseSafe(label); + CFReleaseSafe(properties); } /* Different types of summary types from least desired to most desired. */ @@ -3598,8 +3593,7 @@ static CFAbsoluteTime SecCertificateGetChainsFirstValidity( bool SecCertificateIsValid(SecCertificateRef certificate, CFAbsoluteTime verifyTime) { - check(certificate); - return certificate->_notBefore <= verifyTime && + return certificate && certificate->_notBefore <= verifyTime && verifyTime <= certificate->_notAfter; } @@ -4828,7 +4822,7 @@ static bool matches_expected(DERItem der, CFTypeRef expected) { return decoded.content.length == 0 && expected == NULL; } break; - + case ASN1_UTF8_STRING: { if (isString(expected)) { CFStringRef expectedString = (CFStringRef) expected; @@ -4840,7 +4834,7 @@ static bool matches_expected(DERItem der, CFTypeRef expected) { } } break; - + case ASN1_OCTET_STRING: { if (isData(expected)) { CFDataRef expectedData = (CFDataRef) expected; @@ -4852,7 +4846,7 @@ static bool matches_expected(DERItem der, CFTypeRef expected) { } } break; - + case ASN1_INTEGER: { SInt32 expected_value = 0; if (isString(expected)) @@ -4864,7 +4858,7 @@ static bool matches_expected(DERItem der, CFTypeRef expected) { { CFNumberGetValue(expected, kCFNumberSInt32Type, &expected_value); } - + uint32_t num_value = 0; if (!DERParseInteger(&decoded.content, &num_value)) { @@ -4872,7 +4866,7 @@ static bool matches_expected(DERItem der, CFTypeRef expected) { } } break; - + default: break; } @@ -4930,7 +4924,7 @@ static CFDataRef CreateOidDataFromString(CFAllocatorRef allocator, CFStringRef s { CFMutableDataRef currentResult = NULL; CFDataRef encodedResult = NULL; - + CFArrayRef parts = NULL; CFIndex count = 0; @@ -5085,7 +5079,7 @@ out: bool SecCertificateAppendToXPCArray(SecCertificateRef certificate, xpc_object_t xpc_certificates, CFErrorRef *error) { if (!certificate) return true; // NOOP - + size_t length = SecCertificateGetLength(certificate); const uint8_t *bytes = SecCertificateGetBytePtr(certificate); if (!length || !bytes) @@ -5104,7 +5098,7 @@ SecCertificateRef SecCertificateCreateWithXPCArrayAtIndex(xpc_object_t xpc_certi } if (!certificate) SecError(errSecParam, error, CFSTR("certificates[%zu] failed to decode"), index); - + return certificate; } @@ -5150,18 +5144,23 @@ exit: #define do_if_registered(sdp, ...) if (gSecurityd && gSecurityd->sdp) { return gSecurityd->sdp(__VA_ARGS__); } -static CFArrayRef CopyEscrowCertificates(CFErrorRef* error) +static CFArrayRef CopyEscrowCertificates(SecCertificateEscrowRootType escrowRootType, CFErrorRef* error) { __block CFArrayRef result = NULL; - - do_if_registered(ota_CopyEscrowCertificates, error); - - securityd_send_sync_and_do(kSecXPCOpOTAGetEscrowCertificates, error, NULL, - ^bool(xpc_object_t response, CFErrorRef *error) + + do_if_registered(ota_CopyEscrowCertificates, escrowRootType, error); + + securityd_send_sync_and_do(kSecXPCOpOTAGetEscrowCertificates, error, + ^bool(xpc_object_t message, CFErrorRef *error) + { + xpc_dictionary_set_uint64(message, "escrowType", (uint64_t)escrowRootType); + return true; + }, + ^bool(xpc_object_t response, CFErrorRef *error) { xpc_object_t xpc_array = xpc_dictionary_get_value(response, kSecXPCKeyResult); - if (response && (NULL != xpc_array)) + if (response && (NULL != xpc_array)) { result = (CFArrayRef)_CFXPCCreateCFObjectFromXPCObject(xpc_array); } @@ -5176,23 +5175,31 @@ static CFArrayRef CopyEscrowCertificates(CFErrorRef* error) CFArrayRef SecCertificateCopyEscrowRoots(SecCertificateEscrowRootType escrowRootType) { - CFArrayRef result = NULL; + CFArrayRef result = NULL; int iCnt; CFDataRef certData = NULL; - int numRoots = 0; + int numRoots = 0; - // The request is for the base line certificates. + // The request is for the base line certificates. // Use the hard coded data to generate the return array - if (kSecCertificateBaselineEscrowRoot == escrowRootType) + if (kSecCertificateBaselineEscrowRoot == escrowRootType || + kSecCertificateBaselinePCSEscrowRoot == escrowRootType) { // Get the hard coded set of roots - numRoots = kNumberOfBaseLineEscrowRoots; - SecCertificateRef baseLineCerts[numRoots]; - struct RootRecord* pRootRecord = NULL; - + numRoots = (kSecCertificateBaselineEscrowRoot == escrowRootType) ? + kNumberOfBaseLineEscrowRoots : + kNumberOfBaseLinePCSEscrowRoots; + SecCertificateRef baseLineCerts[numRoots]; + struct RootRecord** pEscrowRoots = kBaseLineEscrowRoots; + struct RootRecord* pRootRecord = NULL; + + if (kSecCertificateBaselinePCSEscrowRoot == escrowRootType) { + pEscrowRoots = kBaseLinePCSEscrowRoots; + } + for (iCnt = 0; iCnt < numRoots; iCnt++) { - pRootRecord = kBaseLineEscrowRoots[iCnt]; + pRootRecord = pEscrowRoots[iCnt]; if (NULL != pRootRecord && pRootRecord->_length > 0 && NULL != pRootRecord->_bytes) { certData = CFDataCreate(kCFAllocatorDefault, pRootRecord->_bytes, pRootRecord->_length); @@ -5208,29 +5215,29 @@ CFArrayRef SecCertificateCopyEscrowRoots(SecCertificateEscrowRootType escrowRoot { if (NULL != baseLineCerts[iCnt]) { - CFRelease(baseLineCerts[iCnt]); + CFRelease(baseLineCerts[iCnt]); } } } - // The request is for the current certificates. - else if (kSecCertificateProductionEscrowRoot == escrowRootType) + // The request is for the current certificates. + else { CFErrorRef error = NULL; - CFArrayRef cert_datas = CopyEscrowCertificates(&error); + CFArrayRef cert_datas = CopyEscrowCertificates(escrowRootType, &error); if (NULL != error || NULL == cert_datas) { if (NULL != error) { CFRelease(error); } - + if (NULL != cert_datas) { CFRelease(cert_datas); } return result; } - + numRoots = (int)(CFArrayGetCount(cert_datas)); SecCertificateRef assetCerts[numRoots]; @@ -5240,14 +5247,14 @@ CFArrayRef SecCertificateCopyEscrowRoots(SecCertificateEscrowRootType escrowRoot if (NULL != certData) { SecCertificateRef aCertRef = SecCertificateCreateWithData(kCFAllocatorDefault, certData); - assetCerts[iCnt] = aCertRef; + assetCerts[iCnt] = aCertRef; } else { assetCerts[iCnt] = NULL; } } - + if (numRoots > 0) { result = CFArrayCreate(kCFAllocatorDefault, (const void **)assetCerts, numRoots, &kCFTypeArrayCallBacks); @@ -5255,7 +5262,7 @@ CFArrayRef SecCertificateCopyEscrowRoots(SecCertificateEscrowRootType escrowRoot { if (NULL != assetCerts[iCnt]) { - CFRelease(assetCerts[iCnt]); + CFRelease(assetCerts[iCnt]); } } } diff --git a/Security/sec/Security/SecCertificate.h b/Security/sec/Security/SecCertificate.h new file mode 100644 index 00000000..4e38ef05 --- /dev/null +++ b/Security/sec/Security/SecCertificate.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2006-2009,2012-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@ + */ + +/*! + @header SecCertificate + The functions provided in SecCertificate.h implement and manage a + particular type of keychain item that represents a X.509 public key + certificate. You can store a certificate in a keychain, but a + certificate can also be a transient object. + + You can use a certificate as a keychain item in most functions. +*/ + +#ifndef _SECURITY_SECCERTIFICATE_H_ +#define _SECURITY_SECCERTIFICATE_H_ + +#include +#include + +__BEGIN_DECLS + +/*! + @function SecCertificateGetTypeID + @abstract Returns the type identifier of SecCertificate instances. + @result The CFTypeID of SecCertificate instances. +*/ +CFTypeID SecCertificateGetTypeID(void) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +/*! + @function SecCertificateCreateWithData + @abstract Create a certificate given it's DER representation as a CFData. + @param allocator CFAllocator to allocate the certificate with. + @param certificate DER encoded X.509 certificate. + @result Return NULL if the passed-in data is not a valid DER-encoded + X.509 certificate, return a SecCertificateRef otherwise. +*/ +SecCertificateRef SecCertificateCreateWithData(CFAllocatorRef allocator, + CFDataRef data) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @function SecCertificateCopyData + @abstract Return the DER representation of an X.509 certificate. + @param certificate SecCertificate object created with + SecCertificateCreateWithData(). + @result DER encoded X.509 certificate. +*/ +CFDataRef SecCertificateCopyData(SecCertificateRef certificate) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @function SecCertificateCopySubjectSummary + @abstract Return a simple string which hopefully represents a human + understandable summary. + @param certificate SecCertificate object created with + SecCertificateCreateWithData(). + @discussion All the data in this string comes from the certificate itself + and thus it's in whatever language the certificate itself is in. + @result A CFStringRef which the caller should CFRelease() once it's no + longer needed. +*/ +CFStringRef SecCertificateCopySubjectSummary(SecCertificateRef certificate) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +__END_DECLS + +#endif /* !_SECURITY_SECCERTIFICATE_H_ */ diff --git a/sec/Security/SecCertificateInternal.h b/Security/sec/Security/SecCertificateInternal.h similarity index 99% rename from sec/Security/SecCertificateInternal.h rename to Security/sec/Security/SecCertificateInternal.h index 11f7a8ff..cbd8a127 100644 --- a/sec/Security/SecCertificateInternal.h +++ b/Security/sec/Security/SecCertificateInternal.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2007-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/sec/Security/SecCertificatePath.c b/Security/sec/Security/SecCertificatePath.c similarity index 93% rename from sec/Security/SecCertificatePath.c rename to Security/sec/Security/SecCertificatePath.c index 2b46451a..f634500c 100644 --- a/sec/Security/SecCertificatePath.c +++ b/Security/sec/Security/SecCertificatePath.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2010,2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -51,6 +51,7 @@ #include #include #include +#include // MARK: - // MARK: SecCertificatePath @@ -83,9 +84,7 @@ struct SecCertificatePath { SecCertificateRef certificates[]; }; -/* CFRuntime regsitration data. */ -static pthread_once_t kSecCertificatePathRegisterClass = PTHREAD_ONCE_INIT; -static CFTypeID kSecCertificatePathTypeID = _kCFRuntimeNotATypeID; +CFGiblisWithHashFor(SecCertificatePath) static void SecCertificatePathDestroy(CFTypeRef cf) { SecCertificatePathRef certificatePath = (SecCertificatePathRef) cf; @@ -95,7 +94,7 @@ static void SecCertificatePathDestroy(CFTypeRef cf) { } } -static Boolean SecCertificatePathEqual(CFTypeRef cf1, CFTypeRef cf2) { +static Boolean SecCertificatePathCompare(CFTypeRef cf1, CFTypeRef cf2) { SecCertificatePathRef cp1 = (SecCertificatePathRef) cf1; SecCertificatePathRef cp2 = (SecCertificatePathRef) cf2; if (cp1->count != cp2->count) @@ -120,7 +119,7 @@ static CFHashCode SecCertificatePathHash(CFTypeRef cf) { return hashCode; } -static CFStringRef SecCertificateCopyPathDescription(CFTypeRef cf) { +static CFStringRef SecCertificatePathCopyDescription(CFTypeRef cf) { SecCertificatePathRef certificatePath = (SecCertificatePathRef) cf; CFMutableStringRef desc = CFStringCreateMutable(kCFAllocatorDefault, 0); CFStringRef typeStr = CFCopyTypeIDDescription(CFGetTypeID(cf)); @@ -142,30 +141,6 @@ static CFStringRef SecCertificateCopyPathDescription(CFTypeRef cf) { return desc; } -static void SecCertificatePathRegisterClass(void) { - static const CFRuntimeClass kSecCertificatePathClass = { - 0, /* version */ - "SecCertificatePath", /* class name */ - NULL, /* init */ - NULL, /* copy */ - SecCertificatePathDestroy, /* dealloc */ - SecCertificatePathEqual, /* equal */ - SecCertificatePathHash, /* hash */ - NULL, /* copyFormattingDesc */ - SecCertificateCopyPathDescription /* copyDebugDesc */ - }; - - kSecCertificatePathTypeID = - _CFRuntimeRegisterClass(&kSecCertificatePathClass); -} - -/* SecCertificatePath API functions. */ -CFTypeID SecCertificatePathGetTypeID(void) { - pthread_once(&kSecCertificatePathRegisterClass, - SecCertificatePathRegisterClass); - return kSecCertificatePathTypeID; -} - /* Create a new certificate path from an old one. */ SecCertificatePathRef SecCertificatePathCreate(SecCertificatePathRef path, SecCertificateRef certificate) { diff --git a/sec/Security/SecCertificatePath.h b/Security/sec/Security/SecCertificatePath.h similarity index 98% rename from sec/Security/SecCertificatePath.h rename to Security/sec/Security/SecCertificatePath.h index b102a05e..ed157bdd 100644 --- a/sec/Security/SecCertificatePath.h +++ b/Security/sec/Security/SecCertificatePath.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2009,2012-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/sec/Security/SecCertificatePriv.h b/Security/sec/Security/SecCertificatePriv.h new file mode 100644 index 00000000..bff3964e --- /dev/null +++ b/Security/sec/Security/SecCertificatePriv.h @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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 SecCertificatePriv + The functions provided in SecCertificatePriv.h implement and manage a particular + type of keychain item that represents a certificate. You can store a + certificate in a keychain, but a certificate can also be a transient + object. + + You can use a certificate as a keychain item in most functions. + Certificates are able to compute their parent certificates, and much more. +*/ + +#ifndef _SECURITY_SECCERTIFICATEPRIV_H_ +#define _SECURITY_SECCERTIFICATEPRIV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +typedef uint32_t SecKeyUsage; +enum { + kSecKeyUsageUnspecified = 0, + kSecKeyUsageDigitalSignature = 1 << 0, + kSecKeyUsageNonRepudiation = 1 << 1, + kSecKeyUsageContentCommitment= 1 << 1, + kSecKeyUsageKeyEncipherment = 1 << 2, + kSecKeyUsageDataEncipherment = 1 << 3, + kSecKeyUsageKeyAgreement = 1 << 4, + kSecKeyUsageKeyCertSign = 1 << 5, + kSecKeyUsageCRLSign = 1 << 6, + kSecKeyUsageEncipherOnly = 1 << 7, + kSecKeyUsageDecipherOnly = 1 << 8, + kSecKeyUsageCritical = 1 << 31, + kSecKeyUsageAll = 0x7FFFFFFF +}; + +typedef uint32_t SecCertificateEscrowRootType; +enum { + kSecCertificateBaselineEscrowRoot = 0, + kSecCertificateProductionEscrowRoot = 1, + kSecCertificateBaselinePCSEscrowRoot = 2, + kSecCertificateProductionPCSEscrowRoot = 3, +}; + +/* The names of the files that contain the escrow certificates */ +extern CFTypeRef kSecCertificateProductionEscrowKey; +extern CFTypeRef kSecCertificateProductionPCSEscrowKey; +extern CFTypeRef kSecCertificateEscrowFileName; + + +/* Return a certificate for the DER representation of this certificate. + Return NULL if the passed-in data is not a valid DER-encoded X.509 + certificate. */ +SecCertificateRef SecCertificateCreateWithBytes(CFAllocatorRef allocator, + const UInt8 *bytes, CFIndex length); + +/* Return the length of the DER representation of this certificate. */ +CFIndex SecCertificateGetLength(SecCertificateRef certificate); + +/* Return the bytes of the DER representation of this certificate. */ +const UInt8 *SecCertificateGetBytePtr(SecCertificateRef certificate); + +// MARK: - +// MARK: Certificate Accessors + +CFDataRef SecCertificateGetSHA1Digest(SecCertificateRef certificate); + +CFDataRef SecCertificateCopyIssuerSHA1Digest(SecCertificateRef certificate); + +CFDataRef SecCertificateCopyPublicKeySHA1Digest(SecCertificateRef certificate); + +/*! + @function SecCertificateCopyIssuerSummary + @abstract Return a simple string which hopefully represents a human understandable issuer. + @param certificate SecCertificate object created with SecCertificateCreateWithData(). + @discussion All the data in this string comes from the certificate itself + and thus it's in whatever language the certificate itself is in. + @result A CFStringRef which the caller should CFRelease() once it's no longer needed. +*/ +CFStringRef SecCertificateCopyIssuerSummary(SecCertificateRef certificate); + +/*! + @function SecCertificateCopyProperties + @abstract Return a property array for this trust certificate. + @param certificate A reference to the certificate to evaluate. + @result A property array. It is the caller's responsability to CFRelease + the returned array when it is no longer needed. + See SecTrustCopySummaryPropertiesAtIndex on how to intepret this array. + Unlike that function call this function returns a detailed description + of the certificate in question. +*/ +CFArrayRef SecCertificateCopyProperties(SecCertificateRef certificate); + +CFMutableArrayRef SecCertificateCopySummaryProperties( + SecCertificateRef certificate, CFAbsoluteTime verifyTime); + +/* Return the content of a DER-encoded integer (without the tag and length + fields) for this certificate's serial number. The caller must CFRelease + the value returned. */ +CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate); + +/* Return an array of CFStringRefs representing the ip addresses in the + certificate if any. */ +CFArrayRef SecCertificateCopyIPAddresses(SecCertificateRef certificate); + +/* Return an array of CFStringRefs representing the dns addresses in the + certificate if any. */ +CFArrayRef SecCertificateCopyDNSNames(SecCertificateRef certificate); + +/* Return an array of CFStringRefs representing the email addresses in the + certificate if any. */ +CFArrayRef SecCertificateCopyRFC822Names(SecCertificateRef certificate); + +/* Return an array of CFStringRefs representing the common names in the + certificates subject if any. */ +CFArrayRef SecCertificateCopyCommonNames(SecCertificateRef certificate); + +/* Return an array of CFStringRefs representing the organization in the + certificate's subject if any. */ +CFArrayRef SecCertificateCopyOrganization(SecCertificateRef certificate); + +/* Return an array of CFStringRefs representing the organizational unit in the + certificate's subject if any. */ +CFArrayRef SecCertificateCopyOrganizationalUnit(SecCertificateRef certificate); + +/* Return an array of CFStringRefs representing the NTPrincipalNames in the + certificate if any. */ +CFArrayRef SecCertificateCopyNTPrincipalNames(SecCertificateRef certificate); + +/* Return a string formatted according to RFC 2253 representing the complete + subject of certificate. */ +CFStringRef SecCertificateCopySubjectString(SecCertificateRef certificate); + +/* Return a string with the company name of an ev leaf certificate. */ +CFStringRef SecCertificateCopyCompanyName(SecCertificateRef certificate); + +/* X.509 Certificate Version: 1, 2 or 3. */ +CFIndex SecCertificateVersion(SecCertificateRef certificate); +CFAbsoluteTime SecCertificateNotValidBefore(SecCertificateRef certificate); +CFAbsoluteTime SecCertificateNotValidAfter(SecCertificateRef certificate); + +/* Return true iff certificate is self signed and has a basic constraints + extension indicating that it's a certificate authority. */ +bool SecCertificateIsSelfSignedCA(SecCertificateRef certificate); + +SecKeyUsage SecCertificateGetKeyUsage(SecCertificateRef certificate); + +/* Returns an array of CFDataRefs for all extended key usage oids or NULL */ +CFArrayRef SecCertificateCopyExtendedKeyUsage(SecCertificateRef certificate); + +/* Returns a certificate from a pem blob */ +SecCertificateRef SecCertificateCreateWithPEM(CFAllocatorRef allocator, + CFDataRef pem_certificate); + +/* Append certificate to xpc_certificates. */ +bool SecCertificateAppendToXPCArray(SecCertificateRef certificate, xpc_object_t xpc_certificates, CFErrorRef *error); + +/* Decode certificate from xpc_certificates[index] as encoded by SecCertificateAppendToXPCArray(). */ +SecCertificateRef SecCertificateCreateWithXPCArrayAtIndex(xpc_object_t xpc_certificates, size_t index, CFErrorRef *error); + +/* Retrieve the array of valid Escrow certificates for a given root type */ +CFArrayRef SecCertificateCopyEscrowRoots(SecCertificateEscrowRootType escrowRootType); + +/* Return an xpc_array of data from an array of SecCertificateRefs. */ +xpc_object_t SecCertificateArrayCopyXPCArray(CFArrayRef certificates, CFErrorRef *error); + +/* Return an array of SecCertificateRefs from a xpc_object array of datas. */ +CFArrayRef SecCertificateXPCArrayCopyArray(xpc_object_t xpc_certificates, CFErrorRef *error); + +__END_DECLS + +#endif /* !_SECURITY_SECCERTIFICATEPRIV_H_ */ diff --git a/sec/Security/SecCertificateRequest.c b/Security/sec/Security/SecCertificateRequest.c similarity index 95% rename from sec/Security/SecCertificateRequest.c rename to Security/sec/Security/SecCertificateRequest.c index 7f748f4f..7cf9f916 100644 --- a/sec/Security/SecCertificateRequest.c +++ b/Security/sec/Security/SecCertificateRequest.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-2009,2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -55,6 +55,8 @@ OSStatus SecCmsArraySortByDER(void **objs, const SecAsn1Template *objtemplate, v #include #include +#include + #include #include "SecCertificateRequest.h" @@ -114,6 +116,7 @@ static uint8_t * oid_der_data(PRArenaPool *poolp, CFStringRef oid_string, size_t *oid_data_len = tmp_oid_data_ptr - tmp_oid_data; return tmp_oid_data; out: + CFReleaseSafe(oid); return NULL; } @@ -400,6 +403,7 @@ CFTypeRef kSecSubjectAltName = CFSTR("subjectAltName"); CFTypeRef kSecCertificateKeyUsage = CFSTR("keyUsage"); CFTypeRef kSecCSRBasicContraintsPathLen = CFSTR("basicConstraints"); CFTypeRef kSecCertificateExtensions = CFSTR("certificateExtensions"); +CFTypeRef kSecCertificateExtensionsEncoded = CFSTR("certificateExtensionsEncoded"); static const uint8_t pkcs9ExtensionsRequested[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 14 }; static const uint8_t pkcs9ChallengePassword[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 7 }; @@ -408,7 +412,7 @@ static const uint8_t encoded_asn1_true = 0xFF; static const SecAsn1Item asn1_true = { sizeof(encoded_asn1_true), (uint8_t*)&encoded_asn1_true }; -static inline uint32_t highest_bit(uint32_t n) +__unused static inline uint32_t highest_bit(uint32_t n) { return ((n) >> 16 ? ((n)>>=16, 16) : 0) + \ ((n) >> 8 ? ((n)>>=8, 8) : 0) + \ @@ -423,6 +427,7 @@ struct add_custom_extension_args { NSS_CertExtension *csr_extension; uint32_t num_extensions; uint32_t max_extensions; + bool encodeData; }; static void add_custom_extension(const void *key, const void *value, void *context) @@ -436,6 +441,9 @@ static void add_custom_extension(const void *key, const void *value, void *conte SecAsn1Item encoded_value = {}; if (CFGetTypeID(value) == CFStringGetTypeID()) { + if (!args->encodeData) { + goto out; + } CFIndex buffer_size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value), kCFStringEncodingUTF8); char *buffer = (char *)PORT_ArenaZNewArray(args->poolp, uint8_t, buffer_size); if (!CFStringGetCString(value, buffer, buffer_size, kCFStringEncodingUTF8)) @@ -444,8 +452,14 @@ static void add_custom_extension(const void *key, const void *value, void *conte SecAsn1Item buffer_item = { strlen(buffer), (uint8_t*)buffer }; SEC_ASN1EncodeItem(args->poolp, &encoded_value, &buffer_item, kSecAsn1UTF8StringTemplate); } else if (CFGetTypeID(value) == CFDataGetTypeID()) { - SecAsn1Item data_item = { CFDataGetLength(value), (uint8_t*)CFDataGetBytePtr(value) }; - SEC_ASN1EncodeItem(args->poolp, &encoded_value, &data_item, kSecAsn1OctetStringTemplate); + if (args->encodeData) { + SecAsn1Item data_item = { CFDataGetLength(value), (uint8_t*)CFDataGetBytePtr(value) }; + SEC_ASN1EncodeItem(args->poolp, &encoded_value, &data_item, kSecAsn1OctetStringTemplate); + } + else { + encoded_value.Length = CFDataGetLength(value); + encoded_value.Data = (uint8_t*)CFDataGetBytePtr(value); + } } else goto out; @@ -537,12 +551,27 @@ extensions_from_parameters(PRArenaPool *poolp, CFDictionaryRef parameters) poolp, csr_extension, num_extensions, - max_extensions + max_extensions, + true }; CFDictionaryApplyFunction(custom_extension_requested, add_custom_extension, &args); num_extensions = args.num_extensions; } + CFDictionaryRef custom_encoded_extension_requested = CFDictionaryGetValue(parameters, kSecCertificateExtensionsEncoded); + if (custom_encoded_extension_requested) { + require(CFGetTypeID(custom_encoded_extension_requested) == CFDictionaryGetTypeID(), out); + struct add_custom_extension_args args = { + poolp, + csr_extension, + num_extensions, + max_extensions, + false + }; + CFDictionaryApplyFunction(custom_encoded_extension_requested, add_custom_extension, &args); + num_extensions = args.num_extensions; + } + /* extensions requested (subjectAltName, keyUsage) sequence of extension sequences */ uint32_t ix = 0; for (ix = 0; ix < num_extensions; ix++) @@ -668,9 +697,11 @@ CFDataRef SecGenerateCertificateRequestWithParameters(SecRDN *subject, atv_num++; /* one more */ num++; } - NSS_ATV atvs[atv_num]; - NSS_ATV *atvps[atv_num]; - NSS_RDN rdns[num]; + const unsigned min1atv_num = atv_num > 0 ? atv_num : 1; + const unsigned min1num = num > 0 ? num : 1; + NSS_ATV atvs[min1atv_num]; + NSS_ATV *atvps[min1atv_num]; + NSS_RDN rdns[min1num]; NSS_RDN *rdnps[num+1]; atv_num = 0; unsigned rdn_num = 0; @@ -892,34 +923,42 @@ out: static OSStatus DER_CFDateToUTCTime(PRArenaPool *poolp, CFAbsoluteTime date, SecAsn1Item * utcTime) { - CFGregorianDate gdate = CFAbsoluteTimeGetGregorianDate(date, NULL /* GMT */); unsigned char *d; - SInt8 second; - + utcTime->Length = 13; utcTime->Data = d = PORT_ArenaAlloc(poolp, 13); if (!utcTime->Data) - return SECFailure; - + return SECFailure; + + int year; + int month; + int day; + int hour; + int minute; + int second; + + if (!CFCalendarDecomposeAbsoluteTime(SecCFCalendarGetZulu(), date, "yMdHms", &year, &month, &day, &hour, &minute, &second)) + return SECFailure; + + /* UTC time does not handle the years before 1950 */ - if (gdate.year < 1950) - return SECFailure; - + if (year < 1950) + return SECFailure; + /* remove the century since it's added to the year by the - CFAbsoluteTimeGetGregorianDate routine, but is not needed for UTC time */ - gdate.year %= 100; - second = gdate.second; - - d[0] = HIDIGIT(gdate.year); - d[1] = LODIGIT(gdate.year); - d[2] = HIDIGIT(gdate.month); - d[3] = LODIGIT(gdate.month); - d[4] = HIDIGIT(gdate.day); - d[5] = LODIGIT(gdate.day); - d[6] = HIDIGIT(gdate.hour); - d[7] = LODIGIT(gdate.hour); - d[8] = HIDIGIT(gdate.minute); - d[9] = LODIGIT(gdate.minute); + CFAbsoluteTimeGetGregorianDate routine, but is not needed for UTC time */ + year %= 100; + + d[0] = HIDIGIT(year); + d[1] = LODIGIT(year); + d[2] = HIDIGIT(month); + d[3] = LODIGIT(month); + d[4] = HIDIGIT(day); + d[5] = LODIGIT(day); + d[6] = HIDIGIT(hour); + d[7] = LODIGIT(hour); + d[8] = HIDIGIT(minute); + d[9] = LODIGIT(minute); d[10] = HIDIGIT(second); d[11] = LODIGIT(second); d[12] = 'Z'; @@ -1119,6 +1158,7 @@ out: return cert; } +CF_RETURNS_RETAINED CFDataRef SecGenerateCertificateRequestSubject(SecCertificateRef ca_certificate, CFArrayRef subject) { diff --git a/Security/sec/Security/SecCertificateRequest.h b/Security/sec/Security/SecCertificateRequest.h new file mode 100644 index 00000000..61f32bc3 --- /dev/null +++ b/Security/sec/Security/SecCertificateRequest.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2008-2009,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@ + */ + +/*! + @header SecCertificateRequest +*/ + +#ifndef _SECURITY_SECCERTIFICATEREQUEST_H_ +#define _SECURITY_SECCERTIFICATEREQUEST_H_ + +#include +#include + +__BEGIN_DECLS + +extern const void * kSecOidCommonName; +extern const void * kSecOidCountryName; +extern const void * kSecOidStateProvinceName; +extern const void * kSecOidLocalityName; +extern const void * kSecOidOrganization; +extern const void * kSecOidOrganizationalUnit; + +extern const unsigned char SecASN1PrintableString; +extern const unsigned char SecASN1UTF8String; + +/* + Parameter keys for certificate request generation: + @param kSecCSRChallengePassword CFStringRef + conversion to PrintableString or UTF8String needs to be possible. + @param kSecCertificateKeyUsage CFNumberRef + with key usage mask using kSecKeyUsage constants. + @param kSecSubjectAltName CFArrayRef of CFStringRef or CFDataRef + either dnsName or emailAddress (if contains @) or + ipAddress, ipv4 (4) or ipv6 (16) bytes + @param kSecCSRBasicContraintsPathLen CFNumberRef + if set will include basic constraints and mark it as + a CA cert. If 0 <= number < 256, specifies path length, otherwise + path length will be omitted. Basic contraints will always be + marked critical. + @param kSecCertificateExtensions CFDictionaryRef + if set all keys (strings with oids in dotted notation) will be added + as extensions with accompanying value in binary (CFDataRef) or + appropriate string (CFStringRef) type (based on used character set). + @param kSecCertificateExtensionsEncoded CFDictionaryRef + if set all keys (strings with oids in dotted notation) will be added + as extensions with accompanying value. It is assumed that the value + is a CFDataRef and is already properly encoded. This value will be + placed straight into the extension value OCTET STRING. +*/ +extern const void * kSecCSRChallengePassword; +extern const void * kSecSubjectAltName; +extern const void * kSecCertificateKeyUsage; +extern const void * kSecCSRBasicContraintsPathLen; +extern const void * kSecCertificateExtensions; +extern const void * kSecCertificateExtensionsEncoded; + +typedef struct { + const void *oid; /* kSecOid constant or CFDataRef with oid */ + unsigned char type; /* currently only SecASN1PrintableString */ + CFTypeRef value; /* CFStringRef -> ASCII, UTF8, CFDataRef -> binary */ +} SecATV; + +typedef SecATV *SecRDN; + +/* + @function SecGenerateCertificateRequest + @abstract Return a newly generated CSR for subject and keypair. + @param subject RDNs in the subject + @param num Number of RDNs + @param publicKey Public key + @param privateKey Private key + @discussion only handles RSA keypairs and uses a SHA-1 PKCS1 signature + @result On success, a newly allocated CSR, otherwise NULL + +Example for subject: + SecATV cn[] = { { kSecOidCommonName, SecASN1PrintableString, CFSTR("test") }, {} }; + SecATV c[] = { { kSecOidCountryName, SecASN1PrintableString, CFSTR("US") }, {} }; + SecATV o[] = { { kSecOidOrganization, SecASN1PrintableString, CFSTR("Apple Inc.") }, {} }; + SecRDN atvs[] = { cn, c, o, NULL }; +*/ +CFDataRef SecGenerateCertificateRequestWithParameters(SecRDN *subject, + CFDictionaryRef parameters, SecKeyRef publicKey, SecKeyRef privateKey) CF_RETURNS_RETAINED; + +CFDataRef SecGenerateCertificateRequest(CFArrayRef subject, + CFDictionaryRef parameters, SecKeyRef publicKey, SecKeyRef privateKey) CF_RETURNS_RETAINED; + +/* + @function SecVerifyCertificateRequest + @abstract validate a CSR and return contained information to certify + @param publicKey (optional/out) SecKeyRef public key to certify + @param challenge (optional/out) CFStringRef enclosed challenge + @param subject (optional/out) encoded subject RDNs + @param extensions (optional/out) encoded extensions +*/ +bool SecVerifyCertificateRequest(CFDataRef csr, SecKeyRef *publicKey, + CFStringRef *challenge, CFDataRef *subject, CFDataRef *extensions); + +SecCertificateRef +SecGenerateSelfSignedCertificate(CFArrayRef subject, CFDictionaryRef parameters, + SecKeyRef publicKey, SecKeyRef privateKey); + +SecCertificateRef +SecIdentitySignCertificate(SecIdentityRef issuer, CFDataRef serialno, + SecKeyRef publicKey, CFTypeRef subject, CFTypeRef extensions); + + +/* PRIVATE */ + +CF_RETURNS_RETAINED +CFDataRef +SecGenerateCertificateRequestSubject(SecCertificateRef ca_certificate, CFArrayRef subject); + +__END_DECLS + +#endif /* _SECURITY_SECCERTIFICATEREQUEST_H_ */ diff --git a/Security/sec/Security/SecDH.c b/Security/sec/Security/SecDH.c new file mode 100644 index 00000000..5da3f7af --- /dev/null +++ b/Security/sec/Security/SecDH.c @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2007-2008,2010,2012-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@ + */ + +/* + * SecDH.c - Implement the crypto required for a Diffie-Hellman key exchange. + */ + +#include "SecDH.h" +#include +#include +#include +#include +#include +#include +#include "utilities/debugging.h" +#include +#include +#include +#include +#include + +#ifdef DEBUG +#define DH_DEBUG 1 +#endif + +static inline ccdh_gp_t SecDH_gp(SecDHContext dh) +{ + void *p = dh; + ccdh_gp_t gp = { .gp = p }; + return gp; +} + +static inline ccdh_full_ctx_t SecDH_priv(SecDHContext dh) +{ + void *p = dh; + cczp_t zp = { .u = p }; + cc_size s = ccn_sizeof_n(cczp_n(zp)); + ccdh_full_ctx_t priv = { .hdr = (struct ccdh_ctx_header *)(p+ccdh_gp_size(s)) }; + return priv; +} + +static inline size_t SecDH_context_size(size_t p_len) +{ + cc_size n = ccn_nof_size(p_len); + cc_size real_p_len = ccn_sizeof_n(n); + size_t context_size = ccdh_gp_size(real_p_len)+ccdh_full_ctx_size(real_p_len); + return context_size; +} + +/* Shared static functions. */ + +static OSStatus +der2OSStatus(DERReturn derReturn) +{ + switch(derReturn) + { + case DR_Success: return errSecSuccess; + case DR_EndOfSequence: return errSecDecode; + case DR_UnexpectedTag: return errSecDecode; + case DR_DecodeError: return errSecDecode; + case DR_Unimplemented: return errSecUnimplemented; + case DR_IncompleteSeq: return errSecDecode; + case DR_ParamErr: return errSecParam; + case DR_BufOverflow: return errSecBufferTooSmall; + default: return errSecInternal; + } +} + +static int dhRngCallback(struct ccrng_state *rng, unsigned long outlen, void *out) +{ + return SecRandomCopyBytes(kSecRandomDefault, outlen, out); +} + +static struct ccrng_state dhrng = { + .generate = dhRngCallback +}; + +OSStatus SecDHCreate(uint32_t g, const uint8_t *p, size_t p_len, + uint32_t l, const uint8_t *recip, size_t recip_len, SecDHContext *pdh) +{ + cc_size n = ccn_nof_size(p_len); + size_t context_size = SecDH_context_size(p_len); + void *context = malloc(context_size); + bzero(context, context_size); + + ccdh_gp_t gp; + gp.gp = context; + + CCDH_GP_N(gp) = n; + CCDH_GP_L(gp) = l; + + if(ccn_read_uint(n, CCDH_GP_PRIME(gp), p_len, p)) + goto errOut; + if(recip) { + if(ccn_read_uint(n+1, CCDH_GP_RECIP(gp), recip_len, recip)) + goto errOut; + gp.zp.zp->mod_prime = cczp_mod; + } else { + cczp_init(gp.zp); + }; + ccn_seti(n, CCDH_GP_G(gp), g); + + *pdh = (SecDHContext) context; + + return errSecSuccess; + +errOut: + SecDHDestroy(context); + *pdh = NULL; + return errSecInternal; + +} + +/* this used to be in libgDH */ +/* + * Support for encoding and decoding DH parameter blocks. + * Apple form encodes the reciprocal of the prime p. + */ +/* PKCS3, Openssl compatible */ +typedef struct { + DERItem p; + DERItem g; + DERItem l; + DERItem recip; /* Only used in Apple Custom blocks. */ +} DER_DHParams; + +static const DERItemSpec DER_DHParamsItemSpecs[] = +{ + { DER_OFFSET(DER_DHParams, p), + ASN1_INTEGER, + DER_DEC_NO_OPTS | DER_ENC_SIGNED_INT }, + { DER_OFFSET(DER_DHParams, g), + ASN1_INTEGER, + DER_DEC_NO_OPTS | DER_ENC_SIGNED_INT }, + { DER_OFFSET(DER_DHParams, l), + ASN1_INTEGER, + DER_DEC_OPTIONAL | DER_ENC_SIGNED_INT }, + /* Not part of PKCS3 per-se, but we add it on just for kicks. Since + it's optional we will automatically decode any apple specific + params, but we won't add this section unless the caller asks + us to. */ + { DER_OFFSET(DER_DHParams, recip), + ASN1_PRIVATE | ASN1_PRIMITIVE | 0, + DER_DEC_OPTIONAL | DER_ENC_SIGNED_INT }, +}; +static const DERSize DER_NumDHParamsItemSpecs = +sizeof(DER_DHParamsItemSpecs) / sizeof(DERItemSpec); + + +OSStatus SecDHCreateFromParameters(const uint8_t *params, + size_t params_len, SecDHContext *pdh) +{ + DERReturn drtn; + DERItem paramItem = {(DERByte *)params, params_len}; + DER_DHParams decodedParams; + uint32_t l; + + drtn = DERParseSequence(¶mItem, + DER_NumDHParamsItemSpecs, DER_DHParamsItemSpecs, + &decodedParams, sizeof(decodedParams)); + if(drtn) + return drtn; + + drtn = DERParseInteger(&decodedParams.l, &l); + if(drtn) + return drtn; + cc_size n = ccn_nof_size(decodedParams.p.length); + cc_size p_len = ccn_sizeof_n(n); + size_t context_size = ccdh_gp_size(p_len)+ccdh_full_ctx_size(p_len); + void *context = malloc(context_size); + if(context==NULL) + return errSecAllocate; + + bzero(context, context_size); + + ccdh_gp_t gp; + gp.gp = context; + + CCDH_GP_N(gp) = n; + CCDH_GP_L(gp) = l; + + if(ccn_read_uint(n, CCDH_GP_PRIME(gp), decodedParams.p.length, decodedParams.p.data)) + goto errOut; + if(decodedParams.recip.length) { + if(ccn_read_uint(n+1, CCDH_GP_RECIP(gp), decodedParams.recip.length, decodedParams.recip.data)) + goto errOut; + gp.zp.zp->mod_prime = cczp_mod; + } else { + cczp_init(gp.zp); + }; + + if(ccn_read_uint(n, CCDH_GP_G(gp), decodedParams.g.length, decodedParams.g.data)) + goto errOut; + + *pdh = (SecDHContext) context; + return errSecSuccess; + +errOut: + SecDHDestroy(context); + *pdh = NULL; + return errSecInvalidKey; +} + +OSStatus SecDHCreateFromAlgorithmId(const uint8_t *alg, size_t alg_len, + SecDHContext *pdh) { + DERAlgorithmId algorithmId; + DERItem algId; + + algId.data = (uint8_t *)alg; + algId.length = alg_len; + + DERReturn drtn = DERParseSequence(&algId, + DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs, + &algorithmId, sizeof(algorithmId)); + if (drtn != DR_Success) + return der2OSStatus(drtn); + + return SecDHCreateFromParameters(algorithmId.params.data, + algorithmId.params.length, pdh); +} + +size_t SecDHGetMaxKeyLength(SecDHContext dh) { + cczp_const_t zp; + zp.u = (cc_unit *)dh; + + return ccn_sizeof_n(cczp_n(zp)); +} + + +OSStatus SecDHGenerateKeypair(SecDHContext dh, uint8_t *pub_key, + size_t *pub_key_len) +{ + int result; + ccdh_gp_t gp = SecDH_gp(dh); + ccdh_full_ctx_t priv = SecDH_priv(dh); + + if((result = ccdh_generate_key(gp, &dhrng, priv))) + return result; + + /* output y as a big endian byte buffer */ + size_t ylen = ccn_write_uint_size(ccdh_gp_n(gp), ccdh_ctx_y(priv)); + if(*pub_key_len < ylen) + return errSecBufferTooSmall; + ccn_write_uint(ccdh_gp_n(gp),ccdh_ctx_y(priv), ylen, pub_key); + *pub_key_len = ylen; + + return errSecSuccess; +} + +OSStatus SecDHComputeKey(SecDHContext dh, + const uint8_t *pub_key, size_t pub_key_len, + uint8_t *computed_key, size_t *computed_key_len) +{ + ccdh_gp_t gp = SecDH_gp(dh); + ccdh_full_ctx_t priv = SecDH_priv(dh); + ccdh_pub_ctx_decl_gp(gp, pub); + cc_size n = ccdh_gp_n(gp); + cc_unit r[n]; + + if(ccdh_import_pub(gp, pub_key_len, pub_key, pub)) + return errSecInvalidKey; + + if(ccdh_compute_key(priv, pub, r)) + return errSecInvalidKey; + + ccn_write_uint(n, r, *computed_key_len, computed_key); + size_t out_size = ccn_write_uint_size(n, r); + if(out_size < *computed_key_len) + *computed_key_len=out_size; + + return errSecSuccess; +} + +void SecDHDestroy(SecDHContext dh) { + /* Zero out key material. */ + ccdh_gp_t gp = SecDH_gp(dh); + cc_size p_len = ccn_sizeof_n(ccdh_gp_n(gp)); + size_t context_size = SecDH_context_size(p_len); + + bzero(dh, context_size); + free(dh); +} + +/* Max encoded size for standard (PKCS3) parameters */ +#define DH_ENCODED_PARAM_SIZE(primeSizeInBytes) \ +DER_MAX_ENCODED_SIZE( \ +DER_MAX_ENCODED_SIZE(primeSizeInBytes) + /* g */ \ +DER_MAX_ENCODED_SIZE(primeSizeInBytes) + /* p */ \ +DER_MAX_ENCODED_SIZE(4)) /* l */ + + +OSStatus SecDHEncodeParams(CFDataRef g, CFDataRef p, + CFDataRef l, CFDataRef recip, + CFDataRef *params) +{ + OSStatus ortn; + DER_DHParams derParams = + { + .p = { + .length = CFDataGetLength(p), + .data = (DERByte *)CFDataGetBytePtr(p), + }, + .g = { + .length = CFDataGetLength(g), + .data = (DERByte *)CFDataGetBytePtr(g), + }, + .l = { + .length = l?CFDataGetLength(l):0, + .data = (DERByte *)(l?CFDataGetBytePtr(l):NULL), + }, + .recip = { + .length = recip?CFDataGetLength(recip):0, + .data = (DERByte *)(recip?CFDataGetBytePtr(recip):NULL), + }, + }; + + DERSize ioLen = DERLengthOfEncodedSequence(ASN1_CONSTR_SEQUENCE, + &derParams, + DER_NumDHParamsItemSpecs, DER_DHParamsItemSpecs); + + DERByte *der = malloc(ioLen); + // FIXME: What if this fails - we should probably not have a malloc here ? + assert(der); + ortn = (int)DEREncodeSequence(ASN1_CONSTR_SEQUENCE, + &derParams, + DER_NumDHParamsItemSpecs, DER_DHParamsItemSpecs, + der, + &ioLen); + + if(!ortn && params) + *params=CFDataCreate(kCFAllocatorDefault, der, ioLen); + + // FIXME: we should just allocate the CFDataRef + + free(der); + return ortn; +} + + +OSStatus SecDHDecodeParams(CFDataRef *g, CFDataRef *p, + CFDataRef *l, CFDataRef *r, + CFDataRef params) +{ + DERReturn drtn; + DERItem paramItem = {(DERByte *)CFDataGetBytePtr(params), CFDataGetLength(params)}; + DER_DHParams decodedParams; + + drtn = DERParseSequence(¶mItem, + DER_NumDHParamsItemSpecs, DER_DHParamsItemSpecs, + &decodedParams, sizeof(decodedParams)); + if(drtn) + return drtn; + + if(g) *g=CFDataCreate(kCFAllocatorDefault, decodedParams.g.data, decodedParams.g.length); + if(p) *p=CFDataCreate(kCFAllocatorDefault, decodedParams.p.data, decodedParams.p.length); + if(l) *l=CFDataCreate(kCFAllocatorDefault, decodedParams.l.data, decodedParams.l.length); + if(r) *r=CFDataCreate(kCFAllocatorDefault, decodedParams.recip.data, decodedParams.recip.length); + + return errSecSuccess; +} diff --git a/sec/Security/SecDH.h b/Security/sec/Security/SecDH.h similarity index 91% rename from sec/Security/SecDH.h rename to Security/sec/Security/SecDH.h index 2bfdb109..03460739 100644 --- a/sec/Security/SecDH.h +++ b/Security/sec/Security/SecDH.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2008,2010,2012-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -31,7 +31,7 @@ #define _SECURITY_SECDH_H_ #include -#include +#include #include #include #include @@ -157,6 +157,23 @@ OSStatus SecDHComputeKey(SecDHContext dh, */ void SecDHDestroy(SecDHContext dh); + +/*! + @function SecDHEncodeParams + @abstract Encode parameters in a PKCS#3 blob + */ +OSStatus SecDHEncodeParams(CFDataRef g, CFDataRef p, + CFDataRef l, CFDataRef recip, + CFDataRef *params); + +/*! + @function SecDHDecodeParams + @abstract Decode parameters in a PKCS#3 blob + */ +OSStatus SecDHDecodeParams(CFDataRef *g, CFDataRef *p, + CFDataRef *l, CFDataRef *r, + CFDataRef params); + #ifdef __cplusplus } #endif diff --git a/Security/sec/Security/SecECKey.c b/Security/sec/Security/SecECKey.c new file mode 100644 index 00000000..80c10ca2 --- /dev/null +++ b/Security/sec/Security/SecECKey.c @@ -0,0 +1,848 @@ +/* + * Copyright (c) 2010-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * SecECKey.c - CoreFoundation based rsa key object + */ + +#include "SecECKey.h" +#include "SecECKeyPriv.h" + +#include +#include +#include +#include +#include /* For error codes. */ +#include /* For error codes. */ +#include +#include +#include +#include +#include +#include +#include +#include "SecItemPriv.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define kMaximumECKeySize 521 + +static CFIndex SecECKeyGetAlgorithmID(SecKeyRef key) { + return kSecECDSAAlgorithmID; +} + + +/* + * + * Public Key + * + */ + +/* Public key static functions. */ +static void SecECPublicKeyDestroy(SecKeyRef key) { + /* Zero out the public key */ + ccec_pub_ctx_t pubkey; + pubkey.pub = key->key; + if (ccec_ctx_cp(pubkey).zp) + cc_zero(ccec_pub_ctx_size(ccn_sizeof_n(ccec_ctx_n(pubkey))), pubkey.pub); +} + +static ccec_const_cp_t getCPForPublicSize(CFIndex encoded_length) +{ + size_t keysize = ccec_x963_import_pub_size(encoded_length); + if(ccec_keysize_is_supported(keysize)) { + return ccec_get_cp(keysize); + } + ccec_const_cp_t nullCP = { .zp = NULL }; + return nullCP; +} + +static ccec_const_cp_t getCPForPrivateSize(CFIndex encoded_length) +{ + size_t keysize = ccec_x963_import_priv_size(encoded_length); + if(ccec_keysize_is_supported(keysize)) { + return ccec_get_cp(keysize); + } + ccec_const_cp_t nullCP = { .zp = NULL }; + return nullCP; +} + +static ccoid_t ccoid_secp192r1 = CC_EC_OID_SECP192R1; +static ccoid_t ccoid_secp256r1 = CC_EC_OID_SECP256R1; +static ccoid_t ccoid_secp224r1 = CC_EC_OID_SECP224R1; +static ccoid_t ccoid_secp384r1 = CC_EC_OID_SECP384R1; +static ccoid_t ccoid_secp521r1 = CC_EC_OID_SECP521R1; + +static ccec_const_cp_t ccec_cp_for_oid(ccoid_t oid) +{ + if (oid.oid) { + if (ccoid_equal(oid, ccoid_secp192r1)) { + return ccec_cp_192(); + } else if (ccoid_equal(oid, ccoid_secp256r1)) { + return ccec_cp_256(); + } else if (ccoid_equal(oid, ccoid_secp224r1)) { + return ccec_cp_224(); + } else if (ccoid_equal(oid, ccoid_secp384r1)) { + return ccec_cp_384(); + } else if (ccoid_equal(oid, ccoid_secp521r1)) { + return ccec_cp_521(); + } + } + return (ccec_const_cp_t){NULL}; +} + +static OSStatus SecECPublicKeyInit(SecKeyRef key, + const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) { + ccec_pub_ctx_t pubkey; + pubkey.pub = key->key; + OSStatus err = errSecParam; + + switch (encoding) { + case kSecDERKeyEncoding: + { + const SecDERKey *derKey = (const SecDERKey *)keyData; + if (keyDataLength != sizeof(SecDERKey)) { + err = errSecDecode; + break; + } + + ccec_const_cp_t cp = getCPForPublicSize(derKey->keyLength); + + /* TODO: Parse and use real params from passed in derKey->algId.params */ + err = (ccec_import_pub(cp, derKey->keyLength, derKey->key, pubkey) + ? errSecDecode : errSecSuccess); + break; + } + case kSecKeyEncodingBytes: + { + ccec_const_cp_t cp = getCPForPublicSize(keyDataLength); + err = (ccec_import_pub(cp, keyDataLength, keyData, pubkey) + ? errSecDecode : errSecSuccess); + break; + } + case kSecExtractPublicFromPrivate: + { + ccec_full_ctx_t fullKey; + fullKey._full = (ccec_full_ctx *) keyData; + + cc_size fullKeyN = ccec_ctx_n(fullKey); + require(fullKeyN <= ccn_nof(kMaximumECKeySize), errOut); + memcpy(pubkey._pub, fullKey.pub, ccec_pub_ctx_size(ccn_sizeof_n(fullKeyN))); + err = errSecSuccess; + break; + } + case kSecKeyEncodingApplePkcs1: + default: + err = errSecParam; + break; + } + +errOut: + return err; +} + +static OSStatus SecECPublicKeyRawVerify(SecKeyRef key, SecPadding padding, + const uint8_t *signedData, size_t signedDataLen, + const uint8_t *sig, size_t sigLen) { + int err = errSSLCrypto; // TODO: Should be errSecNotSigner; + ccec_pub_ctx_t pubkey; + pubkey.pub = key->key; + bool valid = 0; + + if (ccec_verify(pubkey, signedDataLen, signedData, sigLen, sig, &valid)) + err = errSSLCrypto; // TODO: This seems weird. Shouldn't be SSL error + if (valid) + err = errSecSuccess; + + return err; +} + +static OSStatus SecECPublicKeyRawEncrypt(SecKeyRef key, SecPadding padding, + const uint8_t *plainText, size_t plainTextLen, + uint8_t *cipherText, size_t *cipherTextLen) { + ccec_pub_ctx_t pubkey; + pubkey.pub = key->key; + int err = errSecUnimplemented; + +#if 0 + require_noerr(err = ccec_wrap_key(pubkey, &ccsha256_di, + plainTextLen, plainText, cipherText), errOut); + +errOut: +#endif + return err; +} + +static size_t SecECPublicKeyBlockSize(SecKeyRef key) { + /* Get key size in octets */ + ccec_pub_ctx_t pubkey; + pubkey.pub = key->key; + return ccec_ctx_size(pubkey); +} + +/* Encode the public key and return it in a newly allocated CFDataRef. */ +static CFDataRef SecECPublicKeyExport(CFAllocatorRef allocator, + ccec_pub_ctx_t pubkey) { + size_t pub_size = ccec_export_pub_size(pubkey); + CFMutableDataRef blob = CFDataCreateMutable(allocator, pub_size); + if (blob) { + CFDataSetLength(blob, pub_size); + ccec_export_pub(pubkey, CFDataGetMutableBytePtr(blob)); + } + + return blob; +} + +static OSStatus SecECPublicKeyCopyPublicOctets(SecKeyRef key, CFDataRef *serailziation) +{ + ccec_pub_ctx_t pubkey; + pubkey.pub = key->key; + + CFAllocatorRef allocator = CFGetAllocator(key); + *serailziation = SecECPublicKeyExport(allocator, pubkey); + + if (NULL == *serailziation) + return errSecDecode; + else + return errSecSuccess; +} + +static CFDictionaryRef SecECPublicKeyCopyAttributeDictionary(SecKeyRef key) { + return SecKeyGeneratePublicAttributeDictionary(key, kSecAttrKeyTypeEC); +} + +static const char * +getCurveName(SecKeyRef key) +{ + SecECNamedCurve curveType = SecECKeyGetNamedCurve(key); + + switch (curveType) + { + case kSecECCurveSecp256r1: + return "kSecECCurveSecp256r1"; + break; + case kSecECCurveSecp384r1: + return "kSecECCurveSecp384r1"; + break; + case kSecECCurveSecp521r1: + return "kSecECCurveSecp521r1"; + default: + return "kSecECCurveNone"; + } +} + +static CFStringRef SecECPublicKeyCopyKeyDescription(SecKeyRef key) +{ + ccec_pub_ctx_t ecPubkey; + CFStringRef keyDescription = NULL; + size_t xlen, ylen, ix; + CFMutableStringRef xString = NULL; + CFMutableStringRef yString = NULL; + + ecPubkey.pub = key->key; + + const char* curve = getCurveName(key); + + uint8_t *xunit = (uint8_t*)ccec_ctx_x(ecPubkey); + require_quiet( NULL != xunit, fail); + xlen = (size_t)strlen((char*)xunit); + + + xString = CFStringCreateMutable(kCFAllocatorDefault, xlen * 2); + require_quiet( NULL != xString, fail); + + for (ix = 0; ix < xlen; ++ix) + { + CFStringAppendFormat(xString, NULL, CFSTR("%02X"), xunit[ix]); + } + + uint8_t *yunit = (uint8_t*)ccec_ctx_y(ecPubkey); + require_quiet( NULL != yunit, fail); + ylen = (size_t)strlen((char*)yunit); + + yString = CFStringCreateMutable(kCFAllocatorDefault, ylen*2); + require_quiet( NULL != yString, fail); + + for(ix = 0; ix < ylen; ++ix) + { + CFStringAppendFormat(yString, NULL, CFSTR("%02X"), yunit[ix]); + } + + keyDescription = CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR( ""), curve, (long)SecKeyGetAlgorithmID(key), key->key_class->name, key->key_class->version, (8*SecKeyGetBlockSize(key)), yString, xString, key); + +fail: + CFReleaseSafe(xString); + CFReleaseSafe(yString); + if(!keyDescription) + keyDescription = CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR(""), curve,(long)SecKeyGetAlgorithmID(key), key->key_class->name, key->key_class->version, (8*SecKeyGetBlockSize(key)), key); + + return keyDescription; +} + +static const struct ccec_rfc6637_curve * get_rfc6637_curve(SecKeyRef key) +{ + SecECNamedCurve curveType = SecECKeyGetNamedCurve(key); + + if (curveType == kSecECCurveSecp256r1) { + return &ccec_rfc6637_dh_curve_p256; + } else if (curveType == kSecECCurveSecp521r1) { + return &ccec_rfc6637_dh_curve_p521; + } + return NULL; +} + +static CFDataRef SecECKeyCopyWrapKey(SecKeyRef key, SecKeyWrapType type, CFDataRef unwrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error) +{ + ccec_pub_ctx_t pubkey; + int err = errSecUnimplemented; + const struct ccec_rfc6637_curve *curve; + const struct ccec_rfc6637_wrap *wrap = NULL; + uint8_t sym_alg = 0; + long flags = 0; + + pubkey.pub = key->key; + + if (type != kSecKeyWrapPublicKeyPGP) { + SecError(errSecUnsupportedOperation, error, CFSTR("unsupported key wrapping algorithm")); + return NULL; + } + + curve = get_rfc6637_curve(key); + if (curve == NULL) { + SecError(errSecUnsupportedOperation, error, CFSTR("unsupported curve")); + return NULL; + } + + CFNumberRef num = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPSymAlg); + if (!isNumber(num) || !CFNumberGetValue(num, kCFNumberSInt8Type, &sym_alg)) { + SecError(errSecUnsupportedOperation, error, CFSTR("unknown symalg given")); + return NULL; + } + + CFDataRef fingerprint = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPFingerprint); + if (!isData(fingerprint) || CFDataGetLength(fingerprint) < kSecKeyWrapPGPFingerprintMinSize) { + SecError(errSecUnsupportedOperation, error, CFSTR("invalid fingerprint")); + return NULL; + } + + CFTypeRef wrapAlg = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPWrapAlg); + if (wrapAlg == NULL) { + SecError(errSecUnsupportedOperation, error, CFSTR("no wrap alg")); + return NULL; + } else if (CFEqual(wrapAlg, _kSecKeyWrapRFC6637WrapDigestSHA256KekAES128)) { + wrap = &ccec_rfc6637_wrap_sha256_kek_aes128; + } else if (CFEqual(wrapAlg, _kSecKeyWrapRFC6637WrapDigestSHA512KekAES256)) { + wrap = &ccec_rfc6637_wrap_sha512_kek_aes256; + } else { + SecError(errSecUnsupportedOperation, error, CFSTR("unknown wrap alg")); + return NULL; + } + + num = CFDictionaryGetValue(parameters, _kSecKeyWrapRFC6637Flags); + if (isNull(num)) { + if (!CFNumberGetValue(num, kCFNumberLongType, &flags)) { + SecError(errSecUnsupportedOperation, error, CFSTR("invalid flags: %@"), num); + return NULL; + } + } else if (num) { + SecError(errSecUnsupportedOperation, error, CFSTR("unknown flags")); + return NULL; + } + + CFIndex unwrappedKey_size = CFDataGetLength(unwrappedKey); + + CFIndex output_size = ccec_rfc6637_wrap_key_size(pubkey, flags, unwrappedKey_size); + if (output_size == 0) { + SecError(errSecUnsupportedOperation, error, CFSTR("can't wrap that key, can't build size")); + return NULL; + } + + CFMutableDataRef data = CFDataCreateMutableWithScratch(NULL, output_size); + require(data, errOut); + + err = ccec_rfc6637_wrap_key(pubkey, CFDataGetMutableBytePtr(data), flags, + sym_alg, CFDataGetLength(unwrappedKey), CFDataGetBytePtr(unwrappedKey), + curve, wrap, CFDataGetBytePtr(fingerprint), + ccrng_seckey); + if (err) { + SecError(errSecUnsupportedOperation, error, CFSTR("Failed to wrap key")); + CFReleaseNull(data); + } + +errOut: + return data; +} + + +SecKeyDescriptor kSecECPublicKeyDescriptor = { + kSecKeyDescriptorVersion, + "ECPublicKey", + ccec_pub_ctx_size(ccn_sizeof(kMaximumECKeySize)), /* extraBytes */ + SecECPublicKeyInit, + SecECPublicKeyDestroy, + NULL, /* SecKeyRawSignMethod */ + SecECPublicKeyRawVerify, + SecECPublicKeyRawEncrypt, + NULL, /* SecKeyDecryptMethod */ + NULL, /* SecKeyComputeMethod */ + SecECPublicKeyBlockSize, + SecECPublicKeyCopyAttributeDictionary, + SecECPublicKeyCopyKeyDescription, + SecECKeyGetAlgorithmID, + SecECPublicKeyCopyPublicOctets, + SecECKeyCopyWrapKey, + NULL, /* SecKeyCopyUnwrapKey */ +}; + +/* Public Key API functions. */ +SecKeyRef SecKeyCreateECPublicKey(CFAllocatorRef allocator, + const uint8_t *keyData, CFIndex keyDataLength, + SecKeyEncoding encoding) { + return SecKeyCreate(allocator, &kSecECPublicKeyDescriptor, keyData, + keyDataLength, encoding); +} + + + +/* + * + * Private Key + * + */ + +/* Private key static functions. */ +static void SecECPrivateKeyDestroy(SecKeyRef key) { + /* Zero out the public key */ + ccec_full_ctx_t fullkey; + fullkey.hdr = key->key; + if (ccec_ctx_cp(fullkey).zp) + cc_zero(ccec_full_ctx_size(ccn_sizeof_n(ccec_ctx_n(fullkey))), fullkey.hdr); +} + + +static OSStatus SecECPrivateKeyInit(SecKeyRef key, + const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) { + ccec_full_ctx_t fullkey; + fullkey.hdr = key->key; + OSStatus err = errSecParam; + + switch (encoding) { + case kSecKeyEncodingPkcs1: + { + /* TODO: DER import size (and thus cp), pub.x, pub.y and k. */ + //err = ecc_import(keyData, keyDataLength, fullkey); + + /* DER != PKCS#1, but we'll go along with it */ + ccoid_t oid; + size_t n; + ccec_const_cp_t cp; + + require_noerr(ccec_der_import_priv_keytype(keyDataLength, keyData, &oid, &n), abort); + cp = ccec_cp_for_oid(oid); + if (cp.zp == NULL) { + cp = ccec_curve_for_length_lookup(n * 8 /* bytes -> bits */, + ccec_cp_192(), ccec_cp_224(), ccec_cp_256(), ccec_cp_384(), ccec_cp_521(), NULL); + } + require_action(cp.zp != NULL, abort, err = errSecDecode); + ccec_ctx_init(cp, fullkey); + + require_noerr(ccec_der_import_priv(cp, keyDataLength, keyData, fullkey), abort); + err = errSecSuccess; + break; + } + case kSecKeyEncodingBytes: + { + ccec_const_cp_t cp = getCPForPrivateSize(keyDataLength); + require(cp.zp != NULL, abort); + + ccec_ctx_init(cp, fullkey); + size_t pubSize = ccec_export_pub_size(fullkey); + + require(pubSize < (size_t) keyDataLength, abort); + require_noerr_action(ccec_import_pub(cp, pubSize, keyData, fullkey), + abort, + err = errSecDecode); + + + keyData += pubSize; + keyDataLength -= pubSize; + + cc_unit *k = ccec_ctx_k(fullkey); + require_noerr_action(ccn_read_uint(ccec_ctx_n(fullkey), k, keyDataLength, keyData), + abort, + err = errSecDecode); + + err = errSecSuccess; + break; + + } + case kSecGenerateKey: + { + CFDictionaryRef parameters = (CFDictionaryRef) keyData; + + CFTypeRef ksize = CFDictionaryGetValue(parameters, kSecAttrKeySizeInBits); + CFIndex keyLengthInBits = getIntValue(ksize); + + ccec_const_cp_t cp = ccec_get_cp(keyLengthInBits); + + if (!cp.zp) { + secwarning("Invalid or missing key size in: %@", parameters); + return errSecKeySizeNotAllowed; + } + + if (!ccec_generate_key(cp, ccrng_seckey, fullkey)) + err = errSecSuccess; + break; + } + + default: + break; + } +abort: + return err; +} + +static OSStatus SecECPrivateKeyRawSign(SecKeyRef key, SecPadding padding, + const uint8_t *dataToSign, size_t dataToSignLen, + uint8_t *sig, size_t *sigLen) { + ccec_full_ctx_t fullkey = {}; + fullkey.hdr = key->key; + int err; + require_action_quiet(sigLen, errOut, err = errSecParam); + require_noerr(err = ccec_sign(fullkey, dataToSignLen, dataToSign, + sigLen, sig, ccrng_seckey), errOut); +errOut: + + return err; +} + +#if 0 +static const struct ccdigest_info * +ccdigest_lookup_by_oid(unsigned long oid_size, const void *oid) { + static const struct ccdigest_info *dis[] = { + &ccsha1_di, + &ccsha224_di, + &ccsha256_di, + &ccsha384_di, + &ccsha512_di + }; + size_t i; + for (i = 0; i < array_size(dis); ++i) { + if (oid_size == dis[i]->oid_size && !memcmp(dis[i]->oid, oid, oid_size)) + return dis[i]; + } + return NULL; +} +#endif + +static OSStatus SecECPrivateKeyRawDecrypt(SecKeyRef key, SecPadding padding, + const uint8_t *cipherText, size_t cipherTextLen, + uint8_t *plainText, size_t *plainTextLen) { + ccec_full_ctx_t fullkey; + fullkey.hdr = key->key; + int err = errSecUnimplemented; + +#if 0 + err = ccec_unwrap_key(fullkey, ccrng_seckey, ccdigest_lookup_by_oid, + cipherTextLen, cipherText, plainTextLen, plainText); +#endif + + return err; +} + +static size_t SecECPrivateKeyBlockSize(SecKeyRef key) { + ccec_full_ctx_t fullkey; + fullkey.hdr = key->key; + /* Get key size in octets */ + return ccec_ctx_size(fullkey); +} + +static OSStatus SecECPrivateKeyCopyPublicOctets(SecKeyRef key, CFDataRef *serailziation) +{ + ccec_full_ctx_t fullkey; + fullkey.hdr = key->key; + + CFAllocatorRef allocator = CFGetAllocator(key); + *serailziation = SecECPublicKeyExport(allocator, fullkey); + + if (NULL == *serailziation) + return errSecDecode; + else + return errSecSuccess; +} + +static CFDataRef SecECPPrivateKeyExport(CFAllocatorRef allocator, + ccec_full_ctx_t fullkey) { + size_t prime_size = ccec_cp_prime_size(ccec_ctx_cp(fullkey)); + size_t key_size = ccec_export_pub_size(fullkey) + prime_size; + CFMutableDataRef blob = CFDataCreateMutable(allocator, key_size); + if (blob) { + CFDataSetLength(blob, key_size); + ccec_export_pub(fullkey, CFDataGetMutableBytePtr(blob)); + UInt8 *dest = CFDataGetMutableBytePtr(blob) + ccec_export_pub_size(fullkey); + const cc_unit *k = ccec_ctx_k(fullkey); + ccn_write_uint_padded(ccec_ctx_n(fullkey), k, prime_size, dest); + } + + return blob; +} + + +static CFDictionaryRef SecECPrivateKeyCopyAttributeDictionary(SecKeyRef key) { + CFDictionaryRef dict = NULL; + CFAllocatorRef allocator = CFGetAllocator(key); + + ccec_full_ctx_t fullkey; + fullkey.hdr = key->key; + + CFDataRef fullKeyBlob = NULL; + + /* Export the full ec key pair. */ + require(fullKeyBlob = SecECPPrivateKeyExport(allocator, fullkey), errOut); + + dict = SecKeyGeneratePrivateAttributeDictionary(key, kSecAttrKeyTypeEC, fullKeyBlob); + +errOut: + CFReleaseSafe(fullKeyBlob); + + return dict; +} +static CFStringRef SecECPrivateKeyCopyKeyDescription(SecKeyRef key) { + + const char* curve = getCurveName(key); + + return CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR( ""), curve, (long)SecKeyGetAlgorithmID(key), key->key_class->name, key->key_class->version, (8*SecKeyGetBlockSize(key)), key); + +} + +static CFDataRef SecECKeyCopyUnwrapKey(SecKeyRef key, SecKeyWrapType type, CFDataRef wrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error) +{ + const struct ccec_rfc6637_curve *curve; + const struct ccec_rfc6637_unwrap *unwrap; + ccec_full_ctx_t fullkey; + CFMutableDataRef data; + int res; + uint8_t sym_alg = 0; + unsigned long flags = 0; + + fullkey.hdr = key->key; + + curve = get_rfc6637_curve(key); + if (curve == NULL) { + SecError(errSecUnsupportedOperation, error, CFSTR("unsupported curve")); + return NULL; + } + + CFTypeRef wrapAlg = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPWrapAlg); + if (wrapAlg == NULL) { + SecError(errSecUnsupportedOperation, error, CFSTR("no wrap alg")); + return NULL; + } else if (CFEqual(wrapAlg, _kSecKeyWrapRFC6637WrapDigestSHA256KekAES128)) { + unwrap = &ccec_rfc6637_unwrap_sha256_kek_aes128; + } else if (CFEqual(wrapAlg, _kSecKeyWrapRFC6637WrapDigestSHA512KekAES256)) { + unwrap = &ccec_rfc6637_unwrap_sha512_kek_aes256; + } else { + SecError(errSecUnsupportedOperation, error, CFSTR("unknown wrap alg")); + return NULL; + } + + CFDataRef fingerprint = CFDictionaryGetValue(parameters, _kSecKeyWrapPGPFingerprint); + if (!isData(fingerprint) || CFDataGetLength(fingerprint) < kSecKeyWrapPGPFingerprintMinSize) { + SecError(errSecUnsupportedOperation, error, CFSTR("invalid fingerprint")); + return NULL; + } + + CFNumberRef num = CFDictionaryGetValue(parameters, _kSecKeyWrapRFC6637Flags); + if (isNull(num)) { + if (!CFNumberGetValue(num, kCFNumberSInt32Type, &num)) { + SecError(errSecUnsupportedOperation, error, CFSTR("invalid flags: %@"), num); + return NULL; + } + } else if (num) { + SecError(errSecUnsupportedOperation, error, CFSTR("unknown flags")); + return NULL; + } + + size_t keysize = CFDataGetLength(wrappedKey); + data = CFDataCreateMutableWithScratch(NULL, keysize); + if (data == NULL) + return NULL; + + res = ccec_rfc6637_unwrap_key(fullkey, &keysize, CFDataGetMutableBytePtr(data), + flags, &sym_alg, curve, unwrap, + CFDataGetBytePtr(fingerprint), + CFDataGetLength(wrappedKey), CFDataGetBytePtr(wrappedKey)); + if (res != 0) { + CFReleaseNull(data); + SecError(errSecUnsupportedOperation, error, CFSTR("failed to wrap key")); + return NULL; + } + assert(keysize <= (size_t)CFDataGetLength(data)); + CFDataSetLength(data, keysize); + + if (outParam) { + CFMutableDictionaryRef out = CFDictionaryCreateMutableForCFTypes(NULL); + if (out) { + CFNumberRef num = CFNumberCreate(NULL, kCFNumberSInt8Type, &sym_alg); + if (num) { + CFDictionarySetValue(out, _kSecKeyWrapPGPSymAlg, num); + CFRelease(num); + } + *outParam = out; + } + } + + return data; +} + + +SecKeyDescriptor kSecECPrivateKeyDescriptor = { + kSecKeyDescriptorVersion, + "ECPrivateKey", + ccec_full_ctx_size(ccn_sizeof(kMaximumECKeySize)), /* extraBytes */ + SecECPrivateKeyInit, + SecECPrivateKeyDestroy, + SecECPrivateKeyRawSign, + NULL, /* SecKeyRawVerifyMethod */ + NULL, /* SecKeyEncryptMethod */ + SecECPrivateKeyRawDecrypt, + NULL, /* SecKeyComputeMethod */ + SecECPrivateKeyBlockSize, + SecECPrivateKeyCopyAttributeDictionary, + SecECPrivateKeyCopyKeyDescription, + SecECKeyGetAlgorithmID, + SecECPrivateKeyCopyPublicOctets, + SecECKeyCopyWrapKey, + SecECKeyCopyUnwrapKey, +}; + +/* Private Key API functions. */ +SecKeyRef SecKeyCreateECPrivateKey(CFAllocatorRef allocator, + const uint8_t *keyData, CFIndex keyDataLength, + SecKeyEncoding encoding) { + return SecKeyCreate(allocator, &kSecECPrivateKeyDescriptor, keyData, + keyDataLength, encoding); +} + + +OSStatus SecECKeyGeneratePair(CFDictionaryRef parameters, + SecKeyRef *publicKey, SecKeyRef *privateKey) { + OSStatus status = errSecParam; + + CFAllocatorRef allocator = NULL; /* @@@ get from parameters. */ + SecKeyRef pubKey = NULL; + + SecKeyRef privKey = SecKeyCreate(allocator, &kSecECPrivateKeyDescriptor, + (const void*) parameters, 0, kSecGenerateKey); + + require(privKey, errOut); + + /* Create SecKeyRef's from the pkcs1 encoded keys. */ + pubKey = SecKeyCreate(allocator, &kSecECPublicKeyDescriptor, + privKey->key, 0, kSecExtractPublicFromPrivate); + + require(pubKey, errOut); + + if (publicKey) { + *publicKey = pubKey; + pubKey = NULL; + } + if (privateKey) { + *privateKey = privKey; + privKey = NULL; + } + + status = errSecSuccess; + +errOut: + CFReleaseSafe(pubKey); + CFReleaseSafe(privKey); + + return status; +} + + +/* It's debatable whether this belongs here or in the ssl code since the + curve values come from a tls related rfc4492. */ +SecECNamedCurve SecECKeyGetNamedCurve(SecKeyRef key) { + if (key->key_class != &kSecECPublicKeyDescriptor && + key->key_class != &kSecECPrivateKeyDescriptor) + return kSecECCurveNone; + + ccec_pub_ctx_t pubkey; + pubkey.pub = key->key; + switch (ccec_ctx_size(pubkey)) { +#if 0 + case 24: + return kSecECCurveSecp192r1; + case 28: + return kSecECCurveSecp224r1; +#endif + case 32: + return kSecECCurveSecp256r1; + case 48: + return kSecECCurveSecp384r1; + case 66: + return kSecECCurveSecp521r1; + } + return kSecECCurveNone; +} + +CFDataRef SecECKeyCopyPublicBits(SecKeyRef key) { + if (key->key_class != &kSecECPublicKeyDescriptor && + key->key_class != &kSecECPrivateKeyDescriptor) + return NULL; + + ccec_pub_ctx_t pubkey; + pubkey.pub = key->key; + return SecECPublicKeyExport(CFGetAllocator(key), pubkey); +} + +/* Vile accessors that get us the pub or priv key to use temporarily */ + +bool SecECDoWithFullKey(SecKeyRef key, CFErrorRef* error, void (^action)(ccec_full_ctx_t private)) { + if (key->key_class == &kSecECPrivateKeyDescriptor) { + action(key->key); + } else { + return SecError(errSecParam, error, CFSTR("Not an EC Full Key object, sorry can't do.")); + } + + return true; +} + +bool SecECDoWithPubKey(SecKeyRef key, CFErrorRef* error, void (^action)(ccec_pub_ctx_t public)) { + if (key->key_class == &kSecECPublicKeyDescriptor) { + action(key->key); + } else { + return SecError(errSecParam, error, CFSTR("Not an EC Public Key object, sorry can't do.")); + } + + return true; +} + diff --git a/sec/Security/SecECKey.h b/Security/sec/Security/SecECKey.h similarity index 92% rename from sec/Security/SecECKey.h rename to Security/sec/Security/SecECKey.h index 2433818f..27df9ffc 100644 --- a/sec/Security/SecECKey.h +++ b/Security/sec/Security/SecECKey.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2010,2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -43,6 +43,10 @@ typedef struct SecECPublicKeyParams { CFIndex exponentLength; } SecECPublicKeyParams; +enum { + kSecPaddingECIES_SHA2_AES128GCM_MAC128 = 0x9000, /* EC Key Using IESGCM to encrypt */ +}; + /* Given an EC public key in encoded form return a SecKeyRef representing that key. Supported encodings are kSecKeyEncodingPkcs1. */ SecKeyRef SecKeyCreateECPublicKey(CFAllocatorRef allocator, @@ -55,10 +59,6 @@ SecKeyRef SecKeyCreateECPrivateKey(CFAllocatorRef allocator, const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding); -/* @@@ Private @@@ */ -OSStatus SecECKeyGeneratePair(CFDictionaryRef parameters, - SecKeyRef *rsaPublicKey, SecKeyRef *rsaPrivateKey); - /* These are the named curves we support. These values come from RFC 4492 section 5.1.1, with the exception of SSL_Curve_None which means "ECDSA not negotiated". */ @@ -74,6 +74,7 @@ typedef enum SecECNamedCurve SecECKeyGetNamedCurve(SecKeyRef ecPrivateKey); CFDataRef SecECKeyCopyPublicBits(SecKeyRef key); + __END_DECLS #endif /* !_SECURITY_SECECKEY_H_ */ diff --git a/Security/sec/Security/SecECKeyPriv.h b/Security/sec/Security/SecECKeyPriv.h new file mode 100644 index 00000000..f9af3d2c --- /dev/null +++ b/Security/sec/Security/SecECKeyPriv.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef _SECURITY_SECECKEYPRIV_H_ +#define _SECURITY_SECECKEYPRIV_H_ + +#include +#include + +__BEGIN_DECLS + +OSStatus SecECKeyGeneratePair(CFDictionaryRef parameters, + SecKeyRef *rsaPublicKey, SecKeyRef *rsaPrivateKey); + +/* Vile accessors to enable stream encryption until + we have better APIs for encryption with EC keys */ +bool SecECDoWithFullKey(SecKeyRef key, CFErrorRef* error,void (^action)(ccec_full_ctx_t full_key)); +bool SecECDoWithPubKey(SecKeyRef key, CFErrorRef* error, void (^action)(ccec_pub_ctx_t pub_key)); + +__END_DECLS + +#endif /* !_SECURITY_SECECKEYPRIV_H_ */ diff --git a/sec/Security/SecExports.exp-in b/Security/sec/Security/SecExports.exp-in similarity index 92% rename from sec/Security/SecExports.exp-in rename to Security/sec/Security/SecExports.exp-in index 58479bd7..35fd8cfb 100644 --- a/sec/Security/SecExports.exp-in +++ b/Security/sec/Security/SecExports.exp-in @@ -1,8 +1,6 @@ // SecExports.exp-in // sec // -// Created by Mitch Adler on 4/2/13. -// // // CFError to OSStatus conversion @@ -31,6 +29,7 @@ _kSecPasswordSeparator _kSecPasswordCharacterCount _kSecPasswordCharacters _SecPasswordIsPasswordWeak +_SecPasswordIsPasswordWeak2 _SecPasswordGenerate _SecPasswordCopyDefaultPasswordLength @@ -61,8 +60,11 @@ _kSecPolicyAppleTestMobileStore _kSecPolicyAppleOTAPKISigner _kSecPolicyAppleTestOTAPKISigner _kSecPolicyAppleEscrowService +_kSecPolicyApplePCSEscrowService _kSecPolicyAppleProfileSigner _kSecPolicyAppleQAProfileSigner +_kSecPolicyAppleSMPEncryption +_kSecPolicyAppleTestSMPEncryption _kSecPolicyCheckAnchorSHA1 _kSecPolicyCheckAnchorTrusted _kSecPolicyCheckBasicCertificateProcessing @@ -110,7 +112,13 @@ _SecPolicyCreate _SecPolicyCreateAppleIDAuthorityPolicy #if TARGET_OS_IPHONE _SecPolicyCreateAppleIDValidationRecordSigningPolicy +_SecPolicyCreateAppleSMPEncryption +_SecPolicyCreateTestAppleSMPEncryption #endif +_SecPolicyCreateAppleIDSService +_SecPolicyCreateApplePushService +_SecPolicyCreateAppleMMCSService +_SecPolicyCreateAppleSSLService _SecPolicyCreateBasicX509 _SecPolicyCreateCodeSigning _SecPolicyCreateConfigurationProfileSigner @@ -121,6 +129,7 @@ _SecPolicyCreateTestOTAPKISigner #endif _SecPolicyCreateEAP _SecPolicyCreateEscrowServiceSigner +_SecPolicyCreatePCSEscrowServiceSigner _SecPolicyCreateFactoryDeviceCertificate _SecPolicyCreateIPSec _SecPolicyCreateMobileStoreSigner @@ -222,6 +231,7 @@ _SecIdentitySignCertificate _kSecCertificateKeyUsage _kSecCertificateExtensions +_kSecCertificateExtensionsEncoded _SecCertificateCopyCommonNames _SecCertificateCopyCompanyName _SecCertificateCopyEscrowRoots @@ -292,6 +302,7 @@ _SecCertificatePathSetSelfIssued _SecCertificatePathVerify _SecCertificateVersion _kSecCertificateProductionEscrowKey +_kSecCertificateProductionPCSEscrowKey _kSecCertificateEscrowFileName // @@ -346,6 +357,8 @@ _SecOTRPublicIdentityCopyFromPrivate _SecOTRPublicIdentityCreateFromData _SecOTRPublicIdentityCreateFromSecKeyRef _SecOTRPacketTypeString +_SecOTRSessionCreateRemote +_SecOTRSessionProcessPacketRemote // // DH @@ -355,7 +368,9 @@ _SecDHComputeKey _SecDHCreate _SecDHCreateFromAlgorithmId _SecDHCreateFromParameters +_SecDHDecodeParams _SecDHDestroy +_SecDHEncodeParams _SecDHGenerateKeypair _SecDHGetMaxKeyLength @@ -373,11 +388,18 @@ _kSecXPCKeyPeerInfos _kSecXPCKeyOperation _kSecXPCKeyResult _kSecXPCKeyError +_kSecXPCKeyClientToken _kSecXPCKeyUserLabel _kSecXPCKeyUserPassword _sSecXPCErrorDomain _kSecXPCKeyOTAFileDirectory +// +// Logging +// + +_SecGetCurrentServerLoggingInfo +_SecSetLoggingInfoForXPCScope // // CMS @@ -510,9 +532,14 @@ _SecKeyFromPassphraseDataHMACSHA1 // // Key // - +_SecECDoWithFullKey +_SecECDoWithPubKey +_SecECKeyCopyPublicBits +_SecECKeyGetNamedCurve _SecKeyCopyAttributeDictionary +_SecKeyCopyExponent _SecKeyCopyMatchingPrivateKey +_SecKeyCopyModulus _SecKeyCopyPersistentRef _SecKeyCopyPublicBytes _SecKeyCreate @@ -537,8 +564,18 @@ _SecKeyGetSize _SecKeyGetTypeID _SecKeyRawSign _SecKeyRawVerify +_SecKeySignDigest +_SecKeyVerifyDigest _kSecPrivateKeyAttrs _kSecPublicKeyAttrs +__SecKeyCopyWrapKey +__SecKeyCopyUnwrapKey +__kSecKeyWrapPGPSymAlg +__kSecKeyWrapPGPFingerprint +__kSecKeyWrapPGPWrapAlg +__kSecKeyWrapRFC6637WrapDigestSHA256KekAES128 +__kSecKeyWrapRFC6637WrapDigestSHA512KekAES256 +__kSecKeyWrapRFC6637Flags // // Keychain/SecItem @@ -553,6 +590,7 @@ _kSecAttrAccessibleWhenUnlocked _kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly _kSecAttrAccessibleAlwaysThisDeviceOnly _kSecAttrAccessibleWhenUnlockedThisDeviceOnly +_kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly _kSecAttrAccount _kSecAttrAddress _kSecAttrAlias @@ -702,9 +740,17 @@ __SecItemParsePersistentRef __SecKeychainCopyBackup __SecKeychainCopyOTABackup __SecKeychainRestoreBackup -__SecKeychainSyncUpdate +__SecKeychainSyncUpdateKeyParameter +__SecKeychainSyncUpdateCircle +__SecKeychainSyncUpdateMessage __SecKeychainBackupSyncable __SecKeychainRestoreSyncable +__SecKeychainRollKeys + +_SecAddSharedWebCredential +_SecRequestSharedWebCredential +_SecCreateSharedWebCredentialPassword +_kSecSharedPassword _kSecXPCKeyAttributesToUpdate _kSecXPCKeyBackup @@ -714,8 +760,21 @@ _kSecXPCKeyDomain _kSecXPCKeyKeybag _kSecXPCKeyQuery _kSecXPCKeySettings +_kSecXPCPublicPeerId +_kSecXPCOTRSession +_kSecXPCData +_kSecXPCOTRReady +_kSecXPCKeyDeviceID _SecCertificatePathCopyXPCArray _SecCertificateXPCArrayCopyArray _SecPolicyXPCArrayCopyArray _SecServerSetMachServiceName + +// +// ServerEncryption +// + +_SecCopyEncryptedToServer +_SecCopyEncryptedToServerKey +_SecCopyDecryptedForServer diff --git a/sec/Security/SecFramework.c b/Security/sec/Security/SecFramework.c similarity index 80% rename from sec/Security/SecFramework.c rename to Security/sec/Security/SecFramework.c index b9a4bf5f..3c4f7d06 100644 --- a/sec/Security/SecFramework.c +++ b/Security/sec/Security/SecFramework.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2010,2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -32,7 +32,7 @@ #endif #include "SecFramework.h" -#include +#include #include #include #include @@ -44,41 +44,41 @@ #include #include #include +#include #include #include #include +#if !(TARGET_IPHONE_SIMULATOR && defined(IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED) && IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED < 1090) +#include +#define USE_GUARDED_OPEN 1 +#else +#define USE_GUARDED_OPEN 0 +#endif + + /* 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; - -static void SecFrameworkBundleLookup(void) { - kSecFrameworkBundle = CFBundleGetBundleWithIdentifier(kSecFrameworkBundleID); - if (kSecFrameworkBundle) - CFRetain(kSecFrameworkBundle); -} +CFGiblisGetSingleton(CFBundleRef, SecFrameworkGetBundle, bundle, ^{ + *bundle = CFRetainSafe(CFBundleGetBundleWithIdentifier(kSecFrameworkBundleID)); +}) CFStringRef SecFrameworkCopyLocalizedString(CFStringRef key, CFStringRef tableName) { - pthread_once(&kSecFrameworkBundleLookup, SecFrameworkBundleLookup); - if (kSecFrameworkBundle) { - return CFBundleCopyLocalizedString(kSecFrameworkBundle, key, key, - tableName); - } + CFBundleRef bundle = SecFrameworkGetBundle(); + if (bundle) + return CFBundleCopyLocalizedString(bundle, key, key, tableName); - CFRetain(key); - return key; + return CFRetainSafe(key); } CFURLRef SecFrameworkCopyResourceURL(CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName) { CFURLRef url = NULL; - pthread_once(&kSecFrameworkBundleLookup, SecFrameworkBundleLookup); - if (kSecFrameworkBundle) { - url = CFBundleCopyResourceURL(kSecFrameworkBundle, resourceName, + CFBundleRef bundle = SecFrameworkGetBundle(); + if (bundle) { + url = CFBundleCopyResourceURL(bundle, resourceName, resourceType, subDirName); if (!url) { secwarning("resource: %@.%@ in %@ not found", resourceName, @@ -89,7 +89,6 @@ CFURLRef SecFrameworkCopyResourceURL(CFStringRef resourceName, return url; } - CFDataRef SecFrameworkCopyResourceContents(CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName) { CFURLRef url = SecFrameworkCopyResourceURL(resourceName, resourceType, @@ -150,38 +149,14 @@ CFDataRef SecDigestCreate(CFAllocatorRef allocator, return digest; } -/* Default random ref for /dev/random. */ -const SecRandomRef kSecRandomDefault = NULL; -/* File descriptor for "/dev/random". */ -static int kSecRandomFD; -static pthread_once_t kSecDevRandomOpen = PTHREAD_ONCE_INIT; - -static void SecDevRandomOpen(void) { - kSecRandomFD = open("/dev/random", O_RDONLY); -} +#include +const SecRandomRef kSecRandomDefault = NULL; int SecRandomCopyBytes(SecRandomRef rnd, size_t count, uint8_t *bytes) { if (rnd != kSecRandomDefault) return errSecParam; - pthread_once(&kSecDevRandomOpen, SecDevRandomOpen); - if (kSecRandomFD < 0) - return -1; - while (count) { - ssize_t bytes_read = read(kSecRandomFD, bytes, count); - if (bytes_read == -1) { - if (errno == EINTR) - continue; - return -1; - } - if (bytes_read == 0) { - return -1; - } - bytes += bytes_read; - count -= bytes_read; - } - - return 0; + return CCRandomCopyBytes(kCCRandomDefault, bytes, count); } #if 0 diff --git a/sec/Security/SecFramework.h b/Security/sec/Security/SecFramework.h similarity index 96% rename from sec/Security/SecFramework.h rename to Security/sec/Security/SecFramework.h index 6b1f6e0e..56bd0168 100644 --- a/sec/Security/SecFramework.h +++ b/Security/sec/Security/SecFramework.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007,2009-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2007,2009-2010,2012-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/sec/Security/SecFrameworkStrings.h b/Security/sec/Security/SecFrameworkStrings.h similarity index 92% rename from sec/Security/SecFrameworkStrings.h rename to Security/sec/Security/SecFrameworkStrings.h index 51f847e8..41674589 100644 --- a/sec/Security/SecFrameworkStrings.h +++ b/Security/sec/Security/SecFrameworkStrings.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2009,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, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -181,32 +181,33 @@ __BEGIN_DECLS #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_CK_PASSWORD_INCORRECT SecStringWithDefaultValue("iCloud Password incorrect, try again", "CloudKeychain", 0, "iCloud password is incorrect, try again", "Title for alert when password has been entered incorrectly") +#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") #define SEC_CK_ALLOW SecStringWithDefaultValue("Allow", "CloudKeychain", 0, "Allow", "Allow button") #define SEC_CK_DONT_ALLOW SecStringWithDefaultValue("Don't Allow", "CloudKeychain", 0, "Don't Allow", "Don't Allow button") -#define SEC_CK_ICLOUD_PASSWORD SecStringWithDefaultValue("Password", "CloudKeychain", 0, "Password", "Password prompt text") -#define SEC_CK_JOIN_PROMPT SecStringWithDefaultValue("Enter the Apple ID password for “%@” to allow %@ to use iCloud Keychain.", "CloudKeychain", 0, "Enter the Apple ID password for “%@” to allow %@ to use iCloud Keychain.", "Message for alert when a new device is joining the circle") -#define SEC_CK_JOIN_TITLE SecStringWithDefaultValue("Allow “%@” to use your passwords?", "CloudKeychain", 0, "Allow “%@” to use iCloud Keychain?", "Title for alert when a new device is joining the circle") +#define SEC_CK_ICLOUD_PASSWORD SecStringWithDefaultValue("Password", "CloudKeychain", 0, "password", "Password prompt text") +#define SEC_CK_JOIN_PROMPT SecStringWithDefaultValue("Enter the Apple ID password for “%@” to allow this new %@ to use your passwords.", "CloudKeychain", 0, "Enter the Apple ID password for “%@” to allow this new %@ to use your passwords.", "Message for alert when a new device is joining the circle") +#define SEC_CK_JOIN_TITLE SecStringWithDefaultValue("Allow “%@” to Use iCloud Keychain?", "CloudKeychain", 0, "Allow “%@” to Use iCloud Keychain?", "Title for alert when a new device is joining the circle") #define SEC_CK_ARS0_TITLE SecStringWithDefaultValue("Waiting for Approval to Use iCloud Keychain", "CloudKeychain", 0, "Waiting for Approval to Use iCloud Keychain", "Title for alert when this device's application has been pending for a long time & no security code is set") -#define SEC_CK_ARS0_BODY SecStringWithDefaultValue("%@ must be approved from one of your other devices using iCloud Keychain. If no other devices are available, reset iCloud Keychain in Settings.%@", "CloudKeychain", 0, "%@ must be approved from one of your other devices using iCloud Keychain. If no other devices are available, reset iCloud Keychain in Settings.%@", "Explanation of the waiting for approval alert") +#define SEC_CK_ARS0_BODY SecStringWithDefaultValue("%@ must be approved from one of your other devices using iCloud Keychain. If no other devices are available, reset iCloud Keychain in Settings.", "CloudKeychain", 0, "%@ must be approved from one of your other devices using iCloud Keychain. If no other devices are available, reset iCloud Keychain in Settings.", "Explanation of the waiting for approval alert") #define SEC_CK_ARS1_TITLE SecStringWithDefaultValue("Use Security Code to Turn On iCloud Keychain?", "CloudKeychain", 0, "Use Security Code to Turn On iCloud Keychain?", "Title for alert when this device's application has been pending for a long time & a security code is set") -#define SEC_CK_ARS1_BODY SecStringWithDefaultValue("This iPhone is still waiting for approval from one of your other devices using iCloud Keychain. You can use your Security Code to turn on iCloud Keychain.%@", "CloudKeychain", 0, "This iPhone is still waiting for approval from one of your other devices using iCloud Keychain. You can use your Security Code to turn on iCloud Keychain.%@", "Explanation of the waiting for approval alert") +#define SEC_CK_ARS1_BODY SecStringWithDefaultValue("%@ is still waiting for approval from one of your other devices using iCloud Keychain. You can use your Security Code to turn on iCloud Keychain.", "CloudKeychain", 0, "%@ is still waiting for approval from one of your other devices using iCloud Keychain. You can use your Security Code to turn on iCloud Keychain.", "Explanation of the waiting for approval alert") #define SEC_CK_AR_APPROVE_OTHER SecStringWithDefaultValue("Approve with Other Device", "CloudKeychain", 0, "Approve with Other Device", "Button text for approval with other device") #define SEC_CK_AR_USE_CODE SecStringWithDefaultValue("Use Security Code", "CloudKeychain", 0, "Use Security Code", "Button text for approval via security code") #define SEC_CK_TID_FUTURE SecStringWithDefaultValue("the future", "CloudKeychain", 0, "the future", "the future") #define SEC_CK_TID_NOW SecStringWithDefaultValue("now", "CloudKeychain", 0, "now", "now") -#define SEC_CK_TID_SUBSECOND SecStringWithDefaultValue("less then a second", "CloudKeychain", 0, "less then a second", "Less then then one second") -#define SEC_CK_TID_SECONDS SecStringWithDefaultValue("seconds", "CloudKeychain", 0, "seconds", "More then one second") -#define SEC_CK_TID_MINUTES SecStringWithDefaultValue("minutes", "CloudKeychain", 0, "minutes", "More then one minute") -#define SEC_CK_TID_HOURS SecStringWithDefaultValue("hours", "CloudKeychain", 0, "hours", "More then one hour") +#define SEC_CK_TID_SUBSECOND SecStringWithDefaultValue("less than a second", "CloudKeychain", 0, "less than a second", "Less then then one second") +#define SEC_CK_TID_SECONDS SecStringWithDefaultValue("seconds", "CloudKeychain", 0, "seconds", "More than one second") +#define SEC_CK_TID_MINUTES SecStringWithDefaultValue("minutes", "CloudKeychain", 0, "minutes", "More than one minute") +#define SEC_CK_TID_HOURS SecStringWithDefaultValue("hours", "CloudKeychain", 0, "hours", "More than one hour") #define SEC_CK_TID_DAY SecStringWithDefaultValue("day", "CloudKeychain", 0, "day", "One day") -#define SEC_CK_TID_DAYS SecStringWithDefaultValue("days", "CloudKeychain", 0, "days", "More then one day") +#define SEC_CK_TID_DAYS SecStringWithDefaultValue("days", "CloudKeychain", 0, "days", "More than one day") #define SEC_CK_CR_TITLE SecStringWithDefaultValue("iCloud Keychain Reset", "CloudKeychain", 0, "iCloud Keychain Reset", "Title for alert when this device has left the circle") #define SEC_CK_CR_BODY_REVOKED SecStringWithDefaultValue("%@ is no longer participating in iCloud Keychain because it was reset by another device", "CloudKeychain", 0, "%@ is no longer participating in iCloud Keychain because it was reset by another device", "Body text for kSOSMembershipRevoked") -#define SEC_CK_CR_BODY_LEFT_UNTRUSTED SecStringWithDefaultValue("%@ is no longer participating in iCloud Keychain!", "CloudKeychain", 0, "%@ is no longer participating in iCloud Keychain!", "Body text for kSOSLeftUntrustedCircle") +#define SEC_CK_CR_BODY_LEFT_UNTRUSTED SecStringWithDefaultValue("%@ is no longer participating in iCloud Keychain.", "CloudKeychain", 0, "%@ is no longer participating in iCloud Keychain.", "Body text for kSOSLeftUntrustedCircle") #define SEC_CK_CR_BODY_UNKNOWN SecStringWithDefaultValue("%@ is no longer participating in iCloud Keychain.", "CloudKeychain", 0, "%@ is no longer participating in iCloud Keychain.", "Body text for unknown departure reason") #define SEC_CK_CR_OK SecStringWithDefaultValue("OK", "CloudKeychain", 0, "OK", "Button text for confused user who just wants the alert to go away") #define SEC_CK_CR_USE_CODE SecStringWithDefaultValue("Use Security Code", "CloudKeychain", 0, "Use Security Code", "Button text for approval via security code") diff --git a/Security/sec/Security/SecIdentity.c b/Security/sec/Security/SecIdentity.c new file mode 100644 index 00000000..7668a5e9 --- /dev/null +++ b/Security/sec/Security/SecIdentity.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2002-2004,2007-2008,2010,2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * SecIdentity.c - CoreFoundation based object containing a + * private key, certificate tuple. + */ + + +#include + +#include +#include +#include +#include +#include +#include "SecIdentityPriv.h" +#include +#include + +struct __SecIdentity { + CFRuntimeBase _base; + SecCertificateRef _certificate; + SecKeyRef _privateKey; +}; + +CFGiblisWithHashFor(SecIdentity) + +/* Static functions. */ +static CFStringRef SecIdentityCopyDescription(CFTypeRef cf) { + SecIdentityRef identity = (SecIdentityRef)cf; + return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, + CFSTR(""), identity); +} + +static void SecIdentityDestroy(CFTypeRef cf) { + SecIdentityRef identity = (SecIdentityRef)cf; + CFReleaseSafe(identity->_certificate); + CFReleaseSafe(identity->_privateKey); +} + +static Boolean SecIdentityCompare(CFTypeRef cf1, CFTypeRef cf2) { + SecIdentityRef identity1 = (SecIdentityRef)cf1; + SecIdentityRef identity2 = (SecIdentityRef)cf2; + if (identity1 == identity2) + return true; + if (!identity2) + return false; + return CFEqual(identity1->_certificate, identity2->_certificate) && + CFEqual(identity1->_privateKey, identity2->_privateKey); +} + +/* Hash of identity is hash of certificate plus hash of key. */ +static CFHashCode SecIdentityHash(CFTypeRef cf) { + SecIdentityRef identity = (SecIdentityRef)cf; + return CFHash(identity->_certificate) + CFHash(identity->_privateKey); +} + +OSStatus SecIdentityCopyCertificate(SecIdentityRef identity, + SecCertificateRef *certificateRef) { + *certificateRef = identity->_certificate; + CFRetain(*certificateRef); + return 0; +} + +OSStatus SecIdentityCopyPrivateKey(SecIdentityRef identity, + SecKeyRef *privateKeyRef) { + *privateKeyRef = identity->_privateKey; + CFRetain(*privateKeyRef); + return 0; +} + +SecIdentityRef SecIdentityCreate(CFAllocatorRef allocator, + SecCertificateRef certificate, SecKeyRef privateKey) { + CFIndex size = sizeof(struct __SecIdentity); + SecIdentityRef result = (SecIdentityRef)_CFRuntimeCreateInstance( + allocator, SecIdentityGetTypeID(), size - sizeof(CFRuntimeBase), 0); + if (result) { + CFRetain(certificate); + CFRetain(privateKey); + result->_certificate = certificate; + result->_privateKey = privateKey; + } + return result; +} + diff --git a/Security/sec/Security/SecIdentity.h b/Security/sec/Security/SecIdentity.h new file mode 100644 index 00000000..83cb3ddf --- /dev/null +++ b/Security/sec/Security/SecIdentity.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2002-2004,2007-2009,2012-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@ + */ + +/*! + @header SecIdentity + The functions provided in SecIdentity.h implement a convenient way to + match private keys with certificates. +*/ + +#ifndef _SECURITY_SECIDENTITY_H_ +#define _SECURITY_SECIDENTITY_H_ + +#include +#include + +__BEGIN_DECLS + +/*! + @function SecIdentityGetTypeID + @abstract Returns the type identifier of SecIdentity instances. + @result The CFTypeID of SecIdentity instances. +*/ +CFTypeID SecIdentityGetTypeID(void) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +/*! + @function SecIdentityCopyCertificate + @abstract Returns a reference to a certificate for the given identity + reference. + @param identityRef An identity reference. + @param certificateRef On return, a pointer to the found certificate + reference. + @result A result code. See "Security Error Codes" (SecBase.h). +*/ +OSStatus SecIdentityCopyCertificate( + SecIdentityRef identityRef, + SecCertificateRef *certificateRef) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +/*! + @function SecIdentityCopyPrivateKey + @abstract Returns the private key associated with an identity. + @param identityRef An identity reference. + @param privateKeyRef On return, a pointer to the private key for the given + identity. The private key must be of class type kSecAppleKeyItemClass. + @result A result code. See "Security Error Codes" (SecBase.h). +*/ +OSStatus SecIdentityCopyPrivateKey( + SecIdentityRef identityRef, + SecKeyRef *privateKeyRef) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +__END_DECLS + +#endif /* !_SECURITY_SECIDENTITY_H_ */ diff --git a/Security/sec/Security/SecIdentityPriv.h b/Security/sec/Security/SecIdentityPriv.h new file mode 100644 index 00000000..8d39dd20 --- /dev/null +++ b/Security/sec/Security/SecIdentityPriv.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2007-2008,2010,2012-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@ + */ + +/*! + @header SecIdentityPriv + The functions provided in SecIdentityPriv.h implement a convenient way to + match private keys with certificates. +*/ + +#ifndef _SECURITY_SECIDENTITYPRIV_H_ +#define _SECURITY_SECIDENTITYPRIV_H_ + +#include +#include + +__BEGIN_DECLS + +/*! @function SecIdentityCreate. + @abstract create a new identity object from the passed-in certificate + and private key. + @discussion this function will most likely become private SPI soon. +*/ +SecIdentityRef SecIdentityCreate(CFAllocatorRef allocator, + SecCertificateRef certificate, SecKeyRef privateKey); + +__END_DECLS + +#endif /* !_SECURITY_SECIDENTITYPRIV_H_ */ diff --git a/Security/sec/Security/SecImportExport.c b/Security/sec/Security/SecImportExport.c new file mode 100644 index 00000000..65670d02 --- /dev/null +++ b/Security/sec/Security/SecImportExport.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2007-2008,2012-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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "p12import.h" +#include "SecImportExport.h" + +CFStringRef kSecImportExportPassphrase = CFSTR("passphrase"); +CFStringRef kSecImportItemLabel = CFSTR("label"); +CFStringRef kSecImportItemKeyID = CFSTR("keyid"); +CFStringRef kSecImportItemTrust = CFSTR("trust"); +CFStringRef kSecImportItemCertChain = CFSTR("chain"); +CFStringRef kSecImportItemIdentity = CFSTR("identity"); + + +static void collect_certs(const void *key, const void *value, void *context) +{ + if (!CFDictionaryContainsKey(value, CFSTR("key"))) { + CFDataRef cert_bytes = CFDictionaryGetValue(value, CFSTR("cert")); + if (!cert_bytes) + return; + SecCertificateRef cert = + SecCertificateCreateWithData(kCFAllocatorDefault, cert_bytes); + if (!cert) + return; + CFMutableArrayRef cert_array = (CFMutableArrayRef)context; + CFArrayAppendValue(cert_array, cert); + CFRelease(cert); + } +} + +typedef struct { + CFMutableArrayRef identities; + CFArrayRef certs; +} build_trust_chains_context; + +static void build_trust_chains(const void *key, const void *value, + void *context) +{ + CFMutableDictionaryRef identity_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, + 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + SecKeyRef private_key = NULL; + SecCertificateRef cert = NULL; + SecIdentityRef identity = NULL; + SecPolicyRef policy = NULL; + CFMutableArrayRef cert_chain = NULL, eval_chain = NULL; + SecTrustRef trust = NULL; + build_trust_chains_context * a_build_trust_chains_context = (build_trust_chains_context*)context; + + CFDataRef key_bytes = CFDictionaryGetValue(value, CFSTR("key")); + require(key_bytes, out); + CFDataRef cert_bytes = CFDictionaryGetValue(value, CFSTR("cert")); + require(cert_bytes, out); + CFDataRef algoid_bytes = CFDictionaryGetValue(value, CFSTR("algid")); + + + DERItem algorithm = { (DERByte *)CFDataGetBytePtr(algoid_bytes), CFDataGetLength(algoid_bytes) }; + if (DEROidCompare(&oidEcPubKey, &algorithm)) { + require (private_key = SecKeyCreateECPrivateKey(kCFAllocatorDefault, + CFDataGetBytePtr(key_bytes), CFDataGetLength(key_bytes), + kSecKeyEncodingPkcs1), out); + } else if (DEROidCompare(&oidRsa, &algorithm)) { + require (private_key = SecKeyCreateRSAPrivateKey(kCFAllocatorDefault, + CFDataGetBytePtr(key_bytes), CFDataGetLength(key_bytes), + kSecKeyEncodingPkcs1), out); + } else { + goto out; + } + + require(cert = SecCertificateCreateWithData(kCFAllocatorDefault, cert_bytes), out); + require(identity = SecIdentityCreate(kCFAllocatorDefault, cert, private_key), out); + CFDictionarySetValue(identity_dict, kSecImportItemIdentity, identity); + + eval_chain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + require(eval_chain, out); + CFArrayAppendValue(eval_chain, cert); + CFRange all_certs = { 0, CFArrayGetCount(a_build_trust_chains_context->certs) }; + CFArrayAppendArray(eval_chain, a_build_trust_chains_context->certs, all_certs); + require(policy = SecPolicyCreateBasicX509(), out); + SecTrustResultType result; + SecTrustCreateWithCertificates(eval_chain, policy, &trust); + require(trust, out); + SecTrustEvaluate(trust, &result); + CFDictionarySetValue(identity_dict, kSecImportItemTrust, trust); + + require(cert_chain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks), out); + CFIndex cert_chain_length = SecTrustGetCertificateCount(trust); + int i; + for (i = 0; i < cert_chain_length; i++) + CFArrayAppendValue(cert_chain, SecTrustGetCertificateAtIndex(trust, i)); + CFDictionarySetValue(identity_dict, kSecImportItemCertChain, cert_chain); + + CFArrayAppendValue(a_build_trust_chains_context->identities, identity_dict); +out: + CFReleaseSafe(identity_dict); + CFReleaseSafe(identity); + CFReleaseSafe(private_key); + CFReleaseSafe(cert); + CFReleaseSafe(policy); + CFReleaseSafe(cert_chain); + CFReleaseSafe(eval_chain); + CFReleaseSafe(trust); +} + +OSStatus SecPKCS12Import(CFDataRef pkcs12_data, CFDictionaryRef options, CFArrayRef *items) +{ + pkcs12_context context = {}; + SecAsn1CoderCreate(&context.coder); + if (options) + context.passphrase = CFDictionaryGetValue(options, kSecImportExportPassphrase); + context.items = CFDictionaryCreateMutable(kCFAllocatorDefault, + 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + int status = p12decode(&context, pkcs12_data); + if (!status) { + CFMutableArrayRef certs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFDictionaryApplyFunction(context.items, collect_certs, certs); + + CFMutableArrayRef identities = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + build_trust_chains_context a_build_trust_chains_context = { identities, certs }; + CFDictionaryApplyFunction(context.items, build_trust_chains, &a_build_trust_chains_context); + CFReleaseSafe(certs); + + /* ignoring certs that weren't picked up as part of the certchain for found keys */ + + *items = identities; + } + + CFReleaseSafe(context.items); + SecAsn1CoderRelease(context.coder); + + switch (status) { + case p12_noErr: return errSecSuccess; + case p12_passwordErr: return errSecAuthFailed; + case p12_decodeErr: return errSecDecode; + default: return errSecInternal; + }; + return errSecSuccess; +} + diff --git a/Security/sec/Security/SecImportExport.h b/Security/sec/Security/SecImportExport.h new file mode 100644 index 00000000..a0cc4af4 --- /dev/null +++ b/Security/sec/Security/SecImportExport.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2007-2009,2012-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@ + */ + +/*! + @header SecImportExport + contains import/export functionality for keys and certificates. +*/ + +#ifndef _SECURITY_SECIMPORTEXPORT_H_ +#define _SECURITY_SECIMPORTEXPORT_H_ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/*! + @enum Import/Export options + @discussion Predefined key constants used to pass in arguments to the + import/export functions + @constant kSecImportExportPassphrase Specifies a passphrase represented by + a CFStringRef to be used to encrypt/decrypt. +*/ +extern CFStringRef kSecImportExportPassphrase + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @enum Import/Export item description + @discussion Predefined key constants used to pass back a CFArray with a + CFDictionary per item. + + @constant kSecImportItemLabel a CFStringRef representing the item label. + This implementation specific identifier cannot be expected to have + any format. + @constant kSecImportItemKeyID a CFDataRef representing the key id. Often + the SHA-1 digest of the public key. + @constant kSecImportItemIdentity a SecIdentityRef representing the identity. + @constant kSecImportItemTrust a SecTrustRef set up with all relevant + certificates. Not guaranteed to succesfully evaluate. + @constant kSecImportItemCertChain a CFArrayRef holding all relevant + certificates for this item's identity +*/ +extern CFStringRef kSecImportItemLabel + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFStringRef kSecImportItemKeyID + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFStringRef kSecImportItemTrust + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFStringRef kSecImportItemCertChain + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFStringRef kSecImportItemIdentity + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @function SecPKCS12Import + @abstract return contents of a PKCS#12 formatted blob. + @param pkcs12_data PKCS#12 formatted data + @param options Dictionary containing options for decode. A + kSecImportExportPassphrase is required at a minimum. Only password- + based PKCS#12 blobs are currently supported. + @param items Array containing a dictionary for every item extracted. See + kSecImportItem constants. + @result errSecSuccess in case of success. errSecDecode means either the + blob can't be read or it is malformed. errSecAuthFailed means an + incorrect password was passed, or data in the container got damaged. +*/ +OSStatus SecPKCS12Import(CFDataRef pkcs12_data, CFDictionaryRef options, + CFArrayRef *items) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +__END_DECLS + +#endif /* !_SECURITY_SECIMPORTEXPORT_H_ */ diff --git a/Security/sec/Security/SecInternal.h b/Security/sec/Security/SecInternal.h new file mode 100644 index 00000000..d979a05c --- /dev/null +++ b/Security/sec/Security/SecInternal.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2007,2009-2010,2012-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@ + */ + +/*! + @header SecInternal + SecInternal defines common internal constants macros and SPI functions. +*/ + +#ifndef _SECURITY_SECINTERNAL_H_ +#define _SECURITY_SECINTERNAL_H_ + +#include +#include +#include + +#include "utilities/SecCFRelease.h" + +__BEGIN_DECLS + +#define DICT_DECLARE(MAXVALUES) \ + CFIndex numValues = 0, maxValues = (MAXVALUES); \ + const void *keys[maxValues]; \ + const void *values[maxValues]; + +#define DICT_ADDPAIR(KEY,VALUE) do { \ + if (numValues < maxValues) { \ + keys[numValues] = (KEY); \ + values[numValues] = (VALUE); \ + numValues++; \ + } else \ + assert(false); \ +} while(0) + +#define DICT_CREATE(ALLOCATOR) CFDictionaryCreate((ALLOCATOR), keys, values, \ + numValues, NULL, &kCFTypeDictionaryValueCallBacks) + +/* Non valid CFTimeInterval or CFAbsoluteTime. */ +#define NULL_TIME 0.0 + + +static inline CFIndex getIntValue(CFTypeRef cf) { + if (cf) { + if (CFGetTypeID(cf) == CFNumberGetTypeID()) { + CFIndex value; + CFNumberGetValue(cf, kCFNumberCFIndexType, &value); + return value; + } else if (CFGetTypeID(cf) == CFStringGetTypeID()) { + return CFStringGetIntValue(cf); + } + } + return -1; +} + +__END_DECLS + +#endif /* !_SECURITY_SECINTERNAL_H_ */ diff --git a/sec/Security/SecItem.c b/Security/sec/Security/SecItem.c similarity index 80% rename from sec/Security/SecItem.c rename to Security/sec/Security/SecItem.c index 63906855..2c16f7d8 100644 --- a/sec/Security/SecItem.c +++ b/Security/sec/Security/SecItem.c @@ -1,5 +1,6 @@ +; /* - * Copyright (c) 2006-2013 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -31,6 +32,8 @@ #include #include #include +#include +#include #ifndef SECITEM_SHIM_OSX #include #include @@ -69,8 +72,8 @@ #include #include -#include "securityd_client.h" -#include "SecuritydXPC.h" +#include +#include #include #include #include @@ -165,13 +168,12 @@ static OSStatus osstatus_for_der_error(CFIndex derError) { switch (derError) { case kSecDERErrorUnknownEncoding: - //case kSecDERErrorUnsupportedDERType: + case kSecDERErrorUnsupportedDERType: + case kSecDERErrorUnsupportedNumberType: return errSecDecode; case kSecDERErrorUnsupportedCFObject: - case kSecDERErrorUnsupportedNumberType: return errSecParam; case kSecDERErrorAllocationFailure: - case kSecDERErrorUnderlyingError: return errSecAllocate; default: return errSecInternal; @@ -201,7 +203,7 @@ OSStatus SecErrorGetOSStatus(CFErrorRef error) { } else if (CFEqual(sSecDERErrorDomain, domain)) { status = osstatus_for_der_error(CFErrorGetCode(error)); } else { - secerror("unknown error domain: %@ for error: %@", domain, error); + secnotice("securityd", "unknown error domain: %@ for error: %@", domain, error); status = errSecInternal; } } @@ -308,35 +310,6 @@ extern CFTypeRef SecItemCreateFromAttributeDictionary(CFDictionaryRef refAttribu #endif -/* Turn the returned dictionary that contains all the attributes to create a - ref into the exact result the client asked for */ -static CFTypeRef makeRef(CFTypeRef ref, bool return_data, bool return_attributes) -{ - CFTypeRef result = NULL; - if (!ref || (CFGetTypeID(ref) != CFDictionaryGetTypeID())) - return NULL; - - CFTypeRef return_ref = SecItemCreateFromAttributeDictionary(ref); - - if (return_data || return_attributes) { - if (return_attributes) - result = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, ref); - else - result = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - if (return_ref) { - CFDictionarySetValue((CFMutableDictionaryRef)result, kSecValueRef, return_ref); - CFRelease(return_ref); - } - - if (!return_data) - CFDictionaryRemoveValue((CFMutableDictionaryRef)result, kSecValueData); - } else - result = return_ref; - - return result; -} - OSStatus SecItemCopyDisplayNames(CFArrayRef items, CFArrayRef *displayNames) { @@ -587,6 +560,55 @@ static bool cf_bool_value(CFTypeRef cf_bool) return (cf_bool && CFEqual(kCFBooleanTrue, cf_bool)); } +/* Turn the returned dictionary that contains all the attributes to create a + ref into the exact result the client asked for */ +CF_RETURNS_RETAINED +static CFTypeRef makeResult(CFTypeRef ref, bool return_ref, bool return_data, bool return_attributes, bool return_persistentref) +{ + CFTypeRef result = NULL; + if (!ref || (CFGetTypeID(ref) != CFDictionaryGetTypeID())) + return CFRetainSafe(ref); + + CFTypeRef returned_ref = return_ref ? SecItemCreateFromAttributeDictionary(ref) : NULL; + + if (return_data || return_attributes || return_persistentref) { + if (return_attributes) + result = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, ref); + else + result = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + if (returned_ref) { + CFDictionarySetValue((CFMutableDictionaryRef)result, kSecValueRef, returned_ref); + CFRelease(returned_ref); + } + + if (return_data) { + CFTypeRef r_data = CFDictionaryGetValue(ref, kSecValueData); + if (r_data) + CFDictionarySetValue((CFMutableDictionaryRef)result, kSecValueData, r_data); + } else { + CFDictionaryRemoveValue((CFMutableDictionaryRef)result, kSecValueData); + } + + if (return_persistentref) { + CFTypeRef persistent_ref = CFDictionaryGetValue(ref, kSecValuePersistentRef); + if (persistent_ref) + CFDictionarySetValue((CFMutableDictionaryRef)result, kSecValuePersistentRef, persistent_ref); + } + + CFDataRef ac_data = CFDictionaryGetValue(result, kSecAttrAccessControl); + if (ac_data) { + SecAccessControlRef ac = SecAccessControlCreateFromData(kCFAllocatorDefault, ac_data, NULL); + if (ac) { + CFDictionarySetValue((CFMutableDictionaryRef)result, kSecAttrAccessControl, ac); + CFRelease(ac); + } + } + } else if (return_ref) + result = returned_ref; + + return result; +} static void result_post(CFDictionaryRef query, CFTypeRef raw_result, CFTypeRef *result) { @@ -601,25 +623,39 @@ result_post(CFDictionaryRef query, CFTypeRef raw_result, CFTypeRef *result) { bool return_ref = cf_bool_value(CFDictionaryGetValue(query, kSecReturnRef)); bool return_data = cf_bool_value(CFDictionaryGetValue(query, kSecReturnData)); bool return_attributes = cf_bool_value(CFDictionaryGetValue(query, kSecReturnAttributes)); + bool return_persistentref = cf_bool_value(CFDictionaryGetValue(query, kSecReturnPersistentRef)); + + if (CFGetTypeID(raw_result) == CFArrayGetTypeID()) { + CFIndex i, count = CFArrayGetCount(raw_result); + CFMutableArrayRef tmp_array = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks); + for (i = 0; i < count; i++) { + CFTypeRef ref = makeResult(CFArrayGetValueAtIndex(raw_result, i), return_ref, return_data, return_attributes, + return_persistentref); + if (ref) { + CFArrayAppendValue(tmp_array, ref); + CFRelease(ref); + } + } + *result = tmp_array; + } else + *result = makeResult(raw_result, return_ref, return_data, return_attributes, return_persistentref); - if (return_ref) { - if (CFGetTypeID(raw_result) == CFArrayGetTypeID()) { - CFIndex i, count = CFArrayGetCount(raw_result); - CFMutableArrayRef tmp_array = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks); - for (i = 0; i < count; i++) { - CFTypeRef ref = makeRef(CFArrayGetValueAtIndex(raw_result, i), return_data, return_attributes); - if (ref) { - CFArrayAppendValue(tmp_array, ref); - CFRelease(ref); - } - } - *result = tmp_array; - } else - *result = makeRef(raw_result, return_data, return_attributes); + CFRelease(raw_result); +} - CFRelease(raw_result); - } else - *result = raw_result; +static void attributes_pre(CFDictionaryRef attributes, CFMutableDictionaryRef *result) { + CFDataRef data = NULL; + SecAccessControlRef access_control = NULL; + *result = NULL; + access_control = (SecAccessControlRef)CFDictionaryGetValue(attributes, kSecAttrAccessControl); + require_quiet(access_control, out); + data = SecAccessControlCopyData(access_control); + require_quiet(data, out); + *result = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, attributes); + CFDictionarySetValue(*result, kSecAttrAccessControl, data); + +out: + CFReleaseSafe(data); } #if SECITEM_SHIM_OSX @@ -642,7 +678,18 @@ static bool cftype_to_bool_cftype_error_request(enum SecXPCOperation op, CFTypeR }); } -static bool cftype_ag_to_bool_cftype_error_request(enum SecXPCOperation op, CFTypeRef attributes, __unused CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error) { +static CFArrayRef dict_to_array_error_request(enum SecXPCOperation op, CFDictionaryRef attributes, CFErrorRef *error) +{ + CFArrayRef result = NULL; + bool success = cftype_to_bool_cftype_error_request(op, attributes, (CFTypeRef*)&result, error); + if(success && !isArray(result)){ + SecError(errSecUnimplemented, error, CFSTR("Unexpected nonarray returned: %@"), result); + CFReleaseNull(result); + } + return result; +} + +bool cftype_ag_to_bool_cftype_error_request(enum SecXPCOperation op, CFTypeRef attributes, __unused CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error) { return cftype_to_bool_cftype_error_request(op, attributes, result, error); } @@ -704,30 +751,37 @@ SecItemAdd_ios(CFDictionaryRef attributes, CFTypeRef *result) SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result) #endif // *** END SECITEM_SHIM_OSX *** { - CFMutableDictionaryRef args = NULL; + CFMutableDictionaryRef args1 = NULL, args2 = NULL; OSStatus status; #ifndef SECITEM_SHIM_OSX require_quiet(!explode_identity(attributes, (secitem_operation)SecItemAdd, &status, result), errOut); - require_noerr_quiet(status = cook_query(attributes, &args), errOut); - infer_cert_label(attributes, args); + require_noerr_quiet(status = cook_query(attributes, &args1), errOut); + infer_cert_label(attributes, args1); + if (args1) + attributes = args1; #endif // *** END SECITEM_SHIM_OSX *** - if (args) - attributes = args; - status = SecOSStatusWith(^bool (CFErrorRef *error) { + SecAccessControlRef access_control = (SecAccessControlRef)CFDictionaryGetValue(attributes, kSecAttrAccessControl); + if(access_control && SecAccessControlGetConstraints(access_control) && CFEqualSafe(CFDictionaryGetValue(attributes, kSecAttrSynchronizable), kCFBooleanTrue)) + require_noerr_quiet(status = errSecParam, errOut); + + attributes_pre(attributes, &args2); + if (args2) + attributes = args2; + + require_noerr_quiet(status = SecOSStatusWith(^bool (CFErrorRef *error) { CFTypeRef raw_result = NULL; if (!SECURITYD_XPC(sec_item_add, cftype_ag_to_bool_cftype_error_request, attributes, SecAccessGroupsGetCurrent(), &raw_result, error)) return false; result_post(attributes, raw_result, result); return true; - }); + }), errOut); -#ifndef SECITEM_SHIM_OSX errOut: -#endif // *** END SECITEM_SHIM_OSX *** - CFReleaseSafe(args); + CFReleaseSafe(args1); + CFReleaseSafe(args2); return status; } @@ -740,38 +794,33 @@ SecItemCopyMatching(CFDictionaryRef inQuery, CFTypeRef *result) #endif // *** END SECITEM_SHIM_OSX *** { __block CFDictionaryRef query = inQuery; - __block CFMutableDictionaryRef args = NULL; + __block CFMutableDictionaryRef args1 = NULL, args2 = NULL; OSStatus status; #ifndef SECITEM_SHIM_OSX require_quiet(!explode_identity(query, (secitem_operation)SecItemCopyMatching, &status, result), errOut); - require_noerr_quiet(status = cook_query(query, &args), errOut); + require_noerr_quiet(status = cook_query(query, &args1), errOut); + if (args1) + query = args1; #endif // *** END SECITEM_SHIM_OSX *** - if (args) - query = args; - status = SecOSStatusWith(^bool (CFErrorRef *error) { + attributes_pre(query, &args2); + if (args2) + query = args2; + + require_noerr_quiet(status = SecOSStatusWith(^bool (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)) return false; -#ifdef SECITEM_SHIM_OSX - if ((!cf_bool_value(CFDictionaryGetValue(query, kSecReturnPersistentRef))) && cf_bool_value(CFDictionaryGetValue(query, kSecReturnRef))) { - CFReleaseSafe(args); - args = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, query); - CFDictionaryAddValue(args, kSecReturnPersistentRef, kCFBooleanTrue); - query = args; - } -#endif result_post(query, raw_result, result); return true; - }); + }), errOut); -#ifndef SECITEM_SHIM_OSX errOut: -#endif // *** END SECITEM_SHIM_OSX *** - CFReleaseSafe(args); - return status; + CFReleaseSafe(args1); + CFReleaseSafe(args2); + return status; } OSStatus @@ -781,15 +830,23 @@ SecItemUpdate_ios(CFDictionaryRef query, CFDictionaryRef attributesToUpdate) SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate) #endif // *** END SECITEM_SHIM_OSX *** { - CFMutableDictionaryRef args = NULL; + CFMutableDictionaryRef args1 = NULL, args2 = NULL, args3 = NULL; __block OSStatus status; // TODO loose block once gSecurityd functions return CFErrorRefs #ifndef SECITEM_SHIM_OSX - require_noerr_quiet(status = cook_query(query, &args), errOut); + require_noerr_quiet(status = cook_query(query, &args1), errOut); + if (args1) + query = args1; #endif - if (args) - query = args; - status = SecOSStatusWith(^bool (CFErrorRef *error) { + attributes_pre(attributesToUpdate, &args2); + if (args2) + attributesToUpdate = args2; + + attributes_pre(query, &args3); + if (args3) + query = args3; + + require_noerr_quiet(status = SecOSStatusWith(^bool (CFErrorRef *error) { bool ok = false; if (gSecurityd) { // Ensure the dictionary passed to securityd has proper kCFTypeDictionaryKeyCallBacks. @@ -812,12 +869,12 @@ SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate) } } return ok; - }); + }), errOut); -#ifndef SECITEM_SHIM_OSX errOut: -#endif - CFReleaseSafe(args); + CFReleaseSafe(args1); + CFReleaseSafe(args2); + CFReleaseSafe(args3); return status; } @@ -868,7 +925,7 @@ SecItemDelete_ios(CFDictionaryRef query) SecItemDelete(CFDictionaryRef query) #endif // *** END SECITEM_SHIM_OSX *** { - CFMutableDictionaryRef args1 = NULL, args2 = NULL; + CFMutableDictionaryRef args1 = NULL, args2 = NULL, args3 = NULL; OSStatus status; #ifndef SECITEM_SHIM_OSX @@ -877,19 +934,22 @@ SecItemDelete(CFDictionaryRef query) query = args1; require_quiet(!explode_identity(query, (secitem_operation)SecItemDelete, &status, NULL), errOut); require_noerr_quiet(status = cook_query(query, &args2), errOut); -#endif // *** END SECITEM_SHIM_OSX *** if (args2) query = args2; +#endif // *** END SECITEM_SHIM_OSX *** + + attributes_pre(query, &args3); + if (args3) + query = args3; - status = SecOSStatusWith(^bool (CFErrorRef *error) { + require_noerr_quiet(status = SecOSStatusWith(^bool (CFErrorRef *error) { return SECURITYD_XPC(sec_item_delete, dict_ag_to_error_request, query, SecAccessGroupsGetCurrent(), error); - }); + }), errOut); -#ifndef SECITEM_SHIM_OSX errOut: -#endif // *** END SECITEM_SHIM_OSX *** CFReleaseSafe(args1); CFReleaseSafe(args2); + CFReleaseSafe(args3); return status; } @@ -899,6 +959,7 @@ SecItemDeleteAll(void) return SecOSStatusWith(^bool (CFErrorRef *error) { bool ok; if (gSecurityd) { + ok = true; #ifndef SECITEM_SHIM_OSX SecTrustStoreRef ts = SecTrustStoreForDomain(kSecTrustStoreDomainUser); if (!gSecurityd->sec_truststore_remove_all(ts, error)) @@ -906,7 +967,6 @@ SecItemDeleteAll(void) #endif // *** END SECITEM_SHIM_OSX *** if (!gSecurityd->sec_item_delete_all(error)) ok = SecError(errSecInternal, error, CFSTR("sec_item_delete_all is NULL")); - ok = true; } else { ok = securityd_send_sync_and_do(sec_delete_all_id, error, NULL, NULL); } @@ -929,8 +989,19 @@ OSStatus _SecKeychainRestoreBackup(CFDataRef backup, CFDataRef backupKeybag, }); } -bool _SecKeychainSyncUpdate(CFDictionaryRef updates, CFErrorRef *error) { - return SECURITYD_XPC(sec_keychain_sync_update, dict_to_error_request, updates, error); +CFArrayRef _SecKeychainSyncUpdateKeyParameter(CFDictionaryRef updates, CFErrorRef *error) { + + return SECURITYD_XPC(sec_keychain_sync_update_key_parameter, dict_to_array_error_request, updates, error); +} + +CFArrayRef _SecKeychainSyncUpdateCircle(CFDictionaryRef updates, CFErrorRef *error) { + + return SECURITYD_XPC(sec_keychain_sync_update_circle, dict_to_array_error_request, updates, error); +} + +CFArrayRef _SecKeychainSyncUpdateMessage(CFDictionaryRef updates, CFErrorRef *error) { + + return SECURITYD_XPC(sec_keychain_sync_update_message, dict_to_array_error_request, updates, error); } OSStatus _SecKeychainBackupSyncable(CFDataRef keybag, CFDataRef password, CFDictionaryRef backup_in, CFDictionaryRef *backup_out) @@ -948,7 +1019,6 @@ OSStatus _SecKeychainRestoreSyncable(CFDataRef keybag, CFDataRef password, CFDic }); } - #ifndef SECITEM_SHIM_OSX OSStatus SecTaskValidateForRequirement(SecTaskRef task, CFStringRef requirement); @@ -962,3 +1032,26 @@ OSStatus SecTaskValidateForRequirement(SecTaskRef task, CFStringRef requirement) extern OSStatus SecTaskValidateForRequirement(SecTaskRef task, CFStringRef requirement); #endif + +#define do_if_registered(sdp, ...) if (gSecurityd && gSecurityd->sdp) { return gSecurityd->sdp(__VA_ARGS__); } + +bool _SecKeychainRollKeys(bool force, CFErrorRef *error) +{ + do_if_registered(sec_roll_keys, force, error); + + __block bool result = false; + + secdebug("secitem","enter - %s", __FUNCTION__); + securityd_send_sync_and_do(kSecXPCOpRollKeys, error, + ^bool(xpc_object_t message, CFErrorRef *error) { + xpc_dictionary_set_bool(message, "force", force); + return true; + }, + ^bool(xpc_object_t response, __unused CFErrorRef *error) { + result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); + return result; + }); + return result; +} + + diff --git a/Security/sec/Security/SecItem.h b/Security/sec/Security/SecItem.h new file mode 100644 index 00000000..8a7ed537 --- /dev/null +++ b/Security/sec/Security/SecItem.h @@ -0,0 +1,1006 @@ +/* + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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 SecItem + SecItem defines CoreFoundation-based constants and functions for + access to Security items (certificates, keys, identities, and + passwords.) +*/ + +#ifndef _SECURITY_SECITEM_H_ +#define _SECURITY_SECITEM_H_ + +#include +#include +#include + +__BEGIN_DECLS + +/*! + @enum Class Key Constant + @discussion Predefined key constant used to get or set item class values in + a dictionary. Its value is one of the constants defined in the Value + Constants for kSecClass. + @constant kSecClass Specifies a dictionary key whose value is the item's + class code. You use this key to get or set a value of type CFTypeRef + that contains the item class code. +*/ +extern CFTypeRef kSecClass + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @enum Class Value Constants + @discussion Predefined item class constants used to get or set values in + a dictionary. The kSecClass constant is the key and its value is one + of the constants defined here. + @constant kSecClassGenericPassword Specifies generic password items. + @constant kSecClassInternetPassword Specifies Internet password items. + @constant kSecClassCertificate Specifies certificate items. + @constant kSecClassKey Specifies key items. + @constant kSecClassIdentity Specifies identity items. +*/ +extern CFTypeRef kSecClassGenericPassword + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); +extern CFTypeRef kSecClassInternetPassword + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecClassCertificate + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); +extern CFTypeRef kSecClassKey + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); +extern CFTypeRef kSecClassIdentity + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + + +/*! + @enum Attribute Key Constants + @discussion Predefined item attribute keys used to get or set values in a + dictionary. Not all attributes apply to each item class. The table + below lists the currently defined attributes for each item class: + + kSecClassGenericPassword item attributes: + kSecAttrAccessible + kSecAttrAccessControl + kSecAttrAccessGroup + kSecAttrCreationDate + kSecAttrModificationDate + kSecAttrDescription + kSecAttrComment + kSecAttrCreator + kSecAttrType + kSecAttrLabel + kSecAttrIsInvisible + kSecAttrIsNegative + kSecAttrAccount + kSecAttrService + kSecAttrGeneric + + kSecClassInternetPassword item attributes: + kSecAttrAccessible + kSecAttrAccessControl + kSecAttrAccessGroup + kSecAttrCreationDate + kSecAttrModificationDate + kSecAttrDescription + kSecAttrComment + kSecAttrCreator + kSecAttrType + kSecAttrLabel + kSecAttrIsInvisible + kSecAttrIsNegative + kSecAttrAccount + kSecAttrSecurityDomain + kSecAttrServer + kSecAttrProtocol + kSecAttrAuthenticationType + kSecAttrPort + kSecAttrPath + + kSecClassCertificate item attributes: + kSecAttrAccessible + kSecAttrAccessControl + kSecAttrAccessGroup + kSecAttrCertificateType + kSecAttrCertificateEncoding + kSecAttrLabel + kSecAttrSubject + kSecAttrIssuer + kSecAttrSerialNumber + kSecAttrSubjectKeyID + kSecAttrPublicKeyHash + + kSecClassKey item attributes: + kSecAttrAccessible + kSecAttrAccessControl + kSecAttrAccessGroup + kSecAttrKeyClass + kSecAttrLabel + kSecAttrApplicationLabel + kSecAttrIsPermanent + kSecAttrApplicationTag + kSecAttrKeyType + kSecAttrKeySizeInBits + kSecAttrEffectiveKeySize + kSecAttrCanEncrypt + kSecAttrCanDecrypt + kSecAttrCanDerive + kSecAttrCanSign + kSecAttrCanVerify + kSecAttrCanWrap + kSecAttrCanUnwrap + + kSecClassIdentity item attributes: + Since an identity is the combination of a private key and a + certificate, this class shares attributes of both kSecClassKey and + kSecClassCertificate. + + @constant kSecAttrAccessible Specifies a dictionary key whose value + indicates when your application needs access to an item's data. You + should choose the most restrictive option that meets your application's + needs to allow the system to protect that item in the best way possible. + See the "kSecAttrAccessible Value Constants" section for a list of + values which can be specified. + IMPORTANT: This attribute is currently not supported for OS X keychain + items, unless the kSecAttrSynchronizable attribute is also present. If + both attributes are specified on either OS X or iOS, the value for the + kSecAttrAccessible key may only be one whose name does not end with + "ThisDeviceOnly", as those cannot sync to another device. + + @constant kSecAttrAccessControl Specifies a dictionary key whose value + is SecAccessControl instance which contains access control conditions + for item. + + @constant kSecAttrAccessGroup Specifies a dictionary key whose value is + a CFStringRef indicating which access group a item is in. The access + groups that a particular application has membership in are determined by + two entitlements for that application. The application-identifier + entitlement contains the application's single access group, unless + there is a keychain-access-groups entitlement present. The latter + has as its value a list of access groups; the first item in this list + is the default access group. Unless a specific access group is provided + as the value of kSecAttrAccessGroup when SecItemAdd is called, new items + are created in the application's default access group. Specifying this + attribute in SecItemCopyMatching, SecItemUpdate, or SecItemDelete calls + limits the search to the specified access group (of which the calling + application must be a member to obtain matching results.) To share + keychain items between multiple applications, each application must have + a common group listed in its keychain-access-groups entitlement, and each + must specify this shared access group name as the value for the + kSecAttrAccessGroup key in the dictionary passed to SecItem functions. + + @constant kSecAttrSynchronizable Specifies a dictionary key whose value is + a CFBooleanRef indicating whether the item in question can be synchronized. + To add a new item which can be synced to other devices, or to obtain + synchronizable results from a query, supply this key with a value of + kCFBooleanTrue. If the key is not supplied, or has a value of + kCFBooleanFalse, then no synchronizable items will be added or returned. + A predefined value, kSecAttrSynchronizableAny, may be provided instead of + kCFBooleanTrue if both synchronizable and non-synchronizable results are + desired. + + IMPORTANT: Specifying the kSecAttrSynchronizable key has several caveats: + + - Updating or deleting items using the kSecAttrSynchronizable key will + affect all copies of the item, not just the one on your local device. + Be sure that it makes sense to use the same password on all devices + before deciding to make a password synchronizable. + - Only password items can currently be synchronized. Keychain syncing + is not supported for certificates or cryptographic keys. + - Items stored or obtained using the kSecAttrSynchronizable key cannot + specify SecAccessRef-based access control with kSecAttrAccess. If a + password is intended to be shared between multiple applications, the + kSecAttrAccessGroup key must be specified, and each application + using this password must have a 'keychain-access-groups' entitlement + with the specified access group value. + - Items stored or obtained using the kSecAttrSynchronizable key may + not also specify a kSecAttrAccessible value which is incompatible + with syncing (namely, those whose names end with "ThisDeviceOnly".) + - Items stored or obtained using the kSecAttrSynchronizable key cannot + be specified by reference. You must pass kSecReturnAttributes and/or + kSecReturnData to retrieve results; kSecReturnRef is currently not + supported for synchronizable items. + - Persistent references to synchronizable items should be avoided; + while they may work locally, they cannot be moved between devices, + and may not resolve if the item is modified on some other device. + - When specifying a query that uses the kSecAttrSynchronizable key, + search keys are limited to the item's class and attributes. + The only search constant which may be used is kSecMatchLimit; other + constants using the kSecMatch prefix are not supported at this time. + + @constant kSecAttrSynchronizableAny Specifies that both synchronizable and + non-synchronizable results should be returned from this query. This may be + used as a value for the kSecAttrSynchronizable dictionary key in a call to + SecItemCopyMatching, SecItemUpdate, or SecItemDelete. + + @constant kSecAttrCreationDate (read-only) Specifies a dictionary key whose + value is the item's creation date. You use this key to get a value + of type CFDateRef that represents the date the item was created. + @constant kSecAttrModificationDate (read-only) Specifies a dictionary key + whose value is the item's modification date. You use this key to get + a value of type CFDateRef that represents the last time the item was + updated. + @constant kSecAttrDescription Specifies a dictionary key whose value is + the item's description attribute. You use this key to set or get a + value of type CFStringRef that represents a user-visible string + describing this particular kind of item (e.g., "disk image password"). + @constant kSecAttrComment Specifies a dictionary key whose value is the + item's comment attribute. You use this key to set or get a value of + type CFStringRef containing the user-editable comment for this item. + @constant kSecAttrCreator Specifies a dictionary key whose value is the + item's creator attribute. You use this key to set or get a value of + type CFNumberRef that represents the item's creator. This number is + the unsigned integer representation of a four-character code (e.g., + 'aCrt'). + @constant kSecAttrType Specifies a dictionary key whose value is the item's + type attribute. You use this key to set or get a value of type + CFNumberRef that represents the item's type. This number is the + unsigned integer representation of a four-character code (e.g., + 'aTyp'). + @constant kSecAttrLabel Specifies a dictionary key whose value is the + item's label attribute. You use this key to set or get a value of + type CFStringRef containing the user-visible label for this item. + @constant kSecAttrIsInvisible Specifies a dictionary key whose value is the + item's invisible attribute. You use this key to set or get a value + of type CFBooleanRef that indicates whether the item is invisible + (i.e., should not be displayed.) + @constant kSecAttrIsNegative Specifies a dictionary key whose value is the + item's negative attribute. You use this key to set or get a value of + type CFBooleanRef that indicates whether there is a valid password + associated with this keychain item. This is useful if your application + doesn't want a password for some particular service to be stored in + the keychain, but prefers that it always be entered by the user. + @constant kSecAttrAccount Specifies a dictionary key whose value is the + item's account attribute. You use this key to set or get a CFStringRef + that contains an account name. (Items of class + kSecClassGenericPassword, kSecClassInternetPassword have this + attribute.) + @constant kSecAttrService Specifies a dictionary key whose value is the + item's service attribute. You use this key to set or get a CFStringRef + that represents the service associated with this item. (Items of class + kSecClassGenericPassword have this attribute.) + @constant kSecAttrGeneric Specifies a dictionary key whose value is the + item's generic attribute. You use this key to set or get a value of + CFDataRef that contains a user-defined attribute. (Items of class + kSecClassGenericPassword have this attribute.) + @constant kSecAttrSecurityDomain Specifies a dictionary key whose value + is the item's security domain attribute. You use this key to set or + get a CFStringRef value that represents the Internet security domain. + (Items of class kSecClassInternetPassword have this attribute.) + @constant kSecAttrServer Specifies a dictionary key whose value is the + item's server attribute. You use this key to set or get a value of + type CFStringRef that contains the server's domain name or IP address. + (Items of class kSecClassInternetPassword have this attribute.) + @constant kSecAttrProtocol Specifies a dictionary key whose value is the + item's protocol attribute. You use this key to set or get a value of + type CFNumberRef that denotes the protocol for this item (see the + SecProtocolType enum in SecKeychainItem.h). (Items of class + kSecClassInternetPassword have this attribute.) + @constant kSecAttrAuthenticationType Specifies a dictionary key whose value + is the item's authentication type attribute. You use this key to set + or get a value of type CFNumberRef that denotes the authentication + scheme for this item (see the kSecAttrAuthenticationType value + constants below). + @constant kSecAttrPort Specifies a dictionary key whose value is the item's + port attribute. You use this key to set or get a CFNumberRef value + that represents an Internet port number. (Items of class + kSecClassInternetPassword have this attribute.) + @constant kSecAttrPath Specifies a dictionary key whose value is the item's + path attribute, typically this is the path component of the URL. You use + this key to set or get a CFStringRef value that represents a path. (Items + of class kSecClassInternetPassword have this attribute.) + @constant kSecAttrSubject (read-only) Specifies a dictionary key whose + value is the item's subject. You use this key to get a value of type + CFDataRef that contains the X.500 subject name of a certificate. + (Items of class kSecClassCertificate have this attribute.) + @constant kSecAttrIssuer (read-only) Specifies a dictionary key whose value + is the item's issuer. You use this key to get a value of type + CFDataRef that contains the X.500 issuer name of a certificate. (Items + of class kSecClassCertificate have this attribute.) + @constant kSecAttrSerialNumber (read-only) Specifies a dictionary key whose + value is the item's serial number. You use this key to get a value + of type CFDataRef that contains the serial number data of a + certificate. (Items of class kSecClassCertificate have this + attribute.) + @constant kSecAttrSubjectKeyID (read-only) Specifies a dictionary key whose + value is the item's subject key ID. You use this key to get a value + of type CFDataRef that contains the subject key ID of a certificate. + (Items of class kSecClassCertificate have this attribute.) + @constant kSecAttrPublicKeyHash (read-only) Specifies a dictionary key + whose value is the item's public key hash. You use this key to get a + value of type CFDataRef that contains the hash of a certificate's + public key. (Items of class kSecClassCertificate have this attribute.) + @constant kSecAttrCertificateType (read-only) Specifies a dictionary key + whose value is the item's certificate type. You use this key to get + a value of type CFNumberRef that denotes the certificate type + (Currently only the value of this attribute must be equal to the + version of the X509 certificate. So 1 for v1 2 for v2 and 3 for v3 + certificates). Only items of class kSecClassCertificate have this + attribute. + @constant kSecAttrCertificateEncoding (read-only) Specifies a dictionary + key whose value is the item's certificate encoding. You use this key + to get a value of type CFNumberRef that denotes the certificate + encoding (Currently only the value 3 meaning + kSecAttrCertificateEncodingDER is supported). Only items of class + kSecClassCertificate have this attribute. + @constant kSecAttrKeyClass (read only) Specifies a dictionary key whose + value is one of kSecAttrKeyClassPublic, kSecAttrKeyClassPrivate or + kSecAttrKeyClassSymmetric. + @constant kSecAttrApplicationLabel Specifies a dictionary key whose value + is the key's application label attribute. This is different from the + kSecAttrLabel (which is intended to be human-readable). This attribute + is used to look up a key programmatically; in particular, for keys of + class kSecAttrKeyClassPublic and kSecAttrKeyClassPrivate, the value of + this attribute is the hash of the public key. + @constant kSecAttrIsPermanent Specifies a dictionary key whose value is a + CFBooleanRef indicating whether the key in question will be stored + permanently. + @constant kSecAttrApplicationTag Specifies a dictionary key whose value is a + CFDataRef containing private tag data. + @constant kSecAttrKeyType Specifies a dictionary key whose value is a + CFNumberRef indicating the algorithm associated with this key + (Currently only the value 42 is supported, alternatively you can use + kSecAttrKeyTypeRSA). + @constant kSecAttrKeySizeInBits Specifies a dictionary key whose value + is a CFNumberRef indicating the number of bits in this key. + @constant kSecAttrEffectiveKeySize Specifies a dictionary key whose value + is a CFNumberRef indicating the effective number of bits in this key. + For example, a DES key has a kSecAttrKeySizeInBits of 64, but a + kSecAttrEffectiveKeySize of 56 bits. + @constant kSecAttrCanEncrypt Specifies a dictionary key whole value is a + CFBooleanRef indicating whether the key in question can be used to + encrypt data. + @constant kSecAttrCanDecrypt Specifies a dictionary key whose value is a + CFBooleanRef indicating whether the key in question can be used to + decrypt data. + @constant kSecAttrCanDerive Specifies a dictionary key whole value is a + CFBooleanRef indicating whether the key in question can be used to + derive another key. + @constant kSecAttrCanSign Specifies a dictionary key whole value is a + CFBooleanRef indicating whether the key in question can be used to + create a digital signature. + @constant kSecAttrCanVerify Specifies a dictionary key whole value is a + CFBooleanRef indicating whether the key in question can be used to + verify a digital signature. + @constant kSecAttrCanWrap Specifies a dictionary key whole value is a + CFBooleanRef indicating whether the key in question can be used to + wrap another key. + @constant kSecAttrCanUnwrap Specifies a dictionary key whole value is a + CFBooleanRef indicating whether the key in question can be used to + unwrap another key. +*/ +extern CFTypeRef kSecAttrAccessible + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); +extern CFTypeRef kSecAttrAccessControl + __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); +extern CFTypeRef kSecAttrAccessGroup + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_3_0); +extern CFTypeRef kSecAttrSynchronizable + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecAttrSynchronizableAny + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecAttrCreationDate + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrModificationDate + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrDescription + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrComment + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrCreator + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrType + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrLabel + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrIsInvisible + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrIsNegative + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrAccount + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrService + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrGeneric + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrSecurityDomain + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrServer + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocol + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrAuthenticationType + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrPort + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrPath + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrSubject + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrIssuer + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrSerialNumber + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrSubjectKeyID + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrPublicKeyHash + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrCertificateType + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrCertificateEncoding + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrKeyClass + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrApplicationLabel + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrIsPermanent + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrApplicationTag + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrKeyType + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrKeySizeInBits + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrEffectiveKeySize + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrCanEncrypt + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrCanDecrypt + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrCanDerive + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrCanSign + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrCanVerify + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrCanWrap + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrCanUnwrap + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @enum kSecAttrAccessible Value Constants + @discussion Predefined item attribute constants used to get or set values + in a dictionary. The kSecAttrAccessible constant is the key and its + value is one of the constants defined here. + When asking SecItemCopyMatching to return the item's data, the error + errSecInteractionNotAllowed will be returned if the item's data is not + available until a device unlock occurs. + @constant kSecAttrAccessibleWhenUnlocked Item data can only be accessed + while the device is unlocked. This is recommended for items that only + need be accesible while the application is in the foreground. Items + with this attribute will migrate to a new device when using encrypted + backups. + @constant kSecAttrAccessibleAfterFirstUnlock Item data can only be + accessed once the device has been unlocked after a restart. This is + recommended for items that need to be accesible by background + applications. Items with this attribute will migrate to a new device + when using encrypted backups. + @constant kSecAttrAccessibleAlways Item data can always be accessed + regardless of the lock state of the device. This is not recommended + for anything except system use. Items with this attribute will migrate + to a new device when using encrypted backups. + @constant kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly Item data can + only be accessed while the device is unlocked. This class is only + available if a passcode is set on the device. This is recommended for + items that only need to be accessible while the application is in the + foreground. Items with this attribute will never migrate to a new + device, so after a backup is restored to a new device, these items + will be missing. No items can be stored in this class on devices + without a passcode. Disabling the device passcode will cause all + items in this class to be deleted. + @constant kSecAttrAccessibleWhenUnlockedThisDeviceOnly Item data can only + be accessed while the device is unlocked. This is recommended for items + that only need be accesible while the application is in the foreground. + Items with this attribute will never migrate to a new device, so after + a backup is restored to a new device, these items will be missing. + @constant kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly Item data can + only be accessed once the device has been unlocked after a restart. + This is recommended for items that need to be accessible by background + applications. Items with this attribute will never migrate to a new + device, so after a backup is restored to a new device these items will + be missing. + @constant kSecAttrAccessibleAlwaysThisDeviceOnly Item data can always + be accessed regardless of the lock state of the device. This option + is not recommended for anything except system use. Items with this + attribute will never migrate to a new device, so after a backup is + restored to a new device, these items will be missing. +*/ +extern CFTypeRef kSecAttrAccessibleWhenUnlocked + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); +extern CFTypeRef kSecAttrAccessibleAfterFirstUnlock + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); +extern CFTypeRef kSecAttrAccessibleAlways + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); +extern CFTypeRef kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly + __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); +extern CFTypeRef kSecAttrAccessibleWhenUnlockedThisDeviceOnly + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); +extern CFTypeRef kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); +extern CFTypeRef kSecAttrAccessibleAlwaysThisDeviceOnly + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); + +/*! + @enum kSecAttrProtocol Value Constants + @discussion Predefined item attribute constants used to get or set values + in a dictionary. The kSecAttrProtocol constant is the key and its + value is one of the constants defined here. + @constant kSecAttrProtocolFTP. + @constant kSecAttrProtocolFTPAccount. + @constant kSecAttrProtocolHTTP. + @constant kSecAttrProtocolIRC. + @constant kSecAttrProtocolNNTP. + @constant kSecAttrProtocolPOP3. + @constant kSecAttrProtocolSMTP. + @constant kSecAttrProtocolSOCKS. + @constant kSecAttrProtocolIMAP. + @constant kSecAttrProtocolLDAP. + @constant kSecAttrProtocolAppleTalk. + @constant kSecAttrProtocolAFP. + @constant kSecAttrProtocolTelnet. + @constant kSecAttrProtocolSSH. + @constant kSecAttrProtocolFTPS. + @constant kSecAttrProtocolHTTPS. + @constant kSecAttrProtocolHTTPProxy. + @constant kSecAttrProtocolHTTPSProxy. + @constant kSecAttrProtocolFTPProxy. + @constant kSecAttrProtocolSMB. + @constant kSecAttrProtocolRTSP. + @constant kSecAttrProtocolRTSPProxy. + @constant kSecAttrProtocolDAAP. + @constant kSecAttrProtocolEPPC. + @constant kSecAttrProtocolIPP. + @constant kSecAttrProtocolNNTPS. + @constant kSecAttrProtocolLDAPS. + @constant kSecAttrProtocolTelnetS. + @constant kSecAttrProtocolIMAPS. + @constant kSecAttrProtocolIRCS. + @constant kSecAttrProtocolPOP3S. +*/ +extern CFTypeRef kSecAttrProtocolFTP + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolFTPAccount + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolHTTP + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolIRC + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolNNTP + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolPOP3 + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolSMTP + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolSOCKS + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolIMAP + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolLDAP + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolAppleTalk + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolAFP + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolTelnet + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolSSH + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolFTPS + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolHTTPS + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolHTTPProxy + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolHTTPSProxy + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolFTPProxy + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolSMB + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolRTSP + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolRTSPProxy + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolDAAP + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolEPPC + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolIPP + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolNNTPS + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolLDAPS + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolTelnetS + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolIMAPS + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolIRCS + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrProtocolPOP3S + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @enum kSecAttrAuthenticationType Value Constants + @discussion Predefined item attribute constants used to get or set values + in a dictionary. The kSecAttrAuthenticationType constant is the key + and its value is one of the constants defined here. + @constant kSecAttrAuthenticationTypeNTLM. + @constant kSecAttrAuthenticationTypeMSN. + @constant kSecAttrAuthenticationTypeDPA. + @constant kSecAttrAuthenticationTypeRPA. + @constant kSecAttrAuthenticationTypeHTTPBasic. + @constant kSecAttrAuthenticationTypeHTTPDigest. + @constant kSecAttrAuthenticationTypeHTMLForm. + @constant kSecAttrAuthenticationTypeDefault. +*/ +extern CFTypeRef kSecAttrAuthenticationTypeNTLM + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrAuthenticationTypeMSN + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrAuthenticationTypeDPA + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrAuthenticationTypeRPA + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrAuthenticationTypeHTTPBasic + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrAuthenticationTypeHTTPDigest + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrAuthenticationTypeHTMLForm + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecAttrAuthenticationTypeDefault + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @enum kSecAttrKeyClass Value Constants + @discussion Predefined item attribute constants used to get or set values + in a dictionary. The kSecAttrKeyClass constant is the key + and its value is one of the constants defined here. + @constant kSecAttrKeyClassPublic. + @constant kSecAttrKeyClassPrivate. + @constant kSecAttrKeyClassSymmetric. +*/ +extern CFTypeRef kSecAttrKeyClassPublic + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); +extern CFTypeRef kSecAttrKeyClassPrivate + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); +extern CFTypeRef kSecAttrKeyClassSymmetric + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + +/*! + @enum kSecAttrKeyType Value Constants + @discussion Predefined item attribute constants used to get or set values + in a dictionary. The kSecAttrKeyType constant is the key + and its value is one of the constants defined here. + @constant kSecAttrKeyTypeRSA. + @constant kSecAttrKeyTypeEC. +*/ +extern CFTypeRef kSecAttrKeyTypeRSA + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); +extern CFTypeRef kSecAttrKeyTypeEC + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); + +/*! + @enum Search Constants + @discussion Predefined search constants used to set values in a query + dictionary. You can specify a combination of search attributes and + item attributes when looking for matching items with the + SecItemCopyMatching function. + @constant kSecMatchPolicy Specifies a dictionary key whose value is a + SecPolicyRef. If provided, returned certificates or identities must + verify with this policy. + @constant kSecMatchIssuers Specifies a dictionary key whose value is a + CFArray of X.500 names (of type CFDataRef). If provided, returned + certificates or identities will be limited to those whose + certificate chain contains one of the issuers provided in this list. + @constant kSecMatchEmailAddressIfPresent Specifies a dictionary key whose + value is a CFStringRef containing an RFC822 email address. If + provided, returned certificates or identities will be limited to those + that contain the address, or do not contain any email address. + @constant kSecMatchSubjectContains Specifies a dictionary key whose value + is a CFStringRef. If provided, returned certificates or identities + will be limited to those containing this string in the subject. + @constant kSecMatchCaseInsensitive Specifies a dictionary key whose value + is a CFBooleanRef. If this value is kCFBooleanFalse, or is not + provided, then case-sensitive string matching is performed. + @constant kSecMatchTrustedOnly Specifies a dictionary key whose value is + a CFBooleanRef. If provided with a value of kCFBooleanTrue, only + certificates which can be verified back to a trusted anchor will be + returned. If this value is kCFBooleanFalse, or is not provided, then + both trusted and untrusted certificates may be returned. + @constant kSecMatchValidOnDate Specifies a dictionary key whose value is + of type CFDateRef. If provided, returned keys, certificates or + identities will be limited to those which are valid for the given date. + Pass a value of kCFNull to indicate the current date. + @constant kSecMatchLimit Specifies a dictionary key whose value is a + CFNumberRef. If provided, this value specifies the maximum number of + results to return. If not provided, results are limited to the first + item found. Predefined values are provided for a single item + (kSecMatchLimitOne) and all matching items (kSecMatchLimitAll). + @constant kSecMatchLimitOne Specifies that results are limited to the first + item found; used as a value for the kSecMatchLimit dictionary key. + @constant kSecMatchLimitAll Specifies that an unlimited number of results + may be returned; used as a value for the kSecMatchLimit dictionary + key. +*/ +extern CFTypeRef kSecMatchPolicy + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecMatchItemList + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecMatchSearchList + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecMatchIssuers + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecMatchEmailAddressIfPresent + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecMatchSubjectContains + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecMatchCaseInsensitive + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecMatchTrustedOnly + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecMatchValidOnDate + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecMatchLimit + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecMatchLimitOne + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecMatchLimitAll + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + + +/*! + @enum Return Type Key Constants + @discussion Predefined return type keys used to set values in a dictionary. + You use these keys to specify the type of results which should be + returned by the SecItemCopyMatching or SecItemAdd function. You can + specify zero or more of these return types. If more than one of these + result types is specified, the result is returned as a CFDictionaryRef + whose keys are the result types and values are the requested data. + @constant kSecReturnData Specifies a dictionary key whose value is of type + CFBooleanRef. A value of kCFBooleanTrue indicates that the data of + an item (CFDataRef) should be returned. For keys and password + items, data is secret (encrypted) and may require the user to enter + a password for access. + @constant kSecReturnAttributes Specifies a dictionary key whose value is + of type CFBooleanRef. A value of kCFBooleanTrue indicates that the + (non-encrypted) attributes of an item (CFDictionaryRef) should be + returned. + @constant kSecReturnRef Specifies a dictionary key whose value is a + CFBooleanRef. A value of kCFBooleanTrue indicates that a reference + should be returned. Depending on the item class requested, the + returned reference(s) may be of type SecKeychainItemRef, SecKeyRef, + SecCertificateRef, or SecIdentityRef. + @constant kSecReturnPersistentRef Specifies a dictionary key whose value + is of type CFBooleanRef. A value of kCFBooleanTrue indicates that a + persistent reference to an item (CFDataRef) should be returned. +*/ +extern CFTypeRef kSecReturnData + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecReturnAttributes + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecReturnRef + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecReturnPersistentRef + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + + +/*! + @enum Value Type Key Constants + @discussion Predefined value type keys used to pass values in a dictionary. + You can specify zero or more of these types depending on the function + you are calling. For SecItemCopyMatching or SecItemAdd these are + used as keys in the results dictionary. + @constant kSecValueData Specifies a dictionary key whose value is of type + CFDataRef. For keys and password items, data is secret (encrypted) + and may require the user to enter a password for access. + @constant kSecValueRef Specifies a dictionary key whose value, depending + on the item class requested, is of type SecKeychainItemRef, SecKeyRef, + SecCertificateRef, or SecIdentityRef. + @constant kSecValuePersistentRef Specifies a dictionary key whose value + is of type CFDataRef. The bytes in this CFDataRef can be stored by + the caller and used on a subsequent invocation of the application (or + even a different application) to retrieve the item referenced by it. +*/ +extern CFTypeRef kSecValueData + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecValueRef + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecValuePersistentRef + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + + +/*! + @enum Other Constants + @discussion Predefined constants used to set values in a dictionary. + @constant kSecUseItemList Specifies a dictionary key whose value is a + CFArray of items. If provided, this array is treated as the set of + all possible items to search, or add if the API being called is + SecItemAdd. The items in this array may be of type SecKeyRef, + SecCertificateRef, SecIdentityRef, or CFDataRef (for a persistent + item reference.) The items in the array must all be of the same + type. When this attribute is provided, no keychains are searched. + @constant kSecUseOperationPrompt Specifies a dictionary key whose value + is a CFStringRef that represents a user-visible string describing + the operation for which the application is attempting to authenticate. + The application is responsible for the text localization. + @constant kSecUseNoAuthenticationUI Specifies a dictionary key whose value + is a CFBooleanRef. If provided with a value of kCFBooleanTrue, the error + errSecInteractionNotAllowed will be returned if the item is attempting + to authenticate with UI. +*/ +extern CFTypeRef kSecUseItemList + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern CFTypeRef kSecUseOperationPrompt + __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); +extern CFTypeRef kSecUseNoAuthenticationUI + __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); + +/*! + @function SecItemCopyMatching + @abstract Returns one or more items which match a search query. + @param query A dictionary containing an item class specification and + optional attributes for controlling the search. See the "Keychain + Search Attributes" section for a description of currently defined + search attributes. + @param result On return, a CFTypeRef reference to the found item(s). The + exact type of the result is based on the search attributes supplied + in the query, as discussed below. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Attributes defining a search are specified by adding key/value + pairs to the query dictionary. + + A typical query consists of: + + * a kSecClass key, whose value is a constant from the Class + Constants section that specifies the class of item(s) to be searched + * one or more keys from the "Attribute Key Constants" section, whose value + is the attribute data to be matched + * one or more keys from the "Search Constants" section, whose value is + used to further refine the search + * a key from the "Return Type Key Constants" section, specifying the type of + results desired + + Result types are specified as follows: + + * To obtain the data of a matching item (CFDataRef), specify + kSecReturnData with a value of kCFBooleanTrue. + * To obtain the attributes of a matching item (CFDictionaryRef), specify + kSecReturnAttributes with a value of kCFBooleanTrue. + * To obtain a reference to a matching item (SecKeychainItemRef, + SecKeyRef, SecCertificateRef, or SecIdentityRef), specify kSecReturnRef + with a value of kCFBooleanTrue. + * To obtain a persistent reference to a matching item (CFDataRef), + specify kSecReturnPersistentRef with a value of kCFBooleanTrue. Note + that unlike normal references, a persistent reference may be stored + on disk or passed between processes. + * If more than one of these result types is specified, the result is + returned as a CFDictionaryRef containing all the requested data. + * If a result type is not specified, no results are returned. + + By default, this function returns only the first match found. To obtain + more than one matching item at a time, specify kSecMatchLimit with a value + greater than 1. The result will be a CFArrayRef containing up to that + number of matching items; the items' types are described above. + + To filter a provided list of items down to those matching the query, + specify a kSecMatchItemList whose value is a CFArray of SecKeychainItemRef, + SecKeyRef, SecCertificateRef, or SecIdentityRef items. The objects in the + provided array must be of the same type. + + To convert from a persistent item reference to a normal item reference, + specify a kSecValuePersistentRef whose value a CFDataRef (the persistent + reference), and a kSecReturnRef whose value is kCFBooleanTrue. +*/ +OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @function SecItemAdd + @abstract Add one or more items to a keychain. + @param attributes A dictionary containing an item class specification and + optional entries specifying the item's attribute values. See the + "Attribute Key Constants" section for a description of currently defined + attributes. + @param result On return, a CFTypeRef reference to the newly added item(s). + The exact type of the result is based on the values supplied + in attributes, as discussed below. Pass NULL if this result is not + required. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Attributes defining an item are specified by adding key/value + pairs to the attributes dictionary. To add multiple items to a keychain + at once use the kSecUseItemList key with an array of items as its value. + This is currently only supported for non password items. + + Result types are specified as follows: + + * To obtain the data of the added item (CFDataRef), specify + kSecReturnData with a value of kCFBooleanTrue. + * To obtain all the attributes of the added item (CFDictionaryRef), + specify kSecReturnAttributes with a value of kCFBooleanTrue. + * To obtain a reference to the added item (SecKeychainItemRef, SecKeyRef, + SecCertificateRef, or SecIdentityRef), specify kSecReturnRef with a + value of kCFBooleanTrue. + * To obtain a persistent reference to the added item (CFDataRef), specify + kSecReturnPersistentRef with a value of kCFBooleanTrue. Note that + unlike normal references, a persistent reference may be stored on disk + or passed between processes. + * If more than one of these result types is specified, the result is + returned as a CFDictionaryRef containing all the requested data. + * If a result type is not specified, no results are returned. +*/ +OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @function SecItemUpdate + @abstract Modify zero or more items which match a search query. + @param query A dictionary containing an item class specification and + optional attributes for controlling the search. See the "Attribute + Constants" and "Search Constants" sections for a description of + currently defined search attributes. + @param attributesToUpdate A dictionary containing one or more attributes + whose values should be set to the ones specified. Only real keychain + attributes are permitted in this dictionary (no "meta" attributes are + allowed.) See the "Attribute Key Constants" section for a description of + currently defined value attributes. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Attributes defining a search are specified by adding key/value + pairs to the query dictionary. +*/ +OSStatus SecItemUpdate(CFDictionaryRef query, + CFDictionaryRef attributesToUpdate) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @function SecItemDelete + @abstract Delete zero or more items which match a search query. + @param query A dictionary containing an item class specification and + optional attributes for controlling the search. See the "Attribute + Constants" and "Search Constants" sections for a description of + currently defined search attributes. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Attributes defining a search are specified by adding key/value + pairs to the query dictionary. + + By default, this function deletes all items matching the specified query. + You can change this behavior by specifying one of the follow keys: + + * To delete an item identified by a transient reference, specify + kSecValueRef with a reference returned by using the kSecReturnRef + key in a previous call to SecItemCopyMatching or SecItemAdd. + * To delete an item identified by a persistent reference, specify + kSecValuePersistentRef with a persistent reference returned by + using the kSecReturnPersistentRef key to SecItemCopyMatching or + SecItemAdd. + * To delete multiple items specify kSecMatchItemList with an array + of references. + * If more than one of these result keys is specified, the behavior is + undefined. +*/ +OSStatus SecItemDelete(CFDictionaryRef query) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +__END_DECLS + +#endif /* !_SECURITY_SECITEM_H_ */ diff --git a/Security/sec/Security/SecItemConstants.c b/Security/sec/Security/SecItemConstants.c new file mode 100644 index 00000000..7d84e9ba --- /dev/null +++ b/Security/sec/Security/SecItemConstants.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2006-2008,2010-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#define __CONSTANT_CFSTRINGS__ 1 +#include + +/* String constant declarations */ + +#define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); + +/* Class Key Constant */ +SEC_CONST_DECL (kSecClass, "class"); + +/* Class Value Constants */ +SEC_CONST_DECL (kSecClassGenericPassword, "genp"); +SEC_CONST_DECL (kSecClassInternetPassword, "inet"); +SEC_CONST_DECL (kSecClassAppleSharePassword, "apls"); +SEC_CONST_DECL (kSecClassCertificate, "cert"); +SEC_CONST_DECL (kSecClassKey, "keys"); +SEC_CONST_DECL (kSecClassIdentity, "idnt"); + +/* Attribute Key Constants */ +SEC_CONST_DECL (kSecAttrAccessible, "pdmn"); +SEC_CONST_DECL (kSecAttrAccessControl, "accc"); +SEC_CONST_DECL (kSecAttrAccessGroup, "agrp"); +SEC_CONST_DECL (kSecAttrCreationDate, "cdat"); +SEC_CONST_DECL (kSecAttrModificationDate, "mdat"); +SEC_CONST_DECL (kSecAttrDescription, "desc"); +SEC_CONST_DECL (kSecAttrComment, "icmt"); +SEC_CONST_DECL (kSecAttrCreator, "crtr"); +SEC_CONST_DECL (kSecAttrType, "type"); +SEC_CONST_DECL (kSecAttrLabel, "labl"); +SEC_CONST_DECL (kSecAttrIsInvisible, "invi"); +SEC_CONST_DECL (kSecAttrIsNegative, "nega"); +SEC_CONST_DECL (kSecAttrAccount, "acct"); +SEC_CONST_DECL (kSecAttrService, "svce"); +SEC_CONST_DECL (kSecAttrGeneric, "gena"); +SEC_CONST_DECL (kSecAttrSecurityDomain, "sdmn"); +SEC_CONST_DECL (kSecAttrServer, "srvr"); +SEC_CONST_DECL (kSecAttrProtocol, "ptcl"); +SEC_CONST_DECL (kSecAttrAuthenticationType, "atyp"); +SEC_CONST_DECL (kSecAttrPort, "port"); +SEC_CONST_DECL (kSecAttrPath, "path"); +SEC_CONST_DECL (kSecAttrVolume, "volm"); +SEC_CONST_DECL (kSecAttrAddress, "addr"); +SEC_CONST_DECL (kSecAttrAFPServerSignature, "afps"); +SEC_CONST_DECL (kSecAttrAlias, "alis"); +SEC_CONST_DECL (kSecAttrSubject, "subj"); +SEC_CONST_DECL (kSecAttrIssuer, "issr"); +SEC_CONST_DECL (kSecAttrSerialNumber, "slnr"); +SEC_CONST_DECL (kSecAttrSubjectKeyID, "skid"); +SEC_CONST_DECL (kSecAttrPublicKeyHash, "pkhh"); +SEC_CONST_DECL (kSecAttrCertificateType, "ctyp"); +SEC_CONST_DECL (kSecAttrCertificateEncoding, "cenc"); +SEC_CONST_DECL (kSecAttrKeyClass, "kcls"); +SEC_CONST_DECL (kSecAttrApplicationLabel, "klbl"); +SEC_CONST_DECL (kSecAttrIsPermanent, "perm"); +SEC_CONST_DECL (kSecAttrIsPrivate, "priv"); +SEC_CONST_DECL (kSecAttrIsModifiable, "modi"); +SEC_CONST_DECL (kSecAttrApplicationTag, "atag"); +SEC_CONST_DECL (kSecAttrKeyCreator, "crtr"); +SEC_CONST_DECL (kSecAttrKeyType, "type"); +SEC_CONST_DECL (kSecAttrKeySizeInBits, "bsiz"); +SEC_CONST_DECL (kSecAttrEffectiveKeySize, "esiz"); +SEC_CONST_DECL (kSecAttrStartDate, "sdat"); +SEC_CONST_DECL (kSecAttrEndDate, "edat"); +SEC_CONST_DECL (kSecAttrIsSensitive, "sens"); +SEC_CONST_DECL (kSecAttrWasAlwaysSensitive, "asen"); +SEC_CONST_DECL (kSecAttrIsExtractable, "extr"); +SEC_CONST_DECL (kSecAttrWasNeverExtractable, "next"); +SEC_CONST_DECL (kSecAttrCanEncrypt, "encr"); +SEC_CONST_DECL (kSecAttrCanDecrypt, "decr"); +SEC_CONST_DECL (kSecAttrCanDerive, "drve"); +SEC_CONST_DECL (kSecAttrCanSign, "sign"); +SEC_CONST_DECL (kSecAttrCanVerify, "vrfy"); +SEC_CONST_DECL (kSecAttrCanSignRecover, "snrc"); +SEC_CONST_DECL (kSecAttrCanVerifyRecover, "vyrc"); +SEC_CONST_DECL (kSecAttrCanWrap, "wrap"); +SEC_CONST_DECL (kSecAttrCanUnwrap, "unwp"); +/* Attribute Constants (Private) */ +SEC_CONST_DECL (kSecAttrScriptCode, "scrp"); +SEC_CONST_DECL (kSecAttrHasCustomIcon, "cusi"); +SEC_CONST_DECL (kSecAttrCRLType, "crlt"); +SEC_CONST_DECL (kSecAttrCRLEncoding, "crle"); +SEC_CONST_DECL (kSecAttrSynchronizable, "sync"); +SEC_CONST_DECL (kSecAttrSynchronizableAny, "syna"); +SEC_CONST_DECL (kSecAttrTombstone, "tomb"); + +/* Search Constants */ +SEC_CONST_DECL (kSecMatchPolicy, "m_Policy"); +SEC_CONST_DECL (kSecMatchItemList, "m_ItemList"); +SEC_CONST_DECL (kSecMatchSearchList, "m_SearchList"); +SEC_CONST_DECL (kSecMatchIssuers, "m_Issuers"); +SEC_CONST_DECL (kSecMatchEmailAddressIfPresent, "m_EmailAddressIfPresent"); +SEC_CONST_DECL (kSecMatchSubjectContains, "m_SubjectContains"); +SEC_CONST_DECL (kSecMatchCaseInsensitive, "m_CaseInsensitive"); +SEC_CONST_DECL (kSecMatchTrustedOnly, "m_TrustedOnly"); +SEC_CONST_DECL (kSecMatchValidOnDate, "m_ValidOnDate"); +SEC_CONST_DECL (kSecMatchLimit, "m_Limit"); +/* Could just use kCFBooleanTrue and kCFBooleanFalse for these 2. */ +SEC_CONST_DECL (kSecMatchLimitOne, "m_LimitOne"); +SEC_CONST_DECL (kSecMatchLimitAll, "m_LimitAll"); + +/* Return Type Key Constants */ +SEC_CONST_DECL (kSecReturnData, "r_Data"); +SEC_CONST_DECL (kSecReturnAttributes, "r_Attributes"); +SEC_CONST_DECL (kSecReturnRef, "r_Ref"); +SEC_CONST_DECL (kSecReturnPersistentRef, "r_PersistentRef"); + +/* Value Type Key Constants */ +SEC_CONST_DECL (kSecValueData, "v_Data"); +SEC_CONST_DECL (kSecValueRef, "v_Ref"); +SEC_CONST_DECL (kSecValuePersistentRef, "v_PersistentRef"); + +/* Other 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"); +#if defined(MULTIPLE_KEYCHAINS) +/* Other Constants (Private) */ +SEC_CONST_DECL (kSecUseKeychain, "u_Keychain"); +SEC_CONST_DECL (kSecUseKeychainList, "u_KeychainList"); +#endif /* !defined(MULTIPLE_KEYCHAINS) */ + +/* kSecAttrAccessible Value Constants. */ +SEC_CONST_DECL (kSecAttrAccessibleWhenUnlocked, "ak"); +SEC_CONST_DECL (kSecAttrAccessibleAfterFirstUnlock, "ck"); +SEC_CONST_DECL (kSecAttrAccessibleAlways, "dk"); +SEC_CONST_DECL (kSecAttrAccessibleWhenUnlockedThisDeviceOnly, "aku"); +SEC_CONST_DECL (kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, "cku"); +SEC_CONST_DECL (kSecAttrAccessibleAlwaysThisDeviceOnly, "dku"); +SEC_CONST_DECL (kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, "akpu"); + +/* kSecAttrProtocol Value Constants. */ +SEC_CONST_DECL (kSecAttrProtocolFTP, "ftp "); +SEC_CONST_DECL (kSecAttrProtocolFTPAccount, "ftpa"); +SEC_CONST_DECL (kSecAttrProtocolHTTP, "http"); +SEC_CONST_DECL (kSecAttrProtocolIRC, "irc "); +SEC_CONST_DECL (kSecAttrProtocolNNTP, "nntp"); +SEC_CONST_DECL (kSecAttrProtocolPOP3, "pop3"); +SEC_CONST_DECL (kSecAttrProtocolSMTP, "smtp"); +SEC_CONST_DECL (kSecAttrProtocolSOCKS, "sox "); +SEC_CONST_DECL (kSecAttrProtocolIMAP, "imap"); +SEC_CONST_DECL (kSecAttrProtocolLDAP, "ldap"); +SEC_CONST_DECL (kSecAttrProtocolAppleTalk, "atlk"); +SEC_CONST_DECL (kSecAttrProtocolAFP, "afp "); +SEC_CONST_DECL (kSecAttrProtocolTelnet, "teln"); +SEC_CONST_DECL (kSecAttrProtocolSSH, "ssh "); +SEC_CONST_DECL (kSecAttrProtocolFTPS, "ftps"); +SEC_CONST_DECL (kSecAttrProtocolHTTPS, "htps"); +SEC_CONST_DECL (kSecAttrProtocolHTTPProxy, "htpx"); +SEC_CONST_DECL (kSecAttrProtocolHTTPSProxy, "htsx"); +SEC_CONST_DECL (kSecAttrProtocolFTPProxy, "ftpx"); +SEC_CONST_DECL (kSecAttrProtocolSMB, "smb "); +SEC_CONST_DECL (kSecAttrProtocolRTSP, "rtsp"); +SEC_CONST_DECL (kSecAttrProtocolRTSPProxy, "rtsx"); +SEC_CONST_DECL (kSecAttrProtocolDAAP, "daap"); +SEC_CONST_DECL (kSecAttrProtocolEPPC, "eppc"); +SEC_CONST_DECL (kSecAttrProtocolIPP, "ipp "); +SEC_CONST_DECL (kSecAttrProtocolNNTPS, "ntps"); +SEC_CONST_DECL (kSecAttrProtocolLDAPS, "ldps"); +SEC_CONST_DECL (kSecAttrProtocolTelnetS, "tels"); +SEC_CONST_DECL (kSecAttrProtocolIMAPS, "imps"); +SEC_CONST_DECL (kSecAttrProtocolIRCS, "ircs"); +SEC_CONST_DECL (kSecAttrProtocolPOP3S, "pops"); + +/* kSecAttrAuthenticationType Value Constants. */ +SEC_CONST_DECL (kSecAttrAuthenticationTypeNTLM, "ntlm"); +SEC_CONST_DECL (kSecAttrAuthenticationTypeMSN, "msna"); +SEC_CONST_DECL (kSecAttrAuthenticationTypeDPA, "dpaa"); +SEC_CONST_DECL (kSecAttrAuthenticationTypeRPA, "rpaa"); +SEC_CONST_DECL (kSecAttrAuthenticationTypeHTTPBasic, "http"); +SEC_CONST_DECL (kSecAttrAuthenticationTypeHTTPDigest, "httd"); +SEC_CONST_DECL (kSecAttrAuthenticationTypeHTMLForm, "form"); +SEC_CONST_DECL (kSecAttrAuthenticationTypeDefault, "dflt"); + +/* kSecAttrKeyClass Value Constants. Based on + CSSM_KEYCLASS_PUBLIC_KEY = 0, + CSSM_KEYCLASS_PRIVATE_KEY = 1, + CSSM_KEYCLASS_SESSION_KEY = 2, + */ +SEC_CONST_DECL (kSecAttrKeyClassPublic, "0"); +SEC_CONST_DECL (kSecAttrKeyClassPrivate, "1"); +SEC_CONST_DECL (kSecAttrKeyClassSymmetric, "2"); + +/* kSecAttrKeyType Value Constants. Based on CSSM_ALGORITHMS. */ +SEC_CONST_DECL (kSecAttrKeyTypeRSA, "42"); +SEC_CONST_DECL (kSecAttrKeyTypeEC, "73"); /* rdar://10755886 */ + +/* Constants used by SecKeyGeneratePair() - in SecKey.h. Never used in + any SecItem apis directly. */ +SEC_CONST_DECL (kSecPrivateKeyAttrs, "private"); +SEC_CONST_DECL (kSecPublicKeyAttrs, "public"); + +/* Constants used by SecPassword - in SecPasswordStrength */ +SEC_CONST_DECL (kSecPasswordMaxLength, "PasswordMaxLength"); +SEC_CONST_DECL (kSecPasswordMinLength, "PasswordMaxLength"); +SEC_CONST_DECL (kSecPasswordAllowedCharacters, "PasswordAllowedCharacters"); +SEC_CONST_DECL (kSecPasswordRequiredCharacters, "PasswordRequiredCharacters"); + +/* Constants used by SecSharedCredential - in */ +SEC_CONST_DECL (kSecSharedPassword, "spwd"); diff --git a/sec/Security/SecItemInternal.h b/Security/sec/Security/SecItemInternal.h similarity index 81% rename from sec/Security/SecItemInternal.h rename to Security/sec/Security/SecItemInternal.h index bc59891d..ebce894b 100644 --- a/sec/Security/SecItemInternal.h +++ b/Security/sec/Security/SecItemInternal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2009,2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -31,12 +31,13 @@ #include #include +#include __BEGIN_DECLS #define kSecServerKeychainChangedNotification "com.apple.security.keychainchanged" -CFDataRef _SecItemMakePersistentRef(CFTypeRef class, sqlite_int64 rowid); +CF_RETURNS_RETAINED CFDataRef _SecItemMakePersistentRef(CFTypeRef class, sqlite_int64 rowid); bool _SecItemParsePersistentRef(CFDataRef persistent_ref, CFStringRef *return_class, sqlite_int64 *return_rowid); @@ -45,6 +46,9 @@ 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); + + __END_DECLS #endif /* !_SECURITY_SECITEMINTERNAL_H_ */ diff --git a/Security/sec/Security/SecItemPriv.h b/Security/sec/Security/SecItemPriv.h new file mode 100644 index 00000000..0d2a93e0 --- /dev/null +++ b/Security/sec/Security/SecItemPriv.h @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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 SecItemPriv + SecItemPriv defines private constants and SPI functions for access to + Security items (certificates, identities, keys, and keychain items.) +*/ + +#ifndef _SECURITY_SECITEMPRIV_H_ +#define _SECURITY_SECITEMPRIV_H_ + +#include +#include + +__BEGIN_DECLS + +/*! + @enum Class Value Constants (Private) + @discussion Predefined item class constants used to get or set values in + a dictionary. The kSecClass constant is the key and its value is one + of the constants defined here. + @constant kSecClassAppleSharePassword Specifies AppleShare password items. +*/ +extern CFTypeRef kSecClassAppleSharePassword; + + +/*! + @enum Attribute Key Constants (Private) + @discussion Predefined item attribute keys used to get or set values in a + dictionary. Not all attributes apply to each item class. The table + below lists the currently defined attributes for each item class: + + kSecClassGenericPassword item attributes: + kSecAttrAccessGroup + kSecAttrCreationDate + kSecAttrModificationDate + kSecAttrDescription + kSecAttrComment + kSecAttrCreator + kSecAttrType + kSecAttrScriptCode (private) + kSecAttrLabel + kSecAttrAlias (private) + kSecAttrIsInvisible + kSecAttrIsNegative + kSecAttrHasCustomIcon (private) + kSecAttrProtected (private) + kSecAttrAccount + kSecAttrService + kSecAttrGeneric + + kSecClassInternetPassword item attributes: + kSecAttrAccessGroup + kSecAttrCreationDate + kSecAttrModificationDate + kSecAttrDescription + kSecAttrComment + kSecAttrCreator + kSecAttrType + kSecAttrScriptCode (private) + kSecAttrLabel + kSecAttrAlias (private) + kSecAttrIsInvisible + kSecAttrIsNegative + kSecAttrHasCustomIcon (private) + kSecAttrProtected (private) + kSecAttrAccount + kSecAttrSecurityDomain + kSecAttrServer + kSecAttrProtocol + kSecAttrAuthenticationType + kSecAttrPort + kSecAttrPath + + kSecClassAppleSharePassword item attributes: + kSecAttrAccessGroup + kSecAttrCreationDate + kSecAttrModificationDate + kSecAttrDescription + kSecAttrComment + kSecAttrCreator + kSecAttrType + kSecAttrScriptCode (private) + kSecAttrLabel + kSecAttrAlias (private) + kSecAttrIsInvisible + kSecAttrIsNegative + kSecAttrHasCustomIcon (private) + kSecAttrProtected (private) + kSecAttrAccount + kSecAttrVolume + kSecAttrAddress + kSecAttrAFPServerSignature + + kSecClassCertificate item attributes: + kSecAttrAccessGroup + kSecAttrCertificateType + kSecAttrCertificateEncoding + kSecAttrLabel + kSecAttrAlias (private) + kSecAttrSubject + kSecAttrIssuer + kSecAttrSerialNumber + kSecAttrSubjectKeyID + kSecAttrPublicKeyHash + + kSecClassKey item attributes: + kSecAttrAccessGroup + kSecAttrKeyClass + kSecAttrLabel + kSecAttrAlias (private) + kSecAttrApplicationLabel + kSecAttrIsPermanent + kSecAttrIsPrivate (private) + kSecAttrIsModifiable (private) + kSecAttrApplicationTag + kSecAttrKeyCreator (private) + kSecAttrKeyType + kSecAttrKeySizeInBits + kSecAttrEffectiveKeySize + kSecAttrStartDate (private) + kSecAttrEndDate (private) + kSecAttrIsSensitive (private) + kSecAttrWasAlwaysSensitive (private) + kSecAttrIsExtractable (private) + kSecAttrWasNeverExtractable (private) + kSecAttrCanEncrypt + kSecAttrCanDecrypt + kSecAttrCanDerive + kSecAttrCanSign + kSecAttrCanVerify + kSecAttrCanSignRecover (private) + kSecAttrCanVerifyRecover (private) + kSecAttrCanWrap + kSecAttrCanUnwrap + + kSecClassIdentity item attributes: + Since an identity is the combination of a private key and a + certificate, this class shares attributes of both kSecClassKey and + kSecClassCertificate. + + @constant kSecAttrScriptCode Specifies a dictionary key whose value is the + item's script code attribute. You use this tag to set or get a value + of type CFNumberRef that represents a script code for this item's + strings. (Note: use of this attribute is deprecated; string attributes + should always be stored in UTF-8 encoding. This is currently private + for use by syncing; new code should not ever access this attribute.) + @constant kSecAttrAlias Specifies a dictionary key whose value is the + item's alias. You use this key to get or set a value of type CFDataRef + which represents an alias. For certificate items, the alias is either + a single email address, an array of email addresses, or the common + name of the certificate if it does not contain any email address. + (Items of class kSecClassCertificate have this attribute.) + @constant kSecAttrHasCustomIcon Specifies a dictionary key whose value is the + item's custom icon attribute. You use this tag to set or get a value + of type CFBooleanRef that indicates whether the item should have an + application-specific icon. (Note: use of this attribute is deprecated; + custom item icons are not supported in Mac OS X. This is currently + private for use by syncing; new code should not use this attribute.) + @constant kSecAttrVolume Specifies a dictionary key whose value is the + item's volume attribute. You use this key to set or get a CFStringRef + value that represents an AppleShare volume name. (Items of class + kSecClassAppleSharePassword have this attribute.) + @constant kSecAttrAddress Specifies a dictionary key whose value is the + item's address attribute. You use this key to set or get a CFStringRef + value that contains the AppleTalk zone name, or the IP or domain name + that represents the server address. (Items of class + kSecClassAppleSharePassword have this attribute.) + @constant kSecAttrAFPServerSignature Specifies a dictionary key whose value + is the item's AFP server signature attribute. You use this key to set + or get a CFDataRef value containing 16 bytes that represents the + server's signature block. (Items of class kSecClassAppleSharePassword + have this attribute.) + @constant kSecAttrCRLType (read-only) Specifies a dictionary key whose + value is the item's certificate revocation list type. You use this + key to get a value of type CFNumberRef that denotes the CRL type (see + the CSSM_CRL_TYPE enum in cssmtype.h). (Items of class + kSecClassCertificate have this attribute.) + @constant kSecAttrCRLEncoding (read-only) Specifies a dictionary key whose + value is the item's certificate revocation list encoding. You use + this key to get a value of type CFNumberRef that denotes the CRL + encoding (see the CSSM_CRL_ENCODING enum in cssmtype.h). (Items of + class kSecClassCertificate have this attribute.) + @constant kSecAttrKeyCreator Specifies a dictionary key whose value is a + CFDataRef containing a CSSM_GUID structure representing the module ID of + the CSP that owns this key. + @constant kSecAttrIsPrivate Specifies a dictionary key whose value is a + CFBooleanRef indicating whether the raw key material of the key in + question is private. + @constant kSecAttrIsModifiable Specifies a dictionary key whose value is a + CFBooleanRef indicating whether any of the attributes of this key are + modifiable. + @constant kSecAttrStartDate Specifies a dictionary key whose value is a + CFDateRef indicating the earliest date on which this key may be used. + If kSecAttrStartDate is not present, the restriction does not apply. + @constant kSecAttrEndDate Specifies a dictionary key whose value is a + CFDateRef indicating the last date on which this key may be used. + If kSecAttrEndDate is not present, the restriction does not apply. + @constant kSecAttrIsSensitive Specifies a dictionary key whose value + is a CFBooleanRef indicating whether the key in question must be wrapped + with an algorithm other than CSSM_ALGID_NONE. + @constant kSecAttrWasAlwaysSensitive Specifies a dictionary key whose value + is a CFBooleanRef indicating that the key in question has always been + marked as sensitive. + @constant kSecAttrIsExtractable Specifies a dictionary key whose value + is a CFBooleanRef indicating whether the key in question may be wrapped. + @constant kSecAttrWasNeverExtractable Specifies a dictionary key whose value + is a CFBooleanRef indicating that the key in question has never been + marked as extractable. + @constant kSecAttrCanSignRecover Specifies a dictionary key whole value is a + CFBooleanRef indicating whether the key in question can be used to + perform sign recovery. + @constant kSecAttrCanVerifyRecover Specifies a dictionary key whole value is + a CFBooleanRef indicating whether the key in question can be used to + perform verify recovery. + @constant kSecAttrTombstone Specifies a dictionary key whose value is + a CFBooleanRef indicating that the item in question is a tombstone. +*/ +extern CFTypeRef kSecAttrScriptCode; +extern CFTypeRef kSecAttrAlias; +extern CFTypeRef kSecAttrHasCustomIcon; +extern CFTypeRef kSecAttrVolume; +extern CFTypeRef kSecAttrAddress; +extern CFTypeRef kSecAttrAFPServerSignature; +extern CFTypeRef kSecAttrCRLType; +extern CFTypeRef kSecAttrCRLEncoding; +extern CFTypeRef kSecAttrKeyCreator; +extern CFTypeRef kSecAttrIsPrivate; +extern CFTypeRef kSecAttrIsModifiable; +extern CFTypeRef kSecAttrStartDate; +extern CFTypeRef kSecAttrEndDate; +extern CFTypeRef kSecAttrIsSensitive; +extern CFTypeRef kSecAttrWasAlwaysSensitive; +extern CFTypeRef kSecAttrIsExtractable; +extern CFTypeRef kSecAttrWasNeverExtractable; +extern CFTypeRef kSecAttrCanSignRecover; +extern CFTypeRef kSecAttrCanVerifyRecover; +extern CFTypeRef kSecAttrTombstone; + +/*! + @enum Other Constants (Private) + @discussion Predefined constants used to set values in a dictionary. + @constant kSecUseTombstones Specifies a dictionary key whose value is a + CFBooleanRef if present this overrides the default behaviour for when + we make tombstones. The default being we create tombstones for + synchronizable items unless we are explicitly deleting or updating a + tombstone. Setting this to false when calling SecItemDelete or + SecItemUpdate will ensure no tombstones are created. Setting it to + true will ensure we create tombstones even when deleting or updating non + synchronizable items. + @constant kSecUseKeychain Specifies a dictionary key whose value is a + keychain reference. You use this key to specify a value of type + SecKeychainRef that indicates the keychain to which SecItemAdd + will add the provided item(s). + @constant kSecUseKeychainList Specifies a dictionary key whose value is + either an array of keychains to search (CFArrayRef), or a single + keychain (SecKeychainRef). If not provided, the user's default + keychain list is searched. kSecUseKeychainList is ignored if an + explicit kSecUseItemList is also provided. This key can be used + for the SecItemCopyMatching, SecItemUpdate and SecItemDelete calls. + @constant kSecUseCredentialReference Specifies a CFDataRef containing + CoreAuthentication reference handle to be used when authorizing access + to the item. +*/ +extern CFTypeRef kSecUseTombstones + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecUseCredentialReference + __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); +#if defined(MULTIPLE_KEYCHAINS) +extern CFTypeRef kSecUseKeychain; +extern CFTypeRef kSecUseKeychainList; +#endif /* !defined(MULTIPLE_KEYCHAINS) */ + + +/*! + @function SecItemCopyDisplayNames + @abstract Returns an array containing unique display names for each of the + certificates, keys, identities, or passwords in the provided items + array. + @param items An array containing items of type SecKeychainItemRef, + SecKeyRef, SecCertificateRef, or SecIdentityRef. All items in the + array should be of the same type. + @param displayNames On return, an array of CFString references containing + unique names for the supplied items. You are responsible for releasing + this array reference by calling the CFRelease function. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Use this function to obtain item names which are suitable for + display in a menu or list view. The returned names are guaranteed to + be unique across the set of provided items. +*/ +OSStatus SecItemCopyDisplayNames(CFArrayRef items, CFArrayRef *displayNames); + +/*! + @function SecItemDeleteAll + @abstract Removes all items from the keychain and added root certificates + from the trust store. + @result A result code. See "Security Error Codes" (SecBase.h). +*/ +OSStatus SecItemDeleteAll(void); + +/* + Ensure the escrow keybag has been used to unlock the system keybag before + calling either of these APIs. + The password argument is optional, passing NULL implies no backup password + was set. We're assuming there will always be a backup keybag, except in + the OTA case where the loaded OTA backup bag will be used. + */ +CFDataRef _SecKeychainCopyBackup(CFDataRef backupKeybag, CFDataRef password); +CFDataRef _SecKeychainCopyOTABackup(void); +OSStatus _SecKeychainRestoreBackup(CFDataRef backup, CFDataRef backupKeybag, + CFDataRef password); + +OSStatus _SecKeychainBackupSyncable(CFDataRef keybag, CFDataRef password, CFDictionaryRef backup_in, CFDictionaryRef *backup_out); +OSStatus _SecKeychainRestoreSyncable(CFDataRef keybag, CFDataRef password, CFDictionaryRef backup_in); + +/* Called by clients to push sync circle and message changes to us. + Requires caller to have the kSecEntitlementKeychainSyncUpdates entitlement. */ +CFArrayRef _SecKeychainSyncUpdateKeyParameter(CFDictionaryRef updates, CFErrorRef *error); +CFArrayRef _SecKeychainSyncUpdateCircle(CFDictionaryRef updates, CFErrorRef *error); +CFArrayRef _SecKeychainSyncUpdateMessage(CFDictionaryRef updates, CFErrorRef *error); +/* Returns an OSStatus value for the given CFErrorRef, returns errSecInternal if the domain of the providied error is not recognized. Passing NULL returns errSecSuccess (0). */ +OSStatus SecErrorGetOSStatus(CFErrorRef error); + +bool _SecKeychainRollKeys(bool force, CFErrorRef *error); + +__END_DECLS + +#endif /* !_SECURITY_SECITEMPRIV_H_ */ diff --git a/sec/Security/SecKey.c b/Security/sec/Security/SecKey.c similarity index 94% rename from sec/Security/SecKey.c rename to Security/sec/Security/SecKey.c index 227a6c07..0ff9dde9 100644 --- a/sec/Security/SecKey.c +++ b/Security/sec/Security/SecKey.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2006-2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -36,7 +36,7 @@ #include #include "SecRSAKeyPriv.h" -#include "SecECKey.h" +#include "SecECKeyPriv.h" #include "SecBasePriv.h" #include @@ -56,13 +56,6 @@ #include #include -static pthread_once_t kSecKeyRegisterClass = PTHREAD_ONCE_INIT; -static CFTypeID kSecKeyTypeID = _kCFRuntimeNotATypeID; - -/* Forward declartions of static functions. */ -static CFStringRef SecKeyCopyDescription(CFTypeRef cf); -static void SecKeyDestroy(CFTypeRef cf); - /* Static functions. */ #define MAX_DIGEST_LEN (CC_SHA512_DIGEST_LENGTH) @@ -110,14 +103,6 @@ static size_t DEREncodeDigestInfoPrefix(const SecAsn1Oid *oid, return ix; } -static struct ccrng_system_state ccrng_system_state_seckey; - -static void register_algs(void) { - ccrng_seckey = (struct ccrng_state *)&ccrng_system_state_seckey; - ccrng_system_init(&ccrng_system_state_seckey); -} - - static CFDataRef SecKeyCopyPublicKeyHash(SecKeyRef key) { CFDataRef pubKeyDigest = NULL, pubKeyBlob = NULL; @@ -138,9 +123,9 @@ errOut: /* */ -static CF_RETURNS_RETAINED CFDictionaryRef SecKeyGenerateAttributeDictionaryFor(SecKeyRef key, - CFTypeRef keyType, - CFDataRef privateBlob) +static CFDictionaryRef SecKeyCopyAttributeDictionaryWithLocalKey(SecKeyRef key, + CFTypeRef keyType, + CFDataRef privateBlob) { CFAllocatorRef allocator = CFGetAllocator(key); DICT_DECLARE(25); @@ -197,17 +182,14 @@ CFDictionaryRef SecKeyGeneratePrivateAttributeDictionary(SecKeyRef key, CFTypeRef keyType, CFDataRef privateBlob) { - return SecKeyGenerateAttributeDictionaryFor(key, keyType, privateBlob); + return SecKeyCopyAttributeDictionaryWithLocalKey(key, keyType, privateBlob); } CFDictionaryRef SecKeyGeneratePublicAttributeDictionary(SecKeyRef key, CFTypeRef keyType) { - return SecKeyGenerateAttributeDictionaryFor(key, keyType, NULL); + return SecKeyCopyAttributeDictionaryWithLocalKey(key, keyType, NULL); } -/* - */ - static CFStringRef SecKeyCopyDescription(CFTypeRef cf) { SecKeyRef key = (SecKeyRef)cf; @@ -244,28 +226,13 @@ static Boolean SecKeyEqual(CFTypeRef cf1, CFTypeRef cf2) return result; } -static void SecKeyRegisterClass(void) { - static const CFRuntimeClass kSecKeyClass = { - 0, /* version */ - "SecKey", /* class name */ - NULL, /* init */ - NULL, /* copy */ - SecKeyDestroy, /* dealloc */ - SecKeyEqual, /* equal */ - NULL, /* hash */ - NULL, /* copyFormattingDesc */ - SecKeyCopyDescription /* copyDebugDesc */ - }; - - kSecKeyTypeID = _CFRuntimeRegisterClass(&kSecKeyClass); - register_algs(); -} +struct ccrng_state *ccrng_seckey; -/* Public API functions. */ -CFTypeID SecKeyGetTypeID(void) { - pthread_once(&kSecKeyRegisterClass, SecKeyRegisterClass); - return kSecKeyTypeID; -} +CFGiblisWithFunctions(SecKey, NULL, NULL, SecKeyDestroy, SecKeyEqual, NULL, NULL, SecKeyCopyDescription, NULL, NULL, ^{ + static struct ccrng_system_state ccrng_system_state_seckey; + ccrng_seckey = (struct ccrng_state *)&ccrng_system_state_seckey; + ccrng_system_init(&ccrng_system_state_seckey); +}) static bool getBoolForKey(CFDictionaryRef dict, CFStringRef key, bool default_value) { CFTypeRef value = CFDictionaryGetValue(dict, key); @@ -446,8 +413,7 @@ SecKeyRef SecKeyCreatePublicFromDER(CFAllocatorRef allocator, SecKeyRef SecKeyCreate(CFAllocatorRef allocator, const SecKeyDescriptor *key_class, const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) { - check(key_class); - + if (!key_class) return NULL; size_t size = sizeof(struct __SecKey) + key_class->extraBytes; SecKeyRef result = (SecKeyRef)_CFRuntimeCreateInstance(allocator, SecKeyGetTypeID(), size - sizeof(CFRuntimeBase), NULL); @@ -1097,3 +1063,45 @@ OSStatus SecKeyCopyPersistentRef(SecKeyRef key, CFDataRef* persistentRef) return status; } + +/* + * + */ + +#define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); + +SEC_CONST_DECL(_kSecKeyWrapPGPSymAlg, "kSecKeyWrapPGPSymAlg"); +SEC_CONST_DECL(_kSecKeyWrapPGPFingerprint, "kSecKeyWrapPGPFingerprint"); +SEC_CONST_DECL(_kSecKeyWrapPGPWrapAlg, "kSecKeyWrapPGPWrapAlg"); +SEC_CONST_DECL(_kSecKeyWrapRFC6637Flags, "kSecKeyWrapPGPECFlags"); +SEC_CONST_DECL(_kSecKeyWrapRFC6637WrapDigestSHA256KekAES128, "kSecKeyWrapPGPECWrapDigestSHA256KekAES128"); +SEC_CONST_DECL(_kSecKeyWrapRFC6637WrapDigestSHA512KekAES256, "kSecKeyWrapPGPECWrapDigestSHA512KekAES256"); + +#undef SEC_CONST_DECL + +CFDataRef +_SecKeyCopyWrapKey(SecKeyRef key, SecKeyWrapType type, CFDataRef unwrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error) +{ + if (error) + *error = NULL; + if (outParam) + *outParam = NULL; + if (key->key_class->version > 2 && key->key_class->copyWrapKey) + return key->key_class->copyWrapKey(key, type, unwrappedKey, parameters, outParam, error); + SecError(errSecUnsupportedOperation, error, CFSTR("No key wrap supported for key %@"), key); + return NULL; +} + +CFDataRef +_SecKeyCopyUnwrapKey(SecKeyRef key, SecKeyWrapType type, CFDataRef wrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error) +{ + if (error) + *error = NULL; + if (outParam) + *outParam = NULL; + if (key->key_class->version > 2 && key->key_class->copyUnwrapKey) + return key->key_class->copyUnwrapKey(key, type, wrappedKey, parameters, outParam, error); + + SecError(errSecUnsupportedOperation, error, CFSTR("No key unwrap for key %@"), key); + return NULL; +} diff --git a/Security/sec/Security/SecKey.h b/Security/sec/Security/SecKey.h new file mode 100644 index 00000000..96700755 --- /dev/null +++ b/Security/sec/Security/SecKey.h @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2006-2009,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@ + */ + +/*! + @header SecKey + The functions provided in SecKey.h implement and manage a particular + type of keychain item that represents a key. A key can be stored in a + keychain, but a key can also be a transient object. + + You can use a key as a keychain item in most functions. +*/ + +#ifndef _SECURITY_SECKEY_H_ +#define _SECURITY_SECKEY_H_ + +#include +#include +#include + +__BEGIN_DECLS + +/* Padding Types (iPhone OS 2.0 and later only). */ +typedef uint32_t SecPadding; +enum +{ + kSecPaddingNone = 0, + kSecPaddingPKCS1 = 1, + kSecPaddingOAEP = 2, + + /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is an MD2 + hash; standard ASN.1 padding will be done, as well as PKCS1 padding + of the underlying RSA operation. */ + kSecPaddingPKCS1MD2 = 0x8000, /* Unsupported as of iOS 5.0 */ + + /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is an MD5 + hash; standard ASN.1 padding will be done, as well as PKCS1 padding + of the underlying RSA operation. */ + kSecPaddingPKCS1MD5 = 0x8001, /* Unsupported as of iOS 5.0 */ + + /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is a SHA1 + hash; standard ASN.1 padding will be done, as well as PKCS1 padding + of the underlying RSA operation. */ + kSecPaddingPKCS1SHA1 = 0x8002, + + /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is a SHA224 + hash; standard ASN.1 padding will be done, as well as PKCS1 padding + of the underlying RSA operation. */ + kSecPaddingPKCS1SHA224 = 0x8003, + + /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is a SHA256 + hash; standard ASN.1 padding will be done, as well as PKCS1 padding + of the underlying RSA operation. */ + kSecPaddingPKCS1SHA256 = 0x8004, + + /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is a SHA384 + hash; standard ASN.1 padding will be done, as well as PKCS1 padding + of the underlying RSA operation. */ + kSecPaddingPKCS1SHA384 = 0x8005, + + /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is a SHA512 + hash; standard ASN.1 padding will be done, as well as PKCS1 padding + of the underlying RSA operation. */ + kSecPaddingPKCS1SHA512 = 0x8006, +}; + + +/*! + @function SecKeyGetTypeID + @abstract Returns the type identifier of SecKey instances. + @result The CFTypeID of SecKey instances. +*/ +CFTypeID SecKeyGetTypeID(void) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +/*! + @enum Dictionary key constants for SecKeyGeneratePair API. + @discussion Predefined key constants used to get or set values + in a dictionary. + @constant kSecPrivateKeyAttrs The value for this key is a CFDictionaryRef + containing attributes specific for the private key to be generated. + @constant kSecPublicKeyAttrs The value for this key is a CFDictionaryRef + containing attributes specific for the public key to be generated. +*/ +extern CFTypeRef kSecPrivateKeyAttrs + __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_2_0); +extern CFTypeRef kSecPublicKeyAttrs + __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_2_0); + +/*! + @function SecKeyGeneratePair + @abstract Generate a private/public keypair. + @param parameters A dictionary containing one or more key-value pairs. + See the discussion sections below for a complete overview of options. + @param publicKey On return, a SecKeyRef reference to the public key. + @param privateKey On return, a SecKeyRef reference to the private key. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion In order to generate a keypair the parameters dictionary must + at least contain the following keys: + + * kSecAttrKeyType with a value being kSecAttrKeyTypeRSA or any other + kSecAttrKeyType defined in SecItem.h + * kSecAttrKeySizeInBits with a value being a CFNumberRef or CFStringRef + containing the requested key size in bits. Example sizes for RSA + keys are: 512, 768, 1024, 2048. + + The values below may be set either in the top-level dictionary or in a + dictionary that is the value of the kSecPrivateKeyAttrs or + kSecPublicKeyAttrs key in the top-level dictionary. Setting these + attributes explicitly will override the defaults below. See SecItem.h + for detailed information on these attributes including the types of + the values. + + * kSecAttrLabel default NULL + * kSecAttrIsPermanent if this key is present and has a Boolean + value of true, the key or key pair will be added to the default + keychain. + * kSecAttrApplicationTag default NULL + * kSecAttrEffectiveKeySize default NULL same as kSecAttrKeySizeInBits + * kSecAttrCanEncrypt default false for private keys, true for public keys + * kSecAttrCanDecrypt default true for private keys, false for public keys + * kSecAttrCanDerive default true + * kSecAttrCanSign default true for private keys, false for public keys + * kSecAttrCanVerify default false for private keys, true for public keys + * kSecAttrCanWrap default false for private keys, true for public keys + * kSecAttrCanUnwrap default true for private keys, false for public keys + +*/ +OSStatus SecKeyGeneratePair(CFDictionaryRef parameters, SecKeyRef *publicKey, + SecKeyRef *privateKey) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + + +/*! + @function SecKeyRawSign + @abstract Given a private key and data to sign, generate a digital + signature. + @param key Private key with which to sign. + @param padding See Padding Types above, typically kSecPaddingPKCS1SHA1. + @param dataToSign The data to be signed, typically the digest of the + actual data. + @param dataToSignLen Length of dataToSign in bytes. + @param sig Pointer to buffer in which the signature will be returned. + @param sigLen IN/OUT maximum length of sig buffer on input, actualy + length of sig on output. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion If the padding argument is kSecPaddingPKCS1, PKCS1 padding + will be performed prior to signing. If this argument is kSecPaddingNone, + the incoming data will be signed "as is". + + When PKCS1 padding is performed, the maximum length of data that can + be signed is the value returned by SecKeyGetBlockSize() - 11. + + NOTE: The behavior this function with kSecPaddingNone is undefined if the + first byte of dataToSign is zero; there is no way to verify leading zeroes + as they are discarded during the calculation. + + If you want to generate a proper PKCS1 style signature with DER encoding + of the digest type - and the dataToSign is a SHA1 digest - use + kSecPaddingPKCS1SHA1. + */ +OSStatus SecKeyRawSign( + SecKeyRef key, + SecPadding padding, + const uint8_t *dataToSign, + size_t dataToSignLen, + uint8_t *sig, + size_t *sigLen) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + + +/*! + @function SecKeyRawVerify + @abstract Given a public key, data which has been signed, and a signature, + verify the signature. + @param key Public key with which to verify the signature. + @param padding See Padding Types above, typically kSecPaddingPKCS1SHA1. + @param signedData The data over which sig is being verified, typically + the digest of the actual data. + @param signedDataLen Length of signedData in bytes. + @param sig Pointer to the signature to verify. + @param sigLen Length of sig in bytes. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion If the padding argument is kSecPaddingPKCS1, PKCS1 padding + will be checked during verification. If this argument is kSecPaddingNone, + the incoming data will be compared directly to sig. + + If you are verifying a proper PKCS1-style signature, with DER encoding + of the digest type - and the signedData is a SHA1 digest - use + kSecPaddingPKCS1SHA1. + */ +OSStatus SecKeyRawVerify( + SecKeyRef key, + SecPadding padding, + const uint8_t *signedData, + size_t signedDataLen, + const uint8_t *sig, + size_t sigLen) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + + +/*! + @function SecKeyEncrypt + @abstract Encrypt a block of plaintext. + @param key Public key with which to encrypt the data. + @param padding See Padding Types above, typically kSecPaddingPKCS1. + @param plainText The data to encrypt. + @param plainTextLen Length of plainText in bytes, this must be less + or equal to the value returned by SecKeyGetBlockSize(). + @param cipherText Pointer to the output buffer. + @param cipherTextLen On input, specifies how much space is available at + cipherText; on return, it is the actual number of cipherText bytes written. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion If the padding argument is kSecPaddingPKCS1, PKCS1 padding + will be performed prior to encryption. If this argument is kSecPaddingNone, + the incoming data will be encrypted "as is". + + When PKCS1 padding is performed, the maximum length of data that can + be encrypted is the value returned by SecKeyGetBlockSize() - 11. + + When memory usage is a critical issue, note that the input buffer + (plainText) can be the same as the output buffer (cipherText). + */ +OSStatus SecKeyEncrypt( + SecKeyRef key, + SecPadding padding, + const uint8_t *plainText, + size_t plainTextLen, + uint8_t *cipherText, + size_t *cipherTextLen) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + + +/*! + @function SecKeyDecrypt + @abstract Decrypt a block of ciphertext. + @param key Private key with which to decrypt the data. + @param padding See Padding Types above, typically kSecPaddingPKCS1. + @param cipherText The data to decrypt. + @param cipherTextLen Length of cipherText in bytes, this must be less + or equal to the value returned by SecKeyGetBlockSize(). + @param plainText Pointer to the output buffer. + @param plainTextLen On input, specifies how much space is available at + plainText; on return, it is the actual number of plainText bytes written. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion If the padding argument is kSecPaddingPKCS1, PKCS1 padding + will be removed after decryption. If this argument is kSecPaddingNone, + the decrypted data will be returned "as is". + + When memory usage is a critical issue, note that the input buffer + (plainText) can be the same as the output buffer (cipherText). + */ +OSStatus SecKeyDecrypt( + SecKeyRef key, /* Private key */ + SecPadding padding, /* kSecPaddingNone, + kSecPaddingPKCS1, + kSecPaddingOAEP */ + const uint8_t *cipherText, + size_t cipherTextLen, /* length of cipherText */ + uint8_t *plainText, + size_t *plainTextLen) /* IN/OUT */ + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + +/*! + @function SecKeyGetBlockSize + @abstract Decrypt a block of ciphertext. + @param key The key for which the block length is requested. + @result The block length of the key in bytes. + @discussion If for example key is an RSA key the value returned by + this function is the size of the modulus. + */ +size_t SecKeyGetBlockSize(SecKeyRef key) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + + +__END_DECLS + +#endif /* !_SECURITY_SECKEY_H_ */ diff --git a/sec/Security/SecKeyInternal.h b/Security/sec/Security/SecKeyInternal.h similarity index 91% rename from sec/Security/SecKeyInternal.h rename to Security/sec/Security/SecKeyInternal.h index 337f5ffb..7a71b7d4 100644 --- a/sec/Security/SecKeyInternal.h +++ b/Security/sec/Security/SecKeyInternal.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2010,2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2010-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -33,7 +33,7 @@ __BEGIN_DECLS -struct ccrng_state *ccrng_seckey; +extern struct ccrng_state *ccrng_seckey; __END_DECLS diff --git a/Security/sec/Security/SecKeyPriv.h b/Security/sec/Security/SecKeyPriv.h new file mode 100644 index 00000000..2fc55910 --- /dev/null +++ b/Security/sec/Security/SecKeyPriv.h @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2006-2010,2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecKeyPriv + The functions provided in SecKeyPriv.h implement and manage a particular + type of keychain item that represents a key. A key can be stored in a + keychain, but a key can also be a transient object. + + You can use a key as a keychain item in most functions. +*/ + +#ifndef _SECURITY_SECKEYPRIV_H_ +#define _SECURITY_SECKEYPRIV_H_ + +#include +#include +#include +#include + +__BEGIN_DECLS + +typedef struct __SecDERKey { + uint8_t *oid; + CFIndex oidLength; + + uint8_t *parameters; + CFIndex parametersLength; + + /* Contents of BIT STRING in DER Encoding */ + uint8_t *key; + CFIndex keyLength; +} SecDERKey; + + +typedef uint32_t SecKeyEncoding; +enum { + /* Typically only used for symmetric keys. */ + kSecKeyEncodingRaw = 0, + + /* RSA keys are DER-encoded according to PKCS1. */ + kSecKeyEncodingPkcs1 = 1, + + /* RSA keys are DER-encoded according to PKCS1 with Apple Extensions. */ + kSecKeyEncodingApplePkcs1 = 2, + + /* RSA public key in SecRSAPublicKeyParams format. keyData is a pointer + to a SecRSAPublicKeyParams and keyDataLength is + sizeof(SecRSAPublicKeyParams). */ + kSecKeyEncodingRSAPublicParams = 3, + + /* RSA public key in SecRSAPublicKeyParams format. keyData is a pointer + to a SecRSAPublicKeyParams and keyDataLength is + sizeof(SecRSAPublicKeyParams). */ + kSecDERKeyEncoding = 4, + + /* Internal "encodings to send other data" */ + kSecGenerateKey = 5, + kSecExtractPublicFromPrivate = 6, + + /* Encoding came from SecKeyCopyPublicBytes for a public key, + or internally from a private key */ + kSecKeyEncodingBytes = 7, + + /* Handing in a private key from corecrypto directly. */ + kSecKeyCoreCrypto = 8, + +}; + +typedef uint32_t SecKeyWrapType; +enum { + /* wrap key in RFC3394 (AESWrap) */ + kSecKeyWrapRFC3394 = 0, + + /* wrap key in PGP style (support EC keys only right now) */ + kSecKeyWrapPublicKeyPGP = 1, + +}; + +typedef OSStatus (*SecKeyInitMethod)(SecKeyRef, const uint8_t *, CFIndex, + SecKeyEncoding); +typedef void (*SecKeyDestroyMethod)(SecKeyRef); +typedef OSStatus (*SecKeyRawSignMethod)(SecKeyRef key, SecPadding padding, + const uint8_t *dataToSign, size_t dataToSignLen, + uint8_t *sig, size_t *sigLen); +typedef OSStatus (*SecKeyRawVerifyMethod)( + SecKeyRef key, SecPadding padding, const uint8_t *signedData, + size_t signedDataLen, const uint8_t *sig, size_t sigLen); +typedef OSStatus (*SecKeyEncryptMethod)(SecKeyRef key, SecPadding padding, + const uint8_t *plainText, size_t plainTextLen, + uint8_t *cipherText, size_t *cipherTextLen); +typedef OSStatus (*SecKeyDecryptMethod)(SecKeyRef key, SecPadding padding, + const uint8_t *cipherText, size_t cipherTextLen, + uint8_t *plainText, size_t *plainTextLen); +typedef OSStatus (*SecKeyComputeMethod)(SecKeyRef key, + const uint8_t *pub_key, size_t pub_key_len, + uint8_t *computed_key, size_t *computed_key_len); +typedef size_t (*SecKeyBlockSizeMethod)(SecKeyRef key); +typedef CFDictionaryRef (*SecKeyCopyDictionaryMethod)(SecKeyRef key); +typedef CFIndex (*SecKeyGetAlgorithmIDMethod)(SecKeyRef key); +typedef OSStatus (*SecKeyCopyPublicBytesMethod)(SecKeyRef key, CFDataRef *serialization); +typedef CFDataRef (*SecKeyCopyWrapKeyMethod)(SecKeyRef key, SecKeyWrapType type, CFDataRef unwrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error); +typedef CFDataRef (*SecKeyCopyUnwrapKeyMethod)(SecKeyRef key, SecKeyWrapType type, CFDataRef wrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error); +typedef CFStringRef (*SecKeyDescribeMethod)(SecKeyRef key); + +#define kSecKeyDescriptorVersion (3) + +typedef struct __SecKeyDescriptor { + /* Version of this SecKeyDescriptor. Must be kSecKeyDescriptorVersion. */ + uint32_t version; + + /* Name of this key class for use by SecKeyShow(). */ + const char *name; + + /* If nonzero, SecKeyCreate will allocate this many bytes for the key + field in the SecKeyRef it creates. If zero key is NULL and the + implementor can choose to dynamically allocate it in the init + function and free it in the destroy function. */ + uint32_t extraBytes; + + /* Called by SecKeyCreate(). */ + SecKeyInitMethod init; + /* Called by destructor (final CFRelease() or gc if using). */ + SecKeyDestroyMethod destroy; + /* Called by SecKeyRawSign(). */ + SecKeyRawSignMethod rawSign; + /* Called by SecKeyRawVerify(). */ + SecKeyRawVerifyMethod rawVerify; + /* Called by SecKeyEncrypt(). */ + SecKeyEncryptMethod encrypt; + /* Called by SecKeyDecrypt(). */ + SecKeyDecryptMethod decrypt; + /* Reserved for future use. */ + SecKeyComputeMethod compute; + /* Called by SecKeyGetBlockSize(). */ + SecKeyBlockSizeMethod blockSize; + /* Called by SecKeyCopyAttributeDictionary(), which is private. */ + SecKeyCopyDictionaryMethod copyDictionary; + /* Called by SecKeyDescribeMethod(). */ + SecKeyDescribeMethod describe; +#if kSecKeyDescriptorVersion > 0 + /* Called by SecKeyCopyAttributeDictionary(), which is private. */ + SecKeyGetAlgorithmIDMethod getAlgorithmID; +#endif +#if kSecKeyDescriptorVersion > 1 + SecKeyCopyPublicBytesMethod copyPublic; +#endif +#if kSecKeyDescriptorVersion > 2 + SecKeyCopyWrapKeyMethod copyWrapKey; + SecKeyCopyUnwrapKeyMethod copyUnwrapKey; +#endif +} SecKeyDescriptor; + +struct __SecKey { + CFRuntimeBase _base; + + const SecKeyDescriptor *key_class; + + /* The actual key handled by class. */ + void *key; +}; + +/*! + @function SecKeyCreate + @abstract Given a private key and data to sign, generate a digital signature. + @param allocator allocator to use when allocating this key instance. + @param key_class pointer to a SecKeyDescriptor. + @param keyData The second argument to the init() function in the key_class. + @param keyDataLength The third argument to the init() function in the key_class. + @param encoding The fourth argument to the init() function in the key_class. + @result A newly allocated SecKeyRef. + */ +SecKeyRef SecKeyCreate(CFAllocatorRef allocator, + const SecKeyDescriptor *key_class, const uint8_t *keyData, + CFIndex keyDataLength, SecKeyEncoding encoding); + +/* Create a public key from an oid, params and keyData all in DER format. */ +SecKeyRef SecKeyCreatePublicFromDER(CFAllocatorRef allocator, + const SecAsn1Oid *oid1, const SecAsn1Item *params, + const SecAsn1Item *keyData); + +/* Create public key from private key */ +SecKeyRef SecKeyCreatePublicFromPrivate(SecKeyRef privateKey); +SecKeyRef SecKeyCopyMatchingPrivateKey(SecKeyRef publicKey, CFErrorRef *error); +CFDataRef SecKeyCreatePersistentRefToMatchingPrivateKey(SecKeyRef publicKey, CFErrorRef *error); + +/* Return an attribute dictionary used to store this item in a keychain. */ +CFDictionaryRef SecKeyCopyAttributeDictionary(SecKeyRef key); + +/* Return a key from an attribute dictionary that was used to store this item + in a keychain. */ +SecKeyRef SecKeyCreateFromAttributeDictionary(CFDictionaryRef refAttributes); + +OSStatus SecKeyDigestAndVerify( + SecKeyRef key, /* Public key */ + const SecAsn1AlgId *algId, /* algorithm oid/params */ + const uint8_t *dataToDigest, /* signature over this data */ + size_t dataToDigestLen,/* length of dataToDigest */ + const uint8_t *sig, /* signature to verify */ + size_t sigLen); /* length of sig */ + +OSStatus SecKeyDigestAndSign( + SecKeyRef key, /* Private key */ + const SecAsn1AlgId *algId, /* algorithm oid/params */ + const uint8_t *dataToDigest, /* signature over this data */ + size_t dataToDigestLen,/* length of dataToDigest */ + uint8_t *sig, /* signature, RETURNED */ + size_t *sigLen); /* IN/OUT */ + +OSStatus SecKeyVerifyDigest( + SecKeyRef key, /* Private key */ + const SecAsn1AlgId *algId, /* algorithm oid/params */ + const uint8_t *digestData, /* signature over this digest */ + size_t digestDataLen,/* length of dataToDigest */ + const uint8_t *sig, /* signature to verify */ + size_t sigLen); /* length of sig */ + +OSStatus SecKeySignDigest( + SecKeyRef key, /* Private key */ + const SecAsn1AlgId *algId, /* algorithm oid/params */ + const uint8_t *digestData, /* signature over this digest */ + size_t digestDataLen,/* length of digestData */ + uint8_t *sig, /* signature, RETURNED */ + size_t *sigLen); /* IN/OUT */ + +OSStatus SecKeyCopyPublicBytes(SecKeyRef key, CFDataRef* serializedPublic); +SecKeyRef SecKeyCreateFromPublicBytes(CFAllocatorRef allocator, CFIndex algorithmID, const uint8_t *keyData, CFIndex keyDataLength); +SecKeyRef SecKeyCreateFromPublicData(CFAllocatorRef allocator, CFIndex algorithmID, CFDataRef serialized); + +CF_RETURNS_RETAINED +CFDictionaryRef SecKeyGeneratePrivateAttributeDictionary(SecKeyRef key, + CFTypeRef keyType, + CFDataRef privateBlob); +CF_RETURNS_RETAINED +CFDictionaryRef SecKeyGeneratePublicAttributeDictionary(SecKeyRef key, CFTypeRef keyType); + +enum { + kSecNullAlgorithmID = 0, + kSecRSAAlgorithmID = 1, + kSecDSAAlgorithmID = 2, /* unsupported, just here for reference. */ + kSecECDSAAlgorithmID = 3, +}; + +CFIndex SecKeyGetAlgorithmID(SecKeyRef key); + +typedef enum { + kSecKeyKeySizeInBits = 0, + kSecKeySignatureSize = 1, + kSecKeyEncryptedDataSize = 2, + // More might belong here, but we aren't settled on how + // to take into account padding and/or digest types. +} SecKeySize; + +/*! + @function SecKeyGetSize + @abstract Returns a size in bytes. + @param key The key for which the block length is requested. + @param whichSize The size that you want evaluated. + @result The block length of the key in bytes. + @discussion If for example key is an RSA key the value returned by + this function is the size of the modulus. + */ +size_t SecKeyGetSize(SecKeyRef key, SecKeySize whichSize) +__OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_5_0); + + +/*! + @function SecKeyLookupPersistentRef + @abstract Looks up a SecKeyRef via persistent ref. + @param persistentRef The persistent ref data for looking up. + @param lookedUpData retained SecKeyRef for the found object. + @result Errors when using SecItemFind for the persistent ref. + */ +OSStatus SecKeyFindWithPersistentRef(CFDataRef persistentRef, SecKeyRef* lookedUpData) +__OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + +/*! + @function SecKeyCopyPersistentRef + @abstract Gets a persistent reference for a key. + @param key Key to make a persistent ref for. + @param persistentRef Allocated data representing the persistent ref. + @result Errors when using SecItemFind for the persistent ref. + */ +OSStatus SecKeyCopyPersistentRef(SecKeyRef key, CFDataRef* persistentRef) +__OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + + +/* + * + */ + +extern CFTypeRef _kSecKeyWrapPGPSymAlg; /* CFNumber */ +extern CFTypeRef _kSecKeyWrapPGPFingerprint; /* CFDataRef, at least 20 bytes */ +extern CFTypeRef _kSecKeyWrapPGPWrapAlg; /* kSecKeyWrapRFC6637WrapNNN, or any of the other PGP wrap algs */ +extern CFTypeRef _kSecKeyWrapRFC6637Flags; +extern CFTypeRef _kSecKeyWrapRFC6637WrapDigestSHA256KekAES128; +extern CFTypeRef _kSecKeyWrapRFC6637WrapDigestSHA512KekAES256; + +enum { kSecKeyWrapPGPFingerprintMinSize = 20 }; +/*! + @function _SecKeyCopyWrapKey + @abstract Wrap a key + */ + +CFDataRef +_SecKeyCopyWrapKey(SecKeyRef key, SecKeyWrapType type, CFDataRef unwrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error) +__OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); + +/*! + @function _SecKeyWrapKey + @abstract Unwrap a key + */ + +CFDataRef +_SecKeyCopyUnwrapKey(SecKeyRef key, SecKeyWrapType type, CFDataRef wrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error) +__OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); + + +__END_DECLS + +#endif /* !_SECURITY_SECKEYPRIV_H_ */ diff --git a/Security/sec/Security/SecLogging.c b/Security/sec/Security/SecLogging.c new file mode 100644 index 00000000..78d30069 --- /dev/null +++ b/Security/sec/Security/SecLogging.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include "securityd_client.h" +#include "SecuritydXPC.h" + +static bool dict_to_error_request(enum SecXPCOperation op, CFDictionaryRef query, CFErrorRef *error) +{ + return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { + return SecXPCDictionarySetPList(message, kSecXPCKeyQuery, query, error); + }, NULL); +} + +static CFDictionaryRef void_to_dict_error_request(enum SecXPCOperation op, CFErrorRef *error) { + __block CFDictionaryRef dict = NULL; + securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) { + return (dict = SecXPCDictionaryCopyPList(response, kSecXPCKeyResult, error)); + }); + return dict; +} + +CFArrayRef SecGetCurrentServerLoggingInfo(CFErrorRef *error) +{ + return SECURITYD_XPC(sec_get_log_settings, void_to_dict_error_request, error); +} + +bool SecSetLoggingInfoForXPCScope(CFPropertyListRef /* String or Dictionary of strings */ settings, CFErrorRef *error) +{ + return SECURITYD_XPC(sec_set_xpc_log_settings, dict_to_error_request, settings, error); + +} diff --git a/Security/sec/Security/SecLogging.h b/Security/sec/Security/SecLogging.h new file mode 100644 index 00000000..cad6f6f0 --- /dev/null +++ b/Security/sec/Security/SecLogging.h @@ -0,0 +1,18 @@ +// +// SecLogging.h +// sec +// +// Remote control for logging settings in securityd/secd +// + + +#ifndef _SECURITY_SECLOGGING_H_ +#define _SECURITY_SECLOGGING_H_ + +#include + +CFArrayRef SecGetCurrentServerLoggingInfo(CFErrorRef *error); + +bool SecSetLoggingInfoForXPCScope(CFPropertyListRef /* String or Dictionary of strings */ settings, CFErrorRef *error); + +#endif diff --git a/Security/sec/Security/SecOTR.h b/Security/sec/Security/SecOTR.h new file mode 100644 index 00000000..743320a2 --- /dev/null +++ b/Security/sec/Security/SecOTR.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef _SECOTR_H_ +#define _SECOTR_H_ + +/* + * Message Protection interfaces +*/ + +#include +#include +#include +#include + +#include + +__BEGIN_DECLS + +/*! + @typedef + @abstract Full identity (public and private) for Message Protection + @discussion Abstracts what kind of crypto is going on beyond it being public/priate +*/ +typedef struct _SecOTRFullIdentity* SecOTRFullIdentityRef; + +/*! + @typedef + @abstract Public identity for Message Protection message validation and encryption to send + @discussion Abstracts what kind of crypto is going on beyond it being public/priate + */ +typedef struct _SecOTRPublicIdentity* SecOTRPublicIdentityRef; + +/* + * Full identity functions + */ +SecOTRFullIdentityRef SecOTRFullIdentityCreate(CFAllocatorRef allocator, CFErrorRef *error); + +SecOTRFullIdentityRef SecOTRFullIdentityCreateFromSecKeyRef(CFAllocatorRef allocator, SecKeyRef privateKey, + CFErrorRef *error); +SecOTRFullIdentityRef SecOTRFullIdentityCreateFromData(CFAllocatorRef allocator, CFDataRef serializedData, CFErrorRef *error); + +SecOTRFullIdentityRef SecOTRFullIdentityCreateFromBytes(CFAllocatorRef allocator, const uint8_t**bytes, size_t *size, CFErrorRef *error); + +bool SecOTRFIPurgeFromKeychain(SecOTRFullIdentityRef thisID, CFErrorRef *error); + +bool SecOTRFIAppendSerialization(SecOTRFullIdentityRef fullID, CFMutableDataRef serializeInto, CFErrorRef *error); + + +bool SecOTRFIPurgeAllFromKeychain(CFErrorRef *error); + + +/* + * Public identity functions + */ +SecOTRPublicIdentityRef SecOTRPublicIdentityCopyFromPrivate(CFAllocatorRef allocator, SecOTRFullIdentityRef fullID, CFErrorRef *error); + +SecOTRPublicIdentityRef SecOTRPublicIdentityCreateFromSecKeyRef(CFAllocatorRef allocator, SecKeyRef publicKey, + CFErrorRef *error); + +SecOTRPublicIdentityRef SecOTRPublicIdentityCreateFromData(CFAllocatorRef allocator, CFDataRef serializedData, CFErrorRef *error); +SecOTRPublicIdentityRef SecOTRPublicIdentityCreateFromBytes(CFAllocatorRef allocator, const uint8_t**bytes, size_t * size, CFErrorRef *error); + +bool SecOTRPIAppendSerialization(SecOTRPublicIdentityRef publicID, CFMutableDataRef serializeInto, CFErrorRef *error); + +void SecOTRAdvertiseHashes(bool advertise); + +__END_DECLS + +#endif diff --git a/Security/sec/Security/SecOTRDHKey.c b/Security/sec/Security/SecOTRDHKey.c new file mode 100644 index 00000000..fb5d2e25 --- /dev/null +++ b/Security/sec/Security/SecOTRDHKey.c @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include "SecOTRDHKey.h" +#include + +#include "SecOTRMath.h" +#include "SecOTRPacketData.h" + +#include +#include +#include +#include + +#include + +#define kECKeySize 256 + +struct _SecOTRFullDHKey { + CFRuntimeBase _base; + + ccec_full_ctx_decl(ccn_sizeof(kECKeySize), _key); + uint8_t keyHash[CCSHA1_OUTPUT_SIZE]; + +}; + +CFGiblisWithCompareFor(SecOTRFullDHKey); + +static size_t AppendECPublicKeyAsDATA(CFMutableDataRef data, ccec_pub_ctx_t public_key) +{ + size_t size = ccec_export_pub_size(public_key); + + AppendLong(data, (uint32_t)size); /* cast: no overflow, pub size always fit in 32 bits */ + ccec_export_pub(public_key, CFDataIncreaseLengthAndGetMutableBytes(data, (CFIndex)size)); + + return size; +} + +static size_t AppendECCompactPublicKey(CFMutableDataRef data, ccec_pub_ctx_t public_key) +{ + size_t size = ccec_compact_export_size(false, public_key._full); + + ccec_compact_export(false, CFDataIncreaseLengthAndGetMutableBytes(data, (CFIndex)size), public_key._full); + + return size; +} + + +static CFStringRef SecOTRFullDHKeyCopyDescription(CFTypeRef cf) +{ + SecOTRFullDHKeyRef session = (SecOTRFullDHKeyRef)cf; + return CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR(""), session); +} + +static Boolean SecOTRFullDHKeyCompare(CFTypeRef leftCF, CFTypeRef rightCF) +{ + SecOTRFullDHKeyRef left = (SecOTRFullDHKeyRef)leftCF; + SecOTRFullDHKeyRef right = (SecOTRFullDHKeyRef)rightCF; + + return 0 == memcmp(left->keyHash, right->keyHash, sizeof(left->keyHash)); +} + +static void SecOTRFullDHKeyDestroy(CFTypeRef cf) +{ + SecOTRFullDHKeyRef fullKey = (SecOTRFullDHKeyRef)cf; + + bzero(fullKey->_key, sizeof(fullKey->_key)); +} + +SecOTRFullDHKeyRef SecOTRFullDHKCreate(CFAllocatorRef allocator) +{ + SecOTRFullDHKeyRef newFDHK = CFTypeAllocate(SecOTRFullDHKey, struct _SecOTRFullDHKey, allocator); + + SecFDHKNewKey(newFDHK); + + return newFDHK; +} + +SecOTRFullDHKeyRef SecOTRFullDHKCreateFromBytes(CFAllocatorRef allocator, const uint8_t**bytes, size_t*size) +{ + SecOTRFullDHKeyRef newFDHK = CFTypeAllocate(SecOTRFullDHKey, struct _SecOTRFullDHKey, allocator); + + ccec_ctx_init(ccec_cp_256(), newFDHK->_key); + + uint32_t publicKeySize; + require_noerr(ReadLong(bytes, size, &publicKeySize), fail); + + require(publicKeySize <= *size, fail); + require_noerr(ccec_import_pub(ccec_cp_256(), publicKeySize, *bytes, newFDHK->_key), fail); + ccdigest(ccsha1_di(), publicKeySize, *bytes, newFDHK->keyHash); + + *size -= publicKeySize; + *bytes += publicKeySize; + + require_noerr(ReadMPI(bytes, size, ccec_ctx_n(newFDHK->_key), ccec_ctx_k(newFDHK->_key)), fail); + + return newFDHK; + +fail: + CFReleaseNull(newFDHK); + return NULL; +} + +void SecFDHKNewKey(SecOTRFullDHKeyRef fullKey) +{ + struct ccrng_state *rng=ccDRBGGetRngState(); + + // We need compact keys, maybe we should be using + // ccecdh_generate_key or ccechd_generate_compact_key, but for now ecdh are fine for compact use IFF we don't + // use the non-compact pub part. + + ccec_compact_generate_key(ccec_cp_256(), rng, fullKey->_key); + + size_t size = ccec_export_pub_size(fullKey->_key); + uint8_t publicKey[size]; + + ccec_export_pub(fullKey->_key, publicKey); + ccdigest(ccsha1_di(), size, publicKey, fullKey->keyHash); +} + +void SecFDHKAppendSerialization(SecOTRFullDHKeyRef fullKey, CFMutableDataRef appendTo) +{ + AppendECPublicKeyAsDATA(appendTo, fullKey->_key); + AppendMPI(appendTo, ccec_ctx_n(fullKey->_key), ccec_ctx_k(fullKey->_key)); +} + +void SecFDHKAppendPublicSerialization(SecOTRFullDHKeyRef fullKey, CFMutableDataRef appendTo) +{ + if(ccec_ctx_bitlen(fullKey->_key) != kECKeySize) return; + AppendECPublicKeyAsDATA(appendTo, fullKey->_key); +} + +void SecFDHKAppendCompactPublicSerialization(SecOTRFullDHKeyRef fullKey, CFMutableDataRef appendTo) +{ + if(ccec_ctx_bitlen(fullKey->_key) != kECKeySize) return; + AppendECCompactPublicKey(appendTo, fullKey->_key); +} + + +uint8_t* SecFDHKGetHash(SecOTRFullDHKeyRef fullKey) +{ + return fullKey->keyHash; +} + + + + +// +// +// +struct _SecOTRPublicDHKey { + CFRuntimeBase _base; + + ccec_pub_ctx_decl(ccn_sizeof(kECKeySize), _key); + uint8_t keyHash[CCSHA1_OUTPUT_SIZE]; + +}; + +CFGiblisWithCompareFor(SecOTRPublicDHKey); + +static CFStringRef SecOTRPublicDHKeyCopyDescription(CFTypeRef cf) { + SecOTRPublicDHKeyRef session = (SecOTRPublicDHKeyRef)cf; + return CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR(""), session); +} + +static Boolean SecOTRPublicDHKeyCompare(CFTypeRef leftCF, CFTypeRef rightCF) +{ + SecOTRPublicDHKeyRef left = (SecOTRPublicDHKeyRef)leftCF; + SecOTRPublicDHKeyRef right = (SecOTRPublicDHKeyRef)rightCF; + + return 0 == memcmp(left->keyHash, right->keyHash, sizeof(left->keyHash)); +} + +static void SecOTRPublicDHKeyDestroy(CFTypeRef cf) { + SecOTRPublicDHKeyRef pubKey = (SecOTRPublicDHKeyRef)cf; + (void) pubKey; +} + +static void ccec_copy_public(ccec_pub_ctx_t source, ccec_pub_ctx_t dest) +{ + ccec_ctx_cp(dest) = ccec_ctx_cp(source); + // TODO: +1?! + ccn_set(3*ccec_ctx_n(source), (cc_unit*) ccec_ctx_point(dest)._p, (cc_unit*) ccec_ctx_point(source)._p); +} + +SecOTRPublicDHKeyRef SecOTRPublicDHKCreateFromFullKey(CFAllocatorRef allocator, SecOTRFullDHKeyRef full) +{ + SecOTRPublicDHKeyRef newPDHK = CFTypeAllocate(SecOTRPublicDHKey, struct _SecOTRPublicDHKey, allocator); + + ccec_copy_public(full->_key, newPDHK->_key); + memcpy(newPDHK->keyHash, full->keyHash, CCSHA1_OUTPUT_SIZE); + + return newPDHK; +} + +SecOTRPublicDHKeyRef SecOTRPublicDHKCreateFromSerialization(CFAllocatorRef allocator, const uint8_t** bytes, size_t *size) +{ + size_t publicKeySize; + { + uint32_t readSize = 0; + require_noerr(ReadLong(bytes, size, &readSize), fail); + publicKeySize = readSize; + } + + require(publicKeySize <= *size, fail); + + *size -= publicKeySize; + + return SecOTRPublicDHKCreateFromBytes(allocator, bytes, &publicKeySize); +fail: + return NULL; +} + +SecOTRPublicDHKeyRef SecOTRPublicDHKCreateFromCompactSerialization(CFAllocatorRef allocator, const uint8_t** bytes, size_t *size) +{ + SecOTRPublicDHKeyRef newPDHK = CFTypeAllocate(SecOTRPublicDHKey, struct _SecOTRPublicDHKey, allocator); + + size_t publicKeySize = ccec_cp_prime_size(ccec_cp_256()); + + require_quiet(publicKeySize <= *size, fail); + + require_noerr_quiet(ccec_compact_import_pub(ccec_cp_256(), publicKeySize, *bytes, newPDHK->_key), fail); + + *size -= publicKeySize; + *bytes += publicKeySize; + + ccdigest(ccsha1_di(), *size, *bytes, newPDHK->keyHash); + + return newPDHK; +fail: + CFReleaseNull(newPDHK); + return NULL; +} + + +SecOTRPublicDHKeyRef SecOTRPublicDHKCreateFromBytes(CFAllocatorRef allocator, const uint8_t** bytes, size_t *size) +{ + SecOTRPublicDHKeyRef newPDHK = CFTypeAllocate(SecOTRPublicDHKey, struct _SecOTRPublicDHKey, allocator); + + require_noerr(ccec_import_pub(ccec_cp_256(), *size, *bytes, newPDHK->_key), fail); + ccdigest(ccsha1_di(), *size, *bytes, newPDHK->keyHash); + + *bytes += *size; + *size = 0; + + return newPDHK; +fail: + CFReleaseNull(newPDHK); + return NULL; +} + + +void SecPDHKAppendSerialization(SecOTRPublicDHKeyRef pubKey, CFMutableDataRef appendTo) +{ + AppendECPublicKeyAsDATA(appendTo, pubKey->_key); +} + +void SecPDHKAppendCompactSerialization(SecOTRPublicDHKeyRef pubKey, CFMutableDataRef appendTo) +{ + AppendECPublicKeyAsDATA(appendTo, pubKey->_key); +} + + +uint8_t* SecPDHKGetHash(SecOTRPublicDHKeyRef pubKey) +{ + return pubKey->keyHash; +} + + +void SecPDHKeyGenerateS(SecOTRFullDHKeyRef myKey, SecOTRPublicDHKeyRef theirKey, cc_unit* s) +{ + ccn_zero(kExponentiationUnits, s); + + size_t keyLen = ccn_sizeof_n(kExponentiationUnits); + ccec_compute_key(myKey->_key, theirKey->_key, &keyLen, (uint8_t*)s); +} + +static int ccec_cmp(ccec_pub_ctx_t l, ccec_pub_ctx_t r) +{ + size_t lsize = ccec_export_pub_size(l); + size_t rsize = ccec_export_pub_size(r); + + int result = 0; + + if (lsize == rsize) { + uint8_t lpub[lsize]; + uint8_t rpub[rsize]; + + ccec_export_pub(l, lpub); + ccec_export_pub(r, rpub); + + result = memcmp(lpub, rpub, lsize); + } else { + result = rsize < lsize ? -1 : 1; + } + + return result; +} + +bool SecDHKIsGreater(SecOTRFullDHKeyRef myKey, SecOTRPublicDHKeyRef theirKey) +{ + return ccec_cmp(myKey->_key, theirKey->_key) > 0; +} + +static void DeriveKeys(CFDataRef dataToHash, + uint8_t* messageKey, + uint8_t* macKey) +{ + if (messageKey == NULL && macKey == NULL) + return; + + uint8_t hashedSharedKey[CCSHA1_OUTPUT_SIZE]; + + ccdigest(ccsha1_di(), CFDataGetLength(dataToHash), CFDataGetBytePtr(dataToHash), hashedSharedKey); + + if (messageKey) + memcpy(messageKey, hashedSharedKey, kOTRMessageKeyBytes); + + if (macKey) { + ccdigest(ccsha1_di(), kOTRMessageKeyBytes, messageKey, macKey); + } + + bzero(hashedSharedKey, sizeof(hashedSharedKey)); +} + +void SecOTRDHKGenerateOTRKeys(SecOTRFullDHKeyRef myKey, SecOTRPublicDHKeyRef theirKey, + uint8_t* sendMessageKey, uint8_t* sendMacKey, + uint8_t* receiveMessageKey, uint8_t* receiveMacKey) +{ + CFMutableDataRef dataToHash = CFDataCreateMutable(kCFAllocatorDefault, 0); + + { + cc_unit s[kExponentiationUnits]; + + SecPDHKeyGenerateS(myKey, theirKey, s); + AppendByte(dataToHash, SecDHKIsGreater(myKey, theirKey) ? 0x01 : 0x02); + AppendMPI(dataToHash, kExponentiationUnits, s); + + ccn_zero(kExponentiationUnits, s); + } + + DeriveKeys(dataToHash, receiveMessageKey, receiveMacKey); + + uint8_t *messageTypeByte = CFDataGetMutableBytePtr(dataToHash); + + *messageTypeByte ^= 0x03; // Invert the bits since it's either 1 or 2. + + DeriveKeys(dataToHash, sendMessageKey, sendMacKey); + + CFReleaseNull(dataToHash); +} diff --git a/Security/sec/Security/SecOTRDHKey.h b/Security/sec/Security/SecOTRDHKey.h new file mode 100644 index 00000000..14d1ae87 --- /dev/null +++ b/Security/sec/Security/SecOTRDHKey.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SECOTRDHKEY_H_ +#define _SECOTRDHKEY_H_ + +#include +#include +#include + +__BEGIN_DECLS + +typedef struct _SecOTRFullDHKey* SecOTRFullDHKeyRef; +typedef struct _SecOTRPublicDHKey* SecOTRPublicDHKeyRef; + +SecOTRFullDHKeyRef SecOTRFullDHKCreate(CFAllocatorRef allocator); +SecOTRFullDHKeyRef SecOTRFullDHKCreateFromBytes(CFAllocatorRef allocator, const uint8_t**bytes, size_t*size); + +void SecFDHKNewKey(SecOTRFullDHKeyRef key); +void SecFDHKAppendSerialization(SecOTRFullDHKeyRef fullKey, CFMutableDataRef appendTo); +void SecFDHKAppendPublicSerialization(SecOTRFullDHKeyRef fullKey, CFMutableDataRef appendTo); +void SecFDHKAppendCompactPublicSerialization(SecOTRFullDHKeyRef fullKey, CFMutableDataRef appendTo); + +uint8_t* SecFDHKGetHash(SecOTRFullDHKeyRef pubKey); + + +SecOTRPublicDHKeyRef SecOTRPublicDHKCreateFromFullKey(CFAllocatorRef allocator, SecOTRFullDHKeyRef full); +SecOTRPublicDHKeyRef SecOTRPublicDHKCreateFromSerialization(CFAllocatorRef allocator, const uint8_t**bytes, size_t*size); +SecOTRPublicDHKeyRef SecOTRPublicDHKCreateFromCompactSerialization(CFAllocatorRef allocator, const uint8_t** bytes, size_t *size); +SecOTRPublicDHKeyRef SecOTRPublicDHKCreateFromBytes(CFAllocatorRef allocator, const uint8_t** bytes, size_t *size); + +void SecPDHKAppendSerialization(SecOTRPublicDHKeyRef pubKey, CFMutableDataRef appendTo); +void SecPDHKAppendCompactSerialization(SecOTRPublicDHKeyRef pubKey, CFMutableDataRef appendTo); +uint8_t* SecPDHKGetHash(SecOTRPublicDHKeyRef pubKey); + +void SecPDHKeyGenerateS(SecOTRFullDHKeyRef myKey, SecOTRPublicDHKeyRef theirKey, cc_unit* s); + +bool SecDHKIsGreater(SecOTRFullDHKeyRef myKey, SecOTRPublicDHKeyRef theirKey); + +void SecOTRDHKGenerateOTRKeys(SecOTRFullDHKeyRef myKey, SecOTRPublicDHKeyRef theirKey, + uint8_t* sendMessageKey, uint8_t* sendMacKey, + uint8_t* receiveMessageKey, uint8_t* receiveMacKey); + +__END_DECLS + +#endif diff --git a/Security/sec/Security/SecOTRErrors.h b/Security/sec/Security/SecOTRErrors.h new file mode 100644 index 00000000..8a39f3f3 --- /dev/null +++ b/Security/sec/Security/SecOTRErrors.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef messsageProtection_SecMessageProtectionErrors_h +#define messsageProtection_SecMessageProtectionErrors_h + +static const CFIndex kSecOTRErrorFailedToEncrypt = -1; +static const CFIndex kSecOTRErrorFailedToDecrypt = -2; +static const CFIndex kSecOTRErrorFailedToVerify = -3; +static const CFIndex kSecOTRErrorFailedToSign = -4; +static const CFIndex kSecOTRErrorSignatureDidNotMatch = -5; +static const CFIndex kSecOTRErrorFailedSelfTest = -6; +static const CFIndex kSecOTRErrorParameterError = -7; +static const CFIndex kSecOTRErrorUnknownFormat = -8; +static const CFIndex kSecOTRErrorCreatePublicIdentity = -9; +static const CFIndex kSecOTRErrorCreatePublicBytes = -10; + +// Errors 100-199 reserved for errors being genrated by workarounds/known issues failing +static const CFIndex kSecOTRErrorSignatureTooLarge = -100; +static const CFIndex kSecOTRErrorSignatureDidNotRecreate = -101; + +#endif diff --git a/sec/Security/SecOTRFullIdentity.c b/Security/sec/Security/SecOTRFullIdentity.c similarity index 94% rename from sec/Security/SecOTRFullIdentity.c rename to Security/sec/Security/SecOTRFullIdentity.c index 2bb032fb..538862ed 100644 --- a/sec/Security/SecOTRFullIdentity.c +++ b/Security/sec/Security/SecOTRFullIdentity.c @@ -1,12 +1,27 @@ /* - * SecOTRFullIdentity.c - * libsecurity_libSecOTR - * - * Created by Mitch Adler on 2/9/11. - * Copyright 2011 Apple Inc. All rights reserved. + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include "SecOTR.h" #include "SecOTRIdentityPriv.h" #include diff --git a/sec/Security/SecOTRIdentityPriv.h b/Security/sec/Security/SecOTRIdentityPriv.h similarity index 75% rename from sec/Security/SecOTRIdentityPriv.h rename to Security/sec/Security/SecOTRIdentityPriv.h index 2ade61e8..4e2b6e63 100644 --- a/sec/Security/SecOTRIdentityPriv.h +++ b/Security/sec/Security/SecOTRIdentityPriv.h @@ -1,12 +1,27 @@ /* - * SecOTRIdentityPriv.h - * libsecurity_libSecOTR - * - * Created by Mitch Adler on 2/9/11. - * Copyright 2011 Apple Inc. All rights reserved. + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #ifndef _SECOTRIDENTITYPRIV_H_ #include @@ -100,7 +115,7 @@ OSStatus appendSizeAndData(CFDataRef data, CFMutableDataRef appendTo); SecKeyRef CreateECPrivateKeyFrom(CFAllocatorRef allocator, const uint8_t** data, size_t* limit); SecKeyRef CreateECPublicKeyFrom(CFAllocatorRef allocator, const uint8_t** data, size_t* limit); -void SecOTRCreateError(enum SecOTRError family, CFIndex errorCode, CFStringRef descriptionString, CFErrorRef previousError, CFErrorRef *newError); +bool SecOTRCreateError(enum SecOTRError family, CFIndex errorCode, CFStringRef descriptionString, CFErrorRef previousError, CFErrorRef *newError); __END_DECLS diff --git a/sec/Security/SecOTRMath.c b/Security/sec/Security/SecOTRMath.c similarity index 79% rename from sec/Security/SecOTRMath.c rename to Security/sec/Security/SecOTRMath.c index 65615ffc..73482073 100644 --- a/sec/Security/SecOTRMath.c +++ b/Security/sec/Security/SecOTRMath.c @@ -1,13 +1,28 @@ -// -// OTRMath.c -// libsecurity_libSecOTR -// -// Created by Mitch Adler on 1/28/11. -// Copyright 2011 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 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@ + */ + #include "SecOTRMath.h" -#include "SecOTRMathPrivate.h" #include "SecOTRPacketData.h" @@ -19,47 +34,19 @@ #include #include +#include #include -static inline -void cczp_init_from_bytes(cc_size n, cczp_t zp, size_t pSize, const void *p, size_t rSize, const void* r) -{ - CCZP_N(zp) = n; - zp.zp->mod_prime = cczp_mod; - ccn_read_uint(n, CCZP_PRIME(zp), pSize, p); - ccn_read_uint(n+1, CCZP_RECIP(zp), rSize, r); - -} - -static pthread_once_t kOTRImportGroupData = PTHREAD_ONCE_INIT; - -static cc_unit sOTRGenerator[kOTRDHGroupUnits]; -static cczp_decl_n(kOTRDHGroupUnits, sOTRGroup_zp); - -static void setupGroupValues() -{ - __Check( kExponentiationUnits == kOTRDHGroupUnits ); - - cczp_init_from_bytes(kOTRDHGroupUnits, sOTRGroup_zp, - sizeof(kOTRDHGroup), kOTRDHGroup, - sizeof(kOTRDHGroup_Recip), kOTRDHGroup_Recip); - - ccn_seti(kOTRDHGroupUnits, sOTRGenerator, kOTRGeneratorValue); -} - void OTRExponentiate(cc_unit* res, const cc_unit* base, const cc_unit* exponent) { - pthread_once(&kOTRImportGroupData, setupGroupValues); - - cczp_power(sOTRGroup_zp, res, base, exponent); + ccdh_const_gp_t gp = ccdh_gp_rfc3526group05(); + cczp_power(gp.zp, res, base, exponent); } void OTRGroupExponentiate(cc_unit* res, const cc_unit* exponent) { - pthread_once(&kOTRImportGroupData, setupGroupValues); - - OTRExponentiate(res, sOTRGenerator, exponent); + OTRExponentiate(res, ccdh_gp_g(ccdh_gp_rfc3526group05()) , exponent); } // diff --git a/Security/sec/Security/SecOTRMath.h b/Security/sec/Security/SecOTRMath.h new file mode 100644 index 00000000..6f966e3a --- /dev/null +++ b/Security/sec/Security/SecOTRMath.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 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@ + */ + + +#ifndef _SECOTRMATH_H_ +#define _SECOTRMATH_H_ + +#include + +#include +#include +#include + +#define kOTRAuthKeyBytes 16 +#define kOTRAuthMACKeyBytes 32 + +#define kOTRMessageKeyBytes 16 +#define kOTRMessageMacKeyBytes 20 + +#define kExponentiationBits 1536 +#define kExponentiationUnits ccn_nof(kExponentiationBits) +#define kExponentiationBytes ((kExponentiationBits+7)/8) + +#define kSHA256HMAC160Bits 160 +#define kSHA256HMAC160Bytes (kSHA256HMAC160Bits/8) + +// Result and exponent are expected to be kExponentiationUnits big. +void OTRExponentiate(cc_unit* res, const cc_unit* base, const cc_unit* exponent); +void OTRGroupExponentiate(cc_unit* result, const cc_unit* exponent); + +OSStatus GetRandomBytesInLSBs(size_t bytesOfRandomness, size_t n, cc_unit* place); +OSStatus FillWithRandomBytes(size_t n, cc_unit* place); + +typedef enum { + kSSID = 0x00, + kCs = 0x01, + kM1 = 0x02, + kM2 = 0x03, + kM1Prime = 0x04, + kM2Prime = 0x05 +} KeyType; + + +void DeriveOTR256BitsFromS(KeyType whichKey, size_t sSize, const cc_unit* s, size_t keySize, uint8_t* key); +void DeriveOTR128BitPairFromS(KeyType whichHalf, size_t sSize, const cc_unit* s, + size_t firstKeySize, uint8_t* firstKey, + size_t secondKeySize, uint8_t* secondKey); +void DeriveOTR64BitsFromS(KeyType whichKey, size_t sSize, const cc_unit* s, + size_t firstKeySize, uint8_t* firstKey); + + +void AES_CTR_HighHalf_Transform(size_t keySize, const uint8_t* key, + uint64_t highHalf, + size_t howMuch, const uint8_t* from, + uint8_t* to); + +void AES_CTR_IV0_Transform(size_t keySize, const uint8_t* key, + size_t howMuch, const uint8_t* from, + uint8_t* to); + +#endif diff --git a/Security/sec/Security/SecOTRPacketData.c b/Security/sec/Security/SecOTRPacketData.c new file mode 100644 index 00000000..8206f4c8 --- /dev/null +++ b/Security/sec/Security/SecOTRPacketData.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 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@ + */ + + +#include "SecOTRPacketData.h" + diff --git a/sec/Security/SecOTRPacketData.h b/Security/sec/Security/SecOTRPacketData.h similarity index 82% rename from sec/Security/SecOTRPacketData.h rename to Security/sec/Security/SecOTRPacketData.h index 39769676..c7b3d67f 100644 --- a/sec/Security/SecOTRPacketData.h +++ b/Security/sec/Security/SecOTRPacketData.h @@ -1,10 +1,26 @@ -// -// SecOTRPacketData.h -// libsecurity_libSecOTR -// -// Created by Mitch Adler on 2/26/11. -// Copyright 2011 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #ifndef _SECOTRPACKETDATA_H_ #define _SECOTRPACKETDATA_H_ @@ -36,6 +52,7 @@ static OSStatus SizeAndSkipMPI(const uint8_t **bytes, size_t *size, const uint8_t **mpiBytes, size_t *mpiSize); +static OSStatus ReadLongLongCompact(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value); static OSStatus ReadLongLong(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value); static OSStatus ReadLong(const uint8_t**bytesPtr, size_t*sizePtr, uint32_t* value); static OSStatus ReadShort(const uint8_t**bytesPtr, size_t*sizePtr, uint16_t* value); @@ -46,6 +63,7 @@ static OSStatus ReadDATA(const uint8_t**bytesPtr, size_t*sizePtr, size_t* dataSi static OSStatus CreatePublicKey(const uint8_t**bytesPtr, size_t*sizePtr, SecOTRPublicIdentityRef* publicId); static CFMutableDataRef CFDataCreateMutableFromOTRDATA(CFAllocatorRef allocator, const uint8_t**bytesPtr, size_t*sizePtr); +static void AppendLongLongCompact(CFMutableDataRef appendTo, uint64_t value); static void AppendLongLong(CFMutableDataRef appendTo, uint64_t value); static void AppendLong(CFMutableDataRef appendTo, uint32_t value); static void AppendShort(CFMutableDataRef appendTo, uint16_t value); @@ -67,25 +85,51 @@ static inline OSStatus ReadLongLong(const uint8_t**bytesPtr, size_t*sizePtr, uin require(bytesPtr != NULL, fail); require(sizePtr != NULL, fail); require(value != NULL, fail); - require(*sizePtr >= 4, fail); - + require(*sizePtr >= 8, fail); + *value = ((uint64_t)(*bytesPtr)[0]) << 56 | - ((uint64_t)(*bytesPtr)[1]) << 48 | - ((uint64_t)(*bytesPtr)[2]) << 40 | - ((uint64_t)(*bytesPtr)[3]) << 32 | - ((uint64_t)(*bytesPtr)[4]) << 24 | - ((uint64_t)(*bytesPtr)[5]) << 16 | - ((uint64_t)(*bytesPtr)[6]) << 8 | - ((uint64_t)(*bytesPtr)[7]) << 0; - + ((uint64_t)(*bytesPtr)[1]) << 48 | + ((uint64_t)(*bytesPtr)[2]) << 40 | + ((uint64_t)(*bytesPtr)[3]) << 32 | + ((uint64_t)(*bytesPtr)[4]) << 24 | + ((uint64_t)(*bytesPtr)[5]) << 16 | + ((uint64_t)(*bytesPtr)[6]) << 8 | + ((uint64_t)(*bytesPtr)[7]) << 0; + *bytesPtr += 8; *sizePtr -= 8; - + return errSecSuccess; fail: return errSecParam; } +static inline OSStatus ReadLongLongCompact(const uint8_t**bytesPtr, size_t*sizePtr, uint64_t* value) +{ + bool moreBytes = true; + + require(bytesPtr != NULL, fail); + require(sizePtr != NULL, fail); + require(value != NULL, fail); + + *value = 0; + + while (moreBytes && *sizePtr > 0) { + uint8_t thisByte = **bytesPtr; + + moreBytes = (0x80 & thisByte) != 0; + + *value <<= 7; + *value |= (thisByte & 0x7F); + + ++*bytesPtr; + --*sizePtr; + } + +fail: + return !moreBytes ? errSecSuccess : errSecDecode; +} + static inline OSStatus ReadLong(const uint8_t**bytesPtr, size_t*sizePtr, uint32_t* value) { require(bytesPtr != NULL, fail); @@ -140,6 +184,18 @@ static inline OSStatus ReadByte(const uint8_t**bytesPtr, size_t*sizePtr, uint8_t fail: return errSecParam; } + +static inline OSStatus ReadByteAsBool(const uint8_t**bytesPtr, size_t*sizePtr, bool* value) +{ + uint8_t byte = 0; + + OSStatus result = ReadByte(bytesPtr, sizePtr, &byte); + + if (result == noErr) + *value = byte != 0; + + return result; +} static inline OSStatus ReadMessageType(const uint8_t**bytesPtr, size_t*sizePtr, OTRMessageType* type) { @@ -348,6 +404,24 @@ static inline OSStatus SizeAndSkipMPI(const uint8_t **bytes, size_t *size, // // Appending functions // +static inline void AppendLongLongCompact(CFMutableDataRef appendTo, uint64_t value) +{ + uint8_t compact[(sizeof(value) * 8 + 7) / 7]; // We can only need enough bytes to hold 8/7 expansion. + + uint8_t *end = compact + sizeof(compact); + uint8_t *lastFilled = end; + + --lastFilled; + *lastFilled = (value & 0x7F); + + for (value >>= 7; value != 0; value >>= 7) { + --lastFilled; + *lastFilled = (value & 0x7f) | 0x80; + } + + CFDataAppendBytes(appendTo, lastFilled, end - lastFilled); +} + static inline void AppendLongLong(CFMutableDataRef appendTo, uint64_t value) { uint8_t bigEndian[sizeof(value)] = { value >> 56, value >> 48, value >> 40, value >> 32, diff --git a/sec/Security/SecOTRPackets.c b/Security/sec/Security/SecOTRPackets.c similarity index 89% rename from sec/Security/SecOTRPackets.c rename to Security/sec/Security/SecOTRPackets.c index f13d967d..ced396ea 100644 --- a/sec/Security/SecOTRPackets.c +++ b/Security/sec/Security/SecOTRPackets.c @@ -1,10 +1,26 @@ -// -// SecOTRPackets.c -// libsecurity_libSecOTR -// -// Created by Mitch Adler on 2/23/11. -// Copyright 2011 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include "SecOTRSessionPriv.h" #include "SecOTRPackets.h" @@ -16,10 +32,6 @@ #include "SecOTRPacketData.h" #include "SecOTRDHKey.h" -#ifdef USECOMMONCRYPTO -#include -#endif - #include #include @@ -41,11 +53,7 @@ static inline void AppendSHA256HMAC(CFMutableDataRef appendTo, { uint8_t *to = CFDataIncreaseLengthAndGetMutableBytes(appendTo, CCSHA256_OUTPUT_SIZE); -#ifdef USECOMMONCRYPTO - CCHmac(kCCHmacAlgSHA256, key, keybytes, from, howMuch, to); -#else cchmac(ccsha256_di(), keybytes, key, howMuch, from, to); -#endif } // First 160 bits of the HMAC @@ -134,11 +142,8 @@ void SecOTRAppendDHMessage(SecOTRSessionRef session, AppendLong(appendTo, CCSHA256_OUTPUT_SIZE); uint8_t* hashLocation = CFDataIncreaseLengthAndGetMutableBytes(appendTo, CCSHA256_OUTPUT_SIZE); -#ifdef USECOMMONCRYPTO - (void) CC_SHA256(gxmpiLocation, (uint32_t)gxmpiSize, hashLocation); -#else ccdigest(ccsha256_di(), gxmpiSize, gxmpiLocation, hashLocation); -#endif + CFReleaseNull(gxmpi); } diff --git a/Security/sec/Security/SecOTRPackets.h b/Security/sec/Security/SecOTRPackets.h new file mode 100644 index 00000000..334ba51e --- /dev/null +++ b/Security/sec/Security/SecOTRPackets.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + +#include + +#ifndef _SECOTRPACKETS_H_ +#define _SECOTRPACKETS_H_ + +void SecOTRAppendDHMessage(SecOTRSessionRef session, CFMutableDataRef appendTo); +void SecOTRAppendDHKeyMessage(SecOTRSessionRef session, CFMutableDataRef appendTo); +void SecOTRAppendRevealSignatureMessage(SecOTRSessionRef session, CFMutableDataRef appendTo); +void SecOTRAppendSignatureMessage(SecOTRSessionRef session, CFMutableDataRef appendTo); + +typedef enum { + kDHMessage = 0x02, + kDataMessage = 0x03, + kDHKeyMessage = 0x0A, + kRevealSignatureMessage = 0x11, + kSignatureMessage = 0x12, + + kEvenCompactDataMessage = 0x20, + kOddCompactDataMessage = 0x21, + + kInvalidMessage = 0xFF +} OTRMessageType; + +#endif diff --git a/sec/Security/SecOTRPublicIdentity.c b/Security/sec/Security/SecOTRPublicIdentity.c similarity index 83% rename from sec/Security/SecOTRPublicIdentity.c rename to Security/sec/Security/SecOTRPublicIdentity.c index e37c7ef6..89cfb17c 100644 --- a/sec/Security/SecOTRPublicIdentity.c +++ b/Security/sec/Security/SecOTRPublicIdentity.c @@ -1,12 +1,27 @@ /* - * SecOTRPublicIdentity.c - * libsecurity_libSecOTR - * - * Created by Mitch Adler on 2/9/11. - * Copyright 2011 Apple Inc. All rights reserved. + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ + #include "SecOTR.h" #include "SecOTRIdentityPriv.h" #include @@ -242,25 +257,27 @@ size_t SecOTRPISignatureSize(SecOTRPublicIdentityRef publicID) bool SecOTRPIAppendSerialization(SecOTRPublicIdentityRef publicID, CFMutableDataRef serializeInto, CFErrorRef *error) { CFIndex start = CFDataGetLength(serializeInto); - - CFMutableDataRef signingKeySerialized = NULL; + CFMutableDataRef signingKeySerialized = CFDataCreateMutable(kCFAllocatorDefault, 0); - signingKeySerialized = CFDataCreateMutable(kCFAllocatorDefault, 0); - - uint8_t outputBuffer[16384]; - uint8_t* outputBufferEnd = outputBuffer + sizeof(outputBuffer); - - uint8_t sendHashes[1]; - sendHashes[0] = 0xFF; + uint8_t sendHashes[1] = { 0xFF }; require_noerr(appendPublicOctetsAndSize(publicID->publicSigningKey, signingKeySerialized), fail); + size_t outputSize = ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, + ccder_sizeof_implicit_raw_octet_string(CCDER_CONTEXT_SPECIFIC | kOTRPIDER_SigningID, (size_t)CFDataGetLength(signingKeySerialized)) + + (sAdvertiseHashes ? ccder_sizeof_implicit_raw_octet_string(CCDER_CONTEXT_SPECIFIC | kOTRPIDER_SupportsHashes, sizeof(sendHashes)) : 0)); + + CFDataIncreaseLength(serializeInto, outputSize); + + uint8_t *outputBuffer = CFDataGetMutableBytePtr(serializeInto) + start; + uint8_t *outputBufferEnd = outputBuffer + outputSize; + uint8_t *result = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, outputBufferEnd, outputBuffer, - ccder_encode_implicit_raw_octet_string(CCDER_CONTEXT_SPECIFIC | kOTRPIDER_SigningID, (size_t)CFDataGetLength(signingKeySerialized), CFDataGetBytePtr(signingKeySerialized), outputBuffer, - sAdvertiseHashes ? ccder_encode_implicit_raw_octet_string(CCDER_CONTEXT_SPECIFIC | kOTRPIDER_SupportsHashes, sizeof(sendHashes), sendHashes, outputBuffer, outputBufferEnd) : outputBufferEnd)); - - CFDataAppendBytes(serializeInto, result, outputBufferEnd - result); - + ccder_encode_implicit_raw_octet_string(CCDER_CONTEXT_SPECIFIC | kOTRPIDER_SigningID, (size_t)CFDataGetLength(signingKeySerialized), CFDataGetBytePtr(signingKeySerialized), outputBuffer, + sAdvertiseHashes ? ccder_encode_implicit_raw_octet_string(CCDER_CONTEXT_SPECIFIC | kOTRPIDER_SupportsHashes, sizeof(sendHashes), sendHashes, outputBuffer, outputBufferEnd) : outputBufferEnd)); + + require_quiet(result == outputBuffer, fail); + CFReleaseSafe(signingKeySerialized); return true; @@ -293,6 +310,7 @@ static void SecOTRPIRecreateSignature(const uint8_t *oldSignature, size_t oldSig oldSignature = ccder_decode_sequence_tl(&oldSignatureEnd, oldSignature, oldSignatureEnd); oldSignature = mp_decode_forced_uint(n, r, oldSignature, oldSignatureEnd); oldSignature = mp_decode_forced_uint(n, s, oldSignature, oldSignatureEnd); + (void) oldSignature; // We could check for a good end, but it'll come out when we re-encode. const uint8_t *outputPointer = *newSignature; uint8_t *outputEndPointer = *newSignature + *newSignatureSize; @@ -315,9 +333,7 @@ bool SecOTRPIVerifySignature(SecOTRPublicIdentityRef publicID, dataToHash, amountToHash, (uint8_t*)signatureStart, signatureSize, NULL), fail); return true; -fail: - // Workaround some type of compiler bug that won't recognize uint8_t after a label - ; +fail: ; uint8_t replacementSignature[signatureSize + 3]; size_t replacementSignatureLen = sizeof(replacementSignature); diff --git a/Security/sec/Security/SecOTRSession.c b/Security/sec/Security/SecOTRSession.c new file mode 100644 index 00000000..1f7d80a3 --- /dev/null +++ b/Security/sec/Security/SecOTRSession.c @@ -0,0 +1,1030 @@ +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include +#include "utilities/comparison.h" + +#include "SecOTRSession.h" + +#include "SecOTRMath.h" +#include "SecOTRDHKey.h" +#include "SecOTRSessionPriv.h" +#include "SecOTRPackets.h" +#include "SecOTRPacketData.h" +#include "SecOTRIdentityPriv.h" + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include + +CFGiblisFor(SecOTRSession); + +static OTRMessageType SecOTRSGetMessageType(CFDataRef message) +{ + OTRMessageType type = kInvalidMessage; + + CFDataRef decodedBytes = SecOTRCopyIncomingBytes(message); + + const uint8_t *bytes = CFDataGetBytePtr(decodedBytes); + size_t size = CFDataGetLength(decodedBytes); + + if (noErr != ReadHeader(&bytes, &size, &type)) { + uint8_t firstByte = *CFDataGetBytePtr(decodedBytes); + switch (firstByte) { + case kOddCompactDataMessage: + case kEvenCompactDataMessage: + type = firstByte; + break; + + default: + break; + } + } + + CFReleaseNull(decodedBytes); + + return type; +} + +const char *SecOTRPacketTypeString(CFDataRef message) +{ + if (!message) return "NoMessage"; + switch (SecOTRSGetMessageType(message)) { + case kDHMessage: return "DHMessage (0x02)"; + case kDataMessage: return "DataMessage (0x03)"; + case kDHKeyMessage: return "DHKeyMessage (0x0A)"; + case kRevealSignatureMessage: return "RevealSignatureMessage (0x11)"; + case kSignatureMessage: return "SignatureMessage (0x12)"; + case kEvenCompactDataMessage: return "kEvenCompactDatamessage (0x20)"; + case kOddCompactDataMessage: return "kOddCompactDataMessage (0x21)"; + case kInvalidMessage: return "InvalidMessage (0xFF)"; + default: return "UnknownMessage"; + } +} + +static const char *SecOTRAuthStateString(SecOTRAuthState authState) +{ + switch (authState) { + case kIdle: return "Idle"; + case kAwaitingDHKey: return "AwaitingDHKey"; + case kAwaitingRevealSignature: return "AwaitingRevealSignature"; + case kAwaitingSignature: return "AwaitingSignature"; + case kDone: return "Done"; + default: return "InvalidState"; + } +} + +static CF_RETURNS_RETAINED CFStringRef SecOTRSessionCopyDescription(CFTypeRef cf) { + SecOTRSessionRef session = (SecOTRSessionRef)cf; + return CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR("<%s %s %s%s%s%s %d:%d %s%s>"), + SecOTRAuthStateString(session->_state), + session->_compactAppleMessages ? "C" :"c", + session->_me ? "F" : "f", + session->_them ? "P" : "p", + session->_receivedDHMessage ? "D" : "d", + session->_receivedDHKeyMessage ? "K" : "k", + session->_keyID, + session->_theirKeyID, + session->_theirPreviousKey ? "P" : "p", + session->_theirKey ? "T" : "t"); +} + +static void SecOTRSessionDestroy(CFTypeRef cf) { + SecOTRSessionRef session = (SecOTRSessionRef)cf; + + CFReleaseNull(session->_receivedDHMessage); + CFReleaseNull(session->_receivedDHKeyMessage); + + CFReleaseNull(session->_me); + CFReleaseNull(session->_myKey); + CFReleaseNull(session->_myNextKey); + + CFReleaseNull(session->_them); + CFReleaseNull(session->_theirKey); + CFReleaseNull(session->_theirPreviousKey); + + CFReleaseNull(session->_macKeysToExpose); + + dispatch_release(session->_queue); +} + +static void SecOTRSessionResetInternal(SecOTRSessionRef session) +{ + session->_state = kIdle; + + CFReleaseNull(session->_receivedDHMessage); + CFReleaseNull(session->_receivedDHKeyMessage); + + session->_keyID = 0; + CFReleaseNull(session->_myKey); + CFReleaseNull(session->_myNextKey); + //session->_myNextKey = SecOTRFullDHKCreate(kCFAllocatorDefault); + session->_theirKeyID = 0; + CFReleaseNull(session->_theirKey); + CFReleaseNull(session->_theirPreviousKey); + CFReleaseNull(session->_macKeysToExpose); + session->_macKeysToExpose = CFDataCreateMutable(kCFAllocatorDefault, 0); + + bzero(session->_keyCache, sizeof(session->_keyCache)); +} + +void SecOTRSessionReset(SecOTRSessionRef session) +{ + dispatch_sync_f(session->_queue, session, (dispatch_function_t) SecOTRSessionResetInternal); +} + + +SecOTRSessionRef SecOTRSessionCreateFromID(CFAllocatorRef allocator, + SecOTRFullIdentityRef myID, + SecOTRPublicIdentityRef theirID) +{ + SecOTRSessionRef newID = CFTypeAllocate(SecOTRSession, struct _SecOTRSession, allocator); + + newID->_queue = dispatch_queue_create("OTRSession", DISPATCH_QUEUE_SERIAL); + + newID->_me = myID; + newID->_them = theirID; + newID->_receivedDHMessage = NULL; + newID->_receivedDHKeyMessage = NULL; + newID->_myKey = NULL; + newID->_myNextKey = NULL; + newID->_theirKey = NULL; + newID->_theirPreviousKey = NULL; + newID->_macKeysToExpose = NULL; + newID->_textOutput = false; + newID->_compactAppleMessages = false; + + SecOTRSessionResetInternal(newID); + + CFRetain(newID->_me); + CFRetain(newID->_them); + + return newID; +} + +SecOTRSessionRef SecOTRSessionCreateFromIDAndFlags(CFAllocatorRef allocator, + SecOTRFullIdentityRef myID, + SecOTRPublicIdentityRef theirID, + uint32_t flags) +{ + SecOTRSessionRef newID = SecOTRSessionCreateFromID(allocator, myID, theirID); + if (flags & kSecOTRSendTextMessages) { + newID->_textOutput = true; + } + if (flags & kSecOTRUseAppleCustomMessageFormat) { + newID->_compactAppleMessages = true; + } + return newID; +} + +static uint64_t constant_zero = 0; + +static bool hashIsZero(uint8_t hash[CCSHA1_OUTPUT_SIZE]) +{ + bool isZero = true; + for(size_t byte = 0; isZero && byte < CCSHA1_OUTPUT_SIZE; ++byte) + isZero = (0 == hash[byte]); + + return isZero; +} + + +static bool SOSOTRSCacheEntryIsEmpty(SecOTRCacheElement *element) +{ + return hashIsZero(element->_fullKeyHash) && hashIsZero(element->_publicKeyHash); +} + +static void SecOTRSFindKeysForMessage(SecOTRSessionRef session, + SecOTRFullDHKeyRef myKey, + SecOTRPublicDHKeyRef theirKey, + bool sending, + uint8_t** messageKey, uint8_t** macKey, uint64_t **counter) +{ + SecOTRCacheElement* emptyKeys = NULL; + SecOTRCacheElement* cachedKeys = NULL; + + if ((NULL == myKey) || (NULL == theirKey)) { + if (messageKey) + *messageKey = NULL; + if (macKey) + *macKey = NULL; + if (counter) + *counter = &constant_zero; + + return; + } + + for(int i = 0; i < kOTRKeyCacheSize; ++i) + { + if (0 == constant_memcmp(session->_keyCache[i]._fullKeyHash, SecFDHKGetHash(myKey), CCSHA1_OUTPUT_SIZE) + && (0 == constant_memcmp(session->_keyCache[i]._publicKeyHash, SecPDHKGetHash(theirKey), CCSHA1_OUTPUT_SIZE))) { + cachedKeys = &session->_keyCache[i]; + break; + } + + if (emptyKeys == NULL && SOSOTRSCacheEntryIsEmpty(&(session->_keyCache[i]))) { + emptyKeys = &session->_keyCache[i]; + } + } + + if (cachedKeys == NULL) { + if (emptyKeys == NULL) { + secerror("SecOTRSession key cache was full. Should never happen, spooky.\n"); + emptyKeys = &session->_keyCache[0]; + } + + // Fill in the entry. + memcpy(emptyKeys->_fullKeyHash, SecFDHKGetHash(myKey), CCSHA1_OUTPUT_SIZE); + memcpy(emptyKeys->_publicKeyHash, SecPDHKGetHash(theirKey), CCSHA1_OUTPUT_SIZE); + + emptyKeys->_counter = 0; + emptyKeys->_theirCounter = 0; + + SecOTRDHKGenerateOTRKeys(myKey, theirKey, + emptyKeys->_sendEncryptionKey, emptyKeys->_sendMacKey, + emptyKeys->_receiveEncryptionKey, emptyKeys->_receiveMacKey); + + cachedKeys = emptyKeys; + } + + if (messageKey) + *messageKey = sending ? cachedKeys->_sendEncryptionKey : cachedKeys->_receiveEncryptionKey; + if (macKey) + *macKey = sending ? cachedKeys->_sendMacKey : cachedKeys->_receiveMacKey; + if (counter) + *counter = sending ? &cachedKeys->_counter : &cachedKeys->_theirCounter; +} + +SecOTRSessionRef SecOTRSessionCreateFromData(CFAllocatorRef allocator, CFDataRef data) +{ + if (data == NULL) + return NULL; + + SecOTRSessionRef result = NULL; + SecOTRSessionRef session = CFTypeAllocate(SecOTRSession, struct _SecOTRSession, allocator); + + const uint8_t *bytes = CFDataGetBytePtr(data); + size_t size = (size_t)CFDataGetLength(data); + + session->_queue = dispatch_queue_create("OTRSession", DISPATCH_QUEUE_SERIAL); + + session->_me = NULL; + session->_them = NULL; + session->_myKey = NULL; + session->_myNextKey = NULL; + session->_theirKey = NULL; + session->_theirPreviousKey = NULL; + session->_receivedDHMessage = NULL; + session->_receivedDHKeyMessage = NULL; + session->_textOutput = false; + session->_compactAppleMessages = false; + + bzero(session->_keyCache, sizeof(session->_keyCache)); + + uint8_t version; + require_noerr(ReadByte(&bytes, &size, &version), fail); + require(version <= 4, fail); + + require_noerr(ReadLong(&bytes, &size, &session->_state), fail); + session->_me = SecOTRFullIdentityCreateFromBytes(kCFAllocatorDefault, &bytes, &size, NULL); + require(session->_me != NULL, fail); + session->_them = SecOTRPublicIdentityCreateFromBytes(kCFAllocatorDefault, &bytes, &size, NULL); + require(session->_them != NULL, fail); + + require(size > sizeof(session->_r), fail); + memcpy(session->_r, bytes, sizeof(session->_r)); + bytes += sizeof(session->_r); + size -= sizeof(session->_r); + + { + uint8_t hasMessage = false; + ReadByte(&bytes, &size, &hasMessage); + if (hasMessage) { + session->_receivedDHMessage = CFDataCreateMutableFromOTRDATA(kCFAllocatorDefault, &bytes, &size); + } + } + + if (version >= 2) { + uint8_t hasMessage = false; + ReadByte(&bytes, &size, &hasMessage); + if (hasMessage) { + session->_receivedDHKeyMessage = CFDataCreateMutableFromOTRDATA(kCFAllocatorDefault, &bytes, &size); + } + } + + if (version < 3) { + uint8_t ready; + require_noerr(ReadByte(&bytes, &size, &ready), fail); + if (ready && session->_state == kIdle) + session->_state = kDone; + } + + require_noerr(ReadLong(&bytes, &size, &session->_keyID), fail); + if (session->_keyID > 0) { + session->_myKey = SecOTRFullDHKCreateFromBytes(kCFAllocatorDefault, &bytes, &size); + require(session->_myKey != NULL, fail); + session->_myNextKey = SecOTRFullDHKCreateFromBytes(kCFAllocatorDefault, &bytes, &size); + require(session->_myNextKey != NULL, fail); + } + + require_noerr(ReadLong(&bytes, &size, &session->_theirKeyID), fail); + if (session->_theirKeyID > 0) { + if (session->_theirKeyID > 1) { + session->_theirPreviousKey = SecOTRPublicDHKCreateFromSerialization(kCFAllocatorDefault, &bytes, &size); + require(session->_theirPreviousKey != NULL, fail); + } + session->_theirKey = SecOTRPublicDHKCreateFromSerialization(kCFAllocatorDefault, &bytes, &size); + require(session->_theirKey != NULL, fail); + } + + uint64_t *counter; + SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirKey, false, NULL, NULL, &counter); + require_noerr(ReadLongLong(&bytes, &size, counter), fail); + SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirKey, true, NULL, NULL, &counter); + require_noerr(ReadLongLong(&bytes, &size, counter), fail); + SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirPreviousKey, false, NULL, NULL, &counter); + require_noerr(ReadLongLong(&bytes, &size, counter), fail); + SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirPreviousKey, true, NULL, NULL, &counter); + require_noerr(ReadLongLong(&bytes, &size, counter), fail); + SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirKey, false, NULL, NULL, &counter); + require_noerr(ReadLongLong(&bytes, &size, counter), fail); + SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirKey, true, NULL, NULL, &counter); + require_noerr(ReadLongLong(&bytes, &size, counter), fail); + SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirPreviousKey, false, NULL, NULL, &counter); + require_noerr(ReadLongLong(&bytes, &size, counter), fail); + SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirPreviousKey, true, NULL, NULL, &counter); + require_noerr(ReadLongLong(&bytes, &size, counter), fail); + + session->_macKeysToExpose = CFDataCreateMutableFromOTRDATA(kCFAllocatorDefault, &bytes, &size); + require(session->_macKeysToExpose != NULL, fail); + + require_noerr(ReadByteAsBool(&bytes, &size, &session->_textOutput), fail); + + if (version >= 4) { + require_noerr(ReadByteAsBool(&bytes, &size, &session->_compactAppleMessages), fail); + } + + result = session; + session = NULL; + +fail: + CFReleaseNull(session); + return result; +} + + +OSStatus SecOTRSAppendSerialization(SecOTRSessionRef session, CFMutableDataRef serializeInto) +{ + __block OSStatus result = errSecParam; + + require(session, abort); + require(serializeInto, abort); + + CFIndex start = CFDataGetLength(serializeInto); + + dispatch_sync(session->_queue, ^{ + const uint8_t version = 4; + + CFDataAppendBytes(serializeInto, &version, sizeof(version)); + + AppendLong(serializeInto, session->_state); + + result = (SecOTRFIAppendSerialization(session->_me, serializeInto, NULL)) ? errSecSuccess : errSecParam; + + if (result == errSecSuccess) { + result = (SecOTRPIAppendSerialization(session->_them, serializeInto, NULL)) ? errSecSuccess : errSecParam; + } + + if (result == errSecSuccess) { + CFDataAppendBytes(serializeInto, session->_r, sizeof(session->_r)); + + if (session->_receivedDHMessage == NULL) { + AppendByte(serializeInto, 0); + } else { + AppendByte(serializeInto, 1); + AppendCFDataAsDATA(serializeInto, session->_receivedDHMessage); + } + + if (session->_receivedDHKeyMessage == NULL) { + AppendByte(serializeInto, 0); + } else { + AppendByte(serializeInto, 1); + AppendCFDataAsDATA(serializeInto, session->_receivedDHKeyMessage); + } + + AppendLong(serializeInto, session->_keyID); + if (session->_keyID > 0) { + SecFDHKAppendSerialization(session->_myKey, serializeInto); + SecFDHKAppendSerialization(session->_myNextKey, serializeInto); + } + + AppendLong(serializeInto, session->_theirKeyID); + if (session->_theirKeyID > 0) { + if (session->_theirKeyID > 1) { + SecPDHKAppendSerialization(session->_theirPreviousKey, serializeInto); + } + SecPDHKAppendSerialization(session->_theirKey, serializeInto); + } + + uint64_t *counter; + SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirKey, false, NULL, NULL, &counter); + AppendLongLong(serializeInto, *counter); + SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirKey, true, NULL, NULL, &counter); + AppendLongLong(serializeInto, *counter); + SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirPreviousKey, false, NULL, NULL, &counter); + AppendLongLong(serializeInto, *counter); + SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirPreviousKey, true, NULL, NULL, &counter); + AppendLongLong(serializeInto, *counter); + SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirKey, false, NULL, NULL, &counter); + AppendLongLong(serializeInto, *counter); + SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirKey, true, NULL, NULL, &counter); + AppendLongLong(serializeInto, *counter); + SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirPreviousKey, false, NULL, NULL, &counter); + AppendLongLong(serializeInto, *counter); + SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirPreviousKey, true, NULL, NULL, &counter); + AppendLongLong(serializeInto, *counter); + + AppendCFDataAsDATA(serializeInto, session->_macKeysToExpose); + + AppendByte(serializeInto, session->_textOutput ? 1 : 0); + AppendByte(serializeInto, session->_compactAppleMessages ? 1 : 0); + } + }); + + if (result != errSecSuccess) + CFDataSetLength(serializeInto, start); + +abort: + return result; +} + + +bool SecOTRSGetIsReadyForMessages(SecOTRSessionRef session) +{ + __block bool result; + + dispatch_sync(session->_queue, ^{ result = session->_state == kDone; }); + + return result; +} + +bool SecOTRSGetIsIdle(SecOTRSessionRef session) +{ + __block bool result; + + dispatch_sync(session->_queue, ^{ result = session->_state == kIdle; }); + + return result; +} + +static void SecOTRSExpireCachedKeysForFullKey(SecOTRSessionRef session, SecOTRFullDHKeyRef myKey) +{ + for(int i = 0; i < kOTRKeyCacheSize; ++i) + { + if (0 == constant_memcmp(session->_keyCache[i]._fullKeyHash, SecFDHKGetHash(myKey), CCSHA1_OUTPUT_SIZE)) { + CFDataAppendBytes(session->_macKeysToExpose, session->_keyCache[i]._receiveMacKey, sizeof(session->_keyCache[i]._receiveMacKey)); + + bzero(&session->_keyCache[i], sizeof(session->_keyCache[i])); + } + } +} + +static void SecOTRSExpireCachedKeysForPublicKey(SecOTRSessionRef session, SecOTRPublicDHKeyRef theirKey) +{ + for(int i = 0; i < kOTRKeyCacheSize; ++i) + { + if (0 == constant_memcmp(session->_keyCache[i]._publicKeyHash, SecPDHKGetHash(theirKey), CCSHA1_OUTPUT_SIZE)) { + CFDataAppendBytes(session->_macKeysToExpose, session->_keyCache[i]._receiveMacKey, sizeof(session->_keyCache[i]._receiveMacKey)); + + bzero(&session->_keyCache[i], sizeof(session->_keyCache[i])); + } + } +} + +static void SecOTRSPrecalculateForPair(SecOTRSessionRef session, + SecOTRFullDHKeyRef myKey, + SecOTRPublicDHKeyRef theirKey) +{ + if (myKey == NULL || theirKey == NULL) + return; + + SecOTRSFindKeysForMessage(session, myKey, theirKey, true, NULL, NULL, NULL); + SecOTRSFindKeysForMessage(session, myKey, theirKey, false, NULL, NULL, NULL); +} + +static void SecOTRSPrecalculateKeysInternal(SecOTRSessionRef session) +{ + SecOTRSPrecalculateForPair(session, session->_myKey, session->_theirKey); + SecOTRSPrecalculateForPair(session, session->_myNextKey, session->_theirKey); + SecOTRSPrecalculateForPair(session, session->_myKey, session->_theirPreviousKey); + SecOTRSPrecalculateForPair(session, session->_myNextKey, session->_theirPreviousKey); +} + +void SecOTRSPrecalculateKeys(SecOTRSessionRef session) +{ + dispatch_sync_f(session->_queue, session, (dispatch_function_t) SecOTRSPrecalculateKeysInternal); +} + +enum SecOTRSMessageKind SecOTRSGetMessageKind(SecOTRSessionRef session, CFDataRef message) +{ + OTRMessageType type = SecOTRSGetMessageType(message); + + enum SecOTRSMessageKind kind; + + switch (type) { + case kDataMessage: + case kEvenCompactDataMessage: + case kOddCompactDataMessage: + kind = kOTRDataPacket; + break; + case kDHMessage: + case kDHKeyMessage: + case kRevealSignatureMessage: + case kSignatureMessage: + kind = kOTRNegotiationPacket; + break; + case kInvalidMessage: + default: + kind = kOTRUnknownPacket; + break; + } + + return kind; +} + +static OSStatus SecOTRSSignAndProtectRaw_locked(SecOTRSessionRef session, + CFDataRef sourceMessage, CFMutableDataRef destinationMessage, + uint8_t* messageKey, uint8_t* macKey, uint64_t* counter) +{ + CFIndex start = CFDataGetLength(destinationMessage); + + AppendHeader(destinationMessage, kDataMessage); + AppendByte(destinationMessage, 0); // Flags, all zero + + AppendLong(destinationMessage, session->_keyID); + AppendLong(destinationMessage, session->_theirKeyID); + SecFDHKAppendPublicSerialization(session->_myNextKey, destinationMessage); + AppendLongLong(destinationMessage, ++*counter); + + CFIndex sourceSize = CFDataGetLength(sourceMessage); + assert(((unsigned long)sourceSize)<=UINT32_MAX); /* this is correct as long as CFIndex is a signed long */ + AppendLong(destinationMessage, (uint32_t)sourceSize); + uint8_t* encryptedDataPointer = CFDataIncreaseLengthAndGetMutableBytes(destinationMessage, sourceSize); + AES_CTR_HighHalf_Transform(kOTRMessageKeyBytes, messageKey, + *counter, + (size_t)sourceSize, CFDataGetBytePtr(sourceMessage), + encryptedDataPointer); + + CFIndex macedContentsSize = CFDataGetLength(destinationMessage) - start; + CFIndex macSize = CCSHA1_OUTPUT_SIZE; + uint8_t* macDataPointer = CFDataIncreaseLengthAndGetMutableBytes(destinationMessage, macSize); + + cchmac(ccsha1_di(), + kOTRMessageMacKeyBytes, macKey, + macedContentsSize, CFDataGetBytePtr(destinationMessage) + start, + macDataPointer); + + CFDataAppend(destinationMessage, session->_macKeysToExpose); + + return errSecSuccess; +} + +const size_t kCompactMessageMACSize = 16; + +static OSStatus SecOTRSSignAndProtectCompact_locked(SecOTRSessionRef session, + CFDataRef sourceMessage, CFMutableDataRef destinationMessage, + uint8_t* messageKey, uint8_t* macKey, uint64_t* counter) +{ + CFIndex start = CFDataGetLength(destinationMessage); + + AppendByte(destinationMessage, (session->_theirKeyID & 0x1) ? kOddCompactDataMessage : kEvenCompactDataMessage); + + SecFDHKAppendCompactPublicSerialization(session->_myNextKey, destinationMessage); + AppendLongLongCompact(destinationMessage, ++*counter); + + CFIndex sourceSize = CFDataGetLength(sourceMessage); + assert(((unsigned long)sourceSize)<=UINT32_MAX); /* this is correct as long as CFIndex is a signed long */ + uint8_t* encryptedDataPointer = CFDataIncreaseLengthAndGetMutableBytes(destinationMessage, sourceSize); + AES_CTR_HighHalf_Transform(kOTRMessageKeyBytes, messageKey, + *counter, + (size_t)sourceSize, CFDataGetBytePtr(sourceMessage), + encryptedDataPointer); + + CFIndex macedContentsSize = CFDataGetLength(destinationMessage) - start; + CFIndex macSize = CCSHA1_OUTPUT_SIZE; + uint8_t mac[macSize]; + cchmac(ccsha1_di(), + kOTRMessageMacKeyBytes, macKey, + macedContentsSize, CFDataGetBytePtr(destinationMessage) + start, + mac); + + CFDataAppendBytes(destinationMessage, mac, kCompactMessageMACSize); + + return errSecSuccess; +} + +OSStatus SecOTRSSignAndProtectMessage(SecOTRSessionRef session, + CFDataRef sourceMessage, + CFMutableDataRef protectedMessage) +{ + __block OSStatus result = errSecParam; + + require(session, abort); + require(sourceMessage, abort); + require(protectedMessage, abort); + + dispatch_sync(session->_queue, ^{ + if (session->_myKey == NULL || + session->_theirKey == NULL) { + return; + } + + uint8_t *messageKey; + uint8_t *macKey; + uint64_t *counter; + + SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirKey, + true, + &messageKey, &macKey, &counter); + + + CFMutableDataRef destinationMessage = session->_textOutput ? CFDataCreateMutable(kCFAllocatorDefault, 0) : CFRetainSafe(protectedMessage); + + result = session->_compactAppleMessages ? SecOTRSSignAndProtectCompact_locked(session, sourceMessage, destinationMessage, messageKey, macKey, counter) + : SecOTRSSignAndProtectRaw_locked(session, sourceMessage, destinationMessage, messageKey, macKey, counter); + + if (result == errSecSuccess) { + if (session->_textOutput) { + SecOTRPrepareOutgoingBytes(destinationMessage, protectedMessage); + } + + CFDataSetLength(session->_macKeysToExpose, 0); + } + + CFReleaseSafe(destinationMessage); + + result = errSecSuccess; + }); + +abort: + return result; +} + +static void SecOTRAcceptNewRemoteKey(SecOTRSessionRef session, SecOTRPublicDHKeyRef newKey) +{ + if (session->_theirPreviousKey) { + SecOTRSExpireCachedKeysForPublicKey(session, session->_theirPreviousKey); + } + + CFReleaseNull(session->_theirPreviousKey); + session->_theirPreviousKey = session->_theirKey; + session->_theirKey = CFRetainSafe(newKey); + + session->_theirKeyID += 1; +} + +static void SecOTRGenerateNewProposedKey(SecOTRSessionRef session) +{ + SecOTRSExpireCachedKeysForFullKey(session, session->_myKey); + + // Swap the keys so we know the current key. + { + SecOTRFullDHKeyRef oldKey = session->_myKey; + session->_myKey = session->_myNextKey; + session->_myNextKey = oldKey; + } + + // Derive a new next key by regenerating over the old key. + SecFDHKNewKey(session->_myNextKey); + + session->_keyID += 1; +} + +static OSStatus SecOTRVerifyAndExposeRaw_locked(SecOTRSessionRef session, + CFDataRef decodedBytes, + CFMutableDataRef exposedMessageContents) +{ + OSStatus result = errSecDecode; + + SecOTRPublicDHKeyRef newKey = NULL; + const uint8_t* bytes; + size_t size; + + bytes = CFDataGetBytePtr(decodedBytes); + size = CFDataGetLength(decodedBytes); + + const uint8_t* macDataStart = bytes; + + uint32_t theirID; + uint32_t myID; + + require_noerr_quiet(result = ReadAndVerifyHeader(&bytes, &size, kDataMessage), fail); + require_action_quiet(size > 0, fail, result = errSecDecode); + + require_noerr_quiet(result = ReadAndVerifyByte(&bytes, &size, 0), fail); // Flags, always zero + + require_noerr_quiet(result = ReadLong(&bytes, &size, &theirID), fail); + + require_action_quiet(theirID == session->_theirKeyID || (theirID == (session->_theirKeyID - 1) && session->_theirPreviousKey != NULL), + fail, + result = ((theirID + 1) < session->_theirKeyID) ? errSecOTRTooOld : errSecOTRIDTooNew); + + require_noerr_quiet(result = ReadLong(&bytes, &size, &myID), fail); + + require_action_quiet(myID == session->_keyID || (myID == session->_keyID + 1 && session->_myNextKey != NULL), + fail, + result = (myID < session->_keyID) ? errSecOTRTooOld : errSecOTRIDTooNew); + + + // Choose appripriate keys for message: + { + uint8_t *messageKey; + uint8_t *macKey; + uint64_t *theirCounter; + + SecOTRFullDHKeyRef myKeyForMessage = (myID == session->_keyID) ? session->_myKey : session->_myNextKey; + SecOTRPublicDHKeyRef theirKeyForMessage = (theirID == session->_theirKeyID) ? session->_theirKey : session->_theirPreviousKey; + + SecOTRSFindKeysForMessage(session, myKeyForMessage, theirKeyForMessage, false, + &messageKey, &macKey, &theirCounter); + + size_t nextKeyMPISize; + const uint8_t* nextKeyMPIBytes; + require_noerr_quiet(result = SizeAndSkipMPI(&bytes, &size, &nextKeyMPIBytes, &nextKeyMPISize), fail); + + uint64_t counter; + require_noerr_quiet(result = ReadLongLong(&bytes, &size, &counter), fail); + require_action_quiet(counter > *theirCounter, fail, result = errSecOTRTooOld); + + size_t messageSize; + const uint8_t* messageStart; + require_noerr_quiet(result = SizeAndSkipDATA(&bytes, &size, &messageStart, &messageSize), fail); + + size_t macDataSize = (bytes - macDataStart) ? (size_t)(bytes - macDataStart) : 0; + uint8_t mac[CCSHA1_OUTPUT_SIZE]; + require_action_quiet(sizeof(mac) <= size, fail, result = errSecDecode); + + cchmac(ccsha1_di(), + kOTRMessageMacKeyBytes, macKey, + macDataSize, macDataStart, + mac); + + require_noerr_action_quiet(constant_memcmp(mac, bytes, sizeof(mac)), fail, result = errSecAuthFailed); + + uint8_t* dataSpace = CFDataIncreaseLengthAndGetMutableBytes(exposedMessageContents, (CFIndex)messageSize); + + AES_CTR_HighHalf_Transform(kOTRMessageKeyBytes, messageKey, + counter, + messageSize, messageStart, + dataSpace); + + // Everything is good, accept the meta data. + *theirCounter = counter; + + newKey = SecOTRPublicDHKCreateFromBytes(kCFAllocatorDefault, &nextKeyMPIBytes, &nextKeyMPISize); + } + + bool acceptTheirNewKey = newKey != NULL && theirID == session->_theirKeyID; + + if (acceptTheirNewKey) { + SecOTRAcceptNewRemoteKey(session, newKey); + } + + if (myID == (session->_keyID + 1)) { + SecOTRGenerateNewProposedKey(session); + } + + SecOTRSPrecalculateKeysInternal(session); + +fail: + CFReleaseNull(newKey); + return result; +} + +static OSStatus SecOTRVerifyAndExposeRawCompact_locked(SecOTRSessionRef session, + CFDataRef decodedBytes, + CFMutableDataRef exposedMessageContents) +{ + SecOTRPublicDHKeyRef theirProposal = NULL; + OSStatus result = errSecDecode; + const uint8_t* bytes; + size_t size; + + bytes = CFDataGetBytePtr(decodedBytes); + size = CFDataGetLength(decodedBytes); + + const uint8_t* macDataStart = bytes; + + uint8_t type_byte; + require_noerr_quiet(result = ReadByte(&bytes, &size, &type_byte), fail); + require_action_quiet(type_byte == kOddCompactDataMessage || type_byte == kEvenCompactDataMessage, fail, result = errSecDecode); + + bool useEvenKey = (type_byte == kEvenCompactDataMessage); + + bool useCurrentKey = useEvenKey ^ (session->_keyID & 1); + SecOTRFullDHKeyRef myKeyForMessage = useCurrentKey ? session->_myKey : session->_myNextKey; + + theirProposal = SecOTRPublicDHKCreateFromCompactSerialization(kCFAllocatorDefault, &bytes, &size); + + require_action_quiet(theirProposal, fail, result = errSecDecode); + + bool proposalIsNew = !CFEqualSafe(theirProposal, session->_theirKey); + SecOTRPublicDHKeyRef theirKeyForMessage = proposalIsNew ? session->_theirKey : session->_theirPreviousKey; + + uint8_t *messageKey; + uint8_t *macKey; + uint64_t *theirCounter; + + SecOTRSFindKeysForMessage(session, myKeyForMessage, theirKeyForMessage, false, &messageKey, &macKey, &theirCounter); + + uint64_t counter; + require_noerr_quiet(result = ReadLongLongCompact(&bytes, &size, &counter), fail); + require_action_quiet(counter > *theirCounter, fail, result = errSecOTRTooOld); + + uint8_t mac[CCSHA1_OUTPUT_SIZE]; + require_action_quiet(sizeof(mac) < size, fail, result = errSecDecode); // require space for the mac and some bytes + + size_t messageSize = size - kCompactMessageMACSize; // It's all message except for the MAC + const uint8_t* messageStart = bytes; + + bytes += messageSize; + + size_t macDataSize = (size_t)(bytes - macDataStart); + + cchmac(ccsha1_di(), + kOTRMessageMacKeyBytes, macKey, + macDataSize, macDataStart, + mac); + + require_noerr_action_quiet(constant_memcmp(mac, bytes, kCompactMessageMACSize), fail, result = errSecAuthFailed); + + uint8_t* dataSpace = CFDataIncreaseLengthAndGetMutableBytes(exposedMessageContents, (CFIndex)messageSize); + + AES_CTR_HighHalf_Transform(kOTRMessageKeyBytes, messageKey, + counter, + messageSize, messageStart, + dataSpace); + + // Everything is good, accept the meta data. + *theirCounter = counter; + + if (proposalIsNew) { + SecOTRAcceptNewRemoteKey(session, theirProposal); + } + + if (!useCurrentKey) { + SecOTRGenerateNewProposedKey(session); + } + + SecOTRSPrecalculateKeysInternal(session); + +fail: + CFReleaseNull(theirProposal); + return result; +} + + +OSStatus SecOTRSVerifyAndExposeMessage(SecOTRSessionRef session, + CFDataRef incomingMessage, + CFMutableDataRef exposedMessageContents) +{ + __block OSStatus result = errSecParam; + + + require(session, abort); + require(incomingMessage, abort); + require(exposedMessageContents, abort); + + dispatch_sync(session->_queue, ^{ + CFDataRef decodedBytes = SecOTRCopyIncomingBytes(incomingMessage); + + OTRMessageType messageType = SecOTRSGetMessageType(decodedBytes); + + switch (messageType) { + case kDataMessage: + result = SecOTRVerifyAndExposeRaw_locked(session, decodedBytes, exposedMessageContents); + break; + + case kOddCompactDataMessage: + case kEvenCompactDataMessage: + result = SecOTRVerifyAndExposeRawCompact_locked(session, decodedBytes, exposedMessageContents); + break; + + default: + result = errSecUnsupportedFormat; + break; + } + + CFReleaseSafe(decodedBytes); + }); + +abort: + return result; +} + + +OSStatus SecOTRSEndSession(SecOTRSessionRef session, + CFMutableDataRef messageToSend) +{ + return errSecUnimplemented; +} + +static CFDataRef data_to_data_error_request(enum SecXPCOperation op, CFDataRef publicPeerId, CFErrorRef *error) { + __block CFDataRef result = NULL; + securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { + return SecXPCDictionarySetDataOptional(message, kSecXPCPublicPeerId, publicPeerId, error); + }, ^bool(xpc_object_t response, CFErrorRef *error) { + return (result = SecXPCDictionaryCopyData(response, kSecXPCKeyResult, error)); + }); + return result; +} + +static bool data_data_to_data_data_bool_error_request(enum SecXPCOperation op, CFDataRef sessionData, CFDataRef inputPacket, CFDataRef* outputSessionData, CFDataRef* outputPacket, bool *readyForMessages, CFErrorRef *error) { + __block CFDataRef tempOutputSessionData = NULL; + __block CFDataRef tempOutputPacket = NULL; + __block bool tempReadyForMessages = false; + + bool result = securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { + return SecXPCDictionarySetDataOptional(message, kSecXPCOTRSession, sessionData, error) + && SecXPCDictionarySetDataOptional(message, kSecXPCData, inputPacket, error); + }, ^bool(xpc_object_t response, CFErrorRef *error) { + if (xpc_dictionary_get_bool(response, kSecXPCKeyResult)) { + tempOutputSessionData = SecXPCDictionaryCopyData(response, kSecXPCOTRSession, error); + tempOutputPacket = SecXPCDictionaryCopyData(response, kSecXPCData, error); + tempReadyForMessages = xpc_dictionary_get_bool(response, kSecXPCOTRReady); + return true; + } else { + return false; + } + + }); + + *outputSessionData = tempOutputSessionData; + *outputPacket = tempOutputPacket; + *readyForMessages = tempReadyForMessages; + + return result; +} + + +CFDataRef SecOTRSessionCreateRemote(CFDataRef publicPeerId, CFErrorRef *error) { + + CFDataRef otrSession = SECURITYD_XPC(sec_otr_session_create_remote, data_to_data_error_request, publicPeerId, error); + return otrSession; + +} + +bool SecOTRSessionProcessPacketRemote(CFDataRef sessionData, CFDataRef inputPacket, CFDataRef* outputSessionData, CFDataRef* outputPacket, bool *readyForMessages, CFErrorRef *error) { + + return SECURITYD_XPC(sec_otr_session_process_packet_remote, data_data_to_data_data_bool_error_request, sessionData, inputPacket, outputSessionData, outputPacket, readyForMessages, error); +} diff --git a/Security/sec/Security/SecOTRSession.h b/Security/sec/Security/SecOTRSession.h new file mode 100644 index 00000000..5b60f81e --- /dev/null +++ b/Security/sec/Security/SecOTRSession.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef _SECOTRSESSION_H_ +#define _SECOTRSESSION_H_ + +#include +#include + +#include + +__BEGIN_DECLS + +// MARK: MessageTypes + +enum SecOTRSMessageKind { + kOTRNegotiationPacket, + kOTRDataPacket, + kOTRUnknownPacket +}; + +// MARK: OTR Session + +enum SecOTRCreateFlags { + kSecOTRSendTextMessages = 1, // OTR messages will be encoded as Base-64 with header/footer per the standard, not just given back in binary + kSecOTRUseAppleCustomMessageFormat = 2, // OTR Messages will be encoded without revealing MAC keys and as compact as we can (P-256) +}; + +/*! + @typedef + @abstract OTRSessions encapsulate a commuincaiton between to parties using the + otr protocol. + @discussion Sessions start with IDs. One end sends a start packet (created with AppendStartPacket). + Both sides process packets they exchange on the negotiation channel. + */ +typedef struct _SecOTRSession* SecOTRSessionRef; + +SecOTRSessionRef SecOTRSessionCreateFromID(CFAllocatorRef allocator, + SecOTRFullIdentityRef myID, + SecOTRPublicIdentityRef theirID); + +SecOTRSessionRef SecOTRSessionCreateFromIDAndFlags(CFAllocatorRef allocator, + SecOTRFullIdentityRef myID, + SecOTRPublicIdentityRef theirID, + uint32_t flags); + +SecOTRSessionRef SecOTRSessionCreateFromData(CFAllocatorRef allocator, CFDataRef data); + + void SecOTRSessionReset(SecOTRSessionRef session); +OSStatus SecOTRSAppendSerialization(SecOTRSessionRef publicID, CFMutableDataRef serializeInto); + +OSStatus SecOTRSAppendStartPacket(SecOTRSessionRef session, CFMutableDataRef appendInitiatePacket); + +OSStatus SecOTRSAppendRestartPacket(SecOTRSessionRef session, CFMutableDataRef appendPacket); + +OSStatus SecOTRSProcessPacket(SecOTRSessionRef session, + CFDataRef incomingPacket, + CFMutableDataRef negotiationResponse); + +OSStatus SecOTRSEndSession(SecOTRSessionRef session, + CFMutableDataRef messageToSend); + + +bool SecOTRSGetIsReadyForMessages(SecOTRSessionRef session); +bool SecOTRSGetIsIdle(SecOTRSessionRef session); + +enum SecOTRSMessageKind SecOTRSGetMessageKind(SecOTRSessionRef session, CFDataRef incomingPacket); + +/*! + @function + @abstract Precalculates keys for current key sets to save time when sending or receiving. + @param session OTRSession receiving message + */ +void SecOTRSPrecalculateKeys(SecOTRSessionRef session); + +/*! + @function + @abstract Encrypts and Signs a message with OTR credentials. + @param session OTRSession receiving message + @param incomingMessage Cleartext message to protect + @param protectedMessage Data to append the encoded protected message to + @result OSStatus errSecAuthFailed -> bad signature, no data appended. + */ + +OSStatus SecOTRSSignAndProtectMessage(SecOTRSessionRef session, + CFDataRef sourceMessage, + CFMutableDataRef protectedMessage); + +/*! + @function + @abstract Verifies and exposes a message sent via OTR + @param session OTRSession receiving message + @param incomingMessage Encoded message + @param exposedMessageContents Data to append the exposed message to + @result OSStatus errSecAuthFailed -> bad signature, no data appended. + */ + +OSStatus SecOTRSVerifyAndExposeMessage(SecOTRSessionRef session, + CFDataRef incomingMessage, + CFMutableDataRef exposedMessageContents); + + + +const char *SecOTRPacketTypeString(CFDataRef message); + +CFDataRef SecOTRSessionCreateRemote(CFDataRef publicPeerId, CFErrorRef *error); +bool SecOTRSessionProcessPacketRemote(CFDataRef sessionData, CFDataRef inputPacket, CFDataRef* outputSessionData, CFDataRef* outputPacket, bool *readyForMessages, CFErrorRef *error); + + +__END_DECLS + +#endif diff --git a/sec/Security/SecOTRSessionAKE.c b/Security/sec/Security/SecOTRSessionAKE.c similarity index 91% rename from sec/Security/SecOTRSessionAKE.c rename to Security/sec/Security/SecOTRSessionAKE.c index 8c6664a2..0613d815 100644 --- a/sec/Security/SecOTRSessionAKE.c +++ b/Security/sec/Security/SecOTRSessionAKE.c @@ -1,10 +1,26 @@ -// -// SecOTRSession.c -// libsecurity_libSecOTR -// -// Created by Mitch Adler on 2/22/11. -// Copyright 2011 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include "SecOTRSession.h" @@ -51,11 +67,11 @@ OSStatus SecOTRSAppendStartPacket(SecOTRSessionRef session, CFMutableDataRef app // Generate r and x and calculate gx: SecOTRInitMyDHKeys(session); - CFMutableDataRef destinationMessage; + CFMutableDataRef destinationMessage = NULL; if (session->_textOutput) { destinationMessage = CFDataCreateMutable(kCFAllocatorDefault, 0); } else { - destinationMessage = appendPacket; + destinationMessage = CFRetainSafe(appendPacket); } @@ -64,9 +80,9 @@ OSStatus SecOTRSAppendStartPacket(SecOTRSessionRef session, CFMutableDataRef app SecOTRAppendDHMessage(session, destinationMessage); if (session->_textOutput) { SecOTRPrepareOutgoingBytes(destinationMessage, appendPacket); - CFReleaseSafe(destinationMessage); } } + CFReleaseSafe(destinationMessage); }); return result; @@ -86,7 +102,7 @@ OSStatus SecOTRSAppendRestartPacket(SecOTRSessionRef session, CFMutableDataRef a if (session->_textOutput) { destinationMessage = CFDataCreateMutable(kCFAllocatorDefault, 0); } else { - destinationMessage = appendPacket; + destinationMessage = CFRetainSafe(appendPacket); } session->_state = kAwaitingDHKey; @@ -96,8 +112,8 @@ OSStatus SecOTRSAppendRestartPacket(SecOTRSessionRef session, CFMutableDataRef a SecOTRAppendDHMessage(session, destinationMessage); if (session->_textOutput) { SecOTRPrepareOutgoingBytes(destinationMessage, appendPacket); - CFReleaseSafe(destinationMessage); } + CFReleaseSafe(destinationMessage); }); return result; @@ -237,7 +253,6 @@ static OSStatus SecOTRSProcessDHKeyMessage(SecOTRSessionRef session, SecOTRAppendRevealSignatureMessage(session, negotiationResponse); session->_state = kAwaitingSignature; session->_receivedDHKeyMessage = CFDataCreateCopy(kCFAllocatorDefault, incomingPacket); - CFRetain(incomingPacket); result = errSecSuccess; break; case kAwaitingSignature: @@ -388,8 +403,8 @@ static OSStatus SecVerifySignatureAndMac(SecOTRSessionRef session, uint32_t xbSize = 0; result = ReadLong(signatureAndMacBytes, signatureAndMacSize, &xbSize); require_noerr(result, exit); - require(xbSize > 4, exit); - require(xbSize <= *signatureAndMacSize, exit); + require_action(xbSize > 4, exit, result = errSecDecode); + require_action(xbSize <= *signatureAndMacSize, exit, result = errSecDecode); uint8_t signatureMac[CCSHA256_OUTPUT_SIZE]; cchmac(ccsha256_di(), sizeof(m2), m2, xbSize + 4, encSigDataBlobStart, signatureMac); @@ -398,7 +413,7 @@ static OSStatus SecVerifySignatureAndMac(SecOTRSessionRef session, const uint8_t *macStart = *signatureAndMacBytes + xbSize; // check the outer hmac - require(0 == memcmp(macStart, signatureMac, kSHA256HMAC160Bytes), exit); + require_action(0 == memcmp(macStart, signatureMac, kSHA256HMAC160Bytes), exit, result = errSecDecode); { @@ -516,8 +531,7 @@ OSStatus SecOTRSProcessPacket(SecOTRSessionRef session, require(CFDataGetLength(incomingPacket) > 0, fail); dispatch_sync(session->_queue, ^{ - CFMutableDataRef decodedBytes = CFDataCreateMutable(kCFAllocatorDefault, 0); - SecOTRGetIncomingBytes(incomingPacket, decodedBytes); + CFDataRef decodedBytes = SecOTRCopyIncomingBytes(incomingPacket); const uint8_t* bytes = CFDataGetBytePtr(decodedBytes); size_t size = CFDataGetLength(decodedBytes); @@ -530,7 +544,7 @@ OSStatus SecOTRSProcessPacket(SecOTRSessionRef session, if (session->_textOutput) { destinationMessage = CFDataCreateMutable(kCFAllocatorDefault, 0); } else { - destinationMessage = negotiationResponse; + destinationMessage = CFRetainSafe(negotiationResponse); } switch (packetType) { @@ -557,8 +571,8 @@ OSStatus SecOTRSProcessPacket(SecOTRSessionRef session, if (session->_textOutput) { SecOTRPrepareOutgoingBytes(destinationMessage, negotiationResponse); - CFReleaseSafe(destinationMessage); } + CFReleaseSafe(destinationMessage); CFReleaseSafe(decodedBytes); }); diff --git a/Security/sec/Security/SecOTRSessionPriv.h b/Security/sec/Security/SecOTRSessionPriv.h new file mode 100644 index 00000000..357890eb --- /dev/null +++ b/Security/sec/Security/SecOTRSessionPriv.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef _SECOTRSESSIONPRIV_H_ +#define _SECOTRSESSIONPRIV_H_ + +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include +#include + +__BEGIN_DECLS + +typedef enum { + kIdle, + kAwaitingDHKey, + kAwaitingRevealSignature, + kAwaitingSignature, + kDone +} SecOTRAuthState; + +struct _SecOTRCacheElement { + uint8_t _fullKeyHash[CCSHA1_OUTPUT_SIZE]; + uint8_t _publicKeyHash[CCSHA1_OUTPUT_SIZE]; + + uint8_t _sendMacKey[kOTRMessageMacKeyBytes]; + uint8_t _sendEncryptionKey[kOTRMessageKeyBytes]; + + uint8_t _receiveMacKey[kOTRMessageMacKeyBytes]; + uint8_t _receiveEncryptionKey[kOTRMessageKeyBytes]; + + uint64_t _counter; + uint64_t _theirCounter; + +}; +typedef struct _SecOTRCacheElement SecOTRCacheElement; + +#define kOTRKeyCacheSize 4 + +struct _SecOTRSession { + CFRuntimeBase _base; + + SecOTRAuthState _state; + + SecOTRFullIdentityRef _me; + SecOTRPublicIdentityRef _them; + + uint8_t _r[kOTRAuthKeyBytes]; + + CFDataRef _receivedDHMessage; + CFDataRef _receivedDHKeyMessage; + + uint32_t _keyID; + SecOTRFullDHKeyRef _myKey; + SecOTRFullDHKeyRef _myNextKey; + + uint32_t _theirKeyID; + SecOTRPublicDHKeyRef _theirPreviousKey; + SecOTRPublicDHKeyRef _theirKey; + + CFMutableDataRef _macKeysToExpose; + + dispatch_queue_t _queue; + + SecOTRCacheElement _keyCache[kOTRKeyCacheSize]; + + bool _textOutput; + bool _compactAppleMessages; +}; + +CFDataRef SecOTRCopyIncomingBytes(CFDataRef incomingMessage); +void SecOTRPrepareOutgoingBytes(CFMutableDataRef destinationMessage, CFMutableDataRef protectedMessage); + +__END_DECLS + +#endif diff --git a/sec/Security/SecOTRUtils.c b/Security/sec/Security/SecOTRUtils.c similarity index 79% rename from sec/Security/SecOTRUtils.c rename to Security/sec/Security/SecOTRUtils.c index 76b24042..7b18c583 100644 --- a/sec/Security/SecOTRUtils.c +++ b/Security/sec/Security/SecOTRUtils.c @@ -1,10 +1,26 @@ -// -// SecOTRUtils.c -// libSecOTR -// -// Created by Keith Henrickson on 6/11/12. -// -// +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include "SecOTR.h" #include "SecOTRIdentityPriv.h" @@ -24,7 +40,7 @@ CFStringRef sLocalErrorDomain = CFSTR("com.apple.security.otr.error"); -void SecOTRCreateError(enum SecOTRError family, CFIndex errorCode, CFStringRef descriptionString, CFErrorRef previousError, CFErrorRef *newError) { +bool SecOTRCreateError(enum SecOTRError family, CFIndex errorCode, CFStringRef descriptionString, CFErrorRef previousError, CFErrorRef *newError) { if (newError && !(*newError)) { const void* keys[2] = {kCFErrorDescriptionKey, kCFErrorUnderlyingErrorKey}; const void* values[2] = {descriptionString, previousError}; @@ -32,6 +48,8 @@ void SecOTRCreateError(enum SecOTRError family, CFIndex errorCode, CFStringRef d } else { CFReleaseSafe(previousError); } + + return false; } OSStatus insertSize(CFIndex size, uint8_t* here) @@ -163,24 +181,31 @@ SecKeyRef CreateECPublicKeyFrom(CFAllocatorRef allocator, const uint8_t** data, return CallCreateFunctionFrom(allocator, data, limit, &SecKeyCreateECPublicKey); } -void SecOTRGetIncomingBytes(CFDataRef incomingMessage, CFMutableDataRef decodedBytes) +CFDataRef SecOTRCopyIncomingBytes(CFDataRef incomingMessage) { + CFDataRef result = NULL; + CFDataRef header = CFStringCreateExternalRepresentation(kCFAllocatorDefault, CFSTR("?OTR:"), kCFStringEncodingUTF8, '?'); - CFDataRef footer = CFStringCreateExternalRepresentation(kCFAllocatorDefault, CFSTR("."), kCFStringEncodingUTF8, '?'); CFRange headerLoc = CFDataFind(incomingMessage, header, CFRangeMake(0, CFDataGetLength(header)), 0); - CFRange footerLoc = CFDataFind(incomingMessage, footer, CFRangeMake(0, CFDataGetLength(incomingMessage)), 0); + if (kCFNotFound == headerLoc.location) { - CFDataAppend(decodedBytes, incomingMessage); + CFRetainAssign(result, incomingMessage); } else { + CFDataRef footer = CFStringCreateExternalRepresentation(kCFAllocatorDefault, CFSTR("."), kCFStringEncodingUTF8, '?'); + CFRange footerLoc = CFDataFind(incomingMessage, footer, CFRangeMake(0, CFDataGetLength(incomingMessage)), 0); + CFDataRef bodyData = CFDataCreateReferenceFromRange(kCFAllocatorDefault, incomingMessage, CFRangeMake(headerLoc.length, footerLoc.location - headerLoc.length)); size_t size = SecBase64Decode((char*)CFDataGetBytePtr(bodyData), CFDataGetLength(bodyData), NULL, 0); uint8_t decodedByteArray[size]; SecBase64Decode((char*)CFDataGetBytePtr(bodyData), CFDataGetLength(bodyData), decodedByteArray, size); - CFDataAppendBytes(decodedBytes, decodedByteArray, size); + result = CFDataCreate(kCFAllocatorDefault, decodedByteArray, size); + CFRelease(bodyData); + CFRelease(footer); } CFRelease(header); - CFRelease(footer); + + return result; } void SecOTRPrepareOutgoingBytes(CFMutableDataRef destinationMessage, CFMutableDataRef protectedMessage) diff --git a/Security/sec/Security/SecOnOSX.h b/Security/sec/Security/SecOnOSX.h new file mode 100644 index 00000000..ab53de04 --- /dev/null +++ b/Security/sec/Security/SecOnOSX.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2011,2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef _SECONOSX_H_ +#define _SECONOSX_H_ + +#include + +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) + +#include + +#define SecKeyCreateFromPublicData _SecKeyCreateFromPublicData + +#if 0 +SecKeyRef SecKeyCreateFromPublicData(CFAllocatorRef allocator, CFIndex algorithmID, CFDataRef serialized); +#endif + +#endif /* TARGET_OS_MAC */ + +#endif /* _SECONOSX_H_ */ + + diff --git a/sec/Security/SecPBKDF.c b/Security/sec/Security/SecPBKDF.c similarity index 96% rename from sec/Security/SecPBKDF.c rename to Security/sec/Security/SecPBKDF.c index b93a7ed8..0aa2bc24 100644 --- a/sec/Security/SecPBKDF.c +++ b/Security/sec/Security/SecPBKDF.c @@ -1,7 +1,7 @@ /* * SecPBKDF.c * - * Copyright 2010 Apple Inc. All rights reserved. + * Copyright (c) 2010,2012 Apple Inc. All Rights Reserved. * */ diff --git a/sec/Security/SecPBKDF.h b/Security/sec/Security/SecPBKDF.h similarity index 97% rename from sec/Security/SecPBKDF.h rename to Security/sec/Security/SecPBKDF.h index 9d125f3c..9f92da94 100644 --- a/sec/Security/SecPBKDF.h +++ b/Security/sec/Security/SecPBKDF.h @@ -1,7 +1,7 @@ /* * SecPBKDF.h * - * Copyright 2010 Apple Inc. All rights reserved. + * Copyright (c) 2010,2012 Apple Inc. All Rights Reserved. * */ diff --git a/sec/Security/SecPasswordGenerate.c b/Security/sec/Security/SecPasswordGenerate.c similarity index 88% rename from sec/Security/SecPasswordGenerate.c rename to Security/sec/Security/SecPasswordGenerate.c index 07db08ca..01740612 100644 --- a/sec/Security/SecPasswordGenerate.c +++ b/Security/sec/Security/SecPasswordGenerate.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2013 Apple Inc. All Rights Reserved. + * 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, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -170,7 +170,6 @@ static unsigned int pinhash (const char *str, unsigned int len) //pins that reached the top 20 list static const char *blacklist[] = {"1234", "1004", "2000", "1122", "4321", "2001", "2580"}; - bool SecPasswordIsPasswordWeak(CFStringRef passcode) { uppercaseLetterCharacterSet = CFCharacterSetGetPredefined(kCFCharacterSetUppercaseLetter); @@ -202,7 +201,7 @@ bool SecPasswordIsPasswordWeak(CFStringRef passcode) free(pin); return true; } - + CFIndex blacklistLength = (CFIndex)sizeof(blacklist)/sizeof(blacklist[0]); //not all the same number @@ -323,6 +322,165 @@ bool SecPasswordIsPasswordWeak(CFStringRef passcode) } +bool SecPasswordIsPasswordWeak2(bool isSimple, CFStringRef passcode) +{ + uppercaseLetterCharacterSet = CFCharacterSetGetPredefined(kCFCharacterSetUppercaseLetter); + lowercaseLetterCharacterSet = CFCharacterSetGetPredefined(kCFCharacterSetLowercaseLetter); + decimalDigitCharacterSet = CFCharacterSetGetPredefined(kCFCharacterSetDecimalDigit); + punctuationCharacterSet = CFCharacterSetGetPredefined(kCFCharacterSetPunctuation); + + + char* pin = NULL; + + //length checks + if( CFStringGetLength(passcode) < 4 ){ + return true; //weak password + } + + bool isPasscodeNumber = true; + //check to see if passcode is a number + for(CFIndex i = 0; i < CFStringGetLength(passcode); i++){ + if( CFStringFindCharacterFromSet(passcode, decimalDigitCharacterSet, CFRangeMake(i,1), 0, NULL)) + continue; + else { + isPasscodeNumber = false; + break; + } + } + + if(isSimple){ + //checking to see if it's a 4 digit pin + if(isPasscodeNumber && CFStringGetLength(passcode) == 4){ + + pin = CFStringToCString(passcode); + if(in_word_set(pin, 4)){ + free(pin); + return true; + } + + CFIndex blacklistLength = (CFIndex)sizeof(blacklist)/sizeof(blacklist[0]); + + //not all the same number + if(pin[0] == pin[1] == pin[2] == pin[3]){ + free(pin); + return true; //weak password + } + //first two digits being the same and the last two digits being the same + if ( pin[0] == pin[1] && pin[2] == pin[3]){ + free(pin); + return true; //weak password + } + //first two digits not being the same as the last two digits + if(pin[0] == pin[2] && pin[1] == pin[3]){ + free(pin); + return true; //weak password + } + //not in this list + for(CFIndex i = 0; i < blacklistLength; i++) + { + const char* blackCode = blacklist[i]; + if(0 == strcmp(blackCode, pin)) + { + free(pin); + return true; //weak password + } + } + } + else //should be a 4 digit number + return false; + } + else if(isPasscodeNumber && !isSimple){ //dealing with a complex numeric passcode + pin = CFStringToCString(passcode); + //check if PIN is all the same number + for(int i = 0; i < CFStringGetLength(passcode); i++){ + if(i+1 >= CFStringGetLength(passcode)){ + free(pin); + return true; + } + else if (pin[i] == pin[i+1]) + continue; + else + break; + } + //check if PIN is a bunch of incrementing numbers + for(int i = 0; i < CFStringGetLength(passcode); i++){ + if(i == CFStringGetLength(passcode)-1){ + free(pin); + return true; + } + else if ((pin[i] + 1) == pin[i+1]) + continue; + else + break; + } + //check if PIN is a bunch of decrementing numbers + for(int i = 0; i < CFStringGetLength(passcode); i++){ + if(i == CFStringGetLength(passcode)-1){ + free(pin); + return true; + } + else if ((pin[i]) == (pin[i+1] +1)) + continue; + else + break; + } + } + else{ // password is complex, evaluate entropy + int u = 0; + int l = 0; + int d = 0; + int p = 0; + int characterSet = 0; + + //calculate new entropy + for(CFIndex i = 0; i < CFStringGetLength(passcode); i++){ + + if( CFStringFindCharacterFromSet(passcode, uppercaseLetterCharacterSet, CFRangeMake(i,1), kCFCompareBackwards, NULL)){ + u++; + continue; + } + if( CFStringFindCharacterFromSet(passcode, lowercaseLetterCharacterSet, CFRangeMake(i,1), kCFCompareBackwards, NULL)){ + l++; + continue; + } + if( CFStringFindCharacterFromSet(passcode, decimalDigitCharacterSet, CFRangeMake(i,1), kCFCompareBackwards, NULL)){ + d++; + continue; + } + if( CFStringFindCharacterFromSet(passcode, punctuationCharacterSet, CFRangeMake(i,1), kCFCompareBackwards, NULL)){ + p++; + continue; + } + + } + if(u > 0){ + characterSet += alphabetSetSize; + } + if(l > 0){ + characterSet += alphabetSetSize; + } + if(d > 0){ + characterSet += decimalSetSize; + } + if(p > 0){ + characterSet += punctuationSetSize; + } + + double strength = CFStringGetLength(passcode)*log2(characterSet); + + if(strength < entropyStrengthThreshold){ + return true; //weak + } + else + return false; //strong + } + if(pin) + free(pin); + + return false; //strong password + +} + static void getUniformRandomNumbers(uint8_t* buffer, size_t numberOfDesiredNumbers, uint8_t upperBound) { @@ -509,8 +667,8 @@ static void passwordGenerateDefaultParametersDictionary(CFDictionaryRef *returne numReqChars = CFNumberCreateWithCFIndex(kCFAllocatorDefault, defaultiCloudPasswordLength); groupSize = 4; numberOfGroups = 6; - groupSizeRef = CFNumberCreate(NULL, kCFNumberIntType, &groupSize); - numberOfGroupsRef = CFNumberCreate(NULL, kCFNumberIntType, &numberOfGroups); + groupSizeRef = CFNumberCreate(NULL, kCFNumberCFIndexType, &groupSize); + numberOfGroupsRef = CFNumberCreate(NULL, kCFNumberCFIndexType, &numberOfGroups); uppercaseLetterCharacterSet = CFCharacterSetGetPredefined(kCFCharacterSetUppercaseLetter); decimalDigitCharacterSet = CFCharacterSetGetPredefined(kCFCharacterSetDecimalDigit); @@ -530,8 +688,8 @@ static void passwordGenerateDefaultParametersDictionary(CFDictionaryRef *returne numReqChars = CFNumberCreateWithCFIndex(kCFAllocatorDefault, defaultPINLength); groupSize = 4; numberOfGroups = 1; - groupSizeRef = CFNumberCreate(NULL, kCFNumberIntType, &groupSize); - numberOfGroupsRef = CFNumberCreate(NULL, kCFNumberIntType, &numberOfGroups); + groupSizeRef = CFNumberCreate(NULL, kCFNumberCFIndexType, &groupSize); + numberOfGroupsRef = CFNumberCreate(NULL, kCFNumberCFIndexType, &numberOfGroups); decimalDigitCharacterSet = CFCharacterSetGetPredefined(kCFCharacterSetDecimalDigit); CFArrayAppendValue(requiredCharacterSets, decimalDigitCharacterSet); @@ -548,8 +706,8 @@ static void passwordGenerateDefaultParametersDictionary(CFDictionaryRef *returne case(kSecPasswordTypeWifi): groupSize = 4; numberOfGroups = 3; - groupSizeRef = CFNumberCreate(NULL, kCFNumberIntType, &groupSize); - numberOfGroupsRef = CFNumberCreate(NULL, kCFNumberIntType, &numberOfGroups); + groupSizeRef = CFNumberCreate(NULL, kCFNumberCFIndexType, &groupSize); + numberOfGroupsRef = CFNumberCreate(NULL, kCFNumberCFIndexType, &numberOfGroups); lowercaseLetterCharacterSet = CFCharacterSetGetPredefined(kCFCharacterSetLowercaseLetter); decimalDigitCharacterSet = CFCharacterSetGetPredefined(kCFCharacterSetDecimalDigit); @@ -570,8 +728,8 @@ static void passwordGenerateDefaultParametersDictionary(CFDictionaryRef *returne default: groupSize = 4; numberOfGroups = 6; - groupSizeRef = CFNumberCreate(NULL, kCFNumberIntType, &groupSize); - numberOfGroupsRef = CFNumberCreate(NULL, kCFNumberIntType, &numberOfGroups); + groupSizeRef = CFNumberCreate(NULL, kCFNumberCFIndexType, &groupSize); + numberOfGroupsRef = CFNumberCreate(NULL, kCFNumberCFIndexType, &numberOfGroups); uppercaseLetterCharacterSet = CFCharacterSetGetPredefined(kCFCharacterSetUppercaseLetter); lowercaseLetterCharacterSet = CFCharacterSetGetPredefined(kCFCharacterSetLowercaseLetter); decimalDigitCharacterSet = CFCharacterSetGetPredefined(kCFCharacterSetDecimalDigit); @@ -903,18 +1061,22 @@ static bool isDictionaryFormattedProperly(SecPasswordType type, CFDictionaryRef require_action_quiet(isNumber(identicalRef), fail, tempError = CFErrorCreate(kCFAllocatorDefault, CFSTR("The dictionary parameter 'Identical Consecutive Characters' is either null or not a number"), (CFIndex)errSecBadReq, NULL)); } } + fail: + { + bool result = true; if (tempError != NULL) { - *error = tempError; - CFRetain(*error); - return false; + if (error) + *error = CFRetainSafe(tempError); + result = false; } CFReleaseNull(tempError); - return true; + return result; +} } -static bool doesFinalPasswordPass(CFStringRef password, CFDictionaryRef requirements){ +static bool doesFinalPasswordPass(bool isSimple, CFStringRef password, CFDictionaryRef requirements){ CFTypeRef characters, identicalRef = NULL, NRef = NULL, endWith= NULL, startWith= NULL, atLeastCharacters= NULL, atMostCharacters = NULL; uint64_t valuePtr; @@ -971,7 +1133,7 @@ static bool doesFinalPasswordPass(CFStringRef password, CFDictionaryRef requirem if (!passwordContainsRequiredCharacters(password, requiredCharacterSet)) return false; - if(true == SecPasswordIsPasswordWeak(password)) + if(true == SecPasswordIsPasswordWeak2(isSimple, password)) return false; return true; @@ -979,17 +1141,21 @@ static bool doesFinalPasswordPass(CFStringRef password, CFDictionaryRef requirem //entry point into password generation CF_RETURNS_RETAINED CFStringRef SecPasswordGenerate(SecPasswordType type, CFErrorRef *error, CFDictionaryRef passwordRequirements){ - bool check = false; + bool check = false, isSimple = false; CFTypeRef separator = NULL, defaults = NULL, groupSizeRef = NULL, numberOfGroupsRef = NULL; CFDictionaryRef properlyFormattedRequirements = NULL; - *error = NULL; + CFErrorRef localError = NULL; uint64_t valuePtr, groupSize, numberOfGroups; CFNumberRef numberOfRequiredRandomCharacters; CFIndex requiredCharactersSize; CFStringRef randomCharacters = NULL, password = NULL, allowedChars = NULL; CFMutableStringRef finalPassword = NULL; - check = isDictionaryFormattedProperly(type, passwordRequirements, error); + if(type == kSecPasswordTypePIN) + isSimple = true; + else + isSimple = false; + check = isDictionaryFormattedProperly(type, passwordRequirements, &localError); require_quiet(check != false, fail); //should we generate defaults? @@ -1000,7 +1166,7 @@ CF_RETURNS_RETAINED CFStringRef SecPasswordGenerate(SecPasswordType type, CFErro CFRetain(properlyFormattedRequirements); - require_quiet(*error == NULL && properlyFormattedRequirements != NULL, fail); + require_quiet(localError == NULL && properlyFormattedRequirements != NULL, fail); numberOfRequiredRandomCharacters = (CFNumberRef)CFDictionaryGetValue(properlyFormattedRequirements, kSecNumberOfRequiredRandomCharactersKey); CFNumberGetValue(numberOfRequiredRandomCharacters, kCFNumberSInt64Type, &valuePtr); @@ -1056,7 +1222,7 @@ CF_RETURNS_RETAINED CFStringRef SecPasswordGenerate(SecPasswordType type, CFErro } CFReleaseNull(randomCharacters); - require_quiet(doesFinalPasswordPass(password, properlyFormattedRequirements), no_pass); + require_quiet(doesFinalPasswordPass(isSimple, password, properlyFormattedRequirements), no_pass); return password; no_pass: @@ -1064,6 +1230,12 @@ CF_RETURNS_RETAINED CFStringRef SecPasswordGenerate(SecPasswordType type, CFErro } fail: + if (error && localError) { + *error = localError; + localError = NULL; + } + + CFReleaseSafe(localError); CFReleaseNull(properlyFormattedRequirements); return NULL; } @@ -1108,60 +1280,52 @@ const char *in_word_set (const char *str, unsigned int len){ } CFDictionaryRef SecPasswordCopyDefaultPasswordLength(SecPasswordType type, CFErrorRef *error){ - CFIndex tupleLengthInt, numOfTuplesInt; + CFIndex tupleLengthInt = 0, numOfTuplesInt = 0; CFNumberRef tupleLength = NULL; CFNumberRef numOfTuples = NULL; CFMutableDictionaryRef passwordLengthDefaults = NULL; + CFDictionaryRef result = NULL; switch(type){ case(kSecPasswordTypeiCloudRecovery): tupleLengthInt = 4; numOfTuplesInt = 6; - tupleLength = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &tupleLengthInt); - numOfTuples = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &numOfTuplesInt); - passwordLengthDefaults = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 0, 0); - CFDictionaryAddValue(passwordLengthDefaults, kSecPasswordGroupSize, tupleLength); - CFDictionaryAddValue(passwordLengthDefaults, kSecPasswordNumberOfGroups, numOfTuples); - return CFDictionaryCreateCopy(kCFAllocatorDefault, passwordLengthDefaults); + break; case(kSecPasswordTypePIN): tupleLengthInt = 4; numOfTuplesInt = 1; - tupleLength = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &tupleLengthInt); - numOfTuples = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &numOfTuplesInt); - passwordLengthDefaults = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 0, 0); - CFDictionaryAddValue(passwordLengthDefaults, kSecPasswordGroupSize, tupleLength); - CFDictionaryAddValue(passwordLengthDefaults, kSecPasswordNumberOfGroups, numOfTuples); - return CFDictionaryCreateCopy(kCFAllocatorDefault, passwordLengthDefaults); + break; case(kSecPasswordTypeSafari): tupleLengthInt = 4; numOfTuplesInt = 5; - tupleLength = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &tupleLengthInt); - numOfTuples = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &numOfTuplesInt); - passwordLengthDefaults = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 0, 0); - CFDictionaryAddValue(passwordLengthDefaults, kSecPasswordGroupSize, tupleLength); - CFDictionaryAddValue(passwordLengthDefaults, kSecPasswordNumberOfGroups, numOfTuples); - return CFDictionaryCreateCopy(kCFAllocatorDefault, passwordLengthDefaults); + break; - case(kSecPasswordTypeWifi): tupleLengthInt = 4; numOfTuplesInt = 3; - tupleLength = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &tupleLengthInt); - numOfTuples = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &numOfTuplesInt); - passwordLengthDefaults = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 0, 0); - CFDictionaryAddValue(passwordLengthDefaults, kSecPasswordGroupSize, tupleLength); - CFDictionaryAddValue(passwordLengthDefaults, kSecPasswordNumberOfGroups, numOfTuples); - return CFDictionaryCreateCopy(kCFAllocatorDefault, passwordLengthDefaults); + break; - default: if(SecError(errSecBadReq, error, CFSTR("Password type does not exist.")) == false) { secdebug("secpasswordcopydefaultpasswordlength", "could not create error!"); } - return NULL; } + + if (tupleLengthInt != 0 && numOfTuplesInt != 0) { + tupleLength = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &tupleLengthInt); + numOfTuples = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &numOfTuplesInt); + passwordLengthDefaults = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 0, 0); + CFDictionaryAddValue(passwordLengthDefaults, kSecPasswordGroupSize, tupleLength); + CFDictionaryAddValue(passwordLengthDefaults, kSecPasswordNumberOfGroups, numOfTuples); + result = CFDictionaryCreateCopy(kCFAllocatorDefault, passwordLengthDefaults); +} + + CFReleaseSafe(tupleLength); + CFReleaseSafe(numOfTuples); + CFReleaseSafe(passwordLengthDefaults); + return result; } diff --git a/sec/Security/SecPasswordGenerate.h b/Security/sec/Security/SecPasswordGenerate.h similarity index 87% rename from sec/Security/SecPasswordGenerate.h rename to Security/sec/Security/SecPasswordGenerate.h index deb693c1..8af30ba5 100644 --- a/sec/Security/SecPasswordGenerate.h +++ b/Security/sec/Security/SecPasswordGenerate.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2000-2004,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, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -107,6 +107,18 @@ CFDictionaryRef SecPasswordCopyDefaultPasswordLength(SecPasswordType type, CFErr bool SecPasswordIsPasswordWeak(CFStringRef passcode) __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +/* +@function SecPasswordIsPasswordWeak2 +@abstract Evalutes the weakness of a passcode. This function can take any type of passcode. Currently +the function evaluates passcodes with only ASCII characters +@param passcode a string of any length and type (4 digit PIN, complex passcode) +@param isSimple is to indicate whether we're evaluating a 4 digit PIN or a complex passcode +@result True if the password is weak, False if the password is strong. + */ + +bool SecPasswordIsPasswordWeak2(bool isSimple, CFStringRef passcode) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + /* @function SecPasswordGenerate. Supports generating passwords for Safari, iCloud, Personal Hotspot clients. Will also generate 4 digit pins. @@ -126,6 +138,9 @@ bool SecPasswordIsPasswordWeak(CFStringRef passcode) kSecPasswordAllowedCharactersKey / CFStringRef kSecPasswordRequiredCharactersKey / CFArrayRef of CFCharacterSetRefs + *Note: *If you would like a custom password type, file a bug in Sec Utilities requesting + a new type along with generation specifications (ex. should contain one upper case, one lower case etc) + *Note: Be sure to release the returned password when done using it. */ CF_RETURNS_RETAINED CFStringRef SecPasswordGenerate(SecPasswordType type, CFErrorRef *error, CFDictionaryRef passwordRequirements) diff --git a/sec/Security/SecPolicy.c b/Security/sec/Security/SecPolicy.c similarity index 88% rename from sec/Security/SecPolicy.c rename to Security/sec/Security/SecPolicy.c index 1fad4f91..31ba7388 100644 --- a/sec/Security/SecPolicy.c +++ b/Security/sec/Security/SecPolicy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2013 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -42,7 +42,7 @@ #include #include #include -#include +#include /******************************************************** **************** SecPolicy Constants ******************* @@ -189,8 +189,13 @@ SEC_CONST_DECL (kSecPolicyAppleTestMobileStore, "1.2.840.113635.100.1.27"); #if TARGET_OS_IPHONE SEC_CONST_DECL (kSecPolicyAppleOTAPKISigner, "1.2.840.113635.100.1.28"); SEC_CONST_DECL (kSecPolicyAppleTestOTAPKISigner, "1.2.840.113635.100.1.29"); +/* FIXME: this policy name should be deprecated and replaced with "kSecPolicyAppleIDValidationRecordSigning" */ SEC_CONST_DECL (kSecPolicyAppleIDValidationRecordSigningPolicy, "1.2.840.113625.100.1.30"); +SEC_CONST_DECL (kSecPolicyAppleSMPEncryption, "1.2.840.113625.100.1.31"); +SEC_CONST_DECL (kSecPolicyAppleTestSMPEncryption, "1.2.840.113625.100.1.32"); #endif +SEC_CONST_DECL (kSecPolicyAppleServerAuthentication, "1.2.840.113635.100.1.33"); +SEC_CONST_DECL (kSecPolicyApplePCSEscrowService, "1.2.840.113635.100.1.34"); SEC_CONST_DECL (kSecPolicyOid, "SecPolicyOid"); SEC_CONST_DECL (kSecPolicyName, "SecPolicyName"); @@ -233,6 +238,7 @@ static CFStringRef kSecPolicyOIDApplePassbook = CFSTR("ApplePassbook"); static CFStringRef kSecPolicyOIDAppleMobileStore = CFSTR("AppleMobileStore"); static CFStringRef kSecPolicyOIDAppleTestMobileStore = CFSTR("AppleTestMobileStore"); static CFStringRef kSecPolicyOIDAppleEscrowService = CFSTR("AppleEscrowService"); +static CFStringRef kSecPolicyOIDApplePCSEscrowService = CFSTR("ApplePCSEscrowService"); static CFStringRef kSecPolicyOIDAppleProfileSigner = CFSTR("AppleProfileSigner"); static CFStringRef kSecPolicyOIDAppleQAProfileSigner = CFSTR("AppleQAProfileSigner"); static CFStringRef kSecPolicyOIDAppleOTAPKIAssetSigner = CFSTR("AppleOTAPKIAssetSigner"); @@ -386,7 +392,7 @@ const UInt8 kAppleCASHA1[kSecPolicySHA1Size] = { 0xD1, 0x4A, 0xE2, 0x24, 0x52, 0xD1, 0x98, 0xDF, 0x6C, 0x60 }; -static const UInt8 kAppleTESTCASHA1[kSecPolicySHA1Size] = { +__unused static const UInt8 kAppleTESTCASHA1[kSecPolicySHA1Size] = { 0xbc, 0x30, 0x55, 0xc8, 0xc8, 0xd3, 0x48, 0x3f, 0xf4, 0x8d, 0xfe, 0x3d, 0x51, 0x75, 0x31, 0xc9, 0xf4, 0xd7, 0x4a, 0xf7 }; @@ -401,33 +407,41 @@ static const UInt8 kFactoryDeviceCASHA1[kSecPolicySHA1Size] = { 0xe2, 0x2f, 0x09, 0x8f, 0xfd, 0x6a, 0xae, 0xc0, 0x0d, 0x63 }; +#if TARGET_OS_IPHONE static const UInt8 kApplePKISettingsAuthority[kSecPolicySHA1Size] = { - 0x1D, 0x0C, 0xBA, 0xAD, 0x17, 0xFD, 0x7E, 0x9E, 0x9F, 0xF1, - 0xC9, 0xA2, 0x66, 0x79, 0x60, 0x00, 0x8B, 0xAE, 0x70, 0xB8 + 0x1D, 0x0C, 0xBA, 0xAD, 0x17, 0xFD, 0x7E, 0x9E, 0x9F, 0xF1, + 0xC9, 0xA2, 0x66, 0x79, 0x60, 0x00, 0x8B, 0xAE, 0x70, 0xB8 }; static const UInt8 kAppleTestPKISettingsAuthority[kSecPolicySHA1Size] = { - 0xDB, 0xBA, 0x25, 0x0B, 0xD8, 0x62, 0x71, 0x87, 0x54, 0x7E, + 0xDB, 0xBA, 0x25, 0x0B, 0xD8, 0x62, 0x71, 0x87, 0x54, 0x7E, 0xD7, 0xEF, 0x11, 0x94, 0x7E, 0x82, 0xE6, 0xD8, 0x1C, 0x9A }; +static const UInt8 kTestAppleRootCA_ECC_SHA1[kSecPolicySHA1Size] = { + 0x62, 0x0A, 0xED, 0x83, 0xD2, 0x97, 0x4A, 0x77, 0x56, 0x33, + 0x83, 0xBE, 0xDB, 0xF9, 0xA1, 0xBD, 0x5F, 0xFE, 0x55, 0x7B +}; + +static const UInt8 kAppleRootCA_ECC_SHA1[kSecPolicySHA1Size] = { + 0xB5, 0x2C, 0xB0, 0x2F, 0xD5, 0x67, 0xE0, 0x35, 0x9F, 0xE8, + 0xFA, 0x4D, 0x4C, 0x41, 0x03, 0x79, 0x70, 0xFE, 0x01, 0xB0 +}; +#endif + // MARK: - // MARK: SecPolicy /******************************************************** ****************** SecPolicy object ******************** ********************************************************/ -/* CFRuntime registration data. */ -static pthread_once_t kSecPolicyRegisterClass = PTHREAD_ONCE_INIT; -static CFTypeID kSecPolicyTypeID = _kCFRuntimeNotATypeID; - static void SecPolicyDestroy(CFTypeRef cf) { SecPolicyRef policy = (SecPolicyRef) cf; CFRelease(policy->_oid); CFRelease(policy->_options); } -static Boolean SecPolicyEqual(CFTypeRef cf1, CFTypeRef cf2) { +static Boolean SecPolicyCompare(CFTypeRef cf1, CFTypeRef cf2) { SecPolicyRef policy1 = (SecPolicyRef) cf1; SecPolicyRef policy2 = (SecPolicyRef) cf2; return CFEqual(policy1->_oid, policy2->_oid) && @@ -440,7 +454,7 @@ static CFHashCode SecPolicyHash(CFTypeRef cf) { return CFHash(policy->_oid) + CFHash(policy->_options); } -static CF_RETURNS_RETAINED CFStringRef SecPolicyDescribe(CFTypeRef cf) { +static CFStringRef SecPolicyCopyDescription(CFTypeRef cf) { SecPolicyRef policy = (SecPolicyRef) cf; CFMutableStringRef desc = CFStringCreateMutable(kCFAllocatorDefault, 0); CFStringRef typeStr = CFCopyTypeIDDescription(CFGetTypeID(cf)); @@ -453,27 +467,8 @@ static CF_RETURNS_RETAINED CFStringRef SecPolicyDescribe(CFTypeRef cf) { return desc; } -static void SecPolicyRegisterClass(void) { - static const CFRuntimeClass kSecPolicyClass = { - 0, /* version */ - "SecPolicy", /* class name */ - NULL, /* init */ - NULL, /* copy */ - SecPolicyDestroy, /* dealloc */ - SecPolicyEqual, /* equal */ - SecPolicyHash, /* hash */ - NULL, /* copyFormattingDesc */ - SecPolicyDescribe /* copyDebugDesc */ - }; - - kSecPolicyTypeID = _CFRuntimeRegisterClass(&kSecPolicyClass); -} - /* SecPolicy API functions. */ -CFTypeID SecPolicyGetTypeID(void) { - pthread_once(&kSecPolicyRegisterClass, SecPolicyRegisterClass); - return kSecPolicyTypeID; -} +CFGiblisWithHashFor(SecPolicy) /* AUDIT[securityd](done): oid (ok) is a caller provided string, only its cf type has been checked. @@ -559,22 +554,34 @@ SecPolicyRef SecPolicyCreateWithProperties(CFTypeRef policyIdentifier, else if (CFEqual(policyIdentifier, kSecPolicyAppleEscrowService)) { policy = SecPolicyCreateEscrowServiceSigner(); } - else if (CFEqual(policyIdentifier, kSecPolicyAppleProfileSigner)) { - policy = SecPolicyCreateConfigurationProfileSigner(); - } + else if (CFEqual(policyIdentifier, kSecPolicyApplePCSEscrowService)) { + policy = SecPolicyCreatePCSEscrowServiceSigner(); + } + else if (CFEqual(policyIdentifier, kSecPolicyAppleProfileSigner)) { + policy = SecPolicyCreateConfigurationProfileSigner(); + } else if (CFEqual(policyIdentifier, kSecPolicyAppleQAProfileSigner)) { - policy = SecPolicyCreateQAConfigurationProfileSigner(); - } -#if TARGET_OS_IPHONE + policy = SecPolicyCreateQAConfigurationProfileSigner(); + } + else if (CFEqual(policyIdentifier, kSecPolicyAppleServerAuthentication)) { + policy = SecPolicyCreateAppleSSLService(name); + } +#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR else if (CFEqual(policyIdentifier, kSecPolicyAppleOTAPKISigner)) { - policy = SecPolicyCreateOTAPKISigner(); - } + policy = SecPolicyCreateOTAPKISigner(); + } else if (CFEqual(policyIdentifier, kSecPolicyAppleTestOTAPKISigner)) { - policy = SecPolicyCreateTestOTAPKISigner(); - } + policy = SecPolicyCreateTestOTAPKISigner(); + } else if (CFEqual(policyIdentifier, kSecPolicyAppleIDValidationRecordSigningPolicy)) { policy = SecPolicyCreateAppleIDValidationRecordSigningPolicy(); } + else if (CFEqual(policyIdentifier, kSecPolicyAppleSMPEncryption)) { + policy = SecPolicyCreateAppleSMPEncryption(); + } + else if (CFEqual(policyIdentifier, kSecPolicyAppleTestSMPEncryption)) { + policy = SecPolicyCreateTestAppleSMPEncryption(); + } #endif errOut: @@ -631,28 +638,31 @@ CFDictionaryRef SecPolicyCopyProperties(SecPolicyRef policyRef) { outOid = kSecPolicyAppleMobileStore; } else if (CFEqual(oid, kSecPolicyOIDAppleTestMobileStore)) { - outOid = kSecPolicyAppleTestMobileStore; + outOid = kSecPolicyAppleTestMobileStore; } else if (CFEqual(oid, kSecPolicyOIDAppleEscrowService)) { outOid = kSecPolicyAppleEscrowService; } - else if (CFEqual(oid, kSecPolicyOIDAppleProfileSigner)) { - outOid = kSecPolicyAppleProfileSigner; - } + else if (CFEqual(oid, kSecPolicyOIDApplePCSEscrowService)) { + outOid = kSecPolicyApplePCSEscrowService; + } + else if (CFEqual(oid, kSecPolicyOIDAppleProfileSigner)) { + outOid = kSecPolicyAppleProfileSigner; + } else if (CFEqual(oid, kSecPolicyOIDAppleQAProfileSigner)) { - outOid = kSecPolicyAppleQAProfileSigner; + outOid = kSecPolicyAppleQAProfileSigner; } -#if TARGET_OS_IPHONE +#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR else if (CFEqual(oid, kSecPolicyOIDAppleOTAPKIAssetSigner)) { - outOid = kSecPolicyAppleOTAPKISigner; + outOid = kSecPolicyAppleOTAPKISigner; } else if (CFEqual(oid, kSecPolicyOIDAppleTestOTAPKIAssetSigner)) { - outOid = kSecPolicyAppleTestOTAPKISigner; + outOid = kSecPolicyAppleTestOTAPKISigner; } else if (CFEqual(oid, kSecPolicyOIDAppleIDValidationRecordSigningPolicy)) { outOid = kSecPolicyAppleIDValidationRecordSigningPolicy; } -#endif +#endif // Set kSecPolicyOid CFDictionarySetValue(properties, (const void *)kSecPolicyOid, @@ -1218,17 +1228,7 @@ SecPolicyRef SecPolicyCreateiAP(void) { CFDictionaryAddValue(options, kSecPolicyCheckSubjectCommonNamePrefix, CFSTR("IPA_")); - CFGregorianDate gd = { - 2006, - 5, - 31, - 0, - 0, - 0.0 - }; - require(tz = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, 0), errOut); - CFAbsoluteTime at = CFGregorianDateGetAbsoluteTime(gd, tz); - require(date = CFDateCreate(kCFAllocatorDefault, at), errOut); + date = CFDateCreateForGregorianZuluDay(NULL, 2006, 5, 31); CFDictionaryAddValue(options, kSecPolicyCheckNotValidBefore, date); require(result = SecPolicyCreate(kSecPolicyOIDiAP, options), @@ -1733,10 +1733,10 @@ SecPolicyRef SecPolicyCreateShoeboxCardSigner(CFStringRef cardIssuer) { return _SecPolicyCreatePassbookCardSigner(cardIssuer, nil, false); } - + static SecPolicyRef CreateMobileStoreSigner(Boolean forTest) { - + SecPolicyRef result = NULL; CFMutableDictionaryRef options = NULL; require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, @@ -1744,20 +1744,20 @@ static SecPolicyRef CreateMobileStoreSigner(Boolean forTest) &kCFTypeDictionaryValueCallBacks), errOut); SecPolicyAddBasicX509Options(options); SecPolicyAddAppleAnchorOptions(options); - + require(SecPolicyAddChainLengthOptions(options, 3), errOut); - + CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName, CFSTR("Apple System Integration 2 Certification Authority")); - + add_ku(options, kSecKeyUsageDigitalSignature); - + const DERItem* pOID = (forTest) ? &oidApplePolicyTestMobileStore : &oidApplePolicyMobileStore; - + add_certificate_policy_oid(options, pOID, NULL); - + require(result = SecPolicyCreate(kSecPolicyOIDAppleMobileStore, options), errOut); - + errOut: CFReleaseSafe(options); return result; @@ -1780,32 +1780,33 @@ CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreateEscrowServiceSigner(void) { SecPolicyRef result = NULL; CFMutableDictionaryRef options = NULL; + CFArrayRef anArray = NULL; require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); SecPolicyAddBasicX509Options(options); - + add_ku(options, kSecKeyUsageKeyEncipherment); //add_leaf_marker(options, &oidApplePolicyEscrowService); - require(SecPolicyAddChainLengthOptions(options, 2), errOut); + require(SecPolicyAddChainLengthOptions(options, 2), errOut); + - Boolean anchorAdded = false; // Get the roots by calling the SecCertificateCopyEscrowRoots - CFArrayRef anArray = SecCertificateCopyEscrowRoots(kSecCertificateProductionEscrowRoot); + anArray = SecCertificateCopyEscrowRoots(kSecCertificateProductionEscrowRoot); CFIndex numRoots = 0; if (NULL == anArray || 0 == (numRoots = CFArrayGetCount(anArray))) { goto errOut; } - + for (CFIndex iCnt = 0; iCnt < numRoots; iCnt++) - { + { SecCertificateRef aCert = (SecCertificateRef)CFArrayGetValueAtIndex(anArray, iCnt); - + if (NULL != aCert) { CFDataRef sha_data = SecCertificateGetSHA1Digest(aCert); @@ -1820,21 +1821,81 @@ CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreateEscrowServiceSigner(void) } } } - CFRelease(anArray); - + CFReleaseNull(anArray); + if (!anchorAdded) { goto errOut; } - + require(result = SecPolicyCreate(kSecPolicyOIDAppleEscrowService, options), errOut); errOut: + CFReleaseSafe(anArray); CFReleaseSafe(options); return result; } +CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreatePCSEscrowServiceSigner(void) +{ + SecPolicyRef result = NULL; + CFMutableDictionaryRef options = NULL; + CFArrayRef anArray = NULL; + require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), errOut); + + SecPolicyAddBasicX509Options(options); + + + add_ku(options, kSecKeyUsageKeyEncipherment); + + //add_leaf_marker(options, &oidApplePolicyEscrowService); + require(SecPolicyAddChainLengthOptions(options, 2), errOut); + + + Boolean anchorAdded = false; + anArray = SecCertificateCopyEscrowRoots(kSecCertificateProductionPCSEscrowRoot); + CFIndex numRoots = 0; + if (NULL == anArray || 0 == (numRoots = CFArrayGetCount(anArray))) + { + goto errOut; + } + + for (CFIndex iCnt = 0; iCnt < numRoots; iCnt++) + { + SecCertificateRef aCert = (SecCertificateRef)CFArrayGetValueAtIndex(anArray, iCnt); + + if (NULL != aCert) + { + CFDataRef sha_data = SecCertificateGetSHA1Digest(aCert); + if (NULL != sha_data) + { + const UInt8* pSHAData = CFDataGetBytePtr(sha_data); + if (NULL != pSHAData) + { + SecPolicyAddAnchorSHA1Options(options, pSHAData); + anchorAdded = true; + } + } + } + } + CFReleaseNull(anArray); + + if (!anchorAdded) + { + goto errOut; + } + + + require(result = SecPolicyCreate(kSecPolicyOIDApplePCSEscrowService, options), errOut); + +errOut: + CFReleaseSafe(anArray); + CFReleaseSafe(options); + return result; +} SecCertificateRef SecPolicyCopyEscrowRootCertificate(void) { SecCertificateRef result = NULL; @@ -1857,7 +1918,7 @@ SecPolicyRef SecPolicyCreateConfigurationProfileSigner(void) add_eku(options, &oidAppleExtendedKeyUsageProfileSigning); require(result = SecPolicyCreate(kSecPolicyOIDAppleProfileSigner, options), errOut); - + errOut: CFReleaseSafe(options); return result; @@ -1879,7 +1940,7 @@ SecPolicyRef SecPolicyCreateQAConfigurationProfileSigner(void) add_eku(options, &oidAppleExtendedKeyUsageQAProfileSigning); require(result = SecPolicyCreate(kSecPolicyOIDAppleQAProfileSigner, options), errOut); - + errOut: CFReleaseSafe(options); return result; @@ -1894,12 +1955,12 @@ SecPolicyRef SecPolicyCreateOTAPKISigner(void) &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); SecPolicyAddBasicX509Options(options); - + SecPolicyAddAnchorSHA1Options(options, kApplePKISettingsAuthority); require(SecPolicyAddChainLengthOptions(options, 2), errOut); - + require(result = SecPolicyCreate(kSecPolicyOIDAppleOTAPKIAssetSigner, options), errOut); - + errOut: CFReleaseSafe(options); return result; @@ -1915,17 +1976,91 @@ SecPolicyRef SecPolicyCreateTestOTAPKISigner(void) &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), errOut); SecPolicyAddBasicX509Options(options); - + SecPolicyAddAnchorSHA1Options(options, kAppleTestPKISettingsAuthority); require(SecPolicyAddChainLengthOptions(options, 2), errOut); - + require(result = SecPolicyCreate(kSecPolicyOIDAppleTestOTAPKIAssetSigner, options), errOut); - + errOut: CFReleaseSafe(options); return result; } +/*! + @function SecPolicyCreateAppleSMPEncryption + @abstract Check for intermediate certificate 'Apple System Integration CA - G3' by name, + and root certificate 'Apple Root CA - G3' by hash. + Leaf cert must have Key Encipherment usage. + Leaf cert must have Apple SMP Encryption marker OID (1.2.840.113635.100.6.30). + Intermediate must have marker OID (1.2.840.113635.100.6.2.13). + */ +SecPolicyRef SecPolicyCreateAppleSMPEncryption(void) +{ + SecPolicyRef result = NULL; + CFMutableDictionaryRef options = NULL; + require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), errOut); + SecPolicyAddBasicCertOptions(options); + + SecPolicyAddAnchorSHA1Options(options, kAppleRootCA_ECC_SHA1); + require(SecPolicyAddChainLengthOptions(options, 3), errOut); + + CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName, + CFSTR("Apple System Integration CA - G3")); + + // Check that leaf has extension with "Apple SMP Encryption" oid (1.2.840.113635.100.6.30) + add_leaf_marker(options, &oidAppleCertExtAppleSMPEncryption); + + // Check that intermediate has extension (1.2.840.113635.100.6.2.13) + add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleSystemIntgG3); + + add_ku(options, kSecKeyUsageKeyEncipherment); + + // Ensure that revocation is checked (OCSP) + CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse); + + require(result = SecPolicyCreate(kSecPolicyAppleSMPEncryption, options), errOut); + +errOut: + CFReleaseSafe(options); + return result; +} + +/*! + @function SecPolicyCreateTestAppleSMPEncryption + @abstract Check for intermediate certificate 'Test Apple System Integration CA - ECC' by name, + and root certificate 'Test Apple Root CA - ECC' by hash. + Leaf cert must have Key Encipherment usage. Other checks TBD. + */ +SecPolicyRef SecPolicyCreateTestAppleSMPEncryption(void) +{ + SecPolicyRef result = NULL; + CFMutableDictionaryRef options = NULL; + require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), errOut); + SecPolicyAddBasicCertOptions(options); + + SecPolicyAddAnchorSHA1Options(options, kTestAppleRootCA_ECC_SHA1); + require(SecPolicyAddChainLengthOptions(options, 3), errOut); + + CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName, + CFSTR("Test Apple System Integration CA - ECC")); + + add_ku(options, kSecKeyUsageKeyEncipherment); + + // Ensure that revocation is checked (OCSP) + CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse); + + require(result = SecPolicyCreate(kSecPolicyAppleTestSMPEncryption, options), errOut); + +errOut: + CFReleaseSafe(options); + return result; +} + SecPolicyRef SecPolicyCreateAppleIDValidationRecordSigningPolicy(void) { @@ -1944,9 +2079,9 @@ SecPolicyRef SecPolicyCreateAppleIDValidationRecordSigningPolicy(void) // Check for an extension with " Apple ID Validation Record Signing" oid (1.2.840.113635.100.6.25) add_leaf_marker(options, &oidAppleCertExtensionAppleIDRecordValidationSigning); - // and validate that intermediate has extension - // Application Integration Intermediate Certificate (1.2.840.113635.100.6.2.3) - // and also validate that intermediate has extension + // and validate that intermediate has extension + // Application Integration Intermediate Certificate (1.2.840.113635.100.6.2.3) + // and also validate that intermediate has extension // System Integration 2 Intermediate Certificate (1.2.840.113635.100.6.2.10) add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleID); add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleSystemIntg2); @@ -1955,10 +2090,71 @@ SecPolicyRef SecPolicyCreateAppleIDValidationRecordSigningPolicy(void) CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse); require(result = SecPolicyCreate(kSecPolicyOIDAppleIDValidationRecordSigningPolicy, options), errOut); - + errOut: CFReleaseSafe(options); return result; } +/*! + @function SecPolicyCreateAppleIDSService + @abstract Ensure we're appropriately pinned to the IDS service (SSL + Apple restrictions) + */ +SecPolicyRef SecPolicyCreateAppleIDSService(CFStringRef hostname) +{ + return SecPolicyCreateSSL(true, hostname); +} + +/*! + @function SecPolicyCreateApplePushService + @abstract Ensure we're appropriately pinned to the Push service (SSL + Apple restrictions) + */ +SecPolicyRef SecPolicyCreateApplePushService(CFStringRef hostname) +{ + return SecPolicyCreateSSL(true, hostname); +} + +/*! + @function SecPolicyCreateAppleMMCSService + @abstract Ensure we're appropriately pinned to the IDS service (SSL + Apple restrictions) + */ +SecPolicyRef SecPolicyCreateAppleMMCSService(CFStringRef hostname) +{ + return SecPolicyCreateSSL(true, hostname); +} + +/*! + @function SecPolicyCreateAppleSSLService + @abstract Ensure we're appropriately pinned to an Apple server (SSL + Apple restrictions) + */ +SecPolicyRef SecPolicyCreateAppleSSLService(CFStringRef hostname) +{ + // SSL server, pinned to an Apple intermediate + SecPolicyRef policy = SecPolicyCreateSSL(true, hostname); + CFMutableDictionaryRef options = NULL; + require(policy, errOut); + + // change options for SSL policy evaluation + require((options=(CFMutableDictionaryRef)policy->_options) != NULL, errOut); + + // Apple CA anchored + require(SecPolicyAddAppleAnchorOptions(options), errOut); + + // Check leaf for Apple Server Authentication marker oid (1.2.840.113635.100.6.27.1) + add_leaf_marker(options, &oidAppleCertExtAppleServerAuthentication); + + // Check intermediate for Apple Server Authentication intermediate marker (1.2.840.113635.100.6.2.12) + add_oid(options, kSecPolicyCheckIntermediateMarkerOid, &oidAppleIntmMarkerAppleServerAuthentication); + + // Ensure that revocation is checked (OCSP only) + CFDictionaryAddValue(options, kSecPolicyCheckRevocation, kCFBooleanFalse); + + return policy; + +errOut: + CFReleaseSafe(options); + CFReleaseSafe(policy); + return NULL; +} + #endif // TARGET_OS_IPHONE diff --git a/Security/sec/Security/SecPolicy.h b/Security/sec/Security/SecPolicy.h new file mode 100644 index 00000000..e7cdf458 --- /dev/null +++ b/Security/sec/Security/SecPolicy.h @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2002-2010,2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecPolicy + The functions provided in SecPolicy.h provide an interface to various + X.509 certificate trust policies. +*/ + +#ifndef _SECURITY_SECPOLICY_H_ +#define _SECURITY_SECPOLICY_H_ + +#include +#include +#include + +__BEGIN_DECLS + +/*! + @enum Policy Constants + @discussion Predefined constants used to specify a policy. + @constant kSecPolicyAppleX509Basic + @constant kSecPolicyAppleSSL + @constant kSecPolicyAppleSMIME + @constant kSecPolicyAppleEAP + @constant kSecPolicyAppleIPsec + @constant kSecPolicyApplePKINITClient + @constant kSecPolicyApplePKINITServer + @constant kSecPolicyAppleCodeSigning + @constant kSecPolicyMacAppStoreReceipt + @constant kSecPolicyAppleIDValidation + @constant kSecPolicyAppleTimeStamping + @constant kSecPolicyAppleRevocation +*/ +extern CFTypeRef kSecPolicyAppleX509Basic + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleSSL + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleSMIME + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleEAP + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleIPsec + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPolicyApplePKINITClient + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyApplePKINITServer + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyAppleCodeSigning + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPolicyMacAppStoreReceipt + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyAppleIDValidation + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleTimeStamping + __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleRevocation + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + +/*! + @enum Policy Value Constants + @abstract Predefined property key constants used to get or set values in + a dictionary for a policy instance. + @discussion + All policies will have the following read-only value: + kSecPolicyOid (the policy object identifier) + + Additional policy values which your code can optionally set: + kSecPolicyName (name which must be matched) + kSecPolicyClient (evaluate for client, rather than server) + kSecPolicyRevocationFlags (only valid for a revocation policy) + + @constant kSecPolicyOid Specifies the policy OID (value is a CFStringRef) + @constant kSecPolicyName Specifies a CFStringRef (or CFArrayRef of same) + containing a name which must be matched in the certificate to satisfy + this policy. For SSL/TLS, EAP, and IPSec policies, this specifies the + server name which must match the common name of the certificate. + For S/MIME, this specifies the RFC822 email address. + @constant kSecPolicyClient Specifies a CFBooleanRef value that indicates + this evaluation should be for a client certificate. If not set (or + false), the policy evaluates the certificate as a server certificate. + @constant kSecPolicyRevocationFlags Specifies a CFNumberRef that holds a + kCFNumberCFIndexType bitmask value. See "Revocation Policy Constants" + for a description of individual bits in this value. + */ +extern CFTypeRef kSecPolicyOid + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPolicyName + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPolicyClient + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPolicyRevocationFlags + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + + +/*! + @function SecPolicyGetTypeID + @abstract Returns the type identifier of SecPolicy instances. + @result The CFTypeID of SecPolicy instances. +*/ +CFTypeID SecPolicyGetTypeID(void) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +/*! + @function SecPolicyCopyProperties + @abstract Returns a dictionary of this policy's properties. + @param policyRef A policy reference. + @result A properties dictionary. See "Policy Value Constants" for a list + of currently defined property keys. It is the caller's responsibility to + CFRelease this reference when it is no longer needed. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function returns the properties for a policy, as set by the + policy's construction function or by a prior call to SecPolicySetProperties. +*/ +CFDictionaryRef SecPolicyCopyProperties(SecPolicyRef policyRef) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); + +/*! + @function SecPolicyCreateBasicX509 + @abstract Returns a policy object for the default X.509 policy. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. +*/ +SecPolicyRef SecPolicyCreateBasicX509(void) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @function SecPolicyCreateSSL + @abstract Returns a policy object for evaluating SSL certificate chains. + @param server Passing true for this parameter creates a policy for SSL + server certificates. + @param hostname (Optional) If present, the policy will require the specified + hostname to match the hostname in the leaf certificate. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. +*/ +SecPolicyRef SecPolicyCreateSSL(Boolean server, CFStringRef hostname) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @enum Revocation Policy Constants + @abstract Predefined constants which allow you to specify how revocation + checking will be performed for a trust evaluation. + @constant kSecRevocationOCSPMethod If this flag is set, perform revocation + checking using OCSP (Online Certificate Status Protocol). + @constant kSecRevocationCRLMethod If this flag is set, perform revocation + checking using the CRL (Certificate Revocation List) method. + @constant kSecRevocationPreferCRL If this flag is set, then CRL revocation + checking will be preferred over OCSP (by default, OCSP is preferred.) + Note that this flag only matters if both revocation methods are specified. + @constant kSecRevocationRequirePositiveResponse If this flag is set, then + the policy will fail unless a verified positive response is obtained. If + the flag is not set, revocation checking is done on a "best attempt" basis, + where failure to reach the server is not considered fatal. + @constant kSecRevocationNetworkAccessDisabled If this flag is set, then + no network access is performed; only locally cached replies are consulted. + @constant kSecRevocationUseAnyAvailableMethod Specifies that either + OCSP or CRL may be used, depending on the method(s) specified in the + certificate and the value of kSecRevocationPreferCRL. + */ +enum { + kSecRevocationOCSPMethod = (1 << 0), + kSecRevocationCRLMethod = (1 << 1), + kSecRevocationPreferCRL = (1 << 2), + kSecRevocationRequirePositiveResponse = (1 << 3), + kSecRevocationNetworkAccessDisabled = (1 << 4), + kSecRevocationUseAnyAvailableMethod = (kSecRevocationOCSPMethod | + kSecRevocationCRLMethod) +}; + +/*! + @function SecPolicyCreateRevocation + @abstract Returns a policy object for checking revocation of certificates. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + @param revocationFlags Flags to specify revocation checking options. + @discussion Use this function to create a revocation policy with behavior + specified by revocationFlags. See the "Revocation Policy Constants" section + for a description of these flags. Note: it is usually not necessary to + create a revocation policy yourself unless you wish to override default + system behavior (e.g. to force a particular method, or to disable + revocation checking entirely.) +*/ +SecPolicyRef SecPolicyCreateRevocation(CFOptionFlags revocationFlags) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + +/*! + @function SecPolicyCreateWithProperties + @abstract Returns a policy object based on an object identifier for the + policy type. See the "Policy Constants" section for a list of defined + policy object identifiers. + @param policyIdentifier The identifier for the desired policy type. + @param properties (Optional) A properties dictionary. See "Policy Value + Constants" for a list of currently defined property keys. + @result The returned policy reference, or NULL if the policy could not be + created. +*/ +SecPolicyRef SecPolicyCreateWithProperties(CFTypeRef policyIdentifier, + CFDictionaryRef properties) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + + +/* + * Legacy functions (OS X only) + */ +#if TARGET_OS_MAC && !TARGET_OS_IPHONE +#include + +/*! + @enum Policy Value Constants (OS X) + @discussion Predefined property key constants used to get or set values in + a dictionary for a policy instance. + + Some policy values may specify CFBooleanRef key usage constraints: + kSecPolicyKU_DigitalSignature + kSecPolicyKU_NonRepudiation + kSecPolicyKU_KeyEncipherment + kSecPolicyKU_DataEncipherment + kSecPolicyKU_KeyAgreement + kSecPolicyKU_KeyCertSign + kSecPolicyKU_CRLSign + kSecPolicyKU_EncipherOnly + kSecPolicyKU_DecipherOnly + + kSecPolicyKU policy values define certificate-level key purposes, + in contrast to the key-level definitions in SecItem.h + + For example, a key in a certificate might be acceptable to use for + signing a CRL, but not for signing another certificate. In either + case, this key would have the ability to sign (i.e. kSecAttrCanSign + is true), but may only sign for specific purposes allowed by these + policy constants. Similarly, a public key might have the capability + to perform encryption or decryption, but the certificate in which it + resides might have a decipher-only certificate policy. + + These constants correspond to values defined in RFC 5280, section + 4.2.1.3 (Key Usage) which define the purpose of a key contained in a + certificate, in contrast to section 4.1.2.7 which define the uses that + a key is capable of. + + Note: these constants are not available on iOS. Your code should + avoid direct reliance on these values for making policy decisions + and use higher level policies where possible. + + @constant kSecPolicyKU_DigitalSignature Specifies that the certificate must + have a key usage that allows it to be used for signing. + @constant kSecPolicyKU_NonRepudiation Specifies that the certificate must + have a key usage that allows it to be used for non-repudiation. + @constant kSecPolicyKU_KeyEncipherment Specifies that the certificate must + have a key usage that allows it to be used for key encipherment. + @constant kSecPolicyKU_DataEncipherment Specifies that the certificate must + have a key usage that allows it to be used for data encipherment. + @constant kSecPolicyKU_KeyAgreement Specifies that the certificate must + have a key usage that allows it to be used for key agreement. + @constant kSecPolicyKU_KeyCertSign Specifies that the certificate must + have a key usage that allows it to be used for signing certificates. + @constant kSecPolicyKU_CRLSign Specifies that the certificate must + have a key usage that allows it to be used for signing CRLs. + @constant kSecPolicyKU_EncipherOnly Specifies that the certificate must + have a key usage that permits it to be used for encryption only. + @constant kSecPolicyKU_DecipherOnly Specifies that the certificate must + have a key usage that permits it to be used for decryption only. + */ +extern CFTypeRef kSecPolicyKU_DigitalSignature + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyKU_NonRepudiation + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyKU_KeyEncipherment + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyKU_DataEncipherment + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyKU_KeyAgreement + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyKU_KeyCertSign + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyKU_CRLSign + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyKU_EncipherOnly + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern CFTypeRef kSecPolicyKU_DecipherOnly + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @function SecPolicyCreateWithOID + @abstract Returns a policy object based on an object identifier for the + policy type. See the "Policy Constants" section for a list of defined + policy object identifiers. + @param policyOID The OID of the desired policy. + @result The returned policy reference, or NULL if the policy could not be + created. + @discussion This function is deprecated in Mac OS X 10.9 and later; + use SecPolicyCreateWithProperties (or a more specific policy creation + function) instead. +*/ +SecPolicyRef SecPolicyCreateWithOID(CFTypeRef policyOID) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecPolicyGetOID + @abstract Returns a policy's object identifier. + @param policyRef A policy reference. + @param oid On return, a pointer to the policy's object identifier. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in Mac OS X 10.7 and later; + use SecPolicyCopyProperties instead. +*/ +OSStatus SecPolicyGetOID(SecPolicyRef policyRef, CSSM_OID *oid) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecPolicyGetValue + @abstract Returns a policy's value. + @param policyRef A policy reference. + @param value On return, a pointer to the policy's value. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in Mac OS X 10.7 and later; + use SecPolicyCopyProperties instead. +*/ +OSStatus SecPolicyGetValue(SecPolicyRef policyRef, CSSM_DATA *value) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecPolicySetValue + @abstract Sets a policy's value. + @param policyRef A policy reference. + @param value The value to be set into the policy object, replacing any + previous value. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in Mac OS X 10.7 and later. Policy + instances should be considered read-only; in cases where your code would + consider changing properties of a policy, it should instead create a new + policy instance with the desired properties. +*/ +OSStatus SecPolicySetValue(SecPolicyRef policyRef, const CSSM_DATA *value) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecPolicySetProperties + @abstract Sets a policy's properties. + @param policyRef A policy reference. + @param properties A properties dictionary. See "Policy Value Constants" + for a list of currently defined property keys. This dictionary replaces the + policy's existing properties, if any. Note that the policy OID (specified + by kSecPolicyOid) is a read-only property of the policy and cannot be set. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in Mac OS X 10.9 and later. Policy + instances should be considered read-only; in cases where your code would + consider changing properties of a policy, it should instead create a new + policy instance with the desired properties. +*/ +OSStatus SecPolicySetProperties(SecPolicyRef policyRef, + CFDictionaryRef properties) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecPolicyGetTPHandle + @abstract Returns the CSSM trust policy handle for the given policy. + @param policyRef A policy reference. + @param tpHandle On return, a pointer to a value of type CSSM_TP_HANDLE. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in Mac OS X 10.7 and later. +*/ +OSStatus SecPolicyGetTPHandle(SecPolicyRef policyRef, CSSM_TP_HANDLE *tpHandle) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + +#endif /* TARGET_OS_MAC && !TARGET_OS_IPHONE */ + + +__END_DECLS + +#endif /* !_SECURITY_SECPOLICY_H_ */ diff --git a/Security/sec/Security/SecPolicyCerts.h b/Security/sec/Security/SecPolicyCerts.h new file mode 100644 index 00000000..450381a0 --- /dev/null +++ b/Security/sec/Security/SecPolicyCerts.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecPolicyCerts + Provides certificates used by policies for specific Apple services. + These certificates allow a complete chain to be built in cases where + the caller is unable to provide them; no inherent trust is granted + by adding certificates to this file. +*/ + +#ifndef _SECURITY_SECPOLICYCERTS_H_ +#define _SECURITY_SECPOLICYCERTS_H_ + +/* Test Apple Root CA - ECC */ +static const UInt8 _SEC_TestAppleRootCAECC[]={ + 0x30,0x82,0x02,0x27,0x30,0x82,0x01,0xCD,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x59, + 0xD1,0xEC,0x10,0x92,0x41,0xC7,0xC4,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D, + 0x04,0x03,0x02,0x30,0x67,0x31,0x21,0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x0C,0x18, + 0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20, + 0x43,0x41,0x20,0x2D,0x20,0x45,0x43,0x43,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,0x34,0x30,0x31,0x33,0x31,0x32,0x31,0x34,0x36,0x34,0x36,0x5A,0x17,0x0D,0x33, + 0x34,0x30,0x31,0x32,0x36,0x32,0x31,0x34,0x36,0x34,0x36,0x5A,0x30,0x67,0x31,0x21, + 0x30,0x1F,0x06,0x03,0x55,0x04,0x03,0x0C,0x18,0x54,0x65,0x73,0x74,0x20,0x41,0x70, + 0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x20,0x2D,0x20,0x45,0x43, + 0x43,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,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D, + 0x02,0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00,0x04, + 0x7B,0x38,0x10,0xD0,0x0A,0xA3,0x1B,0x7C,0x1D,0x24,0xFB,0x39,0xD6,0x6B,0x1C,0x0A, + 0x97,0x48,0x30,0xFF,0x4C,0x70,0x49,0x3D,0x21,0x66,0x4F,0xF5,0x89,0x00,0xAF,0x93, + 0xEF,0x74,0x9A,0xE8,0x4C,0x27,0x3D,0xBE,0x95,0x50,0x52,0x3D,0x53,0x90,0xF3,0x32, + 0xAB,0x83,0xB6,0x5E,0x73,0xC8,0xE7,0x17,0x8B,0x18,0x09,0x93,0x9F,0x97,0xD5,0x16, + 0xA3,0x63,0x30,0x61,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xD2, + 0x47,0xE2,0xC5,0x34,0x71,0xC6,0x10,0x8D,0x93,0xEE,0x04,0x43,0x1F,0xE1,0x1B,0x0F, + 0xE1,0xCD,0x11,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,0xD2,0x47,0xE2,0xC5,0x34,0x71,0xC6,0x10,0x8D,0x93,0xEE,0x04,0x43,0x1F,0xE1, + 0x1B,0x0F,0xE1,0xCD,0x11,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04, + 0x04,0x03,0x02,0x01,0x06,0x30,0x0A,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03, + 0x02,0x03,0x48,0x00,0x30,0x45,0x02,0x21,0x00,0xDC,0x06,0x2B,0x72,0x87,0x20,0xEC, + 0xF7,0xDC,0xC8,0xF2,0xF8,0x89,0x0A,0x57,0x63,0x9A,0x92,0x4A,0x84,0x6E,0xDD,0x17, + 0x50,0xEE,0x6F,0x01,0x4C,0xA1,0xA0,0x74,0xD1,0x02,0x20,0x1F,0x35,0x7A,0xB5,0x0B, + 0x79,0x80,0xD4,0x9C,0x9F,0x31,0xDC,0x36,0x1C,0xC6,0xFD,0x65,0x72,0x40,0x67,0xBA, + 0xFC,0x6F,0x59,0x5E,0xEF,0xEA,0x5E,0x87,0xAC,0x30,0x0D +}; + +#endif /* !_SECURITY_SECPOLICYCERTS_H_ */ diff --git a/sec/Security/SecPolicyInternal.h b/Security/sec/Security/SecPolicyInternal.h similarity index 98% rename from sec/Security/SecPolicyInternal.h rename to Security/sec/Security/SecPolicyInternal.h index 44418aea..ebe7258f 100644 --- a/sec/Security/SecPolicyInternal.h +++ b/Security/sec/Security/SecPolicyInternal.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2008-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/Security/sec/Security/SecPolicyPriv.h b/Security/sec/Security/SecPolicyPriv.h new file mode 100644 index 00000000..e4afcf4d --- /dev/null +++ b/Security/sec/Security/SecPolicyPriv.h @@ -0,0 +1,439 @@ +/* + * Copyright (c) 2007-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecPolicyPriv + The functions provided in SecPolicyPriv provide an interface to various + X.509 certificate trust policies. +*/ + +#ifndef _SECURITY_SECPOLICYPRIV_H_ +#define _SECURITY_SECPOLICYPRIV_H_ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/*! + @enum Policy Constants (Private) + @discussion Predefined constants used to specify a policy. + @constant kSecPolicyApplePassbookSigning + @constant kSecPolicyAppleMobileStore + @constant kSecPolicyAppleTestMobileStore + @constant kSecPolicyAppleEscrowService + @constant kSecPolicyAppleProfileSigner + @constant kSecPolicyAppleQAProfileSigner + @constant kSecPolicyAppleServerAuthentication + @constant kSecPolicyAppleOTAPKISigner + @constant kSecPolicyAppleTestOTAPKISigner + @constant kSecPolicyAppleIDValidationRecordSigning + @constant kSecPolicyAppleSMPEncryption + @constant kSecPolicyAppleTestSMPEncryption + @constant kSecPolicyApplePCSEscrowService + +*/ +extern CFTypeRef kSecPolicyApplePassbookSigning + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleMobileStore + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleTestMobileStore + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleEscrowService + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleProfileSigner + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleQAProfileSigner + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleServerAuthentication + __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); +#if TARGET_OS_IPHONE +extern CFTypeRef kSecPolicyAppleOTAPKISigner + __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleTestOTAPKISigner + __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleIDValidationRecordSigningPolicy + __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_7_0); +extern CFTypeRef kSecPolicyAppleSMPEncryption + __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0); +extern CFTypeRef kSecPolicyAppleTestSMPEncryption + __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0); +#endif +extern CFTypeRef kSecPolicyApplePCSEscrowService + __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_7_0); + + +/*! + @enum Policy Value Constants + @abstract Predefined property key constants used to get or set values in + a dictionary for a policy instance. + @constant kSecPolicyTeamIdentifier Specifies a CFStringRef containing a + team identifier which must be matched in the certificate to satisfy + this policy. For the Passbook signing policy, this string must match + the Organizational Unit field of the certificate subject. +*/ +extern CFTypeRef kSecPolicyTeamIdentifier + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + +/*! + @function SecPolicyCreateiPhoneActivation + @abstract Returns a policy object for verifying iPhone Activation + certificate chains. + @discussion This policy is like the Basic X.509 policy with the additional + requirements that the chain must contain exactly three certificates, the + anchor is the Apple Inc. CA, and the subject of the first intermediate + certificate has "Apple iPhone Certification Authority" as its only + Common Name entry. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. +*/ +SecPolicyRef SecPolicyCreateiPhoneActivation(void); + +/*! + @function SecPolicyCreateiPhoneDeviceCertificate + @abstract Returns a policy object for verifying iPhone Device certificate + chains. + @discussion This policy is like the Basic X.509 policy with the additional + requirements that the chain must contain exactly four certificates, the + anchor is the Apple Inc. CA, and the subject of the first intermediate + certificate has "Apple iPhone Device CA" as its only Common Name entry. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. +*/ +SecPolicyRef SecPolicyCreateiPhoneDeviceCertificate(void); + +/*! + @function SecPolicyCreateFactoryDeviceCertificate + @abstract Returns a policy object for verifying Factory Device certificate + chains. + @discussion This policy is like the Basic X.509 policy with the additional + requirements that the chain must be anchored to the factory device certificate + issuer. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. +*/ +SecPolicyRef SecPolicyCreateFactoryDeviceCertificate(void); + +/*! + @function SecPolicyCreateiAP + @abstract Returns a policy object for verifying iAP certificate chains. + @discussion This policy is like the Basic X.509 policy with these + additional requirements: + * The leaf's NotValidBefore should be greater than 5/31/06 midnight GMT. + * The Common Name of the leaf begins with the characters "IPA_". + * No validity checking is performed for any of the certificates. + The intended use of this policy is that the caller pass in the + intermediates for iAP1 and iAP2 to SecTrustSetAnchorCertificates(). + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. +*/ +SecPolicyRef SecPolicyCreateiAP(void); + +/*! + @function SecPolicyCreateiTunesStoreURLBag + @abstract Returns a policy object for verifying iTunes Store URL bag + certificates. + @discussion This policy is like the Basic X.509 policy with these + additional requirements: + * The leaf's Organization is Apple Inc. + * The Common Name of the leaf is "iTunes Store URL Bag". + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. +*/ +SecPolicyRef SecPolicyCreateiTunesStoreURLBag(void); + +/*! + @function SecPolicyCreateEAP + @abstract Returns a policy object for verifying for 802.1x/EAP certificates. + @param server Passing true for this parameter create a policy for EAP + server certificates. + @param trustedServerNames Optional; if present, the hostname in the leaf + certificate must be in the trustedServerNames list. Note that contrary + to all other policies the trustedServerNames list entries can have wildcards + whilst the certificate cannot. This matches the existing deployments. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. +*/ +SecPolicyRef SecPolicyCreateEAP(Boolean server, CFArrayRef trustedServerNames); + +/*! + @function SecPolicyCreateIPSec + @abstract Returns a policy object for evaluating IPSec certificate chains. + @param server Passing true for this parameter create a policy for IPSec + server certificates. + @param hostname Optional; if present, the policy will require the specified + hostname or ip address to match the hostname in the leaf certificate. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. +*/ +SecPolicyRef SecPolicyCreateIPSec(Boolean server, CFStringRef hostname); + +/*! + @function SecPolicyCreateiPhoneApplicationSigning + @abstract Returns a policy object for evaluating signed application + signatures. This is for apps signed directly by the app store. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. +*/ +SecPolicyRef SecPolicyCreateiPhoneApplicationSigning(void); + +/*! + @function SecPolicyCreateiPhoneProfileApplicationSigning + @abstract Returns a policy object for evaluating signed application + signatures. This is meant for certificates inside a UPP or regular + profile. Currently it only checks for experation of the leaf and + revocation status. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. +*/ +SecPolicyRef SecPolicyCreateiPhoneProfileApplicationSigning(void); + +/*! + @function SecPolicyCreateiPhoneProvisioningProfileSigning + @abstract Returns a policy object for evaluating provisioning profile signatures. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. +*/ +SecPolicyRef SecPolicyCreateiPhoneProvisioningProfileSigning(void); + +/*! + @function SecPolicyCreateOCSPSigner + @abstract Returns a policy object for evaluating ocsp response signers. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. +*/ +SecPolicyRef SecPolicyCreateOCSPSigner(void); + + +enum { + kSecSignSMIMEUsage = (1 << 0), + kSecKeyEncryptSMIMEUsage = (1 << 1), + kSecDataEncryptSMIMEUsage = (1 << 2), + kSecKeyExchangeDecryptSMIMEUsage = (1 << 3), + kSecKeyExchangeEncryptSMIMEUsage = (1 << 4), + kSecKeyExchangeBothSMIMEUsage = (1 << 5), + kSecAnyEncryptSMIME = kSecKeyEncryptSMIMEUsage | kSecDataEncryptSMIMEUsage | + kSecKeyExchangeDecryptSMIMEUsage | kSecKeyExchangeEncryptSMIMEUsage +}; + +/*! + @function SecPolicyCreateSMIME + @abstract Returns a policy object for evaluating S/MIME certificate chains. + @param smimeUsage Pass the bitwise or of one or more kSecXXXSMIMEUsage + flags, to indicated the intended usage of this certificate. A certificate which allows + @param email Optional; if present, the policy will require the specified + email to match the email in the leaf certificate. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. +*/ +SecPolicyRef SecPolicyCreateSMIME(CFIndex smimeUsage, CFStringRef email); + +/*! + @function SecPolicyCreateCodeSigning + @abstract Returns a policy object for evaluating code signing certificate chains. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. +*/ +SecPolicyRef SecPolicyCreateCodeSigning(void); + +/*! + @function SecPolicyCreateLockdownPairing + @abstract basic x509 policy for checking lockdown pairing certificate chains. + It explicitly allows for empty subjects +*/ +SecPolicyRef SecPolicyCreateLockdownPairing(void); + +/*! + @function SecPolicyCreateURLBag + @abstract check for private CA, eku codesigning and certificate policy that + pertains to signing of URL bags. + */ +SecPolicyRef SecPolicyCreateURLBag(void); + +/*! + @function SecPolicyCreateOTATasking + @abstract check for 3 long chain through Apple Certification Policy with common name + "OTA Task Signing". + */ +SecPolicyRef SecPolicyCreateOTATasking(void); + +/*! + @function SecPolicyCreateMobileAsset + @abstract check for 3 long chain through Apple Certification Policy with common name + "Asset Manifest Signing". + */ +SecPolicyRef SecPolicyCreateMobileAsset(void); + +/*! + @function SecPolicyCreateAppleIDAuthorityPolicy + @abstract check for an Apple ID identity per marker in the leaf and marker in the intermediate, rooted in the Apple CA. + */ +SecPolicyRef SecPolicyCreateAppleIDAuthorityPolicy(void); + +/*! + @function SecPolicyCreatePassbookCardSigner + @abstract check rooted in the Apple CA, eku shoebox, marker shoebox and name matching + @param cardIssuer Required; must match name in marker extension. + @param teamIdentifier Optional; if present, the policy will require the specified + team ID to match the organizationalUnit field in the leaf certificate's subject. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +SecPolicyRef SecPolicyCreatePassbookCardSigner(CFStringRef cardIssuer, + CFStringRef teamIdentifier); + +/*! + @function SecPolicyCreateShoeboxCardSigner + @abstract Deprecated; use SecPolicyCreatePassbookCardSigner instead + */ +SecPolicyRef SecPolicyCreateShoeboxCardSigner(CFStringRef cardIssuer); + +/*! + @function SecPolicyCreateMobileStoreSigner + @abstract Check for key usage of digital signature, + check for 3 long chain through Apple System Integration 2 Certification Authority + with a certificate policy OID of 1.2.840.113635.100.5.12 that roots to the + Apple root + */ +SecPolicyRef SecPolicyCreateMobileStoreSigner(void); + +/*! + @function SecPolicyCreateTestMobileStoreSigner + @abstract Check for key usage of digital signature, + check for 3 long chain through Apple System Integration 2 Certification Authority + with a certificate policy OID of 1.2.840.113635.100.5.12.1 that roots to the + Apple root + */ +SecPolicyRef SecPolicyCreateTestMobileStoreSigner(void); + +/*! + @function SecPolicyCreateEscrowServiceSigner + @abstract Check for key usage of digital signature, has a leaf marker OID of + 1.2.840.113635.100.6.23.1 and roots to the production Escrow Root + */ +SecPolicyRef SecPolicyCreateEscrowServiceSigner(void); + +/*! + @function SecPolicyCreatePCSEscrowServiceSigner + @abstract Check for key usage of digital signature, has a leaf marker OID of + 1.2.840.113635.100.6.23.1 and roots to the production PCS Escrow Root + */ +SecPolicyRef SecPolicyCreatePCSEscrowServiceSigner(void); + +/*! + @function SecPolicyCopyEscrowRootCertificate + @abstract Return back the Root certificate for the Escrow service +*/ +SecCertificateRef SecPolicyCopyEscrowRootCertificate(void); + +/*! + @function SecPolicyCreateConfigurationProfileSigner + @abstract Check for key usage of digital signature, has a EKU OID of + 1.2.840.113635.100.4.16 and + roots to Apple Application Integration 2 Certification Authority +*/ +SecPolicyRef SecPolicyCreateConfigurationProfileSigner(void); + +/*! + @function SecPolicyCreateQAConfigurationProfileSigner + @abstract Check for key usage of digital signature, has a EKU OID of + 1.2.840.113635.100.4.17 and + roots to Apple Application Integration 2 Certification Authority +*/ +SecPolicyRef SecPolicyCreateQAConfigurationProfileSigner(void); + +#if TARGET_OS_IPHONE +/*! + @function SecPolicyCreateOTAPKISigner + @abstract Check for key usage of digital signature, and + roots to Apple PKI Settings Root Certification Authority +*/ +SecPolicyRef SecPolicyCreateOTAPKISigner(void); + +/*! + @function SecPolicyCreateTestOTAPKISigner + @abstract Check for key usage of digital signature, and + roots to Apple PKI Settings Root - TESTING +*/ +SecPolicyRef SecPolicyCreateTestOTAPKISigner(void); + +/*! + @function SecPolicyCreateAppleIDValidationRecordSigningPolicy + @abstract Check for leaf certificate contains the + appleIDValidationRecordSigning (1 2 840 113635 100 6 25), and + intermediate certificate contains + appleCertificateExtensionApplicationIntegrationIntermediate + (1 2 840 113635 100 6 2 3) and + appleCertificateExtensionSystemIntegration2Intermediate + (1 2 840 113635 100 6 2 10) and roots to the Apple root +*/ +SecPolicyRef SecPolicyCreateAppleIDValidationRecordSigningPolicy(void); + +/*! + @function SecPolicyCreateAppleSMPEncryption + @abstract Check for intermediate certificate 'Apple System Integration CA - ECC' by name, + and root certificate 'Apple Root CA - ECC' by hash. + Leaf cert must have Key Encipherment usage. Other checks TBD. + */ +SecPolicyRef SecPolicyCreateAppleSMPEncryption(void); + +/*! + @function SecPolicyCreateTestAppleSMPEncryption + @abstract Check for intermediate certificate 'Test Apple System Integration CA - ECC' by name, + and root certificate 'Test Apple Root CA - ECC' by hash. + Leaf cert must have Key Encipherment usage. Other checks TBD. + */ +SecPolicyRef SecPolicyCreateTestAppleSMPEncryption(void); + + +#endif + +/*! + @function SecPolicyCreateAppleIDSService + @abstract Ensure we're appropriately pinned to the IDS service (SSL + Apple restrictions) + */ +SecPolicyRef SecPolicyCreateAppleIDSService(CFStringRef hostname); + +/*! + @function SecPolicyCreateApplePushService + @abstract Ensure we're appropriately pinned to the Push service (SSL + Apple restrictions) + */ +SecPolicyRef SecPolicyCreateApplePushService(CFStringRef hostname); + +/*! + @function SecPolicyCreateAppleMMCSService + @abstract Ensure we're appropriately pinned to the IDS service (SSL + Apple restrictions) + */ +SecPolicyRef SecPolicyCreateAppleMMCSService(CFStringRef hostname); + +/*! + @function SecPolicyCreateAppleSSLService + @abstract Ensure we're appropriately pinned to an Apple server (SSL + Apple restrictions) + */ +SecPolicyRef SecPolicyCreateAppleSSLService(CFStringRef hostname); + +__END_DECLS + +#endif /* !_SECURITY_SECPOLICYPRIV_H_ */ diff --git a/sec/Security/SecRSAKey.c b/Security/sec/Security/SecRSAKey.c similarity index 99% rename from sec/Security/SecRSAKey.c rename to Security/sec/Security/SecRSAKey.c index 51bb5207..67b3bc54 100644 --- a/sec/Security/SecRSAKey.c +++ b/Security/sec/Security/SecRSAKey.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2010,2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -609,6 +609,8 @@ SecKeyDescriptor kSecRSAPublicKeyDescriptor = { SecRSAPublicKeyCopyDescription, NULL, SecRSAPublicKeyCopyPublicSerialization, + NULL, + NULL }; /* Public Key API functions. */ @@ -652,7 +654,7 @@ CFDataRef SecKeyCopyExponent(SecKeyRef key) { CFDataSetLength(exponentData, e_size); - ccn_write_uint(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey), e_size, CFDataGetMutableBytePtr(exponentData)); + ccn_write_uint(ccrsa_ctx_n(pubkey), ccrsa_ctx_e(pubkey), e_size, CFDataGetMutableBytePtr(exponentData)); return exponentData; } @@ -1081,6 +1083,8 @@ SecKeyDescriptor kSecRSAPrivateKeyDescriptor = { SecRSAPrivateKeyCopyDescription, NULL, SecRSAPrivateKeyCopyPublicSerialization, + NULL, + NULL }; /* Private Key API functions. */ diff --git a/sec/Security/SecRSAKey.h b/Security/sec/Security/SecRSAKey.h similarity index 96% rename from sec/Security/SecRSAKey.h rename to Security/sec/Security/SecRSAKey.h index 706a06cf..e54bf82c 100644 --- a/sec/Security/SecRSAKey.h +++ b/Security/sec/Security/SecRSAKey.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2008,2010,2012-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/sec/Security/SecRSAKeyPriv.h b/Security/sec/Security/SecRSAKeyPriv.h similarity index 95% rename from sec/Security/SecRSAKeyPriv.h rename to Security/sec/Security/SecRSAKeyPriv.h index bd3de485..27e1393d 100644 --- a/sec/Security/SecRSAKeyPriv.h +++ b/Security/sec/Security/SecRSAKeyPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2007,2012-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/sec/Security/SecRandom.h b/Security/sec/Security/SecRandom.h new file mode 100644 index 00000000..0ee3a311 --- /dev/null +++ b/Security/sec/Security/SecRandom.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2007-2009,2012-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@ + */ + +/*! + @header SecRandom + The functions provided in SecRandom.h implement high-level accessors + to cryptographically secure random numbers. +*/ + +#ifndef _SECURITY_SECRANDOM_H_ +#define _SECURITY_SECRANDOM_H_ + +#include +#include +#include + +__BEGIN_DECLS + +/*! + @typedef SecRandomRef + @abstract Reference to a (psuedo) random number generator. +*/ +typedef const struct __SecRandom * SecRandomRef; + +/* This is a synonym for NULL, if you'd rather use a named constant. This + refers to a cryptographically secure random number generator. */ +extern const SecRandomRef kSecRandomDefault + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + +/*! + @function SecRandomCopyBytes + @abstract Return count random bytes in *bytes, allocated by the caller. + @result Return 0 on success or -1 if something went wrong, check errno + to find out the real error. +*/ +int SecRandomCopyBytes(SecRandomRef rnd, size_t count, uint8_t *bytes) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + +__END_DECLS + +#endif /* !_SECURITY_SECRANDOM_H_ */ diff --git a/sec/Security/SecSCEP.c b/Security/sec/Security/SecSCEP.c similarity index 94% rename from sec/Security/SecSCEP.c rename to Security/sec/Security/SecSCEP.c index 6b25f1ac..d5efc144 100644 --- a/sec/Security/SecSCEP.c +++ b/Security/sec/Security/SecSCEP.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2008-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-2010,2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -50,7 +50,7 @@ typedef enum { transId = 7 } scep_attr_t; -static CFDataRef scep_oid(scep_attr_t type) +static CF_RETURNS_RETAINED CFDataRef scep_oid(scep_attr_t type) { /* +-------------------+-----------------------------------------------+ | Name | ASN.1 Definition | @@ -87,13 +87,13 @@ static CFDataRef scep_oid(scep_attr_t type) static const char CertRep[] = "3"; static const char PKCSReq[] = "19"; static const char GetCertInitial[] = "20"; -static const char GetCert[] = "21"; -static const char GetCRL[] = "22"; +__unused static const char GetCert[] = "21"; +__unused static const char GetCRL[] = "22"; static const char PKIStatusSUCCESS[] = "0"; -static const char PKIStatusFAILURE[] = "2"; +__unused static const char PKIStatusFAILURE[] = "2"; static const char PKIStatusPENDING[] = "3"; -static CFDataRef +static CF_RETURNS_RETAINED CFDataRef printable_string_data(size_t length, const char *bytes) { DERSize der_length_len = DERLengthOfLength(length); @@ -110,7 +110,7 @@ printable_string_data(size_t length, const char *bytes) #define scep_result(value) printable_string_data(sizeof(value)-1, value) -static CFTypeRef +static CF_RETURNS_NOT_RETAINED CFTypeRef dictionary_array_value_1(CFDictionaryRef attrs, CFTypeRef attr) { CFTypeRef value = NULL; @@ -142,7 +142,7 @@ static bool scep_attr_has_val(CFDictionaryRef attrs, scep_attr_t attr, const cha return result; } -static CFDataRef hexencode(CFDataRef data) +static CF_RETURNS_RETAINED CFDataRef hexencode(CFDataRef data) { CFIndex ix, length = CFDataGetLength(data); const uint8_t *bin_data = CFDataGetBytePtr(data); @@ -254,7 +254,9 @@ SecSCEPGenerateCertificateRequest(CFArrayRef subject, CFDictionaryRef parameters SecIdentityRef self_signed_identity = NULL; CFMutableDataRef signed_request = NULL; SecCertificateRef recipient = NULL; - + CFDataRef msgtype_value_data = NULL; + CFDataRef msgtype_oid_data = NULL; + if (CFGetTypeID(recipients) == SecCertificateGetTypeID()) { recipient = (SecCertificateRef)recipients; } else if (CFGetTypeID(recipients) == CFArrayGetTypeID()) { @@ -291,8 +293,8 @@ SecSCEPGenerateCertificateRequest(CFArrayRef subject, CFDictionaryRef parameters CFReleaseNull(transid_data); /* message type: PKCSReq (19) */ - CFDataRef msgtype_value_data = NULL; - CFDataRef msgtype_oid_data = NULL; + msgtype_value_data = NULL; + msgtype_oid_data = NULL; require(msgtype_oid_data = scep_oid(messageType), out); require(msgtype_value_data = printable_string_data(strlen(PKCSReq), PKCSReq), out); @@ -330,6 +332,8 @@ SecSCEPGenerateCertificateRequest(CFArrayRef subject, CFDictionaryRef parameters out: CFReleaseSafe(simple_attr); + CFReleaseSafe(msgtype_oid_data); + CFReleaseSafe(msgtype_value_data); CFReleaseSafe(self_signed_identity); CFReleaseSafe(enveloped_data); CFReleaseSafe(csr); @@ -558,11 +562,13 @@ SecSCEPVerifyReply(CFDataRef request, CFDataRef reply, CFTypeRef ca_certificates goto out; // FAILURE, the end (return NULL) } else if (CFEqual(pki_status, CFSTR("3"))) { CFDataRef transid_oid_data = NULL, transid_value = NULL; - require(transid_oid_data = scep_oid(transId), out); - require(transid_value = dictionary_array_value_1(signed_attributes, transid_oid_data), out); - CFDictionaryRef err_dict = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&transid_oid_data, (const void **)&transid_value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - *server_error = CFErrorCreate(kCFAllocatorDefault, - CFSTR("PENDING"), 3, err_dict); + CFDictionaryRef err_dict = NULL; + require(transid_oid_data = scep_oid(transId), inner_out); + require(transid_value = dictionary_array_value_1(signed_attributes, transid_oid_data), inner_out); + err_dict = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&transid_oid_data, (const void **)&transid_value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (server_error) + *server_error = CFErrorCreate(kCFAllocatorDefault, CFSTR("PENDING"), 3, err_dict); + inner_out: CFReleaseSafe(err_dict); CFReleaseSafe(transid_oid_data); goto out; @@ -617,7 +623,8 @@ OSStatus SecSCEPValidateCACertMessage(CFArrayRef certs, OSStatus status = errSecParam; SecCertificateRef _ca_certificate = NULL, _ra_signing_certificate = NULL, _ra_encryption_certificate = NULL, _ra_certificate = NULL; - + CFDataRef ca_cert_data = NULL; + CFDataRef ca_hash_cfdata = NULL; CFIndex j, count = CFArrayGetCount(certs); CFMutableArrayRef chain = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); SecPolicyRef policy = SecPolicyCreateBasicX509(); @@ -642,7 +649,7 @@ OSStatus SecSCEPValidateCACertMessage(CFArrayRef certs, if (ca_fingerprint) { secdebug("scep", "checking ca %@ against fingerprint %@", ca_leaf, ca_fingerprint); uint8_t ca_hash[CC_SHA1_DIGEST_LENGTH]; /*max(md5,sha-1)*/ - CFDataRef ca_cert_data = SecCertificateCopyData(ca_leaf); + ca_cert_data = SecCertificateCopyData(ca_leaf); require(ca_cert_data, out); size_t ca_data_len = CFDataGetLength(ca_cert_data); size_t ca_fingerprint_len = CFDataGetLength(ca_fingerprint); @@ -661,13 +668,11 @@ OSStatus SecSCEPValidateCACertMessage(CFArrayRef certs, default: goto out; } - CFRelease(ca_cert_data); - CFDataRef ca_hash_cfdata = CFDataCreate(kCFAllocatorDefault, - ca_hash, ca_fingerprint_len); + CFReleaseNull(ca_cert_data); + ca_hash_cfdata = CFDataCreate(kCFAllocatorDefault, ca_hash, ca_fingerprint_len); require(ca_hash_cfdata, out); - require_action(CFEqual(ca_fingerprint, ca_hash_cfdata), - out, CFRelease(ca_hash_cfdata)); - CFRelease(ca_hash_cfdata); + require(CFEqual(ca_fingerprint, ca_hash_cfdata), out); + CFReleaseNull(ca_hash_cfdata); } _ca_certificate = ca_leaf; CFRetain(ca_leaf); @@ -724,12 +729,14 @@ OSStatus SecSCEPValidateCACertMessage(CFArrayRef certs, status = errSecSuccess; out: - if (_ra_encryption_certificate) CFRelease(_ra_encryption_certificate); - if (_ra_signing_certificate) CFRelease(_ra_signing_certificate); - if (_ca_certificate) CFRelease(_ca_certificate); - if (policy) CFRelease(policy); - if (trust) CFRelease(trust); - if (chain) CFRelease(chain); + CFReleaseSafe(_ra_encryption_certificate); + CFReleaseSafe(_ra_signing_certificate); + CFReleaseSafe(_ca_certificate); + CFReleaseSafe(ca_cert_data); + CFReleaseSafe(ca_hash_cfdata); + CFReleaseSafe(policy); + CFReleaseSafe(trust); + CFReleaseSafe(chain); return status; } @@ -743,7 +750,7 @@ out: // XXX/cs pass CA/RA certificates as a CFTypeRef: one or more certificates for ca_certificate and recipient -CFDataRef +CF_RETURNS_RETAINED CFDataRef SecSCEPGetCertInitial(SecCertificateRef ca_certificate, CFArrayRef subject, CFDictionaryRef parameters, CFDictionaryRef signed_attrs, SecIdentityRef signer, CFTypeRef recipient) { @@ -751,6 +758,8 @@ SecSCEPGetCertInitial(SecCertificateRef ca_certificate, CFArrayRef subject, CFDi CFMutableDictionaryRef simple_attr = NULL; CFDataRef pki_message_contents = NULL; CFMutableDataRef enveloped_data = NULL; + CFDataRef msgtype_value_data = NULL; + CFDataRef msgtype_oid_data = NULL; require(signed_attrs, out); require(pki_message_contents = SecGenerateCertificateRequestSubject(ca_certificate, subject), out); @@ -761,8 +770,6 @@ SecSCEPGetCertInitial(SecCertificateRef ca_certificate, CFArrayRef subject, CFDi simple_attr = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 3, signed_attrs); /* message type: GetCertInitial (20) */ - CFDataRef msgtype_value_data = NULL; - CFDataRef msgtype_oid_data = NULL; require(msgtype_oid_data = scep_oid(messageType), out); require(msgtype_value_data = printable_string_data(sizeof(GetCertInitial) - 1, GetCertInitial), out); CFDictionarySetValue(simple_attr, msgtype_oid_data, msgtype_value_data); @@ -779,6 +786,8 @@ out: CFReleaseSafe(simple_attr); CFReleaseSafe(pki_message_contents); CFReleaseSafe(enveloped_data); + CFReleaseSafe(msgtype_oid_data); + CFReleaseSafe(msgtype_value_data); return signed_request; } diff --git a/sec/Security/SecSCEP.h b/Security/sec/Security/SecSCEP.h similarity index 98% rename from sec/Security/SecSCEP.h rename to Security/sec/Security/SecSCEP.h index bc26548c..dc5c7da4 100644 --- a/sec/Security/SecSCEP.h +++ b/Security/sec/Security/SecSCEP.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-2010,2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -89,6 +89,7 @@ SecSCEPVerifyReply(CFDataRef request, CFDataRef reply, CFTypeRef signer, @abstract generate a scep cert initial request, to be presented to a scep server, in case the first request timed out */ +CF_RETURNS_RETAINED CFDataRef SecSCEPGetCertInitial(SecCertificateRef ca_certificate, CFArrayRef subject, CFDictionaryRef parameters, CFDictionaryRef signed_attrs, SecIdentityRef signer, CFTypeRef recipient); diff --git a/Security/sec/Security/SecServerEncryptionSupport.c b/Security/sec/Security/SecServerEncryptionSupport.c new file mode 100644 index 00000000..1168987b --- /dev/null +++ b/Security/sec/Security/SecServerEncryptionSupport.c @@ -0,0 +1,355 @@ +// +// SecServerEncryptionSupport.c +// sec +// +// + +#include + +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include +#include + +#if !(TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) + +// +// We assume that SecKey is set up for this to work. +// Specifically ccrng_seckey needs to be initialized +// +// As it happens we work in terms of SecKeys at the +// higher level, so we're good. +// + +const uint32_t kBlobCipherKeySize = CCAES_KEY_SIZE_128; +const uint32_t kBlobMacSize = 16; + +static void InitServerECIES(ccecies_gcm_t ecies, const struct ccmode_gcm *gcm_mode) +{ + ccecies_encrypt_gcm_setup(ecies, + ccsha256_di(), + ccrng_seckey, + gcm_mode, + kBlobCipherKeySize, + kBlobMacSize, + ECIES_EXPORT_PUB_STANDARD+ECIES_EPH_PUBKEY_IN_SHAREDINFO1); +} + +// +// Der Encode +// + +// +// EncryptedPayloadToServerVersion ::= INTEGER {v1(1)} +// +// EncryptedPayloadToServer ::= SEQUENCE { +// version EncryptedPayloadToServerVersion DEFAULT v1, +// ephemeralPublicKey OCTET STRING, +// GCMEncryptedData OCTET STRING, +// GCMTag OCTET STRING +// } + + +enum { + SERVER_BLOB_ENCRYPTED_DATA = 0 +}; + +static size_t sizeof_implicit_nocopy(ccder_tag implicit_tag, size_t space) +{ + return ccder_sizeof(implicit_tag, space); +} + +static uint8_t *encode_implicit_nocopy(ccder_tag implicit_tag, size_t size, uint8_t**start, const uint8_t *der, uint8_t *der_end) +{ + if (start == NULL) + return NULL; + + return ccder_encode_tl(implicit_tag, size, der, + (*start = ccder_encode_body_nocopy(size, der, der_end))); +} + +static uint8_t *encode_octect_string_nocopy(size_t size, uint8_t**start, const uint8_t *der, uint8_t *der_end) +{ + return encode_implicit_nocopy(CCDER_OCTET_STRING, size, start, der, der_end); +} + +static size_t sizeof_server_blob(size_t public_key_size, + size_t ciphertext_size, + size_t verifier_size) +{ + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, + sizeof_implicit_nocopy(CCDER_OCTET_STRING, public_key_size) + + sizeof_implicit_nocopy(CCDER_OCTET_STRING, ciphertext_size) + + sizeof_implicit_nocopy(CCDER_OCTET_STRING, verifier_size)); +} + + +static uint8_t* encode_empty_server_blob_for(size_t public_key_size, uint8_t **public_key_start, + size_t ciphertext_size, uint8_t **ciphertext, + size_t verifier_size, uint8_t **verifier, + const uint8_t *der, uint8_t *der_end) +{ + return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + encode_octect_string_nocopy(public_key_size, public_key_start, der, + encode_octect_string_nocopy(ciphertext_size, ciphertext, der, + encode_octect_string_nocopy(verifier_size, verifier, der, der_end)))); +} + +static const uint8_t* decode_octect_string(size_t* size, const uint8_t ** start, const uint8_t *der, const uint8_t* der_end) +{ + if (size == NULL) + return NULL; + + der = ccder_decode_tl(CCDER_OCTET_STRING, size, der, der_end); + + if (der && start) { + *start = der; + der += *size; + } + + return der; +} + +static const uint8_t* decode_server_blob(size_t *public_key_size, const uint8_t **public_key_start, + size_t *ciphertext_size, const uint8_t **ciphertext, + size_t *verifier_size, const uint8_t **verifier, + CFErrorRef *error, const uint8_t *der, const uint8_t *der_end) +{ + const uint8_t *sequence_end; + der = ccder_decode_sequence_tl(&sequence_end, der, der_end); + + if (der_end != sequence_end) + der = NULL; + + der = decode_octect_string(public_key_size, public_key_start, der, der_end); + der = decode_octect_string(ciphertext_size, ciphertext, der, der_end); + der = decode_octect_string(verifier_size, verifier, der, der_end); + + return der; +} + +static CFMutableDataRef CreateDataForEncodeEncryptedBlobOf(ccec_pub_ctx_t public_key, + size_t public_key_size, uint8_t **public_key_start, + size_t ciphertext_size, uint8_t **ciphertext, + size_t verifier_size, uint8_t **verifier, + CFErrorRef *error) +{ + CFMutableDataRef result = NULL; + CFMutableDataRef allocated = CFDataCreateMutableWithScratch(kCFAllocatorDefault, sizeof_server_blob(public_key_size, ciphertext_size, verifier_size)); + + require_action_quiet(allocated, fail, SecError(errSecAllocate, error, CFSTR("failed to create data"))); + + uint8_t *der = CFDataGetMutableBytePtr(allocated); + uint8_t *der_end = der + CFDataGetLength(allocated); + + der = encode_empty_server_blob_for(public_key_size, public_key_start, + ciphertext_size, ciphertext, + verifier_size, verifier, + der, der_end); + + require_action_quiet(der, fail, SecError(errSecParam, error, CFSTR("Encoding failed"))); + + CFRetainAssign(result, allocated); + +fail: + CFReleaseNull(allocated); + return result; +} + +static bool ParseAndFindEncryptedData(CFDataRef blob, + size_t *public_key_size, const uint8_t **public_key_start, + size_t *ciphertext_size, const uint8_t **ciphertext, + size_t *verifier_size, const uint8_t **verifier, + CFErrorRef *error) +{ + bool success = false; + const uint8_t *der = CFDataGetBytePtr(blob); + const uint8_t *der_end = der + CFDataGetLength(blob); + der = decode_server_blob(public_key_size, public_key_start, + ciphertext_size, ciphertext, + verifier_size, verifier, + error, der, der_end); + + require_action_quiet(der == der_end, fail, SecError(errSecParam, error, CFSTR("Blob failed to decode"))); + + success = true; +fail: + return success; + +} + +static size_t ccec_x963_pub_export_size(ccec_pub_ctx_t key) +{ + return ccec_x963_export_size(0,(ccec_full_ctx_t)key.body); // We lie since the API is broken. +} + +CFDataRef SecCopyEncryptedToServerKey(SecKeyRef publicKey, CFDataRef dataToEncrypt, CFErrorRef *error) +{ + __block CFDataRef result = NULL; + + + SecECDoWithPubKey(publicKey, error, ^(ccec_pub_ctx_t public_key) { + CFMutableDataRef encrypted = NULL; + + struct ccecies_gcm ecies_encrypt; + InitServerECIES(&ecies_encrypt, ccaes_gcm_encrypt_mode()); + + size_t plain_size = CFDataGetLength(dataToEncrypt); + size_t encrypted_size = ccecies_encrypt_gcm_ciphertext_size(public_key, &ecies_encrypt, plain_size); + + CFMutableDataRef encryption_temp = CFDataCreateMutableWithScratch(kCFAllocatorDefault, encrypted_size); + require_action_quiet(encryption_temp, errout, SecError(errSecAllocate, error, CFSTR("failed to create data"))); + + uint8_t *encryption_buffer = (uint8_t *) CFDataGetMutableBytePtr(encryption_temp); + + int encrypt_result = ccecies_encrypt_gcm(public_key, + &ecies_encrypt, + plain_size, CFDataGetBytePtr(dataToEncrypt), + 0, NULL, + 0, NULL, + &encrypted_size, encryption_buffer); + + + size_t public_key_size = ccec_x963_pub_export_size(public_key); + uint8_t *public_key_data = NULL; + size_t ciphertext_size = plain_size; + uint8_t *ciphertext = NULL; + size_t tag_size = kBlobMacSize; + uint8_t *tag = NULL; + + require_action_quiet(public_key_size + ciphertext_size + tag_size == encrypted_size, errout, SecError(errSecInternal, error, CFSTR("Allocation mismatch"), encrypt_result)); + + encrypted = CreateDataForEncodeEncryptedBlobOf(public_key, + public_key_size, &public_key_data, + ciphertext_size, &ciphertext, + tag_size, &tag, + error); + require_quiet(encrypted, errout); + + // + // Core crypto SPI a work in progress, until then we copy. + // + + memcpy(public_key_data, encryption_buffer, public_key_size); + memcpy(ciphertext, encryption_buffer + public_key_size, ciphertext_size); + memcpy(tag, encryption_buffer + public_key_size + ciphertext_size, tag_size); + + require_action_quiet(encrypt_result == 0, errout, SecError(errSecBadReq, error, CFSTR("ccecies_encrypt_gcm failed %d"), encrypt_result)); + + CFRetainAssign(result, encrypted); + errout: + CFReleaseSafe(encryption_temp); + CFReleaseSafe(encrypted); + }); + + + return result; +} + + +CFDataRef SecCopyDecryptedForServer(SecKeyRef serverFullKey, CFDataRef blob, CFErrorRef* error) +{ + __block CFDataRef result = NULL; + + SecECDoWithFullKey(serverFullKey, error, ^(ccec_full_ctx_t private_key) { + CFMutableDataRef plain = NULL; + CFMutableDataRef crypto_buffer = NULL; + size_t encrypted_size; + + size_t plain_size; + + struct ccecies_gcm ecies_decrypt; + InitServerECIES(&ecies_decrypt, ccaes_gcm_decrypt_mode()); + size_t public_key_size; + const uint8_t *public_key_start = NULL; + size_t ciphertext_size; + const uint8_t *ciphertext = NULL; + size_t verifier_size; + const uint8_t *verifier = NULL; + + require_quiet(ParseAndFindEncryptedData(blob, + &public_key_size, &public_key_start, + &ciphertext_size, &ciphertext, + &verifier_size, &verifier, + error), errout); + + require_quiet(public_key_start, errout); // Silence analyzer, shouldn't ever happen. + require_quiet(ciphertext, errout); // Silence analyzer, shouldn't ever happen. + require_quiet(verifier, errout); // Silence analyzer, shouldn't ever happen. + + encrypted_size = public_key_size + ciphertext_size + verifier_size; + crypto_buffer = CFDataCreateMutableWithScratch(kCFAllocatorDefault, encrypted_size); + require_action_quiet(crypto_buffer, errout, SecError(errSecAllocate, error, CFSTR("failed to create data"))); + + uint8_t *crypto_buffer_ptr = CFDataGetMutableBytePtr(crypto_buffer); + memcpy(crypto_buffer_ptr, public_key_start, public_key_size); + memcpy(crypto_buffer_ptr + public_key_size, ciphertext, ciphertext_size); + memcpy(crypto_buffer_ptr + public_key_size + ciphertext_size, verifier, verifier_size); + + + plain_size = ccecies_decrypt_gcm_plaintext_size(private_key, &ecies_decrypt, encrypted_size); + plain = CFDataCreateMutableWithScratch(kCFAllocatorDefault, plain_size); + + int decrypt_result = ccecies_decrypt_gcm(private_key, + &ecies_decrypt, + encrypted_size, crypto_buffer_ptr, + 0, NULL, + 0, NULL, + &plain_size, CFDataGetMutableBytePtr(plain)); + + require_action_quiet(decrypt_result == 0, errout, SecError(errSecBadReq, error, CFSTR("ccecies_decrypt_gcm failed %d"), decrypt_result)); + + CFRetainAssign(result, plain); + + errout: + CFReleaseSafe(plain); + CFReleaseSafe(crypto_buffer); + }); + + return result; +} + +CFDataRef SecCopyEncryptedToServer(SecTrustRef trustedEvaluation, CFDataRef dataToEncrypt, CFErrorRef *error) +{ + CFDataRef result = NULL; + SecKeyRef trustKey = SecTrustCopyPublicKey(trustedEvaluation); + + require_action_quiet(trustKey, fail, + SecError(errSecInteractionNotAllowed, error, CFSTR("Failed to get key out of trust ref, was it evaluated?"))); + + + result = SecCopyEncryptedToServerKey(trustKey, dataToEncrypt, error); + +fail: + + return result; +} + +#else + +CFDataRef SecCopyDecryptedForServer(SecKeyRef serverFullKey, CFDataRef encryptedData, CFErrorRef* error) +{ + SecError(errSecUnimplemented, error, CFSTR("SecCopyDecryptedForServer not implemented on this platform")); + + return NULL; +} + +CFDataRef SecCopyEncryptedToServer(SecTrustRef trustedEvaluation, CFDataRef dataToEncrypt, CFErrorRef *error) +{ + SecError(errSecUnimplemented, error, CFSTR("SecCopyEncryptedToServer not implemented on this platform")); + + return NULL; +} + +#endif diff --git a/Security/sec/Security/SecServerEncryptionSupport.h b/Security/sec/Security/SecServerEncryptionSupport.h new file mode 100644 index 00000000..e96b474c --- /dev/null +++ b/Security/sec/Security/SecServerEncryptionSupport.h @@ -0,0 +1,26 @@ +// +// SecServerEncryptionSupport.h +// +// + +#ifndef _SECURITY_SECSERVERENCRYPTIONSUPPORT_H_ +#define _SECURITY_SECSERVERENCRYPTIONSUPPORT_H_ + +#include +#include +#include +#include + +CFDataRef SecCopyEncryptedToServer(SecTrustRef trustedEvaluation, CFDataRef dataToEncrypt, CFErrorRef *error) + __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0); + +// +// For testing +// +CFDataRef SecCopyDecryptedForServer(SecKeyRef serverFullKey, CFDataRef encryptedData, CFErrorRef* error) + __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0); + +CFDataRef SecCopyEncryptedToServerKey(SecKeyRef publicKey, CFDataRef dataToEncrypt, CFErrorRef *error) + __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0); + +#endif diff --git a/Security/sec/Security/SecSharedCredential.c b/Security/sec/Security/SecSharedCredential.c new file mode 100644 index 00000000..eb0cbf2e --- /dev/null +++ b/Security/sec/Security/SecSharedCredential.c @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * SecSharedCredential.c - CoreFoundation-based functions to store and retrieve shared credentials. + * + */ + +#include +#include +#include +#include +#include "SecItemInternal.h" +#include +#include "SecPasswordGenerate.h" + +/* forward declarations */ +OSStatus SecAddSharedWebCredentialSync(CFStringRef fqdn, CFStringRef account, CFStringRef password, CFErrorRef *error); +OSStatus SecCopySharedWebCredentialSync(CFStringRef fqdn, CFStringRef account, CFArrayRef *credentials, CFErrorRef *error); + + +OSStatus SecAddSharedWebCredentialSync(CFStringRef fqdn, + CFStringRef account, + CFStringRef password, + CFErrorRef *error) +{ + OSStatus status; + __block CFErrorRef* outError = error; + __block CFMutableDictionaryRef args = CFDictionaryCreateMutable(kCFAllocatorDefault, + 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (fqdn) { + CFDictionaryAddValue(args, kSecAttrServer, fqdn); + } + if (account) { + CFDictionaryAddValue(args, kSecAttrAccount, account); + } + if (password) { +#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR + CFDictionaryAddValue(args, kSecSharedPassword, password); +#else + CFDictionaryAddValue(args, CFSTR("spwd"), password); +#endif + } + status = SecOSStatusWith(^bool (CFErrorRef *error) { + CFTypeRef raw_result = NULL; + bool xpc_result; + bool internal_spi = false; // TODO: support this for SecurityDevTests + if(internal_spi && gSecurityd && gSecurityd->sec_add_shared_web_credential) { + xpc_result = gSecurityd->sec_add_shared_web_credential(args, NULL, NULL, 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); + } + CFReleaseSafe(args); + if (!xpc_result) { + if (NULL == *error) { + SecError(errSecInternal, error, CFSTR("Internal error (XPC failure)")); + } + } + if (outError) { + *outError = (error) ? *error : NULL; + CFRetainSafe(*outError); + } else { + CFReleaseNull(*error); + } + CFReleaseNull(raw_result); + return xpc_result; + }); + + return status; +} + +void SecAddSharedWebCredential(CFStringRef fqdn, + CFStringRef account, + CFStringRef password, + void (^completionHandler)(CFErrorRef error)) +{ + __block CFErrorRef error = NULL; + __block dispatch_queue_t dst_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0); + dispatch_retain(dst_queue); + + /* sanity check input arguments */ + CFStringRef errStr = NULL; + if (!fqdn || CFGetTypeID(fqdn) != CFStringGetTypeID() || !CFStringGetLength(fqdn) || + !account || CFGetTypeID(account) != CFStringGetTypeID() || !CFStringGetLength(account) ) { + errStr = CFSTR("fqdn or account was not of type CFString, or not provided"); + } + else if (password && CFGetTypeID(password) != CFStringGetTypeID()) { + errStr = CFSTR("non-nil password was not of type CFString"); + } + if (errStr) { + SecError(errSecParam, &error, errStr); + dispatch_async(dst_queue, ^{ + if (completionHandler) { + completionHandler(error); + } + CFReleaseSafe(error); + dispatch_release(dst_queue); + }); + return; + } + + __block CFStringRef serverStr = CFRetainSafe(fqdn); + __block CFStringRef accountStr = CFRetainSafe(account); + __block CFStringRef passwordStr = CFRetainSafe(password); + + dispatch_async(dst_queue, ^{ + OSStatus status = SecAddSharedWebCredentialSync(serverStr, accountStr, passwordStr, &error); + CFReleaseSafe(serverStr); + CFReleaseSafe(accountStr); + CFReleaseSafe(passwordStr); + + if (status && !error) { + SecError(status, &error, CFSTR("Error adding shared password")); + } + dispatch_async(dst_queue, ^{ + if (completionHandler) { + completionHandler(error); + } + CFReleaseSafe(error); + dispatch_release(dst_queue); + }); + }); + +} + +OSStatus SecCopySharedWebCredentialSync(CFStringRef fqdn, + CFStringRef account, + CFArrayRef *credentials, + CFErrorRef *error) +{ + OSStatus status; + __block CFErrorRef* outError = error; + __block CFMutableDictionaryRef args = CFDictionaryCreateMutable(kCFAllocatorDefault, + 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (fqdn) { + CFDictionaryAddValue(args, kSecAttrServer, fqdn); + } + if (account) { + CFDictionaryAddValue(args, kSecAttrAccount, account); + } + status = SecOSStatusWith(^bool (CFErrorRef *error) { + CFTypeRef raw_result = NULL; + bool xpc_result; + bool internal_spi = false; // TODO: support this for SecurityDevTests + if(internal_spi && gSecurityd && gSecurityd->sec_copy_shared_web_credential) { + xpc_result = gSecurityd->sec_copy_shared_web_credential(args, NULL, NULL, 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); + } + CFReleaseSafe(args); + if (!xpc_result) { + if (NULL == *error) { + SecError(errSecInternal, error, CFSTR("Internal error (XPC failure)")); + } + } + if (outError) { + *outError = (error) ? *error : NULL; + CFRetainSafe(*outError); + } else { + CFReleaseNull(*error); + } + if (!raw_result) { + raw_result = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + } + *credentials = raw_result; + return xpc_result; + }); + + return status; + +} + +void SecRequestSharedWebCredential(CFStringRef fqdn, + CFStringRef account, + void (^completionHandler)(CFArrayRef credentials, CFErrorRef error)) +{ + __block CFArrayRef result = NULL; + __block CFErrorRef error = NULL; + __block dispatch_queue_t dst_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0); + dispatch_retain(dst_queue); + + /* sanity check input arguments, if provided */ + CFStringRef errStr = NULL; + if (fqdn && (CFGetTypeID(fqdn) != CFStringGetTypeID() || !CFStringGetLength(fqdn))) { + errStr = CFSTR("fqdn was empty or not a CFString"); + } + else if (account && (CFGetTypeID(account) != CFStringGetTypeID() || !CFStringGetLength(account))) { + errStr = CFSTR("account was empty or not a CFString"); + } + if (errStr) { + SecError(errSecParam, &error, errStr); + dispatch_async(dst_queue, ^{ + if (completionHandler) { + completionHandler(result, error); + } + CFReleaseSafe(error); + CFReleaseSafe(result); + dispatch_release(dst_queue); + }); + return; + } + + __block CFStringRef serverStr = CFRetainSafe(fqdn); + __block CFStringRef accountStr = CFRetainSafe(account); + + dispatch_async(dst_queue, ^{ + OSStatus status = SecCopySharedWebCredentialSync(serverStr, accountStr, &result, &error); + CFReleaseSafe(serverStr); + CFReleaseSafe(accountStr); + + if (status && !error) { + SecError(status, &error, CFSTR("Error copying shared password")); + } + dispatch_async(dst_queue, ^{ + if (completionHandler) { + completionHandler(result, error); + } + CFReleaseSafe(error); + CFReleaseSafe(result); + dispatch_release(dst_queue); + }); + }); + +} + +CFStringRef SecCreateSharedWebCredentialPassword(void) +{ + + CFStringRef password = NULL; + CFErrorRef error = NULL; + CFMutableDictionaryRef passwordRequirements = NULL; + + CFStringRef allowedCharacters = CFSTR("abcdefghkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789"); + CFCharacterSetRef requiredCharactersLower = CFCharacterSetCreateWithCharactersInString(NULL, CFSTR("abcdefghkmnopqrstuvwxyz")); + CFCharacterSetRef requiredCharactersUppder = CFCharacterSetCreateWithCharactersInString(NULL, CFSTR("ABCDEFGHJKLMNPQRSTUVWXYZ")); + CFCharacterSetRef requiredCharactersNumbers = CFCharacterSetCreateWithCharactersInString(NULL, CFSTR("3456789")); + + int groupSize = 3; + int groupCount = 4; + int totalLength = (groupSize * groupCount); + CFNumberRef groupSizeRef = CFNumberCreate(NULL, kCFNumberIntType, &groupSize); + CFNumberRef groupCountRef = CFNumberCreate(NULL, kCFNumberIntType, &groupCount); + CFNumberRef totalLengthRef = CFNumberCreate(NULL, kCFNumberIntType, &totalLength); + CFStringRef separator = CFSTR("-"); + + CFMutableArrayRef requiredCharacterSets = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(requiredCharacterSets, requiredCharactersLower); + CFArrayAppendValue(requiredCharacterSets, requiredCharactersUppder); + CFArrayAppendValue(requiredCharacterSets, requiredCharactersNumbers); + + passwordRequirements = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); + CFDictionaryAddValue(passwordRequirements, kSecPasswordAllowedCharactersKey, allowedCharacters); + CFDictionaryAddValue(passwordRequirements, kSecPasswordRequiredCharactersKey, requiredCharacterSets); + CFDictionaryAddValue(passwordRequirements, kSecPasswordGroupSize, groupSizeRef ); + CFDictionaryAddValue(passwordRequirements, kSecPasswordNumberOfGroups, groupCountRef); + CFDictionaryAddValue(passwordRequirements, kSecPasswordSeparator, separator); + CFDictionaryAddValue(passwordRequirements, kSecPasswordMaxLengthKey, totalLengthRef); + CFDictionaryAddValue(passwordRequirements, kSecPasswordMinLengthKey, totalLengthRef); + CFDictionaryAddValue(passwordRequirements, kSecPasswordDefaultForType, CFSTR("false")); + CFRelease(requiredCharactersLower); + CFRelease(requiredCharactersUppder); + CFRelease(requiredCharactersNumbers); + CFRelease(groupSizeRef); + CFRelease(groupCountRef); + CFRelease(totalLengthRef); + + password = SecPasswordGenerate(kSecPasswordTypeSafari, &error, passwordRequirements); + + CFRelease(requiredCharacterSets); + CFRelease(passwordRequirements); + if ((error && error != errSecSuccess) || !password) + { + if (password) CFRelease(password); + secwarning("SecPasswordGenerate failed to generate a password for SecCreateSharedWebCredentialPassword."); + return NULL; + } else { + return password; + } + +} diff --git a/Security/sec/Security/SecSharedCredential.h b/Security/sec/Security/SecSharedCredential.h new file mode 100644 index 00000000..68f4ed4c --- /dev/null +++ b/Security/sec/Security/SecSharedCredential.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecSharedCredential + SecSharedCredential defines CoreFoundation-based functions for + storing and requesting shared password-based credentials. + These credentials are currently able to be shared with Safari and + applications which have a 'com.apple.developer.associated-domains' + entitlement that includes the domain being requested. + */ + +#ifndef _SECURITY_SECSHAREDCREDENTIAL_H_ +#define _SECURITY_SECSHAREDCREDENTIAL_H_ + +#include +#include +#include + +__BEGIN_DECLS + +#ifdef __BLOCKS__ + +/*! + @enum Credential Key Constants + @discussion Predefined key constants used to get values in a dictionary + of credentials returned by SecRequestWebCredential. + @constant kSecSharedPassword Specifies a dictionary key whose value is a + shared password. You use this key to get a value of type CFStringRef + that contains a password. +*/ +extern CFTypeRef kSecSharedPassword + __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0); + +/*! + @function SecAddSharedWebCredential + @abstract Asynchronously store (or update) a shared password for a website. + @param fqdn The fully qualified domain name of the website requiring the password. + @param account The account name associated with this password. + @param password The password to be stored. Pass NULL to remove a shared password if it exists. + @param completionHandler A block which will be invoked when the function has completed. If the shared password was successfully added (or removed), the CFErrorRef parameter passed to the block will be NULL. If the error parameter is non-NULL, an error occurred and the error reference will hold the result. Note: the error reference will be automatically released after this handler is called, though you may optionally retain it for as long as needed. + @discussion This function adds a shared password item which will be accessible by Safari and applications that have the specified fully-qualified domain name in their 'com.apple.developer.associated-domains' entitlement. If a shared password item already exists for the specified website and account, it will be updated with the provided password. To remove a password, pass NULL for the password parameter. + + Note: since a request involving shared web credentials may potentially require user interaction or other verification to be approved, this function is dispatched asynchronously; your code provides a completion handler that will be called once the results (if any) are available. + */ +void SecAddSharedWebCredential(CFStringRef fqdn, CFStringRef account, CFStringRef password, + void (^completionHandler)(CFErrorRef error)) + __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0); + +/*! + @function SecRequestSharedWebCredential + @abstract Asynchronously obtain one or more shared passwords for a website. + @param fqdn (Optional) Fully qualified domain name of the website for which passwords are being requested. If NULL is passed in this argument, the domain name(s) listed in the calling application's 'com.apple.developer.associated-domains' entitlement are searched implicitly. + @param account (Optional) Account name for which passwords are being requested. The account may be NULL to request all shared credentials which are available for the site, allowing the caller to discover an existing account. + @param completionHandler A block which will be called to deliver the requested credentials. If no matching items were found, the credentials array will be empty, and the CFErrorRef parameter will provide the error result. Note: the credentials and error references will be automatically released after this handler is called, though you may optionally retain either for as long as needed. + @discussion This function requests one or more shared passwords for a given website, depending on whether the optional account parameter is supplied. To obtain results, the website specified in the fqdn parameter must be one which matches an entry in the calling application's 'com.apple.developer.associated-domains' entitlement. + + If matching shared password items are found, the credentials provided to the completionHandler will be a CFArrayRef containing CFDictionaryRef entries. Each dictionary entry will contain the following pairs (see Security/SecItem.h): + key: kSecAttrServer value: CFStringRef (the website) + key: kSecAttrAccount value: CFStringRef (the account) + key: kSecSharedPassword value: CFStringRef (the password) + + If the found item specifies a non-standard port number (i.e. other than 443 for https), the following key may also be present: + key: kSecAttrPort value: CFNumberRef (the port number) + + Note: since a request involving shared web credentials may potentially require user interaction or other verification to be approved, this function is dispatched asynchronously; your code provides a completion handler that will be called once the results (if any) are available. + */ +void SecRequestSharedWebCredential(CFStringRef fqdn, CFStringRef account, + void (^completionHandler)(CFArrayRef credentials, CFErrorRef error)) + __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0); + +/*! + @function SecCreateSharedWebCredentialPassword + @abstract Returns a randomly generated password. + @return CFStringRef password in the form xxx-xxx-xxx-xxx where x is taken from the sets "abcdefghkmnopqrstuvwxy", "ABCDEFGHJKLMNPQRSTUVWXYZ", "3456789" with at least one character from each set being present. +*/ + +CFStringRef SecCreateSharedWebCredentialPassword(void) +__OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0); + + +#endif /* __BLOCKS__ */ + +__END_DECLS + +#endif /* !_SECURITY_SECSHAREDCREDENTIAL_H_ */ + diff --git a/sec/Security/SecTrust.c b/Security/sec/Security/SecTrust.c similarity index 96% rename from sec/Security/SecTrust.c rename to Security/sec/Security/SecTrust.c index d7f4775f..a7138f50 100644 --- a/sec/Security/SecTrust.c +++ b/Security/sec/Security/SecTrust.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2006-2013 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,11 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ * * SecTrust.c - CoreFoundation based certificate trust evaluator * - * Created by Michael Brouwer on 10/17/06. */ #include @@ -30,8 +29,12 @@ #include #include #include +#include #include -#include +#include +#include +#include +#include #include #include #include @@ -43,17 +46,18 @@ #include #include #include -#include + +#include #include #include #include +#include #include "SecRSAKey.h" #include -#include -#include + #include -#include + #include #define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); @@ -106,17 +110,11 @@ struct __SecTrust { SecNetworkPolicy _networkPolicy; }; -/* CFRuntime registration data. */ -static pthread_once_t kSecTrustRegisterClass = PTHREAD_ONCE_INIT; -static CFTypeID kSecTrustTypeID = _kCFRuntimeNotATypeID; - /* Forward declarations of static functions. */ -static CFStringRef SecTrustDescribe(CFTypeRef cf); -static void SecTrustDestroy(CFTypeRef cf); static OSStatus SecTrustEvaluateIfNecessary(SecTrustRef trust); /* Static functions. */ -static CF_RETURNS_RETAINED CFStringRef SecTrustDescribe(CFTypeRef cf) { +static CFStringRef SecTrustCopyDescription(CFTypeRef cf) { SecTrustRef trust = (SecTrustRef)cf; return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR(""), trust); @@ -136,27 +134,8 @@ static void SecTrustDestroy(CFTypeRef cf) { CFReleaseSafe(trust->_exceptions); } -static void SecTrustRegisterClass(void) { - static const CFRuntimeClass kSecTrustClass = { - 0, /* version */ - "SecTrust", /* class name */ - NULL, /* init */ - NULL, /* copy */ - SecTrustDestroy, /* dealloc */ - NULL, /* equal */ - NULL, /* hash */ - NULL, /* copyFormattingDesc */ - SecTrustDescribe /* copyDebugDesc */ - }; - - kSecTrustTypeID = _CFRuntimeRegisterClass(&kSecTrustClass); -} - /* Public API functions. */ -CFTypeID SecTrustGetTypeID(void) { - pthread_once(&kSecTrustRegisterClass, SecTrustRegisterClass); - return kSecTrustTypeID; -} +CFGiblisFor(SecTrust) OSStatus SecTrustCreateWithCertificates(CFTypeRef certificates, CFTypeRef policies, SecTrustRef *trust) { @@ -216,7 +195,10 @@ errOut: } else { result->_certificates = l_certs; result->_policies = l_policies; - *trust = result; + if (trust) + *trust = result; + else + CFReleaseSafe(result); } return status; } @@ -458,6 +440,46 @@ static void SecTrustCheckException(const void *key, const void *value, void *con } } +#if TARGET_OS_IPHONE +static CFArrayRef SecTrustCreatePolicyAnchorsArray(const UInt8* certData, CFIndex certLength) +{ + CFArrayRef array = NULL; + CFAllocatorRef allocator = kCFAllocatorDefault; + SecCertificateRef cert = SecCertificateCreateWithBytes(allocator, certData, certLength); + if (cert) { + array = CFArrayCreate(allocator, (const void **)&cert, 1, &kCFTypeArrayCallBacks); + CFReleaseSafe(cert); + } + return array; +} +#endif + +static void SecTrustAddPolicyAnchors(SecTrustRef trust) +{ + /* Provide anchor certificates specifically required by certain policies. + This is used to evaluate test policies where the anchor is not provided + in the root store and may not be able to be supplied by the caller. + */ + CFArrayRef policies = (trust) ? trust->_policies : NULL; + if (!policies) { + return; + } + CFIndex ix, count = CFArrayGetCount(policies); + for (ix = 0; ix < count; ++ix) { + SecPolicyRef policy = (SecPolicyRef) CFArrayGetValueAtIndex(policies, ix); + if (policy) { + #if TARGET_OS_IPHONE + if (CFEqual(policy->_oid, kSecPolicyAppleTestSMPEncryption)) { + CFReleaseSafe(trust->_anchors); + trust->_anchors = SecTrustCreatePolicyAnchorsArray(_SEC_TestAppleRootCAECC, sizeof(_SEC_TestAppleRootCAECC)); + trust->_anchorsOnly = true; + break; + } + #endif + } + } +} + OSStatus SecTrustEvaluate(SecTrustRef trust, SecTrustResultType *result) { if (!trust) { @@ -505,7 +527,6 @@ OSStatus SecTrustEvaluate(SecTrustRef trust, SecTrustResultType *result) { DoneCheckingTrust: trust->_trustResult = trustResult; -#if DEBUG /* log to syslog when there is a trust failure */ if (trustResult != kSecTrustResultProceed && trustResult != kSecTrustResultConfirm && @@ -514,8 +535,7 @@ DoneCheckingTrust: secerror("%@", failureDesc); CFRelease(failureDesc); } -#endif - + *result = trustResult; @@ -611,6 +631,8 @@ static OSStatus SecTrustEvaluateIfNecessary(SecTrustRef trust) { CFReleaseNull(trust->_details); CFReleaseNull(trust->_info); + SecTrustAddPolicyAnchors(trust); + /* @@@ Consider an optimization where we keep a side dictionary with the SHA1 hash of ever SecCertificateRef we send, so we only send potential duplicates once, and have the server respond with either just the SHA1 hash of a certificate, or the complete certificate in the response depending on whether the client already sent it, so we don't send back certificates to the client it already has. */ return SecOSStatusWith(^bool (CFErrorRef *error) { trust->_trustResult = SECURITYD_XPC(sec_trust_evaluate, certs_anchors_bool_policies_date_ag_to_details_info_chain_int_error_request, trust->_certificates, trust->_anchors, trust->_anchorsOnly, trust->_policies, SecTrustGetVerifyTime(trust), SecAccessGroupsGetCurrent(), &trust->_details, &trust->_info, &trust->_chain, error); @@ -1199,16 +1221,12 @@ struct __SecTrustNode { }; typedef struct __SecTrustNode SecTrustNode; -/* CFRuntime registration data. */ -static pthread_once_t kSecTrustNodeRegisterClass = PTHREAD_ONCE_INIT; -static CFTypeID kSecTrustNodeTypeID = _kCFRuntimeNotATypeID; - /* Forward declarations of static functions. */ static CFStringRef SecTrustNodeDescribe(CFTypeRef cf); static void SecTrustNodeDestroy(CFTypeRef cf); /* Static functions. */ -static CFStringRef SecTrustNodeDescribe(CFTypeRef cf) { +static CFStringRef SecTrustNodeCopyDescription(CFTypeRef cf) { SecTrustNodeRef node = (SecTrustNodeRef)cf; return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR(""), node); @@ -1227,27 +1245,8 @@ static void SecTrustNodeDestroy(CFTypeRef cf) { } } -static void SecTrustNodeRegisterClass(void) { - static const CFRuntimeClass kSecTrustNodeClass = { - 0, /* version */ - "SecTrustNode", /* class name */ - NULL, /* init */ - NULL, /* copy */ - SecTrustNodeDestroy, /* dealloc */ - NULL, /* equal */ - NULL, /* hash */ - NULL, /* copyFormattingDesc */ - SecTrustNodeDescribe /* copyDebugDesc */ - }; - - kSecTrustNodeTypeID = _CFRuntimeRegisterClass(&kSecTrustNodeClass); -} - /* SecTrustNode API functions. */ -CFTypeID SecTrustNodeGetTypeID(void) { - pthread_once(&kSecTrustNodeRegisterClass, SecTrustNodeRegisterClass); - return kSecTrustNodeTypeID; -} +CFGiblisFor(SecTrustNode) SecTrustNodeRef SecTrustNodeCreate(SecTrustRef trust, SecCertificateRef certificate, SecTrustNodeRef child) { diff --git a/Security/sec/Security/SecTrust.h b/Security/sec/Security/SecTrust.h new file mode 100644 index 00000000..8e43aba5 --- /dev/null +++ b/Security/sec/Security/SecTrust.h @@ -0,0 +1,681 @@ +/* + * Copyright (c) 2002-2010,2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecTrust + The functions and data types in SecTrust implement trust computation + and allow the caller to apply trust decisions to the evaluation. + */ + +#ifndef _SECURITY_SECTRUST_H_ +#define _SECURITY_SECTRUST_H_ + +#include +#include +#include + +__BEGIN_DECLS + +/*! + @typedef SecTrustResultType + @abstract Specifies the trust result type. + @discussion SecTrustResultType results have two dimensions. They specify + both whether evaluation suceeded and whether this is because of a user + decision. The commonly expected result is kSecTrustResultUnspecified, + which indicates a positive result that wasn't decided by the user. The + common failure is kSecTrustResultRecoverableTrustFailure, which means a + negative result. kSecTrustResultProceed and kSecTrustResultDeny are the + positive and negative result respectively when decided by the user. User + decisions are persisted through the use of SecTrustCopyExceptions() and + SecTrustSetExceptions(). Finally, kSecTrustResultFatalTrustFailure is a + negative result that must not be circumvented. + @constant kSecTrustResultInvalid Indicates an invalid setting or result. + This result usually means that SecTrustEvaluate has not yet been called. + @constant kSecTrustResultProceed Indicates you may proceed. This value + may be returned by the SecTrustEvaluate function or stored as part of + the user trust settings. + @constant kSecTrustResultConfirm Indicates confirmation with the user + is required before proceeding. Important: this value is no longer returned + or supported by SecTrustEvaluate or the SecTrustSettings API starting in + OS X 10.5; its use is deprecated in OS X 10.9 and later, as well as in iOS. + @constant kSecTrustResultDeny Indicates a user-configured deny; do not + proceed. This value may be returned by the SecTrustEvaluate function + or stored as part of the user trust settings. + @constant kSecTrustResultUnspecified Indicates the evaluation succeeded + and the certificate is implicitly trusted, but user intent was not + explicitly specified. This value may be returned by the SecTrustEvaluate + function or stored as part of the user trust settings. + @constant kSecTrustResultRecoverableTrustFailure Indicates a trust policy + failure which can be overridden by the user. This value may be returned + by the SecTrustEvaluate function but not stored as part of the user + trust settings. + @constant kSecTrustResultFatalTrustFailure Indicates a trust failure + which cannot be overridden by the user. This value may be returned by the + SecTrustEvaluate function but not stored as part of the user trust + settings. + @constant kSecTrustResultOtherError Indicates a failure other than that + of trust evaluation. This value may be returned by the SecTrustEvaluate + function but not stored as part of the user trust settings. + */ +typedef uint32_t SecTrustResultType; +enum { + kSecTrustResultInvalid = 0, + kSecTrustResultProceed = 1, + kSecTrustResultConfirm SEC_DEPRECATED_ATTRIBUTE = 2, + kSecTrustResultDeny = 3, + kSecTrustResultUnspecified = 4, + kSecTrustResultRecoverableTrustFailure = 5, + kSecTrustResultFatalTrustFailure = 6, + kSecTrustResultOtherError = 7 +}; + +/*! + @typedef SecTrustRef + @abstract CFType used for performing X.509 certificate trust evaluations. + */ +typedef struct __SecTrust *SecTrustRef; + +/*! + @enum Trust Property Constants + @discussion Predefined key constants used to obtain values in a + per-certificate dictionary of trust evaluation results, + as retrieved from a call to SecTrustCopyProperties. + @constant kSecPropertyTypeTitle Specifies a key whose value is a + CFStringRef containing the title (display name) of this certificate. + @constant kSecPropertyTypeError Specifies a key whose value is a + CFStringRef containing the reason for a trust evaluation failure. + */ +extern CFTypeRef kSecPropertyTypeTitle + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +extern CFTypeRef kSecPropertyTypeError + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); + +/*! + @enum Trust Result Constants + @discussion Predefined key constants used to obtain values in a + dictionary of trust evaluation results for a certificate chain, + as retrieved from a call to SecTrustCopyResult. + @constant kSecTrustEvaluationDate + This key will be present if a trust evaluation has been performed + and results are available. Its value is a CFDateRef representing + when the evaluation for this trust object took place. + @constant kSecTrustExtendedValidation + This key will be present and have a value of kCFBooleanTrue + if this chain was validated for EV. + @constant kSecTrustOrganizationName + Organization name field of subject of leaf certificate. This + field is meant to be displayed to the user as the validated + name of the company or entity that owns the certificate if the + kSecTrustExtendedValidation key is present. + @constant kSecTrustResultValue + This key will be present if a trust evaluation has been performed. + Its value is a CFNumberRef representing the SecTrustResultType result + for the evaluation. + @constant kSecTrustRevocationChecked + This key will be present iff this chain had its revocation checked. + The value will be a kCFBooleanTrue if revocation checking was + successful and none of the certificates in the chain were revoked. + The value will be kCFBooleanFalse if no current revocation status + could be obtained for one or more certificates in the chain due + to connection problems or timeouts. This is a hint to a client + to retry revocation checking at a later time. + @constant kSecTrustRevocationValidUntilDate + This key will be present iff kSecTrustRevocationChecked has a + value of kCFBooleanTrue. The value will be a CFDateRef representing + the earliest date at which the revocation info for one of the + certificates in this chain might change. + */ +extern CFTypeRef kSecTrustEvaluationDate + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecTrustExtendedValidation + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecTrustOrganizationName + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecTrustResultValue + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecTrustRevocationChecked + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern CFTypeRef kSecTrustRevocationValidUntilDate + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + +#ifdef __BLOCKS__ +/*! + @typedef SecTrustCallback + @abstract Delivers the result from an asynchronous trust evaluation. + @param trustRef A reference to the trust object which has been evaluated. + @param trustResult The trust result of the evaluation. Additional status + information can be obtained by calling SecTrustCopyProperties(). + */ +typedef void (^SecTrustCallback)(SecTrustRef trustRef, SecTrustResultType trustResult); +#endif /* __BLOCKS__ */ + + +/*! + @function SecTrustGetTypeID + @abstract Returns the type identifier of SecTrust instances. + @result The CFTypeID of SecTrust instances. + */ +CFTypeID SecTrustGetTypeID(void) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +/*! + @function SecTrustCreateWithCertificates + @abstract Creates a trust object based on the given certificates and + policies. + @param certificates The group of certificates to verify. This can either + be a CFArrayRef of SecCertificateRef objects or a single SecCertificateRef + @param policies An array of one or more policies. You may pass a + SecPolicyRef to represent a single policy. + @param trust On return, a pointer to the trust management reference. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion If multiple policies are passed in, all policies must verify + for the chain to be considered valid. + */ +OSStatus SecTrustCreateWithCertificates(CFTypeRef certificates, + CFTypeRef policies, SecTrustRef *trust) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +/*! + @function SecTrustSetPolicies + @abstract Set the policies for which trust should be verified. + @param trust A trust reference. + @param policies An array of one or more policies. You may pass a + SecPolicyRef to represent a single policy. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function will invalidate the existing trust result, + requiring a fresh evaluation for the newly-set policies. + */ +OSStatus SecTrustSetPolicies(SecTrustRef trust, CFTypeRef policies) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_6_0); + +/*! + @function SecTrustCopyPolicies + @abstract Returns an array of policies used for this evaluation. + @param trust A reference to a trust object. + @param policies On return, an array of policies used by this trust. + Call the CFRelease function to release this reference. + @result A result code. See "Security Error Codes" (SecBase.h). + */ +OSStatus SecTrustCopyPolicies(SecTrustRef trust, CFArrayRef *policies) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_7_0); + +/*! + @function SecTrustSetNetworkFetchAllowed + @abstract Specifies whether a trust evaluation is permitted to fetch missing + intermediate certificates from the network. + @param trust A trust reference. + @param allowFetch If true, and a certificate's issuer is not present in the + trust reference but its network location is known, the evaluation is permitted + to attempt to download it automatically. Pass false to disable network fetch + for this trust evaluation. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion By default, network fetch of missing certificates is enabled if + the trust evaluation includes the SSL policy, otherwise it is disabled. + */ +OSStatus SecTrustSetNetworkFetchAllowed(SecTrustRef trust, + Boolean allowFetch) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + +/*! + @function SecTrustGetNetworkFetchAllowed + @abstract Returns whether a trust evaluation is permitted to fetch missing + intermediate certificates from the network. + @param trust A trust reference. + @param allowFetch On return, the boolean pointed to by this parameter is + set to true if the evaluation is permitted to download missing certificates. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion By default, network fetch of missing certificates is enabled if + the trust evaluation includes the SSL policy, otherwise it is disabled. + */ +OSStatus SecTrustGetNetworkFetchAllowed(SecTrustRef trust, + Boolean *allowFetch) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + +/*! + @function SecTrustSetAnchorCertificates + @abstract Sets the anchor certificates for a given trust. + @param trust A reference to a trust object. + @param anchorCertificates An array of anchor certificates. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Calling this function without also calling + SecTrustSetAnchorCertificatesOnly() will disable trusting any + anchors other than the ones in anchorCertificates. + */ +OSStatus SecTrustSetAnchorCertificates(SecTrustRef trust, + CFArrayRef anchorCertificates) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +/*! + @function SecTrustSetAnchorCertificatesOnly + @abstract Reenables trusting anchor certificates in addition to those + passed in via the SecTrustSetAnchorCertificates API. + @param trust A reference to a trust object. + @param anchorCertificatesOnly If true, disables trusting any anchors other + than the ones passed in via SecTrustSetAnchorCertificates(). If false, + the built in anchor certificates are also trusted. + @result A result code. See "Security Error Codes" (SecBase.h). + */ +OSStatus SecTrustSetAnchorCertificatesOnly(SecTrustRef trust, + Boolean anchorCertificatesOnly) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @function SecTrustCopyCustomAnchorCertificates + @abstract Returns an array of custom anchor certificates used by a given + trust, as set by a prior call to SecTrustSetAnchorCertificates, or NULL if + no custom anchors have been specified. + @param trust A reference to a trust object. + @param anchors On return, an array of custom anchor certificates (roots) + used by this trust, or NULL if no custom anchors have been specified. Call + the CFRelease function to release this reference. + @result A result code. See "Security Error Codes" (SecBase.h). + */ +OSStatus SecTrustCopyCustomAnchorCertificates(SecTrustRef trust, + CFArrayRef *anchors) + __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_7_0); + +/*! + @function SecTrustSetVerifyDate + @abstract Set the date for which the trust should be verified. + @param trust A reference to a trust object. + @param verifyDate The date for which to verify trust. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function lets you evaluate certificate validity for a + given date (for example, to determine if a signature was valid on the date + it was signed, even if the certificate has since expired.) If this function + is not called, the time at which SecTrustEvaluate() is called is used + implicitly as the verification time. + */ +OSStatus SecTrustSetVerifyDate(SecTrustRef trust, CFDateRef verifyDate) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +/*! + @function SecTrustGetVerifyTime + @abstract Returns the verify time. + @param trust A reference to the trust object being verified. + @result A CFAbsoluteTime value representing the time at which certificates + should be checked for validity. + @discussion This function retrieves the verification time for the given + trust reference, as set by a prior call to SecTrustSetVerifyDate(). If the + verification time has not been set, this function returns a value of 0, + indicating that the current date/time is implicitly used for verification. + */ +CFAbsoluteTime SecTrustGetVerifyTime(SecTrustRef trust) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + +/*! + @function SecTrustEvaluate + @abstract Evaluates a trust reference synchronously. + @param trust A reference to the trust object to evaluate. + @param result A pointer to a result type. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function will completely evaluate trust before returning, + possibly including network access to fetch intermediate certificates or to + perform revocation checking. Since this function can block during those + operations, you should call it from within a function that is placed on a + dispatch queue, or in a separate thread from your application's main + run loop. Alternatively, you can use the SecTrustEvaluateAsync function. + */ +OSStatus SecTrustEvaluate(SecTrustRef trust, SecTrustResultType *result) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + +#ifdef __BLOCKS__ +/*! + @function SecTrustEvaluateAsync + @abstract Evaluates a trust reference asynchronously. + @param trust A reference to the trust object to evaluate. + @param queue A dispatch queue on which the result callback should be + executed. Pass NULL to use the current dispatch queue. + @param result A SecTrustCallback block which will be executed when the + trust evaluation is complete. + @result A result code. See "Security Error Codes" (SecBase.h). + */ +OSStatus SecTrustEvaluateAsync(SecTrustRef trust, + dispatch_queue_t queue, SecTrustCallback result) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +#endif + +/*! + @function SecTrustGetTrustResult + @param trust A reference to a trust object. + @param result A pointer to the result from the most recent call to + SecTrustEvaluate for this trust reference. If SecTrustEvaluate has not been + called or trust parameters have changed, the result is kSecTrustResultInvalid. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function replaces SecTrustGetResult for the purpose of + obtaining the current evaluation result of a given trust reference. + */ +OSStatus SecTrustGetTrustResult(SecTrustRef trust, + SecTrustResultType *result) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); + +/*! + @function SecTrustCopyPublicKey + @abstract Return the public key for a leaf certificate after it has + been evaluated. + @param trust A reference to the trust object which has been evaluated. + @result The certificate's public key, or NULL if it the public key could + not be extracted (this can happen with DSA certificate chains if the + parameters in the chain cannot be found). The caller is responsible + for calling CFRelease on the returned key when it is no longer needed. + */ +SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + +/*! + @function SecTrustGetCertificateCount + @abstract Returns the number of certificates in an evaluated certificate + chain. + @param trust A reference to a trust object. + @result The number of certificates in the trust chain, including the anchor. + @discussion Important: if the trust reference has not yet been evaluated, + this function will evaluate it first before returning. If speed is critical, + you may want to call SecTrustGetTrustResult first to make sure that a + result other than kSecTrustResultInvalid is present for the trust object. + */ +CFIndex SecTrustGetCertificateCount(SecTrustRef trust) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + +/*! + @function SecTrustGetCertificateAtIndex + @abstract Returns a certificate from the trust chain. + @param trust Reference to a trust object. + @param ix The index of the requested certificate. Indices run from 0 + (leaf) to the anchor (or last certificate found if no anchor was found). + The leaf cert (index 0) is always present regardless of whether the trust + reference has been evaluated or not. + @result A SecCertificateRef for the requested certificate. + */ +SecCertificateRef SecTrustGetCertificateAtIndex(SecTrustRef trust, CFIndex ix) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + +/*! + @function SecTrustCopyExceptions + @abstract Returns an opaque cookie which will allow future evaluations + of the current certificate to succeed. + @param trust A reference to an evaluated trust object. + @result An opaque cookie which when passed to SecTrustSetExceptions() will + cause a call to SecTrustEvaluate() return kSecTrustResultProceed. This + will happen upon subsequent evaluation of the current certificate unless + some new error starts happening that wasn't being reported when the cookie + was returned from this function (for example, if the certificate expires + then evaluation will start failing again until a new cookie is obtained.) + @discussion Normally this API should only be called once the errors have + been presented to the user and the user decided to trust the current + certificate chain regardless of the errors being presented, for the + current application/server/protocol combination. + */ +CFDataRef SecTrustCopyExceptions(SecTrustRef trust) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); + +/*! + @function SecTrustSetExceptions + @abstract Set a trust cookie to be used for evaluating this certificate chain. + @param trust A reference to a trust object. + @param exceptions An exceptions cookie as returned by a call to + SecTrustCopyExceptions() in the past. + @result Upon calling SecTrustEvaluate(), any failures that where present at the + time the exceptions object was created are ignored, and instead of returning + kSecTrustResultRecoverableTrustFailure, kSecTrustResultProceed will be returned + (if the certificate for which exceptions was created matches the current leaf + certificate). + @result Returns true if the exceptions cookies was valid and matches the current + leaf certificate, false otherwise. This function will invalidate the existing + trust result, requiring a subsequent evaluation for the newly-set exceptions. + Note that this function returning true doesn't mean the caller can skip calling + SecTrustEvaluate, as there may be new errors since the exceptions cookie was + created (for example, a certificate may have subsequently expired.) + @discussion Clients of this interface will need to establish the context of this + exception to later decide when this exception cookie is to be used. + Examples of this context would be the server we are connecting to, the ssid + of the wireless network for which this cert is needed, the account for which + this cert should be considered valid, and so on. + */ +bool SecTrustSetExceptions(SecTrustRef trust, CFDataRef exceptions) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); + +/*! + @function SecTrustCopyProperties + @abstract Return a property array for this trust evaluation. + @param trust A reference to a trust object. If the trust has not been + evaluated, the returned property array will be empty. + @result A property array. It is the caller's responsibility to CFRelease + the returned array when it is no longer needed. + @discussion This function returns an ordered array of CFDictionaryRef + instances for each certificate in the chain. Indices run from 0 (leaf) to + the anchor (or last certificate found if no anchor was found.) See the + "Trust Property Constants" section for a list of currently defined keys. + */ +CFArrayRef SecTrustCopyProperties(SecTrustRef trust) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + +/*! + @function SecTrustCopyResult + @abstract Returns a dictionary containing information about the + evaluated certificate chain for use by clients. + @param trust A reference to a trust object. + @result A dictionary with various fields that can be displayed to the user, + or NULL if no additional info is available or the trust has not yet been + validated. The caller is responsible for calling CFRelease on the value + returned when it is no longer needed. + @discussion Returns a dictionary for the overall trust evaluation. See the + "Trust Result Constants" section for a list of currently defined keys. + */ +CFDictionaryRef SecTrustCopyResult(SecTrustRef trust) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + +/*! + @function SecTrustSetOCSPResponse + @abstract Attach OCSPResponse data to a trust object. + @param trust A reference to a trust object. + @param responseData This may be either a CFData object containing a single + DER-encoded OCSPResponse (per RFC 2560), or a CFArray of these. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Allows the caller to provide OCSPResponse data (which may be + obtained during a TLS/SSL handshake, per RFC 3546) as input to a trust + evaluation. If this data is available, it can obviate the need to contact + an OCSP server for current revocation information. + */ +OSStatus SecTrustSetOCSPResponse(SecTrustRef trust, CFTypeRef responseData) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + + +/* + * Legacy functions (OS X only) + */ +#if TARGET_OS_MAC && !TARGET_OS_IPHONE +#include +#include + +/*! + @typedef SecTrustUserSetting + @abstract Specifies a user-specified trust setting value. + @discussion Deprecated in OS X 10.9. User trust settings are managed by + functions in SecTrustSettings.h (starting with OS X 10.5), and by the + SecTrustCopyExceptions and SecTrustSetExceptions functions (starting with + iOS 4 and OS X 10.9). The latter two functions are recommended for both OS X + and iOS, as they avoid the need to explicitly specify these values. + */ +typedef SecTrustResultType SecTrustUserSetting + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); + +/*! + @typedef SecTrustOptionFlags + @abstract Options for customizing trust evaluation. + @constant kSecTrustOptionAllowExpired Allow expired certificates. + @constant kSecTrustOptionLeafIsCA Allow CA as leaf certificate. + @constant kSecTrustOptionFetchIssuerFromNet Allow network fetch of CA cert. + @constant kSecTrustOptionAllowExpiredRoot Allow expired roots. + @constant kSecTrustOptionRequireRevPerCert Require positive revocation + check per certificate. + @constant kSecTrustOptionUseTrustSettings Use TrustSettings instead of + anchors. + @constant kSecTrustOptionImplicitAnchors Properly self-signed certs are + treated as anchors implicitly. + */ +typedef uint32_t SecTrustOptionFlags; +enum { + kSecTrustOptionAllowExpired = 0x00000001, + kSecTrustOptionLeafIsCA = 0x00000002, + kSecTrustOptionFetchIssuerFromNet = 0x00000004, + kSecTrustOptionAllowExpiredRoot = 0x00000008, + kSecTrustOptionRequireRevPerCert = 0x00000010, + kSecTrustOptionUseTrustSettings = 0x00000020, + kSecTrustOptionImplicitAnchors = 0x00000040 +}; + +/*! + @function SecTrustSetOptions + @abstract Sets optional flags for customizing a trust evaluation. + @param trustRef A trust reference. + @param options Flags to change evaluation behavior for this trust. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is not available on iOS. Use SecTrustSetExceptions + and SecTrustCopyExceptions to modify default trust results, and + SecTrustSetNetworkFetchAllowed to specify whether missing CA certificates + can be fetched from the network. + */ +OSStatus SecTrustSetOptions(SecTrustRef trustRef, SecTrustOptionFlags options) + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +/*! + @function SecTrustSetParameters + @abstract Sets the action and action data for a trust object. + @param trustRef The reference to the trust to change. + @param action A trust action. + @param actionData A reference to data associated with this action. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in OS X 10.7 and later, where it + was replaced by SecTrustSetOptions, and is not available on iOS. Your code + should use SecTrustSetExceptions and SecTrustCopyExceptions to modify default + trust results, and SecTrustSetNetworkFetchAllowed to specify whether missing + CA certificates can be fetched from the network. + */ +OSStatus SecTrustSetParameters(SecTrustRef trustRef, + CSSM_TP_ACTION action, CFDataRef actionData) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecTrustSetKeychains + @abstract Sets the keychains for a given trust object. + @param trust A reference to a trust object. + @param keychainOrArray A reference to an array of keychains to search, a + single keychain, or NULL to use the default keychain search list. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion By default, the user's keychain search list and the system + anchors keychain are searched for certificates to complete the chain. You + can specify a zero-element array if you do not want any keychains searched. + Note: this function is not applicable to iOS. + */ +OSStatus SecTrustSetKeychains(SecTrustRef trust, CFTypeRef keychainOrArray) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); + +/*! + @function SecTrustGetResult + @abstract Returns detailed information on the outcome of an evaluation. + @param trustRef A reference to a trust object. + @param result A pointer to the result from the call to SecTrustEvaluate. + @param certChain On return, a pointer to the certificate chain used to + validate the input certificate. Call the CFRelease function to release + this pointer. + @param statusChain On return, a pointer to the status of the certificate + chain. Do not attempt to free this pointer; it remains valid until the + trust is destroyed or the next call to SecTrustEvaluate. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in OS X 10.7 and later, + and is not available on iOS. + To get the complete certificate chain, use SecTrustGetCertificateCount and + SecTrustGetCertificateAtIndex. To get detailed status information for each + certificate, use SecTrustCopyProperties. To get the overall trust result + for the evaluation, use SecTrustGetTrustResult. + */ +OSStatus SecTrustGetResult(SecTrustRef trustRef, SecTrustResultType *result, + CFArrayRef *certChain, CSSM_TP_APPLE_EVIDENCE_INFO **statusChain) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecTrustGetCssmResult + @abstract Gets the CSSM trust result. + @param trust A reference to a trust. + @param result On return, a pointer to the CSSM trust result. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in OS X 10.7 and later, + and is not available on iOS. + To get detailed status information for each certificate, use + SecTrustCopyProperties. To get the overall trust result for the evaluation, + use SecTrustGetTrustResult. + */ +OSStatus SecTrustGetCssmResult(SecTrustRef trust, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR *result) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecTrustGetCssmResultCode + @abstract Gets the result code from the most recent call to SecTrustEvaluate + for the specified trust. + @param trust A reference to a trust. + @param resultCode On return, the result code produced by the most recent + evaluation of the given trust (cssmerr.h). The value of resultCode is + undefined if SecTrustEvaluate has not been called. + @result A result code. See "Security Error Codes" (SecBase.h). Returns + errSecTrustNotAvailable if SecTrustEvaluate has not been called for the + specified trust. + @discussion This function is deprecated in OS X 10.7 and later, + and is not available on iOS. + To get detailed status information for each certificate, use + SecTrustCopyProperties. To get the overall trust result for the evaluation, + use SecTrustGetTrustResult. + */ +OSStatus SecTrustGetCssmResultCode(SecTrustRef trust, OSStatus *resultCode) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecTrustGetTPHandle + @abstract Gets the CSSM trust handle + @param trust A reference to a trust. + @param handle On return, a CSSM trust handle. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is deprecated in OS X 10.7 and later. + */ +OSStatus SecTrustGetTPHandle(SecTrustRef trust, CSSM_TP_HANDLE *handle) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + +/*! + @function SecTrustCopyAnchorCertificates + @abstract Returns an array of default anchor (root) certificates used by + the system. + @param anchors On return, an array containing the system's default anchors + (roots). Call the CFRelease function to release this pointer. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function is not available on iOS, as certificate data + for system-trusted roots is currently unavailable on that platform. + */ +OSStatus SecTrustCopyAnchorCertificates(CFArrayRef *anchors) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); + +#endif /* TARGET_OS_MAC && !TARGET_OS_IPHONE */ + + +__END_DECLS + +#endif /* !_SECURITY_SECTRUST_H_ */ diff --git a/Security/sec/Security/SecTrustPriv.h b/Security/sec/Security/SecTrustPriv.h new file mode 100644 index 00000000..72dae004 --- /dev/null +++ b/Security/sec/Security/SecTrustPriv.h @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2008-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecTrustPriv + The functions and data types in SecTrustPriv implement trust computation + and allow the user to apply trust decisions to the trust configuration. +*/ + +#ifndef _SECURITY_SECTRUSTPRIV_H_ +#define _SECURITY_SECTRUSTPRIV_H_ + +#include +#include +#include + +__BEGIN_DECLS + +typedef enum { + useNetworkDefault, // default policy: network fetch enabled only for SSL + useNetworkDisabled, // explicitly disable network use for any policy + useNetworkEnabled // explicitly enable network use for any policy +} SecNetworkPolicy; + +/* Constants used as keys in property lists. See + SecTrustCopySummaryPropertiesAtIndex for more information. */ +extern CFTypeRef kSecPropertyKeyType; +extern CFTypeRef kSecPropertyKeyLabel; +extern CFTypeRef kSecPropertyKeyLocalizedLabel; +extern CFTypeRef kSecPropertyKeyValue; + +extern CFTypeRef kSecPropertyTypeWarning; +extern CFTypeRef kSecPropertyTypeSuccess; +extern CFTypeRef kSecPropertyTypeSection; +extern CFTypeRef kSecPropertyTypeData; +extern CFTypeRef kSecPropertyTypeString; +extern CFTypeRef kSecPropertyTypeURL; +extern CFTypeRef kSecPropertyTypeDate; + +/* Constants used as keys in the dictionary returned by SecTrustCopyInfo. */ +extern CFTypeRef kSecTrustInfoExtendedValidationKey; +extern CFTypeRef kSecTrustInfoCompanyNameKey; +extern CFTypeRef kSecTrustInfoRevocationKey; +extern CFTypeRef kSecTrustInfoRevocationValidUntilKey; + +/*! + @function SecTrustCopySummaryPropertiesAtIndex + @abstract Return a property array for the certificate. + @param trust A reference to the trust object to evaluate. + @param ix The index of the requested certificate. Indices run from 0 + (leaf) to the anchor (or last certificate found if no anchor was found). + @result A property array. It is the caller's responsibility to CFRelease + the returned array when it is no longer needed. This function returns a + short summary description of the certificate in question. The property + at index 0 of the array might also include general information about the + entire chain's validity in the context of this trust evaluation. + + @discussion Returns a property array for this trust certificate. A property + array is an array of CFDictionaryRefs. Each dictionary (we call it a + property for short) has the following keys: + + kSecPropertyKeyType This key's value determines how this property + should be displayed. Its associated value is one of the + following: + kSecPropertyTypeWarning + The kSecPropertyKeyLocalizedLabel and kSecPropertyKeyLabel keys are not + set. The kSecPropertyKeyValue is a CFStringRef which should + be displayed in yellow with a warning triangle. + kSecPropertyTypeError + The kSecPropertyKeyLocalizedLabel and kSecPropertyKeyLabel keys are not + set. The kSecPropertyKeyValue is a CFStringRef which should + be displayed in red with an error X. + kSecPropertyTypeSuccess + The kSecPropertyKeyLocalizedLabel and kSecPropertyKeyLabel keys are not + set. The kSecPropertyKeyValue is a CFStringRef which should + be displayed in green with a checkmark in front of it. + kSecPropertyTypeTitle + The kSecPropertyKeyLocalizedLabel and kSecPropertyKeyLabel keys are not + set. The kSecPropertyKeyValue is a CFStringRef which should + be displayed in a larger bold font. + kSecPropertyTypeSection + The optional kSecPropertyKeyLocalizedLabel is a CFStringRef with the name + of the next section to display. The value of the + kSecPropertyKeyValue key is a CFArrayRef which is a property + array as defined here. + kSecPropertyTypeData + The optional kSecPropertyKeyLocalizedLabel is a CFStringRef containing + the localized label for the value for the kSecPropertyKeyValue. + The type of this value is a CFDataRef. Its contents should be + displayed as: "bytes length_of_data : hexdump_of_data". Ideally + the UI will only show one line of hex dump data and have a + disclosure arrow to see the remainder. + kSecPropertyTypeString + The optional kSecPropertyKeyLocalizedLabel is a CFStringRef containing + the localized label for the value for the kSecPropertyKeyValue. + The type of this value is a CFStringRef. It's contents should be + displayed in the normal font. + kSecPropertyTypeURL + The optional kSecPropertyKeyLocalizedLabel is a CFStringRef containing + the localized label for the value for the kSecPropertyKeyValue. + The type of this value is a CFURLRef. It's contents should be + displayed as a hyperlink. + kSecPropertyTypeDate + The optional kSecPropertyKeyLocalizedLabel is a CFStringRef containing + the localized label for the value for the kSecPropertyKeyValue. + The type of this value is a CFDateRef. It's contents should be + displayed in human readable form (probably in the current + timezone). + kSecPropertyKeyLocalizedLabel + Human readable localized label for a given property. + kSecPropertyKeyValue + See description of kSecPropertyKeyType to determine what the value + for this key is. + kSecPropertyKeyLabel + Non localized key (label) for this value. This is only + present for properties with fixed label names. + @param certificate A reference to the certificate to evaluate. + @result A property array. It is the caller's responsability to CFRelease + the returned array when it is no longer needed. +*/ +CFArrayRef SecTrustCopySummaryPropertiesAtIndex(SecTrustRef trust, CFIndex ix); + +/*! + @function SecTrustCopyDetailedPropertiesAtIndex + @abstract Return a property array for the certificate. + @param trust A reference to the trust object to evaluate. + @param ix The index of the requested certificate. Indices run from 0 + (leaf) to the anchor (or last certificate found if no anchor was found). + @result A property array. It is the caller's responsibility to CFRelease + the returned array when it is no longer needed. + See SecTrustCopySummaryPropertiesAtIndex on how to intepret this array. + Unlike that function call this function returns a detailed description + of the certificate in question. +*/ +CFArrayRef SecTrustCopyDetailedPropertiesAtIndex(SecTrustRef trust, CFIndex ix); + +/*! + @function SecTrustCopyProperties + @abstract Return a property array for this trust evaluation. + @param trust A reference to the trust object to evaluate. + @result A property array. It is the caller's responsibility to CFRelease + the returned array when it is no longer needed. See + SecTrustCopySummaryPropertiesAtIndex for a detailed description of this array. + Unlike that function, this function returns a short text string suitable for + display in a sheet explaining to the user why this certificate chain is + not trusted for this operation. This function may return NULL if the + certificate chain was trusted. +*/ +CFArrayRef SecTrustCopyProperties(SecTrustRef trust); + +/*! + @function SecTrustCopyInfo + @abstract Return a dictionary with additional information about the + evaluated certificate chain for use by clients. + @param trust A reference to an evaluated trust object. + @discussion Returns a dictionary for this trust evaluation. This + dictionary may have the following keys: + + kSecTrustInfoExtendedValidationKey this key will be present and have + a value of kCFBooleanTrue if this chain was validated for EV. + kSecTrustInfoCompanyNameKey Company name field of subject of leaf + certificate, this field is meant to be displayed to the user + if the kSecTrustInfoExtendedValidationKey is present. + kSecTrustInfoRevocationKey this key will be present iff this chain + had its revocation checked. The value will be a kCFBooleanTrue + if revocation checking was successful and none of the + certificates in the chain were revoked. + The value will be kCFBooleanFalse if no current revocation status + could be obtained for one or more certificates in the chain due + to connection problems or timeouts etc. This is a hint to a + client to retry revocation checking at a later time. + kSecTrustInfoRevocationValidUntilKey this key will be present iff + kSecTrustInfoRevocationKey has a value of kCFBooleanTrue. + The value will be a CFDateRef representing the earliest date at + which the revocation info for one of the certificates in this chain + might change. + + @result A dictionary with various fields that can be displayed to the user, + or NULL if no additional info is available or the trust has not yet been + validated. The caller is responsible for calling CFRelease on the value + returned when it is no longer needed. +*/ +CFDictionaryRef SecTrustCopyInfo(SecTrustRef trust); + +/* For debugging purposes. */ +CFArrayRef SecTrustGetDetails(SecTrustRef trust); + +/* For debugging purposes. */ +CFStringRef SecTrustCopyFailureDescription(SecTrustRef trust); + +/*! + @function SecTrustSetPolicies + @abstract Set the trust policies against which the trust should be verified. + @param trust A reference to a trust object. + @param policies An array of one or more policies. You may pass a + SecPolicyRef to represent a single policy. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function does not invalidate the trust, but should do so in the future. +*/ +OSStatus SecTrustSetPolicies(SecTrustRef trust, CFTypeRef policies) + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_6_0); + +OSStatus SecTrustGetOTAPKIAssetVersionNumber(int* versionNumber); + +OSStatus SecTrustOTAPKIGetUpdatedAsset(int* didUpdateAsset); + +__END_DECLS + +#endif /* !_SECURITY_SECTRUSTPRIV_H_ */ diff --git a/sec/Security/SecTrustSettings.c b/Security/sec/Security/SecTrustSettings.c similarity index 94% rename from sec/Security/SecTrustSettings.c rename to Security/sec/Security/SecTrustSettings.c index a27cc9e3..92fb3354 100644 --- a/sec/Security/SecTrustSettings.c +++ b/Security/sec/Security/SecTrustSettings.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2008,2010,2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -34,6 +34,7 @@ #include "SecBasePriv.h" #include #include +#include #define trustSettingsDbg(args...) secdebug("trustSettings", ## args) #define trustSettingsEvalDbg(args...) secdebug("trustSettingsEval", ## args) @@ -130,9 +131,11 @@ struct __SecTrustSettings { bool _dirty; /* we've changed _trustDict since creation */ }; -/* CFRuntime regsitration data. */ -static pthread_once_t kSecTrustSettingsRegisterClass = PTHREAD_ONCE_INIT; -static CFTypeID kSecTrustSettingsTypeID = _kCFRuntimeNotATypeID; +static CFStringRef SecTrustSettingsCopyDescription(CFTypeRef cf) { + SecTrustSettingsRef ts = (SecTrustSettingsRef)cf; + return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, + CFSTR(""), ts); +} static void SecTrustSettingsDestroy(CFTypeRef cf) { SecTrustSettingsRef ts = (SecTrustSettingsRef) cf; @@ -140,27 +143,8 @@ static void SecTrustSettingsDestroy(CFTypeRef cf) { CFReleaseSafe(ts->_trustDict); } -static void SecTrustSettingsRegisterClass(void) { - static const CFRuntimeClass kSecTrustSettingsClass = { - 0, /* version */ - "SecTrustSettings", /* class name */ - NULL, /* init */ - NULL, /* copy */ - SecTrustSettingsDestroy, /* dealloc */ - NULL, /* equal */ - NULL, /* hash */ - NULL, /* copyFormattingDesc */ - NULL /* copyDebugDesc */ - }; - - kSecTrustSettingsTypeID = _CFRuntimeRegisterClass(&kSecTrustSettingsClass); -} - /* SecTrustSettings API functions. */ -CFTypeID SecTrustSettingsGetTypeID(void) { - pthread_once(&kSecTrustSettingsRegisterClass, SecTrustSettingsRegisterClass); - return kSecTrustSettingsTypeID; -} +CFGiblisFor(SecTrustSettings) /* Make sure a presumed CFNumber can be converted to a 32-bit number */ static bool tsIsGoodCfNum(CFNumberRef cfn, SInt32 *num) diff --git a/Security/sec/Security/SecTrustSettings.h b/Security/sec/Security/SecTrustSettings.h new file mode 100644 index 00000000..eb9a3d5c --- /dev/null +++ b/Security/sec/Security/SecTrustSettings.h @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2007,2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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 SecTrustSettings + The functions and data types in SecTrustSettings implement a way to + set and retrive trustability of certificates. +*/ + +#ifndef _SECURITY_SECTRUSTSETTINGS_H_ +#define _SECURITY_SECTRUSTSETTINGS_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Any certificate (cert) which resides in a keychain can have associated with + * it a set of Trust Settings. Trust Settings specify conditions in which a + * given cert can be trusted or explicitly distrusted. A "trusted" cert is + * either a root (self-signed) cert that, when a cert chain verifies back to that + * root, the entire cert chain is trusted; or a non-root cert that does not need + * to verify to a trusted root cert (which is normally the case when verifying a + * cert chain). An "explicitly distrusted" cert is one which will, when encountered + * during the evaluation of a cert chain, cause immediate and unconditional failure + * of the verify operation. + * + * Trust Settings are configurable by the user; they can apply on three levels + * (called domains): + * + * -- Per-user. + * -- Locally administered, system-wide. Administrator privileges are required + * to make changes to this domain. + * -- System. These Trust Settings are immutable and comprise the set of trusted + * root certificates supplied in Mac OS X. + * + * Per-user Trust Settings override locally administered Trust Settings, which + * in turn override the System Trust Settings. + * + * Each cert's Trust Settings are expressed as a CFArray which includes any + * number (including zero) of CFDictionaries, each of which comprises one set of + * Usage Constraints. Each Usage Constraints dictionary contains zero or one of + * each the following components: + * + * key = kSecTrustSettingsPolicy value = SecPolicyRef + * key = kSecTrustSettingsApplication value = SecTrustedApplicationRef + * key = kSecTrustSettingsPolicyString value = CFString, policy-specific + * key = kSecTrustSettingsKeyUsage value = CFNumber, an SInt32 key usage + * + * A given Usage Constraints dictionary applies to a given cert if *all* of the + * usage constraint components specified in the dictionary match the usage of + * the cert being evaluated; when this occurs, the value of the + * kSecTrustSettingsResult entry in the dictionary, shown below, is the effective + * trust setting for the cert. + * + * key = kSecTrustSettingsResult value = CFNumber, an SInt32 SecTrustSettingsResult + * + * The overall Trust Settings of a given cert are the sum of all such Usage + * Constraints CFDictionaries: Trust Settings for a given usage apply if *any* + * of the CFDictionaries in the cert's Trust Settings array satisfies + * the specified usage. Thus, when a cert has multiple Usage Constraints + * dictionaries in its Trust Settings array, the overall Trust Settings + * for the cert are + * + * (Usage Constraint 0 component 0 AND Usage Constraint 0 component 1 ...) + * -- OR -- + * (Usage Constraint 1 component 0 AND Usage Constraint 1 component 1 ...) + * -- OR -- + * ... + * + * Notes on the various Usage Constraints components: + * + * kSecTrustSettingsPolicy Specifies a cert verification policy, e.g., SSL, + * SMIME, etc. + * kSecTrustSettingsApplication Specifies the application performing the cert + * verification. + * kSecTrustSettingsPolicyString Policy-specific. For the SMIME policy, this is + * an email address. + * For the SSL policy, this is a host name. + * kSecTrustSettingsKeyUsage A bitfield indicating key operations (sign, + * encrypt, etc.) for which this Usage Constraint + * apply. Values are defined below as the + * SecTrustSettingsKeyUsage enum. + * kSecTrustSettingsResult The resulting trust value. If not present this has a + * default of kSecTrustSettingsResultTrustRoot, meaning + * "trust this root cert". Other legal values are: + * kSecTrustSettingsResultTrustAsRoot : trust non-root + * cert as if it were a trusted root. + * kSecTrustSettingsResultDeny : explicitly distrust this + * cert. + * kSecTrustSettingsResultUnspecified : neither trust nor + * distrust; can be used to specify an "Allowed error" + * (see below) without assigning trust to a specific + * cert. + * + * Another optional component in a Usage Constraints dictionary is a CSSM_RETURN + * which, if encountered during certificate verification, is ignored for that + * cert. These "allowed error" values are constrained by Usage Constraints as + * described above; a Usage Constraint dictionary with no constraints but with + * an Allowed Error value causes that error to always be allowed when the cert + * is being evaluated. + * + * The "allowed error" entry in a Usage Constraints dictionary is formatted + * as follows: + * + * key = kSecTrustSettingsAllowedError value = CFNumber, an SInt32 CSSM_RETURN + * + * Note that if kSecTrustSettingsResult value of kSecTrustSettingsResultUnspecified + * is *not* present for a Usage Constraints dictionary with no Usage + * Constraints, the default of kSecTrustSettingsResultTrustRoot is assumed. To + * specify a kSecTrustSettingsAllowedError without explicitly trusting (or + * distrusting) the associated cert, specify kSecTrustSettingsResultUnspecified + * for the kSecTrustSettingsResult component. + * + * Note that an empty Trust Settings array means "always trust this cert, + * with a resulting kSecTrustSettingsResult of kSecTrustSettingsResultTrustRoot". + * An empty Trust Settings array is definitely not the same as *no* Trust + * Settings, which means "this cert must be verified to a known trusted cert". + * + * Note the distinction between kSecTrustSettingsResultTrustRoot and + * kSecTrustSettingsResultTrustAsRoot; the former can only be applied to + * root (self-signed) certs; the latter can only be applied to non-root + * certs. This also means that an empty TrustSettings array for a non-root + * cert is invalid, since the default value for kSecTrustSettingsResult is + * kSecTrustSettingsResultTrustRoot, which is invalid for a non-root cert. + * + * Authentication + * -------------- + * + * When making changes to the per-user Trust Settings, the user will be + * prompted with an alert panel asking for authentication via user name a + * password (or other credentials normally used for login). This means + * that it is not possible to modify per-user Trust Settings when not + * running in a GUI environment (i.e. the user is not logged in via + * Loginwindow). + * + * When making changes to the system-wide Trust Settings, the user will be + * prompted with an alert panel asking for an administrator's name and + * password, unless the calling process is running as root in which case + * no futher authentication is needed. + */ + +/* + * The keys in one Usage Constraints dictionary. + */ +#define kSecTrustSettingsPolicy CFSTR("kSecTrustSettingsPolicy") +#define kSecTrustSettingsApplication CFSTR("kSecTrustSettingsApplication") +#define kSecTrustSettingsPolicyString CFSTR("kSecTrustSettingsPolicyString") +#define kSecTrustSettingsKeyUsage CFSTR("kSecTrustSettingsKeyUsage") +#define kSecTrustSettingsAllowedError CFSTR("kSecTrustSettingsAllowedError") +#define kSecTrustSettingsResult CFSTR("kSecTrustSettingsResult") + +/* + * Key usage bits, the value for Usage Constraints key kSecTrustSettingsKeyUsage. + */ +enum { + /* sign/verify data */ + kSecTrustSettingsKeyUseSignature = 0x00000001, + /* bulk encryption */ + kSecTrustSettingsKeyUseEnDecryptData = 0x00000002, + /* key wrap/unwrap */ + kSecTrustSettingsKeyUseEnDecryptKey = 0x00000004, + /* sign/verify cert */ + kSecTrustSettingsKeyUseSignCert = 0x00000008, + /* sign/verify CRL and OCSP */ + kSecTrustSettingsKeyUseSignRevocation = 0x00000010, + /* key exchange, e.g., Diffie-Hellman */ + kSecTrustSettingsKeyUseKeyExchange = 0x00000020, + /* any usage (the default if this value is not specified) */ + kSecTrustSettingsKeyUseAny = 0xffffffff +}; +typedef uint32_t SecTrustSettingsKeyUsage; + +/*! + @enum SecTrustSettingsResult + @abstract Result of a trust settings evaluation. +*/ +enum { + kSecTrustSettingsResultInvalid = 0, /* Never valid in a Trust Settings array or + * in an API call. */ + kSecTrustSettingsResultTrustRoot, /* Root cert is explicitly trusted */ + kSecTrustSettingsResultTrustAsRoot, /* Non-root cert is explicitly trusted */ + kSecTrustSettingsResultDeny, /* Cert is explicitly distrusted */ + kSecTrustSettingsResultUnspecified /* Neither trusted nor distrusted; evaluation + * proceeds as usual */ +}; +typedef uint32_t SecTrustSettingsResult; + +/* + * Specify user, local administrator, or system domain Trust Properties. + * Note that kSecTrustSettingsDomainSystem settings are read-only, even by + * root. + */ +enum { + kSecTrustSettingsDomainUser = 0, + kSecTrustSettingsDomainAdmin, + kSecTrustSettingsDomainSystem +}; +typedef uint32_t SecTrustSettingsDomain; + +/* + * SecCertificateRef value indicating the default Root Certificate Trust Settings + * for a given domain. When evaluating Trust Settings for a root cert in + * a given domain, *and* no matching explicit Trust Settings exists for the + * root cert in questions, *and* default Root Cert Trust Settings exist + * in that domain which matches the evaluation condition, then the + * SecTrustSettingsResult for that default Trust Setting (if not + * kSecTrustSettingsResultUnspecified) will apply. + * + * This can be used e.g. by a system administrator to explicilty distrust all + * of the root certs in the (immutable) system domain for a specific policy. + * + * This const is passed as the 'SecCertificateRef certRef' argument to + * SecTrustSettingsCopyTrustSettings(), SecTrustSettingsSetTrustSettings(), + * and SecTrustSettingsRemoveTrustSettings(), and + * SecTrustSettingsCopyModificationDate(). + */ +#define kSecTrustSettingsDefaultRootCertSetting ((SecCertificateRef)-1) + +#ifdef __cplusplus +} +#endif + +#endif /* _SECURITY_SECTRUSTSETTINGS_H_ */ diff --git a/Security/sec/Security/SecTrustSettingsPriv.h b/Security/sec/Security/SecTrustSettingsPriv.h new file mode 100644 index 00000000..befddcd5 --- /dev/null +++ b/Security/sec/Security/SecTrustSettingsPriv.h @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2007-2008,2010,2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + */ + +/* + * SecTrustSettingsPriv.h - TrustSettings SPI functions. + */ + +#ifndef _SECURITY_SECTRUSTSETTINGSPRIV_H_ +#define _SECURITY_SECTRUSTSETTINGSPRIV_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * A TrustSettings Record contains the XML encoding of a CFDictionary. This dictionary + * currently contains two name/value pairs: + * + * key = kTrustRecordVersion, value = SInt32 version number + * key = kTrustRecordTrustList, value = CFDictionary + * + * Each key/value pair of the CFDictionary associated with key kTrustRecordTrustList + * consists of: + * -- key = the ASCII representation (with alpha characters in upper case) of the + * cert's SHA1 digest. + * -- value = a CFDictionary representing one cert. + * + * Key/value pairs in the per-cert dictionary are as follows: + * + * -- key = kTrustRecordIssuer, value = non-normalized issuer as CFData + * -- key = kTrustRecordSerialNumber, value = serial number as CFData + * -- key = kTrustRecordModDate, value = CFDateRef of the last modification + date of the per-cert entry. + * -- key = kTrustRecordTrustSettings, value = array of dictionaries. The + * dictionaries are as described in the API in SecUserTrust.h + * although we store the values differently (see below). + * As written to disk, this key/value is always present although + * the usageConstraints array may be empty. + * + * A usageConstraints dictionary is like so (all elements are optional). These key + * strings are defined in SecUserTrust.h. + * + * key = kSecTrustSettingsPolicy value = policy OID as CFData + * key = kSecTrustSettingsApplication value = application path as CFString + * key = kSecTrustSettingsPolicyString value = CFString, policy-specific + * key = kSecTrustSettingsAllowedError value = CFNumber, an SInt32 CSSM_RETURN + * key = kSecTrustSettingsResult value = CFNumber, an SInt32 SecTrustSettingsResult + * key = kSecTrustSettingsKeyUsage value = CFNumber, an SInt32 key usage + * key = kSecTrustSettingsModifyDate value = CFDate, last modification + */ + +/* + * Keys in the top-level dictionary + */ +#define kTrustRecordVersion CFSTR("trustVersion") +#define kTrustRecordTrustList CFSTR("trustList") + +/* + * Keys in the per-cert dictionary in the TrustedRootList record. + */ +/* value = non-normalized issuer as CFData */ +#define kTrustRecordIssuer CFSTR("issuerName") + +/* value = serial number as CFData */ +#define kTrustRecordSerialNumber CFSTR("serialNumber") + +/* value = CFDateRef representation of modification date */ +#define kTrustRecordModDate CFSTR("modDate") + +/* + * value = array of CFDictionaries as used in public API + * Not present for a cert which has no usage Constraints (i.e. + * "wide open" unrestricted, kSecTrustSettingsResultTrustRoot as + * the default SecTrustSettingsResult). + */ +#define kTrustRecordTrustSettings CFSTR("trustSettings") + +/* + * Version of the top-level dictionary. + */ +enum { + kSecTrustRecordVersionInvalid = 0, /* should never be seen on disk */ + kSecTrustRecordVersionCurrent = 1 +}; + +/* + * Key for the (optional) default entry in a TrustSettings record. This + * appears in place of the cert's hash string, and corresponds to + * kSecTrustSettingsDefaultRootCertSetting at the public API. + * If you change this, make sure it has characters other than those + * appearing in a normal cert hash string (0..9 and A..F). + */ +#define kSecTrustRecordDefaultRootCert CFSTR("kSecTrustRecordDefaultRootCert") + +/* + * The location of the system root keychain and its associated TrustSettings. + * These are immutable; this module never modifies either of them. + */ +#define SYSTEM_ROOT_STORE_PATH "/System/Library/Keychains/SystemRootCertificates.keychain" +#define SYSTEM_TRUST_SETTINGS_PATH "/System/Library/Keychains/SystemTrustSettings.plist" + +/* + * The local admin cert store. + */ +#define ADMIN_CERT_STORE_PATH "/Library/Keychains/System.keychain" + +/* + * Per-user and local admin TrustSettings are stored in this directory. + * Per-user settings are of the form .plist. + */ +#define TRUST_SETTINGS_PATH "/Library/Trust Settings" +#define ADMIN_TRUST_SETTINGS "Admin.plist" + +/* + * Additional values for the SecTrustSettingsDomain enum. + */ +enum { + /* + * This indicates a TrustSettings that exists only in memory; it + * can't be written to disk. + */ + kSecTrustSettingsDomainMemory = 100 +}; + +typedef struct __SecTrustSettings *SecTrustSettingsRef; + +CFTypeID SecTrustSettingsGetTypeID(void); +OSStatus SecTrustSettingsCreateFromExternal(SecTrustSettingsDomain domain, + CFDataRef external, SecTrustSettingsRef *ts); +SecTrustSettingsRef SecTrustSettingsCreate(SecTrustSettingsDomain domain, + bool create, bool trim); +CFDataRef SecTrustSettingsCopyExternal(SecTrustSettingsRef ts); +void SecTrustSettingsSet(SecCertificateRef certRef, + CFTypeRef trustSettingsDictOrArray); + +/* + * Fundamental routine used to ascertain status of one cert. + * + * Returns true in *foundMatchingEntry if a trust setting matching + * specific constraints was found for the cert. Returns true in + * *foundAnyEntry if any entry was found for the cert, even if it + * did not match the specified constraints. The TP uses this to + * optimize for the case where a cert is being evaluated for + * one type of usage, and then later for another type. If + * foundAnyEntry is false, the second evaluation need not occur. + * + * Returns the domain in which a setting was found in *foundDomain. + * + * Allowed errors applying to the specified cert evaluation + * are returned in a mallocd array in *allowedErrors and must + * be freed by caller. + */ +OSStatus SecTrustSettingsEvaluateCertificate( + SecCertificateRef certificate, + SecPolicyRef policy, + SecTrustSettingsKeyUsage keyUsage, /* optional */ + bool isSelfSignedCert, /* for checking default setting */ + /* RETURNED values */ + SecTrustSettingsDomain *foundDomain, + CFArrayRef *allowedErrors, /* RETURNED */ + SecTrustSettingsResult *resultType, /* RETURNED */ + bool *foundMatchingEntry,/* RETURNED */ + bool *foundAnyEntry); /* RETURNED */ + +/* + * Add a cert's TrustSettings to a non-persistent TrustSettings record. + * Primarily intended for use in creating a system TrustSettings record + * (which is itself immutable via this module). + * + * The settingsIn argument is an external representation of a TrustSettings + * record, obtianed from this function or from + * SecTrustSettingsCreateExternalRepresentation(). + * If settingsIn is NULL, a new (empty) TrustSettings will be created. + * + * The certRef and trustSettingsDictOrArray arguments are as in + * SecTrustSettingsSetTrustSettings(). May be NULL, when e.g. creating + * a new and empty TrustSettings record. + * + * The external representation is written to the settingOut argument, + * which must eventually be CFReleased by the caller. + */ +OSStatus SecTrustSettingsSetTrustSettingsExternal( + CFDataRef settingsIn, /* optional */ + SecCertificateRef certRef, /* optional */ + CFTypeRef trustSettingsDictOrArray, /* optional */ + CFDataRef *settingsOut); /* RETURNED */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SECURITY_SECTRUSTSETTINGSPRIV_H_ */ + diff --git a/sec/Security/SecTrustStore.c b/Security/sec/Security/SecTrustStore.c similarity index 97% rename from sec/Security/SecTrustStore.c rename to Security/sec/Security/SecTrustStore.c index 4ba1294b..62f49bb9 100644 --- a/sec/Security/SecTrustStore.c +++ b/Security/sec/Security/SecTrustStore.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2009,2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -28,10 +28,10 @@ #include #include +#include #include #include -#include "securityd_client.h" -#include "SecuritydXPC.h" +#include #include "SecFramework.h" #include #include diff --git a/sec/Security/SecTrustStore.h b/Security/sec/Security/SecTrustStore.h similarity index 96% rename from sec/Security/SecTrustStore.h rename to Security/sec/Security/SecTrustStore.h index fed3b79f..6aaad749 100644 --- a/sec/Security/SecTrustStore.h +++ b/Security/sec/Security/SecTrustStore.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2008 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2008,2012-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/sec/Security/Security.h b/Security/sec/Security/Security.h new file mode 100644 index 00000000..9d72fde9 --- /dev/null +++ b/Security/sec/Security/Security.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2007-2008,2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + diff --git a/sec/Security/SecuritydXPC.c b/Security/sec/Security/SecuritydXPC.c similarity index 77% rename from sec/Security/SecuritydXPC.c rename to Security/sec/Security/SecuritydXPC.c index f4a5503d..8a293987 100644 --- a/sec/Security/SecuritydXPC.c +++ b/Security/sec/Security/SecuritydXPC.c @@ -1,12 +1,28 @@ -// -// SecuritydXPC.c -// sec -// -// Created by Mitch Adler on 11/16/12. -// Copyright (c) 2012-2013 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ -#include "SecuritydXPC.h" + +#include #include #include #include @@ -17,6 +33,7 @@ const char *kSecXPCKeyOperation = "operation"; const char *kSecXPCKeyResult = "status"; const char *kSecXPCKeyError = "error"; +const char *kSecXPCKeyClientToken = "client"; const char *kSecXPCKeyPeerInfos = "peer-infos"; const char *kSecXPCKeyUserLabel = "userlabel"; const char *kSecXPCKeyBackup = "backup"; @@ -30,6 +47,11 @@ const char *kSecXPCKeyCertificate = "cert"; const char *kSecXPCKeySettings = "settings"; const char *kSecXPCKeyOTAFileDirectory = "path"; const char *kSecXPCLimitInMinutes = "limitMinutes"; +const char *kSecXPCPublicPeerId = "publicPeerId"; // Public peer id +const char *kSecXPCOTRSession = "otrsess"; // OTR session bytes +const char *kSecXPCData = "data"; // Data to process +const char *kSecXPCOTRReady = "otrrdy"; // OTR ready for messages +const char *kSecXPCKeyDeviceID = "deviceID"; // // XPC Functions for both client and server. @@ -61,14 +83,26 @@ CFStringRef SOSCCGetOperationDescription(enum SecXPCOperation op) return CFSTR("keychain_backup"); case sec_keychain_restore_id: return CFSTR("keychain_restore"); - case sec_keychain_sync_update_id: - return CFSTR("keychain_sync_update"); + case sec_keychain_sync_update_key_parameter_id: + return CFSTR("keychain_sync_update_key_parameter"); + case sec_keychain_sync_update_circle_id: + return CFSTR("keychain_sync_update_circle"); + case sec_keychain_sync_update_message_id: + return CFSTR("keychain_sync_update_message"); case sec_keychain_backup_syncable_id: return CFSTR("keychain_backup_syncable"); case sec_keychain_restore_syncable_id: return CFSTR("keychain_restore_syncable"); case sec_ota_pki_asset_version_id: return CFSTR("ota_pki_asset_version"); + case sec_add_shared_web_credential_id: + return CFSTR("sec_add_shared_web_credential"); + case sec_copy_shared_web_credential_id: + return CFSTR("sec_copy_shared_web_credential"); + case sec_otr_session_create_remote_id: + return CFSTR("sec_otr_session_create_remote"); + case sec_otr_session_process_packet_remote_id: + return CFSTR("sec_otr_session_process_packet_remote"); case kSecXPCOpTryUserCredentials: return CFSTR("TryUserCredentials"); case kSecXPCOpSetUserCredentials: @@ -93,6 +127,12 @@ CFStringRef SOSCCGetOperationDescription(enum SecXPCOperation op) return CFSTR("AcceptApplicants"); case kSecXPCOpRejectApplicants: return CFSTR("RejectApplicants"); + case kSecXPCOpValidateUserPublic: + return CFSTR("ValidateUserPublic"); + case kSecXPCOpCopyValidPeerPeerInfo: + return CFSTR("ValidPeers"); + case kSecXPCOpCopyNotValidPeerPeerInfo: + return CFSTR("NotValidPeers"); case kSecXPCOpCopyApplicantPeerInfo: return CFSTR("ApplicantPeerInfo"); case kSecXPCOpCopyPeerPeerInfo: @@ -101,10 +141,20 @@ CFStringRef SOSCCGetOperationDescription(enum SecXPCOperation op) return CFSTR("ConcurringPeerPeerInfo"); case kSecXPCOpOTAGetEscrowCertificates: return CFSTR("OTAGetEscrowCertificates"); - case kSecXPCOpOTAPKIGetNewAsset: - return CFSTR("sec_ota_pki_get_new_asset"); + case kSecXPCOpOTAPKIGetNewAsset: + return CFSTR("sec_ota_pki_get_new_asset"); case kSecXPCOpProcessSyncWithAllPeers: return CFSTR("ProcessSyncWithAllPeers"); + case soscc_EnsurePeerRegistration_id: + return CFSTR("EnsurePeerRegistration"); + case kSecXPCOpCopyRetirementPeerInfo: + return CFSTR("RetirementPeerInfo"); + case kSecXPCOpCopyGenerationPeerInfo: + return CFSTR("GenerationPeerInfo"); + case kSecXPCOpRollKeys: + return CFSTR("RollKeys"); + case kSecXPCOpSetDeviceID: + return CFSTR("SetDeviceID"); default: return CFSTR("Unknown xpc operation"); } @@ -149,7 +199,7 @@ bool SecXPCDictionarySetString(xpc_object_t message, const char *key, CFStringRe { if (!string) return SecError(errSecParam, error, CFSTR("string for key %s is NULL"), key); - + __block bool ok = true; CFStringPerformWithCString(string, ^(const char *utf8Str) { if (utf8Str) diff --git a/Security/sec/Security/SecuritydXPC.h b/Security/sec/Security/SecuritydXPC.h new file mode 100644 index 00000000..59f9900f --- /dev/null +++ b/Security/sec/Security/SecuritydXPC.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include + +#ifndef _UTILITIES_SECURITYDXPC_H_ +#define _UTILITIES_SECURITYDXPC_H_ + +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 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); + +bool SecXPCDictionarySetString(xpc_object_t message, const char *key, CFStringRef string, CFErrorRef *error); + +CFTypeRef SecXPCDictionaryCopyPList(xpc_object_t message, const char *key, CFErrorRef *error); +bool SecXPCDictionaryCopyPListOptional(xpc_object_t message, const char *key, CFTypeRef *pobject, CFErrorRef *error); + +CFArrayRef SecXPCDictionaryCopyArray(xpc_object_t message, const char *key, CFErrorRef *error); +bool SecXPCDictionaryCopyArrayOptional(xpc_object_t message, const char *key, CFArrayRef *parray, CFErrorRef *error); + +CFDataRef SecXPCDictionaryCopyData(xpc_object_t message, const char *key, CFErrorRef *error); +bool SecXPCDictionaryCopyDataOptional(xpc_object_t message, const char *key, CFDataRef *pdata, CFErrorRef *error); + +CFDictionaryRef SecXPCDictionaryCopyDictionary(xpc_object_t message, const char *key, CFErrorRef *error); + +CFStringRef SecXPCDictionaryCopyString(xpc_object_t message, const char *key, CFErrorRef *error); +bool SecXPCDictionaryCopyDictionaryOptional(xpc_object_t message, const char *key, CFDictionaryRef *pdictionary, CFErrorRef *error); + + +#endif diff --git a/sec/Security/Tool/SecurityCommands.h b/Security/sec/Security/Tool/SecurityCommands.h similarity index 90% rename from sec/Security/Tool/SecurityCommands.h rename to Security/sec/Security/Tool/SecurityCommands.h index e03f9016..4f428552 100644 --- a/sec/Security/Tool/SecurityCommands.h +++ b/Security/sec/Security/Tool/SecurityCommands.h @@ -23,7 +23,11 @@ SECURITY_COMMAND("item", keychain_item, "-u Update item in keychain (require query to match)\n" "-D Delete item from keychain\n" "Add, query, update or delete items from the keychain. Extra attr=value pairs after options always apply to the query\n" - "class=[genp|inet|cert|keys] is required for the query", + "class=[genp|inet|cert|keys] is required for the query\n" + "Security Access Control object can be passed as attribute accc with following syntax:\n" + "accc=\"[;operation[:constraint type(constraint parameters)]...]\"" + "\nExample:\naccc=\"ak;od:policy(DeviceOwnerAuthenticated);odel:true", + "SAC object for deleting item added by default\n" "Manipulate keychain items.") SECURITY_COMMAND_IOS("add-certificates", keychain_add_certificates, @@ -127,3 +131,13 @@ SECURITY_COMMAND_IOS("enroll-secure-profile", command_spc, "[options] \n", "Enroll in secure profile service.") +SECURITY_COMMAND_IOS("keys-need-update", keychain_roll_keys, + "[options]\n" + " -f attempt an update.\n", + "Rotate keys.") + +SECURITY_COMMAND("log", log_control, + "[options] [scope_list]\n" + " -l list current settings.\n" + " -s scope_list set log scopes to scope_list.\n", + "control logging settings") diff --git a/sec/Security/Tool/add_internet_password.c b/Security/sec/Security/Tool/add_internet_password.c similarity index 83% rename from sec/Security/Tool/add_internet_password.c rename to Security/sec/Security/Tool/add_internet_password.c index 9c36c11b..3326df88 100644 --- a/sec/Security/Tool/add_internet_password.c +++ b/Security/sec/Security/Tool/add_internet_password.c @@ -1,10 +1,26 @@ -// -// add_internet_password.c -// sec -// -// Created by Mitch Adler on 1/9/13. -// -// +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include #include diff --git a/Security/sec/Security/Tool/codesign.c b/Security/sec/Security/Tool/codesign.c new file mode 100644 index 00000000..a4423e10 --- /dev/null +++ b/Security/sec/Security/Tool/codesign.c @@ -0,0 +1,427 @@ +/* + * Copyright (c) 2008,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@ + */ + +#include +#if TARGET_OS_EMBEDDED + +#include "SecurityCommands.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Magic numbers used by Code Signing + */ +enum { + CSMAGIC_REQUIREMENT = 0xfade0c00, /* single Requirement blob */ + CSMAGIC_REQUIREMENTS = 0xfade0c01, /* Requirements vector (internal requirements) */ + CSMAGIC_CODEDIRECTORY = 0xfade0c02, /* CodeDirectory blob */ + CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0, /* embedded form of signature data */ + CSMAGIC_DETACHED_SIGNATURE = 0xfade0cc1, /* multi-arch collection of embedded signatures */ + + CSSLOT_CODEDIRECTORY = 0, /* slot index for CodeDirectory */ +}; + + +/* + * Structure of an embedded-signature SuperBlob + */ +typedef struct __BlobIndex { + uint32_t type; /* type of entry */ + uint32_t offset; /* offset of entry */ +} CS_BlobIndex; + +typedef struct __SuperBlob { + uint32_t magic; /* magic number */ + uint32_t length; /* total length of SuperBlob */ + uint32_t count; /* number of index entries following */ + CS_BlobIndex index[]; /* (count) entries */ + /* followed by Blobs in no particular order as indicated by offsets in index */ +} CS_SuperBlob; + + +/* + * C form of a CodeDirectory. + */ +typedef struct __CodeDirectory { + uint32_t magic; /* magic number (CSMAGIC_CODEDIRECTORY) */ + uint32_t length; /* total length of CodeDirectory blob */ + uint32_t version; /* compatibility version */ + uint32_t flags; /* setup and mode flags */ + uint32_t hashOffset; /* offset of hash slot element at index zero */ + uint32_t identOffset; /* offset of identifier string */ + uint32_t nSpecialSlots; /* number of special hash slots */ + uint32_t nCodeSlots; /* number of ordinary (code) hash slots */ + uint32_t codeLimit; /* limit to main image signature range */ + uint8_t hashSize; /* size of each hash in bytes */ + uint8_t hashType; /* type of hash (cdHashType* constants) */ + uint8_t spare1; /* unused (must be zero) */ + uint8_t pageSize; /* log2(page size in bytes); 0 => infinite */ + uint32_t spare2; /* unused (must be zero) */ + /* followed by dynamic content as located by offset fields above */ +} CS_CodeDirectory; + + + //assert(page < ntohl(cd->nCodeSlots)); + //return base + ntohl(cd->hashOffset) + page * 20; + +#if 0 +static void debug_data(uint8_t *data, size_t length) +{ + uint32_t i, j; + for (i = 0; i < length; i+=16) { + fprintf(stderr, "%p ", (void*)(data+i)); + for (j = 0; (j < 16) && (j+i < length); j++) { + uint8_t byte = *(uint8_t*)(data+i+j); + fprintf(stderr, "%.02x %c|", byte, isprint(byte) ? byte : '?'); + } + fprintf(stderr, "\n"); + } +} + +static void write_data(const char *path, uint8_t *data, size_t length) +{ + int fd = open(path, O_RDWR|O_TRUNC|O_CREAT, 0644); + require(fd>0, out); + write(fd, data, length); + close(fd); +out: + return; +} +#endif + +static void fprint_digest(FILE *file, unsigned char *digest, size_t length) { + size_t ix; + for (ix = 0; ix < length; ++ix) { + fprintf(file, "%02x", digest[ix]); + } +} + +static CFMutableDictionaryRef lc_code_sig(uint8_t *lc_code_signature, size_t lc_code_signature_len) +{ + CFMutableDictionaryRef code_signature = + CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + require(code_signature, out); + + CS_SuperBlob *sb = (CS_SuperBlob*)lc_code_signature; + require(ntohl(sb->magic) == CSMAGIC_EMBEDDED_SIGNATURE, out); + uint32_t count; + for (count = 0; count < ntohl(sb->count); count++) { + //uint32_t type = ntohl(sb->index[count].type); + uint32_t offset = ntohl(sb->index[count].offset); + uint8_t *bytes = lc_code_signature + offset; + //fprintf(stderr, "blob[%d]: (type: 0x%.08x, offset: %p)\n", count, type, (void*)offset); + uint32_t magic = ntohl(*(uint32_t*)bytes); + uint32_t length = ntohl(*(uint32_t*)(bytes+4)); + //fprintf(stderr, " magic: 0x%.08x length: %d\n", magic, length); + switch(magic) { + case 0xfade0c01: //write_data("requirements", bytes, length); + break; + case 0xfade0c02: //write_data("codedir", bytes, length); + { + const CS_CodeDirectory *cd = (const CS_CodeDirectory *)bytes; + CFDataRef codedir = CFDataCreate(kCFAllocatorDefault, bytes, length); + require(codedir, out); + CFDictionarySetValue(code_signature, CFSTR("CodeDirectory"), codedir); + CFRelease(codedir); + require_string(ntohl(cd->version) >= 0x20001, out, "incompatible version"); + require_string(ntohl(cd->version) <= 0x2F000, out, "incompatible version"); + require_string(cd->hashSize == 20, out, "unexpected hash size"); + require_string(cd->hashType == 1, out, "unexpected hash type"); + + uint32_t hash_offset = ntohl(cd->hashOffset); + uint32_t entitlement_slot = 5; + + if (ntohl(cd->nSpecialSlots) >= entitlement_slot) { + CFDataRef message = CFDataCreate(kCFAllocatorDefault, bytes+hash_offset-entitlement_slot*cd->hashSize, cd->hashSize); + require(message, out); + CFDictionarySetValue(code_signature, CFSTR("EntitlementsCDHash"), message); + CFRelease(message); + } else + fprintf(stderr, "no entitlements slot yet\n"); + } + break; + case 0xfade0b01: //write_data("signed", lc_code_signature, bytes-lc_code_signature); + if (length != 8) { + CFDataRef message = CFDataCreate(kCFAllocatorDefault, bytes+8, length-8); + require(message, out); + CFDictionarySetValue(code_signature, CFSTR("SignedData"), message); + CFRelease(message); + } + break; + case 0xfade7171: + { + unsigned char digest[CC_SHA1_DIGEST_LENGTH]; + CCDigest(kCCDigestSHA1, bytes, length, digest); + + CFDataRef message = CFDataCreate(kCFAllocatorDefault, digest, sizeof(digest)); + require(message, out); + CFDictionarySetValue(code_signature, CFSTR("EntitlementsHash"), message); + CFRelease(message); + message = CFDataCreate(kCFAllocatorDefault, bytes+8, length-8); + require(message, out); + CFDictionarySetValue(code_signature, CFSTR("Entitlements"), message); + CFRelease(message); + break; + } + default: + fprintf(stderr, "Skipping block with magic: 0x%x\n", magic); + break; + } + } + return code_signature; +out: + if (code_signature) CFRelease(code_signature); + return NULL; +} + +static FILE * +open_bundle(const char * path, const char * mode) +{ + char full_path[1024] = {}; + CFStringRef path_cfstring = NULL; + CFURLRef path_url = NULL; + CFBundleRef bundle = NULL; + CFURLRef exec = NULL; + + path_cfstring = CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path); + require_quiet(path_cfstring, out); + path_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path_cfstring, kCFURLPOSIXPathStyle, true); + require_quiet(path_url, out); + bundle = CFBundleCreate(kCFAllocatorDefault, path_url); + require_quiet(bundle, out); + exec = CFBundleCopyExecutableURL(bundle); + require(exec, out); + require(CFURLGetFileSystemRepresentation(exec, true, (uint8_t*)full_path, sizeof(full_path)), out); +out: + CFReleaseSafe(path_cfstring); + CFReleaseSafe(path_url); + CFReleaseSafe(bundle); + CFReleaseSafe(exec); + + return fopen(full_path, "r"); +} + +static CFMutableDictionaryRef load_code_signature(FILE *binary, size_t slice_offset) +{ + bool signature_found = false; + CFMutableDictionaryRef result = NULL; + struct load_command lc; + do { + require(1 == fread(&lc, sizeof(lc), 1, binary), out); + if (lc.cmd == LC_CODE_SIGNATURE) { + struct { uint32_t offset; uint32_t size; } sig; + require(1 == fread(&sig, sizeof(sig), 1, binary), out); + require_noerr(fseek(binary, slice_offset+sig.offset, SEEK_SET), out); + size_t length = sig.size; + uint8_t *data = malloc(length); + require(length && data, out); + require(1 == fread(data, length, 1, binary), out); + signature_found = true; + result = lc_code_sig(data, length); + free(data); + break; + } + require_noerr(fseek(binary, lc.cmdsize-sizeof(lc), SEEK_CUR), out); + } while(lc.cmd || lc.cmdsize); /* count lc */ +out: + if (!signature_found) + fprintf(stderr, "No LC_CODE_SIGNATURE segment found\n"); + return result; +} + +static CF_RETURNS_RETAINED CFArrayRef load_code_signatures(const char *path) +{ + bool fully_parsed_binary = false; + CFMutableDictionaryRef result = NULL; + CFMutableArrayRef results = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + + FILE *binary = open_bundle(path, "r"); + if (!binary) binary = fopen(path, "r"); + require(binary, out); + + struct mach_header header; + require(1 == fread(&header, sizeof(header), 1, binary), out); + if ((header.magic == MH_MAGIC) || (header.magic == MH_MAGIC_64)) { + if (header.magic == MH_MAGIC_64) + fseek(binary, sizeof(struct mach_header_64) - sizeof(struct mach_header), SEEK_CUR); + result = load_code_signature(binary, 0 /*non fat*/); + require(result, out); + CFStringRef type = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("CPU type: (%d,%d)"), header.cputype, header.cpusubtype); + CFDictionarySetValue(result, CFSTR("ARCH"), type); + CFRelease(type); + CFArrayAppendValue(results, result); + } + else + { + struct fat_header fat; + require(!fseek(binary, 0L, SEEK_SET), out); + require(1 == fread(&fat, sizeof(fat), 1, binary), out); + require(ntohl(fat.magic) == FAT_MAGIC, out); + uint32_t slice, slices = ntohl(fat.nfat_arch); + struct fat_arch *archs = calloc(slices, sizeof(struct fat_arch)); + require(slices == fread(archs, sizeof(struct fat_arch), slices, binary), out); + for (slice = 0; slice < slices; slice++) { + uint32_t slice_offset = ntohl(archs[slice].offset); + require(!fseek(binary, slice_offset, SEEK_SET), out); + require(1 == fread(&header, sizeof(header), 1, binary), out); + require((header.magic == MH_MAGIC) || (header.magic == MH_MAGIC_64), out); + if (header.magic == MH_MAGIC_64) + fseek(binary, sizeof(struct mach_header_64) - sizeof(struct mach_header), SEEK_CUR); + result = load_code_signature(binary, slice_offset); + require(result, out); + CFStringRef type = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("CPU type: (%d,%d)"), header.cputype, header.cpusubtype); + CFDictionarySetValue(result, CFSTR("ARCH"), type); + CFRelease(type); + CFArrayAppendValue(results, result); + CFRelease(result); + } + } + fully_parsed_binary = true; +out: + if (!fully_parsed_binary) { + if (results) { + CFRelease(results); + results = NULL; + } + } + if (binary) + fclose(binary); + return results; +} + + +extern int codesign_util(int argc, char * const *argv) +{ + int result = 1, verbose = 0; + char ch; + + while ((ch = getopt(argc, argv, "v")) != -1) + { + switch (ch) + { + case 'v': + verbose++; + break; + default: + return 2; /* Trigger usage message. */ + } + } + + argc -= optind; + argv += optind; + + if (argc != 1) + return 2; /* Trigger usage message. */ + + CFArrayRef sigs = load_code_signatures(argv[0]); + require(sigs, out); + + if (verbose >= 2) + CFShow(sigs); + + CFIndex i, count = CFArrayGetCount(sigs); + + for (i = 0; i < count; i++) { + CFDictionaryRef signature = CFArrayGetValueAtIndex(sigs, i); + + CFDataRef code_dir = CFDictionaryGetValue(signature, CFSTR("CodeDirectory")); + const CS_CodeDirectory *cd = (CS_CodeDirectory *)CFDataGetBytePtr(code_dir); + + CFDataRef signed_data = CFDictionaryGetValue(signature, CFSTR("SignedData")); + + CFDataRef entitlements = CFDictionaryGetValue(signature, CFSTR("Entitlements")); + CFDataRef entitlements_cd_hash = CFDictionaryGetValue(signature, CFSTR("EntitlementsCDHash")); + CFDataRef entitlements_hash = CFDictionaryGetValue(signature, CFSTR("EntitlementsHash")); + + CFStringRef arch = CFDictionaryGetValue(signature, CFSTR("ARCH")); + + CFShow(arch); + + SecPolicyRef policy = SecPolicyCreateiPhoneApplicationSigning(); + + if (signed_data) { + if (SecCMSVerify(signed_data, code_dir, policy, NULL, NULL)) { + fprintf(stderr, "Failed to verify signature\n"); + result = -1; + } else + fprintf(stderr, "Signature ok\n"); + + } else + fprintf(stderr, "Ad-hoc signed binary\n"); + + if (entitlements_cd_hash) { + if (entitlements_hash && entitlements_cd_hash && CFEqual(entitlements_hash, entitlements_cd_hash)) + fprintf(stderr, "Entitlements ok\n"); + else + fprintf(stderr, "Entitlements modified\n"); + } + + if (verbose >= 2) { + fprintf(stderr, "magic: 0x%x length: %u(%lu)\n", ntohl(cd->magic), ntohl(cd->length), CFDataGetLength(code_dir)); + fprintf(stderr, "code directory version/flags: 0x%x/0x%x special/code hash slots: %u/%u\n" + "codelimit: %u hash size/type: %u/%u hash/ident offset: %u/%u\n", + ntohl(cd->version), ntohl(cd->flags), ntohl(cd->nSpecialSlots), ntohl(cd->nCodeSlots), + ntohl(cd->codeLimit), cd->hashSize, cd->hashType, ntohl(cd->hashOffset), ntohl(cd->identOffset)); + fprintf(stderr, "ident: '%s'\n", CFDataGetBytePtr(code_dir) + ntohl(cd->identOffset)); + + uint32_t ix; + uint8_t *hashes = (uint8_t *)CFDataGetBytePtr(code_dir) + ntohl(cd->hashOffset); + for (ix = 0; ix < ntohl(cd->nSpecialSlots); ++ix) { + fprint_digest(stderr, hashes, cd->hashSize); + fprintf(stderr, "\n"); + hashes += cd->hashSize; + } + } + + if (verbose >= 1) { + if (entitlements) + fprintf(stderr, "Entitlements\n%.*s", (int)CFDataGetLength(entitlements)-8, CFDataGetBytePtr(entitlements)+8); + } + + if (verbose >= 2) { + if (entitlements_hash) { + fprintf(stderr, "digest: "); + fprint_digest(stderr, (uint8_t *)CFDataGetBytePtr(entitlements_hash), CC_SHA1_DIGEST_LENGTH); + fprintf(stderr, "\n"); + } + } + } + + CFReleaseSafe(sigs); + + return result; +out: + return -1; +} + +#endif // TARGET_OS_EMBEDDED diff --git a/Security/sec/Security/Tool/keychain_add.c b/Security/sec/Security/Tool/keychain_add.c new file mode 100644 index 00000000..08ff9151 --- /dev/null +++ b/Security/sec/Security/Tool/keychain_add.c @@ -0,0 +1,130 @@ +/* + * 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 +#if TARGET_OS_EMBEDDED + +#include "Securitycommands.h" + +#include "security.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static int +do_add_certificates(const char *keychainName, bool trustSettings, + int argc, char * const *argv) +{ + int ix, result = 0; + OSStatus status; + + CFMutableDictionaryRef attributes = + CFDictionaryCreateMutable(NULL, 0, NULL, NULL); + CFDictionarySetValue(attributes, kSecClass, kSecClassCertificate); + + for (ix = 0; ix < argc; ++ix) { + CFDataRef data = copyFileContents(argv[ix]); + if (data) { + SecCertificateRef cert = SecCertificateCreateWithData( + kCFAllocatorDefault, data); + if (!cert) { + cert = SecCertificateCreateWithPEM(kCFAllocatorDefault, data); + } + CFRelease(data); + if (cert) { + if (trustSettings) { + SecTrustStoreSetTrustSettings( + SecTrustStoreForDomain(kSecTrustStoreDomainUser), + cert, NULL); + } else { + CFDictionarySetValue(attributes, kSecValueRef, cert); + status = SecItemAdd(attributes, NULL); + CFRelease(cert); + if (status) { + fprintf(stderr, "file %s: SecItemAdd %s", + argv[ix], sec_errstr(status)); + result = 1; + } + } + } else { + result = 1; + fprintf(stderr, "file %s: does not contain a valid certificate", + argv[ix]); + } + } else { + result = 1; + } + } + + CFRelease(attributes); + + return result; +} + + +int +keychain_add_certificates(int argc, char * const *argv) +{ + int ch, result = 0; + const char *keychainName = NULL; + bool trustSettings = false; + while ((ch = getopt(argc, argv, "hk:t")) != -1) + { + switch (ch) + { + case 'k': + keychainName = optarg; + if (*keychainName == '\0') + return 2; + break; + case 't': + trustSettings = true; + break; + case '?': + default: + return 2; /* Return 2 triggers usage message. */ + } + } + + argc -= optind; + argv += optind; + + if (argc == 0) + return 2; + + result = do_add_certificates(keychainName, trustSettings, argc, argv); + + return result; +} + +#endif // TARGET_OS_EMBEDDED diff --git a/sec/Security/Tool/keychain_backup.c b/Security/sec/Security/Tool/keychain_backup.c similarity index 98% rename from sec/Security/Tool/keychain_backup.c rename to Security/sec/Security/Tool/keychain_backup.c index 29efe440..7d0dccbe 100644 --- a/sec/Security/Tool/keychain_backup.c +++ b/Security/sec/Security/Tool/keychain_backup.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2013 Apple Inc. All Rights Reserved. + * 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, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ * * keychain_backup.c diff --git a/Security/sec/Security/Tool/keychain_find.c b/Security/sec/Security/Tool/keychain_find.c new file mode 100644 index 00000000..f5accb5f --- /dev/null +++ b/Security/sec/Security/Tool/keychain_find.c @@ -0,0 +1,556 @@ +// +// +// +// + + + +#include + +#include +#include + +#include +#include + +#include + +#include "SecurityCommands.h" + +#include "keychain_util.h" +#include +#include + +// +// Craptastic hacks. + +typedef uint32_t SecProtocolType; +typedef uint32_t SecAuthenticationType; + + +static CFMutableDictionaryRef +keychain_create_query_from_string(const char *query) { + CFMutableDictionaryRef q; + + q = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (!keychain_query_parse_cstring(q, query)) { + CFReleaseNull(q); + } + return q; +} + +static void add_key(const void *key, const void *value, void *context) { + CFArrayAppendValue(context, key); +} + +static void display_item(const void *v_item, void *context) { + CFDictionaryRef item = (CFDictionaryRef)v_item; + CFIndex dict_count, key_ix, key_count; + CFMutableArrayRef keys = NULL; + CFIndex maxWidth = 10; /* Maybe precompute this or grab from context? */ + + dict_count = CFDictionaryGetCount(item); + keys = CFArrayCreateMutable(kCFAllocatorDefault, dict_count, + &kCFTypeArrayCallBacks); + CFDictionaryApplyFunction(item, add_key, keys); + key_count = CFArrayGetCount(keys); + CFArraySortValues(keys, CFRangeMake(0, key_count), + (CFComparatorFunction)CFStringCompare, 0); + + for (key_ix = 0; key_ix < key_count; ++key_ix) { + CFStringRef key = (CFStringRef)CFArrayGetValueAtIndex(keys, key_ix); + CFTypeRef value = CFDictionaryGetValue(item, key); + CFMutableStringRef line = CFStringCreateMutable(NULL, 0); + + CFStringAppend(line, key); + CFIndex jx; + for (jx = CFStringGetLength(key); + jx < maxWidth; ++jx) { + CFStringAppend(line, CFSTR(" ")); + } + CFStringAppend(line, CFSTR(" : ")); + if (CFStringGetTypeID() == CFGetTypeID(value)) { + CFStringAppend(line, (CFStringRef)value); + } else if (CFNumberGetTypeID() == CFGetTypeID(value)) { + CFNumberRef v_n = (CFNumberRef)value; + CFStringAppendFormat(line, NULL, CFSTR("%@"), v_n); + } else if (CFDateGetTypeID() == CFGetTypeID(value)) { + CFDateRef v_d = (CFDateRef)value; + CFStringAppendFormat(line, NULL, CFSTR("%@"), v_d); + } else if (CFDataGetTypeID() == CFGetTypeID(value)) { + CFDataRef v_d = (CFDataRef)value; + CFStringRef v_s = CFStringCreateFromExternalRepresentation( + kCFAllocatorDefault, v_d, kCFStringEncodingUTF8); + if (v_s) { + CFStringAppend(line, CFSTR("/")); + CFStringAppend(line, v_s); + CFStringAppend(line, CFSTR("/ ")); + CFRelease(v_s); + } + const uint8_t *bytes = CFDataGetBytePtr(v_d); + CFIndex len = CFDataGetLength(v_d); + for (jx = 0; jx < len; ++jx) { + CFStringAppendFormat(line, NULL, CFSTR("%.02X"), bytes[jx]); + } + } else if (SecAccessControlGetTypeID() == CFGetTypeID(value)) { + display_sac_line((SecAccessControlRef)value, line); + } else { + CFStringAppendFormat(line, NULL, CFSTR("%@"), value); + } + + CFStringWriteToFileWithNewline(line, stdout); + + CFRelease(line); + } + CFRelease(keys); + + CFStringWriteToFileWithNewline(CFSTR("===="), stdout); + + //CFShow(item); +} + + +static void display_results(CFTypeRef results) { + if (CFGetTypeID(results) == CFArrayGetTypeID()) { + CFArrayRef r_a = (CFArrayRef)results; + CFArrayApplyFunction(r_a, CFRangeMake(0, CFArrayGetCount(r_a)), + display_item, NULL); + } else if (CFGetTypeID(results) == CFArrayGetTypeID()) { + display_item(results, NULL); + } else { + fprintf(stderr, "SecItemCopyMatching returned unexpected results:"); + CFShow(results); + } +} + +static OSStatus do_find_or_delete(CFDictionaryRef query, bool do_delete) { + OSStatus result; + if (do_delete) { + result = SecItemDelete(query); + if (result) { + sec_perror("SecItemDelete", result); + } + } else { + CFTypeRef results = NULL; + result = SecItemCopyMatching(query, &results); + if (result) { + sec_perror("SecItemCopyMatching", result); + } else { + display_results(results); + } + CFReleaseSafe(results); + } + return result; +} + +static int +do_keychain_find_or_delete_internet_password(Boolean do_delete, + const char *serverName, const char *securityDomain, + const char *accountName, const char *path, UInt16 port, + SecProtocolType protocol, SecAuthenticationType authenticationType, + Boolean get_password) + { + OSStatus result; + CFDictionaryRef query = NULL; + const void *keys[11], *values[11]; + CFIndex ix = 0; + + keys[ix] = kSecClass; + values[ix++] = kSecClassInternetPassword; + if (serverName) { + keys[ix] = kSecAttrServer; + values[ix++] = CFStringCreateWithCStringNoCopy(NULL, serverName, + kCFStringEncodingUTF8, kCFAllocatorNull); + } + if (securityDomain) { + keys[ix] = kSecAttrSecurityDomain; + values[ix++] = CFStringCreateWithCStringNoCopy(NULL, securityDomain, + kCFStringEncodingUTF8, kCFAllocatorNull); + } + if (accountName) { + keys[ix] = kSecAttrAccount; + values[ix++] = CFStringCreateWithCStringNoCopy(NULL, accountName, + kCFStringEncodingUTF8, kCFAllocatorNull); + } + if (path) { + keys[ix] = kSecAttrPath; + values[ix++] = CFStringCreateWithCStringNoCopy(NULL, path, + kCFStringEncodingUTF8, kCFAllocatorNull); + } + if (port != 0) { + keys[ix] = kSecAttrPort; + values[ix++] = CFNumberCreate(NULL, kCFNumberSInt16Type, &port); + } + if (protocol != 0) { + /* Protocol is a 4 char code, perhaps we should use a string rep + instead. */ + keys[ix] = kSecAttrProtocol; + values[ix++] = CFNumberCreate(NULL, kCFNumberSInt32Type, &protocol); + } + if (authenticationType != 0) { + keys[ix] = kSecAttrAuthenticationType; + values[ix++] = CFNumberCreate(NULL, kCFNumberSInt32Type, + &authenticationType); + } + if (get_password) { + /* Only ask for the data if so required. */ + keys[ix] = kSecReturnData; + values[ix++] = kCFBooleanTrue; + } + keys[ix] = kSecReturnAttributes; + values[ix++] = kCFBooleanTrue; + if (!do_delete) { + /* If we aren't deleting ask for all items. */ + keys[ix] = kSecMatchLimit; + values[ix++] = kSecMatchLimitAll; + } + + query = CFDictionaryCreate(NULL, keys, values, ix, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + result = do_find_or_delete(query, do_delete); + CFReleaseSafe(query); + + return result; +} + +static int +parse_fourcharcode(const char *name, uint32_t *code) +{ + /* @@@ Check for errors. */ + char *p = (char *)code; + strncpy(p, name, 4); + return 0; +} + +static int +keychain_find_or_delete_internet_password(Boolean do_delete, int argc, char * const *argv) +{ + char *serverName = NULL, *securityDomain = NULL, *accountName = NULL, *path = NULL; + UInt16 port = 0; + SecProtocolType protocol = 0; + SecAuthenticationType authenticationType = 0; + int ch, result = 0; + Boolean get_password = FALSE; + + while ((ch = getopt(argc, argv, "a:d:hgp:P:r:s:t:")) != -1) + { + switch (ch) + { + case 'a': + accountName = optarg; + break; + case 'd': + securityDomain = optarg; + break; + case 'g': + if (do_delete) + return 2; + get_password = TRUE; + break; + case 'p': + path = optarg; + break; + case 'P': + port = atoi(optarg); + break; + case 'r': + result = parse_fourcharcode(optarg, &protocol); + if (result) + goto loser; + break; + case 's': + serverName = optarg; + break; + case 't': + result = parse_fourcharcode(optarg, &authenticationType); + if (result) + goto loser; + break; + case '?': + default: + return 2; /* @@@ Return 2 triggers usage message. */ + } + } + + result = do_keychain_find_or_delete_internet_password(do_delete, serverName, securityDomain, + accountName, path, port, protocol,authenticationType, get_password); + + +loser: + + return result; +} + +int +keychain_find_internet_password(int argc, char * const *argv) { + return keychain_find_or_delete_internet_password(0, argc, argv); +} + +int +keychain_delete_internet_password(int argc, char * const *argv) { + return keychain_find_or_delete_internet_password(1, argc, argv); +} + +static int +do_keychain_find_or_delete_generic_password(Boolean do_delete, + const char *serviceName, const char *accountName, + Boolean get_password) + { + OSStatus result; + CFDictionaryRef query = NULL; + const void *keys[6], *values[6]; + CFIndex ix = 0; + + keys[ix] = kSecClass; + values[ix++] = kSecClassGenericPassword; + if (serviceName) { + keys[ix] = kSecAttrService; + values[ix++] = CFStringCreateWithCStringNoCopy(NULL, serviceName, + kCFStringEncodingUTF8, kCFAllocatorNull); + } + if (accountName) { + keys[ix] = kSecAttrAccount; + values[ix++] = CFStringCreateWithCStringNoCopy(NULL, accountName, + kCFStringEncodingUTF8, kCFAllocatorNull); + } + if (get_password) { + /* Only ask for the data if so required. */ + keys[ix] = kSecReturnData; + values[ix++] = kCFBooleanTrue; + } + keys[ix] = kSecReturnAttributes; + values[ix++] = kCFBooleanTrue; + if (!do_delete) { + /* If we aren't deleting ask for all items. */ + keys[ix] = kSecMatchLimit; + values[ix++] = kSecMatchLimitAll; + } + + query = CFDictionaryCreate(NULL, keys, values, ix, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + result = do_find_or_delete(query, do_delete); + + CFReleaseSafe(query); + + return result; +} + +int keychain_item(int argc, char * const *argv) { + int ch, result = 0; + CFMutableDictionaryRef query, update = NULL; + bool get_password = false; + bool do_delete = false; + bool do_add = false; + bool verbose = false; + int limit = 0; + + query = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + while ((ch = getopt(argc, argv, "ad:Df:gq:u:vl:")) != -1) + { + switch (ch) + { + case 'a': + do_add = true; + break; + case 'D': + do_delete = true; + break; + case 'd': + { + CFStringRef data = CFStringCreateWithCString(0, optarg, kCFStringEncodingUTF8); + if (data) { + CFDictionarySetValue(update ? update : query, kSecValueData, data); + CFRelease(data); + } else { + result = 1; + goto out; + } + break; + } + case 'f': + { + CFDataRef data = copyFileContents(optarg); + CFDictionarySetValue(update ? update : query, kSecValueData, data); + CFRelease(data); + break; + } + case 'g': + get_password = true; + break; + case 'q': + if (!keychain_query_parse_cstring(query, optarg)) { + result = 1; + goto out; + } + break; + case 'u': + { + bool success = true; + if (!update) + update = keychain_create_query_from_string(optarg); + else + success = keychain_query_parse_cstring(update, optarg); + if (update == NULL || !success) { + result = 1; + goto out; + } + } + break; + case 'v': + verbose = true; + break; + case 'l': + limit = atoi(optarg); + break; + case '?': + default: + /* Return 2 triggers usage message. */ + result = 2; + goto out; + } + } + + if (((do_add || do_delete) && (get_password || update)) || !query) { + result = 2; + goto out; + } + + argc -= optind; + argv += optind; + + int ix; + for (ix = 0; ix < argc; ++ix) { + if (!keychain_query_parse_cstring(query, argv[ix])) { + result = 1; + goto out; + } + } + + if (!update && !do_add && !do_delete) { + CFDictionarySetValue(query, kSecReturnAttributes, kCFBooleanTrue); + if(limit) { + CFNumberRef cfLimit = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &limit); + CFDictionarySetValue(query, kSecMatchLimit, cfLimit); + CFReleaseSafe(cfLimit); + } else { + CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll); + } + if (get_password) + CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue); + } + + if (verbose) + CFShow(query); + + OSStatus error; + if (do_add) { + error = SecItemAdd(query, NULL); + if (error) { + sec_perror("SecItemAdd", error); + result = 1; + } + } else if (update) { + error = SecItemUpdate(query, update); + if (error) { + sec_perror("SecItemUpdate", error); + result = 1; + } + } else if (do_delete) { + error = SecItemDelete(query); + if (error) { + sec_perror("SecItemDelete", error); + result = 1; + } + } else { + do_find_or_delete(query, do_delete); + } + +out: + CFReleaseSafe(query); + CFReleaseSafe(update); + return result; +} + +static int +keychain_find_or_delete_generic_password(Boolean do_delete, + int argc, char * const *argv) +{ + char *serviceName = NULL, *accountName = NULL; + int ch, result = 0; + Boolean get_password = FALSE; + + while ((ch = getopt(argc, argv, "a:s:g")) != -1) + { + switch (ch) + { + case 'a': + accountName = optarg; + break; + case 'g': + if (do_delete) + return 2; + get_password = TRUE; + break; + case 's': + serviceName = optarg; + break; + case '?': + default: + return 2; /* @@@ Return 2 triggers usage message. */ + } + } + + result = do_keychain_find_or_delete_generic_password(do_delete, + serviceName, accountName, get_password); + + return result; +} + +int +keychain_find_generic_password(int argc, char * const *argv) { + return keychain_find_or_delete_generic_password(0, argc, argv); +} + +int +keychain_delete_generic_password(int argc, char * const *argv) { + return keychain_find_or_delete_generic_password(1, argc, argv); +} + +#if TARGET_OS_EMBEDDED + +int +keychain_roll_keys(int argc, char * const *argv) { + int ch, result = 0; + bool force = false; + + while ((ch = getopt(argc, argv, "f")) != -1) + { + switch (ch) + { + case 'f': + force = true; + break; + default: + return 2; + } + } + // argc -= optind; + // argv += optind; + + (void) argc; // These are set so folks could use them + (void) argv; // silence the analyzer since they're not used + + CFErrorRef error = NULL; + bool ok = _SecKeychainRollKeys(force, &error); + + fprintf(stderr, "Keychain keys up to date: %s\n", ok ? "yes" : "no"); + if (!ok && error) { + result = (int)CFErrorGetCode(error); + CFShow(error); + } + + return result; +} + +#endif diff --git a/Security/sec/Security/Tool/keychain_util.c b/Security/sec/Security/Tool/keychain_util.c new file mode 100644 index 00000000..35a319f9 --- /dev/null +++ b/Security/sec/Security/Tool/keychain_util.c @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include + +#include "security.h" +#include "keychain_util.h" +#include "SecAccessControlPriv.h" +#include + +void +display_sac_line(SecAccessControlRef sac, CFMutableStringRef line) { + CFTypeRef protection = SecAccessControlGetProtection(sac); + if(CFStringGetTypeID() == CFGetTypeID(protection)) + { + CFStringAppend(line, protection); + } + + CFDictionaryRef constraints = SecAccessControlGetConstraints(sac); + if(constraints != NULL) + { + CFDictionaryForEach(constraints, ^(const void *key, const void *value) { + CFStringAppend(line, CFSTR(";")); + CFStringAppend(line, key); + CFDictionaryRef constraintData = (CFDictionaryRef)value; + + if(CFStringGetTypeID() == CFGetTypeID(key) && CFDictionaryGetTypeID() == CFGetTypeID(value)) { + CFDictionaryForEach(constraintData, ^(const void *constraintKey, const void *constraintValue) { + CFStringRef constraintType = (CFStringRef)constraintKey; + CFStringAppend(line, CFSTR(":")); + CFStringAppend(line, constraintType); + CFStringAppend(line, CFSTR("(")); + + if(CFStringCompare(constraintType, CFSTR("policy"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) + { + // for policy, argument is plain string + CFStringAppend(line, (CFStringRef)constraintValue); + } + else if(CFStringCompare(constraintType, CFSTR("passcode"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) + { + // for passcode, we have to decode if system-passcode is used + if(CFStringCompare((CFStringRef)constraintValue, CFSTR("passcode"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) + CFStringAppend(line, CFSTR("yes")); + else + CFStringAppend(line, CFSTR("no")); + } + else if(CFStringCompare(constraintType, CFSTR("bio"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) + { + // for bio, argument is plain string + CFStringAppend(line, (CFStringRef)constraintValue); + } + else + CFStringAppend(line, CFSTR("Not yet supported")); + + CFStringAppend(line, CFSTR(")")); + }); + } else { + CFStringAppend(line, CFSTR(":")); + if (value == kCFBooleanTrue) { + CFStringAppend(line, CFSTR("true")); + } else if (value == kCFBooleanFalse) { + CFStringAppend(line, CFSTR("false")); + } else { + CFStringAppend(line, CFSTR("unrecognized value")); + } + } + }); + } +} + +bool +keychain_query_parse_cstring(CFMutableDictionaryRef q, const char *query) { + CFStringRef s; + s = CFStringCreateWithCStringNoCopy(0, query, kCFStringEncodingUTF8, kCFAllocatorNull); + bool result = keychain_query_parse_string(q, s); + CFRelease(s); + return result; +} + +/* Parse a string of the form attr=value,attr=value,attr=value */ +bool +keychain_query_parse_string(CFMutableDictionaryRef q, CFStringRef s) { + bool inkey = true; + bool escaped = false; + bool error = false; + CFStringRef key = NULL; + CFMutableStringRef str = CFStringCreateMutable(0, 0); + CFRange rng = { .location = 0, .length = CFStringGetLength(s) }; + CFCharacterSetRef cs_key = CFCharacterSetCreateWithCharactersInString(0, CFSTR("=\\")); + CFCharacterSetRef cs_value = CFCharacterSetCreateWithCharactersInString(0, CFSTR(",\\")); + while (rng.length) { + CFRange r; + CFStringRef sub; + bool complete = false; + if (escaped) { + r.location = rng.location; + r.length = 1; + sub = CFStringCreateWithSubstring(0, s, r); + escaped = false; + } else if (CFStringFindCharacterFromSet(s, inkey ? cs_key : cs_value, rng, 0, &r)) { + if (CFStringGetCharacterAtIndex(s, r.location) == '\\') { + escaped = true; + } else { + complete = true; + } + CFIndex next = r.location + 1; + r.length = r.location - rng.location; + r.location = rng.location; + sub = CFStringCreateWithSubstring(0, s, r); + rng.length -= next - rng.location; + rng.location = next; + } else { + sub = CFStringCreateWithSubstring(0, s, rng); + rng.location += rng.length; + rng.length = 0; + complete = true; + } + CFStringAppend(str, sub); + CFRelease(sub); + + if (complete) { + CFStringRef value = CFStringCreateCopy(0, str); + CFStringReplaceAll(str, CFSTR("")); + if (inkey) { + key = value; + } else { + if(key && CFStringCompare(key, kSecAttrAccessControl, kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + SecAccessControlRef sac = keychain_query_parse_sac(value); + if(sac) { + CFDictionarySetValue(q, key, sac); + } else { + fprintf(stderr, "SecItemCopyMatching returned unexpected results:"); + error = true; + } + } else { + CFDictionarySetValue(q, key, value); + } + CFReleaseNull(value); + CFReleaseNull(key); + } + inkey = !inkey; + } + if(error) + break; + } + if (key) { + /* Dangeling key value is true?. */ + CFDictionarySetValue(q, key, kCFBooleanTrue); + CFReleaseNull(key); + } + CFRelease(str); + CFRelease(cs_key); + CFRelease(cs_value); + return error == false; +} + +SecAccessControlRef +keychain_query_parse_sac(CFStringRef s) { + SecAccessControlRef sac; + CFArrayRef tokens = CFStringCreateArrayBySeparatingStrings(NULL, s, CFSTR(";")); + + // process protection part + CFStringRef protection = CFArrayGetValueAtIndex(tokens, 0); + + CFErrorRef error = NULL; + sac = SecAccessControlCreateWithFlags(NULL, protection, 0, &error); + if(error != NULL) + { + return NULL; + } + + CFIndex tokensCnt = CFArrayGetCount(tokens); + CFArrayRef params = NULL; + CFArrayRef constraints = NULL; + CFArrayRef pair = NULL; + CFStringRef constraintDetails = NULL; + CFStringRef constraintType = NULL; + bool paramError = false; + + for(CFIndex i = 1; i < tokensCnt; ++i) // process all constraints + { + SecAccessConstraintRef constr = NULL; + + pair = CFStringCreateArrayBySeparatingStrings(NULL, CFArrayGetValueAtIndex(tokens, i), CFSTR(":")); + if(CFArrayGetCount(pair) != 2) + { + paramError = true; + goto paramErr; + } + CFStringRef operationName = CFArrayGetValueAtIndex(pair, 0); + CFStringRef strConstraint = CFArrayGetValueAtIndex(pair, 1); + + if (CFStringHasSuffix(strConstraint, CFSTR(")"))) { + CFStringRef tmp; + tmp = CFStringCreateWithSubstring(NULL, strConstraint, CFRangeMake(0, CFStringGetLength(strConstraint) - 1)); + constraints = CFStringCreateArrayBySeparatingStrings(NULL, tmp, CFSTR("(")); + CFReleaseSafe(tmp); + + if ( CFArrayGetCount(constraints) != 2) { + paramError = true; + goto paramErr; + } + + constraintType = CFArrayGetValueAtIndex(constraints, 0); + constraintDetails = CFArrayGetValueAtIndex(constraints, 1); + + if (CFStringCompare(constraintType, CFSTR("policy"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + constr = SecAccessConstraintCreatePolicy(constraintDetails, &error); + } + + + /* NOT SUPPORTED YET + else if(CFStringCompare(constraintType, CFSTR("passcode"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) + { + bool system; + if(CFStringCompare(constraintDetails, CFSTR("yes"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) + system = true; + else if(CFStringCompare(constraintDetails, CFSTR("no"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) + system = false; + else + { + printf("Wrong system parameter for passcode policy: [%s]\n", CFStringGetCStringPtr(constraintDetails, kCFStringEncodingUTF8)); + paramError = true; + goto paramErr; + } + constr = SecAccessConstraintCreatePasscode(system); + } + else if(CFStringCompare(constraintType, CFSTR("bio"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) + { + constr = SecAccessConstraintCreateTouchID(CFStringCreateExternalRepresentation(NULL, constraintDetails, kCFStringEncodingASCII, 32), &error); + } + else if(CFStringCompare(constraintType, CFSTR("kofn"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) + { + CFIndex kofnParamCount = 0; + bool foundBracket = false; + for(CFIndex j = i + 1; j < tokensCnt; ++j) + { + ++kofnParamCount; + if(CFStringHasSuffix(CFArrayGetValueAtIndex(tokens, j), CFSTR(")"))) + { + foundBracket = true; + break; + } + } + if(!foundBracket || kofnParamCount < 2) + { + printf("Invalid syntax for kofn params\n"); + paramError = true; + goto paramErr; + } + // process params + size_t kofnRequired = CFStringGetIntValue(constraintDetails); + CFMutableArrayRef kofnParams = CFArrayCreateMutable(NULL, kofnRequired, NULL); + CFArrayAppendArray(kofnParams, tokens, CFRangeMake(i + 1, kofnParamCount)); // first param of kofn is number of required methods + // remove ")" for the last method + CFStringRef tmp = CFStringCreateWithSubstring(NULL, CFArrayGetValueAtIndex(kofnParams, kofnParamCount - 1), + CFRangeMake(0, CFStringGetLength(CFArrayGetValueAtIndex(kofnParams, kofnParamCount - 1)) - 1)); + CFArraySetValueAtIndex(kofnParams, kofnParamCount -1, tmp); + i += kofnParamCount; + + // TODO: add this as soon as kOfn starts to work + constr = SecAccessConstraintCreateKofN(kofnRequired, kofnParams, &error); + printf("Created KOFN constraint required %zu\n", kofnRequired); + CFReleaseNull(kofnParams); + CFReleaseNull(tmp); + + } + NOT YET IMPLEMENTED */ + else { + paramError = true; + goto paramErr; + } + + } else if (CFStringCompare(strConstraint, CFSTR("true"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + constr = kCFBooleanTrue; + + } else if (CFStringCompare(strConstraint, CFSTR("false"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + constr = kCFBooleanFalse; + } + + + if (error || constr == NULL) { + paramError = true; + goto paramErr; + } + + SecAccessControlAddConstraintForOperation(sac, operationName, constr, &error); + if (error) { + paramError = true; + goto paramErr; + } + paramErr: + CFReleaseNull(pair); + CFReleaseNull(params); + CFReleaseNull(constraints); + CFReleaseNull(constr); + + if (paramError) { + break; + } + } + + CFReleaseSafe(tokens); + + SecAccessConstraintRef constraintForDelete = SecAccessControlGetConstraint(sac, kAKSKeyOpDelete); + if (!constraintForDelete) { + if(!SecAccessControlAddConstraintForOperation(sac, kAKSKeyOpDelete, kCFBooleanTrue, &error)) { + fprintf(stderr, "adding delete operation to sac object failed \n"); + } + } + + if (paramError) { + fprintf(stderr, "Error constructing SecAccessConstraint object\n"); + CFReleaseSafe(sac); + return NULL; + } + + return sac; +} diff --git a/Security/sec/Security/Tool/keychain_util.h b/Security/sec/Security/Tool/keychain_util.h new file mode 100644 index 00000000..c05247f9 --- /dev/null +++ b/Security/sec/Security/Tool/keychain_util.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef sec_keychain_sac_h +#define sec_keychain_sac_h + +extern bool keychain_query_parse_string(CFMutableDictionaryRef q, CFStringRef s); +extern bool keychain_query_parse_cstring(CFMutableDictionaryRef q, const char *query); +extern SecAccessControlRef keychain_query_parse_sac(CFStringRef s); +extern void display_sac_line(SecAccessControlRef sac, CFMutableStringRef line); + +#endif diff --git a/Security/sec/Security/Tool/log_control.c b/Security/sec/Security/Tool/log_control.c new file mode 100644 index 00000000..a41cb65c --- /dev/null +++ b/Security/sec/Security/Tool/log_control.c @@ -0,0 +1,172 @@ +// +// log_control.c +// +// sec +// + +#include +#include +#include + +#include +#include + +#include + +#include + +#include + +#include + +#include "SecurityCommands.h" + + +static void +set_log_settings(const char * settings) +{ + CFErrorRef error = NULL; + + CFStringRef scope = CFStringCreateWithCString(kCFAllocatorDefault, settings, kCFStringEncodingUTF8); + + if (!SecSetLoggingInfoForXPCScope((CFPropertyListRef) scope, &error)) { + fprintf(stderr, "Failed: "); + CFShow(error); + } + + CFReleaseSafe(scope); + CFReleaseSafe(error); +} + +static const char * getScopeIDName(int id) +{ + switch (id) { + case kScopeIDXPC: return "XPC"; + case kScopeIDDefaults: return "Defaults"; + case kScopeIDEnvironment: return "Environment Variables"; + case kScopeIDConfig: return "Config"; + default: return "Unknown"; + } +}; + +static const char * getPriorityName(CFNumberRef id_number) +{ + int priority = -1; + + CFNumberGetValue(id_number, kCFNumberIntType, &priority); + + switch (priority) { + case ASL_LEVEL_EMERG: return ASL_STRING_EMERG; + case ASL_LEVEL_ALERT: return ASL_STRING_ALERT; + case ASL_LEVEL_CRIT: return ASL_STRING_CRIT; + case ASL_LEVEL_ERR: return ASL_STRING_ERR; + case ASL_LEVEL_WARNING: return ASL_STRING_WARNING; + case ASL_LEVEL_NOTICE: return ASL_STRING_NOTICE; + case ASL_LEVEL_INFO: return ASL_STRING_INFO; + case ASL_LEVEL_DEBUG: return ASL_STRING_DEBUG; + default: return "Unknown"; + + } +}; + +static void print_comma_separated(FILE* file, CFArrayRef array) +{ + fprintf(file, "["); + __block const char *separator = ""; + CFArrayForEach(array, ^(const void *value) { + cffprint(file, CFSTR("%s%@"), separator, value); + separator = ", "; + }); + fprintf(file, "]"); + +} + +static void +list_log_settings() +{ + CFErrorRef error = NULL; + + CFArrayRef result = SecGetCurrentServerLoggingInfo(&error); + if (result) { + __block int index = 0; + CFArrayForEach(result, ^(const void *value) { + printf("%s: ", getScopeIDName(index)); + + if (isArray(value)) { + print_comma_separated(stdout, (CFArrayRef) value); + printf("\n"); + } else if (isDictionary(value)) { + printf("\n"); + CFDictionaryForEach((CFDictionaryRef) value, ^(const void *level, const void *array) { + printf(" %s: ", getPriorityName(level)); + if (isArray(array)) { + print_comma_separated(stdout, (CFArrayRef) array); + } else { + cffprint(stdout, CFSTR("%@"), array); + } + printf("\n"); + }); + } else { + cffprint(stdout, CFSTR("%@\n"), value); + } + + ++index; + }); + } else { + fprintf(stderr, "Failed: "); + CFShow(error); + } + + CFReleaseSafe(error); +} + +int log_control(int argc, char * const *argv) +{ + int ch, result = 2; /* @@@ Return 2 triggers usage message. */ + + bool list = false; + /* + "-l - list" + */ + while ((ch = getopt(argc, argv, "ls:")) != -1) + { + switch (ch) + { + case 'l': + list = true; + break; + case 's': + set_log_settings(optarg); + break; + case '?': + default: + goto fail; + } + } + + argc -= optind; + argv += optind; + + if (argc > 1) + goto fail; + + if (argc == 1) { + set_log_settings(argv[0]); + + argc -= 1; + argv += 1; + } + + (void) argv; + + if (argc != 0) + goto fail; + + if (list) + list_log_settings(); + + result = 0; + +fail: + return result; +} diff --git a/sec/Security/Tool/pkcs12_util.c b/Security/sec/Security/Tool/pkcs12_util.c similarity index 99% rename from sec/Security/Tool/pkcs12_util.c rename to Security/sec/Security/Tool/pkcs12_util.c index 717a28d3..1a33b80d 100644 --- a/sec/Security/Tool/pkcs12_util.c +++ b/Security/sec/Security/Tool/pkcs12_util.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2008-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-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, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/sec/Security/Tool/scep.c b/Security/sec/Security/Tool/scep.c similarity index 91% rename from sec/Security/Tool/scep.c rename to Security/sec/Security/Tool/scep.c index a4779125..66a91684 100644 --- a/sec/Security/Tool/scep.c +++ b/Security/sec/Security/Tool/scep.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004,2006-2007,2009-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2006-2007,2009-2010,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -46,6 +46,7 @@ #include #include "SecBase64.h" +#include #include @@ -58,7 +59,7 @@ static inline void write_data(const char * path, CFDataRef data) #define BUFSIZE 1024 -static CFHTTPMessageRef load_request(CFHTTPMessageRef request, CFMutableDataRef data, int retry, bool validate_cert) +static CF_RETURNS_RETAINED CFHTTPMessageRef load_request(CFHTTPMessageRef request, CFMutableDataRef data, int retry, bool validate_cert) { CFHTTPMessageRef result = NULL; @@ -113,7 +114,7 @@ static CFHTTPMessageRef load_request(CFHTTPMessageRef request, CFMutableDataRef return result; } -static CFDataRef MCNetworkLoadRequest(CFURLRef url, CFDataRef content, CFStringRef type, +static CF_RETURNS_RETAINED CFDataRef MCNetworkLoadRequest(CFURLRef url, CFDataRef content, CFStringRef type, CFStringRef *contentType, bool validate_cert) { CFMutableDataRef out_data = CFDataCreateMutable(kCFAllocatorDefault, 0); @@ -141,13 +142,15 @@ static CFDataRef MCNetworkLoadRequest(CFURLRef url, CFDataRef content, CFStringR CFStringRef url_string = CFURLGetString(url); if (url_string && request_type && out_data) fprintf(stderr, "MCNetworkLoadRequest failed to load\n"); - return NULL; + + CFReleaseNull(out_data); + goto out; } if (contentType) *contentType = CFHTTPMessageCopyHeaderFieldValue(response, CFSTR("Content-Type")); - - CFRelease(response); +out: + CFReleaseSafe(response); return out_data; } @@ -171,7 +174,7 @@ static void _query_string_apply(CFMutableStringRef query_string, const void *key CFRelease(escaped_value); } -static CFURLRef scep_url_operation(CFStringRef base, CFStringRef operation, CFStringRef message) +static CF_RETURNS_RETAINED CFURLRef scep_url_operation(CFStringRef base, CFStringRef operation, CFStringRef message) { CFURLRef url = NULL, base_url = NULL; CFMutableStringRef query_string = @@ -191,7 +194,7 @@ out: return url; } -static CFDataRef perform_pki_op(CFStringRef scep_base_url, CFDataRef scep_request, bool scep_can_use_post, bool validate_cert) +static CF_RETURNS_RETAINED CFDataRef perform_pki_op(CFStringRef scep_base_url, CFDataRef scep_request, bool scep_can_use_post, bool validate_cert) { CFDataRef scep_reply = NULL; CFURLRef pki_op = NULL; @@ -215,7 +218,7 @@ static CFDataRef perform_pki_op(CFStringRef scep_base_url, CFDataRef scep_reques scep_reply = MCNetworkLoadRequest(pki_op, NULL, CFSTR("application/x-pki-message"), NULL, validate_cert); } out: - if (pki_op) CFRelease(pki_op); + CFReleaseSafe(pki_op); return scep_reply; } @@ -294,6 +297,7 @@ extern int command_scep(int argc, char * const *argv) scep_instance_name = CFStringCreateWithCString(kCFAllocatorDefault, optarg, kCFStringEncodingUTF8); break; case 's': + CFReleaseNull(scep_subject_name); scep_subject_name = CFStringCreateWithCString(kCFAllocatorDefault, optarg, kCFStringEncodingUTF8); break; case 'h': @@ -326,6 +330,14 @@ extern int command_scep(int argc, char * const *argv) CFStringRef scep_base_url = NULL; CFDictionaryRef identity_add = NULL; + CFNumberRef scep_key_usage = NULL; + CFNumberRef scep_key_bitsize = NULL; + + CFURLRef url = NULL; + + CFDataRef data = NULL; + CFStringRef ctype = NULL; + scep_base_url = CFStringCreateWithCString(kCFAllocatorDefault, argv[0], kCFStringEncodingASCII); #if 0 @@ -342,8 +354,8 @@ extern int command_scep(int argc, char * const *argv) CFShow(scep_subject); #endif - CFNumberRef scep_key_usage = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &key_usage); - CFNumberRef scep_key_bitsize = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &key_bitsize); + scep_key_usage = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &key_usage); + scep_key_bitsize = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &key_bitsize); const void *keygen_keys[] = { kSecAttrKeyType, kSecAttrKeySizeInBits }; const void *keygen_vals[] = { kSecAttrKeyTypeRSA, scep_key_bitsize }; @@ -365,15 +377,13 @@ extern int command_scep(int argc, char * const *argv) used to carry the certificates to the requester, with a Content-Type of application/x-x509-ca-ra-cert. */ - CFDataRef data = NULL; - CFStringRef ctype = NULL; SecCertificateRef ca_certificate = NULL, ra_certificate = NULL; SecCertificateRef ra_encryption_certificate = NULL; CFArrayRef ra_certificates = NULL; CFTypeRef scep_certificates = NULL; SecCertificateRef scep_signing_certificate = NULL; - CFURLRef url = scep_url_operation(scep_base_url, CFSTR("GetCACert"), scep_instance_name); + url = scep_url_operation(scep_base_url, CFSTR("GetCACert"), scep_instance_name); data = MCNetworkLoadRequest(url, NULL, NULL, &ctype, validate_cert); if (data && ctype) { @@ -415,6 +425,8 @@ extern int command_scep(int argc, char * const *argv) goto out; } + (void) scep_signing_certificate; // Silence analyzer + #if 0 GetCACaps capabilities advertised by SCEP server: @@ -469,6 +481,11 @@ extern int command_scep(int argc, char * const *argv) scep_can_use_post = CFArrayContainsValue(caps, caps_length, CFSTR("POSTPKIOperation")); scep_use_3des = CFArrayContainsValue(caps, caps_length, CFSTR("DES3")); scep_can_use_sha1 = CFArrayContainsValue(caps, caps_length, CFSTR("SHA-1")); + + // We probably inteded these to be the values and not override them below.. + // but for now to quiet the analyzer we reference them here. see scep.c, command_scep assumes 3des and sha1 + (void) scep_use_3des; + (void) scep_can_use_sha1; } scep_use_3des = true; @@ -531,10 +548,12 @@ extern int command_scep(int argc, char * const *argv) CFDataRef retry_get_cert_initial = NULL; CFDictionaryRef error_dict = CFErrorCopyUserInfo(server_error); retry_get_cert_initial = SecSCEPGetCertInitial(ra_certificate ? ra_certificate : ca_certificate, scep_subject, NULL, error_dict, self_signed_identity, scep_certificates); - if (scep_reply) CFRelease(scep_reply); + CFReleaseNull(scep_reply); + CFReleaseSafe(error_dict); fprintf(stderr, "Waiting 10 seconds before trying a GetCertInitial\n"); sleep(10); scep_reply = perform_pki_op(scep_base_url, retry_get_cert_initial, scep_can_use_post, validate_cert); + CFReleaseSafe(retry_get_cert_initial); } require(issued_certs, out); @@ -567,12 +586,20 @@ extern int command_scep(int argc, char * const *argv) out: SecItemDelete(identity_add); - if (identity_add) CFRelease(identity_add); + CFReleaseSafe(identity_add); //if (uuid_cfstr) CFRelease(uuid_cfstr); - if (candidate_identity) CFRelease(candidate_identity); - if (scep_request) CFRelease(scep_request); - if (scep_reply) CFRelease(scep_reply); - if (csr_parameters) CFRelease(csr_parameters); + CFReleaseSafe(candidate_identity); + CFReleaseSafe(scep_request); + CFReleaseSafe(scep_reply); + CFReleaseSafe(scep_key_usage); + CFReleaseSafe(scep_key_bitsize); + CFReleaseSafe(csr_parameters); + CFReleaseSafe(scep_subject_name); + CFReleaseSafe(scep_base_url); + CFReleaseSafe(url); + CFReleaseSafe(issued_certs); + CFReleaseSafe(data); + CFReleaseSafe(ctype); return result; } diff --git a/sec/Security/Tool/show_certificates.c b/Security/sec/Security/Tool/show_certificates.c similarity index 77% rename from sec/Security/Tool/show_certificates.c rename to Security/sec/Security/Tool/show_certificates.c index 1e404f53..6725f74b 100644 --- a/sec/Security/Tool/show_certificates.c +++ b/Security/sec/Security/Tool/show_certificates.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2007,2009-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2007,2009-2010,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -56,81 +56,16 @@ #include #include +#include "keychain_util.h" typedef uint32_t SecProtocolType; typedef uint32_t SecAuthenticationType; -static void -keychain_query_parse_string(CFMutableDictionaryRef q, CFStringRef s) { - bool inkey = true; - bool escaped = false; - CFStringRef key = NULL; - CFMutableStringRef str = CFStringCreateMutable(0, 0); - CFRange rng = { .location = 0, .length = CFStringGetLength(s) }; - CFCharacterSetRef cs_key = CFCharacterSetCreateWithCharactersInString(0, CFSTR("=\\")); - CFCharacterSetRef cs_value = CFCharacterSetCreateWithCharactersInString(0, CFSTR(",\\")); - while (rng.length) { - CFRange r; - CFStringRef sub; - bool complete = false; - if (escaped) { - r.location = rng.location; - r.length = 1; - sub = CFStringCreateWithSubstring(0, s, r); - escaped = false; - } else if (CFStringFindCharacterFromSet(s, inkey ? cs_key : cs_value, rng, 0, &r)) { - if (CFStringGetCharacterAtIndex(s, r.location) == '\\') { - escaped = true; - } else { - complete = true; - } - CFIndex next = r.location + 1; - r.length = r.location - rng.location; - r.location = rng.location; - sub = CFStringCreateWithSubstring(0, s, r); - rng.length -= next - rng.location; - rng.location = next; - } else { - sub = CFStringCreateWithSubstring(0, s, rng); - rng.location += rng.length; - rng.length = 0; - complete = true; - } - CFStringAppend(str, sub); - CFRelease(sub); - if (complete) { - CFStringRef value = CFStringCreateCopy(0, str); - CFStringReplaceAll(str, CFSTR("")); - if (inkey) { - key = value; - } else { - CFDictionarySetValue(q, key, value); - CFReleaseNull(value); - CFReleaseNull(key); - } - inkey = !inkey; - } - } - if (key) { - /* Dangeling key value is true?. */ - CFDictionarySetValue(q, key, kCFBooleanTrue); - CFRelease(key); - } - CFRelease(str); -} - -static void -keychain_query_parse_cstring(CFMutableDictionaryRef q, const char *query) { - CFStringRef s; - s = CFStringCreateWithCStringNoCopy(0, query, kCFStringEncodingUTF8, kCFAllocatorNull); - keychain_query_parse_string(q, s); - CFRelease(s); -} static void show_cert_eval(CFArrayRef certs, bool verbose) { SecPolicyRef policy = SecPolicyCreateSSL(true, NULL); SecTrustRef trust = NULL; - OSStatus status = SecTrustCreateWithCertificates(certs, policy, &trust); + SecTrustCreateWithCertificates(certs, policy, &trust); SecTrustResultType trustResult; const char *trustResults[] = { "invalid", @@ -142,7 +77,7 @@ static void show_cert_eval(CFArrayRef certs, bool verbose) { "fatal trust failure", "other error", }; - status = SecTrustEvaluate(trust, &trustResult); + (void) SecTrustEvaluate(trust, &trustResult); printf("* trust: %s *\n", trustResults[trustResult]); CFArrayRef properties = SecTrustCopyProperties(trust); print_plist(properties); @@ -227,7 +162,10 @@ int keychain_show_certificates(int argc, char * const *argv) output_finger_print = true; break; case 'q': - keychain_query_parse_cstring(query, optarg); + if (!keychain_query_parse_cstring(query, optarg)) { + CFReleaseNull(query); + return 1; + } keychain_certs = true; break; case '?': @@ -249,7 +187,11 @@ int keychain_show_certificates(int argc, char * const *argv) int arg; if (keychain_certs) { for (arg = 0; arg < argc; ++arg) { - keychain_query_parse_cstring(query, argv[arg]); + if (!keychain_query_parse_cstring(query, argv[arg])) { + CFReleaseSafe(query); + CFReleaseSafe(certs); + return 1; + } } CFDictionarySetValue(query, kSecClass, kSecClassCertificate); CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll); @@ -321,6 +263,7 @@ int keychain_show_certificates(int argc, char * const *argv) } fprintf(stdout, "\n"); } + CFReleaseSafe(key_fingerprint); } if (output_pem) { print_buffer_pem(stdout, "CERTIFICATE", diff --git a/sec/Security/Tool/spc.c b/Security/sec/Security/Tool/spc.c similarity index 93% rename from sec/Security/Tool/spc.c rename to Security/sec/Security/Tool/spc.c index 875ea6da..816a7c4d 100644 --- a/sec/Security/Tool/spc.c +++ b/Security/sec/Security/Tool/spc.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2009-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 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, @@ -17,14 +17,13 @@ * 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@ */ /* * spc.c - Security * - * Created by Conrad Sauerwald on 1/9/09. * */ @@ -228,7 +227,7 @@ static void _query_string_apply(const void *key, const void *value, void *contex CFRelease(escaped_value); } -static CFURLRef build_url(CFStringRef base, CFDictionaryRef info) +static CF_RETURNS_RETAINED CFURLRef build_url(CFStringRef base, CFDictionaryRef info) { CFURLRef url = NULL, base_url = NULL; CFMutableStringRef query_string = @@ -238,7 +237,8 @@ static CFURLRef build_url(CFStringRef base, CFDictionaryRef info) CFDictionaryApplyFunction(info, _query_string_apply, query_string); base_url = CFURLCreateWithString(kCFAllocatorDefault, base, NULL); url = CFURLCreateWithString(kCFAllocatorDefault, query_string, base_url); -out: +out: + CFReleaseSafe(query_string); CFReleaseSafe(base_url); return url; } @@ -268,13 +268,15 @@ static bool auth_failed(CFHTTPMessageRef request, CFReadStreamRef readStream) CFStringRef cf_user = CFStringCreateWithCString(kCFAllocatorDefault, user, kCFStringEncodingUTF8); CFStringRef cf_pass = CFStringCreateWithCString(kCFAllocatorDefault, pass, kCFStringEncodingUTF8); CFHTTPMessageAddAuthentication(request, responseHeaders, cf_user, cf_pass, NULL, false); + CFReleaseSafe(cf_pass); + CFReleaseSafe(cf_user); } CFRelease(responseHeaders); } return isAuthenticationChallenge; } -static CFHTTPMessageRef load_request(CFHTTPMessageRef request, CFMutableDataRef data, int retry) +static CF_RETURNS_RETAINED CFHTTPMessageRef load_request(CFHTTPMessageRef request, CFMutableDataRef data, int retry) { CFHTTPMessageRef result = NULL; @@ -307,8 +309,10 @@ static CFHTTPMessageRef load_request(CFHTTPMessageRef request, CFMutableDataRef if (auth_failed(request, rs)) { CFReadStreamClose(rs); CFDataSetLength(data, 0); - if (retry) + if (retry) { + CFReleaseSafe(rs); return load_request(request, data, retry - 1); + } break; } UInt8 buf[BUFSIZE]; @@ -373,9 +377,11 @@ static CFDictionaryRef get_encrypted_profile_packet(CFStringRef base_url) CFRelease(machine_dict); CFURLRef url = build_url(base_url, NULL); - CFHTTPMessageRef request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, + CFHTTPMessageRef request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("POST"), url, kCFHTTPVersion1_1); + CFRelease(url); CFHTTPMessageSetBody(request, signed_data); + CFRelease(signed_data); CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Content-Type"), CFSTR("application/pkcs7-signature")); CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0); @@ -441,6 +447,8 @@ static SecIdentityRef perform_scep(CFDictionaryRef scep_dict) CFStringRef scep_base_url = NULL, scep_instance_name = NULL, scep_challenge = NULL, scep_subject = NULL, scep_subject_requested = NULL; CFTypeRef scep_key_bitsize = NULL; + CFNumberRef key_usage_num = NULL; + SecCertificateRef ca_cert = NULL; const void *keygen_keys[] = { kSecAttrKeyType, kSecAttrKeySizeInBits }; const void *keygen_vals[] = { kSecAttrKeyTypeRSA, CFSTR("512") }; @@ -475,13 +483,12 @@ static SecIdentityRef perform_scep(CFDictionaryRef scep_dict) &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); int key_usage = kSecKeyUsageDigitalSignature | kSecKeyUsageKeyEncipherment; - CFNumberRef key_usage_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &key_usage); + key_usage_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &key_usage); const void *key[] = { kSecCSRChallengePassword, kSecCertificateKeyUsage }; const void *val[] = { scep_challenge ? scep_challenge : CFSTR("magic"), key_usage_num }; - csr_parameters = CFDictionaryCreate(kCFAllocatorDefault, - key, val, array_size(key), NULL, NULL); + csr_parameters = CFDictionaryCreate(kCFAllocatorDefault, key, val, array_size(key), NULL, NULL); - SecCertificateRef ca_cert = get_ca_cert(scep_base_url, scep_instance_name ? scep_instance_name : CFSTR("test")); + ca_cert = get_ca_cert(scep_base_url, scep_instance_name ? scep_instance_name : CFSTR("test")); if (!ca_cert) errx(1, "no ca cert returned from scep server."); @@ -489,12 +496,17 @@ static SecIdentityRef perform_scep(CFDictionaryRef scep_dict) if (!identity) errx(1, "failed to get identity from scep server."); + out: + CFReleaseSafe(ca_cert); + CFReleaseSafe(scep_subject); + CFReleaseSafe(key_usage_num); + CFReleaseSafe(csr_parameters); CFReleaseSafe(parameters); return identity; } -static CFDataRef get_profile(CFStringRef url_cfstring, SecIdentityRef identity) +static CFDataRef CF_RETURNS_RETAINED get_profile(CFStringRef url_cfstring, SecIdentityRef identity) { CFURLRef url = NULL; CFHTTPMessageRef request = NULL; @@ -528,7 +540,9 @@ out: static bool validate_profile(CFDataRef profile_plist_data, SecIdentityRef identity) { CFStringRef type = NULL, uuid = NULL; + CFMutableDataRef dec_data = NULL; CFDataRef enc_payload = NULL; + bool ok = false; CFTypeRef result = CFPropertyListCreateWithData(kCFAllocatorDefault, profile_plist_data, kCFPropertyListImmutable, NULL, NULL); require(valid_cf_obj(result, CFDictionaryGetTypeID()), out); @@ -539,19 +553,19 @@ static bool validate_profile(CFDataRef profile_plist_data, SecIdentityRef identi enc_payload = dict_get_value_of_type(result, CFSTR("EncryptedPayloadContent"), CFDataGetTypeID()); if (enc_payload) { - CFMutableDataRef dec_data = CFDataCreateMutable(kCFAllocatorDefault, 0); + dec_data = CFDataCreateMutable(kCFAllocatorDefault, 0); require_noerr(SecCMSDecryptEnvelopedData(enc_payload, dec_data, NULL), out); - bool sub = validate_profile(dec_data, identity); - CFReleaseSafe(dec_data); - return sub; + ok = validate_profile(dec_data, identity); } else { + ok = true; if (debug) write_data("/tmp/unencrypted_profile.mobileconfig", profile_plist_data); //CFDictionaryRef sub_conf = dict_get_value_of_type(result, CFSTR("PayloadContent"), CFDictionaryGetTypeID()); } - return true; out: - return false; + CFReleaseSafe(dec_data); + CFReleaseSafe(result); + return ok; } #if 0 @@ -662,42 +676,51 @@ extern int command_spc(int argc, char * const *argv) if (argc != 1) return 2; - CFStringRef machine_id_url_cfstring = CFStringCreateWithCString(kCFAllocatorDefault, + int result = -1; + CFDictionaryRef dict = NULL; + CFDictionaryRef scep_config = NULL; + CFDictionaryRef payload_content = NULL; + CFStringRef profile_url = NULL; + CFDataRef profile_data = NULL; + CFDataRef profile_plist = NULL; + CFStringRef machine_id_url_cfstring = CFStringCreateWithCString(kCFAllocatorDefault, argv[0], kCFStringEncodingUTF8); - CFDictionaryRef enroll_packet = get_encrypted_profile_packet(machine_id_url_cfstring); require(enroll_packet && CFGetTypeID(enroll_packet) == CFDictionaryGetTypeID(), out); //require(payload_type(enroll_packet, "Encrypted Profile Service"), out); - CFDictionaryRef scep_config = NULL; - CFDictionaryRef payload_content = NULL; - require(payload_content = dict_get_value_of_type(enroll_packet, + require(payload_content = dict_get_value_of_type(enroll_packet, CFSTR("PayloadContent"), CFDictionaryGetTypeID()), out); require(scep_config = dict_get_value_of_type(payload_content, CFSTR("SCEP"), CFDictionaryGetTypeID()), out); require(identity = perform_scep(scep_config), out); - CFDictionaryRef dict = CFDictionaryCreate(NULL, &kSecValueRef, (const void **)&identity, 1, NULL, NULL); + dict = CFDictionaryCreate(NULL, &kSecValueRef, (const void **)&identity, 1, NULL, NULL); require_noerr(SecItemAdd(dict, NULL), out); - CFReleaseSafe(dict); - CFStringRef profile_url = NULL; - require(profile_url = dict_get_value_of_type(payload_content, + CFReleaseNull(dict); + require(profile_url = dict_get_value_of_type(payload_content, CFSTR("URL"), CFStringGetTypeID()), out); - CFDataRef profile_data = NULL; require(profile_data = get_profile(profile_url, identity), out); - CFDataRef profile_plist = NULL; if (debug) write_data("/tmp/profile.mobileconfig", profile_data); require_noerr(SecCMSVerify(profile_data, NULL, NULL, NULL, &profile_plist), out); - CFRelease(profile_data); + CFReleaseNull(profile_data); require(profile_plist, out); require(validate_profile(profile_plist, identity), out); - return 0; -out: - errx(1, "fail."); - return -1; + result = 0; +out: + CFReleaseSafe(dict); + CFReleaseSafe(identity); + CFReleaseSafe(enroll_packet); + CFReleaseSafe(profile_data); + CFReleaseSafe(profile_plist); + CFReleaseSafe(machine_id_url_cfstring); + + if (result != 0) + errx(1, "fail."); + return result; } diff --git a/Security/sec/Security/certextensions.h b/Security/sec/Security/certextensions.h new file mode 100644 index 00000000..d6fbb4df --- /dev/null +++ b/Security/sec/Security/certextensions.h @@ -0,0 +1,546 @@ +/* + * Copyright (c) 2000-2009,2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + * + * CertExtensions.h -- X.509 Cert Extensions as C structs + */ + +#ifndef _CERT_EXTENSIONS_H_ +#define _CERT_EXTENSIONS_H_ + +#include +#include +//#include + +/*** + *** Structs for declaring extension-specific data. + ***/ + +/* + * GeneralName, used in AuthorityKeyID, SubjectAltName, and + * IssuerAltName. + * + * For now, we just provide explicit support for the types which are + * represented as IA5Strings, OIDs, and octet strings. Constructed types + * such as EDIPartyName and x400Address are not explicitly handled + * right now and must be encoded and decoded by the caller. (See exception + * for Name and OtherName, below). In those cases the SecCEGeneralName.name.Data field + * represents the BER contents octets; SecCEGeneralName.name.Length is the + * length of the contents; the tag of the field is not needed - the BER + * encoding uses context-specific implicit tagging. The berEncoded field + * is set to true in these case. Simple types have berEncoded = false. + * + * In the case of a GeneralName in the form of a Name, we parse the Name + * into a CSSM_X509_NAME and place a pointer to the CSSM_X509_NAME in the + * SecCEGeneralName.name.Data field. SecCEGeneralName.name.Length is set to + * sizeof(CSSM_X509_NAME). In this case berEncoded is false. + * + * In the case of a GeneralName in the form of a OtherName, we parse the fields + * into a SecCEOtherName and place a pointer to the SecCEOtherName in the + * SecCEGeneralName.name.Data field. SecCEGeneralName.name.Length is set to + * sizeof(SecCEOtherName). In this case berEncoded is false. + * + * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + * + * GeneralName ::= CHOICE { + * otherName [0] OtherName + * rfc822Name [1] IA5String, + * dNSName [2] IA5String, + * x400Address [3] ORAddress, + * directoryName [4] Name, + * ediPartyName [5] EDIPartyName, + * uniformResourceIdentifier [6] IA5String, + * iPAddress [7] OCTET STRING, + * registeredID [8] OBJECT IDENTIFIER} + * + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + * + * EDIPartyName ::= SEQUENCE { + * nameAssigner [0] DirectoryString OPTIONAL, + * partyName [1] DirectoryString } + */ +typedef enum { + GNT_OtherName = 0, + GNT_RFC822Name, + GNT_DNSName, + GNT_X400Address, + GNT_DirectoryName, + GNT_EdiPartyName, + GNT_URI, + GNT_IPAddress, + GNT_RegisteredID +} SecCEGeneralNameType; + +typedef struct { + DERItem typeId; + DERItem value; // unparsed, BER-encoded +} SecCEOtherName; + +typedef struct { + SecCEGeneralNameType nameType; // GNT_RFC822Name, etc. + bool berEncoded; + DERItem name; +} SecCEGeneralName; + +typedef struct { + uint32_t numNames; + SecCEGeneralName *generalName; +} SecCEGeneralNames; + +/* + * id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } + * + * AuthorityKeyIdentifier ::= SEQUENCE { + * keyIdentifier [0] KeyIdentifier OPTIONAL, + * authorityCertIssuer [1] GeneralNames OPTIONAL, + * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } + * + * KeyIdentifier ::= OCTET STRING + * + * CSSM OID = CSSMOID_AuthorityKeyIdentifier + */ +typedef struct { + bool keyIdentifierPresent; + DERItem keyIdentifier; + bool generalNamesPresent; + SecCEGeneralNames *generalNames; + bool serialNumberPresent; + DERItem serialNumber; +} SecCEAuthorityKeyID; + +/* + * id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } + * SubjectKeyIdentifier ::= KeyIdentifier + * + * CSSM OID = CSSMOID_SubjectKeyIdentifier + */ +typedef DERItem SecCESubjectKeyID; + +/* + * id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } + * + * KeyUsage ::= BIT STRING { + * digitalSignature (0), + * nonRepudiation (1), + * keyEncipherment (2), + * dataEncipherment (3), + * keyAgreement (4), + * keyCertSign (5), + * cRLSign (6), + * encipherOnly (7), + * decipherOnly (8) } + * + * CSSM OID = CSSMOID_KeyUsage + * + */ +typedef uint16_t SecCEKeyUsage; + +#define SecCEKU_DigitalSignature 0x8000 +#define SecCEKU_NonRepudiation 0x4000 +#define SecCEKU_KeyEncipherment 0x2000 +#define SecCEKU_DataEncipherment 0x1000 +#define SecCEKU_KeyAgreement 0x0800 +#define SecCEKU_KeyCertSign 0x0400 +#define SecCEKU_CRLSign 0x0200 +#define SecCEKU_EncipherOnly 0x0100 +#define SecCEKU_DecipherOnly 0x0080 + +/* + * id-ce-cRLReason OBJECT IDENTIFIER ::= { id-ce 21 } + * + * -- reasonCode ::= { CRLReason } + * + * CRLReason ::= ENUMERATED { + * unspecified (0), + * keyCompromise (1), + * cACompromise (2), + * affiliationChanged (3), + * superseded (4), + * cessationOfOperation (5), + * certificateHold (6), + * removeFromCRL (8) } + * + * CSSM OID = CSSMOID_CrlReason + * + */ +typedef uint32_t SecCECrlReason; + +#define SecCECR_Unspecified 0 +#define SecCECR_KeyCompromise 1 +#define SecCECR_CACompromise 2 +#define SecCECR_AffiliationChanged 3 +#define SecCECR_Superseded 4 +#define SecCECR_CessationOfOperation 5 +#define SecCECR_CertificateHold 6 +#define SecCECR_RemoveFromCRL 8 + +/* + * id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } + * + * SubjectAltName ::= GeneralNames + * + * CSSM OID = CSSMOID_SubjectAltName + * + * GeneralNames defined above. + */ + +/* + * id-ce-extKeyUsage OBJECT IDENTIFIER ::= {id-ce 37} + * + * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId* + * + * KeyPurposeId ::= OBJECT IDENTIFIER + * + * CSSM OID = CSSMOID_ExtendedKeyUsage + */ +typedef struct { + uint32_t numPurposes; + DERItem *purposes; // in Intel pre-encoded format +} SecCEExtendedKeyUsage; + +/* + * id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } + * + * BasicConstraints ::= SEQUENCE { + * cA BOOLEAN DEFAULT FALSE, + * pathLenConstraint INTEGER (0..MAX) OPTIONAL } + * + * CSSM OID = CSSMOID_BasicConstraints + */ +typedef struct { + bool present; + bool critical; + bool isCA; + bool pathLenConstraintPresent; + uint32_t pathLenConstraint; +} SecCEBasicConstraints; + +typedef struct { + bool present; + bool critical; + bool requireExplicitPolicyPresent; + uint32_t requireExplicitPolicy; + bool inhibitPolicyMappingPresent; + uint32_t inhibitPolicyMapping; +} SecCEPolicyConstraints; + +/* + * id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } + * + * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation + * + * PolicyInformation ::= SEQUENCE { + * policyIdentifier CertPolicyId, + * policyQualifiers SEQUENCE SIZE (1..MAX) OF + * PolicyQualifierInfo OPTIONAL } + * + * CertPolicyId ::= OBJECT IDENTIFIER + * + * PolicyQualifierInfo ::= SEQUENCE { + * policyQualifierId PolicyQualifierId, + * qualifier ANY DEFINED BY policyQualifierId } + * + * -- policyQualifierIds for Internet policy qualifiers + * + * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } + * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } + * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } + * + * PolicyQualifierId ::= + * OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) + * + * Qualifier ::= CHOICE { + * cPSuri CPSuri, + * userNotice UserNotice } + * + * CPSuri ::= IA5String + * + * UserNotice ::= SEQUENCE { + * noticeRef NoticeReference OPTIONAL, + * explicitText DisplayText OPTIONAL} + * + * NoticeReference ::= SEQUENCE { + * organization DisplayText, + * noticeNumbers SEQUENCE OF INTEGER } + * + * DisplayText ::= CHOICE { + * visibleString VisibleString (SIZE (1..200)), + * bmpString BMPString (SIZE (1..200)), + * utf8String UTF8String (SIZE (1..200)) } + * + * CSSM OID = CSSMOID_CertificatePolicies + * + * We only support down to the level of Qualifier, and then only the CPSuri + * choice. UserNotice is transmitted to and from this library as a raw + * CSSM_DATA containing the BER-encoded UserNotice sequence. + */ +#if 0 +typedef struct { + DERItem policyQualifierId; // CSSMOID_QT_CPS, CSSMOID_QT_UNOTICE + DERItem qualifier; // CSSMOID_QT_CPS: IA5String contents + // CSSMOID_QT_UNOTICE : Sequence contents +} SecCEPolicyQualifierInfo; +#endif + +typedef struct { + DERItem policyIdentifier; + DERItem policyQualifiers; +} SecCEPolicyInformation; + +typedef struct { + bool present; + bool critical; + size_t numPolicies; // size of *policies; + SecCEPolicyInformation *policies; +} SecCECertificatePolicies; + +typedef struct { + DERItem issuerDomainPolicy; + DERItem subjectDomainPolicy; +} SecCEPolicyMapping; + +/* + PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { + issuerDomainPolicy CertPolicyId, + subjectDomainPolicy CertPolicyId } +*/ +typedef struct { + bool present; + bool critical; + uint32_t numMappings; // size of *mappings; + SecCEPolicyMapping *mappings; +} SecCEPolicyMappings; + +#if 0 +typedef struct { + bool present; + bool critical; + uint32_t skipCerts; +} SecCEInhibitAnyPolicy; + +/* + * netscape-cert-type, a bit string. + * + * CSSM OID = CSSMOID_NetscapeCertType + * + * Bit fields defined in oidsattr.h: SecCENCT_SSL_Client, etc. + */ +typedef uint16_t SecCENetscapeCertType; + +/* + * CRLDistributionPoints. + * + * id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } + * + * cRLDistributionPoints ::= { + * CRLDistPointsSyntax } + * + * CRLDistPointsSyntax ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint + * + * NOTE: RFC 2459 claims that the tag for the optional DistributionPointName + * is IMPLICIT as shown here, but in practice it is EXPLICIT. It has to be - + * because the underlying type also uses an implicit tag for distinguish + * between CHOICEs. + * + * DistributionPoint ::= SEQUENCE { + * distributionPoint [0] DistributionPointName OPTIONAL, + * reasons [1] ReasonFlags OPTIONAL, + * cRLIssuer [2] GeneralNames OPTIONAL } + * + * DistributionPointName ::= CHOICE { + * fullName [0] GeneralNames, + * nameRelativeToCRLIssuer [1] RelativeDistinguishedName } + * + * ReasonFlags ::= BIT STRING { + * unused (0), + * keyCompromise (1), + * cACompromise (2), + * affiliationChanged (3), + * superseded (4), + * cessationOfOperation (5), + * certificateHold (6) } + * + * CSSM OID = CSSMOID_CrlDistributionPoints + */ + +/* + * Note that this looks similar to SecCECrlReason, but that's an enum and this + * is an OR-able bit string. + */ +typedef uint8_t SecCECrlDistReasonFlags; + +#define SecCECD_Unspecified 0x80 +#define SecCECD_KeyCompromise 0x40 +#define SecCECD_CACompromise 0x20 +#define SecCECD_AffiliationChanged 0x10 +#define SecCECD_Superseded 0x08 +#define SecCECD_CessationOfOperation 0x04 +#define SecCECD_CertificateHold 0x02 + +typedef enum { + SecCECDNT_FullName, + SecCECDNT_NameRelativeToCrlIssuer +} SecCECrlDistributionPointNameType; + +typedef struct { + SecCECrlDistributionPointNameType nameType; + union { + SecCEGeneralNames *fullName; + CSSM_X509_RDN_PTR rdn; + } dpn; +} SecCEDistributionPointName; + +/* + * The top-level CRLDistributionPoint. + * All fields are optional; NULL pointers indicate absence. + */ +typedef struct { + SecCEDistributionPointName *distPointName; + bool reasonsPresent; + SecCECrlDistReasonFlags reasons; + SecCEGeneralNames *crlIssuer; +} SecCECRLDistributionPoint; + +typedef struct { + uint32_t numDistPoints; + SecCECRLDistributionPoint *distPoints; +} SecCECRLDistPointsSyntax; + +/* + * Authority Information Access and Subject Information Access. + * + * CSSM OID = CSSMOID_AuthorityInfoAccess + * CSSM OID = CSSMOID_SubjectInfoAccess + * + * SubjAuthInfoAccessSyntax ::= + * SEQUENCE SIZE (1..MAX) OF AccessDescription + * + * AccessDescription ::= SEQUENCE { + * accessMethod OBJECT IDENTIFIER, + * accessLocation GeneralName } + */ +typedef struct { + DERItem accessMethod; + SecCEGeneralName accessLocation; +} SecCEAccessDescription; + +typedef struct { + uint32_t numAccessDescriptions; + SecCEAccessDescription *accessDescriptions; +} SecCEAuthorityInfoAccess; + +/*** CRL extensions ***/ + +/* + * cRLNumber, an integer. + * + * CSSM OID = CSSMOID_CrlNumber + */ +typedef uint32_t SecCECrlNumber; + +/* + * deltaCRLIndicator, an integer. + * + * CSSM OID = CSSMOID_DeltaCrlIndicator + */ +typedef uint32_t SecCEDeltaCrl; + +/* + * IssuingDistributionPoint + * + * id-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-ce 28 } + * + * issuingDistributionPoint ::= SEQUENCE { + * distributionPoint [0] DistributionPointName OPTIONAL, + * onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE, + * onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE, + * onlySomeReasons [3] ReasonFlags OPTIONAL, + * indirectCRL [4] BOOLEAN DEFAULT FALSE } + * + * CSSM OID = CSSMOID_IssuingDistributionPoint + */ +typedef struct { + SecCEDistributionPointName *distPointName; // optional + bool onlyUserCertsPresent; + bool onlyUserCerts; + bool onlyCACertsPresent; + bool onlyCACerts; + bool onlySomeReasonsPresent; + SecCECrlDistReasonFlags onlySomeReasons; + bool indirectCrlPresent; + bool indirectCrl; +} SecCEIssuingDistributionPoint; + +/* + * An enumerated list identifying one of the above per-extension + * structs. + */ +typedef enum { + DT_AuthorityKeyID, // SecCEAuthorityKeyID + DT_SubjectKeyID, // SecCESubjectKeyID + DT_KeyUsage, // SecCEKeyUsage + DT_SubjectAltName, // implies SecCEGeneralName + DT_IssuerAltName, // implies SecCEGeneralName + DT_ExtendedKeyUsage, // SecCEExtendedKeyUsage + DT_BasicConstraints, // SecCEBasicConstraints + DT_CertPolicies, // SecCECertPolicies + DT_NetscapeCertType, // SecCENetscapeCertType + DT_CrlNumber, // SecCECrlNumber + DT_DeltaCrl, // SecCEDeltaCrl + DT_CrlReason, // SecCECrlReason + DT_CrlDistributionPoints, // SecCECRLDistPointsSyntax + DT_IssuingDistributionPoint,// SecCEIssuingDistributionPoint + DT_AuthorityInfoAccess, // SecCEAuthorityInfoAccess + DT_Other // unknown, raw data as a CSSM_DATA +} SecCEDataType; + +/* + * One unified representation of all the cert adn CRL extensions we know about. + */ +typedef union { + SecCEAuthorityKeyID authorityKeyID; + SecCESubjectKeyID subjectKeyID; + SecCEKeyUsage keyUsage; + SecCEGeneralNames subjectAltName; + SecCEGeneralNames issuerAltName; + SecCEExtendedKeyUsage extendedKeyUsage; + SecCEBasicConstraints basicConstraints; + SecCECertPolicies certPolicies; + SecCENetscapeCertType netscapeCertType; + SecCECrlNumber crlNumber; + SecCEDeltaCrl deltaCrl; + SecCECrlReason crlReason; + SecCECRLDistPointsSyntax crlDistPoints; + SecCEIssuingDistributionPoint issuingDistPoint; + SecCEAuthorityInfoAccess authorityInfoAccess; + DERItem rawData; // unknown, not decoded +} SecCEData; + +typedef struct { + SecCEDataType type; + SecCEData extension; + bool critical; +} SecCEDataAndType; +#endif /* 0 */ + +#endif /* _CERT_EXTENSIONS_H_ */ diff --git a/Security/sec/Security/cssmapple.h b/Security/sec/Security/cssmapple.h new file mode 100644 index 00000000..6dc1438b --- /dev/null +++ b/Security/sec/Security/cssmapple.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2000-2004,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@ + * + * cssmapple.h -- CSSM features specific to Apple's Implementation + */ + +#ifndef _CSSMAPPLE_H_ +#define _CSSMAPPLE_H_ 1 + + +#ifdef __cplusplus +extern "C" { +#endif + +/* First, an array of bits indicating various status of the cert. */ +typedef uint32 CSSM_TP_APPLE_CERT_STATUS; +enum +{ + CSSM_CERT_STATUS_EXPIRED = 0x00000001, + CSSM_CERT_STATUS_NOT_VALID_YET = 0x00000002, + CSSM_CERT_STATUS_IS_IN_INPUT_CERTS = 0x00000004, + CSSM_CERT_STATUS_IS_IN_ANCHORS = 0x00000008, + CSSM_CERT_STATUS_IS_ROOT = 0x00000010, + CSSM_CERT_STATUS_IS_FROM_NET = 0x00000020, + /* settings found in per-user Trust Settings */ + CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_USER = 0x00000040, + /* settings found in Admin Trust Settings */ + CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_ADMIN = 0x00000080, + /* settings found in System Trust Settings */ + CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_SYSTEM = 0x00000100, + /* Trust Settings result = Trust */ + CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST = 0x00000200, + /* Trust Settings result = Deny */ + CSSM_CERT_STATUS_TRUST_SETTINGS_DENY = 0x00000400, + /* Per-cert error ignored due to Trust Settings */ + CSSM_CERT_STATUS_TRUST_SETTINGS_IGNORED_ERROR = 0x00000800 +}; + +typedef struct { + CSSM_TP_APPLE_CERT_STATUS StatusBits; + uint32 NumStatusCodes; + CSSM_RETURN *StatusCodes; + + /* index into raw cert group or AnchorCerts depending on IS_IN_ANCHORS */ + uint32 Index; + + /* nonzero if cert came from a DLDB */ + CSSM_DL_DB_HANDLE DlDbHandle; + CSSM_DB_UNIQUE_RECORD_PTR UniqueRecord; +} CSSM_TP_APPLE_EVIDENCE_INFO; + + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* _CSSMAPPLE_H_ */ diff --git a/Security/sec/Security/keychain_find.h b/Security/sec/Security/keychain_find.h new file mode 100644 index 00000000..59c1abfe --- /dev/null +++ b/Security/sec/Security/keychain_find.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2003-2007,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@ + * + * keychain_find.h + */ + +#ifndef _KEYCHAIN_FINDINTERNETPASSWORD_H_ +#define _KEYCHAIN_FINDINTERNETPASSWORD_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int keychain_item(int argc, char * const *argv); + +extern int keychain_find_internet_password(int argc, char * const *argv); + +extern int keychain_find_generic_password(int argc, char * const *argv); + +extern int keychain_find_certificate(int argc, char * const *argv); + +extern int keychain_delete_internet_password(int argc, char * const *argv); + +extern int keychain_delete_generic_password(int argc, char * const *argv); + +extern int keychain_dump(int argc, char * const *argv); + +extern int keychain_show_certificates(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _KEYCHAIN_FINDINTERNETPASSWORD_H_ */ diff --git a/sec/Security/p12import.c b/Security/sec/Security/p12import.c similarity index 97% rename from sec/Security/p12import.c rename to Security/sec/Security/p12import.c index 500055ab..e4c0e36a 100644 --- a/sec/Security/p12import.c +++ b/Security/sec/Security/p12import.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2010,2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -153,7 +153,7 @@ out: static int p12Decrypt(pkcs12_context * context, const SecAsn1AlgId *algId, const SecAsn1Item *cipherText, SecAsn1Item *plainText) { - NSS_P12_PBE_Params pbep; + NSS_P12_PBE_Params pbep = {}; // XXX/cs not requiring decoding, but if pbep is uninit this will fail later algIdParse(context, algId, &pbep); @@ -265,6 +265,9 @@ out: */ static int shroudedKeyBagParse(pkcs12_context * context, const NSS_P12_SafeBag *safeBag) { + CFDataRef algoidData = NULL; + CFDataRef keyData = NULL; + p12DecodeLog("Found shrouded key bag"); const NSS_P12_ShroudedKeyBag *keyBag = safeBag->bagValue.shroudedKeyBag; @@ -279,7 +282,7 @@ static int shroudedKeyBagParse(pkcs12_context * context, const NSS_P12_SafeBag * &pki), out); DERItem algorithm = { pki.algorithm.algorithm.Data, pki.algorithm.algorithm.Length }; - CFDataRef algoidData = NULL; + algoidData = NULL; if (DEROidCompare(&oidEcPubKey, &algorithm)) { algoidData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, oidEcPubKey.data, oidEcPubKey.length, kCFAllocatorNull); } else if (DEROidCompare(&oidRsa, &algorithm)) { @@ -288,14 +291,16 @@ static int shroudedKeyBagParse(pkcs12_context * context, const NSS_P12_SafeBag * goto out; } require_noerr(emit_item(context, safeBag->bagAttrs, CFSTR("algid"), algoidData), out); - CFRelease(algoidData); + CFReleaseNull(algoidData); - CFDataRef keyData = CFDataCreate(kCFAllocatorDefault, pki.privateKey.Data, pki.privateKey.Length); + keyData = CFDataCreate(kCFAllocatorDefault, pki.privateKey.Data, pki.privateKey.Length); require_noerr(emit_item(context, safeBag->bagAttrs, CFSTR("key"), keyData), out); - CFRelease(keyData); + CFReleaseNull(keyData); return 0; out: + CFReleaseSafe(algoidData); + CFReleaseSafe(keyData); return -1; } @@ -305,6 +310,7 @@ out: */ static int certBagParse(pkcs12_context * context, const NSS_P12_SafeBag *safeBag) { + CFDataRef certData = NULL; p12DecodeLog("found certBag"); NSS_P12_CertBag *certBag = safeBag->bagValue.certBag; @@ -313,7 +319,7 @@ static int certBagParse(pkcs12_context * context, const NSS_P12_SafeBag *safeBag { /* certType = CSSM_CERT_X_509v3; certEncoding = CSSM_CERT_ENCODING_DER; */ - CFDataRef certData = CFDataCreate(kCFAllocatorDefault, certBag->certValue.Data, + certData = CFDataCreate(kCFAllocatorDefault, certBag->certValue.Data, certBag->certValue.Length); require_noerr(emit_item(context, safeBag->bagAttrs, CFSTR("cert"), certData), out); CFRelease(certData); @@ -328,6 +334,7 @@ static int certBagParse(pkcs12_context * context, const NSS_P12_SafeBag *safeBag } return 0; out: + CFReleaseSafe(certData); return -1; } diff --git a/sec/Security/p12import.h b/Security/sec/Security/p12import.h similarity index 94% rename from sec/Security/p12import.h rename to Security/sec/Security/p12import.h index 7d38b006..d52c6fb2 100644 --- a/sec/Security/p12import.h +++ b/Security/sec/Security/p12import.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2008,2010,2012-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/sec/Security/p12pbegen.c b/Security/sec/Security/p12pbegen.c similarity index 99% rename from sec/Security/p12pbegen.c rename to Security/sec/Security/p12pbegen.c index 3341b409..92c05be9 100644 --- a/sec/Security/p12pbegen.c +++ b/Security/sec/Security/p12pbegen.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2008,2010,2012-2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/sec/Security/p12pbegen.h b/Security/sec/Security/p12pbegen.h similarity index 94% rename from sec/Security/p12pbegen.h rename to Security/sec/Security/p12pbegen.h index 96974491..be349b54 100644 --- a/sec/Security/p12pbegen.h +++ b/Security/sec/Security/p12pbegen.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2008,2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2008,2010,2012 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/sec/Security/pbkdf2.c b/Security/sec/Security/pbkdf2.c new file mode 100644 index 00000000..d1684942 --- /dev/null +++ b/Security/sec/Security/pbkdf2.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2000-2001,2012,2014 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please obtain + * a copy of the License at http://www.apple.com/publicsource and read it before + * using this file. + * + * This 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. + */ + + +/* + File: pbkdf2.c + Contains: Apple Data Security Services PKCS #5 PBKDF2 function definition. + Copyright (c) 1999,2012,2014 Apple Inc. All Rights Reserved. +*/ +#include "pbkdf2.h" +#include +/* Will write hLen bytes into dataPtr according to PKCS #5 2.0 spec. + See: http://www.rsa.com/rsalabs/node.asp?id=2127 for details. + tempBuffer is a pointer to at least MAX (hLen, saltLen + 4) + hLen bytes. */ +static void +F (PRF prf, size_t hLen, + const void *passwordPtr, size_t passwordLen, + const void *saltPtr, size_t saltLen, + size_t iterationCount, + uint32_t blockNumber, + void *dataPtr, + void *tempBuffer) +{ + uint8_t *inBlock, *outBlock, *resultBlockPtr; + size_t iteration; + outBlock = (uint8_t*)tempBuffer; + inBlock = outBlock + hLen; + /* Set up inBlock to contain Salt || INT (blockNumber). */ + memcpy (inBlock, saltPtr, saltLen); + + inBlock[saltLen + 0] = (uint8_t)(blockNumber >> 24); + inBlock[saltLen + 1] = (uint8_t)(blockNumber >> 16); + inBlock[saltLen + 2] = (uint8_t)(blockNumber >> 8); + inBlock[saltLen + 3] = (uint8_t)(blockNumber); + + /* Caculate U1 (result goes to outBlock) and copy it to resultBlockPtr. */ + resultBlockPtr = (uint8_t*)dataPtr; + prf (passwordPtr, passwordLen, inBlock, saltLen + 4, outBlock); + memcpy (resultBlockPtr, outBlock, hLen); + /* Calculate U2 though UiterationCount. */ + for (iteration = 2; iteration <= iterationCount; iteration++) + { + uint8_t *tempBlock; + uint32_t byte; + /* Swap inBlock and outBlock pointers. */ + tempBlock = inBlock; + inBlock = outBlock; + outBlock = tempBlock; + /* Now inBlock conatins Uiteration-1. Calculate Uiteration into outBlock. */ + prf (passwordPtr, passwordLen, inBlock, hLen, outBlock); + /* Xor data in dataPtr (U1 \xor U2 \xor ... \xor Uiteration-1) with + outBlock (Uiteration). */ + for (byte = 0; byte < hLen; byte++) + resultBlockPtr[byte] ^= outBlock[byte]; + } +} +void pbkdf2 (PRF prf, size_t hLen, + const void *passwordPtr, size_t passwordLen, + const void *saltPtr, size_t saltLen, + size_t iterationCount, + void *dkPtr, size_t dkLen, + void *tempBuffer) +{ + size_t completeBlocks = dkLen / hLen; + size_t partialBlockSize = dkLen % hLen; + uint32_t blockNumber; + uint8_t *dataPtr = (uint8_t*)dkPtr; + uint8_t *blkBuffer = (uint8_t*)tempBuffer; + + /* This check make sure that the following loops ends, in case where dk_len is 64 bits, and very large. + This will cause the derived key to be the maximum size supported by pbkdf2 (4GB * size of the hash) + rather than the actual requested size.*/ + completeBlocks=completeBlocks & UINT32_MAX; + + /* First calculate all the complete hLen sized blocks required. */ + for (blockNumber = 1; blockNumber <= completeBlocks; blockNumber++) + { + F (prf, hLen, passwordPtr, passwordLen, saltPtr, saltLen, + iterationCount, blockNumber, dataPtr, blkBuffer + hLen); + dataPtr += hLen; + } + /* Finally if the requested output size was not an even multiple of hLen, calculate + the final block and copy the first partialBlockSize bytes of it to the output. */ + if (partialBlockSize > 0) + { + F (prf, hLen, passwordPtr, passwordLen, saltPtr, saltLen, + iterationCount, blockNumber, blkBuffer, blkBuffer + hLen); + memcpy (dataPtr, blkBuffer, partialBlockSize); + } +} diff --git a/Security/sec/Security/pbkdf2.h b/Security/sec/Security/pbkdf2.h new file mode 100644 index 00000000..dddf14d9 --- /dev/null +++ b/Security/sec/Security/pbkdf2.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2000-2001,2012,2014 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please obtain + * a copy of the License at http://www.apple.com/publicsource and read it before + * using this file. + * + * This 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. + */ +#include +#include +#include + +/* + File: pbkdf2.h + Contains: Apple Data Security Services PKCS #5 PBKDF2 function declaration. + Copyright (c) 1999,2012,2014 Apple Inc. All Rights Reserved. +*/ + +#ifndef __PBKDF2__ +#define __PBKDF2__ + +__BEGIN_DECLS + +/* This function should generate a pseudo random octect stream + of hLen bytes long (The value hLen is specified as an argument to pbkdf2 + and should be constant for any given prf function.) which is output in the buffer + pointed to by randomPtr (the caller of this function is responsible for allocation + of the buffer). + The inputs to the pseudo random function are the first keyLen octets pointed + to by keyPtr and the first textLen octets pointed to by textPtr. + Both keyLen and textLen can have any nonzero value. + A good prf would be a HMAC-SHA-1 algorithm where the keyPtr octets serve as + HMAC's "key" and the textPtr octets serve as HMAC's "text". */ +typedef void (*PRF)(const uint8_t *keyPtr, size_t keyLen, + const uint8_t *textPtr, size_t textLen, + uint8_t *randomPtr); + +/* This function implements the PBKDF2 key derrivation algorithm described in + http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-5.html + The output is a derived key of dkLen bytes which is written to the buffer + pointed to by dkPtr. + The caller should ensure dkPtr is at least dkLen bytes long. + The Key is derived from passwordPtr (which is passwordLen bytes long) and from + saltPtr (which is saltLen bytes long). The algorithm used is desacribed in + PKCS #5 version 2.0 and iterationCount iterations are performed. + The argument prf is a pointer to a psuedo random number generator declared above. + It should write exactly hLen bytes into its output buffer each time it is called. + The argument tempBuffer should point to a buffer MAX (hLen, saltLen + 4) + 2 * hLen + bytes long. This buffer is used during the calculation for intermediate results. + Security Considerations: + The argument saltPtr should be a pointer to a buffer of at least 8 random bytes + (64 bits). Thus saltLen should be >= 8. + For each session a new salt should be generated. + The value of iterationCount should be at least 1000 (one thousand). + A good prf would be a HMAC-SHA-1 algorithm where the password serves as + HMAC's "key" and the data serves as HMAC's "text". */ +void pbkdf2 (PRF prf, size_t hLen, + const void *passwordPtr, size_t passwordLen, + const void *saltPtr, size_t saltLen, + size_t iterationCount, + void *dkPtr, size_t dkLen, + void *tempBuffer); + + +#ifdef __cplusplus +} +#endif + +#endif /* __PBKDF2__ */ diff --git a/Security/sec/Security/so_01_serverencryption.c b/Security/sec/Security/so_01_serverencryption.c new file mode 100644 index 00000000..d94fd499 --- /dev/null +++ b/Security/sec/Security/so_01_serverencryption.c @@ -0,0 +1,137 @@ +// +// so_01_ServerEncryption.c +// sec +// +// + + +#include + +#include "Security_regressions.h" + +#include +#include +#include +#include +#include +#include +#include + +unsigned char private_key_der[] = { + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x6c, 0x30, 0x0c, 0xac, 0x33, + 0x9b, 0x4c, 0x70, 0x84, 0xe3, 0x41, 0x75, 0xe2, 0xe6, 0xf5, 0xe1, 0xd1, + 0xb1, 0x35, 0xd1, 0x58, 0xbd, 0x57, 0x8c, 0x2b, 0x1a, 0xf8, 0x70, 0xfa, + 0xca, 0xef, 0x17, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0xad, 0x2d, 0x12, + 0x6c, 0x3f, 0x8f, 0x85, 0xbf, 0x57, 0x96, 0xf6, 0xab, 0x84, 0x9b, 0x57, + 0xa3, 0x51, 0x33, 0xfe, 0xd4, 0x91, 0xec, 0xed, 0x02, 0x54, 0xed, 0x6a, + 0x11, 0x69, 0xd9, 0x28, 0x1f, 0x98, 0x01, 0x8f, 0x1a, 0xa7, 0x1d, 0x22, + 0x28, 0x74, 0xd7, 0x2f, 0x47, 0xb0, 0xb2, 0x8d, 0x84, 0xda, 0xcb, 0x88, + 0x01, 0xb9, 0x6e, 0x81, 0x5c, 0x06, 0xf1, 0x15, 0x12, 0x10, 0xcc, 0x70, + 0x90 +}; + +unsigned char public_cert_der[] = { + 0x30, 0x82, 0x02, 0x41, 0x30, 0x82, 0x01, 0xe7, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0x85, 0x31, 0x15, 0x30, 0x13, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0c, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, + 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x05, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x31, 0x10, + 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x07, 0x43, 0x6f, 0x72, + 0x65, 0x20, 0x4f, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x02, 0x43, 0x41, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, + 0x6f, 0x6e, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x0d, 0x74, 0x65, 0x73, 0x74, 0x40, + 0x74, 0x65, 0x73, 0x74, 0x2c, 0x6f, 0x72, 0x67, 0x30, 0x1e, 0x17, 0x0d, + 0x31, 0x34, 0x30, 0x35, 0x30, 0x32, 0x32, 0x33, 0x33, 0x31, 0x31, 0x33, + 0x5a, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x31, 0x32, 0x36, 0x32, 0x33, 0x33, + 0x31, 0x31, 0x33, 0x5a, 0x30, 0x81, 0x85, 0x31, 0x15, 0x30, 0x13, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0c, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, + 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x05, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x31, 0x10, + 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x07, 0x43, 0x6f, 0x72, + 0x65, 0x20, 0x4f, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x02, 0x43, 0x41, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, + 0x6f, 0x6e, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x0d, 0x74, 0x65, 0x73, 0x74, 0x40, + 0x74, 0x65, 0x73, 0x74, 0x2c, 0x6f, 0x72, 0x67, 0x30, 0x59, 0x30, 0x13, + 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, + 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xad, + 0x2d, 0x12, 0x6c, 0x3f, 0x8f, 0x85, 0xbf, 0x57, 0x96, 0xf6, 0xab, 0x84, + 0x9b, 0x57, 0xa3, 0x51, 0x33, 0xfe, 0xd4, 0x91, 0xec, 0xed, 0x02, 0x54, + 0xed, 0x6a, 0x11, 0x69, 0xd9, 0x28, 0x1f, 0x98, 0x01, 0x8f, 0x1a, 0xa7, + 0x1d, 0x22, 0x28, 0x74, 0xd7, 0x2f, 0x47, 0xb0, 0xb2, 0x8d, 0x84, 0xda, + 0xcb, 0x88, 0x01, 0xb9, 0x6e, 0x81, 0x5c, 0x06, 0xf1, 0x15, 0x12, 0x10, + 0xcc, 0x70, 0x90, 0xa3, 0x46, 0x30, 0x44, 0x30, 0x0e, 0x06, 0x03, 0x55, + 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x03, 0xb8, 0x30, + 0x12, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, + 0x06, 0x06, 0x04, 0x55, 0x1d, 0x25, 0x00, 0x30, 0x1e, 0x06, 0x03, 0x55, + 0x1d, 0x11, 0x04, 0x17, 0x30, 0x15, 0x82, 0x13, 0x64, 0x6f, 0x6e, 0x74, + 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6d, 0x65, 0x2e, 0x63, 0x72, + 0x61, 0x7a, 0x79, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xb6, + 0x07, 0x44, 0xa0, 0xad, 0xb2, 0x68, 0x85, 0x5e, 0x40, 0x9e, 0x28, 0x7a, + 0xb6, 0x5a, 0x4d, 0x63, 0x2a, 0xb4, 0x3d, 0x51, 0x56, 0xe9, 0x00, 0x86, + 0xa9, 0xf3, 0x37, 0x82, 0x0d, 0x34, 0x5c, 0x02, 0x20, 0x1e, 0x6e, 0xb6, + 0x24, 0x55, 0xe4, 0xf2, 0x38, 0xc7, 0xf6, 0xbd, 0x78, 0x35, 0xdd, 0xdc, + 0x89, 0x88, 0xd9, 0x97, 0xb4, 0x47, 0x3a, 0xae, 0x02, 0x91, 0x7b, 0xf2, + 0xbf, 0x86, 0x65, 0xd5, 0x1f +}; + +const char *testbytes = "funky"; +CFIndex testbytes_size = 5; + +static int kTestTestCount = 8; +static void tests(void) +{ + CFErrorRef error = NULL; + CFDataRef testData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)testbytes, testbytes_size, kCFAllocatorNull); + + SecCertificateRef cert = SecCertificateCreateWithBytes(kCFAllocatorDefault, public_cert_der, sizeof(public_cert_der)); + CFArrayRef certInArray = CFArrayCreateForCFTypes(kCFAllocatorDefault, cert, NULL); + + SecKeyRef full_key = SecKeyCreateECPrivateKey(kCFAllocatorDefault, private_key_der, sizeof(private_key_der), kSecKeyEncodingPkcs1); + + SecTrustRef trust = NULL; + OSStatus status = SecTrustCreateWithCertificates(cert, SecPolicyCreateBasicX509(), &trust); + ok_status(status, "created"); + status = SecTrustSetAnchorCertificates(trust, certInArray); + ok_status(status, "Anchors"); + + SecTrustResultType result; + status = SecTrustEvaluate(trust, &result); + ok_status(status, "Trust evaluation"); + is(result, (SecTrustResultType)kSecTrustResultUnspecified, "Trust result"); + + CFDataRef encrypted = SecCopyEncryptedToServer(trust, testData, &error); + ok(encrypted != NULL, "Encrypt to server (%@)", error); + CFReleaseNull(error); + + ok(!CFEqualSafe(testData, encrypted), "encrypted different"); + + CFDataRef decrypted = SecCopyDecryptedForServer(full_key, encrypted, &error); + ok(decrypted != NULL, "Decrypt from server (%@)", error); + ok(CFEqualSafe(testData, decrypted), "round trip"); + + + CFReleaseNull(cert); + CFReleaseNull(certInArray); + CFReleaseNull(trust); + CFReleaseNull(testData); + CFReleaseNull(encrypted); + CFReleaseNull(decrypted); +} + +int so_01_serverencryption(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/Security/sec/Security/vmdh.c b/Security/sec/Security/vmdh.c new file mode 100644 index 00000000..78bed9b6 --- /dev/null +++ b/Security/sec/Security/vmdh.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2006-2007,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@ + */ + + +/*! + @header vmdh + The functions provided in vmdh.h implement the crypto exchange required + for a Diffie-Hellman voicemail exchange. +*/ + + +#include "vmdh.h" +#include +#include +#include +#include +#include + +vmdh_t vmdh_create(uint32_t g, const uint8_t *p, size_t p_len, + const uint8_t *recip, size_t recip_len) { + SecDHContext dh; + if (SecDHCreate(g, p, p_len, 0/*l*/, recip, recip_len, &dh)) + return NULL; + return (vmdh_t)dh; +} + +bool vmdh_generate_key(vmdh_t vmdh, uint8_t *pub_key, size_t *pub_key_len) { + return !SecDHGenerateKeypair((SecDHContext)vmdh, pub_key, pub_key_len); +} + +bool vmdh_encrypt_password(vmdh_t vmdh, + const uint8_t *pub_key, size_t pub_key_len, + const uint8_t *pw, size_t pw_len, uint8_t *encpw, size_t *encpw_len) { + uint8_t aes_key[kCCKeySizeAES128]; + size_t aes_key_len = kCCKeySizeAES128; + + if (SecDHComputeKey((SecDHContext)vmdh, pub_key, pub_key_len, + aes_key, &aes_key_len)) { + return false; + } + + /* Use the first 16 bytes in aes_key as an AES key. */ + if (CCCrypt(kCCEncrypt, kCCAlgorithmAES128, + kCCOptionPKCS7Padding, aes_key, kCCKeySizeAES128, NULL, + pw, pw_len, encpw, *encpw_len, encpw_len)) { + return false; + } + + /* Zero out key material. */ + bzero(aes_key, kCCKeySizeAES128); + + return true; +} + +void vmdh_destroy(vmdh_t vmdh) { + return SecDHDestroy((SecDHContext)vmdh); +} diff --git a/Security/sec/Security/vmdh.h b/Security/sec/Security/vmdh.h new file mode 100644 index 00000000..ebb49cee --- /dev/null +++ b/Security/sec/Security/vmdh.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2006-2007,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@ + */ + + +/*! + @header vmdh + The functions provided in vmdh.h implement the crypto exchange required + for a Diffie-Hellman voicemail exchange. +*/ + +#ifndef _SECURITY_VMDH_H_ +#define _SECURITY_VMDH_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct vmdh *vmdh_t; + +/* Return a newly allocated vmdh object given g, p and the recip of p recip. + The recip and recip_len parameters are constant for a given p. They are + optional although providing them improves performance. + The caller should call vmdh_destroy once the returned handle is no longer + needed. */ +vmdh_t vmdh_create(uint32_t g, const uint8_t *p, size_t p_len, + const uint8_t *recip, size_t recip_len); + +/* Generate a dh private/public keypair and return the public key in pub_key. + on input *pub_key_len is the number of bytes available in pub_key, on output + pub_key_len is the number of bytes actually in pub_key. Returns true on + success and false on failure. */ +bool vmdh_generate_key(vmdh_t vmdh, uint8_t *pub_key, size_t *pub_key_len); + +/* Given the length of a password return the size of the encrypted password. */ +#define vmdh_encpw_len(PWLEN) (((PWLEN) & ~0xf) + 16) + +/* Given a vmdh handle and the other parties public key pub_key (of + pub_key_len bytes long), encrypt the password given by pw of pw_len bytes + long and return it in encpw. On input *enc_pw contains the number of bytes + available in encpw, on output *encpw will contain the actual length of + encpw. */ +bool vmdh_encrypt_password(vmdh_t vmdh, + const uint8_t *pub_key, size_t pub_key_len, + const uint8_t *pw, size_t pw_len, uint8_t *encpw, size_t *encpw_len); + +/* Destroy a vmdh object created with vmdh_create(). */ +void vmdh_destroy(vmdh_t vmdh); + +#ifdef __cplusplus +} +#endif + +#endif /* _SECURITY_VMDH_H_ */ diff --git a/sec/SecurityTool/SecurityTool.c b/Security/sec/SecurityTool/SecurityTool.c similarity index 99% rename from sec/SecurityTool/SecurityTool.c rename to Security/sec/SecurityTool/SecurityTool.c index 3d5ebd58..9e0d0346 100644 --- a/sec/SecurityTool/SecurityTool.c +++ b/Security/sec/SecurityTool/SecurityTool.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2010,2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/sec/SecurityTool/SecurityTool.h b/Security/sec/SecurityTool/SecurityTool.h similarity index 96% rename from sec/SecurityTool/SecurityTool.h rename to Security/sec/SecurityTool/SecurityTool.h index 6f1bfc80..20b0b116 100644 --- a/sec/SecurityTool/SecurityTool.h +++ b/Security/sec/SecurityTool/SecurityTool.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004,2006-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2006-2007,2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * diff --git a/Security/sec/SecurityTool/builtin_commands.h b/Security/sec/SecurityTool/builtin_commands.h new file mode 100644 index 00000000..6c1610d3 --- /dev/null +++ b/Security/sec/SecurityTool/builtin_commands.h @@ -0,0 +1,37 @@ +/* + * 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("help", help, + "[command ...]", + "Show all commands. Or show usage for a command.") + +SECURITY_COMMAND("digest", command_digest, + "algo file(s)...\n" + "Where algo is one of:\n" + " sha1\n" + " sha256\n" + " sha512\n", + "Calculate a digest over the given file(s).") diff --git a/Security/sec/SecurityTool/digest_calc.c b/Security/sec/SecurityTool/digest_calc.c new file mode 100644 index 00000000..ed682a22 --- /dev/null +++ b/Security/sec/SecurityTool/digest_calc.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2011,2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include "builtin_commands.h" + +#include +#include +#include + +#include + +#include +#include + +#include + +extern int command_digest(int argc, char * const *argv) +{ + int result = 1, fd; + const struct ccdigest_info *di; + unsigned char *digest = NULL; + unsigned long i,j; + size_t nr = 0, totalBytes = 0; + char data [getpagesize()]; + + if (argc < 3) + return 2; /* Return 2 triggers usage message. */ + + if (strcasecmp("sha1", argv[1]) == 0) + { + //printf("Calculating sha1\n"); + di = ccsha1_di(); + } + else if (strcasecmp("sha256", argv[1]) == 0) + { + //printf("Calculating sha256\n"); + di = ccsha256_di(); + } + else if (strcasecmp("sha512", argv[1]) == 0) + { + //printf("Calculating sha256\n"); + di = ccsha512_di(); + + } + else + return 2; /* Return 2 triggers usage message. */ + + ccdigest_di_decl(di, ctx); + ccdigest_init(di, ctx); + + digest = malloc(di->output_size); + require_quiet(digest, exit); + + for (i = 2; i < (unsigned int)argc; ++i) + { + printf("%s(%s)= ", argv[1], argv[i]); + if ((fd = inspect_file_and_size(argv[i], NULL)) == -1) + { + printf("error reading file\n"); + continue; + } + totalBytes = 0; + while((nr = pread(fd, data, sizeof(data), totalBytes)) > 0){ + ccdigest_update(di, ctx, nr, data); + totalBytes += nr; + } + + ccdigest_final(di, ctx, digest); + + for (j = 0; j < di->output_size; j++) + printf("%02x", digest[j]); + printf("\n"); + } + result = 0; + +exit: + if (digest) + free(digest); + + return result; +} diff --git a/sec/SecurityTool/entitlements.plist b/Security/sec/SecurityTool/entitlements.plist similarity index 100% rename from sec/SecurityTool/entitlements.plist rename to Security/sec/SecurityTool/entitlements.plist diff --git a/Security/sec/SecurityTool/leaks.c b/Security/sec/SecurityTool/leaks.c new file mode 100644 index 00000000..e6ce54b8 --- /dev/null +++ b/Security/sec/SecurityTool/leaks.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2003-2004,2006-2007,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@ + * + * leaks.c + */ + +#include "leaks.h" + +#include +#include +#include +#include +#include +#include + +int +leaks(int argc, char *const *argv) +{ + int result = 1; + pid_t child; + pid_t parent = getpid(); + + child = fork(); + switch (child) + { + case -1: + /* Fork failed we're hosed. */ + fprintf(stderr, "fork: %s", strerror(errno)); + break; + case 0: + { + /* child. */ + char **argvec = (char **)malloc((argc + 2) * sizeof(char *)); + char pidstr[8]; + int ix; + + sprintf(pidstr, "%d", parent); + argvec[0] = "/usr/bin/leaks"; + for (ix = 1; ix < argc; ++ix) + argvec[ix] = argv[ix]; + argvec[ix] = pidstr; + argvec[ix + 1] = NULL; + + execv(argvec[0], argvec); + fprintf(stderr, "exec: %s", strerror(errno)); + _exit(1); + break; + } + default: + { + /* Parent. */ + int status = 0; + for (;;) + { + /* Wait for the child to exit. */ + pid_t waited_pid = waitpid(child, &status, 0); + if (waited_pid == -1) + { + int error = errno; + /* Keep going if we get interupted but bail out on any + other error. */ + if (error == EINTR) + continue; + + fprintf(stderr, "waitpid %d: %s", status, strerror(errno)); + break; + } + + if (WIFEXITED(status)) + { + if (WEXITSTATUS(status)) + { + /* Force usage message. */ + result = 2; + fprintf(stderr, "leaks exited: %d", result); + } + break; + } + else if (WIFSIGNALED(status)) + { + fprintf(stderr, "leaks terminated by signal: %d", WTERMSIG(status)); + break; + } + } + break; + } + } + + return result; +} diff --git a/Security/sec/SecurityTool/leaks.h b/Security/sec/SecurityTool/leaks.h new file mode 100644 index 00000000..f6c16d5d --- /dev/null +++ b/Security/sec/SecurityTool/leaks.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2003-2004,2006-2007,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@ + * + * leaks.h + */ + +#ifndef _LEAKS_H_ +#define _LEAKS_H_ + +#include + +__BEGIN_DECLS + +int leaks(int argc, char *const *argv); + +__END_DECLS + +#endif /* _LEAKS_H_ */ diff --git a/sec/SecurityTool/print_cert.c b/Security/sec/SecurityTool/print_cert.c similarity index 98% rename from sec/SecurityTool/print_cert.c rename to Security/sec/SecurityTool/print_cert.c index 7741a0a3..22b66ba4 100644 --- a/sec/SecurityTool/print_cert.c +++ b/Security/sec/SecurityTool/print_cert.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2008,2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2008,2011,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,6 @@ * * print_cert.c * - * Created by Michael Brouwer on 10/10/06. */ diff --git a/sec/SecurityTool/print_cert.h b/Security/sec/SecurityTool/print_cert.h similarity index 92% rename from sec/SecurityTool/print_cert.h rename to Security/sec/SecurityTool/print_cert.h index 2785c004..4ba89480 100644 --- a/sec/SecurityTool/print_cert.h +++ b/Security/sec/SecurityTool/print_cert.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2007 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2007,2013-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,6 @@ * * print_cert.h * - * Created by Michael Brouwer on 10/10/06. */ #ifndef _PRINT_CERT_H_ diff --git a/sec/SecurityTool/security.1 b/Security/sec/SecurityTool/security.1 similarity index 100% rename from sec/SecurityTool/security.1 rename to Security/sec/SecurityTool/security.1 diff --git a/Security/sec/SecurityTool/tool_errors.h b/Security/sec/SecurityTool/tool_errors.h new file mode 100644 index 00000000..db62c0a4 --- /dev/null +++ b/Security/sec/SecurityTool/tool_errors.h @@ -0,0 +1,76 @@ +/* + * 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@ + */ + + +// +// These functions should be deprectaed! +// Try to find a better way instead of using them. +// + +#ifndef _TOOL_ERRORS_H_ +#define _TOOL_ERRORS_H_ + +#include +#include +#include "SecurityTool/SecurityTool.h" + +static inline const char * +sec_errstr(int err) +{ + const char *errString; + static char buffer[12]; + + sprintf(buffer, "%d", err); + errString = buffer; +#if 0 + if (IS_SEC_ERROR(err)) + errString = SECErrorString(err); + else + errString = cssmErrorString(err); +#endif + return errString; +} + +static inline void +sec_error(const char *msg, ...) +{ + va_list args; + + fprintf(stderr, "%s: ", prog_name); + + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); + + fprintf(stderr, "\n"); +} + +static inline void +sec_perror(const char *msg, int err) +{ + sec_error("%s: %s", msg, sec_errstr(err)); +} + + + +#endif diff --git a/Security/sec/SharedWebCredential/com.apple.security.swcagent.plist b/Security/sec/SharedWebCredential/com.apple.security.swcagent.plist new file mode 100644 index 00000000..cfc5197c --- /dev/null +++ b/Security/sec/SharedWebCredential/com.apple.security.swcagent.plist @@ -0,0 +1,38 @@ + + + + + EnablePressuredExit + + EnableTransactions + + EnvironmentVariables + + DEBUGSCOPE + none + WAIT4DEBUGGER + NO + + Label + com.apple.security.swcagent + MachServices + + com.apple.security.swcagent + + + OnDemand + + ProgramArguments + + /System/Library/Frameworks/Security.framework/swcagent + + ServiceIPC + + Umask + 54 + UserName + mobile + POSIXSpawnType + Interactive + + diff --git a/Security/sec/SharedWebCredential/swcagent.m b/Security/sec/SharedWebCredential/swcagent.m new file mode 100644 index 00000000..7f43fe86 --- /dev/null +++ b/Security/sec/SharedWebCredential/swcagent.m @@ -0,0 +1,802 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include /* for SecErrorGetOSStatus */ +#include +#include + +#include + +#if TARGET_OS_IPHONE +#include +#endif +#if !TARGET_OS_IPHONE +#include +#endif + +#if TARGET_OS_IPHONE +#include +#endif + +#if TARGET_OS_IPHONE +#include +#endif + +#include +#include +#include +#include +#include + +#include +#include "swcagent_client.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +// TODO: Make this include work on both platforms. +#if TARGET_OS_EMBEDDED +#include +#else +/* defines from */ +#define kSecEntitlementAssociatedDomains CFSTR("com.apple.developer.associated-domains") +#define kSecEntitlementPrivateAssociatedDomains CFSTR("com.apple.private.associated-domains") +#endif + +#include + +#include +#include +#include +#include + + +// Local function declarations +CFStringRef SWCAGetOperationDescription(enum SWCAXPCOperation op); +bool SWCAIsAutofillEnabled(void); + +bool swca_confirm_add(CFDictionaryRef attributes, CFStringRef clientTaskName, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error); +bool swca_confirm_copy(CFDictionaryRef attributes, CFStringRef clientTaskName, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error); +bool swca_confirm_update(CFDictionaryRef attributes, CFStringRef clientTaskName, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error); +bool swca_confirm_delete(CFDictionaryRef attributes, CFStringRef clientTaskName, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error); +bool swca_select_item(CFArrayRef items, CFStringRef clientTaskName, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error); + +CFOptionFlags swca_handle_request(enum SWCAXPCOperation operation, CFStringRef client, CFArrayRef domains); +bool swca_process_response(CFOptionFlags response, CFTypeRef *result); + +static CFArrayRef gActiveArray = NULL; +static CFDictionaryRef gActiveItem = NULL; + +#if TARGET_IPHONE_SIMULATOR +#define CHECK_ENTITLEMENTS 0 +#else +#define CHECK_ENTITLEMENTS 0 /* %%% TODO: re-enable when entitlements are available */ +#endif + +#if CHECK_ENTITLEMENTS +static bool SecTaskGetBooleanValueForEntitlement(SecTaskRef task, CFStringRef entitlement) +{ + CFStringRef canModify = (CFStringRef)SecTaskCopyValueForEntitlement(task, entitlement, NULL); + if (!canModify) + return false; + CFTypeID canModifyType = CFGetTypeID(canModify); + bool ok = (CFBooleanGetTypeID() == canModifyType) && CFBooleanGetValue((CFBooleanRef)canModify); + CFRelease(canModify); + return ok; +} + +static CFArrayRef SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task, CFStringRef entitlement) +{ + CFArrayRef value = (CFArrayRef)SecTaskCopyValueForEntitlement(task, + entitlement, NULL); + if (value) { + if (CFGetTypeID(value) == CFArrayGetTypeID()) { + CFIndex ix, count = CFArrayGetCount(value); + for (ix = 0; ix < count; ++ix) { + CFStringRef string = (CFStringRef)CFArrayGetValueAtIndex(value, ix); + if (CFGetTypeID(string) != CFStringGetTypeID()) { + CFRelease(value); + value = NULL; + break; + } + } + } else { + CFRelease(value); + value = NULL; + } + } + + return value; +} + +#endif /* CHECK_ENTITLEMENTS */ + + +/* Identify a client */ +enum { + CLIENT_TYPE_BUNDLE_IDENTIFIER, + CLIENT_TYPE_EXECUTABLE_PATH, +}; + +@interface Client : NSObject +@property int client_type; +@property(retain) NSString *client; +@property(retain) NSString *client_name; +@property(retain) NSString *path; +@property(retain) NSBundle *bundle; +@end +@implementation Client +@end +static Client *identify_client(pid_t pid) +{ + Client *client = [[Client alloc] init]; + if (!client) + return nil; + + char path_buf[PROC_PIDPATHINFO_SIZE] = ""; + NSURL *path_url; + +#if TARGET_OS_IPHONE + if (proc_pidpath(pid, path_buf, sizeof(path_buf)) <= 0) { + asl_log(NULL, NULL, ASL_LEVEL_NOTICE, "Refusing client without path (pid %d)", pid); + [client release]; + return nil; + } +#else + size_t path_len = sizeof(path_buf); + if (responsibility_get_responsible_for_pid(pid, NULL, NULL, &path_len, path_buf) != 0) { + asl_log(NULL, NULL, ASL_LEVEL_NOTICE, "Refusing client without path (pid %d)", pid); + [client release]; + return nil; + } +#endif + path_buf[sizeof(path_buf) - 1] = '\0'; + + if (!(client.path = [NSString stringWithUTF8String:path_buf]) || + !(path_url = [NSURL fileURLWithPath:client.path])) { + asl_log(NULL, NULL, ASL_LEVEL_NOTICE, "Refusing client without path (pid %d)", pid); + [client release]; + return nil; + } + + NSURL *bundle_url; + if ((bundle_url = (NSURL *)_CFBundleCopyBundleURLForExecutableURL((__bridge CFURLRef)path_url)) && + (client.bundle = [NSBundle bundleWithURL:bundle_url]) && + (client.client = [client.bundle bundleIdentifier])) { + client.client_type = CLIENT_TYPE_BUNDLE_IDENTIFIER; + CFStringRef client_name_cf = NULL; +#if TARGET_OS_IPHONE + client_name_cf = SBSCopyLocalizedApplicationNameForDisplayIdentifier((__bridge CFStringRef)client.client); + client.client_name = (NSString *)client_name_cf; +#else + if (!LSCopyDisplayNameForURL((__bridge CFURLRef)bundle_url, &client_name_cf)) + client.client_name = (__bridge_transfer NSString *)client_name_cf; +#endif + if (client_name_cf) + CFRelease(client_name_cf); + } else { +#if TARGET_OS_IPHONE + asl_log(NULL, NULL, ASL_LEVEL_NOTICE, "Refusing client without bundle identifier (%s)", path_buf); + [client release]; + [bundle_url release]; + return nil; +#else + client.client_type = CLIENT_TYPE_EXECUTABLE_PATH; + CFBooleanRef is_app = NULL; + CFStringRef client_name_cf; + if (bundle_url && + CFURLCopyResourcePropertyForKey((__bridge CFURLRef)bundle_url, _kCFURLIsApplicationKey, &is_app, NULL) && + is_app == kCFBooleanTrue) { + if ((client.client = [bundle_url path]) && + !LSCopyDisplayNameForURL((__bridge CFURLRef)bundle_url, &client_name_cf)) + client.client_name = (__bridge_transfer NSString *)client_name_cf; + } else { + client.client = client.path; + if (!LSCopyDisplayNameForURL((__bridge CFURLRef)path_url, &client_name_cf)) + client.client_name = (__bridge_transfer NSString *)client_name_cf; + } + if (is_app) + CFRelease(is_app); +#endif + } + + [bundle_url release]; + return client; +} + +struct __SecTask { + CFRuntimeBase base; + + pid_t pid_self; + audit_token_t token; + + /* Track whether we've loaded entitlements independently since after the + * load, entitlements may legitimately be NULL */ + Boolean entitlementsLoaded; + CFDictionaryRef entitlements; +}; + +static CFStringRef SecTaskCopyLocalizedDescription(SecTaskRef task) +{ + // SecTaskCopyDebugDescription is not sufficient to get the localized client name + pid_t pid; + if (task->pid_self==-1) { + audit_token_to_au32(task->token, NULL, NULL, NULL, NULL, NULL, &pid, NULL, NULL); + } else { + pid = task->pid_self; + } + Client *client = identify_client(pid); + CFStringRef clientTaskName = (__bridge CFStringRef)client.client_name; + CFRetainSafe(clientTaskName); + [client release]; + + return clientTaskName; +} + +static CFArrayRef SecTaskCopyAccessGroups(SecTaskRef task) { +#if CHECK_ENTITLEMENTS + CFArrayRef groups = SecTaskCopyArrayOfStringsForEntitlement(task, kSecEntitlementAssociatedDomains); +#else + CFArrayRef groups = SecAccessGroupsGetCurrent(); + CFRetainSafe(groups); +#endif + return groups; +} + +CFStringRef SWCAGetOperationDescription(enum SWCAXPCOperation op) +{ + switch (op) { + case swca_add_request_id: + return CFSTR("swc add"); + case swca_update_request_id: + return CFSTR("swc update"); + case swca_delete_request_id: + return CFSTR("swc delete"); + case swca_copy_request_id: + return CFSTR("swc copy"); + case swca_select_request_id: + return CFSTR("swc select"); + case swca_copy_pairs_request_id: + return CFSTR("swc copy pairs"); + case swca_set_selection_request_id: + return CFSTR("swc set selection"); + case swca_enabled_request_id: + return CFSTR("swc enabled"); + default: + return CFSTR("Unknown xpc operation"); + } +} + +bool SWCAIsAutofillEnabled(void) +{ +#if TARGET_IPHONE_SIMULATOR + // Assume the setting's on in the simulator: WBUAutoFillGetEnabledDataClasses call failing in the Simulator + return true; +#else + WBSAutoFillDataClasses autofill = WBUAutoFillGetEnabledDataClasses(); + return ((autofill & WBSAutoFillDataClassUsernamesAndPasswords) != 0); +#endif +} + +CFOptionFlags swca_handle_request(enum SWCAXPCOperation operation, CFStringRef client, CFArrayRef domains) +{ + CFUserNotificationRef notification = NULL; + NSMutableDictionary *notification_dictionary = NULL; + NSString *security_path = @"/System/Library/Frameworks/Security.framework"; + NSString *swc_table = @"SharedWebCredentials"; + NSBundle *security_bundle; + NSString *request_key; + NSString *request_format; + NSString *default_button_key; + NSString *alternate_button_key; + NSString *other_button_key; + NSString *info_message_key; + NSString *domain; + char *op = NULL; + CFOptionFlags response = 0 | kCFUserNotificationCancelResponse; + BOOL alert_sem_held = NO; + +check_database: + /* If we have previously allowed this operation/domain for this client, + * check and don't prompt again. + */ + ; /* %%% TBD */ + + /* Only display one alert at a time. */ + static dispatch_semaphore_t alert_sem; + static dispatch_once_t alert_once; + dispatch_once(&alert_once, ^{ + if (!(alert_sem = dispatch_semaphore_create(1))) + abort(); + }); + if (!alert_sem_held) { + alert_sem_held = YES; + if (dispatch_semaphore_wait(alert_sem, DISPATCH_TIME_NOW)) { + /* Wait for the active alert, then recheck the database in case both alerts are for the same client. */ + //asl_log(NULL, NULL, ASL_LEVEL_NOTICE, "Delaying prompt for pid %d", pid); + dispatch_semaphore_wait(alert_sem, DISPATCH_TIME_FOREVER); + goto check_database; + } + } + +#if TARGET_IPHONE_SIMULATOR + security_path = [NSString stringWithFormat:@"%s%@", getenv("IPHONE_SIMULATOR_ROOT"), security_path]; +#endif + security_bundle = [NSBundle bundleWithPath:security_path]; + notification_dictionary = [NSMutableDictionary dictionary]; + domain = nil; + if (1 == [(__bridge NSArray *)domains count]) { + domain = (NSString *)[(__bridge NSArray *)domains objectAtIndex:0]; + } + switch (operation) { + case swca_add_request_id: + op = "ADD"; + break; + case swca_update_request_id: + op = "UPDATE"; + break; + case swca_delete_request_id: + op = "DELETE"; + break; + case swca_copy_request_id: + op = (domain) ? "COPY" : "COPYALL"; + break; + default: + op = "USE"; + break; + } + if (!op) { + goto out; + } + request_key = [NSString stringWithFormat:@"SWC_REQUEST_%s", op]; + request_format = NSLocalizedStringFromTableInBundle(request_key, swc_table, security_bundle, nil); + alternate_button_key = (op) ? [NSString stringWithFormat:@"SWC_ALLOW_%s", op] : nil; + default_button_key = @"SWC_NEVER"; + other_button_key = @"SWC_DENY"; + info_message_key = @"SWC_INFO_MESSAGE"; + + notification_dictionary[(__bridge NSString *)kCFUserNotificationAlertHeaderKey] = [NSString stringWithFormat:request_format, client, domain]; + notification_dictionary[(__bridge NSString *)kCFUserNotificationAlertMessageKey] = NSLocalizedStringFromTableInBundle(info_message_key, swc_table, security_bundle, nil); + notification_dictionary[(__bridge NSString *)kCFUserNotificationDefaultButtonTitleKey] = NSLocalizedStringFromTableInBundle(default_button_key, swc_table, security_bundle, nil); + notification_dictionary[(__bridge NSString *)kCFUserNotificationAlternateButtonTitleKey] = NSLocalizedStringFromTableInBundle(alternate_button_key, swc_table, security_bundle, nil); + + if (other_button_key) { + // notification_dictionary[(__bridge NSString *)kCFUserNotificationOtherButtonTitleKey] = NSLocalizedStringFromTableInBundle(other_button_key, swc_table, security_bundle, nil); + } + notification_dictionary[(__bridge NSString *)kCFUserNotificationLocalizationURLKey] = [security_bundle bundleURL]; + + SInt32 error; + if (!(notification = CFUserNotificationCreate(NULL, 0, kCFUserNotificationStopAlertLevel | kCFUserNotificationNoDefaultButtonFlag, &error, (__bridge CFDictionaryRef)notification_dictionary)) || + error) + goto out; + if (CFUserNotificationReceiveResponse(notification, 0, &response)) + goto out; + +out: + if (alert_sem_held) + dispatch_semaphore_signal(alert_sem); + if (notification) + CFRelease(notification); + return response; +} + +bool swca_process_response(CFOptionFlags response, CFTypeRef *result) +{ + int32_t value = (int32_t)(response & 0x3); + CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value); + *result = number; + return (NULL != number); +} + +bool swca_confirm_add(CFDictionaryRef attributes, CFStringRef clientTaskName, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error) +{ + CFStringRef domain = (CFStringRef) CFDictionaryGetValue(attributes, kSecAttrServer); + CFArrayRef domains = CFArrayCreate(kCFAllocatorDefault, (const void **)&domain, 1, &kCFTypeArrayCallBacks); + CFOptionFlags response = swca_handle_request(swca_add_request_id, clientTaskName, domains); + return swca_process_response(response, result); +} + +bool swca_confirm_copy(CFDictionaryRef attributes, CFStringRef clientTaskName, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error) +{ + CFStringRef domain = (CFStringRef) CFDictionaryGetValue(attributes, kSecAttrServer); + CFArrayRef domains = CFArrayCreate(kCFAllocatorDefault, (const void **)&domain, 1, &kCFTypeArrayCallBacks); + CFOptionFlags response = swca_handle_request(swca_copy_request_id, clientTaskName, domains); + return swca_process_response(response, result); +} + +bool swca_confirm_update(CFDictionaryRef attributes, CFStringRef clientTaskName, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error) +{ + CFStringRef domain = (CFStringRef) CFDictionaryGetValue(attributes, kSecAttrServer); + CFArrayRef domains = CFArrayCreate(kCFAllocatorDefault, (const void **)&domain, 1, &kCFTypeArrayCallBacks); + CFOptionFlags response = swca_handle_request(swca_update_request_id, clientTaskName, domains); + return swca_process_response(response, result); +} + +bool swca_confirm_delete(CFDictionaryRef attributes, CFStringRef clientTaskName, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error) +{ + CFStringRef domain = (CFStringRef) CFDictionaryGetValue(attributes, kSecAttrServer); + CFArrayRef domains = CFArrayCreate(kCFAllocatorDefault, (const void **)&domain, 1, &kCFTypeArrayCallBacks); + CFOptionFlags response = swca_handle_request(swca_delete_request_id, clientTaskName, domains); + return swca_process_response(response, result); +} + +bool swca_select_item(CFArrayRef items, CFStringRef clientTaskName, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error) +{ + CFUserNotificationRef notification = NULL; + NSMutableDictionary *notification_dictionary = NULL; + NSString *security_path = @"/System/Library/Frameworks/Security.framework"; + NSString *swc_table = @"SharedWebCredentials"; + NSBundle *security_bundle; + NSString *request_title_format; + NSString *info_message_key; + NSString *default_button_key; + NSString *alternate_button_key; + CFOptionFlags response = 0 | kCFUserNotificationCancelResponse; + CFIndex item_count = (items) ? CFArrayGetCount(items) : (CFIndex) 0; + BOOL alert_sem_held = NO; + + if (item_count < 1) { + return false; + } + +entry: + ; + /* Only display one alert at a time. */ + static dispatch_semaphore_t select_alert_sem; + static dispatch_once_t select_alert_once; + dispatch_once(&select_alert_once, ^{ + if (!(select_alert_sem = dispatch_semaphore_create(1))) + abort(); + }); + if (!alert_sem_held) { + alert_sem_held = YES; + if (dispatch_semaphore_wait(select_alert_sem, DISPATCH_TIME_NOW)) { + /* Wait for the active alert */ + dispatch_semaphore_wait(select_alert_sem, DISPATCH_TIME_FOREVER); + goto entry; + } + } + + CFRetainSafe(items); + CFReleaseSafe(gActiveArray); + gActiveArray = items; + CFReleaseSafe(gActiveItem); + gActiveItem = NULL; // selection will be set by remote view controller + //gActiveItem = CFArrayGetValueAtIndex(items, 0); + //CFRetainSafe(gActiveItem); + +#if TARGET_IPHONE_SIMULATOR + security_path = [NSString stringWithFormat:@"%s%@", getenv("IPHONE_SIMULATOR_ROOT"), security_path]; +#endif + security_bundle = [NSBundle bundleWithPath:security_path]; + notification_dictionary = [NSMutableDictionary dictionary]; + + request_title_format = NSLocalizedStringFromTableInBundle(@"SWC_ALERT_TITLE", swc_table, security_bundle, nil); + default_button_key = @"SWC_ALLOW_USE"; + alternate_button_key = @"SWC_CANCEL"; + info_message_key = @"SWC_INFO_MESSAGE"; + + notification_dictionary[(__bridge NSString *)kCFUserNotificationAlertHeaderKey] = [NSString stringWithFormat: request_title_format, clientTaskName]; + notification_dictionary[(__bridge NSString *)kCFUserNotificationAlertMessageKey] = NSLocalizedStringFromTableInBundle(info_message_key, swc_table, security_bundle, nil); + notification_dictionary[(__bridge NSString *)kCFUserNotificationDefaultButtonTitleKey] = NSLocalizedStringFromTableInBundle(default_button_key, swc_table, security_bundle, nil); + notification_dictionary[(__bridge NSString *)kCFUserNotificationAlternateButtonTitleKey] = NSLocalizedStringFromTableInBundle(alternate_button_key, swc_table, security_bundle, nil); + + notification_dictionary[(__bridge NSString *)kCFUserNotificationLocalizationURLKey] = [security_bundle bundleURL]; + notification_dictionary[(__bridge NSString *)kCFUserNotificationAlertTopMostKey] = [NSNumber numberWithBool:YES]; + + // additional keys for remote view controller + notification_dictionary[(__bridge NSString *)SBUserNotificationDismissOnLock] = [NSNumber numberWithBool:YES]; + notification_dictionary[(__bridge NSString *)SBUserNotificationDontDismissOnUnlock] = [NSNumber numberWithBool:YES]; + notification_dictionary[(__bridge NSString *)SBUserNotificationRemoteServiceBundleIdentifierKey] = @"com.apple.SharedWebCredentialViewService"; + notification_dictionary[(__bridge NSString *)SBUserNotificationRemoteViewControllerClassNameKey] = @"SWCViewController"; + + SInt32 err; + if (!(notification = CFUserNotificationCreate(NULL, 0, 0, &err, (__bridge CFDictionaryRef)notification_dictionary)) || + err) + goto out; + if (CFUserNotificationReceiveResponse(notification, 0, &response)) + goto out; + + //NSLog(@"Selection: %@, Response: %lu", gActiveItem, (unsigned long)response); + if (result && response == kCFUserNotificationDefaultResponse) { + CFRetainSafe(gActiveItem); + *result = gActiveItem; + } + +out: + if (alert_sem_held) { + dispatch_semaphore_signal(select_alert_sem); + } + CFReleaseSafe(notification); + CFReleaseNull(gActiveArray); + CFReleaseNull(gActiveItem); + + return (result && *result); +} + + +static void swca_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; + CFStringRef clientTaskName = NULL; + CFArrayRef accessGroups = NULL; + + secdebug("swcagent_xpc", "entering"); + if (type == XPC_TYPE_DICTIONARY) { + replyMessage = xpc_dictionary_create_reply(event); + + uint64_t operation = xpc_dictionary_get_uint64(event, kSecXPCKeyOperation); + secdebug("swcagent_xpc", "operation: %@ (%" PRIu64 ")", SWCAGetOperationDescription((enum SWCAXPCOperation)operation), operation); + + bool hasEntitlement; + audit_token_t auditToken = {}; +#if !CHECK_ENTITLEMENTS + hasEntitlement = true; +#else + // check our caller's private entitlement to invoke swcagent + // TODO: on iOS it's enough to have the entitlement; will need to check code requirement on OS X + xpc_connection_get_audit_token(connection, &auditToken); + clientTask = SecTaskCreateWithAuditToken(kCFAllocatorDefault, auditToken); + hasEntitlement = (clientTask && SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementPrivateAssociatedDomains)); + if (!hasEntitlement) { + CFErrorRef entitlementError = NULL; + SecError(errSecMissingEntitlement, &entitlementError, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SWCAXPCOperation)operation), clientTask, kSecEntitlementPrivateAssociatedDomains); + CFReleaseSafe(entitlementError); + } + CFReleaseNull(clientTask); +#endif + + if (hasEntitlement) { + // fetch audit token for process which called securityd + size_t length = 0; + const uint8_t *bytes = xpc_dictionary_get_data(event, kSecXPCKeyClientToken, &length); + if (length == sizeof(audit_token_t)) { + memcpy(&auditToken, bytes, sizeof(audit_token_t)); + } else { + secerror("swcagent_xpc - wrong length for client id"); + hasEntitlement = false; + } + } + if (hasEntitlement) { + // identify original client + clientTask = SecTaskCreateWithAuditToken(kCFAllocatorDefault, auditToken); + accessGroups = SecTaskCopyAccessGroups(clientTask); + clientTaskName = SecTaskCopyLocalizedDescription(clientTask); +#if CHECK_ENTITLEMENTS + // check for presence of original client's shared credential entitlement + hasEntitlement = (clientTask && SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementAssociatedDomains)); + if (!hasEntitlement) { + CFErrorRef entitlementError = NULL; + SecError(errSecMissingEntitlement, &entitlementError, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SWCAXPCOperation)operation), clientTask, kSecEntitlementAssociatedDomains); + CFReleaseSafe(entitlementError); + } +#endif + CFReleaseNull(clientTask); + } + + if (hasEntitlement) { + switch (operation) + { + case swca_add_request_id: + { + CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); + //secdebug("ipc", "swcagent: got swca_add_request_id, query: %@", query); + if (query) { + CFTypeRef result = NULL; + // confirm that we can add this item + if (swca_confirm_add(query, clientTaskName, accessGroups, &result, &error) && result) { + SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); + CFRelease(result); + } + CFRelease(query); + } + break; + } + case swca_copy_request_id: + { + CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); + //secdebug("ipc", "swcagent: got swca_copy_request_id, query: %@", query); + if (query) { + CFTypeRef result = NULL; + // confirm that we can copy this item + if (swca_confirm_copy(query, clientTaskName, accessGroups, &result, &error) && result) { + SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); + CFRelease(result); + } + CFRelease(query); + } + break; + } + case swca_update_request_id: + { + CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); + //secdebug("ipc", "swcagent: got swca_update_request_id, query: %@", query); + if (query) { + CFTypeRef result = NULL; + // confirm that we can copy this item + if (swca_confirm_update(query, clientTaskName, accessGroups, &result, &error) && result) { + SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); + CFRelease(result); + } + CFRelease(query); + } + break; + } + case swca_delete_request_id: + { + CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); + //secdebug("ipc", "swcagent: got swca_delete_request_id, query: %@", query); + if (query) { + CFTypeRef result = NULL; + // confirm that we can copy this item + if (swca_confirm_delete(query, clientTaskName, accessGroups, &result, &error) && result) { + SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); + CFRelease(result); + } + CFRelease(query); + } + break; + } + case swca_select_request_id: + { + CFArrayRef items = SecXPCDictionaryCopyArray(event, kSecXPCKeyQuery, &error); + secdebug("ipc", "swcagent: got swca_select_request_id, items: %@", items); + if (items) { + CFTypeRef result = NULL; + // select a dictionary from an input array of dictionaries + if (swca_select_item(items, clientTaskName, accessGroups, &result, &error) && result) { + SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); + CFRelease(result); + } + CFRelease(items); + } + break; + } + case swca_copy_pairs_request_id: + { + secdebug("ipc", "swcagent: got swca_copy_pairs_request_id"); + SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, gActiveArray, &error); + break; + } + case swca_set_selection_request_id: + { + CFDictionaryRef dict = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); + secdebug("ipc", "swcagent: got swca_set_selection_request_id, dict: %@", dict); + if (dict) { + int32_t value = (int32_t) 1; + CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value); + SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, number, &error); + CFReleaseSafe(number); + } + CFReleaseSafe(gActiveItem); + gActiveItem = dict; + break; + } + case swca_enabled_request_id: + { + // return Safari's password autofill enabled status + CFTypeRef result = (SWCAIsAutofillEnabled()) ? kCFBooleanTrue : kCFBooleanFalse; + SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); + } + default: + secdebug("ipc", "swcagent: got unsupported request id (%ld)", (long)operation); + break; + } + } + if (error) + { + if(SecErrorGetOSStatus(error) == errSecItemNotFound) + secdebug("ipc", "%@ %@ %@", clientTask, SWCAGetOperationDescription((enum SWCAXPCOperation)operation), error); + else + secerror("%@ %@ %@", clientTask, SWCAGetOperationDescription((enum SWCAXPCOperation)operation), error); + + xpcError = SecCreateXPCObjectWithCFError(error); + xpc_dictionary_set_value(replyMessage, kSecXPCKeyError, xpcError); + } else if (replyMessage) { + secdebug("ipc", "%@ %@ responding %@", clientTask, SWCAGetOperationDescription((enum SWCAXPCOperation)operation), replyMessage); + } + } else { + SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, &error, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event); + secerror("%@: returning error: %@", clientTask, error); + xpcError = SecCreateXPCObjectWithCFError(error); + replyMessage = xpc_create_reply_with_format(event, "{%string: %value}", kSecXPCKeyError, xpcError); + } + + if (replyMessage) { + xpc_connection_send_message(connection, replyMessage); + xpc_release(replyMessage); + } + if (xpcError) { + xpc_release(xpcError); + } + CFReleaseSafe(error); + CFReleaseSafe(accessGroups); + CFReleaseSafe(clientTaskName); +} + +static void swca_xpc_init() +{ + secdebug("swcagent_xpc", "start"); + + xpc_connection_t listener = xpc_connection_create_mach_service(kSWCAXPCServiceName, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER); + if (!listener) { + seccritical("swcagent failed to register xpc listener, exiting"); + abort(); + } + + xpc_connection_set_event_handler(listener, ^(xpc_object_t connection) { + if (xpc_get_type(connection) == XPC_TYPE_CONNECTION) { + xpc_connection_set_event_handler(connection, ^(xpc_object_t event) { + if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) { + xpc_retain(connection); + xpc_retain(event); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + swca_xpc_dictionary_handler(connection, event); + xpc_release(event); + xpc_release(connection); + }); + } + }); + xpc_connection_resume(connection); + } + }); + xpc_connection_resume(listener); +} + +int main(int argc, char *argv[]) +{ + @autoreleasepool { + char *wait4debugger = getenv("WAIT4DEBUGGER"); + if (wait4debugger && !strcasecmp("YES", wait4debugger)) { + seccritical("SIGSTOPing self, awaiting debugger"); + kill(getpid(), SIGSTOP); + asl_log(NULL, NULL, ASL_LEVEL_CRIT, + "Again, for good luck (or bad debuggers)"); + kill(getpid(), SIGSTOP); + } + swca_xpc_init(); + dispatch_main(); + } + return 0; +} + +/* vi:set ts=4 sw=4 et: */ diff --git a/Security/sec/SharedWebCredential/swcagent_client.c b/Security/sec/SharedWebCredential/swcagent_client.c new file mode 100644 index 00000000..8b7b4633 --- /dev/null +++ b/Security/sec/SharedWebCredential/swcagent_client.c @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include // TODO Fixme this gets us SecError(). +#include "swcagent_client.h" + +#include + + +CFStringRef sSWCAXPCErrorDomain = CFSTR("com.apple.security.swcagent"); +CFStringRef sSWCASecAttrServer = CFSTR("srvr"); + +// +// MARK: XPC IPC. +// + +static xpc_connection_t swca_create_connection(const char *name) { + if (!name) + name = kSWCAXPCServiceName; + xpc_connection_t connection; + connection = xpc_connection_create_mach_service(name, NULL, 0); + xpc_connection_set_event_handler(connection, ^(xpc_object_t event) { + const char *description = xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION); + secnotice("xpc", "got event: %s", description); + }); + xpc_connection_resume(connection); + return connection; +} + +static xpc_connection_t sSWCAConnection; + +static xpc_connection_t swca_connection(void) { + static dispatch_once_t once; + dispatch_once(&once, ^{ + sSWCAConnection = swca_create_connection(NULL); + }); + return sSWCAConnection; +} + +xpc_object_t +swca_message_with_reply_sync(xpc_object_t message, CFErrorRef *error) +{ + xpc_object_t reply = NULL; + xpc_connection_t connection = swca_connection(); + + const int max_tries = 4; // Per N61/12A342: Audio Playback... for why this needs to be at least 3, so we made it 4. + + unsigned int tries_left = max_tries; + do { + if (reply) xpc_release(reply); + reply = xpc_connection_send_message_with_reply_sync(connection, message); + } while (reply == XPC_ERROR_CONNECTION_INTERRUPTED && --tries_left > 0); + + if (xpc_get_type(reply) == XPC_TYPE_ERROR) { + CFIndex code = 0; + if (reply == XPC_ERROR_CONNECTION_INTERRUPTED || reply == XPC_ERROR_CONNECTION_INVALID) + code = kSecXPCErrorConnectionFailed; + else if (reply == XPC_ERROR_TERMINATION_IMMINENT) + code = kSecXPCErrorUnknown; + else + code = kSecXPCErrorUnknown; + + char *conn_desc = xpc_copy_description(connection); + const char *description = xpc_dictionary_get_string(reply, XPC_ERROR_KEY_DESCRIPTION); + SecCFCreateErrorWithFormat(code, sSWCAXPCErrorDomain, NULL, error, NULL, CFSTR("%s: %s"), conn_desc, description); + free(conn_desc); + xpc_release(reply); + reply = NULL; + } + + return reply; +} + +xpc_object_t swca_create_message(enum SWCAXPCOperation op, CFErrorRef* error) +{ + xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); + if (message) { + xpc_dictionary_set_uint64(message, kSecXPCKeyOperation, op); + } else { + SecCFCreateError(kSecXPCErrorConnectionFailed, sSWCAXPCErrorDomain, + CFSTR("xpc_dictionary_create returned NULL"), NULL, error); + } + return message; +} + +// Return true if there is no error in message, return false and set *error if there is. +bool swca_message_no_error(xpc_object_t message, CFErrorRef *error) { + xpc_object_t xpc_error = xpc_dictionary_get_value(message, kSecXPCKeyError); + if (xpc_error == NULL) + return true; + + if (error) { + *error = SecCreateCFErrorWithXPCObject(xpc_error); + } + return false; +} + +// Return int value of message reply (or -1 if error) +long swca_message_response(xpc_object_t replyMessage, CFErrorRef *error) { + int32_t value = -1; + CFTypeRef result = NULL; + if (!swca_message_no_error(replyMessage, error) || + !SecXPCDictionaryCopyPListOptional(replyMessage, kSecXPCKeyResult, &result, error) || + !result) { + return value; + } + CFTypeID typeID = CFGetTypeID(result); + if (typeID == CFBooleanGetTypeID()) { + value = (CFEqual((CFBooleanRef)result, kCFBooleanTrue)) ? 1 : 0; + } + else if (typeID == CFNumberGetTypeID()) { + if (!CFNumberGetValue((CFNumberRef)result, kCFNumberSInt32Type, &value)) { + value = -1; + } + } + CFReleaseSafe(result); + return value; +} + +bool swca_autofill_enabled(const audit_token_t *auditToken) +{ + bool result = false; + CFErrorRef error = NULL; + xpc_object_t message = swca_create_message(swca_enabled_request_id, &error); + if (message) { + xpc_dictionary_set_data(message, kSecXPCKeyClientToken, auditToken, sizeof(audit_token_t)); + xpc_object_t reply = swca_message_with_reply_sync(message, &error); + if (reply) { + long value = swca_message_response(reply, &error); + result = (value > 0); + xpc_release(reply); + } + xpc_release(message); + } + CFReleaseSafe(error); + return result; +} + +bool swca_confirm_operation(enum SWCAXPCOperation op, + const audit_token_t *auditToken, + CFTypeRef query, + CFErrorRef *error, + void (^add_negative_entry)(CFStringRef fqdn)) +{ + bool result = false; + xpc_object_t message = swca_create_message(op, error); + if (message) { + xpc_dictionary_set_data(message, kSecXPCKeyClientToken, auditToken, sizeof(audit_token_t)); + if (SecXPCDictionarySetPList(message, kSecXPCKeyQuery, query, error)) { + xpc_object_t reply = swca_message_with_reply_sync(message, error); + if (reply) { + long value = swca_message_response(reply, error); + // + // possible values (see CFUserNotification.h): + // unable to get message response = -1 + // kCFUserNotificationDefaultResponse = 0 "Don't Allow" (i.e. permanently) + // kCFUserNotificationAlternateResponse = 1 "OK" + // kCFUserNotificationOtherResponse = 2 (no longer used) + // + result = (value == 1); + if (value == 0 && add_negative_entry) { + CFStringRef fqdn = CFDictionaryGetValue(query, sSWCASecAttrServer); + add_negative_entry(fqdn); + } + xpc_release(reply); + } + } + xpc_release(message); + } + return result; +} + +// Return retained dictionary value of message reply (or NULL if error) +CFTypeRef swca_message_copy_response(xpc_object_t replyMessage, CFErrorRef *error) { + CFTypeRef result = NULL; + if (!swca_message_no_error(replyMessage, error) || + !SecXPCDictionaryCopyPListOptional(replyMessage, kSecXPCKeyResult, &result, error)) { + CFReleaseNull(result); + } + return result; +} + +CFDictionaryRef swca_copy_selected_dictionary(enum SWCAXPCOperation op, + const audit_token_t *auditToken, + CFTypeRef items, // array of dictionaries + CFErrorRef *error) +{ + CFDictionaryRef result = NULL; + xpc_object_t message = swca_create_message(op, error); + if (message) { + xpc_dictionary_set_data(message, kSecXPCKeyClientToken, auditToken, sizeof(audit_token_t)); + if (SecXPCDictionarySetPList(message, kSecXPCKeyQuery, items, error)) { + xpc_object_t reply = swca_message_with_reply_sync(message, error); + if (reply) { + result = (CFDictionaryRef) swca_message_copy_response(reply, error); + if (!(result && CFGetTypeID(result) == CFDictionaryGetTypeID())) { + CFReleaseNull(result); + } + xpc_release(reply); + } + } + xpc_release(message); + } + return result; +} + +// Return retained array value of message reply (or NULL if error) +CFArrayRef swca_copy_pairs(enum SWCAXPCOperation op, + const audit_token_t *auditToken, + CFErrorRef *error) +{ + CFArrayRef result = NULL; + xpc_object_t message = swca_create_message(op, error); + if (message) { + xpc_dictionary_set_data(message, kSecXPCKeyClientToken, auditToken, sizeof(audit_token_t)); + xpc_object_t reply = swca_message_with_reply_sync(message, error); + if (reply) { + result = (CFArrayRef) swca_message_copy_response(reply, error); + if (!(result && CFGetTypeID(result) == CFArrayGetTypeID())) { + CFReleaseNull(result); + } + xpc_release(reply); + } + xpc_release(message); + } + return result; +} + +bool swca_set_selection(enum SWCAXPCOperation op, + const audit_token_t *auditToken, + CFTypeRef dictionary, + CFErrorRef *error) +{ + bool result = false; + xpc_object_t message = swca_create_message(op, error); + if (message) { + xpc_dictionary_set_data(message, kSecXPCKeyClientToken, auditToken, sizeof(audit_token_t)); + if (SecXPCDictionarySetPList(message, kSecXPCKeyQuery, dictionary, error)) { + xpc_object_t reply = swca_message_with_reply_sync(message, error); + if (reply) { + long value = swca_message_response(reply, error); + if (value != 0) { + result = true; + }; + xpc_release(reply); + } + } + xpc_release(message); + } + return result; +} + +bool swca_send_sync_and_do(enum SWCAXPCOperation op, CFErrorRef *error, + bool (^add_to_message)(xpc_object_t message, CFErrorRef* error), + bool (^handle_response)(xpc_object_t response, CFErrorRef* error)) { + xpc_object_t message = swca_create_message(op, error); + bool ok = false; + if (message) { + if (!add_to_message || add_to_message(message, error)) { + xpc_object_t response = swca_message_with_reply_sync(message, error); + if (response) { + if (swca_message_no_error(response, error)) { + ok = (!handle_response || handle_response(response, error)); + } + xpc_release(response); + } + } + xpc_release(message); + } + + return ok; +} + + +/* vi:set ts=4 sw=4 et: */ diff --git a/Security/sec/SharedWebCredential/swcagent_client.h b/Security/sec/SharedWebCredential/swcagent_client.h new file mode 100644 index 00000000..907d62a9 --- /dev/null +++ b/Security/sec/SharedWebCredential/swcagent_client.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#ifndef _SWCAGENT_CLIENT_H_ +#define _SWCAGENT_CLIENT_H_ + +#include + +#include +#include +#include + +#include +#include + +// TODO: This should be in client of XPC code locations... +#define kSWCAXPCServiceName "com.apple.security.swcagent" + +// +// MARK: XPC Information. +// + +extern CFStringRef sSWCAXPCErrorDomain; + +// +// MARK: XPC Interfaces +// + +extern const char *kSecXPCKeyOperation; +extern const char *kSecXPCKeyResult; +extern const char *kSecXPCKeyError; +extern const char *kSecXPCKeyClientToken; +extern const char *kSecXPCKeyPeerInfos; +extern const char *kSecXPCKeyUserLabel; +extern const char *kSecXPCKeyUserPassword; +extern const char *kSecXPCLimitInMinutes; +extern const char *kSecXPCKeyQuery; +extern const char *kSecXPCKeyAttributesToUpdate; +extern const char *kSecXPCKeyDomain; +extern const char *kSecXPCKeyDigest; +extern const char *kSecXPCKeyCertificate; +extern const char *kSecXPCKeySettings; +extern const char *kSecXPCKeyDeviceID; + +// +// MARK: Mach port request IDs +// +enum SWCAXPCOperation { + swca_add_request_id, + swca_update_request_id, + swca_delete_request_id, + swca_copy_request_id, + swca_select_request_id, + swca_copy_pairs_request_id, + swca_set_selection_request_id, + swca_enabled_request_id, +}; + +xpc_object_t swca_message_with_reply_sync(xpc_object_t message, CFErrorRef *error); +xpc_object_t swca_create_message(enum SWCAXPCOperation op, CFErrorRef *error); +bool swca_message_no_error(xpc_object_t message, CFErrorRef *error); +long swca_message_response(xpc_object_t replyMessage, CFErrorRef *error); + +bool swca_autofill_enabled(const audit_token_t *auditToken); + +bool swca_confirm_operation(enum SWCAXPCOperation op, + const audit_token_t *auditToken, + CFTypeRef query, + CFErrorRef *error, + void (^add_negative_entry)(CFStringRef fqdn)); + +CFTypeRef swca_message_copy_response(xpc_object_t replyMessage, CFErrorRef *error); + +CFDictionaryRef swca_copy_selected_dictionary(enum SWCAXPCOperation op, + const audit_token_t *auditToken, + CFTypeRef items, + CFErrorRef *error); + +CFArrayRef swca_copy_pairs(enum SWCAXPCOperation op, + const audit_token_t *auditToken, + CFErrorRef *error); + +bool swca_set_selection(enum SWCAXPCOperation op, + const audit_token_t *auditToken, + CFTypeRef dictionary, + CFErrorRef *error); + +bool swca_send_sync_and_do(enum SWCAXPCOperation op, CFErrorRef *error, + bool (^add_to_message)(xpc_object_t message, CFErrorRef* error), + bool (^handle_response)(xpc_object_t response, CFErrorRef* error)); + + +#endif /* _SWCAGENT_CLIENT_H_ */ diff --git a/Security/sec/config/base.xcconfig b/Security/sec/config/base.xcconfig new file mode 100644 index 00000000..012f1740 --- /dev/null +++ b/Security/sec/config/base.xcconfig @@ -0,0 +1,49 @@ +CODE_SIGN_IDENTITY = - +GCC_VERSION = com.apple.compilers.llvm.clang.1_0 +DEBUG_INFORMATION_FORMAT = dwarf-with-dsym +CURRENT_PROJECT_VERSION = $(RC_ProjectSourceVersion) +VERSIONING_SYSTEM = apple-generic +DEAD_CODE_STRIPPING = YES + +ARCHS = $(ARCHS_STANDARD_32_64_BIT) + +GCC_WARN_CHECK_SWITCH_STATEMENTS = YES +GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO // should be YES at some point +CLANG_WARN_EMPTY_BODY = YES +GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES +GCC_WARN_SHADOW = NO // should be yes +CLANG_WARN_CONSTANT_CONVERSION = YES +GCC_WARN_64_TO_32_BIT_CONVERSION = YES +CLANG_WARN_ENUM_CONVERSION = YES +CLANG_WARN_INT_CONVERSION = NO// should be yes +CLANG_WARN_IMPLICIT_SIGN_CONVERSION = NO // should be yes +GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES +GCC_WARN_ABOUT_RETURN_TYPE = YES +GCC_WARN_MISSING_PARENTHESES = YES +GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = NO // should be yes +GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES +GCC_WARN_ABOUT_MISSING_NEWLINE = YES +//WARNING_CFLAGS +GCC_WARN_ABOUT_POINTER_SIGNEDNESS = YES +GCC_WARN_SIGN_COMPARE = YES +CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = NO // should be yes +GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES +GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES +GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES +GCC_WARN_UNINITIALIZED_AUTOS = YES +GCC_WARN_UNKNOWN_PRAGMAS = YES +GCC_WARN_UNUSED_FUNCTION = YES +GCC_WARN_UNUSED_LABEL = YES +GCC_WARN_UNUSED_PARAMETER = NO // should be yes +GCC_WARN_UNUSED_VALUE = YES +GCC_WARN_UNUSED_VARIABLE = YES + +// No executables are made in sec, it can't know how +// Therefore we shouldn't strip anyting +// if somehow we decide to, the default is debuggable. + +COPY_PHASE_STRIP = NO +STRIP_STYLE = debugging +STRIP_INSTALLED_PRODUCT = NO + +WARNING_CFLAGS = -Wglobal-constructors -Wno-deprecated-declarations $(inherited) diff --git a/sec/config/debug.xcconfig b/Security/sec/config/debug.xcconfig similarity index 100% rename from sec/config/debug.xcconfig rename to Security/sec/config/debug.xcconfig diff --git a/sec/config/lib-arc-only.xcconfig b/Security/sec/config/lib-arc-only.xcconfig similarity index 100% rename from sec/config/lib-arc-only.xcconfig rename to Security/sec/config/lib-arc-only.xcconfig diff --git a/Security/sec/config/lib.xcconfig b/Security/sec/config/lib.xcconfig new file mode 100644 index 00000000..72acaefc --- /dev/null +++ b/Security/sec/config/lib.xcconfig @@ -0,0 +1,34 @@ +PRODUCT_NAME = $(TARGET_NAME) +EXECUTABLE_PREFIX = + +CODE_SIGN_IDENTITY = + +INDIGO_INSTALL_PATH_PREFIX[sdk=iphonesimulator*] = $(SDKROOT) + +HEADER_SEARCH_PATHS = $(inherited) $(PROJECT_DIR) $(PROJECT_DIR)/../utilities $(PROJECT_DIR)/ipc $(PROJECT_DIR)/../sectask $(PROJECT_DIR)/../libsecurity_asn1 $(PROJECT_DIR)/../libsecurity_ssl $(PROJECT_DIR)/../regressions $(PROJECT_DIR)/SOSCircle $(PROJECT_DIR)/../libsecurity_keychain/libDER $(PROJECT_DIR)/ProtectedCloudStorage $(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include + +HEADER_SEARCH_PATHS[sdk=macosx*] = $(inherited) $(PROJECT_DIR)/../libsecurity_smime $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers + +HEADER_SEARCH_PATHS[sdk=iphone*] = $(inherited) $(PROJECT_DIR)/../../libsecurity_smime $(PROJECT_DIR)/sectask + +FRAMEWORK_SEARCH_PATHS[sdk=macosx*] = $(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks + +OTHER_CFLAGS = -isystem$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders $(inherited) + +COPY_PHASE_STRIP = NO +SKIP_INSTALL = YES +COPY_PHASE_STRIP = NO + +ALWAYS_SEARCH_USER_PATHS = YES + +GCC_C_LANGUAGE_STANDARD = gnu99 + +HEADERMAP_INCLUDES_FRAMEWORK_ENTRIES_FOR_ALL_PRODUCT_TYPES = NO + +WARNING_CFLAGS = $(inherited) -Wmost -Wno-four-char-constants -Wno-unknown-pragmas + +GCC_SYMBOLS_PRIVATE_EXTERN = NO + +SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator + +GCC_PREPROCESSOR_DEFINITIONS[sdk=iphonesimulator*] = $(inherited) INDIGO=1 diff --git a/sec/config/release.xcconfig b/Security/sec/config/release.xcconfig similarity index 100% rename from sec/config/release.xcconfig rename to Security/sec/config/release.xcconfig diff --git a/sec/ipc/client.c b/Security/sec/ipc/client.c similarity index 90% rename from sec/ipc/client.c rename to Security/sec/ipc/client.c index 96dafb04..09babe7b 100644 --- a/sec/ipc/client.c +++ b/Security/sec/ipc/client.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2007-2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2009,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, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -36,8 +37,7 @@ #include #include #include // TODO Fixme this gets us SecError(). -#include "securityd_client.h" -#include "SecuritydXPC.h" +#include struct securityd *gSecurityd; @@ -109,20 +109,20 @@ securityd_message_with_reply_sync(xpc_object_t message, CFErrorRef *error) xpc_object_t reply = NULL; xpc_connection_t connection = securityd_connection(); - for (int try = 1; try <= 2; ++try) { + const int max_tries = 4; // Per N61/12A342: Audio Playback... for why this needs to be at least 3, so we made it 4. + + unsigned int tries_left = max_tries; + do { + if (reply) xpc_release(reply); reply = xpc_connection_send_message_with_reply_sync(connection, message); - if (try == 1 && reply == XPC_ERROR_CONNECTION_INTERRUPTED) { - xpc_release(reply); - } else { - break; - } - } + } while (reply == XPC_ERROR_CONNECTION_INTERRUPTED && --tries_left > 0); if (xpc_get_type(reply) == XPC_TYPE_ERROR) { CFIndex code = 0; - if (reply == XPC_ERROR_CONNECTION_INTERRUPTED || reply == XPC_ERROR_CONNECTION_INVALID) + if (reply == XPC_ERROR_CONNECTION_INTERRUPTED || reply == XPC_ERROR_CONNECTION_INVALID) { code = kSecXPCErrorConnectionFailed; - else if (reply == XPC_ERROR_TERMINATION_IMMINENT) + seccritical("Failed to talk to secd after %d attempts.", max_tries); + } else if (reply == XPC_ERROR_TERMINATION_IMMINENT) code = kSecXPCErrorUnknown; else code = kSecXPCErrorUnknown; diff --git a/Security/sec/ipc/com.apple.secd.plist b/Security/sec/ipc/com.apple.secd.plist new file mode 100644 index 00000000..42bc039d --- /dev/null +++ b/Security/sec/ipc/com.apple.secd.plist @@ -0,0 +1,40 @@ + + + + + EnablePressuredExit + + EnableTransactions + + LimitLoadToSessionType + Background + POSIXSpawnType + Interactive + Label + com.apple.secd + MachServices + + com.apple.secd + + com.apple.securityd.xpc + + + OnDemand + + ProgramArguments + + /usr/libexec/secd + + ServiceIPC + + Umask + 54 + EnvironmentVariables + + DEBUGSCOPE + none + WAIT4DEBUGGER + NO + + + diff --git a/Security/sec/ipc/com.apple.securityd.plist b/Security/sec/ipc/com.apple.securityd.plist new file mode 100644 index 00000000..a0ebc012 --- /dev/null +++ b/Security/sec/ipc/com.apple.securityd.plist @@ -0,0 +1,40 @@ + + + + + EnablePressuredExit + + EnableTransactions + + EnvironmentVariables + + DEBUGSCOPE + none + WAIT4DEBUGGER + NO + + GroupName + _securityd + Label + com.apple.securityd + MachServices + + com.apple.securityd + + + OnDemand + + ProgramArguments + + /usr/libexec/securityd + + ServiceIPC + + Umask + 54 + UserName + _securityd + POSIXSpawnType + Interactive + + diff --git a/Security/sec/ipc/securityd_client.h b/Security/sec/ipc/securityd_client.h new file mode 100755 index 00000000..b62c5ea4 --- /dev/null +++ b/Security/sec/ipc/securityd_client.h @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2007-2009,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@ + */ +#ifndef _SECURITYD_CLIENT_H_ +#define _SECURITYD_CLIENT_H_ + +#include + +# include +#ifndef MINIMIZE_INCLUDES +# include +# include +#else +typedef struct __SecTrustStore *SecTrustStoreRef; +# ifndef _SECURITY_SECCERTIFICATE_H_ +typedef struct __SecCertificate *SecCertificateRef; +# endif // _SECURITY_SECCERTIFICATE_H_ +# ifndef _SECURITY_SECCERTIFICATEPATH_H_ +typedef struct SecCertificatePath *SecCertificatePathRef; +# endif // _SECURITY_SECCERTIFICATEPATH_H_ +#endif // MINIMIZE_INCLUDES + +#include +#include +#include + +#include + +#include +#include + +// TODO: This should be in client of XPC code locations... +#if SECITEM_SHIM_OSX +#define kSecuritydXPCServiceName "com.apple.securityd.xpc" +#else +#define kSecuritydXPCServiceName "com.apple.securityd" +#endif // *** END SECITEM_SHIM_OSX *** + +// +// MARK: XPC Information. +// + +extern CFStringRef sSecXPCErrorDomain; + +extern const char *kSecXPCKeyOperation; +extern const char *kSecXPCKeyResult; +extern const char *kSecXPCKeyError; +extern const char *kSecXPCKeyPeerInfos; +extern const char *kSecXPCKeyUserLabel; +extern const char *kSecXPCKeyBackup; +extern const char *kSecXPCKeyKeybag; +extern const char *kSecXPCKeyUserPassword; + +// +// MARK: Dispatch macros +// + +#define SECURITYD_XPC(sdp, wrapper, ...) ((gSecurityd && gSecurityd->sdp) ? gSecurityd->sdp(__VA_ARGS__) : wrapper(sdp ## _id, __VA_ARGS__)) + +// +// MARK: Object to XPC format conversion. +// + + +// +// MARK: XPC Interfaces +// + +extern const char *kSecXPCKeyOperation; +extern const char *kSecXPCKeyResult; +extern const char *kSecXPCKeyError; +extern const char *kSecXPCKeyPeerInfos; +extern const char *kSecXPCKeyUserLabel; +extern const char *kSecXPCKeyUserPassword; +extern const char *kSecXPCLimitInMinutes; +extern const char *kSecXPCKeyQuery; +extern const char *kSecXPCKeyAttributesToUpdate; +extern const char *kSecXPCKeyDomain; +extern const char *kSecXPCKeyDigest; +extern const char *kSecXPCKeyCertificate; +extern const char *kSecXPCKeySettings; +extern const char *kSecXPCPublicPeerId; // Public peer id +extern const char *kSecXPCOTRSession; // OTR session bytes +extern const char *kSecXPCData; // Data to process +extern const char *kSecXPCOTRReady; // OTR ready for messages +extern const char *kSecXPCKeyDeviceID; + +// +// MARK: Mach port request IDs +// +enum SecXPCOperation { + sec_item_add_id = 0, + sec_item_copy_matching_id = 1, + sec_item_update_id = 2, + sec_item_delete_id = 3, + // trust_store_for_domain -- NOT an ipc + sec_trust_store_contains_id = 4, + sec_trust_store_set_trust_settings_id = 5, + sec_trust_store_remove_certificate_id = 6, + // remove_all -- NOT an ipc + sec_delete_all_id = 7, + sec_trust_evaluate_id = 8, + // Any new items MUST be added below here + // This allows updating roots on a device, since SecTrustEvaluate must continue to work + sec_keychain_backup_id, + sec_keychain_restore_id, + sec_keychain_backup_syncable_id, + sec_keychain_restore_syncable_id, + sec_keychain_sync_update_key_parameter_id, + sec_keychain_sync_update_circle_id, + sec_keychain_sync_update_message_id, + sec_ota_pki_asset_version_id, + sec_otr_session_create_remote_id, + sec_otr_session_process_packet_remote_id, + kSecXPCOpOTAPKIGetNewAsset, + kSecXPCOpOTAGetEscrowCertificates, + kSecXPCOpProcessUnlockNotification, + kSecXPCOpProcessSyncWithAllPeers, + kSecXPCOpRollKeys, + sec_add_shared_web_credential_id, + sec_copy_shared_web_credential_id, + sec_get_log_settings_id, + sec_set_xpc_log_settings_id, + soscc_EnsurePeerRegistration_id, + kSecXPCOpRequestEnsureFreshParameters, + // any process using an operation below here is required to have entitlement keychain-cloud-circle + kSecXPCOpTryUserCredentials, + kSecXPCOpSetUserCredentials, + kSecXPCOpCanAuthenticate, + kSecXPCOpPurgeUserCredentials, + kSecXPCOpDeviceInCircle, + kSecXPCOpRequestToJoin, + kSecXPCOpRequestToJoinAfterRestore, + kSecXPCOpResetToOffering, + kSecXPCOpResetToEmpty, + kSecXPCOpRemoveThisDeviceFromCircle, + kSecXPCOpBailFromCircle, + kSecXPCOpAcceptApplicants, + kSecXPCOpRejectApplicants, + kSecXPCOpCopyApplicantPeerInfo, + kSecXPCOpCopyValidPeerPeerInfo, + kSecXPCOpValidateUserPublic, + kSecXPCOpCopyNotValidPeerPeerInfo, + kSecXPCOpCopyPeerPeerInfo, + kSecXPCOpCopyConcurringPeerPeerInfo, + kSecXPCOpCopyGenerationPeerInfo, + kSecXPCOpGetLastDepartureReason, + kSecXPCOpCopyIncompatibilityInfo, + kSecXPCOpCopyRetirementPeerInfo, + kSecXPCOpRequestDeviceID, + kSecXPCOpSetDeviceID, +}; + + + +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_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 + bool (*sec_trust_store_contains)(SecTrustStoreRef ts, CFDataRef digest, bool *contains, CFErrorRef* error); + bool (*sec_trust_store_set_trust_settings)(SecTrustStoreRef ts, SecCertificateRef certificate, CFTypeRef trustSettingsDictOrArray, CFErrorRef* error); + bool (*sec_trust_store_remove_certificate)(SecTrustStoreRef ts, CFDataRef digest, CFErrorRef* error); + 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, 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); + CFArrayRef (*sec_keychain_sync_update_key_parameter)(CFDictionaryRef update, 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); + int (*sec_ota_pki_asset_version)(CFErrorRef* error); + CFDataRef (*sec_otr_session_create_remote)(CFDataRef publicPeerId, CFErrorRef* error); + bool (*sec_otr_session_process_packet_remote)(CFDataRef sessionData, CFDataRef inputPacket, CFDataRef* outputSessionData, CFDataRef* outputPacket, bool *readyForMessages, CFErrorRef* error); + bool (*soscc_TryUserCredentials)(CFStringRef user_label, CFDataRef user_password, CFErrorRef *error); + bool (*soscc_SetUserCredentials)(CFStringRef user_label, CFDataRef user_password, CFErrorRef *error); + bool (*soscc_CanAuthenticate)(CFErrorRef *error); + bool (*soscc_PurgeUserCredentials)(CFErrorRef *error); + SOSCCStatus (*soscc_ThisDeviceIsInCircle)(CFErrorRef* error); + bool (*soscc_RequestToJoinCircle)(CFErrorRef* error); + bool (*soscc_RequestToJoinCircleAfterRestore)(CFErrorRef* error); + bool (*soscc_RequestEnsureFreshParameters)(CFErrorRef* error); + CFStringRef (*soscc_RequestDeviceID)(CFErrorRef* error); + bool (*soscc_SetDeviceID)(CFStringRef IDS, CFErrorRef *error); + bool (*soscc_ResetToOffering)(CFErrorRef* error); + bool (*soscc_ResetToEmpty)(CFErrorRef* error); + bool (*soscc_RemoveThisDeviceFromCircle)(CFErrorRef* error); + bool (*soscc_BailFromCircle)(uint64_t limit_in_seconds, CFErrorRef* error); + bool (*soscc_AcceptApplicants)(CFArrayRef applicants, CFErrorRef* error); + bool (*soscc_RejectApplicants)(CFArrayRef applicants, CFErrorRef* error); + bool (*soscc_ValidateUserPublic)(CFErrorRef* error); + CFArrayRef (*soscc_CopyGenerationPeerInfo)(CFErrorRef* error); + CFArrayRef (*soscc_CopyApplicantPeerInfo)(CFErrorRef* error); + CFArrayRef (*soscc_CopyValidPeerPeerInfo)(CFErrorRef* error); + CFArrayRef (*soscc_CopyNotValidPeerPeerInfo)(CFErrorRef* error); + CFArrayRef (*soscc_CopyRetirementPeerInfo)(CFErrorRef* error); + CFArrayRef (*soscc_CopyPeerInfo)(CFErrorRef* error); + CFArrayRef (*soscc_CopyConcurringPeerInfo)(CFErrorRef* error); + CFStringRef (*soscc_CopyIncompatibilityInfo)(CFErrorRef* error); + enum DepartureReason (*soscc_GetLastDepartureReason)(CFErrorRef* error); + CFArrayRef (*ota_CopyEscrowCertificates)(uint32_t escrowRootType, CFErrorRef* error); + int (*sec_ota_pki_get_new_asset)(CFErrorRef* error); + SyncWithAllPeersReason (*soscc_ProcessSyncWithAllPeers)(CFErrorRef* error); + bool (*soscc_EnsurePeerRegistration)(CFErrorRef* error); + bool (*sec_roll_keys)(bool force, CFErrorRef* error); + CFArrayRef (*sec_keychain_sync_update_circle)(CFDictionaryRef update, CFErrorRef *error); + CFArrayRef (*sec_keychain_sync_update_message)(CFDictionaryRef update, CFErrorRef *error); + CFPropertyListRef (*sec_get_log_settings)(CFErrorRef* error); + bool (*sec_set_xpc_log_settings)(CFTypeRef type, CFErrorRef* error); +}; + +extern struct securityd *gSecurityd; + +CFArrayRef SecAccessGroupsGetCurrent(void); + +// TODO Rename me +CFStringRef SOSCCGetOperationDescription(enum SecXPCOperation op); +xpc_object_t securityd_message_with_reply_sync(xpc_object_t message, CFErrorRef *error); +xpc_object_t securityd_create_message(enum SecXPCOperation op, CFErrorRef *error); +bool securityd_message_no_error(xpc_object_t message, CFErrorRef *error); + + +bool securityd_send_sync_and_do(enum SecXPCOperation op, CFErrorRef *error, + bool (^add_to_message)(xpc_object_t message, CFErrorRef* error), + bool (^handle_response)(xpc_object_t response, CFErrorRef* error)); + +// For testing only, never call this in a threaded program! +void SecServerSetMachServiceName(const char *name); + +#endif /* _SECURITYD_CLIENT_H_ */ diff --git a/Security/sec/ipc/server.c b/Security/sec/ipc/server.c new file mode 100644 index 00000000..4a26d2d7 --- /dev/null +++ b/Security/sec/ipc/server.c @@ -0,0 +1,933 @@ +/* + * Copyright (c) 2007-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* For SecItemDeleteAll */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static CFStringRef SecTaskCopyStringForEntitlement(SecTaskRef task, + CFStringRef entitlement) +{ + CFStringRef value = (CFStringRef)SecTaskCopyValueForEntitlement(task, + entitlement, NULL); + if (value && CFGetTypeID(value) != CFStringGetTypeID()) { + CFRelease(value); + value = NULL; + } + + return value; +} + +static CFArrayRef SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task, + CFStringRef entitlement) +{ + CFArrayRef value = (CFArrayRef)SecTaskCopyValueForEntitlement(task, + entitlement, NULL); + if (value) { + if (CFGetTypeID(value) == CFArrayGetTypeID()) { + CFIndex ix, count = CFArrayGetCount(value); + for (ix = 0; ix < count; ++ix) { + CFStringRef string = (CFStringRef)CFArrayGetValueAtIndex(value, ix); + if (CFGetTypeID(string) != CFStringGetTypeID()) { + CFRelease(value); + value = NULL; + break; + } + } + } else { + CFRelease(value); + value = NULL; + } + } + + return value; +} + +static CFStringRef SecTaskCopyApplicationIdentifier(SecTaskRef task) { + return SecTaskCopyStringForEntitlement(task, + kSecEntitlementApplicationIdentifier); +} + +static CFArrayRef SecTaskCopySharedWebCredentialDomains(SecTaskRef task) { + return SecTaskCopyArrayOfStringsForEntitlement(task, + kSecEntitlementAssociatedDomains); +} + +static CFArrayRef SecTaskCopyAccessGroups(SecTaskRef task) { + CFMutableArrayRef groups = NULL; + CFArrayRef keychainAccessGroups = SecTaskCopyArrayOfStringsForEntitlement(task, + kSecEntitlementKeychainAccessGroups); + CFArrayRef appleSecurityApplicationGroups = SecTaskCopyArrayOfStringsForEntitlement(task, + kSecEntitlementAppleSecurityApplicationGroups); + CFStringRef appID = SecTaskCopyApplicationIdentifier(task); + CFIndex kagLen = keychainAccessGroups ? CFArrayGetCount(keychainAccessGroups) : 0; + CFIndex asagLen = appleSecurityApplicationGroups ? CFArrayGetCount(appleSecurityApplicationGroups) : 0; + CFIndex len = kagLen + asagLen + (appID ? 1 : 0); + if (len) { + groups = CFArrayCreateMutable(kCFAllocatorDefault, len, &kCFTypeArrayCallBacks); + if (kagLen) + CFArrayAppendArray(groups, keychainAccessGroups, CFRangeMake(0, kagLen)); + if (appID) + CFArrayAppendValue(groups, appID); + if (asagLen) + CFArrayAppendArray(groups, appleSecurityApplicationGroups, CFRangeMake(0, asagLen)); +#if TARGET_IPHONE_SIMULATOR + } else { + secwarning("No keychain access group specified whilst running in simulator, falling back to default set"); + groups = (CFMutableArrayRef)CFRetainSafe(SecAccessGroupsGetCurrent()); +#endif + } + + CFReleaseSafe(appID); + CFReleaseSafe(keychainAccessGroups); + CFReleaseSafe(appleSecurityApplicationGroups); + return groups; +} + +static bool SecTaskGetBooleanValueForEntitlement(SecTaskRef task, + CFStringRef entitlement) { + CFStringRef canModify = (CFStringRef)SecTaskCopyValueForEntitlement(task, + entitlement, NULL); + if (!canModify) + return false; + CFTypeID canModifyType = CFGetTypeID(canModify); + bool ok = (CFBooleanGetTypeID() == canModifyType) && CFBooleanGetValue((CFBooleanRef)canModify); + CFRelease(canModify); + return ok; +} + +static void with_label_and_password(xpc_object_t message, void (^action)(CFStringRef label, CFDataRef password)) { + const char *label_utf8 = xpc_dictionary_get_string(message, kSecXPCKeyUserLabel); + + size_t password_length = 0; + const void *password_data = xpc_dictionary_get_data(message, kSecXPCKeyUserPassword, &password_length); + + CFDataRef user_password = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, password_data, password_length, kCFAllocatorNull); + CFStringRef user_label = CFStringCreateWithCString(kCFAllocatorDefault, label_utf8, kCFStringEncodingUTF8); + + action(user_label, user_password); + + CFReleaseNull(user_password); + CFReleaseNull(user_label); +} + +static bool SecXPCDictionarySetChainOptional(xpc_object_t message, const char *key, SecCertificatePathRef path, CFErrorRef *error) { + if (!path) + return true; + xpc_object_t xpc_chain = SecCertificatePathCopyXPCArray(path, error); + if (!xpc_chain) + return false; + + xpc_dictionary_set_value(message, key, xpc_chain); + xpc_release(xpc_chain); + return true; +} + +static SecCertificateRef SecXPCDictionaryCopyCertificate(xpc_object_t message, const char *key, CFErrorRef *error) { + size_t length = 0; + const void *bytes = xpc_dictionary_get_data(message, key, &length); + if (bytes) { + SecCertificateRef certificate = SecCertificateCreateWithBytes(kCFAllocatorDefault, bytes, length); + if (certificate) + return certificate; + SecError(errSecDecode, error, CFSTR("object for key %s failed to create certificate from data"), key); + } else { + SecError(errSecParam, error, CFSTR("object for key %s missing"), key); + } + return NULL; +} + +static bool SecXPCDictionaryCopyCertificates(xpc_object_t message, const char *key, CFArrayRef *certificates, CFErrorRef *error) { + xpc_object_t xpc_certificates = xpc_dictionary_get_value(message, key); + if (!xpc_certificates) + return SecError(errSecAllocate, error, CFSTR("no certs for key %s"), key); + *certificates = SecCertificateXPCArrayCopyArray(xpc_certificates, error); + return *certificates; +} + +static bool SecXPCDictionaryCopyCertificatesOptional(xpc_object_t message, const char *key, CFArrayRef *certificates, CFErrorRef *error) { + xpc_object_t xpc_certificates = xpc_dictionary_get_value(message, key); + if (!xpc_certificates) { + *certificates = NULL; + return true; + } + *certificates = SecCertificateXPCArrayCopyArray(xpc_certificates, error); + return *certificates; +} + +static bool SecXPCDictionaryCopyPoliciesOptional(xpc_object_t message, const char *key, CFArrayRef *policies, CFErrorRef *error) { + xpc_object_t xpc_policies = xpc_dictionary_get_value(message, key); + if (!xpc_policies) { + if (policies) + *policies = NULL; + return true; + } + *policies = SecPolicyXPCArrayCopyArray(xpc_policies, error); + return *policies != NULL; +} + +static SecTrustStoreRef SecXPCDictionaryGetTrustStore(xpc_object_t message, const char *key, CFErrorRef *error) { + SecTrustStoreRef ts = NULL; + CFStringRef domain = SecXPCDictionaryCopyString(message, key, error); + if (domain) { + ts = SecTrustStoreForDomainName(domain, error); + CFRelease(domain); + } + return ts; +} + +static bool SecXPCDictionaryGetDouble(xpc_object_t message, const char *key, double *pvalue, CFErrorRef *error) { + *pvalue = xpc_dictionary_get_double(message, key); + if (*pvalue == NAN) { + return SecError(errSecParam, error, CFSTR("object for key %s bad double"), key); + } + return true; +} + +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; + CFArrayRef accessGroups = NULL; + CFArrayRef domains = NULL; + + secdebug("serverxpc", "entering"); + if (type == XPC_TYPE_DICTIONARY) { + // TODO: Find out what we're dispatching. + replyMessage = xpc_dictionary_create_reply(event); + + uint64_t operation = xpc_dictionary_get_uint64(event, kSecXPCKeyOperation); + secdebug("serverxpc", "operation: %@ (%" PRIu64 ")", SOSCCGetOperationDescription((enum SecXPCOperation)operation), operation); + + bool hasEntitlement; + audit_token_t auditToken = {}; + xpc_connection_get_audit_token(connection, &auditToken); + + clientTask = SecTaskCreateWithAuditToken(kCFAllocatorDefault, auditToken); + accessGroups = SecTaskCopyAccessGroups(clientTask); + if (operation == sec_add_shared_web_credential_id || operation == sec_copy_shared_web_credential_id) { + domains = SecTaskCopySharedWebCredentialDomains(clientTask); + } + + // operations before kSecXPCOpTryUserCredentials don't need this entitlement. + hasEntitlement = (operation < kSecXPCOpTryUserCredentials) || + (clientTask && SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementKeychainCloudCircle)); + + // Per Disable the entitlement check for "keychain-cloud-circle" + // we disable entitlement enforcement. However, we still log so we know who needs the entitlement + + if (!hasEntitlement) { + CFErrorRef entitlementError = NULL; + SecError(errSecMissingEntitlement, &entitlementError, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation)operation), clientTask, kSecEntitlementKeychainCloudCircle); + secnotice("serverxpc", "MissingEntitlement: %@", entitlementError); + CFReleaseSafe(entitlementError); + } + + if (true) { + switch (operation) + { + case sec_item_add_id: + { + CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); + if (query) { + CFTypeRef result = NULL; + if (_SecItemAdd(query, accessGroups, &result, &error) && result) { + SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); + CFRelease(result); + } + CFRelease(query); + } + break; + } + case sec_item_copy_matching_id: + { + CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); + if (query) { + CFTypeRef result = NULL; + if (_SecItemCopyMatching(query, accessGroups, &result, &error) && result) { + SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); + CFRelease(result); + } + CFRelease(query); + } + break; + } + case sec_item_update_id: + { + CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); + if (query) { + CFDictionaryRef attributesToUpdate = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyAttributesToUpdate, &error); + if (attributesToUpdate) { + bool result = _SecItemUpdate(query, attributesToUpdate, accessGroups, &error); + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); + CFRelease(attributesToUpdate); + } + CFRelease(query); + } + break; + } + case sec_item_delete_id: + { + CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); + if (query) { + bool result = _SecItemDelete(query, accessGroups, &error); + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); + CFRelease(query); + } + break; + } + case sec_trust_store_contains_id: + { + SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error); + if (ts) { + CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, &error); + if (digest) { + bool contains; + if (SecTrustStoreContainsCertificateWithDigest(ts, digest, &contains, &error)) + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, contains); + CFRelease(digest); + } + } + break; + } + case sec_trust_store_set_trust_settings_id: + { + SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error); + if (ts) { + SecCertificateRef certificate = SecXPCDictionaryCopyCertificate(event, kSecXPCKeyCertificate, &error); + if (certificate) { + CFTypeRef trustSettingsDictOrArray = NULL; + if (SecXPCDictionaryCopyPListOptional(event, kSecXPCKeySettings, &trustSettingsDictOrArray, &error)) { + bool result = _SecTrustStoreSetTrustSettings(ts, certificate, trustSettingsDictOrArray, &error); + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); + CFReleaseSafe(trustSettingsDictOrArray); + } + CFRelease(certificate); + } + } + break; + } + case sec_trust_store_remove_certificate_id: + { + SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error); + if (ts) { + CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, &error); + if (digest) { + bool result = SecTrustStoreRemoveCertificateWithDigest(ts, digest, &error); + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); + CFRelease(digest); + } + } + break; + } + case sec_delete_all_id: + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, _SecItemDeleteAll(&error)); + break; + case sec_trust_evaluate_id: + { + CFArrayRef certificates = NULL, anchors = NULL, policies = NULL; + bool anchorsOnly = xpc_dictionary_get_bool(event, kSecTrustAnchorsOnlyKey); + double verifyTime; + if (SecXPCDictionaryCopyCertificates(event, kSecTrustCertificatesKey, &certificates, &error) && + SecXPCDictionaryCopyCertificatesOptional(event, kSecTrustAnchorsKey, &anchors, &error) && + SecXPCDictionaryCopyPoliciesOptional(event, kSecTrustPoliciesKey, &policies, &error) && + 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); + + // Clear replyMessage so we don't send a synchronous reply. + xpc_object_t asyncReply = replyMessage; + replyMessage = NULL; + + SecTrustServerEvaluateBlock(certificates, anchors, anchorsOnly, policies, verifyTime, accessGroups, ^(SecTrustResultType tr, CFArrayRef details, CFDictionaryRef info, SecCertificatePathRef chain, CFErrorRef replyError) { + // Send back reply now + if (replyError) { + CFRetain(replyError); + } else { + xpc_dictionary_set_int64(asyncReply, kSecTrustResultKey, tr); + SecXPCDictionarySetPListOptional(asyncReply, kSecTrustDetailsKey, details, &replyError) && + SecXPCDictionarySetPListOptional(asyncReply, kSecTrustInfoKey, info, &replyError) && + SecXPCDictionarySetChainOptional(asyncReply, kSecTrustChainKey, chain, &replyError); + } + if (replyError) { + secdebug("ipc", "%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyError); + xpc_object_t xpcReplyError = SecCreateXPCObjectWithCFError(replyError); + if (xpcReplyError) { + xpc_dictionary_set_value(asyncReply, kSecXPCKeyError, xpcReplyError); + xpc_release(xpcReplyError); + } + CFRelease(replyError); + } else { + secdebug("ipc", "%@ %@ reponding %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), asyncReply); + } + + xpc_connection_send_message(connection, asyncReply); + xpc_release(asyncReply); + xpc_release(connection); + CFReleaseSafe(clientTask); + }); + } + CFReleaseSafe(policies); + CFReleaseSafe(anchors); + CFReleaseSafe(certificates); + break; + } + case sec_keychain_backup_id: + { + CFDataRef keybag = NULL, passcode = NULL; + if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyKeybag, &keybag, &error)) { + if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) { + CFDataRef backup = _SecServerKeychainBackup(keybag, passcode, &error); + if (backup) { + SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, backup, &error); + CFRelease(backup); + } + CFReleaseSafe(passcode); + } + CFReleaseSafe(keybag); + } + break; + } + case sec_keychain_restore_id: + { + CFDataRef 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); + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); + CFReleaseSafe(passcode); + } + CFRelease(keybag); + } + CFRelease(backup); + } + break; + } + case sec_keychain_sync_update_key_parameter_id: + { + CFDictionaryRef updates = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); + if (updates) { + CFArrayRef result = _SecServerKeychainSyncUpdateKeyParameter(updates, &error); + SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); + CFReleaseNull(result); + } + CFReleaseNull(updates); + break; + } + case sec_keychain_sync_update_circle_id: + { + CFDictionaryRef updates = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); + if (updates) { + CFArrayRef result = _SecServerKeychainSyncUpdateCircle(updates, &error); + SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); + CFReleaseNull(result); + } + CFReleaseNull(updates); + break; + } + case sec_keychain_sync_update_message_id: + { + CFDictionaryRef updates = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); + if (updates) { + CFArrayRef result = _SecServerKeychainSyncUpdateMessage(updates, &error); + SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); + CFReleaseNull(result); + } + CFReleaseNull(updates); + break; + } + case sec_keychain_backup_syncable_id: + { + CFDictionaryRef oldbackup = NULL; + if (SecXPCDictionaryCopyDictionaryOptional(event, kSecXPCKeyBackup, &oldbackup, &error)) { + CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error); + if (keybag) { + CFDataRef passcode = NULL; + if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) { + CFDictionaryRef newbackup = _SecServerBackupSyncable(oldbackup, keybag, passcode, &error); + if (newbackup) { + SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, newbackup, &error); + CFRelease(newbackup); + } + CFReleaseSafe(passcode); + } + CFRelease(keybag); + } + CFReleaseSafe(oldbackup); + } + break; + } + case sec_keychain_restore_syncable_id: + { + CFDictionaryRef backup = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyBackup, &error); + if (backup) { + CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error); + if (keybag) { + CFDataRef passcode = NULL; + if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) { + bool result = _SecServerRestoreSyncable(backup, keybag, passcode, &error); + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); + CFReleaseSafe(passcode); + } + CFRelease(keybag); + } + CFRelease(backup); + } + break; + } + case sec_ota_pki_asset_version_id: + { + xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, + SecOTAPKIGetCurrentAssetVersion(&error)); + break; + } + case sec_add_shared_web_credential_id: + { + CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); + if (query) { + CFTypeRef result = NULL; + CFStringRef appID = (clientTask) ? SecTaskCopyApplicationIdentifier(clientTask) : NULL; + if (_SecAddSharedWebCredential(query, &auditToken, appID, domains, &result, &error) && result) { + SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); + CFRelease(result); + } + CFReleaseSafe(appID); + CFRelease(query); + } + break; + } + case sec_copy_shared_web_credential_id: + { + CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); + if (query) { + CFTypeRef result = NULL; + CFStringRef appID = (clientTask) ? SecTaskCopyApplicationIdentifier(clientTask) : NULL; + if (_SecCopySharedWebCredential(query, &auditToken, appID, domains, &result, &error) && result) { + SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); + CFRelease(result); + } + CFReleaseSafe(appID); + CFRelease(query); + } + break; + } + case sec_get_log_settings_id: + { + CFPropertyListRef currentList = SecCopyLogSettings_Server(&error); + if (currentList) { + SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, currentList, &error); + } + CFReleaseSafe(currentList); + break; + } + case sec_set_xpc_log_settings_id: + { + CFPropertyListRef newSettings = SecXPCDictionaryCopyPList(event, kSecXPCKeyQuery, &error); + if (newSettings) { + SecSetXPCLogSettings_Server(newSettings, &error); + } + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true); + CFReleaseNull(newSettings); + break; + } + case sec_otr_session_create_remote_id: + { + CFDataRef publicPeerId = NULL; + if (SecXPCDictionaryCopyDataOptional(event, kSecXPCPublicPeerId, &publicPeerId, &error)) { + CFDataRef otrSession = _SecOTRSessionCreateRemote(publicPeerId, &error); + if (otrSession) { + SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, otrSession, &error); + CFRelease(otrSession); + } + CFReleaseSafe(publicPeerId); + } + break; + } + case sec_otr_session_process_packet_remote_id: + { + CFDataRef sessionData = NULL, inputPacket = NULL, outputSessionData = NULL, outputPacket = NULL; + bool readyForMessages = false; + if (SecXPCDictionaryCopyDataOptional(event, kSecXPCOTRSession, &sessionData, &error)) { + if (SecXPCDictionaryCopyDataOptional(event, kSecXPCData, &inputPacket, &error)) { + bool result = _SecOTRSessionProcessPacketRemote(sessionData, inputPacket, &outputSessionData, &outputPacket, &readyForMessages, &error); + if (result) { + SecXPCDictionarySetData(replyMessage, kSecXPCOTRSession, outputSessionData, &error); + SecXPCDictionarySetData(replyMessage, kSecXPCData, outputPacket, &error); + xpc_dictionary_set_bool(replyMessage, kSecXPCOTRReady, readyForMessages); + CFRelease(outputSessionData); + CFRelease(outputPacket); + } + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); + + CFReleaseSafe(inputPacket); + } + CFReleaseSafe(sessionData); + } + break; + } + case kSecXPCOpTryUserCredentials: + with_label_and_password(event, ^(CFStringRef label, CFDataRef password) { + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, + SOSCCTryUserCredentials_Server(label, password, &error)); + }); + break; + case kSecXPCOpSetUserCredentials: + with_label_and_password(event, ^(CFStringRef label, CFDataRef password) { + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, + SOSCCSetUserCredentials_Server(label, password, &error)); + }); + break; + case kSecXPCOpCanAuthenticate: + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, + SOSCCCanAuthenticate_Server(&error)); + break; + case kSecXPCOpPurgeUserCredentials: + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, + SOSCCPurgeUserCredentials_Server(&error)); + break; + case kSecXPCOpDeviceInCircle: + xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, + SOSCCThisDeviceIsInCircle_Server(&error)); + break; + case kSecXPCOpRequestToJoin: + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, + SOSCCRequestToJoinCircle_Server(&error)); + break; + case kSecXPCOpRequestToJoinAfterRestore: + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, + SOSCCRequestToJoinCircleAfterRestore_Server(&error)); + break; + case kSecXPCOpRequestEnsureFreshParameters: + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, + SOSCCRequestEnsureFreshParameters_Server(&error)); + break; + case kSecXPCOpRequestDeviceID: + { + CFStringRef deviceID = SOSCCRequestDeviceID_Server(&error); + if (deviceID) { + SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, deviceID, &error); + } + } + break; + case kSecXPCOpSetDeviceID: + { + secerror("securityd_xpc_dictionary_handler!"); + CFStringRef IDS = SecXPCDictionaryCopyString(event, kSecXPCKeyDeviceID, &error); + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCSetDeviceID_Server(IDS, &error)); + CFReleaseNull(IDS); + } + break; + case kSecXPCOpResetToOffering: + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, + SOSCCResetToOffering_Server(&error)); + break; + case kSecXPCOpResetToEmpty: + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, + SOSCCResetToEmpty_Server(&error)); + break; + case kSecXPCOpRemoveThisDeviceFromCircle: + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, + SOSCCRemoveThisDeviceFromCircle_Server(&error)); + break; + case kSecXPCOpBailFromCircle: + { + uint64_t limit_in_seconds = xpc_dictionary_get_uint64(event, kSecXPCLimitInMinutes); + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, + SOSCCBailFromCircle_Server(limit_in_seconds, &error)); + } + break; + case kSecXPCOpAcceptApplicants: + { + xpc_object_t xapplicants = xpc_dictionary_get_value(event, kSecXPCKeyPeerInfos); + CFArrayRef applicants = CreateArrayOfPeerInfoWithXPCObject(xapplicants, &error); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants)); + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, + (applicants && SOSCCAcceptApplicants_Server(applicants, &error))); + CFReleaseSafe(applicants); + } + break; + case kSecXPCOpRejectApplicants: + { + xpc_object_t xapplicants = xpc_dictionary_get_value(event, kSecXPCKeyPeerInfos); + CFArrayRef applicants = CreateArrayOfPeerInfoWithXPCObject(xapplicants, &error); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants)); + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, + (applicants && SOSCCRejectApplicants_Server(applicants, &error))); + CFReleaseSafe(applicants); + } + break; + case kSecXPCOpCopyApplicantPeerInfo: + { + CFArrayRef array = SOSCCCopyApplicantPeerInfo_Server(&error); + if (array) { + xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error); + xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); + xpc_release(xpc_array); + } + CFReleaseNull(array); + } + break; + case kSecXPCOpCopyValidPeerPeerInfo: + { + CFArrayRef array = SOSCCCopyValidPeerPeerInfo_Server(&error); + if (array) { + xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error); + xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); + xpc_release(xpc_array); + } + CFReleaseNull(array); + } + break; + case kSecXPCOpValidateUserPublic: + { + bool trusted = SOSCCValidateUserPublic_Server(&error); + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, trusted); + } + break; + case kSecXPCOpCopyNotValidPeerPeerInfo: + { + CFArrayRef array = SOSCCCopyNotValidPeerPeerInfo_Server(&error); + if (array) { + xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error); + xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); + xpc_release(xpc_array); + } + CFReleaseNull(array); + } + break; + case kSecXPCOpCopyGenerationPeerInfo: + { + CFArrayRef array = SOSCCCopyGenerationPeerInfo_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); + } + break; + case kSecXPCOpCopyRetirementPeerInfo: + { + CFArrayRef array = SOSCCCopyRetirementPeerInfo_Server(&error); + if (array) { + xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error); + xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); + xpc_release(xpc_array); + } + CFReleaseNull(array); + } + break; + case kSecXPCOpCopyPeerPeerInfo: + { + CFArrayRef array = SOSCCCopyPeerPeerInfo_Server(&error); + if (array) { + xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error); + xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); + xpc_release(xpc_array); + } + CFReleaseNull(array); + } + break; + case kSecXPCOpCopyConcurringPeerPeerInfo: + { + CFArrayRef array = SOSCCCopyConcurringPeerPeerInfo_Server(&error); + if (array) { + xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error); + xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); + xpc_release(xpc_array); + } + CFReleaseNull(array); + } + break; + case kSecXPCOpGetLastDepartureReason: + xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, + SOSCCGetLastDepartureReason_Server(&error)); + break; + case kSecXPCOpProcessSyncWithAllPeers: + xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, + SOSCCProcessSyncWithAllPeers_Server(&error)); + break; + case soscc_EnsurePeerRegistration_id: + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, + SOSCCProcessEnsurePeerRegistration_Server(&error)); + break; + case kSecXPCOpCopyIncompatibilityInfo: { + CFStringRef iis = SOSCCCopyIncompatibilityInfo_Server(&error); + SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, iis, &error); + CFReleaseSafe(iis); + break; + } + case kSecXPCOpOTAGetEscrowCertificates: + { + uint32_t escrowRootType = (uint32_t)xpc_dictionary_get_uint64(event, "escrowType"); + CFArrayRef array = SecOTAPKICopyCurrentEscrowCertificates(escrowRootType, &error); + if (array) { + xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array); + xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); + xpc_release(xpc_array); + } + CFReleaseNull(array); + } + break; + case kSecXPCOpOTAPKIGetNewAsset: + xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, + SecOTAPKISignalNewAsset(&error)); + break; + case kSecXPCOpRollKeys: + { + bool force = xpc_dictionary_get_bool(event, "force"); + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, + _SecServerRollKeys(force, &error)); + } + break; + default: + break; + } + } + + if (error) + { + if(SecErrorGetOSStatus(error) == errSecItemNotFound || isSOSErrorCoded(error, kSOSErrorPublicKeyAbsent)) + secdebug("ipc", "%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error); + else + secerror("%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error); + + xpcError = SecCreateXPCObjectWithCFError(error); + xpc_dictionary_set_value(replyMessage, kSecXPCKeyError, xpcError); + } else if (replyMessage) { + secdebug("ipc", "%@ %@ responding %@", clientTask, 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); + xpcError = SecCreateXPCObjectWithCFError(error); + replyMessage = xpc_create_reply_with_format(event, "{%string: %value}", kSecXPCKeyError, xpcError); + } + + if (replyMessage) { + xpc_connection_send_message(connection, replyMessage); + xpc_release(replyMessage); + } + if (xpcError) + xpc_release(xpcError); + CFReleaseSafe(error); + CFReleaseSafe(accessGroups); + CFReleaseSafe(domains); + CFReleaseSafe(clientTask); +} + +static void securityd_xpc_init() +{ + secdebug("serverxpc", "start"); + + xpc_connection_t listener = xpc_connection_create_mach_service(kSecuritydXPCServiceName, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER); + if (!listener) { + seccritical("security failed to register xpc listener, exiting"); + abort(); + } + + xpc_connection_set_event_handler(listener, ^(xpc_object_t connection) { + if (xpc_get_type(connection) == XPC_TYPE_CONNECTION) { + xpc_connection_set_event_handler(connection, ^(xpc_object_t event) { + if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) { + xpc_retain(connection); + xpc_retain(event); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + securityd_xpc_dictionary_handler(connection, event); + xpc_release(event); + xpc_release(connection); + }); + } + }); + xpc_connection_resume(connection); + } + }); + xpc_connection_resume(listener); +} + +int main(int argc, char *argv[]) +{ + char *wait4debugger = getenv("WAIT4DEBUGGER"); + if (wait4debugger && !strcasecmp("YES", wait4debugger)) { + seccritical("SIGSTOPing self, awaiting debugger"); + kill(getpid(), SIGSTOP); + asl_log(NULL, NULL, ASL_LEVEL_CRIT, + "Again, for good luck (or bad debuggers)"); + kill(getpid(), SIGSTOP); + } + + securityd_init_server(); + securityd_xpc_init(); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (NSEC_PER_SEC * 10)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), + ^{ + InitializeCloudKeychainTracing(); + }); + dispatch_main(); + return 0; +} + +/* vi:set ts=4 sw=4 et: */ diff --git a/Security/sec/sec.xcodeproj/project.pbxproj b/Security/sec/sec.xcodeproj/project.pbxproj new file mode 100644 index 00000000..7a78c02a --- /dev/null +++ b/Security/sec/sec.xcodeproj/project.pbxproj @@ -0,0 +1,3010 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 0C062B1F175E784B00806CFE /* secd-30-keychain-upgrade.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C062B1C175E784B00806CFE /* secd-30-keychain-upgrade.c */; }; + 0C062B20175E784B00806CFE /* secd-31-keychain-bad.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C062B1D175E784B00806CFE /* secd-31-keychain-bad.c */; }; + 0C062B21175E784B00806CFE /* secd-31-keychain-unreadable.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C062B1E175E784B00806CFE /* secd-31-keychain-unreadable.c */; }; + 0C0BDB611756882A00BC1A7E /* secd_regressions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C0BDB601756882A00BC1A7E /* secd_regressions.h */; }; + 0C0BDB63175688DA00BC1A7E /* secd-01-items.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C0BDB62175688DA00BC1A7E /* secd-01-items.c */; }; + 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 */; }; + 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 */; }; + 18AD566714CB70A8008233F2 /* SecItem.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD563714CB6EB9008233F2 /* SecItem.c */; }; + 18D4043914CE1FE400A2BE4E /* p12import.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD561614CB6EB9008233F2 /* p12import.c */; }; + 18D4043A14CE1FE400A2BE4E /* p12pbegen.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD561814CB6EB9008233F2 /* p12pbegen.c */; }; + 18D4043B14CE1FE400A2BE4E /* pbkdf2.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD561A14CB6EB9008233F2 /* pbkdf2.c */; }; + 18D4043C14CE1FE400A2BE4E /* SecBase64.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD561D14CB6EB9008233F2 /* SecBase64.c */; }; + 18D4043D14CE1FE400A2BE4E /* SecCertificate.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD562014CB6EB9008233F2 /* SecCertificate.c */; }; + 18D4043E14CE1FE400A2BE4E /* SecCertificatePath.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD562314CB6EB9008233F2 /* SecCertificatePath.c */; }; + 18D4043F14CE1FE400A2BE4E /* SecCertificateRequest.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD562614CB6EB9008233F2 /* SecCertificateRequest.c */; }; + 18D4044014CE1FE400A2BE4E /* SecCMS.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD562814CB6EB9008233F2 /* SecCMS.c */; }; + 18D4044114CE1FE400A2BE4E /* SecDH.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD562A14CB6EB9008233F2 /* SecDH.c */; }; + 18D4044214CE1FE400A2BE4E /* SecECKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD562C14CB6EB9008233F2 /* SecECKey.c */; }; + 18D4044314CE1FE400A2BE4E /* SecFramework.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD562E14CB6EB9008233F2 /* SecFramework.c */; }; + 18D4044414CE1FE400A2BE4E /* SecIdentity.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD563114CB6EB9008233F2 /* SecIdentity.c */; }; + 18D4044514CE1FE400A2BE4E /* SecImportExport.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD563414CB6EB9008233F2 /* SecImportExport.c */; }; + 18D4044614CE1FE400A2BE4E /* SecItem.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD563714CB6EB9008233F2 /* SecItem.c */; }; + 18D4044714CE1FE400A2BE4E /* SecItemConstants.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD563914CB6EB9008233F2 /* SecItemConstants.c */; }; + 18D4044814CE1FE400A2BE4E /* SecKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD563C14CB6EB9008233F2 /* SecKey.c */; }; + 18D4044914CE1FE400A2BE4E /* SecPBKDF.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD564014CB6EB9008233F2 /* SecPBKDF.c */; }; + 18D4044A14CE1FE400A2BE4E /* SecPolicy.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD564214CB6EB9008233F2 /* SecPolicy.c */; }; + 18D4044B14CE1FE400A2BE4E /* SecRSAKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD564714CB6EB9008233F2 /* SecRSAKey.c */; }; + 18D4044C14CE1FE400A2BE4E /* SecSCEP.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD564A14CB6EB9008233F2 /* SecSCEP.c */; }; + 18D4044D14CE1FE400A2BE4E /* SecTrust.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD564C14CB6EB9008233F2 /* SecTrust.c */; }; + 18D4044E14CE1FE400A2BE4E /* SecTrustSettings.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD564F14CB6EB9008233F2 /* SecTrustSettings.c */; }; + 18D4044F14CE1FE400A2BE4E /* SecTrustStore.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD565214CB6EB9008233F2 /* SecTrustStore.c */; }; + 18D4045014CE1FE400A2BE4E /* vmdh.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD565514CB6EB9008233F2 /* vmdh.c */; }; + 18D4056614CE53DD00A2BE4E /* asynchttp.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD567D14CB865E008233F2 /* asynchttp.c */; }; + 18D4056814CE53DD00A2BE4E /* policytree.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD568214CB865E008233F2 /* policytree.c */; }; + 18D4056914CE53DD00A2BE4E /* SecCAIssuerCache.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD568414CB865E008233F2 /* SecCAIssuerCache.c */; }; + 18D4056A14CE53DD00A2BE4E /* SecCAIssuerRequest.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD568614CB865E008233F2 /* SecCAIssuerRequest.c */; }; + 18D4056B14CE53DD00A2BE4E /* SecItemServer.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD568814CB865E008233F2 /* SecItemServer.c */; }; + 18D4056C14CE53DD00A2BE4E /* SecOCSPCache.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD565914CB6F79008233F2 /* SecOCSPCache.c */; }; + 18D4056D14CE53DD00A2BE4E /* SecOCSPRequest.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD565B14CB6F79008233F2 /* SecOCSPRequest.c */; }; + 18D4056E14CE53DD00A2BE4E /* SecOCSPResponse.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD565D14CB6F79008233F2 /* SecOCSPResponse.c */; }; + 18D4056F14CE53DD00A2BE4E /* SecPolicyServer.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD565F14CB6F79008233F2 /* SecPolicyServer.c */; }; + 18D4057014CE53DD00A2BE4E /* SecTrustServer.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD566114CB6F79008233F2 /* SecTrustServer.c */; }; + 18D4057114CE53DD00A2BE4E /* SecTrustStoreServer.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD566314CB6F79008233F2 /* SecTrustStoreServer.c */; }; + 18D4057214CE547400A2BE4E /* spi.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD566514CB6F79008233F2 /* spi.c */; }; + 3A70988218CDF648009FD2CC /* si_77_SecAccessControl.c in Sources */ = {isa = PBXBuildFile; fileRef = 3A70988118CDF648009FD2CC /* si_77_SecAccessControl.c */; }; + 4406660F19069C67000DA171 /* si-80-empty-data.c in Sources */ = {isa = PBXBuildFile; fileRef = 4406660E19069707000DA171 /* si-80-empty-data.c */; }; + 446BB5E518F83172005D1B83 /* SecAccessControl.c in Sources */ = {isa = PBXBuildFile; fileRef = C6766767189884D200E9A12C /* SecAccessControl.c */; }; + 4477A8D918F28AB700B5BB9F /* si-78-query-attrs.c in Sources */ = {isa = PBXBuildFile; fileRef = 4477A8D718F28AAE00B5BB9F /* si-78-query-attrs.c */; }; + 4802A59616D711060059E5B9 /* SOSUserKeygen.c in Sources */ = {isa = PBXBuildFile; fileRef = 4802A59516D711060059E5B9 /* SOSUserKeygen.c */; }; + 4802A59816D7156D0059E5B9 /* SOSUserKeygen.h in Headers */ = {isa = PBXBuildFile; fileRef = 4802A59716D711190059E5B9 /* SOSUserKeygen.h */; settings = {ATTRIBUTES = (); }; }; + 486C6C691795F9D600387075 /* secd-61-account-leave-not-in-kansas-anymore.c in Sources */ = {isa = PBXBuildFile; fileRef = 486C6C671795F20E00387075 /* secd-61-account-leave-not-in-kansas-anymore.c */; }; + 48764AE817FA2DD00005C4F1 /* SOSAccountDer.c in Sources */ = {isa = PBXBuildFile; fileRef = 48764AE717FA2DD00005C4F1 /* SOSAccountDer.c */; }; + 48764AEC17FA31E50005C4F1 /* SOSAccountPersistence.c in Sources */ = {isa = PBXBuildFile; fileRef = 48764AEB17FA31E50005C4F1 /* SOSAccountPersistence.c */; }; + 48764AEF17FA36200005C4F1 /* SOSAccountUpdate.c in Sources */ = {isa = PBXBuildFile; fileRef = 48764AEE17FA36200005C4F1 /* SOSAccountUpdate.c */; }; + 48764AF217FA3ACF0005C4F1 /* SOSKVSKeys.c in Sources */ = {isa = PBXBuildFile; fileRef = 48764AF117FA3ACF0005C4F1 /* SOSKVSKeys.c */; }; + 48764AF517FA3FE50005C4F1 /* SOSAccountCircles.c in Sources */ = {isa = PBXBuildFile; fileRef = 48764AF417FA3FE50005C4F1 /* SOSAccountCircles.c */; }; + 4878267B19C0F518002CB56F /* sc-42-circlegencount.c in Sources */ = {isa = PBXBuildFile; fileRef = 4878267919C0F505002CB56F /* sc-42-circlegencount.c */; }; + 4882C517177521AE0095D04B /* secd-58-password-change.c in Sources */ = {isa = PBXBuildFile; fileRef = 4882C516177521AE0095D04B /* secd-58-password-change.c */; }; + 488902EC16C2F88400F119FF /* SOSCoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 488902EB16C2F88400F119FF /* SOSCoder.c */; }; + 4898223A17BDB277003BEF32 /* secd-52-account-changed.c in Sources */ = {isa = PBXBuildFile; fileRef = 4898223917BDB277003BEF32 /* secd-52-account-changed.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 */; }; + 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 */; }; + 48F32D7E1777AFA3001B84BA /* secd-59-account-cleanup.c in Sources */ = {isa = PBXBuildFile; fileRef = 48F32D7D1777AFA3001B84BA /* secd-59-account-cleanup.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 */; }; + 4A5CCA5715ACEFD400702357 /* SecOTRPacketData.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A97168B158FDEB800D439B7 /* SecOTRPacketData.c */; }; + 4A5CCA5815ACEFD400702357 /* SecOTRPackets.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A97168D158FDEB800D439B7 /* SecOTRPackets.c */; }; + 4A5CCA5915ACEFD400702357 /* SecOTRPublicIdentity.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A97168F158FDEB800D439B7 /* SecOTRPublicIdentity.c */; }; + 4A5CCA5A15ACEFD400702357 /* SecOTRSession.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971690158FDEB800D439B7 /* SecOTRSession.c */; }; + 4A5CCA5B15ACEFD400702357 /* SecOTRSessionAKE.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971692158FDEB800D439B7 /* SecOTRSessionAKE.c */; }; + 4A5CCA5C15ACEFD400702357 /* SecOTRUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971694158FDEB800D439B7 /* SecOTRUtils.c */; }; + 4A971695158FDEB800D439B7 /* SecOTR.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A971682158FDEB800D439B7 /* SecOTR.h */; }; + 4A971696158FDEB800D439B7 /* SecOTRDHKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971683158FDEB800D439B7 /* SecOTRDHKey.c */; }; + 4A971697158FDEB800D439B7 /* SecOTRDHKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A971684158FDEB800D439B7 /* SecOTRDHKey.h */; }; + 4A971698158FDEB800D439B7 /* SecOTRErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A971685158FDEB800D439B7 /* SecOTRErrors.h */; }; + 4A971699158FDEB800D439B7 /* SecOTRFullIdentity.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971686158FDEB800D439B7 /* SecOTRFullIdentity.c */; }; + 4A97169A158FDEB800D439B7 /* SecOTRIdentityPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A971687158FDEB800D439B7 /* SecOTRIdentityPriv.h */; }; + 4A97169B158FDEB800D439B7 /* SecOTRMath.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971688158FDEB800D439B7 /* SecOTRMath.c */; }; + 4A97169C158FDEB800D439B7 /* SecOTRMath.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A971689158FDEB800D439B7 /* SecOTRMath.h */; }; + 4A97169E158FDEB800D439B7 /* SecOTRPacketData.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A97168B158FDEB800D439B7 /* SecOTRPacketData.c */; }; + 4A97169F158FDEB800D439B7 /* SecOTRPacketData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A97168C158FDEB800D439B7 /* SecOTRPacketData.h */; }; + 4A9716A0158FDEB800D439B7 /* SecOTRPackets.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A97168D158FDEB800D439B7 /* SecOTRPackets.c */; }; + 4A9716A1158FDEB800D439B7 /* SecOTRPackets.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A97168E158FDEB800D439B7 /* SecOTRPackets.h */; }; + 4A9716A2158FDEB800D439B7 /* SecOTRPublicIdentity.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A97168F158FDEB800D439B7 /* SecOTRPublicIdentity.c */; }; + 4A9716A3158FDEB800D439B7 /* SecOTRSession.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971690158FDEB800D439B7 /* SecOTRSession.c */; }; + 4A9716A4158FDEB800D439B7 /* SecOTRSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A971691158FDEB800D439B7 /* SecOTRSession.h */; }; + 4A9716A5158FDEB800D439B7 /* SecOTRSessionAKE.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971692158FDEB800D439B7 /* SecOTRSessionAKE.c */; }; + 4A9716A6158FDEB800D439B7 /* SecOTRSessionPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A971693158FDEB800D439B7 /* SecOTRSessionPriv.h */; }; + 4A9716A7158FDEB800D439B7 /* SecOTRUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971694158FDEB800D439B7 /* SecOTRUtils.c */; }; + 4AD6F6F21651C86200DB4CE6 /* libSecureObjectSync.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E702E75614E1F3EA00CDE635 /* libSecureObjectSync.a */; }; + 4C055FF317B60F1E001A879A /* SecDbKeychainItem.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C055FED17B60F1E001A879A /* SecDbKeychainItem.c */; }; + 4C055FF417B60F1E001A879A /* SecDbQuery.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C055FEE17B60F1E001A879A /* SecDbQuery.c */; }; + 4C055FF517B60F1E001A879A /* SecItemDataSource.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C055FEF17B60F1E001A879A /* SecItemDataSource.c */; }; + 4C055FF617B60F1E001A879A /* SecItemDb.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C055FF017B60F1E001A879A /* SecItemDb.c */; }; + 4C055FF717B60F1E001A879A /* SecItemSchema.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C055FF117B60F1E001A879A /* SecItemSchema.c */; }; + 4C055FF817B60F1E001A879A /* SecKeybagSupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C055FF217B60F1E001A879A /* SecKeybagSupport.c */; }; + 4C05608A17B60F88001A879A /* SecDbKeychainItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C05608417B60F88001A879A /* SecDbKeychainItem.h */; }; + 4C05608B17B60F88001A879A /* SecDbQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C05608517B60F88001A879A /* SecDbQuery.h */; }; + 4C05608C17B60F88001A879A /* SecItemDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C05608617B60F88001A879A /* SecItemDataSource.h */; }; + 4C05608D17B60F88001A879A /* SecItemDb.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C05608717B60F88001A879A /* SecItemDb.h */; }; + 4C05608E17B60F88001A879A /* SecItemSchema.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C05608817B60F88001A879A /* SecItemSchema.h */; }; + 4C05608F17B60F88001A879A /* SecKeybagSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C05608917B60F88001A879A /* SecKeybagSupport.h */; }; + 4C2C8C3D17AB374700C24C13 /* si-12-item-stress.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2C8C3C17AB374700C24C13 /* si-12-item-stress.c */; }; + 4C3CE9E7176005A700B521C2 /* SecuritydXPC.c in Sources */ = {isa = PBXBuildFile; fileRef = E7B01B8816572579000485F1 /* SecuritydXPC.c */; }; + 4C3CE9E8176005B500B521C2 /* SecuritydXPC.c in Sources */ = {isa = PBXBuildFile; fileRef = E7B01B8816572579000485F1 /* SecuritydXPC.c */; }; + 4C495EDD1982125E00BC1809 /* SOSTestDevice.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C495EDB1982125E00BC1809 /* SOSTestDevice.c */; }; + 4C495EDE1982125E00BC1809 /* SOSTestDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C495EDC1982125E00BC1809 /* SOSTestDevice.h */; }; + 4C495EDF1982145200BC1809 /* SOSTestDevice.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C495EDB1982125E00BC1809 /* SOSTestDevice.c */; }; + 4C495EE21982171500BC1809 /* secd-70-engine-corrupt.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C495EE01982171500BC1809 /* secd-70-engine-corrupt.c */; }; + 4C4EBD541610D7D8007D06A5 /* sc-75-circle-engine.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C4EBD531610D7D8007D06A5 /* sc-75-circle-engine.c */; }; + 4C64F59717C6B3B1009C5AC2 /* sc-45-digestvector.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C64F59617C6B3B1009C5AC2 /* sc-45-digestvector.c */; }; + 4C65154B17B5A08900691B6A /* SOSDigestVector.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C8BDDA017B4FE8100C20EA5 /* SOSDigestVector.c */; }; + 4C6ED19515CB0E44004379B7 /* sc-70-engine.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6ED19415CB0E43004379B7 /* sc-70-engine.c */; }; + 4C6ED19615CB0E72004379B7 /* sc-30-peerinfo.c in Sources */ = {isa = PBXBuildFile; fileRef = E777C72815B9C9F0004044A8 /* sc-30-peerinfo.c */; }; + 4C6ED19715CB0E72004379B7 /* sc-60-peer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6ED19115CB0E26004379B7 /* sc-60-peer.c */; }; + 4C8322EB17B7E01E005B620A /* sc-50-message.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C8322EA17B7E01E005B620A /* sc-50-message.c */; }; + 4C8322EC17B7E01E005B620A /* sc-50-message.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C8322EA17B7E01E005B620A /* sc-50-message.c */; }; + 4C8940DB166EA8CF00241770 /* osxshim.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C8940DA166EA8CF00241770 /* osxshim.c */; }; + 4C8BDD9B17B4FB8F00C20EA5 /* SOSDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C8BDD9A17B4FB8F00C20EA5 /* SOSDataSource.h */; }; + 4C8BDD9D17B4FD2A00C20EA5 /* SOSManifest.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C8BDD9C17B4FD2A00C20EA5 /* SOSManifest.h */; }; + 4C8BDD9F17B4FDE100C20EA5 /* SOSManifest.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C8BDD9E17B4FDE100C20EA5 /* SOSManifest.c */; }; + 4C8BDDA217B4FE9400C20EA5 /* SOSDigestVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C8BDDA117B4FE9400C20EA5 /* SOSDigestVector.h */; }; + 4C8D8627177A71E80019A804 /* SOSCloudCircle.c in Sources */ = {isa = PBXBuildFile; fileRef = E7217B1715F80E0F00D26031 /* SOSCloudCircle.c */; }; + 4C8D8628177A71FB0019A804 /* SecPasswordGenerate.c in Sources */ = {isa = PBXBuildFile; fileRef = CDC765C01729A72800721712 /* SecPasswordGenerate.c */; }; + 4C9DC91A15B602760036D941 /* SOSEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9DC91915B602760036D941 /* SOSEngine.h */; settings = {ATTRIBUTES = (); }; }; + 4C9DC91D15B602910036D941 /* SOSEngine.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C9DC91C15B602910036D941 /* SOSEngine.c */; }; + 4CB8A83816164B7700B52EC7 /* SOSTestDataSource.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CB8A83716164B7700B52EC7 /* SOSTestDataSource.c */; }; + 4CBDB30D17B70206002FA799 /* SOSMessage.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CBDB30B17B70206002FA799 /* SOSMessage.c */; }; + 4CBDB30E17B70206002FA799 /* SOSMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CBDB30C17B70206002FA799 /* SOSMessage.h */; }; + 4CBDB30F17B70306002FA799 /* SOSCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 488902ED16C2F89700F119FF /* SOSCoder.h */; }; + 4CBDB31017B70323002FA799 /* SOSPeerInfoInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 485835871779013E0050F074 /* SOSPeerInfoInternal.h */; }; + 4CC07E26171E252300DCB6CE /* SOSCloudCircle.c in Sources */ = {isa = PBXBuildFile; fileRef = E7217B1715F80E0F00D26031 /* SOSCloudCircle.c */; }; + 4CC929B315A3957800C6D578 /* SOSAccount.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC929AD15A3957800C6D578 /* SOSAccount.c */; }; + 4CC929B415A3957800C6D578 /* SOSAccount.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC929AE15A3957800C6D578 /* SOSAccount.h */; settings = {ATTRIBUTES = (); }; }; + 4CC929B515A3957800C6D578 /* SOSCircle.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC929AF15A3957800C6D578 /* SOSCircle.c */; }; + 4CC929B615A3957800C6D578 /* SOSCircle.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC929B015A3957800C6D578 /* SOSCircle.h */; settings = {ATTRIBUTES = (); }; }; + 4CC929B715A3957800C6D578 /* SOSPeer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC929B115A3957800C6D578 /* SOSPeer.c */; }; + 4CC929B815A3957800C6D578 /* SOSPeer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC929B215A3957800C6D578 /* SOSPeer.h */; settings = {ATTRIBUTES = (); }; }; + 4CC92A5F15A3ABD400C6D578 /* pbkdf2-00-hmac-sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A0F15A3ABD400C6D578 /* pbkdf2-00-hmac-sha1.c */; }; + 4CC92A6015A3ABD400C6D578 /* spbkdf-00-hmac-sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1015A3ABD400C6D578 /* spbkdf-00-hmac-sha1.c */; }; + 4CC92A6115A3ABD400C6D578 /* otr-00-identity.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1215A3ABD400C6D578 /* otr-00-identity.c */; }; + 4CC92A6215A3ABD400C6D578 /* otr-30-negotiation.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1315A3ABD400C6D578 /* otr-30-negotiation.c */; }; + 4CC92A6315A3ABD400C6D578 /* otr-otrdh.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1415A3ABD400C6D578 /* otr-otrdh.c */; }; + 4CC92A6415A3ABD400C6D578 /* otr-packetdata.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1515A3ABD400C6D578 /* otr-packetdata.c */; }; + 4CC92A6515A3ABD400C6D578 /* si-00-find-nothing.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1715A3ABD400C6D578 /* si-00-find-nothing.c */; }; + 4CC92A6615A3ABD400C6D578 /* si-05-add.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1815A3ABD400C6D578 /* si-05-add.c */; }; + 4CC92A6715A3ABD400C6D578 /* si-10-find-internet.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1915A3ABD400C6D578 /* si-10-find-internet.c */; }; + 4CC92A6815A3ABD400C6D578 /* si-11-update-data.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1A15A3ABD400C6D578 /* si-11-update-data.c */; }; + 4CC92A6915A3ABD400C6D578 /* si-14-dateparse.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1B15A3ABD400C6D578 /* si-14-dateparse.c */; }; + 4CC92A6A15A3ABD400C6D578 /* si-15-certificate.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1C15A3ABD400C6D578 /* si-15-certificate.c */; }; + 4CC92A6B15A3ABD400C6D578 /* si-16-ec-certificate.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1D15A3ABD400C6D578 /* si-16-ec-certificate.c */; }; + 4CC92A6C15A3ABD400C6D578 /* si-20-sectrust-activation.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1E15A3ABD400C6D578 /* si-20-sectrust-activation.c */; }; + 4CC92A6D15A3ABD400C6D578 /* si-20-sectrust.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1F15A3ABD400C6D578 /* si-20-sectrust.c */; }; + 4CC92A6E15A3ABD400C6D578 /* si-21-sectrust-asr.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2015A3ABD400C6D578 /* si-21-sectrust-asr.c */; }; + 4CC92A6F15A3ABD400C6D578 /* si-22-sectrust-iap.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2115A3ABD400C6D578 /* si-22-sectrust-iap.c */; }; + 4CC92A7015A3ABD400C6D578 /* si-23-sectrust-ocsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2215A3ABD400C6D578 /* si-23-sectrust-ocsp.c */; }; + 4CC92A7115A3ABD400C6D578 /* si-24-sectrust-appleid.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2315A3ABD400C6D578 /* si-24-sectrust-appleid.c */; }; + 4CC92A7215A3ABD400C6D578 /* si-24-sectrust-digicert-malaysia.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2415A3ABD400C6D578 /* si-24-sectrust-digicert-malaysia.c */; }; + 4CC92A7315A3ABD400C6D578 /* si-24-sectrust-diginotar.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2515A3ABD400C6D578 /* si-24-sectrust-diginotar.c */; }; + 4CC92A7415A3ABD400C6D578 /* si-24-sectrust-itms.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2615A3ABD400C6D578 /* si-24-sectrust-itms.c */; }; + 4CC92A7515A3ABD400C6D578 /* si-24-sectrust-mobileasset.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2715A3ABD400C6D578 /* si-24-sectrust-mobileasset.c */; }; + 4CC92A7615A3ABD400C6D578 /* si-24-sectrust-nist.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2815A3ABD400C6D578 /* si-24-sectrust-nist.c */; }; + 4CC92A7715A3ABD400C6D578 /* si-24-sectrust-otatasking.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2915A3ABD400C6D578 /* si-24-sectrust-otatasking.c */; }; + 4CC92A7815A3ABD400C6D578 /* si-24-sectrust-shoebox.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2A15A3ABD400C6D578 /* si-24-sectrust-shoebox.c */; }; + 4CC92A7915A3ABD400C6D578 /* si-25-sectrust-ipsec-eap.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2B15A3ABD400C6D578 /* si-25-sectrust-ipsec-eap.c */; }; + 4CC92A7A15A3ABD400C6D578 /* si-26-applicationsigning.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2C15A3ABD400C6D578 /* si-26-applicationsigning.c */; }; + 4CC92A7B15A3ABD400C6D578 /* si-27-sectrust-exceptions.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2D15A3ABD400C6D578 /* si-27-sectrust-exceptions.c */; }; + 4CC92A7C15A3ABD400C6D578 /* si-28-sectrustsettings.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2E15A3ABD400C6D578 /* si-28-sectrustsettings.c */; }; + 4CC92A7D15A3ABD400C6D578 /* si-29-sectrust-codesigning.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2F15A3ABD400C6D578 /* si-29-sectrust-codesigning.c */; }; + 4CC92A7E15A3ABD400C6D578 /* si-30-keychain-upgrade.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3015A3ABD400C6D578 /* si-30-keychain-upgrade.c */; }; + 4CC92A7F15A3ABD400C6D578 /* si-31-keychain-bad.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3115A3ABD400C6D578 /* si-31-keychain-bad.c */; }; + 4CC92A8015A3ABD400C6D578 /* si-31-keychain-unreadable.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3215A3ABD400C6D578 /* si-31-keychain-unreadable.c */; }; + 4CC92A8215A3ABD400C6D578 /* si-33-keychain-backup.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3415A3ABD400C6D578 /* si-33-keychain-backup.c */; }; + 4CC92A8315A3ABD400C6D578 /* si-40-seckey-custom.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3515A3ABD400C6D578 /* si-40-seckey-custom.c */; }; + 4CC92A8415A3ABD400C6D578 /* si-40-seckey.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3615A3ABD400C6D578 /* si-40-seckey.c */; }; + 4CC92A8515A3ABD400C6D578 /* si-41-sececkey.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3715A3ABD400C6D578 /* si-41-sececkey.c */; }; + 4CC92A8615A3ABD400C6D578 /* si-42-identity.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3815A3ABD400C6D578 /* si-42-identity.c */; }; + 4CC92A8715A3ABD400C6D578 /* si-43-persistent.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3915A3ABD400C6D578 /* si-43-persistent.c */; }; + 4CC92A8815A3ABD400C6D578 /* si-50-secrandom.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3A15A3ABD400C6D578 /* si-50-secrandom.c */; }; + 4CC92A8915A3ABD400C6D578 /* si-60-cms.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3B15A3ABD400C6D578 /* si-60-cms.c */; }; + 4CC92A8A15A3ABD400C6D578 /* si-61-pkcs12.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3C15A3ABD400C6D578 /* si-61-pkcs12.c */; }; + 4CC92A8B15A3ABD400C6D578 /* si-62-csr.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3D15A3ABD400C6D578 /* si-62-csr.c */; }; + 4CC92A8C15A3ABD400C6D578 /* getcacert-mdes.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A3F15A3ABD400C6D578 /* getcacert-mdes.h */; }; + 4CC92A8D15A3ABD400C6D578 /* getcacert-mdesqa.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A4015A3ABD400C6D578 /* getcacert-mdesqa.h */; }; + 4CC92A8E15A3ABD400C6D578 /* si-63-scep.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A4115A3ABD400C6D578 /* si-63-scep.c */; }; + 4CC92A8F15A3ABD400C6D578 /* si-63-scep.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A4215A3ABD400C6D578 /* si-63-scep.h */; }; + 4CC92A9015A3ABD400C6D578 /* attached_no_data_signed_data.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A4415A3ABD400C6D578 /* attached_no_data_signed_data.h */; }; + 4CC92A9115A3ABD400C6D578 /* attached_signed_data.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A4515A3ABD400C6D578 /* attached_signed_data.h */; }; + 4CC92A9215A3ABD400C6D578 /* detached_content.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A4615A3ABD400C6D578 /* detached_content.h */; }; + 4CC92A9315A3ABD400C6D578 /* detached_signed_data.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A4715A3ABD400C6D578 /* detached_signed_data.h */; }; + 4CC92A9415A3ABD400C6D578 /* privkey.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A4815A3ABD400C6D578 /* privkey.h */; }; + 4CC92A9515A3ABD400C6D578 /* signer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A4915A3ABD400C6D578 /* signer.h */; }; + 4CC92A9615A3ABD400C6D578 /* si-64-ossl-cms.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A4A15A3ABD400C6D578 /* si-64-ossl-cms.c */; }; + 4CC92A9715A3ABD400C6D578 /* si-65-cms-cert-policy.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A4B15A3ABD400C6D578 /* si-65-cms-cert-policy.c */; }; + 4CC92A9815A3ABD400C6D578 /* signed-receipt.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A4D15A3ABD400C6D578 /* signed-receipt.h */; }; + 4CC92A9915A3ABD400C6D578 /* si-66-smime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A4E15A3ABD400C6D578 /* si-66-smime.c */; }; + 4CC92A9A15A3ABD400C6D578 /* Global Trustee.cer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A5015A3ABD400C6D578 /* Global Trustee.cer.h */; }; + 4CC92A9B15A3ABD400C6D578 /* UTN-USERFirst-Hardware.cer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A5115A3ABD400C6D578 /* UTN-USERFirst-Hardware.cer.h */; }; + 4CC92A9C15A3ABD400C6D578 /* addons.mozilla.org.cer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A5215A3ABD400C6D578 /* addons.mozilla.org.cer.h */; }; + 4CC92A9D15A3ABD400C6D578 /* login.live.com.cer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A5315A3ABD400C6D578 /* login.live.com.cer.h */; }; + 4CC92A9E15A3ABD400C6D578 /* login.skype.com.cer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A5415A3ABD400C6D578 /* login.skype.com.cer.h */; }; + 4CC92A9F15A3ABD400C6D578 /* login.yahoo.com.1.cer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A5515A3ABD400C6D578 /* login.yahoo.com.1.cer.h */; }; + 4CC92AA015A3ABD400C6D578 /* login.yahoo.com.2.cer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A5615A3ABD400C6D578 /* login.yahoo.com.2.cer.h */; }; + 4CC92AA115A3ABD400C6D578 /* login.yahoo.com.cer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A5715A3ABD400C6D578 /* login.yahoo.com.cer.h */; }; + 4CC92AA215A3ABD400C6D578 /* mail.google.com.cer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A5815A3ABD400C6D578 /* mail.google.com.cer.h */; }; + 4CC92AA315A3ABD400C6D578 /* www.google.com.cer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A5915A3ABD400C6D578 /* www.google.com.cer.h */; }; + 4CC92AA415A3ABD400C6D578 /* si-67-sectrust-blacklist.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A5A15A3ABD400C6D578 /* si-67-sectrust-blacklist.c */; }; + 4CC92AA515A3ABD400C6D578 /* vmdh-40.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A5C15A3ABD400C6D578 /* vmdh-40.c */; }; + 4CC92AA615A3ABD400C6D578 /* vmdh-41-example.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A5D15A3ABD400C6D578 /* vmdh-41-example.c */; }; + 4CC92AA715A3ABD400C6D578 /* vmdh-42-example2.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A5E15A3ABD400C6D578 /* vmdh-42-example2.c */; }; + 4CC92AC015A3BC4300C6D578 /* Security_regressions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92AB015A3AD0000C6D578 /* Security_regressions.h */; }; + 4CC92AF915A3BC6B00C6D578 /* sd-10-policytree.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92AAC15A3AC4600C6D578 /* sd-10-policytree.c */; }; + 4CC92B1515A3BCA500C6D578 /* securityd_regressions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92AAE15A3ACCE00C6D578 /* securityd_regressions.h */; }; + 4CD1897D169F835400BC96B8 /* print_cert.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CD1897B169F835400BC96B8 /* print_cert.c */; }; + 5214701B16977D7700DF0DB3 /* cloudkeychainproxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 521C0BB315FA5E3F00604B61 /* cloudkeychainproxy.m */; }; + 521C0A7615F908AF00604B61 /* sc-90-ckdclient.c in Sources */ = {isa = PBXBuildFile; fileRef = 521C0A7315F908A700604B61 /* sc-90-ckdclient.c */; }; + 521C0CD615FF9B3300604B61 /* SOSRegressionUtilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 521C0CD515FF9B3300604B61 /* SOSRegressionUtilities.c */; }; + 521C0CDD15FFA05100604B61 /* CKDKeyValueStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 521C0CD915FFA05000604B61 /* CKDKeyValueStore.h */; }; + 521C68601614A6E100E31C3E /* SOSCloudKeychainClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 521C685D1614A6E100E31C3E /* SOSCloudKeychainClient.h */; settings = {ATTRIBUTES = (); }; }; + 521C691F16164B9900E31C3E /* sc-95-ckd2client.c in Sources */ = {isa = PBXBuildFile; fileRef = 521C691E16164B9900E31C3E /* sc-95-ckd2client.c */; }; + 522B0ED21648809300A4675D /* sc-103-syncupdate.c in Sources */ = {isa = PBXBuildFile; fileRef = 522B0ED11648809300A4675D /* sc-103-syncupdate.c */; }; + 5253946116608F6800BA9687 /* sc-51-persistentEC.c in Sources */ = {isa = PBXBuildFile; fileRef = 5253946016608F6800BA9687 /* sc-51-persistentEC.c */; }; + 525394AE1660A30000BA9687 /* SecDbItem.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C4B15931655ED9000734590 /* SecDbItem.c */; }; + 527258D11981C00F003CFCEC /* secd-70-engine.c in Sources */ = {isa = PBXBuildFile; fileRef = 527258CF1981C00F003CFCEC /* secd-70-engine.c */; }; + 528402AE164446410035F320 /* CKDKVSProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 521C0BB015FA5E3F00604B61 /* CKDKVSProxy.m */; }; + 528402AF164446410035F320 /* CKDPersistentState.m in Sources */ = {isa = PBXBuildFile; fileRef = 521C0BB215FA5E3F00604B61 /* CKDPersistentState.m */; }; + 528402B1164446410035F320 /* CKDUserInteraction.m in Sources */ = {isa = PBXBuildFile; fileRef = 52840292164050C80035F320 /* CKDUserInteraction.m */; }; + 528402B2164447610035F320 /* SOSCloudKeychainConstants.c in Sources */ = {isa = PBXBuildFile; fileRef = E7217B2515F8131A00D26031 /* SOSCloudKeychainConstants.c */; }; + 52D0F028169CA72800F07D79 /* SecOnOSX.h in Headers */ = {isa = PBXBuildFile; fileRef = 52D0F026169CA72800F07D79 /* SecOnOSX.h */; }; + 52EAF4BE163C52EB00803D0F /* SOSCloudKeychainClient.c in Sources */ = {isa = PBXBuildFile; fileRef = 521C685C1614A6E100E31C3E /* SOSCloudKeychainClient.c */; }; + 5356520318E3C71000C383C0 /* SecOTRRemote.c in Sources */ = {isa = PBXBuildFile; fileRef = 5356520218E3C71000C383C0 /* SecOTRRemote.c */; }; + 5384299418E492A300E91AFE /* secd-70-otr-remote.c in Sources */ = {isa = PBXBuildFile; fileRef = 5384299318E492A300E91AFE /* secd-70-otr-remote.c */; }; + 5DE4A7BD17441CCD0036339E /* si-71-mobile-store-policy.c in Sources */ = {isa = PBXBuildFile; fileRef = 5DE4A7BC17441CCD0036339E /* si-71-mobile-store-policy.c */; }; + 5E9E159219642DC4001EB804 /* si-81-item-acl-stress.c in Sources */ = {isa = PBXBuildFile; fileRef = 5E9E1590196426C6001EB804 /* si-81-item-acl-stress.c */; }; + 7249E1CB16C01E5F003D7268 /* OTATrustUtilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E2DC0616BC47C800E7B236 /* OTATrustUtilities.c */; }; + 7255A46C1783333D006A8B9A /* si-74-OTAPKISigner.c in Sources */ = {isa = PBXBuildFile; fileRef = 7255A46B1783333D006A8B9A /* si-74-OTAPKISigner.c */; }; + 7255F91417A973D5004A9F38 /* si-75-AppleIDRecordSigning.c in Sources */ = {isa = PBXBuildFile; fileRef = 7255F91317A973D5004A9F38 /* si-75-AppleIDRecordSigning.c */; }; + 72B5923B17C6924000AE738B /* iCloudTrace.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B5923A17C6924000AE738B /* iCloudTrace.h */; }; + 72B5923D17C6939A00AE738B /* iCloudTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B5923C17C6939A00AE738B /* iCloudTrace.c */; }; + 7DE20930192D29D90066419C /* si-79-smp-cert-policy.c in Sources */ = {isa = PBXBuildFile; fileRef = 7DE2092F192D29D90066419C /* si-79-smp-cert-policy.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 */; }; + BE4AC9B518B8022D00B84964 /* swcagent_client.h in Headers */ = {isa = PBXBuildFile; fileRef = BEF9640918B418A400813FA3 /* swcagent_client.h */; }; + BE4AC9B618B8038400B84964 /* SecuritydXPC.c in Sources */ = {isa = PBXBuildFile; fileRef = E7B01B8816572579000485F1 /* SecuritydXPC.c */; }; + BE5EC1F018C80108005E7682 /* swcagent_client.c in Sources */ = {isa = PBXBuildFile; fileRef = BEF9640A18B418A400813FA3 /* swcagent_client.c */; }; + BE62D7601747FF3E001EAA9D /* si-72-syncableitems.c in Sources */ = {isa = PBXBuildFile; fileRef = BE62D75F1747FF3E001EAA9D /* si-72-syncableitems.c */; }; + BE62D7621747FF51001EAA9D /* si-70-sectrust-unified.c in Sources */ = {isa = PBXBuildFile; fileRef = BE62D7611747FF51001EAA9D /* si-70-sectrust-unified.c */; }; + BE642BB2188F32C200C899A2 /* SecSharedCredential.c in Sources */ = {isa = PBXBuildFile; fileRef = BE642BB1188F32C200C899A2 /* SecSharedCredential.c */; }; + BE794826196DBEAD00F4BA63 /* si-81-sectrust-server-auth.c in Sources */ = {isa = PBXBuildFile; fileRef = BE794825196DBEAD00F4BA63 /* si-81-sectrust-server-auth.c */; }; + 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 */; }; + CD09B90818A08EBE00E787E1 /* SOSTransportKeyParameter.c in Sources */ = {isa = PBXBuildFile; fileRef = CD09B90718A08EBE00E787E1 /* SOSTransportKeyParameter.c */; }; + CD09B90A18A08ECD00E787E1 /* SOSTransportKeyParameter.h in Headers */ = {isa = PBXBuildFile; fileRef = CD09B90918A08ECD00E787E1 /* SOSTransportKeyParameter.h */; }; + CD0F8AF218998685003E0C52 /* SOSKVSKeys.h in Headers */ = {isa = PBXBuildFile; fileRef = CD0F8AF118998685003E0C52 /* SOSKVSKeys.h */; }; + CD0F8AF41899BF33003E0C52 /* SOSTransportMessage.c in Sources */ = {isa = PBXBuildFile; fileRef = CD0F8AF31899BF33003E0C52 /* SOSTransportMessage.c */; }; + CD0F8AF61899BF46003E0C52 /* SOSTransportCircle.c in Sources */ = {isa = PBXBuildFile; fileRef = CD0F8AF51899BF46003E0C52 /* SOSTransportCircle.c */; }; + CD0F8AF81899BF57003E0C52 /* SOSTransportMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = CD0F8AF71899BF57003E0C52 /* SOSTransportMessage.h */; }; + CD0F8AFA1899BF63003E0C52 /* SOSTransportCircle.h in Headers */ = {isa = PBXBuildFile; fileRef = CD0F8AF91899BF63003E0C52 /* SOSTransportCircle.h */; }; + CD32776B18F8AEFD006B5280 /* SOSPeerCoder.c in Sources */ = {isa = PBXBuildFile; fileRef = CD32776A18F8AEFD006B5280 /* SOSPeerCoder.c */; }; + CD32776D18F8B06E006B5280 /* SOSPeerCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = CD32776C18F8B06E006B5280 /* SOSPeerCoder.h */; }; + CD32776F18F8B2FC006B5280 /* SOSTransportKeyParameterKVS.c in Sources */ = {isa = PBXBuildFile; fileRef = CD32776E18F8B2FC006B5280 /* SOSTransportKeyParameterKVS.c */; }; + CD32777118F8B30E006B5280 /* SOSTransportKeyParameterKVS.h in Headers */ = {isa = PBXBuildFile; fileRef = CD32777018F8B30E006B5280 /* SOSTransportKeyParameterKVS.h */; }; + CD32777318F8B31E006B5280 /* SOSTransportCircleKVS.c in Sources */ = {isa = PBXBuildFile; fileRef = CD32777218F8B31E006B5280 /* SOSTransportCircleKVS.c */; }; + CD32777518F8B330006B5280 /* SOSTransportCircleKVS.h in Headers */ = {isa = PBXBuildFile; fileRef = CD32777418F8B330006B5280 /* SOSTransportCircleKVS.h */; }; + CD32777718F8B39B006B5280 /* SOSTransportMessageKVS.c in Sources */ = {isa = PBXBuildFile; fileRef = CD32777618F8B39B006B5280 /* SOSTransportMessageKVS.c */; }; + CD32777918F8B3B4006B5280 /* SOSTransportMessageKVS.h in Headers */ = {isa = PBXBuildFile; fileRef = CD32777818F8B3B4006B5280 /* SOSTransportMessageKVS.h */; }; + CD3FD10716C3064B00A83BB6 /* SecuritydXPC.c in Sources */ = {isa = PBXBuildFile; fileRef = E7B01B8816572579000485F1 /* SecuritydXPC.c */; }; + CD86DE4E18BD554D00C90CDF /* SOSTransport.c in Sources */ = {isa = PBXBuildFile; fileRef = CD86DE4D18BD554D00C90CDF /* SOSTransport.c */; }; + CD95312B19228D8D005A76B2 /* SOSTransportTestTransports.c in Sources */ = {isa = PBXBuildFile; fileRef = CDAD4E9818EC8424007D4BC2 /* SOSTransportTestTransports.c */; }; + CD95312C19228D92005A76B2 /* SOSTransportTestTransports.h in Headers */ = {isa = PBXBuildFile; fileRef = CDAD4E9A18EC8447007D4BC2 /* SOSTransportTestTransports.h */; }; + CD95312D19228D96005A76B2 /* SOSAccountTesting.h in Headers */ = {isa = PBXBuildFile; fileRef = E7A10FAA1771245D00C4602F /* SOSAccountTesting.h */; }; + CDAD4E9C18EC9B3D007D4BC2 /* SOSAccountTesting.h in Headers */ = {isa = PBXBuildFile; fileRef = E7A10FAA1771245D00C4602F /* SOSAccountTesting.h */; }; + CDAD4E9D18EC9B67007D4BC2 /* SOSTransportTestTransports.c in Sources */ = {isa = PBXBuildFile; fileRef = CDAD4E9818EC8424007D4BC2 /* SOSTransportTestTransports.c */; }; + CDAD4E9E18EC9B6D007D4BC2 /* SOSTransportTestTransports.h in Headers */ = {isa = PBXBuildFile; fileRef = CDAD4E9A18EC8447007D4BC2 /* SOSTransportTestTransports.h */; }; + CDC765C21729A72800721712 /* SecPasswordGenerate.c in Sources */ = {isa = PBXBuildFile; fileRef = CDC765C01729A72800721712 /* SecPasswordGenerate.c */; }; + CDC765C41729A72800721712 /* SecPasswordGenerate.h in Headers */ = {isa = PBXBuildFile; fileRef = CDC765C11729A72800721712 /* SecPasswordGenerate.h */; }; + CDD565A2173193AC00B6B074 /* si-73-secpasswordgenerate.c in Sources */ = {isa = PBXBuildFile; fileRef = CDD565A1173193AC00B6B074 /* si-73-secpasswordgenerate.c */; }; + CDF1B82318BD7DDE006309BC /* SOSTransport.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF1B82218BD7DDE006309BC /* SOSTransport.h */; }; + E703811514E1FEEF007CB458 /* SOSCloudCircle.h in Headers */ = {isa = PBXBuildFile; fileRef = E703811114E1FEE4007CB458 /* SOSCloudCircle.h */; }; + E71049F3169E023B00DB0045 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 521C0B9815FA5C4A00604B61 /* Foundation.framework */; }; + E7104A01169E036E00DB0045 /* SecurityTool.c in Sources */ = {isa = PBXBuildFile; fileRef = E71049FF169E036E00DB0045 /* SecurityTool.c */; }; + E7104A18169E216E00DB0045 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 521C0B9815FA5C4A00604B61 /* Foundation.framework */; }; + E7217B2715F8131A00D26031 /* SOSCloudKeychainConstants.c in Sources */ = {isa = PBXBuildFile; fileRef = E7217B2515F8131A00D26031 /* SOSCloudKeychainConstants.c */; }; + E7217B2815F8131A00D26031 /* SOSCloudKeychainConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = E7217B2615F8131A00D26031 /* SOSCloudKeychainConstants.h */; settings = {ATTRIBUTES = (); }; }; + E748744515A61AF800624935 /* si-68-secmatchissuer.c in Sources */ = {isa = PBXBuildFile; fileRef = E748744415A61AF800624935 /* si-68-secmatchissuer.c */; }; + E76079C11951FD2800F69731 /* SecLogging.c in Sources */ = {isa = PBXBuildFile; fileRef = E795C94119116EA200FA068C /* SecLogging.c */; }; + E763D6231624E2670038477D /* sc-20-keynames.c in Sources */ = {isa = PBXBuildFile; fileRef = E763D6221624E2670038477D /* sc-20-keynames.c */; }; + E777C6B115B4DDF2004044A8 /* sc-40-circle.c in Sources */ = {isa = PBXBuildFile; fileRef = E777C6B015B4DDF2004044A8 /* sc-40-circle.c */; }; + E777C71C15B73F59004044A8 /* SOSInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = E777C71B15B73F59004044A8 /* SOSInternal.h */; settings = {ATTRIBUTES = (); }; }; + 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 */; settings = {ATTRIBUTES = (); }; }; + E790C10A169E4FD200E0C0C9 /* digest_calc.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C109169E4FD200E0C0C9 /* digest_calc.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 */; }; + E790C143169E5C6200E0C0C9 /* keychain_add.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C138169E5C6200E0C0C9 /* keychain_add.c */; }; + E790C144169E5C6200E0C0C9 /* keychain_find.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C139169E5C6200E0C0C9 /* keychain_find.c */; }; + E790C145169E5C6200E0C0C9 /* pkcs12_util.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C13A169E5C6200E0C0C9 /* pkcs12_util.c */; }; + E790C147169E5C6200E0C0C9 /* scep.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C13D169E5C6200E0C0C9 /* scep.c */; }; + E790C148169E5C6200E0C0C9 /* show_certificates.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C13F169E5C6200E0C0C9 /* show_certificates.c */; }; + E790C149169E5C6200E0C0C9 /* spc.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C140169E5C6200E0C0C9 /* spc.c */; }; + E79277E3163B110A0096F3E2 /* SOSFullPeerInfo.c in Sources */ = {isa = PBXBuildFile; fileRef = E79277E1163B110A0096F3E2 /* SOSFullPeerInfo.c */; }; + E79277E4163B110A0096F3E2 /* SOSFullPeerInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = E79277E2163B110A0096F3E2 /* SOSFullPeerInfo.h */; settings = {ATTRIBUTES = (); }; }; + E795C94019100F6100FA068C /* log_control.c in Sources */ = {isa = PBXBuildFile; fileRef = E795C93E19100F5000FA068C /* log_control.c */; }; + E795C9481911A41300FA068C /* SecLogSettingsServer.c in Sources */ = {isa = PBXBuildFile; fileRef = E795C9471911A41200FA068C /* SecLogSettingsServer.c */; }; + E795C9541913F88D00FA068C /* SecServerEncryptionSupport.c in Sources */ = {isa = PBXBuildFile; fileRef = E795C9531913F88D00FA068C /* SecServerEncryptionSupport.c */; }; + E79D62BB176798FD005A9743 /* secd-50-account.c in Sources */ = {isa = PBXBuildFile; fileRef = E79D62B9176798BF005A9743 /* secd-50-account.c */; }; + E79D62BC176799DB005A9743 /* SOSRegressionUtilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 521C0CD515FF9B3300604B61 /* SOSRegressionUtilities.c */; }; + E79D62BD176799EE005A9743 /* SOSTestDataSource.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CB8A83716164B7700B52EC7 /* SOSTestDataSource.c */; }; + E79D62C01767A5BC005A9743 /* SecdTestKeychainUtilities.c in Sources */ = {isa = PBXBuildFile; fileRef = E79D62BE1767A547005A9743 /* SecdTestKeychainUtilities.c */; }; + E7A10FAC1771246A00C4602F /* secd-55-account-circle.c in Sources */ = {isa = PBXBuildFile; fileRef = E7A10FAB1771246A00C4602F /* secd-55-account-circle.c */; }; + E7A10FAE1771249C00C4602F /* secd-57-account-leave.c in Sources */ = {isa = PBXBuildFile; fileRef = E7A10FAD1771249C00C4602F /* secd-57-account-leave.c */; }; + E7A634E317FA471500920B67 /* SOSPeerInfoCollections.c in Sources */ = {isa = PBXBuildFile; fileRef = E7A634E217FA471500920B67 /* SOSPeerInfoCollections.c */; }; + E7B01B5B16532507000485F1 /* SOSCloudCircleInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = E7B01B5A16532507000485F1 /* SOSCloudCircleInternal.h */; settings = {ATTRIBUTES = (); }; }; + E7B01B691655DF20000485F1 /* SOSCloudCircleServer.c in Sources */ = {isa = PBXBuildFile; fileRef = E7B01B671655CCA6000485F1 /* SOSCloudCircleServer.c */; }; + E7BE10A7167AB32300D2A178 /* sc-41-cloudcircle.c in Sources */ = {isa = PBXBuildFile; fileRef = E7BE10A5167AB2BF00D2A178 /* sc-41-cloudcircle.c */; }; + E7CA197A17179EC20065299C /* si-69-keydesc.c in Sources */ = {isa = PBXBuildFile; fileRef = CDA7729616B899F10069434D /* si-69-keydesc.c */; }; + E7EBD75819145DF000D0F062 /* so_01_serverencryption.c in Sources */ = {isa = PBXBuildFile; fileRef = E7EBD75619145D6400D0F062 /* so_01_serverencryption.c */; }; + E7F0D3EA177BBE35001ACBC1 /* secd-55-account-incompatibility.c in Sources */ = {isa = PBXBuildFile; fileRef = E7F0D3E9177BBE35001ACBC1 /* secd-55-account-incompatibility.c */; }; + E7F18555177A44E000177B23 /* secd-60-account-cloud-identity.c in Sources */ = {isa = PBXBuildFile; fileRef = E7F18554177A44E000177B23 /* secd-60-account-cloud-identity.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 */; }; + EBDAECBC184D32BD005A18F1 /* sc-31-peerinfo-simplefuzz.c in Sources */ = {isa = PBXBuildFile; fileRef = EBDAECBA184D30C3005A18F1 /* sc-31-peerinfo-simplefuzz.c */; }; + F697632318F6CFD60090438B /* keychain_util.c in Sources */ = {isa = PBXBuildFile; fileRef = F697632118F6CC3F0090438B /* keychain_util.c */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 5284029E164445760035F320 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/${PRODUCT_NAME}"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E71049F0169E023B00DB0045 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/${PRODUCT_NAME}"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E7104A19169E216E00DB0045 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/${PRODUCT_NAME}"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E7FEFB88169E363300E18152 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/${PRODUCT_NAME}"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0C062B1C175E784B00806CFE /* secd-30-keychain-upgrade.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-30-keychain-upgrade.c"; sourceTree = ""; }; + 0C062B1D175E784B00806CFE /* secd-31-keychain-bad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-31-keychain-bad.c"; sourceTree = ""; }; + 0C062B1E175E784B00806CFE /* secd-31-keychain-unreadable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-31-keychain-unreadable.c"; sourceTree = ""; }; + 0C0BDB5F175687EC00BC1A7E /* libsecdRegressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecdRegressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 0C0BDB601756882A00BC1A7E /* secd_regressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = secd_regressions.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 0C0BDB62175688DA00BC1A7E /* secd-01-items.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-01-items.c"; sourceTree = ""; }; + 0C664AE7175951270092D3D9 /* secd-02-upgrade-while-locked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = "secd-02-upgrade-while-locked.c"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.c; }; + 0CBF93F5177B7CFC001E5658 /* secd-03-corrupted-items.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-03-corrupted-items.c"; sourceTree = ""; }; + 0CBF93F6177B7CFC001E5658 /* secd-04-corrupted-items.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-04-corrupted-items.c"; sourceTree = ""; }; + 0CBF93FB177BA9D9001E5658 /* secd-05-corrupted-items.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-05-corrupted-items.c"; sourceTree = ""; }; + 0CE7ABDE171383E30088968F /* keychain_backup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keychain_backup.c; sourceTree = ""; }; + 18270C9714CF1AAD00B05E7F /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; + 18270C9814CF1AAD00B05E7F /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 18270C9914CF1AAD00B05E7F /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; + 18270C9A14CF1AAD00B05E7F /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 18270F5514CF651900B05E7F /* libsecipc_client.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecipc_client.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 186CDD0F14CA116C00AF9171 /* libSecItemShimOSX.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSecItemShimOSX.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 18AD560614CB6E7A008233F2 /* client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = client.c; sourceTree = ""; }; + 18AD560714CB6E7A008233F2 /* com.apple.securityd.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.securityd.plist; sourceTree = ""; }; + 18AD560814CB6E7A008233F2 /* securityd_client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = securityd_client.h; sourceTree = ""; }; + 18AD560D14CB6E7A008233F2 /* server.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = server.c; sourceTree = ""; }; + 18AD561514CB6EB9008233F2 /* certextensions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = certextensions.h; sourceTree = ""; }; + 18AD561614CB6EB9008233F2 /* p12import.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = p12import.c; sourceTree = ""; }; + 18AD561714CB6EB9008233F2 /* p12import.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = p12import.h; sourceTree = ""; }; + 18AD561814CB6EB9008233F2 /* p12pbegen.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = p12pbegen.c; sourceTree = ""; }; + 18AD561914CB6EB9008233F2 /* p12pbegen.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = p12pbegen.h; sourceTree = ""; }; + 18AD561A14CB6EB9008233F2 /* pbkdf2.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = pbkdf2.c; sourceTree = ""; }; + 18AD561B14CB6EB9008233F2 /* pbkdf2.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = pbkdf2.h; sourceTree = ""; }; + 18AD561C14CB6EB9008233F2 /* SecBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecBase.h; sourceTree = ""; }; + 18AD561D14CB6EB9008233F2 /* SecBase64.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecBase64.c; sourceTree = ""; }; + 18AD561E14CB6EB9008233F2 /* SecBase64.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecBase64.h; sourceTree = ""; }; + 18AD561F14CB6EB9008233F2 /* SecBasePriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecBasePriv.h; sourceTree = ""; }; + 18AD562014CB6EB9008233F2 /* SecCertificate.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecCertificate.c; sourceTree = ""; }; + 18AD562114CB6EB9008233F2 /* SecCertificate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecCertificate.h; sourceTree = ""; }; + 18AD562214CB6EB9008233F2 /* SecCertificateInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecCertificateInternal.h; sourceTree = ""; }; + 18AD562314CB6EB9008233F2 /* SecCertificatePath.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecCertificatePath.c; sourceTree = ""; }; + 18AD562414CB6EB9008233F2 /* SecCertificatePath.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecCertificatePath.h; sourceTree = ""; }; + 18AD562514CB6EB9008233F2 /* SecCertificatePriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecCertificatePriv.h; sourceTree = ""; }; + 18AD562614CB6EB9008233F2 /* SecCertificateRequest.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecCertificateRequest.c; sourceTree = ""; }; + 18AD562714CB6EB9008233F2 /* SecCertificateRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecCertificateRequest.h; sourceTree = ""; }; + 18AD562814CB6EB9008233F2 /* SecCMS.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecCMS.c; sourceTree = ""; }; + 18AD562914CB6EB9008233F2 /* SecCMS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecCMS.h; sourceTree = ""; }; + 18AD562A14CB6EB9008233F2 /* SecDH.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecDH.c; sourceTree = ""; }; + 18AD562B14CB6EB9008233F2 /* SecDH.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecDH.h; sourceTree = ""; }; + 18AD562C14CB6EB9008233F2 /* SecECKey.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecECKey.c; sourceTree = ""; }; + 18AD562D14CB6EB9008233F2 /* SecECKey.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecECKey.h; sourceTree = ""; }; + 18AD562E14CB6EB9008233F2 /* SecFramework.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecFramework.c; sourceTree = ""; }; + 18AD562F14CB6EB9008233F2 /* SecFramework.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecFramework.h; sourceTree = ""; }; + 18AD563014CB6EB9008233F2 /* SecFrameworkStrings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecFrameworkStrings.h; sourceTree = ""; }; + 18AD563114CB6EB9008233F2 /* SecIdentity.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecIdentity.c; sourceTree = ""; }; + 18AD563214CB6EB9008233F2 /* SecIdentity.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecIdentity.h; sourceTree = ""; }; + 18AD563314CB6EB9008233F2 /* SecIdentityPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecIdentityPriv.h; sourceTree = ""; }; + 18AD563414CB6EB9008233F2 /* SecImportExport.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecImportExport.c; sourceTree = ""; }; + 18AD563514CB6EB9008233F2 /* SecImportExport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecImportExport.h; sourceTree = ""; }; + 18AD563614CB6EB9008233F2 /* SecInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecInternal.h; sourceTree = ""; }; + 18AD563714CB6EB9008233F2 /* SecItem.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecItem.c; sourceTree = ""; }; + 18AD563814CB6EB9008233F2 /* SecItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecItem.h; sourceTree = ""; }; + 18AD563914CB6EB9008233F2 /* SecItemConstants.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecItemConstants.c; sourceTree = ""; }; + 18AD563A14CB6EB9008233F2 /* SecItemInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecItemInternal.h; sourceTree = ""; }; + 18AD563B14CB6EB9008233F2 /* SecItemPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecItemPriv.h; sourceTree = ""; }; + 18AD563C14CB6EB9008233F2 /* SecKey.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecKey.c; sourceTree = ""; }; + 18AD563D14CB6EB9008233F2 /* SecKey.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecKey.h; sourceTree = ""; }; + 18AD563E14CB6EB9008233F2 /* SecKeyInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecKeyInternal.h; sourceTree = ""; }; + 18AD563F14CB6EB9008233F2 /* SecKeyPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecKeyPriv.h; sourceTree = ""; }; + 18AD564014CB6EB9008233F2 /* SecPBKDF.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecPBKDF.c; sourceTree = ""; }; + 18AD564114CB6EB9008233F2 /* SecPBKDF.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecPBKDF.h; sourceTree = ""; }; + 18AD564214CB6EB9008233F2 /* SecPolicy.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecPolicy.c; sourceTree = ""; }; + 18AD564314CB6EB9008233F2 /* SecPolicy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecPolicy.h; sourceTree = ""; }; + 18AD564414CB6EB9008233F2 /* SecPolicyInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecPolicyInternal.h; sourceTree = ""; }; + 18AD564514CB6EB9008233F2 /* SecPolicyPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecPolicyPriv.h; sourceTree = ""; }; + 18AD564614CB6EB9008233F2 /* SecRandom.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecRandom.h; sourceTree = ""; }; + 18AD564714CB6EB9008233F2 /* SecRSAKey.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecRSAKey.c; sourceTree = ""; }; + 18AD564814CB6EB9008233F2 /* SecRSAKey.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecRSAKey.h; sourceTree = ""; }; + 18AD564914CB6EB9008233F2 /* SecRSAKeyPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecRSAKeyPriv.h; sourceTree = ""; }; + 18AD564A14CB6EB9008233F2 /* SecSCEP.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecSCEP.c; sourceTree = ""; }; + 18AD564B14CB6EB9008233F2 /* SecSCEP.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecSCEP.h; sourceTree = ""; }; + 18AD564C14CB6EB9008233F2 /* SecTrust.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecTrust.c; sourceTree = ""; }; + 18AD564D14CB6EB9008233F2 /* SecTrust.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecTrust.h; sourceTree = ""; }; + 18AD564E14CB6EB9008233F2 /* SecTrustPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecTrustPriv.h; sourceTree = ""; }; + 18AD564F14CB6EB9008233F2 /* SecTrustSettings.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecTrustSettings.c; sourceTree = ""; }; + 18AD565014CB6EB9008233F2 /* SecTrustSettings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecTrustSettings.h; sourceTree = ""; }; + 18AD565114CB6EB9008233F2 /* SecTrustSettingsPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecTrustSettingsPriv.h; sourceTree = ""; }; + 18AD565214CB6EB9008233F2 /* SecTrustStore.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecTrustStore.c; sourceTree = ""; }; + 18AD565314CB6EB9008233F2 /* SecTrustStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecTrustStore.h; sourceTree = ""; }; + 18AD565414CB6EB9008233F2 /* Security.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Security.h; sourceTree = ""; }; + 18AD565514CB6EB9008233F2 /* vmdh.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = vmdh.c; sourceTree = ""; }; + 18AD565614CB6EB9008233F2 /* vmdh.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = vmdh.h; sourceTree = ""; }; + 18AD565814CB6F79008233F2 /* SecItemServer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecItemServer.h; sourceTree = ""; }; + 18AD565914CB6F79008233F2 /* SecOCSPCache.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecOCSPCache.c; sourceTree = ""; }; + 18AD565A14CB6F79008233F2 /* SecOCSPCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecOCSPCache.h; sourceTree = ""; }; + 18AD565B14CB6F79008233F2 /* SecOCSPRequest.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecOCSPRequest.c; sourceTree = ""; }; + 18AD565C14CB6F79008233F2 /* SecOCSPRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecOCSPRequest.h; sourceTree = ""; }; + 18AD565D14CB6F79008233F2 /* SecOCSPResponse.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecOCSPResponse.c; sourceTree = ""; }; + 18AD565E14CB6F79008233F2 /* SecOCSPResponse.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecOCSPResponse.h; sourceTree = ""; }; + 18AD565F14CB6F79008233F2 /* SecPolicyServer.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecPolicyServer.c; sourceTree = ""; }; + 18AD566014CB6F79008233F2 /* SecPolicyServer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecPolicyServer.h; sourceTree = ""; }; + 18AD566114CB6F79008233F2 /* SecTrustServer.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecTrustServer.c; sourceTree = ""; }; + 18AD566214CB6F79008233F2 /* SecTrustServer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecTrustServer.h; sourceTree = ""; }; + 18AD566314CB6F79008233F2 /* SecTrustStoreServer.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecTrustStoreServer.c; sourceTree = ""; }; + 18AD566414CB6F79008233F2 /* SecTrustStoreServer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecTrustStoreServer.h; sourceTree = ""; }; + 18AD566514CB6F79008233F2 /* spi.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = spi.c; sourceTree = ""; }; + 18AD566614CB6F79008233F2 /* spi.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = spi.h; sourceTree = ""; }; + 18AD567D14CB865E008233F2 /* asynchttp.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = asynchttp.c; sourceTree = ""; }; + 18AD567E14CB865E008233F2 /* asynchttp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = asynchttp.h; sourceTree = ""; }; + 18AD567F14CB865E008233F2 /* entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = ""; }; + 18AD568214CB865E008233F2 /* policytree.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = policytree.c; sourceTree = ""; }; + 18AD568314CB865E008233F2 /* policytree.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = policytree.h; sourceTree = ""; }; + 18AD568414CB865E008233F2 /* SecCAIssuerCache.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecCAIssuerCache.c; sourceTree = ""; }; + 18AD568514CB865E008233F2 /* SecCAIssuerCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecCAIssuerCache.h; sourceTree = ""; }; + 18AD568614CB865E008233F2 /* SecCAIssuerRequest.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecCAIssuerRequest.c; sourceTree = ""; }; + 18AD568714CB865E008233F2 /* SecCAIssuerRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecCAIssuerRequest.h; sourceTree = ""; }; + 18AD568814CB865E008233F2 /* SecItemServer.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = SecItemServer.c; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.c; }; + 18D4043514CE0CF300A2BE4E /* libsecurity.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurity.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 18D4056214CE53C200A2BE4E /* libsecurityd.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurityd.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 3A70988118CDF648009FD2CC /* si_77_SecAccessControl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = si_77_SecAccessControl.c; sourceTree = ""; }; + 4406660E19069707000DA171 /* si-80-empty-data.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "si-80-empty-data.c"; sourceTree = ""; }; + 4477A8D718F28AAE00B5BB9F /* si-78-query-attrs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-78-query-attrs.c"; sourceTree = ""; }; + 44B2606C18F82631008DF20F /* SecAccessControlExports.exp-in */ = {isa = PBXFileReference; lastKnownFileType = text; path = "SecAccessControlExports.exp-in"; sourceTree = ""; }; + 4802A59516D711060059E5B9 /* SOSUserKeygen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSUserKeygen.c; sourceTree = ""; }; + 4802A59716D711190059E5B9 /* SOSUserKeygen.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSUserKeygen.h; sourceTree = ""; }; + 485835871779013E0050F074 /* SOSPeerInfoInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSPeerInfoInternal.h; sourceTree = ""; }; + 486C6C671795F20E00387075 /* secd-61-account-leave-not-in-kansas-anymore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-61-account-leave-not-in-kansas-anymore.c"; sourceTree = ""; }; + 48764AE717FA2DD00005C4F1 /* SOSAccountDer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccountDer.c; sourceTree = ""; }; + 48764AEA17FA31670005C4F1 /* SOSAccountPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSAccountPriv.h; sourceTree = ""; }; + 48764AEB17FA31E50005C4F1 /* SOSAccountPersistence.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccountPersistence.c; sourceTree = ""; }; + 48764AEE17FA36200005C4F1 /* SOSAccountUpdate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccountUpdate.c; sourceTree = ""; }; + 48764AF117FA3ACF0005C4F1 /* SOSKVSKeys.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSKVSKeys.c; sourceTree = ""; }; + 48764AF417FA3FE50005C4F1 /* SOSAccountCircles.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccountCircles.c; sourceTree = ""; }; + 4878267919C0F505002CB56F /* sc-42-circlegencount.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-42-circlegencount.c"; sourceTree = ""; }; + 4882C516177521AE0095D04B /* secd-58-password-change.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-58-password-change.c"; sourceTree = ""; }; + 488902EB16C2F88400F119FF /* SOSCoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSCoder.c; sourceTree = ""; }; + 488902ED16C2F89700F119FF /* SOSCoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSCoder.h; sourceTree = ""; }; + 4898223917BDB277003BEF32 /* secd-52-account-changed.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-52-account-changed.c"; sourceTree = ""; }; + 48C7DF9217FF2DB500904F1A /* SOSAccountCredentials.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccountCredentials.c; sourceTree = ""; }; + 48C7DF9517FF351A00904F1A /* SOSAccountPeers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccountPeers.c; sourceTree = ""; }; + 48C7DF9717FF360F00904F1A /* SOSAccountFullPeerInfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccountFullPeerInfo.c; sourceTree = ""; }; + 48C7DF9917FF44EF00904F1A /* SOSAccountCloudParameters.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccountCloudParameters.c; sourceTree = ""; }; + 48CE733D1731C49A004C2946 /* sc-130-resignationticket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-130-resignationticket.c"; sourceTree = ""; }; + 48E928C4179DD05500A7F755 /* secd-51-account-inflate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-51-account-inflate.c"; sourceTree = ""; }; + 48F32D7D1777AFA3001B84BA /* secd-59-account-cleanup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-59-account-cleanup.c"; sourceTree = ""; }; + 4A5CCA4F15ACEFA500702357 /* libSecOtrOSX.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSecOtrOSX.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 4A824B03158FF07000F932C0 /* libSecurityRegressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSecurityRegressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 4A971682158FDEB800D439B7 /* SecOTR.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOTR.h; sourceTree = ""; }; + 4A971683158FDEB800D439B7 /* SecOTRDHKey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SecOTRDHKey.c; path = ../../../SecOTRDHKey.c; sourceTree = ""; }; + 4A971684158FDEB800D439B7 /* SecOTRDHKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOTRDHKey.h; sourceTree = ""; }; + 4A971685158FDEB800D439B7 /* SecOTRErrors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOTRErrors.h; sourceTree = ""; }; + 4A971686158FDEB800D439B7 /* SecOTRFullIdentity.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecOTRFullIdentity.c; sourceTree = ""; }; + 4A971687158FDEB800D439B7 /* SecOTRIdentityPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOTRIdentityPriv.h; sourceTree = ""; }; + 4A971688158FDEB800D439B7 /* SecOTRMath.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecOTRMath.c; sourceTree = ""; }; + 4A971689158FDEB800D439B7 /* SecOTRMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOTRMath.h; sourceTree = ""; }; + 4A97168B158FDEB800D439B7 /* SecOTRPacketData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecOTRPacketData.c; sourceTree = ""; }; + 4A97168C158FDEB800D439B7 /* SecOTRPacketData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOTRPacketData.h; sourceTree = ""; }; + 4A97168D158FDEB800D439B7 /* SecOTRPackets.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecOTRPackets.c; sourceTree = ""; }; + 4A97168E158FDEB800D439B7 /* SecOTRPackets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOTRPackets.h; sourceTree = ""; }; + 4A97168F158FDEB800D439B7 /* SecOTRPublicIdentity.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecOTRPublicIdentity.c; sourceTree = ""; }; + 4A971690158FDEB800D439B7 /* SecOTRSession.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecOTRSession.c; sourceTree = ""; }; + 4A971691158FDEB800D439B7 /* SecOTRSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOTRSession.h; sourceTree = ""; }; + 4A971692158FDEB800D439B7 /* SecOTRSessionAKE.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecOTRSessionAKE.c; sourceTree = ""; }; + 4A971693158FDEB800D439B7 /* SecOTRSessionPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOTRSessionPriv.h; sourceTree = ""; }; + 4A971694158FDEB800D439B7 /* SecOTRUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecOTRUtils.c; sourceTree = ""; }; + 4C055FED17B60F1E001A879A /* SecDbKeychainItem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecDbKeychainItem.c; sourceTree = ""; }; + 4C055FEE17B60F1E001A879A /* SecDbQuery.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecDbQuery.c; sourceTree = ""; }; + 4C055FEF17B60F1E001A879A /* SecItemDataSource.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecItemDataSource.c; sourceTree = ""; }; + 4C055FF017B60F1E001A879A /* SecItemDb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecItemDb.c; sourceTree = ""; }; + 4C055FF117B60F1E001A879A /* SecItemSchema.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecItemSchema.c; sourceTree = ""; }; + 4C055FF217B60F1E001A879A /* SecKeybagSupport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecKeybagSupport.c; sourceTree = ""; }; + 4C05608417B60F88001A879A /* SecDbKeychainItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecDbKeychainItem.h; sourceTree = ""; }; + 4C05608517B60F88001A879A /* SecDbQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecDbQuery.h; sourceTree = ""; }; + 4C05608617B60F88001A879A /* SecItemDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecItemDataSource.h; sourceTree = ""; }; + 4C05608717B60F88001A879A /* SecItemDb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecItemDb.h; sourceTree = ""; }; + 4C05608817B60F88001A879A /* SecItemSchema.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecItemSchema.h; sourceTree = ""; }; + 4C05608917B60F88001A879A /* SecKeybagSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecKeybagSupport.h; sourceTree = ""; }; + 4C2C8C3C17AB374700C24C13 /* si-12-item-stress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-12-item-stress.c"; sourceTree = ""; }; + 4C495EDB1982125E00BC1809 /* SOSTestDevice.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSTestDevice.c; sourceTree = ""; }; + 4C495EDC1982125E00BC1809 /* SOSTestDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTestDevice.h; sourceTree = ""; }; + 4C495EE01982171500BC1809 /* secd-70-engine-corrupt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-70-engine-corrupt.c"; sourceTree = ""; }; + 4C4B15931655ED9000734590 /* SecDbItem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecDbItem.c; sourceTree = ""; }; + 4C4B15951655EDA700734590 /* SecDbItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecDbItem.h; sourceTree = ""; }; + 4C4EBD531610D7D8007D06A5 /* sc-75-circle-engine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-75-circle-engine.c"; sourceTree = ""; }; + 4C5EA365164C791400A136B8 /* lib-arc-only.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "lib-arc-only.xcconfig"; sourceTree = ""; }; + 4C64F59617C6B3B1009C5AC2 /* sc-45-digestvector.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-45-digestvector.c"; sourceTree = ""; }; + 4C6ED19115CB0E26004379B7 /* sc-60-peer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-60-peer.c"; sourceTree = ""; }; + 4C6ED19415CB0E43004379B7 /* sc-70-engine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-70-engine.c"; sourceTree = ""; }; + 4C8322EA17B7E01E005B620A /* sc-50-message.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-50-message.c"; sourceTree = ""; }; + 4C8940DA166EA8CF00241770 /* osxshim.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = osxshim.c; sourceTree = ""; }; + 4C8BDD9A17B4FB8F00C20EA5 /* SOSDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSDataSource.h; sourceTree = ""; }; + 4C8BDD9C17B4FD2A00C20EA5 /* SOSManifest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSManifest.h; sourceTree = ""; }; + 4C8BDD9E17B4FDE100C20EA5 /* SOSManifest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSManifest.c; sourceTree = ""; }; + 4C8BDDA017B4FE8100C20EA5 /* SOSDigestVector.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SOSDigestVector.c; sourceTree = ""; }; + 4C8BDDA117B4FE9400C20EA5 /* SOSDigestVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSDigestVector.h; sourceTree = ""; }; + 4C9DC91915B602760036D941 /* SOSEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSEngine.h; sourceTree = ""; }; + 4C9DC91C15B602910036D941 /* SOSEngine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSEngine.c; sourceTree = ""; }; + 4CB8A83716164B7700B52EC7 /* SOSTestDataSource.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSTestDataSource.c; sourceTree = ""; }; + 4CB8A83916164B8C00B52EC7 /* SOSTestDataSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSTestDataSource.h; sourceTree = ""; }; + 4CBDB30B17B70206002FA799 /* SOSMessage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSMessage.c; sourceTree = ""; }; + 4CBDB30C17B70206002FA799 /* SOSMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSMessage.h; sourceTree = ""; }; + 4CC929AD15A3957800C6D578 /* SOSAccount.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccount.c; sourceTree = ""; }; + 4CC929AE15A3957800C6D578 /* SOSAccount.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSAccount.h; sourceTree = ""; }; + 4CC929AF15A3957800C6D578 /* SOSCircle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSCircle.c; sourceTree = ""; }; + 4CC929B015A3957800C6D578 /* SOSCircle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSCircle.h; sourceTree = ""; }; + 4CC929B115A3957800C6D578 /* SOSPeer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSPeer.c; sourceTree = ""; }; + 4CC929B215A3957800C6D578 /* SOSPeer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSPeer.h; sourceTree = ""; }; + 4CC92A0F15A3ABD400C6D578 /* pbkdf2-00-hmac-sha1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "pbkdf2-00-hmac-sha1.c"; sourceTree = ""; }; + 4CC92A1015A3ABD400C6D578 /* spbkdf-00-hmac-sha1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "spbkdf-00-hmac-sha1.c"; sourceTree = ""; }; + 4CC92A1215A3ABD400C6D578 /* otr-00-identity.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "otr-00-identity.c"; sourceTree = ""; }; + 4CC92A1315A3ABD400C6D578 /* otr-30-negotiation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "otr-30-negotiation.c"; sourceTree = ""; }; + 4CC92A1415A3ABD400C6D578 /* otr-otrdh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "otr-otrdh.c"; sourceTree = ""; }; + 4CC92A1515A3ABD400C6D578 /* otr-packetdata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "otr-packetdata.c"; sourceTree = ""; }; + 4CC92A1715A3ABD400C6D578 /* si-00-find-nothing.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-00-find-nothing.c"; sourceTree = ""; }; + 4CC92A1815A3ABD400C6D578 /* si-05-add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-05-add.c"; sourceTree = ""; }; + 4CC92A1915A3ABD400C6D578 /* si-10-find-internet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-10-find-internet.c"; sourceTree = ""; }; + 4CC92A1A15A3ABD400C6D578 /* si-11-update-data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-11-update-data.c"; sourceTree = ""; }; + 4CC92A1B15A3ABD400C6D578 /* si-14-dateparse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-14-dateparse.c"; sourceTree = ""; }; + 4CC92A1C15A3ABD400C6D578 /* si-15-certificate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-15-certificate.c"; sourceTree = ""; }; + 4CC92A1D15A3ABD400C6D578 /* si-16-ec-certificate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-16-ec-certificate.c"; sourceTree = ""; }; + 4CC92A1E15A3ABD400C6D578 /* si-20-sectrust-activation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-20-sectrust-activation.c"; sourceTree = ""; }; + 4CC92A1F15A3ABD400C6D578 /* si-20-sectrust.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-20-sectrust.c"; sourceTree = ""; }; + 4CC92A2015A3ABD400C6D578 /* si-21-sectrust-asr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-21-sectrust-asr.c"; sourceTree = ""; }; + 4CC92A2115A3ABD400C6D578 /* si-22-sectrust-iap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-22-sectrust-iap.c"; sourceTree = ""; }; + 4CC92A2215A3ABD400C6D578 /* si-23-sectrust-ocsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-23-sectrust-ocsp.c"; sourceTree = ""; }; + 4CC92A2315A3ABD400C6D578 /* si-24-sectrust-appleid.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-appleid.c"; sourceTree = ""; }; + 4CC92A2415A3ABD400C6D578 /* si-24-sectrust-digicert-malaysia.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-digicert-malaysia.c"; sourceTree = ""; }; + 4CC92A2515A3ABD400C6D578 /* si-24-sectrust-diginotar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-diginotar.c"; sourceTree = ""; }; + 4CC92A2615A3ABD400C6D578 /* si-24-sectrust-itms.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-itms.c"; sourceTree = ""; }; + 4CC92A2715A3ABD400C6D578 /* si-24-sectrust-mobileasset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-mobileasset.c"; sourceTree = ""; }; + 4CC92A2815A3ABD400C6D578 /* si-24-sectrust-nist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-nist.c"; sourceTree = ""; }; + 4CC92A2915A3ABD400C6D578 /* si-24-sectrust-otatasking.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-otatasking.c"; sourceTree = ""; }; + 4CC92A2A15A3ABD400C6D578 /* si-24-sectrust-shoebox.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-shoebox.c"; sourceTree = ""; }; + 4CC92A2B15A3ABD400C6D578 /* si-25-sectrust-ipsec-eap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-25-sectrust-ipsec-eap.c"; sourceTree = ""; }; + 4CC92A2C15A3ABD400C6D578 /* si-26-applicationsigning.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-26-applicationsigning.c"; sourceTree = ""; }; + 4CC92A2D15A3ABD400C6D578 /* si-27-sectrust-exceptions.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-27-sectrust-exceptions.c"; sourceTree = ""; }; + 4CC92A2E15A3ABD400C6D578 /* si-28-sectrustsettings.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-28-sectrustsettings.c"; sourceTree = ""; }; + 4CC92A2F15A3ABD400C6D578 /* si-29-sectrust-codesigning.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-29-sectrust-codesigning.c"; sourceTree = ""; }; + 4CC92A3015A3ABD400C6D578 /* si-30-keychain-upgrade.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-30-keychain-upgrade.c"; sourceTree = ""; }; + 4CC92A3115A3ABD400C6D578 /* si-31-keychain-bad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-31-keychain-bad.c"; sourceTree = ""; }; + 4CC92A3215A3ABD400C6D578 /* si-31-keychain-unreadable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-31-keychain-unreadable.c"; sourceTree = ""; }; + 4CC92A3415A3ABD400C6D578 /* si-33-keychain-backup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-33-keychain-backup.c"; sourceTree = ""; }; + 4CC92A3515A3ABD400C6D578 /* si-40-seckey-custom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-40-seckey-custom.c"; sourceTree = ""; }; + 4CC92A3615A3ABD400C6D578 /* si-40-seckey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-40-seckey.c"; sourceTree = ""; }; + 4CC92A3715A3ABD400C6D578 /* si-41-sececkey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-41-sececkey.c"; sourceTree = ""; }; + 4CC92A3815A3ABD400C6D578 /* si-42-identity.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-42-identity.c"; sourceTree = ""; }; + 4CC92A3915A3ABD400C6D578 /* si-43-persistent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-43-persistent.c"; sourceTree = ""; }; + 4CC92A3A15A3ABD400C6D578 /* si-50-secrandom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-50-secrandom.c"; sourceTree = ""; }; + 4CC92A3B15A3ABD400C6D578 /* si-60-cms.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-60-cms.c"; sourceTree = ""; }; + 4CC92A3C15A3ABD400C6D578 /* si-61-pkcs12.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-61-pkcs12.c"; sourceTree = ""; }; + 4CC92A3D15A3ABD400C6D578 /* si-62-csr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-62-csr.c"; sourceTree = ""; }; + 4CC92A3F15A3ABD400C6D578 /* getcacert-mdes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "getcacert-mdes.h"; sourceTree = ""; }; + 4CC92A4015A3ABD400C6D578 /* getcacert-mdesqa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "getcacert-mdesqa.h"; sourceTree = ""; }; + 4CC92A4115A3ABD400C6D578 /* si-63-scep.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-63-scep.c"; sourceTree = ""; }; + 4CC92A4215A3ABD400C6D578 /* si-63-scep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "si-63-scep.h"; sourceTree = ""; }; + 4CC92A4415A3ABD400C6D578 /* attached_no_data_signed_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = attached_no_data_signed_data.h; sourceTree = ""; }; + 4CC92A4515A3ABD400C6D578 /* attached_signed_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = attached_signed_data.h; sourceTree = ""; }; + 4CC92A4615A3ABD400C6D578 /* detached_content.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = detached_content.h; sourceTree = ""; }; + 4CC92A4715A3ABD400C6D578 /* detached_signed_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = detached_signed_data.h; sourceTree = ""; }; + 4CC92A4815A3ABD400C6D578 /* privkey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = privkey.h; sourceTree = ""; }; + 4CC92A4915A3ABD400C6D578 /* signer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = signer.h; sourceTree = ""; }; + 4CC92A4A15A3ABD400C6D578 /* si-64-ossl-cms.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-64-ossl-cms.c"; sourceTree = ""; }; + 4CC92A4B15A3ABD400C6D578 /* si-65-cms-cert-policy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-65-cms-cert-policy.c"; sourceTree = ""; }; + 4CC92A4D15A3ABD400C6D578 /* signed-receipt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "signed-receipt.h"; sourceTree = ""; }; + 4CC92A4E15A3ABD400C6D578 /* si-66-smime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-66-smime.c"; sourceTree = ""; }; + 4CC92A5015A3ABD400C6D578 /* Global Trustee.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Global Trustee.cer.h"; sourceTree = ""; }; + 4CC92A5115A3ABD400C6D578 /* UTN-USERFirst-Hardware.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UTN-USERFirst-Hardware.cer.h"; sourceTree = ""; }; + 4CC92A5215A3ABD400C6D578 /* addons.mozilla.org.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = addons.mozilla.org.cer.h; sourceTree = ""; }; + 4CC92A5315A3ABD400C6D578 /* login.live.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.live.com.cer.h; sourceTree = ""; }; + 4CC92A5415A3ABD400C6D578 /* login.skype.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.skype.com.cer.h; sourceTree = ""; }; + 4CC92A5515A3ABD400C6D578 /* login.yahoo.com.1.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.yahoo.com.1.cer.h; sourceTree = ""; }; + 4CC92A5615A3ABD400C6D578 /* login.yahoo.com.2.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.yahoo.com.2.cer.h; sourceTree = ""; }; + 4CC92A5715A3ABD400C6D578 /* login.yahoo.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.yahoo.com.cer.h; sourceTree = ""; }; + 4CC92A5815A3ABD400C6D578 /* mail.google.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mail.google.com.cer.h; sourceTree = ""; }; + 4CC92A5915A3ABD400C6D578 /* www.google.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = www.google.com.cer.h; sourceTree = ""; }; + 4CC92A5A15A3ABD400C6D578 /* si-67-sectrust-blacklist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-67-sectrust-blacklist.c"; sourceTree = ""; }; + 4CC92A5C15A3ABD400C6D578 /* vmdh-40.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "vmdh-40.c"; sourceTree = ""; }; + 4CC92A5D15A3ABD400C6D578 /* vmdh-41-example.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "vmdh-41-example.c"; sourceTree = ""; }; + 4CC92A5E15A3ABD400C6D578 /* vmdh-42-example2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "vmdh-42-example2.c"; sourceTree = ""; }; + 4CC92AAC15A3AC4600C6D578 /* sd-10-policytree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sd-10-policytree.c"; sourceTree = ""; }; + 4CC92AAE15A3ACCE00C6D578 /* securityd_regressions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = securityd_regressions.h; sourceTree = ""; }; + 4CC92AAF15A3ACE600C6D578 /* SOSCircle_regressions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSCircle_regressions.h; sourceTree = ""; }; + 4CC92AB015A3AD0000C6D578 /* Security_regressions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Security_regressions.h; path = Regressions/Security_regressions.h; sourceTree = ""; }; + 4CC92B1415A3BC6B00C6D578 /* libsecuritydRegressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecuritydRegressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CD1897B169F835400BC96B8 /* print_cert.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = print_cert.c; sourceTree = ""; }; + 4CD1897C169F835400BC96B8 /* print_cert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = print_cert.h; sourceTree = ""; }; + 521C0A7315F908A700604B61 /* sc-90-ckdclient.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-90-ckdclient.c"; sourceTree = ""; }; + 521C0B9815FA5C4A00604B61 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 521C0BA615FA5D7400604B61 /* cloudkeychain.entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = cloudkeychain.entitlements.plist; path = SOSCircle/CloudKeychainProxy/cloudkeychain.entitlements.plist; sourceTree = SOURCE_ROOT; }; + 521C0BAD15FA5DA800604B61 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = InfoPlist.strings; sourceTree = ""; }; + 521C0BAF15FA5E3F00604B61 /* CKDKVSProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = CKDKVSProxy.h; path = SOSCircle/CloudKeychainProxy/CKDKVSProxy.h; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 521C0BB015FA5E3F00604B61 /* CKDKVSProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CKDKVSProxy.m; path = SOSCircle/CloudKeychainProxy/CKDKVSProxy.m; sourceTree = SOURCE_ROOT; }; + 521C0BB115FA5E3F00604B61 /* CKDPersistentState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CKDPersistentState.h; path = SOSCircle/CloudKeychainProxy/CKDPersistentState.h; sourceTree = SOURCE_ROOT; }; + 521C0BB215FA5E3F00604B61 /* CKDPersistentState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CKDPersistentState.m; path = SOSCircle/CloudKeychainProxy/CKDPersistentState.m; sourceTree = SOURCE_ROOT; }; + 521C0BB315FA5E3F00604B61 /* cloudkeychainproxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = cloudkeychainproxy.m; path = SOSCircle/CloudKeychainProxy/cloudkeychainproxy.m; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 521C0CD515FF9B3300604B61 /* SOSRegressionUtilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSRegressionUtilities.c; sourceTree = ""; }; + 521C0CD815FF9B4B00604B61 /* SOSRegressionUtilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSRegressionUtilities.h; sourceTree = ""; }; + 521C0CD915FFA05000604B61 /* CKDKeyValueStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = CKDKeyValueStore.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 521C0CDA15FFA05000604B61 /* CKDKeyValueStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKDKeyValueStore.m; sourceTree = ""; }; + 521C685C1614A6E100E31C3E /* SOSCloudKeychainClient.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = SOSCloudKeychainClient.c; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.c; }; + 521C685D1614A6E100E31C3E /* SOSCloudKeychainClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = SOSCloudKeychainClient.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 521C691E16164B9900E31C3E /* sc-95-ckd2client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-95-ckd2client.c"; sourceTree = ""; }; + 522B0ED11648809300A4675D /* sc-103-syncupdate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-103-syncupdate.c"; sourceTree = ""; }; + 522B0ED31649A68E00A4675D /* MobileKeyBag.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileKeyBag.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.Internal.sdk/System/Library/PrivateFrameworks/MobileKeyBag.framework; sourceTree = DEVELOPER_DIR; }; + 5253946016608F6800BA9687 /* sc-51-persistentEC.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-51-persistentEC.c"; sourceTree = ""; }; + 526CBA5116079FB4008DF7C8 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = "../../build/Products/Debug-iphoneos/Security.framework"; sourceTree = ""; }; + 5272501916838BB20029AADD /* CloudKeychainProxy.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = CloudKeychainProxy.1; sourceTree = ""; }; + 527258CF1981C00F003CFCEC /* secd-70-engine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-70-engine.c"; sourceTree = ""; }; + 52840291164050C80035F320 /* CKDUserInteraction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CKDUserInteraction.h; path = SOSCircle/CloudKeychainProxy/CKDUserInteraction.h; sourceTree = SOURCE_ROOT; }; + 52840292164050C80035F320 /* CKDUserInteraction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CKDUserInteraction.m; path = SOSCircle/CloudKeychainProxy/CKDUserInteraction.m; sourceTree = SOURCE_ROOT; }; + 528402A0164445760035F320 /* libCloudKeychainProxy.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCloudKeychainProxy.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 52849FC2164498C9005CDF23 /* SOSARCDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSARCDefines.h; path = SOSCircle/SOSARCDefines.h; sourceTree = SOURCE_ROOT; }; + 52C3D18E169A53150091D9D3 /* ckdmain.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ckdmain.m; path = SOSCircle/CloudKeychainProxy/ckdmain.m; sourceTree = SOURCE_ROOT; }; + 52D0F026169CA72800F07D79 /* SecOnOSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOnOSX.h; sourceTree = ""; }; + 52DD7069160CD40B0027A346 /* libutilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libutilities.a; path = ../../build/Release/libutilities.a; sourceTree = ""; }; + 5356520218E3C71000C383C0 /* SecOTRRemote.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecOTRRemote.c; sourceTree = ""; }; + 5356520418E3C88D00C383C0 /* SecOTRRemote.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecOTRRemote.h; sourceTree = ""; }; + 5384299318E492A300E91AFE /* secd-70-otr-remote.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-70-otr-remote.c"; sourceTree = ""; }; + 5DE4A7BC17441CCD0036339E /* si-71-mobile-store-policy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-71-mobile-store-policy.c"; sourceTree = ""; }; + 5E9E1590196426C6001EB804 /* si-81-item-acl-stress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-81-item-acl-stress.c"; sourceTree = ""; }; + 724D7363177A13A500FA10A1 /* AppleBaselineEscrowCertificates.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppleBaselineEscrowCertificates.h; sourceTree = ""; }; + 7255A46B1783333D006A8B9A /* si-74-OTAPKISigner.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-74-OTAPKISigner.c"; sourceTree = ""; }; + 7255F91317A973D5004A9F38 /* si-75-AppleIDRecordSigning.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-75-AppleIDRecordSigning.c"; sourceTree = ""; }; + 72B5923A17C6924000AE738B /* iCloudTrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iCloudTrace.h; sourceTree = ""; }; + 72B5923C17C6939A00AE738B /* iCloudTrace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iCloudTrace.c; sourceTree = ""; }; + 72E2DC0616BC47C800E7B236 /* OTATrustUtilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = OTATrustUtilities.c; sourceTree = ""; }; + 72E2DC0716BC47C800E7B236 /* OTATrustUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OTATrustUtilities.h; sourceTree = ""; }; + 7DE2092F192D29D90066419C /* si-79-smp-cert-policy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-79-smp-cert-policy.c"; sourceTree = ""; }; + ACFD56BD19007B2D00F5F5D9 /* ios6_1_keychain_2_db.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ios6_1_keychain_2_db.h; sourceTree = ""; }; + BE061FCE1899E5BD00C739F6 /* si-76-shared-credentials.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-76-shared-credentials.c"; sourceTree = ""; }; + BE556A5D19550E1600E6EE8C /* SecPolicyCerts.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecPolicyCerts.h; sourceTree = ""; }; + BE62D75F1747FF3E001EAA9D /* si-72-syncableitems.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-72-syncableitems.c"; sourceTree = ""; }; + BE62D7611747FF51001EAA9D /* si-70-sectrust-unified.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-70-sectrust-unified.c"; sourceTree = ""; }; + BE642BAF188F32AD00C899A2 /* SecSharedCredential.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecSharedCredential.h; sourceTree = ""; }; + BE642BB1188F32C200C899A2 /* SecSharedCredential.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecSharedCredential.c; sourceTree = ""; }; + BE794825196DBEAD00F4BA63 /* si-81-sectrust-server-auth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-81-sectrust-server-auth.c"; sourceTree = ""; }; + BEF9640618B4171200813FA3 /* libSWCAgent.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSWCAgent.a; sourceTree = BUILT_PRODUCTS_DIR; }; + BEF9640918B418A400813FA3 /* swcagent_client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = swcagent_client.h; path = SharedWebCredential/swcagent_client.h; sourceTree = ""; }; + BEF9640A18B418A400813FA3 /* swcagent_client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = swcagent_client.c; path = SharedWebCredential/swcagent_client.c; sourceTree = ""; }; + BEF9640B18B418A400813FA3 /* swcagent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = swcagent.m; path = SharedWebCredential/swcagent.m; sourceTree = ""; }; + C62A296818996D90006C3A11 /* SecAccessControlPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecAccessControlPriv.h; sourceTree = ""; }; + C6766767189884D200E9A12C /* SecAccessControl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecAccessControl.c; sourceTree = ""; }; + C6EE78BA189821AD009B8FEB /* SecAccessControl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecAccessControl.h; sourceTree = ""; }; + CD09B90718A08EBE00E787E1 /* SOSTransportKeyParameter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSTransportKeyParameter.c; sourceTree = ""; }; + CD09B90918A08ECD00E787E1 /* SOSTransportKeyParameter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransportKeyParameter.h; sourceTree = ""; }; + CD0F8AF118998685003E0C52 /* SOSKVSKeys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSKVSKeys.h; sourceTree = ""; }; + CD0F8AF31899BF33003E0C52 /* SOSTransportMessage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSTransportMessage.c; sourceTree = ""; }; + CD0F8AF51899BF46003E0C52 /* SOSTransportCircle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSTransportCircle.c; sourceTree = ""; }; + CD0F8AF71899BF57003E0C52 /* SOSTransportMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransportMessage.h; sourceTree = ""; }; + CD0F8AF91899BF63003E0C52 /* SOSTransportCircle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransportCircle.h; sourceTree = ""; }; + CD32776A18F8AEFD006B5280 /* SOSPeerCoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSPeerCoder.c; sourceTree = ""; }; + CD32776C18F8B06E006B5280 /* SOSPeerCoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSPeerCoder.h; sourceTree = ""; }; + CD32776E18F8B2FC006B5280 /* SOSTransportKeyParameterKVS.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSTransportKeyParameterKVS.c; sourceTree = ""; }; + CD32777018F8B30E006B5280 /* SOSTransportKeyParameterKVS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransportKeyParameterKVS.h; sourceTree = ""; }; + CD32777218F8B31E006B5280 /* SOSTransportCircleKVS.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSTransportCircleKVS.c; sourceTree = ""; }; + CD32777418F8B330006B5280 /* SOSTransportCircleKVS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransportCircleKVS.h; sourceTree = ""; }; + CD32777618F8B39B006B5280 /* SOSTransportMessageKVS.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSTransportMessageKVS.c; sourceTree = ""; }; + CD32777818F8B3B4006B5280 /* SOSTransportMessageKVS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransportMessageKVS.h; sourceTree = ""; }; + CD86DE4D18BD554D00C90CDF /* SOSTransport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSTransport.c; sourceTree = ""; }; + CDA7729616B899F10069434D /* si-69-keydesc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-69-keydesc.c"; sourceTree = ""; }; + CDAD4E9818EC8424007D4BC2 /* SOSTransportTestTransports.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSTransportTestTransports.c; sourceTree = ""; }; + CDAD4E9A18EC8447007D4BC2 /* SOSTransportTestTransports.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransportTestTransports.h; sourceTree = ""; }; + CDC765C01729A72800721712 /* SecPasswordGenerate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecPasswordGenerate.c; sourceTree = ""; }; + CDC765C11729A72800721712 /* SecPasswordGenerate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecPasswordGenerate.h; sourceTree = ""; }; + CDD565A1173193AC00B6B074 /* si-73-secpasswordgenerate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-73-secpasswordgenerate.c"; sourceTree = ""; }; + CDF1B82218BD7DDE006309BC /* SOSTransport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransport.h; sourceTree = ""; }; + E702E75614E1F3EA00CDE635 /* libSecureObjectSync.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSecureObjectSync.a; sourceTree = BUILT_PRODUCTS_DIR; }; + E702E77814E1F48800CDE635 /* libSOSRegressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSOSRegressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; + E703811114E1FEE4007CB458 /* SOSCloudCircle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSCloudCircle.h; sourceTree = ""; }; + E71049F2169E023B00DB0045 /* libSecurityTool.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSecurityTool.a; sourceTree = BUILT_PRODUCTS_DIR; }; + E71049FE169E036E00DB0045 /* security.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = security.1; sourceTree = ""; }; + E71049FF169E036E00DB0045 /* SecurityTool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecurityTool.c; sourceTree = ""; }; + E7104A00169E036E00DB0045 /* SecurityTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecurityTool.h; sourceTree = ""; }; + E7104A0D169E1C1600DB0045 /* tool_errors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tool_errors.h; sourceTree = ""; }; + E7104A1D169E216E00DB0045 /* libSecurityCommands.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSecurityCommands.a; sourceTree = BUILT_PRODUCTS_DIR; }; + E7217B1715F80E0F00D26031 /* SOSCloudCircle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = SOSCloudCircle.c; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.c; }; + E7217B2515F8131A00D26031 /* SOSCloudKeychainConstants.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = SOSCloudKeychainConstants.c; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.c; }; + E7217B2615F8131A00D26031 /* SOSCloudKeychainConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSCloudKeychainConstants.h; sourceTree = ""; }; + E7295C6714E3571A007FBB20 /* Empty.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = Empty.c; sourceTree = ""; }; + E748744415A61AF800624935 /* si-68-secmatchissuer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-68-secmatchissuer.c"; sourceTree = ""; }; + E757D42219254B3200AF22D9 /* SecECKeyPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecECKeyPriv.h; sourceTree = ""; }; + E76079D21951FD2800F69731 /* liblogging.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = liblogging.a; sourceTree = BUILT_PRODUCTS_DIR; }; + E763D6221624E2670038477D /* sc-20-keynames.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-20-keynames.c"; sourceTree = ""; }; + E777C6B015B4DDF2004044A8 /* sc-40-circle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-40-circle.c"; sourceTree = ""; }; + E777C71B15B73F59004044A8 /* SOSInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSInternal.h; sourceTree = ""; }; + E777C71D15B73F9E004044A8 /* SOSInternal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSInternal.c; sourceTree = ""; }; + E777C72415B87528004044A8 /* SOSPeerInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSPeerInfo.h; sourceTree = ""; }; + E777C72515B87544004044A8 /* SOSPeerInfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSPeerInfo.c; sourceTree = ""; }; + E777C72815B9C9F0004044A8 /* sc-30-peerinfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-30-peerinfo.c"; sourceTree = ""; }; + E790C0F4169E3D7200E0C0C9 /* SOSCommands.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSCommands.h; sourceTree = ""; }; + E790C108169E4E7900E0C0C9 /* builtin_commands.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = builtin_commands.h; sourceTree = ""; }; + E790C109169E4FD200E0C0C9 /* digest_calc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = digest_calc.c; sourceTree = ""; }; + E790C10E169E53DF00E0C0C9 /* leaks.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = leaks.c; sourceTree = ""; }; + E790C10F169E53DF00E0C0C9 /* leaks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = leaks.h; sourceTree = ""; }; + E790C136169E5C6200E0C0C9 /* add_internet_password.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = add_internet_password.c; sourceTree = ""; }; + E790C137169E5C6200E0C0C9 /* codesign.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = codesign.c; sourceTree = ""; }; + E790C138169E5C6200E0C0C9 /* keychain_add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keychain_add.c; sourceTree = ""; }; + E790C139169E5C6200E0C0C9 /* keychain_find.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keychain_find.c; sourceTree = ""; }; + E790C13A169E5C6200E0C0C9 /* pkcs12_util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkcs12_util.c; sourceTree = ""; }; + E790C13D169E5C6200E0C0C9 /* scep.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scep.c; sourceTree = ""; }; + E790C13E169E5C6200E0C0C9 /* SecurityCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecurityCommands.h; sourceTree = ""; }; + E790C13F169E5C6200E0C0C9 /* show_certificates.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = show_certificates.c; sourceTree = ""; }; + E790C140169E5C6200E0C0C9 /* spc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = spc.c; sourceTree = ""; }; + E79277E1163B110A0096F3E2 /* SOSFullPeerInfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSFullPeerInfo.c; sourceTree = ""; }; + E79277E2163B110A0096F3E2 /* SOSFullPeerInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSFullPeerInfo.h; sourceTree = ""; }; + E795C93E19100F5000FA068C /* log_control.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = log_control.c; sourceTree = ""; }; + E795C94119116EA200FA068C /* SecLogging.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecLogging.c; sourceTree = ""; }; + E795C94319116ECA00FA068C /* SecLogging.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecLogging.h; sourceTree = ""; }; + E795C9461911A39800FA068C /* SecLogSettingsServer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecLogSettingsServer.h; sourceTree = ""; }; + E795C9471911A41200FA068C /* SecLogSettingsServer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecLogSettingsServer.c; sourceTree = ""; }; + E795C9521913112F00FA068C /* SecServerEncryptionSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecServerEncryptionSupport.h; sourceTree = ""; }; + E795C9531913F88D00FA068C /* SecServerEncryptionSupport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecServerEncryptionSupport.c; sourceTree = ""; }; + E79D62B9176798BF005A9743 /* secd-50-account.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = "secd-50-account.c"; path = "securityd/Regressions/secd-50-account.c"; sourceTree = SOURCE_ROOT; }; + E79D62BE1767A547005A9743 /* SecdTestKeychainUtilities.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecdTestKeychainUtilities.c; sourceTree = ""; }; + E79D62BF1767A55F005A9743 /* SecdTestKeychainUtilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecdTestKeychainUtilities.h; sourceTree = ""; }; + E7A10FAA1771245D00C4602F /* SOSAccountTesting.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSAccountTesting.h; sourceTree = ""; }; + E7A10FAB1771246A00C4602F /* secd-55-account-circle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-55-account-circle.c"; sourceTree = ""; }; + E7A10FAD1771249C00C4602F /* secd-57-account-leave.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-57-account-leave.c"; sourceTree = ""; }; + E7A634E217FA471500920B67 /* SOSPeerInfoCollections.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSPeerInfoCollections.c; sourceTree = ""; }; + E7A634E417FA472700920B67 /* SOSPeerInfoCollections.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSPeerInfoCollections.h; sourceTree = ""; }; + E7B00701170B58BD00B27966 /* SecExports.exp-in */ = {isa = PBXFileReference; lastKnownFileType = text; path = "SecExports.exp-in"; sourceTree = ""; }; + E7B00702170B5FE100B27966 /* SOSExports.exp-in */ = {isa = PBXFileReference; lastKnownFileType = text; lineEnding = 0; path = "SOSExports.exp-in"; sourceTree = ""; }; + E7B01B5A16532507000485F1 /* SOSCloudCircleInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = SOSCloudCircleInternal.h; sourceTree = ""; }; + E7B01B661655CC99000485F1 /* SOSCloudCircleServer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSCloudCircleServer.h; sourceTree = ""; }; + E7B01B671655CCA6000485F1 /* SOSCloudCircleServer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = SOSCloudCircleServer.c; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.c; }; + E7B01B8816572579000485F1 /* SecuritydXPC.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecuritydXPC.c; sourceTree = ""; }; + E7B01B8A1657259F000485F1 /* SecuritydXPC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecuritydXPC.h; sourceTree = ""; }; + E7BE10A5167AB2BF00D2A178 /* sc-41-cloudcircle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-41-cloudcircle.c"; sourceTree = ""; }; + E7EBD75619145D6400D0F062 /* so_01_serverencryption.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = so_01_serverencryption.c; sourceTree = ""; }; + E7F0D3E9177BBE35001ACBC1 /* secd-55-account-incompatibility.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-55-account-incompatibility.c"; sourceTree = ""; }; + E7F18554177A44E000177B23 /* secd-60-account-cloud-identity.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-60-account-cloud-identity.c"; sourceTree = ""; }; + E7F18556177A502900177B23 /* secd-56-account-apply.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-56-account-apply.c"; sourceTree = ""; }; + E7FEFB8C169E363300E18152 /* libSOSCommands.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSOSCommands.a; sourceTree = BUILT_PRODUCTS_DIR; }; + E7FEFB90169E36D800E18152 /* keychain_sync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = keychain_sync.c; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.c; }; + EB973200189C56310063DFED /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + EB973203189C56310063DFED /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.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 = ""; }; + EBDAECBA184D30C3005A18F1 /* sc-31-peerinfo-simplefuzz.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-31-peerinfo-simplefuzz.c"; sourceTree = ""; }; + F697632118F6CC3F0090438B /* keychain_util.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = keychain_util.c; sourceTree = ""; }; + F697632218F6CC3F0090438B /* keychain_util.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = keychain_util.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 0C0BDB59175687EC00BC1A7E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18270F5214CF651900B05E7F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 186CDD0C14CA116C00AF9171 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18D4043214CE0CF300A2BE4E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18D4055F14CE53C200A2BE4E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4A5CCA4C15ACEFA500702357 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4A824AFE158FF07000F932C0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CC92AFA15A3BC6B00C6D578 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5284029D164445760035F320 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BEF9640118B4171200813FA3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E702E74F14E1F3EA00CDE635 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E702E77114E1F48800CDE635 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4AD6F6F21651C86200DB4CE6 /* libSecureObjectSync.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E71049EF169E023B00DB0045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E71049F3169E023B00DB0045 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E7104A17169E216E00DB0045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E7104A18169E216E00DB0045 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E76079C21951FD2800F69731 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E7FEFB86169E363300E18152 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E7FEFB87169E363300E18152 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 18270C9614CF1AAD00B05E7F /* config */ = { + isa = PBXGroup; + children = ( + 18270C9714CF1AAD00B05E7F /* base.xcconfig */, + 18270C9814CF1AAD00B05E7F /* debug.xcconfig */, + 4C5EA365164C791400A136B8 /* lib-arc-only.xcconfig */, + 18270C9914CF1AAD00B05E7F /* lib.xcconfig */, + 18270C9A14CF1AAD00B05E7F /* release.xcconfig */, + ); + path = config; + sourceTree = ""; + }; + 186CDD0414CA116C00AF9171 = { + isa = PBXGroup; + children = ( + 18270C9614CF1AAD00B05E7F /* config */, + 18AD565714CB6ECD008233F2 /* securityd */, + 186CDD1F14CA126D00AF9171 /* ipc */, + E7AC69CE14E1F78400CB09C1 /* SOSCircle */, + 186CDD3014CA159600AF9171 /* Security */, + E71049F4169E023B00DB0045 /* SecurityTool */, + BEF9640718B417EB00813FA3 /* SharedWebCredentialAgent */, + 521C0B9715FA5C4900604B61 /* Frameworks */, + 186CDD1014CA116C00AF9171 /* Products */, + ); + sourceTree = ""; + }; + 186CDD1014CA116C00AF9171 /* Products */ = { + isa = PBXGroup; + children = ( + 186CDD0F14CA116C00AF9171 /* libSecItemShimOSX.a */, + 18D4043514CE0CF300A2BE4E /* libsecurity.a */, + 18D4056214CE53C200A2BE4E /* libsecurityd.a */, + 18270F5514CF651900B05E7F /* libsecipc_client.a */, + E702E75614E1F3EA00CDE635 /* libSecureObjectSync.a */, + E702E77814E1F48800CDE635 /* libSOSRegressions.a */, + 4A824B03158FF07000F932C0 /* libSecurityRegressions.a */, + 4CC92B1415A3BC6B00C6D578 /* libsecuritydRegressions.a */, + 4A5CCA4F15ACEFA500702357 /* libSecOtrOSX.a */, + 528402A0164445760035F320 /* libCloudKeychainProxy.a */, + E71049F2169E023B00DB0045 /* libSecurityTool.a */, + E7104A1D169E216E00DB0045 /* libSecurityCommands.a */, + E7FEFB8C169E363300E18152 /* libSOSCommands.a */, + 0C0BDB5F175687EC00BC1A7E /* libsecdRegressions.a */, + BEF9640618B4171200813FA3 /* libSWCAgent.a */, + E76079D21951FD2800F69731 /* liblogging.a */, + ); + name = Products; + sourceTree = ""; + }; + 186CDD1F14CA126D00AF9171 /* ipc */ = { + isa = PBXGroup; + children = ( + 18AD560614CB6E7A008233F2 /* client.c */, + 18AD560714CB6E7A008233F2 /* com.apple.securityd.plist */, + 18AD560814CB6E7A008233F2 /* securityd_client.h */, + 18AD560D14CB6E7A008233F2 /* server.c */, + ); + path = ipc; + sourceTree = ""; + }; + 186CDD3014CA159600AF9171 /* Security */ = { + isa = PBXGroup; + children = ( + E7104A0F169E1F0800DB0045 /* Tool */, + 4A824AFA158FF05900F932C0 /* Regressions */, + 52D0F026169CA72800F07D79 /* SecOnOSX.h */, + 4A971682158FDEB800D439B7 /* SecOTR.h */, + 4A971684158FDEB800D439B7 /* SecOTRDHKey.h */, + 4A971685158FDEB800D439B7 /* SecOTRErrors.h */, + 4A971686158FDEB800D439B7 /* SecOTRFullIdentity.c */, + 4A971687158FDEB800D439B7 /* SecOTRIdentityPriv.h */, + 4A971688158FDEB800D439B7 /* SecOTRMath.c */, + 4A971689158FDEB800D439B7 /* SecOTRMath.h */, + 4A97168B158FDEB800D439B7 /* SecOTRPacketData.c */, + 4A97168C158FDEB800D439B7 /* SecOTRPacketData.h */, + 4A97168D158FDEB800D439B7 /* SecOTRPackets.c */, + 4A97168E158FDEB800D439B7 /* SecOTRPackets.h */, + 4A97168F158FDEB800D439B7 /* SecOTRPublicIdentity.c */, + 4A971690158FDEB800D439B7 /* SecOTRSession.c */, + 4A971691158FDEB800D439B7 /* SecOTRSession.h */, + 4A971692158FDEB800D439B7 /* SecOTRSessionAKE.c */, + 4A971693158FDEB800D439B7 /* SecOTRSessionPriv.h */, + 4A971694158FDEB800D439B7 /* SecOTRUtils.c */, + 18AD561514CB6EB9008233F2 /* certextensions.h */, + 18AD561614CB6EB9008233F2 /* p12import.c */, + 18AD561714CB6EB9008233F2 /* p12import.h */, + 18AD561814CB6EB9008233F2 /* p12pbegen.c */, + 18AD561914CB6EB9008233F2 /* p12pbegen.h */, + 18AD561A14CB6EB9008233F2 /* pbkdf2.c */, + 18AD561B14CB6EB9008233F2 /* pbkdf2.h */, + C6EE78BA189821AD009B8FEB /* SecAccessControl.h */, + C62A296818996D90006C3A11 /* SecAccessControlPriv.h */, + C6766767189884D200E9A12C /* SecAccessControl.c */, + 18AD561C14CB6EB9008233F2 /* SecBase.h */, + 18AD561D14CB6EB9008233F2 /* SecBase64.c */, + 18AD561E14CB6EB9008233F2 /* SecBase64.h */, + 18AD561F14CB6EB9008233F2 /* SecBasePriv.h */, + 18AD562114CB6EB9008233F2 /* SecCertificate.h */, + 18AD562214CB6EB9008233F2 /* SecCertificateInternal.h */, + 18AD562314CB6EB9008233F2 /* SecCertificatePath.c */, + 18AD562414CB6EB9008233F2 /* SecCertificatePath.h */, + 18AD562514CB6EB9008233F2 /* SecCertificatePriv.h */, + 18AD562614CB6EB9008233F2 /* SecCertificateRequest.c */, + 18AD562714CB6EB9008233F2 /* SecCertificateRequest.h */, + 18AD562814CB6EB9008233F2 /* SecCMS.c */, + 18AD562914CB6EB9008233F2 /* SecCMS.h */, + 18AD562A14CB6EB9008233F2 /* SecDH.c */, + 18AD562B14CB6EB9008233F2 /* SecDH.h */, + 18AD562C14CB6EB9008233F2 /* SecECKey.c */, + 18AD562D14CB6EB9008233F2 /* SecECKey.h */, + E757D42219254B3200AF22D9 /* SecECKeyPriv.h */, + 18AD562E14CB6EB9008233F2 /* SecFramework.c */, + 18AD562014CB6EB9008233F2 /* SecCertificate.c */, + 18AD562F14CB6EB9008233F2 /* SecFramework.h */, + 18AD563014CB6EB9008233F2 /* SecFrameworkStrings.h */, + 18AD563114CB6EB9008233F2 /* SecIdentity.c */, + 18AD563214CB6EB9008233F2 /* SecIdentity.h */, + 18AD563314CB6EB9008233F2 /* SecIdentityPriv.h */, + 18AD563414CB6EB9008233F2 /* SecImportExport.c */, + 18AD563514CB6EB9008233F2 /* SecImportExport.h */, + 18AD563614CB6EB9008233F2 /* SecInternal.h */, + 18AD563714CB6EB9008233F2 /* SecItem.c */, + 18AD563814CB6EB9008233F2 /* SecItem.h */, + 18AD563914CB6EB9008233F2 /* SecItemConstants.c */, + 18AD563A14CB6EB9008233F2 /* SecItemInternal.h */, + 18AD563B14CB6EB9008233F2 /* SecItemPriv.h */, + 18AD563C14CB6EB9008233F2 /* SecKey.c */, + 18AD563D14CB6EB9008233F2 /* SecKey.h */, + 18AD563E14CB6EB9008233F2 /* SecKeyInternal.h */, + 18AD563F14CB6EB9008233F2 /* SecKeyPriv.h */, + CDC765C01729A72800721712 /* SecPasswordGenerate.c */, + CDC765C11729A72800721712 /* SecPasswordGenerate.h */, + 18AD564014CB6EB9008233F2 /* SecPBKDF.c */, + 18AD564114CB6EB9008233F2 /* SecPBKDF.h */, + 18AD564214CB6EB9008233F2 /* SecPolicy.c */, + 18AD564314CB6EB9008233F2 /* SecPolicy.h */, + BE556A5D19550E1600E6EE8C /* SecPolicyCerts.h */, + 18AD564414CB6EB9008233F2 /* SecPolicyInternal.h */, + 18AD564514CB6EB9008233F2 /* SecPolicyPriv.h */, + 18AD564614CB6EB9008233F2 /* SecRandom.h */, + 18AD564714CB6EB9008233F2 /* SecRSAKey.c */, + 18AD564814CB6EB9008233F2 /* SecRSAKey.h */, + 18AD564914CB6EB9008233F2 /* SecRSAKeyPriv.h */, + 18AD564A14CB6EB9008233F2 /* SecSCEP.c */, + 18AD564B14CB6EB9008233F2 /* SecSCEP.h */, + E795C9531913F88D00FA068C /* SecServerEncryptionSupport.c */, + E795C9521913112F00FA068C /* SecServerEncryptionSupport.h */, + 18AD564C14CB6EB9008233F2 /* SecTrust.c */, + 18AD564D14CB6EB9008233F2 /* SecTrust.h */, + 18AD564E14CB6EB9008233F2 /* SecTrustPriv.h */, + 18AD564F14CB6EB9008233F2 /* SecTrustSettings.c */, + 18AD565014CB6EB9008233F2 /* SecTrustSettings.h */, + 18AD565114CB6EB9008233F2 /* SecTrustSettingsPriv.h */, + 18AD565214CB6EB9008233F2 /* SecTrustStore.c */, + 18AD565314CB6EB9008233F2 /* SecTrustStore.h */, + BE642BB1188F32C200C899A2 /* SecSharedCredential.c */, + BE642BAF188F32AD00C899A2 /* SecSharedCredential.h */, + 18AD565414CB6EB9008233F2 /* Security.h */, + 18AD565514CB6EB9008233F2 /* vmdh.c */, + 18AD565614CB6EB9008233F2 /* vmdh.h */, + E7B01B8816572579000485F1 /* SecuritydXPC.c */, + E7B01B8A1657259F000485F1 /* SecuritydXPC.h */, + 724D7363177A13A500FA10A1 /* AppleBaselineEscrowCertificates.h */, + E7B00701170B58BD00B27966 /* SecExports.exp-in */, + 44B2606C18F82631008DF20F /* SecAccessControlExports.exp-in */, + E795C94119116EA200FA068C /* SecLogging.c */, + E795C94319116ECA00FA068C /* SecLogging.h */, + ); + path = Security; + sourceTree = ""; + }; + 18AD565714CB6ECD008233F2 /* securityd */ = { + isa = PBXGroup; + children = ( + 4CC92AAB15A3AC4600C6D578 /* Regressions */, + 18AD567D14CB865E008233F2 /* asynchttp.c */, + 18AD567E14CB865E008233F2 /* asynchttp.h */, + 18AD567F14CB865E008233F2 /* entitlements.plist */, + 72E2DC0616BC47C800E7B236 /* OTATrustUtilities.c */, + 72E2DC0716BC47C800E7B236 /* OTATrustUtilities.h */, + 18AD568214CB865E008233F2 /* policytree.c */, + 18AD568314CB865E008233F2 /* policytree.h */, + 18AD568414CB865E008233F2 /* SecCAIssuerCache.c */, + 18AD568514CB865E008233F2 /* SecCAIssuerCache.h */, + 18AD568614CB865E008233F2 /* SecCAIssuerRequest.c */, + 18AD568714CB865E008233F2 /* SecCAIssuerRequest.h */, + 4C4B15931655ED9000734590 /* SecDbItem.c */, + 4C4B15951655EDA700734590 /* SecDbItem.h */, + 4C055FED17B60F1E001A879A /* SecDbKeychainItem.c */, + 4C05608417B60F88001A879A /* SecDbKeychainItem.h */, + 4C055FEE17B60F1E001A879A /* SecDbQuery.c */, + 4C05608517B60F88001A879A /* SecDbQuery.h */, + 4C055FEF17B60F1E001A879A /* SecItemDataSource.c */, + 4C05608617B60F88001A879A /* SecItemDataSource.h */, + 4C055FF017B60F1E001A879A /* SecItemDb.c */, + 4C05608717B60F88001A879A /* SecItemDb.h */, + 4C055FF117B60F1E001A879A /* SecItemSchema.c */, + 4C05608817B60F88001A879A /* SecItemSchema.h */, + 18AD568814CB865E008233F2 /* SecItemServer.c */, + 18AD565814CB6F79008233F2 /* SecItemServer.h */, + 4C055FF217B60F1E001A879A /* SecKeybagSupport.c */, + 4C05608917B60F88001A879A /* SecKeybagSupport.h */, + 18AD565914CB6F79008233F2 /* SecOCSPCache.c */, + 18AD565A14CB6F79008233F2 /* SecOCSPCache.h */, + 18AD565B14CB6F79008233F2 /* SecOCSPRequest.c */, + 18AD565C14CB6F79008233F2 /* SecOCSPRequest.h */, + 18AD565D14CB6F79008233F2 /* SecOCSPResponse.c */, + 18AD565E14CB6F79008233F2 /* SecOCSPResponse.h */, + 18AD565F14CB6F79008233F2 /* SecPolicyServer.c */, + 18AD566014CB6F79008233F2 /* SecPolicyServer.h */, + 18AD566114CB6F79008233F2 /* SecTrustServer.c */, + 18AD566214CB6F79008233F2 /* SecTrustServer.h */, + E7B01B671655CCA6000485F1 /* SOSCloudCircleServer.c */, + E7B01B661655CC99000485F1 /* SOSCloudCircleServer.h */, + 18AD566314CB6F79008233F2 /* SecTrustStoreServer.c */, + 18AD566414CB6F79008233F2 /* SecTrustStoreServer.h */, + E795C9471911A41200FA068C /* SecLogSettingsServer.c */, + E795C9461911A39800FA068C /* SecLogSettingsServer.h */, + 18AD566514CB6F79008233F2 /* spi.c */, + 18AD566614CB6F79008233F2 /* spi.h */, + 72B5923A17C6924000AE738B /* iCloudTrace.h */, + 72B5923C17C6939A00AE738B /* iCloudTrace.c */, + 5356520218E3C71000C383C0 /* SecOTRRemote.c */, + 5356520418E3C88D00C383C0 /* SecOTRRemote.h */, + ); + path = securityd; + sourceTree = ""; + }; + 4A824AFA158FF05900F932C0 /* Regressions */ = { + isa = PBXGroup; + children = ( + 4CC92AB015A3AD0000C6D578 /* Security_regressions.h */, + 4CC92A0E15A3ABD400C6D578 /* crypto */, + 4CC92A1115A3ABD400C6D578 /* otr */, + 4CC92A1615A3ABD400C6D578 /* secitem */, + 4CC92A5B15A3ABD400C6D578 /* vmdh */, + E7EBD75619145D6400D0F062 /* so_01_serverencryption.c */, + ); + name = Regressions; + sourceTree = ""; + }; + 4CC92A0E15A3ABD400C6D578 /* crypto */ = { + isa = PBXGroup; + children = ( + 4CC92A0F15A3ABD400C6D578 /* pbkdf2-00-hmac-sha1.c */, + 4CC92A1015A3ABD400C6D578 /* spbkdf-00-hmac-sha1.c */, + ); + name = crypto; + path = Regressions/crypto; + sourceTree = ""; + }; + 4CC92A1115A3ABD400C6D578 /* otr */ = { + isa = PBXGroup; + children = ( + 4CC92A1215A3ABD400C6D578 /* otr-00-identity.c */, + 4CC92A1315A3ABD400C6D578 /* otr-30-negotiation.c */, + 4CC92A1415A3ABD400C6D578 /* otr-otrdh.c */, + 4CC92A1515A3ABD400C6D578 /* otr-packetdata.c */, + ); + name = otr; + path = Regressions/otr; + sourceTree = ""; + }; + 4CC92A1615A3ABD400C6D578 /* secitem */ = { + isa = PBXGroup; + children = ( + 4CC92A1715A3ABD400C6D578 /* si-00-find-nothing.c */, + 4CC92A1815A3ABD400C6D578 /* si-05-add.c */, + 4CC92A1915A3ABD400C6D578 /* si-10-find-internet.c */, + 4CC92A1A15A3ABD400C6D578 /* si-11-update-data.c */, + 4C2C8C3C17AB374700C24C13 /* si-12-item-stress.c */, + 4CC92A1B15A3ABD400C6D578 /* si-14-dateparse.c */, + 4CC92A1C15A3ABD400C6D578 /* si-15-certificate.c */, + 4CC92A1D15A3ABD400C6D578 /* si-16-ec-certificate.c */, + 4CC92A1E15A3ABD400C6D578 /* si-20-sectrust-activation.c */, + 4CC92A1F15A3ABD400C6D578 /* si-20-sectrust.c */, + 4CC92A2015A3ABD400C6D578 /* si-21-sectrust-asr.c */, + 4CC92A2115A3ABD400C6D578 /* si-22-sectrust-iap.c */, + 4CC92A2215A3ABD400C6D578 /* si-23-sectrust-ocsp.c */, + 4CC92A2315A3ABD400C6D578 /* si-24-sectrust-appleid.c */, + 4CC92A2415A3ABD400C6D578 /* si-24-sectrust-digicert-malaysia.c */, + 4CC92A2515A3ABD400C6D578 /* si-24-sectrust-diginotar.c */, + 4CC92A2615A3ABD400C6D578 /* si-24-sectrust-itms.c */, + 4CC92A2715A3ABD400C6D578 /* si-24-sectrust-mobileasset.c */, + 4CC92A2815A3ABD400C6D578 /* si-24-sectrust-nist.c */, + 4CC92A2915A3ABD400C6D578 /* si-24-sectrust-otatasking.c */, + 4CC92A2A15A3ABD400C6D578 /* si-24-sectrust-shoebox.c */, + 4CC92A2B15A3ABD400C6D578 /* si-25-sectrust-ipsec-eap.c */, + 4CC92A2C15A3ABD400C6D578 /* si-26-applicationsigning.c */, + 4CC92A2D15A3ABD400C6D578 /* si-27-sectrust-exceptions.c */, + 4CC92A2E15A3ABD400C6D578 /* si-28-sectrustsettings.c */, + 4CC92A2F15A3ABD400C6D578 /* si-29-sectrust-codesigning.c */, + 4CC92A3015A3ABD400C6D578 /* si-30-keychain-upgrade.c */, + 4CC92A3115A3ABD400C6D578 /* si-31-keychain-bad.c */, + 4CC92A3215A3ABD400C6D578 /* si-31-keychain-unreadable.c */, + 4CC92A3415A3ABD400C6D578 /* si-33-keychain-backup.c */, + 4CC92A3515A3ABD400C6D578 /* si-40-seckey-custom.c */, + 4CC92A3615A3ABD400C6D578 /* si-40-seckey.c */, + 4CC92A3715A3ABD400C6D578 /* si-41-sececkey.c */, + 4CC92A3815A3ABD400C6D578 /* si-42-identity.c */, + 4CC92A3915A3ABD400C6D578 /* si-43-persistent.c */, + 4CC92A3A15A3ABD400C6D578 /* si-50-secrandom.c */, + 4CC92A3B15A3ABD400C6D578 /* si-60-cms.c */, + 4CC92A3C15A3ABD400C6D578 /* si-61-pkcs12.c */, + 4CC92A3D15A3ABD400C6D578 /* si-62-csr.c */, + 4CC92A3E15A3ABD400C6D578 /* si-63-scep */, + 4CC92A4115A3ABD400C6D578 /* si-63-scep.c */, + 4CC92A4215A3ABD400C6D578 /* si-63-scep.h */, + 4CC92A4315A3ABD400C6D578 /* si-64-ossl-cms */, + 4CC92A4A15A3ABD400C6D578 /* si-64-ossl-cms.c */, + 4CC92A4B15A3ABD400C6D578 /* si-65-cms-cert-policy.c */, + 4CC92A4C15A3ABD400C6D578 /* si-66-smime */, + 4CC92A4E15A3ABD400C6D578 /* si-66-smime.c */, + 4CC92A4F15A3ABD400C6D578 /* si-67-sectrust-blacklist */, + 4CC92A5A15A3ABD400C6D578 /* si-67-sectrust-blacklist.c */, + E748744415A61AF800624935 /* si-68-secmatchissuer.c */, + CDA7729616B899F10069434D /* si-69-keydesc.c */, + BE62D7611747FF51001EAA9D /* si-70-sectrust-unified.c */, + 5DE4A7BC17441CCD0036339E /* si-71-mobile-store-policy.c */, + BE62D75F1747FF3E001EAA9D /* si-72-syncableitems.c */, + CDD565A1173193AC00B6B074 /* si-73-secpasswordgenerate.c */, + 7255A46B1783333D006A8B9A /* si-74-OTAPKISigner.c */, + 7255F91317A973D5004A9F38 /* si-75-AppleIDRecordSigning.c */, + BE061FCE1899E5BD00C739F6 /* si-76-shared-credentials.c */, + 3A70988118CDF648009FD2CC /* si_77_SecAccessControl.c */, + 4477A8D718F28AAE00B5BB9F /* si-78-query-attrs.c */, + 7DE2092F192D29D90066419C /* si-79-smp-cert-policy.c */, + 4406660E19069707000DA171 /* si-80-empty-data.c */, + 5E9E1590196426C6001EB804 /* si-81-item-acl-stress.c */, + BE794825196DBEAD00F4BA63 /* si-81-sectrust-server-auth.c */, + ); + name = secitem; + path = Regressions/secitem; + sourceTree = ""; + }; + 4CC92A3E15A3ABD400C6D578 /* si-63-scep */ = { + isa = PBXGroup; + children = ( + 4CC92A3F15A3ABD400C6D578 /* getcacert-mdes.h */, + 4CC92A4015A3ABD400C6D578 /* getcacert-mdesqa.h */, + ); + path = "si-63-scep"; + sourceTree = ""; + }; + 4CC92A4315A3ABD400C6D578 /* si-64-ossl-cms */ = { + isa = PBXGroup; + children = ( + 4CC92A4415A3ABD400C6D578 /* attached_no_data_signed_data.h */, + 4CC92A4515A3ABD400C6D578 /* attached_signed_data.h */, + 4CC92A4615A3ABD400C6D578 /* detached_content.h */, + 4CC92A4715A3ABD400C6D578 /* detached_signed_data.h */, + 4CC92A4815A3ABD400C6D578 /* privkey.h */, + 4CC92A4915A3ABD400C6D578 /* signer.h */, + ); + path = "si-64-ossl-cms"; + sourceTree = ""; + }; + 4CC92A4C15A3ABD400C6D578 /* si-66-smime */ = { + isa = PBXGroup; + children = ( + 4CC92A4D15A3ABD400C6D578 /* signed-receipt.h */, + ); + path = "si-66-smime"; + sourceTree = ""; + }; + 4CC92A4F15A3ABD400C6D578 /* si-67-sectrust-blacklist */ = { + isa = PBXGroup; + children = ( + 4A971683158FDEB800D439B7 /* SecOTRDHKey.c */, + 4CC92A5015A3ABD400C6D578 /* Global Trustee.cer.h */, + 4CC92A5115A3ABD400C6D578 /* UTN-USERFirst-Hardware.cer.h */, + 4CC92A5215A3ABD400C6D578 /* addons.mozilla.org.cer.h */, + 4CC92A5315A3ABD400C6D578 /* login.live.com.cer.h */, + 4CC92A5415A3ABD400C6D578 /* login.skype.com.cer.h */, + 4CC92A5515A3ABD400C6D578 /* login.yahoo.com.1.cer.h */, + 4CC92A5615A3ABD400C6D578 /* login.yahoo.com.2.cer.h */, + 4CC92A5715A3ABD400C6D578 /* login.yahoo.com.cer.h */, + 4CC92A5815A3ABD400C6D578 /* mail.google.com.cer.h */, + 4CC92A5915A3ABD400C6D578 /* www.google.com.cer.h */, + ); + path = "si-67-sectrust-blacklist"; + sourceTree = ""; + }; + 4CC92A5B15A3ABD400C6D578 /* vmdh */ = { + isa = PBXGroup; + children = ( + 4CC92A5C15A3ABD400C6D578 /* vmdh-40.c */, + 4CC92A5D15A3ABD400C6D578 /* vmdh-41-example.c */, + 4CC92A5E15A3ABD400C6D578 /* vmdh-42-example2.c */, + ); + name = vmdh; + path = Regressions/vmdh; + sourceTree = ""; + }; + 4CC92AAB15A3AC4600C6D578 /* Regressions */ = { + isa = PBXGroup; + children = ( + ACFD56BD19007B2D00F5F5D9 /* ios6_1_keychain_2_db.h */, + 0CBF93F5177B7CFC001E5658 /* secd-03-corrupted-items.c */, + 0CBF93F6177B7CFC001E5658 /* secd-04-corrupted-items.c */, + 0CBF93FB177BA9D9001E5658 /* secd-05-corrupted-items.c */, + 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 */, + 0C062B1C175E784B00806CFE /* secd-30-keychain-upgrade.c */, + 0C062B1D175E784B00806CFE /* secd-31-keychain-bad.c */, + 0C062B1E175E784B00806CFE /* secd-31-keychain-unreadable.c */, + E79D62B9176798BF005A9743 /* secd-50-account.c */, + 48E928C4179DD05500A7F755 /* secd-51-account-inflate.c */, + 4898223917BDB277003BEF32 /* secd-52-account-changed.c */, + E7A10FAB1771246A00C4602F /* secd-55-account-circle.c */, + E7F0D3E9177BBE35001ACBC1 /* secd-55-account-incompatibility.c */, + E7F18556177A502900177B23 /* secd-56-account-apply.c */, + E7A10FAD1771249C00C4602F /* secd-57-account-leave.c */, + 4882C516177521AE0095D04B /* secd-58-password-change.c */, + 48F32D7D1777AFA3001B84BA /* secd-59-account-cleanup.c */, + E7F18554177A44E000177B23 /* secd-60-account-cloud-identity.c */, + 486C6C671795F20E00387075 /* secd-61-account-leave-not-in-kansas-anymore.c */, + 527258CF1981C00F003CFCEC /* secd-70-engine.c */, + 4C495EE01982171500BC1809 /* secd-70-engine-corrupt.c */, + 5384299318E492A300E91AFE /* secd-70-otr-remote.c */, + E7A10FAA1771245D00C4602F /* SOSAccountTesting.h */, + E79D62BE1767A547005A9743 /* SecdTestKeychainUtilities.c */, + E79D62BF1767A55F005A9743 /* SecdTestKeychainUtilities.h */, + CDAD4E9818EC8424007D4BC2 /* SOSTransportTestTransports.c */, + CDAD4E9A18EC8447007D4BC2 /* SOSTransportTestTransports.h */, + ); + path = Regressions; + sourceTree = ""; + }; + 521C0B9715FA5C4900604B61 /* Frameworks */ = { + isa = PBXGroup; + children = ( + EB97322D189C56DB0063DFED /* CoreFoundation.framework */, + 52DD7069160CD40B0027A346 /* libutilities.a */, + 526CBA5116079FB4008DF7C8 /* Security.framework */, + 521C0B9815FA5C4A00604B61 /* Foundation.framework */, + EB973200189C56310063DFED /* Cocoa.framework */, + EB973215189C56310063DFED /* XCTest.framework */, + EB973202189C56310063DFED /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + 521C0B9B15FA5C4A00604B61 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 521C0BAB15FA5DA800604B61 /* en.lproj */ = { + isa = PBXGroup; + children = ( + 521C0BAC15FA5DA800604B61 /* InfoPlist.strings */, + ); + name = en.lproj; + path = SOSCircle/CloudKeychainProxy/en.lproj; + sourceTree = SOURCE_ROOT; + }; + 5272501416838BB20029AADD /* CloudKeychainProxy */ = { + isa = PBXGroup; + children = ( + 52C3D18E169A53150091D9D3 /* ckdmain.m */, + 521C0BB315FA5E3F00604B61 /* cloudkeychainproxy.m */, + 521C0BAF15FA5E3F00604B61 /* CKDKVSProxy.h */, + 521C0BB015FA5E3F00604B61 /* CKDKVSProxy.m */, + 521C0BB115FA5E3F00604B61 /* CKDPersistentState.h */, + 521C0BB215FA5E3F00604B61 /* CKDPersistentState.m */, + 52840291164050C80035F320 /* CKDUserInteraction.h */, + 52840292164050C80035F320 /* CKDUserInteraction.m */, + 521C0B9B15FA5C4A00604B61 /* Supporting Files */, + 522B0ED31649A68E00A4675D /* MobileKeyBag.framework */, + 521C0BAB15FA5DA800604B61 /* en.lproj */, + 521C0BA615FA5D7400604B61 /* cloudkeychain.entitlements.plist */, + 5272501916838BB20029AADD /* CloudKeychainProxy.1 */, + 5272501716838BB20029AADD /* Supporting Files */, + ); + name = CloudKeychainProxy; + path = ../CloudKeychainProxy; + sourceTree = ""; + }; + 5272501716838BB20029AADD /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + BEF9640718B417EB00813FA3 /* SharedWebCredentialAgent */ = { + isa = PBXGroup; + children = ( + BEF9640918B418A400813FA3 /* swcagent_client.h */, + BEF9640A18B418A400813FA3 /* swcagent_client.c */, + BEF9640B18B418A400813FA3 /* swcagent.m */, + ); + name = SharedWebCredentialAgent; + sourceTree = ""; + }; + E71049F4169E023B00DB0045 /* SecurityTool */ = { + isa = PBXGroup; + children = ( + E790C108169E4E7900E0C0C9 /* builtin_commands.h */, + E790C109169E4FD200E0C0C9 /* digest_calc.c */, + E790C10E169E53DF00E0C0C9 /* leaks.c */, + E790C10F169E53DF00E0C0C9 /* leaks.h */, + 4CD1897B169F835400BC96B8 /* print_cert.c */, + 4CD1897C169F835400BC96B8 /* print_cert.h */, + E71049FE169E036E00DB0045 /* security.1 */, + E71049FF169E036E00DB0045 /* SecurityTool.c */, + E7104A00169E036E00DB0045 /* SecurityTool.h */, + E7104A0D169E1C1600DB0045 /* tool_errors.h */, + ); + path = SecurityTool; + sourceTree = ""; + }; + E7104A0F169E1F0800DB0045 /* Tool */ = { + isa = PBXGroup; + children = ( + F697632118F6CC3F0090438B /* keychain_util.c */, + F697632218F6CC3F0090438B /* keychain_util.h */, + E790C136169E5C6200E0C0C9 /* add_internet_password.c */, + E795C93E19100F5000FA068C /* log_control.c */, + E790C137169E5C6200E0C0C9 /* codesign.c */, + E790C138169E5C6200E0C0C9 /* keychain_add.c */, + E790C139169E5C6200E0C0C9 /* keychain_find.c */, + 0CE7ABDE171383E30088968F /* keychain_backup.c */, + E790C13A169E5C6200E0C0C9 /* pkcs12_util.c */, + E790C13D169E5C6200E0C0C9 /* scep.c */, + E790C13E169E5C6200E0C0C9 /* SecurityCommands.h */, + E790C13F169E5C6200E0C0C9 /* show_certificates.c */, + E790C140169E5C6200E0C0C9 /* spc.c */, + ); + path = Tool; + sourceTree = ""; + }; + E7217B2015F8126700D26031 /* CKBridge */ = { + isa = PBXGroup; + children = ( + 521C685C1614A6E100E31C3E /* SOSCloudKeychainClient.c */, + 521C685D1614A6E100E31C3E /* SOSCloudKeychainClient.h */, + E7217B2515F8131A00D26031 /* SOSCloudKeychainConstants.c */, + E7217B2615F8131A00D26031 /* SOSCloudKeychainConstants.h */, + 52849FC2164498C9005CDF23 /* SOSARCDefines.h */, + ); + path = CKBridge; + sourceTree = ""; + }; + E7295C6614E356FE007FBB20 /* Hacks */ = { + isa = PBXGroup; + children = ( + E7295C6714E3571A007FBB20 /* Empty.c */, + 4C8940DA166EA8CF00241770 /* osxshim.c */, + ); + name = Hacks; + sourceTree = ""; + }; + E7AC69CE14E1F78400CB09C1 /* SOSCircle */ = { + isa = PBXGroup; + children = ( + E7FEFB81169E362100E18152 /* Tool */, + E7295C6614E356FE007FBB20 /* Hacks */, + E7AC69CF14E1F78400CB09C1 /* Regressions */, + E7AC69D114E1F78400CB09C1 /* SecureObjectSync */, + 5272501416838BB20029AADD /* CloudKeychainProxy */, + E7217B2015F8126700D26031 /* CKBridge */, + ); + path = SOSCircle; + sourceTree = ""; + }; + E7AC69CF14E1F78400CB09C1 /* Regressions */ = { + isa = PBXGroup; + children = ( + 521C0CD915FFA05000604B61 /* CKDKeyValueStore.h */, + 521C0CDA15FFA05000604B61 /* CKDKeyValueStore.m */, + 522B0ED11648809300A4675D /* sc-103-syncupdate.c */, + 48CE733D1731C49A004C2946 /* sc-130-resignationticket.c */, + E763D6221624E2670038477D /* sc-20-keynames.c */, + E777C72815B9C9F0004044A8 /* sc-30-peerinfo.c */, + EBDAECBA184D30C3005A18F1 /* sc-31-peerinfo-simplefuzz.c */, + E777C6B015B4DDF2004044A8 /* sc-40-circle.c */, + 4878267919C0F505002CB56F /* sc-42-circlegencount.c */, + E7BE10A5167AB2BF00D2A178 /* sc-41-cloudcircle.c */, + 4C64F59617C6B3B1009C5AC2 /* sc-45-digestvector.c */, + 4C8322EA17B7E01E005B620A /* sc-50-message.c */, + 5253946016608F6800BA9687 /* sc-51-persistentEC.c */, + 4C6ED19115CB0E26004379B7 /* sc-60-peer.c */, + 4C6ED19415CB0E43004379B7 /* sc-70-engine.c */, + 4C4EBD531610D7D8007D06A5 /* sc-75-circle-engine.c */, + 521C0A7315F908A700604B61 /* sc-90-ckdclient.c */, + 521C691E16164B9900E31C3E /* sc-95-ckd2client.c */, + 4CC92AAF15A3ACE600C6D578 /* SOSCircle_regressions.h */, + 521C0CD515FF9B3300604B61 /* SOSRegressionUtilities.c */, + 521C0CD815FF9B4B00604B61 /* SOSRegressionUtilities.h */, + 4CB8A83716164B7700B52EC7 /* SOSTestDataSource.c */, + 4CB8A83916164B8C00B52EC7 /* SOSTestDataSource.h */, + 4C495EDB1982125E00BC1809 /* SOSTestDevice.c */, + 4C495EDC1982125E00BC1809 /* SOSTestDevice.h */, + ); + path = Regressions; + sourceTree = ""; + }; + E7AC69D114E1F78400CB09C1 /* SecureObjectSync */ = { + isa = PBXGroup; + children = ( + 4CC929AD15A3957800C6D578 /* SOSAccount.c */, + 4CC929AE15A3957800C6D578 /* SOSAccount.h */, + 48764AF417FA3FE50005C4F1 /* SOSAccountCircles.c */, + 48C7DF9917FF44EF00904F1A /* SOSAccountCloudParameters.c */, + 48C7DF9217FF2DB500904F1A /* SOSAccountCredentials.c */, + 48764AE717FA2DD00005C4F1 /* SOSAccountDer.c */, + 48C7DF9717FF360F00904F1A /* SOSAccountFullPeerInfo.c */, + 48C7DF9517FF351A00904F1A /* SOSAccountPeers.c */, + 48764AEB17FA31E50005C4F1 /* SOSAccountPersistence.c */, + 48764AEA17FA31670005C4F1 /* SOSAccountPriv.h */, + 48764AEE17FA36200005C4F1 /* SOSAccountUpdate.c */, + 4CC929AF15A3957800C6D578 /* SOSCircle.c */, + 4CC929B015A3957800C6D578 /* SOSCircle.h */, + E7217B1715F80E0F00D26031 /* SOSCloudCircle.c */, + E703811114E1FEE4007CB458 /* SOSCloudCircle.h */, + E7B01B5A16532507000485F1 /* SOSCloudCircleInternal.h */, + 488902EB16C2F88400F119FF /* SOSCoder.c */, + 488902ED16C2F89700F119FF /* SOSCoder.h */, + 4C8BDD9A17B4FB8F00C20EA5 /* SOSDataSource.h */, + 4C8BDDA017B4FE8100C20EA5 /* SOSDigestVector.c */, + 4C8BDDA117B4FE9400C20EA5 /* SOSDigestVector.h */, + 4C9DC91C15B602910036D941 /* SOSEngine.c */, + 4C9DC91915B602760036D941 /* SOSEngine.h */, + E7B00702170B5FE100B27966 /* SOSExports.exp-in */, + E79277E1163B110A0096F3E2 /* SOSFullPeerInfo.c */, + E79277E2163B110A0096F3E2 /* SOSFullPeerInfo.h */, + E777C71D15B73F9E004044A8 /* SOSInternal.c */, + E777C71B15B73F59004044A8 /* SOSInternal.h */, + 48764AF117FA3ACF0005C4F1 /* SOSKVSKeys.c */, + CD0F8AF118998685003E0C52 /* SOSKVSKeys.h */, + 4C8BDD9E17B4FDE100C20EA5 /* SOSManifest.c */, + 4C8BDD9C17B4FD2A00C20EA5 /* SOSManifest.h */, + 4CBDB30B17B70206002FA799 /* SOSMessage.c */, + 4CBDB30C17B70206002FA799 /* SOSMessage.h */, + 4CC929B115A3957800C6D578 /* SOSPeer.c */, + 4CC929B215A3957800C6D578 /* SOSPeer.h */, + CD32776A18F8AEFD006B5280 /* SOSPeerCoder.c */, + CD32776C18F8B06E006B5280 /* SOSPeerCoder.h */, + E777C72515B87544004044A8 /* SOSPeerInfo.c */, + E777C72415B87528004044A8 /* SOSPeerInfo.h */, + E7A634E217FA471500920B67 /* SOSPeerInfoCollections.c */, + E7A634E417FA472700920B67 /* SOSPeerInfoCollections.h */, + 485835871779013E0050F074 /* SOSPeerInfoInternal.h */, + CD86DE4D18BD554D00C90CDF /* SOSTransport.c */, + CDF1B82218BD7DDE006309BC /* SOSTransport.h */, + CD0F8AF51899BF46003E0C52 /* SOSTransportCircle.c */, + CD0F8AF91899BF63003E0C52 /* SOSTransportCircle.h */, + CD32777218F8B31E006B5280 /* SOSTransportCircleKVS.c */, + CD32777418F8B330006B5280 /* SOSTransportCircleKVS.h */, + CD09B90718A08EBE00E787E1 /* SOSTransportKeyParameter.c */, + CD09B90918A08ECD00E787E1 /* SOSTransportKeyParameter.h */, + CD32776E18F8B2FC006B5280 /* SOSTransportKeyParameterKVS.c */, + CD32777018F8B30E006B5280 /* SOSTransportKeyParameterKVS.h */, + CD0F8AF31899BF33003E0C52 /* SOSTransportMessage.c */, + CD0F8AF71899BF57003E0C52 /* SOSTransportMessage.h */, + CD32777618F8B39B006B5280 /* SOSTransportMessageKVS.c */, + CD32777818F8B3B4006B5280 /* SOSTransportMessageKVS.h */, + 4802A59516D711060059E5B9 /* SOSUserKeygen.c */, + 4802A59716D711190059E5B9 /* SOSUserKeygen.h */, + ); + path = SecureObjectSync; + sourceTree = ""; + }; + E7FEFB81169E362100E18152 /* Tool */ = { + isa = PBXGroup; + children = ( + E790C0F4169E3D7200E0C0C9 /* SOSCommands.h */, + E7FEFB90169E36D800E18152 /* keychain_sync.c */, + ); + path = Tool; + sourceTree = ""; + }; + EB973202189C56310063DFED /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + EB973203189C56310063DFED /* Foundation.framework */, + EB973204189C56310063DFED /* CoreData.framework */, + EB973205189C56310063DFED /* AppKit.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 0C0BDB5A175687EC00BC1A7E /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ACFD56BE19007B2D00F5F5D9 /* ios6_1_keychain_2_db.h in Headers */, + CD95312D19228D96005A76B2 /* SOSAccountTesting.h in Headers */, + 0C0BDB611756882A00BC1A7E /* secd_regressions.h in Headers */, + CDAD4E9E18EC9B6D007D4BC2 /* SOSTransportTestTransports.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18270F5314CF651900B05E7F /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 186CDD0D14CA116C00AF9171 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 18AD560F14CB6E7A008233F2 /* securityd_client.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18D4043314CE0CF300A2BE4E /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + CDC765C41729A72800721712 /* SecPasswordGenerate.h in Headers */, + 4A971695158FDEB800D439B7 /* SecOTR.h in Headers */, + 4A971697158FDEB800D439B7 /* SecOTRDHKey.h in Headers */, + 4A971698158FDEB800D439B7 /* SecOTRErrors.h in Headers */, + 4A97169A158FDEB800D439B7 /* SecOTRIdentityPriv.h in Headers */, + 4A97169C158FDEB800D439B7 /* SecOTRMath.h in Headers */, + 4A97169F158FDEB800D439B7 /* SecOTRPacketData.h in Headers */, + 4A9716A1158FDEB800D439B7 /* SecOTRPackets.h in Headers */, + 4A9716A4158FDEB800D439B7 /* SecOTRSession.h in Headers */, + 4A9716A6158FDEB800D439B7 /* SecOTRSessionPriv.h in Headers */, + 52D0F028169CA72800F07D79 /* SecOnOSX.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18D4056014CE53C200A2BE4E /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 72B5923B17C6924000AE738B /* iCloudTrace.h in Headers */, + 4C05608E17B60F88001A879A /* SecItemSchema.h in Headers */, + 4C05608F17B60F88001A879A /* SecKeybagSupport.h in Headers */, + 4C05608C17B60F88001A879A /* SecItemDataSource.h in Headers */, + 4C05608D17B60F88001A879A /* SecItemDb.h in Headers */, + 4C05608A17B60F88001A879A /* SecDbKeychainItem.h in Headers */, + 4C05608B17B60F88001A879A /* SecDbQuery.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4A5CCA4D15ACEFA500702357 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4A824AFF158FF07000F932C0 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4CC92AC015A3BC4300C6D578 /* Security_regressions.h in Headers */, + 4CC92A8C15A3ABD400C6D578 /* getcacert-mdes.h in Headers */, + 4CC92A8D15A3ABD400C6D578 /* getcacert-mdesqa.h in Headers */, + 4CC92A8F15A3ABD400C6D578 /* si-63-scep.h in Headers */, + 4CC92A9015A3ABD400C6D578 /* attached_no_data_signed_data.h in Headers */, + 4CC92A9115A3ABD400C6D578 /* attached_signed_data.h in Headers */, + 4CC92A9215A3ABD400C6D578 /* detached_content.h in Headers */, + 4CC92A9315A3ABD400C6D578 /* detached_signed_data.h in Headers */, + 4CC92A9415A3ABD400C6D578 /* privkey.h in Headers */, + 4CC92A9515A3ABD400C6D578 /* signer.h in Headers */, + 4CC92A9815A3ABD400C6D578 /* signed-receipt.h in Headers */, + 4CC92A9A15A3ABD400C6D578 /* Global Trustee.cer.h in Headers */, + 4CC92A9B15A3ABD400C6D578 /* UTN-USERFirst-Hardware.cer.h in Headers */, + 4CC92A9C15A3ABD400C6D578 /* addons.mozilla.org.cer.h in Headers */, + 4CC92A9D15A3ABD400C6D578 /* login.live.com.cer.h in Headers */, + 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 */, + 4CC92AA115A3ABD400C6D578 /* login.yahoo.com.cer.h in Headers */, + 4CC92AA215A3ABD400C6D578 /* mail.google.com.cer.h in Headers */, + 4CC92AA315A3ABD400C6D578 /* www.google.com.cer.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CC92AFB15A3BC6B00C6D578 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + CDAD4E9C18EC9B3D007D4BC2 /* SOSAccountTesting.h in Headers */, + 4CC92B1515A3BCA500C6D578 /* securityd_regressions.h in Headers */, + CD95312C19228D92005A76B2 /* SOSTransportTestTransports.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BEF9640218B4171200813FA3 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + BE4AC9B518B8022D00B84964 /* swcagent_client.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E702E75014E1F3EA00CDE635 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + CD0F8AFA1899BF63003E0C52 /* SOSTransportCircle.h in Headers */, + E703811514E1FEEF007CB458 /* SOSCloudCircle.h in Headers */, + 4CC929B415A3957800C6D578 /* SOSAccount.h in Headers */, + 4CC929B615A3957800C6D578 /* SOSCircle.h in Headers */, + 4CC929B815A3957800C6D578 /* SOSPeer.h in Headers */, + 4C9DC91A15B602760036D941 /* SOSEngine.h in Headers */, + CD0F8AF218998685003E0C52 /* SOSKVSKeys.h in Headers */, + E777C71C15B73F59004044A8 /* SOSInternal.h in Headers */, + 4C8BDD9B17B4FB8F00C20EA5 /* SOSDataSource.h in Headers */, + CD32777918F8B3B4006B5280 /* SOSTransportMessageKVS.h in Headers */, + 4C8BDD9D17B4FD2A00C20EA5 /* SOSManifest.h in Headers */, + 4802A59816D7156D0059E5B9 /* SOSUserKeygen.h in Headers */, + CD09B90A18A08ECD00E787E1 /* SOSTransportKeyParameter.h in Headers */, + E777C72715B882E5004044A8 /* SOSPeerInfo.h in Headers */, + 4CBDB30F17B70306002FA799 /* SOSCoder.h in Headers */, + CD0F8AF81899BF57003E0C52 /* SOSTransportMessage.h in Headers */, + CD32776D18F8B06E006B5280 /* SOSPeerCoder.h in Headers */, + CD32777518F8B330006B5280 /* SOSTransportCircleKVS.h in Headers */, + 4CBDB31017B70323002FA799 /* SOSPeerInfoInternal.h in Headers */, + CDF1B82318BD7DDE006309BC /* SOSTransport.h in Headers */, + E7217B2815F8131A00D26031 /* SOSCloudKeychainConstants.h in Headers */, + 521C68601614A6E100E31C3E /* SOSCloudKeychainClient.h in Headers */, + 4CBDB30E17B70206002FA799 /* SOSMessage.h in Headers */, + E79277E4163B110A0096F3E2 /* SOSFullPeerInfo.h in Headers */, + E7B01B5B16532507000485F1 /* SOSCloudCircleInternal.h in Headers */, + CD32777118F8B30E006B5280 /* SOSTransportKeyParameterKVS.h in Headers */, + 4C8BDDA217B4FE9400C20EA5 /* SOSDigestVector.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E702E77214E1F48800CDE635 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C495EDE1982125E00BC1809 /* SOSTestDevice.h in Headers */, + 521C0CDD15FFA05100604B61 /* CKDKeyValueStore.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E76079C31951FD2800F69731 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 0C0BDB55175687EC00BC1A7E /* libsecdRegressions */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0C0BDB5C175687EC00BC1A7E /* Build configuration list for PBXNativeTarget "libsecdRegressions" */; + buildPhases = ( + 0C0BDB56175687EC00BC1A7E /* Sources */, + 0C0BDB59175687EC00BC1A7E /* Frameworks */, + 0C0BDB5A175687EC00BC1A7E /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libsecdRegressions; + productName = security; + productReference = 0C0BDB5F175687EC00BC1A7E /* libsecdRegressions.a */; + productType = "com.apple.product-type.library.static"; + }; + 18270F5414CF651900B05E7F /* libsecipc_client */ = { + isa = PBXNativeTarget; + buildConfigurationList = 18270F5614CF651900B05E7F /* Build configuration list for PBXNativeTarget "libsecipc_client" */; + buildPhases = ( + 18270F5114CF651900B05E7F /* Sources */, + 18270F5214CF651900B05E7F /* Frameworks */, + 18270F5314CF651900B05E7F /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libsecipc_client; + productName = libsecipc_client; + productReference = 18270F5514CF651900B05E7F /* libsecipc_client.a */; + productType = "com.apple.product-type.library.static"; + }; + 186CDD0E14CA116C00AF9171 /* libSecItemShimOSX */ = { + isa = PBXNativeTarget; + buildConfigurationList = 186CDD1314CA116C00AF9171 /* Build configuration list for PBXNativeTarget "libSecItemShimOSX" */; + buildPhases = ( + 186CDD0B14CA116C00AF9171 /* Sources */, + 186CDD0C14CA116C00AF9171 /* Frameworks */, + 186CDD0D14CA116C00AF9171 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libSecItemShimOSX; + productName = sec; + productReference = 186CDD0F14CA116C00AF9171 /* libSecItemShimOSX.a */; + productType = "com.apple.product-type.library.static"; + }; + 18D4043414CE0CF300A2BE4E /* libsecurity */ = { + isa = PBXNativeTarget; + buildConfigurationList = 18D4043614CE0CF300A2BE4E /* Build configuration list for PBXNativeTarget "libsecurity" */; + buildPhases = ( + 18D4043114CE0CF300A2BE4E /* Sources */, + 18D4043214CE0CF300A2BE4E /* Frameworks */, + 18D4043314CE0CF300A2BE4E /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libsecurity; + productName = security; + productReference = 18D4043514CE0CF300A2BE4E /* libsecurity.a */; + productType = "com.apple.product-type.library.static"; + }; + 18D4056114CE53C200A2BE4E /* libsecurityd */ = { + isa = PBXNativeTarget; + buildConfigurationList = 18D4056314CE53C200A2BE4E /* Build configuration list for PBXNativeTarget "libsecurityd" */; + buildPhases = ( + 18D4055E14CE53C200A2BE4E /* Sources */, + 18D4055F14CE53C200A2BE4E /* Frameworks */, + 18D4056014CE53C200A2BE4E /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libsecurityd; + productName = securityd; + productReference = 18D4056214CE53C200A2BE4E /* libsecurityd.a */; + productType = "com.apple.product-type.library.static"; + }; + 4A5CCA4E15ACEFA500702357 /* libSecOtrOSX */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4A5CCA5215ACEFA500702357 /* Build configuration list for PBXNativeTarget "libSecOtrOSX" */; + buildPhases = ( + 4A5CCA4B15ACEFA500702357 /* Sources */, + 4A5CCA4C15ACEFA500702357 /* Frameworks */, + 4A5CCA4D15ACEFA500702357 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libSecOtrOSX; + productName = libSecOtrOSX; + productReference = 4A5CCA4F15ACEFA500702357 /* libSecOtrOSX.a */; + productType = "com.apple.product-type.library.static"; + }; + 4A824AFB158FF07000F932C0 /* libSecurityRegressions */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4A824B00158FF07000F932C0 /* Build configuration list for PBXNativeTarget "libSecurityRegressions" */; + buildPhases = ( + 4A824AFC158FF07000F932C0 /* Sources */, + 4A824AFE158FF07000F932C0 /* Frameworks */, + 4A824AFF158FF07000F932C0 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libSecurityRegressions; + productName = security; + productReference = 4A824B03158FF07000F932C0 /* libSecurityRegressions.a */; + productType = "com.apple.product-type.library.static"; + }; + 4CC92AC215A3BC6B00C6D578 /* libsecuritydRegressions */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4CC92B1115A3BC6B00C6D578 /* Build configuration list for PBXNativeTarget "libsecuritydRegressions" */; + buildPhases = ( + 4CC92AC315A3BC6B00C6D578 /* Sources */, + 4CC92AFA15A3BC6B00C6D578 /* Frameworks */, + 4CC92AFB15A3BC6B00C6D578 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libsecuritydRegressions; + productName = security; + productReference = 4CC92B1415A3BC6B00C6D578 /* libsecuritydRegressions.a */; + productType = "com.apple.product-type.library.static"; + }; + 5284029F164445760035F320 /* libCloudKeychainProxy */ = { + isa = PBXNativeTarget; + buildConfigurationList = 528402A9164445760035F320 /* Build configuration list for PBXNativeTarget "libCloudKeychainProxy" */; + buildPhases = ( + 5284029C164445760035F320 /* Sources */, + 5284029D164445760035F320 /* Frameworks */, + 5284029E164445760035F320 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libCloudKeychainProxy; + productName = libCloudKeychainProxy; + productReference = 528402A0164445760035F320 /* libCloudKeychainProxy.a */; + productType = "com.apple.product-type.library.static"; + }; + BEF963FE18B4171200813FA3 /* libSWCAgent */ = { + isa = PBXNativeTarget; + buildConfigurationList = BEF9640318B4171200813FA3 /* Build configuration list for PBXNativeTarget "libSWCAgent" */; + buildPhases = ( + BEF963FF18B4171200813FA3 /* Sources */, + BEF9640118B4171200813FA3 /* Frameworks */, + BEF9640218B4171200813FA3 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libSWCAgent; + productName = libsecipc_client; + productReference = BEF9640618B4171200813FA3 /* libSWCAgent.a */; + productType = "com.apple.product-type.library.static"; + }; + E702E73514E1F3EA00CDE635 /* libSecureObjectSync */ = { + isa = PBXNativeTarget; + buildConfigurationList = E702E75314E1F3EA00CDE635 /* Build configuration list for PBXNativeTarget "libSecureObjectSync" */; + buildPhases = ( + E702E73614E1F3EA00CDE635 /* Sources */, + E702E74F14E1F3EA00CDE635 /* Frameworks */, + E702E75014E1F3EA00CDE635 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libSecureObjectSync; + productName = security; + productReference = E702E75614E1F3EA00CDE635 /* libSecureObjectSync.a */; + productType = "com.apple.product-type.library.static"; + }; + E702E75714E1F48800CDE635 /* libSOSRegressions */ = { + isa = PBXNativeTarget; + buildConfigurationList = E702E77514E1F48800CDE635 /* Build configuration list for PBXNativeTarget "libSOSRegressions" */; + buildPhases = ( + E702E75814E1F48800CDE635 /* Sources */, + E702E77114E1F48800CDE635 /* Frameworks */, + E702E77214E1F48800CDE635 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libSOSRegressions; + productName = security; + productReference = E702E77814E1F48800CDE635 /* libSOSRegressions.a */; + productType = "com.apple.product-type.library.static"; + }; + E71049F1169E023B00DB0045 /* libSecurityTool */ = { + isa = PBXNativeTarget; + buildConfigurationList = E71049FD169E023B00DB0045 /* Build configuration list for PBXNativeTarget "libSecurityTool" */; + buildPhases = ( + E71049EE169E023B00DB0045 /* Sources */, + E71049EF169E023B00DB0045 /* Frameworks */, + E71049F0169E023B00DB0045 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libSecurityTool; + productName = SecurityTool; + productReference = E71049F2169E023B00DB0045 /* libSecurityTool.a */; + productType = "com.apple.product-type.library.static"; + }; + E7104A12169E216E00DB0045 /* libSecurityCommands */ = { + isa = PBXNativeTarget; + buildConfigurationList = E7104A1A169E216E00DB0045 /* Build configuration list for PBXNativeTarget "libSecurityCommands" */; + buildPhases = ( + E7104A13169E216E00DB0045 /* Sources */, + E7104A17169E216E00DB0045 /* Frameworks */, + E7104A19169E216E00DB0045 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libSecurityCommands; + productName = SecurityTool; + productReference = E7104A1D169E216E00DB0045 /* libSecurityCommands.a */; + productType = "com.apple.product-type.library.static"; + }; + E76079971951FD2800F69731 /* liblogging */ = { + isa = PBXNativeTarget; + buildConfigurationList = E76079CF1951FD2800F69731 /* Build configuration list for PBXNativeTarget "liblogging" */; + buildPhases = ( + E76079981951FD2800F69731 /* Sources */, + E76079C21951FD2800F69731 /* Frameworks */, + E76079C31951FD2800F69731 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = liblogging; + productName = security; + productReference = E76079D21951FD2800F69731 /* liblogging.a */; + productType = "com.apple.product-type.library.static"; + }; + E7FEFB82169E363300E18152 /* libSOSCommands */ = { + isa = PBXNativeTarget; + buildConfigurationList = E7FEFB89169E363300E18152 /* Build configuration list for PBXNativeTarget "libSOSCommands" */; + buildPhases = ( + E7FEFB83169E363300E18152 /* Sources */, + E7FEFB86169E363300E18152 /* Frameworks */, + E7FEFB88169E363300E18152 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libSOSCommands; + productName = SecurityTool; + productReference = E7FEFB8C169E363300E18152 /* libSOSCommands.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 186CDD0614CA116C00AF9171 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0600; + }; + buildConfigurationList = 186CDD0914CA116C00AF9171 /* Build configuration list for PBXProject "sec" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 186CDD0414CA116C00AF9171; + productRefGroup = 186CDD1014CA116C00AF9171 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 18D4043414CE0CF300A2BE4E /* libsecurity */, + 18D4056114CE53C200A2BE4E /* libsecurityd */, + 186CDD0E14CA116C00AF9171 /* libSecItemShimOSX */, + 18270F5414CF651900B05E7F /* libsecipc_client */, + E702E73514E1F3EA00CDE635 /* libSecureObjectSync */, + E702E75714E1F48800CDE635 /* libSOSRegressions */, + 4A824AFB158FF07000F932C0 /* libSecurityRegressions */, + 4CC92AC215A3BC6B00C6D578 /* libsecuritydRegressions */, + 4A5CCA4E15ACEFA500702357 /* libSecOtrOSX */, + 5284029F164445760035F320 /* libCloudKeychainProxy */, + E71049F1169E023B00DB0045 /* libSecurityTool */, + E7104A12169E216E00DB0045 /* libSecurityCommands */, + E7FEFB82169E363300E18152 /* libSOSCommands */, + 0C0BDB55175687EC00BC1A7E /* libsecdRegressions */, + BEF963FE18B4171200813FA3 /* libSWCAgent */, + E76079971951FD2800F69731 /* liblogging */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 0C0BDB56175687EC00BC1A7E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E7F0D3EA177BBE35001ACBC1 /* secd-55-account-incompatibility.c in Sources */, + 0C0BDB63175688DA00BC1A7E /* secd-01-items.c in Sources */, + 4882C517177521AE0095D04B /* secd-58-password-change.c in Sources */, + E7A10FAE1771249C00C4602F /* secd-57-account-leave.c in Sources */, + E7F18555177A44E000177B23 /* secd-60-account-cloud-identity.c in Sources */, + 5384299418E492A300E91AFE /* secd-70-otr-remote.c in Sources */, + E7F18557177A502900177B23 /* secd-56-account-apply.c in Sources */, + 0C664AE8175951270092D3D9 /* secd-02-upgrade-while-locked.c in Sources */, + 0CBF93F8177B7CFC001E5658 /* secd-03-corrupted-items.c in Sources */, + 0CBF93FC177BA9D9001E5658 /* secd-05-corrupted-items.c in Sources */, + 527258D11981C00F003CFCEC /* secd-70-engine.c in Sources */, + 4C495EDF1982145200BC1809 /* SOSTestDevice.c in Sources */, + 0CBF93F9177B7CFC001E5658 /* secd-04-corrupted-items.c in Sources */, + 4898223A17BDB277003BEF32 /* secd-52-account-changed.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 */, + E79D62BB176798FD005A9743 /* secd-50-account.c in Sources */, + 48E928C5179DD05500A7F755 /* secd-51-account-inflate.c in Sources */, + 4C495EE21982171500BC1809 /* secd-70-engine-corrupt.c in Sources */, + CDAD4E9D18EC9B67007D4BC2 /* SOSTransportTestTransports.c in Sources */, + 486C6C691795F9D600387075 /* secd-61-account-leave-not-in-kansas-anymore.c in Sources */, + E79D62BD176799EE005A9743 /* SOSTestDataSource.c in Sources */, + E79D62BC176799DB005A9743 /* SOSRegressionUtilities.c in Sources */, + E7A10FAC1771246A00C4602F /* secd-55-account-circle.c in Sources */, + E79D62C01767A5BC005A9743 /* SecdTestKeychainUtilities.c in Sources */, + 48F32D7E1777AFA3001B84BA /* secd-59-account-cleanup.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18270F5114CF651900B05E7F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18270F5914CF654400B05E7F /* client.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 186CDD0B14CA116C00AF9171 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18AD566714CB70A8008233F2 /* SecItem.c in Sources */, + BEFE994E14F2E17200356A97 /* SecDH.c in Sources */, + 4C8D8627177A71E80019A804 /* SOSCloudCircle.c in Sources */, + 446BB5E518F83172005D1B83 /* SecAccessControl.c in Sources */, + 4C3CE9E7176005A700B521C2 /* SecuritydXPC.c in Sources */, + 4C8940DB166EA8CF00241770 /* osxshim.c in Sources */, + 4C8D8628177A71FB0019A804 /* SecPasswordGenerate.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18D4043114CE0CF300A2BE4E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18D4043914CE1FE400A2BE4E /* p12import.c in Sources */, + 18D4043A14CE1FE400A2BE4E /* p12pbegen.c in Sources */, + 18D4043B14CE1FE400A2BE4E /* pbkdf2.c in Sources */, + C6766768189884D200E9A12C /* SecAccessControl.c in Sources */, + 18D4043C14CE1FE400A2BE4E /* SecBase64.c in Sources */, + 18D4043D14CE1FE400A2BE4E /* SecCertificate.c in Sources */, + 18D4043E14CE1FE400A2BE4E /* SecCertificatePath.c in Sources */, + 18D4043F14CE1FE400A2BE4E /* SecCertificateRequest.c in Sources */, + 18D4044014CE1FE400A2BE4E /* SecCMS.c in Sources */, + 18D4044114CE1FE400A2BE4E /* SecDH.c in Sources */, + 18D4044214CE1FE400A2BE4E /* SecECKey.c in Sources */, + 18D4044314CE1FE400A2BE4E /* SecFramework.c in Sources */, + 18D4044414CE1FE400A2BE4E /* SecIdentity.c in Sources */, + 4C8322EB17B7E01E005B620A /* sc-50-message.c in Sources */, + 18D4044514CE1FE400A2BE4E /* SecImportExport.c in Sources */, + 18D4044614CE1FE400A2BE4E /* SecItem.c in Sources */, + 18D4044714CE1FE400A2BE4E /* SecItemConstants.c in Sources */, + 18D4044814CE1FE400A2BE4E /* SecKey.c in Sources */, + 18D4044914CE1FE400A2BE4E /* SecPBKDF.c in Sources */, + 18D4044A14CE1FE400A2BE4E /* SecPolicy.c in Sources */, + 4CC07E26171E252300DCB6CE /* SOSCloudCircle.c in Sources */, + 18D4044B14CE1FE400A2BE4E /* SecRSAKey.c in Sources */, + 18D4044C14CE1FE400A2BE4E /* SecSCEP.c in Sources */, + 18D4044D14CE1FE400A2BE4E /* SecTrust.c in Sources */, + 18D4044E14CE1FE400A2BE4E /* SecTrustSettings.c in Sources */, + BE642BB2188F32C200C899A2 /* SecSharedCredential.c in Sources */, + CDC765C21729A72800721712 /* SecPasswordGenerate.c in Sources */, + 18D4044F14CE1FE400A2BE4E /* SecTrustStore.c in Sources */, + 18D4045014CE1FE400A2BE4E /* vmdh.c in Sources */, + 4A971696158FDEB800D439B7 /* SecOTRDHKey.c in Sources */, + E795C9541913F88D00FA068C /* SecServerEncryptionSupport.c in Sources */, + 4A971699158FDEB800D439B7 /* SecOTRFullIdentity.c in Sources */, + 4A97169B158FDEB800D439B7 /* SecOTRMath.c in Sources */, + 4A97169E158FDEB800D439B7 /* SecOTRPacketData.c in Sources */, + 4A9716A0158FDEB800D439B7 /* SecOTRPackets.c in Sources */, + 4A9716A2158FDEB800D439B7 /* SecOTRPublicIdentity.c in Sources */, + 4A9716A3158FDEB800D439B7 /* SecOTRSession.c in Sources */, + 4A9716A5158FDEB800D439B7 /* SecOTRSessionAKE.c in Sources */, + 4A9716A7158FDEB800D439B7 /* SecOTRUtils.c in Sources */, + CD3FD10716C3064B00A83BB6 /* SecuritydXPC.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18D4055E14CE53C200A2BE4E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E795C9481911A41300FA068C /* SecLogSettingsServer.c in Sources */, + 4C055FF717B60F1E001A879A /* SecItemSchema.c in Sources */, + 4C055FF617B60F1E001A879A /* SecItemDb.c in Sources */, + 7249E1CB16C01E5F003D7268 /* OTATrustUtilities.c in Sources */, + 5356520318E3C71000C383C0 /* SecOTRRemote.c in Sources */, + 18D4056614CE53DD00A2BE4E /* asynchttp.c in Sources */, + 18D4056814CE53DD00A2BE4E /* policytree.c in Sources */, + 18D4056914CE53DD00A2BE4E /* SecCAIssuerCache.c in Sources */, + 18D4056A14CE53DD00A2BE4E /* SecCAIssuerRequest.c in Sources */, + 18D4056B14CE53DD00A2BE4E /* SecItemServer.c in Sources */, + 4C3CE9E8176005B500B521C2 /* SecuritydXPC.c in Sources */, + 18D4056C14CE53DD00A2BE4E /* SecOCSPCache.c in Sources */, + 72B5923D17C6939A00AE738B /* iCloudTrace.c in Sources */, + 4C055FF317B60F1E001A879A /* SecDbKeychainItem.c in Sources */, + 18D4056D14CE53DD00A2BE4E /* SecOCSPRequest.c in Sources */, + 18D4056E14CE53DD00A2BE4E /* SecOCSPResponse.c in Sources */, + 18D4056F14CE53DD00A2BE4E /* SecPolicyServer.c in Sources */, + 4C055FF817B60F1E001A879A /* SecKeybagSupport.c in Sources */, + 4C055FF517B60F1E001A879A /* SecItemDataSource.c in Sources */, + 4C055FF417B60F1E001A879A /* SecDbQuery.c in Sources */, + 18D4057014CE53DD00A2BE4E /* SecTrustServer.c in Sources */, + 18D4057114CE53DD00A2BE4E /* SecTrustStoreServer.c in Sources */, + 18D4057214CE547400A2BE4E /* spi.c in Sources */, + E7B01B691655DF20000485F1 /* SOSCloudCircleServer.c in Sources */, + BE5EC1F018C80108005E7682 /* swcagent_client.c in Sources */, + 525394AE1660A30000BA9687 /* SecDbItem.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4A5CCA4B15ACEFA500702357 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4A5CCA5415ACEFD400702357 /* SecOTRDHKey.c in Sources */, + 4A5CCA5515ACEFD400702357 /* SecOTRFullIdentity.c in Sources */, + 4A5CCA5615ACEFD400702357 /* SecOTRMath.c in Sources */, + 4A5CCA5715ACEFD400702357 /* SecOTRPacketData.c in Sources */, + 4A5CCA5815ACEFD400702357 /* SecOTRPackets.c in Sources */, + 4A5CCA5915ACEFD400702357 /* SecOTRPublicIdentity.c in Sources */, + 4A5CCA5A15ACEFD400702357 /* SecOTRSession.c in Sources */, + 4A5CCA5B15ACEFD400702357 /* SecOTRSessionAKE.c in Sources */, + 4A5CCA5C15ACEFD400702357 /* SecOTRUtils.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4A824AFC158FF07000F932C0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BE794826196DBEAD00F4BA63 /* si-81-sectrust-server-auth.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 */, + 4CC92A6215A3ABD400C6D578 /* otr-30-negotiation.c in Sources */, + 4CC92A6315A3ABD400C6D578 /* otr-otrdh.c in Sources */, + 4CC92A6415A3ABD400C6D578 /* otr-packetdata.c in Sources */, + 7DE20930192D29D90066419C /* si-79-smp-cert-policy.c in Sources */, + 4CC92A6515A3ABD400C6D578 /* si-00-find-nothing.c in Sources */, + 4CC92A6615A3ABD400C6D578 /* si-05-add.c in Sources */, + 4CC92A6715A3ABD400C6D578 /* si-10-find-internet.c in Sources */, + 3A70988218CDF648009FD2CC /* si_77_SecAccessControl.c in Sources */, + 4CC92A6815A3ABD400C6D578 /* si-11-update-data.c in Sources */, + 4CC92A6915A3ABD400C6D578 /* si-14-dateparse.c in Sources */, + 4CC92A6A15A3ABD400C6D578 /* si-15-certificate.c in Sources */, + 4406660F19069C67000DA171 /* si-80-empty-data.c in Sources */, + BE061FCF1899E5BD00C739F6 /* si-76-shared-credentials.c in Sources */, + 4CC92A6B15A3ABD400C6D578 /* si-16-ec-certificate.c in Sources */, + 4CC92A6C15A3ABD400C6D578 /* si-20-sectrust-activation.c in Sources */, + 4CC92A6D15A3ABD400C6D578 /* si-20-sectrust.c in Sources */, + BE62D7601747FF3E001EAA9D /* si-72-syncableitems.c in Sources */, + 4CC92A6E15A3ABD400C6D578 /* si-21-sectrust-asr.c in Sources */, + 4CC92A6F15A3ABD400C6D578 /* si-22-sectrust-iap.c in Sources */, + 4CC92A7015A3ABD400C6D578 /* si-23-sectrust-ocsp.c in Sources */, + 4CC92A7115A3ABD400C6D578 /* si-24-sectrust-appleid.c in Sources */, + 5E9E159219642DC4001EB804 /* si-81-item-acl-stress.c in Sources */, + 4CC92A7215A3ABD400C6D578 /* si-24-sectrust-digicert-malaysia.c in Sources */, + 4CC92A7315A3ABD400C6D578 /* si-24-sectrust-diginotar.c in Sources */, + 4CC92A7415A3ABD400C6D578 /* si-24-sectrust-itms.c 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 */, + 4CC92A7715A3ABD400C6D578 /* si-24-sectrust-otatasking.c in Sources */, + 4CC92A7815A3ABD400C6D578 /* si-24-sectrust-shoebox.c in Sources */, + 4CC92A7915A3ABD400C6D578 /* si-25-sectrust-ipsec-eap.c in Sources */, + 4CC92A7A15A3ABD400C6D578 /* si-26-applicationsigning.c in Sources */, + 4CC92A7B15A3ABD400C6D578 /* si-27-sectrust-exceptions.c in Sources */, + 4CC92A7C15A3ABD400C6D578 /* si-28-sectrustsettings.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 */, + 4CC92A7F15A3ABD400C6D578 /* si-31-keychain-bad.c in Sources */, + 4CC92A8015A3ABD400C6D578 /* si-31-keychain-unreadable.c in Sources */, + 4CC92A8215A3ABD400C6D578 /* si-33-keychain-backup.c in Sources */, + 4CC92A8315A3ABD400C6D578 /* si-40-seckey-custom.c in Sources */, + E7CA197A17179EC20065299C /* si-69-keydesc.c in Sources */, + BE62D7621747FF51001EAA9D /* si-70-sectrust-unified.c in Sources */, + 4CC92A8415A3ABD400C6D578 /* si-40-seckey.c in Sources */, + 4CC92A8515A3ABD400C6D578 /* si-41-sececkey.c in Sources */, + E7EBD75819145DF000D0F062 /* so_01_serverencryption.c in Sources */, + 4CC92A8615A3ABD400C6D578 /* si-42-identity.c in Sources */, + 4CC92A8715A3ABD400C6D578 /* si-43-persistent.c in Sources */, + 4CC92A8815A3ABD400C6D578 /* si-50-secrandom.c in Sources */, + 4CC92A8915A3ABD400C6D578 /* si-60-cms.c in Sources */, + 5DE4A7BD17441CCD0036339E /* si-71-mobile-store-policy.c in Sources */, + CDD565A2173193AC00B6B074 /* si-73-secpasswordgenerate.c in Sources */, + 4CC92A8A15A3ABD400C6D578 /* si-61-pkcs12.c in Sources */, + 4CC92A8B15A3ABD400C6D578 /* si-62-csr.c in Sources */, + 4CC92A8E15A3ABD400C6D578 /* si-63-scep.c in Sources */, + 4CC92A9615A3ABD400C6D578 /* si-64-ossl-cms.c in Sources */, + 7255A46C1783333D006A8B9A /* si-74-OTAPKISigner.c in Sources */, + 7255F91417A973D5004A9F38 /* si-75-AppleIDRecordSigning.c in Sources */, + 4CC92A9715A3ABD400C6D578 /* si-65-cms-cert-policy.c in Sources */, + 4CC92A9915A3ABD400C6D578 /* si-66-smime.c in Sources */, + 4CC92AA415A3ABD400C6D578 /* si-67-sectrust-blacklist.c in Sources */, + 4CC92AA515A3ABD400C6D578 /* vmdh-40.c in Sources */, + 4CC92AA615A3ABD400C6D578 /* vmdh-41-example.c in Sources */, + 4CC92AA715A3ABD400C6D578 /* vmdh-42-example2.c in Sources */, + E748744515A61AF800624935 /* si-68-secmatchissuer.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CC92AC315A3BC6B00C6D578 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4CC92AF915A3BC6B00C6D578 /* sd-10-policytree.c in Sources */, + CD95312B19228D8D005A76B2 /* SOSTransportTestTransports.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5284029C164445760035F320 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5214701B16977D7700DF0DB3 /* cloudkeychainproxy.m in Sources */, + 528402AE164446410035F320 /* CKDKVSProxy.m in Sources */, + 528402AF164446410035F320 /* CKDPersistentState.m in Sources */, + 528402B1164446410035F320 /* CKDUserInteraction.m in Sources */, + 528402B2164447610035F320 /* SOSCloudKeychainConstants.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BEF963FF18B4171200813FA3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BE4AC9B618B8038400B84964 /* SecuritydXPC.c in Sources */, + BEF9640D18B418A400813FA3 /* swcagent_client.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E702E73614E1F3EA00CDE635 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4802A59616D711060059E5B9 /* SOSUserKeygen.c in Sources */, + 4CC929B315A3957800C6D578 /* SOSAccount.c in Sources */, + 4CC929B515A3957800C6D578 /* SOSCircle.c in Sources */, + 4CC929B715A3957800C6D578 /* SOSPeer.c in Sources */, + CD32777718F8B39B006B5280 /* SOSTransportMessageKVS.c in Sources */, + CD0F8AF41899BF33003E0C52 /* SOSTransportMessage.c in Sources */, + 48C7DF9A17FF44EF00904F1A /* SOSAccountCloudParameters.c in Sources */, + CD32776F18F8B2FC006B5280 /* SOSTransportKeyParameterKVS.c in Sources */, + CD09B90818A08EBE00E787E1 /* SOSTransportKeyParameter.c in Sources */, + 48764AEF17FA36200005C4F1 /* SOSAccountUpdate.c in Sources */, + 48C7DF9617FF351A00904F1A /* SOSAccountPeers.c in Sources */, + 4C9DC91D15B602910036D941 /* SOSEngine.c in Sources */, + E777C71E15B73F9E004044A8 /* SOSInternal.c in Sources */, + E777C72615B87545004044A8 /* SOSPeerInfo.c in Sources */, + CD86DE4E18BD554D00C90CDF /* SOSTransport.c in Sources */, + 48764AE817FA2DD00005C4F1 /* SOSAccountDer.c in Sources */, + E7217B2715F8131A00D26031 /* SOSCloudKeychainConstants.c in Sources */, + CD32777318F8B31E006B5280 /* SOSTransportCircleKVS.c in Sources */, + 4C65154B17B5A08900691B6A /* SOSDigestVector.c in Sources */, + E7A634E317FA471500920B67 /* SOSPeerInfoCollections.c in Sources */, + E79277E3163B110A0096F3E2 /* SOSFullPeerInfo.c in Sources */, + 48C7DF9317FF2DB500904F1A /* SOSAccountCredentials.c in Sources */, + 52EAF4BE163C52EB00803D0F /* SOSCloudKeychainClient.c in Sources */, + 4C8BDD9F17B4FDE100C20EA5 /* SOSManifest.c in Sources */, + 488902EC16C2F88400F119FF /* SOSCoder.c in Sources */, + 4CBDB30D17B70206002FA799 /* SOSMessage.c in Sources */, + CD0F8AF61899BF46003E0C52 /* SOSTransportCircle.c in Sources */, + CD32776B18F8AEFD006B5280 /* SOSPeerCoder.c in Sources */, + 48C7DF9817FF360F00904F1A /* SOSAccountFullPeerInfo.c in Sources */, + 48764AF517FA3FE50005C4F1 /* SOSAccountCircles.c in Sources */, + 48764AF217FA3ACF0005C4F1 /* SOSKVSKeys.c in Sources */, + 48764AEC17FA31E50005C4F1 /* SOSAccountPersistence.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E702E75814E1F48800CDE635 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C6ED19615CB0E72004379B7 /* sc-30-peerinfo.c in Sources */, + E777C6B115B4DDF2004044A8 /* sc-40-circle.c in Sources */, + 4C8322EC17B7E01E005B620A /* sc-50-message.c in Sources */, + 4C64F59717C6B3B1009C5AC2 /* sc-45-digestvector.c in Sources */, + 4C6ED19715CB0E72004379B7 /* sc-60-peer.c in Sources */, + 4C6ED19515CB0E44004379B7 /* sc-70-engine.c in Sources */, + 521C0A7615F908AF00604B61 /* sc-90-ckdclient.c in Sources */, + 521C0CD615FF9B3300604B61 /* SOSRegressionUtilities.c in Sources */, + 48CE733E1731C49A004C2946 /* sc-130-resignationticket.c in Sources */, + 4878267B19C0F518002CB56F /* sc-42-circlegencount.c in Sources */, + 4C4EBD541610D7D8007D06A5 /* sc-75-circle-engine.c in Sources */, + 4CB8A83816164B7700B52EC7 /* SOSTestDataSource.c in Sources */, + 521C691F16164B9900E31C3E /* sc-95-ckd2client.c in Sources */, + E763D6231624E2670038477D /* sc-20-keynames.c in Sources */, + 522B0ED21648809300A4675D /* sc-103-syncupdate.c in Sources */, + 5253946116608F6800BA9687 /* sc-51-persistentEC.c in Sources */, + 4C495EDD1982125E00BC1809 /* SOSTestDevice.c in Sources */, + EBDAECBC184D32BD005A18F1 /* sc-31-peerinfo-simplefuzz.c in Sources */, + E7BE10A7167AB32300D2A178 /* sc-41-cloudcircle.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E71049EE169E023B00DB0045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0CE7ABDF171383E30088968F /* keychain_backup.c in Sources */, + E7104A01169E036E00DB0045 /* SecurityTool.c in Sources */, + E790C10A169E4FD200E0C0C9 /* digest_calc.c in Sources */, + E790C110169E53DF00E0C0C9 /* leaks.c in Sources */, + 4CD1897D169F835400BC96B8 /* print_cert.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E7104A13169E216E00DB0045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F697632318F6CFD60090438B /* keychain_util.c in Sources */, + E790C141169E5C6200E0C0C9 /* add_internet_password.c in Sources */, + E790C142169E5C6200E0C0C9 /* codesign.c in Sources */, + E790C143169E5C6200E0C0C9 /* keychain_add.c in Sources */, + E790C144169E5C6200E0C0C9 /* keychain_find.c in Sources */, + E795C94019100F6100FA068C /* log_control.c in Sources */, + E790C145169E5C6200E0C0C9 /* pkcs12_util.c in Sources */, + E790C147169E5C6200E0C0C9 /* scep.c in Sources */, + E790C148169E5C6200E0C0C9 /* show_certificates.c in Sources */, + E790C149169E5C6200E0C0C9 /* spc.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E76079981951FD2800F69731 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E76079C11951FD2800F69731 /* SecLogging.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E7FEFB83169E363300E18152 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E7FEFB91169E36D800E18152 /* keychain_sync.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 521C0BAC15FA5DA800604B61 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 521C0BAD15FA5DA800604B61 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 0C0BDB5D175687EC00BC1A7E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Debug; + }; + 0C0BDB5E175687EC00BC1A7E /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Release; + }; + 18270F5714CF651900B05E7F /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + "GCC_PREPROCESSOR_DEFINITIONS[sdk=macosx*]" = ( + "$(inherited)", + "SECITEM_SHIM_OSX=1", + ); + }; + name = Debug; + }; + 18270F5814CF651900B05E7F /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + "GCC_PREPROCESSOR_DEFINITIONS[sdk=macosx*]" = ( + "$(inherited)", + "SECITEM_SHIM_OSX=1", + ); + }; + name = Release; + }; + 186CDD1114CA116C00AF9171 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9814CF1AAD00B05E7F /* debug.xcconfig */; + buildSettings = { + CLANG_STATIC_ANALYZER_MODE = deep; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + RUN_CLANG_STATIC_ANALYZER = YES; + }; + name = Debug; + }; + 186CDD1214CA116C00AF9171 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9A14CF1AAD00B05E7F /* release.xcconfig */; + buildSettings = { + CLANG_STATIC_ANALYZER_MODE = deep; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + RUN_CLANG_STATIC_ANALYZER = YES; + }; + name = Release; + }; + 186CDD1414CA116C00AF9171 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SECITEM_SHIM_OSX=1", + ); + SECITEM_SHIM_OSX = 1; + }; + name = Debug; + }; + 186CDD1514CA116C00AF9171 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SECITEM_SHIM_OSX=1", + ); + SECITEM_SHIM_OSX = 1; + }; + name = Release; + }; + 18D4043714CE0CF300A2BE4E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + CLANG_WARN_CONSTANT_CONVERSION = NO; + CLANG_WARN_ENUM_CONVERSION = NO; + CLANG_WARN_INT_CONVERSION = NO; + COMBINE_HIDPI_IMAGES = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = NO; + }; + name = Debug; + }; + 18D4043814CE0CF300A2BE4E /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + CLANG_WARN_CONSTANT_CONVERSION = NO; + CLANG_WARN_ENUM_CONVERSION = NO; + CLANG_WARN_INT_CONVERSION = NO; + COMBINE_HIDPI_IMAGES = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = NO; + }; + name = Release; + }; + 18D4056414CE53C200A2BE4E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + "FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]" = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks"; + "GCC_PREPROCESSOR_DEFINITIONS[sdk=macosx*]" = ( + "$(inherited)", + "SECITEM_SHIM_OSX=1", + ); + }; + name = Debug; + }; + 18D4056514CE53C200A2BE4E /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + "FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]" = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks"; + "GCC_PREPROCESSOR_DEFINITIONS[sdk=macosx*]" = ( + "$(inherited)", + "SECITEM_SHIM_OSX=1", + ); + }; + name = Release; + }; + 4A5CCA5015ACEFA500702357 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + }; + name = Debug; + }; + 4A5CCA5115ACEFA500702357 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + }; + name = Release; + }; + 4A824B01158FF07000F932C0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Debug; + }; + 4A824B02158FF07000F932C0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Release; + }; + 4CC92B1215A3BC6B00C6D578 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Debug; + }; + 4CC92B1315A3BC6B00C6D578 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Release; + }; + 528402AA164445760035F320 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4C5EA365164C791400A136B8 /* lib-arc-only.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Debug; + }; + 528402AB164445760035F320 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4C5EA365164C791400A136B8 /* lib-arc-only.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Release; + }; + BEF9640418B4171200813FA3 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + "GCC_PREPROCESSOR_DEFINITIONS[sdk=macosx*]" = ( + "$(inherited)", + "SECITEM_SHIM_OSX=1", + ); + PRODUCT_NAME = libSWCAgent; + }; + name = Debug; + }; + BEF9640518B4171200813FA3 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + "GCC_PREPROCESSOR_DEFINITIONS[sdk=macosx*]" = ( + "$(inherited)", + "SECITEM_SHIM_OSX=1", + ); + PRODUCT_NAME = libSWCAgent; + }; + name = Release; + }; + E702E75414E1F3EA00CDE635 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Debug; + }; + E702E75514E1F3EA00CDE635 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Release; + }; + E702E77614E1F48800CDE635 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Debug; + }; + E702E77714E1F48800CDE635 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Release; + }; + E71049FB169E023B00DB0045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Debug; + }; + E71049FC169E023B00DB0045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Release; + }; + E7104A1B169E216E00DB0045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Debug; + }; + E7104A1C169E216E00DB0045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Release; + }; + E76079D01951FD2800F69731 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + CLANG_WARN_CONSTANT_CONVERSION = NO; + CLANG_WARN_ENUM_CONVERSION = NO; + CLANG_WARN_INT_CONVERSION = NO; + COMBINE_HIDPI_IMAGES = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = NO; + }; + name = Debug; + }; + E76079D11951FD2800F69731 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + CLANG_WARN_CONSTANT_CONVERSION = NO; + CLANG_WARN_ENUM_CONVERSION = NO; + CLANG_WARN_INT_CONVERSION = NO; + COMBINE_HIDPI_IMAGES = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = NO; + }; + name = Release; + }; + E7FEFB8A169E363300E18152 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Debug; + }; + E7FEFB8B169E363300E18152 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 0C0BDB5C175687EC00BC1A7E /* Build configuration list for PBXNativeTarget "libsecdRegressions" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0C0BDB5D175687EC00BC1A7E /* Debug */, + 0C0BDB5E175687EC00BC1A7E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 18270F5614CF651900B05E7F /* Build configuration list for PBXNativeTarget "libsecipc_client" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 18270F5714CF651900B05E7F /* Debug */, + 18270F5814CF651900B05E7F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 186CDD0914CA116C00AF9171 /* Build configuration list for PBXProject "sec" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 186CDD1114CA116C00AF9171 /* Debug */, + 186CDD1214CA116C00AF9171 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 186CDD1314CA116C00AF9171 /* Build configuration list for PBXNativeTarget "libSecItemShimOSX" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 186CDD1414CA116C00AF9171 /* Debug */, + 186CDD1514CA116C00AF9171 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 18D4043614CE0CF300A2BE4E /* Build configuration list for PBXNativeTarget "libsecurity" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 18D4043714CE0CF300A2BE4E /* Debug */, + 18D4043814CE0CF300A2BE4E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 18D4056314CE53C200A2BE4E /* Build configuration list for PBXNativeTarget "libsecurityd" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 18D4056414CE53C200A2BE4E /* Debug */, + 18D4056514CE53C200A2BE4E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4A5CCA5215ACEFA500702357 /* Build configuration list for PBXNativeTarget "libSecOtrOSX" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A5CCA5015ACEFA500702357 /* Debug */, + 4A5CCA5115ACEFA500702357 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4A824B00158FF07000F932C0 /* Build configuration list for PBXNativeTarget "libSecurityRegressions" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A824B01158FF07000F932C0 /* Debug */, + 4A824B02158FF07000F932C0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4CC92B1115A3BC6B00C6D578 /* Build configuration list for PBXNativeTarget "libsecuritydRegressions" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4CC92B1215A3BC6B00C6D578 /* Debug */, + 4CC92B1315A3BC6B00C6D578 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 528402A9164445760035F320 /* Build configuration list for PBXNativeTarget "libCloudKeychainProxy" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 528402AA164445760035F320 /* Debug */, + 528402AB164445760035F320 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + BEF9640318B4171200813FA3 /* Build configuration list for PBXNativeTarget "libSWCAgent" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BEF9640418B4171200813FA3 /* Debug */, + BEF9640518B4171200813FA3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E702E75314E1F3EA00CDE635 /* Build configuration list for PBXNativeTarget "libSecureObjectSync" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E702E75414E1F3EA00CDE635 /* Debug */, + E702E75514E1F3EA00CDE635 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E702E77514E1F48800CDE635 /* Build configuration list for PBXNativeTarget "libSOSRegressions" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E702E77614E1F48800CDE635 /* Debug */, + E702E77714E1F48800CDE635 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E71049FD169E023B00DB0045 /* Build configuration list for PBXNativeTarget "libSecurityTool" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E71049FB169E023B00DB0045 /* Debug */, + E71049FC169E023B00DB0045 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E7104A1A169E216E00DB0045 /* Build configuration list for PBXNativeTarget "libSecurityCommands" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E7104A1B169E216E00DB0045 /* Debug */, + E7104A1C169E216E00DB0045 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E76079CF1951FD2800F69731 /* Build configuration list for PBXNativeTarget "liblogging" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E76079D01951FD2800F69731 /* Debug */, + E76079D11951FD2800F69731 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E7FEFB89169E363300E18152 /* Build configuration list for PBXNativeTarget "libSOSCommands" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E7FEFB8A169E363300E18152 /* Debug */, + E7FEFB8B169E363300E18152 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 186CDD0614CA116C00AF9171 /* Project object */; +} diff --git a/sec/securityd/OTATrustUtilities.c b/Security/sec/securityd/OTATrustUtilities.c similarity index 84% rename from sec/securityd/OTATrustUtilities.c rename to Security/sec/securityd/OTATrustUtilities.c index b6423c37..e3eaa575 100644 --- a/sec/securityd/OTATrustUtilities.c +++ b/Security/sec/securityd/OTATrustUtilities.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2003-2004,2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2006-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, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ * * OTATrustUtilities.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -93,12 +94,13 @@ struct index_record typedef struct index_record index_record; -struct _OpaqueSecOTAPKI +struct _OpaqueSecOTAPKI { CFRuntimeBase _base; CFSetRef _blackListSet; CFSetRef _grayListSet; CFArrayRef _escrowCertificates; + CFArrayRef _escrowPCSCertificates; CFDictionaryRef _evPolicyToAnchorMapping; CFDictionaryRef _anchorLookupTable; const char* _anchorTable; @@ -107,20 +109,21 @@ struct _OpaqueSecOTAPKI CFGiblisFor(SecOTAPKI) -static CF_RETURNS_RETAINED CFStringRef SecOTAPKICopyDescription(CFTypeRef cf) +static CF_RETURNS_RETAINED CFStringRef SecOTAPKICopyDescription(CFTypeRef cf) { SecOTAPKIRef otapkiRef = (SecOTAPKIRef)cf; return CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR(""), otapkiRef->_assetVersion); } -static void SecOTAPKIDestroy(CFTypeRef cf) +static void SecOTAPKIDestroy(CFTypeRef cf) { SecOTAPKIRef otapkiref = (SecOTAPKIRef)cf; - + CFReleaseNull(otapkiref->_blackListSet); CFReleaseNull(otapkiref->_grayListSet); CFReleaseNull(otapkiref->_escrowCertificates); - + CFReleaseNull(otapkiref->_escrowPCSCertificates); + CFReleaseNull(otapkiref->_evPolicyToAnchorMapping); CFReleaseNull(otapkiref->_anchorLookupTable); @@ -132,18 +135,18 @@ static CFDataRef SecOTACopyFileContents(const char *path) CFMutableDataRef data = NULL; int fd = open(path, O_RDONLY, 0666); - if (fd == -1) + if (fd == -1) { goto badFile; } off_t fsize = lseek(fd, 0, SEEK_END); - if (fsize == (off_t)-1) + if (fsize == (off_t)-1) { goto badFile; } - if (fsize > (off_t)INT32_MAX) + if (fsize > (off_t)INT32_MAX) { goto badFile; } @@ -153,25 +156,25 @@ static CFDataRef SecOTACopyFileContents(const char *path) { goto badFile; } - + CFDataSetLength(data, (CFIndex)fsize); void *buf = CFDataGetMutableBytePtr(data); if (NULL == buf) { goto badFile; } - + off_t total_read = 0; - while (total_read < fsize) + while (total_read < fsize) { ssize_t bytes_read; bytes_read = pread(fd, buf, (size_t)(fsize - total_read), total_read); - if (bytes_read == -1) + if (bytes_read == -1) { goto badFile; } - if (bytes_read == 0) + if (bytes_read == 0) { goto badFile; } @@ -182,16 +185,16 @@ static CFDataRef SecOTACopyFileContents(const char *path) return data; badFile: - if (fd != -1) + if (fd != -1) { close(fd); } if (data) - { + { CFRelease(data); } - + return NULL; } @@ -200,16 +203,16 @@ static Boolean PathExists(const char* path, size_t* pFileSize) TestOTALog("In PathExists: checking path %s\n", path); Boolean result = false; struct stat sb; - + if (NULL != pFileSize) { *pFileSize = 0; } - + int stat_result = stat(path, &sb); result = (stat_result == 0); - - + + if (result) { TestOTALog("In PathExists: stat returned 0 for %s\n", path); @@ -239,52 +242,52 @@ static Boolean PathExists(const char* path, size_t* pFileSize) case EACCES: TestOTALog("In PathExists: stat failed because of EACCES\n"); break; - + case EBADF: TestOTALog("In PathExists: stat failed because of EBADF (Not likely)\n"); break; - + case EFAULT: TestOTALog("In PathExists: stat failed because of EFAULT (huh?)\n"); break; - + case ELOOP: TestOTALog("In PathExists: stat failed because of ELOOP (huh?)\n"); break; - + case ENAMETOOLONG: TestOTALog("In PathExists: stat failed because of ENAMETOOLONG (huh?)\n"); break; - + case ENOENT: TestOTALog("In PathExists: stat failed because of ENOENT (missing?)\n"); break; - + case ENOMEM: TestOTALog("In PathExists: stat failed because of ENOMEM (really?)\n"); break; - + case ENOTDIR: TestOTALog("In PathExists: stat failed because of ENOTDIR (really?)\n"); break; - + case EOVERFLOW: TestOTALog("In PathExists: stat failed because of EOVERFLOW (really?)\n"); break; - + default: TestOTALog("In PathExists: unknown errno of %d\n", local_errno); break; } } #endif // #if VERBOSE_LOGGING - + return result; } static int unlink_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { - int rv = remove(fpath); + int rv = remove(fpath); return rv; } @@ -293,7 +296,7 @@ static int rmrf(char *path) const char* p1 = NULL; char path_buffer[PATH_MAX]; memset(path_buffer, 0, sizeof(path_buffer)); - + p1 = realpath(path, path_buffer); if (!strncmp(path, p1, PATH_MAX)) { @@ -306,14 +309,38 @@ static const char* InitOTADirectory(int* pAssetVersion) { TestOTALog("In InitOTADirectory\n"); const char* result = NULL; - + char buffer[PATH_MAX]; DIR *dp; struct dirent *ep; int version = 0; int current_version = 0; + int system_asset_version = 0; CFIndex asset_number = 0; - + + // Look in the resources for a AssetVerstion.plst file + // This is needed to be done to ensure that a software update did not put down a + // A version of the trust store that is greater than the OTA assets + CFDataRef assetVersionData = SecFrameworkCopyResourceContents(CFSTR("AssetVersion"), CFSTR("plist"), NULL); + if (NULL != assetVersionData) + { + CFPropertyListFormat propFormat; + CFDictionaryRef versionPlist = CFPropertyListCreateWithData(kCFAllocatorDefault, assetVersionData, 0, &propFormat, NULL); + if (NULL != versionPlist && CFDictionaryGetTypeID() == CFGetTypeID(versionPlist)) + { + CFNumberRef versionNumber = (CFNumberRef)CFDictionaryGetValue(versionPlist, (const void *)CFSTR("VersionNumber")); + if (NULL != versionNumber) + { + CFNumberGetValue(versionNumber, kCFNumberCFIndexType, &asset_number); + system_asset_version = (int)asset_number; + } + } + CFReleaseSafe(versionPlist); + CFReleaseSafe(assetVersionData); + } + + // Now check to see if the OTA asset directory exists if it does then + // Get the greatest asset number in the OTA asset directory bool assetDirectoryExists = PathExists(kBaseAssertDirectory, NULL); if (assetDirectoryExists) { @@ -332,7 +359,7 @@ static const char* InitOTADirectory(int* pAssetVersion) snprintf(buffer, sizeof(buffer), "%s%s", kVersionDirectoryNamePrefix, kNumberString); sscanf(ep->d_name, buffer, &version); - + TestOTALog("InitOTADirectory: version = %d\n", version); if (current_version > 0) @@ -367,38 +394,15 @@ static const char* InitOTADirectory(int* pAssetVersion) { TestOTALog("InitOTADirectory: PathExists returned false for %s\n", kBaseAssertDirectory); } - - memset(buffer, 0, sizeof(buffer)); - - if (0 == current_version) - { - TestOTALog("InitOTADirectory: current_version = 0\n"); - // No Assets are installed so get the Asset Verson from the AssertVersion.plist in the Security.framework - - // Look in the resources for a AssetVerstion.plst file - - CFDataRef assetVersionData = SecFrameworkCopyResourceContents(CFSTR("AssetVersion"), CFSTR("plist"), NULL); - if (NULL != assetVersionData) - { - CFPropertyListFormat propFormat; - CFDictionaryRef versionPlist = CFPropertyListCreateWithData(kCFAllocatorDefault, assetVersionData, 0, &propFormat, NULL); - if (NULL != versionPlist && CFDictionaryGetTypeID() == CFGetTypeID(versionPlist)) - { - CFNumberRef versionNumber = (CFNumberRef)CFDictionaryGetValue(versionPlist, (const void *)CFSTR("VersionNumber")); - if (NULL != versionNumber) - { - CFNumberGetValue(versionNumber, kCFNumberCFIndexType, &asset_number); - } - } - CFReleaseSafe(versionPlist); - CFReleaseSafe(assetVersionData); - } - - current_version = (int)asset_number; - } - else + + // Check to see which version number is greater. + // If the current_version is greater then the OTA asset is newer. + // If the system_asset_version is greater than the system asset is newer. + if (current_version > system_asset_version) { - TestOTALog("InitOTADirectory: current_version = %d\n", current_version); + // The OTA asset is newer than the system asset number + memset(buffer, 0, sizeof(buffer)); + TestOTALog("InitOTADirectory: current_version = %d\n", current_version); snprintf(buffer, sizeof(buffer), "%s/%s%d", kBaseAssertDirectory, kVersionDirectoryNamePrefix, current_version); size_t length = strlen(buffer); char* temp_str = (char*)malloc(length + 1); @@ -406,7 +410,17 @@ static const char* InitOTADirectory(int* pAssetVersion) strncpy(temp_str, buffer, length); result = temp_str; } - + else + { + // The system asset number is newer than the OTA asset number + current_version = system_asset_version; + if (NULL != result) + { + free((void *)result); + } + result = NULL; + } + if (NULL != pAssetVersion) { *pAssetVersion = current_version; @@ -431,9 +445,9 @@ static CFSetRef InitializeBlackList(const char* path_ptr) char file_path_buffer[PATH_MAX]; memset(file_path_buffer, 0, PATH_MAX); snprintf(file_path_buffer, PATH_MAX, "%s/Blocked.plist", asset_path); - + xmlData = SecOTACopyFileContents(file_path_buffer); - + if (NULL == xmlData) { xmlData = SecFrameworkCopyResourceContents(CFSTR("Blocked"), CFSTR("plist"), NULL); @@ -485,7 +499,7 @@ static CFSetRef InitializeBlackList(const char* path_ptr) static CFSetRef InitializeGrayList(const char* path_ptr) { CFSetRef result = NULL; - + // Check to see if the EVRoots.plist file is in the asset location CFDataRef xmlData = NULL; const char* asset_path = path_ptr; @@ -501,10 +515,10 @@ static CFSetRef InitializeGrayList(const char* path_ptr) snprintf(file_path_buffer, PATH_MAX, "%s/GrayListedKeys.plist", asset_path); xmlData = SecOTACopyFileContents(file_path_buffer); - + if (NULL == xmlData) { - xmlData = SecFrameworkCopyResourceContents(CFSTR("GrayListedKeys"), CFSTR("plist"), NULL); + xmlData = SecFrameworkCopyResourceContents(CFSTR("GrayListedKeys"), CFSTR("plist"), NULL); } } @@ -544,7 +558,7 @@ static CFSetRef InitializeGrayList(const char* path_ptr) { result = tempSet; } - + CFRelease(grayKeys); } return result; @@ -569,32 +583,32 @@ static CFDictionaryRef InitializeEVPolicyToAnchorDigestsTable(const char* path_p snprintf(file_path_buffer, PATH_MAX, "%s/EVRoots.plist", asset_path); xmlData = SecOTACopyFileContents(file_path_buffer); - + if (NULL == xmlData) { xmlData = SecFrameworkCopyResourceContents(CFSTR("EVRoots"), CFSTR("plist"), NULL); } } - + CFPropertyListRef evroots = NULL; - if (xmlData) + if (xmlData) { evroots = CFPropertyListCreateWithData( kCFAllocatorDefault, xmlData, kCFPropertyListImmutable, NULL, NULL); CFRelease(xmlData); } - if (evroots) + if (evroots) { - if (CFGetTypeID(evroots) == CFDictionaryGetTypeID()) + if (CFGetTypeID(evroots) == CFDictionaryGetTypeID()) { /* @@@ Ensure that each dictionary key is a dotted list of digits, each value is an NSArrayRef and each element in the array is a 20 byte digest. */ result = (CFDictionaryRef)evroots; - } - else + } + else { secwarning("EVRoot.plist is wrong type."); CFRelease(evroots); @@ -605,40 +619,40 @@ static CFDictionaryRef InitializeEVPolicyToAnchorDigestsTable(const char* path_p } static void* MapFile(const char* path, int* out_fd, size_t* out_file_size) -{ +{ void* result = NULL; void* temp_result = NULL; if (NULL == path || NULL == out_fd || NULL == out_file_size) { return result; } - + *out_fd = -1; *out_file_size = 0; - - + + *out_fd = open(path, O_RDONLY, 0666); - if (*out_fd == -1) + if (*out_fd == -1) { return result; } off_t fsize = lseek(*out_fd, 0, SEEK_END); - if (fsize == (off_t)-1) + if (fsize == (off_t)-1) { return result; } - if (fsize > (off_t)INT32_MAX) + if (fsize > (off_t)INT32_MAX) { close(*out_fd); *out_fd = -1; return result; } - + size_t malloc_size = (size_t)fsize; - + temp_result = malloc(malloc_size); if (NULL == temp_result) { @@ -646,16 +660,16 @@ static void* MapFile(const char* path, int* out_fd, size_t* out_file_size) *out_fd = -1; return result; } - + *out_file_size = malloc_size; - + off_t total_read = 0; - while (total_read < fsize) + while (total_read < fsize) { ssize_t bytes_read; bytes_read = pread(*out_fd, temp_result, (size_t)(fsize - total_read), total_read); - if (bytes_read == -1) + if (bytes_read == -1) { free(temp_result); temp_result = NULL; @@ -663,7 +677,7 @@ static void* MapFile(const char* path, int* out_fd, size_t* out_file_size) *out_fd = -1; return result; } - if (bytes_read == 0) + if (bytes_read == 0) { free(temp_result); temp_result = NULL; @@ -673,7 +687,7 @@ static void* MapFile(const char* path, int* out_fd, size_t* out_file_size) } total_read += bytes_read; } - + if (NULL != temp_result) { result = temp_result; @@ -694,17 +708,17 @@ static void UnMapFile(void* mapped_data, size_t data_size) static bool InitializeAnchorTable(const char* path_ptr, CFDictionaryRef* pLookupTable, const char** ppAnchorTable) { - + bool result = false; - + if (NULL == pLookupTable || NULL == ppAnchorTable) { return result; } - + *pLookupTable = NULL; *ppAnchorTable = NULL;; - + // first see if there is a file at /var/db/OTA_Anchors const char* dir_path = NULL; CFDataRef cert_index_file_data = NULL; @@ -721,13 +735,13 @@ static bool InitializeAnchorTable(const char* path_ptr, CFDictionaryRef* pLookup CFDataRef index_hash = NULL; CFMutableArrayRef offsets = NULL; Boolean release_offset = false; - + char* local_anchorTable = NULL; size_t local_anchorTableSize = 0; int local_anchorTable_fd = -1; - + // ------------------------------------------------------------------------ - // First determine if there are asset files at /var/Keychains. If there + // First determine if there are asset files at /var/Keychains. If there // are files use them for the trust table. Otherwise, use the files in the // Security.framework bundle. // @@ -735,14 +749,14 @@ static bool InitializeAnchorTable(const char* path_ptr, CFDictionaryRef* pLookup // size of the data is around 250K. // ------------------------------------------------------------------------ dir_path = path_ptr; - + if (NULL != dir_path) { // There is a set of OTA asset files memset(file_path_buffer, 0, PATH_MAX); snprintf(file_path_buffer, PATH_MAX, "%s/certsIndex.data", dir_path); cert_index_file_data = SecOTACopyFileContents(file_path_buffer); - + if (NULL != cert_index_file_data) { memset(file_path_buffer, 0, PATH_MAX); @@ -753,10 +767,10 @@ static bool InitializeAnchorTable(const char* path_ptr, CFDictionaryRef* pLookup free((void *)dir_path); dir_path = NULL; } - + // Check to see if kAnchorTable was indeed set if (NULL == local_anchorTable) - { + { // local_anchorTable is still NULL so the asset in the Security framework needs to be used. CFReleaseSafe(cert_index_file_data); cert_index_file_data = SecFrameworkCopyResourceContents(CFSTR("certsIndex"), CFSTR("data"), NULL); @@ -781,10 +795,16 @@ static bool InitializeAnchorTable(const char* path_ptr, CFDictionaryRef* pLookup } CFReleaseSafe(table_data_url); } - + if (NULL == local_anchorTable || NULL == cert_index_file_data) { // we are in trouble + if (NULL != local_anchorTable) + { + UnMapFile(local_anchorTable, local_anchorTableSize); + local_anchorTable = NULL; + local_anchorTableSize = 0; + } CFReleaseSafe(cert_index_file_data); return result; } @@ -798,7 +818,7 @@ static bool InitializeAnchorTable(const char* path_ptr, CFDictionaryRef* pLookup pIndex = (const index_record*)CFDataGetBytePtr(cert_index_file_data); index_data_size = CFDataGetLength(cert_index_file_data); - anchorLookupTable = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + anchorLookupTable = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); for (index_offset = index_data_size; index_offset > 0; index_offset -= sizeof(index_record), pIndex++) @@ -832,7 +852,7 @@ static bool InitializeAnchorTable(const char* path_ptr, CFDictionaryRef* pLookup } CFRelease(cert_index_file_data); - + if (NULL != anchorLookupTable && NULL != local_anchorTable) { *pLookupTable = anchorLookupTable; @@ -850,15 +870,14 @@ static bool InitializeAnchorTable(const char* path_ptr, CFDictionaryRef* pLookup local_anchorTableSize = 0; } } - - return result; + + return result; } -static CFArrayRef InitializeEscrowCertificates(const char* path_ptr) -{ - CFArrayRef result = NULL; +static void InitializeEscrowCertificates(const char* path_ptr, CFArrayRef *escrowRoots, CFArrayRef *escrowPCSRoots) +{ CFDataRef file_data = NULL; - + const char* dir_path = path_ptr; if (NULL == dir_path) { @@ -871,31 +890,35 @@ static CFArrayRef InitializeEscrowCertificates(const char* path_ptr) snprintf(buffer, 1024, "%s/AppleESCertificates.plist", dir_path); file_data = SecOTACopyFileContents(buffer); } - + if (NULL != file_data) { CFPropertyListFormat propFormat; - CFDictionaryRef certsDictionary = CFPropertyListCreateWithData(kCFAllocatorDefault, file_data, 0, &propFormat, NULL); + CFDictionaryRef certsDictionary = CFPropertyListCreateWithData(kCFAllocatorDefault, file_data, 0, &propFormat, NULL); if (NULL != certsDictionary && CFDictionaryGetTypeID() == CFGetTypeID((CFTypeRef)certsDictionary)) - { + { CFArrayRef certs = (CFArrayRef)CFDictionaryGetValue(certsDictionary, CFSTR("ProductionEscrowKey")); if (NULL != certs && CFArrayGetTypeID() == CFGetTypeID((CFTypeRef)certs) && CFArrayGetCount(certs) > 0) { - result = CFArrayCreateCopy(kCFAllocatorDefault, certs); + *escrowRoots = CFArrayCreateCopy(kCFAllocatorDefault, certs); + } + CFArrayRef pcs_certs = (CFArrayRef)CFDictionaryGetValue(certsDictionary, CFSTR("ProductionPCSEscrowKey")); + if (NULL != pcs_certs && CFArrayGetTypeID() == CFGetTypeID((CFTypeRef)pcs_certs) && CFArrayGetCount(pcs_certs) > 0) + { + *escrowPCSRoots = CFArrayCreateCopy(kCFAllocatorDefault, pcs_certs); } - CFRelease(certsDictionary); } + CFReleaseSafe(certsDictionary); CFRelease(file_data); } - - return result; + } static SecOTAPKIRef SecOTACreate() { TestOTALog("In SecOTACreate\n"); - + SecOTAPKIRef otapkiref = NULL; otapkiref = CFTypeAllocate(SecOTAPKI, struct _OpaqueSecOTAPKI , kCFAllocatorDefault); @@ -904,25 +927,26 @@ static SecOTAPKIRef SecOTACreate() { return otapkiref; } - - // Mkae suer that if this routine has to bail that the clean up + + // Make sure that if this routine has to bail that the clean up // will do the right thing otapkiref->_blackListSet = NULL; otapkiref->_grayListSet = NULL; otapkiref->_escrowCertificates = NULL; + otapkiref->_escrowPCSCertificates = NULL; otapkiref->_evPolicyToAnchorMapping = NULL; otapkiref->_anchorLookupTable = NULL; otapkiref->_anchorTable = NULL; otapkiref->_assetVersion = 0; - + // Start off by getting the correct asset directory info int asset_version = 0; const char* path_ptr = InitOTADirectory(&asset_version); otapkiref->_assetVersion = asset_version; - - TestOTALog("SecOTACreate: asset_path = %s\n", path_ptr); + + TestOTALog("SecOTACreate: asset_path = %s\n", path_ptr); TestOTALog("SecOTACreate: asset_version = %d\n", asset_version); - + // Get the set of black listed keys CFSetRef blackKeysSet = InitializeBlackList(path_ptr); if (NULL == blackKeysSet) @@ -931,7 +955,7 @@ static SecOTAPKIRef SecOTACreate() return otapkiref; } otapkiref->_blackListSet = blackKeysSet; - + // Get the set of gray listed keys CFSetRef grayKeysSet = InitializeGrayList(path_ptr); if (NULL == grayKeysSet) @@ -940,16 +964,21 @@ static SecOTAPKIRef SecOTACreate() return otapkiref; } otapkiref->_grayListSet = grayKeysSet; - - CFArrayRef escrowCerts = InitializeEscrowCertificates(path_ptr); - if (NULL == escrowCerts) + + CFArrayRef escrowCerts = NULL; + CFArrayRef escrowPCSCerts = NULL; + InitializeEscrowCertificates(path_ptr, &escrowCerts, &escrowPCSCerts); + if (NULL == escrowCerts || NULL == escrowPCSCerts) { + CFReleaseNull(escrowCerts); + CFReleaseNull(escrowPCSCerts); CFReleaseNull(otapkiref); return otapkiref; } otapkiref->_escrowCertificates = escrowCerts; - - // Geht the mapping of EV Policy OIDs to Anchor digest + otapkiref->_escrowPCSCertificates = escrowPCSCerts; + + // Get the mapping of EV Policy OIDs to Anchor digest CFDictionaryRef evOidToAnchorDigestMap = InitializeEVPolicyToAnchorDigestsTable(path_ptr); if (NULL == evOidToAnchorDigestMap) { @@ -957,10 +986,10 @@ static SecOTAPKIRef SecOTACreate() return otapkiref; } otapkiref->_evPolicyToAnchorMapping = evOidToAnchorDigestMap; - + CFDictionaryRef anchorLookupTable = NULL; const char* anchorTablePtr = NULL; - + if (!InitializeAnchorTable(path_ptr, &anchorLookupTable, &anchorTablePtr)) { CFReleaseSafe(anchorLookupTable); @@ -968,13 +997,13 @@ static SecOTAPKIRef SecOTACreate() { free((void *)anchorTablePtr); } - + CFReleaseNull(otapkiref); return otapkiref; } otapkiref->_anchorLookupTable = anchorLookupTable; otapkiref->_anchorTable = anchorTablePtr; - return otapkiref; + return otapkiref; } static dispatch_once_t kInitializeOTAPKI = 0; @@ -991,7 +1020,7 @@ SecOTAPKIRef SecOTAPKICopyCurrentOTAPKIRef() kCurrentOTAPKIRef = SecOTACreate(); }); - dispatch_sync(kOTAQueue, + dispatch_sync(kOTAQueue, ^{ result = kCurrentOTAPKIRef; CFRetainSafe(result); @@ -1007,7 +1036,7 @@ CFSetRef SecOTAPKICopyBlackListSet(SecOTAPKIRef otapkiRef) { return result; } - + result = otapkiRef->_blackListSet; CFRetainSafe(result); return result; @@ -1021,21 +1050,35 @@ CFSetRef SecOTAPKICopyGrayList(SecOTAPKIRef otapkiRef) { return result; } - + result = otapkiRef->_grayListSet; CFRetainSafe(result); return result; } -CFArrayRef SecOTAPKICopyEscrowCertificates(SecOTAPKIRef otapkiRef) +CFArrayRef SecOTAPKICopyEscrowCertificates(uint32_t escrowRootType, SecOTAPKIRef otapkiRef) { CFArrayRef result = NULL; if (NULL == otapkiRef) { return result; } - - result = otapkiRef->_escrowCertificates; + + switch (escrowRootType) { + // Note: we shouldn't be getting called to return baseline roots, + // since this function vends production roots by definition. + case kSecCertificateBaselineEscrowRoot: + case kSecCertificateProductionEscrowRoot: + result = otapkiRef->_escrowCertificates; + break; + case kSecCertificateBaselinePCSEscrowRoot: + case kSecCertificateProductionPCSEscrowRoot: + result = otapkiRef->_escrowPCSCertificates; + break; + default: + break; + } + CFRetainSafe(result); return result; } @@ -1048,7 +1091,7 @@ CFDictionaryRef SecOTAPKICopyEVPolicyToAnchorMapping(SecOTAPKIRef otapkiRef) { return result; } - + result = otapkiRef->_evPolicyToAnchorMapping; CFRetainSafe(result); return result; @@ -1062,7 +1105,7 @@ CFDictionaryRef SecOTAPKICopyAnchorLookupTable(SecOTAPKIRef otapkiRef) { return result; } - + result = otapkiRef->_anchorLookupTable; CFRetainSafe(result); return result; @@ -1075,7 +1118,7 @@ const char* SecOTAPKIGetAnchorTable(SecOTAPKIRef otapkiRef) { return result; } - + result = otapkiRef->_anchorTable; return result; } @@ -1087,7 +1130,7 @@ int SecOTAPKIGetAssetVersion(SecOTAPKIRef otapkiRef) { return result; } - + result = otapkiRef->_assetVersion; return result; } @@ -1096,30 +1139,30 @@ void SecOTAPKIRefreshData() { TestOTALog("In SecOTAPKIRefreshData\n"); SecOTAPKIRef new_otaPKRef = SecOTACreate(); - dispatch_sync(kOTAQueue, + dispatch_sync(kOTAQueue, ^{ CFReleaseSafe(kCurrentOTAPKIRef); kCurrentOTAPKIRef = new_otaPKRef; }); } -CFArrayRef SecOTAPKICopyCurrentEscrowCertificates(CFErrorRef* error) +CFArrayRef SecOTAPKICopyCurrentEscrowCertificates(uint32_t escrowRootType, CFErrorRef* error) { CFArrayRef result = NULL; - + SecOTAPKIRef otapkiref = SecOTAPKICopyCurrentOTAPKIRef(); if (NULL == otapkiref) { SecError(errSecInternal, error, CFSTR("Unable to get the current OTAPKIRef")); return result; } - - result = SecOTAPKICopyEscrowCertificates(otapkiref); + + result = SecOTAPKICopyEscrowCertificates(escrowRootType, otapkiref); CFRelease(otapkiref); - + if (NULL == result) { - SecError(errSecInternal, error, CFSTR("Could not get the array of escrow certificates form the current OTAPKIRef")); + SecError(errSecInternal, error, CFSTR("Could not get escrow certificates from the current OTAPKIRef")); } return result; } @@ -1127,14 +1170,14 @@ CFArrayRef SecOTAPKICopyCurrentEscrowCertificates(CFErrorRef* error) int SecOTAPKIGetCurrentAssetVersion(CFErrorRef* error) { int result = 0; - + SecOTAPKIRef otapkiref = SecOTAPKICopyCurrentOTAPKIRef(); if (NULL == otapkiref) { SecError(errSecInternal, error, CFSTR("Unable to get the current OTAPKIRef")); return result; } - + result = otapkiref->_assetVersion; return result; } @@ -1143,5 +1186,5 @@ int SecOTAPKISignalNewAsset(CFErrorRef* error) { TestOTALog("SecOTAPKISignalNewAsset has been called!\n"); SecOTAPKIRefreshData(); - return 1; + return 1; } diff --git a/sec/securityd/OTATrustUtilities.h b/Security/sec/securityd/OTATrustUtilities.h similarity index 87% rename from sec/securityd/OTATrustUtilities.h rename to Security/sec/securityd/OTATrustUtilities.h index f27218b3..a3882c44 100644 --- a/sec/securityd/OTATrustUtilities.h +++ b/Security/sec/securityd/OTATrustUtilities.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2003-2004,2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2004,2006-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, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ * * OTATrustUtilities.h @@ -40,12 +40,12 @@ typedef struct _OpaqueSecOTAPKI *SecOTAPKIRef; CF_EXPORT SecOTAPKIRef SecOTAPKICopyCurrentOTAPKIRef(void); -// Accessor to retrieve a copy of the current black listed key. +// Accessor to retrieve a copy of the current black listed key. // Caller is responsible for releasing the returned CFSetRef CF_EXPORT CFSetRef SecOTAPKICopyBlackListSet(SecOTAPKIRef otapkiRef); -// Accessor to retrieve a copy of the current gray listed key. +// Accessor to retrieve a copy of the current gray listed key. // Caller is responsible for releasing the returned CFSetRef CF_EXPORT CFSetRef SecOTAPKICopyGrayList(SecOTAPKIRef otapkiRef); @@ -53,7 +53,7 @@ CFSetRef SecOTAPKICopyGrayList(SecOTAPKIRef otapkiRef); // Accessor to retrieve the array of Escrow certificates // Caller is responsible for releasing the returned CFArrayRef CF_EXPORT -CFArrayRef SecOTAPKICopyEscrowCertificates(SecOTAPKIRef otapkiRef); +CFArrayRef SecOTAPKICopyEscrowCertificates(uint32_t escrowRootType, SecOTAPKIRef otapkiRef); // Accessor to retrieve the dictionary of EV Policy OIDs to Anchor digest // Caller is responsible for releasing the returned CFDictionaryRef @@ -84,11 +84,11 @@ void SecOTAPKIRefreshData(void); // SPI to return the array of currently trusted Escrow certificates CF_EXPORT -CFArrayRef SecOTAPKICopyCurrentEscrowCertificates(CFErrorRef* error); +CFArrayRef SecOTAPKICopyCurrentEscrowCertificates(uint32_t escrowRootType, CFErrorRef* error); // SPI to return the current OTA PKI asset version CF_EXPORT -int SecOTAPKIGetCurrentAssetVersion(CFErrorRef* error); +int SecOTAPKIGetCurrentAssetVersion(CFErrorRef* error); // SPI to signal securityd to get a new set of trust data CF_EXPORT diff --git a/Security/sec/securityd/Regressions/SOSAccountTesting.h b/Security/sec/securityd/Regressions/SOSAccountTesting.h new file mode 100644 index 00000000..569066de --- /dev/null +++ b/Security/sec/securityd/Regressions/SOSAccountTesting.h @@ -0,0 +1,455 @@ +/* + * 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@ + */ + + +#ifndef SEC_SOSAccountTesting_h +#define SEC_SOSAccountTesting_h + +#include +#include +#include +#include +#include "SOSTransportTestTransports.h" +// +// Account comparison +// + +#define kAccountsAgreeTestMin 9 +#define kAccountsAgreeTestPerPeer 1 +#define accountsAgree(x) (kAccountsAgreeTestMin + kAccountsAgreeTestPerPeer * (x)) + + +static SOSAccountRef SOSAccountCreateBasicTest(CFAllocatorRef allocator, + CFStringRef accountName, + CFDictionaryRef gestalt, + SOSDataSourceFactoryRef factory) { + SOSAccountRef a = SOSAccountCreateBasic(allocator, gestalt, factory); + + return a; +} + +static SOSAccountRef SOSAccountCreateTest(CFAllocatorRef allocator, + CFStringRef accountName, + CFDictionaryRef gestalt, + SOSDataSourceFactoryRef factory) { + SOSAccountRef a = SOSAccountCreateBasicTest(allocator, accountName, gestalt, factory); + + a->retired_peers = CFDictionaryCreateMutableForCFTypes(allocator); + SOSUnregisterTransportKeyParameter(a->key_transport); + + CFReleaseNull(a->circle_transports); + CFReleaseNull(a->message_transports); + CFReleaseNull(a->key_transport); + + SOSAccountEnsureFactoryCirclesTest(a, accountName); + + return a; +} + + +static void unretired_peers_is_subset(const char* label, CFArrayRef peers, CFArrayRef allowed_peers) +{ + CFArrayForEach(peers, ^(const void *value) { + SOSPeerInfoRef pi = (SOSPeerInfoRef) value; + CFErrorRef leftError = NULL; + CFErrorRef rightError = NULL; + + ok(SOSPeerInfoIsRetirementTicket(pi) || SOSPeerInfoIsCloudIdentity(pi) || CFArrayContainsValue(allowed_peers, CFRangeMake(0, CFArrayGetCount(allowed_peers)), pi), "Peer is allowed (%s) Peer: %@, Allowed %@", label, pi, allowed_peers); + + CFReleaseNull(leftError); + CFReleaseNull(rightError); + }); +} + +static void accounts_agree_internal(char *label, SOSAccountRef left, SOSAccountRef right, bool check_peers) +{ + CFErrorRef error = NULL; + { + CFArrayRef leftPeers = SOSAccountCopyActivePeers(left, &error); + ok(leftPeers, "Left peers (%@) - %s", error, label); + CFReleaseNull(error); + + CFArrayRef rightPeers = SOSAccountCopyActivePeers(right, &error); + ok(rightPeers, "Right peers (%@) - %s", error, label); + CFReleaseNull(error); + + ok(CFEqual(leftPeers, rightPeers), "Matching peers (%s) Left: %@, Right: %@", label, leftPeers, rightPeers); + + if (check_peers) { + CFMutableArrayRef allowed_identities = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + + CFArrayRef leftIdentities = SOSAccountCopyAccountIdentityPeerInfos(left, kCFAllocatorDefault, &error); + ok(leftIdentities, "Get identities (%@)", error); + CFReleaseNull(error); + + CFArrayAppendArray(allowed_identities, leftIdentities, CFRangeMake(0, CFArrayGetCount(leftIdentities))); + + CFReleaseNull(leftIdentities); + + CFArrayRef rightIdentities = SOSAccountCopyAccountIdentityPeerInfos(right, kCFAllocatorDefault, &error); + ok(rightIdentities, "Get identities (%@)", error); + CFReleaseNull(error); + + CFArrayAppendArray(allowed_identities, rightIdentities, CFRangeMake(0, CFArrayGetCount(rightIdentities))); + + CFReleaseNull(rightIdentities); + + unretired_peers_is_subset(label, leftPeers, allowed_identities); + } + + CFReleaseNull(leftPeers); + CFReleaseNull(rightPeers); + } + { + CFArrayRef leftConcurringPeers = SOSAccountCopyConcurringPeers(left, &error); + ok(leftConcurringPeers, "Left peers (%@) - %s", error, label); + + CFArrayRef rightConcurringPeers = SOSAccountCopyConcurringPeers(right, &error); + ok(rightConcurringPeers, "Right peers (%@) - %s", error, label); + + ok(CFEqual(leftConcurringPeers, rightConcurringPeers), "Matching concurring peers Left: %@, Right: %@", leftConcurringPeers, rightConcurringPeers); + + CFReleaseNull(leftConcurringPeers); + CFReleaseNull(rightConcurringPeers); + } + { + CFArrayRef leftApplicants = SOSAccountCopyApplicants(left, &error); + ok(leftApplicants, "Left Applicants (%@) - %s", error, label); + + CFArrayRef rightApplicants = SOSAccountCopyApplicants(right, &error); + ok(rightApplicants, "Left Applicants (%@) - %s", error, label); + + ok(CFEqual(leftApplicants, rightApplicants), "Matching applicants (%s) Left: %@, Right: %@", label, leftApplicants, rightApplicants); + + CFReleaseNull(leftApplicants); + CFReleaseNull(rightApplicants); + } +} + +static inline void accounts_agree(char *label, SOSAccountRef left, SOSAccountRef right) +{ + accounts_agree_internal(label, left, right, true); +} + + +// +// Change handling +// + +static void CFDictionaryOverlayDictionary(CFMutableDictionaryRef target, CFDictionaryRef overlay) { + CFDictionaryForEach(overlay, ^(const void *key, const void *value) { + CFDictionarySetValue(target, key, value); + }); +} + +static void CFArrayAppendKeys(CFMutableArrayRef keys, CFDictionaryRef newKeysToAdd) { + CFDictionaryForEach(newKeysToAdd, ^(const void *key, const void *value) { + CFArrayAppendValue(keys, key); + }); +} + +static bool AddNewChanges(CFMutableDictionaryRef changesRecord, CFMutableDictionaryRef newKeysAndValues, SOSAccountRef sender) +{ + __block bool changes_added = false; + CFMutableDictionaryRef emptyDictionary = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionaryAddValue(changesRecord, kCFNull, emptyDictionary); + CFReleaseNull(emptyDictionary); + + CFDictionaryOverlayDictionary((CFMutableDictionaryRef) CFDictionaryGetValue(changesRecord, kCFNull), newKeysAndValues); + + CFDictionaryForEach(changesRecord, ^(const void *key, const void *value) { + if (isArray(value) && (sender == NULL || !CFEqual(sender, key))) { + CFArrayAppendKeys((CFMutableArrayRef) value, newKeysAndValues); + if (CFDictionaryGetCount(newKeysAndValues)) + changes_added = true; + } + }); + + CFDictionaryRemoveAllValues(newKeysAndValues); + + return changes_added; +} + +static bool FillAllChanges(CFMutableDictionaryRef changes) { + __block bool changed = false; + CFArrayForEach(key_transports, ^(const void *value) { + SOSTransportKeyParameterTestRef tpt = (SOSTransportKeyParameterTestRef) value; + changed |= AddNewChanges(changes, SOSTransportKeyParameterTestGetChanges(tpt), SOSTransportKeyParameterTestGetAccount(tpt)); + }); + CFArrayForEach(circle_transports, ^(const void *value) { + SOSTransportCircleTestRef tpt = (SOSTransportCircleTestRef) value; + changed |= AddNewChanges(changes, SOSTransportCircleTestGetChanges(tpt), SOSTransportCircleTestGetAccount(tpt)); + }); + CFArrayForEach(message_transports, ^(const void *value) { + SOSTransportMessageTestRef tpt = (SOSTransportMessageTestRef) value; + CFDictionaryRemoveValue(SOSTransportMessageTestGetChanges(tpt), kCFNull); + changed |=AddNewChanges(changes, SOSTransportMessageTestGetChanges(tpt), SOSTransportMessageTestGetAccount(tpt)); + }); + + return changed; +} + +static void FillChanges(CFMutableDictionaryRef changes, SOSAccountRef forAccount) +{ + CFArrayForEach(key_transports, ^(const void *value) { + SOSTransportKeyParameterTestRef tpt = (SOSTransportKeyParameterTestRef) value; + if(CFEqualSafe(forAccount, SOSTransportKeyParameterTestGetAccount(tpt))){ + AddNewChanges(changes, SOSTransportKeyParameterTestGetChanges(tpt), SOSTransportKeyParameterTestGetAccount(tpt)); + } + }); + CFArrayForEach(circle_transports, ^(const void *value) { + SOSTransportCircleTestRef tpt = (SOSTransportCircleTestRef) value; + if(CFEqualSafe(forAccount, SOSTransportCircleTestGetAccount(tpt))){ + AddNewChanges(changes, SOSTransportCircleTestGetChanges(tpt), SOSTransportCircleTestGetAccount(tpt)); + } + }); + CFArrayForEach(message_transports, ^(const void *value) { + SOSTransportMessageTestRef tpt = (SOSTransportMessageTestRef) value; + if(CFEqualSafe(forAccount, SOSTransportMessageTestGetAccount(tpt))){ + CFDictionaryRemoveValue(SOSTransportMessageTestGetChanges(tpt), kCFNull); + AddNewChanges(changes, SOSTransportMessageTestGetChanges(tpt), SOSTransportMessageTestGetAccount(tpt)); + } + }); + +} + +static inline void FillChangesMulti(CFMutableDictionaryRef changes, SOSAccountRef account, ...) +{ + SOSAccountRef next_account = account; + va_list argp; + va_start(argp, account); + while(next_account != NULL) { + FillChanges(changes, next_account); + next_account = va_arg(argp, SOSAccountRef); + } +} + +static inline CFMutableArrayRef CFDictionaryCopyKeys(CFDictionaryRef dictionary) +{ + CFMutableArrayRef result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + + CFArrayAppendKeys(result, dictionary); + + return result; +} + +#define kFeedChangesToTestCount 1 +static inline void FeedChangesTo(CFMutableDictionaryRef changes, SOSAccountRef account) +{ + CFDictionaryRef full_list = (CFDictionaryRef) CFDictionaryGetValue(changes, kCFNull); + + if (!isDictionary(full_list)) + return; // Nothing recorded to send! + + CFMutableArrayRef account_pending_keys = (CFMutableArrayRef)CFDictionaryGetValue(changes, account); + if (!isArray(account_pending_keys)) { + CFReleaseNull(account_pending_keys); + + account_pending_keys = CFDictionaryCopyKeys(full_list); + CFDictionaryAddValue(changes, account, account_pending_keys); + CFReleaseSafe(account_pending_keys); // The dictionary keeps it, we don't retain it here. + } + + CFMutableArrayRef handled = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + + secerror("Changes for %@: %@", SOSTransportKeyParameterTestGetName((SOSTransportKeyParameterTestRef) account->key_transport), account_pending_keys); + + CFErrorRef error = NULL; + CFMutableDictionaryRef account_pending_messages = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFArrayForEach(account_pending_keys, ^(const void *value) { + CFDictionaryAddValue(account_pending_messages, value, CFDictionaryGetValue(full_list, value)); + }); + + ok(handled = SOSTransportDispatchMessages(account, account_pending_messages, &error), "SOSTransportHandleMessages failed (%@)", error); + + if (isArray(handled)) { + CFArrayForEach(handled, ^(const void *value) { + CFArrayRemoveAllValue(account_pending_keys, value); + }); + } + + CFReleaseNull(handled); + CFReleaseNull(error); +} + +#define kFeedChangesToMultieTestCountPer 1 + +static inline void FeedChangesToMultiV(CFMutableDictionaryRef changes, va_list argp) +{ + SOSAccountRef account = NULL; + while((account = va_arg(argp, SOSAccountRef)) != NULL) { + FeedChangesTo(changes, account); + } +} + +static inline void FeedChangesToMulti(CFMutableDictionaryRef changes, ...) +{ + va_list argp; + va_start(argp, changes); + + FeedChangesToMultiV(changes, argp); + + va_end(argp); +} + +static inline void InjectChangeToMulti(CFMutableDictionaryRef changes, + CFStringRef changeKey, CFTypeRef changeValue, ...) +{ + CFMutableDictionaryRef changes_to_send = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, + changeKey, changeValue, + NULL); + AddNewChanges(changes, changes_to_send, NULL); + CFReleaseNull(changes_to_send); + + va_list argp; + va_start(argp, changeValue); + FeedChangesToMultiV(changes, argp); + +} + + +static inline bool ProcessChangesOnceV(CFMutableDictionaryRef changes, va_list argp) +{ + bool result = FillAllChanges(changes); + + FeedChangesToMultiV(changes, argp); + + return result; +} + + +static inline bool ProcessChangesOnce(CFMutableDictionaryRef changes, ...) +{ + va_list argp; + va_start(argp, changes); + + bool result = ProcessChangesOnceV(changes, argp); + + va_end(argp); + + return result; +} + +static inline int ProcessChangesUntilNoChange(CFMutableDictionaryRef changes, ...) +{ + va_list argp; + va_start(argp, changes); + + int result = 0; + bool new_data = false; + do { + va_list argp_copy; + va_copy(argp_copy, argp); + + new_data = ProcessChangesOnceV(changes, argp_copy); + + ++result; + + va_end(argp_copy); + } while (new_data); + + va_end(argp); + + return result; + +} + +// +// MARK: Account creation +// + +static SOSAccountRef CreateAccountForLocalChanges(CFStringRef name, CFStringRef data_source_name) +{ + SOSDataSourceFactoryRef factory = SOSTestDataSourceFactoryCreate(); + SOSDataSourceRef ds = SOSTestDataSourceCreate(); + SOSTestDataSourceFactoryAddDataSource(factory, data_source_name, ds); + SOSEngineRef engine = SOSEngineCreate(ds, NULL); + ds->engine = engine; + CFDictionaryRef gestalt = SOSCreatePeerGestaltFromName(name); + + SOSAccountRef result = SOSAccountCreateTest(kCFAllocatorDefault, name, gestalt, factory); + + CFReleaseNull(gestalt); + + return result; +} + + +static inline int countPeers(SOSAccountRef account) { + CFErrorRef error = NULL; + CFArrayRef peers; + + peers = SOSAccountCopyPeers(account, &error); + int retval = (int) CFArrayGetCount(peers); + CFReleaseNull(error); + CFReleaseNull(peers); + return retval; +} + +static inline int countActivePeers(SOSAccountRef account) { + CFErrorRef error = NULL; + CFArrayRef peers; + + peers = SOSAccountCopyActivePeers(account, &error); + int retval = (int) CFArrayGetCount(peers); + CFReleaseNull(error); + CFReleaseNull(peers); + return retval; +} + +static inline int countActiveValidPeers(SOSAccountRef account) { + CFErrorRef error = NULL; + CFArrayRef peers; + + peers = SOSAccountCopyActiveValidPeers(account, &error); + int retval = (int) CFArrayGetCount(peers); + CFReleaseNull(error); + CFReleaseNull(peers); + return retval; +} + +static inline int countApplicants(SOSAccountRef account) { + CFErrorRef error = NULL; + CFArrayRef applicants = SOSAccountCopyApplicants(account, &error); + int retval = 0; + + if(applicants) retval = (int)CFArrayGetCount(applicants); + CFReleaseNull(error); + CFReleaseNull(applicants); + return retval; +} + + +static inline void showActiveValidPeers(SOSAccountRef account) { + CFErrorRef error = NULL; + CFArrayRef peers; + + peers = SOSAccountCopyActiveValidPeers(account, &error); + CFArrayForEach(peers, ^(const void *value) { + SOSPeerInfoRef pi = (SOSPeerInfoRef) value; + ok(0, "Active Valid Peer %@", pi); + }); + CFReleaseNull(peers); +} + +#endif diff --git a/Security/sec/securityd/Regressions/SOSTransportTestTransports.c b/Security/sec/securityd/Regressions/SOSTransportTestTransports.c new file mode 100644 index 00000000..3063210b --- /dev/null +++ b/Security/sec/securityd/Regressions/SOSTransportTestTransports.c @@ -0,0 +1,733 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "SOSTransportTestTransports.h" + +static bool sendToPeer(SOSTransportMessageRef transport, CFStringRef circleName, CFStringRef peerID, CFDataRef message, CFErrorRef *error); +static bool syncWithPeers(SOSTransportMessageRef transport, CFDictionaryRef circleToPeerIDs, CFErrorRef *error); +static bool sendMessages(SOSTransportMessageRef transport, CFDictionaryRef circleToPeersToMessage, CFErrorRef *error); +static bool cleanupAfterPeer(SOSTransportMessageRef transport, CFDictionaryRef circle_to_peer_ids, CFErrorRef *error); +static CF_RETURNS_RETAINED +CFDictionaryRef handleMessages(SOSTransportMessageRef transport, CFMutableDictionaryRef circle_peer_messages_table, CFErrorRef *error); +static void destroyMessageTransport(SOSTransportMessageRef transport); +static void SOSTransportMessageTestAddBulkToChanges(SOSTransportMessageTestRef transport, CFDictionaryRef updates); + +static bool flushMessageChanges(SOSTransportMessageRef transport, CFErrorRef *error); +static bool publishCloudParameters(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef* error); +static bool SOSTransportKeyParameterTestPublishCloudParameters(SOSTransportKeyParameterTestRef transport, CFDataRef newParameters, CFErrorRef *error); + +static bool expireRetirementRecords(SOSTransportCircleRef transport, CFDictionaryRef retirements, CFErrorRef *error); +static void destroy(SOSTransportCircleRef transport); +static inline bool flushChanges(SOSTransportCircleRef transport, CFErrorRef *error); +static bool postCircle(SOSTransportCircleRef transport, CFStringRef circleName, CFDataRef circle_data, CFErrorRef *error); +static inline bool postRetirement(SOSTransportCircleRef transport, CFStringRef circleName, CFStringRef peer_id, CFDataRef retirement_data, CFErrorRef *error); +static bool handleKeyParameterChanges(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef error); + +static CFArrayRef handleCircleMessages(SOSTransportCircleRef transport, CFMutableDictionaryRef circle_circle_messages_table, CFErrorRef *error); +static CFDictionaryRef handleRetirementMessages(SOSTransportCircleRef transport, CFMutableDictionaryRef circle_retirement_messages_table, CFErrorRef *error); +static bool setToNewAccount(SOSTransportKeyParameterRef transport); + +static void SOSTransportCircleTestAddBulkToChanges(SOSTransportCircleTestRef transport, CFDictionaryRef updates); +static void SOSTransportCircleTestAddToChanges(SOSTransportCircleTestRef transport, CFStringRef message_key, CFDataRef message_data); +static bool SOSTransportCircleTestSendChanges(SOSTransportCircleTestRef transport, CFDictionaryRef changes, CFErrorRef *error); + + +void SOSAccountUpdateTestTransports(SOSAccountRef account, CFDictionaryRef gestalt){ + CFStringRef new_name = (CFStringRef)CFDictionaryGetValue(gestalt, kPIUserDefinedDeviceName); + SOSTransportKeyParameterTestRef key = (SOSTransportKeyParameterTestRef)account->key_transport; + CFDictionaryRef circles = account->circle_transports; + CFDictionaryRef messages = account->message_transports; + + SOSTransportKeyParameterTestSetName(key, new_name); + CFDictionaryForEach(circles, ^(const void *key, const void *value) { + SOSTransportCircleTestSetName((SOSTransportCircleTestRef)value, new_name); + }); + CFDictionaryForEach(messages, ^(const void *key, const void *value) { + SOSTransportMessageTestSetName((SOSTransportMessageTestRef)value, new_name); + }); + +} + +static SOSCircleRef SOSAccountEnsureCircleTest(SOSAccountRef a, CFStringRef name, CFStringRef accountName, CFErrorRef *error) +{ + CFErrorRef localError = NULL; + + SOSCircleRef circle = SOSAccountFindCircle(a, name, &localError); + + require_action_quiet(circle || !isSOSErrorCoded(localError, kSOSErrorIncompatibleCircle), fail, + if (error) { *error = localError; localError = NULL; }); + + if(NULL == circle){ + circle = SOSCircleCreate(NULL, name, NULL); + if (circle){ + CFDictionaryAddValue(a->circles, name, circle); + CFRelease(circle); + circle = SOSAccountFindCircle(a, name, &localError); + } + } + require_quiet(SOSAccountInflateTestTransportsForCircle(a, name, accountName, &localError), fail); + +fail: + CFReleaseNull(localError); + return circle; +} + +bool SOSAccountEnsureFactoryCirclesTest(SOSAccountRef a, CFStringRef accountName) +{ + bool result = false; + if (a) + { + require(a->factory, xit); + CFArrayRef circle_names = a->factory->copy_names(a->factory); + require(circle_names, xit); + CFArrayForEach(circle_names, ^(const void*name) { + if (isString(name)) + SOSAccountEnsureCircleTest(a, (CFStringRef)name, accountName, NULL); + }); + + CFReleaseNull(circle_names); + result = true; + } +xit: + return result; +} + +bool SOSAccountInflateTestTransportsForCircle(SOSAccountRef account, CFStringRef circleName, CFStringRef accountName, CFErrorRef *error){ + bool success = false; + SOSTransportCircleTestRef tCircle = NULL; + SOSTransportMessageTestRef tMessage = NULL; + + if(account->key_transport == NULL){ + account->key_transport = (SOSTransportKeyParameterRef)SOSTransportTestCreateKeyParameter(account, accountName, circleName); + require_quiet(account->key_transport, fail); + } + if(account->circle_transports == NULL){ + account->circle_transports = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + tCircle = SOSTransportTestCreateCircle(account, accountName, circleName); + require_quiet(tCircle, fail); + CFDictionarySetValue(account->circle_transports, circleName, tCircle); + } + else if(CFDictionaryGetCount(account->circle_transports) == 0){ + tCircle = SOSTransportTestCreateCircle(account, accountName, circleName); + require_quiet(tCircle, fail); + CFDictionarySetValue(account->circle_transports, circleName, tCircle); + } + if(account->message_transports == NULL){ + account->message_transports = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + tMessage = SOSTransportTestCreateMessage(account, accountName, circleName); + require_quiet(tMessage, fail); + CFDictionarySetValue(account->message_transports, circleName, tMessage); + } + else if(CFDictionaryGetCount(account->message_transports) == 0){ + tMessage = SOSTransportTestCreateMessage(account, accountName, circleName); + require_quiet(tMessage, fail); + CFDictionarySetValue(account->message_transports, circleName, tMessage); + } + + success = true; +fail: + CFReleaseNull(tCircle); + CFReleaseNull(tMessage); + return success; +} + +/// +//Mark Test Key Parameter Transport +/// + +struct SOSTransportKeyParameterTest{ + struct __OpaqueSOSTransportKeyParameter k; + CFMutableDictionaryRef changes; + CFStringRef name; + CFStringRef circleName; +}; + +SOSTransportKeyParameterTestRef SOSTransportTestCreateKeyParameter(SOSAccountRef account, CFStringRef name, CFStringRef circleName){ + + SOSTransportKeyParameterTestRef tpt = calloc(1, sizeof(struct SOSTransportKeyParameterTest)); + + tpt->name = CFRetainSafe(name); + tpt->changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + tpt->k.account = CFRetainSafe(account); + tpt->circleName = CFRetainSafe(circleName); + tpt->k.publishCloudParameters = publishCloudParameters; + tpt->k.handleKeyParameterChanges = handleKeyParameterChanges; + tpt->k.setToNewAccount = setToNewAccount; + if(!key_transports) + key_transports = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFArrayAppendValue(key_transports, (SOSTransportKeyParameterRef)tpt); + SOSRegisterTransportKeyParameter((SOSTransportKeyParameterRef)tpt); + return tpt; +} + +static bool handleKeyParameterChanges(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef error){ + SOSAccountRef account = transport->account; + return SOSAccountHandleParametersChange(account, data, &error); +} + +static bool setToNewAccount(SOSTransportKeyParameterRef transport){ + SOSTransportKeyParameterTestRef tpt = (SOSTransportKeyParameterTestRef)transport; + SOSAccountRef a = SOSTransportKeyParameterTestGetAccount(tpt); + CFStringRef accountName = SOSTransportKeyParameterTestGetName(tpt); + CFAllocatorRef allocator = CFGetAllocator(a); + CFReleaseNull(a->circle_identities); + CFReleaseNull(a->circles); + CFReleaseNull(a->retired_peers); + + CFReleaseNull(a->user_key_parameters); + CFReleaseNull(a->user_public); + CFReleaseNull(a->previous_public); + CFReleaseNull(a->_user_private); + + a->user_public_trusted = false; + a->departure_code = kSOSNeverAppliedToCircle; + a->user_private_timer = 0; + a->lock_notification_token = 0; + + // keeping gestalt; + // keeping factory; + // Live Notification + // change_blocks; + // update_interest_block; + // update_block; + + a->circles = CFDictionaryCreateMutableForCFTypes(allocator); + a->circle_identities = CFDictionaryCreateMutableForCFTypes(allocator); + a->retired_peers = CFDictionaryCreateMutableForCFTypes(allocator); + + //unregister all the transports from the global transport queue + SOSUnregisterTransportKeyParameter(a->key_transport); + CFArrayForEach(circle_transports, ^(const void *value) { + SOSTransportCircleTestRef tpt = (SOSTransportCircleTestRef) value; + if(CFStringCompare(SOSTransportCircleTestGetName(tpt), accountName, 0) == 0){ + SOSUnregisterTransportCircle((SOSTransportCircleRef)tpt); + } + }); + CFArrayForEach(message_transports, ^(const void *value) { + SOSTransportMessageTestRef tpt = (SOSTransportMessageTestRef) value; + if(CFStringCompare(SOSTransportMessageTestGetName(tpt), accountName, 0) == 0){ + SOSUnregisterTransportMessage((SOSTransportMessageRef)tpt); + } + }); + + + CFReleaseNull(a->key_transport); + CFReleaseNull(a->circle_transports); + CFReleaseNull(a->message_transports); + + SOSAccountEnsureFactoryCirclesTest(a, accountName); + + return true; +} +CFStringRef SOSTransportKeyParameterTestGetName(SOSTransportKeyParameterTestRef transport){ + return transport->name; +} + +void SOSTransportKeyParameterTestSetName(SOSTransportKeyParameterTestRef transport, CFStringRef accountName){ + CFReleaseNull(transport->name); + transport->name = CFRetain(accountName); +} + +SOSAccountRef SOSTransportKeyParameterTestGetAccount(SOSTransportKeyParameterTestRef transport){ + return ((SOSTransportKeyParameterRef)transport)->account; +} + +CFMutableDictionaryRef SOSTransportKeyParameterTestGetChanges(SOSTransportKeyParameterTestRef transport){ + return transport->changes; +} +static bool publishCloudParameters(SOSTransportKeyParameterRef transport, CFDataRef data, CFErrorRef* error) +{ + return SOSTransportKeyParameterTestPublishCloudParameters((SOSTransportKeyParameterTestRef)transport, data, error); +} + +static bool SOSTransportKeyParameterTestPublishCloudParameters(SOSTransportKeyParameterTestRef transport, CFDataRef newParameters, CFErrorRef *error) +{ + if(!transport->changes) + transport->changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + + CFDictionarySetValue(transport->changes, kSOSKVSKeyParametersKey, newParameters); + + return true; +} + +/// +//MARK: Test Circle Transport +/// +struct SOSTransportCircleTest{ + struct __OpaqueSOSTransportCircle c; + CFMutableDictionaryRef changes; + CFStringRef name; + CFStringRef circleName; +}; +static CFStringRef SOSTransportCircleCopyDescription(SOSTransportCircleTestRef transport) { + + return CFStringCreateWithFormat(NULL, NULL, CFSTR(""), transport); +} + +static CFStringRef copyDescription(SOSTransportCircleRef transport){ + return SOSTransportCircleCopyDescription((SOSTransportCircleTestRef)transport); +} + +CFStringRef SOSTransportCircleTestGetName(SOSTransportCircleTestRef transport){ + return transport->name; +} +void SOSTransportCircleTestSetName(SOSTransportCircleTestRef transport, CFStringRef accountName){ + CFReleaseNull(transport->name); + transport->name = CFRetain(accountName); +} + +CFMutableDictionaryRef SOSTransportCircleTestGetChanges(SOSTransportCircleTestRef transport){ + return transport->changes; +} +SOSTransportCircleTestRef SOSTransportTestCreateCircle(SOSAccountRef account, CFStringRef name, CFStringRef circleName){ + SOSTransportCircleTestRef tpt = calloc(1, sizeof(struct SOSTransportCircleTest)); + if(tpt){ + tpt->c.account = CFRetainSafe(account); + tpt->c.copyDescription = copyDescription; + tpt->c.expireRetirementRecords = expireRetirementRecords; + tpt->c.postCircle = postCircle; + tpt->c.postRetirement = postRetirement; + tpt->c.flushChanges = flushChanges; + tpt->c.handleRetirementMessages = handleRetirementMessages; + tpt->c.handleCircleMessages = handleCircleMessages; + tpt->c.destroy = destroy; + tpt->changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + tpt->name = CFRetainSafe(name); + tpt->circleName = CFRetainSafe(circleName); + if(!circle_transports) + circle_transports = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFArrayAppendValue(circle_transports, (SOSTransportCircleRef)tpt); + SOSRegisterTransportCircle((SOSTransportCircleRef)tpt); + } + + return tpt; +} + +static void destroy(SOSTransportCircleRef transport){ + SOSTransportCircleTestRef tkvs = (SOSTransportCircleTestRef)transport; + CFArrayRemoveAllValue(circle_transports, tkvs); + CFReleaseNull(tkvs->changes); + CFReleaseNull(tkvs->name); + CFReleaseNull(tkvs->circleName); +} + +static inline bool postRetirement(SOSTransportCircleRef transport, CFStringRef circleName, CFStringRef peer_id, CFDataRef retirement_data, CFErrorRef *error) +{ + CFStringRef retirement_key = SOSRetirementKeyCreateWithCircleNameAndPeer(circleName, peer_id); + if (retirement_key) + SOSTransportCircleTestAddToChanges((SOSTransportCircleTestRef)transport, retirement_key, retirement_data); + + CFReleaseNull(retirement_key); + return true; +} + +static inline bool flushChanges(SOSTransportCircleRef transport, CFErrorRef *error) +{ + return true; +} + +static void SOSTransportCircleTestAddToChanges(SOSTransportCircleTestRef transport, CFStringRef message_key, CFDataRef message_data){ + + if (transport->changes == NULL) { + transport->changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + } + if (message_data == NULL) { + CFDictionarySetValue(transport->changes, message_key, kCFNull); + } else { + CFDictionarySetValue(transport->changes, message_key, message_data); + } +} + +static void SOSTransportCircleTestAddBulkToChanges(SOSTransportCircleTestRef transport, CFDictionaryRef updates){ + + if (transport->changes == NULL) { + transport->changes = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, CFDictionaryGetCount(updates), updates); + + } + else{ + CFDictionaryForEach(updates, ^(const void *key, const void *value) { + CFDictionarySetValue(transport->changes, key, value); + }); + } +} + + +static bool expireRetirementRecords(SOSTransportCircleRef transport, CFDictionaryRef retirements, CFErrorRef *error) { + + bool success = true; + SOSTransportCircleTestRef tpt = (SOSTransportCircleTestRef)transport; + CFMutableDictionaryRef keysToWrite = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + + CFDictionaryForEach(retirements, ^(const void *key, const void *value) { + if (isString(key) && isArray(value)) { + CFStringRef circle_name = (CFStringRef) key; + CFArrayRef retirees = (CFArrayRef) value; + + CFArrayForEach(retirees, ^(const void *value) { + if (isString(value)) { + CFStringRef retiree_id = (CFStringRef) value; + + CFStringRef kvsKey = SOSRetirementKeyCreateWithCircleNameAndPeer(circle_name, retiree_id); + + CFDictionaryAddValue(keysToWrite, kvsKey, kCFNull); + + CFReleaseSafe(kvsKey); + } + }); + } + }); + + if(CFDictionaryGetCount(keysToWrite)) { + SOSTransportCircleTestAddBulkToChanges(tpt, keysToWrite); + } + CFReleaseNull(keysToWrite); + + return success; +} + +__unused static bool SOSTransportCircleTestUpdateRetirementRecords(SOSTransportCircleTestRef transport, CFDictionaryRef updates, CFErrorRef* error){ + CFErrorRef updateError = NULL; + bool success = false; + if (SOSTransportCircleTestSendChanges((SOSTransportCircleTestRef)transport, updates, &updateError)){ + success = true; + } else { + SOSCreateErrorWithFormat(kSOSErrorSendFailure, updateError, error, NULL, + CFSTR("update parameters key failed [%@]"), updates); + } + return success; +} + +static bool postCircle(SOSTransportCircleRef transport, CFStringRef circleName, CFDataRef circle_data, CFErrorRef *error){ + SOSTransportCircleTestRef tkvs = (SOSTransportCircleTestRef)transport; + CFStringRef circle_key = SOSCircleKeyCreateWithName(circleName, error); + if (circle_key) + SOSTransportCircleTestAddToChanges(tkvs, circle_key, circle_data); + CFReleaseNull(circle_key); + + return true; +} + +static CFDictionaryRef handleRetirementMessages(SOSTransportCircleRef transport, CFMutableDictionaryRef circle_retirement_messages_table, CFErrorRef *error){ + SOSAccountRef account = transport->account; + CFMutableDictionaryRef handledRetirementMessages = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionaryForEach(circle_retirement_messages_table, ^(const void *key, const void *value) { + if (isString(key) && isDictionary(value)) { + CFStringRef circle_name = (CFStringRef) key; + + CFDictionaryRef retirment_dictionary = (CFDictionaryRef) value; + CFDictionaryForEach(retirment_dictionary, ^(const void *key, const void *value) { + if(isData(value)) { + SOSPeerInfoRef pi = SOSPeerInfoCreateFromData(NULL, error, (CFDataRef) value); + if(pi && CFEqual(key, SOSPeerInfoGetPeerID(pi)) && SOSPeerInfoInspectRetirementTicket(pi, error)) { + CFMutableDictionaryRef circle_retirements = CFDictionaryEnsureCFDictionaryAndGetCurrentValue(account->retired_peers, circle_name); + CFDictionarySetValue(circle_retirements, key, value); + + SOSAccountRecordRetiredPeerInCircleNamed(account, circle_name, pi); + + CFMutableArrayRef handledRetirementIDs = CFDictionaryEnsureCFArrayAndGetCurrentValue(handledRetirementMessages, circle_name); + CFArrayAppendValue(handledRetirementIDs, SOSPeerInfoGetPeerID(pi)); + } + CFReleaseSafe(pi); + } + }); + } + }); + return handledRetirementMessages; +} + +static CFArrayRef handleCircleMessages(SOSTransportCircleRef transport, CFMutableDictionaryRef circle_circle_messages_table, CFErrorRef *error){ + CFMutableArrayRef handledKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionaryForEach(circle_circle_messages_table, ^(const void *key, const void *value) { + CFErrorRef circleMessageError = NULL; + if (!SOSAccountHandleCircleMessage(transport->account, key, value, &circleMessageError)) { + secerror("Error handling circle message %@ (%@): %@", key, value, circleMessageError); + } + else{ + CFStringRef circle_id = (CFStringRef) key; + CFArrayAppendValue(handledKeys, circle_id); + } + CFReleaseNull(circleMessageError); + }); + + return handledKeys; +} + +static bool SOSTransportCircleTestSendChanges(SOSTransportCircleTestRef transport, CFDictionaryRef changes, CFErrorRef *error){ + if(!transport->changes) + transport->changes = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, CFDictionaryGetCount(changes), changes); + else{ + CFDictionaryForEach(changes, ^(const void *key, const void *value) { + CFDictionarySetValue(transport->changes, key, value); + }); + } + return true; +} + +SOSAccountRef SOSTransportCircleTestGetAccount(SOSTransportCircleTestRef transport) { + return ((SOSTransportCircleRef)transport)->account; +} + +/// +//MARK Message Test Transport +/// + +struct SOSTransportMessageTest{ + struct __OpaqueSOSTransportMessage m; + CFMutableDictionaryRef changes; + CFStringRef name; + CFStringRef circleName; +}; + +SOSTransportMessageTestRef SOSTransportTestCreateMessage(SOSAccountRef account, CFStringRef name, CFStringRef circleName){ + SOSTransportMessageTestRef tpt = calloc(1, sizeof(struct SOSTransportMessageTest)); + + SOSEngineRef engine = SOSDataSourceFactoryGetEngineForDataSourceName(account->factory, circleName, NULL); + + tpt->m.engine = CFRetainSafe(engine); + if(tpt){ + tpt->m.sendMessages = sendMessages; + tpt->m.syncWithPeers = syncWithPeers; + tpt->m.flushChanges = flushMessageChanges; + tpt->m.cleanupAfterPeerMessages = cleanupAfterPeer; + tpt->m.destroy = destroyMessageTransport; + tpt->m.handleMessages = handleMessages; + // Initialize ourselves + tpt->changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + tpt->name = CFRetainSafe(name); + tpt->circleName = CFRetainSafe(circleName); + if(!message_transports) + message_transports = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFArrayAppendValue(message_transports, (SOSTransportMessageRef)tpt); + SOSRegisterTransportMessage((SOSTransportMessageRef)tpt); + } + + return tpt; +} +CFStringRef SOSTransportMessageTestGetName(SOSTransportMessageTestRef transport){ + return transport->name; +} + +void SOSTransportMessageTestSetName(SOSTransportMessageTestRef transport, CFStringRef accountName){ + CFReleaseNull(transport->name); + transport->name = CFRetain(accountName); +} + +CFMutableDictionaryRef SOSTransportMessageTestGetChanges(SOSTransportMessageTestRef transport){ + return transport->changes; +} + +static void destroyMessageTransport(SOSTransportMessageRef transport){ + SOSTransportMessageTestRef tkvs = (SOSTransportMessageTestRef)transport; + CFArrayRemoveAllValue(message_transports, tkvs); + CFReleaseNull(tkvs->circleName); + CFReleaseNull(tkvs->changes); + CFReleaseNull(tkvs->name); + +} + +static void SOSTransportMessageTestAddBulkToChanges(SOSTransportMessageTestRef transport, CFDictionaryRef updates){ + + if (transport->changes == NULL) { + transport->changes = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, CFDictionaryGetCount(updates), updates); + + } + else{ + CFDictionaryForEach(updates, ^(const void *key, const void *value) { + CFDictionarySetValue(transport->changes, key, value); + }); + } +} + +static void SOSTransportMessageTestAddToChanges(SOSTransportMessageTestRef transport, CFStringRef message_key, CFDataRef message_data){ + if (transport->changes == NULL) { + transport->changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + } + if (message_data == NULL) { + CFDictionarySetValue(transport->changes, message_key, kCFNull); + } else { + CFDictionarySetValue(transport->changes, message_key, message_data); + } +} + +static bool SOSTransportMessageTestCleanupAfterPeerMessages(SOSTransportMessageTestRef transport, CFDictionaryRef circle_to_peer_ids, CFErrorRef *error) +{ + SOSEngineRef engine = SOSTransportMessageGetEngine((SOSTransportMessageRef)transport); + require_quiet(engine, fail); + + CFArrayRef enginePeers = SOSEngineGetPeerIDs(engine); + + CFDictionaryForEach(circle_to_peer_ids, ^(const void *key, const void *value) { + if (isString(key) && isArray(value)) { + CFStringRef circle_name = (CFStringRef) key; + CFArrayRef peers_to_cleanup_after = (CFArrayRef) value; + + CFArrayForEach(peers_to_cleanup_after, ^(const void *value) { + if (isString(value)) { + CFStringRef cleanup_id = (CFStringRef) value; + // TODO: Since the enginePeers list is not authorative (the Account is) this could inadvertently clean up active peers or leave behind stale peers + if (enginePeers) CFArrayForEach(enginePeers, ^(const void *value) { + if (isString(value)) { + CFStringRef in_circle_id = (CFStringRef) value; + + CFStringRef kvsKey = SOSMessageKeyCreateWithCircleNameAndPeerNames(circle_name, cleanup_id, in_circle_id); + SOSTransportMessageTestAddToChanges(transport, kvsKey, NULL); + CFReleaseSafe(kvsKey); + + kvsKey = SOSMessageKeyCreateWithCircleNameAndPeerNames(circle_name, in_circle_id, cleanup_id); + SOSTransportMessageTestAddToChanges(transport, kvsKey, NULL); + CFReleaseSafe(kvsKey); + } + }); + + } + }); + } + }); + + return SOSTransportMessageFlushChanges((SOSTransportMessageRef)transport, error); +fail: + return true; +} + +static bool sendToPeer(SOSTransportMessageRef transport, CFStringRef circleName, CFStringRef peerID, CFDataRef message, CFErrorRef *error) { + SOSTransportMessageTestRef testTransport = (SOSTransportMessageTestRef) transport; + bool result = true; + CFStringRef message_to_peer_key = SOSMessageKeyCreateFromTransportToPeer((SOSTransportMessageKVSRef)transport, peerID); + CFDictionaryRef a_message_to_a_peer = CFDictionaryCreateForCFTypes(NULL, message_to_peer_key, message, NULL); + + SOSTransportMessageTestAddBulkToChanges((SOSTransportMessageTestRef)testTransport, a_message_to_a_peer); + CFReleaseNull(a_message_to_a_peer); + CFReleaseNull(message_to_peer_key); + + return result; +} + +static bool syncWithPeers(SOSTransportMessageRef transport, CFDictionaryRef circleToPeerIDs, CFErrorRef *error){ + // Each entry is keyed by circle name and contains a list of peerIDs + + __block bool result = true; + + CFDictionaryForEach(circleToPeerIDs, ^(const void *key, const void *value) { + if (isString(key) && isArray(value)) { + CFStringRef circleName = (CFStringRef) key; + CFArrayForEach(value, ^(const void *value) { + if (isString(value)) { + CFStringRef peerID = (CFStringRef) value; + + SOSEnginePeerMessageSentBlock sent = NULL; + CFDataRef message_to_send = NULL; + bool ok = false; + SOSPeerRef peer = SOSPeerCreateWithEngine(SOSTransportMessageGetEngine(transport), peerID); + CFDataRef coderData = SOSEngineGetCoderData(SOSTransportMessageGetEngine(transport), peerID); + + SOSCoderRef coder = SOSCoderCreateFromData(coderData, error); + SOSPeerSetCoder(peer, coder); + + ok = SOSPeerCoderSendMessageIfNeeded(peer, &message_to_send, circleName, peerID, &sent, error); + coder = SOSPeerGetCoder(peer); + + if (message_to_send) { + CFDictionaryRef peer_dict = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + peerID, message_to_send, + NULL); + + CFDictionarySetValue(SOSTransportMessageTestGetChanges((SOSTransportMessageTestRef)transport), circleName, peer_dict); + SOSPeerCoderConsume(&sent, ok); + + CFReleaseSafe(peer_dict); + } + + + Block_release(sent); + + + CFReleaseSafe(message_to_send); + + coderData = SOSCoderCopyDER(coder, error); + + if(!SOSEngineSetCoderData(SOSTransportMessageGetEngine(transport), peerID, coderData, error)){ + secerror("SOSTransportMessageSendMessageIfNeeded, Could not save peer state"); + } + CFReleaseNull(coderData); + + if (coder) + SOSCoderDispose(coder); + + CFReleaseNull(peer); + } + }); + } + }); + + return result; +} + +static bool sendMessages(SOSTransportMessageRef transport, CFDictionaryRef circleToPeersToMessage, CFErrorRef *error) { + __block bool result = true; + + 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) && isData(value)) { + CFStringRef peerID = (CFStringRef) key; + CFDataRef message = (CFDataRef) value; + bool rx = sendToPeer(transport, circleName, peerID, message, error); + result &= rx; + } + }); + } + }); + + return true; +} + +static CF_RETURNS_RETAINED +CFDictionaryRef handleMessages(SOSTransportMessageRef transport, CFMutableDictionaryRef circle_peer_messages_table, CFErrorRef *error) { + SOSTransportMessageTestRef tpt = (SOSTransportMessageTestRef)transport; + CFMutableDictionaryRef handled = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionaryRef peerToMessage = CFDictionaryGetValue(circle_peer_messages_table, tpt->circleName); + CFMutableArrayRef handled_peers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFDictionaryAddValue(handled, tpt->circleName, handled_peers); + + if(peerToMessage){ + CFDictionaryForEach(peerToMessage, ^(const void *key, const void *value) { + CFStringRef peer_id = (CFStringRef) key; + CFDataRef peer_message = (CFDataRef) value; + CFErrorRef localError = NULL; + + if (SOSTransportMessageHandlePeerMessage((SOSTransportMessageRef) transport, peer_id, peer_message, &localError)) { + CFArrayAppendValue(handled_peers, key); + } else { + secdebug("transport", "%@ KVSTransport handle message failed: %@", peer_id, localError); + } + CFReleaseNull(localError); + }); + } + CFReleaseNull(handled_peers); + + return handled; +} + +static bool flushMessageChanges(SOSTransportMessageRef transport, CFErrorRef *error) +{ + return true; +} + +static bool cleanupAfterPeer(SOSTransportMessageRef transport, CFDictionaryRef circle_to_peer_ids, CFErrorRef *error) +{ + return SOSTransportMessageTestCleanupAfterPeerMessages((SOSTransportMessageTestRef) transport, circle_to_peer_ids, error); +} + +SOSAccountRef SOSTransportMessageTestGetAccount(SOSTransportMessageTestRef transport) { + return ((SOSTransportMessageRef)transport)->account; +} + diff --git a/Security/sec/securityd/Regressions/SOSTransportTestTransports.h b/Security/sec/securityd/Regressions/SOSTransportTestTransports.h new file mode 100644 index 00000000..6df9dad2 --- /dev/null +++ b/Security/sec/securityd/Regressions/SOSTransportTestTransports.h @@ -0,0 +1,41 @@ +#ifndef SEC_SOSTransportTestTransports_h +#define SEC_SOSTransportTestTransports_h + +typedef struct SOSTransportKeyParameterTest *SOSTransportKeyParameterTestRef; +typedef struct SOSTransportCircleTest *SOSTransportCircleTestRef; +typedef struct SOSTransportMessageTest *SOSTransportMessageTestRef; + +CF_RETURNS_RETAINED +CFDictionaryRef SOSTransportMessageTestHandleMessages(SOSTransportMessageTestRef transport, CFMutableDictionaryRef circle_peer_messages_table, CFErrorRef *error); + +void SOSAccountUpdateTestTransports(SOSAccountRef account, CFDictionaryRef gestalt); + +SOSTransportKeyParameterTestRef SOSTransportTestCreateKeyParameter(SOSAccountRef account, CFStringRef name, CFStringRef circleName); +SOSTransportCircleTestRef SOSTransportTestCreateCircle(SOSAccountRef account, CFStringRef name, CFStringRef circleName); +SOSTransportMessageTestRef SOSTransportTestCreateMessage(SOSAccountRef account, CFStringRef name, CFStringRef circleName); + +CFMutableArrayRef key_transports; +CFMutableArrayRef circle_transports; +CFMutableArrayRef message_transports; + +CFStringRef SOSTransportMessageTestGetName(SOSTransportMessageTestRef transport); +CFStringRef SOSTransportCircleTestGetName(SOSTransportCircleTestRef transport); +CFStringRef SOSTransportKeyParameterTestGetName(SOSTransportKeyParameterTestRef transport); + +void SOSTransportKeyParameterTestSetName(SOSTransportKeyParameterTestRef transport, CFStringRef accountName); +void SOSTransportCircleTestSetName(SOSTransportCircleTestRef transport, CFStringRef accountName); +void SOSTransportMessageTestSetName(SOSTransportMessageTestRef transport, CFStringRef accountName); + + +CFMutableDictionaryRef SOSTransportMessageTestGetChanges(SOSTransportMessageTestRef transport); +CFMutableDictionaryRef SOSTransportCircleTestGetChanges(SOSTransportCircleTestRef transport); +CFMutableDictionaryRef SOSTransportKeyParameterTestGetChanges(SOSTransportKeyParameterTestRef transport); + +SOSAccountRef SOSTransportMessageTestGetAccount(SOSTransportMessageTestRef transport); +SOSAccountRef SOSTransportCircleTestGetAccount(SOSTransportCircleTestRef transport); +SOSAccountRef SOSTransportKeyParameterTestGetAccount(SOSTransportKeyParameterTestRef transport); + +bool SOSAccountInflateTestTransportsForCircle(SOSAccountRef account, CFStringRef circleName, CFStringRef accountName, CFErrorRef *error); +bool SOSAccountEnsureFactoryCirclesTest(SOSAccountRef a, CFStringRef accountName); + +#endif diff --git a/Security/sec/securityd/Regressions/SecdTestKeychainUtilities.c b/Security/sec/securityd/Regressions/SecdTestKeychainUtilities.c new file mode 100644 index 00000000..e70a7be3 --- /dev/null +++ b/Security/sec/securityd/Regressions/SecdTestKeychainUtilities.c @@ -0,0 +1,59 @@ +/* + * 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 "SecdTestKeychainUtilities.h" + +#include +#include +#include + +#include + +//#include +#include +#include +#include + +void kc_dbhandle_reset(void); + +void secd_test_setup_temp_keychain(const char* test_prefix, dispatch_block_t do_before_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); + + CFStringPerformWithCString(keychain_dir, ^(const char *keychain_dir_string) { + ok_unix(mkpath_np(keychain_dir_string, 0755), "Create temp dir %s", keychain_dir_string); + }); + + + /* set custom keychain dir, reset db */ + CFStringPerformWithCString(tmp_dir, ^(const char *tmp_dir_string) { + SetCustomHomeURL(tmp_dir_string); + }); + + if(do_before_reset) + do_before_reset(); + + kc_dbhandle_reset(); +} diff --git a/Security/sec/securityd/Regressions/SecdTestKeychainUtilities.h b/Security/sec/securityd/Regressions/SecdTestKeychainUtilities.h new file mode 100644 index 00000000..e7a1696c --- /dev/null +++ b/Security/sec/securityd/Regressions/SecdTestKeychainUtilities.h @@ -0,0 +1,33 @@ +/* + * 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@ + */ + + +#ifndef _SECDTESTKEYCHAINUTILITIES_ +#define _SECDTESTKEYCHAINUTILITIES_ + +#include + +#define kSecdTestSetupTestCount 1 +void secd_test_setup_temp_keychain(const char* test_prefix, dispatch_block_t do_before_reset); + +#endif diff --git a/Security/sec/securityd/Regressions/ios6_1_keychain_2_db.h b/Security/sec/securityd/Regressions/ios6_1_keychain_2_db.h new file mode 100644 index 00000000..a4eec207 --- /dev/null +++ b/Security/sec/securityd/Regressions/ios6_1_keychain_2_db.h @@ -0,0 +1,10586 @@ +unsigned char ios6_1_keychain_2_db[] = { + 0x53, 0x51, 0x4c, 0x69, 0x74, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x20, 0x33, 0x00, 0x10, 0x00, 0x01, 0x01, 0x00, 0x40, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, + 0x00, 0x2d, 0xe2, 0x25, 0x0d, 0x0f, 0xfc, 0x00, 0x17, 0x04, 0x99, 0x00, + 0x0e, 0x72, 0x0f, 0xd3, 0x0e, 0x20, 0x0b, 0xed, 0x0d, 0xf7, 0x0a, 0x89, + 0x0b, 0xc4, 0x07, 0xa8, 0x0a, 0x60, 0x07, 0x64, 0x07, 0x2d, 0x06, 0xf6, + 0x06, 0xbf, 0x06, 0x88, 0x06, 0x51, 0x06, 0x1a, 0x05, 0xe3, 0x05, 0xac, + 0x05, 0x75, 0x05, 0x3e, 0x05, 0x07, 0x04, 0xd0, 0x04, 0x99, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x35, 0x17, 0x06, 0x17, 0x17, 0x15, 0x01, 0x4d, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x69, 0x75, 0x6e, 0x77, 0x70, 0x6b, 0x65, 0x79, 0x73, 0x18, + 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x49, 0x4e, 0x44, 0x45, 0x58, + 0x20, 0x69, 0x75, 0x6e, 0x77, 0x70, 0x20, 0x4f, 0x4e, 0x20, 0x6b, 0x65, + 0x79, 0x73, 0x28, 0x75, 0x6e, 0x77, 0x70, 0x29, 0x35, 0x16, 0x06, 0x17, + 0x17, 0x15, 0x01, 0x4d, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x69, 0x77, 0x72, + 0x61, 0x70, 0x6b, 0x65, 0x79, 0x73, 0x17, 0x43, 0x52, 0x45, 0x41, 0x54, + 0x45, 0x20, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x20, 0x69, 0x77, 0x72, 0x61, + 0x70, 0x20, 0x4f, 0x4e, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x77, 0x72, + 0x61, 0x70, 0x29, 0x35, 0x15, 0x06, 0x17, 0x17, 0x15, 0x01, 0x4d, 0x69, + 0x6e, 0x64, 0x65, 0x78, 0x69, 0x76, 0x72, 0x66, 0x79, 0x6b, 0x65, 0x79, + 0x73, 0x16, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x49, 0x4e, 0x44, + 0x45, 0x58, 0x20, 0x69, 0x76, 0x72, 0x66, 0x79, 0x20, 0x4f, 0x4e, 0x20, + 0x6b, 0x65, 0x79, 0x73, 0x28, 0x76, 0x72, 0x66, 0x79, 0x29, 0x35, 0x14, + 0x06, 0x17, 0x17, 0x15, 0x01, 0x4d, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x69, + 0x73, 0x69, 0x67, 0x6e, 0x6b, 0x65, 0x79, 0x73, 0x15, 0x43, 0x52, 0x45, + 0x41, 0x54, 0x45, 0x20, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x20, 0x69, 0x73, + 0x69, 0x67, 0x6e, 0x20, 0x4f, 0x4e, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x28, + 0x73, 0x69, 0x67, 0x6e, 0x29, 0x35, 0x13, 0x06, 0x17, 0x17, 0x15, 0x01, + 0x4d, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x69, 0x64, 0x72, 0x76, 0x65, 0x6b, + 0x65, 0x79, 0x73, 0x14, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x49, + 0x4e, 0x44, 0x45, 0x58, 0x20, 0x69, 0x64, 0x72, 0x76, 0x65, 0x20, 0x4f, + 0x4e, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x64, 0x72, 0x76, 0x65, 0x29, + 0x35, 0x12, 0x06, 0x17, 0x17, 0x15, 0x01, 0x4d, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x69, 0x64, 0x65, 0x63, 0x72, 0x6b, 0x65, 0x79, 0x73, 0x13, 0x43, + 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x20, + 0x69, 0x64, 0x65, 0x63, 0x72, 0x20, 0x4f, 0x4e, 0x20, 0x6b, 0x65, 0x79, + 0x73, 0x28, 0x64, 0x65, 0x63, 0x72, 0x29, 0x35, 0x11, 0x06, 0x17, 0x17, + 0x15, 0x01, 0x4d, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x69, 0x65, 0x6e, 0x63, + 0x72, 0x6b, 0x65, 0x79, 0x73, 0x12, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, + 0x20, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x20, 0x69, 0x65, 0x6e, 0x63, 0x72, + 0x20, 0x4f, 0x4e, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x65, 0x6e, 0x63, + 0x72, 0x29, 0x35, 0x10, 0x06, 0x17, 0x17, 0x15, 0x01, 0x4d, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x69, 0x6b, 0x6c, 0x62, 0x6c, 0x6b, 0x65, 0x79, 0x73, + 0x11, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x49, 0x4e, 0x44, 0x45, + 0x58, 0x20, 0x69, 0x6b, 0x6c, 0x62, 0x6c, 0x20, 0x4f, 0x4e, 0x20, 0x6b, + 0x65, 0x79, 0x73, 0x28, 0x6b, 0x6c, 0x62, 0x6c, 0x29, 0x35, 0x0f, 0x06, + 0x17, 0x17, 0x15, 0x01, 0x4d, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x69, 0x6b, + 0x63, 0x6c, 0x73, 0x6b, 0x65, 0x79, 0x73, 0x10, 0x43, 0x52, 0x45, 0x41, + 0x54, 0x45, 0x20, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x20, 0x69, 0x6b, 0x63, + 0x6c, 0x73, 0x20, 0x4f, 0x4e, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x6b, + 0x63, 0x6c, 0x73, 0x29, 0x35, 0x0e, 0x06, 0x17, 0x17, 0x15, 0x01, 0x4d, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x69, 0x70, 0x6b, 0x68, 0x68, 0x63, 0x65, + 0x72, 0x74, 0x0f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x49, 0x4e, + 0x44, 0x45, 0x58, 0x20, 0x69, 0x70, 0x6b, 0x68, 0x68, 0x20, 0x4f, 0x4e, + 0x20, 0x63, 0x65, 0x72, 0x74, 0x28, 0x70, 0x6b, 0x68, 0x68, 0x29, 0x35, + 0x0d, 0x06, 0x17, 0x17, 0x15, 0x01, 0x4d, 0x69, 0x6e, 0x64, 0x65, 0x78, + 0x69, 0x73, 0x6b, 0x69, 0x64, 0x63, 0x65, 0x72, 0x74, 0x0e, 0x43, 0x52, + 0x45, 0x41, 0x54, 0x45, 0x20, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x20, 0x69, + 0x73, 0x6b, 0x69, 0x64, 0x20, 0x4f, 0x4e, 0x20, 0x63, 0x65, 0x72, 0x74, + 0x28, 0x73, 0x6b, 0x69, 0x64, 0x29, 0x35, 0x0c, 0x06, 0x17, 0x17, 0x15, + 0x01, 0x4d, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x69, 0x73, 0x75, 0x62, 0x6a, + 0x63, 0x65, 0x72, 0x74, 0x0d, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, + 0x49, 0x4e, 0x44, 0x45, 0x58, 0x20, 0x69, 0x73, 0x75, 0x62, 0x6a, 0x20, + 0x4f, 0x4e, 0x20, 0x63, 0x65, 0x72, 0x74, 0x28, 0x73, 0x75, 0x62, 0x6a, + 0x29, 0x35, 0x0b, 0x06, 0x17, 0x17, 0x15, 0x01, 0x4d, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x69, 0x61, 0x6c, 0x69, 0x73, 0x63, 0x65, 0x72, 0x74, 0x0c, + 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x49, 0x4e, 0x44, 0x45, 0x58, + 0x20, 0x69, 0x61, 0x6c, 0x69, 0x73, 0x20, 0x4f, 0x4e, 0x20, 0x63, 0x65, + 0x72, 0x74, 0x28, 0x61, 0x6c, 0x69, 0x73, 0x29, 0x42, 0x0a, 0x06, 0x17, + 0x1d, 0x1d, 0x01, 0x59, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x74, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x0b, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x54, 0x41, 0x42, + 0x4c, 0x45, 0x20, 0x74, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x28, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x4e, 0x54, 0x45, + 0x47, 0x45, 0x52, 0x29, 0x85, 0x35, 0x08, 0x07, 0x17, 0x15, 0x15, 0x01, + 0x8a, 0x4d, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x6b, 0x65, 0x79, 0x73, 0x6b, + 0x65, 0x79, 0x73, 0x09, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x54, + 0x41, 0x42, 0x4c, 0x45, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x72, 0x6f, + 0x77, 0x69, 0x64, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x20, + 0x50, 0x52, 0x49, 0x4d, 0x41, 0x52, 0x59, 0x20, 0x4b, 0x45, 0x59, 0x20, + 0x41, 0x55, 0x54, 0x4f, 0x49, 0x4e, 0x43, 0x52, 0x45, 0x4d, 0x45, 0x4e, + 0x54, 0x2c, 0x63, 0x64, 0x61, 0x74, 0x20, 0x52, 0x45, 0x41, 0x4c, 0x2c, + 0x6d, 0x64, 0x61, 0x74, 0x20, 0x52, 0x45, 0x41, 0x4c, 0x2c, 0x6b, 0x63, + 0x6c, 0x73, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x20, 0x4e, + 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, + 0x55, 0x4c, 0x54, 0x20, 0x30, 0x2c, 0x6c, 0x61, 0x62, 0x6c, 0x20, 0x42, + 0x4c, 0x4f, 0x42, 0x2c, 0x61, 0x6c, 0x69, 0x73, 0x20, 0x42, 0x4c, 0x4f, + 0x42, 0x2c, 0x70, 0x65, 0x72, 0x6d, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, + 0x45, 0x52, 0x2c, 0x70, 0x72, 0x69, 0x76, 0x20, 0x49, 0x4e, 0x54, 0x45, + 0x47, 0x45, 0x52, 0x2c, 0x6d, 0x6f, 0x64, 0x69, 0x20, 0x49, 0x4e, 0x54, + 0x45, 0x47, 0x45, 0x52, 0x2c, 0x6b, 0x6c, 0x62, 0x6c, 0x20, 0x42, 0x4c, + 0x4f, 0x42, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, + 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x27, 0x27, 0x2c, 0x61, + 0x74, 0x61, 0x67, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x20, 0x4e, 0x4f, 0x54, + 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, + 0x54, 0x20, 0x27, 0x27, 0x2c, 0x63, 0x72, 0x74, 0x72, 0x20, 0x49, 0x4e, + 0x54, 0x45, 0x47, 0x45, 0x52, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, + 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x30, + 0x2c, 0x74, 0x79, 0x70, 0x65, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, + 0x52, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, + 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x30, 0x2c, 0x62, 0x73, 0x69, + 0x7a, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x20, 0x4e, 0x4f, + 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, + 0x4c, 0x54, 0x20, 0x30, 0x2c, 0x65, 0x73, 0x69, 0x7a, 0x20, 0x49, 0x4e, + 0x54, 0x45, 0x47, 0x45, 0x52, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, + 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x30, + 0x2c, 0x73, 0x64, 0x61, 0x74, 0x20, 0x52, 0x45, 0x41, 0x4c, 0x20, 0x4e, + 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, + 0x55, 0x4c, 0x54, 0x20, 0x30, 0x2c, 0x65, 0x64, 0x61, 0x74, 0x20, 0x52, + 0x45, 0x41, 0x4c, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, + 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x30, 0x2c, 0x73, + 0x65, 0x6e, 0x73, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, + 0x61, 0x73, 0x65, 0x6e, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, + 0x2c, 0x65, 0x78, 0x74, 0x72, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, + 0x52, 0x2c, 0x6e, 0x65, 0x78, 0x74, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, + 0x45, 0x52, 0x2c, 0x65, 0x6e, 0x63, 0x72, 0x20, 0x49, 0x4e, 0x54, 0x45, + 0x47, 0x45, 0x52, 0x2c, 0x64, 0x65, 0x63, 0x72, 0x20, 0x49, 0x4e, 0x54, + 0x45, 0x47, 0x45, 0x52, 0x2c, 0x64, 0x72, 0x76, 0x65, 0x20, 0x49, 0x4e, + 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x73, 0x69, 0x67, 0x6e, 0x20, 0x49, + 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x76, 0x72, 0x66, 0x79, 0x20, + 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x73, 0x6e, 0x72, 0x63, + 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x76, 0x79, 0x72, + 0x63, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x77, 0x72, + 0x61, 0x70, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x75, + 0x6e, 0x77, 0x70, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, + 0x64, 0x61, 0x74, 0x61, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x61, 0x67, + 0x72, 0x70, 0x20, 0x54, 0x45, 0x58, 0x54, 0x2c, 0x70, 0x64, 0x6d, 0x6e, + 0x20, 0x54, 0x45, 0x58, 0x54, 0x2c, 0x55, 0x4e, 0x49, 0x51, 0x55, 0x45, + 0x28, 0x6b, 0x63, 0x6c, 0x73, 0x2c, 0x6b, 0x6c, 0x62, 0x6c, 0x2c, 0x61, + 0x74, 0x61, 0x67, 0x2c, 0x63, 0x72, 0x74, 0x72, 0x2c, 0x74, 0x79, 0x70, + 0x65, 0x2c, 0x62, 0x73, 0x69, 0x7a, 0x2c, 0x65, 0x73, 0x69, 0x7a, 0x2c, + 0x73, 0x64, 0x61, 0x74, 0x2c, 0x65, 0x64, 0x61, 0x74, 0x2c, 0x61, 0x67, + 0x72, 0x70, 0x29, 0x29, 0x27, 0x09, 0x06, 0x17, 0x3b, 0x15, 0x01, 0x00, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x73, 0x71, 0x6c, 0x69, 0x74, 0x65, 0x5f, + 0x61, 0x75, 0x74, 0x6f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x6b, 0x65, + 0x79, 0x73, 0x5f, 0x31, 0x6b, 0x65, 0x79, 0x73, 0x0a, 0x82, 0x38, 0x06, + 0x07, 0x17, 0x15, 0x15, 0x01, 0x84, 0x53, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x63, 0x65, 0x72, 0x74, 0x63, 0x65, 0x72, 0x74, 0x07, 0x43, 0x52, 0x45, + 0x41, 0x54, 0x45, 0x20, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x20, 0x63, 0x65, + 0x72, 0x74, 0x28, 0x72, 0x6f, 0x77, 0x69, 0x64, 0x20, 0x49, 0x4e, 0x54, + 0x45, 0x47, 0x45, 0x52, 0x20, 0x50, 0x52, 0x49, 0x4d, 0x41, 0x52, 0x59, + 0x20, 0x4b, 0x45, 0x59, 0x20, 0x41, 0x55, 0x54, 0x4f, 0x49, 0x4e, 0x43, + 0x52, 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x2c, 0x63, 0x64, 0x61, 0x74, 0x20, + 0x52, 0x45, 0x41, 0x4c, 0x2c, 0x6d, 0x64, 0x61, 0x74, 0x20, 0x52, 0x45, + 0x41, 0x4c, 0x2c, 0x63, 0x74, 0x79, 0x70, 0x20, 0x49, 0x4e, 0x54, 0x45, + 0x47, 0x45, 0x52, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, + 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x30, 0x2c, 0x63, + 0x65, 0x6e, 0x63, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, + 0x6c, 0x61, 0x62, 0x6c, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x61, 0x6c, + 0x69, 0x73, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x73, 0x75, 0x62, 0x6a, + 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x69, 0x73, 0x73, 0x72, 0x20, 0x42, + 0x4c, 0x4f, 0x42, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, + 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x27, 0x27, 0x2c, + 0x73, 0x6c, 0x6e, 0x72, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x20, 0x4e, 0x4f, + 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, + 0x4c, 0x54, 0x20, 0x27, 0x27, 0x2c, 0x73, 0x6b, 0x69, 0x64, 0x20, 0x42, + 0x4c, 0x4f, 0x42, 0x2c, 0x70, 0x6b, 0x68, 0x68, 0x20, 0x42, 0x4c, 0x4f, + 0x42, 0x2c, 0x64, 0x61, 0x74, 0x61, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, + 0x61, 0x67, 0x72, 0x70, 0x20, 0x54, 0x45, 0x58, 0x54, 0x2c, 0x70, 0x64, + 0x6d, 0x6e, 0x20, 0x54, 0x45, 0x58, 0x54, 0x2c, 0x55, 0x4e, 0x49, 0x51, + 0x55, 0x45, 0x28, 0x63, 0x74, 0x79, 0x70, 0x2c, 0x69, 0x73, 0x73, 0x72, + 0x2c, 0x73, 0x6c, 0x6e, 0x72, 0x2c, 0x61, 0x67, 0x72, 0x70, 0x29, 0x29, + 0x27, 0x07, 0x06, 0x17, 0x3b, 0x15, 0x01, 0x00, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x73, 0x71, 0x6c, 0x69, 0x74, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x6f, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x31, + 0x63, 0x65, 0x72, 0x74, 0x08, 0x84, 0x07, 0x04, 0x07, 0x17, 0x15, 0x15, + 0x01, 0x87, 0x71, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x69, 0x6e, 0x65, 0x74, + 0x69, 0x6e, 0x65, 0x74, 0x05, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, + 0x54, 0x41, 0x42, 0x4c, 0x45, 0x20, 0x69, 0x6e, 0x65, 0x74, 0x28, 0x72, + 0x6f, 0x77, 0x69, 0x64, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, + 0x20, 0x50, 0x52, 0x49, 0x4d, 0x41, 0x52, 0x59, 0x20, 0x4b, 0x45, 0x59, + 0x20, 0x41, 0x55, 0x54, 0x4f, 0x49, 0x4e, 0x43, 0x52, 0x45, 0x4d, 0x45, + 0x4e, 0x54, 0x2c, 0x63, 0x64, 0x61, 0x74, 0x20, 0x52, 0x45, 0x41, 0x4c, + 0x2c, 0x6d, 0x64, 0x61, 0x74, 0x20, 0x52, 0x45, 0x41, 0x4c, 0x2c, 0x64, + 0x65, 0x73, 0x63, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x69, 0x63, 0x6d, + 0x74, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x63, 0x72, 0x74, 0x72, 0x20, + 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x74, 0x79, 0x70, 0x65, + 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x73, 0x63, 0x72, + 0x70, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x6c, 0x61, + 0x62, 0x6c, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x61, 0x6c, 0x69, 0x73, + 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x69, 0x6e, 0x76, 0x69, 0x20, 0x49, + 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x6e, 0x65, 0x67, 0x61, 0x20, + 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x63, 0x75, 0x73, 0x69, + 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x70, 0x72, 0x6f, + 0x74, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x61, 0x63, 0x63, 0x74, 0x20, + 0x42, 0x4c, 0x4f, 0x42, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, + 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x27, 0x27, + 0x2c, 0x73, 0x64, 0x6d, 0x6e, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x20, 0x4e, + 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, + 0x55, 0x4c, 0x54, 0x20, 0x27, 0x27, 0x2c, 0x73, 0x72, 0x76, 0x72, 0x20, + 0x42, 0x4c, 0x4f, 0x42, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, + 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x27, 0x27, + 0x2c, 0x70, 0x74, 0x63, 0x6c, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, + 0x52, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, + 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x30, 0x2c, 0x61, 0x74, 0x79, + 0x70, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, + 0x55, 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, + 0x27, 0x27, 0x2c, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x49, 0x4e, 0x54, 0x45, + 0x47, 0x45, 0x52, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, + 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x30, 0x2c, 0x70, + 0x61, 0x74, 0x68, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x20, 0x4e, 0x4f, 0x54, + 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, + 0x54, 0x20, 0x27, 0x27, 0x2c, 0x64, 0x61, 0x74, 0x61, 0x20, 0x42, 0x4c, + 0x4f, 0x42, 0x2c, 0x61, 0x67, 0x72, 0x70, 0x20, 0x54, 0x45, 0x58, 0x54, + 0x2c, 0x70, 0x64, 0x6d, 0x6e, 0x20, 0x54, 0x45, 0x58, 0x54, 0x2c, 0x55, + 0x4e, 0x49, 0x51, 0x55, 0x45, 0x28, 0x61, 0x63, 0x63, 0x74, 0x2c, 0x73, + 0x64, 0x6d, 0x6e, 0x2c, 0x73, 0x72, 0x76, 0x72, 0x2c, 0x70, 0x74, 0x63, + 0x6c, 0x2c, 0x61, 0x74, 0x79, 0x70, 0x2c, 0x70, 0x6f, 0x72, 0x74, 0x2c, + 0x70, 0x61, 0x74, 0x68, 0x2c, 0x61, 0x67, 0x72, 0x70, 0x29, 0x29, 0x27, + 0x05, 0x06, 0x17, 0x3b, 0x15, 0x01, 0x00, 0x69, 0x6e, 0x64, 0x65, 0x78, + 0x73, 0x71, 0x6c, 0x69, 0x74, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x69, + 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x69, 0x6e, 0x65, 0x74, 0x5f, 0x31, 0x69, + 0x6e, 0x65, 0x74, 0x06, 0x50, 0x03, 0x06, 0x17, 0x2b, 0x2b, 0x01, 0x59, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x71, 0x6c, 0x69, 0x74, 0x65, 0x5f, + 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x71, 0x6c, 0x69, + 0x74, 0x65, 0x5f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x04, + 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x54, 0x41, 0x42, 0x4c, 0x45, + 0x20, 0x73, 0x71, 0x6c, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x65, 0x71, 0x75, + 0x65, 0x6e, 0x63, 0x65, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x73, 0x65, + 0x71, 0x29, 0x82, 0x5e, 0x01, 0x07, 0x17, 0x15, 0x15, 0x01, 0x85, 0x1f, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x67, 0x65, 0x6e, 0x70, 0x67, 0x65, 0x6e, + 0x70, 0x02, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x54, 0x41, 0x42, + 0x4c, 0x45, 0x20, 0x67, 0x65, 0x6e, 0x70, 0x28, 0x72, 0x6f, 0x77, 0x69, + 0x64, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x20, 0x50, 0x52, + 0x49, 0x4d, 0x41, 0x52, 0x59, 0x20, 0x4b, 0x45, 0x59, 0x20, 0x41, 0x55, + 0x54, 0x4f, 0x49, 0x4e, 0x43, 0x52, 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x2c, + 0x63, 0x64, 0x61, 0x74, 0x20, 0x52, 0x45, 0x41, 0x4c, 0x2c, 0x6d, 0x64, + 0x61, 0x74, 0x20, 0x52, 0x45, 0x41, 0x4c, 0x2c, 0x64, 0x65, 0x73, 0x63, + 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x69, 0x63, 0x6d, 0x74, 0x20, 0x42, + 0x4c, 0x4f, 0x42, 0x2c, 0x63, 0x72, 0x74, 0x72, 0x20, 0x49, 0x4e, 0x54, + 0x45, 0x47, 0x45, 0x52, 0x2c, 0x74, 0x79, 0x70, 0x65, 0x20, 0x49, 0x4e, + 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x73, 0x63, 0x72, 0x70, 0x20, 0x49, + 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x6c, 0x61, 0x62, 0x6c, 0x20, + 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x61, 0x6c, 0x69, 0x73, 0x20, 0x42, 0x4c, + 0x4f, 0x42, 0x2c, 0x69, 0x6e, 0x76, 0x69, 0x20, 0x49, 0x4e, 0x54, 0x45, + 0x47, 0x45, 0x52, 0x2c, 0x6e, 0x65, 0x67, 0x61, 0x20, 0x49, 0x4e, 0x54, + 0x45, 0x47, 0x45, 0x52, 0x2c, 0x63, 0x75, 0x73, 0x69, 0x20, 0x49, 0x4e, + 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x70, 0x72, 0x6f, 0x74, 0x20, 0x42, + 0x4c, 0x4f, 0x42, 0x2c, 0x61, 0x63, 0x63, 0x74, 0x20, 0x42, 0x4c, 0x4f, + 0x42, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, + 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x27, 0x27, 0x2c, 0x73, 0x76, + 0x63, 0x65, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x20, 0x4e, 0x4f, 0x54, 0x20, + 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, + 0x20, 0x27, 0x27, 0x2c, 0x67, 0x65, 0x6e, 0x61, 0x20, 0x42, 0x4c, 0x4f, + 0x42, 0x2c, 0x64, 0x61, 0x74, 0x61, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, + 0x61, 0x67, 0x72, 0x70, 0x20, 0x54, 0x45, 0x58, 0x54, 0x2c, 0x70, 0x64, + 0x6d, 0x6e, 0x20, 0x54, 0x45, 0x58, 0x54, 0x2c, 0x55, 0x4e, 0x49, 0x51, + 0x55, 0x45, 0x28, 0x61, 0x63, 0x63, 0x74, 0x2c, 0x73, 0x76, 0x63, 0x65, + 0x2c, 0x61, 0x67, 0x72, 0x70, 0x29, 0x29, 0x27, 0x02, 0x06, 0x17, 0x3b, + 0x15, 0x01, 0x00, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x73, 0x71, 0x6c, 0x69, + 0x74, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x69, 0x6e, 0x64, 0x65, 0x78, + 0x5f, 0x67, 0x65, 0x6e, 0x70, 0x5f, 0x31, 0x67, 0x65, 0x6e, 0x70, 0x03, + 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x01, 0x0f, 0xfb, 0x00, + 0x00, 0x00, 0x00, 0x1a, 0x0f, 0xfb, 0x0f, 0xf6, 0x04, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x55, 0x07, + 0x16, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x34, 0x34, 0x00, 0x88, 0x0a, 0x17, 0x13, 0x41, 0xb7, + 0x59, 0x5c, 0x7e, 0xdf, 0xaa, 0x7a, 0x41, 0xb7, 0x59, 0x5c, 0x7e, 0xdf, + 0xaa, 0x7a, 0x0b, 0x66, 0x7c, 0x18, 0x9e, 0x44, 0x49, 0x2d, 0x40, 0x62, + 0x95, 0x22, 0xa7, 0xe3, 0x08, 0x19, 0x26, 0x0f, 0xd6, 0x6d, 0x3a, 0xdc, + 0x09, 0xb3, 0xcd, 0x3d, 0x7c, 0x47, 0x10, 0xf5, 0x62, 0xa0, 0x5b, 0xd8, + 0x50, 0xe7, 0x56, 0xcb, 0xa1, 0xb8, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, + 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x64, 0x0f, 0xc5, 0x21, 0x02, 0x15, + 0x7c, 0xa5, 0xb2, 0x07, 0xf2, 0xee, 0xe7, 0xeb, 0x55, 0xb1, 0x73, 0x0b, + 0xc7, 0x85, 0xd2, 0x16, 0x2f, 0x68, 0x13, 0x3e, 0x6a, 0x6b, 0x3a, 0x3d, + 0xbd, 0x3d, 0xd9, 0xc4, 0x98, 0x92, 0xea, 0x5a, 0xf1, 0xf3, 0x69, 0x0e, + 0x20, 0x7b, 0x97, 0xca, 0xe6, 0x21, 0x45, 0x98, 0xcf, 0x92, 0x04, 0xf5, + 0xc9, 0x46, 0x27, 0xd4, 0x4f, 0x83, 0x2c, 0x3b, 0xbb, 0x83, 0x22, 0xa3, + 0x3c, 0x4e, 0x8e, 0x37, 0x6e, 0xe1, 0x6f, 0x80, 0x83, 0x0f, 0x19, 0xed, + 0x17, 0xdb, 0xd1, 0x96, 0xb9, 0x33, 0xe6, 0x25, 0x50, 0x4f, 0x40, 0x36, + 0xbf, 0x42, 0x46, 0xfc, 0x1c, 0x4a, 0x84, 0x9a, 0xb5, 0xcb, 0xe1, 0xee, + 0x4c, 0x84, 0xde, 0x41, 0x9f, 0x69, 0x3d, 0x9c, 0xe5, 0x38, 0x68, 0xb1, + 0x9c, 0x59, 0xd6, 0xcf, 0xcd, 0x76, 0xc3, 0xa7, 0x99, 0xf2, 0xe5, 0x8d, + 0x3b, 0x02, 0xcc, 0x1a, 0xed, 0x52, 0xd6, 0xef, 0x8f, 0xb2, 0xba, 0x11, + 0x39, 0xa5, 0x82, 0x12, 0x04, 0x2b, 0x03, 0xda, 0x41, 0x8c, 0x9e, 0xe1, + 0xc0, 0x8d, 0xdb, 0xff, 0x46, 0xce, 0xa9, 0xf3, 0x70, 0xf0, 0x5a, 0xd9, + 0x5e, 0xc1, 0xa3, 0xca, 0xd4, 0x02, 0x2a, 0xce, 0x49, 0x55, 0x61, 0x5d, + 0x22, 0xbf, 0xf6, 0x5a, 0xe6, 0xe4, 0xb4, 0x7a, 0xe2, 0x47, 0x24, 0x72, + 0xba, 0x8b, 0xd2, 0x39, 0x49, 0xf2, 0xa0, 0xda, 0xe6, 0xb6, 0xe1, 0x79, + 0xdc, 0x0d, 0x73, 0x1b, 0xe6, 0x40, 0xe4, 0xda, 0x74, 0x7c, 0xa4, 0x81, + 0x4b, 0x79, 0x8c, 0x23, 0x8d, 0xd5, 0x9d, 0xe0, 0x01, 0xe2, 0x88, 0xa8, + 0x3f, 0x09, 0xec, 0xf3, 0xa8, 0xd5, 0x8b, 0xe2, 0xef, 0x0e, 0x0c, 0x42, + 0x37, 0xc0, 0x2a, 0x7d, 0x25, 0x56, 0xc4, 0x28, 0xc3, 0x70, 0x73, 0xe7, + 0x14, 0xd0, 0xa8, 0x1e, 0x2a, 0xd7, 0xd6, 0x85, 0x0f, 0x4b, 0x94, 0x8d, + 0xa3, 0xb2, 0xee, 0x83, 0x36, 0x0a, 0x59, 0x4b, 0x8a, 0xc3, 0xf8, 0xd1, + 0x64, 0xb4, 0x07, 0x7c, 0x3d, 0x98, 0xaf, 0x7c, 0xd2, 0xed, 0x2a, 0xa2, + 0x91, 0xf4, 0x32, 0xa8, 0xf1, 0x67, 0x0a, 0x34, 0x75, 0x88, 0x4e, 0x69, + 0x78, 0xca, 0xa4, 0x0c, 0xf8, 0x40, 0x9f, 0x86, 0xd9, 0x16, 0x56, 0x67, + 0x74, 0xd4, 0x33, 0x9e, 0xb7, 0xef, 0xa6, 0xdf, 0x32, 0xb2, 0x24, 0x20, + 0xe7, 0xe9, 0x80, 0xdf, 0x7b, 0xa3, 0x49, 0x04, 0xd7, 0x3f, 0x9f, 0xbe, + 0xa6, 0x2d, 0xd0, 0xec, 0xed, 0x04, 0x76, 0xc9, 0x38, 0x0b, 0x2c, 0x02, + 0xcc, 0xd0, 0x98, 0x02, 0x73, 0x96, 0x6b, 0x8b, 0xcb, 0x2b, 0x57, 0x2d, + 0xab, 0x0d, 0x5e, 0x97, 0xb8, 0xd9, 0x81, 0xa6, 0x09, 0x7c, 0x6a, 0x6a, + 0xbe, 0xed, 0x44, 0xe1, 0x87, 0x2a, 0xbd, 0xad, 0x61, 0xfa, 0xdc, 0x76, + 0xaa, 0xa5, 0xfd, 0x40, 0xee, 0x9f, 0xf1, 0xc6, 0x74, 0xe9, 0xba, 0xc1, + 0xaf, 0xf1, 0x5d, 0x16, 0x06, 0x27, 0x60, 0x2b, 0x96, 0x9d, 0x0d, 0xc1, + 0x7c, 0xc3, 0x7b, 0xfd, 0x33, 0xc2, 0xa6, 0x7c, 0xbc, 0xc3, 0x1c, 0xef, + 0x9d, 0xf4, 0xe2, 0x8c, 0x2d, 0xe3, 0x01, 0xc1, 0x95, 0x24, 0x66, 0x15, + 0x1a, 0xa1, 0xa0, 0x61, 0x28, 0x8f, 0x44, 0x77, 0x80, 0xfc, 0x11, 0xce, + 0xad, 0xe1, 0xf1, 0xe9, 0x80, 0x55, 0x6d, 0x77, 0x5d, 0xf7, 0x2a, 0xf8, + 0x15, 0x42, 0xdd, 0xf6, 0x62, 0xac, 0x68, 0x8f, 0xaa, 0x85, 0xd8, 0xfa, + 0xc6, 0x21, 0xe9, 0xa8, 0xa2, 0x1e, 0xe3, 0xd4, 0x32, 0x3e, 0xee, 0xec, + 0x96, 0x54, 0xe1, 0xb1, 0x8f, 0x64, 0x59, 0xc6, 0x49, 0x01, 0x3c, 0xc0, + 0x17, 0xa9, 0xf5, 0xf2, 0x6f, 0x8a, 0xec, 0x9b, 0x66, 0xa7, 0x1d, 0x98, + 0xff, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x64, 0x6b, 0x75, 0x84, 0x07, 0x06, + 0x16, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x34, 0x34, 0x34, 0x86, 0x46, 0x17, 0x13, 0x41, 0xb7, + 0x59, 0x5c, 0x54, 0xdd, 0xc7, 0x58, 0x41, 0xb7, 0x59, 0x5c, 0x54, 0xdd, + 0xc7, 0x58, 0x8e, 0xc3, 0x7e, 0x3a, 0x0f, 0x3a, 0x3a, 0x7e, 0x0e, 0x1e, + 0x69, 0x08, 0x28, 0x2f, 0x21, 0x1c, 0x2a, 0x13, 0xa3, 0x59, 0xe5, 0x0e, + 0x4d, 0x78, 0x41, 0x89, 0x33, 0xa3, 0x28, 0x6d, 0xb9, 0x0a, 0x0b, 0x36, + 0x7b, 0xf9, 0xc7, 0xb9, 0x71, 0xe5, 0x1c, 0x32, 0x04, 0xe7, 0x79, 0xe1, + 0xe0, 0x05, 0x0b, 0xa0, 0xe7, 0xb9, 0xe1, 0x92, 0xbb, 0xa8, 0xae, 0xca, + 0xff, 0x1c, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, + 0x00, 0x00, 0x99, 0x02, 0x2d, 0xc5, 0xee, 0x94, 0x76, 0x6c, 0x0a, 0xe2, + 0xa1, 0xb1, 0x7a, 0x6d, 0x0c, 0xbf, 0x9d, 0xa2, 0x60, 0xdc, 0xb9, 0xf4, + 0xf9, 0x4e, 0x6f, 0x61, 0x37, 0x18, 0x86, 0xbf, 0xef, 0xe9, 0x55, 0x9e, + 0x44, 0x75, 0x32, 0x4c, 0x20, 0x82, 0xb5, 0x3d, 0x42, 0x72, 0x35, 0x69, + 0xba, 0x22, 0x95, 0x0c, 0xec, 0x46, 0xe8, 0x5b, 0x62, 0xe2, 0x07, 0xd4, + 0x80, 0x99, 0xc1, 0x83, 0x12, 0x3f, 0xcc, 0xd4, 0xf6, 0xcd, 0xc2, 0xb2, + 0xcd, 0x4d, 0x94, 0x4c, 0xab, 0x05, 0x48, 0x0c, 0x09, 0xe1, 0x82, 0x1a, + 0x6c, 0x0a, 0xf5, 0x16, 0x06, 0x57, 0x23, 0x9e, 0x18, 0xe8, 0xd9, 0xbb, + 0x4a, 0x8a, 0xcd, 0x69, 0xed, 0xc3, 0xae, 0x71, 0xe8, 0x8f, 0xeb, 0xb5, + 0x76, 0x50, 0xca, 0xb5, 0x69, 0x05, 0xdc, 0x93, 0x5b, 0x49, 0xed, 0xa3, + 0xf8, 0x25, 0xfe, 0x6a, 0x83, 0x6f, 0x16, 0x1e, 0xef, 0x5b, 0xfd, 0x24, + 0x7f, 0x9f, 0x66, 0xf1, 0x65, 0x8c, 0x38, 0x43, 0xd1, 0xbc, 0x13, 0x14, + 0x45, 0x75, 0x66, 0x3b, 0xd7, 0xe1, 0x7a, 0xde, 0xb1, 0xf6, 0x27, 0xd6, + 0x3e, 0xf6, 0x44, 0x7d, 0xf3, 0x3e, 0xd2, 0x95, 0x49, 0xe5, 0x31, 0x6f, + 0x38, 0x95, 0xd0, 0x78, 0xc8, 0xca, 0x68, 0xaf, 0xec, 0xab, 0x1e, 0xcf, + 0x0c, 0xff, 0x3e, 0xc4, 0x12, 0x3e, 0x48, 0xb4, 0x7e, 0x70, 0xc6, 0xa0, + 0x9b, 0xf8, 0x80, 0x30, 0x75, 0x25, 0x1a, 0xf1, 0xdf, 0x3a, 0x37, 0xa1, + 0xac, 0x43, 0x5b, 0xa0, 0xae, 0x9b, 0x91, 0xb3, 0x4a, 0xfa, 0x5f, 0x4b, + 0xf1, 0xba, 0xcd, 0x41, 0x92, 0x38, 0x6a, 0x8d, 0x69, 0x9e, 0xd3, 0x09, + 0xaa, 0x4c, 0xb2, 0x60, 0xcf, 0xff, 0x37, 0xed, 0xa0, 0x39, 0x36, 0x03, + 0x1a, 0x6a, 0xb7, 0xed, 0xce, 0xc8, 0x4e, 0x46, 0xb1, 0x82, 0xfb, 0xe1, + 0x46, 0x2d, 0x12, 0xf4, 0x8a, 0x6c, 0x38, 0x5c, 0x6b, 0xaa, 0x05, 0xf1, + 0xc0, 0xf2, 0x14, 0x8d, 0x3e, 0xdc, 0xec, 0x04, 0x0c, 0x94, 0xe3, 0xbf, + 0x3b, 0x7b, 0x3f, 0xa2, 0x88, 0x98, 0xe6, 0x0c, 0x5f, 0x23, 0x6d, 0x0b, + 0x6f, 0x8e, 0xe9, 0xce, 0xc0, 0xe2, 0x3e, 0xc7, 0xcd, 0xa0, 0x7b, 0xda, + 0xf1, 0x26, 0xfd, 0x3d, 0xc6, 0xe7, 0xe8, 0xed, 0x9d, 0xeb, 0x74, 0xc5, + 0x14, 0x5c, 0xee, 0xcd, 0x4d, 0xc4, 0x4e, 0x1b, 0x2d, 0x09, 0xf4, 0x7b, + 0xdb, 0xf6, 0x96, 0x17, 0x17, 0xd1, 0x16, 0xd5, 0xea, 0xaf, 0x4f, 0x7b, + 0xc2, 0x1e, 0x0f, 0xe1, 0x2c, 0xd8, 0x26, 0xe1, 0xcc, 0x66, 0x64, 0xd1, + 0x3f, 0xd9, 0x16, 0x99, 0x0c, 0xb1, 0x11, 0xc2, 0x13, 0xe5, 0xab, 0x99, + 0x2a, 0x6f, 0x09, 0x37, 0xc5, 0x7c, 0x8e, 0xb8, 0x04, 0x73, 0x3b, 0x0b, + 0x58, 0x87, 0x10, 0x33, 0x1f, 0x5d, 0xea, 0xe9, 0xcd, 0x4e, 0x5b, 0x33, + 0x88, 0xc2, 0x9c, 0x01, 0x1a, 0xe6, 0x92, 0x57, 0xf9, 0xa8, 0x7d, 0x03, + 0x76, 0x79, 0x4e, 0x1e, 0x25, 0xe8, 0xae, 0x61, 0x70, 0x70, 0x6c, 0x65, + 0x64, 0x6b, 0x75, 0x83, 0x0b, 0x05, 0x16, 0x00, 0x07, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x34, 0x00, + 0x84, 0x3c, 0x29, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x53, 0x32, 0x4a, 0x6b, + 0x41, 0xb7, 0x59, 0x5c, 0x53, 0x32, 0x4a, 0x6b, 0x65, 0x6d, 0xb0, 0x14, + 0x83, 0xdf, 0x17, 0xb6, 0x73, 0x59, 0x09, 0xd6, 0x8a, 0xed, 0x02, 0x13, + 0x5a, 0x8b, 0xd4, 0x99, 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, + 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, + 0xaa, 0xa7, 0xbf, 0x94, 0x09, 0x4f, 0x35, 0x59, 0x31, 0xba, 0xaa, 0x89, + 0x4f, 0xfa, 0x26, 0x41, 0x66, 0x87, 0x1b, 0x60, 0x02, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xdc, 0x97, 0xef, 0xa5, + 0xc0, 0xbc, 0x15, 0x38, 0x95, 0x35, 0x74, 0x61, 0x34, 0x68, 0xb9, 0x5c, + 0xef, 0x21, 0xad, 0xeb, 0xc9, 0x50, 0x73, 0xed, 0x31, 0x38, 0x33, 0x44, + 0x03, 0x44, 0x16, 0xaf, 0xa2, 0xba, 0x34, 0x58, 0x3f, 0x49, 0xaf, 0x93, + 0xf8, 0xe4, 0x6e, 0x6f, 0x7f, 0x23, 0x05, 0x46, 0x75, 0x49, 0xdf, 0x84, + 0xad, 0x64, 0x83, 0x11, 0x43, 0xd9, 0x80, 0x11, 0x93, 0x6d, 0xcf, 0xb4, + 0x72, 0x42, 0xc2, 0x5a, 0x78, 0x57, 0x37, 0x2d, 0x9e, 0x9a, 0x3e, 0x30, + 0x9b, 0x72, 0x7b, 0xfa, 0x1d, 0x9e, 0x2d, 0x53, 0x16, 0x85, 0x91, 0x3c, + 0xe9, 0xf1, 0x39, 0x60, 0x1d, 0x9e, 0xc6, 0xee, 0xb1, 0xdc, 0xb1, 0x0d, + 0xb8, 0x23, 0x68, 0xbf, 0xe5, 0x08, 0xc4, 0xac, 0x31, 0x4e, 0x2d, 0x0f, + 0x1f, 0xe1, 0xb3, 0xfe, 0xd2, 0x31, 0x4a, 0x52, 0x3e, 0x03, 0xe1, 0x1a, + 0x66, 0x58, 0x8b, 0x56, 0x99, 0x55, 0x7f, 0x6f, 0x5a, 0xa9, 0x8f, 0xcf, + 0xb3, 0x03, 0x96, 0x79, 0xb0, 0x6c, 0x67, 0x60, 0x35, 0xce, 0x8d, 0xc6, + 0x1c, 0x70, 0x05, 0xa4, 0x5e, 0x4f, 0x83, 0x4f, 0x1a, 0x98, 0x88, 0xdd, + 0x5a, 0x5d, 0xb3, 0x9b, 0xf6, 0xb2, 0xa3, 0x2e, 0x1c, 0x41, 0x81, 0x97, + 0xef, 0x16, 0xb3, 0x8e, 0xbe, 0x09, 0x08, 0x3d, 0x47, 0xaa, 0x2b, 0x90, + 0x61, 0xc7, 0x67, 0xcb, 0x0d, 0xa5, 0x7a, 0x58, 0x4d, 0xa7, 0x9f, 0xd4, + 0x21, 0xf2, 0x47, 0x65, 0x3b, 0x9e, 0x3b, 0xa4, 0xb4, 0x15, 0x05, 0x10, + 0xee, 0x90, 0xe5, 0xd9, 0x2e, 0xa0, 0xfe, 0x85, 0x9c, 0xad, 0x37, 0x71, + 0x51, 0xba, 0x0e, 0x91, 0x48, 0x3e, 0x54, 0xa0, 0x10, 0x1b, 0xc7, 0xff, + 0x4b, 0xd2, 0x24, 0xf8, 0x37, 0xd9, 0xc3, 0x17, 0x12, 0x05, 0x28, 0xbe, + 0xeb, 0xf5, 0xa3, 0x5a, 0x93, 0x7b, 0x9e, 0x59, 0xb2, 0x63, 0xbc, 0x71, + 0x61, 0x6a, 0x5a, 0x6c, 0xbd, 0xae, 0xeb, 0xff, 0x2a, 0x53, 0xf3, 0x44, + 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x61, 0x70, + 0x73, 0x64, 0x64, 0x6b, 0x75, 0x00, 0x00, 0x01, 0x87, 0x00, 0x07, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, + 0x34, 0x34, 0x84, 0x40, 0x17, 0x13, 0x41, 0xb7, 0x59, 0x51, 0x13, 0x75, + 0xf7, 0x83, 0x41, 0xb7, 0x59, 0x51, 0x13, 0x75, 0xf7, 0x83, 0x8e, 0xc3, + 0x7e, 0x3a, 0x0f, 0x3a, 0x3a, 0x7e, 0x0e, 0x1e, 0x69, 0x08, 0x28, 0x2f, + 0x21, 0x1c, 0x2a, 0x13, 0xa3, 0x59, 0xe5, 0x0e, 0x4d, 0x78, 0x41, 0x89, + 0x33, 0xa3, 0x28, 0x6d, 0xb9, 0x0a, 0x0b, 0x36, 0x7b, 0xf9, 0xc7, 0xb9, + 0x71, 0xe5, 0xce, 0x65, 0x7a, 0x52, 0xa0, 0x52, 0xa3, 0xaa, 0xf5, 0x34, + 0xec, 0xfb, 0xf7, 0xcb, 0xdd, 0xe4, 0xee, 0x33, 0x4c, 0x10, 0x02, 0x00, + 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xc9, 0xa4, + 0xb0, 0xbb, 0x30, 0xa3, 0x3d, 0x27, 0x05, 0x4f, 0x4c, 0x5e, 0x1f, 0x82, + 0x66, 0x8e, 0x02, 0x48, 0x36, 0x3c, 0x6b, 0xa3, 0x16, 0x82, 0x0c, 0x12, + 0x58, 0xe2, 0xb6, 0x5f, 0xe3, 0x0a, 0x20, 0xfd, 0xad, 0xa0, 0xc7, 0x99, + 0x65, 0x78, 0xfe, 0x99, 0xa5, 0xac, 0x48, 0x47, 0x0e, 0x2d, 0xc3, 0x76, + 0x76, 0xcb, 0xca, 0x9b, 0xb7, 0xe5, 0x3b, 0x4a, 0xca, 0x8a, 0xb6, 0x6f, + 0x22, 0x08, 0xcb, 0xb4, 0xc6, 0xf6, 0xba, 0x30, 0x52, 0x57, 0x1b, 0x09, + 0xc8, 0x9a, 0x3e, 0xde, 0x73, 0x81, 0xde, 0xb7, 0xc2, 0x2d, 0x46, 0xc9, + 0x52, 0x9f, 0x4b, 0xef, 0x2c, 0x2f, 0x5c, 0xa3, 0x10, 0x98, 0x0d, 0x57, + 0x0b, 0x4c, 0xc5, 0xeb, 0x49, 0x49, 0x7f, 0xae, 0xc3, 0x45, 0xbe, 0x0a, + 0x7d, 0x37, 0x94, 0xc4, 0xfe, 0x53, 0xdf, 0x10, 0x55, 0x98, 0xf9, 0x68, + 0x2a, 0xf7, 0x42, 0x48, 0x6b, 0xa7, 0x5b, 0x3d, 0xa3, 0x9f, 0xed, 0xf2, + 0x70, 0xcb, 0x64, 0x74, 0xa8, 0xfa, 0xdc, 0xe4, 0x5e, 0x90, 0x6f, 0x79, + 0x18, 0x19, 0xc8, 0xbf, 0xf3, 0x78, 0xd9, 0x35, 0x07, 0x42, 0x5f, 0xc6, + 0x04, 0x09, 0x62, 0x1f, 0xa4, 0xe2, 0x67, 0x06, 0x46, 0x47, 0xac, 0x53, + 0x7d, 0x0e, 0xbb, 0xd7, 0xbd, 0x51, 0x00, 0x60, 0x44, 0xa9, 0x47, 0x60, + 0xd5, 0x7f, 0xc4, 0x45, 0xdb, 0xd5, 0x42, 0xbe, 0x8e, 0x5d, 0x89, 0xbd, + 0xb4, 0xe7, 0x6e, 0xdf, 0xcc, 0x21, 0x10, 0x2c, 0x8d, 0xe8, 0x6e, 0x2c, + 0xb8, 0x72, 0x0e, 0x86, 0xe9, 0xd4, 0x08, 0x93, 0xf3, 0xb3, 0x2a, 0x00, + 0xa0, 0xe2, 0x1f, 0xc4, 0x09, 0x3b, 0x75, 0x81, 0x99, 0x17, 0x5b, 0x78, + 0x27, 0x32, 0x6d, 0x0b, 0x29, 0x31, 0x51, 0x70, 0x50, 0x95, 0x0c, 0x94, + 0x90, 0xba, 0x18, 0x17, 0x44, 0x6b, 0xd8, 0x50, 0x58, 0xe8, 0xe2, 0xff, + 0x80, 0xb9, 0x44, 0xfe, 0x1b, 0x8f, 0xdf, 0xa1, 0x91, 0xeb, 0x57, 0x86, + 0xd0, 0x61, 0x1a, 0x09, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x64, 0x6b, 0x75, + 0x84, 0x43, 0x02, 0x16, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x34, 0x00, 0x87, 0x66, 0x17, + 0x13, 0x41, 0xb7, 0x59, 0x50, 0xd8, 0x37, 0x6c, 0x27, 0x41, 0xb7, 0x59, + 0x50, 0xd8, 0x37, 0x6c, 0x27, 0x77, 0xac, 0x86, 0x8b, 0xf9, 0xb8, 0xa0, + 0x50, 0x0b, 0x1f, 0xb3, 0x50, 0x55, 0xe2, 0x63, 0x81, 0xf6, 0x85, 0xbc, + 0xeb, 0x06, 0x98, 0x7e, 0x8b, 0x09, 0xd8, 0x2e, 0xbe, 0x8c, 0x6b, 0x51, + 0x5c, 0x08, 0x13, 0x58, 0xb4, 0x2e, 0x41, 0xcb, 0x34, 0x02, 0x00, 0x00, + 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xf6, 0xbc, 0x81, + 0x5b, 0x23, 0x66, 0x44, 0x13, 0x27, 0xcf, 0x98, 0xc2, 0xc0, 0x31, 0x38, + 0x98, 0xec, 0x01, 0x84, 0xbb, 0x38, 0xb1, 0x79, 0xd7, 0x91, 0x66, 0x5a, + 0x56, 0x22, 0x62, 0x6f, 0xb8, 0xf0, 0x68, 0x00, 0xe7, 0x1a, 0x7a, 0x93, + 0xfc, 0xa8, 0xd4, 0xd9, 0xaf, 0x21, 0x17, 0x71, 0xf3, 0x0c, 0xd6, 0x22, + 0x2f, 0xb0, 0xb7, 0xc3, 0x1e, 0x07, 0xe7, 0x53, 0x34, 0xc9, 0x17, 0x9d, + 0xe8, 0xd3, 0x07, 0x78, 0xe7, 0x74, 0xcd, 0xf0, 0xdd, 0x88, 0x0d, 0x30, + 0x9b, 0x3c, 0x78, 0xfb, 0x43, 0xb7, 0x4f, 0x79, 0xd1, 0x83, 0xcd, 0x56, + 0x60, 0xe7, 0x7e, 0x8d, 0xba, 0x61, 0x9d, 0x4f, 0xf2, 0x71, 0x9b, 0xbd, + 0x11, 0xfc, 0x82, 0x8f, 0xc2, 0x9b, 0x32, 0xb7, 0x4d, 0x5d, 0x93, 0x87, + 0x11, 0x7d, 0xbf, 0x3a, 0x06, 0x11, 0x15, 0xf5, 0x97, 0xf4, 0x03, 0x24, + 0x6a, 0xfb, 0x5e, 0x27, 0x2b, 0xb5, 0xac, 0x20, 0x84, 0xe8, 0x8d, 0x67, + 0xa9, 0xf5, 0x41, 0x8a, 0xbd, 0xea, 0x51, 0x91, 0x30, 0xd7, 0xf2, 0x81, + 0x12, 0xbc, 0x24, 0x61, 0x25, 0x58, 0x9e, 0x4a, 0x4c, 0x89, 0xa4, 0x19, + 0xf1, 0x12, 0xe2, 0x33, 0xf1, 0x37, 0x1f, 0x0f, 0xa0, 0x42, 0xa1, 0x0e, + 0xa2, 0xc4, 0x06, 0xb0, 0xba, 0x61, 0xef, 0xc5, 0x6b, 0x46, 0x33, 0x62, + 0x50, 0xe0, 0xe4, 0x2e, 0x74, 0x20, 0xf4, 0x54, 0xbb, 0xed, 0xa0, 0x73, + 0x51, 0xa5, 0xc6, 0x55, 0x90, 0x61, 0xe9, 0x9c, 0x76, 0x72, 0x21, 0xa9, + 0x19, 0x1a, 0xbd, 0xcf, 0x61, 0x29, 0x8a, 0xef, 0xdd, 0xe0, 0xc6, 0x0a, + 0xf0, 0xd8, 0x50, 0xb9, 0xe9, 0x92, 0x7d, 0xf3, 0xce, 0x7e, 0x9e, 0xcf, + 0x32, 0x92, 0xc7, 0x49, 0x59, 0x23, 0xb5, 0x4e, 0xf2, 0x71, 0xf0, 0xda, + 0xb3, 0x80, 0xe3, 0xb6, 0x7a, 0xe4, 0x14, 0x80, 0x25, 0x3e, 0xd0, 0x89, + 0x13, 0xf4, 0x70, 0x96, 0xee, 0xbe, 0xef, 0x31, 0x61, 0xa1, 0x8d, 0xf7, + 0x9a, 0x5c, 0x92, 0x0a, 0x9b, 0x1f, 0x8c, 0x5e, 0x3d, 0x37, 0x24, 0xc2, + 0x8d, 0x21, 0xe9, 0x47, 0x2e, 0x03, 0xee, 0x32, 0xbf, 0x46, 0xc7, 0x2c, + 0x6e, 0x7a, 0x81, 0x9e, 0x14, 0xb8, 0xbe, 0xdb, 0x22, 0x4f, 0xf1, 0x8d, + 0x47, 0x41, 0x84, 0xc9, 0xeb, 0x4f, 0xe9, 0xf4, 0xad, 0xc4, 0xbe, 0xf8, + 0x28, 0xcb, 0xe6, 0x16, 0xa8, 0x6b, 0xaf, 0xd5, 0x0a, 0x6d, 0x06, 0x59, + 0x4f, 0x7d, 0x53, 0xa6, 0x4e, 0x90, 0xa0, 0x23, 0x1b, 0x92, 0xf0, 0xe8, + 0xef, 0xed, 0x0d, 0xa7, 0x64, 0x01, 0x83, 0x4a, 0x3b, 0x2d, 0x18, 0x90, + 0x1d, 0x19, 0x1d, 0xa2, 0x98, 0xe9, 0xb5, 0xe4, 0x4a, 0x73, 0xcf, 0xdf, + 0x0c, 0x09, 0xd5, 0xf4, 0xd3, 0xd9, 0x12, 0x7c, 0xbb, 0x81, 0x51, 0x26, + 0x2a, 0xcb, 0xa7, 0xc9, 0x6a, 0xe9, 0xfb, 0x1d, 0xca, 0x43, 0xf1, 0xbe, + 0xfb, 0xc3, 0x6f, 0xb6, 0xa1, 0x0c, 0x42, 0x32, 0x18, 0x24, 0x63, 0xf9, + 0xa0, 0x7e, 0x71, 0x8c, 0xa5, 0x16, 0x16, 0x5a, 0x5e, 0x15, 0x5d, 0x6d, + 0x4b, 0x74, 0x5b, 0xde, 0x21, 0xd5, 0xe0, 0x11, 0xa6, 0x91, 0xc3, 0xb2, + 0xd7, 0x38, 0x70, 0xa2, 0x18, 0x29, 0x1b, 0xdc, 0x83, 0x3e, 0x37, 0x45, + 0xc4, 0x1b, 0x61, 0x98, 0x06, 0x12, 0x3e, 0xc0, 0xda, 0x1a, 0xc9, 0x18, + 0x9c, 0x50, 0x0e, 0xc5, 0xe1, 0xa7, 0x4d, 0x05, 0xc6, 0x99, 0x31, 0xab, + 0x17, 0x30, 0xb9, 0xb0, 0x01, 0x1f, 0x93, 0xd9, 0x76, 0xd4, 0x67, 0x0b, + 0xea, 0x7b, 0x2b, 0x0b, 0x42, 0x97, 0x40, 0x07, 0x94, 0x08, 0x61, 0x70, + 0x70, 0x6c, 0x65, 0x64, 0x6b, 0x75, 0x84, 0x3f, 0x01, 0x16, 0x00, 0x07, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x34, 0x00, 0x87, 0x5e, 0x17, 0x13, 0x41, 0xb7, 0x59, 0x50, 0xd8, + 0x33, 0x2b, 0x24, 0x41, 0xb7, 0x59, 0x50, 0xd8, 0x33, 0x2b, 0x24, 0x83, + 0xad, 0xb6, 0xae, 0x9f, 0x27, 0xa5, 0x45, 0x30, 0xb3, 0x67, 0xc8, 0x32, + 0x58, 0x95, 0x85, 0x06, 0xeb, 0xc1, 0xf4, 0x06, 0x98, 0x7e, 0x8b, 0x09, + 0xd8, 0x2e, 0xbe, 0x8c, 0x6b, 0x51, 0x5c, 0x08, 0x13, 0x58, 0xb4, 0x2e, + 0x41, 0xcb, 0x34, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x99, 0xb4, 0x79, 0xc1, 0x37, 0xc1, 0xe1, 0x5c, 0x49, + 0xa0, 0xe1, 0xf3, 0x17, 0xb8, 0x9c, 0x69, 0xe6, 0xba, 0xdc, 0xe7, 0x78, + 0xb2, 0x5d, 0xd6, 0x95, 0xbe, 0xb2, 0xda, 0x91, 0xd3, 0x9b, 0xf2, 0xd4, + 0xe3, 0x95, 0x3c, 0x53, 0x8d, 0x0e, 0x68, 0xe9, 0x02, 0xb3, 0xed, 0xeb, + 0x95, 0xdd, 0x11, 0xb2, 0x64, 0x69, 0x8a, 0xfe, 0x03, 0x05, 0xd5, 0x04, + 0x9b, 0xac, 0x8a, 0xb6, 0x98, 0x29, 0x56, 0x2e, 0xd3, 0xea, 0x4e, 0x84, + 0xee, 0x23, 0x44, 0x03, 0x12, 0x9d, 0x9c, 0x9c, 0x9f, 0x11, 0x62, 0xf0, + 0x86, 0x36, 0x52, 0x15, 0x0f, 0x27, 0x93, 0xdb, 0xde, 0x13, 0xc9, 0x94, + 0x93, 0xe4, 0xa4, 0x6f, 0x58, 0x9d, 0x58, 0x9f, 0x15, 0xba, 0x5f, 0x4c, + 0xf3, 0x9a, 0x90, 0xc0, 0xcb, 0x60, 0xce, 0x9b, 0x56, 0x0c, 0xfe, 0x5b, + 0xd2, 0x4e, 0x0e, 0x82, 0xe6, 0x4c, 0x62, 0x57, 0x08, 0x6e, 0x5d, 0x54, + 0x7b, 0x28, 0xbb, 0x88, 0xdc, 0xec, 0xaa, 0xd1, 0x6e, 0xd3, 0x94, 0x20, + 0x3e, 0x35, 0x81, 0x52, 0xf6, 0xe9, 0xee, 0x42, 0x89, 0xe9, 0xea, 0x61, + 0x2c, 0xd8, 0xdc, 0xe3, 0x82, 0xf7, 0xf0, 0xc0, 0xf6, 0xf9, 0xb7, 0xef, + 0x49, 0xc7, 0x8d, 0x6c, 0x8a, 0x6d, 0x6e, 0xbc, 0x2d, 0xc0, 0xb1, 0xec, + 0x0c, 0xdd, 0xe5, 0xbe, 0x65, 0x3f, 0x69, 0x81, 0xcf, 0xe8, 0xd8, 0xf3, + 0x57, 0x8e, 0xba, 0x73, 0x7f, 0xb0, 0x4e, 0x65, 0xa2, 0xa5, 0xa5, 0xbb, + 0x7b, 0xae, 0xaa, 0x88, 0x06, 0x4f, 0x2c, 0x43, 0xb9, 0x4c, 0x17, 0xa1, + 0x24, 0xfb, 0xe1, 0x90, 0x50, 0xdb, 0xcc, 0xd9, 0xe5, 0x7b, 0x09, 0xaf, + 0x5c, 0x5a, 0x4f, 0xb2, 0x2b, 0x30, 0x53, 0x0f, 0xd3, 0xe2, 0xbd, 0xcd, + 0xf7, 0xa3, 0x19, 0xdc, 0xba, 0xee, 0xd1, 0x49, 0xbc, 0xa6, 0xde, 0x1b, + 0xe6, 0xd3, 0xaf, 0xdd, 0x61, 0xf6, 0xfd, 0xef, 0xb7, 0xda, 0x9d, 0x93, + 0x45, 0x0a, 0xa2, 0xa8, 0x1a, 0xe5, 0x16, 0xb1, 0xaf, 0x20, 0x00, 0x86, + 0x6b, 0x66, 0x42, 0x97, 0x4e, 0x3a, 0xea, 0x0d, 0x33, 0xb2, 0x93, 0x87, + 0x9c, 0xd1, 0x6a, 0x20, 0xbc, 0xc9, 0x7d, 0x46, 0xb9, 0x0a, 0x26, 0x9a, + 0x09, 0x81, 0xc8, 0x6d, 0x9b, 0x63, 0xa5, 0x1f, 0x63, 0x72, 0x6c, 0xa8, + 0x65, 0x65, 0xa2, 0x8a, 0x81, 0x4d, 0x54, 0xd4, 0xa3, 0xc4, 0x86, 0x48, + 0x31, 0x5c, 0x4e, 0x15, 0xf3, 0x48, 0x30, 0xbc, 0x17, 0xac, 0x0b, 0x85, + 0x8f, 0x44, 0x62, 0xf4, 0x57, 0xc7, 0xbd, 0x18, 0xcf, 0xf5, 0xd8, 0xa9, + 0x2d, 0xf5, 0x57, 0xaf, 0x42, 0x09, 0xf7, 0x5b, 0x25, 0x56, 0xa1, 0x04, + 0x0c, 0xf7, 0xa7, 0xc9, 0x2d, 0xd7, 0x84, 0x78, 0x86, 0x82, 0x2d, 0xd3, + 0xaa, 0xd2, 0xbf, 0x77, 0xc0, 0x34, 0x7b, 0xdb, 0x7e, 0x4d, 0xde, 0x63, + 0x8f, 0xcc, 0xb6, 0x6d, 0x01, 0x80, 0x68, 0x51, 0x3e, 0x8f, 0x2a, 0x7c, + 0x0e, 0xaa, 0xc2, 0xbf, 0x77, 0x12, 0x06, 0x88, 0xdf, 0x3f, 0x6c, 0x7d, + 0x69, 0x05, 0x57, 0x71, 0xeb, 0xe7, 0xf3, 0xcb, 0x32, 0x4d, 0x33, 0x54, + 0x8a, 0x2a, 0x1b, 0xb5, 0x6e, 0xb6, 0xa4, 0x64, 0xcd, 0x34, 0x5c, 0xa9, + 0x3d, 0x92, 0xc8, 0x38, 0xbb, 0x84, 0xed, 0xde, 0xe4, 0xa2, 0xe1, 0x68, + 0x2f, 0xcb, 0x4b, 0x3c, 0x76, 0xb2, 0x3b, 0x84, 0x5f, 0x6b, 0x46, 0x72, + 0x2f, 0x7f, 0xf0, 0x6f, 0x6b, 0x7b, 0xd3, 0xc5, 0x4b, 0x20, 0x2b, 0xae, + 0x48, 0x7e, 0xcb, 0x22, 0x38, 0x44, 0x1f, 0x43, 0x1c, 0x55, 0x00, 0x00, + 0x00, 0x05, 0x0d, 0x00, 0x00, 0x00, 0x19, 0x07, 0x0a, 0x00, 0x00, 0x00, + 0x0a, 0x0d, 0xf1, 0x00, 0x0e, 0x8c, 0x0e, 0xf4, 0x0e, 0xc0, 0x0e, 0x24, + 0x0f, 0x99, 0x0e, 0x58, 0x0f, 0xcd, 0x0f, 0x65, 0x0d, 0xf1, 0x0f, 0x28, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x32, 0x05, 0x34, 0x34, 0x15, 0x01, 0xda, 0x39, 0xa3, 0xee, 0x5e, + 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, + 0xd8, 0x07, 0x09, 0xa9, 0x4a, 0x8f, 0xe5, 0xcc, 0xb1, 0x9b, 0xa6, 0x1c, + 0x4c, 0x08, 0x73, 0xd3, 0x91, 0xe9, 0x87, 0x98, 0x2f, 0xbb, 0xd3, 0x74, + 0x65, 0x73, 0x74, 0x11, 0x33, 0x05, 0x34, 0x34, 0x17, 0x01, 0x59, 0x27, + 0x33, 0x2f, 0x22, 0x90, 0x8f, 0xdf, 0x8f, 0x07, 0xfa, 0xa9, 0xeb, 0x8d, + 0x26, 0x20, 0xc7, 0xc6, 0x2a, 0x20, 0x3a, 0xdc, 0x09, 0xb3, 0xcd, 0x3d, + 0x7c, 0x47, 0x10, 0xf5, 0x62, 0xa0, 0x5b, 0xd8, 0x50, 0xe7, 0x56, 0xcb, + 0xa1, 0xb8, 0x69, 0x63, 0x68, 0x61, 0x74, 0x0d, 0x33, 0x05, 0x34, 0x34, + 0x17, 0x01, 0x7f, 0xda, 0x6a, 0xa0, 0x63, 0xf3, 0xfc, 0x5a, 0x86, 0x5c, + 0xa8, 0xf7, 0xa6, 0x9b, 0x5d, 0x69, 0x07, 0x3b, 0x91, 0x55, 0x72, 0x29, + 0x9c, 0x30, 0x4b, 0x50, 0xee, 0xe7, 0xb0, 0xc7, 0x1b, 0x05, 0x97, 0x70, + 0xac, 0x8e, 0x43, 0x5d, 0x69, 0x39, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x12, + 0x33, 0x05, 0x34, 0x34, 0x17, 0x01, 0x05, 0xc5, 0x64, 0xf0, 0xff, 0xc1, + 0x0a, 0xf4, 0x42, 0x83, 0x33, 0x33, 0x5d, 0x04, 0x75, 0x9c, 0x85, 0x9a, + 0x74, 0x0a, 0x3a, 0xdc, 0x09, 0xb3, 0xcd, 0x3d, 0x7c, 0x47, 0x10, 0xf5, + 0x62, 0xa0, 0x5b, 0xd8, 0x50, 0xe7, 0x56, 0xcb, 0xa1, 0xb8, 0x61, 0x70, + 0x70, 0x6c, 0x65, 0x09, 0x33, 0x05, 0x34, 0x34, 0x17, 0x01, 0x51, 0x96, + 0x74, 0xbb, 0x0c, 0xef, 0x0c, 0xf3, 0x24, 0x61, 0xd2, 0x2c, 0xba, 0x9a, + 0xa9, 0xc8, 0x0e, 0x22, 0xff, 0x0b, 0x3a, 0xdc, 0x09, 0xb3, 0xcd, 0x3d, + 0x7c, 0x47, 0x10, 0xf5, 0x62, 0xa0, 0x5b, 0xd8, 0x50, 0xe7, 0x56, 0xcb, + 0xa1, 0xb8, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x08, 0x33, 0x05, 0x34, 0x34, + 0x17, 0x01, 0x0b, 0x66, 0x7c, 0x18, 0x9e, 0x44, 0x49, 0x2d, 0x40, 0x62, + 0x95, 0x22, 0xa7, 0xe3, 0x08, 0x19, 0x26, 0x0f, 0xd6, 0x6d, 0x3a, 0xdc, + 0x09, 0xb3, 0xcd, 0x3d, 0x7c, 0x47, 0x10, 0xf5, 0x62, 0xa0, 0x5b, 0xd8, + 0x50, 0xe7, 0x56, 0xcb, 0xa1, 0xb8, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x07, + 0x3c, 0x05, 0x34, 0x34, 0x29, 0x01, 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, + 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, + 0x07, 0x09, 0xaa, 0xa7, 0xbf, 0x94, 0x09, 0x4f, 0x35, 0x59, 0x31, 0xba, + 0xaa, 0x89, 0x4f, 0xfa, 0x26, 0x41, 0x66, 0x87, 0x1b, 0x60, 0x63, 0x6f, + 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x73, 0x64, + 0x05, 0x33, 0x05, 0x34, 0x34, 0x17, 0x01, 0x8e, 0xc3, 0x7e, 0x3a, 0x0f, + 0x3a, 0x3a, 0x7e, 0x0e, 0x1e, 0x69, 0x08, 0x28, 0x2f, 0x21, 0x1c, 0x2a, + 0x13, 0xa3, 0x59, 0xe5, 0x0e, 0x4d, 0x78, 0x41, 0x89, 0x33, 0xa3, 0x28, + 0x6d, 0xb9, 0x0a, 0x0b, 0x36, 0x7b, 0xf9, 0xc7, 0xb9, 0x71, 0xe5, 0x61, + 0x70, 0x70, 0x6c, 0x65, 0x06, 0x33, 0x05, 0x34, 0x34, 0x17, 0x01, 0x77, + 0xac, 0x86, 0x8b, 0xf9, 0xb8, 0xa0, 0x50, 0x0b, 0x1f, 0xb3, 0x50, 0x55, + 0xe2, 0x63, 0x81, 0xf6, 0x85, 0xbc, 0xeb, 0x06, 0x98, 0x7e, 0x8b, 0x09, + 0xd8, 0x2e, 0xbe, 0x8c, 0x6b, 0x51, 0x5c, 0x08, 0x13, 0x58, 0xb4, 0x2e, + 0x41, 0xcb, 0x34, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x02, 0x32, 0x05, 0x34, + 0x34, 0x17, 0x09, 0x83, 0xad, 0xb6, 0xae, 0x9f, 0x27, 0xa5, 0x45, 0x30, + 0xb3, 0x67, 0xc8, 0x32, 0x58, 0x95, 0x85, 0x06, 0xeb, 0xc1, 0xf4, 0x06, + 0x98, 0x7e, 0x8b, 0x09, 0xd8, 0x2e, 0xbe, 0x8c, 0x6b, 0x51, 0x5c, 0x08, + 0x13, 0x58, 0xb4, 0x2e, 0x41, 0xcb, 0x34, 0x61, 0x70, 0x70, 0x6c, 0x65, + 0x0d, 0x0f, 0xe4, 0x00, 0x03, 0x0f, 0xda, 0x00, 0x0f, 0xf6, 0x0f, 0xda, + 0x0f, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x02, 0x03, 0x15, 0x01, 0x63, 0x65, 0x72, 0x74, 0x02, + 0x00, 0x00, 0x00, 0x08, 0x09, 0x6b, 0x65, 0x79, 0x08, 0x03, 0x03, 0x15, + 0x01, 0x6b, 0x65, 0x79, 0x73, 0x06, 0x08, 0x01, 0x03, 0x15, 0x01, 0x67, + 0x65, 0x6e, 0x70, 0x12, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x02, 0x03, 0xfb, 0x00, 0x09, 0xed, 0x03, 0xfb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, + 0x6f, 0x02, 0x11, 0x00, 0x07, 0x07, 0x01, 0x01, 0x34, 0x00, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x95, 0x12, 0x29, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x4b, + 0x9d, 0x7a, 0x35, 0x41, 0xb7, 0x59, 0x5c, 0x4b, 0x9d, 0x7a, 0x35, 0x03, + 0x03, 0x37, 0xee, 0x5a, 0x85, 0xe1, 0xcb, 0xdd, 0xc8, 0xce, 0x07, 0x77, + 0xee, 0x01, 0x3f, 0x96, 0x7b, 0x33, 0x30, 0x3a, 0xcd, 0x7e, 0x0b, 0xaa, + 0xec, 0xd2, 0x3c, 0x92, 0x58, 0xd7, 0xfd, 0x92, 0x3c, 0xf8, 0x03, 0x3e, + 0x70, 0x20, 0x84, 0xa7, 0x17, 0x2c, 0xf0, 0xfa, 0xf2, 0x6b, 0xa9, 0x12, + 0x4e, 0x73, 0x93, 0x45, 0x6c, 0x2f, 0x97, 0x33, 0x72, 0xa1, 0x3b, 0x0d, + 0x66, 0x6e, 0x37, 0x4b, 0xba, 0xaa, 0x65, 0x68, 0x18, 0x44, 0x35, 0x5b, + 0x9a, 0x6f, 0xf1, 0x3c, 0x2b, 0x18, 0x1f, 0xda, 0x4c, 0xda, 0xde, 0x08, + 0x82, 0x7d, 0xfa, 0x5c, 0xf3, 0x42, 0xb1, 0x04, 0x84, 0xf4, 0xba, 0xe3, + 0x73, 0xe9, 0x35, 0x6f, 0xbb, 0x64, 0x14, 0x5e, 0x86, 0xb3, 0x7b, 0x2d, + 0x6c, 0xa9, 0xc0, 0xcf, 0xd8, 0x43, 0x7e, 0x59, 0x45, 0xac, 0xff, 0x92, + 0x4b, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, + 0x00, 0xc4, 0xe8, 0xe5, 0xde, 0xeb, 0xd1, 0xbc, 0xae, 0x0f, 0x47, 0x6a, + 0xc0, 0xb4, 0xf8, 0x7a, 0xdc, 0xc1, 0x10, 0xb0, 0x90, 0xf2, 0x29, 0x16, + 0x8f, 0x90, 0xeb, 0x31, 0x83, 0x9b, 0x33, 0x91, 0x26, 0x16, 0x4c, 0xce, + 0xfe, 0x98, 0x25, 0x0d, 0xed, 0xe6, 0x9f, 0xc3, 0x91, 0xac, 0xbb, 0xf8, + 0xc0, 0xca, 0x25, 0x42, 0xd4, 0x5d, 0xfe, 0x1b, 0x4d, 0x60, 0x7f, 0x01, + 0xee, 0x5f, 0x16, 0xbd, 0xb8, 0xe7, 0xdc, 0xe1, 0x75, 0xf9, 0x1a, 0xc7, + 0x4f, 0xc5, 0xf1, 0x44, 0x46, 0xfe, 0xdd, 0x91, 0xf8, 0x25, 0xed, 0xbc, + 0x1a, 0xf1, 0x34, 0x71, 0x05, 0x4e, 0x13, 0xb9, 0x21, 0xbf, 0x04, 0x6d, + 0x1e, 0x0f, 0xe6, 0x63, 0x19, 0x0b, 0x77, 0xef, 0xf1, 0x24, 0xf4, 0x55, + 0xf3, 0x71, 0x53, 0x13, 0x8b, 0xbb, 0xd5, 0xdb, 0x3e, 0xcb, 0xc5, 0x3a, + 0x9a, 0xe9, 0x55, 0xa1, 0x75, 0xa1, 0x98, 0x40, 0x80, 0x3b, 0x1e, 0xe1, + 0xbc, 0x44, 0x59, 0xb9, 0xf2, 0x6b, 0xa9, 0x0d, 0x13, 0x0c, 0xd2, 0xb2, + 0x99, 0xbf, 0x1f, 0xa9, 0x86, 0x5b, 0x2b, 0x63, 0x65, 0x28, 0x2f, 0x11, + 0x96, 0x2b, 0xa1, 0x9d, 0x32, 0x5e, 0x55, 0xa1, 0xdf, 0x90, 0x3b, 0x5e, + 0x4e, 0xdd, 0x3f, 0x6f, 0x10, 0xb6, 0x7c, 0xad, 0x92, 0xeb, 0x9f, 0x72, + 0xe4, 0x37, 0x83, 0x59, 0x4b, 0x6c, 0x62, 0x2e, 0xf1, 0x11, 0x5a, 0x75, + 0x86, 0x5b, 0xe4, 0x79, 0x86, 0xca, 0xdb, 0xd8, 0x11, 0xf4, 0x5f, 0x65, + 0x8f, 0x7f, 0x66, 0xc4, 0xe0, 0x35, 0x97, 0x15, 0xe3, 0x13, 0x97, 0xa9, + 0x23, 0x20, 0xce, 0xfe, 0x1a, 0x3a, 0x3f, 0xce, 0xa3, 0x88, 0x36, 0xfa, + 0x58, 0xb2, 0x35, 0x9a, 0x07, 0x69, 0xcd, 0xc7, 0xc7, 0xf4, 0x93, 0x0d, + 0x11, 0x3f, 0xec, 0x74, 0x88, 0x55, 0xfc, 0x12, 0x08, 0x0d, 0xc1, 0xd1, + 0x1f, 0xf6, 0xdd, 0xff, 0xea, 0x75, 0x40, 0x21, 0x06, 0xf2, 0x8a, 0x6c, + 0x2e, 0xc4, 0x84, 0x5d, 0x67, 0x90, 0x29, 0x95, 0xed, 0x6e, 0x55, 0x19, + 0x12, 0xb0, 0x11, 0x41, 0x2e, 0x2b, 0xe0, 0xbb, 0xe4, 0x90, 0x8e, 0xa3, + 0x9f, 0x1c, 0x3d, 0xa0, 0xd1, 0x5c, 0xa3, 0x01, 0xf3, 0x0f, 0x09, 0x64, + 0x7c, 0x12, 0xbc, 0x43, 0x2a, 0x24, 0x32, 0x8c, 0x63, 0x6c, 0x4d, 0x91, + 0xff, 0xe8, 0x0c, 0xc3, 0x54, 0xa8, 0x9b, 0x01, 0x99, 0x56, 0xc3, 0x1c, + 0xe1, 0x8e, 0x18, 0xfb, 0xb7, 0xfe, 0x27, 0x8c, 0x83, 0x3b, 0x07, 0x5b, + 0x93, 0x35, 0xaa, 0xef, 0xda, 0xb5, 0x50, 0x29, 0x92, 0x64, 0x18, 0x5d, + 0x2d, 0x25, 0x13, 0x68, 0x11, 0x37, 0xa7, 0x9e, 0xb1, 0x82, 0xe5, 0x10, + 0x6c, 0x2e, 0x44, 0x23, 0x04, 0x88, 0x47, 0xf0, 0x8e, 0xbc, 0xb2, 0xda, + 0xe2, 0x58, 0x8e, 0x4a, 0xc9, 0x93, 0x28, 0x7a, 0x32, 0x8c, 0x3d, 0x9b, + 0x49, 0x45, 0xcd, 0x13, 0x15, 0x13, 0xef, 0xaa, 0x71, 0x76, 0x08, 0x31, + 0xdf, 0xf2, 0xce, 0xae, 0xc5, 0xf7, 0x01, 0xd4, 0x59, 0x76, 0x88, 0xa3, + 0x8b, 0xfc, 0x3a, 0x24, 0xb6, 0x98, 0x44, 0x51, 0x87, 0xff, 0x14, 0xa7, + 0xb0, 0x47, 0x15, 0xc0, 0x35, 0x9a, 0xb8, 0xf1, 0xff, 0xa8, 0x84, 0x5b, + 0x4e, 0x59, 0x02, 0x65, 0xbf, 0x6f, 0xd5, 0x4d, 0xa0, 0xdb, 0x50, 0x13, + 0x7f, 0x1f, 0x86, 0x3a, 0x7a, 0x6b, 0xfb, 0xf2, 0xb6, 0xa6, 0x3d, 0xac, + 0x97, 0x86, 0xbf, 0x29, 0xdb, 0xb6, 0x99, 0xe8, 0x22, 0xce, 0xea, 0x43, + 0x38, 0xab, 0xfa, 0x64, 0x6c, 0xcc, 0x45, 0x7a, 0xc0, 0x9f, 0x50, 0x7b, + 0x1f, 0x25, 0x33, 0xe6, 0xfc, 0x9f, 0xcc, 0xfb, 0xbb, 0x50, 0x33, 0x31, + 0xe8, 0x62, 0x33, 0x43, 0x7e, 0x8d, 0x82, 0x38, 0x0c, 0x2c, 0x6e, 0x57, + 0x5f, 0x08, 0x31, 0x96, 0x48, 0x02, 0xbb, 0x95, 0x9a, 0xea, 0xd4, 0xcd, + 0x54, 0x49, 0x65, 0x51, 0xf6, 0xc9, 0x39, 0x39, 0xab, 0xe3, 0x92, 0xc2, + 0x71, 0xbb, 0xb1, 0x25, 0x12, 0x96, 0x45, 0xb8, 0x14, 0x34, 0x82, 0x94, + 0x9f, 0xbd, 0xc7, 0xf7, 0x07, 0x4f, 0x7d, 0xb5, 0xa2, 0xe2, 0xd5, 0x91, + 0xbf, 0x9b, 0xde, 0x3d, 0xa2, 0xfe, 0x25, 0x76, 0x5e, 0xac, 0xde, 0xf1, + 0x5f, 0x00, 0xe5, 0x9f, 0x6f, 0x3d, 0xdd, 0xbc, 0x7f, 0xfd, 0x92, 0x52, + 0x56, 0x53, 0x5a, 0x04, 0xca, 0xdc, 0x23, 0x76, 0xe4, 0xc4, 0xeb, 0x00, + 0x5e, 0x3e, 0x71, 0xb9, 0x7c, 0x54, 0x81, 0x4d, 0x6e, 0xb3, 0x09, 0x39, + 0x6f, 0x67, 0x0e, 0xc6, 0x95, 0xdf, 0x03, 0xcc, 0x7e, 0x0b, 0x7c, 0x31, + 0x16, 0xbe, 0x4b, 0xfc, 0x0f, 0x17, 0xb4, 0x7a, 0x9c, 0x44, 0x36, 0x5a, + 0xaf, 0x42, 0x69, 0x40, 0x58, 0xe7, 0xa4, 0x07, 0x5b, 0xe5, 0xd6, 0x35, + 0xe5, 0x4a, 0xde, 0x35, 0x29, 0xc5, 0x69, 0x00, 0x47, 0xfa, 0x3d, 0x54, + 0xbc, 0x1f, 0xa5, 0x58, 0x86, 0xbf, 0xaa, 0x5d, 0x94, 0x60, 0x3b, 0x81, + 0x11, 0xa0, 0xa0, 0x19, 0xf3, 0x7a, 0xfd, 0x69, 0x5f, 0xac, 0xf6, 0x41, + 0xfd, 0x73, 0xff, 0x99, 0x2a, 0x41, 0xee, 0xda, 0x7f, 0xfe, 0x80, 0xcb, + 0x20, 0x9e, 0x8f, 0xdc, 0x6c, 0x3f, 0x71, 0xed, 0x07, 0xc5, 0xd9, 0x4f, + 0x32, 0x9e, 0xe5, 0x0b, 0x63, 0x70, 0x66, 0x2b, 0x42, 0x5d, 0xa3, 0xfa, + 0x81, 0x6a, 0x47, 0x40, 0xa6, 0xed, 0x8c, 0x7d, 0x71, 0x61, 0x74, 0xd3, + 0x40, 0x24, 0x1f, 0x2c, 0x4a, 0x89, 0xd3, 0xbb, 0xb8, 0x14, 0x6b, 0x8f, + 0xb2, 0x3d, 0x16, 0x99, 0xf5, 0x7f, 0x0a, 0x2e, 0x79, 0x6b, 0xb6, 0xe8, + 0x8f, 0xb3, 0x42, 0x67, 0x93, 0x59, 0xe8, 0x69, 0x66, 0x9e, 0x6d, 0x06, + 0x11, 0x5d, 0xfd, 0x0f, 0x19, 0x43, 0x9f, 0x5b, 0x82, 0xbc, 0x5f, 0x79, + 0xeb, 0x4f, 0x7f, 0xcc, 0xfa, 0x8e, 0xe5, 0xe6, 0xe4, 0x01, 0xf7, 0xa0, + 0x7a, 0xb8, 0xe6, 0xb6, 0x08, 0x19, 0x80, 0x30, 0xa4, 0x2f, 0x84, 0xd2, + 0x5e, 0xce, 0xde, 0x59, 0x26, 0xf6, 0x19, 0x19, 0x42, 0x13, 0x0e, 0xcb, + 0x3f, 0xfb, 0x22, 0xbb, 0x61, 0xc6, 0xf8, 0xc9, 0x68, 0x77, 0x60, 0x30, + 0x85, 0x34, 0x2a, 0x30, 0x3c, 0x09, 0xd9, 0x2f, 0xf7, 0x15, 0xdc, 0x50, + 0xc5, 0x05, 0x18, 0x12, 0x2c, 0x8b, 0x55, 0xad, 0x3e, 0x2a, 0xf9, 0x1f, + 0x77, 0xa3, 0xc6, 0x34, 0x47, 0x86, 0x7d, 0x85, 0x11, 0x1c, 0x04, 0x0c, + 0x4a, 0xae, 0xc0, 0x49, 0xba, 0x46, 0xa9, 0x75, 0xd5, 0x86, 0x1b, 0xa0, + 0x18, 0x63, 0xfe, 0x9c, 0x23, 0x6c, 0xb3, 0xfe, 0x06, 0x06, 0x6f, 0xdf, + 0x8b, 0x5b, 0x59, 0x2b, 0xd4, 0x97, 0x50, 0x1b, 0x79, 0x64, 0x57, 0xbe, + 0x62, 0x46, 0xda, 0x38, 0xf3, 0x06, 0x3c, 0xec, 0x3e, 0xcf, 0x14, 0x24, + 0xc6, 0x33, 0xf6, 0x08, 0x0e, 0xe9, 0xb1, 0xbc, 0x29, 0x37, 0x13, 0x96, + 0x79, 0x2a, 0x32, 0x8e, 0x93, 0xed, 0x97, 0xcf, 0x7e, 0x72, 0xb6, 0x60, + 0x6c, 0x68, 0x2a, 0xf2, 0xbf, 0xd2, 0xe0, 0x2b, 0x76, 0xd3, 0x88, 0x24, + 0xf7, 0xfc, 0xed, 0xf9, 0x59, 0xff, 0xd1, 0xd5, 0xf4, 0x69, 0x00, 0xd2, + 0xbd, 0xfc, 0xcb, 0x1e, 0x8b, 0x51, 0x7a, 0xd5, 0x46, 0x6e, 0x11, 0x33, + 0xf8, 0xee, 0xbd, 0xb5, 0x64, 0x8b, 0xf6, 0x31, 0xd4, 0x7f, 0xda, 0x2b, + 0xf0, 0x52, 0x92, 0xaa, 0xee, 0x4e, 0x2e, 0xea, 0xdd, 0x42, 0x14, 0x51, + 0xff, 0xc0, 0xb2, 0x6e, 0xc2, 0x77, 0x7a, 0x9d, 0xce, 0x74, 0xaa, 0xe9, + 0x46, 0x67, 0x40, 0x08, 0xfe, 0xf5, 0xc0, 0xd0, 0x33, 0x2b, 0x7a, 0x07, + 0xb0, 0x37, 0x22, 0x96, 0x0c, 0xe1, 0xe2, 0x97, 0x96, 0x1b, 0xcf, 0xfc, + 0xd3, 0x4a, 0x8f, 0x6e, 0x99, 0xc1, 0xb0, 0x43, 0xb7, 0x96, 0xd4, 0xab, + 0xe6, 0x8b, 0x90, 0x98, 0x8a, 0xed, 0x0f, 0xe1, 0x77, 0x20, 0x87, 0x39, + 0x66, 0x56, 0xfa, 0xa1, 0x58, 0xd1, 0x8a, 0x0e, 0x59, 0xc0, 0x21, 0xf7, + 0x14, 0x10, 0xe3, 0xbb, 0x2f, 0xcd, 0x09, 0xc2, 0x44, 0x04, 0x27, 0x3f, + 0x68, 0xec, 0xc2, 0xd0, 0x04, 0xb5, 0x0b, 0x14, 0x8f, 0xcf, 0x04, 0xc1, + 0x94, 0x65, 0xc2, 0xbc, 0x8f, 0x9c, 0x79, 0x0b, 0xe2, 0xd6, 0x5b, 0xe9, + 0x90, 0xa5, 0x0b, 0x8c, 0xa7, 0x27, 0xc5, 0x6d, 0x89, 0x62, 0x30, 0x3d, + 0x5b, 0x7a, 0xd4, 0xee, 0x33, 0x1c, 0x42, 0x09, 0x64, 0x95, 0x64, 0x25, + 0x79, 0x63, 0x5a, 0x10, 0x79, 0x5d, 0xb4, 0x86, 0x19, 0x84, 0x84, 0x61, + 0x43, 0x1d, 0x46, 0xef, 0xd5, 0x81, 0xc0, 0xe7, 0x3f, 0x64, 0xf1, 0xf0, + 0x36, 0x1b, 0x1f, 0xdf, 0xba, 0x7e, 0x6a, 0x8b, 0xdb, 0xc2, 0x48, 0xe3, + 0x07, 0x12, 0x9e, 0xc1, 0x9c, 0x85, 0xd0, 0xa5, 0x5e, 0xda, 0x88, 0x43, + 0xb3, 0xed, 0xbb, 0xd3, 0xdf, 0x8e, 0x6f, 0x13, 0x51, 0x52, 0x50, 0x73, + 0x97, 0xc1, 0xd0, 0xb7, 0xd7, 0x82, 0x31, 0xfd, 0xc2, 0x96, 0xc3, 0x37, + 0xd4, 0x1c, 0xfd, 0x90, 0x47, 0x1c, 0x7e, 0xc6, 0xb0, 0x0d, 0x6f, 0x96, + 0x65, 0x6b, 0x9d, 0xbd, 0x59, 0x13, 0xca, 0x32, 0xc3, 0x29, 0x39, 0xdc, + 0x6c, 0x26, 0x15, 0xc8, 0x83, 0xa8, 0x5d, 0x9d, 0x1d, 0x30, 0x64, 0x65, + 0x05, 0x48, 0xce, 0xaa, 0x69, 0xf7, 0x42, 0xa6, 0x1f, 0x9d, 0xcb, 0xc9, + 0x5b, 0xe7, 0x69, 0xcf, 0x29, 0xd1, 0xa5, 0xcf, 0x55, 0x79, 0xff, 0x6c, + 0xfa, 0xac, 0xb8, 0xec, 0x33, 0x61, 0xc1, 0x33, 0x5c, 0xef, 0x0f, 0x92, + 0x93, 0x4a, 0x83, 0x79, 0x48, 0x21, 0xba, 0xf7, 0xcb, 0x01, 0x63, 0x84, + 0x22, 0xc6, 0xec, 0x8c, 0x66, 0x8d, 0x97, 0x42, 0x56, 0x75, 0x73, 0x61, + 0xcb, 0xfa, 0xd4, 0x20, 0x66, 0xce, 0x6a, 0x81, 0x78, 0xa6, 0xc8, 0x72, + 0xeb, 0x15, 0x25, 0xb2, 0x06, 0xc0, 0xb2, 0xab, 0x18, 0x66, 0x4e, 0x5e, + 0x73, 0x21, 0x55, 0xd6, 0xe3, 0x60, 0x81, 0x56, 0x85, 0x1f, 0x5a, 0xce, + 0xff, 0xc0, 0x6a, 0xd3, 0x18, 0xdd, 0xfd, 0xaa, 0x73, 0x42, 0xb1, 0xd5, + 0x62, 0xda, 0x2e, 0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, + 0x65, 0x2e, 0x61, 0x70, 0x73, 0x64, 0x64, 0x6b, 0x75, 0x8c, 0x10, 0x01, + 0x11, 0x00, 0x07, 0x07, 0x01, 0x01, 0x34, 0x00, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x95, 0x4a, 0x33, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x4b, 0x83, 0xb6, + 0x03, 0x41, 0xb7, 0x59, 0x5c, 0x4b, 0x83, 0xb6, 0x03, 0x03, 0x03, 0xb1, + 0x0a, 0x33, 0x78, 0x48, 0x21, 0xea, 0x97, 0x6e, 0xb7, 0xc7, 0x2e, 0xdb, + 0x0f, 0x9b, 0x01, 0xd0, 0x22, 0x6d, 0xbb, 0x7e, 0x0b, 0xaa, 0xec, 0xd2, + 0x3c, 0x92, 0x58, 0xd7, 0xfd, 0x92, 0x3c, 0xf8, 0x03, 0x3e, 0x70, 0x20, + 0x84, 0xa7, 0x17, 0x2c, 0xf0, 0xfa, 0xf2, 0x6b, 0xa9, 0x12, 0x4e, 0x73, + 0x93, 0x45, 0x6c, 0x2f, 0x97, 0x33, 0x72, 0xa1, 0x3b, 0x0d, 0x66, 0x6e, + 0x37, 0x4b, 0xba, 0xaa, 0x65, 0x68, 0x18, 0x44, 0x35, 0x5b, 0x9a, 0x6f, + 0xf1, 0x3c, 0x2b, 0x18, 0x1f, 0xda, 0x4c, 0xda, 0xde, 0x08, 0x82, 0x7d, + 0xfa, 0x5c, 0xf3, 0x42, 0xb1, 0x04, 0x84, 0xf4, 0xba, 0xe3, 0x73, 0xe9, + 0x35, 0x6f, 0xbb, 0x64, 0x14, 0x5e, 0x86, 0xb3, 0x7b, 0x2d, 0x6c, 0xa9, + 0xc0, 0xcf, 0xd8, 0x43, 0x7e, 0x59, 0x45, 0xac, 0xff, 0x92, 0x4b, 0x02, + 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x15, + 0x67, 0xb2, 0x55, 0xfa, 0x3d, 0xce, 0x31, 0x23, 0xdf, 0x93, 0xad, 0x9c, + 0x09, 0x8d, 0xbc, 0x7e, 0xb3, 0x84, 0x6c, 0x0a, 0x52, 0x6e, 0xab, 0x7d, + 0x13, 0x86, 0xcc, 0xbe, 0xf3, 0x30, 0x0b, 0x08, 0xf8, 0xa1, 0xcf, 0x62, + 0x7a, 0x7e, 0xaf, 0xd7, 0x55, 0x51, 0x92, 0x16, 0x1d, 0x3e, 0x5e, 0x37, + 0x86, 0xf2, 0xea, 0x51, 0xee, 0x6a, 0xe3, 0xa6, 0xe1, 0xc5, 0xce, 0x5f, + 0x86, 0x3e, 0x5a, 0x3d, 0x6d, 0x31, 0xf9, 0x10, 0xe3, 0xd6, 0x77, 0x76, + 0x33, 0x03, 0xfc, 0x2a, 0x0c, 0x45, 0x5c, 0x29, 0xa8, 0x9f, 0x96, 0x45, + 0xd5, 0xae, 0x9f, 0x21, 0x9a, 0x1a, 0x6d, 0x85, 0x4f, 0x3d, 0x35, 0x85, + 0xf1, 0x6a, 0x11, 0xf3, 0x54, 0x3e, 0x96, 0x4c, 0xbf, 0xa6, 0x01, 0xd4, + 0xc8, 0x67, 0xc1, 0x94, 0x16, 0x19, 0x39, 0x42, 0x28, 0xc9, 0x5b, 0x88, + 0x09, 0xbf, 0xba, 0xf2, 0x9b, 0x4f, 0x13, 0x73, 0x8b, 0x2c, 0x98, 0x07, + 0x70, 0xa7, 0x27, 0xae, 0x02, 0xa3, 0x63, 0x11, 0x5b, 0x1b, 0x8c, 0x85, + 0x8e, 0x0f, 0xde, 0xf9, 0x0b, 0x8f, 0x06, 0xfd, 0xab, 0x03, 0x34, 0x52, + 0x23, 0x52, 0x2e, 0xf1, 0xa8, 0x30, 0x89, 0xe8, 0xdc, 0x8f, 0xe4, 0x9f, + 0xd3, 0xa1, 0x09, 0x33, 0x5b, 0x07, 0xc8, 0x9c, 0x49, 0x47, 0x37, 0x53, + 0x35, 0xc5, 0x1e, 0x78, 0x9f, 0xc7, 0x65, 0x94, 0xf6, 0xb9, 0xcf, 0xcc, + 0xee, 0xfc, 0x73, 0x40, 0x42, 0xb8, 0x37, 0x12, 0xfd, 0x34, 0xea, 0xdd, + 0x89, 0x01, 0x51, 0xfe, 0xde, 0xb6, 0xb6, 0x1e, 0x40, 0x39, 0x12, 0xf8, + 0xdd, 0x5c, 0x96, 0xb6, 0x1b, 0x21, 0x08, 0xaf, 0x6e, 0x62, 0xbb, 0x3c, + 0x65, 0xd1, 0xa9, 0x15, 0xb0, 0xf6, 0x1b, 0xbb, 0xac, 0x26, 0xa5, 0x82, + 0xc6, 0x43, 0xa0, 0x88, 0xf1, 0x64, 0x64, 0x01, 0xd9, 0xa9, 0x5e, 0xf0, + 0x73, 0x52, 0xfb, 0xc9, 0x27, 0x81, 0x0e, 0xce, 0x8e, 0x4c, 0xc8, 0x3d, + 0xef, 0xe2, 0xdc, 0xe3, 0xe9, 0x23, 0x3c, 0x47, 0x93, 0xcb, 0x18, 0xe6, + 0x11, 0xe2, 0x40, 0xd7, 0x73, 0x18, 0x6b, 0xbd, 0x77, 0x56, 0x6e, 0x6c, + 0xe8, 0x25, 0xe7, 0xef, 0x12, 0xc7, 0x8f, 0x38, 0x80, 0x0e, 0xd1, 0x97, + 0x71, 0xef, 0xfa, 0x78, 0xac, 0x3d, 0x55, 0x45, 0x83, 0x45, 0x62, 0xb0, + 0x9a, 0xbf, 0x45, 0xd5, 0xbe, 0x45, 0x8a, 0xa2, 0x21, 0x88, 0xb9, 0xd0, + 0x3e, 0x59, 0xbb, 0x68, 0x77, 0xb7, 0x29, 0x65, 0x4a, 0x8d, 0xf4, 0x1d, + 0xf1, 0xd1, 0x00, 0x92, 0x2d, 0xcb, 0x6b, 0xaa, 0x9d, 0x1d, 0x0f, 0xf1, + 0x45, 0x0b, 0x13, 0x47, 0x2b, 0x47, 0x00, 0x30, 0x72, 0x0c, 0xa8, 0xb2, + 0xcb, 0x5b, 0xcd, 0xee, 0x30, 0x8d, 0xdb, 0x62, 0xd1, 0xb5, 0x5f, 0xe1, + 0x3e, 0xf8, 0x96, 0x09, 0x1e, 0x82, 0x2e, 0xf1, 0x8c, 0x20, 0x52, 0x33, + 0x2e, 0x42, 0x5c, 0x64, 0x39, 0xa2, 0x7b, 0x84, 0x2f, 0xff, 0x02, 0x24, + 0xdd, 0x40, 0x23, 0x9c, 0xec, 0xf0, 0xe9, 0x8f, 0x37, 0x15, 0xfd, 0xca, + 0xa5, 0xa6, 0x30, 0x1f, 0x4f, 0xa6, 0xf1, 0x05, 0xd8, 0x2f, 0x0b, 0xbf, + 0xa4, 0x3a, 0x9f, 0x57, 0x31, 0xb3, 0x9d, 0x64, 0xa5, 0xc9, 0x13, 0x64, + 0x7f, 0xb2, 0xe9, 0x38, 0x55, 0xe2, 0xd7, 0x6f, 0xad, 0xe5, 0x77, 0xf9, + 0xbe, 0x17, 0xcc, 0xec, 0xfb, 0xe4, 0xd1, 0x13, 0xa3, 0x20, 0x6e, 0xa6, + 0x64, 0x4e, 0xda, 0xa8, 0x86, 0xfc, 0xc8, 0x29, 0xb9, 0x47, 0xc1, 0xf0, + 0xe1, 0xc9, 0x62, 0x1d, 0x6a, 0x64, 0x8e, 0x1b, 0x76, 0x6a, 0x49, 0x22, + 0xeb, 0xfc, 0x33, 0xbc, 0x27, 0x8c, 0x84, 0x40, 0xe9, 0x3f, 0x46, 0x11, + 0x52, 0xf7, 0xe1, 0xbe, 0xbb, 0x48, 0x31, 0x28, 0x12, 0x62, 0x4a, 0x88, + 0x46, 0xf2, 0x4c, 0x1b, 0x03, 0xa6, 0x6f, 0xd3, 0x58, 0x35, 0x47, 0x24, + 0x53, 0x61, 0xc2, 0xa3, 0x6b, 0xc2, 0x6b, 0x73, 0x96, 0x2b, 0xd0, 0xd9, + 0x7d, 0x8e, 0xf1, 0x1a, 0x24, 0xfd, 0x34, 0x97, 0x02, 0xde, 0x0e, 0x79, + 0x29, 0xd2, 0x61, 0x2b, 0xca, 0x09, 0xea, 0xf2, 0xda, 0x17, 0x07, 0x8e, + 0x39, 0xc5, 0xee, 0x52, 0x76, 0x36, 0xce, 0x40, 0xee, 0xfa, 0x03, 0x40, + 0x9b, 0x91, 0xf6, 0x5e, 0x82, 0x46, 0x3e, 0x91, 0x13, 0xf2, 0x4e, 0x49, + 0x1d, 0x61, 0xf2, 0x6a, 0xcd, 0x5f, 0x06, 0xf0, 0xde, 0x9d, 0x5c, 0x8d, + 0xf5, 0xf6, 0xe5, 0x20, 0x1f, 0x1e, 0xd3, 0x37, 0x6f, 0x4a, 0xf5, 0x9e, + 0x93, 0x25, 0x27, 0xcc, 0x41, 0x53, 0x0c, 0xc7, 0x6b, 0x23, 0x42, 0xe0, + 0x3e, 0xe0, 0xb0, 0x06, 0x64, 0xc2, 0xf2, 0x6b, 0x45, 0x49, 0x25, 0x16, + 0x39, 0x9b, 0x67, 0xf8, 0xa0, 0x2f, 0x38, 0x48, 0x97, 0xd2, 0x59, 0x16, + 0x5b, 0x86, 0x10, 0xdd, 0x92, 0xa2, 0x26, 0x67, 0x46, 0xd8, 0x5f, 0x1a, + 0xe7, 0x16, 0x9f, 0x8e, 0xb5, 0x04, 0x4d, 0x1b, 0x14, 0xaf, 0x3e, 0xf6, + 0xf3, 0x2e, 0x9f, 0xb0, 0x9f, 0x93, 0x2a, 0x9e, 0xae, 0x2f, 0xeb, 0x23, + 0xf8, 0x34, 0xb4, 0x39, 0x0a, 0xbb, 0x58, 0x5a, 0x43, 0x1e, 0xf0, 0x33, + 0x2e, 0x78, 0x62, 0x69, 0xd6, 0x31, 0x01, 0xc2, 0xc9, 0x7e, 0xcd, 0x8f, + 0x2e, 0xab, 0x2d, 0x46, 0x5a, 0xfe, 0xdb, 0x44, 0x2f, 0x83, 0xbf, 0xd2, + 0x1a, 0x77, 0xd4, 0x1c, 0x9d, 0x6a, 0x72, 0xc1, 0xcd, 0x6c, 0x3a, 0x18, + 0xa7, 0x83, 0x71, 0x4a, 0x2b, 0x25, 0x79, 0xea, 0x34, 0x14, 0x7c, 0xe0, + 0xbf, 0xbc, 0x53, 0xf7, 0xa0, 0x5f, 0x70, 0xa8, 0x4e, 0x7d, 0xec, 0x82, + 0x16, 0x1d, 0xa5, 0x1f, 0x4c, 0xc6, 0xe7, 0xc3, 0x81, 0x9f, 0x1b, 0xd3, + 0x13, 0x5b, 0x22, 0x26, 0x1f, 0xc1, 0x63, 0xb0, 0xe7, 0x42, 0xc6, 0x74, + 0x3b, 0xb4, 0xbf, 0xa8, 0xb9, 0xf6, 0xaa, 0x67, 0x59, 0x96, 0x2d, 0xc1, + 0xd0, 0xf4, 0xe8, 0x84, 0xc7, 0x5e, 0xae, 0xca, 0xe8, 0x45, 0x68, 0xa8, + 0xd4, 0x87, 0x2f, 0x81, 0x08, 0x63, 0xd0, 0xb0, 0x5d, 0x04, 0x4d, 0x6a, + 0x72, 0xc4, 0x11, 0xc2, 0x05, 0x32, 0x20, 0xd6, 0x32, 0x44, 0x1d, 0xae, + 0xc9, 0x5d, 0x27, 0x67, 0xeb, 0xed, 0x63, 0xf6, 0x45, 0x25, 0xb8, 0x4c, + 0xf7, 0x63, 0xed, 0x18, 0x02, 0x0b, 0x53, 0x8d, 0x43, 0x45, 0x2f, 0x94, + 0x2f, 0x0f, 0xe9, 0x40, 0x41, 0x10, 0x57, 0x4f, 0x90, 0x29, 0x5b, 0x6e, + 0x8b, 0x72, 0x35, 0x25, 0xf9, 0x8c, 0xf1, 0x82, 0x3a, 0xa6, 0xcc, 0x8a, + 0xed, 0x3d, 0xfe, 0x85, 0xd7, 0xd9, 0x53, 0x42, 0x14, 0x34, 0x38, 0xef, + 0x1a, 0x8a, 0xbd, 0xd2, 0x17, 0x14, 0xac, 0x3e, 0xd8, 0x14, 0x26, 0xe7, + 0xc5, 0xdf, 0xd7, 0xad, 0x5c, 0xc9, 0x23, 0x46, 0x3d, 0xdb, 0xbd, 0xa0, + 0xc9, 0x12, 0x13, 0x9b, 0x45, 0x66, 0x6a, 0x96, 0xc3, 0x8b, 0xc5, 0x0a, + 0xc7, 0x38, 0x2f, 0x98, 0x4a, 0x32, 0x96, 0xbe, 0x14, 0xf7, 0x8b, 0x8d, + 0x45, 0x64, 0xf9, 0x94, 0x53, 0x1a, 0x00, 0x12, 0x9c, 0xc1, 0x0b, 0x7b, + 0x05, 0x3f, 0xaf, 0xc1, 0x79, 0x7f, 0x75, 0x54, 0xec, 0xc3, 0x1d, 0xd9, + 0xb5, 0x27, 0xed, 0xd9, 0x21, 0xfa, 0x42, 0xe5, 0x53, 0x40, 0xe5, 0x3a, + 0x51, 0x78, 0x8a, 0xe2, 0x80, 0xac, 0x5b, 0xff, 0xfd, 0x11, 0x4a, 0x58, + 0xc1, 0xb4, 0x4d, 0xdc, 0xc4, 0xa3, 0x4c, 0x57, 0x3d, 0x77, 0xb2, 0x98, + 0xdc, 0x9f, 0x7d, 0x97, 0x85, 0xd0, 0x16, 0x2a, 0x63, 0x2c, 0x79, 0x1a, + 0xce, 0xcf, 0x0c, 0x3b, 0x24, 0x2a, 0x39, 0x9f, 0x06, 0x1a, 0xc6, 0x49, + 0xf3, 0x86, 0xd4, 0x8d, 0x65, 0x77, 0x02, 0xc6, 0x35, 0x38, 0x97, 0x23, + 0x85, 0x7c, 0x6f, 0x5c, 0x0e, 0x78, 0xdd, 0xe7, 0x48, 0x40, 0xe5, 0x22, + 0xae, 0xef, 0x81, 0x02, 0xec, 0xc7, 0x0f, 0x12, 0x0f, 0x46, 0xd3, 0x7e, + 0x45, 0x17, 0xf7, 0xbe, 0x33, 0x84, 0x20, 0x08, 0xab, 0xdb, 0xa0, 0x01, + 0xcc, 0x8a, 0x0e, 0xfb, 0x81, 0x53, 0x44, 0x48, 0x07, 0xd5, 0x3e, 0xd2, + 0xcd, 0x3e, 0x6d, 0x00, 0x5d, 0x59, 0xeb, 0x15, 0x38, 0xb2, 0x49, 0x0e, + 0x85, 0x52, 0x93, 0x92, 0xd6, 0x27, 0x1f, 0x8f, 0x58, 0x54, 0x08, 0xc1, + 0x15, 0x66, 0x0a, 0x71, 0x6f, 0xe9, 0xf1, 0x5c, 0x3e, 0xcf, 0x9e, 0xde, + 0x1f, 0xdc, 0x79, 0xe9, 0xc1, 0x38, 0xa5, 0x3f, 0xe3, 0x60, 0x53, 0x0f, + 0xe6, 0xb3, 0x18, 0x67, 0x92, 0xff, 0x02, 0xa3, 0x20, 0x99, 0xda, 0xb2, + 0xa3, 0xa5, 0x72, 0x48, 0x1f, 0x76, 0x3e, 0xa2, 0x78, 0x37, 0xc2, 0xbf, + 0x00, 0x93, 0xdc, 0xa4, 0x96, 0xd1, 0xc8, 0xe9, 0xf1, 0xd2, 0xc7, 0x68, + 0x47, 0xdc, 0x36, 0x1c, 0x13, 0x34, 0xbd, 0xd9, 0x36, 0x9b, 0x70, 0x1a, + 0x56, 0x27, 0xd2, 0x7e, 0xe6, 0xd3, 0x74, 0x84, 0x24, 0x78, 0x68, 0xad, + 0x4c, 0x5e, 0xb9, 0xf2, 0x63, 0x80, 0x58, 0xc2, 0x93, 0xef, 0x7e, 0xf1, + 0xf7, 0x46, 0x4f, 0x89, 0xd3, 0x09, 0x07, 0x2c, 0x83, 0x44, 0x57, 0x7c, + 0x6d, 0x38, 0x27, 0x63, 0x22, 0x28, 0x55, 0xf5, 0x3e, 0xcb, 0x4d, 0x4f, + 0x4d, 0x82, 0x27, 0x96, 0x2d, 0xe9, 0x72, 0xeb, 0x86, 0x3a, 0x90, 0xa6, + 0xc4, 0x09, 0x6d, 0xbc, 0x13, 0x64, 0x58, 0x1e, 0xfc, 0xee, 0xee, 0x00, + 0x25, 0x92, 0x8d, 0x0b, 0x16, 0xf2, 0xd1, 0xd3, 0x2a, 0xb6, 0x00, 0xa3, + 0x4c, 0x58, 0xf9, 0x0b, 0x78, 0x9b, 0xc5, 0x11, 0xba, 0xa9, 0x36, 0xd7, + 0x74, 0xdd, 0x49, 0x30, 0x6d, 0x54, 0x6f, 0xb2, 0x0f, 0xf3, 0x7c, 0xc8, + 0x57, 0x55, 0x8e, 0x19, 0x09, 0x62, 0xaf, 0x34, 0x2e, 0x01, 0x65, 0xe3, + 0x15, 0x2c, 0xd6, 0x5f, 0x62, 0x50, 0xbf, 0xe9, 0xf6, 0x4a, 0xa8, 0x14, + 0x15, 0xe1, 0x22, 0xdc, 0x6d, 0x5e, 0x8b, 0x02, 0x86, 0x3d, 0xea, 0xcf, + 0x62, 0x9c, 0x70, 0xb1, 0x9e, 0x2e, 0x40, 0x62, 0x2d, 0x0d, 0x91, 0xac, + 0xaf, 0xcd, 0x3b, 0xa1, 0xf1, 0xfe, 0xaf, 0x16, 0xd4, 0xa3, 0xe5, 0x76, + 0xd9, 0x0e, 0x3e, 0x15, 0x59, 0x5d, 0x01, 0xc7, 0xf7, 0x57, 0xdb, 0x29, + 0x18, 0x03, 0x61, 0x00, 0xc5, 0x4b, 0xb1, 0x16, 0x3a, 0x9e, 0xa5, 0xc5, + 0x87, 0x88, 0x42, 0xda, 0xcd, 0x87, 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, + 0x77, 0x6e, 0x2d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, + 0x73, 0x64, 0x6b, 0x75, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x0f, 0x7e, 0x00, + 0x0f, 0x7e, 0x0f, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x06, + 0x01, 0x34, 0x34, 0x29, 0x01, 0x03, 0x2c, 0xf0, 0xfa, 0xf2, 0x6b, 0xa9, + 0x12, 0x4e, 0x73, 0x93, 0x45, 0x6c, 0x2f, 0x97, 0x33, 0x72, 0xa1, 0x3b, + 0x0d, 0x66, 0x6e, 0x37, 0x4b, 0xba, 0xaa, 0x65, 0x68, 0x18, 0x44, 0x35, + 0x5b, 0x9a, 0x6f, 0xf1, 0x3c, 0x2b, 0x18, 0x1f, 0xda, 0x4c, 0x63, 0x6f, + 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x73, 0x64, + 0x02, 0x42, 0x06, 0x01, 0x34, 0x34, 0x33, 0x09, 0x03, 0x2c, 0xf0, 0xfa, + 0xf2, 0x6b, 0xa9, 0x12, 0x4e, 0x73, 0x93, 0x45, 0x6c, 0x2f, 0x97, 0x33, + 0x72, 0xa1, 0x3b, 0x0d, 0x66, 0x6e, 0x37, 0x4b, 0xba, 0xaa, 0x65, 0x68, + 0x18, 0x44, 0x35, 0x5b, 0x9a, 0x6f, 0xf1, 0x3c, 0x2b, 0x18, 0x1f, 0xda, + 0x4c, 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x2d, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x05, 0x00, 0x00, 0x00, + 0x01, 0x0f, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0f, 0xfb, 0x00, 0x51, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x61, 0x04, 0x23, 0x00, 0x07, 0x07, + 0x09, 0x34, 0x00, 0x09, 0x09, 0x09, 0x34, 0x34, 0x08, 0x01, 0x02, 0x02, + 0x08, 0x08, 0x08, 0x08, 0x09, 0x08, 0x08, 0x09, 0x09, 0x09, 0x08, 0x08, + 0x08, 0x08, 0x09, 0x89, 0x56, 0x17, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x83, + 0x2b, 0xa8, 0x0d, 0x41, 0xb7, 0x59, 0x5c, 0x83, 0x2b, 0xa8, 0x0d, 0xdf, + 0xb4, 0xb1, 0x32, 0xb5, 0x0f, 0xc0, 0x25, 0xc5, 0x8d, 0xd9, 0x08, 0xc5, + 0x28, 0x81, 0xd3, 0x73, 0x52, 0xf9, 0x26, 0x9b, 0x66, 0x83, 0xaf, 0x24, + 0x40, 0x8e, 0xa7, 0xd6, 0x76, 0x12, 0x4a, 0x40, 0x61, 0xb5, 0x6a, 0xbc, + 0x33, 0xef, 0x01, 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, + 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0x2b, + 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x4e, 0x6b, 0x19, 0x54, 0xf5, 0xf0, 0xaf, 0x61, + 0xfa, 0x1e, 0x1f, 0x1f, 0x5e, 0x17, 0xd3, 0x8e, 0x04, 0x4b, 0xfa, 0x8d, + 0x34, 0x55, 0x45, 0x92, 0xd5, 0xd0, 0xb8, 0x8e, 0x56, 0xe9, 0x39, 0x37, + 0x8e, 0x7d, 0x7e, 0x88, 0x56, 0x30, 0x48, 0x61, 0xb4, 0xed, 0x1e, 0x15, + 0x64, 0xfc, 0xa8, 0xb1, 0x02, 0xbb, 0x9c, 0x14, 0xe9, 0xd1, 0xe0, 0xcf, + 0x40, 0x41, 0x46, 0x5d, 0xb0, 0xda, 0xba, 0x8c, 0x3a, 0x41, 0x12, 0x91, + 0xeb, 0x13, 0xdf, 0x2c, 0x6e, 0x25, 0x75, 0xb3, 0x92, 0xff, 0xb0, 0xa9, + 0xa5, 0xef, 0x3a, 0x4c, 0x6b, 0x54, 0x55, 0x0e, 0x7e, 0x93, 0x16, 0x7f, + 0xe6, 0x22, 0x22, 0x51, 0xe2, 0x22, 0xa4, 0x35, 0x33, 0xec, 0xdc, 0xa8, + 0x73, 0x64, 0x59, 0xc1, 0x4d, 0xad, 0xa0, 0x56, 0xbf, 0xad, 0x45, 0x64, + 0xda, 0xb0, 0x08, 0x4a, 0x82, 0xfc, 0x0d, 0x21, 0xb7, 0x8b, 0x59, 0x90, + 0xac, 0xb2, 0x08, 0x1b, 0x50, 0x82, 0x0c, 0x87, 0xd6, 0x48, 0x5c, 0xdd, + 0x6b, 0x02, 0x7f, 0xab, 0x3e, 0xdc, 0x25, 0x1f, 0x53, 0x49, 0xb5, 0x6d, + 0x0f, 0x0c, 0xbe, 0xae, 0x1d, 0xab, 0x8b, 0x13, 0x9d, 0xd7, 0x6c, 0x91, + 0xaa, 0x90, 0xe8, 0x63, 0x06, 0x6d, 0xa8, 0xf0, 0xea, 0x21, 0xf6, 0xa8, + 0xfd, 0x15, 0x6d, 0x78, 0x66, 0x42, 0xae, 0x4c, 0xa7, 0x7a, 0x85, 0x15, + 0x7d, 0xf9, 0xed, 0x92, 0x1c, 0xde, 0x7c, 0x71, 0xd0, 0x6b, 0x25, 0x24, + 0x22, 0x6b, 0xe4, 0x5e, 0x60, 0xda, 0xbd, 0x95, 0x32, 0x21, 0xe8, 0xb1, + 0xcb, 0x07, 0x1b, 0x08, 0xf5, 0x49, 0x4f, 0x60, 0x8c, 0xe8, 0xb0, 0x71, + 0x2a, 0x8b, 0x91, 0x17, 0x16, 0x93, 0x39, 0x49, 0x8d, 0x47, 0x1f, 0xe8, + 0x2b, 0x12, 0xa6, 0x4f, 0xa1, 0x77, 0x37, 0xe7, 0x39, 0x68, 0x5c, 0x68, + 0x2b, 0xad, 0xa8, 0x3c, 0xa0, 0x8a, 0xf5, 0xb7, 0x51, 0x9f, 0x2d, 0x85, + 0x1a, 0x99, 0x02, 0x4c, 0x84, 0x5f, 0x4d, 0xe6, 0x55, 0x64, 0xd7, 0x5b, + 0x00, 0x48, 0xde, 0xf2, 0x77, 0x39, 0x6e, 0x7b, 0x0e, 0x97, 0x81, 0xd2, + 0x8a, 0x1b, 0x20, 0x30, 0x60, 0xbe, 0x94, 0xf0, 0x09, 0x34, 0xfe, 0x64, + 0xbb, 0xbb, 0xcb, 0x97, 0x91, 0x43, 0x6d, 0x57, 0x45, 0x7d, 0xc5, 0x43, + 0x5a, 0x78, 0x0d, 0xd8, 0xb9, 0xf5, 0x43, 0x13, 0x21, 0xd6, 0x31, 0x6e, + 0x21, 0x9a, 0x3f, 0x8f, 0xe2, 0x57, 0x32, 0xdb, 0x50, 0x61, 0x45, 0x9f, + 0xb9, 0x7b, 0x73, 0x10, 0xb9, 0xd0, 0x66, 0xaf, 0xa0, 0x3a, 0x77, 0x93, + 0x9b, 0xd3, 0x32, 0xb0, 0xda, 0x01, 0x17, 0x90, 0x1a, 0xa5, 0x9f, 0x2b, + 0x9f, 0x8f, 0x93, 0x6e, 0x4d, 0x69, 0x40, 0xec, 0x56, 0x76, 0x61, 0x2d, + 0xcd, 0xdf, 0xc5, 0xfe, 0x9e, 0x26, 0x2f, 0x78, 0x78, 0xab, 0x5a, 0x32, + 0xa6, 0xe9, 0x7a, 0x85, 0x15, 0xc6, 0x2f, 0x10, 0x37, 0x35, 0xf6, 0xfa, + 0xc0, 0xdd, 0xb0, 0xa9, 0xa1, 0x0d, 0x22, 0xc1, 0xab, 0xc8, 0x8c, 0x2a, + 0x77, 0x0b, 0xd3, 0x52, 0xdb, 0x53, 0x33, 0x78, 0xf3, 0xf6, 0x33, 0x5d, + 0x9f, 0xb7, 0xb6, 0x46, 0xf6, 0x79, 0x9e, 0x08, 0x16, 0xd8, 0x48, 0xcf, + 0x70, 0x4d, 0x00, 0x36, 0x30, 0xdb, 0xb3, 0x76, 0xa5, 0x16, 0x78, 0xf8, + 0xaf, 0x71, 0x6b, 0x50, 0x92, 0xfc, 0x52, 0xd6, 0x2c, 0xee, 0xa8, 0xb0, + 0xbe, 0x89, 0x18, 0xc0, 0x7a, 0x72, 0xa5, 0x36, 0x31, 0x7b, 0x86, 0xca, + 0xc0, 0xe4, 0x08, 0x17, 0x1d, 0x6e, 0xe5, 0x4c, 0x82, 0x86, 0x3e, 0x8c, + 0x60, 0xf7, 0x04, 0x8f, 0x2c, 0x64, 0x3d, 0x2e, 0x23, 0x22, 0x10, 0x8e, + 0x88, 0x45, 0xcd, 0x18, 0xd6, 0xba, 0x4c, 0x40, 0x1e, 0x31, 0xfb, 0xbf, + 0xda, 0xe7, 0xae, 0x87, 0x72, 0x81, 0xb2, 0x69, 0x97, 0xe3, 0x2c, 0x5e, + 0xbb, 0x26, 0x1b, 0xe2, 0x83, 0xf3, 0x90, 0x37, 0x0d, 0xb1, 0xa2, 0x58, + 0x88, 0x63, 0xe7, 0x6e, 0x4a, 0xbd, 0x76, 0x90, 0x73, 0x65, 0x85, 0x96, + 0xcc, 0x2d, 0xb7, 0x51, 0x0d, 0xa7, 0x8a, 0xe2, 0x8c, 0x47, 0xb9, 0x44, + 0x09, 0xc3, 0x8f, 0x24, 0x65, 0x79, 0xf0, 0xd0, 0xc3, 0xa5, 0x1f, 0xc3, + 0xca, 0xd7, 0x57, 0xac, 0x1c, 0xcf, 0xa9, 0xfc, 0x81, 0x12, 0x53, 0x0b, + 0xe5, 0x9d, 0x38, 0x29, 0x14, 0xd6, 0xf5, 0x17, 0x06, 0xfb, 0xc2, 0x9d, + 0x25, 0x10, 0xf9, 0xde, 0x4b, 0x33, 0x0d, 0xf1, 0xdd, 0xf5, 0xbc, 0xa8, + 0x2b, 0xdc, 0xdb, 0x51, 0x7d, 0x69, 0x63, 0x68, 0x61, 0x74, 0x64, 0x6b, + 0x75, 0x85, 0x41, 0x03, 0x23, 0x00, 0x07, 0x07, 0x08, 0x34, 0x00, 0x09, + 0x09, 0x09, 0x34, 0x34, 0x08, 0x01, 0x02, 0x02, 0x08, 0x08, 0x08, 0x08, + 0x09, 0x08, 0x08, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x09, 0x89, + 0x16, 0x17, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x83, 0x25, 0xab, 0x8f, 0x41, + 0xb7, 0x59, 0x5c, 0x83, 0x25, 0xab, 0x8f, 0xdf, 0xb4, 0xb1, 0x32, 0xb5, + 0x0f, 0xc0, 0x25, 0xc5, 0x8d, 0xd9, 0x08, 0xc5, 0x28, 0x81, 0xd3, 0x73, + 0x52, 0xf9, 0x26, 0x9b, 0x66, 0x83, 0xaf, 0x24, 0x40, 0x8e, 0xa7, 0xd6, + 0x76, 0x12, 0x4a, 0x40, 0x61, 0xb5, 0x6a, 0xbc, 0x33, 0xef, 0x01, 0xda, + 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, + 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0x2b, 0x01, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0xe3, 0xb5, 0xfb, 0x0d, 0xa0, 0x75, 0xd1, 0xa9, 0x33, 0x31, 0xc6, 0x84, + 0xba, 0x58, 0x50, 0xb0, 0x71, 0x32, 0x4f, 0x72, 0x88, 0x46, 0x71, 0x06, + 0xb3, 0x82, 0x5e, 0x30, 0xfd, 0xc8, 0x5b, 0xc8, 0xf3, 0x24, 0x92, 0xe0, + 0xce, 0x8b, 0xf7, 0x50, 0x20, 0xc3, 0xeb, 0x1b, 0xf4, 0xef, 0x4f, 0xfa, + 0x28, 0x4d, 0x02, 0x4d, 0x7c, 0x46, 0xf1, 0x91, 0x89, 0xde, 0xc6, 0xfa, + 0x79, 0xc5, 0xbd, 0x17, 0xa1, 0xc6, 0x1d, 0x8c, 0xd4, 0x57, 0xa6, 0x58, + 0x66, 0xce, 0xe5, 0xb0, 0x8b, 0x54, 0xef, 0x3b, 0x24, 0x9b, 0xa4, 0xc4, + 0x6a, 0xa9, 0xf3, 0x1b, 0x73, 0x37, 0x10, 0xc0, 0xe1, 0xcb, 0xc8, 0x90, + 0x14, 0x88, 0x97, 0x25, 0x8b, 0x7c, 0xa2, 0x66, 0x36, 0x89, 0x55, 0x8d, + 0x68, 0xe7, 0x55, 0x20, 0x10, 0x68, 0x14, 0x2f, 0x05, 0x3b, 0xe3, 0x81, + 0x08, 0xfe, 0x54, 0x7d, 0xa5, 0x51, 0x2a, 0x39, 0x86, 0x11, 0xce, 0x26, + 0x8d, 0xe1, 0xec, 0x30, 0x3f, 0xf9, 0xa3, 0x3d, 0x43, 0x6c, 0xad, 0x23, + 0x54, 0x20, 0x7d, 0x60, 0xa5, 0x42, 0xbd, 0x3d, 0x22, 0xc8, 0x95, 0x9b, + 0xab, 0x5b, 0xf7, 0xc1, 0x11, 0xfb, 0xf1, 0x70, 0xa2, 0x43, 0xcb, 0x53, + 0x8c, 0x18, 0x0d, 0x8a, 0xb2, 0xa5, 0xbd, 0x87, 0x2b, 0x8b, 0xdf, 0x79, + 0x96, 0x29, 0x20, 0x8e, 0x34, 0x4a, 0x45, 0x96, 0x33, 0x8d, 0xa8, 0xb0, + 0x47, 0x26, 0x4f, 0x8b, 0xad, 0xb5, 0xa7, 0x2d, 0x15, 0x58, 0x92, 0x7b, + 0x4b, 0x53, 0xa9, 0x5e, 0x51, 0x39, 0x9c, 0xbd, 0x7e, 0x8f, 0x7f, 0x9f, + 0xb7, 0x38, 0xcd, 0x7e, 0xff, 0x7d, 0x73, 0x1f, 0xab, 0x3a, 0x61, 0xaa, + 0xde, 0x73, 0x28, 0xb2, 0x6f, 0x1e, 0xc9, 0x5e, 0x59, 0x71, 0x6b, 0xe8, + 0x6d, 0x63, 0xf3, 0x9e, 0xdf, 0x52, 0x86, 0x60, 0x1c, 0xbd, 0xc7, 0xeb, + 0xaf, 0x82, 0x83, 0xaa, 0x68, 0xa6, 0x71, 0x7a, 0xe8, 0xd3, 0xd4, 0xc8, + 0xe7, 0x9a, 0xcc, 0x3c, 0xc2, 0xdf, 0x0c, 0x42, 0xe8, 0xae, 0xc7, 0xd8, + 0x1f, 0x66, 0x0a, 0x57, 0x09, 0x14, 0x02, 0x74, 0x9a, 0x7a, 0x07, 0xb3, + 0x19, 0x87, 0x8d, 0xa9, 0x45, 0x25, 0x26, 0x48, 0xb3, 0x20, 0x3c, 0xf7, + 0x5a, 0x1c, 0xae, 0xc7, 0x06, 0x9e, 0x1a, 0x0a, 0x23, 0xf3, 0x39, 0x25, + 0x2c, 0x91, 0x7c, 0x5e, 0x87, 0xe7, 0x55, 0xc4, 0x69, 0xf3, 0x3e, 0xeb, + 0xc5, 0x44, 0xa8, 0xe3, 0xec, 0xc1, 0xfe, 0x70, 0xbf, 0xdd, 0xbb, 0xf0, + 0x22, 0xe1, 0x19, 0xa1, 0x6d, 0x7a, 0x9a, 0xa3, 0x36, 0x90, 0xbc, 0x1a, + 0xa7, 0x37, 0xf8, 0xcf, 0xdc, 0x9e, 0x23, 0x17, 0x42, 0xd5, 0xa0, 0xd3, + 0x36, 0xb0, 0xb1, 0xf5, 0x1a, 0x95, 0xbc, 0xe8, 0x0f, 0xb4, 0x58, 0x76, + 0x40, 0x74, 0xd0, 0x21, 0xaf, 0xae, 0xc6, 0xb4, 0x84, 0xd7, 0xfc, 0x70, + 0x6a, 0x8f, 0x41, 0x57, 0x2b, 0x8e, 0xbc, 0x6b, 0x21, 0x65, 0xcc, 0xa0, + 0x8e, 0xb9, 0x0b, 0x46, 0xef, 0xb3, 0x56, 0xec, 0x8a, 0xd6, 0x4d, 0xdd, + 0x97, 0xbd, 0xdd, 0x65, 0xbf, 0x26, 0xab, 0xba, 0x0d, 0xd1, 0x22, 0x7e, + 0xb6, 0x8a, 0xb4, 0x92, 0xc9, 0xa6, 0x48, 0xd4, 0x64, 0x17, 0xc6, 0xb5, + 0xb9, 0xce, 0x45, 0x6d, 0xf4, 0xd9, 0x3d, 0xa0, 0xb3, 0x86, 0x67, 0x19, + 0xad, 0xd8, 0x32, 0x2b, 0xf7, 0xab, 0x90, 0xee, 0x91, 0x8f, 0x73, 0xe4, + 0xc0, 0x29, 0xde, 0x45, 0x8a, 0xfb, 0xca, 0x74, 0x3b, 0x50, 0xf1, 0x34, + 0x40, 0x36, 0x25, 0x8a, 0xe0, 0xf9, 0x7f, 0x55, 0xc5, 0x59, 0x89, 0xbb, + 0x43, 0x03, 0xa3, 0xdd, 0x8c, 0x83, 0x03, 0xc6, 0xef, 0x60, 0x02, 0xc5, + 0xd8, 0x29, 0x3f, 0x2f, 0x56, 0xba, 0x8b, 0x97, 0x0a, 0xc4, 0xf3, 0x07, + 0x3f, 0xca, 0x0f, 0xdf, 0xb9, 0x5d, 0x59, 0x42, 0x36, 0x02, 0xf7, 0x0f, + 0x03, 0xc8, 0xf2, 0xb7, 0xd8, 0x64, 0xcd, 0x1e, 0xe4, 0xe1, 0xa0, 0xbd, + 0x0f, 0x70, 0xfb, 0xcf, 0x77, 0x77, 0xef, 0x9d, 0xdd, 0xc1, 0x61, 0xab, + 0x3c, 0xdb, 0xe4, 0x35, 0x11, 0xab, 0xde, 0x40, 0x7d, 0x51, 0xba, 0xb1, + 0x7d, 0x13, 0xf1, 0x58, 0x03, 0xca, 0xae, 0x12, 0x4a, 0xa3, 0xb6, 0xed, + 0xd7, 0x18, 0x1c, 0xb6, 0xd8, 0x69, 0x63, 0x68, 0x61, 0x74, 0x64, 0x6b, + 0x75, 0x89, 0x70, 0x02, 0x23, 0x00, 0x07, 0x07, 0x09, 0x34, 0x00, 0x09, + 0x09, 0x09, 0x34, 0x34, 0x08, 0x01, 0x02, 0x02, 0x08, 0x08, 0x08, 0x08, + 0x09, 0x08, 0x08, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x09, 0x91, + 0x62, 0x29, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x4b, 0xa2, 0xb8, 0x84, 0x41, + 0xb7, 0x59, 0x5c, 0x4b, 0xa2, 0xb8, 0x84, 0x37, 0xee, 0x5a, 0x85, 0xe1, + 0xcb, 0xdd, 0xc8, 0xce, 0x07, 0x77, 0xee, 0x01, 0x3f, 0x96, 0x7b, 0x33, + 0x30, 0x3a, 0xcd, 0x64, 0x14, 0x5e, 0x86, 0xb3, 0x7b, 0x2d, 0x6c, 0xa9, + 0xc0, 0xcf, 0xd8, 0x43, 0x7e, 0x59, 0x45, 0xac, 0xff, 0x92, 0x4b, 0xda, + 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, + 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0x2a, 0x04, 0x00, 0x04, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0xfa, 0x4b, 0x92, 0xea, 0x4b, 0xef, 0xde, 0x03, 0xd5, 0xe2, 0xee, 0xe5, + 0x67, 0xd4, 0x99, 0x63, 0x37, 0x68, 0x91, 0xbc, 0x4f, 0xbc, 0x41, 0xe9, + 0x01, 0xc5, 0x4d, 0x59, 0x2a, 0x9b, 0x42, 0x60, 0x07, 0x7e, 0xc2, 0xbc, + 0x62, 0xcc, 0xbc, 0xa7, 0xf1, 0xe4, 0x20, 0x5f, 0xe3, 0xe8, 0x9f, 0x16, + 0x7a, 0x77, 0xd2, 0xb7, 0xad, 0x98, 0xc3, 0xb4, 0x99, 0xdb, 0x36, 0x1a, + 0xe4, 0xf0, 0xfc, 0xe1, 0xc8, 0x2f, 0x8c, 0xcf, 0x6f, 0x97, 0x48, 0x09, + 0x4a, 0xae, 0xc7, 0xf9, 0xfb, 0xb7, 0x5f, 0x64, 0x6a, 0x79, 0xa1, 0x27, + 0xeb, 0x59, 0x7d, 0x0a, 0xd3, 0x56, 0x27, 0x1d, 0x56, 0xd3, 0x62, 0x1e, + 0x7f, 0xb5, 0x0f, 0x50, 0x9c, 0x4d, 0x1d, 0xd5, 0x53, 0xcb, 0x08, 0x07, + 0x56, 0x93, 0x9e, 0x4f, 0xb2, 0xd0, 0x12, 0xc7, 0x50, 0xcf, 0x99, 0xac, + 0x24, 0xdb, 0x94, 0xab, 0x08, 0x89, 0x60, 0x2f, 0x6c, 0xd0, 0xc2, 0x2e, + 0x6d, 0x08, 0xe0, 0xf9, 0xfc, 0x7e, 0x5b, 0x54, 0x92, 0xaa, 0x01, 0xfd, + 0xf6, 0x49, 0xb1, 0xfc, 0xd4, 0x51, 0x83, 0x73, 0xaf, 0xac, 0x38, 0x78, + 0x8e, 0x9b, 0x42, 0x4e, 0x83, 0xbb, 0x9d, 0xd7, 0x5c, 0xdb, 0x73, 0xd3, + 0x3d, 0x2c, 0xe2, 0x4c, 0x57, 0xa4, 0xfa, 0xdf, 0x53, 0x44, 0x29, 0x71, + 0x22, 0xb6, 0x89, 0x84, 0x80, 0xca, 0xcb, 0x7c, 0x5f, 0x15, 0x19, 0x4b, + 0x06, 0x28, 0x5d, 0x4a, 0x9b, 0xc8, 0x59, 0xa7, 0x9e, 0xa2, 0xba, 0x32, + 0x5d, 0xf2, 0xcb, 0xa9, 0xc6, 0xba, 0x09, 0xee, 0xd2, 0x00, 0x32, 0x53, + 0x8b, 0x39, 0xff, 0xc4, 0x63, 0xac, 0xbc, 0x1c, 0x15, 0xb8, 0x79, 0xc2, + 0xe3, 0xda, 0x8d, 0xb2, 0x95, 0x8d, 0x3c, 0x10, 0xec, 0x93, 0x03, 0xc1, + 0x07, 0x84, 0x47, 0xf3, 0xeb, 0xe3, 0x10, 0x33, 0xa1, 0x2e, 0xc6, 0x48, + 0x44, 0x2c, 0x38, 0x36, 0xe1, 0x68, 0x3c, 0xe8, 0x0d, 0x5c, 0x8a, 0xdc, + 0x1f, 0xe8, 0x3b, 0xb2, 0x0f, 0xea, 0x27, 0x18, 0x7a, 0x7f, 0x82, 0x6a, + 0x96, 0xfa, 0x63, 0xd3, 0x5c, 0xbf, 0xf6, 0x1d, 0x9e, 0xf2, 0xd9, 0x83, + 0x3b, 0xf0, 0x1b, 0x29, 0x49, 0x8d, 0xb3, 0xdc, 0x60, 0x47, 0x9d, 0x2b, + 0xac, 0xd6, 0x6e, 0x59, 0xb3, 0x09, 0x0d, 0xa7, 0xfb, 0x0e, 0x43, 0x56, + 0xa3, 0x80, 0x2c, 0x9f, 0xc1, 0xe8, 0xd2, 0xef, 0x05, 0xc5, 0x25, 0x4c, + 0x5b, 0x67, 0x1a, 0x54, 0x0b, 0x55, 0x83, 0x3d, 0xfb, 0x38, 0x0e, 0xd2, + 0xc0, 0x1a, 0xcd, 0x9f, 0x81, 0x3e, 0x6d, 0x7f, 0xe4, 0x3f, 0x34, 0x0c, + 0xdc, 0x99, 0x5a, 0x77, 0xd4, 0xe4, 0xff, 0x4a, 0x7b, 0x8a, 0x95, 0xe4, + 0x46, 0x3d, 0x7b, 0xc4, 0x0e, 0xdd, 0xc7, 0x2d, 0xf4, 0xfa, 0x5e, 0x50, + 0xae, 0x9c, 0xca, 0x64, 0x97, 0xad, 0x03, 0x30, 0x3e, 0x05, 0xc4, 0x33, + 0x1e, 0x2c, 0x03, 0x2b, 0x06, 0x2c, 0x79, 0x13, 0xae, 0x1b, 0x65, 0xf1, + 0x1f, 0xb9, 0xe4, 0x8a, 0x06, 0x96, 0xea, 0xc4, 0x6e, 0x17, 0x19, 0x03, + 0x54, 0xe8, 0x39, 0xe7, 0xeb, 0x7b, 0xbc, 0x25, 0xd6, 0x55, 0x6c, 0x76, + 0x5f, 0xf7, 0xd2, 0x0e, 0x54, 0x46, 0x9f, 0x5d, 0xa4, 0x3d, 0xac, 0xa1, + 0x19, 0x7b, 0x7c, 0x5a, 0x44, 0x54, 0x65, 0x5d, 0x43, 0x26, 0x5f, 0x47, + 0x63, 0x2b, 0x00, 0xe3, 0xb4, 0xe9, 0x70, 0x8c, 0x31, 0x50, 0x7c, 0x37, + 0x01, 0x43, 0x6c, 0x29, 0xc3, 0xae, 0x59, 0xb7, 0x0b, 0xb9, 0x9a, 0x72, + 0x69, 0xe0, 0xd1, 0xb0, 0x47, 0x53, 0xf0, 0xb8, 0x8b, 0xc8, 0x80, 0x3c, + 0x58, 0xfa, 0x34, 0xf2, 0x44, 0x27, 0xb7, 0xfc, 0x44, 0x73, 0xfb, 0xe5, + 0xe1, 0x8b, 0xdb, 0x2b, 0xc5, 0x73, 0x97, 0x25, 0xb3, 0xef, 0x16, 0xfd, + 0xba, 0x08, 0x3d, 0x15, 0x2a, 0x03, 0xb5, 0x4d, 0x2a, 0x8c, 0xf5, 0x53, + 0x11, 0x97, 0x3c, 0x35, 0x66, 0x1d, 0x59, 0xc8, 0xc9, 0x79, 0x48, 0x6d, + 0x19, 0x4f, 0xa7, 0x07, 0x25, 0x4d, 0xb2, 0xfc, 0x1e, 0xbc, 0x9a, 0x0c, + 0x6e, 0x46, 0x2b, 0x58, 0x45, 0xbe, 0xe7, 0x8e, 0x09, 0xa5, 0xa0, 0xd3, + 0x5a, 0xf5, 0x6e, 0x92, 0x7b, 0x5b, 0x21, 0x07, 0xab, 0xf3, 0x57, 0xd6, + 0x93, 0x4b, 0x56, 0x3b, 0x9c, 0x3c, 0x4b, 0x85, 0xb0, 0x62, 0x18, 0x3e, + 0x7c, 0xc5, 0x25, 0xe2, 0xf2, 0xfc, 0xa3, 0xca, 0x88, 0xd6, 0xb2, 0x01, + 0x11, 0xcd, 0x93, 0x9a, 0x76, 0x84, 0xc2, 0x2d, 0x07, 0xd3, 0xbb, 0xac, + 0x99, 0xde, 0x29, 0x00, 0xf7, 0x3d, 0x06, 0xea, 0xdc, 0x88, 0xfd, 0xc6, + 0x6e, 0xf5, 0x55, 0x64, 0x73, 0x4e, 0x3b, 0xa9, 0x24, 0x44, 0x63, 0x1c, + 0x50, 0x29, 0x66, 0xc4, 0x74, 0x70, 0xcb, 0xd8, 0x57, 0x0c, 0x60, 0x50, + 0x6d, 0x64, 0x64, 0xd1, 0x53, 0xef, 0x62, 0xef, 0x61, 0xf4, 0xe2, 0xfe, + 0x4c, 0xaa, 0x9f, 0xe9, 0x81, 0x01, 0xe1, 0x97, 0xaa, 0xc0, 0x06, 0xbf, + 0x40, 0x19, 0x64, 0x24, 0x6e, 0x80, 0x73, 0x00, 0x5c, 0x86, 0x3e, 0xc2, + 0xcf, 0x8c, 0x09, 0xc0, 0xfa, 0x4a, 0xb3, 0x3a, 0x0d, 0x81, 0x1d, 0x49, + 0x58, 0x09, 0xe8, 0x31, 0x0e, 0xd7, 0x60, 0x8d, 0x9d, 0xfe, 0x9f, 0x35, + 0xf7, 0x8d, 0xa1, 0x12, 0x04, 0xb2, 0x47, 0xac, 0x31, 0x92, 0x03, 0x0a, + 0x10, 0x50, 0xb7, 0x86, 0x3d, 0xcd, 0x15, 0x8f, 0x25, 0x93, 0x24, 0x7a, + 0x5f, 0xa0, 0x3c, 0x41, 0xaa, 0xb2, 0x96, 0xce, 0xd3, 0x0c, 0xe9, 0x55, + 0x66, 0x37, 0x5c, 0xf3, 0x02, 0x3c, 0xa1, 0x09, 0xa4, 0x9e, 0x90, 0xc9, + 0x82, 0xab, 0xd4, 0x04, 0x2e, 0x8b, 0xb4, 0x8d, 0x5b, 0xcc, 0x19, 0x5a, + 0xfe, 0x86, 0x9c, 0x6c, 0x56, 0x09, 0x86, 0x36, 0xef, 0xe8, 0x1f, 0x3a, + 0xbc, 0xda, 0x4c, 0x68, 0xac, 0xa2, 0x1b, 0xd1, 0x23, 0x75, 0x28, 0xed, + 0x9f, 0x84, 0x2e, 0x40, 0x57, 0x5f, 0x0a, 0x85, 0xe4, 0x77, 0x59, 0x53, + 0x12, 0x32, 0xd6, 0x3c, 0x1b, 0xaf, 0x95, 0xa1, 0x1c, 0x14, 0x1a, 0x42, + 0x7d, 0xc7, 0x7b, 0x21, 0xd1, 0x4e, 0xb9, 0x29, 0x85, 0xef, 0xa2, 0x61, + 0x1c, 0xe5, 0x16, 0x44, 0xbe, 0xfb, 0xa3, 0x21, 0x4f, 0x94, 0x70, 0xff, + 0x5c, 0xc2, 0x1d, 0x0b, 0x39, 0x36, 0x84, 0x0e, 0x61, 0xe2, 0x1c, 0x63, + 0x74, 0xe0, 0x30, 0x01, 0xbe, 0x39, 0x0f, 0x6f, 0xe6, 0x29, 0xad, 0xd8, + 0x8c, 0xdd, 0x8b, 0x24, 0x38, 0x6f, 0x67, 0x8a, 0x2d, 0x82, 0x1e, 0x8e, + 0x45, 0xcb, 0xec, 0x2d, 0xe3, 0xb4, 0x03, 0x8e, 0x46, 0x2e, 0x01, 0xb0, + 0xca, 0x4f, 0xe0, 0x2c, 0x52, 0xd3, 0x4c, 0xdd, 0xd6, 0x62, 0xf3, 0x38, + 0x3f, 0x3c, 0xc1, 0x58, 0xaa, 0x87, 0x3d, 0x4f, 0xb2, 0xb1, 0x54, 0x65, + 0xdc, 0x1c, 0xc8, 0x16, 0x88, 0x15, 0x53, 0xb0, 0x4e, 0x77, 0xae, 0xe0, + 0x34, 0x18, 0x36, 0x34, 0x31, 0x74, 0x4c, 0x79, 0x0f, 0x2b, 0x1a, 0x11, + 0x06, 0x06, 0xaa, 0x60, 0x31, 0x6e, 0x65, 0x9e, 0x1b, 0xb0, 0x61, 0xd6, + 0x90, 0xd1, 0x1d, 0x4c, 0x36, 0xfe, 0xec, 0x26, 0xcc, 0xba, 0xce, 0xd7, + 0xe7, 0x0c, 0x53, 0x90, 0xe8, 0xce, 0xce, 0xed, 0x58, 0x37, 0x37, 0x3f, + 0x40, 0x39, 0xeb, 0x8c, 0xfb, 0x7d, 0x93, 0xa2, 0x26, 0x4e, 0xbf, 0x49, + 0xe7, 0x95, 0xc0, 0x12, 0x6a, 0xec, 0xfb, 0xbe, 0x00, 0x62, 0xb9, 0xc9, + 0x0d, 0x5a, 0x37, 0xf9, 0xae, 0x84, 0x95, 0x89, 0x20, 0x47, 0x48, 0xf6, + 0xf8, 0x73, 0x92, 0x5f, 0xe1, 0x4a, 0xb4, 0x9e, 0xd8, 0x75, 0xf3, 0x38, + 0x48, 0xe1, 0x29, 0x95, 0x0d, 0x74, 0x6b, 0x98, 0x96, 0x6e, 0xc9, 0x3f, + 0xfc, 0x44, 0x91, 0x4d, 0xf4, 0x4c, 0xb7, 0x38, 0xd7, 0xec, 0xbf, 0xf6, + 0x78, 0x05, 0x7d, 0x1b, 0xe5, 0x68, 0x8a, 0xbc, 0x6a, 0x6a, 0x29, 0xb6, + 0xc6, 0x9a, 0x8d, 0x7a, 0x0e, 0x00, 0x80, 0x73, 0xf5, 0x88, 0x5d, 0x2a, + 0xa2, 0x60, 0x98, 0x1e, 0xf5, 0x06, 0x3b, 0xef, 0xa9, 0x46, 0x6b, 0x89, + 0x24, 0xb0, 0xf4, 0x34, 0x42, 0x15, 0x87, 0xd3, 0xc9, 0x36, 0xe0, 0x52, + 0x5f, 0x57, 0x8e, 0x65, 0x5c, 0x7f, 0x7c, 0xf2, 0x66, 0xd8, 0xd1, 0xbf, + 0x13, 0x95, 0x65, 0xb0, 0x7a, 0xa0, 0xbb, 0xee, 0xc9, 0x20, 0xff, 0x26, + 0xda, 0xa0, 0x61, 0x65, 0xd5, 0x3c, 0xdf, 0xb5, 0xf0, 0xd2, 0x02, 0x4f, + 0x97, 0x65, 0x48, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, + 0x2e, 0x61, 0x70, 0x73, 0x64, 0x64, 0x6b, 0x75, 0x8a, 0x11, 0x01, 0x23, + 0x00, 0x07, 0x07, 0x09, 0x34, 0x00, 0x09, 0x09, 0x09, 0x34, 0x34, 0x08, + 0x01, 0x02, 0x02, 0x08, 0x08, 0x08, 0x08, 0x09, 0x08, 0x08, 0x09, 0x09, + 0x09, 0x08, 0x08, 0x08, 0x08, 0x09, 0x92, 0x1a, 0x33, 0x13, 0x41, 0xb7, + 0x59, 0x5c, 0x4b, 0x89, 0xf6, 0xba, 0x41, 0xb7, 0x59, 0x5c, 0x4b, 0x89, + 0xf6, 0xba, 0xb1, 0x0a, 0x33, 0x78, 0x48, 0x21, 0xea, 0x97, 0x6e, 0xb7, + 0xc7, 0x2e, 0xdb, 0x0f, 0x9b, 0x01, 0xd0, 0x22, 0x6d, 0xbb, 0x64, 0x14, + 0x5e, 0x86, 0xb3, 0x7b, 0x2d, 0x6c, 0xa9, 0xc0, 0xcf, 0xd8, 0x43, 0x7e, + 0x59, 0x45, 0xac, 0xff, 0x92, 0x4b, 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, + 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, + 0x07, 0x09, 0x2a, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, + 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x12, 0x83, 0x28, 0x8c, 0xcd, + 0x78, 0x8c, 0x1b, 0x02, 0xa2, 0x38, 0xa7, 0x25, 0xc1, 0x25, 0x59, 0xcd, + 0x36, 0xb2, 0x21, 0xa1, 0x91, 0xd0, 0xc3, 0x54, 0x89, 0x64, 0xa8, 0x3d, + 0x07, 0xcb, 0x8f, 0xf7, 0xa6, 0x55, 0xc2, 0x96, 0xf6, 0x35, 0xc1, 0x67, + 0xdf, 0x2f, 0x1f, 0xda, 0xa8, 0xf8, 0x8c, 0xc9, 0xa7, 0x5e, 0x7f, 0x1f, + 0xa8, 0xd3, 0x38, 0x57, 0xa2, 0xf4, 0x57, 0x32, 0x17, 0xe3, 0x06, 0xe3, + 0xb6, 0x56, 0x60, 0x6e, 0xbe, 0x12, 0x60, 0x00, 0xfd, 0xa8, 0x4c, 0x3f, + 0x2b, 0x54, 0x9c, 0xfb, 0x87, 0x8b, 0xfa, 0x9e, 0xb8, 0xb2, 0x80, 0x36, + 0xf1, 0x5b, 0xcd, 0x9d, 0x74, 0xa1, 0x7b, 0xbf, 0xf6, 0x4c, 0x64, 0x58, + 0x67, 0x8b, 0x68, 0x05, 0x15, 0x7e, 0x4b, 0x54, 0xe9, 0x84, 0x59, 0x70, + 0x42, 0x80, 0x67, 0x6c, 0x45, 0x62, 0x12, 0x03, 0x27, 0x2b, 0x32, 0xdc, + 0x78, 0x85, 0x3d, 0x74, 0x28, 0x89, 0x5c, 0x33, 0x15, 0x79, 0x63, 0x1f, + 0xd7, 0x26, 0xbf, 0x5d, 0xf6, 0xb1, 0xb7, 0x9e, 0x37, 0x86, 0xd8, 0xf6, + 0xf9, 0xc3, 0x66, 0x90, 0x50, 0x5a, 0x0e, 0xeb, 0xcc, 0xe0, 0xf2, 0x19, + 0xbb, 0xd7, 0x6a, 0xe4, 0xea, 0x87, 0xf9, 0x17, 0x20, 0x88, 0xf6, 0xc0, + 0xc7, 0xb7, 0x55, 0x25, 0xef, 0x15, 0xec, 0xc5, 0x80, 0x52, 0x9a, 0x92, + 0xdb, 0x32, 0xf3, 0xc2, 0xa2, 0x55, 0xd6, 0xd9, 0x5b, 0xe6, 0xb1, 0x95, + 0x18, 0x2b, 0xf8, 0x94, 0x21, 0x56, 0x29, 0x30, 0xf3, 0x61, 0x39, 0x22, + 0x03, 0x86, 0xce, 0x81, 0x6d, 0x9e, 0xdb, 0x5b, 0x49, 0xdb, 0x2c, 0x1d, + 0x0d, 0x45, 0xa9, 0xb3, 0x1c, 0x1a, 0x43, 0x36, 0x1d, 0xd2, 0x76, 0x28, + 0x27, 0xe0, 0xd3, 0x19, 0x56, 0xd3, 0x52, 0xb2, 0xa0, 0x9c, 0xda, 0xb7, + 0xac, 0x4d, 0xb1, 0x98, 0x22, 0xa5, 0x86, 0x5d, 0x79, 0x6a, 0x69, 0x06, + 0xd7, 0x07, 0xe7, 0x44, 0x55, 0x6c, 0xc7, 0xd0, 0x8a, 0x2b, 0xa1, 0x45, + 0xc6, 0xbf, 0xf3, 0x21, 0x2e, 0x41, 0x5c, 0x84, 0xa2, 0x77, 0x46, 0x65, + 0x80, 0x75, 0xba, 0x49, 0xd6, 0xd7, 0x73, 0xeb, 0x35, 0x2c, 0x46, 0x58, + 0xc4, 0x1d, 0x2f, 0x6b, 0xe6, 0x6c, 0xa7, 0x5f, 0x95, 0x0c, 0xbc, 0x60, + 0x00, 0x3d, 0xa9, 0x0a, 0xd6, 0x0a, 0x66, 0x59, 0xc0, 0x9b, 0x49, 0x5b, + 0x4c, 0x73, 0xf5, 0x9e, 0x6d, 0x38, 0xdd, 0x0f, 0x25, 0xe4, 0x35, 0x84, + 0x34, 0x25, 0xfe, 0x71, 0x35, 0x78, 0xa7, 0x5b, 0xc1, 0x7a, 0xab, 0xd7, + 0xeb, 0x2f, 0x54, 0x93, 0x94, 0x49, 0x8a, 0x1e, 0x04, 0xe6, 0xfc, 0xd7, + 0xe3, 0xa2, 0x41, 0x25, 0x5a, 0xa5, 0x46, 0x59, 0x85, 0xfb, 0x21, 0xc7, + 0x02, 0x48, 0x79, 0xd4, 0xef, 0xc4, 0x03, 0xc2, 0x0a, 0x4b, 0x42, 0x1c, + 0x73, 0x35, 0xcd, 0x21, 0x8b, 0xd5, 0xfc, 0xa3, 0xdc, 0xbb, 0x4b, 0xa3, + 0x45, 0x04, 0x73, 0xa1, 0xdb, 0x3a, 0x97, 0x0e, 0xc7, 0x1c, 0xe2, 0x67, + 0x04, 0xd4, 0x49, 0x68, 0x0e, 0x05, 0xcb, 0x52, 0xd4, 0x37, 0x75, 0xd8, + 0x2a, 0x17, 0xd3, 0x7a, 0x93, 0x96, 0x46, 0xfb, 0x07, 0x6d, 0x3b, 0x92, + 0x60, 0xf4, 0x35, 0x94, 0x3b, 0xbd, 0x2e, 0xf6, 0x0b, 0x18, 0xd5, 0x0d, + 0x1b, 0xe1, 0xd3, 0x14, 0xc1, 0x84, 0xd7, 0x67, 0xd7, 0x96, 0x2d, 0xa9, + 0xab, 0x59, 0x70, 0x43, 0x7b, 0xea, 0x25, 0xa3, 0x05, 0x1c, 0x45, 0xf6, + 0x34, 0x51, 0x8e, 0xaf, 0x46, 0x33, 0x90, 0x68, 0x28, 0x4f, 0x38, 0x5b, + 0xbb, 0x69, 0xee, 0xbb, 0x0a, 0x4c, 0x76, 0x1c, 0x3d, 0xfd, 0xea, 0x1f, + 0x77, 0x9e, 0xd4, 0xa1, 0xeb, 0x74, 0x16, 0x60, 0x20, 0xe9, 0x44, 0xc1, + 0x90, 0x2c, 0x7b, 0x77, 0x6f, 0x70, 0xe3, 0x62, 0x0f, 0xc3, 0x20, 0xf6, + 0xce, 0xc3, 0xa6, 0x0e, 0x9c, 0x6d, 0xa3, 0xa0, 0x21, 0x1c, 0x28, 0x7f, + 0x44, 0xd7, 0xa9, 0x87, 0x62, 0x91, 0x4d, 0x2a, 0x93, 0xe2, 0xc7, 0x94, + 0x0c, 0x75, 0x1d, 0xf6, 0xc7, 0xf8, 0x36, 0x09, 0xa8, 0x23, 0xa3, 0x80, + 0x52, 0x2d, 0xe7, 0x0b, 0x44, 0x5d, 0x4b, 0xf5, 0xdc, 0x57, 0xa3, 0x02, + 0x40, 0x89, 0xdc, 0x40, 0xf7, 0x5c, 0xad, 0xea, 0x5c, 0x1a, 0x59, 0xfc, + 0xb8, 0xaf, 0xcb, 0x71, 0xe0, 0x08, 0xdc, 0x80, 0x08, 0x8a, 0x32, 0x85, + 0x46, 0xa9, 0x9a, 0x17, 0x6b, 0x25, 0x9c, 0xfe, 0x7d, 0x90, 0x22, 0x6e, + 0x7b, 0x01, 0x24, 0x17, 0xf6, 0xa7, 0x70, 0x93, 0x03, 0x60, 0xc2, 0x0d, + 0x7b, 0x3b, 0xe8, 0x5b, 0x02, 0xb0, 0x6d, 0x00, 0x62, 0x97, 0x1b, 0x84, + 0x86, 0x27, 0x72, 0x2d, 0x90, 0xee, 0xdc, 0xb6, 0xb8, 0xa5, 0x58, 0x73, + 0x29, 0x9b, 0x06, 0x99, 0xda, 0x4f, 0x12, 0x0c, 0x74, 0x0a, 0xc1, 0x1b, + 0x34, 0x20, 0xfa, 0x6d, 0x01, 0xd2, 0x1b, 0xf2, 0x0f, 0xe3, 0xfe, 0x34, + 0x2d, 0x44, 0x4f, 0xa3, 0x6a, 0xab, 0xaa, 0x7e, 0x1c, 0x35, 0xef, 0xfe, + 0xa0, 0xc1, 0x8a, 0xeb, 0x77, 0x80, 0xd6, 0x57, 0x20, 0x2e, 0x2b, 0xeb, + 0x67, 0xa0, 0x82, 0x86, 0xc8, 0x0e, 0x70, 0x76, 0x74, 0x52, 0x3e, 0x67, + 0x96, 0xf0, 0x48, 0x3f, 0x9b, 0xdc, 0x5f, 0x36, 0xd9, 0xae, 0x3a, 0xcb, + 0x57, 0x5d, 0xe0, 0x7c, 0x03, 0xa9, 0xe8, 0x88, 0x13, 0x6a, 0x70, 0x94, + 0x4b, 0xf5, 0x92, 0x8f, 0xc0, 0x34, 0x49, 0x3f, 0xf7, 0xe1, 0x59, 0xc4, + 0xf2, 0xae, 0x7a, 0x88, 0x58, 0x39, 0x74, 0x39, 0x6d, 0xaf, 0x7a, 0xec, + 0xaf, 0x44, 0x0e, 0x11, 0x7d, 0xa8, 0x3c, 0x50, 0x5b, 0x64, 0x8d, 0x8a, + 0x21, 0x59, 0xc6, 0x8c, 0x6c, 0xce, 0x05, 0xad, 0x1c, 0x2f, 0x5e, 0x4a, + 0xa3, 0x2a, 0x46, 0x3a, 0xaa, 0x12, 0x7e, 0xcc, 0x82, 0xb6, 0x62, 0xba, + 0xe6, 0x1a, 0x52, 0xc6, 0xe3, 0x96, 0x71, 0xf6, 0x81, 0x21, 0x46, 0xd0, + 0x3f, 0x5d, 0xa1, 0x37, 0x8b, 0xf5, 0xc7, 0x8c, 0x28, 0xf0, 0x2e, 0xe8, + 0x44, 0x25, 0x48, 0x27, 0x8e, 0x2f, 0x65, 0x83, 0xed, 0xf5, 0xb6, 0x9f, + 0x02, 0xa7, 0x1b, 0x1e, 0x90, 0x01, 0x55, 0x88, 0xe5, 0xdf, 0x0e, 0x7e, + 0x16, 0x66, 0xa1, 0xc6, 0x07, 0xf6, 0xb5, 0x84, 0x8d, 0x60, 0x6b, 0xe2, + 0xad, 0xbd, 0x18, 0x39, 0xe5, 0xd2, 0xd9, 0xe0, 0xab, 0xc2, 0xac, 0x2f, + 0x36, 0x24, 0x03, 0x69, 0x4c, 0xf9, 0xf3, 0x67, 0x8f, 0xf6, 0x8b, 0xde, + 0xf9, 0x7c, 0x14, 0xfa, 0x97, 0xc3, 0xe5, 0xc1, 0x7d, 0xcf, 0x16, 0x24, + 0x26, 0xda, 0xde, 0x5c, 0x70, 0x96, 0x90, 0xd9, 0x06, 0x2f, 0xf9, 0x61, + 0xa3, 0x47, 0x19, 0x50, 0x5e, 0xe2, 0xb6, 0x74, 0x5e, 0x55, 0xe6, 0x89, + 0xaa, 0xde, 0x19, 0x27, 0x26, 0x47, 0x95, 0x7b, 0xf0, 0x09, 0x21, 0xa9, + 0xf3, 0xf2, 0xf0, 0xbc, 0x1a, 0xa2, 0x25, 0x77, 0x3f, 0x8a, 0x57, 0x20, + 0xfc, 0x48, 0x45, 0xd8, 0x8b, 0xcb, 0x33, 0x04, 0x10, 0x1d, 0xc6, 0x4b, + 0x4c, 0xe4, 0x92, 0x1f, 0xef, 0x27, 0x5e, 0xd5, 0xac, 0xab, 0xcc, 0x69, + 0xbe, 0xd6, 0x35, 0x0e, 0x0d, 0x96, 0x99, 0x3b, 0x67, 0x8d, 0x33, 0xa0, + 0xe3, 0x16, 0xcc, 0x4a, 0x29, 0x80, 0xc8, 0x47, 0xd1, 0x0c, 0xb1, 0xa0, + 0xc1, 0xbe, 0xcc, 0x16, 0xab, 0xf7, 0xee, 0x8a, 0x77, 0xef, 0xca, 0x08, + 0x82, 0x0a, 0x9e, 0x11, 0xcf, 0x3c, 0xbb, 0x1b, 0x44, 0x96, 0xd1, 0x5e, + 0x65, 0xf9, 0xe7, 0xc7, 0xa1, 0x94, 0x42, 0xa9, 0x0e, 0x36, 0x9a, 0x5b, + 0x7f, 0xf0, 0x91, 0x95, 0xeb, 0xd1, 0xb6, 0x1d, 0x18, 0x44, 0x93, 0xa4, + 0xc1, 0x31, 0x97, 0x07, 0x09, 0x9b, 0x50, 0xae, 0xf3, 0x74, 0x7f, 0xbe, + 0x0d, 0xc2, 0xc3, 0x11, 0x8f, 0xa1, 0xea, 0x1f, 0x4e, 0x84, 0x94, 0x18, + 0x7e, 0x7c, 0xbd, 0xe6, 0xc9, 0x78, 0x0e, 0x39, 0x1e, 0x1a, 0x71, 0xc4, + 0xbc, 0x5c, 0x99, 0x76, 0xf7, 0x26, 0x66, 0x9c, 0x8f, 0xd4, 0xad, 0xa9, + 0x6e, 0x96, 0xb9, 0x54, 0x5b, 0xae, 0xa2, 0x0d, 0x94, 0xa8, 0x5a, 0x34, + 0xc3, 0xdb, 0x52, 0x59, 0x3f, 0xdd, 0x53, 0x72, 0xfc, 0xf6, 0x1d, 0x3c, + 0xe0, 0x1f, 0x4a, 0xee, 0xf5, 0x74, 0xa5, 0x95, 0x7a, 0x5d, 0x75, 0xbd, + 0x27, 0x4a, 0x49, 0x18, 0xcf, 0xf0, 0xe5, 0x32, 0x4f, 0x1b, 0xa0, 0xeb, + 0x00, 0x19, 0x21, 0xbd, 0xf7, 0xf5, 0x4b, 0x47, 0x1d, 0x3b, 0x8b, 0xe6, + 0xca, 0xdc, 0xb6, 0x52, 0x41, 0xa7, 0xab, 0x68, 0xb3, 0xfb, 0x8f, 0x40, + 0xc3, 0x59, 0xd9, 0x2d, 0x13, 0x3a, 0x99, 0x93, 0x9f, 0xa6, 0x90, 0xdd, + 0x65, 0x17, 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x2d, 0x69, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x00, 0x00, 0x00, 0x1d, 0x04, + 0x0a, 0x00, 0x00, 0x00, 0x06, 0x0e, 0x6a, 0x00, 0x0f, 0x2a, 0x0e, 0xaa, + 0x0f, 0x6a, 0x0f, 0xb3, 0x0e, 0xea, 0x0e, 0x6a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x0c, 0x09, 0x34, 0x34, 0x08, + 0x01, 0x02, 0x02, 0x08, 0x08, 0x17, 0x01, 0xfc, 0x9b, 0xff, 0x1a, 0xfd, + 0x18, 0x88, 0xb2, 0x23, 0xc4, 0x27, 0xcd, 0xff, 0x6d, 0xed, 0x99, 0xdb, + 0x40, 0x1d, 0x5c, 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, + 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0x2a, + 0x05, 0x00, 0x05, 0x00, 0x69, 0x63, 0x68, 0x61, 0x74, 0x06, 0x3f, 0x0c, + 0x08, 0x34, 0x34, 0x08, 0x01, 0x02, 0x02, 0x08, 0x08, 0x17, 0x01, 0xfc, + 0x9b, 0xff, 0x1a, 0xfd, 0x18, 0x88, 0xb2, 0x23, 0xc4, 0x27, 0xcd, 0xff, + 0x6d, 0xed, 0x99, 0xdb, 0x40, 0x1d, 0x5c, 0xda, 0x39, 0xa3, 0xee, 0x5e, + 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, + 0xd8, 0x07, 0x09, 0x2a, 0x05, 0x00, 0x05, 0x00, 0x69, 0x63, 0x68, 0x61, + 0x74, 0x05, 0x3f, 0x0c, 0x09, 0x34, 0x34, 0x08, 0x01, 0x02, 0x02, 0x08, + 0x08, 0x17, 0x01, 0x9b, 0x66, 0x83, 0xaf, 0x24, 0x40, 0x8e, 0xa7, 0xd6, + 0x76, 0x12, 0x4a, 0x40, 0x61, 0xb5, 0x6a, 0xbc, 0x33, 0xef, 0x01, 0xda, + 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, + 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0x2b, 0x01, 0x00, 0x01, 0x00, + 0x69, 0x63, 0x68, 0x61, 0x74, 0x04, 0x3f, 0x0c, 0x08, 0x34, 0x34, 0x08, + 0x01, 0x02, 0x02, 0x08, 0x08, 0x17, 0x01, 0x9b, 0x66, 0x83, 0xaf, 0x24, + 0x40, 0x8e, 0xa7, 0xd6, 0x76, 0x12, 0x4a, 0x40, 0x61, 0xb5, 0x6a, 0xbc, + 0x33, 0xef, 0x01, 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, + 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0x2b, + 0x01, 0x00, 0x01, 0x00, 0x69, 0x63, 0x68, 0x61, 0x74, 0x03, 0x48, 0x0c, + 0x09, 0x34, 0x34, 0x08, 0x01, 0x02, 0x02, 0x08, 0x08, 0x29, 0x01, 0x64, + 0x14, 0x5e, 0x86, 0xb3, 0x7b, 0x2d, 0x6c, 0xa9, 0xc0, 0xcf, 0xd8, 0x43, + 0x7e, 0x59, 0x45, 0xac, 0xff, 0x92, 0x4b, 0xda, 0x39, 0xa3, 0xee, 0x5e, + 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, + 0xd8, 0x07, 0x09, 0x2a, 0x04, 0x00, 0x04, 0x00, 0x63, 0x6f, 0x6d, 0x2e, + 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x73, 0x64, 0x02, 0x4c, + 0x0c, 0x09, 0x34, 0x34, 0x08, 0x01, 0x02, 0x02, 0x08, 0x08, 0x33, 0x09, + 0x64, 0x14, 0x5e, 0x86, 0xb3, 0x7b, 0x2d, 0x6c, 0xa9, 0xc0, 0xcf, 0xd8, + 0x43, 0x7e, 0x59, 0x45, 0xac, 0xff, 0x92, 0x4b, 0xda, 0x39, 0xa3, 0xee, + 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, + 0xaf, 0xd8, 0x07, 0x09, 0x2a, 0x04, 0x00, 0x04, 0x00, 0x6c, 0x6f, 0x63, + 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x2d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x69, 0x65, 0x73, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x0f, 0xfb, 0x00, + 0x0f, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 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, 0x01, 0x02, 0x01, 0x05, 0x0a, 0x00, 0x00, 0x00, + 0x02, 0x0f, 0xf7, 0x00, 0x0f, 0xfc, 0x0f, 0xf7, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x01, 0x02, 0x03, 0x03, 0x00, 0x09, + 0x0a, 0x00, 0x00, 0x00, 0x02, 0x0f, 0xcf, 0x00, 0x0f, 0xe8, 0x0f, 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, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x03, 0x34, 0x01, 0x7e, 0x0b, 0xaa, 0xec, 0xd2, + 0x3c, 0x92, 0x58, 0xd7, 0xfd, 0x92, 0x3c, 0xf8, 0x03, 0x3e, 0x70, 0x20, + 0x84, 0xa7, 0x17, 0x02, 0x17, 0x03, 0x34, 0x09, 0x7e, 0x0b, 0xaa, 0xec, + 0xd2, 0x3c, 0x92, 0x58, 0xd7, 0xfd, 0x92, 0x3c, 0xf8, 0x03, 0x3e, 0x70, + 0x20, 0x84, 0xa7, 0x17, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x0f, 0xcf, 0x00, + 0x0f, 0xe8, 0x0f, 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, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x03, 0x34, 0x01, 0xda, + 0xde, 0x08, 0x82, 0x7d, 0xfa, 0x5c, 0xf3, 0x42, 0xb1, 0x04, 0x84, 0xf4, + 0xba, 0xe3, 0x73, 0xe9, 0x35, 0x6f, 0xbb, 0x02, 0x17, 0x03, 0x34, 0x09, + 0xda, 0xde, 0x08, 0x82, 0x7d, 0xfa, 0x5c, 0xf3, 0x42, 0xb1, 0x04, 0x84, + 0xf4, 0xba, 0xe3, 0x73, 0xe9, 0x35, 0x6f, 0xbb, 0x0a, 0x00, 0x00, 0x00, + 0x02, 0x0f, 0xcf, 0x00, 0x0f, 0xe8, 0x0f, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x03, 0x34, 0x01, 0x64, 0x14, 0x5e, 0x86, 0xb3, 0x7b, 0x2d, 0x6c, 0xa9, + 0xc0, 0xcf, 0xd8, 0x43, 0x7e, 0x59, 0x45, 0xac, 0xff, 0x92, 0x4b, 0x02, + 0x17, 0x03, 0x34, 0x09, 0x64, 0x14, 0x5e, 0x86, 0xb3, 0x7b, 0x2d, 0x6c, + 0xa9, 0xc0, 0xcf, 0xd8, 0x43, 0x7e, 0x59, 0x45, 0xac, 0xff, 0x92, 0x4b, + 0x0a, 0x00, 0x00, 0x00, 0x06, 0x0f, 0xe3, 0x00, 0x0f, 0xf2, 0x0f, 0xe8, + 0x0f, 0xfc, 0x0f, 0xf7, 0x0f, 0xed, 0x0f, 0xe3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x09, 0x01, 0x06, 0x04, 0x03, 0x08, 0x01, 0x05, 0x04, 0x03, 0x09, + 0x01, 0x04, 0x04, 0x03, 0x08, 0x01, 0x03, 0x04, 0x03, 0x09, 0x01, 0x02, + 0x03, 0x03, 0x09, 0x09, 0x0a, 0x00, 0x00, 0x00, 0x06, 0x0f, 0x6b, 0x00, + 0x0f, 0xe8, 0x0f, 0xcf, 0x0f, 0xb6, 0x0f, 0x9d, 0x0f, 0x84, 0x0f, 0x6b, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x03, 0x34, 0x01, 0xfc, 0x9b, 0xff, 0x1a, 0xfd, + 0x18, 0x88, 0xb2, 0x23, 0xc4, 0x27, 0xcd, 0xff, 0x6d, 0xed, 0x99, 0xdb, + 0x40, 0x1d, 0x5c, 0x06, 0x18, 0x03, 0x34, 0x01, 0xfc, 0x9b, 0xff, 0x1a, + 0xfd, 0x18, 0x88, 0xb2, 0x23, 0xc4, 0x27, 0xcd, 0xff, 0x6d, 0xed, 0x99, + 0xdb, 0x40, 0x1d, 0x5c, 0x05, 0x18, 0x03, 0x34, 0x01, 0x9b, 0x66, 0x83, + 0xaf, 0x24, 0x40, 0x8e, 0xa7, 0xd6, 0x76, 0x12, 0x4a, 0x40, 0x61, 0xb5, + 0x6a, 0xbc, 0x33, 0xef, 0x01, 0x04, 0x18, 0x03, 0x34, 0x01, 0x9b, 0x66, + 0x83, 0xaf, 0x24, 0x40, 0x8e, 0xa7, 0xd6, 0x76, 0x12, 0x4a, 0x40, 0x61, + 0xb5, 0x6a, 0xbc, 0x33, 0xef, 0x01, 0x03, 0x18, 0x03, 0x34, 0x01, 0x64, + 0x14, 0x5e, 0x86, 0xb3, 0x7b, 0x2d, 0x6c, 0xa9, 0xc0, 0xcf, 0xd8, 0x43, + 0x7e, 0x59, 0x45, 0xac, 0xff, 0x92, 0x4b, 0x02, 0x17, 0x03, 0x34, 0x09, + 0x64, 0x14, 0x5e, 0x86, 0xb3, 0x7b, 0x2d, 0x6c, 0xa9, 0xc0, 0xcf, 0xd8, + 0x43, 0x7e, 0x59, 0x45, 0xac, 0xff, 0x92, 0x4b, 0x0a, 0x00, 0x00, 0x00, + 0x06, 0x0f, 0xe3, 0x00, 0x0f, 0xfc, 0x0f, 0xf7, 0x0f, 0xf2, 0x0f, 0xed, + 0x0f, 0xe8, 0x0f, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x08, 0x01, 0x06, + 0x04, 0x03, 0x08, 0x01, 0x05, 0x04, 0x03, 0x08, 0x01, 0x04, 0x04, 0x03, + 0x08, 0x01, 0x03, 0x04, 0x03, 0x08, 0x01, 0x02, 0x03, 0x03, 0x08, 0x09, + 0x0a, 0x00, 0x00, 0x00, 0x06, 0x0f, 0xe3, 0x00, 0x0f, 0xfc, 0x0f, 0xf7, + 0x0f, 0xf2, 0x0f, 0xed, 0x0f, 0xe8, 0x0f, 0xe3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x09, 0x01, 0x06, 0x04, 0x03, 0x09, 0x01, 0x05, 0x04, 0x03, 0x09, + 0x01, 0x04, 0x04, 0x03, 0x09, 0x01, 0x03, 0x04, 0x03, 0x09, 0x01, 0x02, + 0x03, 0x03, 0x09, 0x09, 0x0a, 0x00, 0x00, 0x00, 0x06, 0x0f, 0xe3, 0x00, + 0x0f, 0xfc, 0x0f, 0xf7, 0x0f, 0xf2, 0x0f, 0xed, 0x0f, 0xe8, 0x0f, 0xe3, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x09, 0x01, 0x06, 0x04, 0x03, 0x09, 0x01, + 0x05, 0x04, 0x03, 0x09, 0x01, 0x04, 0x04, 0x03, 0x09, 0x01, 0x03, 0x04, + 0x03, 0x09, 0x01, 0x02, 0x03, 0x03, 0x09, 0x09, 0x0a, 0x00, 0x00, 0x00, + 0x06, 0x0f, 0xe3, 0x00, 0x0f, 0xfc, 0x0f, 0xf7, 0x0f, 0xf2, 0x0f, 0xed, + 0x0f, 0xe8, 0x0f, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x09, 0x01, 0x06, + 0x04, 0x03, 0x09, 0x01, 0x05, 0x04, 0x03, 0x09, 0x01, 0x04, 0x04, 0x03, + 0x09, 0x01, 0x03, 0x04, 0x03, 0x09, 0x01, 0x02, 0x03, 0x03, 0x09, 0x09, + 0x0a, 0x00, 0x00, 0x00, 0x06, 0x0f, 0xe3, 0x00, 0x0f, 0xfc, 0x0f, 0xf7, + 0x0f, 0xf2, 0x0f, 0xed, 0x0f, 0xe8, 0x0f, 0xe3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x08, 0x01, 0x06, 0x04, 0x03, 0x08, 0x01, 0x05, 0x04, 0x03, 0x08, + 0x01, 0x04, 0x04, 0x03, 0x08, 0x01, 0x03, 0x04, 0x03, 0x08, 0x01, 0x02, + 0x03, 0x03, 0x08, 0x09, 0x0a, 0x00, 0x00, 0x00, 0x06, 0x0f, 0xe3, 0x00, + 0x0f, 0xfc, 0x0f, 0xf7, 0x0f, 0xf2, 0x0f, 0xed, 0x0f, 0xe8, 0x0f, 0xe3, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x08, 0x01, 0x06, 0x04, 0x03, 0x08, 0x01, + 0x05, 0x04, 0x03, 0x08, 0x01, 0x04, 0x04, 0x03, 0x08, 0x01, 0x03, 0x04, + 0x03, 0x08, 0x01, 0x02, 0x03, 0x03, 0x08, 0x09, 0x0a, 0x00, 0x00, 0x00, + 0x06, 0x0f, 0xe3, 0x00, 0x0f, 0xfc, 0x0f, 0xf7, 0x0f, 0xf2, 0x0f, 0xed, + 0x0f, 0xe8, 0x0f, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x09, 0x01, 0x06, + 0x04, 0x03, 0x09, 0x01, 0x05, 0x04, 0x03, 0x09, 0x01, 0x04, 0x04, 0x03, + 0x09, 0x01, 0x03, 0x04, 0x03, 0x09, 0x01, 0x02, 0x03, 0x03, 0x09, 0x09, + 0x0d, 0x00, 0x00, 0x00, 0x05, 0x05, 0x88, 0x00, 0x05, 0x88, 0x07, 0xca, + 0x0a, 0x10, 0x0b, 0x9e, 0x0d, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x55, 0x07, 0x16, 0x00, 0x07, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, + 0x34, 0x00, 0x88, 0x0a, 0x17, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x7e, 0xdf, + 0xaa, 0x7a, 0x41, 0xb7, 0x59, 0x5c, 0x7e, 0xdf, 0xaa, 0x7a, 0x0b, 0x66, + 0x7c, 0x18, 0x9e, 0x44, 0x49, 0x2d, 0x40, 0x62, 0x95, 0x22, 0xa7, 0xe3, + 0x08, 0x19, 0x26, 0x0f, 0xd6, 0x6d, 0x3a, 0xdc, 0x09, 0xb3, 0xcd, 0x3d, + 0x7c, 0x47, 0x10, 0xf5, 0x62, 0xa0, 0x5b, 0xd8, 0x50, 0xe7, 0x56, 0xcb, + 0xa1, 0xb8, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, + 0x00, 0x00, 0x64, 0x0f, 0xc5, 0x21, 0x02, 0x15, 0x7c, 0xa5, 0xb2, 0x07, + 0xf2, 0xee, 0xe7, 0xeb, 0x55, 0xb1, 0x73, 0x0b, 0xc7, 0x85, 0xd2, 0x16, + 0x2f, 0x68, 0x13, 0x3e, 0x6a, 0x6b, 0x3a, 0x3d, 0xbd, 0x3d, 0xd9, 0xc4, + 0x98, 0x92, 0xea, 0x5a, 0xf1, 0xf3, 0x69, 0x0e, 0x20, 0x7b, 0x97, 0xca, + 0xe6, 0x21, 0x45, 0x98, 0xcf, 0x92, 0x04, 0xf5, 0xc9, 0x46, 0x27, 0xd4, + 0x4f, 0x83, 0x2c, 0x3b, 0xbb, 0x83, 0x22, 0xa3, 0x3c, 0x4e, 0x8e, 0x37, + 0x6e, 0xe1, 0x6f, 0x80, 0x83, 0x0f, 0x19, 0xed, 0x17, 0xdb, 0xd1, 0x96, + 0xb9, 0x33, 0xe6, 0x25, 0x50, 0x4f, 0x40, 0x36, 0xbf, 0x42, 0x46, 0xfc, + 0x1c, 0x4a, 0x84, 0x9a, 0xb5, 0xcb, 0xe1, 0xee, 0x4c, 0x84, 0xde, 0x41, + 0x9f, 0x69, 0x3d, 0x9c, 0xe5, 0x38, 0x68, 0xb1, 0x9c, 0x59, 0xd6, 0xcf, + 0xcd, 0x76, 0xc3, 0xa7, 0x99, 0xf2, 0xe5, 0x8d, 0x3b, 0x02, 0xcc, 0x1a, + 0xed, 0x52, 0xd6, 0xef, 0x8f, 0xb2, 0xba, 0x11, 0x39, 0xa5, 0x82, 0x12, + 0x04, 0x2b, 0x03, 0xda, 0x41, 0x8c, 0x9e, 0xe1, 0xc0, 0x8d, 0xdb, 0xff, + 0x46, 0xce, 0xa9, 0xf3, 0x70, 0xf0, 0x5a, 0xd9, 0x5e, 0xc1, 0xa3, 0xca, + 0xd4, 0x02, 0x2a, 0xce, 0x49, 0x55, 0x61, 0x5d, 0x22, 0xbf, 0xf6, 0x5a, + 0xe6, 0xe4, 0xb4, 0x7a, 0xe2, 0x47, 0x24, 0x72, 0xba, 0x8b, 0xd2, 0x39, + 0x49, 0xf2, 0xa0, 0xda, 0xe6, 0xb6, 0xe1, 0x79, 0xdc, 0x0d, 0x73, 0x1b, + 0xe6, 0x40, 0xe4, 0xda, 0x74, 0x7c, 0xa4, 0x81, 0x4b, 0x79, 0x8c, 0x23, + 0x8d, 0xd5, 0x9d, 0xe0, 0x01, 0xe2, 0x88, 0xa8, 0x3f, 0x09, 0xec, 0xf3, + 0xa8, 0xd5, 0x8b, 0xe2, 0xef, 0x0e, 0x0c, 0x42, 0x37, 0xc0, 0x2a, 0x7d, + 0x25, 0x56, 0xc4, 0x28, 0xc3, 0x70, 0x73, 0xe7, 0x14, 0xd0, 0xa8, 0x1e, + 0x2a, 0xd7, 0xd6, 0x85, 0x0f, 0x4b, 0x94, 0x8d, 0xa3, 0xb2, 0xee, 0x83, + 0x36, 0x0a, 0x59, 0x4b, 0x8a, 0xc3, 0xf8, 0xd1, 0x64, 0xb4, 0x07, 0x7c, + 0x3d, 0x98, 0xaf, 0x7c, 0xd2, 0xed, 0x2a, 0xa2, 0x91, 0xf4, 0x32, 0xa8, + 0xf1, 0x67, 0x0a, 0x34, 0x75, 0x88, 0x4e, 0x69, 0x78, 0xca, 0xa4, 0x0c, + 0x84, 0x3f, 0x01, 0x16, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x34, 0x00, 0x87, 0x5e, 0x17, + 0x13, 0x41, 0xb7, 0x59, 0x50, 0xd8, 0x33, 0x2b, 0x24, 0x41, 0xb7, 0x59, + 0x50, 0xd8, 0x33, 0x2b, 0x24, 0x83, 0xad, 0xb6, 0xae, 0x9f, 0x27, 0xa5, + 0x45, 0x30, 0xb3, 0x67, 0xc8, 0x32, 0x58, 0x95, 0x85, 0x06, 0xeb, 0xc1, + 0xf4, 0x06, 0x98, 0x7e, 0x8b, 0x09, 0xd8, 0x2e, 0xbe, 0x8c, 0x6b, 0x51, + 0x5c, 0x08, 0x13, 0x58, 0xb4, 0x2e, 0x41, 0xcb, 0x34, 0x02, 0x00, 0x00, + 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x99, 0xb4, 0x79, + 0xc1, 0x37, 0xc1, 0xe1, 0x5c, 0x49, 0xa0, 0xe1, 0xf3, 0x17, 0xb8, 0x9c, + 0x69, 0xe6, 0xba, 0xdc, 0xe7, 0x78, 0xb2, 0x5d, 0xd6, 0x95, 0xbe, 0xb2, + 0xda, 0x91, 0xd3, 0x9b, 0xf2, 0xd4, 0xe3, 0x95, 0x3c, 0x53, 0x8d, 0x0e, + 0x68, 0xe9, 0x02, 0xb3, 0xed, 0xeb, 0x95, 0xdd, 0x11, 0xb2, 0x64, 0x69, + 0x8a, 0xfe, 0x03, 0x05, 0xd5, 0x04, 0x9b, 0xac, 0x8a, 0xb6, 0x98, 0x29, + 0x56, 0x2e, 0xd3, 0xea, 0x4e, 0x84, 0xee, 0x23, 0x44, 0x03, 0x12, 0x9d, + 0x9c, 0x9c, 0x9f, 0x11, 0x62, 0xf0, 0x86, 0x36, 0x52, 0x15, 0x0f, 0x27, + 0x93, 0xdb, 0xde, 0x13, 0xc9, 0x94, 0x93, 0xe4, 0xa4, 0x6f, 0x58, 0x9d, + 0x58, 0x9f, 0x15, 0xba, 0x5f, 0x4c, 0xf3, 0x9a, 0x90, 0xc0, 0xcb, 0x60, + 0xce, 0x9b, 0x56, 0x0c, 0xfe, 0x5b, 0xd2, 0x4e, 0x0e, 0x82, 0xe6, 0x4c, + 0x62, 0x57, 0x08, 0x6e, 0x5d, 0x54, 0x7b, 0x28, 0xbb, 0x88, 0xdc, 0xec, + 0xaa, 0xd1, 0x6e, 0xd3, 0x94, 0x20, 0x3e, 0x35, 0x81, 0x52, 0xf6, 0xe9, + 0xee, 0x42, 0x89, 0xe9, 0xea, 0x61, 0x2c, 0xd8, 0xdc, 0xe3, 0x82, 0xf7, + 0xf0, 0xc0, 0xf6, 0xf9, 0xb7, 0xef, 0x49, 0xc7, 0x8d, 0x6c, 0x8a, 0x6d, + 0x6e, 0xbc, 0x2d, 0xc0, 0xb1, 0xec, 0x0c, 0xdd, 0xe5, 0xbe, 0x65, 0x3f, + 0x69, 0x81, 0xcf, 0xe8, 0xd8, 0xf3, 0x57, 0x8e, 0xba, 0x73, 0x7f, 0xb0, + 0x4e, 0x65, 0xa2, 0xa5, 0xa5, 0xbb, 0x7b, 0xae, 0xaa, 0x88, 0x06, 0x4f, + 0x2c, 0x43, 0xb9, 0x4c, 0x17, 0xa1, 0x24, 0xfb, 0xe1, 0x90, 0x50, 0xdb, + 0xcc, 0xd9, 0xe5, 0x7b, 0x09, 0xaf, 0x5c, 0x5a, 0x4f, 0xb2, 0x2b, 0x30, + 0x53, 0x0f, 0xd3, 0xe2, 0xbd, 0xcd, 0xf7, 0xa3, 0x19, 0xdc, 0xba, 0xee, + 0xd1, 0x49, 0xbc, 0xa6, 0xde, 0x1b, 0xe6, 0xd3, 0xaf, 0xdd, 0x61, 0xf6, + 0xfd, 0xef, 0xb7, 0xda, 0x9d, 0x93, 0x45, 0x0a, 0xa2, 0xa8, 0x1a, 0xe5, + 0x16, 0xb1, 0xaf, 0x20, 0x00, 0x86, 0x6b, 0x66, 0x42, 0x97, 0x4e, 0x3a, + 0xea, 0x0d, 0x33, 0xb2, 0x93, 0x87, 0x9c, 0xd1, 0x6a, 0x20, 0xbc, 0xc9, + 0x7d, 0x46, 0xb9, 0x0a, 0x26, 0x9a, 0x09, 0x81, 0xc8, 0x6d, 0x9b, 0x63, + 0xa5, 0x1f, 0x63, 0x72, 0x6c, 0xa8, 0x65, 0x65, 0xa2, 0x8a, 0x81, 0x4d, + 0x54, 0xd4, 0xa3, 0xc4, 0x86, 0x48, 0x31, 0x5c, 0x4e, 0x15, 0xf3, 0x48, + 0x30, 0xbc, 0x17, 0xac, 0x0b, 0x85, 0x8f, 0x44, 0x62, 0xf4, 0x57, 0xc7, + 0xbd, 0x18, 0xcf, 0xf5, 0xd8, 0xa9, 0x2d, 0xf5, 0x57, 0xaf, 0x42, 0x09, + 0xf7, 0x5b, 0x25, 0x56, 0xa1, 0x04, 0x0c, 0xf7, 0xa7, 0xc9, 0x2d, 0xd7, + 0x84, 0x78, 0x86, 0x82, 0x2d, 0xd3, 0xaa, 0xd2, 0xbf, 0x77, 0xc0, 0x34, + 0x7b, 0xdb, 0x7e, 0x4d, 0xde, 0x63, 0x8f, 0xcc, 0xb6, 0x6d, 0x01, 0x80, + 0x68, 0x51, 0x3e, 0x8f, 0x2a, 0x7c, 0x0e, 0xaa, 0xc2, 0xbf, 0x77, 0x12, + 0x06, 0x88, 0xdf, 0x3f, 0x6c, 0x7d, 0x69, 0x05, 0x57, 0x71, 0xeb, 0xe7, + 0xf3, 0xcb, 0x32, 0x4d, 0x33, 0x54, 0x8a, 0x2a, 0x1b, 0xb5, 0x6e, 0xb6, + 0xa4, 0x64, 0xcd, 0x34, 0x5c, 0xa9, 0x3d, 0x92, 0xc8, 0x38, 0xbb, 0x84, + 0xed, 0xde, 0xe4, 0xa2, 0xe1, 0x68, 0x2f, 0xcb, 0x4b, 0x3c, 0x76, 0xb2, + 0x3b, 0x84, 0x5f, 0x6b, 0x46, 0x72, 0x2f, 0x7f, 0xf0, 0x6f, 0x6b, 0x7b, + 0xd3, 0xc5, 0x4b, 0x20, 0x2b, 0xae, 0x48, 0x7e, 0xcb, 0x22, 0x38, 0x44, + 0x1f, 0x43, 0x1c, 0x55, 0x85, 0xe0, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x64, + 0x6b, 0x75, 0x84, 0x43, 0x02, 0x16, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x34, 0x00, 0x87, + 0x66, 0x17, 0x13, 0x41, 0xb7, 0x59, 0x50, 0xd8, 0x37, 0x6c, 0x27, 0x41, + 0xb7, 0x59, 0x50, 0xd8, 0x37, 0x6c, 0x27, 0x77, 0xac, 0x86, 0x8b, 0xf9, + 0xb8, 0xa0, 0x50, 0x0b, 0x1f, 0xb3, 0x50, 0x55, 0xe2, 0x63, 0x81, 0xf6, + 0x85, 0xbc, 0xeb, 0x06, 0x98, 0x7e, 0x8b, 0x09, 0xd8, 0x2e, 0xbe, 0x8c, + 0x6b, 0x51, 0x5c, 0x08, 0x13, 0x58, 0xb4, 0x2e, 0x41, 0xcb, 0x34, 0x02, + 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xf6, + 0xbc, 0x81, 0x5b, 0x23, 0x66, 0x44, 0x13, 0x27, 0xcf, 0x98, 0xc2, 0xc0, + 0x31, 0x38, 0x98, 0xec, 0x01, 0x84, 0xbb, 0x38, 0xb1, 0x79, 0xd7, 0x91, + 0x66, 0x5a, 0x56, 0x22, 0x62, 0x6f, 0xb8, 0xf0, 0x68, 0x00, 0xe7, 0x1a, + 0x7a, 0x93, 0xfc, 0xa8, 0xd4, 0xd9, 0xaf, 0x21, 0x17, 0x71, 0xf3, 0x0c, + 0xd6, 0x22, 0x2f, 0xb0, 0xb7, 0xc3, 0x1e, 0x07, 0xe7, 0x53, 0x34, 0xc9, + 0x17, 0x9d, 0xe8, 0xd3, 0x07, 0x78, 0xe7, 0x74, 0xcd, 0xf0, 0xdd, 0x88, + 0x0d, 0x30, 0x9b, 0x3c, 0x78, 0xfb, 0x43, 0xb7, 0x4f, 0x79, 0xd1, 0x83, + 0xcd, 0x56, 0x60, 0xe7, 0x7e, 0x8d, 0xba, 0x61, 0x9d, 0x4f, 0xf2, 0x71, + 0x9b, 0xbd, 0x11, 0xfc, 0x82, 0x8f, 0xc2, 0x9b, 0x32, 0xb7, 0x4d, 0x5d, + 0x93, 0x87, 0x11, 0x7d, 0xbf, 0x3a, 0x06, 0x11, 0x15, 0xf5, 0x97, 0xf4, + 0x03, 0x24, 0x6a, 0xfb, 0x5e, 0x27, 0x2b, 0xb5, 0xac, 0x20, 0x84, 0xe8, + 0x8d, 0x67, 0xa9, 0xf5, 0x41, 0x8a, 0xbd, 0xea, 0x51, 0x91, 0x30, 0xd7, + 0xf2, 0x81, 0x12, 0xbc, 0x24, 0x61, 0x25, 0x58, 0x9e, 0x4a, 0x4c, 0x89, + 0xa4, 0x19, 0xf1, 0x12, 0xe2, 0x33, 0xf1, 0x37, 0x1f, 0x0f, 0xa0, 0x42, + 0xa1, 0x0e, 0xa2, 0xc4, 0x06, 0xb0, 0xba, 0x61, 0xef, 0xc5, 0x6b, 0x46, + 0x33, 0x62, 0x50, 0xe0, 0xe4, 0x2e, 0x74, 0x20, 0xf4, 0x54, 0xbb, 0xed, + 0xa0, 0x73, 0x51, 0xa5, 0xc6, 0x55, 0x90, 0x61, 0xe9, 0x9c, 0x76, 0x72, + 0x21, 0xa9, 0x19, 0x1a, 0xbd, 0xcf, 0x61, 0x29, 0x8a, 0xef, 0xdd, 0xe0, + 0xc6, 0x0a, 0xf0, 0xd8, 0x50, 0xb9, 0xe9, 0x92, 0x7d, 0xf3, 0xce, 0x7e, + 0x9e, 0xcf, 0x32, 0x92, 0xc7, 0x49, 0x59, 0x23, 0xb5, 0x4e, 0xf2, 0x71, + 0xf0, 0xda, 0xb3, 0x80, 0xe3, 0xb6, 0x7a, 0xe4, 0x14, 0x80, 0x25, 0x3e, + 0xd0, 0x89, 0x13, 0xf4, 0x70, 0x96, 0xee, 0xbe, 0xef, 0x31, 0x61, 0xa1, + 0x8d, 0xf7, 0x9a, 0x5c, 0x92, 0x0a, 0x9b, 0x1f, 0x8c, 0x5e, 0x3d, 0x37, + 0x24, 0xc2, 0x8d, 0x21, 0xe9, 0x47, 0x2e, 0x03, 0xee, 0x32, 0xbf, 0x46, + 0xc7, 0x2c, 0x6e, 0x7a, 0x81, 0x9e, 0x14, 0xb8, 0xbe, 0xdb, 0x22, 0x4f, + 0xf1, 0x8d, 0x47, 0x41, 0x84, 0xc9, 0xeb, 0x4f, 0xe9, 0xf4, 0xad, 0xc4, + 0xbe, 0xf8, 0x28, 0xcb, 0xe6, 0x16, 0xa8, 0x6b, 0xaf, 0xd5, 0x0a, 0x6d, + 0x06, 0x59, 0x4f, 0x7d, 0x53, 0xa6, 0x4e, 0x90, 0xa0, 0x23, 0x1b, 0x92, + 0xf0, 0xe8, 0xef, 0xed, 0x0d, 0xa7, 0x64, 0x01, 0x83, 0x4a, 0x3b, 0x2d, + 0x18, 0x90, 0x1d, 0x19, 0x1d, 0xa2, 0x98, 0xe9, 0xb5, 0xe4, 0x4a, 0x73, + 0xcf, 0xdf, 0x0c, 0x09, 0xd5, 0xf4, 0xd3, 0xd9, 0x12, 0x7c, 0xbb, 0x81, + 0x51, 0x26, 0x2a, 0xcb, 0xa7, 0xc9, 0x6a, 0xe9, 0xfb, 0x1d, 0xca, 0x43, + 0xf1, 0xbe, 0xfb, 0xc3, 0x6f, 0xb6, 0xa1, 0x0c, 0x42, 0x32, 0x18, 0x24, + 0x63, 0xf9, 0xa0, 0x7e, 0x71, 0x8c, 0xa5, 0x16, 0x16, 0x5a, 0x5e, 0x15, + 0x5d, 0x6d, 0x4b, 0x74, 0x5b, 0xde, 0x21, 0xd5, 0xe0, 0x11, 0xa6, 0x91, + 0xc3, 0xb2, 0xd7, 0x38, 0x70, 0xa2, 0x18, 0x29, 0x1b, 0xdc, 0x83, 0x3e, + 0x37, 0x45, 0xc4, 0x1b, 0x61, 0x98, 0x06, 0x12, 0x3e, 0xc0, 0xda, 0x1a, + 0xc9, 0x18, 0x9c, 0x50, 0x0e, 0xc5, 0xe1, 0xa7, 0x4d, 0x05, 0xc6, 0x99, + 0x31, 0xab, 0x17, 0x30, 0xb9, 0xb0, 0x01, 0x1f, 0x93, 0xd9, 0x76, 0xd4, + 0x67, 0x0b, 0xea, 0x7b, 0x2b, 0x0b, 0x42, 0x97, 0x40, 0x07, 0x94, 0x08, + 0x61, 0x70, 0x70, 0x6c, 0x65, 0x64, 0x6b, 0x75, 0x83, 0x0b, 0x05, 0x16, + 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x34, 0x34, 0x00, 0x84, 0x3c, 0x29, 0x13, 0x41, 0xb7, 0x59, + 0x5c, 0x53, 0x32, 0x4a, 0x6b, 0x41, 0xb7, 0x59, 0x5c, 0x53, 0x32, 0x4a, + 0x6b, 0x65, 0x6d, 0xb0, 0x14, 0x83, 0xdf, 0x17, 0xb6, 0x73, 0x59, 0x09, + 0xd6, 0x8a, 0xed, 0x02, 0x13, 0x5a, 0x8b, 0xd4, 0x99, 0xda, 0x39, 0xa3, + 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, + 0x90, 0xaf, 0xd8, 0x07, 0x09, 0xaa, 0xa7, 0xbf, 0x94, 0x09, 0x4f, 0x35, + 0x59, 0x31, 0xba, 0xaa, 0x89, 0x4f, 0xfa, 0x26, 0x41, 0x66, 0x87, 0x1b, + 0x60, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, + 0x00, 0xdc, 0x97, 0xef, 0xa5, 0xc0, 0xbc, 0x15, 0x38, 0x95, 0x35, 0x74, + 0x61, 0x34, 0x68, 0xb9, 0x5c, 0xef, 0x21, 0xad, 0xeb, 0xc9, 0x50, 0x73, + 0xed, 0x31, 0x38, 0x33, 0x44, 0x03, 0x44, 0x16, 0xaf, 0xa2, 0xba, 0x34, + 0x58, 0x3f, 0x49, 0xaf, 0x93, 0xf8, 0xe4, 0x6e, 0x6f, 0x7f, 0x23, 0x05, + 0x46, 0x75, 0x49, 0xdf, 0x84, 0xad, 0x64, 0x83, 0x11, 0x43, 0xd9, 0x80, + 0x11, 0x93, 0x6d, 0xcf, 0xb4, 0x72, 0x42, 0xc2, 0x5a, 0x78, 0x57, 0x37, + 0x2d, 0x9e, 0x9a, 0x3e, 0x30, 0x9b, 0x72, 0x7b, 0xfa, 0x1d, 0x9e, 0x2d, + 0x53, 0x16, 0x85, 0x91, 0x3c, 0xe9, 0xf1, 0x39, 0x60, 0x1d, 0x9e, 0xc6, + 0xee, 0xb1, 0xdc, 0xb1, 0x0d, 0xb8, 0x23, 0x68, 0xbf, 0xe5, 0x08, 0xc4, + 0xac, 0x31, 0x4e, 0x2d, 0x0f, 0x1f, 0xe1, 0xb3, 0xfe, 0xd2, 0x31, 0x4a, + 0x52, 0x3e, 0x03, 0xe1, 0x1a, 0x66, 0x58, 0x8b, 0x56, 0x99, 0x55, 0x7f, + 0x6f, 0x5a, 0xa9, 0x8f, 0xcf, 0xb3, 0x03, 0x96, 0x79, 0xb0, 0x6c, 0x67, + 0x60, 0x35, 0xce, 0x8d, 0xc6, 0x1c, 0x70, 0x05, 0xa4, 0x5e, 0x4f, 0x83, + 0x4f, 0x1a, 0x98, 0x88, 0xdd, 0x5a, 0x5d, 0xb3, 0x9b, 0xf6, 0xb2, 0xa3, + 0x2e, 0x1c, 0x41, 0x81, 0x97, 0xef, 0x16, 0xb3, 0x8e, 0xbe, 0x09, 0x08, + 0x3d, 0x47, 0xaa, 0x2b, 0x90, 0x61, 0xc7, 0x67, 0xcb, 0x0d, 0xa5, 0x7a, + 0x58, 0x4d, 0xa7, 0x9f, 0xd4, 0x21, 0xf2, 0x47, 0x65, 0x3b, 0x9e, 0x3b, + 0xa4, 0xb4, 0x15, 0x05, 0x10, 0xee, 0x90, 0xe5, 0xd9, 0x2e, 0xa0, 0xfe, + 0x85, 0x9c, 0xad, 0x37, 0x71, 0x51, 0xba, 0x0e, 0x91, 0x48, 0x3e, 0x54, + 0xa0, 0x10, 0x1b, 0xc7, 0xff, 0x4b, 0xd2, 0x24, 0xf8, 0x37, 0xd9, 0xc3, + 0x17, 0x12, 0x05, 0x28, 0xbe, 0xeb, 0xf5, 0xa3, 0x5a, 0x93, 0x7b, 0x9e, + 0x59, 0xb2, 0x63, 0xbc, 0x71, 0x61, 0x6a, 0x5a, 0x6c, 0xbd, 0xae, 0xeb, + 0xff, 0x2a, 0x53, 0xf3, 0x44, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, + 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x73, 0x64, 0x64, 0x6b, 0x75, 0x84, 0x07, + 0x06, 0x16, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x34, 0x34, 0x86, 0x46, 0x17, 0x13, 0x41, + 0xb7, 0x59, 0x5c, 0x54, 0xdd, 0xc7, 0x58, 0x41, 0xb7, 0x59, 0x5c, 0x54, + 0xdd, 0xc7, 0x58, 0x8e, 0xc3, 0x7e, 0x3a, 0x0f, 0x3a, 0x3a, 0x7e, 0x0e, + 0x1e, 0x69, 0x08, 0x28, 0x2f, 0x21, 0x1c, 0x2a, 0x13, 0xa3, 0x59, 0xe5, + 0x0e, 0x4d, 0x78, 0x41, 0x89, 0x33, 0xa3, 0x28, 0x6d, 0xb9, 0x0a, 0x0b, + 0x36, 0x7b, 0xf9, 0xc7, 0xb9, 0x71, 0xe5, 0x1c, 0x32, 0x04, 0xe7, 0x79, + 0xe1, 0xe0, 0x05, 0x0b, 0xa0, 0xe7, 0xb9, 0xe1, 0x92, 0xbb, 0xa8, 0xae, + 0xca, 0xff, 0x1c, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x99, 0x02, 0x2d, 0xc5, 0xee, 0x94, 0x76, 0x6c, 0x0a, + 0xe2, 0xa1, 0xb1, 0x7a, 0x6d, 0x0c, 0xbf, 0x9d, 0xa2, 0x60, 0xdc, 0xb9, + 0xf4, 0xf9, 0x4e, 0x6f, 0x61, 0x37, 0x18, 0x86, 0xbf, 0xef, 0xe9, 0x55, + 0x9e, 0x44, 0x75, 0x32, 0x4c, 0x20, 0x82, 0xb5, 0x3d, 0x42, 0x72, 0x35, + 0x69, 0xba, 0x22, 0x95, 0x0c, 0xec, 0x46, 0xe8, 0x5b, 0x62, 0xe2, 0x07, + 0xd4, 0x80, 0x99, 0xc1, 0x83, 0x12, 0x3f, 0xcc, 0xd4, 0xf6, 0xcd, 0xc2, + 0xb2, 0xcd, 0x4d, 0x94, 0x4c, 0xab, 0x05, 0x48, 0x0c, 0x09, 0xe1, 0x82, + 0x1a, 0x6c, 0x0a, 0xf5, 0x16, 0x06, 0x57, 0x23, 0x9e, 0x18, 0xe8, 0xd9, + 0xbb, 0x4a, 0x8a, 0xcd, 0x69, 0xed, 0xc3, 0xae, 0x71, 0xe8, 0x8f, 0xeb, + 0xb5, 0x76, 0x50, 0xca, 0xb5, 0x69, 0x05, 0xdc, 0x93, 0x5b, 0x49, 0xed, + 0xa3, 0xf8, 0x25, 0xfe, 0x6a, 0x83, 0x6f, 0x16, 0x1e, 0xef, 0x5b, 0xfd, + 0x24, 0x7f, 0x9f, 0x66, 0xf1, 0x65, 0x8c, 0x38, 0x43, 0xd1, 0xbc, 0x13, + 0x14, 0x45, 0x75, 0x66, 0x3b, 0xd7, 0xe1, 0x7a, 0xde, 0xb1, 0xf6, 0x27, + 0xd6, 0x3e, 0xf6, 0x44, 0x7d, 0xf3, 0x3e, 0xd2, 0x95, 0x49, 0xe5, 0x31, + 0x6f, 0x38, 0x95, 0xd0, 0x78, 0xc8, 0xca, 0x68, 0xaf, 0xec, 0xab, 0x1e, + 0xcf, 0x0c, 0xff, 0x3e, 0xc4, 0x12, 0x3e, 0x48, 0xb4, 0x7e, 0x70, 0xc6, + 0xa0, 0x9b, 0xf8, 0x80, 0x30, 0x75, 0x25, 0x1a, 0xf1, 0xdf, 0x3a, 0x37, + 0xa1, 0xac, 0x43, 0x5b, 0xa0, 0xae, 0x9b, 0x91, 0xb3, 0x4a, 0xfa, 0x5f, + 0x4b, 0xf1, 0xba, 0xcd, 0x41, 0x92, 0x38, 0x6a, 0x8d, 0x69, 0x9e, 0xd3, + 0x09, 0xaa, 0x4c, 0xb2, 0x60, 0xcf, 0xff, 0x37, 0xed, 0xa0, 0x39, 0x36, + 0x03, 0x1a, 0x6a, 0xb7, 0xed, 0xce, 0xc8, 0x4e, 0x46, 0xb1, 0x82, 0xfb, + 0xe1, 0x46, 0x2d, 0x12, 0xf4, 0x8a, 0x6c, 0x38, 0x5c, 0x6b, 0xaa, 0x05, + 0xf1, 0xc0, 0xf2, 0x14, 0x8d, 0x3e, 0xdc, 0xec, 0x04, 0x0c, 0x94, 0xe3, + 0xbf, 0x3b, 0x7b, 0x3f, 0xa2, 0x88, 0x98, 0xe6, 0x0c, 0x5f, 0x23, 0x6d, + 0x0b, 0x6f, 0x8e, 0xe9, 0xce, 0xc0, 0xe2, 0x3e, 0xc7, 0xcd, 0xa0, 0x7b, + 0xda, 0xf1, 0x26, 0xfd, 0x3d, 0xc6, 0xe7, 0xe8, 0xed, 0x9d, 0xeb, 0x74, + 0xc5, 0x14, 0x5c, 0xee, 0xcd, 0x4d, 0xc4, 0x4e, 0x1b, 0x2d, 0x09, 0xf4, + 0x7b, 0xdb, 0xf6, 0x96, 0x17, 0x17, 0xd1, 0x16, 0xd5, 0xea, 0xaf, 0x4f, + 0x7b, 0xc2, 0x1e, 0x0f, 0xe1, 0x2c, 0xd8, 0x26, 0xe1, 0xcc, 0x66, 0x64, + 0xd1, 0x3f, 0xd9, 0x16, 0x99, 0x0c, 0xb1, 0x11, 0xc2, 0x13, 0xe5, 0xab, + 0x99, 0x2a, 0x6f, 0x09, 0x37, 0xc5, 0x7c, 0x8e, 0xb8, 0x04, 0x73, 0x3b, + 0x0b, 0x58, 0x87, 0x10, 0x33, 0x1f, 0x5d, 0xea, 0xe9, 0xcd, 0x4e, 0x5b, + 0x33, 0x88, 0xc2, 0x9c, 0x01, 0x1a, 0xe6, 0x92, 0x57, 0xf9, 0xa8, 0x7d, + 0x03, 0x76, 0x79, 0x4e, 0x1e, 0x25, 0xe8, 0xae, 0x61, 0x70, 0x70, 0x6c, + 0x65, 0x64, 0x6b, 0x75, 0x84, 0x55, 0x07, 0x16, 0x00, 0x07, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x34, + 0x00, 0x88, 0x0a, 0x17, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x7e, 0xdf, 0xaa, + 0x7a, 0x41, 0xb7, 0x59, 0x5c, 0x7e, 0xdf, 0xaa, 0x7a, 0x0b, 0x66, 0x7c, + 0x18, 0x9e, 0x44, 0x49, 0x2d, 0x40, 0x62, 0x95, 0x22, 0xa7, 0xe3, 0x08, + 0x19, 0x26, 0x0f, 0xd6, 0x6d, 0x3a, 0xdc, 0x09, 0xb3, 0xcd, 0x3d, 0x7c, + 0x47, 0x10, 0xf5, 0x62, 0xa0, 0x5b, 0xd8, 0x50, 0xe7, 0x56, 0xcb, 0xa1, + 0xb8, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, + 0x00, 0x64, 0x0f, 0xc5, 0x21, 0x02, 0x15, 0x7c, 0xa5, 0xb2, 0x07, 0xf2, + 0xee, 0xe7, 0xeb, 0x55, 0xb1, 0x73, 0x0b, 0xc7, 0x85, 0xd2, 0x16, 0x2f, + 0x68, 0x13, 0x3e, 0x6a, 0x6b, 0x3a, 0x3d, 0xbd, 0x3d, 0xd9, 0xc4, 0x98, + 0x92, 0xea, 0x5a, 0xf1, 0xf3, 0x69, 0x0e, 0x20, 0x7b, 0x97, 0xca, 0xe6, + 0x21, 0x45, 0x98, 0xcf, 0x92, 0x04, 0xf5, 0xc9, 0x46, 0x27, 0xd4, 0x4f, + 0x83, 0x2c, 0x3b, 0xbb, 0x83, 0x22, 0xa3, 0x3c, 0x4e, 0x8e, 0x37, 0x6e, + 0xe1, 0x6f, 0x80, 0x83, 0x0f, 0x19, 0xed, 0x17, 0xdb, 0xd1, 0x96, 0xb9, + 0x33, 0xe6, 0x25, 0x50, 0x4f, 0x40, 0x36, 0xbf, 0x42, 0x46, 0xfc, 0x1c, + 0x4a, 0x84, 0x9a, 0xb5, 0xcb, 0xe1, 0xee, 0x4c, 0x84, 0xde, 0x41, 0x9f, + 0x69, 0x3d, 0x9c, 0xe5, 0x38, 0x68, 0xb1, 0x9c, 0x59, 0xd6, 0xcf, 0xcd, + 0x76, 0xc3, 0xa7, 0x99, 0xf2, 0xe5, 0x8d, 0x3b, 0x02, 0xcc, 0x1a, 0xed, + 0x52, 0xd6, 0xef, 0x8f, 0xb2, 0xba, 0x11, 0x39, 0xa5, 0x82, 0x12, 0x04, + 0x2b, 0x03, 0xda, 0x41, 0x8c, 0x9e, 0xe1, 0xc0, 0x8d, 0xdb, 0xff, 0x46, + 0xce, 0xa9, 0xf3, 0x70, 0xf0, 0x5a, 0xd9, 0x5e, 0xc1, 0xa3, 0xca, 0xd4, + 0x02, 0x2a, 0xce, 0x49, 0x55, 0x61, 0x5d, 0x22, 0xbf, 0xf6, 0x5a, 0xe6, + 0xe4, 0xb4, 0x7a, 0xe2, 0x47, 0x24, 0x72, 0xba, 0x8b, 0xd2, 0x39, 0x49, + 0xf2, 0xa0, 0xda, 0xe6, 0xb6, 0xe1, 0x79, 0xdc, 0x0d, 0x73, 0x1b, 0xe6, + 0x40, 0xe4, 0xda, 0x74, 0x7c, 0xa4, 0x81, 0x4b, 0x79, 0x8c, 0x23, 0x8d, + 0xd5, 0x9d, 0xe0, 0x01, 0xe2, 0x88, 0xa8, 0x3f, 0x09, 0xec, 0xf3, 0xa8, + 0xd5, 0x8b, 0xe2, 0xef, 0x0e, 0x0c, 0x42, 0x37, 0xc0, 0x2a, 0x7d, 0x25, + 0x56, 0xc4, 0x28, 0xc3, 0x70, 0x73, 0xe7, 0x14, 0xd0, 0xa8, 0x1e, 0x2a, + 0xd7, 0xd6, 0x85, 0x0f, 0x4b, 0x94, 0x8d, 0xa3, 0xb2, 0xee, 0x83, 0x36, + 0x0a, 0x59, 0x4b, 0x8a, 0xc3, 0xf8, 0xd1, 0x64, 0xb4, 0x07, 0x7c, 0x3d, + 0x98, 0xaf, 0x7c, 0xd2, 0xed, 0x2a, 0xa2, 0x91, 0xf4, 0x32, 0xa8, 0xf1, + 0x67, 0x0a, 0x34, 0x75, 0x88, 0x4e, 0x69, 0x78, 0xca, 0xa4, 0x0c, 0xf8, + 0x40, 0x9f, 0x86, 0xd9, 0x16, 0x56, 0x67, 0x74, 0xd4, 0x33, 0x9e, 0xb7, + 0xef, 0xa6, 0xdf, 0x32, 0xb2, 0x24, 0x20, 0xe7, 0xe9, 0x80, 0xdf, 0x7b, + 0xa3, 0x49, 0x04, 0xd7, 0x3f, 0x9f, 0xbe, 0xa6, 0x2d, 0xd0, 0xec, 0xed, + 0x04, 0x76, 0xc9, 0x38, 0x0b, 0x2c, 0x02, 0xcc, 0xd0, 0x98, 0x02, 0x73, + 0x96, 0x6b, 0x8b, 0xcb, 0x2b, 0x57, 0x2d, 0xab, 0x0d, 0x5e, 0x97, 0xb8, + 0xd9, 0x81, 0xa6, 0x09, 0x7c, 0x6a, 0x6a, 0xbe, 0xed, 0x44, 0xe1, 0x87, + 0x2a, 0xbd, 0xad, 0x61, 0xfa, 0xdc, 0x76, 0xaa, 0xa5, 0xfd, 0x40, 0xee, + 0x9f, 0xf1, 0xc6, 0x74, 0xe9, 0xba, 0xc1, 0xaf, 0xf1, 0x5d, 0x16, 0x06, + 0x27, 0x60, 0x2b, 0x96, 0x9d, 0x0d, 0xc1, 0x7c, 0xc3, 0x7b, 0xfd, 0x33, + 0xc2, 0xa6, 0x7c, 0xbc, 0xc3, 0x1c, 0xef, 0x9d, 0xf4, 0xe2, 0x8c, 0x2d, + 0xe3, 0x01, 0xc1, 0x95, 0x24, 0x66, 0x15, 0x1a, 0xa1, 0xa0, 0x61, 0x28, + 0x8f, 0x44, 0x77, 0x80, 0xfc, 0x11, 0xce, 0xad, 0xe1, 0xf1, 0xe9, 0x80, + 0x55, 0x6d, 0x77, 0x5d, 0xf7, 0x2a, 0xf8, 0x15, 0x42, 0xdd, 0xf6, 0x62, + 0xac, 0x68, 0x8f, 0xaa, 0x85, 0xd8, 0xfa, 0xc6, 0x21, 0xe9, 0xa8, 0xa2, + 0x1e, 0xe3, 0xd4, 0x32, 0x3e, 0xee, 0xec, 0x96, 0x54, 0xe1, 0xb1, 0x8f, + 0x64, 0x59, 0xc6, 0x49, 0x01, 0x3c, 0xc0, 0x17, 0xa9, 0xf5, 0xf2, 0x6f, + 0x8a, 0xec, 0x9b, 0x66, 0xa7, 0x1d, 0x98, 0xff, 0x61, 0x70, 0x70, 0x6c, + 0x65, 0x64, 0x6b, 0x75, 0x0d, 0x00, 0x00, 0x00, 0x05, 0x04, 0x3a, 0x00, + 0x07, 0x4c, 0x0d, 0x3f, 0x0e, 0xa9, 0x04, 0x3a, 0x05, 0x5c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x1f, 0x11, 0x16, 0x00, 0x07, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x34, 0x00, 0x83, 0x22, 0x15, 0x11, 0x41, 0xb7, 0x59, 0x5c, 0xf4, + 0x84, 0x43, 0x4e, 0x41, 0xb7, 0x59, 0x5c, 0xf4, 0x84, 0x43, 0x4e, 0xda, + 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, + 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0xa9, 0x4a, 0x8f, 0xe5, 0xcc, + 0xb1, 0x9b, 0xa6, 0x1c, 0x4c, 0x08, 0x73, 0xd3, 0x91, 0xe9, 0x87, 0x98, + 0x2f, 0xbb, 0xd3, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x72, 0xbd, 0xda, 0xaa, 0x55, 0x31, 0xcc, 0x9a, 0xfc, + 0x33, 0x30, 0x52, 0x07, 0x40, 0x54, 0xcb, 0x27, 0x4e, 0xb7, 0x9f, 0x96, + 0xb8, 0xcb, 0xdc, 0x88, 0x3c, 0x09, 0xd1, 0x96, 0xe2, 0x79, 0x54, 0x21, + 0x46, 0xca, 0x50, 0xa2, 0x46, 0xda, 0x44, 0x2e, 0x3b, 0x4b, 0x18, 0xb7, + 0x5a, 0x17, 0xe6, 0x4f, 0x06, 0xde, 0xec, 0x05, 0x9c, 0xec, 0x8e, 0xb5, + 0xd1, 0xb3, 0xe3, 0x0a, 0x3f, 0x44, 0x9c, 0xa5, 0x30, 0x0a, 0x83, 0x66, + 0x82, 0x89, 0xcf, 0x1b, 0xb8, 0xb8, 0xb2, 0x18, 0x54, 0xcf, 0x4d, 0x85, + 0x93, 0x97, 0x75, 0x54, 0x06, 0x23, 0x05, 0xe8, 0xff, 0x42, 0x33, 0x7f, + 0xdf, 0x26, 0xa0, 0x1e, 0xd3, 0xe2, 0x7b, 0xb7, 0xe2, 0x70, 0x88, 0x82, + 0xba, 0x3e, 0x38, 0xaa, 0x95, 0xee, 0xf7, 0x4f, 0x81, 0xbe, 0xf4, 0xfe, + 0x8f, 0x42, 0xb8, 0x94, 0x25, 0xe3, 0x3a, 0x4b, 0xe1, 0x15, 0xe2, 0xe1, + 0xe6, 0x8b, 0xda, 0x49, 0x9a, 0xb1, 0x47, 0xa4, 0x9c, 0xac, 0x35, 0xb8, + 0xa2, 0xb3, 0xc2, 0x5f, 0x2b, 0x87, 0x11, 0xd7, 0x57, 0x47, 0x05, 0x89, + 0x05, 0x86, 0xfa, 0x97, 0xa7, 0x97, 0x46, 0xcf, 0xaa, 0xa8, 0x94, 0x2c, + 0xde, 0xa3, 0xde, 0xb1, 0x92, 0x20, 0xbd, 0x7d, 0x90, 0xd2, 0xa7, 0x21, + 0x26, 0x6f, 0x2b, 0x6e, 0xd3, 0xd9, 0x1a, 0xea, 0x57, 0x04, 0x94, 0x1c, + 0x73, 0x0e, 0x74, 0x65, 0x73, 0x74, 0x61, 0x6b, 0xe1, 0x06, 0x12, 0x17, + 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x34, 0x34, 0x00, 0x81, 0xc0, 0x6a, 0x17, 0x13, 0x41, 0xb7, + 0x59, 0x5c, 0xfe, 0x44, 0x71, 0x3f, 0x41, 0xb7, 0x59, 0x5c, 0xfe, 0x44, + 0x71, 0x3f, 0x7f, 0xda, 0x6a, 0xa0, 0x63, 0xf3, 0xfc, 0x5a, 0x86, 0x5c, + 0xa8, 0xf7, 0xa6, 0x9b, 0x5d, 0x69, 0x07, 0x3b, 0x91, 0x55, 0x72, 0x29, + 0x9c, 0x30, 0x4b, 0x50, 0xee, 0xe7, 0xb0, 0xc7, 0x1b, 0x05, 0x97, 0x70, + 0xac, 0x8e, 0x43, 0x5d, 0x69, 0x39, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, + 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x38, 0xbe, 0xad, 0xda, 0xa8, 0x8a, + 0x50, 0x50, 0xa2, 0x05, 0x34, 0x4f, 0x7d, 0x48, 0x22, 0x81, 0x07, 0x45, + 0x81, 0x36, 0x06, 0x10, 0x48, 0xd5, 0xe0, 0xb8, 0x50, 0xbd, 0x5c, 0xe8, + 0x5d, 0x51, 0x93, 0x3c, 0xfa, 0xeb, 0x83, 0x4d, 0x00, 0xa1, 0x9d, 0x8a, + 0x39, 0x91, 0xac, 0x08, 0x70, 0x37, 0x9a, 0x2d, 0x33, 0xdf, 0xfa, 0x44, + 0xed, 0x61, 0x62, 0x10, 0x2c, 0x22, 0x27, 0x44, 0xa8, 0x19, 0xc3, 0x4f, + 0xd4, 0xb6, 0x7a, 0x6c, 0xf3, 0xb2, 0x4f, 0xf4, 0x06, 0x16, 0x5e, 0xc6, + 0x08, 0x61, 0xd5, 0x6b, 0xaf, 0x9d, 0x1e, 0x1f, 0x9c, 0xed, 0x30, 0xda, + 0x7a, 0xf1, 0xa3, 0x24, 0x26, 0xf5, 0xc9, 0xd6, 0xea, 0xdc, 0x1b, 0x4b, + 0xf6, 0x62, 0x78, 0xa6, 0x64, 0x6c, 0xd4, 0xbf, 0x30, 0x29, 0x36, 0x18, + 0x7c, 0x55, 0x1e, 0x12, 0xbe, 0x30, 0xc9, 0x51, 0x4c, 0x18, 0x83, 0x39, + 0x8d, 0xa2, 0xbc, 0x8a, 0x6f, 0x96, 0x1b, 0x69, 0xbf, 0x99, 0x29, 0x58, + 0x7b, 0xd2, 0x9d, 0x50, 0x32, 0x91, 0x31, 0xd2, 0x25, 0xcc, 0x19, 0xab, + 0x51, 0x6a, 0xc8, 0x5b, 0xd9, 0xf3, 0x64, 0x36, 0xf8, 0xbc, 0x73, 0x23, + 0x07, 0x04, 0x93, 0xd9, 0xbc, 0xd4, 0xb8, 0x7b, 0xd3, 0x58, 0x68, 0x2c, + 0x2b, 0x67, 0xae, 0x57, 0x39, 0x6b, 0xb0, 0xf5, 0x62, 0xe5, 0xec, 0xbe, + 0x42, 0x97, 0x9f, 0xec, 0x9c, 0x43, 0x7c, 0xba, 0xab, 0xad, 0xed, 0xd9, + 0xa0, 0xbc, 0xf4, 0x98, 0x03, 0xca, 0xbe, 0xd8, 0xa3, 0x79, 0x4c, 0xdb, + 0x3d, 0x22, 0x15, 0x71, 0xc9, 0x37, 0x92, 0x9b, 0x05, 0x54, 0x72, 0xe2, + 0x41, 0xd7, 0xd8, 0xb2, 0x4f, 0xcf, 0x56, 0xf3, 0x46, 0x4c, 0x39, 0x5d, + 0x49, 0xdf, 0xae, 0x52, 0xb2, 0x8f, 0xf0, 0x9a, 0xae, 0xe0, 0x00, 0xf4, + 0xd0, 0xd0, 0xa3, 0x8d, 0xf4, 0xba, 0x57, 0xe5, 0x0d, 0xa2, 0x0e, 0xcc, + 0xa3, 0xb9, 0xd0, 0x78, 0x24, 0x3e, 0xdb, 0xdb, 0x4b, 0xc8, 0x60, 0xbb, + 0x71, 0xb8, 0xc6, 0xfe, 0xb0, 0x67, 0x5b, 0x86, 0x09, 0x6c, 0xd0, 0x3e, + 0x6e, 0x0a, 0x82, 0x93, 0xcf, 0xdb, 0x9a, 0x72, 0x5c, 0x41, 0x8f, 0xa5, + 0xfd, 0x44, 0x17, 0xe0, 0x5f, 0x85, 0x9c, 0xb5, 0x71, 0xe4, 0x67, 0x94, + 0x88, 0xdf, 0xfe, 0xad, 0x4e, 0x5e, 0x67, 0x41, 0x49, 0xc3, 0xda, 0x1a, + 0x25, 0xcc, 0x8c, 0xaf, 0xb5, 0xf9, 0xb6, 0x37, 0x2f, 0xe9, 0x73, 0x1d, + 0x71, 0xaf, 0x2a, 0x7d, 0x95, 0xef, 0x8a, 0xe0, 0x0f, 0x0a, 0x73, 0x95, + 0x88, 0x33, 0xe2, 0xe0, 0x88, 0x2b, 0x44, 0x60, 0x51, 0x27, 0xfa, 0x90, + 0xfc, 0x5a, 0x35, 0x54, 0x19, 0x9c, 0xb4, 0x60, 0x2b, 0xd8, 0x4c, 0xf9, + 0x2d, 0xba, 0x88, 0x12, 0xa6, 0xfc, 0x0c, 0x22, 0xfd, 0x27, 0x9e, 0x98, + 0x02, 0xf8, 0x06, 0x70, 0x51, 0x66, 0xa0, 0x1e, 0xb1, 0x6e, 0xe1, 0x90, + 0x86, 0x55, 0xa2, 0x84, 0x92, 0xd6, 0xe4, 0x59, 0x00, 0x00, 0x00, 0x1c, + 0x8b, 0x70, 0x08, 0x16, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x34, 0x00, 0x96, 0x40, 0x17, + 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x7e, 0xe2, 0xe0, 0xc1, 0x41, 0xb7, 0x59, + 0x5c, 0x7e, 0xe2, 0xe0, 0xc1, 0x51, 0x96, 0x74, 0xbb, 0x0c, 0xef, 0x0c, + 0xf3, 0x24, 0x61, 0xd2, 0x2c, 0xba, 0x9a, 0xa9, 0xc8, 0x0e, 0x22, 0xff, + 0x0b, 0x3a, 0xdc, 0x09, 0xb3, 0xcd, 0x3d, 0x7c, 0x47, 0x10, 0xf5, 0x62, + 0xa0, 0x5b, 0xd8, 0x50, 0xe7, 0x56, 0xcb, 0xa1, 0xb8, 0x02, 0x00, 0x00, + 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x4e, 0xcb, 0x84, + 0x35, 0xce, 0xed, 0x00, 0x0f, 0x0d, 0x8f, 0xce, 0xe6, 0x43, 0xc4, 0x14, + 0x6f, 0x42, 0xd5, 0x97, 0xdf, 0xa6, 0x31, 0x52, 0xa2, 0xb2, 0xc4, 0x38, + 0xf2, 0x2e, 0xb2, 0x5e, 0x73, 0x6d, 0xeb, 0x60, 0xa9, 0x70, 0x32, 0xad, + 0x98, 0x3a, 0x23, 0x00, 0x86, 0x4c, 0x75, 0x26, 0x22, 0x28, 0x8f, 0x1a, + 0x96, 0x60, 0x8a, 0x61, 0xa2, 0xc5, 0x0b, 0x5a, 0xf6, 0x7b, 0x3a, 0xb0, + 0x42, 0x02, 0x3a, 0x5f, 0x4c, 0x14, 0xdd, 0x52, 0x6a, 0xff, 0x08, 0x5f, + 0x7e, 0xef, 0x9a, 0x98, 0x0e, 0x06, 0x38, 0x24, 0x6d, 0x4c, 0xa6, 0x29, + 0xeb, 0x44, 0xa8, 0x35, 0x7d, 0x0f, 0x2f, 0x8c, 0x83, 0x5b, 0xc4, 0x43, + 0x5f, 0x9c, 0x33, 0x7f, 0xc0, 0x97, 0x17, 0xed, 0xcb, 0x95, 0xed, 0xa4, + 0xe4, 0x29, 0xdd, 0x62, 0xff, 0x3a, 0x07, 0x91, 0x92, 0xa9, 0xc2, 0x19, + 0xc3, 0xaa, 0xa3, 0xcb, 0xcc, 0x64, 0xf2, 0x00, 0xb8, 0xc9, 0x17, 0x3d, + 0x00, 0x24, 0xb2, 0xaf, 0x0e, 0x6c, 0xd5, 0x64, 0x84, 0x7d, 0x60, 0x19, + 0xad, 0xa6, 0x79, 0x05, 0x88, 0xf7, 0x72, 0x5a, 0xa4, 0x6b, 0x51, 0x77, + 0xb2, 0x28, 0x93, 0xcb, 0xbe, 0x74, 0x70, 0x10, 0x09, 0x00, 0x5f, 0x2d, + 0xe5, 0xf8, 0x9d, 0x90, 0x00, 0x2b, 0xa3, 0xbb, 0x32, 0x6c, 0x2d, 0x9e, + 0x72, 0x25, 0x18, 0x92, 0xec, 0xbf, 0x97, 0x49, 0xc7, 0x4c, 0xee, 0x90, + 0x5d, 0x6d, 0xdc, 0xa4, 0x4f, 0x4c, 0x88, 0x6c, 0x81, 0x9f, 0xcf, 0xd1, + 0x89, 0x29, 0x3d, 0x61, 0x38, 0x33, 0x89, 0x4a, 0x81, 0xd2, 0x0c, 0xc8, + 0xdc, 0x09, 0xb2, 0x6a, 0xa7, 0x16, 0x42, 0x9f, 0xa3, 0x9d, 0x85, 0x02, + 0xb4, 0xb8, 0xd4, 0xae, 0x63, 0xef, 0x50, 0x78, 0x43, 0x3b, 0x20, 0x7c, + 0x87, 0xac, 0xcb, 0x0b, 0x96, 0x1c, 0x8e, 0x1f, 0xc4, 0x84, 0x20, 0xe1, + 0x3c, 0xe3, 0x0a, 0x28, 0xfb, 0x4b, 0xa3, 0x19, 0x7c, 0xc7, 0x37, 0xf0, + 0x29, 0x47, 0x9d, 0xaf, 0xf4, 0xf1, 0xf6, 0x3c, 0x32, 0xae, 0x5b, 0x37, + 0xc5, 0x77, 0x90, 0xf5, 0x59, 0x8b, 0x85, 0x95, 0xee, 0xdf, 0xa7, 0x2e, + 0x4b, 0x5b, 0xf3, 0x0c, 0xe3, 0xc5, 0xe6, 0x6a, 0x85, 0xfb, 0xe2, 0x4a, + 0x5a, 0xb8, 0x06, 0xcc, 0x22, 0x3d, 0x21, 0x76, 0x04, 0xca, 0x5f, 0x61, + 0x18, 0x4f, 0x35, 0x11, 0x20, 0xe9, 0xc1, 0x72, 0x3d, 0x45, 0x58, 0x60, + 0x8b, 0x8e, 0x3d, 0x3d, 0x21, 0xf8, 0xb3, 0xa3, 0x02, 0x57, 0x06, 0xbd, + 0xff, 0xe0, 0x65, 0x35, 0x3a, 0xba, 0xe8, 0xa8, 0x96, 0x6f, 0x6c, 0x67, + 0xeb, 0xd6, 0xf4, 0xdc, 0xf6, 0x26, 0x52, 0xcd, 0xed, 0xc1, 0x73, 0x12, + 0xdb, 0x86, 0xef, 0x36, 0x87, 0x22, 0xc4, 0xfd, 0xaf, 0xc7, 0x35, 0x90, + 0x38, 0xe5, 0xb2, 0x4a, 0x8a, 0xca, 0xcc, 0x1a, 0xd5, 0x82, 0x10, 0xba, + 0xe7, 0x60, 0xb2, 0x0d, 0x6b, 0xb5, 0xbd, 0x9e, 0x6e, 0xd0, 0xe0, 0x36, + 0xd8, 0x0a, 0x09, 0x24, 0x87, 0xcd, 0xc2, 0x94, 0x10, 0x14, 0xc4, 0x15, + 0xc2, 0xf7, 0x37, 0x22, 0x78, 0x6c, 0x88, 0x75, 0x3a, 0x08, 0xdc, 0x81, + 0x58, 0xe6, 0x3a, 0x4b, 0x7a, 0x6b, 0xe8, 0x27, 0x5d, 0x5d, 0xea, 0x6d, + 0x1a, 0xbb, 0x50, 0x8b, 0xa5, 0x7c, 0x1d, 0xd2, 0xd8, 0x86, 0xf3, 0xa7, + 0xd7, 0xd7, 0x82, 0x61, 0x14, 0x7a, 0x4e, 0x32, 0xf3, 0x74, 0x38, 0x09, + 0x9b, 0xeb, 0x7c, 0x55, 0x53, 0x9e, 0x39, 0xec, 0xe1, 0xf0, 0xae, 0x7d, + 0xbe, 0x9a, 0x1d, 0x87, 0xab, 0x97, 0xc2, 0xa6, 0x05, 0xb7, 0xc2, 0x86, + 0x2d, 0xc8, 0x1e, 0x02, 0x0a, 0xa8, 0xaa, 0x4f, 0xb5, 0x70, 0x92, 0x97, + 0x75, 0x7a, 0x3c, 0xe0, 0xd3, 0x2c, 0x87, 0xf6, 0x53, 0x4f, 0x98, 0x69, + 0x2f, 0xb3, 0xa6, 0xeb, 0xb6, 0xfd, 0xf5, 0x07, 0x6d, 0x8c, 0x9d, 0xf7, + 0x70, 0x60, 0xe9, 0x34, 0x66, 0x9b, 0x54, 0x37, 0x20, 0xe2, 0x03, 0xb5, + 0x81, 0xff, 0xa1, 0x52, 0x72, 0x27, 0xae, 0x71, 0xe3, 0x4a, 0xf8, 0xda, + 0xa9, 0x8d, 0xb6, 0x2c, 0x88, 0xa2, 0xa4, 0xf3, 0x01, 0xdc, 0x16, 0x28, + 0xe2, 0xb3, 0x6d, 0x94, 0xa8, 0x17, 0xc7, 0x19, 0x35, 0x57, 0x75, 0x31, + 0x7b, 0x1e, 0x92, 0x44, 0xa3, 0xf4, 0xed, 0x84, 0x9c, 0x3e, 0xae, 0x71, + 0xfe, 0x12, 0x40, 0x76, 0x85, 0xa4, 0x98, 0x0b, 0x07, 0x48, 0x91, 0x22, + 0xff, 0x80, 0x07, 0x51, 0x5a, 0x67, 0x19, 0xa8, 0xf5, 0x11, 0x1b, 0x3a, + 0x2e, 0xae, 0x27, 0x6e, 0x26, 0x0e, 0xb0, 0x3c, 0x3b, 0xaf, 0xc0, 0x31, + 0xf6, 0x76, 0x95, 0x89, 0x66, 0xe5, 0x6d, 0x92, 0x12, 0xc8, 0x96, 0xc6, + 0x42, 0x33, 0x66, 0xb1, 0x3c, 0x9b, 0x45, 0xc8, 0xa2, 0x50, 0x37, 0xeb, + 0x7e, 0xf6, 0x67, 0x9e, 0xda, 0x28, 0x1b, 0x8f, 0x6d, 0xd4, 0x47, 0x71, + 0x6a, 0xa6, 0xd9, 0x0c, 0x3c, 0x49, 0xa8, 0xa5, 0x2a, 0x60, 0x88, 0xd0, + 0x44, 0x8f, 0xb0, 0xb8, 0x28, 0x8b, 0x84, 0xce, 0xdd, 0x05, 0x02, 0x22, + 0xab, 0x7c, 0x7a, 0xfe, 0x5a, 0x6c, 0x60, 0x7e, 0x63, 0x17, 0xc6, 0x8b, + 0xaa, 0x28, 0xf4, 0xa1, 0x59, 0x17, 0x93, 0x8e, 0xfc, 0x20, 0x7a, 0xd2, + 0x6d, 0x60, 0x53, 0x2f, 0xd3, 0x97, 0xaa, 0xc4, 0xc3, 0x1b, 0x81, 0x43, + 0xdd, 0x0b, 0xc2, 0x18, 0x31, 0x05, 0xb3, 0xce, 0xea, 0x46, 0x4a, 0x90, + 0xdb, 0x9f, 0x1e, 0x5b, 0xfd, 0x17, 0x6f, 0x84, 0x0d, 0x05, 0x4b, 0x4b, + 0xcb, 0x63, 0x6c, 0x15, 0x47, 0xcf, 0x8b, 0x77, 0x5d, 0xb7, 0x3a, 0x0e, + 0xe1, 0xc5, 0xd6, 0x4b, 0x8a, 0x81, 0x04, 0x18, 0x4f, 0x2e, 0x25, 0x1d, + 0x3b, 0x45, 0x00, 0xc0, 0xd9, 0x44, 0x23, 0xf0, 0x99, 0xf1, 0xe8, 0xc6, + 0xdc, 0x96, 0x38, 0xde, 0xa9, 0x85, 0x4a, 0x5c, 0x7b, 0x5d, 0xaf, 0x35, + 0xc8, 0x6d, 0xbe, 0x89, 0xd2, 0x2a, 0x5c, 0xec, 0xab, 0xe3, 0x8e, 0x69, + 0x19, 0x54, 0xb0, 0x61, 0xad, 0xfd, 0x0b, 0x68, 0x07, 0x2f, 0xe6, 0x13, + 0xa6, 0x83, 0xc1, 0x23, 0x45, 0x54, 0x9e, 0x19, 0xe0, 0xeb, 0x1b, 0x04, + 0xd4, 0xd9, 0x86, 0x6d, 0x38, 0xe4, 0x5b, 0x63, 0xbb, 0xb5, 0xb6, 0xd5, + 0xc5, 0x6e, 0xb1, 0xa5, 0xaf, 0x16, 0x6e, 0x8e, 0xbe, 0xb2, 0xc4, 0x2a, + 0xa8, 0x2d, 0x41, 0x5e, 0xd4, 0xc9, 0x28, 0x67, 0x65, 0x65, 0x98, 0x4c, + 0x0c, 0xd8, 0x40, 0x79, 0x59, 0x42, 0x77, 0xf3, 0x06, 0x81, 0x06, 0x43, + 0xfb, 0x97, 0xbf, 0x28, 0x41, 0xdc, 0xb5, 0x54, 0xb8, 0xdf, 0x9d, 0xc1, + 0x9d, 0xba, 0x4f, 0x11, 0x2a, 0x4e, 0xca, 0xf9, 0xc4, 0xcb, 0xfc, 0xeb, + 0xc1, 0x2a, 0x87, 0x75, 0x5c, 0x6f, 0xcb, 0x75, 0x36, 0xc2, 0x5e, 0xce, + 0x7a, 0x59, 0x6e, 0x7c, 0x6f, 0xe8, 0x3c, 0xa6, 0x7b, 0xe7, 0x36, 0x4d, + 0xfa, 0xad, 0xac, 0xbd, 0x61, 0xa3, 0x36, 0x53, 0xc4, 0x3d, 0xc5, 0xf5, + 0x46, 0x3a, 0x97, 0x5b, 0x66, 0x0a, 0x84, 0xa2, 0x31, 0xf0, 0xdc, 0xc3, + 0x30, 0xdc, 0x52, 0x93, 0x73, 0xab, 0x2b, 0x7e, 0x61, 0xb1, 0x35, 0xa2, + 0xff, 0x8a, 0x31, 0xf8, 0xfe, 0x0f, 0x22, 0x27, 0xba, 0xe2, 0x9e, 0xd3, + 0xfe, 0x7c, 0x2e, 0xe0, 0x94, 0x45, 0xc5, 0x2b, 0xd6, 0xaa, 0xb5, 0x74, + 0xd0, 0x5a, 0x5b, 0x61, 0x24, 0x69, 0x42, 0x8d, 0x5f, 0xe4, 0x3c, 0xe2, + 0xad, 0x15, 0x2b, 0x87, 0xbe, 0xec, 0xf0, 0x2e, 0x61, 0xb6, 0xc4, 0xe1, + 0xc6, 0x57, 0x9a, 0x5d, 0xc7, 0x35, 0x31, 0x6f, 0xb0, 0x14, 0xcc, 0x59, + 0xfc, 0x8a, 0x88, 0x08, 0xcb, 0x20, 0xdd, 0xc3, 0xc7, 0xa4, 0xdc, 0x9c, + 0x1f, 0x1b, 0x89, 0x28, 0x55, 0xab, 0x36, 0x9c, 0xae, 0x64, 0xb2, 0x7e, + 0x7f, 0x92, 0xb5, 0x79, 0x44, 0x0b, 0x2e, 0x0c, 0x3c, 0xc5, 0xd8, 0xd2, + 0x12, 0x15, 0xb9, 0x5e, 0x76, 0x40, 0xc5, 0xf5, 0x6f, 0x33, 0x41, 0xdf, + 0x83, 0x99, 0x91, 0x9b, 0xc1, 0x72, 0xf6, 0xbe, 0x87, 0xeb, 0x25, 0x82, + 0x49, 0x61, 0x44, 0xc1, 0x0f, 0x79, 0xd3, 0xae, 0x4d, 0x8d, 0xa0, 0xa5, + 0x40, 0x5f, 0xf2, 0x65, 0x94, 0xc3, 0x66, 0x18, 0xa1, 0x3c, 0x3b, 0x50, + 0x4b, 0xc9, 0xc0, 0x55, 0xb6, 0xf6, 0x69, 0xc2, 0x08, 0x10, 0x5f, 0xd7, + 0x7a, 0x62, 0xfb, 0x30, 0xf2, 0xdd, 0x25, 0x45, 0xfb, 0x8c, 0xaa, 0x56, + 0x89, 0xa5, 0xc8, 0x4a, 0xfc, 0x34, 0x57, 0x5a, 0x1c, 0x7b, 0x5b, 0xbd, + 0x7d, 0xfe, 0x43, 0xcb, 0xec, 0x3a, 0xdf, 0x59, 0x46, 0xd4, 0x01, 0xe3, + 0xee, 0xdf, 0x7e, 0xab, 0xc4, 0x55, 0x03, 0xdb, 0x7a, 0x3c, 0x56, 0x84, + 0xec, 0x39, 0x7c, 0xab, 0xd6, 0x64, 0x3b, 0x6e, 0xda, 0xa5, 0x1a, 0x48, + 0x13, 0x31, 0x3f, 0xe2, 0xaf, 0xee, 0x15, 0x74, 0xa6, 0x9d, 0x26, 0x6b, + 0xb4, 0x7d, 0x4d, 0xb2, 0x3e, 0xbe, 0x80, 0xdd, 0x81, 0xad, 0x81, 0x3a, + 0xa8, 0x27, 0x25, 0x13, 0xfc, 0x0e, 0xe6, 0x87, 0xdb, 0xf5, 0x08, 0x50, + 0x7a, 0x2c, 0x06, 0x66, 0x87, 0x07, 0xae, 0x14, 0xa8, 0xe2, 0x49, 0x6b, + 0x5f, 0x03, 0x89, 0x07, 0x8e, 0x1a, 0xa1, 0x5e, 0xa3, 0x9f, 0x1f, 0x1f, + 0xb1, 0x22, 0x14, 0x38, 0x9a, 0xc7, 0x4a, 0x7f, 0xd9, 0xb7, 0xd9, 0xbd, + 0xb5, 0x33, 0xa7, 0x97, 0xbb, 0x24, 0x5c, 0xb0, 0xee, 0x1a, 0xe3, 0x2d, + 0xf1, 0x0d, 0x33, 0x6e, 0x77, 0x02, 0x38, 0x35, 0x7d, 0x0f, 0x4a, 0xfb, + 0x12, 0x10, 0xee, 0x1e, 0xf8, 0x33, 0xa8, 0x19, 0xdb, 0xf1, 0xb3, 0x31, + 0x4b, 0x7b, 0xee, 0x3d, 0x0c, 0x71, 0x3a, 0x7c, 0xb7, 0xbc, 0x5e, 0x44, + 0x97, 0x99, 0xb8, 0x56, 0xee, 0x8a, 0xac, 0x72, 0x12, 0x38, 0xac, 0xe9, + 0x8d, 0x35, 0x05, 0x0a, 0x47, 0x27, 0xea, 0xd9, 0xbe, 0x21, 0xaa, 0xd5, + 0xb3, 0x57, 0x44, 0x15, 0xf9, 0xe7, 0x0d, 0x0d, 0x63, 0xc5, 0xa8, 0xe6, + 0x74, 0x9d, 0x52, 0xf4, 0xdd, 0x04, 0x1b, 0xea, 0x82, 0xe9, 0x5d, 0xca, + 0x43, 0xa5, 0x60, 0x6b, 0x16, 0xee, 0x1b, 0xe0, 0xc2, 0x28, 0x75, 0xad, + 0xb5, 0x87, 0xf2, 0xd2, 0x53, 0x32, 0x00, 0xa7, 0xe6, 0x15, 0xd0, 0x93, + 0x0d, 0x1f, 0x67, 0x56, 0xea, 0xaf, 0x98, 0xe4, 0x87, 0x04, 0x71, 0xfe, + 0xf9, 0x2e, 0xd0, 0x2d, 0x1f, 0x70, 0xa9, 0xee, 0x53, 0xec, 0xdb, 0xc7, + 0x3b, 0x3e, 0x42, 0x7e, 0xf3, 0x07, 0xdd, 0x6e, 0x3f, 0xca, 0x69, 0xcc, + 0xe3, 0x9b, 0x9b, 0xd6, 0xfd, 0xd2, 0x44, 0x27, 0xd5, 0xd0, 0x64, 0x2f, + 0xe8, 0x72, 0x26, 0x3c, 0xaf, 0x49, 0xcb, 0xb6, 0x69, 0xae, 0x95, 0xc1, + 0x24, 0x33, 0xc3, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x64, 0x6b, 0x75, 0x82, + 0x67, 0x09, 0x16, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x34, 0x00, 0x84, 0x2e, 0x17, 0x13, + 0x41, 0xb7, 0x59, 0x5c, 0x7e, 0xe7, 0x05, 0xea, 0x41, 0xb7, 0x59, 0x5c, + 0x7e, 0xe7, 0x05, 0xea, 0x05, 0xc5, 0x64, 0xf0, 0xff, 0xc1, 0x0a, 0xf4, + 0x42, 0x83, 0x33, 0x33, 0x5d, 0x04, 0x75, 0x9c, 0x85, 0x9a, 0x74, 0x0a, + 0x3a, 0xdc, 0x09, 0xb3, 0xcd, 0x3d, 0x7c, 0x47, 0x10, 0xf5, 0x62, 0xa0, + 0x5b, 0xd8, 0x50, 0xe7, 0x56, 0xcb, 0xa1, 0xb8, 0x02, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x10, 0x8e, 0xb4, 0xf5, + 0x90, 0xc1, 0x32, 0x90, 0x6a, 0xe5, 0x04, 0x8f, 0xcf, 0xc2, 0xed, 0xf7, + 0x79, 0x17, 0xfc, 0x2e, 0x73, 0xd6, 0xaa, 0xea, 0xfe, 0xb5, 0x0d, 0x3f, + 0x72, 0xf1, 0x5a, 0x24, 0x01, 0xcd, 0xda, 0x13, 0xc1, 0x2b, 0x8f, 0xa9, + 0x10, 0xf2, 0x28, 0xa0, 0x07, 0xbd, 0xc8, 0x20, 0x8c, 0x85, 0x74, 0x3c, + 0xcb, 0x87, 0xbd, 0x9f, 0x3f, 0xf0, 0xd8, 0x56, 0x35, 0x47, 0x97, 0x13, + 0xc9, 0x22, 0x59, 0x2b, 0x71, 0x3f, 0x46, 0x44, 0xf1, 0x3d, 0x3f, 0xc8, + 0x44, 0x43, 0x4d, 0x5c, 0x56, 0x92, 0x3a, 0x3b, 0x00, 0xb0, 0xc1, 0x42, + 0x91, 0xf8, 0xa5, 0x17, 0x42, 0xa8, 0x6a, 0x4d, 0x1e, 0xfd, 0x6f, 0x05, + 0xfb, 0x89, 0x38, 0x46, 0x67, 0x9f, 0x6d, 0xe5, 0x3b, 0xd5, 0xb1, 0xcc, + 0x8b, 0xa9, 0x67, 0x6f, 0x67, 0x1b, 0x5d, 0x7c, 0xe0, 0x0f, 0xd4, 0xdf, + 0x6e, 0xd1, 0x4a, 0xbb, 0x53, 0x57, 0x47, 0xe8, 0x0c, 0xe7, 0x64, 0x54, + 0x4f, 0x57, 0xb6, 0x8e, 0xce, 0xb3, 0x88, 0x70, 0x36, 0x06, 0x0f, 0xdc, + 0xa8, 0x1d, 0xda, 0x06, 0x2b, 0x03, 0xbb, 0xa4, 0x9d, 0x70, 0xb2, 0x04, + 0xa3, 0xfd, 0x9d, 0x8b, 0x6f, 0x89, 0x74, 0x3a, 0xff, 0xf5, 0x2f, 0x30, + 0x34, 0xb1, 0x6b, 0x21, 0xe3, 0xe9, 0x3a, 0xe0, 0x87, 0x17, 0xf5, 0xb4, + 0x81, 0xf2, 0x8f, 0x5e, 0x86, 0xf1, 0x69, 0x5e, 0x99, 0x20, 0x4c, 0x13, + 0xf6, 0x45, 0x46, 0x54, 0x8a, 0x96, 0xfb, 0x83, 0xee, 0xd3, 0x18, 0xd3, + 0x75, 0xa0, 0x6f, 0x32, 0x71, 0xde, 0x4c, 0x92, 0x22, 0x06, 0xca, 0xd0, + 0x9e, 0x1b, 0x32, 0xb5, 0xc9, 0x6c, 0x7e, 0x5f, 0xd1, 0x34, 0xfa, 0xb6, + 0x70, 0x8c, 0x7d, 0xcd, 0x68, 0x86, 0xd0, 0xb6, 0x97, 0x6d, 0x78, 0x96, + 0x48, 0x96, 0xe5, 0x28, 0x28, 0x87, 0xe1, 0xa6, 0xcc, 0x7f, 0x9c, 0x44, + 0x2e, 0xa4, 0x86, 0xef, 0xa9, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x64, 0x6b, + 0x75, 0x82, 0x54, 0x0d, 0x16, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x34, 0x00, 0x84, 0x08, + 0x17, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x83, 0xe0, 0x01, 0x3f, 0x41, 0xb7, + 0x59, 0x5c, 0x83, 0xe0, 0x01, 0x3f, 0x59, 0x27, 0x33, 0x2f, 0x22, 0x90, + 0x8f, 0xdf, 0x8f, 0x07, 0xfa, 0xa9, 0xeb, 0x8d, 0x26, 0x20, 0xc7, 0xc6, + 0x2a, 0x20, 0x3a, 0xdc, 0x09, 0xb3, 0xcd, 0x3d, 0x7c, 0x47, 0x10, 0xf5, + 0x62, 0xa0, 0x5b, 0xd8, 0x50, 0xe7, 0x56, 0xcb, 0xa1, 0xb8, 0x02, 0x00, + 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xa1, 0x9c, + 0xa0, 0x45, 0x5c, 0x35, 0x23, 0x76, 0xa8, 0xd0, 0x2d, 0x3f, 0xa5, 0x6d, + 0x7a, 0x4d, 0xe6, 0xc5, 0x95, 0x1d, 0xea, 0xcf, 0xd5, 0x75, 0x93, 0x57, + 0x57, 0xc1, 0x28, 0xc0, 0xb2, 0x8f, 0x42, 0x7f, 0x45, 0xd2, 0x6c, 0xc3, + 0xec, 0xe7, 0x48, 0x15, 0xf5, 0xb1, 0x10, 0xf3, 0xbc, 0x0e, 0x78, 0xef, + 0x2f, 0x15, 0x65, 0x7d, 0xe4, 0x09, 0xb7, 0x34, 0x5b, 0x66, 0x24, 0x0c, + 0x93, 0x63, 0xd8, 0xdc, 0xfd, 0x47, 0x1c, 0xeb, 0x4a, 0xd3, 0x86, 0x57, + 0x49, 0xb7, 0x8e, 0x15, 0x47, 0xa1, 0x61, 0xd8, 0x0a, 0x07, 0xb0, 0x97, + 0x08, 0x48, 0x99, 0x2b, 0x88, 0xcf, 0xe5, 0xe8, 0xd3, 0xda, 0xc2, 0xae, + 0x50, 0xd6, 0xbb, 0x64, 0xbf, 0x7a, 0x1f, 0xc8, 0xbe, 0x29, 0x6e, 0x8d, + 0xf1, 0x18, 0x7c, 0xf7, 0x13, 0x78, 0xf6, 0x23, 0x35, 0x9b, 0xf8, 0xf3, + 0x42, 0x4a, 0x5d, 0xef, 0x7d, 0x20, 0x62, 0x2e, 0xa6, 0xb5, 0xce, 0x94, + 0x0a, 0xfd, 0x8b, 0xf9, 0x12, 0xea, 0x53, 0x13, 0x45, 0x9d, 0xdd, 0x66, + 0x7d, 0x42, 0xb2, 0x3f, 0x65, 0xc4, 0x0d, 0xf8, 0x6d, 0xda, 0x0e, 0xe6, + 0x45, 0x35, 0xd4, 0x90, 0xc3, 0x9b, 0x8b, 0xb4, 0x39, 0xf1, 0x4f, 0x70, + 0x4a, 0x7f, 0x51, 0x1d, 0x3d, 0x80, 0x95, 0x4b, 0xd2, 0xb0, 0xd7, 0xb7, + 0xfe, 0xa8, 0x40, 0x38, 0x95, 0x48, 0x27, 0xf8, 0x23, 0xb9, 0xb0, 0xfe, + 0x58, 0x3a, 0x8e, 0x1a, 0x53, 0xf3, 0xa4, 0x59, 0xf9, 0xba, 0x9d, 0x9d, + 0x24, 0x8b, 0xe6, 0x39, 0xc1, 0xaf, 0x86, 0xdc, 0xf7, 0x27, 0x0d, 0x0b, + 0x85, 0xc4, 0x9d, 0x25, 0xb8, 0x81, 0xd4, 0x5d, 0xc2, 0x6a, 0xe4, 0x96, + 0x42, 0x87, 0xaa, 0x67, 0x17, 0xe1, 0x23, 0xa1, 0x32, 0x62, 0xa2, 0x65, + 0x69, 0x63, 0x68, 0x61, 0x74, 0x64, 0x6b, 0x75, 0x00, 0x00, 0x00, 0x1f, + 0x7d, 0x89, 0x47, 0x47, 0xf5, 0xb7, 0xed, 0xb4, 0x95, 0xd6, 0x75, 0x78, + 0xeb, 0x1d, 0x4e, 0xa4, 0x3c, 0x47, 0x73, 0x5e, 0x8d, 0xd2, 0xd4, 0x7c, + 0xc6, 0x32, 0x4b, 0x5d, 0xc7, 0x78, 0xa2, 0xc7, 0xbd, 0xca, 0x06, 0x92, + 0xf9, 0xba, 0x4d, 0x7d, 0xe3, 0xe0, 0xf8, 0x0a, 0xec, 0x73, 0x88, 0xb6, + 0xab, 0x6d, 0x37, 0x6d, 0x37, 0xd2, 0xa5, 0x3d, 0xa8, 0xd0, 0x47, 0x7b, + 0xa1, 0x58, 0xf7, 0x07, 0x73, 0x23, 0x49, 0xfb, 0xa0, 0x7e, 0xae, 0x30, + 0x88, 0x4c, 0x2b, 0x75, 0x91, 0xd7, 0xe3, 0x5d, 0x80, 0x06, 0x12, 0xcc, + 0xb4, 0xe9, 0xdc, 0xc6, 0x01, 0x48, 0x91, 0x2a, 0x38, 0x93, 0x26, 0xee, + 0x01, 0x8a, 0xad, 0xdb, 0x02, 0xdc, 0x54, 0x5a, 0x08, 0x18, 0xf8, 0xe1, + 0xc2, 0x63, 0x80, 0x13, 0xd4, 0x4c, 0x06, 0xf0, 0x1d, 0x60, 0x66, 0x75, + 0x25, 0x43, 0xb9, 0xa1, 0x2b, 0xc7, 0x54, 0x81, 0x91, 0x2d, 0x66, 0xb2, + 0x74, 0xe7, 0x90, 0x8e, 0xd4, 0x03, 0xca, 0xef, 0x9a, 0x13, 0xfe, 0x40, + 0xf8, 0x42, 0x77, 0x52, 0x5b, 0xae, 0x22, 0xd0, 0x6b, 0xb6, 0x77, 0x41, + 0xff, 0x96, 0x80, 0xbc, 0x8f, 0xfa, 0xa1, 0xb6, 0xe4, 0xf1, 0x93, 0x1d, + 0x91, 0x96, 0x7b, 0x84, 0xc7, 0x60, 0x7e, 0x80, 0x98, 0xcd, 0x7b, 0x12, + 0x11, 0x41, 0x90, 0x33, 0x96, 0xc0, 0xeb, 0x6b, 0x9f, 0xb4, 0x1a, 0x2c, + 0x46, 0x80, 0xf0, 0x56, 0xe2, 0x4b, 0x32, 0x3c, 0x6a, 0xa1, 0x94, 0xca, + 0x46, 0xb4, 0x06, 0x63, 0x85, 0xcf, 0x62, 0x20, 0x79, 0xf2, 0x03, 0x97, + 0xa0, 0xa0, 0x44, 0x7b, 0x8e, 0x39, 0x16, 0xca, 0xe0, 0xb2, 0x04, 0x79, + 0xf8, 0x55, 0xf7, 0xe6, 0x3c, 0x3f, 0x67, 0x2f, 0x2b, 0x75, 0x39, 0x55, + 0x12, 0xd5, 0x85, 0xd4, 0x22, 0x37, 0xb6, 0x8c, 0x40, 0x47, 0x51, 0x11, + 0x88, 0xa1, 0xfa, 0x8f, 0x2d, 0x43, 0x41, 0x0a, 0x58, 0xe3, 0x38, 0x94, + 0xa0, 0xe1, 0xda, 0x1e, 0x7b, 0x07, 0x74, 0xc5, 0xe4, 0xd1, 0xb7, 0x3f, + 0xed, 0x46, 0x1e, 0x35, 0x84, 0x7c, 0x58, 0x3d, 0xc3, 0x99, 0x9f, 0x3f, + 0x0e, 0x30, 0x4f, 0xd5, 0xf4, 0x5d, 0x09, 0xef, 0x01, 0xe3, 0xa3, 0xbc, + 0x17, 0x74, 0xa4, 0x28, 0x5f, 0xab, 0xe5, 0x71, 0x66, 0x34, 0x2e, 0x29, + 0x2a, 0x24, 0xbb, 0x6d, 0x41, 0x16, 0x76, 0x86, 0x15, 0x67, 0xb5, 0x07, + 0x60, 0x13, 0xd2, 0x11, 0xa6, 0x90, 0x22, 0xc4, 0x17, 0x76, 0x38, 0x3a, + 0xaf, 0x51, 0xee, 0x4c, 0x9b, 0xfa, 0x84, 0x25, 0xd9, 0x6d, 0xd3, 0x8d, + 0x3e, 0xb2, 0x95, 0xd7, 0x8a, 0x83, 0x19, 0xaf, 0x7a, 0x2f, 0x6b, 0x87, + 0x36, 0x9e, 0xa3, 0x48, 0xdd, 0x8e, 0xe0, 0xdc, 0x40, 0xf3, 0xb7, 0xb4, + 0x3f, 0x95, 0x70, 0x5b, 0x67, 0xf7, 0xa1, 0xe9, 0x91, 0x7a, 0x94, 0xd1, + 0x81, 0xcc, 0xeb, 0x55, 0xb7, 0xc6, 0xd9, 0x0d, 0x59, 0x4a, 0x9f, 0x37, + 0x06, 0x6a, 0xda, 0x4e, 0xd3, 0xef, 0x35, 0x18, 0xa3, 0x90, 0x19, 0x72, + 0x2e, 0xcd, 0x03, 0x61, 0xf7, 0xb2, 0x0f, 0x69, 0x50, 0x47, 0x2f, 0xb3, + 0x10, 0x4a, 0xb1, 0x5d, 0xe8, 0x5a, 0x36, 0x07, 0xd6, 0x95, 0x03, 0x17, + 0x50, 0x1f, 0xa2, 0x58, 0x01, 0x0d, 0xfc, 0x8d, 0xcc, 0xf2, 0x6c, 0x4d, + 0x2f, 0x58, 0x02, 0xb6, 0x5e, 0x7c, 0x6f, 0x47, 0x3e, 0x13, 0x62, 0x33, + 0xc3, 0x7f, 0x64, 0x88, 0x30, 0x45, 0x5a, 0x6a, 0x8f, 0x49, 0x9a, 0xd1, + 0x6e, 0xf4, 0x3a, 0x3a, 0x9b, 0x50, 0x50, 0x8b, 0x59, 0x36, 0xbc, 0x0c, + 0x2c, 0x73, 0xec, 0x21, 0x0c, 0x95, 0xca, 0x32, 0x28, 0x07, 0x85, 0x91, + 0x0a, 0x90, 0xfe, 0x5a, 0x9d, 0x11, 0x09, 0xa2, 0x38, 0x9b, 0x0f, 0x22, + 0xc1, 0x44, 0x09, 0xca, 0x50, 0xe0, 0x4e, 0x01, 0x24, 0xef, 0x8a, 0x58, + 0xa5, 0x56, 0x69, 0x9b, 0x2e, 0x72, 0xf5, 0xb2, 0xbe, 0xa3, 0xca, 0x84, + 0x36, 0x36, 0x84, 0xb0, 0x88, 0x88, 0x74, 0x60, 0xc3, 0xf2, 0x6b, 0x19, + 0x44, 0xb6, 0x8b, 0x02, 0x38, 0x7d, 0x6e, 0x26, 0x89, 0x37, 0xae, 0xc5, + 0x67, 0x9c, 0x4e, 0x5b, 0xeb, 0x68, 0xc1, 0x3a, 0xb9, 0x10, 0xad, 0x10, + 0x00, 0x1f, 0x6a, 0x9a, 0xfe, 0x6a, 0x7e, 0x03, 0xcc, 0x7d, 0x0d, 0x37, + 0xea, 0x91, 0xfa, 0xf4, 0xdb, 0x22, 0x9b, 0x91, 0x70, 0x07, 0x6d, 0xa8, + 0xd6, 0x95, 0x49, 0x66, 0xd6, 0xbc, 0xd1, 0x57, 0x6e, 0xa5, 0x1c, 0x96, + 0x16, 0xaf, 0x94, 0xa5, 0x00, 0x06, 0x38, 0x55, 0xe9, 0xdc, 0xb8, 0x38, + 0x66, 0x26, 0x2d, 0xac, 0x1a, 0xff, 0x95, 0x52, 0xa3, 0x97, 0x58, 0xd9, + 0xe9, 0x35, 0x54, 0x3d, 0x6a, 0xae, 0xe6, 0xcd, 0x00, 0xbe, 0x68, 0x83, + 0x05, 0x5a, 0x65, 0xb8, 0x8c, 0x94, 0x87, 0x6c, 0x27, 0x82, 0x7b, 0x4a, + 0x48, 0x1e, 0x6e, 0x42, 0xc1, 0xe5, 0xd8, 0x25, 0x9b, 0x8a, 0xe4, 0x2b, + 0x85, 0x6f, 0x40, 0x75, 0x65, 0x9e, 0xc5, 0x03, 0xd1, 0x14, 0x82, 0x91, + 0x15, 0x59, 0x66, 0x48, 0x13, 0xfe, 0xd3, 0x17, 0x1e, 0xff, 0xec, 0x58, + 0x43, 0xb5, 0xb9, 0xbf, 0xad, 0x33, 0xb2, 0x91, 0xe2, 0xb5, 0x3b, 0x57, + 0xd6, 0xb1, 0x55, 0x6c, 0xa2, 0xac, 0x7f, 0x5e, 0x9b, 0x28, 0xa7, 0x98, + 0x44, 0x46, 0x1d, 0x30, 0x16, 0x2f, 0xa5, 0x35, 0x85, 0x68, 0xaa, 0x92, + 0x0f, 0x51, 0xb3, 0x88, 0x42, 0xf3, 0x8d, 0xa0, 0x06, 0x8f, 0x91, 0xcf, + 0xf4, 0x8f, 0xbc, 0x95, 0xb1, 0x57, 0xa5, 0x61, 0xd9, 0x1e, 0x40, 0x29, + 0x79, 0x63, 0x84, 0xfd, 0xf5, 0x93, 0xd4, 0x5b, 0xb9, 0xdf, 0x5d, 0x56, + 0xc5, 0xfb, 0xcb, 0xee, 0x1f, 0x3b, 0x9c, 0x02, 0x0c, 0x7d, 0x7f, 0xbb, + 0x81, 0x8d, 0xbb, 0xa5, 0x83, 0x5c, 0x4f, 0xf1, 0x08, 0xf8, 0x18, 0x87, + 0xab, 0x74, 0x5c, 0xa7, 0x57, 0xa8, 0xcf, 0xf4, 0x2f, 0xcc, 0xd2, 0xcc, + 0x5b, 0x99, 0x00, 0xbc, 0xe5, 0x06, 0x42, 0x24, 0xc9, 0xf0, 0x23, 0x45, + 0x60, 0xf1, 0x34, 0xb0, 0x99, 0xb4, 0x24, 0x94, 0x71, 0x76, 0x16, 0x32, + 0x2d, 0xb5, 0x98, 0x38, 0x9e, 0x02, 0xe4, 0x1b, 0xc9, 0x3f, 0x20, 0xa3, + 0x94, 0xc2, 0x4c, 0xff, 0x81, 0x95, 0x05, 0xd5, 0x8c, 0x13, 0xd2, 0xb8, + 0x54, 0xf5, 0x55, 0xff, 0x4a, 0xfa, 0xd0, 0x93, 0xa7, 0x49, 0x5f, 0x43, + 0x6d, 0x23, 0x3e, 0x5f, 0x37, 0xb1, 0x05, 0xb1, 0xc7, 0x99, 0xb5, 0xab, + 0xbe, 0x04, 0x65, 0xef, 0xb0, 0x79, 0x62, 0x47, 0xbc, 0x7b, 0x57, 0x74, + 0xea, 0xac, 0x2d, 0x45, 0xfc, 0x65, 0x26, 0x3d, 0xf7, 0x91, 0x0e, 0xbd, + 0x78, 0x78, 0x72, 0x6b, 0x8a, 0xfe, 0x8d, 0x6e, 0x03, 0x6d, 0x0c, 0x3a, + 0x52, 0xb5, 0xc4, 0x9c, 0x7d, 0x82, 0xdd, 0x52, 0x75, 0xb7, 0xe3, 0xe3, + 0xff, 0xfc, 0x31, 0xa9, 0xc6, 0xd7, 0xa4, 0x1d, 0x05, 0xde, 0x8b, 0x82, + 0x1d, 0x7d, 0xd0, 0xb3, 0x25, 0xcc, 0x45, 0xce, 0x8e, 0x4c, 0x2b, 0xca, + 0x60, 0x15, 0x6c, 0xba, 0x5d, 0x6b, 0x41, 0x22, 0x62, 0x05, 0xef, 0x55, + 0x04, 0x84, 0x2e, 0x14, 0xe6, 0x5e, 0x23, 0x83, 0x82, 0x39, 0xbe, 0x79, + 0xd1, 0x29, 0xe3, 0xac, 0x54, 0x63, 0x03, 0xf9, 0xa0, 0xb7, 0xb7, 0xd4, + 0x37, 0xdc, 0x91, 0xfc, 0x1e, 0x96, 0xe9, 0xcc, 0x66, 0x6b, 0xa4, 0x67, + 0xb8, 0xc8, 0xed, 0x69, 0x4f, 0x08, 0xa2, 0xaf, 0x34, 0x3b, 0xcb, 0x70, + 0xf2, 0x8c, 0xae, 0xc9, 0x2e, 0x96, 0xe3, 0x47, 0x31, 0x36, 0x13, 0x62, + 0xc8, 0xcc, 0x18, 0x7f, 0x48, 0xea, 0x2e, 0xf4, 0x87, 0x09, 0xa2, 0x68, + 0x19, 0xf7, 0x30, 0x8b, 0x72, 0x65, 0xa6, 0x9f, 0xf3, 0x96, 0x22, 0x68, + 0x59, 0x72, 0x69, 0x2f, 0xdd, 0x88, 0x4c, 0x04, 0xd2, 0xb9, 0x71, 0x0c, + 0xd7, 0x2d, 0xd7, 0xef, 0xce, 0x33, 0x7f, 0x5a, 0xe7, 0x80, 0xba, 0x85, + 0xc0, 0xd3, 0x83, 0x27, 0xe9, 0x11, 0x40, 0x67, 0xb7, 0xf7, 0x8f, 0x8e, + 0x8f, 0x93, 0x7d, 0xfb, 0x04, 0x0f, 0x1e, 0x6d, 0xd7, 0xa9, 0xc6, 0x53, + 0x29, 0x58, 0x55, 0xe5, 0x2d, 0xe1, 0x05, 0xe3, 0x00, 0x3b, 0x6f, 0xb9, + 0xdd, 0x5f, 0x42, 0x47, 0x0a, 0x79, 0x43, 0xef, 0x84, 0x47, 0x6d, 0x37, + 0xba, 0x37, 0xb3, 0xef, 0xae, 0x0b, 0xc9, 0x45, 0x32, 0x1a, 0x9a, 0x94, + 0x3f, 0xb8, 0xc7, 0x72, 0xd8, 0x90, 0xb1, 0x61, 0x62, 0xe0, 0x0f, 0xd1, + 0xef, 0x94, 0x04, 0x2f, 0xff, 0xd6, 0x7e, 0x14, 0x81, 0xb8, 0x62, 0xcc, + 0x4e, 0x76, 0x0a, 0xc6, 0x1f, 0x58, 0x51, 0xa1, 0x14, 0xe8, 0xde, 0x2f, + 0xe6, 0x2e, 0xb2, 0xe2, 0xda, 0x24, 0x47, 0xe1, 0xcf, 0x26, 0x2a, 0xfc, + 0xb1, 0xbf, 0xae, 0x1a, 0xb0, 0x4d, 0x3d, 0x97, 0x4d, 0x18, 0xfb, 0x0d, + 0x00, 0x64, 0x40, 0x75, 0x6a, 0x78, 0x3a, 0x60, 0xda, 0x54, 0x06, 0x92, + 0xb6, 0xa9, 0x1c, 0x36, 0xeb, 0x26, 0x46, 0x10, 0x0d, 0x5d, 0x3e, 0x13, + 0xca, 0x7e, 0xb1, 0xbb, 0xa7, 0x37, 0x71, 0x7c, 0x09, 0xd4, 0x5d, 0xd4, + 0x59, 0xb0, 0x46, 0x37, 0x06, 0x2a, 0xdb, 0xd3, 0x0c, 0x26, 0x0a, 0x9d, + 0x18, 0x65, 0x8a, 0xb4, 0xf1, 0x1b, 0xfd, 0x50, 0x32, 0x6a, 0xa9, 0x2f, + 0x0c, 0x46, 0x1f, 0x9b, 0x50, 0x86, 0xf1, 0x91, 0xf0, 0xe0, 0xc2, 0x8d, + 0x84, 0x8e, 0xfe, 0x6d, 0x1e, 0x6e, 0xd4, 0x93, 0xf1, 0x56, 0x4b, 0x3b, + 0x20, 0x10, 0x1f, 0x6a, 0xc5, 0xf3, 0x8c, 0x2f, 0x88, 0x32, 0x28, 0xbe, + 0x05, 0x9a, 0x1b, 0x7d, 0x1b, 0xaa, 0x2d, 0xa5, 0xe4, 0x82, 0xd0, 0xf3, + 0x65, 0x5a, 0xd5, 0xa5, 0x3e, 0xdd, 0xee, 0x98, 0x03, 0xf4, 0x63, 0x6e, + 0xe5, 0x60, 0x35, 0x54, 0xf9, 0xf8, 0x5c, 0x8c, 0x02, 0x5f, 0xa5, 0xf3, + 0xb2, 0xf8, 0x47, 0xce, 0x74, 0xbc, 0xf5, 0xcc, 0x1e, 0x0f, 0x8b, 0x6f, + 0x1f, 0xd3, 0x11, 0x2d, 0x10, 0x40, 0x5d, 0xb2, 0x45, 0x6f, 0xd3, 0xc3, + 0x44, 0xc5, 0x74, 0xab, 0x29, 0x2f, 0x4c, 0x7e, 0xc8, 0x57, 0xcb, 0xaf, + 0x0b, 0x44, 0x12, 0xa2, 0x1d, 0x3b, 0x1c, 0xfa, 0xf5, 0xd3, 0xe6, 0x75, + 0x4e, 0xc7, 0x04, 0x99, 0xd8, 0x32, 0x14, 0x83, 0xda, 0x35, 0xf0, 0xfa, + 0x67, 0x15, 0x8d, 0xab, 0xa9, 0x30, 0x12, 0xd0, 0x4a, 0xb6, 0x09, 0x20, + 0x89, 0x19, 0xee, 0x60, 0x4b, 0x97, 0xd2, 0x38, 0x2a, 0x57, 0x36, 0x22, + 0xe9, 0x02, 0x2f, 0x2d, 0x30, 0x93, 0x88, 0x14, 0x99, 0xa3, 0x31, 0x93, + 0x2a, 0x33, 0x58, 0xae, 0xe6, 0xe6, 0xcc, 0x89, 0x02, 0x95, 0x52, 0xe3, + 0x60, 0xed, 0xd5, 0x9d, 0xac, 0x7f, 0x1f, 0x35, 0x54, 0xd6, 0x89, 0x8e, + 0xed, 0x13, 0x7f, 0xe6, 0xce, 0xba, 0xe7, 0x00, 0x30, 0x7f, 0x46, 0x25, + 0xdc, 0xb3, 0x22, 0xac, 0xef, 0x54, 0xef, 0x17, 0xf8, 0xdc, 0xc4, 0x12, + 0xdb, 0x40, 0xe8, 0x20, 0x7a, 0x1b, 0x5a, 0x6b, 0x37, 0x8d, 0x46, 0xfd, + 0x26, 0xa5, 0x1f, 0x24, 0xb3, 0xaa, 0xe4, 0xb6, 0x1c, 0x93, 0xd9, 0x77, + 0xc2, 0x66, 0xf7, 0x0a, 0xf8, 0xca, 0xa1, 0xfb, 0xa6, 0x78, 0x9c, 0xc3, + 0x7f, 0x40, 0x63, 0x9a, 0x98, 0x52, 0x23, 0xb2, 0x51, 0x0f, 0xab, 0xf2, + 0xa0, 0x41, 0x87, 0x79, 0x18, 0x2e, 0x50, 0x8a, 0x6a, 0x99, 0xc7, 0xef, + 0x0c, 0x33, 0xee, 0xf2, 0x76, 0x26, 0x40, 0x4b, 0xb7, 0x75, 0xb0, 0x8c, + 0x99, 0x8c, 0x96, 0x8a, 0xc3, 0xb6, 0xfd, 0xa2, 0x62, 0x49, 0x29, 0x8c, + 0xc4, 0xfe, 0xc8, 0xe9, 0x89, 0xeb, 0xc7, 0x59, 0x08, 0x99, 0xd3, 0x73, + 0xea, 0x64, 0x50, 0x9d, 0x09, 0x36, 0xe3, 0x85, 0xc4, 0xac, 0x3e, 0x87, + 0x11, 0x5d, 0xf4, 0x5b, 0x21, 0x91, 0xf6, 0x34, 0xfb, 0x08, 0x15, 0xd2, + 0xe1, 0xcb, 0x8c, 0x72, 0xca, 0x88, 0xd6, 0xb1, 0x65, 0xd4, 0xd7, 0x6e, + 0x10, 0x7b, 0x15, 0x0f, 0x41, 0xd7, 0x12, 0x49, 0xcc, 0x8d, 0x39, 0x13, + 0x9c, 0x22, 0x1d, 0x15, 0x43, 0xc1, 0x8a, 0x6f, 0xf3, 0x1d, 0x46, 0x74, + 0xb3, 0x1f, 0xa4, 0xbd, 0x17, 0x20, 0x69, 0x57, 0x53, 0x2c, 0x6a, 0xec, + 0x29, 0xac, 0x02, 0xb1, 0x47, 0x83, 0xf0, 0x2f, 0xc9, 0x20, 0xcc, 0x14, + 0xf0, 0xe4, 0x4f, 0x43, 0xe1, 0x98, 0x3d, 0xbd, 0x2c, 0x48, 0x7f, 0xd5, + 0xd6, 0x33, 0x98, 0xd2, 0x9d, 0xa8, 0xe0, 0xb1, 0x85, 0xe0, 0x14, 0x96, + 0xec, 0xde, 0x18, 0xc4, 0xe9, 0x8f, 0x67, 0x24, 0x48, 0x6c, 0xf9, 0xaf, + 0xfb, 0x89, 0xd1, 0x35, 0xc9, 0x0d, 0xe9, 0x22, 0x08, 0xef, 0x8b, 0x27, + 0x9d, 0x18, 0xa1, 0x19, 0x7d, 0x20, 0xd1, 0xc1, 0x1b, 0x99, 0x59, 0xea, + 0xba, 0xae, 0xe4, 0x09, 0xd4, 0xb6, 0x23, 0x08, 0x5f, 0x0c, 0x0b, 0x49, + 0x69, 0x8a, 0x36, 0x02, 0xf5, 0x32, 0x3e, 0xfb, 0xb4, 0xdb, 0x45, 0x9d, + 0x19, 0x9d, 0x4b, 0xcf, 0xee, 0xa7, 0xbc, 0x5a, 0x06, 0x4e, 0x43, 0x52, + 0xd3, 0xd2, 0x4a, 0x0e, 0x21, 0x08, 0xd6, 0xc0, 0x93, 0x7d, 0xe8, 0xff, + 0x04, 0xd4, 0xef, 0xe8, 0x0d, 0xd1, 0xe7, 0x74, 0xf2, 0x56, 0x66, 0x51, + 0x4c, 0x79, 0xf4, 0x12, 0x9f, 0xf4, 0xd2, 0x61, 0x12, 0x60, 0xc2, 0xfb, + 0x98, 0x5c, 0xed, 0x73, 0x13, 0x06, 0xa7, 0xce, 0x86, 0xea, 0x65, 0x26, + 0xc0, 0xfc, 0xe6, 0xc1, 0xdb, 0xe0, 0xcc, 0x13, 0xd3, 0x63, 0x5f, 0x2d, + 0xfb, 0x5a, 0x95, 0x9e, 0x27, 0x05, 0x3d, 0xd0, 0x1b, 0xaf, 0x29, 0x79, + 0x70, 0x69, 0x12, 0xc7, 0xe6, 0xc2, 0x57, 0x40, 0x31, 0xcb, 0x50, 0xd4, + 0xfe, 0xf3, 0xb1, 0x3e, 0x79, 0xdb, 0xcf, 0xdd, 0x9a, 0x86, 0x2a, 0x58, + 0xb3, 0x51, 0xe6, 0x74, 0x9f, 0x1e, 0xbd, 0xb1, 0x57, 0xd8, 0xa9, 0xe8, + 0xbf, 0x5e, 0x15, 0xcf, 0x2c, 0x4b, 0x00, 0x88, 0x8d, 0x10, 0x15, 0x25, + 0xeb, 0x36, 0xe6, 0x4b, 0x9c, 0xe5, 0x82, 0x26, 0x6e, 0x61, 0xb3, 0x69, + 0xf4, 0x4c, 0x21, 0x15, 0x64, 0x36, 0x0c, 0x8e, 0x77, 0xc1, 0x89, 0xd5, + 0xfd, 0xb0, 0x81, 0x7c, 0x90, 0x7d, 0xdf, 0xd3, 0xe5, 0xc9, 0xd8, 0x4f, + 0xc5, 0x85, 0x12, 0xb7, 0x02, 0x63, 0xb7, 0x24, 0x2c, 0xeb, 0xb5, 0x89, + 0x59, 0x44, 0x2b, 0xa3, 0x8e, 0xfd, 0x42, 0x48, 0x57, 0x57, 0x17, 0x71, + 0xec, 0xe0, 0x0e, 0x72, 0xfc, 0x6c, 0xa2, 0xa5, 0xfb, 0xd3, 0x17, 0xb7, + 0x1a, 0x19, 0xe4, 0x93, 0x22, 0x4d, 0xde, 0x22, 0x4f, 0xb8, 0x42, 0x3a, + 0x06, 0xa7, 0x35, 0x20, 0x57, 0xc4, 0xe6, 0x0c, 0x7f, 0xae, 0x59, 0xfe, + 0xe6, 0xe7, 0x17, 0x0c, 0xec, 0x33, 0x4d, 0x6e, 0x0a, 0xd8, 0x6e, 0xe2, + 0x27, 0x39, 0x3e, 0x32, 0x1b, 0xf8, 0x9d, 0xd5, 0xdb, 0x38, 0xee, 0xe6, + 0x58, 0xbf, 0xfa, 0x05, 0xc0, 0x7e, 0xf1, 0x70, 0x43, 0x8d, 0xc5, 0x5f, + 0xd1, 0xb8, 0x5f, 0xe2, 0xb4, 0xd7, 0x81, 0xd7, 0x04, 0x8d, 0x06, 0x99, + 0x7f, 0x0b, 0x87, 0xea, 0xe3, 0x9a, 0x51, 0xd4, 0xd4, 0x47, 0xeb, 0x29, + 0x98, 0x56, 0xa7, 0x2f, 0x07, 0xa3, 0x04, 0x88, 0xe9, 0x13, 0x4f, 0xac, + 0x0f, 0x29, 0xda, 0xc7, 0x53, 0x2c, 0x9d, 0x00, 0x7a, 0x9e, 0x7a, 0x74, + 0xac, 0xce, 0xf2, 0xfa, 0xe6, 0xd5, 0xa2, 0x0c, 0xab, 0x80, 0xa9, 0x9f, + 0x46, 0x39, 0xe6, 0x8c, 0xc8, 0xf3, 0x90, 0xca, 0x9e, 0xb6, 0xdd, 0x0c, + 0xf9, 0xe6, 0x8c, 0x83, 0x46, 0xb0, 0x12, 0xe3, 0x47, 0xba, 0x12, 0x7b, + 0xf5, 0xb7, 0xe6, 0x49, 0x8c, 0x78, 0x45, 0xc2, 0xa3, 0x7a, 0xdf, 0x47, + 0xa9, 0x80, 0x41, 0x03, 0x29, 0x7f, 0xeb, 0xa1, 0xa8, 0x4b, 0x4f, 0xa8, + 0x41, 0x57, 0xb9, 0xfe, 0x06, 0xa9, 0xce, 0xbc, 0x27, 0x81, 0xed, 0x1b, + 0xab, 0x19, 0x4a, 0xbf, 0x6b, 0xe0, 0xef, 0x58, 0xfb, 0xfa, 0xe3, 0xa1, + 0x85, 0x02, 0x0d, 0x57, 0x9b, 0x04, 0x2b, 0xc0, 0x8e, 0x21, 0x73, 0xdc, + 0x34, 0x21, 0x63, 0x1d, 0xaf, 0xd8, 0xe0, 0x42, 0xaa, 0x45, 0xe9, 0x3c, + 0x44, 0xc5, 0x22, 0x77, 0xc0, 0xe5, 0xa5, 0xf7, 0xa4, 0x83, 0x66, 0xad, + 0xc7, 0x4a, 0x32, 0xc6, 0x7e, 0xca, 0x8f, 0x35, 0xa7, 0x88, 0x64, 0x56, + 0x45, 0x25, 0xec, 0xfa, 0x85, 0x61, 0x34, 0x0d, 0x83, 0x92, 0x1e, 0xf0, + 0x58, 0x4c, 0x47, 0x93, 0xe5, 0x17, 0xaa, 0xe8, 0x22, 0x53, 0xa6, 0x9e, + 0x3d, 0xb1, 0x47, 0x25, 0x09, 0x93, 0x93, 0x9d, 0x08, 0x31, 0x5b, 0xdc, + 0x07, 0x1f, 0x82, 0xbc, 0x88, 0x31, 0xbd, 0xc3, 0xa6, 0x4d, 0x2a, 0xed, + 0xf9, 0xc2, 0x76, 0x1e, 0xa1, 0xfd, 0xca, 0x7e, 0xcd, 0x62, 0x83, 0x06, + 0xca, 0xf3, 0x13, 0xcd, 0x25, 0xa1, 0x45, 0x0c, 0x3a, 0xc3, 0xb1, 0x3b, + 0xf5, 0xa1, 0x12, 0x1e, 0x90, 0xff, 0xf6, 0x56, 0x06, 0x7b, 0x14, 0xb7, + 0x37, 0x5c, 0x7a, 0xe9, 0x7e, 0xca, 0x33, 0x05, 0xc0, 0x7c, 0xa7, 0xcd, + 0xb2, 0x11, 0x2a, 0x0c, 0xe7, 0x2b, 0x36, 0x11, 0x5f, 0xa6, 0xba, 0xc5, + 0x56, 0x6f, 0x7c, 0xb7, 0x8c, 0xee, 0x54, 0xa0, 0x8c, 0x59, 0x85, 0x22, + 0x98, 0xad, 0xbb, 0x93, 0x66, 0x23, 0xfa, 0x00, 0x81, 0x88, 0xb0, 0x0a, + 0x1d, 0xfb, 0x66, 0xa2, 0x14, 0x88, 0x2a, 0x4e, 0x41, 0xb4, 0x89, 0x91, + 0x6d, 0x73, 0x5a, 0x3c, 0x4f, 0xc9, 0xd3, 0xa3, 0x08, 0x10, 0xe0, 0xb2, + 0xc2, 0xda, 0xa1, 0x23, 0x91, 0x40, 0x92, 0x51, 0xa0, 0xf4, 0x92, 0x01, + 0xb1, 0xa7, 0xd1, 0x80, 0x1d, 0xf0, 0x30, 0x29, 0xed, 0x0b, 0xec, 0x80, + 0x02, 0x09, 0x4e, 0x8d, 0x3f, 0xdf, 0x7a, 0x53, 0xcf, 0xed, 0xad, 0x6c, + 0x1b, 0x9c, 0x6a, 0x25, 0xff, 0xc3, 0xd7, 0xe9, 0x99, 0xf8, 0xa6, 0x8d, + 0x3f, 0x4a, 0x17, 0xf1, 0xe4, 0x54, 0x2b, 0x55, 0x67, 0x4a, 0xd2, 0xee, + 0x29, 0x53, 0x44, 0x71, 0x87, 0x6c, 0x98, 0xef, 0x8f, 0x23, 0x06, 0xf5, + 0x56, 0x9d, 0x12, 0x1f, 0x9c, 0xe5, 0x22, 0x51, 0x6e, 0x5b, 0x41, 0x7e, + 0x89, 0x6f, 0x40, 0x4b, 0xd6, 0x81, 0xd1, 0x7f, 0x63, 0xd1, 0x3f, 0xa1, + 0x60, 0xe2, 0xe4, 0x01, 0x7b, 0x76, 0x86, 0xf5, 0x13, 0x4f, 0xa2, 0x50, + 0xaf, 0xc8, 0x74, 0xe3, 0x2f, 0x7a, 0xd0, 0x81, 0x3e, 0xcf, 0xfa, 0x31, + 0xeb, 0xc0, 0xc3, 0x07, 0xc7, 0xe8, 0xb2, 0x9a, 0x51, 0xb9, 0xf7, 0x98, + 0x55, 0x90, 0xce, 0xdd, 0x60, 0xac, 0xc9, 0x08, 0x5e, 0xe8, 0xae, 0xad, + 0x22, 0xed, 0x73, 0x29, 0xa1, 0x5f, 0x43, 0x27, 0x2f, 0xb9, 0x38, 0x78, + 0x9d, 0x32, 0x1f, 0xff, 0xe0, 0xf7, 0x77, 0x37, 0xdf, 0xd1, 0xcb, 0xf7, + 0x50, 0xcd, 0x4a, 0xe9, 0xdd, 0x21, 0x50, 0xa0, 0xf2, 0x7f, 0x73, 0x31, + 0xae, 0xfb, 0x6e, 0xb7, 0x99, 0x1a, 0x43, 0x16, 0x5a, 0x17, 0x3a, 0x77, + 0xf1, 0xc3, 0xa8, 0x33, 0xde, 0xc6, 0x5b, 0xe8, 0x59, 0x53, 0x19, 0xf9, + 0x7f, 0xc5, 0x20, 0x56, 0xfc, 0x99, 0x19, 0x38, 0x77, 0x92, 0xe4, 0x7c, + 0xf3, 0x96, 0xac, 0x22, 0x87, 0x16, 0x5d, 0x43, 0x43, 0x65, 0x4e, 0x46, + 0x45, 0x44, 0x2d, 0x3f, 0x7f, 0x9d, 0xf0, 0x0c, 0x0e, 0x5b, 0xf7, 0x5b, + 0x31, 0x71, 0xcd, 0x27, 0x5b, 0xa3, 0x4a, 0x7a, 0xef, 0x28, 0x1c, 0x9a, + 0x98, 0x26, 0x95, 0xda, 0x35, 0x8d, 0x0d, 0xce, 0x04, 0xa2, 0xed, 0x8a, + 0xbb, 0x46, 0xf7, 0xca, 0x2b, 0x92, 0xd7, 0x8d, 0xae, 0x1b, 0xf1, 0xe4, + 0x9d, 0x67, 0x5b, 0x03, 0x57, 0xd1, 0xf6, 0x1e, 0x8f, 0x03, 0x7d, 0x8d, + 0xb8, 0x4a, 0x74, 0x99, 0x0f, 0x76, 0x3d, 0xe7, 0xb3, 0x4f, 0xdb, 0x9f, + 0x5c, 0xa7, 0x1b, 0x23, 0xa7, 0x99, 0x48, 0x34, 0x65, 0x46, 0x32, 0x83, + 0xc8, 0xcb, 0xee, 0xb3, 0xab, 0xe8, 0x99, 0xc9, 0x8a, 0x50, 0x34, 0x15, + 0x13, 0x52, 0xda, 0x12, 0xbd, 0x20, 0x21, 0x41, 0x57, 0x2a, 0xa0, 0x2c, + 0xba, 0x6c, 0xa9, 0xed, 0xcb, 0x03, 0xc9, 0x10, 0x26, 0x9d, 0x31, 0x52, + 0xf2, 0x66, 0x88, 0x2e, 0x51, 0x80, 0x76, 0xc9, 0xce, 0xfb, 0x8a, 0x4a, + 0x10, 0x8c, 0x83, 0x34, 0xe9, 0x02, 0xfc, 0x4e, 0xfe, 0xaa, 0x6c, 0xd6, + 0xcc, 0x81, 0x5d, 0x45, 0xc8, 0xa6, 0xa0, 0x3a, 0xef, 0xa4, 0xc5, 0xf1, + 0xba, 0x32, 0x93, 0x12, 0x2b, 0x59, 0x68, 0x19, 0x21, 0xe8, 0xd2, 0x8f, + 0x1d, 0x38, 0xd3, 0x56, 0x54, 0x38, 0x1d, 0xbb, 0xa0, 0x69, 0xe4, 0x82, + 0xfc, 0x21, 0x55, 0xee, 0xf8, 0x84, 0x7b, 0xab, 0x5e, 0x83, 0x42, 0x7e, + 0x18, 0xab, 0x3b, 0x1b, 0xea, 0x0e, 0xa0, 0xbd, 0x74, 0x33, 0x6d, 0x8a, + 0xe6, 0x7f, 0xe9, 0x78, 0xcf, 0xc9, 0xfd, 0xb6, 0x95, 0x90, 0x0e, 0x76, + 0x1a, 0xce, 0xb5, 0x72, 0x3f, 0x48, 0xa2, 0xcc, 0x6b, 0xf6, 0x6e, 0x72, + 0xef, 0x0c, 0x5f, 0x1b, 0xb4, 0x61, 0x5d, 0xf2, 0xc3, 0x9f, 0x09, 0x5b, + 0x60, 0xd8, 0xfd, 0xb0, 0x12, 0xe3, 0xc3, 0xeb, 0x4a, 0x5b, 0x26, 0xf8, + 0x5c, 0xfe, 0xd8, 0x93, 0xf1, 0xc8, 0x38, 0x29, 0x2c, 0xfe, 0x76, 0xf8, + 0xf5, 0x7b, 0x1b, 0x48, 0x6e, 0x27, 0xc3, 0xc8, 0xba, 0x23, 0xa8, 0x23, + 0xa3, 0xae, 0x48, 0x24, 0x83, 0x13, 0x6c, 0xbb, 0xfe, 0x7c, 0x36, 0xf7, + 0x7e, 0xe6, 0x1b, 0xd8, 0x86, 0x39, 0xc1, 0x84, 0x89, 0x2d, 0x0e, 0x80, + 0x3f, 0xb9, 0x5f, 0x25, 0x05, 0x85, 0xfa, 0x34, 0x23, 0xb9, 0xfa, 0xa2, + 0x2b, 0xaa, 0x40, 0x6d, 0xd3, 0x9b, 0xc9, 0x6a, 0xf7, 0xe8, 0x60, 0x2b, + 0x38, 0xe2, 0x79, 0xc9, 0x37, 0x62, 0x7d, 0xe0, 0x7a, 0xb5, 0xc6, 0x1f, + 0x80, 0xb1, 0xba, 0x4a, 0xdc, 0x65, 0x99, 0x0d, 0xe4, 0xae, 0x7f, 0x79, + 0x27, 0x93, 0xe6, 0x89, 0xbf, 0xb6, 0xeb, 0x8b, 0x1d, 0xfc, 0xb2, 0x8f, + 0x41, 0x0d, 0x0d, 0xa6, 0x20, 0x8f, 0x14, 0xf7, 0x33, 0x0c, 0xbb, 0x79, + 0xa4, 0xf3, 0x03, 0x23, 0xe9, 0xa3, 0x0a, 0x8b, 0xc2, 0xa6, 0xe3, 0xd3, + 0xaf, 0x11, 0xd3, 0x00, 0xfe, 0x84, 0x36, 0x8e, 0x51, 0x62, 0x00, 0x8a, + 0xaf, 0x45, 0x34, 0xc7, 0x96, 0xc1, 0x48, 0x5f, 0xd7, 0xc4, 0xa1, 0x2e, + 0xf6, 0x86, 0x0e, 0x74, 0xfd, 0x0f, 0x2d, 0x70, 0x9a, 0x83, 0xa6, 0x47, + 0x91, 0x50, 0x9e, 0xf7, 0xbe, 0x00, 0xce, 0xe1, 0xe0, 0x93, 0x47, 0x0f, + 0x3c, 0x2b, 0x1b, 0x68, 0x34, 0x07, 0xc4, 0x28, 0x8f, 0x66, 0xb9, 0xb6, + 0xad, 0xfc, 0x53, 0x42, 0xbb, 0x21, 0x00, 0x35, 0xe7, 0x74, 0xd8, 0x36, + 0x66, 0x7c, 0x54, 0xc2, 0x59, 0xe4, 0x11, 0x52, 0x8f, 0xdb, 0xb5, 0x46, + 0xe6, 0xb3, 0x16, 0x6a, 0xf5, 0x79, 0x51, 0x11, 0x56, 0x13, 0xa9, 0xfe, + 0x39, 0xe7, 0xfe, 0x27, 0x86, 0x05, 0x2a, 0xde, 0x90, 0x43, 0xa3, 0x84, + 0x41, 0x78, 0x24, 0xfb, 0xe3, 0x4f, 0x42, 0xc1, 0x56, 0x65, 0x45, 0xab, + 0x8d, 0x69, 0x42, 0x6d, 0x44, 0x22, 0x19, 0x50, 0x43, 0x73, 0x52, 0x34, + 0xdd, 0xb9, 0xcf, 0x78, 0xe7, 0x81, 0xa7, 0x3a, 0x51, 0xe3, 0x9e, 0xc4, + 0x38, 0xa3, 0x03, 0x2c, 0xe6, 0x45, 0x67, 0x70, 0xc7, 0xc5, 0x4c, 0x50, + 0xf7, 0x68, 0x52, 0x7f, 0x08, 0x94, 0x78, 0xd7, 0xb8, 0x8c, 0xb2, 0x56, + 0x45, 0x90, 0x65, 0xd3, 0x55, 0x1c, 0x20, 0x9c, 0x3c, 0x54, 0x96, 0xf3, + 0x45, 0x42, 0x9b, 0x1b, 0x20, 0xab, 0xc7, 0x1e, 0x73, 0x85, 0x6d, 0x03, + 0x0e, 0xc7, 0x17, 0xc5, 0xf6, 0x02, 0x10, 0x3b, 0x54, 0x2c, 0x17, 0x5c, + 0x08, 0xa2, 0xd6, 0x2e, 0xcc, 0x18, 0x9b, 0x71, 0x60, 0xba, 0xdb, 0xae, + 0x18, 0x54, 0x57, 0xd0, 0x30, 0xda, 0xe9, 0x15, 0x5f, 0x90, 0x43, 0x52, + 0xd9, 0xf5, 0xb6, 0x4e, 0x5b, 0x83, 0x83, 0xaa, 0xc0, 0x16, 0xe2, 0xa9, + 0x5f, 0x31, 0x30, 0x79, 0x87, 0x9d, 0x0c, 0xd8, 0xf2, 0xdb, 0x4e, 0x3e, + 0xe6, 0xd9, 0xc9, 0x17, 0xb7, 0x11, 0x8d, 0x9c, 0x72, 0x17, 0x45, 0xde, + 0x2b, 0x6a, 0xc7, 0x60, 0x79, 0x3f, 0xbe, 0xf8, 0xdd, 0x47, 0x07, 0x66, + 0x24, 0xe3, 0xa6, 0x00, 0x91, 0xa2, 0x6f, 0x6d, 0xbf, 0x76, 0x0c, 0x18, + 0xe0, 0x87, 0xe1, 0xb8, 0x0e, 0x75, 0x18, 0xa2, 0x46, 0x62, 0x9a, 0x20, + 0x85, 0x5e, 0x8b, 0xb4, 0xfe, 0xd2, 0x24, 0x4b, 0x6b, 0x2c, 0x53, 0x3e, + 0xba, 0xb3, 0x28, 0x6b, 0x29, 0x81, 0x6a, 0x74, 0xc8, 0xb6, 0x92, 0x13, + 0x77, 0x2b, 0xe7, 0xad, 0x1f, 0x20, 0x41, 0x0c, 0xdd, 0xb4, 0xa7, 0xa2, + 0xb8, 0x88, 0x2e, 0xb3, 0x12, 0xec, 0xfb, 0x36, 0x7a, 0xea, 0x77, 0xb3, + 0x22, 0xb4, 0x52, 0xd0, 0x97, 0x41, 0xae, 0xc1, 0xb2, 0x04, 0xd0, 0x7f, + 0x88, 0x23, 0x66, 0x50, 0x21, 0xee, 0xb5, 0x89, 0xcd, 0xeb, 0xe4, 0x46, + 0xed, 0x7b, 0x89, 0x4a, 0xb9, 0xc2, 0xa6, 0x33, 0x13, 0xdd, 0xc3, 0x96, + 0x16, 0xd5, 0xe0, 0x70, 0xfb, 0x13, 0xb8, 0xa3, 0x64, 0x86, 0x18, 0x2e, + 0xb6, 0x0f, 0x86, 0x2c, 0x1f, 0xda, 0x82, 0xb0, 0x79, 0x9c, 0x73, 0xa9, + 0x7e, 0x7b, 0xe9, 0x49, 0x84, 0x08, 0x53, 0x14, 0x31, 0x77, 0xdc, 0xa1, + 0x65, 0xd5, 0xaa, 0xb2, 0x99, 0xa6, 0x85, 0x30, 0x45, 0x95, 0x06, 0x31, + 0xc3, 0xd2, 0xb2, 0x5e, 0xcd, 0x8d, 0x4a, 0x24, 0x66, 0xfb, 0x97, 0x02, + 0xf0, 0xca, 0x1c, 0x5c, 0x79, 0x28, 0xa1, 0x97, 0x47, 0xac, 0xba, 0x85, + 0x05, 0x79, 0x1c, 0x06, 0x2c, 0xdf, 0x1f, 0xcf, 0xca, 0xd4, 0xa8, 0x31, + 0xa6, 0x76, 0x8d, 0x3d, 0x3e, 0xd6, 0xba, 0xf9, 0xe6, 0xb1, 0xae, 0x49, + 0xca, 0x4c, 0x5b, 0xb3, 0x58, 0xee, 0x44, 0xec, 0xa9, 0x82, 0x73, 0xa3, + 0xe3, 0x1e, 0xd0, 0xc0, 0x28, 0x15, 0x6a, 0x7a, 0x1f, 0x5b, 0xc1, 0xc6, + 0x14, 0x17, 0x15, 0x2f, 0x15, 0xd5, 0xcb, 0xb0, 0x4a, 0x58, 0x56, 0x5a, + 0xa5, 0xac, 0x82, 0x89, 0x22, 0x2d, 0xe0, 0x0c, 0x89, 0xab, 0x05, 0x82, + 0x29, 0x73, 0x03, 0xc9, 0xcc, 0x03, 0x8e, 0x4e, 0x81, 0x75, 0x16, 0x2e, + 0x7f, 0xe4, 0x41, 0x3f, 0x6b, 0x49, 0xfa, 0xb4, 0x15, 0xd0, 0x71, 0xea, + 0x53, 0xf0, 0xa3, 0x40, 0x0e, 0x63, 0x8e, 0x31, 0x30, 0x02, 0x6d, 0x35, + 0x47, 0x65, 0x84, 0x72, 0x12, 0xd3, 0x78, 0x6e, 0x35, 0xba, 0x32, 0x41, + 0x62, 0x26, 0x61, 0x33, 0x39, 0x89, 0xc2, 0xc3, 0x58, 0x09, 0x2a, 0x32, + 0x44, 0xaf, 0xd8, 0xe9, 0x16, 0x41, 0x08, 0xbf, 0x6f, 0x20, 0x0d, 0x9f, + 0xc8, 0xdd, 0x5a, 0xdf, 0xc7, 0xec, 0xcc, 0x81, 0x57, 0x12, 0xa1, 0x9a, + 0x5e, 0xe2, 0x68, 0x2d, 0xa9, 0x6b, 0xd8, 0x7f, 0x36, 0x5f, 0xe1, 0x43, + 0xca, 0xbc, 0x7e, 0x8c, 0x74, 0x11, 0xd4, 0xf4, 0x20, 0xa5, 0xf8, 0x28, + 0x3b, 0x7d, 0x24, 0xe6, 0x3c, 0x46, 0xd8, 0x46, 0x4d, 0xea, 0x84, 0x16, + 0x7b, 0xf7, 0xb9, 0x9b, 0x7f, 0xf6, 0x1d, 0x53, 0x6f, 0x32, 0x02, 0x74, + 0xd3, 0x12, 0x62, 0x92, 0x0c, 0x53, 0xa2, 0xbf, 0x16, 0x4e, 0xde, 0x1d, + 0xe5, 0xe4, 0x9f, 0x75, 0xe4, 0xac, 0xa0, 0x71, 0x54, 0x45, 0x37, 0xfc, + 0x3b, 0x1a, 0x40, 0x99, 0x1e, 0x4a, 0x66, 0xe3, 0x1e, 0x47, 0x18, 0xe1, + 0xa6, 0x66, 0x26, 0x90, 0x31, 0xc6, 0x89, 0xb1, 0x0e, 0x98, 0x3d, 0x1e, + 0xb8, 0x47, 0x8a, 0xb5, 0xd1, 0x4c, 0xee, 0x25, 0x2c, 0x1f, 0x29, 0x30, + 0xd6, 0x57, 0x9a, 0xb7, 0x66, 0x6c, 0x92, 0x13, 0xa8, 0x49, 0xdd, 0x59, + 0xc4, 0xc3, 0xe0, 0x44, 0x2e, 0xeb, 0x4e, 0x2e, 0x39, 0x4f, 0x37, 0x63, + 0xf9, 0xbe, 0x7d, 0x39, 0x53, 0x0b, 0x8b, 0x6b, 0x40, 0x6a, 0x6f, 0x21, + 0x3a, 0xea, 0x15, 0xc9, 0xc3, 0x19, 0x58, 0x50, 0x27, 0x5f, 0xd0, 0x33, + 0x55, 0x68, 0xad, 0xe3, 0xf2, 0x84, 0x97, 0x0b, 0x7f, 0x39, 0xeb, 0xad, + 0x25, 0x6b, 0xa4, 0xbe, 0x77, 0x5d, 0xcc, 0x25, 0xda, 0x50, 0xbf, 0xbb, + 0xfc, 0x03, 0xd1, 0x54, 0xfb, 0x21, 0x5c, 0x7f, 0x35, 0x7f, 0x4b, 0x76, + 0x2e, 0x46, 0x5c, 0x6d, 0xc0, 0x40, 0xbc, 0x08, 0x54, 0xab, 0x27, 0xfd, + 0xaf, 0x2c, 0xff, 0x4e, 0x14, 0xe2, 0xa9, 0xa4, 0xba, 0xa0, 0x34, 0x47, + 0xbd, 0x7a, 0x81, 0x7c, 0xd1, 0xe4, 0xe3, 0xa3, 0x20, 0x33, 0xa3, 0x64, + 0x9a, 0x78, 0x0c, 0xc2, 0x3a, 0x55, 0xdb, 0x98, 0x35, 0x2d, 0x39, 0x04, + 0x2d, 0xf3, 0x22, 0xdf, 0x2e, 0x9c, 0x7c, 0x57, 0x53, 0xf3, 0x9d, 0xd3, + 0x1e, 0xcf, 0xf9, 0x15, 0xd4, 0x5b, 0x1f, 0xac, 0x56, 0x47, 0xb7, 0x36, + 0x4e, 0x5c, 0x88, 0x0c, 0x01, 0xf5, 0x7c, 0xc7, 0xe0, 0x20, 0xea, 0xcc, + 0xe7, 0x6e, 0x41, 0xab, 0xcc, 0xa6, 0x2b, 0x8a, 0x99, 0xe5, 0x01, 0x47, + 0xf5, 0xb7, 0xbf, 0x98, 0x73, 0x89, 0x44, 0xa9, 0xa1, 0x75, 0x6f, 0xfb, + 0x0b, 0x64, 0x55, 0xca, 0xb4, 0x75, 0xbf, 0xc3, 0x55, 0xce, 0x87, 0x50, + 0xce, 0x0b, 0xf7, 0x7c, 0x24, 0x19, 0xe4, 0xe9, 0x97, 0x29, 0x86, 0x5f, + 0x8a, 0x16, 0x97, 0xf7, 0x87, 0x5a, 0x41, 0x7b, 0x38, 0x13, 0x70, 0x62, + 0x0f, 0xf0, 0xad, 0xe9, 0xd7, 0xf9, 0x7f, 0x62, 0xda, 0x77, 0x2a, 0x60, + 0x8d, 0xd2, 0x85, 0x5c, 0x6b, 0xc4, 0x43, 0xa7, 0x30, 0x27, 0x2d, 0x18, + 0x79, 0x52, 0x94, 0x76, 0xd8, 0xea, 0xb2, 0xb7, 0x2d, 0x86, 0xbb, 0xef, + 0xf7, 0x54, 0x17, 0x1b, 0xec, 0x1d, 0x9a, 0x7f, 0xa9, 0xb7, 0x35, 0x15, + 0xb1, 0xdf, 0x61, 0xd9, 0x76, 0x7c, 0x2d, 0x4a, 0x59, 0xf5, 0xf6, 0x5e, + 0xde, 0xfe, 0x3a, 0x27, 0x8d, 0x33, 0xa9, 0x72, 0xfc, 0x7e, 0xa9, 0xf5, + 0xdd, 0x72, 0xe9, 0x2c, 0x0d, 0xd3, 0x89, 0x89, 0x54, 0xc0, 0x9e, 0xd2, + 0x61, 0x68, 0xc5, 0x7b, 0xd1, 0x91, 0xd0, 0x55, 0xaa, 0x69, 0xb5, 0x19, + 0x0f, 0x83, 0x37, 0xbb, 0x72, 0x90, 0xb9, 0x7f, 0x47, 0xd8, 0xc4, 0xf0, + 0x29, 0x9d, 0x96, 0xe8, 0x32, 0x70, 0x64, 0x85, 0xc4, 0xa0, 0xfb, 0x53, + 0x9a, 0x45, 0xe6, 0x94, 0xcb, 0x6d, 0x09, 0x8a, 0xe2, 0x9d, 0xf7, 0x35, + 0xa7, 0x43, 0xbb, 0x46, 0x9d, 0x18, 0x37, 0x58, 0x14, 0x5b, 0xc5, 0x1c, + 0x35, 0x57, 0xf5, 0x30, 0x60, 0x8d, 0x3b, 0xba, 0xab, 0x90, 0x3f, 0x22, + 0xa1, 0x2a, 0xff, 0xae, 0xa4, 0xe4, 0x95, 0xa9, 0x43, 0x89, 0x12, 0x2d, + 0xf0, 0xe0, 0x70, 0x25, 0x1c, 0x90, 0xd7, 0x70, 0x1b, 0xbe, 0x82, 0xad, + 0x26, 0x59, 0x01, 0x05, 0x2c, 0x8e, 0xf4, 0x74, 0x50, 0xa0, 0x83, 0xbe, + 0x76, 0x05, 0x41, 0x55, 0xf8, 0x12, 0x3e, 0x0c, 0x11, 0xf6, 0x59, 0x9c, + 0x23, 0xc3, 0x13, 0x41, 0xee, 0xd3, 0x0d, 0xa6, 0x00, 0x5c, 0x11, 0x12, + 0x00, 0x00, 0x00, 0x1b, 0x99, 0x90, 0xef, 0x9c, 0x6b, 0x48, 0x2f, 0x5d, + 0xe2, 0x75, 0x64, 0x30, 0x6e, 0x94, 0x88, 0xcd, 0xc7, 0xb1, 0x7d, 0xd2, + 0xc6, 0xc6, 0x44, 0xab, 0x2d, 0xff, 0x54, 0x7b, 0x29, 0x79, 0x07, 0xd6, + 0xd2, 0x68, 0x7c, 0x74, 0xcd, 0x27, 0x28, 0x1c, 0x58, 0x5c, 0xd9, 0x4e, + 0xbd, 0xee, 0xc0, 0x02, 0xe7, 0x71, 0x41, 0xc9, 0x31, 0x14, 0x6b, 0x68, + 0x2f, 0xb9, 0xfb, 0xf5, 0x49, 0x17, 0x23, 0x35, 0x8d, 0x3e, 0x7b, 0x5a, + 0x21, 0x21, 0x3a, 0x71, 0x00, 0x14, 0xb1, 0x84, 0x71, 0x13, 0x3d, 0xf2, + 0xb3, 0xad, 0x9c, 0xff, 0xe9, 0xd3, 0x19, 0x7c, 0x67, 0x5c, 0x7c, 0x5d, + 0x0b, 0xb9, 0x4e, 0xfc, 0x2a, 0x9d, 0x19, 0x37, 0x80, 0xe6, 0xbe, 0xef, + 0x5d, 0xb6, 0xf9, 0x90, 0x5d, 0xdf, 0x25, 0x93, 0x98, 0x04, 0x0a, 0x46, + 0xce, 0xd8, 0xe3, 0x92, 0xd1, 0x8e, 0x90, 0xf6, 0xce, 0xe8, 0x6f, 0x58, + 0x8c, 0xe0, 0x4c, 0x44, 0x61, 0x8d, 0x84, 0xe8, 0xc7, 0xc9, 0xa6, 0x80, + 0xdf, 0x96, 0x8d, 0x22, 0x2d, 0x86, 0x38, 0x19, 0x0f, 0x36, 0x1c, 0xbb, + 0x5c, 0xa1, 0xa1, 0xb3, 0xb0, 0xc6, 0xbf, 0xf1, 0x41, 0x9b, 0x3f, 0xf6, + 0x5c, 0x1f, 0x96, 0xc5, 0xce, 0x8f, 0x8a, 0xd5, 0xcc, 0xc5, 0xc4, 0x14, + 0xce, 0xe0, 0xea, 0x87, 0x7a, 0x30, 0xac, 0x17, 0xf6, 0xc8, 0x4a, 0x17, + 0xb2, 0x2d, 0xf8, 0x46, 0xf9, 0x5c, 0xad, 0x02, 0xc7, 0x4a, 0x19, 0x33, + 0xe1, 0x7e, 0x39, 0x06, 0xe7, 0x88, 0x1a, 0x3b, 0xc7, 0x4b, 0xb7, 0x0f, + 0x05, 0x34, 0x06, 0xae, 0x6d, 0x92, 0x5b, 0xea, 0x22, 0x17, 0x6c, 0xad, + 0x65, 0x86, 0x68, 0xba, 0x4e, 0x38, 0xf5, 0x3a, 0xeb, 0xe4, 0x81, 0x2a, + 0xff, 0x22, 0x33, 0x73, 0x85, 0xeb, 0x11, 0x78, 0x98, 0xcb, 0x4d, 0xc9, + 0xbf, 0x4f, 0x24, 0x8e, 0x6b, 0xf7, 0x44, 0x7b, 0xbf, 0xf2, 0xa9, 0x4e, + 0x08, 0xcd, 0xfc, 0xb7, 0xfc, 0xd9, 0xb8, 0x19, 0xf5, 0x80, 0xd1, 0xce, + 0x45, 0x06, 0x9b, 0xc8, 0x4c, 0xd8, 0xd1, 0x19, 0xd7, 0x9b, 0xc8, 0x67, + 0x11, 0x04, 0x86, 0x69, 0xae, 0x5d, 0xd5, 0xa2, 0xb3, 0xe5, 0x64, 0x50, + 0x2b, 0x9c, 0x18, 0xf5, 0xef, 0x65, 0x90, 0xdc, 0xb9, 0x7a, 0x67, 0x1d, + 0x62, 0xf3, 0x17, 0xbf, 0x1d, 0x67, 0xaf, 0xb3, 0x0c, 0xe4, 0xda, 0x27, + 0x06, 0xa3, 0x34, 0xe6, 0x8f, 0x43, 0xd1, 0x20, 0x17, 0x44, 0x44, 0x10, + 0x93, 0x91, 0x61, 0x43, 0xb7, 0x75, 0x9f, 0x1e, 0x91, 0x0b, 0xa0, 0x5e, + 0x49, 0x02, 0xba, 0x5d, 0xbc, 0xde, 0x6c, 0xb5, 0xbb, 0x26, 0x87, 0x68, + 0x03, 0x94, 0xe1, 0x05, 0xd1, 0xfc, 0xba, 0x48, 0xc7, 0x87, 0x86, 0xef, + 0xe9, 0x54, 0x0a, 0xaf, 0xd1, 0x7b, 0x0a, 0xd4, 0xf5, 0x07, 0xe6, 0x1f, + 0x60, 0xec, 0x82, 0x2c, 0xc5, 0x93, 0xc3, 0x60, 0xee, 0x78, 0x85, 0x28, + 0xa5, 0x08, 0x9f, 0x36, 0x47, 0x9c, 0xb2, 0x8e, 0x0a, 0x90, 0xf2, 0xa2, + 0xd0, 0x13, 0x3e, 0xfa, 0x40, 0x46, 0x6e, 0x97, 0x92, 0xea, 0x56, 0x60, + 0xe3, 0x95, 0xa1, 0x35, 0x3c, 0x26, 0xe2, 0x4d, 0x35, 0x92, 0x5e, 0xe4, + 0xbd, 0x4c, 0xea, 0x8e, 0xbf, 0x81, 0xd6, 0xe8, 0xa2, 0x37, 0x70, 0x3b, + 0x3c, 0xc4, 0x8d, 0x05, 0x16, 0x9a, 0x3a, 0x34, 0x47, 0x99, 0xd7, 0x49, + 0xc7, 0x9a, 0x34, 0x1c, 0x7f, 0xbf, 0xce, 0x56, 0x7e, 0x64, 0xaa, 0xba, + 0xc6, 0xfc, 0xe7, 0x3e, 0x62, 0x7f, 0xa6, 0x38, 0xdd, 0x3a, 0x95, 0x80, + 0xd4, 0xf8, 0x49, 0x58, 0xe7, 0x02, 0x4e, 0xa0, 0x08, 0x74, 0x71, 0x19, + 0x79, 0x75, 0x41, 0x95, 0x88, 0xc8, 0xe1, 0xe4, 0x9d, 0x19, 0x7c, 0x06, + 0x03, 0x0d, 0x27, 0x36, 0x5d, 0x2b, 0xbc, 0xa6, 0xb6, 0x22, 0x94, 0x12, + 0x17, 0xa2, 0xa2, 0x1e, 0x07, 0x60, 0x0e, 0x8d, 0x53, 0x60, 0x41, 0x7b, + 0x92, 0xfb, 0x13, 0x74, 0x1c, 0x6c, 0x1a, 0xd3, 0x7d, 0xda, 0xe1, 0x1c, + 0x16, 0xb9, 0xf9, 0xd2, 0x39, 0x36, 0xc0, 0xbb, 0x49, 0x00, 0xd4, 0x8d, + 0x7a, 0x59, 0x41, 0x9c, 0x2f, 0x09, 0x3b, 0x63, 0x1c, 0x82, 0x15, 0xe3, + 0x36, 0x62, 0x37, 0x07, 0x3b, 0x6e, 0x7c, 0x8d, 0x6c, 0x7b, 0x2b, 0xa0, + 0xa8, 0xd2, 0xe1, 0x24, 0x58, 0x3d, 0xb2, 0xf2, 0x3f, 0xf8, 0x86, 0x44, + 0x09, 0xe7, 0xab, 0x5f, 0x34, 0xa8, 0x37, 0xda, 0x2d, 0xd8, 0xae, 0x01, + 0x88, 0x0d, 0x43, 0x38, 0x35, 0x7d, 0xb5, 0xe7, 0x6e, 0x79, 0x0d, 0xe9, + 0xe9, 0x25, 0xf8, 0xdb, 0xfd, 0x3b, 0xd9, 0x73, 0x77, 0x55, 0x45, 0xc3, + 0x22, 0xf5, 0x43, 0x22, 0x4f, 0x47, 0xbf, 0x78, 0xfb, 0x34, 0xd1, 0xee, + 0xd0, 0xcc, 0x3a, 0xa5, 0xa4, 0xe5, 0x78, 0xe9, 0xd6, 0x55, 0xe0, 0x15, + 0x86, 0x4b, 0x58, 0x9d, 0x62, 0x2f, 0x29, 0x62, 0xd8, 0xdf, 0x96, 0x80, + 0x05, 0x1a, 0x9d, 0xc1, 0x0d, 0xb9, 0xd1, 0x44, 0x29, 0x6f, 0xe0, 0x86, + 0x25, 0xde, 0x7f, 0x78, 0x6f, 0xe0, 0x9c, 0xdf, 0x14, 0xdd, 0x89, 0x3e, + 0x44, 0xf4, 0xe0, 0x4c, 0x20, 0x58, 0xbb, 0x55, 0xf5, 0x4e, 0x96, 0xaa, + 0x82, 0x74, 0x2d, 0xbd, 0xc2, 0xad, 0x7f, 0xc3, 0xed, 0x8b, 0xd5, 0x98, + 0xf7, 0xad, 0x5a, 0xc4, 0x90, 0x14, 0xb2, 0xa8, 0xf4, 0x81, 0xc4, 0xaf, + 0x6c, 0x05, 0xfe, 0xee, 0x04, 0x3c, 0x51, 0xbd, 0x75, 0xd7, 0x32, 0xf5, + 0x7e, 0x45, 0x19, 0x39, 0x19, 0x28, 0x45, 0x9a, 0xc7, 0xcf, 0x82, 0x7d, + 0x56, 0xac, 0x68, 0xdb, 0xde, 0x89, 0x9d, 0x72, 0x1a, 0x46, 0xea, 0xb0, + 0xc3, 0xbc, 0x6f, 0x0d, 0x4b, 0x41, 0x3b, 0x38, 0xb3, 0xc7, 0xcb, 0x04, + 0xbe, 0xf3, 0x4c, 0x3b, 0x74, 0xa9, 0x2a, 0xe4, 0xe3, 0x2f, 0xc7, 0x8c, + 0x90, 0x30, 0x67, 0xcb, 0xb1, 0x1f, 0xbf, 0xc0, 0xad, 0x37, 0x74, 0x80, + 0xa9, 0x04, 0x7c, 0xc8, 0x57, 0x33, 0x83, 0x5b, 0x8c, 0xe6, 0xfc, 0xd5, + 0xa4, 0xf3, 0x9b, 0x6b, 0x2d, 0xdc, 0x64, 0x2b, 0x83, 0xe7, 0xdc, 0xb4, + 0x48, 0x8d, 0x11, 0x65, 0x22, 0xb5, 0xb5, 0x54, 0xec, 0x26, 0xdc, 0x1f, + 0x96, 0xbc, 0x68, 0x87, 0x67, 0xed, 0x1c, 0x41, 0xd3, 0xd8, 0x4f, 0xe2, + 0xc8, 0x43, 0xbb, 0x22, 0xd9, 0xa1, 0x39, 0xe1, 0x72, 0xdb, 0x75, 0x81, + 0x58, 0x74, 0x89, 0xb9, 0x58, 0x8b, 0x0f, 0x8a, 0xa0, 0x6a, 0x9e, 0x70, + 0x6b, 0x3b, 0x01, 0x2f, 0x2b, 0xf4, 0x00, 0xb8, 0x1c, 0xf9, 0x34, 0xa4, + 0x30, 0x80, 0x80, 0x4a, 0x0e, 0xcc, 0x52, 0x4e, 0xc7, 0xc1, 0x01, 0xfd, + 0x73, 0x22, 0x26, 0x33, 0x68, 0xfe, 0x01, 0x1d, 0xe1, 0xf0, 0x04, 0x66, + 0xfd, 0xcc, 0x77, 0xe5, 0xa1, 0x4b, 0xbe, 0x0e, 0xde, 0x95, 0x74, 0x72, + 0xbf, 0xbb, 0xa2, 0x5c, 0x08, 0x5d, 0x13, 0xcb, 0xcb, 0xd7, 0xa6, 0x34, + 0x61, 0x53, 0x0b, 0x3e, 0xb1, 0xe0, 0xb5, 0xd3, 0xaf, 0xe9, 0x07, 0x67, + 0x4c, 0x1a, 0x5b, 0x64, 0x68, 0xac, 0x94, 0x6f, 0xc4, 0xdb, 0x0f, 0x84, + 0x52, 0x88, 0x4b, 0x1e, 0xe5, 0xf1, 0x05, 0x70, 0x94, 0xee, 0xc1, 0x62, + 0xfd, 0x6f, 0x41, 0x2a, 0x1f, 0xda, 0xbe, 0x9f, 0xfb, 0x87, 0xf0, 0x96, + 0x8d, 0xa0, 0x60, 0x74, 0x7d, 0x53, 0x6e, 0x2e, 0x2d, 0x42, 0x49, 0x3d, + 0x9a, 0xae, 0xbc, 0x1b, 0x76, 0xa0, 0xc7, 0xaf, 0x4b, 0xb9, 0x18, 0x6f, + 0x4b, 0xe8, 0xbc, 0x56, 0x7b, 0x57, 0x60, 0xd1, 0xd3, 0x0c, 0x4d, 0xe0, + 0xe2, 0x3d, 0xcc, 0x82, 0x36, 0x78, 0xa2, 0x53, 0xe8, 0xe8, 0xf6, 0x13, + 0xa6, 0xc1, 0x1f, 0x0c, 0x9f, 0x5b, 0x0c, 0xf9, 0x89, 0x8e, 0xae, 0x70, + 0x51, 0xd0, 0x1f, 0x7b, 0xab, 0x69, 0xda, 0xb9, 0x56, 0x4d, 0x2d, 0x93, + 0x18, 0xa4, 0x40, 0x55, 0x95, 0xdf, 0x58, 0xca, 0xbd, 0x36, 0x89, 0x07, + 0x58, 0x11, 0xa6, 0x22, 0xf8, 0x83, 0x1c, 0x8e, 0xe7, 0xa9, 0xc7, 0xd3, + 0xdc, 0x5e, 0x54, 0x35, 0xd6, 0xf1, 0xe4, 0x41, 0x98, 0xa4, 0x16, 0x67, + 0x73, 0x56, 0xdd, 0x69, 0x6d, 0xaa, 0x3f, 0xb8, 0xad, 0xfa, 0xd7, 0xce, + 0xee, 0x65, 0xc5, 0x10, 0xe8, 0x39, 0x1d, 0xff, 0x57, 0x1a, 0x85, 0x43, + 0x77, 0x3f, 0xb1, 0xe1, 0x21, 0x81, 0xa6, 0x8e, 0xd8, 0x49, 0xec, 0xe8, + 0x44, 0x0c, 0x4c, 0x44, 0x8f, 0x8d, 0x78, 0x45, 0xcc, 0x81, 0xed, 0x17, + 0xd1, 0xac, 0x54, 0x3c, 0x58, 0xa4, 0x8e, 0x65, 0xd0, 0xd8, 0x94, 0xc9, + 0xd7, 0x8d, 0x46, 0x5d, 0xc1, 0x3c, 0xb6, 0xb9, 0x0d, 0x88, 0xdf, 0x2c, + 0xb8, 0x51, 0x6d, 0x30, 0x87, 0x76, 0x27, 0x0a, 0xd7, 0xfe, 0x0a, 0x2b, + 0x2d, 0xdc, 0xd1, 0xd2, 0xfd, 0x72, 0xcd, 0x0f, 0x1b, 0xb7, 0xb6, 0x0d, + 0xbd, 0xe0, 0x10, 0x60, 0xec, 0xfd, 0xe1, 0x18, 0x0d, 0x88, 0x48, 0x34, + 0xec, 0xf6, 0x7f, 0x4a, 0x24, 0xce, 0xa9, 0x8d, 0x45, 0x4e, 0xde, 0xcc, + 0x5e, 0xfc, 0x48, 0xf8, 0x7e, 0xa8, 0x0a, 0x9c, 0x5b, 0xad, 0x3c, 0x5e, + 0x5d, 0x3e, 0x33, 0x89, 0xec, 0x88, 0x58, 0xa9, 0xca, 0xa6, 0xe7, 0x59, + 0x5a, 0x8e, 0xfb, 0x21, 0x43, 0x8a, 0x45, 0x49, 0x0f, 0x91, 0xb8, 0xf8, + 0x60, 0x5b, 0x35, 0x44, 0xd7, 0x0d, 0x68, 0x9f, 0x47, 0x6f, 0xbf, 0x3d, + 0xa1, 0x6f, 0xd7, 0xfc, 0xef, 0xbd, 0x9b, 0x84, 0xce, 0x79, 0xbd, 0xf9, + 0x59, 0x4d, 0x46, 0x6e, 0xde, 0x49, 0xdd, 0xde, 0xb8, 0x27, 0x33, 0xf9, + 0xdb, 0x33, 0xdb, 0xea, 0x42, 0x30, 0xff, 0x96, 0x72, 0x5b, 0x55, 0xb6, + 0xa3, 0xa9, 0x15, 0xb3, 0xbd, 0x31, 0xb6, 0x7c, 0x4e, 0xc8, 0xec, 0x5a, + 0x2a, 0x53, 0xe9, 0xa8, 0x25, 0x26, 0x75, 0xeb, 0xce, 0xd5, 0x27, 0x6e, + 0x85, 0xe2, 0x01, 0x0b, 0xd6, 0x1b, 0x09, 0xe8, 0x0a, 0x11, 0xf3, 0x2d, + 0x94, 0xcf, 0xab, 0x03, 0xb9, 0x83, 0x8a, 0x6f, 0x3b, 0x05, 0x98, 0xb4, + 0x72, 0x3b, 0xba, 0x90, 0xbd, 0x23, 0x07, 0x8b, 0xf8, 0xd9, 0x26, 0x13, + 0x74, 0xe3, 0x1c, 0x85, 0xec, 0x8f, 0x43, 0x29, 0xa8, 0x17, 0x6d, 0xb7, + 0x00, 0xda, 0xd1, 0x34, 0x1d, 0x1c, 0xd2, 0xc3, 0xe6, 0xd7, 0x11, 0x51, + 0x79, 0x1b, 0x73, 0x00, 0x51, 0xd0, 0xe7, 0x92, 0xe1, 0x11, 0x5d, 0x9b, + 0x5c, 0x11, 0x88, 0x4c, 0xfa, 0x02, 0x82, 0x78, 0x86, 0xed, 0x65, 0x08, + 0x4f, 0x1c, 0xcb, 0x8c, 0x78, 0x59, 0x65, 0xea, 0x97, 0x8c, 0xe6, 0x52, + 0xe1, 0x3f, 0xdd, 0xbb, 0x20, 0xe6, 0x7c, 0xf9, 0xc7, 0xf8, 0xb9, 0xe6, + 0x74, 0xa0, 0xa5, 0xcb, 0xe9, 0x89, 0xb9, 0xff, 0x88, 0xa3, 0xb8, 0x7b, + 0x60, 0x8d, 0xb0, 0xca, 0x50, 0xe8, 0xc0, 0x80, 0xc1, 0x68, 0x27, 0xef, + 0x48, 0xe7, 0x00, 0x22, 0x52, 0xb4, 0x2e, 0x30, 0x97, 0x96, 0xde, 0xb3, + 0xd0, 0xa1, 0x8b, 0x6a, 0x31, 0x6a, 0xc4, 0x52, 0xef, 0xba, 0x74, 0x57, + 0xf1, 0xc6, 0x19, 0x37, 0x0b, 0x22, 0xa0, 0x23, 0xb9, 0xe0, 0x26, 0x0c, + 0x23, 0xa3, 0xb8, 0x4c, 0x71, 0x7b, 0x45, 0xa4, 0xe8, 0xfd, 0x94, 0xfc, + 0x96, 0x47, 0xba, 0x0f, 0xaa, 0x67, 0x90, 0xa3, 0x2d, 0x95, 0x70, 0xd2, + 0xa3, 0xfa, 0x7b, 0x49, 0x03, 0x45, 0x44, 0x45, 0x8a, 0x38, 0x2a, 0x04, + 0x1b, 0x9a, 0xa3, 0xbd, 0xc6, 0xa9, 0xcf, 0x4f, 0x88, 0x41, 0x98, 0x0c, + 0x2a, 0x5e, 0x22, 0x60, 0x01, 0xf3, 0x78, 0x98, 0xf4, 0x13, 0xc9, 0x27, + 0x80, 0x6e, 0xee, 0x4f, 0xa0, 0xf2, 0xbe, 0x8f, 0x83, 0x69, 0x52, 0xc4, + 0xf8, 0x82, 0x36, 0xd6, 0xe4, 0x91, 0xd9, 0x62, 0xa4, 0x09, 0xa1, 0xbd, + 0xff, 0xec, 0x96, 0x74, 0x0d, 0x6f, 0x17, 0xf9, 0xb7, 0xe3, 0xe4, 0x16, + 0x7f, 0x03, 0xd7, 0x27, 0x7f, 0xaa, 0x94, 0x27, 0x61, 0x3a, 0x3c, 0x0a, + 0x92, 0x82, 0x93, 0x6a, 0xed, 0x55, 0x12, 0xac, 0xe4, 0x89, 0xc2, 0x25, + 0x36, 0x50, 0x63, 0x68, 0x49, 0xb7, 0x5f, 0x44, 0x95, 0xe8, 0x41, 0x09, + 0x6f, 0xdf, 0x66, 0x0c, 0xde, 0x6f, 0xba, 0x7a, 0x0f, 0x9e, 0x87, 0x43, + 0x62, 0x99, 0x9b, 0x97, 0xe7, 0xb1, 0x46, 0x2d, 0xa2, 0x10, 0x57, 0x92, + 0x5a, 0xbe, 0xec, 0xc1, 0x24, 0x91, 0x94, 0x80, 0x1c, 0xea, 0x0f, 0xc7, + 0xfe, 0x02, 0x4d, 0x99, 0x88, 0x1b, 0xc1, 0xaa, 0xce, 0x4d, 0x6a, 0xc7, + 0xe0, 0x93, 0x4b, 0x35, 0x71, 0x49, 0x81, 0x6b, 0x98, 0x54, 0x17, 0x6d, + 0xf5, 0xbc, 0xc2, 0xc3, 0xb8, 0x5b, 0x00, 0xfd, 0xec, 0x50, 0x50, 0x6e, + 0xb6, 0xe7, 0xdc, 0x6c, 0x2b, 0x4b, 0x77, 0x73, 0xeb, 0xee, 0xc1, 0xc3, + 0xe1, 0xee, 0xc1, 0xc6, 0xc9, 0xce, 0xad, 0x6b, 0x8f, 0x40, 0x95, 0xb3, + 0x41, 0xb9, 0x86, 0xf8, 0x6a, 0x9a, 0x59, 0x7e, 0xc8, 0xb3, 0x26, 0xa0, + 0x55, 0x6e, 0x41, 0x90, 0xff, 0xf2, 0x69, 0x01, 0x70, 0x61, 0x81, 0x6a, + 0x61, 0x14, 0x78, 0x8c, 0x31, 0xbc, 0xc4, 0x51, 0x81, 0x4e, 0x12, 0x54, + 0xef, 0xd8, 0x85, 0x07, 0x92, 0xa4, 0x02, 0xae, 0x54, 0x80, 0x70, 0x94, + 0x26, 0x49, 0x8a, 0xa2, 0x3e, 0x63, 0x6f, 0x3a, 0xa5, 0xbe, 0x71, 0x02, + 0x22, 0x99, 0xf0, 0x98, 0xe8, 0x8f, 0xc5, 0x58, 0x1e, 0xcd, 0x2b, 0xe8, + 0xf5, 0xa0, 0x2c, 0xd0, 0x21, 0x87, 0x3a, 0x38, 0x28, 0x0d, 0x87, 0x1f, + 0x0f, 0x3e, 0xfb, 0xd6, 0xd3, 0x12, 0x86, 0x66, 0x25, 0x02, 0x6c, 0x08, + 0x54, 0x10, 0xfb, 0x29, 0x8f, 0x7f, 0xe5, 0x96, 0xa8, 0x56, 0xba, 0x72, + 0x71, 0x36, 0xdd, 0xc6, 0x81, 0xe2, 0x1f, 0x7a, 0xd4, 0x8d, 0xdc, 0xea, + 0xe6, 0xff, 0x2f, 0xb5, 0xea, 0x44, 0xea, 0x88, 0x69, 0x80, 0x2e, 0x49, + 0x4d, 0x84, 0x6f, 0xa1, 0x7a, 0xed, 0x05, 0x55, 0x73, 0x42, 0x56, 0xe4, + 0xa6, 0x9f, 0x65, 0x32, 0x46, 0x32, 0xb3, 0x97, 0x87, 0x74, 0x7a, 0xd3, + 0xdd, 0xcf, 0x9f, 0x01, 0x96, 0x37, 0xf2, 0xd1, 0xeb, 0x45, 0x4a, 0x23, + 0xb5, 0x33, 0x6c, 0xa5, 0x7b, 0x98, 0x65, 0xd2, 0xe1, 0x78, 0xf9, 0x44, + 0x03, 0x3b, 0x29, 0xa8, 0xf2, 0x45, 0xb2, 0x96, 0x3e, 0xac, 0x09, 0x24, + 0x76, 0x48, 0xb9, 0x75, 0x87, 0xba, 0x2c, 0x4e, 0x33, 0x67, 0xdf, 0xdc, + 0x70, 0x3b, 0xc3, 0x1f, 0xbb, 0xd9, 0x36, 0xf8, 0x19, 0x2e, 0xeb, 0x42, + 0xe5, 0x6b, 0xaa, 0x85, 0x3f, 0xeb, 0xac, 0x51, 0x78, 0xdb, 0x62, 0x9e, + 0x2a, 0x5f, 0x1e, 0xb2, 0x72, 0xa7, 0xdd, 0x25, 0xb0, 0x6b, 0xcb, 0xc5, + 0xb5, 0xe3, 0x88, 0x1c, 0xcd, 0xfa, 0xa8, 0x6e, 0x2a, 0x0e, 0xa0, 0x79, + 0x7a, 0x04, 0x1f, 0xed, 0x3d, 0xc2, 0x65, 0xaf, 0x0b, 0xaa, 0xb2, 0xec, + 0x73, 0x6e, 0x0f, 0xd4, 0x21, 0xd8, 0x29, 0x39, 0x10, 0x53, 0x2c, 0xf8, + 0x31, 0xaf, 0x5f, 0x4b, 0x81, 0xff, 0xb2, 0x6f, 0x96, 0x41, 0xcf, 0x25, + 0x0f, 0x03, 0x13, 0x05, 0x72, 0x7f, 0x75, 0x5c, 0x31, 0x09, 0x72, 0x90, + 0x65, 0x01, 0x43, 0x4b, 0xef, 0x55, 0x91, 0xd3, 0x75, 0x85, 0x44, 0x78, + 0xe9, 0x4c, 0xb0, 0x9b, 0x68, 0xdd, 0xf2, 0x2d, 0x4a, 0x96, 0x21, 0xb6, + 0x2c, 0x2f, 0x86, 0x76, 0x6f, 0xc5, 0x1f, 0x30, 0x6c, 0xc4, 0xf8, 0x12, + 0x8d, 0x0a, 0x1d, 0x76, 0xe7, 0x79, 0xac, 0x85, 0xd4, 0x2f, 0xfc, 0x2c, + 0x9b, 0x54, 0x2b, 0xdc, 0xf7, 0xad, 0x4a, 0x64, 0x03, 0x40, 0xb4, 0xaa, + 0x21, 0x5f, 0x47, 0x55, 0xf2, 0xfd, 0x9d, 0xe2, 0x14, 0x2e, 0x68, 0x84, + 0xef, 0x98, 0x8e, 0xcd, 0xe3, 0x04, 0x52, 0xd1, 0xc2, 0x6c, 0x3b, 0xc3, + 0x2c, 0x49, 0xc4, 0x53, 0x6c, 0xcb, 0x7e, 0xb5, 0x8a, 0xce, 0x18, 0x02, + 0x34, 0x3c, 0xcb, 0xa4, 0xd6, 0xd8, 0xc9, 0xea, 0xa0, 0x19, 0x08, 0x52, + 0x3a, 0x76, 0x49, 0xc5, 0x6c, 0xb3, 0xbf, 0x23, 0x4d, 0x17, 0x18, 0xa4, + 0x27, 0xea, 0x2c, 0x89, 0xc0, 0x77, 0xe5, 0x5c, 0xab, 0x78, 0xdc, 0x17, + 0x29, 0x7a, 0xde, 0x43, 0x4b, 0x40, 0x06, 0x5d, 0x57, 0xa4, 0xf4, 0xe9, + 0xf0, 0xc3, 0xfe, 0x75, 0x71, 0xb3, 0x57, 0x5d, 0x02, 0x84, 0x1e, 0x35, + 0x9c, 0x2b, 0x97, 0x4b, 0x73, 0x8b, 0xaf, 0x7c, 0x1f, 0xae, 0x2b, 0xb2, + 0x85, 0x3b, 0x00, 0xe6, 0xa6, 0x3f, 0x93, 0x8a, 0xfb, 0x47, 0x71, 0x47, + 0xcb, 0xfd, 0x34, 0xd9, 0xf0, 0xbd, 0x7d, 0x85, 0x02, 0x9b, 0x90, 0x88, + 0x7f, 0x6e, 0x97, 0xce, 0x1a, 0x9f, 0x61, 0x19, 0x59, 0x81, 0x05, 0xfb, + 0xb8, 0xbc, 0x3c, 0x19, 0x1c, 0x1a, 0x5b, 0x60, 0xe0, 0x24, 0xcc, 0x52, + 0xb7, 0x49, 0x9e, 0xb6, 0x08, 0xd5, 0x0e, 0x69, 0xfe, 0xc0, 0x92, 0x74, + 0x73, 0x72, 0x93, 0x32, 0xe7, 0xe6, 0xe9, 0x8f, 0xb2, 0xb4, 0x86, 0x47, + 0x67, 0x67, 0xff, 0xc5, 0x2f, 0x25, 0x54, 0x36, 0x50, 0xeb, 0xf4, 0x34, + 0x91, 0x83, 0xde, 0x05, 0xd7, 0xc6, 0xc8, 0xce, 0xf8, 0xe0, 0xbb, 0xc7, + 0x27, 0x24, 0x65, 0x60, 0x21, 0x47, 0x0d, 0x4e, 0x2c, 0x03, 0xad, 0x14, + 0x0b, 0xe3, 0x0f, 0xe3, 0x50, 0xef, 0x06, 0x63, 0x22, 0xb0, 0x51, 0xff, + 0x72, 0x6d, 0x03, 0xaf, 0x76, 0xf6, 0x0f, 0x06, 0xa1, 0x84, 0x53, 0xa2, + 0x79, 0xe1, 0x68, 0x1c, 0xe7, 0x57, 0x09, 0xf3, 0xff, 0x64, 0x6a, 0x33, + 0x81, 0x8a, 0x84, 0x80, 0xd0, 0x85, 0x84, 0x99, 0x75, 0xc6, 0x2e, 0xae, + 0xe0, 0x6d, 0x49, 0xaa, 0xbd, 0x0e, 0x8d, 0xb9, 0x88, 0xb7, 0x52, 0x55, + 0x00, 0xaf, 0xcb, 0x68, 0xb4, 0x53, 0x25, 0x8d, 0x58, 0xc3, 0xcf, 0x94, + 0x1f, 0x80, 0x8a, 0xda, 0x1f, 0x70, 0xe2, 0x19, 0x6d, 0xdd, 0x1d, 0xac, + 0xab, 0xf8, 0xef, 0x0f, 0x43, 0xe0, 0x91, 0xd7, 0x7c, 0xed, 0xb4, 0x8f, + 0x2f, 0x2a, 0xa6, 0x36, 0x18, 0x86, 0xd7, 0xcc, 0xd1, 0xde, 0xda, 0x0d, + 0x0c, 0xde, 0xae, 0x9f, 0xbc, 0x49, 0xf7, 0x07, 0x82, 0xbe, 0x6e, 0xd0, + 0x2b, 0xb1, 0xd4, 0xfa, 0x1a, 0xfe, 0xcc, 0x57, 0x97, 0x2f, 0x4d, 0x12, + 0xf0, 0xba, 0xa0, 0x3f, 0x7f, 0xb4, 0xfe, 0xb8, 0x0f, 0xb3, 0xc5, 0x03, + 0xdc, 0x77, 0x98, 0x95, 0xc6, 0x0b, 0x7b, 0x6f, 0xad, 0xae, 0x9d, 0xb4, + 0xf0, 0x0d, 0xa2, 0xa1, 0xa8, 0x83, 0x62, 0xc7, 0x31, 0x27, 0x9c, 0x52, + 0x36, 0x06, 0x13, 0x52, 0x0e, 0xd6, 0x30, 0x41, 0xc4, 0x38, 0x29, 0x1d, + 0x39, 0x7c, 0x23, 0x32, 0x45, 0xcc, 0x79, 0xca, 0xa5, 0x9a, 0x62, 0x6e, + 0x00, 0x02, 0xc9, 0xb9, 0xd3, 0x84, 0x02, 0x5d, 0xe3, 0x69, 0x5c, 0x8e, + 0xbe, 0x55, 0xf4, 0x96, 0xdf, 0xcb, 0x8b, 0x52, 0xa1, 0x4e, 0x9c, 0x38, + 0x56, 0xa1, 0xd7, 0x82, 0x4a, 0x6a, 0xd3, 0x19, 0xa6, 0x74, 0x80, 0x04, + 0x6d, 0xc5, 0x7e, 0xd6, 0xda, 0x91, 0x5e, 0x2c, 0x81, 0x3b, 0x0c, 0x6a, + 0xc6, 0xe8, 0x40, 0xb7, 0x9c, 0x2a, 0x4f, 0xb3, 0x87, 0x46, 0xc5, 0x4b, + 0x81, 0x87, 0xbe, 0x93, 0x5a, 0x9c, 0xc8, 0xdc, 0x97, 0x93, 0xff, 0x06, + 0x36, 0x8e, 0xa6, 0x24, 0x03, 0x10, 0x17, 0xf9, 0x20, 0xed, 0x75, 0xef, + 0xed, 0xcf, 0x28, 0x1b, 0x7b, 0x64, 0x00, 0x7c, 0x78, 0x10, 0x84, 0xa2, + 0x96, 0x4b, 0x04, 0x42, 0x57, 0x76, 0xaa, 0x2b, 0x7d, 0x7c, 0xc4, 0x85, + 0x83, 0xef, 0x04, 0xdd, 0x6a, 0x68, 0x5e, 0xe3, 0xba, 0xb4, 0x08, 0xe0, + 0x8a, 0xdc, 0x32, 0x53, 0x1a, 0x4b, 0x06, 0x06, 0x8c, 0x12, 0xb9, 0xf7, + 0xd2, 0xf6, 0x5d, 0x12, 0x7b, 0x1b, 0xb9, 0xcf, 0x0d, 0x8c, 0xfe, 0xb2, + 0x4b, 0xfb, 0xaf, 0x0c, 0xf6, 0x1a, 0x89, 0xe1, 0xdb, 0xa0, 0x92, 0x3b, + 0xb0, 0x15, 0xaf, 0x76, 0xe5, 0x22, 0x5f, 0x93, 0x0f, 0x08, 0x33, 0xa6, + 0xe0, 0x52, 0x00, 0x49, 0x7d, 0xf2, 0xd0, 0xdd, 0xe0, 0xb5, 0xbb, 0x07, + 0x78, 0x2f, 0xd3, 0x17, 0xe0, 0xce, 0xd1, 0x60, 0xef, 0x26, 0x27, 0x68, + 0x81, 0x7e, 0x23, 0xa2, 0xcf, 0x93, 0x12, 0xc6, 0x44, 0x1b, 0xaf, 0x47, + 0x8b, 0x26, 0x47, 0xba, 0x95, 0x7c, 0x2f, 0xc0, 0xff, 0xc6, 0xdc, 0xe8, + 0x1f, 0x2c, 0x35, 0xa1, 0x4b, 0xdc, 0x16, 0x1a, 0xbf, 0x78, 0x05, 0xbc, + 0xb2, 0x1d, 0x69, 0x75, 0x74, 0x6e, 0x32, 0x05, 0x4e, 0x20, 0x6e, 0x1f, + 0xaf, 0x11, 0xf2, 0x37, 0x41, 0x0a, 0x7b, 0xfd, 0x28, 0x9f, 0xa4, 0x47, + 0xfc, 0x25, 0xf5, 0x1c, 0xd5, 0x62, 0xde, 0x84, 0xcb, 0xf9, 0x52, 0xe2, + 0xdd, 0x26, 0x3f, 0x8e, 0x8c, 0xd4, 0xba, 0x54, 0x34, 0xbf, 0x9b, 0xff, + 0x9e, 0x05, 0x2f, 0x9c, 0x98, 0xce, 0xa6, 0x4e, 0x36, 0xde, 0x96, 0x81, + 0x30, 0x05, 0x75, 0x07, 0xdd, 0xa0, 0x74, 0x4f, 0x39, 0x60, 0xcb, 0x5e, + 0x26, 0x2e, 0xbb, 0x00, 0xaf, 0xf7, 0x3b, 0xd9, 0xb1, 0x70, 0x4f, 0xa4, + 0x31, 0x45, 0x06, 0x63, 0x61, 0x03, 0x45, 0x27, 0xe3, 0x66, 0xf7, 0x9f, + 0x15, 0x5b, 0x22, 0x45, 0xb7, 0x6d, 0xe8, 0xb2, 0x67, 0x35, 0x8e, 0x72, + 0x02, 0x76, 0xf4, 0xb4, 0x63, 0x4a, 0x7c, 0xd7, 0xd1, 0x00, 0x6c, 0x93, + 0xfc, 0x63, 0x53, 0x20, 0x40, 0x59, 0xbb, 0x2e, 0xad, 0x26, 0x9c, 0xff, + 0x63, 0xbf, 0xb8, 0x7c, 0x2c, 0x87, 0xb8, 0x5d, 0x07, 0xeb, 0x6d, 0x40, + 0x04, 0x8d, 0x48, 0xc2, 0x92, 0x67, 0x47, 0x16, 0x95, 0x9f, 0x31, 0x93, + 0x3e, 0x09, 0x92, 0x7f, 0xcf, 0xaf, 0x10, 0xec, 0x39, 0xff, 0xd7, 0xb7, + 0xee, 0x8f, 0x86, 0x4e, 0x02, 0x83, 0x04, 0x76, 0x9f, 0x32, 0xf5, 0xa6, + 0xc4, 0xeb, 0xc0, 0x7a, 0xa3, 0x9c, 0x77, 0xd0, 0xb8, 0x9e, 0xf7, 0xad, + 0x51, 0x69, 0xf0, 0x1b, 0xf6, 0x57, 0xde, 0x1e, 0x2b, 0x24, 0xa6, 0x15, + 0x20, 0xba, 0xde, 0xe5, 0xfb, 0x62, 0x60, 0x9c, 0x3e, 0x94, 0xa1, 0x6a, + 0x16, 0x02, 0xa2, 0xc0, 0xc7, 0xe9, 0x21, 0x33, 0x5b, 0xf2, 0x18, 0xbc, + 0x6b, 0x11, 0x13, 0x0a, 0xaa, 0x71, 0x4e, 0xd0, 0x6a, 0x17, 0x91, 0x65, + 0xfd, 0x5f, 0x5e, 0x93, 0xba, 0x9f, 0x70, 0xfa, 0x91, 0xc2, 0x74, 0xf2, + 0xbb, 0xe0, 0x47, 0xf5, 0x7c, 0x0a, 0x91, 0x3c, 0x08, 0x13, 0x74, 0x3f, + 0x63, 0xd6, 0x9c, 0xc6, 0xf6, 0x04, 0x7f, 0xd7, 0x5b, 0xa9, 0x8c, 0x74, + 0x0a, 0x57, 0x45, 0x32, 0x5e, 0x31, 0xf9, 0xa2, 0x68, 0xed, 0xc5, 0xba, + 0x08, 0xf5, 0x41, 0x83, 0x98, 0x65, 0x47, 0x9a, 0x86, 0x87, 0x75, 0x64, + 0xa6, 0xd2, 0x6c, 0xfe, 0x0b, 0xdd, 0x17, 0xb0, 0x4e, 0xbe, 0x09, 0xdb, + 0xe7, 0x2f, 0x5e, 0xd4, 0x2b, 0x2d, 0x2d, 0x26, 0x63, 0xd2, 0xeb, 0x64, + 0x79, 0xd2, 0x55, 0x4f, 0xf1, 0x45, 0x89, 0xc2, 0xf9, 0x38, 0x96, 0xab, + 0xba, 0x5a, 0xfb, 0x42, 0x06, 0xb9, 0xe6, 0x9d, 0x16, 0xaf, 0x79, 0x45, + 0xf7, 0xe7, 0xe6, 0x2e, 0xec, 0x1b, 0x69, 0xe6, 0xbf, 0x54, 0x88, 0x2c, + 0xea, 0xd2, 0x0c, 0xc6, 0x96, 0xfe, 0xc9, 0x5a, 0x5b, 0x16, 0xd8, 0x9a, + 0x13, 0x77, 0x43, 0x37, 0x88, 0xe8, 0x6a, 0x82, 0x06, 0xe4, 0x5d, 0x0a, + 0x50, 0xd9, 0xff, 0xd0, 0x62, 0xcd, 0x8c, 0xcf, 0x86, 0x47, 0xd4, 0xba, + 0x7b, 0xec, 0x4d, 0x78, 0xa5, 0xff, 0x67, 0x2f, 0xf8, 0x70, 0xf4, 0x42, + 0x4b, 0xce, 0xa3, 0xef, 0x25, 0x4c, 0x92, 0x3d, 0x7e, 0x10, 0xfb, 0x03, + 0x97, 0x0a, 0xfe, 0xf4, 0xd3, 0x73, 0x64, 0x00, 0xa1, 0x5e, 0x68, 0xdb, + 0x5f, 0x7a, 0xff, 0x2e, 0x9f, 0xe2, 0x75, 0xd4, 0xf9, 0xa4, 0x49, 0xf0, + 0xe9, 0x5b, 0xe2, 0x37, 0x3b, 0x0c, 0xa9, 0x0c, 0x77, 0x3b, 0x7a, 0x64, + 0xe4, 0x7a, 0x9f, 0x10, 0x9d, 0x18, 0x25, 0x92, 0xd0, 0xcf, 0x6d, 0x1c, + 0xdd, 0xc4, 0xd5, 0x51, 0x6c, 0x52, 0x92, 0x62, 0x57, 0xaa, 0x50, 0x44, + 0xdd, 0xc9, 0xef, 0x8d, 0x28, 0x8a, 0x8b, 0x9c, 0x2c, 0xf6, 0x8d, 0x42, + 0xa2, 0x83, 0xf9, 0xc8, 0xc6, 0x65, 0x0b, 0x6b, 0xd5, 0x5f, 0x76, 0x5e, + 0x76, 0xc1, 0x6f, 0x00, 0x2c, 0xc5, 0x8d, 0x27, 0x7b, 0x28, 0xf0, 0xa3, + 0x0d, 0x5d, 0x1e, 0xa9, 0x6e, 0xe6, 0x4c, 0xc0, 0x12, 0x22, 0x77, 0x0f, + 0x9e, 0x73, 0xba, 0x83, 0x41, 0xbf, 0x8f, 0x0d, 0x7c, 0x27, 0x65, 0x85, + 0x76, 0x88, 0xf4, 0xf1, 0x65, 0x33, 0x55, 0x27, 0x18, 0xcb, 0x1d, 0xd0, + 0xc8, 0xf7, 0x2d, 0x53, 0x94, 0x1f, 0x2a, 0xfa, 0xdd, 0x48, 0xf7, 0x9a, + 0x25, 0xf4, 0xba, 0x8c, 0x16, 0xd3, 0xfa, 0xec, 0x7f, 0x67, 0x28, 0x61, + 0x44, 0x0a, 0x55, 0xaf, 0x9e, 0xd1, 0x51, 0x69, 0x9d, 0x22, 0x3b, 0xf5, + 0x17, 0x23, 0x4c, 0xb9, 0x79, 0xcc, 0xac, 0x6e, 0xc0, 0x3e, 0x81, 0xa6, + 0x4e, 0xec, 0x98, 0x18, 0x6f, 0xf1, 0x05, 0x68, 0xd5, 0x9c, 0x43, 0x1c, + 0x17, 0xbc, 0x34, 0x9d, 0xa5, 0x9f, 0x87, 0x53, 0x0d, 0xdf, 0xf7, 0xa1, + 0xb2, 0xab, 0x5d, 0x0e, 0xc6, 0xb7, 0x7a, 0x0d, 0xe5, 0x35, 0xfc, 0xab, + 0xea, 0x40, 0xfb, 0xd5, 0xc6, 0xc0, 0x4c, 0xfc, 0x28, 0x5c, 0xc0, 0x0a, + 0x4d, 0xac, 0x1e, 0xb0, 0xb3, 0x63, 0xdd, 0x9d, 0x48, 0x87, 0xee, 0x2d, + 0xb3, 0x63, 0xbf, 0x9c, 0x21, 0xe2, 0x5c, 0xd6, 0x03, 0x79, 0x25, 0x00, + 0x98, 0xf8, 0xf6, 0xb5, 0x4c, 0x6f, 0xfb, 0x16, 0x09, 0xbc, 0x64, 0x10, + 0x78, 0xb7, 0x57, 0x26, 0x40, 0x0c, 0xf1, 0x09, 0xcc, 0x93, 0xc1, 0x52, + 0xf4, 0x74, 0xf6, 0x96, 0xb6, 0x97, 0x73, 0xcd, 0x1a, 0xb4, 0x4d, 0xac, + 0x4f, 0xfd, 0x76, 0x0a, 0xc1, 0xc0, 0xd7, 0x94, 0xe4, 0x89, 0xd5, 0xc6, + 0x37, 0xe1, 0xf8, 0x47, 0x20, 0x78, 0xc8, 0xf9, 0xe9, 0xdf, 0xaa, 0xe9, + 0x53, 0x51, 0x0c, 0xc5, 0xac, 0xea, 0x6c, 0xd4, 0x4d, 0x2e, 0x4d, 0x78, + 0x36, 0x00, 0x36, 0x5b, 0xce, 0xca, 0x92, 0xea, 0xb9, 0x90, 0x7e, 0x15, + 0xc2, 0xe2, 0xa9, 0xff, 0x53, 0xa5, 0x91, 0x0f, 0x26, 0x79, 0x72, 0x8e, + 0x69, 0xd9, 0xde, 0xdf, 0x41, 0x85, 0x5a, 0x9b, 0xbe, 0xb7, 0xf7, 0x0f, + 0x0c, 0x24, 0x55, 0xc9, 0x64, 0x85, 0x69, 0xa5, 0x09, 0x92, 0x25, 0x47, + 0x0a, 0x47, 0x49, 0x3d, 0x16, 0x2d, 0xe1, 0x44, 0xf9, 0x3a, 0x0a, 0x82, + 0xcf, 0x3a, 0xf4, 0x1f, 0x18, 0xc4, 0xba, 0x5c, 0x4a, 0xdb, 0xe8, 0xf3, + 0xbb, 0xa4, 0x71, 0x96, 0x6f, 0x5a, 0x77, 0x53, 0x74, 0xf9, 0x40, 0xbc, + 0xae, 0x54, 0xf5, 0x02, 0xae, 0xd1, 0x5f, 0x08, 0xf6, 0x44, 0x65, 0x70, + 0xc2, 0x97, 0x34, 0x10, 0x9a, 0x74, 0x6c, 0x4f, 0x22, 0xa1, 0x50, 0xdf, + 0x17, 0xec, 0x82, 0xed, 0x1d, 0xca, 0x19, 0xdd, 0x67, 0x56, 0x77, 0x3f, + 0x3d, 0x91, 0x19, 0x0e, 0xbb, 0x3b, 0x71, 0x4c, 0xfc, 0x48, 0x60, 0x49, + 0xb2, 0x40, 0x80, 0xbf, 0xc6, 0x71, 0xdf, 0x58, 0x59, 0x73, 0x68, 0x4e, + 0xdb, 0x63, 0xc8, 0xd8, 0x37, 0x97, 0x6a, 0x0a, 0x2a, 0x46, 0xbf, 0xd6, + 0xab, 0x38, 0xaf, 0xf6, 0x42, 0xe6, 0x82, 0x49, 0x3b, 0x6a, 0x0a, 0x43, + 0x04, 0x59, 0xd3, 0x29, 0xf5, 0xd7, 0xef, 0x9e, 0x81, 0x57, 0x3e, 0xa9, + 0x65, 0xa2, 0x20, 0xfd, 0xa3, 0xdc, 0x1e, 0xc3, 0xde, 0xcc, 0x7d, 0xc0, + 0x93, 0xb9, 0x60, 0x56, 0x52, 0x13, 0x51, 0x98, 0xac, 0x60, 0xc2, 0x5f, + 0x84, 0xe9, 0xd6, 0xaa, 0xc6, 0x3c, 0x50, 0x99, 0x98, 0xf5, 0x6e, 0xd7, + 0x7c, 0xe1, 0x08, 0x80, 0x24, 0x76, 0xd0, 0xcc, 0x3a, 0xbd, 0x31, 0x18, + 0x40, 0x7f, 0x79, 0x66, 0xf4, 0x74, 0xb5, 0x83, 0xb3, 0xe2, 0xcc, 0xbc, + 0x49, 0x67, 0x5f, 0x3a, 0x1f, 0xd2, 0x4f, 0x79, 0xf6, 0x38, 0x67, 0xf6, + 0x02, 0x55, 0x21, 0x64, 0xf2, 0x93, 0x5e, 0xbb, 0x3d, 0xa7, 0x5a, 0xc6, + 0xa7, 0x90, 0xd6, 0x46, 0x71, 0x13, 0xb0, 0xa3, 0x47, 0xfe, 0xd5, 0xe0, + 0x17, 0xbd, 0xdc, 0x35, 0x72, 0x68, 0x4e, 0xa0, 0x96, 0xc2, 0xbc, 0x78, + 0x5b, 0xb1, 0x4f, 0x34, 0x26, 0xdc, 0x0f, 0x84, 0x58, 0x6e, 0x7d, 0xb1, + 0x54, 0xc2, 0x9d, 0xac, 0x2c, 0xde, 0xf5, 0xf8, 0x72, 0x43, 0x15, 0x5c, + 0x52, 0x48, 0x0c, 0x67, 0x39, 0x25, 0x8c, 0x3f, 0x49, 0xd2, 0x8b, 0x51, + 0x43, 0xe8, 0x2f, 0x3c, 0x16, 0xdc, 0x48, 0x0b, 0x76, 0xee, 0xd9, 0xb7, + 0x8e, 0x2e, 0x99, 0xbb, 0xa5, 0xda, 0xdd, 0xfe, 0x99, 0x47, 0xf1, 0x22, + 0x53, 0xfc, 0x2e, 0xaa, 0xf7, 0xcf, 0x7b, 0x13, 0x1b, 0x08, 0x18, 0x3a, + 0x6b, 0xe4, 0x66, 0x8a, 0x3e, 0x77, 0xbd, 0x14, 0xb0, 0x90, 0x60, 0xaa, + 0x97, 0x65, 0x1a, 0xd5, 0x0e, 0xea, 0x12, 0xa5, 0x05, 0x87, 0x78, 0x0f, + 0xf4, 0x05, 0xd5, 0x8c, 0x2e, 0x14, 0x26, 0x80, 0x01, 0x7d, 0x06, 0x79, + 0x37, 0x63, 0x70, 0xb1, 0x57, 0x2b, 0x62, 0x2a, 0xe8, 0x76, 0x48, 0x46, + 0x79, 0xea, 0x4a, 0x7a, 0x35, 0xf2, 0xcb, 0x10, 0x7a, 0x3b, 0x62, 0x04, + 0x34, 0x76, 0xe0, 0xf7, 0x9c, 0x1d, 0x73, 0x89, 0x90, 0xf2, 0xc5, 0x79, + 0x7c, 0x15, 0xa0, 0x7f, 0x99, 0x5f, 0xb8, 0x73, 0x62, 0x75, 0x6b, 0x0f, + 0xbe, 0xf1, 0x34, 0x5f, 0x28, 0x14, 0x18, 0x71, 0xe9, 0xde, 0xb7, 0x28, + 0x00, 0x65, 0xa2, 0x08, 0x57, 0xdd, 0x5e, 0x14, 0xa9, 0xc5, 0x0b, 0xb1, + 0x92, 0xa8, 0x20, 0xb2, 0xbd, 0x42, 0x77, 0xf5, 0xb0, 0xa0, 0x00, 0xbe, + 0xa7, 0x82, 0xd0, 0x6a, 0xc8, 0xa9, 0x57, 0xfa, 0x07, 0x3a, 0x97, 0x69, + 0x60, 0xe8, 0xd1, 0x94, 0x0d, 0xa5, 0x7d, 0x74, 0x7f, 0x50, 0xc6, 0x50, + 0x9b, 0x05, 0x41, 0x8d, 0x08, 0x2b, 0x2b, 0x01, 0x37, 0xd0, 0xee, 0x4d, + 0xca, 0x15, 0x70, 0xca, 0x75, 0x4a, 0xc2, 0x54, 0x10, 0xc0, 0x80, 0x27, + 0xe1, 0xcd, 0x52, 0xec, 0x06, 0xb5, 0x73, 0xf4, 0xc2, 0x0b, 0xea, 0x79, + 0xe6, 0x30, 0x5d, 0x41, 0x07, 0x4c, 0x8a, 0xae, 0x03, 0xb0, 0x9b, 0xc2, + 0x5d, 0xf2, 0x43, 0x3f, 0x5e, 0xb7, 0x53, 0x36, 0xc3, 0x81, 0xf6, 0xe5, + 0xd9, 0x35, 0x69, 0x04, 0xe0, 0x36, 0xb8, 0xeb, 0x71, 0x58, 0x71, 0x6f, + 0x47, 0x17, 0xf2, 0x16, 0xe2, 0x09, 0xc7, 0xc2, 0x35, 0xa4, 0x4d, 0xfe, + 0x1a, 0xd2, 0x28, 0x06, 0x34, 0xb3, 0x0f, 0x33, 0xf0, 0xd6, 0x18, 0xf4, + 0x6d, 0x54, 0xb2, 0xbd, 0x88, 0x17, 0x02, 0x40, 0x11, 0x21, 0x59, 0x8b, + 0x62, 0xcb, 0x87, 0xad, 0x0f, 0xc0, 0x08, 0x14, 0x29, 0xf9, 0x5c, 0x3e, + 0xfc, 0xe4, 0x95, 0x1c, 0x9b, 0x60, 0x94, 0xcb, 0x83, 0xb4, 0x1c, 0x1b, + 0xbd, 0xfd, 0x55, 0x88, 0xbf, 0xa6, 0xa5, 0x94, 0xc2, 0xb3, 0x76, 0x5a, + 0x9b, 0xd4, 0xc1, 0xe1, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x51, 0x00, + 0x0a, 0xec, 0x05, 0xf9, 0x03, 0x35, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x85, 0x61, 0x04, 0x23, 0x00, 0x07, 0x07, 0x09, 0x34, 0x00, 0x09, + 0x09, 0x09, 0x34, 0x34, 0x08, 0x01, 0x02, 0x02, 0x08, 0x08, 0x08, 0x08, + 0x09, 0x08, 0x08, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x09, 0x89, + 0x56, 0x17, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x83, 0x2b, 0xa8, 0x0d, 0x41, + 0xb7, 0x59, 0x5c, 0x83, 0x2b, 0xa8, 0x0d, 0xdf, 0xb4, 0xb1, 0x32, 0xb5, + 0x0f, 0xc0, 0x25, 0xc5, 0x8d, 0xd9, 0x08, 0xc5, 0x28, 0x81, 0xd3, 0x73, + 0x52, 0xf9, 0x26, 0x9b, 0x66, 0x83, 0xaf, 0x24, 0x40, 0x8e, 0xa7, 0xd6, + 0x76, 0x12, 0x4a, 0x40, 0x61, 0xb5, 0x6a, 0xbc, 0x33, 0xef, 0x01, 0xda, + 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, + 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0x2b, 0x01, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x4e, 0x6b, 0x19, 0x54, 0xf5, 0xf0, 0xaf, 0x61, 0xfa, 0x1e, 0x1f, 0x1f, + 0x5e, 0x17, 0xd3, 0x8e, 0x04, 0x4b, 0xfa, 0x8d, 0x34, 0x55, 0x45, 0x92, + 0xd5, 0xd0, 0xb8, 0x8e, 0x56, 0xe9, 0x39, 0x37, 0x8e, 0x7d, 0x7e, 0x88, + 0x56, 0x30, 0x48, 0x61, 0xb4, 0xed, 0x1e, 0x15, 0x64, 0xfc, 0xa8, 0xb1, + 0x02, 0xbb, 0x9c, 0x14, 0xe9, 0xd1, 0xe0, 0xcf, 0x40, 0x41, 0x46, 0x5d, + 0xb0, 0xda, 0xba, 0x8c, 0x3a, 0x41, 0x12, 0x91, 0xeb, 0x13, 0xdf, 0x2c, + 0x6e, 0x25, 0x75, 0xb3, 0x92, 0xff, 0xb0, 0xa9, 0xa5, 0xef, 0x3a, 0x4c, + 0x6b, 0x54, 0x55, 0x0e, 0x7e, 0x93, 0x16, 0x7f, 0xe6, 0x22, 0x22, 0x51, + 0xe2, 0x22, 0xa4, 0x35, 0x33, 0xec, 0xdc, 0xa8, 0x73, 0x64, 0x59, 0xc1, + 0x4d, 0xad, 0xa0, 0x56, 0xbf, 0xad, 0x45, 0x64, 0xda, 0xb0, 0x08, 0x4a, + 0x82, 0xfc, 0x0d, 0x21, 0xb7, 0x8b, 0x59, 0x90, 0xac, 0xb2, 0x08, 0x1b, + 0x50, 0x82, 0x0c, 0x87, 0xd6, 0x48, 0x5c, 0xdd, 0x6b, 0x02, 0x7f, 0xab, + 0x3e, 0xdc, 0x25, 0x1f, 0x53, 0x49, 0xb5, 0x6d, 0x0f, 0x0c, 0xbe, 0xae, + 0x1d, 0xab, 0x8b, 0x13, 0x9d, 0xd7, 0x6c, 0x91, 0xaa, 0x90, 0xe8, 0x63, + 0x06, 0x6d, 0xa8, 0xf0, 0xea, 0x21, 0xf6, 0xa8, 0xfd, 0x15, 0x6d, 0x78, + 0x66, 0x42, 0xae, 0x4c, 0xa7, 0x7a, 0x85, 0x15, 0x7d, 0xf9, 0xed, 0x92, + 0x1c, 0xde, 0x7c, 0x71, 0xd0, 0x6b, 0x25, 0x24, 0x22, 0x6b, 0xe4, 0x5e, + 0x60, 0xda, 0xbd, 0x95, 0x32, 0x21, 0xe8, 0xb1, 0xcb, 0x07, 0x1b, 0x08, + 0xf5, 0x49, 0x4f, 0x60, 0x8c, 0xe8, 0xb0, 0x71, 0x2a, 0x8b, 0x91, 0x17, + 0x16, 0x93, 0x39, 0x49, 0x8d, 0x47, 0x1f, 0xe8, 0x2b, 0x12, 0xa6, 0x4f, + 0xa1, 0x77, 0x37, 0xe7, 0x39, 0x68, 0x5c, 0x68, 0x2b, 0xad, 0xa8, 0x3c, + 0xa0, 0x8a, 0xf5, 0xb7, 0x51, 0x9f, 0x2d, 0x85, 0x1a, 0x99, 0x02, 0x4c, + 0x84, 0x5f, 0x4d, 0xe6, 0x55, 0x64, 0xd7, 0x5b, 0x00, 0x48, 0xde, 0xf2, + 0x77, 0x39, 0x6e, 0x7b, 0x0e, 0x97, 0x81, 0xd2, 0x8a, 0x1b, 0x20, 0x30, + 0x60, 0xbe, 0x94, 0xf0, 0x09, 0x34, 0xfe, 0x64, 0xbb, 0xbb, 0xcb, 0x97, + 0x91, 0x43, 0x6d, 0x57, 0x45, 0x7d, 0xc5, 0x43, 0x5a, 0x78, 0x0d, 0xd8, + 0xb9, 0xf5, 0x43, 0x13, 0x21, 0xd6, 0x31, 0x6e, 0x21, 0x9a, 0x3f, 0x8f, + 0xe2, 0x57, 0x32, 0xdb, 0x50, 0x61, 0x45, 0x9f, 0xb9, 0x7b, 0x73, 0x10, + 0xb9, 0xd0, 0x66, 0xaf, 0xa0, 0x3a, 0x77, 0x93, 0x9b, 0xd3, 0x32, 0xb0, + 0xda, 0x01, 0x17, 0x90, 0x1a, 0xa5, 0x9f, 0x2b, 0x9f, 0x8f, 0x93, 0x6e, + 0x4d, 0x69, 0x40, 0xec, 0x56, 0x76, 0x61, 0x2d, 0xcd, 0xdf, 0xc5, 0xfe, + 0x9e, 0x26, 0x2f, 0x78, 0x78, 0xab, 0x5a, 0x32, 0xa6, 0xe9, 0x7a, 0x85, + 0x15, 0xc6, 0x2f, 0x10, 0x37, 0x35, 0xf6, 0xfa, 0xc0, 0xdd, 0xb0, 0xa9, + 0xa1, 0x0d, 0x22, 0xc1, 0xab, 0xc8, 0x8c, 0x2a, 0x77, 0x0b, 0xd3, 0x52, + 0xdb, 0x53, 0x33, 0x78, 0xf3, 0xf6, 0x33, 0x5d, 0x9f, 0xb7, 0xb6, 0x46, + 0xf6, 0x79, 0x9e, 0x08, 0x16, 0xd8, 0x48, 0xcf, 0x70, 0x4d, 0x00, 0x36, + 0x30, 0xdb, 0xb3, 0x76, 0xa5, 0x16, 0x78, 0xf8, 0xaf, 0x71, 0x6b, 0x50, + 0x92, 0xfc, 0x52, 0xd6, 0x2c, 0xee, 0xa8, 0xb0, 0xbe, 0x89, 0x18, 0xc0, + 0x7a, 0x72, 0xa5, 0x36, 0x31, 0x7b, 0x86, 0xca, 0xc0, 0xe4, 0x08, 0x17, + 0x1d, 0x6e, 0xe5, 0x4c, 0x82, 0x86, 0x3e, 0x8c, 0x60, 0xf7, 0x04, 0x8f, + 0x2c, 0x64, 0x3d, 0x2e, 0x23, 0x22, 0x10, 0x8e, 0x88, 0x45, 0xcd, 0x18, + 0xd6, 0xba, 0x4c, 0x40, 0x1e, 0x31, 0xfb, 0xbf, 0xda, 0xe7, 0xae, 0x87, + 0x72, 0x81, 0xb2, 0x69, 0x97, 0xe3, 0x2c, 0x5e, 0xbb, 0x26, 0x1b, 0xe2, + 0x83, 0xf3, 0x90, 0x37, 0x0d, 0xb1, 0xa2, 0x58, 0x88, 0x63, 0xe7, 0x6e, + 0x4a, 0xbd, 0x76, 0x90, 0x73, 0x65, 0x85, 0x96, 0xcc, 0x2d, 0xb7, 0x51, + 0x0d, 0xa7, 0x8a, 0xe2, 0x8c, 0x47, 0xb9, 0x44, 0x09, 0xc3, 0x8f, 0x24, + 0x65, 0x79, 0xf0, 0xd0, 0xc3, 0xa5, 0x1f, 0xc3, 0xca, 0xd7, 0x57, 0xac, + 0x1c, 0xcf, 0xa9, 0xfc, 0x81, 0x12, 0x53, 0x0b, 0xe5, 0x9d, 0x38, 0x29, + 0x14, 0xd6, 0xf5, 0x17, 0x06, 0xfb, 0xc2, 0x9d, 0x25, 0x10, 0xf9, 0xde, + 0x4b, 0x33, 0x0d, 0xf1, 0xdd, 0xf5, 0xbc, 0xa8, 0x2b, 0xdc, 0xdb, 0x51, + 0x7d, 0x69, 0x63, 0x68, 0x61, 0x74, 0x64, 0x6b, 0x75, 0x85, 0x41, 0x03, + 0x23, 0x00, 0x07, 0x07, 0x08, 0x34, 0x00, 0x09, 0x09, 0x09, 0x34, 0x34, + 0x08, 0x01, 0x02, 0x02, 0x08, 0x08, 0x08, 0x08, 0x09, 0x08, 0x08, 0x09, + 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x09, 0x89, 0x16, 0x17, 0x13, 0x41, + 0xb7, 0x59, 0x5c, 0x83, 0x25, 0xab, 0x8f, 0x41, 0xb7, 0x59, 0x5c, 0x83, + 0x25, 0xab, 0x8f, 0xdf, 0xb4, 0xb1, 0x32, 0xb5, 0x0f, 0xc0, 0x25, 0xc5, + 0x8d, 0xd9, 0x08, 0xc5, 0x28, 0x81, 0xd3, 0x73, 0x52, 0xf9, 0x26, 0x9b, + 0x66, 0x83, 0xaf, 0x24, 0x40, 0x8e, 0xa7, 0xd6, 0x76, 0x12, 0x4a, 0x40, + 0x61, 0xb5, 0x6a, 0xbc, 0x33, 0xef, 0x01, 0xda, 0x39, 0xa3, 0xee, 0x5e, + 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, + 0xd8, 0x07, 0x09, 0x2b, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xe3, 0xb5, 0xfb, 0x0d, + 0xa0, 0x75, 0xd1, 0xa9, 0x33, 0x31, 0xc6, 0x84, 0xba, 0x58, 0x50, 0xb0, + 0x71, 0x32, 0x4f, 0x72, 0x88, 0x46, 0x71, 0x06, 0xb3, 0x82, 0x5e, 0x30, + 0xfd, 0xc8, 0x5b, 0xc8, 0xf3, 0x24, 0x92, 0xe0, 0xce, 0x8b, 0xf7, 0x50, + 0x20, 0xc3, 0xeb, 0x1b, 0xf4, 0xef, 0x4f, 0xfa, 0x28, 0x4d, 0x02, 0x4d, + 0x7c, 0x46, 0xf1, 0x91, 0x89, 0xde, 0xc6, 0xfa, 0x79, 0xc5, 0xbd, 0x17, + 0xa1, 0xc6, 0x1d, 0x8c, 0xd4, 0x57, 0xa6, 0x58, 0x66, 0xce, 0xe5, 0xb0, + 0x8b, 0x54, 0xef, 0x3b, 0x24, 0x9b, 0xa4, 0xc4, 0x6a, 0xa9, 0xf3, 0x1b, + 0x73, 0x37, 0x10, 0xc0, 0xe1, 0xcb, 0xc8, 0x90, 0x14, 0x88, 0x97, 0x25, + 0x8b, 0x7c, 0xa2, 0x66, 0x36, 0x89, 0x55, 0x8d, 0x68, 0xe7, 0x55, 0x20, + 0x10, 0x68, 0x14, 0x2f, 0x05, 0x3b, 0xe3, 0x81, 0x08, 0xfe, 0x54, 0x7d, + 0xa5, 0x51, 0x2a, 0x39, 0x86, 0x11, 0xce, 0x26, 0x8d, 0xe1, 0xec, 0x30, + 0x3f, 0xf9, 0xa3, 0x3d, 0x43, 0x6c, 0xad, 0x23, 0x54, 0x20, 0x7d, 0x60, + 0xa5, 0x42, 0xbd, 0x3d, 0x22, 0xc8, 0x95, 0x9b, 0xab, 0x5b, 0xf7, 0xc1, + 0x11, 0xfb, 0xf1, 0x70, 0xa2, 0x43, 0xcb, 0x53, 0x8c, 0x18, 0x0d, 0x8a, + 0xb2, 0xa5, 0xbd, 0x87, 0x2b, 0x8b, 0xdf, 0x79, 0x96, 0x29, 0x20, 0x8e, + 0x34, 0x4a, 0x45, 0x96, 0x33, 0x8d, 0xa8, 0xb0, 0x47, 0x26, 0x4f, 0x8b, + 0xad, 0xb5, 0xa7, 0x2d, 0x15, 0x58, 0x92, 0x7b, 0x4b, 0x53, 0xa9, 0x5e, + 0x51, 0x39, 0x9c, 0xbd, 0x7e, 0x8f, 0x7f, 0x9f, 0xb7, 0x38, 0xcd, 0x7e, + 0xff, 0x7d, 0x73, 0x1f, 0xab, 0x3a, 0x61, 0xaa, 0xde, 0x73, 0x28, 0xb2, + 0x6f, 0x1e, 0xc9, 0x5e, 0x59, 0x71, 0x6b, 0xe8, 0x6d, 0x63, 0xf3, 0x9e, + 0xdf, 0x52, 0x86, 0x60, 0x1c, 0xbd, 0xc7, 0xeb, 0xaf, 0x82, 0x83, 0xaa, + 0x68, 0xa6, 0x71, 0x7a, 0xe8, 0xd3, 0xd4, 0xc8, 0xe7, 0x9a, 0xcc, 0x3c, + 0xc2, 0xdf, 0x0c, 0x42, 0xe8, 0xae, 0xc7, 0xd8, 0x1f, 0x66, 0x0a, 0x57, + 0x09, 0x14, 0x02, 0x74, 0x9a, 0x7a, 0x07, 0xb3, 0x19, 0x87, 0x8d, 0xa9, + 0x45, 0x25, 0x26, 0x48, 0xb3, 0x20, 0x3c, 0xf7, 0x5a, 0x1c, 0xae, 0xc7, + 0x06, 0x9e, 0x1a, 0x0a, 0x23, 0xf3, 0x39, 0x25, 0x2c, 0x91, 0x7c, 0x5e, + 0x87, 0xe7, 0x55, 0xc4, 0x69, 0xf3, 0x3e, 0xeb, 0xc5, 0x44, 0xa8, 0xe3, + 0xec, 0xc1, 0xfe, 0x70, 0xbf, 0xdd, 0xbb, 0xf0, 0x22, 0xe1, 0x19, 0xa1, + 0x6d, 0x7a, 0x9a, 0xa3, 0x36, 0x90, 0xbc, 0x1a, 0xa7, 0x37, 0xf8, 0xcf, + 0xdc, 0x9e, 0x23, 0x17, 0x42, 0xd5, 0xa0, 0xd3, 0x36, 0xb0, 0xb1, 0xf5, + 0x1a, 0x95, 0xbc, 0xe8, 0x0f, 0xb4, 0x58, 0x76, 0x40, 0x74, 0xd0, 0x21, + 0xaf, 0xae, 0xc6, 0xb4, 0x84, 0xd7, 0xfc, 0x70, 0x6a, 0x8f, 0x41, 0x57, + 0x2b, 0x8e, 0xbc, 0x6b, 0x21, 0x65, 0xcc, 0xa0, 0x8e, 0xb9, 0x0b, 0x46, + 0xef, 0xb3, 0x56, 0xec, 0x8a, 0xd6, 0x4d, 0xdd, 0x97, 0xbd, 0xdd, 0x65, + 0xbf, 0x26, 0xab, 0xba, 0x0d, 0xd1, 0x22, 0x7e, 0xb6, 0x8a, 0xb4, 0x92, + 0xc9, 0xa6, 0x48, 0xd4, 0x64, 0x17, 0xc6, 0xb5, 0xb9, 0xce, 0x45, 0x6d, + 0xf4, 0xd9, 0x3d, 0xa0, 0xb3, 0x86, 0x67, 0x19, 0xad, 0xd8, 0x32, 0x2b, + 0xf7, 0xab, 0x90, 0xee, 0x91, 0x8f, 0x73, 0xe4, 0xc0, 0x29, 0xde, 0x45, + 0x8a, 0xfb, 0xca, 0x74, 0x3b, 0x50, 0xf1, 0x34, 0x40, 0x36, 0x25, 0x8a, + 0xe0, 0xf9, 0x7f, 0x55, 0xc5, 0x59, 0x89, 0xbb, 0x43, 0x03, 0xa3, 0xdd, + 0x8c, 0x83, 0x03, 0xc6, 0xef, 0x60, 0x02, 0xc5, 0xd8, 0x29, 0x3f, 0x2f, + 0x56, 0xba, 0x8b, 0x97, 0x0a, 0xc4, 0xf3, 0x07, 0x3f, 0xca, 0x0f, 0xdf, + 0xb9, 0x5d, 0x59, 0x42, 0x36, 0x02, 0xf7, 0x0f, 0x03, 0xc8, 0xf2, 0xb7, + 0xd8, 0x64, 0xcd, 0x1e, 0xe4, 0xe1, 0xa0, 0xbd, 0x0f, 0x70, 0xfb, 0xcf, + 0x77, 0x77, 0xef, 0x9d, 0xdd, 0xc1, 0x61, 0xab, 0x3c, 0xdb, 0xe4, 0x35, + 0x11, 0xab, 0xde, 0x40, 0x7d, 0x51, 0xba, 0xb1, 0x7d, 0x13, 0xf1, 0x58, + 0x03, 0xca, 0xae, 0x12, 0x4a, 0xa3, 0xb6, 0xed, 0xd7, 0x18, 0x1c, 0xb6, + 0xd8, 0x69, 0x63, 0x68, 0x61, 0x74, 0x64, 0x6b, 0x75, 0x89, 0x70, 0x02, + 0x23, 0x00, 0x07, 0x07, 0x09, 0x34, 0x00, 0x09, 0x09, 0x09, 0x34, 0x34, + 0x08, 0x01, 0x02, 0x02, 0x08, 0x08, 0x08, 0x08, 0x09, 0x08, 0x08, 0x09, + 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x09, 0x91, 0x62, 0x29, 0x13, 0x41, + 0xb7, 0x59, 0x5c, 0x4b, 0xa2, 0xb8, 0x84, 0x41, 0xb7, 0x59, 0x5c, 0x4b, + 0xa2, 0xb8, 0x84, 0x37, 0xee, 0x5a, 0x85, 0xe1, 0xcb, 0xdd, 0xc8, 0xce, + 0x07, 0x77, 0xee, 0x01, 0x3f, 0x96, 0x7b, 0x33, 0x30, 0x3a, 0xcd, 0x64, + 0x14, 0x5e, 0x86, 0xb3, 0x7b, 0x2d, 0x6c, 0xa9, 0xc0, 0xcf, 0xd8, 0x43, + 0x7e, 0x59, 0x45, 0xac, 0xff, 0x92, 0x4b, 0xda, 0x39, 0xa3, 0xee, 0x5e, + 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, + 0xd8, 0x07, 0x09, 0x2a, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xfa, 0x4b, 0x92, 0xea, + 0x4b, 0xef, 0xde, 0x03, 0xd5, 0xe2, 0xee, 0xe5, 0x67, 0xd4, 0x99, 0x63, + 0x37, 0x68, 0x91, 0xbc, 0x4f, 0xbc, 0x41, 0xe9, 0x01, 0xc5, 0x4d, 0x59, + 0x2a, 0x9b, 0x42, 0x60, 0x07, 0x7e, 0xc2, 0xbc, 0x62, 0xcc, 0xbc, 0xa7, + 0xf1, 0xe4, 0x20, 0x5f, 0xe3, 0xe8, 0x9f, 0x16, 0x7a, 0x77, 0xd2, 0xb7, + 0xad, 0x98, 0xc3, 0xb4, 0x99, 0xdb, 0x36, 0x1a, 0xe4, 0xf0, 0xfc, 0xe1, + 0xc8, 0x2f, 0x8c, 0xcf, 0x6f, 0x97, 0x48, 0x09, 0x4a, 0xae, 0xc7, 0xf9, + 0xfb, 0xb7, 0x5f, 0x64, 0x6a, 0x79, 0xa1, 0x27, 0xeb, 0x59, 0x7d, 0x0a, + 0xd3, 0x56, 0x27, 0x1d, 0x56, 0xd3, 0x62, 0x1e, 0x7f, 0xb5, 0x0f, 0x50, + 0x9c, 0x4d, 0x1d, 0xd5, 0x53, 0xcb, 0x08, 0x07, 0x56, 0x93, 0x9e, 0x4f, + 0xb2, 0xd0, 0x12, 0xc7, 0x50, 0xcf, 0x99, 0xac, 0x24, 0xdb, 0x94, 0xab, + 0x08, 0x89, 0x60, 0x2f, 0x6c, 0xd0, 0xc2, 0x2e, 0x6d, 0x08, 0xe0, 0xf9, + 0xfc, 0x7e, 0x5b, 0x54, 0x92, 0xaa, 0x01, 0xfd, 0xf6, 0x49, 0xb1, 0xfc, + 0xd4, 0x51, 0x83, 0x73, 0xaf, 0xac, 0x38, 0x78, 0x8e, 0x9b, 0x42, 0x4e, + 0x83, 0xbb, 0x9d, 0xd7, 0x5c, 0xdb, 0x73, 0xd3, 0x3d, 0x2c, 0xe2, 0x4c, + 0x57, 0xa4, 0xfa, 0xdf, 0x53, 0x44, 0x29, 0x71, 0x22, 0xb6, 0x89, 0x84, + 0x80, 0xca, 0xcb, 0x7c, 0x5f, 0x15, 0x19, 0x4b, 0x06, 0x28, 0x5d, 0x4a, + 0x9b, 0xc8, 0x59, 0xa7, 0x9e, 0xa2, 0xba, 0x32, 0x5d, 0xf2, 0xcb, 0xa9, + 0xc6, 0xba, 0x09, 0xee, 0xd2, 0x00, 0x32, 0x53, 0x8b, 0x39, 0xff, 0xc4, + 0x63, 0xac, 0xbc, 0x1c, 0x15, 0xb8, 0x79, 0xc2, 0xe3, 0xda, 0x8d, 0xb2, + 0x95, 0x8d, 0x3c, 0x10, 0xec, 0x93, 0x03, 0xc1, 0x07, 0x84, 0x47, 0xf3, + 0xeb, 0xe3, 0x10, 0x33, 0xa1, 0x2e, 0xc6, 0x48, 0x44, 0x2c, 0x38, 0x36, + 0xe1, 0x68, 0x3c, 0xe8, 0x0d, 0x5c, 0x8a, 0xdc, 0x1f, 0xe8, 0x3b, 0xb2, + 0x0f, 0xea, 0x27, 0x18, 0x7a, 0x7f, 0x82, 0x6a, 0x96, 0xfa, 0x63, 0xd3, + 0x5c, 0xbf, 0xf6, 0x1d, 0x9e, 0xf2, 0xd9, 0x83, 0x3b, 0xf0, 0x1b, 0x29, + 0x49, 0x8d, 0xb3, 0xdc, 0x60, 0x47, 0x9d, 0x2b, 0xac, 0xd6, 0x6e, 0x59, + 0xb3, 0x09, 0x0d, 0xa7, 0xfb, 0x0e, 0x43, 0x56, 0xa3, 0x80, 0x2c, 0x9f, + 0xc1, 0xe8, 0xd2, 0xef, 0x05, 0xc5, 0x25, 0x4c, 0x5b, 0x67, 0x1a, 0x54, + 0x0b, 0x55, 0x83, 0x3d, 0xfb, 0x38, 0x0e, 0xd2, 0xc0, 0x1a, 0xcd, 0x9f, + 0x81, 0x3e, 0x6d, 0x7f, 0xe4, 0x3f, 0x34, 0x0c, 0xdc, 0x99, 0x5a, 0x77, + 0xd4, 0xe4, 0xff, 0x4a, 0x7b, 0x8a, 0x95, 0xe4, 0x46, 0x3d, 0x7b, 0xc4, + 0x0e, 0xdd, 0xc7, 0x2d, 0xf4, 0xfa, 0x5e, 0x50, 0xae, 0x9c, 0xca, 0x64, + 0x97, 0xad, 0x03, 0x30, 0x3e, 0x05, 0xc4, 0x33, 0x1e, 0x2c, 0x03, 0x2b, + 0x06, 0x2c, 0x79, 0x13, 0xae, 0x1b, 0x65, 0xf1, 0x1f, 0xb9, 0xe4, 0x8a, + 0x06, 0x96, 0xea, 0xc4, 0x6e, 0x17, 0x19, 0x03, 0x54, 0xe8, 0x39, 0xe7, + 0xeb, 0x7b, 0xbc, 0x25, 0xd6, 0x55, 0x6c, 0x76, 0x5f, 0xf7, 0xd2, 0x0e, + 0x54, 0x46, 0x9f, 0x5d, 0xa4, 0x3d, 0xac, 0xa1, 0x19, 0x7b, 0x7c, 0x5a, + 0x44, 0x54, 0x65, 0x5d, 0x43, 0x26, 0x5f, 0x47, 0x63, 0x2b, 0x00, 0xe3, + 0xb4, 0xe9, 0x70, 0x8c, 0x31, 0x50, 0x7c, 0x37, 0x01, 0x43, 0x6c, 0x29, + 0xc3, 0xae, 0x59, 0xb7, 0x0b, 0xb9, 0x9a, 0x72, 0x69, 0xe0, 0xd1, 0xb0, + 0x47, 0x53, 0xf0, 0xb8, 0x8b, 0xc8, 0x80, 0x3c, 0x58, 0xfa, 0x34, 0xf2, + 0x44, 0x27, 0xb7, 0xfc, 0x44, 0x73, 0xfb, 0xe5, 0xe1, 0x8b, 0xdb, 0x2b, + 0xc5, 0x73, 0x97, 0x25, 0xb3, 0xef, 0x16, 0xfd, 0xba, 0x08, 0x3d, 0x15, + 0x2a, 0x03, 0xb5, 0x4d, 0x2a, 0x8c, 0xf5, 0x53, 0x11, 0x97, 0x3c, 0x35, + 0x66, 0x1d, 0x59, 0xc8, 0xc9, 0x79, 0x48, 0x6d, 0x19, 0x4f, 0xa7, 0x07, + 0x25, 0x4d, 0xb2, 0xfc, 0x1e, 0xbc, 0x9a, 0x0c, 0x6e, 0x46, 0x2b, 0x58, + 0x45, 0xbe, 0xe7, 0x8e, 0x09, 0xa5, 0xa0, 0xd3, 0x5a, 0xf5, 0x6e, 0x92, + 0x7b, 0x5b, 0x21, 0x07, 0xab, 0xf3, 0x57, 0xd6, 0x93, 0x4b, 0x56, 0x3b, + 0x9c, 0x3c, 0x4b, 0x85, 0xb0, 0x62, 0x18, 0x3e, 0x7c, 0xc5, 0x25, 0xe2, + 0xf2, 0xfc, 0xa3, 0xca, 0x88, 0xd6, 0xb2, 0x01, 0x11, 0xcd, 0x93, 0x9a, + 0x76, 0x84, 0xc2, 0x2d, 0x07, 0xd3, 0xbb, 0xac, 0x99, 0xde, 0x29, 0x00, + 0xf7, 0x3d, 0x06, 0xea, 0xdc, 0x88, 0xfd, 0xc6, 0x6e, 0xf5, 0x55, 0x64, + 0x73, 0x4e, 0x3b, 0xa9, 0x24, 0x44, 0x63, 0x1c, 0x50, 0x29, 0x66, 0xc4, + 0x74, 0x70, 0xcb, 0xd8, 0x57, 0x0c, 0x60, 0x50, 0x6d, 0x64, 0x64, 0xd1, + 0x53, 0xef, 0x62, 0xef, 0x61, 0xf4, 0xe2, 0xfe, 0x4c, 0xaa, 0x9f, 0xe9, + 0x81, 0x01, 0xe1, 0x97, 0xaa, 0xc0, 0x06, 0xbf, 0x40, 0x19, 0x64, 0x24, + 0x6e, 0x80, 0x73, 0x00, 0x5c, 0x86, 0x3e, 0xc2, 0xcf, 0x8c, 0x09, 0xc0, + 0xfa, 0x4a, 0xb3, 0x3a, 0x0d, 0x81, 0x1d, 0x49, 0x58, 0x09, 0xe8, 0x31, + 0x0e, 0xd7, 0x60, 0x8d, 0x9d, 0xfe, 0x9f, 0x35, 0xf7, 0x8d, 0xa1, 0x12, + 0x04, 0xb2, 0x47, 0xac, 0x31, 0x92, 0x03, 0x0a, 0x10, 0x50, 0xb7, 0x86, + 0x3d, 0xcd, 0x15, 0x8f, 0x25, 0x93, 0x24, 0x7a, 0x5f, 0xa0, 0x3c, 0x41, + 0xaa, 0xb2, 0x96, 0xce, 0xd3, 0x0c, 0xe9, 0x55, 0x66, 0x37, 0x5c, 0xf3, + 0x02, 0x3c, 0xa1, 0x09, 0xa4, 0x9e, 0x90, 0xc9, 0x82, 0xab, 0xd4, 0x04, + 0x2e, 0x8b, 0xb4, 0x8d, 0x5b, 0xcc, 0x19, 0x5a, 0xfe, 0x86, 0x9c, 0x6c, + 0x56, 0x09, 0x86, 0x36, 0xef, 0xe8, 0x1f, 0x3a, 0xbc, 0xda, 0x4c, 0x68, + 0xac, 0xa2, 0x1b, 0xd1, 0x23, 0x75, 0x28, 0xed, 0x9f, 0x84, 0x2e, 0x40, + 0x57, 0x5f, 0x0a, 0x85, 0xe4, 0x77, 0x59, 0x53, 0x12, 0x32, 0xd6, 0x3c, + 0x1b, 0xaf, 0x95, 0xa1, 0x1c, 0x14, 0x1a, 0x42, 0x7d, 0xc7, 0x7b, 0x21, + 0xd1, 0x4e, 0xb9, 0x29, 0x85, 0xef, 0xa2, 0x61, 0x1c, 0xe5, 0x16, 0x44, + 0xbe, 0xfb, 0xa3, 0x21, 0x4f, 0x94, 0x70, 0xff, 0x5c, 0xc2, 0x1d, 0x0b, + 0x39, 0x36, 0x84, 0x0e, 0x61, 0xe2, 0x1c, 0x63, 0x74, 0xe0, 0x30, 0x01, + 0xbe, 0x39, 0x0f, 0x6f, 0xe6, 0x29, 0xad, 0xd8, 0x8c, 0xdd, 0x8b, 0x24, + 0x38, 0x6f, 0x67, 0x8a, 0x2d, 0x82, 0x1e, 0x8e, 0x45, 0xcb, 0xec, 0x2d, + 0xe3, 0xb4, 0x03, 0x8e, 0x46, 0x2e, 0x01, 0xb0, 0xca, 0x4f, 0xe0, 0x2c, + 0x52, 0xd3, 0x4c, 0xdd, 0xd6, 0x62, 0xf3, 0x38, 0x3f, 0x3c, 0xc1, 0x58, + 0xaa, 0x87, 0x3d, 0x4f, 0xb2, 0xb1, 0x54, 0x65, 0xdc, 0x1c, 0xc8, 0x16, + 0x88, 0x15, 0x53, 0xb0, 0x4e, 0x77, 0xae, 0xe0, 0x34, 0x18, 0x36, 0x34, + 0x31, 0x74, 0x4c, 0x79, 0x0f, 0x2b, 0x1a, 0x11, 0x06, 0x06, 0xaa, 0x60, + 0x31, 0x6e, 0x65, 0x9e, 0x1b, 0xb0, 0x61, 0xd6, 0x90, 0xd1, 0x1d, 0x4c, + 0x36, 0xfe, 0xec, 0x26, 0xcc, 0xba, 0xce, 0xd7, 0xe7, 0x0c, 0x53, 0x90, + 0xe8, 0xce, 0xce, 0xed, 0x58, 0x37, 0x37, 0x3f, 0x40, 0x39, 0xeb, 0x8c, + 0xfb, 0x7d, 0x93, 0xa2, 0x26, 0x4e, 0xbf, 0x49, 0xe7, 0x95, 0xc0, 0x12, + 0x6a, 0xec, 0xfb, 0xbe, 0x00, 0x62, 0xb9, 0xc9, 0x0d, 0x5a, 0x37, 0xf9, + 0xae, 0x84, 0x95, 0x89, 0x20, 0x47, 0x48, 0xf6, 0xf8, 0x73, 0x92, 0x5f, + 0xe1, 0x4a, 0xb4, 0x9e, 0xd8, 0x75, 0xf3, 0x38, 0x48, 0xe1, 0x29, 0x95, + 0x0d, 0x74, 0x6b, 0x98, 0x96, 0x6e, 0xc9, 0x3f, 0xfc, 0x44, 0x91, 0x4d, + 0xf4, 0x4c, 0xb7, 0x38, 0xd7, 0xec, 0xbf, 0xf6, 0x78, 0x05, 0x7d, 0x1b, + 0xe5, 0x68, 0x8a, 0xbc, 0x6a, 0x6a, 0x29, 0xb6, 0xc6, 0x9a, 0x8d, 0x7a, + 0x0e, 0x00, 0x80, 0x73, 0xf5, 0x88, 0x5d, 0x2a, 0xa2, 0x60, 0x98, 0x1e, + 0xf5, 0x06, 0x3b, 0xef, 0xa9, 0x46, 0x6b, 0x89, 0x24, 0xb0, 0xf4, 0x34, + 0x42, 0x15, 0x87, 0xd3, 0xc9, 0x36, 0xe0, 0x52, 0x5f, 0x57, 0x8e, 0x65, + 0x5c, 0x7f, 0x7c, 0xf2, 0x66, 0xd8, 0xd1, 0xbf, 0x13, 0x95, 0x65, 0xb0, + 0x7a, 0xa0, 0xbb, 0xee, 0xc9, 0x20, 0xff, 0x26, 0xda, 0xa0, 0x61, 0x65, + 0xd5, 0x3c, 0xdf, 0xb5, 0xf0, 0xd2, 0x02, 0x4f, 0x97, 0x65, 0x48, 0x63, + 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x73, + 0x64, 0x64, 0x6b, 0x75, 0x8a, 0x11, 0x01, 0x23, 0x00, 0x07, 0x07, 0x09, + 0x34, 0x00, 0x09, 0x09, 0x09, 0x34, 0x34, 0x08, 0x01, 0x02, 0x02, 0x08, + 0x08, 0x08, 0x08, 0x09, 0x08, 0x08, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, + 0x08, 0x09, 0x92, 0x1a, 0x33, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x4b, 0x89, + 0xf6, 0xba, 0x41, 0xb7, 0x59, 0x5c, 0x4b, 0x89, 0xf6, 0xba, 0xb1, 0x0a, + 0x33, 0x78, 0x48, 0x21, 0xea, 0x97, 0x6e, 0xb7, 0xc7, 0x2e, 0xdb, 0x0f, + 0x9b, 0x01, 0xd0, 0x22, 0x6d, 0xbb, 0x64, 0x14, 0x5e, 0x86, 0xb3, 0x7b, + 0x2d, 0x6c, 0xa9, 0xc0, 0xcf, 0xd8, 0x43, 0x7e, 0x59, 0x45, 0xac, 0xff, + 0x92, 0x4b, 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, + 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0x2a, 0x04, + 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x12, 0x83, 0x28, 0x8c, 0xcd, 0x78, 0x8c, 0x1b, 0x02, + 0xa2, 0x38, 0xa7, 0x25, 0xc1, 0x25, 0x59, 0xcd, 0x36, 0xb2, 0x21, 0xa1, + 0x91, 0xd0, 0xc3, 0x54, 0x89, 0x64, 0xa8, 0x3d, 0x07, 0xcb, 0x8f, 0xf7, + 0xa6, 0x55, 0xc2, 0x96, 0xf6, 0x35, 0xc1, 0x67, 0xdf, 0x2f, 0x1f, 0xda, + 0xa8, 0xf8, 0x8c, 0xc9, 0xa7, 0x5e, 0x7f, 0x1f, 0xa8, 0xd3, 0x38, 0x57, + 0xa2, 0xf4, 0x57, 0x32, 0x17, 0xe3, 0x06, 0xe3, 0xb6, 0x56, 0x60, 0x6e, + 0xbe, 0x12, 0x60, 0x00, 0xfd, 0xa8, 0x4c, 0x3f, 0x2b, 0x54, 0x9c, 0xfb, + 0x87, 0x8b, 0xfa, 0x9e, 0xb8, 0xb2, 0x80, 0x36, 0xf1, 0x5b, 0xcd, 0x9d, + 0x74, 0xa1, 0x7b, 0xbf, 0xf6, 0x4c, 0x64, 0x58, 0x67, 0x8b, 0x68, 0x05, + 0x15, 0x7e, 0x4b, 0x54, 0xe9, 0x84, 0x59, 0x70, 0x42, 0x80, 0x67, 0x6c, + 0x45, 0x62, 0x12, 0x03, 0x27, 0x2b, 0x32, 0xdc, 0x78, 0x85, 0x3d, 0x74, + 0x28, 0x89, 0x5c, 0x33, 0x15, 0x79, 0x63, 0x1f, 0xd7, 0x26, 0xbf, 0x5d, + 0xf6, 0xb1, 0xb7, 0x9e, 0x37, 0x86, 0xd8, 0xf6, 0xf9, 0xc3, 0x66, 0x90, + 0x50, 0x5a, 0x0e, 0xeb, 0xcc, 0xe0, 0xf2, 0x19, 0xbb, 0xd7, 0x6a, 0xe4, + 0xea, 0x87, 0xf9, 0x17, 0x20, 0x88, 0xf6, 0xc0, 0xc7, 0xb7, 0x55, 0x25, + 0xef, 0x15, 0xec, 0xc5, 0x80, 0x52, 0x9a, 0x92, 0xdb, 0x32, 0xf3, 0xc2, + 0xa2, 0x55, 0xd6, 0xd9, 0x5b, 0xe6, 0xb1, 0x95, 0x18, 0x2b, 0xf8, 0x94, + 0x21, 0x56, 0x29, 0x30, 0xf3, 0x61, 0x39, 0x22, 0x03, 0x86, 0xce, 0x81, + 0x6d, 0x9e, 0xdb, 0x5b, 0x49, 0xdb, 0x2c, 0x1d, 0x0d, 0x45, 0xa9, 0xb3, + 0x1c, 0x1a, 0x43, 0x36, 0x1d, 0xd2, 0x76, 0x28, 0x27, 0xe0, 0xd3, 0x19, + 0x56, 0xd3, 0x52, 0xb2, 0xa0, 0x9c, 0xda, 0xb7, 0xac, 0x4d, 0xb1, 0x98, + 0x22, 0xa5, 0x86, 0x5d, 0x79, 0x6a, 0x69, 0x06, 0xd7, 0x07, 0xe7, 0x44, + 0x55, 0x6c, 0xc7, 0xd0, 0x8a, 0x2b, 0xa1, 0x45, 0xc6, 0xbf, 0xf3, 0x21, + 0x2e, 0x41, 0x5c, 0x84, 0xa2, 0x77, 0x46, 0x65, 0x80, 0x75, 0xba, 0x49, + 0xd6, 0xd7, 0x73, 0xeb, 0x35, 0x2c, 0x46, 0x58, 0xc4, 0x1d, 0x2f, 0x6b, + 0xe6, 0x6c, 0xa7, 0x5f, 0x95, 0x0c, 0xbc, 0x60, 0x00, 0x3d, 0xa9, 0x0a, + 0xd6, 0x0a, 0x66, 0x59, 0xc0, 0x9b, 0x49, 0x5b, 0x4c, 0x73, 0xf5, 0x9e, + 0x6d, 0x38, 0xdd, 0x0f, 0x25, 0xe4, 0x35, 0x84, 0x34, 0x25, 0xfe, 0x71, + 0x35, 0x78, 0xa7, 0x5b, 0xc1, 0x7a, 0xab, 0xd7, 0xeb, 0x2f, 0x54, 0x93, + 0x94, 0x49, 0x8a, 0x1e, 0x04, 0xe6, 0xfc, 0xd7, 0xe3, 0xa2, 0x41, 0x25, + 0x5a, 0xa5, 0x46, 0x59, 0x85, 0xfb, 0x21, 0xc7, 0x02, 0x48, 0x79, 0xd4, + 0xef, 0xc4, 0x03, 0xc2, 0x0a, 0x4b, 0x42, 0x1c, 0x73, 0x35, 0xcd, 0x21, + 0x8b, 0xd5, 0xfc, 0xa3, 0xdc, 0xbb, 0x4b, 0xa3, 0x45, 0x04, 0x73, 0xa1, + 0xdb, 0x3a, 0x97, 0x0e, 0xc7, 0x1c, 0xe2, 0x67, 0x04, 0xd4, 0x49, 0x68, + 0x0e, 0x05, 0xcb, 0x52, 0xd4, 0x37, 0x75, 0xd8, 0x2a, 0x17, 0xd3, 0x7a, + 0x93, 0x96, 0x46, 0xfb, 0x07, 0x6d, 0x3b, 0x92, 0x60, 0xf4, 0x35, 0x94, + 0x3b, 0xbd, 0x2e, 0xf6, 0x0b, 0x18, 0xd5, 0x0d, 0x1b, 0xe1, 0xd3, 0x14, + 0xc1, 0x84, 0xd7, 0x67, 0xd7, 0x96, 0x2d, 0xa9, 0xab, 0x59, 0x70, 0x43, + 0x7b, 0xea, 0x25, 0xa3, 0x05, 0x1c, 0x45, 0xf6, 0x34, 0x51, 0x8e, 0xaf, + 0x46, 0x33, 0x90, 0x68, 0x28, 0x4f, 0x38, 0x5b, 0xbb, 0x69, 0xee, 0xbb, + 0x0a, 0x4c, 0x76, 0x1c, 0x3d, 0xfd, 0xea, 0x1f, 0x77, 0x9e, 0xd4, 0xa1, + 0xeb, 0x74, 0x16, 0x60, 0x20, 0xe9, 0x44, 0xc1, 0x90, 0x2c, 0x7b, 0x77, + 0x6f, 0x70, 0xe3, 0x62, 0x0f, 0xc3, 0x20, 0xf6, 0xce, 0xc3, 0xa6, 0x0e, + 0x9c, 0x6d, 0xa3, 0xa0, 0x21, 0x1c, 0x28, 0x7f, 0x44, 0xd7, 0xa9, 0x87, + 0x62, 0x91, 0x4d, 0x2a, 0x93, 0xe2, 0xc7, 0x94, 0x0c, 0x75, 0x1d, 0xf6, + 0xc7, 0xf8, 0x36, 0x09, 0xa8, 0x23, 0xa3, 0x80, 0x52, 0x2d, 0xe7, 0x0b, + 0x44, 0x5d, 0x4b, 0xf5, 0xdc, 0x57, 0xa3, 0x02, 0x40, 0x89, 0xdc, 0x40, + 0xf7, 0x5c, 0xad, 0xea, 0x5c, 0x1a, 0x59, 0xfc, 0xb8, 0xaf, 0xcb, 0x71, + 0xe0, 0x08, 0xdc, 0x80, 0x08, 0x8a, 0x32, 0x85, 0x46, 0xa9, 0x9a, 0x17, + 0x6b, 0x25, 0x9c, 0xfe, 0x7d, 0x90, 0x22, 0x6e, 0x7b, 0x01, 0x24, 0x17, + 0xf6, 0xa7, 0x70, 0x93, 0x03, 0x60, 0xc2, 0x0d, 0x7b, 0x3b, 0xe8, 0x5b, + 0x02, 0xb0, 0x6d, 0x00, 0x62, 0x97, 0x1b, 0x84, 0x86, 0x27, 0x72, 0x2d, + 0x90, 0xee, 0xdc, 0xb6, 0xb8, 0xa5, 0x58, 0x73, 0x29, 0x9b, 0x06, 0x99, + 0xda, 0x4f, 0x12, 0x0c, 0x74, 0x0a, 0xc1, 0x1b, 0x34, 0x20, 0xfa, 0x6d, + 0x01, 0xd2, 0x1b, 0xf2, 0x0f, 0xe3, 0xfe, 0x34, 0x2d, 0x44, 0x4f, 0xa3, + 0x6a, 0xab, 0xaa, 0x7e, 0x1c, 0x35, 0xef, 0xfe, 0xa0, 0xc1, 0x8a, 0xeb, + 0x77, 0x80, 0xd6, 0x57, 0x20, 0x2e, 0x2b, 0xeb, 0x67, 0xa0, 0x82, 0x86, + 0xc8, 0x0e, 0x70, 0x76, 0x74, 0x52, 0x3e, 0x67, 0x96, 0xf0, 0x48, 0x3f, + 0x9b, 0xdc, 0x5f, 0x36, 0xd9, 0xae, 0x3a, 0xcb, 0x57, 0x5d, 0xe0, 0x7c, + 0x03, 0xa9, 0xe8, 0x88, 0x13, 0x6a, 0x70, 0x94, 0x4b, 0xf5, 0x92, 0x8f, + 0xc0, 0x34, 0x49, 0x3f, 0xf7, 0xe1, 0x59, 0xc4, 0xf2, 0xae, 0x7a, 0x88, + 0x58, 0x39, 0x74, 0x39, 0x6d, 0xaf, 0x7a, 0xec, 0xaf, 0x44, 0x0e, 0x11, + 0x7d, 0xa8, 0x3c, 0x50, 0x5b, 0x64, 0x8d, 0x8a, 0x21, 0x59, 0xc6, 0x8c, + 0x6c, 0xce, 0x05, 0xad, 0x1c, 0x2f, 0x5e, 0x4a, 0xa3, 0x2a, 0x46, 0x3a, + 0xaa, 0x12, 0x7e, 0xcc, 0x82, 0xb6, 0x62, 0xba, 0xe6, 0x1a, 0x52, 0xc6, + 0xe3, 0x96, 0x71, 0xf6, 0x81, 0x21, 0x46, 0xd0, 0x3f, 0x5d, 0xa1, 0x37, + 0x8b, 0xf5, 0xc7, 0x8c, 0x28, 0xf0, 0x2e, 0xe8, 0x44, 0x25, 0x48, 0x27, + 0x8e, 0x2f, 0x65, 0x83, 0xed, 0xf5, 0xb6, 0x9f, 0x02, 0xa7, 0x1b, 0x1e, + 0x90, 0x01, 0x55, 0x88, 0xe5, 0xdf, 0x0e, 0x7e, 0x16, 0x66, 0xa1, 0xc6, + 0x07, 0xf6, 0xb5, 0x84, 0x8d, 0x60, 0x6b, 0xe2, 0xad, 0xbd, 0x18, 0x39, + 0xe5, 0xd2, 0xd9, 0xe0, 0xab, 0xc2, 0xac, 0x2f, 0x36, 0x24, 0x03, 0x69, + 0x4c, 0xf9, 0xf3, 0x67, 0x8f, 0xf6, 0x8b, 0xde, 0xf9, 0x7c, 0x14, 0xfa, + 0x97, 0xc3, 0xe5, 0xc1, 0x7d, 0xcf, 0x16, 0x24, 0x26, 0xda, 0xde, 0x5c, + 0x70, 0x96, 0x90, 0xd9, 0x06, 0x2f, 0xf9, 0x61, 0xa3, 0x47, 0x19, 0x50, + 0x5e, 0xe2, 0xb6, 0x74, 0x5e, 0x55, 0xe6, 0x89, 0xaa, 0xde, 0x19, 0x27, + 0x26, 0x47, 0x95, 0x7b, 0xf0, 0x09, 0x21, 0xa9, 0xf3, 0xf2, 0xf0, 0xbc, + 0x1a, 0xa2, 0x25, 0x77, 0x3f, 0x8a, 0x57, 0x20, 0xfc, 0x48, 0x45, 0xd8, + 0x8b, 0xcb, 0x33, 0x04, 0x10, 0x1d, 0xc6, 0x4b, 0x4c, 0xe4, 0x92, 0x1f, + 0xef, 0x27, 0x5e, 0xd5, 0xac, 0xab, 0xcc, 0x69, 0xbe, 0xd6, 0x35, 0x0e, + 0x0d, 0x96, 0x99, 0x3b, 0x67, 0x8d, 0x33, 0xa0, 0xe3, 0x16, 0xcc, 0x4a, + 0x29, 0x80, 0xc8, 0x47, 0xd1, 0x0c, 0xb1, 0xa0, 0xc1, 0xbe, 0xcc, 0x16, + 0xab, 0xf7, 0xee, 0x8a, 0x77, 0xef, 0xca, 0x08, 0x82, 0x0a, 0x9e, 0x11, + 0xcf, 0x3c, 0xbb, 0x1b, 0x44, 0x96, 0xd1, 0x5e, 0x65, 0xf9, 0xe7, 0xc7, + 0xa1, 0x94, 0x42, 0xa9, 0x0e, 0x36, 0x9a, 0x5b, 0x7f, 0xf0, 0x91, 0x95, + 0xeb, 0xd1, 0xb6, 0x1d, 0x18, 0x44, 0x93, 0xa4, 0xc1, 0x31, 0x97, 0x07, + 0x09, 0x9b, 0x50, 0xae, 0xf3, 0x74, 0x7f, 0xbe, 0x0d, 0xc2, 0xc3, 0x11, + 0x8f, 0xa1, 0xea, 0x1f, 0x4e, 0x84, 0x94, 0x18, 0x7e, 0x7c, 0xbd, 0xe6, + 0xc9, 0x78, 0x0e, 0x39, 0x1e, 0x1a, 0x71, 0xc4, 0xbc, 0x5c, 0x99, 0x76, + 0xf7, 0x26, 0x66, 0x9c, 0x8f, 0xd4, 0xad, 0xa9, 0x6e, 0x96, 0xb9, 0x54, + 0x5b, 0xae, 0xa2, 0x0d, 0x94, 0xa8, 0x5a, 0x34, 0xc3, 0xdb, 0x52, 0x59, + 0x3f, 0xdd, 0x53, 0x72, 0xfc, 0xf6, 0x1d, 0x3c, 0xe0, 0x1f, 0x4a, 0xee, + 0xf5, 0x74, 0xa5, 0x95, 0x7a, 0x5d, 0x75, 0xbd, 0x27, 0x4a, 0x49, 0x18, + 0xcf, 0xf0, 0xe5, 0x32, 0x4f, 0x1b, 0xa0, 0xeb, 0x00, 0x19, 0x21, 0xbd, + 0xf7, 0xf5, 0x4b, 0x47, 0x1d, 0x3b, 0x8b, 0xe6, 0xca, 0xdc, 0xb6, 0x52, + 0x41, 0xa7, 0xab, 0x68, 0xb3, 0xfb, 0x8f, 0x40, 0xc3, 0x59, 0xd9, 0x2d, + 0x13, 0x3a, 0x99, 0x93, 0x9f, 0xa6, 0x90, 0xdd, 0x65, 0x17, 0x6c, 0x6f, + 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x2d, 0x69, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x69, 0x65, 0x73, 0x64, 0x6b, 0x75, 0x0d, 0x00, 0x00, 0x00, + 0x02, 0x07, 0x57, 0x00, 0x0c, 0xce, 0x07, 0x57, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x8a, 0x74, 0x06, 0x23, 0x00, 0x07, 0x07, 0x09, 0x34, + 0x00, 0x09, 0x09, 0x09, 0x34, 0x34, 0x08, 0x01, 0x02, 0x02, 0x08, 0x08, + 0x08, 0x08, 0x09, 0x08, 0x08, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, + 0x09, 0x93, 0x7c, 0x17, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x83, 0xd8, 0xc4, + 0xac, 0x41, 0xb7, 0x59, 0x5c, 0x83, 0xd8, 0xc4, 0xac, 0xdb, 0x80, 0x31, + 0x14, 0x76, 0xc0, 0x68, 0x81, 0x87, 0xa3, 0xfd, 0xf3, 0xa2, 0xd6, 0x51, + 0xa9, 0xbf, 0x9e, 0x90, 0x88, 0xfc, 0x9b, 0xff, 0x1a, 0xfd, 0x18, 0x88, + 0xb2, 0x23, 0xc4, 0x27, 0xcd, 0xff, 0x6d, 0xed, 0x99, 0xdb, 0x40, 0x1d, + 0x5c, 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, + 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0x2a, 0x05, 0x00, + 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, + 0x00, 0x00, 0x08, 0xd8, 0x16, 0x86, 0x7c, 0x84, 0xb6, 0xc0, 0xb3, 0x50, + 0x2d, 0x2a, 0x95, 0x72, 0x8c, 0x1b, 0x64, 0xd9, 0xce, 0xbb, 0x9c, 0xc8, + 0xc6, 0x63, 0x5a, 0xd5, 0x38, 0x7c, 0x27, 0x74, 0xaa, 0x87, 0x88, 0x30, + 0xf3, 0x87, 0x6a, 0x7d, 0x11, 0xc7, 0x6a, 0xf8, 0x5a, 0x6c, 0xd9, 0xaf, + 0xae, 0xb7, 0x3e, 0x35, 0x89, 0x91, 0x11, 0xe7, 0x44, 0x9c, 0xc1, 0xa1, + 0x18, 0x0e, 0x78, 0x20, 0xfe, 0x4a, 0xf9, 0x47, 0x3a, 0xf4, 0x23, 0x28, + 0x3c, 0x45, 0xa2, 0x22, 0xe8, 0x63, 0x71, 0x92, 0xc8, 0xfd, 0x85, 0xf8, + 0x03, 0x28, 0x38, 0xb6, 0x09, 0x66, 0x5b, 0x56, 0xc8, 0xa6, 0x52, 0x03, + 0xea, 0xbf, 0xb5, 0x6f, 0xaf, 0x68, 0xdc, 0xb6, 0x9c, 0xa2, 0x16, 0xa5, + 0x33, 0x1a, 0xb7, 0x13, 0x15, 0x1d, 0x52, 0x29, 0x54, 0x51, 0xc4, 0x3e, + 0xa0, 0x03, 0xf9, 0x73, 0xa9, 0x3e, 0xf6, 0x45, 0xd8, 0xf2, 0x1e, 0xa9, + 0x40, 0x14, 0xc4, 0x5f, 0xbc, 0xce, 0x6f, 0xb5, 0xa2, 0x93, 0x7b, 0xf2, + 0x7c, 0xfa, 0xa5, 0x82, 0x97, 0x64, 0x77, 0x2e, 0x6d, 0x8f, 0x00, 0x71, + 0x64, 0xed, 0xc9, 0x51, 0x61, 0x69, 0x8f, 0x2a, 0xf4, 0x80, 0xd2, 0x24, + 0x6c, 0xc3, 0x53, 0x9f, 0xca, 0x72, 0x9d, 0x22, 0x54, 0x27, 0xd5, 0xba, + 0xae, 0x53, 0xb4, 0x7e, 0xae, 0xa9, 0xe1, 0x48, 0x67, 0xf5, 0x7b, 0xd7, + 0x7e, 0x36, 0x6f, 0xd1, 0xf8, 0x40, 0x8a, 0x9b, 0x07, 0x80, 0x2c, 0x17, + 0x6c, 0x42, 0x2f, 0x7b, 0x8b, 0x98, 0xc4, 0x20, 0xaf, 0x5b, 0x25, 0x73, + 0xb5, 0x5b, 0xa3, 0x4d, 0xe6, 0xeb, 0x66, 0x21, 0x91, 0x9d, 0x85, 0xa3, + 0x8b, 0xfa, 0x40, 0x2d, 0x0b, 0x20, 0x66, 0x47, 0x70, 0x83, 0xe3, 0x02, + 0x0f, 0xc2, 0x56, 0xd6, 0x49, 0x83, 0x3d, 0xad, 0x16, 0x1f, 0x55, 0x33, + 0xcf, 0x79, 0x6d, 0x8d, 0xb1, 0xf7, 0x5d, 0x08, 0x10, 0xd8, 0xe2, 0x0e, + 0xe7, 0xa1, 0x74, 0xdb, 0xef, 0x19, 0xc0, 0xe7, 0xf3, 0xb7, 0x73, 0xf8, + 0x4d, 0x78, 0x98, 0xf0, 0x64, 0xc3, 0xc5, 0x99, 0xb7, 0xf6, 0x07, 0xd4, + 0xae, 0x17, 0xe4, 0xee, 0xd9, 0x35, 0x53, 0xb6, 0x2d, 0xb5, 0xa0, 0xc4, + 0x50, 0x48, 0x3e, 0x16, 0x18, 0xea, 0x20, 0x34, 0x9c, 0xeb, 0xeb, 0xef, + 0xee, 0xb8, 0xf4, 0x32, 0xb1, 0xda, 0x32, 0x35, 0x4e, 0x47, 0x1a, 0x4e, + 0xad, 0x46, 0x53, 0xe6, 0xce, 0x22, 0x7e, 0xe3, 0xf3, 0xbc, 0x34, 0x77, + 0xb0, 0x53, 0x21, 0x81, 0x19, 0x42, 0xb7, 0x1d, 0x0d, 0x81, 0x0f, 0x29, + 0xea, 0x2f, 0x3d, 0xba, 0x40, 0x0c, 0xea, 0x2e, 0xaf, 0x20, 0x88, 0x96, + 0x88, 0xc2, 0xea, 0x3b, 0xec, 0x58, 0x4f, 0x16, 0x66, 0xec, 0x9c, 0xe3, + 0xc8, 0x77, 0x6b, 0xfe, 0xc5, 0xeb, 0x5f, 0xab, 0xbc, 0xc2, 0x6b, 0x03, + 0xdb, 0xbc, 0x0e, 0xd6, 0xd2, 0x8d, 0x3e, 0xd8, 0x63, 0xe7, 0x13, 0xa9, + 0xc3, 0x98, 0xfa, 0xf6, 0xbd, 0xe9, 0x53, 0x33, 0x83, 0x26, 0x2b, 0x78, + 0xa4, 0x91, 0xb5, 0x5b, 0x39, 0xcf, 0x1d, 0x26, 0xc4, 0x05, 0xbe, 0xeb, + 0x8b, 0xa4, 0xee, 0xcd, 0xe0, 0x76, 0xac, 0x41, 0xdf, 0x85, 0x05, 0x60, + 0xe3, 0xc2, 0x5e, 0x57, 0x73, 0x00, 0x48, 0xa2, 0x3f, 0x3c, 0xd2, 0x3c, + 0x78, 0x8e, 0x20, 0xa2, 0xbd, 0xc6, 0xb6, 0x09, 0xdb, 0xdd, 0xf5, 0x39, + 0x8b, 0x5f, 0x2d, 0x13, 0xb9, 0x18, 0x3c, 0x43, 0x55, 0xcc, 0xf6, 0x87, + 0x97, 0xbe, 0x82, 0x03, 0x18, 0xa2, 0xb0, 0xf5, 0x05, 0xec, 0xe3, 0x64, + 0x43, 0x67, 0xef, 0xf7, 0x3c, 0x23, 0xde, 0x2a, 0xa7, 0xff, 0xee, 0xc1, + 0x95, 0x3d, 0xc8, 0x99, 0xea, 0xb7, 0x73, 0x2a, 0x89, 0xc8, 0x1b, 0x2e, + 0x47, 0x25, 0xae, 0x2a, 0x40, 0x77, 0x87, 0x6d, 0xea, 0xa9, 0x71, 0x49, + 0xa0, 0x11, 0xe5, 0x89, 0x0e, 0xd8, 0x01, 0x10, 0xe2, 0x6f, 0xea, 0xb2, + 0xbf, 0x6d, 0x2b, 0x03, 0x92, 0x28, 0x2a, 0xe8, 0x21, 0x70, 0x55, 0x48, + 0xe5, 0x9f, 0xf4, 0xea, 0x37, 0x69, 0x22, 0xb9, 0x3f, 0x48, 0x06, 0xd1, + 0x97, 0x6e, 0x72, 0x13, 0x4b, 0x20, 0xb5, 0x55, 0x64, 0x5c, 0xfc, 0x0b, + 0xec, 0xf9, 0x6f, 0x0d, 0xfa, 0x2d, 0xa4, 0xf9, 0x6a, 0x98, 0x5f, 0xd2, + 0x17, 0x31, 0xbf, 0x86, 0xc4, 0xd8, 0x21, 0x0a, 0x51, 0x62, 0xf1, 0x30, + 0x72, 0xef, 0x39, 0xb5, 0x05, 0x6b, 0xc9, 0x15, 0x1f, 0xbd, 0xb5, 0xfc, + 0xe5, 0x0b, 0x35, 0x13, 0x9b, 0xc5, 0x48, 0x3e, 0xf1, 0x1f, 0x7a, 0x1d, + 0x7f, 0xcb, 0x61, 0xba, 0x58, 0xbb, 0x74, 0xc2, 0x1b, 0xd9, 0xc0, 0x45, + 0x45, 0xe9, 0xbf, 0x3b, 0x56, 0x14, 0x9c, 0xd7, 0xaa, 0xcd, 0x77, 0xc4, + 0x32, 0x6c, 0x7e, 0x5d, 0xc0, 0x1c, 0xde, 0xad, 0xbb, 0xe4, 0x46, 0xca, + 0x6c, 0x13, 0x08, 0x58, 0x07, 0xd6, 0xa7, 0xc5, 0xa1, 0x90, 0xc6, 0x93, + 0x4d, 0xbd, 0xc4, 0xd7, 0x75, 0x02, 0x16, 0x47, 0x38, 0x33, 0x92, 0x11, + 0xb9, 0x6a, 0x85, 0xc4, 0x97, 0x7d, 0xdc, 0x54, 0x31, 0x07, 0xf9, 0xcd, + 0xeb, 0x09, 0x85, 0xae, 0x14, 0x6d, 0x2c, 0xb0, 0xfa, 0xa3, 0x49, 0x26, + 0xb6, 0x98, 0x69, 0xb1, 0x85, 0x52, 0x02, 0x0d, 0x3a, 0x8d, 0x40, 0x3b, + 0x83, 0x05, 0x66, 0x5c, 0xe3, 0xb1, 0x51, 0xe4, 0xc9, 0x59, 0x74, 0x0a, + 0x8a, 0xbb, 0xcb, 0x95, 0xde, 0x81, 0xa4, 0x92, 0x09, 0x63, 0x9d, 0xef, + 0x27, 0xf4, 0xe1, 0x66, 0xf6, 0x4f, 0xe9, 0x6d, 0xce, 0x8d, 0xcb, 0x91, + 0x55, 0xd7, 0xf9, 0xba, 0x49, 0xf2, 0x27, 0x0c, 0x15, 0x68, 0x21, 0x42, + 0x2d, 0x69, 0xe2, 0x0d, 0xee, 0x69, 0x55, 0x68, 0xc3, 0xb5, 0x8d, 0xd7, + 0x37, 0x32, 0xda, 0x6f, 0x78, 0x2b, 0xc8, 0xf9, 0x30, 0x3b, 0xd1, 0xe5, + 0xa5, 0x4c, 0xcb, 0xfe, 0xeb, 0x6f, 0x5d, 0x3c, 0x99, 0xfb, 0x33, 0xc1, + 0x8e, 0xac, 0x48, 0x70, 0x8c, 0x30, 0x85, 0xe1, 0x30, 0x69, 0xde, 0x82, + 0x82, 0x18, 0xe2, 0xc5, 0x6b, 0xb7, 0x1d, 0xdb, 0xce, 0x09, 0x4d, 0x9a, + 0x8e, 0x93, 0x89, 0x46, 0x5f, 0x8c, 0xe9, 0xf5, 0x4c, 0xa1, 0x62, 0xd9, + 0x22, 0x4c, 0xad, 0xbe, 0x77, 0x5c, 0x4f, 0x34, 0xc0, 0x64, 0x23, 0x0d, + 0x9d, 0xed, 0x3e, 0x70, 0x9b, 0x5f, 0x65, 0x84, 0x98, 0x63, 0x1a, 0x0b, + 0xd9, 0x7c, 0xb0, 0x95, 0xee, 0x6a, 0x9a, 0x5c, 0xc3, 0x76, 0x7c, 0x18, + 0x75, 0xba, 0x86, 0xca, 0x43, 0xa5, 0xb5, 0xe1, 0x0b, 0x26, 0xc0, 0xfb, + 0xd6, 0x3a, 0x23, 0x9f, 0xfb, 0xba, 0x68, 0xa3, 0x9b, 0xc0, 0xe5, 0x21, + 0xe3, 0x77, 0x75, 0x84, 0x40, 0x1d, 0x9b, 0xc9, 0xf2, 0x25, 0x6c, 0xba, + 0x6c, 0x8c, 0xb2, 0x2e, 0xec, 0xce, 0x90, 0xb1, 0x4a, 0x90, 0x24, 0xf3, + 0x34, 0x9d, 0xc3, 0x62, 0xb2, 0x11, 0x02, 0xd1, 0xf5, 0x67, 0x95, 0x48, + 0x45, 0x04, 0xe1, 0xd4, 0xb3, 0xdd, 0x1e, 0x00, 0x35, 0x84, 0x7c, 0x41, + 0xea, 0xf9, 0x50, 0xd3, 0x82, 0x14, 0x7d, 0xe7, 0x72, 0xe2, 0xb4, 0x9e, + 0xfc, 0xe7, 0x2e, 0xf7, 0x06, 0xb4, 0x29, 0xfe, 0x7e, 0x72, 0x6a, 0xe1, + 0xde, 0xa8, 0xfa, 0xd9, 0xde, 0xf4, 0xdd, 0xce, 0xff, 0xdb, 0xdc, 0x09, + 0x31, 0x14, 0x1d, 0x09, 0x53, 0xb5, 0x3f, 0x2c, 0x66, 0x74, 0xa8, 0x66, + 0xaa, 0xa2, 0x3d, 0x32, 0x61, 0xed, 0x43, 0xa5, 0x69, 0xf8, 0x6b, 0x0d, + 0x16, 0xe4, 0x67, 0xf5, 0x62, 0xaa, 0x76, 0xac, 0x01, 0x3f, 0x5f, 0x44, + 0x29, 0x34, 0x95, 0x0c, 0x1a, 0x07, 0x96, 0x6b, 0xf4, 0x60, 0x96, 0x5b, + 0xe2, 0x53, 0x2a, 0x87, 0x02, 0xc6, 0xf4, 0x01, 0xf3, 0x7a, 0xdb, 0x82, + 0x5f, 0xc3, 0x85, 0xd4, 0x1a, 0x9b, 0x63, 0xc4, 0x60, 0xb7, 0x82, 0x3c, + 0x9c, 0x70, 0x6f, 0x62, 0x72, 0x10, 0x13, 0xe2, 0xf5, 0x7b, 0x06, 0x41, + 0x48, 0xc7, 0x63, 0xa0, 0xb9, 0xde, 0x56, 0x96, 0x0f, 0x0d, 0x67, 0xd9, + 0x0e, 0x8a, 0x94, 0x3f, 0xca, 0x2f, 0x94, 0x19, 0xff, 0x47, 0xad, 0x59, + 0x3b, 0x9b, 0xb4, 0xc5, 0x4b, 0x51, 0x0d, 0x18, 0x74, 0xc9, 0x53, 0x34, + 0xf0, 0x6c, 0x58, 0x51, 0xbe, 0x4b, 0xfe, 0x24, 0x37, 0xd2, 0x0b, 0x4d, + 0xfa, 0x54, 0xfd, 0x92, 0xc4, 0x25, 0xb3, 0xe8, 0xe2, 0xb5, 0xda, 0xd1, + 0xd1, 0x44, 0x82, 0xb9, 0x2b, 0xb7, 0x03, 0xd9, 0xca, 0x78, 0x71, 0x9c, + 0xc6, 0x8f, 0xb6, 0x59, 0x37, 0xbd, 0x15, 0x02, 0x5e, 0xfb, 0xf5, 0x8c, + 0x7c, 0x46, 0x8e, 0xe2, 0xc8, 0xed, 0xf9, 0x96, 0xdb, 0xa8, 0xbe, 0xe5, + 0x09, 0x70, 0x3f, 0xf4, 0xfb, 0xbf, 0xf4, 0xf5, 0xe1, 0xd4, 0x5e, 0xda, + 0x60, 0x8f, 0x9d, 0xff, 0x94, 0x00, 0xa2, 0xe6, 0x40, 0xd2, 0x47, 0xdb, + 0x2d, 0x0e, 0x82, 0x7c, 0x7f, 0xab, 0x94, 0x2b, 0xc2, 0x6b, 0x46, 0x4d, + 0x55, 0x44, 0x7b, 0xb9, 0x2e, 0x68, 0x89, 0xbb, 0xc0, 0x69, 0x44, 0x77, + 0xa1, 0x41, 0xf8, 0x3b, 0x3f, 0xe5, 0xfb, 0x3c, 0x12, 0x0f, 0x59, 0x78, + 0x6a, 0x52, 0x6e, 0xe1, 0x2a, 0xf7, 0xab, 0xcd, 0xc8, 0xb2, 0x5d, 0x8d, + 0x1c, 0xf6, 0x24, 0xae, 0xb3, 0xda, 0x8a, 0xa7, 0x75, 0x3b, 0x58, 0x77, + 0x08, 0x72, 0xa9, 0x06, 0x0c, 0x7e, 0x4d, 0xad, 0x52, 0x42, 0xc5, 0x9d, + 0x32, 0x10, 0x49, 0xbb, 0xe1, 0x32, 0xc6, 0xb6, 0x2a, 0x68, 0xd3, 0x8d, + 0xba, 0x9e, 0x69, 0x63, 0x68, 0x61, 0x74, 0x64, 0x6b, 0x75, 0x86, 0x2f, + 0x05, 0x23, 0x00, 0x07, 0x07, 0x08, 0x34, 0x00, 0x09, 0x09, 0x09, 0x34, + 0x34, 0x08, 0x01, 0x02, 0x02, 0x08, 0x08, 0x08, 0x08, 0x09, 0x08, 0x08, + 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x09, 0x8a, 0x72, 0x17, 0x13, + 0x41, 0xb7, 0x59, 0x5c, 0x83, 0xd3, 0xa8, 0x82, 0x41, 0xb7, 0x59, 0x5c, + 0x83, 0xd3, 0xa8, 0x82, 0xdb, 0x80, 0x31, 0x14, 0x76, 0xc0, 0x68, 0x81, + 0x87, 0xa3, 0xfd, 0xf3, 0xa2, 0xd6, 0x51, 0xa9, 0xbf, 0x9e, 0x90, 0x88, + 0xfc, 0x9b, 0xff, 0x1a, 0xfd, 0x18, 0x88, 0xb2, 0x23, 0xc4, 0x27, 0xcd, + 0xff, 0x6d, 0xed, 0x99, 0xdb, 0x40, 0x1d, 0x5c, 0xda, 0x39, 0xa3, 0xee, + 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, + 0xaf, 0xd8, 0x07, 0x09, 0x2a, 0x05, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x38, 0xe1, 0x14, + 0x34, 0xc4, 0xb0, 0x8c, 0x51, 0x96, 0xb8, 0x94, 0xef, 0xe7, 0xf0, 0x5b, + 0x0e, 0x91, 0xf7, 0x07, 0x87, 0x90, 0x3f, 0x8d, 0x5f, 0xf6, 0x59, 0x69, + 0x11, 0x87, 0xdb, 0xaa, 0xdb, 0x60, 0x19, 0xe3, 0x42, 0xdd, 0xd2, 0x2e, + 0xbf, 0xc3, 0x0d, 0x32, 0x66, 0x01, 0xb9, 0xde, 0xce, 0xb5, 0x23, 0xa4, + 0x8e, 0x40, 0x6f, 0xe6, 0xa9, 0xea, 0xc6, 0x1e, 0x64, 0xc9, 0x57, 0x83, + 0x42, 0x36, 0x52, 0x9b, 0xa5, 0x29, 0x32, 0x5f, 0xe9, 0xc2, 0xe3, 0x2d, + 0x5b, 0x00, 0x7b, 0x3e, 0xad, 0xd4, 0x78, 0x7f, 0xfa, 0x02, 0x30, 0xb0, + 0x02, 0xfd, 0xd2, 0xbc, 0xa5, 0xe8, 0x0b, 0x4f, 0x96, 0x16, 0x79, 0x43, + 0x1a, 0xc1, 0x6d, 0xb5, 0xcf, 0x11, 0x35, 0x58, 0x61, 0x08, 0x64, 0x23, + 0xa3, 0x07, 0x76, 0xdb, 0x4d, 0x7d, 0x0e, 0xe0, 0x43, 0x7d, 0xc9, 0x3d, + 0x5e, 0xf4, 0x05, 0x0d, 0xb2, 0xbe, 0x23, 0x13, 0x19, 0x5f, 0x2a, 0xe9, + 0x10, 0xe7, 0x69, 0xed, 0x95, 0x7b, 0x66, 0xb3, 0xe5, 0xa5, 0x8b, 0x6f, + 0xe7, 0xa8, 0x2c, 0xab, 0xed, 0xd1, 0x12, 0xcf, 0xfb, 0xc7, 0x9a, 0xa5, + 0xf0, 0xe9, 0x2a, 0x98, 0x38, 0x96, 0x6a, 0xbb, 0x8d, 0xf2, 0xbf, 0x08, + 0x7f, 0xa7, 0x52, 0xd6, 0x12, 0x3b, 0x00, 0x47, 0xfe, 0xf3, 0x35, 0x63, + 0xf8, 0xc0, 0xec, 0xcf, 0x47, 0x72, 0x45, 0x81, 0x77, 0x4f, 0x23, 0x89, + 0x57, 0x15, 0x3c, 0xd7, 0xf9, 0x51, 0x14, 0xbd, 0x2a, 0x3d, 0xf4, 0x3d, + 0x83, 0xc1, 0xd0, 0x58, 0x07, 0x65, 0x5e, 0xe9, 0x23, 0x9a, 0xb9, 0x76, + 0xd1, 0xe1, 0x5f, 0xfd, 0x7c, 0xfe, 0x31, 0xad, 0xcd, 0xd6, 0x03, 0xb9, + 0x37, 0xe0, 0xae, 0x49, 0x85, 0x6b, 0x3c, 0x03, 0x97, 0x29, 0x99, 0x7c, + 0x1d, 0x36, 0x1a, 0xdd, 0xda, 0x47, 0xa1, 0x38, 0x21, 0xfa, 0x91, 0x4a, + 0x8d, 0xe7, 0x26, 0x9d, 0xaa, 0x44, 0xf7, 0x91, 0x25, 0xca, 0xa8, 0x84, + 0x77, 0x58, 0x2a, 0x50, 0xd6, 0xa4, 0xab, 0x69, 0xd3, 0xd4, 0xac, 0x1e, + 0x08, 0xfc, 0xa2, 0xbd, 0xab, 0x27, 0x72, 0xa4, 0x5a, 0x40, 0x76, 0x15, + 0x24, 0x0e, 0x50, 0x5a, 0x6f, 0x5d, 0x00, 0x75, 0x6c, 0x75, 0x75, 0xbb, + 0x13, 0x85, 0x0e, 0xcf, 0x27, 0x28, 0x94, 0x41, 0x64, 0xf0, 0x76, 0x97, + 0xbb, 0x58, 0x20, 0x12, 0x46, 0xa9, 0xf5, 0x23, 0xc2, 0x6b, 0xf6, 0x9b, + 0xd1, 0x20, 0xc5, 0x98, 0xa5, 0xdb, 0x77, 0xd9, 0x2a, 0xe7, 0xd8, 0x06, + 0xfc, 0x5d, 0xca, 0x85, 0xd8, 0x6e, 0x44, 0xf0, 0x4a, 0x32, 0x37, 0x66, + 0xbf, 0xde, 0x0a, 0x4c, 0xd8, 0xd8, 0xeb, 0x96, 0x0f, 0x6a, 0x37, 0x16, + 0x09, 0x63, 0x48, 0x8d, 0x31, 0xe8, 0x7c, 0xa6, 0x5b, 0xf0, 0xd3, 0x51, + 0xad, 0x5b, 0x12, 0xd5, 0x42, 0x86, 0xbd, 0x46, 0x7c, 0x62, 0x9c, 0x92, + 0x10, 0xeb, 0xdd, 0x5f, 0xc4, 0x16, 0xcc, 0x2d, 0xe1, 0xce, 0x42, 0xb0, + 0x80, 0x26, 0xcf, 0x49, 0x11, 0x0e, 0x4b, 0xe3, 0x63, 0xb4, 0x6f, 0x84, + 0x9b, 0x4d, 0xaf, 0x67, 0x56, 0x5f, 0x51, 0xff, 0xc9, 0xbd, 0xd5, 0xe4, + 0x7d, 0x96, 0x2c, 0x64, 0xe8, 0xa2, 0x42, 0x95, 0x2f, 0xf9, 0xb3, 0xa5, + 0x3c, 0xb2, 0x33, 0xa9, 0x4a, 0x03, 0xfe, 0x2c, 0x56, 0x00, 0xaa, 0xc6, + 0x5b, 0xea, 0x89, 0x0e, 0xa7, 0xae, 0xa0, 0x92, 0x7c, 0x04, 0xe5, 0x91, + 0xf4, 0x91, 0x8e, 0x77, 0xc0, 0x74, 0xd9, 0x85, 0xd6, 0x4f, 0x13, 0x11, + 0xc4, 0xd7, 0xeb, 0xd6, 0xfa, 0xbd, 0x70, 0x09, 0xb2, 0xa5, 0x77, 0x8d, + 0xbe, 0x23, 0x0b, 0xb3, 0x4c, 0xd6, 0x2f, 0xd0, 0x37, 0x62, 0x60, 0x88, + 0xd1, 0xbd, 0xec, 0x1c, 0x98, 0xbb, 0xd4, 0x9b, 0xa8, 0x50, 0x1e, 0xa4, + 0xb3, 0xe1, 0x1f, 0xe2, 0x49, 0x5b, 0x09, 0xc8, 0x3c, 0xb4, 0x38, 0xaf, + 0x5c, 0xec, 0xf8, 0x5d, 0xa1, 0xe1, 0xbf, 0xad, 0x5a, 0x33, 0xc8, 0x65, + 0x6a, 0x21, 0x10, 0x94, 0x70, 0x5c, 0x16, 0xd2, 0x5a, 0xfd, 0x52, 0x13, + 0xb8, 0xb7, 0xdb, 0xc2, 0x26, 0x7f, 0x24, 0xb2, 0xc3, 0x19, 0x19, 0x7c, + 0x7c, 0x5e, 0x70, 0x8a, 0x99, 0x74, 0x27, 0x3e, 0x5a, 0xb3, 0x17, 0x10, + 0xd8, 0x8a, 0x3e, 0xc2, 0x7e, 0x99, 0x67, 0x74, 0xe3, 0x65, 0x32, 0x18, + 0x90, 0x66, 0x7f, 0xe1, 0x74, 0x7d, 0xe7, 0xb8, 0xd1, 0xe2, 0xd3, 0x29, + 0xf1, 0xf2, 0x5d, 0xf1, 0x05, 0xca, 0x11, 0x7b, 0xf7, 0x32, 0xdf, 0x68, + 0x37, 0x84, 0xce, 0x00, 0x16, 0x5f, 0x9d, 0x9a, 0x5e, 0x04, 0xe0, 0xb1, + 0xa8, 0x39, 0x08, 0xfe, 0x75, 0xcc, 0x6b, 0x7c, 0x99, 0x28, 0x8d, 0x4c, + 0x50, 0x81, 0x0a, 0x4a, 0xba, 0x72, 0xbe, 0x90, 0x96, 0xcc, 0xac, 0x36, + 0x11, 0x5e, 0x9f, 0xe3, 0xc8, 0x97, 0x8b, 0x86, 0x87, 0x05, 0x68, 0x59, + 0x4d, 0xfa, 0xf7, 0xb8, 0x83, 0x0b, 0x42, 0xbd, 0xba, 0x63, 0x64, 0x3f, + 0xd6, 0xba, 0x66, 0x65, 0xbb, 0x1c, 0x69, 0x5d, 0xab, 0x22, 0x73, 0xd9, + 0xbc, 0x86, 0x0d, 0x06, 0x69, 0x63, 0x68, 0x61, 0x74, 0x64, 0x6b, 0x75, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x35, 0x1d, 0x3e, 0x1d, 0x24, 0xd4, 0x92, + 0xad, 0x2d, 0xbe, 0xf7, 0x22, 0xa4, 0x69, 0xce, 0x73, 0xef, 0xfc, 0x8d, + 0xfa, 0x05, 0xac, 0xfe, 0xf0, 0xa4, 0xe5, 0xb1, 0x82, 0x82, 0x42, 0xbd, + 0xaf, 0xba, 0xb2, 0x56, 0xf3, 0x3f, 0x14, 0x2c, 0xc6, 0xf5, 0x78, 0xb1, + 0x7f, 0x9e, 0xa5, 0xfb, 0x83, 0x3c, 0x1a, 0xdf, 0x4f, 0x79, 0x59, 0x61, + 0xed, 0xa5, 0x9a, 0x9b, 0x35, 0x8e, 0x10, 0x15, 0xb2, 0x49, 0x4d, 0x07, + 0x88, 0x4f, 0xc6, 0xb2, 0x3e, 0xca, 0x64, 0xae, 0xa3, 0x70, 0x5b, 0x2b, + 0xad, 0x74, 0x05, 0x2b, 0xc7, 0xcb, 0xff, 0x0e, 0x65, 0x85, 0xcc, 0xf3, + 0x4c, 0x85, 0x59, 0xa8, 0x34, 0x86, 0x92, 0xa5, 0xef, 0x3c, 0xdd, 0x52, + 0x13, 0x96, 0x52, 0x18, 0x3b, 0xd2, 0xaf, 0xab, 0x00, 0x17, 0x32, 0x82, + 0x71, 0xee, 0x90, 0x05, 0x81, 0x57, 0x52, 0x4f, 0x24, 0xff, 0xb3, 0xe6, + 0x3b, 0x94, 0xa3, 0x90, 0x7f, 0xd0, 0x26, 0xb0, 0x8b, 0x3e, 0xad, 0x36, + 0x5f, 0xb7, 0x28, 0x67, 0xac, 0xed, 0x35, 0xce, 0x51, 0xee, 0x78, 0xd5, + 0x99, 0x36, 0xea, 0x49, 0x22, 0x60, 0xc0, 0x75, 0x30, 0x7e, 0x96, 0x9d, + 0x60, 0x6e, 0x6a, 0xfb, 0x82, 0xb7, 0xa6, 0x41, 0xdf, 0x0c, 0x36, 0x9d, + 0xd2, 0xf7, 0xb7, 0xd1, 0x89, 0x95, 0x07, 0xac, 0x41, 0xa4, 0x60, 0x0a, + 0x6e, 0x4f, 0x41, 0xc3, 0x26, 0xed, 0xa0, 0x48, 0x91, 0xdd, 0xff, 0xc2, + 0xe9, 0x65, 0x2f, 0x76, 0x53, 0x05, 0xc3, 0x6f, 0x6a, 0x51, 0x27, 0xf8, + 0x55, 0xdf, 0xd7, 0xc3, 0x13, 0x25, 0x2d, 0x6b, 0xf1, 0x99, 0xd2, 0xda, + 0x9a, 0xed, 0x6d, 0x4f, 0xd0, 0x40, 0x73, 0xc2, 0x35, 0xeb, 0x8d, 0xa7, + 0x0f, 0x78, 0xc7, 0x43, 0x04, 0x53, 0x8d, 0x20, 0x6d, 0xb4, 0xd1, 0x18, + 0xf8, 0xd9, 0x5e, 0x92, 0x98, 0x0a, 0xa1, 0x16, 0xe8, 0x9f, 0x5a, 0x2a, + 0x2a, 0x89, 0x50, 0xda, 0xa3, 0xd6, 0xb1, 0xea, 0x50, 0x0c, 0x84, 0x7a, + 0xd9, 0xd8, 0x10, 0x75, 0x9d, 0x04, 0x3e, 0x4a, 0x5a, 0x8d, 0x9f, 0xf4, + 0xf9, 0xc4, 0x11, 0x6b, 0x76, 0x80, 0xf0, 0x56, 0x28, 0x13, 0xe3, 0x05, + 0x6b, 0x78, 0x23, 0x79, 0x88, 0x16, 0x51, 0x0c, 0x9b, 0xde, 0x4e, 0x90, + 0xd0, 0x2c, 0x53, 0x1c, 0x70, 0x41, 0xe7, 0xad, 0x73, 0xa3, 0xed, 0xc2, + 0x91, 0xc2, 0xb3, 0x3e, 0x99, 0xf2, 0x57, 0xf9, 0x7d, 0xc7, 0xc9, 0xe5, + 0x3e, 0xe2, 0x0b, 0x4b, 0xb6, 0xee, 0x29, 0x5b, 0xc9, 0xc5, 0xa6, 0x70, + 0x77, 0xe5, 0xbc, 0x43, 0x9e, 0xa2, 0x01, 0x22, 0x32, 0xb5, 0xdd, 0x1f, + 0x35, 0xd5, 0x3c, 0xdc, 0x7a, 0x4e, 0x85, 0x5f, 0xe2, 0x8f, 0x48, 0x28, + 0x70, 0x46, 0x89, 0x38, 0x5f, 0x72, 0x00, 0x65, 0x96, 0xfd, 0xc4, 0x36, + 0x01, 0xd6, 0x64, 0x70, 0xcc, 0xda, 0xd0, 0xc1, 0xee, 0x5b, 0x5a, 0xde, + 0x27, 0x1e, 0x35, 0xda, 0xae, 0x3c, 0xaf, 0xd3, 0x1c, 0x1a, 0x57, 0x24, + 0x0a, 0xf0, 0x79, 0xf0, 0xc1, 0xd7, 0x04, 0xcb, 0x21, 0xb2, 0xf4, 0x1e, + 0x1a, 0xa8, 0xc7, 0x89, 0xca, 0x1e, 0x68, 0x55, 0x71, 0x96, 0x68, 0x16, + 0x19, 0xb9, 0x9c, 0x96, 0xfa, 0xab, 0x34, 0xbb, 0xe0, 0x21, 0xb1, 0xae, + 0xb5, 0x8d, 0xf2, 0xd6, 0xce, 0x69, 0xc4, 0x58, 0x3f, 0x3c, 0xec, 0x28, + 0xcd, 0x9f, 0xfa, 0x97, 0xb3, 0xb0, 0xa4, 0x80, 0x7b, 0x07, 0x51, 0x0b, + 0x01, 0x23, 0x09, 0xcc, 0x7d, 0x94, 0x5d, 0xb4, 0xe9, 0x81, 0x5c, 0x3a, + 0x6b, 0xc4, 0x52, 0xc1, 0x86, 0xcc, 0xdf, 0x24, 0xcb, 0x3e, 0xbe, 0xc7, + 0xeb, 0xd7, 0xe0, 0x3a, 0xfc, 0xa1, 0x4d, 0x17, 0x8b, 0x41, 0x82, 0xeb, + 0x79, 0x2b, 0x87, 0x4d, 0xea, 0x27, 0xfb, 0x9e, 0x03, 0x75, 0xfc, 0x29, + 0x05, 0x4e, 0x76, 0xf3, 0x0f, 0x6d, 0xf2, 0x0f, 0xf6, 0x33, 0x58, 0x58, + 0xce, 0x67, 0xe7, 0x18, 0x97, 0x3a, 0x21, 0x4c, 0xaf, 0x64, 0x55, 0xd9, + 0x84, 0x53, 0xfd, 0x8b, 0x84, 0xad, 0x1a, 0xa5, 0x1c, 0x22, 0xac, 0xa5, + 0x21, 0xfb, 0xa2, 0x26, 0x69, 0x85, 0x24, 0xa3, 0x50, 0x24, 0x62, 0xe2, + 0xf8, 0x6c, 0x45, 0x97, 0xf6, 0xca, 0xe3, 0xbb, 0xb3, 0x02, 0x73, 0x7d, + 0x8b, 0x86, 0x69, 0xe6, 0x3a, 0x0c, 0x38, 0xa1, 0x85, 0xf5, 0xc8, 0xe6, + 0xbf, 0xce, 0x67, 0xeb, 0x68, 0xea, 0xe1, 0x05, 0x28, 0x48, 0xa6, 0xd5, + 0x2a, 0x35, 0xb5, 0x81, 0xaf, 0x3c, 0x47, 0xbb, 0x10, 0x4a, 0xc1, 0x29, + 0x9b, 0xa3, 0x16, 0x2b, 0x34, 0x18, 0x44, 0x2a, 0x1d, 0x43, 0x57, 0x1b, + 0x14, 0xea, 0x25, 0xbf, 0x1c, 0x95, 0x3e, 0x1e, 0x0d, 0x65, 0x50, 0x5a, + 0xe1, 0xd7, 0x14, 0x3f, 0xbb, 0xe2, 0xdd, 0x6f, 0x53, 0x5f, 0xd3, 0xc2, + 0x68, 0xa6, 0x14, 0xb2, 0x70, 0x36, 0x60, 0x99, 0x9d, 0x12, 0x9f, 0xee, + 0xcd, 0x99, 0x50, 0xbd, 0x41, 0x6f, 0x1b, 0xd4, 0x0d, 0x3b, 0xde, 0x00, + 0x20, 0xfd, 0x4c, 0x49, 0x80, 0x2e, 0x99, 0x4e, 0x23, 0xa8, 0x50, 0x14, + 0x42, 0x80, 0xb1, 0x4b, 0xe1, 0x97, 0x01, 0x1f, 0x8f, 0xf8, 0x05, 0x15, + 0xe6, 0x0e, 0x92, 0xdb, 0x10, 0xa2, 0x24, 0xf7, 0x4f, 0xc2, 0xf2, 0xe5, + 0xd8, 0xbc, 0xcc, 0x43, 0x10, 0xa0, 0x94, 0xff, 0x75, 0xee, 0xc2, 0x35, + 0x62, 0x2d, 0x9c, 0xe1, 0xd0, 0x0c, 0x02, 0x5b, 0xf0, 0x78, 0x32, 0xfe, + 0xf2, 0xf8, 0xdf, 0xd6, 0x7a, 0xdc, 0xc5, 0x82, 0xcd, 0xd4, 0x46, 0xd4, + 0x80, 0x99, 0xd6, 0x68, 0xb0, 0x60, 0xb2, 0x27, 0xdf, 0xbb, 0x41, 0x7f, + 0x49, 0x53, 0x93, 0x25, 0x05, 0x9a, 0xce, 0xc0, 0xd6, 0xc6, 0x46, 0xff, + 0xd7, 0xaa, 0x2d, 0xfa, 0x6b, 0x45, 0x09, 0xb0, 0xd2, 0x35, 0xfa, 0x8a, + 0xb4, 0xbb, 0xc2, 0x76, 0xe9, 0xd1, 0x91, 0x18, 0xde, 0x65, 0xd7, 0x81, + 0xa5, 0xbd, 0xd8, 0xf9, 0x89, 0xc6, 0x6f, 0xd9, 0xd3, 0xe4, 0x03, 0x4f, + 0x83, 0xf2, 0xd4, 0xd7, 0x41, 0x74, 0x5e, 0xe3, 0xcc, 0x8b, 0xf2, 0x22, + 0xb3, 0x89, 0xbc, 0xd5, 0x42, 0x43, 0x06, 0x76, 0xee, 0x0e, 0x79, 0x05, + 0xbd, 0xb2, 0x1e, 0xf6, 0x76, 0x12, 0x30, 0x2b, 0xd1, 0x9c, 0xe0, 0xd4, + 0xc9, 0x44, 0x09, 0x0a, 0xed, 0xae, 0x16, 0xdc, 0x9a, 0x26, 0xf4, 0xbb, + 0x37, 0xec, 0xc8, 0xa3, 0x7b, 0x12, 0x09, 0xcf, 0x17, 0x5c, 0x17, 0x74, + 0x0a, 0xa7, 0x71, 0x7c, 0xb0, 0x88, 0x15, 0xac, 0x98, 0xea, 0xfb, 0x3d, + 0x73, 0x3b, 0x46, 0xe9, 0xb0, 0x29, 0x73, 0xac, 0xe9, 0xdd, 0x1d, 0x8e, + 0xff, 0x79, 0xb9, 0x87, 0xf6, 0x07, 0x24, 0x49, 0xbf, 0xf6, 0x97, 0x71, + 0xbc, 0x5d, 0x14, 0x3f, 0x0f, 0x81, 0x6f, 0xcb, 0x49, 0x09, 0x51, 0x9e, + 0x4f, 0x24, 0x19, 0x7a, 0x00, 0x22, 0x9a, 0xa0, 0x52, 0xe3, 0x5b, 0x4a, + 0x9d, 0xe5, 0xb0, 0x96, 0xfc, 0x40, 0x15, 0xeb, 0x48, 0x1c, 0x4f, 0x25, + 0x64, 0xe9, 0x79, 0xbf, 0xb5, 0xef, 0x5f, 0xc3, 0x29, 0xbe, 0x7c, 0x6e, + 0x14, 0xe5, 0xe4, 0x36, 0xeb, 0x66, 0x27, 0x07, 0xbc, 0x2d, 0x1c, 0x2e, + 0x71, 0x51, 0x67, 0x60, 0x4d, 0xfc, 0x6c, 0x74, 0x8f, 0xc7, 0x84, 0x3e, + 0xe3, 0x8a, 0xfb, 0x34, 0xe3, 0x8e, 0x84, 0x5c, 0xdd, 0xc9, 0x0c, 0x3a, + 0xf4, 0x8c, 0xac, 0x40, 0xb0, 0x6b, 0x08, 0xe7, 0x4e, 0xa3, 0x92, 0xe3, + 0x57, 0xfc, 0x25, 0x08, 0x82, 0xd5, 0xf6, 0x35, 0x35, 0x41, 0x6a, 0xd9, + 0xf6, 0x78, 0x81, 0xca, 0x81, 0xe7, 0x5b, 0x58, 0x15, 0x5c, 0x57, 0x6e, + 0x5e, 0xe1, 0x65, 0xe5, 0xfc, 0xb1, 0xe9, 0x1a, 0x97, 0x9d, 0x86, 0xb9, + 0xb1, 0xa1, 0xb0, 0xbd, 0x3e, 0xb8, 0x0d, 0xc6, 0x33, 0x7e, 0xb5, 0x47, + 0xcc, 0x0a, 0x29, 0xcb, 0xf9, 0xaa, 0xff, 0x14, 0x33, 0x01, 0xd0, 0x3d, + 0x12, 0xb6, 0xc9, 0x33, 0x5d, 0xa8, 0x99, 0x30, 0x38, 0x38, 0xe3, 0x35, + 0x5a, 0x36, 0xf9, 0xca, 0xaf, 0x1d, 0xfe, 0x8c, 0x6a, 0xb7, 0xce, 0x67, + 0x0c, 0x6d, 0xc2, 0x29, 0xcd, 0x9e, 0x32, 0x46, 0xe8, 0xf4, 0x23, 0xa3, + 0xf3, 0xff, 0xf5, 0x74, 0xa6, 0xeb, 0xbd, 0xc3, 0x3e, 0xe2, 0x14, 0xd9, + 0xa5, 0xe8, 0x0e, 0xf6, 0x6f, 0xbd, 0xc3, 0x08, 0x56, 0x0a, 0xf0, 0x8a, + 0x14, 0xa1, 0xd6, 0x2d, 0xaf, 0xf7, 0x03, 0xff, 0xdc, 0x1c, 0x85, 0xdb, + 0xc9, 0x10, 0x33, 0xa2, 0x8d, 0x46, 0x69, 0x51, 0x70, 0x59, 0xc9, 0x4d, + 0x38, 0xb2, 0x69, 0x0e, 0xa8, 0xf4, 0xef, 0xdf, 0xb6, 0x34, 0xcf, 0x3d, + 0xec, 0xe8, 0x37, 0xea, 0xb3, 0x8e, 0x70, 0xb6, 0xf8, 0x5a, 0xa5, 0x13, + 0xde, 0x4c, 0x18, 0x6d, 0x04, 0xc5, 0xfd, 0xa4, 0x28, 0x15, 0x1b, 0x49, + 0xb3, 0x39, 0xfe, 0x9b, 0x54, 0xc1, 0x1e, 0x7f, 0x86, 0xe8, 0x3c, 0xe7, + 0xd5, 0x55, 0xa8, 0x89, 0xe1, 0xf4, 0xb5, 0x94, 0x0b, 0xff, 0xa8, 0xc2, + 0x56, 0xaa, 0xba, 0x6d, 0xb9, 0xc7, 0x54, 0xea, 0xbb, 0x1a, 0x17, 0x2a, + 0x3e, 0xae, 0x10, 0x2b, 0x89, 0xa8, 0x5d, 0xb1, 0x13, 0x46, 0xb1, 0x1c, + 0x6c, 0x7c, 0x58, 0x27, 0xc6, 0xf8, 0xfb, 0x9b, 0xca, 0x6b, 0x12, 0xd4, + 0x14, 0xbf, 0x3b, 0xb8, 0xea, 0xa7, 0xfa, 0x76, 0x55, 0x16, 0x0b, 0x2c, + 0xbb, 0x94, 0xd1, 0x12, 0x47, 0x0f, 0x3f, 0x89, 0xf4, 0xc2, 0xc3, 0x8d, + 0x03, 0x11, 0x0c, 0xe8, 0xe3, 0x96, 0x8f, 0x89, 0x25, 0x90, 0xa5, 0xe1, + 0xf4, 0x20, 0xf4, 0xfc, 0x24, 0xfe, 0xf0, 0x28, 0x11, 0x2a, 0x74, 0x10, + 0x9e, 0x20, 0x79, 0x11, 0xd4, 0x8b, 0x4b, 0x26, 0x75, 0x4f, 0x82, 0xd8, + 0x17, 0x64, 0xdf, 0x21, 0x73, 0x85, 0xa7, 0x57, 0x35, 0x8d, 0x67, 0x37, + 0x4a, 0x9a, 0xfe, 0x87, 0xa7, 0x45, 0x87, 0x51, 0xf3, 0x19, 0x3b, 0x1a, + 0xd4, 0x39, 0x37, 0x45, 0x99, 0xe9, 0x71, 0x96, 0x8b, 0x3e, 0xd8, 0xa6, + 0x8e, 0xc7, 0xf5, 0x62, 0x14, 0x1c, 0x8c, 0x4c, 0xfa, 0x60, 0x48, 0x35, + 0xb1, 0xba, 0xcd, 0xf5, 0xba, 0xf5, 0x67, 0xb6, 0xa2, 0x38, 0xf9, 0xd2, + 0xa3, 0xde, 0xbc, 0xfb, 0x58, 0xb2, 0xd2, 0x3d, 0x10, 0x63, 0x12, 0xed, + 0x23, 0xfd, 0xab, 0x65, 0x18, 0x6d, 0x94, 0x61, 0x06, 0xaa, 0x0b, 0xcc, + 0x3c, 0xd2, 0x91, 0xc9, 0x1b, 0x1e, 0x66, 0x38, 0x26, 0x0b, 0x0a, 0xb8, + 0x15, 0x88, 0xaf, 0x93, 0x03, 0x41, 0x2f, 0x0c, 0x2b, 0x68, 0x94, 0x1f, + 0xa7, 0x8d, 0xed, 0x3d, 0xa1, 0xca, 0x53, 0x93, 0xf8, 0x81, 0x95, 0x07, + 0xc5, 0x92, 0xf0, 0xa4, 0x74, 0x76, 0x1b, 0x14, 0x6e, 0xe6, 0x2f, 0x71, + 0x43, 0x8e, 0x79, 0x4c, 0x91, 0x71, 0xd7, 0x1e, 0x63, 0x94, 0xbd, 0xba, + 0x40, 0xb2, 0x86, 0x95, 0x90, 0x8c, 0xad, 0x22, 0x65, 0xfa, 0x65, 0x4c, + 0x65, 0xc4, 0x78, 0x7c, 0xef, 0x7a, 0x46, 0x25, 0xad, 0xac, 0xfc, 0x9c, + 0x6f, 0x24, 0xdf, 0xe4, 0xfe, 0x5f, 0x67, 0x31, 0x4e, 0xb9, 0x2a, 0xdb, + 0xfd, 0xfc, 0x9b, 0x99, 0xe4, 0xc3, 0x7b, 0x61, 0x04, 0x76, 0x0f, 0x4d, + 0x21, 0xcb, 0x27, 0xd9, 0x6d, 0x62, 0x42, 0x4f, 0x6c, 0xd8, 0x0a, 0xbc, + 0xa9, 0xbb, 0xc6, 0x61, 0x4b, 0xc3, 0xec, 0x82, 0x8b, 0xcc, 0x7b, 0x55, + 0xdd, 0xaa, 0xc1, 0x9e, 0x93, 0xd8, 0x77, 0xae, 0x34, 0x83, 0xbc, 0x90, + 0x85, 0x73, 0x4f, 0xba, 0x55, 0xa6, 0x66, 0x31, 0xe3, 0x8b, 0x11, 0x6b, + 0xce, 0xdf, 0x6a, 0xa3, 0x6e, 0xca, 0xe5, 0x65, 0x77, 0xd6, 0x08, 0x22, + 0x20, 0x20, 0x44, 0x04, 0xc7, 0x2a, 0x46, 0x4f, 0x17, 0xc7, 0xf6, 0x6f, + 0x45, 0x6a, 0xd3, 0xfc, 0xce, 0xa0, 0x9c, 0x43, 0xe3, 0x68, 0x83, 0x9b, + 0x70, 0x7f, 0x74, 0x1e, 0x8f, 0x9b, 0x61, 0x2d, 0x7f, 0x1f, 0x45, 0xd1, + 0xef, 0x92, 0xfb, 0x5f, 0xfa, 0x7a, 0x7f, 0x20, 0x0d, 0x86, 0xc6, 0x6f, + 0x5d, 0x8a, 0x0a, 0xd2, 0xb7, 0xe6, 0x82, 0xc9, 0x66, 0xb7, 0x54, 0x20, + 0x80, 0x19, 0xc9, 0x09, 0x10, 0x7e, 0x81, 0x92, 0x93, 0xab, 0x4e, 0xc9, + 0x49, 0x2d, 0xf4, 0xef, 0x5d, 0x08, 0x37, 0x6e, 0x0c, 0xfa, 0xfc, 0xd3, + 0xe0, 0xc4, 0x43, 0x04, 0x15, 0x47, 0x51, 0x9b, 0xc3, 0x9b, 0x6b, 0x80, + 0x03, 0xc6, 0x8b, 0x9a, 0x0d, 0x3c, 0xf1, 0x49, 0x0b, 0xd6, 0x39, 0x36, + 0x42, 0xd4, 0x81, 0xb2, 0x63, 0xe0, 0xa0, 0x8a, 0x34, 0xc0, 0x8a, 0xd0, + 0x67, 0xed, 0x3f, 0xed, 0x5f, 0x46, 0xa6, 0x04, 0x6b, 0x07, 0x81, 0xaa, + 0xc6, 0xc5, 0x0f, 0x17, 0x82, 0x28, 0xe9, 0xc7, 0xcd, 0xe5, 0xfc, 0xc3, + 0xb6, 0x45, 0xce, 0xe9, 0xd5, 0xe6, 0xe1, 0xc3, 0x92, 0x88, 0xe3, 0x22, + 0x3d, 0x63, 0x99, 0x47, 0x00, 0x3c, 0x21, 0x71, 0x02, 0x84, 0xd5, 0xb0, + 0x05, 0x9d, 0x19, 0x71, 0x5c, 0x9c, 0xea, 0x21, 0x64, 0x59, 0x0c, 0xa2, + 0x33, 0xdd, 0xcb, 0xcc, 0x5d, 0xcf, 0xd3, 0xc5, 0xc5, 0x38, 0xfc, 0xe1, + 0x9d, 0xd7, 0xff, 0xe4, 0x13, 0x76, 0x9d, 0xe7, 0xa5, 0xa1, 0x76, 0xc5, + 0xd3, 0xa6, 0xfa, 0x62, 0x5e, 0xb0, 0xf9, 0x8c, 0x1d, 0x8a, 0x75, 0x7f, + 0xef, 0x5b, 0x73, 0x76, 0xb6, 0x0a, 0x0e, 0xca, 0x34, 0x77, 0x7c, 0x42, + 0xcb, 0xe3, 0x62, 0x34, 0xda, 0xf2, 0x5a, 0x83, 0x37, 0xdd, 0xba, 0x06, + 0x4c, 0xa6, 0xf2, 0x80, 0x87, 0xfe, 0x61, 0x0b, 0xa3, 0x27, 0x84, 0x28, + 0x80, 0x81, 0x9a, 0x07, 0x4f, 0x77, 0xbf, 0x56, 0x7c, 0xe9, 0x24, 0xdc, + 0xa0, 0xe7, 0x1c, 0x0a, 0x32, 0x67, 0x22, 0x64, 0x47, 0x1c, 0x41, 0x06, + 0xac, 0x0a, 0x1f, 0x34, 0xa2, 0x08, 0xd9, 0x94, 0x02, 0x91, 0x79, 0x73, + 0x1e, 0x86, 0xd2, 0x21, 0x71, 0x02, 0x8d, 0xf3, 0xef, 0x9f, 0x17, 0xac, + 0xe2, 0x74, 0xec, 0x11, 0xbb, 0xe4, 0x62, 0xfc, 0x17, 0x38, 0x7d, 0x57, + 0x21, 0x0d, 0x5a, 0x4e, 0x8d, 0xa5, 0x8b, 0xc6, 0x44, 0xd9, 0xfb, 0x42, + 0xd5, 0x0b, 0x18, 0xdd, 0xf1, 0x7d, 0xca, 0x3b, 0x02, 0x00, 0x23, 0x38, + 0xd6, 0xa9, 0xb8, 0x4b, 0x1f, 0x7a, 0xe8, 0x55, 0x4a, 0xb3, 0xaf, 0xf8, + 0x0a, 0x57, 0xe5, 0xd7, 0xff, 0xee, 0x2b, 0xbc, 0xb5, 0x1f, 0xb5, 0xf1, + 0x43, 0xd0, 0x6f, 0xcf, 0xf1, 0x4e, 0x22, 0xe0, 0x01, 0x79, 0xc1, 0xbd, + 0x1e, 0xdb, 0x48, 0xb6, 0x9c, 0x26, 0xc2, 0xa9, 0x91, 0xee, 0x89, 0x1b, + 0xd5, 0x23, 0x08, 0x8c, 0x62, 0xc9, 0x86, 0x3e, 0x33, 0x6a, 0xb9, 0x7f, + 0x63, 0x51, 0x28, 0xab, 0xba, 0x60, 0x2c, 0x12, 0xcf, 0x66, 0x43, 0x38, + 0x0d, 0xc5, 0x3b, 0x2f, 0xf0, 0x70, 0x9c, 0xeb, 0x39, 0xe0, 0x8f, 0xcd, + 0x4c, 0x73, 0x1c, 0x70, 0x01, 0xfa, 0x78, 0xd3, 0x16, 0x1a, 0xae, 0x27, + 0x2d, 0x02, 0xdc, 0xdb, 0xba, 0x4b, 0xed, 0xae, 0x61, 0x1f, 0x55, 0x77, + 0xf5, 0xff, 0x88, 0xdb, 0x8b, 0xfc, 0x18, 0xc4, 0x9b, 0x41, 0xf1, 0x0e, + 0x6f, 0x6e, 0xc6, 0x77, 0x05, 0x8c, 0x6a, 0x7d, 0xbd, 0x69, 0xb8, 0x26, + 0x68, 0xd1, 0x55, 0x93, 0x9b, 0x4c, 0x66, 0xd6, 0xcf, 0xb4, 0x33, 0x5e, + 0x6a, 0xc1, 0x96, 0xca, 0xe6, 0x8b, 0x2d, 0xdf, 0xd6, 0x1d, 0xa6, 0x67, + 0xfc, 0x26, 0x96, 0xfc, 0xfa, 0xcd, 0x65, 0x77, 0x43, 0x44, 0x10, 0x01, + 0x08, 0x93, 0xa6, 0xb2, 0x1a, 0x27, 0x9c, 0x50, 0xde, 0xc0, 0xcf, 0xba, + 0x8d, 0x35, 0x6c, 0x57, 0x5b, 0x0e, 0x11, 0x7c, 0x89, 0x74, 0xca, 0x7e, + 0xf5, 0x08, 0xaf, 0xe4, 0x9f, 0x78, 0x14, 0x8d, 0x2e, 0x1f, 0x47, 0x0a, + 0x18, 0x26, 0xb0, 0x7d, 0xce, 0x36, 0x63, 0x30, 0xa5, 0x63, 0x5e, 0x10, + 0x98, 0xf9, 0xe2, 0x57, 0xe2, 0x0c, 0x17, 0x34, 0xfd, 0x4c, 0x35, 0xe5, + 0x44, 0xbf, 0xf1, 0xa1, 0x9f, 0x07, 0x4c, 0x5f, 0xb1, 0xff, 0x57, 0xd3, + 0xf9, 0xe8, 0xd6, 0x76, 0xae, 0xda, 0xd0, 0xd8, 0x49, 0x44, 0x65, 0x76, + 0xd1, 0xa3, 0x1b, 0xe5, 0x5e, 0x86, 0x12, 0xd2, 0x77, 0x6c, 0x19, 0xfa, + 0x32, 0x9b, 0xe6, 0xf8, 0x6d, 0xc8, 0x87, 0x52, 0xad, 0x80, 0xcd, 0xbd, + 0x83, 0xa7, 0x94, 0x68, 0x39, 0x01, 0x32, 0xa4, 0x91, 0x20, 0xe9, 0xb8, + 0xcc, 0x49, 0x8a, 0xad, 0x9f, 0x59, 0x11, 0x2a, 0x8a, 0x8c, 0xaa, 0x54, + 0x82, 0x58, 0x97, 0xc9, 0x4e, 0x2e, 0x99, 0xa0, 0xc6, 0x29, 0xc3, 0x3b, + 0x61, 0x51, 0xf8, 0x65, 0xa5, 0x76, 0x33, 0xf5, 0xa4, 0x5d, 0x3e, 0x3f, + 0xdc, 0xfc, 0x4d, 0xa9, 0x78, 0x16, 0x29, 0x61, 0x5f, 0x2b, 0x1d, 0x82, + 0x61, 0x8e, 0x5e, 0xb6, 0x10, 0xfc, 0x6c, 0x07, 0x9d, 0xe8, 0x34, 0x5d, + 0xe0, 0xad, 0x81, 0x19, 0x4c, 0x32, 0x9b, 0x1c, 0x5d, 0xae, 0xe6, 0x4e, + 0xaf, 0xba, 0xf3, 0x0d, 0x54, 0x7a, 0x9f, 0x84, 0x5b, 0xc0, 0x6c, 0xba, + 0x21, 0x14, 0x19, 0x57, 0x09, 0x63, 0x48, 0x92, 0xdb, 0x8b, 0x02, 0xff, + 0xf9, 0x3b, 0xd5, 0xe7, 0xa1, 0x97, 0x57, 0x88, 0x95, 0xc9, 0xf7, 0x99, + 0xc8, 0xab, 0x28, 0x6f, 0x89, 0x06, 0xde, 0x54, 0x2e, 0xe5, 0xeb, 0x51, + 0x0f, 0x36, 0xfd, 0xcf, 0x37, 0x43, 0x67, 0x21, 0xd8, 0xeb, 0xa4, 0xeb, + 0x5d, 0xf4, 0x64, 0xd5, 0xb7, 0x1d, 0xf6, 0xea, 0x0a, 0xe9, 0x75, 0x77, + 0xe5, 0x4e, 0xa4, 0x28, 0xdc, 0xc4, 0x09, 0xce, 0xf0, 0x66, 0x8f, 0x8c, + 0xa0, 0x28, 0x81, 0xc5, 0x87, 0x00, 0x61, 0x6b, 0xd3, 0x15, 0x3b, 0x81, + 0x9b, 0x72, 0xc5, 0xfc, 0x04, 0x22, 0x4c, 0x29, 0xfa, 0x42, 0x41, 0x0b, + 0x7c, 0xe5, 0xd9, 0xf6, 0xcd, 0x0d, 0xd5, 0x98, 0x05, 0x3c, 0x5e, 0x4c, + 0x0d, 0x4d, 0x1b, 0x8c, 0x8e, 0xb2, 0x13, 0xa9, 0xf7, 0x46, 0x38, 0xa1, + 0x52, 0x20, 0x67, 0x96, 0xa9, 0x50, 0x33, 0x7f, 0xb3, 0x00, 0x21, 0x3e, + 0x4e, 0x47, 0xd9, 0x9c, 0x53, 0x8d, 0xf7, 0xb6, 0xfa, 0x45, 0x19, 0x57, + 0x56, 0xfa, 0x4e, 0x75, 0x07, 0x9f, 0xe4, 0x5e, 0x13, 0xa9, 0x2b, 0xd7, + 0x70, 0x3b, 0xca, 0x2b, 0xd4, 0x65, 0xb1, 0xbc, 0xb6, 0xc0, 0xbc, 0xfa, + 0x58, 0x3a, 0x09, 0x9e, 0x4e, 0x8c, 0x08, 0xd0, 0x3c, 0xd1, 0xb0, 0x1c, + 0xd2, 0x60, 0xdd, 0x4e, 0xaf, 0xef, 0x62, 0x97, 0x01, 0x80, 0xb8, 0xab, + 0x22, 0x74, 0x2e, 0x0f, 0xd2, 0x34, 0x1b, 0x88, 0x86, 0x9a, 0xa1, 0x5f, + 0xf1, 0x2a, 0x4b, 0x90, 0xd4, 0x1c, 0x68, 0x7a, 0xb0, 0xb8, 0x6a, 0x2c, + 0xeb, 0x80, 0xdf, 0x6d, 0x4c, 0xf6, 0x43, 0x0e, 0x52, 0x91, 0x89, 0x10, + 0x6d, 0x71, 0xec, 0x03, 0xe9, 0x27, 0x2a, 0xa6, 0x31, 0xbb, 0xaa, 0x39, + 0x40, 0xef, 0x97, 0xe3, 0xec, 0x88, 0xb8, 0x47, 0x98, 0x4e, 0xc6, 0xf7, + 0xa3, 0x98, 0x6d, 0xc7, 0x1c, 0x12, 0x55, 0xf2, 0x4f, 0x8e, 0x61, 0xad, + 0x68, 0xb3, 0xf2, 0xf2, 0x1f, 0x20, 0x85, 0xba, 0x9f, 0x8a, 0x7d, 0x91, + 0xe2, 0x3f, 0xf7, 0xa6, 0x7f, 0x3f, 0xee, 0x09, 0x47, 0xf9, 0x7f, 0x68, + 0xcf, 0x83, 0xaf, 0x01, 0xda, 0x33, 0x0b, 0x88, 0xf0, 0xf7, 0xcb, 0x7a, + 0xa5, 0x92, 0x42, 0x0f, 0xd6, 0xc8, 0x25, 0xc1, 0xff, 0x8e, 0x32, 0xc0, + 0xbc, 0x72, 0x92, 0xc9, 0xf4, 0xf5, 0xfa, 0x15, 0x9b, 0x00, 0x46, 0x25, + 0x6e, 0x24, 0xf6, 0x10, 0x95, 0xea, 0x1c, 0xb0, 0x96, 0x0e, 0x8f, 0xb5, + 0x70, 0x68, 0xa7, 0x8f, 0x60, 0x23, 0xc7, 0xeb, 0x26, 0x09, 0xc9, 0x45, + 0x6a, 0xdc, 0x6e, 0xde, 0x82, 0x0f, 0xac, 0xea, 0x22, 0x5d, 0x47, 0x26, + 0xee, 0x9a, 0x6e, 0x0a, 0x42, 0xf2, 0xda, 0x18, 0x3c, 0x7d, 0xd8, 0x68, + 0x7e, 0x4a, 0x4c, 0xbd, 0xb0, 0x00, 0x73, 0x2c, 0x5c, 0x33, 0xf8, 0xb3, + 0x3e, 0x5c, 0xc7, 0x3b, 0xf4, 0x8d, 0xee, 0xee, 0x83, 0x21, 0x5c, 0x42, + 0x24, 0xb3, 0x13, 0xb3, 0x28, 0x1b, 0x85, 0xf5, 0xaa, 0x1c, 0xf9, 0xd8, + 0x90, 0x91, 0xaf, 0x98, 0x40, 0x7c, 0xce, 0x8c, 0x12, 0x5c, 0x68, 0x86, + 0xd4, 0x55, 0xd8, 0x80, 0x93, 0x01, 0x64, 0x34, 0x98, 0x8b, 0x9a, 0x7a, + 0x85, 0x62, 0xc0, 0x76, 0x92, 0xa3, 0x98, 0x11, 0x13, 0x60, 0xc3, 0x72, + 0xb4, 0xb1, 0x8b, 0xf4, 0xf8, 0xc6, 0x23, 0xf6, 0xe6, 0x98, 0x5a, 0xde, + 0x48, 0xff, 0x86, 0x28, 0x41, 0x6c, 0xcb, 0xc7, 0x70, 0x90, 0x17, 0xb9, + 0x61, 0x0f, 0x26, 0x2f, 0x8f, 0xb9, 0x56, 0x49, 0x79, 0x09, 0x88, 0xf2, + 0x3e, 0xff, 0x06, 0x90, 0xb5, 0x78, 0x8e, 0xb1, 0xac, 0x89, 0xe8, 0x8b, + 0x26, 0x4b, 0x6e, 0x7c, 0xbd, 0x54, 0x76, 0xdb, 0x6f, 0x78, 0xfc, 0xdd, + 0x9d, 0x31, 0x17, 0x15, 0xb7, 0x65, 0xc7, 0x9f, 0x55, 0x76, 0x5e, 0xa0, + 0xb9, 0x8e, 0xd9, 0xa1, 0x93, 0x23, 0x6c, 0x18, 0x47, 0x31, 0xee, 0x73, + 0x77, 0xa1, 0x44, 0xb2, 0x53, 0xd8, 0xd6, 0x82, 0x07, 0x0e, 0x1b, 0x86, + 0x2d, 0xb0, 0xe2, 0x22, 0x9f, 0xac, 0xb6, 0xb7, 0x88, 0xa0, 0x03, 0x07, + 0xe6, 0xbd, 0x45, 0x4d, 0x50, 0xec, 0xce, 0x4d, 0xe9, 0x43, 0x90, 0x8e, + 0xaf, 0xdf, 0xc0, 0x4d, 0xe8, 0x3d, 0xfe, 0xb8, 0x34, 0x2b, 0x81, 0xbf, + 0x02, 0x50, 0x87, 0x40, 0xaa, 0x70, 0x43, 0xc8, 0xda, 0x8e, 0xc0, 0xa6, + 0x7a, 0xab, 0xe7, 0x5a, 0x4d, 0xf2, 0x44, 0x9d, 0xbd, 0x7e, 0x76, 0x63, + 0xd8, 0x00, 0x45, 0xb2, 0x1e, 0x20, 0xb7, 0x96, 0x08, 0xb9, 0x4c, 0x06, + 0x81, 0x43, 0x26, 0xd4, 0x5b, 0x90, 0x3c, 0x39, 0xc3, 0x3b, 0xee, 0x27, + 0x7a, 0x4e, 0x1d, 0x5f, 0x9e, 0xeb, 0xe1, 0x2f, 0x10, 0xf0, 0xd9, 0x2e, + 0x61, 0x8a, 0x67, 0xca, 0xbb, 0xbf, 0x17, 0xe3, 0xf6, 0x58, 0xaa, 0xeb, + 0x5f, 0xd7, 0xda, 0xfb, 0x81, 0x63, 0x0e, 0xe0, 0xac, 0x93, 0xe8, 0x1b, + 0x11, 0x3a, 0x1f, 0x51, 0x26, 0x99, 0xea, 0xf3, 0x73, 0x99, 0x2a, 0xd0, + 0xaf, 0x76, 0xd1, 0xda, 0xcc, 0xfe, 0xce, 0x82, 0x69, 0x6d, 0xe4, 0xc3, + 0x44, 0xa6, 0x7a, 0x8e, 0xda, 0x44, 0xdf, 0x07, 0xaf, 0xf0, 0x6d, 0x33, + 0x90, 0x8a, 0xc4, 0x8c, 0x68, 0xa6, 0x86, 0xa8, 0x59, 0x00, 0x62, 0x36, + 0x0c, 0x55, 0x7d, 0x63, 0xd2, 0xea, 0x3a, 0x2b, 0x6a, 0x5b, 0x76, 0x9d, + 0xab, 0x26, 0xb6, 0x25, 0xe7, 0x95, 0x42, 0x54, 0x11, 0xf5, 0x05, 0x33, + 0x7f, 0x6e, 0x8a, 0xa0, 0x4c, 0x25, 0x63, 0x3f, 0x13, 0xfe, 0x81, 0x54, + 0x7b, 0x86, 0x45, 0x9b, 0xba, 0x6b, 0x34, 0x4a, 0x1e, 0xeb, 0x92, 0x67, + 0x9e, 0x13, 0x30, 0xc1, 0x3c, 0xfd, 0xe1, 0xe8, 0xbe, 0xe2, 0x5c, 0x93, + 0xf5, 0xd9, 0xf6, 0x9d, 0x42, 0x88, 0x59, 0x2f, 0x76, 0x77, 0x6a, 0x4a, + 0x4c, 0x8e, 0xed, 0x0e, 0x49, 0x7e, 0xdc, 0x08, 0xef, 0x84, 0x74, 0x1e, + 0x27, 0x37, 0x53, 0xd4, 0x7e, 0xbf, 0xac, 0x32, 0x94, 0x00, 0x06, 0xf4, + 0x57, 0x0f, 0xa6, 0xe7, 0xa6, 0x70, 0x25, 0x3a, 0x2e, 0x8d, 0x83, 0xa0, + 0x1c, 0xa8, 0x08, 0x2c, 0xbd, 0x14, 0x71, 0xad, 0x57, 0xd1, 0xb1, 0xed, + 0x49, 0x91, 0x1f, 0x72, 0xe8, 0xab, 0x46, 0x83, 0x89, 0xb8, 0x16, 0xe4, + 0xf5, 0x7f, 0x73, 0x1f, 0x44, 0x01, 0xc9, 0x88, 0x9c, 0xdc, 0x65, 0xb4, + 0x44, 0xbd, 0x47, 0x8b, 0x52, 0x48, 0x5c, 0x30, 0xf9, 0x73, 0xa0, 0x8c, + 0x72, 0xa3, 0x4c, 0x93, 0x0f, 0xb1, 0xda, 0x0b, 0x8c, 0x02, 0xb4, 0x07, + 0x06, 0xda, 0x78, 0xed, 0x7a, 0x4c, 0x4a, 0xb2, 0x21, 0xee, 0x23, 0xe8, + 0x56, 0x4c, 0x6d, 0x03, 0xa0, 0x71, 0x2c, 0xdf, 0x6a, 0xc4, 0x68, 0xa4, + 0xf0, 0x18, 0x49, 0xcd, 0x7e, 0x66, 0xef, 0x62, 0x1e, 0xe7, 0x23, 0x3b, + 0x87, 0x19, 0x54, 0x12, 0x67, 0x63, 0xb7, 0x5f, 0xa6, 0xd2, 0x26, 0xed, + 0x33, 0x09, 0xfe, 0x58, 0xae, 0x78, 0x48, 0x03, 0x17, 0x00, 0x01, 0x7f, + 0x70, 0xe2, 0xde, 0xc0, 0x1d, 0x4c, 0x32, 0x66, 0xec, 0xe0, 0x8f, 0x00, + 0x3e, 0xf3, 0x57, 0x77, 0xe3, 0x9b, 0x8d, 0x70, 0xac, 0x3c, 0x36, 0x0e, + 0x7b, 0x67, 0xc6, 0x1d, 0xc5, 0x64, 0x9c, 0x0a, 0xfb, 0xdb, 0x40, 0xf9, + 0x85, 0x42, 0x1a, 0x01, 0x4b, 0x86, 0xb2, 0x60, 0xc3, 0xc6, 0x69, 0x48, + 0xff, 0x22, 0xf8, 0xcb, 0xc2, 0x4a, 0xb2, 0x36, 0x62, 0xdb, 0xaa, 0x1f, + 0xe5, 0xdc, 0x2c, 0xa5, 0x2c, 0x33, 0x42, 0xf0, 0xe3, 0x9b, 0x48, 0xa7, + 0x50, 0xaa, 0x0f, 0x3e, 0x6c, 0xfb, 0xed, 0x4b, 0xbd, 0xd1, 0x1b, 0x5d, + 0x96, 0xa2, 0x9c, 0x1a, 0xe3, 0xb6, 0x32, 0xf0, 0xcb, 0x08, 0x60, 0xdf, + 0x48, 0xde, 0x04, 0x62, 0xfc, 0x01, 0x30, 0x29, 0x9e, 0x39, 0x4a, 0x0c, + 0x4f, 0x79, 0x3b, 0xc9, 0xce, 0xd8, 0xc4, 0xee, 0xcc, 0xdc, 0x63, 0x50, + 0xe5, 0xa4, 0x6c, 0x95, 0x66, 0xc0, 0x47, 0x0f, 0xbe, 0xa2, 0x02, 0x6d, + 0xcd, 0x32, 0xc3, 0x14, 0x0e, 0x95, 0x21, 0xbc, 0x61, 0xee, 0x25, 0x65, + 0xfc, 0x4c, 0x23, 0xe0, 0xa5, 0x0a, 0x65, 0xc0, 0xe3, 0xe8, 0x56, 0x10, + 0xb3, 0xb1, 0x6a, 0xd1, 0xd3, 0x71, 0xb2, 0xb5, 0x90, 0x74, 0x32, 0x24, + 0xe5, 0xa7, 0x04, 0x37, 0xde, 0x71, 0xef, 0x08, 0x4c, 0x1c, 0x80, 0x6b, + 0x99, 0x17, 0x47, 0x72, 0x44, 0x31, 0x22, 0xd9, 0xce, 0xff, 0x61, 0x2d, + 0x72, 0xe0, 0xbd, 0x48, 0x3e, 0xfd, 0x5a, 0xc5, 0x7b, 0x16, 0x96, 0xbd, + 0x47, 0x60, 0x6d, 0xa1, 0x6a, 0x34, 0xe9, 0xaa, 0xd5, 0xfe, 0x09, 0x1d, + 0xfa, 0x94, 0xb8, 0xc0, 0x63, 0xa9, 0x1d, 0x8a, 0x27, 0x7b, 0xf0, 0xd2, + 0xe7, 0x3e, 0x5e, 0x6e, 0x6a, 0x8e, 0xe3, 0x4b, 0xa8, 0x0c, 0xac, 0xc4, + 0x50, 0x1c, 0xa0, 0xfc, 0x48, 0x42, 0x53, 0x54, 0x08, 0x64, 0xae, 0x9f, + 0x19, 0xd6, 0xd3, 0xc9, 0x55, 0x0e, 0x72, 0x18, 0x53, 0xef, 0x02, 0xd1, + 0x14, 0x81, 0xa9, 0xa8, 0xb6, 0xf5, 0x93, 0x56, 0xcb, 0xd0, 0x63, 0xbc, + 0xb9, 0xfd, 0x77, 0xa4, 0x1d, 0x3f, 0x29, 0xba, 0x97, 0xb5, 0xed, 0x7c, + 0xe5, 0x35, 0xe5, 0x74, 0x6b, 0x08, 0xe8, 0x3f, 0x6d, 0xc4, 0x70, 0x06, + 0x3b, 0xd1, 0x92, 0xcc, 0xab, 0x7a, 0x22, 0x13, 0x96, 0x41, 0xfc, 0x92, + 0x81, 0xb7, 0x39, 0xdf, 0x68, 0xaa, 0x77, 0x21, 0x87, 0xff, 0x78, 0x83, + 0xf5, 0xca, 0x8b, 0x08, 0xa9, 0xcd, 0xc0, 0xa0, 0xb8, 0x7c, 0x52, 0x93, + 0xec, 0x93, 0x5c, 0xe6, 0xd9, 0xc9, 0x49, 0x94, 0x60, 0xac, 0x1c, 0x9e, + 0x1e, 0x19, 0xac, 0xc3, 0xfa, 0x3f, 0xe0, 0x36, 0x1d, 0x99, 0x8f, 0xea, + 0xc7, 0xe6, 0x1e, 0x0b, 0x7f, 0x02, 0x73, 0x3c, 0xda, 0x49, 0x68, 0x44, + 0x91, 0x76, 0x3c, 0x4d, 0x53, 0xfc, 0xda, 0x99, 0x8d, 0x13, 0xcf, 0xd3, + 0x88, 0xbb, 0xdf, 0x3f, 0xab, 0x42, 0x08, 0x9b, 0xeb, 0x1f, 0x93, 0x09, + 0x59, 0x39, 0x21, 0x2c, 0x91, 0xe5, 0xef, 0x97, 0xf7, 0x8c, 0x56, 0x34, + 0x66, 0x94, 0x05, 0x18, 0x1b, 0x50, 0x41, 0xf3, 0xa6, 0xca, 0x82, 0xdf, + 0xa3, 0x8e, 0xa9, 0x3f, 0x6d, 0xa0, 0xfb, 0x74, 0x2b, 0x35, 0x2c, 0x02, + 0xc3, 0xd3, 0xba, 0x21, 0x0e, 0xef, 0x23, 0x35, 0x06, 0xcd, 0xc7, 0x5e, + 0x44, 0x6f, 0xa5, 0x5d, 0xee, 0x9a, 0x42, 0x54, 0x47, 0x78, 0xbe, 0x47, + 0x9e, 0x17, 0x56, 0x94, 0xf7, 0xb2, 0x6c, 0x97, 0x45, 0x16, 0xea, 0xa0, + 0xe4, 0xb4, 0x84, 0xf0, 0xda, 0xb6, 0x3a, 0xb6, 0xee, 0x1d, 0x5f, 0x87, + 0x0d, 0xa4, 0x13, 0x19, 0xa3, 0x4b, 0x27, 0x4c, 0xec, 0x9e, 0x66, 0x2b, + 0x6f, 0x91, 0x85, 0x22, 0xee, 0x2e, 0x55, 0xa2, 0xe5, 0x52, 0x09, 0x78, + 0x05, 0x39, 0x32, 0x27, 0xda, 0x7c, 0xe2, 0xcc, 0x78, 0x40, 0xfc, 0x11, + 0xab, 0x95, 0xbc, 0xb6, 0x3f, 0x26, 0x90, 0x15, 0xcb, 0x59, 0xd5, 0x10, + 0x36, 0xeb, 0x03, 0x25, 0x8e, 0x46, 0xcf, 0x63, 0x1d, 0x34, 0x76, 0xda, + 0x61, 0xef, 0xfd, 0x86, 0x66, 0x7a, 0x23, 0x9a, 0xff, 0xcb, 0xe1, 0x61, + 0xc7, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x64, 0x6b, 0x75, 0xd3, 0x13, 0xc6, + 0x7f, 0x6c, 0x2b, 0xef, 0x9b, 0xbf, 0x66, 0x14, 0xe8, 0x6f, 0xb2, 0xaf, + 0xf4, 0x61, 0x91, 0x3f, 0x7b, 0xf7, 0x9b, 0xb5, 0x34, 0x6b, 0x8f, 0xca, + 0xcf, 0x32, 0x6c, 0xe0, 0xb4, 0xea, 0x51, 0xff, 0x01, 0x8b, 0xd7, 0x80, + 0x95, 0x46, 0xb9, 0xbc, 0xe3, 0x92, 0x52, 0x3b, 0xec, 0x63, 0xc3, 0x6e, + 0x34, 0xef, 0xc7, 0xb1, 0x52, 0x41, 0x87, 0x21, 0xa5, 0xf1, 0xe5, 0x37, + 0xc5, 0x7c, 0x9d, 0xa3, 0x14, 0xb8, 0xee, 0x35, 0x63, 0xed, 0x00, 0xce, + 0x91, 0xf8, 0xc7, 0x88, 0x41, 0xf6, 0xbf, 0x5a, 0x6c, 0x73, 0xca, 0x0b, + 0x1a, 0xde, 0x7e, 0x49, 0x7c, 0xc1, 0xe8, 0xeb, 0xe3, 0xba, 0xf2, 0x8a, + 0x98, 0xce, 0x19, 0x98, 0xdb, 0x62, 0x03, 0x15, 0x08, 0x33, 0x83, 0x77, + 0x3f, 0x7c, 0xc8, 0x27, 0xef, 0x2d, 0x4b, 0x4b, 0x7f, 0x80, 0xfc, 0x12, + 0x41, 0x4b, 0x89, 0x88, 0x32, 0x19, 0xaa, 0xf4, 0xff, 0x39, 0x61, 0xc9, + 0x06, 0xfd, 0x78, 0x79, 0xc0, 0x52, 0x7e, 0xe6, 0x79, 0x7d, 0x50, 0x43, + 0xb3, 0xf2, 0x86, 0xb2, 0xf3, 0x38, 0x35, 0x72, 0xbf, 0xb7, 0x35, 0x45, + 0x34, 0xb3, 0x05, 0x67, 0x3e, 0xb7, 0x71, 0x5e, 0x55, 0x36, 0xc7, 0xbf, + 0x3b, 0x6d, 0xc3, 0xf9, 0x9c, 0x94, 0x4f, 0x63, 0x3e, 0x34, 0x44, 0x9e, + 0x5f, 0x2b, 0x65, 0xc2, 0xeb, 0x5b, 0x5c, 0x61, 0x20, 0x6a, 0x3e, 0xb5, + 0x38, 0xf0, 0x5b, 0xde, 0x45, 0xa7, 0x1f, 0xa7, 0xad, 0xd0, 0xb5, 0x0d, + 0x2d, 0x15, 0x9f, 0x7c, 0x62, 0x7a, 0xf1, 0x2a, 0xb8, 0x6c, 0xeb, 0x0f, + 0xd5, 0x84, 0xa9, 0xfa, 0x5f, 0xc6, 0x39, 0x66, 0xd7, 0xaa, 0x8c, 0x4b, + 0xbe, 0xaf, 0x26, 0xc1, 0x7b, 0xbb, 0xbb, 0x45, 0xa9, 0x58, 0xb7, 0x62, + 0x6b, 0x96, 0x3a, 0xe9, 0xb0, 0x87, 0x1b, 0x5d, 0x8b, 0x77, 0xe0, 0xcc, + 0x9c, 0xad, 0x3b, 0xfb, 0xe9, 0x53, 0x85, 0x1c, 0xae, 0xf8, 0x70, 0x06, + 0x66, 0x88, 0x30, 0x12, 0x44, 0xa5, 0x31, 0xd8, 0x23, 0xdc, 0x4f, 0x80, + 0x36, 0x02, 0x9c, 0x9e, 0x36, 0x09, 0x70, 0xd5, 0xa4, 0x41, 0xa6, 0x48, + 0xfd, 0xd3, 0x39, 0x19, 0xa0, 0x43, 0x7e, 0x8d, 0xe9, 0x41, 0x3b, 0x1b, + 0x58, 0x6b, 0xb0, 0xe2, 0x28, 0x21, 0x21, 0xe3, 0x6d, 0xa1, 0x84, 0x29, + 0x1e, 0xcf, 0x5f, 0xeb, 0x81, 0xf9, 0xc6, 0x07, 0x09, 0xc9, 0xe1, 0x6d, + 0x53, 0x47, 0x59, 0xf7, 0x14, 0x23, 0x5d, 0x39, 0x12, 0x4b, 0xbe, 0x7e, + 0x28, 0xb9, 0x9c, 0x23 +}; +unsigned int ios6_1_keychain_2_db_len = 126976; + diff --git a/sec/securityd/Regressions/sd-10-policytree.c b/Security/sec/securityd/Regressions/sd-10-policytree.c similarity index 97% rename from sec/securityd/Regressions/sd-10-policytree.c rename to Security/sec/securityd/Regressions/sd-10-policytree.c index 4da60bb5..ccce8913 100644 --- a/sec/securityd/Regressions/sd-10-policytree.c +++ b/Security/sec/securityd/Regressions/sd-10-policytree.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2009,2012 Apple Inc. All Rights Reserved. */ #include diff --git a/sec/securityd/Regressions/secd-01-items.c b/Security/sec/securityd/Regressions/secd-01-items.c similarity index 80% rename from sec/securityd/Regressions/secd-01-items.c rename to Security/sec/securityd/Regressions/secd-01-items.c index 2624aa12..0979cea9 100644 --- a/sec/securityd/Regressions/secd-01-items.c +++ b/Security/sec/securityd/Regressions/secd-01-items.c @@ -1,10 +1,26 @@ -// -// secd-01-dbitems.c -// sec -// -// Created by Fabrice Gautier on 5/29/13. -// -// +/* + * 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" @@ -125,6 +141,9 @@ int secd_01_items(int argc, char *const *argv) SetCustomHomeURL(NULL); kc_dbhandle_reset(); + CFReleaseSafe(item); + CFReleaseSafe(query); + return 0; } diff --git a/sec/securityd/Regressions/secd-02-upgrade-while-locked.c b/Security/sec/securityd/Regressions/secd-02-upgrade-while-locked.c similarity index 79% rename from sec/securityd/Regressions/secd-02-upgrade-while-locked.c rename to Security/sec/securityd/Regressions/secd-02-upgrade-while-locked.c index 0566a7a5..e05949cd 100644 --- a/sec/securityd/Regressions/secd-02-upgrade-while-locked.c +++ b/Security/sec/securityd/Regressions/secd-02-upgrade-while-locked.c @@ -1,10 +1,26 @@ -// -// secd-02-corruption.c -// sec -// -// Created by Fabrice Gautier on 5/31/13. -// -// +/* + * 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" @@ -32,7 +48,7 @@ #include "SecdTestKeychainUtilities.h" -#include "brighton_keychain_2_db.h" +#include "ios6_1_keychain_2_db.h" static OSStatus query_one(void) { @@ -77,7 +93,7 @@ static void *do_query(void *arg) CFTypeRef results = NULL; for(int i=0;i<20;i++) - verify_action(SecItemCopyMatching(query, &results)==errSecUpgradePending, return (void *)-1); + verify_action(SecItemCopyMatching(query, &results)==errSecUpgradePending, CFReleaseSafe(query); return (void *)-1); CFReleaseSafe(query); @@ -110,7 +126,7 @@ int secd_02_upgrade_while_locked(int argc, char *const *argv) CFStringRef keychain_path_cf = __SecKeychainCopyPath(); CFStringPerformWithCString(keychain_path_cf, ^(const char *keychain_path) { - writeFile(keychain_path, brighton_keychain_2_db, brighton_keychain_2_db_len); + writeFile(keychain_path, ios6_1_keychain_2_db, ios6_1_keychain_2_db_len); /* custom notification */ SecItemServerSetKeychainChangedNotification("com.apple.secdtests.keychainchanged"); diff --git a/sec/securityd/Regressions/secd-03-corrupted-items.c b/Security/sec/securityd/Regressions/secd-03-corrupted-items.c similarity index 81% rename from sec/securityd/Regressions/secd-03-corrupted-items.c rename to Security/sec/securityd/Regressions/secd-03-corrupted-items.c index 336f456f..b6294434 100644 --- a/sec/securityd/Regressions/secd-03-corrupted-items.c +++ b/Security/sec/securityd/Regressions/secd-03-corrupted-items.c @@ -1,10 +1,26 @@ -// -// secd-03-corrupted-item.c -// sec -// -// Created by Fabrice Gautier on 06/19/13. -// -// +/* + * 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" diff --git a/sec/securityd/Regressions/secd-04-corrupted-items.c b/Security/sec/securityd/Regressions/secd-04-corrupted-items.c similarity index 82% rename from sec/securityd/Regressions/secd-04-corrupted-items.c rename to Security/sec/securityd/Regressions/secd-04-corrupted-items.c index 0774ad3b..1e5d3aac 100644 --- a/sec/securityd/Regressions/secd-04-corrupted-items.c +++ b/Security/sec/securityd/Regressions/secd-04-corrupted-items.c @@ -1,10 +1,26 @@ -// -// secd-04-corrupted-item.c -// sec -// -// Created by Fabrice Gautier on 06/19/13. -// -// +/* + * 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" diff --git a/sec/securityd/Regressions/secd-05-corrupted-items.c b/Security/sec/securityd/Regressions/secd-05-corrupted-items.c similarity index 81% rename from sec/securityd/Regressions/secd-05-corrupted-items.c rename to Security/sec/securityd/Regressions/secd-05-corrupted-items.c index 91007679..18ade753 100644 --- a/sec/securityd/Regressions/secd-05-corrupted-items.c +++ b/Security/sec/securityd/Regressions/secd-05-corrupted-items.c @@ -1,10 +1,26 @@ -// -// secd-05-corrupted-item.c -// sec -// -// Created by Fabrice Gautier on 06/26/13. -// -// +/* + * 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" diff --git a/sec/securityd/Regressions/secd-30-keychain-upgrade.c b/Security/sec/securityd/Regressions/secd-30-keychain-upgrade.c similarity index 87% rename from sec/securityd/Regressions/secd-30-keychain-upgrade.c rename to Security/sec/securityd/Regressions/secd-30-keychain-upgrade.c index 01c729d5..bdf2dcc9 100644 --- a/sec/securityd/Regressions/secd-30-keychain-upgrade.c +++ b/Security/sec/securityd/Regressions/secd-30-keychain-upgrade.c @@ -1,12 +1,27 @@ /* - * secd-30-keychain-upgrade.c - * Security - * - * Created by Michael Brouwer on 4/29/08. - * Copyright (c) 2008,2010,2013 Apple Inc.. All Rights Reserved. + * Copyright (c) 2008,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@ */ + #include #include #include diff --git a/sec/securityd/Regressions/secd-31-keychain-bad.c b/Security/sec/securityd/Regressions/secd-31-keychain-bad.c similarity index 78% rename from sec/securityd/Regressions/secd-31-keychain-bad.c rename to Security/sec/securityd/Regressions/secd-31-keychain-bad.c index 0297c12e..e9c8bfcf 100644 --- a/sec/securityd/Regressions/secd-31-keychain-bad.c +++ b/Security/sec/securityd/Regressions/secd-31-keychain-bad.c @@ -1,12 +1,27 @@ /* - * secd-31-keychain-bad.c - * Security - * - * Created by Michael Brouwer on 5/23/08. - * Copyright (c) 2008,2010,2013 Apple Inc.. All Rights Reserved. + * Copyright (c) 2008,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@ */ + #include #include #include diff --git a/Security/sec/securityd/Regressions/secd-31-keychain-unreadable.c b/Security/sec/securityd/Regressions/secd-31-keychain-unreadable.c new file mode 100644 index 00000000..4f277df2 --- /dev/null +++ b/Security/sec/securityd/Regressions/secd-31-keychain-unreadable.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2008-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@ + */ + + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "secd_regressions.h" + +#include + +#include "SecdTestKeychainUtilities.h" + + +/* Create an empty keychain file that can't be read or written and make sure + securityd can deal with it. */ +static void tests(void) +{ + /* custom keychain dir */ + secd_test_setup_temp_keychain("secd_31_keychain_unreadable", ^{ + CFStringRef keychain_path_cf = __SecKeychainCopyPath(); + + CFStringPerformWithCString(keychain_path_cf, ^(const char *keychain_path) { + int fd; + ok_unix(fd = open(keychain_path, O_RDWR | O_CREAT | O_TRUNC, 0644), + "create keychain file '%s'", keychain_path); + ok_unix(fchmod(fd, 0), " keychain file '%s'", keychain_path); + ok_unix(close(fd), "close keychain file '%s'", keychain_path); + + }); + + CFReleaseSafe(keychain_path_cf); + }); + + int v_eighty = 80; + CFNumberRef eighty = CFNumberCreate(NULL, kCFNumberSInt32Type, &v_eighty); + 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("members.spamcop.net")); + CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("smith")); + CFDictionaryAddValue(query, kSecAttrPort, eighty); + CFDictionaryAddValue(query, kSecAttrProtocol, kSecAttrProtocolHTTP); + CFDictionaryAddValue(query, kSecAttrAuthenticationType, kSecAttrAuthenticationTypeDefault); + CFDictionaryAddValue(query, kSecValueData, pwdata); + ok_status(SecItemAdd(query, NULL), "add internet password"); + is_status(SecItemAdd(query, NULL), errSecDuplicateItem, + "add internet password again"); + + ok_status(SecItemCopyMatching(query, NULL), "Found the item we added"); + + ok_status(SecItemDelete(query),"Deleted the item we added"); + + CFReleaseSafe(eighty); + CFReleaseSafe(pwdata); + CFReleaseSafe(query); +} + +int secd_31_keychain_unreadable(int argc, char *const *argv) +{ + plan_tests(7 + kSecdTestSetupTestCount); + tests(); + + return 0; +} diff --git a/Security/sec/securityd/Regressions/secd-50-account.c b/Security/sec/securityd/Regressions/secd-50-account.c new file mode 100644 index 00000000..b92c5237 --- /dev/null +++ b/Security/sec/securityd/Regressions/secd-50-account.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "secd_regressions.h" +#include "SOSTestDataSource.h" + +#include "SOSRegressionUtilities.h" +#include + +#include +#include "SecdTestKeychainUtilities.h" +#include "SOSAccountTesting.h" + +static int kTestTestCount = 10 + kSecdTestSetupTestCount; +static void tests(void) +{ + secd_test_setup_temp_keychain("secd_50_account", ^{ + }); + + CFErrorRef error = NULL; + CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); + CFStringRef cfaccount = CFSTR("test@test.org"); + + SOSDataSourceFactoryRef test_factory = SOSTestDataSourceFactoryCreate(); + SOSDataSourceRef test_source = SOSTestDataSourceCreate(); + SOSTestDataSourceFactoryAddDataSource(test_factory, CFSTR("TestType"), test_source); + + SOSAccountRef account = CreateAccountForLocalChanges(CFSTR("Test Device"),CFSTR("TestType") ); + + ok(SOSAccountAssertUserCredentials(account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + CFReleaseNull(cfpassword); + + ok(NULL != account, "Created"); + + ok(1 == SOSAccountCountCircles(account), "Has one circle"); + + size_t size = SOSAccountGetDEREncodedSize(account, &error); + CFReleaseNull(error); + uint8_t buffer[size]; + uint8_t* start = SOSAccountEncodeToDER(account, &error, buffer, buffer + sizeof(buffer)); + CFReleaseNull(error); + + ok(start, "successful encoding"); + ok(start == buffer, "Used whole buffer"); + + const uint8_t *der = buffer; + SOSAccountRef inflated = SOSAccountCreateFromDER(kCFAllocatorDefault, test_factory, + &error, &der, buffer + sizeof(buffer)); + + SOSAccountEnsureFactoryCirclesTest(inflated, CFSTR("Test Device")); + ok(inflated, "inflated"); + ok(CFEqual(inflated, account), "Compares"); + + CFDictionaryRef new_gestalt = SOSCreatePeerGestaltFromName(CFSTR("New Device")); + ok(SOSAccountResetToOffering(account, &error), "Reset to Offering (%@)", error); + CFReleaseNull(error); + is(SOSAccountIsInCircles(account, &error), kSOSCCInCircle, "Was in Circle (%@)", error); + CFReleaseNull(error); + + SOSAccountUpdateGestalt(account, new_gestalt); + + is(SOSAccountIsInCircles(account, &error), kSOSCCInCircle, "Still in Circle (%@)", error); + CFReleaseNull(error); + + CFReleaseNull(new_gestalt); + CFReleaseNull(account); + + SOSUnregisterAllTransportMessages(); + SOSUnregisterAllTransportCircles(); + SOSUnregisterAllTransportKeyParameters(); + + CFArrayRemoveAllValues(key_transports); + CFArrayRemoveAllValues(circle_transports); + CFArrayRemoveAllValues(message_transports); + +} + +int secd_50_account(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/sec/securityd/Regressions/secd-51-account-inflate.c b/Security/sec/securityd/Regressions/secd-51-account-inflate.c similarity index 77% rename from sec/securityd/Regressions/secd-51-account-inflate.c rename to Security/sec/securityd/Regressions/secd-51-account-inflate.c index 96766c5b..100a6cf3 100644 --- a/sec/securityd/Regressions/secd-51-account-inflate.c +++ b/Security/sec/securityd/Regressions/secd-51-account-inflate.c @@ -1,10 +1,26 @@ -// -// secd-51-account-inflate.c -// sec -// -// Created by Richard Murphy on 7/22/13. -// -// +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include #include @@ -26,6 +42,8 @@ #include #include "SecdTestKeychainUtilities.h" +#include "SOSAccountTesting.h" +#include "SOSTransportTestTransports.h" uint8_t staticbuffer[439] = { 0x30, 0x82, 0x01, 0xB3, 0x31, 0x1D, 0x30, 0x1B, 0x0C, 0x0C, 0x43, 0x6F, 0x6D, 0x70, 0x75, 0x74, @@ -60,82 +78,86 @@ uint8_t staticbuffer[439] = { -static int kTestTestCount = 11 + kSecdTestSetupTestCount; +static int kTestTestCount = 7 + kSecdTestSetupTestCount; static void tests(void) { secd_test_setup_temp_keychain("secd_51_account_inflate", ^{ }); - + CFErrorRef error = NULL; CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); CFStringRef cfaccount = CFSTR("test@test.org"); - - SOSAccountKeyInterestBlock interest_block = ^(bool getNewKeysOnly, CFArrayRef alwaysKeys, CFArrayRef afterFirstUnlockKeys, CFArrayRef unlockedKeys) {}; - SOSAccountDataUpdateBlock update_block = ^ bool (CFDictionaryRef keys, CFErrorRef *error) {return true;}; - + SOSDataSourceFactoryRef test_factory = SOSTestDataSourceFactoryCreate(); SOSDataSourceRef test_source = SOSTestDataSourceCreate(); SOSTestDataSourceFactoryAddDataSource(test_factory, CFSTR("TestType"), test_source); - - CFDictionaryRef gestalt = SOSCreatePeerGestaltFromName(CFSTR("Test Device")); - SOSAccountRef account = SOSAccountCreate(kCFAllocatorDefault, gestalt, test_factory, - interest_block, update_block); + + SOSAccountRef account = CreateAccountForLocalChanges(CFSTR("Test Device"), CFSTR("TestType")); ok(SOSAccountAssertUserCredentials(account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); CFReleaseNull(error); CFReleaseNull(cfpassword); - + ok(NULL != account, "Created"); - + ok(1 == SOSAccountCountCircles(account), "Has one circle"); - + // Use this part with suitable changes to test when we allow account upgrades. size_t size = SOSAccountGetDEREncodedSize(account, &error); CFReleaseNull(error); uint8_t buffer[size]; uint8_t* start = SOSAccountEncodeToDER(account, &error, buffer, buffer + sizeof(buffer)); CFReleaseNull(error); - + ok(start, "successful encoding"); ok(start == buffer, "Used whole buffer"); - + const uint8_t *der = buffer; - SOSAccountRef inflated = SOSAccountCreateFromDER(kCFAllocatorDefault, test_factory, interest_block, update_block, + SOSAccountRef inflated = SOSAccountCreateFromDER(kCFAllocatorDefault, test_factory, &error, &der, buffer + sizeof(buffer)); - + ok(inflated, "inflated"); ok(CFEqual(inflated, account), "Compares"); - + #if UPGRADE_FROM_PREVIOUS_VERSION CFDictionaryRef new_gestalt = SOSCreatePeerGestaltFromName(CFSTR("New Device")); - + ok(SOSAccountResetToOffering(account, &error), "Reset to Offering (%@)", error); CFReleaseNull(error); - + is(SOSAccountIsInCircles(account, &error), kSOSCCInCircle, "Was in Circle (%@)", error); CFReleaseNull(error); - + SOSAccountUpdateGestalt(account, new_gestalt); - + is(SOSAccountIsInCircles(account, &error), kSOSCCInCircle, "Still in Circle (%@)", error); CFReleaseNull(error); - -// See if this account inflates: - + + // See if this account inflates: + const uint8_t *der2 = staticbuffer; SOSAccountRef inflated2 = SOSAccountCreateFromDER(kCFAllocatorDefault, test_factory, interest_block, update_block, &error, &der2, staticbuffer + sizeof(staticbuffer)); - + ok(!inflated2, "inflated2"); #endif - CFReleaseNull(gestalt); CFReleaseNull(account); + + + SOSUnregisterAllTransportMessages(); + SOSUnregisterAllTransportCircles(); + SOSUnregisterAllTransportKeyParameters(); + CFArrayRemoveAllValues(key_transports); + CFArrayRemoveAllValues(circle_transports); + CFArrayRemoveAllValues(message_transports); + + } int secd_51_account_inflate(int argc, char *const *argv) { plan_tests(kTestTestCount); - + tests(); - - return 0; + + return 0; } diff --git a/Security/sec/securityd/Regressions/secd-52-account-changed.c b/Security/sec/securityd/Regressions/secd-52-account-changed.c new file mode 100644 index 00000000..066b05c3 --- /dev/null +++ b/Security/sec/securityd/Regressions/secd-52-account-changed.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "secd_regressions.h" +#include "SOSTestDataSource.h" + +#include "SOSRegressionUtilities.h" +#include + +#include + +#include "SecdTestKeychainUtilities.h" +#include "SOSAccountTesting.h" + +static int kTestTestCount = 156; + +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 carol_account = CreateAccountForLocalChanges(CFSTR("Carol"), CFSTR("TestSource")); + + ok(SOSAccountAssertUserCredentials(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, carol_account, NULL), 1, "update"); + + + CFDictionaryRef new_gestalt = SOSCreatePeerGestaltFromName(CFSTR("New Device")); + ok (SOSAccountUpdateGestalt(bob_account, new_gestalt), "did we send a null circle?"); + CFReleaseNull(new_gestalt); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 1, "nothing published"); + + ok(SOSAccountAssertUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + ok(SOSAccountAssertUserCredentials(carol_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + CFReleaseNull(cfpassword); + + /* ==================== Three Accounts setup =============================================*/ + + ok(SOSAccountResetToOffering(alice_account, &error), "Reset to offering (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 2, "update"); + + ok(SOSAccountJoinCircles(bob_account, &error), "Bob Applies (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 2, "update"); + + + ok(SOSAccountJoinCircles(carol_account, &error), "Carol Applies (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 2, "update"); + + + { + CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); + + ok(applicants && CFArrayGetCount(applicants) == 2, "See two applicants %@ (%@)", applicants, error); + ok(SOSAccountAcceptApplicants(alice_account, applicants, &error), "Alice accepts (%@)", error); + CFReleaseNull(error); + CFReleaseNull(applicants); + } + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 4, "update"); + + accounts_agree_internal("bob&alice pair", bob_account, alice_account, false); + accounts_agree_internal("bob&carol pair", bob_account, carol_account, false); + + /* ==================== Three Accounts in circle =============================================*/ + InjectChangeToMulti(changes, CFSTR("^AccountChanged"), CFSTR("none"), alice_account, bob_account, carol_account, NULL); + + SOSAccountEnsureFactoryCirclesTest(alice_account, CFSTR("Alice")); + SOSAccountEnsureFactoryCirclesTest(bob_account, CFSTR("Bob")); + SOSAccountEnsureFactoryCirclesTest(carol_account, CFSTR("Carol")); + + is(SOSAccountIsInCircles(alice_account, &error), kSOSCCError, "Account reset - no user keys - error"); + is(SOSAccountIsInCircles(bob_account, &error), kSOSCCError, "Account reset - no user keys - error"); + is(SOSAccountIsInCircles(carol_account, &error), kSOSCCError, "Account reset - no user keys - error"); + + CFDataRef cfpassword2 = CFDataCreate(NULL, (uint8_t *) "ooFooFooF", 10); + CFStringRef cfaccount2 = CFSTR("test2@test.org"); + + ok(SOSAccountAssertUserCredentials(alice_account, cfaccount2, cfpassword2, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + + is(SOSAccountIsInCircles(alice_account, &error), kSOSCCCircleAbsent, "Account reset - circle is absent"); + is(SOSAccountIsInCircles(bob_account, &error), kSOSCCError, "Account reset - no user keys - error"); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 2, "updates"); + + ok(SOSAccountAssertUserCredentials(bob_account, cfaccount2, cfpassword2, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + + ok(SOSAccountAssertUserCredentials(carol_account, cfaccount2, cfpassword2, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 1, "updates"); + + is(SOSAccountIsInCircles(bob_account, &error), kSOSCCCircleAbsent, "Account reset - circle is absent"); + is(SOSAccountIsInCircles(carol_account, &error), kSOSCCCircleAbsent, "Account reset - circle is absent"); + // Now everyone is playing the same account. + + /* ==================== Three Accounts setup =============================================*/ + + ok(SOSAccountResetToOffering(alice_account, &error), "Reset to offering (%@)", error); + CFReleaseNull(error); + is(countActivePeers(alice_account), 2, "2 peers - alice and icloud"); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 2, "updates"); + + is(SOSAccountIsInCircles(alice_account, &error), kSOSCCInCircle, "Alice is in circle"); + is(SOSAccountIsInCircles(bob_account, &error), kSOSCCNotInCircle, "Bob is not in circle"); + is(SOSAccountIsInCircles(carol_account, &error), kSOSCCNotInCircle, "Carol is not in circle"); + + ok(SOSAccountJoinCircles(bob_account, &error), "Bob Applies (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 2, "updates"); + + ok(SOSAccountJoinCircles(carol_account, &error), "Carol Applies (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 2, "updates"); + + is(SOSAccountIsInCircles(carol_account, &error), kSOSCCRequestPending, "Carol has a pending request"); + + { + CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); + + ok(applicants && CFArrayGetCount(applicants) == 2, "See two applicants %@ (%@)", applicants, error); + ok(SOSAccountAcceptApplicants(alice_account, applicants, &error), "Alice accepts (%@)", error); + CFReleaseNull(error); + CFReleaseNull(applicants); + is(countActivePeers(alice_account), 4, "4 peers - alice, bob, carol, and icloud"); + } + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 4, "updates"); + + accounts_agree_internal("bob&alice pair", bob_account, alice_account, false); + accounts_agree_internal("bob&carol pair", bob_account, carol_account, false); + + CFReleaseSafe(cfpassword2); + + SOSUnregisterAllTransportMessages(); + SOSUnregisterAllTransportCircles(); + SOSUnregisterAllTransportKeyParameters(); + CFArrayRemoveAllValues(key_transports); + CFArrayRemoveAllValues(circle_transports); + CFArrayRemoveAllValues(message_transports); + +} + + +int secd_52_account_changed(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/Security/sec/securityd/Regressions/secd-55-account-circle.c b/Security/sec/securityd/Regressions/secd-55-account-circle.c new file mode 100644 index 00000000..39b31e84 --- /dev/null +++ b/Security/sec/securityd/Regressions/secd-55-account-circle.c @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + + + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "secd_regressions.h" +#include "SOSTestDataSource.h" + +#include "SOSRegressionUtilities.h" +#include +#include + +#include + +#include "SOSAccountTesting.h" + +static int kTestTestCount = 304; + +static void tests(void) +{ + CFErrorRef error = NULL; + CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); + CFDataRef cfwrong_password = CFDataCreate(NULL, (uint8_t *) "NotFooFooFoo", 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 carol_account = CreateAccountForLocalChanges(CFSTR("Carol"), CFSTR("TestSource")); + + ok(SOSAccountAssertUserCredentials(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, carol_account, NULL), 1, "updates"); + + ok(SOSAccountAssertUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + ok(SOSAccountTryUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential trying (%@)", error); + CFReleaseNull(error); + ok(!SOSAccountTryUserCredentials(alice_account, cfaccount, cfwrong_password, &error), "Credential failing (%@)", error); + CFReleaseNull(cfwrong_password); + is(error ? CFErrorGetCode(error) : 0, kSOSErrorWrongPassword, "Expected SOSErrorWrongPassword"); + CFReleaseNull(error); + + ok(SOSAccountResetToOffering(alice_account, &error), "Reset to offering (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 2, "updates"); + + ok(SOSAccountJoinCircles(bob_account, &error), "Bob Applies (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_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, carol_account, NULL), 3, "updates"); + + accounts_agree("bob&alice pair", bob_account, alice_account); + + CFArrayRef peers = SOSAccountCopyPeers(alice_account, &error); + ok(peers && CFArrayGetCount(peers) == 2, "See two peers %@ (%@)", peers, error); + CFReleaseNull(peers); + + CFDictionaryRef alice_new_gestalt = SOSCreatePeerGestaltFromName(CFSTR("Alice, but different")); + + ok(SOSAccountUpdateGestalt(alice_account, alice_new_gestalt), "Update gestalt %@ (%@)", alice_account, error); + SOSAccountUpdateTestTransports(alice_account, alice_new_gestalt); + CFReleaseNull(alice_new_gestalt); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 2, "updates"); + + accounts_agree("Alice's name changed", bob_account, alice_account); + + ok(SOSAccountLeaveCircles(alice_account, &error), "Alice Leaves (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 3, "updates"); + + accounts_agree("Alice bails", bob_account, alice_account); + + peers = SOSAccountCopyPeers(alice_account, &error); + ok(peers && CFArrayGetCount(peers) == 1, "See one peer %@ (%@)", peers, error); + CFReleaseNull(peers); + + ok(SOSAccountJoinCircles(alice_account, &error), "Alice re-applies (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 2, "updates"); + + + { + CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); + + ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); + ok(SOSAccountAcceptApplicants(bob_account, applicants, &error), "Bob accepts (%@)", error); + CFReleaseNull(error); + CFReleaseNull(applicants); + } + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 3, "updates"); + + accounts_agree("Alice accepts' Bob", bob_account, alice_account); + + ok(SOSAccountLeaveCircles(alice_account, &error), "Alice Leaves (%@)", error); + CFReleaseNull(error); + ok(SOSAccountJoinCircles(alice_account, &error), "Alice re-applies (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 4, "updates"); + + { + CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); + + ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); + ok(SOSAccountAcceptApplicants(bob_account, applicants, &error), "Bob accepts (%@)", error); + CFReleaseNull(error); + CFReleaseNull(applicants); + } + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 3, "updates"); + + accounts_agree("Bob accepts Alice", bob_account, alice_account); + + // As of PR-13917727/PR-13906870 this no longer works (by "design"), in favor of making another more common + // failure (apply/OSX-psudo-reject/re-apply) work. Write races might be "fixed better" with affirmitave rejection. +#if 0 + + // + // Write race emulation. + // + // + + ok(SOSAccountLeaveCircles(alice_account, &error), "Alice Leaves (%@)", error); + CFReleaseNull(error); + FeedChangesTo(changes, bob_account); // Bob sees Alice leaving and rejoining + FeedChangesTo(changes, alice_account); // Alice sees bob concurring + + accounts_agree("Alice leaves & returns", bob_account, alice_account); + + ok(SOSAccountJoinCircles(alice_account, &error), "Alice re-applies (%@)", error); + CFReleaseNull(error); + + FeedChangesTo(changes, bob_account); // Bob sees Alice Applying + + { + CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); + + ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); + ok(SOSAccountAcceptApplicants(bob_account, applicants, &error), "Bob accepts (%@)", error); + CFReleaseNull(error); + CFReleaseNull(applicants); + } + + CFMutableDictionaryRef bobAcceptanceChanges = ExtractPendingChanges(changes); + + // Alice re-applies without seeing that she was accepted. + ok(SOSAccountLeaveCircles(alice_account, &error), "Alice Leaves again (%@)", error); + CFReleaseNull(error); + ok(SOSAccountJoinCircles(alice_account, &error), "Alice re-applies (%@)", error); + CFReleaseNull(error); + + CFReleaseSafe(ExtractPendingChanges(changes)); // Alice loses the race to write her changes - bob never sees em. + + FeedChangesTo(&bobAcceptanceChanges, alice_account); // Alice sees bob inviting her in the circle. + + FeedChangesTo(changes, bob_account); // Bob sees Alice Concurring + + // As of PR-13917727/PR-13906870 + accounts_agree("Alice leave, applies back, loses a race and eventually gets in", bob_account, alice_account); +#endif + + // Both in circle. + + // Emulation of Innsbruck11A368 +Roots: Device A was removed when Device B joined. + + // We want Alice to leave circle while an Applicant on a full concordance signed circle with old-Alice as an Alum and Bob a peer. + // ZZZ + ok(SOSAccountLeaveCircles(alice_account, &error), "Alice leaves once more (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 3, "updates"); + accounts_agree("Alice and Bob see Alice out of circle", bob_account, alice_account); + + ok(SOSAccountJoinCircles(alice_account, &error), "Alice re-applies (%@)", error); + CFReleaseNull(error); + + ok(SOSAccountLeaveCircles(alice_account, &error), "Alice leaves while applying (%@)", error); + FeedChangesTo(changes, bob_account); // Bob sees Alice become an Alum. + + CFReleaseNull(error); + + is(SOSAccountIsInCircles(alice_account, &error), kSOSCCNotInCircle, "Alice isn't applying any more"); + accounts_agree("Alice leaves & some fancy concordance stuff happens", bob_account, alice_account); + + ok(SOSAccountJoinCircles(alice_account, &error), "Alice re-applies (%@)", error); + CFReleaseNull(error); + + FeedChangesTo(changes, bob_account); // Bob sees Alice reapply. + + { + CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); + + ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); + ok(SOSAccountAcceptApplicants(bob_account, applicants, &error), "Bob accepts (%@)", error); + CFReleaseNull(error); + CFReleaseNull(applicants); + } + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 2, "updates"); + + accounts_agree("Alice comes back", bob_account, alice_account); + + // Emulation of + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 1, "updates"); + + ok(SOSAccountAssertUserCredentials(carol_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(cfpassword); + ok(SOSAccountJoinCircles(carol_account, &error), "Carol Applies (%@)", error); + CFReleaseNull(error); + + CFMutableDictionaryRef dropped_changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + FillChanges(dropped_changes, carol_account); + CFReleaseNull(dropped_changes); + + ok(SOSAccountResetToOffering(carol_account, &error), "Reset to offering (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, bob_account, carol_account, NULL), 2, "updates"); + accounts_agree("13889901", carol_account, bob_account); + is(SOSAccountGetLastDepartureReason(bob_account, &error), kSOSMembershipRevoked, "Bob affirms he hasn't left."); + + ok(SOSAccountJoinCircles(bob_account, &error), "Bob ReApplies (%@)", error); + is(ProcessChangesUntilNoChange(changes, bob_account, carol_account, NULL), 2, "updates"); + { + CFArrayRef applicants = SOSAccountCopyApplicants(carol_account, &error); + + ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); + ok(SOSAccountAcceptApplicants(carol_account, applicants, &error), "Carol accepts (%@)", error); + CFReleaseNull(error); + CFReleaseNull(applicants); + } + is(ProcessChangesUntilNoChange(changes, bob_account, carol_account, NULL), 3, "updates"); + accounts_agree("rdar://problem/13889901-II", bob_account, carol_account); + + CFReleaseNull(alice_new_gestalt); + + CFReleaseNull(bob_account); + CFReleaseNull(alice_account); + CFReleaseNull(carol_account); + + SOSUnregisterAllTransportMessages(); + SOSUnregisterAllTransportCircles(); + SOSUnregisterAllTransportKeyParameters(); + CFArrayRemoveAllValues(key_transports); + CFArrayRemoveAllValues(circle_transports); + CFArrayRemoveAllValues(message_transports); + +} + +int secd_55_account_circle(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/Security/sec/securityd/Regressions/secd-55-account-incompatibility.c b/Security/sec/securityd/Regressions/secd-55-account-incompatibility.c new file mode 100644 index 00000000..b49625c6 --- /dev/null +++ b/Security/sec/securityd/Regressions/secd-55-account-incompatibility.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + + + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "secd_regressions.h" +#include "SOSTestDataSource.h" + +#include "SOSRegressionUtilities.h" +#include +#include + +#include + +#include "SOSAccountTesting.h" + + +static int kTestTestCount = 10; + +static void tests(void) +{ + CFErrorRef error = NULL; + CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); + CFDataRef cfwrong_password = CFDataCreate(NULL, (uint8_t *) "NotFooFooFoo", 10); + CFStringRef cfaccount = CFSTR("test@test.org"); + CFStringRef data_name = CFSTR("TestSource"); + CFStringRef circle_key_name = SOSCircleKeyCreateWithName(data_name, NULL); + + CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + + SOSAccountRef alice_account = CreateAccountForLocalChanges(CFSTR("Alice"), data_name); + SOSAccountRef bob_account = CreateAccountForLocalChanges(CFSTR("Bob"), data_name); + SOSAccountRef carol_account = CreateAccountForLocalChanges(CFSTR("Carol"), data_name); + + ok(SOSAccountAssertUserCredentials(bob_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + + // Bob wins writing at this point, feed the changes back to alice. + FillAllChanges(changes); + FeedChangesToMulti(changes, alice_account, carol_account, NULL); + + ok(SOSAccountAssertUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + ok(SOSAccountTryUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential trying (%@)", error); + CFReleaseNull(error); + CFReleaseNull(cfpassword); + + ok(!SOSAccountTryUserCredentials(alice_account, cfaccount, cfwrong_password, &error), "Credential failing (%@)", error); + CFReleaseNull(cfwrong_password); + is(error ? CFErrorGetCode(error) : 0, kSOSErrorWrongPassword, "Expected SOSErrorWrongPassword"); + CFReleaseNull(error); + + CFDataRef incompatibleDER = SOSCircleCreateIncompatibleCircleDER(&error); + + InjectChangeToMulti(changes, circle_key_name, incompatibleDER, alice_account, NULL); + CFReleaseNull(circle_key_name); + CFReleaseNull(incompatibleDER); + + is(ProcessChangesUntilNoChange(changes, alice_account, NULL), 1, "updates"); + +#if 0 + is(SOSAccountIsInCircles(alice_account, &error), kSOSCCError, "Is in circle"); + CFReleaseNull(error); + +//#if 0 + ok(SOSAccountResetToOffering(alice_account, &error), "Reset to offering (%@)", error); + CFReleaseNull(error); + FillChanges(changes, CFSTR("Alice")); + FeedChangesTo(changes, bob_account, transport_bob); + + ok(SOSAccountJoinCircles(bob_account, &error), "Bob Applies (%@)", error); + CFReleaseNull(error); + + FeedChangesTo(changes, alice_account, transport_alice); + + { + 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); + } + + FillChanges(changes, CFSTR("Alice")); + FeedChangesTo(changes, bob_account, transport_bob); // Bob sees he's accepted + + FillChanges(changes, CFSTR("Bob")); + FeedChangesTo(changes, alice_account, transport_alice); // Alice sees bob-concurring + + ok(CFDictionaryGetCount(changes) == 0, "We converged. (%@)", changes); + + FillChanges(changes, CFSTR("Alice")); + accounts_agree("bob&alice pair", bob_account, alice_account); + + CFArrayRef peers = SOSAccountCopyPeers(alice_account, &error); + ok(peers && CFArrayGetCount(peers) == 2, "See two peers %@ (%@)", peers, error); + CFReleaseNull(peers); + + CFDictionaryRef alice_new_gestalt = SOSCreatePeerGestaltFromName(CFSTR("Alice, but different")); + + ok(SOSAccountUpdateGestalt(alice_account, alice_new_gestalt), "Update gestalt %@ (%@)", alice_account, error); + CFReleaseNull(alice_new_gestalt); + + FillChanges(changes, CFSTR("Alice")); + FeedChangesTo(changes, bob_account, transport_bob); // Bob sees alice change her name. + + FillChanges(changes, CFSTR("Bob")); + FeedChangesTo(changes, alice_account, transport_alice); // Alice sees the fallout. + + accounts_agree("Alice's name changed", bob_account, alice_account); + + ok(SOSAccountLeaveCircles(alice_account, &error), "Alice Leaves (%@)", error); + CFReleaseNull(error); + + FillChanges(changes, CFSTR("Alice")); + FeedChangesTo(changes, bob_account, transport_bob); // Bob sees alice bail. + + FillChanges(changes, CFSTR("Bob")); + FeedChangesTo(changes, alice_account), transport_alice; // Alice sees the fallout. + + FillChanges(changes, CFSTR("Alice")); + FillChanges(changes, CFSTR("Bob")); + accounts_agree("Alice bails", bob_account, alice_account); + + peers = SOSAccountCopyPeers(alice_account, &error); + ok(peers && CFArrayGetCount(peers) == 1, "See one peer %@ (%@)", peers, error); + CFReleaseNull(peers); + + ok(SOSAccountJoinCircles(alice_account, &error), "Alice re-applies (%@)", error); + CFReleaseNull(error); + + FillChanges(changes, CFSTR("Alice")); + FeedChangesTo(changes, bob_account, transport_bob); + + + { + CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); + + ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); + ok(SOSAccountAcceptApplicants(bob_account, applicants, &error), "Bob accepts (%@)", error); + CFReleaseNull(error); + CFReleaseNull(applicants); + } + + FillChanges(changes, CFSTR("Bob")); + FeedChangesTo(changes, alice_account, transport_alice); // Alice sees bob accepting + + FillChanges(changes, CFSTR("Alice")); + FeedChangesTo(changes, bob_account, transport_bob); // Bob sees Alice concurring + + accounts_agree("Alice accepts' Bob", bob_account, alice_account); + + ok(SOSAccountLeaveCircles(alice_account, &error), "Alice Leaves (%@)", error); + CFReleaseNull(error); + ok(SOSAccountJoinCircles(alice_account, &error), "Alice re-applies (%@)", error); + CFReleaseNull(error); + + FillChanges(changes, CFSTR("Alice")); + FeedChangesTo(changes, bob_account, transport_bob); // Bob sees Alice leaving and rejoining + FillChanges(changes, CFSTR("Bob")); + FeedChangesTo(changes, alice_account, transport_alice); // Alice sees bob concurring + + { + CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); + + ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); + ok(SOSAccountAcceptApplicants(bob_account, applicants, &error), "Bob accepts (%@)", error); + CFReleaseNull(error); + CFReleaseNull(applicants); + } + FillChanges(changes, CFSTR("Bob")); + FeedChangesTo(changes, alice_account, transport_alice); // Alice sees bob accepting + FillChanges(changes, CFSTR("Alice")); + FeedChangesTo(changes, bob_account, transport_bob); // Bob sees Alice concurring + + accounts_agree("Bob accepts Alice", bob_account, alice_account); + + + CFReleaseNull(alice_new_gestalt); +#endif + + CFReleaseNull(bob_account); + CFReleaseNull(alice_account); + CFReleaseNull(carol_account); + + SOSUnregisterAllTransportMessages(); + SOSUnregisterAllTransportCircles(); + SOSUnregisterAllTransportKeyParameters(); + CFArrayRemoveAllValues(key_transports); + CFArrayRemoveAllValues(circle_transports); + CFArrayRemoveAllValues(message_transports); + + +} + +int secd_55_account_incompatibility(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/Security/sec/securityd/Regressions/secd-56-account-apply.c b/Security/sec/securityd/Regressions/secd-56-account-apply.c new file mode 100644 index 00000000..bf8ffea2 --- /dev/null +++ b/Security/sec/securityd/Regressions/secd-56-account-apply.c @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + + + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "secd_regressions.h" +#include "SOSTestDataSource.h" + +#include "SOSRegressionUtilities.h" +#include +#include + +#include + +#include "SOSAccountTesting.h" + + +static int kTestTestCount = 125; + +#if 0 +static int countPeers(SOSAccountRef account, bool active) { + CFErrorRef error = NULL; + CFArrayRef peers; + + if(active) peers = SOSAccountCopyActivePeers(account, &error); + else peers = SOSAccountCopyPeers(account, &error); + int retval = (int) CFArrayGetCount(peers); + CFReleaseNull(error); + CFReleaseNull(peers); + return retval; +} +#endif + +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")); + SOSAccountRef david_account = CreateAccountForLocalChanges(CFSTR("David"), CFSTR("TestSource")); + + ok(SOSAccountAssertUserCredentials(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, david_account, NULL), 1, "updates"); + + ok(SOSAccountAssertUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + + ok(SOSAccountAssertUserCredentials(carole_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + + ok(SOSAccountAssertUserCredentials(david_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(cfpassword); + CFReleaseNull(error); + + ok(SOSAccountResetToOffering(alice_account, &error), "Reset to offering (%@)", error); + CFReleaseNull(error); + + // Lost Application Scenario + is(ProcessChangesOnce(changes, alice_account, bob_account, carole_account, david_account, NULL), 1, "updates"); + + ok(SOSAccountJoinCircles(bob_account, &error), "Bob Applies (%@)", error); + CFReleaseNull(error); + + ok(SOSAccountJoinCircles(carole_account, &error), "Carole Applies too (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, david_account, NULL), 3, "updates"); + + accounts_agree("alice and carole agree", alice_account, carole_account); + accounts_agree("alice and bob agree", alice_account, bob_account); + + { + CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); + + ok(applicants && CFArrayGetCount(applicants) == 2, "See two applicants %@ (%@)", applicants, error); + CFReleaseNull(error); + CFReleaseSafe(applicants); + } + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, david_account, NULL), 1, "updates"); + + accounts_agree("alice and carole agree", alice_account, carole_account); + + CFReleaseNull(error); + + { + CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); + ok(applicants && CFArrayGetCount(applicants) == 2, "See two applicants %@ (%@)", applicants, error); + ok(SOSAccountRejectApplicants(alice_account, applicants, &error), "Everyone out the pool"); + CFReleaseNull(error); + CFReleaseSafe(applicants); + } + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, david_account, NULL), 2, "updates"); + + accounts_agree("alice and carole agree", alice_account, carole_account); + + { + CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); + ok(applicants && CFArrayGetCount(applicants) == 0, "See no applicants %@ (%@)", applicants, error); + CFReleaseNull(error); + CFReleaseSafe(applicants); + } + + ok(SOSAccountJoinCircles(bob_account, &error), "Bob asks again"); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, david_account, NULL), 2, "updates"); + + { + CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); + ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicants %@ (%@)", applicants, error); + CFReleaseNull(error); + ok(SOSAccountAcceptApplicants(alice_account, applicants, &error), "Accept bob into the fold"); + CFReleaseNull(error); + CFReleaseSafe(applicants); + } + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, david_account, NULL), 3, "updates"); + +#if 0 + + { + CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); + + ok(applicants && CFArrayGetCount(applicants) == 1, "Bob automatically re-applied %@ (%@)", applicants, error); + ok(SOSAccountAcceptApplicants(alice_account, applicants, &error), "Alice accepts (%@)", error); + CFReleaseNull(error); + CFReleaseNull(applicants); + } + + is(countPeers(alice_account, 0), 3, "Bob is accepted after auto-reapply"); + + FillAllChanges(changes); + FeedChangesToMulti(AliceChanges, bob_account, carole_account, david_account, NULL); + FeedChangesToMulti(BobChanges, alice_account, carole_account, david_account, NULL); + FeedChangesToMulti(CarolChanges, bob_account, alice_account, david_account, NULL); + FeedChangesToMulti(DavidChanges, bob_account, alice_account, carole_account, NULL); + + FillAllChanges(changes); + FeedChangesToMulti(AliceChanges, bob_account, carole_account, david_account, NULL); + FeedChangesToMulti(BobChanges, alice_account, carole_account, david_account, NULL); + FeedChangesToMulti(CarolChanges, bob_account, alice_account, david_account, NULL); + FeedChangesToMulti(DavidChanges, bob_account, alice_account, carole_account, NULL); + + FillAllChanges(changes); + FeedChangesToMulti(AliceChanges, bob_account, carole_account, david_account, NULL); + FeedChangesToMulti(BobChanges, alice_account, carole_account, david_account, NULL); + FeedChangesToMulti(CarolChanges, bob_account, alice_account, david_account, NULL); + FeedChangesToMulti(DavidChanges, bob_account, alice_account, carole_account, NULL); + accounts_agree("alice and carole agree after bob gets in", alice_account, carole_account); + + // Rejected Application Scenario + ok(SOSAccountJoinCircles(david_account, &error), "Dave Applies (%@)", error); + CFReleaseNull(error); + + FillAllChanges(changes); + FeedChangesToMulti(AliceChanges, bob_account, carole_account, david_account, NULL); + FeedChangesToMulti(BobChanges, alice_account, carole_account, david_account, NULL); + FeedChangesToMulti(CarolChanges, bob_account, alice_account, david_account, NULL); + FeedChangesToMulti(DavidChanges, bob_account, alice_account, carole_account, NULL); + + SOSAccountPurgePrivateCredential(alice_account); + + { + CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); + + ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); + ok(SOSAccountRejectApplicants(alice_account, applicants, &error), "Alice rejects (%@)", error); + CFReleaseNull(error); + CFReleaseNull(applicants); + } + + FillAllChanges(changes); + FeedChangesToMulti(AliceChanges, bob_account, carole_account, david_account, NULL); + FeedChangesToMulti(BobChanges, alice_account, carole_account, david_account, NULL); + FeedChangesToMulti(CarolChanges, bob_account, alice_account, david_account, NULL); + FeedChangesToMulti(DavidChanges, bob_account, alice_account, carole_account, NULL); + + FillAllChanges(changes); + FeedChangesToMulti(AliceChanges, bob_account, carole_account, david_account, NULL); + FeedChangesToMulti(BobChanges, alice_account, carole_account, david_account, NULL); + FeedChangesToMulti(CarolChanges, bob_account, alice_account, david_account, NULL); + FeedChangesToMulti(DavidChanges, bob_account, alice_account, carole_account, NULL); + + FillAllChanges(changes); + FeedChangesToMulti(AliceChanges, bob_account, carole_account, david_account, NULL); + FeedChangesToMulti(BobChanges, alice_account, carole_account, david_account, NULL); + FeedChangesToMulti(CarolChanges, bob_account, alice_account, david_account, NULL); + FeedChangesToMulti(DavidChanges, bob_account, alice_account, carole_account, NULL); + + accounts_agree("alice and carole still agree after david is rejected", alice_account, carole_account); + ok(SOSAccountTryUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + + FillAllChanges(changes); + FeedChangesToMulti(AliceChanges, bob_account, carole_account, david_account, NULL); + FeedChangesToMulti(BobChanges, alice_account, carole_account, david_account, NULL); + FeedChangesToMulti(CarolChanges, bob_account, alice_account, david_account, NULL); + FeedChangesToMulti(DavidChanges, bob_account, alice_account, carole_account, NULL); + + FillAllChanges(changes); + + ok(CFDictionaryGetCount(CarolChanges) == 0, "We converged. (%@)", CarolChanges); + ok(CFDictionaryGetCount(BobChanges) == 0, "We converged. (%@)", BobChanges); + ok(CFDictionaryGetCount(AliceChanges) == 0, "We converged. (%@)", AliceChanges); + ok(CFDictionaryGetCount(DavidChanges) == 0, "We converged. (%@)", DavidChanges); + + accounts_agree("bob&alice pair", bob_account, alice_account); + + ok(SOSAccountJoinCirclesAfterRestore(carole_account, &error), "Carole cloud identiy joins (%@)", error); + CFReleaseNull(error); + + is(countPeers(carole_account, false), 3, "Carole sees 3 valid peers after sliding in"); + + FillAllChanges(changes); + FeedChangesToMulti(AliceChanges, bob_account, carole_account, david_account, NULL); + FeedChangesToMulti(BobChanges, alice_account, carole_account, david_account, NULL); + FeedChangesToMulti(CarolChanges, bob_account, alice_account, david_account, NULL); + FeedChangesToMulti(DavidChanges, bob_account, alice_account, carole_account, NULL); + + FillAllChanges(changes); + FeedChangesToMulti(AliceChanges, bob_account, carole_account, david_account, NULL); + FeedChangesToMulti(BobChanges, alice_account, carole_account, david_account, NULL); + FeedChangesToMulti(CarolChanges, bob_account, alice_account, david_account, NULL); + FeedChangesToMulti(DavidChanges, bob_account, alice_account, carole_account, NULL); + + FillAllChanges(changes); + FeedChangesToMulti(AliceChanges, bob_account, carole_account, david_account, NULL); + FeedChangesToMulti(BobChanges, alice_account, carole_account, david_account, NULL); + FeedChangesToMulti(CarolChanges, bob_account, alice_account, david_account, NULL); + FeedChangesToMulti(DavidChanges, bob_account, alice_account, carole_account, NULL); // Bob and carole see the final result. + + accounts_agree_internal("Carole's in", bob_account, alice_account, false); + accounts_agree_internal("Carole's in - 2", bob_account, carole_account, false); +#endif + CFReleaseNull(bob_account); + CFReleaseNull(alice_account); + CFReleaseNull(carole_account); + + SOSUnregisterAllTransportMessages(); + SOSUnregisterAllTransportCircles(); + SOSUnregisterAllTransportKeyParameters(); + CFArrayRemoveAllValues(key_transports); + CFArrayRemoveAllValues(circle_transports); + CFArrayRemoveAllValues(message_transports); + +} + +int secd_56_account_apply(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/Security/sec/securityd/Regressions/secd-57-account-leave.c b/Security/sec/securityd/Regressions/secd-57-account-leave.c new file mode 100644 index 00000000..2c196d72 --- /dev/null +++ b/Security/sec/securityd/Regressions/secd-57-account-leave.c @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + + + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "secd_regressions.h" +#include "SOSTestDataSource.h" + +#include "SOSRegressionUtilities.h" +#include +#include + +#include + +#include "SOSAccountTesting.h" + + +static int kTestTestCount = 264; + +/* + static void trim_retirements_from_circle(SOSAccountRef account) { + SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { + SOSCircleRemoveRetired(circle, NULL); + }); + } + */ + + +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")); + SOSAccountRef david_account = CreateAccountForLocalChanges(CFSTR("David"), CFSTR("TestSource")); + + ok(SOSAccountAssertUserCredentials(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, david_account, NULL), 1, "updates"); + + ok(SOSAccountAssertUserCredentials(alice_account , cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + + ok(SOSAccountAssertUserCredentials(carole_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + + ok(SOSAccountAssertUserCredentials(david_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, david_account, NULL), 2, "updates"); + + ok(SOSAccountJoinCircles(bob_account , &error), "Bob Applies (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, david_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, david_account, NULL), 3, "updates"); + + accounts_agree("bob&alice pair", bob_account, alice_account); + is(SOSAccountGetLastDepartureReason(bob_account, &error), kSOSNeverLeftCircle, "Bob affirms he hasn't left."); + + CFArrayRef peers = SOSAccountCopyPeers(alice_account, &error); + ok(peers && CFArrayGetCount(peers) == 2, "See two peers %@ (%@)", peers, error); + CFReleaseNull(peers); + + SOSAccountPurgePrivateCredential(alice_account); + + ok(SOSAccountLeaveCircles(alice_account , &error), "Alice Leaves (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, david_account, NULL), 3, "updates"); + + accounts_agree("Alice bails", bob_account, alice_account); + + { + CFArrayRef concurring = SOSAccountCopyConcurringPeers(alice_account, &error); + + ok(concurring && CFArrayGetCount(concurring) == 2, "See two concurring %@ (%@)", concurring, error); + CFReleaseNull(error); + CFReleaseNull(concurring); + } + + ok(SOSAccountTryUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + + ok(SOSAccountJoinCircles(alice_account , &error), "Alice re-applies (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, david_account, NULL), 2, "updates"); + + is(countActivePeers(bob_account), 3, "Bob sees 2 active peers"); + is(countPeers(bob_account), 1, "Bob sees 1 valid peer"); + + { + CFArrayRef applicants = SOSAccountCopyApplicants(bob_account, &error); + + ok(applicants && CFArrayGetCount(applicants) == 1, "See alice's reapp. %@ (%@)", applicants, error); + ok(SOSAccountAcceptApplicants(bob_account , applicants, &error), "Bob accepts (%@)", error); + CFReleaseNull(error); + CFReleaseNull(applicants); + } + + + is(countActivePeers(bob_account), 3, "Bob sees 3 active peers"); + is(countPeers(bob_account), 2, "Bob sees 2 valid peers"); + + is(countActivePeers(alice_account), 3, "Alice sees 2 active peers"); + is(countPeers(alice_account), 1, "Alice sees 1 valid peers"); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, david_account, NULL), 3, "updates"); + + accounts_agree("Alice rejoined", bob_account, alice_account); + accounts_agree_internal("Alice rejoined, carole noticed", bob_account, carole_account, false); + + ok(SOSAccountJoinCircles(carole_account , &error), "Carole applies (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, david_account, NULL), 2, "updates"); + + accounts_agree_internal("Carole applied", bob_account, alice_account, false); + accounts_agree_internal("Carole applied - 2", bob_account, carole_account, false); + + { + CFArrayRef applicants = SOSAccountCopyApplicants(bob_account, &error); + + ok(applicants && CFArrayGetCount(applicants) == 1, "See Carole's eapp. %@ (%@)", applicants, error); + ok(SOSAccountAcceptApplicants(bob_account , applicants, &error), "Bob accepts carole (%@)", error); + CFReleaseNull(error); + CFReleaseNull(applicants); + } + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, david_account, NULL), 4, "updates"); + // david ends up with a 3 peerinfo member circle. + + accounts_agree_internal("Carole joined", bob_account, alice_account, false); + accounts_agree_internal("Carole joined - 2", bob_account, carole_account, false); + + // Now test lost circle change when two leave simultaneously, needing us to see the retirement tickets + + ok(SOSAccountLeaveCircles(alice_account , &error), "Alice Leaves (%@)", error); + CFReleaseNull(error); + + ok(SOSAccountLeaveCircles(carole_account , &error), "carole Leaves (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, david_account, NULL), 3, "updates"); + + is(countPeers(bob_account), 1, "Bob sees 1 valid peer"); + is(countActivePeers(bob_account), 4, "Bob sees 4 active peers"); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, david_account, NULL), 1, "updates"); + + is(SOSAccountGetLastDepartureReason(carole_account, &error), kSOSWithdrewMembership, "Carole affirms she left on her own."); + + ok(SOSAccountAssertUserCredentials(david_account , cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + CFReleaseNull(cfpassword); + is(countPeers(david_account), 1, "david sees 1 peers"); + is(countActivePeers(david_account), 4, "david sees 4 active peers"); + + ok(SOSAccountJoinCircles(david_account , &error), "David applies (%@)", error); + CFReleaseNull(error); + is(countPeers(david_account), 1, "david sees 1 peers"); + is(countActivePeers(david_account), 4, "david sees 4 active peers"); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, david_account, NULL), 2, "updates"); + + { + CFArrayRef applicants = SOSAccountCopyApplicants(bob_account, &error); + + ok(applicants && CFArrayGetCount(applicants) == 1, "See David's app. %@ (%@)", applicants, error); + ok(SOSAccountAcceptApplicants(bob_account , applicants, &error), "Bob accepts carole (%@)", error); + CFReleaseNull(error); + CFReleaseNull(applicants); + } + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, david_account, NULL), 3, "updates"); + + is(countPeers(bob_account), 2, "Bob sees 2 valid peer"); + is(countActivePeers(bob_account), 3, "Bob sees 3 active peers"); + + CFReleaseNull(bob_account); + CFReleaseNull(alice_account); + + SOSUnregisterAllTransportMessages(); + SOSUnregisterAllTransportCircles(); + SOSUnregisterAllTransportKeyParameters(); + CFArrayRemoveAllValues(key_transports); + CFArrayRemoveAllValues(circle_transports); + CFArrayRemoveAllValues(message_transports); +} + +int secd_57_account_leave(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/Security/sec/securityd/Regressions/secd-58-password-change.c b/Security/sec/securityd/Regressions/secd-58-password-change.c new file mode 100644 index 00000000..e95a839d --- /dev/null +++ b/Security/sec/securityd/Regressions/secd-58-password-change.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + + + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "secd_regressions.h" +#include "SOSTestDataSource.h" + +#include "SOSRegressionUtilities.h" +#include +#include + +#include + +#include "SOSAccountTesting.h" + +static int kTestTestCount = 244; + +static bool AssertCreds(SOSAccountRef account,CFStringRef acct_name, CFDataRef password) { + CFErrorRef error = NULL; + bool retval; + ok((retval = SOSAccountAssertUserCredentials(account, acct_name, password, &error)), "Credential setting (%@)", error); + CFReleaseNull(error); + return retval; +} + +static bool ResetToOffering(SOSAccountRef account) { + CFErrorRef error = NULL; + bool retval; + ok((retval = SOSAccountResetToOffering(account, &error)), "Reset to offering (%@)", error); + CFReleaseNull(error); + return retval; +} + +static bool JoinCircle(SOSAccountRef account) { + CFErrorRef error = NULL; + bool retval; + ok((retval = SOSAccountJoinCircles(account, &error)), "Join Circle (%@)", error); + CFReleaseNull(error); + return retval; +} + +static bool AcceptApplicants(SOSAccountRef account, CFIndex cnt) { + CFErrorRef error = NULL; + bool retval = false; + CFArrayRef applicants = SOSAccountCopyApplicants(account, &error); + + ok((retval = (applicants && CFArrayGetCount(applicants) == cnt)), "See applicants %@ (%@)", applicants, error); + if(retval) ok((retval = SOSAccountAcceptApplicants(account, applicants, &error)), "Accept Applicants (%@)", error); + CFReleaseNull(applicants); + CFReleaseNull(error); + return retval; +} + +static void tests(void) +{ + 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 carol_account = CreateAccountForLocalChanges(CFSTR("Carol"), CFSTR("TestSource")); + + /* Set Initial Credentials and Parameters for the Syncing Circles ---------------------------------------*/ + ok(AssertCreds(bob_account, cfaccount, cfpassword), "Setting credentials for Bob"); + // Bob wins writing at this point, feed the changes back to alice. + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 1, "updates"); + + ok(AssertCreds(alice_account, cfaccount, cfpassword), "Setting credentials for Alice"); + ok(AssertCreds(carol_account, cfaccount, cfpassword), "Setting credentials for Carol"); + CFReleaseNull(cfpassword); + + /* Make Alice First Peer -------------------------------------------------------------------------------*/ + ok(ResetToOffering(alice_account), "Reset to offering - Alice as first peer"); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 2, "updates"); + + /* Bob Joins -------------------------------------------------------------------------------------------*/ + ok(JoinCircle(bob_account), "Bob Applies"); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 2, "updates"); + + /* Alice Accepts -------------------------------------------------------------------------------------------*/ + ok(AcceptApplicants(alice_account, 1), "Alice Accepts Bob's Application"); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 3, "4 updates"); + accounts_agree("bob&alice pair", bob_account, alice_account); + + /* Carol Applies -------------------------------------------------------------------------------------------*/ + ok(JoinCircle(carol_account), "Carol Applies"); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 2, "updates"); + is(countPeers(alice_account), 2, "See two peers"); + + + /* Change Password ------------------------------------------------------------------------------------------*/ + CFDataRef cfnewpassword = CFDataCreate(NULL, (uint8_t *) "ooFooFooF", 10); + + ok(AssertCreds(bob_account , cfaccount, cfnewpassword), "Credential resetting for Bob"); + is(countPeers(bob_account), 2, "There are two valid peers - iCloud and Bob"); + is(countActivePeers(bob_account), 3, "There are three active peers - bob, alice, and iCloud"); + is(countActiveValidPeers(bob_account), 2, "There is two active valid peer - Bob and iCloud"); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 2, "updates"); + + ok(AssertCreds(alice_account , cfaccount, cfnewpassword), "Credential resetting for Alice"); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 3, "updates"); + + is(countPeers(alice_account), 2, "There are two peers - bob and alice"); + is(countActiveValidPeers(alice_account), 3, "There are three active valid peers - alice, bob, and icloud"); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 1, "updates"); + + accounts_agree("bob&alice pair", bob_account, alice_account); + is(countPeers(alice_account), 2, "There are two peers - bob and alice"); + is(countActiveValidPeers(alice_account), 3, "There are three active valid peers - alice, bob, and icloud"); + + ok(AssertCreds(carol_account , cfaccount, cfnewpassword), "Credential resetting for Carol"); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 1, "updates"); + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 2, "updates"); + + accounts_agree("bob&alice pair", bob_account, alice_account); + accounts_agree_internal("bob&carol pair", bob_account, carol_account, false); + + ok(AcceptApplicants(alice_account , 1), "Alice Accepts Carol's Application"); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 4, "updates"); + + accounts_agree_internal("bob&alice pair", bob_account, alice_account, false); + accounts_agree_internal("bob&carol pair", bob_account, carol_account, false); + accounts_agree_internal("carol&alice pair", alice_account, carol_account, false); + + + /* Change Password 2 ----------------------------------------------------------------------------------------*/ + CFReleaseNull(cfnewpassword); + cfnewpassword = CFDataCreate(NULL, (uint8_t *) "ffoffoffo", 10); + + /* Bob */ + ok(AssertCreds(bob_account , cfaccount, cfnewpassword), "Credential resetting for Bob"); + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 2, "updates"); + + is(countPeers(bob_account), 3, "There are three peers - Alice, Carol, Bob"); + is(countActivePeers(bob_account), 4, "There are four active peers - bob, alice, carol and iCloud"); + is(countActiveValidPeers(bob_account), 2, "There is two active valid peer - Bob and iCloud"); + + + /* Alice */ + ok(AssertCreds(alice_account , cfaccount, cfnewpassword), "Credential resetting for Alice"); + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 3, "updates"); + + is(countPeers(alice_account), 3, "There are three peers - Alice, Carol, Bob"); + is(countActivePeers(alice_account), 4, "There are four active peers - bob, alice, carol and iCloud"); + is(countActiveValidPeers(alice_account), 3, "There are three active valid peers - alice, bob, and icloud"); + + + /* Carol */ + ok(AssertCreds(carol_account , cfaccount, cfnewpassword), "Credential resetting for Carol"); + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 4, "updates"); + + is(countPeers(carol_account), 3, "There are three peers - Alice, Carol, Bob"); + is(countActivePeers(carol_account), 4, "There are four active peers - bob, alice, carol and iCloud"); + is(countActiveValidPeers(carol_account), 4, "There are three active valid peers - alice, bob, carol, and icloud"); + + + accounts_agree_internal("bob&alice pair", bob_account, alice_account, false); + + CFReleaseNull(bob_account); + CFReleaseNull(alice_account); + CFReleaseNull(carol_account); + CFReleaseNull(cfnewpassword); + + SOSUnregisterAllTransportMessages(); + SOSUnregisterAllTransportCircles(); + SOSUnregisterAllTransportKeyParameters(); + CFArrayRemoveAllValues(key_transports); + CFArrayRemoveAllValues(circle_transports); + CFArrayRemoveAllValues(message_transports); + +} + +int secd_58_password_change(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/Security/sec/securityd/Regressions/secd-59-account-cleanup.c b/Security/sec/securityd/Regressions/secd-59-account-cleanup.c new file mode 100644 index 00000000..43f2d394 --- /dev/null +++ b/Security/sec/securityd/Regressions/secd-59-account-cleanup.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + + + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "secd_regressions.h" +#include "SOSTestDataSource.h" + +#include "SOSRegressionUtilities.h" +#include +#include + +#include + +#include "SOSAccountTesting.h" + +static int kTestTestCount = 136; + +static void tests(void) +{ + CFErrorRef error = NULL; + CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); + CFStringRef cfaccount = CFSTR("test@test.org"); + CFStringRef circle_name = CFSTR("TestSource"); + + CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + + SOSAccountRef alice_account = CreateAccountForLocalChanges(CFSTR("Alice"), circle_name); + SOSAccountRef bob_account = CreateAccountForLocalChanges(CFSTR("Bob"), circle_name); + SOSAccountRef carole_account = CreateAccountForLocalChanges(CFSTR("Carole"), circle_name); + + ok(SOSAccountAssertUserCredentials(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(SOSAccountAssertUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + + ok(SOSAccountAssertUserCredentials(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); + + CFArrayRef peers = SOSAccountCopyPeers(alice_account, &error); + ok(peers && CFArrayGetCount(peers) == 2, "See two peers %@ (%@)", peers, error); + CFReleaseNull(peers); + + SOSFullPeerInfoRef fpiAlice = SOSAccountGetMyFullPeerInCircleNamed(alice_account, circle_name, NULL); + CFStringRef alice_id = CFStringCreateCopy(NULL, SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(fpiAlice))); + + ok(SOSAccountLeaveCircles(alice_account, &error), "Alice Leaves (%@)", error); + CFReleaseNull(error); + CFReleaseNull(cfpassword); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, NULL), 3, "updates"); + + accounts_agree("Alice bails", bob_account, alice_account); + accounts_agree("Alice bails", bob_account, carole_account); + + SOSAccountCleanupRetirementTickets(bob_account, 0, &error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, NULL), 1, "updates"); + + //is(CFDictionaryGetCountOfValue(BobChanges, kCFNull),0, "0 Keys Nulled Out"); + + ok(SOSAccountJoinCircles(carole_account, &error), "Carole Applies (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, NULL), 2, "updates"); + + + { + CFArrayRef applicants = SOSAccountCopyApplicants(bob_account, &error); + + ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); + ok(SOSAccountAcceptApplicants(bob_account, applicants, &error), "Bob accepts Carole (%@)", error); + CFReleaseNull(error); + CFReleaseNull(applicants); + } + + // Bob should not yet cleanup Alice's retirment here on his own since it hasn't been long enough + // by default. + //is(CFDictionaryGetCountOfValue(BobChanges, kCFNull),0, "0 Keys Nulled Out"); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, NULL), 3, "updates"); + + accounts_agree("Carole joins", bob_account, carole_account); + + SOSAccountCleanupRetirementTickets(bob_account, 0, &error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, NULL), 2, "updates"); + + is(countPeers(bob_account), 2, "Active peers after forced cleanup"); + is(countActivePeers(bob_account), 3, "Inactive peers after forced cleanup"); + + //is(CFDictionaryGetCountOfValue(BobChanges, kCFNull), 1, "1 Keys Nulled Out"); + +// CFDictionaryForEach(BobChanges, ^(const void *key, const void *value) { +// if(isNull(value)) { +// CFStringRef circle_name = NULL, retiree = NULL; +// SOSKVSKeyType keytype = SOSKVSKeyGetKeyTypeAndParse(key, &circle_name, &retiree, NULL); +// is(keytype, kRetirementKey, "Expect only a retirement key"); +// ok(CFEqualSafe(alice_id, retiree), "Alice (%@) is retiree (%@)", alice_id, retiree); +// CFReleaseNull(circle_name); +// CFReleaseNull(retiree); +// } +// }); + + CFReleaseNull(alice_id); + CFReleaseNull(carole_account); + CFReleaseNull(bob_account); + CFReleaseNull(alice_account); + + SOSUnregisterAllTransportMessages(); + SOSUnregisterAllTransportCircles(); + SOSUnregisterAllTransportKeyParameters(); + CFArrayRemoveAllValues(key_transports); + CFArrayRemoveAllValues(circle_transports); + CFArrayRemoveAllValues(message_transports); + +} + +int secd_59_account_cleanup(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/Security/sec/securityd/Regressions/secd-60-account-cloud-identity.c b/Security/sec/securityd/Regressions/secd-60-account-cloud-identity.c new file mode 100644 index 00000000..4f83c93e --- /dev/null +++ b/Security/sec/securityd/Regressions/secd-60-account-cloud-identity.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + + + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "secd_regressions.h" +#include "SOSTestDataSource.h" + +#include "SOSRegressionUtilities.h" +#include +#include + +#include + +#include "SOSAccountTesting.h" + +static int kTestTestCount = 145; + + + +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(SOSAccountAssertUserCredentials(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(SOSAccountAssertUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + + ok(SOSAccountAssertUserCredentials(carole_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + CFReleaseNull(cfpassword); + 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); + + /*----- normal join after restore -----*/ + + ok(SOSAccountJoinCirclesAfterRestore(carole_account, &error), "Carole cloud identity joins (%@)", error); + CFReleaseNull(error); + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, NULL), 4, "updates"); + + is(countApplicants(alice_account), 0, "See no applicants"); + + is(countPeers(carole_account), 3, "Carole sees 3 valid peers after sliding in"); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, NULL), 1, "updates"); + + accounts_agree_internal("Carole's in", bob_account, alice_account, false); + accounts_agree_internal("Carole's in - 2", bob_account, carole_account, false); + + ok(SOSAccountLeaveCircles(carole_account, &error), "Carol Leaves again"); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, NULL), 3, "updates"); + + /*----- join - join after restore -----*/ + + ok(SOSAccountJoinCircles(carole_account, &error), "Carole normally joins (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, NULL), 2, "updates"); + + is(countApplicants(alice_account), 1, "See one applicant"); + + ok(SOSAccountJoinCirclesAfterRestore(carole_account, &error), "Carole cloud identity joins (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, NULL), 4, "updates"); + + + is(countApplicants(alice_account), 0, "See no applicants"); + + is(countPeers(carole_account), 3, "Carole sees 3 valid peers after sliding in"); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, NULL), 1, "updates"); + + accounts_agree_internal("Carole's in", bob_account, alice_account, false); + accounts_agree_internal("Carole's in - 2", bob_account, carole_account, false); + + CFReleaseNull(bob_account); + CFReleaseNull(alice_account); + CFReleaseNull(carole_account); + + SOSUnregisterAllTransportMessages(); + SOSUnregisterAllTransportCircles(); + SOSUnregisterAllTransportKeyParameters(); + CFArrayRemoveAllValues(key_transports); + CFArrayRemoveAllValues(circle_transports); + CFArrayRemoveAllValues(message_transports); + +} + +int secd_60_account_cloud_identity(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/Security/sec/securityd/Regressions/secd-61-account-leave-not-in-kansas-anymore.c b/Security/sec/securityd/Regressions/secd-61-account-leave-not-in-kansas-anymore.c new file mode 100644 index 00000000..1225a092 --- /dev/null +++ b/Security/sec/securityd/Regressions/secd-61-account-leave-not-in-kansas-anymore.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "secd_regressions.h" +#include "SOSTestDataSource.h" + +#include "SOSRegressionUtilities.h" +#include +#include + +#include + +#include "SOSAccountTesting.h" + +static int kTestTestCount = 126; +#if 0 +static int countPeers(SOSAccountRef account, bool active) { + CFErrorRef error = NULL; + CFArrayRef peers; + + if(active) peers = SOSAccountCopyActivePeers(account, &error); + else peers = SOSAccountCopyPeers(account, &error); + int retval = (int) CFArrayGetCount(peers); + CFReleaseNull(error); + CFReleaseNull(peers); + return retval; +} +#endif +/* + static void trim_retirements_from_circle(SOSAccountRef account) { + SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { + SOSCircleRemoveRetired(circle, NULL); + }); + } + */ +static bool accept_applicants(SOSAccountRef account, int count) { + CFErrorRef error = NULL; + CFArrayRef applicants = SOSAccountCopyApplicants(account, &error); + bool retval = false; + ok(applicants, "Have Applicants"); + if(!applicants) goto errout; + is(CFArrayGetCount(applicants), count, "See applicants %@ (%@)", applicants, error); + if(CFArrayGetCount(applicants) != count) goto errout; + ok(retval = SOSAccountAcceptApplicants(account, applicants, &error), "Account accepts (%@)", error); +errout: + CFReleaseNull(error); + CFReleaseNull(applicants); + 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")); + SOSAccountRef david_account = CreateAccountForLocalChanges ( CFSTR("David"), CFSTR("TestSource")); + + ok(SOSAccountAssertUserCredentials(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, david_account, NULL), 1, "updates"); + + ok(SOSAccountAssertUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + + ok(SOSAccountAssertUserCredentials(carole_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + + ok(SOSAccountAssertUserCredentials(david_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, david_account, NULL), 2, "updates"); + + + ok(SOSAccountJoinCircles(bob_account, &error), "Bob Applies (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 2, "updates"); + + + ok(accept_applicants(alice_account, 1), "Alice Accepts Application"); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, david_account, NULL), 3, "updates"); + + accounts_agree("bob&alice pair", bob_account, alice_account); + is(SOSAccountGetLastDepartureReason(bob_account, &error), kSOSNeverLeftCircle, "Bob affirms he hasn't left."); + + // ============================== Alice and Bob are in the Account. ============================================ + + + ok(SOSAccountJoinCircles(carole_account, &error), "Carole Applies (%@)", error); + CFReleaseNull(error); + is(ProcessChangesUntilNoChange(changes, alice_account, carole_account, david_account, NULL), 2, "updates"); + + ok(accept_applicants(alice_account, 1), "Alice Accepts Application"); + + // Let everyone concur. + is(ProcessChangesUntilNoChange(changes, alice_account, carole_account, david_account, NULL), 3, "updates"); + + CFArrayRef peers = SOSAccountCopyPeers(alice_account, &error); + + ok(peers && CFArrayGetCount(peers) == 3, "See three peers %@ (%@)", peers, error); + CFReleaseNull(peers); + + // SOSAccountPurgePrivateCredential(alice_account); + + ok(SOSAccountLeaveCircles(alice_account, &error), "Alice Leaves (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, carole_account, david_account, NULL), 3, "updates"); + + + ok(SOSAccountJoinCircles(david_account, &error), "David Applies (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, carole_account, david_account, NULL), 2, "updates"); + + ok(accept_applicants(carole_account, 1), "Carole Accepts Application"); + + // ============================== We added Carole and David while Bob was in a drawer. Alice has left ============================================ + + // ============================== Bob comes out of the drawer seeing alice left and doesn't recognize the remainder. ============================================ + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, david_account, NULL), 4, "updates"); + + CFReleaseNull(error); + is(SOSAccountIsInCircles(carole_account, &error), kSOSCCInCircle, "Carole still in Circle (%@)", error); + CFReleaseNull(error); + is(SOSAccountIsInCircles(david_account, &error), kSOSCCInCircle, "David still in Circle (%@)", error); + CFReleaseNull(error); + is(SOSAccountIsInCircles(bob_account, &error), kSOSCCNotInCircle, "Bob is not in Circle (%@)", error); + CFReleaseNull(error); + is(SOSAccountGetLastDepartureReason(bob_account, &error), kSOSLeftUntrustedCircle, "Bob affirms he left because he doesn't know anyone."); + CFReleaseNull(error); + is(SOSAccountIsInCircles(alice_account, &error), kSOSCCNotInCircle, "Alice is not in Circle (%@)", error); + CFReleaseNull(error); + is(SOSAccountGetLastDepartureReason(alice_account, &error), kSOSWithdrewMembership, "Alice affirms she left by request."); + CFReleaseNull(error); + + + CFReleaseNull(carole_account); + CFReleaseNull(david_account); + CFReleaseNull(bob_account); + CFReleaseNull(alice_account); + CFReleaseNull(cfpassword); + + SOSUnregisterAllTransportMessages(); + SOSUnregisterAllTransportCircles(); + SOSUnregisterAllTransportKeyParameters(); + CFArrayRemoveAllValues(key_transports); + CFArrayRemoveAllValues(circle_transports); + CFArrayRemoveAllValues(message_transports); + +} + +int secd_61_account_leave_not_in_kansas_anymore(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/Security/sec/securityd/Regressions/secd-70-engine-corrupt.c b/Security/sec/securityd/Regressions/secd-70-engine-corrupt.c new file mode 100644 index 00000000..cf00bde1 --- /dev/null +++ b/Security/sec/securityd/Regressions/secd-70-engine-corrupt.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +// Test syncing between SecItemDataSource and SOSTestDataSource + +#include +#include +#include "secd_regressions.h" +#include "SecdTestKeychainUtilities.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static int kTestTestCount = 125; + +static void nosha1(void) { + __block int iteration = 0; + __block CFErrorRef error = NULL; + SOSTestDeviceListTestSync("nosha1", test_directive, test_reason, 0, true, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest) { + iteration++; + // Add 10 items in first 10 sync messages + if (iteration <= 6) { + CFStringRef account = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("item%d"), iteration); + SOSTestDeviceAddGenericItem(source, account, CFSTR("nosha1")); + CFReleaseSafe(account); + // Corrupt the 4th item added + if (iteration == 4) { + ok(SecDbPerformWrite(source->db, &error, ^(SecDbConnectionRef dbconn) { + ok(SecDbTransaction(dbconn, kSecDbExclusiveTransactionType, &error, ^(bool *commit) { + ok(SecDbExec(dbconn, CFSTR("UPDATE genp SET sha1=X'0000000000000000000000000000000000000000' WHERE rowid=5;"), &error), + "Corrupting rowid 5 by zeroing sha1: %@", error); + CFReleaseNull(error); + }), "SecDbTransaction: %@", error); + CFReleaseNull(error); + }), "SecDbPerformWrite: %@", error); + CFReleaseNull(error); + return true; + } + return true; + } + + + return false; + }, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message) { + return false; + }, CFSTR("Bad"), CFSTR("Good"), NULL); +} + +static void drop_item(void) { + __block int iteration = 0; + __block CFErrorRef error = NULL; + SOSTestDeviceListTestSync("drop_item", test_directive, test_reason, 0, true, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest) { + iteration++; + // Add 10 items in first 10 sync messages + if (iteration <= 6) { + CFStringRef account = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("item%d"), iteration); + SOSTestDeviceAddGenericItem(source, account, CFSTR("drop_item")); + CFReleaseSafe(account); + // Corrupt the 4th item added + if (iteration == 4) { + ok(SecDbPerformWrite(source->db, &error, ^(SecDbConnectionRef dbconn) { + ok(SecDbTransaction(dbconn, kSecDbExclusiveTransactionType, &error, ^(bool *commit) { + ok(SecDbExec(dbconn, CFSTR("DELETE FROM genp WHERE rowid=5;"), &error), + "Corrupting rowid 5 by deleting object: %@", error); + CFReleaseNull(error); + }), "SecDbTransaction: %@", error); + CFReleaseNull(error); + }), "SecDbPerformWrite: %@", error); + CFReleaseNull(error); + return true; + } + return true; + } + + + return false; + }, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message) { + return false; + }, CFSTR("Abegail"), CFSTR("Billy"), NULL); +} + +static void drop_manifest(void) { + __block int iteration = 0; + SOSTestDeviceListTestSync("drop_manifest", test_directive, test_reason, 0, true, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest) { + iteration++; + // Add 5 items on Alice and 4 on Bob in first 9 sync messages + if (iteration <= 9) { + CFStringRef account = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("item%d"), iteration / 2); + SOSTestDeviceAddGenericItem(source, account, CFSTR("drop_manifest")); + CFReleaseSafe(account); + // Corrupt the manifest after 4th item added + if (iteration == 4) { + SOSEngineRef engine = SOSDataSourceGetSharedEngine(source->ds, NULL); + SOSManifestRef mf = SOSEngineCopyManifest(engine, NULL); + struct SOSDigestVector empty = SOSDigestVectorInit; + ok(SOSEngineUpdateLocalManifest(engine, kSOSDataSourceSOSTransaction, + (struct SOSDigestVector *)SOSManifestGetDigestVector(mf), &empty, NULL), + "droped manifest from %@", source); + CFReleaseNull(mf); + return true; + } + return true; + } + + return false; + }, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message) { + return false; + }, CFSTR("Ann"), CFSTR("Ben"), NULL); +} + +static void add_sha1(void) { + TODO: { + //todo("this never stops syncing"); + __block int iteration = 0; + __block CFErrorRef error = NULL; + SOSTestDeviceListTestSync("add_sha1", test_directive, test_reason, 0, true, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest) { + iteration++; + // Add 9 items in first 9 sync messages + if (iteration <= 9) { + CFStringRef account = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("item%d"), iteration); + SOSTestDeviceAddGenericItem(source, account, CFSTR("add_sha1")); + CFReleaseSafe(account); + // Corrupt the manifest after 4th item added + if (iteration == 4) { + ok(SecDbPerformWrite(source->db, &error, ^(SecDbConnectionRef dbconn) { + ok(SecDbTransaction(dbconn, kSecDbExclusiveTransactionType, &error, ^(bool *commit) { + ok(SecDbExec(dbconn, CFSTR("UPDATE genp SET sha1=X'0000000000000000000000000000000000000000' WHERE rowid=5;"), &error), + "Corrupting rowid 5 by zeroing sha1: %@", error); + CFReleaseNull(error); + }), "SecDbTransaction: %@", error); + CFReleaseNull(error); + }), "SecDbPerformWrite: %@", error); + CFReleaseNull(error); + + SOSEngineRef engine = SOSDataSourceGetSharedEngine(source->ds, NULL); + struct SOSDigestVector del = SOSDigestVectorInit; + struct SOSDigestVector add = SOSDigestVectorInit; + uint8_t zeroDigest[20] = {}; + SOSDigestVectorAppend(&add, zeroDigest); + ok(SOSEngineUpdateLocalManifest(engine, kSOSDataSourceSOSTransaction, + &del, &add, NULL), "corrupting manifest"); + return true; + } + return true; + } + + return false; + }, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message) { + return false; + }, CFSTR("Andy"), CFSTR("Bill"), NULL); + } +} + +static void change_sha1(void) { +TODO: { + //todo("this never stops syncing"); + __block int iteration = 0; + __block CFErrorRef error = NULL; + SOSTestDeviceListTestSync("change_sha1", test_directive, test_reason, 0, true, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest) { + iteration++; + // Add 9 items in first 9 sync messages + if (iteration <= 9) { + CFStringRef account = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("item%d"), iteration); + CFStringRef server = CFSTR("change_sha1"); + // Corrupt the manifest after 4th item added + if (!SOSDataSourceWithAPI(source->ds, true, &error, ^(SOSTransactionRef txn, bool *commit) { + SOSObjectRef object = SOSDataSourceCreateGenericItem(source->ds, account, server); + ok(SOSDataSourceMergeObject(source->ds, txn, object, NULL, &error), "%@ added API object %@", SOSTestDeviceGetID(source), error ? (CFTypeRef)error : (CFTypeRef)CFSTR("ok")); + if (iteration == 3) { + sqlite_int64 rowid = SecDbItemGetRowId((SecDbItemRef)object, NULL); + CFStringRef sql = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("UPDATE genp SET sha1=X'0000000000000000000000000000000000000000' WHERE rowid=%lld;"), rowid); + ok(SecDbExec((SecDbConnectionRef)txn, sql, &error), + "Corrupting rowid %lld by zeroing sha1: %@", rowid, error); + CFReleaseNull(sql); + SOSEngineRef engine = SOSDataSourceGetSharedEngine(source->ds, NULL); + struct SOSDigestVector del = SOSDigestVectorInit; + struct SOSDigestVector add = SOSDigestVectorInit; + uint8_t zeroDigest[20] = {}; + SOSDigestVectorAppend(&add, zeroDigest); + CFDataRef digest = SOSObjectCopyDigest(source->ds, object, NULL); + const uint8_t *d = CFDataGetBytePtr(digest); + SOSDigestVectorAppend(&del, d); + ok(SOSEngineUpdateLocalManifest(engine, kSOSDataSourceSOSTransaction, + &del, &add, NULL), "corrupting manifest %lld %02X%02x%02x%02x", + rowid, d[0], d[1], d[2], d[3]); + CFReleaseSafe(digest); + } + CFReleaseSafe(object); + CFReleaseNull(error); + })) + fail("ds transaction %@", error); + CFReleaseNull(error); + CFReleaseNull(account); + return true; + } + return false; + }, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message) { + if (iteration >= 3) + pass("%@", source); + return false; + }, CFSTR("Alice"), CFSTR("Bob"), NULL); +} +} + +int secd_70_engine_corrupt(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + /* custom keychain dir */ + secd_test_setup_temp_keychain("secd_70_engine_corrupt", NULL); + + nosha1(); + drop_item(); + drop_manifest(); + add_sha1(); + change_sha1(); + + return 0; +} diff --git a/Security/sec/securityd/Regressions/secd-70-engine.c b/Security/sec/securityd/Regressions/secd-70-engine.c new file mode 100644 index 00000000..4922f549 --- /dev/null +++ b/Security/sec/securityd/Regressions/secd-70-engine.c @@ -0,0 +1,510 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +// Test syncing between SecItemDataSource and SOSTestDataSource + +#include +#include +#include "secd_regressions.h" +#include "SecdTestKeychainUtilities.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static int kTestTestCount = 1286; + +__unused static bool SOSCircleHandleCircleWithLock(SOSEngineRef engine, CFStringRef myID, CFDataRef message, CFErrorRef *error) { + + CFMutableArrayRef trustedPeers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFMutableArrayRef untrustedPeers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFStringRef peerID = NULL; + const uint8_t expected[20] = { 0xea, 0x6c, 0x01, 0x4d, + 0xc7, 0x2d, 0x6f, 0x8c, + 0xcd, 0x1e, 0xd9, 0x2a, + 0xce, 0x1d, 0x41, 0xf0, + 0xd8, 0xde, 0x89, 0x57 }; + + const char resultSize = sizeof(expected); + + CFDataRef coder = CFDataCreate(kCFAllocatorDefault, expected, resultSize); + CFArrayForEachC(SOSEngineGetPeerIDs(engine), peerID){ + CFArrayAppendValue(trustedPeers, peerID); + SOSEngineSetCoderData(engine, peerID, coder, error); + }; + CFReleaseNull(coder); + + CFShow(trustedPeers); + // all trusted + SOSEngineCircleChanged_locked(engine, myID,trustedPeers, untrustedPeers); + + // make first peer untrusted + peerID = (CFStringRef)CFArrayGetValueAtIndex(trustedPeers, 0); + CFArrayAppendValue(untrustedPeers, peerID); + CFArrayRemoveAllValue(trustedPeers, peerID); + //we should see peerState cleared out except for the coder! + SOSEngineCircleChanged_locked(engine, myID, trustedPeers, untrustedPeers); + + CFArrayAppendValue(trustedPeers, peerID); + CFArrayRemoveAllValue(untrustedPeers, peerID); + + + return true; +} + +static void testsync3(const char *name, const char *test_directive, const char *test_reason) { + __block int iteration=0; + SOSTestDeviceListTestSync(name, test_directive, test_reason, 0, false, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest) { + iteration++; + if (iteration == 12 || iteration == 13) { + pass("pre-rcv %@", dest); + } + if (iteration == 19) { + pass("pre-send %@", source); + } + return false; + }, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message) { + if (iteration == 10) { + pass("pre-add %@", source); + //SOSTestDeviceAddGenericItem(source, CFSTR("test_account"), CFSTR("test service")); + SOSTestDeviceAddRemoteGenericItem(source, CFSTR("test_account"), CFSTR("test service")); + pass("post-add %@", source); + return true; // db changed + } else if (iteration == 12 || iteration == 15) { + pass("post-rcv %@", dest); + } + return false; + }, CFSTR("AAA"), CFSTR("BBB"), CFSTR("CCC"), NULL); +} + +static void testsync2(const char *name, const char *test_directive, const char *test_reason, void (^aliceInit)(SOSDataSourceRef ds), void (^bobInit)(SOSDataSourceRef ds), CFStringRef msg, ...) { + __block int iteration=0; + SOSTestDeviceListTestSync(name, test_directive, test_reason, kSOSPeerVersion, false, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest) { + if (iteration == 96) { + pass("%@ before message", source); + } + return false; + }, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message) { + iteration++; + if (iteration == 60) { + pass("%@ before addition", source); + //SOSTestDeviceAddGenericItem(source, CFSTR("test_account"), CFSTR("test service")); + SOSTestDeviceAddRemoteGenericItem(source, CFSTR("test_account"), CFSTR("test service")); + pass("%@ after addition", source); + return true; + } + return false; + }, CFSTR("alice"), CFSTR("bob"), CFSTR("claire"), CFSTR("dave"),CFSTR("edward"), CFSTR("frank"), CFSTR("gary"), NULL); +} + +static void testsync(const char *name, const char *test_directive, const char *test_reason, void (^aliceInit)(SOSDataSourceRef ds), void (^bobInit)(SOSDataSourceRef ds), ...) { + __block int msg_index = 0; + __block int last_msg_index = 0; + va_list args; + va_start(args, bobInit); + CFArrayRef messages = CFArrayCreateForVC(kCFAllocatorDefault, &kCFTypeArrayCallBacks, args); + SOSTestDeviceListTestSync(name, test_directive, test_reason, 0, false, + ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest) { + if (msg_index == 0) { + aliceInit(source->ds); + bobInit(dest->ds); + return true; + } + return false; + }, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message) { + CFStringRef hexMsg = msg_index < CFArrayGetCount(messages) ? (CFStringRef)CFArrayGetValueAtIndex(messages, msg_index) : 0; + /* We are expecting a message and msg is it's digest. */ + if (message) { + msg_index++; + CFStringRef messageDigestStr = SOSMessageCopyDigestHex(message); + if (hexMsg) { + if (CFEqual(messageDigestStr, hexMsg)) { + pass("%s %@ handled message [%d] %@", name, SOSEngineGetMyID(dest->ds->engine), msg_index, message); + } else { + fail("%s %@ received message [%d] digest %@ != %@ %@", name, SOSEngineGetMyID(dest->ds->engine), msg_index, messageDigestStr, hexMsg, message); + } + last_msg_index = msg_index; + } else { + fail("%s %@ sent extra message [%d] with digest %@: %@", name, SOSEngineGetMyID(source->ds->engine), msg_index, messageDigestStr, message); + } + CFReleaseSafe(messageDigestStr); + //SOSCircleHandleCircleWithLock(source->ds->engine, SOSEngineGetMyID(source->ds->engine), CFDataCreate(kCFAllocatorDefault, 0, 0), NULL); + + } + return false; + }, CFSTR("alice"), CFSTR("bob"), NULL); + + if (msg_index < CFArrayGetCount(messages)) { + fail("%s nothing sent expecting message [%d] digest %@", name, msg_index, CFArrayGetValueAtIndex(messages, msg_index)); + } else if (last_msg_index < msg_index) { + fail("%s exchanged %d messages not in expected list", name, msg_index - last_msg_index); + } + + +} + +#if 0 +// Test syncing an empty circle with 1 to 10 devices and both version 0 and version 2 protocols +static void testsyncempty(void) { + CFMutableArrayRef deviceIDs = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + for (int deviceIX=0; deviceIX < 10; ++deviceIX) { + CFStringRef deviceID = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%c"), 'A' + deviceIX); + CFArrayAppendValue(deviceIDs, deviceID); + CFReleaseSafe(deviceID); + if (deviceIX > 0) { + for (CFIndex version = 0; version < 3; version += 2) { + CFMutableDictionaryRef testDevices = SOSTestDeviceListCreate(false, version, deviceIDs); + SOSTestDeviceListSync("syncempty", test_directive, test_reason, testDevices, NULL, NULL); + SOSTestDeviceListInSync("syncempty", test_directive, test_reason, testDevices); + CFReleaseSafe(testDevices); + } + } + } + CFReleaseSafe(deviceIDs); +} +#endif + +static CFIndex syncmany_add(int iteration) { + if (iteration % 7 < 3 && iteration < 10) + return iteration % 17 + 200; + return 0; +} + +static void testsyncmany(const char *name, const char *test_directive, const char *test_reason, int devFirst, int devCount, int version, CFIndex (*should_add)(int iteration)) { + CFMutableArrayRef deviceIDs = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + for (int deviceIX=0; deviceIX < devCount; ++deviceIX) { + CFStringRef deviceID = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%c"), 'A' + deviceIX); + CFArrayAppendValue(deviceIDs, deviceID); + CFReleaseSafe(deviceID); + if (deviceIX >= devFirst) { + CFMutableDictionaryRef testDevices = SOSTestDeviceListCreate(false, version, deviceIDs); + __block int iteration = 0; + SOSTestDeviceListSync(name, test_directive, test_reason, testDevices, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest) { + bool didAdd = false; + iteration++; + // Add 10 items in first 10 sync messages + CFIndex toAdd = should_add(iteration); + if (toAdd) { + CFStringRef account = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("item%d"), iteration); + didAdd = SOSTestDeviceAddGenericItems(source, toAdd, account, CFSTR("testsyncmany")); + CFReleaseSafe(account); + } + if (iteration == 279 || iteration == 459) + pass("pre-send[%d] %@", iteration, source); + + return didAdd; + }, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message) { + if (iteration == 262) + pass("post-rcv[%d] %@", iteration, dest); + + if (iteration == 272 || iteration == 279) + pass("post-send[%d] %@", iteration, source); + + return false; + }); + SOSTestDeviceListInSync(name, test_directive, test_reason, testDevices); + CFReleaseSafe(testDevices); + } + } + CFReleaseSafe(deviceIDs); +} + +static void testsync2p(void) { + __block int iteration = 0; + SOSTestDeviceListTestSync("testsync2p", test_directive, test_reason, 0, false, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest) { + iteration++; + // Add 10 items in first 10 sync messages + if (iteration <= 10) { + CFStringRef account = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("item%d"), iteration); + SOSTestDeviceAddGenericItem(source, account, CFSTR("testsync2p")); + CFReleaseSafe(account); + return true; + } + return false; + }, ^bool(SOSTestDeviceRef source, SOSTestDeviceRef dest, SOSMessageRef message) { + return false; + }, CFSTR("Atestsync2p"), CFSTR("Btestsync2p"), NULL); +} + +static void synctests(void) { +#if 0 + // TODO: Adding items gives us non predictable creation and mod dates so + // the message hashes can't be precomputed. + CFDictionaryRef item = CFDictionaryCreateForCFTypes + (0, + kSecClass, kSecClassGenericPassword, + kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked, + kSecAttrSynchronizable, kCFBooleanTrue, + kSecAttrService, CFSTR("service"), + kSecAttrAccount, CFSTR("account"), + NULL); + SecItemAdd(item, NULL); + CFReleaseSafe(item); +#endif + +SKIP: + { + +#ifdef NO_SERVER + // Careful with this in !NO_SERVER, it'll destroy debug keychains. + WithPathInKeychainDirectory(CFSTR("keychain-2-debug.db"), ^(const char *keychain_path) { + unlink(keychain_path); + }); + + // Don't ever do this in !NO_SERVER, it'll destroy real keychains. + WithPathInKeychainDirectory(CFSTR("keychain-2.db"), ^(const char *keychain_path) { + unlink(keychain_path); + }); + + void kc_dbhandle_reset(void); + kc_dbhandle_reset(); +#else + skip("Keychain not reset", kTestTestCount, false); +#endif + + testsync3("secd_70_engine3", test_directive, test_reason); + + // Sync between 2 empty dataSources + testsync("secd_70_engine", test_directive, test_reason, + ^ (SOSDataSourceRef dataSource) {}, + ^ (SOSDataSourceRef dataSource) {}, + CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), + CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), + CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), + CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), + NULL); + + // Sync a dataSource with one object to an empty dataSource + testsync("secd_70_engine-alice1", test_directive, test_reason, + ^ (SOSDataSourceRef dataSource) { + __block CFErrorRef error = NULL; + SOSObjectRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); + // TODO: Needs to be a SecDBItemRef for the SecItemDataSource... + ok(SOSDataSourceWith(dataSource, &error, ^(SOSTransactionRef txn, bool *commit) { + ok(SOSDataSourceMergeObject(dataSource, txn, object, NULL, &error), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource->engine), error); + }), "ds transaction failed %@", error); + CFReleaseSafe(object); + CFReleaseNull(error); + }, + ^ (SOSDataSourceRef dataSource) {}, + CFSTR("DDDB2DCEB7B36F0757F400251ECD11E377A0DCE8"), + CFSTR("B2777CC898AE381B3F375B27E4FD9757F6CE9948"), + CFSTR("CB67BF9ECF00DC7664834DE7A2D7CC1523D25341"), + CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), + + //CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), + //CFSTR("147B6C509908CC4A9FC4263973A842104A64CE01"), + //CFSTR("019B494F3C06B48BB02C280AF1E19AD861A7003C"), + //CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), + NULL); + + // Sync a dataSource with one object to another dataSource with the same object + testsync("secd_70_engine-alice1bob1", test_directive, test_reason, + ^ (SOSDataSourceRef dataSource) { +#if 0 + CFErrorRef error = NULL; + // TODO: Needs to be a SecDBItemRef for the SecItemDataSource... + CFDictionaryRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); + ok(SOSDataSourceMergeObject(dataSource, object, NULL, &error), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource->engine), error); + CFReleaseSafe(object); + CFReleaseNull(error); +#endif + }, + ^ (SOSDataSourceRef dataSource) { + __block CFErrorRef error = NULL; + SOSObjectRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); + ok(SOSDataSourceWith(dataSource, &error, ^(SOSTransactionRef txn, bool *commit) { + ok(SOSDataSourceMergeObject(dataSource, txn, object, NULL, &error), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource->engine), error); + }), "ds transaction failed %@", error); + CFReleaseSafe(object); + CFReleaseNull(error); + }, + CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), + CFSTR("CB67BF9ECF00DC7664834DE7A2D7CC1523D25341"), + CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), + + //CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), + //CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), + //CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), + NULL); + + // Sync a dataSource with one object to another dataSource with the same object + testsync("secd_70_engine-alice1bob2", test_directive, test_reason, + ^ (SOSDataSourceRef dataSource) { +#if 0 + CFErrorRef error = NULL; + // TODO: Needs to be a SecDBItemRef for the SecItemDataSource... + SOSObjectRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); + ok(SOSDataSourceMergeObject(dataSource, object, NULL, &error), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource->engine), error); + CFReleaseSafe(object); + CFReleaseNull(error); +#endif + }, + ^ (SOSDataSourceRef dataSource) { + __block CFErrorRef error = NULL; + __block SOSObjectRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); + ok(SOSDataSourceWith(dataSource, &error, ^(SOSTransactionRef txn, bool *commit) { + ok(SOSDataSourceMergeObject(dataSource, txn, object, NULL, &error), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource->engine), error); + CFReleaseSafe(object); + CFReleaseNull(error); + object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("account1"), CFSTR("service1")); + ok(SOSDataSourceMergeObject(dataSource, txn, object, NULL, &error), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource->engine), error); + CFReleaseSafe(object); + }), "ds transaction failed %@", error); + CFReleaseNull(error); + }, + CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), + CFSTR("270EB3953B2E1E295F668CFC27CBB7137991A4BE"), + CFSTR("D1B3944E3084425F41B2C2EA0BE82170E10AA37D"), + + //CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), + //CFSTR("D4049A1063CFBF7CAF8424E13DE3CE926FF5856C"), + //CFSTR("9624EA855BBED6B668868BB723443E804D04F6A1"), + //CFSTR("063E097CCD4FEB7F3610ED12B3DA828467314846"), + //CFSTR("D1B3944E3084425F41B2C2EA0BE82170E10AA37D"), + NULL); + + // Sync a dataSource with a tombstone object to another dataSource with the same object + TODO: { + todo(" Test case in sd-70-engine fails due to need for RowID"); + testsync("secd_70_engine-update", test_directive, test_reason, + ^ (SOSDataSourceRef dataSource) { + __block CFErrorRef error = NULL; + const char *password = "password1"; + CFDataRef data = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)password, strlen(password)); + // TODO: Needs to be a SecDBItemRef for the SecItemDataSource... + SOSObjectRef object_to_find = SOSDataSourceCreateGenericItemWithData(dataSource, CFSTR("test_account"), CFSTR("test service"), true, NULL); + SOSObjectRef object = SOSDataSourceCopyObject(dataSource, object_to_find, &error); + SOSObjectRef old_object = NULL; + SKIP: { + skip("no object", 1, ok(object, "Finding object %@, error: %@", object_to_find, error)); + CFReleaseNull(data); + // TODO: Needs to be a SecDBItemRef for the SecItemDataSource... + old_object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); + ok(SOSDataSourceWith(dataSource, &error, ^(SOSTransactionRef txn, bool *commit) { + ok(SOSDataSourceMergeObject(dataSource, txn, object, NULL, &error), "dataSource %@ update object %@", SOSEngineGetMyID(dataSource->engine), error); + }), "ds transaction failed %@", error); + } + CFReleaseSafe(data); + CFReleaseSafe(old_object); + CFReleaseSafe(object); + CFReleaseNull(error); + }, + ^ (SOSDataSourceRef dataSource) { + __block CFErrorRef error = NULL; + __block SOSObjectRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); + ok(SOSDataSourceWith(dataSource, &error, ^(SOSTransactionRef txn, bool *commit) { + ok(SOSDataSourceMergeObject(dataSource, txn, object, NULL, &error), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource->engine), error); + CFReleaseSafe(object); + CFReleaseNull(error); + object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("account1"), CFSTR("service1")); + ok(SOSDataSourceMergeObject(dataSource, txn, object, NULL, &error), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource->engine), error); + CFReleaseSafe(object); + }), "ds transaction failed %@", error); + CFReleaseNull(error); + }, + CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), + CFSTR("270EB3953B2E1E295F668CFC27CBB7137991A4BE"), + CFSTR("D1B3944E3084425F41B2C2EA0BE82170E10AA37D"), + + //CFSTR("5D07A221A152D6D6C5F1919189F259A7278A08C5"), + //CFSTR("D4049A1063CFBF7CAF8424E13DE3CE926FF5856C"), + //CFSTR("137FD34E9BF11B4BA0620E8EBFAB8576BCCCF294"), + //CFSTR("5D07A221A152D6D6C5F1919189F259A7278A08C5"), + NULL); + } + + // Sync a dataSource with one object to another dataSource with the same object + testsync("secd_70_engine-foreign-add", test_directive, test_reason, + ^ (SOSDataSourceRef dataSource) { + }, + ^ (SOSDataSourceRef dataSource) { + __block CFErrorRef error = NULL; + const char *password = "password1"; + CFDataRef data = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)password, strlen(password)); + __block SOSObjectRef object = SOSDataSourceCreateGenericItemWithData(dataSource, CFSTR("test_account"), CFSTR("test service"), false, data); + CFReleaseSafe(data); + ok(SOSDataSourceWith(dataSource, &error, ^(SOSTransactionRef txn, bool *commit) { + ok(SOSDataSourceMergeObject(dataSource, txn, object, NULL, &error), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource->engine), error); + CFReleaseSafe(object); + CFReleaseNull(error); + object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("account1"), CFSTR("service1")); + ok(SOSDataSourceMergeObject(dataSource, txn, object, NULL, &error), "dataSource %@ added object %@", SOSEngineGetMyID(dataSource->engine), error); + CFReleaseSafe(object); + }), "ds transaction failed %@", error); + CFReleaseNull(error); + }, + CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), + CFSTR("769F63675CEE9CB968BFD9CA48DB9079BFCAFB6C"), + CFSTR("818C24B9BC495940836B9C8F76517C838CEFFA98"), + + //CFSTR("D1B3944E3084425F41B2C2EA0BE82170E10AA37D"), + //CFSTR("607EEF976943FD781CFD2B3850E6DC7979AA61EF"), + //CFSTR("28434CD1B90CC205460557CAC03D7F12067F2329"), + //CFSTR("D1B3944E3084425F41B2C2EA0BE82170E10AA37D"), + NULL); + } + + // Sync between 2 empty dataSources + testsync2("secd_70_engine2", test_directive, test_reason, + ^ (SOSDataSourceRef dataSource) {}, + ^ (SOSDataSourceRef dataSource) {}, + CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), + CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), + CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), + CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), + CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), + NULL); + + //testsyncempty(); +TODO: { + todo("testsync fails with 10 peers and staggered adds"); + testsyncmany("syncmany", test_directive, test_reason, 9, 10, 0, syncmany_add); +} + testsyncmany("v2syncmany", test_directive, test_reason, 9, 10, 2, syncmany_add); + testsync2p(); +} + +int secd_70_engine(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + /* custom keychain dir */ + secd_test_setup_temp_keychain("secd_70_engine", NULL); + + synctests(); + + return 0; +} diff --git a/Security/sec/securityd/Regressions/secd-70-otr-remote.c b/Security/sec/securityd/Regressions/secd-70-otr-remote.c new file mode 100644 index 00000000..1ef97963 --- /dev/null +++ b/Security/sec/securityd/Regressions/secd-70-otr-remote.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + +#include "secd_regressions.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "SOSCircle_regressions.h" +#include "SOSRegressionUtilities.h" +#include "SOSTestDataSource.h" +#include "SecOTRRemote.h" +#include "SOSAccount.h" + + +static void RegressionsLogError(CFErrorRef error) { + if (error == NULL) { + return; + } + CFDictionaryRef tempDictionary = CFErrorCopyUserInfo(error); + CFIndex errorCode = CFErrorGetCode(error); + CFStringRef errorDomain = CFErrorGetDomain(error); + CFStringRef errorString = CFDictionaryGetValue(tempDictionary, kCFErrorDescriptionKey); + CFErrorRef previousError = (CFErrorRef)CFDictionaryGetValue(tempDictionary, kCFErrorUnderlyingErrorKey); + if (previousError != NULL) { + RegressionsLogError(previousError); + } + char errorDomainStr[1024]; + char errorStringStr[1024]; + + CFStringGetCString(errorDomain, errorDomainStr, 1024, kCFStringEncodingUTF8); + CFStringGetCString(errorString, errorStringStr, 1024, kCFStringEncodingUTF8); + printf("OTR: %s (%ld) -- %s\n", errorDomainStr, errorCode, errorStringStr); + CFReleaseSafe(tempDictionary); +} + +static int kTestTestCount = 10; +static void tests(void) +{ + __block CFErrorRef testError = NULL; + + CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); + + CFStringRef circleName = CFSTR("Woot Circle"); + + /* DataSource */ + SOSDataSourceRef aliceDs = SOSTestDataSourceCreate(); + SOSDataSourceRef bobDs = SOSTestDataSourceCreate(); + + SOSDataSourceFactoryRef aliceDsf = SOSTestDataSourceFactoryCreate(); + SOSTestDataSourceFactoryAddDataSource(aliceDsf, circleName, aliceDs); + + SOSDataSourceFactoryRef bobDsf = SOSTestDataSourceFactoryCreate(); + SOSTestDataSourceFactoryAddDataSource(bobDsf, circleName, bobDs); + + CFDictionaryRef alice_gestalt = SOSCreatePeerGestaltFromName(CFSTR("Alice Device")); + CFDictionaryRef bob_gestalt = SOSCreatePeerGestaltFromName(CFSTR("Bob Device")); + + SOSAccountRef alice_account = SOSAccountCreate(kCFAllocatorDefault, alice_gestalt, aliceDsf); + SOSAccountRef bob_account = SOSAccountCreate(kCFAllocatorDefault, bob_gestalt, bobDsf); + + SOSAccountAssertUserCredentials(alice_account, CFSTR("alice"), cfpassword, &testError); + SOSAccountAssertUserCredentials(bob_account, CFSTR("bob"), cfpassword, &testError); + + CFReleaseNull(cfpassword); + + SOSAccountJoinCircles(alice_account, &testError); + SOSAccountJoinCircles(bob_account, &testError); + + CFDataRef alice_account_data = SOSAccountCopyEncodedData(alice_account, kCFAllocatorDefault, &testError); + CFDataRef bob_account_data = SOSAccountCopyEncodedData(bob_account, kCFAllocatorDefault, &testError); + + CFArrayRef alice_peers = SOSAccountCopyPeers(alice_account, &testError); + CFArrayRef bob_peers = SOSAccountCopyPeers(bob_account, &testError); + + SOSPeerInfoRef alice_peer_info = (SOSPeerInfoRef)CFArrayGetValueAtIndex(alice_peers, 0); + SOSPeerInfoRef bob_peer_info = (SOSPeerInfoRef)CFArrayGetValueAtIndex(bob_peers, 0); + + CFStringRef alice_peer_id = SOSPeerInfoGetPeerID(alice_peer_info); + CFStringRef bob_peer_id = SOSPeerInfoGetPeerID(bob_peer_info); + + CFDataRef alice_peer_external_form = CFStringCreateExternalRepresentation(kCFAllocatorDefault, alice_peer_id, kCFStringEncodingUTF8, '?'); + CFDataRef bob_peer_external_form = CFStringCreateExternalRepresentation(kCFAllocatorDefault, bob_peer_id, kCFStringEncodingUTF8, '?'); + + bool aliceReady = false; + bool bobReady = false; + + CFDataRef aliceSideSession = SecOTRSessionCreateRemote_internal(bob_account_data, bob_peer_external_form, alice_account_data, &testError); + RegressionsLogError(testError); + CFReleaseNull(testError); + + ok(aliceSideSession != NULL, "Make Alice side remote session"); + + CFDataRef bobSideSession = SecOTRSessionCreateRemote_internal(alice_account_data, alice_peer_external_form, bob_account_data, &testError); + RegressionsLogError(testError); + CFReleaseNull(testError); + + ok(bobSideSession != NULL, "Make Bob side remote session"); + + CFDataRef aliceSideSessionResult = NULL; + CFDataRef bobSideSessionResult = NULL; + CFDataRef aliceToBob = NULL; + CFDataRef bobToAlice = NULL; + + do { + bool aliceStatus = SecOTRSessionProcessPacketRemote(aliceSideSession, bobToAlice, &aliceSideSessionResult, &aliceToBob, &aliceReady, &testError); + ok (aliceStatus, "Alice sent packet OK"); + RegressionsLogError(testError); + CFReleaseNull(testError); + CFReleaseSafe(aliceSideSession); + aliceSideSession = aliceSideSessionResult; + + if (aliceReady) { + break; + } + + bool bobStatus = SecOTRSessionProcessPacketRemote(bobSideSession, aliceToBob, &bobSideSessionResult, &bobToAlice, &bobReady, &testError); + ok (bobStatus, "Bob sent packet OK"); + RegressionsLogError(testError); + CFReleaseNull(testError); + CFReleaseSafe(bobSideSession); + bobSideSession = bobSideSessionResult; + } while (1); + + ok(bobReady, "Bob finished negotiating at the same time as Alice."); + + CFReleaseNull(aliceSideSession); + CFReleaseNull(bobSideSession); + + SecOTRFIPurgeAllFromKeychain(&testError); + RegressionsLogError(testError); + CFReleaseNull(bob_peer_external_form); + CFReleaseNull(alice_peer_external_form); + CFReleaseNull(alice_account_data); + CFReleaseNull(bob_account_data); + CFReleaseNull(alice_peers); + CFReleaseNull(bob_peers); + CFReleaseNull(aliceSideSession); + CFReleaseNull(bobSideSession); + CFReleaseNull(testError); +} + +int secd_70_otr_remote(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/Security/sec/securityd/Regressions/secd_regressions.h b/Security/sec/securityd/Regressions/secd_regressions.h new file mode 100644 index 00000000..abeb040b --- /dev/null +++ b/Security/sec/securityd/Regressions/secd_regressions.h @@ -0,0 +1,48 @@ +/* + * 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 + +ONE_TEST(secd_01_items) +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_30_keychain_upgrade) //obsolete, needs updating +ONE_TEST(secd_31_keychain_bad) +ONE_TEST(secd_31_keychain_unreadable) +ONE_TEST(secd_50_account) +ONE_TEST(secd_51_account_inflate) +ONE_TEST(secd_52_account_changed) +ONE_TEST(secd_55_account_circle) +ONE_TEST(secd_55_account_incompatibility) +ONE_TEST(secd_56_account_apply) +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_61_account_leave_not_in_kansas_anymore) +ONE_TEST(secd_70_engine) +ONE_TEST(secd_70_engine_corrupt) +DISABLED_ONE_TEST(secd_70_otr_remote) diff --git a/Security/sec/securityd/Regressions/securityd_regressions.h b/Security/sec/securityd/Regressions/securityd_regressions.h new file mode 100644 index 00000000..f7e965fc --- /dev/null +++ b/Security/sec/securityd/Regressions/securityd_regressions.h @@ -0,0 +1,7 @@ +/* To add a test: + 1) add it here + 2) Add it as command line argument for SecurityTest.app in the Release and Debug schemes + */ +#include + +ONE_TEST(sd_10_policytree) diff --git a/Security/sec/securityd/SOSCloudCircleServer.c b/Security/sec/securityd/SOSCloudCircleServer.c new file mode 100644 index 00000000..8aa8d45f --- /dev/null +++ b/Security/sec/securityd/SOSCloudCircleServer.c @@ -0,0 +1,1190 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#if TARGET_OS_EMBEDDED || TARGET_IPHONE_SIMULATOR +#include +#else +#include + +// We need authorization, but that doesn't exist +// on sec built for desktop (iOS in a process) +// Define AuthorizationRef here to make SystemConfiguration work +// as if it's on iOS. +typedef const struct AuthorizationOpaqueRef * AuthorizationRef; +#endif + +#define SOSCKCSCOPE "sync" + +#define USE_SYSTEMCONFIGURATION_PRIVATE_HEADERS +#import + +#include + +static SOSCCAccountDataSourceFactoryBlock accountDataSourceOverride = NULL; + +bool SOSKeychainAccountSetFactoryForAccount(SOSCCAccountDataSourceFactoryBlock block) +{ + accountDataSourceOverride = Block_copy(block); + + return true; +} + +// +// Forward declared +// + +static void do_with_account(void (^action)(SOSAccountRef account)); +static void do_with_account_async(void (^action)(SOSAccountRef account)); + +// +// Constants +// +CFStringRef kSOSInternalAccessGroup = CFSTR("com.apple.security.sos"); + +CFStringRef kSOSAccountLabel = CFSTR("iCloud Keychain Account Meta-data"); + +static CFStringRef accountFileName = CFSTR("PersistedAccount.plist"); + +static CFDictionaryRef SOSItemCopyQueryForSyncItems(CFStringRef service, bool returnData) +{ + return CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecClass, kSecClassGenericPassword, + kSecAttrService, service, + kSecAttrAccessGroup, kSOSInternalAccessGroup, + kSecReturnData, returnData ? kCFBooleanTrue : kCFBooleanFalse, + NULL); +} + +CFDataRef SOSItemCopy(CFStringRef service, CFErrorRef* error) +{ + CFDictionaryRef query = SOSItemCopyQueryForSyncItems(service, true); + + CFDataRef result = NULL; + + OSStatus copyResult = SecItemCopyMatching(query, (CFTypeRef*) &result); + + CFReleaseNull(query); + + if (copyResult != noErr) { + SecError(copyResult, error, CFSTR("Error %@ reading for service '%@'"), result, service); + CFReleaseNull(result); + return NULL; + } + + if (!isData(result)) { + SOSCreateErrorWithFormat(kSOSErrorProcessingFailure, NULL, error, NULL, CFSTR("SecItemCopyMatching returned non-data in '%@'"), service); + CFReleaseNull(result); + return NULL; + } + + return result; +} + +static CFDataRef SOSKeychainCopySavedAccountData() +{ + CFErrorRef error = NULL; + CFDataRef accountData = SOSItemCopy(kSOSAccountLabel, &error); + if (!accountData) + secnotice("account", "Failed to load account: %@", error); + CFReleaseNull(error); + + return accountData; +} + +bool SOSItemUpdateOrAdd(CFStringRef service, CFStringRef accessibility, CFDataRef data, CFErrorRef *error) +{ + CFDictionaryRef query = SOSItemCopyQueryForSyncItems(service, false); + + CFDictionaryRef update = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kSecValueData, data, + kSecAttrAccessible, accessibility, + NULL); + OSStatus saveStatus = SecItemUpdate(query, update); + + if (errSecItemNotFound == saveStatus) { + CFMutableDictionaryRef add = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, query); + CFDictionaryForEach(update, ^(const void *key, const void *value) { + CFDictionaryAddValue(add, key, value); + }); + saveStatus = SecItemAdd(add, NULL); + CFReleaseNull(add); + } + + CFReleaseNull(query); + CFReleaseNull(update); + + return SecError(saveStatus, error, CFSTR("Error saving %@ to service '%@'"), data, service); +} + +static CFStringRef accountStatusFileName = CFSTR("accountStatus.plist"); +#include +#include +#include +#if 0 +static const uint8_t* ccder_decode_bool(bool* boolean, const uint8_t* der, const uint8_t *der_end) +{ + if (NULL == der) + return NULL; + + size_t payload_size = 0; + const uint8_t *payload = ccder_decode_tl(CCDER_BOOLEAN, &payload_size, der, der_end); + + if (NULL == payload || (der_end - payload) < 1 || payload_size != 1) { + return NULL; + } + + if (boolean) + *boolean = (*payload != 0); + + return payload + payload_size; +} +#endif + +bool SOSCCCircleIsOn_Artifact(void) { + bool circle_on = false; + CFDataRef accountStatus = NULL; + CFURLRef accountStatusFileURL = SecCopyURLForFileInKeychainDirectory(accountStatusFileName); + require_quiet(accountStatusFileURL && CFURLResourceIsReachable(accountStatusFileURL, NULL), xit); + accountStatus = (CFDataRef) CFPropertyListReadFromFile(accountStatusFileURL); + + if(isData(accountStatus)) { + size_t size = CFDataGetLength(accountStatus); + const uint8_t *der = CFDataGetBytePtr(accountStatus); + const uint8_t *der_p = der; + + const uint8_t *sequence_end; + der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der_p, der_p + size); + der_p = ccder_decode_bool(&circle_on, der_p, sequence_end); + (void) der_p; + } + +xit: + CFReleaseSafe(accountStatusFileURL); + CFReleaseSafe(accountStatus); + + return circle_on; +} + +#if 0 +static size_t ccder_sizeof_bool(bool value __unused, CFErrorRef *error) +{ + return ccder_sizeof(CCDER_BOOLEAN, 1); +} + + +static uint8_t* ccder_encode_bool(bool value, const uint8_t *der, uint8_t *der_end) +{ + uint8_t value_byte = value; + + return ccder_encode_tl(CCDER_BOOLEAN, 1, der, + ccder_encode_body(1, &value_byte, der, der_end)); +} +#endif + +static void SOSCCCircleIsOn_SetArtifact(bool account_on) { + static CFDataRef sLastSavedAccountStatus = NULL; + CFErrorRef saveError = NULL; + size_t der_size = ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, ccder_sizeof_bool(account_on, NULL)); + uint8_t der[der_size]; + uint8_t *der_end = der + der_size; + der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + ccder_encode_bool(account_on, der, der_end)); + + CFDataRef accountStatusAsData = CFDataCreate(kCFAllocatorDefault, der_end, der_size); + + require_quiet(accountStatusAsData, exit); + if (sLastSavedAccountStatus && CFEqual(sLastSavedAccountStatus, accountStatusAsData)) goto exit; + + CFURLRef accountStatusFileURL = SecCopyURLForFileInKeychainDirectory(accountStatusFileName); + CFPropertyListWriteToFile((CFPropertyListRef) accountStatusAsData, accountStatusFileURL); + CFReleaseSafe(accountStatusFileURL); + + CFReleaseNull(sLastSavedAccountStatus); + sLastSavedAccountStatus = accountStatusAsData; + accountStatusAsData = NULL; + +exit: + CFReleaseNull(saveError); + CFReleaseNull(accountStatusAsData); +} + +static void SOSCCCircleIsOn_UpdateArtifact(SOSCCStatus status) +{ + switch (status) { + case kSOSCCCircleAbsent: + case kSOSCCNotInCircle: + SOSCCCircleIsOn_SetArtifact(false); + break; + case kSOSCCInCircle: + case kSOSCCRequestPending: + SOSCCCircleIsOn_SetArtifact(true); + break; + case kSOSCCError: + default: + // do nothing + break; + } +} + +static void SOSKeychainAccountEnsureSaved(SOSAccountRef account) +{ + static CFDataRef sLastSavedAccountData = NULL; + + CFErrorRef saveError = NULL; + SOSCCCircleIsOn_UpdateArtifact(SOSAccountIsInCircles(account, NULL)); + + CFDataRef accountAsData = SOSAccountCopyEncodedData(account, kCFAllocatorDefault, &saveError); + + require_action_quiet(accountAsData, exit, secerror("Failed to transform account into data, error: %@", saveError)); + require_quiet(!CFEqualSafe(sLastSavedAccountData, accountAsData), exit); + + if (!SOSItemUpdateOrAdd(kSOSAccountLabel, kSecAttrAccessibleAlwaysThisDeviceOnly, accountAsData, &saveError)) { + secerror("Can't save account: %@", saveError); + goto exit; + } + + CFReleaseNull(sLastSavedAccountData); + sLastSavedAccountData = accountAsData; + accountAsData = NULL; + +exit: + CFReleaseNull(saveError); + CFReleaseNull(accountAsData); +} + + +/* + Stolen from keychain_sync.c + */ + +static bool clearAllKVS(CFErrorRef *error) +{ + return true; + __block bool result = false; + const uint64_t maxTimeToWaitInSeconds = 30ull * NSEC_PER_SEC; + dispatch_queue_t processQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0); + dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds); + + SOSCloudKeychainClearAll(processQueue, ^(CFDictionaryRef returnedValues, CFErrorRef cerror) + { + result = (cerror != NULL); + dispatch_semaphore_signal(waitSemaphore); + }); + + dispatch_semaphore_wait(waitSemaphore, finishTime); + dispatch_release(waitSemaphore); + + return result; +} + +static SOSAccountRef SOSKeychainAccountCreateSharedAccount(CFDictionaryRef our_gestalt) +{ + secdebug("account", "Created account"); + + CFDataRef savedAccount = SOSKeychainCopySavedAccountData(); + SOSAccountRef account = NULL; + SOSDataSourceFactoryRef factory = accountDataSourceOverride ? accountDataSourceOverride() + : SecItemDataSourceFactoryGetDefault(); + + if (savedAccount) { + CFErrorRef inflationError = NULL; + + account = SOSAccountCreateFromData(kCFAllocatorDefault, savedAccount, factory, &inflationError); + + if (account){ + SOSAccountUpdateGestalt(account, our_gestalt); + } + else + secerror("Got error inflating account: %@", inflationError); + CFReleaseNull(inflationError); + } + CFReleaseSafe(savedAccount); + + if (!account) { + account = SOSAccountCreate(kCFAllocatorDefault, our_gestalt, factory); + + if (!account) + secerror("Got NULL creating account"); + } + + return account; +} + +// +// Mark: Gestalt Handling +// + +static CFStringRef CopyModelName(void) +{ + static dispatch_once_t once; + static CFStringRef modelName = NULL; + dispatch_once(&once, ^{ +#if TARGET_OS_EMBEDDED || TARGET_IPHONE_SIMULATOR + modelName = MGCopyAnswer(kMGQDeviceName, NULL); +#else + modelName = ASI_CopyComputerModelName(FALSE); +#endif + if (modelName == NULL) + modelName = CFSTR("Unknown model"); + }); + return CFStringCreateCopy(kCFAllocatorDefault, modelName); +} + +static CFStringRef CopyComputerName(SCDynamicStoreRef store) +{ + CFStringRef deviceName = SCDynamicStoreCopyComputerName(store, NULL); + if (deviceName == NULL) { + deviceName = CFSTR("Unknown name"); + } + return deviceName; +} + +static bool _EngineMessageProtocolV2Enabled(void) +{ +#if DEBUG + //sudo rhr + static dispatch_once_t onceToken; + static bool v2_enabled = false; + dispatch_once(&onceToken, ^{ + CFTypeRef v2Pref = (CFNumberRef)CFPreferencesCopyValue(CFSTR("engineV2"), CFSTR("com.apple.security"), kCFPreferencesAnyUser, kCFPreferencesCurrentHost); + + if (v2Pref && CFGetTypeID(v2Pref) == CFBooleanGetTypeID()) { + v2_enabled = CFBooleanGetValue((CFBooleanRef)v2Pref); + secnotice("server", "Engine v2 : %s", v2_enabled ? "enabled":"disabled"); + } + CFReleaseSafe(v2Pref); + }); + + return v2_enabled; +#else + return false; +#endif +} + + +static CFDictionaryRef CFDictionaryCreateDeviceGestalt(SCDynamicStoreRef store, CFArrayRef keys, void *context) +{ + CFStringRef modelName = CopyModelName(); + CFStringRef computerName = CopyComputerName(store); + SInt32 version = _EngineMessageProtocolV2Enabled() ? kEngineMessageProtocolVersion : 0; + CFNumberRef protocolVersion = CFNumberCreate(0, kCFNumberSInt32Type, &version); + + + CFDictionaryRef gestalt = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + kPIUserDefinedDeviceName, computerName, + kPIDeviceModelName, modelName, + kPIMessageProtocolVersion, protocolVersion, + NULL); + CFReleaseSafe(modelName); + CFReleaseSafe(computerName); + CFReleaseSafe(protocolVersion); + + return gestalt; +} + +static void SOSCCProcessGestaltUpdate(SCDynamicStoreRef store, CFArrayRef keys, void *context) +{ + do_with_account(^(SOSAccountRef account) { + if(account){ + CFDictionaryRef gestalt = CFDictionaryCreateDeviceGestalt(store, keys, context); + if (SOSAccountUpdateGestalt(account, gestalt)) { + notify_post(kSOSCCCircleChangedNotification); + } + CFReleaseSafe(gestalt); + } + }); +} + + +static CFDictionaryRef CFDictionaryCreateGestaltAndRegisterForUpdate(dispatch_queue_t queue, void *info) +{ + SCDynamicStoreContext context = { .info = info }; + SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("com.apple.securityd.cloudcircleserver"), SOSCCProcessGestaltUpdate, &context); + CFStringRef computerKey = SCDynamicStoreKeyCreateComputerName(NULL); + CFArrayRef keys = NULL; + CFDictionaryRef gestalt = NULL; + + if (store == NULL || computerKey == NULL) { + goto done; + } + keys = CFArrayCreate(NULL, (const void **)&computerKey, 1, &kCFTypeArrayCallBacks); + if (keys == NULL) { + goto done; + } + gestalt = CFDictionaryCreateDeviceGestalt(store, keys, info); + SCDynamicStoreSetNotificationKeys(store, keys, NULL); + SCDynamicStoreSetDispatchQueue(store, queue); + +done: + if (store) CFRelease(store); + if (computerKey) CFRelease(computerKey); + if (keys) CFRelease(keys); + return gestalt; +} + +static void do_with_account(void (^action)(SOSAccountRef account)); +static void do_with_account_async(void (^action)(SOSAccountRef account)); + +static SOSAccountRef GetSharedAccount(void) { + static SOSAccountRef sSharedAccount = NULL; + static dispatch_once_t onceToken; + +#if !(TARGET_OS_EMBEDDED) + if(geteuid() == 0){ + secerror("Cannot inflate account object as root"); + return NULL; + } +#endif + + dispatch_once(&onceToken, ^{ + secdebug("account", "Account Creation start"); + + CFDictionaryRef gestalt = CFDictionaryCreateGestaltAndRegisterForUpdate(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); + + if (!gestalt) { +#if TARGET_OS_IPHONE && TARGET_IPHONE_SIMULATOR + gestalt = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, NULL); +#else + secerror("Didn't get machine gestalt! This is going to be ugly."); +#endif + } + + sSharedAccount = SOSKeychainAccountCreateSharedAccount(gestalt); + + SOSCCSetThisDeviceDefinitelyNotActiveInCircle(SOSAccountIsInCircles(sSharedAccount, NULL)); + + SOSAccountAddChangeBlock(sSharedAccount, ^(SOSCircleRef circle, + CFSetRef peer_additions, CFSetRef peer_removals, + CFSetRef applicant_additions, CFSetRef applicant_removals) { + CFErrorRef pi_error = NULL; + SOSPeerInfoRef me = SOSAccountGetMyPeerInCircle(sSharedAccount, circle, &pi_error); + if (!me) { + secerror("Error finding me for change: %@", pi_error); + } else { + if (SOSCircleHasPeer(circle, me, NULL) && CFSetGetCount(peer_additions) != 0) { + secnotice("updates", "Requesting Ensure Peer Registration."); + SOSCloudKeychainRequestEnsurePeerRegistration(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); + } + + if (CFSetContainsValue(peer_additions, me)) { + SOSCCSyncWithAllPeers(); + } + } + + CFReleaseNull(pi_error); + + if (CFSetGetCount(peer_additions) != 0 || + CFSetGetCount(peer_removals) != 0 || + CFSetGetCount(applicant_additions) != 0 || + CFSetGetCount(applicant_removals) != 0) { + + SOSCCSetThisDeviceDefinitelyNotActiveInCircle(SOSAccountIsInCircles(sSharedAccount, NULL)); + notify_post(kSOSCCCircleChangedNotification); + } + }); + + SOSCloudKeychainSetItemsChangedBlock(^CFArrayRef(CFDictionaryRef changes) { + CFRetainSafe(changes); + __block CFMutableArrayRef handledKeys = NULL; + do_with_account(^(SOSAccountRef account) { + CFStringRef changeDescription = SOSChangesCopyDescription(changes, false); + secdebug(SOSCKCSCOPE, "Received: %@", changeDescription); + CFReleaseSafe(changeDescription); + + CFErrorRef error = NULL; + handledKeys = SOSTransportDispatchMessages(account, changes, &error); + if (!handledKeys) { + secerror("Error handling updates: %@", error); + CFReleaseNull(error); + } + }); + CFReleaseSafe(changes); + return handledKeys; + }); + CFReleaseSafe(gestalt); + + SOSCloudKeychainRequestEnsurePeerRegistration(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); + }); + + + return sSharedAccount; +} + +static void do_with_account_dynamic(void (^action)(SOSAccountRef account), bool sync) { + SOSAccountRef account = GetSharedAccount(); + + if(account){ + dispatch_block_t do_action_and_save = ^{ + action(account); + SOSKeychainAccountEnsureSaved(account); + }; + + if (sync) { + dispatch_sync(SOSAccountGetQueue(account), do_action_and_save); + } else { + dispatch_async(SOSAccountGetQueue(account), do_action_and_save); + } + } +} + +__unused static void do_with_account_async(void (^action)(SOSAccountRef account)) { + do_with_account_dynamic(action, false); +} + +static void do_with_account(void (^action)(SOSAccountRef account)) { + do_with_account_dynamic(action, true); +} + +#if TARGET_IPHONE_SIMULATOR +#define MKBDeviceUnlockedSinceBoot() true +#endif + +static bool do_if_after_first_unlock(CFErrorRef *error, dispatch_block_t action) +{ + bool beenUnlocked = false; + require_quiet(SecAKSGetHasBeenUnlocked(&beenUnlocked, error), fail); + + require_action_quiet(beenUnlocked, fail, + SOSCreateErrorWithFormat(kSOSErrorNotReady, NULL, error, NULL, + CFSTR("Keybag never unlocked, ask after first unlock"))); + + action(); + return true; + +fail: + return false; +} + +static bool do_with_account_if_after_first_unlock(CFErrorRef *error, bool (^action)(SOSAccountRef account, CFErrorRef* error)) +{ + __block bool action_result = false; + +#if !(TARGET_OS_EMBEDDED) + if(geteuid() == 0){ + secerror("Cannot inflate account object as root"); + return false; + } +#endif + return do_if_after_first_unlock(error, ^{ + do_with_account(^(SOSAccountRef account) { + action_result = action(account, error); + }); + + }) && action_result; +} + +static bool do_with_account_while_unlocked(CFErrorRef *error, bool (^action)(SOSAccountRef account, CFErrorRef* error)) +{ + __block bool action_result = false; + +#if !(TARGET_OS_EMBEDDED) + if(geteuid() == 0){ + secerror("Cannot inflate account object as root"); + return false; + } +#endif + + return SecAKSDoWhileUserBagLocked(error, ^{ + do_with_account(^(SOSAccountRef account) { + action_result = action(account, error); + }); + + }) && action_result; +} + +SOSAccountRef SOSKeychainAccountGetSharedAccount() +{ + __block SOSAccountRef result = NULL; + + do_with_account(^(SOSAccountRef account) { + result = account; + }); + + return result; +} + +// +// Mark: Credential processing +// + + +bool SOSCCTryUserCredentials_Server(CFStringRef user_label, CFDataRef user_password, CFErrorRef *error) +{ + return do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + return SOSAccountTryUserCredentials(account, user_label, user_password, block_error); + }); +} + +#define kWAIT2MINID "EFRESH" + +static bool EnsureFreshParameters(SOSAccountRef account, CFErrorRef *error) { + dispatch_semaphore_t wait_for = dispatch_semaphore_create(0); + dispatch_retain(wait_for); // Both this scope and the block own it. + + CFMutableArrayRef keysToGet = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFArrayAppendValue(keysToGet, kSOSKVSKeyParametersKey); + + __block CFDictionaryRef valuesToUpdate = NULL; + __block bool success = false; + + secnoticeq("fresh", "%s calling SOSCloudKeychainSynchronizeAndWait", kWAIT2MINID); + + SOSCloudKeychainSynchronizeAndWait(keysToGet, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(CFDictionaryRef returnedValues, CFErrorRef sync_error) { + + if (sync_error) { + secerrorq("%s SOSCloudKeychainSynchronizeAndWait: %@", kWAIT2MINID, sync_error); + if (error) { + *error = sync_error; + CFRetainSafe(*error); + } + } else { + secnoticeq("fresh", "%s returned from call; in callback to SOSCloudKeychainSynchronizeAndWait: results: %@", kWAIT2MINID, returnedValues); + valuesToUpdate = returnedValues; + CFRetainSafe(valuesToUpdate); + success = true; + } + + dispatch_semaphore_signal(wait_for); + dispatch_release(wait_for); + }); + + dispatch_semaphore_wait(wait_for, DISPATCH_TIME_FOREVER); + // TODO: Maybe we timeout here... used to dispatch_time(DISPATCH_TIME_NOW, 30ull * NSEC_PER_SEC)); + dispatch_release(wait_for); + CFMutableArrayRef handledKeys = NULL; + if ((valuesToUpdate) && (account)) { + handledKeys = SOSTransportDispatchMessages(account, valuesToUpdate, error); + if (!handledKeys) { + secerrorq("%s Freshness update failed: %@", kWAIT2MINID, error ? *error : NULL); + success = false; + } + } + CFReleaseNull(handledKeys); + CFReleaseNull(valuesToUpdate); + CFReleaseNull(keysToGet); + + return success; +} + +static bool Flush(CFErrorRef *error) { + __block bool success = false; + + dispatch_semaphore_t wait_for = dispatch_semaphore_create(0); + dispatch_retain(wait_for); // Both this scope and the block own it. + + secnotice("flush", "Starting"); + + SOSCloudKeychainFlush(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(CFDictionaryRef returnedValues, CFErrorRef sync_error) { + success = (sync_error == NULL); + if (error) { + CFRetainAssign(*error, sync_error); + } + + dispatch_semaphore_signal(wait_for); + dispatch_release(wait_for); + }); + + dispatch_semaphore_wait(wait_for, DISPATCH_TIME_FOREVER); + dispatch_release(wait_for); + + secnotice("flush", "Returned %s", success? "Success": "Failure"); + + return success; +} + +bool SOSCCSetUserCredentials_Server(CFStringRef user_label, CFDataRef user_password, CFErrorRef *error) +{ + secnotice("updates", "Setting credentials for %@", user_label); // TODO: remove this notice + bool result = do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + if (!EnsureFreshParameters(account, block_error)) { + return false; + } + if (!SOSAccountAssertUserCredentials(account, user_label, user_password, block_error)) { + secnotice("updates", "EnsureFreshParameters/SOSAccountAssertUserCredentials error: %@", *block_error); + return false; + } + return true; + }); + + return result && Flush(error); +} + +bool SOSCCCanAuthenticate_Server(CFErrorRef *error) +{ + bool result = do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + return SOSAccountGetPrivateCredential(account, block_error) != NULL; + }); + + if (!result && error && *error && CFErrorGetDomain(*error) == kSOSErrorDomain) { + CFIndex code = CFErrorGetCode(*error); + if (code == kSOSErrorPrivateKeyAbsent || code == kSOSErrorPublicKeyAbsent) { + CFReleaseNull(*error); + } + } + + return result; +} + +bool SOSCCPurgeUserCredentials_Server(CFErrorRef *error) +{ + return do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + SOSAccountPurgePrivateCredential(account); + return true; + }); +} + + +#if USE_BETTER +static bool sAccountInCircleCache = false; + +static void do_with_not_in_circle_bool_queue(bool start_account, dispatch_block_t action) +{ + static dispatch_queue_t account_start_queue; + static dispatch_queue_t not_in_circle_queue; + static bool account_started = false; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + not_in_circle_queue = dispatch_queue_create("nis queue", DISPATCH_QUEUE_SERIAL); + account_start_queue = dispatch_queue_create("init nis queue", DISPATCH_QUEUE_SERIAL);; + account_started = false; + }); + + __block bool done = false; + dispatch_sync(not_in_circle_queue, ^{ + if (account_started) { + done = true; + action(); + } + }); + + if (!done && start_account) { + dispatch_sync(account_start_queue, ^{ + __block bool do_start = false; + dispatch_sync(not_in_circle_queue, ^{ + do_start = !account_started; + account_started = true; + }); + if (do_start) + SOSCCThisDeviceIsInCircle(NULL); // Inflate account. + }); + + dispatch_sync(not_in_circle_queue, action); + } +} +#endif + +bool SOSCCThisDeviceDefinitelyNotActiveInCircle() +{ + return !SOSCCCircleIsOn_Artifact(); +#if USE_BETTER + __block bool result = false; + do_with_not_in_circle_bool_queue(true, ^{ + result = sAccountInCircleCache; + }); + + return result; +#endif +} + +void SOSCCSetThisDeviceDefinitelyNotActiveInCircle(SOSCCStatus currentStatus) +{ + SOSCCCircleIsOn_UpdateArtifact(currentStatus); +#if USE_BETTER + do_with_not_in_circle_bool_queue(false, ^{ + sAccountInCircleCache = notActive; + }); +#endif +} + + +SOSCCStatus SOSCCThisDeviceIsInCircle_Server(CFErrorRef *error) +{ + __block SOSCCStatus status; + + return do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + status = SOSAccountIsInCircles(account, block_error); + return true; + }) ? status : kSOSCCError; +} + +bool SOSCCRequestToJoinCircle_Server(CFErrorRef* error) +{ + __block bool result = true; + + return do_with_account_while_unlocked(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + result = SOSAccountJoinCircles(account, block_error); + return result; + }); +} + +bool SOSCCRequestToJoinCircleAfterRestore_Server(CFErrorRef* error) +{ + __block bool result = true; + bool returned = false; + returned = do_with_account_while_unlocked(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + SOSAccountEnsurePeerRegistration(account, block_error); + result = SOSAccountJoinCirclesAfterRestore(account, block_error); + return result; + }); + return returned; + +} + +bool SOSCCRequestEnsureFreshParameters_Server(CFErrorRef* error) +{ + __block bool result = true; + bool returned = false; + returned = do_with_account_while_unlocked(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + result = EnsureFreshParameters(account, NULL); + return result; + }); + return returned; +} + +CFStringRef SOSCCRequestDeviceID_Server(CFErrorRef *error) +{ + __block CFStringRef result = NULL; + + (void) do_with_account_while_unlocked(error, ^bool(SOSAccountRef account, CFErrorRef *error) { + result = SOSAccountGetDeviceID(account, error); + return (!isNull(result)); + }); + return result; +} + +bool SOSCCSetDeviceID_Server(CFStringRef IDS, CFErrorRef *error){ + __block bool result = true; + + return do_with_account_while_unlocked(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + result = SOSAccountSetMyDSID(account, IDS, block_error); + return result; + }); + +} +bool SOSCCResetToOffering_Server(CFErrorRef* error) +{ + __block bool result = true; + + return do_with_account_while_unlocked(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + clearAllKVS(NULL); + result = SOSAccountResetToOffering(account, block_error); + return result; + }); + +} + +bool SOSCCResetToEmpty_Server(CFErrorRef* error) +{ + __block bool result = true; + + return do_with_account_while_unlocked(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + result = SOSAccountResetToEmpty(account, block_error); + return result; + }); + +} + +bool SOSCCRemoveThisDeviceFromCircle_Server(CFErrorRef* error) +{ + __block bool result = true; + + return do_with_account_while_unlocked(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + result = SOSAccountLeaveCircles(account, block_error); + return result; + }); +} + +bool SOSCCBailFromCircle_Server(uint64_t limit_in_seconds, CFErrorRef* error) +{ + __block bool result = true; + + return do_with_account_while_unlocked(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + result = SOSAccountBail(account, limit_in_seconds, block_error); + return result; + }); + +} + +CFArrayRef SOSCCCopyApplicantPeerInfo_Server(CFErrorRef* error) +{ + __block CFArrayRef result = NULL; + + (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + result = SOSAccountCopyApplicants(account, block_error); + return result != NULL; + }); + + return result; +} + +CFArrayRef SOSCCCopyGenerationPeerInfo_Server(CFErrorRef* error) +{ + __block CFArrayRef result = NULL; + + (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + result = SOSAccountCopyGeneration(account, block_error); + return result != NULL; + }); + + return result; +} + +CFArrayRef SOSCCCopyValidPeerPeerInfo_Server(CFErrorRef* error) +{ + __block CFArrayRef result = NULL; + + (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + result = SOSAccountCopyValidPeers(account, block_error); + return result != NULL; + }); + + return result; +} + +bool SOSCCValidateUserPublic_Server(CFErrorRef* error) +{ + __block bool result = NULL; + + (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + result = SOSValidateUserPublic(account, block_error); + return result; + }); + + return result; +} + +CFArrayRef SOSCCCopyNotValidPeerPeerInfo_Server(CFErrorRef* error) +{ + __block CFArrayRef result = NULL; + + (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + result = SOSAccountCopyNotValidPeers(account, block_error); + return result != NULL; + }); + + return result; +} + +CFArrayRef SOSCCCopyRetirementPeerInfo_Server(CFErrorRef* error) +{ + __block CFArrayRef result = NULL; + + (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + result = SOSAccountCopyRetired(account, block_error); + return result != NULL; + }); + + return result; +} + +bool SOSCCAcceptApplicants_Server(CFArrayRef applicants, CFErrorRef* error) +{ + __block bool result = true; + return do_with_account_while_unlocked(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + result = SOSAccountAcceptApplicants(account, applicants, block_error); + return result; + }); + +} + +bool SOSCCRejectApplicants_Server(CFArrayRef applicants, CFErrorRef* error) +{ + __block bool result = true; + return do_with_account_while_unlocked(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + result = SOSAccountRejectApplicants(account, applicants, block_error); + return result; + }); +} + +CFArrayRef SOSCCCopyPeerPeerInfo_Server(CFErrorRef* error) +{ + __block CFArrayRef result = NULL; + + (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + result = SOSAccountCopyPeers(account, block_error); + return result != NULL; + }); + + return result; +} + +CFArrayRef SOSCCCopyConcurringPeerPeerInfo_Server(CFErrorRef* error) +{ + __block CFArrayRef result = NULL; + + (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + result = SOSAccountCopyConcurringPeers(account, block_error); + return result != NULL; + }); + + return result; +} + +CFStringRef SOSCCCopyIncompatibilityInfo_Server(CFErrorRef* error) +{ + __block CFStringRef result = NULL; + + (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + result = SOSAccountCopyIncompatibilityInfo(account, block_error); + return result != NULL; + }); + + return result; +} + +enum DepartureReason SOSCCGetLastDepartureReason_Server(CFErrorRef* error) +{ + __block enum DepartureReason result = kSOSDepartureReasonError; + + (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + result = SOSAccountGetLastDepartureReason(account, block_error); + return result != kSOSDepartureReasonError; + }); + + return result; +} + + +bool SOSCCProcessEnsurePeerRegistration_Server(CFErrorRef* error) +{ + secnotice("updates", "Request for registering peers"); + return do_with_account_while_unlocked(error, ^bool(SOSAccountRef account, CFErrorRef *error) { + return SOSAccountEnsurePeerRegistration(account, error); + }); +} + +SyncWithAllPeersReason SOSCCProcessSyncWithAllPeers_Server(CFErrorRef* error) +{ + /* + #define kIOReturnLockedRead iokit_common_err(0x2c3) // device read locked + #define kIOReturnLockedWrite iokit_common_err(0x2c4) // device write locked + */ + __block SyncWithAllPeersReason result = kSyncWithAllPeersSuccess; + CFErrorRef action_error = NULL; + + if (!do_with_account_while_unlocked(&action_error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + CFErrorRef localError = NULL; + if (!SOSAccountSyncWithAllPeers(account, &localError)) { + secerror("sync with all peers failed: %@", localError); + CFReleaseSafe(localError); + // This isn't a device-locked error, but returning false will + // have CloudKeychainProxy ask us to try sync again after next unlock + result = kSyncWithAllPeersOtherFail; + return false; + } + return true; + })) { + if (action_error) { + if (SecErrorGetOSStatus(action_error) == errSecInteractionNotAllowed) { + secnotice("updates", "SOSAccountSyncWithAllPeers failed because device is locked; letting CloudKeychainProxy know"); + result = kSyncWithAllPeersLocked; // tell CloudKeychainProxy to call us back when device unlocks + CFReleaseNull(action_error); + } else { + secerror("Unexpected error: %@", action_error); + } + + if (error && *error == NULL) { + *error = action_error; + action_error = NULL; + } + + CFReleaseNull(action_error); + } + } + + return result; +} + +void SOSCCSyncWithAllPeers(void) +{ + SOSCloudKeychainRequestSyncWithAllPeers(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); +} + +CF_RETURNS_RETAINED CFArrayRef SOSCCHandleUpdateKeyParameter(CFDictionaryRef updates) +{ + CFArrayRef result = NULL; + SOSAccountRef account = SOSKeychainAccountGetSharedAccount(); //HACK to make sure itemsChangedBlock is set + (account) ? (result = SOSCloudKeychainHandleUpdateKeyParameter(updates)) : (result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault)); + return result; +} + +CF_RETURNS_RETAINED CFArrayRef SOSCCHandleUpdateCircle(CFDictionaryRef updates) +{ + CFArrayRef result = NULL; + SOSAccountRef account = SOSKeychainAccountGetSharedAccount(); //HACK to make sure itemsChangedBlock is set + (account) ? (result = SOSCloudKeychainHandleUpdateKeyParameter(updates)) : (result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault)); + return result; +} + +CF_RETURNS_RETAINED CFArrayRef SOSCCHandleUpdateMessage(CFDictionaryRef updates) +{ + CFArrayRef result = NULL; + SOSAccountRef account = SOSKeychainAccountGetSharedAccount(); //HACK to make sure itemsChangedBlock is set + (account) ? (result = SOSCloudKeychainHandleUpdateKeyParameter(updates)) : (result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault)); + return result; +} + + diff --git a/Security/sec/securityd/SOSCloudCircleServer.h b/Security/sec/securityd/SOSCloudCircleServer.h new file mode 100644 index 00000000..8acce8a3 --- /dev/null +++ b/Security/sec/securityd/SOSCloudCircleServer.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef _SECURITY_SOSCLOUDCIRCLESERVER_H_ +#define _SECURITY_SOSCLOUDCIRCLESERVER_H_ + +#include +#include + + +__BEGIN_DECLS + +// +// MARK: Server versions of our SPI +// +bool SOSCCTryUserCredentials_Server(CFStringRef user_label, CFDataRef user_password, CFErrorRef *error); +bool SOSCCSetUserCredentials_Server(CFStringRef user_label, CFDataRef user_password, CFErrorRef *error); +bool SOSCCCanAuthenticate_Server(CFErrorRef *error); +bool SOSCCPurgeUserCredentials_Server(CFErrorRef *error); + +SOSCCStatus SOSCCThisDeviceIsInCircle_Server(CFErrorRef *error); +bool SOSCCRequestToJoinCircle_Server(CFErrorRef* error); +bool SOSCCRequestToJoinCircleAfterRestore_Server(CFErrorRef* error); +CFStringRef SOSCCRequestDeviceID_Server(CFErrorRef *error); +bool SOSCCSetDeviceID_Server(CFStringRef IDS, CFErrorRef *error); +bool SOSCCRemoveThisDeviceFromCircle_Server(CFErrorRef* error); +bool SOSCCBailFromCircle_Server(uint64_t limit_in_seconds, CFErrorRef* error); +bool SOSCCRequestEnsureFreshParameters_Server(CFErrorRef* error); + +CFArrayRef SOSCCCopyGenerationPeerInfo_Server(CFErrorRef* error); +CFArrayRef SOSCCCopyApplicantPeerInfo_Server(CFErrorRef* error); +CFArrayRef SOSCCCopyValidPeerPeerInfo_Server(CFErrorRef* error); +bool SOSCCValidateUserPublic_Server(CFErrorRef* error); + +CFArrayRef SOSCCCopyNotValidPeerPeerInfo_Server(CFErrorRef* error); +CFArrayRef SOSCCCopyRetirementPeerInfo_Server(CFErrorRef* error); +bool SOSCCRejectApplicants_Server(CFArrayRef applicants, CFErrorRef* error); +bool SOSCCAcceptApplicants_Server(CFArrayRef applicants, CFErrorRef* error); + +CFArrayRef SOSCCCopyPeerPeerInfo_Server(CFErrorRef* error); +CFArrayRef SOSCCCopyConcurringPeerPeerInfo_Server(CFErrorRef* error); + +bool SOSCCResetToOffering_Server(CFErrorRef* error); +bool SOSCCResetToEmpty_Server(CFErrorRef* error); + +CFStringRef SOSCCCopyIncompatibilityInfo_Server(CFErrorRef* error); +enum DepartureReason SOSCCGetLastDepartureReason_Server(CFErrorRef* error); + +bool SOSCCProcessEnsurePeerRegistration_Server(CFErrorRef* error); +SyncWithAllPeersReason SOSCCProcessSyncWithAllPeers_Server(CFErrorRef* error); + +// +// MARK: Internal kicks. +// +CF_RETURNS_RETAINED CFArrayRef SOSCCHandleUpdateKeyParameter(CFDictionaryRef updates); +CF_RETURNS_RETAINED CFArrayRef SOSCCHandleUpdateCircle(CFDictionaryRef updates); +CF_RETURNS_RETAINED CFArrayRef SOSCCHandleUpdateMessage(CFDictionaryRef updates); + + +// Expected to be called when the data source changes. +void SOSCCSyncWithAllPeers(void); +void SOSCCAddSyncablePeerBlock(CFStringRef ds_name, SOSAccountSyncablePeersBlock changeBlock); +dispatch_queue_t SOSCCGetAccountQueue(void); + + +// Internal careful questioning. +bool SOSCCThisDeviceDefinitelyNotActiveInCircle(void); +void SOSCCSetThisDeviceDefinitelyNotActiveInCircle(SOSCCStatus currentStatus); + +// +// MARK: Internal access to local account for tests. +// +typedef SOSDataSourceFactoryRef (^SOSCCAccountDataSourceFactoryBlock)(); + +SOSAccountRef SOSKeychainAccountGetSharedAccount(void); +bool SOSKeychainAccountSetFactoryForAccount(SOSCCAccountDataSourceFactoryBlock factory); + +// +// MARK: Testing operations, dangerous to call in normal operation. +// +bool SOSKeychainSaveAccountDataAndPurge(CFErrorRef *error); + + +// +// MARK: Constants for where we store persistent information in the keychain +// + +extern CFStringRef kSOSInternalAccessGroup; + +extern CFStringRef kSOSAccountLabel; +extern CFStringRef kSOSPeerDataLabel; + +CFDataRef SOSItemCopy(CFStringRef label, CFErrorRef* error); +bool SOSItemUpdateOrAdd(CFStringRef label, CFStringRef accessibility, CFDataRef data, CFErrorRef *error); + +bool SOSCCCircleIsOn_Artifact(void); + +__END_DECLS + +#endif diff --git a/sec/securityd/SecCAIssuerCache.c b/Security/sec/securityd/SecCAIssuerCache.c similarity index 99% rename from sec/securityd/SecCAIssuerCache.c rename to Security/sec/securityd/SecCAIssuerCache.c index 685b73e2..4bc1ce11 100644 --- a/sec/securityd/SecCAIssuerCache.c +++ b/Security/sec/securityd/SecCAIssuerCache.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,10 +17,9 @@ * 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@ * - * Created by Michael Brouwer on 6/17/11. */ /* diff --git a/sec/securityd/SecCAIssuerCache.h b/Security/sec/securityd/SecCAIssuerCache.h similarity index 94% rename from sec/securityd/SecCAIssuerCache.h rename to Security/sec/securityd/SecCAIssuerCache.h index 460b7533..d22fd6b4 100644 --- a/sec/securityd/SecCAIssuerCache.h +++ b/Security/sec/securityd/SecCAIssuerCache.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,10 +17,9 @@ * 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@ * - * Created by Michael Brouwer on 6/17/11. */ /*! diff --git a/sec/securityd/SecCAIssuerRequest.c b/Security/sec/securityd/SecCAIssuerRequest.c similarity index 97% rename from sec/securityd/SecCAIssuerRequest.c rename to Security/sec/securityd/SecCAIssuerRequest.c index d2e8af02..e0cf2e54 100644 --- a/sec/securityd/SecCAIssuerRequest.c +++ b/Security/sec/securityd/SecCAIssuerRequest.c @@ -2,22 +2,21 @@ * SecCAIssuerRequest.c * Security * - * Created by Michael Brouwer on 9/17/09. - * Copyright (c) 2009-2011 Apple Inc.. All Rights Reserved. + * Copyright (c) 2009-2014 Apple Inc.. All Rights Reserved. * */ /* - * Copyright (c) 2009-2011 Apple Inc. All Rights Reserved. + * Copyright (c) 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, @@ -25,7 +24,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@ */ diff --git a/Security/sec/securityd/SecCAIssuerRequest.h b/Security/sec/securityd/SecCAIssuerRequest.h new file mode 100644 index 00000000..01034021 --- /dev/null +++ b/Security/sec/securityd/SecCAIssuerRequest.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2009-2010,2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include +#include + +bool SecCAIssuerCopyParents(SecCertificateRef certificate, + dispatch_queue_t queue, void *context, void (*callback)(void *, CFArrayRef)); diff --git a/sec/securityd/SecDbItem.c b/Security/sec/securityd/SecDbItem.c similarity index 80% rename from sec/securityd/SecDbItem.c rename to Security/sec/securityd/SecDbItem.c index 34ec0b5c..077f0d48 100644 --- a/sec/securityd/SecDbItem.c +++ b/Security/sec/securityd/SecDbItem.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,17 +17,18 @@ * 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@ */ /* * SecDbItem.c - CoreFoundation-based constants and functions representing * database items (certificates, keys, identities, and passwords.) - * Created by Michael Brouwer on 11/15/12. */ #include +#include +#include #include #include #include @@ -37,6 +38,8 @@ #include #include #include +#include +#include // MARK: type converters @@ -231,7 +234,7 @@ CFMutableDictionaryRef SecDbItemCopyPListWithMask(SecDbItemRef item, CFOptionFla if (!CFEqual(kCFNull, value)) { CFDictionarySetValue(dict, desc->name, value); } else if (desc->flags & kSecDbNotNullFlag) { - SecError(errSecInternal, error, CFSTR("attribute %@ has NULL value"), desc->name); + SecError(errSecDecode, error, CFSTR("attribute %@ has NULL value"), desc->name); secerror("%@", error ? *error : (CFErrorRef)CFSTR("error == NULL")); CFReleaseNull(dict); break; @@ -272,57 +275,68 @@ static CFDataRef SecDbItemCopySHA1(SecDbItemRef item, CFErrorRef *error) { return SecDbItemCopyDigestWithMask(item, kSecDbInHashFlag, error); } -static CFDataRef SecDbItemCopyUnencryptedData(SecDbItemRef item, CFErrorRef *error) { - return SecDbItemCopyDERWithMask(item, kSecDbInCryptoDataFlag, error); -} - -static keyclass_t SecDbItemParseKeyclass(CFTypeRef value, CFErrorRef *error) { - if (!isString(value)) { - SecError(errSecParam, error, CFSTR("accessible attribute %@ not a string"), value); - } else if (CFEqual(value, kSecAttrAccessibleWhenUnlocked)) { - return key_class_ak; - } else if (CFEqual(value, kSecAttrAccessibleAfterFirstUnlock)) { - return key_class_ck; - } else if (CFEqual(value, kSecAttrAccessibleAlways)) { - return key_class_dk; - } else if (CFEqual(value, kSecAttrAccessibleWhenUnlockedThisDeviceOnly)) { - return key_class_aku; - } else if (CFEqual(value, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly)) { - return key_class_cku; - } else if (CFEqual(value, kSecAttrAccessibleAlwaysThisDeviceOnly)) { - return key_class_dku; - } else { - SecError(errSecParam, error, CFSTR("accessible attribute %@ unknown"), value); +SecAccessControlRef SecDbItemCopyAccessControl(SecDbItemRef item, CFErrorRef *error) { + SecAccessControlRef accc = NULL; + SecAccessControlRef pdmn = NULL; + CFTypeRef acccData = SecDbItemGetValue(item, SecDbClassAttrWithKind(item->class, kSecDbAccessControlAttr, error), error); + CFTypeRef pdmnValue = SecDbItemGetValue(item, SecDbClassAttrWithKind(item->class, kSecDbAccessAttr, error), error); + if (!acccData || !pdmnValue) + return NULL; + if (!CFEqual(acccData, kCFNull)) { + accc = SecAccessControlCreateFromData(CFGetAllocator(item), acccData, error); + if (!accc) + return NULL; } - return 0; -} - -keyclass_t SecDbItemGetKeyclass(SecDbItemRef item, CFErrorRef *error) { - if (!item->keyclass) { - const SecDbAttr *desc = SecDbClassAttrWithKind(item->class, kSecDbAccessAttr, error); - if (desc) { - CFTypeRef value = SecDbItemGetValue(item, desc, error); - if (value) { - item->keyclass = SecDbItemParseKeyclass(value, error); + if (!CFEqual(pdmnValue, kCFNull)) { + pdmn = SecAccessControlCreateWithFlags(CFGetAllocator(item), pdmnValue, 0, error); + if (!pdmn) { + CFReleaseSafe(accc); + return NULL; + } + } + if (accc && pdmn) { + CFTypeRef acccProt = SecAccessControlGetProtection(accc); + CFTypeRef pdmnProt = SecAccessControlGetProtection(pdmn); + if (!acccProt || !pdmnProt || !CFEqual(acccProt, pdmnProt)) { + secerror("SecDbItemCopyAccessControl accc %@ != pdmn %@, setting pdmn to accc value", acccProt, pdmnProt); + __security_simulatecrash(CFSTR("Corrupted item on decrypt accc != pdmn"), __sec_exception_code_CorruptItem); + // Setting pdmn to accc prot value. + if (!SecDbItemSetValue(item, SecDbClassAttrWithKind(item->class, kSecDbAccessAttr, error), acccProt, error)) { + // Fixing the kSecDbAccessAttr failed, return the error. + CFReleaseNull(accc); } } + CFReleaseNull(pdmn); + } else if (!accc) { + accc = pdmn; } - return item->keyclass; + return accc; +} + +void SecDbItemSetCredHandle(SecDbItemRef item, CFTypeRef cred_handle) { + CFRetainAssign(item->credHandle, cred_handle); +} + +void SecDbItemSetCallerAccessGroups(SecDbItemRef item, CFArrayRef caller_access_groups) { + CFRetainAssign(item->callerAccessGroups, caller_access_groups); } static CFDataRef SecDbItemCopyEncryptedData(SecDbItemRef item, CFErrorRef *error) { CFDataRef edata = NULL; - CFDataRef plain = SecDbItemCopyUnencryptedData(item, error); - if (plain) { - keyclass_t keyclass = SecDbItemGetKeyclass(item, error); - if (keyclass) { - if (ks_encrypt_data(item->keybag, keyclass, plain, &edata, error)) { + CFMutableDictionaryRef attributes = SecDbItemCopyPListWithMask(item, kSecDbInCryptoDataFlag, error); + CFMutableDictionaryRef auth_attributes = SecDbItemCopyPListWithMask(item, kSecDbInAuthenticatedDataFlag, error); + if (attributes || auth_attributes) { + SecAccessControlRef access_control = SecDbItemCopyAccessControl(item, error); + if (access_control) { + if (ks_encrypt_data(item->keybag, access_control, &item->credHandle, attributes, auth_attributes, &edata, error)) { item->_edataState = kSecDbItemEncrypting; } else { seccritical("ks_encrypt_data (db): failed: %@", error ? *error : (CFErrorRef)CFSTR("")); } + CFRelease(access_control); } - CFRelease(plain); + CFReleaseSafe(attributes); + CFReleaseSafe(auth_attributes); } return edata; @@ -331,19 +345,25 @@ static CFDataRef SecDbItemCopyEncryptedData(SecDbItemRef item, CFErrorRef *error CFDataRef SecDbItemCopyEncryptedDataToBackup(SecDbItemRef item, uint64_t handle, CFErrorRef *error) { CFDataRef edata = NULL; keybag_handle_t keybag = (keybag_handle_t)handle; - CFDataRef plain = SecDbItemCopyUnencryptedData(item, error); - if (plain) { - keyclass_t keyclass = SecDbItemGetKeyclass(item, error); - if (keyclass) { - if (!ks_encrypt_data(keybag, keyclass, plain, &edata, error)) + CFMutableDictionaryRef attributes = SecDbItemCopyPListWithMask(item, kSecDbInCryptoDataFlag, error); + CFMutableDictionaryRef auth_attributes = SecDbItemCopyPListWithMask(item, kSecDbInAuthenticatedDataFlag, error); + if (attributes || auth_attributes) { + SecAccessControlRef access_control = SecDbItemCopyAccessControl(item, error); + if (access_control) { + if (ks_encrypt_data(keybag, access_control, &item->credHandle, attributes, auth_attributes, &edata, error)) { + item->_edataState = kSecDbItemEncrypting; + } else { seccritical("ks_encrypt_data (db): failed: %@", error ? *error : (CFErrorRef)CFSTR("")); + } + CFRelease(access_control); } - CFRelease(plain); + CFReleaseSafe(attributes); + CFReleaseSafe(auth_attributes); } return edata; } -static bool SecDbItemEnsureDecrypted(SecDbItemRef item, CFErrorRef *error) { +bool SecDbItemEnsureDecrypted(SecDbItemRef item, CFDataRef *authNeeded, CFTypeRef *credHandle, CFErrorRef *error) { // If we haven't yet decrypted the item, make sure we do so now bool result = true; @@ -355,7 +375,11 @@ static bool SecDbItemEnsureDecrypted(SecDbItemRef item, CFErrorRef *error) { return SecError(errSecInternal, error, CFSTR("state= encrypted but edata is NULL")); // Decrypt calls set value a bunch of times which clears our edata and changes our state. item->_edataState = kSecDbItemDecrypting; - result = SecDbItemDecrypt(item, edata, error); + if (credHandle) + SecDbItemSetCredHandle(item, *credHandle); + result = SecDbItemDecrypt(item, edata, authNeeded, error); + if (credHandle) + CFRetainAssign(*credHandle, item->credHandle); if (result) item->_edataState = kSecDbItemClean; else @@ -381,6 +405,7 @@ static CFTypeRef SecDbItemCopyValue(SecDbItemRef item, const SecDbAttr *attr, CF case kSecDbAccessAttr: case kSecDbStringAttr: case kSecDbBlobAttr: + case kSecDbAccessControlAttr: if (attr->flags & kSecDbNotNullFlag) { if (attr->flags & kSecDbDefault0Flag) { value = CFSTR("0"); @@ -435,13 +460,13 @@ static CFTypeRef SecDbItemCopyValue(SecDbItemRef item, const SecDbAttr *attr, CF // an error. It will return NULL and optionally set *error if there was an error computing an // attribute, or if a required attribute was missing a value and had no known way to compute // it's value. -CF_RETURNS_NOT_RETAINED CFTypeRef SecDbItemGetValue(SecDbItemRef item, const SecDbAttr *desc, CFErrorRef *error) { +CFTypeRef SecDbItemGetValue(SecDbItemRef item, const SecDbAttr *desc, CFErrorRef *error) { // Propagate chained errors if (!desc) return NULL; - if (desc->flags & kSecDbInCryptoDataFlag) { - if (!SecDbItemEnsureDecrypted(item, error)) + if (desc->flags & kSecDbInCryptoDataFlag || desc->flags & kSecDbInAuthenticatedDataFlag) { + if (!SecDbItemEnsureDecrypted(item, NULL, NULL, error)) return NULL; } @@ -449,7 +474,10 @@ CF_RETURNS_NOT_RETAINED CFTypeRef SecDbItemGetValue(SecDbItemRef item, const Sec if (!value) { value = SecDbItemCopyValue(item, desc, error); if (value) { - if (!CFEqual(kCFNull, value)) { + if (CFEqual(kCFNull, value)) { + CFRelease(value); // This is redundant but it shuts clang's static analyzer up. + value = kCFNull; + } else { SecDbItemSetValue(item, desc, value, error); CFRelease(value); value = SecDbItemGetCachedValue(item, desc); @@ -561,6 +589,9 @@ static CFStringRef SecDbItemCopyDescription(CFTypeRef cf) { if (isString(value)) access = value; break; + case kSecDbAccessControlAttr: + /* TODO: Add formatting of ACLs. */ + break; } } @@ -595,6 +626,8 @@ static CFStringRef SecDbItemCopyDescription(CFTypeRef cf) { static void SecDbItemDestroy(CFTypeRef cf) { SecDbItemRef item = (SecDbItemRef)cf; CFReleaseSafe(item->attributes); + CFReleaseSafe(item->credHandle); + CFReleaseSafe(item->callerAccessGroups); } static CFHashCode SecDbItemHash(CFTypeRef cf) { @@ -628,6 +661,7 @@ static SecDbItemRef SecDbItemCreate(CFAllocatorRef allocator, const SecDbClass * item->attributes = CFDictionaryCreateMutableForCFTypes(allocator); item->keybag = keybag; item->_edataState = kSecDbItemDirty; + item->cryptoOp = kSecKsUnwrap; return item; } @@ -635,12 +669,12 @@ const SecDbClass *SecDbItemGetClass(SecDbItemRef item) { return item->class; } -const keybag_handle_t SecDbItemGetKeybag(SecDbItemRef item) { +keybag_handle_t SecDbItemGetKeybag(SecDbItemRef item) { return item->keybag; } bool SecDbItemSetKeybag(SecDbItemRef item, keybag_handle_t keybag, CFErrorRef *error) { - if (!SecDbItemEnsureDecrypted(item, error)) + if (!SecDbItemEnsureDecrypted(item, NULL, NULL, error)) return false; if (item->keybag != keybag) { item->keybag = keybag; @@ -657,10 +691,13 @@ bool SecDbItemSetValue(SecDbItemRef item, const SecDbAttr *desc, CFTypeRef value if (!desc) return false; + if (!value) + value = kCFNull; + bool changed = false; CFTypeRef attr = NULL; - if (desc->flags & kSecDbInCryptoDataFlag) - if (!SecDbItemEnsureDecrypted(item, error)) + if (desc->flags & kSecDbInCryptoDataFlag || desc->flags & kSecDbInAuthenticatedDataFlag) + if (!SecDbItemEnsureDecrypted(item, NULL, NULL, error)) return false; switch (desc->kind) { @@ -680,6 +717,7 @@ bool SecDbItemSetValue(SecDbItemRef item, const SecDbAttr *desc, CFTypeRef value } break; case kSecDbBlobAttr: + case kSecDbAccessControlAttr: attr = copyBlob(value); break; case kSecDbDateAttr: @@ -722,7 +760,7 @@ bool SecDbItemSetValue(SecDbItemRef item, const SecDbAttr *desc, CFTypeRef value SecDbItemSetValue(item, SecDbClassAttrWithKind(item->class, kSecDbSHA1Attr, NULL), kCFNull, NULL); if (desc->flags & kSecDbPrimaryKeyFlag) SecDbItemSetValue(item, SecDbClassAttrWithKind(item->class, kSecDbPrimaryKeyAttr, NULL), kCFNull, NULL); - if (desc->flags & kSecDbInCryptoDataFlag && item->_edataState == kSecDbItemClean) + if ((desc->flags & kSecDbInCryptoDataFlag || desc->flags & kSecDbInAuthenticatedDataFlag) && item->_edataState == kSecDbItemClean) SecDbItemSetValue(item, SecDbClassAttrWithKind(item->class, kSecDbEncryptedDataAttr, NULL), kCFNull, NULL); } @@ -747,23 +785,13 @@ bool SecDbItemSetValueWithName(SecDbItemRef item, CFStringRef name, CFTypeRef va return false; } -static bool SecDbItemSetNumber(SecDbItemRef item, const SecDbAttr *desc, int32_t number, CFErrorRef *error) { - bool ok = true; - CFNumberRef value = CFNumberCreate(CFGetAllocator(item), kCFNumberSInt32Type, &number); - if (value) { - ok = SecDbItemSetValue(item, desc, value, error); - CFRelease(value); - } else { - ok = SecError(errSecInternal, error, CFSTR("Failed to create CFNumber for %" PRId32), number); - } - return ok; -} - -bool SecDbItemSetKeyclass(SecDbItemRef item, keyclass_t keyclass, CFErrorRef *error) { +bool SecDbItemSetAccessControl(SecDbItemRef item, SecAccessControlRef access_control, CFErrorRef *error) { bool ok = SecDbItemSetValue(item, SecDbClassAttrWithKind(item->class, kSecDbEncryptedDataAttr, error), kCFNull, error); if (ok) { item->_edataState = kSecDbItemDirty; - ok = SecDbItemSetNumber(item, SecDbClassAttrWithKind(item->class, kSecDbAccessAttr, error), keyclass, error); + CFDataRef data = SecAccessControlCopyData(access_control); + ok = SecDbItemSetValue(item, SecDbClassAttrWithKind(item->class, kSecDbAccessControlAttr, error), data, error); + CFRelease(data); } return ok; } @@ -823,6 +851,9 @@ SecDbColumnCopyValueWithAttr(CFAllocatorRef allocator, sqlite3_stmt *stmt, const case kSecDbRowIdAttr: value = SecDbColumnCopyNumber64(allocator, stmt, col, error); break; + case kSecDbAccessControlAttr: + /* This attributes does not have any database column associated, exists only inside encrypted blob as metadata. */ + break; } return value; } @@ -834,7 +865,11 @@ SecDbItemRef SecDbItemCreateWithStatement(CFAllocatorRef allocator, const SecDbC if (return_attr(attr)) { CFTypeRef value = SecDbColumnCopyValueWithAttr(allocator, stmt, attr, col++, error); if (value) { - SecDbItemSetValue(item, attr, value, error); + if (attr->kind == kSecDbSHA1Attr) { + SecDbItemSetValue(item, attr, value, NULL); + } else if (!SecDbItemSetValue(item, attr, value, error)) { + CFReleaseNull(item); + } CFRelease(value); } } @@ -1056,6 +1091,17 @@ static bool SecDbItemSetLastInsertRowId(SecDbItemRef item, SecDbConnectionRef db return SecDbItemSetRowId(item, rowid, error); } +bool SecDbItemIsSyncableOrCorrupted(SecDbItemRef item) { + bool is_syncable_or_corrupted = false; + CFErrorRef localError = NULL; + if (!SecDbItemGetBoolValue(item, SecDbClassAttrWithKind(item->class, kSecDbSyncAttr, &localError), + &is_syncable_or_corrupted, &localError)) { + is_syncable_or_corrupted = SecErrorGetOSStatus(localError) == errSecDecode; + } + CFReleaseSafe(localError); + return is_syncable_or_corrupted; +} + bool SecDbItemIsSyncable(SecDbItemRef item) { bool is_syncable; if (SecDbItemGetBoolValue(item, SecDbClassAttrWithKind(item->class, kSecDbSyncAttr, NULL), &is_syncable, NULL)) @@ -1089,8 +1135,10 @@ static SecDbQueryRef SecDbQueryCreateWithItemPrimaryKey(SecDbItemRef item, CFErr return NULL; SecDbQueryRef query = query_create(item->class, NULL, error); - if (query) + if (query) { + CFReleaseSafe(query->q_item); query->q_item = dict; + } else CFRelease(dict); @@ -1099,21 +1147,91 @@ static SecDbQueryRef SecDbQueryCreateWithItemPrimaryKey(SecDbItemRef item, CFErr static bool SecDbItemIsCorrupt(SecDbItemRef item, bool *is_corrupt, CFErrorRef *error) { CFErrorRef localError = NULL; - bool ok = SecDbItemEnsureDecrypted(item, &localError); - if (localError) { + // Cache the storedSHA1 digest so we use the one from the db not the recomputed one for notifications. + const struct SecDbAttr *sha1attr = SecDbClassAttrWithKind(item->class, kSecDbSHA1Attr, &localError); + CFDataRef storedSHA1 = CFRetainSafe(SecDbItemGetValue(item, sha1attr, &localError)); + SecDbItemSetValue(item, sha1attr, kCFNull, &localError); + CFDataRef access_control_data = NULL; + + bool akpu = false; + + if (localError || !SecDbItemEnsureDecrypted(item, &access_control_data, NULL, &localError)) { if (SecErrorGetOSStatus(localError) == errSecDecode) { // We failed to decrypt the item - secerror("error %@ reading item %@ (corrupted)", localError, item); - __security_simulatecrash(CFSTR("Corrupted item found in keychain"), __sec_exception_code_CorruptItem); + SecAccessControlRef access_control = NULL; + CFTypeRef access_class = NULL; + + if (access_control_data != NULL && + (access_control = + SecAccessControlCreateFromData(kCFAllocatorDefault, access_control_data, NULL)) != NULL && + (access_class = SecAccessControlGetProtection(access_control)) != NULL && + CFStringCompare(access_class, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, 0) == kCFCompareEqualTo) { + akpu = true; + secwarning("cannot decrypt item %@, item is irrecoverably lost with older passcode (error %@)", item, localError); + } else { + secerror("error %@ reading item %@ (corrupted)", localError, item); + __security_simulatecrash(CFSTR("Corrupted item found in keychain"), __sec_exception_code_CorruptItem); + } + CFReleaseSafe(access_control); + CFReleaseNull(localError); *is_corrupt = true; - ok = true; - } else if (error && *error == NULL) { - *error = localError; - localError = NULL; } - CFReleaseSafe(localError); } - return ok; + CFReleaseNull(access_control_data); + + CFDataRef computedSHA1 = SecDbItemGetValue(item, sha1attr, NULL); + if (storedSHA1 && computedSHA1) { + if (!CFEqual(storedSHA1, computedSHA1)) { + secerror("error %@ %@ != %@ item %@ (corrupted)", sha1attr->name, storedSHA1, computedSHA1, item); + __security_simulatecrash(CFSTR("Corrupted item (sha1 mismatch) found in keychain"), __sec_exception_code_CorruptItem); + *is_corrupt = true; + // Restore original (bad) sha1 digest so db notifications will properly update our manifest + SecDbItemSetValue(item, sha1attr, storedSHA1, NULL); + CFReleaseSafe(storedSHA1); + return true; + } + } + CFReleaseSafe(storedSHA1); + + // Sanity check that all attributes that must not be NULL actually aren't + if (!localError) SecDbForEachAttr(item->class, attr) { + if (attr->flags & (kSecDbInCryptoDataFlag | kSecDbInAuthenticatedDataFlag)) { + CFTypeRef value = SecDbItemGetValue(item, attr, &localError); + if (value) { + if (CFEqual(kCFNull, value) && attr->flags & kSecDbNotNullFlag) { + secerror("error attribute %@ has NULL value in item %@ (corrupted)", attr->name, item); + __security_simulatecrash(CFSTR("Corrupted item (attr NULL) found in keychain"), __sec_exception_code_CorruptItem); + *is_corrupt = true; + break; + } + } else { + if (SecErrorGetOSStatus(localError) == errSecDecode) { + // We failed to decrypt the item + if (akpu) { + secwarning("attribute %@: %@ item %@ (item lost with older passcode)", attr->name, localError, item); + } else { + secerror("error attribute %@: %@ item %@ (corrupted)", attr->name, localError, item); + __security_simulatecrash(CFSTR("Corrupted item found in keychain"), __sec_exception_code_CorruptItem); + } + *is_corrupt = true; + CFReleaseNull(localError); + } + break; + } + } + } + return CFErrorPropagate(localError, error); +} + +static void SecDbItemRecordUpdate(SecDbConnectionRef dbconn, SecDbItemRef deleted, SecDbItemRef inserted) { + CFDataRef deletedDigest = NULL; + CFDataRef insertedDigest = NULL; + if (deleted && SecDbItemIsSyncableOrCorrupted(deleted)) + deletedDigest = SecDbItemGetSHA1(deleted, NULL); + if (inserted && SecDbItemIsSyncable(inserted)) + insertedDigest = SecDbItemGetSHA1(inserted, NULL); + if (deletedDigest || insertedDigest) + SecDbRecordChange(dbconn, deletedDigest, insertedDigest); } static bool SecDbItemDoInsert(SecDbItemRef item, SecDbConnectionRef dbconn, CFErrorRef *error) { @@ -1130,18 +1248,22 @@ static bool SecDbItemDoInsert(SecDbItemRef item, SecDbConnectionRef dbconn, CFEr }); CFRelease(sql); } - if (ok) + if (ok) { secnotice("item", "inserted %@", item); + SecDbItemRecordUpdate(dbconn, NULL, item); + } return ok; } -bool SecDbItemInsertOrReplace(SecDbItemRef item, SecDbConnectionRef dbconn, CFErrorRef *error, void(^duplicate)(SecDbItemRef item, SecDbItemRef *replace)) { +bool SecDbItemInsertOrReplace(SecDbItemRef item, SecDbConnectionRef dbconn, CFMutableArrayRef authlist, CFErrorRef *error, void(^duplicate)(SecDbItemRef item, SecDbItemRef *replace)) { __block CFErrorRef localError = NULL; __block bool ok = SecDbItemDoInsert(item, dbconn, &localError); if (!ok && localError && CFErrorGetCode(localError) == SQLITE_CONSTRAINT && CFEqual(kSecDbErrorDomain, CFErrorGetDomain(localError))) { SecDbQueryRef query = SecDbQueryCreateWithItemPrimaryKey(item, error); if (query) { + CFRetainAssign(query->q_required_access_controls, authlist); + CFRetainAssign(query->q_use_cred_handle, item->credHandle); SecDbItemSelect(query, dbconn, error, ^bool(const SecDbAttr *attr) { return attr->flags & kSecDbPrimaryKeyFlag; }, NULL, NULL, ^(SecDbItemRef old_item, bool *stop) { @@ -1174,34 +1296,16 @@ bool SecDbItemInsertOrReplace(SecDbItemRef item, SecDbConnectionRef dbconn, CFEr CFReleaseNull(localError); // Clear the error, since we replaced the item. } }); + SecDbItemSetCredHandle(item, query->q_use_cred_handle); ok &= query_destroy(query, error); } - if (localError) - ok = false; // We didn't clear the error so we're failing again. } - if (!ok) { - /* - CFErrorRef e = localError ? localError : error ? *error : NULL; - secerror("INSERT %@ failed: %@%s", item, e, (e && CFErrorGetCode(e) == SQLITE_CONSTRAINT) ? - " and SELECT failed to find tombstone" : ""); - */ - secerror("INSERT failed: %@", localError); - if (localError) { - if (error && *error == NULL) { - *error = localError; - localError = NULL; - } else { - CFReleaseNull(localError); + return ok & CFErrorPropagate(localError, error); // Don't use && here! } - } - } - return ok; -} - -bool SecDbItemInsert(SecDbItemRef item, SecDbConnectionRef dbconn, CFErrorRef *error) { - return SecDbItemInsertOrReplace(item, dbconn, error, ^(SecDbItemRef old_item, SecDbItemRef *replace) { +bool SecDbItemInsert(SecDbItemRef item, SecDbConnectionRef dbconn, CFMutableArrayRef authlist, CFErrorRef *error) { + return SecDbItemInsertOrReplace(item, dbconn, authlist, error, ^(SecDbItemRef old_item, SecDbItemRef *replace) { if (SecDbItemIsTombstone(old_item)) { CFRetain(item); *replace = item; @@ -1261,8 +1365,10 @@ bool SecDbItemDoUpdate(SecDbItemRef old_item, SecDbItemRef new_item, SecDbConnec }); CFRelease(sql); } - if (ok) + if (ok) { secnotice("item", "replaced %@ with %@ in %@", old_item, new_item, dbconn); + SecDbItemRecordUpdate(dbconn, old_item, new_item); + } return ok; } @@ -1303,8 +1409,10 @@ static bool SecDbItemDoDelete(SecDbItemRef item, SecDbConnectionRef dbconn, CFEr }); CFRelease(sql); } - if (ok) + if (ok) { secnotice("item", "deleted %@ from %@", item, dbconn); + SecDbItemRecordUpdate(dbconn, item, NULL); + } return ok; } @@ -1477,8 +1585,9 @@ bool SecDbItemSelect(SecDbQueryRef query, SecDbConnectionRef dbconn, CFErrorRef bool (^bind_added_where)(sqlite3_stmt *stmt, int col), void (^handle_row)(SecDbItemRef item, bool *stop)) { __block bool ok = true; + __block bool decrypted = true; bool (^return_attr)(const SecDbAttr *attr) = ^bool (const SecDbAttr * attr) { - return attr->kind == kSecDbRowIdAttr || attr->kind == kSecDbEncryptedDataAttr; + return attr->kind == kSecDbRowIdAttr || attr->kind == kSecDbEncryptedDataAttr || attr->kind == kSecDbSHA1Attr; }; CFStringRef sql = SecDbItemCopySelectSQL(query, return_attr, use_attr_in_where, add_where_sql); if (sql) { @@ -1487,6 +1596,21 @@ bool SecDbItemSelect(SecDbQueryRef query, SecDbConnectionRef dbconn, CFErrorRef SecDbStep(dbconn, stmt, error, ^(bool *stop) { SecDbItemRef item = SecDbItemCreateWithStatement(kCFAllocatorDefault, query->q_class, stmt, query->q_keybag, error, return_attr); if (item) { + if (query->q_required_access_controls) { + CFDataRef authNeeded = NULL; + item->cryptoOp = query->q_crypto_op; + SecDbItemSetCallerAccessGroups(item, query->q_caller_access_groups); + decrypted = SecDbItemEnsureDecrypted(item, &authNeeded, &query->q_use_cred_handle, NULL); + if (decrypted && authNeeded) { + // Do not process the item right now, just remember that it will need + // authentication to properly process it. + CFArrayAppendValue(query->q_required_access_controls, authNeeded); + CFRelease(authNeeded); + CFRelease(item); + return; + } + CFReleaseSafe(authNeeded); + } handle_row(item, stop); CFRelease(item); } else { diff --git a/Security/sec/securityd/SecDbItem.h b/Security/sec/securityd/SecDbItem.h new file mode 100644 index 00000000..5934e960 --- /dev/null +++ b/Security/sec/securityd/SecDbItem.h @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + @header SecDbItem + The functions provided in SecDbItem provide an interface to + database items (certificates, keys, identities, and passwords). + */ + +#ifndef _SECURITYD_SECDBITEM_H_ +#define _SECURITYD_SECDBITEM_H_ + +#include +#include +#include // For CCSHA1_OUTPUT_SIZE +#include +#include +#include +#include +#include +#include + +// MARK SecDbAttrKind, SecDbFlag + +typedef enum { + kSecDbBlobAttr, // CFString or CFData, preserves caller provided type. + kSecDbDataAttr, + kSecDbStringAttr, + kSecDbNumberAttr, + kSecDbDateAttr, + kSecDbCreationDateAttr, + kSecDbModificationDateAttr, + kSecDbSHA1Attr, + kSecDbRowIdAttr, + kSecDbEncryptedDataAttr, + kSecDbPrimaryKeyAttr, + kSecDbSyncAttr, + kSecDbTombAttr, + kSecDbAccessAttr, + kSecDbAccessControlAttr +} SecDbAttrKind; + +enum { + kSecDbPrimaryKeyFlag = (1 << 0), // attr is part of primary key + kSecDbInFlag = (1 << 1), // attr exists in db + kSecDbIndexFlag = (1 << 2), // attr should have a db index + kSecDbSHA1ValueInFlag = (1 << 3), // col in db is sha1 of attr value + kSecDbReturnAttrFlag = (1 << 4), + kSecDbReturnDataFlag = (1 << 5), + kSecDbReturnRefFlag = (1 << 6), + kSecDbInCryptoDataFlag = (1 << 7), + kSecDbInHashFlag = (1 << 8), + kSecDbInBackupFlag = (1 << 9), + kSecDbDefault0Flag = (1 << 10), // default attr value is 0 + kSecDbDefaultEmptyFlag = (1 << 11), // default attr value is "" + kSecDbNotNullFlag = (1 << 12), // attr value can't be null + kSecDbInAuthenticatedDataFlag = (1 << 13), +}; + +#define SecVersionDbFlag(v) ((v & 0xFF) << 8) + +#define SecDbFlagGetVersion(flags) ((flags >> 8) & 0xFF) + +#define SECDB_ATTR(var, name, kind, flags) const SecDbAttr var = { CFSTR(name), kSecDb ## kind ## Attr, flags } + +typedef struct SecDbAttr { + CFStringRef name; + SecDbAttrKind kind; + CFOptionFlags flags; +} SecDbAttr; + +typedef struct SecDbClass { + CFStringRef name; + const SecDbAttr *attrs[]; +} SecDbClass; + + +#define SecDbForEachAttr(class, attr) for (const SecDbAttr * const* _pattr = (class)->attrs, *attr = *_pattr; attr; attr = *(++_pattr)) + +#define SecDbForEachAttrWithMask(class, attr, flag_mask) SecDbForEachAttr(class, attr) if ((attr->flags & (flag_mask)) == (flag_mask)) + +// MARK: Stuff that needs to move out of SecItemServer.c + + +CFDataRef kc_copy_sha1(size_t len, const void *data, CFErrorRef *error); +CFDataRef kc_copy_plist_sha1(CFPropertyListRef plist, CFErrorRef *error); +CFDataRef kc_plist_copy_der(CFPropertyListRef plist, CFErrorRef *error); + +// MARK: SecDbItem + +typedef struct SecDbItem *SecDbItemRef; + +enum SecDbItemState { + kSecDbItemDirty, // We have no edata (or if we do it's invalid), attributes are the truth + kSecDbItemEncrypted, // Attributes haven't been decrypted yet from edata + kSecDbItemClean, // Attributes and _edata are in sync. + kSecDbItemDecrypting, // Temporary state while we are decrypting so set knows not to blow away the edata. + kSecDbItemEncrypting, // Temporary state while we are encrypting so set knows to move to clean. +}; + +struct SecDbItem { + CFRuntimeBase _base; + const SecDbClass *class; + keyclass_t keyclass; + keybag_handle_t keybag; + //sqlite3_int64 _rowid; + //CFDataRef _primaryKey; + //CFDataRef _sha1; + //CFDataRef _edata; + enum SecDbItemState _edataState; + CFMutableDictionaryRef attributes; + CFTypeRef credHandle; + enum SecKsCryptoOp cryptoOp; + CFArrayRef callerAccessGroups; +}; + +// TODO: Make this a callback to client +bool SecDbItemDecrypt(SecDbItemRef item, CFDataRef edata, CFDataRef *neededAuth, CFErrorRef *error); + +CFTypeID SecDbItemGetTypeID(void); + +static inline size_t SecDbClassAttrCount(const SecDbClass *dbClass) { + size_t n_attrs = 0; + SecDbForEachAttr(dbClass, attr) { n_attrs++; } + return n_attrs; +} + +const SecDbAttr *SecDbClassAttrWithKind(const SecDbClass *class, SecDbAttrKind kind, CFErrorRef *error); + +SecDbItemRef SecDbItemCreateWithAttributes(CFAllocatorRef allocator, const SecDbClass *class, CFDictionaryRef attributes, keybag_handle_t keybag, CFErrorRef *error); + +const SecDbClass *SecDbItemGetClass(SecDbItemRef item); +keybag_handle_t SecDbItemGetKeybag(SecDbItemRef item); +bool SecDbItemSetKeybag(SecDbItemRef item, keybag_handle_t keybag, CFErrorRef *error); +SecAccessControlRef SecDbItemCopyAccessControl(SecDbItemRef item, CFErrorRef *error); +bool SecDbItemSetAccessControl(SecDbItemRef item, SecAccessControlRef access_control, CFErrorRef *error); +void SecDbItemSetCredHandle(SecDbItemRef item, CFTypeRef cred_handle); +void SecDbItemSetCallerAccessGroups(SecDbItemRef item, CFArrayRef caller_access_groups); + +CFTypeRef SecDbItemGetCachedValueWithName(SecDbItemRef item, CFStringRef name); +CFTypeRef SecDbItemGetValue(SecDbItemRef item, const SecDbAttr *desc, CFErrorRef *error); + +bool SecDbItemSetValue(SecDbItemRef item, const SecDbAttr *desc, CFTypeRef value, CFErrorRef *error); +bool SecDbItemSetValues(SecDbItemRef item, CFDictionaryRef values, CFErrorRef *error); +bool SecDbItemSetValueWithName(SecDbItemRef item, CFStringRef name, CFTypeRef value, CFErrorRef *error); + +sqlite3_int64 SecDbItemGetRowId(SecDbItemRef item, CFErrorRef *error); +bool SecDbItemSetRowId(SecDbItemRef item, sqlite3_int64 rowid, CFErrorRef *error); + +bool SecDbItemIsSyncableOrCorrupted(SecDbItemRef item); +bool SecDbItemIsSyncable(SecDbItemRef item); + +bool SecDbItemSetSyncable(SecDbItemRef item, bool sync, CFErrorRef *error); + +bool SecDbItemIsTombstone(SecDbItemRef item); + +CFMutableDictionaryRef SecDbItemCopyPListWithMask(SecDbItemRef item, CFOptionFlags mask, CFErrorRef *error); + +CFDataRef SecDbItemGetPrimaryKey(SecDbItemRef item, CFErrorRef *error); +CFDataRef SecDbItemGetSHA1(SecDbItemRef item, CFErrorRef *error); + +CFDataRef SecDbItemCopyEncryptedDataToBackup(SecDbItemRef item, uint64_t handle, CFErrorRef *error); + +SecDbItemRef SecDbItemCreateWithStatement(CFAllocatorRef allocator, const SecDbClass *class, sqlite3_stmt *stmt, keybag_handle_t keybag, CFErrorRef *error, bool (^return_attr)(const SecDbAttr *attr)); + +SecDbItemRef SecDbItemCreateWithEncryptedData(CFAllocatorRef allocator, const SecDbClass *class, + CFDataRef edata, keybag_handle_t keybag, CFErrorRef *error); + +SecDbItemRef SecDbItemCreateWithPrimaryKey(CFAllocatorRef allocator, const SecDbClass *class, CFDataRef primary_key); + +#if 0 +SecDbItemRef SecDbItemCreateWithRowId(CFAllocatorRef allocator, const SecDbClass *class, sqlite_int64 row_id, keybag_handle_t keybag, CFErrorRef *error); +#endif + +bool SecDbItemEnsureDecrypted(SecDbItemRef item, CFDataRef *authNeeded, CFTypeRef *credHandle, CFErrorRef *error); + +SecDbItemRef SecDbItemCopyWithUpdates(SecDbItemRef item, CFDictionaryRef updates, CFErrorRef *error); + +SecDbItemRef SecDbItemCopyTombstone(SecDbItemRef item, CFErrorRef *error); + +bool SecDbItemInsertOrReplace(SecDbItemRef item, SecDbConnectionRef dbconn, CFMutableArrayRef authlist, CFErrorRef *error, void(^duplicate)(SecDbItemRef item, SecDbItemRef *replace)); + +bool SecDbItemInsert(SecDbItemRef item, SecDbConnectionRef dbconn, CFMutableArrayRef authlist, CFErrorRef *error); + +bool SecDbItemDelete(SecDbItemRef item, SecDbConnectionRef dbconn, bool makeTombstone, CFErrorRef *error); + +// Low level update, just do the update +bool SecDbItemDoUpdate(SecDbItemRef old_item, SecDbItemRef new_item, SecDbConnectionRef dbconn, CFErrorRef *error, bool (^use_attr_in_where)(const SecDbAttr *attr)); + +// High level update, will replace tombstones and create them if needed. +bool SecDbItemUpdate(SecDbItemRef old_item, SecDbItemRef new_item, SecDbConnectionRef dbconn, bool makeTombstone, CFErrorRef *error); + + +// MARK: - +// MARK: SQL Construction helpers -- These should become private in the future + +void SecDbAppendElement(CFMutableStringRef sql, CFStringRef value, bool *needComma); +void SecDbAppendWhereOrAnd(CFMutableStringRef sql, bool *needWhere); +void SecDbAppendWhereOrAndEquals(CFMutableStringRef sql, CFStringRef col, bool *needWhere); + + +// MARK: type converters. +// TODO: these should be static and private to SecDbItem, or part of the schema + +CFStringRef copyString(CFTypeRef obj); +CFDataRef copyData(CFTypeRef obj); +CFTypeRef copyBlob(CFTypeRef obj); +CFDataRef copySHA1(CFTypeRef obj); +CFTypeRef copyNumber(CFTypeRef obj); +CFDateRef copyDate(CFTypeRef obj); + +__END_DECLS + +#endif /* _SECURITYD_SECDBITEM_H_ */ diff --git a/Security/sec/securityd/SecDbKeychainItem.c b/Security/sec/securityd/SecDbKeychainItem.c new file mode 100644 index 00000000..39c38ef6 --- /dev/null +++ b/Security/sec/securityd/SecDbKeychainItem.c @@ -0,0 +1,982 @@ +/* + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + */ + +/* + * SecDbKeychainItem.c - CoreFoundation-based constants and functions for + access to Security items (certificates, keys, identities, and + passwords.) + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if USE_KEYSTORE +#include +#include +#include +#include +#include +#endif /* USE_KEYSTORE */ + +pthread_key_t CURRENT_CONNECTION_KEY; + +// From SecItemServer, should be a acl-check block +bool itemInAccessGroup(CFDictionaryRef item, CFArrayRef accessGroups); + +static keyclass_t kc_parse_keyclass(CFTypeRef value, CFErrorRef *error); +static CFTypeRef kc_encode_keyclass(keyclass_t keyclass); +static CFDataRef kc_copy_protection_data(SecAccessControlRef access_control); +static CFTypeRef kc_copy_protection_from_data(CFDataRef data); +static CFMutableDictionaryRef s3dl_item_v2_decode(CFDataRef plain, CFErrorRef *error); +static CFMutableDictionaryRef s3dl_item_v3_decode(CFDataRef plain, CFErrorRef *error); +#if USE_KEYSTORE +static CFDataRef kc_copy_constraints_data(SecAccessControlRef access_control, CFDictionaryRef auth_attributes); +static void kc_dict_from_auth_data(const SecDbClass *class, const uint8_t *der, const uint8_t *der_end, CFMutableDictionaryRef *authenticated_attributes, CFMutableDictionaryRef *acl); +static CFDataRef kc_copy_access_groups_data(CFArrayRef access_groups, CFErrorRef *error); +#endif + +/* Given plainText create and return a CFDataRef containing: + BULK_KEY = RandomKey() + version || keyclass|ACL || KeyStore_WRAP(keyclass, BULK_KEY) || + AES(BULK_KEY, NULL_IV, plainText || padding) + */ +bool ks_encrypt_data(keybag_handle_t keybag, SecAccessControlRef access_control, CFTypeRef *cred_handle, + CFDictionaryRef attributes, CFDictionaryRef authenticated_attributes, CFDataRef *pBlob, CFErrorRef *error) { + CFMutableDataRef blob = NULL; + CFDataRef ac_data = NULL; + bool ok = true; + //check(keybag >= 0); + + /* Precalculate output blob length. */ + const uint32_t bulkKeySize = 32; /* Use 256 bit AES key for bulkKey. */ + const uint32_t maxKeyWrapOverHead = 8 + 32; + uint8_t bulkKey[bulkKeySize]; + CFMutableDataRef bulkKeyWrapped = CFDataCreateMutable(NULL, 0); + CFDataSetLength(bulkKeyWrapped, bulkKeySize + maxKeyWrapOverHead); + uint32_t key_wrapped_size; + +#if USE_KEYSTORE + CFDataRef access_control_data = NULL; + CFDataRef constraint_data = NULL; + CFDataRef acm_context = NULL; +#endif + + /* If access_control specifies only protection and no ACL, use legacy blob format version 3, + which has better support for sync/backup. Otherwise, force new format v4. */ + const uint32_t version = SecAccessControlGetConstraints(access_control) ? 4 : 3; + CFDataRef plainText = NULL; + if (version < 4) { + CFMutableDictionaryRef attributes_dict = CFDictionaryCreateMutableCopy(NULL, 0, attributes); + if (authenticated_attributes) { + CFDictionaryForEach(authenticated_attributes, ^(const void *key, const void *value) { + CFDictionaryAddValue(attributes_dict, key, value); + }); + } + + if (attributes_dict) { + // Drop the accc attribute for non v4 items during encode. + CFDictionaryRemoveValue(attributes_dict, kSecAttrAccessControl); + plainText = kc_plist_copy_der(attributes_dict, error); + CFRelease(attributes_dict); + } + } else { +#if USE_KEYSTORE + if (attributes) { + plainText = kc_plist_copy_der(attributes, error); + } +#else + CFMutableDictionaryRef attributes_dict = CFDictionaryCreateMutableCopy(NULL, 0, attributes); + if (authenticated_attributes) { + CFDictionaryForEach(authenticated_attributes, ^(const void *key, const void *value) { + CFDictionaryAddValue(attributes_dict, key, value); + }); + } + + if (attributes_dict) { + plainText = kc_plist_copy_der(attributes_dict, error); + CFRelease(attributes_dict); + } +#endif + } + + if (!plainText || CFGetTypeID(plainText) != CFDataGetTypeID() + || access_control == 0) { + ok = SecError(errSecParam, error, CFSTR("ks_encrypt_data: invalid plain text")); + goto out; + } + + size_t ptLen = CFDataGetLength(plainText); + size_t ctLen = ptLen; + size_t tagLen = 16; + keyclass_t actual_class; + + if (SecRandomCopyBytes(kSecRandomDefault, bulkKeySize, bulkKey)) { + ok = SecError(errSecAllocate, error, CFSTR("ks_encrypt_data: SecRandomCopyBytes failed")); + goto out; + } + + /* Extract keyclass from access control. */ + keyclass_t keyclass = kc_parse_keyclass(SecAccessControlGetProtection(access_control), error); + if (!keyclass) + goto out; + +#if USE_KEYSTORE + if (version >= 4) { + if (*cred_handle == NULL || isData(*cred_handle)) { + CFTypeRef auth_ref = VRCreateNewReferenceWithACMContext(*cred_handle, error); + if (!auth_ref) { + ok = false; + goto out; + } + CFReleaseSafe(*cred_handle); + *cred_handle = auth_ref; + } + + access_control_data = SecAccessControlCopyData(access_control); + CFErrorRef authError = NULL; + ok = VRValidateACL(*cred_handle, access_control_data, &authError); + if (!ok) { + ok = SecCFCreateError(errSecParam, kSecErrorDomain, CFSTR("Invalid ACL"), authError, error); + CFReleaseSafe(authError); + goto out; + } + + constraint_data = kc_copy_constraints_data(access_control, authenticated_attributes); + require_quiet(ok = ks_crypt_acl(kSecKsWrap, keybag, + keyclass, bulkKeySize, bulkKey, bulkKeyWrapped, constraint_data, NULL, NULL, error), out); + } + else { +#endif + /* Encrypt bulkKey. */ + require_quiet(ok = ks_crypt(kSecKsWrap, keybag, + keyclass, bulkKeySize, bulkKey, + &actual_class, bulkKeyWrapped, + error), out); +#if USE_KEYSTORE + } +#endif + + key_wrapped_size = (uint32_t)CFDataGetLength(bulkKeyWrapped); + UInt8 *cursor; + size_t blobLen = sizeof(version); + uint32_t prot_length; + + if (version == 3) { + blobLen += sizeof(actual_class); + } else { + require_quiet(ac_data = kc_copy_protection_data(access_control), out); + prot_length = (uint32_t)CFDataGetLength(ac_data); + blobLen += sizeof(prot_length) + prot_length; + } + + blobLen += sizeof(key_wrapped_size) + key_wrapped_size + ctLen + tagLen; + require_quiet(blob = CFDataCreateMutable(NULL, blobLen), out); + CFDataSetLength(blob, blobLen); + cursor = CFDataGetMutableBytePtr(blob); + + *((uint32_t *)cursor) = version; + cursor += sizeof(version); + + //secerror("class: %d actual class: %d", keyclass, actual_class); + if (version == 3) { + *((keyclass_t *)cursor) = actual_class; + cursor += sizeof(keyclass); + } else { + *((uint32_t *)cursor) = prot_length; + cursor += sizeof(prot_length); + + CFDataGetBytes(ac_data, CFRangeMake(0, prot_length), cursor); + cursor += prot_length; + } + + *((uint32_t *)cursor) = key_wrapped_size; + cursor += sizeof(key_wrapped_size); + + memcpy(cursor, CFDataGetBytePtr(bulkKeyWrapped), key_wrapped_size); + cursor += key_wrapped_size; + + /* Encrypt the plainText with the bulkKey. */ + CCCryptorStatus ccerr = CCCryptorGCM(kCCEncrypt, kCCAlgorithmAES128, + bulkKey, bulkKeySize, + NULL, 0, /* iv */ + NULL, 0, /* auth data */ + CFDataGetBytePtr(plainText), ptLen, + cursor, + cursor + ctLen, &tagLen); + if (ccerr) { + ok = SecError(errSecInternal, error, CFSTR("ks_encrypt_data: CCCryptorGCM failed: %d"), ccerr); + goto out; + } + if (tagLen != 16) { + ok = SecError(errSecInternal, error, CFSTR("ks_encrypt_data: CCCryptorGCM expected: 16 got: %ld byte tag"), tagLen); + goto out; + } + +out: + memset(bulkKey, 0, sizeof(bulkKey)); + CFReleaseSafe(ac_data); + CFReleaseSafe(bulkKeyWrapped); + CFReleaseSafe(plainText); + if (!ok) { + CFReleaseSafe(blob); + } else { + *pBlob = blob; + } + +#if USE_KEYSTORE + CFReleaseSafe(access_control_data); + CFReleaseSafe(constraint_data); + CFReleaseSafe(acm_context); +#endif + return ok; +} + +/* Given cipherText containing: + version || keyclass || KeyStore_WRAP(keyclass, BULK_KEY) || + AES(BULK_KEY, NULL_IV, plainText || padding) + return the plainText. */ +bool ks_decrypt_data(keybag_handle_t keybag, enum SecKsCryptoOp cryptoOp, SecAccessControlRef *paccess_control, CFTypeRef *cred_handle, + CFDataRef blob, const SecDbClass *db_class, CFArrayRef caller_access_groups, + CFMutableDictionaryRef *attributes_p, uint32_t *version_p, CFErrorRef *error) { + const uint32_t v0KeyWrapOverHead = 8; + CFMutableDataRef bulkKey = CFDataCreateMutable(0, 32); /* Use 256 bit AES key for bulkKey. */ + CFDataSetLength(bulkKey, 32); /* Use 256 bit AES key for bulkKey. */ + bool ok = true; + SecAccessControlRef access_control = NULL; + + CFMutableDataRef plainText = NULL; + CFMutableDictionaryRef attributes = NULL; + uint32_t version = 0; + CFDataRef access_control_data = NULL; + +#if USE_KEYSTORE + CFDataRef acm_context = NULL; + CFMutableDictionaryRef authenticated_attributes = NULL; + CFDataRef caller_access_groups_data = NULL; + +#if TARGET_OS_IPHONE + check(keybag >= 0); +#else + check((keybag >= 0) || (keybag == session_keybag_handle)); +#endif +#endif + + if (!blob) { + ok = SecError(errSecParam, error, CFSTR("ks_decrypt_data: invalid blob")); + goto out; + } + + size_t blobLen = CFDataGetLength(blob); + const uint8_t *cursor = CFDataGetBytePtr(blob); + keyclass_t keyclass; + uint32_t wrapped_key_size; + + /* Check for underflow, ensuring we have at least one full AES block left. */ + if (blobLen < sizeof(version) + sizeof(keyclass) + + CFDataGetLength(bulkKey) + v0KeyWrapOverHead + 16) { + ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: Check for underflow")); + goto out; + } + + version = *((uint32_t *)cursor); + cursor += sizeof(version); + + size_t minimum_blob_len = sizeof(version) + 16; + size_t ctLen = blobLen - sizeof(version); + + if (version == 4) { + /* Deserialize SecAccessControl object from the blob. */ + uint32_t prot_length = *((uint32_t *)cursor); + cursor += sizeof(prot_length); + + CFDataRef protection_data = CFDataCreate(kCFAllocatorDefault, cursor, prot_length); + CFTypeRef protection = kc_copy_protection_from_data(protection_data); + CFRelease(protection_data); + if (!protection) { + ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: invalid ACL")); + goto out; + } + else { + access_control = SecAccessControlCreate(NULL, NULL); + require_quiet(access_control, out); + ok = SecAccessControlSetProtection(access_control, protection, NULL); + CFRelease(protection); + if (!ok) { + SecError(errSecDecode, error, CFSTR("ks_decrypt_data: invalid ACL")); + goto out; + } + } + + cursor += prot_length; + + minimum_blob_len += sizeof(prot_length) + prot_length; + ctLen -= sizeof(prot_length) + prot_length; + + /* Get numeric value of keyclass from the access_control. */ + keyclass = kc_parse_keyclass(SecAccessControlGetProtection(access_control), error); + if (!keyclass) { + ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: invalid ACL")); + goto out; + } + } else { + keyclass = *((keyclass_t *)cursor); + //secerror("class: %d keyclass: %d", keyclass, keyclass & key_class_last); +#if USE_KEYSTORE + CFTypeRef protection = kc_encode_keyclass(keyclass & key_class_last); // mask out generation +#else + CFTypeRef protection = kc_encode_keyclass(keyclass); +#endif + if (protection) { + access_control = SecAccessControlCreateWithFlags(kCFAllocatorDefault, protection, 0, error); + } + if (!access_control) { + ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: invalid keyclass detected")); + goto out; + } + cursor += sizeof(keyclass); + + minimum_blob_len += sizeof(keyclass); + ctLen -= sizeof(keyclass); + } + + size_t tagLen = 0; + switch (version) { + case 0: + wrapped_key_size = (uint32_t)CFDataGetLength(bulkKey) + v0KeyWrapOverHead; + break; + case 2: + case 3: + /* DROPTHROUGH */ + /* v2 and v3 have the same crypto, just different dictionary encodings. */ + /* Difference between v3 and v4 is already handled above, so treat v3 as v4. */ + case 4: + tagLen = 16; + minimum_blob_len -= 16; // Remove PKCS7 padding block requirement + ctLen -= tagLen; // Remove tagLen from ctLen + /* DROPTHROUGH */ + case 1: + wrapped_key_size = *((uint32_t *)cursor); + cursor += sizeof(wrapped_key_size); + minimum_blob_len += sizeof(wrapped_key_size); + ctLen -= sizeof(wrapped_key_size); + break; + default: + ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: invalid version %d"), version); + goto out; + } + + /* Validate key wrap length against total length */ + require(blobLen - minimum_blob_len - tagLen >= wrapped_key_size, out); + ctLen -= wrapped_key_size; + if (version < 2 && (ctLen & 0xF) != 0) { + ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: invalid version")); + goto out; + } + +#if USE_KEYSTORE + if (version >= 4) { + /* Verify before we try to unwrap the key. */ + if (*cred_handle == NULL || isData(*cred_handle)) { + CFTypeRef auth_ref = VRCreateNewReferenceWithACMContext(*cred_handle, error); + if (!auth_ref) { + ok = false; + goto out; + } + CFReleaseSafe(*cred_handle); + *cred_handle = auth_ref; + } + + CFMutableDictionaryRef acl = NULL; + kc_dict_from_auth_data(db_class, cursor, cursor + wrapped_key_size, &authenticated_attributes, &acl); + SecAccessControlSetConstraints(access_control, acl); + CFReleaseSafe(acl); + access_control_data = SecAccessControlCopyData(access_control); + + static CFDictionaryRef hints = NULL; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + CFNumberRef noninteractiveKey = CFNumberCreateWithCFIndex(kCFAllocatorDefault, kLAOptionNotInteractive); + hints = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, noninteractiveKey, kCFBooleanTrue, NULL); + CFRelease(noninteractiveKey); + }); + + CFErrorRef authError = NULL; + ok = VREvaluateACL(*cred_handle, access_control_data, (cryptoOp == kSecKsDelete)?kAKSKeyOpDelete:kAKSKeyOpDecrypt, hints, &authError); + if (!ok) { + if (CFEqual(CFErrorGetDomain(authError), CFSTR(kLAErrorDomain)) && + CFErrorGetCode(authError) == kLAErrorNotInteractive) { + /* UI is needed, but this is not really an error, just leave with no output data. */ + ok = true; + } else { + ok = SecCFCreateError(errSecAuthFailed, kSecErrorDomain, CFSTR("CoreAuthentication failed"), authError, error); + } + CFReleaseSafe(authError); + goto out; + } + + acm_context = VRCopyACMContext(*cred_handle, error); + + if (caller_access_groups) { + caller_access_groups_data = kc_copy_access_groups_data(caller_access_groups, error); + require_quiet(ok = (caller_access_groups_data != NULL), out); + } + require_quiet(ok = ks_crypt_acl(cryptoOp, keybag, + keyclass, wrapped_key_size, cursor, bulkKey, NULL, acm_context, caller_access_groups_data, error), out); + if (cryptoOp == kSecKsDelete) { + attributes = CFRetainSafe(authenticated_attributes); + goto out; + } + } + else { +#endif + /* Now unwrap the bulk key using a key in the keybag. */ + require_quiet(ok = ks_crypt(kSecKsUnwrap, keybag, + keyclass, wrapped_key_size, cursor, NULL, bulkKey, error), out); +#if USE_KEYSTORE + } +#endif + + cursor += wrapped_key_size; + + plainText = CFDataCreateMutable(NULL, ctLen); + if (!plainText) { + ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: failed to allocate data for plain text")); + goto out; + } + CFDataSetLength(plainText, ctLen); + + /* Decrypt the cipherText with the bulkKey. */ + CCCryptorStatus ccerr; + if (tagLen) { + uint8_t tag[tagLen]; + ccerr = CCCryptorGCM(kCCDecrypt, kCCAlgorithmAES128, + CFDataGetBytePtr(bulkKey), CFDataGetLength(bulkKey), + NULL, 0, /* iv */ + NULL, 0, /* auth data */ + cursor, ctLen, + CFDataGetMutableBytePtr(plainText), + tag, &tagLen); + if (ccerr) { + /* TODO: Should this be errSecDecode once AppleKeyStore correctly + identifies uuid unwrap failures? */ + /* errSecInteractionNotAllowed; */ + ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: CCCryptorGCM failed: %d"), ccerr); + goto out; + } + if (tagLen != 16) { + ok = SecError(errSecInternal, error, CFSTR("ks_decrypt_data: CCCryptorGCM expected: 16 got: %ld byte tag"), tagLen); + goto out; + } + cursor += ctLen; + if (memcmp(tag, cursor, tagLen)) { + ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: CCCryptorGCM computed tag not same as tag in blob")); + goto out; + } + } else { + size_t ptLen; + ccerr = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, + CFDataGetBytePtr(bulkKey), CFDataGetLength(bulkKey), NULL, cursor, ctLen, + CFDataGetMutableBytePtr(plainText), ctLen, &ptLen); + if (ccerr) { + /* TODO: Should this be errSecDecode once AppleKeyStore correctly + identifies uuid unwrap failures? */ + /* errSecInteractionNotAllowed; */ + ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: CCCrypt failed: %d"), ccerr); + goto out; + } + CFDataSetLength(plainText, ptLen); + } + + if (version < 2) { + attributes = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue(attributes, CFSTR("v_Data"), plainText); + } else if (version < 3) { + attributes = s3dl_item_v2_decode(plainText, error); + } else { + attributes = s3dl_item_v3_decode(plainText, error); + +#if USE_KEYSTORE + if (version >= 4 && authenticated_attributes != NULL) { + CFDictionaryForEach(authenticated_attributes, ^(const void *key, const void *value) { + CFDictionaryAddValue(attributes, key, value); + }); + } +#endif + } + + if (!attributes) { + secerror("decode v%d failed: %@ [item: %@]", version, error ? *error : NULL, plainText); + ok = false; + } +out: + memset(CFDataGetMutableBytePtr(bulkKey), 0, CFDataGetLength(bulkKey)); + CFReleaseSafe(bulkKey); + CFReleaseSafe(plainText); + + // Always copy access control data (if present), because if we fail it may indicate why. + if (paccess_control) + *paccess_control = access_control; + else + CFReleaseSafe(access_control); + + if (ok) { + if (attributes_p) + *attributes_p = CFRetainSafe(attributes); + if (version_p) + *version_p = version; + } + CFReleaseSafe(attributes); + CFReleaseSafe(access_control_data); +#if USE_KEYSTORE + CFReleaseSafe(acm_context); + CFReleaseSafe(authenticated_attributes); + CFReleaseSafe(caller_access_groups_data); +#endif + return ok; +} + +// TODO: Move to utilities - CFPropertyListCopyDERData() +CFDataRef kc_plist_copy_der(CFPropertyListRef plist, CFErrorRef *error) { + size_t len = der_sizeof_plist(plist, error); + CFMutableDataRef encoded = CFDataCreateMutable(0, len); + CFDataSetLength(encoded, len); + uint8_t *der_end = CFDataGetMutableBytePtr(encoded); + const uint8_t *der = der_end; + der_end += len; + der_end = der_encode_plist(plist, error, der, der_end); + if (!der_end) { + CFReleaseNull(encoded); + } else { + assert(!der_end || der_end == der); + } + return encoded; +} + +static CFDataRef kc_copy_digest(const struct ccdigest_info *di, size_t len, + const void *data, CFErrorRef *error) { + CFMutableDataRef digest = CFDataCreateMutable(0, di->output_size); + CFDataSetLength(digest, di->output_size); + ccdigest(di, len, data, CFDataGetMutableBytePtr(digest)); + return digest; +} + +CFDataRef kc_copy_sha1(size_t len, const void *data, CFErrorRef *error) { + return kc_copy_digest(ccsha1_di(), len, data, error); +} + +CFDataRef kc_copy_plist_sha1(CFPropertyListRef plist, CFErrorRef *error) { + CFDataRef der = kc_plist_copy_der(plist, error); + CFDataRef digest = NULL; + if (der) { + digest = kc_copy_sha1(CFDataGetLength(der), CFDataGetBytePtr(der), error); + CFRelease(der); + } + return digest; +} + +static keyclass_t kc_parse_keyclass(CFTypeRef value, CFErrorRef *error) { + if (!isString(value)) { + SecError(errSecParam, error, CFSTR("accessible attribute %@ not a string"), value); + } else if (CFEqual(value, kSecAttrAccessibleWhenUnlocked)) { + return key_class_ak; + } else if (CFEqual(value, kSecAttrAccessibleAfterFirstUnlock)) { + return key_class_ck; + } else if (CFEqual(value, kSecAttrAccessibleAlways)) { + return key_class_dk; + } else if (CFEqual(value, kSecAttrAccessibleWhenUnlockedThisDeviceOnly)) { + return key_class_aku; + } else if (CFEqual(value, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly)) { + return key_class_cku; + } else if (CFEqual(value, kSecAttrAccessibleAlwaysThisDeviceOnly)) { + return key_class_dku; + } else if (CFEqual(value, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly)) { + return key_class_akpu; + } else { + SecError(errSecParam, error, CFSTR("accessible attribute %@ unknown"), value); + } + return 0; +} + +static CFTypeRef kc_encode_keyclass(keyclass_t keyclass) { + switch (keyclass) { + case key_class_ak: + return kSecAttrAccessibleWhenUnlocked; + case key_class_ck: + return kSecAttrAccessibleAfterFirstUnlock; + case key_class_dk: + return kSecAttrAccessibleAlways; + case key_class_aku: + return kSecAttrAccessibleWhenUnlockedThisDeviceOnly; + case key_class_cku: + return kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; + case key_class_dku: + return kSecAttrAccessibleAlwaysThisDeviceOnly; + case key_class_akpu: + return kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly; + default: + return 0; + } +} + +#if USE_KEYSTORE +static void kc_dict_from_auth_data(const SecDbClass *class, const uint8_t *der, const uint8_t *der_end, CFMutableDictionaryRef *authenticated_attributes, CFMutableDictionaryRef *acl) +{ + CFPropertyListRef aks_data = NULL; + der = der_decode_plist(NULL, kCFPropertyListImmutable, &aks_data, NULL, der, der_end); + if(der == der_end) { + CFDictionaryRef authenticated_data = CFDictionaryGetValue(aks_data, kAKSKeyAuthData); + if (authenticated_data) { + *acl = CFDictionaryCreateMutableCopy(NULL, 0, authenticated_data); + SecDbForEachAttrWithMask(class, attr_desc, kSecDbInAuthenticatedDataFlag) { + CFDictionaryRemoveValue(*acl, attr_desc->name); + CFTypeRef value = CFDictionaryGetValue(authenticated_data, attr_desc->name); + if (value) { + if (!*authenticated_attributes) + *authenticated_attributes = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + CFDictionaryAddValue(*authenticated_attributes, attr_desc->name, value); + } + } + } + } + + CFReleaseSafe(aks_data); +} + +static CFDataRef kc_copy_constraints_data(SecAccessControlRef access_control, CFDictionaryRef auth_attributes) { + CFDictionaryRef constraints = SecAccessControlGetConstraints(access_control); + CFMutableDictionaryRef auth_data = CFDictionaryCreateMutableCopy(NULL, 0, constraints); + if (auth_attributes) { + CFDictionaryForEach(auth_attributes, ^(const void *key, const void *value) { + CFDictionaryAddValue(auth_data, key, value); + }); + } + + CFDataRef encoded = kc_plist_copy_der(auth_data, NULL); + CFReleaseSafe(auth_data); + return encoded; +} + +static CFDataRef kc_copy_access_groups_data(CFArrayRef access_groups, CFErrorRef *error) +{ + size_t ag_size = der_sizeof_plist(access_groups, error); + CFMutableDataRef result = CFDataCreateMutable(kCFAllocatorDefault, 0); + CFDataSetLength(result, ag_size); + if (!der_encode_plist(access_groups, error, CFDataGetMutableBytePtr(result), CFDataGetMutableBytePtr(result) + ag_size)) { + CFRelease(result); + return NULL; + } + else + return result; +} + +#endif /* USE_KEYSTORE */ + +static CFDataRef kc_copy_protection_data(SecAccessControlRef access_control) +{ + CFTypeRef protection = SecAccessControlGetProtection(access_control); + size_t protection_size = der_sizeof_plist(protection, NULL); + CFMutableDataRef result = CFDataCreateMutable(NULL, 0); + CFDataSetLength(result, protection_size); + if (!der_encode_plist(protection, NULL, CFDataGetMutableBytePtr(result), CFDataGetMutableBytePtr(result) + protection_size)) { + CFRelease(result); + return NULL; + } + else + return result; +} + +static CFTypeRef kc_copy_protection_from_data(CFDataRef data) +{ + CFTypeRef result = NULL; + der_decode_plist(NULL, kCFPropertyListImmutable, &result, NULL, CFDataGetBytePtr(data), CFDataGetBytePtr(data) + CFDataGetLength(data)); + return result; +} + +/* Return a (mutable) dictionary if plist is a dictionary, return NULL and set error otherwise. Does nothing if plist is already NULL. */ +static CF_RETURNS_RETAINED +CFMutableDictionaryRef dictionaryFromPlist(CFPropertyListRef plist CF_CONSUMED, CFErrorRef *error) { + if (plist && !isDictionary(plist)) { + CFStringRef typeName = CFCopyTypeIDDescription(CFGetTypeID((CFTypeRef)plist)); + SecError(errSecDecode, error, CFSTR("plist is a %@, expecting a dictionary"), typeName); + CFReleaseSafe(typeName); + CFReleaseNull(plist); + } + return (CFMutableDictionaryRef)plist; +} + +static CF_RETURNS_RETAINED +CFMutableDictionaryRef s3dl_item_v2_decode(CFDataRef plain, CFErrorRef *error) { + CFPropertyListRef item; + item = CFPropertyListCreateWithData(0, plain, kCFPropertyListMutableContainers, NULL, error); + return dictionaryFromPlist(item, error); +} + +static CF_RETURNS_RETAINED +CFMutableDictionaryRef s3dl_item_v3_decode(CFDataRef plain, CFErrorRef *error) { + CFPropertyListRef item = NULL; + const uint8_t *der = CFDataGetBytePtr(plain); + const uint8_t *der_end = der + CFDataGetLength(plain); + der = der_decode_plist(0, kCFPropertyListMutableContainers, &item, error, der, der_end); + if (der && der != der_end) { + SecCFCreateError(errSecDecode, kSecErrorDomain, CFSTR("trailing garbage at end of decrypted item"), NULL, error); + CFReleaseNull(item); + } + return dictionaryFromPlist(item, error); +} + +bool s3dl_item_from_data(CFDataRef edata, Query *q, CFArrayRef accessGroups, + CFMutableDictionaryRef *item, SecAccessControlRef *access_control, CFErrorRef *error) { + SecAccessControlRef ac = NULL; + CFDataRef ac_data = NULL; + bool ok = false; + + /* Decrypt and decode the item and check the decoded attributes against the query. */ + uint32_t version = 0; + require_quiet((ok = ks_decrypt_data(q->q_keybag, q->q_crypto_op, &ac, &q->q_use_cred_handle, edata, q->q_class, q->q_caller_access_groups, item, &version, error)), out); + if (version < 2) { + goto out; + } + + ac_data = SecAccessControlCopyData(ac); + if (!*item) { + /* Item cannot be decrypted, because interactive authentication is needed. */ + if (!q->q_required_access_controls) { + ok = SecError(errSecInteractionNotAllowed, error, CFSTR("item would need ui for decrypting")); + goto out; + } + CFArrayAppendValue(q->q_required_access_controls, ac_data); + *item = NULL; + goto out; + } + + if (*item && !itemInAccessGroup(*item, accessGroups)) { + secerror("items accessGroup %@ not in %@", + CFDictionaryGetValue(*item, kSecAttrAccessGroup), + accessGroups); + ok = SecError(errSecDecode, error, CFSTR("items accessGroup %@ not in %@"), + CFDictionaryGetValue(*item, kSecAttrAccessGroup), + accessGroups); + CFReleaseNull(*item); + } + + /* AccessControl attribute does not exist in the db, so synthesize it. */ + if (*item) { + CFDictionarySetValue(*item, kSecAttrAccessControl, ac_data); + } + + /* TODO: Validate access_control attribute. */ + +out: + if (access_control) + *access_control = CFRetainSafe(ac); + CFReleaseSafe(ac); + CFReleaseSafe(ac_data); + return ok; +} + +/* Infer accessibility and access group for pre-v2 (iOS4.x and earlier) items + being imported from a backup. */ +static bool SecDbItemImportMigrate(SecDbItemRef item, CFErrorRef *error) { + bool ok = true; + CFStringRef agrp = SecDbItemGetCachedValueWithName(item, kSecAttrAccessGroup); + CFStringRef accessible = SecDbItemGetCachedValueWithName(item, kSecAttrAccessible); + + if (!isString(agrp) || !isString(accessible)) + return ok; + if (SecDbItemGetClass(item) == &genp_class && CFEqual(accessible, kSecAttrAccessibleAlways)) { + CFStringRef svce = SecDbItemGetCachedValueWithName(item, kSecAttrService); + if (!isString(svce)) return ok; + if (CFEqual(agrp, CFSTR("apple"))) { + if (CFEqual(svce, CFSTR("AirPort"))) { + ok = SecDbItemSetValueWithName(item, kSecAttrAccessible, kSecAttrAccessibleAfterFirstUnlock, error); + } else if (CFEqual(svce, CFSTR("com.apple.airplay.password"))) { + ok = SecDbItemSetValueWithName(item, kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked, error); + } else if (CFEqual(svce, CFSTR("YouTube"))) { + ok = (SecDbItemSetValueWithName(item, kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked, error) && + SecDbItemSetValueWithName(item, kSecAttrAccessGroup, CFSTR("com.apple.youtube.credentials"), error)); + } else { + CFStringRef desc = SecDbItemGetCachedValueWithName(item, kSecAttrDescription); + if (!isString(desc)) return ok; + if (CFEqual(desc, CFSTR("IPSec Shared Secret")) || CFEqual(desc, CFSTR("PPP Password"))) { + ok = SecDbItemSetValueWithName(item, kSecAttrAccessible, kSecAttrAccessibleAfterFirstUnlock, error); + } + } + } + } else if (SecDbItemGetClass(item) == &inet_class && CFEqual(accessible, kSecAttrAccessibleAlways)) { + if (CFEqual(agrp, CFSTR("PrintKitAccessGroup"))) { + ok = SecDbItemSetValueWithName(item, kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked, error); + } else if (CFEqual(agrp, CFSTR("apple"))) { + CFTypeRef ptcl = SecDbItemGetCachedValueWithName(item, kSecAttrProtocol); + bool is_proxy = false; + if (isNumber(ptcl)) { + SInt32 iptcl; + CFNumberGetValue(ptcl, kCFNumberSInt32Type, &iptcl); + is_proxy = (iptcl == FOUR_CHAR_CODE('htpx') || + iptcl == FOUR_CHAR_CODE('htsx') || + iptcl == FOUR_CHAR_CODE('ftpx') || + iptcl == FOUR_CHAR_CODE('rtsx') || + iptcl == FOUR_CHAR_CODE('xpth') || + iptcl == FOUR_CHAR_CODE('xsth') || + iptcl == FOUR_CHAR_CODE('xptf') || + iptcl == FOUR_CHAR_CODE('xstr')); + } else if (isString(ptcl)) { + is_proxy = (CFEqual(ptcl, kSecAttrProtocolHTTPProxy) || + CFEqual(ptcl, kSecAttrProtocolHTTPSProxy) || + CFEqual(ptcl, kSecAttrProtocolRTSPProxy) || + CFEqual(ptcl, kSecAttrProtocolFTPProxy)); + } + if (is_proxy) + ok = SecDbItemSetValueWithName(item, kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked, error); + } + } + return ok; +} + +bool SecDbItemDecrypt(SecDbItemRef item, CFDataRef edata, CFDataRef *neededAuth, CFErrorRef *error) { + bool ok = true; + CFMutableDictionaryRef dict = NULL; + SecAccessControlRef access_control = NULL; + uint32_t version = 0; + + if (!ks_decrypt_data(SecDbItemGetKeybag(item), item->cryptoOp, &access_control, &item->credHandle, edata, item->class, item->callerAccessGroups, &dict, &version, error)) { + // Copy access control data, which might indicate why decryption failed. + if (neededAuth) + *neededAuth = SecAccessControlCopyData(access_control); + ok = false; + goto out; + } + + if (!dict) { + if (neededAuth) + *neededAuth = SecAccessControlCopyData(access_control); + else + require_quiet(ok = SecError(errSecInteractionNotAllowed, error, CFSTR("auth needed, but caller does not provide it")), out); + } else { + if (neededAuth) + *neededAuth = NULL; + if (version < 2) { + /* Old V4 style keychain backup being imported. */ + ok = SecDbItemSetValueWithName(item, CFSTR("v_Data"), CFDictionaryGetValue(dict, CFSTR("v_Data")), error) && + SecDbItemImportMigrate(item, error); + } else { + ok = dict && SecDbItemSetValues(item, dict, error); + } + } + + SecAccessControlRef my_access_control = SecDbItemCopyAccessControl(item, error); + if (!my_access_control) { + ok = false; + goto out; + } + + /* Make sure that the protection of ACL in the dictionary (read from DB) matched what we got + back from decoding the data blob. */ + if (!CFEqual(SecAccessControlGetProtection(my_access_control), SecAccessControlGetProtection(access_control))) { + ok = SecError(errSecDecode, error, CFSTR("ACL protection doesn't match the one in blob (%@ : %@)"), + SecAccessControlGetProtection(my_access_control), + SecAccessControlGetProtection(access_control)); + } + CFRelease(my_access_control); + + // Update real protection used for decrypting in the item. + ok = ok && SecDbItemSetAccessControl(item, access_control, error); + +out: + CFReleaseSafe(dict); + CFReleaseSafe(access_control); + return ok; +} + +/* Automagically make a item syncable, based on various attributes. */ +bool SecDbItemInferSyncable(SecDbItemRef item, CFErrorRef *error) +{ + CFStringRef agrp = SecDbItemGetCachedValueWithName(item, kSecAttrAccessGroup); + + if (!isString(agrp)) + return true; + + if (CFEqual(agrp, CFSTR("com.apple.cfnetwork")) && SecDbItemGetClass(item) == &inet_class) { + CFTypeRef srvr = SecDbItemGetCachedValueWithName(item, kSecAttrServer); + CFTypeRef ptcl = SecDbItemGetCachedValueWithName(item, kSecAttrProtocol); + CFTypeRef atyp = SecDbItemGetCachedValueWithName(item, kSecAttrAuthenticationType); + + if (isString(srvr) && isString(ptcl) && isString(atyp)) { + /* This looks like a Mobile Safari Password, make syncable */ + secnotice("item", "Make this item syncable: %@", item); + return SecDbItemSetSyncable(item, true, error); + } + } + + return true; +} + +/* This create a SecDbItem from the item dictionnary that are exported for backups. + Item are stored in the backup as a dictionary containing two keys: + - v_Data: the encrypted data blob + - v_PersistentRef: a persistent Ref. + src_keybag is normally the backup keybag. + dst_keybag is normally the device keybag. + */ +SecDbItemRef SecDbItemCreateWithBackupDictionary(CFAllocatorRef allocator, const SecDbClass *dbclass, CFDictionaryRef dict, keybag_handle_t src_keybag, keybag_handle_t dst_keybag, CFErrorRef *error) +{ + CFDataRef edata = CFDictionaryGetValue(dict, CFSTR("v_Data")); + SecDbItemRef item = NULL; + + if (edata) { + item = SecDbItemCreateWithEncryptedData(kCFAllocatorDefault, dbclass, edata, src_keybag, error); + if (item) + if (!SecDbItemSetKeybag(item, dst_keybag, error)) + CFReleaseNull(item); + } else { + SecError(errSecDecode, error, CFSTR("No v_Data in backup dictionary %@"), dict); + } + + return item; +} + +bool SecDbItemExtractRowIdFromBackupDictionary(SecDbItemRef item, CFDictionaryRef dict, CFErrorRef *error) { + CFDataRef ref = CFDictionaryGetValue(dict, CFSTR("v_PersistentRef")); + if (!ref) + return SecError(errSecDecode, error, CFSTR("No v_PersistentRef in backup dictionary %@"), dict); + + CFStringRef className; + sqlite3_int64 rowid; + if (!_SecItemParsePersistentRef(ref, &className, &rowid)) + return SecError(errSecDecode, error, CFSTR("v_PersistentRef %@ failed to decode"), ref); + + if (!CFEqual(SecDbItemGetClass(item)->name, className)) + return SecError(errSecDecode, error, CFSTR("v_PersistentRef has unexpected class %@"), className); + + return SecDbItemSetRowId(item, rowid, error); +} diff --git a/Security/sec/securityd/SecDbKeychainItem.h b/Security/sec/securityd/SecDbKeychainItem.h new file mode 100644 index 00000000..63a82d4d --- /dev/null +++ b/Security/sec/securityd/SecDbKeychainItem.h @@ -0,0 +1,50 @@ +/* + * 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@ + */ + +/*! + @header SecDbKeychainItem.h - The thing that does the stuff with the gibli. + */ + +#ifndef _SECURITYD_SECKEYCHAINITEM_H_ +#define _SECURITYD_SECKEYCHAINITEM_H_ + +#include +#include +#include + +__BEGIN_DECLS + +bool ks_encrypt_data(keybag_handle_t keybag, SecAccessControlRef access_control, CFTypeRef *cred_handle, + CFDictionaryRef attributes, CFDictionaryRef authenticated_attributes, CFDataRef *pBlob, CFErrorRef *error); +bool ks_decrypt_data(keybag_handle_t keybag, enum SecKsCryptoOp cryptoOp, SecAccessControlRef *paccess_control, CFTypeRef *cred_handle, + CFDataRef blob, const SecDbClass *db_class, CFArrayRef caller_access_groups, + CFMutableDictionaryRef *attributes_p, uint32_t *version_p, CFErrorRef *error); +bool s3dl_item_from_data(CFDataRef edata, Query *q, CFArrayRef accessGroups, + CFMutableDictionaryRef *item, SecAccessControlRef *access_control, CFErrorRef *error); +SecDbItemRef SecDbItemCreateWithBackupDictionary(CFAllocatorRef allocator, const SecDbClass *dbclass, CFDictionaryRef dict, keybag_handle_t src_keybag, keybag_handle_t dst_keybag, CFErrorRef *error); +bool SecDbItemExtractRowIdFromBackupDictionary(SecDbItemRef item, CFDictionaryRef dict, CFErrorRef *error); +bool SecDbItemInferSyncable(SecDbItemRef item, CFErrorRef *error); + +__END_DECLS + +#endif /* _SECURITYD_SECKEYCHAINITEM_H_ */ diff --git a/Security/sec/securityd/SecDbQuery.c b/Security/sec/securityd/SecDbQuery.c new file mode 100644 index 00000000..98c6e539 --- /dev/null +++ b/Security/sec/securityd/SecDbQuery.c @@ -0,0 +1,842 @@ +/* + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + */ + +/* + * SecDbQuery.c - CoreFoundation-based constants and functions for + access to Security items (certificates, keys, identities, and + passwords.) + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#if USE_KEYSTORE +#include +#include +#include +#endif + +/* Upper limit for number of keys in a QUERY dictionary. */ +#define QUERY_KEY_LIMIT_BASE (128) +#ifdef NO_SERVER +#define QUERY_KEY_LIMIT (31 + QUERY_KEY_LIMIT_BASE) +#else +#define QUERY_KEY_LIMIT QUERY_KEY_LIMIT_BASE +#endif + +/* Inline accessors to attr and match values in a query. */ +CFIndex query_attr_count(const Query *q) +{ + return q->q_attr_end; +} + +Pair query_attr_at(const Query *q, CFIndex ix) +{ + return q->q_pairs[ix]; +} + +CFIndex query_match_count(const Query *q) +{ + return q->q_match_end - q->q_match_begin; +} + +__unused static inline Pair query_match_at(const Query *q, CFIndex ix) +{ + return q->q_pairs[q->q_match_begin + ix]; +} + +/* Private routines used to parse a query. */ + +const SecDbClass *kc_class_with_name(CFStringRef name) { + if (isString(name)) { +#if 0 + // TODO Iterate kc_db_classes and look for name == class->name. + // Or get clever and switch on first letter of class name and compare to verify + static const void *kc_db_classes[] = { + &genp_class, + &inet_class, + &cert_class, + &keys_class, + &identity_class + }; +#endif + if (CFEqual(name, kSecClassGenericPassword)) + return &genp_class; + else if (CFEqual(name, kSecClassInternetPassword)) + return &inet_class; + else if (CFEqual(name, kSecClassCertificate)) + return &cert_class; + else if (CFEqual(name, kSecClassKey)) + return &keys_class; + else if (CFEqual(name, kSecClassIdentity)) + return &identity_class; + } + return NULL; +} + +static void query_set_access_control(Query *q, SecAccessControlRef access_control) { + if (q->q_access_control) { + if (!CFEqual(q->q_access_control, access_control)) { + SecError(errSecItemIllegalQuery, &q->q_error, CFSTR("conflicting kSecAccess and kSecAccessControl attributes")); + } + } else { + /* Store access control virtual attribute. */ + q->q_access_control = (SecAccessControlRef)CFRetain(access_control); + + /* Also set legacy access attribute. */ + CFDictionarySetValue(q->q_item, kSecAttrAccessible, SecAccessControlGetProtection(q->q_access_control)); + } +} + +/* AUDIT[securityd](done): + key (ok) is a caller provided, string or number of length 4. + value (ok) is a caller provided, non NULL CFTypeRef. + */ +static void query_add_attribute_with_desc(const SecDbAttr *desc, const void *value, Query *q) +{ + if (CFEqual(desc->name, kSecAttrSynchronizable)) { + q->q_sync = true; + if (CFEqual(value, kSecAttrSynchronizableAny)) + return; /* skip the attribute so it isn't part of the search */ + } + + CFTypeRef attr = NULL; + switch (desc->kind) { + case kSecDbDataAttr: + attr = copyData(value); + break; + case kSecDbBlobAttr: + case kSecDbAccessControlAttr: + attr = copyBlob(value); + break; + case kSecDbDateAttr: + case kSecDbCreationDateAttr: + case kSecDbModificationDateAttr: + attr = copyDate(value); + break; + case kSecDbNumberAttr: + case kSecDbSyncAttr: + case kSecDbTombAttr: + attr = copyNumber(value); + break; + case kSecDbAccessAttr: + case kSecDbStringAttr: + attr = copyString(value); + break; + case kSecDbSHA1Attr: + attr = copySHA1(value); + break; + case kSecDbRowIdAttr: + case kSecDbPrimaryKeyAttr: + case kSecDbEncryptedDataAttr: + break; + } + + if (!attr) { + SecError(errSecItemInvalidValue, &q->q_error, CFSTR("attribute %@: value: %@ failed to convert"), desc->name, value); + return; + } + + /* Store plaintext attr data in q_item unless it's a kSecDbSHA1Attr. */ + if (q->q_item && desc->kind != kSecDbSHA1Attr) { + CFDictionarySetValue(q->q_item, desc->name, attr); + } + + if (desc->kind == kSecDbAccessControlAttr) { + SecAccessControlRef access_control = SecAccessControlCreateFromData(kCFAllocatorDefault, attr, &q->q_error); + if (access_control) { + query_set_access_control(q, access_control); + CFRelease(access_control); + } + } + + if (desc->kind == kSecDbAccessAttr) { + SecAccessControlRef access_control = SecAccessControlCreateWithFlags(kCFAllocatorDefault, attr, 0, &q->q_error); + if (access_control) { + query_set_access_control(q, access_control); + CFRelease(access_control); + } + } + + /* Convert attr to (sha1) digest if requested. */ + if (desc->flags & kSecDbSHA1ValueInFlag) { + CFDataRef data = copyData(attr); + CFRelease(attr); + if (!data) { + SecError(errSecInternal, &q->q_error, CFSTR("failed to get attribute %@ data"), desc->name); + return; + } + + CFMutableDataRef digest = CFDataCreateMutable(0, CC_SHA1_DIGEST_LENGTH); + CFDataSetLength(digest, CC_SHA1_DIGEST_LENGTH); + /* 64 bits cast: worst case is we generate the wrong hash */ + assert((unsigned long)CFDataGetLength(data)kind != kSecDbAccessControlAttr) { + /* Record the new attr key, value in q_pairs. */ + q->q_pairs[q->q_attr_end].key = desc->name; + q->q_pairs[q->q_attr_end++].value = attr; + } else { + CFReleaseSafe(attr); + } +} + +void query_add_attribute(const void *key, const void *value, Query *q) +{ + const SecDbAttr *desc = SecDbAttrWithKey(q->q_class, key, &q->q_error); + if (desc) + query_add_attribute_with_desc(desc, value, q); +} + +/* First remove key from q->q_pairs if it's present, then add the attribute again. */ +static void query_set_attribute_with_desc(const SecDbAttr *desc, const void *value, Query *q) { + if (CFDictionaryContainsKey(q->q_item, desc->name)) { + CFIndex ix; + for (ix = 0; ix < q->q_attr_end; ++ix) { + if (CFEqual(desc->name, q->q_pairs[ix].key)) { + CFReleaseSafe(q->q_pairs[ix].value); + --q->q_attr_end; + for (; ix < q->q_attr_end; ++ix) { + q->q_pairs[ix] = q->q_pairs[ix + 1]; + } + CFDictionaryRemoveValue(q->q_item, desc->name); + break; + } + } + } + query_add_attribute_with_desc(desc, value, q); +} + +/* AUDIT[securityd](done): + key (ok) is a caller provided, string starting with 'm'. + value (ok) is a caller provided, non NULL CFTypeRef. + */ +static void query_add_match(const void *key, const void *value, Query *q) +{ + /* Record the match key, value in q_pairs. */ + --(q->q_match_begin); + q->q_pairs[q->q_match_begin].key = key; + q->q_pairs[q->q_match_begin].value = value; + + if (CFEqual(kSecMatchLimit, key)) { + /* Figure out what the value for kSecMatchLimit is if specified. */ + if (CFGetTypeID(value) == CFNumberGetTypeID()) { + if (!CFNumberGetValue(value, kCFNumberCFIndexType, &q->q_limit)) + SecError(errSecItemInvalidValue, &q->q_error, CFSTR("failed to convert match limit %@ to CFIndex"), value); + } else if (CFEqual(kSecMatchLimitAll, value)) { + q->q_limit = kSecMatchUnlimited; + } else if (CFEqual(kSecMatchLimitOne, value)) { + q->q_limit = 1; + } else { + SecError(errSecItemInvalidValue, &q->q_error, CFSTR("unsupported match limit %@"), value); + } + } else if (CFEqual(kSecMatchIssuers, key) && + (CFGetTypeID(value) == CFArrayGetTypeID())) + { + CFMutableArrayRef canonical_issuers = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + if (canonical_issuers) { + CFIndex i, count = CFArrayGetCount(value); + for (i = 0; i < count; i++) { + CFTypeRef issuer_data = CFArrayGetValueAtIndex(value, i); + CFDataRef issuer_canonical = NULL; + if (CFDataGetTypeID() == CFGetTypeID(issuer_data)) + issuer_canonical = SecDistinguishedNameCopyNormalizedContent((CFDataRef)issuer_data); + if (issuer_canonical) { + CFArrayAppendValue(canonical_issuers, issuer_canonical); + CFRelease(issuer_canonical); + } + } + + if (CFArrayGetCount(canonical_issuers) > 0) { + q->q_match_issuer = canonical_issuers; + } else + CFRelease(canonical_issuers); + } + } +} + +static bool query_set_class(Query *q, CFStringRef c_name, CFErrorRef *error) { + const SecDbClass *value; + if (c_name && CFGetTypeID(c_name) == CFStringGetTypeID() && + (value = kc_class_with_name(c_name)) && + (q->q_class == 0 || q->q_class == value)) { + q->q_class = value; + return true; + } + + if (error && !*error) + SecError((c_name ? errSecNoSuchClass : errSecItemClassMissing), error, CFSTR("can find class named: %@"), c_name); + + + return false; +} + +static const SecDbClass *query_get_class(CFDictionaryRef query, CFErrorRef *error) { + CFStringRef c_name = NULL; + const void *value = CFDictionaryGetValue(query, kSecClass); + if (isString(value)) { + c_name = value; + } else { + value = CFDictionaryGetValue(query, kSecValuePersistentRef); + if (isData(value)) { + CFDataRef pref = value; + _SecItemParsePersistentRef(pref, &c_name, 0); + } + } + + if (c_name && (value = kc_class_with_name(c_name))) { + return value; + } else { + if (c_name) + SecError(errSecNoSuchClass, error, CFSTR("can't find class named: %@"), c_name); + else + SecError(errSecItemClassMissing, error, CFSTR("query missing class name")); + return NULL; + } +} + +/* AUDIT[securityd](done): + key (ok) is a caller provided, string starting with 'c'. + value (ok) is a caller provided, non NULL CFTypeRef. + */ +static void query_add_class(const void *key, const void *value, Query *q) +{ + if (CFEqual(key, kSecClass)) { + query_set_class(q, value, &q->q_error); + } else { + SecError(errSecItemInvalidKey, &q->q_error, CFSTR("add_class: key %@ is not %@"), key, kSecClass); + } +} + +/* AUDIT[securityd](done): + key (ok) is a caller provided, string starting with 'r'. + value (ok) is a caller provided, non NULL CFTypeRef. + */ +static void query_add_return(const void *key, const void *value, Query *q) +{ + ReturnTypeMask mask; + if (CFGetTypeID(value) != CFBooleanGetTypeID()) { + SecError(errSecItemInvalidValue, &q->q_error, CFSTR("add_return: value %@ is not CFBoolean"), value); + return; + } + + int set_it = CFEqual(value, kCFBooleanTrue); + + if (CFEqual(key, kSecReturnData)) + mask = kSecReturnDataMask; + else if (CFEqual(key, kSecReturnAttributes)) + mask = kSecReturnAttributesMask; + else if (CFEqual(key, kSecReturnRef)) + mask = kSecReturnRefMask; + else if (CFEqual(key, kSecReturnPersistentRef)) + mask = kSecReturnPersistentRefMask; + else { + SecError(errSecItemInvalidKey, &q->q_error, CFSTR("add_return: unknown key %@"), key); + return; + } + + if ((q->q_return_type & mask) && !set_it) { + /* Clear out this bit (it's set so xor with the mask will clear it). */ + q->q_return_type ^= mask; + } else if (!(q->q_return_type & mask) && set_it) { + /* Set this bit. */ + q->q_return_type |= mask; + } +} + +/* AUDIT[securityd](done): + key (ok) is a caller provided, string starting with 'u'. + value (ok since q_use_item_list is unused) is a caller provided, non + NULL CFTypeRef. + */ +static void query_add_use(const void *key, const void *value, Query *q) +{ + if (CFEqual(key, kSecUseItemList)) { + /* TODO: Add sanity checking when we start using this. */ + q->q_use_item_list = value; + } else if (CFEqual(key, kSecUseTombstones)) { + if (CFGetTypeID(value) == CFBooleanGetTypeID()) { + q->q_use_tomb = value; + } else if (CFGetTypeID(value) == CFNumberGetTypeID()) { + q->q_use_tomb = CFBooleanGetValue(value) ? kCFBooleanTrue : kCFBooleanFalse; + } else if (CFGetTypeID(value) == CFStringGetTypeID()) { + q->q_use_tomb = CFStringGetIntValue(value) ? kCFBooleanTrue : kCFBooleanFalse; + } else { + SecError(errSecItemInvalidValue, &q->q_error, CFSTR("add_use: value %@ for key %@ is neither CFBoolean nor CFNumber"), value, key); + return; + } + } else if (CFEqual(key, kSecUseCredentialReference)) { + if (isData(value)) { + CFRetainAssign(q->q_use_cred_handle, value); + } else { + SecError(errSecItemInvalidValue, &q->q_error, CFSTR("add_use: value %@ for key %@ is not CFData"), value, key); + return; + } + } else if (CFEqual(key, kSecUseOperationPrompt)) { + if (isString(value)) { + CFRetainAssign(q->q_use_operation_prompt, value); + } else { + SecError(errSecItemInvalidValue, &q->q_error, CFSTR("add_use: value %@ for key %@ is not CFString"), value, key); + return; + } + } else if (CFEqual(key, kSecUseNoAuthenticationUI)) { + if (isBoolean(value)) { + q->q_use_no_authentication_ui = value; + } else if (isNumber(value)) { + q->q_use_no_authentication_ui = CFBooleanGetValue(value) ? kCFBooleanTrue : kCFBooleanFalse; + } else if (isString(value)) { + q->q_use_no_authentication_ui = CFStringGetIntValue(value) ? kCFBooleanTrue : kCFBooleanFalse; + } else { + SecError(errSecItemInvalidValue, &q->q_error, CFSTR("add_use: value %@ for key %@ is neither CFBoolean nor CFNumber"), 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) */ + } else { + SecError(errSecItemInvalidKey, &q->q_error, CFSTR("add_use: unknown key %@"), key); + return; + } +} + +static void query_set_data(const void *value, Query *q) { + if (!isData(value)) { + SecError(errSecItemInvalidValue, &q->q_error, CFSTR("set_data: value %@ is not type data"), value); + } else { + q->q_data = value; + if (q->q_item) + CFDictionarySetValue(q->q_item, kSecValueData, value); + } +} + +/* AUDIT[securityd](done): + key (ok) is a caller provided, string starting with 'u'. + value (ok) is a caller provided, non NULL CFTypeRef. + */ +static void query_add_value(const void *key, const void *value, Query *q) +{ + if (CFEqual(key, kSecValueData)) { + query_set_data(value, q); +#ifdef NO_SERVER + } else if (CFEqual(key, kSecValueRef)) { + q->q_ref = value; + /* TODO: Add value type sanity checking. */ +#endif + } else if (CFEqual(key, kSecValuePersistentRef)) { + CFStringRef c_name; + if (_SecItemParsePersistentRef(value, &c_name, &q->q_row_id)) + query_set_class(q, c_name, &q->q_error); + else + SecError(errSecItemInvalidValue, &q->q_error, CFSTR("add_value: value %@ is not a valid persitent ref"), value); + } else { + SecError(errSecItemInvalidKey, &q->q_error, CFSTR("add_value: unknown key %@"), key); + return; + } +} + +/* AUDIT[securityd](done): + key (ok) is a caller provided, unchecked. + value (ok) is a caller provided, unchecked. + */ +static void query_update_applier(const void *key, const void *value, + void *context) +{ + Query *q = (Query *)context; + /* If something went wrong there is no point processing any more args. */ + if (q->q_error) + return; + + /* Make sure we have a string key. */ + if (!isString(key)) { + SecError(errSecItemInvalidKeyType, &q->q_error, CFSTR("update_applier: unknown key type %@"), key); + return; + } + + if (!value) { + SecError(errSecItemInvalidValue, &q->q_error, CFSTR("update_applier: key %@ has NULL value"), key); + return; + } + + if (CFEqual(key, kSecValueData)) { + query_set_data(value, q); + } else { + query_add_attribute(key, value, q); + } +} + +/* AUDIT[securityd](done): + key (ok) is a caller provided, unchecked. + value (ok) is a caller provided, unchecked. + */ +static void query_applier(const void *key, const void *value, void *context) +{ + Query *q = (Query *)context; + /* If something went wrong there is no point processing any more args. */ + if (q->q_error) + return; + + /* Make sure we have a key. */ + if (!key) { + SecError(errSecItemInvalidKeyType, &q->q_error, CFSTR("applier: NULL key")); + return; + } + + /* Make sure we have a value. */ + if (!value) { + SecError(errSecItemInvalidValue, &q->q_error, CFSTR("applier: key %@ has NULL value"), key); + return; + } + + /* Figure out what type of key we are dealing with. */ + CFTypeID key_id = CFGetTypeID(key); + if (key_id == CFStringGetTypeID()) { + CFIndex key_len = CFStringGetLength(key); + /* String keys can be different things. The subtype is determined by: + length 4 strings are all attributes. Otherwise the first char + determines the type: + c: class must be kSecClass + m: match like kSecMatchPolicy + r: return like kSecReturnData + u: use keys + v: value + */ + if (key_len == 4) { + /* attributes */ + query_add_attribute(key, value, q); + } else if (key_len > 1) { + UniChar k_first_char = CFStringGetCharacterAtIndex(key, 0); + switch (k_first_char) + { + case 'c': /* class */ + query_add_class(key, value, q); + break; + case 'm': /* match */ + query_add_match(key, value, q); + break; + case 'r': /* return */ + query_add_return(key, value, q); + break; + case 'u': /* use */ + query_add_use(key, value, q); + break; + case 'v': /* value */ + query_add_value(key, value, q); + break; + default: + SecError(errSecItemInvalidKey, &q->q_error, CFSTR("applier: key %@ invalid"), key); + break; + } + } else { + SecError(errSecItemInvalidKey, &q->q_error, CFSTR("applier: key %@ invalid length"), key); + } + } else if (key_id == CFNumberGetTypeID()) { + /* Numeric keys are always (extended) attributes. */ + /* TODO: Why is this here? query_add_attribute() doesn't take numbers. */ + query_add_attribute(key, value, q); + } else { + /* We only support string and number type keys. */ + SecError(errSecItemInvalidKeyType, &q->q_error, CFSTR("applier: key %@ neither string nor number"), key); + } +} + +static CFStringRef query_infer_keyclass(Query *q, CFStringRef agrp) { + /* apsd and lockdown are always dku. */ + if (CFEqual(agrp, CFSTR("com.apple.apsd")) + || CFEqual(agrp, CFSTR("lockdown-identities"))) { + return kSecAttrAccessibleAlwaysThisDeviceOnly; + } + /* All other certs or in the apple agrp is dk. */ + if (q->q_class == &cert_class) { + /* third party certs are always dk. */ + return kSecAttrAccessibleAlways; + } + /* The rest defaults to ak. */ + return kSecAttrAccessibleWhenUnlocked; +} + +void query_ensure_access_control(Query *q, CFStringRef agrp) { + if (q->q_access_control == 0) { + CFStringRef accessible = query_infer_keyclass(q, agrp); + query_add_attribute(kSecAttrAccessible, accessible, q); + } +} + +bool query_error(Query *q, CFErrorRef *error) { + CFErrorRef tmp = q->q_error; + q->q_error = NULL; + return CFErrorPropagate(tmp, error); +} + +bool query_destroy(Query *q, CFErrorRef *error) { + bool ok = query_error(q, error); + CFIndex ix, attr_count = query_attr_count(q); + for (ix = 0; ix < attr_count; ++ix) { + CFReleaseSafe(query_attr_at(q, ix).value); + } + CFReleaseSafe(q->q_item); + CFReleaseSafe(q->q_primary_key_digest); + CFReleaseSafe(q->q_match_issuer); + CFReleaseSafe(q->q_access_control); + CFReleaseSafe(q->q_use_cred_handle); + CFReleaseSafe(q->q_required_access_controls); + CFReleaseSafe(q->q_use_operation_prompt); + CFReleaseSafe(q->q_caller_access_groups); + + free(q); + return ok; +} + +bool query_notify_and_destroy(Query *q, bool ok, CFErrorRef *error) { + if (ok && !q->q_error && q->q_sync_changed) { + SecKeychainChanged(true); + } + return query_destroy(q, error) && ok; +} + +/* Allocate and initialize a Query object for query. */ +Query *query_create(const SecDbClass *qclass, CFDictionaryRef query, + CFErrorRef *error) +{ + if (!qclass) { + if (error && !*error) + SecError(errSecItemClassMissing, error, CFSTR("Missing class")); + return NULL; + } + + /* 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. */ + CFIndex key_count = SecDbClassAttrCount(qclass); + if (key_count == 0) { + // Identities claim to have 0 attributes, but they really support any keys or cert attribute. + key_count = SecDbClassAttrCount(&cert_class) + SecDbClassAttrCount(&keys_class); + } + + if (query) { + key_count += CFDictionaryGetCount(query); + SecDbForEachAttr(qclass, attr) { + if (CFDictionaryContainsKey(query, attr->name)) + --key_count; + } + } + + if (key_count > QUERY_KEY_LIMIT) { + if (error && !*error) + { + secerror("key_count: %ld, QUERY_KEY_LIMIT: %d", (long)key_count, QUERY_KEY_LIMIT); + SecError(errSecItemIllegalQuery, error, CFSTR("Past query key limit")); + } + return NULL; + } + + Query *q = calloc(1, sizeof(Query) + sizeof(Pair) * key_count); + if (q == NULL) { + if (error && !*error) + SecError(errSecAllocate, error, CFSTR("Out of memory")); + return NULL; + } + + q->q_keybag = KEYBAG_DEVICE; + q->q_class = qclass; + q->q_match_begin = q->q_match_end = key_count; + q->q_item = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + q->q_crypto_op = kSecKsUnwrap; + + return q; +} + +/* Parse query for a Query object q. */ +static bool query_parse_with_applier(Query *q, CFDictionaryRef query, + CFDictionaryApplierFunction applier, + CFErrorRef *error) { + CFDictionaryApplyFunction(query, applier, q); + return query_error(q, error); +} + +/* Parse query for a Query object q. */ +static bool query_parse(Query *q, CFDictionaryRef query, + CFErrorRef *error) { + return query_parse_with_applier(q, query, query_applier, error); +} + +/* Parse query for a Query object q. */ +bool query_update_parse(Query *q, CFDictionaryRef update, + CFErrorRef *error) { + return query_parse_with_applier(q, update, query_update_applier, error); +} + +Query *query_create_with_limit(CFDictionaryRef query, CFIndex limit, + CFErrorRef *error) { + Query *q; + q = query_create(query_get_class(query, error), query, error); + if (q) { + q->q_limit = limit; + if (!query_parse(q, query, error)) { + query_destroy(q, error); + return NULL; + } + if (!q->q_sync && !q->q_row_id) { + /* query did not specify a kSecAttrSynchronizable attribute, + * and did not contain a persistent reference. */ + query_add_attribute(kSecAttrSynchronizable, kCFBooleanFalse, q); + } + } + return q; +} + + +//TODO: Move this to SecDbItemRef + +/* Make sure all attributes that are marked as not_null have a value. If + force_date is false, only set mdat and cdat if they aren't already set. */ +void +query_pre_add(Query *q, bool force_date) { + CFDateRef now = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); + SecDbForEachAttrWithMask(q->q_class, desc, kSecDbInFlag) { + if (desc->kind == kSecDbCreationDateAttr || + desc->kind == kSecDbModificationDateAttr) { + if (force_date) { + query_set_attribute_with_desc(desc, now, q); + } else if (!CFDictionaryContainsKey(q->q_item, desc->name)) { + query_add_attribute_with_desc(desc, now, q); + } + } else if ((desc->flags & kSecDbNotNullFlag) && + !CFDictionaryContainsKey(q->q_item, desc->name)) { + CFTypeRef value = NULL; + if (desc->flags & kSecDbDefault0Flag) { + if (desc->kind == kSecDbDateAttr) + value = CFDateCreate(kCFAllocatorDefault, 0.0); + else { + SInt32 vzero = 0; + value = CFNumberCreate(0, kCFNumberSInt32Type, &vzero); + } + } else if (desc->flags & kSecDbDefaultEmptyFlag) { + if (desc->kind == kSecDbDataAttr) + value = CFDataCreate(kCFAllocatorDefault, NULL, 0); + else { + value = CFSTR(""); + CFRetain(value); + } + } + if (value) { + /* Safe to use query_add_attribute here since the attr wasn't + set yet. */ + query_add_attribute_with_desc(desc, value, q); + CFRelease(value); + } + } + } + CFReleaseSafe(now); +} + +//TODO: Move this to SecDbItemRef + +/* Update modification_date if needed. */ +void +query_pre_update(Query *q) { + SecDbForEachAttr(q->q_class, desc) { + if (desc->kind == kSecDbModificationDateAttr) { + CFDateRef now = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); + query_set_attribute_with_desc(desc, now, q); + CFReleaseSafe(now); + } + } +} + +void +query_set_caller_access_groups(Query *q, CFArrayRef caller_access_groups) { + CFRetainAssign(q->q_caller_access_groups, caller_access_groups); +} + +bool +query_needs_authentication(Query *q) { + return q->q_required_access_controls && CFArrayGetCount(q->q_required_access_controls) > 0; +} + +void +query_enable_interactive(Query *q) { + CFAssignRetained(q->q_required_access_controls, CFArrayCreateMutableForCFTypes(kCFAllocatorDefault)); +} + +bool +query_authenticate(Query *q, CFErrorRef **error) { + bool ok = true; + CFMutableDictionaryRef hints = NULL; +#if USE_KEYSTORE + if (q->q_use_no_authentication_ui && CFBooleanGetValue(q->q_use_no_authentication_ui)) { + SecError(errSecInteractionNotAllowed, *error, CFSTR("authentication UI is not allowed")); + return false; + } + if (isString(q->q_use_operation_prompt)) { + if (!hints) { + hints = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + } + // VRHintAppAction + CFNumberRef reasonKey = CFNumberCreateWithCFIndex(kCFAllocatorDefault, kLAOptionAuthenticationReason); + CFDictionaryAddValue(hints, reasonKey, q->q_use_operation_prompt); + CFRelease(reasonKey); + } + + if (*error) + CFReleaseNull(**error); + + CFErrorRef authError = NULL; + CFDataRef ac_data; + CFArrayForEachC(q->q_required_access_controls, ac_data) { + ok = VREvaluateACL(q->q_use_cred_handle, ac_data, kAKSKeyOpDecrypt, hints, &authError); + if (!ok) { + ok = SecCFCreateError(errSecAuthFailed, kSecErrorDomain, CFSTR("LocalAuthentication failed"), authError, *error); + CFReleaseSafe(authError); + goto out; + } + } + CFArrayRemoveAllValues(q->q_required_access_controls); + +out: +#endif + CFReleaseSafe(hints); + return ok; +} diff --git a/Security/sec/securityd/SecDbQuery.h b/Security/sec/securityd/SecDbQuery.h new file mode 100644 index 00000000..fff782e2 --- /dev/null +++ b/Security/sec/securityd/SecDbQuery.h @@ -0,0 +1,163 @@ +/* + * 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@ + */ + +/*! + @header SecDbQuery.h - The thing that does the stuff with the gibli. + */ + +#ifndef _SECURITYD_SECDBQUERY_H_ +#define _SECURITYD_SECDBQUERY_H_ + +#include +#include + +__BEGIN_DECLS + +typedef struct Pair *SecDbPairRef; +typedef struct Query *SecDbQueryRef; + +/* Return types. */ +typedef uint32_t ReturnTypeMask; +enum +{ + kSecReturnDataMask = 1 << 0, + kSecReturnAttributesMask = 1 << 1, + kSecReturnRefMask = 1 << 2, + kSecReturnPersistentRefMask = 1 << 3, +}; + +/* Constant indicating there is no limit to the number of results to return. */ +enum +{ + kSecMatchUnlimited = kCFNotFound +}; + +typedef struct Pair +{ + const void *key; + const void *value; +} Pair; + +/* Nothing in this struct is retained since all the + values below are extracted from the dictionary passed in by the + caller. */ +typedef struct Query +{ + /* Class of this query. */ + const SecDbClass *q_class; + + /* Dictionary with all attributes and values in clear (to be encrypted). */ + CFMutableDictionaryRef q_item; + + /* q_pairs is an array of Pair structs. Elements with indices + [0, q_attr_end) contain attribute key value pairs. Elements with + indices [q_match_begin, q_match_end) contain match key value pairs. + Thus q_attr_end is the number of attrs in q_pairs and + q_match_begin - q_match_end is the number of matches in q_pairs. */ + CFIndex q_match_begin; + CFIndex q_match_end; + CFIndex q_attr_end; + + CFErrorRef q_error; + ReturnTypeMask q_return_type; + + CFDataRef q_data; + CFTypeRef q_ref; + sqlite_int64 q_row_id; + + 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; + + /* True if query contained a kSecAttrSynchronizable attribute, + * regardless of its actual value. If this is false, then we + * will add an explicit sync=0 to the query. */ + bool q_sync; + + // Set to true if we modified any item as part of executing this query + bool q_changed; + + // Set to true if we modified any synchronizable item as part of executing this query + bool q_sync_changed; + + // Set to true if we want to delete item + enum SecKsCryptoOp q_crypto_op; + + /* Keybag handle to use for this item. */ + keybag_handle_t q_keybag; + + /* ACL and credHandle passed to the query. q_use_cred_handle can contain either CFDataRef passed from outside + * or CoreAuth context object. */ + SecAccessControlRef q_access_control; + CFTypeRef q_use_cred_handle; + + // Array filled during the query execution with CFDataRef conatining serialized SecAccessControl objects + // which need to be verified in order to include all items in the results. + CFMutableArrayRef q_required_access_controls; + + // Text describing the operation for which the application is attempting to authenticate. + CFStringRef q_use_operation_prompt; + + // True if the authentication UI is not allowed. + CFBooleanRef q_use_no_authentication_ui; + + // SHA1 digest of DER encoded primary key + CFDataRef q_primary_key_digest; + + CFArrayRef q_match_issuer; + + /* Caller acces groups for AKS */ + CFArrayRef q_caller_access_groups; + + Pair q_pairs[]; +} Query; + +Query *query_create(const SecDbClass *qclass, 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); +void query_add_attribute(const void *key, const void *value, Query *q); +void query_ensure_access_control(Query *q, CFStringRef agrp); +void query_pre_add(Query *q, bool force_date); +bool query_notify_and_destroy(Query *q, bool ok, CFErrorRef *error); +CFIndex query_match_count(const Query *q); +CFIndex query_attr_count(const Query *q); +Pair query_attr_at(const Query *q, CFIndex ix); +bool query_update_parse(Query *q, CFDictionaryRef update, CFErrorRef *error); +void query_pre_update(Query *q); +void query_enable_interactive(Query *q); +bool query_needs_authentication(Query *q); +bool query_authenticate(Query *q, CFErrorRef **error); +const SecDbClass *kc_class_with_name(CFStringRef name); +void query_set_caller_access_groups(Query *q, CFArrayRef caller_access_groups); + + +__END_DECLS + +#endif /* _SECURITYD_SECDBQUERY_H_ */ diff --git a/Security/sec/securityd/SecItemDataSource.c b/Security/sec/securityd/SecItemDataSource.c new file mode 100644 index 00000000..af0b3131 --- /dev/null +++ b/Security/sec/securityd/SecItemDataSource.c @@ -0,0 +1,640 @@ +/* + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + */ + +/* + * SecItemDataSource.c - CoreFoundation-based constants and functions for + access to Security items (certificates, keys, identities, and + passwords.) + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * + * + * SecItemDataSource + * + * + */ +typedef struct SecItemDataSource *SecItemDataSourceRef; + +struct SecItemDataSource { + struct SOSDataSource ds; + SecDbRef db; // The database we operate on + CFStringRef name; // The name of the slice of the database we represent. +}; + +static const SecDbClass *dsSyncedClasses[] = { + &genp_class, + &inet_class, + &keys_class, +}; + +static bool SecDbItemSelectSHA1(SecDbQueryRef query, SecDbConnectionRef dbconn, CFErrorRef *error, + bool (^use_attr_in_where)(const SecDbAttr *attr), + bool (^add_where_sql)(CFMutableStringRef sql, bool *needWhere), + bool (^bind_added_where)(sqlite3_stmt *stmt, int col), + void (^row)(sqlite3_stmt *stmt, bool *stop)) { + __block bool ok = true; + bool (^return_attr)(const SecDbAttr *attr) = ^bool (const SecDbAttr * attr) { + return attr->kind == kSecDbSHA1Attr; + }; + CFStringRef sql = SecDbItemCopySelectSQL(query, return_attr, use_attr_in_where, add_where_sql); + if (sql) { + ok &= SecDbPrepare(dbconn, sql, error, ^(sqlite3_stmt *stmt) { + ok = (SecDbItemSelectBind(query, stmt, error, use_attr_in_where, bind_added_where) && + SecDbStep(dbconn, stmt, error, ^(bool *stop){ row(stmt, stop); })); + }); + CFRelease(sql); + } else { + ok = false; + } + return ok; +} + +static SOSManifestRef SecItemDataSourceCopyManifest(SecItemDataSourceRef ds, CFErrorRef *error) { + __block SOSManifestRef manifest = NULL; + __block CFErrorRef localError = NULL; + if (!SecDbPerformRead(ds->db, error, ^(SecDbConnectionRef dbconn) { + __block struct SOSDigestVector dv = SOSDigestVectorInit; + for (size_t class_ix = 0; class_ix < array_size(dsSyncedClasses); + ++class_ix) { + Query *q = query_create(dsSyncedClasses[class_ix], NULL, error); + if (q) { + q->q_return_type = kSecReturnDataMask | kSecReturnAttributesMask; + q->q_limit = kSecMatchUnlimited; + q->q_keybag = KEYBAG_DEVICE; + query_add_attribute(kSecAttrSynchronizable, kCFBooleanTrue, q); + //query_add_attribute(kSecAttrAccessible, ds->name, q); + // Select everything including tombstones that is synchronizable. + if (!SecDbItemSelectSHA1(q, dbconn, &localError, ^bool(const SecDbAttr *attr) { + return attr->kind == kSecDbSyncAttr; + }, NULL, NULL, ^(sqlite3_stmt *stmt, bool *stop) { + const uint8_t *digest = sqlite3_column_blob(stmt, 0); + size_t digestLen = sqlite3_column_bytes(stmt, 0); + if (digestLen != SOSDigestSize) { + secerror("digest %zu bytes", digestLen); + } else { + SOSDigestVectorAppend(&dv, digest); + } + })) { + secerror("SecDbItemSelect failed: %@", localError); + } + query_destroy(q, &localError); + if (localError) { + secerror("query_destroy failed: %@", localError); + } + } else if (localError) { + secerror("query_create failed: %@", localError); + } + } + manifest = SOSManifestCreateWithDigestVector(&dv, &localError); + SOSDigestVectorFree(&dv); + })) { + CFReleaseNull(manifest); + }; + + if (error && !*error && localError) + *error = localError; + else + CFReleaseSafe(localError); + + return manifest; +} + +// Return the newest object (conflict resolver) +static SecDbItemRef SecItemDataSourceCopyMergedItem(SecDbItemRef item1, SecDbItemRef item2, CFErrorRef *error) { + CFErrorRef localError = NULL; + SecDbItemRef result = NULL; + CFDateRef m1, m2; + const SecDbAttr *desc = SecDbAttrWithKey(SecDbItemGetClass(item1), kSecAttrModificationDate, error); + m1 = SecDbItemGetValue(item1, desc, &localError); + m2 = SecDbItemGetValue(item2, desc, &localError); + if (m1 && m2) switch (CFDateCompare(m1, m2, NULL)) { + case kCFCompareGreaterThan: + result = item1; + break; + case kCFCompareLessThan: + result = item2; + break; + case kCFCompareEqualTo: + { + // Return the item with the smallest digest. + CFDataRef digest1 = SecDbItemGetSHA1(item1, &localError); + CFDataRef digest2 = SecDbItemGetSHA1(item2, &localError); + if (digest1 && digest2) switch (CFDataCompare(digest1, digest2)) { + case kCFCompareGreaterThan: + case kCFCompareEqualTo: + result = item2; + break; + case kCFCompareLessThan: + result = item1; + break; + } else if (SecErrorGetOSStatus(localError) == errSecDecode) { + if (digest1) result = item1; + if (digest2) result = item2; + } + break; + } + } else if (SecErrorGetOSStatus(localError) == errSecDecode) { + // If one of the two objects has an unparsable date, + // the object with the parsable date wins. + if (m1) result = item1; + if (m2) result = item2; + } + + if (localError) { + if (!result && error && !*error) + *error = localError; + else + CFRelease(localError); + } + return CFRetainSafe(result); +} + +// +// MARK: DataSource protocol implementation +// + +static CFStringRef dsGetName(SOSDataSourceRef data_source) { + SecItemDataSourceRef ds = (SecItemDataSourceRef)data_source; + return ds->name; +} + +static void dsSetNotifyPhaseBlock(SOSDataSourceRef data_source, SOSDataSourceNotifyBlock notifyBlock) { + SecItemDataSourceRef ds = (SecItemDataSourceRef)data_source; + SecDbSetNotifyPhaseBlock(ds->db, ^(SecDbConnectionRef dbconn, SecDbTransactionPhase phase, SecDbTransactionSource source, struct SOSDigestVector *removals, struct SOSDigestVector *additions) { + if (notifyBlock) { + notifyBlock(&ds->ds, (SOSTransactionRef)dbconn, phase, source, removals, additions); + } else { + secerror("NULL notifyBlock"); // TODO: remove message; see SOSEngineSetTrustedPeers + } + }); +} + + +static SOSManifestRef dsCopyManifest(SOSDataSourceRef data_source, CFErrorRef *error) { + struct SecItemDataSource *ds = (struct SecItemDataSource *)data_source; + return SecItemDataSourceCopyManifest(ds, error); +} + +static bool dsForEachObject(SOSDataSourceRef data_source, SOSManifestRef manifest, CFErrorRef *error, void (^handle_object)(CFDataRef key, SOSObjectRef object, bool *stop)) { + struct SecItemDataSource *ds = (struct SecItemDataSource *)data_source; + __block bool result = true; + const SecDbAttr *sha1Attr = SecDbClassAttrWithKind(&genp_class, kSecDbSHA1Attr, error); + if (!sha1Attr) return false; + bool (^return_attr)(const SecDbAttr *attr) = ^bool (const SecDbAttr * attr) { + return attr->kind == kSecDbRowIdAttr || attr->kind == kSecDbEncryptedDataAttr; + }; + bool (^use_attr_in_where)(const SecDbAttr *attr) = ^bool (const SecDbAttr * attr) { + return attr->kind == kSecDbSHA1Attr; + }; + Query *select_queries[array_size(dsSyncedClasses)] = {}; + CFStringRef select_sql[array_size(dsSyncedClasses)] = {}; + sqlite3_stmt *select_stmts[array_size(dsSyncedClasses)] = {}; + + __block Query **queries = select_queries; + __block CFStringRef *sqls = select_sql; + __block sqlite3_stmt **stmts = select_stmts; + + result &= SecDbPerformRead(ds->db, error, ^(SecDbConnectionRef dbconn) { + // 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)) + && (sqls[class_ix] = SecDbItemCopySelectSQL(queries[class_ix], return_attr, use_attr_in_where, NULL)) + && (stmts[class_ix] = SecDbCopyStmt(dbconn, sqls[class_ix], NULL, error))); + } + + if (result) SOSManifestForEach(manifest, ^(CFDataRef key, bool *stop) { + __block SecDbItemRef item = NULL; + for (size_t class_ix = 0; result && !item && class_ix < array_size(dsSyncedClasses); ++class_ix) { + CFDictionarySetValue(queries[class_ix]->q_item, sha1Attr->name, key); + result = (SecDbItemSelectBind(queries[class_ix], stmts[class_ix], error, use_attr_in_where, NULL) && SecDbStep(dbconn, stmts[class_ix], error, ^(bool *unused_stop) { + item = SecDbItemCreateWithStatement(kCFAllocatorDefault, queries[class_ix]->q_class, stmts[class_ix], KEYBAG_DEVICE, error, return_attr); + })) && SecDbReset(stmts[class_ix], error); + } + handle_object(key, (SOSObjectRef)item, stop); + CFReleaseSafe(item); + }); + + // Cleanup + for (size_t class_ix = 0; class_ix < array_size(dsSyncedClasses); ++class_ix) { + result &= SecDbReleaseCachedStmt(dbconn, sqls[class_ix], stmts[class_ix], error); + CFReleaseSafe(sqls[class_ix]); + result &= query_destroy(queries[class_ix], error); + } + }); + return result; +} + +static bool dsRelease(SOSDataSourceRef data_source, CFErrorRef *error) { + // We never release our dataSource since it's tracking changes + // to the keychain for the engine and its peers. + return true; +} + +static SOSObjectRef objectCreateWithPropertyList(CFDictionaryRef plist, CFErrorRef *error) { + SecDbItemRef item = NULL; + const SecDbClass *class = NULL; + CFTypeRef cname = CFDictionaryGetValue(plist, kSecClass); + if (cname) { + class = kc_class_with_name(cname); + if (class) { + item = SecDbItemCreateWithAttributes(kCFAllocatorDefault, class, plist, KEYBAG_DEVICE, error); + } else { + SecError(errSecNoSuchClass, error, CFSTR("can find class named: %@"), cname); + } + } else { + SecError(errSecItemClassMissing, error, CFSTR("query missing %@ attribute"), kSecClass); + } + return (SOSObjectRef)item; +} + +static CFDataRef copyObjectDigest(SOSObjectRef object, CFErrorRef *error) { + SecDbItemRef item = (SecDbItemRef) object; + CFDataRef digest = SecDbItemGetSHA1(item, error); + CFRetainSafe(digest); + 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); + CFMutableDictionaryRef authDataDict = SecDbItemCopyPListWithMask(item, kSecDbInAuthenticatedDataFlag, error); + + if (cryptoDataDict) { + if (authDataDict) { + CFDictionaryForEach(authDataDict, ^(const void *key, const void *value) { + CFDictionarySetValue(cryptoDataDict, key, value); + }); + } + CFDictionaryAddValue(cryptoDataDict, kSecClass, SecDbItemGetClass(item)->name); + } + + CFReleaseSafe(authDataDict); + return cryptoDataDict; +} + +static bool dsWith(SOSDataSourceRef data_source, CFErrorRef *error, SOSDataSourceTransactionSource source, void(^transaction)(SOSTransactionRef txn, bool *commit)) { + SecItemDataSourceRef ds = (SecItemDataSourceRef)data_source; + __block bool ok = true; + ok &= SecDbPerformWrite(ds->db, error, ^(SecDbConnectionRef dbconn) { + ok &= SecDbTransaction(dbconn, + source == kSOSDataSourceAPITransaction ? kSecDbExclusiveTransactionType : kSecDbExclusiveRemoteTransactionType, + error, ^(bool *commit) { + transaction((SOSTransactionRef)dbconn, commit); + }); + }); + return ok; +} + +static SOSMergeResult dsMergeObject(SOSTransactionRef txn, SOSObjectRef peersObject, SOSObjectRef *createdObject, CFErrorRef *error) { + SecDbConnectionRef dbconn = (SecDbConnectionRef)txn; + SecDbItemRef peersItem = (SecDbItemRef)peersObject; + __block SOSMergeResult mr = kSOSMergeFailure; + __block SecDbItemRef mergedItem = NULL; + __block SecDbItemRef replacedItem = NULL; + if (!peersItem || !dbconn || !SecDbItemSetKeybag(peersItem, KEYBAG_DEVICE, error)) return mr; + if (SecDbItemInsertOrReplace(peersItem, dbconn, NULL, error, ^(SecDbItemRef myItem, SecDbItemRef *replace) { + // An item with the same primary key as dbItem already exists in the the database. That item is old_item. + // Let the conflict resolver choose which item to keep. + mergedItem = SecItemDataSourceCopyMergedItem(peersItem, myItem, error); + if (!mergedItem) return; + if (CFEqual(mergedItem, myItem)) { + // Conflict resolver choose my (local) item + secnotice("ds", "Conflict resolver choose 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); + mr = kSOSMergePeersObject; + } else { + // Conflict resolver created a new item; return it to our caller + secnotice("ds", "Conflict resolver created a new item; return it to our caller: %@", mergedItem); + if (createdObject) + *createdObject = (SOSObjectRef)CFRetain(mergedItem); + mr = kSOSMergeCreatedObject; + } + } + })) { + if (mr == kSOSMergeFailure) + { + secnotice("ds", "kSOSMergeFailure => kSOSMergePeersObject"); + mr = kSOSMergePeersObject; + } + } + + if (error && *error && mr != kSOSMergeFailure) + CFReleaseNull(*error); + + CFReleaseSafe(mergedItem); + CFReleaseSafe(replacedItem); + return mr; +} + + /* + Truthy backup format is a dictionary from sha1 => item. + Each item has class, hash and item data. + + TODO: sha1 is included as binary blob to avoid parsing key. + */ +enum { + kSecBackupIndexHash = 0, + kSecBackupIndexClass, + kSecBackupIndexData, +}; + +static const void *kSecBackupKeys[] = { + [kSecBackupIndexHash] = CFSTR("hash"), + [kSecBackupIndexClass] = CFSTR("class"), + [kSecBackupIndexData] = CFSTR("data"), +}; + +#define kSecBackupHash kSecBackupKeys[kSecBackupIndexHash] +#define kSecBackupClass kSecBackupKeys[kSecBackupIndexClass] +#define kSecBackupData kSecBackupKeys[kSecBackupIndexData] + +static CFDictionaryRef objectCopyBackup(SOSObjectRef object, uint64_t handle, CFErrorRef *error) { + const void *values[array_size(kSecBackupKeys)]; + SecDbItemRef item = (SecDbItemRef)object; + CFDictionaryRef backup_item = NULL; + + if ((values[kSecBackupIndexHash] = SecDbItemGetSHA1(item, error))) { + if ((values[kSecBackupIndexData] = SecDbItemCopyEncryptedDataToBackup(item, handle, error))) { + values[kSecBackupIndexClass] = SecDbItemGetClass(item)->name; + backup_item = CFDictionaryCreate(kCFAllocatorDefault, kSecBackupKeys, values, array_size(kSecBackupKeys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFRelease(values[kSecBackupIndexData]); + } + } + + return backup_item; +} + +static CFDataRef dsCopyStateWithKey(SOSDataSourceRef data_source, CFStringRef key, CFStringRef pdmn, CFErrorRef *error) { + SecItemDataSourceRef ds = (SecItemDataSourceRef)data_source; + CFStringRef dataSourceID = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("SOSDataSource-%@"), ds->name); + CFMutableDictionaryRef dict = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, + kSecAttrAccessGroup, kSOSInternalAccessGroup, + kSecAttrAccount, key, + kSecAttrService, dataSourceID, + kSecAttrAccessible, pdmn, + kSecAttrSynchronizable, kCFBooleanFalse, + NULL); + CFReleaseSafe(dataSourceID); + __block CFDataRef data = NULL; + SecDbQueryRef query = query_create(&genp_class, dict, error); + if (query) { + if (query->q_item) CFReleaseSafe(query->q_item); + query->q_item = dict; + SecDbPerformRead(ds->db, error, ^(SecDbConnectionRef dbconn) { + SecDbItemSelect(query, dbconn, error, ^bool(const SecDbAttr *attr) { + return CFDictionaryContainsKey(dict, attr->name); + }, NULL, NULL, ^(SecDbItemRef item, bool *stop) { + secnotice("ds", "found item for key %@@%@", key, pdmn); + data = CFRetainSafe(SecDbItemGetValue(item, &v6v_Data, error)); + }); + }); + query_destroy(query, error); + } else { + CFReleaseSafe(dict); + } + if (!data) secnotice("ds", "failed to load %@@%@ state: %@", key, pdmn, error ? *error : NULL); + return data; +} + +static bool dsSetStateWithKey(SOSDataSourceRef data_source, SOSTransactionRef txn, CFStringRef key, CFStringRef pdmn, CFDataRef state, CFErrorRef *error) { + SecItemDataSourceRef ds = (SecItemDataSourceRef)data_source; + CFStringRef dataSourceID = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("SOSDataSource-%@"), ds->name); + CFMutableDictionaryRef dict = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, + kSecAttrAccessGroup, kSOSInternalAccessGroup, + kSecAttrAccount, key, + kSecAttrService, dataSourceID, + kSecAttrAccessible, pdmn, + kSecAttrSynchronizable, kCFBooleanFalse, + kSecValueData, state, + NULL); + CFReleaseSafe(dataSourceID); + SecDbItemRef item = SecDbItemCreateWithAttributes(kCFAllocatorDefault, &genp_class, dict, KEYBAG_DEVICE, error); + SOSMergeResult mr = dsMergeObject(txn, (SOSObjectRef)item, NULL, error); + if (mr == kSOSMergeFailure) secerror("failed to save %@@%@ state: %@", key, pdmn, error ? *error : NULL); + CFReleaseSafe(item); + CFReleaseSafe(dict); + return mr != kSOSMergeFailure; +} + +static bool dsRestoreObject(SOSTransactionRef txn, uint64_t handle, CFDictionaryRef item, CFErrorRef *error) { + CFStringRef item_class = CFDictionaryGetValue(item, kSecBackupClass); + CFDataRef data = CFDictionaryGetValue(item, kSecBackupData); + const SecDbClass *dbclass = NULL; + + if (!item_class || !data) + return SecError(errSecDecode, error, CFSTR("no class or data in object")); + + dbclass = kc_class_with_name(item_class); + if (!dbclass) + return SecError(errSecDecode, error, CFSTR("no such class %@; update kc_class_with_name "), item_class); + + SecDbItemRef dbitem = SecDbItemCreateWithEncryptedData(kCFAllocatorDefault, dbclass, data, (keybag_handle_t)handle, error); + bool ok = dbitem && (dsMergeObject(txn, (SOSObjectRef)dbitem, NULL, error) != kSOSMergeFailure); + CFReleaseSafe(dbitem); + return ok; +} + +SOSDataSourceRef SecItemDataSourceCreate(SecDbRef db, CFStringRef name, CFErrorRef *error) { + SecItemDataSourceRef ds = calloc(1, sizeof(struct SecItemDataSource)); + ds->ds.dsGetName = dsGetName; + ds->ds.dsSetNotifyPhaseBlock = dsSetNotifyPhaseBlock; + ds->ds.dsCopyManifest = dsCopyManifest; + ds->ds.dsCopyStateWithKey = dsCopyStateWithKey; + ds->ds.dsForEachObject = dsForEachObject; + ds->ds.dsWith = dsWith; + ds->ds.dsRelease = dsRelease; + + ds->ds.dsMergeObject = dsMergeObject; + ds->ds.dsSetStateWithKey = dsSetStateWithKey; + ds->ds.dsRestoreObject = dsRestoreObject; + + // Object field accessors + ds->ds.objectCopyDigest = copyObjectDigest; + ds->ds.objectCopyPrimaryKey = objectCopyPrimaryKey; + + // Object encode and decode. + ds->ds.objectCreateWithPropertyList = objectCreateWithPropertyList; + ds->ds.objectCopyPropertyList = objectCopyPropertyList; + ds->ds.objectCopyBackup = objectCopyBackup; + + ds->db = CFRetainSafe(db); + ds->name = CFRetainSafe(name); + + // Do this after the ds is fully setup so the engine can query us right away. + ds->ds.engine = SOSEngineCreate(&ds->ds, error); + if (!ds->ds.engine) { + free(ds); + ds = NULL; + } + return &ds->ds; +} + +static CFArrayRef SecItemDataSourceFactoryCopyNames(SOSDataSourceFactoryRef factory) +{ + return CFArrayCreateForCFTypes(kCFAllocatorDefault, + kSecAttrAccessibleWhenUnlocked, + //kSecAttrAccessibleAfterFirstUnlock, + //kSecAttrAccessibleAlways, + NULL); +} + +struct SecItemDataSourceFactory { + struct SOSDataSourceFactory factory; + CFMutableDictionaryRef dsCache; + dispatch_queue_t queue; + SecDbRef db; +}; + +static SOSDataSourceRef SecItemDataSourceFactoryCopyDataSource(SOSDataSourceFactoryRef factory, CFStringRef dataSourceName, CFErrorRef *error) +{ + struct SecItemDataSourceFactory *f = (struct SecItemDataSourceFactory *)factory; + __block SOSDataSourceRef dataSource = NULL; + dispatch_sync(f->queue, ^{ + dataSource = (SOSDataSourceRef)CFDictionaryGetValue(f->dsCache, dataSourceName); + if (!dataSource) { + dataSource = (SOSDataSourceRef)SecItemDataSourceCreate(f->db, dataSourceName, error); + CFDictionarySetValue(f->dsCache, dataSourceName, dataSource); + } + }); + return dataSource; +} + +static void SecItemDataSourceFactoryDispose(SOSDataSourceFactoryRef factory) +{ + // Nothing to do here. +} + +// Fire up the SOSEngines so they can +static bool SOSDataSourceFactoryStartYourEngines(SOSDataSourceFactoryRef factory) { + bool ok = true; + CFArrayRef dsNames = factory->copy_names(factory); + CFStringRef dsName = NULL; + CFArrayForEachC(dsNames, dsName) { + CFErrorRef localError = NULL; + SOSDataSourceRef ds = factory->create_datasource(factory, dsName, &localError); + if (!ds) + secerror("create_datasource %@ failed %@", dsName, localError); + CFReleaseNull(localError); + SOSDataSourceRelease(ds, &localError); + CFReleaseNull(localError); + } + CFReleaseSafe(dsNames); + return ok; +} + +static SOSDataSourceFactoryRef SecItemDataSourceFactoryCreate(SecDbRef db) { + struct SecItemDataSourceFactory *dsf = calloc(1, sizeof(struct SecItemDataSourceFactory)); + dsf->factory.copy_names = SecItemDataSourceFactoryCopyNames; + dsf->factory.create_datasource = SecItemDataSourceFactoryCopyDataSource; + dsf->factory.release = SecItemDataSourceFactoryDispose; + dsf->dsCache = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, NULL); + dsf->queue = dispatch_queue_create("dsf queue", DISPATCH_QUEUE_SERIAL); + dsf->db = CFRetainSafe(db); + if (!SOSDataSourceFactoryStartYourEngines(&dsf->factory)) + secerror("Failed to start engines, gonna lose the race."); + return &dsf->factory; +} + +SOSDataSourceFactoryRef SecItemDataSourceFactoryGetShared(SecDbRef db) { + static dispatch_once_t sDSFQueueOnce; + static dispatch_queue_t sDSFQueue; + static CFMutableDictionaryRef sDSTable = NULL; + + dispatch_once(&sDSFQueueOnce, ^{ + sDSFQueue = dispatch_queue_create("dataSourceFactory queue", DISPATCH_QUEUE_SERIAL); + }); + + __block SOSDataSourceFactoryRef result = NULL; + dispatch_sync(sDSFQueue, ^{ + CFStringRef dbPath = SecDbGetPath(db); + if (sDSTable) { + result = (SOSDataSourceFactoryRef) CFDictionaryGetValue(sDSTable, dbPath); + } else { + sDSTable = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, NULL); + } + + if (!result) { + result = SecItemDataSourceFactoryCreate(db); + + CFDictionaryAddValue(sDSTable, dbPath, result); + } + }); + + return result; +} + +void SecItemServerAppendItemDescription(CFMutableStringRef desc, CFDictionaryRef object) { + SOSObjectRef item = objectCreateWithPropertyList(object, NULL); + if (item) { + CFStringRef itemDesc = CFCopyDescription(item); + if (itemDesc) { + CFStringAppend(desc, itemDesc); + CFReleaseSafe(itemDesc); + } + CFRelease(item); + } +} + +SOSManifestRef SOSCreateManifestWithBackup(CFDictionaryRef backup, CFErrorRef *error) +{ + __block struct SOSDigestVector dv = SOSDigestVectorInit; + if (backup) { + CFDictionaryForEach(backup, ^void (const void * key, const void * value) { + if (isDictionary(value)) { + /* converting key back to binary blob is horrible */ + CFDataRef sha1 = CFDictionaryGetValue(value, kSecBackupHash); + if (isData(sha1) && CFDataGetLength(sha1) == CCSHA1_OUTPUT_SIZE) + SOSDigestVectorAppend(&dv, CFDataGetBytePtr(sha1)); + } + }); + } + SOSManifestRef manifest = SOSManifestCreateWithDigestVector(&dv, error); + SOSDigestVectorFree(&dv); + return manifest; +} diff --git a/Security/sec/securityd/SecItemDataSource.h b/Security/sec/securityd/SecItemDataSource.h new file mode 100644 index 00000000..9b9a66c8 --- /dev/null +++ b/Security/sec/securityd/SecItemDataSource.h @@ -0,0 +1,51 @@ +/* + * 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@ + */ + +/*! + @header SecItemDataSource.h + The functions provided in SecDbItem provide an implementation of a + SOSDataSource required by the Secure Object Syncing code. + */ + +#ifndef _SECURITYD_SECITEMDATASOURCE_H_ +#define _SECURITYD_SECITEMDATASOURCE_H_ + +#include +#include + +__BEGIN_DECLS + +SOSDataSourceFactoryRef SecItemDataSourceFactoryGetShared(SecDbRef db); + + +SOSDataSourceRef SecItemDataSourceCreate(SecDbRef db, CFStringRef name, CFErrorRef *error); + +SOSManifestRef SOSCreateManifestWithBackup(CFDictionaryRef backup, CFErrorRef *error); + +// Hack to log objects from inside SOS code +void SecItemServerAppendItemDescription(CFMutableStringRef desc, CFDictionaryRef object); + + +__END_DECLS + +#endif /* _SECURITYD_SECITEMDATASOURCE_H_ */ diff --git a/Security/sec/securityd/SecItemDb.c b/Security/sec/securityd/SecItemDb.c new file mode 100644 index 00000000..51d10fa1 --- /dev/null +++ b/Security/sec/securityd/SecItemDb.c @@ -0,0 +1,1210 @@ +/* + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + */ + +/* + * SecItemDb.c - CoreFoundation-based constants and functions for + access to Security items (certificates, keys, identities, and + passwords.) + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* label when certificate data is joined with key data */ +#define CERTIFICATE_DATA_COLUMN_LABEL "certdata" + +const SecDbAttr *SecDbAttrWithKey(const SecDbClass *c, + CFTypeRef key, + CFErrorRef *error) { + /* Special case: identites can have all attributes of either cert + or keys. */ + if (c == &identity_class) { + const SecDbAttr *desc; + if (!(desc = SecDbAttrWithKey(&cert_class, key, 0))) + desc = SecDbAttrWithKey(&keys_class, key, error); + return desc; + } + + if (isString(key)) { + SecDbForEachAttr(c, a) { + if (CFEqual(a->name, key)) + return a; + } + } + + SecError(errSecNoSuchAttr, error, CFSTR("attribute %@ not found in class %@"), key, c->name); + + return NULL; +} + +bool kc_transaction(SecDbConnectionRef dbt, CFErrorRef *error, bool(^perform)()) { + __block bool ok = true; + return ok && SecDbTransaction(dbt, kSecDbExclusiveTransactionType, error, ^(bool *commit) { + ok = *commit = perform(); + }); +} + +static CFStringRef SecDbGetKindSQL(SecDbAttrKind kind) { + switch (kind) { + case kSecDbBlobAttr: + case kSecDbDataAttr: + case kSecDbSHA1Attr: + case kSecDbPrimaryKeyAttr: + case kSecDbEncryptedDataAttr: + return CFSTR("BLOB"); + case kSecDbAccessAttr: + case kSecDbStringAttr: + return CFSTR("TEXT"); + case kSecDbNumberAttr: + case kSecDbSyncAttr: + case kSecDbTombAttr: + return CFSTR("INTEGER"); + case kSecDbDateAttr: + case kSecDbCreationDateAttr: + case kSecDbModificationDateAttr: + return CFSTR("REAL"); + case kSecDbRowIdAttr: + return CFSTR("INTEGER PRIMARY KEY AUTOINCREMENT"); + case kSecDbAccessControlAttr: + /* This attribute does not exist in the DB. */ + return NULL; + } +} + +static void SecDbAppendUnique(CFMutableStringRef sql, CFStringRef value, bool *haveUnique) { + assert(haveUnique); + if (!*haveUnique) + CFStringAppend(sql, CFSTR("UNIQUE(")); + + SecDbAppendElement(sql, value, haveUnique); +} + +void SecDbAppendCreateTableWithClass(CFMutableStringRef sql, const SecDbClass *c) { + CFStringAppendFormat(sql, 0, CFSTR("CREATE TABLE %@("), c->name); + SecDbForEachAttrWithMask(c,desc,kSecDbInFlag) { + CFStringAppendFormat(sql, 0, CFSTR("%@ %@"), desc->name, SecDbGetKindSQL(desc->kind)); + if (desc->flags & kSecDbNotNullFlag) + CFStringAppend(sql, CFSTR(" NOT NULL")); + if (desc->flags & kSecDbDefault0Flag) + CFStringAppend(sql, CFSTR(" DEFAULT 0")); + if (desc->flags & kSecDbDefaultEmptyFlag) + CFStringAppend(sql, CFSTR(" DEFAULT ''")); + CFStringAppend(sql, CFSTR(",")); + } + + bool haveUnique = false; + SecDbForEachAttrWithMask(c,desc,kSecDbPrimaryKeyFlag | kSecDbInFlag) { + SecDbAppendUnique(sql, desc->name, &haveUnique); + } + if (haveUnique) + CFStringAppend(sql, CFSTR(")")); + + CFStringAppend(sql, CFSTR(");")); +} + +static CFDataRef SecPersistentRefCreateWithItem(SecDbItemRef item, CFErrorRef *error) { + sqlite3_int64 row_id = SecDbItemGetRowId(item, error); + if (row_id) + return _SecItemMakePersistentRef(SecDbItemGetClass(item)->name, row_id); + return NULL; +} + +CFTypeRef SecDbItemCopyResult(SecDbItemRef item, ReturnTypeMask return_type, CFErrorRef *error) { + CFTypeRef a_result; + + if (return_type == 0) { + /* Caller isn't interested in any results at all. */ + a_result = kCFNull; + } else if (return_type == kSecReturnDataMask) { + a_result = SecDbItemGetCachedValueWithName(item, kSecValueData); + if (a_result) { + CFRetainSafe(a_result); + } else { + a_result = CFDataCreate(kCFAllocatorDefault, NULL, 0); + } + } else if (return_type == kSecReturnPersistentRefMask) { + a_result = SecPersistentRefCreateWithItem(item, error); + } else { + CFMutableDictionaryRef dict = CFDictionaryCreateMutableForCFTypes(CFGetAllocator(item)); + /* We need to return more than one value. */ + if (return_type & kSecReturnRefMask) { + CFDictionarySetValue(dict, kSecClass, SecDbItemGetClass(item)->name); + } + CFOptionFlags mask = (((return_type & kSecReturnDataMask || return_type & kSecReturnRefMask) ? kSecDbReturnDataFlag : 0) | + ((return_type & kSecReturnAttributesMask || return_type & kSecReturnRefMask) ? kSecDbReturnAttrFlag : 0)); + SecDbForEachAttr(SecDbItemGetClass(item), desc) { + if ((desc->flags & mask) != 0) { + CFTypeRef value = SecDbItemGetValue(item, desc, error); + if (value && !CFEqual(kCFNull, value)) { + CFDictionarySetValue(dict, desc->name, value); + } else if (value == NULL) { + CFReleaseNull(dict); + break; + } + } + } + if (return_type & kSecReturnPersistentRefMask) { + CFDataRef pref = SecPersistentRefCreateWithItem(item, error); + CFDictionarySetValue(dict, kSecValuePersistentRef, pref); + CFReleaseSafe(pref); + } + + a_result = dict; + } + + return a_result; +} + +/* AUDIT[securityd](done): + attributes (ok) is a caller provided dictionary, only its cf type has + been checked. + */ +bool +s3dl_query_add(SecDbConnectionRef dbt, Query *q, CFTypeRef *result, CFErrorRef *error) +{ + if (query_match_count(q) != 0) + return errSecItemMatchUnsupported; + + /* Add requires a class to be specified unless we are adding a ref. */ + if (q->q_use_item_list) + return errSecUseItemListUnsupported; + + /* Actual work here. */ + SecDbItemRef item = SecDbItemCreateWithAttributes(kCFAllocatorDefault, q->q_class, q->q_item, KEYBAG_DEVICE, error); + if (!item) + return false; + + bool ok = true; + if (q->q_data) + ok = SecDbItemSetValueWithName(item, CFSTR("v_Data"), q->q_data, error); + if (q->q_row_id) + ok = SecDbItemSetRowId(item, q->q_row_id, error); + SecDbItemSetCredHandle(item, q->q_use_cred_handle); + + if (ok) { + ok = SecDbItemInsert(item, dbt, q->q_required_access_controls, error); + CFRetainAssign(q->q_use_cred_handle, item->credHandle); + } + if (ok) { + if (result && q->q_return_type) { + *result = SecDbItemCopyResult(item, q->q_return_type, error); + } + } + if (!ok && error && *error) { + if (CFEqual(CFErrorGetDomain(*error), kSecDbErrorDomain) && CFErrorGetCode(*error) == SQLITE_CONSTRAINT) { + CFReleaseNull(*error); + SecError(errSecDuplicateItem, error, CFSTR("duplicate item %@"), item); + } + } + + if (ok) { + q->q_changed = true; + if (SecDbItemIsSyncable(item)) + q->q_sync_changed = true; + } + + secdebug("dbitem", "inserting item %@%s%@", item, ok ? "" : "failed: ", ok || error == NULL ? (CFErrorRef)CFSTR("") : *error); + + CFRelease(item); + + return ok; +} + +typedef void (*s3dl_handle_row)(sqlite3_stmt *stmt, void *context); + +static CFDataRef +s3dl_copy_data_from_col(sqlite3_stmt *stmt, int col, CFErrorRef *error) { + return CFDataCreateWithBytesNoCopy(0, sqlite3_column_blob(stmt, col), + sqlite3_column_bytes(stmt, col), + kCFAllocatorNull); +} + +static bool +s3dl_item_from_col(sqlite3_stmt *stmt, Query *q, int col, CFArrayRef accessGroups, + CFMutableDictionaryRef *item, SecAccessControlRef *access_control, CFErrorRef *error) { + CFDataRef edata = NULL; + bool ok = false; + require(edata = s3dl_copy_data_from_col(stmt, col, error), out); + ok = s3dl_item_from_data(edata, q, accessGroups, item, access_control, error); + +out: + CFReleaseSafe(edata); + return ok; +} + +struct s3dl_query_ctx { + Query *q; + CFArrayRef accessGroups; + SecDbConnectionRef dbt; + CFTypeRef result; + int found; +}; + +/* Return whatever the caller requested based on the value of q->q_return_type. + keys and values must be 3 larger than attr_count in size to accomadate the + optional data, class and persistent ref results. This is so we can use + the CFDictionaryCreate() api here rather than appending to a + mutable dictionary. */ +static CF_RETURNS_RETAINED CFTypeRef handle_result(Query *q, CFMutableDictionaryRef item, + sqlite_int64 rowid) { + CFTypeRef a_result; + CFDataRef data; + data = CFDictionaryGetValue(item, kSecValueData); + if (q->q_return_type == 0) { + /* Caller isn't interested in any results at all. */ + a_result = kCFNull; + } else if (q->q_return_type == kSecReturnDataMask) { + if (data) { + a_result = data; + CFRetain(a_result); + } else { + a_result = CFDataCreate(kCFAllocatorDefault, NULL, 0); + } + } else if (q->q_return_type == kSecReturnPersistentRefMask) { + a_result = _SecItemMakePersistentRef(q->q_class->name, rowid); + } else { + /* We need to return more than one value. */ + if (q->q_return_type & kSecReturnRefMask) { + CFDictionarySetValue(item, kSecClass, q->q_class->name); + } else if ((q->q_return_type & kSecReturnAttributesMask)) { + if (!(q->q_return_type & kSecReturnDataMask)) { + CFDictionaryRemoveValue(item, kSecValueData); + } + } else { + CFRetainSafe(data); + CFDictionaryRemoveAllValues(item); + if ((q->q_return_type & kSecReturnDataMask) && data) { + CFDictionarySetValue(item, kSecValueData, data); + } + CFReleaseSafe(data); + } + if (q->q_return_type & kSecReturnPersistentRefMask) { + CFDataRef pref = _SecItemMakePersistentRef(q->q_class->name, rowid); + CFDictionarySetValue(item, kSecValuePersistentRef, pref); + CFRelease(pref); + } + + a_result = item; + CFRetain(item); + } + + return a_result; +} + +static void s3dl_merge_into_dict(const void *key, const void *value, void *context) { + CFDictionarySetValue(context, key, value); +} + +static void s3dl_query_row(sqlite3_stmt *stmt, void *context) { + struct s3dl_query_ctx *c = context; + Query *q = c->q; + + sqlite_int64 rowid = sqlite3_column_int64(stmt, 0); + CFMutableDictionaryRef item; + bool ok = s3dl_item_from_col(stmt, q, 1, c->accessGroups, &item, NULL, &q->q_error); + if (!ok) { + OSStatus status = SecErrorGetOSStatus(q->q_error); + // errSecDecode means the item is corrupted, stash it for delete. + if (status == errSecDecode) { + secwarning("ignoring corrupt %@,rowid=%" PRId64 " %@", q->q_class->name, rowid, q->q_error); + { + CFDataRef edata = s3dl_copy_data_from_col(stmt, 1, NULL); + CFMutableStringRef edatastring = CFStringCreateMutable(kCFAllocatorDefault, 0); + if(edatastring) { + CFStringAppendEncryptedData(edatastring, edata); + secnotice("item", "corrupted edata=%@", edatastring); + } + CFReleaseSafe(edata); + CFReleaseSafe(edatastring); + } + CFReleaseNull(q->q_error); + } else { + secerror("decode %@,rowid=%" PRId64 " failed (%" PRIdOSStatus "): %@", q->q_class->name, rowid, status, q->q_error); + } + // q->q_error will be released appropriately by a call to query_error + return; + } + + if (!item) + goto out; + + if (q->q_class == &identity_class) { + // TODO: Use col 2 for key rowid and use both rowids in persistent ref. + + CFMutableDictionaryRef key; + /* TODO : if there is a errSecDecode error here, we should cleanup */ + if (!s3dl_item_from_col(stmt, q, 3, c->accessGroups, &key, NULL, &q->q_error) || !key) + goto out; + + CFDataRef certData = CFDictionaryGetValue(item, kSecValueData); + if (certData) { + CFDictionarySetValue(key, CFSTR(CERTIFICATE_DATA_COLUMN_LABEL), + certData); + CFDictionaryRemoveValue(item, kSecValueData); + } + CFDictionaryApplyFunction(item, s3dl_merge_into_dict, key); + CFRelease(item); + item = key; + } + + if (!match_item(c->dbt, q, c->accessGroups, item)) + goto out; + + CFTypeRef a_result = handle_result(q, item, rowid); + if (a_result) { + if (a_result == kCFNull) { + /* Caller wasn't interested in a result, but we still + count this row as found. */ + CFRelease(a_result); // Help shut up clang + } else if (q->q_limit == 1) { + c->result = a_result; + } else { + CFArrayAppendValue((CFMutableArrayRef)c->result, a_result); + CFRelease(a_result); + } + c->found++; + } + +out: + CFReleaseSafe(item); +} + +static void +SecDbAppendWhereROWID(CFMutableStringRef sql, + CFStringRef col, sqlite_int64 row_id, + bool *needWhere) { + if (row_id > 0) { + SecDbAppendWhereOrAnd(sql, needWhere); + CFStringAppendFormat(sql, NULL, CFSTR("%@=%lld"), col, row_id); + } +} + +static void +SecDbAppendWhereAttrs(CFMutableStringRef sql, const Query *q, bool *needWhere) { + CFIndex ix, attr_count = query_attr_count(q); + for (ix = 0; ix < attr_count; ++ix) { + SecDbAppendWhereOrAndEquals(sql, query_attr_at(q, ix).key, needWhere); + } +} + +static void +SecDbAppendWhereAccessGroups(CFMutableStringRef sql, + CFStringRef col, + CFArrayRef accessGroups, + bool *needWhere) { + CFIndex ix, ag_count; + if (!accessGroups || 0 == (ag_count = CFArrayGetCount(accessGroups))) { + return; + } + + SecDbAppendWhereOrAnd(sql, needWhere); + CFStringAppend(sql, col); + CFStringAppend(sql, CFSTR(" IN (?")); + for (ix = 1; ix < ag_count; ++ix) { + CFStringAppend(sql, CFSTR(",?")); + } + CFStringAppend(sql, CFSTR(")")); +} + +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); + SecDbAppendWhereAccessGroups(sql, CFSTR("agrp"), accessGroups, &needWhere); +} + +static void SecDbAppendLimit(CFMutableStringRef sql, CFIndex limit) { + if (limit != kSecMatchUnlimited) + CFStringAppendFormat(sql, NULL, CFSTR(" LIMIT %" PRIdCFIndex), limit); +} + +static CFStringRef s3dl_select_sql(Query *q, CFArrayRef accessGroups) { + CFMutableStringRef sql = CFStringCreateMutable(NULL, 0); + if (q->q_class == &identity_class) { + CFStringAppendFormat(sql, NULL, CFSTR("SELECT crowid, " + CERTIFICATE_DATA_COLUMN_LABEL ", rowid,data FROM " + "(SELECT cert.rowid AS crowid, cert.labl AS labl," + " cert.issr AS issr, cert.slnr AS slnr, cert.skid AS skid," + " keys.*,cert.data AS " CERTIFICATE_DATA_COLUMN_LABEL + " FROM keys, cert" + " WHERE keys.priv == 1 AND cert.pkhh == keys.klbl")); + SecDbAppendWhereAccessGroups(sql, CFSTR("cert.agrp"), accessGroups, 0); + /* The next 3 SecDbAppendWhere calls are in the same order as in + SecDbAppendWhereClause(). This makes sqlBindWhereClause() work, + as long as we do an extra sqlBindAccessGroups first. */ + SecDbAppendWhereROWID(sql, CFSTR("crowid"), q->q_row_id, 0); + CFStringAppend(sql, CFSTR(")")); + bool needWhere = true; + SecDbAppendWhereAttrs(sql, q, &needWhere); + SecDbAppendWhereAccessGroups(sql, CFSTR("agrp"), accessGroups, &needWhere); + } else { + CFStringAppend(sql, CFSTR("SELECT rowid, data FROM ")); + CFStringAppend(sql, q->q_class->name); + SecDbAppendWhereClause(sql, q, accessGroups); + } + SecDbAppendLimit(sql, q->q_limit); + + return sql; +} + +static bool sqlBindAccessGroups(sqlite3_stmt *stmt, CFArrayRef accessGroups, + int *pParam, CFErrorRef *error) { + bool result = true; + int param = *pParam; + CFIndex ix, count = accessGroups ? CFArrayGetCount(accessGroups) : 0; + for (ix = 0; ix < count; ++ix) { + result = SecDbBindObject(stmt, param++, + CFArrayGetValueAtIndex(accessGroups, ix), + error); + if (!result) + break; + } + *pParam = param; + return result; +} + +static bool sqlBindWhereClause(sqlite3_stmt *stmt, const Query *q, + CFArrayRef accessGroups, int *pParam, CFErrorRef *error) { + bool result = true; + int param = *pParam; + CFIndex ix, attr_count = query_attr_count(q); + for (ix = 0; ix < attr_count; ++ix) { + result = SecDbBindObject(stmt, param++, query_attr_at(q, ix).value, error); + if (!result) + break; + } + + /* Bind the access group to the sql. */ + if (result) { + result = sqlBindAccessGroups(stmt, accessGroups, ¶m, error); + } + + *pParam = param; + return result; +} + +bool SecDbItemQuery(SecDbQueryRef query, CFArrayRef accessGroups, SecDbConnectionRef dbconn, CFErrorRef *error, + void (^handle_row)(SecDbItemRef item, bool *stop)) { + __block bool ok = true; + __block bool decrypted = true; + /* Sanity check the query. */ + if (query->q_ref) + return SecError(errSecValueRefUnsupported, error, CFSTR("value ref not supported by queries")); + + bool (^return_attr)(const SecDbAttr *attr) = ^bool (const SecDbAttr * attr) { + return attr->kind == kSecDbRowIdAttr || attr->kind == kSecDbEncryptedDataAttr || attr->kind == kSecDbSHA1Attr; + }; + + CFStringRef sql = s3dl_select_sql(query, accessGroups); + ok = sql; + if (sql) { + ok &= SecDbPrepare(dbconn, sql, error, ^(sqlite3_stmt *stmt) { + /* Bind the values being searched for to the SELECT statement. */ + int param = 1; + if (query->q_class == &identity_class) { + /* Bind the access groups to cert.agrp. */ + ok &= sqlBindAccessGroups(stmt, accessGroups, ¶m, error); + } + if (ok) + ok &= sqlBindWhereClause(stmt, query, accessGroups, ¶m, error); + if (ok) { + SecDbStep(dbconn, stmt, error, ^(bool *stop) { + SecDbItemRef item = SecDbItemCreateWithStatement(kCFAllocatorDefault, query->q_class, stmt, query->q_keybag, error, return_attr); + if (item) { + if (query->q_required_access_controls) { + CFDataRef authNeeded = NULL; + item->cryptoOp = query->q_crypto_op; + SecDbItemSetCallerAccessGroups(item, query->q_caller_access_groups); + decrypted = SecDbItemEnsureDecrypted(item, &authNeeded, &query->q_use_cred_handle, NULL); + if (decrypted && authNeeded) { + // Do not process the item right now, just remember that it will need + // authentication to properly process it. + CFArrayAppendValue(query->q_required_access_controls, authNeeded); + CFRelease(authNeeded); + CFRelease(item); + return; + } + CFReleaseSafe(authNeeded); + } + if (match_item(dbconn, query, accessGroups, item->attributes)) + handle_row(item, stop); + CFRelease(item); + } else { + secerror("failed to create item from stmt: %@", error ? *error : (CFErrorRef)"no error"); + if (error) { + CFReleaseNull(*error); + } + //*stop = true; + //ok = false; + } + }); + } + }); + CFRelease(sql); + } + + return ok; +} + +static bool +s3dl_query(s3dl_handle_row handle_row, + void *context, CFErrorRef *error) +{ + struct s3dl_query_ctx *c = context; + SecDbConnectionRef dbt = c->dbt; + Query *q = c->q; + CFArrayRef accessGroups = c->accessGroups; + + /* Sanity check the query. */ + if (q->q_ref) + return SecError(errSecValueRefUnsupported, error, CFSTR("value ref not supported by queries")); + + /* Actual work here. */ + if (q->q_limit == 1) { + c->result = NULL; + } else { + c->result = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + } + CFStringRef sql = s3dl_select_sql(q, accessGroups); + bool ok = SecDbWithSQL(dbt, sql, error, ^(sqlite3_stmt *stmt) { + bool sql_ok = true; + /* Bind the values being searched for to the SELECT statement. */ + int param = 1; + if (q->q_class == &identity_class) { + /* Bind the access groups to cert.agrp. */ + sql_ok = sqlBindAccessGroups(stmt, accessGroups, ¶m, error); + } + if (sql_ok) + sql_ok = sqlBindWhereClause(stmt, q, accessGroups, ¶m, error); + if (sql_ok) { + SecDbForEach(stmt, error, ^bool (int row_index) { + handle_row(stmt, context); + return (!q->q_error) && (q->q_limit == kSecMatchUnlimited || c->found < q->q_limit); + }); + } + return sql_ok; + }); + + CFRelease(sql); + + // First get the error from the query, since errSecDuplicateItem from an + // update query should superceed the errSecItemNotFound below. + if (!query_error(q, error)) + ok = false; + if (ok && c->found == 0) + ok = SecError(errSecItemNotFound, error, CFSTR("no matching items found")); + + return ok; +} + +bool +s3dl_copy_matching(SecDbConnectionRef dbt, Query *q, CFTypeRef *result, + CFArrayRef accessGroups, CFErrorRef *error) +{ + struct s3dl_query_ctx ctx = { + .q = q, .accessGroups = accessGroups, .dbt = dbt, + }; + if (q->q_row_id && query_attr_count(q)) + return SecError(errSecItemIllegalQuery, error, + CFSTR("attributes to query illegal; both row_id and other attributes can't be searched at the same time")); + + // Only copy things that aren't tombstones unless the client explicitly asks otherwise. + if (!CFDictionaryContainsKey(q->q_item, kSecAttrTombstone)) + query_add_attribute(kSecAttrTombstone, kCFBooleanFalse, q); + bool ok = s3dl_query(s3dl_query_row, &ctx, error); + if (ok && result) + *result = ctx.result; + else + CFReleaseSafe(ctx.result); + + return ok; +} + +/* AUDIT[securityd](done): + attributesToUpdate (ok) is a caller provided dictionary, + only its cf types have been checked. + */ +bool +s3dl_query_update(SecDbConnectionRef dbt, Query *q, + CFDictionaryRef attributesToUpdate, CFArrayRef accessGroups, CFErrorRef *error) +{ + /* Sanity check the query. */ + if (query_match_count(q) != 0) + return SecError(errSecItemMatchUnsupported, error, CFSTR("match not supported in attributes to update")); + if (q->q_ref) + return SecError(errSecValueRefUnsupported, error, CFSTR("value ref not supported in attributes to update")); + if (q->q_row_id && query_attr_count(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); + if (u == NULL) return false; + require_action_quiet(query_update_parse(u, attributesToUpdate, error), errOut, result = false); + query_pre_update(u); + result &= SecDbTransaction(dbt, kSecDbExclusiveTransactionType, error, ^(bool *commit) { + // Make sure we only update real items, not tombstones, unless the client explicitly asks otherwise. + if (!CFDictionaryContainsKey(q->q_item, kSecAttrTombstone)) + query_add_attribute(kSecAttrTombstone, kCFBooleanFalse, q); + result &= SecDbItemQuery(q, accessGroups, dbt, error, ^(SecDbItemRef item, bool *stop) { + // We always need to know the error here. + CFErrorRef localError = NULL; + // Cache the storedSHA1 digest so we use the one from the db not the recomputed one for notifications. + const SecDbAttr *sha1attr = SecDbClassAttrWithKind(item->class, kSecDbSHA1Attr, NULL); + CFDataRef storedSHA1 = CFRetainSafe(SecDbItemGetValue(item, sha1attr, NULL)); + SecDbItemRef new_item = SecDbItemCopyWithUpdates(item, u->q_item, &localError); + SecDbItemSetValue(item, sha1attr, storedSHA1, NULL); + CFReleaseSafe(storedSHA1); + if (SecErrorGetOSStatus(localError) == errSecDecode) { + // We just ignore this, and treat as if item is not found. + secwarning("deleting corrupt %@,rowid=%" PRId64 " %@", q->q_class->name, SecDbItemGetRowId(item, NULL), localError); + CFReleaseNull(localError); + if (!SecDbItemDelete(item, dbt, false, &localError)) { + secerror("failed to delete corrupt %@,rowid=%" PRId64 " %@", q->q_class->name, SecDbItemGetRowId(item, NULL), localError); + CFReleaseNull(localError); + } + return; + } + if (new_item != NULL && u->q_access_control != NULL) + SecDbItemSetAccessControl(new_item, u->q_access_control, &localError); + result = CFErrorPropagate(localError, error) && new_item; + if (new_item) { + bool item_is_sync = SecDbItemIsSyncable(item); + bool makeTombstone = q->q_use_tomb ? CFBooleanGetValue(q->q_use_tomb) : (item_is_sync && !SecDbItemIsTombstone(item)); + result = SecDbItemUpdate(item, new_item, dbt, makeTombstone, error); + if (result) { + q->q_changed = true; + if (item_is_sync || SecDbItemIsSyncable(new_item)) + q->q_sync_changed = true; + } + CFRelease(new_item); + } + if (!result) + *stop = true; + }); + if (!result) + *commit = false; + }); + if (result && !q->q_changed) + result = SecError(errSecItemNotFound, error, CFSTR("No items updated")); +errOut: + if (!query_destroy(u, error)) + result = false; + return result; +} + +bool +s3dl_query_delete(SecDbConnectionRef dbt, Query *q, CFArrayRef accessGroups, CFErrorRef *error) +{ + __block bool ok = true; + // Only delete things that aren't tombstones, unless the client explicitly asks otherwise. + if (!CFDictionaryContainsKey(q->q_item, kSecAttrTombstone)) + query_add_attribute(kSecAttrTombstone, kCFBooleanFalse, q); + ok &= SecDbItemSelect(q, dbt, error, ^bool(const SecDbAttr *attr) { + return false; + },^bool(CFMutableStringRef sql, bool *needWhere) { + SecDbAppendWhereClause(sql, q, accessGroups); + return true; + },^bool(sqlite3_stmt * stmt, int col) { + return sqlBindWhereClause(stmt, q, accessGroups, &col, error); + }, ^(SecDbItemRef item, bool *stop) { + // Cache the storedSHA1 digest so we use the one from the db not the recomputed one for notifications. + const SecDbAttr *sha1attr = SecDbClassAttrWithKind(item->class, kSecDbSHA1Attr, NULL); + CFDataRef storedSHA1 = CFRetainSafe(SecDbItemGetValue(item, sha1attr, NULL)); + bool item_is_sync = SecDbItemIsSyncable(item); + SecDbItemSetValue(item, sha1attr, storedSHA1, NULL); + CFReleaseSafe(storedSHA1); + bool makeTombstone = q->q_use_tomb ? CFBooleanGetValue(q->q_use_tomb) : (item_is_sync && !SecDbItemIsTombstone(item)); + item->cryptoOp = kSecKsDelete; + ok = SecDbItemDelete(item, dbt, makeTombstone, error); + if (ok) { + q->q_changed = true; + if (item_is_sync) + q->q_sync_changed = true; + } + }); + if (ok && !q->q_changed) { + ok = SecError(errSecItemNotFound, error, CFSTR("Delete failed to delete anything")); + } + return ok; +} + +/* 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) { + CFStringRef agrp = CFDictionaryGetValue(item, kSecAttrAccessGroup); + if (!isString(agrp)) + return false; + + if (CFEqualSafe(agrp, kSOSInternalAccessGroup)) { + secdebug("backup", "found sysbound item: %@", item); + return true; + } + + if (CFEqual(agrp, CFSTR("lockdown-identities"))) { + secdebug("backup", "found sys_bound item: %@", item); + return true; + } + + if (CFEqual(agrp, CFSTR("apple")) && class == &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")))) { + secdebug("backup", "found sys_bound item: %@", item); + return true; + } + } + secdebug("backup", "found non sys_bound item: %@", item); + return false; +} + +/* Delete all items from the current keychain. If this is not an in + place upgrade we don't delete items in the 'lockdown-identities' + access group, this ensures that an import or restore of a backup + will never overwrite an existing activation record. */ +static bool SecServerDeleteAll(SecDbConnectionRef dbt, CFErrorRef *error) { + return kc_transaction(dbt, error, ^{ + bool ok = (SecDbExec(dbt, CFSTR("DELETE from genp;"), error) && + SecDbExec(dbt, CFSTR("DELETE from inet;"), error) && + SecDbExec(dbt, CFSTR("DELETE from cert;"), error) && + SecDbExec(dbt, CFSTR("DELETE from keys;"), error)); + return ok; + }); +} + +struct s3dl_export_row_ctx { + struct s3dl_query_ctx qc; + keybag_handle_t dest_keybag; + enum SecItemFilter filter; +}; + +static void s3dl_export_row(sqlite3_stmt *stmt, void *context) { + struct s3dl_export_row_ctx *c = context; + Query *q = c->qc.q; + SecAccessControlRef access_control = NULL; + CFErrorRef localError = NULL; + + sqlite_int64 rowid = sqlite3_column_int64(stmt, 0); + CFMutableDictionaryRef item; + if (s3dl_item_from_col(stmt, q, 1, c->qc.accessGroups, &item, &access_control, &localError)) { + if (item) { + /* Only export sysbound items is 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) { + /* Re-encode the item. */ + secdebug("item", "export rowid %llu item: %@", rowid, item); + /* The code below could be moved into handle_row. */ + CFDataRef pref = _SecItemMakePersistentRef(q->q_class->name, rowid); + if (pref) { + if (c->dest_keybag != KEYBAG_NONE) { + CFMutableDictionaryRef auth_attribs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + SecDbForEachAttrWithMask(q->q_class, desc, kSecDbInAuthenticatedDataFlag) { + CFTypeRef value = CFDictionaryGetValue(item, desc->name); + if(value) { + CFDictionaryAddValue(auth_attribs, desc->name, value); + CFDictionaryRemoveValue(item, desc->name); + } + } + + /* Encode and encrypt the item to the specified keybag. */ + CFDataRef edata = NULL; + bool encrypted = ks_encrypt_data(c->dest_keybag, access_control, &q->q_use_cred_handle, item, auth_attribs, &edata, &q->q_error); + CFDictionaryRemoveAllValues(item); + CFRelease(auth_attribs); + if (encrypted) { + CFDictionarySetValue(item, kSecValueData, edata); + CFReleaseSafe(edata); + } else { + seccritical("ks_encrypt_data %@,rowid=%" PRId64 ": failed: %@", q->q_class->name, rowid, q->q_error); + CFReleaseNull(q->q_error); + } + } + if (CFDictionaryGetCount(item)) { + CFDictionarySetValue(item, kSecValuePersistentRef, pref); + CFArrayAppendValue((CFMutableArrayRef)c->qc.result, item); + c->qc.found++; + } + CFReleaseSafe(pref); + } + } + CFRelease(item); + } + } else { + /* This happens a lot when trying to migrate keychain before first unlock, so only a notice */ + /* If the error is "corrupted item" then we just ignore it, otherwise we save it in the query */ + secnotice("item","Could not export item for rowid %llu: %@", rowid, localError); + if(SecErrorGetOSStatus(localError)==errSecDecode) { + CFReleaseNull(localError); + } else { + CFReleaseSafe(q->q_error); + q->q_error=localError; + } + } + 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) { + CFMutableDictionaryRef keychain; + keychain = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (!keychain) { + if (error && !*error) + SecError(errSecAllocate, error, CFSTR("Can't create keychain dictionary")); + goto errOut; + } + unsigned class_ix; + Query q = { .q_keybag = src_keybag }; + q.q_return_type = kSecReturnDataMask | kSecReturnAttributesMask | \ + kSecReturnPersistentRefMask; + q.q_limit = kSecMatchUnlimited; + + /* Enable interactive means that auth-protected items will be silently ignored + (and their ACLs copied into query, which we will simply ignore). */ + query_enable_interactive(&q); + + /* Get rid of this duplicate. */ + const SecDbClass *SecDbClasses[] = { + &genp_class, + &inet_class, + &cert_class, + &keys_class + }; + + for (class_ix = 0; class_ix < array_size(SecDbClasses); + ++class_ix) { + q.q_class = SecDbClasses[class_ix]; + struct s3dl_export_row_ctx ctx = { + .qc = { .q = &q, .dbt = dbt }, + .dest_keybag = dest_keybag, .filter = filter, + }; + + secnotice("item", "exporting class '%@'", q.q_class->name); + + CFErrorRef localError = NULL; + if (s3dl_query(s3dl_export_row, &ctx, &localError)) { + if (CFArrayGetCount(ctx.qc.result)) + CFDictionaryAddValue(keychain, q.q_class->name, ctx.qc.result); + + } else { + OSStatus status = (OSStatus)CFErrorGetCode(localError); + if (status == errSecItemNotFound) { + CFRelease(localError); + } else { + secerror("Export failed: %@", localError); + if (error) { + CFReleaseSafe(*error); + *error = localError; + } else { + CFRelease(localError); + } + CFReleaseNull(keychain); + CFReleaseNull(ctx.qc.result); + break; + } + } + CFReleaseNull(ctx.qc.result); + } + + /* Release all ignored ACLs of auth-protected items. */ + CFReleaseNull(q.q_required_access_controls); +errOut: + return keychain; +} + +struct SecServerImportClassState { + SecDbConnectionRef dbt; + CFErrorRef error; + keybag_handle_t src_keybag; + keybag_handle_t dest_keybag; + enum SecItemFilter filter; +}; + +struct SecServerImportItemState { + const SecDbClass *class; + struct SecServerImportClassState *s; +}; + +static void SecServerImportItem(const void *value, void *context) { + struct SecServerImportItemState *state = + (struct SecServerImportItemState *)context; + if (state->s->error) + return; + if (!isDictionary(value)) { + SecError(errSecParam, &state->s->error, CFSTR("value %@ is not a dictionary"), value); + return; + } + + CFDictionaryRef dict = (CFDictionaryRef)value; + + secdebug("item", "Import Item : %@", dict); + + /* We don't filter non sys_bound items during import since we know we + 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)) + return; + + SecDbItemRef item; + + /* This is sligthly confusing: + - During upgrade all items are exported with KEYBAG_NONE. + - During restore from backup, existing sys_bound items are exported with KEYBAG_NONE, and are exported as dictionary of attributes. + - Item in the actual backup are export with a real keybag, and are exported as encrypted v_Data and v_PersistentRef + */ + if (state->s->src_keybag == KEYBAG_NONE) { + item = SecDbItemCreateWithAttributes(kCFAllocatorDefault, state->class, dict, state->s->dest_keybag, &state->s->error); + } else { + item = SecDbItemCreateWithBackupDictionary(kCFAllocatorDefault, state->class, dict, state->s->src_keybag, state->s->dest_keybag, &state->s->error); + } + + if (item) { + if(state->s->filter != kSecSysBoundItemFilter) { + SecDbItemExtractRowIdFromBackupDictionary(item, dict, &state->s->error); + } + SecDbItemInferSyncable(item, &state->s->error); + SecDbItemInsert(item, state->s->dbt, NULL, &state->s->error); + } + + /* Reset error if we had one, since we just skip the current item + and continue importing what we can. */ + if (state->s->error) { + secwarning("Failed to import an item (%@) of class '%@': %@ - ignoring error.", + item, state->class->name, state->s->error); + CFReleaseNull(state->s->error); + } + + CFReleaseSafe(item); +} + +static void SecServerImportClass(const void *key, const void *value, + void *context) { + struct SecServerImportClassState *state = + (struct SecServerImportClassState *)context; + if (state->error) + return; + if (!isString(key)) { + SecError(errSecParam, &state->error, CFSTR("class name %@ is not a string"), key); + return; + } + const SecDbClass *class = kc_class_with_name(key); + if (!class || class == &identity_class) { + SecError(errSecParam, &state->error, CFSTR("attempt to import an identity")); + return; + } + struct SecServerImportItemState item_state = { + .class = class, .s = state + }; + if (isArray(value)) { + CFArrayRef items = (CFArrayRef)value; + CFArrayApplyFunction(items, CFRangeMake(0, CFArrayGetCount(items)), + SecServerImportItem, &item_state); + } else { + CFDictionaryRef item = (CFDictionaryRef)value; + SecServerImportItem(item, &item_state); + } +} + +bool SecServerImportKeychainInPlist(SecDbConnectionRef dbt, + keybag_handle_t src_keybag, keybag_handle_t dest_keybag, + CFDictionaryRef keychain, enum SecItemFilter filter, CFErrorRef *error) { + bool ok = true; + + CFDictionaryRef sys_bound = NULL; + 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); + } + + /* Delete everything in the keychain. */ + require(ok = SecServerDeleteAll(dbt, error), errOut); + + struct SecServerImportClassState state = { + .dbt = dbt, + .src_keybag = src_keybag, + .dest_keybag = dest_keybag, + .filter = filter, + }; + /* Import the provided items, preserving rowids. */ + CFDictionaryApplyFunction(keychain, SecServerImportClass, &state); + + if (sys_bound) { + state.src_keybag = KEYBAG_NONE; + /* Import the items we preserved with random rowids. */ + state.filter = kSecSysBoundItemFilter; + CFDictionaryApplyFunction(sys_bound, SecServerImportClass, &state); + } + if (state.error) { + if (error) { + CFReleaseSafe(*error); + *error = state.error; + } else { + CFRelease(state.error); + } + ok = false; + } + +errOut: + CFReleaseSafe(sys_bound); + + return ok; +} + +#pragma mark - key rolling support +#if USE_KEYSTORE + +struct check_generation_ctx { + struct s3dl_query_ctx query_ctx; + uint32_t current_generation; +}; + +static void check_generation(sqlite3_stmt *stmt, void *context) { + struct check_generation_ctx *c = context; + CFDataRef blob = NULL; + size_t blobLen = 0; + const uint8_t *cursor = NULL; + uint32_t version; + keyclass_t keyclass; + uint32_t current_generation = c->current_generation; + + require(blob = s3dl_copy_data_from_col(stmt, 1, &c->query_ctx.q->q_error), out); + blobLen = CFDataGetLength(blob); + cursor = CFDataGetBytePtr(blob); + + /* Check for underflow, ensuring we have at least one full AES block left. */ + if (blobLen < sizeof(version) + sizeof(keyclass)) { + SecError(errSecDecode, &c->query_ctx.q->q_error, CFSTR("check_generation: Check for underflow")); + goto out; + } + + version = *((uint32_t *)cursor); + cursor += sizeof(version); + + (void) version; // TODO: do something with the version number. + + keyclass = *((keyclass_t *)cursor); + + // TODO: export get_key_gen macro + if (((keyclass & ~key_class_last) == 0) != (current_generation == 0)) { + c->query_ctx.found++; + } + + CFReleaseSafe(blob); + return; + +out: + c->query_ctx.found++; + CFReleaseSafe(blob); +} + +bool s3dl_dbt_keys_current(SecDbConnectionRef dbt, uint32_t current_generation, CFErrorRef *error) { + CFErrorRef localError = NULL; + struct check_generation_ctx ctx = { .query_ctx = { .dbt = dbt }, .current_generation = current_generation }; + + const SecDbClass *classes[] = { + &genp_class, + &inet_class, + &keys_class, + &cert_class, + }; + + for (size_t class_ix = 0; class_ix < array_size(classes); ++class_ix) { + Query *q = query_create(classes[class_ix], NULL, &localError); + if (!q) + return false; + + ctx.query_ctx.q = q; + q->q_limit = kSecMatchUnlimited; + + bool ok = s3dl_query(check_generation, &ctx, &localError); + query_destroy(q, NULL); + CFReleaseNull(ctx.query_ctx.result); + + if (!ok && localError && (CFErrorGetCode(localError) == errSecItemNotFound)) { + CFReleaseNull(localError); + continue; + } + secerror("Class %@ not up to date", classes[class_ix]->name); + return false; + } + return true; +} + +bool s3dl_dbt_update_keys(SecDbConnectionRef dbt, CFErrorRef *error) { + return SecDbTransaction(dbt, kSecDbExclusiveTransactionType, error, ^(bool *commit) { + __block bool ok = false; + uint32_t keystore_generation_status; + + /* can we migrate to new class keys right now? */ + if (!aks_generation(KEYBAG_DEVICE, generation_noop, &keystore_generation_status) && + (keystore_generation_status & generation_change_in_progress)) { + + /* take a lock assertion */ + bool operated_while_unlocked = SecAKSDoWhileUserBagLocked(error, ^{ + CFErrorRef localError = NULL; + CFDictionaryRef backup = SecServerExportKeychainPlist(dbt, + 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, + KEYBAG_DEVICE, backup, kSecNoItemFilter, &localError); + if (localError) { + secerror("Ignoring export error: %@ during roll export", localError); + CFReleaseNull(localError); + } + CFRelease(backup); + } + }); + if (!operated_while_unlocked) + ok = false; + } else { + ok = SecError(errSecBadReq, error, CFSTR("No key roll in progress.")); + } + + *commit = ok; + }); +} +#endif diff --git a/Security/sec/securityd/SecItemDb.h b/Security/sec/securityd/SecItemDb.h new file mode 100644 index 00000000..cbef46ee --- /dev/null +++ b/Security/sec/securityd/SecItemDb.h @@ -0,0 +1,131 @@ +/* + * 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@ + */ + +/*! + @header SecItemDb.h - A Database full of SecDbItems. + */ + +#ifndef _SECURITYD_SECITEMDB_H_ +#define _SECURITYD_SECITEMDB_H_ + +#include + +#define CURRENT_DB_VERSION 6 + +__BEGIN_DECLS + +#if 0 +// +// MARK: SecItemDb (a SecDb of SecDbItems) +// +typedef struct SecItemDb *SecItemDbRef; +typedef struct SecItemDbConnection *SecItemDbConnectionRef; + +struct SecItemDb { + CFRuntimeBase _base; + SecDbRef db; + CFDictionaryRef classes; // className -> SecItemClass mapping +}; + +struct SecItemDbConnection { + SecDbConnectionRef db; +}; + +SecItemDbRef SecItemDbCreate(SecDbRef db); +SecItemDbRef SecItemDbRegisterClass(SecItemDbRef db, const SecDbClass *class, void(^upgrade)(SecDbItemRef item, uint32_t current_version)); + +SecItemDbConnectionRef SecItemDbAquireConnection(SecItemDbRef db); +void SecItemDbReleaseConnection(SecItemDbRef db, SecItemDbConnectionRef dbconn); + +bool SecItemDbInsert(SecItemDbConnectionRef dbconn, SecDbItemRef item, CFErrorRef *error); + +bool SecItemDbDelete(SecItemDbConnectionRef dbconn, SecDbItemRef item, CFErrorRef *error); + +// Low level update, just do the update +bool SecItemDbDoUpdate(SecItemDbConnectionRef dbconn, SecDbItemRef old_item, SecDbItemRef new_item, CFErrorRef *error, + bool (^use_attr_in_where)(const SecDbAttr *attr)); + +// High level update, will replace tombstones and create them if needed. +bool SecItemDbUpdate(SecItemDbConnectionRef dbconn, SecDbItemRef old_item, SecDbItemRef new_item, CFErrorRef *error); + +bool SecItemDbSelect(SecItemDbConnectionRef dbconn, SecDbQueryRef query, CFErrorRef *error, + bool (^use_attr_in_where)(const SecDbAttr *attr), + bool (^add_where_sql)(CFMutableStringRef sql, bool *needWhere), + bool (^bind_added_where)(sqlite3_stmt *stmt, int col), + void (^handle_row)(SecDbItemRef item, bool *stop)); +#endif + +CFTypeRef SecDbItemCopyResult(SecDbItemRef item, ReturnTypeMask return_type, CFErrorRef *error); + +bool SecDbItemSelect(SecDbQueryRef query, SecDbConnectionRef dbconn, CFErrorRef *error, + bool (^use_attr_in_where)(const SecDbAttr *attr), + bool (^add_where_sql)(CFMutableStringRef sql, bool *needWhere), + bool (^bind_added_where)(sqlite3_stmt *stmt, int col), + void (^handle_row)(SecDbItemRef item, bool *stop)); + +CFStringRef SecDbItemCopySelectSQL(SecDbQueryRef query, + bool (^return_attr)(const SecDbAttr *attr), + bool (^use_attr_in_where)(const SecDbAttr *attr), + bool (^add_where_sql)(CFMutableStringRef sql, bool *needWhere)); +bool SecDbItemSelectBind(SecDbQueryRef query, sqlite3_stmt *stmt, CFErrorRef *error, + bool (^use_attr_in_where)(const SecDbAttr *attr), + bool (^bind_added_where)(sqlite3_stmt *stmt, int col)); + +bool SecDbItemQuery(SecDbQueryRef query, CFArrayRef accessGroups, SecDbConnectionRef dbconn, CFErrorRef *error, + void (^handle_row)(SecDbItemRef item, bool *stop)); + + +// +// MARK: backup restore stuff +// + +/* Forward declaration of import export SPIs. */ +enum SecItemFilter { + kSecNoItemFilter, + kSecSysBoundItemFilter, + kSecBackupableItemFilter, +}; + +CF_RETURNS_RETAINED CFDictionaryRef SecServerExportKeychainPlist(SecDbConnectionRef dbt, + 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); + +void SecDbAppendCreateTableWithClass(CFMutableStringRef sql, const SecDbClass *c); +bool kc_transaction(SecDbConnectionRef dbt, CFErrorRef *error, bool(^perform)()); +bool s3dl_copy_matching(SecDbConnectionRef dbt, Query *q, CFTypeRef *result, + CFArrayRef accessGroups, CFErrorRef *error); +bool s3dl_query_add(SecDbConnectionRef dbt, Query *q, CFTypeRef *result, CFErrorRef *error); +bool s3dl_query_update(SecDbConnectionRef dbt, Query *q, + CFDictionaryRef attributesToUpdate, CFArrayRef accessGroups, CFErrorRef *error); +bool s3dl_query_delete(SecDbConnectionRef dbt, Query *q, CFArrayRef accessGroups, CFErrorRef *error); +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); + +__END_DECLS + +#endif /* _SECURITYD_SECITEMDB_H_ */ diff --git a/Security/sec/securityd/SecItemSchema.c b/Security/sec/securityd/SecItemSchema.c new file mode 100644 index 00000000..25352df9 --- /dev/null +++ b/Security/sec/securityd/SecItemSchema.c @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + */ + +/* + * SecItemSchema.c - CoreFoundation-based constants and functions for + access to Security items (certificates, keys, identities, and + passwords.) + */ + +#include "SecItemSchema.h" + +// MARK - +// MARK Keychain version 6 schema + +#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 __FLAGS_ 0 +#define __FLAGS_P kSecDbPrimaryKeyFlag +#define __FLAGS_L kSecDbInFlag +#define __FLAGS_I kSecDbIndexFlag +#define __FLAGS_S kSecDbSHA1ValueInFlag +#define __FLAGS_A kSecDbReturnAttrFlag +#define __FLAGS_D kSecDbReturnDataFlag +#define __FLAGS_R kSecDbReturnRefFlag +#define __FLAGS_C kSecDbInCryptoDataFlag +#define __FLAGS_H kSecDbInHashFlag +#define __FLAGS_B kSecDbInBackupFlag +#define __FLAGS_Z kSecDbDefault0Flag +#define __FLAGS_E kSecDbDefaultEmptyFlag +#define __FLAGS_N kSecDbNotNullFlag +#define __FLAGS_U kSecDbInAuthenticatedDataFlag + +// ,-------------- P : Part of primary key +// / ,------------- L : Stored in local database +// / / ,------------ I : Attribute wants an index in the database +// / / / ,----------- S : SHA1 hashed attribute value in database (implies L) +// / / / / ,---------- A : Returned to client as attribute in queries +// / / / / / ,--------- D : Returned to client as data in queries +// / / / / / / ,-------- R : Returned to client as ref/persistant ref in queries +// / / / / / / / ,------- C : Part of encrypted blob +// / / / / / / / / ,------ H : Attribute is part of item SHA1 hash (Implied by C) +// / / / / / / / / / ,----- B : Attribute is part of iTunes/iCloud backup bag +// / / / / / / / / / / ,---- Z : Attribute has a default value of 0 +// / / / / / / / / / / / ,--- E : Attribute has a default value of "" or empty data +// / / / / / / / / / / / / ,-- N : Attribute must have a value +// / / / / / / / / / / / / / ,- U : Attribute is stored in authenticated, but not necessarily encrypted data +// / / / / / / / / / / / / / / +// / / / / / / / / / / / / / / +// | | | | | | | | | | | | | | +// common to all | | | | | | | | | | | | | | +SECDB_ATTR(v6rowid, "rowid", RowId, SecDbFlags( ,L, , , , ,R, , ,B, , , , )); +SECDB_ATTR(v6cdat, "cdat", CreationDate, SecDbFlags( ,L, , ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6mdat, "mdat",ModificationDate,SecDbFlags( ,L, , ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6labl, "labl", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , )); +SECDB_ATTR(v6data, "data", EncryptedData, SecDbFlags( ,L, , , , , , , ,B, , , , )); +SECDB_ATTR(v6agrp, "agrp", String, SecDbFlags(P,L, , ,A, , , ,H, , , , ,U)); +SECDB_ATTR(v6pdmn, "pdmn", Access, SecDbFlags( ,L, , ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6sync, "sync", Sync, SecDbFlags(P,L,I, ,A, , , ,H, ,Z, ,N,U)); +SECDB_ATTR(v6tomb, "tomb", Tomb, SecDbFlags( ,L, , , , , , ,H, ,Z, ,N,U)); +SECDB_ATTR(v6sha1, "sha1", SHA1, SecDbFlags( ,L,I, ,A, ,R, , , , , , , )); +SECDB_ATTR(v6accc, "accc", AccessControl, SecDbFlags( , , , ,A, , , , , , , , , )); +SECDB_ATTR(v6v_Data, "v_Data", Data, SecDbFlags( , , , , ,D, ,C,H, , , , , )); +SECDB_ATTR(v6v_pk, "v_pk", PrimaryKey, SecDbFlags( , , , , , , , , , , , , , )); +// genp and inet and keys | | | | | | | | | | | | | +SECDB_ATTR(v6crtr, "crtr", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6alis, "alis", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , )); +// genp and inet | | | | | | | | | | | | | +SECDB_ATTR(v6desc, "desc", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , )); +SECDB_ATTR(v6icmt, "icmt", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , )); +SECDB_ATTR(v6type, "type", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6invi, "invi", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6nega, "nega", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6cusi, "cusi", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6prot, "prot", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , )); +SECDB_ATTR(v6scrp, "scrp", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6acct, "acct", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, )); +// genp only | | | | | | | | | | | | | +SECDB_ATTR(v6svce, "svce", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, )); +SECDB_ATTR(v6gena, "gena", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , )); +// inet only | | | | | | | | | | | | | +SECDB_ATTR(v6sdmn, "sdmn", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, )); +SECDB_ATTR(v6srvr, "srvr", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, )); +SECDB_ATTR(v6ptcl, "ptcl", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, )); +SECDB_ATTR(v6atyp, "atyp", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, )); +SECDB_ATTR(v6port, "port", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, )); +SECDB_ATTR(v6path, "path", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, )); +// cert only | | | | | | | | | | | | | +SECDB_ATTR(v6ctyp, "ctyp", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, )); +SECDB_ATTR(v6cenc, "cenc", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6subj, "subj", Data, SecDbFlags( ,L,I,S,A, , ,C,H, , , , , )); +SECDB_ATTR(v6issr, "issr", Data, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, )); +SECDB_ATTR(v6slnr, "slnr", Data, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, )); +SECDB_ATTR(v6skid, "skid", Data, SecDbFlags( ,L,I,S,A, , ,C,H, , , , , )); +SECDB_ATTR(v6pkhh, "pkhh", Data, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , )); +// cert attributes that share names with common ones but have different flags +SECDB_ATTR(v6certalis, "alis", Blob, SecDbFlags( ,L,I,S,A, , ,C,H, , , , , )); +// keys only | | | | | | | | | | | | | +SECDB_ATTR(v6kcls, "kcls", Number, SecDbFlags(P,L,I,S,A, , ,C,H, ,Z, ,N, )); +SECDB_ATTR(v6perm, "perm", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6priv, "priv", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6modi, "modi", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6klbl, "klbl", Data, SecDbFlags(P,L,I, ,A, , ,C,H, , ,E,N, )); +SECDB_ATTR(v6atag, "atag", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, )); +SECDB_ATTR(v6bsiz, "bsiz", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, )); +SECDB_ATTR(v6esiz, "esiz", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, )); +SECDB_ATTR(v6sdat, "sdat", Date, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, )); +SECDB_ATTR(v6edat, "edat", Date, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, )); +SECDB_ATTR(v6sens, "sens", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6asen, "asen", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6extr, "extr", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6next, "next", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6encr, "encr", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6decr, "decr", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6drve, "drve", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6sign, "sign", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6vrfy, "vrfy", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6snrc, "snrc", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6vyrc, "vyrc", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6wrap, "wrap", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , )); +SECDB_ATTR(v6unwp, "unwp", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , )); +// 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, )); +SECDB_ATTR(v6keycrtr, "crtr", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, )); + +const SecDbClass genp_class = { + .name = CFSTR("genp"), + .attrs = { + &v6rowid, + &v6cdat, + &v6mdat, + &v6desc, + &v6icmt, + &v6crtr, + &v6type, + &v6scrp, + &v6labl, + &v6alis, + &v6invi, + &v6nega, + &v6cusi, + &v6prot, + &v6acct, + &v6svce, + &v6gena, + &v6data, + &v6agrp, + &v6pdmn, + &v6sync, + &v6tomb, + &v6sha1, + &v6v_Data, + &v6v_pk, + &v6accc, + NULL + }, +}; + +const SecDbClass inet_class = { + .name = CFSTR("inet"), + .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, + &v6v_Data, + &v6v_pk, + &v6accc, + 0 + }, +}; + +const SecDbClass cert_class = { + .name = CFSTR("cert"), + .attrs = { + &v6rowid, + &v6cdat, + &v6mdat, + &v6ctyp, + &v6cenc, + &v6labl, + &v6certalis, + &v6subj, + &v6issr, + &v6slnr, + &v6skid, + &v6pkhh, + &v6data, + &v6agrp, + &v6pdmn, + &v6sync, + &v6tomb, + &v6sha1, + &v6v_Data, + &v6v_pk, + &v6accc, + 0 + }, +}; + +const SecDbClass keys_class = { + .name = CFSTR("keys"), + .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, + &v6v_Data, + &v6v_pk, + &v6accc, + 0 + } +}; + +/* An identity which is really a cert + a key, so all cert and keys attrs are + allowed. */ +const SecDbClass identity_class = { + .name = CFSTR("idnt"), + .attrs = { + 0 + }, +}; diff --git a/Security/sec/securityd/SecItemSchema.h b/Security/sec/securityd/SecItemSchema.h new file mode 100644 index 00000000..e7e4c008 --- /dev/null +++ b/Security/sec/securityd/SecItemSchema.h @@ -0,0 +1,59 @@ +/* + * 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@ + */ + +/*! + @header SecItemSchema.h - The thing that does the stuff with the gibli. + */ + +#ifndef _SECURITYD_SECITEMSCHEMA_H_ +#define _SECURITYD_SECITEMSCHEMA_H_ + +#include + +__BEGIN_DECLS + +// TODO: Rename to something like kSecItemGenpClass +extern const SecDbClass genp_class; + +// TODO: Rename to something like kSecItemInetClass +extern const SecDbClass inet_class; + +// TODO: Rename to something like kSecItemCertClass +extern const SecDbClass cert_class; + +// TODO: Rename to something like kSecItemKeysClass +extern const SecDbClass keys_class; + +// TODO: Rename to something like kSecItemIdentityClass // <-- not really a class per-se +extern const SecDbClass identity_class; + +// TODO: Rename to something like kSecItemValueDataAttr +extern const SecDbAttr v6v_Data; + +// TODO: Directly expose other important attributes like +// kSecItemSyncAttr, kSecItemTombAttr, kSecItemCdatAttr, kSecItemMdatAttr, kSecItemDataAttr +// This will prevent having to do lookups in SecDbItem for thing by kind. + +__END_DECLS + +#endif /* _SECURITYD_SECITEMSCHEMA_H_ */ diff --git a/Security/sec/securityd/SecItemServer.c b/Security/sec/securityd/SecItemServer.c new file mode 100644 index 00000000..d776366f --- /dev/null +++ b/Security/sec/securityd/SecItemServer.c @@ -0,0 +1,1885 @@ +/* + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + */ + +/* + * SecItemServer.c - CoreFoundation-based constants and functions for + access to Security items (certificates, keys, identities, and + passwords.) + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// TODO: Make this include work on both platforms. rdar://problem/16526848 +#if TARGET_OS_EMBEDDED +#include +#else +/* defines from */ +#define kSecEntitlementAssociatedDomains CFSTR("com.apple.developer.associated-domains") +#define kSecEntitlementPrivateAssociatedDomains CFSTR("com.apple.private.associated-domains") +#endif + +#include +#include +#include +#include "swcagent_client.h" + +#if TARGET_OS_IPHONE +#include +#else +typedef uint32_t SWCFlags; +#define kSWCFlags_None 0 +#define kSWCFlag_Pending ( 1U << 0 ) +#define kSWCFlag_SiteApproved ( 1U << 1 ) +#define kSWCFlag_SiteDenied ( 1U << 2 ) +#define kSWCFlag_UserApproved ( 1U << 3 ) +#define kSWCFlag_UserDenied ( 1U << 4 ) +#define kSWCFlag_ExternalMask ( kSWCFlag_UserApproved | kSWCFlag_UserDenied ) +#endif + +/* Changed the name of the keychain changed notification, for testing */ +static const char *g_keychain_changed_notification = kSecServerKeychainChangedNotification; + +void SecItemServerSetKeychainChangedNotification(const char *notification_name) +{ + g_keychain_changed_notification = notification_name; +} + +void SecKeychainChanged(bool syncWithPeers) { + uint32_t result = notify_post(g_keychain_changed_notification); + if (syncWithPeers) + SOSCCSyncWithAllPeers(); + if (result == NOTIFY_STATUS_OK) + secnotice("item", "Sent %s%s", syncWithPeers ? "SyncWithAllPeers and " : "", g_keychain_changed_notification); + else + secerror("%snotify_post %s returned: %" PRIu32, syncWithPeers ? "Sent SyncWithAllPeers, " : "", g_keychain_changed_notification, result); + } + +static const char * const s3dl_upgrade_sql[] = { + /* 0 */ + "", + + /* 1 */ + /* Create indices. */ + "CREATE INDEX igsha ON genp(sha1);" + "CREATE INDEX iisha ON inet(sha1);" + "CREATE INDEX icsha ON cert(sha1);" + "CREATE INDEX iksha ON keys(sha1);" + "CREATE INDEX ialis ON cert(alis);" + "CREATE INDEX isubj ON cert(subj);" + "CREATE INDEX iskid ON cert(skid);" + "CREATE INDEX ipkhh ON cert(pkhh);" + "CREATE INDEX ikcls ON keys(kcls);" + "CREATE INDEX iklbl ON keys(klbl);" + "CREATE INDEX iencr ON keys(encr);" + "CREATE INDEX idecr ON keys(decr);" + "CREATE INDEX idrve ON keys(drve);" + "CREATE INDEX isign ON keys(sign);" + "CREATE INDEX ivrfy ON keys(vrfy);" + "CREATE INDEX iwrap ON keys(wrap);" + "CREATE INDEX iunwp ON keys(unwp);", + + /* 2 */ + "", + + /* 3 */ + /* Rename version 2 or version 3 tables and drop version table since + step 0 creates it. */ + "ALTER TABLE genp RENAME TO ogenp;" + "ALTER TABLE inet RENAME TO oinet;" + "ALTER TABLE cert RENAME TO ocert;" + "ALTER TABLE keys RENAME TO okeys;" + "DROP TABLE tversion;", + + /* 4 */ + "", + + /* 5 */ + "", + + /* 6 */ + "", + + /* 7 */ + /* Move data from version 5 tables to new ones and drop old ones. */ + "INSERT INTO genp (rowid,cdat,mdat,desc,icmt,crtr,type,scrp,labl,alis,invi,nega,cusi,prot,acct,svce,gena,data,agrp,pdmn) SELECT rowid,cdat,mdat,desc,icmt,crtr,type,scrp,labl,alis,invi,nega,cusi,prot,acct,svce,gena,data,agrp,pdmn from ogenp;" + "INSERT INTO inet (rowid,cdat,mdat,desc,icmt,crtr,type,scrp,labl,alis,invi,nega,cusi,prot,acct,sdmn,srvr,ptcl,atyp,port,path,data,agrp,pdmn) SELECT rowid,cdat,mdat,desc,icmt,crtr,type,scrp,labl,alis,invi,nega,cusi,prot,acct,sdmn,srvr,ptcl,atyp,port,path,data,agrp,pdmn from oinet;" + "INSERT INTO cert (rowid,cdat,mdat,ctyp,cenc,labl,alis,subj,issr,slnr,skid,pkhh,data,agrp,pdmn) SELECT rowid,cdat,mdat,ctyp,cenc,labl,alis,subj,issr,slnr,skid,pkhh,data,agrp,pdmn from ocert;" + "INSERT INTO keys (rowid,cdat,mdat,kcls,labl,alis,perm,priv,modi,klbl,atag,crtr,type,bsiz,esiz,sdat,edat,sens,asen,extr,next,encr,decr,drve,sign,vrfy,snrc,vyrc,wrap,unwp,data,agrp,pdmn) SELECT rowid,cdat,mdat,kcls,labl,alis,perm,priv,modi,klbl,atag,crtr,type,bsiz,esiz,sdat,edat,sens,asen,extr,next,encr,decr,drve,sign,vrfy,snrc,vyrc,wrap,unwp,data,agrp,pdmn from okeys;" + "DROP TABLE ogenp;" + "DROP TABLE oinet;" + "DROP TABLE ocert;" + "DROP TABLE okeys;" + "CREATE INDEX igsha ON genp(sha1);" + "CREATE INDEX iisha ON inet(sha1);" + "CREATE INDEX icsha ON cert(sha1);" + "CREATE INDEX iksha ON keys(sha1);", +}; + +struct sql_stages { + int pre; + int main; + int post; + bool init_pdmn; // If true do a full export followed by an import of the entire database so all items are re-encoded. +}; + +/* On disk database format version upgrade scripts. + If pre is 0, version is unsupported and db is considered corrupt for having that version. + First entry creates the current db, each susequent entry upgrade to current from the version + represented by the index of the slot. Each script is either -1 (disabled) of the number of + the script in the main table. + {pre,main,post, reencode} */ + + +static struct sql_stages s3dl_upgrade_script[] = { + { -1, 0, 1, false },/* 0->current: Create version 6*/ + {}, /* 1->current: Upgrade to version 6 from version 1 -- Unsupported. */ + {}, /* 2->current: Upgrade to version 6 from version 2 -- Unsupported */ + {}, /* 3->current: Upgrade to version 6 from version 3 -- Unsupported */ + {}, /* 4->current: Upgrade to version 6 from version 4 -- Unsupported */ + { 3, 0, 7, true }, /* 5->current: Upgrade to version 6 from version 5 */ +}; + +static bool sql_run_script(SecDbConnectionRef dbt, int number, CFErrorRef *error) +{ + /* Script -1 == skip this step. */ + if (number < 0) + return true; + + /* If we are attempting to run a script we don't have, fail. */ + if ((size_t)number >= array_size(s3dl_upgrade_sql)) + return SecDbError(SQLITE_CORRUPT, error, CFSTR("script %d exceeds maximum %d"), + number, (int)(array_size(s3dl_upgrade_sql))); + __block bool ok = true; + if (number == 0) { + CFMutableStringRef sql = CFStringCreateMutable(0, 0); + SecDbAppendCreateTableWithClass(sql, &genp_class); + SecDbAppendCreateTableWithClass(sql, &inet_class); + SecDbAppendCreateTableWithClass(sql, &cert_class); + SecDbAppendCreateTableWithClass(sql, &keys_class); + CFStringAppend(sql, CFSTR("CREATE TABLE tversion(version INTEGER);INSERT INTO tversion(version) VALUES(6);")); + CFStringPerformWithCString(sql, ^(const char *sql_string) { + ok = SecDbErrorWithDb(sqlite3_exec(SecDbHandle(dbt), sql_string, NULL, NULL, NULL), + SecDbHandle(dbt), error, CFSTR("sqlite3_exec: %s"), sql_string); + }); + CFReleaseSafe(sql); + } else { + ok = SecDbErrorWithDb(sqlite3_exec(SecDbHandle(dbt), s3dl_upgrade_sql[number], NULL, NULL, NULL), + SecDbHandle(dbt), error, CFSTR("sqlite3_exec: %s"), s3dl_upgrade_sql[number]); + } + return ok; +} + +/* Return the current database version in *version. Returns a + SQLITE error. */ +static bool s3dl_dbt_get_version(SecDbConnectionRef dbt, int *version, CFErrorRef *error) +{ + CFStringRef sql = CFSTR("SELECT version FROM tversion LIMIT 1"); + return SecDbWithSQL(dbt, sql, error, ^(sqlite3_stmt *stmt) { + __block bool found_version = false; + bool step_ok = SecDbForEach(stmt, error, ^(int row_index __unused) { + if (!found_version) { + *version = sqlite3_column_int(stmt, 0); + found_version = true; + } + return found_version; + }); + if (!found_version) { + /* We have a tversion table but we didn't find a single version + value, now what? I suppose we pretend the db is corrupted + since this isn't supposed to ever happen. */ + step_ok = SecDbError(SQLITE_CORRUPT, error, CFSTR("Failed to read version: database corrupt")); + secwarning("SELECT version step: %@", error ? *error : NULL); + } + return step_ok; + }); +} + + +static bool s3dl_dbt_upgrade_from_version(SecDbConnectionRef dbt, int version, CFErrorRef *error) +{ + /* We need to go from db version to CURRENT_DB_VERSION, let's do so. */ + __block bool ok = true; + /* O, guess we're done already. */ + if (version == CURRENT_DB_VERSION) + return ok; + + if (ok && version < 6) { + // Pre v6 keychains need to have WAL enabled, since SecDb only + // does this at db creation time. + // NOTE: This has to be run outside of a transaction. + ok = (SecDbExec(dbt, CFSTR("PRAGMA auto_vacuum = FULL"), error) && + SecDbExec(dbt, CFSTR("PRAGMA journal_mode = WAL"), error)); + } + + // Start a transaction to do the upgrade within + if (ok) { ok = SecDbTransaction(dbt, kSecDbExclusiveTransactionType, error, ^(bool *commit) { + // Be conservative and get the version again once we start a transaction. + int cur_version = version; + s3dl_dbt_get_version(dbt, &cur_version, NULL); + + /* If we are attempting to upgrade to a version greater than what we have + an upgrade script for, fail. */ + if (ok && (cur_version < 0 || + (size_t)cur_version >= array_size(s3dl_upgrade_script))) { + ok = SecDbError(SQLITE_CORRUPT, error, CFSTR("no upgrade script for version: %d"), cur_version); + secerror("no upgrade script for version %d", cur_version); + } + + struct sql_stages *script; + if (ok) { + script = &s3dl_upgrade_script[cur_version]; + if (script->pre == 0) + ok = SecDbError(SQLITE_CORRUPT, error, CFSTR("unsupported db version %d"), cur_version); + } + if (ok) + ok = sql_run_script(dbt, script->pre, error); + if (ok) + ok = sql_run_script(dbt, script->main, error); + if (ok) + ok = sql_run_script(dbt, script->post, error); + if (ok && script->init_pdmn) { + CFErrorRef localError = NULL; + CFDictionaryRef backup = SecServerExportKeychainPlist(dbt, + KEYBAG_DEVICE, KEYBAG_NONE, kSecNoItemFilter, &localError); + if (backup) { + if (localError) { + secerror("Ignoring export error: %@ during upgrade export", localError); + CFReleaseNull(localError); + } + ok = SecServerImportKeychainInPlist(dbt, KEYBAG_NONE, + KEYBAG_DEVICE, backup, kSecNoItemFilter, &localError); + CFRelease(backup); + } else { + ok = false; + + if (localError && SecErrorGetOSStatus(localError) == errSecInteractionNotAllowed) { + SecError(errSecUpgradePending, error, + CFSTR("unable to complete upgrade due to device lock state")); + secerror("unable to complete upgrade due to device lock state"); + } else { + secerror("unable to complete upgrade for unknown reason, marking DB as corrupt: %@", localError); + SecDbCorrupt(dbt); + } + } + + if (localError) { + if (error && !*error) + *error = localError; + else + CFRelease(localError); + } + } else if (!ok) { + secerror("unable to complete upgrade scripts, marking DB as corrupt: %@", error ? *error : NULL); + SecDbCorrupt(dbt); + } + *commit = ok; + }); } else { + secerror("unable to complete upgrade scripts, marking DB as corrupt: %@", error ? *error : NULL); + SecDbCorrupt(dbt); + } + + return ok; +} + + +/* This function is called if the db doesn't have the proper version. We + start an exclusive transaction and recheck the version, and then perform + the upgrade within that transaction. */ +static bool s3dl_dbt_upgrade(SecDbConnectionRef dbt, CFErrorRef *error) +{ + // Already in a transaction + //return kc_transaction(dbt, error, ^{ + int version = 0; // Upgrade from version 0 == create new db + s3dl_dbt_get_version(dbt, &version, NULL); + return s3dl_dbt_upgrade_from_version(dbt, version, error); + //}); +} + +/* AUDIT[securityd](done): + accessGroup (ok) is a caller provided, non NULL CFTypeRef. + + Return true iff accessGroup is allowable according to accessGroups. + */ +static bool accessGroupsAllows(CFArrayRef accessGroups, + CFStringRef accessGroup) { + /* NULL accessGroups is wildcard. */ + if (!accessGroups) + return true; + /* Make sure we have a string. */ + if (!isString(accessGroup)) + return false; + + /* Having the special accessGroup "*" allows access to all accessGroups. */ + CFRange range = { 0, CFArrayGetCount(accessGroups) }; + if (range.length && + (CFArrayContainsValue(accessGroups, range, accessGroup) || + CFArrayContainsValue(accessGroups, range, CFSTR("*")))) + return true; + + return false; +} + +bool itemInAccessGroup(CFDictionaryRef item, CFArrayRef accessGroups) { + return accessGroupsAllows(accessGroups, + CFDictionaryGetValue(item, kSecAttrAccessGroup)); +} + + +static CF_RETURNS_RETAINED CFDataRef SecServerExportKeychain(SecDbConnectionRef dbt, + 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, + src_keybag, dest_keybag, kSecBackupableItemFilter, + error); + if (keychain) { + data_out = CFPropertyListCreateData(kCFAllocatorDefault, keychain, + kCFPropertyListBinaryFormat_v1_0, + 0, error); + CFRelease(keychain); + } + + return data_out; +} + +static bool SecServerImportKeychain(SecDbConnectionRef dbt, + keybag_handle_t src_keybag, + keybag_handle_t dest_keybag, CFDataRef data, CFErrorRef *error) { + return kc_transaction(dbt, error, ^{ + bool ok = false; + CFDictionaryRef keychain; + keychain = CFPropertyListCreateWithData(kCFAllocatorDefault, data, + kCFPropertyListImmutable, NULL, + error); + if (keychain) { + if (isDictionary(keychain)) { + ok = SecServerImportKeychainInPlist(dbt, src_keybag, + dest_keybag, keychain, + kSecBackupableItemFilter, + error); + } else { + ok = SecError(errSecParam, error, CFSTR("import: keychain is not a dictionary")); + } + CFRelease(keychain); + } + return ok; + }); +} + +static CF_RETURNS_RETAINED CFDataRef SecServerKeychainBackup(SecDbConnectionRef dbt, 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 = SecServerExportKeychain(dbt, KEYBAG_DEVICE, backup_keybag, error); + if (!ks_close_keybag(backup_keybag, error)) { + CFReleaseNull(backup); + } + } + return backup; +} + +static bool SecServerKeychainRestore(SecDbConnectionRef dbt, 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 = SecServerImportKeychain(dbt, backup_keybag, KEYBAG_DEVICE, + backup, error); + ok &= ks_close_keybag(backup_keybag, error); + + return ok; +} + + +// MARK - External SPI support code. + +CFStringRef __SecKeychainCopyPath(void) { + CFStringRef kcRelPath = NULL; + if (use_hwaes()) { + kcRelPath = CFSTR("keychain-2.db"); + } else { + kcRelPath = CFSTR("keychain-2-debug.db"); + } + + CFStringRef kcPath = NULL; + CFURLRef kcURL = SecCopyURLForFileInKeychainDirectory(kcRelPath); + if (kcURL) { + kcPath = CFURLCopyFileSystemPath(kcURL, kCFURLPOSIXPathStyle); + CFRelease(kcURL); + } + return kcPath; + +} + +// MARK; - +// MARK: kc_dbhandle init and reset + +SecDbRef SecKeychainDbCreate(CFStringRef path) { + return SecDbCreate(path, ^bool (SecDbConnectionRef dbconn, bool didCreate, CFErrorRef *localError) { + bool ok; + if (didCreate) + ok = s3dl_dbt_upgrade_from_version(dbconn, 0, localError); + else + ok = s3dl_dbt_upgrade(dbconn, localError); + + if (!ok) + secerror("Upgrade %sfailed: %@", didCreate ? "from v0 " : "", localError ? *localError : NULL); + + return ok; + }); +} + +static SecDbRef _kc_dbhandle = NULL; + +static void kc_dbhandle_init(void) { + SecDbRef oldHandle = _kc_dbhandle; + _kc_dbhandle = NULL; + CFStringRef dbPath = __SecKeychainCopyPath(); + if (dbPath) { + _kc_dbhandle = SecKeychainDbCreate(dbPath); + CFRelease(dbPath); + } else { + secerror("no keychain path available"); + } + if (oldHandle) { + secerror("replaced %@ with %@", oldHandle, _kc_dbhandle); + CFRelease(oldHandle); + } +} + +static dispatch_once_t _kc_dbhandle_once; + +static SecDbRef kc_dbhandle(void) { + dispatch_once(&_kc_dbhandle_once, ^{ + kc_dbhandle_init(); + }); + return _kc_dbhandle; +} + +/* For whitebox testing only */ +void kc_dbhandle_reset(void); +void kc_dbhandle_reset(void) +{ + __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(); +} + +static SecDbConnectionRef kc_aquire_dbt(bool writeAndRead, CFErrorRef *error) { + SecDbRef db = kc_dbhandle(); + if (db == NULL) { + SecError(errSecDataNotAvailable, error, CFSTR("failed to get a db handle")); + return NULL; + } + return SecDbConnectionAquire(db, !writeAndRead, error); +} + +/* Return a per thread dbt handle for the keychain. If create is true create + the database if it does not yet exist. If it is false, just return an + error if it fails to auto-create. */ +static bool kc_with_dbt(bool writeAndRead, CFErrorRef *error, bool (^perform)(SecDbConnectionRef dbt)) +{ + // Make sure we initialize our engines before writing to the keychain + if (writeAndRead) + SecItemDataSourceFactoryGetDefault(); + + bool ok = false; + SecDbConnectionRef dbt = kc_aquire_dbt(writeAndRead, error); + if (dbt) { + ok = perform(dbt); + SecDbConnectionRelease(dbt); + } + return ok; +} + +static bool +items_matching_issuer_parent(SecDbConnectionRef dbt, CFArrayRef accessGroups, + CFDataRef issuer, CFArrayRef issuers, int recurse) +{ + Query *q; + CFArrayRef results = NULL; + CFIndex i, count; + bool found = false; + + if (CFArrayContainsValue(issuers, CFRangeMake(0, CFArrayGetCount(issuers)), issuer)) + return true; + + const void *keys[] = { kSecClass, kSecReturnRef, kSecAttrSubject }; + const void *vals[] = { kSecClassCertificate, kCFBooleanTrue, issuer }; + CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, array_size(keys), NULL, NULL); + + if (!query) + return false; + + CFErrorRef localError = NULL; + q = query_create_with_limit(query, kSecMatchUnlimited, &localError); + CFRelease(query); + if (q) { + s3dl_copy_matching(dbt, q, (CFTypeRef*)&results, accessGroups, &localError); + query_destroy(q, &localError); + } + if (localError) { + secerror("items matching issuer parent: %@", localError); + CFReleaseNull(localError); + return false; + } + + count = CFArrayGetCount(results); + for (i = 0; (i < count) && !found; i++) { + CFDictionaryRef cert_dict = (CFDictionaryRef)CFArrayGetValueAtIndex(results, i); + CFDataRef cert_issuer = CFDictionaryGetValue(cert_dict, kSecAttrIssuer); + if (CFEqual(cert_issuer, issuer)) + continue; + if (recurse-- > 0) + found = items_matching_issuer_parent(dbt, accessGroups, cert_issuer, issuers, recurse); + } + CFReleaseSafe(results); + + return found; +} + +bool match_item(SecDbConnectionRef dbt, Query *q, CFArrayRef accessGroups, CFDictionaryRef item) +{ + 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*/)) + return false; + } + + /* Add future match checks here. */ + + return true; +} + +/**************************************************************************** + **************** 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 + +/* AUDIT[securityd](done): + query (ok) is a caller provided dictionary, only its cf type has been checked. + */ +static bool +SecItemServerCopyMatching(CFDictionaryRef query, CFTypeRef *result, + CFArrayRef accessGroups, CFErrorRef *error) +{ + CFIndex ag_count; + if (!accessGroups || 0 == (ag_count = CFArrayGetCount(accessGroups))) { + return SecError(errSecMissingEntitlement, error, + CFSTR("client has neither application-identifier nor keychain-access-groups entitlements")); + } + + if (CFArrayContainsValue(accessGroups, CFRangeMake(0, ag_count), CFSTR("*"))) { + /* Having the special accessGroup "*" allows access to all accessGroups. */ + accessGroups = NULL; + } + + bool ok = false; + Query *q = query_create_with_limit(query, 1, error); + if (q) { + CFStringRef agrp = CFDictionaryGetValue(q->q_item, kSecAttrAccessGroup); + if (agrp && accessGroupsAllows(accessGroups, agrp)) { + // TODO: Return an error if agrp is not NULL and accessGroupsAllows() fails above. + const void *val = agrp; + accessGroups = CFArrayCreate(0, &val, 1, &kCFTypeArrayCallBacks); + } else { + CFRetainSafe(accessGroups); + } + + query_enable_interactive(q); + query_set_caller_access_groups(q, accessGroups); + + /* Sanity check the query. */ + 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")); + } else if (q->q_return_type != 0 && result == NULL) { + ok = SecError(errSecReturnMissingPointer, error, CFSTR("missing pointer")); + } else if (!q->q_error) { + do { + ok = kc_with_dbt(false, error, ^(SecDbConnectionRef dbt) { + return s3dl_copy_matching(dbt, q, result, accessGroups, error); + }); + } while (query_needs_authentication(q) && (ok = query_authenticate(q, &error))); + } + + CFReleaseSafe(accessGroups); + if (!query_destroy(q, error)) + ok = false; + } + + return ok; +} + +bool +_SecItemCopyMatching(CFDictionaryRef query, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error) { + return SecItemServerCopyMatching(query, result, accessGroups, error); +} + +/* 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) +{ + bool ok = true; + CFIndex ag_count; + if (!accessGroups || 0 == (ag_count = CFArrayGetCount(accessGroups))) + return SecError(errSecMissingEntitlement, error, + CFSTR("client has neither application-identifier nor keychain-access-groups entitlements")); + + Query *q = query_create_with_limit(attributes, 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; + + if (agrp) { + /* The user specified an explicit access group, validate it. */ + if (!accessGroupsAllows(accessGroups, agrp)) + return SecError(errSecNoAccessForItem, error, CFSTR("NoAccessForItem")); + } else { + agrp = (CFStringRef)CFArrayGetValueAtIndex(ag, 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); + } + + query_ensure_access_control(q, agrp); + query_enable_interactive(q); + + 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) { + do { + ok = kc_with_dbt(true, error, ^(SecDbConnectionRef dbt){ + return kc_transaction(dbt, error, ^{ + query_pre_add(q, true); + return s3dl_query_add(dbt, q, result, error); + }); + }); + } while (query_needs_authentication(q) && (ok = query_authenticate(q, &error))); + } + ok = query_notify_and_destroy(q, ok, error); + } else { + ok = false; + } + return ok; +} + +/* AUDIT[securityd](done): + query (ok) and attributesToUpdate (ok) are a caller provided dictionaries, + only their cf types have been checked. + */ +bool +_SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate, + CFArrayRef accessGroups, CFErrorRef *error) +{ + CFIndex ag_count; + if (!accessGroups || 0 == (ag_count = CFArrayGetCount(accessGroups))) { + return SecError(errSecMissingEntitlement, error, + CFSTR("client has neither application-identifier nor keychain-access-groups entitlements")); + } + + if (CFArrayContainsValue(accessGroups, CFRangeMake(0, ag_count), CFSTR("*"))) { + /* Having the special accessGroup "*" allows access to all accessGroups. */ + accessGroups = NULL; + } + + bool ok = true; + Query *q = query_create_with_limit(query, kSecMatchUnlimited, error); + if (!q) { + ok = false; + } + if (ok) { + /* Sanity check the query. */ + query_set_caller_access_groups(q, accessGroups); + 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. */ + ok = SecError(errSecReturnDataUnsupported, error, CFSTR("return data not supported by update")); + } else if (q->q_return_type & kSecReturnAttributesMask) { + ok = SecError(errSecReturnAttributesUnsupported, error, CFSTR("return attributes not supported by update")); + } else if (q->q_return_type & kSecReturnRefMask) { + ok = SecError(errSecReturnRefUnsupported, error, CFSTR("return ref not supported by update")); + } else if (q->q_return_type & kSecReturnPersistentRefMask) { + ok = SecError(errSecReturnPersistentRefUnsupported, error, CFSTR("return persistent ref not supported by update")); + } else { + /* Access group sanity checking. */ + CFStringRef agrp = (CFStringRef)CFDictionaryGetValue(attributesToUpdate, + kSecAttrAccessGroup); + if (agrp) { + /* The user is attempting to modify the access group column, + validate it to make sure the new value is allowable. */ + if (!accessGroupsAllows(accessGroups, agrp)) { + ok = SecError(errSecNoAccessForItem, error, CFSTR("accessGroup %@ not in %@"), agrp, accessGroups); + } + } + } + } + if (ok) { + if (!q->q_use_tomb && SOSCCThisDeviceDefinitelyNotActiveInCircle()) { + q->q_use_tomb = kCFBooleanFalse; + } + query_enable_interactive(q); + do { + ok = kc_with_dbt(true, error, ^(SecDbConnectionRef dbt) { + return s3dl_query_update(dbt, q, attributesToUpdate, accessGroups, error); + }); + } while (query_needs_authentication(q) && (ok = query_authenticate(q, &error))); + } + if (q) { + ok = query_notify_and_destroy(q, ok, error); + } + return ok; +} + + +/* AUDIT[securityd](done): + query (ok) is a caller provided dictionary, only its cf type has been checked. + */ +bool +_SecItemDelete(CFDictionaryRef query, CFArrayRef accessGroups, CFErrorRef *error) +{ + CFIndex ag_count; + if (!accessGroups || 0 == (ag_count = CFArrayGetCount(accessGroups))) { + return SecError(errSecMissingEntitlement, error, + CFSTR("client has neither application-identifier nor keychain-access-groups entitlements")); + } + + if (CFArrayContainsValue(accessGroups, CFRangeMake(0, ag_count), CFSTR("*"))) { + /* Having the special accessGroup "*" allows access to all accessGroups. */ + accessGroups = NULL; + } + + Query *q = query_create_with_limit(query, kSecMatchUnlimited, error); + bool ok; + if (q) { + q->q_crypto_op = kSecKsDelete; + query_set_caller_access_groups(q, accessGroups); + /* Sanity check the query. */ + if (q->q_limit != kSecMatchUnlimited) + ok = SecError(errSecMatchLimitUnsupported, error, CFSTR("match limit not supported by delete")); + else if (query_match_count(q) != 0) + ok = SecError(errSecItemMatchUnsupported, error, CFSTR("match not supported by delete")); + 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)) + ok = SecError(errSecItemIllegalQuery, error, CFSTR("rowid and other attributes are mutually exclusive")); + else { + if (!q->q_use_tomb && SOSCCThisDeviceDefinitelyNotActiveInCircle()) { + q->q_use_tomb = kCFBooleanFalse; + } + query_enable_interactive(q); + do { + ok = kc_with_dbt(true, error, ^(SecDbConnectionRef dbt) { + return s3dl_query_delete(dbt, q, accessGroups, error); + }); + } while (query_needs_authentication(q) && (ok = query_authenticate(q, &error))); + } + ok = query_notify_and_destroy(q, ok, error); + } else { + ok = false; + } + return ok; +} + + +/* AUDIT[securityd](done): + No caller provided inputs. + */ +static bool +SecItemServerDeleteAll(CFErrorRef *error) { + return kc_with_dbt(true, error, ^bool (SecDbConnectionRef dbt) { + return (kc_transaction(dbt, error, ^bool { + return (SecDbExec(dbt, CFSTR("DELETE from genp;"), error) && + SecDbExec(dbt, CFSTR("DELETE from inet;"), error) && + SecDbExec(dbt, CFSTR("DELETE from cert;"), error) && + SecDbExec(dbt, CFSTR("DELETE from keys;"), error)); + }) && SecDbExec(dbt, CFSTR("VACUUM;"), error)); + }); +} + +bool +_SecItemDeleteAll(CFErrorRef *error) { + return SecItemServerDeleteAll(error); +} + + +// MARK: - +// MARK: Shared web credentials + +/* constants */ +#define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); + +SEC_CONST_DECL (kSecSafariAccessGroup, "com.apple.cfnetwork"); +SEC_CONST_DECL (kSecSafariDefaultComment, "default"); +SEC_CONST_DECL (kSecSafariPasswordsNotSaved, "Passwords not saved"); +SEC_CONST_DECL (kSecSharedCredentialUrlScheme, "https://"); +SEC_CONST_DECL (kSecSharedWebCredentialsService, "webcredentials"); + +#if !TARGET_IPHONE_SIMULATOR +static SWCFlags +_SecAppDomainApprovalStatus(CFStringRef appID, CFStringRef fqdn, CFErrorRef *error) +{ + __block SWCFlags flags = kSWCFlags_None; + +#if TARGET_OS_IPHONE + CFRetainSafe(appID); + CFRetainSafe(fqdn); + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + dispatch_retain(semaphore); + if (0 == SWCCheckService(kSecSharedWebCredentialsService, appID, fqdn, + ^void (OSStatus inStatus, SWCFlags inFlags, CFDictionaryRef inDetails) { + if (!inStatus) { flags = inFlags; } + CFReleaseSafe(appID); + CFReleaseSafe(fqdn); + dispatch_semaphore_signal(semaphore); + dispatch_release(semaphore); + //secerror("SWCCheckService: inStatus=%d, flags=%0X", inStatus, flags); + })) + { + // wait for the block to complete, as we need its answer + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + } + else // didn't queue the block + { + CFReleaseSafe(appID); + CFReleaseSafe(fqdn); + dispatch_release(semaphore); + } + dispatch_release(semaphore); +#else + flags |= (kSWCFlag_SiteApproved); +#endif + + if (!error) { return flags; } + *error = NULL; + + // check website approval status + if (!(flags & kSWCFlag_SiteApproved)) { + if (flags & kSWCFlag_Pending) { + SecError(errSecAuthFailed, error, CFSTR("Approval is pending for \"%@\", try later"), fqdn); + } else { + SecError(errSecAuthFailed, error, CFSTR("\"%@\" failed to approve \"%@\""), fqdn, appID); + } + return flags; + } + + // check user approval status + if (flags & kSWCFlag_UserDenied) { + SecError(errSecAuthFailed, error, CFSTR("User denied access to \"%@\" by \"%@\""), fqdn, appID); + } + return flags; +} +#endif + +#if !TARGET_IPHONE_SIMULATOR +static bool +_SecEntitlementContainsDomainForService(CFArrayRef domains, CFStringRef domain, CFStringRef service) +{ + bool result = false; + CFIndex idx, count = (domains) ? CFArrayGetCount(domains) : (CFIndex) 0; + if (!count || !domain || !service) { + return result; + } + for (idx=0; idx < count; idx++) { + CFStringRef str = (CFStringRef) CFArrayGetValueAtIndex(domains, idx); + if (str && CFStringHasPrefix(str, kSecSharedWebCredentialsService)) { + CFIndex prefix_len = CFStringGetLength(kSecSharedWebCredentialsService)+1; + CFIndex substr_len = CFStringGetLength(str) - prefix_len; + CFRange range = { prefix_len, substr_len }; + CFStringRef substr = CFStringCreateWithSubstring(kCFAllocatorDefault, str, range); + if (substr && CFEqual(substr, domain)) { + result = true; + } + CFReleaseSafe(substr); + if (result) { + break; + } + } + } + return result; +} +#endif + +static bool +_SecAddNegativeWebCredential(CFStringRef fqdn, CFStringRef appID, bool forSafari) +{ + bool result = false; + if (!fqdn) { return result; } + +#if TARGET_OS_IPHONE + // update our database + CFRetainSafe(appID); + CFRetainSafe(fqdn); + if (0 == SWCSetServiceFlags(kSecSharedWebCredentialsService, + appID, fqdn, kSWCFlag_ExternalMask, kSWCFlag_UserDenied, + ^void(OSStatus inStatus, SWCFlags inNewFlags){ + CFReleaseSafe(appID); + CFReleaseSafe(fqdn); + })) + { + result = true; + } + else // didn't queue the block + { + CFReleaseSafe(appID); + CFReleaseSafe(fqdn); + } +#endif + if (!forSafari) { return result; } + + // below this point: create a negative Safari web credential item + + CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (!attrs) { return result; } + + CFErrorRef error = NULL; + CFStringRef accessGroup = CFSTR("*"); + CFArrayRef accessGroups = CFArrayCreate(kCFAllocatorDefault, (const void **)&accessGroup, 1, &kCFTypeArrayCallBacks); + + CFDictionaryAddValue(attrs, kSecClass, kSecClassInternetPassword); + CFDictionaryAddValue(attrs, kSecAttrAccessGroup, kSecSafariAccessGroup); + CFDictionaryAddValue(attrs, kSecAttrAuthenticationType, kSecAttrAuthenticationTypeHTMLForm); + CFDictionaryAddValue(attrs, kSecAttrProtocol, kSecAttrProtocolHTTPS); + CFDictionaryAddValue(attrs, kSecAttrServer, fqdn); + CFDictionaryAddValue(attrs, kSecAttrSynchronizable, kCFBooleanTrue); + + (void)_SecItemDelete(attrs, accessGroups, &error); + CFReleaseNull(error); + + CFDictionaryAddValue(attrs, kSecAttrAccount, kSecSafariPasswordsNotSaved); + CFDictionaryAddValue(attrs, kSecAttrComment, kSecSafariDefaultComment); + + CFStringRef label = CFStringCreateWithFormat(kCFAllocatorDefault, + NULL, CFSTR("%@ (%@)"), fqdn, kSecSafariPasswordsNotSaved); + if (label) { + CFDictionaryAddValue(attrs, kSecAttrLabel, label); + CFReleaseSafe(label); + } + + UInt8 space = ' '; + CFDataRef data = CFDataCreate(kCFAllocatorDefault, &space, 1); + if (data) { + CFDictionarySetValue(attrs, kSecValueData, data); + CFReleaseSafe(data); + } + + CFTypeRef addResult = NULL; + result = _SecItemAdd(attrs, accessGroups, &addResult, &error); + + CFReleaseSafe(addResult); + CFReleaseSafe(error); + CFReleaseSafe(attrs); + CFReleaseSafe(accessGroups); + + return result; +} + +/* Specialized version of SecItemAdd for shared web credentials */ +bool +_SecAddSharedWebCredential(CFDictionaryRef attributes, + const audit_token_t *clientAuditToken, + CFStringRef appID, + CFArrayRef domains, + CFTypeRef *result, + CFErrorRef *error) { + + CFStringRef fqdn = CFDictionaryGetValue(attributes, kSecAttrServer); + CFStringRef account = CFDictionaryGetValue(attributes, kSecAttrAccount); +#if TARGET_OS_IPHONE + CFStringRef password = CFDictionaryGetValue(attributes, kSecSharedPassword); +#else + CFStringRef password = CFDictionaryGetValue(attributes, CFSTR("spwd")); +#endif + CFStringRef accessGroup = CFSTR("*"); + CFArrayRef accessGroups = NULL; + CFMutableDictionaryRef query = NULL, attrs = NULL; + SInt32 port = -1; + bool ok = false, update = false; + //bool approved = false; + + // check autofill enabled status + if (!swca_autofill_enabled(clientAuditToken)) { + SecError(errSecBadReq, error, CFSTR("Autofill is not enabled in Safari settings")); + goto cleanup; + } + + // parse fqdn with CFURL here, since it could be specified as domain:port + if (fqdn) { + CFRetainSafe(fqdn); + CFStringRef urlStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@%@"), kSecSharedCredentialUrlScheme, fqdn); + if (urlStr) { + CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault, urlStr, nil); + if (url) { + CFStringRef hostname = CFURLCopyHostName(url); + if (hostname) { + CFReleaseSafe(fqdn); + fqdn = hostname; + port = CFURLGetPortNumber(url); + } + CFReleaseSafe(url); + } + CFReleaseSafe(urlStr); + } + } + + if (!account) { + SecError(errSecParam, error, CFSTR("No account provided")); + goto cleanup; + } + if (!fqdn) { + SecError(errSecParam, error, CFSTR("No domain provided")); + goto cleanup; + } + +#if TARGET_IPHONE_SIMULATOR + secerror("app/site association entitlements not checked in Simulator"); +#else + OSStatus status = errSecMissingEntitlement; + // validate that fqdn is part of caller's shared credential domains entitlement + if (!appID) { + SecError(status, error, CFSTR("Missing application-identifier entitlement")); + goto cleanup; + } + if (_SecEntitlementContainsDomainForService(domains, fqdn, kSecSharedWebCredentialsService)) { + status = errSecSuccess; + } + if (errSecSuccess != status) { + CFStringRef msg = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, + CFSTR("%@ not found in %@ entitlement"), fqdn, kSecEntitlementAssociatedDomains); + if (!msg) { + msg = CFRetain(CFSTR("Requested domain not found in entitlement")); + } + SecError(status, error, CFSTR("%@"), msg); + CFReleaseSafe(msg); + goto cleanup; + } +#endif + +#if TARGET_IPHONE_SIMULATOR + secerror("Ignoring app/site approval state in the Simulator."); +#else + // get approval status for this app/domain pair + SWCFlags flags = _SecAppDomainApprovalStatus(appID, fqdn, error); + //approved = ((flags & kSWCFlag_SiteApproved) && (flags & kSWCFlag_UserApproved)); + if (!(flags & kSWCFlag_SiteApproved)) { + goto cleanup; + } +#endif + + // give ourselves access to see matching items for kSecSafariAccessGroup + accessGroups = CFArrayCreate(kCFAllocatorDefault, (const void **)&accessGroup, 1, &kCFTypeArrayCallBacks); + + // create lookup query + query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (!query) { + SecError(errSecAllocate, error, CFSTR("Unable to create query dictionary")); + goto cleanup; + } + CFDictionaryAddValue(query, kSecClass, kSecClassInternetPassword); + CFDictionaryAddValue(query, kSecAttrAccessGroup, kSecSafariAccessGroup); + CFDictionaryAddValue(query, kSecAttrAuthenticationType, kSecAttrAuthenticationTypeHTMLForm); + CFDictionaryAddValue(query, kSecAttrServer, fqdn); + CFDictionaryAddValue(query, kSecAttrSynchronizable, kCFBooleanTrue); + + // check for presence of Safari's negative entry ('passwords not saved') + CFDictionarySetValue(query, kSecAttrAccount, kSecSafariPasswordsNotSaved); + ok = _SecItemCopyMatching(query, accessGroups, result, error); + CFReleaseNull(*result); + CFReleaseNull(*error); + if (ok) { + SecError(errSecDuplicateItem, error, CFSTR("Item already exists for this server")); + goto cleanup; + } + + // now use the provided account (and optional port number, if one was present) + CFDictionarySetValue(query, kSecAttrAccount, account); + if (port < -1 || port > 0) { + SInt16 portValueShort = (port & 0xFFFF); + CFNumberRef portNumber = CFNumberCreate(NULL, kCFNumberSInt16Type, &portValueShort); + CFDictionaryAddValue(query, kSecAttrPort, portNumber); + CFReleaseSafe(portNumber); + } + + // look up existing password + if (_SecItemCopyMatching(query, accessGroups, result, error)) { + // found it, so this becomes either an "update password" or "delete password" operation + CFReleaseNull(*result); + CFReleaseNull(*error); + update = (password != NULL); + if (update) { + attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDataRef credential = CFStringCreateExternalRepresentation(kCFAllocatorDefault, password, kCFStringEncodingUTF8, 0); + CFDictionaryAddValue(attrs, kSecValueData, credential); + CFReleaseSafe(credential); + CFDictionaryAddValue(attrs, kSecAttrComment, kSecSafariDefaultComment); + + // confirm the update + // (per rdar://16676310 we always prompt, even if there was prior user approval) + 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); + } + } + else { + // confirm the delete + // (per rdar://16676288 we always prompt, even if there was prior user approval) + 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); + } + } + if (ok) { + CFReleaseNull(*error); + } + goto cleanup; + } + CFReleaseNull(*result); + CFReleaseNull(*error); + + // password does not exist, so prepare to add it + if (true) { + CFStringRef label = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ (%@)"), fqdn, account); + if (label) { + CFDictionaryAddValue(query, kSecAttrLabel, label); + CFReleaseSafe(label); + } + // NOTE: we always expect to use HTTPS for web forms. + CFDictionaryAddValue(query, kSecAttrProtocol, kSecAttrProtocolHTTPS); + + CFDataRef credential = CFStringCreateExternalRepresentation(kCFAllocatorDefault, password, kCFStringEncodingUTF8, 0); + CFDictionarySetValue(query, kSecValueData, credential); + CFReleaseSafe(credential); + CFDictionarySetValue(query, kSecAttrComment, kSecSafariDefaultComment); + + CFReleaseSafe(accessGroups); + accessGroups = CFArrayCreate(kCFAllocatorDefault, (const void **)&kSecSafariAccessGroup, 1, &kCFTypeArrayCallBacks); + + // mark the item as created by this function + const int32_t creator_value = 'swca'; + CFNumberRef creator = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &creator_value); + if (creator) { + CFDictionarySetValue(query, kSecAttrCreator, creator); + CFReleaseSafe(creator); + ok = true; + } + else { + // confirm the add + // (per rdar://16680019, we won't prompt here in the normal case) + ok = /*approved ||*/ swca_confirm_operation(swca_add_request_id, clientAuditToken, query, error, + ^void (CFStringRef fqdn) { _SecAddNegativeWebCredential(fqdn, appID, false); }); + } + } + if (ok) { + ok = _SecItemAdd(query, accessGroups, result, error); + } + +cleanup: +#if 0 /* debugging */ +{ + const char *op_str = (password) ? ((update) ? "updated" : "added") : "deleted"; + const char *result_str = (ok) ? "true" : "false"; + secerror("result=%s, %s item %@, error=%@", result_str, op_str, *result, *error); +} +#else + (void)update; +#endif + CFReleaseSafe(attrs); + CFReleaseSafe(query); + CFReleaseSafe(accessGroups); + CFReleaseSafe(fqdn); + return ok; +} + +/* Specialized version of SecItemCopyMatching for shared web credentials */ +bool +_SecCopySharedWebCredential(CFDictionaryRef query, + const audit_token_t *clientAuditToken, + CFStringRef appID, + CFArrayRef domains, + CFTypeRef *result, + CFErrorRef *error) { + + CFMutableArrayRef credentials = NULL; + CFMutableArrayRef foundItems = NULL; + CFMutableArrayRef fqdns = NULL; + CFArrayRef accessGroups = NULL; + CFStringRef fqdn = NULL; + CFStringRef account = NULL; + CFIndex idx, count; + SInt32 port = -1; + bool ok = false; + + require_quiet(result, cleanup); + credentials = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + foundItems = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + fqdns = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + + // give ourselves access to see matching items for kSecSafariAccessGroup + CFStringRef accessGroup = CFSTR("*"); + accessGroups = CFArrayCreate(kCFAllocatorDefault, (const void **)&accessGroup, 1, &kCFTypeArrayCallBacks); + + // On input, the query dictionary contains optional fqdn and account entries. + fqdn = CFDictionaryGetValue(query, kSecAttrServer); + account = CFDictionaryGetValue(query, kSecAttrAccount); + + // Check autofill enabled status + if (!swca_autofill_enabled(clientAuditToken)) { + SecError(errSecBadReq, error, CFSTR("Autofill is not enabled in Safari settings")); + goto cleanup; + } + + // Check fqdn; if NULL, add domains from caller's entitlement. + if (fqdn) { + CFArrayAppendValue(fqdns, fqdn); + } + else if (domains) { + CFIndex idx, count = CFArrayGetCount(domains); + for (idx=0; idx < count; idx++) { + CFStringRef str = (CFStringRef) CFArrayGetValueAtIndex(domains, idx); + // Parse the entry for our service label prefix + if (str && CFStringHasPrefix(str, kSecSharedWebCredentialsService)) { + CFIndex prefix_len = CFStringGetLength(kSecSharedWebCredentialsService)+1; + CFIndex substr_len = CFStringGetLength(str) - prefix_len; + CFRange range = { prefix_len, substr_len }; + fqdn = CFStringCreateWithSubstring(kCFAllocatorDefault, str, range); + if (fqdn) { + CFArrayAppendValue(fqdns, fqdn); + CFRelease(fqdn); + } + } + } + } + count = CFArrayGetCount(fqdns); + if (count < 1) { + SecError(errSecParam, error, CFSTR("No domain provided")); + goto cleanup; + } + + // Aggregate search results for each domain + for (idx = 0; idx < count; idx++) { + CFMutableArrayRef items = NULL; + CFMutableDictionaryRef attrs = NULL; + fqdn = (CFStringRef) CFArrayGetValueAtIndex(fqdns, idx); + CFRetainSafe(fqdn); + port = -1; + + // Parse the fqdn for a possible port specifier. + if (fqdn) { + CFStringRef urlStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@%@"), kSecSharedCredentialUrlScheme, fqdn); + if (urlStr) { + CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault, urlStr, nil); + if (url) { + CFStringRef hostname = CFURLCopyHostName(url); + if (hostname) { + CFReleaseSafe(fqdn); + fqdn = hostname; + port = CFURLGetPortNumber(url); + } + CFReleaseSafe(url); + } + CFReleaseSafe(urlStr); + } + } + + #if TARGET_IPHONE_SIMULATOR + secerror("app/site association entitlements not checked in Simulator"); + #else + OSStatus status = errSecMissingEntitlement; + if (!appID) { + SecError(status, error, CFSTR("Missing application-identifier entitlement")); + CFReleaseSafe(fqdn); + goto cleanup; + } + // validate that fqdn is part of caller's entitlement + if (_SecEntitlementContainsDomainForService(domains, fqdn, kSecSharedWebCredentialsService)) { + status = errSecSuccess; + } + if (errSecSuccess != status) { + CFStringRef msg = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, + CFSTR("%@ not found in %@ entitlement"), fqdn, kSecEntitlementAssociatedDomains); + if (!msg) { + msg = CFRetain(CFSTR("Requested domain not found in entitlement")); + } + SecError(status, error, CFSTR("%@"), msg); + CFReleaseSafe(msg); + CFReleaseSafe(fqdn); + goto cleanup; + } + #endif + + attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (!attrs) { + SecError(errSecAllocate, error, CFSTR("Unable to create query dictionary")); + CFReleaseSafe(fqdn); + goto cleanup; + } + CFDictionaryAddValue(attrs, kSecClass, kSecClassInternetPassword); + CFDictionaryAddValue(attrs, kSecAttrAccessGroup, kSecSafariAccessGroup); + CFDictionaryAddValue(attrs, kSecAttrAuthenticationType, kSecAttrAuthenticationTypeHTMLForm); + CFDictionaryAddValue(attrs, kSecAttrServer, fqdn); + if (account) { + CFDictionaryAddValue(attrs, kSecAttrAccount, account); + } + if (port < -1 || port > 0) { + SInt16 portValueShort = (port & 0xFFFF); + CFNumberRef portNumber = CFNumberCreate(NULL, kCFNumberSInt16Type, &portValueShort); + CFDictionaryAddValue(attrs, kSecAttrPort, portNumber); + CFReleaseSafe(portNumber); + } + CFDictionaryAddValue(attrs, kSecAttrSynchronizable, kCFBooleanTrue); + CFDictionaryAddValue(attrs, kSecMatchLimit, kSecMatchLimitAll); + CFDictionaryAddValue(attrs, kSecReturnAttributes, kCFBooleanTrue); + CFDictionaryAddValue(attrs, kSecReturnData, kCFBooleanTrue); + + ok = _SecItemCopyMatching(attrs, accessGroups, (CFTypeRef*)&items, error); + if (count > 1) { + // ignore interim error since we have multiple domains to search + CFReleaseNull(*error); + } + if (ok && items && CFGetTypeID(items) == CFArrayGetTypeID()) { + #if TARGET_IPHONE_SIMULATOR + secerror("Ignoring app/site approval state in the Simulator."); + bool approved = true; + #else + // get approval status for this app/domain pair + SWCFlags flags = _SecAppDomainApprovalStatus(appID, fqdn, error); + if (count > 1) { + // ignore interim error since we have multiple domains to check + CFReleaseNull(*error); + } + bool approved = (flags & kSWCFlag_SiteApproved); + #endif + if (approved) { + CFArrayAppendArray(foundItems, items, CFRangeMake(0, CFArrayGetCount(items))); + } + } + CFReleaseSafe(items); + CFReleaseSafe(attrs); + CFReleaseSafe(fqdn); + } + +// If matching credentials are found, the credentials provided to the completionHandler +// will be a CFArrayRef containing CFDictionaryRef entries. Each dictionary entry will +// contain the following pairs (see Security/SecItem.h): +// key: kSecAttrServer value: CFStringRef (the website) +// key: kSecAttrAccount value: CFStringRef (the account) +// key: kSecSharedPassword value: CFStringRef (the password) +// Optional keys: +// key: kSecAttrPort value: CFNumberRef (the port number, if non-standard for https) + + count = CFArrayGetCount(foundItems); + for (idx = 0; idx < count; idx++) { + CFDictionaryRef dict = (CFDictionaryRef) CFArrayGetValueAtIndex(foundItems, idx); + CFMutableDictionaryRef newdict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (newdict && dict && CFGetTypeID(dict) == CFDictionaryGetTypeID()) { + CFStringRef srvr = CFDictionaryGetValue(dict, kSecAttrServer); + CFStringRef acct = CFDictionaryGetValue(dict, kSecAttrAccount); + CFNumberRef pnum = CFDictionaryGetValue(dict, kSecAttrPort); + CFStringRef icmt = CFDictionaryGetValue(dict, kSecAttrComment); + CFDataRef data = CFDictionaryGetValue(dict, kSecValueData); + if (srvr) { + CFDictionaryAddValue(newdict, kSecAttrServer, srvr); + } + if (acct) { + CFDictionaryAddValue(newdict, kSecAttrAccount, acct); + } + if (pnum) { + SInt16 pval = -1; + if (CFNumberGetValue(pnum, kCFNumberSInt16Type, &pval) && + (pval < -1 || pval > 0)) { + CFDictionaryAddValue(newdict, kSecAttrPort, pnum); + } + } + if (data) { + CFStringRef password = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, data, kCFStringEncodingUTF8); + if (password) { + #if TARGET_OS_IPHONE + CFDictionaryAddValue(newdict, kSecSharedPassword, password); + #else + CFDictionaryAddValue(newdict, CFSTR("spwd"), password); + #endif + CFReleaseSafe(password); + } + } + if (icmt && CFEqual(icmt, kSecSafariDefaultComment)) { + CFArrayInsertValueAtIndex(credentials, 0, newdict); + } else { + CFArrayAppendValue(credentials, newdict); + } + } + CFReleaseSafe(newdict); + } + + if (count) { + + ok = false; + + // create a new array of dictionaries (without the actual password) for picker UI + count = CFArrayGetCount(credentials); + CFMutableArrayRef items = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + for (idx = 0; idx < count; idx++) { + CFDictionaryRef dict = (CFDictionaryRef) CFArrayGetValueAtIndex(credentials, idx); + CFMutableDictionaryRef newdict = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, dict); + #if TARGET_OS_IPHONE + CFDictionaryRemoveValue(newdict, kSecSharedPassword); + #else + CFDictionaryRemoveValue(newdict, CFSTR("spwd")); + #endif + CFArrayAppendValue(items, newdict); + CFReleaseSafe(newdict); + } + + // prompt user to select one of the dictionary items + CFDictionaryRef selected = swca_copy_selected_dictionary(swca_select_request_id, + clientAuditToken, items, error); + if (selected) { + // find the matching item in our credentials array + CFStringRef srvr = CFDictionaryGetValue(selected, kSecAttrServer); + CFStringRef acct = CFDictionaryGetValue(selected, kSecAttrAccount); + CFNumberRef pnum = CFDictionaryGetValue(selected, kSecAttrPort); + for (idx = 0; idx < count; idx++) { + CFDictionaryRef dict = (CFDictionaryRef) CFArrayGetValueAtIndex(credentials, idx); + CFStringRef srvr1 = CFDictionaryGetValue(dict, kSecAttrServer); + CFStringRef acct1 = CFDictionaryGetValue(dict, kSecAttrAccount); + CFNumberRef pnum1 = CFDictionaryGetValue(dict, kSecAttrPort); + + if (!srvr || !srvr1 || !CFEqual(srvr, srvr1)) continue; + if (!acct || !acct1 || !CFEqual(acct, acct1)) continue; + if ((pnum && pnum1) && !CFEqual(pnum, pnum1)) continue; + + // we have a match! + CFReleaseSafe(selected); + CFRetainSafe(dict); + selected = dict; + ok = true; + break; + } + } + CFReleaseSafe(items); + CFArrayRemoveAllValues(credentials); + if (selected && ok) { +#if TARGET_OS_IPHONE + fqdn = CFDictionaryGetValue(selected, kSecAttrServer); +#endif + CFArrayAppendValue(credentials, selected); + } + +#if 0 + // confirm the access + ok = swca_confirm_operation(swca_copy_request_id, clientAuditToken, query, error, + ^void (CFStringRef fqdn) { _SecAddNegativeWebCredential(fqdn, appID, false); }); +#endif + if (ok) { + #if TARGET_OS_IPHONE + // register confirmation with database + CFRetainSafe(appID); + CFRetainSafe(fqdn); + if (0 != SWCSetServiceFlags(kSecSharedWebCredentialsService, + appID, fqdn, kSWCFlag_ExternalMask, kSWCFlag_UserApproved, + ^void(OSStatus inStatus, SWCFlags inNewFlags){ + CFReleaseSafe(appID); + CFReleaseSafe(fqdn); + })) + { + // we didn't queue the block + CFReleaseSafe(appID); + CFReleaseSafe(fqdn); + } + #endif + } + CFReleaseSafe(selected); + } + else if (NULL == *error) { + // found no items, and we haven't already filled in the error + SecError(errSecItemNotFound, error, CFSTR("no matching items found")); + } + +cleanup: + if (!ok) { + CFArrayRemoveAllValues(credentials); + } + CFReleaseSafe(foundItems); + *result = credentials; + CFReleaseSafe(accessGroups); + CFReleaseSafe(fqdns); +#if 0 /* debugging */ + secerror("result=%s, copied items %@, error=%@", (ok) ? "true" : "false", *result, *error); +#endif + return ok; +} + +// MARK: - +// MARK: Keychain backup + +CF_RETURNS_RETAINED CFDataRef +_SecServerKeychainBackup(CFDataRef keybag, CFDataRef passcode, CFErrorRef *error) { + CFDataRef backup; + SecDbConnectionRef dbt = SecDbConnectionAquire(kc_dbhandle(), false, error); + + if (!dbt) + return NULL; + + if (keybag == NULL && passcode == NULL) { +#if USE_KEYSTORE + backup = SecServerExportKeychain(dbt, KEYBAG_DEVICE, backup_keybag_handle, error); +#else /* !USE_KEYSTORE */ + SecError(errSecParam, error, CFSTR("Why are you doing this?")); + backup = NULL; +#endif /* USE_KEYSTORE */ + } else { + backup = SecServerKeychainBackup(dbt, keybag, passcode, error); + } + + SecDbConnectionRelease(dbt); + + return backup; +} + +bool +_SecServerKeychainRestore(CFDataRef backup, 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); + }); + + if (ok) { + SecKeychainChanged(true); + } + + return ok; +} + +// MARK: - +// MARK: SecItemDataSource + +// Make sure to call this before any writes to the keychain, so that we fire +// up the engines to monitor manifest changes. +SOSDataSourceFactoryRef SecItemDataSourceFactoryGetDefault(void) { + return SecItemDataSourceFactoryGetShared(kc_dbhandle()); + } + +/* AUDIT[securityd]: + args_in (ok) is a caller provided, CFDictionaryRef. + */ + +CF_RETURNS_RETAINED CFArrayRef +_SecServerKeychainSyncUpdateKeyParameter(CFDictionaryRef updates, CFErrorRef *error) { + // This never fails, trust us! + return SOSCCHandleUpdateKeyParameter(updates); +} + + +CF_RETURNS_RETAINED CFArrayRef +_SecServerKeychainSyncUpdateCircle(CFDictionaryRef updates, CFErrorRef *error) { + // This never fails, trust us! + return SOSCCHandleUpdateCircle(updates); +} + +CF_RETURNS_RETAINED CFArrayRef +_SecServerKeychainSyncUpdateMessage(CFDictionaryRef updates, CFErrorRef *error) { + // This never fails, trust us! + return SOSCCHandleUpdateMessage(updates); +} + + +// +// Truthiness in the cloud backup/restore support. +// + +static CFDictionaryRef +_SecServerCopyTruthInTheCloud(CFDataRef keybag, CFDataRef password, + CFDictionaryRef backup, CFErrorRef *error) +{ + SOSManifestRef mold = NULL, mnow = NULL, mdelete = NULL, madd = NULL; + __block CFMutableDictionaryRef backup_new = NULL; + keybag_handle_t bag_handle; + if (!ks_open_keybag(keybag, password, &bag_handle, error)) + return backup_new; + + // We need to have a datasource singleton for protection domain + // kSecAttrAccessibleWhenUnlocked and keep a single shared engine + // instance around which we create in the datasource constructor as well. + SOSDataSourceFactoryRef dsf = SecItemDataSourceFactoryGetDefault(); + SOSDataSourceRef ds = dsf->create_datasource(dsf, kSecAttrAccessibleWhenUnlocked, error); + if (ds) { + backup_new = backup ? CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, backup) : CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + mold = SOSCreateManifestWithBackup(backup, error); + SOSEngineRef engine = SOSDataSourceGetSharedEngine(ds, error); + mnow = SOSEngineCopyManifest(engine, error); + if (!mnow) { + mnow = SOSDataSourceCopyManifest(ds, error); + } + if (!mnow) { + CFReleaseNull(backup_new); + secerror("failed to obtain manifest for keychain: %@", error ? *error : NULL); + } else { + SOSManifestDiff(mold, mnow, &mdelete, &madd, error); + } + + // Delete everything from the new_backup that is no longer in the datasource according to the datasources manifest. + SOSManifestForEach(mdelete, ^(CFDataRef digest_data, bool *stop) { + CFStringRef deleted_item_key = CFDataCopyHexString(digest_data); + CFDictionaryRemoveValue(backup_new, deleted_item_key); + CFRelease(deleted_item_key); + }); + + __block struct SOSDigestVector dvdel = SOSDigestVectorInit; + SOSDataSourceForEachObject(ds, madd, error, ^void(CFDataRef digest, SOSObjectRef object, bool *stop) { + CFErrorRef localError = NULL; + CFDataRef digest_data = NULL; + CFTypeRef value = NULL; + if (!object) { + // Key in our manifest can't be found in db, remove it from our manifest + SOSDigestVectorAppend(&dvdel, CFDataGetBytePtr(digest)); + } else if (!(digest_data = SOSObjectCopyDigest(ds, object, &localError)) + || !(value = SOSObjectCopyBackup(ds, object, bag_handle, &localError))) { + if (SecErrorGetOSStatus(localError) == errSecDecode) { + // Ignore decode errors, pretend the objects aren't there + CFRelease(localError); + // Object undecodable, remove it from our manifest + SOSDigestVectorAppend(&dvdel, CFDataGetBytePtr(digest)); + } else { + // Stop iterating and propagate out all other errors. + *stop = true; + *error = localError; + CFReleaseNull(backup_new); + } + } else { + // TODO: Should we skip tombstones here? + CFStringRef key = CFDataCopyHexString(digest_data); + CFDictionarySetValue(backup_new, key, value); + CFReleaseSafe(key); + } + CFReleaseSafe(digest_data); + CFReleaseSafe(value); + }) || CFReleaseNull(backup_new); + + if (dvdel.count) { + struct SOSDigestVector dvadd = SOSDigestVectorInit; + if (!SOSEngineUpdateLocalManifest(engine, kSOSDataSourceSOSTransaction, &dvdel, &dvadd, error)) { + CFReleaseNull(backup_new); + } + SOSDigestVectorFree(&dvdel); + } + + SOSDataSourceRelease(ds, error) || CFReleaseNull(backup_new); + } + + CFReleaseSafe(mold); + CFReleaseSafe(mnow); + CFReleaseSafe(madd); + CFReleaseSafe(mdelete); + ks_close_keybag(bag_handle, error) || CFReleaseNull(backup_new); + + return backup_new; +} + +static bool +_SecServerRestoreTruthInTheCloud(CFDataRef keybag, CFDataRef password, CFDictionaryRef backup_in, CFErrorRef *error) { + __block bool ok = true; + keybag_handle_t bag_handle; + if (!ks_open_keybag(keybag, password, &bag_handle, error)) + return false; + + SOSManifestRef mbackup = SOSCreateManifestWithBackup(backup_in, error); + if (mbackup) { + SOSDataSourceFactoryRef dsf = SecItemDataSourceFactoryGetDefault(); + SOSDataSourceRef ds = dsf->create_datasource(dsf, kSecAttrAccessibleWhenUnlocked, error); + if (ds) { + ok = SOSDataSourceWith(ds, error, ^(SOSTransactionRef txn, bool *commit) { + SOSManifestRef mnow = SOSDataSourceCopyManifest(ds, error); + SOSManifestRef mdelete = NULL, madd = NULL; + SOSManifestDiff(mnow, mbackup, &mdelete, &madd, error); + + // Don't delete everything in datasource not in backup. + + // Add items from the backup + SOSManifestForEach(madd, ^void(CFDataRef e, bool *stop) { + CFDictionaryRef item = NULL; + CFStringRef sha1 = CFDataCopyHexString(e); + if (sha1) { + item = CFDictionaryGetValue(backup_in, sha1); + CFRelease(sha1); + } + if (item) { + CFErrorRef localError = NULL; + + if (!SOSObjectRestoreObject(ds, txn, bag_handle, item, &localError)) { + OSStatus status = SecErrorGetOSStatus(localError); + if (status == errSecDuplicateItem) { + // Log and ignore duplicate item errors during restore + secnotice("titc", "restore %@ not replacing existing item", item); + } else { + if (status == errSecInteractionNotAllowed) + *stop = true; + // Propagate the first other error upwards (causing the restore to fail). + secerror("restore %@ failed %@", item, localError); + ok = false; + if (error && !*error) { + *error = localError; + localError = NULL; + } + } + CFReleaseSafe(localError); + } + } + }); + ok &= SOSDataSourceRelease(ds, error); + CFReleaseNull(mdelete); + CFReleaseNull(madd); + CFReleaseNull(mnow); + }); + } else { + ok = false; + } + CFRelease(mbackup); + } + + ok &= ks_close_keybag(bag_handle, error); + + return ok; +} + + +CF_RETURNS_RETAINED CFDictionaryRef +_SecServerBackupSyncable(CFDictionaryRef backup, CFDataRef keybag, CFDataRef password, CFErrorRef *error) { + require_action_quiet(isData(keybag), errOut, SecError(errSecParam, error, CFSTR("keybag %@ not a data"), keybag)); + require_action_quiet(!backup || isDictionary(backup), errOut, SecError(errSecParam, error, CFSTR("backup %@ not a dictionary"), backup)); + require_action_quiet(!password || isData(password), errOut, SecError(errSecParam, error, CFSTR("password %@ not a data"), password)); + + return _SecServerCopyTruthInTheCloud(keybag, password, backup, error); + +errOut: + return NULL; +} + +bool +_SecServerRestoreSyncable(CFDictionaryRef backup, CFDataRef keybag, CFDataRef password, CFErrorRef *error) { + bool ok; + 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"))); + } + + ok = _SecServerRestoreTruthInTheCloud(keybag, password, backup, error); + +errOut: + return ok; +} + +bool _SecServerRollKeys(bool force, CFErrorRef *error) { +#if USE_KEYSTORE + uint32_t keystore_generation_status = 0; + if (aks_generation(KEYBAG_DEVICE, generation_noop, &keystore_generation_status)) + return false; + uint32_t current_generation = keystore_generation_status & generation_current; + + return kc_with_dbt(true, error, ^(SecDbConnectionRef dbt) { + 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); + if (up_to_date) { + secerror("Completed roll keys."); + up_to_date = s3dl_dbt_keys_current(dbt, current_generation, NULL); + } + if (!up_to_date) + secerror("Failed to roll keys."); + } + return up_to_date; + }); +#else + return true; +#endif +} diff --git a/Security/sec/securityd/SecItemServer.h b/Security/sec/securityd/SecItemServer.h new file mode 100644 index 00000000..23d493b1 --- /dev/null +++ b/Security/sec/securityd/SecItemServer.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2007-2009,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@ + */ + +/*! + @header SecItemServer + The functions provided in SecItemServer.h provide an interface to + the backend for SecItem APIs in the server. +*/ + +#ifndef _SECURITYD_SECITEMSERVER_H_ +#define _SECURITYD_SECITEMSERVER_H_ + +#include +#include +#include +#include + +__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 _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); +CF_RETURNS_RETAINED CFArrayRef _SecServerKeychainSyncUpdateKeyParameter(CFDictionaryRef updates, CFErrorRef *error); +CF_RETURNS_RETAINED CFArrayRef _SecServerKeychainSyncUpdateCircle(CFDictionaryRef updates, CFErrorRef *error); +CF_RETURNS_RETAINED CFArrayRef _SecServerKeychainSyncUpdateMessage(CFDictionaryRef updates, CFErrorRef *error); +CF_RETURNS_RETAINED CFDictionaryRef _SecServerBackupSyncable(CFDictionaryRef backup, CFDataRef keybag, CFDataRef password, CFErrorRef *error); + +bool _SecServerRestoreSyncable(CFDictionaryRef backup, CFDataRef keybag, CFDataRef password, CFErrorRef *error); + +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); + +// Hack to log objects from inside SOS code +void SecItemServerAppendItemDescription(CFMutableStringRef desc, CFDictionaryRef object); + +SecDbRef SecKeychainDbCreate(CFStringRef path); + +SOSDataSourceFactoryRef SecItemDataSourceFactoryGetDefault(void); + +/* FIXME: there is a specific type for keybag handle (keybag_handle_t) + but it's not defined for simulator so we just use an int32_t */ +void SecItemServerSetKeychainKeybag(int32_t keybag); +void SecItemServerResetKeychainKeybag(void); + +void SecItemServerSetKeychainChangedNotification(const char *notification_name); + +CFStringRef __SecKeychainCopyPath(void); + +bool _SecServerRollKeys(bool force, CFErrorRef *error); + + +// Should all be blocks called from SecItemDb +bool match_item(SecDbConnectionRef dbt, Query *q, CFArrayRef accessGroups, CFDictionaryRef item); +bool itemInAccessGroup(CFDictionaryRef item, CFArrayRef accessGroups); +void SecKeychainChanged(bool syncWithPeers); + +__END_DECLS + +#endif /* _SECURITYD_SECITEMSERVER_H_ */ diff --git a/Security/sec/securityd/SecKeybagSupport.c b/Security/sec/securityd/SecKeybagSupport.c new file mode 100644 index 00000000..d285c587 --- /dev/null +++ b/Security/sec/securityd/SecKeybagSupport.c @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + */ + +/* + * SecKeybagSupport.c - CoreFoundation-based constants and functions for + access to Security items (certificates, keys, identities, and + passwords.) + */ + +#include + +#include + +#if USE_KEYSTORE +#include +#include +#include +#include +#include +#if TARGET_OS_EMBEDDED +#include +#endif +#endif /* USE_KEYSTORE */ + + +/* 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 */ +#if USE_KEYSTORE +#if TARGET_OS_MAC && !TARGET_OS_EMBEDDED +keybag_handle_t g_keychain_keybag = session_keybag_handle; +#else +keybag_handle_t g_keychain_keybag = device_keybag_handle; +#endif +#else /* !USE_KEYSTORE */ +keybag_handle_t g_keychain_keybag = 0; /* 0 == device_keybag_handle, constant dictated by AKS */ +#endif /* USE_KEYSTORE */ + +void SecItemServerSetKeychainKeybag(int32_t keybag) +{ + g_keychain_keybag=keybag; +} + +void SecItemServerResetKeychainKeybag(void) +{ +#if USE_KEYSTORE +#if TARGET_OS_MAC && !TARGET_OS_EMBEDDED + g_keychain_keybag = session_keybag_handle; +#else + g_keychain_keybag = device_keybag_handle; +#endif +#else /* !USE_KEYSTORE */ + g_keychain_keybag = 0; /* 0 == device_keybag_handle, constant dictated by AKS */ +#endif /* USE_KEYSTORE */ +} + +#if USE_KEYSTORE + +static bool hwaes_key_available(void) +{ + keybag_handle_t handle = bad_keybag_handle; + keybag_handle_t special_handle = bad_keybag_handle; +#if TARGET_OS_MAC && !TARGET_OS_EMBEDDED + special_handle = session_keybag_handle; +#elif TARGET_OS_EMBEDDED + special_handle = device_keybag_handle; +#endif + kern_return_t kr = aks_get_system(special_handle, &handle); + if (kr != kIOReturnSuccess) { +#if TARGET_OS_EMBEDDED + /* TODO: Remove this once the kext runs the daemon on demand if + there is no system keybag. */ + int kb_state = MKBGetDeviceLockState(NULL); + asl_log(NULL, NULL, ASL_LEVEL_INFO, "AppleKeyStore lock state: %d", kb_state); +#endif + } + return true; +} + +#else /* !USE_KEYSTORE */ + +static bool hwaes_key_available(void) +{ + return false; +} + +#endif /* USE_KEYSTORE */ + +/* Wrap takes a 128 - 256 bit key as input and returns output of + inputsize + 64 bits. + In bytes this means that a + 16 byte (128 bit) key returns a 24 byte wrapped key + 24 byte (192 bit) key returns a 32 byte wrapped key + 32 byte (256 bit) key returns a 40 byte wrapped key */ +bool ks_crypt(uint32_t operation, keybag_handle_t keybag, + keyclass_t keyclass, uint32_t textLength, const uint8_t *source, keyclass_t *actual_class, CFMutableDataRef dest, CFErrorRef *error) { +#if USE_KEYSTORE + kern_return_t kernResult = kIOReturnBadArgument; + + int dest_len = (int)CFDataGetLength(dest); + if (operation == kSecKsWrap) { + kernResult = aks_wrap_key(source, textLength, keyclass, keybag, CFDataGetMutableBytePtr(dest), &dest_len, actual_class); + } else if (operation == kSecKsUnwrap) { + kernResult = aks_unwrap_key(source, textLength, keyclass, keybag, CFDataGetMutableBytePtr(dest), &dest_len); + } + + if (kernResult != KERN_SUCCESS) { + if ((kernResult == kIOReturnNotPermitted) || (kernResult == kIOReturnNotPrivileged)) { + /* Access to item attempted while keychain is locked. */ + return SecError(errSecInteractionNotAllowed, error, CFSTR("ks_crypt: %x failed to %s item (class %"PRId32", bag: %"PRId32") Access to item attempted while keychain is locked."), + kernResult, (operation == kSecKsWrap ? "wrap" : "unwrap"), keyclass, keybag); + } else if (kernResult == kIOReturnError) { + /* Item can't be decrypted on this device, ever, so drop the item. */ + return SecError(errSecDecode, error, CFSTR("ks_crypt: %x failed to %s item (class %"PRId32", bag: %"PRId32") Item can't be decrypted on this device, ever, so drop the item."), + kernResult, (operation == kSecKsWrap ? "wrap" : "unwrap"), keyclass, keybag); + } else { + return SecError(errSecNotAvailable, error, CFSTR("ks_crypt: %x failed to %s item (class %"PRId32", bag: %"PRId32")"), + kernResult, (operation == kSecKsWrap ? "wrap" : "unwrap"), keyclass, keybag); + } + } + else + CFDataSetLength(dest, dest_len); + return true; +#else /* !USE_KEYSTORE */ + uint32_t dest_len = (uint32_t)CFDataGetLength(dest); + if (operation == kSecKsWrap) { + /* The no encryption case. */ + if (dest_len >= textLength + 8) { + memcpy(CFDataGetMutableBytePtr(dest), source, textLength); + memset(CFDataGetMutableBytePtr(dest) + textLength, 8, 8); + CFDataSetLength(dest, textLength + 8); + *actual_class = keyclass; + } else + return SecError(errSecNotAvailable, error, CFSTR("ks_crypt: failed to wrap item (class %"PRId32")"), keyclass); + } else if (operation == kSecKsUnwrap) { + if (dest_len + 8 >= textLength) { + memcpy(CFDataGetMutableBytePtr(dest), source, textLength - 8); + CFDataSetLength(dest, textLength - 8); + } else + return SecError(errSecNotAvailable, error, CFSTR("ks_crypt: failed to unwrap item (class %"PRId32")"), keyclass); + } + return true; +#endif /* USE_KEYSTORE */ +} + +#if USE_KEYSTORE +bool ks_crypt_acl(uint32_t operation, keybag_handle_t keybag, keyclass_t keyclass, + uint32_t textLength, const uint8_t *source, CFMutableDataRef dest, + CFDataRef acl, CFDataRef acm_context, CFDataRef caller_access_groups, CFErrorRef *error) { + kern_return_t kernResult = kIOReturnBadArgument; + uint8_t *params = NULL, *der = NULL; + const uint8_t *access_groups = caller_access_groups?CFDataGetBytePtr(caller_access_groups):NULL; + size_t params_len = 0, der_len = 0, access_groups_len = caller_access_groups?CFDataGetLength(caller_access_groups):0; + + if (operation == kSecKsWrap) { + aks_operation_optional_params(0, 0, CFDataGetBytePtr(acl), CFDataGetLength(acl), 0, 0, (void**)¶ms, ¶ms_len); + kernResult = aks_encrypt(keybag, keyclass, source, textLength, params, params_len, (void**)&der, &der_len); + } else if (operation == kSecKsUnwrap) { + aks_operation_optional_params(access_groups, access_groups_len, 0, 0, CFDataGetBytePtr(acm_context), (int)CFDataGetLength(acm_context), (void**)¶ms, ¶ms_len); + kernResult = aks_decrypt(keybag, source, textLength, params, params_len, (void**)&der, &der_len); + } else if (operation == kSecKsDelete) { + aks_operation_optional_params(access_groups, access_groups_len, 0, 0, CFDataGetBytePtr(acm_context), (int)CFDataGetLength(acm_context), (void**)¶ms, ¶ms_len); + kernResult = aks_delete(keybag, source, textLength, params, params_len); + } + + bool result = false; + if (kernResult != KERN_SUCCESS) { + if ((kernResult == kIOReturnNotPermitted) || (kernResult == kIOReturnNotPrivileged)) { + /* Access to item attempted while keychain is locked. */ + result = SecError(errSecInteractionNotAllowed, error, CFSTR("ks_crypt_acl: %x failed to %s item (class %"PRId32", bag: %"PRId32") Access to item attempted while keychain is locked."), + kernResult, (operation == kSecKsWrap ? "wrap" : "unwrap"), keyclass, keybag); + } else if (kernResult == kIOReturnError) { + /* Item can't be decrypted on this device, ever, so drop the item. */ + result = SecError(errSecDecode, error, CFSTR("ks_crypt_acl: %x failed to %s item (class %"PRId32", bag: %"PRId32") Item can't be decrypted on this device, ever, so drop the item."), + kernResult, (operation == kSecKsWrap ? "wrap" : "unwrap"), keyclass, keybag); + } else { + result = SecError(errSecNotAvailable, error, CFSTR("ks_crypt_acl: %x failed to %s item (class %"PRId32", bag: %"PRId32")"), + kernResult, (operation == kSecKsWrap ? "wrap" : "unwrap"), keyclass, keybag); + } + } + else { + if (operation != kSecKsDelete) { + const uint8_t *value = der; + if (operation == kSecKsUnwrap) { + ccder_tag der_tag; + size_t der_tag_len; + value = ccder_decode_tag(&der_tag, der, der + der_len); + value = ccder_decode_len(&der_tag_len, value, der + der_len); + + require_action(der_tag == CCDER_OCTET_STRING, out, + SecError(errSecDecode, error, CFSTR("ks_crypt_acl: %x failed to %s item (class %"PRId32", bag: %"PRId32") Item can't be decrypted due to invalid der tag, so drop the item."), + kernResult, (operation == kSecKsWrap ? "wrap" : "unwrap"), keyclass, keybag)); + require_action(der_tag_len == (size_t)((der + der_len) - value), out, + SecError(errSecDecode, error, CFSTR("ks_crypt_acl: %x failed to %s item (class %"PRId32", bag: %"PRId32") Item can't be decrypted due to invalid der tag length, so drop the item."), + kernResult, (operation == kSecKsWrap ? "wrap" : "unwrap"), keyclass, keybag)); + } + + if(CFDataGetLength(dest) != (der + der_len) - value) + CFDataSetLength(dest, (der + der_len) - value); + + memcpy(CFDataGetMutableBytePtr(dest), value, CFDataGetLength(dest)); + } + result = true; + } + +out: + if(params) + free(params); + if(der) + free(der); + return result; +} +#endif + +bool use_hwaes(void) { + static bool use_hwaes; + static dispatch_once_t check_once; + dispatch_once(&check_once, ^{ + use_hwaes = hwaes_key_available(); + if (use_hwaes) { + asl_log(NULL, NULL, ASL_LEVEL_INFO, "using hwaes key"); + } else { + asl_log(NULL, NULL, ASL_LEVEL_ERR, "unable to access hwaes key"); + } + }); + return use_hwaes; +} + +bool ks_open_keybag(CFDataRef keybag, CFDataRef password, keybag_handle_t *handle, CFErrorRef *error) { +#if USE_KEYSTORE + kern_return_t kernResult; + kernResult = aks_load_bag(CFDataGetBytePtr(keybag), (int)CFDataGetLength(keybag), handle); + if (kernResult) + return SecKernError(kernResult, error, CFSTR("aks_load_bag failed: %@"), keybag); + + if (password) { + kernResult = aks_unlock_bag(*handle, CFDataGetBytePtr(password), (int)CFDataGetLength(password)); + if (kernResult) { + aks_unload_bag(*handle); + return SecKernError(kernResult, error, CFSTR("aks_unlock_bag failed")); + } + } + return true; +#else /* !USE_KEYSTORE */ + *handle = KEYBAG_NONE; + return true; +#endif /* USE_KEYSTORE */ +} + +bool ks_close_keybag(keybag_handle_t keybag, CFErrorRef *error) { +#if USE_KEYSTORE + IOReturn kernResult = aks_unload_bag(keybag); + if (kernResult) { + return SecKernError(kernResult, error, CFSTR("aks_unload_bag failed")); + } +#endif /* USE_KEYSTORE */ + return true; +} diff --git a/Security/sec/securityd/SecKeybagSupport.h b/Security/sec/securityd/SecKeybagSupport.h new file mode 100644 index 00000000..1dece9c5 --- /dev/null +++ b/Security/sec/securityd/SecKeybagSupport.h @@ -0,0 +1,97 @@ +/* + * 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@ + */ + +/*! + @header SecKeybagSupport.h - The thing that does the stuff with the gibli. + */ + +#ifndef _SECURITYD_SECKEYBAGSUPPORT_H_ +#define _SECURITYD_SECKEYBAGSUPPORT_H_ + +#include +#include + +#if TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_IPHONE_SIMULATOR) +#define USE_KEYSTORE 1 +#elif TARGET_OS_EMBEDDED && !TARGET_IPHONE_SIMULATOR +#define USE_KEYSTORE 1 +#else /* no keystore on this platform */ +#define USE_KEYSTORE 0 +#endif + +#if USE_KEYSTORE +#include +#endif /* USE_KEYSTORE */ + +__BEGIN_DECLS + +// TODO: Get this out of this file +#if USE_KEYSTORE +typedef int32_t keyclass_t; +#else + +/* TODO: this needs to be available in the sim! */ +typedef int32_t keyclass_t; +typedef int32_t key_handle_t; +enum key_classes { + key_class_ak = 6, + key_class_ck, + key_class_dk, + key_class_aku, + key_class_cku, + key_class_dku, + key_class_akpu +}; +#endif /* !USE_KEYSTORE */ + +enum SecKsCryptoOp { + kSecKsWrap = 10, + kSecKsUnwrap, + kSecKsDelete +}; + + +/* KEYBAG_NONE is private to security and have special meaning. + They should not collide with AppleKeyStore constants, but are only referenced + in here. + */ +#define KEYBAG_NONE (-1) /* Set q_keybag to KEYBAG_NONE to obtain cleartext data. */ +#define KEYBAG_DEVICE (g_keychain_keybag) /* actual keybag used to encrypt items */ +extern keybag_handle_t g_keychain_keybag; + +bool use_hwaes(void); +bool ks_crypt(uint32_t operation, keybag_handle_t keybag, + keyclass_t keyclass, uint32_t textLength, const uint8_t *source, keyclass_t *actual_class, + CFMutableDataRef dest, CFErrorRef *error); +#if USE_KEYSTORE +bool ks_crypt_acl(uint32_t operation, keybag_handle_t keybag, + keyclass_t keyclass, uint32_t textLength, const uint8_t *source, + CFMutableDataRef dest, CFDataRef acl, CFDataRef acm_context, CFDataRef caller_access_groups, + CFErrorRef *error); +#endif +bool ks_open_keybag(CFDataRef keybag, CFDataRef password, keybag_handle_t *handle, CFErrorRef *error); +bool ks_close_keybag(keybag_handle_t keybag, CFErrorRef *error); + +__END_DECLS + +#endif /* _SECURITYD_SECKEYBAGSUPPORT_H_ */ diff --git a/Security/sec/securityd/SecLogSettingsServer.c b/Security/sec/securityd/SecLogSettingsServer.c new file mode 100644 index 00000000..b0a3fbfa --- /dev/null +++ b/Security/sec/securityd/SecLogSettingsServer.c @@ -0,0 +1,35 @@ +// +// SecLogSettingsServer.c +// sec +// +// + +#include +#include +#include +#include +#include +#include + +CFPropertyListRef +SecCopyLogSettings_Server(CFErrorRef* error) +{ + return CopyCurrentScopePlist(); +} + +bool +SecSetXPCLogSettings_Server(CFTypeRef type, CFErrorRef* error) +{ + bool success = false; + if (isString(type)) { + ApplyScopeListForID(type, kScopeIDXPC); + success = true; + } else if (isDictionary(type)) { + ApplyScopeDictionaryForID(type, kScopeIDXPC); + success = true; + } else { + success = SecError(errSecParam, error, CFSTR("Unsupported CFType")); + } + + return success; +} diff --git a/Security/sec/securityd/SecLogSettingsServer.h b/Security/sec/securityd/SecLogSettingsServer.h new file mode 100644 index 00000000..e314011b --- /dev/null +++ b/Security/sec/securityd/SecLogSettingsServer.h @@ -0,0 +1,19 @@ +// +// SecLogSettingsServer.h +// sec +// +// + +#ifndef _SECURITY_SECLOGSETTINGSSERVER_H_ +#define _SECURITY_SECLOGSETTINGSSERVER_H_ + +#include + +__BEGIN_DECLS + +CFPropertyListRef SecCopyLogSettings_Server(CFErrorRef* error); +bool SecSetXPCLogSettings_Server(CFTypeRef type, CFErrorRef* error); + +__END_DECLS + +#endif diff --git a/sec/securityd/SecOCSPCache.c b/Security/sec/securityd/SecOCSPCache.c similarity index 98% rename from sec/securityd/SecOCSPCache.c rename to Security/sec/securityd/SecOCSPCache.c index 1ae99dbe..8d415fa5 100644 --- a/sec/securityd/SecOCSPCache.c +++ b/Security/sec/securityd/SecOCSPCache.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2009-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2009-2010,2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -42,8 +42,6 @@ #include "utilities/iOSforOSX.h" #define expireSQL CFSTR("DELETE FROM responses WHERE expires + +#include +#include +#include #include #include #include -#include -#include #include #include #include #include -#include -#include #include #include "SecInternal.h" +#include -#define ocspdErrorLog(args...) asl_log(NULL, NULL, ASL_LEVEL_ERR, ## args) +#define ocspdErrorLog(args, ...) secerror(args, ## __VA_ARGS__) #define ocspdHttpDebug(args...) secdebug("ocspdHttp", ## args) #define ocspdDebug(args...) secdebug("ocsp", ## args) @@ -183,12 +184,14 @@ errOut: static bool SecOCSPResponseCalculateValidity(SecOCSPResponseRef this, CFTimeInterval maxAge, CFTimeInterval defaultTTL) { + bool ok = false; this->latestNextUpdate = NULL_TIME; CFAbsoluteTime now = this->verifyTime = CFAbsoluteTimeGetCurrent(); + CFStringRef hexResp = CFDataCopyHexString(this->data); if (this->producedAt > now + LEEWAY) { - ocspdErrorLog("OCSPResponse: producedAt more than 1:15 from now"); - return false; + ocspdErrorLog("OCSPResponse: producedAt more than 1:15 from now %@", hexResp); + goto exit; } /* Make this->latestNextUpdate be the date farthest in the future @@ -200,8 +203,8 @@ static bool SecOCSPResponseCalculateValidity(SecOCSPResponseRef this, /* thisUpdate later than 'now' invalidates the whole response. */ CFAbsoluteTime thisUpdate = genTimeToCFAbsTime(&resp->thisUpdate); if (thisUpdate > now + LEEWAY) { - ocspdErrorLog("OCSPResponse: thisUpdate more than 1:15 from now"); - return false; + ocspdErrorLog("OCSPResponse: thisUpdate more than 1:15 from now %@", hexResp); + goto exit; } /* Keep track of latest nextUpdate. */ @@ -211,17 +214,17 @@ static bool SecOCSPResponseCalculateValidity(SecOCSPResponseRef this, this->latestNextUpdate = nextUpdate; } } -#ifdef STRICT_RFC5019 else { /* RFC 5019 section 2.2.4 states on nextUpdate: Responders MUST always include this value to aid in response caching. See Section 6 for additional information on caching. */ - ocspdErrorLog("OCSPResponse: nextUpdate not present"); - return false; - } + ocspdErrorLog("OCSPResponse: nextUpdate not present %@", hexResp); +#ifdef STRICT_RFC5019 + goto exit; #endif + } } /* Now that we have this->latestNextUpdate, we figure out the latest @@ -261,8 +264,8 @@ static bool SecOCSPResponseCalculateValidity(SecOCSPResponseRef this, /* Absolute expire time = current time plus defaultTTL */ this->expireTime = now + defaultTTL; } else if (this->latestNextUpdate < now - LEEWAY) { - ocspdErrorLog("OCSPResponse: latestNextUpdate more than 1:15 ago"); - return false; + ocspdErrorLog("OCSPResponse: latestNextUpdate more than 1:15 ago %@", hexResp); + goto exit; } else if (maxAge > 0) { /* Beware of double overflows such as: @@ -278,7 +281,7 @@ static bool SecOCSPResponseCalculateValidity(SecOCSPResponseRef this, /* maxAge http header attempting to make us cache the response longer than it's valid for, bad http header! Ignoring you. */ ocspdErrorLog("OCSPResponse: now + maxAge > latestNextUpdate," - " using latestNextUpdate"); + " using latestNextUpdate %@", hexResp); this->expireTime = this->latestNextUpdate; } } else { @@ -286,11 +289,15 @@ static bool SecOCSPResponseCalculateValidity(SecOCSPResponseRef this, this->expireTime = this->latestNextUpdate; } - return true; + ok = true; +exit: + CFReleaseSafe(hexResp); + return ok; } SecOCSPResponseRef SecOCSPResponseCreate(CFDataRef ocspResponse, CFTimeInterval maxAge) { + CFStringRef hexResp = CFDataCopyHexString(ocspResponse); SecAsn1OCSPResponse topResp = {}; SecOCSPResponseRef this; @@ -306,29 +313,29 @@ SecOCSPResponseRef SecOCSPResponseCreate(CFDataRef ocspResponse, resp.Data = (uint8_t *)CFDataGetBytePtr(ocspResponse); if (SecAsn1DecodeData(this->coder, &resp, kSecAsn1OCSPResponseTemplate, &topResp)) { - ocspdErrorLog("OCSPResponse: decode failure at top level"); + ocspdErrorLog("OCSPResponse: decode failure at top level %@", hexResp); } /* remainder is valid only on RS_Success */ if ((topResp.responseStatus.Data == NULL) || (topResp.responseStatus.Length == 0)) { - ocspdErrorLog("OCSPResponse: no responseStatus"); + ocspdErrorLog("OCSPResponse: no responseStatus %@", hexResp); goto errOut; } this->responseStatus = topResp.responseStatus.Data[0]; if (this->responseStatus != kSecOCSPSuccess) { - secdebug("ocsp", "OCSPResponse: status: %d", this->responseStatus); + secdebug("ocsp", "OCSPResponse: status: %d %@", this->responseStatus, hexResp); /* not a failure of our constructor; this object is now useful, but * only for this one byte of status info */ - return this; + goto fini; } if (topResp.responseBytes == NULL) { /* I don't see how this can be legal on RS_Success */ - ocspdErrorLog("OCSPResponse: empty responseBytes"); + ocspdErrorLog("OCSPResponse: empty responseBytes %@", hexResp); goto errOut; } if (!SecAsn1OidCompare(&topResp.responseBytes->responseType, &OID_PKIX_OCSP_BASIC)) { - ocspdErrorLog("OCSPResponse: unknown responseType"); + ocspdErrorLog("OCSPResponse: unknown responseType %@", hexResp); goto errOut; } @@ -336,7 +343,7 @@ SecOCSPResponseRef SecOCSPResponseCreate(CFDataRef ocspResponse, /* decode the SecAsn1OCSPBasicResponse */ if (SecAsn1DecodeData(this->coder, &topResp.responseBytes->response, kSecAsn1OCSPBasicResponseTemplate, &this->basicResponse)) { - ocspdErrorLog("OCSPResponse: decode failure at SecAsn1OCSPBasicResponse"); + ocspdErrorLog("OCSPResponse: decode failure at SecAsn1OCSPBasicResponse %@", hexResp); goto errOut; } @@ -345,17 +352,17 @@ SecOCSPResponseRef SecOCSPResponseCreate(CFDataRef ocspResponse, /* decode the SecAsn1OCSPResponseData */ if (SecAsn1DecodeData(this->coder, &this->basicResponse.tbsResponseData, kSecAsn1OCSPResponseDataTemplate, &this->responseData)) { - ocspdErrorLog("OCSPResponse: decode failure at SecAsn1OCSPResponseData"); + ocspdErrorLog("OCSPResponse: decode failure at SecAsn1OCSPResponseData %@", hexResp); goto errOut; } this->producedAt = genTimeToCFAbsTime(&this->responseData.producedAt); if (this->producedAt == NULL_TIME) { - ocspdErrorLog("OCSPResponse: bad producedAt"); + ocspdErrorLog("OCSPResponse: bad producedAt %@", hexResp); goto errOut; } if (this->responseData.responderID.Data == NULL) { - ocspdErrorLog("OCSPResponse: bad responderID"); + ocspdErrorLog("OCSPResponse: bad responderID %@", hexResp); goto errOut; } @@ -373,12 +380,12 @@ SecOCSPResponseRef SecOCSPResponseCreate(CFDataRef ocspResponse, templ = kSecAsn1OCSPResponderIDAsKeyTemplate; break; default: - ocspdErrorLog("OCSPResponse: bad responderID tag"); + ocspdErrorLog("OCSPResponse: bad responderID tag %@", hexResp); goto errOut; } if (SecAsn1DecodeData(this->coder, &this->responseData.responderID, templ, &this->responderID)) { - ocspdErrorLog("OCSPResponse: decode failure at responderID"); + ocspdErrorLog("OCSPResponse: decode failure at responderID %@", hexResp); goto errOut; } @@ -394,8 +401,11 @@ SecOCSPResponseRef SecOCSPResponseCreate(CFDataRef ocspResponse, mExtensions = new OCSPExtensions(mResponseData.responseExtensions); #endif +fini: + CFReleaseSafe(hexResp); return this; errOut: + CFReleaseSafe(hexResp); if (this) { SecOCSPResponseFinalize(this); } diff --git a/sec/securityd/SecOCSPResponse.h b/Security/sec/securityd/SecOCSPResponse.h similarity index 98% rename from sec/securityd/SecOCSPResponse.h rename to Security/sec/securityd/SecOCSPResponse.h index ebd02d53..d9959150 100644 --- a/sec/securityd/SecOCSPResponse.h +++ b/Security/sec/securityd/SecOCSPResponse.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2009,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, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/Security/sec/securityd/SecOTRRemote.c b/Security/sec/securityd/SecOTRRemote.c new file mode 100644 index 00000000..d1ec5dcb --- /dev/null +++ b/Security/sec/securityd/SecOTRRemote.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include "SecOTRRemote.h" +#include +#include +#include +#include + +#include "SOSAccount.h" + +CFDataRef SecOTRSessionCreateRemote_internal(CFDataRef publicAccountData, CFDataRef publicPeerId, CFDataRef privateAccountData, CFErrorRef *error) { + SOSDataSourceFactoryRef ds = SecItemDataSourceFactoryGetDefault(); + + SOSAccountRef privateAccount = (privateAccountData == NULL) ? SOSKeychainAccountGetSharedAccount() : SOSAccountCreateFromData(kCFAllocatorDefault, privateAccountData, ds, error); + + SOSAccountRef publicAccount = (publicAccountData == NULL) ? SOSKeychainAccountGetSharedAccount() : SOSAccountCreateFromData(kCFAllocatorDefault, publicAccountData, ds, error); + + if(!privateAccount || !publicAccount) + return NULL; + + __block SOSFullPeerInfoRef full_peer_info = NULL; + SOSAccountForEachCircle(privateAccount, ^(SOSCircleRef circle) { + if (full_peer_info == NULL) { + full_peer_info = SOSAccountGetMyFullPeerInCircle(privateAccount, circle, error); + } + }); + + SecKeyRef privateKeyRef = SOSFullPeerInfoCopyDeviceKey(full_peer_info, error); + + CFStringRef publicKeyString = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, publicPeerId, kCFStringEncodingUTF8); + __block SOSPeerInfoRef peer_info = NULL; + SOSAccountForEachCircle(publicAccount, ^(SOSCircleRef circle) { + if (peer_info == NULL) { + peer_info = SOSCircleCopyPeerWithID(circle, publicKeyString, error); + } + }); + + SecKeyRef publicKeyRef = SOSPeerInfoCopyPubKey(peer_info); + + SecOTRFullIdentityRef privateIdentity = SecOTRFullIdentityCreateFromSecKeyRef(kCFAllocatorDefault, privateKeyRef, error); + SecOTRPublicIdentityRef publicIdentity = SecOTRPublicIdentityCreateFromSecKeyRef(kCFAllocatorDefault, publicKeyRef, error); + + SecOTRSessionRef ourSession = SecOTRSessionCreateFromID(kCFAllocatorDefault, privateIdentity, publicIdentity); + + CFMutableDataRef exportSession = CFDataCreateMutable(kCFAllocatorDefault, 0); + SecOTRSAppendSerialization(ourSession, exportSession); + + return exportSession; +} + +CFDataRef _SecOTRSessionCreateRemote(CFDataRef publicPeerId, CFErrorRef *error) { + return SecOTRSessionCreateRemote_internal(NULL, publicPeerId, NULL, error); +} + +bool _SecOTRSessionProcessPacketRemote(CFDataRef sessionData, CFDataRef inputPacket, CFDataRef* outputSessionData, CFDataRef* outputPacket, bool *readyForMessages, CFErrorRef *error) { + + SecOTRSessionRef session = SecOTRSessionCreateFromData(kCFAllocatorDefault, sessionData); + + CFMutableDataRef negotiationResponse = CFDataCreateMutable(kCFAllocatorDefault, 0); + + if (inputPacket) { + SecOTRSProcessPacket(session, inputPacket, negotiationResponse); + } else { + SecOTRSAppendStartPacket(session, negotiationResponse); + } + + CFMutableDataRef outputSession = CFDataCreateMutable(kCFAllocatorDefault, 0); + + SecOTRSAppendSerialization(session, outputSession); + *outputSessionData = outputSession; + + *outputPacket = negotiationResponse; + + *readyForMessages = SecOTRSGetIsReadyForMessages(session); + + return true; +} + diff --git a/Security/sec/securityd/SecOTRRemote.h b/Security/sec/securityd/SecOTRRemote.h new file mode 100644 index 00000000..44775958 --- /dev/null +++ b/Security/sec/securityd/SecOTRRemote.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef sec_SecOTRRemote_h +#define sec_SecOTRRemote_h + +#include + +CFDataRef SecOTRSessionCreateRemote_internal(CFDataRef publicAccountData, CFDataRef publicPeerId, CFDataRef privateAccountData, CFErrorRef *error); +CFDataRef _SecOTRSessionCreateRemote(CFDataRef publicPeerId, CFErrorRef *error); +bool _SecOTRSessionProcessPacketRemote(CFDataRef sessionData, CFDataRef inputPacket, CFDataRef* outputSessionData, CFDataRef* outputPacket, bool *readyForMessages, CFErrorRef *error); + +#endif diff --git a/sec/securityd/SecPolicyServer.c b/Security/sec/securityd/SecPolicyServer.c similarity index 96% rename from sec/securityd/SecPolicyServer.c rename to Security/sec/securityd/SecPolicyServer.c index fc2b910c..7d003917 100644 --- a/sec/securityd/SecPolicyServer.c +++ b/Security/sec/securityd/SecPolicyServer.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2008-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -96,10 +96,10 @@ static CFArrayRef SecPolicyAnchorDigestsForEVPolicy(const DERItem *policyOID) { return result; } - + CFDictionaryRef evToPolicyAnchorDigest = SecOTAPKICopyEVPolicyToAnchorMapping(otapkiRef); CFRelease(otapkiRef); - + if (NULL == evToPolicyAnchorDigest) { return result; @@ -107,16 +107,17 @@ static CFArrayRef SecPolicyAnchorDigestsForEVPolicy(const DERItem *policyOID) CFArrayRef roots = NULL; CFStringRef oid = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, policyOID); - if (oid && evToPolicyAnchorDigest) + if (oid && evToPolicyAnchorDigest) { result = (CFArrayRef)CFDictionaryGetValue(evToPolicyAnchorDigest, oid); - if (roots && CFGetTypeID(result) != CFArrayGetTypeID()) + if (roots && CFGetTypeID(result) != CFArrayGetTypeID()) { ocspdErrorLog("EVRoot.plist has non array value"); result = NULL; } CFRelease(oid); } + CFReleaseSafe(evToPolicyAnchorDigest); return result; } @@ -467,6 +468,77 @@ static void SecPolicyCheckQualifiedCertStatements(SecPVCRef pvc, CFStringRef key) { } +/* Compare hostname suffix to domain name. + This function does not process wildcards, and allows hostname to match + any subdomain level of the provided domain. + + To match, the last domain length chars of hostname must equal domain, + and the character immediately preceding domain in hostname (if any) + must be a dot. This means that domain 'bar.com' will match hostname + values 'host.bar.com' or 'host.sub.bar.com', but not 'host.foobar.com'. + + Characters in each string are converted to lowercase for the comparison. + Trailing '.' characters in both names will be ignored. + + Returns true on match, else false. + */ +static bool SecDomainSuffixMatch(CFStringRef hostname, CFStringRef domain) { + CFStringInlineBuffer hbuf, dbuf; + UniChar hch, dch; + CFIndex hix, dix, + hlength = CFStringGetLength(hostname), + dlength = CFStringGetLength(domain); + CFRange hrange = { 0, hlength }, drange = { 0, dlength }; + CFStringInitInlineBuffer(hostname, &hbuf, hrange); + CFStringInitInlineBuffer(domain, &dbuf, drange); + + if((hlength == 0) || (dlength == 0)) { + /* trivial case with at least one empty name */ + return (hlength == dlength) ? true : false; + } + + /* trim off trailing dots */ + hch = CFStringGetCharacterFromInlineBuffer(&hbuf, hlength-1); + dch = CFStringGetCharacterFromInlineBuffer(&dbuf, dlength-1); + if(hch == '.') { + hrange.length = --hlength; + } + if(dch == '.') { + drange.length = --dlength; + } + + /* trim off leading dot in suffix, if present */ + dch = CFStringGetCharacterFromInlineBuffer(&dbuf, 0); + if((dlength > 0) && (dch == '.')) { + drange.location++; + drange.length = --dlength; + } + + if(hlength < dlength) { + return false; + } + + /* perform case-insensitive comparison of domain suffix */ + for (hix = (hlength-dlength), + dix = drange.location; dix < drange.length; dix++) { + hch = CFStringGetCharacterFromInlineBuffer(&hbuf, hix); + dch = CFStringGetCharacterFromInlineBuffer(&dbuf, dix); + if (towlower(hch) != towlower(dch)) { + return false; + } + } + + /* require a dot prior to domain suffix, unless hostname == domain */ + if(hlength > dlength) { + hch = CFStringGetCharacterFromInlineBuffer(&hbuf, (hlength-(dlength+1))); + if(hch != '.') { + return false; + } + } + + return true; +} + /* Compare hostname, to a server name obtained from the server's cert Obtained from the SubjectAltName or the CommonName entry in the Subject. Limited wildcard checking is performed here as outlined in @@ -525,7 +597,7 @@ static bool SecDNSMatch(CFStringRef hostname, CFStringRef servername) { form 'foo*.com' or '*.com'. Match until next '.' in hostname. */ do { /* Since we're not at the end of servername yet (that case - was handeled above), running out of chars in hostname + was handled above), running out of chars in hostname means we don't have a match. */ if (hix >= hlength) return false; @@ -560,6 +632,45 @@ static bool SecDNSMatch(CFStringRef hostname, CFStringRef servername) { return true; } +#define kSecPolicySHA1Size 20 +static const UInt8 kAppleCorpCASHA1[kSecPolicySHA1Size] = { + 0xA1, 0x71, 0xDC, 0xDE, 0xE0, 0x8B, 0x1B, 0xAE, 0x30, 0xA1, + 0xAE, 0x6C, 0xC6, 0xD4, 0x03, 0x3B, 0xFD, 0xEF, 0x91, 0xCE +}; + +/* Check whether hostname is in a particular set of allowed domains. + Returns true if OK, false if not allowed. + */ +static bool SecPolicyCheckDomain(SecPVCRef pvc, CFStringRef hostname) +{ + CFIndex count = SecPVCGetCertificateCount(pvc); + SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, count - 1); + CFDataRef anchorSHA1 = SecCertificateGetSHA1Digest(cert); + + /* is this chain anchored by kAppleCorpCASHA1? */ + CFDataRef corpSHA1 = CFDataCreateWithBytesNoCopy(NULL, + kAppleCorpCASHA1, kSecPolicySHA1Size, kCFAllocatorNull); + bool isCorpSHA1 = (corpSHA1 && CFEqual(anchorSHA1, corpSHA1)); + CFReleaseSafe(corpSHA1); + if (isCorpSHA1) { + /* limit hostname to specified domains */ + const CFStringRef dnlist[] = { + CFSTR("apple.com"), + CFSTR("icloud.com"), + }; + unsigned int idx, dncount=2; + for (idx = 0; idx < dncount; idx++) { + if (SecDomainSuffixMatch(hostname, dnlist[idx])) { + return true; + } + } + return false; + } + /* %%% other CA pinning checks TBA */ + + return true; +} + /* AUDIT[securityd](done): policy->_options is a caller provided dictionary, only its cf type has been checked. @@ -612,7 +723,12 @@ static void SecPolicyCheckSSLHostname(SecPVCRef pvc, if (!dnsMatch) { /* Hostname mismatch or no hostnames found in certificate. */ SecPVCSetResult(pvc, key, 0, kCFBooleanFalse); - } + } + else if (!SecPolicyCheckDomain(pvc, hostName)) { + /* Hostname match, but domain not allowed for this CA */ + SecPVCSetResult(pvc, key, 0, kCFBooleanFalse); + } + if ((dnsMatch || pvc->details) && SecPolicySubscriberCertificateCouldBeEV(leaf)) { secdebug("policy", "enabling optionally_ev"); @@ -1067,10 +1183,10 @@ static void SecPolicyCheckBlackListedLeaf(SecPVCRef pvc, { /* Check for blacklisted intermediates keys. */ CFDataRef dgst = SecCertificateCopyPublicKeySHA1Digest(cert); - if (dgst) + if (dgst) { /* Check dgst against blacklist. */ - if (CFSetContainsValue(blackListedKeys, dgst)) + if (CFSetContainsValue(blackListedKeys, dgst)) { SecPVCSetResult(pvc, key, 0, kCFBooleanFalse); } @@ -1093,10 +1209,10 @@ static void SecPolicyCheckGrayListedLeaf(SecPVCRef pvc, CFStringRef key) SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, 0); CFDataRef dgst = SecCertificateCopyPublicKeySHA1Digest(cert); - if (dgst) + if (dgst) { /* Check dgst against gray. */ - if (CFSetContainsValue(grayListedKeys, dgst)) + if (CFSetContainsValue(grayListedKeys, dgst)) { SecPVCSetResult(pvc, key, 0, kCFBooleanFalse); } @@ -1671,17 +1787,17 @@ static void SecPolicyCheckCertificatePolicyOid(SecPVCRef pvc, CFStringRef key) DERItem key_value; key_value.data = NULL; key_value.length = 0; - + if (CFGetTypeID(value) == CFDataGetTypeID()) { CFDataRef key_data = (CFDataRef)value; key_value.data = (DERByte *)CFDataGetBytePtr(key_data); key_value.length = (DERSize)CFDataGetLength(key_data); - + for (ix = 0; ix < count; ix++) { SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, ix); policy_set_t policies = policies_for_cert(cert); - + if (policy_set_contains(policies, &key_value)) { return; } @@ -2324,7 +2440,7 @@ void SecPVCDelete(SecPVCRef pvc) { } void SecPVCSetPath(SecPVCRef pvc, SecCertificatePathRef path, - CFArrayRef details) { + CF_CONSUMED CFArrayRef details) { secdebug("policy", "%@", path); if (pvc->path != path) { /* Changing path makes us clear the Revocation Verification Contexts */ diff --git a/sec/securityd/SecPolicyServer.h b/Security/sec/securityd/SecPolicyServer.h similarity index 97% rename from sec/securityd/SecPolicyServer.h rename to Security/sec/securityd/SecPolicyServer.h index c46e2272..bb9a6194 100644 --- a/sec/securityd/SecPolicyServer.h +++ b/Security/sec/securityd/SecPolicyServer.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2008-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-2010,2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -66,7 +66,7 @@ void SecPVCInit(SecPVCRef pvc, SecPathBuilderRef builder, CFArrayRef policies, CFAbsoluteTime verifyTime); void SecPVCDelete(SecPVCRef pvc); void SecPVCSetPath(SecPVCRef pvc, SecCertificatePathRef path, - CFArrayRef details); + CF_CONSUMED CFArrayRef details); SecPolicyRef SecPVCGetPolicy(SecPVCRef pv); CFAbsoluteTime SecPVCGetVerifyTime(SecPVCRef pv); CFIndex SecPVCGetCertificateCount(SecPVCRef pv); diff --git a/sec/securityd/SecTrustServer.c b/Security/sec/securityd/SecTrustServer.c similarity index 99% rename from sec/securityd/SecTrustServer.c rename to Security/sec/securityd/SecTrustServer.c index fc12a774..f5bb542d 100644 --- a/sec/securityd/SecTrustServer.c +++ b/Security/sec/securityd/SecTrustServer.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2010,2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,11 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ * * SecTrustServer.c - certificate trust evaluation engine * - * Created by Michael Brouwer on 12/12/08. * */ @@ -58,7 +57,7 @@ #include #include #include -#include "securityd_client.h" +#include #include #include "OTATrustUtilities.h" @@ -1154,6 +1153,7 @@ static bool SecPathBuilderComputeDetails(SecPathBuilderRef builder) { CFIndex ix, pathLength = SecCertificatePathGetCount(builder->bestPath); CFMutableArrayRef details = CFArrayCreateMutableCopy(kCFAllocatorDefault, pathLength, builder->leafDetails); + CFRetainSafe(details); SecPVCSetPath(pvc, builder->bestPath, details); /* Only report on EV stuff if the bestPath actually was valid for EV. */ pvc->optionally_ev = builder->bestPathIsEV; @@ -1177,6 +1177,8 @@ static bool SecPathBuilderComputeDetails(SecPathBuilderRef builder) { builder->rejectScore = 0; } + CFReleaseSafe(details); + return completed; } diff --git a/sec/securityd/SecTrustServer.h b/Security/sec/securityd/SecTrustServer.h similarity index 97% rename from sec/securityd/SecTrustServer.h rename to Security/sec/securityd/SecTrustServer.h index 0a5b8888..45b70807 100644 --- a/sec/securityd/SecTrustServer.h +++ b/Security/sec/securityd/SecTrustServer.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2008-2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2008-2009,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, @@ -17,12 +17,11 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ * * SecTrustServer.h - certificate trust evaluation engine * - * Created by Michael Brouwer on 12/12/08. * */ diff --git a/sec/securityd/SecTrustStoreServer.c b/Security/sec/securityd/SecTrustStoreServer.c similarity index 99% rename from sec/securityd/SecTrustStoreServer.c rename to Security/sec/securityd/SecTrustStoreServer.c index 18a1e48c..fe5be3d5 100644 --- a/sec/securityd/SecTrustStoreServer.c +++ b/Security/sec/securityd/SecTrustStoreServer.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2007-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2010,2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -45,7 +45,7 @@ #include #include "SecBasePriv.h" #include -#include "securityd_client.h" +#include #include #include "utilities/sqlutils.h" #include "utilities/SecDb.h" diff --git a/sec/securityd/SecTrustStoreServer.h b/Security/sec/securityd/SecTrustStoreServer.h similarity index 95% rename from sec/securityd/SecTrustStoreServer.h rename to Security/sec/securityd/SecTrustStoreServer.h index e51cb1de..9d2f37af 100644 --- a/sec/securityd/SecTrustStoreServer.h +++ b/Security/sec/securityd/SecTrustStoreServer.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2007-2009 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2009,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, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/sec/securityd/asynchttp.c b/Security/sec/securityd/asynchttp.c similarity index 96% rename from sec/securityd/asynchttp.c rename to Security/sec/securityd/asynchttp.c index 155f8d8d..2a29fd2c 100644 --- a/sec/securityd/asynchttp.c +++ b/Security/sec/securityd/asynchttp.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2009-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2009-2010,2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -133,6 +133,7 @@ static CFStringRef copyParseMaxAge(CFStringRef cacheControlHeader) { equalIdx ++; } if (equalIdx < maxCompRg) { + CFReleaseNull(maxAgeValue); maxAgeValue = CFStringCreateWithSubstring(kCFAllocatorDefault, cacheControlHeader, CFRangeMake(equalIdx, maxCompRg-equalIdx)); } } else if (!CFCharacterSetIsCharacterMember(whitespaceSet, equalCh)) { @@ -218,10 +219,9 @@ static void handle_server_response(CFReadStreamRef stream, //CFHTTPMessageAppendBytes(http->response, buffer, length); CFDataAppendBytes(http->data, buffer, length); } else { - /* Read 0 bytes, are we are done or do we wait for - kCFStreamEventEndEncountered? */ - asynchttp_complete(http); - break; + /* Read 0 bytes. This is a no-op, but we need to keep + reading until CFReadStreamHasBytesAvailable is false. + */ } } while (CFReadStreamHasBytesAvailable(stream)); break; @@ -285,9 +285,10 @@ static CFURLRef createGetURL(CFURLRef responder, CFDataRef request) { require(base64RequestString = CFStringCreateWithBytes(kCFAllocatorDefault, CFDataGetBytePtr(base64Request), base64Len, kCFStringEncodingUTF8, false), errOut); + /* percent-encode all reserved characters from RFC 3986 [2.2] */ require(peRequest = CFURLCreateStringByAddingPercentEscapes( - kCFAllocatorDefault, base64RequestString, NULL, CFSTR("+/="), - kCFStringEncodingUTF8), errOut); + kCFAllocatorDefault, base64RequestString, NULL, + CFSTR(":/?#[]@!$&'()*+,;="), kCFStringEncodingUTF8), errOut); #if 1 CFStringRef urlString = CFURLGetString(responder); CFStringRef fullURL; @@ -383,7 +384,7 @@ errOut: } -static void asynchttp_timer_proc(asynchttp_t *http) { +static void asynchttp_timer_proc(asynchttp_t *http CF_CONSUMED) { CFStringRef req_meth = http->request ? CFHTTPMessageCopyRequestMethod(http->request) : NULL; CFURLRef req_url = http->request ? CFHTTPMessageCopyRequestURL(http->request) : NULL; secnotice("http", "Timeout during %@ %@.", req_meth, req_url); diff --git a/sec/securityd/asynchttp.h b/Security/sec/securityd/asynchttp.h similarity index 96% rename from sec/securityd/asynchttp.h rename to Security/sec/securityd/asynchttp.h index 9db96d8c..38201cf8 100644 --- a/sec/securityd/asynchttp.h +++ b/Security/sec/securityd/asynchttp.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2009-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2009-2010,2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/Security/sec/securityd/entitlements.plist b/Security/sec/securityd/entitlements.plist new file mode 100644 index 00000000..08919a3c --- /dev/null +++ b/Security/sec/securityd/entitlements.plist @@ -0,0 +1,18 @@ + + + + + application-identifier + com.apple.securityd + com.apple.keystore.access-keychain-keys + + com.apple.keystore.lockassertion + + com.apple.private.associated-domains + + com.apple.private.CoreAuthentication.SPI + + com.apple.private.CoreAuthentication.CallerPID + + + diff --git a/Security/sec/securityd/iCloudTrace.c b/Security/sec/securityd/iCloudTrace.c new file mode 100644 index 00000000..2b3d2a11 --- /dev/null +++ b/Security/sec/securityd/iCloudTrace.c @@ -0,0 +1,536 @@ +/* + * 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 "iCloudTrace.h" +#include +#include +#include +#include +#include +#include +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) +#include +#endif +#include + +extern bool SOSCCThisDeviceDefinitelyNotActiveInCircle(void); + + +#define MAX_PATH 1024 + +/* -------------------------------------------------------------------------- + Function: GetNumberOfItemsBeingSynced + + Description: Determine the number of items being synced. NOTE: + This uses the SOSDataSourceFactoryRef instead of + calling the SecItem interface because the SecItem + interface requires an entitlement but the + SOSDataSourceFactoryRef does not. + -------------------------------------------------------------------------- */ +static int64_t GetNumberOfItemsBeingSynced() +{ + __block int64_t result = 0; + SOSDataSourceFactoryRef dsFactRef = SecItemDataSourceFactoryGetDefault(); + CFArrayRef ds_names = dsFactRef->copy_names(dsFactRef); + + if (ds_names) { + CFArrayForEach(ds_names, ^(const void *value) { + if (isString(value)) { + SOSManifestRef manifestRef = NULL; + SOSDataSourceRef ds = dsFactRef->create_datasource(dsFactRef, value, NULL); + + if (ds) { + manifestRef = SOSDataSourceCopyManifest(ds, NULL); + if (manifestRef) + result += SOSManifestGetCount(manifestRef); + } + + CFReleaseSafe(manifestRef); + SOSDataSourceRelease(ds, NULL); + } + }); + } + + CFReleaseSafe(ds_names); + return result; +} + +/* -------------------------------------------------------------------------- + Function: GetNumberOfPeers + + Description: Determine the number of peers in the circle that this + device is in + -------------------------------------------------------------------------- */ +static int64_t GetNumberOfPeers() +{ + int64_t result = 0; + + CFErrorRef error = NULL; + CFArrayRef peers = NULL; + + peers = SOSCCCopyPeerPeerInfo(&error); + if (NULL != error) + { + CFRelease(error); + if (NULL != peers) + { + CFRelease(peers); + } + return result; + } + + if (NULL != peers) + { + result = (int64_t)CFArrayGetCount(peers); + CFRelease(peers); + } + + return result; +} + +static const char* kLoggingPlistPartialPath = "/Library/Preferences/com.apple.security.logging.plist"; + +/* -------------------------------------------------------------------------- + Function: PathExists + + Description: Utility fucntion to see if a file path exists + -------------------------------------------------------------------------- */ +static Boolean PathExists(const char* path, size_t* pFileSize) +{ + Boolean result = false; + struct stat sb; + + if (NULL != pFileSize) + { + *pFileSize = 0; + } + + int stat_result = stat(path, &sb); + result = (stat_result == 0); + + if (result) + { + if (S_ISDIR(sb.st_mode)) + { + // It is a directory + ; + } + else + { + // It is a file + if (NULL != pFileSize) + { + *pFileSize = (size_t)sb.st_size; + } + } + } + return result; +} + +/* -------------------------------------------------------------------------- + Function: CopyFileContents + + Description: Given a file path read the entire contents of the file + into a CFDataRef + -------------------------------------------------------------------------- */ +static CFDataRef CopyFileContents(const char *path) +{ + CFMutableDataRef data = NULL; + int fd = open(path, O_RDONLY, 0666); + + if (fd == -1) + { + goto badFile; + } + + off_t fsize = lseek(fd, 0, SEEK_END); + if (fsize == (off_t)-1) + { + goto badFile; + } + + if (fsize > (off_t)INT32_MAX) + { + goto badFile; + } + + data = CFDataCreateMutable(kCFAllocatorDefault, (CFIndex)fsize); + if (NULL == data) + { + goto badFile; + } + + CFDataSetLength(data, (CFIndex)fsize); + void *buf = CFDataGetMutableBytePtr(data); + if (NULL == buf) + { + goto badFile; + } + + off_t total_read = 0; + while (total_read < fsize) + { + ssize_t bytes_read; + + bytes_read = pread(fd, buf, (size_t)(fsize - total_read), total_read); + if (bytes_read == -1) + { + goto badFile; + } + if (bytes_read == 0) + { + goto badFile; + } + total_read += bytes_read; + } + + close(fd); + return data; + +badFile: + if (fd != -1) + { + close(fd); + } + + if (data) + { + CFRelease(data); + } + + return NULL; +} + +static const CFStringRef kLoggingPlistKey = CFSTR("LoggingTime"); + +/* -------------------------------------------------------------------------- + Function: CopyPlistPath + + Description: Return the fully qualified file path to the logging + plist + -------------------------------------------------------------------------- */ +static const char* CopyPlistPath() +{ + const char* result = NULL; + CFURLRef url = NULL; + + +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) + CFStringRef path_string = NULL; + const char *homeDir = getenv("HOME"); + + if (!homeDir) + { + struct passwd* pwd = getpwuid(getuid()); + if (pwd) + homeDir = pwd->pw_dir; + } + + path_string = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, homeDir, kCFStringEncodingUTF8, kCFAllocatorNull); + if (NULL == path_string) + { + return result; + } + + url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path_string, kCFURLPOSIXPathStyle, true); + CFRelease(path_string); +#endif + +#if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR) + url = CFCopyHomeDirectoryURL(); +#endif + + if (url) + { + UInt8 file_path_buffer[MAX_PATH+1]; + memset(file_path_buffer, 0, MAX_PATH); + size_t length = 0; + + if(!CFURLGetFileSystemRepresentation(url, false, file_path_buffer, MAX_PATH)) + { + CFRelease(url); + return result; // better to log too much than not at all + } + + CFRelease(url); + + if (strnlen((const char *)file_path_buffer, MAX_PATH) + strlen(kLoggingPlistPartialPath) >= MAX_PATH) + { + return result; // better to log too much than not at all + } + + strncat((char *)file_path_buffer, kLoggingPlistPartialPath, MAX_PATH); + length = strlen((char *)file_path_buffer) + 1; + result = malloc(length); + if (NULL == result) + { + return result; + } + + memset((void *)result, 0, length); + strncpy((char *)result, (char *)file_path_buffer, length - 1); + return result; + } + + return NULL; + +} + +/* -------------------------------------------------------------------------- + Function: ShouldLog + + Description: Get the current time and match that against the value + in the logging plist and see if logging should be done + -------------------------------------------------------------------------- */ +static bool ShouldLog() +{ + bool result = false; + size_t fileSize = 0; + CFDataRef file_data = NULL; + CFPropertyListRef logging_time_data = NULL; + CFDataRef time_data = NULL; + const char* plist_path = NULL; + + plist_path = CopyPlistPath(); + if (NULL == plist_path) + { + return true; // better to log too much than not at all + } + + if (!PathExists((const char *)plist_path, &fileSize)) + { + free((void *)plist_path); + return true; // better to log too much than not at all + } + + file_data = CopyFileContents((const char *)plist_path); + free((void *)plist_path); + if (NULL == file_data) + { + return true; // better to log too much than not at all + } + + logging_time_data = CFPropertyListCreateWithData(kCFAllocatorDefault, file_data, kCFPropertyListMutableContainersAndLeaves, NULL, NULL); + CFRelease(file_data); + + if (NULL == logging_time_data) + { + return true; // better to log too much than not at all + } + + require_action(CFDictionaryGetTypeID() == CFGetTypeID(logging_time_data), xit, result = true); // better to log too much than not at all + + time_data = (CFDataRef)CFDictionaryGetValue((CFDictionaryRef)logging_time_data, kLoggingPlistKey); + require_action(time_data, xit, result = true); // better to log too much than not at all + + CFAbsoluteTime startTime = 0; + memcpy(&startTime, CFDataGetBytePtr(time_data), sizeof(startTime)); + + CFAbsoluteTime endTime = CFAbsoluteTimeGetCurrent(); + + int days = 0; + + CFCalendarRef gregorian = CFCalendarCopyCurrent(); + CFCalendarGetComponentDifference(gregorian, startTime, endTime, 0, "d", &days); + + CFRelease(gregorian); + +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) + if (days > 6) + { + result = true; + } +#endif + +#if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR) + if (days > 0) + { + result = true; + } +#endif + +xit: + CFReleaseSafe(logging_time_data); + return result; +} + +/* -------------------------------------------------------------------------- + Function: WriteOutLoggingTime + + Description: Write out the logging plist with the time that the + last logging was done. + -------------------------------------------------------------------------- */ +static void WriteOutLoggingTime(void) +{ + int fd = -1; + CFAbsoluteTime now; + CFDataRef now_data; + CFDictionaryRef plistData = NULL; + CFErrorRef error = NULL; + CFDataRef output_data = NULL; + + const char* filepath = CopyPlistPath(); + if (NULL == filepath) + { + return; + } + + fd = open(filepath, (O_WRONLY | O_CREAT | O_TRUNC), 0666); + free((void *)filepath); + if (fd <= 0) + { + return; + } + + now = CFAbsoluteTimeGetCurrent(); + now_data = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)&now, sizeof(now)); + if (NULL == now_data) + { + close(fd); + return; + } + + plistData = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&kLoggingPlistKey, (const void **)&now_data, 1, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (NULL == plistData) + { + close(fd); + CFRelease(now_data); + return; + } + CFRelease(now_data); + + output_data = CFPropertyListCreateData(kCFAllocatorDefault, plistData, kCFPropertyListBinaryFormat_v1_0, 0, &error); + CFRelease(plistData); + if (NULL != error || NULL == output_data) + { + close(fd); + if (NULL != error) + { + CFRelease(error); + } + + if (NULL != output_data) + { + CFRelease(output_data); + } + + return; + } + + write(fd, CFDataGetBytePtr(output_data), CFDataGetLength(output_data)); + close(fd); + + CFRelease(output_data); + +} + +/* -------------------------------------------------------------------------- + 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; +} + +/* -------------------------------------------------------------------------- + Function: DoLogging + + Description: If it has been determined that logging should be done + this function will perform the logging + -------------------------------------------------------------------------- */ +static void DoLogging() +{ + int64_t value = 1; + + void* token = BeginCloudKeychainLoggingTransaction(); + + value = GetNumberOfPeers(); + value = Bucket(value); + AddKeyValuePairToKeychainLoggingTransaction(token, kNumberOfiCloudKeychainPeers, value); + + value = GetNumberOfItemsBeingSynced(); + value = Bucket(value); + + AddKeyValuePairToKeychainLoggingTransaction(token, kNumberOfiCloudKeychainItemsBeingSynced, value); + CloseCloudKeychainLoggingTransaction(token); + + WriteOutLoggingTime(); +} + +/* -------------------------------------------------------------------------- + Function: InitializeCloudKeychainTracing + + Description: Called when secd starts up. It will first determine if + the device is in a circle and if so it will see if + logging should be done (if enough time has expired since + the last time logging was done) and if logging should + be done will perform the logging. + -------------------------------------------------------------------------- */ +void InitializeCloudKeychainTracing() +{ + if (SOSCCThisDeviceDefinitelyNotActiveInCircle()) // No circle no logging + { + return; + } + + if (ShouldLog()) + { + DoLogging(); + } +} diff --git a/Security/sec/securityd/iCloudTrace.h b/Security/sec/securityd/iCloudTrace.h new file mode 100644 index 00000000..cd99dc09 --- /dev/null +++ b/Security/sec/securityd/iCloudTrace.h @@ -0,0 +1,45 @@ +/* + * 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@ + */ + + +#ifndef sec_iCloudTrace_h +#define sec_iCloudTrace_h +#include + +extern const CFStringRef kNumberOfiCloudKeychainPeers + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); +extern const CFStringRef kNumberOfiCloudKeychainItemsBeingSynced + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); +extern const CFStringRef kNumbrerOfiCloudKeychainSyncingConflicts + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); +extern const CFStringRef kNumberOfiCloudKeychainTimesSyncFailed + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); +extern const CFStringRef kNumberOfiCloudKeychainConflictsResolved + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); +extern const CFStringRef kNumberOfiCloudKeychainTimesSyncedWithPeers + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); + +void InitializeCloudKeychainTracing(void) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + +#endif diff --git a/sec/securityd/policytree.c b/Security/sec/securityd/policytree.c similarity index 99% rename from sec/securityd/policytree.c rename to Security/sec/securityd/policytree.c index a85b1cdc..b6086a38 100644 --- a/sec/securityd/policytree.c +++ b/Security/sec/securityd/policytree.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2009-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2009-2010,2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/sec/securityd/policytree.h b/Security/sec/securityd/policytree.h similarity index 97% rename from sec/securityd/policytree.h rename to Security/sec/securityd/policytree.h index ef5761df..38a60436 100644 --- a/sec/securityd/policytree.h +++ b/Security/sec/securityd/policytree.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2009-2010 Apple Inc. All Rights Reserved. + * Copyright (c) 2009-2010,2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/Security/sec/securityd/spi.c b/Security/sec/securityd/spi.c new file mode 100644 index 00000000..c9ec2b23 --- /dev/null +++ b/Security/sec/securityd/spi.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2009-2010,2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "utilities/iOSforOSX.h" +#include "utilities/SecFileLocations.h" +#include "OTATrustUtilities.h" + +static struct securityd spi = { + .sec_item_add = _SecItemAdd, + .sec_item_copy_matching = _SecItemCopyMatching, + .sec_item_update = _SecItemUpdate, + .sec_item_delete = _SecItemDelete, + .sec_add_shared_web_credential = _SecAddSharedWebCredential, + .sec_copy_shared_web_credential = _SecCopySharedWebCredential, + .sec_trust_store_for_domain = SecTrustStoreForDomainName, + .sec_trust_store_contains = SecTrustStoreContainsCertificateWithDigest, + .sec_trust_store_set_trust_settings = _SecTrustStoreSetTrustSettings, + .sec_trust_store_remove_certificate = SecTrustStoreRemoveCertificateWithDigest, + .sec_truststore_remove_all = _SecTrustStoreRemoveAll, + .sec_item_delete_all = _SecItemDeleteAll, + .sec_trust_evaluate = SecTrustServerEvaluate, + .sec_keychain_backup = _SecServerKeychainBackup, + .sec_keychain_restore = _SecServerKeychainRestore, + .sec_keychain_sync_update_key_parameter = _SecServerKeychainSyncUpdateKeyParameter, + .sec_keychain_backup_syncable = _SecServerBackupSyncable, + .sec_keychain_restore_syncable = _SecServerRestoreSyncable, + .sec_otr_session_create_remote = _SecOTRSessionCreateRemote, + .sec_otr_session_process_packet_remote = _SecOTRSessionProcessPacketRemote, + .sec_ota_pki_asset_version = SecOTAPKIGetCurrentAssetVersion, + .soscc_TryUserCredentials = SOSCCTryUserCredentials_Server, + .soscc_SetUserCredentials = SOSCCSetUserCredentials_Server, + .soscc_CanAuthenticate = SOSCCCanAuthenticate_Server, + .soscc_PurgeUserCredentials = SOSCCPurgeUserCredentials_Server, + .soscc_ThisDeviceIsInCircle = SOSCCThisDeviceIsInCircle_Server, + .soscc_RequestToJoinCircle = SOSCCRequestToJoinCircle_Server, + .soscc_RequestToJoinCircleAfterRestore = SOSCCRequestToJoinCircleAfterRestore_Server, + .soscc_RequestEnsureFreshParameters = SOSCCRequestEnsureFreshParameters_Server, + .soscc_ResetToOffering = SOSCCResetToOffering_Server, + .soscc_ResetToEmpty = SOSCCResetToEmpty_Server, + .soscc_RemoveThisDeviceFromCircle = SOSCCRemoveThisDeviceFromCircle_Server, + .soscc_BailFromCircle = SOSCCBailFromCircle_Server, + .soscc_AcceptApplicants = SOSCCAcceptApplicants_Server, + .soscc_RejectApplicants = SOSCCRejectApplicants_Server, + .soscc_CopyApplicantPeerInfo = SOSCCCopyApplicantPeerInfo_Server, + .soscc_CopyGenerationPeerInfo = SOSCCCopyGenerationPeerInfo_Server, + .soscc_CopyValidPeerPeerInfo = SOSCCCopyValidPeerPeerInfo_Server, + .soscc_ValidateUserPublic = SOSCCValidateUserPublic_Server, + .soscc_CopyNotValidPeerPeerInfo = SOSCCCopyNotValidPeerPeerInfo_Server, + .soscc_CopyRetirementPeerInfo = SOSCCCopyRetirementPeerInfo_Server, + .soscc_CopyPeerInfo = SOSCCCopyPeerPeerInfo_Server, + .soscc_CopyConcurringPeerInfo = SOSCCCopyConcurringPeerPeerInfo_Server, + .ota_CopyEscrowCertificates = SecOTAPKICopyCurrentEscrowCertificates, + .sec_ota_pki_get_new_asset = SecOTAPKISignalNewAsset, + .soscc_ProcessSyncWithAllPeers = SOSCCProcessSyncWithAllPeers_Server, + .soscc_EnsurePeerRegistration = SOSCCProcessEnsurePeerRegistration_Server, + .sec_roll_keys = _SecServerRollKeys, + .soscc_RequestDeviceID = SOSCCRequestDeviceID_Server, + .soscc_SetDeviceID = SOSCCSetDeviceID_Server, + .sec_keychain_sync_update_circle = _SecServerKeychainSyncUpdateCircle, + .sec_keychain_sync_update_message = _SecServerKeychainSyncUpdateMessage, + .sec_get_log_settings = SecCopyLogSettings_Server, + .sec_set_xpc_log_settings = SecSetXPCLogSettings_Server, +}; + +void securityd_init_server(void) { + gSecurityd = &spi; + SecPolicyServerInitalize(); +} + +void securityd_init(char* home_path) { + if (home_path) + SetCustomHomeURL(home_path); + + securityd_init_server(); +} diff --git a/Security/sec/securityd/spi.h b/Security/sec/securityd/spi.h new file mode 100644 index 00000000..006b1f61 --- /dev/null +++ b/Security/sec/securityd/spi.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2009-2010,2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#ifndef _SECURITYD_SPI_H_ +#define _SECURITYD_SPI_H_ + +#include +#include + +__BEGIN_DECLS + +/* Calling this function initializes the spi interface in the library to call + directly into the backend. It uses home_dir for root of files if specified. */ +void securityd_init(char* home_dir); + +// Don't call this function unless you are really securityd +void securityd_init_server(void); + +__END_DECLS + +#endif /* _SECURITYD_SPI_H_ */ diff --git a/Security/secdtests/main.c b/Security/secdtests/main.c new file mode 100644 index 00000000..9c24682b --- /dev/null +++ b/Security/secdtests/main.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include + +#include "test/testenv.h" + +#include "testlist.h" +#include +#include "testlist.h" +#include + +#include + +int main(int argc, char *argv[]) +{ + //printf("Build date : %s %s\n", __DATE__, __TIME__); + + /* We run this as if we are secd, so we need to initialize this */ + securityd_init(NULL); + + int result = tests_begin(argc, argv); + + fflush(stdout); + fflush(stderr); + + sleep(1); + + return result; +} diff --git a/Security/secdtests/testlist.h b/Security/secdtests/testlist.h new file mode 100644 index 00000000..e4b0f70a --- /dev/null +++ b/Security/secdtests/testlist.h @@ -0,0 +1,4 @@ +/* Don't prevent multiple inclusion of this file. */ +#include +#include +#include diff --git a/sectests/SecurityTests-Entitlements.plist b/Security/sectests/SecurityTests-Entitlements.plist similarity index 100% rename from sectests/SecurityTests-Entitlements.plist rename to Security/sectests/SecurityTests-Entitlements.plist diff --git a/Security/sectests/main.c b/Security/sectests/main.c new file mode 100644 index 00000000..dcb0c395 --- /dev/null +++ b/Security/sectests/main.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include + +#include "test/testenv.h" + +#include "testlist.h" +#include +#include "testlist.h" +#include + +int main(int argc, char *argv[]) +{ + //printf("Build date : %s %s\n", __DATE__, __TIME__); + + int result = tests_begin(argc, argv); + + fflush(stdout); + fflush(stderr); + + sleep(1); + + return result; +} diff --git a/Security/sectests/test/testenv.c b/Security/sectests/test/testenv.c new file mode 100644 index 00000000..b02247c2 --- /dev/null +++ b/Security/sectests/test/testenv.c @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2005-2007,2009-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@ + * + * testenv.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "testmore.h" +#include "testenv.h" + +int test_verbose = 0; + +#if NO_SERVER +#include + +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) +{ + char command_buf[256]; + if (strlen(path) + 10 > sizeof(command_buf) || strchr(path, '\'')) + { + fprintf(stderr, "# rmdir_recursive: invalid path: %s", path); + return -1; + } + + sprintf(command_buf, "rm -rf '%s'", path); + return system(command_buf); +} +#endif + +static int tests_init(void) { +#if NO_SERVER + char preferences_dir[80]; + char library_dir[70]; + + char *path = getenv("TESTHOME"); + if (path) + setenv("TESTHOME", path, 1); + securityd_init(); + + 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); + return (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")); + +#else + return 0; +#endif +} + +static int +tests_end(void) +{ +#if 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); +} + +static int tests_run_index(int i, 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]); + } + } + + fprintf(stderr, "TEST: Test Case '%s' started.\n", testlist[i].name); + + run_one_test(&testlist[i], argc, argv); + if(testlist[i].failed_tests) { + fprintf(stderr, "FAIL: Test Case '%s' failed.\n", testlist[i].name); + } else { + fprintf(stderr, "PASS: Test Case '%s' passed. (%lu ms)\n", testlist[i].name, testlist[i].duration); + } + return testlist[i].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_index(i, argc, argv); + optind = curroptind; + } + } + + return failcount; +} + +int +tests_begin(int argc, char * const *argv) +{ + const char *testcase = NULL; + bool initialized = false; + int testix = -1; + int failcount = 0; + int ch; + int loop = 0; + + for (;;) { + while (!testcase && (ch = getopt(argc, argv, "klw")) != -1) + { + switch (ch) + { +#ifdef NO_SERVER + case 'k': + keep_scratch_dir = true; + break; +#endif + case 'w': + sleep(100); + break; + case 'l': + loop=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 (testix < 0) { + if (!initialized) { + initialized = true; + tests_init(); + failcount+=tests_run_all(argc, argv); + } + break; + } else { + if (!initialized) { + tests_init(); + initialized = true; + } + optind++; + failcount+=tests_run_index(testix, argc, argv); + testix = -1; + } + } + + printf("Total failcount = %d\n", failcount); + + /* 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/Security/sectests/testlist.h b/Security/sectests/testlist.h new file mode 100644 index 00000000..b9939b23 --- /dev/null +++ b/Security/sectests/testlist.h @@ -0,0 +1,6 @@ +/* Don't prevent multiple inclusion of this file. */ +#include +#include +#include +#include + diff --git a/Security/security2/security2.1 b/Security/security2/security2.1 new file mode 100644 index 00000000..041df6d1 --- /dev/null +++ b/Security/security2/security2.1 @@ -0,0 +1,28 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. +.\"See Also: +.\"man mdoc.samples for a complete listing of options +.\"man mdoc for the short list of editing options +.Dd January 10, 2013 \" DATE +.Dt security2 1 \" Program name and manual section number +.Os Darwin +.Sh NAME \" Section Header - required - don't modify +.Nm security2 +.\" The following lines are read in generating the apropos(man -k) database. Use only key +.\" words here as the database is built based on the words here and in the .ND line. +.\" Use .Nm macro to designate other names for the documented program. +.Nd temporary adjunct to the security(1) command. +.Sh DESCRIPTION \" Section Header - required - don't modify +This command is intended for internal testing of iCloud Keychain functionality. +.br +Invoke without any arguments to see usage. +.Pp +.Sh WARNING +*** APPLE INTERNAL USE ONLY - DO NOT DISTRIBUTE *** +.Pp +Do not rely on the existence of +.Nm +as it will be merged into security(1). +.br +See: +.Pp +*** APPLE INTERNAL USE ONLY - DO NOT DISTRIBUTE *** diff --git a/Security/security2/security_tool_commands.c b/Security/security2/security_tool_commands.c new file mode 100644 index 00000000..388af043 --- /dev/null +++ b/Security/security2/security_tool_commands.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include +#include "SecurityTool/SecurityTool.h" + +#include "SecurityTool/security_tool_commands.h" + +#include "SecurityTool/builtin_commands.h" +#include "security2/sub_commands.h" + +// Redefine for making them declaraionts. +#include "SecurityTool/security_tool_commands_table.h" + +const command commands[] = +{ +#include "SecurityTool/builtin_commands.h" + +#include "security2/sub_commands.h" + + {} +}; diff --git a/Security/security2/sub_commands.h b/Security/security2/sub_commands.h new file mode 100644 index 00000000..e018521e --- /dev/null +++ b/Security/security2/sub_commands.h @@ -0,0 +1,28 @@ +/* + * 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 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" diff --git a/tlsnke/loadkext.sh b/Security/tlsnke/loadkext.sh similarity index 100% rename from tlsnke/loadkext.sh rename to Security/tlsnke/loadkext.sh diff --git a/Security/tlsnke/tlsnke.xcodeproj/project.pbxproj b/Security/tlsnke/tlsnke.xcodeproj/project.pbxproj new file mode 100644 index 00000000..a57a7850 --- /dev/null +++ b/Security/tlsnke/tlsnke.xcodeproj/project.pbxproj @@ -0,0 +1,611 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + 0CE08A7E148FF61C000473EB /* host-loadkext */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 0CE08A7F148FF61C000473EB /* Build configuration list for PBXAggregateTarget "host-loadkext" */; + buildPhases = ( + 0CE08A89148FF86C000473EB /* ShellScript */, + ); + dependencies = ( + 0CE08A83148FF628000473EB /* PBXTargetDependency */, + ); + name = "host-loadkext"; + productName = all; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 0C271D7515C8C80300560531 /* libsecurity_ssl_kext.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CBE354615C8C3A5006241C7 /* libsecurity_ssl_kext.a */; }; + 0C38E43D14BF707500DD862C /* tlsnke.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C38E43C14BF707500DD862C /* tlsnke.h */; }; + 0C6C642715D5A9C200BC68CD /* ssl-utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C6C642515D5A9C200BC68CD /* ssl-utils.c */; }; + 0C7CF8D714E18A9F00DF9D95 /* dtls_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C7CF8D614E18A9F00DF9D95 /* dtls_client.c */; }; + 0CBE354515C8C340006241C7 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CBE354415C8C340006241C7 /* Security.framework */; }; + 0CC9A7FA146DF66000C18F89 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0CC9A7F8146DF66000C18F89 /* InfoPlist.strings */; }; + 0CC9A7FC146DF66000C18F89 /* tlsnke.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CC9A7FB146DF66000C18F89 /* tlsnke.c */; }; + 0CDF46A414DC794F00FFE2FD /* tlssocket.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CA31A4214B7DFAB00BD348C /* tlssocket.c */; }; + 0CDF46A514DC795400FFE2FD /* tlssocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CA31A4514B7DFBA00BD348C /* tlssocket.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0CDF46A614DC79FA00FFE2FD /* libtlssocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CDF46A014DC794300FFE2FD /* libtlssocket.a */; }; + 0CE08A77148FF2C7000473EB /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CE08A76148FF2C7000473EB /* main.c */; }; + 0CEF580014C0E227000A93B0 /* st_test.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CEF57FF14C0E227000A93B0 /* st_test.c */; }; + 0CEF580614C0E566000A93B0 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CEF580514C0E566000A93B0 /* CoreFoundation.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 0CDF46A714DC79FF00FFE2FD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0CC9A7E5146DF66000C18F89 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0CDF469F14DC794300FFE2FD; + remoteInfo = tlssocket; + }; + 0CE08A82148FF628000473EB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0CC9A7E5146DF66000C18F89 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0CC9A7EF146DF66000C18F89; + remoteInfo = tlsnke; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 0CE08A71148FF2C6000473EB /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0C31453A1492D4B600427C0B /* tlsnke-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "tlsnke-Info.plist"; sourceTree = ""; }; + 0C38E43C14BF707500DD862C /* tlsnke.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tlsnke.h; sourceTree = ""; }; + 0C6C642515D5A9C200BC68CD /* ssl-utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-utils.c"; sourceTree = ""; }; + 0C6C642615D5A9C200BC68CD /* ssl-utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ssl-utils.h"; sourceTree = ""; }; + 0C7CF8D614E18A9F00DF9D95 /* dtls_client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dtls_client.c; sourceTree = ""; }; + 0CA31A4214B7DFAB00BD348C /* tlssocket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tlssocket.c; path = tlsnketest/tlssocket.c; sourceTree = ""; }; + 0CA31A4514B7DFBA00BD348C /* tlssocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tlssocket.h; path = tlsnketest/tlssocket.h; sourceTree = ""; }; + 0CBE354415C8C340006241C7 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Security.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 0CBE354615C8C3A5006241C7 /* libsecurity_ssl_kext.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libsecurity_ssl_kext.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 0CC9A7F0146DF66000C18F89 /* tlsnke.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = tlsnke.kext; sourceTree = BUILT_PRODUCTS_DIR; }; + 0CC9A7F4146DF66000C18F89 /* Kernel.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Kernel.framework; path = System/Library/Frameworks/Kernel.framework; sourceTree = SDKROOT; }; + 0CC9A7F9146DF66000C18F89 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 0CC9A7FB146DF66000C18F89 /* tlsnke.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = tlsnke.c; sourceTree = ""; }; + 0CC9A7FD146DF66000C18F89 /* tlsnke-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "tlsnke-Prefix.pch"; sourceTree = ""; }; + 0CDF468F14DC788000FFE2FD /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 0CDF46A014DC794300FFE2FD /* libtlssocket.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libtlssocket.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 0CE08A73148FF2C6000473EB /* tlsnketest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tlsnketest; sourceTree = BUILT_PRODUCTS_DIR; }; + 0CE08A76148FF2C7000473EB /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 0CEF57FF14C0E227000A93B0 /* st_test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = st_test.c; sourceTree = ""; }; + 0CEF580514C0E566000A93B0 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 0CC9A7EB146DF66000C18F89 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C271D7515C8C80300560531 /* libsecurity_ssl_kext.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0CDF469D14DC794300FFE2FD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0CE08A70148FF2C6000473EB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0CDF46A614DC79FA00FFE2FD /* libtlssocket.a in Frameworks */, + 0CBE354515C8C340006241C7 /* Security.framework in Frameworks */, + 0CEF580614C0E566000A93B0 /* CoreFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0C953FB814E4621800077526 /* Libraries */ = { + isa = PBXGroup; + children = ( + 0CBE354615C8C3A5006241C7 /* libsecurity_ssl_kext.a */, + ); + name = Libraries; + sourceTree = ""; + }; + 0CC9A7E3146DF66000C18F89 = { + isa = PBXGroup; + children = ( + 0CDF468814DC784200FFE2FD /* tlssocket */, + 0CC9A7F5146DF66000C18F89 /* tlsnke */, + 0CE08A75148FF2C6000473EB /* tlsnketest */, + 0CC9A7F2146DF66000C18F89 /* Frameworks */, + 0C953FB814E4621800077526 /* Libraries */, + 0CC9A7F1146DF66000C18F89 /* Products */, + ); + sourceTree = ""; + }; + 0CC9A7F1146DF66000C18F89 /* Products */ = { + isa = PBXGroup; + children = ( + 0CC9A7F0146DF66000C18F89 /* tlsnke.kext */, + 0CE08A73148FF2C6000473EB /* tlsnketest */, + 0CDF46A014DC794300FFE2FD /* libtlssocket.a */, + ); + name = Products; + sourceTree = ""; + }; + 0CC9A7F2146DF66000C18F89 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 0CBE354415C8C340006241C7 /* Security.framework */, + 0CEF580514C0E566000A93B0 /* CoreFoundation.framework */, + 0CDF468F14DC788000FFE2FD /* Foundation.framework */, + 0CC9A7F3146DF66000C18F89 /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + 0CC9A7F3146DF66000C18F89 /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 0CC9A7F4146DF66000C18F89 /* Kernel.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 0CC9A7F5146DF66000C18F89 /* tlsnke */ = { + isa = PBXGroup; + children = ( + 0CC9A7FB146DF66000C18F89 /* tlsnke.c */, + 0C38E43C14BF707500DD862C /* tlsnke.h */, + 0CC9A7F6146DF66000C18F89 /* Supporting Files */, + ); + path = tlsnke; + sourceTree = ""; + }; + 0CC9A7F6146DF66000C18F89 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 0C31453A1492D4B600427C0B /* tlsnke-Info.plist */, + 0CC9A7F8146DF66000C18F89 /* InfoPlist.strings */, + 0CC9A7FD146DF66000C18F89 /* tlsnke-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 0CDF468814DC784200FFE2FD /* tlssocket */ = { + isa = PBXGroup; + children = ( + 0CA31A4214B7DFAB00BD348C /* tlssocket.c */, + 0CA31A4514B7DFBA00BD348C /* tlssocket.h */, + ); + name = tlssocket; + sourceTree = ""; + }; + 0CE08A75148FF2C6000473EB /* tlsnketest */ = { + isa = PBXGroup; + children = ( + 0C6C642515D5A9C200BC68CD /* ssl-utils.c */, + 0C6C642615D5A9C200BC68CD /* ssl-utils.h */, + 0CE08A76148FF2C7000473EB /* main.c */, + 0CEF57FF14C0E227000A93B0 /* st_test.c */, + 0C7CF8D614E18A9F00DF9D95 /* dtls_client.c */, + ); + path = tlsnketest; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 0CC9A7EC146DF66000C18F89 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C38E43D14BF707500DD862C /* tlsnke.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0CDF469E14DC794300FFE2FD /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0CDF46A514DC795400FFE2FD /* tlssocket.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 0CC9A7EF146DF66000C18F89 /* tlsnke */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0CC9A800146DF66000C18F89 /* Build configuration list for PBXNativeTarget "tlsnke" */; + buildPhases = ( + 0CC9A7EA146DF66000C18F89 /* Sources */, + 0CC9A7EB146DF66000C18F89 /* Frameworks */, + 0CC9A7EC146DF66000C18F89 /* Headers */, + 0CC9A7ED146DF66000C18F89 /* Resources */, + 0CC9A7EE146DF66000C18F89 /* Rez */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = tlsnke; + productName = tlsnke; + productReference = 0CC9A7F0146DF66000C18F89 /* tlsnke.kext */; + productType = "com.apple.product-type.kernel-extension"; + }; + 0CDF469F14DC794300FFE2FD /* tlssocket */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0CDF46A114DC794300FFE2FD /* Build configuration list for PBXNativeTarget "tlssocket" */; + buildPhases = ( + 0CDF469C14DC794300FFE2FD /* Sources */, + 0CDF469D14DC794300FFE2FD /* Frameworks */, + 0CDF469E14DC794300FFE2FD /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = tlssocket; + productName = tlssocket; + productReference = 0CDF46A014DC794300FFE2FD /* libtlssocket.a */; + productType = "com.apple.product-type.library.static"; + }; + 0CE08A72148FF2C6000473EB /* tlsnketest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0CE08A7C148FF2C7000473EB /* Build configuration list for PBXNativeTarget "tlsnketest" */; + buildPhases = ( + 0CE08A6F148FF2C6000473EB /* Sources */, + 0CE08A70148FF2C6000473EB /* Frameworks */, + 0CE08A71148FF2C6000473EB /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + 0CDF46A814DC79FF00FFE2FD /* PBXTargetDependency */, + ); + name = tlsnketest; + productName = tlsnketest; + productReference = 0CE08A73148FF2C6000473EB /* tlsnketest */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 0CC9A7E5146DF66000C18F89 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0430; + ORGANIZATIONNAME = "Apple, Inc."; + }; + buildConfigurationList = 0CC9A7E8146DF66000C18F89 /* Build configuration list for PBXProject "tlsnke" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 0CC9A7E3146DF66000C18F89; + productRefGroup = 0CC9A7F1146DF66000C18F89 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 0CE08A7E148FF61C000473EB /* host-loadkext */, + 0CC9A7EF146DF66000C18F89 /* tlsnke */, + 0CE08A72148FF2C6000473EB /* tlsnketest */, + 0CDF469F14DC794300FFE2FD /* tlssocket */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 0CC9A7ED146DF66000C18F89 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0CC9A7FA146DF66000C18F89 /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXRezBuildPhase section */ + 0CC9A7EE146DF66000C18F89 /* Rez */ = { + isa = PBXRezBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXRezBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 0CE08A89148FF86C000473EB /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "sudo /var/root/loadkext.sh ${BUILT_PRODUCTS_DIR}/tlsnke.kext\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 0CC9A7EA146DF66000C18F89 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0CC9A7FC146DF66000C18F89 /* tlsnke.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0CDF469C14DC794300FFE2FD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0CDF46A414DC794F00FFE2FD /* tlssocket.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0CE08A6F148FF2C6000473EB /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0CE08A77148FF2C7000473EB /* main.c in Sources */, + 0CEF580014C0E227000A93B0 /* st_test.c in Sources */, + 0C7CF8D714E18A9F00DF9D95 /* dtls_client.c in Sources */, + 0C6C642715D5A9C200BC68CD /* ssl-utils.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 0CDF46A814DC79FF00FFE2FD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0CDF469F14DC794300FFE2FD /* tlssocket */; + targetProxy = 0CDF46A714DC79FF00FFE2FD /* PBXContainerItemProxy */; + }; + 0CE08A83148FF628000473EB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0CC9A7EF146DF66000C18F89 /* tlsnke */; + targetProxy = 0CE08A82148FF628000473EB /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 0CC9A7F8146DF66000C18F89 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 0CC9A7F9146DF66000C18F89 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 0CC9A7FE146DF66000C18F89 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + CLANG_STATIC_ANALYZER_MODE = deep; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + RUN_CLANG_STATIC_ANALYZER = YES; + SUPPORTED_PLATFORMS = "iphoneos macosx"; + }; + name = Debug; + }; + 0CC9A7FF146DF66000C18F89 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + CLANG_STATIC_ANALYZER_MODE = deep; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + RUN_CLANG_STATIC_ANALYZER = YES; + SUPPORTED_PLATFORMS = "iphoneos macosx"; + }; + name = Release; + }; + 0CC9A801146DF66000C18F89 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "tlsnke/tlsnke-Prefix.pch"; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/../libsecurity_ssl/lib", + /usr/local/include, + ); + INFOPLIST_FILE = "tlsnke/tlsnke-Info.plist"; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Extensions"; + MODULE_NAME = com.apple.nke.tls; + MODULE_START = tlsnke_start; + MODULE_STOP = tlsnke_stop; + MODULE_VERSION = 1.0; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = kext; + }; + name = Debug; + }; + 0CC9A802146DF66000C18F89 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "tlsnke/tlsnke-Prefix.pch"; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/../libsecurity_ssl/lib", + /usr/local/include, + ); + INFOPLIST_FILE = "tlsnke/tlsnke-Info.plist"; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Extensions"; + MODULE_NAME = com.apple.nke.tls; + MODULE_START = tlsnke_start; + MODULE_STOP = tlsnke_stop; + MODULE_VERSION = 1.0; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = kext; + }; + name = Release; + }; + 0CDF46A214DC794300FFE2FD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + EXECUTABLE_PREFIX = lib; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + ../libsecurity_ssl, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 0CDF46A314DC794300FFE2FD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + EXECUTABLE_PREFIX = lib; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + ../libsecurity_ssl, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 0CE08A7A148FF2C7000473EB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + HEADER_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)/usr/local/include"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(BUILT_PRODUCTS_DIR)", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 0CE08A7B148FF2C7000473EB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + HEADER_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)/usr/local/include"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(BUILT_PRODUCTS_DIR)", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 0CE08A80148FF61C000473EB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 0CE08A81148FF61C000473EB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 0CC9A7E8146DF66000C18F89 /* Build configuration list for PBXProject "tlsnke" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0CC9A7FE146DF66000C18F89 /* Debug */, + 0CC9A7FF146DF66000C18F89 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0CC9A800146DF66000C18F89 /* Build configuration list for PBXNativeTarget "tlsnke" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0CC9A801146DF66000C18F89 /* Debug */, + 0CC9A802146DF66000C18F89 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0CDF46A114DC794300FFE2FD /* Build configuration list for PBXNativeTarget "tlssocket" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0CDF46A214DC794300FFE2FD /* Debug */, + 0CDF46A314DC794300FFE2FD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0CE08A7C148FF2C7000473EB /* Build configuration list for PBXNativeTarget "tlsnketest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0CE08A7A148FF2C7000473EB /* Debug */, + 0CE08A7B148FF2C7000473EB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0CE08A7F148FF61C000473EB /* Build configuration list for PBXAggregateTarget "host-loadkext" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0CE08A80148FF61C000473EB /* Debug */, + 0CE08A81148FF61C000473EB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 0CC9A7E5146DF66000C18F89 /* Project object */; +} diff --git a/tlsnke/tlsnke.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Security/tlsnke/tlsnke.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from tlsnke/tlsnke.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to Security/tlsnke/tlsnke.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/tlsnke/tlsnke.xcodeproj/xcshareddata/xcschemes/Device.xcscheme b/Security/tlsnke/tlsnke.xcodeproj/xcshareddata/xcschemes/Device.xcscheme similarity index 96% rename from tlsnke/tlsnke.xcodeproj/xcshareddata/xcschemes/Device.xcscheme rename to Security/tlsnke/tlsnke.xcodeproj/xcshareddata/xcschemes/Device.xcscheme index 4a684220..91e2ef16 100644 --- a/tlsnke/tlsnke.xcodeproj/xcshareddata/xcschemes/Device.xcscheme +++ b/Security/tlsnke/tlsnke.xcodeproj/xcshareddata/xcschemes/Device.xcscheme @@ -1,6 +1,6 @@ + allowLocationSimulation = "YES" + showNonLocalizedStrings = "NO"> + allowLocationSimulation = "YES" + showNonLocalizedStrings = "NO"> + allowLocationSimulation = "YES" + showNonLocalizedStrings = "NO"> diff --git a/tlsnke/tlsnke.xcodeproj/xcshareddata/xcschemes/tlsnketest.xcscheme b/Security/tlsnke/tlsnke.xcodeproj/xcshareddata/xcschemes/tlsnketest.xcscheme similarity index 96% rename from tlsnke/tlsnke.xcodeproj/xcshareddata/xcschemes/tlsnketest.xcscheme rename to Security/tlsnke/tlsnke.xcodeproj/xcshareddata/xcschemes/tlsnketest.xcscheme index 1d30b00a..82c5adfb 100644 --- a/tlsnke/tlsnke.xcodeproj/xcshareddata/xcschemes/tlsnketest.xcscheme +++ b/Security/tlsnke/tlsnke.xcodeproj/xcshareddata/xcschemes/tlsnketest.xcscheme @@ -1,6 +1,6 @@ + allowLocationSimulation = "YES" + showNonLocalizedStrings = "NO"> #include diff --git a/Security/tlsnke/tlsnke/tlsnke.h b/Security/tlsnke/tlsnke/tlsnke.h new file mode 100644 index 00000000..3256dc43 --- /dev/null +++ b/Security/tlsnke/tlsnke/tlsnke.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef __TLSNKE_H__ +#define __TLSNKE_H__ + +/* Those should be defined in kernel headers eg */ + + +#define TLS_HANDLE_IP4 0xBABABABA /* Temp hack to identify this filter */ +#define TLS_HANDLE_IP6 0xABABABAB /* Temp hack to identify this filter */ + + +/* +SO_TLS_HANDLE: +Get the DTLS handle used to enable utun to dtls bypass. (getsockopt only) +option_value type: int +*/ +#define SO_TLS_HANDLE 0x20000 + +/* +SO_TLS_INIT_CIPHER: +Initialize the new cipher key material. (setsockopt only) +option_value type: +struct { + uint16_t cipherspec; + bool server; + int keylen; + char key[keylen]; +} +*/ +#define SO_TLS_INIT_CIPHER 0x20001 + +/* +SO_TLS_PROTOCOL_VERSION: +Set the protocol version. (setsockopt only) +option_value type: int +*/ +#define SO_TLS_PROTOCOL_VERSION 0x20002 + +/* +SO_TLS_ADVANCE_READ_CIPHER: +Update the read cipher to use the new key. (setsockopt only) +No option value. +*/ +#define SO_TLS_ADVANCE_READ_CIPHER 0x20003 + +/* +SO_TLS_ADVANCE_WRITE_CIPHER: +Update the write cipher to use the new key. (setsockopt only) +No option value. +*/ +#define SO_TLS_ADVANCE_WRITE_CIPHER 0x20004 + +/* +SO_TLS_ROLLBACK_WRITE_CIPHER: +Rollback the write cipher to the previous key. (setsockopt only) +No option value. +*/ +#define SO_TLS_ROLLBACK_WRITE_CIPHER 0x20005 + +/* + SO_TLS_SERVICE_WRITE_QUEUE: + Service the record write queue + No option value. + */ +#define SO_TLS_SERVICE_WRITE_QUEUE 0x20006 + + +/* +SCM_TLS_HEADER: + Type of anciallary data for DTLS record header +*/ + +#define SCM_TLS_HEADER 0x12345 + +typedef struct tls_record_hdr{ + uint8_t content_type; + uint16_t protocol_version; +} *tls_record_hdr_t; + + +#endif /* __TLSNKE_H__ */ diff --git a/tlsnke/tlsnketest/cert-1.h b/Security/tlsnke/tlsnketest/cert-1.h similarity index 100% rename from tlsnke/tlsnketest/cert-1.h rename to Security/tlsnke/tlsnketest/cert-1.h diff --git a/tlsnke/tlsnketest/dtls_client.c b/Security/tlsnke/tlsnketest/dtls_client.c similarity index 84% rename from tlsnke/tlsnketest/dtls_client.c rename to Security/tlsnke/tlsnketest/dtls_client.c index 1dc76b03..a889243a 100644 --- a/tlsnke/tlsnketest/dtls_client.c +++ b/Security/tlsnke/tlsnketest/dtls_client.c @@ -1,17 +1,32 @@ -// -// dtls_client.c -// tlsnke -// -// Created by Fabrice Gautier on 2/7/12. -// Copyright (c) 2012 Apple, Inc. All rights reserved. -// +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + /* * dtlsEchoClient.c * Security * - * Created by Fabrice Gautier on 1/31/11. - * Copyright 2011 Apple, Inc. All rights reserved. + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. * */ diff --git a/tlsnke/tlsnketest/identity-1.h b/Security/tlsnke/tlsnketest/identity-1.h similarity index 100% rename from tlsnke/tlsnketest/identity-1.h rename to Security/tlsnke/tlsnketest/identity-1.h diff --git a/Security/tlsnke/tlsnketest/main.c b/Security/tlsnke/tlsnketest/main.c new file mode 100644 index 00000000..583de681 --- /dev/null +++ b/Security/tlsnke/tlsnketest/main.c @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include "tlssocket.h" +#include "tlsnke.h" + + +static void print_data(const char *s, size_t l, const unsigned char *p) +{ + printf("%s, %zu:",s, l); + for(int i=0; ih_addr); + bzero(&(server_addr.sin_zero),8); + + err = connect(sock, (struct sockaddr *)&server_addr, + sizeof(struct sockaddr)); + if(err) + { + perror("connect"); + return err; + } + + return sock; +} + +/* simple test */ +static int kext_test(const char *hostname, int bypass) +{ + int sock, i; + char send_data[1024]; + int tlsfd; + pthread_t server_thread; + + if(strcmp(hostname, "localhost")==0) { + pthread_create(&server_thread, NULL, server_thread_func, NULL); + // Just wait for the server to be setup + sleep(1); + } + + + sock = create_client_socket(hostname); + + if(bypass) { + /* Have to open this after we attached the filter to the client socket */ + tlsfd=open("/dev/tlsnke", O_RDWR); + if(tlsfd<0) { + perror("open tlsnke"); + exit(1); + } + } + + + for(i=0; i<20;i++) { + int n; + ssize_t err; + n=sprintf(send_data, "Message #%d\n", i); + if(n<0) { + perror("sprintf"); + exit(1); + } + + printf("Client(1) sending %d bytes (\"%s\")\n", n, send_data); + + if(bypass) { + err = write(tlsfd, send_data, n); + if(err<0) { + perror("write to tlsnke"); + exit(1); + } + } else { + SSLRecord rec; + + rec.contentType = SSL_RecordTypeAppData; + rec.protocolVersion = DTLS_Version_1_0; + rec.contents.data = (uint8_t *)send_data; + rec.contents.length = n; + + err = TLSSocket_Funcs.write((intptr_t)sock, rec); + if(err<0) { + perror("write to socket"); + exit(1); + } + + /* serviceWriteQueue every 2 writes, this will trigger rdar://11348395 */ + if(i&1) { + int err; + err = TLSSocket_Funcs.serviceWriteQueue((intptr_t)sock); + if(err<0) { + perror("service write queue"); + exit(1); + } + } + } + + sleep(1); + } + + return 0; +} + + +/* handshake test */ +int st_test(); + +/* echo test */ +int dtls_client(const char *hostname, int bypass); + +static +int usage(const char *argv0) +{ + printf("Usage: %s \n", argv0); + printf(" : type of test: 's'imple, 'h'andshake or 'e'cho] (see below)\n"); + printf(" : hostname of server\n"); + printf(" : use /dev/tlsnke bypass test\n"); + + printf("\n 'S'imple test:\n" + "\tVery basic test with no handshake. DTLS packets are sent through the socket filter, non encrypted.\n" + "\tIf hostname is 'localhost', a local simple server will be created that will also use the tls filter,\n" + "\tsuch that the input path is tested.\n" + "\tOtherwise, a server on the other side is not required only the output path is tested. If there is no server replying\n" + "\tonly the ouput path will be tested. If a server is replying, input packet will be processed but are never read to userspace\n" + "\tif bypass=1, also send the same packet through the /dev/tlsnke interface, as if they were coming from utun\n"); + + printf("\n 'H'andshake:\n"); + printf("\tTest SSL Handshake with various ciphers, between a local client going through the tlsnke\n" + "\tfilter, and a local server using only the userland SecureTransport.\n" + "\thostname and bypass are ignored.\n"); + + printf("\n 'E'cho:\n"); + printf("\tTest to connect to an udp echo server indicated by hostname, on port 23232.\n" + "\tSet bypass=1 to use the /dev/tlsnke bsd device to send/recv the app data (emulate utun behaviour)\n"); + + printf("\n\tbypass=1 require the tlsnke kext to be compiled with TLS_TEST=1 (not the default in the build)\n"); + + return -1; +} + +int main (int argc, const char * argv[]) +{ + + printf("argv0=%s argc=%d\n", argv[0], argc); + if(argc<2) + return usage(argv[0]); + + switch (argv[1][0]) { + case 's': + case 'S': + if(argc<3) return usage(argv[0]); + return kext_test(argv[2], atoi(argv[3])?1:0); + case 'h': + case 'H': + return st_test(); + case 'e': + case 'E': + if(argc<3) return usage(argv[0]); + return dtls_client(argv[2], atoi(argv[3])?1:0); + default: + return usage(argv[0]); + } +} + diff --git a/tlsnke/tlsnketest/privkey-1.h b/Security/tlsnke/tlsnketest/privkey-1.h similarity index 100% rename from tlsnke/tlsnketest/privkey-1.h rename to Security/tlsnke/tlsnketest/privkey-1.h diff --git a/Security/tlsnke/tlsnketest/ssl-utils.c b/Security/tlsnke/tlsnketest/ssl-utils.c new file mode 100644 index 00000000..d9c87427 --- /dev/null +++ b/Security/tlsnke/tlsnketest/ssl-utils.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include + +#include "ssl-utils.h" + +#if TARGET_OS_IPHONE + + +#include +#include +#include +#include +#include + + +#include "privkey-1.h" +#include "cert-1.h" + +static +CFArrayRef chain_from_der(const unsigned char *cert_der, size_t cert_der_len, const unsigned char *pkey_der, size_t pkey_der_len) +{ + SecKeyRef pkey = NULL; + SecCertificateRef cert = NULL; + SecIdentityRef ident = NULL; + CFArrayRef items = NULL; + + require(pkey = SecKeyCreateRSAPrivateKey(kCFAllocatorDefault, pkey_der, pkey_der_len, kSecKeyEncodingPkcs1), errOut); + require(cert = SecCertificateCreateWithBytes(kCFAllocatorDefault, cert_der, cert_der_len), errOut); + require(ident = SecIdentityCreate(kCFAllocatorDefault, cert, pkey), errOut); + require(items = CFArrayCreate(kCFAllocatorDefault, (const void **)&ident, 1, &kCFTypeArrayCallBacks), errOut); + +errOut: + CFReleaseSafe(pkey); + CFReleaseSafe(cert); + CFReleaseSafe(ident); + return items; +} + +#else + +#include "identity-1.h" +#define P12_PASSWORD "password" + +static +CFArrayRef chain_from_p12(const unsigned char *p12_data, size_t p12_len) +{ + char keychain_path[] = "/tmp/keychain.XXXXXX"; + + SecKeychainRef keychain; + CFArrayRef list; + CFDataRef data; + + require_noerr(SecKeychainCopyDomainSearchList(kSecPreferencesDomainUser, &list), errOut); + require(mktemp(keychain_path), errOut); + require_noerr(SecKeychainCreate (keychain_path, strlen(P12_PASSWORD), P12_PASSWORD, + FALSE, NULL, &keychain), errOut); + require_noerr(SecKeychainSetDomainSearchList(kSecPreferencesDomainUser, list), errOut); // restores the previous search list + require(data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, p12_data, p12_len, kCFAllocatorNull), errOut); + + SecExternalFormat format=kSecFormatPKCS12; + SecExternalItemType type=kSecItemTypeAggregate; + SecItemImportExportFlags flags=0; + SecKeyImportExportParameters params = {0,}; + CFArrayRef out = NULL; + + params.passphrase=CFSTR("password"); + params.keyAttributes = CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_SENSITIVE; + + require_noerr(SecKeychainItemImport(data, CFSTR(".p12"), &format, &type, flags, + ¶ms, keychain, &out), errOut); + +errOut: + CFReleaseSafe(keychain); + CFReleaseSafe(list); + + return out; +} + +#endif + +CFArrayRef server_chain(void) +{ +#if TARGET_OS_IPHONE + return chain_from_der(privkey_1_der, privkey_1_der_len, cert_1_der, cert_1_der_len); +#else + return chain_from_p12(identity_1_p12, identity_1_p12_len); +#endif +} + +CFArrayRef client_chain(void) +{ +#if TARGET_OS_IPHONE + return chain_from_der(privkey_1_der, privkey_1_der_len, cert_1_der, cert_1_der_len); +#else + return chain_from_p12(identity_1_p12, identity_1_p12_len); +#endif +} + + diff --git a/Security/tlsnke/tlsnketest/ssl-utils.h b/Security/tlsnke/tlsnketest/ssl-utils.h new file mode 100644 index 00000000..a9009a0d --- /dev/null +++ b/Security/tlsnke/tlsnketest/ssl-utils.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef __SSL_UTILS_H__ +#define __SSL_UTILS_H__ + +#define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) { CFRelease(_cf); } } +#define CFReleaseNull(CF) { CFTypeRef _cf = (CF); if (_cf) { (CF) = NULL; CFRelease(_cf); } } + +CFArrayRef server_chain(void); +CFArrayRef client_chain(void); + +#endif diff --git a/tlsnke/tlsnketest/st_test.c b/Security/tlsnke/tlsnketest/st_test.c similarity index 96% rename from tlsnke/tlsnketest/st_test.c rename to Security/tlsnke/tlsnketest/st_test.c index 224373fe..e8e39131 100644 --- a/tlsnke/tlsnketest/st_test.c +++ b/Security/tlsnke/tlsnketest/st_test.c @@ -1,10 +1,26 @@ -// -// st_test.c -// tlsnke -// -// Created by Fabrice Gautier on 1/13/12. -// Copyright (c) 2012 Apple, Inc. All rights reserved. -// +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include @@ -56,7 +72,7 @@ can be looked up in ciphers(1). All SSL_DH_* and TLS_DH_* are disabled because neither openssl nor - securetranport support them: + securetransport support them: SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA, SSL_DH_DSS_WITH_DES_CBC_SHA, SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA, SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DH_RSA_WITH_DES_CBC_SHA, SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA, diff --git a/tlsnke/tlsnketest/tlssocket.c b/Security/tlsnke/tlsnketest/tlssocket.c similarity index 86% rename from tlsnke/tlsnketest/tlssocket.c rename to Security/tlsnke/tlsnketest/tlssocket.c index 03c6bb65..6f0e6622 100644 --- a/tlsnke/tlsnketest/tlssocket.c +++ b/Security/tlsnke/tlsnketest/tlssocket.c @@ -1,10 +1,26 @@ -// -// tlssocket.c -// tlsnke -// -// Created by Fabrice Gautier on 1/6/12. -// Copyright (c) 2012 Apple, Inc. All rights reserved. -// +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include #include @@ -276,6 +292,15 @@ int TLSSocket_ServiceWriteQueue(SSLRecordContextRef ref) } +static +int TLSSocket_SetOption(SSLRecordContextRef ref, + SSLRecordOption option, + bool value) +{ + /* This is not implemented, and is not needed for DTLS */ + return EINVAL; +} + const struct SSLRecordFuncs TLSSocket_Funcs = { .read = TLSSocket_Read, .write = TLSSocket_Write, @@ -286,6 +311,7 @@ const struct SSLRecordFuncs TLSSocket_Funcs = { .setProtocolVersion = TLSSocket_SetProtocolVersion, .free = TLSSocket_Free, .serviceWriteQueue = TLSSocket_ServiceWriteQueue, + .setOption = TLSSocket_SetOption, }; diff --git a/Security/tlsnke/tlsnketest/tlssocket.h b/Security/tlsnke/tlsnketest/tlssocket.h new file mode 100644 index 00000000..b68bfe90 --- /dev/null +++ b/Security/tlsnke/tlsnketest/tlssocket.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef __TLSSOCKET_H__ +#define __TLSSOCKET_H__ + +#include + +/* + Attach the TLS socket filter. + + This makes a socket a TLS socket by attaching the TLS socket filter to that socket. + Return a positive TLS handle or a negative error. + The return TLS handle can be used to route VPN data directly through this TLS + socket + */ +int TLSSocket_Attach(int socket); + +/* + Detach the TLS socket filter. + + Return 0 or negative error. + If the TLS Socket is used with SecureTransport, one should make sure + to tear down the SecureTransport session before calling this. + It is not required to use this, as closing the socket would have the same effect. +*/ +int TLSSocket_Detach(int socket); + +/* + Secure Transport Record Layer functions for TLS Sockets. + + To use SecureTransport with a TLS kernel socket, pass this to SSLSetRecordFuncs and + the socket descriptor to SSLSetRecordContext + */ +const struct SSLRecordFuncs TLSSocket_Funcs; + + +#endif diff --git a/Security/utilities/Regressions/su-05-cfwrappers.c b/Security/utilities/Regressions/su-05-cfwrappers.c new file mode 100644 index 00000000..8130711a --- /dev/null +++ b/Security/utilities/Regressions/su-05-cfwrappers.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include +#include + +#include "utilities_regressions.h" + +#define kCFWrappersTestCount 25 + +static CFDataRef *testCopyDataPtr(void) { + static CFDataRef sData = NULL; + if (!sData) + sData = CFDataCreate(kCFAllocatorDefault, NULL, 0); + else + CFRetain(sData); + return &sData; +} + +static void +test_object(CFDataRef data) { + CFDataRef myData = CFRetainSafe(data); + ok(CFEqual(myData, data), ""); + is(CFGetRetainCount(myData), 2, ""); + ok(CFReleaseNull(myData) == ((CFDataRef)(0)), ""); + is(myData, NULL, ""); + + is(CFGetRetainCount(data), 1); + CFRetainAssign(myData, data); + is(CFGetRetainCount(data), 2); + CFRetainAssign(myData, data); + is(CFGetRetainCount(data), 2); + CFRetainAssign(myData, NULL); + is(CFGetRetainCount(data), 1); + is(myData, NULL, ""); + + CFDataRef *pData = testCopyDataPtr(); + is(CFGetRetainCount(*pData), 1); + CFDataRef objects[10] = {}, *object = objects; + *object = *pData; + CFRetainAssign(*testCopyDataPtr(), *object++); + is(CFGetRetainCount(*pData), 2, "CFRetainAssign evaluates it's first argument argument %" PRIdCFIndex " times", CFGetRetainCount(*pData) - 1); + is(object - objects, 1, "CFRetainAssign evaluates it's second argument %td times", object - objects); + + is(CFGetRetainCount(data), 1); + CFAssignRetained(myData, data); + is(CFGetRetainCount(myData), 1); +} + +static void +test_null(void) { + CFTypeRef nullObject1 = NULL; + CFTypeRef nullObject2 = NULL; + + nullObject1 = CFRetainSafe(NULL); + + is(nullObject1, NULL, ""); + is(CFReleaseNull(nullObject1), NULL, "CFReleaseNull(nullObject1) returned"); + is(nullObject1, NULL); + is(CFReleaseSafe(nullObject1), NULL, "CFReleaseSafe(nullObject1) returned"); + is(CFReleaseSafe(NULL), NULL, "CFReleaseSafe(NULL)"); + is(CFReleaseNull(nullObject2), NULL, "CFReleaseNull(nullObject2) returned"); + is(nullObject2, NULL, "nullObject2 still NULL"); + + CFRetainAssign(nullObject2, nullObject1); + + CFTypeRef *object, objects[10] = {}; + + object = &objects[0]; + CFRetainSafe(*object++); + is(object - objects, 1, "CFRetainSafe evaluates it's argument %td times", object - objects); + + object = &objects[0]; + CFReleaseSafe(*object++); + is(object - objects, 1, "CFReleaseSafe evaluates it's argument %td times", object - objects); + + object = &objects[0]; + CFReleaseNull(*object++); + is(object - objects, 1, "CFReleaseNull evaluates it's argument %td times", object - objects); +} + +int +su_05_cfwrappers(int argc, char *const *argv) { + plan_tests(kCFWrappersTestCount); + + test_null(); + CFDataRef data = CFDataCreate(kCFAllocatorDefault, NULL, 0); + test_object(data); + CFReleaseNull(data); + ok(data == NULL, "data is NULL now"); + return 0; +} diff --git a/Security/utilities/Regressions/su-07-debugging.c b/Security/utilities/Regressions/su-07-debugging.c new file mode 100644 index 00000000..93543908 --- /dev/null +++ b/Security/utilities/Regressions/su-07-debugging.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + +#include +#include +#include + +#include "utilities_regressions.h" +#include "utilities/debugging.h" +#include "utilities/debugging_test.h" + +#define kTestCount (39) + +static void +tests(void) { + ok(IsScopeActive(ASL_LEVEL_ERR, NULL), "Errors are active by default"); + + ok(!IsScopeActive(ASL_LEVEL_INFO, CFSTR("testscope")), "scope is off"); + + ApplyScopeListForIDC("-first", kScopeIDXPC); + + ok(IsScopeActive(ASL_LEVEL_INFO, CFSTR("testscope")), "scope is on"); + ok(!IsScopeActive(ASL_LEVEL_INFO, CFSTR("first")), "scope is off"); + + ApplyScopeListForIDC("first", kScopeIDXPC); + + ok(IsScopeActive(ASL_LEVEL_INFO, CFSTR("first")), "scope is on"); + ok(!IsScopeActive(ASL_LEVEL_INFO, CFSTR("testscope")), "scope is off"); + + ApplyScopeListForIDC("testscope, bar, baz,frog", kScopeIDXPC); + + ok(IsScopeActive(ASL_LEVEL_INFO, CFSTR("testscope")), "scope is on"); + ok(IsScopeActive(ASL_LEVEL_INFO, CFSTR("bar")), "scope is on"); + ok(IsScopeActive(ASL_LEVEL_INFO, CFSTR("baz")), "scope is on"); + ok(IsScopeActive(ASL_LEVEL_INFO, CFSTR("frog")), "scope is on"); + ok(!IsScopeActive(ASL_LEVEL_INFO, CFSTR("bonzo")), "scope is off"); + ok(!IsScopeActive(ASL_LEVEL_INFO, CFSTR("nothing")), "scope is off"); + + ApplyScopeListForID(CFSTR("-bonzo, boy"), kScopeIDDefaults); + + ok(IsScopeActive(ASL_LEVEL_INFO, CFSTR("testscope")), "scope is on"); + ok(IsScopeActive(ASL_LEVEL_INFO, CFSTR("bar")), "scope is on"); + ok(IsScopeActive(ASL_LEVEL_INFO, CFSTR("baz")), "scope is on"); + ok(IsScopeActive(ASL_LEVEL_INFO, CFSTR("frog")), "scope is on"); + ok(!IsScopeActive(ASL_LEVEL_INFO, CFSTR("bonzo")), "scope is off"); + ok(IsScopeActive(ASL_LEVEL_INFO, CFSTR("nothing")), "scope is on"); + + ApplyScopeListForID(CFSTR(""), kScopeIDDefaults); + + ok(IsScopeActive(ASL_LEVEL_INFO, CFSTR("testscope")), "scope is on"); + ok(IsScopeActive(ASL_LEVEL_INFO, CFSTR("bar")), "scope is on"); + ok(IsScopeActive(ASL_LEVEL_INFO, CFSTR("baz")), "scope is on"); + ok(IsScopeActive(ASL_LEVEL_INFO, CFSTR("frog")), "scope is on"); + ok(!IsScopeActive(ASL_LEVEL_INFO, CFSTR("bonzo")), "scope is off"); + ok(!IsScopeActive(ASL_LEVEL_INFO, CFSTR("nothing")), "scope is on"); + + int value = ASL_LEVEL_NOTICE; + CFNumberRef noticeNumber = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &value); + + value = ASL_LEVEL_INFO; + CFNumberRef infoNumber = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &value); + + CFDictionaryRef settings_dictionary = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + CFSTR(ASL_STRING_DEBUG), CFSTR("-baz"), + CFSTR(ASL_STRING_WARNING), CFSTR("baz,bar"), + noticeNumber, CFSTR("bar"), + infoNumber, CFSTR("baz"), + NULL); + + ApplyScopeDictionaryForID(settings_dictionary, kScopeIDXPC); + + ok(!IsScopeActive(ASL_LEVEL_INFO, CFSTR("testscope")), "scope is off"); + ok(!IsScopeActive(ASL_LEVEL_INFO, CFSTR("bar")), "scope is off"); + ok(IsScopeActive(ASL_LEVEL_INFO, CFSTR("baz")), "scope is on"); + + ok(!IsScopeActive(ASL_LEVEL_NOTICE, CFSTR("testscope")), "scope is off"); + ok(IsScopeActive(ASL_LEVEL_NOTICE, CFSTR("bar")), "scope is on"); + ok(!IsScopeActive(ASL_LEVEL_NOTICE, CFSTR("baz")), "scope is off"); + + ok(!IsScopeActive(ASL_LEVEL_WARNING, CFSTR("testscope")), "scope is off"); + ok(IsScopeActive(ASL_LEVEL_WARNING, CFSTR("bar")), "scope is on"); + ok(IsScopeActive(ASL_LEVEL_WARNING, CFSTR("baz")), "scope is on"); + + ok(IsScopeActive(ASL_LEVEL_DEBUG, CFSTR("testscope")), "scope is on"); + ok(IsScopeActive(ASL_LEVEL_DEBUG, CFSTR("bar")), "scope is on"); + ok(!IsScopeActive(ASL_LEVEL_DEBUG, CFSTR("baz")), "scope is off"); + + ok(!IsScopeActive(ASL_LEVEL_ALERT, CFSTR("testscope")), "scope is off"); + ok(!IsScopeActive(ASL_LEVEL_ALERT, CFSTR("bar")), "scope is off"); + ok(!IsScopeActive(ASL_LEVEL_ALERT, CFSTR("baz")), "scope is off"); + + CFReleaseSafe(noticeNumber); + CFReleaseSafe(infoNumber); + CFReleaseSafe(settings_dictionary); + + ApplyScopeListForIDC("", kScopeIDXPC); + ApplyScopeListForIDC("", kScopeIDDefaults); + +} + +#if !defined(NDEBUG) +#define kTestLogCount (6 + 5) +#else +#define kTestLogCount (6 + 1) +#endif + +static void +testLog() +{ + int value = ASL_LEVEL_NOTICE; + CFNumberRef noticeNumber = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &value); + + value = ASL_LEVEL_INFO; + CFNumberRef infoNumber = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &value); + + CFDictionaryRef settings_dictionary = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, + CFSTR(ASL_STRING_DEBUG), CFSTR("-baz"), + CFSTR(ASL_STRING_WARNING), CFSTR("baz,bar"), + noticeNumber, CFSTR("-bar"), + infoNumber, CFSTR("baz"), + NULL); + + + ApplyScopeDictionaryForID(settings_dictionary, kScopeIDXPC); + + __block int level = -1; + __block CFStringRef scope = NULL; + __block CFStringRef message = NULL; + __block CFStringRef file = NULL; + __block CFStringRef function = NULL; + __block int line = 0; + + __block bool called = false; + + security_log_handler verify = ^(int level_sent, CFStringRef scope_sent, const char *functionC, + const char *fileC, int line_sent, CFStringRef message_sent) { + called = true; + + level = level_sent; + scope = CFRetainSafe(scope_sent); + file = CFStringCreateWithCString(kCFAllocatorDefault, fileC, kCFStringEncodingUTF8); + function = CFStringCreateWithCString(kCFAllocatorDefault, functionC, kCFStringEncodingUTF8); + line = line_sent; + message = CFRetainSafe(message_sent); + }; + + add_security_log_handler(verify); + + called = false; CFReleaseNull(scope); CFReleaseNull(message); CFReleaseNull(file); CFReleaseNull(function); level = -1; line = 0; + + secdebug("bar", "Get this!"); + +#if !defined(NDEBUG) + is(called, true, "Handler called"); + is(level, ASL_LEVEL_DEBUG, "level"); + eq_cf(scope, CFSTR("bar"), "Scope"); + eq_cf(message, CFSTR("Get this!"), "message"); + eq_cf(function, CFSTR("testLog"), "function"); +#else + is(called, false, "Handler not called"); +#endif + + called = false; + CFReleaseNull(scope); + CFReleaseNull(message); + CFReleaseNull(function); + + secnotice("bunz", "Get this, too!"); + + is(called, true, "Handler called"); + is(level, ASL_LEVEL_NOTICE, "level"); + eq_cf(scope, CFSTR("bunz"), "Scope"); + eq_cf(message, CFSTR("Get this, too!"), "message"); + eq_cf(function, CFSTR("testLog"), "function"); + + CFReleaseNull(scope); + CFReleaseNull(message); + CFReleaseNull(function); + + remove_security_log_handler(verify); + + CFReleaseSafe(settings_dictionary); + CFReleaseSafe(infoNumber); + CFReleaseSafe(noticeNumber); + + CFPropertyListRef result = CopyCurrentScopePlist(); + + ok(result, "exported"); + + CFReleaseSafe(result); +} + +int +su_07_debugging(int argc, char *const *argv) { + plan_tests(kTestCount + kTestLogCount); + tests(); + testLog(); + + return 0; +} diff --git a/Security/utilities/Regressions/su-10-cfstring-der.c b/Security/utilities/Regressions/su-10-cfstring-der.c new file mode 100644 index 00000000..98176101 --- /dev/null +++ b/Security/utilities/Regressions/su-10-cfstring-der.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include "utilities/der_plist.h" +#include "utilities/der_plist_internal.h" + +#include "utilities/SecCFRelease.h" +#include "utilities/array_size.h" + +#include + +#include "utilities_regressions.h" + + +#define kMaxResultSize 256 + +struct test_case { + CFStringRef str; + size_t size; + uint8_t res[kMaxResultSize]; +}; + +static struct test_case test_cases[] = { + { .str = CFSTR("FOO"), .size = 5, .res = { 0x0C, 0x03, 0x46, 0x4F, 0x4F, } }, + { .str = CFSTR("!ß∂ƒ˙圈ø¥®xzfff"), .size = 29, .res = { 0x0C, 0x1B, 0x21, 0xC3, 0x9F, 0xE2, 0x88, 0x82, 0xC6, 0x92, + 0xCB, 0x99, 0xC3, 0xA5, 0xC5, 0x93, 0xCB, 0x86, 0xC3, 0xB8, + 0xC2, 0xA5, 0xC2, 0xAE, 0x78, 0x7A, 0x66, 0x66, 0x66, } }, +}; + + +#define kTestsPerTestCase 8 +static void one_test(const struct test_case * thisCase) +{ + uint8_t buffer[4 * kMaxResultSize + 1]; + uint8_t* buffer_end = buffer + sizeof(buffer); + + uint8_t* encoded = der_encode_string(thisCase->str, NULL, buffer, buffer_end); + + ok(encoded != NULL && + (thisCase->size == (buffer_end - encoded)) && + (memcmp(encoded, thisCase->res, thisCase->size) == 0)); + + CFStringRef decoded = NULL; + + const uint8_t* decode_end = der_decode_string(NULL, kCFPropertyListMutableContainersAndLeaves, + &decoded, NULL, encoded, buffer_end); + + ok(decode_end == buffer_end); + ok((decoded != NULL) && CFEqual(decoded, thisCase->str)); + + encoded = der_encode_plist(thisCase->str, NULL, buffer, buffer_end); + + ok(encoded != NULL && + (thisCase->size == (buffer_end - encoded)) && + (memcmp(encoded, thisCase->res, thisCase->size) == 0)); + + CFTypeRef decoded_type = NULL; + + decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainersAndLeaves, + &decoded_type, NULL, encoded, buffer_end); + + ok(decode_end == buffer_end); + ok((decoded_type != NULL) && CFEqual(decoded_type, thisCase->str)); + + ok(der_sizeof_string(thisCase->str, NULL) == thisCase->size); + ok(der_sizeof_plist(thisCase->str, NULL) == thisCase->size); + + CFReleaseNull(decoded); + CFReleaseNull(decoded_type); +} + +#define kTestCount (array_size(test_cases) * kTestsPerTestCase) +static void tests(void) +{ + for (int testnumber = 0; testnumber < array_size(test_cases); ++testnumber) + one_test(test_cases + testnumber); +} + +int su_10_cfstring_der(int argc, char *const *argv) +{ + plan_tests(kTestCount); + tests(); + + return 0; +} diff --git a/utilities/Regressions/su-11-cfdata-der.c b/Security/utilities/Regressions/su-11-cfdata-der.c similarity index 88% rename from utilities/Regressions/su-11-cfdata-der.c rename to Security/utilities/Regressions/su-11-cfdata-der.c index 34b5fcac..ceeeddf9 100644 --- a/utilities/Regressions/su-11-cfdata-der.c +++ b/Security/utilities/Regressions/su-11-cfdata-der.c @@ -1,10 +1,26 @@ -// -// su-11-cfdata-der.c -// utilities -// -// Created by Mitch Adler on 6/20/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include "utilities/der_plist.h" #include "utilities/der_plist_internal.h" diff --git a/Security/utilities/Regressions/su-12-cfboolean-der.c b/Security/utilities/Regressions/su-12-cfboolean-der.c new file mode 100644 index 00000000..ed6fe783 --- /dev/null +++ b/Security/utilities/Regressions/su-12-cfboolean-der.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include "utilities/der_plist.h" +#include "utilities/der_plist_internal.h" + +#include "utilities/SecCFRelease.h" +#include "utilities/array_size.h" + +#include + +#include "utilities_regressions.h" + +#define kMaxResultSize 16 + +#define kTestsPerTestCase 8 +static void one_test(CFBooleanRef value, size_t der_size, const uint8_t *expected_der) +{ + + uint8_t buffer[kMaxResultSize]; + uint8_t *buffer_end = buffer + sizeof(buffer); + + uint8_t* encoded = der_encode_plist(value, NULL, buffer, buffer_end); + + ok(encoded != NULL && + (der_size == (buffer_end - encoded)) && + (memcmp(encoded, expected_der, der_size) == 0)); + + encoded = der_encode_boolean(value, NULL, buffer, buffer_end); + + ok(encoded != NULL && + (der_size == (buffer_end - encoded)) && + (memcmp(encoded, expected_der, der_size) == 0)); + +#if 0 + printf(".size = %d, .res = { ", (buffer_end - encoded)); + for(int c = 0; c < (buffer_end - encoded); ++c) + printf("0x%02X, ", encoded[c]); + printf("},\n"); +#endif + + CFBooleanRef decoded = NULL; + const uint8_t* decode_end = der_decode_boolean(NULL, kCFPropertyListMutableContainersAndLeaves, + &decoded, NULL, encoded, buffer_end); + + ok(decode_end == buffer_end); + ok((decoded != NULL) && CFEqual(decoded, value)); + + CFPropertyListRef decoded_type = NULL; + decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainersAndLeaves, + &decoded_type, NULL, encoded, buffer_end); + + ok(decode_end == buffer_end); + ok((decoded != NULL) && CFEqual(decoded_type, value)); + + ok(der_sizeof_boolean(value, NULL) == der_size); + ok(der_sizeof_plist(value, NULL) == der_size); + + CFReleaseNull(decoded); + CFReleaseNull(decoded_type); +} + +#define kTestCount (2 * kTestsPerTestCase) +static void tests(void) +{ + const uint8_t der_true[] = { 0x01, 0x01, 0x01 }; + + one_test(kCFBooleanTrue, sizeof(der_true), der_true); + + const uint8_t der_false[] = { 0x01, 0x01, 0x00 }; + + one_test(kCFBooleanFalse, sizeof(der_false), der_false); +} + +int su_12_cfboolean_der(int argc, char *const *argv) +{ + plan_tests(kTestCount); + tests(); + + return 0; +} diff --git a/utilities/Regressions/su-13-cfnumber-der.c b/Security/utilities/Regressions/su-13-cfnumber-der.c similarity index 77% rename from utilities/Regressions/su-13-cfnumber-der.c rename to Security/utilities/Regressions/su-13-cfnumber-der.c index d9bc0c4d..8eb5d038 100644 --- a/utilities/Regressions/su-13-cfnumber-der.c +++ b/Security/utilities/Regressions/su-13-cfnumber-der.c @@ -1,10 +1,26 @@ -// -// su-13-cfnumber-der.c -// utilities -// -// Created by Mitch Adler on 6/20/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include "utilities/der_plist.h" #include "utilities/der_plist_internal.h" diff --git a/utilities/Regressions/su-14-cfarray-der.c b/Security/utilities/Regressions/su-14-cfarray-der.c similarity index 77% rename from utilities/Regressions/su-14-cfarray-der.c rename to Security/utilities/Regressions/su-14-cfarray-der.c index 1763a1b4..5627a9db 100644 --- a/utilities/Regressions/su-14-cfarray-der.c +++ b/Security/utilities/Regressions/su-14-cfarray-der.c @@ -1,10 +1,26 @@ -// -// su-14-cfarray-der.c -// utilities -// -// Created by Mitch Adler on 6/20/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include "utilities/der_plist.h" #include "utilities/der_plist_internal.h" diff --git a/utilities/Regressions/su-15-cfdictionary-der.c b/Security/utilities/Regressions/su-15-cfdictionary-der.c similarity index 86% rename from utilities/Regressions/su-15-cfdictionary-der.c rename to Security/utilities/Regressions/su-15-cfdictionary-der.c index f414e629..945bf3fe 100644 --- a/utilities/Regressions/su-15-cfdictionary-der.c +++ b/Security/utilities/Regressions/su-15-cfdictionary-der.c @@ -1,10 +1,26 @@ -// -// su-15-cfdictionary-der.c -// utilities -// -// Created by Mitch Adler on 6/20/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include "utilities_regressions.h" diff --git a/utilities/Regressions/su-16-cfdate-der.c b/Security/utilities/Regressions/su-16-cfdate-der.c similarity index 87% rename from utilities/Regressions/su-16-cfdate-der.c rename to Security/utilities/Regressions/su-16-cfdate-der.c index 9cd41607..86080d0e 100644 --- a/utilities/Regressions/su-16-cfdate-der.c +++ b/Security/utilities/Regressions/su-16-cfdate-der.c @@ -1,10 +1,26 @@ -// -// su-16-cfdate-der.c -// utilities -// -// Created by Michael Brouwer on 7/10/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include "utilities/der_plist.h" #include "utilities/der_plist_internal.h" @@ -61,8 +77,9 @@ static struct test_case test_cases[] = static CFStringRef string_create_with_hex(const uint8_t* start, const uint8_t* end) { CFMutableStringRef s = CFStringCreateMutable(NULL, 0); CFStringAppendFormat(s, 0, CFSTR(".size = %" PRIdPTR ", .res = { "), (intptr_t)(end - start)); - while (start < end) - CFStringAppendFormat(s, 0, CFSTR("0x%02X, "), *start++); + if (start) + while (start < end) + CFStringAppendFormat(s, 0, CFSTR("0x%02X, "), *start++); CFStringAppend(s, CFSTR("},\n")); return s; } diff --git a/utilities/Regressions/su-40-secdb.c b/Security/utilities/Regressions/su-40-secdb.c similarity index 87% rename from utilities/Regressions/su-40-secdb.c rename to Security/utilities/Regressions/su-40-secdb.c index 6a60617b..4202b53b 100644 --- a/utilities/Regressions/su-40-secdb.c +++ b/Security/utilities/Regressions/su-40-secdb.c @@ -1,10 +1,26 @@ -// -// su-40-secdb.c -// utilities -// -// Created by Michael Brouwer on 11/15/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include #include @@ -94,6 +110,7 @@ static void tests(void) CFStringRef dbName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s/Library/Keychains/su-40-sqldb.db"), home_var ? home_var : ""); SecDbRef db = SecDbCreate(dbName, NULL); + CFReleaseNull(dbName); ok(db, "SecDbCreate"); __block CFErrorRef error = NULL; diff --git a/utilities/Regressions/su-41-secdb-stress.c b/Security/utilities/Regressions/su-41-secdb-stress.c similarity index 86% rename from utilities/Regressions/su-41-secdb-stress.c rename to Security/utilities/Regressions/su-41-secdb-stress.c index f348604f..e682c7d3 100644 --- a/utilities/Regressions/su-41-secdb-stress.c +++ b/Security/utilities/Regressions/su-41-secdb-stress.c @@ -1,10 +1,26 @@ -// -// su-41-secdb-stress.c -// utilities -// -// Created by Michael Brouwer on 7/25/13. -// Copyright (c) 2013 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include #include @@ -15,7 +31,7 @@ #include "utilities_regressions.h" #include -#define kTestCount 3415 +#define kTestCount 3417 // Queue to protect counters and test_ok invocations static dispatch_queue_t count_queue; @@ -223,8 +239,13 @@ static void tests(void) dispatch_release_null(count_queue); is(max_idle, kSecDbMaxIdleHandles, "max idle connection count is %d", kSecDbMaxIdleHandles); - is(max_writers, kSecDbMaxWriters, "max writers is %d", kSecDbMaxWriters); - is(max_readers, kSecDbMaxReaders, "max readers is %d", kSecDbMaxReaders); + cmp_ok(max_writers, >=, kSecDbMaxWriters - 1, "max writers at least %d", kSecDbMaxWriters - 1); + cmp_ok(max_readers, >=, kSecDbMaxReaders - 1, "max readers at least %d", kSecDbMaxReaders - 1); + TODO: { + todo("race conditions make us not always hit the limits reliably."); + is(max_writers, kSecDbMaxWriters, "max writers is %d", kSecDbMaxWriters); + is(max_readers, kSecDbMaxReaders, "max readers is %d", kSecDbMaxReaders); + } CFReleaseNull(db); } diff --git a/utilities/Regressions/utilities_regressions.h b/Security/utilities/Regressions/utilities_regressions.h similarity index 88% rename from utilities/Regressions/utilities_regressions.h rename to Security/utilities/Regressions/utilities_regressions.h index 6b34bcc2..a106c681 100644 --- a/utilities/Regressions/utilities_regressions.h +++ b/Security/utilities/Regressions/utilities_regressions.h @@ -4,6 +4,8 @@ */ #include +ONE_TEST(su_07_debugging) +ONE_TEST(su_05_cfwrappers) ONE_TEST(su_10_cfstring_der) ONE_TEST(su_11_cfdata_der) ONE_TEST(su_12_cfboolean_der) diff --git a/Security/utilities/SecLogging.mobileconfig b/Security/utilities/SecLogging.mobileconfig new file mode 100644 index 00000000..b851948b --- /dev/null +++ b/Security/utilities/SecLogging.mobileconfig @@ -0,0 +1,53 @@ + + + + + PayloadIdentifier + com.apple.security.logging + PayloadUUID + B4F88847-3A51-4B9D-A2EB-44D7481D1525 + + PayloadDescription + Sets defaults + PayloadDisplayName + Security Logging Defaults - Test Profile + PayloadOrganization + Apple, Inc + PayloadType + Configuration + PayloadVersion + 1 + + DurationUntilRemoval + 259200 + + PayloadContent + + + PayloadUUID + 65DB0454-B417-4F10-92DE-1EB5F8F997FF + PayloadIdentifier + com.apple.defaults.1 + PayloadType + com.apple.defaults.managed + PayloadVersion + 1 + PayloadContent + + + + + DefaultsDomainName + .GlobalPreferences + DefaultsData + + SecLogLevel + 7 + + + + + + + + diff --git a/Security/utilities/SecurityTool/not_on_this_platorm.c b/Security/utilities/SecurityTool/not_on_this_platorm.c new file mode 100644 index 00000000..26d0d70b --- /dev/null +++ b/Security/utilities/SecurityTool/not_on_this_platorm.c @@ -0,0 +1,30 @@ +/* + * 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@ + */ + + +int command_not_on_this_platform(int argc, char * const *argv); + +int command_not_on_this_platform(int argc, char * const *argv) +{ + return 0; +} diff --git a/Security/utilities/SecurityTool/readline.c b/Security/utilities/SecurityTool/readline.c new file mode 100644 index 00000000..14ef05ef --- /dev/null +++ b/Security/utilities/SecurityTool/readline.c @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2003-2004,2006-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@ + * + * readline.c + */ + +#include "readline.h" + +#include +#include +#include +#include +#include +#include + +/* Inspects a file's existence and size. Returns a file handle or -1 on failure */ +int inspect_file_and_size(const char* name, off_t *out_off_end) { + + int fd, result; + off_t off_end; + + do { + fd = open(name, O_RDONLY, 0); + } while (fd == -1 && errno == EINTR); + + if (fd == -1) + { + fprintf(stderr, "open %s: %s", name, strerror(errno)); + result = -1; + goto loser; + } + + off_end = lseek(fd, 0, SEEK_END); + if (off_end == -1) + { + fprintf(stderr, "lseek %s, SEEK_END: %s", name, strerror(errno)); + result = -1; + goto loser; + } + + if (off_end > (unsigned)SIZE_MAX) { + fprintf(stderr, "file %s too large %llu bytes", name, off_end); + result = -1; + goto loser; + } + + if (out_off_end) { + *out_off_end = off_end; + } + + return fd; + +loser: + return result; +} + + +/* Read a line from stdin into buffer as a null terminated string. If buffer is + non NULL use at most buffer_size bytes and return a pointer to buffer. Otherwise + return a newly malloced buffer. + if EOF is read this function returns NULL. */ +char * +readline(char *buffer, int buffer_size) +{ + int ix = 0, bytes_malloced = 0; + + if (!buffer) + { + bytes_malloced = 64; + buffer = (char *)malloc(bytes_malloced); + buffer_size = bytes_malloced; + } + + for (;;++ix) + { + int ch; + + if (ix == buffer_size - 1) + { + if (!bytes_malloced) + break; + bytes_malloced += bytes_malloced; + buffer = (char *)realloc(buffer, bytes_malloced); + buffer_size = bytes_malloced; + } + + ch = getchar(); + if (ch == EOF) + { + if (bytes_malloced) + free(buffer); + return NULL; + } + if (ch == '\n') + break; + buffer[ix] = ch; + } + + /* 0 terminate buffer. */ + buffer[ix] = '\0'; + + return buffer; +} + +/* Read the file name into buffer. On return buffer contains a newly + malloced buffer or length buffer_size. Return 0 on success and -1 on failure. */ +int +read_file(const char *name, uint8_t **outData, size_t *outLength) +{ + int fd, result; + char *buffer = NULL; + off_t off_end; + ssize_t bytes_read; + size_t length; + + if( (fd = inspect_file_and_size(name, &off_end)) == -1 ){ + result = -1; + goto loser; + } + + length = (size_t)off_end; + buffer = malloc(length); + + do { + bytes_read = pread(fd, buffer, length, 0); + } while (bytes_read == -1 && errno == EINTR); + + if (bytes_read == -1) + { + fprintf(stderr, "pread %s: %s", name, strerror(errno)); + result = -1; + goto loser; + } + if (bytes_read != (ssize_t)length) + { + fprintf(stderr, "read %s: only read %zu of %zu bytes", name, bytes_read, length); + result = -1; + goto loser; + } + + do { + result = close(fd); + } while (result == -1 && errno == EINTR); + + if (result == -1) + { + fprintf(stderr, "close %s: %s", name, strerror(errno)); + goto loser; + } + + *outData = (uint8_t *)buffer; + *outLength = length; + + return result; + +loser: + if (buffer) + free(buffer); + + return result; +} + +CFDataRef copyFileContents(const char *path) { + CFMutableDataRef data = NULL; + int fd = open(path, O_RDONLY, 0666); + if (fd == -1) { + fprintf(stderr, "open %s: %s", path, strerror(errno)); + goto badFile; + } + + off_t fsize = lseek(fd, 0, SEEK_END); + if (fsize == (off_t)-1) { + fprintf(stderr, "lseek %s, 0, SEEK_END: %s", path, strerror(errno)); + goto badFile; + } + + if (fsize > (off_t)INT32_MAX) { + fprintf(stderr, "file %s too large %llu bytes", path, fsize); + goto badFile; + } + + data = CFDataCreateMutable(kCFAllocatorDefault, (CFIndex)fsize); + CFDataSetLength(data, (CFIndex)fsize); + void *buf = CFDataGetMutableBytePtr(data); + off_t total_read = 0; + while (total_read < fsize) { + ssize_t bytes_read; + + bytes_read = pread(fd, buf, (size_t)(fsize - total_read), total_read); + if (bytes_read == -1) { + fprintf(stderr, "read %s: %s", path, strerror(errno)); + goto badFile; + } + if (bytes_read == 0) { + fprintf(stderr, "read %s: unexpected end of file", path); + goto badFile; + } + total_read += bytes_read; + } + + if (close(fd) == -1) { + fprintf(stderr, "close %s: %s", path, strerror(errno)); + /* Failure to close the file isn't fatal. */ + } + + return data; +badFile: + if (fd != -1) { + if (close(fd) == -1) { + fprintf(stderr, "close %s: %s", path, strerror(errno)); + } + } + if (data) + CFRelease(data); + return NULL; +} + + +bool writeFileContents(const char *path, CFDataRef data) { + int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd == -1) { + fprintf(stderr, "open %s: %s", path, strerror(errno)); + goto badFile; + } + + const void *buf = CFDataGetBytePtr(data); + off_t fsize = CFDataGetLength(data); + + off_t total_write = 0; + while (total_write < fsize) { + ssize_t bytes_write; + + bytes_write = pwrite(fd, buf, (size_t)(fsize - total_write), total_write); + if (bytes_write == -1) { + fprintf(stderr, "write %s: %s", path, strerror(errno)); + goto badFile; + } + if (bytes_write == 0) { + fprintf(stderr, "write %s: unexpected end of file", path); + goto badFile; + } + total_write += bytes_write; + } + + if (close(fd) == -1) { + fprintf(stderr, "close %s: %s", path, strerror(errno)); + /* Failure to close the file isn't fatal. */ + } + + return true; +badFile: + if (fd != -1) { + if (close(fd) == -1) { + fprintf(stderr, "close %s: %s", path, strerror(errno)); + } + } + if (data) + CFRelease(data); + return false; +} diff --git a/Security/utilities/SecurityTool/readline.h b/Security/utilities/SecurityTool/readline.h new file mode 100644 index 00000000..20fa4e4b --- /dev/null +++ b/Security/utilities/SecurityTool/readline.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2003-2004,2006-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@ + * + * readline.h + */ + +#ifndef _READLINE_H_ +#define _READLINE_H_ 1 + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Inspects a file's existence and size. Returns a file handle or -1 on failure */ +extern int inspect_file_and_size(const char* name, off_t *out_off_end); + +/* Read a line from stdin into buffer as a null terminated string. If buffer is + non NULL use at most buffer_size bytes and return a pointer to buffer. Otherwise + return a newly malloced buffer. + if EOF is read this function returns NULL. */ +extern char *readline(char *buffer, int buffer_size); + +/* Read the file name into buffer. On return outData.Data contains a newly + malloced buffer of outData.Length bytes. Return 0 on success and -1 on failure. */ +extern int read_file(const char *name, uint8_t **outData, size_t *outLength); + +extern CFDataRef copyFileContents(const char *path); + +extern bool writeFileContents(const char *path, CFDataRef data); + +#ifdef __cplusplus +} +#endif + +#endif /* _READLINE_H_ */ diff --git a/Security/utilities/SecurityTool/security_tool_commands.h b/Security/utilities/SecurityTool/security_tool_commands.h new file mode 100644 index 00000000..7e01dfc6 --- /dev/null +++ b/Security/utilities/SecurityTool/security_tool_commands.h @@ -0,0 +1,44 @@ +/* + * 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 included to make SECURITY_COMMAND macros result in declarations of +// commands for use in SecurityTool + +#ifndef SECURITY_COMMAND +#define SECURITY_COMMAND(name, function, parameters, description) int function(int argc, char * const *argv); + +#if TARGET_OS_EMBEDDED +#define SECURITY_COMMAND_IOS(name, function, parameters, description) int function(int argc, char * const *argv); +#else +#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)) +#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); +#endif + + +#endif diff --git a/Security/utilities/SecurityTool/security_tool_commands_table.h b/Security/utilities/SecurityTool/security_tool_commands_table.h new file mode 100644 index 00000000..844f225b --- /dev/null +++ b/Security/utilities/SecurityTool/security_tool_commands_table.h @@ -0,0 +1,45 @@ +/* + * 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 included to make SECURITY_COMMAND macros result in table of +// commands for use in SecurityTool + +#undef SECURITY_COMMAND +#undef SECURITY_COMMAND_IOS +#undef SECURITY_COMMAND_MAC +#define SECURITY_COMMAND(name, function, parameters, description) { name, function, parameters, description }, + +#if TARGET_OS_EMBEDDED +#define SECURITY_COMMAND_IOS(name, function, parameters, description) { name, function, parameters, description }, +#else +#define SECURITY_COMMAND_IOS(name, function, parameters, description) { name, command_not_on_this_platform, "", "Not available on this platform" }, +#endif + +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) +#define SECURITY_COMMAND_MAC(name, function, parameters, description) { name, function, parameters, description }, +#else +#define SECURITY_COMMAND_MAC(name, function, parameters, description) { name, command_not_on_this_platform, "", "Not available on this platform" }, +#endif + diff --git a/Security/utilities/config/lib.xcconfig b/Security/utilities/config/lib.xcconfig new file mode 100644 index 00000000..21200259 --- /dev/null +++ b/Security/utilities/config/lib.xcconfig @@ -0,0 +1,2 @@ +COPY_PHASE_STRIP = NO +SKIP_INSTALL = YES diff --git a/utilities/src/SecAKSWrappers.c b/Security/utilities/src/SecAKSWrappers.c similarity index 97% rename from utilities/src/SecAKSWrappers.c rename to Security/utilities/src/SecAKSWrappers.c index 037fa4d3..48d9409a 100644 --- a/utilities/src/SecAKSWrappers.c +++ b/Security/utilities/src/SecAKSWrappers.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2013 Apple Inc. All rights reserved. + * 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, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/Security/utilities/src/SecAKSWrappers.h b/Security/utilities/src/SecAKSWrappers.h new file mode 100644 index 00000000..ba3382b2 --- /dev/null +++ b/Security/utilities/src/SecAKSWrappers.h @@ -0,0 +1,121 @@ +/* + * 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@ + */ + + +#ifndef _SECAKSWRAPPERS_H_ +#define _SECAKSWRAPPERS_H_ + +#include +#include +#include + +#if TARGET_IPHONE_SIMULATOR + +#include + +// Make the compiler happy so this will compile. +#define device_keybag_handle 0 +#define session_keybag_handle 0 + +enum keybag_state { + keybag_state_unlocked = 0, + keybag_state_locked = 1 << 0, + keybag_state_no_pin = 1 << 1, + keybag_state_been_unlocked = 1 << 2, +}; +typedef uint32_t keybag_state_t; +typedef int32_t keybag_handle_t; + +static kern_return_t aks_get_lock_state(keybag_handle_t handle, keybag_state_t *state) { + if (state) *state = keybag_state_no_pin & keybag_state_been_unlocked; + return kIOReturnSuccess; +} + +#else + +#include + +#endif + +// +// MARK: User lock state +// + +enum { + user_keybag_handle = TARGET_OS_EMBEDDED ? device_keybag_handle : session_keybag_handle, +}; + +extern const char * const kUserKeybagStateChangeNotification; + +static inline bool SecAKSGetLockedState(keybag_state_t *state, CFErrorRef* error) +{ + kern_return_t status = aks_get_lock_state(user_keybag_handle, state); + + if (kIOReturnSuccess != status) { + SecCFCreateError(status, CFSTR("com.apple.kern_return_t"), CFSTR("Kern return error"), NULL, error); + return false; + } + + return true; +} + +// returns true if any of the bits in bits is set in the current state of the user bag +static inline bool SecAKSLockedAnyStateBitIsSet(bool* isSet, keybag_state_t bits, CFErrorRef* error) +{ + keybag_state_t state; + bool success = SecAKSGetLockedState(&state, error); + + require_quiet(success, exit); + + if (isSet) + *isSet = (state & bits); + +exit: + return success; + +} + +static inline bool SecAKSGetIsLocked(bool* isLocked, CFErrorRef* error) +{ + return SecAKSLockedAnyStateBitIsSet(isLocked, keybag_state_locked, error); +} + +static inline bool SecAKSGetIsUnlocked(bool* isUnlocked, CFErrorRef* error) +{ + bool isLocked = false; + bool success = SecAKSGetIsLocked(&isLocked, error); + + if (success && isUnlocked) + *isUnlocked = !isLocked; + + return success; +} + +static inline bool SecAKSGetHasBeenUnlocked(bool* hasBeenUnlocked, CFErrorRef* error) +{ + return SecAKSLockedAnyStateBitIsSet(hasBeenUnlocked, keybag_state_been_unlocked, error); +} + +bool SecAKSDoWhileUserBagLocked(CFErrorRef *error, dispatch_block_t action); + +#endif diff --git a/Security/utilities/src/SecCFError.c b/Security/utilities/src/SecCFError.c new file mode 100644 index 00000000..56cefa6a --- /dev/null +++ b/Security/utilities/src/SecCFError.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include +#include + +bool SecKernError(kern_return_t result, CFErrorRef *error, CFStringRef format, ...) { + if (!result) return true; + if (error) { + va_list args; + CFIndex code = result; + CFErrorRef previousError = *error; + + *error = NULL; + va_start(args, format); + SecCFCreateErrorWithFormatAndArguments(code, kSecKernDomain, previousError, error, NULL, format, args); + va_end(args); + } + return false; +} + +bool SecCheckErrno(int result, CFErrorRef *error, CFStringRef format, ...) { + if (result == 0) return true; + if (error) { + va_list args; + int errnum = errno; + CFIndex code = errnum; + CFErrorRef previousError = *error; + + *error = NULL; + va_start(args, format); + CFStringRef message = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, format, args); + va_end(args); + SecCFCreateErrorWithFormat(code, kSecErrnoDomain, previousError, error, NULL, CFSTR("%@: [%d] %s"), message, errnum, strerror(errnum)); + CFReleaseSafe(message); + } + return false; +} + +bool SecError(OSStatus status, CFErrorRef *error, CFStringRef format, ...) { + if (status == 0) return true; + if (error) { + va_list args; + CFIndex code = status; + CFErrorRef previousError = *error; + + *error = NULL; + va_start(args, format); + SecCFCreateErrorWithFormatAndArguments(code, kSecErrorDomain, previousError, error, NULL, format, args); + va_end(args); + } + return false; +} + +bool SecCFCreateError(CFIndex errorCode, CFStringRef domain, CFStringRef descriptionString, + CFErrorRef previousError, CFErrorRef *newError) +{ +#pragma clang diagnostic push +#pragma GCC diagnostic ignored "-Wformat-security" + return SecCFCreateErrorWithFormat(errorCode, domain, previousError, newError, NULL, descriptionString); +#pragma clang diagnostic pop +} + +bool SecCFCreateErrorWithFormat(CFIndex errorCode, CFStringRef domain, CFErrorRef previousError, CFErrorRef *newError, + CFDictionaryRef formatoptions, CFStringRef format, ...) +{ + va_list args; + va_start(args, format); + + bool result = SecCFCreateErrorWithFormatAndArguments(errorCode, domain, previousError, newError, formatoptions, format, args); + + va_end(args); + + return result; +} + +bool SecCFCreateErrorWithFormatAndArguments(CFIndex errorCode, CFStringRef domain, + CFErrorRef previousError, CFErrorRef *newError, + CFDictionaryRef formatoptions, CFStringRef format, va_list args) +{ + if (newError && !(*newError)) { + CFStringRef formattedString = CFStringCreateWithFormatAndArguments(NULL, formatoptions, format, args); + + const void* keys[2] = { kCFErrorDescriptionKey, kCFErrorUnderlyingErrorKey}; + const void* values[2] = { formattedString, previousError }; + const CFIndex numEntriesToUse = (previousError != NULL) ? 2 : 1; + + *newError = CFErrorCreateWithUserInfoKeysAndValues(kCFAllocatorDefault, domain, errorCode, + keys, values, numEntriesToUse); + + CFReleaseNull(formattedString); + if (previousError) + secnotice("error", "encapsulated %@ with new error: %@", previousError, *newError); + } else { + if (previousError && newError && (previousError != *newError)) { + secnotice("error", "dropping %@", previousError); + CFRelease(previousError); + } + } + + return false; +} diff --git a/Security/utilities/src/SecCFError.h b/Security/utilities/src/SecCFError.h new file mode 100644 index 00000000..7e579943 --- /dev/null +++ b/Security/utilities/src/SecCFError.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef _SECCFERROR_H_ +#define _SECCFERROR_H_ + +#include + +// +// Leaf error creation from other systems +// + +// kern_return_t errors +#define kSecKernDomain kCFErrorDomainMach +bool SecKernError(kern_return_t result, CFErrorRef *error, CFStringRef format, ...); + +// Unix errno errors +#define kSecErrnoDomain kCFErrorDomainPOSIX +bool SecCheckErrno(int result, CFErrorRef *error, CFStringRef format, ...); + +// OSStatus errors +#define kSecErrorDomain kCFErrorDomainOSStatus +bool SecError(OSStatus status, CFErrorRef *error, CFStringRef format, ...); + +// +// Create and chain, all return false to make the analyzer happy. +// +bool SecCFCreateError(CFIndex errorCode, CFStringRef domain, CFStringRef descriptionString, + CFErrorRef previousError, CFErrorRef *newError); + +bool SecCFCreateErrorWithFormat(CFIndex errorCode, CFStringRef domain, CFErrorRef previousError, CFErrorRef *newError, + CFDictionaryRef formatoptions, CFStringRef descriptionString, ...) + CF_FORMAT_FUNCTION(6,7); + + +bool SecCFCreateErrorWithFormatAndArguments(CFIndex errorCode, CFStringRef domain, + CFErrorRef previousError, CFErrorRef *newError, + CFDictionaryRef formatoptions, CFStringRef descriptionString, va_list args) + CF_FORMAT_FUNCTION(6, 0); + +#endif diff --git a/Security/utilities/src/SecCFRelease.h b/Security/utilities/src/SecCFRelease.h new file mode 100644 index 00000000..97d27c4b --- /dev/null +++ b/Security/utilities/src/SecCFRelease.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef _SECCFRELEASE_H_ +#define _SECCFRELEASE_H_ + +#include + +// Retains its argument unless it's NULL. Always returns its argument. +#define CFRetainSafe(CF) ({ __typeof__(CF) _cf = (CF); _cf ? (CFRetain(_cf), _cf) : _cf; }) + +// Assume CF is NULL or an already retained object and CFReleaseSafe VAR and assigns CF to VAR. Returns CF. +#define CFAssignRetained(VAR,CF) ({ \ + __typeof__(VAR) *const _pvar = &(VAR); \ + __typeof__(CF) _cf = (CF); \ + (*_pvar) = *_pvar ? (CFRelease(*_pvar), _cf) : _cf; \ +}) + +// CFRetainSafe CF and CFReleaseSafe VAR and assigns CF to VAR. Returns CF. +#define CFRetainAssign(VAR,CF) ({ \ + __typeof__(VAR) *const _pvar = &(VAR); \ + __typeof__(CF) _cf = (CF); \ + (((*_pvar) == _cf) ? _cf \ + : ((*_pvar) = (_cf ? (CFRetain(_cf), (*_pvar ? (CFRelease(*_pvar), _cf) : _cf)) \ + : (CFRelease(*_pvar), ((__typeof__(_cf))0))))); \ +}) + +// Releases CF unless it's NULL. Always returns NULL, for your convenience and constructs like: +// return CFReleaseSafe(foo); +#define CFReleaseSafe(CF) ({ __typeof__(CF) _cf = (CF); (_cf ? (CFRelease(_cf), ((__typeof__(CF))0)) : _cf); }) + +// Assigns NULL to CF. Releases the value stored at CF unless it was NULL. Always returns NULL, for your convenience +#define CFReleaseNull(CF) ({ __typeof__(CF) *const _pcf = &(CF), _cf = *_pcf; (_cf ? (*_pcf) = ((__typeof__(CF))0), (CFRelease(_cf), ((__typeof__(CF))0)) : _cf); }) + + +#endif /* _SECCFRELEASE_H_ */ diff --git a/Security/utilities/src/SecCFWrappers.c b/Security/utilities/src/SecCFWrappers.c new file mode 100644 index 00000000..0c33c803 --- /dev/null +++ b/Security/utilities/src/SecCFWrappers.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + +// +// Global sigleton Zulu time. +// +CFGiblisGetSingleton(CFCalendarRef, SecCFCalendarGetZulu, zuluCalendar, ^{ + *zuluCalendar = CFCalendarCreateWithIdentifier(kCFAllocatorDefault, kCFGregorianCalendar); + CFTimeZoneRef tz = CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0.0); + CFCalendarSetTimeZone(*zuluCalendar, tz); + CFReleaseSafe(tz); +}) + + + +void CFStringPerformWithCStringAndLength(CFStringRef inStr, void(^operation)(const char *utf8String, size_t utf8Length)) { + const char *cstr = CFStringGetCStringPtr(inStr, kCFStringEncodingUTF8); + if (cstr) { + operation(cstr, strlen(cstr)); + } else { + CFIndex neededLen = 0; + CFRange range = { 0, CFStringGetLength(inStr) }; + CFStringGetBytes(inStr, range, kCFStringEncodingUTF8, + 0, FALSE, NULL, 0, &neededLen); + CFIndex usedLen = 0; + if (neededLen < 4096) { + char buf[neededLen + 1]; + CFStringGetBytes(inStr, range, kCFStringEncodingUTF8, + 0, FALSE, (UInt8 *)buf, neededLen, &usedLen); + assert(usedLen == neededLen); + buf[usedLen] = 0; + operation(buf, (size_t)usedLen); + //cc_zero(neededLen, buf); + } else { + char *buf = malloc(neededLen + 1); + CFStringGetBytes(inStr, range, kCFStringEncodingUTF8, + 0, FALSE, (UInt8 *)buf, neededLen, &usedLen); + assert(usedLen == neededLen); + buf[usedLen] = 0; + operation(buf, (size_t)usedLen); + //cc_zero(neededLen, buf); + free(buf); + } + } +} + +void CFStringPerformWithCString(CFStringRef inStr, void(^operation)(const char *utf8String)) { + const char *cstr = CFStringGetCStringPtr(inStr, kCFStringEncodingUTF8); + if (cstr) { + operation(cstr); + } else { + CFIndex neededLen = 0; + CFRange range = { 0, CFStringGetLength(inStr) }; + CFStringGetBytes(inStr, range, kCFStringEncodingUTF8, + 0, FALSE, NULL, 0, &neededLen); + CFIndex usedLen = 0; + if (neededLen < 4096) { + char buf[neededLen + 1]; + CFStringGetBytes(inStr, range, kCFStringEncodingUTF8, + 0, FALSE, (UInt8 *)buf, neededLen, &usedLen); + assert(usedLen == neededLen); + buf[usedLen] = 0; + operation(buf); + //cc_zero(neededLen, buf); + } else { + char *buf = malloc(neededLen + 1); + CFStringGetBytes(inStr, range, kCFStringEncodingUTF8, + 0, FALSE, (UInt8 *)buf, neededLen, &usedLen); + assert(usedLen == neededLen); + buf[usedLen] = 0; + operation(buf); + //cc_zero(neededLen, buf); + free(buf); + } + } +} diff --git a/Security/utilities/src/SecCFWrappers.h b/Security/utilities/src/SecCFWrappers.h new file mode 100644 index 00000000..e18413f2 --- /dev/null +++ b/Security/utilities/src/SecCFWrappers.h @@ -0,0 +1,807 @@ +/* + * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef _SECCFWRAPPERS_H_ +#define _SECCFWRAPPERS_H_ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +// +// Convenience routines. +// + +// +// Macros for the pattern +// +// typedef struct _privateNewClass* NewClassRef; +// +// struct _privateNewClass { +// CFRuntimeBase _base; +// ... class additions +// }; +// +// kClassNameRegisterClass +// kClassNameTypeID +// +// ClassNameGetTypeID() +// +// CFGiblisFor(NewClass); +// +// .. define NewClassDestroy +// .. define NewClassCopyDescription +// +// .. use CFTypeAllocate(NewClass, _privateNewClass, allocator); +// +// + +// Call this to create a function that returns a singleton instance of type stype, +// which is initialized once by calling doThisOnce, with result in its context. Upon +// completion body should assign to *result. +#define CFGiblisGetSingleton(returnType, giblisClassName, result, doThisOnce) \ +returnType giblisClassName(void); \ +returnType giblisClassName(void) { \ + static dispatch_once_t s##giblisClassName##Once; \ + static returnType s##giblisClassName##Singleton; \ + returnType *result = &s##giblisClassName##Singleton; \ + dispatch_once(&s##giblisClassName##Once, doThisOnce); \ + return s##giblisClassName##Singleton; \ +} + +#define CFGiblisWithFunctions(gibliClassName, init_func, copy_func, finalize_func, equal_func, hash_func, copyFormattingDesc_func, copyDebugDesc_func, reclaim_func, refcount_func, run_once_block) \ +CFGiblisGetSingleton(CFTypeID, gibliClassName##GetTypeID, typeID, (^{ \ + void(^_onceBlock)() = (run_once_block); \ + static const CFRuntimeClass s##gibliClassName##Class = { \ + .version = (reclaim_func == NULL ? 0 : _kCFRuntimeResourcefulObject) \ + | (refcount_func == NULL ? 0 : _kCFRuntimeCustomRefCount), \ + .className = #gibliClassName, \ + .init = init_func, \ + .copy = copy_func, \ + .finalize = finalize_func, \ + .equal = equal_func, \ + .hash = hash_func, \ + .copyFormattingDesc = copyFormattingDesc_func, \ + .copyDebugDesc = copyDebugDesc_func, \ + .reclaim = reclaim_func, \ + .refcount = refcount_func, \ + }; \ + *typeID = _CFRuntimeRegisterClass(&s##gibliClassName##Class); \ + if (_onceBlock) \ + _onceBlock(); \ +})) + + +#define CFGiblisWithHashFor(gibliClassName) \ + static CFStringRef gibliClassName##CopyDescription(CFTypeRef cf); \ + static void gibliClassName##Destroy(CFTypeRef cf); \ + static Boolean gibliClassName##Compare(CFTypeRef lhs, CFTypeRef rhs); \ + static CFHashCode gibliClassName##Hash(CFTypeRef cf); \ + \ + CFGiblisWithFunctions(gibliClassName, NULL, NULL, gibliClassName##Destroy, gibliClassName##Compare, gibliClassName##Hash, NULL, gibliClassName##CopyDescription, NULL, NULL, NULL) + +#define CFGiblisWithCompareFor(gibliClassName) \ + static CFStringRef gibliClassName##CopyDescription(CFTypeRef cf); \ + static void gibliClassName##Destroy(CFTypeRef cf); \ + static Boolean gibliClassName##Compare(CFTypeRef lhs, CFTypeRef rhs); \ + \ + CFGiblisWithFunctions(gibliClassName, NULL, NULL, gibliClassName##Destroy, gibliClassName##Compare, NULL, NULL, gibliClassName##CopyDescription, NULL, NULL, NULL) + + +#define CFGiblisFor(gibliClassName) \ + static CFStringRef gibliClassName##CopyDescription(CFTypeRef cf); \ + static void gibliClassName##Destroy(CFTypeRef cf); \ + \ + CFGiblisWithFunctions(gibliClassName, NULL, NULL, gibliClassName##Destroy, NULL, NULL, NULL, gibliClassName##CopyDescription, NULL, NULL, NULL) + +#define CFTypeAllocateWithSpace(classType, space, allocator) \ + (classType##Ref) _CFRuntimeCreateInstance(allocator, classType##GetTypeID(), space, NULL) + +#define CFTypeAllocate(classType, internalType, allocator) \ + CFTypeAllocateWithSpace(classType, sizeof(internalType) - sizeof(CFRuntimeBase), allocator) + + +__BEGIN_DECLS + +// +// Call block function +// + +static void apply_block_1(const void *value, void *context) +{ + return ((void (^)(const void *value))context)(value); +} + +static void apply_block_2(const void *key, const void *value, void *context) +{ + return ((void (^)(const void *key, const void *value))context)(key, value); +} + +// +// CFEqual Helpers +// + +static inline bool CFEqualSafe(CFTypeRef left, CFTypeRef right) +{ + if (left == NULL || right == NULL) + return left == right; + else + return CFEqual(left, right); +} + + +// +// Printing +// + +static void fprint_string(FILE *file, CFStringRef string) { + UInt8 buf[256]; + CFRange range = { .location = 0 }; + range.length = CFStringGetLength(string); + while (range.length > 0) { + CFIndex bytesUsed = 0; + CFIndex converted = CFStringGetBytes(string, range, kCFStringEncodingUTF8, 0, false, buf, sizeof(buf), &bytesUsed); + fwrite(buf, 1, bytesUsed, file); + range.length -= converted; + range.location += converted; + } +} + +static inline void cffprint_v(FILE *file, CFStringRef fmt, va_list args) { + CFStringRef line = CFStringCreateWithFormatAndArguments(NULL, NULL, fmt, args); + fprint_string(file, line); + CFRelease(line); +} + +static inline void cffprint_c_v(FILE *file, const char *fmt, va_list args) { + CFStringRef cffmt = CFStringCreateWithCString(kCFAllocatorDefault, fmt, kCFStringEncodingUTF8); + cffprint_v(file, cffmt, args); + CFRelease(cffmt); +} + +static void cffprint(FILE *file, CFStringRef fmt, ...) CF_FORMAT_FUNCTION(2,0); +static inline void cffprint(FILE *file, CFStringRef fmt, ...) { + va_list args; + va_start(args, fmt); + cffprint_v(file, fmt, args); + va_end(args); +} + +// +// CFError Helpers +// + +/* Return false if possibleError is set. Propagates possibleError into *error + if *error is NULL, otherwise releases possibleError. */ +static inline +bool CFErrorPropagate(CFErrorRef possibleError CF_CONSUMED, CFErrorRef *error) { + if (possibleError) { + if (error && !*error) { + *error = possibleError; + } else { + CFRelease(possibleError); + } + return false; + } + return true; +} + +// +// CFNumber Helpers +// + +static inline CFNumberRef CFNumberCreateWithCFIndex(CFAllocatorRef allocator, CFIndex value) +{ + return CFNumberCreate(allocator, kCFNumberCFIndexType, &value); +} + +// +// CFData Helpers +// + +static inline CFMutableDataRef CFDataCreateMutableWithScratch(CFAllocatorRef allocator, CFIndex size) { + CFMutableDataRef result = CFDataCreateMutable(allocator, 0); + CFDataSetLength(result, size); + + return result; +} + +static inline void CFDataAppend(CFMutableDataRef appendTo, CFDataRef dataToAppend) +{ + CFDataAppendBytes(appendTo, CFDataGetBytePtr(dataToAppend), CFDataGetLength(dataToAppend)); +} + +static inline CFDataRef CFDataCreateReferenceFromRange(CFAllocatorRef allocator, CFDataRef sourceData, CFRange range) +{ + return CFDataCreateWithBytesNoCopy(allocator, + CFDataGetBytePtr(sourceData) + range.location, range.length, + kCFAllocatorNull); +} + +static inline CFDataRef CFDataCreateCopyFromRange(CFAllocatorRef allocator, CFDataRef sourceData, CFRange range) +{ + return CFDataCreate(allocator, CFDataGetBytePtr(sourceData) + range.location, range.length); +} + +static inline uint8_t* CFDataIncreaseLengthAndGetMutableBytes(CFMutableDataRef data, CFIndex extraLength) +{ + CFIndex startOffset = CFDataGetLength(data); + + CFDataIncreaseLength(data, extraLength); + + return CFDataGetMutableBytePtr(data) + startOffset; +} + +static inline uint8_t* CFDataGetMutablePastEndPtr(CFMutableDataRef theData) +{ + return CFDataGetMutableBytePtr(theData) + CFDataGetLength(theData); +} + +static inline const uint8_t* CFDataGetPastEndPtr(CFDataRef theData) { + return CFDataGetBytePtr(theData) + CFDataGetLength(theData); +} + +static inline CFComparisonResult CFDataCompare(CFDataRef left, CFDataRef right) +{ + const size_t left_size = CFDataGetLength(left); + const size_t right_size = CFDataGetLength(right); + const size_t shortest = (left_size <= right_size) ? left_size : right_size; + + int comparison = memcmp(CFDataGetBytePtr(left), CFDataGetBytePtr(right), shortest); + + if (comparison > 0 || (comparison == 0 && left_size > right_size)) + return kCFCompareGreaterThan; + else if (comparison < 0 || (comparison == 0 && left_size < right_size)) + return kCFCompareLessThan; + else + return kCFCompareEqualTo; +} + + +// +// CFString Helpers +// + +// +// Turn a CFString into an allocated UTF8-encoded C string. +// +static inline char *CFStringToCString(CFStringRef inStr) +{ + if (!inStr) + return (char *)strdup(""); + CFRetain(inStr); // compensate for release on exit + + // need to extract into buffer + CFIndex length = CFStringGetLength(inStr); // in 16-bit character units + size_t len = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8); + char *buffer = (char *)malloc(len); // pessimistic + if (!CFStringGetCString(inStr, buffer, len, kCFStringEncodingUTF8)) + buffer[0] = 0; + + CFRelease(inStr); + return buffer; +} + +// runs operation with inStr as a zero terminated C string +// in utf8 encoding passed to the operation block. +void CFStringPerformWithCString(CFStringRef inStr, void(^operation)(const char *utf8Str)); + +// runs operation with inStr as a zero terminated C string +// in utf8 passed to the operation block, the length of +// the string is also provided to the block. +void CFStringPerformWithCStringAndLength(CFStringRef inStr, void(^operation)(const char *utf8Str, size_t utf8Length)); + +#include + +static inline void CFStringAppendEncryptedData(CFMutableStringRef s, CFDataRef edata) +{ + const uint8_t *bytes = CFDataGetBytePtr(edata); + CFIndex len = CFDataGetLength(edata); + CFStringAppendFormat(s, 0, CFSTR("%04lx:"), len); + if(len<=8) { + for (CFIndex ix = 0; ix < len; ++ix) { + CFStringAppendFormat(s, 0, CFSTR("%02X"), bytes[ix]); + } + } else { + uint64_t crc = 0; + CNCRC(kCN_CRC_64_ECMA_182, bytes+8, len-8, &crc); + for (CFIndex ix = 0; ix < 8; ++ix) { + CFStringAppendFormat(s, 0, CFSTR("%02X"), bytes[ix]); + } + CFStringAppendFormat(s, 0, CFSTR("...|%08llx"), crc); + } +} + +static inline void CFStringAppendHexData(CFMutableStringRef s, CFDataRef data) { + const uint8_t *bytes = CFDataGetBytePtr(data); + CFIndex len = CFDataGetLength(data); + for (CFIndex ix = 0; ix < len; ++ix) { + CFStringAppendFormat(s, 0, CFSTR("%02X"), bytes[ix]); + } +} + +static inline CF_RETURNS_RETAINED CFStringRef CFDataCopyHexString(CFDataRef data) { + CFMutableStringRef hexString = CFStringCreateMutable(kCFAllocatorDefault, 2 * CFDataGetLength(data)); + CFStringAppendHexData(hexString, data); + return hexString; +} + +static inline void CFDataPerformWithHexString(CFDataRef data, void (^operation)(CFStringRef dataString)) { + CFStringRef hexString = CFDataCopyHexString(data); + operation(hexString); + CFRelease(hexString); +} + +static inline void BufferPerformWithHexString(const UInt8 *bytes, CFIndex length, void (^operation)(CFStringRef dataString)) { + CFDataRef bufferAsData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, bytes, length, kCFAllocatorNull); + + CFDataPerformWithHexString(bufferAsData, operation); + + CFReleaseNull(bufferAsData); +} + + + +static inline void CFStringWriteToFile(CFStringRef inStr, FILE* file) +{ + CFStringPerformWithCStringAndLength(inStr, ^(const char *utf8Str, size_t utf8Length) { + fwrite(utf8Str, 1, utf8Length, file); + }); +} + +static inline void CFStringWriteToFileWithNewline(CFStringRef inStr, FILE* file) +{ + CFStringWriteToFile(inStr, file); + fputc('\n', file); +} + +// +// MARK: CFCollectionHelpers +// + +static inline +const void *SecCFRetainForCollection(CFAllocatorRef allocator, const void *value) +{ + return CFRetain(value); +} + +static inline +void SecCFReleaseForCollection(CFAllocatorRef allocator, const void *value) +{ + CFRelease(value); +} + +// +// MARK: CFArray Helpers +// + +static inline CFIndex CFArrayRemoveAllValue(CFMutableArrayRef array, const void* value) +{ + CFIndex position = kCFNotFound; + CFIndex numberRemoved = 0; + + position = CFArrayGetFirstIndexOfValue(array, CFRangeMake(0, CFArrayGetCount(array)), value); + while (position != kCFNotFound) { + CFArrayRemoveValueAtIndex(array, position); + ++numberRemoved; + position = CFArrayGetFirstIndexOfValue(array, CFRangeMake(0, CFArrayGetCount(array)), value); + } + + return numberRemoved; +} + +#define CFArrayForEachC(array, value) for (CFIndex _aCount = CFArrayGetCount(array), _aIX = 0;value = (__typeof__(value))(_aIX < _aCount ? CFArrayGetValueAtIndex(array, _aIX) : 0), _aIX < _aCount; ++_aIX) + +static inline void CFArrayForEach(CFArrayRef array, void (^operation)(const void *value)) { + CFArrayApplyFunction(array, CFRangeMake(0, CFArrayGetCount(array)), apply_block_1, operation); +} + +static inline void CFArrayForEachReverse(CFArrayRef array, void (^operation)(const void *value)) { + for(CFIndex count = CFArrayGetCount(array); count > 0; --count) { + operation(CFArrayGetValueAtIndex(array, count - 1)); + } +} + +static inline const void *CFArrayGetValueMatching(CFArrayRef array, bool (^match)(const void *value)) { + CFIndex i, n = CFArrayGetCount(array); + for (i = 0; i < n; ++i) { + const void *value = CFArrayGetValueAtIndex(array, i); + if (match(value)) { + return value; + } + } + return NULL; +} + +static inline bool CFArrayHasValueMatching(CFArrayRef array, bool (^match)(const void *value)) { + return CFArrayGetValueMatching(array, match) != NULL; +} + +static inline void CFMutableArrayModifyValues(CFMutableArrayRef array, const void * (^process)(const void *value)) { + CFIndex i, n = CFArrayGetCount(array); + for (i = 0; i < n; ++i) { + const void *value = CFArrayGetValueAtIndex(array, i); + CFArraySetValueAtIndex(array, i, process(value)); + } +} + +// +// MARK: CFArray creatino Var args helper functions. +// +static inline CFArrayRef CFArrayCreateCountedForVC(CFAllocatorRef allocator, const CFArrayCallBacks *cbs, CFIndex entries, va_list args) +{ + const void *values[entries ? entries : 1]; + for (CFIndex currentValue = 0; currentValue < entries; ++currentValue) + { + values[currentValue] = va_arg(args, void*); + + if (values[currentValue] == NULL) + values[currentValue] = kCFNull; + } + + return CFArrayCreate(allocator, values, entries, cbs); +} + +static inline CFArrayRef CFArrayCreateForVC(CFAllocatorRef allocator, const CFArrayCallBacks *cbs, va_list args) +{ + va_list count; + va_copy(count, args); + + CFIndex entries = 0; + while (NULL != va_arg(count, void*)) { + entries += 1; + } + + return CFArrayCreateCountedForVC(allocator, cbs, entries, args); + +} + + + +// +// MARK: CFArray of CFTypes support +// + +static inline CFMutableArrayRef CFArrayCreateMutableForCFTypesWithCapacity(CFAllocatorRef allocator, CFIndex capacity) +{ + return CFArrayCreateMutable(allocator, capacity, &kCFTypeArrayCallBacks); +} + + +static inline CFMutableArrayRef CFArrayCreateMutableForCFTypes(CFAllocatorRef allocator) +{ + return CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks); +} + +static inline CFArrayRef CFArrayCreateForCFTypes(CFAllocatorRef allocator, ...) +{ + va_list args; + va_start(args, allocator); + + return CFArrayCreateForVC(allocator, &kCFTypeArrayCallBacks, args); + +} + +static inline CFArrayRef CFArrayCreateCountedForCFTypes(CFAllocatorRef allocator, CFIndex entries, ...) +{ + va_list args; + va_start(args, entries); + + return CFArrayCreateCountedForVC(allocator, &kCFTypeArrayCallBacks, entries, args); +} + +static inline CFArrayRef CFArrayCreateCountedForCFTypesV(CFAllocatorRef allocator, CFIndex entries, va_list args) +{ + return CFArrayCreateCountedForVC(allocator, &kCFTypeArrayCallBacks, entries, args); +} + +// +// MARK: CFDictionary of CFTypes helpers +// + +static inline CFDictionaryRef CFDictionaryCreateCountedForCFTypesV(CFAllocatorRef allocator, CFIndex entries, va_list args) +{ + const void *keys[entries]; + const void *values[entries]; + + for(CFIndex currentValue = 0; currentValue < entries; ++currentValue) + { + keys[currentValue] = va_arg(args, void*); + values[currentValue] = va_arg(args, void*); + + if (values[currentValue] == NULL) + values[currentValue] = kCFNull; + } + + return CFDictionaryCreate(allocator, keys, values, entries, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); +} + +static inline CFDictionaryRef CFDictionaryCreateForCFTypes(CFAllocatorRef allocator, ...) +{ + va_list args; + va_start(args, allocator); + + CFIndex entries = 0; + while (NULL != va_arg(args, void*)) { + entries += 2; + (void) va_arg(args, void*); + } + + entries /= 2; + + va_start(args, allocator); + + return CFDictionaryCreateCountedForCFTypesV(allocator, entries, args); + +} + +static inline CFDictionaryRef CFDictionaryCreateCountedForCFTypes(CFAllocatorRef allocator, CFIndex entries, ...) +{ + va_list args; + va_start(args, entries); + + return CFDictionaryCreateCountedForCFTypesV(allocator, entries, args); +} + +static inline CFMutableDictionaryRef CFDictionaryCreateMutableForCFTypes(CFAllocatorRef allocator) +{ + return CFDictionaryCreateMutable(allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); +} + +static inline CFMutableDictionaryRef CFDictionaryCreateMutableForCFTypesWith(CFAllocatorRef allocator, ...) +{ + CFMutableDictionaryRef result = CFDictionaryCreateMutableForCFTypes(allocator); + + va_list args; + va_start(args, allocator); + + void* key = va_arg(args, void*); + + while (key != NULL) { + CFDictionarySetValue(result, key, va_arg(args, void*)); + key = va_arg(args, void*); + }; + + return result; +} + +// +// MARK: CFSet Helpers +// + +static inline CFMutableSetRef CFSetCreateMutableForCFTypes(CFAllocatorRef allocator) +{ + return CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks); +} + +static inline void CFSetForEach(CFSetRef set, void (^operation)(const void *value)) { + CFSetApplyFunction(set, apply_block_1, operation); +} + +static inline void CFSetSetValues(CFMutableSetRef set, CFArrayRef valuesToSet) { + CFArrayForEach(valuesToSet, ^(const void *value) { + CFSetSetValue(set, value); + }); +} + +static inline CFMutableArrayRef CFSetCopyValues(CFSetRef set) { + CFMutableArrayRef values = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + + CFSetForEach(set, ^(const void *value) { + CFArrayAppendValue(values, value); + }); + + return values; +} + +// +// MARK: CFDictionary Helpers +// + +static inline void CFDictionaryForEach(CFDictionaryRef dictionary, void (^operation)(const void *key, const void *value)) { + CFDictionaryApplyFunction(dictionary, apply_block_2, operation); +} + +// +// MARK: CFCalendar helpers +// + +CFCalendarRef SecCFCalendarGetZulu(); + +// +// MARK: CFAbsoluteTime helpers +// + +static inline CFAbsoluteTime CFAbsoluteTimeForCalendarMoment(CFCalendarRef cal, int year, int month, int day, int hour, int minute, int second) { + CFAbsoluteTime at; + CFCalendarComposeAbsoluteTime(cal, &at, "yMdHms", year, month, day, hour, minute, second); + return at; +} + +static inline CFAbsoluteTime CFAbsoluteTimeForCalendarDay(CFCalendarRef cal, int year, int month, int day) { + CFAbsoluteTime at; + CFCalendarComposeAbsoluteTime(cal, &at, "yMd", year, month, day); + return at; +} + +static inline CFAbsoluteTime CFAbsoluteTimeForGregorianMoment(CFTimeZoneRef tz, int year, int month, int day, int hour, int minute, int second) +{ + CFCalendarRef cal = CFCalendarCreateWithIdentifier(NULL, kCFGregorianCalendar); + CFCalendarSetTimeZone(cal, tz); + CFAbsoluteTime at = CFAbsoluteTimeForCalendarMoment(cal, year, month, day, hour, minute, second); + CFReleaseSafe(cal); + return at; +} + +static inline CFAbsoluteTime CFAbsoluteTimeForGregorianDay(CFTimeZoneRef tz, int year, int month, int day) +{ + CFCalendarRef cal = CFCalendarCreateWithIdentifier(NULL, kCFGregorianCalendar); + CFCalendarSetTimeZone(cal, tz); + CFAbsoluteTime at = CFAbsoluteTimeForCalendarDay(cal, year, month, day); + CFReleaseSafe(cal); + return at; +} + +static inline CFAbsoluteTime CFAbsoluteTimeForGregorianZuluMoment(int year, int month, int day, int hour, int minute, int second) +{ + return CFAbsoluteTimeForCalendarMoment(SecCFCalendarGetZulu(), year, month, day, hour, minute, second); +} + + +static inline CFAbsoluteTime CFAbsoluteTimeForGregorianZuluDay(int year, int month, int day) +{ + return CFAbsoluteTimeForCalendarDay(SecCFCalendarGetZulu(), year, month, day); +} + + + +// +// MARK: CFDate Helpers +// + +static inline CFDateRef CFDateCreateForGregorianMoment(CFAllocatorRef allocator, CFTimeZoneRef tz, int year, int month, int day, int hour, int minute, int second) +{ + return CFDateCreate(allocator, CFAbsoluteTimeForGregorianMoment(tz, year, month, day, hour, minute, second)); +} + +static inline CFDateRef CFDateCreateForGregorianDay(CFAllocatorRef allocator, CFTimeZoneRef tz, int year, int month, int day, int hour, int minute, int second) +{ + return CFDateCreate(allocator, CFAbsoluteTimeForGregorianDay(tz, year, month, day)); +} + +static inline CFDateRef CFDateCreateForGregorianZuluMoment(CFAllocatorRef allocator, int year, int month, int day, int hour, int minute, int second) +{ + return CFDateCreate(allocator, CFAbsoluteTimeForGregorianZuluMoment(year, month, day, hour, minute, second)); +} + +static inline CFDateRef CFDateCreateForGregorianZuluDay(CFAllocatorRef allocator, int year, int month, int day) +{ + return CFDateCreate(allocator, CFAbsoluteTimeForGregorianZuluDay(year, month, day)); +} + + +// +// MARK: Type checking +// + +static inline bool isArray(CFTypeRef cfType) { + return cfType && CFGetTypeID(cfType) == CFArrayGetTypeID(); +} + +static inline bool isSet(CFTypeRef cfType) { + return cfType && CFGetTypeID(cfType) == CFSetGetTypeID(); +} + +static inline bool isData(CFTypeRef cfType) { + return cfType && CFGetTypeID(cfType) == CFDataGetTypeID(); +} + +static inline bool isDate(CFTypeRef cfType) { + return cfType && CFGetTypeID(cfType) == CFDateGetTypeID(); +} + +static inline bool isDictionary(CFTypeRef cfType) { + return cfType && CFGetTypeID(cfType) == CFDictionaryGetTypeID(); +} + +static inline bool isNumber(CFTypeRef cfType) { + return cfType && CFGetTypeID(cfType) == CFNumberGetTypeID(); +} + +static inline bool isNumberOfType(CFTypeRef cfType, CFNumberType number) { + return isNumber(cfType) && CFNumberGetType((CFNumberRef)cfType) == number; +} + +static inline bool isString(CFTypeRef cfType) { + return cfType && CFGetTypeID(cfType) == CFStringGetTypeID(); +} + +static inline bool isBoolean(CFTypeRef cfType) { + return cfType && CFGetTypeID(cfType) == CFBooleanGetTypeID(); +} + +static inline bool isNull(CFTypeRef cfType) { + return cfType && CFGetTypeID(cfType) == CFNullGetTypeID(); +} + + +// +// MARK: PropertyList Helpers +// + +// +// Crazy reading and writing stuff +// + +static inline void CFPropertyListWriteToFile(CFPropertyListRef plist, CFURLRef file) +{ + CFWriteStreamRef writeStream = CFWriteStreamCreateWithFile(kCFAllocatorDefault, file); + CFErrorRef error = NULL; + + CFWriteStreamOpen(writeStream); + CFPropertyListWrite(plist, writeStream, kCFPropertyListBinaryFormat_v1_0, 0, &error); + if (error) + secerror("Can't write plist: %@", error); + + CFReleaseNull(error); + CFReleaseNull(writeStream); +} + +static inline CF_RETURNS_RETAINED CFPropertyListRef CFPropertyListReadFromFile(CFURLRef file) +{ + CFPropertyListRef result = NULL; + CFErrorRef error = NULL; + CFBooleanRef isRegularFile; + if (!CFURLCopyResourcePropertyForKey(file, kCFURLIsRegularFileKey, &isRegularFile, &error)) { + secdebug("plist", "file %@: %@", file, error); + } else if (CFBooleanGetValue(isRegularFile)) { + CFReadStreamRef readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault, file); + if (readStream) { + if (CFReadStreamOpen(readStream)) { + CFPropertyListFormat format; + result = CFPropertyListCreateWithStream(kCFAllocatorDefault, readStream, 0, kCFPropertyListMutableContainers, &format, &error); + if (!result) { + secerror("read plist from %@: %@", file, error); + } + } + CFRelease(readStream); + } + } + CFReleaseNull(error); + + return result; +} + +__END_DECLS + +#endif /* _SECCFWRAPPERS_H_ */ diff --git a/utilities/src/SecCertificateTrace.c b/Security/utilities/src/SecCertificateTrace.c similarity index 93% rename from utilities/src/SecCertificateTrace.c rename to Security/utilities/src/SecCertificateTrace.c index b8feab17..e3246cdc 100644 --- a/utilities/src/SecCertificateTrace.c +++ b/Security/utilities/src/SecCertificateTrace.c @@ -1,10 +1,26 @@ -// -// SecCertificateTrace.c -// utilities -// -// Created on 10/18/13. -// Copyright (c) 2013 Apple Inc. All rights reserved. -// +/* + * 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 "SecCertificateTrace.h" #include @@ -105,6 +121,7 @@ static bool OSX_AddKeyValuePairToCertificateLoggingTransaction(void* token, CFSt memset(key_buffer, 0,key_length); if (!CFStringGetCString(real_key, key_buffer, key_length, kCFStringEncodingUTF8)) { + CFRelease(real_key); return false; } CFRelease(real_key); @@ -186,6 +203,7 @@ static bool OSX_SetCertificateTraceValueForKey(CFStringRef key, int64_t value) memset(key_buffer, 0,key_length); if (!CFStringGetCString(real_key, key_buffer, key_length, kCFStringEncodingUTF8)) { + CFRelease(real_key); return false; } CFRelease(real_key); @@ -466,11 +484,18 @@ void CloseCertificateLoggingTransaction(void* token) CFStringRef SecCFStringCopyEncodingDelimiters(CFStringRef str, CFStringRef delimiters) { CFMutableStringRef newStr = (str) ? CFStringCreateMutableCopy(kCFAllocatorDefault, 0, str) : NULL; - if (str && delimiters) + if (newStr && delimiters) { - CFStringRef stringToFind = delimiters; CFStringRef replacementString = CFSTR("_"); + CFIndex idx, count = CFStringGetLength(delimiters); + for (idx = 0; idx < count; idx++) { + UniChar uc = CFStringGetCharacterAtIndex(delimiters, idx); + CFStringRef stringToFind = CFStringCreateWithCharacters(kCFAllocatorDefault, &uc, 1); + if (stringToFind) { CFStringFindAndReplace(newStr, stringToFind, replacementString, CFRangeMake(0, CFStringGetLength(newStr)), 0); + CFRelease(stringToFind); + } + } } return (CFStringRef) newStr; } diff --git a/utilities/src/SecCertificateTrace.h b/Security/utilities/src/SecCertificateTrace.h similarity index 95% rename from utilities/src/SecCertificateTrace.h rename to Security/utilities/src/SecCertificateTrace.h index f1fae848..5337f069 100644 --- a/utilities/src/SecCertificateTrace.h +++ b/Security/utilities/src/SecCertificateTrace.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2013 Apple Inc. All Rights Reserved. + * 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, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/utilities/src/SecDb.c b/Security/utilities/src/SecDb.c similarity index 92% rename from utilities/src/SecDb.c rename to Security/utilities/src/SecDb.c index e204d587..4de373a7 100644 --- a/utilities/src/SecDb.c +++ b/Security/utilities/src/SecDb.c @@ -1,10 +1,26 @@ -// -// SecDb.c -// utilities -// -// Created by Michael Brouwer on 11/12/12. -// Copyright (c) 2012-2013 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include "SecDb.h" #include "debugging.h" @@ -20,6 +36,8 @@ #include "SecIOFormat.h" #include #include "Security/SecBase.h" +#include +#include #define LOGE(ARG,...) secerror(ARG, ## __VA_ARGS__) #define LOGV(ARG,...) secdebug("secdb", ARG, ## __VA_ARGS__) @@ -43,8 +61,12 @@ struct __OpaqueSecDbConnection { SecDbRef db; // NONRETAINED, since db or block retains us bool readOnly; bool inTransaction; + SecDbTransactionSource source; bool isCorrupted; sqlite3 *handle; + // Pending deletions and addtions to the manifest for the current transaction + struct SOSDigestVector todel; + struct SOSDigestVector toadd; }; struct __OpaqueSecDb { @@ -57,6 +79,7 @@ struct __OpaqueSecDb { dispatch_semaphore_t read_semaphore; bool didFirstOpen; bool (^opened)(SecDbConnectionRef dbconn, bool did_create, CFErrorRef *error); + SecDBNotifyBlock notifyPhase; }; // MARK: Error domains and error helper functions @@ -73,6 +96,7 @@ bool SecDbError(int sql_code, CFErrorRef *error, CFStringRef format, ...) { *error = NULL; va_start(args, format); SecCFCreateErrorWithFormatAndArguments(code, kSecDbErrorDomain, previousError, error, NULL, format, args); + CFReleaseNull(previousError); va_end(args); } return false; @@ -183,6 +207,25 @@ SecDbIdleConnectionCount(SecDbRef db) { return count; } +void SecDbSetNotifyPhaseBlock(SecDbRef db, SecDBNotifyBlock notifyPhase) { + if (db->notifyPhase) + Block_release(db->notifyPhase); + db->notifyPhase = Block_copy(notifyPhase); +} + +static void SecDbNotifyPhase(SecDbConnectionRef dbconn, SecDbTransactionPhase phase) { + if (dbconn->todel.count || dbconn->toadd.count) { + if (dbconn->db->notifyPhase) + dbconn->db->notifyPhase(dbconn, phase, dbconn->source, &dbconn->todel, &dbconn->toadd); + SOSDigestVectorFree(&dbconn->todel); + SOSDigestVectorFree(&dbconn->toadd); + } +} + +CFStringRef SecDbGetPath(SecDbRef db) { + return db->db_path; +} + #pragma mark - #pragma mark SecDbConnectionRef @@ -462,6 +505,8 @@ static bool SecDbBeginTransaction(SecDbConnectionRef dbconn, SecDbTransactionTyp case kSecDbImmediateTransactionType: query = CFSTR("BEGIN IMMEDATE"); break; + case kSecDbExclusiveRemoteTransactionType: + dbconn->source = kSecDbSOSTransaction; case kSecDbExclusiveTransactionType: query = CFSTR("BEGIN EXCLUSIVE"); break; @@ -477,17 +522,26 @@ static bool SecDbBeginTransaction(SecDbConnectionRef dbconn, SecDbTransactionTyp if (query != NULL && sqlite3_get_autocommit(dbconn->handle) != 0) { ok = SecDbExec(dbconn, query, error); } + if (ok) + dbconn->inTransaction = true; return ok; } static bool SecDbEndTransaction(SecDbConnectionRef dbconn, bool commit, CFErrorRef *error) { + bool ok = true, commited = false; if (commit) { - return SecDbExec(dbconn, CFSTR("END"), error); + SecDbNotifyPhase(dbconn, kSecDbTransactionWillCommit); + commited = ok = SecDbExec(dbconn, CFSTR("END"), error); } else { - return SecDbExec(dbconn, CFSTR("ROLLBACK"), error); + ok = SecDbExec(dbconn, CFSTR("ROLLBACK"), error); + commited = false; } + dbconn->inTransaction = false; + SecDbNotifyPhase(dbconn, commited ? kSecDbTransactionDidCommit : kSecDbTransactionDidRollback); + dbconn->source = kSecDbAPITransaction; + return ok; } bool SecDbTransaction(SecDbConnectionRef dbconn, SecDbTransactionType type, @@ -504,9 +558,7 @@ bool SecDbTransaction(SecDbConnectionRef dbconn, SecDbTransactionType type, } else { ok = SecDbBeginTransaction(dbconn, type, error); if (ok) { - dbconn->inTransaction = true; transaction(&commit); - dbconn->inTransaction = false; ok = SecDbEndTransaction(dbconn, commit, error); } } @@ -780,7 +832,7 @@ static void SecDbConectionSetReadOnly(SecDbConnectionRef dbconn, bool readOnly) go to the start of the queue. */ SecDbConnectionRef SecDbConnectionAquire(SecDbRef db, bool readOnly, CFErrorRef *error) { CFRetain(db); - secdebug("dbconn", "aquire %s connection", readOnly ? "ro" : "rw"); + secdebug("dbconn", "acquire %s connection", readOnly ? "ro" : "rw"); dispatch_semaphore_wait(readOnly ? db->read_semaphore : db->write_semaphore, DISPATCH_TIME_FOREVER); __block SecDbConnectionRef dbconn = NULL; __block bool ok = true; @@ -1200,4 +1252,18 @@ bool SecDbForEach(sqlite3_stmt *stmt, CFErrorRef *error, bool(^row)(int row_inde } #endif +void SecDbRecordChange(SecDbConnectionRef dbconn, CFDataRef deleted, CFDataRef inserted) { + if (!dbconn->db->notifyPhase) return; + if (deleted) + SOSDigestVectorAppend(&dbconn->todel, CFDataGetBytePtr(deleted)); + if (inserted) + SOSDigestVectorAppend(&dbconn->toadd, CFDataGetBytePtr(inserted)); + if (!dbconn->inTransaction) { + secerror("db %@ changed outside txn", dbconn); + SecDbNotifyPhase(dbconn, kSecDbTransactionWillCommit); + SecDbNotifyPhase(dbconn, kSecDbTransactionDidCommit); + } +} + + CFGiblisFor(SecDbConnection) diff --git a/Security/utilities/src/SecDb.h b/Security/utilities/src/SecDb.h new file mode 100644 index 00000000..55848de0 --- /dev/null +++ b/Security/utilities/src/SecDb.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef _UTILITIES_SECDB_H_ +#define _UTILITIES_SECDB_H_ + +#include +#include + +__BEGIN_DECLS + +// MARK: SecDbRef and SecDbConnectionRef forward declarations +typedef struct __OpaqueSecDb *SecDbRef; +typedef struct __OpaqueSecDbConnection *SecDbConnectionRef; +typedef struct __OpaqueSecDbStatement *SecDbStatementRef; +struct SOSDigestVector; + +// MARK: Configuration values, not used by clients directly. +// TODO: Move this section to a private header +enum { + kSecDbMaxReaders = 4, + kSecDbMaxWriters = 1, + kSecDbMaxIdleHandles = 3, +}; + +// MARK: SecDbTransactionType +enum { + kSecDbNoneTransactionType = 0, + kSecDbImmediateTransactionType, + kSecDbExclusiveTransactionType, + kSecDbNormalTransactionType, + kSecDbExclusiveRemoteTransactionType, +}; +typedef CFOptionFlags SecDbTransactionType; + +enum SecDbTransactionPhase { + kSecDbTransactionDidRollback = 0, // A transaction just got rolled back + kSecDbTransactionWillCommit, // A transaction is about to commit. + kSecDbTransactionDidCommit, // A transnaction sucessfully committed. +}; +typedef CFOptionFlags SecDbTransactionPhase; + +enum SecDbTransactionSource { + kSecDbSOSTransaction, // A remotely initated transaction. + kSecDbAPITransaction, // A user initated transaction. +}; +typedef CFOptionFlags SecDbTransactionSource; + +// MARK: -- +// MARK: Error creation helpers. + +// SQLITE3 errors are in this domain +extern CFStringRef kSecDbErrorDomain; + +bool SecDbError(int sql_code, CFErrorRef *error, CFStringRef format, ...); +bool SecDbErrorWithDb(int sql_code, sqlite3 *db, CFErrorRef *error, CFStringRef format, ...); +bool SecDbErrorWithStmt(int sql_code, sqlite3_stmt *stmt, CFErrorRef *error, CFStringRef format, ...); + +// MARK: mark - +// MARK: mark SecDbRef + +typedef void (^SecDBNotifyBlock)(SecDbConnectionRef dbconn, SecDbTransactionPhase phase, SecDbTransactionSource source, struct SOSDigestVector *removals, struct SOSDigestVector *additions); + +CFTypeID SecDbGetTypeID(void); + +SecDbRef SecDbCreate(CFStringRef dbName, bool (^opened)(SecDbConnectionRef dbconn, bool did_create, CFErrorRef *error)); + +void SecDbSetNotifyPhaseBlock(SecDbRef db, SecDBNotifyBlock notifyPhase); + +// Read only connections go to the end of the queue, writeable +// connections go to the start of the queue. Use SecDbPerformRead() and SecDbPerformWrite() if you +// can to avoid leaks. +SecDbConnectionRef SecDbConnectionAquire(SecDbRef db, bool readOnly, CFErrorRef *error); +void SecDbConnectionRelease(SecDbConnectionRef dbconn); + +// Perform a database read operation, +bool SecDbPerformRead(SecDbRef db, CFErrorRef *error, void (^perform)(SecDbConnectionRef dbconn)); +bool SecDbPerformWrite(SecDbRef db, CFErrorRef *error, void (^perform)(SecDbConnectionRef dbconn)); + +// TODO: DEBUG only -> Private header +CFIndex SecDbIdleConnectionCount(SecDbRef db); + +CFStringRef SecDbGetPath(SecDbRef db); + +// MARK: - +// MARK: SecDbConectionRef + +CFTypeID SecDbConnectionGetTypeID(void); + +bool SecDbPrepare(SecDbConnectionRef dbconn, CFStringRef sql, CFErrorRef *error, void(^exec)(sqlite3_stmt *stmt)); + +bool SecDbStep(SecDbConnectionRef dbconn, sqlite3_stmt *stmt, CFErrorRef *error, void (^row)(bool *stop)); + +bool SecDbExec(SecDbConnectionRef dbconn, CFStringRef sql, CFErrorRef *error); + +bool SecDbCheckpoint(SecDbConnectionRef dbconn, CFErrorRef *error); + +bool SecDbTransaction(SecDbConnectionRef dbconn, SecDbTransactionType ttype, CFErrorRef *error, + void (^transaction)(bool *commit)); + +sqlite3 *SecDbHandle(SecDbConnectionRef dbconn); + +// Do not call this unless you are SecDbItem! +void SecDbRecordChange(SecDbConnectionRef dbconn, CFDataRef deleted, CFDataRef inserted); + +// MARK: - +// MARK: Bind helpers + +#if 0 +bool SecDbBindNull(sqlite3_stmt *stmt, int param, CFErrorRef *error); +#endif +bool SecDbBindBlob(sqlite3_stmt *stmt, int param, const void *zData, size_t n, void(*xDel)(void*), CFErrorRef *error); +bool SecDbBindText(sqlite3_stmt *stmt, int param, const char *zData, size_t n, void(*xDel)(void*), CFErrorRef *error); +bool SecDbBindDouble(sqlite3_stmt *stmt, int param, double value, CFErrorRef *error); +bool SecDbBindInt(sqlite3_stmt *stmt, int param, int value, CFErrorRef *error); +bool SecDbBindInt64(sqlite3_stmt *stmt, int param, sqlite3_int64 value, CFErrorRef *error); +bool SecDbBindObject(sqlite3_stmt *stmt, int param, CFTypeRef value, CFErrorRef *error); + +// MARK: - +// MARK: SecDbStatementRef + +bool SecDbReset(sqlite3_stmt *stmt, CFErrorRef *error); +bool SecDbClearBindings(sqlite3_stmt *stmt, CFErrorRef *error); +bool SecDbFinalize(sqlite3_stmt *stmt, CFErrorRef *error); +sqlite3_stmt *SecDbPrepareV2(SecDbConnectionRef dbconn, const char *sql, size_t sqlLen, const char **sqlTail, CFErrorRef *error); +sqlite3_stmt *SecDbCopyStmt(SecDbConnectionRef dbconn, CFStringRef sql, CFStringRef *tail, CFErrorRef *error); +bool SecDbReleaseCachedStmt(SecDbConnectionRef dbconn, CFStringRef sql, sqlite3_stmt *stmt, CFErrorRef *error); +bool SecDbWithSQL(SecDbConnectionRef dbconn, CFStringRef sql, CFErrorRef *error, bool(^perform)(sqlite3_stmt *stmt)); +bool SecDbForEach(sqlite3_stmt *stmt, CFErrorRef *error, bool(^row)(int row_index)); + +// Mark the database as corrupted. +void SecDbCorrupt(SecDbConnectionRef dbconn); + +__END_DECLS + +#endif /* !_UTILITIES_SECDB_H_ */ diff --git a/Security/utilities/src/SecDispatchRelease.h b/Security/utilities/src/SecDispatchRelease.h new file mode 100644 index 00000000..42ef2dbf --- /dev/null +++ b/Security/utilities/src/SecDispatchRelease.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + + +#ifndef _SECDISPATCHRELEASE_H_ +#define _SECDISPATCHRELEASE_H_ + +#include +#include + +#define dispatch_retain_safe(DO) { \ + __typeof__(DO) _do = (DO); \ + if (_do) \ + dispatch_retain(_do); \ +} + +#define dispatch_release_safe(DO) { \ + __typeof__(DO) _do = (DO); \ + if (_do) \ + dispatch_release(_do); \ +} + +#define dispatch_release_null(DO) { \ + __typeof__(DO) _do = (DO); \ + if (_do) { \ + (DO) = NULL; \ + dispatch_release(_do); \ + } \ +} + + +#define xpc_retain_safe(XO) { \ + __typeof__(XO) _xo = (XO); \ + if (_xo) \ + xpc_retain(_xo); \ +} + +#define xpc_release_safe(XO) { \ + __typeof__(XO) _xo = (XO); \ + if (_xo) \ + xpc_release(_xo); \ +} + +#define xpc_release_null(XO) { \ + __typeof__(XO) _xo = (XO); \ + if (_xo) { \ + (XO) = NULL; \ + xpc_release(_xo); \ + } \ +} + +#endif + diff --git a/utilities/src/SecFileLocations.c b/Security/utilities/src/SecFileLocations.c similarity index 99% rename from utilities/src/SecFileLocations.c rename to Security/utilities/src/SecFileLocations.c index 93dc294f..349549b8 100644 --- a/utilities/src/SecFileLocations.c +++ b/Security/utilities/src/SecFileLocations.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2012-2013 Apple, Inc. All Rights Reserved. + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/utilities/src/SecFileLocations.h b/Security/utilities/src/SecFileLocations.h similarity index 95% rename from utilities/src/SecFileLocations.h rename to Security/utilities/src/SecFileLocations.h index 443b80f9..26b6822a 100644 --- a/utilities/src/SecFileLocations.h +++ b/Security/utilities/src/SecFileLocations.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2012-2013 Apple, Inc. All Rights Reserved. + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/Security/utilities/src/SecIOFormat.h b/Security/utilities/src/SecIOFormat.h new file mode 100644 index 00000000..8630e229 --- /dev/null +++ b/Security/utilities/src/SecIOFormat.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef _SECIOFORMAT_H_ +#define _SECIOFORMAT_H_ +// TODO: Name this file SecType.h? To match inttype.h? + +#include + +// MARK: Guidlines and Examples + +/* Tips for using printf and CFStringCreateWithFormat style functions. + + Avoid using casts in arguments to these functions like the plague. If you + have to use them, think again. You are probably wrong and you are writing + non portable code. Instead try following this pattern: + + Type Format String Variants + size_t "%zu" + ssize_t "%zd" + ptrdiff_t "%td" printf("array_len: %td", pos - begin) + OSStatus "%"PRIdOSStatus printf("%"PRIxCFIndex" returned", status) + CFIndex "%"PRIdCFIndex printf("ar[%"PRIdCFIndex"]=%p", ix, CFArrayGetValueAtIndex(ar, ix)) + sint64_t "%"PRId64 + uint64_t "%"PRIu64 printf("sqlite3_rowid: %"PRIu64, rowid) + sint32_t "%"PRId32 + uint32_t "%"PRIu32 + uint8_t "%"PRIx8 + + All of the above examples also work inside a CFSTR(). For example: + CFStringAppendFormat(ms, NULL, CFSTR("ar[%"PRIdCFIndex"]=%p"), ix, CFArrayGetValueAtIndex(ar, ix)) + Also you can use any of d i o u x X where appropriate for some of these types + although u x X are for unsigned types only. + + Try to avoid using these types unless you know what you are doing because + they can lead to portability issues on different flavors of 32 and 64 bit + platforms: + + int "%d" + long "%ld" + long long "%lld" + */ + +// MARK: CFIndex printing support + +// Note that CFIndex is signed so the u variants won't work. +#ifdef __LLP64__ +# define PRIdCFIndex "lld" +# define PRIiCFIndex "lli" +# define PRIoCFIndex "llo" +# define PRIuCFIndex "llu" +# define PRIxCFIndex "llx" +# define PRIXCFIndex "llX" +#else +# define PRIdCFIndex "ld" +# define PRIiCFIndex "li" +# define PRIoCFIndex "lo" +# define PRIuCFIndex "lu" +# define PRIxCFIndex "lx" +# define PRIXCFIndex "lX" +#endif + +// MARK: OSStatus printing support + +// Note that OSStatus is signed so the u variants won't work. +#ifdef __LP64__ +# define PRIdOSStatus "d" +# define PRIiOSStatus "i" +# define PRIoOSStatus "o" +# define PRIuOSStatus "u" +# define PRIxOSStatus "x" +# define PRIXOSStatus "X" +#else +# define PRIdOSStatus "ld" +# define PRIiOSStatus "li" +# define PRIoOSStatus "lo" +# define PRIuOSStatus "lu" +# define PRIxOSStatus "lx" +# define PRIXOSStatus "lX" +#endif + +#endif diff --git a/Security/utilities/src/SecMeta.h b/Security/utilities/src/SecMeta.h new file mode 100644 index 00000000..f6212dcf --- /dev/null +++ b/Security/utilities/src/SecMeta.h @@ -0,0 +1,203 @@ +/* + * 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@ + */ + + +#ifndef _UTILITIES_SECMETA_H_ +#define _UTILITIES_SECMETA_H_ + +#include + +// +// MARK - SecMeta +// MARK - Logging, Trace, Error reporting, action log capture, and more. +// + +#define SecInline static inline + +// Disable all logging. +#define SecDisableLogging() do { _secOptions = _SecClearMask(_secOptions, mask); } while(0) + +// For people who don't like flag1|flag2|flag3 syntax use SecFlags(flag1,flag2,flag3) +#define SecFlags(...) _SecFlags(0, __VA_ARGS__) + +// Set the current scopes log level. +#define SecSetLogLevel(level) _SecSetLogLevel(&secOptions, (level)); + +// Mark that we performed an action for the log and for an generated errors. +#define SecAction(flags, key, action,...) \ + if (_SecLogLevel(flags)) { _SecSetLogLevel(&_secFlags, _SecLogLevel(flags)); } \ + if (_SecSetFlags(flags) \ + if ((_secFlags | flags) & kSecTraceAction) {} \ + if ((_secFlags | flags) & kSecLogEveryActionFlag) { \ + if (flags & kSecLogLevelMask) { \ + + + } \ + } \ +// _SecAction(&_secResult, &_secFlags, &_secName, &_secError, &_secChain, &_secActions, flags, key, action, __VA_ARGS__) + +// Usage: declare a variable that represents the result of your function +#define SecTry(result,flags,humanReadableFunctionNameForLogs) switch (0) case 0: { \ + __typeof__(result) _secResult = result; \ + __typeof__(flags) _secFlags = flags; \ + __typeof__(format) _secName = humanReadableFunctionNameForLogs; \ + CFErrorRef _secError = NULL; \ + CFMutableArrayRef _secChain = NULL; \ + CFMutableStringRef _secActions = NULL; \ + CFMutableDictionaryRef _secFormatOptions = NULL; \ + SecAction(_secFlags, CFSTR("entered")); + + + +#define SecEnableFlags(&_secFlags, flags) _secFlags = (flags); +#define SecDisableFlags(&_secFlags, flags) _secFlags = (flags); + +#define SecSetFlags(flags) _SecSetFlags(&_secFlags, flags) + +#define SecCatch(result, flags, error, ...) } _SecCatch(&_secResult, &_secFlags, &_secName, &_secError, &_secChain, &_secActions, result, flags, error,__VA_ARGS__) + +// Add pending errors to *error Clears any pending errors, and will log anything that was marked as needing to be logged. +#define SecFinally(result, flags, error, ...) _SecFinally(&_secResult, &_secFlags, &_secName, &_secError, &_secChain, &_secActions, result, flags, error, __VA_ARGS__) + +// Boolean function result +#define SecOk(result, flags, format, ...) _SecOK() + +// Log action and it's arguments into the action log. +#if DEBUG +#define SecDebugAction(flags, action...) SecAction(flags, action...) +#else +#define SecDebugAction(flags, action,...) +#endif + +#define SecThrow(result, domain, flags, body, format...) { rtype _r = body(); __security_trace_return_api(__FUNCTION__, format, _r); return _r; } + + +#define SecEnd(rtype, body, error, format...) { rtype _r = body(); __security_trace_return_api(__FUNCTION__, format, _r); return _r; } + +// Internal USE only DO NOT USE directly +#define _SecClearMask(flags, mask) (((flags) | (mask)) ^ (mask)) +#define _SecLogLevel(level) (((level) << 0) & kSecLogLevelMask) +#define _SecLogStyle(style) (((style) << 4) & kSecLogStyleMask) + +__BEGIN_DECLS + +enum SecFlagEnum { + kSecNoFlag = 0, // No flags, no logging nada + kSecLogLevelMask = (15 << 0), // Bits 0-3 contain the log levels 1-15 (since 0 is no flags). + + kSecFirstLogLevel = _SecLogLevel(1), // Lowest log level + kSecDebugLogLevel = _SecLogLevel(1), // log secdebug + kSecInfoLogLevel = _SecLogLevel(2), // log info + kSecNoticeLogLevel = _SecLogLevel(3), // log notice + kSecWarningLogLevel = _SecLogLevel(4), // log warning + kSecErrorLogLevel = _SecLogLevel(5), // log error + kSecCriticalLogLevel = _SecLogLevel(6), // log critical + kSecAlertLogLevel = _SecLogLevel(7), // log alert + kSecLastLogLevel = _SecLogLevel(15),// Max available log level. + + kSecLogStyleMask = ( 0x30), // Bits 4-5 are used to store log style chhoices. The choice is yours. + kSecLogPlainStyle = _SecLogStyle(0), // Log plain message in code only no built in function names. + kSecLogFunctionStyle = _SecLogStyle(1), // Log full __FUNCTION_NAME__ + kSecLogPrettyFuncStyle=_SecLogStyle(2), // Log full ___PRETTY_FUNCTION__ + kSecLogNameStyle = _SecLogStyle(3), // Log name argument to SecWith() + + kSecFlagMask = ( 0xFFC0), // Bits 4-16 are option flags and can be ored together with | + kSecFirstFlag = ( 1 << 6), // First flag defined + + kSecTraceFlag = ( 1 << 6), // trace this api call + kSecChainFlag = ( 1 << 7), // chain multiple errors together in a array with the last error Enclosing all the others. + kSecFlagAssert = ( 1 << 8), // assert that result is not fail without an error having been thrown + kSecSafeModeFlag = ( 1 << 9), // Do not evaluate format arguments to avoid infinite recursion. + kSecClearPendingFlag = ( 1 << 10), // Clear any pending errors. + kSecLogDisabledFlag = ( 1 << 11), // Logging is disabled. + kSecLogAlwaysFlag = ( 1 << 12), // always log regardless of success or failure + kSecLogEveryActionFlag = ( 1 << 13), // log every action + kSecReservedFlag = ( 1 << 14), // Reserved for future use. + kSecLastFlag = ( 1 << 15), // Reserved for future use. + + + kSecActionsMask = (15 << 16), // Bits 4-16 are option flags and can be ored together with | + kSecLowerLogLevelAction = ( 1 << 16), // Allow the log level to be lowered + kSecTraceAction = ( 1 << 17), // Trace this action. + kSecReserved3Action = ( 1 << 18), // Reserved for future use. + kSecReserved4Action = ( 1 << 19), // Reserved for future use. + kSecReserved5Action = ( 1 << 20), // Reserved for future use. + kSecReserved6Action = ( 1 << 21), // Reserved for future use. + kSecReserved7Action = ( 1 << 22), // Reserved for future use. + kSecReserved8Action = ( 1 << 23), // Reserved for future use. + kSecReserved9Action = ( 1 << 24), // Reserved for future use. + kSecReserved10Action = ( 1 << 25), // Reserved for future use. + kSecReserved11Action = ( 1 << 26), // Reserved for future use. + kSecReserved12Action = ( 1 << 27), // Reserved for future use. + kSecReserved13Action = ( 1 << 28), // Reserved for future use. + kSecReserved14Action = ( 1 << 29), // Reserved for future use. + kSecReserved14Action = ( 1 << 30), // Reserved for future use. + kSecLastAction = ( 1 << 31), // The last action defined. + +}; +typedef uint32_t SecFlagType; + +SecInline SecFlagType _SecFlags(flag, ...) { + SecFlagType _flag = flag; + va_list ap; + va_start(ap, flag); + SecFlagType nextFlag; + while ((nextFlag = va_arg(ap, SecFlagType))) _flag |= nextFlag; + va_end(ap); + return _flag; +} + +SecInline void _SecSetLogLevel(SecFlagType flags[1], SecFlagType newFlags) { + SecFlagType newLevel = _SecLogLevel(newFlags); + if (!newLevel || newFlags & kSecLowerLogLevelAction) + *oldFlags = newLevel & _SecClearMask(newFlags, kSecActionsMask); + else if (newLevel > _SecLogLevel(*oldFlags)) + *oldFlags = _SecClearMask(*oldFlags, kSecLogLevelMask) | newLevel; + // Canot lower log level +} + +SecInline void _SecAction(void *_secResult, void *flags, void *name, CFErrorRef *error, CFMutableArrayRef *chain, CFMutableStringRef *actions, SecFlagType flags, key, CFStringRef action, __VA_ARGS__) { +} + +SecInline void _SecSetFlags(SecFlagType oldFlags[1], SecFlagType newFlags) { + // Log level can't be lowered unless kSecLowerLogLevelAction is present in newFlags. + newLevel = newFlags & kSecLogLevelMask + if (!newLevel || newFlags & kSecLowerLogLevelAction) + *oldFlags = newFlags & (kSecLogLevelMask | kSecFlagMask); + else if (newLevel > _SecLogLevel(*oldFlags)) + *oldFlags = _SecClearMask(*oldFlags, kSecLogLevelMask) + (_SecLogLevel(newFlags)) ? _SecClearMask(*oldFlags); + *oldFlags |= newFlags; +} + +SecInline void _SecEnableFlags(SecFlagType oldFlags[1], SecFlagType newFlags) { + (_SecLogLevel(newFlags)) ? _SecClearMask(*oldFlags); + *oldFlags |= newFlags; +} + +SecInline void _SecDisableFlags(SecFlagType oldFlags[1], SecFlagType newFlags) { +} + +__END_DECLS + +#endif /* _UTILITIES_SECMETA_H_ */ diff --git a/Security/utilities/src/SecXPCError.c b/Security/utilities/src/SecXPCError.c new file mode 100644 index 00000000..afa8f001 --- /dev/null +++ b/Security/utilities/src/SecXPCError.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + +#include +#include +#include + +CFStringRef sSecXPCErrorDomain = CFSTR("com.apple.security.xpc"); + +static const char* kDomainKey = "domain"; +static const char* kDescriptionKey = "description"; +static const char* kCodeKey = "code"; + +CFErrorRef SecCreateCFErrorWithXPCObject(xpc_object_t xpc_error) +{ + CFErrorRef result = NULL; + + if (xpc_get_type(xpc_error) == XPC_TYPE_DICTIONARY) { + CFStringRef domain = NULL; + + const char * domain_string = xpc_dictionary_get_string(xpc_error, kDomainKey); + if (domain_string != NULL) { + domain = CFStringCreateWithCString(kCFAllocatorDefault, domain_string, kCFStringEncodingUTF8); + } else { + domain = sSecXPCErrorDomain; + CFRetain(domain); + } + CFIndex code = (CFIndex) xpc_dictionary_get_int64(xpc_error, kCodeKey); + + const char *description = xpc_dictionary_get_string(xpc_error, kDescriptionKey); + + SecCFCreateErrorWithFormat(code, domain, NULL, &result, NULL, CFSTR("Remote error : %s"), description); + + CFReleaseSafe(domain); + } else { + SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, &result, NULL, CFSTR("Remote error not dictionary!: %@"), xpc_error); + } + return result; +} + +static void SecXPCDictionarySetCFString(xpc_object_t dict, const char *key, CFStringRef string) +{ + CFStringPerformWithCString(string, ^(const char *utf8Str) { + xpc_dictionary_set_string(dict, key, utf8Str); + }); +} + +xpc_object_t SecCreateXPCObjectWithCFError(CFErrorRef error) +{ + xpc_object_t error_xpc = xpc_dictionary_create(NULL, NULL, 0); + + SecXPCDictionarySetCFString(error_xpc, kDomainKey, CFErrorGetDomain(error)); + xpc_dictionary_set_int64(error_xpc, kCodeKey, CFErrorGetCode(error)); + + CFStringRef description = CFErrorCopyDescription(error); + SecXPCDictionarySetCFString(error_xpc, kDescriptionKey, description); + CFReleaseNull(description); + + return error_xpc; +} diff --git a/Security/utilities/src/SecXPCError.h b/Security/utilities/src/SecXPCError.h new file mode 100644 index 00000000..0c13b522 --- /dev/null +++ b/Security/utilities/src/SecXPCError.h @@ -0,0 +1,49 @@ +/* + * 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@ + */ + + +#ifndef _UTILITIES_SECXPCERROR_H_ +#define _UTILITIES_SECXPCERROR_H_ + +#include +#include +#include + +__BEGIN_DECLS + +extern CFStringRef sSecXPCErrorDomain; + +enum { + kSecXPCErrorSuccess = 0, + kSecXPCErrorUnexpectedType = 1, + kSecXPCErrorUnexpectedNull = 2, + kSecXPCErrorConnectionFailed = 3, + kSecXPCErrorUnknown = 4, +}; + +CFErrorRef SecCreateCFErrorWithXPCObject(xpc_object_t xpc_error); +xpc_object_t SecCreateXPCObjectWithCFError(CFErrorRef error); + +__END_DECLS + +#endif /* UTILITIES_SECXPCERROR_H */ diff --git a/Security/utilities/src/array_size.h b/Security/utilities/src/array_size.h new file mode 100644 index 00000000..8a365ca7 --- /dev/null +++ b/Security/utilities/src/array_size.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef utilities_array_size_h +#define utilities_array_size_h + +#define array_size(array) (sizeof(array)/sizeof(*array)) + +#endif diff --git a/utilities/src/cloud_keychain_diagnose.c b/Security/utilities/src/cloud_keychain_diagnose.c similarity index 97% rename from utilities/src/cloud_keychain_diagnose.c rename to Security/utilities/src/cloud_keychain_diagnose.c index df2ffa60..155c9f4e 100644 --- a/utilities/src/cloud_keychain_diagnose.c +++ b/Security/utilities/src/cloud_keychain_diagnose.c @@ -2,12 +2,6 @@ * clang cloud_keychain_diagnose.c -laks -framework CoreFoundation -framework IOKit -framework Security -o /tmp/cloud_keychain_diagnose */ - -#if !TARGET_OS_EMBEDDED -#include "sec/Security/SecBase.h" -#include "sec/Security/SecKey.h" -#endif - #include #include @@ -315,6 +309,7 @@ BAIL: close(log_fd); log_fd = -1; + (void) log_fd; } return result; @@ -631,7 +626,6 @@ dump_circle_state( int result = FAILURE; CFErrorRef error = NULL; SOSCCStatus circle_status; - char *circle_state_string = NULL; CFArrayRef peer_list = NULL; CFIndex num_peers; CFIndex i; @@ -640,7 +634,7 @@ dump_circle_state( CFStringRef peer_name; CFStringRef peer_device_type; CFStringRef peerID; - char buffer[BUFFER_SIZE]; + char buffer[BUFFER_SIZE] = {}; /* * Dump the SOS circle state. @@ -657,7 +651,8 @@ dump_circle_state( /* Dump and consume the error. */ dump_cferror(log_file, "Could not call SOSCCThisDeviceIsInCircle", error); } else { - + char *circle_state_string = NULL; + switch (circle_status) { case kSOSCCInCircle: { @@ -679,17 +674,10 @@ dump_circle_state( case kSOSCCError: { circle_state_string = "kSOSCCError"; }break; - - case kSOSCCParamErr: { - circle_state_string = "kSOSCCParamErr"; - }break; - - case kSOSCCMemoryErr: { - circle_state_string = "kSOSCCMemoryErr"; - }break; - + default: { - circle_state_string = "Unknown circle status?"; + sprintf(buffer, "Unknown circle status (%d)?", circle_status); + circle_state_string = buffer; } } @@ -714,7 +702,7 @@ dump_circle_state( /* Copy the peers. */ peer_list = SOSCCCopyPeerPeerInfo(&error); - if (error) { + if (!peer_list) { /* Dump the error. */ dump_cferror(log_file, "Could not call SOSCCCopyPeerPeerInfo", error); @@ -814,7 +802,7 @@ dump_circle_state( /* Copy the applicant peers. */ peer_list = SOSCCCopyApplicantPeerInfo(&error); - if (error) { + if (!peer_list) { /* Dump the error. */ dump_cferror(log_file, "Could not call SOSCCCopyApplicantPeerInfo", error); @@ -1119,7 +1107,7 @@ dump_dict_applier( } else if (CFGetTypeID(value_object) == CFDictionaryGetTypeID()) { - /* Recurse motherfucker! */ + /* Recurse */ fprintf(dump_state->log_file, "\n"); dump_dict(dump_state->log_file, (CFDictionaryRef) value_object, dump_state->indent_level + 1); } else { @@ -1168,7 +1156,7 @@ dump_asl_sender( } else { /* Enumerate the ASL messages in the response. */ - while ((log_message = aslresponse_next(log_response)) != NULL) { + while ((log_message = asl_next(log_response)) != NULL) { /* Format the message entry. */ message_string = asl_format_message((asl_msg_t *)log_message, ASL_MSG_FMT_STD, ASL_TIME_FMT_LCL, ASL_ENCODE_SAFE, &message_length); @@ -1197,7 +1185,7 @@ BAIL: /* Release the ASL response? */ if (log_response != NULL) { - aslresponse_free(log_response); + asl_free(log_response); log_response = NULL; } diff --git a/Security/utilities/src/comparison.c b/Security/utilities/src/comparison.c new file mode 100644 index 00000000..cbc0d969 --- /dev/null +++ b/Security/utilities/src/comparison.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include +#include +#include "comparison.h" + +uint64_t constant_memcmp(const uint8_t *first, const uint8_t *second, size_t count) { + uint64_t error_counter = 0; + for (size_t counter = 0; counter < count; counter++) { + error_counter |= first[counter] ^ second[counter]; + } + return error_counter; +} diff --git a/Security/utilities/src/comparison.h b/Security/utilities/src/comparison.h new file mode 100644 index 00000000..a72f19db --- /dev/null +++ b/Security/utilities/src/comparison.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef utilities_comparison_h +#define utilities_comparison_h + +#define MIN(a, b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a <= _b ? _a : _b; }) +#define MAX(a, b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a >= _b ? _a : _b; }) + +uint64_t constant_memcmp(const uint8_t *first, const uint8_t *second, size_t count); + +#endif diff --git a/Security/utilities/src/debugging.c b/Security/utilities/src/debugging.c new file mode 100644 index 00000000..2d421599 --- /dev/null +++ b/Security/utilities/src/debugging.c @@ -0,0 +1,556 @@ +/* + * Copyright (c) 2006-2010,2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* + * debugging.c - non-trivial debug support + */ +#include "utilities/debugging.h" +#include "utilities/debugging_test.h" +#include "utilities/SecCFWrappers.h" +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + + +const CFStringRef kStringNegate = CFSTR("-"); +const CFStringRef kStringAll = CFSTR("all"); + +const CFStringRef kAPIScope = CFSTR("api"); + +static CFMutableArrayRef sLogSettings = NULL; /* Either sets or dictionaries of level => set. */ + +static dispatch_queue_t GetDispatchControlQueue(void) { + static dispatch_queue_t sLoggingScopeControlQueue; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sLoggingScopeControlQueue = dispatch_queue_create("security scope control", DISPATCH_QUEUE_CONCURRENT); + }); + return sLoggingScopeControlQueue; +} + +static void with_scopes_read(dispatch_block_t action) { + dispatch_sync(GetDispatchControlQueue(), action); +} + +static void with_scopes_write(dispatch_block_t action) { + dispatch_barrier_sync(GetDispatchControlQueue(), action); +} + +bool IsScopeActive(int level, CFStringRef scope) +{ + if (scope == NULL) + return true; + + CFNumberRef level_number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &level); + + __block bool isActive = false; + with_scopes_read(^{ + if (sLogSettings) { + CFArrayForEach(sLogSettings, ^(const void *value) { + CFSetRef setToCheck = NULL; + + if (isSet(value)) { + setToCheck = (CFSetRef) value; + } else if (isDictionary(value)) { + CFDictionaryRef levels = (CFDictionaryRef) value; + + setToCheck = CFDictionaryGetValue(levels, level_number); + + if (!isSet(setToCheck)) + setToCheck = NULL; + } + + if (setToCheck != NULL && !isActive) { + bool negated = CFSetContainsValue(setToCheck, kStringNegate); + bool inSet = CFSetContainsValue(setToCheck, scope); + + isActive = negated ^ inSet; + } + }); + } + }); + + CFReleaseNull(level_number); + + return isActive; +} + +bool IsScopeActiveC(int level, const char *scope) +{ + CFStringRef scopeString = CFStringCreateWithBytes(kCFAllocatorDefault, (const uint8_t*)scope, strlen(scope), kCFStringEncodingUTF8, false); + bool isActive = IsScopeActive(level, scopeString); + CFReleaseNull(scopeString); + + return isActive; +} + + + +static CFStringRef copyScopeName(const char *scope, CFIndex scopeLen) { + return CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8 *)scope, + scopeLen, kCFStringEncodingUTF8, false); +} + +static CFMutableSetRef CopyScopesFromScopeList(CFStringRef scopes) { + CFMutableSetRef resultSet = CFSetCreateMutableForCFTypes(kCFAllocatorDefault); + + CFStringRef allocated_scope_list = NULL; + CFStringRef clean_scope_list = scopes; + bool add_negate = false; + + if (CFStringHasPrefix(scopes, kStringNegate)) { + allocated_scope_list = CFStringCreateWithSubstring(kCFAllocatorDefault, scopes, CFRangeMake(CFStringGetLength(kStringNegate), CFStringGetLength(scopes) - 1)); + clean_scope_list = allocated_scope_list; + add_negate = true; + } + + CFArrayRef commaArray = CFStringCreateArrayBySeparatingStrings(kCFAllocatorDefault, clean_scope_list, CFSTR(",")); + + if (commaArray) { + CFArrayForEach(commaArray, ^(const void *value) { + if (isString(value)) { + CFMutableStringRef copy = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, (CFStringRef) value); + CFStringTrimWhitespace(copy); + CFSetSetValue(resultSet, copy); + CFReleaseNull(copy); + } + }); + } + + CFSetRemoveValue(resultSet, CFSTR("none")); + CFSetRemoveValue(resultSet, CFSTR("")); + + if (CFSetContainsValue(resultSet, CFSTR("all"))) { + CFSetRemoveAllValues(resultSet); + add_negate = !add_negate; + } + + if (add_negate) + CFSetSetValue(resultSet, kStringNegate); + + CFReleaseNull(commaArray); + CFReleaseNull(allocated_scope_list); + + return resultSet; +} + +static CFMutableArrayRef CFArrayCreateMutableForCFTypesFilledWithCFNull(CFAllocatorRef allocator, CFIndex capacity) { + CFMutableArrayRef result = CFArrayCreateMutableForCFTypesWithCapacity(kCFAllocatorDefault, kScopeIDMax); + + for(int count = 0; count <= capacity; ++count) + CFArrayAppendValue(result, kCFNull); + + return result; +} + +static bool CFArrayIsAll(CFArrayRef array, const void *value) +{ + return CFArrayGetCountOfValue(array, CFRangeMake(0, CFArrayGetCount(array)), value) == CFArrayGetCount(array); +} + +static void SetNthScopeSet(int nth, CFTypeRef collection) +{ + with_scopes_write(^{ + if (sLogSettings == NULL) { + sLogSettings = CFArrayCreateMutableForCFTypesFilledWithCFNull(kCFAllocatorDefault, kScopeIDMax); + } + + CFArraySetValueAtIndex(sLogSettings, nth, collection); + + if (CFArrayIsAll(sLogSettings, kCFNull)) { + CFReleaseNull(sLogSettings); + } + }); +} + +static int string_to_log_level(CFStringRef string) { + if (CFEqual(string, CFSTR(ASL_STRING_EMERG))) + return ASL_LEVEL_EMERG; + else if (CFEqual(string, CFSTR(ASL_STRING_ALERT))) + return ASL_LEVEL_ALERT; + else if (CFEqual(string, CFSTR(ASL_STRING_CRIT))) + return ASL_LEVEL_CRIT; + else if (CFEqual(string, CFSTR(ASL_STRING_ERR))) + return ASL_LEVEL_ERR; + else if (CFEqual(string, CFSTR(ASL_STRING_WARNING))) + return ASL_LEVEL_WARNING; + else if (CFEqual(string, CFSTR(ASL_STRING_NOTICE))) + return ASL_LEVEL_NOTICE; + else if (CFEqual(string, CFSTR(ASL_STRING_INFO))) + return ASL_LEVEL_INFO; + else if (CFEqual(string, CFSTR(ASL_STRING_DEBUG))) + return ASL_LEVEL_DEBUG; + else + return -1; +} + +static void CFSetAppendValues(CFSetRef set, CFMutableArrayRef appendTo) +{ + CFSetForEach(set, ^(const void *value) { + CFArrayAppendValue(appendTo, value); + }); +} + +static CFMutableArrayRef CFSetOfCFObjectsCopyValues(CFSetRef setOfCFs) +{ + CFMutableArrayRef result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + + CFSetForEach(setOfCFs, ^(const void *value) { + CFArrayAppendValue(result, value); + }); + + return result; +} + +CFPropertyListRef CopyCurrentScopePlist(void) +{ + CFMutableArrayRef result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + with_scopes_read(^{ + CFArrayForEach(sLogSettings, ^(const void *value) { + if (isSet(value)) { + CFArrayRef values = CFSetOfCFObjectsCopyValues((CFSetRef) value); + CFArrayAppendValue(result, values); + CFReleaseNull(values); + } else if (isDictionary(value)) { + CFMutableDictionaryRef levels = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + + CFDictionaryForEach((CFDictionaryRef) value, ^(const void *key, const void *value) { + if (isSet(value)) { + CFArrayRef values = CFSetOfCFObjectsCopyValues((CFSetRef) value); + CFDictionaryAddValue(levels, key, values); + CFReleaseNull(values); + } + }); + + CFArrayAppendValue(result, levels); + } else { + CFArrayAppendValue(result, kCFNull); + } + }); + }); + return result; +} + +void ApplyScopeDictionaryForID(CFDictionaryRef scopeDictionary, SecDebugScopeID whichID) +{ + CFMutableDictionaryRef dictionary_for_id = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + + CFDictionaryForEach(scopeDictionary, ^(const void *key, const void *value) { + CFSetRef scope_set = NULL; + CFNumberRef key_number = NULL; + if (isString(key)) { + int level = string_to_log_level((CFStringRef) key); + + if (level >= 0) + key_number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &level); + } else if (isNumber(key)) { + key_number = CFRetainSafe(key); + } + + if (isString(value)) { + scope_set = CopyScopesFromScopeList(value); + } + + if (key_number && scope_set) + CFDictionaryAddValue(dictionary_for_id, key_number, scope_set); + + CFReleaseNull(key_number); + CFReleaseNull(scope_set); + }); + + if (CFDictionaryGetCount(dictionary_for_id) > 0) { + SetNthScopeSet(whichID, dictionary_for_id); + } + + CFReleaseNull(dictionary_for_id); +} + +void ApplyScopeListForID(CFStringRef scopeList, SecDebugScopeID whichID) +{ + CFMutableSetRef scopesToUse = CopyScopesFromScopeList(scopeList); + + SetNthScopeSet(whichID, scopesToUse); + + CFReleaseNull(scopesToUse); +} + +void ApplyScopeListForIDC(const char *scopeList, SecDebugScopeID whichID) { + CFStringRef scope_string = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, scopeList, kCFStringEncodingUTF8, kCFAllocatorNull); + + ApplyScopeListForID(scope_string, whichID); + + CFReleaseNull(scope_string); +} + +#pragma mark - Log Handlers to catch log information + +static CFMutableArrayRef sSecurityLogHandlers; + +#if TARGET_OS_IPHONE + +/* + * Instead of using CFPropertyListReadFromFile we use a + * CFPropertyListCreateWithStream directly + * here. CFPropertyListReadFromFile() uses + * CFURLCopyResourcePropertyForKey() andCF pulls in CoreServices for + * CFURLCopyResourcePropertyForKey() and that doesn't work in install + * enviroment. + */ + +static CFPropertyListRef +CopyPlistFromFile(CFURLRef url) +{ + CFDictionaryRef d = NULL; + CFReadStreamRef s = CFReadStreamCreateWithFile(kCFAllocatorDefault, url); + if (s && CFReadStreamOpen(s)) { + d = (CFDictionaryRef)CFPropertyListCreateWithStream(kCFAllocatorDefault, s, 0, kCFPropertyListImmutable, NULL, NULL); + } + CFReleaseSafe(s); + + return d; +} +#endif + +static void ApplyScopeByTypeForID(CFPropertyListRef scopes, SecDebugScopeID whichID) { + if (isDictionary(scopes)) { + ApplyScopeDictionaryForID(scopes, whichID); + } else if (isString(scopes)) { + ApplyScopeListForID(scopes, whichID); + } +} + +static void setup_config_settings() { +#if TARGET_OS_IPHONE + CFURLRef prefURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("/Library/Managed Preferences/mobile/.GlobalPreferences.plist"), kCFURLPOSIXPathStyle, false); + if(prefURL) { + CFPropertyListRef plist = CopyPlistFromFile(prefURL); + if (plist) { + ApplyScopeByTypeForID(CFDictionaryGetValue(plist, CFSTR("SecLogging")), kScopeIDConfig); + } + CFReleaseSafe(plist); + } + CFReleaseSafe(prefURL); +#endif +} + +static void setup_defaults_settings() { + CFPropertyListRef scopes_value = CFPreferencesCopyValue(CFSTR("Logging"), CFSTR("com.apple.security"), kCFPreferencesAnyUser, kCFPreferencesCurrentHost); + + ApplyScopeByTypeForID(scopes_value, kScopeIDDefaults); + + CFReleaseSafe(scopes_value); +} + +static void setup_environment_scopes() { + const char *cur_scope = getenv("DEBUGSCOPE"); + if (cur_scope == NULL) + cur_scope = ""; + + ApplyScopeListForIDC(cur_scope, kScopeIDEnvironment); +} + +void __security_debug_init(void) { + static dispatch_once_t sdOnceToken; + + dispatch_once(&sdOnceToken, ^{ + setup_environment_scopes(); + setup_config_settings(); + setup_defaults_settings(); + }); +} + + +// MARK: Log handler recording (e.g. grabbing security logging and sending it to test results). +static void clean_aslclient(void *client) +{ + asl_close(client); +} + +static aslclient get_aslclient() +{ + static dispatch_once_t once; + static pthread_key_t asl_client_key; + dispatch_once(&once, ^{ + pthread_key_create(&asl_client_key, clean_aslclient); + }); + aslclient client = pthread_getspecific(asl_client_key); + if (!client) { + client = asl_open(NULL, "SecLogging", 0); + asl_set_filter(client, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG)); + pthread_setspecific(asl_client_key, client); + } + + return client; +} + +static CFMutableArrayRef get_log_handlers() +{ + static dispatch_once_t handlers_once; + + dispatch_once(&handlers_once, ^{ + sSecurityLogHandlers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + + CFArrayAppendValue(sSecurityLogHandlers, ^(int level, CFStringRef scope, const char *function, + const char *file, int line, CFStringRef message){ + CFStringRef logStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %s %@\n"), scope ? scope : CFSTR(""), function, message); + CFStringPerformWithCString(logStr, ^(const char *logMsg) { + aslmsg msg = asl_new(ASL_TYPE_MSG); + if (scope) { + CFStringPerformWithCString(scope, ^(const char *scopeStr) { + asl_set(msg, ASL_KEY_FACILITY, scopeStr); + }); + } + asl_log(get_aslclient(), msg, level, "%s", logMsg); + asl_free(msg); + }); + CFReleaseSafe(logStr); + }); + }); + + return sSecurityLogHandlers; +} + +static void log_api_trace_v(const char *api, const char *caller_info, CFStringRef format, va_list args) +{ + aslmsg msg = asl_new(ASL_TYPE_MSG); + asl_set(msg, ASL_KEY_LEVEL, ASL_STRING_DEBUG); + CFStringPerformWithCString(kAPIScope, ^(const char *scopeStr) { + asl_set(msg, ASL_KEY_FACILITY, scopeStr); + }); + asl_set(msg, "SecAPITrace", api); + asl_set(msg, caller_info ? "ENTER" : "RETURN", ""); + + if (format) { + CFStringRef message = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, format, args); + CFStringPerformWithCString(message, ^(const char *utf8Str) { + asl_set(msg, ASL_KEY_MSG, utf8Str); + }); + CFReleaseSafe(message); + } + + if (caller_info) { + asl_set(msg, "CALLER", caller_info); + } + + asl_send(get_aslclient(), msg); + asl_free(msg); +} + +void __security_trace_enter_api(const char *api, CFStringRef format, ...) +{ + if (!IsScopeActive(ASL_LEVEL_DEBUG, kAPIScope)) + return; + + va_list args; + va_start(args, format); + + { + char stack_info[80]; + + snprintf(stack_info, sizeof(stack_info), "C%p F%p", __builtin_return_address(1), __builtin_frame_address(2)); + + log_api_trace_v(api, stack_info, format, args); + } + + va_end(args); +} + +void __security_trace_return_api(const char *api, CFStringRef format, ...) +{ + if (!IsScopeActive(ASL_LEVEL_DEBUG, kAPIScope)) + return; + + va_list args; + va_start(args, format); + + log_api_trace_v(api, NULL, format, args); + + va_end(args); +} + + +void add_security_log_handler(security_log_handler handler) +{ + CFArrayAppendValue(get_log_handlers(), handler); +} + +void remove_security_log_handler(security_log_handler handler) +{ + CFArrayRemoveAllValue(get_log_handlers(), handler); +} + +static void __security_post_msg(int level, CFStringRef scope, const char *function, + const char *file, int line, CFStringRef message) +{ + CFArrayForEach(get_log_handlers(), ^(const void *value) { + security_log_handler handler = (security_log_handler) value; + + handler(level, scope, function, file, line, message); + }); +} + +static void __security_log_msg_v(int level, CFStringRef scope, const char *function, + const char *file, int line, CFStringRef format, va_list args) +{ + __security_debug_init(); + + if (!IsScopeActive(level, scope)) + return; + + CFStringRef message = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, format, args); + __security_post_msg(level, scope, function, file, line, message); + CFRelease(message); + +} + +void __security_debug(CFStringRef scope, const char *function, + const char *file, int line, CFStringRef format, ...) +{ + va_list args; + va_start(args, format); + + __security_log_msg_v(ASL_LEVEL_DEBUG, scope, function, file, line, format, args); + + va_end(args); +} + +void __security_log(int level, CFStringRef scope, const char *function, + const char *file, int line, CFStringRef format, ...) +{ + va_list args; + va_start(args, format); + + __security_log_msg_v(level, scope, function, file, line, format, args); + + va_end(args); +} diff --git a/Security/utilities/src/debugging.h b/Security/utilities/src/debugging.h new file mode 100644 index 00000000..6505702e --- /dev/null +++ b/Security/utilities/src/debugging.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2006-2007,2009-2010,2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * debugging.h - non-trivial debug support + */ +#ifndef _SECURITY_UTILITIES_DEBUGGING_H_ +#define _SECURITY_UTILITIES_DEBUGGING_H_ + +#ifdef KERNEL + #include + #define secalert(format, ...) printf((format), ## __VA_ARGS__) + #define secemergency(format, ...) printf((format), ## __VA_ARGS__) + #define seccritical(format, ...) printf((format), ## __VA_ARGS__) + #define secerror(format, ...) printf((format), ## __VA_ARGS__) + #define secwarning(format, ...) printf((format), ## __VA_ARGS__) + #define secnotice(scope, format, ...) printf((format), ## __VA_ARGS__) + #define secnoticeq(scope, format, ...) printf((format), ## __VA_ARGS__) + #define secinfo(scope, format, ...) printf((format), ## __VA_ARGS__) + #if !defined(NDEBUG) + #define secdebug(scope, format, ...) printf((format), ## __VA_ARGS__) + #else // NDEBUG + #define secdebug(scope, format, ...) /* nothing */ + #endif // NDEBUG +#else // !KERNEL + +#include +#include +#include + +__BEGIN_DECLS + +extern void __security_trace_enter_api(const char *api, CFStringRef format, ...) CF_FORMAT_FUNCTION(2, 3); +extern void __security_trace_return_api(const char *api, CFStringRef format, ...) CF_FORMAT_FUNCTION(2, 3); + +extern void __security_debug(CFStringRef scope, + const char *function, const char *file, int line, + CFStringRef format, ...) CF_FORMAT_FUNCTION(5,6); + +extern void __security_log(int level, CFStringRef scope, + const char *function, const char *file, int line, + CFStringRef format, ...) CF_FORMAT_FUNCTION(6,7); + +#define sec_trace_enter_api(format...) __security_trace_enter_api(__FUNCTION__, format) +#define sec_trace_return_api(rtype, body, format...) { rtype _r = body(); __security_trace_return_api(__FUNCTION__, format, _r); return _r; } +#define sec_trace_return_bool_api(body, format...) { bool _r = body(); typeof(format) _fmt = format; __security_trace_return_api(__FUNCTION__, _fmt ? _fmt : CFSTR("return=%d"), (int)_r); return _r; } + +#define secemergency(format, ...) __security_log(ASL_LEVEL_EMERG, NULL, \ + __FUNCTION__, __FILE__, __LINE__, \ + CFSTR(format), ## __VA_ARGS__) + +#define secalert(format, ...) __security_log(ASL_LEVEL_ALERT, NULL, \ + __FUNCTION__, __FILE__, __LINE__, \ + CFSTR(format), ## __VA_ARGS__) + +#define seccritical(format, ...) __security_log(ASL_LEVEL_CRIT, NULL, \ + __FUNCTION__, __FILE__, __LINE__, \ + CFSTR(format), ## __VA_ARGS__) + +#define secerror(format, ...) __security_log(ASL_LEVEL_ERR, NULL, \ + __FUNCTION__, __FILE__, __LINE__, \ + CFSTR(format), ## __VA_ARGS__) + +#define secerrorq(format, ...) __security_log(ASL_LEVEL_ERR, NULL, \ + "", "", 0, \ + CFSTR(format), ## __VA_ARGS__) + +#define secwarning(format, ...) __security_log(ASL_LEVEL_WARNING, NULL, \ + __FUNCTION__, __FILE__, __LINE__, \ + CFSTR(format), ## __VA_ARGS__) + +#define secnotice(scope, format, ...) __security_log(ASL_LEVEL_NOTICE, CFSTR(scope), \ + __FUNCTION__, __FILE__, __LINE__, \ + CFSTR(format), ## __VA_ARGS__) + +#define secnoticeq(scope, format, ...) __security_log(ASL_LEVEL_NOTICE, CFSTR(scope), \ + "", "", 0, \ + CFSTR(format), ## __VA_ARGS__) + +#define secinfo(scope, format, ...) __security_log(ASL_LEVEL_INFO, CFSTR(scope), \ + __FUNCTION__, __FILE__, __LINE__, \ + CFSTR(format), ## __VA_ARGS__) + +#if !defined(NDEBUG) + +# define secdebug(scope,format, ...) __security_debug(CFSTR(scope), \ + __FUNCTION__, __FILE__, __LINE__, \ + CFSTR(format), ## __VA_ARGS__) +#else +# define secdebug(scope,...) /* nothing */ +#endif + +typedef void (^security_log_handler)(int level, CFStringRef scope, const char *function, + const char *file, int line, CFStringRef message); + +void add_security_log_handler(security_log_handler handler); +void remove_security_log_handler(security_log_handler handler); + +/* To simulate a process crash in some conditions */ +void __security_simulatecrash(CFStringRef reason, uint32_t code); + +/* predefined simulate crash exception codes */ +#define __sec_exception_code(x) (0x53c00000+x) +#define __sec_exception_code_CorruptDb(db,rc) __sec_exception_code(1|((db)<<8)|((rc)<<16)) +#define __sec_exception_code_CorruptItem __sec_exception_code(2) +#define __sec_exception_code_OTRError __sec_exception_code(3) +#define __sec_exception_code_DbItemDescribe __sec_exception_code(4) +#define __sec_exception_code_TwiceCorruptDb(db) __sec_exception_code(5|((db)<<8)) + +/* Logging control functions */ + +typedef enum { + kScopeIDEnvironment = 0, + kScopeIDDefaults = 1, + kScopeIDConfig = 2, + kScopeIDXPC = 3, + kScopeIDMax = 3, +} SecDebugScopeID; + +void ApplyScopeListForID(CFStringRef scopeList, SecDebugScopeID whichID); +void ApplyScopeDictionaryForID(CFDictionaryRef scopeList, SecDebugScopeID whichID); +CFPropertyListRef CopyCurrentScopePlist(void); + +__END_DECLS + +#endif // !KERNEL + +#endif /* _SECURITY_UTILITIES_DEBUGGING_H_ */ diff --git a/Security/utilities/src/debugging_test.h b/Security/utilities/src/debugging_test.h new file mode 100644 index 00000000..444c667b --- /dev/null +++ b/Security/utilities/src/debugging_test.h @@ -0,0 +1,32 @@ +// +// debugging_test.h +// Copyright (c) 2014 Apple Inc. All Rights Reserved. +// + +// +// Interfaces exported for tests for debugging code. +// + +#ifndef _SECURITY_UTILITIES_DEBUGGING_TEST_H_ +#define _SECURITY_UTILITIES_DEBUGGING_TEST_H_ + +#include +#include "utilities/debugging.h" + +__BEGIN_DECLS + +// +// These would all be static inside +// debugging.c, but unit tests can use them +// + +void __security_debug_init(void); + +bool IsScopeActive(int level, CFStringRef scope); +bool IsScopeActiveC(int level, const char *scope); + +void ApplyScopeListForIDC(const char *scopeList, SecDebugScopeID whichID); + +__END_DECLS + +#endif diff --git a/Security/utilities/src/der_array.c b/Security/utilities/src/der_array.c new file mode 100644 index 00000000..95eaf95e --- /dev/null +++ b/Security/utilities/src/der_array.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + +#include "utilities/SecCFRelease.h" +#include "utilities/der_plist.h" +#include "utilities/der_plist_internal.h" + +#include +#include + + +const uint8_t* der_decode_array(CFAllocatorRef allocator, CFOptionFlags mutability, + CFArrayRef* array, CFErrorRef *error, + const uint8_t* der, const uint8_t *der_end) +{ + if (NULL == der) + return NULL; + + CFMutableArrayRef result = CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks); + + const uint8_t *elements_end; + const uint8_t *current_element = ccder_decode_sequence_tl(&elements_end, der, der_end); + + while (current_element != NULL && current_element < elements_end) { + CFPropertyListRef element = NULL; + current_element = der_decode_plist(allocator, mutability, &element, error, current_element, elements_end); + if (current_element) { + CFArrayAppendValue(result, element); + CFReleaseNull(element); + } + } + + if (current_element) { + *array = result; + result = NULL; + } + + CFReleaseNull(result); + return current_element; +} + + +size_t der_sizeof_array(CFArrayRef data, CFErrorRef *error) +{ + size_t body_size = 0; + for(CFIndex position = CFArrayGetCount(data) - 1; + position >= 0; + --position) + { + body_size += der_sizeof_plist(CFArrayGetValueAtIndex(data, position), error); + } + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, body_size); +} + + +uint8_t* der_encode_array(CFArrayRef array, CFErrorRef *error, + const uint8_t *der, uint8_t *der_end) +{ + uint8_t* original_der_end = der_end; + for(CFIndex position = CFArrayGetCount(array) - 1; + position >= 0; + --position) + { + der_end = der_encode_plist(CFArrayGetValueAtIndex(array, position), error, der, der_end); + } + + return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, original_der_end, der, der_end); +} diff --git a/Security/utilities/src/der_boolean.c b/Security/utilities/src/der_boolean.c new file mode 100644 index 00000000..4ad2ce5a --- /dev/null +++ b/Security/utilities/src/der_boolean.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + +#include "utilities/SecCFRelease.h" +#include "utilities/der_plist.h" +#include "utilities/der_plist_internal.h" + +#include +#include + + +const uint8_t* der_decode_boolean(CFAllocatorRef allocator, CFOptionFlags mutability, + CFBooleanRef* boolean, CFErrorRef *error, + const uint8_t* der, const uint8_t *der_end) +{ + if (NULL == der) + return NULL; + + size_t payload_size = 0; + const uint8_t *payload = ccder_decode_tl(CCDER_BOOLEAN, &payload_size, der, der_end); + + if (NULL == payload || (der_end - payload) < payload_size || payload_size != 1) { + SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown boolean encoding"), NULL, error); + return NULL; + } + + *boolean = *payload ? kCFBooleanTrue : kCFBooleanFalse; + + return payload + payload_size; +} + + +size_t der_sizeof_boolean(CFBooleanRef data __unused, CFErrorRef *error) +{ + return ccder_sizeof(CCDER_BOOLEAN, 1); +} + + +uint8_t* der_encode_boolean(CFBooleanRef boolean, CFErrorRef *error, + const uint8_t *der, uint8_t *der_end) +{ + uint8_t value = CFBooleanGetValue(boolean); + + return ccder_encode_tl(CCDER_BOOLEAN, 1, der, + ccder_encode_body(1, &value, der, der_end)); + +} diff --git a/Security/utilities/src/der_data.c b/Security/utilities/src/der_data.c new file mode 100644 index 00000000..404aaea6 --- /dev/null +++ b/Security/utilities/src/der_data.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + +#include "utilities/SecCFRelease.h" +#include "utilities/der_plist.h" +#include "utilities/der_plist_internal.h" + +#include +#include + + +const uint8_t* der_decode_data_mutable(CFAllocatorRef allocator, CFOptionFlags mutability, + CFMutableDataRef* data, CFErrorRef *error, + const uint8_t* der, const uint8_t *der_end) +{ + if (NULL == der) + return NULL; + + size_t payload_size = 0; + const uint8_t *payload = ccder_decode_tl(CCDER_OCTET_STRING, &payload_size, der, der_end); + + if (NULL == payload || (der_end - payload) < payload_size) { + SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown data encoding"), NULL, error); + return NULL; + } + + *data = CFDataCreateMutable(allocator, 0); + + if (NULL == *data) { + SecCFDERCreateError(kSecDERErrorAllocationFailure, CFSTR("Failed to create data"), NULL, error); + return NULL; + } + + CFDataAppendBytes(*data, payload, payload_size); + + return payload + payload_size; +} + + +const uint8_t* der_decode_data(CFAllocatorRef allocator, CFOptionFlags mutability, + CFDataRef* data, CFErrorRef *error, + const uint8_t* der, const uint8_t *der_end) +{ + if (NULL == der) + return NULL; + + size_t payload_size = 0; + const uint8_t *payload = ccder_decode_tl(CCDER_OCTET_STRING, &payload_size, der, der_end); + + if (NULL == payload || (der_end - payload) < payload_size) { + SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown data encoding"), NULL, error); + return NULL; + } + + *data = CFDataCreate(allocator, payload, payload_size); + + if (NULL == *data) { + SecCFDERCreateError(kSecDERErrorAllocationFailure, CFSTR("Failed to create data"), NULL, error); + return NULL; + } + + return payload + payload_size; +} + + +size_t der_sizeof_data(CFDataRef data, CFErrorRef *error) +{ + return ccder_sizeof_raw_octet_string(CFDataGetLength(data)); +} + + +uint8_t* der_encode_data(CFDataRef data, CFErrorRef *error, + const uint8_t *der, uint8_t *der_end) +{ + const CFIndex data_length = CFDataGetLength(data); + + return ccder_encode_tl(CCDER_OCTET_STRING, data_length, der, + ccder_encode_body(data_length, CFDataGetBytePtr(data), der, der_end)); + +} diff --git a/Security/utilities/src/der_date.c b/Security/utilities/src/der_date.c new file mode 100644 index 00000000..08b56870 --- /dev/null +++ b/Security/utilities/src/der_date.c @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include "utilities/SecCFRelease.h" +#include "utilities/SecCFWrappers.h" +#include "utilities/der_date.h" +#include "utilities/der_plist.h" +#include "utilities/der_plist_internal.h" + +#include +#include +#include +#include + +#define NULL_TIME NAN + +/* Cumulative number of days in the year for months up to month i. */ +static int mdays[13] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; + +static CFAbsoluteTime SecGregorianDateGetAbsoluteTime(int year, int month, int day, int hour, int minute, int second, CFTimeInterval timeZoneOffset, CFErrorRef *error) { + int is_leap_year = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) ? 1 : 0; + if (month < 1 || month > 12 || day < 1 || day > 31 || hour >= 24 || minute >= 60 || second >= 60.0 + || (month == 2 && day > mdays[month] - mdays[month - 1] + is_leap_year) + || (month != 2 && day > mdays[month] - mdays[month - 1])) { + /* Invalid date. */ + SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Invalid date."), 0, error); + return NULL_TIME; + } + + int dy = year - 2001; + if (dy < 0) { + dy += 1; + day -= 1; + } + + int leap_days = dy / 4 - dy / 100 + dy / 400; + day += ((year - 2001) * 365 + leap_days) + mdays[month - 1] - 1; + if (month > 2) + day += is_leap_year; + + CFAbsoluteTime absTime = (CFAbsoluteTime)((day * 24 + hour) * 60 + minute) * 60 + second; + return absTime - timeZoneOffset; +} + +static bool SecAbsoluteTimeGetGregorianDate(CFTimeInterval at, int *year, int *month, int *day, int *hour, int *minute, int *second, CFErrorRef *error) { + // TODO: Remove CFCalendarDecomposeAbsoluteTime dependancy because CFTimeZoneCreateWithTimeIntervalFromGMT is expensive and requires filesystem access to timezone files when we are only doing zulu time anyway + if (!CFCalendarDecomposeAbsoluteTime(SecCFCalendarGetZulu(), at, "yMdHms", year, month, day, hour, minute, second)) { + SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Failed to encode date."), 0, error); + return false; + } + return true; +} + +static int der_get_char(const uint8_t **der_p, const uint8_t *der_end, + CFErrorRef *error) { + const uint8_t *der = *der_p; + if (!der) { + /* Don't create a new error in this case. */ + return -1; + } + + if (der >= der_end) { + SecCFDERCreateError(kSecDERErrorUnknownEncoding, + CFSTR("Unexpected end of datetime"), 0, error); + *der_p = NULL; + return -1; + } + + int ch = *der++; + *der_p = der; + return ch; +} + + +static int der_decode_decimal(const uint8_t **der_p, const uint8_t *der_end, + CFErrorRef *error) { + char ch = der_get_char(der_p, der_end, error); + if (ch < '0' || ch > '9') { + SecCFDERCreateError(kSecDERErrorUnknownEncoding, + CFSTR("Not a decimal digit"), 0, error); + *der_p = NULL; + return -1; + } + return ch - '0'; +} + +static int der_decode_decimal_pair(const uint8_t **der_p, const uint8_t *der_end, + CFErrorRef *error) { + return (10 * der_decode_decimal(der_p, der_end, error)) + + der_decode_decimal(der_p, der_end, error); +} + +static int der_peek_byte(const uint8_t *der, const uint8_t *der_end) { + if (!der || der >= der_end) + return -1; + + return *der; +} + +static const uint8_t *der_decode_decimal_fraction(double *fraction, CFErrorRef *error, + const uint8_t* der, const uint8_t *der_end) { + int ch = der_peek_byte(der, der_end); + if (ch == -1) { + der = NULL; + } else if (ch == '.') { + uint64_t divisor = 1; + uint64_t value = 0; + int last = -1; + while (++der < der_end) { + last = ch; + ch = *der; + if (ch < '0' || ch > '9') { + break; + } + if (divisor < UINT64_MAX / 10) { + divisor *= 10; + value *= 10; + value += (ch - '0'); + } + } + if (der >= der_end) + der = NULL; + else if (last == '0') { + SecCFDERCreateError(kSecDERErrorUnknownEncoding, + CFSTR("fraction ends in 0"), 0, error); + der = NULL; + } else if (last == '.') { + SecCFDERCreateError(kSecDERErrorUnknownEncoding, + CFSTR("fraction without digits"), 0, error); + der = NULL; + } else { + *fraction = (double)value / divisor; + } + } else { + *fraction = 0.0; + } + + return der; +} + +static const CFTimeInterval der_decode_timezone_offset(const uint8_t **der_p, + const uint8_t *der_end, + CFErrorRef *error) { + CFTimeInterval timeZoneOffset; + int ch = der_get_char(der_p, der_end, error); + if (ch == 'Z') { + /* Zulu time. */ + timeZoneOffset = 0.0; + } else { + /* ZONE INDICATOR */ + int multiplier; + if (ch == '-') + multiplier = -60; + else if (ch == '+') + multiplier = +60; + else { + SecCFDERCreateError(kSecDERErrorUnknownEncoding, + CFSTR("Invalid datetime character"), 0, error); + return NULL_TIME; + } + + timeZoneOffset = multiplier * + (der_decode_decimal_pair(der_p, der_end, error) + * 60 + der_decode_decimal_pair(der_p, der_end, error)); + } + return timeZoneOffset; +} + +static const uint8_t* der_decode_commontime_body(CFAbsoluteTime *at, CFErrorRef *error, int year, + const uint8_t* der, const uint8_t *der_end) +{ + int month = der_decode_decimal_pair(&der, der_end, error); + int day = der_decode_decimal_pair(&der, der_end, error); + int hour = der_decode_decimal_pair(&der, der_end, error); + int minute = der_decode_decimal_pair(&der, der_end, error); + int second = der_decode_decimal_pair(&der, der_end, error); + double fraction; + der = der_decode_decimal_fraction(&fraction, error, der, der_end); + + CFTimeInterval timeZoneOffset = der_decode_timezone_offset(&der, der_end, error); + +#if 0 + secdebug("dateparse", + "date %.*s year: %04d%02d%02d%02d%02d%02d%+05g", + length, bytes, g.year, g.month, + g.day, g.hour, g.minute, g.second, + timeZoneOffset / 60); +#endif + + if (der) { + if (der != der_end) { + SecCFDERCreateError(kSecDERErrorUnknownEncoding, + CFSTR("trailing garbage at end of datetime"), 0, error); + return NULL; + } + + *at = SecGregorianDateGetAbsoluteTime(year, month, day, hour, minute, second, timeZoneOffset, error) + fraction; + if (*at == NULL_TIME) + return NULL; + } + + return der; +} + +const uint8_t* der_decode_generalizedtime_body(CFAbsoluteTime *at, CFErrorRef *error, + const uint8_t* der, const uint8_t *der_end) +{ + int year = 100 * der_decode_decimal_pair(&der, der_end, error) + der_decode_decimal_pair(&der, der_end, error); + return der_decode_commontime_body(at, error, year, der, der_end); +} + +const uint8_t* der_decode_universaltime_body(CFAbsoluteTime *at, CFErrorRef *error, + const uint8_t* der, const uint8_t *der_end) +{ + SInt32 year = der_decode_decimal_pair(&der, der_end, error); + if (year < 50) { + /* 0 <= year < 50 : assume century 21 */ + year += 2000; + } else if (year < 70) { + /* 50 <= year < 70 : illegal per PKIX */ + SecCFDERCreateError(kSecDERErrorUnknownEncoding, + CFSTR("Invalid universal time year between 50 and 70"), 0, error); + der = NULL; + } else { + /* 70 < year <= 99 : assume century 20 */ + year += 1900; + } + + return der_decode_commontime_body(at, error, year, der, der_end); +} + +const uint8_t* der_decode_date(CFAllocatorRef allocator, CFOptionFlags mutability, + CFDateRef* date, CFErrorRef *error, + const uint8_t* der, const uint8_t *der_end) +{ + if (NULL == der) + return NULL; + + der = ccder_decode_constructed_tl(CCDER_GENERALIZED_TIME, &der_end, der, der_end); + CFAbsoluteTime at = 0; + der = der_decode_generalizedtime_body(&at, error, der, der_end); + if (der) { + *date = CFDateCreate(allocator, at); + if (NULL == *date) { + SecCFDERCreateError(kSecDERErrorAllocationFailure, CFSTR("Failed to create date"), NULL, error); + return NULL; + } + } + return der; +} + +extern char *__dtoa(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve); +extern void __freedtoa(char *); + +static size_t ccder_sizeof_nanoseconds(CFAbsoluteTime at) { + int dotoff; + int sign; + char *end; + char *str = __dtoa(at, 0, 0, &dotoff, &sign, &end); + ptrdiff_t len = end - str; + __freedtoa(str); + return len < dotoff ? 0 : len - dotoff; + //return len < dotoff ? 0 : len - dotoff > 9 ? 9 : len - dotoff; +} + +size_t der_sizeof_generalizedtime_body(CFAbsoluteTime at, CFErrorRef *error) +{ + size_t subsec_digits = ccder_sizeof_nanoseconds(at); + + /* Generalized zulu time YYYYMMDDhhmmss[.ssss]Z */ + return subsec_digits ? 16 + subsec_digits : 15; +} + +size_t der_sizeof_generalizedtime(CFAbsoluteTime at, CFErrorRef *error) +{ + return ccder_sizeof(CCDER_GENERALIZED_TIME, + der_sizeof_generalizedtime_body(at, error)); +} + +size_t der_sizeof_date(CFDateRef date, CFErrorRef *error) +{ + return der_sizeof_generalizedtime(CFDateGetAbsoluteTime(date), error); +} + + +static uint8_t *ccder_encode_byte(uint8_t byte, + const uint8_t *der, uint8_t *der_end) { + if (der + 1 > der_end) { + return NULL; + } + *--der_end = byte; + return der_end; +} + +static uint8_t *ccder_encode_decimal_pair(int v, const uint8_t *der, + uint8_t *der_end) { + if (der_end == NULL || der + 2 > der_end) { + return NULL; + } + assert(v < 100); + *--der_end = '0' + v % 10; + *--der_end = '0' + v / 10; + return der_end; +} + +static uint8_t *ccder_encode_decimal_quad(int v, const uint8_t *der, + uint8_t *der_end) { + return ccder_encode_decimal_pair(v / 100, der, + ccder_encode_decimal_pair(v % 100, der, der_end)); +} + +static uint8_t *ccder_encode_nanoseconds(CFAbsoluteTime at, const uint8_t *der, + uint8_t *der_end) { + int dotoff; + int sign; + char *end; + char *str = __dtoa(at, 0, 0, &dotoff, &sign, &end); + char *begin = str + (dotoff < 0 ? 0 : dotoff); + // Compute 1.0000000 - fraction in ascii space + if (at < 0.0 && begin < end) { + char *p = end - 1; + // Borrow for last digit + *p = ('9' + 1) - (*p - '0'); + while (p-- > begin) { + // Every other digit is a 9 since we borrowed from the last one + *p = '9' - (*p - '0'); + } + } + + ptrdiff_t len = end - str; + if (len > dotoff) { + if (dotoff < 0) { + assert(-1.0 < at && at < 1.0); + der_end = ccder_encode_body(len, (const uint8_t *)str, der, der_end); + der_end = ccder_encode_body_nocopy(-dotoff, der, der_end); + if (der_end) + memset(der_end, at < 0.0 ? '9' : '0', -dotoff); + } else { + der_end = ccder_encode_body(len - dotoff, (const uint8_t *)(str + dotoff), der, der_end); + } + der_end = ccder_encode_byte('.', der, der_end); + } + __freedtoa(str); + + return der_end; +} + +/* Encode generalized zulu time YYYYMMDDhhmmss[.ssss]Z */ +uint8_t* der_encode_generalizedtime_body(CFAbsoluteTime at, CFErrorRef *error, + const uint8_t *der, uint8_t *der_end) +{ + int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0; + if (!SecAbsoluteTimeGetGregorianDate(at, &year, &month, &day, &hour, &minute, &second, error)) + return NULL; + + return ccder_encode_decimal_quad(year, der, + ccder_encode_decimal_pair(month, der, + ccder_encode_decimal_pair(day, der, + ccder_encode_decimal_pair(hour, der, + ccder_encode_decimal_pair(minute, der, + ccder_encode_decimal_pair(second, der, + ccder_encode_nanoseconds(at, der, + ccder_encode_byte('Z', der, der_end)))))))); +} + +uint8_t* der_encode_generalizedtime(CFAbsoluteTime at, CFErrorRef *error, + const uint8_t *der, uint8_t *der_end) +{ + return ccder_encode_constructed_tl(CCDER_GENERALIZED_TIME, der_end, der, + der_encode_generalizedtime_body(at, error, der, der_end)); +} + + +uint8_t* der_encode_date(CFDateRef date, CFErrorRef *error, + const uint8_t *der, uint8_t *der_end) +{ + return der_encode_generalizedtime(CFDateGetAbsoluteTime(date), error, + der, der_end); +} diff --git a/Security/utilities/src/der_date.h b/Security/utilities/src/der_date.h new file mode 100644 index 00000000..327ea7de --- /dev/null +++ b/Security/utilities/src/der_date.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef _UTILITIES_DER_DATE_H_ +#define _UTILITIES_DER_DATE_H_ + +#include + +const uint8_t* der_decode_generalizedtime_body(CFAbsoluteTime *at, CFErrorRef *error, + const uint8_t* der, const uint8_t *der_end); +const uint8_t* der_decode_universaltime_body(CFAbsoluteTime *at, CFErrorRef *error, + const uint8_t* der, const uint8_t *der_end); + +size_t der_sizeof_generalizedtime(CFAbsoluteTime at, CFErrorRef *error); +uint8_t* der_encode_generalizedtime(CFAbsoluteTime at, CFErrorRef *error, + const uint8_t *der, uint8_t *der_end); + +size_t der_sizeof_generalizedtime_body(CFAbsoluteTime at, CFErrorRef *error); +uint8_t* der_encode_generalizedtime_body(CFAbsoluteTime at, CFErrorRef *error, + const uint8_t *der, uint8_t *der_end); + +#endif /* _UTILITIES_DER_DATE_H_ */ diff --git a/utilities/src/der_dictionary.c b/Security/utilities/src/der_dictionary.c similarity index 85% rename from utilities/src/der_dictionary.c rename to Security/utilities/src/der_dictionary.c index eb70aef9..bb002953 100644 --- a/utilities/src/der_dictionary.c +++ b/Security/utilities/src/der_dictionary.c @@ -1,10 +1,26 @@ -// -// der_dictionary.c -// utilities -// -// Created by Mitch Adler on 6/18/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include @@ -64,7 +80,7 @@ const uint8_t* der_decode_dictionary(CFAllocatorRef allocator, CFOptionFlags mut CFMutableDictionaryRef dict = CFDictionaryCreateMutable(allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (NULL == dict) { - SecCFDERCreateError(kSecDERErrorUnderlyingError, CFSTR("Failed to create data"), NULL, error); + SecCFDERCreateError(kSecDERErrorAllocationFailure, CFSTR("Failed to create dictionary"), NULL, error); payload = NULL; goto exit; } @@ -77,9 +93,10 @@ const uint8_t* der_decode_dictionary(CFAllocatorRef allocator, CFOptionFlags mut if (payload) { CFDictionaryAddValue(dict, key, value); - CFReleaseNull(key); - CFReleaseNull(value); } + + CFReleaseNull(key); + CFReleaseNull(value); } diff --git a/Security/utilities/src/der_null.c b/Security/utilities/src/der_null.c new file mode 100644 index 00000000..b462a031 --- /dev/null +++ b/Security/utilities/src/der_null.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + +#include "utilities/SecCFRelease.h" +#include "utilities/der_plist.h" +#include "utilities/der_plist_internal.h" + +#include +#include + + +const uint8_t* der_decode_null(CFAllocatorRef allocator, CFOptionFlags mutability, + CFNullRef* nul, CFErrorRef *error, + const uint8_t* der, const uint8_t *der_end) +{ + if (NULL == der) + return NULL; + + size_t payload_size = 0; + const uint8_t *payload = ccder_decode_tl(CCDER_NULL, &payload_size, der, der_end); + + if (NULL == payload || payload_size != 0) { + SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown null encoding"), NULL, error); + return NULL; + } + + *nul = kCFNull; + + return payload + payload_size; +} + + +size_t der_sizeof_null(CFNullRef data __unused, CFErrorRef *error) +{ + return ccder_sizeof(CCDER_NULL, 0); +} + + +uint8_t* der_encode_null(CFNullRef boolean __unused, CFErrorRef *error, + const uint8_t *der, uint8_t *der_end) +{ + return ccder_encode_tl(CCDER_NULL, 0, der, der_end); +} diff --git a/utilities/src/der_number.c b/Security/utilities/src/der_number.c similarity index 77% rename from utilities/src/der_number.c rename to Security/utilities/src/der_number.c index 979b97bd..67bbf3e2 100644 --- a/utilities/src/der_number.c +++ b/Security/utilities/src/der_number.c @@ -1,10 +1,26 @@ -// -// der_number.c -// utilities -// -// Created by Mitch Adler on 6/19/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include diff --git a/utilities/src/der_plist.c b/Security/utilities/src/der_plist.c similarity index 82% rename from utilities/src/der_plist.c rename to Security/utilities/src/der_plist.c index 6899aa11..b651a41b 100644 --- a/utilities/src/der_plist.c +++ b/Security/utilities/src/der_plist.c @@ -1,10 +1,26 @@ -// -// der_plist.c -// utilities -// -// Created by Mitch Adler on 7/2/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #include diff --git a/Security/utilities/src/der_plist.h b/Security/utilities/src/der_plist.h new file mode 100644 index 00000000..a1219bd7 --- /dev/null +++ b/Security/utilities/src/der_plist.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef _DER_PLIST_H_ +#define _DER_PLIST_H_ + +#include + +// +// Error Codes for PropertyList <-> DER +// + +static const CFIndex kSecDERErrorUnknownEncoding = -1; +static const CFIndex kSecDERErrorUnsupportedDERType = -2; +static const CFIndex kSecDERErrorAllocationFailure = -3; +static const CFIndex kSecDERErrorUnsupportedNumberType = -4; +static const CFIndex kSecDERErrorUnsupportedCFObject = -5; + +extern CFStringRef sSecDERErrorDomain; + +// PropertyList <-> DER Functions + +size_t der_sizeof_plist(CFPropertyListRef pl, CFErrorRef *error); + +uint8_t* der_encode_plist(CFPropertyListRef pl, CFErrorRef *error, + const uint8_t *der, uint8_t *der_end); + +const uint8_t* der_decode_plist(CFAllocatorRef pl, CFOptionFlags mutability, + CFPropertyListRef* cf, CFErrorRef *error, + const uint8_t* der, const uint8_t *der_end); + +#endif diff --git a/Security/utilities/src/der_plist_internal.c b/Security/utilities/src/der_plist_internal.c new file mode 100644 index 00000000..1fded953 --- /dev/null +++ b/Security/utilities/src/der_plist_internal.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include "utilities/der_plist_internal.h" +#include "utilities/SecCFError.h" +#include "utilities/SecCFRelease.h" +#include + +CFStringRef sSecDERErrorDomain = CFSTR("com.apple.security.cfder.error"); + +bool SecCFDERCreateError(CFIndex errorCode, CFStringRef descriptionString, CFErrorRef previousError, CFErrorRef *newError) { + return SecCFCreateError(errorCode, sSecDERErrorDomain, descriptionString, previousError, newError); +} diff --git a/utilities/src/der_plist_internal.h b/Security/utilities/src/der_plist_internal.h similarity index 79% rename from utilities/src/der_plist_internal.h rename to Security/utilities/src/der_plist_internal.h index 5ab3038e..9dabcfc1 100644 --- a/utilities/src/der_plist_internal.h +++ b/Security/utilities/src/der_plist_internal.h @@ -1,17 +1,34 @@ -// -// der_plist_internal.h -// utilities -// -// Created by Mitch Adler on 7/2/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + #ifndef _DER_PLIST_INTERNAL_H_ #define _DER_PLIST_INTERNAL_H_ #include -void SecCFDERCreateError(CFIndex errorCode, CFStringRef descriptionString, CFErrorRef previousError, CFErrorRef *newError); +// Always returns false, to satisfy static analysis +bool SecCFDERCreateError(CFIndex errorCode, CFStringRef descriptionString, CFErrorRef previousError, CFErrorRef *newError); // CFArray <-> DER diff --git a/Security/utilities/src/der_string.c b/Security/utilities/src/der_string.c new file mode 100644 index 00000000..2cb6854a --- /dev/null +++ b/Security/utilities/src/der_string.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + +#include "utilities/SecCFRelease.h" +#include "utilities/der_plist.h" +#include "utilities/der_plist_internal.h" + +#include +#include + + +const uint8_t* der_decode_string(CFAllocatorRef allocator, CFOptionFlags mutability, + CFStringRef* string, CFErrorRef *error, + const uint8_t* der, const uint8_t *der_end) +{ + if (NULL == der) + return NULL; + + size_t payload_size = 0; + const uint8_t *payload = ccder_decode_tl(CCDER_UTF8_STRING, &payload_size, der, der_end); + + if (NULL == payload || (der_end - payload) < payload_size){ + SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown string encoding"), NULL, error); + return NULL; + } + + *string = CFStringCreateWithBytes(allocator, payload, payload_size, kCFStringEncodingUTF8, false); + + if (NULL == *string) { + SecCFDERCreateError(kSecDERErrorAllocationFailure, CFSTR("String allocation failed"), NULL, error); + return NULL; + } + + return payload + payload_size; +} + + +size_t der_sizeof_string(CFStringRef str, CFErrorRef *error) +{ + const CFIndex str_length = CFStringGetLength(str); + const CFIndex maximum = CFStringGetMaximumSizeForEncoding(str_length, kCFStringEncodingUTF8); + + CFIndex encodedLen = 0; + CFIndex converted = CFStringGetBytes(str, CFRangeMake(0, str_length), kCFStringEncodingUTF8, 0, false, NULL, maximum, &encodedLen); + + return ccder_sizeof(CCDER_UTF8_STRING, (converted == str_length) ? encodedLen : 0); +} + + +uint8_t* der_encode_string(CFStringRef string, CFErrorRef *error, + const uint8_t *der, uint8_t *der_end) +{ + // Obey the NULL allowed rules. + if (!der_end) + return NULL; + + const CFIndex str_length = CFStringGetLength(string); + + ptrdiff_t der_space = der_end - der; + CFIndex bytes_used = 0; + uint8_t *buffer = der_end - der_space; + CFIndex converted = CFStringGetBytes(string, CFRangeMake(0, str_length), kCFStringEncodingUTF8, 0, false, buffer, der_space, &bytes_used); + if (converted != str_length){ + SecCFDERCreateError(kSecDERErrorUnsupportedCFObject, CFSTR("String extraction failed"), NULL, error); + return NULL; + } + + return ccder_encode_tl(CCDER_UTF8_STRING, bytes_used, der, + ccder_encode_body(bytes_used, buffer, der, der_end)); + +} diff --git a/Security/utilities/src/fileIo.c b/Security/utilities/src/fileIo.c new file mode 100644 index 00000000..bb8523ab --- /dev/null +++ b/Security/utilities/src/fileIo.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2005-2007,2010,2012-2013 Apple Inc. All Rights Reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "fileIo.h" + +int writeFile( + const char *fileName, + const unsigned char *bytes, + size_t numBytes) +{ + int rtn; + int fd; + ssize_t wrc; + + if (!fileName) { + fwrite(bytes, 1, numBytes, stdout); + fflush(stdout); + return ferror(stdout); + } + + fd = open(fileName, O_RDWR | O_CREAT | O_TRUNC, 0600); + if(fd <= 0) { + return errno; + } + wrc = write(fd, bytes, (size_t)numBytes); + if(wrc != numBytes) { + if(wrc >= 0) { + fprintf(stderr, "writeFile: short write\n"); + } + rtn = EIO; + } + else { + rtn = 0; + } + close(fd); + return rtn; +} + +/* + * Read entire file. + */ +int readFile( + const char *fileName, + unsigned char **bytes, // mallocd and returned + size_t *numBytes) // returned +{ + int rtn; + int fd; + char *buf; + struct stat sb; + size_t size; + ssize_t rrc; + + *numBytes = 0; + *bytes = NULL; + fd = open(fileName, O_RDONLY); + if(fd <= 0) { + return errno; + } + rtn = fstat(fd, &sb); + if(rtn) { + goto errOut; + } + if (sb.st_size > SIZE_MAX) { + rtn = EFBIG; + goto errOut; + } + size = (size_t)sb.st_size; + buf = (char *)malloc(size); + if(buf == NULL) { + rtn = ENOMEM; + goto errOut; + } + rrc = read(fd, buf, size); + if(rrc != size) { + if(rtn >= 0) { + free(buf); + fprintf(stderr, "readFile: short read\n"); + } + rtn = EIO; + } + else { + rtn = 0; + *bytes = (unsigned char *)buf; + *numBytes = size; + } + +errOut: + close(fd); + return rtn; +} diff --git a/Security/utilities/src/fileIo.h b/Security/utilities/src/fileIo.h new file mode 100644 index 00000000..d12413fe --- /dev/null +++ b/Security/utilities/src/fileIo.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2005-2007,2010,2012 Apple Inc. All Rights Reserved. + */ + +#include + +/* + * Read entire file. + */ +#ifdef __cplusplus +extern "C" { +#endif + +int readFile( + const char *fileName, + unsigned char **bytes, // mallocd and returned + size_t *numBytes); // returned + +int writeFile( + const char *fileName, + const unsigned char *bytes, + size_t numBytes); + +#ifdef __cplusplus +} +#endif diff --git a/Security/utilities/src/iCloudKeychainTrace.c b/Security/utilities/src/iCloudKeychainTrace.c new file mode 100644 index 00000000..8061d78e --- /dev/null +++ b/Security/utilities/src/iCloudKeychainTrace.c @@ -0,0 +1,459 @@ +/* + * 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 "iCloudKeychainTrace.h" +#include +#include +#include "SecCFWrappers.h" +#include +#include + +const CFStringRef kNumberOfiCloudKeychainPeers = CFSTR("numberOfPeers"); +const CFStringRef kNumberOfiCloudKeychainItemsBeingSynced = CFSTR("numberOfItemsBeingSynced"); +const CFStringRef kCloudKeychainNumberOfSyncingConflicts = CFSTR("conflictsCount"); +const CFStringRef kCloudKeychainNumberOfTimesSyncFailed = CFSTR("syncFailureCount"); +const CFStringRef kCloudKeychainNumberOfConflictsResolved = CFSTR("conflictsResolved"); +const CFStringRef kCloudKeychainNumberOfTimesSyncedWithPeers = CFSTR("syncedWithPeers"); + +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) +static const char* gTopLevelKeyForiCloudKeychainTracing = "com.apple.cloudkeychain"; +#endif + +#if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR) +static const char* gTopLevelKeyForiCloudKeychainTracing = "com.apple.cloudkeychain"; +#endif + +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)) +#include + +static const char* gMessageTracerSetPrefix = "com.apple.message."; + +static const char* gMessageTracerDomainField = "com.apple.message.domain"; + +/* -------------------------------------------------------------------------- + Function: OSX_BeginCloudKeychainLoggingTransaction + + Description: For OSX the message tracer back end wants its logging + done in "bunches". This function allows for beginning + a 'transaction' of logging which will allow for putting + all of the transactions items into a single log making + the message tracer folks happy. + + The work of this function is to create the aslmsg context + and set the domain field and then return the aslmsg + context as a void* + -------------------------------------------------------------------------- */ +static void* OSX_BeginCloudKeychainLoggingTransaction() +{ + void* result = NULL; + aslmsg mAsl = NULL; + mAsl = asl_new(ASL_TYPE_MSG); + if (NULL == mAsl) + { + return result; + } + + asl_set(mAsl, gMessageTracerDomainField, gTopLevelKeyForiCloudKeychainTracing); + + result = (void *)mAsl; + return result; +} + +/* -------------------------------------------------------------------------- + Function: OSX_AddKeyValuePairToKeychainLoggingTransaction + + Description: Once a call to OSX_BeginCloudKeychainLoggingTransaction + is done, this call all allow for adding items to the + "bunch" of items being logged. + + NOTE: The key should be a simple key such as + "numberOfPeers". This is because this function will + apptend the required prefix of "com.apple.message." + -------------------------------------------------------------------------- */ +static bool OSX_AddKeyValuePairToKeychainLoggingTransaction(void* token, CFStringRef key, int64_t value) +{ + if (NULL == token || NULL == key) + { + return false; + } + + aslmsg mAsl = (aslmsg)token; + + // Fix up the key + CFStringRef real_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%@"), gMessageTracerSetPrefix, key); + if (NULL == real_key) + { + return false; + } + + CFIndex key_length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(real_key), kCFStringEncodingUTF8); + key_length += 1; // For null + char key_buffer[key_length]; + memset(key_buffer, 0,key_length); + if (!CFStringGetCString(real_key, key_buffer, key_length, kCFStringEncodingUTF8)) + { + CFRelease(real_key); + return false; + } + CFRelease(real_key); + + CFStringRef value_str = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%lld"), value); + if (NULL == value_str) + { + return false; + } + + CFIndex value_str_numBytes = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value_str), kCFStringEncodingUTF8); + value_str_numBytes += 1; // For null + char value_buffer[value_str_numBytes]; + memset(value_buffer, 0, value_str_numBytes); + if (!CFStringGetCString(value_str, value_buffer, value_str_numBytes, kCFStringEncodingUTF8)) + { + CFRelease(value_str); + return false; + } + CFRelease(value_str); + + asl_set(mAsl, key_buffer, value_buffer); + return true; +} + +/* -------------------------------------------------------------------------- + Function: OSX_CloseCloudKeychainLoggingTransaction + + Description: Once a call to OSX_BeginCloudKeychainLoggingTransaction + is done, and all of the items that are to be in the + "bunch" of items being logged, this function will do the + real logging and free the aslmsg context. + -------------------------------------------------------------------------- */ +static void OSX_CloseCloudKeychainLoggingTransaction(void* token) +{ + if (NULL != token) + { + aslmsg mAsl = (aslmsg)token; + asl_log(NULL, mAsl, ASL_LEVEL_NOTICE, ""); + asl_free(mAsl); + } +} + +/* -------------------------------------------------------------------------- + Function: OSX_SetCloudKeychainTraceValueForKey + + Description: If "bunching" of items either cannot be done or is not + desired, then this 'single shot' function shold be used. + It will create the aslmsg context, register the domain + fix up the key and log the key value pair and then + do the real logging and free the aslmsg context. + -------------------------------------------------------------------------- */ +static bool OSX_SetCloudKeychainTraceValueForKey(CFStringRef key, int64_t value) +{ + bool result = false; + + if (NULL == key) + { + return result; + } + + aslmsg mAsl = NULL; + mAsl = asl_new(ASL_TYPE_MSG); + if (NULL == mAsl) + { + return result; + } + + // Fix up the key + CFStringRef real_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%@"), gMessageTracerSetPrefix, key); + if (NULL == real_key) + { + return false; + } + + CFIndex key_length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(real_key), kCFStringEncodingUTF8); + key_length += 1; // For null + char key_buffer[key_length]; + memset(key_buffer, 0,key_length); + if (!CFStringGetCString(real_key, key_buffer, key_length, kCFStringEncodingUTF8)) + { + CFRelease(real_key); + return false; + } + CFRelease(real_key); + + + CFStringRef value_str = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%lld"), value); + if (NULL == value_str) + { + asl_free(mAsl); + return result; + } + + CFIndex value_str_numBytes = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value_str), kCFStringEncodingUTF8); + value_str_numBytes += 1; // For null + char value_buffer[value_str_numBytes]; + memset(value_buffer, 0, value_str_numBytes); + if (!CFStringGetCString(value_str, value_buffer, value_str_numBytes, kCFStringEncodingUTF8)) + { + asl_free(mAsl); + CFRelease(value_str); + return result; + } + CFRelease(value_str); + + asl_set(mAsl, gMessageTracerDomainField, gTopLevelKeyForiCloudKeychainTracing); + + asl_set(mAsl, key_buffer, value_buffer); + asl_log(NULL, mAsl, ASL_LEVEL_NOTICE, "%s is %lld", key_buffer, value); + asl_free(mAsl); + return true; + +} +#endif + +#if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR) + +typedef void (*type_ADClientClearScalarKey)(CFStringRef key); +typedef void (*type_ADClientAddValueForScalarKey)(CFStringRef key, int64_t value); + +static type_ADClientClearScalarKey gADClientClearScalarKey = NULL; +static type_ADClientAddValueForScalarKey gADClientAddValueForScalarKey = NULL; + +static dispatch_once_t gADFunctionPointersSet = 0; +static CFBundleRef gAggdBundleRef = NULL; +static bool gFunctionPointersAreLoaded = false; + +/* -------------------------------------------------------------------------- + Function: InitializeADFunctionPointers + + Description: Linking to the Aggregate library causes a build cycle so + This function will dynamically load the needed function + pointers. + -------------------------------------------------------------------------- */ +static bool InitializeADFunctionPointers() +{ + if (gFunctionPointersAreLoaded) + { + return gFunctionPointersAreLoaded; + } + + dispatch_once(&gADFunctionPointersSet, + ^{ + CFStringRef path_to_aggd_framework = CFSTR("/System/Library/PrivateFrameworks/AggregateDictionary.framework"); + + CFURLRef aggd_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path_to_aggd_framework, kCFURLPOSIXPathStyle, true); + + if (NULL != aggd_url) + { + gAggdBundleRef = CFBundleCreate(kCFAllocatorDefault, aggd_url); + if (NULL != gAggdBundleRef) + { + gADClientClearScalarKey = (type_ADClientClearScalarKey) + CFBundleGetFunctionPointerForName(gAggdBundleRef, CFSTR("ADClientClearScalarKey")); + + gADClientAddValueForScalarKey = (type_ADClientAddValueForScalarKey) + CFBundleGetFunctionPointerForName(gAggdBundleRef, CFSTR("ADClientAddValueForScalarKey")); + } + CFRelease(aggd_url); + } + }); + + gFunctionPointersAreLoaded = ((NULL != gADClientClearScalarKey) && (NULL != gADClientAddValueForScalarKey)); + return gFunctionPointersAreLoaded; +} + +/* -------------------------------------------------------------------------- + Function: Internal_ADClientClearScalarKey + + Description: This fucntion is a wrapper around calling the + ADClientClearScalarKey function. + + NOTE: The key should be a simple key such as + "numberOfPeers". This is because this function will + apptend the required prefix of "com.apple.cloudkeychain" + -------------------------------------------------------------------------- */ +static void Internal_ADClientClearScalarKey(CFStringRef key) +{ + if (InitializeADFunctionPointers()) + { + CFStringRef real_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s.%@"), gTopLevelKeyForiCloudKeychainTracing, key); + if (NULL == real_key) + { + return; + } + + gADClientClearScalarKey(real_key); + CFRelease(real_key); + } +} + +/* -------------------------------------------------------------------------- + Function: Internal_ADClientAddValueForScalarKey + + Description: This fucntion is a wrapper around calling the + ADClientAddValueForScalarKey function. + + NOTE: The key should be a simple key such as + "numberOfPeers". This is because this function will + apptend the required prefix of "com.apple.cloudkeychain" + -------------------------------------------------------------------------- */ +static void Internal_ADClientAddValueForScalarKey(CFStringRef key, int64_t value) +{ + if (InitializeADFunctionPointers()) + { + CFStringRef real_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s.%@"), gTopLevelKeyForiCloudKeychainTracing, key); + if (NULL == real_key) + { + return; + } + + gADClientAddValueForScalarKey(real_key, value); + CFRelease(real_key); + } +} + + +/* -------------------------------------------------------------------------- + Function: iOS_SetCloudKeychainTraceValueForKey + + Description: This fucntion is a wrapper around calling either + ADClientAddValueForScalarKey or ADClientClearScalarKey + depending on if the value is 0. + + NOTE: The key should be a simple key such as + "numberOfPeers". This is because this function will + apptend the required prefix of "com.apple.cloudkeychain" + -------------------------------------------------------------------------- */ +static bool iOS_SetCloudKeychainTraceValueForKey(CFStringRef key, int64_t value) +{ + if (NULL == key) + { + return false; + } + + if (0LL == value) + { + Internal_ADClientClearScalarKey(key); + } + else + { + Internal_ADClientAddValueForScalarKey(key, value); + } + return true; +} + +/* -------------------------------------------------------------------------- + Function: iOS_AddKeyValuePairToKeychainLoggingTransaction + + Description: For iOS the is no "bunching" This function will simply + call iOS_SetCloudKeychainTraceValueForKey to log the + key value pair + -------------------------------------------------------------------------- */ +static bool iOS_AddKeyValuePairToKeychainLoggingTransaction(void* token, CFStringRef key, int64_t value) +{ +#pragma unused(token) + return iOS_SetCloudKeychainTraceValueForKey(key, value); +} +#endif + +/* -------------------------------------------------------------------------- + Function: SetCloudKeychainTraceValueForKey + + Description: SPI to log a single key value pair with the logging system + -------------------------------------------------------------------------- */ +bool SetCloudKeychainTraceValueForKey(CFStringRef key, int64_t value) +{ +#if (TARGET_IPHONE_SIMULATOR) + return false; +#endif + +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) + return OSX_SetCloudKeychainTraceValueForKey(key, value); +#endif + +#if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR) + return iOS_SetCloudKeychainTraceValueForKey(key, value); +#endif +} + +/* -------------------------------------------------------------------------- + Function: BeginCloudKeychainLoggingTransaction + + Description: SPI to begin a logging transaction + -------------------------------------------------------------------------- */ +void* BeginCloudKeychainLoggingTransaction() +{ +#if (TARGET_IPHONE_SIMULATOR) + return (void *)-1; +#endif + +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) + return OSX_BeginCloudKeychainLoggingTransaction(); +#endif + +#if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR) + return NULL; +#endif +} + +/* -------------------------------------------------------------------------- + Function: AddKeyValuePairToKeychainLoggingTransaction + + Description: SPI to add a key value pair to an outstanding logging + tansaction + -------------------------------------------------------------------------- */ +bool AddKeyValuePairToKeychainLoggingTransaction(void* token, CFStringRef key, int64_t value) +{ +#if (TARGET_IPHONE_SIMULATOR) + return false; +#endif + +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) + return OSX_AddKeyValuePairToKeychainLoggingTransaction(token, key, value); +#endif + +#if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR) + return iOS_AddKeyValuePairToKeychainLoggingTransaction(token, key, value); +#endif +} + +/* -------------------------------------------------------------------------- + Function: CloseCloudKeychainLoggingTransaction + + Description: SPI to complete a logging transaction and clean up the + context + -------------------------------------------------------------------------- */ +void CloseCloudKeychainLoggingTransaction(void* token) +{ +#if (TARGET_IPHONE_SIMULATOR) + ; // nothing +#endif + +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) + OSX_CloseCloudKeychainLoggingTransaction(token); +#endif + +#if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR) + ; // nothing +#endif +} + diff --git a/Security/utilities/src/iCloudKeychainTrace.h b/Security/utilities/src/iCloudKeychainTrace.h new file mode 100644 index 00000000..cd75ef67 --- /dev/null +++ b/Security/utilities/src/iCloudKeychainTrace.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2006-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@ + */ + +/* + * iCloudKeychainTrace.h - log statistics for iCloud Keychain usage + */ + +#include + +const CFStringRef kCloudKeychainNumberOfSyncingConflicts + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +const CFStringRef kCloudKeychainNumberOfTimesSyncFailed + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +const CFStringRef kCloudKeychainNumberOfConflictsResolved + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +const CFStringRef kCloudKeychainNumberOfTimesSyncedWithPeers + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + +bool SetCloudKeychainTraceValueForKey(CFStringRef key, int64_t value) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + +void* BeginCloudKeychainLoggingTransaction(void) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + +bool AddKeyValuePairToKeychainLoggingTransaction(void* token, CFStringRef key, int64_t value) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + +void CloseCloudKeychainLoggingTransaction(void* token) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + + + + + diff --git a/Security/utilities/src/iOSforOSX-SecAttr.c b/Security/utilities/src/iOSforOSX-SecAttr.c new file mode 100644 index 00000000..00ad58c0 --- /dev/null +++ b/Security/utilities/src/iOSforOSX-SecAttr.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) +#include + +#include +#include +#include +#include "iOSforOSX.h" +#include +#include + +// Was in SOSAccount.c +#define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); +// We may not have all of these we need +SEC_CONST_DECL (kSecAttrAccessible, "pdmn"); +SEC_CONST_DECL (kSecAttrAccessibleAlwaysThisDeviceOnly, "dku"); +SEC_CONST_DECL (kSecAttrAccessControl, "accc"); +SEC_CONST_DECL (kSecUseCredentialReference, "u_CredRef"); +SEC_CONST_DECL (kSecUseOperationPrompt, "u_OpPrompt"); +SEC_CONST_DECL (kSecUseNoAuthenticationUI, "u_NoAuthUI"); + +#endif diff --git a/Security/utilities/src/iOSforOSX-SecRandom.c b/Security/utilities/src/iOSforOSX-SecRandom.c new file mode 100644 index 00000000..f576e83a --- /dev/null +++ b/Security/utilities/src/iOSforOSX-SecRandom.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) +const void *kSecRandomDefault = (void*)0; +#endif diff --git a/Security/utilities/src/iOSforOSX.c b/Security/utilities/src/iOSforOSX.c new file mode 100644 index 00000000..5dd2b181 --- /dev/null +++ b/Security/utilities/src/iOSforOSX.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) + +#include +#include +#include + +#include +#include +#include +#include "iOSforOSX.h" +#include +#include + +#include ".././libsecurity_keychain/lib/SecBase64P.c" + +CFURLRef SecCopyKeychainDirectoryFile(CFStringRef file) +{ + struct passwd *passwd = getpwuid(getuid()); + if (!passwd) + return NULL; + + CFURLRef pathURL = NULL; + CFURLRef fileURL = NULL; + CFStringRef home = NULL; + CFStringRef filePath = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s/%@"), "Library/Keychains", file); + require(filePath, xit); + + if (passwd->pw_dir) + home = CFStringCreateWithCString(NULL, passwd->pw_dir, kCFStringEncodingUTF8); + + pathURL = CFURLCreateWithFileSystemPath(NULL, home?home:CFSTR("/"), kCFURLPOSIXPathStyle, true); + if (pathURL) + fileURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault, pathURL, filePath, false); + +xit: + CFReleaseSafe(filePath); + CFReleaseSafe(pathURL); + CFReleaseSafe(home); + return fileURL; +} + +// XXX: do we still need this? see securityd_files? +CFURLRef PortableCFCopyHomeDirectoryURL(void) +{ + char *path = getenv("HOME"); + if (!path) { + struct passwd *pw = getpwuid(getuid()); + path = pw->pw_dir; + } + CFStringRef path_cf = CFStringCreateWithCStringNoCopy(NULL, path, kCFStringEncodingUTF8, kCFAllocatorNull); + CFURLRef path_url = CFURLCreateWithFileSystemPath(NULL, path_cf, kCFURLPOSIXPathStyle, true); + + CFRelease(path_cf); + return path_url; +} + +#endif diff --git a/Security/utilities/src/iOSforOSX.h b/Security/utilities/src/iOSforOSX.h new file mode 100644 index 00000000..c9fb607d --- /dev/null +++ b/Security/utilities/src/iOSforOSX.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#ifndef utilities_iOSforOSX_h +#define utilities_iOSforOSX_h + +#include +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) + +extern CFURLRef SecCopyKeychainDirectoryFile(CFStringRef file); + +CFURLRef PortableCFCopyHomeDirectoryURL(void); + +#ifndef _SECURITY_SECRANDOM_H_ +extern const void *kSecRandomDefault; +#endif + +#ifndef _SECURITY_SECBASE_H_ +typedef struct OpaqueSecKeyRef *SecKeyRef; +#endif +OSStatus SecKeyCopyPersistentRef(SecKeyRef item, CFDataRef *newPersistantRef); +OSStatus SecKeyFindWithPersistentRef(CFDataRef persistantRef, SecKeyRef *key); + + +#endif + +CFURLRef PortableCFCopyHomeDirectoryURL(void) asm("_CFCopyHomeDirectoryURL"); + +#endif diff --git a/Security/utilities/src/simulate_crash.c b/Security/utilities/src/simulate_crash.c new file mode 100644 index 00000000..ba56aa71 --- /dev/null +++ b/Security/utilities/src/simulate_crash.c @@ -0,0 +1,53 @@ +// +// simulate_crash +// utilities +// +// Copyright (c) 2014 Apple Inc. All Rights Reserved. +// + +#include "debugging.h" + +#include +#include +#include + +/// Type to represent a boolean value. +#if TARGET_OS_IPHONE && __LP64__ +typedef bool BOOL; +#else +typedef signed char BOOL; +// BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C" +// even if -funsigned-char is used. +#endif + +static void __security_simulatecrash_link(CFStringRef reason, uint32_t code) +{ +#if !TARGET_IPHONE_SIMULATOR + // Prototype defined in , but objC only. + // Soft linking here so we don't link unless we hit this. + static BOOL (*__SimulateCrash)(pid_t pid, mach_exception_data_type_t exceptionCode, CFStringRef description); + + static dispatch_once_t once = 0; + dispatch_once(&once, ^{ + void *image = dlopen("/System/Library/PrivateFrameworks/CrashReporterSupport.framework/CrashReporterSupport", RTLD_NOW); + if (image) + __SimulateCrash = dlsym(image, "SimulateCrash"); + else + __SimulateCrash = NULL; + }); + + if (__SimulateCrash) + __SimulateCrash(getpid(), code, reason); + else + secerror("SimulateCrash not available"); +#else + secerror("SimulateCrash not available in iOS simulator"); +#endif +} + + +void __security_simulatecrash(CFStringRef reason, uint32_t code) +{ + secerror("Simulating crash, reason: %@, code=%08x", reason, code); + __security_simulatecrash_link(reason, code); +} diff --git a/Security/utilities/src/sqlutils.h b/Security/utilities/src/sqlutils.h new file mode 100644 index 00000000..db551dec --- /dev/null +++ b/Security/utilities/src/sqlutils.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 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@ + */ + + +/* + * sqlutils.h - some wrapper for sql3lite + */ +#ifndef _SECURITY_UTILITIES_SQLUTILS_H_ +#define _SECURITY_UTILITIES_SQLUTILS_H_ + +#include + +/* Those are just wrapper around the sqlite3 functions, but they have size_t for some len parameters, + and checks for overflow before casting to int */ +static inline int sqlite3_bind_blob_wrapper(sqlite3_stmt* pStmt, int i, const void* zData, size_t n, void(*xDel)(void*)) +{ + if(n>INT_MAX) return SQLITE_TOOBIG; + return sqlite3_bind_blob(pStmt, i, zData, (int)n, xDel); +} + +static inline int sqlite3_bind_text_wrapper(sqlite3_stmt* pStmt, int i, const void* zData, size_t n, void(*xDel)(void*)) +{ + if(n>INT_MAX) return SQLITE_TOOBIG; + return sqlite3_bind_text(pStmt, i, zData, (int)n, xDel); +} + +static inline int sqlite3_prepare_wrapper(sqlite3 *db, const char *zSql, size_t nByte, sqlite3_stmt **ppStmt, const char **pzTail) +{ + if(nByte>INT_MAX) return SQLITE_TOOBIG; + return sqlite3_prepare(db, zSql, (int)nByte, ppStmt, pzTail); +} + +#endif diff --git a/utilities/utilities b/Security/utilities/utilities similarity index 100% rename from utilities/utilities rename to Security/utilities/utilities diff --git a/Security/utilities/utilities.xcodeproj/project.pbxproj b/Security/utilities/utilities.xcodeproj/project.pbxproj new file mode 100644 index 00000000..112b1e84 --- /dev/null +++ b/Security/utilities/utilities.xcodeproj/project.pbxproj @@ -0,0 +1,572 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 4C068F811653146500E8A1BB /* iOSforOSX.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C068F801653146500E8A1BB /* iOSforOSX.h */; }; + 4C143CF8165172AD003035A3 /* SecDb.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C143CF7165172AD003035A3 /* SecDb.c */; }; + 4C3600451680DEB90049891B /* iOSforOSX-SecAttr.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C3600431680DEB90049891B /* iOSforOSX-SecAttr.c */; }; + 4C3600461680DEB90049891B /* iOSforOSX-SecRandom.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C3600441680DEB90049891B /* iOSforOSX-SecRandom.c */; }; + 4C3963D915ACF2E700762091 /* su-16-cfdate-der.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C3963D815ACF2E700762091 /* su-16-cfdate-der.c */; }; + 4C5BCD8A17304CE600DCEFB4 /* der_null.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C5BCD8917304B8100DCEFB4 /* der_null.c */; }; + 4C6882D615ABADBC00028C8F /* SecCFRelease.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6882BF15ABADBC00028C8F /* SecCFRelease.h */; }; + 4C6882D715ABADBC00028C8F /* SecCFWrappers.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6882C015ABADBC00028C8F /* SecCFWrappers.h */; }; + 4C6882D815ABADBC00028C8F /* array_size.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6882C115ABADBC00028C8F /* array_size.h */; }; + 4C6882D915ABADBC00028C8F /* comparison.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882C215ABADBC00028C8F /* comparison.c */; }; + 4C6882DA15ABADBC00028C8F /* comparison.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6882C315ABADBC00028C8F /* comparison.h */; }; + 4C6882DB15ABADBC00028C8F /* debugging.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882C415ABADBC00028C8F /* debugging.c */; }; + 4C6882DC15ABADBC00028C8F /* debugging.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6882C515ABADBC00028C8F /* debugging.h */; }; + 4C6882DD15ABADBC00028C8F /* der_array.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882C615ABADBC00028C8F /* der_array.c */; }; + 4C6882DE15ABADBC00028C8F /* der_boolean.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882C715ABADBC00028C8F /* der_boolean.c */; }; + 4C6882DF15ABADBC00028C8F /* der_data.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882C815ABADBC00028C8F /* der_data.c */; }; + 4C6882E015ABADBC00028C8F /* der_date.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882C915ABADBC00028C8F /* der_date.c */; }; + 4C6882E115ABADBC00028C8F /* der_dictionary.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882CA15ABADBC00028C8F /* der_dictionary.c */; }; + 4C6882E215ABADBC00028C8F /* der_number.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882CB15ABADBC00028C8F /* der_number.c */; }; + 4C6882E315ABADBC00028C8F /* der_plist.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882CC15ABADBC00028C8F /* der_plist.c */; }; + 4C6882E415ABADBC00028C8F /* der_plist.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6882CD15ABADBC00028C8F /* der_plist.h */; }; + 4C6882E515ABADBC00028C8F /* der_plist_internal.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882CE15ABADBC00028C8F /* der_plist_internal.c */; }; + 4C6882E615ABADBC00028C8F /* der_plist_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6882CF15ABADBC00028C8F /* der_plist_internal.h */; }; + 4C6882E715ABADBC00028C8F /* der_string.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882D015ABADBC00028C8F /* der_string.c */; }; + 4C6882E815ABADBC00028C8F /* fileIo.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882D115ABADBC00028C8F /* fileIo.c */; }; + 4C6882E915ABADBC00028C8F /* fileIo.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6882D215ABADBC00028C8F /* fileIo.h */; }; + 4C6882EA15ABADBC00028C8F /* sqlutils.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6882D315ABADBC00028C8F /* sqlutils.h */; }; + 4C8BDD7017B3920F00C20EA5 /* SecMeta.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C8BDD6F17B3920F00C20EA5 /* SecMeta.h */; }; + 4C8BDD7217B4ABCC00C20EA5 /* su-05-cfwrappers.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C8BDD7117B4ABCC00C20EA5 /* su-05-cfwrappers.c */; }; + 4CB23B9816A09503003A0131 /* not_on_this_platorm.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CB23B9716A09503003A0131 /* not_on_this_platorm.c */; }; + 4CC0275217A1C796004067B2 /* su-41-secdb-stress.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC0275117A1C796004067B2 /* su-41-secdb-stress.c */; }; + 4CC92B1F15A3C55200C6D578 /* utilities_regressions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92B1E15A3C55200C6D578 /* utilities_regressions.h */; }; + 4CF1FAC21654EAD100261CF4 /* SecCFWrappers.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CF1FAC11654EAD100261CF4 /* SecCFWrappers.c */; }; + 4CF1FAC416550F6900261CF4 /* su-40-secdb.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CF1FAC316550F6900261CF4 /* su-40-secdb.c */; }; + 52743BD616BB278C001A299D /* SecFileLocations.c in Sources */ = {isa = PBXBuildFile; fileRef = 52743BD516BB278C001A299D /* SecFileLocations.c */; }; + 52743BD816BB27A1001A299D /* SecFileLocations.h in Headers */ = {isa = PBXBuildFile; fileRef = 52743BD716BB27A1001A299D /* SecFileLocations.h */; }; + 52E2E4951738371400E78313 /* SecXPCError.h in Headers */ = {isa = PBXBuildFile; fileRef = 52E2E4941738371400E78313 /* SecXPCError.h */; }; + 52E2E4971738394C00E78313 /* SecXPCError.c in Sources */ = {isa = PBXBuildFile; fileRef = 52E2E4961738394C00E78313 /* SecXPCError.c */; }; + 72B918A1179723B500940533 /* iCloudKeychainTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B9189F179723AE00940533 /* iCloudKeychainTrace.c */; }; + 72B918A2179723C100940533 /* iCloudKeychainTrace.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B918A0179723AE00940533 /* iCloudKeychainTrace.h */; }; + BEA22A361811E4C800BE7682 /* SecCertificateTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = BEA22A341811E4A600BE7682 /* SecCertificateTrace.c */; }; + BEA22A371811E4CF00BE7682 /* SecCertificateTrace.h in Headers */ = {isa = PBXBuildFile; fileRef = BEA22A351811E4A600BE7682 /* SecCertificateTrace.h */; }; + E706B78A18FC822B00797907 /* simulate_crash.c in Sources */ = {isa = PBXBuildFile; fileRef = E706B78918FC822B00797907 /* simulate_crash.c */; }; + E72D461E175FB73100F70B9B /* SecAKSWrappers.h in Headers */ = {isa = PBXBuildFile; fileRef = E72D461D175FAF1E00F70B9B /* SecAKSWrappers.h */; }; + E72D462D175FC35500F70B9B /* SecAKSWrappers.c in Sources */ = {isa = PBXBuildFile; fileRef = E72D462C175FC35500F70B9B /* SecAKSWrappers.c */; }; + E765E23615A79F77006C7347 /* su-15-cfdictionary-der.c in Sources */ = {isa = PBXBuildFile; fileRef = E765E23315A79EA6006C7347 /* su-15-cfdictionary-der.c */; }; + E777C72115B74029004044A8 /* SecCFError.h in Headers */ = {isa = PBXBuildFile; fileRef = E777C71F15B74024004044A8 /* SecCFError.h */; }; + E777C72315B74038004044A8 /* SecCFError.c in Sources */ = {isa = PBXBuildFile; fileRef = E777C72215B74037004044A8 /* SecCFError.c */; }; + E790C14C169E5D9C00E0C0C9 /* readline.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C14A169E5D9C00E0C0C9 /* readline.c */; }; + E790C14D169E5D9C00E0C0C9 /* readline.h in Headers */ = {isa = PBXBuildFile; fileRef = E790C14B169E5D9C00E0C0C9 /* readline.h */; }; + E7934D7115A3A29D007666E0 /* su-14-cfarray-der.c in Sources */ = {isa = PBXBuildFile; fileRef = E7934D6E15A3A298007666E0 /* su-14-cfarray-der.c */; }; + E79D9CE3159D2DB8000834EC /* su-12-cfboolean-der.c in Sources */ = {isa = PBXBuildFile; fileRef = E79D9CE2159D2DB8000834EC /* su-12-cfboolean-der.c */; }; + E79D9CE5159D3138000834EC /* su-13-cfnumber-der.c in Sources */ = {isa = PBXBuildFile; fileRef = E79D9CE4159D3138000834EC /* su-13-cfnumber-der.c */; }; + E7AAB5FA15929D44005C8BCC /* su-11-cfdata-der.c in Sources */ = {isa = PBXBuildFile; fileRef = E7AAB5F815929D3E005C8BCC /* su-11-cfdata-der.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 */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 4C068F801653146500E8A1BB /* iOSforOSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iOSforOSX.h; sourceTree = ""; }; + 4C068F821653147D00E8A1BB /* iOSforOSX.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iOSforOSX.c; sourceTree = ""; }; + 4C143CF7165172AD003035A3 /* SecDb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecDb.c; sourceTree = ""; }; + 4C143CF9165172C0003035A3 /* SecDb.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecDb.h; sourceTree = ""; }; + 4C3600431680DEB90049891B /* iOSforOSX-SecAttr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "iOSforOSX-SecAttr.c"; sourceTree = ""; }; + 4C3600441680DEB90049891B /* iOSforOSX-SecRandom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "iOSforOSX-SecRandom.c"; sourceTree = ""; }; + 4C3963D815ACF2E700762091 /* su-16-cfdate-der.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-16-cfdate-der.c"; sourceTree = ""; }; + 4C5BCD8917304B8100DCEFB4 /* der_null.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = der_null.c; sourceTree = ""; }; + 4C6882BF15ABADBC00028C8F /* SecCFRelease.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCFRelease.h; sourceTree = ""; }; + 4C6882C015ABADBC00028C8F /* SecCFWrappers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCFWrappers.h; sourceTree = ""; }; + 4C6882C115ABADBC00028C8F /* array_size.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = array_size.h; sourceTree = ""; }; + 4C6882C215ABADBC00028C8F /* comparison.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = comparison.c; sourceTree = ""; }; + 4C6882C315ABADBC00028C8F /* comparison.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = comparison.h; sourceTree = ""; }; + 4C6882C415ABADBC00028C8F /* debugging.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = debugging.c; sourceTree = ""; }; + 4C6882C515ABADBC00028C8F /* debugging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debugging.h; sourceTree = ""; }; + 4C6882C615ABADBC00028C8F /* der_array.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = der_array.c; sourceTree = ""; }; + 4C6882C715ABADBC00028C8F /* der_boolean.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = der_boolean.c; sourceTree = ""; }; + 4C6882C815ABADBC00028C8F /* der_data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = der_data.c; sourceTree = ""; }; + 4C6882C915ABADBC00028C8F /* der_date.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = der_date.c; sourceTree = ""; }; + 4C6882CA15ABADBC00028C8F /* der_dictionary.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = der_dictionary.c; sourceTree = ""; }; + 4C6882CB15ABADBC00028C8F /* der_number.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = der_number.c; sourceTree = ""; }; + 4C6882CC15ABADBC00028C8F /* der_plist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = der_plist.c; sourceTree = ""; }; + 4C6882CD15ABADBC00028C8F /* der_plist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = der_plist.h; sourceTree = ""; }; + 4C6882CE15ABADBC00028C8F /* der_plist_internal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = der_plist_internal.c; sourceTree = ""; }; + 4C6882CF15ABADBC00028C8F /* der_plist_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = der_plist_internal.h; sourceTree = ""; }; + 4C6882D015ABADBC00028C8F /* der_string.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = der_string.c; sourceTree = ""; }; + 4C6882D115ABADBC00028C8F /* fileIo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fileIo.c; sourceTree = ""; }; + 4C6882D215ABADBC00028C8F /* fileIo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fileIo.h; sourceTree = ""; }; + 4C6882D315ABADBC00028C8F /* sqlutils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqlutils.h; sourceTree = ""; }; + 4C6882EB15ABC4B400028C8F /* der_date.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = der_date.h; sourceTree = ""; }; + 4C8BDD6F17B3920F00C20EA5 /* SecMeta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecMeta.h; sourceTree = ""; }; + 4C8BDD7117B4ABCC00C20EA5 /* su-05-cfwrappers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-05-cfwrappers.c"; sourceTree = ""; }; + 4CB23B9616A09318003A0131 /* security_tool_commands_table.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = security_tool_commands_table.h; sourceTree = ""; }; + 4CB23B9716A09503003A0131 /* not_on_this_platorm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = not_on_this_platorm.c; sourceTree = ""; }; + 4CC0275117A1C796004067B2 /* su-41-secdb-stress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-41-secdb-stress.c"; sourceTree = ""; }; + 4CC92B1E15A3C55200C6D578 /* utilities_regressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utilities_regressions.h; sourceTree = ""; }; + 4CF1FAC11654EAD100261CF4 /* SecCFWrappers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecCFWrappers.c; sourceTree = ""; }; + 4CF1FAC316550F6900261CF4 /* su-40-secdb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-40-secdb.c"; sourceTree = ""; }; + 52743BD516BB278C001A299D /* SecFileLocations.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecFileLocations.c; sourceTree = ""; }; + 52743BD716BB27A1001A299D /* SecFileLocations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecFileLocations.h; sourceTree = ""; }; + 52E2E4941738371400E78313 /* SecXPCError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecXPCError.h; sourceTree = ""; }; + 52E2E4961738394C00E78313 /* SecXPCError.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecXPCError.c; sourceTree = ""; }; + 72B9189F179723AE00940533 /* iCloudKeychainTrace.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = iCloudKeychainTrace.c; sourceTree = ""; }; + 72B918A0179723AE00940533 /* iCloudKeychainTrace.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = iCloudKeychainTrace.h; sourceTree = ""; }; + BEA22A341811E4A600BE7682 /* SecCertificateTrace.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecCertificateTrace.c; sourceTree = ""; }; + BEA22A351811E4A600BE7682 /* SecCertificateTrace.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecCertificateTrace.h; sourceTree = ""; }; + E706B78918FC822B00797907 /* simulate_crash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = simulate_crash.c; sourceTree = ""; }; + E72D461D175FAF1E00F70B9B /* SecAKSWrappers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecAKSWrappers.h; sourceTree = ""; }; + E72D462C175FC35500F70B9B /* SecAKSWrappers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecAKSWrappers.c; sourceTree = ""; }; + E742A09C14E343E70052A486 /* libutilities.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libutilities.a; sourceTree = BUILT_PRODUCTS_DIR; }; + E742A0C014E344940052A486 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + E765E23315A79EA6006C7347 /* su-15-cfdictionary-der.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-15-cfdictionary-der.c"; sourceTree = ""; }; + E777C71F15B74024004044A8 /* SecCFError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecCFError.h; sourceTree = ""; }; + E777C72215B74037004044A8 /* SecCFError.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecCFError.c; sourceTree = ""; }; + E790C0F6169E4B8500E0C0C9 /* security_tool_commands.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = security_tool_commands.h; sourceTree = ""; }; + E790C14A169E5D9C00E0C0C9 /* readline.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readline.c; sourceTree = ""; }; + E790C14B169E5D9C00E0C0C9 /* readline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = readline.h; sourceTree = ""; }; + E7934D6E15A3A298007666E0 /* su-14-cfarray-der.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-14-cfarray-der.c"; sourceTree = ""; }; + E79D9CE2159D2DB8000834EC /* su-12-cfboolean-der.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-12-cfboolean-der.c"; sourceTree = ""; }; + E79D9CE4159D3138000834EC /* su-13-cfnumber-der.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-13-cfnumber-der.c"; sourceTree = ""; }; + E7AAB5F815929D3E005C8BCC /* su-11-cfdata-der.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-11-cfdata-der.c"; sourceTree = ""; }; + E7B01B961664031B000485F1 /* SecDispatchRelease.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecDispatchRelease.h; sourceTree = ""; }; + E7CC89D31909DF3F005FFA08 /* debugging_test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = debugging_test.h; sourceTree = ""; }; + E7CC89D41909E0A2005FFA08 /* su-07-debugging.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-07-debugging.c"; sourceTree = ""; }; + E7E0D8F9158FA9A3002CA176 /* libutilitiesRegressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libutilitiesRegressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; + E7E0D908158FD9CD002CA176 /* su-10-cfstring-der.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-10-cfstring-der.c"; sourceTree = ""; }; + E7FC081B161A3038008E0760 /* SecIOFormat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecIOFormat.h; sourceTree = ""; }; + EBCB283E184D054900EF102F /* lib.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = lib.xcconfig; path = config/lib.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + E742A09914E343E70052A486 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E7E0D8ED158FA9A3002CA176 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 4C6882BC15ABADBC00028C8F /* src */ = { + isa = PBXGroup; + children = ( + 4C8BDD6F17B3920F00C20EA5 /* SecMeta.h */, + 72B9189F179723AE00940533 /* iCloudKeychainTrace.c */, + 72B918A0179723AE00940533 /* iCloudKeychainTrace.h */, + E72D462C175FC35500F70B9B /* SecAKSWrappers.c */, + E72D461D175FAF1E00F70B9B /* SecAKSWrappers.h */, + BEA22A341811E4A600BE7682 /* SecCertificateTrace.c */, + BEA22A351811E4A600BE7682 /* SecCertificateTrace.h */, + 4C6882BF15ABADBC00028C8F /* SecCFRelease.h */, + 4CF1FAC11654EAD100261CF4 /* SecCFWrappers.c */, + 4C6882C015ABADBC00028C8F /* SecCFWrappers.h */, + E777C72215B74037004044A8 /* SecCFError.c */, + E777C71F15B74024004044A8 /* SecCFError.h */, + E7B01B961664031B000485F1 /* SecDispatchRelease.h */, + E7FC081B161A3038008E0760 /* SecIOFormat.h */, + 4C6882C115ABADBC00028C8F /* array_size.h */, + 4C6882C215ABADBC00028C8F /* comparison.c */, + 4C6882C315ABADBC00028C8F /* comparison.h */, + 4C6882C415ABADBC00028C8F /* debugging.c */, + 4C6882C515ABADBC00028C8F /* debugging.h */, + E7CC89D31909DF3F005FFA08 /* debugging_test.h */, + 4C6882C615ABADBC00028C8F /* der_array.c */, + 4C6882C715ABADBC00028C8F /* der_boolean.c */, + 4C5BCD8917304B8100DCEFB4 /* der_null.c */, + 4C6882C815ABADBC00028C8F /* der_data.c */, + 4C6882C915ABADBC00028C8F /* der_date.c */, + 4C6882EB15ABC4B400028C8F /* der_date.h */, + 4C6882CA15ABADBC00028C8F /* der_dictionary.c */, + 4C6882CB15ABADBC00028C8F /* der_number.c */, + 4C6882CC15ABADBC00028C8F /* der_plist.c */, + 4C6882CD15ABADBC00028C8F /* der_plist.h */, + 4C6882CE15ABADBC00028C8F /* der_plist_internal.c */, + 4C6882CF15ABADBC00028C8F /* der_plist_internal.h */, + 4C6882D015ABADBC00028C8F /* der_string.c */, + 4C6882D115ABADBC00028C8F /* fileIo.c */, + 4C6882D215ABADBC00028C8F /* fileIo.h */, + 4C6882D315ABADBC00028C8F /* sqlutils.h */, + 4C068F801653146500E8A1BB /* iOSforOSX.h */, + 4C068F821653147D00E8A1BB /* iOSforOSX.c */, + 4C3600431680DEB90049891B /* iOSforOSX-SecAttr.c */, + 4C3600441680DEB90049891B /* iOSforOSX-SecRandom.c */, + 4C143CF7165172AD003035A3 /* SecDb.c */, + 4C143CF9165172C0003035A3 /* SecDb.h */, + 52743BD516BB278C001A299D /* SecFileLocations.c */, + 52743BD716BB27A1001A299D /* SecFileLocations.h */, + 52E2E4941738371400E78313 /* SecXPCError.h */, + 52E2E4961738394C00E78313 /* SecXPCError.c */, + E706B78918FC822B00797907 /* simulate_crash.c */, + ); + path = src; + sourceTree = ""; + }; + E742A09114E343E70052A486 = { + isa = PBXGroup; + children = ( + EBCB283D184D051D00EF102F /* config */, + 4C6882BC15ABADBC00028C8F /* src */, + E7E0D8E7158FA984002CA176 /* Regressions */, + E790C0F5169E4B5E00E0C0C9 /* SecurityTool */, + E742A09E14E343E70052A486 /* Frameworks */, + E742A09D14E343E70052A486 /* Products */, + ); + sourceTree = ""; + }; + E742A09D14E343E70052A486 /* Products */ = { + isa = PBXGroup; + children = ( + E742A09C14E343E70052A486 /* libutilities.a */, + E7E0D8F9158FA9A3002CA176 /* libutilitiesRegressions.a */, + ); + name = Products; + sourceTree = ""; + }; + E742A09E14E343E70052A486 /* Frameworks */ = { + isa = PBXGroup; + children = ( + E742A0C014E344940052A486 /* CoreFoundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + E790C0F5169E4B5E00E0C0C9 /* SecurityTool */ = { + isa = PBXGroup; + children = ( + E790C14A169E5D9C00E0C0C9 /* readline.c */, + E790C14B169E5D9C00E0C0C9 /* readline.h */, + E790C0F6169E4B8500E0C0C9 /* security_tool_commands.h */, + 4CB23B9616A09318003A0131 /* security_tool_commands_table.h */, + 4CB23B9716A09503003A0131 /* not_on_this_platorm.c */, + ); + path = SecurityTool; + sourceTree = ""; + }; + E7E0D8E7158FA984002CA176 /* Regressions */ = { + isa = PBXGroup; + children = ( + 4CC92B1E15A3C55200C6D578 /* utilities_regressions.h */, + 4C8BDD7117B4ABCC00C20EA5 /* su-05-cfwrappers.c */, + E7CC89D41909E0A2005FFA08 /* su-07-debugging.c */, + E7E0D908158FD9CD002CA176 /* su-10-cfstring-der.c */, + E7AAB5F815929D3E005C8BCC /* su-11-cfdata-der.c */, + E79D9CE2159D2DB8000834EC /* su-12-cfboolean-der.c */, + E79D9CE4159D3138000834EC /* su-13-cfnumber-der.c */, + E7934D6E15A3A298007666E0 /* su-14-cfarray-der.c */, + E765E23315A79EA6006C7347 /* su-15-cfdictionary-der.c */, + 4C3963D815ACF2E700762091 /* su-16-cfdate-der.c */, + 4CF1FAC316550F6900261CF4 /* su-40-secdb.c */, + 4CC0275117A1C796004067B2 /* su-41-secdb-stress.c */, + ); + path = Regressions; + sourceTree = ""; + }; + EBCB283D184D051D00EF102F /* config */ = { + isa = PBXGroup; + children = ( + EBCB283E184D054900EF102F /* lib.xcconfig */, + ); + name = config; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + E742A09A14E343E70052A486 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 72B918A2179723C100940533 /* iCloudKeychainTrace.h in Headers */, + 4C6882D615ABADBC00028C8F /* SecCFRelease.h in Headers */, + 52E2E4951738371400E78313 /* SecXPCError.h in Headers */, + 4C6882D715ABADBC00028C8F /* SecCFWrappers.h in Headers */, + E72D461E175FB73100F70B9B /* SecAKSWrappers.h in Headers */, + 4C6882D815ABADBC00028C8F /* array_size.h in Headers */, + 4C6882DA15ABADBC00028C8F /* comparison.h in Headers */, + 4C6882DC15ABADBC00028C8F /* debugging.h in Headers */, + 4C6882E415ABADBC00028C8F /* der_plist.h in Headers */, + BEA22A371811E4CF00BE7682 /* SecCertificateTrace.h in Headers */, + 4C6882E615ABADBC00028C8F /* der_plist_internal.h in Headers */, + 4C6882E915ABADBC00028C8F /* fileIo.h in Headers */, + 4C6882EA15ABADBC00028C8F /* sqlutils.h in Headers */, + E777C72115B74029004044A8 /* SecCFError.h in Headers */, + 4C068F811653146500E8A1BB /* iOSforOSX.h in Headers */, + E790C14D169E5D9C00E0C0C9 /* readline.h in Headers */, + 52743BD816BB27A1001A299D /* SecFileLocations.h in Headers */, + 4C8BDD7017B3920F00C20EA5 /* SecMeta.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E7E0D8EF158FA9A3002CA176 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4CC92B1F15A3C55200C6D578 /* utilities_regressions.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + E742A09B14E343E70052A486 /* utilities */ = { + isa = PBXNativeTarget; + buildConfigurationList = E742A0A914E343E70052A486 /* Build configuration list for PBXNativeTarget "utilities" */; + buildPhases = ( + E742A09814E343E70052A486 /* Sources */, + E742A09914E343E70052A486 /* Frameworks */, + E742A09A14E343E70052A486 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = utilities; + productName = security_utilities; + productReference = E742A09C14E343E70052A486 /* libutilities.a */; + productType = "com.apple.product-type.library.static"; + }; + E7E0D8E8158FA9A3002CA176 /* utilitiesRegressions */ = { + isa = PBXNativeTarget; + buildConfigurationList = E7E0D8F6158FA9A3002CA176 /* Build configuration list for PBXNativeTarget "utilitiesRegressions" */; + buildPhases = ( + E7E0D8E9158FA9A3002CA176 /* Sources */, + E7E0D8ED158FA9A3002CA176 /* Frameworks */, + E7E0D8EF158FA9A3002CA176 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = utilitiesRegressions; + productName = security_utilities; + productReference = E7E0D8F9158FA9A3002CA176 /* libutilitiesRegressions.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + E742A09314E343E70052A486 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0600; + ORGANIZATIONNAME = "Apple Inc."; + }; + buildConfigurationList = E742A09614E343E70052A486 /* Build configuration list for PBXProject "utilities" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = E742A09114E343E70052A486; + productRefGroup = E742A09D14E343E70052A486 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + E742A09B14E343E70052A486 /* utilities */, + E7E0D8E8158FA9A3002CA176 /* utilitiesRegressions */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + E742A09814E343E70052A486 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C6882D915ABADBC00028C8F /* comparison.c in Sources */, + 4C6882DB15ABADBC00028C8F /* debugging.c in Sources */, + 72B918A1179723B500940533 /* iCloudKeychainTrace.c in Sources */, + 4C6882DD15ABADBC00028C8F /* der_array.c in Sources */, + 4C6882DE15ABADBC00028C8F /* der_boolean.c in Sources */, + 4C6882DF15ABADBC00028C8F /* der_data.c in Sources */, + 4C6882E015ABADBC00028C8F /* der_date.c in Sources */, + E706B78A18FC822B00797907 /* simulate_crash.c in Sources */, + E72D462D175FC35500F70B9B /* SecAKSWrappers.c in Sources */, + 4C6882E115ABADBC00028C8F /* der_dictionary.c in Sources */, + 4C6882E215ABADBC00028C8F /* der_number.c in Sources */, + 4C6882E315ABADBC00028C8F /* der_plist.c in Sources */, + 4C6882E515ABADBC00028C8F /* der_plist_internal.c in Sources */, + 4C6882E715ABADBC00028C8F /* der_string.c in Sources */, + 4C6882E815ABADBC00028C8F /* fileIo.c in Sources */, + E777C72315B74038004044A8 /* SecCFError.c in Sources */, + 4C143CF8165172AD003035A3 /* SecDb.c in Sources */, + 4CF1FAC21654EAD100261CF4 /* SecCFWrappers.c in Sources */, + 52E2E4971738394C00E78313 /* SecXPCError.c in Sources */, + 4C3600451680DEB90049891B /* iOSforOSX-SecAttr.c in Sources */, + 4C3600461680DEB90049891B /* iOSforOSX-SecRandom.c in Sources */, + BEA22A361811E4C800BE7682 /* SecCertificateTrace.c in Sources */, + E790C14C169E5D9C00E0C0C9 /* readline.c in Sources */, + 4CB23B9816A09503003A0131 /* not_on_this_platorm.c in Sources */, + 4C5BCD8A17304CE600DCEFB4 /* der_null.c in Sources */, + 52743BD616BB278C001A299D /* SecFileLocations.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E7E0D8E9158FA9A3002CA176 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4CC0275217A1C796004067B2 /* su-41-secdb-stress.c in Sources */, + E7E0D909158FD9CD002CA176 /* su-10-cfstring-der.c in Sources */, + E7AAB5FA15929D44005C8BCC /* su-11-cfdata-der.c in Sources */, + E79D9CE3159D2DB8000834EC /* su-12-cfboolean-der.c in Sources */, + E79D9CE5159D3138000834EC /* su-13-cfnumber-der.c in Sources */, + 4C8BDD7217B4ABCC00C20EA5 /* su-05-cfwrappers.c in Sources */, + E7934D7115A3A29D007666E0 /* su-14-cfarray-der.c in Sources */, + E765E23615A79F77006C7347 /* su-15-cfdictionary-der.c in Sources */, + 4C3963D915ACF2E700762091 /* su-16-cfdate-der.c in Sources */, + 4CF1FAC416550F6900261CF4 /* su-40-secdb.c in Sources */, + E7CC89D51909E0A2005FFA08 /* su-07-debugging.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + E742A0A714E343E70052A486 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_STATIC_ANALYZER_MODE = deep; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DEBUG=1", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + RUN_CLANG_STATIC_ANALYZER = YES; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx"; + }; + name = Debug; + }; + E742A0A814E343E70052A486 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_STATIC_ANALYZER_MODE = deep; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1"; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + RUN_CLANG_STATIC_ANALYZER = YES; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + E742A0AA14E343E70052A486 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = EBCB283E184D054900EF102F /* lib.xcconfig */; + buildSettings = { + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/../sec/SOSCircle/", + "$(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + E742A0AB14E343E70052A486 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = EBCB283E184D054900EF102F /* lib.xcconfig */; + buildSettings = { + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/../sec/SOSCircle/", + "$(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + E7E0D8F7158FA9A3002CA176 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/../regressions", + "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + E7E0D8F8158FA9A3002CA176 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/../regressions", + "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + E742A09614E343E70052A486 /* Build configuration list for PBXProject "utilities" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E742A0A714E343E70052A486 /* Debug */, + E742A0A814E343E70052A486 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E742A0A914E343E70052A486 /* Build configuration list for PBXNativeTarget "utilities" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E742A0AA14E343E70052A486 /* Debug */, + E742A0AB14E343E70052A486 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E7E0D8F6158FA9A3002CA176 /* Build configuration list for PBXNativeTarget "utilitiesRegressions" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E7E0D8F7158FA9A3002CA176 /* Debug */, + E7E0D8F8158FA9A3002CA176 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = E742A09314E343E70052A486 /* Project object */; +} diff --git a/SecurityTests/AppleID-certs/Apple Application Integration Certification Authority Cert.crt b/SecurityTests/AppleID-certs/Apple Application Integration Certification Authority Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..a2d8bdb96f1c6100bf4635af5845489ffa5b3f96 GIT binary patch literal 1051 zcmXqLVi7lJV*0;;nTe5!iBZ~smyJ`a&7D}zCjA-4f18*?ZNn=n&ou%WPl zAc(^y%;i{6kdvz5nU}0*sAix7666+^g$O#Q7L{bCWhN(1c-z=)ibXoHN6PpY#g32Xkt`C4kJcZ2IeM4eg>d87gG}>Bg5n9&FWb^ z`}0=$JU?ompX>8%(bTK2uQIJKC~@0)v44&A_Io@n7be92e;(<4Zr9agN8kGY*?)L? zq~*_)7kpmx=YM-s)$!{7w&zKV^|SbodWpSW^K3@ElU>tk+09w+r4My)pa<$PA!+a^h?>U@f+u| z&MsRI&R!1Q4Y9jeBR^KMF5!$$TlThl@}A?dmF5p!Oegl;xXwRyQo8e+Qf(nmWi!Fp z%b%Kd2s1G=GB7S~TxZa@+JFxj(z5)FjQ?3!fXS=PfFHyc2Ju-9n1PgmEJ%QlMT|wn z@KxDL<&vfMul#+t;NY@(#{~HV-x$b)q?K7D48$5lv@c}3PbuU4_a(bm&tchjci(!B zI0G|~0(lmF16>2{1)2-g+f*}3N(!v>^~=l4^%6lTR4+L{S0BtuPSh^~COEz1q8tMO zHZE`?PflTDVrF3irgPL}4~$YqhThbci~p@{)srTOev3S3ee%%%Ij%PS$9}rBpZ@!x z(o8{D?z`40PG5~L|MnXQADmbgDcNvs^l}=n`}-4f%%5Do^>yJ5r`LM}#h6W}$VM4D*;X|E^Ix>zYEK2{lhYb` zY5p($w{N|)$X0TrvaEgDcH}^m-j6GbHRi4Y03KYFR{#J2 literal 0 HcmV?d00001 diff --git a/SecurityTests/AppleID-certs/Apple Production ShareServices-7130767241416543643077536561487847634e4d6f773d3d.crt b/SecurityTests/AppleID-certs/Apple Production ShareServices-7130767241416543643077536561487847634e4d6f773d3d.crt new file mode 100644 index 0000000000000000000000000000000000000000..02db461493e80b333b4f57bb78e41e3af1897192 GIT binary patch literal 1543 zcmZ`(3rtg27(Vy*wjkvxibhxM${bUqoIdEKD2;{Ss4Ucti3?_!a@*QgXzT3-RGdQN zkT4vY0d9y34uNexa8v6f6BGtRhipFZkqwEMWj@KoO{Uw}&S`{&m5`pL_F#qTeUs=*-7&KimNfZ`@a5ex~C~D zd3{t$*Fjr~RiY(VO?Z%uPlD-$q4%H84^CYQ?ilGCI%L@jI!?tZ+8WVkL z?a?`xEhURTsI1mRjvjyEXu9XuhuTFBeb@P4&Rx!(ziUrJ2Dk0N%J$y6&EYNA7u_Ed zUT}w2+O+Kcqhq^=UY~os`^4&Y?G|BDbQI`6?DtX4!i1ZpLt?|)B74$_eY4K0!beit zzn`nVE){b6ORgpFJv*NhcL_AlEIAe3qVpfD`ZSb&{O6hn!@-_}>hzsEYYx?qWOj~b zKJDEzvY~0q$mV@t-FY+p$Kl?sqvkJ*NFD)*1~*v?-DHjTjS+=YBm_`|4n(woihwf& z{?P)0&-ddIlMxB$<8mZ58%7k*kliczERt&+yz=*O{n@6EyTgLR9>8Es2qB1nD2hk& z%6#($QxVjRK3l$X-;zr@VL;U0-D}<{O7Co{MCb7>ZV*#$q78voG(6+4G-Kow2sWd! zal!#fB4nHACd}XsU;??o3Jkyw7!-?v14UxM0Sn5yP=vEA!d75LgF#Hr%gX_qP!;## zrxQh(<;%HHXFkY7JUoK|b>Uf@s6JK4jA~d1tNNZ;*?@RXuP3aPgCbmajrST+js-?< z2lkaWu3-1(7_WOH@`?T8m0*1baxO-GTxh1nD0<$CoQR3{f|*#MU5 z>$dv!T-?AI)r#pIg}>>4;-c=x&;LRF_WffT<{(@B+Tasut45&E$;IEq^?ZIZlFYQsBg2!4D>>yS-j;I@c+L7YuChh5U7`KHvAiEsOqE5wMI&W5Px=0B&b;#hyADPKr1x`dQTTp(jgCTo z!8UtFgP!fq=lSQ_e%AKXkUH`2+}53ZH{)ckownU-we|}?AHyW>jf!G=C0A{DZzqYZ zUR*fIJvj8>dVR;uKYl+hIQwj|k87R0Pjj_t->jT;Rj-bAq&^<-@B zm%W!-{69S|b&uzbviZg$sSC@eoYZAvW@KPo+{9P~43RPeK43h`@-s62XJG-R8#V)e z5MLO?XEk63QUIB4HrbfL%co zBPgB8DzG#$asX{)0b&Md!c0zKWi)8~WT3^yq0I(NqwGwKVsaTJB?ZM+`ugSN<$8&r zl&P1TpQ{gMB`4||G#-X4W-@5pCe^q(C^aWDF)uk)0hmHdGBS%5lHrLqRUxTTAu+E~ zp&+rS1js5bF3n9XR!B@vPAw>b=t%?WNd@6N1&|%Uq@D!K48=g%l*FPGg_6{wT%d-$ z6ouscyp&8(HYirePg5u@PSruNs30Gx7i1YwCER{crYR^&OfJa;IuB@ONosCtUP-YY za{2^jO7!e*{cX?eJDxY@8r; zW8atJ+3zl;@Sm>qH@UIM?q|jS>=W#7YAu_)gB31Y9ND;kmOoeaf9*e!%UL;V#2vx} zUUwk!R<>!CBEM2a=7;zgw~E zguTASugG_6SFxo3)|+Pa2irq$E}yy6$m#cutA+FG76xsX-aFYzMMzw9>OIdRD+ Xyc@&=R&`yy_2kb5PImJRrKO4hMS!&; literal 0 HcmV?d00001 diff --git a/SecurityTests/AppleID-certs/Invalid-asset_signing.crt b/SecurityTests/AppleID-certs/Invalid-asset_signing.crt new file mode 100644 index 0000000000000000000000000000000000000000..1584f8e619bb10046e0357b5df991b92bbdf158f GIT binary patch literal 1009 zcmXqLVt#AT#B_B5GZP~d6QiyHFB_*;n@8JsUPeY%RtAGgLv903Hs(+kHesgFU_)U8 zK@f*an9H%CASYG9GcQ@sP|ZLEB*-l+3lVfqEh@=O%S=uz$;{7Fa4ap!$S=w)sWj9z z&<3ev7FL0%%M8fK&r4Onq1-@DoY&CMz}(Qp$jI2p#3BmFwLsz;q!HmXMFV+=(DoSB}NnU`+R#HfTEDvYcQ%uS5^3_x)% zrY1&4hOMU?euOso%j{8?^UbQ$b$xu%+$e7M6VHeQ#)P(24jqeERj%L;ooaJtb^qaY zB_;(-doD%yEJ!vwIyZ8mPyfF=Hw`M4oC>Jk^jr|6Ez@U`nXJq`(!otkN-T+QIvcfD(1`Oa( zmgQp+V-ZOXIP!1P6)p?89ZBU2Vhr}ktdTuvU;)x8&thnxZ=kzCdx2(~dPYe}ft9{~ zd3m{BA}F!xCFkergIURm`k4iww4;|?lw%+X(y0Klliz^XfE${AlT%nZkfRNln1Rv8 z$S{Aw;)fMaJ&$;_$MB0E@aDF^JAJ{LiCf;N)_i+(p?P+N%-+3zd(W?7ePODueY{(@ z>A@Wr2{WD0#`l4{=frKCyDM&q=IXx0gT~7`RGu&JaD917PW!-07G0BBp|e&Una0&T z?~;ACZQEwvZ$4W$@s<{R+PY}(iAdq6e)}UQKU{ZO?s%bL+7XMcC;Qw&ta>7+awOZR zo88JPN!H6gc>Le}PX;Q<3sqImg>5(7@kZ_7<819fslNJl?T z-{bHLyT$ikXL2}Dv-QN$X?yd2>b!_iJbYCtCAfX#-PH@{y_E3knAN;r_fW#c$$NKY Rc5XCjzmYWI%_WiD#sF=GeT4u3 literal 0 HcmV?d00001 diff --git a/SecurityTests/AppleID-certs/iPhoneCACert.crt b/SecurityTests/AppleID-certs/iPhoneCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..c6849621d8e5b36ead6142b5114848dafa03b52e GIT binary patch literal 1015 zcmXqLV*YH<#B_TBGZP~d6Qj5RFB_*;n@8JsUPeY%RtAG4Lv903Hs(+kHesgFU_)U8 zK@f*an9H%CASYG9GcQ@sP|ZLEB*-l+3lVfqEh@=O%S=uz$;{7Fa4ap!$S=w)sWcQb z5CN%U7UqSh3(C(gQE+xNkQ3)MFgGwUG%_?dF*dS@66ZBCLgE@!Qqc{%2HFres6gD1 z8IX~mm#Ton$p%e~O2{F?$jZRn#K_M86z5`UVq|1kEVu82`++U<1ft!R>`>g{-=TN^-~VKbh}-g#39Ky`9aEMgMTN@p>1ZSKbYrTiU-xZ~2>YcXQDL;mv== zZ|-@%;_acH#6wy?-<(?-cP;aE3U@C@|BeL#Zk%@{pFG_#C3pAtnKO>OnC<9y7c4RFPLxU$=(tOZCj!l;mPyL{ko`$@wWpDT)YbQ>1@?9Fz?Y5eSPss&UA~=u#KkL z5wBbptF^v6k>>T}eCG$-S4~q?K7D48$5lv@c}3PbuU4_a(bm&tchjci(!BI0G|~0(lmF17IXB&|IM2 zrkYVwQedU8UtV6Wmk3Iaddc~@`e0UaqJ9xDdFdq=jbqms=gzg*sn91{GbD=8J&d6~n@F()GI-fXLftl>|S&R^mO E07{s9>Hq)$ literal 0 HcmV?d00001 diff --git a/SecurityTests/CreateCerts.sh b/SecurityTests/CreateCerts.sh new file mode 100644 index 00000000..6269bd74 --- /dev/null +++ b/SecurityTests/CreateCerts.sh @@ -0,0 +1,86 @@ +#!/bin/sh + +# CreateCerts.sh +# Security +# +# Created by Fabrice Gautier on 6/7/11. +# Copyright 2011 Apple, Inc. All rights reserved. + +echo "Create Certs" + + +#Overrride which openssl to use: +# System openssl +#OPENSSL=/usr/bin/openssl +# Macport openssl +#OPENSSL=/opt/local/bin/openssl +# your own openssl +OPENSSL=/usr/local/ssl/bin/openssl + +#Override which gnutls-certtool to use: +# Macport gnutls +#GNUTLS_CERTTOOL=/opt/local/gnutls-certtool +# your own gnutls +GNUTLS_CERTTOOL=/usr/local/bin/certtool + + +DIR=test-certs + +mkdir -p $DIR +cd $DIR + +#generate EC params +${OPENSSL} ecparam -name secp256k1 -out ecparam.pem + +echo "**** Generating CA keys and certs..." +# generate CA certs +${OPENSSL} req -x509 -nodes -days 365 -subj '/CN=SecurityTest CA Cert (RSA)' -newkey rsa:1024 -keyout CAKey.rsa.pem -out CACert.rsa.pem +${OPENSSL} req -x509 -nodes -days 365 -subj '/CN=SecurityTest CA Cert (ECC)' -newkey ec:ecparam.pem -keyout CAKey.ecc.pem -out CACert.ecc.pem + +echo "**** Generating Server keys and csr..." +# generate Server EC key +${GNUTLS_CERTTOOL} -p --ecc --sec-param high --outfile ServerKey.ecc.pem + +# generate Server certs +${OPENSSL} req -new -nodes -days 365 -subj '/CN=SecurityTests Server Cert (RSA)' -newkey rsa:1024 -keyout ServerKey.rsa.pem -out ServerReq.rsa.pem +${OPENSSL} req -new -nodes -days 365 -subj '/CN=SecurityTests Server Cert (ECC)' -key ServerKey.ecc.pem -out ServerReq.ecc.pem + +echo "**** Generating Client keys and csr..." +# generate Client EC key +${GNUTLS_CERTTOOL} -p --ecc --sec-param high --outfile ClientKey.ecc.pem + +# generate client certs +${OPENSSL} req -new -nodes -days 365 -subj '/CN=SecurityTests Client Cert (RSA)' -newkey rsa:1024 -keyout ClientKey.rsa.pem -out ClientReq.rsa.pem +${OPENSSL} req -new -nodes -days 365 -subj '/CN=SecurityTests Client Cert (ECC)' -key ClientKey.ecc.pem -out ClientReq.ecc.pem + +echo "**** Signing Servers certs..." +# sign certs +${OPENSSL} x509 -req -in ServerReq.rsa.pem -CA CACert.rsa.pem -CAkey CAKey.rsa.pem -set_serial 1 -out ServerCert.rsa.rsa.pem +${OPENSSL} x509 -req -in ServerReq.rsa.pem -CA CACert.ecc.pem -CAkey CAKey.ecc.pem -set_serial 2 -out ServerCert.rsa.ecc.pem +${OPENSSL} x509 -req -in ServerReq.ecc.pem -CA CACert.rsa.pem -CAkey CAKey.rsa.pem -set_serial 3 -out ServerCert.ecc.rsa.pem +${OPENSSL} x509 -req -in ServerReq.ecc.pem -CA CACert.ecc.pem -CAkey CAKey.ecc.pem -set_serial 4 -out ServerCert.ecc.ecc.pem + +echo "**** Signing Clients certs..." +${OPENSSL} x509 -req -in ClientReq.rsa.pem -CA CACert.rsa.pem -CAkey CAKey.rsa.pem -set_serial 1001 -out ClientCert.rsa.rsa.pem +${OPENSSL} x509 -req -in ClientReq.rsa.pem -CA CACert.ecc.pem -CAkey CAKey.ecc.pem -set_serial 1002 -out ClientCert.rsa.ecc.pem +${OPENSSL} x509 -req -in ClientReq.ecc.pem -CA CACert.rsa.pem -CAkey CAKey.rsa.pem -set_serial 1003 -out ClientCert.ecc.rsa.pem +${OPENSSL} x509 -req -in ClientReq.ecc.pem -CA CACert.ecc.pem -CAkey CAKey.ecc.pem -set_serial 1004 -out ClientCert.ecc.ecc.pem + + +#export client keys and cert into .h + +${OPENSSL} ec -outform DER -in ClientKey.ecc.pem -out ClientKey.ecc.der +${OPENSSL} rsa -outform DER -in ClientKey.rsa.pem -out ClientKey.rsa.der + +xxd -i ClientKey.ecc.der > ClientKey_ecc.h +xxd -i ClientKey.rsa.der > ClientKey_rsa.h + +${OPENSSL} x509 -outform DER -in ClientCert.rsa.rsa.pem -out ClientCert.rsa.rsa.der +${OPENSSL} x509 -outform DER -in ClientCert.rsa.ecc.pem -out ClientCert.rsa.ecc.der +${OPENSSL} x509 -outform DER -in ClientCert.ecc.rsa.pem -out ClientCert.ecc.rsa.der +${OPENSSL} x509 -outform DER -in ClientCert.ecc.ecc.pem -out ClientCert.ecc.ecc.der + +xxd -i ClientCert.rsa.rsa.der > ClientCert_rsa_rsa.h +xxd -i ClientCert.rsa.ecc.der > ClientCert_rsa_ecc.h +xxd -i ClientCert.ecc.rsa.der > ClientCert_ecc_rsa.h +xxd -i ClientCert.ecc.ecc.der > ClientCert_ecc_ecc.h diff --git a/SecurityTests/DigiNotar/DigiNotarCA2007RootCertificate.crt b/SecurityTests/DigiNotar/DigiNotarCA2007RootCertificate.crt new file mode 100644 index 0000000000000000000000000000000000000000..00a5ab28647d753f1cbb757b4f8ee51bde9965d9 GIT binary patch literal 1422 zcmXqLV(l_$VlG<1%*4pVB*0U4YtBR-Kb?91L@z{4w(&9GW#iOp^Jx3d%gD&e%3u(0 z$Zf#M#vIDRCd}mLV<==G0OD{7bGl@vXZq!rBo-M;8AyP{n1u!5VhTa|`6UX@j)n>b za&YrF8N~!M^V0GiQh-|XKw9s?#f`PbQZp>SPtKoOZ@Y72Y5T4~j~Cqq zc2il7-q?0n>}JP?jqS1px7xPwi*#3=7r0nrwn(VDyv?ifS@nG;!HlJTZR<=TW~&HS zgej@YF?M?g7XEHJ6FDujBPt{K=uTcH^V8mY(!3_rX>qf%zZHuQoltti?WA<`BaVF^ zmCwwSy{5(AtRNbp-lX^Ik>BiU9v2DLkKP&eqtbA^7?II^N&?I8EdlJH=TSY&&qq&N5ic9@(DYcV;%3~ z-gTzDlzn}xv(9K)=Eb{bI_6)za57Et4qN)sDOIy_lYDB=JV8mY|dcVDOw}CsqMw9nQUsn+BIuobL3aV)vO7i{_vD zkg+#gcGLadeD=Aw`qGcP%bnV}U(0FY_T=ESk4}ppeu?sp$lm&7iSgQ)0@*tcKD{m$ znK+C2;46mIJ?wwZ3kfRetXr_x>cJwd8<8(HFH4v%StA%Pxpk}be6T6*Ya5`s&n~HnLi8o+vB9kGV9IG^WH^!A90wiSJqE@dW!LK!R?wRWgRg?o?~Y0 z6RI}Kr$-#Ij)?5s(9;vJ`9|C6jKxQ|o@aV1oI5BN<~?<#a>fmV8;4(S2n{^@^sn}g zue$~32Zww!k?g7DG&_|jt}4#mG^3cOyyWmz-s3BTe2y;hoRd{Wy+t;VXlt_CQZ+hDEp>5`lr$_I%9NhjI0CYZBZ2$lO literal 0 HcmV?d00001 diff --git a/SecurityTests/DigiNotar/DigiNotar_Root_CA_G2-RootCertificate.crt b/SecurityTests/DigiNotar/DigiNotar_Root_CA_G2-RootCertificate.crt new file mode 100644 index 0000000000000000000000000000000000000000..6f69f3f43765c7396a2c96f2e533d88d6a4b475b GIT binary patch literal 1428 zcmXqLVx3^n#9Xm}nTe5!Nr0Pym_kr~eu;v!qk_AU zp@M-N+(=GFF~Q8dw0wsYpzb`7ZoRx5137VC14{#Q17kyDQ%eJ*C~;mRWG-FY(8Q#K z>~%&~2IeLveg=akCN8EXCPs$+>jW5o``B$;!~Au|dF4qOON4EuZY}WdPJOEPSnVP@VJVctN4XKnOaebQ+rw3dk&NfC-v@qa-zRWK(w~>=z_A;4SkGed>x!M z3l>|duFjaW_L)iL`zhj=vh@`VSXWN8T*DK?czkKmhJJpD-bI$T?wCw*SvtYNb;rBs zPqM#cn%}s(s6qeg&u_kJuY(sXY>mIL_mr-T+PZ=nwo-cvla*&WcdoOsj!X|WGjrm7 zm@2?AD|qLNx`!KfDc_o{EYI%UG~ zYkp}hOx6u&?mueJNx4)I?_aPx$5}$^WzK_!u%kzxF|57s`!=xm*elMDoLq};1-tvt zo^koX$$dB4W0nRl?p=L(j~;i`emBA7B@v>lWb*!bvIR4FeZKt3@oaefRMj01+dn5v zuYaT1dFpam&fUO?ZpIEbJf`TrVlCReMP^~h_T$f9dev!fx~?c0&+uecOz%RA^_E(1 z5==cJ^eY#g^3i%yw?eQZ@a=wn>pa$t4epjt(jT=a9_d@tev*lqk%4islYxT)KQOV& z3NtePXJIv922uumAOU`m01Gfru^GsM_4P;CB)D(H}KAbO<{WjTuc5>slIsqgY^^Nhb}Mg zXSY03@|jw(Wy+aw&UuRMYo;v}mgYV>Gd)K3qv%$XJ9~b}y;*HPMSWA}%s*En?3ONJ zyX^c^#*DY0Ng(DcD?|COqiESqR%vBEK8N(Jm0l^OB-qzUh5vVvK7K#?^5(NYH{|;sI^FcNJ5TdMWaFG1zrWQ2*UJRv z>$o=li!E5Qr{VM`#Y2aalx|D-3G};eke;QayyS|^_pC+6_kW&YT@m_X@ATFc_co{A z^m3g_DeO<#RDP_BL`=$meS`%Lw%KO6qN zb6fTQo9)s439C#JO|?HWF?M;);ZjQcH5Iesx=eL<-gAtd2zXJFN>Rf?zabb zoctR9#6Fl6RyZTc|8d-(%Acpt9NiJaYIq{)+sgd^*^fVzU4FIixg+Cup5-pVnh);2 iznQHQapL-nN3u^eH+MhHDLa|moGVqCSM2lPz-a&%q*gHi literal 0 HcmV?d00001 diff --git a/SecurityTests/DigiNotar/Expectations.plist b/SecurityTests/DigiNotar/Expectations.plist new file mode 100644 index 00000000..06054ba4 --- /dev/null +++ b/SecurityTests/DigiNotar/Expectations.plist @@ -0,0 +1,8 @@ + + + + + Invalid-CertiID_Enterprise_Certificate_Authority.crt + + + diff --git a/SecurityTests/DigiNotar/Invalid-CertiID_Enterprise_Certificate_Authority.crt b/SecurityTests/DigiNotar/Invalid-CertiID_Enterprise_Certificate_Authority.crt new file mode 100644 index 0000000000000000000000000000000000000000..3e58bd3f2193952825b22c950aeea0dbcbc650b0 GIT binary patch literal 1558 zcmah|Yfuwc7|kY|AkqL5ijn6cLW5#*LjidU22_wz9wHK_LI{zpgltR#Y09GzMnF(O zMJyB*@r4KjDU`Nofhs7BL}N8z6;VJ(8Ns5U_!y-ds}5~{^!~YX&fM?pnX~5uDvB9U zkzQ4kh!ByufN-q!@+k9~`)ViO<{0nVz4m}gFIGH+wksRphYJ+{?|}_ie|unX1X4K~5`+Yc z~V47TrNm03yZ4d0``ZD{MFFuwERM6tNc|c?WNd=h@aDF~f z1wn)s+ZeVJ)sCBD+dB&19;*EPcE+YU%iKF<)Jtvqlg}1NWR~k9vNGbQt?B7?rB`22 z9;KcN{v~kLU;<^__Vwbkw-_iIf8*NmDrjJ42>Pwy{+@<7N%LtlQ3JBy;*jLWiPK z`}}H^s`H>NBD*<(hVNs@i<8_HV!ZySmc;HQ*W&_h`Mid-CoFC5<0YrTmIA@cvI#rqd;V` z0R+KJ-~yI@zyQj(70TrjZx$<^Cqk2WaugFY|IraMy*LemX5o2&f?q_40CL;)Bm(EQ zg4|}1+eCqJgwrPhbaLfLW$;FmV#9|GLZt;mMFx zfmja&NeCuJurw*65G2Y_yhe=ws5#>UQUSt~NJMzk5=8<;jv+je=-rq^iY2A-;27HLk0FEkD}8o&OjZ;j;f`ffMHk{pj1MY(5ymdh%qO>CVsBhM6AcQog~b`9-$ z76_W%;Fuh3z~N5ssIA?(^GuhMY$6~kq9;`RT_KVuxiQew>z?29Nx-XW7wxtO4e6cS zUsob+j~6-CW;D9*SJnqjc2A}}d`Ns&G(OxvRPiDow7yIkJ{KdSkXD5{MBZwuh2Kn5 z+8m3rLezD%bDgbj{zB)=U6_|hai6O4ZanDjw1KO*PvNnx;uytojd$ zg>}MqLyxTm8m#TxDYe(7{Ej>E>NVvP8S3HV8;DgM=l8ca2UJIg6|>%Kqy7jsue?v? zFnQ6IyBjK`^o|}zud!}$UF=VHQFEV2r$*9e=XO>6L6$gg>}R+rGUH9q0Re4&WP*#f zY$1tX4TpRm`DvB%eX)}ny;ZRlp(T5c+B>SJ`d3$& wUEDqfagX?v93dP#ZsJ892up5?zi`6yMt!1X%t8Mz&i{}_Q}O1FJ)a)?3tEn3Z2$lO literal 0 HcmV?d00001 diff --git a/SecurityTests/DigiNotar/Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt b/SecurityTests/DigiNotar/Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..20f2254d38c5c34e9a13371cb69d5bf4bbcb7b6d GIT binary patch literal 1696 zcmXqLVw+>o#L}{WnTe5!iG|V7WWNC~8>d#AN85K^Mn-N{27^RHZUas>=1>+kVJ1Hx zLpcK(5QmFLG`J)&u|y#ywMfA)6-eeJ=B1?O85$WFfaIBZG_lGn_!p%o=4BQqmSmnb%MBoD8vbTE}7|> ze)%PdMG8)OVR}e*BP0U6J@d;_i!xF(Q$Y41TMxFoiAf3B$Be8D%uP)E3(98lPF^^4!F zjK=;|*&pW?8BgQ;zNuyDQuQP19|Mau%Xg*c{qwoA<iYlk>CH^%5yh4(8t7JFl<(n%6p$>8$TWmVLWpQRnqiC4}8}dWN}MHt+EjitB|#o^WP; z^mXGp8T)&-|K5AQw}+hGVKHa9C%u7dJ5`8ZH8QBaPTR{TKEOiDo4I-8T-JX+TZYK&Uob{Y5)pu)7 zy2H+eaZ6&*vj(BuscoPMG!>XTm9Xc|p#1z2Shj3pVVE)Pi-9M|8S*Sn1`Y;x3v3ox zwOK&Dm|T>jhvXxWCtdP$kusQ1Vo7RoiF1&TuDg*QP_=<9$S6J*F&2?Mu~V#XuC8WQ zElxaiTld|c)%~dpk+UJN-~nbsMuz@Bx<1=)>Ry%K`~LKo?HS^wbN#M;hU2`+qsNE8Y!%Z#ad_YL%f+i1%zjFF)m=+|8RxcZ>9#)6?TfW;ILp3| zJt5!Ny1D!Nf158izqoPO&)Flp;N}XSv#LRUTpJa>%fEEK8RFI`JnKMQNsiVGqgQ{* zck?b?WH>{quBPVsttD&UY}b>LEd1dSaLc)0r{(TJ2ldBWKZyEGyYeIEahs-__H}Fa z*B13B+QO$_ey?SGL_FYXN@lipwrgChzWAvqzw?K$TiSfJp6|AE_H#bZ>2t4LeJsuY zs-MwsmhhBFE+%#lZ>faU_5N?UZ-nw@sA*ZIt&4rUbLS?V40*X(6PPVO ztlGTfjAyrm$xHK-)tbj!YVut~_1`2$vYd21z35udqMCZmN!PrNb~~-O^6%A+u|C)X5HMQhW{_b@NHdD_u-}fuJs-3o^HJuv2^{M!sVKb6Ph#4n^<@K v;XKHZ*HdAA*qEuo-ldg8_I_v>$6B3M-Pn!H57(_KIlAPt-!AhR)lEAArK7fA literal 0 HcmV?d00001 diff --git a/SecurityTests/DigiNotar/Invalid-asterisk.google.com.crt b/SecurityTests/DigiNotar/Invalid-asterisk.google.com.crt new file mode 100644 index 0000000000000000000000000000000000000000..31f5b0638f5ea6c2e2b55c0f03d6eb4d4ad33e5d GIT binary patch literal 1324 zcmXqLV%0EcVi8!t%*4pVB*6OU*^;xIuR^Y+ZYceyv?$DgmyJ`a&7D}zCr zA-4f18*?ZNn=q4~kD-u(0EojS%;}Pup6Qogl2~M@Xdn*~V-}Wxizx(@Cgo%%D>yqU z7#SFu8Y&pb!Hwl)6cfzMOUrji0h*8pGC?md$3RY;*U-?w+|a<#(!k8vAPUGeHZV7^ zgmMkCklYa(Y$$9X2yq9Odwza;PO5@uUb3N>fe1*DU6|K5zcjBTF*8pgEHky-P~1Qi zB+e?#7vODRU|?iqX#}JUj0{B$gdr~H(b7u?o1>SUpKH*>sDvC0jI0dIO^o~uKyfan zCPqevv$>Df<*1fq=p;f|#FGb-ms@pzRH?rET)bmji?zCf z^u0xam8Y!o-15HfWMSSF_?WrC)g}JCpRWAj{2SZfD^)e?nI0B1U#PKr;;QY_BqwHn zeZNY+LhTJ(vbO!Xk5&@7KIST%t5P0@NJ^)^t~ZMbUmbf!tJ0@mPxkiKx5ta)a+7Ax z*FE*;Xq7^XC3DT5&&BNDPpmKKbe^?i$GIp?+r#{m?}eNHSo_J#;Rcg$MhENp@WMoq zU1vTpoqX23eVf3PSSDsh2FArrjAwu$a>BrhjYFFam{!;s8CmoUbPTj$d;`Wdxr~yM z0xNy}vc#Osl*E$E{5(CBSO+B>S!EUp1F;5?`^E>>Px@#6XWI=iu?sghPQ3anZz(wG z$qKVD888?$9s?;>U}@ZE(74;6aR(b;LW=-ndnO|zBNGcSDH}8{HBg7y&BQ1s4Yj+x zyd1?+{p5mTgDSW}CWAbw9OwMJluVHGiggqcixqNH^FW-`6ovdeh5XVYh4R#-;>?m% z1r2n=G=b`iQWX*l3V_KyF$tIuOY#*Gb8^7C3X1YmN|Q^96%zAO6pB-e$}*Evi}egV zLH>|uaWZf)uv=iWz^csx>Qbl@G}jj8=of%<6DTL?=OmV-7MC~&`RFAV|HLuVyd5p(?#b?8=9`IT_wjfJ@~Cu;`#r~x{Qo2>2aC~np-ZL3+|Y{m2IYfcH=U2 z?~h(mwY4fmviIMInQlDgC}jQa=``^uo*F`_fv=qw{v25tVG5 zs{Z@vwcf&Yohs!m%h+}ZU-|Ugud1J|b5jZcZ#~aZ literal 0 HcmV?d00001 diff --git a/SecurityTests/DigiNotar/Invalid-diginotarpkioverheidcaoverheid.crt b/SecurityTests/DigiNotar/Invalid-diginotarpkioverheidcaoverheid.crt new file mode 100644 index 0000000000000000000000000000000000000000..e6ae7dd482605dab52cc98dc5ed2939cb4685aab GIT binary patch literal 1151 zcmXqLVyQN0VoqMb%*4pV#KLIkQf9!*#;Mij(e|B}k&%^^!64F*+klgeIh2J>n90w_ zP|iRG#NiSa4K7JcEKx{FEmH7H1(G?5c`2!RhFS(1AbDnCMXd4){$;5}8L62m3eJuO za^k!OCI)6kCI%LUmc~X=;=G0iK&~;6Yi?{7We|jFwYY&O#A-g5%=ApZ{F1~X1t+~Q zJtR935&_aKrS7&|ugw?9< z>$N!tF z*r(Yot<1mNQdVc(n;gX5GDGMlbLF}_Rfp;}KHs`8*6yxSyUE5k+0K8}ravk0K34qo z^EJH{CoMY#Y@cW+d0v{e>zDd}5igg`3DQdsoOjptYO_AF;cka$$TO!{QFSI}Mh3>k zO^gA+5b-ha00y|M0*j-8y@4$o3y{fRU}|8@#-YsyOdIS>jAH5;B_#z``ugSN<$5W= zSjhv$ie6rhesV#venEC7EDj9#K_&?^GX7^_HDCr(27Dj^evkkQF!8Y&G&X<)lvyeb z${R$u+ph7KFV5KbJB9ObM_vqzO!!ONg^^3b4MI_q1fkTZW}pHz6_^@jv8TqM{QMGN zN^D|bm@%so=tZCls@+YRfELmHyWNOS}gNNG=o|!wcddhs z^MzIW_O*YI-!q$wWur+BXRhFG) zZn`QZuzuq!D~H`*YOKsR@BTki@QguE|0yfMeV_a1^+c{c;i(;Xo1w(ryZ-N7tup`% CLZ$Qo literal 0 HcmV?d00001 diff --git a/SecurityTests/DigiNotar/Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt b/SecurityTests/DigiNotar/Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..a8c7e7a1f4cf9db53897feaa057f92b8990d14c6 GIT binary patch literal 1164 zcmXqLV(BnwVlG&~%*4pV#KLHpxxs*!jZ>@5qwPB{BO@y-gF&Prw*e;`b0`a&Fq5B; zp`3vXh{Gi;8eEc?SfY@UTBP8Y3M6w9^HNgt47Ch2K=RDOidf|p{L4~{GEy^B6r3Fm ze)%PdMG8)O zVS0u@6Cif#AtVC4J@XM(A*@Z!Q*cU6Day<$OU*NAVpKx*E+Z=ga}y&!15licsfm%1 z;m+Pm%l)#rc3UrMeOS-1cHb6*j2Y}_7gQaYa=!3qm-&<6*WqPnx}W9zd)FR%!frQ< zCByQDiZ#*xbzk=G2-#6+&2H#vIXR?8!Makre|O@9+Kp?T$xqOm>&mz?Mc4PR{?6wC zSN*hNR+p8TyIrq*<23X8qBl!A3+`BGw=Y|z@@(!T73qE7{$A0S6t8+_#6Bg2HQ4!O z&Ytz|r}v!xyVu%9sPSXA_wKh_&aYPWm$-C>>Ca;Stxm?LBhPZ)xg79!L0Qk5y0k8* zZ);^Hectw4#O<~3b$x>ex$mOQ_PLa7S6~fq^?ku0x#%0uvvms(INe{qrYZJ##&(Hk zo!+yuf1RuR`B`T<6Eh6-WB|sTF&l?A8!(}; zGck&(XOxr_Sn2DRmzV3M0HY`m6h(S@Ir_;3#rg%=nXm{k;0Ku`%*gnkh1Gx=NEz^f z1o%M$EWnh=X3*FG5>RHTG$?Nn;cmOeU%ohFtE)RSdv;?;vD3o2UKAo3)0TVBE}-(!*Q~=?Bk5%cK2zDFwEUTP;207IM zGZ`?|F*5K>X_wmX`?&SdyX!ZSEBONMA8U!ewEN~)LoO-P=_U6?erfUByLUav^bMVY60B`kBczc+Dly??SC1e!1+!ss> V<8zo0=(0xY@5gto^531JQUL;>v2g$Z literal 0 HcmV?d00001 diff --git a/SecurityTests/DigiNotar/Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt b/SecurityTests/DigiNotar/Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt new file mode 100644 index 0000000000000000000000000000000000000000..5fc902b4fc236f0bc2c7e276177528be0216f2f1 GIT binary patch literal 1364 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/DigiNotar/Invalid-www.maestre.com-diginotal.extended.validation.crt b/SecurityTests/DigiNotar/Invalid-www.maestre.com-diginotal.extended.validation.crt new file mode 100644 index 0000000000000000000000000000000000000000..4cfb98f85f5aef5ffca5ffcc49619237f09e72fb GIT binary patch literal 1375 zcmZuxeNYr-7{7P#0|5^_mJfq~7h&Q+?(SVag(2fS5CXd4+mJ$*y9JjycCXuoLo)SF zJU^0;a+qeynJ6Oc9}+CXU_vJ_CMwg!_(Q`?Y9<{Z28Yaob`cSq_K$bwdFFY3&+~hK zzju*SUWS}9Lx&Ut7^ae3Qs?ZbZ(HgcAF$QYze|U0JRLB>-}{1Tlmsa#u); zWeOZK<`O<=gBW<=?&)+jZDe`UMns`VF(<|0Y7S;J@DyXF%&>&C&}NdSSq2*P1VkaL z@b180MKe`wnpr?%L?kU^K_LN3l#CJyL=f==+Oji1Nf1IJc_lLZ%uMX>fkHyF09=O#U;N~KK%$m6S!}f-h>-%0j7>;gtHa5Rf^K_G> zxy54-xp3n0Ena)^uY9#pKVR-^Ega}Qy?ADRSMT@XH>D--M|4+uM%-;`NcBF|-c&v0 zSJ7O0es(}jCgv(JDUg6pC-_`Y^el2*6et8knd1xO7(kAGg;zz>25^`L0IXLC2Xb@? zCR-=SDwn%qz&~g=&s$S;I+5{O`{+zo4mGY8Vu%T}7+A(kiw5LkAj!d6iV*|Bnt~XUe4cN8k#LAXrN^MLQ5QPX|JZf}@Oz0sTKr#F4@GyDmy z7YlFzmSh-`pnNe3m1UzWw7ny}W1A~&1%G9mC%|V=tM%%s1rZ=Ega%ge7M3%a&SK)s(#V`n9#@5`Gm@Cjb)d{o%aU z8SkV+v89Xa!pP&#rbR4{8DqHYtHB@bESk%Zbp^eb?za#zb?8{$8*!W}t7li+Hx-dS zz5ImyNN3~gA=cB)AMd#^a8s3 zypN4fk9<9pc&nlByJ(NwSK}l0zo|dv8~cf#Q=W6}58F5Nr>^|ym?lS=pEz2ky4N)p zc-B$gzPF`M-gffbjzRrkOS5P0Xu#z06YsnvxfYXDl+$V`{=@H|*j-R literal 0 HcmV?d00001 diff --git a/SecurityTests/DigiNotar/Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt b/SecurityTests/DigiNotar/Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt new file mode 100644 index 0000000000000000000000000000000000000000..f96e21513101d5dd2d3c09e23f933af5ee74b8f3 GIT binary patch literal 951 zcmZ8gYe*DP6y7_tk2WSDFcH9>Gh*OSz$&HMg1wV=$$rWwpeg~ob&PBbG~!Fdm%_)h9I5P zL{o^OqQWlpmQ=Mv_?bXKtYwqf1`$T{l--59zeFHpFzCQb!oX~#%k)MIwY-SLK$Mn@ zwU`%jRorqxX8gns6E%#s*g_aCW&O3Bo0TvD=M3!1Cm2#fh0Vws&GDOrJdav~*J@<) zK1hj=fLw4o37J6%kc#*S;#5-@NkKXJuaq>f|B;fk%FE(qLM7*8@q*0Nnb-l4?S$F6 z*^rw-CPAu3Gg%Ug7(dJ7r9Os{wlLMA8qdTU7a)V!AVFgpEYT}VAV-CWdU9t0nMKG* zBifP_2m~^#hZ}hXN#^(}X=F@IzjA8y?vO!8EBkez?4=Y%*Wb_??P!zh?H509URZOz z>rztJp`x8@`ouVX(BvpDS8H%MxaI4-UBlk=hWE2o32CG;Qk8L9zy<>8%j^R~1c# zA~f1a^%KylgPlX`&LQ!{L9R9HipS=5P3sh2KsFuvSogB1<(;lKy!*A-x1!sc lU~SKC=ggg#o(vVUJ$YNwJGOrK)Ybd=*6SCp^mXNlzX8zYE*$^> literal 0 HcmV?d00001 diff --git a/SecurityTests/DigiNotar/Ministerie_van_Defensie_Certificatie_Autoriteit.crt b/SecurityTests/DigiNotar/Ministerie_van_Defensie_Certificatie_Autoriteit.crt new file mode 100644 index 0000000000000000000000000000000000000000..d079183e29368b4380e41efef16bcbd84eb07077 GIT binary patch literal 1262 zcmXqLVtHlI#C&N1GZP~d6APnZ{uTpXHcqWJkGAi;jEtABPGB=hUK-%(Tqp#1f!h$I_DgqRf)i%o2kpMkQpA zGqN%;H!<=v0L8hOniv@wb{BSSmy^!eT4P%7ON(o@&zeY!bCHbLh4ov&;h+Rk!6c|RWg=)3ulkh_h8kPma}O05dB zX)G%GnqC)Kx+k)JNK{xAGs)`zs)JT_o0wbg>8zUhR$kE7brwrg`2;(?GNXyCGcO%= zTA8Y)`8410_hg;DQbk|9@31$zWEk9XvE9SFQ{igR(XFmYe2PZUj3U22vUcIDPuJr*??%eF<+!($Fz z{+RPkw#n~dvEEOa8u!oB_swYg73!VK#LURRxVVXN1u#UG7`OvNSyq9?!NAVIhK&Wt zWH2x>Famm%4VYxunHa^?GD=Dctn~Gh3ySrU6ZLX4foUU6FE2+Q!qQDn)CEfE8}Ne+ z5@uxl&%$cJ45SRgVTLd=vUnSK0&RjCYQWTH4K=j9yj-s!J2M}el0e25gVG`}5#}LM zB1{@+eR5HW0UyXFevnNpz_iY0(AWSHP-dw#C~pwqZo9@`zBps!?-b6%9eFVVYk3wfnJ*q zEYyl}&^_pqpX*=dlUR~kT;d$$1N2djfh`{T<%^Fro;h3QwW zEuFNt?{nXktP_T63u`{4&bPQJ=)W+)@U}v`u)=~?4{N4#6ZBp(ac^A0v`*@9(H<}1 zUGoF-Y%V^&`i`A_0ati{gX-~X2D;4mSr;Gp7rY}!V5j+sn`tj&rzMH{8{b&s%gGeZ z>iN5N&0F0~Z*=+1t}S)>w$M4!DS&m;#4C)uwkEOM;J-1qr%pcNvHre!ixwvTQDFIK z!hQbZ%)85buioK*w66JId#AN85K^Mn-N{27^RHZUas>=1>+kVJ1Hx zLpcK(5QmFLG`J)&u|y#ywMfA)6-eeJ=B1?O85$WFfaIBZG_lGn_!p%o=4BQqmSmm_n;4l!iSq(YF*Y&=at%#Pq73p-ouFVK2XTV9Zzj;F zlGGxgS!IcN3NEQ>sd>ejsfM-&)(}US;83C9oLW?pnUW)WpQdu>942E6wmc*|%Klud5Zk4!IWCC8u=cX}nfcRp_1{ z*ETm)h4VjD=YJD_GA#bWL*^yjao6{oX>R#*ipg%r?`h}S{h6{CJ1&u&>9)|<)ubrb zqkEnB>y{}YYlL?cUH{eYV(OAUEBWrx{hRqduxIB4r5OdNzNph^jp_O|*^htE;aCTm z>#tRHB=#?ldbVcn^N@tcK3r@I9qqEaHlKca&#v?N7S|~YtM*^}u~Y2Jb8RJ-g`6{- zjIo}>?+WmA4~@-gwU0OdxM3N_mM1=mbBd9}RWG%5M->!G&%e`qlAZH( z+cyu@^$$DV+%pi{RmAQmuX-V3bTvKu0RHm;NS^bQ7Th&X((t4=B3&nz-^_XC$hRSoo?f_ z)~Z=%1}#-!Ogf`GOPFP`eEW)yU0+MT+?P&GejuFunMK9dylFBMGb01z;wHu=22G3$ z4BUZ9O;&-$!NAVIhK&WtWH2x>Fk<7-W@BV!WoKd(Q_CnRDX`MlPcA6dOHS0w%>-tY zG`+kWeF#f8IZ+oVrElN_)5FNfVuoyn0aF{yjPmkwy@Kq_{Ib-djMU5&kSV|%rTT8oNq5+}Fm6eVK@@6^Bb4d24K#tK0yDi5_Dmm?pI-vY?M*BUGp2np@B}$S zp2f)k7;Xz}7Fe}ez(T1g2i=D*`MF5NhEHNiYH^8kkPq0;ML7ntAfxzL#8^bmMgEOc z{(R%y4!79$#J~GB?1i?aAm?OYc?QhMj0_7uG+mf=uW-VK`A@<+zI}b*+CODg(X=&- z4&-tuh;mhPbM9pRc=-9B!j$Ys%ksL*-UVL>{jKJ0@jCDN55=aKm8A-A1-D=P=^7}Q zIQ`A?zn?e%ogv9B-*jox>HQu8rmf2lFRAhpNDH^g`fb*oFk#8N9rioE32NCXZkqi$ zSK>j%V>Q7^yWa;Kezb1$>1T7=2a6n)&VMzHN7ZeD&c_GajYBrg{T}ph!HM-o5=%Y^{I~zQ^^kt3 zT(|uC>}&~xHI8d{+gE?He!lay)t2-GDKATXd5M|RIU>%L#UB@$8+YG$qfwqF>-qTS zzb?54zB?4Y#xE)9{X9WFjXy$`+1l~%2AylzuESKzw07O`+zl&Q z_dZxW>1cWI)^j_oXT?{gMBBZ1HP7-hxAfYQ@LO8#NnfQFe6(p;_xZBJkK~=sUqZ^Q zI2{_yu5UW>Q0h@4L)m3+>*=QZy8{L8*B|^Tpqvx4!18l`+|38~xev8plKqh+uxqdD z$uGv~mT|kMPfx3#&Ds;w_@}~Oa{7DiHwTl|b6=m{UL!KgdnxCYJDM9gl-YOy&E~(> literal 0 HcmV?d00001 diff --git a/SecurityTests/DigiNotar/diginotar-public-ca-2025-Cert.crt b/SecurityTests/DigiNotar/diginotar-public-ca-2025-Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..76e1e59d07dc679dfffac9675703a84a06f3aee6 GIT binary patch literal 1543 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/DigiNotar/diginotar.cyberca-gte.global.root-Cert.crt b/SecurityTests/DigiNotar/diginotar.cyberca-gte.global.root-Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..c25eb8290bd398bf664704be94d2e6271f81976c GIT binary patch literal 1374 zcmXqLVvRCrVmZ8knTe5!iG^KVfY*SRjZ>@5qwPB{BO@y-gF&eww*e;`b0`a&FjHu- zp@e}Lh{Gk!?;hf+;GADnkYAKol9``psBWMNlHnGX1Ittadi zD0t>2>lrE=D1sC+3rnFXbkE68O3YCR%Fiz`kQ3)MFf%kTFflYRH8C`d66ZBEgmR66 zT!RE8XZiUU3K6mV&dRp@M-N+@G9`VuG1@ zY55K*K)rb&y?S{$22D&#$YH_A%D~*j#LoZ}=VEGNVq~~Nr175Voy)yy?7kdd`Hk2X@-G1br}dx>IsT!+LMfmgQ@TT*Z%l=zP6p zmFlNh@3@OM+jm{7t@(P+Xug2)(T!fa<0cv&y71ER(8QEFPDkt8-5lmwt4;;o+iEFy zpo4j-efLb^MCYxun>N2w$Unc(Wzj4BY=`;%+Tm*#1|Mow%AC8vKJY%b<3!%24_B;; z@#Kizd#}K8Bmc?d?925gB~1DzQ5B^!8C8wxU7v3`d`L+CGD+b&^D^7Ta_L7}q#c)@ z?0L5LmB%(#F^rH=TGD*-a!e50d-f`p@%)i39J_`)$HeMV3F)svTVPG1h0#Kvjj_`NaT ze%{HN($Edh4{k1harg*>=~RaT0Wa2js=Mb$E=}3vp0GdRaap%;=-r1URXfkCEX%6D zm!jknkdACWm@3&2x1kM|8td&Wc z>2X>+r)*m2eo0r(TQqdtWZ!Yt(rK=XH1b+7vIlA#(r1RAKt1~nV z?3tJu85kEgF}4{rF*X?p0h5}nFeBrC77hb8AjQPUXb=n%Q(*Bi@G|gVvNJJ?>1LFa6jv34h%DogouBxhU3}|)3%A?O23Pww z1hFlwTv9$j`52f{mKwN%Tqw_CXJBJswZLM5S(^zyFDIvG>Lz98={pDc=o=XrTIeUI z6zC-vXGvoewFZ1iwu08QZ_Z(afr|v$4oL7P67IR}GLw`p0(rETw zE@^x+D`E_)jh}F-vHW>IPs-w&-a`2cGu;oBrl|a#XRT4TQ%xgrB2TW)50?2g0gP84 zXRd!QddYRR3a3^YtG{aFsn~t14o0f4Gwy5pe!pZx=;pp3&&^NdtqODbwl}y@d7AB( bUq)TQX)daZRF5sQQSJHgK!Z(byP6{a`N8v7 literal 0 HcmV?d00001 diff --git a/SecurityTests/DigiNotar/diginotar.extended.validation-diginotar.root.ca-Cert.crt b/SecurityTests/DigiNotar/diginotar.extended.validation-diginotar.root.ca-Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..ca6362b9032cf7829fff35e405b6778d235b7b97 GIT binary patch literal 1542 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/DigiNotar/staatdernederlandenoverheidca-Cert.crt b/SecurityTests/DigiNotar/staatdernederlandenoverheidca-Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..e239a2d16f221ce54290201f784c908a32210220 GIT binary patch literal 1158 zcmXqLVrepHV$NE?%*4pV#KJIRR;2+i8>d#AN85K^Mn+av27^#TZUas>=1>+kVJ1Hx zLpcK(5Qj@xG`J)&u|y#ywMfA)6-eeJ=B1?O8LAnmfaIBlWwFXD1m)+KC^$PB$cghB z7#kQGSsEG{8Jd_ziSrto8kied0J#Rn7EuO~q*<$FpaHQ~5xceiWvN9OshKGttD6{= zkUh!B%D~*j$j<;2=VEGNWMo+9EAJA2cq4D7e%yk8n>%*~7#_*UnIUuRuguzoZ=Bfj zY#U8i*gm|+#S_Ss;BR(br=*}u>iQY0>mlcs{|_{4-(x1aT0nE*(c9<6f;L!B^#51I zCHLfH+xyF@*?TRHn(}tJPJN$pAs|Af`L}G}hR4c}JK8x@_wZg1{56wt?k%HPH>^%h z?P)Fwo8}QJd`#{yU)7G@6TfZ<={&Sy`*#2O4)^ebx)-7tG90d5U~es`w9%Tf>&PkY zC?Ae=mrZlmU$;*xPOb2m%@gw4plezB&X0#42uNql@(@W{LjK_ zzzn1e0zm=_EM5j425xLDKqiBMoq-J-hc+89y|6PeiWy{-loVL$>z9|8>lI{Y=0k&C zFE2;GAU`KFIWx6bKP5j`H@{35%&#=y0~yH=vV#Sf5ZMeG8$bfeER_c34I(RQU++m? zQX*W!@MhYB%O(eP_UHUq7`Y^zMk%uimy52$wfKn zzVb;dNi8mM4)W0hN*c(5bn>x?v50WDUE?oboU!qD3g_XDycial@Rzp8DG!*vfGLlW zp`ox$sebA1mb=9_#8y}2t@Py-h}zbbr7qHCm2b1xgey4W+iA91POsKe8)X{H+2Be z=y~@3?CRHv+Cn?*vurdBxsQkNoHw|5{ft-N)!CQK0+$HJ!43Q^i8N=6h{ujBd OTkBt6|96Sp0u}(J_M?&j literal 0 HcmV?d00001 diff --git a/SecurityTests/DigicertMalaysia/Digisign-Server-ID-Enrich-Entrust-Cert.crt b/SecurityTests/DigicertMalaysia/Digisign-Server-ID-Enrich-Entrust-Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..b3c29c58108e0b16caf2c282bfef58efc684b579 GIT binary patch literal 1234 zcmXqLVmW8f#Jp_*GZP~d6N?XDa+U!v8>d#AN85K^Mn+av27|^eh9U++Y|No7T*BP0 zc_l@q#U*-qsU?OE26iA(ZV~hH@^ZaYgp9s(KybW~fr*7eW?piBQGuR9Ql&ysYMP#c zMowmKW=XL^PG(|~o~EIyfilNH8JZgz8=FS~xuy`VDTr&3 zYRGNC2{M*Vn8`QNP})Ee#NiSaa>-23Oa_{*5S)^yr{I*4qGu>*zz=aJhl#1VnSq6_ zx1pMW3dBvaAoazW>3IslsYPX}MGBrS3c3m!u6ae7$r+jkO^iy&0m{hAz}&>h&j1wX zVrpV!WH{RS10EejG~Js zVm({Lb*A4dK6+z<=mIJ2uctSAw7Gnc?eID0=p^<2E6=@u4!0~7zO#i|WzBUvcqxDB zrW4_Inv3T=c-dN>_F~3zmAZWgA{CyxaDDUHb z(=&x(B}HHKEyy5$G%fJ(yM|MlmI*R#2i(fuI+mCD7Ps>H6<72AX}#oN~_6wWflnou?CUQCyf^c8}{Ak+{v-n@aIAmPO+T@$SDh$Re>pskzu;edoL@` zHAR066tcHyMlU})m1V+DqpOEnv+gl3H2>Mjupw$qXx(jR)Bh(Ke+2G3qju^<){-M3 zc4~6Zc^03Yo<8O7GN;!uXZtNHvyCei*(!fExroj@b8x%mWw)f7O$D#>&nc|3lidEY zq-oBUrQW`Y4CYVTFMSfRN~zhgvO4j>WTod<=i9kIGb>vVe1n16ihrx|ziFo~Uuv?_ zyL;W^;gjW=XJlT^^m=}(!1X#eJKwBQ=?nUk^1m%%KfG7Qds)l2+7+`_URtjCkvlw7 zZhE-d8*S$`S6rJ}8D2jA;O4;o>($1<;>j{g?*d#AN85K^Mn+av27^*VZUas>=1>+kVW!Yv zLkR;h5Qj^c-#x@t!8yOEAipTFBr`wHP~AWkB*QH%2bQT!N-YX0DlINi2+q$b1*s_3 zQSi)5)-zN#Py{Jt7M4O&=$@0Gl$fIsl%HQ>AScdiU~XV;Xl`g~Xl`N=CC+PT1m&8U znnW2SBRR`A(oot!65=c&m(29c$#6 zLEIn>QeT{zo~IC;T2z)=q~PhIpy8TVl$o5NY0x+yIW!nq8JHV;84MabnHn1z)~-nL z_H94j61nsD1h)mtIuCsOclB0ClR589ZC5p}7hxOfPp$aU=ib8Dr1^Mr*4Bxie@|`Q zQ?w%G1((B|qhAWwRaa-RznUQ8-`lx<%IZyQSD3P@XUIqHv^pE|OX2<|Ev}b4?q*In zpn2Kv!t}RkXO2pGveo~J)2XR$l{Rv^Up-ZoiJ6gsad8u4g+UWziGdK%H?qQvjQ?3U z4A_7a6C;B`3`k6YCDb6;z=Mrbn~jl$aibkj+}gmBjRVMKWo2h#6w}QpDJihh*G~pT zSP3Y?^zw7_GK+wbpqHGVt6!8_kYAixl3!G*mzdEr*a=n7mq@2uT zU5HmfK1@!})J@9F({~Q?(Kj+Mw9rpZDbPzU$}x}y8Nj2e@jxb#K19nlJVF zp_gWqQj2eZzBkXO|E-6rL$A0r?aN)0-nVCq{G>U74N@ZC@>VByaIclA|Lz?Scr8_W ynR}sV+=jx>rXrur_a>jX`eAaEN&F4l7qQ=u${l!mUcOCbr44)9*@KtNk|P0F+&9Jm literal 0 HcmV?d00001 diff --git a/SecurityTests/DigicertMalaysia/Invalid-webmail.jaring.my.crt b/SecurityTests/DigicertMalaysia/Invalid-webmail.jaring.my.crt new file mode 100644 index 0000000000000000000000000000000000000000..c9aeb09f7db67b21f00d625f32c4f1c74b518483 GIT binary patch literal 849 zcmXqLV)iv?VlrL8%*4pV#O$8^*MOIeQ>)FR?K>|cBP%O|L8>9Q0Vf-CC<~h~lW(M< zw1Fgu!zC=_l9`^FoLW?(5S)^yr{I*4qGu>*zz>q-7UnQ9H8(S`(DgP{Gf)8uF$>Fr z)E8%_=P3lI7L}zIDR{al=qhNq<`rcoXJ{J8iSrs78UXben44IbSVjT4#z?p9C_<vBlV!hBGEO*p zf9B{s*7G&!XbMBs5(dqEzn`7hKIvXi;SXhXu|EIEBZq@@Hq{l~+}N>hsWPK(bn@L^ zPq}_3W=00a#kB_227*9qW%*dRSU4QBm(GiLs=3|31tg@vVryV+V9Cas(Co#?XkcKV z$Ht+}28>g7CPp!(jFOT9D}DX)@^ZZtXhiBI=jQ?gK|i^mSTCa_7wjKdWfmR-t_BVt zzcZ>D%$kh`+#sX*Sy-5vSUwYpo}f7x!st^Dj> z!EZNho)@0;F6dL#nJC;JnSS;p|AXq_kItfPD`k5^gF^Uc?0>joyVK40Z5!BrDW@7; z{P}aPZDesl_pIah)uot&Le;PP1TuEjCJG*&BC}?}hc@=>JPONW!dGT4&-r3i&so3v zPxkv;PeTm39z9uRvn{#M%XwAyiy7-T@=ed4?r0FcYli5_JJ;U+ljP+8)P4Ku8m*d_ ry89;1P+k&ws9^K!%U(Bba7{d{I5lj)SnH7u#yj|~ZBT05y#E3KHu4&} literal 0 HcmV?d00001 diff --git a/SecurityTests/DigicertMalaysia/Invalid-www.cybersecurity.my.crt b/SecurityTests/DigicertMalaysia/Invalid-www.cybersecurity.my.crt new file mode 100644 index 0000000000000000000000000000000000000000..e8be772accdf19cb4902015293ae3cded3dc8d8e GIT binary patch literal 786 zcmXqLV&*ewVk%$2%*4pV#H?vG$$*!QQ>)FR?K>|cBP%O|L9!vY0Vf-CC<~h~lW(M< zw1Fgu!zC=_l9`^FoLW?(5S)^yr{I*4qGu>*zz>q-7UnQ9H8(S`(DgP{F;D^tF$+tB z)E8%_=P3lI7L}zIDR{alXt?GTWhQ568pw(B8X6cF85tQ^7+M$_Mgh4-NL+))<%aSG zvJi{KoGX)3i-J>=ON%l~DiwSaa}q0yGZPK@fi4GI&KB$$671??C~F`Mv09|Oyj(9C zq^lUJOE0(5P~1QiB+V|&2Xs)Tf_G|eQes|uVxFOfff_srI2pwxiz|y0Q*tx&959T4 z`j-lQ z#^SpV1Y?y}$UQdpv*v8Ff19xIErZ-VhZhdBt6F}}oBs7c&F35M&$6(xChh(E^wYsZ zb&IHQbf{z8&v+(gMh3>kja>$f?FNECzsvHmaItXso~nG<$wJUW1(Q9Fh|j1#U6E|Bb zG4Px4QJA+vJwD4d^iimiZ_i1mNgDoSB}NnU`+R#HfTEDvYcQ%uS5^3_x)% zrY1&4hOMU?euOso%j{8?^UbQ$b$xu%+$e7M6VHeQ#)P(24jqeERj%L;ooaJtb^qaY zB_;(-doD%yEJ!vwIyZ8mPyfF=Hw`M4oC>Jk^jr|6Ez@U`nXJq`(!otkN-T+QIvcfD(1`Oa( zmgQp+V-ZOXIP!1P6)p?89ZBU2Vhr}ktdTuvU;)x8&thnxZ=kzCdx2(~dPYe}ft9{~ zd3m{BA}F!xCFkergIURm`k4iww4;|?lw%+X(y0Klliz^XfE${AlT%nZkfRNln1Rv8 z$S{Aw;)fMaJ&$;_$MB0E@aDF^JAJ{LiCf;N)_i+(p?P+N%-+3zd(W?7ePODueY{(@ z>A@Wr2{WD0#`l4{=frKCyDM&q=IXx0gT~7`RGu&JaD917PW!-07G0BBp|e&Una0&T z?~;ACZQEwvZ$4W$@s<{R+PY}(iAdq6e)}UQKU{ZO?s%bL+7XMcC;Qw&ta>7+awOZR zo88JPN!H6gc>Le}PX;Q<3sqImg>5(7@kZ_7<819fslNJl?T z-{bHLyT$ikXL2}Dv-QN$X?yd2>b!_iJbYCtCAfX#-PH@{y_E3knAN;r_fW#c$$NKY Rc5XCjzmYWI%_WiD#sF=GeT4u3 literal 0 HcmV?d00001 diff --git a/SecurityTests/OTATasking-certs/task_signing.crt b/SecurityTests/OTATasking-certs/task_signing.crt new file mode 100644 index 0000000000000000000000000000000000000000..223fa7f1da40cc8f22cbb3b75492acabc30f1978 GIT binary patch literal 1000 zcmXqLVt!)K#B^o>GZP~d6Qhm+FB_*;n@8JsUPeY%RtAGgLv903Hs(+kHesgFU_)U8 zK@f*an9H%CASYG9GcQ@sP|ZLEB*-l+3lVfqEh@=O%S=uz$;{7Fa4ap!$S=w)sWj9z z&<3ev7FL0%%M8fK&r4Onq1-@DoY&CMz}(Qp$jI2p*f0vnwLsz;#1i2&IRhDp(?p?G z`Uflchd3&PBo=39=A|1-8i+%jBmfgt2+mB;14wk;=~i``UOMiesZe88p0+Sa$JI!$Ic`q(_Mk~Srk?54ZYs-ty83Ku+m!=ltu%Gj|Vi>^peV*8p0_m%}m2Nf|J2$^u zX|(rQk&w8$lwqN++5b4jO}m>C%u7dK8aXzVxO0|ufjKO^IR78YhE_6Bf@krifPGGH)}1xfL- zh_Q&=o__gJtl^=w|Es4eKWmOi(Yl!b(!c^FEze?Tpl_hNKzo5^n|ek`Nr9EVetCJh zULq)s=_Tjq>VsLyiTarZpd_Q0T$E!V3DT(mvXkF{*MJ+EY?D)1Igz6cn1+GT#>ik| zv!Lbi=T9H*y?vc4blKl)f9TV@NbK3PdvPV{QKw{8Cm3wnZ?w#J zld|)4?#Y`jZ$9{7*Y)RR_PgDMw1sZUUsx)&=l1*K-t04SI?gpMXgSyXzhIlS@1cVn z(?8rU=T2SG6Y<=2>h7I8C6_3j*SPpQ=4V!=%C!@%n-;IX95l)8>GZpY7S}$i;VYW5 zVX4|r+oXWj4HZo38`E7614i*h|4YmyCLNO6A5ZL{(gyP|$moc$5b22Aj{%1#tUd+PU$;6Rf%-Yb& zM8w3%&e(*H59+Uzqluvnlv~!cige@_15D4U`db%64T-o5OrRlitdN~H5O31Xh7F}n zzUTRF?U8tbWcs?ac8UPectVdnJUC5;{Gq6d&y%6YVs^<*z8W~Q71GR1N9xSG=`CczH7s{a zS2=Kboj__=37kfrc|V_84xpxFVb0Nl7^GkV0Oac`mIQ;uBFZ9zj?oodoLWDLI z;r-TEROY=y8IMbaL-%q*&S0Mjq&FJc5RxpPnt>LH92J$|$Q;wqBD z)^5+uNgD(iLfS2rLC^fI3<%~xZ~+~a+P*aVj;V@uqgX_EX?HY@T`E8t_Gt<9c z|7(x+KgNyi|6<&(v!(40*%170-%n1Ukia;QMvN$-OS_J&?B6dCiJSgV6pKeoy zm5@+-kXEs&H2?T(W(JTtvgV#h(sK9j?{@ma$^6FqfwS)IU*5X%|JuK8MmG$u^55R% z-p0L_-sEYx9)zCm!twKk1CI?p;`c_ukTEhDdvP6%4Hb!w9yx)qF`0~bVErW?96H@^ zjDLLr-$@NUUp>ve!OOkv=}H^ydvY?NZ)Q>60|(#+T_RsS4SomCEy{tqG&fzy(v$_3 zHO|9?ak63E7C&EG{Dr-K0g+RtLr#+?YU)+UxkdId7c!3qE@}4{J|R zKpm1up|KwsTjSWW;;L8a zZEt_blJK;Nh{6l<$EwU{G4l(itsA__|Dzf>N3KLm9u<^4W9SIPudn zwTGE3?Q1B0PTy;3ldv~JuYb8}d4H3{pon8K&U5w&#<7>gWH_Me03myU5wZ*lJK43zlhSl!G5v zg7vvnQDG&V$ZceSuV`OZMO;y}oXmp>!e2viuyB5_g}^?oXN5bFvDI8AB3k~gz`u@^ zXg3~>yOZN0S@wP^tJ1(^@5Fj$;Xt5m;hz)& zv$4ZX>J>@%ttcW8?$Hw z#%Z|Ub(HuME=%D_S9J;|ojb&rn~pUEd8k}fL-5bhmyC+xZ3&Eu^PKjJrqdkGfW0(; zvRl$MYdSa8SRBc2qSnx=+_BuJs;!N*bwAo|bB3VH>QMfj9AA#DDf-B^cAR}MRYRum zgF%VgKqZXD50ja*IDw3fr#mK9Yy!z*mqF_f=PIa3Z-#{YFKtHG1) zfmc(nLpzH!txifZ(TE^LwEJ^Gl#UA?*ojkBthyTArS?aMYK?OQOw%h(AMy{g9HGu{*8re>6?t$m3n?sf&8%rj$DY8$As`dWKyX#EW` zGdo+Ed9WpRm(0iX_JJbBWw6TuDO*q5DR>#RdOS90ds!l6qBMR8C_ySYfNKlHIaV50 zf%puwft;DoOh8g9kaUt2F#PSgvQi>Z)+aGkB4^hxI9?a3+e^r$xC~*Iub0tRUSz9V zmeeTIk8ypuPFTRkwZZJehr}O0)9rb4<0y2fqGcb}Ni$HJA}}l_RY+#$%V{RVV!y6w zUGvvz2d(wQgyUi^?k^n?FVCNw)#;Z{jL#ezEf*1cYtUuZvT=FZM;tJ$a!o1~)*wG6 znF&AF9!S|Wej7%1RS7zDGmS=yw+;VGOO$pY5~iFCoonqmW6*YRY&U8vOp50)i1(nX zz8($FpzF^RomKAPyl)vib^6z;B%3{~Lk|J$9CikB=$NH>{A?fRY|96uaqNBcvw{)% z&J4{jnMnb_UfI=|%{wFMb01JSo#XTdLe}kz*4lCSfLXaIOuP&K0}u9($3G=#$D>ZW` z$l97b*&D1|o2XhWw zBG1gnU>RhkkrF*!@QkmvhwX4!mNf+J2r5o#(PS*mPK;j5@lXprl7g1;s-+HBl-liz z`ZaOSvF}%uy*16?%V)oG@x0ZytINB`TG@+5X5X35`{(*;G?X9H_v7nRpKj5S zH*?ad7Yp3?_xVwt9zU0!U$r*VBF4^T_qUBM_1q=eu2=Wl#6xG=DP8ERH+^rkFLro- zzsKRutuNHJa9v@IbgI@WV~Whs41q1e`fGV1cQI#gq?>NLehO!oeR5fB+;pk`&?ALf zQ6|kiW+0=E{=`}j7xr3iWN*%;V}l|yx{ynwL{k8hVHl_~S5Uqziu((F+2xQF6eZ*~ zFlS{F1s%(t#n<7-LvNoG17?J=QYH|1r$+FkxW8))ZZ*18|4?5sOW-%!7qjaO&3&<> z5=+5!0a&!ZS{)k3qOYvK|3iq7jmK7jnW$!Js3EasW~As|fEtfXUj!fQ9<*YFQv(0P z6lX-PiVN}a-9~`%+G`w(uQ5V%Et*C0V{);>0M-_#chqsek**RpIXEH=>NWK(CRYPO%lOC0D*8ZZ6zu>9ZII0!~z|e^H6gKHoVxQly63K1pGJ|oYZ$+?q z3p97Rb(_7I4rUc=HsM7K;?c{$vtk`o!pU}e5MX#OZl$D`zP>9v$0E=6X z5-{YJ4EdB>EVfu-3<>8T!FUvu5HC5`$B1RzD)y45N9HT`afTWv3`g&iMjs?@obajj zlC$C-kbd1&L%S_aas8^*cAzM;SenTtqKHOQw6el;Wx#hfN!{vyZZ$|JlaU_*-&N}haDV~z_ zRi19{)XazmX_57>gPmeV$@KIah&=1#oht_4T?b~z_}_N;E*PXj92h9Cao#Zm2p>rN znK;04EhUjLyigSM1hrvE$cn6FeZl1s?E=_%<4ELOO#&QYNl@gS=w^0y@ucWF6IhON zFe>r2h@R?ww=0QR)7%#nhXVVe4Q^*#JTBTLT}P$?KB4AMInmI7op6C5^m|0-p?<$) z!IUfCSV4Y18#PWkhQu`3_QGqU!44 zWh(r0hd?9AuL)qX{ReOoDhli7!52Nu zuO8Noe8~xvxlkpU51cy_Qp^$HaEG@`{_BWzsqM2@O!WMj1JJN8UghjwEBQBFjys-5 z>@klodd7B-Rs@4|R*df8#^#iyXi_2u>rT@nmLMP_8a_j8ntds>?Eb8KI}b$1mVkqL zq*AB>Q4}LHX)0biybfb&8YG@i2_1y8c}}IQ+!<=*tP_qM;}n;};i)#SHmQ&;b6f)l zS6F0k+(ni13xuR=mbK+>nwm%ig~tx&`#4A58{Z9drfY2GZZlkf1v=7qNfen-Qk~B& z^^X<_y^kJ8o($t*D)ZgCdC86$|v&C}v4do728f#T)PDg{}}8brgRm zgB|kG#;MbE)@UzwT^;Obc6WdxxAGl!B}H<)S^?O{?q%Q(Uv-@Oq)bKiD=w6iBpyi= zhvPo089Q3ixPbC?v2WC`r6nR`wItp1K2iOD^)(PMuxKn zqD%V%0ex4hqq;u~$Ip#wPDvME#&xfk0bL_sHB`c{C^DioNqnQx3ERNr1j4KkWRd6) zC1+bb@R3o72LzMwpWDGkgH!u!KI=qxcWpoY*WXPdXo?D22x$-Et%52{HP9w61OPI| zD>y$R3$96%Hyt}j=~k;1F0@Hc=!zpx*jbMW_VL!8|K7%Fnn+$dQrnI;O5+L=7VY8N zu-0R6r4p)WoITS|8&VX7YRD|7Z>xYQ6xr)js6J_|m;DW9%YteEbS>PPiP8Db0uPG^UCz zHvNpfJ4kuM>R~873(21+B6oEVTcXUZ)EILgx}>i5OMs_j7)ySo#uf1o1$z*SoA2K;nlRdld7E>9)48Wp=Lp${kIX<0~>#j zMZs=pN<^%-=4RPNKN(4*hT(WcXiU*gN8bZB+aVUf##`GLJ*U7(H%rHoui~UjvaB3F z;Eu@gS@hw2D6jdv67{cIPNnwY$0(w6PKt}g`s6v8R84E^jcKey+%s!u$$%jdL=k_) zzx*Czob^WkjZ!>v%zgmvTB#g*1Av z6Z{@EsVAGl>+2o*#`!(P{GEES@P+8OALf0x^D10?=*d{j#ULN zR;fYwI4bUl4plh6@J@$lQ}Z6D(55BUjt9W&Mb>f+Si4-}qTs>=M@9Ou=tp(Y2S4|R zzM=RW)3pumRBvdXiPiZMflIYx1cB!_6MpSOh!dE7l0=d$2OI)J5+C3~7P3;K*RAAe zHVPa=;7z^6e#g9PVjy2IlfarbGV&x@p<^OhY@7W`&CYW>w^GxyHafv6xl6_d_b7KS z?e->TjWIwh?O4p$0S?xTIBVa9j99Odjg2U7)$LUP!)O5{D;&v%u{xqe(N#>X1c4;E zUu92l670nab2DsU6YBEfn)sy6@B+%kT$`CbB?e6gy03yD72MwmK>20My*cyD6A}M0 zC_#OKXs!oRXzZ2IZ#L(=zd_AuYAaE8Qcsd9B`T5IK*>E#9;9vVpk;-Qg2Cn3S>ze3!P zZbqNjO4!>JI&B&M-nz22aA7WozxjyFU6_JQsZOCP&uYgCadho zEQ;P)8p8pCh1#ICjqz)7yKlQtfvFJH`RDS5!3v0(%3CjcNizm5Z`N`z zRJnJ^QFsy&EPaA2#u)U-Av5WDvo%o4{PUR3zJsZp;rlE$-=miGdH%BLiqnzIY$!S^ z<(!;QC->@C)$m7Le^}`f`qyQ!4MLx99WEqBfPJ&&gO)oHTJb$?QpwvS|D$D4CaTk| zj!S03nh$i3en)mh!yARVm3A4in+g80eY_lM=lr&K0#!m4`37KPe9ZHtp<5!1^^`L!u1SMC?A zT?737ztL#_im!h)8Z!$6!~gbs85#dWq%r;*Is8un!?KoiLT|3eQ(@7{U?Vp)HW*7o6`ixU>hrQN8#%|<=fiCOo<95w zLIJPW&-d{uKAdl9<;mUqZ0hBvG>e-R!~PQPjt}?O+a35_Xe+-DXQmI&0A>gxPWJD| z%i`qs_3@%LXBwP3U3IG|&P)mRXCtOqtl0@;fTTKIA$MRg^UqrcS&r*!=nV_XdCOHz z;r2Y7Lwo0gYRfI0}LS)J-@DP>xpI^}g8_osaMKrYSf%dBHZIfWVm; z$L6QolUXG9%`Dpi=e^X=xgt&TcrB2|8VVqiF z-z{bi7PE-=Q;)P5>5a>IY5T7^a&sgqK$(IH!6TjY1RNzOts+Yv;Pu8GgBUw@p;~(M zM^cQtzMBnU(eF8$L$JjtwEt`Yjl#+xB9>ubEYTy(ycK)mc6K??$DkoX0`{lW!f*)t zdftHZdAh9Q4fx|7*am@PuAxur_uY8x1_*?t1P)j%rW1M_&@&mYStA@%Y2w!(&QVBx z1_kAjjy7!6SH!OiDl#M`n_vC;l8dUfMeh~GbdrB@aWPpJBzPZBwl}(R^1{rPxk`Om zjTPLa$EB2;b3M$kSTrqY;~+vNooX^~U|csI9l^!>G_#RGYe92&Se%e1LS$qC7_H3P z57YUSjDr;D`#`}FbrSBIV*68z$b?soFF#%+e zhHA}g(SpE9@3cI>3Hkx{Cd}Cep5={7=DrR@oJbMl_b`EKO!X3u@yNw@KYkqAKt+3k z8N(cYkDwrlO7ah$7?hhC%dhF`z<^0ge=8Vj48p)&kj;05m0(m7PP8+Opp>KV$E65b zg$Xx3N1tl28tbt`g3v*xRuvD(QsK-WQ|}fMc<}GOb_fnVeFPLu?Ox-p(Li|TbqqdZ z+K+H01&m0Oz#Dc>Y_9n$rmC9tM*+F(K&i|G{pc=n<5({@XsKQ+QbeR_*m*VCTIbKT zR<2^46xK7V>M{aY4eQfznk~B#?OIzKVRzh(my-6Jm%%*%D#A&q&Jrqc<-}Zfg>kAC zE*1u@B`kFz#mw#zvL*cF~J>NgsgYfo*Hw9dHv$GaPlu2IyvltVXJck8e@D^ZRd{ zSmY(1g~DN@z%ITtR+P7#7D?TSYrTqMd(w-~#d~6pP$SGJ(Ps#DQzt}IIa&pL{Eq4t z1Ue@w9iKY+`-tVB8SwCDh@bYO9r#E91SCv2B;{ls+U5IzlG~AEY!{)^{_zLwYVcLE2Cq_+i-wPWS_lTw*I_%P=v3%51i?zUNcGkb`r8dl97OTbAjA2? z(_k%}FP9O8G1ic)@W?tDc^dbpeEIa#kI7SCc0f!{7Q78!y$si)kOZZrhw2D9v4?6O znQiGaGK!VvS>^Y6`Ox82Hf5+n12E-dn zn)FS>G?y)goP!@djpB?_PXhDyJq6I>r3M(DoE_2K(Tc$r7pe*|s?!IBLvhB?f!NyA2HVD_71GUS2E%SMI|GN> z#4yzwBxCEbd-ZrokWs1v$k2|vON>dCZzn%U_|b&q5T2DAX%(DrF?Xts^o2aRX5sV9 z%EXwGYrEczWYz7bxu0(siY4gGB*wq4&BeXZag=puu~!q?+eaYeByD5? zkl=Yy0-){1M|-YK6+$P~qmSFkCdh9KCsZABM$GeU?v~#T>KCOvB>OoYceeMSA~~Zr z0gLZsVYI!xQ+T7q(YW>%ap#f6uQM%%X+$qGOm;S1u!)p47iy^?b5y*AzSe(EKT?Qn z57t%s@}l>;?h~ZyDut*NQQ$+_N>=r(PV!zb>G`5z!)dy_JU+75NHlAc`!Bv1A8F^v zW*C}Ok`gh3@9~D5zpKEZc4SId6Z@k8GAA-NVplfk8eI_Uwdy1AMw&!Gf_T4s1e8wk zVAF&D_OT$FkfLuI)g7nn^YLys} zls}5M5D)C-qF$HilU}5E(6#I*xnwUkQ0ZCXsU&VaNttjx6rpd|n~qyi>aFCIP<}Dm zeQdg8o%*c@F)apWjC;?Qpqb&^zNJsA3h`Pyl~yv(lYUmuPG&hspc?XR8qkNI7Hdnn#co7;oT z>G*%&Z{YcLev)S@CTD%SJwF^vyZx;K)$ZPpreTqiYucb!w z?LlXev~$>O?$hl9H>*mm?qL||tUZPwJ-JV*rh+><$J9? zC?_8sscUw1!jlFeukSr_$N!3e-B!9UK2q1JgZ1xpSBe=NyCL0i5*%??xiGc!jn_Zf`0gcRz?4A!p`3yqYJw z%F(R`ezSRCt5%*rAdB8+3dOVV{OZ(82=gN=Y&AiI3MiU`7f7KGa1eE*qr|d;t=Aea zW?kstf~OJIo9}Rhv_e%rL#b7$#u}GcVmTld?Z!&>W$j~&{^UzdW_vXxsoWF|)Kach zuxsl+osMTkEVq}WVR|xe7$vGAi58XEB4A@X33r;Rs?7+Mm$M-05U^enbs`KeLzQ!Z zQLnyqw6MC0ZsPS1T~tbU~A3MO}}h@mf6x~G@oTLn|N3CBPyyqy++al1|J z#fOk9pW%=F)^iB6$gFQ@iAWE=Y-k$itluw2O-PI8c4>G6-VyTxtqhemxV4RsPzF8e z6IL*H9G{cqk?x>obCjlYn63ytm2|6$s`qT2n0mqCPn>V4 zA=u20>PcTAHAq-HI|1t4hHq)P5vi+Di>k4t1e?}Ikfs^8P@!b|s@+LnPkc776*GQO zHjGa9rK+iO+Mnu}dC!|%9Wo26Yw1Wtfi-|X#t8ybE?m>uki|Gm#5HAt_OGo%C7FQC zI#3`**jVsujwgvWYNokolaRI40USi(8V$$^>lcN8Szvxvf!T3UL}C;ETHzEZ@q_HR zZ_}LIeO?SvOlPAeG9f8GxPzEaA;7stwwvu=S~j2TKzFeM8JbPZ-f(VjO}MeV9)**c zfVqlEG9QsWG*I=}9l|m2U%B122LCi@t^M0xL$Ug9n>brNKH#s<3e{Aof2ksl zwrxf}ULaMJh;VSZH-R`|Cn(zTRwqs^{__otwi|5p5Krp5_ZHfbT%@bM+yi#T3zTV= z6A85^>)DbEH8H{mQqoN_HNPP|b!6sg{wJp|RD|o6%PjOyKFxp^ELM26;sP!4Vis1e zE-RM)_N41kT8WzF&3D@OER&uIn}XsY3`n(bc+Q32y{^u8Z~cyORVf%Ft9szc2IG&4 z%Eq(a_fU$psViGCF!ushas!_T7^AWghL&`FBz*Cxa%Wv-{~7CsSzrit!?af0=}(VH z-Kzq!&ZH#b<3*~!(+5Y_gNJgac}=A$fK_?6%7b;)pAnHKF@3SG%R99Q1NAz|a zl+O6bgEy?REHymlReHz-ySthsS;;4bPI{?L6agosm#oG+u0$LsNfp%n$p4*O}U16_U=IiS?i(y2`&9cU8bqF z>DdhCwJoo_z5aM)Je=Esjl0(lza9yl8nVzw=F;bH7$Rw!rByr7^9;Zu#Vd;1bb)Oh zGMf*Fq;AAS078Pgi^{Ls0~bik2SKLEJCMS~z_3Wqffs3VES|FRDLUYjBrH|&uQDw< z9J#+ygoL&SkFPZGNO`kWhIeba4w4sXJ2*UJ=!*VqA3A)Uc8yqAnnBppoq zISd!gp2mEzW`F_go!<$)Wg;Z`h)Ho%;-K)#L)Qwu$8itYwY75479a^Cn2W??{U*SX zxG~M_nkCs~UBf{Pd`=KtxSCuW{kv-H5t`PtAjcBXy{-TL`tI#5P6Z?E8 z&!AU}Pq>Q{i6 zjr8-?{e&Yi&T4p~K}T6gQ3P*=-gz{e0_Dc`Q-kg%Mr=jsW^!SAQIN@=!q@0hjjH~E zxteFO9b)2eIx}x^VJ$ffl*>!#;bo~~GAlc-RjA1mqeRQ1r>tq0s>MJFpqmutwgFK= z3)>@D)O-6S!<{SHi5S&Lt*Jv~li>;iJuW#su7fm+#?H*TQ=by@?EhUd}>bbRKy@lU#?H1Bl zrf7fuVLH)DsnZBKhBC5Y|0q>_G^`l6BqUJsdL!nie!V(A0shh$B3^xs8E`8v5@_@o z=V6g-++CXvB3q4!Lr+pi>yO`HzIP6TK60z#JJh6o+`dYg3qWEHymM*@{MV9L2lZQ6!1olQ*f$dN9HgyAiqw+*?IHJq&Gql&9JsR6LKf&pDeHsZ5qFty@k3c~|wsO+=-Qq3`I-LDK zMz6__n$xW%Av%3w-*f8K5Gw_rKDKoNXttd5qnkb2ihl)mg$|$++WqJA0-c`k)BY%G z7w9y{S)kLHHRv;5q0FE@FU3-ZbQUGZOBU)$MVP+!`_zu^37;S}Mv6|JiIC0dPjg?X zZCHEzjx9Uxv=OslrsI_4LCW(?maaO*gbe9VjFqJA(8vlf!u+JD_FDRINEumlSbmNZh#o0_%g?Sp!Tkl zj>71|?diNfB*3|$x@Y^a#yax?IGk&wIRgP(ZuTcBK}M){i!@sxB&WYOH|aDHgkcSk zEM^ZY1P4k67~P7bnu4GL6Nwh_6+iB?WR4Ck!Go^$)3#J#Asyq$ejXT@3Rf3FO>zw< z=O4_)6o)o4f78i5sn+f~R8*-q^$Q)S4?gSKY%Y6fAm?W01a9tEWIC*O0y~A0tm*78 zW-w>CVn`Oi>;}NB_d#|tW(Lj(bZ(*?JN{1a7=3!3S##ducJVJrf5^BFF8Ghermlr% z2S%iMlu8YfQG%lAl5jqbPmg_>;_ytuMGOMpvH0x_w6YLbYncq7RqoBLzE(FDM7|45 z505mHwp#7_j$yRt2X(Nn{`~-#0tnWG-0omXH6pB)TJ|{PhrVq z_7<+b2u7{HY}uOow>DCKvAs08os!ZIic%k#0K~rS?cN18_{it=X=i~#AoAmyhx^{K z-~y-vryO{`2?bc@>}jX&Kgdggpk67#1+kY~!d2{X=rO(hVZ=8+F ztn}&G*K@TW7>xu6IAqwQoijMLPz zEr$@jtOG(7sHW-U4MB?AOcmRrvOv6R`v69>k}yS=98-eG?+0}m+=x>) zDGJdaLmUKjKe$kD9&fFF(-85^!DT#INz?c&6wCPg>M)hmR8Q`M&A{j<1GNbKz`=IA zTsrIcXPXiH8~VSJvSH3DWkAeIeU2F#Oye;cKJ&I&m#O8 z!wyYdc#2dA_GaIpCDB@-90n80LNl9+S2NpG8q@1mg~qvn6CW|n*fSo{c9jbY7M57D zgJk?9yh`Uh3HH79_{{_v$K5ft?sroA?LzB?(d+%z*Hir_@}dAXM(P{6ZYm?@*I|5= z8mClxh*0mowX+oe#;5BGz5j2N{C}rL|5wkNnT?t8|EN*+|5T&@mZ<(GH9C#6X-U(5 zzpc+W3+>`$(`BhA z+S8rI?Av4hr)uh0akJ6oytmOYl|p{$`C#V5rT)ZvzrNnSmd?Y!RPK@0`(Qu26QpB6 zUbXEERd16t&?`jpLFFz(pCC>kZZ9X^Lk?k)1&EE;**@Lp87jBb6)g2G)y~(=?epdC zFa&6%TE2zMf0o2eSR>`vcUZpzPU{c`8i|rZ`1Q*LGzq50sJ$q;8^8ro{fSF>5bN7` zBx~>4Gb3G+3E1d65xbU*BxMAv7ITMruF?le80H$r1iq@N04pw%~Kq%eYpk!KiwJamON-+{Cb2w2+S-Om{Z zB23RZa#TP72iYbU5jfd@c7L+yc0~0MfLKArDsn+PR2W%#2#6#bl(u&O*syNeAk5R8 zGRH)&1^RLrq#q5C(|xYs-OHR+&p+&3wZO3jBmC%&8iYVtCCs5RhaTNZTeMT%4_YxU zS&(t1i3h>Ji!k@RxR@?OR+9vA9uPf2lhK0=N-xy7!9$TFVSkyQR(pMaxS^jEn|Y4( zRxEJilemwLH`jy6vVm1C|$z5j|#S4IbHZq>g1bno(9#!>aBC;;qB+NG`*x6hv3 z_%ShAc*{?f{#qfHv7g$VmzbcQC zt|DS;{xE7z-$czVhBo&cPhM{4Elsi!;rCd|SfoI?wAkFSDQS>l=BBHOM<(NZu^9S1 z8#Fr-2bf@I_?nl-M}us09h1*sd6jf7S-*{`#Svw@*k$9~m~_m%=v0Pzdtg3X5sg-J z8FIgZ4~hCpLkH-NoVz_#1ffG5A{GEv0pJht5!Ok!uBcXCLmNB`Xkw;B<6d80U zx+H{abGDR{Os0Y{B{l;dD1VP&N&+I4ZZW2Q_ePLTo!5?G zbC9{o1t}(hv;)Obld#L3;!hlI7BUz>YO^B}Ng;;>SKEvOSzx+5g8yExdZ3_q8P|-Z zYDrznNd3Yh(QNR-70!hqh;K6y$WByd6?3?dv7Ex7N^}7_~4r@S^(W%Q`iZ`H`kO|9SI77P5R9EX{YQ6 z5r8zzEZ_|H*kqiG-)I80RE}TvCWL~708aD|C;^xeW!!z=0*qlOuAKapS9@C=A`|*x zr9Xq}B-Wb^ffFcBbVmK$XyPkXy#sMq2u~piyrs>oRAbdyXfbtZk=GUt42+Yf80m%1aTMts!hSzW`;ew6 z%ZNeDCQT)fqiZh0xCJr;J%J;S6*~zE`k;k(BHl^%TCe!>H2w2d5}J(&-Ja@G<_;lu=3U<3sW*cg&%O_w=;^VOL7@sQy-{Xu;OD6QB)wk%5| zxcF5bfe?37FZ2i>{F-Z$@u6lw)7**H><5Z_o2WT62iq99zjU1Yba|hAA8fLxX@7yI z_|y+w9;La3&la6*^@fRND7Tl_dlP4-2Z0W@02*hP+bM;n+8Kp%Oa3Z5h5b$P^aeeh z@^8j5d@0Y$Bo@iaBzV%y$}Akrk~U2F#hM8Qo`Gff)R~b*{4*1c_`xzGJKtY4@BUAK zl<3m_mYve1Q;tk_*#h{T@&E>}t@L_^AL&N6#TJ^RiS!%#$A4+@u)9TI|O8ssxB|nMC zY$uo6gpf+5y+nC{>vH16Y;kQ)RcV3bB}1`VJ)~1n>CLenO6fvx@C9Hak%UbWH@Q;J z$vZOzPFTi4fu0TA8M{*!cQW=1-^L zmI~`FqHS4r)55jo`OeCoHOaC_t#vmjT~Kr#fLsGy=%&*+N>9PCj=5R1%CRc;qjk4i zWQFOjN*Co%dF8^mMswXSL9eD)rQl$6Iw{4juyQrorjfH?L_M1d#-n+SMwRGDbzQB zZg-0*qfaEuGoiMncR1;b_bYxpI^U{fUZPiJxLb4h#iHxlRruHMco0@;LyC`TTsz2g zSb*O-5!gFN_|itJH8L@Sn;$CHxWof*5`#kIAF8vw=xLc~e-CK{0bmPo@(np_A4u-G4}w!}1q`B@JcZZ+GoT9_bq>MIyEQtMoUs-DdNk9G?A zJyU44+9JBPogXkx9%t+F5NntgpJY(`x%bq;2k7Bi-?q=&A}Y@dXEdag4MH&`VshbjW|HiVq-(n_00yVBwSJI#|8pGLELyy(;j>C}9 zBDtbI0~@+aM|!?yJ%e|0k~vU{vvO9gH&z=G z7>T#24*ydPFN-#^wx|xoD3Sc3syq?3O~`xOpaNo+vI2Pq!jV%E3FuP76+uyc1+Bsd z&!=RV(mWF!9Po<})wUw)fMB8 z^`eU&)`{k}Y}h#Z$<;XLg1|HkBsgJ^A7llOrdI29m_Q8}xp{BFu zk`N?lOZXehbR2=Z^$}t0hDM|qW-j23$2eD1V`~fO@>Rbe!{Z~!3f8@fBg10fv3rt3 zlDenDkzQQWqGLIB(R(N=c6_0mO@FFa(eG?^6k}*Nkv#bD&^d6BCOwsjq_(X2UIX-4 zW>+8n1;knwI$^9)23nuoy~)&sQ2fsil1+EGc`;`slul@68+tmvn5Dio36vCxpzF0+ z9Aj;P43Hy9qPChk zm6m#a#k{)TwzV^0M6)o;>GymQXy>@J(LIx*L0zF3yPjz?t6OIgo) zYBK2JWu;NJjUICve{sE&>$r-#)FdXHqK<$jJ9-BzTdE|GCHh5|eYt+`7he-C`s7Dml4V z(tLHTh=UH&_!m``uc5*DR4axgNoL168k|1Tv6RKm8z;Gzo zTUB1at>1tAJI!k*P)9v!$Uu3|mQw^}+Z5BexFLe#v3?5aCUtI@&0)VPMO_@c1{Us! zMHL$x#q~Lp8Zxl$Sl0%b8*B&0&27vXo6C0q@tlohyTS0UR^w0%S!hgb@XY2+o$ED3 z>;2A`9fHcnI*t_@SU6%Ig5`&+G?2!EP^x1CC=v`ie>kH58*uKH>$T(}F) zc$dt?gjHs@jAf-P1Rp!1unzq2@Dn*7XNx*B|0kRp{B_k=jHc#7nInf9bbg8NGZ|02 z2W{}MI!D*hyRp(i3+T@sa9|}25yNxKwu&HF2*x)*-?j5EAjW@KF%jmk}LDX*}mM zGe}!RKCiN{9RbQ2ls-X2lu7!?7&G!XzapFkbrEvNLAfP_TCH?hZWLRiXfS> zw)IyfZnzmL0ZLppu`HQ{(_c65KDz%r1_u$;iJ}nlgW7 z3oRMY5(;6!ZkaHk!J8gNx3`I)55-5wh)fmSQUx*h{`|CcHexG;k7CBHfJUuI^yceEqNm-kv(;K($SbxbqNk$O$a(HYbhj zr!U}AD4TC?TL3;Ep7*Z4At(KJ&cOeAHO0cf#QwjX0Van3a0ZzEZSMU~&cO9QkEw{+ z|KFP4T#S@btCj)CVfsB`Yp_3#knK2_BZM*i`)4^-_wx45%O6iOWM%_v%~%f~)sHRW zm%7i>^V{scUcjRnjrPxn&&65(s~@PsKd;BJrH7x$VTh+#2yY)hn>VA#R{*=-KgR$g z=Ye%II76A2djxvh_6Xg;&VKWP^0y8Hdj=c;92k?B2S-+q%fRgnIP8slKvvh9&T<9~w8l2FBAAeYApb`kacKnq=c zVobdkRw)Q2YqMD#=!+vI8Agy}Y6fFxiyYl4Z2cOtvJ%?jP>yDKrYD)XlGX20YvnFj z79LxOB^51>j!n;tgaq$~?F5kfB_)yO!%pJ+&wIE;=OfXI0u0hMHPpg)EHs$-o{*yX zH5yxY-Ui`zy~xOWemOf0FzhYs^B&M}uXO|P#kjUITZm!1x|Hg;ta)D$wF8^;5GKjo z9hhJqp}85Y8TZtie>;}}_TDdskAd07DkXL7UY#8P3%ZmI^>x^Bmf8+N>UZJM+X?9v zoY}xTwr$&X zmu=gA%C>FWt}ffyJ+tGDnS+V=ztcR(gUratEAL$Ex)~Qgq_9pZ4QiFJ1zgqwE4Xl) zRxti#VUT1WiNi0S;!o$qQ7a9VT2@2I$SQ{Wo%94Hjq!8y#YewfRP|YT{FsXvmYdeXEVIuOE1Uucpy6p{hUhbLb;=Zp zfHk9m6$g_-IjjIpA&v|8+GhiCn%RID;}GWye*C~0E5{m(MberW<75BOAg3oZT9hA5 z4AcU)+BT)-8fO+0@2cOvVJFo!Z$UOyz*Dm7@s z6Pe8DJcg%mnKV({0b!0gjy){itYJHp^TZ@xcC{g#>W1I}8Goj=EiR18Cvc)+ zV`5d-Rk9Z?wILWLiU$Lw?EFD8yUYR02n42m3rPna_y&?zp#GtRhAgB~aTgT&AKsrN z1C+Vs55*-4uItz!##n4DP;fzLk0WltxXXQ(HYixX3ff~%L0DAt$%Nw`O&&dvx%=GK ztoT$It?zwisC%Ub-@2GY=3)83+|P`aluAZ-E_!z1Z48F7DzJ7U5p)eAMeU@tj8+;% z$0Q6s5J{woRs)0D*r65zyP|?9(RswvD&iTs7?Aqd+KK2#ZS$}(ALzIf?`6bdN;M=! za!M_noh&=UZLOX63vLR%FkZ#~=m2-zqs z9gO_V6*Z#kw7k#N#Erq0Aku?M;}ufg)~J#_s4OUc)K_8&P|Z-J-CMSvQpb06YBudJ z(yo#YTR9G++k#&n%Shi=(o3uwTXEB9DK#6#h6Q3i$h=o$e<*qRR$x`1=#c}6M!#h$ zu?E8;0FLRDqiN1@VcUS{1pTvb=dnWzqqHkq+{!9YQV0vL=XDITixj%P(nw_fUaO)u zc8S8q&clMt5`M^x3M3Y)?~sl;C?`22Z#}s&3I-&7_OmPuZ@7VZmganq>de}w`W5uj zV%JKWoEZhE`SGsyFnyvzTSE0?_LSk*F#KZ;G!DjCrh5)p-^@`o&WS2#Z34eGR8w_z z=dd|pA<_wA43(P_MrhE3zWU8flk_6l&aNq5R#%*DzX@$;X}}%nDo}+fXcX;}=Y!P@ zON{E@lk_&OZH$5ydpV1I3tx-^8%27_nJ*KLs0Gt65 zYi4-d!gtgi(QTsi)S66)T%W;W8dVNOjm@}`AgCcfG1lGj77+$YpDqXV4Rje7Bcy1G z6m{a!E92gwbli*SnMXcVD@MuuW5AQ|ejnG$#uV4Oz;@GxG>X8g7Jz zr8rB*yV#6Fu`F+vOIjr*Dqr$LeLPc=$33jf%eHusSl`aUvl@MGJOo?^tk0Q!xQve+lE!F@h?Fwor>Kr|UD*K~_gXh^-!Qb{-SJ=&m%VLt z22Stfr~Ellw)p8pEKw1@>z^Z&z1Z)cN9sS~bX-+ja!DqG5h0hB z=(JLd|16YRI>eWL^L@G^f6a)y)XQf7{ytgI`*wa~-9{_j`Tl&k`#KCFung`fTX^S} z_3iGH7?0%c`aZW)Gf27jRxyoNgL0?*eJJ(VnUy?DxA@h>i*pXyZn6Nx8Xc~MX; zNNeVVM#wr%KIE7}M@MOA`SdeMvq(Zw`XQ_{V#6`#R8iu4Rz=#N0E1q>{Yi)fntU6b z{_&nk=Sb^A6Z%6_r+ApWC@OK^wK_rg&PhD%96G&ZNUO$z^gC;%SN~j~c=)@e(dp6+ z|A}_Xv006i9{#zapH5yLu7A(*w<_G1l)=%xp#$vIPVB9emiOp6KYtJtu*@;(o!X2A zix1RG=g>yc&(WQsxn^u!^f0R}@n4Z#3=SU%zDJK$_sH7_A3zkj(-b~&dVd(;_{jT3 z3D+pMnj#e*+$*-T%Jsro|J7v;$rQGuUPj_OiXaGWcSgMH6XC^iz%Ff6%-!!y|DO7xmsy&z2Ae&yB;ti6I% z4S=Dw2VcU?4&6k}nU0>H26obF&Pf=@|`a)iP3SJ#+>AmY`eE3JB$n85SY2CCa}mkYlS@Y@P}$a|Amq<|RDWC$Oovm1J*6xLQpbsoEM?ZaM?Lik1!Dgu);K4> zQG_?%u?u4%v)_<*%rs#G^Jtv*P5_@g3xA=AStCU%GSPx0F5)$Spim?!6q;F0H| zTzM-=##qQu+Xo?Ku*|GSM5`;MR4siDC!LG3*PqGo-p4t|hsG$TwoZ#*_ zP>qiUV-JBB2%91(mAzCyH_-8I*vOCx`@DMddNMG0$3)J7rZRr6&I`XCn36F8oiJrE zoWY}hvwjXv^jUsMJ1;=)5Y>^m6rhpv@<+5BRDj&y)aFYhY-wXu9`0kipG-<0?6G}b zp@VM4Hj|e{1XQzCtQe4z4kOw*!v@&`@+xP`kUoQ$a1#FBdDMc1dOv?LmM zJ=rK;kra9{lzradkF-6EY>u*@w!Jfi(8Rx|{~*`=g6}d^Ec0eAtu>UT6Gr0WV4_qdU=i}r@6e@HYN~L^f0h8k5|@uXs+30G}?C~BG~yMG|=kLh^w1C zg$HrF3~Oe;Qlwcj>N8t(x26^BkL4#h6qY!qZ>hnOOV z04*v&K<|1jAv&LQ6`n;X0Mu%|z1&)JQ?YjZV?+9vI@dG;xNgf_Ie{-gC?0x3&4M@gz(uz7+dQQn7C?;P3IenmR~CN&U3=9!b2vel`Dva z+#+l8f{{*|yH#2%;K@CX4b}zl6FmwUV|gAey~HP}7JC?8>wQIF9ZdfYV4kGUnp6gT zQ5LOH+w}v48&zGyXwom=U@F3t5PGs17V}M|r1yt_rt9AKw&wo1+1L!90PDU{_7%W) zMPIYVVR&o05u;RiqRX50GMV(ndLBkHU0c>H+_R(Z4iU!G5;;myDUi*P*)%qQbF;#f z(|d{>?@}GkLbs)UuK7G8(bZID7TY1JV_VDF%~CfJGi(i^AFh_CXWhlY>VN?|Swq3@C_ma;4HBdG%%n`_6kC{!cAKJBz71jR^uWd) zEaFtLfoChJQR%1}SHnSL8ybxBb+;MuGx75jd_RQmL}Tr2Fvmh z&)M?lO4iuPuhYpF1Ot}jM3tq5rsnpRa8d}URD&!}N@l1Vi* zLnX?--0nvKZTg%~Q=oQALreAWkx`0Z{YrmGOz7uL6Tu}Xeru#Ho?RjUlR2$wFGL(A zQlj}rwfTvRDJ%eBjR&;KVIp-RkJgp#P!q`~7(GulxQ=VEg?}>zoaNLU7FmGlDby0DH$q^_Zq(O*#`qVr|WtTRQJla>Z&H@?A?Q&TlIgN%Sp* zjj~`89H609>eBQ((Oo6~&jbtY zsJWgBymcHlMDn1Fs>bIBS(n7xhqPHDSYV+C$1@|K*C8*H(k#<(`^1HLjW~C4ibla= ztFZd_;g9^<)V99R-Q{|&wm;-*NLN7bM8*TZliZ5C-OuwFSy~;XM0bSKi5Ynf1$pTyz4nhPC3<82>VBx@11lk#^A+dR4J`4>^6(Qb#NB zjFQ?ErkDkzC`P+O67B;95`p<(jSqejt2yJW_)1;)2D*0!9{yh_{ZAu=iJkMmQ2HOi z(SM=zzrs5I7nHtWL;Z`=lkL08VhN-$;6hAeH0{(s+9|f0T4qJ^w;ryac^>YBjN~#T z>?RNyVk$@GJiJd%8^n0~_i94<;i12APXiI&ZcgYC_`RK8c$)zOxjlS5J-mL{wKWjI zD=oPQJ2`tm?$1XfKVRnXRWLslx?=EfmnKeQ00e!w2AKJ!UKhKf_F{fWA?=}Dv3q5* zg+p`rVn#5oP>YP>{E&sJVxLT34^LYI=Nkjh%zZ4q2l6nc_4)=EJY#+f`erw_F;<{FWOIM0WMM~V{`lJ6fBsGG@ zt5I*mTgBQ8uJ7u^MWQ8ViQ;9x_KQX-ad@*d`L_H4+T6(+uJ48Spbe+?+(E}69P2=R zVsX7P4}oKb{VePlhc)@d7?}TPyhCjDfWoan>H?|&eHQhE)H0Z3UH{UnS^US6S9EK3 zxiP}4X^pPY*#uLW3kH!q>dv7yNV2_hnF9Zp^D!!}#KFSo*xl41%F+ReMlW^r-c(`N zIHt)jwh$%~E~^~-gqA5_`~eSf@kZt2d0lQ)LkR*MC8ESec#y4apj zL9^5Fv6`+H4yi$ZyZ>T)LT|^#5b%kP8x}%3ns3X;b1h`Q@gSgioXLcFZ%sGTL|mK$ ztx1cPKq=$s?s}pMiUv<5n18I-{%mqXu6#J>hK3$`H zBy3>uk#H^nwYA@31^^|)3ak3a_VRiR)@2|`?o)Y5F*k_w>6>8#8WmbnKg8Xz&v2h& zl&QtvY33zCY>L0O`JS3QKY&pyM!E{px3K896AG$I6nh_AOPm%7XT-%trlP^3=4n4i zKH-p4k}nvKHkyckdG0SKQjwXnw;cQsCnbeAgO2k@&$OOKcgI7I_p%Iu!*GTd8k&aY z0`w|V9Z!Rx=u+_nLC_3Sg!yp|E?4bWYLZaPBY<==|3Wd2-B%;kI=VVxk%Xq@uF61$ z?1Mv5qoFwg25YAj3j0*wR1UJ}F}YtQPTMN(#HdAUp*PSn8OF3~Gp2P&S3NXrFaYR+ zf}GAPvwV7PBOg2wk?hjW?P=t<4YII-z`R;9smd}VX;V>fPjq*!7VnDmp-ai*p^f7x zSwPt*3$fTF)BLR(47iiBMz&j$FY0C&WEYc+v1>XFmqlGR91EG8!ThQSsU+UET$E{K zMX<)42Jf&8kr{xq)dAqv zH!PSOWAmiza@)9iMSC^HZFe><(Ynd6qe6J$@*@T~Ak? z_fszbE~gy@)thLhww(W_*I5{F-_pZ=DR2~t@A!TzU0U4`(W^)Q1hW8Di4GDuzyJ8 z;h9aYwub6QNmGTy_gmVQEOmVZ<9ctLjs6&v_}P0{A-Le7-KvY8jqDP^+qe zB~D7YBeE>Nb4yQbG0PQ+^&G{DKVqT-oZBhFI5Or3G<{UrcH5cdX#4~9HL9XE);&D~ z*Ax%M_~pqp)s?sGu~WUH?Z9#6>6ef8^kJDYnurg0-zrdREt^kx&vBcZN%A<|d`?^w z-{q4Fk-1dxT;&+;a-9_KGjE7mtgL%u2+L$kOsxKuiBKEwvfF@Q8!8%{@R8>%Hpo8C zg4`1Eby03@i}GUedzNcGG9q%axy_qY;f&Ef5ec^s-=dW)nxGDy8l}Wj}qA@|t zyYgT_i#lY*Qo&6(+%?$3xVvP#BbwEHeQ>d)tK6Js|C=^PRYq~Y1i6^gez~cz3Prrt zJKTVb2VfGiXn;^>3*-n!X~;CUUNz0q%y=mv-8v_={7XaAdSMvz+|>4fI;^(sQYqz~ zp?MtE3I3yD4M5XZwFVH0w_HKi^B`yq%}Nlgs8zCYq*BgfGV9dpE%0>CsmzU~gQmd; z>yLPQMgw~S`J>z=l~yY>wTrF#p&uE=gpb~KsYjBX21!xJ?a`9pb9Qe*E3~)1^1IFZ3bcA|rR3ls zQVOl4WOW}!T7}Y(5p~PVBkI+Reih}Hb+^8n3=6CKmG*{OKnGq>DtsJY$cBV_Ji05Q z?m3DblCHAqm;m{$syFp!lK0@?Rumc9@Q4NYUa_&N^ebMb=xQA+a#Ypi0tP;8Uaigg zA`d1>f|X#rNH;Cpl6IQynb^bC)c(X4H%`i0tt4;D-hk@kx2`CxSBa7{4;_gMA|iu$ z6|Rq4ysBv)!pHKW0WY(1r_b^4Be13w_!p7KaDw}_Nqz-}L5$Tw+ecgxZce&$@Tl$L z{$_Q$`ok%WYRmY{I_(71iUa9<{y~{>jv!J>grQY|m*`WFlezv2rBXR>lsiu=x=J&2C+U<>E%S2=IKOt=c;mz^7fVH*HGc+V(` z9+-^6-wRI3mstYjdo<$-0CvmRA25fuKjvyK!@kigrpgNq8sL7`2EQnxA~PXv)zC>l z%f@plrZp+1RlXf@Kw07}y?y;YN3#Y!<@53GO0{ucA7W!6+y3UJKx@P|I;HJNCxTci zGyqL0c>$Z$aPAJJQvbFVW%tb{lvL_|MQPJg0>j!DVvTf%H_N(+Cm9{|8El%^h<)yI zr7Y?z7OHps@tK^no&`Lcx(N%ms(+W>CW9{D)nVy>RwW(pcIWW42%VTJj2lFK((WQe zvNS41oK0Bpdr#%=wLYqF!xYXG^%H1elf>}a-&Rw%Cz|Ha)dqoF=?Xbw z_O+G3%lUat$2EN|sPFUp3b)|S$1{4s+UwIx5N)6GGqfGVfA71(GTtm3s+-t zc;*j*>!Jujk{Y~j28$@im1KPZgFdvs2l%PI-2m?h*~EOkWfsBp^Hpe^btl=>jG}|p z1l80z=YX;e^R&zA;!g@fz0s3}_WVo|MRsf@cqe|4hk7*pdE2hdg(1EdBB zJ3SFXiaF@-ARH72D28Baa~2h&z^@nq*60{&$^``c5bCqEC6x?8O@|Un(l1f=F!no4 zT0O?bMu9A=i>Q8Zp@rUvy~c$GQ*~DD70*BfxR$x#58G*02TX-1|1Nx@h@DV`aeXcQ zS$+9@2Aa5`dR4IM^HJi6Km-CyYf?M)AGk{6aqOd4v(Yvc&d@IPauF2Tol>(%lYLJK z%|I9r+d*`F%c)bN=-LZV^Op|$Nqv;{-1ax`?z0~7**xkr{gP9$B<=`QNv3Xu;ugn4 znG@O{LvO5;0)gyBjPB<+i+wLDi+#&xYz$UWhi{-&zrf*DGw4`(H|60bIuTr%rRYL~ zo-r@UD5<=BB~i_(evq|3V1vjr{?0b!lJbd!W{g|V#lBb2*sh5(BrZNW7>IZh#5pI#tscz9+E3YyK)SszN5=#FV zjy4?yt;b@>4D~^XXn7RO1g>3O$Xm1(En}}bI=L)pMUQm)4RGIvJXEtvG55IyUr{f> zjAK^jKyQ=hkc)`X{w->t6kcBhm+joCf{|>fH4YiDr>r~|KF}a$)ebqkevNqT5DR`V z94R-3BvdBVG9Or`yjomhRsPh>b}O}`z?KB*c0uk=cKfy9d;v#SeI@VVzSrY{YWg!^ zYIvlWAB1Y&-Bu6{vk}&V04@lIK7rdW#z~MftbkM2M^jacy5v#CK^I>QbU>4s7duln z`@q6t?*iGIFzevK+G{%c&|Lnw24|k8@FKj}1fsI|Q}ud7kr!t|)A!M(N`u0x_-9Lo zl6RAHfID6G*hivcOx=z(?WuLy3D7)4<;ggT1UnIn>RGGmSXU=IvoejNn<<4L;wCN8 z;;&g%(pC(ExGYe|pr&*duHp!zWbFAgPcl`_zg=ScZ!b&naJkZulE2SXRxSS8l`z~N zSsyM|<+GwaZ$9>)jjVz6&^K;zDj7-sdQLujgg8HD8wbRA{8){#dYOAM! zrOZ)i;0bItDOW?UZ(`C2*Qjc$T2Va5;5HBD5NHXR7CBA__$cw?YF_%=0T>@1p!F5U zN;Q3aCCk(gzmnqUwtYR#t!~LpbEI-9@FoR;8~G8Qb1^iEz~|$$&bcf~%^U1F3Tk{y z+Vu`#l5&h^YZ1}wXNorexJij{)(+C%h;CBw2=y(F3c#SvLH(%@r_T2p+f*7OdzF9~ zF*{5Y4N91(tDN}z%5SJe%1x5JjF;=LNbhwwO@j0fxk!K@mzE6Y%wYAI8dlU_J*TFn z*(&;@NDEmg;>>QCuzWj0cwx5YQ!brm`oJtJuhc~mo4huFK8@k|$@tNB=)jQ~v} z7y0T?bQ8WKex13ieM#y!F|rO|cL1B-ef9CHETNGS_s)zp_iMV76Fj<;3|hW*4$Yw3 zLV*s=2Se*?qFeo&$Igs1PJT7yFW5Q15`*ASS{f`|kN0(tdwM>P_8u?yQiJuU*GJ00 z?nP=@a>9f&{a(N1uOSNCoWSwLlfgdB7nTJQ%ntT}?nNjSlnl zFL;OKswrzAK;!w*w5)NzAfgrREJhuLH`M6OPNc2{-x=rG{*;_EA9PG~o(?3m--EBs z&(0PKzmdozKfnz!MU73>mj@GKN~|qH-UjP1@#f}W_)04o85|~%v%kmTy1mq^Ac*?O zqC&v3-Jickdh>IC*Lt1VviFWl=q&DWRLmG|9)w6$=8lKkLmI=ez?reXV)^?-2uR-R zn`Z_1Dvmv`)%w}Up=#>xsh@A=U0)3O}7%(?RtY znONLw>g|Fz6deLnZXGRHE{m4`iVeJRmAo@+zCXoA9{`c+0M%)Y9K9LXbja8>B$+Y_ zvy+$uD|TA|rqvpg)c_SQ(97Anz&=0(SSBa~{tz=VkeQ^a??mgX4!^f)IaSCn7V~Y+ z9sk5)FbwT*1g*nY5b~yM8@U?S`=Ig{P0v6$M3tUd(ono}6M~#vafeRy!BM{9xc1PENzoEmIN~t{ zE-7i@WTm{I{Jg_9yay9Ftu3AeaB?mNrX01E_Hy#!f|Q94Fsb~_A<;|9Be=3?pcWdz zI0*V3Riw`0qjZzdS|xV084*N@gH^IwgY3JiNp2(c=RJA>IM4!iQEkoR=pZJG5J8%# z=HT*$3UcD`!$pCmk4agh`g88x*>+kR2?p*dm%ekk*i~sz*5E0X>C7on8^^Q%3Lgs| z%P#}{;3ycJR6on1NM6gYA_yVLdZ~W5sT9TD&CS<5gZ><4c3A2Rds07!Bg_ zzO4U)uU%5Or6By$(U%+dvC#SGB~P`4z>cB^g_L)21m8)FFuJ4ymk&4ditUL#C}@@| zr8G=}+O~kW@{x84w>eMmPMY;PB%!hbg44AObK;;fg^Ef_4ND?iz@u+F>M$>}R2rTv zSVtCGR$Qh3cF)s={~izyRY62*&CEn!Y(zQS0(3@mSi`#=1H?7#R+5k}jx!WbgyBsu zuCG5&iwmT!SLvk2e;B1(9L<+>2sPQH)X?#_qzV_PG7(6`37TX=LGyZ-1*oM#*QSk$ z3W`41nUS~Y`xdY?5VIjdc7zlAF`Hf&78kGsYABLHHk>VySq zRxlGgymnF@=izW_Lf^t;{b#-0)}GgY4Tu#)nzt4Fr-6D<@RJh0oF^m+YuG`AM0X_N z{96VX)hA`c-R@>!mjnV2QC9itLZ;d9nErK}BZ6vaHeAA0?uk%_ zb!LrfH>j*}=C`7XVTwifseQ>y`pdLub2L9 zvOjkb}U}?M>q&#Hxd5=`jx06wAKVC8KysEr`^e%_Myp80$<$#|4bJC zt5Ux?>RXlF8l49z^$h-JXj#3iNp1iYHkGSW(shl_%W=z6vqVaCImj^J$P^f)Hq=iA z%-`k1X4pWITQIBs4tO4ZQX{A-a&RtzFy7p>jWrGGl^0~jAf$Wl_8fN%JEk#D`-hU) zxdrMNmbtUtA3P?v1bc7~(AjA5EylLc$?S);Z{Gx4+!7K@T_PApS`bs?)@buzDvpq2Xai{05N*n) z;NBE0@!Qpsv?9%#F*WG09)FjdWiS!+6~2_dS!NP^q#)PZ%b^+!oZSP69YQi_KiuoI z+|1p@XC29}iqN$2k{}IwcN>5Tw!!5e7uYzRcYE>ew^eijcb?~dg^IsrF~9&ew&%YS z%u;2cApwd2Up@K02Sih-5j!?*h4iVZImsMA7y6lmN=94kEcz#mStmi_g6^Hn#%?^Gu+woSoP>dEl5Y5l#IxMt$EL9_Q!<*!s{0{E0{SR|P-w5~ei(QJGZB+``c?2l#dPU;BzJn@_BXY8x3;zswaW&Rp(F(1R56+e8oitX#KWaXn}O znJ@~`b$jHu^BnB-Hb*O~n(G+0hB-rA1KhJm!|F7QMhBL`#5r%aToDz?6YF=6AvJ=+ z^t80Trtpn@gB$b zf4`KaA{gnSUpWhY?#6m9PQ1sdMR2=R6F7tUCj2nHpH=JCe%K@}q*@@fb3tm7Actqp zG9hap(Q{ASmbfL1c7Ygbn7b`i3#C$m=o7Fu05@VOwf9<_w8=8t;hT=k`U ztgfZ-I&u#`m5FHAHOcf`mNr}S)M`}L6LQ-=3(VZ)CLK8TR5b@~qN5G-AF6A2!zEuI zJq$;dhXA-z`pbY&{DR&Py6^*XRJxen0w5;L_?W(5JHc%}dF3dKw!x6|m)kbiA^})zW|>EFYo8N0m<}hal5shnpS5~#_niy< zYW-ZzDKXbKJIBJ?P<=8gMu-@|j;2ycZJ3l{BIIpHv&QpBS{^r{vauv7%F1f($`Vc1 ziebQQMSzCFFno6VxszR{82Hf_Mm1Z9J3|TaoguVy{u=1gA-!BWk3-q?yE}2${`ZS& zz(A8q^s3wnXa02eRnZMsX|e2+nqnk^kh0t5g67D_&+FAF5s9W5;y6o>syuVraX`D5 zIElcdXPJ5Qs513O_K5hcweEGUP%PI@jV)aD-Hx=ewgY^zWf<=_bHc>!Q(&)=(ivvd zOi61JtRCvhjHp8&1pkR13sqk?MfKmK)>{i*u~xOzp)lR%)v@#1u9!Q|7|~~e86a0B zmYk2+6WGP`H+(M8!2{55&q&nGWP#k$-_y2UlU^FkIO7@}+%lMgdI%qw%dmylDNfMF zYG1o`QjzR5hta@|()sV)SQXX}6MuXoi^2o`7s>w<+GOHn`p;~W`5#}zf6X@k^-KEy zJ=+|M`Ma2}>sjpuw--M0-?PmJLjp&fJb&DP&3YitAEVlL@8yOLXd+TMIafJ3n4sp? z;Zk*Hb!WF4wD7g>&sVwGy}saw(_C%uAMacLYJkAI4PD*mx*^QC$?7XnZwg%H_-=f< zFLV0^Zt#BJPAH^V@Z%S!??Ptq^&7o9(4(=wKE9TAEZlFEuC)>_^|^wlxF(1Zm3DDL z!;Qz1m+-bS6oYs}ib1(wQ-F7#-3YfrZRFTr%@QQFmfHRKhOmZnzzx5*xAMl%f#s-o zFY3OFzrOipJ&l+ulIWjHK6%{{Bw+uTZQ|vI-KnYD)UVROyd+$at^a@$P~iWFG(0v} z_VVX<{o_x6_8Z$9e?EX%yCMqSmA>6gccRc4_He&0Pr(3Gr<;Y!aT$JpA@5*5O9-kN zmz*S<(VU80eWSI(w!XFcHU}kh$7SbEpbHPUC_78x`!h<~y!17&?!jbCe&k6^jhavgA8X8z2<)Fa*)^(t^A3Gi1rnR$<)k=l9ORw0!H55Hxcb{J2-#qeO#A$4Y|uw>%P9z#KP% zHmj@F!~#(=QNIa(O_jO`>cc?b3NQv~()eXQHCOTMQx@c&)%OVBaLC4wku?6io}z0#pv7_J zu8EXHdpA2Z<*!Zp%m{m!!!#@lDIpQ7E%wPwP}L4EWD8zPnL}L_>m2BaJSdJ#bG4f1 ztjb|`9`)p)K_9{u`BQ>uZ6`?q>)>>{l=q5Bk%*4vhG}Ndj?KoS;$RVcf+-v_Z1k=H zR7Y8xTA+ve$n~-1S;C;uc&iajfjn7~7fp$LAs6D&yTo@DBn|v_dxCvYAf|RVyNf&{ z;{jDK;7E|4QkwRCJ^^Ix@K3ofhk zCcIJTtsb>(ut9~wOf`apb$any#N<)+r{TA;Q^7ZW3U+%LCJEnaoHpNx>1SX;3hH}^z8|wQOwRFWBc*s9*OXO zM8fNo_Tf@I{Fs)Y19Ru`5{M}RDy){dOy8rerty~5t=n$EbTw}@2@1(lRY_TDFf=GH zpA%9{lM8v>kM8Q?lXMe|!R^)lXrYF~y)Dnz66kIvY>6~b2Xnx(yPTKUcIC7$30jNT z%pR-);CB4mj~1Bh&~$J*dd=wygA74$4^KiVM!hmC(|L6glBl5kg@a+3(sL?|)5B6j zng!EUAI~IHFf3=2>FURXbRZ=sFK7#v3C*W){q#WZuP;hOMG@D;VlCmZHPH$m` z1n>Crrwx{bR0t0(e!R!6U^972peQ;Dhw6~lZrLHPra=6r4u?B0CkQQWtgKgImU65h zfS-Ri`0}Uc>Kz9{1>l@Jvj`TqyX^GpBLs4kWuCbzZRyInSP?Z7dx*3D4$a7CGX27Zia$X1c<4f8croJP zLAb*XMB%*bl4gVcv5w1b#efq!fNQP*D}HL2f*qfdoK1U|!osFFypq@wA;A~ciB_h# z4fzhkO=M8RHQ$=9+#trMtuo%yW!OoI9X8gHP>R<&?oB*hmDfuEhev>-xwv|Xg;knqEq zrr_;XFX<(a@Sp`_Srog&%wjMP>D+hQ^FMH^I@oseyHE}i+-U(;Qim1jpfF#}B5)u3 z94>mXh)sblP*{Z4iFA6X-;viUQwUENk-C<34oMTUtPRTC+(YAATOpgp)|IL5-1&Zn%9`wI}=%45v6BE;a z0(s2;)MWn)i2iTe1^C9*Ad5jl;|)8>~9^G?)BXxGQ~`b zs>8FLJ5ic>*FmHH;bB=Wcj>GQ!FT7=MgC^S$_cWN)BEf3YUCQ;cewQI=JmN_;yzmy z^Z`z@@9{Nt;92f1@9$VMS5{I^Gkfu1@lT>>#&F`D5=S`_-5V2@IaA{DDiI$m!oti9 z|0XZrj*q6aVIv>BBXTAgCu4%9tT}?0ImESyK4M1Bb;$v|WzI;&irjTDyOHYa-au zZZT0a+|y}=;Rx2^C}`p=d}B>lT-M1#ZGXOb820>6hIvrQt5vR_XF$3{+4Vszd^P^L zPZ|;q-AM0Yb)eh=W~Op9kET;?%bs4m_(CRK9P{@CHo3P(95FC(bwlFfy0!_&;b2e{ zMJL5^$Wb}ky1@bq4mj0_AqK(uFM+2JWLJWVhn!U9PUTB)7R#75Wj3l=ED=y=IV`sG z--qPR2nyiOh+JFtQx9aq6i8?JvhyP%kEBmUm!QyVwG`y=a=&@xa2c}u zP7P{yH+$Paj}o9rYCTb>`4T{AM=;sAyd{r2GSoVg@?Rje?9?;*+sjhRhH;@eIG;?( zV>OMMG8mp~RYbAmJmlkR?^-RDi^lKAO-7Y5W!EIV=TOhI0N3w@T4lNrswUzdnJn8% z#6P}I3yXO@JC;$oiy_Eg-^YTDv1ovQy5hDGn4{4&B%cK9XFgF#hKG}q6FC|#Gdxma zABXxEx%G4PH;*-P43KIT7`w7TU}r4wnJ|3GY^mdGP`2J0FxfJLHf)mU)Keh%;XN8l zL$P@8i;V9%M_`n$CdwZ>(FMDoI4@9p29EzV0jv9BQVyJnhAeFh*`m=;Rt77*pJv5n zO2V^nehTgGBh2Hkg*7MzrF{>w^Ez2?|VL%5+K>kn-##)&C5kApYA~vf){?kJ7BQnwzKS4?0dX$fB>szs!JuiW)1+(fW- z#kUh6on5zDT+D9-jIsm)PBC^YAP=Tehl2@-wvaU0BWnLM3J*0MWm|p|VIE)_GFSpt zQaIoi5-Ki7=S?uG^J_UrQ3ZQPI>o7Uj5l|7NE~&@Nr($&Do^Qh|2#s|oX06Qv%JJb zb%rY$JU0YnN{3a%zCxZTZJM%)#2iEF4Y@0ogm|lOo7|gRUe!Y@DHe9p(8L5bIt@j8 z;g2@Ie43Qw#ipC;N9%gg3eFNe(FDn}bdrYT!6}x7sXqj1L@DO{Unwy9Y;dw9JVcfF z7;rMKJ|1~2{^1Nu0))<5VretkSBt#KTl>+zByQjd>V~U|1*yH)>s_SQBw0G#wv$|L zCyw_|pfD|~Ty7?9sSQF=*D4#t(`A*#*=_K;5iihm!~B+DtBEZf(8w?&soW^l6fZpR zPs+A>2$;!A3tU_JUJPwit7Fo37XVKi9XFDW;sE1AMyBLB2Rg{XTzWXCc9x9?Tpvi+ z`pMx7l?X|HJqv72+?+n*hPbZ$7>q|GVyUxXq3V-4^54z6^jNj%D6Kz2tWnN7^kYg4 zzyCIqm!Jaz1t~>5(AP;<7^>lG#IBgt%srA>>IN4s>>YHnBe8>k7&o-Ww)Yix(gKka zJJ}$XFg*hUBkb>hsY(6m9(y1BIJIE2>N{@h;8CxHuxX7|QjsxqO@1&+oKH zeIFw49=`KB_q$Z5)Gt|?Ag!ov)>VRCvMafgH2nI|2<3%LSAaRr^+~6w}p?wF!(T=NUkuLEvL(qHrz7u zJLM;DGR$Gpp=l`r?0#C|8BTX@+jA^oe8-pg4E*xGB6_KfjAkEtG>f-fORy_5&HV-; zyZ2l=bWT`@iF#uyY*rnh4VBRg)t7Twre(`TT1zddE6(esSse>I<1p-hEr+31l4K|K z{YI0N(Phe8A8((v@8|573YTSe`%3W}n|-CrAwGC)Dus-&NEzvmiz(1v#Oe#UoF2%D zXV4p(#for@<#p*o8DyQq1zc#{lR2i)OKb4BCtT>BL<_#sB*OSgAj0%=pQ!OZYt%KPg8^T9(v*5c zjAlgL0*25`#eYm&!F0W*QZm~Nu(CQ?Etv|rpNf~GplG`An5oD-Y)l&&AFLP)YegRp zGqx69_9vcnc&g(mNEq1Y8VSm)$tX6+v&1M-O$z*lz4l8w5uy9y;6PkMRcQ3TY4rd&hmK* zci!|xkU8|Ep|QHQMi(Q~Z%#*`7cJ5D|0JzQpR?7^dFrJp3U)TQzf0UWopl3ANZMjA zlV|6G3~v%?E|WL19NF55fMi|Y7VV70*baf*`nz3R&6oPC!4uq&e77{Z06!!N{`oHV zlkTg5?}iNYOVp`#vQ?gW4w^lp*HWsDwu@PE0nuV30ulg6HB}K`ie$ zhVqwSU;2Z!ea5FtH29-z)G+|HC+sx=v&JcEYW}02z$jhsDhzwo+n?hlgE2~G%vFMH zYPo(>rYp`R{c?7kvsVPSI|z%0O)I-|qY3NpF0{K8I9;*lJ&ww@&1t%^&Hf`pt;ESC zaJkknh1ATiAjveSfz6y|sHUFr4G1jKmH&^icWTl#Y_l!Xwr$(CZQHiB(zb2ewr$(C zGgq=#SI5`2BX%9sKX{McxSn~>IfnMEpcegAHXK)L?^a%jx)8CPT%NzO_B8q zE1KQ@l+W`BpE^tV$__K?=BnL`!za#l{; zonS5A@9Yqv6#?W;g}57VqkI^i%nxkD1){Tx#jmJS`8qtc!_K}Mzg1`~{~HzBjkcuq^E6`br}{K! zzT{m^sNnvC)A$Xr@IMh6O}sF{9;qL{u4+$m@oj?1+|}9vYiNVmWl862r8x2I+a!oPX+&;37H^-s=it3HOz!=e0I|-tKPRuhw-DNl(1LWL)-zqZ2yC z0UKO;5mzKHqR}4W8Xjb1riN9!i)y*5_80A|HaG8#a+?EA!ak*XhCvLlKZSYZo{Di$ zeZw)}z+<>5(}C8=bM!kT;@Q@8T)F>#pE$wFQ4t~^@yOypOM__rW07kp- zZ~_b2BH`7aeNLqUQLk9;OFI1M2lK6C;Y|8K5vc^|3yu`j=8S3Zb6cj+Q?mNWt-g;$ z_kp~j#A-wf0lf+HeU=HH;Vwm;e&?vp_;%oCWOoJHbK)FO3%7c#GjkNlaV8V@X3DM6 zj1<6TZYUIpDP=umVIGsGxf&PF#e%U#*8|uaBvxUOL<>`^h$yMKWJgUV1Qwte7#2FmR>{+9CPu-w zlSNFVoN0xTkDT5RSjwC-?37{{WVmEoG+OHinIr?*novxHBk<2g&$wZTygaQ7LuZm1 zu~Bv8M4btpG>TdPV3U#+IH^q)s(xa0sC>}`vOt;m()Xd%#9dm3s0{j1*P+{#`RIwb z^dvb^!W+RE%?8$K$;@8ESfZ+sfC~->(h*z3F*sBvrW4985H8sK3gMO!=i6wH_-v>E zV^?Jn;DNGUu<_D9dt~T?@C#jJY@s0T3rC?C$LW7Qtz!-8DQ{;ruK(PBJ@UsZ&%Ya$u$!xQH%OMGc~4?7t+Tma)-G9}bIDTz;beo{eaB zU)P$aM4vo*@!p@?^2C8B@88 zIc#o>i=>+!Ut~4JtNkbwg>tPw5*}jzFjPwhyN(mqT_<}J)8&%3&!=l?W4dDt5pB~w zq2YGLiFl(-VjY2`m>*Kr%*8>467k-KSff>~FogZqNur~PwCI#i*s}bRw(SC=)@t0k zoX;{)7o8IusVZc=JRN=`5T_Y1Pz2I$xB~M_xUYHjrP%ovh4X~iwlwz!-_POfT(XmM z@q&l;32Rw$RuUoaKInE;7RlOVxO5dZM`jD;+V$f+uWmSy9*m&adU+) z=g)Eg05eY2Dl$J5ni6WC#*G7*5X3={{mRu7$b8fGx;tVSc1CzK8M`g+ZfN8LXulZu z_=W42y$0UioU#Y96KALOy1Xh~g;Jw>22^V`a>7HJ7rxQ!rwO zJ;#pXJjIr*we5N%TK@4y>qvTHsPZS74WUX{Na@P1CGxY|R^*oSyk_ zzq!;v=haZbSt3Weugs7Aj+Ob7f5a~VePNTI>U!-<;WKatq0v6w91!MAxGRp-mX8Xh zwZsDFdOcfc=P1iTr?H;~P zNekuD)f(pF-=@7D${Ht`56g3kq62jy@f4OSi)Ye#MX_~uu8)oLa->TLD#cJg;-ZXg zc;X@_m@xn=wgbFA&rcxDwX$D{+p+A9PqrHC@oN0rq~sp`kcymcouQE~*M*HI!mxg_ z>tIUnPjFmgXXg&@{nm<}F=b3DCduXP1pG<{MIz~dfUx(KYrf#7;F@vukRh z`s}n#lx9U#ilxF^;)zJQ5!z#=LKQXY0G34ivRtBKBM5-fm+`j59itNH?P13Is{RDn zGS$Ok>R4RMRwP$831s4TD=>nj)LeiqT`oftn@s9(t^i+y?gV1QF_HBg%+uOAza|A8jVU@mdDxS9x(s8ymqd77urYtrqYgo{4#af|S z@T^gCIj@>OLs!ElR4qHKv))elp9`u*Gi!8-O1>J%!(w+h--t?cam%)@L-r3c!ZRNY z0?>%C^I0q2Y)ZY!lzllr;8pwM|I^s#zi#mVsgPDD#6<-!uEW>U(fh?zNm3g;rqUiww~hbv+m2dAo=~iZVuw? zKLkJaety!r8b4=tPo`>by>{#ucS9b3FS;~dvpS&LrdaV8?e=b!t}jUb;a6|>lW*u? zd{BOTcE7=?eP;45e_OkB9@|!TXu#RW*Mf*020S8JJT#N!U;Fw(j--Yj&TxBsZYK{) zuI-ipcK4+o3gv&ATzW`-=l0)SJ)c+d4&{fp_KK(TCe;0Q-ck9Tq2Qa62Az+~!jkUI z9%IuxpVOSTw;`KW%+nm(tWmC`c}yDCf6^{2MOEh@IJ5N`2T$V9Bt8~ zs!dbj$%50|&*1-F{~^wwvb%Mxnok)Ou|X#zj6uP>v1Na>GvSC=c;%JJc+R_Q+kxu` zm-lx_V#{POss+n*lS0}SDKhh~WZFBBLL@wx)b1vn&Za$rXniwFW)|*21~CzUojgwx zLH>x!`cn6KY_?-+KVbhQwXIrE3O<7_4uTXgY<;Zma`Mbk_Z$6EBNJ$6(Q9vGx{u)i z-p2d14H1OBZ;!3BoeRe6D)BaMCF&q0?U~~Ad`b+0E0Wb1msslm}1O`G3z_|w& zu?uK0n|~JJvZZ`AKWqW5V#=7_>pzJN$K<$|A&*7rAd{mL+u-7lSRHRD8JaXTF-*Hr zPq@0A*8VQb_FmGEQfQB5ksegYpzYTlTWnYp`PT;%lQzr0ypKrYdh275U5`y7-u}C+ql@6gl1oW*-YIU)r6cGO%txZ)2yB z^a;z^LdeI+O1AWoi5Agv6?>rHWOERUn9Uhp2_$RduB%(ykMfUum7kco06OiDe-}4k z9%yL`Q}%%;oE#n{9;pHETfAUJ0#8w!uS&L8_cn*VYA3BlPnHs@CTa|GvUwD`SuOKA z=3k7J@g|!HIMI&-DvTO@=7bE2_`;?z{QgW1?2++2Y-%5>gmok@5F)^+8e+uMTOH2m zMm9J!6+fssYFW+m8VM$$qkc7O6?h8vCuM@JI-QRlm>!x42$*jcc!zL-qi+r9a!jBW z3y@7kmY~9rh+SmH!(c0k`eTF$X-5zBFW8kJv*O<7!%NzUx_1!Mddat9<)A`J2|H`a?07QO;Ev}XdF*o27ckcz|*$45V8zyHk}C>Imh35rw6(Gy7NEWN zF<=gv9T!~Q>{5=wA&HHgjQ7YGP|7_H$0STbxW)syS;m}2Kk;02sQf(9^H}E1Ecae< z?2DT`R8~Rs4`NvVh=@0xfxrCv#XJ|PlA?^!5a}i1&)SiCUXsmEXnAB z9%M*Q6(3I7l)p(l)<3P}gQkhWQ9;fL)3{_};ZP*E@#95@whqr@Aq5^3^n+elyJtKS z79pC;i9!W`RX$Y<&O@?OY34G(8Uf{=p5Qcf_-b+UXW~1?)i`|snUrya`q?S!LJrgE z9vlcZnId&~sFPS`_z`C7H^_~=;=Bo6L1q$RXrcrscftuhA{J?tr%|7 z0vRHJ;?OX{T${_4J3+t6wPIybqp1}ZnU37Qfc&XzAJY^(v54FroZ8ssnLAZpg)SVE zTunLt%wJLYm&8!!T*pI@R2Y*42viSET5p>x!VIR{7Th>u(WcW#!7QU$3W`Kb0-qWl z%jVjS@C6i7aw#sfN8i9xGKL%}5Vzz8VcGOIb#zOEDCUlI>iH(CgJQH8WERjD8_%Vo z_K|s$2L%u30!tcMVMSG{S1?eS16l$xMlH-eYeieEs5%D?V|6%zg6-^^$pHruH2{@i zy)z(JfzKm0Q9%TFk#U@9n`q-^EmFz!i+0n*EJ1xlpPVkh76rs_iw*B(Bw~VnyG9C zvTD1e=uuv)O5w`n+3RpKL!`n1&QPQ_fxj3SYVbZ_#E>hms|)L0Z-+f6x`OTHB3I=Yyv^_TDkV1X75kCFWy z&e7hCr?-4w6kqNnMs(t=ySYT5pcwZe9{}=t-riARHOWPPnOrRULgJ}VeP8e8PBXtx z{-`UAl9;46vOd4eHoxChmgS*>RK4CV=#1GrnO5e^SCXyDh~eXunPCrc93u9~e1y`3 zMhnsY_`7h3#VN7Eer$tEyCuKyr#8zsFtVvHp4jzRhV3g7S9{ndmW_q|ys|Zf3!lSE zTVi$L)JV<>`%-;6A~E;a-7Luld7{wRdMWE$P4qU(RGax|cEd_jF-21F$xFOZ02uh8k8{M!^#5pS47( z6u5dLGCAjK8MGSwE%HxIiF`MUEqYLDicTvo#`K1+jhS85ewgW`0mu+Q<0blRX^;q7 zZPmGmU1<8H%9C1~{!DWCsmn->7hdjc;Y%xz=CxK}^EATa70Py{8&;!u0ZDhL<>Jgy zh3E=Q=%H5OrPuGL|6e3BrhN4Q7U@iLHMuLoBd(*LZl|?oC{~(8n?%|fPp-}SzTKQ` zvaS=RB)Fhy*uzsW9^~eWnk0TJ6YXnVcH9lNyY%09=3A7G2w##M3)xpw0iXRTY5f@C z){c_f_5B>FI$6n;#~VZ2$ropLrBE!GgDQ@Z9-mb~#kjGH^SMu1ys#MTeM#-&>HHJp zWwNj(yV{BA6tM>tL!z!JsyeqFXj}8w7+~GhO-QK~Tx`kTHP#Tiygv3n%qqLpIbFpZQbLt8Cn_5$)!>IQ=ebU+tdv!Q zx^S8&FMxRLi}uKl?ih+Iynj#;!@NjZ2t`^CRrAqB6! zrVlmasn(Yf%6#p$y|~noaV#KsCW<(gmhB|-h2)$^vT8#olI7{}{SpCs+OL{xy|bg< zGjs4}SQ798Wu91AxsQ2w1eaj~ootV{&AVc+oUFPNiQ(tF52VTxh^(6DB1a^{xnf@S zbg+of2162`h#q=iV@o`}?V&1-O8@R=Cnl2!y+r9TEx#F%zfMI1zPGy|um zk`fjj*BwN~bG1#?4OV#Lho;vq^#zvrF|L4{BGVsuCK1XIno{+pRX-uI2Am8C$LQx9h*(-kELzqN z{57_R#TFfHafC2_A&Lw+HJw0{NwhgRS$^v1>(snaxxC}h^zF%YEFJ4MarBnz+RGCh zbG(;oY675)dJ4%AT&o%#ZKMPs$T!gKIv6*qJ6g3|KjH`S4y8x z_RFB^u}Z&IC|kwSKh8Sh#vF50CD`XKbRF&1$vs%G=UdQ|r1p~?Kb_hF? z<)NJGJ>ww(IuK+JzEXN%*q8F;gfFu(d=(KVa750 zF`ONXOA_g5i&C;XD@QZO>LdH~OT4G6PQJ_8ZTXrLF3&S(2`6VDMz$t)B#7tO9aW~fXdFaN zl6q7^B=j;IokR%PA0_cHczi4lEC9!G`qbD0p8fo%O39P*e+2UnCh}$G9GHIpaSh(O zVAJ4AlguL6Phh(hJd;riY`v0K|D48i$`pB>)d=)9$xRzB-@7<~NXr`+7+rhK9n0HK zhuyoJ1kjE_QeMOkC_83t>BZBM7;DMSb~YWi@w$cIGM#}$yge|!hyq7WVz0Zjo%ZhK z{S_~ao9R?&kawkhF^w~J$2&o!m z79t+G0@Oy&l|?j;br-GIW+L>$Vx!l-9L>CyD=xX{wSEW34Y^S4R@9J()}WaW`({rW zfv^B;ZqX8|>zAn^KS26=LDB!Afc9Ux!v7mUurM++{C5EH9|p<)5kUNJT#Yx{vT@sN zFgCOQgk%=^#{rv)Fjn3z^{Xo1ZJuQ^;!U3m?efp6orW36;a|Y~LAW;B8nsKBF zamPntxGxZ4zj!~q6klfo_&)Pt^nQF_A4>;$E~>b_UoQ^6zW#Fjui)@d>O8-W?|(1h z4(`AH78`i{d>&l!HaE>d`F@W>mwO0tZL8i27>zKpwuaquf+EC`!Q7nN!$R93*07fZXlSdp7s~oAk1DylO3#BU}?yqVxgq@{wyKUDvE{$jTUuw$@Oc7_;Q5a<1~3A!>o^KVoegGb=Yq5_ZT zcJ@+aE=og%loDCFpTK*7u~Oa#G?_2kT>@Ic)^2KiR0c@Sv{`}x|!`E`+9x~q%m_WEd! z(7%6Qzf7%RopCx7uin6_faeumLo?i(=)qO9+z!cbJft~+G_0Lr4OIDaJkLBRN11VJ|9w*11H88DCBaje#yl7EwdgTj>et zI1Z_*n4U|T5M%837hP|*L$m2CVkZ1$OURS`rd#1AOeP=?Iqkqj%X4F*kP5OywY3WH zRAO={=<0-JzwDnCCCv$Ul>tsS>|ncGCV4YKyPAi{HIevlSbV!1B)RqfT0Fi4MkLy- zP1nf*MGL`pu+pzCzVf-XB0iDm9sE|Uj|fAWT2@ znhb_JBIvs_YdB>HWSGcsif#Zx79GP)17RSw%C(Dn$#-cei}wUi9&_Eo@1(}XW=ZEb zDl0A)V&9*4I$PIpGi&j2&wEffcwIB_1TJ<}lcuaH@g9~pa%}9ufPXoG4 zdVrIkPZ{)psLJdS?qa<2!9c)N*5K$uv|>uVr3;|KmeB%LK}bhPy$Zw477CD_kuOi6 z#-ya5Y@LF3dGzcmP9|=Xc@%FH1*Ul({{wFURx=i!e@XSvO{0pIGQ&j zy!5`dYba<^yIN#Qw9qRVEek-Ojq-~DU5J}Gg9ZF&@H;C97BkLKD_agnBC@!jl}tJ=62^C&0^n^P+tG6m#Xv5I%qQz+}C zV?%4oaY2TD`TYmftjb{3YG8>iRC_ge%U~)Yl*`OD9 z4CJ+o5{YxrsdBj4GIhuC)3yN@1=4A|u}m`?apQX6jBO*UYrPel;r9W#Ncv)DTONXJ z!d_!Cq@CVm&$16h6}Mp#dloz@Q}+FIHfj`G*jJ#s?Mn2pZr>`ruFzvH)3kM8W5#%luZZGY&Dxk@?|6_Hx7f!lWz=BI56fIxtHF5uLJo0qA*RO#_$=$hU>hH_%YMDAV3M5NternQwss?)BSQB;l zTIj7|w-=RjTnn_EGj`^!>HnIOKOY5liBY7a3_=`FtwUtm*UM{XfKiE2PEY!NFcB0M z{uw=4I`BKE8bJM@PK*Dv*qInu{`+l%_5YSVvHmY*Pxk-De!c%6$V{I|v>yS1{Gp%? z6zEyudDS)m56Xr9`}4%%9V4-jgxk>#egG(xSn=2aZ_nqe+Em>4{qA57*!hcZi#sQL&^oktAmo0Kb9!pb{hKM8Veqjp)`6W?JLma3#hB;)V$v_qr?g#IPK{@p z<(s90`Qi=C8>#tQI}|rod$8w9gnUzo=1$w#Msizv*M2RWMIhG%`Fk)Sm5!sl^BoFf zsrZo2EoJsXCusMUfjSqgGM$>;#}p0dc4}pMKPHuowFTq6=(cAtKd1QQgs!CXQRglk zY?tzY1P0>_RR&eeljr@|M{M^%6RGcmx8&;4G((EMDrjB+ttA;KSX7d9!m;q3H!|9D zFIkmQIZQ1S`rxU~VR$!)4Dgm{SJMz$YoX6;us~RQ=ze;N5oQM8WJq!#r~dElS$;-r z_`g{1DlC&l#fT`)1EHYnXl0`;|Mv;j}R4aZj{qVAwFggG!HES|S`RS(k)kLq@}& zjxtg^Fg7mK*CZU`bcYCe(mUCvX;RX&WEYmDPS*1>IR*ixnnAz>=+g4i`fAvBtN{>W zDju$n=>&kBTjTKzW9RSBXa|CL_QkqK$~8g}d|fax?mPk>7ibZju@H-AXp&)h%yUlB zuX;933Oi9HCc6eSc^GsM6Y%EF ze%R6*0zxw`+e8CJ380uz^Z9?|P25;P{dYLOhpoZAm~xi}o1-R7Mb6eg?otT?esm;g zf^RMFK{JGauLkkVlByUa`Ozb!8o>-f499?R1_=WWpJt|i3`iD%+bi~|cpBgoGyh5I zag>dz4qRu}<#ud! z7np=2B^h9>SC8isLm#lx6fl1opX+wh$v%5dfco&r3{ZKW=jJ0s00Rzt3@MopvZHIV zPd|Vy&4VSyBVBwUSu<>)CNSBdTyr#pvsV~&3;?ktaPSbz15T0O`Sf+Z-Uphn#r0=< zW~M~Ez~BrI3Pc_0&~|$55@8M3&rtP_a7TG65eb2SkdV867|aNz8X!rb9t4WVnorgr z&75hL-z*QX1YI@UIs##g2Sk?v0|7NtWi`#|jW9s>pN<9d-^)JOsYL^2*Ojd+KM#B) zp5!E+XmxQUfJa(5;tCsmAF#HVCX@#SdA}1IuO$nre%e6O0rrNaLHCOaQB=Oee@+hN z&_RFHo7Mq2BbVBxLl0x!*v7noTaW3j4KZ9o$N+B$B2XJ#^MfjCZkxbG{UF%-wIe}(jlx#{ik8OI|2 z!H09@OdN~H8m3~;Jj7UzIU|Kl0I}u2bBc;R8;VuW*;IOnx z$lX04Y~HsCRbt~hjCc-f)F4wb?|hItTK32tm)i*uA^=+tIo?#5T4rITaG|Ee6N#2G z5Q%L2H?!>!dx;)rxw2G*$UY}3=SkJJNu<^V8PyPrppw+h6!2oMU0UQ!lG9YMCCdSu zf{nS5NM3?rM~tB(*$x~)1#gXok)+xUBgXZt?i;bn&6pV937*jtdR%yjXX|T4T0FhP8(~c47DWhsBm2wkw zqB-hS)>pQ&@or6^vQCq{Qn6Mdw*}!0a*k8P<}%kSqIVW*b}1qfJt$4&BqU9oorn)v zqMuW|j|DpO8b@dB4R4RVm2^_m-vhgjhwj~rPEEFz-%69@76@8Vnh>|nnh2CPefp%% za%E_Bk+pQKTK2olbicS;ltJY5rO{2oc&)JZZLXzk>6I%dg!j43T-av6%5>_MT9Fx2 zhHy*RF{Lfyr9Dg$V$?w(+v~4GPusqs9;r(@oB(dKh>|KXes8J0fed~TG?FDu(h>LA zrbg6rlMJ3hhGsSfJU2D{2Qxb3C=VPz0C<5CRLK7#UNar|*Qg80;Zs2w1}M50t=Bw( z5}2p#&jv5PCH3L3TCYMCnjG0HghztxJI0u>4E{xIpzoPFl#ps|Ic5^Bcu$!}xH1tO zd)T72z(LInCy9_{--l*petAJ5Nt#WQw4{PLw_-{PO5$2!L&0Q>86#s?Z$)hfPK-P6 zkP$(Y8E>^muUgZmmf`GKFl&bF)bD5zH$4$9V;2$wD+B^2jq)rA50CS% z$^21yNY5;WCC@o=H|w&p#Z3L$(h7H&29nV^-YiXys6AWT`?gTKa-7j*ZG5RuloAO( z_715jN$nw~RVNYXi8s*3toWl!r+usN;3bBONjtGDzWQRJ?R@_3 zWAJ7x`MiYP{;zb6IC`-Va(2g|>s1vo-qw)siUz}ugd%QDx)G=IN&M)|F@Q0TF;f(vQ>+HWO zDl82D-6v=L56R)b6C&3CoqlU7_P7&v=S_W?OF*?cj1-yz(NgwfX(ra0UP6(X~yVS$Q8(XP-8|av0y+ z`+0nRxw$AC=^pKrzLx!R&8;0`o_1hmAoXcuc-W5_s(_WTO{}gB@(@Vz^=XoVnuQu94iU&d_b=+RmUElg<|~pP%+`Q=5A~VooP>0E(kn6_qStt zJ!De|gYW(Bf?wj${Q@e@2SP}?VWV*Y*OreB43c=)8F)xkyntpf$_3L+xL$@P8E6?C zPQsK(_ZN#{>po=h6>$l!Yxf0N?vF`7Z7RY>AUzBY;u3E>|DGGe{T!0C)d zrjOm|;nKrFFBAuHwb^fj0dG7AN27C`fQM{z$jVWj&0X`oF)~QsKZh6qKoWV02ILQ@ zz!h_d?!U0A!PeyypwWE~%p1D8A1O-VOz+o~SMbLG*%T4Yso^m^htqR%ia6{PZ4i_h z_863PWO4e-ben@O?L(oF5%D`-CSUyN#d~J>Ngxcu>r4_f9DD?02tJ(hN(kM^#Q=1ng}o&U?Lx3;?&8Of+Pxs;Af(Oa++Vt5z`3^s2vX8n zZAyya!qmy1p^fR8km#lvL`;6%J~HBVA0&(hZcSWLMluJ+@|*euwk;zNW}S#oOTV$F z;qZe>-Bz7*b$)|DI{A89&N(UE!I$5)5=l3F=eQzKKvpT%0M2hJ1juaQDEqiV0)1L$ zKVD@DIg!#wTf}KXgrL&#VX8u_*4bccpQZ!jnP-?&HE!P_30XRCt$GA$lVOJJ%$O(E zx$mE*$yDiG%XzxEv=}uo(@`g^?oG^h@(+0}PVCs<<|A~+c%U2^M`GohOwR3+|iXrcceN3lQ}eEp<$K#!a{ zu@6V1_Uf1Tz6KikXa|0KFSjlqdqn(Oz0adwT$7U%yBwJ*2gf>C;H zyy84JpW3;yoKzoFW~neHFEzYQO`2UKBS}5epYe4);QJ-*66J6b$;&CHq9&~ZZ&4Nw z!ts5}zpKuWFz&P1bycF#QtZh%0f1D+Er#VTv4DzeF9Sxk$igL&6v0T*mdU7w4QKmF z%4JwL71>o)0x>c5?T8F77TI3;_cn07b6ygBDeC5G4!ed~7d4`-4NFS8?L!GA&O4W2 zUIH@J_!EC>kCVRE@XPuViQJ#|5~pfXr=)h8N{?L5c{#u9+A4A$9i}w6L5VWf%1p(( zXw}>Xf@wS6A<~zDsXwS4v-QmhkR<=GCOGilF)6P8#($a((*3Clc$91`KD~BkCJiW( z_CWX>xKsAPDCX83m2e~TrHi={SE@bsN42ves1@Jj3cm5hd3=@h^aC-S&}wW7sW?xv z1ub-*v&3`21p6R0ro^Zb`02IL;Vd6T347J$c7rjGn{pMc&M@ySyyax7M^$-ny{+Js zjM0}elH$aPtC;jV-+7rIhIWGXo)C(VGYvZfqjFgFq$SvnrJzwr1}XzsZT!TtktfE% zy-}#arZv7yTFfHL6uC!6br6s8n7EW@ycRlNMarBKeaeT?P{^)J}Bpc)n?F0OD2aQna7&Sfz#V z2|YzaPunTYi<0D$kyy9l-kwBKYlm8nBV4|oSSE%aS-Eb#P&R?_yM&{ouVq8yP&MSSnT0I& z(_T74x7WwItQHHJN>>s;^uWtjjRYMg0jkEc}U0t=} zk+S`%^Y9*}zf=EZ#XoL}3zJ^7 ziky3_`ZQ%FSShRhwA!cot0lzjik6jBDtc5P>^wV6wr1)Mvc;0_QQ#k{8x~_xGsVoy z2B&Nh9BI^lG_z0o8CiwavsbH?7H)`ySbHMz(NSuVmLl75$-JY4TnCBQv{L7CZQ`+K zwcp_5(l51?H=K_gv-?Nbbaoc@?jiL@b%rYSpBdrE`@HHRd}GPC+ZqXjqyP@31ap(T zQvfStlR*++tL46nK5#|s*xC3-@5xLHa7i3&@HsYD+yu)wH7hF#&IlxJ8tuLs1?bY= zrjAA@+9wo;t%%K+yf`R&TffXKPjgCxw)~e6e+o6z{?eACk2m?|wn zAXBnWG$PPSPlkw*_WHp`q5qsPhbXb%F&It*+x~#M1r|{Rf1$cfnyWC(RDd+zF?=A- zbT1#W_E&cwRs4%m zTD>#dZ=ndN$yqX+!hk+f?Dqo!waejJD-1jU%Nz8v+>uHp1A$`g}9#zOz| ziG%6NSxsDYi#z(taPb_X3IG8WXzTlApx|RJ1lqOh0eh7*vz!yoZJU1$k?Om1vg5^m zyAPn`do~99iQmJ#wt=FukmeBSn=*p&spIytbn*KTYHa>LeboG?Vb9FS`QOjptpB00 z{2w1R|0@xij&{`5IHK=c-ThM_*&pRLtY`xsWAMjTLjriiy~LSDl7MUJAK%K(&JUsr z(hYMTGhnlR@uf>?*PSZ9IYj!$_q`#%SRmhO74fr`hqgZapU0txJx3KBzt6FQFUNQz z{|-5*_pkS@2Y7YQtjhBaX%zC7xIGx;aqXhx@8Jdx$vUPKVKI| z@?leB2V)b2Qj=)~JR(noRv0sqSUNQalG)-F@VK_i9sNxCzWo#n6;NM4pnbi>Y}MtI@1&Iws{4{YNii5aqK z#h;;=B3L^NkYFg25p4uasKLGWFsq9bpTm2J<@5Abf_zy>xF6`;2^94qq=H{M3N$1% zkG8Tu63!|BKEJC(c{~X%k0UZXh}q@yg%LzfY{$_GC(?1p65BxXuYwF-Fg&AaVB(G= zokfkLu$m*1tf5k~=L9k;vlK)~e#@}gvXyw4;%HTk>l@U6$D8W8K3iquFfuMh=W{7S zi?iyk(cXQKOVl;TM4mj*i`IJLC~Zi#C@`bp>wHYN1;UxK;Al1ZA5AT)yx@^Crz~|> z1RF=^gcRJa6wBs{2O?xYa55s^qK^B(rU+u-bIC1v9=NXu;E15Z2u4`sYlgHT< zR&CR5%8HeM>|T%O6x>#@snVu;R*QIX*Qc@f1NexcX|V92h%&5SA__so$K^>K4W|ka z_@uACra3|YY8IRoKLSm`O5k+`Brl0$k?2mU1PxLHt_U*TW3g%$9>F%W3)6O%x7{PC zDKi=VHFcoMWRJIjS`3aPls~$vb!tFoZlbq7L$Q&WR-D6us8mm(neoAtnfK%%k59%- z{u{35isV#UndeqIQK`?sDbb^o59MZwghLJJeJr*$!6kdHv8aT==xlDYvsJ{ySe zJOS%~Xnud)D=zA;5wV^hpcaa`&+6cGgi^zMxtC}F)rw@CuJ1MZL^VdYt`|v{VtuVh zs*b8CFlj51$ei0RHt?6XuN#0^CQn-5kYG!`tYAO0BN*_mbvVdvRc^Byyxf|+BN(U+ zs8&?}q1ClnA|sxDC1$8c`&>>X#Vu+fhKS;Q9tHpLumXvTE;~pvJTL&*p*o)cilrrv zXTm&_+sk%Xp^V-{Kg35^prmCjJLOu&2b#_4^@2Kx&Qs+E@$oy`4=GCtI#iidDk7@5 zXL&Rg3>IzZQiiaVMdGDtvp~WBExxov*Il~7t&NkFcU1{ia3-)Gc^E273M8tJC}m@6 z#(J_a6URtW(k?Z##ZanUk8n~7h;Nw&qgZM7+JXQ_H&2`MTCCUgV9{ft_|;8vy`?K1 zFlD>MHce(qmNv@TA}tH1<`w84xJuBvby?;Ton5_YHW^m9)tpJKe7e^3yRGd1VeB1a zL}{}&+_vrAwr$(oZQHhcw{6?DZQHhO8)wg(%$bvXlblKFPo;iW<*v2v=enq3G2Wq zbfcqc40umivF;GKwh0?|cDO|TVrgoX=EKpw7G`mF=1*Z)?4r>|eZW28u}&!KM{yTO zvnbXXHBhbSXJTKUY8drw*O1Jx+rV|`bldoi^b^V9RDc2-uT}@l&vN8^F z#bRfo_r7k?mml(*_P#EtzTD@9=Yj6J6dd9Q=G%}z+4s<)H`8}fRuAkCCEDSvw-j!s zvIPmU%^>MDj0xSagL#0qNl>RK`WfrJf;Zol<}!F?L?34~A=gkW`X;dDAG+jAI?d%? zbn8VN0JPL8TmVb^hp$^@t1E3Wg)Y0w!P$kieZ>L~!qOlqX6L6A->OhaKTPfWV;ZXn z)}%AnjzG(?;$uY1q-o<%tSoleVD1aRDZvqJ6~>LO8>C9L3qf@1Kh%{++e>eIRuYP?UrH4El_lz@#T+XT=IkiW&Xek4nBoda)xsdyn7^;mXdtm z%x0o4^3N=q4JelNO=B6yP_S@C?;2;AYJ#HyfP#gyv#9gSVf~J)p>fvD;slLQ5F<~L zqv;&2yc|zIHT9LpoQZ_}E_j#hE7{|0A$Nf8cZIrNZlkn5%Vv6jIcVr3v;ZvI=EZ%Z zfOBWR2PWVNvHCoQ`R1;?v{sQ^xgCd>NZ+2;+b zBs+iTlE*WjvM!aY+YNiCZ`+A{-!=6~z_|A(4vxZp-CG?8yB<*YIF}|@+Tl0))&*WZ z?fmG_*m(q(oe$lJ&HdZA5sxJuG>Vhs3Vfr{HPig$!!gjPxZfG5G89rs_4>laX#M69 zegKk2%KvR*u`48thrtgZw1|I>QsztSPMCas4QVKF)6WV6=@KgGb`>k=%vw##4{n9p z!+Pz`)8$}jrQ=qZTaZW+2#}@9wcYx5Wl?mCRU!2f{t}CRM@p9|+VmIiS_j>%#QZ0R zuMW&#k#G`ehcn|<)RncCzWPFt){i?O*qw;UasP|6Ctk@ccM^B&6N?k691o41=Jf#& z-nlw$vFW$nj- zuH48A8Q*S|&FzfE%lFLI&Ws88?WOBY&yNGfWoHiD__Q5B!z+8|l&7cfihB+7*6YOw zU$*Rx93PD+I1hKm^zHc6IXyY1DSfWF62>vlD?7t3$}xQ;`^l~U!(hybJKwzFD?=qn zWB(2U-2{Yh&nK@^g~-9;KP(*Vjbh)h8SuyjL7-QB{(<+&7ac5j2{?!l6w zTflUQISe*mC|JzE0y(VKrTemek1up;KTy9HY4jvpg}f+XmoKp7680kl9f9`YS4BYf zZDbO3XFk2j6F)m@G$)c`f;+BMTpJFIfYEc{t9t+8F6m|{6Z1eY|tMLf9bH+M*ZOwnY_^WMXAFxYXLli!2(50WR6F zR{5D)e+}(jRulZ()!a=|t|lU4B+7@y1$2nISm4=EN0IpLCbwl()5EK$Za1X|Ce#A8 z4YI?zQD%XsDr#u6k13NRlrdDyO(-kP0xpX-AX~F}G(}h}#`I0|b?Hj?;rR|#w-)u# zrj=q%*5^_Kk}jz8`0bp90$R&I>+V&e#$lqc^ivOGpn-A_QlgKtu6yKS=R>~wgcKL@ zg2==a1%kV1a{7f2*hnH`fB(l~8lXDJjyT8EpO&Wx=wY+QC6E#=kbt4yv1M$_rOUll{^qzsw;5Q}v zaKAZ6GG~(9;e^l{=AjfiY*rB&?FXY~H31}rh9h$*bpb|50zv}2*?n%2z(~QYT4|6# z&YB;!md;4oXltq}xO}lMVu`1It{~X-Lt3JQSqF^=SJgg9yB0F&bRD61X2C6rfdRle z7%eCREGJDo3_VR1J5d&QcYxlsKYd&LBkV<;!Y7*t{pem$7 z#+;rs?1cvDaB9lV@$}uiX+487SaMDmS5tuN)2LH^&$pUWfUwdpV$s^hiu zh|jQz9(kEu2~7QQh3)zNJ1m&MGOQQKsl2M}<*5dt9pkK%5s#T>yW>p}=ba&^`;zZ` z!ry<@BDWbMnFDwy^|A9|B{UzH1_))7_U4kRbsg&rfLhAIGTlXuB{IYG3S+crcr08l zb!v>;c{J24#sL|ODm7Xf0Zz!7Ma0yn=c!24lD?oN1QCZ|*&MNLbKV_Ni364KWj zP@?Qp$$8SgcIcoNuH5f_iMpn9a|@+ZoH}&2FE9BEupLZL81)^~a0`Wezt@rqmObLY zzesS7Zi&AxQ;KQ)E)!gVm7QtNlhu4LQR$R3q)@j{wKsr_vS(7Dx0=&6QCrZ>*(RkR zeXC~;<1B`1MQoKOno&%3AT*c3vUj zR2W0W*FD^F z2KPaikGeLFnjy_!NT>WrUq;v7u@hQ{+iClXQ@K^O@ZMGV&YX%d(2qGDX|eG(I~q#S z5(`9w=T66~--Ku5V{Y9@#~T9Xn0lW!m%p>HbtaXWH8(4C1}7vm4XQWm$?ZPKU$|V# zuh1Xh0!MXJSVoyW>($y2o*l4GW}?0_>F~1)F+;n*o|RmIDA_>rU4W$lJmMZdk52BL zP^R&lzAaJTUNB{4b9m8R#ECr~&}s%d-tFa(kGcX}_SrCpXYPgp2tKrv??j^?^I?XF zzvsmS*#hg+P-R_(G)~rD5ewj7{F=jWEfc6!Dx#TMP}zJh;JH0$0w+|bdZw1HDuhA# z>q=7a_>*~8I;L@Kmu_V35w_JyTAWP-XwnclCrb4{XU=87H)j$vv<74Lcd1H)mNi4?G?Mi zmayXVhlL)v+dPEfDA@ffUnx7J+TpbF_u zwE8l(xGyvD9-)l2^IOvg^=n#h^~v~g{1vl(Vm(GL!(Mx<=AKLO^{vSBy%PcETyBlm z*BSh4j{B8$3K)Q>`;8N-(TyJlpzoY}&*>pd7s>Xg4_7Fq(NjuJ^v>`v;JRoAnX664%Cv0+4$Q*zNxuw^VNovxC4X$x_o+{)$|4RAos9T$PEFS zD)Q;UhRew}8tb^&B1Q#b*9o6Vvo+!M9uLORd$}3l<2wE(-{rD?yS_O2+d*Fc!qHf} zzQ}ILAqs}YWKB0B~QFY^403r-sjK&?4E zk7DaMq^Uiyc7P_3DLl^?3|dMLOy-N=!HNOCGccRJSuj!6^|4{^mLW11OS`l`K&3&JJ7Y4M52u6Kf&4FY=w zUj!^P^vfBi*^j#u{N{SeJ_j3nx1***^Kq9Z<>b+ODLXifjY=;CyW0aKpEgF&vwpZ= z4tCYaFwgr8GRu&n4oh}GJhmUiC-wei@}65{AfSuOHb;219YR~`?t#83VM7C#vflLcyo6z z(K?`FZh~Pj0$#Du%Y%0ruR(~%uGGjl0tcg0O8V6z3?oB$wm)@zR7Tt9+c&87a;>NP ziax=Hwd#?sm@TxPokK^Ee%o^&)d3{>j@8Eg3dCgD&?5!P%ozyEzVxt%sxX%B!fg0!&hOmJyBgjad>KWb80NFlryN4tFx9FU3(}WI@yjzH`?p5 zD<{MggG!RsP3(2lo3E$R-V~M}=WEM(*wjfG!XL>OF0YYlQHVik4QI_}BwLwWK*`mV zeaOm+YYyl>{=<-xV@g$Mmu>#la4KK0j$|HBHkys%38)%4YEC)-nzKJ88bN!QDSMa7 zpO>35otIKeBuSO%!VO5}5JT$96t3tLnQIBjo46WIR9!->eErv!lB-Y2XNWyfKkhFP zgpAG>CJ8d2?CJDKCk}gGRV;t5;JdKddrGVC(D+%e#+Z$j$_Nc&mhRd9$Fp_vf zBO5gM3UsJl#r?ZC#N=AwY0o~E(*vv`WGFiMouh(thB_(Kz%b(54N|jYI5`!qJE}S> zZ%~+=2~rX}zFlTsFM^AbcB^4=_C_;g!;FwY_!Hn_HZ*ITbLyRvMBPLy&2NtlvZ3_W zLz&ENlI-HK+<^b6D%aJ`EZ0_|G$2wm6jm!c^R}a$3Qi+8+^1 z^9$lP`_3n@Bo$2WQ=R;I9hI`ig#{lz%B!RHyT#%;8%*nhxoG{mT!B%zb?yd=#tgv^ zS}5y?Zjx3gEXDWYSsSRUsK58wB(3&aT5`u(*EDFh4xAy#fCf3rMX73MZVWethf3iM z^{gi5*RB2iGFxpA+x1o&`(o(EGdtPjT+LtczGRgaPvtW4UFz|mFgaY}^;JG-Jb$SV z$b6FVsNqAAZ~F08bs;|q#8ii?w>yFO8O=>&bvHC4;h+BQS?9#0+v2tkmzGCrfSjbK zNj9UvtQ^m{4wZH-Ga1{8D8Sux9M4_>*b}gxei&4%lngEo_a%L9>VYGgaU}~a<@HH~ z9XA>hD!x+9+5|)KmmUFVR3_?J>aqgJwHcTlWp&8CYQM2t8^P<&>i80IHS@NkwHF|O z;#`W8N@xUARv0CSFVODXpHLbM(p)gC;#xtp=ROUGQT5Z62McM?rfTA|#n>Vg8X+j{ z1G^`H(;Da#3fmxcbQ&U$pc%jqAV#u4TMgpSCGCvQTN8;7!6>e)D7GtMTqonO-KV~d z6(*H&Y^YNw&+T5zyPf;uZ3faTBnFBHw<-ts=t8!H!YscU4&`g>DYo&72mMU&DhG;i zHZ_AXyn@sbdoRXplc-B9lxgkL=N*4J+oMrbn`X1^Dma>t?aH`b23#Px@Lo76N^JY) zyAQ~1lQ_vL2EB^7!uK4KaG zZC+Ox%ll>s&n^B*5WXP@13F;1t9cZ|y^a5|*hM>u2IJ z4nbpmZ~TBSHzvUNZ_(r54OvEdw*RO-SpToY1d$IF4oeIW;4!Qxa$eovvJszlaH`@H=2in!f`DTX zG7{Ca(I#j*-nxQY zT;WD6(>M9Zq;TcHf0OMv*taU(40RoJMIYPabeZF|EN@BOj|*&6|F9A5m>uy239Q!8 z6k-+#(Q3q;87WR(Y~9x)KxBNpAUh8c?(N+*!_@@fhT0t*LX2Hjzzfgee$Q8iEBY7i0iZ5h<}_O(rZQ?DJF@nl>RcO^YB;WMH7z@f&2Th%y=L zRSX+m8ZhQJH!Y7NgyNf!Il-ea_WFz-H^mtG!eS$V?YZoriD(CtcaD%rRzIE6O=xm6 z66DZj;Bt9Ic;HIk!-O(Era9LzLxNkWnv(xFoGQ7pjv`nICYI67&eqS zZl*i>U^CqIig~=i2fWQzrRl^?EbhPb{`0avGtaINxo792 z1#0EsQGQAsrBPAF4!Uv+WsH7`%kX<++P!(p$9CI6|GR}%4jQK z3yH10xrfe*s|{K$Aly@C0WzxlsEF}mc1e0&hXd^J{J4<5Adqfoc zyFx)#(Kr!%GAEXyE>=rXyzC-BV-b6mp%1}C6DG?(dFR$hpjTe^p(4%Bkfg@>mD5Cx z{a)ifR+2bhz2%F2uxaywk9WdNT*}#Mshp)vL{P5PX&%3;-xw*8WBa6y>I#ay^_2Nd zXts=?HHQw;AEl#;IU9{u!OY60@rmm>SNi<;70U>e0kT6JV<;N1c)T!!#Oek*bJJjjrJuOGT zo-7+`oK81BO1v+h7ZJ|GQg4`Qu zX#m5caaZHEYSX!elPe#!c?xqs#L-SOX)YzPghc)^Wo-gwfXuT>WlNAD4mB6#stxzZ zeJsi->o|I^aMuh<0e;d^ksx&cv)lnve^fhs6|_duRqOIN$@qpdki_8e#LnT#?H3?i zs`{z#aJHM1p-UMaw$ZTea{6#j&z9l zm@!8#3)PQxodBjP`tAI^JFBIFJWz#&O;w!ya*NLmBAOty_6f0KU_~0txqE()r^Ed& z3>6xaBHjpTf_!T138%Df8ft{sYLVB8*iv^UqgqB#N8D)9As7`~g5>Q>a^pUVDwKwM z*E7;~_^=PM{>401)jqbvQQGDq86p}~msiFCT{aq}lh>^_K@5*l1 zP35W><)&DmiE@>wdCcnh^LF-Eqw-|t{fr8YHOy+ICbdMCViyhc4ka`+)qpe7G^rFy z)kzy=_XO?P07&EExU|(=QgfDV0-KrgDNT*e+j4oeW4_(uwTzTuA#HT7w9rXxSpap4 zPth=JH`LCbZsK7p{f@!cIivy(M9ce8T;122fb!0EngzQcL((M;)boW^VZdkY=ggDl~x z1{Q<*vn!q1s)(oQl8l$-D%%+G8$wN0m(l5EnZ0yLop9|4*Tmk3*qv=Tn@Q3&P%-bO z-O<-WC5MPzHN$!@7I^aWcU*@QY(5PKqp1tycx=l=75gh0Z5l7eu{f!>DA18se{CD9 zaJn_RFQe}@Q$%XiEc8>3Bf1wBDf1H?2g|N~dDO~rEj)E^RI-TI-^N32l1LKM8NVw` zfD1#lbR|pYm)OEG;~8pWy6YT-u*^S;>xdD7yO`Ta>DH}CWDWUIxyefX|H^9vD5Q)bab#WL5Hd@IX=-3xe!L* zl5LvXCr74o1S#LzUs1B8o90*AK=^L+Ed#@0EttDqX%X#cK423srM1_b z{gqQwYusI$)4OorW^n}G4>qu~$69Er?u?7*?WLO}p;}CT1*C++CD;z^Ea@ru2`&r3 zHm*#O3sIeFH&ksxsWNw~4`L+%k`7#_FLgULiuiC;$o){2K?j#+EB8H7gFk5da}8I! zyfY4lGVfm`Py8JNiYB(4tq(3D+3@O`2U z3h{E$!a`@~s{?#UxbrfW#5li!^wFGsrA)_VpjI5wB?aToj}+igQ8<-vA+>JsNyJdF zf2?kUNA}Z^V<3w>J4YWk<|i_m#ay@J6kD+K#(_ujglHwDrXa!2F!;(my-?=QTCuMo zazv1KB80{s08BlLIgJEo8Kb-l1?eMo(J7jBm+faZ#jX9Q7>_B1xL15}R;0_6S@Y^!<#OU6U%Z8M z+YGC0?9{tx4$+eWTjDWleZ)Ibo9%7eO5LzwJvu~0HZZ0RK@I|d9D%LRBk9PtV`PK1 zJYV-r;zYO!S{QreWs&i>qRX&5syOR-aJblvn+*MT62LpCKghyNL4UrqU~wGiaMJGF z{b26w%mexW4F4`{?IiEATMXP7-`>^{-k8>cYWsgmW$p^JTH*IBNBa*e7!+>va?Z%t zS62&6X!BVL&7k}ob!hCE99e|`{~jJVz?o5+Pfa5n-M}&=Ljg~eDM282NM@ZJ1S3!IvYg%qztWMLna@D{6et=qnCp=>O1 zbP0bI823|x2%{^PZ z+D+3R$+&bRPS5?s@H^^MRN8##VUvRDK9|c<>pqx`LV+cIHIftyRyP=PZgWN+Tswh5 z*n@=Q7nmrcI3#iia`m?0v<)*2?x23FZSOS;W@CxNFf;jW9J6V&kf_5-GDvJ846mQNz>OLdy0kbQ~2ycVk-6~lP3 zmNSS@T=UL03rWP@Sst?PDwkIY8{T$zLzf%y=4r2s*$&k4ZdV|tQth*1M zC4(4cHQFihiTE!5xnZX*&7Kp7BKPL^et<`EEWtlZY%J@wu{)WkCiI7NCdaQ0dj!p) z?KIlusQAj8pIZ5SE{B3}>O+L$<}*RYv5F9dC{1_Vo)O4)Ox zU9+{t4LkX?s28nc$JV4&8Fk#=cJ{J&9sHD8(Fe{h+;0ZO42ymwdz<^+z{68^(8V>k z!@_5d;n7GD6yAGjNtlO*w{TpF3+XVMhw?ioCQCJ7f`m$u%N%k}WhZldNk5u9-@$iz zV%bR!I{8e2#ocvjvjiB-eRAA1=Xy-)h<=!HhSc}YytDpWN>3K%rbhRRnlSR&a%tvr1)f z8z^=oY*LYy*)_NzG>XGT;tA5$!>wj)PNtYmY2UJnHlucKf!ws&)=ukS%WS<=!3Fy< z;Fhz4%cxO%pcWfT!$M6n9dKQOwz9E$Bfuaf&aJl90Yi&q z^yFtR=?j);&`QXMO~(cw3E&2s9)L)ebTWtw1}ztJq=PxNaZkj0X61W&vQM5V1%Aee zJ}bC5-;+0saDgdggL{5uZm5*q{~q=<+qpD8H(QDhTBw%MbmlY-);0)f#=wMELaW7G z)M9%;=KB7u?mTeGf^TAIKEh|=%Hl{$laf!;oTvnttpPFI4p8npVQSgwDP{!;e6DwT zw2_lPVa~T!|>FyjqD9RriG)Qe~wbUe*b3 zb=zSC{8F(5ObiI)Y(dLyolsV8EU9=-Fec#$2zTEq$wCeqeFJ}h&cfxDKwIk3Oe#w7 z=9H&S3+^ZZ8b+z9sn;*ZF-%=YgA*M?J-fdA-D{;enHbasWH{D+;=V149&Tqd_Y!H# z&ciXFw`A$I3N|P7#MCP(ptCBptM9;Tu)@<;UoXPwq)Yg>HcDxhRonCw(;7QUJz1JmrRnGWQ2v-vdPs*+=~mKvBNr?_0B*^ zb-|!?X01!O1LGE+W$3lnu$>_+Zw!6Do!f_kom--mj_tfyo1ZtA9P#S~+n2b8DAA8x zgnM7=U_8L=cK%T(9c~6`?3*4#V`RwW8ke;-S*-Ubwt!}uf%cDPN44=~;Tp%^Iq#UwU+p79E>( zQbY&0MzkF1$YMe~q<9)BF@cfaH@zJ?h3PkxNFL+SD3Bcs!4}(=vkFol2{9|sB&c7x zMx_ozwTiUDo`uQsO|?}h!C>Sx6O8(5R%(=qLJz)P&j?qhWw(DXu4E`pR4lOsjo#3; zMI1cd#y@gG-W*?emez>v|81oH@8&BL3p3;Y`_stwf7OO;|C8EKLn?y!Zy)xrE&D+* z=}D3TR78*uzMF>mwf53_1q=^nJL0Ds6)FftQX)-VyMd>R9%fO=^bGOW-4NHHNcQ*3 z?M?#3Po)ys$5G+Vnl;r9sWTH3JfEYegzL$AO0VuB}Ezam8=_kZ#Hjad%}x>Nz?6Ft14P zy_h@yTCHHkBLi-p6;ZdVL@-Q3f|yHTjy+OWWqmof&(2I4UWTeWDSZ3sk_E%h0pao! zkruwemm^cp_=ch5@4~T zXniFE-|h5ky}oynH$Y3mUqk{)n+6_T+(C2$=h9*9hTXf_D&;hi-Q%F+gLa!ecKQv% zRX*FX%b|BP`@NL2OK?o6vV$P@fecZX(9Cs2B8;B90(yMZA}HJ zkm0z*CWn~qJpTm&A8Z)fcb3nUyDpTsfZiauXCE><*X_^Etbb>ZR;tdWC%;Bua=XoH zMS*lMs%T2( zLgNdQBFt2?bqIJN2MrY!H$PImap3|gKRj6OC^Y?rQgvCOunw@g zzv4HRF^-0VOiH-WyFq3nN=5TVPg-tN7D#!wGl1Pn85-(_5(! zJ(t5~U3$2_T_A&PNFp_u^}XbJpg&&X!#HPP!T`8v9$M&jI8KH$Q%wCXEc-+TLm{+B zOd@=#E^!WbdTQ(E3WpxjkPOYPYkN-qABimF4KZ)xu4O^QBEz-Pw310Ms8OuYNBMjK z@IO7o!4`4E4og^dN3 zo>%%7`|;v7EV*&u)d4f?9qV|e=p;~Thl~cP0iIch{Rt)( zgO`$(fLTwV;3N;O&kNN@c~Dri!{4XztjMf0Q)lyq73)b>;9I}#2cg_om2=2XEGktj zdG$Fds|9 zJ-Sw(hcT0={k{pTHl$oc+DsIfDX>Wq+^dq%rh#jEoek~DMRAO|I0l)LY8z_=$BuKs zZt`sOEwhW2i_C7?7wm5%TpU;v^F~z~9PS(*2a?p?+SfNuV-_ty?{{{h^znQqd6ox( zm{4?EkEuY`32l~&&P-FQ%I`MtT2JISE)wEfvj+q_y2*ax4tUShbUD1jNf1W)?-?Md2WyRbyRU6XW zZeKE=Ma#P|Mxt#4o$D!rM-I}6uu-;~ZVqShuC4J^oq&*`Q^F_Je7<0zNx4nki&03- z&8EE+_~Njvj7F}ObpYm8u3Rruh!Q(|5`Sm&TXe=D-xL z^v^q^u6-$9Xy4J*0_tNhR?_daky+eR=EDs!=scgQvM3Fc+HdzcPq)D{xGE`;g7621 zac3pbN+}<_>@_|8yRE9`NHmwzZ(q=+7e_k%B;vxulhefnm|TmzrVx>(Wc((opuf(j z(}2W9ALSI97+WjPZH~!h+eNQ@Ya60y6D?r>7ll#D&2k`!ze<|=_KS7Ht9E1kZO+95 z(H=IQ{?WDNC4x`p*Bvk!&s%7ljxeB}HRe52uoyfnMTUj*Di3|nG{A9My>hATtkOvr zq}F89rCAwY{^n&@_%&D)B4}Z*V~@;wSb0-gM{r@T(uM6N`JEA%8E;j2E;-V-nT#O4 z6fZk8!pdr(XDkzZ-aLg?7GQ=_3s{dcI(d0{^9zbl&4IlrKdueLQH%tMz-F51Zw!BO zf2q2k794-yEms(U#=qaQdn1jIm!x3)Ml>U=o(%+$g1s4B|5e!bwzNs)iVY_CRnW)E z+qeqRjmnhrI~3h~&>4u2Iscv-PqUz3`s)-TSPqQ-QHrJNLrOQz}JQSg| z+qS7?0q(?%s%mqA8&|0e?{4w)YJa&(b;oGN`tTji z=)yx3t73~xp8)0rQ2?e|8QmjQ=5-vHcqb@SmLn+y5ln)0DEL?m*oB zYsTiJ|7&TNqQSttbiDj)+k;ULymUYwC5-JD+li4ZdMRKroVmN}Vg~mb=AkK5dOE8J z8NWo7{qcOg30w1ldX>QPe!p4?`4`6w?bcnW{UG8}mOL zv;IXF9Xc&*JHRtu-lCXiF526qp1+%fy`!tW6bqf*eR+7&V~+#$;g*JWdPtxX;O4Bp zSCYO}y1oAHJuH0RkS4o5)Dc?dV;>8J;M#F~oCsL9`o41%AfS^Z zbTzhshIKi)4B8%pXTLulq=<(iUXFqeFAF?%1$~f{DfB3n;f))p;WnFY$2ueKXE@WW zpCbG7%k$$>d2FWWp^gNE06WR{E?$U!fC7wkwL5@3Ef-i`@N9ZCBTeX-;Q0if7#itq z<|r26t};x2c2NEpFqaIbbt+uuYJsa<3YPq7S{>U@E^yc?zipQYt>0IY_4g7XV2ZlU z?RF4R2uG)|`3-*e*?&Ucuz|%JX<}=|$-fG8DesIQoY48@87a}lJC2zk55-MJ*fP|u za;m)z9PTDt`eebcWxwZ?>?a^@64*Rr-00L;$rFvsi_N+Rr(16n?bvVV=K~bFvDiL# z{SeCZ5|)fGLsCkTcH`n^k`GW;nZDxVf=mGqSI-WWI&m3e+lbs<(>f%b3O&&9d8OP8jULJwPSgWtSm{3KrZ5~{#k6qdYY|^k zam5fnR1)u)l{u)~AtzgK;jhqz(ZmS_YK2OR-UF(q9s?aGbf;WiZz~50BI2WKfvRc!Vp~ek!qGt39@X3qpD~idzfg$2cG|zf+8> z96@4oCGaRl+WOGx%!f(z1G;T=OSzvax@)eE>wdT)klAoRXIW@Jz!}CmtK-g7zF$## zYm-pt)}QGN$s4&m2KZ$D`sC*FdIVmGR1_sniKH@>1J}^!Qsj2@_9ybhM`N$GsacAqrvKJC=tIqOBNK4ZczDo{f&byTRO&M)if(`OU!C zZZabp66&Hl(1O6DY&Y(etuI|E42~Mr-`2uqE@Or7&hlW(M2W(XoU)AQQd~Mlc>1iz z{0>-rFX7Pp^_S*w_P04r5u+}O`@v#g#HVqAuh$jbUD%IMD>4Ejo14LZ>xdLPeq(lW z8V@e}jcLG%`xoAWqy?J$s5L0gAUo5*mv^yfWDz#rCrmgQg+~oX8kh?)BbnT0E7yXD$5ix`ObqsiuXFzn)&0O~*&{cCwH1M~9^qhJ7+7dWn3J&vT z)T}l)FpazfyC6|*iIP~dh*V+m4}Nh1Cr%sH2?y_yl$ICDDWWENDY+gGA;(4A%7f%B z@$8V9>fQ;lv$!ba(7G*PhMZ--$_#u64S+@~+sCNmU&@!Ie+F4n((U5RctGad`JjAu z^o9|FI^j&qW`(#~u{PB+%b3wmcPn5V!6}Zs@0pmaJd>vD%$$YO^(hLs@4MZh$| zU>j{xODPX9p1o_$PtSX)RH-s9-X?)$Z4y(ElwS6XRyx6iV^Ix^A|}VTw*Ed+o%ttAB_)_{eL_L`f&Y!8(K&U&MY(!KwF2tREU4 zq5~oQOR2KvyuormelF^+ zs`bcCY)fS|TKh6pd(XeAnoa;KZt@z5V1WRCmx7`0&S}AzrHveJ>%P_h&GtJ5!AsKE8Mxk23&f3WE%44uFpmp&)2j3PMX1)>`TE89GH0gVwvOs(^McMxV}*^r zT1F1um9v=V*4O%lMySkqyI_r&|ay#Cl#tM*iury@Od`7$%I`;p=*gFM>(r#V2NmgvzwwS!R*gB|F~?Ko5iOUPEv@LYRvViufs`~U7Rvibs$382{}s#jb^>p z&^h2%C_T_^j-Cmy?&jW9np^D5e!`xZ8H5`^3O4J)5VV1VZSYL>Ev8!z z0lv3AltJQ-2pj#_$W_YfI+#k;qC>=hPd<@F7LJm9EZ%RU@Pm!ms)MG zv6X{#DC_-BGZJv9DoSfYOK?(1!bcOPC{u4V=-jk5KFFlC1^y%`HcTPk&rn%xU;UP0 zU{TlFcRYAhd)kXwgq|*#E|72*lq1azx#wAr|?~W+UY5Kc2M?9 z8r8=w!>4OnG=E<#o=&%itDDygqecpp8)H;ZP})FR*lFpsq#eY$9V<@TqlW!?*MZ3s zFj4CP;ROg*482Qko26sJi<)}+2V)d{*gV*=bvhnqiitA4s<8Pt!1BFG>rSA^%fZ~Y zS1*pK4aeWb7qt-zZoSN|;`<#pj7eJ{b5T%|>dg{@UQsgi_?FC_B2u1w+txs*#k81& zAf-*2m;{P${VP8Y_d=r522Xz(^!yJbwu}PTLHH7F(ig>AOU=Q~7^Hcpcp&fND}462 zCnaw%HkztJ0L;CM0}N-!`5^EDJ^hvaP>a-yJTB%7gl!OETkhn3VNWrhm;QDTkeuKb zNco`09U&HT$blYNAbwy3^c9^~Aw%wCCh)Zx?(Y)@+;j_1J0W>8u^+CdyjWmv7(N?+ z+FgU4m8T3gl3+?=($>097*|x$8X7ZL4H5vKPAbYfR;&GzazAvk`)5^@1XK0`bc&ef z>B0KIp)Zi|%fSv|)~N6Vsa7v{cO%F;$b<)Wym!xlQ*5)4LsYAb1v`Boohv#rZy1W+ z&Quy6cwB}RS3K)SIq`Kwh%k4p)G($)CS|@~drut3$xd(k05HUe;n?Wd2xkoUTK(P^ zdJsj%SiBhiANAhk`RLn7m`n;P>3tweclLQs_TT{@QJXEpUu=^jhGA^xT%$#d`zoFXDe6$e;jggtkRoF=tX33D4B{kuM z2p+lS0Wo~g5y2H`RHdfZwLKkWL6MoFr-rrz7Knp^qIWR$OY5gTJADs%0<8OB^%pUP zey>nyi#R=(`xMkTCGIQ&?{yyK$`z?XMHQ}4t{yO8`Z4R3>hK-*#!9iuqa$`w@-sCQ z-HdwH@6e1x0(6)Q|nL7?|^4A(yrXWcVElp#frQ6D^zt z(>%w<+Gk8_bl)+)Z%iv`5^K>bt^!#Z`wmSk;otkp7elvO=4x$4xN&FDCFV(#lH|q& z+XchS#OhgwB?TbfuQb|A+Y1#YW-LuTlOq7hIGyioG(pShT@a?Gnwiqt!cmq~cNYOS z<-aYx;mYhZL?%fuCz^Ik#5PXtN|>LjW`e)2j7pF?FIAPtDk@eIfMfBU;kp_2OwKK( z!KiF6mPR!KL>=gGN3*MRm;#6~LoCoWIiT6AlQCVix^Xf8C2Iod;W z5M6JiBYWW%hw15teo<-bN->HD=}KV8;RWL>I7<75mT<>S?X^O^+G%O=uGGS1xx-0R zjY@sl|7kJO9L>q5;OzZ_#S~$L@h$~`5}v1cS5Qt+ZzKsLCM{N;a)O+$f%^PmVt+!fNFq#ax5|v*qeyui&0_m{}H?Ice zZ~TO&nO9EvV}}Z&jF|RGn2NY&Ksd3%+`c3RjREch}1qEUgpMZY+Xq{c-sxq13>R+KY z`Tm#IyH2HJ{Kd1z)rD58MWy2y|6H?#vup`rUHf|LeDnPA3X}DBCIbTZz`xG3++CuQ zVLJ+qoVW(HuVFLmmfLO0U6#qudZ!{in%ZsgJ(@hK)_xC5z-ha?);L2}qQJ1F>Yz)B zi5)aOum|EcB9Y{gzqHMJ!ck5zcLU}X8gD#d?)Rpu6-t&U^u>(<(>>TNep@E6DSzJ+ z-(eaHfov{-(6?8pc8{j-Zz(>jLaC&0dQcNKU#OcIVD;Qz;08{=l#}PMGLeI7=gx_) zOLoEaI6t9>0*D# zAM-tB9eJVa!8WvfH3T29CGQd5|12G8yV1_Y5E#D>>AM>Et?Kor#l^r=l&Z|daK>id zP7jANdcJUmcRm2WVSPR@Lh6Z&a+QTnm4)6U+zxN7)X*RDpl4grJZsCES8lu>B)vhX zs`C4{u$oUH>9yskESru{$e$Ln9q)fgfK$kH4R3V zpqGcl5Vm2Kh7axVd`D$ti{Zu3)#S*3K7QB`%=A`#U5lY24F-$4`;GmEidOE=Lw-z8 z$&nfAjONIXy2Gg78cCfbL~3(e@o`Ot6Ss50DL=PXA40 z{o7g0$i(oUz)$x73!`HH-(XZ?KU>ErKU>Em4FvP<@%)f{h_Y(qy)AyAc%a)IzHp$^ zgFf5t8OfothRRNl575vcYH0}S*;{v=Lh)@qr#?Dg9*nPazP|?zWx7B1$929P-(t8~ zN_4&+51$?-7~9N%KR(``=X16< z&>!g;yma%6D<3nbyrNK=dfJH1zJFqxnsju#(%tONharXs7)*;HbktNo9G%!Q;j>NE z(~b=W*7(T*qz7%<;|{@KP(l?6RhJluev1nLW%?cS-#K_-8Ocfd7y~|6A+2wmKu(Wy zXl`ca1RC$D9!ZUrVA%zVfx}Fb9$5*Z?#>?{+UR`W9X_6?lOJ` z);?05suNY|lbFov69goEiEXt{_qvKq)Yc1i4uEfLAQY|o*`0Y@;ptO!{S%cc$zNt|=%`Xop#7m< zUdDpGxK{pQndQGb#m1}76WVJ=D_5Q+vSC?+5CUVUl`ZChYT;bMonnqfW>azC{J<{1N+ z$U~?pA2Qq}Pth-`L)R%qh;Pu)$(wHOywV_ul{4HWD*6IHfQ}{(sJ_eVxl*`(AKY-K zug_1_Gn|W`gEfR&*n~AY{1q80Rpz1v^A~|o6_0MC^Rbk@oY2BsVbc0jkVaQ}B7aQO z7c{tG+jm zDuPiL;(&81WK*A^t43zk-Y)&*vTOpzOVvIM|f+!_yr^65q zCd&Z$TZa|PIGmJobLbIP-3E%GGQh3gEpRX}#t(<2Hgl6j{{$U=?H(yahMP0wCK#6` zR;P$`)_@(2=4s4P9?lc)Z3sr|kA0eNaAdj6p!wcno3P$OD6%L;d|YAv&|Lwz@w7Qu zW7`Rxb&e3*!MGr``0F`yUVHce!I5U@Kt98e`pGbEWxJ{O#Y{Z14BDol%$w*YoTdL? z+En?;Bg1QSO8m=M51H=bgT*MtBZQ1%Y!Xec=E3tsp8%nvv?Qw<0jIPJBXbcNM{c;2 z9d?uOc~Yf-5j%+m$IBp^Oi5cmvC7}@pa2Zb%{v=cZntv%_!A$9tdbkF2I8;*S4BVg z4VQqNn1kca;sx1Kh(hLQ^G~4=zr8+;JS{&rS;t5()KNMeax(6_vk{a0jM91AGE=*w z!lv_&8ihwkrOIdC;;sSs&(c9sa@yssro zP!(Mk@gY2xgAA%SusK#eG3nw%JG7GIiME9A*E;ifi*m7;ne(`fz0&L02r;htb`s_J z4+93t+}gWbbn_6(V7W{F2oX3%TJvp10Y9Zn!kQ4lhwL?>GbInKq;v8CY>83*+@ymWe0zEWmmF#|V%QZ0P5Uwl$EINrR3 zo}%+$1=swVi_iU(hc-r^{os)9D6Wb@y*8OsagZi=t;F}AxkUX;cr#pX_= ztcsTIuSM%^-#y0cZCrY;L9pMcpW)Cl!7@v#i0}yZS#D=@dKmGT7LjJ9SB;*aRq^Ow zJc$K+P7H0RBdR%a|HK-NI58Pik`Rtyx2Vo@fu*4=6URZJ$ngmpB>_calgq|kZA@&q z!d|6w={dN2VWkkJf$(VV75Lds9`OTN`&yiTMTOdY)GL+5 zc9n>;tk{g8aDj!&M0~xP78C2Kn#!vQkw-k9i1V|`I1(X2Y4jCOW5G9+OArPlM|}Z5 zkz%bswcswU+_3_^rDzGaJxh79TzCUw(U(=K(kX!n3?i{tJ|V;zDv;yS#GWOLzW2z_ zAw4;y@0(eQ-_&y`=Z5l|=9_H?LD9c?9NdON#PKa~xL6Rx>3D(@1C~(FqIPO-24l3Y zj=xseFf=^6(4wBlby#Oh7U={<9IIQ^3_HH-4$P^l@~?9auNb-U8O~X68ZyC|IXAZ+ zY4lC{p+mD+`n`ZFqIK+G)~^^KnFqM_652;%G|7Uw3^#6E%1EO5<~cC7bE&U`yyJYA zMCAIGoqRymxbPV%n|pL_P45VTOsXs*q%DQsuAtYudgeg(LSG8KFX;Z%(E;tXzQ+Lg zh{u({jhYk%;aSmxS8SVDWn5|u(@E)-;6yGe3p<8(am`glY=ddHu~MZ-ReRz25d6FR z;3b8XdK7^tF1M4&{)Bqi62L}S{&U&E!$OZzQewr9k#NqousA(5P2T9laCJm8cuXaK zvPu?AWCQbeprBvKJtZtbQJ-_ZV5SDU2k}}Gi`|ihXC+xry!(^}Ac+JGTj59gnf;bX zZ3x|Vfdvoim@cQ_x-)!^7=!bu@N~{*TTDud(gfO3&tj}eD&eeluhNoGW9e!!3L$xK z?o`+ruv_C1WKl7TqK5fR@nNVc@I?2yo1LhCAgA>Z=Ur5m7#7)qptq)=! zh0@nx+5d(N6gZIK!9_7y;y>aYi`Z_-MqTHR()=a;u7^hmw(DKn`KmULNa1G0XusziK4oDHiH|8*nEds z<|POwr`8#)?*K$mhe&>@?O|S!9XDtN9E6d(IA>pXoMUz{1Ub~`rr1@2sk{Fk+rj*e z1~XtquEn>D3B9?im1(YPUMh~n86IW6AxFY%_Kv6fxfGo2&wo2xZOMwpWl>gM+TBUe zty8y_m}w=2!wlg$t649GV8J>|$S*}>X*aW-Xm7P&y-zI3n8T@=@M=kaYrUkPV45Fb zTsA6JH=bXq`+Q#qiJ*bjkdReb@YC>8fsJmQA^lbsigsw*__Zfo#zXc=pvH~zXAZm6 zzgO#IYdWA@$D#e2hbRK;G!t4bKOW`ftdVMl*nIwXzZYq=7 zc%A060O7h8cJ5)XMLW{z4AD(*;w5l`?v45oAj3-*L61U9F6TL(zg<61dL>BX<4hAjRJmAf4S;U66FuL)0@`#F}pz+y=+yZYOkak#Z) zR#ALfE^kKC`W&Cnd>@TG_TM+X%}HOcT5_zcMU_>tNVw^bOier$#o z#O?aB>x~bjCqMIMm33(Y{=RSdUE|e^$Gh#c(0qC`yy{KzoH6|rz!p9P7oO)#uFoDl zp>jL*3^gG#Y@v5es^nvww%4uick7N_%_cFUZ3H1i*v0V{iWE@X*OIU zj5|IzbnJ zSTIsXFg^ZD8TPO0>YrXW6BFxyEEw$nj>`B?ubcgUg2`!$MNt304&DZW@ilpIzPOq5 ze-&YoHrhR40mpmY*Wh9VLGtp(O5LZ2Zs~s6XOc8^o^>j`cF85*Tc5|oJG@kjqi#-b zkJm0fU;U@s{}_1RrrSf7x#)DukiIIVYkasqZwE6Ax!>o{dB5xtoU@W6>MJ@#k$89x zV(it(itI*pe#*D!5BKNsBh9jh)hJkR?Uabt5F}be>5yqiSXALN+eTHg)A>vJs)SB* zSDW3iU=aB^drvyt+s@Q5Oi$ulT~EW)M}ZYkX1Guo{@R;)A$67+Op3*d!3@Hvgay~? z-URM!$eb$`m2SivfNW{TSY6sT1fM;`gzO$`j1@&D9y|zJXBN3DVj=u7!gpmLBiMsH zx}|+9R!`QOd94d5$UdI_zpVopi2(|=6_(&N`%u60`A-i!9)yt6U_Z=ZGH2=VX=4y$ zS;IwJ@p&53IV8-fIIaG;u$J?5`Nqr*HSDd5`R@ugP%cvfH=8PG^)?R|?9CjZ@?2J5HJ)u(N)OzcJ)b_;y4&W zEkpNmN%*khpzPMwd}H=+($rcN%)i^a98lelu`6=!a*m4zWDzwdq`#?S>}@!xLyi$; zAKK;!xXc|AQcV%Oa6>9n^`JxM^q|wk@rZL7tIsAPH-cfUSh_CX_>{`NjIf z@RQ2xYT%Q7P9Lx|_eqX09~gEx3nTBhPcH`w>8jQOn9`a{YNkcf?uf#&;Jl z3)(8r}u@Z7=5&rw8{=WH-?hDm`az zw71&@552ldOBnAxPr41l70jcZXT(g2sUa+1o}JN?g+G$1NN6-{D1M?`3c`q?<1rUh z^~*}CdNNpa)457}3{fk8pp`WdDMoJb!DsAa=iWh7k_jA?Qzn^nqz9A|Zj0qCvkcpf zYKaGp9eG)i&#IX(2R56dR_CEy+Zm7II9_x_~$sgrhF94yGsOLW{*q z^1LiPVpEHyQXUMPjQy@RGwC1!H*uLzoiZTsZZe^$bhu9S6Fu^seqy@~eWIgEBkE)m z&Glblz|>^Dqf)%%3r6w{vDQ{%(e&JsuDBsS>(Eti zw()hw$m>&Jm*Bu}E&~erX#d1y0oY_Mi1Bfvo$`SV!@VrsnK-XjA-()+lzRoF;2PA6gDmZp~7L@wCF2B5ubDja-RnzTVQrE3)(= zLdhr$VqTh21wBC&mBT?i)d9J`{LaZ`i~@0jD_TNJo$WxxsUPGH&X>ar{w8>mCkau* z!O-O>JMD<+6PP18A@49={D~Jw0mC|%I4ZbJ*5wvXL=}4C2SnjIe5#av8H$~+Bg6Bh z0_#aa<(pzvT!Xyq$VJ3k^W+esCgCfG6OYvvf71Q67B7lRkUBK1Wb7yM=cr}&+c7KZ zru+-j9VR~G*E(REYKoA%hQ2_*JY2?aF&OpuUv2U*MgqzK&SfJdk*4{+VKh2~v$g6_ zB={8BL*RTfX@-Ns)&z%&x$}Z!5V|#(nVK!whDv~234z)c?TxkezgVB)0KZFl6tJId zMxG5@BCl^I$8>38Fz}4M3AmZhaKI9Q!A~=M=aR^8kfAT&-uDa6^F z043;fzY4=f>BU0%Yv0bLB+=z^*cnd4 zk3976l1NFb!eQSgjEDYO6wG@^#e-2aqd}#n?3tPbBz_9ovLmDspwd&mQV(7oIzu^c zv|r#9HD-uG@*5cQv;|jDI3Vw3H_7n9*8}c*+i5>!HuBc$x30SG z-d9z!XufeJ$q3}GNO8sv`P zS5)3m##t~WIw3UG01_s1*O3aQJRRfzY`nzHM|%O-FCvVM6~b#Zb=G9AoDb?|$`w$b z3#e}m>0_1tN~Rpu*D@Z9Dm~lZB5kjt&&1-If#r^wpNwTlYHGa)Byrw}I9lW;I`ou-IEpVBmU%Gi_%?s|^ z{J0_bbe;D^2Hm6~gk3Iu+T3hthN!%YbG_-`G``pxedQhOiQ z+^V02urJP%2y@LdBi-pA+_b$P+s<5WZl=lchRX_xMqjR6vJW0FtDE8t+}8B*l{edx zeknCmbeO~Qgev1Gd`5EtPU~>xYx(U|zWr^`!Y;kIdt#UgHJJ9U#vwM>( z@hP|(LwA3y0d~tQ;{NNw`jb*13;=AKo&9ZI%0ZQck53Zz^^^1NBA(6pK#yfNodw+$ z&6nxjfT(BvexsSU z>xu6}Ce<0@hDDbo-ixB$!kWd^ykwJQ;guLHBAjQN!lfK;xe?@!XTdxQU`fVS?e029 z0~auGntzFb4f@ijp<;k7was9Hr^S|d469Jd*k;S z649co2Ew1oF}U?p&!qpRJO6F+Wn^Jz`RD#W8WfWK|MI@r|0mv;#t%t>?H`ZDi)K%m zHc=FSf$vHfTqg~DZb*KMGt`gA!sB$Cjw0MW@<@+tigOhm%JmZCH@WwLNcaZIv;F<{ zW;Yg~Po*N(@#4{Xj!XAf<0}~tN`{Tk=4H;cVae5dR05DO_jldvt0|lJ{f86T!Oh3> z=KTF;$}Op4!Y8|ckoAaKVSLPMo3P$gdCyKH!(ckC=Nq}aiH?PbBNDG1Syfp8J7S0AU-wJ0Ab za^M&cN*=ivyVXh?obsd&AAXVD2)3ele>@WuFN_yEB0g*dm>9{K{Qlf7bG8dFuv2Mn zx>xFLU{1Ot%y3d6_RDyHxSj2XTaSvzn>V&ALYdkA4X6v?dKlF%D%ckI1PkhWfA_(gz}uGCqFUk_?|6*bJY=E^ zhk9^X0pH@6dQ`2BpO*5WO^_1^0&6e?G|P?4!;0C>Ix~{_*&hwq8S|rOvQ0)B_6ajG zkdko5C4uW-TE>hqo=7$KmlXb%JzmP=F;XUzu_LeS5n=?DD{`>h<*pY(HL0BFN!D#; z#L^np0U|J@B*TJom-;&}y_3|#R%~E=!6+g8>uQwIEAKlnA!cVVDv>fWbLlxqB4FN6 z4-c#g{Z;qo!1sd2kR%*LKc(o!`dBlWDJYybK4D2)g8@Er(fFY8;&E*SuH(0Ducu^4WUm!i0#!97a5&-S+{Dzl*;|m4>sQn%nX zDF8bI+i=H`!7(+7t}^~*WHQR2Nh=+EF* zLf8?{9>7i#tHMVetw>9bCM3%|DC22%V@4k;)Kymm{p!o1Olv$s@wId0Hzja!OYv8U zZB|rl@h2D=xk=n|){r}>Eo6w6=$D~`Z;TZ^)srC|S1vqyrXm>%Rasp&5`RR%RcK zdp2a)4R2xe2M}#%yj}11Z@4z9N3tCp+Y-B(+XGPF6L!N>^kv^v;h~FWjwecj?vr{uf`WH}#qyW?QKrpEjA?FK zq8t&+rAJ-uijizuKHA^bjlR_@o#X>;PITV6S3(iz=~`oTGFrth2oU1Jf>7O%f9$%fM2b>VBabAH2aUb} z6pdfp9M^^*Rr)HL1W#J%|k)mpF;lU8F8t?_tI2PCZUyCC_#ooJ1QPC+x2)1mwY;&tpBWVZ%^2-JC}C z`>F)`_PYKGd)R4nm8aUCM|TLh2(D%e^n`^TK;V^eF?Jo&qP!>d z4jfi~jocP~jXd;?6$KBzTSQ=|uoTrExL8DJme9zXey3Z-i4nCbYZRgw7kyL~n!8J= zSVkc4ZLAUU%4!r2I!)3F_+7wY5g|pYBde54Byqp;3eIF*NZvHtH!+gE-|{kaxaRR% z-S#o^MkfEo<d8LC`i@yEfMPq(GcW=SN(J`g}RztX-mv`Cyf0+Fj#s zC6?c(y;X0oUgbIRUN|2c;Ex7*t4x&)n{M8ZkN%^Y7e&ji z&)b`aH+-(9b2e$n)Z4f9qv3+hm&xB{>ZfpDT!VO#n^E})UvGAfji?snljIGi~lRYnd0}k6fRyK99 zAo|1)=NilRBt|SZL@tqt78caaUpGEn3Og$w&oGOWO7lxYF$Lt4aitW%u)xx zX2hdv)F9ne(Rk(nO>+i?$rP)N`Y;v)&8fr{R(A@KV`>6E;Qr_nt*ka~)XRvJQ!W+U z@X{(~g35R|ii& zF&s9!EJdJu#y4|pT9T}kYdqh}W!|Kpax002pfJW{Fy#x4}hojWDkP0mr zxOlU9cQjtvJ)oI0&O(ANNv4jF3aAcX5MW}sRy$0Mfz?H=hc*yijme<5fb?FF;BgfD z6>9nb;YxRxG4f;mwJ%_L=eB+91*xV1?K;9^1Utp~jKSot4$8?K3+N=iDI7Nlm~SIC z*05PQtSpi}@O79#&@KcP&(sw&R8+A|;Aj3mnN_aVbDGVJL>1*zsFwcc?FMJ4_brda z4lgl9-<{bdCX7~!@^#tGwOjZ$?f``kp-|MBOE;DfbGW{(v!MkpO|6Wq7cv9e?-<6bJJ2do#>5qp;_F= z??n~Rh7lDO5sc51LTDE&_AJ_w9@dW0-)mP~138K1x2fh@n(&lKwVQUJ%Z)`3V`JS; zjW}T!&QrdI%-h1V=Eb90TNT*ro8^3(k7oDU-U?JAXdQs6#TvbKc@AN28J+9jQtL@q z`)95-Ra2FzL@v<$(@snH1a0FmvsKWS@h{*!oen5i3FP{6f#?sC;M)-lPJv*H{El*% zWKkS{Fkj9J`F0}P^?`!I3-*=?#dc*7zc_&5_ltl)VVJBAEH|6gG^eIrldp~vnnpbt zvXHWkGrUxRi84sF;RgY!ESyI!u#ZkA@RFOMsJ67p&`}* z@xZgW#(v>aw=A~u;0{(R9fKRb^9tH~wSjZjQS%-VXkDmVjxh;(IRI{z6s<3$qrl}S zb1N~`51}E^K^<)+Gl4U_ylW`c(ppcDiW@Nr4&I3(Jaw#qG#vfH zhA*qmKF+V$#jk;jl5<$ zP89d+_AXVF6wjRybD1?-Bk$Re<8iMewU<<~%jUwQOG#D0IMyo<{3npTHPOfoD6Om#Rz7WV^YW%1P z1xzV)+O%`7eSdgMuI}m>{BnkDv4vRF89)Y{*s&A^xb``1qMlS~tfkCVQeUIuU-6fM zYNCKg^X={x?Kv)%IBA9SB^d*yA_cX@0%+#n5%mHF3T?vN>=EM|DwwNCAR)G>chnHpVV89|BEBy_@8h@ z8spaItni!1R2{UsDFX6^;NZZBWZI4{e*gc}+s`TJ?PNo>DXEJ_VSwTM7xbx2w^%X+ zu9c7bn`hyj7{InVY3r`fubX?gjBfpk70>tm-P1=v&bD(lRN!dWPpkX=UdxT6$8-Fi z?yuLIySJM|S6>D$6*yU}9vdAWj6~4O7Jz`04%}RoPA~@F8)x{nc0NoQIvVdo6W2nv ztnD*C^zNizaCieq(MPbmS&jU6Hv5P8Af43H>|8LryLs(v1`&HaFH~cWd7>|{A?w75 zGKd4cW&JDEvZj1twq8s-{QpR@GG66YJJhCD{@q327OX2h`!@&~_W;c8kGtAo*mV0XI9_5${^(bp=N1RQi~YUQ2(H)*(U@BHt;XhN(T$=GER6QW%u$6;IlKlQBPw`~W_Dcfe^U|uwa}DJ zKxaCc%j_Dy$@iPrquN2R3|Dvl<$r4m^4Fg)v!d6$26R5b!pt6iUarDz7gWfd4b1!q zwBin4q8*hv3?tGYRu3;X#R0G<{ve5+By?(Th}G#&u)3@!NTC0@2pnmGj^{}PF7I4wzFhOY_2 zF}7Asj52EHHp?I~vvV6hf6J4>{Hm!6y^?KS3unjSSe~M7ohk=Lv3Q}z1L5MiauU%v zCL{2Xd?R(N-mL3ty)3lEq-B$#Dz-leCs9CEIy7&LScQxES~(hVx?#`>5tD^8qPlL* zF+^5E!T##{?hUepX=wm{(eA?lz8D~X3XRHT5%kVHl_J6;KOjw+&lG}?%vvqyA;-uX z0A)&@>IOe~i=C7N``~F#2eKwBkW*-teY0Z1AHObj;tI_tZJC8zheN)~?@v|mK$)g)DZaMUBEYNGr{SFDC%UHGh~EZ5h~@Qzj3NW5;naq^ ztrU>vd^($zR8Q8+Ql*|-H2HCn*hRdhV}EG@8y3`C5nPa8EW`dPMa;RevEP)+riy2T zXf_57pvOhe=W8He$4!Y$)|1P1>SYa$8(*NpMv~evUa&2eJ(#7V50)JM{v~mjX8E8c z&PnEHHDRNXrDVOC4Cde`O%82m@J_AXh_r9Ju|wJadyf*?heR){(dUo7b6(LOqIP6w zhumJ2+1wCvxlj^Jj#wKV5lOfVQ$s8s^*0;>9 zg1vOE(Aa&5$>wOhzmQrHfOMO^fdyvKUv^&J(VXFc1gbT+(crrxw6n>ObDqw?3RrAC zfaUK=VQ-f9Q==KF3L&&ydO7p(A`$+WM#-`D{_a-tG6lx##%E#h+#c3>hvh;wUeh8& zvOh(bX?$KQCKo)6D~P6j=m+xoO%m4;Ggt3gi6DoopBS~@w`<&p*4;=Xa;3Wtm$D|c;Si-?)*uOoslP7N0Ai{>14)mkf#jYM zhf3Nx4hI5T3v(KNRoPPgszRSn$?-eD)pE?*Gd=bH+wOZXgn57+?_vBlEoeWT6B+w#UH{Zbb}$hQrr!pQ=I=Mwm&+*-c}9e4DIEYGzxh zEw=mulJa`cl*;${sNo**TaFd$KrYV5iuGM}S7M^Xao?hnE2T4gJh}0J%Xal&KQG(< zhzAX=24))n(naF*4BqXE282|6+0$<7;pEoDv&A8ICUdxUAKb64vX^1Mt=C)^ z9dD19)AmiB)3P4|qlFGr*eZ?yIiu7o5_~`)gjjj>INPnawoZ)UI1Fm)_xro(%56^De-kh}Hn8+w38Lu8+glkdXWP{vXItPe^CYAOjZw zqR6iLQLZN*?9GAzl}sZWnKz2hdVu*Yq!!#JpkmEEyX(boo?EcTm4N-E#6i3A^QiHC zY6wgpnvqhRi}rW9G&4P$mNMw6UrDoQ1(ZPMK#y^xv}KH4xyN=NagJB{jYgDJt@u?< z=EBOEPanq{u8cBhA3PfY)vMf8c1uoGe_$q<2;gO@<#%U9b7T{=K^Cgcv3>*aB~vF; z3s4j4%{zANGeA@4vGl~`-a{;(K+Uq1wd$|C9RBiF1lf-3=fuab6dX1FP`38=`5^3>OwROp$m zu(|UuUu~+6sAT-&V6au3xEVaG{2(NX1JD~MQ<=Umb}Y#YFQr4CDR@i4mUAkFIW{;U zvih?G`Y>Cvn5O)<7R#-1zV)MS88V2!pL<;4vl0CS@RwJUm~z{d`#7gQo$m69ss+;L z&}_auhII(Xu<9*ZGv@rRNG+^v`&!%tg#pNv5jKWuk(fiHt)GEzZL4bLFyv5JZnoij zDPkA6K0%ZuRK82Q_PZGnI(w(M41GQ~NuB68Aa7=Z0|a?|EXdthprOdy90{DiHENa- zoVaWAC9{INv>xI>loVjpLyqm=cyhXrO&+5@%e6t6e2G9FibNjCRYdOyniZi&MEPpG z4oMY7rV0yP7ukzMA(1RAq2 zv&5K*SV9ReIB&T~9X)^nzaWLGDa&1zEB6XRb5paCL+NOENCH|hEj4KbUVDN96a0m% z;p0DRg&a9T$k@?qAQj$9#Uvr`)%cf`{D7RoPFA74>|cR+byj{YDdJt~VUP4SP<8^} zCo0WGb5YiUn~EHP9Yh%ci+m~Abm9lN5$yEz?B^>JF;?_;gExl{OUz;O7K&42it&~7 zDd%R%EI@-PWu-#>ru;OSriH`HrrnZ5h1A*ylBE7g4p6esHfz|3J6ocn4$%s zRjkCz9t~&W-A?u8D>ZUbc3*Oa!C9k`bNBGO0vzk>mXbox^i^pwPN6@FYYx)Q?6tlS zskD^sJZb(>6e&@F2LD)zx%+|oxd-|O6^_F{+$2U!>Fg?H>zW3# zQfy_42ewvpO}qJj7<;D}UE*(ByN%WEUTxd%e%oGc+qP}nwr$(CZQELHe`}vF|Ll{T zeX*}9zoe47sHAGlImeif{I66ey|S1xUi2AaSGABngC@ZbAMjtR$46Am&>B`j#w66? zc5#xm27=ltv}sAu__5<)*?;%#ST&|O$GXQnnN`TF{{7nqR)->PmX=idgD#-@ux-Pv zr}@1&>rD6CZ=ePXL#RdBY;Kni=mGK?tV&-N;<-+>+gjp$wOL7stB;P3dElLlb1Bf4 z|DxpvH*kNY%29`qFU0Tl=tH^wd2V4M@@f*U1BR%u`C#t*gz6LLWLj`+W8ctR?T!*R z_WDR!v1xKoQ)5epmSM4sxM^5%eI??eWsNqu_r%EDM=I?PQv8|`wjpW$I)A$#Bm%Z| z|I*2)iDEfRb^fValz_vPUl0L0eyFjSt}H)JX#__1v1%TWTElF5)uub7Mkzxx8?}`7 zd~e@>k1>rG+4zn$g3U%8YI&3MyDWwf|t;T)nA={!Y)6T)A)d-*T&tlDGfMRs69(oX}`a_ot<*~Z- z;dTi-WahtC1PJ`Pm{8h@Y;KI(6uKSVP|p0ERqNc+dqZe+QFK~K!>^oTVfFE>+Fo2W zy)F@}(l;GwLVY%=%C^@jxKK5`ro!wYU71<4K_0seXs!hNFuLZ=Xl5P}_iC#ySCM`- zy8g4J+UO#(X&ofYx}VtW89pE&iQFc?Z#+P5`NCV34X=;wto>j2@uoB{X78r3RY2!f zZC9#wmXocjab0h=CwvS2yH2(6Yf877uE5W1s&QF&q}sW}ve~;hM%FU9XxF09k7BzF zt%Bn@m}tP$*Z;C!5Yyrx&4)kdwGkB%eimWiVh7cId)FF4-|w* zNRx1}?VDNfiJXQ};R^ERy7`l~0}aQxs4biPu(#Z%tS5tt?bhAI_q@Jc+8xsRx(mdL z;3AwsJ)|ccGQ37=eInN}br`}*H|*V0ti$XaLv?+s)3_Kc%zz5V-)$7x?YE_Ga?=OL zIVIPeCa{w>99FKxeLssOU_&_C=pSz=vMi6L!j?M%p-olx(OWcw99bjBxHALQxDdWV z^+J8)A5lJ}UTPpk&32k~CvixW>tI=9Xg3j^vy#G|3EO5k37h=QEQ7qeC~|z4{@KkC z#~5U;DW630ue>;y7CvjF4BGO$qH@J<36u;(rt1#o#%tx3fKQA+Y1Z$Heg92euNU7p z;(Ny!>^w|E7^Q8YFr!VfaVp2L?^yD4V-WHoMvHu24`(fUxv+2DxNH{>BUCFzSgG#M z)0^r*k%U`ulJn>TSm3VPIM46%BAi`Vu+7iKi!|Zs<*c@}(w8o<)wW@v7tKz3i6$T!DQv6S%HSZs+>? zzF*UK`j%E2yqxmo%G}Bl;KVc&+&z5RcIwX5fqp*6?#66)p@OjG|JhrDC!Nw8Z2;qGOJ-pIgKTccbT6>X-ab!`C8c(R)MNg zV@mjj{6=Zo&V9WTjhqeTWSzDED|QXI>r0Z)iW_hFZcDW^l!UKw9Hfv8=g) z&<1F1%ic9fBAmt=%io|l-y0M0r!&y2yyBn=mr`DrE<*A_DpEf*!DibsQf<4iOc7L& zYt>|SxvMdaXUmXeiIQH*7m~^_A`Y37xjO!3d zlzG3bL5O|}1+xWh9teYkxo5z>6prMS&d34;2I%0u1LTLigi+1kJ`0hvIS{snX0)~t}6J0Jlg z-;?pzZxbTPVe1Nw3*#sUQg7^vdD7DYasfvdu=K;s37r%NZr`{Jb0_?V9Zz_HX&t79 z&GsXmSvv%UkWO=j2p&M7f>QsMz1RUU8i4C67!tar12rL7J;3zA06H6Q{oX{f=dB)E>hc>Ae~`5V{4k)Yks%-e5(o(M&HyE{26h>1H+S zuBafKO*b9W1ynRf*o{Z@9l0R0Uko8pJK)Jo-g>`%4Z?eIt~o-0=rwS4JvcKPVHAsV z6brT;2%uj;yRlJJ6g;EGf!3e|o;Ej+PpMfC9j(Q~9}MPg*=B~R47yu578F<3K#J{t1eMGHiFzGK z%l^+P`!T7s|6Es;55{1nM4_w|I+4QBtCs8YV_UEF?$h(^tW+aw8WWag1a1;3+~_r1 zNni_pw$V5nyFvf8Q4pBaI%!ZTWTgTN!!wc4WOKOhI`6h(4d2rEML>Ev|+sUL+)5)>y*6#`XqWIyt z_SihJh6C$^Mm`GWY3HCjJzg%LD+*B$jUYo8>B&Z3+B9`@Bgne+?|g&S2O4M(x92?Y zgHA4L?c|QC;5?v8n9L~FF3buW*I0UkZTS$LjgXvZd^fSO_}duvG#rD%!6$QtI)u90 zCA)4f&+9OILHztLW6G=k?KIo2^Tprd=U+WaoblNg&R*wlL_JO2T}{E>pK=LG2Xc<6 z0$3{aB;`h0r6efp2=>`y@q)#&rX-Zk$)_~teP*a0#HrO0kmB#cB$PrwT;dBQNM7jT z9luQq+vy?i9Vr%wrT_v|dpZG0Gv9#(-F@Igrb%1o+Cwq$TU~TbBF$I+JZq9{JiadRc3f)e zrQte_EpJ8ZTNv7|T6&|KjhVQ8>^^9Ruc%TxGRSG1TZgax0g@4CqF-w^#Z?yHGl{A% zl!G})GOko*sf91@CGH6`?HVpPD!y~w0~Zm2wrBQ=4;J?s3#Z*_Zl|;JkuYuX7QKE$ z;23DPk6%#8snE{^_PrTH;Q0+g-BIv*D0n0`XfN={s=?32%aJb+I`>eP(uBhi$MJp#c09~udWa%Czh3*<@?+-}w0BvUJW1p}jZX>=du3%^X2y@V?(J zFSWin-=nI_`?Eh=JY75I{aGVIbH7BozCZ3}(S5^0S9i&aPgj3-czSofx^VWsC?|lQ z^Y#~Sd!<&)+3=flmKZw4V_mYEGnz66i?(pc4^6u;_YB`_ZtrIp@VARTy;u~nc*`L% zvhnsjH84N%Lo&xHy3~6Iuh>c8N=L7Wwd&6?Ut^6u3dQUYLPBX2GJ=Nu%gwEj!fO2f z)b-@*e2jC?K;+b!KmLP!_fj2vTCDge z99jt$BG1V;ivcvtRJdx(?b+WdS(G8Yl1dujtP*?@f)$24}erREplu8f1U|BFF z`&XD{-Q7VUg7|Q~MWpz4hN8l6fYjle11%B8Gf`YXU%UE5gI7IE=F#p9Ea}#mAS*?L zFPfOs?m4u5q#QDv<_5iHUP-F3R0R4gFvdYl#x4kxsR0Tq)ZRzrYSqg+R%A*nJJbjd zqD)#V&i2@V+$ZA<&lQ|Zj!fbzqbP$NdrBzjDfB)^5g)rgWoBfMovx`BBXu0UlV4;O zJlKklfp`;{G!Jh_OP?&z+P(cERgH9^;gy*v8g|$cbuot=YND2nT@0uJkvm>!rj%5a zgb)g+FdHzqxWgixKFk!JOxQ7jjaG#sf13yo>R1SHnj~^g@J|Y}KY=`=uak**_%2vGz^ux{}oCu*2-qp5|i)XP_m7#&q#Sjpd6Pk}QP{S^~J~j_c z8iy}manD1WG>3|YSP3n+cRr3|9Th2%$w&wBf`d-LYV|sia~NZxd{~i626UNXiI{Rg zw*7FVrw&J9N>YX7HnBN5L*XTx?2wyR(T~Mr1YW06!y;-%gSeLO$VPloYd9VmYnnL0 z0GoG~)y!fM>qvk~LrEbr<^NXrkKK0N?qrs5-9qk@GulL-_!Om%m1J#yQ4~8?NxVgh zTQUXBp;+7l#dgW4>tNj9kf(Ts6z=-o5Dz?;n`JTMyku(9r_vpK#%blyse1c0^y zM!ZT85rih4qcA~&Zb@>b7z0g?Z31cU`uFjj{Na>h6+&=JUT*4jwGF2Dz;aYi?4ZOCRWr^1;9+D!ih(I2CU zEk_Vv^Ge(haRV@&8BN@dvqEs1u2ZFEkJK<|P6t|d#9~OAIwIZ(q6$5wD`-QyE39f% z!U##VoFx7lg8Q=-iLM^pDCJmPsh$tg_O#wDIIkSmooXg7jJP?e7U*28(@*dDNTk&s zvWJlH0ElSBlqQcz(vn4fTkj4wEp|U@f08gKGVL92DSOOIohR~GlP|1RG$3r z$d?J^wi8H2OD;&NM&YWj46fvoys)2D(aESIKsFIZ7d=@1lu>&{(G zty-sqXYzwxg-R{%NMSx#(6uq4{5U)mxM71~Uv~FeZ&IY%ee@0TNM87J7NnsNtO!|s zW{EaKNis~k|F1R@=rcm{h6D(wJVe;`67K@%bs@-Pp&Jg!FbL?_XOW?Xc>Yr z=4I>$oY=_6Aj`Lz-ON0?Bn0$ScXEYHKikZ^*x)_C?9SWmNKyC{ zzojOipNbiX>8RE}d31$U?`Az?J3OhBE(oAocunsWLRSH}V{0D2Mgqe7M`}ddR8r}x+K^<9=P_NB19NdLAF98qt+b}z2zgDRH4FHEjZyD) zRw#7pJmTpol_o%C2U53w2GS0edqX~Ea|m`XEX#ict0E?<*ez451|}S=bF>5B>p+e? zD&%BQ&VmSWIrfaT*)zNkZJ9f7O}{)29DxToGV>oh<$nZ2=>PtB#{F1=UdeZi(CMOn zHy!yRJ#Cl&z>$9Pq5Mo<-@J$6sg~bIKG(*5shjy0D$Tg%Mn0nlc+Y?1OMh6Jfz%Rx z5Bt$y@I`tuKh+K@^NCT%?*92$)un0@^u>kf(q<;{X@%9yw256^-Kkl$tev+RJQxxA zDA6snpvVrX)arnLEgSULto{s-fu%F%Lk=vBo<;OI&+k7J4u#l6$z)J9_?lAhXJiG{ z(Dv5wL(%q8unQUG`&L+AU=D0=ALRj_)WU9uQ-uO1yw6w9jg%csOKcCWYFzVIMF z%mfH4^?M=O!iNH}a{>ivXieNCRlp4KkVx2HNyCwU zPkqn~vjbm{a3+COxtkl`lGV&|96>PbLjm=CWDh4|*TO}l!<8VEwH)n_MhPM+@e z@$oyMT~KhnUJ-Rni8cy6Vhs}Y2kg-8&$e6@h|Ch-b9`ceigrWuwH1=Q7>BbD*nxSF z%tbO7VcH0AaUn!$bjO?*mz1&`Iyf;E!>$jlv!whobuh+_V&)&ZgWSxUx4ICp=PgL~ zxkgw9V|0~>yqKs8fX}`gL2k;Cn*X_;kN7yh1Kvq{R;pD-dFyYWvX1)JImGj18s*@( z?#lObo#qZu9Clv@5DA43&GU~Q%2kF<>9kOQZ4MJtlLn<4MciQ!gT;AgWLrRz%g5 zTryOi3Bk0GB)svGD!rHJo1r$698)75hI6pv%jhA>^kLv=NR`b6BnjaT_v7dpOMslU zJ%+C4jD`hzi=o9SJB;}C#d3{n*xcp1!1cwdo;FK>dH%IPPJQa3r&AWCv8BFBpMYt; z>I0I5T~Hl}BR9h6sUsPnECYj|K2D4S{Hj9?D<7kEyo17Nj^8-B>U72$r<=F%Bz{;z z<-EN)1de&(s(u3=00I63!!5;8&{)~ z>R;1Z%O+}@HT|9=eE<*|#5!qCYSyZcpg-gYFL}=bbJru^!yP-Bkd%}6#-ii(K;nCM^-P^oZoNCt zz@0AM6e$awgn=C&c-f((%jq&9$AG_+v*?eL2Qok);3hZ$merSwzA(b|$u|AVR(a+R z{9`^&F?Cl{S~sBkt`~av3Rae2W8D^H7q6Hs+5uh%C5%WtNSd9igf5voue~JUv~aWj zMQKX2CyUj1W=^IWM}9cxJ6N6@@0JxXiuABkf_?CHoarOX^PwMnzO(f)5HtT_os`LZtqx#~kzZ zh$#D24?+iDN2ktz@pV*JNx!7MkR#z3tIvgDP;9>AQ&}zdnTofh1w*$M;pn#X+}GK{ zM9-7b{}JDyam2|Q^pkavR6;1s*F4ZurF8Q7nvNyg&u}-L^YW3Sp)3*9K=7_8ygd}@ z0)+$Z&xDe(R&IoWRNwrED}JdGe(CS5qWHCdd46J#0hz>c15 z5UgsfO0@{|>~S_g#zqjpNBW|WlnH=#Pc_bk6SFoO{P1-F~LaAr5*)YSNKa?_I}w1 z%G}#>zw~rC-P2ruTfU^vcA-ugz@smwQH}xpQiJo@<6Q(3d+;{7B$b?H+iA62vm&$P zo8hd*YdU&Qx+OBFDnKOk$G;T&6~EZl$oHn!z_(-4hv22KkK8NlQ8E;XXhM@+ z7LqjMj0c182g)FBEkSUwBd4B!d77_iPE$Nz38sGIXdRvBMZI7}7u&;mO+<}h?l*h4 zVWeQ>TiH9{t^`eZ$y69^zL+abu0lUlUY&j@t~nuk5h#<{iIc-NFL};$lC|}syjvjF zy@1+=Y@s~1BzysFH<83+ah9DolRe?D%7NJ!0{bTNIqB|43e`Hc(~@{^!(|ph{;@l( z0If({E!etY=ig~Nya274C#!$jTIIXu50csku6Y5;3WE6KItdbnH#V2N)GJ|lL7OdE z_?cr5bO`sp=I3FWZVKl+H@Ma-W%bQo`zV}0n)Cr?A}(U0-w`mA;elA7evXBV%6PUye==#`@O3+_I*%#Vh|yh2`q*JNJ=i zXk0)T-lc=AciRz0#%YrYB9Cnz-HIv~=d(0#oW8?zv(L6xt4Ol?u$Iy09H0Bj{_sHm zl7UN-YiD0?ku`Fv7WruU11obPjT_uC2S*+YkJ z;wKs1yyl`H_=jTeJ-7Gs`}}Kik$zc8;lgw?*RnHbS(rxE6AAzIUf6=KSgrQ-DFDAX z01{ew*6rSK)*(2wJW?Ylupa_#2;w958ziPHY<0fEF3^Q_HU_O&R^gzaNH?i-?5RV$ zsI4LxuSQ=GRCN!!wQ>+L?T#_Z?VkA4A&L6dzx=L~h2871@y&PFE}vlmAs`bcicQt} zkR@k^VF)DrEQjIC<7udmnuT?To>uD#WzKbBpe^`zkZ+d{3?f((-yH7;5gY9TB3ALQ zMT!M3#LDPDlzj9;6EF(k_Xyp&#oDsVJbjan`n7DQ7&!o)ZiQY@c)&TO7A`&nFCL28 zHeK~f1v4Cg2-`Sz+DweeFrMlgBRpPiD#X^7_?tpvMY5nrEzY(y>-22crjG0~)$-63 zi`br=#l)XF(vNl>VGisgg80qtJ&HIR&mu=tkJ{Z>e2jSCUq-`oV91vs6vPo^Q!I^p zSEp8jSv|CuOd(6HWq*(0_K|09g9)=DEidJk2FwR1>aLMIdYCXc&k{P(%11n=deAZ` znlr^I_>x62Ho0=uZjx;QkBQanSJ({;Ca)(+@#cG%vl>^T0(AkZOv7Ap7-#?(%n^Op zpmOvxBxG6s80J43ld^z^#`;TTSDQ86j?a|YxAUbH$kpdgP4weX1q(kYGn^sHcqAcj zTVHLRFF~AXZ&p}6rYE%CBlY$Mvxqvy6xUf12zgO6K%PM>W5eIc_!Lp~$0NDH?XQSb zbR-i#aR!xXci;_jxsz40!)}<4(FqE0=yOWDf)Y-Tl0w5uA;9ScEL@gbbQLRGEx+ar zFFZ3EVPa_UmVu3ScybP;#UfBvk8*F98TGlwQL@7$hKxbMfd5XIZl}EoESIu&1FLBv zSt@Zaa%WljTo2QIg>*WiX>l(Xx$eLP9BrieHr6lR2`yqX5jlZ0| z!_Ths?WwYg4>5Q=`6<8m(AU4H_jOt_k^zuT-`A1Q@6I9pXWu%fvQt(B0Ht?3cB?!aOl- z>Ma|*05vp)y)!jRhC|8enu}3XJXHOre{va+4GZT&#A|W=7tzwbTO+;j*Axs9QD1@z z?dFMpe|2fqjcTE!S_r8)QF!{6Ok7c-jJn0^5CqTL!|k_v ztaxjb#|0G3$GI9==w?83=0$#QA(ax`-|jCN2MuW&(o76kFZZz3dlB@cId4_ z2oFo)IPQk)=J)~&km?w{C0n`x@*pIxz-uG-Wo19rntW5d$Nz@1ApDicQcyJi{gwUX zH@&h1jn!6(EbZc@-Wzp5l-|0_^kf*-QbbBGkP{n1^Qout8>EW(1IW)ft#I_FC17t;Zb#zk?_ zq5vbHBY2fIfmJ(*BLTF&WMNn#S(vw`WN8u%`Bu7Vib}-wH@^CTD^Y)t)TNRqA3>Sp zg8sVLd|EU#=IsE53NVd25B)&FP@5#}cY&TrKl#06(A<6p@g?%>8>-m%p zD|}F&bkcUo42^+bJCTE~F&06M7jp^D`}w)c>5mmz;&%&HSM9{%Q7&NQ+BzZqh?Cjy?@}vlgZps|YaLbkubb@YxN&>R%WKfIlAqtm z70i%MG@@)$!fWvNqb8EnW+R5KN!`EO_4W6=N%X>Eo)oTNvL&raAUTPn)+dTxa3-NT zQICgz(^$JfCS8sePYVCKb-X2{r1V3vc4-#|E7ak(4a$q==Bf^5F%N3vEw-7sP!;95 zorq^JTCOzNMVbi4;AV5e`5R5yFx}nadd&FzaXnq2!7pT8ESf>hmw9JYz!b%&kY4SN zgfQb+A)K1@+8rF{cyXXdAxD6%Ed{s z{>7tj4x3x4WlYMTk`M(5wY}Rz`l9E7|slutIpL+w5Y-o-0 z(vn{=Y77;+5gBO);u?$x;*^#M#yUrg`YTxk*Nb-qh~$jW-!i^f#0?Oyad6* z60gP7{CiEG3yT@3eNH0C2u+`_VyR}@#4OSv8QUA*E9DkRrN+~yfL33TJgz#%!!fEU zu@O_8_EKFhq%d(a(?lX+lP1cbl`#^@+-oinX_fSNnj=ZZP%JzUOODgZbq)`+se#!Z zWut|IGQN|}t&@NLdHA5x9hf?#m8kPB4IedHEP2$?>Lia62w1Tu>W{)zx=?*14R&`R z$em+-F4rb=FzjedvX`_eK_w9&)O%A}n%R~a&N!M#h%o3tjareJkmd5OX%-EnDB4u@ z#ugw2*`+opi75rUpp#2Yi1xPpA>myEea6hmmY!%9X`NJ=Hb!!@RJ*}HVndqAHTo$1 zB;mKDzQh79ZuR1vu5!9&pvs=rg0|?GbC+h&lim%!_i5IejeE2hMYawq{PcajdiJ&KA$B@ zLL=9y70|YfOX+of1OwAv@}z1oqjs8iM5SD0o+kFitFOr)1)b zIT_a||C3X?Tn`Jq5Rg@z0PZqgV_i7;4mWG1nv$oavZXv+ex;rl^U~=Nr!qzqM@mhC zN%)N6tK|WMkU&UJyfg>v%Di2nZr)OW#zjI6U;2jIv;W59>$kH-;@_DxmhjOwZG@lM z89)_cA}e)PSi?pO8a%?}%Dn0^q8O@$TJ{PhD-)X*`K@AZ!8LB}>0VZFr@+RFPBQNz zFHbqIKmA{wXJ!(MYa;_r=NG!~&u`=Pp-j(-3n;C1kz19X(5_P9YJz@k4+Lw&WdS~V zl@^Y8z;}!|lE>7Y8g*Ajy(9~{Qx(HbtPWhx@r8Uo4J$f!xv|$8IMZDr9I|sT;_cp_ z;to!xMoyP)o>zy_djraR|0roUU$MV&Hw@vTejeDD8K8~mp;ATMn&WI1k|kg-HS(>e4b%HQ1^F)wqb}H(fDU+)Kb>gwI+u;#$=r;gqY6t};piWl;2TC!qrdnf zv=0Fem9>k$0s#D($v!bmPm@dNp*`Cx)z?^QV$bJO(knN>1x8qkn>!~p7Vh1jw>121 z6lfFh!zp8o0X%Y$2xN#mXV%xAJtNm=npa?5HZ`Jswul@z3Xm7l>Zld-BTFn zOpzRSYo<4&uQccyFAH-u&~}!qc9%>qI7s^iCHr z?5?K>v^V63D38>1#CZk_nsBU5RAwquY=?upIoEf5o#-F8!JmA^3E0|^0I@Z8h#vV@ zDjBU)Pp?sC7rEZx?P$s4jeg6sPS_*tUg2Lm0S3g|sOD>EqX)WWgw}1VK(NmS{D;>` z*9x#&tP0XJWmigq(XxMiH0HRx(ErZXNjuE}@YvH5ZQU$@j5h*stJ^SCSf1w`{I8ER zsVzJpqpyN<yP4Jf4zhFs*+{N6#d}~`F&bNWvePhw@15A>916TuTzOaZ}%Qc z?TmIIse(l!ubNo!uO>Qqm@OdwHFj7w$)0OOud`Dyv&Z|-mDR?mBu1}Yt4f*nyB~xV z5p=6#dwpEQFYw=zl8Gx#u%7rvYggoPeW18CcAkh9HSYmVBGk@**~$ow*z0ViSO ztI|L%I!S6RpF(|QTuF4J5fowT)R~OV-z+4l5N}KgA$ENAe`&k?Jh{k|>CihP=#hA-|XiIxLe3WX4~)kx_8DV{|&VsL>zXEufiA2}hvu0N-q zF`)V07Exn25)feUI`wZn21jd%Wt8U)VAt0n^inQB9w z2Zd|2kG$6^X}9ATbQ}u6Xu-+K9&;;E4Yz^#=3XD;+}MI00Gay(WQ$5ELX*6%Cf|gbZ0nB5 z{b~@q8*M9AC*$IJ^x6sgW{H}q1F(#2{9M_LnxVpqm@6H|7cr}Rdbh6Ky-{Q#)^XfO zSFzK|ZUv#7PX?Ite8j{Hn}Cp$?PQX}9cZ5TO|d9{Wra+`y^Oi8zSMN zf)0vWJtze85=owKI{k<^I-ugTS&$0`H+0<4h^@Xs<&E}(Nv$Q0$YDa0J;c>_g&x&c(#6VQpNb+#uN(Q;f<2QN_c8Z8*J2#Dt|U5c z%71DRjE*h0wq<}!WoKB%=h%)Hbk0KfK5rwA_ylG3;I{j)|40HE)h{>rANg)gIr=ZQcv1jqiJMksass? zkI&nz@V|k95_)gNWUcSd-%~!VZ`@wgRNbGqpp0T@geBbtQ z=g#*`t(GUU;gT!qvTLd*=^m>avK)XT3Peu&^lsA5K;q+o;VW5}9V=V)AojhbzEI*^ zVkmkI(|0EC2wP4adL!j5R74fTd}%N;Zoqq%D5fKJhi7|JK^fSlF%1=EfPO7EC=*@9k?%sifw~%0z`G(0w~;t>??~ zkr!mW`di=HA9iDv(~OiJ93(X_=+{eL#T_lhRlGhAtthxyV)VeMOocJ$2nSse7=Igk z?&}wIUt9`D!SDh;>_*S?bAE>m>-!4AAXzAm$!e#x1aAJwgpQ zT1^swArDYgrm_v@S849ovLb~huiV`mi(3B+W%R}T2rXolThD~)OvEidJdxtj{t`Mh zZ%;qJ31lPz*DxH8OS)hcLx7v%Q@F~ZA4U-l?6e!>L>L38?g2_kEs!YNX$z#?i(P$x z-Qc*MtV|}0%h-A7DQW045ZCV%%32394q!&Cp2Ff=kJd~N`k{}!Q9J#ZIEMO$8wmbaE%zvR$eGH-+MwALSorn49f!ap?>G6SyZ zU*0$9b8lVA>BB$fumCD|e(u zVo-cA5b%PFsrSYfH-^O0(?`Ut@j7L7E=%S9czgLE(uAn;qSTi*SbpY*_@8$2YG&p|a#D6Oz(Ww#@HHVz6w2o*aL-H#&?-^ z(@_K@dp2|Z@kkVl!?ndggWUj)cWMpesb=URkz6sPk#BA$2d(i0_GE@@8zO`GKEXEk z>$c?M>iH#U)6}gOIX~$^rdf>e9_D#gXG z1#B3vj4aUkj>D`}kd5gm`ZOkD_VyJSkQuz0|dhoQH2Fk2Fi`BopZt5#iK zYtWxl1udT}E_kOnfJa!H=M;`ym$Rho{qRg;hG^ss$3C25NPj~E@*F&q1x04nDyMX= z$mxqe|Gm{YB-D)8SclM{ztdE;gOzgl7~-dy3!Un5o2Pc-s#S!ky<{0_$S<#9xY8nr zkWOKc8%_+|{h5xTeeT7Fq_4)QnWbd;S*B9h0tEpafB%CzWUf67jLMoz!WBW_H z+?MeutZB;*jf90HpjdGl>Jq{-TSo?TDST?eli`!;C&8e^s7#ic=U6bo;fMfvq(cuh ztREnMz;kt)w8$+Brh`T0UeN6#yDH^6SEziVp|)(Oy2}nKW;5?_{H2)PjaU@>5nPY*{G zW#+9+B$KY<&0~mNJ2N-Re&Uml@h~dsvnT4ogw+e|@R6O{AggB>>5$?rGl->w%Acy? znFWJk#;i$x*x3{zvxHf%ReWAK#)8p#!F9@p+{~)wtY3SrKLCd=UyY0J)80K-4ev;} zmg$W$efp1$T;5LvXz#*vRqWDT6J^!5JsgxV(nj{-6u%V2@MJSmeBEZz>1SINFf?)f>$kxU!|bk^ z%SQe>h_xB>3HUOZ0y1t@3VwmX>7n{E=dxz0FapZocAX%OPhzRh4US;-d#;NG=jXVT zs4OdI*ipr1s7tI@-!1i_*@zgpgWYT*bN!IT%o>#4-1y&zK#8sAliyCwv^y$oi}wlv zpqewpfvsfq3IMmZ6nn*5d-L&<@e{+dWVqc#GVn1WQ*sv6>izt6*ygoU(9zR6&wJyQ z@DLu@mGSXKrn<5xdrV!K$xo9~;l~BBMeskRGm5CGsoCF}xcBYVvRt&anofq@e?Fe^ z_4Ji)zi&9K*ajo(`OAx60#aE=fCb=sU<@+VR-;!sd5KW{iSXYZfCvImfE*w|Dnk!m z()nHPHJTC4WYczg3puwguMmKy2JkLTJa|#uZWTk&#xuJ8Jq$%yTPsLf1>_RT@gb?#ow%`6g#?C1?mj{dX;fZbAwr$(CZJyY+ZQHhO z+jer2lbe~U|E;-o=V4y@rMs)Ts=K~#uf5k^zdAQzfXlyL2=LXoI_<3UAxbCTzswq~ z(l#Q(9cMl=5^4X8u}te5>6>zG9H)AdXB?RgEtKQxHCQom7AUKcy9MmI(5Di)<)`pI z{_e$3d-nb9@YVwb!~{KFoFmpMDz&9B=4Ma{Ja_mNVzjG{eSZ275sC&~{Uo5$Jpk)} z^kF&SmhF$BjW9d<8BGq_P{yj;(g&qnadu?0KdYa6tW(j3*NYLHjE1t-SluNq$NyZu z^&uz*XFv0}dYnw&mf*0V1BzB6~`Vj2z(4)YaEk^p7 znV^TjytA`~ghnifXOC)kh{6s|Zi(<)p5-yxUW0v1`0zw%lyGGp=P1kQXaI?I25gyT*sS}&;SK_Z=DW&B`b2n`J6Neo& zZadyUu#U)Rd80eN`mE$M4HMm4%X_YaRN=DC!+FHFnRE2KGIlY^wmt6k`Cc{_c?@cr zdUBRZ-%UtN`c6VFCd#v7d$)&Munysljw#J^Hib-e*gMA>08w1^<5mggz!to zE&G$pwpaZ4w&!c1^}VdnVKG~8O$$@@@cU7`8QDt8ICPcugOzU;P>l6^)~nB<>?r<4 zz4)vVZzFp?9TSSXl!?X?+y`PyJzt4|*;sw?fES2kSF z^#p4(7gd*8dFZz67Ls7X9(PL1C8DgquXnqN1K-$ZiMdbbt-rZHpXExwgGw)+HhXb% zdU*VtVi(5)2M~7u`hGlSascjpJ+4A&pE7AL71cEM-hm?PyfNI}roLC*M|yOaGX>^f zuIn;Sjp!^rezw~E_Hh4txtsKqU^y_f1=3DS{fPw&z*rLLei*Q0uXb#D5w_x)#?(8< z@Z$xSdzP|8fVpE&i7fItcW6PYW8T=y_9UEG9+O+*zg?;V)2v{728iw8VToB{q|uEk zk(e1m6Ei;SYN8vJ#tKtvYayZKY)2y1`b!Ca5WL6?H#3g+jxoY~PY=wKzM$)lYHy(B z@M|4T7I4v97hDk>5Qmg`Ouzl<)vlk-t(N;{T4W)KErtBJImtvE9O8#sc7PMvUDtPP zg~l<^CBXemp1yTBmls^}`Em>M)Bc;UHes7D@lX&e5;+J@4ND_P_*sQI%B_3~stKaW zVKs;>K2?wi`m?|L&aHc->(#MJ*J;TN9qU>w8U`wCpidT75=P3f1nKf17)rP%EnSY# zG%qD3rvZ?uc_N9~@C?ryeVpT!i0;mOOe`dd%uN6ajaeK%U-fBL63IZsm*#wg%#_|_ zbp)n~VMwZN97DeoDnNSmCQ1B2e+S7nM0cDRZ@Tn}BJ`kf6*INA9*v>aIsSnFur$b5 z>8-D>_8dam`^T@9J|TiREwT#bL>h1y^!3x=WIxWvS{;c;O1J%lX}UNV=;V=OparhG zA2Ijw2_@Gb=8uxSv~>avvBmFTirG=rs7F!8`hSo|G`2asN4kZeihMV zPTGf6zY~UBLEkM`5wsOH4&wv+K-q+d0JsszU9fa&fl;VQE9fMCLvbrEQCy7xqk|O( zzo6>*+4S;eK0fhm8&X7jQ=AT%;W}S%@nG!jAiaSx<+?Xf2*DY9*hiya4T9!Oot5R> zQhQ-Z$z|l4_DMQsTPp#(Jhegm7NsLnJK5E!14Rl_`Y#5^+3Clv!~sTM&VUi8JK|P+ z#ijTcl&5<6*v))Nr7;_b)u45mHd`=mNfkgi!_i;A?=iJgpt$gPVFbuyV7TvaAJG!b zxo1~K-NP2(M-GU04X6X}=WJ`@AvU7|W+3PYR+63d*|6kAp6sCVo1^6?*BC$4rvnlr z-Q#A1au^7sjodxo8Lc|4AcJj7Xd{$K^Wgj!3XT}g!l|aIst5kAQTijzd&}GvaBWTl z>d%dR8ekWC*_VcQ13PyG8g~u*1viiO=M|hHVFk-^oyaBD^si!C`nK;0z2j90PVFeYs&?rM7_O z(rfTe{_$^ZZjxGs6YnHji3%9~p&1&sW+9XXin11d zTEtdq(N~BR<82I!nrvo9O|mK-F9d@=r%S}TgvSYyQLe$9Qv(aMa`+QO^spF%WXAR= zdbd*MEQP-k!g~%OsI<13gT6!0!P~eQOHm>me-G#x>sTq>vxli@yZr|$)WY&305;DO84LB&9h^R4Cdkx13o#VEy`HR)`9CzgSr`) z4Gq~a?+CvnHRkaU5w%Jgf9ZaxDqI>NYQw^_5z4iJ%3$zBgBi?w6 zaep2TLde1dsn3Q{ao{xPP2sMj==(5I?2_`#mj%2v{9@PGG14p8>Wv$mPLh>Dag%1v z*~i^$(1!`b-dyK+i0|f8eMuyCnP6-(r$gDu*X$zU{5yQPc=*W11tBH0G039ws0!Td z)@(3)=8ZZR&(3qwLk^D5q|mlCz(?M~*((p^&Cuz#DjVmhITF71ZA{36_bC=*oqrEtkYjnIQX~DWKIfI6cAb_KnvVrwR;>w(-{oSANp_%v1Ml%_JAd8t#nu>TjO`2V} z&FFbIuYtYggd2B>z}ET-ZLQ&arA#4Rdmp`%o1H@BuJ#97X*-{QwO4t7Gm3;u*vm7n z)`MRos(w-v8s&|U>}bcWg2C;aq+sqiMVGL8SteT;WC=K1xZ2{kGhY170(F+WU;dgJ z-n<%~0;)<>XKG@FVTyem$-Z&xNhz)ju-;cx0w9D@Vaa0*zbx-AgcC#Q_gRO#W7 zYluMwTT_US97K1{4H(+o{&NbDr;IO%VTto-4G z&TOWo#M^A9f4$RFXup<1&i%ICpVMEbIZRuAc1CJRrrvm5RB@P(dc9p0UTQ)@9v9S{%SJ%o%-2rDg6AN^$3SsyVloG&xT089I%+Nyj;978a!?J>U= z7dvXyMmAYj9T6C*f%VW-ze-Ne3PzOBk=Rb;oI|l5jTg4Dbkt?AjmGvxr-tR6n?v#_ za=Q`|A0HMJV@{iaKTtxt55)F^&jSY2Py-WJF)RY-RFyblkY=m9?F&bpFiibwJ$~c zH+a1{&6#-5>jN%Bm(HxNu4d0ssZc!!pq6QP#|~-F?y9z|`&H09v}gwypJ{L^zAtrP zE9SpfEMd*2C+V1OS5f8M%y`uXdBGy-;%tSs9f1l!eIoWfo$7au=s9dcQAf~O!=aWACR!k}6o{;8LamL% z6~vG#E;Ts|C8D;?Os}BP;hoc51+1EuiD#>eNO8);d3r*^l-(D#{%&@yyL+SHmXX>w zkR`11gU}{L#Sd~ue(%GJnJXd@hW7Xii62Vr*c6>Z4+|kcjOP=<+jmeR?<<^>Anzk& zkSQFs4>ZJ(LGDhXz~VR@+iw-<^;9ROPe^ky?!y^CHaQXJVjRf4;(q|({8=*8yoA#V z(l+^ou-0w5PrEn@Sd&|AZu)@V07`u;-*j$W+gLBwY-5p<#-f0E@P|4-KOYKKC7<0% z?#OF|w5&8=AW#SP*Po*d%Suwj$`WgT*}N+g7hQ8jF!Ac2e<%U#NZDNIu-l+rul(4= z0>)m^1wLUsVchH>Qr%;e3zTz@Y#sguL==PZASg23($e*^#`l$E{JddxpcD&+{3^)A z#_n|#0 zLYzojAlc|*yZ~qy>*(=f4dNTAyb!&H_Xo&Q6a(H8iji)zZpDW5;@)OMZ*Pmj36)$4 zmEEDm!yyq`Zx(pNNZC6g)^vt_cbFn)ZN{9V*2X>t*DPrPZ|sC+9iK@+ss|icUbDwnhIJj--xiP5TP97U_1h=n>iL>1Zc8(0D$E&Rs6x^ z{Mf_X1!TNT&Lh@>HH4$-inEYH;$_bv@}#i0hB3NwJ0VWH_R(hy6>Q9bEL-B;T5)L| zrf8Vub**;=Fppr;f6XQ%9F0-rkGvx8Ks)8f3L$P$Iz!GM)d>J{%an5vGIC;K79j;A zF`Tf}4Y)D|LjZ3XC>si4t+5!oXt<0`HQP*270N!L8J8Ao>yA zdnAzy6he7nA6y6P20X8p?eb#{+QKA~?bISPyD#}skL)Gq4~S_NiF0`#zB5Pn*(nZY zCaViUUy*?8i1JLGtK_5@1yhd`#!~~-&cB1q{54#|Z#NtxJoNHq37)7F_ES@ie>P1^ z!8QcUYgUoB*`{PTF9zhG6tCe#wEN`8#;`A_m)zA}iyialDb+h7!&XwRC71-~Fp<*q zpq|0X3jA!1d8DUTLOkql0EWVT^S}2)hvAJ1_)94FYS?l>Bw;$u-uak6Rqytcw?DTs z|G}XkD4j(|%s~PH1H4*im*pcan{b_(Sm#tOIRb9f5}gTS?yCtN#xH%pRz`z8e|-@( zkq&Qkqqs61h9V%A4<$4uynW!Mgs@ZaJMsbRw?^u8(4|>TK5Da&2i#cn^5t25nS6Bd zu$M^{Q6kf;0GuPd^&HVXSMCxoIVa-FvdIXU!2+L}GvEQvQtPN>geK2Y2IhI`*BepmR^9D@$=AB0KH@h}jG zM~ZT9Vl#=b1F2BCaG%VU;Z%C-lfZ5v{vm6RvA87qGc!NG3(<+VQqoLudxYtCFn`!2 z!X2q006k?@9itR%j?fhn+XjR~s6{L)bpb%Zr-alf_kw&C;yJaJ7H`AZq9`b9RgsjO zm!y&+ElQk>ryHyKKzMI+L^N@)XvB#L6?r;r(wv)L?$lVen8d0Rdb*1kvy9MyVitrg zKJ!@EbM5TDB4#)`@TofF3U1?zN~pNivXs90?J=N%XJU%ujbRp&qfWv-)mr=+$C=^c zhNy@lLHHUAIEyB!w()EqialUC3}6cWo{pd~Ti5W3P*}8R4OJS5jS;Debt<4i^JGt5 z$YbYgenz#Nr=p!Nd)w-?EtW+f*%8w!Cv8D=&bcew#@;dGPj86U=W-sPd zHc0O=1N9Ys*9#JPL*?n${u%LR#s9d@DInZrw@gw-9sQBxWvPQ$C zZy*RTRacV5_nJt?+HVw1Aj)0@V&JjLhVnGh#kbvqas45e$k4#hikP^^_0a-f`xkB0HM`_4N_Ip->BCu$IfeeWR<) z8kJ8?b=mlcUY^YxkHgGVgWugQm6a+LAx0W+-|WwtC-PFDgNQ-nn5v;$p~_c&AuK`G zVx!7u%CEiBO16#3d7~yo`-5h}i)6f>g3dnl0Lj)`Id(1ez363~YnknzZGvj-+Gh<< zU`8<96HDweCMCT7R&I+CE2YYYX_(7xt;W!0{gZ$b!yv~=NU1fN`CsaUb=!=<;ov=N z>#w6zCW^@2)o6Q3A#%8W)cR|;B{ow6hQAxwFZZyEv|y(cloI2Rkg0ORRGDX}GqeFk(a9C5 zdt&>Ep86%po7Ea{TywKG8#Y@QA+INYr<9cyjMSstUuXdbVV{rmHk*fwuFCEQnFLT( zt^~)jBk!}Fj@;5`%xFEe@er!Gbl(_5cU=DB70>`Q+l=?Gt2r6+T63X6mCZsUs}3ZA zwOgniE2n&;untKBR>K0qK%C9Aw%KSJ(Hxgxv!ON-kT&&IUlZ`$$rP8CuJhYU^OYZ_5qC9T`S_l$7y6 zEtx5wMoN$T9~}UE8`9MOUvy(Tf?2P}R1OCZU`wtz!_&;(fV~^Tk{uP?$x;~rO7{2H<<0%IEYQ|wBCx+)*Vp0GWF-e+&e!9s1oR^Y zDM2uzoc9ZN?lUoTF4z4)ZW8)A6Zh01h%4_TL{=ZedqJ;B+BQhSZ9`+WJw4ldsr?Y& z&R^fx2iMn2NlMUyBngsqb8MFVH+SS%=OoJ&Z$Ebx4n)x@{l%|OKwUEuvSJI!H}I*5 z;(V+DpC>$-h|_!SKnb)r1awn$bNX>K&IT)kTNSMN_&j}ee-rHi;jp(yv#bRH=0MCn zz}W?I+B3<5Eu0^2R!LH#d)n^bZO;Lw;g}m=ZL8z>c@J`g-}oG$Qbs3H^yUjaBjbf- zMu2pMla@-Jz}n{^Jw5P*fmje21XF1ovG@d#bwSL6A#oi;a)_R>Kcl8&btPqbwIHY{ zhoG=2?}hz~vs2u#SMgG4SflYJQHc?H%$P!?gakX&iV24ijJzS+gr99exH9mPbD-b% z1tNbJ-JeYPxUmp=;Os;a=SFr(_<3B)iKe=3r?QDRi)Qri+61jE)Tdxfh;V5tji6S? zh~%oB@MTYMrai)(jGycabcq(KeT4H7?d*sHQ5)SbWBeTa`}+&$=E9< zQO+FJT059)aAqzF9n#=joHGfI2kA+f-(FiBn+k??>eqaje)kVlItR`r zpuAUus({DlAf0ePanM-q0ABxs8y15#0G*!pkhM3=Oo2_;k{&NBJ35*cI5c zS`{9Q_?rx~a`ySNVJ|ubN`LJRWYQF8twoS0fu!aKXgpGgNRKk9*cUX{DgFi+U5;dY zP8`u1aye)}N5I@AfSm??IG`DJ4H7`EfhI8>N80sqIo8eC?B-~Xf;gN5Y>CsuQRsHa zX#_d1rVc{NsCf6~hA4AbhJnxO2?Yg==3+#`=L6x}F13q^-2A@%p2ZNg+E~QJ4Cn;S zLSbKLRcg$ym2_XqBxO*tE*PgaS9SN|F6Te84VFQXGt?xNNjec}Wj!C{TfqmrhgZQM zHP69zuZXh;BpxtWpBMEi5adhmX;cVVcMk;co1%kIQRm|URZKD(J@1^)-qzWQ+R$5Z z;!y@`{H@JQXX#&YkYl*yIFbPlrYiHIMVMOgqN>9e- zH`O@n?$uf4B9#;pvChj-IE;ToscB^OmQe(|ECBgH#&++?><3&p3YD{tjc05XDN8~E z)590G1Bvcv##{Y?#B-gln#6P+O!n*SQs_XsCD*H-yF6Q>^35cy#3B-LMrUp$zNtsn zGWZg297QCdpdUkemrl`NqsYwD9ZWo~v49AZ2aYU90Lqr6*`yUAR<`mgy>YY` zVnv}u&4%U8qD5lHL5vh_=^bx4;K`dHpf~0`ytPTa+*Te=tk;N z`Wk{`GE`e^lYS2FYU&KZaIVQ%RcVVT2osCNzk4Kn1ChsRhJG0VV4CE}$OtkA_LZHS zO|c5+Szw`{Y?Ld)+TR_CUkAyVe-onwVFoX$mzSo^cVDGAr)Vl z-_MU7O5NrJyjYtoQK}99Q>Q2^2yGiu$p*rE-5{V_{%+`q?bD&*^Ygr~;16x1X;g_C zBy|zJZMW@$R`%{(2ibHg1xBB~_Jm&8!`n2l2W(B&9n*M0e2d_SIjqpD zO6henk#=RE`UCFBHIOd~)c589C7$bamK96h{>xE8$L=qydu<}XJBPC3)ip>T{$=sQ z=@~J3$;)^)h)i7V8iB0~qV~2R{#mGEvvFsTLjls%r#=nHurP0Ta31KzG01#LxJaQ_ zp1}^n#W1fDA7Tm4sOE*vLt1`}BkW&dpLQYLw&B?AR_@X&*ZA?)>$+r^?KySMYE&<+ zuem}|xj%@Q8C%QUExEQfj!i>aI$uE7kY?T{ow6$0?G2SD7kp0qtev9zYHk&>Wpeml)>tA$s&pVR%rNP4(vj9NPjRbL&${tU(O0l-j)BRnv;2$$cWbV^(>@M!# zkJ8EB0Tq|`Lp-?ITR8f&(fb2|{fO6Iy}zF)w2Q}IubBbwU%7C#w{X2xXzZ`-$xu_E zcbm7pJ5Th3GVdN87EGI&o+YuR7}!3bPQWaGu(+o^+bDSSXlU9zy^;3xi1Y?an=+qe zs5Iqu_lGB@)qIqIX;|sJnRuOg-SoC$bniMaPJ6q*i^ma9@-w*^Pe9-zL35{sy!RqD zrAHP;xPbw1CPS_be2lk}bL^Z}b4Vz|52+RQ4x!}ieXw!2DQZqZ-3~ui6g;v&E@1Q21lM*|01*XO~Y(-j_Y z!W+ksjMGE3ImKs>@0;z$%kb|QR=H5Vjonv_7Rh(VDmmI+(L-BD&jpF1%q1fu4 zmdid-b_-#67K}<+V|yAIy8I1*#6)3y7wR>9?H*mg^>W`%n0AC&IgX-9SMCZ`SAcP7 ztXblmm!*m#Xa$Cd)q4(&+3*k8+VjbXeMlC<4Oj}y<2FIRCHfQ$i3L+Ka{^rXQP=9o(fZ8L@BSQjfMbg85Pzby#=!(DC(`I_T|W~p zs#E`SfI-JK(Xx3p&K)*VV59IFyuz47eUTSs!}fxyV;kgxxMv z`w#_l048DyxdjHZbHoL%e;-m<6hgk#xq*O6Apc&7p3L>Rr<|X4y(tfMpN=RNRBT0v zYXB9K?7EN#-^^Jh3qy8r0QY?Re#y@9!Y>>ebt%ZYnfYC!{j{MT{xfRW31?okzr(`; zsX+lLBzbQ+CkwVme)M~t>fTKm=RvPlgnC5qH8^>OaCU`PK3lI~gg69lQu}i;$@u1V zI&^W~m*mmEc2Jxe9C%1D4AkIJBMpJ>DnAc~PH#QrLV%21td~{!=8t zMhLT?keP!Q?`Z8nNSa_+!m6-~gAhs1f%#vch}e_ys!p~KeHDi&qEImgHoo~%77#g) zAf3$A%oInuTAVpOgLNuiWZN`a{wND3j`NsajKqfYKJ>79t^SelC5hT535=HBNM+OU za$0>+AX|}jTK%Uv2&*XKWmlY_h@sZ{dQW=8!4MfH?!Icn)M~#5Fu20;@6$kU5^nmA zC7BXm5PVa>xCDX(BXqYBGg!&|+e(YgVDPkwU^hz8I4Yp5?~^n;>TsFz=LKTNJk=8e z)+0F9%-Lp#>EN*7`fzn1V;v zQ#UB6TQ%klVG%FoctC0151?SS$5H}FkHJbvI;?CGkSqIU1-j4EL8s4chLd=}*XwCf zy?X_1Pux=~ktea?x{j=QQ^I>Bnqz0U8~!>jaRa3@$R1nuk^J#?GWZ zN{eoy>H>A!K5B?vF>XZgDyoQFF;zg`C|n((y+Uv_N(CEih*%S{p|sj=XH}`+WAY5U z*v$X?nyuNS9jf6>P@Lx6f)r^W+*AS9o`&YliT0W?ts;e_pE-c3nX_Di6xu)qv9rSM@jk~i)@~S zJJ?N17kLp&hwt73nCmNmP({)vQ18o6p53}cROn7Nivtpg3HEf#qJD2QJ)8bw>nh0M zV(AFPKfM!+>k%nrBEEXMIR|DKV=RygM>GVd#L@R4o$11Gq#!LdFR@r6jGNUUtk*Lu zJ)fUrz$K#fn0c4MZ$IS`?W*@$G>@Kr(n3T1w4@ zoigMq{f(n$$KFdNf&NQzsiLC42<=GIZsQO#-)vHjV$DLwLIZ7A4wV|Q4uWd?tn)QY z#B0%bIzjpT4!6uIxO;*U&c+;(&hR2Wo!Tx+Bf#b)b3ttCkc;5C37*f$0(4}HK4s>W zzRG?*hs;v{!e{~^@zO#=(WdaXlt+xYmugLgO3{vMh&;Q{EhzRY=*%WLmi4d9KL6T_*tjS+bO|plg0=i7t9^J=FOUYnAtK$A_$PSZi&-I1N*>dO3 z&!qs{1cj3Vk(}KMLKo}D(q!ms!Rncn=K<$UTNSw?_KIXBl*?v{Vaw_6BJt)gbvJ^> zF$Ea|^~ex=Wte>@xz8QGjD){iAhAfGBAr~`a6Ar}QuwP{Exl|dzaFLp(V|T0&FM9_ zn&kHV0uAj}UagC*bksZcG%{_q^ANf&@D(%)aft5i=btW+r#orrwm~L!DSzzr`(Ia% zpJpxfEzef+m4m-G7i*Rya-~}dpI=w1YGlh3B3xq6ACawa8fsJ`8I`hKtT3Q)6>ESy zRQ#>P8l!5hZu#;}9rz>%kzppkL{lPDz4eXTxtM<$ziMeYg%W+-ac?YDlHg*C$&v8- zyEC2s5f`Xr!-gsg2AtUhMY0;>Xku4rDSOCsu+&_CAr_q5FBz{t<^?qao39aM56`NJXbg3Iu`d$!MtU=ID=iK%s(JT&zH%kHbpi z;Q_I;#HBQU;Ybs#T#w9wXQsw|JHBmGv!v1VnTa)X%{DplvAZg;2;68gp9ABZ4hKD{ z!@mJTL#O#6clYdYW_>5_=&PtqxE_B)r$%(?^g$aPWBr~$m_NYR<0afMv`qR?n}*+% zU>oj+g1 z+hyIBn|psXLihw6I~0B#8?Q*tbOdk;bx8VQ<6mn|Vrrua3gc4Ji(%+;GN2Z(hHUz( zHsbL~bF)bwc3hbPv*y$*?f;O)*MwYMXzL?IS$eQrb6XcXx8}3zR>pb1lW3F!^Aj}%_hUy8P=-W>ha9?{0a;WL-~O^P9CiO=*n{d zTRY4?N0<5yv~6)@_g`hjKW=g+de;AN*f9PRYxtj?_5TgzD-n4$hVZY>dSm_uM!O_F zNcVDot3Mbo`Yt!?8$G?#{jM8zyTnA2^7a>MrdVKyq@t;)sCT_t`M*WQYvceQ+y|oQ z54v|XwD<4%gH~51?eEXa{rAbhU+zz-0FYwd@1w`FY)*imPqV!;mT99B!5ASBOW36D z8O@nVIkm2esyX|^)B10;UtT$jjinf$MKC^i=YQZ&>)%a218T?ML($M56engkN?w_J z4NfX^p4bOL4!vO#efvY<#V9|epFlrij`oG@6YHf35aT7h3eZ@lR_3|dIEg1b=yFgg zCKtY%XldW;gMq89x~iZyy2d&NWO22b`euH%no~nt>3$^6(QzN&MM#%<3Ej7CG(5x~ z2JRRu2)fkh1(AvHGZ9GbF&?iqIzfsDYx*SqYVO>1YQi!_u_dw6Od%N&p$^@=7?bJ)=((hjUzd zb~eU%L^k+jBIkv?|bhn4uL?2lr5Oibo<4FJ@Hw+p?By(7^vw2Q3RiLUfV|bSYlDdstoZ2_I1~^Irt-Z z6kFhvV#CL1B9rl8g~zI5Exhl)A-)O%k+VJ;>8rV|quO285WB!5C|^Bf{w_i`86Y%J zCzA$qRNz#qj-61ftxl*G;;vyUpin7rJ1$^3Y;tg_>D*=NrxZY;$y0N}jnRLHutS{@ zP8}iJ^zVYRO79$f z{JZ{Bq3CRh@=om5gLrs4t(HW@5rtxaY;#ON*hGb?Ps&C7Z42o)cx*|@uF1!4nmE#T z?}G|2n0D~c-Z0p&;^SYurv35A%-5kbOOfDIC)MXm_p)S_(omg4 zC`E^ui9le`IjI}is|w}_)?i=Tgh>lBbx&V%L8%z5yw8u$QrMTA_#Cx52?E-)D`wbH z@`_!h(~tPUzEyDia>(=8yTp=U2oy~d_OKSzVE^P$f zEs9IHRPMBfpFPtRT{YCNP2(jq7LX^phqzb3$BN81;6<-ZF!> z0xeh^fE_cI2?w0O+>w>QmCRgc=f_%FJKlo7J(t^JT8k3cc2G)46h*zcOu znT6fYd6k~}v}vqZ`Qrzsu_2IOTV()K4Qy4Q!%}{&l;3w?B3(zbxbA<~%v}UkA?^%& zxs*c&3eNY&S?yJZm0H+#iaQ29z%0gSMz6q(7ang&;|rbHIa{b0-dVz6PE?Ap6|;f0wasY5x;Y$c3Lr8J|BZRjQE6(fQ3A(N^YYw&V?6`nJ}*N^&2 zmU>(!%+<-TlYyB%9=f#Rbg-um@0|5;u^~EhYMBR#9cpd4t9Naq94$1t-DEXpgzc0W zV?c|3W-PhHGUkerQqHbg!a8mNE!DR!r!8%eZDqd1m2t|@{*o}eM6+p-!5XL?2*7L5 zx%=366#yn$Xq5R`tCI=MA3rBTFyic$A)ocTZEMb()Cjp<(VUBZM0RUMt&sQ&rwK)q zLTxDoQ(Q$Qvz-%Q_0S2&4+XqYi0af%s}4)mmf^L}{1_wow()KZH=BBgq+<{|yP*J8 zknxv@Cd=yPwU{wLJr-M{DnjQ4*Bh&|pvg96to~OPg|%$*5=oD4>RF;D-iiW`Yi@e( z#>d%8a5-d8@nM;1Y4!HUoUI0#n~J1*UA4?n=jMenPU1!ar@c`yq-Z3Nf%++RX=LBX zLT!CTwa=(%I7`X&kz13*(!r|MLFK#kB4;$`yszUKh)rOFP+yvB74h&zP?YOrbtrV_ zO?z=oth8od{6#`#idN_59B^p<9%Lr%AV#p4UP(yNl)+ zl=((nAS%PZ$ADBB`j0lCF#LBfJu^xyduG7&@qhMz;p=Sc7?K0?elqQJY(4Mf?5#IX-lJj&u%y&=zFDAZ zCR^W1pr!!2ICO?6*)omoI8EkjY};OcrtiT-6n-2(=!q&l zeg0P|@QZw=(qrm0XQ;$)>-Nz^WxJ<(wgDfJ$jOMoxZUsL8G5Y5Zw>lB@C56Msriq{}`eN z^xucHp~OZjSL-}Yt9A8}8^_XD2v}g@h^8Y)`}eO59G+1GU~*cM1tS3N8)brRVnWbyH1+>p?KjAR5V65uxEMk?5=f0m6kR zIN;6045WLj!XTI15Oaz1aWuOxCf68xC=>ct!oy_oDL`0Hcw*~7rB3Upd zoJ>0;L)%|0l?1H%poIbCi4}R&W8fxN3hRuFd}%yt3iV`v1waj~QvzrJf;hofA2A`` zll488L7oo;6={(6Mk$5VEMiiJtLla$IEg+6lReT)l1Y==X5Bu>L)PIV?3BcN!ia$c z1ezO1L^P&;7T2}QuRKhQf0bnv-S|O{dVH;-2d{`S<-+Jh##&QiW5K1T0Fh2T1`ruT zH*Dx3+R32upZMMN)Bhq0-fH<%62XxTION3XsY5Gig8JZR8c_%F=pIz8=gq2rV|X-& zCVSz_t8qB@t)iWr2jtTusb7BE^=PFJrPV~0pJspH!D21Y$eB#)CMl^Ap7XPNA$}HTD&VT=iYZIp8_*UB8(s=>RVd<7 zIP$@{E9Pu2vFv=z`zSa))SeN7(Rnn=c|Sf>)Xv6@#9mDnTk(lHml%tyR;BQ+a_A-g z0CE|0O5Fu`=xGUrqJM41K?Fft{8GDOwPvNkMVHF~U{$E83zP|?GU(h;^p{JRMaT~Q zS(>xeB*}7449l%I1J2~r@0ytBw>Jn*(q*wrb*Kg&93-Vfyxyu9nMNDwDHpNP4Y!_@ z7?h{q6)`UFZy3H;AN`yw!0RnBGBe&#e59t}Wu@byNJNQQ#{m)#Ofpd*LLdAeKu$cg z5f5fbS593OA^Je<1%#&(h@(qgX&FdEm9jSa%umGqOD>_PWgg7bKS)T85|M_@3jR!_ zb`{pWi6~mXE-l7TTFbtKtMb>O5aYxuYJZJzpu!kR?v0c&_B3e7%B0~+Elnw_ z1XFYUQ(F}B(*PSy=#u3)1W4#1ug~aEF3+&}V~cyhIuwb+YsR)6BieLqA(24^!C=W$ z@&X23}A`su9U>uthSPEE$D-o!sIM<=X z+Nyo7^+XIuyQqj zy@0|S1JPvAKv(9|%^c2~50UddM8_`N%LH+0%W6dQ4p`0J$+s1R5xt@jXwNN#XG1-4 z4$l+DCNTU&4y(o5=Ax;Tpv+rWoA~(GZBX1LgPLIO!IxmKOC0Qs3t&*r*xW_9u`0?l zV2wn2rVm&Fm3d37hTp&j)v;2*FkI5tKW)FdIa~=}GV3gzQufhIi8aHNwn9b|84^)- z$zf|*5ZBYw5e3t>)#1F?+Q_w&Dew<%CCt_em%WpP0UUH_ zs-MHIj4QKU;bS6R&xId>{_zRIXrbPbHo>@n6Dz=lcCt!=h)CAi!FTNGALQ6so2ZVK z^$16d!mu#i9uBu~GFl;;*wwgFQeip2L1*hJ&;)anj>Z{v^*ulx>IKbcInqJ%egMu( z_rr)V{X4pZ{TQcD6GY$o=N?!VYkv`Vkk-4|f``BF zU<9B2!m-?~gAgf+33c<1&g8JVE{FlD#hNEE_Y1C>l-`HSu}2py2`wUyGRk+MGp#{c z&{Un46FbDjj-n_a@@SAep0z}n9W+EYb|oy%St?f3lQXP+^q};wN@D6>Smi#QK41Nv z)Egx?OUeQ%u_;@_IjK~y=AbFLf-QZCX354056E3KkIfk9(A8}gLeJQ7Olg8FX^x(yWr4`sU1+KH+8*%R8umP* z6x@BXUaA}X{XvLQ7Z_64W?>)A%`#eXFGuY%R!*l4?gfdd%?c#BnlX#DVG~|@&17gk z(a>Ar6dG{FM~g^OGX1|MVL&@3e}03q%uJNMgLQ+B7YJZa?~=^GyUL|I`knANWYaSZHu$vCYsP(wd~}l-5kscaHbAgX z&6k_2z&kSZ%HM1?nj9O23Wb65oT+qIQ*4pHn0_xXyLKl2;h|;i-mU~`vL3|RYNrwI zX!4TssnP7n>WSqC#C_u|PPdW73OUSlM9-s{J~Ra5!6fAvc&yRm1Oa&%h0w~Q{8wd8V&AxDMmZT) z$+^79GZ&QQrN|QUQK-mAEjFFMrjr1R4chwBekuA|xJ$5eXEMj1&{6FszJuczy@nUZ z(+ZEwtHt!CKH8BC(R zKJg`lR6MV1e_yfSX;JL2Q5l7;`3S9*1RzCFGY4pi76;6Vt(K#xMT<9YuBw$07jfEh zXPiy=3?N+STh)k3UXX5+iZq637*w-qcgJ-HTey$vb!({1Noz12nPe;Eqa&a5P0-1X zd6&mByZi*mOKlGFB^XCc`|H!iKkM%~daTrBq(e*L+?p&!nimKpZ1 z&*9E4p>3(AznDW&mT&IgCwhu7U5eO-T~g}`DRspx`em~IGW&JKMH6uD4)&wqzQR%& zmr3H9flQY&9ff(30v847*gxVKR6knX12Q5uurUQS11np?t6Z&+y9?w-4GN}X#g%Pr zSOW$c%}sdVp15P{FUFFs*Re&*urz3yV}`}7dxr?uVH?;}*x0^&jqR@6eod=E9jqEc z`~=XQMCY#gwoVP>?c%>#{eOc7_W%6h|FhXJ{V%=eO#jE;^Z&swc`E^70dm1~HMOB9#PbdB52#Q=VK5-N<;^LaMb;GP)t!~bE2csniT zd{e;v`MTb}_2c-$>qQOY`~9}}@R3*K?FdQ(x^e$L-LIp2A=uyU_2r2$;G9U37mTud zyRqQROsap|i8A{t9>(CEd}Pio&WgPt>Go&27wa%i|B|5Wnvl5xiF!xg2BrEre71w1 zt%L8SE?!Wy&u~tqs4kML=k1D=a#!(Wd?Q+{+WrfDDuNe(`+Z;G>d)X7^9HK;zA8Bf!tuL_dswl zz9Z@=XSGr7Q_<}^%s>F$5*`CF=$}Fk1XQ3njVB!gP|SPB4BjCspLgO&ML``y-6uBk z<`+ig&3L;M_lg_p4E_rNXBe>rCNa{6Rc*wW2t_AaS?Lgn>p%2U+_R4dDUT?#DE2cD z2ls}*0xeg1JRiR2VNa1B+~AxN|Dlz}Il!AavJ+%nwS-CCMLU;?jpiuS87ww=F*g8v z7hdiXJw(w3?S;31hsd)=ZXx_$5~oi|=mpJ)!H}?c2Z(`>iNhnQj#aNPY++183ier# z!5(*2n&@Eciof`(@wskFIiFC-sg>$3fPFB5Jyuyb<7GR384AYga>8=vS<5t_9vv*h z?3|ZBIx7b#70T1)n6`MhGj8!USi8&`n91ACqYOZw*b&oXn z#fpjVF9NfVp!&v-uYW;3zjFzezY7aYQD~2n2Oncp+)|vM0#BoqsYk!`0;gOw$ajr^Yp`n^T5IbCNmfJ&pK*qA*_mC9u&hw7u7?A6TML>JNM{5fKOZ*?n zACB|Sv;xawp1?gO%aV*8iDf<+`V{~~3>uIq6jd**mjDVfo{}DcBgpXw1IB=7^3<>u z&? zLVewheFaripr~P_bFuYoNy{Uz z>i+%7JY5q8u5_kjhlyy`KyTh}v$7(A?F?`)-z`NgzK75(m0T->>RZX7*-k$K7hIXXs)7COfB`KR~{g+>Hy9JEO%FT9jRTq;1JNIawQfyze@sX_bbgU1n(1bn7? zTX0emfalZ|DMtPDRF(bfPPaGyuZvi{aS)|p9m|;3zwQPuHAWM;WERAl6Cs{z6bL1S z9;qcHuakjFg#nWU$U78{@`F|tyvLv;)A7hKWly}U&r2FwUzrTWP?i&RZQcw=Hu4&q z`Qmj)c%l3op*^h3)T5NcYva7V=b+Q(O6=ph2&{#HcKINUlkwu(Tt)(HzBPY;4Md=~Ye<6f2JG9UCKUxTBpmtij*VZ*jN z8`rHsN$^mW6o`;(t(?J=(#C#4bFNgbR6u^0xHc?VQ~6Y{xt7CQAl-$;bE##N88 z+%3?6V0tVe9#ojm>vOMNZd0B2B^A9zxOFwQw!QNHSk$G=OU;^!{55%M^*`kAO4dlv z4@Xp)k0Tv;GhUgGm$bmxzkH%z+f87P=I=pO*+s%gh*I6!)%C5q(!k_G-3QGTULgCY z2dLUJTdOwN;ag)-n5Z*JEBy!G6FZC>(`g2^xbax++C1%@^Xk(c$`Wn4b(rD;TCaAV zEL=;lz75h^I_$C<_fm*|$6bAzx-kZ6-+k&ZnbJ zso?g#T)uW6ScjEUhKtW+?O%}z{BDMKSXMtUk_mNoL$CPTAW1Cg1iSm!b4%^8 zdB}6&OKKjB4L#_q)y7C`r~JeVnT>jRh4M_j3=K7MZ(!Ki!{iU^3;jFazid_|^x^a@ zET#T>KDj_O94>{=!dn*{P?d?T@QBXL?u}zS?`v@EKTxSEa5^+Y!_vBV_-|qqVw_6d zS%xwF1eRky`JNF;+zV8( zUYU~?co;?9m)6V~zHyi+2wBWg>{1=3Q)F39vN!_C`pHqJ2Vo4+gxun)sW*>Yct(0> zkK5^J3|%28A2_OLm~bjQ+3X@MC=Sv@-uf>+8xUiu!@%-B#-R}H?c+yP{ZRGa&@lJ% z>4=@ojV~TjT92NIMXB9#;(n=-${D|jEtS?eevEc%PB*Rwrj@Cb=xk+qyT3Z7d9H1P zJ0*xswA$RPh?n=4(GY#MKj(c}3-zX+IaLC@EFba}mE8&h@qBD1U40&?zSaXQ9YGGQ zoslcBDAljht);-aIT#&s7O7@En!NDZ`psxxJiumZNoUX&wRwtCgf5X;hJzT_@`C8q zuap&cFC#m$Q$q;bWqDH>+^RRq%?QsC8MyJMiBjdIO^5{(FX5hNF%*9SolaFo^9ee30${e~#8JT4LIvlz@r7mr-{&OOQYvPYq-M;Z*jv_z6 zjofQ~Y|Pc;Ts9PI#T<^$``*#(rtWatHp2`E&qQ_qd-$KH@V3s4ED1o$p?G zK0AeNsq1vPB*W;n3UHG9#|xeHe7@<>Oq%A)yEym`KK-r!DL8bi(V5Yt*E@83yzj)S zmm!Miu)1UMb&ET6YbpKcSSD)IFPA`T(tgn3J=OB%_<}DHL#z1TGWLH3=l|LfU}yNB z8T-F2I{)JZpXvWp39l_>MZ$sfZ%1IsqoB)^3ON#F(+2;ARX<&b>F+jf`e5Ib$?uOS z`4dD*@l>SsMdnt)vyo2U-?V)-aAcsM2f^oxj|#U% z`1akjr>iYOWME|_iV+LyA-ESwl@QwIM6-mOBZ}#N%$JB$yvN0HYbD@`BLc2P-n(1~ zD5wSN%#+*;Wc<;y=ME44uKI2B^zM8&E~KZt?6@(9Ms@wndj&aPnfme7xo}UCyBw|3 zn5Bp_WH3z{17A=PMN^NFz-UXn<%=4oYe>vNqDLo3DLQPI=RU}X7{nZvdjyo69>bJA zqqs^zpU?y??G-c=Z1X!Q3oDR|ud8PRLnR+XC>K5aN^cRai#I&KLYn7uFiqz-sls<= zW>I^uWD@U#jYs_r-^o8}viD3J4U>2xPl6xc86CtDrc>eI>2Y$0Ss0I{L3dC{e~C#P zki3t6_a2(LiVk=wBH;f7eimma@XYRIBeBj1xlU-s-1UPCge^x2A6T?3f^Ez9<(xAK zbr-nEMGK-N@-&!;MmEa?CsI8q?1_dDqDp5s7={ux&1zuYux?cVTB^>0TOfQ6%@_i> z!4LB0C`@_>z3!scOu#$4b*BH49Ngbe6Tt*q_9+u`2ERxo%LlbL96(~k!f_~f=#i?& zA|CTjI0?JTyvs@us;Y+yv9k%(a?2ddNC{%1$_aX$)-7)i(Mposi=*%m*wd`=1{2XA zjW>Hzz;Z^=u5TqzEE5^t4-|5M1dp@)HyDB?m;$fUWM${C6L5Sq*d|0r3_i1o0QCpV zq zsh1FT0J+b%E;CWz0q1frz7vx|C0nrlApFpXL?gk2OU?u<%15`a{1gkLV&7T~ZSgBP7z}MibJb5GGL4l1H4( zk&754ZKuM%*k#P-5Z{ zjr$j^82B_OHw{gsv1ZGKh6g;k4zS1CPeV!WW_GZnQQyOSh(9!{+8k|GN6XcPeYTcu zryT7}!gV_0m$VDITv^T{Kxqn6tA2y^EMSTTHoRfSnqjB98*lxTi2GK;18SRCXJ{$&Jdm~O?8wjx9% z9h~YYCP6Pl$KS#5KB(rm)S~WA;6o8D0PLeW9bx?SsD^r4t?o5w3+D1^Gnq_d_;p8^ z^QIy@Z=D3(cIL`sU_Ur8;gjMK`GT68#@!u$g=m;O%^Dg1_FRL#(R=0;qLt-9dW)UD zVZ z1*Myk&At444NyYzp+Chocw54YLLg(&&p!nyb-7l;{pvcK% zwj%n(5<|l+P8=si0d{h}9&zH(o%Vj}e|LtlZ2mp>p?@Ij_#VcSM`^%l{fs(1>pT_e z=uCZW=mJwtZMwN5`2+5*4*qQb_=An_Dg!M)$o*1-h9KwDHB>8Ebo;MY3S3Ex0bxc# z&uPx&w!JiA9V5n+DV4T2jbi!hsKLi^P32K~lUx4O5L@7GtH5McC!AHI*APKl)vxHL zo^z(9!2zIk5tn1xnVD14?V+7s2~|b9y@9SJ1GuMwePQ+(b$W*n zL?)MLSKzNZ7YJnZzLw1Og=?b?#C;PuYn*Qn-kPdWC+CX|*BseZ0B(QR2qnPb{)b!k zh8!;8J_C+3PRK`D>wE5t)3Y?=fbWa6?`5t;UouGlDAwv4G@lnKay$M_hVYWSonnx! zU4mbIt^|!!+_ylk$>(7>{)-{o6HvLvpEEC|*&*EHxahvI=okTp{}2p)@wTutV?W@vj=c8OAR35s*cfXltDOM3oL=wYF1| z3t6*su1%i~(gfbWG6$uMCs?{H3NTiLfVqhTb_hgTQ*>G~&zb*RZekKm))A%5-!m$) zsqpU&#A@^fw(6VW-;~f;x^wKb(?P1%oX4%iI%T`S^LL;Z5=EM4Q?10;%GX)dDRg2^ zK`@PK8kfiMfU0hLwA0YUc+&Z(Dmq!t?F3Z^61-(8>%-F;!-Uk8OdJ$rCc~wz z_DfQ>jucioCr5Dh=aGbbKCIc09d&5Mon0&0-(H%%NNl1hx(xol%%@ zE3LGu?p?`d)GP;wbvS98V8;15;X{NtRXHJOgB*BG7;Pxy86nGV9ei7O%e5 zpPT77a*$YcBy0y$RNtupn3$%x7g%bqTHB*aMHf7a@sDq#N_H>@J?rpOnJ0g{KMQAg zR#SYN@$2x}5G~4W^&;ND zZ|1_R4nAK3nkL4JJt=o%F5JG7hgURR)Q+!@?Cl&A)ut!lGrwhhchYL=ho!Jx`U1RH zM^gK7eB%pzQ)2zEng72@eMSz}|DncV`fp>-|IGaVA$b((L@lhHO&sY&tqq(_giVa> zj7@lXp`4r@O$=rJ_jM{{!%!H5E*FQh|yHJ{Q6D(7?Razn!%7g9p7H^xBC8 z;}s+)YiutrZtA86WM5G82qNlnqd=vwPmccbew``|`N>v_;V&K5_5Mc_ANMP3H+)$4 z>+SyWLNJW9=}B?$xVek}>zx$G==(7`i%zIUL3`lBGal7evrn{jK}R$c=B=snC0U~= z81$stUG4Yzk`}gV2hV3is-T#Q&Koh4RBpn8Zc&Px!m;TfhRYRMrg9ObegKdF1}zk! zqLFXSnxA6Ef_DdIG)_e=*Jp3*LO(~*qrx0FN^wwp@1Ro>6uNOFs@ngFU=aZ`c_b34 ztB-?25JzQmLp(^i?{bA`1}3`sjKU@9B17YB%*ai8Io~h6lJp@~xGor+2Wwo+k+sji zA-pbzb?6zQkwVveC{Rqg95 zaCWHBpPiV5&`Za(T0(j3PeYOHK)r>MkkW|%h&UQhk|K8sltX=-DU>{YYB4MYlvC}(H_;V__>NF)Io$a2{zL*7T!UGjp!I7cBP;@>_O z#fy=3!69oho`~qddWuP)qRMMfEf*P6v@z^WaFeDiT9*iB027E1=8b!VQBZG{@8cto z%0`S~SbWHK_Z9j9jTnZds$e}%AR@x3Y`bgW(!i}qigE#_A^5fCdcVZf+0iF9M)wLX z50pplh$Jc1j&|xH(Y0X5ztU&&$9#`y{FW{D2UIwa^x;r?{)UWOQ1r0V|O%|JV5u|it%-++EpBgsTf$nPTji9Jk^ z0K++t0b_Jnbw?0^=LaIMunW<<7O_$DbeB_DMDe#wus?q1Quh7carm^Eg>jh9%|PQz zA#Y+7_JnxS4W0eKHi<&??d4D(2f*AhV8Mz>Y6R1ZX$jJ9_Y)FtR4!gIF$?IPc)D*G zWzp%GC2&>CnIy71Bg$?ocZ~kB6)}e+gZ?g93GV(P$07k*(Y5O0MppTc z*ducFn|HvL0S29|0+ln^H({EELntw`o5K1U`E2(2D4_^1^3HwuC5`e6ZNN=qWs$k3 z9Bh6?Br!*qUki@R^WR|w$~!3Fay;Q2ll^C5c*0Lv*TnCw2}i#fK{ThH^!y=hs-+t?JZI6MoZ~xc^A($&A^ng)QLJDUt#KF2*z2uJS7?HMO@mp z&$HvUf9yJ4ZgwxNiFd+ctvl1cbbmcwhhlbZam>xs=lx`lFAa;gCNIY_)$KlYeyCGW zV%&Br`(9m6MI`e?@GpqcIzrADfriwy(-EmFoJ}k=BpE^P*r;9UY{{+kW#iGJtQYX| z$6Hk8@1<7(kCU@tk_U~n{)X)2R8B=<70*%3NlO02Tu+cUWSlacCtN=(j}U!C>KcYI zx^}$kcLTrSgjinL-sj3hzS-OdM_{|O4zL!Mr_MhtW%hCvuI&zYje}sDX(?Lq`xQTJ zz<$p#{{(MI^34;-I^ca!L?hgtXz z#M|OJv85IO=IPJf>S^X68Ylow1eVd|T(KSh{BEMM3I>G8hG;p{y@?L~{L9y6eaFS!&2n2~o64$0NUu`oE-a-M;cZbnW53Q20G#F?x*o6- zgxz3cH0^`Hj{W_}-8>Dm_R_^=XfzT1lh*S$C_>lra&Fg@n@Ss3e(DTxavno)3X{Ro zE!fc)%`ZHqe|w(5XK>fU!r6}sVAn@>#|Jk8R)rg`+19_VS(_g3de+&BE6IgbI&W(c zwwFXQEKFv$O%wnhj6{WOP-@49Py-4B$z1uRj!1F_XwhjV#31&GxB*|&m(m^72VZ=+ zyF5|D9Rd*AN}j?~*}KI0xaVb|;8x2Cr%UVFoHGK+r&NGenL~Z%05dx{%~8yuO65?X zJGfmnMrpl@c|LhF_8iw5VC6nw{rm=;I}W)G4s9N8>YV7_zg8bJY$Wb&v!R>#o0V)1 zVr)`S-c!UARjd!(uCL2C%0PyeOMR0^ZE=mUY4eP+z06*+jp=$xuXeUg{$w#v6IHyQ zAJFa%5g0iBLXtc19N#)^3n#_D{K1zocqDItg(==pQ4Jsc)7a~?jw67d3Uus>bhss8 zL%!Ea0aub(;C0`;?#Che%Uv;emZn~R0dJn@T9sRZG)P*?x*RRdr=$ZuWLj#Z#1mEL zfVfC?#ma}(h$QLdsXYCc4?+mnxOG#fu!~|3lMK@wbeund=Uk2j2A`oQ^{%WL6kG}B z-&dHTvVlyZ2Bk3Ey=Z!bYvR=U-&R?I1%opiXQPwpjc5YT{HAavak-S!ji?m za{pH{Bb+Uz4~0Ifh&-G46fS`ID&7JksD;mA_AZz%MK%nuj1l02-T#)NSx-FLwlG`H zAN~Szkeokk2A?LD3RqSqM#CEGp-*_E<-*N3?YE5(l@yjp2n&B_&=AObEXBg#@I!OH zjo$5`IBejpoJ=#VRiZMZNgqgi06AnO-{Wbt#r=B7#VyP zjm*6-cf~;}Ir%t1V&r#zg?RYPJOpqvp3=?P09yh#5S6oOH3Kr3ckL8_P6f#~fekha zdC{tY1SqkKDL-9&u*6WfQrN51zrz4kI6(+Wjv$@+Yb0VZu)anMnFC`gZ6;dwLZVS> z&7*?;PX=%o)_JJ{5Gso?lrx(93WGQ|red?2`+yG!%;Vw0@gjE!wIRZ4)Efed>PxbVZ3hJON_Mn_ILr#NiJYObh9Of(T9q>PWxf5N zXxp7eFx&t*?kY<@})$Mx@$ueaqW)T_;Cg$RE9P{hB?oEv7gC5Bz&^G5r zvddS=xWWC2FHYl#29mkgrD1t5cK~0tqqASJ6DN`L1V_CMl7OSZ+c?YpsU}X{<=NKM z)Qom^`tPhSlWzVK27FXIv<|yxX!70PLJg?i9w~L3RQ%gB&aX$6B>fhc${zIoV^b>B z_L}sGs{z3x;olvLBVKcE-X`KSFKj*Z%H;09E(MH3w|kB9v$56WdXJUyIi*iFLp8T6 zPR^{Ne-etk@CO(AJ14c08|Hf&=X>=lN|pzY)d0HA@n*l`!?YB*g)&Rp24Y#VH8?I! zy?e@}opzPk9d4MvgNoT|=0c$7tPc#{tvJZxxc?5weXBno?(uGP(#@J5YCTZu)o#t; zE{*sqXZ&5z?|01@j$SIvwOY zpO}v8Hi>W(>8*-1(WC)#IgPf<(}pj8g0BXn4Ep_Le=j&L)X>?utf)uPxh}nxMThPY zU*WK1s2#@I{6m}UTk6j|7~<0Zp;d9t^nKtzjFqtv=3A&=`Z-S;tE%Fo!C66jNhv4U zsbjU{(bL`y7`Z?va;C@{WLE*UH^OZ>jYK7MP+PL>V<6?^oQ*3cJKUKJ8$3&0F+C}? za0__-)dt0HJee<)K15@AdRKZS!B@~<=>{%BcWk3qHt}9%{305HDT0|5xD>Ot@Q>$r zc3bskAl~c<<|X{>iNw>3;@-i*^8v>%6UFnT_-BGBILpZtfnI%*o-#*i3&t0lwjOepU50l}l0MZ7AphY6q_yTq^q}=JNjXI+?dSEixhI_x>`gXE$KG`doTNYPZlQNAn=pZmZ^{RJW;O zVgB}C)oGtEcT$U;O9%5)9j}(_OEMw3smy3w2(-?g(0082zXu+jk{-xX7@A#arJUR> zY!nSKfnlPS?gXlyxPE1Si(~5`Jq;lLPRVrj5gkByh$NK|6j--$YDU0O6}X(yI2*FI z4+z_rn=sAgh4l>9l}#_l3AZ8M=sM^aV19ts&J7K5?O)I7nU|+NRkHGXYGA!>QNZo( zg+iiZ)kRBRzmw!wcyAlua6RGVWORUh! zprT76V9G3~w1{>DcT;Hvd+ja!FbNAs%GI|(F!-Z&eO>Q5QFpN1sm2WV!PlQOG8s%5 zR1Lt|SZxq~f%FsI${WKD&T;k`_Eq(RQs|IJcB(5VBStbmRerg`9`31hlf>F`^!G7w z-E0e-8Xy*c_NfBh4j85UWW}r2d^q4PMxKCp4*|@~gC_!Vh^-7Ic|@R@fQe(O6P~IV zjzSVktRNr?O|qPa;q6Wo8Zy&1#8y-fR`OBY8yp=8!iQ^gHZfrTh`@OHj;E zLjYnrqr@cNTzrM-S|Lq|XA|DHhop0aN$Wx}G#Ho!gl$mqm)=nU_CiwYBz7puj#?On zxiw=DcuR?%zd@q_++^~hR3*rD$QKH5XS6Eldp{uEsV{R&&j`uocK+?62$1~us^ace zd#)@$PlaE6H7D8Ukg?E28@RJNNIRri*DCKdA?;3epR_-~4P86V+^h~X5xSUPiw=q# zyEYN~PY4yiW$x0Z>?tt?^%9;NNpek7Kjp1zAh_h9O}n?ictiank{&|4z_|k$01q7= z{F1?d;OBq{nk97vxEOt!al}NxS!%3XT&Lhc4oo!kv{1p#<}=ujv5nn}^hw4tE1W(a z$(JD+%3dV?*|?5+82A*iB*qDm1gSL%n5{<2RJq5fY{ze9GwF^ z9Bb|#0xwF>Yx%Vq)d=S#&W~K+hkvwfHsKtYODC6? zg}Qe4mF8u*l0>j+7*CywopYWb!Z0q{wV5~L_+|_OK`StCiCM(moK?u~3i~N_*5Cj* ziG`8n+=L!boy-qrCWFw>Ms<-;(3S%!^-n>zx&9pq$VbiVDEG{J{iHSuG<;%>)_e~= zT)nz*8JL;D--0sk!6=PDa)WO4uDRHQ)^=GNwvFxBm#pT_s88GgqP(~NbmAsuYPERI z4<5gQp$r!es8pc=RjwZD-~?p-Py}v(aWo|Swuv%D<;=fF5C0?RnlGP^$gX!{19ji} zcI~oS5(cW)TLxTd3~{r!Or+DuXfNTWw&W5GN!3q2{MEOrGF*ymwqcR40~B*-typg> z4$CcZT$rMtpm#g_OqC9y<}EE^2s60gCZI2O|q^mvST^vpt- zcKdPTutwRmz}W8r)ID=|@Ms!wQ&fydmc$gvkU1ME6zfS*rG_o`r9vy#ldTcPYvUV* zhhSS|Sb?6gNZlls?XQ0bh|`4;M*nMSwAYZ0RDju7b?D)m#z#5}X`atGKanAzlvsYH zlna+L6TvGc;He=Dlhy(@h>gU}^rHpWj24gupLV#Uy79D+Eg*if7 zwC}-Mf^GZ$DrLmq*ed|uQcKOIVy71YjB`XKqp6W~zrw=)*R9>dNy%Li1tELgzcd+Q zO`0``Pn_P0AG%^Fz5F-b%6KDL;aZtx#9I6`Ojy`!8PzF8wJ8q#+6(vFNod7ec92}$ zMDb_Mu`1aIFVl1y?}n6T^Xit{5pF;!)`I>af|A2G#fBrz!sts$0lr6&@1mewt#*}u z-qnC{QGPq1YAM@@<1%|@ReQgT+ZpAw9fdRtC@A=8p%lq4-aS_t+gs3P>phdrG5I)` zkUs(g87G((kr;QqhBig6Td|_DSaRaeMi-h7Z$vWAlHIo!d*{)kE)bya9b*FdCJ?O9P4y>D=_rq2oYR;lDKtD6 z0NA8}Ox%P%TxuGaqI?=g`miDyt5OYQ%;r(g`JF$whIDxCIFB{91Ay(6dP<|f*KkB{TA{Xvnx_vlKI_>2b52x%FCn&yf|&`Nw1Sp`J~OK zQQf?{NV(7kTP30Rdc>NH?mRtRo6MtJS{$OGNSd;HPL*%v$LO4Cv>Ypqp-Kxz743Y` z2=8`hKP~&G+re@AIK(LL;AcUiWXQN41@s%UBuSkMM_ASVe8B-JWww%999+5?w1ckv z#5J~59CzuZobJy9W~Nj_`&7?eM#)Cyxir+iM+^38_(sgV2#Mm+q3P?%tT zGfmGPZGQ+rKD)^v=hHOk;L!;`k-9VQnQwXwV1SFd-O4JQpE7Y$=8~%^F-Hd;B z!B?0Mcuc?MNa&0lhwXEHKI0%QN>U2C#XXL*c{9)MQk;lU0lT3%k@mA!x3hYD$TLBV zztUmmu750+9e8ALl%RvYiFs~#s7<`K?ZldgO#`{%gGs{DZ6T#-+YE(5dUbyW zlt8{lC`|%wI1t-07{LcKJ=>vOl8O^*BcJp|doili{f+@+{F2n8>iAxqeC|j+Z*p!E zY(`(bWV=~z`OEyDQ?k&yqmBXIn#Y66$C3)DB+nw$*hBA^Q?Q$6f0gH9|vgAq(U#4V@URP}}`Y-}4WYv8f~*stNp z@??knAJO29VR_Ss<{%iZD~XAyVck*<#|?7GQQo*-=%%B*gS#ktsLJ6HTq>AoiZ61h zuT1FL*)l>uo`a1U}z zmtlh0e^fzt<}mwYnY*-lDuOY6F(wtu0Kf-mK)Ww zs5rAlw|*57M}RTel4PVngkoLo&KtjHg09bQk*?4BQgQMZsl`H)vPZRb{O8(Ye!H)g zI^M5Lnr`Ty4VJsC;GfwaA<=Dw{TCparj4_Uiv=n4zkgkieM1Ke$X)_K00=PoXJER93GC$nRtMrhO7Vjx~Rt$^2>duWBz*V5c`JaUGBl4|>{hu9S4IVUqhDY(bff{y=um7C zQ*Q9u0&n-4Wf~zCY^*<(w=Lt=+q-}QY6K(dHqt>B_w8-j#mj3cHVCm86&5dR|4M!e z(gvKF5e!xKfaFCLL2uFdN#TAakRw>bE=j5;dLk)ld`~LOgR!rV*+>6f#4~uUC-G91 z-^A?Y%4oWA`BB_sxn^}gYhfmM7HNL32u!+8^jM(p$w+B{9k|$XN6-jNKTOv6+GZbQa4tQ z-bDH_c9I70{8ePqgP8VWUqdX|kA^t&Y8GdgVvkYmA!#MBr^;+M(U%@&C{0VvRg5#~ zc`SkTiIlQr2F|wF-b~L%Bnsd=0c%NBw)66|;KYptu{BGt|<}H~#y#q=}FQjuV$2qo#RqXk@s- z6@(l{O9#nES2T3ix=%~Fw--%<79Lp3E(%nUx~{o{kU&?mby}ms+_A=n)|ZUWUlL z*D7PaVBl_1P^po2!H{{u7uH8yH$LguVd?`%^qPxj zz^^wGz|qv}9L(!JvpaPvrL8V2OV*?9hiv2^_bRSbBS7F?*b&>{jO*#E;r=X=Y}J_n z3rAOow=*`b_Wd7Q6`2e_k`g;&PqQD4arMdiYC;=0oH%b& z`!n33tRY`qP~4~k+0##@pd`w7#qaP0yqx^SNO~OA5wu-z?i<#l!4H_Ut)LgCvU#~os_GK5}k@mN7zO-j}q~(_`u@( zr80E|ws&DWuloj9ENJ|0Gt3{j2b`KlXDzPKQ0xkWc%|ffG31~V6qZqWqhz!F@_TU3 z#bh*DK~8c7w9cX=^OK`RP1qS-;0^&_z6w#c!%nZ*(Kct!JC9h zWu%TD>TSn3YKG%qW3|O!2#oZ6PF~)P(p2|d@ESQSHGJ(G*qnJSTPu?EGpwruz1r(E zq<<|9+87_@h^_*8#nyBFJhu+sEElq1%wuwK#Bm4jKn3eC|KSSW`RCJkk&(Dw6Rfjz z+O;ziyfYXYR^KJDPDAKQWU$6;OG)FWxK1EgtpK`*TBmSiP5x!5X`lZb`%W z9lUE&M;@wc%u2*D>)^awdxCww%k62&!~T=(=G3Zf=tTLS$DG2U8iUNrLJK)vG=RD~ zl-RQFW6=(#mzv%o9>c#XoR?2u`-0mI zE_TZR$D1RFnHc7)$QnDD6E|+659gq>MfZh6bCh+qHKYz1np}C|c2(VPjS{*w&>yQT zSCOT_wafaDA&*RwRk&2;Q-)R>(UAzevR(MCs&zVu5==d}e8a0&5j7%@cC@Xtrh_OW zKOZwH&6L%f{Toed8tQI!>yWmv^*5*R8l~nnMD*$A`bT)JTX}1m_)ew<7uv91A?uJ; zpSI=9vUYy+6KC>Rn%k9%Zm#r<3gZ*FPv?@ED^OD$z@ZLH9^RP#Twk4 z3qqntXujl8@58C;c53lj^NICL76;f&3z&O?HeLKS#TUDHt+Ll@Ld@kyerKuE{aE$=au~AIuSqXFXmXNgt+^@~&8YvfhXXHjlBw zN^Hp*51k?(S&yQd%#K>I8oeG(_bI}f@!BR#;iNuE2_5Jv0GR8ArvDi_>r^aspoG$R z9BXYae91LBPz|)6iQ&1?cRUcP02c&N4dtP(X?T)K8pbC>rUvxIaV@bja?0|+f>(@u zzs#5K5iRo7&(jg;V*`R^|Fbwkc8Y?91L4YehXC0k7x|8f!uf8%>pmDD2fV+$`M&o~ zp!%=6?cV_#MkWsW|5z~myHM*tb=&_6Q>`sg^^XUyPfx*2C(xyPY7o4I{D|`R0FYFul*B1jm-0H-T-nZ}T z*&eK4Xx-u6njdcNF0Ouj*}cBNet4T7&exYE?9JWtyGH-x^VrbI^+DPt;Apls2R{zL zp6~Y)^|W)c8GI5CRr-$XYOzvxl z3Ki23O=4gPCNmbZ&z)W@}ao_A> z7=ZU4Pt=xa83m($xq}f(UGctjYF))=_Y?9#dc_>-TkWIS2&e&j^k|E{*UFzYzGJ*D zniu1p(ySacO=Mg-(Q07f-w#ynACtPK1dm53Q0smpBuGD~!R%tfkLlOvdBy^lkE#!f z4_CtjJ3M83#w}7Opxx_NV*I{|yYB%HObi*{@($4-S!lA21x)m$g+yh8Xv~2|$}DlN zKns$rxZ13~ee=8MM2$DPBne8MB z22z|%WOKzx#P-Psp7Hj-T-{K3Mc~1mE{z96Hb!qlF2Ja-DDUtAKZU8TSwL__oarQZ z8eKqI$P01s7QMqEmOneHnhc2xqoV_0iE}_A$A(AZ{7mjO1^J5)EDW=WZk;0ZPNeJ* zB5a+h(Iy%e#s&K#|vDO->CdZ^2A(Qal7B8k3Cq}Ot_HMQbM<%vjB=zW9F#m0le)r2~ z5fV>LA)P&U%k6KuIq5s?{YyPe5HJT(o=QYzhE@rKMBrbJBJ~Xv+Q~d~Sjc*iWqgna zh-G^bkWqWZ;P7CBqV_1!XLtY7Y9Nx!M7hsK5>`w%5 z4Bn+Wd&u(s7IqS0uQd+zUBA0T-|z?h>z%5$diUvB1Nj5{1_V&%jtsBjLeIYM_WgY zqF0U3CB`zAMPw@}g2p8?1on)8;b9=isu+lM`F*W~orS?)`Wh+L&{lfvk+7{SzwC@Y zGWUyuwu6lJ&m^|avB?EpmlquPl)0Q?tqkl1)+?pl=VZivnCD;%?dcY}>alAL!gzop z2p@PNL%SGwj4+g6N7Dc#q7+QIlMi3cmE8lKDP_z=pD{aQACY;Q^^-_5@s=b4cA2U5 z>Mgm+)_KsXNBku(q+9509+FLPv zs%xBJH1cJutRg;>Bt-(g5cS|uR&{56)kFx;Y|HkgfNd91`*l|{+MO{qPS%*OHcn1% zJfAvuJ(N4FgB^|dw`6TTfF61gIQ=c8Sz)%GAfY09Hc7-|Gf6Zn>ya+n3oYJHy~R6l zQk;C?RO!xEq3v1_$%dGsHBP}x>nJ~9{+OoRBd^l7|31|?(U5r^t#<7Cl2nwHSSvlg zrL5AHf4!-0^wyZ5Tq8}nCea43SJ%!te}!&3bTZ3w(q*iEgFWIA1*vx)p@wGbcrl8toRx{%$K{nMo|kDbt7`?+F_tN*7EgG? z35-Fv=34p^71dRfT1@duc*bWZy}}~TOj;Wvj&Vq3bfJ+@BL9-PW~ER4SfP+>$HrNY z42;(7okFI?Oj?10v4kylGn|dASdRL)c_W|pMd?wQn09JfmfAH^EQePA-AHXH31uWr zw$(uC*+yZ3kQbi;bJ50ILBJ#ns8TKf?F$Y;(yYRniVGX`yr#6K;*>m-pPYZ3 z9-)^ooY?(|4T;1P{xxvSa1XDKx=6;|%v($NyrK9C82noGPsHMQ9c{dnRCg11Ew^=_ zYZ@c+SF=<@qiPEgR-G&FQ>o39q1dDi8kc6IqGgkaqgXp7O`@6`0wAYjiePNRDft}sw1_V4-7m8?83s8G>@zFR z%EY{)-paoksd@gg5V+i_Ne0u?En#dM6S0cO@+EKqU* zHk)?EhNLtDeA@NBg^*Ku8m%b?41_vrh74piVyxmN>aHz_QdyRCOwu_NT;66gDAA1- z?LASMRe|++ENXi?P9c`qKD(`tMhyFAGb+R{Lo90a(eI7@KQB@W{CHaT%zIsjW~pma z`eW@k1ffe`OZe%9b~|UlD&)Ppje*a?@2%Uz%8$xj$YFG2F%(epmb&0FbbG!*9Ym%M zC5+~6rwc{guABPOGCWpuuGzajzfLH`B%58Yp3@5D8j>3uRptX%pq}&zn!UI}n}e*E zx)4m=8*JORHsNF$3y{S%ZjxWPL)E=sYQ**m99$n$2j9To8vm6|$NcZG2_xHo=FXY_ zUHSAM`j_Q@g=f~1h#Kxh=$)%Ock0JUA(mog4&8W*-wF!A7POs!I))$bI=(GKt!Z6x zom-vp8uGs{EK#0PBk|$601x}eV3U707r^_ffam*u_9K9uU*+7ZVEaBV4}M<*W^=`Y z!9jZcpqcN^nm7PGWl{dA)H;`}#gl4xWD0atD78FDw|FCvp^sBUty}r(%82_ZLerU4aFH8vcxl zoaCI*B+es{t7Ey%{PqhAL5F2}iv*ax_6ng5?{$&9;ncdA3hTw5#$-sW8n01Z!ZcxH00336=x%?%lx*vK;ennbP;h?K}WA{ zBJonb%;Q%FZ1(8k0hsf;LilbM|FCcyeqauiar-xH7_j@ zTb5v+vh=Rd)krYI@+Bt~kLcT&s!i@s8Vr+Y3cdJilrlI+|1G4a#nB0~bOU)PH$<$j zBAA|9py~Cr~~Mv1lvOFITRe_jDzeH zPo>zcuRw%G9XChvPCGf~08HQ4_vgoMX2kB$lBbp`w9XK1V>MXlq^)TfA5XluU-m$V z)*VRU8b_tw4uc#f-!$c~ELM}*Yiv+8uPK>ft>JDrfmoqDKq~fvm_@l9>$YEbHe&4A z3m)7p;V}&q%!aY?fIUTQMq)k|R^u;3tD%~ZG)5xQqIxs`O%pUNQtVs;-BCP_ayVim zt0;z+*!%jLZcqYLKf(|UBhaR*RnqC43>>OlPE!6jaDU{@s!a({)onc;65P=~WPO0) z?pRgbz}tbcWuiYJ4%Y0{mObwtgERb&79k#p_G>|dX|4enO^{%{S`Fc@@fTxwz?h|K z9FwE)5oeZ#jFS5a0~))|^;Qw7Pc5~TxHNg=$*1U;zwB<@WYfS|3A%fNVO*#f(i6cd zwiZJB={QZXqkC?3+<<@!2$oT@>-jo5w$_Lc!MdqbzK_xE-1NmQ~nO;%OC6aA-6VDqk|CoSJKmQ}*sxq%XGKdz#;kP9kp zj@Jvlj_aM8Q+X8#O=b|RwZnIT0+7hnQb+lf{@BLf$PS9K09e;U#|B}s!q(*5b_uXp z)hoA>(@IKL>adjOHnhE=bLdqMyz3G?lePSdlIa*0gRl2V8^bE5S(>w3d1a7bm7^p_ znin?#(krbUudbefo=&Q3P1^N}$nus+Y2o116f;P{)QiyZn8%CIYZ6)dp1bM6s8<%aPB82f0td^R zRv`&=o!H8MdiN&>+$a*%-#$eRwduV+-yn&+G&uP?j z1*tcoL1VVh;nAi=Z&Al>WE~mti=Opmbbb25hRQx$_IvE%mlhja?O_BxTz1rE!%4)5 zCyo;TERMOU@0B^y1WGRDAO(U%*J~-9J%`Pxg^Q6cqZE^-HQCYQfO0aM85Kqmr=SIn z7m&d5_ExLDB2C;MSL5c)vBY`vfSiRVZnq&L3*KCO`k_&L+?q*kCRhCKhAk>w8a*OrwS7FQ_wm$@((@dq0<&QA> z=tJLh`sJX`SbA#C?d*uRBlyrw7=$vnObWO5jtpBl^ov~`F?3WM+nU~wIBT!v`qQiH zy}Uw*Ufrv4jNZM!*DBf`mS4Hw6m4ICjV8K@Y*m`Y8*lPl4I(j^S`_JF0*D7 zIa;WBokP9qNLgxr$<#zCtu0S@+hev9y(;^=5?{!OidEycKn?JuG+|R+)G$lE?8kQ8 z3L=?b6?I&_xe8n!ohvV?nQ>}egD1wd&WkQYG0E^=>7Gv zHH2sPAQ0O3b)QxhpM|V;->7q}vfcVbxqVt^2!r?Fp>#mjA_0LmY_}43UB~zRcztr# zwwEcAoE!(GCtN17+?Y|tY~Kd!7jY(YQKf!|WpKdOKmjGCvk%tOQAMAn?O(WIILmu+ zV0chrKxa{K*I+$aW>$sbij*2vJdS5T^W>A1nwlbK&*T$&UF&S&5e)dHjqFoHatBpg z7=q0W;0Mm#Wr^cEPwGvtnY(ZCie{~)aa?1z*8k<;Lc*4$K?uBYXI==Cfhw+WFi4Up zB2|ge6`dC6I$k^csDirbZ~mM0`k}5pSDT+SAbNsO_2Pi=E;;WzvnpEa^Jp`%1^!P7 zFb3clj0JwuO^#8?{e52r-uUje=yf_j65(HO~=x{fTT5BpmTQ;X^l*KGPqOJYX#K zD{gi|Y^mQ!oo4(2bwmVQ92`Q~A^maK1@N+#9I1!E??4QAk8t^_ugR&~rA*1H`6%fJG0eMSM1R}M zL=aM`$>%@&F!3J120Kt`w=cQ?G6CISk61?63pG=q;`W$^YB2u6-Zhq&B)>}V9I6i^ zPy?!En1j#)C_>yrs$MXm;9P3agF~ihf+8T7FUG2ndKHHAhdL=$7VJNUhq6_u2EY@A zrv;jk!yx-XESG5_Omouf(N5rXhN0k;XS2)y){aN&Do8}7mLb#_SP|2P?Na4vg|LPA zQlNLG*uRzEB9!U{a}(23iv`3zU|kvib}R=#hVk2T4|Wo-19XhI9Xl?4<-ivev-U@E zTbT+#50?5mEJmM%0b$`~p#V3~-ZgDcHiZ3>c?6J_%{=Ta?j@T*3E0h5|IOHvmb!hM zWG@#S`@WoulB6Ruc;RGd$mZRVzMJh#Sj2cH%_>TJ;`23I-y1SL~js0UOY@U<(vFm!f3LThIE7l-KKWQK_ z?WV7=LHmP?6p4dk=T8Dmt@0u@5N%PwQ*-E0a+cuR_8m40qKs3bA)+5=d&E;-7Jw8e zJP9gf0yJEJP$n$>qB2*GA3Tqk44u(;FT%f6Wx(wDNE5bBUHogVOHn_|Qe7&Y(hz_1dx~Nq@xT&|$muP{ zd3KZ2KK9_<2ZS!y?!nG^e1U3a8l{?2FC2yOQ~Ghz)DPYLsO3t70*@+WGxsAOG#EY? z1*kGG4$cPy%5NJ?| zf*cqvIEot`KOnaYD= z0iLKSUp6?V#4yxcGSB%EC`b+W`pr^PX<`CDj54m%+JOC%E}?-=x~9pc9C;;f(i#|E z^8{pILp~>*Cbd;V-6s0T^eo{{za)7S$cJ+=Mp46E33F>{G7kM=W^STUM#TX)NTbC$ z3#eU9d@VzF;%#bE z{fbt`2(1k^zyC%@+Eo|Qn~_9E<-KZ68Tyu_*1>>*a{HzjSNxv@FxEo54+f@gBydM$ zX*Z?%8xe}kv-C6{g*~N|^UK$$$_E8Hr!S4cs_oxK84#$;CciI)pKQI0pS zX>WPuL3CL^^(u%mo77-cu=AZ8vXsIh^|BO3UcOvf#8 zXUDZ&2!7#@)G>8-VA=k8x7aKM8jp59^GUQQHR@WoEx}m?9NZGn=~?GB#<-hM#<=RI zVT~{t;lB}u4l6@EpOZFI$R2icgqEZk5Q=HteT4l>3OXTI)!|`HERz&0ms3Wc*(nss zwsJ(d#vq7!`DmUPWrf9aqf}+zNTFIkYwFOB4t5L7MYoXcv*Tg4Wn{{A2Dw# zukU47^QUGX_V17Wtg;+{_y?FEMHl|%EuMNZ{97kdH2#n-< z^vt!&8!xqqzWDt`+Inyedzw1hSA(#uI$#>umw=P&@R7w=x4+W``LFsNC7&I%JjJmt zNpq!nlQu?z&aln=8fQdnPBo*~i;M!)SpN32LelZ(a@Ao=mttngXg610#G2B87M#*A z7gffv`}Z+)%3GaUCObT-^|?}tehhFE%NN)g-NGHS7Ll&iSC@EXaO)t39Q}9N%TJ6g zwkW@5V9!`*O=@JBOU?2)84+(p<)$GpAL8vir}=2AW*MfTA0a7R# zG6OOiR7S^h`n(wQ&}b4aY&kO(2*?J?*c)Jeb=FC=AsDV18#olDKQ!N)kriW$9RxZZ zK9=Z@Ll(J=#{&?0a7irAx_H5B%|o&b~Maa@a_Q`o~MJ!C1sFZt0>0dQaRuTumisuAFjjAz^PY@FkJZ&)sN^sB^J8z0G>tB|S#mJwqfc4gB56{UR`HtKJs zh301Pck^;~4=|{ujhIrsEnF#pAK^xv+*~=*ZCH@R7%bYmYiC@`^3qS^;NM@e*%z(b zTo1Ozib)syyU5oq^{&X09RYp??etB`Ei0%woqLK7Qd%MUO6=9=+ok`p$lRapblcHZ z;}T#`clEk8otFJo0-D9sNO1Y45%hBPQ2(dC;tNWyxo(pEq%lw!YNpR#pH4*P0{MR5YbhF5r9<0Dg(VyAdW_Oh&o^e&=QO09S{8*3&nt5x53^XQvr-~pee9{rF#kI@tGXiu? zunHcqzRH1Hv4diU$YN%U_W*jyGwmN}zRpXlha@&aHokJE^pBGTNTe)BTp1YVo+P!l;mZQp!0YJYx8jihCVxFS7+m_^Z3;8M`9O z4Wdr$Y?CStcxkvOj9?#7A8Ag(eL(*oU_c{bI-a_(kKwcIYp*FR*T^i2 z03p!FBDYKNt+hWU_5M9dU!Od9PpE@XT=3wjAxPZVi#J#1RJV96W#3Vx@GU4TI5yF? zi(SCwOkbe=Ry-pB55dihDIZ+>S?)2XBg$S0PvQor=O`-E&bM})@2$Nhu#sa8#H zSZk*sE-z57#yg9z1A~^HS$_BR9QvdylZWtK9tskhJjhP#BrO3IlGtr})+%1ju=MeK zz_I$NAN@Bk)W62`e|gwBSpK7rjOE`oW&gPg`duBP<-U3tWcBbt4hp2HfsU++Kl!~XvtMR2W;@8d6AnO|7d z;o~JAUal_Qarx}hgaja!?zijPQ53Jl>vLSxD?#m_%Rby(Jv?8Hx`yW~EUPa^grzGw z#py-e<2Vm_Gz(KV1l(Fm9=KD&QH_fz`9A=D$3)w~Wnd9&GOzA~a7P1&VJK(c% zI0`I2FTg^ef|_A1{shyeP{yknmQ^M(A#6t7Ca7I>Q46CD(Dp#=4105`1bfwVAk$(2 zE=8?bLKf0|Qke-%qD10;C=tz3q?|oa8f$KF7G~Buagai;u%zp}P53^w!V25aTC&3q zTY#>bD{G}7C?u+QJ0MGfI4bL4seVk81LR~qNF3#Rb_lsU67^MwcPXWxP>ysZu@OSq zpUQximYP`}8T{Ja&!PzGNF4t4LjAUo-I_jl_}+o~IPwy^N{C>V2a1jJt=jk?{|Wyk z4PTShko93-BC&+)w7CC|`(aCN1eyENbf}s&7l77cJ?i6N$_wiPBB5A=M69zcuY-3G zdog*guH&*$!2@5o^FDF~1SX;gr+R?`j&XECH!m0$p7V5=Nt8QByplt)D&wzdsxIN( z2D7`R3uYDUWB*?J!)! zHGVk=j>+E7_a>`s^Q|udn&$FAqAHI^Jw`3FDFClGLs94+kC$pXY6Zlss(87GH1S** z4>~}_UjlI_KJxggWGiDxp35^wYwGa9gP!>-njn^R!+|sDihO9jy0IWkGK@SnKWRL{ z9YX3-eDzn>v4#Qwg%hXJC_o6<6|lV(WDb=B1R%z(MkD8DSm>xCgY<$8pR3+CR>|L9{5j{_ci(2OMR;8-a0kup7m-tAocZN}%Te+NgOqln{kr zyB(g%>ACAyqqSv3fxi%iFp5B!iMlKG-pGxE<+r_8TKe}C){jlzC|8nt9jE>ncX?Cy zJjotD$oje?L%KA~>FDE)UE0d#V@~Bg08N8AJ40NJNh{=E5YABEbsD%9qz)BS0@fTN@BJ ztI?*~!-Qwc){)~Q3p|7Y1e|OSm5%-eR5ZWMOO}TVxKt(MM`dEayLC)zhZKBpFCM!aB$nlQ>DDjsQoM zrnMMO9GHBVp(x4g&QW69omeFiu}it!7|Gk#)yPn&i;1j}!%87+EAc9ndE^3P3=`K* zzaUMXqh*g>ViyKRkhyFP4ptSvhH8Q8;b`Q4BY46jX88}nb|{K^S{c@%13I^b;tk^~ zJ6nT|#G@S#Mwd8>!ETB#Cl|tJr&IfTF@=J&gSA zA$Y~|y@uZpRMxuXndCfDvb#gSj0Ex0X$Uk}@3efXMcnMnKRthQtZMrF!@aPe!V71}U14FRjEZN0zL5;p z=+zzdlp1hX|MNygv9C4!@=*EJ%Ma9dRIv_kj1@o8zX7|!&9l3Lbee3DY(bx-qrVg# z&Iqf%ttll{ru$d4j?%+k?`kkT2uM;sL|lo3eAK0;t2Ml*A7Zni17$A$!jLD9{lY_|y2 zH6K#cKG8Mmh=4X&H^+tMFrJXBswwi^tpJ^kooukcH8AG&%u= z07Vt``hK4wX^b)xMaIoN59x9l9TJ>R7&@;EAh~O<=1jQ#;^msu=~6hKVXJ<;Z;y}S z2W*X$K8AmFOxWGkKgr70a~~;}o0$a#{M+=Iwrg4eQ6>`hg82i8;(~p{(52ysQ|jwnI!} z+XkUmE;lXp4AIAIw=%$@o!g+d$m->^ZQuQ*AEiv3)Q~)e!Zr-YQ_@P9RIV9sUw@K$ zX$tW``~%cw$GMjFkk9py5r@Nl;jz|5ASh`kS! zwk>qd9CK-H?<|5(_Wdn%0W8}ywyo1!^NfYo0irjzZmo*mKcrHJccw+2vU+T-ax>+L zIWTe@y$&e$Y{=@s9BrSmvjEvIU>`TD%yr&}(Uk7d`D@NCu*2}ao)d(^uOhQm8>z0> z_QmUDT(m!7=hztNhwuVIMg=+On^*n1k%S^CxA1~@DTN00a~*!%>(MAkf%SPQz;F!G zcRvA1GGik|F%nogcC%6SWJW!$(+4Y?Uj9vVpek`<9uS#n=J>D>v&(Aiz{703u&djV zF*CBus}W#zmCyhgvTkQoT!{6WPA9uue?b_~N$(!l`1Viig}p z8LQq}DSC%B^CZcJxU3VD5JSp-aZm}t``EQ#gK?P$)HclsLM=_AUf67!FnJCYdd(rb%5l;-x0vpq=H2)6fup>5?_$vS$CH_)1F-8DnG(kzQ` zlW9&K`-dg7+1mM$kGb8Zwm|pKOf>D%_k!q{OaF|kP*m2fnG=>c@qU4|{i&%J7A(4U zjlNFMl3@1rM2%8rlp-VD-;+l^?a)-;|2i@JJ0`(I&&d3L(-SQJZf*L{iQykd+5fx2 zSfcK@^`G>_!WqEM0jc5-8gSQhe5N0O1HEGeB3{V<^qG-K=Hw8B71uUtH!l)^+i(iJ_Or{FZKs!W@LD_w)1djLmED?h=nr z@9D^URgGtMNd=@^+MdC6^|^9%Be;r@9^lJ8=zVhr5U;b!b8u?>MIVr5AG*ersTiZX zF>{$nx)6#R_IJqR%ak|kLySF7SJgt(liCya_w|+@uI|s2)od&p(;u40TrWI*J{-N+ zq^kBLNhcbZGUg`tT3fb3PAp@E4S$=Nwks9Anx@c8EHxe7?@0oYh_VC7&`ub#yBO4) zzPm`?o|3G9O|1;6kiva2(0TVUSW54+MrdLQm{dnWl zzHCswSOac^5oC;IX=u8{LD1QM?4fhw3dGLi{*KJ)Yn-%l*eX-8e190fp9pxBN$t-{Zg2z zk+>zRo>A&P4UP!}S>p3@{D6@w6hWByeZr?>k|#fcJRW)A7mP(QmZ(N>Q11h#gKv0} z_3>*$1Hh8Ad_O$TF#%DnxjC}N3R9P`?vE-z3d|}Q7{ZEwC_A6R(Q#%Ckf%<(g^rv~ z=P57Qqt@!gG?q8Zqnw^RV49P!&L*f83R-8GCx`iJwfkNoVP@ZK_45yDx)h%bpns#& zsctgy=jm<-r&;LJOjWFMFMIB3mjnG zpo6Cm?GcRqy-H0`|18K6CQhUmQnwZaUpiH4wlg@wUtTq62pc%q1`-QHa;1Ev9cRN9 zqRAwdV7NlbEy!=GMXITpu@HKBLolZGx7L0!au;P@=8dg8zV9xW$WEZsfba{aQyCrb zezEUQA=+T9&WM#^>Yc-;gS1} z7XQ}hqYn8c0|^gdbO0O!2dByvMBUO%@I?7!=OuKaQ}2h`vPud9WLi>pM3W#g1BGJp zWW8T{W0L9d0C$4VLNao!GZ&`GKMFkzfV}=v-c@b{Ol4pkRhf36O*$NFwl-`oLGeB` z5Pxc)+aS_6Ub!Xb4|$)gS})@@fEua!+b1#3`Jt7K8QHPX>~t>$-Gn(%xHU+(Z7}0G zIM!qrF!0dvD#bXO5&!&S4|=%jcW4EK`n7xt4l1NmPQC*>vruzba|gx3Tr?)^bG4~d zI3;Sprfvg}1zWBDx?Z0lT_dznQE2^bdsN!DdYX=+;&Mo}qO!&p7+L9wj@xP6&U!%0 zKntX6%Bd5KG2a%qmLwa+)~}hnc(rK`V7}wvMgCF4PX zh(@3o?d5Kik!B~sX%+b9Xp8^R>}1&N_w08@qSvYwAO=|?mFLQWsu*waSN@6!bg0Q# zUlBFM%W*{0XykKQaMx97iIGaY08-|u^0*1{q2<+ zmZRFSqf$flgyA}E?!{n1gKWGUvVNK4`Oahc?NCId%A12f&~kXdK6T4+(lohfLRW3q zckBSej2>gMHxJnbf?^t1&B37}&F?cEfODS|an!g=91OWQTf9wfYNE)@PJYUGz%-l<Jnp>$2*Gzcr&ix`LP2!gI6Z=2nM5$p_9X%Ng89S`dqaJEHdwTC1Eu?rz;mn@`S z)t9tKKeht%$I7yXEpF+R;d%wz#Z>G8FWdxI4cQIjQ#`j?vF_toC!UT_EWo8} z84Nyc>pv#ZlNa%GIX9pBl6#R|bhQtv?4!=q$lbUl9C{cbfYN5Jr z=bSN7P~^eK82)&J?|qgE^)X&BdNfNE^pmYpTQ3QYAmn&zE(ums6vb)bJH9gf+q}a? zb1fbY(bJA3OAM(_|L%J#G+FA}6SADEgJq_UY2Tt|jTvzr0RM7BnNM@6w5@9i z<7%^Rm8}>aCW(UXS+4%6gR=XhRnN5e!;cTng*_L-670e8UiM*j!?wA=byC`|SZ%%* z6o!c*O4D0UKwWOckvNR%gh&EThUOEItWrd< zB+Zg#99&re=uyo8Ge^YBe(LEs!6Gswvx;s=OI^ud45RgfW>fp7BJW?u)cE`)5n?Ex zs^_il-7adWPjHKw>c*{=P4i)78-ap7SzCq(QIRp~x_rRkLQ_*y3a${ATK2Vw1R4hs zxU6};;o~NNB@FkO_ra-bCPVxt4B@ILN&F=0e`GF`^MJh$zU!oRIQPxUKHT%1or`+b z{8BAw+^r0sw+mW1O?RU=*WDiiwMZ{?PY9kgys_yKYFC%|j>#L+*Z%Eo+J5C`%@zf! zveZEB(=qmXw9|)P^+D)mU&6+VesucT&KwiMVCzS_38XPMClb!_1ok>+xIP%I%jsch zW7pW1`G>2iUhrE?3w>>lZOfU)qBk$VrWl8LFxXJ%#`K62ufCS0|G8R9ri%Hn-bV#& zCAh1-XMc)>^rPdVih$zf$AqSc<_BrJvB3bEpD6sW^xF^16=v_h%Km?+Lw>*||50|s z`d@(Htp7V8xJ1;|_&?y1@*i+X2Zd6g;QZx4TL2g@bgzf?-N1gw>n&HRw&0|6N~NdI zktx3t%?TpLC0fG$vIO3j*Gpc|KcYX3K4a*%Z|Cz#F3fMN?c(m8?-tj0+k$0qJs*YJ z@8k3C49#c$NAvgPrsTG8R-OI*$u*ng&Q8u9RFk@&hi&weF-gL#*gIpeSOl#2T}@t7Lgf@(EnlwC7+ z5_>lT%`}ggcH_wAI`%Kj^P+MGJB+3pA;l@|=Ja=P4HY%7Ll5(-^Dw(%$ zZ|u2`Ey@p@o8L0V3&jc`nu@LokUXNasWRrUe_XA^b=yZbNjhySi4LH!@b-YH1ZHtpK(vTfV8ZQHhOcd^UvvXNyQUAAr8HoCrg z=8cJe{)pL_-OPxLD>v>t)_JbuT1%%D;pspF9bOy3IUu6IjKrLT0y(4@;;5+aUUtBS z2Swqgu)l@VWF5#;s$YAiFj?CHsX{@Wp4k)y>J5leu$kLT5%?fARulv3_ZQ(@ph^+B zr6kE8#<2qK6P6mJ<6oSkLnzw~^gXP2sJP+$ckxIXtgMlhX9;@5H7hJHPHq`Zz5Vc# zTvWiX6uu|6!1|ugA~pY9 zl;Ho<^rr6*0cPwb9C|_3YnVCAKy3)?1BM8F9>`{cR{94K27MJxf*;192BKFsRc^Zd zcT}Ka3uF`*B=j~qCwp>j1Lm>!u=~O7d9c9(D#!or*_mgZ4ZymgxKu~J8WJSZ}>+GZ|ntC1PR0z zrw=kF{)#qlz&GRzGS3ytEDmES{<75dpfvJ>*vkHK=rlT4 z`Pv9>IJ)zF;vz-1fPzv6JN2Rdvuww?$JFTmJspC#GX^RrfN&y+(Vgt>F3fLi{v_um zwM4F%Q1x>;MiCs(NW`<{t`h=Rp#LRO#(Gn^yXcI32k(3s79tOCBi zBXkJ?X6shQ>;YCm?60 z++?D>{I2zbg0b3NqD_SQG%h2`)a7T2jNPwaKZZmdzW~cV8RioE6|a2J81hR&=9Pef z`p3Isp!D<1dHe<}E`5B3TR{u?6B5bK%cYw_%u1$c=>E_|Cve^CFCM@eBzEX{2c%;4d=N zE(xRJ#hSHAqh@^_%v`U2I2p$*>l^NpD4ydP>*?el@tA+L=XBQ|poc_$IBPI<$+o&W zQOO4uSm`mC3+mpBTN@k64wP4WP&GeCIteSDiNi#|WDoXg%~&G^d$vQ|v!DnEs+p9E z=FGuJLdS;9sKm9X10}6}>zW1}k%1CAFV2O0Dm&iVD8592p&CsH9_5@M7hXoOVK7Dn zCMujjxofI8!Ly&%3V@#I-G`(s#;za`+q*%YpItPjVa1_h^@@bnK;}^jHmfVcstlX0 zyr}tKX(`vgzQBK?+}INfk>VYw))z|ir%Xk>Xr>aZSrHD*Ddn875cJ{a7~_d*mDVS1pqi7VDw=iA_FPQX zdZiFCZ#KOYhIQkDh*y7BqvF|td)N~Z<4S~+y%F^+a+5)3f#N}dkeje1#*SL%NMoOE z7AmwNpO~EXNh%bE=kFg+s`d{X@V=L#l0UL@oV{EyD#2MK^|>nYz)@D9y&tm-NOW4W z9#zjcV9xbSi}u*(q}pmGnfi@b8E%Y%S!ENTC;-fvK3=+z6f~#Z^`hZU#V(J?&Jne$ zKi|!kgy>E+HB>e}ebi<#{1fQ1F#RzQEbyovv{Q{h}2jdf$I zi5mSC#I>qfQ~77e-wZg?OudT72ztFkt^KV!8@0;6Y#r)4!!>mW1hqCz{4Zj1vjFJ0 z>%}JOr#EE1imC>Rz&}pQ)-Dw-SK4TqzJb+?a93BS+Epb6%4RHb*K8m_j%E@MI@mw&*q7+)#grTS*+53$wrVw@d4-jxwS$vkk1Bh{+p2c;b2@r) z^zBk2Uymw((`9SApeSLSh164Rw8rmG?A@xCqT4CWd6p8Mzv^ukF(1Fr31+mdS3$7Z zWG%=s!3Jk$+~=`uP5iv5SK*Ca{rzWAx;oT7*cHy0wuP@u?=-i^{5`4way5p&Gs|vO zkx&NpHg3mgBuxWW#}4P(eyfX3Yg&K3@Tcp#S+gZta5Pl{%H^RTJj$GXsI}jMab=~T zMgK0`ThAbu`ut|k!($35o5QRa9BP!ajV@L>FPb|~S+*ZcPPfJe`;B1jHF@iaT)`N0 z;6E5*kq{4|z9y~{H*OdvxBlEC+iqEPy9c+}J2$aLqel5*p&!(}Y${RIl?4jczIVt) zMbL-s7p^rwM7Ftteoa^WyrJE(i1k(*eIF53Kg+7Bdy!IC%Toa8&Mm3sKi_4oR9ZCW zsCC?m@SnxbM+qTlz|JR+9zSsKfRhwSyd+J~q7rQ8f;yrYk`S0t*w>Xx%{}tOAYn0` z0i(AZ!pV}*q}yB|9XumLCpv}MeU!`SP@;YCk=)P;{ zH#va#3lD3KydTI&vlu$~C+XGPCAVQ-J~gRmo1_}k_zKje&>z)@jZR{oxa_=UC1 z6-{Qk02u5}Cus48v49M>ca(WTp<@y}Pzv!C>7Fr0`%BZJs8^3unAjVE>=$&2^+4XgFZIjx}C%4Rw{~Bw2nk{WPKYwFM1& zl7CVKGb0k%CG+LqW|c11-0+0P;P-QXLUMyYk$7<7!svN=bDJml3wT8j_ws7o!9&2W zV>4CY>MHjtujT!_U(IoNzNX`vU=x1g>hw7m!9Q&SNM41rmBoLB(e29cVj%{? z1>7dCI+q*sF(Kw?phnQYFPNZYDy%VBV6%TA6vUJC0^g~jbCNYWleV6Bp4cl$W}bTE zQZB0pw^F1J!eu&FqR7nXj{K6aUERxb(|vjx_6xd5Vh=Jbh0AI}&@ic*D@J!k5~L2dq^zgh zHz=yBNpQ9b(b^$CE9-E5Y2uiQn2HYrKREH@;mq0Ocur^nA53sLwO}8(&V=8>MuSRs ztQE9sqb{I9`v=N~wEd`95g`fhAR!>J^&{}4pi4FT!(}*sjuI4#a%$C$f6Vkf%+73e zI1w~AV!WNS$u_GOJ7U(eVQP=rS0cpCUd(HyW63 z1E+0G3;Pu0w-%$+wazc(w6w5Lz?6X|eF__Uh(xo)M(%1nWjc=?2&yfbA8{5RyPy@K zV30z+Wj$n3JxAQ5FQ$BH&}jX}DpPVE?OXt_WibY&O?In~Yz zWVp6TBmu!}4Zy(dj72(tQxfE(yi$>H5B^cbC5}vH|Es0izbnJK(YYJu-(+pm(xI4$a=~j_EV2X->6&cF@lLXWKxk^ z5c5KN1|1?DM$!HC6S>}Q#Otv~eJ55^ySyy%H#Ur(oFu6@FT~wREZdYI-|My*MPP)3 zOiAPD2h%3ONW$8h9(P%ilbC8-%B19z)W7akk|YhAb$7Nm6R$}0P$nXWZ0@{~H7@-1 zbh%+gx0-4xtcf=r!NL%8z=XAPh<515RVAVuH8;y?$%X|K;(chHPQ8Q&3Sl&Cf`3y- znrasb)GSEJG%b?FpX2~4U&juLGa>HUD>xtNi#Kr+sBzT)+*4Ay>OrQU8=C>D^r*j z_@Qqvn2=hyl~5s-hLXR|I?Y$SMF({1JDY6yR8im39-yUuod_SNlGUxq*XDz5Hdgsiyqjq~mlrLQ#WXUu=5F7jnT1;O5CU%oY3%7u zCk7^wO7EW{D{f}}8N1z=WGS#zaSXXo?+hy}&1Sb#Xo1W;@>W|*7FC`AEkm?Vk{cRxS{fB2!9%X+7GaXS~iONUmSTB+uJcIK}PAESweS>5dj zGqG5Q;O6kcwfpyoe8UF9@|f2xo&V~x&y3$<<7*jzwNu{nR7FRc16; zu&Z3IW@x=wPGD;Z;4@CPmNNFW=(*l1hgcmW{3j-N|B?gSVV-VqJ+37cQcn!Ebl_b& zY~9}E8x-lcYr#&`#j&sP@P%&?aBlq*xFS|EjOV0TvNwJEgcH|7L({$d(`RyTEquKS zoST4aXKJGxkV*d?5qQ|gxD42s8g_N`)l<2WuAQcOmQZNRK3Addva{8&d&zR9a5CUK z1i-Mo(_)T=VaT<&iFm8UE#}y#`YaxLzCYDnN_Sa&_%%$|zuvu9x!6M7(Bc}h<$1qj zJ)K9-W@v4%z}~}k;=Q?=eRZb016 zzqae7_VbKkUu|UY3%U>4)}8Z}&`_=?V>Opy(s`=fU#2PscJcGf>x_NAR4QYYx$8?& z;g973_V(}7<{v4-&i1_cN30UF;On_3Ong&gzENL?B&Wlh-OPMyEB{q7{+l{yW@Gvf z7@hs!c}4%J82`s|YzGn!_smz`{>}li6!a|b zp6KrSe7L!Ly1BPTfpf$hmy_KPjcecwDqaN-P*z|`E5v?{!2YgcdldX<%e<54BeSm^ z)pTo;6;pWl^dgVIGIyQOWZXj%^UFBdi4;f|LLi1sJxnVL%zlXjM7ra=E0FQqHRECd~zt5KqD4}_U4}~fdsGiq6;Wp|8vgygpofttC<33tNbA)vX z-^*`TFb7_W(&*b7LbdU!i-eZ}NegzU6`kMyyWE1p@!H>r9>l@U6m$SOWj6zZLRl%k zHezhnDAJq`hc38O#b-U2-bs9EvCGybowR0M_*B4(MpkGNvWxK-fyFGt}$$*E`%i6 zofoA8IlvAY^8ka{h$M|Q{-FLHEr6KjDc)MwsX?52BaqU9(!#J9LGo%Z$uEo|n0T#G zuzNRGtofrXLP)YV&rwL`8rPV)%|2qU5gtLl320rW+f5y+c!wEn<7>K_=`JK$%rA9Ta3{K9X==2K0m z`{nUr=^-!7^LLtHNCXAbVk!HwZK>OVdw+O)i+qX^hG4!o)UeXa3KQLAl7mQ?0UI!} z_hAG+$+NRb;R~}s@W<(hLwSw3F&9`7WNte=2hW*C`JEQLkXD=@Tg04Z z0xIobpTsalU}veg=~ieIOEUW!R1V!}#5)fhPh0XTk`b7f%tj(Cjpc|U<2~~LGee*R z0MI!i1L`E5Nfl$xAa_>joH71LhS|KC8WBcmoaNpT(+XXj+}0lACWBzTX?_WAkw(-I zt*`?ql^!AW#nUVZ*X-&ImdhV%a}Uo_+>m>zYx0B#2a?FORCHMKvD5cu|7@N~3sUZ? z>wt>SP!G1)^V%g2Wb6n%KWU1|Pn!1nop~!!&3T0OFJ_`=bLNgxM7zxvYW=xSRD=)i z3kNp9sp+E|aWptDG<0mmQjBb~-dh5B3P0Y3-Q}g`^V@$PcDop7Jhw9kTnxcWgIc56 zQcspNe7QHbab(#$H%DY75HTdXczaPn6%Wax1i;Ksjj}!-+<W2rx~%hIAX&#LN^BE@`v=adKM1N+OV>3Qukt#jYY9Cz`7o8+B$p3^Bjx0_dpJ z?S};Bqb~q5vdc)W-6GP`OvRTCYkv!ZM!7QYFE@-0c!{w^IBMqr<;$}cb1Dgcje0Nq z{B`eEhTEB!7_vzKlpHfkJ$3NR6HAEC^)ug4*0Li0O z1f92+GzKYx{3F6tnXEHVVUMg09&5ta?C|sk$i9xMf-`KR)ESHXAz7Y~p?hL2C%U!L z1&~=5^__Y-Y?^@FQxtEVYG(V?5@rHM(!9Bc1e+1!;0h|=lDU$fx39Q^X>}hG+H7f~ zG%DJfc0S4dTcOd|-8RTCLNFgQw*kd7$HevKHXJY2@x{9A>k|M38HTQP%Jra4%s~c^ za{w&*O@ilA0jD{Mz-fya@~FUh3EShsU9b}E5mV@jV&G~DPq&OHt`BFdr?UU@`Nj)ILb^{Vn>GkrG*PNLJ4ptw&5k;d{ z;76k;#?W5q0-$lEsKBt)INog3w1%{UDrZD)QHHs_tms2j)7x_8HJ3_Qck3#yPF^Wg zioa+4hEA#xuW2u|1Wa^AFXD~-VwrL#7`<8rMp;`CQ+4B-OY-CQ;_26_FTD(EPR{Mk z@N=A8V&Mt>Xu=W|AG0!YgeByOye|vsdPm?2T$QAE1&uLNr;bEd3;HLy!KD~QIDjRE z_(Aqx;$~-&q&8HM#n{hPoQSA%q1cWj;H^QOuF^2SX!-T!BoWjG1T~JE_jZ=#1Rzk= zRe&Snd^K~3L%NjFQ9!0AC!F+BY_Lr)>Lq?5Xk9L=B2Cdj9r=H);TSq~p<;ywpY=W6 z?}xMYnbR6%x5gM@Yp*feRv7C}#=Z75u~rmO!O}TnNvdH$-8>sgzNI?uUXLjY3Ojd@MT_!<-~eb7 zYYp@_tU>V+hTJl;f-TvqjMt1Eeg$~@j_eqZjRjrv{cxbG4PCd5EoD9lz zbd}U=#QJEzaCA>y(X{SCtK6(BGmo)?c^ym9ZXp|dbFgdVr+UoPzI=_sLARl}GB<6n zTLCa(Yd}00y5!5MTTErTTP$yGdwQmbHJlD!jh4UqVA*5Ijf$8b+Wy=wXv-`K3>ugNh9XN|h#IO0zu zDa1G+zCGLcu-5luI6y(B#Zo;`6ormY^kAPBBx(_+Cbn*Nn zbvX}3s?2Vk`9FEPZvdaV5sw*Hhlqo*p<9So7BV&ozYdPbuFajxc9ncKe3t#>T#o=C zZ+yf5F022IW;1g#{s+3j@m~scIsTVI-OKOPCek*vuH~AM2BPsbVQ8U5#edKZa02k{ z&YuY2)8C;@4zt*a#-rsIXIL458Rd|nDJ{O&^FGQ^5?*iH{Q(NVe;bsuvouP!|K8p# z3uOOA$%&kI`11Dr`;=GY+ekqH=6id2T_VtZo)ohE_w`&X<6KKWr0p##t;V?v5)9!% zOm?}UP12imP)+V-&td!T-ObZ?zNgu>x%Y$FwaSH_=LMd(6UJ%L0R7yagLF-w81XW#{zZN zB79L&h~QIn<@{_m?xE14d z8&c5N;}I2|D;^)WL7O`DBo#vKQ}b^zUDUQtISfy5Yg}@1cq1o!ilTeQWUM6&W|kmx z^()S%q~_pUk4yMyVK7VB%L>?`TG~%|`d=*RK_nb~C2xM5$+`G)0i_sA4CBm{I)yvK z+v7jcBY3=FCg{qy2c4 zQEs%KjHIfUDJNiqhOTB{Xa6calfCg3hB^IJs)ACQunqH5t&DcX)S$fJ5U~|U&x4Vp zTnE33zIzV6kd;!x0Pi@d``|&D=Us~VaKhxF1>Y41%aopH7tge7_F59%6vq=Q`O^3yDw7v!V;ama5F^+`dFaE`n?8M66{Ow?S$=0OHH zP0T8tgb*#DC5acbEr{2xC#e-qt^UZ!thXyOE<8O&P$K$9?O?vVdquh)yS1?x~rMk-B16IX; z1OAxQOTrtz3=r3*7RGnG;nHB%C5Tj{p+W}SaRZm|c{x*ZIZ|37Sw$gG+wIO&BFD9+ zc^+#OKSUrm;wBm9k|4gu(yc`Jwhf)^?4k3x8||u9ecc0q7{kyjU8jBFU3sljQcD2ihTJe z@2C605NaWrF-rVa}o z8C8QoFT1F;>=6%%{HGx z$sNc;;xftDbOu7(=tae8ayv3*r)OOCO`{`2k-1+(!r~r# zn@od{XZYyERHV60x>`^&GLo88LE^^vMQf|3{MlNjkJe=@4-O3}^a3TFKZf%cU|7@( zNFoIGMRQj1RrrXXO_9Bf*o*OY4(3{;0BhiawFEsoe5en@Lj2bwF28`6q6RZNdSsjISwtY63XcwUk< ziQ|N{ikW{uLC5^|`j(ZB?e%*^QfKiFV4OF+d&7!=KW`+XU)Xw{PHDV@p#g2Ak&x29xCMB1)|l>kHZU2 zd4IKbQ`gH&`5y*5iA`(D{%r}XGm~mg+SpBQ2p@}icPH7OPJ=KBmpnCo@zY+SQzoU8 zuH9tx!*PaXE)g@{!(~AsPY`O_LG?Kmm%nB!!DLra9e)Um3yVLs`mOfyp(=4CXc*7G znBnQBBL#0_i{e4H@)vvEq5JhWA3rLFz6(2F(LVQU@1AWql^Q+<<|j27#msjMd4cK` z#W9(UB(~XNmWbxmy?|z|5I7%YNQY|e=wqwXtPS!bZwk{8Zv@XGYpN|=5}OT~oD@^Z zNTLTz$TwN?C3JsK!cb2=-1W(^Kt)PIMp9p^p7J)AS&DSH9p7C z+CQRIs|<<85D%zfa3FV-()J23%{#oTu*O<3860pTqhUl%1InBUik|70v@nPj$w$>X zq>yaRzgJu#GXzV|#)#04&CNBl}5 zTnjHNjwXg3|hd4mwGK8o|Fy5Z79)%5sqo5HN(a*&MLL&PikW1%kda z^Y#<+jp5CJ`vD(=T-Edg%<1UK|&q282LUMPkQu8w;8ty zI<-6%Rn&JfP7Rnplqrf;MQai0uh_z72^0Kk(#luvg~|ndIUJ`|q}BmWeHxj*fPo93 zKOSLmX>n5SDnjJN125T!rb6jWnC8c%?UF3dOs=3wj4nE6c*$9b>?!$#b2R1@#T`_` zw@IZapSk6%xGH4%A4LlQ7fKW)Cazz7nLnr@Rl`i^4hVKj+=3V; z7jH1myG+KpDsyzOf=Ev(Je0GfQ>S;Cqw_mxkMAO3wc);YL2P1%m%ATA&O0?HuMe{B zUj|l5bv?w+|ALtJx=mfDZOIQbCbd7)*qRkd%fS*e><@Pgnnj>nT=)kLL53&U$$^QWeHaWD+1Jg^ zIiS)vpl2waZ^5F>9G7v!H@k;j9Dzl>a*u3UFyE<1 zBPIR_{aC{U%iI3_VfUfE<^IdoR9f25)EdxYC9Ps%<9D#tN^CIo$9M9Ol@4?u_R4sy zfw+UdWR%&mC{=;VY_B31hU?n1Wr71uA%eV~sx|&ZnS+2!2SKoXQUI4ThNJ7KIR)e+ z(#QS|aAGzPEf^pAF!-e&bSs*Z@oMO8ws^1RL%+j_CE&SQrQ>)&r+7_0qetIa+}-cT zQQTkvXK5xB=M?}@>E!XIu{%UAJ}Wgv=`!;P+6{ZRzaV(AIVBrav+uqq|6Dkj2?*zL z7##55@_OI$*gB|;)8nP)fAKn|lYj2_*ea4yo6NR$v}?*d7h~Q);X2;YQ43c-vQ?xk zzp}b5LrbD>5vz^y=B(MAg}%2sc7Dh~`8j&L;gYCAop^ahGr2IfejR1d?8-&t0fOl-sj0im{2ZMG$nZp^C-O4|dHkn~ z1n;lJP!6CLg&eY+M9 zT!K9R7ooE(Vh@5jLNr1L!}tq`IrZanp|43w+PS-V)4>=v&q_wu`qi4`Ji^E8<$5y! z{-5azFH7S)2-oX*Spd%;#$j;xIbfTwYtsuzBzxd^T>w77e-Q$z`|o2*Qd&wO*Qi&* zy;P)_97TRg;R1yndH^y!zBI!TDL#fL6+SwKf1jb1LZUt|9q;78=p2K@uZlNsr5BJe zoDJEDD61`>B8X?N0lElQvM8rU0fgpprCr4S;KO_4epYM~L*9UDsJv%EH-BhstW*)B znRiB^*+lGa>h6)Abnl=zFF*YWvB+F>uE39i8)Sh-`g;%)K~HGX=jWF0jX#~6pUwbA zD)X7&k9S)QL#A_Sx<#B37{qsIV&+aZak>KZ(u9YS>oUF-ITD$aRM*GONuV%nBo^Qn z7;Cwwa&(Kcb4i^Vg~eJ(UUtEjGwh?djEW)*mT0D_5>_(K6rt82djO+wA}fqTXv(ol z5^ykJwaDXE#1R+*5c$TI=jL%K&|(A_2;iASX=qLTUUb)bB&4l8G$KzBQ$OR(TD-K8 zR*N%~t9gHX2q~P)86awKSh>0Fb9fQX$IE53EKYY0eLp&(Rjd-afmk8Z% z=4I2~=Gx6lo&J=e+;}FW7Qv?@V}vK>R?XtIkhn7wPvR?0-C_epc-iml&m_`_VFKYZ zskTE-1GUW^`IVHQcC8YSP^_Acy=~Prx91~SBP6L=9(Bn(D9M9`Wxb?XrZm!J(CD9; zu-GXVek(i)9`w4&CS@=i%SrkV!pH-0;M>UL>U^nm-!6%}@U$fo-7MlAu}WBzFDNwR zurN{ONIrf9{T%t1P*HFZq%x+UIXs>)inn~Hc-nOzDITZ4p%)2i){n3g5`=UoF|ooC z=^RYz&b<+ZNsEoFcdC^@5hQ7RK3IO`ym|UvmdMCZEuIh7%@=!B*D9CRX&TxUn+Eu+^P&F`Lm0#?+>{`2U3oATx z3Osg$aXa2|4=bF^FNpN2(*H;%xS-4tCK-O;s>RPB+%pdMLvXI7e|CnTvSj#WKi9Pv z{1Hlqs|7dbmh-~#FBYHR9e6(runceN>P$)ORFC}4;$sbc8;Y^Gfdla%*EjlreQg(R z`vMI{D%M&m9%d5X3WMR%c~GL#4mHRcv(+AbbJ((kr{5K?qwcSY-ZpyJ#xHo4kCFbK z$k271DfHoS712ii0G@e{d|KOoED;cb0%h0o6`IZ|#!!mFv2*rl&Z*rw10fA60#bui zJ^2T6af|}Uh+laJzdwT&(c|6?_oY%WZXGEUqr+oEBSZ$s6{c8p;tx)R)%mGy29V{{> zQL zzmMi1C!vX}#7-vFs#qv^#vq&yS542WILC$NVn#-te>&fpn|6770*uY$cJq0`p$dgHb#E z{nE&z5?N>>LfL4@9%=Waz7iIh+Dq1sc|fj#zmeTUFx*)!Qj%R;WClMVreJ3x_VVDo zFcfD24aF|=t{IBx@Mafdw30d^jjioSy>acH1ZGq8zPezu$pLAiI!AUE<*OkjkDzi9 zTW!KP6MNa>c;i8M>2IoSAQyKh%{$o>pJ*%XKi1 z?9zM@*@ukIzxXC_#S&Mqz9CX0_Nv>Ji21j!6)rJay=WFfMD zat8mti_?i7hpW7%7I2 zwh+BD_$oznfurCIYCNmAv%6ajN&AY0aJlZ2IqVcmsatZj12rq`#I4^S0H_t7BC0YjEt#ifmW6Jm4mhH#NgsXI#=njRKGGT59udPD!t`fi}Pe# zENy`rkSxWq&wy2`S6`6q#HxRs{dDrvR_&6ar2;OH_Y3*aps;ZsvM8~?Ke7|~60$5v z?v^sp)p^KtVw>sF8?$f>{Qk&~8b7XIBwy6!65T*tegEvXXk=PO{F734;-EgqEY<4% zAKBrW6{^+Ev+uJEl5@;ZwGnUfWhY)f&{5JzB5y#rN~53qdr1G4EHPCO!f+j>(yWxy z=xUXz{@2T}t3ai`q*I2`&@VH{mks=)R`4$rH(3Yr=ZE|#8j*g5O8urWOTBD%`&Wm` z9n1I8{xNTh*1o>a4Wr$~L$=IKrXyrmuGIo3u$`UQvPrdiW~(wT4GYiu{bfLrinD37 zdLff}zQL!ycVfX-z6wdk@B8lu=Dmz107bIE&aJ(2c^AB$@i6O3z@Y-Bf$*XO=DwkW zu~;T`H*nm6Z5ajCvKrd;OKb7 z%cmmEM+)`vO=n-nc})IS)%tG?o0*;UKVn=s{+;gfAFK_>|5$?i|EX4w0kI-bR%}Os z^1dJFjYVbS)qPRcbZtkt1zqpDO z{1;0M{=WXp78qA3nP>R&Z|&xN;~&(=c;* zH6s)urVL9PQcZ_401}nj*2$51F@+dflV?qJurrV#JQ%+NW-4iV4c#h3VihG-w69 zZ`EQkd42ORE=Tte0vLM!9b94r{3geR$uaI1^4L$z7*6n~$g7VyHo`CHu(5r$t)L&+ z?=GTl2s}dbsD~t2%yt~0SEb=X;jPvruuqaZpet!hC@eALHi7^txHN+tQFq2PF5Ov9 zJP+Pe+t5ynXWBzr^Mxfcdj7-Hw>NhoMA4Z>aR+#0|1#0Rty4{dAjB^lNc-(ff9I70 zR~Q6jVREs?u}R^FL&?o3sJ5_1TRcJefi;8pTsk4a;EibgFP#Coc#!<){1Ii?{e=x- zUaN6KKRZ0e=KhjesHO%d5NRoq9H;GvLNI?%Ib0;&9fFB)bdv?M%>yvPk+j;57YO52 zqw$~QY%~wS!*Vi9NOM5b2(*^#Yf9`8jMLoHzH-)}4CJl-rnIoYMt_tI#f$GphLf)SO<3Ujx0P9cIS+uLVlxej-IHm*)_Y`%CqXF2*|fR-zu!uH+~SEJ*`e$yi2#h9FY~tjXG&B7Qq1 zGMP>!+Xb3e;D^sp-)R$+OKr>QMhR)`HgR=2eas9H24X#y!l^6ilw^o%_BCW^e0ANb z@VG|QBgBrA4;;p;{N)KI?Uz7#xmPaA?7YKwPBt)eqBSB^WFX^{BRJ1Ye2K3HJ!78Fc)3PLQ(^hbKHNtT$9T z5k1|k<4Av35i=fMIdC?v`7G&J;DZHVR^eS{&TBvLE8lp$5i>+(wdy#$RX2E`-Num%v)uLB*J0r&fA5-+ev8Xobr5ZQ(u zj~YyU=_v@9yJ*6QcF5P>TDE9;SRzjpU@*KMwD1?ih0!1-?pW0tj%Ubzu6W{z&S6VH zVC*&R5wEaCgPrVR0y5Bw0u;8Cte3iF8ItB(c{aTVI?#S&WGa~SA%E1WPI2_6NSUo{ z0VB+V7BmceBP!zH)>27@aHdj~2XJ;z5KXC+PKu-1iNYAqmG2re6BFAwNS zJnSa=fRo(sauJ$+`im(DC19#)!J{A@uOSEpNz^xVfm7Bq++S31HHC>YDuwum*S(Vb zv*i7M!@zKAgM$XvlA|LdQS&X-TjY!3rodRcB-YSimlZ?$QaTlzFSzy#YX9IWE3!nM zZ0I^u!z8sa3=Tch>Yz0phtKTa#Ln=I_-d+%y2g@y7md*HEL1v*!3_X_L}n(E&gq*< zAnmR8=(V_sYzQZFe=aL_a>0`PylGAhrLWxg7=40Snf59) znNkyKRaSZLXtbsjM%iB_wOLAR4`Mz^I0YSY+0gkhGDV)lzL`Q(ie09rSFd2B(F6}2 zrZYRm28f0-6?7g{2lvcef~Z>vq+g{iZ<;*o4{>JbEVkd(r1{|$TVSD@d2~tFnng5c zKure7a&HTk6o=3n70zr*+#dio8mNM_5ZgI@|$K`pQ|z-;Oz7fXnQ1w9ID10|cUf{8okxx)`sZ79Z@8SW<27 z9qj^YB^_sepcfcaymXL7(m@|b}o-3>KqcEby8 z!8U+G7ylH`K?hVVcXm~5aDl&D3zg^K>aF)vK2!hNHgIV$BXYxIfA0w$l~iEAj4{Z@yRm33zXNaMUs*FLwP;?|1oxsv7x+s*RE~bw%zX9wr$((u5H`4ZQHip zUAwz|`af?@a^B>8ILV#NOfs3wmr2&WX8qPx;9)d*h;7Byo!<&2bxVSlIzGUPPuuKp z+8-Nz|As(fqRxdIj&W?Ky-`&4^P{@Jq?=HGR_OyH;p%u}M{Z&&O^k2kjEkr*HL8+N zb%VQ;NzNXxF=ehsSf|upXOF67Yoev|R#gka9PZXyi>6_;NXWvkq2fgV5pY!wRPm!KY-5MZd~dH67HpC>{9*tI2BQwJhdJmkVKL1A2! zm^Ym7Z&O-`@GF_v{8iEp`sC(R9>3VTTVzsFsNTxJjuq);{yDOX)DuJ$p5L7s__$C( zD{JtY7TO5X_7q-sjRe-;nYXiVEfrT(Y}FYR0*OwA`>lyvV&i|OvkRyd(M2i_Ak&M= zAq_=BlM4jeoHwGhQCkLMm6xmh-y$P-hO$+af3eE{I?ih*)TJmAf&Im|)*dz{@7=?` z@466=_9YlysC`F>{W%EqxHihAlm+w!7@+v|Qz#}cqrgT4KWF8?rF^kL$Zjg%&&NJw zc()4^i9iEpSBS|&5%MWmTc7C#JW{HO^U+VVe|fZG(u3~Q-6*XzMdRcRj;zQ)ncI{M zsl>H=lanLqN$t2QV+kKQ-Yp~kCo+tJ3;occ(c*=Taw(^%fUHb=opWfR)iIkQ$e$GNWR01f;k2l{;()VUM;k~6XEB<;GA^5$sOzcM;o zbw57K*4HD}cRptH^!%*Vc0i|Um-KeKh%=S-W{HZwOUG(E?r%Rinyf8+pUqvP-DfAM zGfB5g;LOuItFmhrnk7p*7sh*^=`-f!(a?@R0X31!zWSLOR%Hp!ZeLn#8L6ym9e83r z(v=>;G~SVN;G5Hl@4nY3`{beaXl2DN@Ly7;WG|t-pWh9kL`+*(UcG@0w52s$p5?O! z-pgojk4?K#f13uOB&?59eqq*Jco;i(EEg`ZXjR6fxaUxdijTeSzG@N{+1%BeMV;)v zUGfn$1TXdfm z)QT0Ox%&S6jCHvF>`3Rh@gM&@+_?SvuKVEjRq34ly|dlB<$qCM3m!b1y6gIjZxHVG zI#w?R3QS(?iREg)EGN`n+4fcp^%n3YaD=>9UqKg8iQ{+k@N*B|=YhrWbI5^@ zo9=)5WN@Dra2wC-fn|k`95%yCg8SPF9Y~0@!E;BjGD~2^>;s>}-64PxxR+i?uJ*6| zqQmh5fr`Zf#h`5~DyEFI1whl=wDHfSsvGbge#KWv=E~Q{1|o;&i>B}LM&^qsl+6o0 z^n5P20HgC(V&ZlIy{|r~-3faWK(u?6-?T=LyWFyJby{ zCs2T9p(R_1O%fkV5XU1$i>{nU`j#Da$2RbY*op@g=%uEk_{tUTLxgJ3n!D=qqJTBH ztLbySnN;Y z>Dfznvae(28AMempN%K-r}1ZDdPiFAD$|~y@J}`ZLnC69l*K+@>%kW9p z@RMf&BlLG+) z)tchlh%`@HK4~PgX$ZCERDIN#XNO%i6r=NDwWr#g_Z!M`-qcB(QC`QF;kR19Jutts zc-#UJMQ0d}Oo>#i=s5`#S1QQ>)eyehBZ3}dm;6?nRCK&pv49Ri2XI#Rj zow3XFmCk~d$)0R-=D)Smgba0`var3>*b3yOudPA5`8Vcvc zub+9krY-XKnBkJ-j+S%4K?G8WBxVUJoGt$adf4>g20+}VJ$NDVSP^mjdKi%V$v*==9t8j6MbD!Xx=m7 zE^5oJU3A<(nk#$%VlF7$k_o&#M2>psxNrLnXo;YIhhl#P1J;JG^nyLNV6c_ zZX(#WHY?loil6XCQRsS&@B)Rnqg`#VdCnVShs_3JRw#AFg+el{w76pbbtCh%eH6f%_UQ)p=amK8uJF2>sXG%5n%-%aJV#RTbmk#X07|3=E`) z0%UrOoD6$fVXRxFKkq|w#E4Cgq*lu$^FE^r$R9$OWEddUZxI1e-H9%SeYoF|4`Wa) z*kAS_21wvH$G1Z@ah>dgf{3LRM=WRN6kaZfzhgrqB^I@dPYkB8ZG-q;kPML68u=LuPZIy@5&zsk?Q9+V` zQ`)M+%%UGBFJtcWVK$Zm!P+H#CQ&(sSSY`wC)@ZkzXEPukG z)Smn}x;f|ll#rv8kfDmKV)$nku;D5lJn^bsEcahe8-RZ!26O6^tQn?-;zNYgPI(*$ z_p8Q5{}3-s#G5#-Q8IlPSrXWo_8+66^6u-)5P?$H;5P_6`=Wx84u%^FgtLf@zS1Dw zdm|DYz*!eG1lg4w0v#K#9cQ9w}$0@E~D90se!$Ei)*A=kM!4G)9CGkjie2H9jNs`BZeSg?%@#?_+?YwhprlsoaH+T9>|=#o(%UOI za1e65Ne`Q{%xw6aIf0U+ohv`>o&d16I}EWoj9v|5helo-z~=F!3Fyb(S-Ly98@xL? zuecql2qxwOw!`}cWY^R)c3AoW;c#cVjsT^FrkN)V_FFGxc0jA!qK@m7Y_}GtQvE3T zSpAssrM*4v^5+LT4Vh%R_Ma{%-QY_T>zsqFN68%{El^F(#s0zpOO2eyPz{C1XDM>l z_TtQx`8E(W!p3gJJQ2<&QW33To|H&zTT)Fs+WCYuO{iu`>{ldGO(|R(i{&5_(WgPl zrYQFDZ6Eb;Re`}vsip{tol zN-hN?7#6KGA`*QpgC65v2G@f*Lg+JU>JUl^u2jPwnxP$FY!Q9NgY6jiRKpU-e4Gel z6t+!*IfnhLs>bo} zQMHTeRNgGekck9Uyodg3y{NJ3F>K$^3|YRYX)m|YW)te20_)PVQLEnwU3FFAoDFZR zRoPTY9CKNAtsXz$u}|lc!^-o+1#U6@ zQ&&Gl`umsNK2?0em91Mlc`(>k%h2&1?XK3VWY*DsuiQ5$#H(2`7e_5z@AvcLPdw)f zHz#87=G)uz%RRv`s9qN8_4D;(fA;2{V1M(MFE2Ewgaex0qC(E_$I>nB)@3B*f zeri^UaNq%@C$7KOhxBrG_;S5dYzm4wBaX

G>F5`D5JqKdW(J^VEQ26oGLU`vKI!#tYrhwN+&| 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�B9#&+IrCEi)Vt4P;Z;HofQ6uES+C@G_t)Y1+tYa|DB@2~yA=@`;{2g;tiDA{ zzupCpKW9b!Zkc~ixdgnhr5yg$QOtxa1Cki8p)E%m8KX9;iA2yXqwGd$vkQSmoVGD& z4*{)Dx;{dKeZly>utOjWtyB>!tq)eZ$ouB&C-QN>f~Wox51bGe3CeG7M4hxKZmiLu zG&Q5>>J%5$UcXNy_<^L@N@|AJ?=&z>Wkg;sc@2EH7DyE!9$|lCc#4TANQHR{bLTJ^ ztPElE=+*D%>0!{{5K=8fl=elr-DryjE(B>_BWY_92#9n*h|E;6=@kB8`<4=T^sX_~ zt9DV-#ttRpgTY)r#v=Xykg~$SMk$l@7QvVz8Ywg<)P) zD}j|z#KVD2YUmlT8Pz0TCEwu=@^fy6*aQ8nO^zzDhkg%eo?W9g(rC{{OLDvPyyc{P zTw-iIv9aQasP9Oe2?!K~2}EMJdBW4( zA~5>uRcM$EOgvffzzrakEE?!yPrMJqb(8pnM8}Yv_i^!h<|b>tF%6qI7qDN0|(^1c8G1-pH6k#fGL7G`>Mcn-i^s z!LtReQd1(qfl6+u*Wx1$l8l655@FIwNcg-2q3C*siXf_6HzrJ2hlW!Y4Db=uN8Ehd zN;NA^rjcVnl!qtGNoeMQZ} z*b)z~ES`{7kW&x(%hRhhVyvR}I^Uu5`Ph@JSYC@bH6%`tsEcWB*&uVi(ORTVM(fH1 z8Y3`}Go@M4M$Tr}DAdRw2Y@b9r-Cl3avN!^)V`H+%#>>5#R1b4$VC5{FDQ%e$t! z-GpKrs*GlKMx1=BTo2P*#d+k=bA3l0hNg;?NsiJ~f}ZN6*eC~YN$fO_lY*;MU^08u zsR_}WpwIYcukalAS(XFRTEZJ54?_WTSj>{uPF4LKfnWNM1y=F0hQ-jJ3D7Id_goz+ zAqqw|Epy*r6@a(yPU#n1&s4oBYtw&xg14Ju2mHDX(GCf1i$`o&VfsrrTr;sMAW0up zQAx$BU)G<;B|jRTps&t2vljv$ORS&OZy|QI?SdSNIg}EHTi2VP)kB+HWUDss*(+jc z?!jWJaYwp$3Lpg#r|ls%p53d-g3fT#r_@i_p_$i4mV%S8ZHJnq-Fc*u zwZ*aZcEV=2WSI1r9TW*uhcqM;KQyNNuKrRxSbCrx1hGpvIlW?k`e>A8+`3!(c3z^G zW8ayhinr!B4`!zqOH<5^xSE+KH7~%9caLHR>ABDs&nmO(^uz~?k!~p4rZ{#!GT2?} zfn89-At>^+hT;4ryV7=qHw~6DUnlFl2l~CJgpIYcSb7J(O?=N2P4Xc>bdXK2!WJ?m za>!jeDj^6(nb?{}fxIk8NN1nUkJqFoBecFDm;@Y!KqSNWuqfP(g?2nOEt184Tf%Qf z_9~$rze-t=|027#glGM0qM!Dr%mH;RczEQv9R5=GtiPIZbekxYBE1m)u_;78fpC_jBsKO5 z4dcoGD`GLnLH<*}qrV@1Ok{Yn0(K~qAhDVZ4}B>5k9DLr>!;KWg-59H`A*0VR#lH? zm~ugz!$jEGrxFMbg)$;dm^eC@tA_xDKiQSCCRzOLc1#W~n*!C}V1tYg*C6r?+{btA zxK6ZWwPY1gTl!F%rkyGqdpho!D-QM{z|MK{#(o@4BE3e-UfV<;nFkZR+?DR+C3h{L zW-2^G@fk5Wmwn@t>J0Y!v;+6$GHR`*vFqx)c}4doQZ7MMoF`X%>FHQmi^0M_%mW&p zo119_BZ?r?3v=9Rv`#V!=$&S=5AUgP*@A}+yqdh*{e{z5@SgM=5wVCS#YBSRo!c_7b z=rNdq?CxSNwq9`s&$?J_z~_`9r-{#YTAp(%w^zA`sK>^w{C zPr!SbLV&^A+o-Hg%~hxn-ba(zF0tTaYxI<9)V8u5XpQoe^Cbg~*X*1&wp7$A>6yQI zkwVABW}11ap32^jZf8`6d4E>7qt)LWtZY>!x-b5mD?{G8b+WdSHTcZMoD>Xngne|e zzRb6tbZ|=APFFWO%EXefXkLGtwVp(=Q_g>xw4PAm^?a@T=+fQ26>aE*=m_hFpJV!H zJF8iiq&(Q-uH^O($Q!K>*|2h_M7*OmXl0{o|9FL1zhV^hL+rxERcDxt2XJw z&wFGsTDt7M6WUIzMEUGwe5|ydz(i55Z@HG~%Di^5rmp!sRC5;ol;~-zAmiO`jJbJO z$$}>`P1-SkY$$-H+m zCP%~6-cv;>x3t_ld06N1a+o)MU4MaNuNi&*H~sZ5QT4A>EAxL&N^$p{Pmc=*O1s1x%Ol-~Ypq^U>|bhkzaIZp*1{##@T`;<@++?nHI59oiTKayM0he-|V+wB_- zkf{{x>U?bY`INPZl+^f8L+Zs$h&F_|rVhXd0F}HyR<$#-pon7N+Y(VIWL5^>*}|TN zYi&|k&vg`Al1fU8GIC)86-9ij)^uvAz!h6=&bHTh!a|lCdNruLP3Np~`qqpvbmsHx{?Hr(&em z7%@ng6LCD8K)~=A<>5B5-34dUZ(&kol z2&*C)LM%h_RF@3cTtc4AZ2x?Z-(l~Prvi_7hAVBs-aV92mHB13<0ZOWxldzXh;oCf z%A{73Ma27s@ofg)EdFxALbG>ACCug|dE71fPu{bbz}WzEc5%G~y00u)*+e+^U=_z_ zWS-KpB1VchRqjR?_uwo!^R@TU1B{FK{<5p|qZe z^y{u@$XMS5r^n512$ge7N3YOuCH~-x3|H1zjC5P#zWzDWv%uvXEkGf@ZA12J}$rUGyoG|b79o>E z_bJ@n>CQyuj7`Xgg;K}R?@2`IaU7U#*Uq@N)MLwC#0iB_i+s$ym%TDb2=;MgFG~vNC^#Au zGyvSK8G(6`h1M~qyH&9>()nHNXUAWXY<;e^DS8cM4h+au-uh26ZHx;jx0|o0cHBfz zm0}{*FRwK@b;aa)Mj%W_JC&ia}C7 z5DYc&cD2nyAcI!$j%!Ln7DSFC1}50yx>w;Hyh}Llnw+kE1phnLo+}tYV{%vuld#a3 z6cVKDL+>t@K(*y&90MmHPY4F)=j0|Dz9WQ}XWanYXT?|@gBSjMjgUlcTFrJEmZlfT7{>Q_MpnfDXR(kLaOfaJ*g;~w4f}q5e9tgeNqW#pu{muL>r?()*f)H<& z(BO1E4X)RfaMSOPnSw1vYr1Uvw`w<+ubF{Q;T`3%(%7_;b zzH#;x5TVwEX9_`MeWGWutmQ&EDu_Q;xlOyhs%LGvrjXK;@q4R{NU{p$J}_Z9!<-`S zN1gYUP+L-H&wgpluo(`tF5#TALEpFVZ*%h{Rp=HoZWMqEU!XhQLJinlmhQOnbOi5N z^ezFVnFlXn_H6^RnxOP+*yI%UR8wV=#BZHySr(dZF&*Rkb1n}Og7TowEWq2)QkUP?45#RZP&KlI3u=g+qP}n#)xg(wliX9 z#I|kQcK*!yt#|!%)tVb$)m^>Qz1dyQb=`fQ$MHR+AgKC|sp`#mm@}fmR)B%H3hW0zx_V!*!6d&j*H zjOPw#PlY9TVu#XiSOax*uVhIXd#9ok7T%2Y5y<&-b^$wXdmd3kyrMdMtez_xA5YQCr38T7pr0}?yk)Ss&2KMDJ0*h-Dl7qbun_NP_@mk7o z5U0dX6YHuEN9}9-T-zkXF90nB#pp&~W~}-TgMqbiJ zn}n}C&RZ}DLgJQ-%A-F*&oR(cgNd@k+}k~`tL}VPYmkMCkEVPbR^+BAj<|c_+i=*#mK7YL z7>9rkU=J5c=Yh0Y=apuM#a-?=Cg5V1`myiqm^m}!2bZmQbK&BNDUeN#(HMVAMXP#& z^}$~!w#*?1za0&@HiNWK#zv&b1uHJ{@nf%a-%y>&hB%J>{p-0N7& zC_MA_QW}drU`Efe_3NMQKyk^Anf9@2>M*svkY4MHW8x|@f4*IM6zK)HXNva6d+tj3|kBzX1tNP2CX>lR0HC0z#wmInVi8D8v#$#ZIe-x#`K{b}7 zIKY!Agq;~Fz$rv@-XTbQX{0>9bC^{Ud5^i2ECRehEqU<;LYejMq~g^Sy)in5FcMvS z0A7*?$-6{Hv6L6m>dJ^f_Z3J*l7np{5td6X=qGC$TPy3qwrk4%M3<_)C<&<_z13as*H+kMlSsS>>)qTocB0Mi=#fD?o=;ea!~*HILu~^9{6>U&=#u z;B#o^!=a8}_imhQUbewjk2b^dfdAx#u^aV5%yygb)YPP7bUlb`D2yDaADfEtn1V7b zf=etYa=EA?odBobiEtKU4(8lLy8RV%l|5b;6mxGq_&!%jlWRD^tvDrL~+k>9BNfWMo`KS_)?La5@{rCM^qKA)aan#-U zZ6D9o_jCS~Z?}T|^S0)1=rR|{VJ8m z-ow&-sqV$#u9`Q)56ykRy=%qHZOWqkVgd+{KNJ~_YS#giqMyl>L(9vNKbnK7M5v9n%Yv5jbH`#y|FcP!ql+Ta3hWt2=d zbDZlwsANg%L@RV1i2!Jz4KQj^i;v4&*DSE=KK3UR>;m&JQJ*C6`Q$tpSB2Q3Zga2E z>yiDPlB^l2S-xGA)4_v0Nm|oBGe4wqJSrnU?X z&1Cg1`Nv1ap({)i81UCJh9Si#5sYP3ai$^Mp>*+{SOOqKG}G8lqlrjmjkl!<$B)_{ z{#VZ~Xs@E^j}Y{lv*F64WB%Dx2K+dSL(<=iBJHDtJeA!`zyn5{ek^?9nrRSwpX7IDpYhyQHw%jlE6~xu-0}q-8&9WKNpm zBhA$&bPf2+#w4>F_7JC-*)e6<)r%oyuL!?tsY|^q3;82px>ir7iT99;)UJwt_c86; z!jdCnJ35}Fyzm3pVOu_C6>k*92>;HzgFOgJDKu?!2QbVwdujEV!x150#9E&%ws#ks zPE5EIafk+wIUFS?X*XbBd%J&RIXz0XEOcUoSDe>Ma1|$M9E*PhJ{EF<4#wv1kBTtyxRGG7Br7E`@Z1>Z zt~OwWu?tOMAIWi+Us+K<+vpHGF;Kc|7d@S`PZAl|n%G9vO#%oII2FWQA@LPr4}QxM zyIzjFp9mN4;RCw|>&Ih-y)HoXTSDDMGeqp3)6J|dXwNC4{ty7CV=WoI_V3FT$d<T1jI&IU8rh$Qu)4&NEi&3JgA#Wx0 zujCZQfhjhj0Fhf9f+(PJCj@6VVM?W=L;Ti$Y>jk{l#va2&7-B{pz;hMj7J{u%rWWS z>cHYO`g>mw_SfKUC0?Y&m35q=4Rh$BvwI5#=_Vqi5sV61cJL7rG9cu{V2K2rEavnF zcT9nLkWkF$^dgMk?eoZjH`Ba}euIYNu4d&LfAvt|8ixwuYM%ltpA}ud-r4 zX5TUrT3EWAt(}uf@eb3L?PAV80%F`WYV`yik+l~?I=kK5fiO(!) znRF-_1A~Jf(#P}EYyV;qYO94BG7WTA1^RZhc;>N~7&cPB!zoXlU<(nUr&M+*?kqW% zk{K7xeS0}kP=+ab>Dy4C)l7^xUOB67rr6pr*Q=3TIS;EoMM;U*jwbv2N~5^PwB}85 zSO&vsp6G*tAttR+lZB~Br0TeOBOs1=sZ%wnu;h2j9T>Snq!itw=8)2 z7v9?I1C9HJb-%-!3@17NNHvuvn@)gRikMZIgA1lrJS3|@6rj~-iB(Y?wB0gI8J zjNBzgO}SeM&Bp32=!w?J{TkGVqjN?gPWDGIP77pPs;f5=YQys&SZ=Zh!Y*U*Cd?+a zjszxi9J)}VF(^o0IsqvFZWY_qagy_b^2iS4wN)Eyekk^iml$%2+0vR!b6-$0cA6Ce zSBnyF;r^}79-vM1C6k2E7^QZP2D9I>inZT)4SML)aCt{H`_MR*e18y@Ap)-rR)37=ViaNTx%6KTOp7S8bWL#Qs?jKlvFU6$PV{qy&NlGR_pqGM zg~_L5c5IsEvd{a0%X-yZLJsJF=9lvC>G^aWLT(vWigr+HSo9jsrrS-RtE?Pbh~Tj~ zE;pWLV4ynxCVStlo1l>^_V~6~W^SE1GthP~m=X-exVl2_< zdqEr~gY4^ymHW8ZN0KZZJTZD7js)BuCL?UKnfSZXCH~_IOLd_;r8s^c=&EUJ~W%sG#Dko zftB`jsSzy4v7#t{=Usbfg=>9^IsW%wuf6NA&5cS|Z6KHXufcH5&`@&Gh*KNMoCB~D z@&z_H9G6^c3I+8*yV68GgB=V}HWrJH_<_3u<}O`W{~2 z)|;}U>y~Am1^COlJuo2Sw7$-xo?&y7%K4=KRB^~wk#ASA3}e$&3|HdnY2s-fU%(!@ zg=b;AjwME9CEVy@79l+1q>HL)nDoV()3Pfk940Er95XkwZd#LxtMSavUb@4NEP!tm zIpF%agaq}%P9Fo)%?s`WO(-4~qBKk-3jXUtjC z(|M1C3g5f&A;sBnHnlA)#9u%mf;H9N z1_AgavR))ZV01SOxfYj7#&VF>W!$Nb`4Em2C*CkwFufq|G*~sH$&Bs?IKwN==)WJh zBU7=1!Z?6uA}&Q`i94w3h^P{eLbZ|R(l@yvmn>a>cK~+E~ut;Hf88&Q?ED($jf~2V6IQZaqpytJR@avEIqm|vmmb!yrAXg>6o&yTY zt|bqti@pZF$%a?JoTxu>aT8%F&1G9SjA4m`yQ2 z>-U-$RjBMGBSbChX5EvKEM$ew+EG*R6HwQ*j7pXdB#s& zg{3S9N+u)e;`et5qfVYRI5T<%YZ&0ca3vL#JFe}&&h!<0?4rVWj!?1FdSq$`O5Lk$ z4=$=H?2rro;(iLH)0hzna3_#A6MUB0%(W4+RZ13La&!Ai7Gt8jcPOIpcj}h6cXB+g zAp-)YlCVeI5j$bad|kvH(h|bQbQ1W6BZl^hL^%iW`J6XRQscWOrZ1%1me3w4)C0go zt@@RvXBAj8tp)!Esw@H!V8&Av2=LJ;vlJi$Wi=qCSz7~r z6c%H_W_6a-Gc*X8fhrMUyj85js7L1SM$`pwkfgWd7Lh&Z)=>d)uq^di*#Yusi%FR9 z4A%A&zs_1gYBQd%4(oNEjnyIl`SHnA3en#LNRJsX`yx3`OQV}+v0x*G0e15%rAl4xdf9_o0JeBV2^PUIa$_c3M4|<`H{Azo8#MyJC90P zRp6))Vx1JUG>zbVl749mXKZ4NnecAg>bT{{V~$N$JOa`~KDO3>wArQO$=r&@>?M%~ z8pugNJNtuqC5Pm^TEKgKrJiy+Y8JCBgTdZ~=3DXvwA!%S?S%D6DaiCY$nN*uk-z6H z>A$k?%_S^m1n-nUlH~j$<(t$X37EKhw^&`sGQ4$ixk(p&C?u8z8SJ>?H2Qu(<(}5} zr&+x_mCT=(V$agk6b9ntuD%p4!=G_-!I%yUh#6VBT(mQgBqQle6wd8Zr_{y@wR5y* zmLaDEV7^P^YobAc?tRt+@0#o6)}Og$OxV$E+2FZ2=HJBZ_pPK1FV)eIa0^V^S>s4; zO}z=;f|ZPY`@1aAEO7NSrKOt^^GvWdJ{n10*Tu=0lhoJlKDy zu8Op+*w^$ZRBgreXGEG#?sNXVpO17eVaCKxy0pm(01b=;pO6d~FI<`|^Ge3BGGnft z{N1Ol1XY2QFfr>KCKGcmd5Vmasu^`2nJg7(Zk7g@LLEG;UtnvSZv>U31d9fr-|p!;*#V48DxX+ z1paoz8rMdzI#>#&G8tb!lLOkMYw!1s+9x1zh8ojH3p5A7qU~WSpJ{Gh8#> z>iX@BCEh%C-{Oy~;ZyzdMh-%-nFVnAe5*^hWk)(_pPai)KiRI;qQQ;cP|p3xlAqfy80EWg#s7Evi+ zaEO>J>6~TOoR>wytox45C)ygvCfO9$)}9*=vFR+wDQLeiG8|*Z(@w!+)AVFGeoiXe z;e@m4VT5{rhxL70Nmf(>nH~3w-FPJs!8wMxkAy)??;ab4RtG2KU3ZJHw;gnoez*s+}{R&BBr-4d|&+2xI5;F3U@!V zaaRfX_)Eng5`vYj>*foCChna){LTuP-eY8At&@+hAIR%Jw6k$ZxQQUA=S~?)>#oG2 z71@E2CM2xFo=&p%lJwZV!Rz6=SO3e%_&;;t|8NT#nEu}jYDW5h;41(3f|`;3e`^&z z{I^xK#^~*)MId{abBB(J@I7AKo zZ6D>*pcjl7;0!%Z$l=pb`prOl!3Lh*%wc@}lDMqgqw7y}Sh*YiVxb1@@hWtub}c zfEa0EgSf7AXk$z~rM@-wJJWf96iu&B=>sk8e7|GzYmjV01N5T~9Pc#b{-|eN1Gvd6 z$Z*)K06AeAbJF8FGRi7Z!MuAms;F~fBROT6#%(0KDHoced=WT8_(pI>kjaQ?qBNn6 zMGwPV_aOo#m@MP098`HGuX6-ZObn^M`a3cppCJAe1ym?Rk$Ut3>p>DwvYmz`E?R(P zNKHM8pHw#=QV&{YeaPdzA%9lPN4Ab|G{o174WO1f|0yX{71O3P4zLI^6`gznfN*?I z)K=>t>>_Olt||hQp{q1?gK+nss{%s+#4mc`)C*dq_1LSGSeF=S7P+!U5v{)fa!$&C z6C*4R_zwYwF6th=jpAh1oH4Vg!T~-c9k8a!1HWMT7T>yYf%vo5_7m9H1!_nf6W#IR zq^gBZHWA;&X;-7bEoDb#=_VRje zg37302=iN6^8<_OK@kFftt=iJ|01a5Z&6nqgcWo--K-zDd2#0h@MYQ>b0{$LNP`J+ z9!(Lt9w3MDp^;3-#7*1CK*uG$f^rk_Lc?50V8z>VjR)!tNF~5G8GuV_OaE{<3@#k( zW&Xy3h%$}FkwIfVOu%vPR{xAu0LWhZL(eCbk4WBqe9)n$FZ=$!0Mw%P;M6(^tl}UA zOf1q^!D0tT2>1l;e;u=&4g&+w&PzlHwe9S>fN|!&IUkY(%@auv=xNsrZI0#6dv*l& z=n{nM_?r&^CXr<$4!I(f|H#Hm3{dWOAb6B0lgVBWs3b7G4yeY&AGFdKEk>j5#Zq#d zhVG1tM1gcOYgJ+qosJ;dF-+o#-z?bEep(??)HU)nBB!*L_jIAYIwt3lce$ z+miC+RarC4%SnJ3!xs2TmK(&+w>e0Z6BOkpoEkWZy%LoAWYNPCJCi4j5mq`emzZ7H zR#2Q0hcIAEacm*)e8m+mWxcLKLaMkB(?1mpIyG$J)7FnrRXTe^P8lg??AyP)yw`G6 z`dTe1tS_(84R|$3Gphs;)I`XGWzNSN|58F7R5xa_E2>M?2_z)9yRip36d0T*1SV&1 zt)RT8$QFh3y_9ZrdQ-#NI2!9O`XE4f0^HG(cwLKt5A0~q4_QohY{*T3RJP~0J@*~> zL{_QV0_$Jtm)q+jgNl7@|Jud)Og!2t40W6&m@=IwO3D;%qFfvc$c4%`pq(CQFZAu_ zSXVAtYfA4kwr)n>WKC1~pg={szm{#BE?hBp8J7*r*>gx6lT{{DtUGw1er-(UO!CP~ zK$w$V;2CTYBPlXWEJBD9upz3o8)<5J$QuQ3PK^os6XDqg076jvtQ9)-c;AO!DD+I_ z`_*6HsCpL9&E&ZyKiTSAc~{zEAbOyg;5$KPPxK=yJ+$S9*y<{sSpE2gTY^A2h- z5M!ByS6Mrl;ylnZrW_hlN9pu)lZT~Hh`R+NnTzzihZ|sqzfY4qe3K9>ELp}gke8=; zw^$=PkmQb@nnt}BxudV`yyYM}CILmFy5I3x)%XDlFLVtH=BVp^wr9>ywui;ZIaiS# zaw(BeC?0PCtUcJ<9STS>D63Eb&O76Q0vB}v>>!r+phONS;^q?Q1&`b%Z+WiBx2uk; zq>W1WuN}B^ygJf}1m>^G(-xsk;YaD zQ*x($@|WTU@HK?oG)}WnO9mhLou^hzOm#o`m8R!SwW}q^C9dv;UlMYqSx1eO&^9v;h!|}b%Ujn+3;-g#z;_RQpv8}&7(bPcRj(OCT_~@;%c`XPsNDXb zJ)ZAkBcoru+B$T|9>v!B8J2t7SEiC{^$oJalkeP$Cub042>e_L<%h@Sm0PWhnR=dG z))mTRHr5$)z0?LN_@U+4!wwWnHL3^Q{X|~43Ou}=w%MB0lhvljma^#`_{^59Kx(lkCJVn@4Mkrr+n3?97+*gtsNbPU%BGk6%ddaCJlmC zNwj@3#cY7{x3GqWjv#{m1TRV~AJ$=$(?=RTw|%)moG9)NsHl*yv1gl2R9BMNa~>RP zIrKis%_vTI6liQ$;5_+chmz(_c2*KVH%N-Z6jph^g*~w;yNf3P=PU^**_Q1gaB!r< zKS}9Z-&kT7$5B%u68$EhL*BDi^_l^az-hceif_|7gTL%|T1-MTRvGHOk8k z*ix#@+3y1wQy#8?=8XIiW(}5Lucb=8J2FO*X+_53TgfR2HOSjJ>FXj!(P-ECQ)4iw zCT33j>Mxh%Y^W%oiy};k!}Hss0_Jv>jU4k@clA#N=jQhTFDM1uHK|hJs!xlAl5p+P zW>?+f#`v^-zy;D2`2N>{_n+4|B9qIE(UP{pYTTk&bwM)```cKUjbQk`T5Id#L z3q&`}RIHL`&N7~e?kS2YRW3?qeQ$yqU^QEp(ZFHM3O=l~IO~G^K(!rdJfTH6oYDou z)ft=R0x`C)I*mw+xtcQQAQ4EHr(y0!j=B3L`-`Nn3GBw3M;2{)W~>@_81R_pfjt;l ziGm1^lVeX{m6YL~_pJ1Jnx`5RJbNDPZ;!ynPqh@29I*_EoH&U5b|&%!<&wM3aAM-m zoRpLth7zm6Tr#uqLEoVlVp3UKOW5o$-$6nl#gJt=aX^g#75=5c6K~UY^^3b4=(;Rvy5!((x1{x&f*Tn=t z(YBMI$BOYyM~J(?kAJ$QN0c+St%ggds=M{^I zY%!;CvI;E?VgutYN@4zVEJr9GU*%t{&P2bgpDZxZfs88*Cu87Zj=dnSHAT=fgfUcw zT|fg@uYDcZ%X^^ps6eyLJc31I5T+mW^>s zR+WYzr+%q>8W4cEUADE|c>mFo$JKgZepjwRWTi~A<)z6M(wAd-!g>TIyc!-mr zF4&$N@Y}x#0Ekzr4H)o%$cBOZXLUl#Q8~q-3i7rK(<>Nq4hdT$eK}0Uuyz2FOrvg` za$<63h)Do7*N*}lm>_-~!N?&_e=ta1U=2GORzAWI(NH8z^1A*WAP`3BP&)mE3Bb`cO#KsI+IINK2ijb5M@iYj%imvMc^+F)0fdOMkU6FYOAW^X!j^UEB zj)CiNwF}aO1hNhVK~q==!2M(Eeq3@dQ;?^XC6Omoiyr{SxI@VDY=-VRaV$tzq$Q&G z6eN>L)?;+t=02j={J5A)oj3$VQkz(OEyu+p1 zrvxSvA>y=~Gd($TQGLPdq%~r~s0T4*OzJ5)V*RqjB}W&R|6Hf}rWK01@?16KVwrZL-S^*2rPQx!k_P{4iT*7&=asL#?^@k;7nRQ1uil}G2t+z%6fIl{gm`qXG!A6bxDcCx zotgXRRCr8WT6h+{nV%}ePdxGs;5{OiX!$Dy3yj!VhOV04E17t!4Nw_-_ zUI0hg5gh)e;()n3(>ptrY{Mumn!^Mbsk#;0DJ|P_@gy6{`82Lt;VB*{KtLg(dTP%< z&66=&=3#1a;#{NXhuev?YD7T$b%qrUWj3h#GYSf&a%PY2PWxnS^?F&C`52;l?BI-Sw7(cbz1BxJP+qEW^<)h`{hXjsPT$MB0JhE)j zcS=YHP{BSCouJi&j5C~umd<+1@BLBf^Sd)sp{1m^y1Xv5wsM@BY>v&DIJM{f;zrBW zxaEp~pv>dTkPbw7n^GJ)-_jUvS~;)qSA$`&JMWi#tq(wf0XC<`%0&nD_t;p=F(z3N z{O{V5j)0K&%)1DYFSv|5O~UZ8?z-iu0vtCfSm%jV*v-mCe+RqCSzWt;x_!uAwzs{d zyv+tQE_{-~Gd^9jEDY(yPir8&O*AtDV)FGoh6fUibsO=q$zSsY0wq^sXRPBdnz3S+ zW38goQa5qDn|5rR*__VnS9T=QZOcA|NU3LGzES{DL^C=PONK9XVi-C+_FmB((NY%U z@up-6iMDq>YE^axxSS!41*a4rN{<6Hmlh3NQJjLM2_s(2L?@`B^j>ge$@FQq&|^ZY z?1|3Zc4+l^B}OQMA;zACU9~x#R%!Z1`tq&x190Lw|6Ve7h!U1{Zg)x2qv(nax?|;y=|{d^m!uSaZEETyuH9dkr)?z~@y14PGvHPepX3Wn z(7L@i2e|z%rx7%=+ft_r3_%=V|*$#pp+F2#gl78f`y+1Mw z$MKSu8TOfZekTmr&1}_({l>CKL-N5L=b@}0BeEW!JYSD%PODw6vfuH&zF#VNXR8!* zYz#`R9=M%y#@+a-uRryhphX0LUa#33<_MjE!-+oEIGj%vAR(bL~y!oFP20DHyev38G z0X)9v=yt5QB;jMd_U3#i1Xx*lbv;dlollXayE5GO>(g~8$;WR=z84+7kEipNpW^hc z-tGM1Zi}y%=hv-`USF|p?|E!D&&TZ~ciGL=wQpO+;ZaRw=jF0VC&h1_96Qu4-3yh< zOowHW{`W%)ZPe<{vhzJ#*y>uRDvw~k+iJ2GO$|4EFC5xssx7%`m{sQ$P^xVDJMI&OQPVl%?A}a{$aTS^z=MdVx}(=id5o5XIjop za6MZ4em&oh)AeV(ZJ%;t!yk0|Eu5u*KRZgSgy_dgb3<0Fs|1aEiYgh2jbw`>*LHJnE>qW zQn|!e%}-XwJaiEiG! z7gmn0g^l+*gBXBV;a9DMYoKLntDTCEm{-wzDW=t?cRC4=JehawAsOA*@5&N=sye3g ztG6H0Fb;_MBI(GunG^6U(!HUQYYb4XYtK9sJGjR-ZXS&6EQ$!OXg9){!U@io5#REB zzy(niKhDc*xWtK3C6{Ao`!+UVKbx}z)34l(OcmD3Y+W3O;dS|9Tyk;>StYzrOws>A z2YExKAoLacf-j7)kH}GvMS$RGW@Ou-^s?Aha-t6Hnv=j>@eUq-oghcNKOqqH$G8(( zqK2-?0S3*3aGA~1Iq9PlN2|~NS|KXswuhxQ?uUCYl=rQEh;r+WWlL|}Cv(KbXX*}u z+5K_7~oXFqhZw#STEXIPNNt(H_9~O*pphn&AM_Ry%2_Jqz_E5yw=@JCTx(6 zUy^{~mgt*zXmYI(@dc}h58?w;LMp)OI?|eQzZZ?DGj_LR&i2wRz3%$m183qwsGTRM zZ!y*(zaBAB*&vFmYDzht(PP^#7xmG4TP`Gi@QTN^LNwFQVRQyso!>Ay2pGuwl7=AK zMOUwm#k4u8UJOjQA_y$3nHQ^v%0kP$Fqm+t z5)0i4V(k}4!xf94qD2j%bD8A$wt!*4=w`AdBwE6CaURT6PTgT85f zhJWTpy(b$u{{FqPEs<<$C53wVR;Jt z)a*%SW&4S8ZrUJyM9atn*%a7Urxh3lberj{A8c87@q6e~J4Jdd3<)z^kU6y89HOTo zxT!N{5GVjm=px}D1x2 zsCGdpncYLDhv0RF+9`M@&Zd}pNA3ZjomLO1$VAE8+E+-3qD#0N;9x=5ww^g>E)qbB^(Ti7;Q=8~Nbm%zUB60dsIGEnL^jyNRttwF zLg`TjVU5fTp)Z9Md+N*#0#v6b%z>Gm1$7M!1AOM7L)hNE&#C3xFG9i(7l)P(K z3O$)!pBwm963YDhd0Ckhfjg#_yx?9oHvb|!Ceu#eUl`r%x`+xS%fXYlFC1^SKjuS8 zh0Ewx9vrggUhzO0+NLzjH_FN=cHEYfL-jq6xsHN-GQt+r3QXn~8YCnpmJmGY2n%=R zvv8pza{x~(2+%Gkd>s9k#Y&N^-{d`vCkliS7&E=j4foWix!k!6Z+`?rLr`?&9GPTY z=-(1mtvO8FF&YVCjW%xoWgwtFr%;3&%mJAn6cKF?O^npWAA76CfXKFOZ+cG^tRuN7 z78iAU$9fD0_j~CFRT-)L`#lW^U?2sF2&r_ zvO1bPzd34?hY39Mc*6Bvu{zXMtiEWh6L89SB+fv$!sWCL zVeC7u3iQfN^FbL`iDPL`w?a4$o7e^ZVIODpS&k7^AziOtY1-}_5?L)Qpv}J{^XG_; z#{^`+pl|J9u#_^_NDL!=z!6WE4nwtHJv{#w+ddxgik8`o#q(t z2#O%6DuK%-9=IOxgC_dPXayFYP&Z{XgRA>JKU%XbTM{00u>y|KbnA!#gwT-mp>}zB z_gM(>O@i51GMCaUkQH9>Jui?BZYnduEHj(D1#uwRtM|q;Y3a&06 z(Bpp<2!HZS=4*FCReItLhIZDfI+M1Wx@;SFF`g$l+0+lsdRJjs?V@*HMKO-4`iNsj z=J;YZOEfqJVIwcb?FI0ff^zsbs;~^b$v*WU(8FaGd&yv^_BL76M(ugnGe);9i)W4ge4qEIQr^tir6u=7E{W?zph=R9Jb z)~r_k-GyVAndvPc_vehcUYJJ{Up3}Zw6>Lki|V{4+sWdR&*1AV=nt^FCZavN(OkuX zGjF+QjK$^BRKtBu%JnR*4Jxgmd%lXYY&YBUw?MOD(oX1eT`}X)93H(-YSH$+Zb8rbg1V1x-w5VK#(R42^%9CS!6O} zh76dHBWY~|`ZL~Ny=`LiW@<`Fkz>4=GC;1eJDka2S%U)-;Uq7Fp{TzqndfadQ@rWC z=v#6y`N@0x!P*aj4AEy~%Ca;~r;|94wP6xCgE`^6l>+m(hr`lbDj>Vagg>Bn@)t>4 z7JG2eMBKmyA=D2w6+oZ!Vl)7|d-=6u6Gc(04j100_^Wzs8?w!~>pV9gDzHOrnC{0l zQe=-W>HYCo>^PaaNM*ztiMoQ1?Ftem972L;F+Uu}C({Wtr*6{lb=D|sgho+kb0#Wx zHM;pFVK>J6YRI=KdfS1~YEUWRz3JK|?y$iL@D3Wp>o^}j%PkC(9i|0#H-0+|&#x^2 z&}xEhzLKfJ4R*$WvTLe zZ|3|MH(RC0_+kvpS1DjY!4re5`S{FxMk=q$kS?lfd|g5jE~|lD6jL2CX0)6N9wb>f zjCa8L+SQfQVd!5+o8L06uN`i2CH$Ko9eBRe}aWUN>;s>s7WFxFK0 zOd$`SSgoa7X$VpcoAXDEyu(pcJKb&Z;G%rst)kK*1_tk4aego@F<)vPnOY^b-q7Qj zf4{Z(D4%M~;PBJM@uB`eQm8W%eXf+34KU(H>5cc@E&&dBD!jkJ=M@$vpsZFdyACX* zqkp@M^Iz{y~GK0X6Qy092#GLJ23GJA}EaxUwYP9Anwd7tt*;o!L9fts~tg zfEu5I&D}!@qJ`T?=|R~tbS*3F1eQ`2!S4!bVi6q1FZlM}MRvNPkLe)Cy8!lec1l6k zCz{{=S4?!f%!AUU71#VTQb=lqMl4MZja(EtWcF^WC@sqh!&{P7X@UmsZrS}v$=FnS z?#x<6^OXKZ?Iz>}qV)S11^)j3VeFh@WNp{2-L`GpcK2-Cwr$(CZO*oB+s16$HfI0* zt(}#vy>gahZsjJ34?lD?wx+X49%%%al?KUlWwmjs~*JoNxJtxJm#C(^R zkOc5$1h9A1$f}+^O#Kd87 z2(NzW9v~{f%0ch5rHAn^tse}W(;iN=G3$ftM!J(a$PMf9`R`o!1r?)nSw?O^-R#^l zP;DZIyAxUY%BoRfqiZbD7C6an)-LtW)*((#ZCh0<6YTmJ92kmtcrSq?hRgd#&TSS- zMP0c1HHBEk(BoC|;QeLd(4l<&D6w@6!dOGSF6Eebfs=}b{`P?{=-TR=BDMT(d(KK1 z!6kB}!280>^+N_Q@`F3TCB7r^6T__V2shMrI-zC#s_hyAWa@EEw)`DpX%l&c%*EtPVt+Z!ZifC;slkle z%kzmIhcX-a-&Bl$NfZA#16de3|F_YYiShq$G-hJ_zcm_5*&VPU^qi=@YV*_S{nKcS zz+U}GRkoXgRWbx=pv)W7+x>Ze`|~m(5|(Jkl_cbXQW!LMUD&mR%^UJf_9O?x zLgej1E;?6Gwz|-@Rk5;KtK7iG8!V%>UESlxQTV85W&x5DT0C-Cf+8K1lrnR6_XdW4 z8;jgC=5~d85&M|i4rTQ%P9PYFLvjmDa4g5^Bph4P7x8A9F)OysrWZ%ZWjBSD7tz8= zIFeu(j+c?3-$%fCv1qa;_n$ASmmlsapJ%vB&quueym!O)z1Uijo8hl$^cZvfq=*wF zqhE5p4A*~i6kfDul#GIg4#vdwo&=ALiamR*%P>jM2VYYipC@sE+B--~)$va&$Sz0+ zXK2M7ItKc01 zZ1ta~su1dJR+_~@!m?fjJrS%9x{`eZILFBb*umF4cfx2?wVfu34iE--!eH4KA5MVT z>VYwfB}AuKN9OP(A>Nk?Dr(zzPHrrLn-AW_rA3B|qV6$mYl?7PAai%>OPYtB2}V2V zM68-pe7P<^-W`AO~D5X@)C$eC6Mg-7&8F2Gl(}E5L&p>8XP~>=tzjYx;C63 zbRScg!|=Ix$v77*LW0?GmU13@df22N639gH-WT}*L%x5Ey4G7F%4P8Zh?+? z1Z!W2lM?yHxh?=M5Pe|mJGIC?BRi|S%R(yB@+5>%Z$ zh*vq|+n1RaYq6V-0X%m^ql>4U=v?|q5H$M$u$d`qk-f&m4T7?`@z(?A_I{7jhJv)d zDVV4Ldrgq@?gU)A}7HYle#Afy_-Mj&0~Mn^3xp^4TaxFV>LM`(2(zVLH_)FGzhOWa7pdzP(0N z-?*bfMp%JSvj#8~h#q}?k&nsTP>}^R!<*Ur97*s>lMSy7`lSo@!7?Dk-axN4 zA@I^F4^R&}{4B?(f%or@`A_L>xcY)sslytk@IpC5Mx?y&G`+LZtG~+!QJa9z1UJ|E zLdnnErkIK{k*iZc!}T~5H`H(y6>10y5KT!V0l@Y&jIb8~gbz5dX&-D`?g6g8&pXq?q_ zew81$qLgXEw{#goY66gXRP#ZYcc_^0X-LV}u|ej%B<|_zNxfZgj9Q(OOC{k~tc*d+ zD0B}&G+=qhLQ?a1r<(0=m1J=jT?NBkW!F1v(qGKbl9q|eL91x&Mf(cYJmTkVa`w*K z)*qlTD{I-hZ5m+hPR?mg&hnl_Vyk*VMOj8op%r&uG*a8qMa*<6tLz7-P`ERPr^nPa z{qq@{%cI-4xucE54$>UiQ+GxZo20dHqSIYEZgdW2`Sdxa#W#U%)F_?EZul~rn8b#{ zTydooXqyq8W!G5|+(n_2r-g?7Ic;8Y`!nL$jl&t@hoH=wBlO;GN+xj3Uql}|6kW$J z>vrYI z#Uvb>$)!WAf#BXeI(^y|N9Z^G_@3!R)IYAOPL1!Cev!}^5`U4@C^gWd=cvk~BRE5s zbJcQqsa?d1B`3vRiFkc@X*It7iM{zkVs?U2T?jRNQuWk{%2^qDHha&PnJI&nEiol~ z@*Uq)HL;WBr`J@a`6@Dylln!VsVY#it~Vfv3Vq#Vt^6|m^MPI%4&=~~JfuyFb+>$z zl#WxkYK!;MV&mEBxN=xkpsa;S2@RINn8la(&l98rP2EBZN7$9PR2!zPWkxHG3&xBc<>#2U&ep8v>qC5g<;LoOyfDw#KLA%D7%W6^V|tMr z?IcC#bS!0pKihg?GquEf19Q2aZLX3UGa9R`3gOn}0Ol#G=!ACnR;(uI!GJ>D?EvSJ zptBtMbvl^7Cuu$@C+q96eFKArdtv-n^7!}i0TToJ|2DfaG5$MC=RfBs|EFeGO{pki zc7&h#$t|b87-@M48b-f658q)6L%h%!E&Lc^eD~o^sbq z#i&^nuJvD^S2N<AJ>~85V z-*xC)g6I8pI|F*z?W>SGS9%=2-Cfe2L_B}8Aq9`e-k#6Lf4IYfNEqmHL^E7c@bL5r zkEL4mRRV{ntQ%u69OE?S){#J=yBd6Le0!x$t&yEiv=+vuwZx5u2;R4H5Q5Jo9ge(~ zL}Da`EPH<8j+JjW0kvp+#E$ez?lriZ)#?*Nv=HJXz;z(u$FN#vlw6J=;^{n7D&R7M zP6{!K-3V4(SRRXUM2KP(z|-yQvsvdO@Wi{aAfu6F6aQdGkgY*-=>hP-l~!Yt zYNIo7szWQ~5y%6G7$HOGDLR=uYH+8vslBh~{RSDc;m{2fmdV5S4Dh)N`?((M*r zR+Jv&-opbQAT$;9lL?l~JBwWoQ1t}xfHV;b2!7Uyomc#s|>%GdN5=z4H2 zbnxi@^5wu0O_B}alVbS{;)W>=U^~t)#5riT{Y!*KXcX~W2G3i2cM#$cT80tX%U&H9 ze+E6?H?kk_sFctd@zL4Ru32kuNEevWjiEM$5IDnPP6j0f^)?|LR<|o%R;F1K#HxZr z+v7AtAM(~Z_O9|Y58hR)Ohq6g4TYvvK&w(&Q@Jf)l07}_@`pH6?lTSN@N92cVkDh+ z64~-MR-+_DsF{eg=DN#T1_B6t z2FqC!D+qF%MOZa;;Q%q~ipE4--<7qga3m9bM9O@sE`{T5)r!<@*;rm$;c?!A6^7Jx zPgig`^AdMqp?KK0jisO@BSTanIseo61l6XkE%z~67BQoMVsam2-_9M*YPDq_Pq%sD zx~mchwF{-!35a;hI%_Tygr?->!~*4GD9Y|ZE$syef zYOsnoL~}|Cn^am?G~Ab*6@BU6t|qBcTX=|>4^b(i@^@n?d^}s;xm8p;9C<*dH=P#o zVl_yPVi@Wj45z1GC~9Azy-Lee=8!bjnTE638D6Fwd+R8^S_Me>qPpdJs@ZZx0Zw|^ zfH>zYXe&^znzH~)X{KyEhSe-Ev%D^&%pUS@^Dgk9zajM==c_u@bt+O^L9ro6i9HI_ zo(=@9dXf@2UeDYZ1x4i7^xiMEht8U>C7DWYDEkcWnXAXJ1TA@vSl|#}Hl2(RAFAM6Tjd%G`4)<~< z`uUwCpKCRx;zEh#^A$&%wJaEFvEB1VG#!hr>vjn%QlSm%C6vF8?J9JvmN6%sLz%)_V!z$AnuQ6*~=^( zVJPmj1lZ-kpQGhv7R`>ko_T0V?byyw%=&1S>CQ~08|4Stk;*Tn>BU~w<7wUgE(t={ zgEV`)(x|r9nde#G=qAjcAZUUDxgn93Dxo1%B)B#wIT9?g`k^~UX!3_FO6XBt86j9` zH!f)0XvflPn$4_w`=9%r9iYW}(K6gS{<+v+eUaSYFTaj zdhtTZ8XPlXSC;;oOctZi^xpUchb+V4|F87$ZzuQ9ZsUK_!@sjJ{*xa5PyLo!|EpW{ z{f}-DKlK0U7G@lSX~LSaY_d32_5P~ADID?ePwv(cx!d1vu6JVm{ZuPr9xNZO;yU&G zHa-W73?Ht3BKJc#>lmr`4U(r=ok{Oa*;z;iQu4m9gZe#NADq7Pc?F=DqV}X3 z$S9Dkb$9y_Y5E_J!r3IS-4*^E8ZJ<|o5B$6r^WWmo}#EvEu`v$tE-NW7hfgktu+Xs zu+d*JqdjoRl7X0KC6o9J!XU-4NQZ-KbKGI*1LyH?{%HF9{&^@ds2KLmdl-OZf{w=X z+`6~~RBfSgs@+_0{F1of?yR!MaO)u3IA)PlqsL z6gWl5DdP-)3x-kSzAypwV)l?ps4y|V1336gSBpxSAS+6j5OeXoL6$@_ntdW(9_a}b zi^6E6ke#4SfsRu}O#t!I7f4-qGh=krAi)DGMB>D)SA=-u z6BY?81Is(XBihYO?R`eaV}@!)s(_+6d>DbvdRD`UA1NaaLD9U8ORfzBWIN-#wGsg0 z;psrRB#G4nHd4w}51k#A(Uy{?7`1ctAQD@!*fRqA9-5QB%g0A0%^^&Yk!_Z;*MGXz zV`elGTo$5D^C`HFQ7ii_;#2S$ByBl2@Q?}e@Sbp@mv+L~6Lj#)fhjS`jR|d-QBO^f zZ57bC8UqMQ%15u{vYr4}v|XvV3ebcRDZhg)S(-pUp4%95e5@1@mWm<<*=r=M&d_u6 zmyD5kB-8=EN`|_N;8z{)I9IMoycq3S>~UB|Jidh1RBd_%O39l1Er@%_$AK_8zVXWE zvru+(N~jwE3qy|sMcLS*bL%Vdq6R3cJ~p|?QT7HTl;z7})na<5+^=KFwk%^ssJmgR z0w%fA1W8+z!vHLCwv3tyGX<2SRH^{g*OK?nb^GH+97pmTs5~qPI;+WC5R-!AHX~iy zI#IgI3pPcNj}7wMTF|(&Zr(M(Z+0xX0Nz6SL8E_UjK^Xn9?qrG$8@~Y>to{7N12m` zSHh1|W2rRR+NQ>hV(}}Gpa!Dq^P#nP&Y71IaPzE*NJy;2s3_euAe~ZMip3j6h>ak1 z)wN<*>0Fy%t1@_MeH$T*C7AhzR6!yMBNuHgWvEKM=Vl)$2km@A+;qiydX}#6Iu<~W zPwDRmpi3p%SVQ43cryuKU7GO-IPjVb6EQ|K+!y9amU2p?B#Pw>N?G6GY=xV~PGjc{ zcyL7DNa9vwi$>BIq-PFDVpcH=1U^;v^kQ46S=zZBRyMA~OIu%3Wu2+E_)=T6q?*JY zV0&om2clcunH^4P`PZp@nhzCsgAI(Y6z4N-${KzcE^1@;WG=1V2Vuq6FwVapqMcEf zbO_gCI=t-8XD|?n7d)gz?gnByqV|2+UCfqVnFh+-_qNKo-<+41wk+;uO0J`u{^tue za8i6dQ%g8ZvdN16P12;(noa&Mc_F5y6UF97Uih-;{O$CM+NM?6G=yhf zm8S9n+vY`R(RJNZn{zaov|}9o!)OO!5$k>Gbz~?7wvb`5@~Y+vG(yIR{HPTI7TgWf+=$f-dr7D>-Lk2P^L^bYyjkec~FH zg1bcbv2v8$8Jstx+T$%w@%icFFH%Z>Dt<|*&%UjjYRI_=RlR9k*bBj={g3`(`u`Omu-B( zA+DVIs`jkxJK3m9DL=Cs)b=yCx(?m_$wP}{;d++>oD~$fVV9@hIP#vrsAqJU7LQpL zIP9jvEz$t42^;oms;w+W{D}JAb&}V%EhVuoQ{8!%i zx2=?T5&t!)X-`!=$8(w9+2v9Cl8Y1p0!Yoks?$NU9IPko|WbnCK2 z&p$5)_%#T0r)iE_|zAT>*ljo9T{DYN-$^ ztO7PITi>kIq=o8ibmX1ef6{~vDBfK*thJ}7 zf&oqT$vk>l0!0pRMF%;AHSeU!obs~UhP?pyqw@~YJ5)#g#X9hW@-3I2^~tT9%$Hj@ z(;1omn8U7|fwak6)^>8jud)^_{pBT=D*3E8Z{fHOZ z?ZgLVxyj+|th&RP54y95OdzOS&P&Q`vNNxo8B!wO#Z6+3t)*@ZFl0*{d9bx6eEZ{D z9`u&$QlRFMla_jywEl7EpDTZ+;pDGUHtv|$H?PI_6116eRYjzMCP(TB>E;h0dCLk$ zZiW$-{9V&U?Ge1Ln_*jq5mxv5Vn;a#IsVWM*GtzKp}drOqGryd$x zX(MaODroBCvJFt?_|gr-P!_`BkeAsyu!!vBw~;Q-L9yudEH6AmNf#pKdV90sH z64HfWW5_&pw@Z>qg7}3nf^R;lWDls052@OI@S8H4XQM3!WF|^@eH&2pc#HGucE>PE zi^V{xbc@an8+0E)+co)xLt&C}N?HF=->%*5gGyzNE>jSbt%FkZgqG4q2~6@_jgZWQ z>vb?XD09?AVBj+RGehDV6eH?T%JIFFMBG5M?%vxZ1<-Fn zn^nir&Xl_>@(oKFMTmkYDA}*OD{H>zoFxNKj)%$K8s1PP$9Ei#GckeLZK02zNCkCDzM7kyQ6SL1&uleJBr=yq~988tO zoY-LhR-)noI|&3W*i_y&ESn2bf9Xrgzp?GeFAr-?osq{}442*(71G)8^yrI@OQ8M1 z1oM#O5=RjdG4<)2rR|%9X%YvkPU+J*f%PO7USTE9D^I7k6q2R1TF$RR>xYf5B{fE4Al*y|cbE-!0Z8mW zLrt1je?coYv|bp2?byyD$~bn>F+P3qB#y5F27OG{#LBt$$g|>oi9tZsfuUEL^NxV& zUE&U&>urD9EMCKyO0PSius~6X=LqIu2_!BxmL#KboUJ5_W!bDy9xmdz;0_==x761y zmsbwc6dmnf$=*-p)#G9zpHx)YQa)y<(PAOqEfjioSGGJx;LZ8)3x6-(EF)HQ4Pk;W z)@K&2J<%s^SyGsd_BRSLH4I)2^TN|eh_L%gUA(>Dg}56(le48C=U%3Y@07QACqOeH zqotsGxUWUK9b;KOJ~;BmT88t$!V>CUNi#|TE7o!f&9b8rZ^ z-0n~D2H+(P*D|2!W^-W=d%K|qGrGhCX34CuVu{@#W~c}Q3o+p?T6cH2OdKrsdv=XA zUf3_YvZ)NY$Q@m*2lgq_l`(q@II32G{-LZQ2UF+t2ijKtTR;2rfA?s?}fEnB=M`Y;il!Yr2HLea+0V zt$bEK$&T&{?N_Z2ign3H1>}uRG5i$PI5y9S>8oz8+$aj(10E6f@-0#ZsUz9G;*ab! ztx-!9v{RoPl@6nWy4I$^S*Zc(-}HIso*DF6krW8Pk}ENg;AS`i4ag}9 z7&3WoW83jYDhUy^&q(G{V;~es8FqBHU21XGgK3}>%*Z|VjLTpv_063v(B3X1e$xqW z5F9PYYnlK>mm|%uWknbtm^wt`=dgnx?6+Qr#mpu-crJA{yLxI*!X{b`i#OZI(`aw6 zdL%NmuCu-3f&6*Z?;;CJ*QQuT?5`q}+BIk#Ni2!cI+1^Mxu| zkfxuFnMI1@a<(y|kg9B=qX*w+WLAo&_hBmL)`yUTSR`L}7p zB$>d8W3F26yD)s#OiNkzu)l`aHZ(&ifaP^=7giseh4kEeYIQUYwa%^7oXA!RY5oR9 zim844*10kdm_4(Q1K5S@6lui0xxfsT zmqG&>lxEU!b~DJ2l5*>&byhgtdc08+6N@93YRK^*X=i~69%?Cm@bxir-R=DD`7|5d z%sVzTt6KZ|`)5+`yXnKNZNjzp`{C&7V3_HpZ148%?qw^F-f?uR)$h~u(0l)WY@5u* zIOt>dU}*GKOU9CeiScSL!eC=ir)G2ZmU?r)_HSYenfA(}E)Hi_Tc}*Zv%MAUrDdFT zaGbNtEa&I@pHV&C?O(dS8S``)+~Sg5>kh{et2fBMEcwog_&R0Q6u5y76~-lSo=i64 zZi7Eq7I+OeIj@!4PWIGo0xWxl+K4+rqWAN&7NTevM$?n~lF|yywwTY2jrcPO1P(|m z$;!XDn(36zTK%Ur)<$`Kb6*i!9$Pny6qg5r^&EIFYjPl7O%jPHy=tKxM{6Hj8$xdMPS~|z0aqk&&|>9o^acNs z5X(%6UDYgi;Fi*updp7c1d#|0I4l|D0Two-DCvubyMH+`8iNSyKPZhb^9*#adNANC zbZ#S)jnIWyLUEkE&VYa30lC30cO}ekX=f$I1#h)BEe`NN2H7&$Ha;uQSPj{=-eVk% z_$f#GW2jyNrzWh6gx0V}nK}T0rLxC1A@%Ewt6alY5OFMgyI7KfPLsK2HhgF7#o|l)ig#7PuUHlC~)jrK};he9Cj$i ztOwWBGS=nT_LnR|%vJ^%&8p2e8zk6cP)g5e<^HD3cs9PMr}(~jbP^F51_}dOK=3P) zG8mz#c1PG*KPo}>pgh$bfk+}n8GH?dU;CAOtnd})GbVK!Gz)hATH`1@$*&^R4z7`6 zNrFH4W+&zgvK6=Ud$JLG1eu#64YYDILCWU~GT7SzqyV~1=2B&V5K0&*n*%j2jSGRQ zSKR4ANGcM25*0scrT%bg0a8l941dj#cwj~l39@p$u?f(`S?~oU zU6{(8gWj+c2}$Tgo67d6sx)G}G8W-P&MWiCdu!TvR;p^U)r#}cGh&$%Z|Ra31SZZ7 ziDZnCnaZjKHri~X`|0cTbpf@MoC=k2g3V2R_H>|h?S)+iIF;E$uvCLXUCtw(D5sb{ z4p$!Y+e>XH48H;-E?Fp%U7#sv27=J?oFW}MbS900>#FdbU+ZsmIrfk-vFS(tGFL`Z z@SI~?rFu+A$JmT@#-*fuV%#6?hkkqqdZ90`q{q z9FHCk*w?D2ZbCRpX(YfS<>|mgo^$Rq?j(8Z+FTJ4Flt?|fb7wK#hUOTu+#P?fp zqNp$>;hgSZt28iy$5)ZOEa=`)65xwP8|A4RP*@Ez5z*FenjR^pe-W@m)?M*-?SuP|f1sc~VXzT>URwK2 zHX|RmrHT3%THb~e>dVpmf{#Jd>RI{NX5wKou4Nio_r14p(A$X%(@}N%-$P1vTI#31 zKTSNU<9uOBNK8H=%q)%dk>j&y%P6VzYOzET7LTgOV;nJq)KXbK26j>mDwhPq=Qx-yEgYryvDRIZ*_LoyU2j^ZwT*o;~bpX`j4^P3GHsWCS z-4x}u%1rj_M@vT1etfXzr^tj&Wde<)zp6alyezH^je))oiH-*TBvs@JgW9mM$^dV| z<1EqH9#(z84gZ1_ZncHV#z^*GUGa`3ve2te!n5Ge7;(?;ee(E6OSsy=Tum13 zqI?gg1E;<>nhZm0;OP>q%Bly1d``kk$jluqmNdoD-9}gsBIw+F50aP3{C1RcuCi1b z_rT*F$V@3ZL&LSQh_2nAk0P<4ujsyf^BMPRN;Q4%^y=AYJv${}Vr697zpbnc$1wye zFpBzt(fMtGq`AR)=k8PfqI+^pgs+_NZ%RSl@+VYU;4O zrz5Go8^H%2_9HTf{5AJemVhJHip$8SKSou0vxCj@4&dpALM}ON!=iz%7e=OTj75eL zBn!>g+W2<*(to1XK7kD0%MMp_Imb}R%5D6_@$lw*Pu!b_6VeHVm2zDe(Fy|TTm4f# zE#$7!!d8jOeb^Ei`s>M%iQNL>&544F^YBDZ+7|bDjGiotqiOxo&@rkLl;R4Eo@^DR z8qiL=l4|SM-jZBzy7ym5j^>s53e~U?kQZHhD)fV#{w3jlQ3{v8pWo}$Oyf**mCI|MB-^aPbdtINYcvg1gU$&&va%tH0Y$4_@E%JAt+x{C>0DE`hG6 z6M_x=Ie-p4?bZRnVh|_5<6H{yP`w-Y-KJHxjRPBBKVd8w*DpA2`eA{d$KLL*``h>D zTN8qGkTtgweJaS~_mM=HSI&7U6ybMNJOx#6Ly0m`u(#Y>AR3IVH^$5-iCP80MBSH# z5j#p9m_WLk+a>nbhXiFh^kMjXno(VeY;mZ2JG|qgGtU&W+sQQD^T*<&SyvK~l7zIZ zk|Ze5{-|#N*kE1B#PD2mUqjC=)k=yEa{(%d)Qk|5lvCNk?7M;#bMJ%8ZI6R2+-+}S z@}4hN&VCFWP3f{O5h<^<-MCn^m)|zx!1T2!Rd8ByK0_<|v=D~tB(vQxac={%FnJ8G z70-T+5CC|!xgTA9P#&xi7gs$rbo|L~G?z|0=|Sgcn{&-xPN~@U!G~Z1{w;vTRV9=9{cOMbsV=T?te33e9bmMkD-H*wnl!K86Ie9A zQkYwSPWIwmI@K8(xMXC{H{=9d<{Y^)IWuO|aMVcB2He>;=*TVx=6l`~uq(<5OsaGm zz&oZe#uP+YD`GM)-Q^-BMFvl@^DlL0Xzw@Nl3BE<)cbP5 zf0i;eMMM){r}`8C>BornZbOym^(O%YtRT)ZuwXF5>Z+7WNja-6zD@+@t^8k)ImhVx ze%W}aW+=09o)j@2h>p9Y_wAMpgGhf*M{~K-!1~GLwENp<;g1r5;jwF{xz3` zaZVx}pN1TtD73&I^|fBscvB^l&9kV+63-K-6+Vjr+ldtDB?KcJ#mG@2TN=C>|v?YAl04LKK?l472OVmD_}FKgugmmAc;Pb ztxyOmc4k)$GMz1(j`vp@*8E)5=;H}DPFHEQ3!7ZY_9TqK!D(rd3$QI5DsE%zoQ4{`w%x0@|IeDowf*5Wx zQrfH8zfAxAnqvwf-jFPr8W{%6<$~W}&1I??xm?h&k|X3-Y_6F|b~1YG9F!F3lw6!L zg@mHP^%z?*<3}iyx4x6D;M%|omh#(sFEZp!b|!bud{ws35;E*Jb}Q9QwY*5dVIc!< zDl_K&^RN|>vNo8igLRs&DriqEraYkU05)sUoAOY)L0=Q`fn+DmXnuJF_LKntTq}r~ z$dol@YtpUefRUA`%wdRo6H0_rrvl%BtqNDRwArRJ1?~RZ^F02xhTmxnwmtf4R^s@ zqUHeQRpA<(;-@>M3~u@2Q?>P4df?o4HQix|l8fFFgyxW&Kd>be&8PfQCYx!FB&wR( zqS&uWy@({OpDF_a^N=%RhV@TdGQ<73}@%fQnW)pMfd9~^06oxz*<=Ior za8k{0LtBId)!PVgalRSMEogvi&#xyCumy)r0H8+QBR=oLB9YpGp>kWg7m@k$eidhk zQU(O}nf?lB3mG@MMsXBzo*C)Jczn+l}-*c*FCKTf0VN& zmBEWT8bBLpKuV#qwA>aHY z?mwwEZEByb#fHPGmIUa3`fV+QD$OMA9jNX!zfJs%IcGD{}bf zkuLR>lldZpQ|NM(eQ_YQXzuSwE|(15WClizDpW`=lU>On+Nk5}j3QD`xz;nv1$z_f z&=cwueL*0(pXUqJu7(hAs>RjUBe9k0Bmz@FF6}?R6Ma*lM3+zLPFDr%Vtl*VzNq?# zwVPrGDafoJtx#UJ9xG9vc@}EZ>*i~JCHjK8sd5zWxe0d%PFeZ^oj0Sn*>v%f&wf-U z{G|Jo=&D_txTir^$7s9*ovTEsEL}VjEj;In=*+gRI9vVJ?8lEH?RY%xm0qY|_@Ion z%(o7FGQPrie|Yanqv{!;3Y^w zo>^4kziSJ<`}uff-x@yPF~q_DJ4pT8|HZ__&iM~%{i}(UiTR%Zo`2r{2S_phpSqE> zB;qbO;CfbT$2|Ovr6p3W2^i!jCk<@jDfHoD+GXT`ea!QBO1^!Q3ehGStV>(Euuz~N zsAAC~Kif`?7IJoPSGV%Q;J#_fg0PqOMr+-^|Bmj(-8ON5zFuALz1d#cmjQeF{Jq)B zL-zsryz%SJ?hG5x=4OsLx%LI}QqA0sd-P4$=MWN;+w)cYYFAoBe8ik`R?hJ=J53_q z1-XKWU1HguSA1Pql=PK1vybH-G+BrgJ#79Yz%ZA{XBSIy^%&5Z`3yjx==Dcuf&<)0 zkn6knF}4Yd+B!z(9dAu*EY{xv+Srg|9}d2a))Ca6%dtpv-DJ(+khJJ3uO#!}!bkrR z?vD3%=Q=&pQ^m}&h)4Q>zeSj^!38pxsqY|O#H|iJA_>@+3f+463b_O2+b)NP$afoY5))<#pxY} zN6*_EI?~QUAu;8f!G1mnKk$Ik)6#}8U^ZC0gkTZYe!%+WWt0%1-wHsi?bRH7_+trf zBhI4{`r-j^XCW^8D)}wF0KI z5(hru!ExGLdP%;}5a11nvKAN%sUGy4WPcG1C|SAfQLc+Dq!=uda#G8%Vt=3uSyS60 zge1eR@jg=)=d`6J++fLKw9HsKrQMdb404GjD6;^zOAU!&ghG}k*00LSWieK`~Jg#(_ylR z%Q#tG2QNduJ;6XI7-F}UBAheB9 zQ4IEb0PN5a2aYYXq~vBZ%3Q%$pI&wwIE=5LT`xB4kjg18ef8TqQ#^9nrx1iewFjQE zEx}Z`J=tRRnV#9vQKrQtYzut}qXn>Y(ODT((5W*0J-jHf6B=*lo{{(?&WY8;*4Q$W zphFI-F(>y)7v}h{uRb(LrYY1tiYxr|rR-!YxqGU} z4ba9ZJcf_EqjW1z4v^9H%pdsdfPJJl2g=5=v>vb#*ip%}4(+;x9##g7L2He+D~i^k zz8HqWJ7!>vgr)xLCQC<(meMK7S?G#|(TJ;13Nj%bF@p6x>hiOhIzJnSJjX5j1&BN~ zY_xmt=@_n>L~^h0Qiq)xwQ`?id>MfgV&G#h>2ZxQl!vGxN~xS!6)0}4v+B4HBeGIQ zkXmX)31mZ*+vgjO*_Bh{V@=A7*F7EXWQD6j(eq&NlD8!C8{vrb-Lpps&N+DT+msOR zTE0?W8#&5G$TSH)pO5GOk(HTEMfNsP6{ffIK7cCT!Y&q(L&PfhJu6_o{atR+Lfwv| z1U%X-?gF%1U4x?Pf9nbfh8!zImpG$uM~QQ&snlb6X92HjuMvI`nlTt8(Ot>LEqMD^ z<*6JEs*eKmu8-+V+l6O$fq*&ABqGeky*WOVLn0}t@g_sEIVw!u4tE+3&jrTO!y=oT z$Z2l$;pRWE)$Pn(qscQxnFe25E6~1MpH>*s8@pf7d&F8F!DwIsqrBQw_h!DL4v=?v zDBYZT)jb|Gl3eIZNN}O=;0d%0bX&3y{t#tl!Yg{ zYX~O1E90_pUbwrK*RWaeo{;CjQ)2!V$*#Ue2R(st&2Y{YXf4cXo-l->hZ2zNNRU9! zq|OnScy{*H8<$nYi}--~%lCC!O9mgoX>=L`DG-#;q)SG~3@#NJR{TP?F7gv8xCr(> zwMOrtb44cG`8j?}*?xwq`NgJ*#sOh1jLT-!=0D@+RzC) z?3;*Ee?47^OHo%cg2pAEg=PaL9EEBYQ%5Tfhech2NfPATPNglqaP>3RUqWp8fWO#uf4kl8sApw1&P*?|U%)6*6D9SYBPr z{BMrK1jJBgX>R^3zVXFkmt$Dn0428(cvpeB0Ox*pr2v$bETf;1=Sz3~W% zLJr>ye{!1B82;{y32+YBrzmoiCz!uU_-#FD9(PM5Q+7G85d0A|vAd93@M3(Iguj_S zDW%nYoy6C8*3Q&g&vjI4PT}_b@BA(3~dN+Lgm3b8A+ZLOTjNGICm*Too!!C|6U=$LIHtMs_9gwG30;~3U*UJmAO*+9<$0DP6luUqzADZrWkCbj(w z`~GLN`=5aa%>Uj-{7*vsXWXkuFKS`!Y~n~SYHi?bB5Y!0XKcd92j%4KXkuUk<(_?| zCGoR%i1M%YOntFVNqwkI*N^x={6cU-wi*Os{KtvCd9CKuX-g_w$gQ10n77L1#igyi zrFJZa{$@d zpr51}g&&U1NpjbJ<+cMoAQzO0KWm@fE;1U|9PX!maTAC(3MA;31x}B&3(w&)A#b*e z`u{O@PSKUN>$Z(;+qP}nwr#s&r()Z-ZC7mDs@TcNTKoK`t&7##+4u8qeiyyH&lr6m z%{x9CXEZ01%_Tn!CnS-$XC;H)NXTfp{=LvNfCXxldpuQ8;+%a_B6baW0Gbai9Xu_~ z1%Vk8PO`FodJFI67#>2@fPFA1Xz)Bc2=4_OH=`mz8S}<#9&m?@o)y|&A?ZGgOb|Ts z#OaG|%PPB#TsVD+K#4~2*|r&oh=|5t2j9j0zCY-OEe3l{T-Q3= z^-R-8a=(#_=WHu_M6XSdO_+sIiQvkLNN{LO*b4eD8!~NzAU9ANf?Ee60G-cQ(T=JcV*P-p{J^PS?~Jmdv0^^M zAFVVkqs@rKe)U<#nWvMTSCEaesz@PEV83e?3RK_75)X=#!ch+j^dSTV+7AyZE%`0q z09d2AK^89L^f(O?*Gx=2<1o!Z6#@gYeHPaeA0xouv%o(>5ag$&{Fo)FOu^=3j0LMo zB-N2J7q3W8Nl?&Yn1kbd7mlg)Dn*T=f}2yta=Oc$lY+C^u96oSMErctK@~(-sj`W+ z26REmT92%Ss9WhYCoH+07`zqfOj9V6iv#S}LS`DnAv&MZtR!?>F`PS45l+3tJLs^C^-vGZrr_1!&3lJ8Nt%EO)-_d|4LMw_m|N0X83uPKnY=<1}B< z#jB_qP;iBGPYkh!7XzqR7_<)X zm}DoR6{GDG$9b5A3#)&=$p!Xb7WKiblk_Y;g^hur0Im{wy7|CTa4ijh)gNfvbn334A`C+Y?QZ zPvqx=TiT0%E)|_uU)9{DCaP1g{i?-Wh1AUC=uoRuw8)N8N=3qV0(?;qiIpqi@LJpq zCFihV%}%BBVR$2kIcLR(YQ?>cQ-3mUOksQeXe^kx=F+NYM}dr3I~h25A87( zVx_Du${|7&EjO|%a%4o93me#$bmzV4kMt)bo!&q{gASqFcT%L6MeL77Rc8~U7 zdq(4qmL;B=2eF97syv5KvGTLkPhA64Dm~arcaE6??c#1g;zGUX=b*^ed&@Nf@TA14 zCGZ6}`cC{a>k><%>lMBVj;klkVkCf^PXk{YtYJ{G41GmTG`H4qTjRF}pl;mu1&XC|pMB8Evn<|u2A9no`IN~!)A0wD z8HX9{qU{YT!3ScgwsA(DZ92kk1(QADq2+9I$H!udIa%u{j4V}i!!4{dncp%;l5gKY zII3%MP-9&`ssSg=ZD?<*+^teDN|%;b#vJ--^w${qmbC9B^V#9C|rR-^+ap9!l! zG^n;;+C%wwYF0Vqb2qDyG;0cjyRz5);oATsJuf*M#D06L^hN=?QPniqNNt7@BRVv5*6$Fnys9n zMB?E(uHtM*F3w8VUG_wx8fDuDFd3I5%_a?T4 zE#^IacCj4*+8_~X5Lfy$PQ$9@k8IpxyZ$DYc=w^jcs+P$X8TjvfTI1cM-|T8X|$C= zg-Y44i^@{m`SC)&jirSJty7fm;VRPisXpZnFRl{{NHgW->4_^`9$#t?t!wR%)ZMd9 zu_(14Bi6avEagD_;7UXhXwm@7_HGSqUKrW`f^Z!aF|D?;97#aTK2*~_T)A2va4N_k&|+2A4y@)()5-R;gmPe))awogF=%O`5=#WzoA#4&L^j+tbO>2mkq)jR;Z zRb0^`*X7#oDY|Op!a3W5Daq_3NGD9gF#my+j6gEt;3TwNQ!y=)AT~CGuAQ@V*xkMr z{&fep&uJMq90yF9=;bB?va~eObCpdI6#jv5#WCPcf0IPT@+*($-4D2TN!(Cqv0~xY zBuQ1rXz{2-`ItP66830b=8c?PS$PE628ubC@qpT2nN67XN{5?izJ^QwcGsTgVs09wZOId4E4qg1Ca$g`xI#zES-ii zZKAvLAw(2cm;f+ck#LDDu;0cBL1PgJlc}48Wv zRxmx2APwLEN!nDXv!n1HO&9u@K{cdR+|ULVBDj-buA`|)rVIV86QJORHLT7S z0{due6>%0RtQsHVp-!es?>NgDVqcRWq~>o)7;-36IP3Q@&jh9f$}%mH)n8JKKPa`) zG)~l0XVEoS;HNCd!z>0txYQU&1=xyj*cXFZx=9iYI;X7`qOfQ7Q&>?gzK~%WP=iT8 z)TU92|D-o0NTCp{gpRMdKif?p!VUfG<^qr4NOPB|-cb)X#~5qh z2m)W(Q?-DLVkwoAQN>hxvmBz%=yAvO1L&r8AN)oL6Hr?$8_X z$!I}Sly~teovMO911i2_Vs%{2_;^I|zKSoN49#)E=4GQ_)}!sT=hQ%4^KTa2Mgr4v z!)&2T>S{BYKQz?UDc~w7X(#?#|qpTBI1u>lf!XT*_|qz1h0FRYvM3 zDGGK9vO=iXaVjzS0>-$`@oKn@73qq}DnjF9k%7FNDXRkI6%Sz9eM6q655GOt9vw6b zg)Te5E4`T2nrCm`8!H-rxTVUfI{--j%NSjCh| z&a~h(5HYQ1als6K@>u3h?rgE^6jd&68UMA9Dbq^L0{{in*D@hNrdgS;nLye0SZR)$ zVSP9SG2JUdT-E=Zlf?)6OIdKsKr#J~#eA8^SCy!iP*Wp3lIyLD6&HFeYAdl~l<2lV zK}*Rs2|xj(E6Is?mt}u$HMO$68fmK)7i!d==rzjV`{wq|NX`V@v}m)4G*2d@Zn7o* z<(c-Ha@nqZU(Pa{R#U~Y>sK4Px7ARRpSS%ri)38_XZBMssJ&LUr)=HqX6y*1pJ$D{ zbR-Ml3(9Y&bYflU_;VldU1P-}uVc62AR=G#NR>{$&}>&4dB$DAcrnM`bfTqKt^q0L zKb!h57%1f&zEY7%!#(p>TdGZN=RGR9?DY6u#FQCn{%=5mQvCRts$FGjyc8Exe@-1y znb$QA?{~O)^_HtqxIYaf>__6z-h6+Bx-7TlMi5rB*Y%N8?(o0N#SX=i1$D7=YZ32F zZ=R~;k&--b)ePK)?TeYa>^sZQ*R>t~7dCVEbZ|KuyYhNns(y3l| zOcpz1_h9o%rAk{zq=d69xvFOP&KBDD=)5^Wdo{KE#Q9}axwfKkLJkX5 z#Xsn4Qz|~Fzeo3Fm;QW4fZM;xb(LSfW5h1U^AG!j+hYxXnr*9$yn|E6DCnwtIF#J{ zNtdcLR{LQco?U+DY80z-RaCZYlHw7Y53{$2u1LOY{lkGJCC}xAl;-@+#DH%SmI;a- zpvLtMH!o|YX3uEj80wEM_;RgaW3ja&EBwanc#w!DMJNcnfzFOdw@t9Dz zG$s=RV5qlNQT(cAcdDk>sC>F5`DxzC>hZN=dGvn*^9rzPUztyasm)-&P?e7v>vd;Y z(RXZtS`zVs%$p-X*QKD;(Lde42ERYJ1u5W7$1Rk<@}+td^xuUt?<_XDCSmA;cJG8^ z)5^ab@ODA_6oa`=AYG}?WN5X#P!F2?;`OE3Oker2E^A209M zGv>{}-y8hDcn2)k2NgL?o6`hv1!bNndu_zfRw z9kc(^P6f1D-hlr+laR&Wb3CvFj0+ni+)?z%8WQT5JH4=8a+LGXb=%k`oQ;lhEXt7O z1SY1NS?Ty?8T?uJbf)~fvBURuclULBHyP+C6+Sq|Y3@z{bn@pNL>zcQ4|ggP^Ka=B zd6T$v&Xci^Eh=A&AF^{36Rewrln<_c+4XVZd3em&s52F+D5_|fxC{@RP4ixp*ZiQG zSw)>lKOo(Ksbzw}2X=28{zUo)r@z}90}Gr#GXK|B2BN=J7H`{dLNuG&S zgy(kqOELk^4{mhJn9HsSazEzF2AFuS7yqrY3gL@Q8hdjSi``z~!@LULd5seN39A69=e> znOPj4m7DOW+0u4T^lkcc-LCVn9JB^=Rlz^IZ$|-8hvnG33=4vEqBuQiY@nYHm?As* zC(+4P+8KUwhg#Q(cV95=iW57~9ULFc;1CGJ6YdyeCqhpMIpBQDp78fG621MRxH)ed zD1!tn^*0YHJ+4~_{_s(&WSAmOB)TzTykO1;(O(0A{BMDU&QrK%QPyZPmOP>AY4$qV z86BTLLnYn$&Piqo;+_L>uq3-h1x0`sf*xxm`Dz(`#eu)mU71CF%>^j)B}fRpj*W2V z5h!;c8uc(<<`%rIxseFYaZMh>O)@-1rd-=jHv3rF&#+TLU}!I1NY1c{dfHZZAB@cy z?l+5~Q26Q`M8Gp-Bb+q>Quh&`f~!QMtrtlPW0j{P2qg<8(LW2e15vOEbo&H6qLLt5 zCTa5S4(1sNM9D!jCk~lM4iZWZO3SM%n=tkX#Sp3=~pREs?!0EuTjjhJwoh#Wa110v3GU^fS{I@~t(oXSt} z8e2{FWKn3ZQUg`6vDEl--bgoRE zg(&dLh$BWo9SD-`3mT)n%15*Tv zs+}!K(1B7~AC7o{o>fQ0)GM&VNgFXl;`EC#CP5B6(=<403sI&LQ+lfsgp5iv=Hdf> z7)0=<9u`QA7b((s(0J-W0IF9eVEE$RlLW~L2$pBo z6wQfZwWO=_RSn@no4N8C{b|i-js(IpfSdgxdO(L z2aK1AmU@7Y(Jc-G{VI$DT&0W-pj$9|K?Eg^X}^#MKhNPT0ip@psxhef27^LnT<9TQ zHNqyHpi*5b&oAT7_;+pseyI`1HP5k2lQPWB7LKH|f)3bHb22AZtt!Fq*K?_qOzLk- zMYWG(sG5$Bd7#ELG6*wubrk;kOmHggLx#q~t5oP`?aH8l^vKLU=p*poAAS-KVP2w+C8Ysg4bSo{5Wh;~G~)Jy+rxu`v7E3}-pbbeN&N6t7<3 z*iG0mLhycvaKgYoRqw4vawU5`LED_78)SL=^a@DZI2XPLJwq>oYXF}!;9aU;p&JbC zRO{yr=b88Rkv~B%0%-=d*)0a;ege(-1#G;5T5(kG$)9mOH7J6H;po;wuX%DT_8@n- zS9yp0x|@WDX(oIReXUjl?$9SHYpPVI$8wtb@S6g%NyN?s^?2Rg-1-9(elubwBMwn2 z+EYEC!3~s^Jkk}EQtClC=>=|A76ZtD?5Jvc+0@NeBCfKJW*Cu2(b9t_9+^sNtoLxVuKEe|m^_1H~sZ00W{(UJZn5Eg7XqchV4E2W_ z)Tyt*2GznfIL<`Ybwdh{3a@I5Qo$W&NU1ex{^=<4@wb+gwUcU%KGgu}=Kw+byDE3%X8=<{ky6QZwsQav75lJKL5PmDTKsaVP6lyB0oM=`0~g z5iME2y_AwbLuF+_^F)3bWx>`sTv3L!btK+QD7?k@#7&(XD$)BY}LkL}3nZenzI z20^g#Vu!)V(9iAW7+_=rPyM$iv7J1KB|=ko0@CD@*4l% z98f2Fy#qGCetBX8+~2F&Q3G2vjJ^N&(U#!R%2!uP00XNPYKARNyfwgOiM1tQQAsPg z5>3Ag669n2ikv-w0gH_-V3GODK$bv*mXW)&i}fi*6E@xXr_%s$8@MC)-$?i0`10%UD<}MI`nM`sWwit{Vj?;Dq-~g>jfB98Z4s*v%tN_-HJS;3(W0!dMTF%w+Ocm2g7R&z7enm=rX&^J5+zq zeY>w5~`lW0T^zlBfV%gfWtG>nTH{CpEJw~25ja*i zfM+_4CN9LvH1Qmc-xoNid|K$q|H>*QF@GV~!IC%>klr$yNmq?gA<=>%&FtCHev zHn4?2!wfB@RYV@^I0;^?;I7(T8$ZdO{pD}AfX}P9lYjGSGuEtdR0>?&ZfXh|e1)wA zxS$@T2X__kNO*I9Cjl}wmFKyM%`rR}qnzQbD*m_G96(#I*ZBkx_2CkU-Ryfq8-V0? zeVx3nv3rHCe?F_WHyVtoK&W7xV5db%NR*Z=}?`^;42@{&qzDlG5hC+fe@~6>I%)AUVx`*Mqk;ZV$l!lPFP*Tm#bw*?n zg%0IN0uH}^o*!gU$@DzLMG6icB7 zMr`t;}@Bgq`+&VEKeysuk20i<1BMUDa*4dV%}3gkp$ zvfmaM$i)gD@dTQqGPieK=+{alPd^@{qTdw?E4Qq_Q4>^lxkq^IAT(>IhjjBiNt>ci zjf~22@uVJ%n?kFasXjvxjBw$5eDdT1!y4aBH7_|UX4KLNwQRa*YUY!nAEuA2D-5%*q`Gh z>3SERDyG3AC!hM7s==lS8wE+bgBlg-b4r5zh`nhkc|&GZ`gxUi3mr=xa4QPZKpnJXFi9Kp;zgz! zC=|OXCoLO6m^8~`Qsj6-gmS4@=NbXVcMf~Fy6R!udiIO3MdB&m zY<6ua4`Ud#M3%xGk5AXsp5iUE1&gRQa(_zI2_n^W!z}6YM4Tmikr3yMQYfCPaMoE5 zm8)o{^A2}MPDm=@s}D-|o^6fLgfq)bB&Y?hf6D8!ac-OYRC!vA#4<%gCRcVz-^wf`XW-5+q}BTFTZMaW}J3di4fgps*)RYAMVanBB0HjIGNqp3)h0@#SMKuUcTR-r=%@JFbtfpr)nHVqM z*}CpJsq~O1t?Bpv&G_>#MaB+zQJIR_tXFH!NQEX>op=nfYRKz)Bn*Y_o;bSl$XSx3 z@IPoM=dYC%DnTQ!R}~APwkhhpA*fi8u4Y4Zv!Yf^$nRcg;IX>4AIOFD#6u!iu(P4Tj3m-$7pc z4O9hy9+h(%w=?J2n+r6$+0Xov19(qgoymWJmWfZo3Ob@*n~4Ok^z7yP_&nIn(6&?_ zB0nr(T0nvf6kx6}Y?ME;BQy?cGS_^7xuG8@D%CT5A5l7{id$?d#cjwzy|RS9 zki-)Nq-lPzm{E=<*EP**2yNB)MHf6{%5$YA57B5cNzf|X^8!?5&U!U7>J_-6?P|N+ zsC77>%41#(~Fu zGwe-R1jkUO)B_d3HdB_Wz82qt8Z#K(dn1-qgbWHCyk1t&o%HwaP4D@=kcpN4D@6Sh zOZ(|F{Ks=4%Rhb5|9md|UrF-+Q*&D$S|owU076pldukg1z>Ct|to{G?c~bF`4lmco zTSkEN()W$cdOXh>=XnOMbHjSwVZR#l+@>qHQg`tEz6_t$F>KxRzdStreErpU-MGPF zYdk(}pAXiqKdv9|^8>yfXTlaP21{>&tnq!@1#SRp`M#YLbnW2`yxbMAYBNso9`et; zj^JX>pI<<89CdEPZk{dM7`vdRyVbxgEPywFaj;gryCU%a1_#M*+&F4)+@Rt%f^!Xw zfwYG$Sg_z6d*^LA6zTYZbZy;|IL|_z?2gvf@=u+eOG<8Fs-&s1mQm>zHjs#oIyKO= z?ZwmSzjea`?_u#Lmz*Ut3v`OBavv@pjL7?X1Mq~0fX%16trTSpFhZNdTD<#W2M>T+ z5av|+!_Ln$#U2+qHX!=>o~`-$_+ESRMN|%+pKw^ilU+mmloor!Qlp!Z%A!w&`x%Sj zEu3yA@D*Tn3Q6-VA{GQ!1E_Bk-9Ruf=e&g|nz95TyENg;sn}{!)nMR|UIt37T{;_# zt4hY1-|ic*>t33SdCp2>1M1%U|rr@0wiSZxQg8^co~#uX+n$A z0F;ab5XT%*{Ax^suO{J#1f6_d?S*wvQD})GCdV7ES9Zp)9{V=$+Oz(^&r_!&?BlF1 zD^S(9!@k=uXRz+EAwbK`;+o|jgE*fx3IrfsnZx6l$2k|v&p4j29Tk&IUq4a7{!H1T zNcMPw`;utxi}Qp6p8^$5@VPtnkYbIg8d8?+EFmtWjNxiv)9oBde)Tmu{pU;_%dhZN+Bx; zXkXE)&|F#*BaKtRkr2x%6$lJA*DwnbH1#S`f)Fwgp{2WNubUjEwv`|Sa2qXJOxA4D zO^~T(lEHR5*XRsrA|1WU1sf&h+X#_xt{RBEsBn9z_TcQbd=0h&om=x(ANc01!$i!y zBtmzjm3X^-;2c&3?GxdTtKu*1cm&;RO1O&3J1KtnmPFmTl#{it7mnmOth|WAj3Cjt ze!@=MIlAODZAvmqHo(?iL@ z#)GBXws8+abgs9WL@y(r&SJld#ozEdVA|RP)WHkiQ~;gvTfp$#gbyY_z!-H zUD|&!6xvY-qijdlHH6l_hbr;VGBy%h7rRA)2D6x(1Bx&wA}Y2_mVylB z^OdCS(I8I286)!~-0v@ri@FujHrU7A>(zG!IBV8_6XeuPT#0Loz|%lvZ)UWkqG=@P z&<+61MPC$UI0S8{(+Ojs-r(Fdf~15E)Pd~xz467bO`peu1j)jp9hv}!?@%`hu;f=cEnj< zQr(#7VIQp-D?vML_5}wnN~LVHhL%tnDgSU^n2ZHEfBdsPMnx#NVdnx7ah)FdmzXn# z+=tPGH~QaWr>89L{e;oX{P&jnd_SUz4DnWk3%M4Yjp)YkA`oe}fy)3eC8Jp5%2f#) z+4?3EbiF7{(NL0Cj~3ed%Ki`X9H|jG^5991VbxnTgD|IW@N%`nM`Lf>ie`>OSQTqq z>mkvl7PJ#rVK>%Nbk`E#!}uWYVE5PhkEYjAr^4{&^aa-d9qI<8|T*DTqOJ;X@PkIj(*MEZZJ6XGb4yN&X*)?ro z-CUj~Y=EWhWK^b%^t=w^MP%fBV0WYFsCL+i71h}&Iq>~OXn|Yli`vZPT;DxCF(mWO zH<6p^i?t?7&FwHC&e&+E${qtj8*CaxWQ14K9__FU~+=&%R2dX?$W=@#i?7RNY#q=QnBA^mvW^&uf9tMtfz~NLY3h{?A3}lqNRcC$QjqmE>?tt zVn0t|`@ddWs5rPOW$^=zX+b)jt6GmW`t=@asAP6T+V3m%$7_Y48Hepb20UQ2TlKLk` z$Hc_(@9OCPG(%bbDUALnN&W8z1AcP<q*iu8wYgt$pT* zEnUz2>h0?36$yz2LxuNx{+ij+uXO`=2=9FU_35S3v*Rv)<;@XTEbUq{+3I(*;IDJB z;#UjH`xX1#+pV*$?}vE>NVa=-pLsfaQ8?dLmp}?jp##T$|5lLP@t}(&lI@^_w={d> z7+9#O2#Pn_>94u5(wuwV8`;DQi*a1LJvbvi$gZ-^Y+y<+EtqqT_OgH^)eWA42 zbdstJmCENTrsT#y@UO_)irHYg8L9L#G>ZVcC08vO^K^GAbqhl^!h{*Hqz%%ch_{vS z4zcfy(E$aOMrj<4)?6#-J=PIiPqY1MfYJLKwAWhU&Y!v5?!xctv**3j+C#-2To_nz zX*gIeUK~l#c3Sp7`^UO{5ZSJFNVzt)GWDhij{!^Q&LAzFSJl`df{wyYjMaV1tX&}V zBZ%`}0xg&t@wgp%{xP=(W+-_PH{Y6YC$qSh5(g-$#qc{ruFu3hWfwTBss->mCK!nl+08Swhy7O|20#CegcF;JeA;#{;Ld31E zX+mP>P`;Vx{?gvU&syv9^re*u14BR$a2zQ{|6or2rEd+#l7kKN2s|LLyqe&q0B}48 zRP{c~MtBS*15w+6GorMKgaLWvo~?e>uRU>F`*XN6CVnI|+?sy)BRuWyq(F^&9&)fz zN>liq-M*5~KpW@(|Nr9YON zZG!|o5C?MRRC)m}Bc_=9kS+x{)Bl zb%toJ%~)km)2A7vv9d39c|F7P!@r9Kg@9D+{gRxBs;7;3@4?xL=a|5X6d3H32J$W4 zbw&yTs2o=-!})!z1STcuR{FN|RQX@WQYKQ#b)%k?43!-FP3uuq(-!OH>C6w@Tfu@P6=8zG6(+R`phmPrOKat(fG9tPc@p+l`=&8F%a2SYze7sn6ARO6^WfS6W%ii z>ncPG=zdm;FcKwS<_WC3G&l^}u@UbSPV+^`Rl1zR9d0R3OD5Y+d2H6JkvTae*1HI4 z-R%x6YK)C8ovanG+_2U(tP^PAxcc>?^)al62?IuZXLAzF>ohX50n3EXfIBqPSh6Bp zb#{p+6Pd%1i3n5N`5}0wtae`lnmkbRHJ-B_#cO-{?(yWZ+|G~e&82D(;@F_eepQ}( zd8Xb_8Y7K2l`}0mm|9<|Y`AR1`H~yQO{?_F{5Waa&&=XogIYo|wQG{fu_LaEeWrFf z#OH4t{*Q0`4)Q#Sc75??_`J4T*gt!t%2B8U8gG{Ddeqm|V%I5OmB-#1wK}KOYO+9< zDj3g|1G0vip4p_+2kv|ziiWvdj*&x_MC)L)$~DpH%S4HPvdGF8p3L>UP_-6|nN~@E zxJZlj_yljN5Dk*8q3qz~raymuqQk@vl)p9;kW(G+topQpR85+PJV;H?wKrLV^^rCR zKT3m@`Np0nVhJ3vlFS7&s)bQ}Dww=J<0t%Ow6xd?$<|?b{TM`E|JEI$dcY^*o;pg- zqnY)ZY^xw_rXs<5Sa=MiaiV&n&&$ESHH~JqbP8wtpy{+!CVO~3K$dx`+J@EVJh$yj z+iQh}EyPGn!DGhzy5xOZ8RLsTQ#;M|Y`(8v`ZG76#O0Q2s^0jQGn@nro2${3WFypi z5Zc}u<-#UbQ?AX?<-=ygTL0{ga{O%%&6Sa~wXW(F1diQu*`scWnRZ-?kk3SudR%J& ze?x+ngc{95N|z*my$dD89iYiWW#KJNM!VSJmv59#n=6rFt^y*3gnyV9r#U- zeKe#fE$J*YRc*A_n)%ngkEp*x*c@iC9R@vk5J4~?<@mpKL2|J|H| zq%|og($8_Q>%Q;aLYfjZ7G%Q||9IITO_;e=(*O>3EA{ogP=TUoHsv+vs={ebG-z^K z6ch7y7(KILxSQwm=K47i;#;#^Zn|;-|GVS;U0<%ZxN!er^w%|>{!JG|D%al4(%EBf zX>U)Oa@)t_POo0@*7T%kNbVicR0-Wa^amC^1jl>qO79kL@Al_B4MlPr`ylGkq?;Og zxnVWAhBS}eh3M?uUlzcVqF`ve1w`;)JT~UiK(x0AHFpTLFj2B55%lKj&Nm7uz6nU8 zw;OA^haIm`D49?*ih=~bh?8c!5MB3!$GbO;lD#F=c!Q`!r-Mt+eM+}FJsh7{YR#ytH7%JTJ5A#=8tm=+k~;i!M6@`tmAjmldmSOYG6+OGkaSXE zdUss6gcP^vb^ZyNypL0w?MhvH3hVwOJ8iQ81Vori^IOCO^A1zq!Ol^jZF+SE|k z!3ss)0Wa$S5Gr0G%QZd}V8*RdO6wrFX1Bl&eMq(6*@fff05={%+>(fMCcr9>riy?u z$Cioc#sIp@K`L}P&R__aD0q#6V~_hO4wN|(VL^^`PngrRKzhjVeeE7uHE`0?J~JEd zAyH|7@=x^PBBExMpa`ors-rPloDyB?)(XG4z(+uhnRUoARZrO**!C@D^UnVS%cpl` zsCD=?7x?09kd$NoqAO}ClD)8Fi=6ht#{f+!IyzWl_Q$NZ|1D6`f0Qc#(;Z5j5)Ryq z^B_z`jw+p*4WoKV@BF4+gv0j@v9E^UE)S8|<<*y+0J!_)4k^A62sQwUP!M58F$BP} zs}MavJ%GGI1es!uxB|CEhZ_kEjgKbyB`JrHQx1zKq8MW~bkKi!%6dz+cN#y$OUA?@ z$#TFzQdtK=XKopCN?=W>BZvjYA3Y!I%epi95nlk`!9eVSGCHb!BzfAT_+3UDM-=(g zV5z#JjcEh!egPmR-o|{r-P$G%NUSkS4!K^Y4L;F|sDoUB0Ar!QSU?}HO-%x3z_dZ6 z5#+F`X=NcKWELQza)^+i0j_3fq2pvA7aNfg)#mxi#YK~! z%|xlpqOqO2*mqZs0Y7m+0N=hCfjFF1cZw1y-KP{=MhtOYJc&9Ag(kB(6p=x0bo=~4 zb*k^Mdlw155LaQ8>=xF-&*gi~8l^U(<`|7FI8QC)T&zWj^f4#u1+4tGe&ad}uYJt9!>eFAbqbv|^rK4&5uTnB8=lJwf@4S} zCgzmYVIz%ydxMzRFDlW7$_oi8XyEFxTEy3j69xk8YaHuA5wbL;h`6 z@o^iOHq(f7NJDN5k<4B zl@xGYXs_~W`Qz~RF8EkJb&X3I)MZTZ6GU-eJB_0N=&*EQ9v254QP4q*H&o?X&AsUu z!4zLUCJ@I%h|>s{1?*KftJxr5rI(tF_m6ufHix*ay5Qyu(nb{{^0T-z^mjaidIKGC zy0+(g0`FYpBfK`ek_OlzLd^a{}43{qn4g;hZ8h z^{b+kUkQPVunca%Y>h8o>Ssc$7?Lr@`2Dh=y*j_RO^T8K3bAYDOMV_O?y3 z>YaEn1&qUuSI9*#!~Eg6#J5Y|dz5NnV1!i*(!b_3Dw?`4u_!Rp%$fI#vH@02htiZX z=&sq19C=sUBV_-q9NyBM_{u}E1vnYyp4+||q`leLHoOxKPs{B{!XmhXC@wu`hbK0q zj`j-s+nYJL60KY0vZmGRn92^PQ*mH2t^TDu(kAe_`fDc!r&<@ay&PJi6r?9x(P+8Q z0JMNo`ByV{s<7u?Yeb48C;_Wf+_C~?RLY6tJcw}KVL25Jf9fq-m#lA3Hc?yL73|YA z)QhMsh_q__U78I z57xp7lo$6Y(ny`$AhM-UBK>MMN2IRoxpcu5Sp|g2YUGoz#Rgnaut-2S#%hZHK*^nETTv9Ieo%k3d<=dcOGI(S24E4AwhS zEUL0iUUJx13ao{$ST0jOHaXCZvzl={+6*k$bM4L$mp*>Z_^*ve&fp~8K3cYE)E;xT z*O>aea??l+l;m+b8p5y<}roq z&fC^!zduOB&U4uCEW7K3zDnmM93X2BW1C}1P;-r*Lu(T39Tk*ds}fmkLMyn= z8v>xF8V@6M+1X2+xO*3aNOx?O`HLfn8?9EWKUbx0;1=@xzF-q24X}bYGN#gkb0s1x zps$g6J1p*#SKH~p9QfyHRaN+TEOYgMYz#N8dp65FvhDhJcssN6O`Jf3nQ9-z4AgVz zdt{AvGYYN2f2>jIaUuFe#vAx$O;U|O_l)}@-N$Tb+6CV)IV)~Kql((%3Civqg>8Ye zc^4E}r?yl!Ek^N_yw0fA*rya+cMThh(J9i&q?M7Ak_(n7@(Xu$OiK_&Y*132SZ#x$ zU#p9BWoalY-2!*{7TM-d60BtYa`N6>1b5kdsC5NiFeM(qYK6QxnnQC*Hb&KER?tu~ zUK6X7f5UMx%?C=m(zCcz4MjhFeu%bp1x+nA;*OM9f3gOc=NCC}mHx^)A5ucpgg8%w2zS|J>PoCx~N_+-IssHibLzwm zCno)PXLVyPi&AOQ#6o|Xhvjq>KS6GuJK=%(p>=inrv*?`Qz%18u|1dbl_#?k7-2Sp3pHHSw13HUur63 zK9_nme^wcQPJseCu9{IcnB!%Hz&;^P1p?(FXiRNBMs%kb+TTz721Xmo>rhE#%_*6! z!vf^BZZ@rWRU6k7*xK;@`Wql^wV~kx!yU%@yh~&=%e75MZQZ8J7HswqMkH_I;u8-y zorzziX|7bIX>94X*HJ#@DlgYfdBS!7J}oPN`zmu(*Tjx>%HYU5T&pTU@BvqRGtcQr zH3D#@JbTM7i9)tV?1he7iM{&LbaJJnsa{M$1`&8?@eUTpUV6l{;e*ku2eWhbOj0TC zL9waVdh0Vq5i9>GCAa$~_S)Mt+h=bIKdnV#pWo2kXe0jHi&lCOA=ogaVKpTo!Kp1fm6DyiV3L&pt~ z`T-X*xAWs1&r<--7*}35o2T2+_S_8EXRTEoI1t`y%`UhpNWbbUO{FFj2A_CvC5QS@ zv`fF?w{9}=Jne$$8Zlm_FVY5tM0V?qR+6~zl%bDl3VBL$ zDZk)`TS>ve_}A_9_dtH@n0%^6O^vL{`OKehEWr@k9p}-yFk`bQ!TWZ8!so(aXoq+t z-kyy#|DSPKT7K_=WfXeIPC;}}MD{GzI}Ptu=naoB5PyQg#OdCq51+0hLUn&n-L4w7 zVJw9r&2>vA*^Jx5T7AAtJ?8c77Aw!q*Cxi2wzrC0fu{@u4^Q1h+sqfDj7ORtFDdtq z$2{;4aOupY5z|M;Lu}Jk%EL+Q>~bvq=>YfPcK|A#To{J*kJ2wDH>p1x(*6D2M$Mo9~Ce~sJd=Yz#>H3DV_X-NI}R4RYC zOxe70zjRyG@3Wk+C|8QDm3VX?{4vJ2J~|O!X8bnQNnLlox?Uekw|MoHE_*(m9iN?m z1G%C&p@4GT-VC4b$1XRo&o1QuJUl#49V|?xz5)+pX}$Wb1NOYXZOBI@az=EDj}$9*m$=GMK}=@ekPTB0`VNGb0OQudsjn zJWDOX>E4fSESrKt(&dUnu03Vb=|Jr96S`%lhq5eU$1WRYxcVxuG^FmPh|!#G~K1LvX*h z?6RC3xkP!p6Y0nkT}a43rpdDgwA}P=7WHFb1I|3Y5jbrWLD+n+$*Or(@Ec4DowOA= zyy=Qnu3&>!D)akHGB;k%Q4Yf1!~E<0(tb$HNzs%Rr((T$2RCic5gO z?||%dHo^(wf`%zKpJREcceM;#O}+Hjwi+*MAhQh0-uhq@Kb=gWW-b4G7h!f|Y z6^C)#K_Dp#wHVfDv=D`rDdxZTg)&pSd$lOS_JoO(h~&aCVpjeF zW0!D${Ip0qpJOpD!FbAI1mb3K95yvc?H?!pWyQxy7s23=a`ZVXV==Bv-Mna@44Kkh z(>G<(Rxys?BA*FNaC#-QtDeM5;FrURILh6N4Pv}&DOad6dspLTgF7!ldONm_e87{M zZYXk$c0FGMpdBsA{Yw;3b6F?Qj-E=QQQEImQP>NAbME1q8judY&jw9eN+>QVTAuur z;H zi`<@2doysSg7LRae|g;PFj*!(+?T^ib*BURvH%`eYYZ~nu7ma(8KGxu6T?D0YW+F3 zD$KjzXnBk57pqWR&C|~jj7BwEFUFB3_ zsN`vg+#d$_E+?Im%?f2!{OQ&V;F(h#TlLy+#Y$gOlSmB)iaG+t99DvFbLy?Ri_)Jj zp@AxmTQI4kmhh6HXvbI70>mR@)?zqb!Pgm?rnJ@)t}LlNR^S9x?1C5`HCUNpmT9vQ z>yB_PzjxxPFD$)CQJ?YP$WVrzNV+dc@8-LEAwJLsbiSIOJ83wlU?LHtvT#iRt&}2m z^eh13Z^g;$7wHlMgiHaR9^T*gmzC;_`C2}ewdInqH{_n#l{oa7XBnnlB99^A$O-KW zz3bG7GU{unM;jkur{OI{RNrxSP($IzHtgt97u@=aQgvkVlL!fNyJ{9D=%D-EwaLOn z=QIe{<2#rl)zV6?N!k?Yic9_1nZw!0tI3j0*1?Q*@MpvKkPN4+N?5Z|JnLqNbaFHp zwV%^_be7RXi%B@PpVi8(t$$KzN9k#&mIGiXC^BXq<)?vPleu~(ER&6)6UhZ}rAQPR z-=+}#FK{l=4wM*=^^h@%BfkrVNk6!;nOIq5iK~uVwzDxg_a_%*5 zmh_N4iLh>>G38kg$?h)1@)hNYk)j8SWgFea zJwRYYB=AL?281<4&z~fgj-vCKjc!Cn6e@kG3LJagrIii zSG{s=ov?&t-5unPyjjiF_6s)r;2`tdx|ks^n6`a~8XD=`iQC|ZeOy#wxrcM|gWrv* z6k3jUoHUj~3@LyNUG8*(WN7754>wcYtz<+aVPZxftz0{vajpQ>r*mrd^L%G&#FMY2 z*0`*F26J-1Hbq8&o{?fLq)wCX)OcCZJj5q zt#>R#)gh}k)+?Wp9kyd=GsNo|0ykb&KgA&E+{$9%7HCbp1U<{SfM#TJ`&&Je;cce~ zN~v@D@Sjm|{Pgmg=`j13i|qZqYPUWrejOa!mg2THD<>^XF?N&qni1rYzLi=D2~0x@ zk|dZedE2;Kk~nw5id)yc+Ap_>7N<&o;RaHv>}!u1Tq!AjR)Q%G6lAzFH>d%2ajI+m z>~c`)@Z6yo-4z64q4%i_rC?yiAZ}juTU&qln~Ou2R@e{8%$HjlK_{x^dhI#RKt?qS~1f9`` zuw|_esvfG%A-w$BOn3x!K=;eV+Jj>6|2aux@GL(k32X1?B=KY+?dR155mOnpL*~>K zXSy0d&XgU89z&*jsNcDwjmXy6QL3gTJ?f|Rhq&`1$g-jOPNh?Sa`!3M1qGAUjv?p_ zL8KE~<&Wu@lmOm%-9z=7$saXtn?jCu`gaPW>K2;(|3+Gvu zIZf?FTRgJphSIJ74Q&8s#)Be9*(@dx%U7Gk_yUd^)Xf-YG<_guCw{dkpuJ13+zTq1 z)Xk`VAoi%WFsqpnB$ui%F@5}q{Xrm2F8|bXzKNhe^wzx!ESrazz;omV6_UMRpFu`loAZe?bX#`@g! z=yo4aH$rBthmZ0QMmg~1*YoX8cE2y|!?di&^N1}R@3-}HE?tF-@5ja7*%jbom?Jlt zSI?*8^E2Wl0PpA5gnS?Ld6~`$H`bDQPR#h!R~d=dpM|Qs`u7ANVlCG;G80cA{?S*y5oq>0#t4@Q#>j zclj2b z;M;j1R&tUq0*1rAVchF;j`3tnq=pE?y6f2rt5?fZSZQ@aNZ0bhC^Z6t z!$;sCA0qp_M=~ogr!+n&$~2wU<Ux>)c5(U<>^5`k)RBU4f!D^k*-ry`4P+cZ#hY2qNrs&340l~^QxF!1P&Ql#f7>} zrsPzW_d~eFcgEreFEP@I6w-z0A;&}`uX^4?hx5)fKFUWUWs_vEjd3jkR@hU5AO{&M zhl$2oK2Hij;Nz=P8-|Ldoftuk@bNEh2yh156k41GmF7X%MGC6V*=0lz2g~0vNS~^M z(EGeHSZewKV#?LkO~%hoEec1EgE7Igc?{W+02qc2k%!=@gcHM0#ga=bkV0u!qA@}2 zl>H*HVWm&u8?pZ*-$sT))g&z1sh1TNj~?pyAxv9JOU1n$KL|`~4s8_AMd&eFmx`A2 zQ;Vdh`nF?>0WiZlb1z2%r1_vhz*-ECc~~+zurg@yU?<9GQ|8ZqhQWLY$_}=};aor` zmMerc7!Bb3g##p(4~1A@4CzAD$fp=HiGR4@1vo1ZKc|eSZXXJ&&Ys98V5d`XDbYuX zdhjPWUp!3bX$mp^98N2tbr7KgBmgaF6IU!Y7lUMV! z-jw5{;Z^!Cf;L{kIU{o0Q#{s|`ka1|9$0 zRH!}2+Rn?k#c=~;AjXu+A{4A!#Ka+!hx}|4tBs)X^TmU66^E3MNXLM4mMdS9c%We_ z-a&)Zp7RKfiMjJOA2lvXB(jHKrOONdY#6`|uyunI<>(dW6<72M=8z~vA58!`TANps zHEX^oNS3>->w4l#fVWhYjz5|u?=ns9~eK1#oqJjf!FMoU${}g!V4s+nH=YYpO=ipDndgHsbf9 zgwNq7DJzim9ce1Ni`^{?L4nA?nj+PqYHiAVOCWca0w=}&;I(2e=}A-{##^(&!P~$aSp?f^^!LYI2*Jr z;zx$OmOtb}8JKt*bgncC_Cz5+TD!qU$B5r(GYVKI`oSSx91fl7xPSOm6G4&J$i{-O zcKxqGU6n*xi;7Zs_WiHZtzi%dz%X5y=%r5HBCVG&Bm(TYd59@x!X!v$+9+NoC_mNt zSf$61zs#YYt+wZ#AF*j#Rmjy}Uf|&$G9$Cb0m`bL(9=*L6jowFOYB-N)s|G3#*Dqh zM2WnyQQXm@GE@71emugf7st?kl=T5^jVwapZIOF2-c2(!{4a{@ZLT--fg$0T&DOM< zFn;5Z%3A2(iS6ieg(JwMiFK|f>=o-Ww?{ku+Oo`AK1EthZOV&_OcNVZ6y}ZCS*Ie- za#<@5SPL@>Lq+d_Rmk2}a}Etd-tIHCSv&oOdYwD&j2M5Ng&{r6&Nv0?YyGuw zDKPAy49s{02kZ7&U6q`!NM>oxDd}0^qM2(Kmf7dJh0d0O>2;c#*$!{O+ZrSRke*Q& z1IRtcbDhncO^Q)UMDOPwj$TlG-Rzy%>yHcw0v_GvR|*s_XCK1$o9hpZsPd1d^x1PN$D_Cu^q4|~;U#oI#`6sj=yfhnL zi*jzz=RRh+cQj})pK40aYtAYUHZERB^gqpi5+ILX=^fpce_Ny6otziW96h>0$y+ZU zw?RYaFRUF_&mMJl2((S2>8rN#0?7@xghCTSG8(Bn?^|TH1sW6IQfSNP#9uLeWum9c zYJb5_$e0fLEuI}J#eqq9r;au*oq@#0cj2`Gh3LTLgMD1j?1r=m@vO^4=kI)H?L9hh zb_ezwstYlH-~+i%;9I4i17=xkz6P5AvYr6d@^Q)BHYeYPbLJOn!eII-4+FVfY)lkWs4n1jPIC zTw>|c@)owfxH8Qva)A1P{juJJ@?FxeSFt}ih0#j~vxHma<#f=Rx7R;x+x^1?wp6_R z!r_bwud4Mq5Pin%Tf2CR9tx=SG5o2Z`V{eiRV~M-eK}|CDclh|dr|%zHt5^>o`0AR zQjr(mujCz>i(MyG|7d#WrEF2I_^)2$zqf4}m{=J8|Jn!3f5Ee`{7-lmtqGe8HiWGc z$}XHg=qTdIw6q>fW@%mL=Z-~u&+3m z>p91P{qB7K%)8|Uf7=b@`M9g??EOBv)$FQ(_5C=x9+}XVV_U4WtA(TeDe8W-f&+No zyZw8kD?2Vda#yqkLR$Br%)O`j@qW4wT3AxZ!gPyE>)Yw+)Bb*B;6iu4{Z!(cV>b?- zwFlA$=Ci`q-JoY?@uwVL2>lceYlwA`F#65k_0IQ%T$hCl@ zY^c;NDmq~8^^Gln#~mA^6own#ZAV;VTZOm*x$rbc!MX0aX1Rjb&!C!vsev5^1IBy| zhDzp0mL|?B=f+*qLb5rt$XSJxsW}GHwvt@5c%`}v zSy?66zmzh}MsVIv#dSusx&t?}!(N4jxu!yd#WP#fMTj0lE)03eiX%mcka8a=7t#rd zci^;U#7K@{r3PPYak35YWJ~}$Xrw$Ui~wYuuE`-QSo-(aM8ZD~oeTkW5QBmX(Q@JYpoGb(3dit!w(CWpI zu)GWaq@xbLS#`h+hNAica@@U|kTeDPm<2mP#1E&{z3bHN&V?;%stdmPeBg#qPX|FN z$a18^o9lRFm^B>;L#&l=(eFXB6{gttmaNdBm&3VY|PmoN^; zr_}V&*3p}rvQvEc3p*D+yq_T4lU=w!@LPdz6~5ID3lP{a9q|BI0}P1`NI-0q<}H(8 zjN!NTeKH${eF%DqmjxcjhorFcKAs#$Uk3~; z9`%wIaM9Gpz0}R_s53L@9GgmnqS~t$bVDRM>lB<9h2t3h0*-yKL&;H@Can2RKm|4G z{JX_cK+@l&rQ*6sr=*WbUc~60{0yhnI-PXY^+KzN5U5pZ`2Ku@kD~G)Y`_mYQfB^6LCuab{ba@ z(udTBmz$ZQoaukn^TDmT8ElOMn<#sbP|S4pv2dux4L|%+CO~};$CEGTKSrYMr)zlR z^4UK8OSR18tqfP{ky}rh&WxkT$k!iqSA6V>HrqK8l5V zvrR7ncvBn|Cvj-sz%%q?HTr{rq5sQjRE|;#KsJO(icM|%$bfX27EY?G3g8%OY71`T znw&7Xvu5!d3rW%^m|4{me+B`Xn3^xHONKDhGmwnv)|SScr?})%2}ezsOpiV^Yn^?J z;7|OEUzD{A>n{l9@mTI?R(kHA-fU)0FTU$o7KL7XE8tej3;7TQimGjpBu*Ub@PR}_ z$H;pA4-g2OFRda%dW*1@*xnSJg>qkFO#ClRuyj>_2YQn1@74wABY%YmYBKZkjM#X4 z#vI9G1bBXzRLf&J&LV>)b9|Oy<7Ilm)Luq86V0@d3^k8bg`6RZHi?lMIigOPI~Hhi z#Y;u6$3OeO7zZ6(;#Vq{ds^l;T3EJ#)Od*oHE%520$X&tkKH_1ox8TOJ}$6qTqzyq zHUXXoz_D$fA*9r8RGPI-nlrN(S98Y?SlKJ+{mnARlXQ2>LLB%dP5K9sYbG;hX%ckp z%M{Z)cox^}xuB=xZiQ1~IdPVk3w~2KmnAG(X$xtklx_V)mveU&FXy034By;`x1D#B z*2=E!7oeYO{An~H?RB4fkxkNY9V$J;_A@xQ^x~>@>K;_Y2x>kT#<-YbW;3uSLKUBi zEv)qnN=diwYZB@`1vddg+ibcD4^2YF&#;NZ!Q3WNjhA=i=PQh#*VtWYxFfd^vJ>8$ zGj6H2>(`StKOSzRpH(Bfc(-;mF7M|)A9#+HoqR1dbtA5IZS*2(OH}z#K(BJ+u0u~` z`JQQ`>&<)SXf8Ti3*Ms@aiyM2AzTzbQxAH>zhp%pXr(&%?=de@%a3Jc?lG|uWV~oH zdJ!%&k9(P?Z2#zrI;y~VEqsV?=9auhW7IGNXe8!Iq6_rHbNuPDn9IYhAp}^UHVe}D#l*g z6r<&U;feENBjp(@i2w<*s~9=^;76|evHE91Tnx$*1EA07*REoi|4}nT2`K|oj)9C9|6l9%m-Ryb%~BY z<}FUueF47op+TkGw6=MiMK4KOBQUSa}h#K+VqyoQtO; z-^OE%_Z09J$alzTCyy;+`{4@6M({&(8{KYUP@{|!PT`2(T(_sqREMMDq6gzG@i1`3!x zX!Gw+2k1ZDNay(pi*W6p+_l+yC{mi#$r6t*6%Xzz*bmn`oxU!RU+&f}_!(O(J2(HN z`du-UJ8ONnxw&?PK@|fdz#Bck{t5M8HSr8?-Q)IRCF4GQ&b{#CHV=qC{))ZzzL@~v zIw-AY`&>E6z0UbT|4BW~viQ9WlgI*(w&QjbhD7hq{lSSSvaCcF3!$$C;@V~Ua2kfy zz*Z(gK4*m+(6L0xr;gccMWpx?a=epwF1mN8Bgh|^yRW+u^XoG|<9cDiFy0dvMW1B~ zEzUY+w5A+3Q}d^~+GDJPr$Y0W)&q|fJzltJ7CyT!d&e)Za_hkDe@PAij6NY0-ki(1 zMJ#P&0;=T4kz&%;!7zgYH|PtvHhb9pD`{8BZov_Ir9XJ0EDpRH`50E0gCzHjQ9H9Ol^ zL>~)}NeBB1I`L?la0@bkO%ecoJ3*SWHQTPZRWNN`qGl#JW@_wXG^^6}q7*B(V$dqJ>9$DR3qPHQ1KTl=^1d+H@I?ZsE z%(_~VJ@t=%00aKmfVhZqJ1lJQthGod=PD@W-kapyb+=NH!SbPC01?<5v0#uPPYB*> zIr>J$$duNfgwV{huJjUtC!vIC;AAubwcp=#x3BdLTw`VCDyYE7&9$s!qzv7DWWf8t zuidz>@q)#~9SdQ^Pz4v`&NYP*RZ6MgF+Ld(icd;jyVRU2IwIka3e`cB8JK^I#_8^0 zYjHa*X^$+jkQNfknLZ@x!*4gH`AxBpcjsRh_6!iRl!i49RuuV*;U~GGs*&X7&l#yK zhdqPDaxE8Qo{?}`GM#Y^XC0LPG~RK0>Me>0)w?hoX!F2OQRUQ1TIoKsohT(L-lbv* z*2Z8YvJp)rP>gkT$?B?Rg=9j=RLz7Q-a{tsmE!gh2bst%%9tl+439O=$Azq3%30SM z;zhxjf=rQQ%PmxLyP0196XfBng)LkK%5;z^UNuOD{Lqa8j5#J#(e`hrIi}$q$g0;m zRU;H(5a9?|guDjo)UrPanXcDDxGf%#*Rn?k^{x&~`(03I-0x#QL_4IN8mVd%Q?6aQ zDW-CaRIBIb&meY?X>ia5k(rnYg4c$UYM?CY%uwO<3e;MI+5V#`6Ol|&0Vz*}#VZq* zvkaqr?SsJcLhO_O9C3<+K{rYHmS;Lk+H|L(?=El8(7$&8>F((UV;^W{PQc5Nrot?^ zNF^|0U6gce`khZA<}G}BoWJVC5tin_W=ZgOM2Xs5+o}FuFFx=Df|Tw|Lf=ft0z)NY ztk(}`qyNh#Mmaj!TvMb_Wu#iD+&#>FASou^Mxi}YO#<%dJW?El$D0jq*_LwWY92Kp zz}rYaD1H;CflE5d2dpPl&XR!kQrB zDV1u`H>%mj+!z=Wovss0czDh|x%O?qDylv`rMqKJ&gXpP_)+Zm zG>GcVg=niHWMh6`zpPGsGQ~APQhd8O$@3Lm$1j(1 zq$DF5>q(LVwa|6g*8nGrCF%}_Hk!#A=vo;GmCP;{@^+%PEwQogn$9R{X{E%7MH50~ z^Zh=W+zx3$WpJDQPUv7MVVSi8sKxgL++{J!liSc}OypMyrNaYFx%i)=4v(dE_t?Mk zN=1qbJDS^>VUrkEMfj!nwnT@nq5{)e9RmF8rzdKky~TLer=avbw2%!7mm>TAJG9`WJDoQfmTb@ zGLpfor)dqlf}_KeAhsVDk-{GI&h?o#+=H}gSD<~hd#JLRFGEMtQfQMWM99qpiMkAx z;h)ipA3<3LPaCEBNTnFHx8Wr>unV(Zq9XO{U!D6%sgr+~tM>PE4m>miz1wd}DK#Hg zN)^&12A=*-#5L7emVZ%Su}NnxJ)=;f-l5*NC$GB-#@ybaHv6YEmGm$;SxsFC*(Vd-Wa&^)V)Kgh0igGzCAfp8j=l@w+QR5LOtC2?~6 z%}at)NY@ciV(BwKTPGtqV+e0-J%TPAj|#v8*CfXuEKBn}x^dp#b8iMqes4B&zTezTXu`Y46+`g*>c zg$~^4D`9Z^*fMo_` z3m=Gv#G{G?UXQu3i;dtF4$yo&NwAlSoHOi7)>6-Yby_48*b9ySZ60zqfd1Agq55Xe zK~)_$V6a9u72cpi3x>YgU1*eMS`DHuAPq&)GsG$uIXfl_H5XdDePDWhOZEc{A0ZZ= z6#oI)$k6M9s04DQm04+=n?nH`^yM8F9U9F`&SGBjpUeSAwKY+g0eIHq5LS_b4$_@5 zNqa_MvzIF@#SnxLCt$qN>1l@5PZ${`M0d<@gY|}{uPZ@P((j1`mry;M2LR9Fi)+I> z`^mEju|SA4Lt8E;96ZqRVWH;SgOiUs+6*4ye1hYOdjCbK1{k=#lZZ7!G2~Otz%s>T zYEspo)CU;QK-a0$a>a+JrL&@^-3RFPI$DF`(A4kbC>+}UYQ)O%abs${CGs_c!Ql&x zcbwHpu$p9v^-msvV4!p-0$~InRv4;#noHg=#ndga(|DFz#+jQ1o4i`!tdpS2%F<$D z(hS=)Aes&#=TOHf3EL$TzOarfkex>1oNZLqPuH2(g;BfnIF1DC+wA)*Laqr?Z44Y^ zz9053KqBBI$dmQppoOvFjGj{56I+aC7mQd>Gf`Ar1o#AmA!;a6Nzyqu3(X>CsyQVBbsGq5Vt3Rv3}V})uYNSRl2B#w(hf;wxf>1Q*o#rGqpD_7n-NNR#+R|F{*v_SUU+d;`3LKg@n&sC0dW6Si+QzVaiOO#g<@N z!?2@qbc+zRfX4gJPxfnG1P#p&qqdJe@yV)>z8EDNb;24uEkNDbGhy@xE04ZeAnZc) ztUbxV!Zw3$jt+%TGxxA4;t9AdWZo02DU~G>zKpo(s5SvSc`ZkO1Ik8BNL72lNB9iT zE|)ds#=y)N20a=dXrFs!A@D*GER2b|`s7YZE>VT3YcOSj6m$ers}YD{dJdIjfJHfz z{4ZqDh+-gW#;QH)1;+~uf%ZV`kro}&%wnj4qJBht)G2y$T#G#2#psS&I&z@#!ve|5 z6gr|f-9J51a}$%1!ZNU#<)+~9P%;wSXY9#dLby&M+sHxdc3z^v0`oNPV1mgfV=rmx zzl=n(*#1wUP&X-%r8GwRug17DZxJIJ&VXdAXLnC} zx#Y%|@puOam#Tth0!UG!DDkFh9#-j;`#|f{598o1-uILB>p_+86*%a`*P*zkQbOxSo7c}BhoG!gIXc&`GZM8-Ylq~(6WFjWW0 zU)o!GFvD|E`gEyve7MDD3ubv}zj*=1oxesqH>!rQ=?PuEa0zQAh`qr^J)q~^iBG!q z48FzzlIVy|g7wovs>{ITjhWW$tukKH2I|-Hh9|L*?jcBeQxvR`liNh=l79s z!+kw6Uj*E$uZehKaI2a^qYNe+fW^aEC8h2=vq`_Rnevm!wwLo*4UY? zaD+<5!e?y~zz(qSyTY0)rMC*~xgM%o)M$rQLms%U%K5~Ba@_wyJN6~kxkm4Pf%!As zn5w0yC;wdPk9E}+@t(eUrOo1WC+0FW^cop9tU;#TxHJmwIN>YK-WBVcwxPF`5>Ko- zElWGg!Zu=ethw$-`XJYN&+5~NI7on4s>u7u4p{rz-U!Q)3Dqq^bB$8oaw;D-JR`Ss ztD9T-kIfl|ySqmzL81&pz@pLNBwpBekUekKB>aS7h#A*BJ`fWgqRh;HOM}wWPO&pF zu)^e}jzode1NG4UQgwgJe6nh~ch4BKj_9+{@E{ag}I9HHhNi!3nj~aEmM~IWbv+VKENIVw$QzWJy z^rwUV^Di-ima$Q-WP5(2fZTZgU{6CnmBjfTnJUZbd!)aLVbuj^AqQ>SF)f&OeeSWp z@U?DvGK>6rO@?QhFLfRI7u~b(_RuG-)!(VL@B50qML*uQ&9(1d{CC~9FR)AB&JD2l z+AbUTJI}Rmfzhee@0@+tr|<8SPus2bzAsAB1LnJ{S6}OwV^jO~+RM*mSAr#ms|2)E z`^I|}5nmS1+?F;L*B!_nAjche56kWCo4qSdZrA#!>;rFdQ{ENR$PHx;ra!0CtG-F~ zqH!MH!#)4Jd1J{&Z*)W2kwsZAbW`2ay2NH%)lK(z%-bhyQER$qhqf=>0av%Z6vde9 zXsc@)FTCuS_K)tgSAlv?Mqf)49iT4{RBsikHpY8Z!{cHc!@IS!kgnb7>79&h+vwh* z89~b1R-=<*ruvqfsEe-Mj7u-oOVql1pX}_L^7c7s3w(eGH^y(@*Tux?%bnQJZ@`Y( zhq?bM2mig;$H2t;pK|cu>Hq(bgRK86?dFgTw&z53(cOPMB7tg+ua8g1d36H-@R%-b zW16Zi6x4<0{W%rsG0$qOhA3O2gVQW;-FN~)*vBhO*SS)Y?c?US7d+S(>ohR;VXv0g z#^-ZmkN2*Ityf7)DxgB8+OL`%SFM4Cx-OOgw4NL@-Zy+ z<@0nLrfd1+wG0O4`|}l-Rd$B8mueZ{!2WHTK$daZkrj^gPw=h60S3h+EEv*s)N|Hf zH~xXs1q;SNjx&26SW=$?eV%_8T?9~!9w9^O82I?O;qm))vqS}mVT1UCK^Wzk zQ$4InN;+0?8*=#gt0hrY-KX}I$2+ht`!m}gQ)~-{Kk*9aSQ&)uU{=zs$o`IH3!Rb5 zu8z+Ez-{xj>1hXuLF7V-7YZ*hzj>DgHhRP1DMlwMIOZB#IIqkOkyqOfsV01vQS!2H zEC)R&XvuE?3)`cnfW zg*{Vo>;7)J!?9WfZHP%3rLjTLC>W%9`vQll);A4;b_N4LyqD;^R3(GJ z2`=JR>ZnPVQANLVgbGX5dK1cUfeGs->nddVlRO0-QY|PIvys-Q@D0W|hf~N5jm6B9 z;P#50A))62C!Q4|==J&qNh>*H0FANw_fJ=v8ADMI{*nm8VALP0-D&|?)(Z5&Z~$01 zN6U3Wfg@l8t_=81&sB%;)tU_aI>2OEZ?0gu2+}a%xo85Ui6?2H<6{v0jr9zCNOxqY z4I7sMsqP(vU=MwWhMo}oD=A01#_TB0r_U}TFEr(P9&_VvK^#2+5+0iyIcAF0hw_+$ z7-w0ng%3)k#Rg;{jZtlpp|eeF8_U2k9j)HJhpa-Bu{aTtbj3;O9=W1WL2(u4xJJvu ze~~GYnZPKSg5_Pj zqh5q<9ODEtDy9AAw-xgH!Kd^w;P=$LJ-Q~{X88)`lUW`{LMOZ z^%2yx61S9yg#DEM@Ysr3|#cP_|`j%zw=-)&HSblY5$%42n;KZDT5mFqC5v&rL?{u0LF7W67< z{A&TmBvhll?DHb555prEgx>Op<@T%=@xg0@Y7&&wx0>8oGuL*D`kmh7D!J# z7fXbpB4-d&iUT5}GH#=xQ`P7prpb6*JdQNkkus)}GqdF1XsvnZV|IdZgV_ z)oEFVLex)JRnDa{;2R_eFQ8x0YqNm2rRt^48p&Qc+wWduWaJ$#Z zc*i;{S4W!3SM(~g<`C@QO+ZU-MaFf`Z?j@M297bpR9@d=yZ9wxLqZ?M;~M@Vy%KML zCdW;F?pm~5@IDOWxq;I+jo;*{Y zdm80ZXf1&yuer2{w*iwrJN8f0#&nQ@N!+)i?SnYfrRO@DV>52eaglEJg_AL5{yfer z-?rq$ZWb5`A@e+n(pdtbKH0p)(rCWM@^QRYr1}ea%~-T-Q#U&hR$8;KYn$amOXam;KOz$$qTEkg@>ah8aKg;&mw`r2HD`4Wt{>AM! zrHo1!ud00GJw__Bu^-&6IL(p{hWN;4-8!V4WW3ad$=_Mmlt;yQhak(7p)r;1Qn<76E(hF4BqGeeMS{ywf_bMVH zE#<&0Qce7VTKLq>Xkl4-Z3m{YQAuxMP<<03Z+U*wo$($FFW#F(T@J`Q3oo=^{w0qn zdZrV)bmtWZ)u>Ko2YGB{@K0O+`)IA0Pz5) zr13^sUjbji($oy8Olj>r(<}&=2dKQSmAha?aoBN2#5QIz&P^&`IZX9DO0uSoO}eI-JL^m(e1&*Al`5-gjkl?|Epay0uOez+bb~ z##iJEHirk$x0Pl1C*ZdeF|`xY3v9@f);ocqHM&DR@_qV&?Wav#F59;Q(bx0RX?gFO z_b~CodDoBXn>y$X>>DZ!2}Wp}`h6B5Z!#M4a&+sP6zN9w-{kMVH0}S5dFlT{{<8iT z1P<%}hQJZGrDXl50L6|7wS{CpocmYK1jNz8aMlCxW~ zmfNQ!@Q&YCEfEb}lD;xghSz$!VOX*C6Uxx<%bt<^{5NxwGM9=5p=**gv;#2_iVszHPbzEuD$_4mcB-S46M#w;zY!tno_N7{oL}l3L=QkH z$8-;h!^j9h7H>v_Z6PmLp)0(G#exr=4iDV32OGwpwu^;b0THa{*MBv2g9#}F^8@Ot zG`)py@Rf~T$5pb8U*O8SSQF<^AdjGQbBT_Sn?2^!JPi@`z?f}AGMnqpet{~(%{LLp z>iaGb*?Sd|Jq@PmL*x>6x0huA%UOJme=F&(rkEaGCue>E1iP8Zmf)L*^(;g!3)e2~PDTMZ61 z5ILx^aml`k8Q|Veiwt@si6>+H`G1U^Q;=-UqOIFnZQHhO+qP|MHCEfUZQHhO+gfei z-sjvu&VJYr`=uhPV$P_DtgM(LGshTTbUf=p1Y9Q0C^0-i|K%TN;5m;p9CfyJ>6AR} z%nAJ?$s)k*$gWt!vLoG(WyHNqnHx97*t0Dn>OFl*o>v6jsA1{dX$a=$%dwEI@Sd$u z&pXVHf!t|J)kyS!@+ErCmH>Prr6_P;|49G{Y@`@j0)x?B;V-S4!|L1aFdo7ewGXJ@et@%*tFRKn+31*+F%#bHbJfsH2vNMK$VH zDE2GXF3!uj5XwMM5;SIPes@mnlw+@7Tkg=l8qo2ImbAqC+iF=2A$lCR&I9G2o*{Qs zzb8>Kz%*bInK%++Ag60l3V!_}t9>@8c1SX;f_{ipf0DNwvl0_myB4m&%^CJ1EOolH zk*C-_+B~Mu=~Ktxz3n6b$;@3djE;c$xEt)^Vx+Q4X4Gqk)KI=aKK;y}#>W{xCjsY& z=%rL{X=+kPkrX~X77jiG#NCAux!;4wn@1Eo*PYu36)Y(F9Z**g8j}l)lN8Q5#J?_I z4&B_QQ8o-kjr}f(5^Qy>Ef>%suJk5Fxf7gu7B6C44%xm`t%7#m`qPsWd9 zN9?Msk~fY19Qk3~2I6`j)sz`B0-ANcg$(e-E8++A2ndP|AicEhs@zaXZy0+7EH$C@ zoAzFdrJYXF*?fUlm5G8stsZ`DL|lvoCdbOg)oL|#>Y;)0AxXkK`qMyVHMUB!*j*$K zW+SiL;*Mgoda+#Jz|Js;Ac0Sko4g+Z>Dk+KjeD3Z^}*qoJP>r6qWLMt3re<9sBLt4 zN|4SFwPe7_jlm4?uxeW24PDWq!y$kndUu{ig3XpbQklN6Z7BCX z4pgGeQiI)%>MozVSa5`1a@c-_v>hCS$$eD6N%#{TW%fu}#b=aIWFr*|RSP5KwdqN~ zGH+w@@Yv(MiirTGe1-wp>ZP6}1QHDTx3kI1@ryhNCv0R28xA&ilT-$^Ei};bCSfv= ze3!eSI6`i@8^KZ>ZM8ChHXJZPy;?}!wSYH&rV8tNBV}T;N?xp#@UjK4wunkwFd#2P zv_gfJg5p{#xKd&uN?+*-J_5KPY$EbPg!$Rp;h%^fv)pk7^@n*aidZGMg4$0q9OCq} z%-%fug(QP2XQ4@AE#?vfwho$R~CbtMz0*pM&fQaY>+z z;S%-vDPtI^Thd{^fx%naX-0cQX}p9AYCVGJe>v!?h}p*UjK;K6_!w#7r# z>dkT`h@LVe4V7sP|I1;AX=0lwR93@6fC(GF3k@cunH@RNNShKykis)HkRC*3DJ<{q zY+{(umoZ62fF?_PP2CN$6Rln#GHqla)Deq821flK?mCf9PYHdMA|>F;2;N@rNdT+i z_!yeu;D!A|e-70A3>|yVm0~h_lL+Tp{0a!r#m{Qk0F|~Qo#eY60}N;2Bgu3Wxcg!GIUzU4*jUX6+3l`+^NE7RC1;Y8p*@|I&$6O6fU(e~v zjBL-c>Q*b=%57!-IoDjxkY-M>kIngs(tM4~l`r&Xd;a3jrA^RU+4~{iLO)O6rDutr z=EX0ZpZh<5!+)-WoVLu>JSJ+%?$dr#KSp@}mbzzI`O42?zV{wdz*m5oP_%NmXv++q zimzbfrKPQCQYWN&NQo2{n^$ioJra@(x0~Y|i1WUX)XsR5{Fu_%F^qdQ`>hqx75!*4 zaX(u&bp}upB%9r?9MY6sR-qftJ^f2_+o&NZE)AzRgGXu*lH?Mt>FDiy( zj=d8=)EK){K7GZz)nNAD550c<$ewMlhpurL22>rf5#*oo-6p?g`}v@K<7L~h7j4JO zuDeC`3w5VL`q3BY1Kzr3{+_kD1^qVJ+RkbHy`f96x}l4Pp~k=~$$qEzY5xJLxupvt zakO0QE}P#U-){()IAV|!khz>;qQ8giUJkq`W>3;UPH$!q_~0r@Ij%PyGaa#X$L&8ohHG%!FKrO)1|GmOn;!ajlIdV6n!)S2!2wrF9AAwSem zC()b$fMi?yYmK|{q<_C;>l?s5K?40hipPJ#n&{^! zeMRlmnjaHvg&3b$UWW$f*fbXa4|?bF=PVuUa^mA_u%8BvvZ1;9+Fu`^h9S+EexG6g zPNjSa688J|%f(Mr2JQ_$|A*N$GC;?N^Cew%e*4^m*Uio6hgoX}5VUf#1NYt94|u!K z@B<=Cn_hUkGsE76qEa6$3VYJ=+m z!=bC6!o^~a4Z5g~tz-j^L2jSn+qIazF_o*=WU&?B{;8ZhgAkWzA>Ae#?phl=n{2*7 z2`(6pRLXRG6>CXt`=Pa=G_aadUyGD@M7VKKT@gorT*8HUY-rU!|4I`%ELo2s zLe$4c4lkiMbP2l_aP0Ril!J6Qzpg}KknlNCu6{#+K9bN{GrE>)0NiqJiOQUgHoXV~ zkFyD%0|ZZXc8M_GZY`#$R`G&^bhe37yq8IK-q{Ky(^iw&!33d6*QStk0*dLXkr~cn z0=_YKep|#0)L)|C1D|f#r05VzBP1ZJk*x%2+hOGci}0$3jTlRP1em6ynfei~SxJq3 ztB47s=Z76y=gEs_f1h8yi1Fb4em;;vN#&&QCQIbr^C57I~_7jjQ+>^h{Ly8z`ADhEukv6b3 z%XkqXZxbXqX6y|%DlWEE=p~b5Y_|b)regiTsZO>0bC|c;x+HP8y7mQ zPYsjs!>nnS;sA~EBA`mfUPX@%58&dQ;G9`u-D7kzz)9!w%YFlqk&dOuxs+kHPMrPn ziZLQyB2YmqrOgYco$}tpFD7W+m)rN<1Oa$vlRGGMv|h6s)4qFeZX28*+%Bq97vR22 z*f7{F{2Ncd2yO}KPU0XbE;kh)kyj0fmO?3V;OKl(mz)4Jr+B}x=o36{l+t+A#u2s1 z`d8=LYr}v1#JhXJ|IweOdehWdNJ{gdA*faM)q0{*_c&d5I`Z6DwW?+}IQdoiK4VnM zOuyjsycSEF1Chi9I1Ay0BVtD34}Ji50x2KV-TpoxN9m@YPdor#Q{HtKe1_kE8);i4 z@awFCEpq+XVS*^zAy|}+t`5Bm95Qp(BoL*>sf`dM-nXxTwb#ej=nje=3~C!uih#c8 zC`K_cOdyqR)Jy^ZEQLhigu^+E{EEjym@W}k=1}5oa`WF0a{`SUhs-R_WA9aN71hlu z!7DJ@0toT8LzK5HK<#-dg6g7qmLP~C48#-Eh;$^~0n5}G>I!lmiV}T{)-lkLV$KfN zY)>$As21g~)Q)uun;Bf{h|S(=Q-)rG}@ zJjiH&a_%aRGhL}TssZa$K!Gx~tyC}G53%hc7J#R!r?(a8I|BoGEYIxsnTzZ;w&FCE ze(O94Ol-7D(`O%+rfYoswSHU_te2U898J!6u+Wrj)z}WDDRD{qKL`w&?&Z9}bz;&<``&ptW|sQQlO_>qQy9#F$z|B~vWx_8i+7DHH0|6s({xSx9%`!I zzP{0{dTXpxXuXj&O<3QN-xqkt3y*R0z`h(Mw^>-4yYy@c#Wy+hEHNYBvSjl}SslKh zBlOi0;o*)*c+w=YIp4BCYk7GFk->)CEJ6;60Sn7DJavMMS8%XVOj|IfwQYrX(y!me@a?_qttOC=Du|IE=FkZ2-%nS_2|jHJEFO+2Yqj=X4UV2+ER0Yy&Gb zP2289CCzUBmT?-;ZTlw0uFmk!uJ8qjFeMLLn+pzCWRkpH+u&@JcT;l)cPCnaN!w3B zSDfefMmlJ^x9NbYDy1Q!4vdGj3N*Fa$uRDa;VzB04^uiRnYa0Je6Vt}n42T|rP}DV z3jB&2&*Wq#E+!3Tc2}@?uRqLSS7J-+dVc&>2dKrWv-xqznc&kUw`Yh}uH_O1 zEIk|>M|ebWytDMI=(Y8@$BFm2@JrwChIEChM>Fj+jqOdc&_3 z_p_oSW_oI~EbOQ)dS&scv7MA!NXd2Sow~MKtIQid4%Iomr3H7>xnmfGyHRO1~K2?w*U<*bp5vM@WE_g@vKYj-myVZ8^CTkkze7lH6@6|pnUPu)<(E`niW zStaK{*jR0pwp7?oA2nJSXHfee1(7%9ObA6Z?6OGt%7agoG2-dTPH(n#Arhn1-c*coXmZo5; zNIBz02If$aq{&+)>P|;M^LX1C@RbAlVlR{BE&XZEcYnFak^K()S95+3u1`0wI76Q{ z9VoZnx6j){1h>S?- zz1PRRmLUSk@d;(T`~?Eb^eGig?W(*EoaHZWc+UIRwy zO#@fc?$OyZP;^GsGjn}vUNALQNj>l9@vuR7Hrhf-HN7887Cy@Q;T}8TmJ06_ ztVT!%2)YT_I)R8mdn>F+>%&FQ2g-;(NGK{b6Cq!VHj3@m`KfWZ`DBEf9re zqV>a#-hRTr?o{5t&_pSQMd${}5c2{y7UFurS5?Q>4iA)5iOj+hM|FA4%8y|NBkiVC zI=m&i>8AAOUxFpB4C?Rq<5-M&f!iu(1TFn{8jI>A!M!J1O94qOHjyRp#Fze9-Qr+e zNxIbM!u*=DcK%g0UAuw5Wf&iOKH5Qpqi+KnRuMyVzt+G(MrXRWwkr&OE>#$sg~r9E z{JuWmf!fxa01PQMGbrqBVUMh4&Bd#>5UUQc&S1E=sB`CqpjM}Dlg}#VQSV&980SQ| z5vpy9RI>@-pnrrnz+z{K$rA|;ce$4zT7Nz7hG=t#{t;{Z+sl#B6UD#Ktot1~NSwQn zd=wh%u|G~#qW*|6Kxp~E+8dDwtkDk%cm^255B)h`RYV;DbmM6eoiaN%4e?W9S z(jZ-leKH`slr71ba*cG(@vnh|_zJePd&g8_(T;zABFF-3Hu5KRLVM!kqb?@fx>n>gTsxaqz{O93Jp z?sbtP5Hbz!`f&x|O6(r^XK_(%97E^0AQJRBk5pXZ!B$X_57Dm^9njp@HwRn75!^1Y zF_Z3_ga{4Hg$`0w!q9;aV=d^zL|X(Q4SB&{ETodsGlx{~I^`o+`!;k6#EF&~LhbuX z@ES!_?_rg|&333_s2FRRwXcRnjomx*7W&!;`fq8o1Tku(Tri7kQeYeUF+5x&{U&|7 ztD1m>VX8;Phs=PMGLJ0c?cwyecewrhjzu)CBo{=r`y%U3}6FHg(R6|?Zu_;@YH zq8a%g)&pQ0dZE?SD*Q73B3ffrnAnMHOWKcQ6rmNcj$Xf;V(Ii?2J+e9L}z$+?eY3Vo|DVR&NpM z&X(D5+xt~mEjwOk$%;%M)6g_^C1t|0`**YfaznR-m8Ye#)BmguWqy=N^wDE6DMO6b0U|A zKvkIqT0sY_)!JlplSV^S-S;m$i)7M}zM;k79wweTTTQUgrB;{3b?I!$VEME`7z*Qr zKvT2@)Umd;%~kxS-%^N{^^ot2Ju}tu8Ot(g9IpelcDa_Cd0aa{ETs?~1z7vPQn{aRoi=hZvB8LYCUAwvncOseSlVmu9}sa7V1xF_WUmWIIyh) zfS|DIR6jqo z?d|ozm9|i2v(DM3{z;KvC{8=*+pHBFb{Hq;(DbGYIz>?(O-?jL5fqg;S>0TdHgs&0 zeWOF64t$exI4gGttR`}kF`Ic7S+p#N`Q7yiVq-9UVhx3lSnIl7S*e6KZ>JK@{oFTl zZi`C*Xc3WPKVK6h3TNu6k8wFs{6<-RkexvQYg&!((zi2o>Kv|Di_SS8Rw_eMh16ML zltSqSC*9ss3>6^Np@jm)&@FG8bcfHXo9wV{!An)aySM5bYV=EPNRo&=*W60Qn zddUwryAv(Ida8t5{c~7gQLQKO5qA{72eAScA{MM=7{3(bG?O-^Hu19Ih^jn z)uqA!c}cj19vBfshga+%?VpB!R^UgoFdQ^${qq0L^V9fphab+lkKd8~1_zQfh5nCn z?H|7*BNIEr|83>5{|DL;`+r3{(v+|}U`771LB44B(z3-N{Wc>RtC*Ynl*KGG7t z_1uHo-O1|=)Xo_;v$EsH*VCGX+_A#fgHv_={I*)Ei!-G}7gK!ke1BTH#Fyc-gKHy{ zqw>9RK?gTe1E&Z6OMDA=-5azkAzl?8%5+i84qt{Oo zvGG>B5eU}(vS^CX2+?TI5|^L7J$XOqvk*oXg#+ZS1n~17N`PlQ8^F{ZlI>)K; zA^9QuFaN{u(U0|@?710FkTQ~w*+xdE%!r7BqzfOX5eP3OO)%p>tDw$BC{X$q4YGG# zP~oxhB>=-?w~RjK_L7al=A?mQJ9F43@Y{ANJqQSsnP0^5kn8^`(~ z5;s-ZT2biPYcyv5p6y!D*9vTExk##_a6K;kB|IUjF6o-W5|9}p&EkvVP2_~4oXD`GiBL8O?-d@C`E#WV#*D~CFmVkyB{*@j!*gYeM*K9ZV0cLTK&5cyl(v2*BLo~8C^Cs4Hqh#V zAR7ot0KYDOtL(enszb43s2SiqjUBs2`gc)kHcB{Hkt)?%!?ow%I77RSqO;JVp>Jq# zoE3Rc5b*|sf|x?-FXa`S;aH9m;4a9bp1PocKd*PYQ!GRe1yjji;D12i?(rQ=G|=8W+WZx^_wl1Y;A6*Il1eL-=p|pi__Ht72JCGG-Uhs^BzA;D z$iZX(mdl-V1V2KG*vgotPNkQ2ewFa41FbY%vvbZz>jFbRt*B3(+si181A(C?+KvhY?2Z_L%cuID*dQE%y zij-ok{A+=B?Ij&+cW}f0yf33)$xhpz$QA>~^|BT31z@wam5#VCc?JaS(rBz$w!{t_$|+$5=F@i-Nt<*~N6B&VOF2&C{&Y}fRpHjFC!a`G0vCEd|R4SgbmTZ@~E zXA*1nJa$G6lOCqE91vWjSY69xd*kUM!iX*2vuObngYjFkqzF(-EYur|cLh{wBgq!7 zno?+-s!xv*11AQwyFDX)6(hBt^{$`ek8F5Uy?tu#k43{klRu6+Ytlx}JAs&jWw7li)Ks$ z)yiOuBh~YYBFjiA(RmrV-`@?)XRZqdkf$3GO`5}{j*xUSTW8t)>SE2^>AM9pc*}ZIX5V(WSH0h|VgQxiOE!Z$XujMc9>g7KpSK9^x5QI#?rsXN zmvq?tURXo%jGyN{`P*t*&*l(1;-2cXM0SOH=_NR`_GGI76Oh+s^FY+d5VP?B4Z=pM2Yn)B;-k722ElWCI}qLF z712rXP$aCjwzv#8e72EMtv{9v(G|r%wNIl{5u;NK>B+lhmsg`Q1?#aRHDb1=5!zv! zl~wjij!F@J>nw++GMkw@Z`Oy$>N_Nk3!`@^*CoVkM-OmPw&$|Jldf!zObG@gZ5+6F zYhyB5J~R(?qcS?L7&D@_+o79_s==9^(R!m`)`zC>&r^rRtXCd~rmXrzY;%6=!QS2T zeipqy7lv&vj%WUSGw`*j?Xt1BN0FqhWnJ)QrA%k=rm~J3Mw>*MM3!n?#-oU>h%K0e z+0<-!)TXzaBU8gqsT5mK)0rj$B!0T%F7Nv*@Y&kEI7V9w>&UuYv}*4=fUzNofr0K}3*9{kNDN8H2_Q#}Eu9dH~w z?Ykor;`g7F(f`Pu|8dAMGW}a2Ap1Wt;(y!7V*fAUBR|Rr{{Jf@JwlRR z_*nKIWdsWJxAwFOE;j^dOX}OljNKcWL^1w=eatWlv=fTPF_>wGdz20VyzTwwdMC^8 zU*ZUB@p=Q#?O)=EEHZqnrRN$~_ZkeahLZt%@%rd_Yi7oj?8soX>*Mv2{Ic~XW<2_y z9ELYs%snvYnH72ziFe>u*TVa=B}MN#TlczK+F1Nb|1~(a1Oc@hucH7&;I@=MICrTD zxt1}q4^_UtR{`c8MH-3tJ#bxuZ*gz(#DPu$4bVt&AHORo2hN9_VrzC;Yp}nB$b^Ml zs{DK|-?Fd>Z6WHI{N16qY46PE2hjrrrtd5lo?5`WN7ilF4>1}1xGS&6^))WWXi2@H}Y^OmjeJ`zdn46b1n&{g3>W z_2(Rvy%sd1EgALtts#isigCqa%alW1w+2F^{GWHpVh`d?-{E@*w854AfTG`}xk8&V z0mN;bO#Rwl{>b4lD4VcJKpQxCdvF*)^q@#5Bcjz;#qLO%p5$7u_ds%$5TiEB{W3)4 zV5#GTR?)9CSXx(yL5x52%fpLOBql~evXg8!W?LmP$%YTTS17=6o3VAfVpx-Y!gga6I8jW3z_z62x*qot&lsZ zI$0D@j6k2IrGk3B6GeifQEwt z(P3btvHIwgR_l>kG6uCJs;5z2PVu|nPy;OK>CA(?eJOeX5* z|4u-hCeg^=1IdlZN9HoDck6J$l&!GhSkDFBdwQKf)u_YaPay%|SQTk;bxR#o;UEZ> z{}Zvhy5e=-=3xV=lzen0ZK+_s9`lj($NX;T$e`hNy>^H>Vz2N7@o$&mmCX-RGmC*4 zkb1dKNXzpMk)12hlQ=gFAac0kXzswnhhyvUcubNW?HF~6xV};XJ^1i&Mp7k`DR4XW zp;Jm#6>h4;C8m%K!#nG2PMa--h}9qrd(Et)4JkT;{yVZ%Hr#GQLCGuD3*b&{#MjJB z$__%jy<5#%XVzg`DAY5E4_eiGF-~I-p3lCjUu1|8Vm@mRY^9euq6dc521@k15x`yG z{s482s;_B=7i7h1sXdpkt8pv#c#jK6PFL0_m_A4aa>KyoM&was2D9Q-c*hcUH9F7) zngDu{Ez}gb1Z<4PxyUg%ME8Bqyg^L7X{O4fvUzt=VXte~V0g&&2*~q>0CkW-E%MB5 z#7P&JVlsZVc617wLdxXA46*2wa?@>B;7L!1%r&jV?`|b7uI+xB8 zJ8kuM*`{kSn!|^Ub1)wLm$xmhS^Dv&<(>TZ1Ks$PNzeF3@8dGnLT2^ufWccTVdJ05 z%~X*hq$mArRfF|_NAOOMqQJ+HY7DtrjJx-$ff29v2dejhYgu3L?OPgaGtX=Z4O8cH z#YvMg;9+^?6T<=WR(rb4tZj~#_btT5YH0HO@DEz#xxuk;`F_Sss-uLeJLI`+C4Q+Y zd}N@?F7ILr{7xpSv|KV|2J0*o_@sNHfLr9b(tuO`b-^k;o8-Azpo`tUhhXNqv6SX+ z$Ksj++3CgZHZP!p4!T9uDtubHe}czsW;CN%E|3%Ffq)fMpekj~ekb{bA1x!P29KMS zqq-W^&3-YO*q+oU7Qaj^hoc#sIqPYw(A~)y>x%NnHH3$1TC{{)H8#9eshQ~EDJR-% zy(FLKnwe?~wNz@4>Wtf-^$q{^;c<oZFt(*N<~~}TK)a|7PS(7t~+T}CXgjIQ47hY`wM0@VnBo36p0t3rpVeC zcWIK;o4rP5$>adRJZ`0&rZZ?oQM4y}iPOfg$&xS;Yv~<9W2#<`RNfT!5i8DxAa1Dg zjU%kGe1k81G@Yu!F{J2YXoV$=`e&$(w?ZqWjsIt;32d2{V*NF>#N$ZfW^3D zylbNfIr&ms`f{b9HZ@jFQN7$_Sw$ztuR@$0l`Zm&{oA`G1`VG^^#I|^hPd)}<s(kOn7w5pYE zcqc*XROX5=Np{GscjX&M{Z(n)M_!~PwjieovC5FiLgwoRUOUnEZ1T*vZ7W^%A9dM3 zE;B|ZmVe`Ov;ULl{dZmVUx7NbrR@F*?)sH4X|c-F&z=#7biu&u!v%Cr0jCZCFr|FH zOND#NCmVNAZe?X}<@yT_nP?&7;qk@0MnrIbp6tye`1#6~C*&-h)#%}VJr113xGQIV zyueQD&z!bcUA<=>+K%c8^=cq4o?w z+QwZ|9uboH1iNb-SG;thx2_K?*@MWY-3_KqCp_f;R5{Xo`+S}ZJX{RKQ1vAyriA?} zZqR>ld?E+ll%<9OQE2QZi$#fcM?SC2_l~(G2+)6tnr1NIdo_!NFJgBVq$tOU+Z5m|5`cfn z#o7&XRDdGsCnCjmh^Skl#N>~4fgyfO7nlX$%b(en`@>i*j9 z>g8Zh(vjErl|q`(i-$xjTh4O;E3Qk@@A~KIPt+gQe%jfga7kV|N?cgHzR){VSfBDM z-)$E^`|hvKL{QjKD|zkt_wH6jQV%TyJ~}hErG;n=QZEO#v^?$DDgF#NA3}P^(;Ixs zGU^V|cZbj6xOgh+h zsS{hO*^7ua3IC%%HTnEKMZH&5>}j{RyQ<@$9#ocsBW(C~{7L4yVSPCexH(VwLn`Kp z(Le;j1JW;2`7!+3a%ekAdBR$Xe$=-3+4v&-yL}P`SYE)W=UeJjtp&Kc>_)r}>!g{C z_BcLbaoE*itdIZ*_i55TsIc;#`v^sBt~5HbvB$$P`T zI`3Mmo=04{V{Mni869T#3kp{OZAGL}6gkSRhO+|Sp}T2e@fsM;(^&X@l1^4hREevZ zd6SA7daPka_Niz=;Z{$sTg2CdV_TcdA*lJ}qyo>l6XO|m#I)pd@5ft-Nzor*-a8ns zWm^>1os2#QcAQ32UA<&ysR&srZ8LLNnS^I8l#T%westktE{$wjKkyc2D*ryjB-2I8 zS}?m{kYXa_O(fCQ~Y-Bfe8ZYewu@;9#s2IZ@{}?62Ydz~rOp=lnbmnMaTMsrtv#*3lgK z!*N0T=A+_Te@k^bA#M^$RY{5au*LeJ9ae4b<--fPYgy5Cd2G#C?Aihhfil8z`3~Wj zjNs1kM_#wu-a8S7h#Tesp^2|ji30EF3H*sl*z$KLJiFI<$mmEAHwxs66KDI%xPHVX z!=2>>wGETt6QlN|27lYOAqXjG`}Xk9{KIr`f5qnT#+TY?)P9Ey=pb^5w~H1`WQ1lP zrL7Nl2g#yw&XV4Sr1%3^NG&lX`ev+pF*SKd?>EBYhf;49>;NxHSC?8nJM4uZf z3k1C|AeDvdq@IKx=q}taCr69al{q+$If%bJ$(y!BvlLSwNL^N8*p^KmuKb4+bA|Xzw$WBwFGIs^smF?b>&$~e)+i;3Y-%m;gO?sq=ZQ-HPZa-l6l!vv z5LPV(02wg3WhYoLxnO!idMoXh`K|eFn9Qc5c5or$ZCIRS@ihux61HOGkZ0w|qVbf= zO5(3r^Uh)s1IZB@PzLXAY*8gJOAw!+#d>AJ0>zU}f1VI!)g$YkVosEXGVi9uK!(%` z5KDBW&>^A8oS$lDx2_8;%LTVRD1b6ByB$qgDMfc>JK7{AkMtKnE0vUUBtI$)m363? z+gsV%REd(+&+cG!>Dm~A;TBv&bUIrs!`ffG!RQj3Y;X*bS%~a7%tCFuMxp*t%-78X zU>&&@XVYaI!U<&FH=JqXJFV;B@Cj!OY}|WWVZ*bMtGps@w!rJQE(p-E4F=Z zO-QT;YVT$hcF$wnS>M~M_MZj&*fIsX_-PJ~#Rh~psl4aPv9;k9K)PlC6 zV3e%*9qyYr4Dy-ra5+xm##H*Eyrj zT;1&LMo2`{qfiWsvfSSDgdwW~KRg?B?J~*I1}Wmj6G^UlbS20A3H5y$Nv_B?%l)bF zOG}P>1Lg{5w$ZZV;QJj(t_*c13I;?o{)1Rtg0An((({`7kA@mIa`npOVHc8rUb>^e%P1!KybF9toC z{cex$^2Sb^?s3|e)S7&tqs-Z_T%ZZi8(zJupXsf-mRa*;>uuakSppgE&-|wB(QX+a zA!w=uaig9+*TH}_piF}A`+N-{ZW*QsA`eCrA`?*&eaA6yL#cd=*=3ZuC2k%P_@WO> z(Zs4`^?*9Jd-m<=Zs|@ioV_7uQ=XQ@AH-c(QtU|4yG~v1Quh6rC)b{KBSI0WRRb6=ILnhErmhi-xB1CPXuY~AM{hH4ivvuS_W%r|B zR&{2hBfS~4jbjKtT1Pfxr)}BJvb)E;xa@`>nlRJ3mF~H77 zOyX3`)`*I2$)r~YK^DbZMWsl8AjWD=|KuvyHsnCvlae48V)DQE5&2WcC3x?;TxhOvQ?Thfvtf0MVkO>hLfuKwC7(#-oMP_JW% zr$v=$y?ukaqF{B2Cu}qF=J2sRs80(|xz(bf;r5!UbVI0jzz(w})fuc%`2{P@E}PwT z$*+`HwjFzl7~KtfT)GV> zrh+iR+HP%Y8x0THBU>DkOD{cMwNtEPt4Z3CV~w)IACSrHH7>z0_74@k?ZifHNf851 zojhARpvqc0sx%;eaxXJ7lr6J@ub1e2*$TW8UFcGev^Jw&=E@}o4F4Uo=JuY)zrYn@Oa8oJKdj0XP+Aj za#2WWB6^p-5&Fq?-7=IP*L7`AW3wHBRv6cV$g3$%7%3MV6g`}shO4j)3ml4J2$k_i~ zZ#>OQEUr&u1~qPdY)_+BSImeBBgFtj<94FD>hra@uDREvI5dvSx!<7-Fz6Mv%6>S~ zX1d+mpO|@3kMu=PB=Mu1ILcIbHBP8F!zGb-*iaU?N?#%|h&XE;w~N$)E)HAE+9%Y5 zt)`o6wBV3{pi~rSPSfLb(*S2>zn3og6T>VzkVLvBDPFRVs)B8@LehbH6_78bumqnp13PChLgn5pjVjUoz?+MlIQ5z#+O*ACp5@p@>_+Rg6a=oi0Z2_`5vZA zKfjwLb1O%yQDiXh2^m{&8h5HwJ)v_$Z6z!PFWD}z?o)hM0VvNY8wU&CFqJ_C$cZp` z^10@n0rD|>yX0Dih_D2p8@@1OWJyu;V{2-F%wdR0z~2IG@)8je3Y0E?Z2VN}@ZU&^ zyi~xsbb%7l@NYTVlAMC>C=CHcrz<+QaDH9)x1T7yl3@*HA~HB5)VPM#519p##Vfd? zQ~E&Va%Y*7Glzba#3>bPJ89sI74|v}lP$H?L{j?1X`v$|V9qM8Zya8S^8B*HZX99< z1#PLhk<|TG-YVhhpsnhB%>04$VUEz+3}(9~8QjS!O1w&csSM5yM>L}?Sh5Z_1(56R zMR0&8iXL=Dpa7JzoNzphP6;^W7ccHw_s$=x6yb_zF{GXSFj8{^)=kSAK{-6?Dx|bt zI)IUuJQa+hl$&5=^2^FVOSyR-EDgZGIPNXV#8Tq|59WNq z2_6VaQ-jrAr32GVvz#ia8O61$?)2PyOs|*)3;}z{S$$oVMv15Q2AY`o`E*d!I zoQ9WHc}dCvhdApb{>rrgl&>PxLg#285uT@+^Cz8B+_Em`k4#qt)!!%Hl(lIA7UR6{ zTs2?LW(&|2i(X;G@gfFtk`yJB&Z=(>M>E-OFLf)<2=ARU74XC!m>Ib*3Nj^+2g$#a zG<+nfx%T%sPzkARv>k6Nri~44Ms`mX!t2{mDOajYKcNgea~Z`p*FCrU;fXn5+*CGI z3Np79Q4FEyO_Fy1>`fVf!HkNj>L%sy10$QEN8ye;CctCNOud3>xgm0`>p)OpMAK>n zW#aoHe-A4HB9f>tVV~nxd}4q7LQ@pJu>z;)uQUW|?WX#WJ7v9?NqXCCNMV7mtY3~Q z&87DCXp1ffIl_P!xR}yv0Bqy3jgdku$gAKlC4|>0V0Y(nrfs%X3@7P=hw`n4LNxgB zX$irCJmCAAcB3rl7OD+?X?{a1_GR)L&S$(k*`0P@E7Cl6L_yQI%#`2k_Hfgf_b)f9 z;mxW^v8lqc57?oLy(P zzAgJEdnO1q{gH&xVRVDhh@_~TJguRZbN1jjB?dcBNz_wAI5#1vde`XJ0!`rG9#cG5 zxNn)wBaqI20H&sQ=(#Q@`&z8o<8tIzxsqsU!>z+u^@#$}zj&(Z}_- z>9^g}uB@J*6=<#VuB{9&7{SvOw79Os{C6}i3tbST$z|6wGTlWSlKenX#kQwv_j&Y^78*%GUx+dSo9R|M^`{xC0|KBL@}eLDqJxhq9$3LIuu)t(I{ilC zl_dU_(OU|LL^j)E!Kirz8)qpv5;QSbE3nGW%k+d9v&T`gA1X1d{84qy2L)Y{n9^J1 z9lVzREy2c{VCw0-UNn8zAkm2~%P5C5W}v#}bSr!t+5$4GeU?>wDG$4sy0AECTCLW7 zw*UVB7<;EEOS)}qG;LPewryA1R%KS&wr#7@wr$(CZQHn6-@f~t-P*q&&P%j50)1k| zT5H6NK6;3eJCh|m02^C^*Nc`nBj0Ld?v%(JEzBGunVH)=?>F^N=Q|4eXZG#f0QN%T0*JLrs^zcfRIE5uT!t zqOuVic|{g;yw>C64;(Qq0V%dYx1sGzX8TpseIXIAVy(|9uo;-iKYrJ0nzV<85E~56 z!;9ue_g%7iPS7)~=FdcgcVTIi{{#9ob^bi+I5LWO;a9vlz#On|OtoEeW}nLbMpJE# z@MGgQfAA72n9q#>s!k4*VfCS24U$OUC497CDANOmh5?dB*RmSP{aYSPDw32Sj=3^* zxgch z>*<_@u?$UgymWEFlJR@+6C<%E5855SV`Fg@_=Mj%RB86*PuLE1KeV}dnezMR#Gnn1 z^V-78uaL`ns*Y(Evx!cq9jpSRop0X0up! zc@b|P4_IGM_!myhU#+mp`gnVqJ&t~6-B#MP-A#$AKBzQRHY!R|p0G=m;{)$9c?|UuzpTfrmv}#DMGJ+XH#@mL@>n-dgfKBf{8>$LgJSQKPzu0Lbje23* zvn=jObU)AqEV=;UB8MM6?U79Hd!t^`vsb{vRn*xu2-}(nZN#kaW*dkanwWYE`F5db zn-V9f-pMvbxbP~5q=x&|Q~hoP6P_>q%oRz`iF3`~zjN=qyl{gHdz(^XHm~tT zYUXv{NTOM4N}P27xTw1&D0rY}TNHR4Nc287HUOT;-9zEdt_+5_AlL660#nm#&Cbhj z*uE)jC>8Ye&QS|l#lUw;@;EgIc}8bR`z~Pij?WS$7WqBzVz9curZPXg<1mH7L-puM z`8$HkUa^9~QTSZtx;{XGSO7>?!;RL+PnCw?Iya!;5DU$;V1olU=mIY}&-L}_7T(rk z{mtSPo!;mm=3`!by{UAoE|j3JsVmC*8xQEUUwfX+cuATI_%_c7U$eae8_eD$*Iq;RCAM0P9Ly zidMpVkT6u3hWshW_Ai=wkAvE)=kB)Vcnd2ymJ3&a1{{0Feq@%X-GX{hHDI+zWMx|_VY7tMpZ{Q{o&B=9Y9ZY+9K!8m(tGEbS_FV& zdAL9j=gA~OVeqQ`$;fN*qe3_EvUL-zB0EK~l1&l-j4J0rLDiaK8@{my4RV?!Wmi<88Gk(_|vN%_J?OV=|4r?aaDfPyeldKzSAx_mtpuwUWoA{b ze>Q^WDBpo?3{=R}v6jneKu*GprO-qnfNai-KxDkZjrO?cin~0DZ&tO)!8_|b6(x5m zTk2~5du*M$JbtFXsCJ#aE88$``)@c@lCsfpSk5l-1&(0^W@y|M;Ts1C3tSlrs_KN_ z>5LSK+0&Y8Cbk*yAb66J3+ePKyMXpOd@?3<@_f9^zV5<;0U&B&bob;iOqJllxr$o$qMX3f7N@I2I7&x-jj%)Y+K5cOylnC z34Hp|2);2_e|bs2r{uLa3j}KIssgqZKN&jZxC?uk8+q0&OrKAr5hw*|j>|zvSWzlB zD{bhmg_fVg>dxFnvBXTBE}zjo|5Cp0x+U+TZtCli=-0KA6^}|e&Y$2v*+*{ZrsDA4 z6qG8`tDY4M%vK|h!eMQUP-c)hIRUE-Kc+(`48Ry^bc(2+mUZUggUDCRgu4ZTC?Ux1 zUiaOSW8$7G>aGvFdL&e8r19|YRW>td6S7@wYtThE>hsTfZ|z{Z(eC1W+O5)Dg6S8}B~ z_duiyF6jiR4}n@H5NtH zX%OID!>u2*%$z&D-L~+A+z41*+(yT&ut6@v3 zDgW36r_5gB1l|+!-jG6Ou?IAWw{gmI`j_JE1WjUk2qK+?Ki+{{s)-mQA?Xq}Njqft zjRk!#zgY=*9*C!|X%@uRJ2`>rQ!tOV!s*Ycl)`J|zuEx$&!7Xb*?aPsnpS&V$>Co4oaf(8B_ z55LI4o0x5UAXLwqUxd97h+hPa%92mS>}?W%M3FLrzPY__dIii7~rt@2-% zBW%iBsnLTSb_l$sWM*dD!v4bnFyyWYBA7-!`r=15A^hcnjNpl*BlQO3^Fpb*nWP3d z(#gOfh3pHKOzxP#Oq61M+$KySw~kO8ZZHi}dp~2Ps^z3GQ*5205_$^(w;vF+?S`Qd zwHZ=^g_qu(avghh?1kw&3!KVVuJx?+@-qo#2oCABz;u^&EFl*bO2r>PdfWzDqy-#y zl9XD8Cv#e2a?He&rhkn{FI0GnF{_3+haW;wDL%L|F(+MD|Cp$t&<38UC>%(L)gafu zWS~~rQ#{Zo{R0)Yeu!%_B2)N=tJ^=m2u8Sx^%MD^wx84DC$rUo1^(`mUr4Tg$#4a; z5WzBkzq?OJ?s|`!Y0h9lWGHX5Bk&GbEZJ*9i9|RnSCT!1orYfW5x&uCCb?&U0;5&cGD^FRAz@WmQhi0A%o26ID)g z*Cc*^+6#Cfpj2mQAiK?i(;Fjv{2g5q2sK3uRn9A$f;!#e736ISwFS_wKIn|No~+Oa z%q`IjkF_$p~l%5!15&q^SIhBrI|L!s$sW0+745|DdMyx%64X$i4IJ z=`st)-#aKg!%^?)BD(Fj_v#1ERqaL--xY4=6+2c=#Q_X&miN|&$37RF>hCV>=7-bn z^d|7f5%~A+%ytg?ix%$d8T-hk>24P*xO8{kMVjTAHemOAC^yYxSm*4}z98EAy-8>% z1liA~qu-ajJX@ZbfJo_ALzv0q-RXGLdOkbJXaGM0FfIY9)@vZl5D>S3J#2u2RC6M8 zANGfQ5N4?8EHEWYOA+zrVBo!cs-Bwn-4xIPs5<-ftfcviDjO#CrKxWqT#+`sLrUM z5&F|>|95lkHaU9(46VBY6GrbXzWC!NcNjB{ugxxdt1M5+W76U*7S6dAa z2!v*Y#8Mlq%+Xfw{f8ea7JkOwW&Yz2m;f**KXFAzK-olE)tTb$(?cz6Z(4`FgAn=?^jbWTa2raiwe#5cYwIi1L}z z16+Vz&@&uk?#oDwUIE%g(ui|LV%9mve!2U)Dex{l)sf*OLWw8r*2}$x#Hq_bR@{EN zh2#Ar3n(j6tn!+!>1=Lf776zJYnI=9kTHWFK#^;Sk|F6r*W9|CxmpN9I+*%GmEJNa zL}*WHP=qSNGufrP#3*{KoN-B~w1I~a$DFu(E4nB?*Cglt;xUEbm6h-}64$Lkk_}pn zW<`tGE)g}6o{$TrsZ5r-72zU}HN<^#L9KuumeWvVnB7~pA=cS4 z6au4y+?Y!Wr$mLg$7&p?xr0)dg6aspuYLDp-T4aI%!k^|;(p-esX{AH8}Okth0<0) z@$@cBGD(4{Dpyx1tA(>zWMirn49V&8JP-+(fyGvXSQhlgiO@JnGMp0vX{c~wSH=se zGuNoChtSIZ^z!Am>8LXn2S=Q=DI1_729P;aPoZX5eqoIT8h%MoR1kJ5-5^Dz_2Y8=sXfg z<~lTwu3+E`>>kTP`}nL-D^_D#fCnqiKPr5itk^NeqQtRz5M!}CG7%8|D^1wHEoS2? z4Ly&Nei(z6O1vds{VpDv!q9`-vKq)~4y>vI*6ea}4y+80&62*yvw^iZMLN_f@B6Eo z#_9rVDaYZN$*Sh4Ru*`caN|ev#N2~~QU(xWhq#L>EvNoSC@ohjow|K{y)+ME__U3^ zSoI=})Nbl$Z0={dUVcm?(c00OPRib(xpd6&SSrY(E}<)*3s(h!f*LIWX+ID^ktk_p znNyrL*dn}lj?2R1|K9cLw}>hWHgU8 zdY3u<8Yf41lD}bix6LD8Nqv&&^sryFoCfXf8pam)v3gTQ^tw?M>P1rx8~1zdWRHR` z3E}{t9-KGPRc%hhMwpSOGz3g`B;byeME@}~wKFNYRcvj>KQPN-$+%eKaKvOnyi zeZv#h3cvl{%t~Yv(S%qzbx&aPRZpyAQY%Rw78E-&=FyB=66VQTq(}7fzJHdS<6dRv zO9W0e{hEbOk!1L<(8N65;^&tzKI8FD8nAp}(9L+g5EtN4_$JXv_&itPR0IvyiM!JF zoiq2B1}DPi31Pa#z1T*sX5)TishHaq|I#~T`}5A)_0Hx^Wi9v6=`$x@y4;+Jefv=F zLu(AA^INl2hPP5=CGeoTvbM%;vnz&{eE+>k4{Ztb4w-Hq^bC2;Q}#DHY|g3-N~B`e z09t8P(0+U@rr`$Q>0oNC{bENAT<<; z;r9AZ(ngL(FN{Bb}mrR4;<$RlY zAWBfAhVI%PO?~e`mqX2-k&)D{ZVdHxEh>Wjy>K4thmG7^ahAL|X2E`yxERU>?{nImneRZo5B7^S+EBx3K-!-U?U^^6xp z3u|9%Xu}e!dCMWifaP3HDI8l5>-SBpGd8yN18bxDesNN|+LNm%5jyQhj|lu9xU09e z3q{f3>$VG$V)G&JAZt=JmM`%D135|3I*-i{@M@j%s{fj<{F_H>Db( zjt3))#a^m2X*{9L)MXln6!cE*R>*}?l> zpDbhs-v>|n!rI3kUDqLz4ADuMEHr(rAPGp+#}xdVn7iqqz{O8>853k0u=A}9LSmch zLQnt4Z!t6Do!FKzV~Z%Q8&6a(e3pv{e_6c1MSKTj^(nZ5klD_f;fBaq!R!e zr($5r#g)};t|A-*iQ>78Y2vcE?|_GqiZXRhEf|kVgyAxyvPoR>j`lq)3Ref3AaEjb>ApYzGmbBiJ%CQx$Mm!DjdlIruS2dU z-We)$45+k;AC&cGoL?O<9i~Yz>%?n_n0@;mY`eZ>8E==Sii#OpGQRF(p_BR1G_$q} zXT5$rd|5;jo6IfNly&1S2DQ&X!48HK{P={S9-Q;2R2UFKD==h*|KkZwCOFK7455X z5#FC_E@e2a#-;lOQdXpcqaZYjp_2A8gXR(P6Y{-J&qLO>@Rbjifc+(`qe0q{=uT-I z#YquX$CM=K9oNvkx*l_-=SQM(3d2&rHY3XK3zDjabLG|c?r~>5{t$HX>23MQK~`jT zAs{)is(9s}7V?rty>VEymem>ve)-~BN;%SuY?v3QCH;a(ky+?HQ~QI^s_ZtZLwS4P zt(#Ha2=yYJma}MWexW=F7%4>6eBuK5c3V0NaM|TmUO?`5U?laZs^_4cL{=xn4fJ(` zgG37E)LD5ze@Zwwo1_-&)pfFie$DyRgkGe8P*nDsY0ssxJZn zpo&e{qW9*8>*D&{FpIthpYLjVaT?7)C4cslQD7Ama=0UFMN-)M@|M!idSb~Oo(osW zB(@ubvR8nk|KK~1k0=DJ88NCQeiSr=h6TGdEkYQjx;2$@zi-ZSF59>T%C#QLq}HJ= zaPAdvvkJSgJrk-wtJ|sJe4E6+p=!VL09+%-we1s;FzIzr*PLB0MvB?4)2G%>!)%k* zZYh}|+^41(aia2AFq9C&0stvABegkUGbx5Rmrw#{`V{XDTK=+NI`D_| z+onShb5067cAS~}M)*4FksRHY*~@h*EZP-L2g^$$WzotyWH_t|l#FgUQop*FWR{VR zc>RoDq!&Vdq9i6uuG{=zT9%->4#%|)QjLHC@8xNrM(ZP!mRc; zVqWbn$&&y=i3p!6R)=kNe$Q*oEO`|cHIdZxgQ4TK@-Pxl!~DpKPWVawQHg{dvy|OD zVCLK}41{}d5x7wzPs+mYba|y9bRjpgBqE)QcradOgzp~FMwjMZp5J?UK)8qtp9S|Jq#}=kgg>YO@lOWD!q3ErgdZ=CeuU@Ph)A)8pyrLS zrTK8Xp{)Q-xtV6PerN@z2tQhux+Hewp_0%1t3`PbLwbfY7nE?SVO{ zPN!2Fk>GHxR^m)JWMd?W%*{h^0;9l26&((FhOs)NiWT3I?_w9tN|N=H3Pk9o{}7R9r`F*vLr@Ea=)llhJYfuceuxxV(#%4H6w7l1ig?A|u&r zWIqaYM$AZ4+M6kN5OguuZQzr60w}iZU01SB`hn-iXPeU`kD{#~0miFlWCnm|IxD#giOtUTC6qd)cJu+E?(@{ImTH#Obm2UVNmeSnY{zd;jpO~i>7ZW7?1(qUKCdnp0(YDd!0^Amr z?lQn-4LmJrP*3Ag@5$9dn;i->rubF8wn_NcD3VS!@!HwU!q&$nRv`k9*>nIY4>&a&lTrM>zBgev^kBa_J1zrMaP!naXzoVR-{^$#o;ch0cM!{09L@ed5((7+euxX$Ip!CW1wFxi!q6&reIE6>go^R4~w{s?7* zo^j=KI5k{K*IR!WHMXKNzK+kOA0GS{qM-0?r_xWr z)Fl;-!YF(hpYT>zrT&-$a~|{Xg8indtvt|C(>A=l|hV<$|Vk^nD|2=Ty}- zN4J!)=W2I%_vN{a@1_Fvv{0;OD(b)+stN7O8=|m8ASXwqfve8T6^%{CGao%OxlDB`=1a2ctzJGX~%iB)h7X-y|&vMe`72fRVlQc-a_% z+jG*P7w#-2&PYyfX@R z&oC+wH1rx@$f2nkI3mca%y#WPvl)Ju<}y`A9d;0eg!oH|+q&WTa8;g{?fsbWuPmt=U6qtMQNg)^=uR zSJ`Nb%}{sNsHq1%k9Q-I8=T^gu}6owi}P$cGkU~?&d>8Ymg8zBs!AE+&qE!g7Epy$tFA60d%YPD2K){}e z!f%p&u57}Q`?5UKf|Ydd!!~ARcv!0HhV+UT{jniXD_jjsW)RInCIcy`@k<;q>v77y z$he?yvc|Y%Nd3MA(F@h{dcu%Jy86_Bvua*EKI25s7`RZ#1hhIe2fb-9(i9k|fFVan z-t!hymnHiwS-4d@>l{whJ-r-_Py|&XHMoLEDOrueL$>nfc!fo4SV_x3$XsVl?EZ9i zK}RNsQbS6;mc?Mne1@3xD{rPFq}$Y(06mW&kReCk1| z4WdsKk!A_}Sf~Kr!wr%>4%ecb>N9(o>|4ck=>lOvky*^}T-C8*2N+f)?Th zQ(2mxdGOUOq0Bd-mQm7hTltV~Ncg)@Xu)&-LI+bQ4lcm$hSM|yrTGDNH6CqQ z?T$sAx8^V_g2mjZJ>6G4ZkX+@d7;p1rVa%_BlydR#S_aC&9K9ax8Nx zAAxd_KCm!13Awg><_NPU>uGi|aIm@PcV<39$BtQPu2x|w>qY*sU{IOds!1~CWDFRv z{Lh~at6XUbA%@9jn6!GrIGj!3mMynAzTgTVpy6jG@y&}K(7{bsxB2d6sm#{%`WRE1 z<^i23=b;3oUV{Czl=gOf<9waNi_$4Ri>(ZqR3T!J)!|Wi0Pa-tN&)WL#iqh-dMiLz zvm#qnv=y}z3kU6;?=*l_5K90q?%g%Ql0(&~zK3qL!qU}0+?+^&U%k#5I;^F@kjKZC zWlc<}aEc+DGT;)L5m9yfRC7g&L17K1LaN->A4vnaCV*?%MQ+$46piJ*)Bj&^6J*zLFJmFN69P!_(BQ*sKA~5V|+i z)CfunK1J4-vhQDvZYd0_um*`qwMmT@-bcOpRBR#0SeM}_od@N}ID=X1CErzGnW$_X zJE=Z{EY!JWh-}bDz&asZ!?(oPWZS0{u*TUa`}UmsbE)*3CGLRWQ==JDIDqY&ImEF$) zjT|q&saewXb+_ep40(782{t_Bg#e~Z!s(gBHd>(T6~m+-jkM$uCqw!z3b$$k*}Bc4 z;+nyo@K!`8(=aN+%^$+P&BT8cq&p4vR4$`7tZo;8Pec-{P?&?{r{S%THh@}{^%nx( zCIBk_lwSlxPOlBpL%0nE$)r0{Umfe=1221(<&kRkRjygApvkEuc0isN2il7f|F)tg z8~%adO5kw2WrcamR0&*V)dbpaa~AaPYM0!^`-GQHYz5V2TL`j@ zKr!ZUMAJU~De(-@9%HtCS0?A&6t3AQ^~3x>>!>ok_GGCoL^#QYGHxRk(&_O3ggo?P z>E|R(ltg8WmA9Z*7!=PITWIYeq}ury`JfaxwE`&ZAx4*COk&UqyM`IGE{GHBu|_ed z`%-rL(Aqzlod5sR5E$tK#vuv(naM!2FoOKhX8OaK{p;~bvFFjE1E_6Rmm zy4;ktG?-bx1eX+tysQ?af5GMVkCC@;POXO;SqbOaAPI2xRJc2jx*$ofi#_$%;*%V% z2Jd725dFT^I4Cr`DsXP6iER@E4V zpcIJyJ!t(Qq*nQ^wa^NLU^#Rl-(&DypbGH{LU$qm4$^TMrT!jSME-k?`M-iyl)u5n zKS3f9gx9W5>?ecaV~oG3Dc{l5nZF5UN3VhgQ`4Lr(44B*XkQ^D1m_chE6BHyp-}ZP z!I_&3YQy(?St#0tIDr4Ma{I5$@1G=*nSO7R+ylx zJ1P%t{1P$oL|7P@eSL-OCK{l7x%)*rvBP$Xst4ojo^;&UdHh6QR2%kJ3~+Z|ut~c%AtQt8_aD&(DUJOGqrA!r%Y0nxx5A58%`xB; zb~!wl1^y&1zPQ>RD&mT0pJ(=aQQ*FNdHQK~pWCcA_Xit)QHv3bhi$%TRGB_$G;b)( z#a}|xO|)lNPX6B61Y2_M@RuJ2SPopA{ye%6ct}2<#V}gOpQe}{X2FZHQ%tRSzJ==D z=lY$V3*v`IKHL@i&P~C1dMsTL*333%DF7*ak?13VN!TYOxoOGZadnR&vc8_l3iKr1 z9?+{|-!AoTSEgcoNSW^FUbXwnIbSF|MaF9P$Zp(`0Nr@Q?79I-x&!DOAH&w2PfEcI zp6@0QCU-pXXe{?x5LKgB zwM}^VPzf_{D%$ZTO{)4i*0U!_`r12lDktNB0XC9XSiyZ%ZZZLyPhna1)*dX2Z%=?% zPA2WIp-pSz+MBpkXVFDRkBs+iK7N8nD*A*mN~zQmUmyIXPwm4@24?0 zl$nhdO?2bOUmhnc;~H81I6~4?Dl!0=^idglZhCIB4bNt(wMZVO3u!lPrj@0sJx;F!6zCYI`r5o>?e2PC`>3!U=Jan;CwrY3ZvNqBD zDDb2`S~nLZT;GqAHUZ@g0Q}fD1X-b+!0Z&s z`K`0n5w{eQG^oC+3s5@u6lCukdG%msO2BSE*+DZY$YS88mBGMNCxm|PR$S`L?Qkqj33JqU8Q)dcs1Eg>q?f_Q@F6- z*{@Z5A%hQ!xv@;j&}Mb|)ha+^S)gvRrM~U~sV)Haw#BQ>K=su8CpvluQY;C1tA?w$E zdKvp4w~*lDI`s8+4TQ%=)Kx)8z4et6!_6;2^H}>!o{q1hH3T;g#~&Lj3mrdyn+bh` zj6HQtx0_TilsFsHi5dMVVLMu9b9V{uD4Xo(S{qJ^B{$qnw^zjoea$1o2QuE9Eg5Bw zY_3C^D31|Lo#c30wUyU}he|{B*7q`!M&}}n>G`dJN~1z*(w~uGZlsR;gMt-%?UpN>eLoqe3c`A_U}jUW^cU}+^I z(j3&vJd(eMJTIN!Y+dFZ!w7q02l)c&$C%LZFv_jvdNg~`t)coe(||)NL9wm_2f9p` ziT2B0q2K`|kJ8bC<%PAcUCH7Ihtoj9R92q<+`@^yrnjbB67(O*$r?LrcgR+@Z;w@M z3n&ta9TS}Lipiq2)#X|DU*s}&QCbu`cSRT3T8^3Pi+QLJNu__%^_SWdk>Pd#Ur)=M zD!!=YX_W{$hANY8TfE}hOpL82EI50DYG?1ht>sDiyu3piJIvArMeb?{1`KE|%`7=@<;(q1&1W-`#|tDY8nRNRa}M%Ly2(*t^b8$lKBg@T7ozy_$@XuAQsV} zrbz=9-;KeL_uZfd^}ld2Z2sbs(j=oYk`%u2{?MOT)c&Wz6F5SKMLlT^dKv=>sV2@J z`ZS9b>}e1@M1|5=|FrIBN}#BR+4dJV9v6>2iAgV;R8JtBNXj(Fct=Cl7m&Etsvd*~Pp1!VsVm0kDU#l|2R+$0Dt zA}~v||7{)N(>VX{wC02U9V5T~KhqU`IcX>n!PM~;Nc^~o_hZUyyPx)nG%;sBj*!TN zg7L6vh-+Y$P;BQ~{r;p6cyM^X;kM|Sh0JV)lDA=Z_qXt+$%xxd z=DP&8;+Wm$8}ymg)Ydl<_$Nstkd^*VvzY;@x14kzZhKytaB= zg=@ALCoQKC(ve)Z&DryYtA;q5aneozR z60Ltn)&RFxN8W_#bty;e=ws=l+xd8JM)5f@1W{SRN2B}GIju+OhkYNP8iHQWtDS-m zNGRQ$QJ&A%-^g}&BJ!8jvtjG|ly@=Q%)z_hOce|z~Deh{XNdQvqka zHDKUgv)pUqG?8fxNSbUAJ$mkBc+zP2WF}^BrCSdL>4(jiI;l6tJN|N@6sGuOVgpm*1Z)HCDO{SWD}#I7|9-tUHct{So(P zmiBD5mE?~e2A(5OyR#QZIxXg)wnGrR={tcP2b7QuVsxu)gRLbD*mZOPa{SKq?GfcsG74p1&B{ z;5le{7#7zRD3_r*m<|%`>z7d*>O5ife}F)1BW5kydUwL1>btQBb@0e@EeCro0jnUp z7r?1Z=CVWL{rGT#hm!9zwFkU4eL{Q}k=K25LHM{fL$!VLkniF1=2lZY58V@(;$fCE zAU7;4S>a}x=p0z2dV|F6Ak?%A>5A&Iz>^?sPMQmyQYB@F_heM6Ab%7r#vFAsMWdLb zcf;^rL=Zb2F&DwtjT{&OY-5KYWl%UK4?c@qUMhNSSLC)`-3&DZ{QA8y!T0+T;_{^7 zdlmv4PR8J(v`o6dTFviTIp!K4-W0I^RBlSki)+3kG`_TV#=?7$PR=McP5*frBKn!) zJ(L=%?m**Y1IeNKf(U}yl_z|{?h=7%erb@eO?%rqilDG0(2Qgc@YF185ejkSsBqm9 z+6-1}3RK{Uygw57$z86AQ?yU5FntTvpm)3}X;C`WQRYSAb{P1npgq4pBlQGA=+Bb{l?q1vAg20O{X@rCDE&R!BT7Dd(R|BWC>J zx?_nslV7CJuK$KT8gkML*3&43g)w$*mXhw7cNF$X&N+h`APDTd2AJ#a!QE#1Y-SW5 zAaHqd+KwI`(Z{EucPx2o=hxtpJ65ThyD?y#rfILHFZpEjqe6>I@ypa;-JamMj-iF$ zjU^?1^`m`iLR-B}iR`I7XnG|H)IDt{(MCo7O=U15?lR4mzLO!=_3#v^${6-uIxcT@CV zOIat3Er`HoMbp-p6uzFH#bI?#A-8mXZ?b;1iyc1vc?r-0pfe6GjU#cUs!Ddwx&5Wt zeL+&47O8TIS2)kG4^H+18BsGR3O)|WPGVfpZzwn>v#*4MX3eOyB2@_|hHoVOuz&8! zGFvcCYz6kVvcTAC7#r+|_*_wveVe7l1$!no9` z*~r*UpG(im%bB;C+%07&6YO5@4h2U&6WNF-ND<1qxEfLwyZsqLbK8-ewAW3BphGZI zk(%IgI(m4A7gTs47l&X3TyYQOB0|*-a40g`5 z>f3bT{9mf5?(u>ub0JYNt=MBb#i*NYGoJf<266a2%cw~cCSZ2*?yN-swAbK38{D9d zvuV%+7UWJHjq4*tBfnOi{p&2w_}cA8BLxuPU8=TUgKv! z*r#*pbTLQMhqKA$2nqA>bK~dMcvc_QxwOfke%)wYXV2nB&mU7))>u1I|B{|MnCCmeh`GzX_a&>^} zo#(W;mp1U0Cax>tKSkm3f=Dbbultmbk}B+L6P(6GabFZxVT9wvI!-ttbB&3g_#2qr zVZxiZvDFLJm}TG!Fl*YI@z%(%Y51<)V6zKoWC1r7lT+H06M#QhU()el%HiR~S!^5E zue=5xM0fEaZ_a!RJm+Y=JBV#kee5yJ;hJ9PiJjg=_XT#A=4yyv;nYIofW3O13=uU9 z3WvW!@{msm%9*fDzlK8zhC}@n#c&n?8;iuUA6=KCVw=sVoj0gmx9vtzuqyn6bt0f{ zR@=1hYgG7s&>6rm8L~x_od9_`P(>ymTs90K$|mC7Rz%ZuuXueewOF|G zd7EF;^yr2&#y+U&O_V9Q3v|W07}YTJ>@H3o)nBw3!(`NNFt^_bNE$7kazQEAEPCi| zP>+r^ZxU9q0qcY`l0&7wA8?pD&vg^Nj8|E9W1yGP6<#a5 znX{uF>IohPDZ=7ZOk|V_)EepuJBsqJ(#2u3iHwS4befc-w-S<>lI{n0d@>RR1TO49S!i~FE5z=@0`p}*F>aW&jVrX{UlVWAo4t4qYi zg)B|bBWEOqE=I1Y3+|bo*D1HFYA|V8fKS)a9P0}xi?dq`;;6r?uGia&@9|9+^;XC! zJ-y%QTxaCW{_Cpczlo(xjQ_zmWn%b$EqRz2{x6n13!0MA`;C7^ijM1i9i9t8U@(s} zGvQ*={6X#LJtWidmq9}4Ufu}K28!};&fSpoYnV!No>9)U@`)X1j=s`AJylMAPak5d z+JC-O74dmHe=dn<-F0PsIcY40^NBWSC)TkNOiZ7~S#y2eZ;Y6DLoy%#dbQ^{y!&mM zyMU$%zp6||jH{HS1`jk8Q+P%b#m;^thIEAOYBM@RyT-V?4JMl2+!G6CjO`i1BD!JI zFK}3l6~!FOaT-Jf|Kody1H;GqE`&c8w(TyMC}z5?0|SKUoH+`(Z{A6R1k&H_sDDb{ zN&TtdaCrI}BKVP0eyBay?e=)oWN-xA5+&T^_i0BO2R$V!TFVL3fiy3-`LHKCCX{Ip zNsfxF=<6}CWLCo>{)#IRQ{EdfaA0iveW6%CX1A3@4xBxZ!Pq>I$*i8qVJAK2E4|i4 zZEa|Yq|?WS{h2T<@8e{_G5%+VB8Gn%Pto3YR~dKvVKGc?DDxZ}a4g3V!PG_8?D|8g z^DH@L@kdOsq6W3rRUEdrxj9XCxj9{IP;pdRT4|lIb#45KWY)LE{F$N#lP_R={OzNd zZ6{;Fjj`oU)YgF&2k>bCF`sAA*TAVH z1?-n9$-eBCaP7b^J7T%3v6;$6v9qryY}MqO&j{{a6toK)zDSpmFhSJ=9<4pa(k8Yr zkGBYgst3qmFV)nJpW(i>0`wW=5RQ=ua;Dij8`)(#FY>mK#EN_2YPfsF#y|)p9=Q@n zMW2UD+KboK1#!%e@7c)}lO{Tq**zwaOb>>5wG}3i=hsI$C25&W9LmRzS)CLvlA5O0 z;?ham*;Sgs@*yRW;R06TAUR3o~#)N!*pbxrIuv2aP{}_A6C|#DO zZLn?I*lpXkZQHhO+qP|Mx6R$VZQJhYbLM;2JhSFqYuHm&vUXZSM2zC^39wa;>APNQOIrdq%Sb*8n80 z`r&pSl5|ooXkwxF+klCpPryvP)($fbsXjNPiR&vMUd@v75uj!M#u%k(aXKuBRkq8U06l-+pPDUyHk-q&JX znX8n1{x;;#DO=)rz2+=5d6vtt6*&Tz)W*0h=s%@av&#}mtbMwR$HZOV%|Wq5T!aSN z7O5wpCr{YoFU$RA5U3kR&s|42@F5CbSaC{S_zdY#NJ#anetzo57sXp~+WXb_kPOit zSglRv*jjPddx~zXgvFdNS|b<1dOB+%e?+tig7PJ+4N0o#u_A^WIze+AI?lj8e)3hn zk~rw~`_eM1c2CV^UhjgEx3+@kHWxW!$P$Xt&(0L5_2SGETL}AtmA*BHnxLp;Fi;Tb(@J)3ih@2HE$~Lzj{f>O8Du%Znpt!r$j^!pG=*5`TRPw}e~nrknh+BV+F{ zyaQ4ae3Dq!$!Iqd(!C7^{4%VbSNS`HlM<)1;1^p*Tb)|e$)=$ZNk}~v+n8?$AE9V! zGhuMm!E9F9shmVI$uaSS7KS%Q<8zcQlE<=Anvi}-JMO3V&C?k1+8?lZA={L!MQ282 zhWj_)2$oe&el94BuCg>0`6x-TY3qWUf+l0kLPFA)H{ElNSAb_3yGvw^V$cJ*UFIt1 zissoF7+*{0^#a~jRL3Uw7Y1-9B^4qScVtQ~XDwxsK-oo(>xHLD|;b6Hum2(H|=p^Va}lu7uKNjB&cWbfv2H_{Be5!HS!|CD{@HqG_u3lo(zh z$&5C?jOMfdcI8Jm<8E+U#S}q=b!ZOrs-+Rln;u$MW+mrT)~C^OgEt?zL7I0bfIRHs za@jZr9~&hse$kmHNgc#njNDWd9SJcg*IY;$jnO)g^Y2XUD^$A5I;6QyvZ-ypHvjUa_ZP&N&|GUyI}1rDGOFaQ2z1czw%GhFjLf5o6OmIY(W2Fe|qMg$TPYy5HM`KN4Ikp3NBk;WI*KDC0r8@IhV05LP8lij$@74_WHVLuVRXe!h|&B6J1Gd|9^jt)9biEFw@nK*+sC!BXL zzfb?WGX~>bBEDs6ZRRsXXs%Ua_`_KxzYNFSR+ zvC?N(z05d_T4&#uzUJJ;`Gu*ou&G65Ma~!g%aXbMy}?dTR)eov06cd*TE|pTm@3;4hvHLcim%C&_|3drIv{Uh}G}9c2SQLY}Jv z9qT?Tb$Up@zl@qoIU?l1bkrTaJqatJOwUx$jPSmRccMJKzK1TG9_V_mJDGUQ7u=20 z$6%sezH~Op0r!1(l@jl%5-yF?3ObSXM{HJGe-^B8cVOAsf~nP_H_>&UY#0i^_v%OFo0z1{BH8i<5>gavYT!{W!$yX6M>|Yu_grR8JMMnA)E|W*yLE-<9!Y8{0kx zjPS{AnZKUx-FL`a6&{R)ia+Ok`F2i@;)s%@zo|^l9!n3$PCW0rNt5 z13<#gusxvUHQ2&V$cK!IlMg~hP`R;+&^jD&tquZCK5+ZWKp}Stxw+TglHcB<&n|qB zg;lsrpFIQ(CLd^+wr2(0&`ibf%8>QXP+$s&Bcb6mu`}>d|MZ=QUe&X;hS=UKFKK0$ z4=hTZ7~`4O+^BoCfZQh-X3uEkb|H|CYNAdVPC&{wp%BFjU)ke5VkTnehm=JbW=(UK z3jx%_fc#N}XvlES-^}{Vt2!T%yz`iSC8b!uvqwEdf<6Y3O_Cq@>+NM zPTJ7Z2-Tq*mSlYZ67tsa!rq6Tl%03d0RTz*=sK819Et&l)_)=&;0D-S-B=P zuBQAurD9iPJ;tU905_Rr^Nd(fWT_l2j<>Riru>L>*bojK*R$WCtX*c2|5JeUZ`AWo zTE`De(f@-Vz{Kz$Sb_iA8)Eq1Fmo+qPsS3p-SX-cGzDbbOp_8o#G9%DIy%+!!v)wy zAcIKwza(zU^{C4<{t7iMVc{H8-^?sL^6u>v$sYHAAu&Af^^|1M~ z(me(H`M#}71$3Bi?~QZ5Ybijboa(X=2r^B4 z7r4!R>j+GjNuX;x6qOL3wtkZ+ad7CV8~Y;nB!bNKZdjb-Gk##KH$pHNj4pF=V_1x< z%h+*oo5rY@-LWWAS9gX5IJ%6DyF0>JpIovdUOI87yt*WBfU^vu=WA#tv3W5>bC;*Pre-?3L17GiFU9m_dX7P(Fy zhBH#}N8M)!!D^CDc{>rfy3x%;QlwN>Rlm?iaQXt2@zeZ7r^4-dCMtI^kR&?l|5QV^d#u?QF!GP*Pm&}N}e3lrlI0v?> zH_5Q$FGMMqkPX``jh8jv4qK(_56omlCT5Lkz3PIfEP&lj9%92-A@GJg#7M|LaFd}- zRhK=TJ&9ifIB&h2p%Y{<1O-)pfdfr=3tp<0HKIgP1v?mPh`kh5Z@B$Jo@*!yo7!?< z#2-PXJ&2H^=Im zED&NtoI~X;W{cF@CLv}1#$m9XOV(jDuE2ZssMwTd4%dopM3W}h0@-;4ZpZ=`n@-}j z;$9W;xK1e4Sk#_|p8MPv+Xa>dV}bAb;T&Bf@nJ6vYG^t{6*@?YW@7*mOJ~J^e+;o# zWYW%h8y?TwwFrI(u&(7m^-d7ZX}^u~8sR7xSIqvl40e-o*rSe5eQu(D6)Uc_UInHE zdrDv@kg$_jM;x!2lP3U{g_YVAmd~ry_2PN}S3ML)$g8x|S=LiquLr>J-093Y&D-j? z+DGh6FolqhrZyP`h|qNI2o|p@Crl_*#upEDb?v5^aPaB zb3je2iod<*7>@9ZFtgfV49--$Tck7i_aOpnm#^C}=5>GW%l$I(41}*sy%>v(bIyi( zA%RD*<%9n9vcNl(^7&D~Ufa^<^rnJtpT7HRP&G;sHkAhI?>`R*V+s}Me%Xra9L%n%zY{>HlG@E zBearmkGSQ^E@@|2SRQqXCcJA{^j)m`{%BtzzMFKmLx|1pk{`h4&QoS&x)tDDj})}? zBH%;`#9Lz#CjRcDZ@UT$B!)3!8}HD@Vq=FO?`|6}lfNKk*vNomjt9lL_C-lTMj9yu zcYQPpJ z-17^liXUI-Tn)OSqHZmnt=a5|L7W^VTR(#x{!BOagZ%58(uS~TY-!i|h*o+}B5XpY zRd|MtU|Q?isdvrCB--=6ij4|!MJB5D%5I;sEJOQCb)Phj8zf0O+|+4%&&ut3v#Y&H z+aZ0^o8}8`%Dv*&J0XYQ8*TE!7`yLFunY06dQgSr7c4N6Reg)#+>IR6k|)WK&%JSp6Dce0$Di4xY}@TzBf~Rd_HoSJ^uW zIF4Ay$QRb^ssQfp_y5Av>(Rq_aHa7U*mRy*+zClv%` z8HG7@nu)7xaM&DSVZ_)tB*kg}l(`C_uJa8vjT9)Tk2G^ai(GeyWpvx}UhwUqb6Hz- zQTJ3jwP5g=f70|cG)03$cBJh;RL6o@LD|M4C^EUC&9p5(`-pH8ED;v z1RjY7OIw$qHnrt)QK$2c^K?o$!{x29CRWeda+LN9^uN`*KeGdOn*7x+5_Z+H@H2&n zp}lNbkmtqEbRV4Y9?U|k%((hxc5)OTlIALqyWh;UzOY6SXt%|2m3cBpM#lzK{$#(B z3%G*RvK6zq?aarEQ-ZGL)V+BL`io@)J0Q-nd2;gT=SvLs;BhTBLt)$Wh^*JgPQK85 zV(KN6emEK&*R!rp58p{O1Ci@rFj;ImJ~~g;abMSm-wjcpBt~Y&PnSeyO*wjQ8xMPU zqB3JyTCZh=M_Errv%%4`Sx83(ofajD&)$r^sK5in1veGEsOWO%Kqh_VyIKjohky0r z1*=^7V1U!u{=7X<58`UK$RPCjS50RGV zlqR?}XZq-~GIJP%#Jor^d_$2+GKPPu%u*0yo6(ZC5#9ZuMO?yfyCIaiZ%nXplJBWn z?aLb?%g0WD51KiccG#oDu4*gRq4a+6h3L7`bM&cF$rIJ^o}RrixI9CH9w@v%=XQM$ zT}$K2*9i>|Py+A0EA4UaVRZcLsp#IBd)+>w2^+;@ujhS#x!Dbywn%zAyHC^KuBoV1 zJyTh(;j7q*nG~_b#)oEgph52wXjCOtobpXY#$5AzFOkF-M(wc-Q`nY|ji;U9SG4cNX)T5jC@HD_J@XJ*# z2OyrzB&>aXpOoocrUHbRQ^OruM2SAVk476*VNOLXx(D}>_UHR57jM9a?yN-zx|_#G zjE5Hnfh;ib$8Z=%{MB9&d~H~c1)<17yj4$a71~k4k8ei_8kj8j`wtUF4gN?fkWXR- z3WOpQ-u8rkv+s!()I&juB7ryszyU}N{#t6F&5ccvjR!8BMJNrek7vay2n8?yvftb8 zf_!)s;Gr@Uj0zNli70kxMM?ZEqYMQ?F-jw$&t#+Ns;8iIX#;4$T67y!p@mp2>f#de}+YR>x#Fe+RQh7Ls@lh(X%_*fsXT7h54Tjb z00~6O;iLWBX&2S}c_38(*d9nuYV(cTxJEDrep*fnk*=*^7u0YAU}ZW ze{7~uS%x24fuj9g%1HmC4%Hj?cP-|)oxn;Z5>Egu8ND3y;lm_6JX)al?xqrEFC-=(0`YOK<97+w6GaOhAje5>af`KY zWR}%3o$Ja^=-P5HX+eXw9v}XP4jurrj1-{w=5V%byJw&xyZ7U6u_>Z7{m(tos@Z+u zce)w!4ZeHmMx1oD62Oa4h6V<_`vkV%i5Lp*t+xGfUf;*=?&IW89CFx7XW5+7NwCnf z;WQ>iyLao2bySlVvGzFm7Z{`$%c*q&dX)5UvtyaY8SUxe!N2cM49cX_Oz!9Dr&QhP zR8>Ru%n4@NGjX-^NfaZnp^Q3j}i0{USl^$F^%{#{IsILV_-i3q$psD-q^bS@3X zzq)g%W-HB;QOhoB!dQbzl>l6LEHg6XWbR@@m?Rsin+h^}M0z~#%F+S9V+BV-sf;x) zGC+^RLEpNn#IZkTu+&6bKqX1sm;_WqqG~;>uvykYeWkto8+vT2E5H&g80HZ(q#wyN zrnKd=9Og)U4~ETxhu|5(N-2o|8`<2s*iH5(`fEI#TTDQ7mz6?f;-I`2>w?$O^~D;} zbl~P7DMS_JvD$`qez-YCEEUcB$WujeSWQ}3UGVro3hf%YupSKQ$0qtgIDW{@;flLZ zi4O?TM@3sn&HFbj$pNVRd-|!ab>ijhXApR5mN7-2_C7FjU1Im5i@I9dO{dZPNF)?) z*%qkOe>SiC65mXtSY|9ym=bVjdzk9$Yv&h_Z!YIQNi03x7iFN2r^`L7UszncTI>>W z#FO3~RzMWvn9?c9;^r{yS*&jXGPkNpM}Eyz&Fn2}OyGv5J#IAWve?0iCh{}04#e~| zyNnWS{=Hyvne>g29bCE8;!jvA%@pnFN_}CUNmSZtMThL8DZnYIGo0%K{z|zxlv}>; zsAuOpq8w*pNEp9BEnYR;OgPq*R9X)%Kv+-62CBqmAknO@Kiw0v)*#T+r-U=Bl^2Aa zX+bEUy8{X;p^(<}*&oXuq#!Qajgh1~g6n8hkrv~?8c@r>(V$<-#-D6@G=nuYRyPxS z&312ZBydUe5Sm;BybEb2*IDv&lYxue-U$!)etmbPh|k@i5bjDXxP!&m+%*?~hP$*= zf>gKRNxB!_%E!7hOyVrGuE!py7XH;WkcMbO+PG$Iy!LY`Y!d4@(xOmB~#zG4sY2t_T>l%)TbG zAotR6b$1@K6{dtmJFp@86tfHb^3I2{)yBHfYE5QVMwlwZSfnC+JljyyY3a49)Y20u z6Z&Wa@^L!@xzTBH<9Vx;1X1+Q=hA5yI4M(x<%|Y>Vzz~^Kejl~=H;RX9n#85@_bIy zEwseIcH@e2&R1vq`W(GX9Ip_taJu&RC8ze8+4wq5C-r(5O`p}upO}g`Sc!BsXx}4G z=X2)XtW`}wDI%Vf4u4#<7FpCRA*EdEO1*omh^rT1MYWggoiN+PX33i|ddzL*lQ?am zy5>rc0d(}(Uq3h0skI5_H@`@3a;F(LqojCis6HmMb-n$-R+e{&pA4|y+Svz)b)*7ShA$Z zypNdjYOzhNPNT0z5S!&$W^EW+exoX^?V0+7*)Z4%(mOr*7i0o=+n+xDpj5uTpBPYVWMdGwLoU7O*b9@r)G2&6KRg|###k0m;{6np8aJbu}A)BtthD;ja9X7)Ipw)V6hdc|jLO^>_DXrqN5pVSDs9 z?Vxx4XN{_Y?9B0UfE!y2SKjnq(-DpHO^_XQSs z){r62$F)8V_2|GZBq;Ln-C6pGMZxt0Uipd0sqHNFlj^kxU%D1seBb*;C*k6Aww~JF z#$-L*T_uuSd(dNSdXnL&s93#k==U*2CUvHXop*WkS@4QjIR z$Enl-`=p|6on9LVVR>&+X&>MR+NVF-8aC^Ie|sjInU}xbxsS1bcLQ zPQJh+w84o+;Rt&OO$@L9L!C^VB@gg@qM7lhDS`6EGYT2RmH$inYt6(p1`u!Rk(fNlP=|X3eO6 z7;i}8x6&r_9^v9#d0B6!7xyUim{Ieb5B~K=xWJpQSuJz_jvnz132bHoKYZo6p9!a8 zN0X1zd8gS2+$H@7(Dow!;7i;p1h2zpvIoohCjkaNg?9Aimet;!Q7qRmtq_6Aro7HD zbyi#RZpe3NdM#9idn1x!hEoi_Qv8bK9q-())EYSl+Y;(8-G&v9v5a<4=fM!OZ`Z<= z;3Ht<7Sc&q)%uqUJvy8GUgdoLz6oh`&8OD0EA+h#T340Jhl@5YnYHfr7S~r3g1izg z+4h%j5)=4AJLiSEATA%McAqFWzBVAv)#ZreQObeW3HoixSXktaIL<3b5h-!|gKBL%;0YvPG+9uP$>zIg9B@lDU`Y)4UP z@J|_0O{p*zte4U|URL6;f^pZ%)&ke~sJ7|u#Sks>9_8!@n~rJEMp@@nDD!s5Qp{LKuRMbe<}4W5Y__)@wE8+Jtl=m2;S6`=JU&wM@%B4Q^eo!Y zS>$V1s^QQFscI}9&_Ts<(AILw;}_vc7(TZ>${=nw9rp|9ch1l_tnhPVa@$918r5A_ zLOt)4w%hPog>)6FFY5~D%|aeM%{9u}ET^$uT!?yIH?ILn(mcjTZjh|j2{qv>i64-1 z5kFVM;5%9mMue>a$V!sEduqYb-0+G++_KVc&Q7)^y~UiieFN4wE)m$T~crE z*bm*zd^HsG?~}(cDZ%`AL}XbQBI*;HUW6TdHim$&Fj+l0=845{M06ZNLB4iMP(CG= z8}ViSqNzqX{WFTC^)}IhSga6jN_55=U?Dj|1^hYkC557R_gd+5{%xglHK77 zCOp>k2glhnN7n<~(P$MCMhLd5c;f{)s4Ox&E{2=kiQo3}(o^JlDY`7h`&>yZD-bR3 zLQ$_6q9HjIKTWa=#K+ z4Z{ebpo=1~ILPeP&<^v?A)sAfnL!Go_H)esbt$^&o$oBBZD zwdV>I|Cr}9w`K(N&iK1??kU1xz*T_F3@FT}Q9u%bs$PFRpJf!}=@1+>JrLSbN8A7I z0r28B+U_>YU_eAYa0cY*7Ch3hxMq6N0M=3>2bt13~nezb}tLtjui?d^cu2kju z5j=Frzsf6vD!t&zH+rhRP~3+j8pC1W)Ka->+$TnaXx9@c%upPPGg0QOZQ_xBPP29z z|E2|Fq6S4%E-gdm<4uW1BU7wXf7u6|Dg>`=y@ylD)vl0Wz#1s4?9=@XUg?}D|9=cb z|5IJZ#LD@`}UwTX?#{UgH<}&tpBz4E_mY%|Kz@Jn>MN_EEz_aO{tZ88UXuBcwrUpwyA`+PFx3WyLxcnT)&k;y*%FBixcyGZ*CDsA7l`=M*U_K$l) z-L<~FuQ&N2lC%eQJwwU3MG`RKx6|3QzKII8~<1tYyOoRiIDHhj_IhUl!5D<$S$qbJK4GwIC9_ z^BDZAOPRT+=hg+BXSA}j$Cc~<*Dp$sp4h5Cx~dq~1}sILv}#+QjExExH+l3mi9l>?jByMb zcbM*yo8L465ExQuLEN%+5i= zJE!1EqO?ZB%uLD$-(+e?c++up#K7g*Se;+rZf@?AUtinHIzEp(xT?(q5^dMT39u3Q zprx(i-ugXDZ~vPsI@)G#x|z84v(i*ztK|ie z1DShxjIYMYX5t;=^jG$?p((7uyBmBN)n&RPk=s61$4 z)hYY%17!h~KT+H}MVV28eumZx#|ydCQoBN5Vm|6sp5VL@`ZbPrL3n_X!2^eu!{~(E z33q5wmY-6LQ{v%SKKcU5%c}m)0$jdh$sheqhMI>NHL+&@TF-v1!eIx8pop(!5LYyQ zY5^@j#d!O+^gR_Ehk(VyAf(XLO+^%9+EM?7LtPY-`BT4y>v^7#6g7Iul@1MXYzxs{ zY1VhX{joY>M@Ht5rID@wGCfE&F;#Ii92U@RNtkgSZEp3Cq@6*R+Wu0v-QUMWQ%Qlw zgU*U*dJL(=UtsBu^NRbQu`;%hhJ^lmlyVBe;=uY;(RLN>dO;A{hj95#fzy@_WO&is zAx=@7jgTx!_x1p$RFVGQ(;5@XWl`ufetq8kQzPdT9ajFwDq<7s8NC|E;Ti8^9gpE zRz&f9#^GA-z00-L zT`39%;|H~h+g@ed}-v=tY8U1Q*c^TuykBz*zw`yTiB$x$C zlSXo858+yWU=v1HL-t1d7$Poo!;RNp9H!NfGi7oo+&dADRg-;%c%T#`p(Gc|%H|2u z7>{_IJx7KOC9rNan~=Z649CE|k`<)e!&FgjV8|1*d9n2r4k0 z^-3=J#XNqb-E0-Uz!Kcrl}^vxNA%6V6sg#h+iFQ;}8;r@`uZ67ZzHC zC|2#$btt-Ij+3eAUTxa`RV1ck{BRixjL6aqh;3XzuOBPWeN`1@O8kCnX4m_;!uswM zMX&v`r;3=|sO)I~#wAmgiB-d>a%UsAxqq)HG6!o^Mbq`dNMuFU&iM*XOEfXLd%4oV z4#_GisKW9#^8E&^w|aBifX^xIQ}ESn=u5{4q6itnPZ6bp&Pq6b!^d47QoyNsc{uPa zYJUZz`l>$*$8b7=5NI3Ya5`h5O?3!Gz!k!gMVgl!VB;5lP_ZGZ&50q8|BU+Nj-xgx zRftm2hJj6u|NEI+(>Z#%_Cum}{mpXWvk?!+q~~}R&aD$l౧xz#%4$WQQj-j1- zII;z6lk~%JBo;YK7)y^kX0Q?pyS+W9^^M05h+MV?5!&4|L%>W^Vi6NnekTg_13Pkg z&L2j-t&k*ckGS7A_S!ya&4#V4rn(IBC+gq$hRgy^Qd@W&}d zFRGHxxQ?y23lko>tEgK1{wWO(nWBD_;8sOl=aQO05?fY{n_Xv+D8fBe|em(gK>O3vs3e5H0E3Qh2Mpsj5Fj@s;~iUp(ytwX(A+ z=b-rmJ!@?5`ng|5ryh%Ko-jW#qFGd;Q5jgP?lw>xxvxL6)MQ>m3abQ0{LUYv8Q}u+eBYYKA!Ykpdl74$CX$Xj+7o-rzbE*)14J z;{iZcG3+G2#rz(-AeFPrYItPqjl@V3pRmBV{Z*m|MWMCb7h93Xh&p|?6uJgc8i#Hq z64k7gUMV9KUV6v4<0{(%@&`a$!qbp11MpEzCzL)NE9x`YiX=7Lv8R2UQBvmC{dl!o zoaVmAHN^WF#}uu&)WBRX4ZM;)cu9l911{^dY)aXz=ihJWZmzRcwO@uWYxoe^&^}$- z?pA=A)S25Ag|#M^Ri7owPJvBQ6i{_uTAFfy==pk-V0W+<9(Um1=T_ZzhgtG!8P+>; zaU_RIJh+RVqNeY_h9#&p+p^mKL>i{ADp$SB9D;K#B{yVe*L`X8Lt}3iij+28H4kH< z3}bZq?Y@7il32&)`JKLhLaetP^qvblh3$M#L>$3c^({q^PIB7n0)Al1F}s!fy$C1q z{0f#~e5LCF?}rJy#Ev)>x(1MM?nHO|M=H2$=8XwpNyTOA7Ku(|=1Lu`N8`&laqau5 z-_D|4FDIJvwO;@L@v$$m8(A;ypr3Wy7Iut}C;xV-;{p*rV;}I;`x=+VDmhd>ZG-`0 z`pZKj0>RpxU2;e~93vJ%;@(;qL$&!w9FC}lLm0T8Wm(0fjsep|kJVid0%rfTDm8pS zvI+wIw4mE)n2bk_=Vc41RS$`Fk#RhZ0&W_|!_oo8IuOXi@|Q^xK5&%wG6ZdaRJ|U0 zHi-f*8V`F}0X0j1V8)OIZl^3X1C5C{6qJd^(gC>L-P#;q8RDlWEcB^JDZBmMs`_ST zD+Jm_dwQg2{i3S*5&4f+)0|Z$iV2E;SKD9hv6pv6$a`8q(ztVfEMb{ctH($WKs67wB;S=rJ<1+5M3f$^RqEfjP;N z_(xm3!2UMCn|ylWkQ^LWKx7X%53O(=AQmRCc&!uv1q;8PJ{D^XOcrmuQ8V5JGeY4X zfS72(aMCBd2dw_em4ZXJ&+Y@IWtm z%%{WGcYH}2$}Oa<1?RDaq(!qr=TV%f2qBQ74!nnUPcet@ z_GfPs3&R5Rpu=Ex*&K4=ki3d#7A0hQ_yujtX zA4~gf)T>I1&-dJxKmEICe*)DIAZj9}YI5Z|j`W0;*V?rr4aG~?)n7G$4}pt&t?27b*_ije+`6rWmcCE&lIe(Pw+o?bzg~aV;xmE)KEuNQmp#1Wtk5x?jKm z@E}*_x}Ux28sd3 zm@!_^2Kq0kn@s>7lr!BAGK^4S&P&P^>84>lhW^DWl8A3HZ(`$Lp~u;)>xnr%VD*sj z<+RzZJiqcUNjaIv!??{!4|G^qSkkKo&TrLEcSqEIUe)7mzf`>JkC2WE8VGD z+z%|8cz5ToWt;0B&!>{K`I})R1M}{Q#trt?|!VYd723qQn@a?s4#UG5%e$qVQm6>3%el{nFEUd4M80zU-Ag-Z)!x7GF?}gIYXs|;C-8Zl2 z0^sQ3M-z!fya?q$VYnc{t9xnT35#auKl*EQJ;^Cx9C()S(CLia@4t;3i)8Wh*FU!a z2B6U`BS^Gh9>N_H=bmRamKi%zF|QfNVRmiYu?S*K z*j#n~V!kcaANU-C|h z${avdWKHuD#UuDUoC)%p3^HNbs~?bW>l76MvDV&}(&i9LtL9j^NRz%uXj>-K>;HJu zS^yqG2=E~@&@D{beA==HsHI@2x!uq0-%IWw;woygzuid0yS(B>9T8$ zS`%A{Pmp3Gt*aa&QkUof#=?x`5<5q9dboqd%~ly-i|Kt(K*%iGAX83*DQS#HX=f^l znCf9t7QX>8)G{YH+0qxql)*mgreCMvLMtIFq$fp{)_QRx9;CCgMt-B6E+fa1Os#BB zt2KqH+c3C;C9MXdg%QouEp9NZQfZ~tEqeYYjK7%pTy_6R`70(bm_Yz%DXb!R9IDtW zW(3J-w-Tl=K|BuF2KFH}EYzVowY(5yxJTQuEmDhRMu7F|igMRoD21Lb52mh$*!yrjs9*gliRvMVBIqe~5^ljdivU^&GwSQy>8x^^emY9da!kKx zzs(^NtPhNGx=ij3d6}6> zv3WJ#-U*3d?|2sIJnKWM*9|tUuVmWDw_lebiVn51uzphr9B(W^(d10&C=9kJb+7d}GaNoj*KH9#7BmS${+IRbHm? zv4;JLQCeC8;?wh6|8i&5%9rc=UZ@b#GXQ_zx+@Bl?bve3Kk2f3D-}8!aF$%Gdcenf zZ&lh5A!HfhQQr>FrQy>lTiar8=&<$lm#xC%a+(^wm8obu4=^hp@4@}4sT9(~-Adp{ zfunf$nJZPz*Jtjz4)xNE=2c?5T$TN)p{nDv(bZ+kEA?Jw z?{Xr-7ahfnio_+{l9D1sxAd6~u@*k(x@T;TsOr8corV@o77fu zt1jZ3h&oqa#PIrComD_-2kfUVxyvHlO7unl2E`uz(uQCyN^4?KvoUGvqM0pSS|x|G zB+e6`cf!k(gNfT*ibyVQw&7X-t|6afGMGlme^(!WDVIp&xGv?o*v0Qwr{7)`+(}cH zJo6X*h^Kt;$8&kQBo?Ct_{;Cmc)@&_BA9WQaefEyMZgkQewvWzAiRy!CZ#pF@f&wR zn%ckpa8mSZ8#DaB3E!Cxis3SNFu8}V=FN>wX+0x0izl_uH}U+nB1Qvlohv`FTUV*pT^RgDa{flX$_$PgnL)hzv+`_keO7Ut4SaY9 zLhg2?4YRQm6M-ZpxpiximE9d3dz4Gdjdk3rCs!F(zBH7mu>A{jaetc>GhiPdEo$G# z&_MI^!_Xk~a$wC6(DQF%r;Zpk@0^VPz){w@KsQ491vg)e+eS*SbU?@b_o7nXH@1>$ z+V%xV5W)imb%`cZhl*0rG`R@<;GB?6y5|C4EvfcC6AY3jjx2YZL zQ~R*Al}LjRCx9uRFfP#!vBSh4>fD@Ekt9JQQ_~FIJwlEL_Fo-Iu&L~2CN9cPg1FX zfo?6BMY<@WALks|SO$o2kzGW+J1t|L#yX{}E;hFGc$1c{#@*o&?XKCzBCUllG#b;x z&<9zUFrqhxD1X+87JCl1EPFGmjnukNJE2u`==Rhq3_VY z?KNQWZz=*y&)!|J^w*>b=w|^DTzg@Hz}DWYfjgNck?29JVw9ITvvGFb2_Hp4MK$Ye zbn|Y{K%6xaYwzY$TkBm%4}e;XHjN{mn7V3a_@SrSO`P3$wVNz_!6VbeD)!u~M4ah; zC(GuwegoZ)BmTRWvddQZ{x38IK;-z|Hj+@=iodECpywQ=l=}ZDn zOTc4amETI_mt=oSmBZ)b^YScT^*5Z{^4ob{)ux9EmE{?~&D7h+`rBxd#$t<3-uFw1 zf(bP2mFA+qg#gRhoX#Gr_MOlitg^G*r613CGiR=vo@kQ)3N{bRWP;e=R*_}?@gf4h zo4Nc~p%zf(Ei{!ym!Q>=_ZmmbKWHw%cQK7N2G}YTqeT@;?Z>6|iC~ORKm4t-fSdC} zJ>N%jkNurBr$YFp*+>TySVeN4umpG(Vq+-$Nw!*}aP1@fQDckfAgV87R|Z5hU7_+L zbS#a2q0;gyQMA0Gjnw*ss%YfAO^4lhVXY5pk|Ruj$V0fMIpr_+3laYpW8V~=+1@@G z+qT`YZQHi(q?2@P+qP||gN|+6wlVp>nKN_#v(Cl2-0yzZ+BbXsYS&XwRhh@tr(mL>B3{>V?f;{C)z5-P(w0B@MzVQWak8Zrtu6x{6vJA zNVX;3j3%rq-~nRDxbT|=)YF87FYy#9)$$H!bq)v}1lXA&%F7?};Je>QqXDIQ9_&Rw z6XLz^pRB=7UUawjHz}q0!)y-*V|wJXK5Tt6U{AOvKrulZ+?2rx3#|co5g9*#?quT8 zOoo2c)+C?)kw?6 z@F%fuCww0*@GX7$sXo$yK9Dncp8k}qQqW~w98;^(sF@kEsc7E6juyXldLUgXn1V$5 zfnC>&^r1;Fvsjd@7dJYS75s7V*FMjjs#ZlxL~T>qAr9tMMCQ;USa!5R`hMEYZx>Z2 zPXfQxL1>(&e2Kwg=q7Ee?ve6|meFwWm!Mya2h=|zI-Wfh)TS9dy%i0qKJk&!>v9)f zJXi_Af_=wVE1Vmjcv*Z8P%R1gpg9>i18wL4h`z3ZmiD@F;6DS*xSui0CKTQi$CJF8 zPM_v)t-*K79@>=XLzj+&>a>@i1c9s+V4yvEm080AV&X4mK;$BV|GN5+KljoZt{GM}{RQObSD|)#VefN=A)@#^j$jY=e2a zgsi@!*$clPUdo?^jDysNK0D0QUEW`Pm%Xq4&g4BM_x~g(aW!g%T zjy+wnOFME=;b}fgc_Yo9nqnNgQ`mA+fA%SHuwq6M=2b4WKL*H7z7|CO`RrI7n~4$` zhHv~Nm38qXIZzR`MX2kq2Kd26uj=h8};o_U+1KJ_XN zm2DazrMLI;e?r4)jgpr3AJ4Qx9(^Y`WKWV{)5q#~uLpW*e1W6OnDPA+|M)MC{0Ds) zSpHT#&&2c(rBO`(rZnn8Q>x+{a{d!4taDvvN}_>=A%sUBaS8SRVUFG{aZEz&?*n@r z@?@5)7v2$7{Mrw@yDQZhJ;+uUyq2xc<@ekE$DHSiRqr>e20pva{5-h%kdb zEzXv;yPTfIa_ihdFC$BO*iud0HKp}GN}q_%Rj6JiH$7QCtDf0xd@+H(i})V0qvTWd zR^jEr@n!XVxe>R{y2Pv}Z?YUsc2HA2eibTzjx1}em6kQL%p0MI{igQj zPwK}3?t{F!hC%D7)Gub(x)+ByA_i=VhKyr3fkHV}vK6qkW@1R9IQv}i;a2HG$RYJ(V|M9*_nyT zP(VgHg9g?XN;4**Oi(()IxFI+kCa%|F9|Dt0V|*cnaD^!?TDodkK|9u-rtNV9`}DI z>pi30~bbD08dX8#`x;1FnhEpb6RA7z7&>JQK(nT6)Ev6sS&~ z{|-^Mt*VV`syUsl!LtKb|q_-$Rw6E zwJCP=q=J)d;8EUi_BbU^OjT!TkM#IC=_y`WIB+cA+TE#uP;B@c)GB@_&wB=Y?lAg4124BT!m0n&gcQShV%m}%OqD%NtBg$S9L7c~8+usj; z?LO`9EPrMDYC!lGAlamN8xAsP$uu7r{FB;lp8wO3kk*UY4q>~AjP?r#Hwbxvwwk@o z9`52~t4mPF9q&?2eMWm}gwjD(1-WWFez61&IEA&Ijvzw z8nQngDPhPlWV!aNM^OQ`w=CRImUSLnGNEmh4mc*Taq`ESash@V#bCdw#MEhaVIry7; z&PzhKpyG7#!tb}$JZYz?CKRV4=k0a$s4&^wjQuW=pF^ZrL7XRCn&5@7*pY>V5_4P@ z$l?5&;%^gPCNZ=5&?$Mgj_4`#l1(2yfwjy;p75!0RqyG6{qa+-oVM>9JiU-tyTJRM zeSs!t)X4h4t@`rx4JN>Tkk?OR%f5q|kzR<{{3kY)0TZd9jb0p!2B$}m7Gi9Q1^)GC zPrR+x7mgIPe_Ho-K4JLO9r7Rr!5UT?kmIrUo}==;|l?B$-L}{LF->? zMWIX!wYyjH^8Q%d!Wl7;5;fN1H?wXlfelYsqVpL)dU4HRtc=v3#o|_t0KK~oM}w8% zrSJl+JcN^Rl1omBJfdU*e<7VwKfB#azkd+m8^r(Sc`9?e$}<~I1MCCIQR&5hBjaI- zF(b$_FwpyQc)Qd9*tFfkUD$Ws9}`40>CKXNZUqQ0E^2%h)SssPLEJshf0RC_UG!k2 z5;JXb=|Z9G-q>rygv0`dEU-#3Y@5Kqbb-QfgFs!y-6?k~%@dx2u)I%=W$rJAI zdNamhZ39p7h66%HuBD&n^=^MCgpVJ-nWta&R<;Y7R(C*WNc`;X(Z!cu{z2qF!qi_% z1_LYo|0^74V*1M__IGCVZ)$5UG{>sH1&)oan(KC7C53z%OnMmhwvqe}KpdeZ$lW}k7R4J+tfBnFhCr!ILdg={XCKgT;;Fs4<*RgMuHz3Bd2#)c6?v*9~W98 z4=+jfuQ!3H8*B?NF?t>|aMNQSzC7Ci`RG?Ss?nd#;7q=!CQ?0R zUo}TLo6$!tat#9fWm%dSBE9lLbo=sbU4a4*`FUW@1;86hV~`+Cifdt75(&}mv1pF; zA0`p{2IVSOQswHu)?~qCltH)er;X)cnGe~I@j!GCz$mLMjq|^NScW$rBXRR!ed4iC zn?rzI6iju1`0Zrra3Fn`&J z?OrO9@+Om85$=pWPs$iN(nkdyHv364@7J`2SIxyHNvO;x1V0oK{qPk5eG&7_#*_S{ zK5p^#1G6WGCeT+n>Pc3ZJJn$mgB`yZMC6RdWdI!U;LB31_1n#(*MPf1gf=?GjGQH_ zP3Xr4v~{}zdBfoGBhHKW6oE69fheq~n`Z8CHBDMtJDqP|*{+CTWzx_5SroEre;Avd zfyRWO2u2m9oX%oLvWZG>^{MLuUe3*t2b;m3!2$-l(FI%y&Off_(E7vdX`7{pTuwC? zR%J^C-6(Yy=UF{;vX$51AdhfME2A>94AM*FffwZusAT0 zXyx~eYb|`ljE~028-+w7Wn}*12d8>UyhZl4F*%2o%}t7L$#qJ+&~WtN(3}^g(M0H= zGbSil(mKCQu5eCB0!c_Tw#{#z>{GowHn`uOi`LaK<;44 zR^SBTD3j||Vp?GhXpyYmNvW}w7 zQxWHeB+}&Ckn>alN+TJiNa{8QT|0q}-q*MqcF3E&-6vKX(H5{|HOwZqDT<~bZAQY- z)$0rfXJEpwbWpI>b^Zu^W{lG92=gNd=w`b;K7qoc ziMci8#(JErIZ#+I01HalQ!p{Mn7ZQNhKgA8mqn+k$N56QE6Ra|s|G3wF8T!}5*asq z9DX@uBKk3!#&D{|ysOxvb(>*%yL-(w#T#a}^W5vsD%KA+MKwNl`=2MLzY^b7BI!&& zv1Y66LS=tHugPuE^)VmL&)h8Isj~~y_5MjVHVc}(dZ68?&`7Giel1sLMIbmbr9h{w zW7hFdVr&UEr1_OYY@2ugT$V{spKnc}!y?GzY<7Nx>S}(ojXg<57qXkgqJ5J#G4bjc zp3RBIlpOQU$-m6?H9e7v@Au%>?oDtWO16Z=Wfio5$q9HmP5V>hwog0?`} zfx`Yw`3U#|igFW5!%~JR9rweIxO?NE;9D1L8s7SftCOhe0rgq@=tH7d4Df;O{*%V}@DUHg@>*4oLtn|eqOQ$Gv3zLVt+T61BY zyQ*zJ$SwE;ak$9;Bj)_2!F*Grzj=_E{@MutJLdeWz70wCz zhp3LW+;xAIQb^*nb~AWm-Jk;#%U)0NZA!+YjPme1&*?vsp3wtL<%n5Hi3!p38Rh+> zn&kCzX5Wt2nO_YzA2CwxW6Y-~Ejq>8@%f@v6pls3y-*CK6i_~Ibr(AHtlrxOrbF11 z|JkGG!_lb&j}Ioue}>LO47zoSL-jD|q;rasG+ZPncR>Pq<~W`2=1Y5jmdUQ6w8J1V zhv_>!8|^&lM}ljm=9do-%wkv+o9^-oq+>+NlMyXnn4&)K-a9rZnKFiz_`b5lpLM!E zpb=AVulJSy-Wm^JD)N`=2`=J(3B$qEt9~mjz(6k6Ruj&VsjMo%zz)W;vLuD*ut`af$ zV?6>NgYJ}uGp>(xEr7S+*XZhUVX&)@Y@O&2p4e$F?dz#Xwt&TfM7Fw8n4&l;ie4Z8kIs7 z;&ib;XlO_4*5)opHA)V5OrU5vlXcAwI zi8K;V=qn&=z2c{O&=qT{jT@9NO;YH3)2}h?^eSu1u2v`Z&b&d2jcT@Zt~A)*tFfgD z3EMT{vf}V}k8J$rU19*2;#wedCg z0E9MR5)_)s0&;J+9dCiNlg^ckx7W}OXdZ`}<-cw$EyX?3`-%L_?u$1%f;MLJLYMf% z+)7i@m`sySxH_J@MZ!t!f|4-0N2peJ{sathh4syw0x?VoV&6tMW&j-InXCxA=$TVf zF_!e+hV6{E)5Md*Fe1whI;F}^lFNTHx!K4h@LoM zv)O_n?Ro=#(I+ zJrJl^Z=1w*I=INuib7>_Vv0CZHCC!-T*3rHjYIKhod6x!8{N@;i7F)g`pGZ?TP6C@ z6u;RVpvr7agFl1z*Wq?0M^h{MWS{mNN*&^~bJ(vqVQF6wM7oXP;}m`}>y}FcN&0n4 zYl|r^?I|3l!vGqF(xl6JR+27LsG_)yoVgp@%tzZFLbGVMUf`K4dbnz7lVIsBlliB` z%WhP9l?2%qlzs%uEv$?&>Oks(driW)f-L-RzFLZLNUCYk7iuY#?KJV9Y$oBsyC0$8 zo5?N;9wmZ*TpTUXF?7EDl}sMXLDuQWo^WSU!%>(m*6>}{85C@cUjbsN7duN!D8G&e z!w#GK2Ab@7QIk?f<6qRZ=9gBZFub+>cIFiEqIN23bnB{2x@Q)Co=&Hb;s`{-Ii-h(b3obXs}h12MsZ%Z8 zi^Xg;ej}4|dS<@2PA-F4Bi99KF2@~d3%N%=y^f~7Qjv@N+D;!_Ft4#6(Ao^c(*Jmh z|0SLLT6CHn{DG_ldiqQS0c8oJ!Sb^Sz75IDXId%Xc z>9hB$N5^-uN!LLKOqe^Lk)CiH-4W`gwFs-+7*PmqS9MIZigcO_y}{NOdtOc>Lrfh@ z^eNFj-2_MHN$1OlCf1I#eT-Vf(kYpBm}oksEGwF&0{9#2M?`XpZ~KLol%q{SUQ)a= z-3;aqdO01oZW@{(DxY$^@?5EJsg}i_QCK=?hQyd+ybUR(EL!&J=oaLr+|NyfG0}PF z3v5J{TYtB$cp*#dveikbJkU1C$*OpBj*a-p z4Y<$Qq2@<#eY#T~b=|5sc8IrTg!96-Q7yKihmgA3n;xV(`Xzh_V8dqwg188YAd*9Q28t2$+TI zE{7QKS}J!r<&_D7qbx1BPz&I(i%# z5Rls{cF+$HgwLc8A*vjSCHHvsZdBl$XF>l)VBen|nL_%Jvsz?e)l&#Qs)1d*02VM~ zT2x$4xxd7%a#KBD;Qyo1^W zBqT8{D`)|i@aC5~p0rw4`)uL@!-re$xu*?O=v+e4iKYo-(q_2Fe{}o=_|eh1sPY>L zwPx`Rb@;3;3J$+Io03r+Z`v3E+!UL}c!wPq>P} zGo&{T7Q<$x=@w@Xw5Ffo{j<{f_6x9avTvH$Xhcm5~gzisHJAQ4(Q91RS1h4q`L;WHu^I# z>)I$5cc3}FNvzb9^?4sn+fC$+o^Zf@v|rIaN+Ev|q67Jd`(k;dnsEwRA*- zWfHEp%jbzMvr=i}1`NK5D#3?n^tRnduk%yNqWH6|rI*=3akgEFG2~;Czbc!a)&q9m zt^QeZubz5M2|mrfQTVW1>!R*uRK2KRZ&cmu?$Z$rq16}&zVXjNjXOY?1E0eZAfWXF z0VSRt!5>UYtqE2OBSf%dp2vMTWIM}pZszfE_XfW6^_GfmR0y4x*Y*b4=>_sM7sZ_~ zoQBB|_RrwW-34=elFn6tdkMlwp_%%pgE+4CZfdFoo}$ElJ8ExkaZ`fam$4}$7;Qot zguQG-8Vd+H&`MgqF;7;-rz3?vpSuCV~>>>FtLi}&FgyC;vDCWPGxc){7nEy@8 z?zdX10 zU4XpGA@HQiHu9Xxieu$-n!I_fNgNl+wD3RF1D{vnpUmo5yl*J=uw_}EL`%R2p30zL z{NYR&$$u|8xnsv{?4`e4|B==>G6w9dIGs9@)j6r_D)`i+=e^RU?TVl5OJ60yuP>B) z3;-$o_$yJZC@q$Aui0=SDPPGcD+5{O*Kl zt!SL^6uCsleO!1>zBQsddn9e^oaLe0ve77lK!H6CXIqCSzDD?>VLBwU(S;8-nfW7@ z`Gy!gCmtNpO$G|dPE>f=)xC1QqI%sZ^Zs1q`3K^F5o;D%OFOd3(Z=ezEj9@M&apL>Y^hs^| zW%pZ)Li`H<_hn2(`$}|fHVvW&`qNPXJJRWh~1W;qq;ENHkcf5&vBX<77{X# zG|Z5%z=V3#$EHEEERi>sy;$!@`QEmTS7vSn+Ymg7-Cgsjq3kyv&zo8xh^7MS{?j{& z(EhrgOf+==id9Hoj9Cvk;kGus;NP7Q;Pe?er zf32pfA*ZISfl5i&&AQt@N-vJVT100|Bwgn(393r!KMLzd;d z_Q5?`kJ2v2fJPC{=EDWs0_VXM)v+k*rV6 z1)h7=L6@h|SLtfKeY;W&o?Nb=C2!0giTVmz=?vQ)M`^i)%L=-7YfzPgRzUV0Gt&(- z_OGQCt0}0>rk0D{-nBD1=)sO-7HxGg%LN!%HpS@|D5!FAz}oTLX7erLG>9vT%%=CU zCiFYvU07a)!ZG6KeV!cnACP*{-mDPfkWUyuuMUlbI_|bE@RtTC1kIN!Xki3lGP+-< z_BLZk_rG|MlSS7>Q6;qnP*Ew_lt9zEo)Cv+B8Q5#MXd1=#`4lU3V;pE2KqPaqaHoD zRez7F{@l`}qs^=8GU&L=TgWejd`#NH{*B?0+Ucbg;Id$8F#3e6Hy1aT?l3*NrfW#) zCDK7F-%$%=m~cNC zd>>(0_x4FCX0cyUYH@Y(oV|nEjRmW0Q)O%EfI)2dljl7F^Ht4%!n1beXbYb2EA|8T zD*gN}C#0k$0MzF`4P3~s^CS7&RDn6YfZsD;Y(0u4ogf5DkwfEywH3HZ;59wfEo$!V z^>%Xo>iW!_biR#I&*=8bodP2Qj2iLS6f~IBM1x)7zcbIS#YJ-PvO;q=PhbU7XCYvs zPd8f5o~#sQ**;96!NHMB7R#-~qCP)3OI+>RJ@SKf%%i(07Xk-QM^nk1LUB5lA}TQ) z6@I5}WNcMMCi3991)zz=cyk3e$~#h|?y~8pSmv^z!F@V;vLbU^_|WC56p3=)j`rZj1BEiih>Lw z@jzHgb*Z8*hwORF?0v#s}@p;;E3@I4n&x*iO*` z$Y27LUU^&{Ms#EF<`?xcmn_35&GtAgZJXkqMh?o+Ug;KU3)(P_;2gQjl*;sITC6UI zKEhWWy;^psD}_p44g4$Nr(`5<5e<6a|ZN>V(#FNbcThdC4yJe%3X$Sxb+?ei8CVc=;u-n$y7e4v}2Li zcaJfZx zTFP9l9j4N~`~t>D#-yDu+BAbhWyP%Uq5%(d%gAD<{8pqSR6`Fn)fSL9k;8J1p)J!nu_2~uc;VnR!DKztg65XB;X>J?gOo1>#ld2714;v>cn4X@=vskWpg zIVEPLEerUpS!d8LEIPwW)|po(>S$J^pX?RwM0HQU3ca4nogP)AZ#(@8sLkC?Y^R|Z zC|Ly9HSQj*jdPhW^ccLeCNT1tkXebJT-=LVIE=rwCS5zRvBR6!RDr9W4 zM?%)CcD`nV$*Ath&t+A}(67l^ys#pToI=4T_Pe2|WRO>8+CO($EO2Gr796!o#T^T7 zn-}plJU21%DeL6RuCJsA)lH4^C_%l(Dz%F(J;`IGnMx}iUO9#gZQh;Uc@ApriMnF2 zqup>u^=KWbIxj8`ZGOsyP3s0XHzJt?6h*o0Z&s|Yi-~s$Q(vA1@VygX@@8~!28(;} zsN)33Z=zqc$8ZOkSKb3rp9_08H(%A@;UpPfWGxRcR4sn09e|Cqn!FI^4@Za4xuEjr zK$>f6_xk4nIG^1!bih^b4An!BK=cFw4?G!Pi67u8h<;B0h$(-G2MjEXe>3W_{6m}! z%fE?}`8$F5T~=BGivh;{Ur7P%IPbV>4TuNjSoifwDm?x@)|x!c*sMf{I`%;bjq(<` zM{YKhSosU*vl`^Hf#Ao|=;_!|{}i9HPf$tz>+R6a$-^|1^{KD7o==50cLmh->60F( z!JDQlfyYvq6TA$$_Li&uF;b5Ig|N`l>?1&4*2PWPi3@r5HF);PV;T5DSYAzCT(Ri= zCR+%g5A%Ib_ouU)JCCQP8<@;53T`}_r-FzKxU6alQoCWs~W^%59JWk#-WXl}R1>Xb$k7IoV z6B2+yU3th9OAE>>mBhM|X``7wJb>3($RX`0VqnF9Ve9%g>70q#lh>~$V7AO(MS7U2 zfyFLX!qb9X)Q!yogRWQZXbtBV!JsaWsjTt>r8;oTVDB(&dnKv(`8787Yr~ga6Io0k zR~dhQuKyT_JEV}qW0>}8z3xX%@Q&6np%a=0Ax{isE>z@fX87R(mcR_MwUS26-p9Cn zWPQp(lx(g8JfOuig#eyr;yv`#S9#iyP!#%GOCSABi6LtQIa8{8HpO2vG_ZYlc?rD2xoUEJu_zbG@qdX|cXEC~yF% zP5Q|C#`hRIJYWu$u_Vj|5+lGo)O?#mXOvKT7L{~#t>r9KJ}|UC3H>~%SY7D&4sjk2 z9k&#ZT}0;k;7^Q+uU~+Q5#?9^N(D86q-o zQVuk9d?99-%E_RAl{41&?9heaO{zWO zM!<>&5T?H+jZ{G%pO9tLf}y;QkW)Dwpoj!=VJ$V~4#mbhaiVZw$Xa)j_NNq?&#u{V z1IEWa!vnqkOL-0wupctl?3j+D zjDvDnAHOk!B{Kf)QdY%mms6Wzl>9h)7s5t;v177^KHYZP176}Z10!JN#n&fh_YTH@ zQNk=%i}`cu{ipio_^-u9PJLN)t8H6Il(yGSbi|(L2S3BrEXrxdm}1E@GOe5O*>IQh z$k+XD=2!ETSQ`b=Em?8m-zON>s5>Xz5%A9G&W%A}N>81C#-}#Cc3Ux_t+vF)4}k=! zwA|?gZ$FHlxI9T*?hts>$Kqt*6WzzDexSlyHk4wSlsTI$_-fO8F^K^80Zu202$g5z zy1;x$N*_OrbMboT?1?lWYYV$=FPkD&SRgs%36$Uk)0$g5B1}C)9064GM=GGhfNXoe zIcAhZlS(aoGylqVc9ysqH-* z%4|R^mB@-(B3!o(IfZ!qG=dCL*Eg4ldut=Yu%gu=15PW(4V%|wS7VzqQ zTz$;KKa+gZsuIEx#Ks7Si(-#Fd;2Y%TusOXBHihJuP#=vB0Sljc% zOxU&>St6RF7Vit8G(*vo^V|cCr)v>|+(JzaTX-Nr&E;=&``MVoj^>hwE4;lvES_%L z-{R|gDo6EuMuyRY+jfg(}Q`ph6emqivnfMjl5XP}Y6*da#0U$59>;UKs}s zjB-4?FS`)Ts~oeaNoc-0(xkUobSic2R!nNNK^+M=K?&M4lD7kLvXkIb|A*ng}1lHWCdze*C~0V zkT)cVtB^cGaiK2q24)RHwwDT65LGW1@;;FcNP4_r)#v+LJLK;QUrL;MVD?USwxA)N zu|bjsGP%|M(i6=@wF(zk&>v6BPmr=!hzz3T0vjc5`l?&c(rLt`8atzlTgfoEDq ze4Wjn1(s%cd4I&iw*Uvy2IvaL z0r%SJxSJfw!~(KsYur2sWty>aAi^Gw$iIyYFInq{*&8yAVQSEtJ9k;*~n0J2o)qVXbq+%%Zmo%ip zi}&(_l?JlXkjitydXD6!=#W@YXBX!!n`zJaO3T=-NT+iO7S~8Hh zuur9#2Z0tBIyvYQp}*J)9mt{9ET4Za*&R&NCbTwF0WCdkIxdJLo&Mn|J+Mr1VK5n> z&!Jh8(X7@SI+}|b#>1W`~ zHjaz!y12|G$};LGq_xv|wDBR7FF3cAGbicQCtADA6ROKD#AlbYok_yq@84bqr@2&=;&X{PdW}0LnDM?B3tChG%HG5@kzz!s8j); zm#+?5_4;E^9oaNiis|4wlf3RPUhbGsZu2?_KQy?Di@N>BjPQe|q?hg|*oJQume@ei zPuzW|u{9kRJ<*&u7zvIlmGrx~S@3A6u zJ$-BQ{BRZG;Yb7!wQCnbw!qA>La|zC1R(%vQr>(`@`=Whx7n_YJOOo-5ymz#58?Z% zuqZw~?31#I*>zaEvW z%HcHEU8+Hs{46GTSsbu4-tnv>z&(mT`Fg&tZy!Hz55ytVJL;enshvq12k!#80(4Ha z8i1vggh=6ac|}sv@x;?PhJT%o!&e4%E~feNo}medYS@mgA5JHkHx^j55*w<;4i`kTr&1NW$ zmunJi`A=G$!igVY#7`G@AHQkD!uT7wh3)dAgI{QXv_yvf3^b*XyFpn`9Bo&z%@S`~E0wqgRm8*ixWr-dzc*&ulrb+T}e zCq8L%QSgb(&InoB7RJN{3>E|U;c#jNm9vKsHSNkN%AR%^4-rIB7z0mU5a;~4D{CtS zXsB@{JiJ2vB3va>B6)qB&xA?ja)d-Q!jX>6Kypqp4P2S4i(HkPO-8!R2Kf+M9HQo0 z|A}`QaId1r?}Tlo;RI$iA?1#>DCkgLB^#IQ7ZQsm(p<@Y-FSPd0_(Y9jN+KmC{riQ z&DSsx#G0eEoM&{YIZA7>t?7ygb(~g|0#50KXOem|o2rG$&8opVK`(|vFF}V1o+-`1 ztIW|8ZiG}c#^W!xCjSFFS}Pp8;>*kteUUq3WFs@InvR|E5)E>Mt*)W zk45RRt-pARgj5I>p&NDv&VmwQu#GW0)*JVfNG=?H6;{-7P}j)y!|z^nt6!mt^TWL?RC%vCvMzR828A)a!4 ziQV+8Qw5oiRL7;2%oO}aaPWP;vsHcBKRE~M$jMG{x10yMzg{)L;I$mS>$UOLg5G zArD7I%cG%e6KJl$y?jF|oSftGw>~|RVpfNbM)2*DTh(Vk4@Q^9yfw2k`$flD%c*k6 z6VGlPSXZrlR)tBW{7hO}J_$=l@+>WJNNEn~iHAj=Ae33|N^p31eG*4oi2*iv4SSMd zLIT~{9Jbt^XAxu*SeMSTZpLw*POHCT@AjRv!+=|%?Le#Bky5=||2mj&oceTZ{67yFsC{L2sz?@Tp#aW};q)Cnx64Gvx%x_pVQTGJpyf zcl)BM>D^gg5ZP{F@!h~uvRW9?WLCYrC_e$!O!TAv5pDhwZobjxZ&52Oe=Ugp4Q*Ke zrMv#W;{8<3aGUS|NYDk+dOb z!Uz7#7UshWfQ@(eaO~)Nqj&W^L3848Ob`C;2%Onf%Z?iZ>*jsv@Tgz|!0YXA*%{y+SkMZHWhP*{5siz!s;T($w<9*J{d&iqZo`!}-rjRf zz+@Z>$w{;4^&Mvf#K;7fE)b36fO7ONo%rFiSSwyiHc(5&4FAL(srURvHah6?z=5h$%&-SyMtLV;hdM!zS{`jdX~3o3P1nI@Q%W zE;m3tR0)$4f#j2*%~WJ_v@DP>X5Q$Y5|~OvwFmuUKFK&)d{V5LyD|fAcb=}(H}y7? zUrZo|eN?W|7KdyAMT@dLc8MI5x^Ot&%{-nB=A*fNAVD>Weu5bB&w{ zx1tCo7|NQbpidTd`mg?K4ylPx=SH&f)V*VpxpFn5BLO6=DTGHjGAonlVoDlacD-A_7tkir1L?%07}5vjVLAh(=CI(R>xMM~5G)w6;G7qI-Wxf+9P*s% zQY6_mP`k&;kSmw8qH<3RS-F{?|TZWVf9|>Nprj%`9 zU1SuwN^5&3Z!q;Rb!0FN&w4)uY+QwH=mf&M_E2`Y)3RwG~o7Fh^THxFRwXy(I+>t{FR^-2=zC!U&?% zYHw}a(az3@om9*OAF)*+5}_w6L3do-G#ZQ;HBmT3E7`=?MEP9~m}%}ytQezj)jyIY z8v8P-4>2CCb(wFPAY9L1yDTYFP=zE)!(X45^Y&V|D*!sG`EX(mhQC8QHd8Ca7Ka)ob2;Jy*4ReGyI@$Z!H^Q|4Sa`8t>qPu<1JK&_vx5zE^zkR7 z-hJTLT>G#w)L%f`)Rk}^f)2IyPVON8?jly{Y~vMjUbfq^lXPy^AWq@eeLjW4k)<17 zCtApn5$`wrJfsX;%aMFzC+*7lz|v$gIrXeN+qaZ#t0;UdxFTgBQ7>6dRGBzfI)GL} zAR3|#rovBv}6&b8PAX<-&Q-N_;` z0(kRg+(e-#R(J)cLF2x#zQel!#`ab4enWd5m|3GO1y$??_r=oT+wuQ_B8HNr(ru7C zG)z&GUDZjrSz=^1%u*BXeBvgchmqK4`3|)6UI&YNn_V`# zY}>YN+v>8qY}+=vY~5OWpLJv1h!t`6eaei;e9eF49COTX+{J7Y=4pF9+9Y8g&TKAi z-feT8%pdvMUtL!Gn}+>InEva`G5^DvWBZqLeYU^cy8kOKOzXclDgQ^q3TUw*{?APc z*opqERtu;H#ms+hQjA`t9hiPJaIeClrHxw9CJ>bmi*s2v*S$QQ=0@-GqwWl`w!XX` zo-XII`G%_edU-vb-+d@&d@lojd3k+1I!@dK@O|CCgL|xA_cw=LNw27OIhsLh1m06= zq+Q7t{AB+WEiuo;&C-nIK0hejHFbjTy%t0P1Y6tI^>z1f_kK-kD6-gSPFF`_spR!+ zD%Du(`+c&q#7(RPbJO2={5!x}0j>v08DqToI%+#e7J3Kt4pHNfS$fzo@;%KO8s==`$_ki=k167Th6)KjhY3x~^9bBmia3)H@jx}9}>Bv$Zq|rtO=+HIQzzWy zY^m-SQQEE3uJkbVeDO0STShY#CKEbjCbW!h+rqrro$f>1*@Dcn(+v^qp~*Qz6i;z0 zg&>e$%+oi-fBMD4gWaU|wGWg0nzS-!17fUICs12f^g|Hl;5+=P4%|bPbpY3j}W9$r-P)NH-e$WNkAWD@z1cgQOU=HaV(V3 zQA8JU&C%ikVcD)&akxgOWn2`m_ueqjVsolB7*{9EEQgNa*WtZB2;RwwU`R^M=Z0ia zV9>*GE=ZF?$jxS)8L!5nm zRpTqQ$RfC4Fr3E*96Okr4!m$lJmAY*r(2DGH#0Iy+KDD%Q{JDj5uq>`;9!EhZA+4j z)GevFyVYuoQgQ1&hHjM+8;@Mr=t>A1%k?K40K-dNwL91vu#&1WefhMTC@~^PyAAh@ zMx1J$U(qms*JFe4w<=4&d&g$P4tDs-F=3t-Vi+Qv$lw}$d}KeRgmXeS4wV30*r+b& zAW^?8TNdepmI}vXlVqxqv5&Os5ONTg>7tjKko7WUDFLT)_jw+8u#s_qpnrVmOfsx3 zG!aZT5UjFj<;6auf5otj@MjLhrO3!sN(YFVNk|up+n9br?o7S5Yd$$UjIb&; zzZX`u50@vsAJa!j;+Jw4C_kj#MHfRJ+k`eZ? z{K}H!*@wUt4HL+oZ!dDSG#ic@%8VN}09s9;_yw7=Dy`n8vmXUsj04c`KQ@k_Xx<8a z&c-#C8tCKNn&Tamj+Q8kqaJ0Mug)wPkj-35C4aFwz=&Cu5KTi?jeus*qUf_oqLt zwDZWULMjud>AO@62hr~QScSvf-Z-h%TvOXDG3heZLltA+-b%O5SIxT7yJ0G)x^u>2 ziJH^G1bi?M4a6Kj%~8&|U|<4shu?`JU_|LmooEhSqUgqrBonEh9s9Fs>YS7P< zo!%x$kqr3vzH)obHZjmmT5rj9Gak6~W?gfdTe9b@zO-CEu~b*`=eh<8u__P1W3yv} zz*1#L2QT9I@jIDtAG1z;0`rh;oClw2KHXoZ&*RicDlXBS4v)GsBCCAuq{8a#nCyCwWz_nlOgR@n?fnz{KGVaXp@Q;=d zZT?mM{@y?_vT^>Sjfd@DFaT`-8wTLN`RnQ0>+cax0e&0|22hfW^S-$UfS1POyjcJq zwEa7Oolt-mL(09%)12A+oxk2!CwjOcepyXf5xBb==a26B4QFHszUuXHdwVW7xxHIu z*8Ta?;OQAJWG!PTxD(d0otYb30m$<$e-O1b$%Pmj3{r0+NP?8fTSVfA}7xs=- z6mlp`Dlu_7tKblsUf%=Ff#t=pOx63b+(8DePsXKyi$l1T@)|N3jS%|#lzo6u>3hon zq+(qM^>lj4qFPV7G1dWcVpS8{&RfNK0hC7p03P^9+3(nUoWCmIL00NRlCj=n>uB6F z5rRt{Pf_8pNuS}^pLhXTyvp3nlf70|S$YOAh2AG|vXNam6*KL)^9}~b8j?%}y)t%l zIN|9$pJ-#%-H%67`;B|GZ19=%X8t&Rc@`bPzswD z2jB>L&iQ9&5gMI#o-Leng+W2JQ=Xq9JtIlGNC49Hu^NDKm6$b;;E*7`be#dhh@u6Le53a5y|v=h^@I&b-{YBxf4U;QX}HbrDZYC|(-FbX;U_4O^-s zW;hEe{Df^W#W-BE{NPQS-O)QbbAWEf{+o>WMFHM*7B!wju z9A7TVLavACX~dcorahRf5-<5DLgO64F$xunS9r=hU3#iZVWPZ&$@57g{0PvX0EgksF}zo9)5hE^8i;GdEcGGHE?`REd`@l*s1Bf~%!U zWDUqo*ax9JMjBq@y*VeJ`=DD&RLEJTr)>AC#(U6=sowTkOxMc!UMm(6igDZ{1>)tmIJ_Z} zuoP$3*Vz^*?EMAGwcJlaGFl~vg!9|0oI6wWmALC+k&K`_yasPeu-6>t<$gPs;Ksw5 zqCzk1oSUhOQD16()FZETgPE?Ze$vOP1}1`q5-dOeDs-=dx1 zB?Lpe16W_*LB#6f1=1Ado!zfBPuJRia8$*RslA)dqvT21dy~u7(}6vBEOsfAXI*Gn z9?MA@j6>Ki^^4*B_ASbEigvBVVeJ32p{%rrFcz7PJbPp_ZVNATB#@EwBysKTiI0QM zo;~l0QyJMJ4}jFb^}6s5ZnP}9|I+;F zLW@KY5kOXcIGkAf|3~G3Px1wx=6-Ku!b$RSB%#0ROFTyxPf{TRuWRzctGf^^N1>`2SOiUUmC z8&yiN)`VtlDzIa^*>gTCz}xL$e+Od=#-ruQ>!RDLlHeH6G;KA$peJ!Xw=Rli-}EE; za`YQ(>$m5jhcA#>^xuNmd-2k!#-1T9P%me`WdsVLXx1kBP5=_P4RhSzBFazR?ToN3 zYhg5!h2oAne8R)dc&n$Q3uXE&l$ovfqo(F5RAM>ZyVd||7#1!#*3BiJOCYn z?)g4)#c`X54-P&?{Y<5zlA_T?Uc3ihl?({%-^DAoT);}z_j20ssR7Ygg?#LAxcjx*&?%C*En1+4<~m1(m*Fi2);BPoks5Vr^S<&#Q5Hfhpl5&qsyfKuA59 zGW(Ds)BE%EQJTro3Cxqi*ddM$3vi7E3T5U`B2M00KQ$%%>y|W?P#Vq>%rAZ$39pT` z>h+ZUHr4qBx@$8eIBl`0Q`4KhkcS|>qs_Vis2-YQDLlwGceJ&OGZ*qCE zBx=9(5vBkK3n;cShd|0J+ly%7;L|tUuKLb#@r!8oj2*Gm>``f!-u(1ksMWz!wma)Z z2#UXF!(&wc0nCFn_Arz(3@<5wOw z!#AwzY7XBw;U8fRtE67G3eAdAd+|ShgmTRJ zvmp|1=Tk>nB)Gi8kouHTFv+riZoeqg*8`_QK8FKayRYE;@ygw7i3<|>!nd>uFbU3O%!W5Pn>7siqySX1tB*DD zN^WA#LuF~1d!So$Gc?ZLaC}lsU{k}fs2Kc&w|&wy67cl%zoz}4UKv;I7KVM4sGh` zTuK!0W9lXp8OKI64%>@`QWre^KmC{N1T0A)RL3p_BKh5%m+l3YhHWvainhR)s_bQp zd{m0k!lJ*N6(p#JZlc)XV0TQDD`P`N?eX_+><+tvkC||<<@sjaQg}^n*cG`E0cPHIP__jE z{KS389aixezIE@1e!W;BK|5nT`~d3**1D~9ed>gf8O7B-b;nfRjbfec>%0Wl`EYYW z%_A|Szwd;}2b~C#YA~Pw^#D61{#Fql2N0mJXK7esNHG0(CHZaV;{Ts{RU60M4 zL~(C_Uz}_Yk?o83y#w)iI$)z!)u#L7=K5SN)3;Bl{^fDG|MMjuwROS&>+St7H+K!7 z`}NKeyu$}Nd*!JecwKlN^71R-q}Qe3wCOZxfV4uXW}7WLNVokNLYba>Mi*$zUUx#( z)j-_SJ>1IkdQO`>dHH5x{Rf^$_&7?p(Zeo+_4cjeLS~Z0c{0vx^`&y4oO+|l=*^Bb z2YVO1T3r{`5}v28_U_^iY|>;9FdveS+GkKI)Vi%Pxy;x49XYtwFry9r>vuB!_ zxoETAeADAyrP21As%Z9t@Hf#y%`LB@eS9~3JRGxlbX*eX1e#HUF|z0eeN@l-LiF9N zH+|x^L}x|2I+m1asHfWnTUc*D7t7*Uga?)@xOEi48XQpbFhwZFXnUH%Y4Sc!56X^gv-l=QO%BJ2cMV?~Q%Er`i*r?cdHNo>cl ztKRQ%i;{H!)Y0O>Oq?7tptIh1cnLvLvo3eUNVqjAg}vF0iu@ZH>kQ~8dW(3|0k5?;OCATi1v522o}t3He% zuZMpfl|cw@&42;6O$g~A@yRpA>It?Z{FxC6fp`qyRx|f2Cx*jJTq0ZC(VN(>{Lj0G z^Z~RM@VcC)6EZDRbd+jW44PzzADXP0`&FYvcCXoAJ@e(+b#pa$1M`khkXqd20(W# zmK8u=#C*3QszpI$5BmoRKt1iihH7C1kp-q6bw3EfLp_t=gil%gym={RJNQh(>HI`XUtNe~N|`+oO4z|b4{L-?g!Y}n4Mkey*~eD- zS<%g{4J=paNk{D|YDyXAR)h$`bV(-08ANtV6qCnYBNvd3U2^sj&*jLMPR>JV08Xqp zX~91#oa+5z)^maQ?heWhhtR+*m_w!∈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

+We+cQ&G0} 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/PostSecurityTests.sh b/SecurityTests/PostSecurityTests.sh new file mode 100644 index 00000000..a2d7898d --- /dev/null +++ b/SecurityTests/PostSecurityTests.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +# PostSecurityTests.sh +# Security +# +# Created by Fabrice Gautier on 6/9/11. +# Copyright 2011 Apple, Inc. All rights reserved. + +echo "PostSecuritTests.sh: post-run script" + +echo "Killing all servers..." + +killall openssl +killall gnutls-serv +kill `cat tcprelay.pid` + +echo "Done killing~~" diff --git a/SecurityTests/PreSecurityTests.sh b/SecurityTests/PreSecurityTests.sh new file mode 100644 index 00000000..1178c6e5 --- /dev/null +++ b/SecurityTests/PreSecurityTests.sh @@ -0,0 +1,59 @@ +#!/bin/sh + +# PreSecurityTest.sh +# Security +# +# Created by Fabrice Gautier on 6/7/11. +# Copyright 2011 Apple, Inc. All rights reserved. + +echo "PreSecuritTests.sh: pre-run script" + +# Use this for macport install of gnutls: +#GNUTLS_DIR=/opt/local + +# Use this if you compiled your own gnutls: +GNUTLS_DIR=/usr/local + +# System openssl +#OPENSSL_DIR=/usr + +# Macport openssl +OPENSSL_DIR=/opt/local + +# your own openssl +#OPENSSL_DIR=/usr/local + + +echo "Starting servers" + +echo "openssl s_server RSA/RSA..." +${OPENSSL_DIR}/bin/openssl s_server -accept 4445 -state -key test-certs/ServerKey.rsa.pem -cert test-certs/ServerCert.rsa.rsa.pem -www -cipher ALL:eNULL > /tmp/s_server.rsa.rsa.log 2>&1 & + +echo "openssl s_server RSA/ECC..." +${OPENSSL_DIR}/bin/openssl s_server -accept 4446 -state -key test-certs/ServerKey.rsa.pem -cert test-certs/ServerCert.rsa.ecc.pem -www -cipher ALL:eNULL > /tmp/s_server.rsa.ecc.log 2>&1 & + +echo "openssl s_server ECC/RSA..." +${OPENSSL_DIR}/bin/openssl s_server -accept 4447 -state -key test-certs/ServerKey.ecc.pem -cert test-certs/ServerCert.ecc.rsa.pem -www -cipher ALL:eNULL > /tmp/s_server.ecc.rsa.log 2>&1 & + +echo "openssl s_server ECC/ECC..." +${OPENSSL_DIR}/bin/openssl s_server -accept 4448 -state -key test-certs/ServerKey.ecc.pem -cert test-certs/ServerCert.ecc.ecc.pem -www -cipher ALL:eNULL > /tmp/s_server.ecc.ecc.log 2>&1 & + +echo "gnutls-serv RSA/RSA..." +${GNUTLS_DIR}/bin/gnutls-serv -p 5556 -d 4 --http --x509keyfile test-certs/ServerKey.rsa.pem --x509certfile test-certs/ServerCert.rsa.rsa.pem --priority "NORMAL:+ANON-DH:+NULL" > /tmp/gnutls-serv.rsa.rsa.log 2>&1 & + +echo "gnutls-serv RSA/ECC..." +${GNUTLS_DIR}/bin/gnutls-serv -p 5557 -d 4 --http --x509keyfile test-certs/ServerKey.rsa.pem --x509certfile test-certs/ServerCert.rsa.ecc.pem --priority "NORMAL:+ANON-DH:+NULL" > /tmp/gnutls-serv.rsa.ecc.log 2>&1 & + +echo "gnutls-serv ECC/RSA..." +${GNUTLS_DIR}/bin/gnutls-serv -p 5558 -d 4 --http --x509keyfile test-certs/ServerKey.ecc.pem --x509certfile test-certs/ServerCert.ecc.rsa.pem --priority "NORMAL:+ANON-DH:+NULL" > /tmp/gnutls-serv.ecc.rsa.log 2>&1 & + +echo "gnutls-serv ECC/ECC..." +${GNUTLS_DIR}/bin/gnutls-serv -p 5559 -d 4 --http --x509keyfile test-certs/ServerKey.ecc.pem --x509certfile test-certs/ServerCert.ecc.ecc.pem --priority "NORMAL:+ANON-DH:+NULL" > /tmp/gnutls-serv.ecc.ecc.log 2>&1 & + + +echo "tcprelay..." +/usr/local/bin/tcprelay localhost:4445 localhost:4446 localhost:4447 localhost:4448 localhost:5556 localhost:5557 localhost:5558 localhost:5559 > tcprelay.log 2>&1 & +echo $! > /tmp/tcprelay.pid +cat /tmp/tcprelay.pid + +echo "Logs in $DIR" diff --git a/SecurityTests/SecurityDevTests-Info.plist b/SecurityTests/SecurityDevTests-Info.plist new file mode 100644 index 00000000..5f47d229 --- /dev/null +++ b/SecurityTests/SecurityDevTests-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.apple.security.${PRODUCT_NAME:identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleShortVersionString + 10.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSMainNibFile + MainWindow + CFBundleName + SecurityDevTests + + diff --git a/SecurityTests/SecurityTests-Entitlements.plist b/SecurityTests/SecurityTests-Entitlements.plist new file mode 100644 index 00000000..7fb6baf3 --- /dev/null +++ b/SecurityTests/SecurityTests-Entitlements.plist @@ -0,0 +1,42 @@ + + + + + com.apple.private.CoreAuthentication.SPI + + keychain-cloud-circle + + com.apple.keystore.access-keychain-keys + + com.apple.keystore.lockassertion + + com.apple.keystore.device + + restore-keychain + + migrate-keychain + + modify-anchor-certificates + + com.apple.springboard.wipedevice + + application-identifier + com.apple.security.regressions + keychain-access-groups + + com.apple.security.regressions + lockdown-identities + apple + + com.apple.private.ubiquity-kvstore-access + + com.apple.securityd + + com.apple.developer.ubiquity-kvstore-identifier + com.apple.security.cloudkeychainproxy3 + com.apple.developer.shared-web-credentials + + localhost + + + diff --git a/SecurityTests/SecurityTests-Info.plist b/SecurityTests/SecurityTests-Info.plist new file mode 100644 index 00000000..ec50ce26 --- /dev/null +++ b/SecurityTests/SecurityTests-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.apple.security.${PRODUCT_NAME:identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleShortVersionString + 10.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSMainNibFile + MainWindow + CFBundleName + SecurityTests + + diff --git a/SecurityTests/StartTLSServers.sh b/SecurityTests/StartTLSServers.sh new file mode 100644 index 00000000..7f8c95bb --- /dev/null +++ b/SecurityTests/StartTLSServers.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +# StartTLSServers.sh +# Security +# +# Created by Fabrice Gautier on 6/7/11. +# Copyright 2011 Apple, Inc. All rights reserved. + +# Use this for macport install of gnutls: +#GNUTLS_DIR=/opt/local + +# Use this if you compiled your own gnutls: +GNUTLS_DIR=/usr/local + +# System openssl +#OPENSSL_DIR=/usr + +# Macport openssl +OPENSSL_DIR=/opt/local + +# your own openssl +#OPENSSL_DIR=/usr/local + + +echo "Starting servers" + +echo "openssl s_server RSA/RSA..." +${OPENSSL_DIR}/bin/openssl s_server -accept 4001 -state -key test-certs/ServerKey.rsa.pem -cert test-certs/ServerCert.rsa.rsa.pem -www -cipher ALL:eNULL > /tmp/s_server.rsa.rsa.log 2>&1 & + +echo "openssl s_server RSA/ECC..." +${OPENSSL_DIR}/bin/openssl s_server -accept 4002 -state -key test-certs/ServerKey.rsa.pem -cert test-certs/ServerCert.rsa.ecc.pem -www -cipher ALL:eNULL > /tmp/s_server.rsa.ecc.log 2>&1 & + +echo "openssl s_server ECC/RSA..." +${OPENSSL_DIR}/bin/openssl s_server -accept 4003 -state -key test-certs/ServerKey.ecc.pem -cert test-certs/ServerCert.ecc.rsa.pem -www -cipher ALL:eNULL > /tmp/s_server.ecc.rsa.log 2>&1 & + +echo "openssl s_server ECC/ECC..." +${OPENSSL_DIR}/bin/openssl s_server -accept 4004 -state -key test-certs/ServerKey.ecc.pem -cert test-certs/ServerCert.ecc.ecc.pem -www -cipher ALL:eNULL > /tmp/s_server.ecc.ecc.log 2>&1 & + +echo "gnutls-serv RSA/RSA..." +${GNUTLS_DIR}/bin/gnutls-serv -p 5001 -d 4 --http -a --x509keyfile test-certs/ServerKey.rsa.pem --x509certfile test-certs/ServerCert.rsa.rsa.pem --priority "NORMAL:+ANON-DH:+NULL" > /tmp/gnutls-serv.rsa.rsa.log 2>&1 & + +echo "gnutls-serv RSA/ECC..." +${GNUTLS_DIR}/bin/gnutls-serv -p 5002 -d 4 --http -a --x509keyfile test-certs/ServerKey.rsa.pem --x509certfile test-certs/ServerCert.rsa.ecc.pem --priority "NORMAL:+ANON-DH:+NULL" > /tmp/gnutls-serv.rsa.ecc.log 2>&1 & + +echo "gnutls-serv ECC/RSA..." +${GNUTLS_DIR}/bin/gnutls-serv -p 5003 -d 4 --http -a --x509keyfile test-certs/ServerKey.ecc.pem --x509certfile test-certs/ServerCert.ecc.rsa.pem --priority "NORMAL:+ANON-DH:+NULL" > /tmp/gnutls-serv.ecc.rsa.log 2>&1 & + +echo "gnutls-serv ECC/ECC..." +${GNUTLS_DIR}/bin/gnutls-serv -p 5004 -d 4 --http -a --x509keyfile test-certs/ServerKey.ecc.pem --x509certfile test-certs/ServerCert.ecc.ecc.pem --priority "NORMAL:+ANON-DH:+NULL" > /tmp/gnutls-serv.ecc.ecc.log 2>&1 & + +echo "openssl s_server RSA/RSA + Client Side Auth..." +${OPENSSL_DIR}/bin/openssl s_server -accept 4011 -verify 3 -CAfile test-certs/CACert.rsa.pem -state -key test-certs/ServerKey.rsa.pem -cert test-certs/ServerCert.rsa.rsa.pem -www -cipher ALL:eNULL > /tmp/s_server.rsa.rsa.csa.log 2>&1 & + +echo "openssl s_server RSA/ECC + Client Side Auth...." +${OPENSSL_DIR}/bin/openssl s_server -accept 4012 -verify 3 -CAfile test-certs/CACert.rsa.pem -state -key test-certs/ServerKey.rsa.pem -cert test-certs/ServerCert.rsa.ecc.pem -www -cipher ALL:eNULL > /tmp/s_server.rsa.ecc.csa.log 2>&1 & + +echo "openssl s_server ECC/RSA + Client Side Auth...." +${OPENSSL_DIR}/bin/openssl s_server -accept 4013 -verify 3 -CAfile test-certs/CACert.rsa.pem -state -key test-certs/ServerKey.ecc.pem -cert test-certs/ServerCert.ecc.rsa.pem -www -cipher ALL:eNULL > /tmp/s_server.ecc.rsa.csa.log 2>&1 & + +echo "openssl s_server ECC/ECC + Client Side Auth...." +${OPENSSL_DIR}/bin/openssl s_server -accept 4014 -verify 3 -CAfile test-certs/CACert.rsa.pem -state -key test-certs/ServerKey.ecc.pem -cert test-certs/ServerCert.ecc.ecc.pem -www -cipher ALL:eNULL > /tmp/s_server.ecc.ecc.csa.log 2>&1 & + +echo "gnutls-serv RSA/RSA + Client Side Auth...." +${GNUTLS_DIR}/bin/gnutls-serv -p 5011 -d 4 --http --x509keyfile test-certs/ServerKey.rsa.pem --x509certfile test-certs/ServerCert.rsa.rsa.pem --priority "NORMAL:+ANON-DH:+NULL" > /tmp/gnutls-serv.rsa.rsa.csa.log 2>&1 & + +echo "gnutls-serv RSA/ECC + Client Side Auth...." +${GNUTLS_DIR}/bin/gnutls-serv -p 5012 -d 4 --http --x509keyfile test-certs/ServerKey.rsa.pem --x509certfile test-certs/ServerCert.rsa.ecc.pem --priority "NORMAL:+ANON-DH:+NULL" > /tmp/gnutls-serv.rsa.ecc.csa.log 2>&1 & + +echo "gnutls-serv ECC/RSA + Client Side Auth...." +${GNUTLS_DIR}/bin/gnutls-serv -p 5013 -d 4 --http --x509keyfile test-certs/ServerKey.ecc.pem --x509certfile test-certs/ServerCert.ecc.rsa.pem --priority "NORMAL:+ANON-DH:+NULL" > /tmp/gnutls-serv.ecc.rsa.csa.log 2>&1 & + +echo "gnutls-serv ECC/ECC + Client Side Auth...." +${GNUTLS_DIR}/bin/gnutls-serv -p 5014 -d 4 --http --x509keyfile test-certs/ServerKey.ecc.pem --x509certfile test-certs/ServerCert.ecc.ecc.pem --priority "NORMAL:+ANON-DH:+NULL" > /tmp/gnutls-serv.ecc.ecc.csa.log 2>&1 & diff --git a/SecurityTests/StopTLSServers.sh b/SecurityTests/StopTLSServers.sh new file mode 100644 index 00000000..ab7add28 --- /dev/null +++ b/SecurityTests/StopTLSServers.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +# StopTLSServers.sh +# Security +# +# Created by Fabrice Gautier on 6/9/11. +# Copyright 2011 Apple, Inc. All rights reserved. + +echo "Killing all servers..." + +killall openssl +killall gnutls-serv + +echo "Done killing~~" diff --git a/SecurityTests/clxutils/ChangeLog b/SecurityTests/clxutils/ChangeLog new file mode 100644 index 00000000..3d677618 --- /dev/null +++ b/SecurityTests/clxutils/ChangeLog @@ -0,0 +1,40 @@ +As of April 9 2003, the clxutils directory will be tagged +with the version of Security.framework with which the +particular version of clxutils works. When a change +is introduced into clxutils which prevents the tests +from building or running with previous version of Security, +an entry will be made in this file and the whole directory +will be tagged with the same tag as the version of Security +needed to run with the current version of clxutils. + +Addenda: tags are now of the form clxutils-XXX since the Security reorg. + + Date Tag Notes +-------- ----------- ----------------------------------------------- +04/04/05 TigerGM TigerGM (8A428) baseline. +02/19/05 clxutils-111 New tests for AppleCerts, AppleCodeSigning, localTime, + iChat policy. + Support for SHA2 signature in signerAndSubj. +12/20/04 clxutils-110 Updates to smimePolicy for radar 3880193 (iChat TP policy mods) +11/01/04 clxutils-109 Fix for radar 855635 - CSSM_CERT_STATUS_IS_IN_ANCHORS missed + if cert is from a DLDB +09/14/04 clxutils-108 Radar 3722218 - CertGroupVerify can now return + CSSMERR_APPLETP_HOSTNAME_MISMATCH. +08/12/04 clxutils-107 CSSMOID_APPLE_TP_CODE_SIGN trust policy testing. +07/21/04 clxutils-106 OCSP and major mods to certCertify() and certcrl program. +05/13/04 clxutils-105 Radar 3537553, SPI for ASN.1 encode/decode. +05/04/04 clxutils-104 Mods for AuthorityInfoAccess extension +04/28/04 clxutils-103 Mods for Radar 3636036 - errSSLConnectionRefused +04/20/04 clxutils-101 Extended Key Use testing per 3622077, 3628039 +04/20/04 clxutils-100 Tag for just before changes for Extended Key Use in clxutils-101 +08/05/03 Security-132 Unnormalized subject/issuer names, 3347430 +07/16/03 Security-119 Add testing for 3300879, expired root handling +06/16/03 Security-114 Mods for updated SSL host name checking, 3093245 + Test resumable session SPI, 3260631 +05/16/03 Security-102 Fixed corner cases in SSL HostName checking + SecureTransport vfy via SecTrust, SSLGetPeerSecTrust +04/24/03 Security-90 S/MIME policy testing +04/17/03 Security-88 Support for buildit + Was nssOidToAlg, is cssmOidToAlg + Run cgVerify with DSA certs +04/09/03 Security-87 Partial DSA public key processing diff --git a/SecurityTests/clxutils/Makefile b/SecurityTests/clxutils/Makefile new file mode 100644 index 00000000..f6d1b5ad --- /dev/null +++ b/SecurityTests/clxutils/Makefile @@ -0,0 +1,92 @@ +# +# Top-level Makefile for clxutils. Allows build or clean +# of all directories in one swoop. +# +SHELL := /bin/zsh + +SUBDIRS= clAppUtils anchorTest caVerify certChain certInCrl certTime certcrl \ + certLabelTest certSerialEncodeTest certsFromDb cgConstruct \ + cgVerify clTool cmstool \ + dotMacArchive dotMacTool extendAttrTest extendAttrTool \ + extenGrab extenTest extenTestTp extractCertFields findCert \ + idTool kcImport kcExport kcTime kcTool keyFromCert \ + newCmsTool ocspdTool ocspTool pemtool \ + parseCert parseCrl pemtool secTime secTrustTime \ + signerAndSubj signerAndSubjSsl \ + signerAndSubjTp smimePolicy sslAlert sslAuth sslBench sslCipher \ + sslEcdsa sslHandshakeTime sslProt \ + sslServer sslSession sslSubjName sslViewer \ + sysIdTool threadTest trustAnchors trustApps unBER \ + vfyCert vfyCertChain +# krbtool removed pending new kerb changes +# krbtool + +# note the p12 tests removed - I really want p12Reencode back in...p12 we can do without +# extractCertFields idTool kcImport kcExport kcTime kcTool keyFromCert pemtool p12 p12Reencode \ + +INSTALLDIR=$(DSTROOT)/usr/local/bin + +# default SRCROOT for clean target +SRCROOT ?= $(shell pwd) + +# +# The "if [[ -a $$i ]]" allows use of this Makefile on a fragment of +# clxutils, e.g., the SslExamples package built by buildSsl. +# +first: + @foreach i in $(SUBDIRS); \ + if [[ -a $$i ]] then; \ + echo "=== Making $$i ==="; \ + cd $$i || exit 1; \ + make -r || exit 1; \ + cd ..; \ + fi; \ + end + +build: first + +sphinx: + make "SPHINX=-DSPHINX" + +# architecture options + +64bit: + make "DEBUG_CFLAGS=-arch x86_64" "CMDLINE_LDFLAGS=-arch x86_64" + +64bitFat: + make "DEBUG_CFLAGS=-arch x86_64 -arch i386" "CMDLINE_LDFLAGS=-arch x86_64 -arch i386" + +fat: + make "DEBUG_CFLAGS=-arch i386" "CMDLINE_LDFLAGS=-arch i386" + +install: + @foreach i in $(SUBDIRS); \ + if [[ -a $$i ]] then; \ + echo "=== Installing $$i ==="; \ + cd $$i; \ + make install "DSTROOT=$(DSTROOT)" "SYMROOT=$(SYMROOT)" \ + "OBJROOT=$(OBJROOT)" || exit 1; \ + cd ..; \ + fi; \ + end + install -d -m 0755 $(INSTALLDIR) + install -p -m 0755 cltpdvt $(INSTALLDIR) + echo "** BUILD SUCCEEDED **" + +# this module doesn't need to install any headers +installhdrs: + +installsrc: + cp -R . $(SRCROOT) + +clean: + @foreach i in $(SUBDIRS); \ + if [[ -a $$i ]] then; \ + echo "=== Cleaning $$i ==="; \ + cd $$i || exit 1; \ + make clean "DSTROOT=$(DSTROOT)" "SYMROOT=$(SYMROOT)" \ + "OBJROOT=$(OBJROOT)" "SRCROOT=$(SRCROOT)/$$i" \ + || exit 1; \ + cd ..; \ + fi; \ + end diff --git a/SecurityTests/clxutils/Makefile.cdsa b/SecurityTests/clxutils/Makefile.cdsa new file mode 100644 index 00000000..73b21dd8 --- /dev/null +++ b/SecurityTests/clxutils/Makefile.cdsa @@ -0,0 +1,165 @@ +# +# Common makefile fragment for dmitch's clxutils. +# This is -included from project-specific Makefiles, assumed +# to be one directory down from this file. +# +# See Makefile.template for sample project-specific Makefile. +# + +# Defaults for variables provided by buildit +# +# Object files written to '.' unless OBJROOT specified +# +OBJROOT ?= . +SRCROOT ?= . +# +# Executables written to SYMROOT if specified, else to LOCAL_BUILD_DIR +# env var if specified, else to '.'. +# +SYMROOT ?= $(shell echo $(LOCAL_BUILD_DIR)) +LOCAL_BUILD=$(SYMROOT) +ifeq "" "$(LOCAL_BUILD)" + LOCAL_BUILD = . +endif + +# independent of SYMROOT +CLEAN_DIR=$(shell echo $(LOCAL_BUILD_DIR)) +ifeq "" "$(CLEAN_DIR)" + CLEAN_DIR = . +endif + +# +# DSTROOT only used for install +$ +DSTROOT ?= "" + +INSTALLDIR := $(DSTROOT)/usr/local/bin + +UTIL_LIB_SRC= ../clAppUtils +COMMON_LIB_SRC= ../../cspxutils +CSPUTIL_LIB_BIN=libcsputils.a +CLUTIL_LIB_BIN=libclutils.a + +# cspxutils headers and lib come from ../cspxutils, or from /usr/local if DSTROOT is specified +ifeq ("", $(DSTROOT)) + UTILLIB_HDRS=$(COMMON_LIB_SRC) + UTILLIB_PATH=$(COMMON_LIB_SRC)/utilLib + CSPUTIL_LIB_BIN_PATH=$(LOCAL_BUILD)/$(CSPUTIL_LIB_BIN) + CLUTIL_LIB_BIN_PATH=$(LOCAL_BUILD)/$(CLUTIL_LIB_BIN) +else + UTILLIB_HDRS=$(DSTROOT)/usr/local/include + UTILLIB_PATH=$(DSTROOT)/usr/local/lib + CSPUTIL_LIB_BIN_PATH=/usr/local/lib/$(CSPUTIL_LIB_BIN) + CLUTIL_LIB_BIN_PATH=$(UTILLIB_PATH)/$(CLUTIL_LIB_BIN) +endif + +OFILES= $(CSOURCE:%.c=$(OBJROOT)/%.o) $(CPSOURCE:%.cpp=$(OBJROOT)/%.o) + +# +# Assume final load with cc, not ld +# +STD_LIBS=-lclutils -lcsputils +STD_LIBPATH= -L$(LOCAL_BUILD) -L$(UTILLIB_PATH) -L$(UTIL_LIB_SRC) +ALL_LIBS= $(STD_LIBS) $(PROJ_LIBS) +ALL_LIBPATHS= $(STD_LIBPATH) $(PROJ_LIBPATH) +PRIV_FRAMEWORK_PATH= /System/Library/PrivateFrameworks + +# +# Override this from the make command line to add e.g. -lMallocDebug +# +CMDLINE_LDFLAGS?= + +ALL_LDFLAGS= $(CMDLINE_LDFLAGS) -F$(LOCAL_BUILD) $(ALL_LIBS) $(ALL_LIBPATHS) \ + $(PROJ_LDFLAGS) -F$(PRIV_FRAMEWORK_PATH) -lsecurity_cdsa_client -lsecurity_utilities -lsecurity_cdsa_utilities -lsecurity_cdsa_utils + +CC=c++ + +VARIANT_SUFFIX= + +STD_FRAMEWORKS= -framework Security$(VARIANT_SUFFIX) -framework CoreFoundation + +ALL_FRAMEWORKS= $(STD_FRAMEWORKS) $(PROJ_FRAMEWORKS) + +# +# to get to headers in frameworks +# +STD_FINCLUDES= -F$(LOCAL_BUILD) -F$(PRIV_FRAMEWORK_PATH) -F$(PRIV_FRAMEWORK_PATH) +# +# the common headers for csputils +# +STD_INCLUDES= -I.. -I$(UTILLIB_HDRS) -F$(PRIV_FRAMEWORK_PATH) +ALL_INCLUDES= $(STD_INCLUDES) $(PROJ_INCLUDES) +CINCLUDES= $(STD_FINCLUDES) $(ALL_INCLUDES) + +###WFLAGS= -Wno-four-char-constants -Wall -Werror +WFLAGS= -Wno-four-char-constants -Wall -Wno-deprecated-declarations + +STD_CFLAGS= -g $(VERBOSE) $(SPHINX) +DEBUG_CFLAGS?= + +ALL_CFLAGS= $(CINCLUDES) $(STD_CFLAGS) $(PROJ_CFLAGS) $(WFLAGS) $(DEBUG_CFLAGS) + +# +# Executable in build folder +# +BUILT_TARGET= $(LOCAL_BUILD)/$(EXECUTABLE) + +first: LIB_CLUTILS $(PROJ_DEPENDS) $(CSPUTIL_LIB_BIN_PATH) $(BUILT_TARGET) + +build: first + +debug: + make "VARIANT_SUFFIX=,_debug" + +sphinx: + make "SPHINX=-DSPHINX" + +# architecture options + +64bit: + make "DEBUG_CFLAGS=-arch x86_64" "CMDLINE_LDFLAGS=-arch x86_64" + +64bitFat: + make "DEBUG_CFLAGS=-arch x86_64 -arch i386" "CMDLINE_LDFLAGS=-arch x86_64 -arch i386" + +fat: + make "DEBUG_CFLAGS=-arch i386" "CMDLINE_LDFLAGS=-arch i386" + +install: build + install -d -m 0755 $(INSTALLDIR) + install -p -m 0755 $(BUILT_TARGET) $(INSTALLDIR) + +installhdrs: + +# +# Executable might be in . if no LOCAL_BUILD_DIR specified +# +clean: + rm -f $(BUILT_TARGET) $(EXECUTABLE) + cd $(SRCROOT); rm -f $(OFILES) *.o + cd $(LOCAL_BUILD); rm -f $(EXECUTABLE) $(OTHER_TO_CLEAN) + rm -f $(CLEAN_DIR)/$(EXECUTABLE) + +# +# Make sure libcsputils.a has been built... +# +$(CSPUTIL_LIB_BIN_PATH): + @if ! ( [ -e $(CSPUTIL_LIB_BIN_PATH) ] );\ + then \ + echo === You must build libcsputils.a before building this project. === ;\ + echo === Please cd to the cspxutils/utilLib directory and type make. === ;\ + echo === $(CSPUTIL_LIB_BIN_PATH) not found. === ;\ + exit 1; \ + fi + +LIB_CLUTILS: + (cd $(UTIL_LIB_SRC); make) + +$(BUILT_TARGET): $(OFILES) $(CSPUTIL_LIB_BIN_PATH) $(CLUTIL_LIB_BIN_PATH) + $(CC) -o $(BUILT_TARGET) $(ALL_FRAMEWORKS) $^ $(ALL_LDFLAGS) + +$(OBJROOT)/%.o: %.c $(HDR_DEPENDS) + $(CC) $(ALL_CFLAGS) -c -o $(OBJROOT)/$*.o $< + +$(OBJROOT)/%.o: %.cpp $(HDR_DEPENDS) + $(CC) $(ALL_CFLAGS) -c -o $(OBJROOT)/$*.o $< diff --git a/SecurityTests/clxutils/Makefile.lib b/SecurityTests/clxutils/Makefile.lib new file mode 100644 index 00000000..dd14859e --- /dev/null +++ b/SecurityTests/clxutils/Makefile.lib @@ -0,0 +1,113 @@ +# +# Common makefile fragment for dmitch's SecurityX-style clxutils, +# tailored for building a library. +# This is -included from project-specific Makefiles, assumed +# to be one directory down from this file. +# +# See Makefile.template for sample project-specific Makefile. +# + +# Defaults for variables provided by buildit +# +# Object files written to '.' unless OBJROOT specified +# +OBJROOT ?= . +SRCROOT ?= . +# +# Library written to SYMROOT if specified, else to LOCAL_BUILD_DIR +# env var if specified, else to '.'. +# +SYMROOT ?= $(shell echo $(LOCAL_BUILD_DIR)) +LOCAL_BUILD=$(SYMROOT) +ifeq "" "$(LOCAL_BUILD)" + LOCAL_BUILD = . +endif + +# independent of SYMROOT +CLEAN_DIR=$(shell echo $(LOCAL_BUILD_DIR)) +ifeq "" "$(CLEAN_DIR)" + CLEAN_DIR = . +endif + +# +# DSTROOT only used for install +# +DSTROOT ?= "" + +# if DSTROOT not specified, skip the extra -I to get to cspxutils headers +ifeq ("", $(DSTROOT)) + UTILLIB_HDRS= +else + UTILLIB_HDRS="-I$(DSTROOT)/usr/local/include" +endif + +INSTALLDIR := $(DSTROOT)/usr/local/lib + +CC=c++ + +COMMON_LIB_SRC= -I../../cspxutils/ + +OFILES := $(CSOURCE:%.c=$(OBJROOT)/%.o) $(CPSOURCE:%.cpp=$(OBJROOT)/%.o) + +PRIV_FRAMEWORK_PATH= /System/Library/PrivateFrameworks + +ALL_LDFLAGS= -static $(PROJ_LDFLAGS) + +STD_FRAMEWORKS= +ALL_FRAMEWORKS= $(STD_FRAMEWORKS) $(PROJ_FRAMEWORKS) + +# +# to get to headers in frameworks +# +STD_FINCLUDES= -F$(LOCAL_BUILD) -F/System/Library/Frameworks/CoreServices.framework/Frameworks +STD_INCLUDES= -I.. $(COMMON_LIB_SRC) $(UTILLIB_HDRS) -F$(PRIV_FRAMEWORK_PATH) + +ALL_INCLUDES= $(STD_INCLUDES) $(PROJ_INCLUDES) +CINCLUDES= $(STD_FINCLUDES) $(ALL_INCLUDES) + +###WFLAGS= -Wno-four-char-constants -Wall -Werror +WFLAGS= -Wno-four-char-constants -Wall -Wno-deprecated-declarations +STD_CFLAGS= -g $(VERBOSE) +DEBUG_CFLAGS?= + +ALL_CFLAGS= $(CINCLUDES) $(STD_CFLAGS) $(PROJ_CFLAGS) $(WFLAGS) $(DEBUG_CFLAGS) + +# +# Executable has to be in build folder for MDS +# +BUILT_TARGET= $(LOCAL_BUILD)/$(EXECUTABLE) + +first: $(PROJ_DEPENDS) $(BUILT_TARGET) + +build: first + +# architecture options + +64bit: + make "DEBUG_CFLAGS=-arch x86_64" + +64bitFat: + make "DEBUG_CFLAGS=-arch x86_64 -arch i386" + +fat: + make "DEBUG_CFLAGS=-arch i386" "CMDLINE_LDFLAGS=-arch i386" + +install: build + install -d -m 0755 $(INSTALLDIR) + install -p -m 0644 $(BUILT_TARGET) $(INSTALLDIR) + +installhdrs: + +$(BUILT_TARGET): $(OFILES) + libtool $(ALL_LDFLAGS) -o $(BUILT_TARGET) $^ + +clean: + cd $(SRCROOT); rm -f $(OFILES) *.o + rm -f $(BUILT_TARGET) + rm -f $(CLEAN_DIR)/$(EXECUTABLE) + +$(OBJROOT)/%.o: %.c + $(CC) $(ALL_CFLAGS) -c -o $(OBJROOT)/$*.o $< + +$(OBJROOT)/%.o: %.cpp + $(CC) $(ALL_CFLAGS) -c -o $(OBJROOT)/$*.o $< diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/CoveringLetter.pdf b/SecurityTests/clxutils/NISCC/TLS_SSL/CoveringLetter.pdf new file mode 100755 index 00000000..67fbdf56 --- /dev/null +++ b/SecurityTests/clxutils/NISCC/TLS_SSL/CoveringLetter.pdf @@ -0,0 +1,3314 @@ +%PDF-1.3 %âãÏÓ +9 0 obj << /Linearized 1 /O 11 /H [ 25659 1176 ] /L 278516 /E 275492 /N 2 /T 278219 >> endobj xref 9 1261 0000000016 00000 n +0000025569 00000 n +0000026835 00000 n +0000027049 00000 n +0000039688 00000 n +0000039738 00000 n +0000039788 00000 n +0000039838 00000 n +0000039888 00000 n +0000039938 00000 n +0000039988 00000 n +0000040038 00000 n +0000040088 00000 n +0000040138 00000 n +0000040188 00000 n +0000040238 00000 n +0000040288 00000 n +0000040338 00000 n +0000040388 00000 n +0000040438 00000 n +0000040488 00000 n +0000040538 00000 n +0000040588 00000 n +0000040638 00000 n +0000040688 00000 n +0000040738 00000 n +0000040788 00000 n +0000040838 00000 n +0000040888 00000 n +0000040938 00000 n +0000040988 00000 n +0000041038 00000 n +0000041088 00000 n +0000041138 00000 n +0000041188 00000 n +0000041238 00000 n +0000041288 00000 n +0000041338 00000 n +0000041388 00000 n +0000041438 00000 n +0000041488 00000 n +0000041538 00000 n +0000041588 00000 n +0000041638 00000 n +0000041688 00000 n +0000041738 00000 n +0000041788 00000 n +0000041838 00000 n +0000041888 00000 n +0000041938 00000 n +0000041988 00000 n +0000042038 00000 n +0000042088 00000 n +0000042138 00000 n +0000042188 00000 n +0000042238 00000 n +0000042288 00000 n +0000042338 00000 n +0000042388 00000 n +0000042437 00000 n +0000042487 00000 n +0000042536 00000 n +0000042586 00000 n +0000042636 00000 n +0000042686 00000 n +0000042736 00000 n +0000042786 00000 n +0000042836 00000 n +0000042886 00000 n +0000042936 00000 n +0000042986 00000 n +0000043036 00000 n +0000043086 00000 n +0000043135 00000 n +0000043185 00000 n +0000043235 00000 n +0000043285 00000 n +0000043334 00000 n +0000043383 00000 n +0000043433 00000 n +0000043483 00000 n +0000043532 00000 n +0000043582 00000 n +0000043632 00000 n +0000043682 00000 n +0000043732 00000 n +0000043782 00000 n +0000043832 00000 n +0000043882 00000 n +0000043932 00000 n +0000043982 00000 n +0000044032 00000 n +0000044083 00000 n +0000044134 00000 n +0000044185 00000 n +0000044236 00000 n +0000044287 00000 n +0000044338 00000 n +0000044389 00000 n +0000044440 00000 n +0000044491 00000 n +0000044542 00000 n +0000044593 00000 n +0000044644 00000 n +0000044695 00000 n +0000044746 00000 n +0000044797 00000 n +0000044848 00000 n +0000044899 00000 n +0000044950 00000 n +0000045001 00000 n +0000045052 00000 n +0000045103 00000 n +0000045154 00000 n +0000045205 00000 n +0000045256 00000 n +0000045307 00000 n +0000045358 00000 n +0000045409 00000 n +0000045460 00000 n +0000045511 00000 n +0000045562 00000 n +0000045613 00000 n +0000045664 00000 n +0000045715 00000 n +0000045766 00000 n +0000045817 00000 n +0000045868 00000 n +0000045919 00000 n +0000045970 00000 n +0000046021 00000 n +0000046072 00000 n +0000046123 00000 n +0000046174 00000 n +0000046225 00000 n +0000046276 00000 n +0000046327 00000 n +0000046378 00000 n +0000046429 00000 n +0000046480 00000 n +0000046531 00000 n +0000046582 00000 n +0000046633 00000 n +0000046684 00000 n +0000046735 00000 n +0000046786 00000 n +0000046837 00000 n +0000046888 00000 n +0000046939 00000 n +0000046990 00000 n +0000047041 00000 n +0000047092 00000 n +0000047143 00000 n +0000047194 00000 n +0000047245 00000 n +0000047296 00000 n +0000047347 00000 n +0000047398 00000 n +0000047449 00000 n +0000047500 00000 n +0000047551 00000 n +0000047602 00000 n +0000047653 00000 n +0000047704 00000 n +0000047755 00000 n +0000047806 00000 n +0000047857 00000 n +0000047908 00000 n +0000047959 00000 n +0000048010 00000 n +0000048061 00000 n +0000048112 00000 n +0000048163 00000 n +0000048214 00000 n +0000048265 00000 n +0000048316 00000 n +0000048367 00000 n +0000048418 00000 n +0000048469 00000 n +0000048520 00000 n +0000048571 00000 n +0000048622 00000 n +0000048673 00000 n +0000048724 00000 n +0000048775 00000 n +0000048826 00000 n +0000048877 00000 n +0000048928 00000 n +0000048979 00000 n +0000049030 00000 n +0000049081 00000 n +0000049132 00000 n +0000049183 00000 n +0000049234 00000 n +0000049285 00000 n +0000049336 00000 n +0000049387 00000 n +0000049438 00000 n +0000049489 00000 n +0000049540 00000 n +0000049591 00000 n +0000049642 00000 n +0000049693 00000 n +0000049744 00000 n +0000049795 00000 n +0000049846 00000 n +0000049897 00000 n +0000049948 00000 n +0000049999 00000 n +0000050050 00000 n +0000050101 00000 n +0000050152 00000 n +0000050203 00000 n +0000050254 00000 n +0000050305 00000 n +0000050356 00000 n +0000050407 00000 n +0000050458 00000 n +0000050509 00000 n +0000050560 00000 n +0000050611 00000 n +0000050662 00000 n +0000050712 00000 n +0000050763 00000 n +0000050814 00000 n +0000050865 00000 n +0000050915 00000 n +0000050966 00000 n +0000051017 00000 n +0000051067 00000 n +0000051118 00000 n +0000051169 00000 n +0000051220 00000 n +0000051271 00000 n +0000051322 00000 n +0000051373 00000 n +0000051424 00000 n +0000051475 00000 n +0000051526 00000 n +0000051577 00000 n +0000051628 00000 n +0000051679 00000 n +0000051730 00000 n +0000051781 00000 n +0000051832 00000 n +0000051883 00000 n +0000051934 00000 n +0000051985 00000 n +0000052036 00000 n +0000052087 00000 n +0000052138 00000 n +0000052189 00000 n +0000052240 00000 n +0000052291 00000 n +0000052342 00000 n +0000052393 00000 n +0000052444 00000 n +0000052495 00000 n +0000052546 00000 n +0000052597 00000 n +0000052648 00000 n +0000052699 00000 n +0000052749 00000 n +0000052800 00000 n +0000052851 00000 n +0000052902 00000 n +0000052953 00000 n +0000053004 00000 n +0000053055 00000 n +0000053106 00000 n +0000053157 00000 n +0000053208 00000 n +0000053259 00000 n +0000053309 00000 n +0000053360 00000 n +0000053411 00000 n +0000053462 00000 n +0000053513 00000 n +0000053564 00000 n +0000053615 00000 n +0000053666 00000 n +0000053717 00000 n +0000053767 00000 n +0000053818 00000 n +0000053869 00000 n +0000053910 00000 n +0000053960 00000 n +0000054011 00000 n +0000054571 00000 n +0000054621 00000 n +0000054851 00000 n +0000054901 00000 n +0000054951 00000 n +0000055002 00000 n +0000055053 00000 n +0000055104 00000 n +0000055326 00000 n +0000055377 00000 n +0000055806 00000 n +0000055857 00000 n +0000055908 00000 n +0000055959 00000 n +0000056010 00000 n +0000056061 00000 n +0000056112 00000 n +0000056163 00000 n +0000056214 00000 n +0000056265 00000 n +0000056316 00000 n +0000056367 00000 n +0000056418 00000 n +0000056469 00000 n +0000056520 00000 n +0000056571 00000 n +0000056622 00000 n +0000056673 00000 n +0000056724 00000 n +0000056775 00000 n +0000056826 00000 n +0000056877 00000 n +0000056928 00000 n +0000056979 00000 n +0000057030 00000 n +0000057081 00000 n +0000057132 00000 n +0000057183 00000 n +0000057234 00000 n +0000057285 00000 n +0000057336 00000 n +0000057387 00000 n +0000057438 00000 n +0000057489 00000 n +0000057540 00000 n +0000057591 00000 n +0000057642 00000 n +0000057693 00000 n +0000057744 00000 n +0000057795 00000 n +0000057845 00000 n +0000057896 00000 n +0000057947 00000 n +0000057998 00000 n +0000058049 00000 n +0000058100 00000 n +0000058151 00000 n +0000058202 00000 n +0000058253 00000 n +0000058304 00000 n +0000058355 00000 n +0000058406 00000 n +0000058457 00000 n +0000058508 00000 n +0000058558 00000 n +0000058608 00000 n +0000058659 00000 n +0000058710 00000 n +0000058761 00000 n +0000058812 00000 n +0000058863 00000 n +0000058914 00000 n +0000058964 00000 n +0000059015 00000 n +0000059066 00000 n +0000059117 00000 n +0000059168 00000 n +0000059219 00000 n +0000059270 00000 n +0000059321 00000 n +0000059372 00000 n +0000059423 00000 n +0000059474 00000 n +0000059525 00000 n +0000059576 00000 n +0000059627 00000 n +0000059678 00000 n +0000059729 00000 n +0000059779 00000 n +0000059830 00000 n +0000059881 00000 n +0000059932 00000 n +0000059983 00000 n +0000060034 00000 n +0000060085 00000 n +0000060136 00000 n +0000060187 00000 n +0000060238 00000 n +0000060289 00000 n +0000060340 00000 n +0000060391 00000 n +0000060442 00000 n +0000060493 00000 n +0000060544 00000 n +0000060595 00000 n +0000060646 00000 n +0000060697 00000 n +0000060748 00000 n +0000060799 00000 n +0000060850 00000 n +0000060901 00000 n +0000060952 00000 n +0000061002 00000 n +0000061053 00000 n +0000061104 00000 n +0000061155 00000 n +0000061206 00000 n +0000061257 00000 n +0000061308 00000 n +0000061359 00000 n +0000061410 00000 n +0000061461 00000 n +0000061512 00000 n +0000061563 00000 n +0000061614 00000 n +0000061665 00000 n +0000061716 00000 n +0000061767 00000 n +0000061818 00000 n +0000061869 00000 n +0000061920 00000 n +0000061971 00000 n +0000061993 00000 n +0000062835 00000 n +0000062857 00000 n +0000063389 00000 n +0000063411 00000 n +0000063966 00000 n +0000063988 00000 n +0000064532 00000 n +0000064554 00000 n +0000065091 00000 n +0000065113 00000 n +0000065653 00000 n +0000065675 00000 n +0000066579 00000 n +0000066602 00000 n +0000068220 00000 n +0000068319 00000 n +0000068424 00000 n +0000068553 00000 n +0000068661 00000 n +0000068778 00000 n +0000068889 00000 n +0000068997 00000 n +0000069120 00000 n +0000069249 00000 n +0000069357 00000 n +0000069483 00000 n +0000069603 00000 n +0000069729 00000 n +0000069861 00000 n +0000069981 00000 n +0000070110 00000 n +0000070236 00000 n +0000070356 00000 n +0000070461 00000 n +0000070566 00000 n +0000070668 00000 n +0000070794 00000 n +0000070902 00000 n +0000071013 00000 n +0000071136 00000 n +0000071265 00000 n +0000071397 00000 n +0000071511 00000 n +0000071607 00000 n +0000071709 00000 n +0000071811 00000 n +0000071910 00000 n +0000072018 00000 n +0000072114 00000 n +0000072222 00000 n +0000072327 00000 n +0000072438 00000 n +0000072546 00000 n +0000072648 00000 n +0000072747 00000 n +0000072852 00000 n +0000072948 00000 n +0000073032 00000 n +0000073122 00000 n +0000073200 00000 n +0000073284 00000 n +0000073362 00000 n +0000073446 00000 n +0000073536 00000 n +0000073623 00000 n +0000073719 00000 n +0000073812 00000 n +0000073899 00000 n +0000073989 00000 n +0000074082 00000 n +0000074193 00000 n +0000074295 00000 n +0000074403 00000 n +0000074502 00000 n +0000074595 00000 n +0000074694 00000 n +0000074790 00000 n +0000074907 00000 n +0000092433 00000 n +0000130129 00000 n +0000132807 00000 n +0000132903 00000 n +0000132981 00000 n +0000133037 00000 n +0000133133 00000 n +0000133226 00000 n +0000133316 00000 n +0000133409 00000 n +0000133514 00000 n +0000133613 00000 n +0000133709 00000 n +0000133793 00000 n +0000133883 00000 n +0000133973 00000 n +0000134060 00000 n +0000134138 00000 n +0000134222 00000 n +0000134300 00000 n +0000134369 00000 n +0000134483 00000 n +0000134600 00000 n +0000134714 00000 n +0000134834 00000 n +0000134948 00000 n +0000135074 00000 n +0000135185 00000 n +0000135296 00000 n +0000135416 00000 n +0000135533 00000 n +0000135641 00000 n +0000135749 00000 n +0000135863 00000 n +0000136055 00000 n +0000136235 00000 n +0000136364 00000 n +0000136496 00000 n +0000136669 00000 n +0000136801 00000 n +0000136927 00000 n +0000137056 00000 n +0000137173 00000 n +0000137305 00000 n +0000137422 00000 n +0000137539 00000 n +0000137659 00000 n +0000137773 00000 n +0000137872 00000 n +0000137980 00000 n +0000138073 00000 n +0000138166 00000 n +0000138274 00000 n +0000138382 00000 n +0000138472 00000 n +0000138550 00000 n +0000138631 00000 n +0000138709 00000 n +0000138802 00000 n +0000138889 00000 n +0000138976 00000 n +0000139108 00000 n +0000139222 00000 n +0000139327 00000 n +0000139453 00000 n +0000139558 00000 n +0000139675 00000 n +0000139792 00000 n +0000139900 00000 n +0000139993 00000 n +0000140086 00000 n +0000140182 00000 n +0000140278 00000 n +0000140374 00000 n +0000140461 00000 n +0000140647 00000 n +0000140752 00000 n +0000140845 00000 n +0000140935 00000 n +0000141049 00000 n +0000141172 00000 n +0000141301 00000 n +0000141421 00000 n +0000141508 00000 n +0000141619 00000 n +0000141733 00000 n +0000141859 00000 n +0000141967 00000 n +0000142045 00000 n +0000142123 00000 n +0000142213 00000 n +0000142297 00000 n +0000142405 00000 n +0000142531 00000 n +0000142642 00000 n +0000142750 00000 n +0000142864 00000 n +0000142978 00000 n +0000143071 00000 n +0000143173 00000 n +0000143281 00000 n +0000143398 00000 n +0000143527 00000 n +0000143644 00000 n +0000143761 00000 n +0000143860 00000 n +0000143956 00000 n +0000144070 00000 n +0000144178 00000 n +0000144301 00000 n +0000144400 00000 n +0000144508 00000 n +0000144625 00000 n +0000144733 00000 n +0000144832 00000 n +0000144937 00000 n +0000145033 00000 n +0000145150 00000 n +0000145255 00000 n +0000145375 00000 n +0000145495 00000 n +0000145609 00000 n +0000145711 00000 n +0000145822 00000 n +0000145942 00000 n +0000146044 00000 n +0000146140 00000 n +0000146269 00000 n +0000146392 00000 n +0000146565 00000 n +0000146694 00000 n +0000146820 00000 n +0000146946 00000 n +0000147078 00000 n +0000147201 00000 n +0000147371 00000 n +0000147470 00000 n +0000147563 00000 n +0000147656 00000 n +0000147752 00000 n +0000147866 00000 n +0000147980 00000 n +0000148076 00000 n +0000148181 00000 n +0000148295 00000 n +0000148502 00000 n +0000148685 00000 n +0000148862 00000 n +0000149069 00000 n +0000149246 00000 n +0000149432 00000 n +0000149630 00000 n +0000149828 00000 n +0000150005 00000 n +0000150191 00000 n +0000150371 00000 n +0000150560 00000 n +0000150773 00000 n +0000151001 00000 n +0000151196 00000 n +0000151400 00000 n +0000151598 00000 n +0000151676 00000 n +0000151778 00000 n +0000151904 00000 n +0000151976 00000 n +0000152055 00000 n +0000152124 00000 n +0000152193 00000 n +0000152363 00000 n +0000152555 00000 n +0000152753 00000 n +0000152963 00000 n +0000153158 00000 n +0000153287 00000 n +0000153460 00000 n +0000153655 00000 n +0000153856 00000 n +0000153988 00000 n +0000154108 00000 n +0000154234 00000 n +0000154345 00000 n +0000154462 00000 n +0000154585 00000 n +0000154711 00000 n +0000154822 00000 n +0000154945 00000 n +0000155115 00000 n +0000155238 00000 n +0000155364 00000 n +0000155490 00000 n +0000155622 00000 n +0000155751 00000 n +0000155868 00000 n +0000155982 00000 n +0000156093 00000 n +0000156266 00000 n +0000156452 00000 n +0000156581 00000 n +0000156758 00000 n +0000156890 00000 n +0000157067 00000 n +0000157256 00000 n +0000157439 00000 n +0000157568 00000 n +0000157697 00000 n +0000157826 00000 n +0000157949 00000 n +0000158075 00000 n +0000158192 00000 n +0000158362 00000 n +0000158479 00000 n +0000158649 00000 n +0000158763 00000 n +0000158895 00000 n +0000159018 00000 n +0000159147 00000 n +0000159327 00000 n +0000159540 00000 n +0000159744 00000 n +0000159951 00000 n +0000160124 00000 n +0000160304 00000 n +0000160484 00000 n +0000160661 00000 n +0000160847 00000 n +0000161027 00000 n +0000161207 00000 n +0000161393 00000 n +0000161573 00000 n +0000161792 00000 n +0000162017 00000 n +0000162257 00000 n +0000162476 00000 n +0000162701 00000 n +0000162818 00000 n +0000163016 00000 n +0000163220 00000 n +0000163418 00000 n +0000163625 00000 n +0000163823 00000 n +0000164027 00000 n +0000164219 00000 n +0000164420 00000 n +0000164618 00000 n +0000164825 00000 n +0000165023 00000 n +0000165215 00000 n +0000165395 00000 n +0000165527 00000 n +0000165641 00000 n +0000165811 00000 n +0000165943 00000 n +0000166109 00000 n +0000166232 00000 n +0000166346 00000 n +0000166457 00000 n +0000166559 00000 n +0000166679 00000 n +0000166796 00000 n +0000166916 00000 n +0000167042 00000 n +0000167147 00000 n +0000167246 00000 n +0000167372 00000 n +0000167564 00000 n +0000167756 00000 n +0000167942 00000 n +0000168134 00000 n +0000168335 00000 n +0000168551 00000 n +0000168749 00000 n +0000168959 00000 n +0000169154 00000 n +0000169280 00000 n +0000169409 00000 n +0000169538 00000 n +0000169661 00000 n +0000169781 00000 n +0000169895 00000 n +0000170015 00000 n +0000170126 00000 n +0000170312 00000 n +0000170492 00000 n +0000170672 00000 n +0000170855 00000 n +0000171053 00000 n +0000171239 00000 n +0000171425 00000 n +0000171614 00000 n +0000171740 00000 n +0000171926 00000 n +0000172133 00000 n +0000172328 00000 n +0000172523 00000 n +0000172748 00000 n +0000172967 00000 n +0000173174 00000 n +0000173372 00000 n +0000173542 00000 n +0000173659 00000 n +0000173770 00000 n +0000173875 00000 n +0000173998 00000 n +0000174130 00000 n +0000174259 00000 n +0000174391 00000 n +0000174499 00000 n +0000174694 00000 n +0000174886 00000 n +0000175078 00000 n +0000175258 00000 n +0000175387 00000 n +0000175567 00000 n +0000175737 00000 n +0000175863 00000 n +0000176064 00000 n +0000176274 00000 n +0000176484 00000 n +0000176694 00000 n +0000176907 00000 n +0000177102 00000 n +0000177303 00000 n +0000177507 00000 n +0000177741 00000 n +0000177921 00000 n +0000178110 00000 n +0000178296 00000 n +0000178488 00000 n +0000178710 00000 n +0000178914 00000 n +0000179106 00000 n +0000179313 00000 n +0000179511 00000 n +0000179634 00000 n +0000179811 00000 n +0000180003 00000 n +0000180186 00000 n +0000180384 00000 n +0000180579 00000 n +0000180771 00000 n +0000180966 00000 n +0000181167 00000 n +0000181365 00000 n +0000181554 00000 n +0000181767 00000 n +0000181983 00000 n +0000182175 00000 n +0000182373 00000 n +0000182574 00000 n +0000182769 00000 n +0000182951 00000 n +0000183152 00000 n +0000183347 00000 n +0000183558 00000 n +0000183765 00000 n +0000183969 00000 n +0000184175 00000 n +0000184378 00000 n +0000184582 00000 n +0000184785 00000 n +0000184988 00000 n +0000185189 00000 n +0000185391 00000 n +0000185592 00000 n +0000185789 00000 n +0000185988 00000 n +0000186187 00000 n +0000186386 00000 n +0000186588 00000 n +0000186791 00000 n +0000186995 00000 n +0000187205 00000 n +0000187416 00000 n +0000187627 00000 n +0000187839 00000 n +0000188050 00000 n +0000188260 00000 n +0000188472 00000 n +0000188681 00000 n +0000188887 00000 n +0000189095 00000 n +0000189305 00000 n +0000189511 00000 n +0000189720 00000 n +0000189928 00000 n +0000190134 00000 n +0000190344 00000 n +0000190550 00000 n +0000190757 00000 n +0000190961 00000 n +0000191169 00000 n +0000191373 00000 n +0000191578 00000 n +0000191781 00000 n +0000191986 00000 n +0000192190 00000 n +0000192390 00000 n +0000192587 00000 n +0000192787 00000 n +0000192983 00000 n +0000193182 00000 n +0000193373 00000 n +0000193572 00000 n +0000193769 00000 n +0000193966 00000 n +0000194168 00000 n +0000194370 00000 n +0000194580 00000 n +0000194785 00000 n +0000194997 00000 n +0000195204 00000 n +0000195407 00000 n +0000195618 00000 n +0000195828 00000 n +0000196032 00000 n +0000196239 00000 n +0000196444 00000 n +0000196649 00000 n +0000196855 00000 n +0000197057 00000 n +0000197264 00000 n +0000197474 00000 n +0000197685 00000 n +0000197903 00000 n +0000198122 00000 n +0000198343 00000 n +0000198566 00000 n +0000198786 00000 n +0000199003 00000 n +0000199221 00000 n +0000199441 00000 n +0000199660 00000 n +0000199881 00000 n +0000200102 00000 n +0000200321 00000 n +0000200542 00000 n +0000200764 00000 n +0000200982 00000 n +0000201198 00000 n +0000201413 00000 n +0000201631 00000 n +0000201851 00000 n +0000202070 00000 n +0000202291 00000 n +0000202517 00000 n +0000202746 00000 n +0000202968 00000 n +0000203187 00000 n +0000203412 00000 n +0000203635 00000 n +0000203873 00000 n +0000204113 00000 n +0000204343 00000 n +0000204572 00000 n +0000204803 00000 n +0000205033 00000 n +0000205264 00000 n +0000205496 00000 n +0000205727 00000 n +0000205957 00000 n +0000206189 00000 n +0000206415 00000 n +0000206641 00000 n +0000206868 00000 n +0000207097 00000 n +0000207324 00000 n +0000207550 00000 n +0000207770 00000 n +0000207991 00000 n +0000208207 00000 n +0000208423 00000 n +0000208639 00000 n +0000208858 00000 n +0000209071 00000 n +0000209289 00000 n +0000209504 00000 n +0000209726 00000 n +0000209948 00000 n +0000210168 00000 n +0000210392 00000 n +0000210615 00000 n +0000210835 00000 n +0000211049 00000 n +0000211261 00000 n +0000211476 00000 n +0000211692 00000 n +0000211910 00000 n +0000212123 00000 n +0000212342 00000 n +0000212558 00000 n +0000212770 00000 n +0000212986 00000 n +0000213208 00000 n +0000213429 00000 n +0000213646 00000 n +0000213862 00000 n +0000214087 00000 n +0000214322 00000 n +0000214554 00000 n +0000214780 00000 n +0000215008 00000 n +0000215235 00000 n +0000215460 00000 n +0000215684 00000 n +0000215909 00000 n +0000216132 00000 n +0000216353 00000 n +0000216575 00000 n +0000216794 00000 n +0000217013 00000 n +0000217235 00000 n +0000217472 00000 n +0000217706 00000 n +0000217939 00000 n +0000218177 00000 n +0000218413 00000 n +0000218649 00000 n +0000218889 00000 n +0000219133 00000 n +0000219378 00000 n +0000219617 00000 n +0000219849 00000 n +0000220085 00000 n +0000220318 00000 n +0000220564 00000 n +0000220804 00000 n +0000221045 00000 n +0000221288 00000 n +0000221534 00000 n +0000221773 00000 n +0000222017 00000 n +0000222261 00000 n +0000222508 00000 n +0000222758 00000 n +0000223018 00000 n +0000223277 00000 n +0000223543 00000 n +0000223813 00000 n +0000224076 00000 n +0000224340 00000 n +0000224603 00000 n +0000224858 00000 n +0000225121 00000 n +0000225384 00000 n +0000225646 00000 n +0000225910 00000 n +0000226173 00000 n +0000226438 00000 n +0000226714 00000 n +0000226981 00000 n +0000227251 00000 n +0000227514 00000 n +0000227769 00000 n +0000228018 00000 n +0000228266 00000 n +0000228514 00000 n +0000228763 00000 n +0000229008 00000 n +0000229258 00000 n +0000229508 00000 n +0000229767 00000 n +0000230030 00000 n +0000230308 00000 n +0000230583 00000 n +0000230848 00000 n +0000231111 00000 n +0000231377 00000 n +0000231639 00000 n +0000231898 00000 n +0000232158 00000 n +0000232420 00000 n +0000232682 00000 n +0000232943 00000 n +0000233199 00000 n +0000233457 00000 n +0000233718 00000 n +0000233977 00000 n +0000234240 00000 n +0000234502 00000 n +0000234762 00000 n +0000235023 00000 n +0000235274 00000 n +0000235517 00000 n +0000235755 00000 n +0000236000 00000 n +0000236247 00000 n +0000236498 00000 n +0000236749 00000 n +0000236997 00000 n +0000237249 00000 n +0000237499 00000 n +0000237750 00000 n +0000237991 00000 n +0000238235 00000 n +0000238481 00000 n +0000238726 00000 n +0000238973 00000 n +0000239220 00000 n +0000239446 00000 n +0000239679 00000 n +0000239912 00000 n +0000240146 00000 n +0000240385 00000 n +0000240624 00000 n +0000240865 00000 n +0000241099 00000 n +0000241328 00000 n +0000241564 00000 n +0000241807 00000 n +0000242045 00000 n +0000242279 00000 n +0000242515 00000 n +0000242745 00000 n +0000242978 00000 n +0000243209 00000 n +0000243425 00000 n +0000243641 00000 n +0000243857 00000 n +0000244079 00000 n +0000244302 00000 n +0000244529 00000 n +0000244757 00000 n +0000244983 00000 n +0000245206 00000 n +0000245426 00000 n +0000245645 00000 n +0000245862 00000 n +0000246080 00000 n +0000246296 00000 n +0000246509 00000 n +0000246722 00000 n +0000246936 00000 n +0000247152 00000 n +0000247376 00000 n +0000247593 00000 n +0000247809 00000 n +0000248026 00000 n +0000248236 00000 n +0000248449 00000 n +0000248660 00000 n +0000248869 00000 n +0000249076 00000 n +0000249285 00000 n +0000249496 00000 n +0000249704 00000 n +0000249912 00000 n +0000250123 00000 n +0000250344 00000 n +0000250565 00000 n +0000250798 00000 n +0000251031 00000 n +0000251257 00000 n +0000251487 00000 n +0000251717 00000 n +0000251942 00000 n +0000252168 00000 n +0000252394 00000 n +0000252625 00000 n +0000252851 00000 n +0000253078 00000 n +0000253305 00000 n +0000253526 00000 n +0000253741 00000 n +0000253949 00000 n +0000254153 00000 n +0000254352 00000 n +0000254552 00000 n +0000254755 00000 n +0000254961 00000 n +0000255168 00000 n +0000255381 00000 n +0000255594 00000 n +0000255812 00000 n +0000256034 00000 n +0000256255 00000 n +0000256473 00000 n +0000256694 00000 n +0000256917 00000 n +0000257136 00000 n +0000257353 00000 n +0000257570 00000 n +0000257784 00000 n +0000257994 00000 n +0000258206 00000 n +0000258421 00000 n +0000258639 00000 n +0000258855 00000 n +0000259075 00000 n +0000259295 00000 n +0000259508 00000 n +0000259717 00000 n +0000259935 00000 n +0000260153 00000 n +0000260374 00000 n +0000260595 00000 n +0000260818 00000 n +0000261042 00000 n +0000261265 00000 n +0000261486 00000 n +0000261713 00000 n +0000261938 00000 n +0000262162 00000 n +0000262379 00000 n +0000262601 00000 n +0000262822 00000 n +0000263040 00000 n +0000263258 00000 n +0000263483 00000 n +0000263703 00000 n +0000263922 00000 n +0000264145 00000 n +0000264369 00000 n +0000264593 00000 n +0000264816 00000 n +0000265035 00000 n +0000265265 00000 n +0000265492 00000 n +0000265715 00000 n +0000265939 00000 n +0000266163 00000 n +0000266391 00000 n +0000266619 00000 n +0000266854 00000 n +0000267089 00000 n +0000267323 00000 n +0000267551 00000 n +0000267779 00000 n +0000268006 00000 n +0000268238 00000 n +0000268472 00000 n +0000268706 00000 n +0000268941 00000 n +0000269178 00000 n +0000269418 00000 n +0000269669 00000 n +0000269913 00000 n +0000270151 00000 n +0000270385 00000 n +0000270621 00000 n +0000270864 00000 n +0000271104 00000 n +0000271343 00000 n +0000271579 00000 n +0000271812 00000 n +0000272049 00000 n +0000272290 00000 n +0000272530 00000 n +0000272771 00000 n +0000273009 00000 n +0000273246 00000 n +0000273483 00000 n +0000273704 00000 n +0000273922 00000 n +0000274144 00000 n +0000274361 00000 n +0000274571 00000 n +0000274769 00000 n +0000274961 00000 n +0000275152 00000 n +0000025659 00000 n +0000026811 00000 n +trailer << /Size 1270 /Info 7 0 R /Root 10 0 R /Prev 278210 /ID[<60fee8f0a7aa5e5930d8ab5a36aee088><61d6746a07d1d4e2932a4e5f16fbc432>] >> startxref 0 %%EOF 10 0 obj << /Type /Catalog /Pages 6 0 R /Metadata 8 0 R /PageLabels 5 0 R >> endobj 1268 0 obj << /S 49 /L 2745 /Filter /FlateDecode /Length 1269 0 R >> stream +H‰ì“ÝkÛeÇ¿Íêy#¾]¸Î /½Ê."“a¡P- @ ,½ð/ ô¢,æun}¯iÓ¦i›µMM·ôUV­[…Š­/àÃÏ9¿0-(EñÂßáœç<çœçœó|Ïó“tJz뢞{AOé×Ïô3ðãïϨñöë +Dó{Rj=˜ï9ö3/¿©¶‘Î6ù|ÁzöÄþ$ûŸ¢Ðvb÷÷óý™5°ºú²5§«*jUƒÅöÙ¼¢WAé<9òØ +ø2äԐÏѺMR!í̺f53ŽjœÈô>,}äîGÏxwiüYç„w˜¡v‘ªœÈAA79—óZ֎Ë$Xg¾æé!ÐmR†{ù.ÙþR>«´Ï=MLžlv¦Ô¼GºÙKÊçoVìÇ;]Å?@öAh™êV'ë¯9ʙ1|ùæ;ÉáM“½àTt„FUwL­nÅ;¶,ÝÜ.ïuìô ßÂp/9ÂCX>p9Eô¨Æ5‚†4 _× §a·ˆšÒ4\@~Bô$Ú8Ú$Ò4Ë1 ?Æz“ 7õ®Áסa¨€ošØÏdsƒÆñLx2,ê–4‡¾à»E—ö%Í>´®èSl6­[Úbn5ökÈ5Ýöõ6+ªb­².p¢ä4eòT -y­zšÅWÆ7Ï: W81Ǻ¬uϵJžeâ­Þ¢WžGn‚üêo@;ÚÕçÚ&zÛì?Ó]Ömì»ÚÓ}éP?è'5ô|7tìú÷z Ýs {úºG®ûС-ÒÏD48{Ìþy¬oõµ¾AzŽ#´}ªmqjmŸ _qzŸvéÁ¬{ÜâT§£mìu°Ùð3uÖžµ&FîXåÆ+ŽÎ¼Ï¢6E*á2ç¯oŠ0O1ûI¤MËj¬¯V6ƒ5ŸCϬ¿¼‹1EŸ…!]ö©[¥9j|Vs*’¿ì³äø³˜kž-³³>Í»äyjD»Uhª»Ve:uhÉí€ÎnóöwÙmûÜ6AÆ&·…¶éÙ+~Wûû¯éCý׿Vµ^x†5¿ñ‹<-=; endstream endobj 1269 0 obj 1056 endobj 11 0 obj << /Type /Page /Parent 6 0 R /Resources 12 0 R /Contents [ 429 0 R 431 0 R 433 0 R 435 0 R 437 0 R 439 0 R 441 0 R 443 0 R ] /MediaBox [ 0 0 595 842 ] /CropBox [ 0 0 595 842 ] /Rotate 0 >> endobj 12 0 obj << /ProcSet [ /PDF /Text /ImageC /ImageI ] /Font << /TT2 296 0 R /TT4 306 0 R >> /XObject << /Im1 858 0 R /Im2 859 0 R /Im3 860 0 R /Im4 861 0 R /Im5 862 0 R /Im6 863 0 R /Im7 864 0 R /Im8 865 0 R /Im9 866 0 R /Im10 867 0 R /Im11 868 0 R /Im12 869 0 R /Im13 870 0 R /Im14 871 0 R /Im15 872 0 R /Im16 873 0 R /Im17 874 0 R /Im18 875 0 R /Im19 876 0 R /Im20 877 0 R /Im21 878 0 R /Im22 879 0 R /Im23 880 0 R /Im24 881 0 R /Im25 882 0 R /Im26 883 0 R /Im27 884 0 R /Im28 885 0 R /Im29 886 0 R /Im30 887 0 R /Im31 888 0 R /Im32 889 0 R /Im33 890 0 R /Im34 891 0 R /Im35 892 0 R /Im36 893 0 R /Im37 894 0 R /Im38 895 0 R /Im39 896 0 R /Im40 897 0 R /Im41 898 0 R /Im42 899 0 R /Im43 900 0 R /Im44 901 0 R /Im45 902 0 R /Im46 903 0 R /Im47 904 0 R /Im48 905 0 R /Im49 906 0 R /Im50 907 0 R /Im51 908 0 R /Im52 909 0 R /Im53 910 0 R /Im54 911 0 R /Im55 912 0 R /Im56 913 0 R /Im57 914 0 R /Im58 915 0 R /Im59 916 0 R /Im60 917 0 R /Im61 918 0 R /Im62 919 0 R /Im63 920 0 R /Im64 921 0 R /Im65 922 0 R /Im66 923 0 R /Im67 924 0 R /Im68 925 0 R /Im69 926 0 R /Im70 927 0 R /Im71 928 0 R /Im72 929 0 R /Im73 930 0 R /Im74 931 0 R /Im75 932 0 R /Im76 933 0 R /Im77 934 0 R /Im78 935 0 R /Im79 936 0 R /Im80 937 0 R /Im81 938 0 R /Im82 939 0 R /Im83 940 0 R /Im84 941 0 R /Im85 942 0 R /Im86 943 0 R /Im87 944 0 R /Im88 945 0 R /Im89 946 0 R /Im90 947 0 R /Im91 948 0 R /Im92 949 0 R /Im93 950 0 R /Im94 951 0 R /Im95 952 0 R /Im96 953 0 R /Im97 954 0 R /Im98 955 0 R /Im99 956 0 R /Im100 957 0 R /Im101 958 0 R /Im102 959 0 R /Im103 960 0 R /Im104 961 0 R /Im105 962 0 R /Im106 963 0 R /Im107 964 0 R /Im108 965 0 R /Im109 966 0 R /Im110 967 0 R /Im111 968 0 R /Im112 969 0 R /Im113 970 0 R /Im114 971 0 R /Im115 972 0 R /Im116 973 0 R /Im117 974 0 R /Im118 975 0 R /Im119 976 0 R /Im120 977 0 R /Im121 978 0 R /Im122 979 0 R /Im123 980 0 R /Im124 981 0 R /Im125 982 0 R /Im126 983 0 R /Im127 984 0 R /Im128 985 0 R /Im129 986 0 R /Im130 987 0 R /Im131 988 0 R /Im132 989 0 R /Im133 990 0 R /Im134 991 0 R /Im135 992 0 R /Im136 993 0 R /Im137 994 0 R /Im138 995 0 R /Im139 996 0 R /Im140 997 0 R /Im141 998 0 R /Im142 999 0 R /Im143 1000 0 R /Im144 1001 0 R /Im145 1002 0 R /Im146 1003 0 R /Im147 1004 0 R /Im148 1005 0 R /Im149 1006 0 R /Im150 1007 0 R /Im151 1008 0 R /Im152 1009 0 R /Im153 1010 0 R /Im154 1011 0 R /Im155 1012 0 R /Im156 1013 0 R /Im157 1014 0 R /Im158 1015 0 R /Im159 1016 0 R /Im160 1017 0 R /Im161 1018 0 R /Im162 1019 0 R /Im163 1020 0 R /Im164 1021 0 R /Im165 1022 0 R /Im166 1023 0 R /Im167 1024 0 R /Im168 1025 0 R /Im169 1026 0 R /Im170 1027 0 R /Im171 1028 0 R /Im172 1029 0 R /Im173 1030 0 R /Im174 1031 0 R /Im175 1032 0 R /Im176 1033 0 R /Im177 1034 0 R /Im178 1035 0 R /Im179 1036 0 R /Im180 1037 0 R /Im181 1038 0 R /Im182 1039 0 R /Im183 1040 0 R /Im184 1041 0 R /Im185 1042 0 R /Im186 1043 0 R /Im187 1044 0 R /Im188 1045 0 R /Im189 1046 0 R /Im190 1047 0 R /Im191 1048 0 R /Im192 1049 0 R /Im193 1050 0 R /Im194 1051 0 R /Im195 1052 0 R /Im196 1053 0 R /Im197 1054 0 R /Im198 1055 0 R /Im199 1056 0 R /Im200 1057 0 R /Im201 1058 0 R /Im202 1059 0 R /Im203 1060 0 R /Im204 1061 0 R /Im205 1062 0 R /Im206 1063 0 R /Im207 1064 0 R /Im208 1065 0 R /Im209 1066 0 R /Im210 1067 0 R /Im211 1068 0 R /Im212 1069 0 R /Im213 1070 0 R /Im214 1071 0 R /Im215 1072 0 R /Im216 1073 0 R /Im217 1074 0 R /Im218 1075 0 R /Im219 1076 0 R /Im220 1077 0 R /Im221 1078 0 R /Im222 1079 0 R /Im223 1080 0 R /Im224 1081 0 R /Im225 1082 0 R /Im226 1083 0 R /Im227 1084 0 R /Im228 1085 0 R /Im229 1086 0 R /Im230 1087 0 R /Im231 1088 0 R /Im232 1089 0 R /Im233 1090 0 R /Im234 1091 0 R /Im235 1092 0 R /Im236 1093 0 R /Im237 1094 0 R /Im238 1095 0 R /Im239 1096 0 R /Im240 1097 0 R /Im241 1098 0 R /Im242 1099 0 R /Im243 1100 0 R /Im244 1101 0 R /Im245 1102 0 R /Im246 1103 0 R /Im247 1104 0 R /Im248 1105 0 R /Im249 1106 0 R /Im250 1107 0 R /Im251 1108 0 R /Im252 1109 0 R /Im253 1110 0 R /Im254 1111 0 R /Im255 1112 0 R /Im256 1113 0 R /Im257 1114 0 R /Im258 1115 0 R /Im259 1116 0 R /Im260 1117 0 R /Im261 1118 0 R /Im262 1119 0 R /Im263 1120 0 R /Im264 1121 0 R /Im265 1122 0 R /Im266 1123 0 R /Im267 1124 0 R /Im268 1125 0 R /Im269 1126 0 R /Im270 1127 0 R /Im271 1128 0 R /Im272 1129 0 R /Im273 1130 0 R /Im274 1131 0 R /Im275 1132 0 R /Im276 1133 0 R /Im277 1134 0 R /Im278 1135 0 R /Im279 1136 0 R /Im280 1137 0 R /Im281 1138 0 R /Im282 1139 0 R /Im283 1140 0 R /Im284 1141 0 R /Im285 1142 0 R /Im286 1143 0 R /Im287 1144 0 R /Im288 1145 0 R /Im289 1146 0 R /Im290 1147 0 R /Im291 1148 0 R /Im292 1149 0 R /Im293 1150 0 R /Im294 1151 0 R /Im295 1152 0 R /Im296 1153 0 R /Im297 1154 0 R /Im298 1155 0 R /Im299 1156 0 R /Im300 1157 0 R /Im301 1158 0 R /Im302 1159 0 R /Im303 1160 0 R /Im304 1161 0 R /Im305 1162 0 R /Im306 1163 0 R /Im307 1164 0 R /Im308 1165 0 R /Im309 1166 0 R /Im310 1167 0 R /Im311 1168 0 R /Im312 1169 0 R /Im313 1170 0 R /Im314 1171 0 R /Im315 1172 0 R /Im316 1173 0 R /Im317 1174 0 R /Im318 1175 0 R /Im319 1176 0 R /Im320 1177 0 R /Im321 1178 0 R /Im322 1179 0 R /Im323 1180 0 R /Im324 1181 0 R /Im325 1182 0 R /Im326 1183 0 R /Im327 1184 0 R /Im328 1185 0 R /Im329 1186 0 R /Im330 1187 0 R /Im331 1188 0 R /Im332 1189 0 R /Im333 1190 0 R /Im334 1191 0 R /Im335 1192 0 R /Im336 1193 0 R /Im337 1194 0 R /Im338 1195 0 R /Im339 1196 0 R /Im340 1197 0 R /Im341 1198 0 R /Im342 1199 0 R /Im343 1200 0 R /Im344 1201 0 R /Im345 1202 0 R /Im346 1203 0 R /Im347 1204 0 R /Im348 1205 0 R /Im349 1206 0 R /Im350 1207 0 R /Im351 1208 0 R /Im352 1209 0 R /Im353 1210 0 R /Im354 1211 0 R /Im355 1212 0 R /Im356 1213 0 R /Im357 1214 0 R /Im358 1215 0 R /Im359 1216 0 R /Im360 1217 0 R /Im361 1218 0 R /Im362 1219 0 R /Im363 1220 0 R /Im364 1221 0 R /Im365 1222 0 R /Im366 1223 0 R /Im367 1224 0 R /Im368 1225 0 R /Im369 1226 0 R /Im370 1227 0 R /Im371 1228 0 R /Im372 1229 0 R /Im373 1230 0 R /Im374 1231 0 R /Im375 1232 0 R /Im376 1233 0 R /Im377 1234 0 R /Im378 1235 0 R /Im379 1236 0 R /Im380 1237 0 R /Im381 1238 0 R /Im382 1239 0 R /Im383 1240 0 R /Im384 1241 0 R /Im385 1242 0 R /Im386 1243 0 R /Im387 1244 0 R /Im388 1245 0 R /Im389 1246 0 R /Im390 1247 0 R /Im391 1248 0 R /Im392 1249 0 R /Im393 1250 0 R /Im394 1251 0 R /Im395 1252 0 R /Im396 1253 0 R /Im397 1254 0 R /Im398 1255 0 R /Im399 1256 0 R /Im400 1257 0 R /Im401 1258 0 R /Im402 1259 0 R /Im403 1260 0 R /Im404 1261 0 R /Im405 1262 0 R /Im406 1263 0 R /Im407 1264 0 R /Im408 1265 0 R /Im409 1266 0 R /Im410 1267 0 R >> /ExtGState << /GS1 673 0 R >> /ColorSpace << /Cs6 293 0 R /Cs8 281 0 R /Cs9 290 0 R /Cs10 287 0 R /Cs11 325 0 R /Cs12 322 0 R /Cs13 332 0 R /Cs14 329 0 R /Cs15 310 0 R /Cs16 317 0 R /Cs17 316 0 R /Cs18 244 0 R /Cs19 242 0 R /Cs20 252 0 R /Cs21 248 0 R /Cs22 230 0 R /Cs23 237 0 R /Cs24 234 0 R /Cs25 270 0 R /Cs26 267 0 R /Cs27 278 0 R /Cs28 275 0 R /Cs29 258 0 R /Cs30 334 0 R /Cs31 262 0 R /Cs32 398 0 R /Cs33 396 0 R /Cs34 403 0 R /Cs35 387 0 R /Cs36 392 0 R /Cs37 390 0 R /Cs38 421 0 R /Cs39 424 0 R /Cs40 409 0 R /Cs41 416 0 R /Cs42 350 0 R /Cs43 352 0 R /Cs44 353 0 R /Cs45 339 0 R /Cs46 344 0 R /Cs47 358 0 R /Cs48 371 0 R /Cs49 377 0 R /Cs50 363 0 R /Cs51 364 0 R /Cs52 365 0 R /Cs53 381 0 R /Cs54 346 0 R /Cs55 408 0 R /Cs56 384 0 R /Cs57 85 0 R /Cs58 81 0 R /Cs59 89 0 R /Cs60 86 0 R /Cs61 69 0 R /Cs62 67 0 R /Cs63 77 0 R /Cs64 92 0 R /Cs65 111 0 R /Cs66 112 0 R /Cs67 115 0 R /Cs68 96 0 R /Cs69 93 0 R /Cs70 103 0 R /Cs71 100 0 R /Cs72 28 0 R /Cs73 31 0 R /Cs74 34 0 R /Cs75 16 0 R /Cs76 14 0 R /Cs77 23 0 R /Cs78 20 0 R /Cs79 57 0 R /Cs80 58 0 R /Cs81 64 0 R /Cs82 51 0 R /Cs83 39 0 R /Cs84 49 0 R /Cs85 45 0 R /Cs86 191 0 R /Cs87 188 0 R /Cs88 199 0 R /Cs89 195 0 R /Cs90 176 0 R /Cs91 183 0 R /Cs92 180 0 R /Cs93 217 0 R /Cs94 214 0 R /Cs95 225 0 R /Cs96 222 0 R /Cs97 205 0 R /Cs98 206 0 R /Cs99 209 0 R /Cs100 136 0 R /Cs101 135 0 R /Cs102 143 0 R /Cs103 140 0 R /Cs104 124 0 R /Cs105 121 0 R /Cs106 131 0 R /Cs107 146 0 R /Cs108 162 0 R /Cs109 166 0 R /Cs110 169 0 R /Cs111 150 0 R /Cs112 148 0 R /Cs113 157 0 R /Cs114 154 0 R /Cs115 168 0 R /Cs116 126 0 R /Cs117 145 0 R /Cs118 211 0 R /Cs119 220 0 R /Cs120 175 0 R /Cs121 189 0 R /Cs122 43 0 R /Cs123 55 0 R /Cs124 33 0 R /Cs125 101 0 R /Cs126 117 0 R /Cs127 75 0 R /Cs128 80 0 R /Cs129 351 0 R /Cs130 359 0 R /Cs131 341 0 R /Cs132 347 0 R /Cs133 419 0 R /Cs134 402 0 R /Cs135 264 0 R /Cs136 273 0 R /Cs137 229 0 R /Cs138 243 0 R /Cs139 311 0 R /Cs140 307 0 R /Cs141 301 0 R /Cs142 295 0 R /Cs143 285 0 R /Cs144 292 0 R /Cs145 323 0 R /Cs146 330 0 R /Cs147 309 0 R /Cs148 315 0 R /Cs149 250 0 R /Cs150 231 0 R /Cs151 239 0 R /Cs152 272 0 R /Cs153 276 0 R /Cs154 254 0 R /Cs155 261 0 R /Cs156 404 0 R /Cs157 383 0 R /Cs158 427 0 R /Cs159 418 0 R /Cs160 415 0 R /Cs161 357 0 R /Cs162 336 0 R /Cs163 375 0 R /Cs164 370 0 R /Cs165 369 0 R /Cs166 345 0 R /Cs167 423 0 R /Cs168 83 0 R /Cs169 91 0 R /Cs170 68 0 R /Cs171 72 0 R /Cs172 106 0 R /Cs173 114 0 R /Cs174 98 0 R /Cs175 29 0 R /Cs176 36 0 R /Cs177 15 0 R /Cs178 21 0 R /Cs179 52 0 R /Cs180 59 0 R /Cs181 44 0 R /Cs182 119 0 R /Cs183 197 0 R /Cs184 177 0 R /Cs185 185 0 R /Cs186 219 0 R /Cs187 223 0 R /Cs188 201 0 R /Cs189 208 0 R /Cs190 134 0 R /Cs191 132 0 R /Cs192 129 0 R /Cs193 164 0 R /Cs194 171 0 R /Cs195 149 0 R /Cs196 155 0 R /Cs197 153 0 R /Cs198 158 0 R /Cs199 156 0 R /Cs200 152 0 R /Cs201 147 0 R /Cs202 151 0 R /Cs203 159 0 R /Cs204 167 0 R /Cs205 172 0 R /Cs206 170 0 R /Cs207 161 0 R /Cs208 160 0 R /Cs209 165 0 R /Cs210 163 0 R /Cs211 127 0 R /Cs212 128 0 R /Cs213 130 0 R /Cs214 125 0 R /Cs215 120 0 R /Cs216 122 0 R /Cs217 123 0 R /Cs218 141 0 R /Cs219 142 0 R /Cs220 144 0 R /Cs221 139 0 R /Cs222 133 0 R /Cs223 138 0 R /Cs224 137 0 R /Cs225 173 0 R /Cs226 207 0 R /Cs227 212 0 R /Cs228 210 0 R /Cs229 202 0 R /Cs230 203 0 R /Cs231 204 0 R /Cs232 213 0 R /Cs233 221 0 R /Cs234 226 0 R /Cs235 224 0 R /Cs236 215 0 R /Cs237 216 0 R /Cs238 218 0 R /Cs239 200 0 R /Cs240 181 0 R /Cs241 182 0 R /Cs242 184 0 R /Cs243 179 0 R /Cs244 174 0 R /Cs245 178 0 R /Cs246 186 0 R /Cs247 194 0 R /Cs248 196 0 R /Cs249 198 0 R /Cs250 193 0 R /Cs251 187 0 R /Cs252 192 0 R /Cs253 190 0 R /Cs254 46 0 R /Cs255 47 0 R /Cs256 50 0 R /Cs257 48 0 R /Cs258 40 0 R /Cs259 41 0 R /Cs260 42 0 R /Cs261 60 0 R /Cs262 61 0 R /Cs263 63 0 R /Cs264 62 0 R /Cs265 53 0 R /Cs266 54 0 R /Cs267 56 0 R /Cs268 38 0 R /Cs269 19 0 R /Cs270 24 0 R /Cs271 22 0 R /Cs272 18 0 R /Cs273 13 0 R /Cs274 17 0 R /Cs275 25 0 R /Cs276 32 0 R /Cs277 37 0 R /Cs278 35 0 R /Cs279 27 0 R /Cs280 26 0 R /Cs281 30 0 R /Cs282 65 0 R /Cs283 99 0 R /Cs284 104 0 R /Cs285 102 0 R /Cs286 94 0 R /Cs287 95 0 R /Cs288 97 0 R /Cs289 105 0 R /Cs290 113 0 R /Cs291 118 0 R /Cs292 116 0 R /Cs293 107 0 R /Cs294 108 0 R /Cs295 110 0 R /Cs296 109 0 R /Cs297 73 0 R /Cs298 74 0 R /Cs299 76 0 R /Cs300 71 0 R /Cs301 66 0 R /Cs302 70 0 R /Cs303 78 0 R /Cs304 87 0 R /Cs305 88 0 R /Cs306 90 0 R /Cs307 227 0 R /Cs308 79 0 R /Cs309 84 0 R /Cs310 82 0 R /Cs311 397 0 R /Cs312 386 0 R /Cs313 391 0 R /Cs314 425 0 R /Cs315 414 0 R /Cs316 349 0 R /Cs317 335 0 R /Cs318 376 0 R /Cs319 379 0 R /Cs320 366 0 R /Cs321 367 0 R /Cs322 368 0 R /Cs323 360 0 R /Cs324 361 0 R /Cs325 362 0 R /Cs326 378 0 R /Cs327 380 0 R /Cs328 372 0 R /Cs329 373 0 R /Cs330 374 0 R /Cs331 342 0 R /Cs332 343 0 R /Cs333 340 0 R /Cs334 337 0 R /Cs335 338 0 R /Cs336 354 0 R /Cs337 355 0 R /Cs338 356 0 R /Cs339 348 0 R /Cs340 382 0 R /Cs341 413 0 R /Cs342 417 0 R /Cs343 412 0 R /Cs344 407 0 R /Cs345 411 0 R /Cs346 410 0 R /Cs347 426 0 R /Cs348 422 0 R /Cs349 420 0 R /Cs350 389 0 R /Cs351 406 0 R /Cs352 393 0 R /Cs353 388 0 R /Cs354 385 0 R /Cs355 394 0 R /Cs356 401 0 R /Cs357 405 0 R /Cs358 400 0 R /Cs359 395 0 R /Cs360 399 0 R /Cs361 259 0 R /Cs362 260 0 R /Cs363 265 0 R /Cs364 263 0 R /Cs365 255 0 R /Cs366 256 0 R /Cs367 257 0 R /Cs368 266 0 R /Cs369 274 0 R /Cs370 279 0 R /Cs371 277 0 R /Cs372 268 0 R /Cs373 269 0 R /Cs374 271 0 R /Cs375 253 0 R /Cs376 235 0 R /Cs377 236 0 R /Cs378 238 0 R /Cs379 233 0 R /Cs380 228 0 R /Cs381 232 0 R /Cs382 240 0 R /Cs383 247 0 R /Cs384 249 0 R /Cs385 251 0 R /Cs386 246 0 R /Cs387 241 0 R /Cs388 245 0 R /Cs389 280 0 R /Cs390 314 0 R /Cs391 319 0 R /Cs392 318 0 R /Cs393 313 0 R /Cs394 308 0 R /Cs395 312 0 R /Cs396 320 0 R /Cs397 328 0 R /Cs398 333 0 R /Cs399 331 0 R /Cs400 327 0 R /Cs401 321 0 R /Cs402 326 0 R /Cs403 324 0 R /Cs404 288 0 R /Cs405 289 0 R /Cs406 291 0 R /Cs407 286 0 R /Cs408 282 0 R /Cs409 283 0 R /Cs410 284 0 R /Cs411 302 0 R /Cs412 303 0 R /Cs413 305 0 R /Cs414 300 0 R /Cs415 294 0 R /Cs416 299 0 R /Cs417 297 0 R >> >> endobj 13 0 obj [ /Indexed 293 0 R 17 814 0 R ] endobj 14 0 obj [ /Indexed 293 0 R 13 578 0 R ] endobj 15 0 obj [ /Indexed 293 0 R 36 776 0 R ] endobj 16 0 obj [ /Indexed 293 0 R 12 576 0 R ] endobj 17 0 obj [ /Indexed 293 0 R 16 809 0 R ] endobj 18 0 obj [ /Indexed 293 0 R 24 819 0 R ] endobj 19 0 obj [ /Indexed 293 0 R 26 821 0 R ] endobj 20 0 obj [ /Indexed 293 0 R 13 580 0 R ] endobj 21 0 obj [ /Indexed 293 0 R 33 754 0 R ] endobj 22 0 obj [ /Indexed 293 0 R 29 820 0 R ] endobj 23 0 obj [ /Indexed 293 0 R 10 581 0 R ] endobj 24 0 obj [ /Indexed 293 0 R 23 822 0 R ] endobj 25 0 obj [ /Indexed 293 0 R 18 808 0 R ] endobj 26 0 obj [ /Indexed 293 0 R 25 811 0 R ] endobj 27 0 obj [ /Indexed 293 0 R 24 812 0 R ] endobj 28 0 obj [ /Indexed 293 0 R 12 558 0 R ] endobj 29 0 obj [ /Indexed 293 0 R 39 779 0 R ] endobj 30 0 obj [ /Indexed 293 0 R 19 720 0 R ] endobj 31 0 obj [ /Indexed 293 0 R 13 472 0 R ] endobj 32 0 obj [ /Indexed 293 0 R 20 807 0 R ] endobj 33 0 obj [ /Indexed 293 0 R 24 452 0 R ] endobj 34 0 obj [ /Indexed 293 0 R 12 577 0 R ] endobj 35 0 obj [ /Indexed 293 0 R 25 813 0 R ] endobj 36 0 obj [ /Indexed 293 0 R 41 777 0 R ] endobj 37 0 obj [ /Indexed 293 0 R 22 810 0 R ] endobj 38 0 obj [ /Indexed 293 0 R 29 818 0 R ] endobj 39 0 obj [ /Indexed 293 0 R 23 571 0 R ] endobj 40 0 obj [ /Indexed 293 0 R 29 791 0 R ] endobj 41 0 obj [ /Indexed 293 0 R 29 790 0 R ] endobj 42 0 obj [ /Indexed 293 0 R 35 793 0 R ] endobj 43 0 obj [ /Indexed 293 0 R 25 457 0 R ] endobj 44 0 obj [ /Indexed 293 0 R 29 729 0 R ] endobj 45 0 obj [ /Indexed 293 0 R 20 573 0 R ] endobj 46 0 obj [ /Indexed 293 0 R 42 803 0 R ] endobj 47 0 obj [ /Indexed 293 0 R 44 802 0 R ] endobj 48 0 obj [ /Indexed 293 0 R 30 792 0 R ] endobj 49 0 obj [ /Indexed 293 0 R 20 574 0 R ] endobj 50 0 obj [ /Indexed 293 0 R 23 797 0 R ] endobj 51 0 obj [ /Indexed 293 0 R 19 569 0 R ] endobj 52 0 obj [ /Indexed 293 0 R 28 731 0 R ] endobj 53 0 obj [ /Indexed 293 0 R 33 817 0 R ] endobj 54 0 obj [ /Indexed 293 0 R 33 816 0 R ] endobj 55 0 obj [ /Indexed 293 0 R 23 460 0 R ] endobj 56 0 obj [ /Indexed 293 0 R 34 815 0 R ] endobj 57 0 obj [ /Indexed 293 0 R 13 579 0 R ] endobj 58 0 obj [ /Indexed 293 0 R 17 575 0 R ] endobj 59 0 obj [ /Indexed 293 0 R 29 730 0 R ] endobj 60 0 obj [ /Indexed 293 0 R 32 796 0 R ] endobj 61 0 obj [ /Indexed 293 0 R 31 795 0 R ] endobj 62 0 obj [ /Indexed 293 0 R 26 806 0 R ] endobj 63 0 obj [ /Indexed 293 0 R 31 794 0 R ] endobj 64 0 obj [ /Indexed 293 0 R 16 570 0 R ] endobj 65 0 obj [ /Indexed 293 0 R 21 627 0 R ] endobj 66 0 obj [ /Indexed 293 0 R 14 643 0 R ] endobj 67 0 obj [ /Indexed 293 0 R 7 564 0 R ] endobj 68 0 obj [ /Indexed 293 0 R 31 774 0 R ] endobj 69 0 obj [ /Indexed 293 0 R 7 562 0 R ] endobj 70 0 obj [ /Indexed 293 0 R 13 646 0 R ] endobj 71 0 obj [ /Indexed 293 0 R 12 644 0 R ] endobj 72 0 obj [ /Indexed 293 0 R 33 773 0 R ] endobj 73 0 obj [ /Indexed 293 0 R 14 621 0 R ] endobj 74 0 obj [ /Indexed 293 0 R 13 633 0 R ] endobj 75 0 obj [ /Indexed 293 0 R 15 464 0 R ] endobj 76 0 obj [ /Indexed 293 0 R 12 645 0 R ] endobj 77 0 obj [ /Indexed 293 0 R 10 567 0 R ] endobj 78 0 obj [ /Indexed 293 0 R 13 649 0 R ] endobj 79 0 obj [ /Indexed 293 0 R 27 636 0 R ] endobj 80 0 obj [ /Indexed 293 0 R 18 449 0 R ] endobj 81 0 obj [ /Indexed 293 0 R 9 489 0 R ] endobj 82 0 obj [ /Indexed 293 0 R 24 634 0 R ] endobj 83 0 obj [ /Indexed 293 0 R 21 785 0 R ] endobj 84 0 obj [ /Indexed 293 0 R 22 635 0 R ] endobj 85 0 obj [ /Indexed 293 0 R 7 490 0 R ] endobj 86 0 obj [ /Indexed 293 0 R 8 563 0 R ] endobj 87 0 obj [ /Indexed 293 0 R 16 650 0 R ] endobj 88 0 obj [ /Indexed 293 0 R 19 648 0 R ] endobj 89 0 obj [ /Indexed 293 0 R 4 527 0 R ] endobj 90 0 obj [ /Indexed 293 0 R 19 647 0 R ] endobj 91 0 obj [ /Indexed 293 0 R 34 780 0 R ] endobj 92 0 obj [ /Indexed 293 0 R 10 566 0 R ] endobj 93 0 obj [ /Indexed 293 0 R 12 557 0 R ] endobj 94 0 obj [ /Indexed 293 0 R 21 631 0 R ] endobj 95 0 obj [ /Indexed 293 0 R 15 632 0 R ] endobj 96 0 obj [ /Indexed 293 0 R 14 555 0 R ] endobj 97 0 obj [ /Indexed 293 0 R 18 630 0 R ] endobj 98 0 obj [ /Indexed 293 0 R 35 778 0 R ] endobj 99 0 obj [ /Indexed 293 0 R 21 626 0 R ] endobj 100 0 obj [ /Indexed 293 0 R 17 559 0 R ] endobj 101 0 obj [ /Indexed 293 0 R 18 467 0 R ] endobj 102 0 obj [ /Indexed 293 0 R 19 628 0 R ] endobj 103 0 obj [ /Indexed 293 0 R 17 560 0 R ] endobj 104 0 obj [ /Indexed 293 0 R 16 625 0 R ] endobj 105 0 obj [ /Indexed 293 0 R 15 629 0 R ] endobj 106 0 obj [ /Indexed 293 0 R 33 772 0 R ] endobj 107 0 obj [ /Indexed 293 0 R 14 617 0 R ] endobj 108 0 obj [ /Indexed 293 0 R 17 620 0 R ] endobj 109 0 obj [ /Indexed 293 0 R 16 622 0 R ] endobj 110 0 obj [ /Indexed 293 0 R 13 623 0 R ] endobj 111 0 obj [ /Indexed 293 0 R 12 565 0 R ] endobj 112 0 obj [ /Indexed 293 0 R 11 561 0 R ] endobj 113 0 obj [ /Indexed 293 0 R 20 624 0 R ] endobj 114 0 obj [ /Indexed 293 0 R 33 775 0 R ] endobj 115 0 obj [ /Indexed 293 0 R 17 556 0 R ] endobj 116 0 obj [ /Indexed 293 0 R 17 618 0 R ] endobj 117 0 obj [ /Indexed 293 0 R 17 466 0 R ] endobj 118 0 obj [ /Indexed 293 0 R 20 619 0 R ] endobj 119 0 obj [ /Indexed 293 0 R 31 732 0 R ] endobj 120 0 obj [ /Indexed 293 0 R 29 832 0 R ] endobj 121 0 obj [ /Indexed 293 0 R 20 552 0 R ] endobj 122 0 obj [ /Indexed 293 0 R 33 835 0 R ] endobj 123 0 obj [ /Indexed 293 0 R 33 838 0 R ] endobj 124 0 obj [ /Indexed 293 0 R 21 553 0 R ] endobj 125 0 obj [ /Indexed 293 0 R 32 833 0 R ] endobj 126 0 obj [ /Indexed 293 0 R 24 469 0 R ] endobj 127 0 obj [ /Indexed 293 0 R 31 582 0 R ] endobj 128 0 obj [ /Indexed 293 0 R 31 789 0 R ] endobj 129 0 obj [ /Indexed 293 0 R 38 727 0 R ] endobj 130 0 obj [ /Indexed 293 0 R 31 834 0 R ] endobj 131 0 obj [ /Indexed 293 0 R 20 551 0 R ] endobj 132 0 obj [ /Indexed 293 0 R 29 724 0 R ] endobj 133 0 obj [ /Indexed 293 0 R 39 826 0 R ] endobj 134 0 obj [ /Indexed 293 0 R 25 721 0 R ] endobj 135 0 obj [ /Indexed 293 0 R 20 549 0 R ] endobj 136 0 obj [ /Indexed 293 0 R 19 540 0 R ] endobj 137 0 obj [ /Indexed 293 0 R 39 824 0 R ] endobj 138 0 obj [ /Indexed 293 0 R 39 825 0 R ] endobj 139 0 obj [ /Indexed 293 0 R 47 831 0 R ] endobj 140 0 obj [ /Indexed 293 0 R 25 550 0 R ] endobj 141 0 obj [ /Indexed 293 0 R 38 839 0 R ] endobj 142 0 obj [ /Indexed 293 0 R 37 837 0 R ] endobj 143 0 obj [ /Indexed 293 0 R 24 548 0 R ] endobj 144 0 obj [ /Indexed 293 0 R 43 836 0 R ] endobj 145 0 obj [ /Indexed 293 0 R 23 465 0 R ] endobj 146 0 obj [ /Indexed 293 0 R 23 547 0 R ] endobj 147 0 obj [ /Indexed 293 0 R 35 753 0 R ] endobj 148 0 obj [ /Indexed 293 0 R 28 545 0 R ] endobj 149 0 obj [ /Indexed 293 0 R 42 737 0 R ] endobj 150 0 obj [ /Indexed 293 0 R 25 546 0 R ] endobj 151 0 obj [ /Indexed 293 0 R 35 751 0 R ] endobj 152 0 obj [ /Indexed 293 0 R 38 752 0 R ] endobj 153 0 obj [ /Indexed 293 0 R 35 747 0 R ] endobj 154 0 obj [ /Indexed 293 0 R 25 568 0 R ] endobj 155 0 obj [ /Indexed 293 0 R 37 748 0 R ] endobj 156 0 obj [ /Indexed 293 0 R 33 749 0 R ] endobj 157 0 obj [ /Indexed 293 0 R 25 544 0 R ] endobj 158 0 obj [ /Indexed 293 0 R 38 746 0 R ] endobj 159 0 obj [ /Indexed 293 0 R 36 750 0 R ] endobj 160 0 obj [ /Indexed 293 0 R 44 741 0 R ] endobj 161 0 obj [ /Indexed 293 0 R 44 738 0 R ] endobj 162 0 obj [ /Indexed 293 0 R 29 542 0 R ] endobj 163 0 obj [ /Indexed 293 0 R 35 743 0 R ] endobj 164 0 obj [ /Indexed 293 0 R 37 726 0 R ] endobj 165 0 obj [ /Indexed 293 0 R 37 744 0 R ] endobj 166 0 obj [ /Indexed 293 0 R 33 541 0 R ] endobj 167 0 obj [ /Indexed 293 0 R 35 745 0 R ] endobj 168 0 obj [ /Indexed 293 0 R 24 446 0 R ] endobj 169 0 obj [ /Indexed 293 0 R 24 543 0 R ] endobj 170 0 obj [ /Indexed 293 0 R 49 739 0 R ] endobj 171 0 obj [ /Indexed 293 0 R 40 725 0 R ] endobj 172 0 obj [ /Indexed 293 0 R 42 740 0 R ] endobj 173 0 obj [ /Indexed 293 0 R 40 827 0 R ] endobj 174 0 obj [ /Indexed 293 0 R 34 848 0 R ] endobj 175 0 obj [ /Indexed 293 0 R 23 454 0 R ] endobj 176 0 obj [ /Indexed 293 0 R 21 536 0 R ] endobj 177 0 obj [ /Indexed 293 0 R 29 736 0 R ] endobj 178 0 obj [ /Indexed 293 0 R 34 846 0 R ] endobj 179 0 obj [ /Indexed 293 0 R 33 847 0 R ] endobj 180 0 obj [ /Indexed 293 0 R 17 538 0 R ] endobj 181 0 obj [ /Indexed 293 0 R 28 842 0 R ] endobj 182 0 obj [ /Indexed 293 0 R 22 841 0 R ] endobj 183 0 obj [ /Indexed 293 0 R 17 539 0 R ] endobj 184 0 obj [ /Indexed 293 0 R 30 844 0 R ] endobj 185 0 obj [ /Indexed 293 0 R 29 734 0 R ] endobj 186 0 obj [ /Indexed 293 0 R 35 845 0 R ] endobj 187 0 obj [ /Indexed 293 0 R 34 801 0 R ] endobj 188 0 obj [ /Indexed 293 0 R 19 554 0 R ] endobj 189 0 obj [ /Indexed 293 0 R 24 459 0 R ] endobj 190 0 obj [ /Indexed 293 0 R 35 805 0 R ] endobj 191 0 obj [ /Indexed 293 0 R 16 572 0 R ] endobj 192 0 obj [ /Indexed 293 0 R 38 804 0 R ] endobj 193 0 obj [ /Indexed 293 0 R 31 798 0 R ] endobj 194 0 obj [ /Indexed 293 0 R 36 823 0 R ] endobj 195 0 obj [ /Indexed 293 0 R 18 534 0 R ] endobj 196 0 obj [ /Indexed 293 0 R 34 800 0 R ] endobj 197 0 obj [ /Indexed 293 0 R 31 735 0 R ] endobj 198 0 obj [ /Indexed 293 0 R 38 799 0 R ] endobj 199 0 obj [ /Indexed 293 0 R 18 535 0 R ] endobj 200 0 obj [ /Indexed 293 0 R 33 843 0 R ] endobj 201 0 obj [ /Indexed 293 0 R 24 723 0 R ] endobj 202 0 obj [ /Indexed 293 0 R 35 840 0 R ] endobj 203 0 obj [ /Indexed 293 0 R 40 852 0 R ] endobj 204 0 obj [ /Indexed 293 0 R 32 851 0 R ] endobj 205 0 obj [ /Indexed 293 0 R 19 530 0 R ] endobj 206 0 obj [ /Indexed 293 0 R 19 532 0 R ] endobj 207 0 obj [ /Indexed 293 0 R 37 830 0 R ] endobj 208 0 obj [ /Indexed 293 0 R 22 722 0 R ] endobj 209 0 obj [ /Indexed 293 0 R 21 531 0 R ] endobj 210 0 obj [ /Indexed 293 0 R 34 828 0 R ] endobj 211 0 obj [ /Indexed 293 0 R 25 470 0 R ] endobj 212 0 obj [ /Indexed 293 0 R 36 829 0 R ] endobj 213 0 obj [ /Indexed 293 0 R 35 850 0 R ] endobj 214 0 obj [ /Indexed 293 0 R 23 533 0 R ] endobj 215 0 obj [ /Indexed 293 0 R 35 855 0 R ] endobj 216 0 obj [ /Indexed 293 0 R 33 854 0 R ] endobj 217 0 obj [ /Indexed 293 0 R 20 537 0 R ] endobj 218 0 obj [ /Indexed 293 0 R 36 849 0 R ] endobj 219 0 obj [ /Indexed 293 0 R 29 733 0 R ] endobj 220 0 obj [ /Indexed 293 0 R 22 468 0 R ] endobj 221 0 obj [ /Indexed 293 0 R 41 853 0 R ] endobj 222 0 obj [ /Indexed 293 0 R 19 528 0 R ] endobj 223 0 obj [ /Indexed 293 0 R 27 728 0 R ] endobj 224 0 obj [ /Indexed 293 0 R 34 857 0 R ] endobj 225 0 obj [ /Indexed 293 0 R 20 529 0 R ] endobj 226 0 obj [ /Indexed 293 0 R 36 856 0 R ] endobj 227 0 obj [ /Indexed 293 0 R 26 642 0 R ] endobj 228 0 obj [ /Indexed 293 0 R 28 706 0 R ] endobj 229 0 obj [ /Indexed 293 0 R 22 451 0 R ] endobj 230 0 obj [ /Indexed 293 0 R 7 526 0 R ] endobj 231 0 obj [ /Indexed 293 0 R 23 768 0 R ] endobj 232 0 obj [ /Indexed 293 0 R 32 709 0 R ] endobj 233 0 obj [ /Indexed 293 0 R 27 703 0 R ] endobj 234 0 obj [ /Indexed 293 0 R 7 524 0 R ] endobj 235 0 obj [ /Indexed 293 0 R 24 711 0 R ] endobj 236 0 obj [ /Indexed 293 0 R 24 705 0 R ] endobj 237 0 obj [ /Indexed 293 0 R 9 525 0 R ] endobj 238 0 obj [ /Indexed 293 0 R 31 704 0 R ] endobj 239 0 obj [ /Indexed 293 0 R 21 767 0 R ] endobj 240 0 obj [ /Indexed 293 0 R 30 710 0 R ] endobj 241 0 obj [ /Indexed 293 0 R 31 661 0 R ] endobj 242 0 obj [ /Indexed 293 0 R 11 522 0 R ] endobj 243 0 obj [ /Indexed 293 0 R 21 461 0 R ] endobj 244 0 obj [ /Indexed 293 0 R 13 513 0 R ] endobj 245 0 obj [ /Indexed 293 0 R 28 660 0 R ] endobj 246 0 obj [ /Indexed 293 0 R 29 662 0 R ] endobj 247 0 obj [ /Indexed 293 0 R 28 708 0 R ] endobj 248 0 obj [ /Indexed 293 0 R 10 523 0 R ] endobj 249 0 obj [ /Indexed 293 0 R 25 707 0 R ] endobj 250 0 obj [ /Indexed 293 0 R 14 770 0 R ] endobj 251 0 obj [ /Indexed 293 0 R 25 685 0 R ] endobj 252 0 obj [ /Indexed 293 0 R 11 521 0 R ] endobj 253 0 obj [ /Indexed 293 0 R 20 716 0 R ] endobj 254 0 obj [ /Indexed 293 0 R 25 756 0 R ] endobj 255 0 obj [ /Indexed 293 0 R 23 691 0 R ] endobj 256 0 obj [ /Indexed 293 0 R 22 690 0 R ] endobj 257 0 obj [ /Indexed 293 0 R 18 702 0 R ] endobj 258 0 obj [ /Indexed 293 0 R 13 519 0 R ] endobj 259 0 obj [ /Indexed 293 0 R 23 687 0 R ] endobj 260 0 obj [ /Indexed 293 0 R 21 686 0 R ] endobj 261 0 obj [ /Indexed 293 0 R 29 755 0 R ] endobj 262 0 obj [ /Indexed 293 0 R 16 517 0 R ] endobj 263 0 obj [ /Indexed 293 0 R 18 692 0 R ] endobj 264 0 obj [ /Indexed 293 0 R 23 456 0 R ] endobj 265 0 obj [ /Indexed 293 0 R 20 689 0 R ] endobj 266 0 obj [ /Indexed 293 0 R 22 714 0 R ] endobj 267 0 obj [ /Indexed 293 0 R 11 515 0 R ] endobj 268 0 obj [ /Indexed 293 0 R 20 718 0 R ] endobj 269 0 obj [ /Indexed 293 0 R 26 719 0 R ] endobj 270 0 obj [ /Indexed 293 0 R 9 520 0 R ] endobj 271 0 obj [ /Indexed 293 0 R 26 717 0 R ] endobj 272 0 obj [ /Indexed 293 0 R 19 762 0 R ] endobj 273 0 obj [ /Indexed 293 0 R 21 458 0 R ] endobj 274 0 obj [ /Indexed 293 0 R 24 713 0 R ] endobj 275 0 obj [ /Indexed 293 0 R 12 516 0 R ] endobj 276 0 obj [ /Indexed 293 0 R 19 757 0 R ] endobj 277 0 obj [ /Indexed 293 0 R 23 715 0 R ] endobj 278 0 obj [ /Indexed 293 0 R 12 514 0 R ] endobj 279 0 obj [ /Indexed 293 0 R 24 712 0 R ] endobj 280 0 obj [ /Indexed 293 0 R 32 663 0 R ] endobj 281 0 obj [ /Indexed 293 0 R 0 512 0 R ] endobj 282 0 obj [ /Indexed 293 0 R 36 684 0 R ] endobj 283 0 obj [ /Indexed 293 0 R 27 682 0 R ] endobj 284 0 obj [ /Indexed 293 0 R 24 681 0 R ] endobj 285 0 obj [ /Indexed 293 0 R 20 742 0 R ] endobj 286 0 obj [ /Indexed 293 0 R 34 683 0 R ] endobj 287 0 obj [ /Indexed 293 0 R 13 510 0 R ] endobj 288 0 obj [ /Indexed 293 0 R 35 678 0 R ] endobj 289 0 obj [ /Indexed 293 0 R 33 677 0 R ] endobj 290 0 obj [ /Indexed 293 0 R 7 511 0 R ] endobj 291 0 obj [ /Indexed 293 0 R 34 680 0 R ] endobj 292 0 obj [ /Indexed 293 0 R 21 765 0 R ] endobj 293 0 obj [ /ICCBased 509 0 R ] endobj 294 0 obj [ /Indexed 293 0 R 5 672 0 R ] endobj 295 0 obj [ /Indexed 293 0 R 16 445 0 R ] endobj 296 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 146 /Widths [ 250 0 0 0 0 0 0 0 333 333 0 0 250 333 250 278 500 500 500 500 500 500 500 500 500 500 278 278 0 0 0 0 921 722 667 667 722 0 556 722 722 333 389 722 611 889 722 722 556 0 667 556 611 722 722 944 722 722 0 0 0 0 0 0 0 444 500 444 500 444 333 500 500 278 278 500 278 778 500 500 500 500 333 389 278 500 500 722 500 500 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 333 ] /Encoding /WinAnsiEncoding /BaseFont /FGCMDD+TimesNewRoman /FontDescriptor 298 0 R >> endobj 297 0 obj [ /Indexed 293 0 R 4 674 0 R ] endobj 298 0 obj << /Type /FontDescriptor /Ascent 891 /CapHeight 656 /Descent -216 /Flags 34 /FontBBox [ -568 -307 2028 1007 ] /FontName /FGCMDD+TimesNewRoman /ItalicAngle 0 /StemV 94 /XHeight 0 /FontFile2 508 0 R >> endobj 299 0 obj [ /Indexed 293 0 R 4 675 0 R ] endobj 300 0 obj [ /Indexed 293 0 R 7 669 0 R ] endobj 301 0 obj [ /Indexed 293 0 R 14 444 0 R ] endobj 302 0 obj [ /Indexed 293 0 R 26 676 0 R ] endobj 303 0 obj [ /Indexed 293 0 R 23 671 0 R ] endobj 304 0 obj << /Type /FontDescriptor /Ascent 891 /CapHeight 0 /Descent -216 /Flags 34 /FontBBox [ -558 -307 2034 1026 ] /FontName /FGCMEE+TimesNewRoman,Bold /ItalicAngle 0 /StemV 160 /FontFile2 507 0 R >> endobj 305 0 obj [ /Indexed 293 0 R 15 670 0 R ] endobj 306 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 121 /Widths [ 250 0 0 0 0 0 0 0 0 0 0 0 0 333 0 0 0 0 0 0 0 0 0 0 0 0 333 0 0 0 0 0 0 0 0 722 0 0 0 0 0 389 0 0 0 0 722 0 611 0 722 556 0 0 722 0 0 0 0 0 0 0 0 0 0 500 556 444 556 444 333 0 0 278 0 556 278 0 556 500 0 0 444 389 333 556 0 722 0 500 ] /Encoding /WinAnsiEncoding /BaseFont /FGCMEE+TimesNewRoman,Bold /FontDescriptor 304 0 R >> endobj 307 0 obj [ /Indexed 293 0 R 16 463 0 R ] endobj 308 0 obj [ /Indexed 293 0 R 35 659 0 R ] endobj 309 0 obj [ /Indexed 293 0 R 20 766 0 R ] endobj 310 0 obj [ /Indexed 293 0 R 13 505 0 R ] endobj 311 0 obj [ /Indexed 293 0 R 19 471 0 R ] endobj 312 0 obj [ /Indexed 293 0 R 28 654 0 R ] endobj 313 0 obj [ /Indexed 293 0 R 40 664 0 R ] endobj 314 0 obj [ /Indexed 293 0 R 34 666 0 R ] endobj 315 0 obj [ /Indexed 293 0 R 16 769 0 R ] endobj 316 0 obj [ /Indexed 293 0 R 12 503 0 R ] endobj 317 0 obj [ /Indexed 293 0 R 14 504 0 R ] endobj 318 0 obj [ /Indexed 293 0 R 45 665 0 R ] endobj 319 0 obj [ /Indexed 293 0 R 37 667 0 R ] endobj 320 0 obj [ /Indexed 293 0 R 30 653 0 R ] endobj 321 0 obj [ /Indexed 293 0 R 28 656 0 R ] endobj 322 0 obj [ /Indexed 293 0 R 17 501 0 R ] endobj 323 0 obj [ /Indexed 293 0 R 15 764 0 R ] endobj 324 0 obj [ /Indexed 293 0 R 39 679 0 R ] endobj 325 0 obj [ /Indexed 293 0 R 20 506 0 R ] endobj 326 0 obj [ /Indexed 293 0 R 35 668 0 R ] endobj 327 0 obj [ /Indexed 293 0 R 31 657 0 R ] endobj 328 0 obj [ /Indexed 293 0 R 38 652 0 R ] endobj 329 0 obj [ /Indexed 293 0 R 14 502 0 R ] endobj 330 0 obj [ /Indexed 293 0 R 18 763 0 R ] endobj 331 0 obj [ /Indexed 293 0 R 35 658 0 R ] endobj 332 0 obj [ /Indexed 293 0 R 15 500 0 R ] endobj 333 0 obj [ /Indexed 293 0 R 38 655 0 R ] endobj 334 0 obj [ /Indexed 293 0 R 14 518 0 R ] endobj 335 0 obj [ /Indexed 293 0 R 23 593 0 R ] endobj 336 0 obj [ /Indexed 293 0 R 24 782 0 R ] endobj 337 0 obj [ /Indexed 293 0 R 20 610 0 R ] endobj 338 0 obj [ /Indexed 293 0 R 24 609 0 R ] endobj 339 0 obj [ /Indexed 293 0 R 13 485 0 R ] endobj 340 0 obj [ /Indexed 293 0 R 17 599 0 R ] endobj 341 0 obj [ /Indexed 293 0 R 16 462 0 R ] endobj 342 0 obj [ /Indexed 293 0 R 24 588 0 R ] endobj 343 0 obj [ /Indexed 293 0 R 22 587 0 R ] endobj 344 0 obj [ /Indexed 293 0 R 13 494 0 R ] endobj 345 0 obj [ /Indexed 293 0 R 18 788 0 R ] endobj 346 0 obj [ /Indexed 293 0 R 9 486 0 R ] endobj 347 0 obj [ /Indexed 293 0 R 17 450 0 R ] endobj 348 0 obj [ /Indexed 293 0 R 17 615 0 R ] endobj 349 0 obj [ /Indexed 293 0 R 22 616 0 R ] endobj 350 0 obj [ /Indexed 293 0 R 14 475 0 R ] endobj 351 0 obj [ /Indexed 293 0 R 17 447 0 R ] endobj 352 0 obj [ /Indexed 293 0 R 13 477 0 R ] endobj 353 0 obj [ /Indexed 293 0 R 17 476 0 R ] endobj 354 0 obj [ /Indexed 293 0 R 20 608 0 R ] endobj 355 0 obj [ /Indexed 293 0 R 20 611 0 R ] endobj 356 0 obj [ /Indexed 293 0 R 19 614 0 R ] endobj 357 0 obj [ /Indexed 293 0 R 24 783 0 R ] endobj 358 0 obj [ /Indexed 293 0 R 10 493 0 R ] endobj 359 0 obj [ /Indexed 293 0 R 20 448 0 R ] endobj 360 0 obj [ /Indexed 293 0 R 7 596 0 R ] endobj 361 0 obj [ /Indexed 293 0 R 7 595 0 R ] endobj 362 0 obj [ /Indexed 293 0 R 10 590 0 R ] endobj 363 0 obj [ /Indexed 293 0 R 11 497 0 R ] endobj 364 0 obj [ /Indexed 293 0 R 10 496 0 R ] endobj 365 0 obj [ /Indexed 293 0 R 11 492 0 R ] endobj 366 0 obj [ /Indexed 293 0 R 17 594 0 R ] endobj 367 0 obj [ /Indexed 293 0 R 11 597 0 R ] endobj 368 0 obj [ /Indexed 293 0 R 9 598 0 R ] endobj 369 0 obj [ /Indexed 293 0 R 21 787 0 R ] endobj 370 0 obj [ /Indexed 293 0 R 22 784 0 R ] endobj 371 0 obj [ /Indexed 293 0 R 12 495 0 R ] endobj 372 0 obj [ /Indexed 293 0 R 16 583 0 R ] endobj 373 0 obj [ /Indexed 293 0 R 19 586 0 R ] endobj 374 0 obj [ /Indexed 293 0 R 21 589 0 R ] endobj 375 0 obj [ /Indexed 293 0 R 23 781 0 R ] endobj 376 0 obj [ /Indexed 293 0 R 19 592 0 R ] endobj 377 0 obj [ /Indexed 293 0 R 12 498 0 R ] endobj 378 0 obj [ /Indexed 293 0 R 11 585 0 R ] endobj 379 0 obj [ /Indexed 293 0 R 18 591 0 R ] endobj 380 0 obj [ /Indexed 293 0 R 12 584 0 R ] endobj 381 0 obj [ /Indexed 293 0 R 11 487 0 R ] endobj 382 0 obj [ /Indexed 293 0 R 13 613 0 R ] endobj 383 0 obj [ /Indexed 293 0 R 22 761 0 R ] endobj 384 0 obj [ /Indexed 293 0 R 9 491 0 R ] endobj 385 0 obj [ /Indexed 293 0 R 23 697 0 R ] endobj 386 0 obj [ /Indexed 293 0 R 25 640 0 R ] endobj 387 0 obj [ /Indexed 293 0 R 17 481 0 R ] endobj 388 0 obj [ /Indexed 293 0 R 26 694 0 R ] endobj 389 0 obj [ /Indexed 293 0 R 19 651 0 R ] endobj 390 0 obj [ /Indexed 293 0 R 14 483 0 R ] endobj 391 0 obj [ /Indexed 293 0 R 22 641 0 R ] endobj 392 0 obj [ /Indexed 293 0 R 16 484 0 R ] endobj 393 0 obj [ /Indexed 293 0 R 22 695 0 R ] endobj 394 0 obj [ /Indexed 293 0 R 20 700 0 R ] endobj 395 0 obj [ /Indexed 293 0 R 22 693 0 R ] endobj 396 0 obj [ /Indexed 293 0 R 18 480 0 R ] endobj 397 0 obj [ /Indexed 293 0 R 24 637 0 R ] endobj 398 0 obj [ /Indexed 293 0 R 18 499 0 R ] endobj 399 0 obj [ /Indexed 293 0 R 18 688 0 R ] endobj 400 0 obj [ /Indexed 293 0 R 25 698 0 R ] endobj 401 0 obj [ /Indexed 293 0 R 19 701 0 R ] endobj 402 0 obj [ /Indexed 293 0 R 21 455 0 R ] endobj 403 0 obj [ /Indexed 293 0 R 16 479 0 R ] endobj 404 0 obj [ /Indexed 293 0 R 26 758 0 R ] endobj 405 0 obj [ /Indexed 293 0 R 24 699 0 R ] endobj 406 0 obj [ /Indexed 293 0 R 23 696 0 R ] endobj 407 0 obj [ /Indexed 293 0 R 18 601 0 R ] endobj 408 0 obj [ /Indexed 293 0 R 7 488 0 R ] endobj 409 0 obj [ /Indexed 293 0 R 15 474 0 R ] endobj 410 0 obj [ /Indexed 293 0 R 19 603 0 R ] endobj 411 0 obj [ /Indexed 293 0 R 23 600 0 R ] endobj 412 0 obj [ /Indexed 293 0 R 17 602 0 R ] endobj 413 0 obj [ /Indexed 293 0 R 14 612 0 R ] endobj 414 0 obj [ /Indexed 293 0 R 23 638 0 R ] endobj 415 0 obj [ /Indexed 293 0 R 23 771 0 R ] endobj 416 0 obj [ /Indexed 293 0 R 15 473 0 R ] endobj 417 0 obj [ /Indexed 293 0 R 17 607 0 R ] endobj 418 0 obj [ /Indexed 293 0 R 25 759 0 R ] endobj 419 0 obj [ /Indexed 293 0 R 17 453 0 R ] endobj 420 0 obj [ /Indexed 293 0 R 19 604 0 R ] endobj 421 0 obj [ /Indexed 293 0 R 15 482 0 R ] endobj 422 0 obj [ /Indexed 293 0 R 12 605 0 R ] endobj 423 0 obj [ /Indexed 293 0 R 19 786 0 R ] endobj 424 0 obj [ /Indexed 293 0 R 17 478 0 R ] endobj 425 0 obj [ /Indexed 293 0 R 23 639 0 R ] endobj 426 0 obj [ /Indexed 293 0 R 15 606 0 R ] endobj 427 0 obj [ /Indexed 293 0 R 26 760 0 R ] endobj 428 0 obj 762 endobj 429 0 obj << /Filter /FlateDecode /Length 428 0 R >> stream +H‰””Mo›@†ïüŠ9.Æû½KNUªJ¤V­‚z‰zp‰ÜÚ bèÇ¿ï°8¶7Ñ®,yÁ¼3žwfxÞVÙ¢ª$¨2!Ó‡mKô`$ +ÎTÛl±ÜY¨wá9‡]Ýf‹÷7wG4uV<]þÊزkX B^}Ë$–Î@!P¨.3>‰y…ÇT€ž (¤Aá Xʤgí¿Ù§¿²[öq5¬»vµ«6·hØC¿Ú ýXçÆ>œMN1%ƒ›¦ûõð–]Ñõ÷ë6òi‡¾üku}Ú +ñs•ä +¥§-r;÷B8tž~;º6øìP,Îî„G®HMµ5ÿdJS¬^m›¾kû7ízW×øØýÄñ{ˆ+”U»c7Ü8× ænÀ§¾»ërᜨٗqÓ6ýên½!ßyá¨E³ÑÓ¤ûR)§”3·ìê]=6Û¼¤ &W”F‚‹óè“^ìÛðBÙÂ=[‘[V5› à’ƒ£qiæóB0.Åt J…Íïát¸1á›bBAîiVîdT։螯Úóéj.Bˆõ4œ}ÈÔ}ܸ}Sî¨T—Óz2çËp–2Þ«òÅöœýÿq¼(Ý¡9áÿh­¯n–Ë oÁ¹Õ2l±~=ùY^£­žž²ó-šÃÎ"œšæ¿ßq“›­s ×ã†^3Çh•,•dÜÐ8è™ +ßs•ïªìGV–¨ìL +¤NzB ½@D7M¥&˜\m\vÙç×ÄF&ˆ¥Os-öèy‚ØÄô¨â Ò¬â :ôñÚxƒŽ~M‹xƒ–Ž±7hQǤåŽ7h°Œ7hÐÆ4¨ã ”ñ5–ñ5ºxƒ„åxƒšnÄ<Þ JŒJŒJŒJŒLŒLŒLŒLŒHŒHŒHŒH O O O O€Œ) CâxȐ82$Ž‡Œñ !q> stream +H‰”Ö-Ž1Ea^«¨xì÷ç2˜5FÙ?‰¢º ¢S­M.yú¬£:Öj^gÿûkçµÚu3«¹u?}Ÿ_ãüñ}ü<~ÿ÷ëñ8ÛoŒ«¿1özc<žûïq=?0Z0almÝŽç}àÄqÜ^8¶ûÀ…ã.‚Ö£M!$ÃÑR)¹ŒfòJ‰|´.ϔ{»äJrì-åJ‚ì/­!Éþ ŒõR°Ükɍe,퍁å^Kp ,ãÒâXîµ$ÇÀr¯¥9–{-Ñ1°Œ©Õ1°ÜkÍYN펑åÔð8Y––Çɲ4=N–¥íq²,“ei}œ,Sëãd™Z'ËÔú8Y¦ÖÇÉ2´>A–¡õ ² ­Oeh}‚,]ëdéZŸ K×úYºÖ'ÈÒ´>A–¦õ ²4­O’¥i}’,‡Ö'Érh}’,‡Ö'Ér¼|öe×ú$Yv­O’e×ú$Yv­O’e×úXúÒúXîµÔ§Àr¯¥>–{-õ)°ôKëS`¹×RŸ˽–úXîµÔ§ÀÒ§Ö§Àr¯¥>“,ç¿úü`gì endstream endobj 432 0 obj 475 endobj 433 0 obj << /Filter /FlateDecode /Length 432 0 R >> stream +H‰„Ô;ŠQ „áü®â®@£’Ôç‘;™Ðkp< Þâ3`8¥¨è é¦ñÁÿúøüšxÿú~ý~ý}ím9ÞþóXÔ{m[ë=sÂóýçëõ³±çu×)×£îºäºü®¹Æ¸ë!֏mºrÊõ +—\]¹å:î•Ëźlß+—²,›÷Ê¥,Ëê^¹”e»V–eNW*Ë´IW*Ë´‡®T–iAW*Ë4§+•eغWneöÜ+·² Ë{åV–a~¯Üʶî•[YÂ]©,qþÞµ²×g+Kçúleé\Ÿ­,ëW˜Îù ÍØܸàùTazæŧ +Ô3>U¨ž9uª19D€R\"@©NN T'·Pªƒc(ÕÁ5”êàJup¥úp¥úp‘N@䜒„Pª7 ¡T‹£„PªÅUB(ÕjY +¥Z-K¡T³e)”j¶,…R͖¥PªÙ²”J5Z–R©FËR*ÕhYJ¥-K©T£e)•*Z–R©¢e)•*Z–R©¢e)•ª·,•Rõ–¥RªÞ²TJÕ[–J¨b·,•P=sÎR U얥ªgÎY*¡ŠÕ²TBõÌÿgéŸXùèô endstream endobj 434 0 obj 464 endobj 435 0 obj << /Filter /FlateDecode /Length 434 0 R >> stream +H‰„Ô-ŽADaÞ§è”3£þ¹‰¡Ï`¼Zíý‰kXzj0R+¤>õ{~ýùʶßßßÏßççÙ»ÔñÆç)jïÚe­wæ*-¢¾ÿ¾žÏ¼ÎsØ˖ͅó±l^qޚÍÎå§v˜²ýԁóé§Nœ7?uá\~*©Žvê Õ^¦:Hµ—n§RíEvê Õ^ÂN¤ÚÊòSIµ•î§’j+ÕO%ÕVÂO%ÕZ–ŸJªµ ;u’j=omNªµ¤:IUçÇ椪2ìÔIªº²4IUW–&©æ•¥Iªyei’j^Yš¤šW–©Æ•¥Eªqei‘j\YZ¤W–©Æ•¥ª±¯,-P=sÏÒÕ3÷,-P=sÏÒÕXW–6¨ž¹giƒê™{–6¨ž¹giƒjÌ+KTÏܳ´Iu^YÚ¤:¯,mRW–6©Ž+K›T‡gé|¶8·,)Hµ{–¤Ú=KŸ?Òܲ¤ ÕîYRjó,)Hµy–¤Ú> stream +H‰„Ô=j%1Eáü­¢W Q«~Tʝ8ô&6ÆûO¦ ®:47)>8×Û×ëãõý:gX^óç˯:£êÊçïYÓ®¿Ÿ¯?ïŸkí‹æYm^8woóƒó5ç6a^ãd›ß8ßíT[8÷vªÎW;Õ糟0ßc÷SçÑO%Õ=V?•T÷˜ýTRÍQíT'ÕÑNuRÍaíT'Õ³ê¤£Ú©Nª1²ŸJªñümsRq÷SI՟§ÍIÕGöSIՇ·SƒT}ÜíÔ U“,©šd)HÕ$KAª&Y +R]’¥ Õ%Y +R]’¥ Õ%Y +R]’¥$Õ[²”¤zK–’ToÉR’ê-YJR’¥$Õ)YJR’¥$Õ)YJPýyú© ú<=KTëH–6¨>OÏÒÕ*ÉÒÕgÞ³´Aõ™÷,mP}æ=KTkK–6¨>óž¥Mª[²´IuK–ŠTS²T¤š’¥"Ք,©¦d©H5%KEª!Y*R ÉR‘jH–ŠTC²T¤ê’¥Cª.Y:¤ê’¥Cª.Y:¤j’¥Cª&Y:¤j’¥Cª&Y:¤º$K‡T—déêêY²Iª«gÉ&©Þ=K6IõîY²ù_õŸ6é endstream endobj 438 0 obj 460 endobj 439 0 obj << /Filter /FlateDecode /Length 438 0 R >> stream +H‰„Ô;®1EÑüŽâŽÀØ®Ÿ;'!d ÄOˆù'ø :lu`©u’Ò’öëy†å{~~cûû<ãœwž5ܧ½|¼¾|û°éï¯?_ß_¿^ÿœïÙæó9žlóÄyí6/œûióƒóÝO}p>Û©kþ^ϨvêZ8vêÚ8ßíÔe8ŸíÔªuÆ駂êG?TïÜú© z糟 +ªUãôSAõγºIµîß6'Õ«ºI5ïÓ椚#Û©›Tsx?•Ts¬~*©Æxú©¤#û©¤’¥Mª!Y2Ruɒ‘ªK–ŒT]²d¤ê’%#U—,©šdÉHÕ$KFª&Y2R5ɒ‘ê–,9©nɒ“ê–,9©nɒ“ê’,9©.ɒ“ê’,9©.ɒ“ê”,9©Nɒ“ê”,©NÉR€j>’¥Õ;ïY +P½óž¥Õ;ïY +PÍ#Y +P½óž¥Õ;ïY +P½óž¥Õ;ïYJP͒,%©–d)Iµ$KIª%YJRMÉR’jJ–’TS²”¤š’¥$Ր,%©†d©H5>³ä礒¥"U—,©ºd©HÕ%KEª.Y*R5ÉR‘ªI–ŠTM²T¤j’¥CªûO–~ 03*ìí endstream endobj 440 0 obj 824 endobj 441 0 obj << /Filter /FlateDecode /Length 440 0 R >> stream +H‰”—]oÓ0†ïó+|™ Õ³$\®Ch€Æ`áCb\dmÊm"²”jÿž;KOéMZ³ìññyÏk½r£³Ë]šIvÑFQžóÔ21üp¥Y–ó,cÖ*î”HÙjy\‘¸Îž’¸ÒBO¸&q!PuCà’;‹pKâKu$®°ÔŒÄ…FxNà‚gâ8™\¸ARsÊUÁS$5§\\ ©9᪁$5'\Ü"WsÂU3¼E“!\\b©„«&ƒ„®n±TÂUÀõQ*<’¸´'\5Žç +ᄫ€Û ᔫŽkpÊUÇ–J¹jyŽ¥R®ZKZP®ZKZP®ZKZP®ZKZR®K”§‡ £H¢aH¬qÑ°™/Pã(¢a1_`Šcˆ†QÑ0Š –ó*?4lç T8zhXÎwPâØ¡a;_ Ä‘CÃj¾@ã††Ý|G £ ¡a1[ Îÿ#dž2Ï€ÿ™ó"’0ÿÌÓáI«&¾ØE‚«á×!ŠYR|À^w²…ç¤cÅE$w™Ê.fžYÈábãr¶\št€üÐr_kx2¾àõ[vþö3ËRå— Ïkgž(3mþ%~Ó6ë6h–|-^ø±¼œªk_ý擼fòüeh{ìHñÔï~Òö(ïÞS®Mz ڎ=†Mǁ¨0@5Û …mÞɚi ֗»¨ÊÎÿ»x†7€¿ÂÃYQhš6ãz;­w½ð’]˜Íûê9cWUHàî·Ývݵý0-¯@MÜnÙMµÚwuÿÈ>î·MՕwõ¶îëê!/ã0ÓETh¸(ƒ$•Â­P_XWEj&ÅiªàȬBBü㼀 d,I5֚Ƈ†3 à8¥ 2 *‹ûŠ}hê¾Z³×uómÝî¸ÈÅìªìë¶)·ì²ÙtåCßíWý¾«‚" —7¸ËŠÉÇÐÛ4‹e»h»uÝølY5=¬¼¯.o–ËÛd<¡Æ©‹rêo8×C÷åÌh%¶ì®ZAƒU2,ŒYy(“……§nxïY»aO}üÚoC¿–Ã×5qzXü6)ìxø-ÀvÜo endstream endobj 442 0 obj 1538 endobj 443 0 obj << /Filter /FlateDecode /Length 442 0 R >> stream +H‰|WÍrÛ6¾û)p$;+REMN§¦Ó$X´“é"! 1¨(G¯Ñ'î·XP”l%›¤ÉÅî~?»¾ù”ÕÉMºÈÊD§“¿ZíµrBáÔA¥ólžté é?ëßnª¬XŠ©X¿¾™fÓét&ÖõÍd¸|ºIZa”²Ý£ØwÖÛÚ¶îV¤ëÏ7“b‘åGä‹Ó×súäSò묘݊ûßê/i•å‰Jq•àÑýïBšFü5ŸN3!Ö;%ž瑗Ùbºˆ™œ’È9à£Qш/é2«8N-’£ÀE‰‹íV՞ÒkúÚ;áwҋ£íEˆ;‰)Ñù"FG]üºÊÄZ9¯ÍƒðV4Ò+±“NtªÕrÓC¡ù<«Î:4;Ë­­ÙêŽJ-¸Ô*i8 )œ~0z«ki¼0=¿³Q°Û!=Š~ÙÅj<¡âBËdß"üò­2^zmÛÎò#Àܨ½Âœw *Îhž˜ÆvÜèeh¯!N)Ði=8(Ñè-ïÛ@Ÿ=bÍ@dºLl 8À¤sl• }µê¼ÉbUáSY\LN' W A ”@ï¼H +bj§ý‘Úäq`(³¼<ËûÛ]’`>t}½#VlZÅpâ ;*flW$ÍH1‚ò ©‚ëÄ߃¢veø +i‹7f`ËjþA}JX’5aŽ¢–Dí}Cï7J±µ=ÎÂ!'¦ òUòü*ѽ +L\%Ú›á(*16> ÇæIÛoÁr`¸JA ðòYV•W…˜Hbiنöªî I@â©[*}••'S½ÅXzÁÉõ]1KÞ(¡¾î[«=Ԇª±Ôb–ÍËÅ3Y¬Æp+'Q•F¦ÔLª×{Y?* "­8GQ„èYŒñ"ñ?Žlß6¢ÕŠïv²SÚl¹…³$h¾ÅH=i¿ nC¼€äå·‚ìÀ0¯ã=õ7pyȋ^Ž ŽìØö]BضÒ=†Ð”‰~€—‰A¡ËÆòÙjžø!·è¢E¾ø®[qúTþG«šªu!96(É&fä½2Z¿¦˜õ¡oÃüÑ> stream +ýýýþÿþÿÿÿ†i{º©³ÇÇǜœœ¯¯¯ìì쨨¨¦¦¦§§§¡¡¡ÒÒҞŒ— +endstream endobj 445 0 obj << /Length 52 >> stream +ýýýÿÿÿù÷øxYlÏÃËööö»»»ŸŸŸ§§§®®®ÇÇÇ¡¡¡¦¦¦ñññ¯©Žu„þþþ +endstream endobj 446 0 obj << /Length 76 >> stream +ýýýÿÿÿ¶¤¯atþýþþÿÿþþþùùù®®®¡¡¡åååóó󞞞ÆÆÆÞÞÞÔÔÔ¨¨¨¦¦¦§§§¢¢¢¥¥¥°°°öôõqQeÖËÒ +endstream endobj 447 0 obj << /Length 55 >> stream +ýýýÿÿÿöôõrSgÜÓØÖÖ֓““©©©§§§¦¦¦«««¨¨¨žžžéé麪´€cuþýþþÿÿ +endstream endobj 448 0 obj << /Length 64 >> stream +ýýýÿÿÿéäçjL^òïñÛÛۑ‘‘ƒƒƒ‡‡‡¥¥¥¨¨¨§§§±±±¤¤¤£££µµµüüüþþþÜÓØrSgöôõ +endstream endobj 449 0 obj << /Length 58 >> stream +ýýýþÿÿþýþ€cuºª´ÿÿÿéééÛÛÛ   •••›››©©©§§§¦¦¦¬¬¬¢¢¢ÖÖÖ¢›–Ž +endstream endobj 450 0 obj << /Length 55 >> stream +ýýýÿÿÿ¯©Žu„þþþ¬¬¬¥¥¥¨¨¨   ÄÄĤ¤¤§§§¡¡¡¶¶¶ù÷ùwWjʼŠ+endstream endobj 451 0 obj << /Length 70 >> stream +ýýýÿÿÿÜÓØrSgöôõþþþûûû   ºººôôô»»»¥¥¥¤¤¤§§§ŸŸŸÌÌ̽½½¡¡¡¦¦¦õõõéäçjL^òïñ +endstream endobj 452 0 obj << /Length 76 >> stream +ýýýÿÿÿéäçjL^òïñþþþøøøØØØûûûÙÙÙ   ¿¿¿ÑÑÑÌÌÌÝÝݖ––¨¨¨§§§£££¢¢¢¡¡¡êêêÖËÒqQeöôõ +endstream endobj 453 0 obj << /Length 55 >> stream +ýýýÿÿÿœ‰•¡ŽšÚÚÚ´´´›››œœœ¨¨¨§§§ŸŸŸÌÌ̞žž¢¢¢ÖÖÖþþþv†´¢­ +endstream endobj 454 0 obj << /Length 73 >> stream +ýýýÿÿÿºª´€cuþýþþÿÿþþþ÷÷÷´´´öööÄÄÄÅÅÅÈÈȘ˜˜¸¸¸   ¨¨¨§§§©©©£££ØØØöôõrSgÜÓØ +endstream endobj 455 0 obj << /Length 67 >> stream +ýýýþÿþÿÿÿ„hyµ¤®þþþüüü¬¬¬ÏÏÏììì¡¡¡¢¢¢¥¥¥´´´¦¦¦¨¨¨ÅÅŧ§§¤¤¤õõõžŒ— +endstream endobj 456 0 obj << /Length 73 >> stream +ýýýÿÿÿøö÷sTgÐÄËÊÊʕ••ààत¤¥¥¥¨¨¨¡¡¡···¸¸¸ŽŽŽÚÚÚÃÃݝ§§§   ¼¼¼þþþ´£®Šo€ +endstream endobj 457 0 obj << /Length 79 >> stream +ýýýþÿþÿÿÿ„hyµ¤®þþþùùù¡¡¡ÇÇÇÈÈÈÄÄĖ––éééëë뛛›ÔÔÔ···œœœ¨¨¨§§§©©©¦¦¦¥¥¥¢¢¢ºººžŒ— +endstream endobj 458 0 obj << /Length 67 >> stream +ýýýÿÿÿòïñlN`ïìíÏÏÏÇÇÇñññ‘‘‘¤¤¤§§§¨¨¨   ŒŒŒ×××òòò¥¥¥¢¢¢ÖÖÖÏÃËxYlù÷ø +endstream endobj 459 0 obj << /Length 76 >> stream +ýýýÿÿÿŸ˜™ƒëëëøøøþþþ«««áááîîîûûû¬¬¬¶¶¶¼¼¼   §§§£££²²²ªªª¢¢¢õõõþÿÿþýþat¶¤¯ +endstream endobj 460 0 obj << /Length 73 >> stream +ýýýÿÿÿøö÷sTgÐÄËôôô———çççÇÇǕ••ÈÈÈÌÌ̑‘‘îîî±±±ŸŸŸ¨¨¨§§§¢¢¢¥¥¥ÍÍ͵¤®„hyþÿþ +endstream endobj 461 0 obj << /Length 67 >> stream +ýýýÿÿÿĵ¿~`süûüÚÚÚ   èèèæææ~~~¢¢¢¨¨¨ÜÜÜÙÙٛ››§§§ŸŸŸ¹¹¹þþþôòópQdâÛß +endstream endobj 462 0 obj << /Length 52 >> stream +ýýýÿÿÿʼÅwWjù÷ùàà॥¥¦¦¦§§§¤¤¤µµµ©©©¡¡¡ÝÝÝòïñjL^éäç +endstream endobj 463 0 obj << /Length 52 >> stream +ýýýÿÿÿœ‰•¡ŽšØØؓ““¤¤¤õõõËËË   §§§¥¥¥®®®øøøþþþŽu„¯© +endstream endobj 464 0 obj << /Length 49 >> stream +ýýýÿÿÿ–Ž¢›¸¸¸ãããüüüººº¤¤¤§§§¦¦¦žžžÈÈÈþþþŽu„¯© +endstream endobj 465 0 obj << /Length 73 >> stream +ýýýþÿÿþýþ€cuºª´ÿÿÿþþþùùù®®®÷÷÷©©©¦¦¦¨¨¨¡¡¡‚‚‚ÆÆÆ»»»§§§¤¤¤¥¥¥²²²úúú¢›–Ž +endstream endobj 466 0 obj << /Length 55 >> stream +ýýýÿÿÿ¯©Žu„þþþèèèÐÐÐõõõüüüººº¤¤¤§§§ªªª¦¦¦¢¢¢ù÷ùwWjʼŠ+endstream endobj 467 0 obj << /Length 58 >> stream +ýýýÿÿÿʼÅwWjù÷ùôôôœœœ¼¼¼þþþ»»»ŸŸŸ§§§¦¦¦¤¤¤¬¬¬øøøòïñjL^éäç +endstream endobj 468 0 obj << /Length 70 >> stream +ýýýÿÿÿÜÓÙnObõòôÔÔԕ••éééÅÅŖ––¤¤¤šššÈÈÈÚÚڏ¨¨¨§§§¦¦¦ÃÃޞžãÜàhI\òðñ +endstream endobj 469 0 obj << /Length 76 >> stream +ýýýÿÿÿ™ƒŸ˜þþþùùù¯¯¯ªªªøøøüüü¢¢¢¥¥¥«««ÜÜ܉‰‰¨¨¨§§§¤¤¤¦¦¦£££°°°þÿþ„hyµ¤® +endstream endobj 470 0 obj << /Length 79 >> stream +ýýýÿÿÿóñòlM`âÛàþþþùùù®®®¥¥¥öööúúúµµµ¦¦¦£££§§§¬¬¬‹‹‹ŸŸŸ¨¨¨¢¢¢¹¹¹°°°¼¼¼¿¯¹}^qüûü +endstream endobj 471 0 obj << /Length 61 >> stream +ýýýÿÿÿ«˜£’{ŠýþþçççÃÃÃþþþÎÎΙ™™©©©¡¡¡žžžåå姧§ÜÜÜüûü€buÉ»Ä +endstream endobj 472 0 obj << /Length 43 >> stream +ýýýÿÿÿúùúnNb¯¨ôôô¡¡¡§§§   ïïïýþþ”~Œ…k{þþþ +endstream endobj 473 0 obj << /Length 49 >> stream +ýýýÿÿÿðëîZ8M”}‹þþþõõõ¢¢¢§§§¥¥¥²²²úúúþüýx[msTgüûü +endstream endobj 474 0 obj << /Length 49 >> stream +ýýýÿÿÿ¼¬¶J&<ÐÃË÷÷÷¥¥¥   ›››žžž¶¶¶úúúþþþ¶£¯P,BÖÊÒ +endstream endobj 475 0 obj << /Length 46 >> stream +ýýýþþþÿÿÿ˜€[9NðëîÙÙٜœœ¨¨¨¦¦¦¤¤¤õõõÜÑØR.Dµ£® +endstream endobj 476 0 obj << /Length 55 >> stream +ýýýþÿÿÿþÿ}arrTgüûüÿÿÿööö   ŸŸŸ¶¶¶ÃÃÃüüüþþþðëî[9N˜€ +endstream endobj 477 0 obj << /Length 43 >> stream +ýýýÿÿÿÜÑØQ-C»«µóó󝝝§§§   ôôôþþþ›„“\:Oðëî +endstream endobj 478 0 obj << /Length 55 >> stream +ýýýþÿÿÿþÿ~btgG[ôïòÿÿÿóóó¡¡¡íííüüü¯¯¯   ïïïäÛáX5Kœ„“þþþ +endstream endobj 479 0 obj << /Length 52 >> stream +ýýýÿÿÿ·¤°G"8²¼þþþüüüººº¢¢¢²²²ÅÅœ““ôôôýþþ§’ M)?ÑÄÌ +endstream endobj 480 0 obj << /Length 58 >> stream +ýýýþÿþÿÿÿ‰oX5KäÜáþþþüüüººº¤¤¤£££îîîÕÕ՗——óóó̾ÇK'=¨’ ýþþ +endstream endobj 481 0 obj << /Length 55 >> stream +ýýýÿÿÿãÛàU2G“zŠþþþüüüººº¢¢¢¬¬¬ûûûÀÀÀ–––ôôôüûüuWjdDXóîñ +endstream endobj 482 0 obj << /Length 49 >> stream +ýýýÿÿÿãÚàU2Hœ…”þþþ¿¿¿———×××ØØØÙÙÙþÿÿÿþþƒgxdCXòîñ +endstream endobj 483 0 obj << /Length 46 >> stream +ýýýÿÿÿ±žªM)?ÑÄÌööö¨¨¨ÀÀÀ¶¶¶ªªªøøø·¤°J%;Ë½Æ +endstream endobj 484 0 obj << /Length 52 >> stream +ýýýÿÿÿþüýz]odCWóîñÒÒÒ¡¡¡žžžäää¼¼¼šššóóóäÜáW4J˜þþþ +endstream endobj 485 0 obj << /Length 43 >> stream +ýýýÿÿÿŶÀM)?ÏÂËëëëÑÑÑ¡¡¡¼¼¼¹¹¹þþþ»«µS0EáÙÞ +endstream endobj 486 0 obj << /Length 31 >> stream +ýýýÿÿÿðëî[8N§“ þþþx‡{^pÿþÿþÿÿ +endstream endobj 487 0 obj << /Length 37 >> stream +ýýýÿÿÿ§“ [8NðëîþþþøøøÑÑÑûûûàØÝX6KÎÁÉ +endstream endobj 488 0 obj << /Length 25 >> stream +ýýýÿÿÿ± ª[8NïëîàØÝX6KÎÁÉ +endstream endobj 489 0 obj << /Length 31 >> stream +ýýýÿÿÿüûüpPd‰•þÿÿÿþÿ{^px‡þþþ +endstream endobj 490 0 obj << /Length 25 >> stream +ýýýÿÿÿº©³^;QïêîÔÈÏU2GÚÏÖ +endstream endobj 491 0 obj << /Length 31 >> stream +ýýýÿÿÿù÷øiH]¥‘žþþþx‡{^pÿþÿþÿÿ +endstream endobj 492 0 obj << /Length 37 >> stream +ýýýÿÿÿðëî[8N§“ ðð𣣣úúúþþþ’{‰hH\ùøù +endstream endobj 493 0 obj << /Length 34 >> stream +ýýýÿÿÿ»«µS0EáÙÞâââÍÍÍÆÆÆ¿¿¿ÏÂÊP,B +endstream endobj 494 0 obj << /Length 43 >> stream +ýýýÿÿÿùøùhH\’{‰þþþÓÓÓ²²²ïïïÙÙÙûùúnOb†l|þÿþ +endstream endobj 495 0 obj << /Length 40 >> stream +ýýýÿÿÿòíñdBW Š˜ýþþÎÎÎÕÕÕ¯¯¯àààþÿÿÿþÿ|`q +endstream endobj 496 0 obj << /Length 34 >> stream +ýýýÿÿÿ§“ [8Nðëîòòò“““èèèáÙÞS0E»«µ +endstream endobj 497 0 obj << /Length 37 >> stream +ýýýÿÿÿðëî[8N§“ þþþüüü®®®ÄÄđzˆqReüûü +endstream endobj 498 0 obj << /Length 40 >> stream +ýýýÿÿÿ§“ [8NðëîðððÖÖÖ©©©øøøþþþÛÐ×W4IÎÁÉ +endstream endobj 499 0 obj << /Length 58 >> stream +ýýýÿÿÿóîñeEYoPcõñôþþþüüü»»»™™™›››ÍÍÍ÷÷÷ïïïáááëåé^> stream +ýýýÿÿÿäÚàƒbwM,@K*>`>RŸ”äÛáÞÒٔv‰Z9NL+>Q0DŽpƒêâç +endstream endobj 501 0 obj << /Length 55 >> stream +ýýýÿÿÿäÛáŽoƒV4HM,@N-AhG[•wŠÁ¬ºïêîêä軥³Œl€^=QL+?_=R¢†— +endstream endobj 502 0 obj << /Length 46 >> stream +ýýýÿÿÿðêî‹m€L*?M,@tShŲ¾þþþº¤²hF[J)=U3Hœ€’öóõ +endstream endobj 503 0 obj << /Length 40 >> stream +ýýýýþþÿÿÿ¹¥²S0EN,A—{÷óöñëï‡h|H&:_=RÏÀÊ +endstream endobj 504 0 obj << /Length 46 >> stream +ýýýÿÿÿèáæxXlH&:b@VƳ¿ýþþþþþÿþþ¯—¦Y6LI';‡h|ñëï +endstream endobj 505 0 obj << /Length 43 >> stream +ýýýþþþÿÿÿ³«U2GJ)=qOdÖÈÑÀ«¸gEZI(<_> stream +ýýýÿÿÿ÷ôöº£±~]qR1EN-AO.BM,@\;PqOd‚auœ~‘š|}\qpNcY7LM-@…dyÇ´Àþþþ +endstream endobj 507 0 obj << /Filter /FlateDecode /Length 17434 /Length1 31492 >> stream +H‰\U tWþö9ÿo„D4"ñ¾q%‚¤!âU 7A„ÑŠˆ%‘‡xDS,â1JÐÖkšM½:C…éÐ5¹*ÞEŠ©NÅ»Œ…Eš(ʚŲܾĬi;ÿ^ÿZç±Ï>ûñíï@ø`4RGü&2jâд À¼\MÉ.È*|æÝõ20‡S©Èž=ˑå[[ÃÉuÀË+¯pRÁçIQsͼ2iÚܼþ}F1݀ˆ.ù¹Y9§vø­¢½*žé™Ïÿ!Í*ß/8ï˜_0«(ìBä:Ϋæ›§½™…ëy¼bçeYE…>鲚ç9‡czVAîÐQ#žEßҟw ߜ9‹~ó+ª¨ß/œ‘[8µdäYÀ¹hæ6‡ö氆¿^‹Ö€u‹?}µj=ÉÖ s*œž)Vµö§µŽ/ÿÿ~!XŠŽ¨E)Žb¶æáÆMOW  _â8îÓZ¢ŒÖžV +^èŠÞ´ïà/ÌÜ1Ê i*Á2„–¿”rKO×wiùOxˆ§ø—„ÉdY¨¨b3ªn±µ¡Œ0Ž6†` ¦á3 •8dz›ÔµP½­÷êëF˜ñȊµŽÃ†Hêcã:ƒ‹ø;ë•(Ãå²Z¨w›ïXóéo$òÅRlÃ<SIi.é!½Ù|©”[ª­rª4=Q—›«¬¹Öj+ã‘Ë“S°Ë°gq÷ñPZñd$OTY-ïË uVÑºÔˆ3JÆ1ã…ÙÌ<æ9ï©fÖëítÃpÊxäas½ŸrWEKkiGKý%™–&Hž,ùP¶ÊvÙ+'åœÜ“Gòo¤V©µêú«:«Î鶺‹vé?ê*#ظjüdϪkë9êyd5¶ºZ=¬k“uÍzØP…6Dü "º¦’ –¢âc漧q‰¸»Ù 5xÌü$6¢©%=ê Né$áŒnŒ¤ÉY!k¤L¾’[R#/TՁÒEõTÉ*C«ê…öÖN¯‹ôGú‚~nÌ5£(;Í=æc[=Ä«êÅƺx&{J=­bÑFäù³ç¢1˜Kf•sðef“–æQ–‡å”Ïq_£Š¹?‹kd¨zëå+ñ#êàÅzšâEyé{7Vfђ)¹¬íK™/Ų\ÖQ6Êd ó{^.ÈE¹)wä c‚ŠPñj0#JUãÔxÊ•­«•ª‚rF]V×Ômõ\ûéfº½î¤ô$ýž^¡ÝºB«/¡F¼‘dL5Nçy’9Ĝ`f›+Í-æVó˜ùYcZ¶5¶Olûmµvo{O{ª}´}¹ýÏöCöëvË«ñ4œÞwÆÏßgDª±Ô~Æ}DÍÒ§ÔZÙù ˜+èA&¨ýú°úxA‰¾­?SŀájØîO«Â¨2/f-NªVø|¸Vg©#j½ +’žº¯±Ì¨"ëÌ¥Ÿ[ÕMeWåÔ¸ÏjLÀëÒÿ4ÞÀ#æÿ¬¹‚9MT7d§úJ%ÉWP¦a=6#WzÑ»ìÁs| ´Cöwoã úgoÈºj€-HͶõa…ÈHë¤êlÝg×ߒe¸¦ŸûoHŠDb;î°ê—$ZÚ£5ΓùÚa#Qûìf~ctd=Át£š5¬û›ÇeÎÒK䩊g9˜{D=“ƒ×‘«êyÔåDY¤¡£ïã´t`/Ú®bÞÇA€½M-R–þÚpà÷¨ÖÃxëoÉOm$š– +0™q8¬»ž2Z˜‚XÄÊDI‡‹;IhgÐóíä¢8+ÃZoŽ5»âŒ “%{1‹¥f#ÏCjV°¯!IVb·'•|W‚$D¢ˆ¦‡æl³ÄÜaV˜GÌÓ¶î(b×ndoãG¾Éf.¾Ç3b} »'œýO/’ø†MScõa ’V($†‘·2é¬äLZ)Æ*öÓ6¾!gðXü$Gp…È>Ïæý^´3¯³ê3±ì¸Dvs%íЅyz.¾«fñ¾zž-%ÏVÒ§ë¸Kæ°ü +—¾âbõ²ñ¬¾—yCO¤Ê.$Z{‰„¸t¾CG¾®Ù£e<—Ilø¢-z›wD!ܓbŪÉú°´àkèKTæËÞ_Þ¢MGdb<ƒÑ›oì"¤šÛââGÇ x­¿¾}zÇöŠ‰îÕ½[ä«á]»tëÒÑÙ!ØѾ]Û6­[µ +lÐÜÿ•f~M}}š4önäe·™†V‚ðgb¦Ãšé6BIIõsg²~±évp)ñ×:nGfƒšãךqÔÌû?͸—šqÿÓ?G?ô‹w$8îÓ.§c¿¤LãxµË9Öá~Ø0Þ0.iûpÌŽ„ |—Ã-™Žwâìü ™.šÛÕØ{sP®wD8vy7æ°1Gî@gá. |M*0¡Ï./:ånåt%¸[:]õ¸uHBVŽ;udZ‚«upð؈ðÿ°^­±Q\WøÌcg×tÁkó²fü\øUÊâµ ¶yùÙui»~@‹µ ¥4ÄI¡˜Á4 QÒ"‚¢¦ӆ±%¦¢ÈQ¤¤ýú£2J“GMRA$©’ªjO¿swfY«Ðª–?Ÿ{ϹsÏýî9cKŠtíUVzH ¡ˆØÆÒ"–Wl£oçÓÐ1} xØì +P{<äï4:Û6G-¥-Æ{d„°oµ5ó;ïͺÕÅ♑è‘Tk¶bÖÌÚ®s×4è֙Æhª5Èc1¬¹rnmܬÅÖ}bC³ŽÝäñ¨%Ɩ:Ÿ„O•8ߣ†5ñº•fTÛÌq\ÍÓ¢¦ýÁÁ9sÂçíwhNn¶D µ"ۈµUç ÜCfÓþf‡õÙã-%ŁŒD`¦¥; ÿÔÔƖ¤M´Äpn54%#+±GFaé:<‰8SÿÙRFfG†á'&a–Õ‰Ùn¥Eâf ‚õ<ßòä ÝüŒÀãÆõñš6G£å>#n2O’TƒÝm[¡UTÄñFp§ðñK¢¿¬¤xߐüŒ±; C |´±m‹U,DøƒA¾àcCajGÇêiŒ&ú:µgRxa(fÉq¶ »–¬léq-ÉéqL~‘ø”,˗—üM̘^³­Â’fü󖄽¡Ùhhlê5f܉mC˸^Â^–´9-kz$ªdËNKÎV„¤Üœ̝¨ßRsñ« Rwy}`¥ÐHz­ˆ¯NüM ïrҐý1ÏâÖ4ÇM«"4¾_9®?Î=¿©Àa5Onhi5Í)ãlµÈ@¦YkèµfÜl²{Ú =`˜çñ¹’o»7:dÿæX¶UÛÃ!¶I`«LU†ÔÛ8–z›[£çø·«·%:(Kr$^˜[ô¼NZ9©åžÎ=üã¦Ê>aÊ>&êVU(D¿cH"¡ó¹:‰:†ä„. tø)á»÷ÇjèÁýëèXS F°!õ»§@+—r¸%»è§sê²T¢`½èZ?5ÉåÔ'³ì§ÙÐS}Œ +0¾ +ýŐ­°ËÐ×G€Å@XÔk¹XÁ{'±F!¯#$ÑCÞ=´Ùó:<›(Ùd£]¨¾K ´rjBʽbì ´À–ç=N…w/ú0n)KôóÔnÚ{=ڋxMœ#r }û_fŸ!#êÏè •ìhçaí͘RŽÓ:Èõë¡¯‚~-úµ˜S$÷Û¯£]v±YÃzqönÊÖaNülëuÓ +ئcß È…@ìYJ>='½JÏ@~Y-$¿87ƈsoºu&ÈU§IÀ>²©`Ÿärûàmà]Ç·ºÛÀ~¥‚¨CYB•=€Áë˗pæ&’`¯ðü“*>²?ǹÞf¨”Žþ5øÙèy‘–q˜&Àß©§àÓ§´¶ö$-€~©|?8¶•È?¥2-—Òp¾VŒ­º÷˜ Ô‚û°!§ªïÓØæy¸ÃsNœôù~q>û#øqcfæ–àW'°?ǜï>CÚ4nÚ×`û +ð5œ«xöo€Ã11ó±n¥Ãä˜{)(`\ð=¹Hp„²€{䯇€ÇÝÀVƒu‹0žy҅5kПÇü`n`-¾‡z‡;àw¡àXâÍüq¬féޖƒ©›Åï…9+Þ Þó‘¹Åœq%ó[ðþ¬ô2Ÿ“ï'_´»D½/¥båW¨!Ç¿ >̦år•É&•©iø6û"Úߥ2å—À Äà€=ªÎD¯†þ'ÀÌû#â™Û'ó ðàæއöÛQ^¢2Ï£è炫¯AŽÿÀ¼/PŸò<õi:,wØ'ÄúŒccðz<XèJöÕŤ>ÿœü“ú[}ËϤ“øÇkðºb)µG‰ì?¹ 9Ö(§³ÀùM̦ƒÒ“DîIz8åà×´ZÈ wxPê6ªzNC–@~Œ§€ ÀMubqœ^|Aÿ + ù"EYÂþð[àŠkKï5™>ê_i\ß³˜fÈÅø&,¦Ûǟ¦¥ê·‘ká[Pöц6vy}´Kþ ô›0oBßS@O©»è¾;ùs'H E"† „ïæŒw þFãúüÿZïnû}øºˆÿZ 8tñ÷Ršt¾*½C+•S´†áôã"ž§i‘{OÐ÷ +ý„ûWPš(¶­êŠßljã<ÛIúEÒöÛ ®ÓÔæ%mºh$Ïý¢cs›NѾèšLBFÖÐ6ѵØeÓ>¤Zê$HК@ÙÊ­É}luBýÇVØJ†&%-¬éÖVP$ë]?’îwïsB‰Z±IÛ?“õ;¿sî=÷Üóλ¾ïÞ ùž„S®±eÊÞ%1mÏÌ{#´‘Ôi=˜¨56ËÆò –‚ý8‘ëüë3vÎUmöú”@m·I †DmwK vD¾ß•¸¦®_’uŜr,™~?Óë|öû‘y9~¿3$½j6ϬïÂ~ñ±5¿Ù^ï3¶ÜKÎÎòùè?ñÑÿ•Åüþ;¿^Žý¯ç¢Øäá“û„<£nÇYu+þ¯‘B&ӄ\>JȬŠÉ+àap/¾Uà_Q´áë0¹¼øú.à;‚#ûTÒQE+œ+Ñ7µ ~9;ÎÔ<èuˆÿW`?ðC´Ÿ’€~wðúß´ÇN} üؗÀß^EVô•]П¶@ø'°ˆÚñ.Ãïò!y¹Î=ô¿Ë7¸ü»lß7Hdšgß!þ#ÞþÉ<ûÎ1ýþ?‰§ï×aU‡Â½éíkî>7ºã|Œ±~\×gé ΔyŽ–gYy~–çÇiV÷6ì…ù+¯a<¿Ê³³<¿‚kÁë‹ÎaOÿ1Y5×Òv5ïàÖºu†™×.W,ÂKÃ²CT-4œu‘[ˆŽ*æU«"V¯.(+Wي©3Æâò:10qP¶GYáåÆÄQؔO/¥²•_±|s0Ÿ´¼•†÷ñ‹Èí"a¤÷“<ÀH'ÿ€¤÷ƒ¢îV9?h•z üljȜôBRe›€ô·*çÉðo o¹7&b ¶bù­ñ9üMäó;þ: ÿ¼ü2xø…h*ϧ-¯ÏÈ`¾ýpßÏ"KÑý3¾ƒàgøäZ¹{žã"1â¥üß©\ä÷“ð}ü^aèþþ425ù»–Ë-ó{Wøæƒü®ysàu^óuï ßN¢€|’œåҌl¼Œçð˜9”EGŽ”ô(iò×a¾_𠙇¾!¾›Ì?Ësõü¿ Ü>”Q0ßS¢¤^’¥yŒ|܅ÕEQñó¨øy5Û?¬šU‰×ð‘ÀPÔÓÐNCóázZN ôØåø{èy>Q~’¤ø$ ô@w äC<¬”PØ8Ìwñ¨„oµ£h}Ørydf;EE¥rÛi•yŒ–A>‚ a1M>jÍ_`tðGÕ£d­ÕrÀ…« ¥û¶ý.0p‡|ƒ<ÃQ•Ø­*Ð÷LJ¼ü;jðU«¬ÜHãí·Áì„Ü ã€nmx†6Òp¸·Z¯áà_Qƒ?#<õú ߀Gß ªµAÌ ¨œo· làŸÅ"ÙÄ7Š»t$¸Y`°ìÝh­j2b|£zàBÚÍ¢ò&¥¬.{ñ¬±JËåtk•c­(ñ¨æÚÂÿŽG¬9ó ‹±I=R½üŠá‚ëb@-²â†å«À¿‹*mƒt½@àÀ‹4ànàEä”jñò•x¦•ø|­Äc§ '†ö[I °8 +œŠTkÀÐà Y€!b¶Ò:€ Ð ä  ˜ ñ:ÌSïdèÆ^È2ä± }ÜO&ñ}ÖqÒí2›hš¤iš¥yڑ.JûÒå%æŠ%Ë ó)–K†hìp¥\¹LW«‹û\~Ë]͋â¦zYálª?‘x'q)Á+³Îl1Š—Ñr2Œœ Q,,Ÿù}>Ô<Ö<Þ̇c‰ñ:9vrü$ª«¯ãf¢ºÉhl§4M÷P‡N£´…n¢ŽvÞÉÓ|wè<Ê[°î”;ãæ1·énusŸÛïfYw¯»Ïw»‹úœyç°ó”sÂYÔêìp¦œgÖÙëtêÅÑâ–bÓ阈¯ao ¨½}#ȬÒ|ª'9¬ì¬²; SÊ6![•„ŒI ª .EœqBùI;“6Ä~m)È,ÀØqsa 2CÌò‡ щ +±¾P>Äòñ&6ª²E–£*ËQŒUs".4 ˆlG”ßüF”ßü¤v½¶ȔÒLÈV¥!cRc#"ØèÏgO b;d0p…l:•¥Kö¤Éº­[–™ë5ØA›Û´P‘uS•Ñ÷²n„ìFÈn‘–´Hëjžu‰µÒ·KÜfSSýX¼ŸJ™JîR]HudÒ¢-J;¨|¼3vä)¥¥ {gƵ+M‡œËY7~]мlZw˜nFæá4I*ÊK*rìˆØV¡çØ "ìY6 IñJÆQ{¾¯ä/•ìQò'J~QI¯éjƒÚoƒÚ /ewš'”<§ä=¦'¤½Ҏ…´ý!í©6@O“:n6«Úـö§€v( =Ðö´-ms@û\@† +?ÑØ")éV%šóýÚ¿ög¿öª_{ů=é×¾ìךüp§çñÑÔpבò1%WjÐômQƒv„ag¢w +/q 0Fï$/‘f=Ç]ŠØÍ"±´P$â j‘ø<¨J$UŠÄ^=îb^ڏ‰Î<´¿Dr™ˆìF·Û¦Ù +*‘Oé9:%"AÐe‘\º$’‹AŠdèI/Ò¿“$Cú7‘܇ðô–aé[¤†=ΉD ¼Ù³ÓH3]‚fAL™}^D}FD "ýܦý"¢ƒžÉå }"¹ôS‘<êáûd¼.Vq'5Š‰jtß/2BJ$¢ N‘XºW4¿Ú&šÏÈ¡wÓ~Š•M“$¢2ýšHFÐÝ^x¯’°êÞBV¨È·‹„,Éz$®Ñu…YK×ȃ]MûUSDbpk‘Ðmvå>-’µ U"ŒÓFއʭ,L°T¾ŸiiÈ@AyNºH.-Éu j9IUf­ Í*©r‘^>ñë/Q7Iªˆ¥¤†vÿZŸDÜËÍ9ú¡_2s%TèÂÿ"¾êc›H®øÌúc7vl¯Äv¼^Öë79/àÄ !‰mb;Wj ¡œÍ%G’Sr È7JU®¡:à(¢G¯R¹Jý8U¢¥­¸[ +Ü©PU×ӉüQ¤~‰¦í©íåt¤´ÒÒ7ëôÂIüÕ:ë™÷vÞoæÍ{óföÈ5á£ô€ðtÒZáïp„vMø@ïG€™…?ò ¿"Æ ï7 ·å!_sS˜Kor°0uh@x{H›á-†].Õä) £ßÚ)¼T„ rž¬áuŸ&:`¢“Áákò a +Ba2}F˜òÂhÍ Â¡¢È% v Ã`ÈK0fpè%¡?ø-¡/¬­ø…àBwX³!5¤Y´#¢ ¾0Ô%tÀ +@%XA Äe†n +ß$>Bµ8>÷ð¥¦w(ø +ãY¨ã±Mô»ôËô½—n‡ïM5 Ez]Î8–±2¥Œ‰a#£g(1ˆ*ϯ.Æ·W¹‘%Ĩ'­^ãYŠ´Ðœ„ …¾ˆÔ2]ŠJu·«MJ*O¯v©[•”Jï~>“ÃøYœR /¢Ô€O}Ø-å±iÏ~Õ µcՑB©½ín«Ô«yŒöfòx•Œ8É©Žxfa¼ñä9ŽÐŽ“ç²Y䜎º£Žˆ½¹#ñ”¦o­M&”õâV”Ͻñê·SÝõ§|V f•Ï¦Ôgº}=™yê0u(™˜§FÉfæñ0u8ÙEúñp" ° †"ÔÀPš€Q=(B`Ðßó ç ;‘‹DŠ ]8G@phvi ýEPüIî,Žk ¸î¬ú~QaÖ +c„Ìp5…AÃa æ&°œ,ÃLC2äB2rrHïY×ŗ‹âËDœÇx]–‹«­A²¦A¦j£üË`ûÿ0ϵMÉ$¥dŸ”„Ú§žv«³>_îÈ4øTÜ7ðâ0¡ýƒê´4˜PH _®-óq†ˆÛ¤De’{3¹Ll0q¥-֖”úÙ¹Î[Ç>§ëÌgº¶žxÊd'Èd[‰®Î±§ˆÇˆ¸“è#ºÆˆ®ÎX§¦+ÕՎS»39µgã=E:G™MpZú81ÛîdG#ÚÑiÝ/s7ô_Bf%«–Jíª*Õn¯ÝNDp¤‰È +ݶ5‘ûå‘»/­‰Xè¶Kíhҝ<˜€ß”ÉÉ)(à㉉¢¯ÝEÁ¤’Ôä˜nR+€žÔ ­wM>‰¦Ö‹¢±hB‰grétÒ}0ÁA?Gòn%;¥¨PQ諵Dß©%úf£³þ^ú/é¦u-Ã_€º¨eøÈî .B†¿AWˆ,D#ºBz!½Øû ÷ïë +µ µ‹µº¦µUY +\¦”‰)Ò­`ÍZÍnxT&bò}o +é%^Rì×Æ)0‹òÙXe™( +§´!Åމõ†{îW<` Ú¯Rø¶‘Îë˜X2èo됉Ößƨ’1nSºwðvT‚xr+ìÃÖG­ìrkúQ+ŠÏ®@³¥N´‹ö4p‹£Ÿ®°3 O‘O_ ×x¥f¨èòÄJáòp¥þò9·ÒÉ>`ÿŠ6§—¶Ôa1,R3æ©gñÑ»ˆä·«âÝ-dF.šG•°•Ž²ãD—îp˜mº%Q+*Ý¿½KfZîM/“E-EÉl +9+ʍ’_74–=Áã}Éþþ$ÔDGÿ¡º[Ú+ÔGãEn€¬zÏêŸ ÏFà +?œ«³s%¦o¾HkÔ4–¦ÔSÂ5–¥=§œg=¯qg¼Ìˆ}Ä1cŸqœ±ÿØxÉrÑõ+×ûœÉèDrܹÝ;ë<é:Ž⽮¿¹Á´YŽ§-ÓÜ©²6ºÉjwTñh?ÅcœÇå1`şØVÃ!^g=TQ‚l¶c»gTƲ#pd‡1>ž‰•ØL‚‰2¥++—ÓëåæŠÜR¶“í}؛~ 9ÆÞÜüÑòf—–—ûޖºT÷L.ÄÄgbUN¯ÑR*»L ]B9Ùâ4Ñ Ùm  !€!N!x‚ŠrâîC½cX» í’,K~#m¬(w8ëCMFðunpTՇ\Z—á¹êŸ¼ñÕßl‰öÜùîì½éñ]üÝã·¯¿³·^ûAO¥o3myÌßy}úÂüµÇ÷¾3zfêØÈ[¸# ÷"U›ëɎ<añ±a'ä _ÕŠ±&oÔäã)¿ßãã~?çã±_2ûx»_rØ!Ÿg<6Nà(.b6‘Ãì‹&\gŠ™FM“þ4”©Ò'!Çñ ‹" "U'ÆÄ⬨‹±mÜÛ;6®@|A qßK?ÚJL'q¨Ãõ¡¦Æ¦Æ°½!…Å +ÉOwØ˝ÎzêãG-µ-U«Ùo®¥~Ix›ÙoV¿{H÷•á†ê5~åàÁRbïX*BæípÀ +ÿ}ÅÒLHìXi3ëõÚX/ÏÛ,ÛxF³Ûå÷SÛxÚ/Ù}¼s§„DV¤DÞNj¬×…m<A¸Ès~d·Y1æ]"ÃÐ4¢\NÆV‚©«Í‚X°åøn K¬½Æ‹8¼›Ãˆ; +þ;îלÀ.õŽ“sŸ&5^¼ˆ'XxÍÍØîhv4CsÚºI9­?~A§›…h+ôgf[ß9ÍÞÁÄo$ýB«jL) #kkBã¾QqÖ7+~·÷¯¢«¢EïӋA}µÙ_ôÙüêóWÊÂ@~+s?l9fÙóøM¯Êª^<Ö«/×ÏY¦œ‹²$Ï,q¸£ˆ±–EQ~õ“µ7[yԖ_ýp0@ÅêŠââÅH®hlo¨–iØF+Ua—0ìb}=lr#lpµ,W‡ñcê{RÝ.ìký+##Ißca4Ã+íÃΕëÔ³_V¶Q€YÚÕ÷éýÁ•NuxÿaÝ»U~*7[Bú‹°»T…îÎ#ìîØ.ûØ&Î;ŽßsgûÎñÅ÷ØñùÎç÷»œ“óù%ñÅI.vœ£ o³ÂxWªRåÅÑ ++Ú¤¼ukÑF£[5ªݺ" +¦t¢[Ñ´uh‹¦M£ŒUkÔISÃ&-cªXž³£½H³uÏóø¹“-?ßßïûùýh=f©»É¥'À$Ÿ»ûT´%©èRV±°C”­H—‚/– …M^œtP0âwGü‡üçü„ÿxùBQ€ƒt#FC/Ó#4Nï‹c½€DŽ¡®š­IhÖÕš1kAíÕ³3píEdëÈ"QÉ'ð\€Ã’/žQ "ۜ1.’Å°š)$ÆLÔâYn`=:®\çBBäã1Ë}Iᱬ ߑp%¸xÓÜðcýÁà€‰j×æùï¾´åOqÏþññçð­óGwé¢,KÝ»ˆ=Öjê•ñwD?=w?yzò‹ D¯Ð J¨ù¢Ñ·VN³%ñÒ +aih©¸%ô¸Hzßж¶ì“Á}Á}âQévðÒT–:ãÿð)ÿ ð@°g)ºŠÿöJíŒk ë˜ÑÂЭ£± D9–DŸ$‰¥.aÉPù|t~üÕ¸ö¥—?_ŠÎç7ø£„Œâgæ~ Mì8û ‹£?´Å£u6t¾m²/N8ÜÀɐª£g85ͨPñdŘڜêLvªO*ǔcÉ ÕäÛMú¿1»Ü`±Lg´ï¼ÐG6ÆÂÑXD«(º–D6bp᫨ •`\ r…Û^f¯r–9ïzËu‹q¨ +ã²Iö|;!åYç0Ø vƒƒàE`ë°Là‰**Ý^¡`¸; + ¥p +m]‰¶g=U ¿¹¾f±CÓ3æ*¨ÞG 9m֑Íé´HR]Çà'æ쌹€ok][¾éÀû׬7b„‹`pYI¨£®íÌ~×3ÌóʄzŠyÝuÃõ¾ë}¦{C{›…m4ՙÍú8ýÍúl¨>j©\òhþ…TM´dÇ;-Œ×8NüÄ¥„?ߺ ً÷ýÌü?ncŸm‹ +=^YN=8¹gBÛ6~ýÕu÷Þz¤”="ìŋ¿Ú¹4-e3ñ5OoÛöüÅ¿ ;VÇî|´uÛÆՋ>wè[›_†ô¢X¯¥*Dô»\£ª¼$D硹cJšm’Å¡º9 sÛ¹ \•³ù9Žå³ƒ0@©ÃºÃ4å +Óñ Q}ø‚ÑɑŽ…‘ÄI2Í¡?ͱv‡£•  U€¥H‡¶Å±”ÝNÆi ùªSBuÁµôò‰ãìmÁ8ð¬áÑÚ¡¥§â/îä« 5QóSU ÍÍñ«?1ð±Z³ÓbÑËéI‡D<2”Q­|´ÉðÖ¼¥ +:ŸŽÏg×èÃøqÿú3 è6,ª.µ¯”éþÜõ³¶Î÷œ²ìgÂÞös&¾aç ÉÐÙrÛMÿFÜ%ÞÃÚ±">h°u[ ê9£8Ðq"ÿuòlž(YEԖù«:ø +ùZúõâµôOÓwâ¿KßÉœvæÉÅä`Ó ·<¿žÛJÂÎæσ«à*Ek$8T:cûfú•vV*—÷”Ƹ—Ù7Àùž›àÃRå/—¾P –Q8ëeñ‚õ+·8ý/Ó('Eª©V5%«)¥¨]Ònh„MëՆ´ÚWµsÚ÷µi¿Ô~¯Íh®=Ð +>*N=A=MÙpª@­¤öSǨsÔkÔϨ(§‹ +R{(Â祾1UÑ7*[³…exn3³Yœ7µƒá£üf~7Žƒ¿É“à?áÿÉQëz*êÐLe¶¢þ؄feÖDXGÀ¸o¹GŸWW³è>‚Å,Â:œ›†u?óZƒ§^´éðç,º‹E]`¬qWh>Ì㘹¡†Ž\wOHj€„‘ɸìJè wÄÁè˜3‚jî¢+‚ÁPc4ˆhè¶"X­«Uaq¡ã<Œ^`¬bbè« =y¡#“-Ÿ©/÷Ÿ> yŽeK5Æäº8«¥H´xõ§´¾üÒÑòhä9£uQR%–ú֎ÝÞ5q–s7ø…`$·c ¼±á™BK<ÎŸÜ>¼ãÒ×íRÂ^žª­í‹Wj˞[Ry$99ʈC™ì_q +èKWwve¤ ÷êÃi[ù‡µ€Õã]BaäpÀ<ÍQ® +îA)1N‘„Ëåcèâ0 ¢JÀ ¯‚Ô¼¼"oMFw¡·£¬L)x›b(eeòmå‡Ê» +©¸Ýˆð@Òã5 hƒ,ÃwáªZ­«*5þÿ‹êòmâ<ãø½gûìsî|wþuþygߝí؇}.q~_ύ6I™ÖQua”2&¨H¨F¬ +¿ +m¦ :1i)ÚèF‘Â+4]ÕTZ*uBšÙ$–uMQÕ²¥-DS7Þ÷h—?ÞçIôÞ+åyžÏó|ŸAk ó÷'ÆÂI,i'ÆB Ë^å +„±¿ ú Óà«;uݺšm\Í.\Í~åêü‚ÎãgðhÑm¾\FÕFŽ#);ëHiéh$!):H¥ìJř°D°Ù ¾J¥3(ÂJ‘tI™ÿ˱µÂª¾ä ÃÚ)׎s®+v××Ë49lvËéSŽÓâa°Úœbœp+µ0uJ y-øÚžGht×7žß¸çÚÁž]g§[oA‡(wOW˪GÚ2Ýk=õúžÁÚџ~q°Øö¼ý—ßðÅ¢dªþ‹{‡Õ®UK.Lÿeõ'M’“꺅þN:Ý.´ˆÌùŸ–·ÐߑwÑ»Ü;¥Ó¾ ¾ þ«ä¸ÿ-i\”þ˜ð6O¬FLCÔÐ4"íÈÚ-éƒIú\@Â?Bé&gòëö&X¶<:‰X® kѤ…‡Ðº_DFS·¡Gp19FÆ;îaûV³^ª9vA.zJΰÖqÜR:¬9½X$€lŠzgvZ2av/Ïp݉å‚TÃzŠ# Ü¥,~`’·ã˜7ËXÓ¾12p¸m¦Ü=¹ãé-{§N¾¹¢£«—¦DQ.*¥§Vµ?ñÈÚ;¡ìF‘Þ;9úãuËû6WÂá–ÞŸºÓ¥0+O++€ ùS}ýû6{%h÷zÛ]„ÄK¤(çiWè¬,Mªœš¥ø¹ŒÎR28미ôC Lm\Ì°¸;™ö;á)‚pñ “rDˆ‘¡œ@DˆCO"ò"B(b4(Ãf ÃÖôC¼V5ƒ0F Ґa#21/fú€²oçŎý¡‡MÇÒç¿ÍV±Ô®€À^fù»³ÿEw« dBÓ¬äXŸ–RS$åM7g²’ò¤_:CäX8RB2ƒ2œžYX“€’œE‰1Àø”ÜEc <ÃÞ]â°:Ý›?,˿ƞžYt.øæ¢ñEž}Ü+‰³Xí·è6t t tã×û-Mð€¼iŠϵõ·[—mí¢™b÷‘Ç·¥B)£”›×ö9zþsí2aOöþdÍґ½§ôŠl Æc¹úáã~ùg¯ÿæ|Úw¬Q¶*0 ¨Õ\KyŸðWý;ü[χvû)÷ää‡ÂuòºmŠ +üËöoÖ=€~é ”ÖضØv(C¶aå í°çûI€Î¹î‘‹¦u\ —ÍUu$‚Z¼Šš/GÓ>§ã*’Ƙ&:ˆ³ÛÙ ša¥ü. ÂÉìqœš<%l͐ÐJD ¥¢lPn+v%‘m,]‹ùò,+y6],YUÃ@9Õxć“ Vq¿ë­Wg0ƒºŽ‹E×Ë…su¼™ÍUgÿá U!0&ã©hK’Šye‰ˆøƒ’„¨„čºÈéûQUÇIDɍ‰‡è…ü9K` تõûôºß.oêPz®î®m[S?üúgj* –’]èîøöo.{:xfÿÈþ÷n¡À§g_ÿ¾ìmé?£B(º ÂÖ ÛRéæ3¦(Ÿ¬‘E8eŠwÚs:PVàY†ñBÃ×yŽÑd礂4™f£r´µ‚4Yœ>@yÏÁEpæ±Û0EO…3dã¦a3@,£[1-…¤¬b‚UNdnæQþAd‚žcjânÔ CÞ`Yo–Á1‡‡°5ìâR‚©1$H ¦ÈìcN0# E0<³ÑrkÌ猓 'Œ¢AŒ?$ÇÑfD°ê‚܉Û"̸Á™AB–÷1?¯Ï½ÙÃâ¼ú@÷ցïYÜFAjCæÊNlNŒ8Õ@ªÖÜ¥d« ¶¶´fJ_6QÜQcŠ +ˆ–ºéO¬©ÿµÒê?zýùòÞ¡Ç-= +ë/Æ3ä1ۊúг¡”MÓP´ØC¾²i…qb♎|w[’Ž \ÀÍ[G‡6á~šƒCul'šˆñ73(íÄ +'^"& ¼—Q¢&{q UXM°£†49öú !Jm¥Q +Q&˜åÜ4l þÚP ¦-Ë0+³$› ‰&×n×4RŸ#pSPãË Â~æPýÓ\F&o“ïz¦ÈOÉ/XGœŽ4¥cŠ¢¨í±o±›ÙÙ!aû£èIöwŠÿuä{™›â?áý$gãéHÄÛìu4䰙DR.ëÏ $Å9{ʕ— D“K¦)¿¨¤d-¨¹á_ã듓“•údeÏ_KZõrÔ|‘Ј¯ñ…¢ê•Ç$Ƀ §ìö4Éî`L”ƒYMÖT…&áÕï—²&«ªšÓ䂪Úï“ÀÌ|µRòøáCžãžÇüðÇJñÏyHä*ÊDpÓˆQ茗âë%è”fHÓÔ`À}³x»HQ ,w£` ˺‘û*½äÙɏ#P£H2ƒ±Õ\\Ž“ñ!I’9BÆ՘ËYB–'K(×Zv:kφâH}hÃìéå^@Xš¯ÎÔgææªõù¹> Ý Vžår¸—Ÿ› Õgp!X2Åu¤ {^âo?RéUìU ¡^ãg?AXçW}ÞUv•X'Âë ‚‡aoÚKok2@Qÿ#»Zc㸪ðܙ™Ý½»;׳³»Þ×ÌîÌì®w'›u’ÙØNÖÙ릉›GM‚ È“BH)M€8D©¶Ô@¥u@MD¨U+Ú? qã8E¢ŽR% bїRP% +ªy(U¥ +bsîÌ:¨Ô¶î™;>sçqÏ÷ï“å8°(+¥µ ‚œøÿº|ssqEϵ>ÿØCü4¥|!_»ÔêÙ´”ߘîªlwþçøC²Y;X* ë&¿²ôÛWºM¨¶îXjR6þê@S¶m©< Ì<âKLa:€Yjp4•!öAS‘"rG ‘H„HèÔÃ-ðªèáh–03‘´àJI s+‰*±J¦ë®‹;èd‘ZÏsMaÄa‚y|ÌPŸQÏ©BCm«SêœzKU–¿ÆuYœ©¯v»ð]T6-Uš)¢:™=Û+Í¥ŠEá̑‘áý;ž]zê \JïCÏ|«U<¶„¿Öï£ð O|òÜvР¡£\}†v_Ë J©Ÿ ÆÊQÄÉ©² +â< ¬x‰-;®@Œå{ / û¡í…éA—Ejƒ+›³æ-ž³¨õ ÅEj=mñ–¢*¯ÒyŒpGKz–fq$$N›°Æ䋕fÿ8ãJó|×Á 3ÌÏ-rþµ=ýx/*°ˆ†^ÐyI‹'â¼$•³¹L.$%ªVà-ó:J†Të–óÔ‰U.Ät§t.'¦*œ×nßÔ‡95=hmCÛȑˆxHšˆLCéIi*2E&Ó¯òWð„ E™èž’'£“ÊTw¼äØø(Ð-´lèÙ²o(ՔÉü˜ð°¡l?Ëhéè￾ÿè[¯-üõƺm©¾ou]¯Dµr)#\yô½'®}ÿYÔså:r†ïÿóïŒ oO›ƒ{Qñ…‰|‚1ÉЩ߀¬¢ + ã2ÀZ„øàñ/ÓYÃu:Ìqò¼Ñô¦yÝ?­/Ҋ–t‰ƒNáÓÑ.WɃ­¬y¢“ª„ÉTŠ3Á“z„œºjä=B¶l£Ê9o…×*ToA½çúÚÊWÅpUIχ•1.üÚËÐދ'äyù–,€}‰b®ª¤ ÐG5Ëô«Éô¸Àu½˜-x‘jjҝ3Ñ!q&1yóíÚÈg•W:çâ"YðõԂãÀŸ#{æӦ갷ã0áƒÍWR¾S`^!å›A@8@€Úõ±õoZÝ‘ÃÑ|¦š( 9Òè_’`¸Ü+œyýÇ{·´7o¿7 %Íö—¾ýVÿɦA²ŠGyqW2—™ÎÚ½¼À¿{´–œ~÷&H;@¢Uä«IKjWKWË7ÉßÈGD®’R­Ÿ¬¯=ŽOZ'íçñsÖ,~ÑÂbDŒ«‰È0Þ‘(¦^]kp§y!Æ:ˆbµý4£r´…ƹÓjN¸ÛN·‘>52+H9‘A™Yt€ZéÓÉÛª*–YÕË*Vý&JՄ‹P¹")òEÏ%bÅõgfŒÍWT ð ÅE ÷Sî^÷›î„{֕\U A>HáÿÈÌT{VŒeêñH€Ý“^ÇÍ VpÄí8é…`82ȒRpAjÅv°•°`H–` +Þ¡M†ÿð; ðúð¬·hV(~®fO> xÖð",Ãâù»+9£ Þ +4hO7|Á\ $ C,C4é'Ž‚Ue7Òu]ië³ËšŽh~„ ÏCº—èå]âDè¦*äŠ:$Š:d‰ÚJ +yŸézD?XäÈû»½Ò á®vƒ†à]XKò³ØKux4Àñü´áU¡«”êÐ_`ö ÁA©-§4»ü¯é”ÁâÂÅîB;’KÛÜÝÞ6ʍ€‘ÆÆq«ìù0(úƒ`Áƒ‚%¬cìäÉCøm2û–b'úø§sð±¡ê­€Êc#OîÙ|HÇÅd‘˜õ_líl=ü³ú='´s8Û¥&»…ËK—Ÿ|¸ÏΦ«×~°gäÔ®^‹v?¾±Ö»uø‘þOï;x¶¤(`£¼|›?¸Ã¥¹ŸÒØžŠðހ#\zÍÀö4MH<Æ#©€{1Å>Úü0‹b4/â™H&‹N ‘kñd∦Å)|ü¸/ÂM·Ÿ‹ÏDžx:Øj>/ȀZ¾únï_„)×¾³0ÖnÝaç`ŠÈu¦˜¹qÔµ.aAf¬òIƒ™ÛõëûÐì;ï(e2´Aß=3z¬+|ôÑ_߸³ô¾;/ïnä÷%çö š§ÐGÖè+GW·—k„3œ‰~r‰³áé~ ZϞ·ùP$©E¶E‘ŸçžÏÍæÿÿäMŠ£n‘  Šã ‰ãwe´,#&‡-K±¸eé¶aZ–Z8½?„Ø3Mø'Õ:ÒX—˜t“@ËI ß$&ß$¦Ü$&Ú$&Ú$¦á$¦Ü$¦ÜnHH‘PAº!ñœD$^b2.l3Ehƒ‚³; +Îî(7»£ÜX<_óÿ +ÛÇâÙ¯ÖØ(®+|î<Ö3»Þñ̾fgvÆd_xÖ3,±‰—¼íń;e ´6†`ó²ò ÅªÚ¤±P+%J¥&RÒ +ñ£ú#MJ¨,U¨TE‰”QþõO#¡ŠÊ*AÑÒõöܙ5¦­›Vʯ¹£ïÞs»{î·÷|SÑPÀÏ#óf†q2G3L_ÚH¼£ž+gqa©©ß¤¦~“¼ÅÜc'Š2îŠDé¼ô¡ÄJÚ=MA·,ɇ© [Ö´]«Ýéѱè*:¼\½àª¹Ú1W¿cI ÿ‰ã·T<ý+äržÖjoîú†û\—ý °iéÙþçwŒ|»#¿™ÌEצ2« =TuÕ3ôgntë¾ï!³T^Õ¿;±1ÕGÈ5WlPù_áî™Gގ€BŠ •ŸGb]ÀJ„TdVæZœ˜“pÔ¾X_¢O‰$FÔÝüîÈxz†ßœˆJR'Òû§äoEæ'ÕÙô ó™ü ö+օÀŸà’t¹x®¯‡>—ns` 8™W¸tŵ÷Ú"!L$¢D£”CF0™ÖŒ$—'y«`äA”EFäCT£&~³hÂPsfÖÈUOUXõílå EÓ*«†3 3 +" öitÓ+²„Ý£È1E‘‘ÀT•Ú™cN,¦£%d’?›7MÆ´ò†e8«È ó¹¤E–MÕJ±Ûv¹ÑÓåŽf»;V’šÞeWBRàob~i[Uõü“¦±@:]Ù«Uå7¤L1:Nëø±!²ëĊ8*²¢Öi/0ãgÛ·+¹@ŠßG•I ¥kÈ&=Y×µzrûàäÀ¥šG$*4)y°EÔ2Q"åríZŠZž¶-aNþ=?o'­cÒ-jX–žy‘ÈçÝÞò†óµ»¯Ÿ—…^¡—=µ’Ó­*éÆ'g±vÉ ·ÆX7Ê !VVÄ;áyÂÞÃÒs»»=îžíѨ«cÚãÏsu×m!ìÅÜìúkO^»—\X—1O=Lw:ä=éÕÏ=£çî#q{ƒµô·UÌõ1æg¯:¦”Í®Š(»–~Df’ÛÖ +Ù,«©‰mèŽéù —ͺOÖ5zÎ)KUv™îožk a¦•–­7¢ñ͉‘áÁðþuýÑÔnû ý‰ÔûTj!õ^J*D ±èÑ«P O¦Z¦Z_q^‡×õµ0®v­Žhm1q-aÄežð„3°ºFXG<_ÈX’ãTu-¦ëZk8œÄÒÞ$a iwtM +·BK<ï@†š„çõÌeëÅt[ær:ÃÈtí-}RºRbK”dáX¡«„¼j‹;q&¾@؊ʯ]kæ»òy6ÿ~»ü‡Xu´u%¼çRÉ¥Ñðµzí"—@ÖqW˜ÒÃgX^ì[\T(m"”Cj9RžlËeȼԤ +x7Ëwòån†´²ÇJOþí3ôÅÃ+âør©zG¹ºôÑÀ×lòY©°þôÌý¥Í¤loXº>Y<°cjK×úM„B[2UؐcÎýd÷Y“Ì]z‰¤^¾?[d²Y~Ó[õmKïÝùxÿƇ*ý¹PhuǏáV›þ?qæ˃¬YÌÛÿìO¿þ¤‡À;„w‚¯ÝFkñ¿G[@¾ +ˆį¨§o#yÁCj'Àª1é?˜¯Ýƚ +@ö1€Ü@¡êÁZ硳Ç>|øðáÇ>|øðáÇËЖZDG`ÅÆÞéÈw:«—œÛiW‚{¡{@ùvØÀ`uËÐV€‡`û<<°kü‘Ýð(<¶òg%ƒÓد-ûNØý°¶Ã(ì€qØaŽÀ“ð4œh40öî˜1ŒÙ‡1‡à0÷bŸþ竹+5vÅ¿iÆjؓæ/ÒðòìZëéŽs"ά‡mM› æš6‹ó?hÚÚ¿mÚ´ÿRÝÒ?<8hí<839»}òé±#3û82=ñåo@¶`چa/ vbÒf`f1“˜¸1Lò ¦ò0Ré´§aç&a +S?óÇÿ‡ç¿Š'h¦ù\…^ æ1³28°  eÙ¢I%/âC‹zË#ìg"øø­öÏÛۇ *È·]æ¡›mî2siêùoŒ_y¼­÷º  nô™O»«t<÷þ/Œ›§ê?”…nté¾»+ÿc ‡õ +endstream endobj 508 0 obj << /Filter /FlateDecode /Length 37604 /Length1 58304 >> stream +H‰\U P”Gþ^÷ß3ñD„x10r(ƒÁ aÅÌ!Ê%Ȉƨk¢ Q)ðH\¢R¥D×HȚÁ¬F»A7º1Ä+*kDÊÛ]]ט”[Âô>ØìV²óÕ?õºûu÷÷^¿þ 3VA"eÊôˆèÌä´uÀõáÜ;9«Ðᴍ­Ì®ÙZ‘µd±å‡âËoòØÀ|,ۙSøçûñ +¦¨œ‚eÙsn=¢]ÀÖ¦ÜyŽ¹'gÊ~¼^)ÏšËÞ»7].r{@ná⥅%ÑmÜnzî((Êrˆ÷Ü@#û÷ü Ð±ÔéUE¿åù~ìoYà(œç·=öE åkæ“â,Z´˜y󯥶}ÜY<Ïycxs±nºz« €šþúÊ +ôt 7ø»ãž [Õ|XÝùúšôæÙ¿ÿù‚°ïcRŽ ð!^@ +*0§ð)º`5€ ¨EùC ¾¤P‰Kx Ÿ‰kE2®R^Ç'za„¾ËÿÉ(ÕØËñ؍ƒT@ÓÁv’°Qï¼Q7À¡ú„¾È­í¸It=’غ…îÁJ¼‹ÈÇ7ºµ=ƒÈD ­ »@ʍ£LÏÇHìÅyJfk–©‹ö¢€gí"_jÐÍú6þdæñJo¡”ïAƒ,ãÕXŒç1ý .‘7EÉ8¢ÇêJî­Á#&ŽI3óÃxÌÁzìäl4á~$/BÛ©Žq†¨öÓMÆ«XÎuµ³WƒOp€¢(Jø +_Ζ/"•Ç6¢š÷ÿ §)™Ò©Ëjé£{j}[k B3|‡yÇÉ>¼ƒ ”‹þÆbÝö&G8Ûpg˜ÇUÎûxBƒ-â ±RÏÒµú&sñ€?†c*f£Kð~ǧz_áŸôTtbÏSÆQµ\=ԛ8·ÁËܧ°÷t^»œOiö3š8Êîdá(†ÓdšF9´‘6Ó~ºD—„Iˆ…âžtÉFyŪ”Žå•z¡?ïkÅ,äò ¼ÁÙÞÄñÖâ(Ž“S8GÔÄó#Ec—8%®ÊÕr£ÑªÖ¸¯¹ÿæ~ªË`æ*ÇyxsþA½˜Ã@ʧEt™¿#þ »ÈnÒ*‡Èä ™.Ke…üZž4Š:㲯ªÎìp/pŸÑÉúmÎÁļB`C †qýds5Íg~NF1VàM”a×Ë&ì@Çý%Žã<¾Çßù@Ì9w/äª[M•ô ¦£tœZè§vˆ@F¨*ƈx‘(rÄjF…8-šÄÙWfɕr£J †¡U4#I•«S£9ԜdÎôø¶õ~Û ¶ô¶«n¸{»_tovvßÖ3õ2æ„p f¦k™e%×`5ãc®Ä}8†oq¡ƒë#¤¸âýÈÊÕ`ãSCãh§ƒŒóÔL·è=\ÄBr5‰!Fp¤ñbœ˜"¦1rDÃ)ŠÅ>¡ñ™8 š¤· ’áÒ!ÊJ¹[‘çä¿ a،c”1ÓÈ1JŒSÆã¢ñTù+»ÊUUꈩ)ƔjÊ7m5}jºcj5›Ì)æLó +ó9³öbµú ǽ¿üE˜NÑ"ÕÓX*šù^øI§ZK©œ1“˜! äùÊ¦‡ÒB—©LæÉùz—LOdÍ_R ôW±2ë ©N´ˆÇâ¶áC3Ä] +5Þ¥ÏE‘Œ¦öMÔYÃÇ(Qwq±âujGe‰,ÑD¬ª¢fU%ÎÀb\Þhæ[½VláI'Ež(Gš£ž"óþ‘ZÊù-Ji-—èLÃø:!èœôDz;G +>”"ŠTyÈtZ!b•øËIR$×În,àP!BXÓì¬&g)~ØÂzÿØ}¨]±ÕEUÎu¶SÚ0 ‘xY4"–ïÆMFÖ ¹K)¶b…^EsY÷'±~ +ì§|D«¥/s[ÉïE/ÈZ8‡w}Âúÿ «~2=Àkdá›Õ€P£}dageÊ`ý-gÌÅËÜچM¦½ê,¦/`XÜU\åWð +¿9×yÿÞÅüfc§acÖV慽ŸõóíÕÓ»G÷n]»t~Æ˳“‡Ù¤ )6»51Ãâ +ÎpÁÖ¤¤ðö¶ÕÁŽ_td¸,ܕøk—%£ÃÍòkÏ8öÌþ?ϸÿxÆýϓºYFaT¸Íb·Z\'¬–ý4{jÛë¬é×ý{R‡ýN‡Ý™í€ž`±ûå&X\”a±»—ä–Ù3x¹z/Ïxkü<Ïpê=½ØôbËåku֓ïhê0„¯=¶^À£3“rõ¶&Ø]ÏZÚ¸dÝ1ו25͞Ð' =Üæ¢ø,k¦ Ö±®®a.ÿf½Z€£ºÊðϹû(MÈ&¼“@wsÙ`^„‡<V6» ÛæA؍©n t€h‹Ã£¢¦ дTíP†2 £†h¹ ­&:Äq:Œ:X'0}¨•m¡Ã€3Ð1×ï?wï²Ù¢ c&ßþçüÿyüç?ß9ÿ¹VӘî°éQÓø7ðjh¯¿¯r(¹oÀGk9FgG{̔qž#¿ó֙“¾ñÁäÛU ^ŽíδÉddò?W“ÉÝ~óhc,Óàßxc˜"M$£˜xBØÐìÇ\¢'3µLèçuðšìÕ­3"¬Ilô›÷ˌõɍ lLaÒ¤¦íþÂÂРõFüɖ˜0—ñŽºâ¾ñ”lÚ~jJÈ?e´¥ª²Ï—o‡µol^ª“›YX—¶©’jÎ¥†¦t\5öÈX:˜þµ~x3°¦…ü³n!%×.D3üÅ5ô2;±Ìû‰¤¯z÷7]AŸáOÞ ì¿ñч£5);è»A\d–¤‰»S6+*Ìòr&ˆ'Œ…KT}^Uå¶a›|~„Al;âµÕ~ ÀÛ»w DkP1»cvÝOkŠú)T]7E‚-CŽeÂ*¶t;–t÷„¿Fü}1Áô–¦ÿó|ÇEÖךÚÄÿ`^gÛš†Æ¶˜?’L¤bÛÐ2ªfÛ¦m©’fpS"RË P¯©-Æ +ü»‚Q#²!Q£Íqá˜,q»$Š¤ +ümOÌ•X¥݊ÿ/¬4š?júõöo|L p¬¹—·»¥ÖdÖVŒ®/Uå^NRÂa½T4´´%“cFÙ¢¸¬’ɨá&Ɏ«{á÷ÉA“±ä¦HÂÙþë§{‹Ìè¾8±^«µ-ë3´=}!mOs[lЇO¬=-±~¡‰pbY¼o:l±A?îg¥¬e%Wü\A~éè^Õ¾h0DÔ­¬ºR¨úڍ”Îëè4Z; lÏÑ èt[R:þã›"ÜËä€:Xñ*õÀj`$B«}ôɖ‘&_­¢ZƟë3î­˜KÂ^زŽzt|_qŸ zw Vñ5j„­˜ ýý +¢ýã¨7C5$¡_| T̀XĀ•ÀS@#ښÀ·x r?µ{¾D®³äsµR °eCŸÊõÍ@¹žë˜o®œJå(—ÀV晊¶g­KlG»Õ®ý6S7ìKP¿(ðì§"È<`ô…ç8û Ù ÏðZ­«(oƒËQþ2 +_ë WBÿ0ʋ\ôùœ¨±Ö¢œòbÄ&å ‚~7¹ÚçÂÇNØÇ£.¸-æͅ,ⶳL^Њ´CxS] >½…ÆÃ>Vëæ5;kbÿÙ§ƒ(û— Û?öUÜöíSYX'窽ڙZëaqŽ6É£Ö5” ÷xŠ0<hÖ÷!P£wÒÏTë¯ðq¹ë5š‡º˜¬Àc¦]ò:…`«p¿ÞtÒ1†yÖ-ñMšê҃X/âM3à{œ¹.LG»fÕ¿“¦é—¨åÃKôçtœì}dq¿â%ë#Œf`œAà úOÂüÕÞw­u¤m/Ãö$°™L‚}¯â0úpÌóyžÃÞò)Ì=`ŽƒÔþ8¸ßŠÿ …‰À$`Àó¾ü xø.·Á¸Ñ~üxš9ÃÜd~07ÿÁ'ÅYÞÇ͈ sÌ>3?Ñ`rò"ëe5>c‹õE…cțS}SP¾:¸“ÏÛñ¶»ƒ¿Ê×L?ÙÇ;øÇcð¸ªÚè:åYïA[Ž4ŠýÔ o£íh»vÏüÃÕ.‡SøÕ+Ù4âŒÍӞfêóè'ÀN”+!O'í:Þz0öÈSn|*0Ä2ðº#ÀAàWŽ-<םô™pÑèúëÔÍЮ[ÿdd·×wÒ|Ì7__LЗéy†{µy¶Q›Äý OØYuÌ3G6Þ͟»A{“f©ÚÝËï|v9?ÿ¿Æ»W`w*®à>¶94V;O%­­r+}zêq'žÚupqœ¾£ôéý³õà +IÎÙYúìzö¾Þ­.N᭛‡i>¼@Ï2ô¥hÿ/î«6(ªë ŸsÏÝ»»®—]‚p€Ý« kÀµ?¶Ù»4|LÀhh'KµÆ©Ñ«M¦)ÆT-45ÚICÓ P–»jµ•IÇdÌd”Ît¦þPlí¯þ(IZ;iQúœ³»ˆF'éLû§»ó¼Ïy?Î{Î=÷Ü{ßÜ«;.‘´‹ð]ü¬®¾õ9hDr\ΉÈ=v®Õ’íŠs͔}LêWpÖD¬ì¯“ƒòÙ”S䛓þ¥ä%)ëúˆXWŒ)ý©û“º/÷ÞÌÏT/¨g/“ðZp8œû;ù¾¸kϯIì÷I]¼Kþ|O̝gâγgåA9ÿŸ€gçà}à½ÿõXïñŽð²F]I*´¥¨=×Wo}HÈxx&¾ xòÆGÑþ-ځ"´ßíxiÆoÃ>ï¶Òí“j&êwBöÈq»%Ñ÷ÖMà¹DŽ[çù×ï“Ø•è?~Xváø)»wü@9ú¤òüú寧NäGûÖuà@5p4Áã?„߉1~'ê‘ûœCÿ«ü óÇåä9#˜âϜ!þ^ù…ø®3Gêþ§Î÷a¹ÉùkSæó 3Î]Œý㜠+ÔÒ^QSŠ:ZÔ²6ÔÏ¢~œdqn{\òÌdž»Å7PÔ΢~µ-AͬÉyM9Vœ%ë&†ÙõXEEÀŒƒ‹–l†„Ãʜø%»®ô‘„Ãp͚%=W­²²dã‘e‰Flá¢Àµð4v•üPØUv$zÅ +Œ…u(ûqSJ8éF½b²?Ä|ó]؇ðÀ.‘oÈn—,}F ßgïtÔÕgØé¤çt,mF€„wâR(†F1@%Íì-Òt +=HµÂÂzY/æكþnÈb èT²Ž½ û3B²Ÿ³­$}°Ãdø%vHò›àLð°ç€_‡.¸+©Ÿ ÿñ¤ýUè³Áǒ|ö,ðè‚_IêÏâÓ#úíJr7ÛiåpO8þ\ `hFë0–î°¨ )û>Û&GÀÛŒåj³ò¼òµÅš胶aéÛ°rmX¹6¢Â՚ŠiMÄ,b­ˆiEL+bZ±*%l'ÆÛ)6)¤ÈÖ}'Ö]Ø£ÃÀˆ´¿Ù t =‡u,Ĭö³­VÇ&Û[nBçØÓXj“=››踣9§‰NK²[Än–ÞÍ1çtaÝËÌN0¢ž §±M什B2 }À—€r@e›,_1?˞ ÛÄLãíJ;kWÛmjI9M¿À¤opNÒÙ"D@!ii“³Å¹ÛÉ<Î\g‰ÓtÖ9mͬu0ÆY1 ±Za¶øÄ°e_±d®ÖV,étu»¢®a׈ËՆµmTÓl¹Z‰fjuZ“Ö¢íÖ:µnÍÙ©uڕ&W‹k·‹y\¹®—éªsÙ¸v‡÷²âÛéZ€N@ÅG`ÏeO܍–â)QéBh`íQ° šqnĹauÃꆕ@ +Oд$½Ú¤'ÕGď  Š¢4XÓ°¶£c¢TAÓ¡éÐtD(㘡2¨˜´Ø5)_IÒßhÒ?&cR>SôUÆͯ/.¤ÑBÚ]H; © …f>DzzzÄ1"‘µÙÛl44÷¨µÞZ£¶ ¶G yCF¨ Ô£{‹â‚â•{¹Á xÚQ3Ps¡æJ©i®i¯a¥¸u1«¨$ 9ß|ښ›(u‡WâJI² ¸0Â!‹Ð ¨Ê$Wúa퇵ŸÔÀ†ýâõɓ>aï’>Ñ~å.?Å÷Y+–Ô†«ðʍ]Cî>øûdt¢5 íQÈQi¯MÆwK;‡LõaxÁ5Ê×\#¿F"@ `#WØr @fH´€ÊñßÀ6(ýø÷)}Ìoê‹gq2{6 +¦ôOØ£LÇÐQd yLÊýR†¤ô™iUúÍ*ýWUú‹Uú4”†ã°”y¦+¬Ÿ +ëµa½0¬#ÛC$èÊ,)5!é_¤|BJ¿™‘§š§’§”§¿–§ïÈÓ¿œ'úÍó«+Rº„¤G¤¬’r¾éâú{\ßÀõR®‡uz’btR&eŽ”YBҏO¹ËÝÄyŽ~Lʑ‰ZÁBWˆ$:aàÛVp5è–< ú§<ÄÏÓO©ü¤Ñ›–ïÏ¢£•ªÐ?IòG´’ô‚ÇÀ[À?#Aj€ß´‚{DüOÑÿ8ô7H¾CÄ¿Nêd¿.Z)í¯%ûýÄòoĨ',ÿw0êq◣µü7`=dù÷ƒ^¶üÛ@–!&¸Õ +.äát ñ)"v11“šäˆ#ó6ðêDç +Ë/z•‹âô1Ë»´@Ìò<õ’:9·¼ò"³‰W¦˜G¼rÒYМFÝrò:ɗ찼{E;eÜàÿžNþNÝÖIþ§ó¸¾õPÿH+­^þ›!±\¿âSã ¿ì=Ç/úât½Å‡ýqüq…žæƒXä(bz†ø·ð~¯ôöxáÅ­î +.â'¼üUºÅ÷øϋií¸âõp7øå5Á^¾ÊˆS¸Í 3§ñÞoñå0/‹ÓÊX/_싋©” Gï¾#Î÷Ê©|¥ô¬²”Øé·M¿}—}£}½}}¥}‰}‘=מmŸgÏp¤;<Ž4ÇtÇ4‡Ã¡9T‡â ŽŒøĨ‰C%šG¦ +©Ê¶GB¼õêPðìDg²j¥zm¦W“êueÑÒ¢ê¸}âÉ貢ꨣî«õƒ”þ¨ZTÙ§d]=6¨0í͊¦?V?D(-Þ{0Kpëރ ´::¼‰To̍Þ\‹ë˜¶¦1jó–Í!³Ÿ Í ¥?:cùªòûˆ¦¤,ºó›S4õ7';z¤zm}ôíì†h@4&²ª£«×æ~­~HÙ¡4W”)-‚ê‡èóʎŠ'…>_Þ0Fò•„¡âoI„ÅH¾#ù4&Ãjd¶i~Eù`~~"è]Z)‚°}ޕA[¹|¹ê!LÉ!>™Ë§äˆ0ì‡D2÷ÔdÓ uËdîéD&›'‚ !~C„ –4J¥»÷ŽÛk$¦Ó@ 9ŽAä8ÿf½hc›º®÷Þç÷^^œÄßö{ $þˆÍ’WB>lƒÓWòœÄ¬ e±$ōóÅÇØHƒãN£Ð„N+ƒ B·µ°‘‘ì+ý€)NR¨ RÃl¥ý‘Jm'ub"Ú2 ­Š¶F!Îε£¢jü™´§wι¾çøžsÏǽça|_æ+Ȃ%’2òÿóé®ý„ñdûµ®ÎP·+u…º¢‰<½CL tØíã]×(Þ`<юΔ¶w'®¹ºë]®zûx{ç؝”ÝîªG¡ÍÍãjwýD»Úrµ×·LŽöׅ¿¤ëкêú°X?]¬Žê ?€¦ìQª+Lu…©®Qu4­+¼©‡76g¡Ú–º­:I´ÙPÑGK­UÿÔÚtq<ìŸ-˜Ò ¸¶´rK"ÇU›È ¬•Á•Aʂ꤬<˜Ö-±ÄgvLáW–Xz˜6¸j‘ŒÄÐÎú/ÞX,ÖG!—÷ÅÅô\­£)œX÷µÖ愒PB 5Z߂i8âKO]³ªŸVfÒ£ô+ƒÊ°2¦°ñx L§3NÒæìqö;ÃÎ1'G[›Ï©Ê°ó'‡lÂ}ð„êÓ:ã@á¥?ûâ1ú PȨ“ãr]sЉ:¡ÛÅЙ¯D&@@‹~ø=€¿ü @ƒ¾ øÇ¿˜¤3ÌJfeHÜYO5¶ÈôЙÊÉr_åš$ÐömÚԚ¡¡ ª+E 5UÙA4ÞM~àÏÿø€e*™ÊôâñLÖ¶ÄPLÆ`>‚}Åä>,ÃSw÷ÅdQ  Q9ïŽÅ¸„Ò³1ú·8¥÷á †³˜MwˈGã_ oB›Ê“é Äj’äÍ×”ÍÓÁYŒ¤,Ž>A .AޅŸD¢¬¿¥,(ôŸ* +ª±þ Šr‡Áap‚Ãݳ3ï©,º‹ìš‹à‰Í©²=ŠL¨Zu½dxÙ@žÏ9d Ù':M`U¶ðJžs#‡¹óæ'©’Èü‚¢èAÃ|Í|E9Šà¶xVxˆOV[8ŽX̶BBöï>6„+o=sjƒ#¿aªÇ½~Û øðû؏w—ÖœzéʟÆ¿ü3°¡ lؒ¶! —hJ³ePn#Lp›Ù`@æ{†á,Í¿þo#pÄä³Ú¬F‹ñ>¿ßèó®(#e'º‡R3·ŸntHá}lWixۏRßþ õv +ïv‡>»®|8Z5˜š"›GaîÛqºò ‹s¸]BZ$«ËÊiUP«}‚Zãkð°0&á{9ßØK×êÝ#Ëtoåî´õ™`´J –•ƒ—Ò¸l•J×eçÈZˆ(ƒ6©bß)Úî‡@&™j.ā€ÙñZ”ÄEªÙΔ3Qæ)f„™e8æþ-yG“Ä=ãשÖùO©C•å [&ï×_®(—1va²6eو?b~¾…} ÖB ‹7˜7ØHŠÑÔD{–º¿ –µP’››ŸÄ:Õ(ä#ê!ª'êñÌz4ÎkC=¨ ¢¨>É=… ÁµKќߠôÞjœ_J³ºï¨ëq±«ØYL8‚L8Þ½¬`yAaÙ<:·Ö#J6‰p¡qù؜#kŒŠ±½d2ê-HÊ”¾)*MCié“׸²Ãf5˜ xx…gµÞf­ªô¯ö 2)D~Ø×Úwòûïu\:ð­Ë¡@¯¿¯°¬¼8PR]ï{ÔKNÝÀo +_I}œ:÷âßw;ucüÅö=gpàÆÉX¹ã‘¦ÔÄè&5x̊Ž«fUŒŠ#⬨A¢*’§ÑóˆäMx'|£x9ᜡã,» ÀÿF:¼YaáªÐ}ëˆ@0+dåMáÛ þ˜jÌËÓ©_¹®_wL7¢Óè$Û)ÆsKΕ•Fýü-aˆ®L}6&ËéS¥7brWÌV«Íâð­%>êºÿ›¸ÁaR¶¦Ht5›wç»k5üÅ݃{Ö·›,¯ØK®ý¤Ô^XDóð!ØãiØc!Þ¡>NjڀM\öˆWTIé +­Ö^áã_å9Õþ„¦5ë [«¸+«ÏÐgÒþ<阮3Ú3yWÙ«¶·ÄmŠ³ö;š;6 |‰h$¶À"Y%Ûr‘lZQ»Ü+}U:d´ó¢Dˆ-_ʑ¸\F",'Ú ^x“&7 f‚jΩ°dªÔ=›?(áaiL"ÒSŽ;2‰INaQs÷×ÇMm¦S¿IcJb^5©°©|dWív&j±»t߁:ËŪjn#=¤Ÿ ’i2C®“OH‘Š¦ðÑûù<§d2:Òe¥§…5¿éUjzÇ9R·¹ùAO 3A‘ÞyŽaéȢψ¼¾_:"¿%O9¨g÷_΃’Ľ{"1z‘ɘqøòy!TïògŽ:žã ï¨ôûW3§ÛîÍâvl?µ»kØã–fNþæ/å £wÖâŽo~}]>fSwݸŸxõÀh¼÷üÞ?¶}û/Ϧn®ÑWÐÆ¡ ª| ij¯?²g'rBrñ¢ªä‚B({6ìÔ̸¤dM‰êzg¼³ÞÛÙ<òâ ÐïÚ[öZñù⩲«e×]×ÿCu¹Eu_qü÷»ï}\öî.ì² »îe¹{Ù]`Ñe1FPµ1c#! ±AR…D”²¬0PmZ[\«Æ×dAqEG›NM_N§ií´C,MB:ô/:mSÁž{w-3÷þÎÞÝÙYÎùžÏùåOşäÍ(æ5B0‰Ç +$”¤¦Ç]‚K’téš•ؑÄ'¯xH8RêÅt\ƒ×q3ÊDê¯Ä´j@ ë5€JŽš±9‰‡áyQ¼ˆ.JQEðüÊ&¾þ÷$õ7b$¥8Qú£Rª¸·ü*±ß²SvWTÎǟH¯Îl}ûœv›†Yè Ïv¬˜­Ÿµ•GR *+ŽxF ÃåÉ~9_Vd†c•Œ@Àp‰0EØkH6©Øh(æJñ"Ñ£ÑFªH;”Ð>øÓ{¬µ‡Ãö29P'‡^,9=¤œÐ|}b:{~¿Ö‡Zeùæecý§k«&{â;Ž.üýЖˆìr[w;•PÓwüîEáãë|5'Wïk8ÑÌ|éб–šç_Y<±gtßù•ª§P`Wp¦‘¶šµOx +*½Æ¯ö×lí}Sc¸ºõT׈Dt—8DXš¾( M,8dÆY<Ó–ÃŒÙ$"Æ,2œY„®Ê%6^ÈäyA ž3 h‘ˆÅëøûàŸLø$YÌŽXÆlf®Ã^GɚˆÉ`°Ðø$ý6MÑIü/’WèíeÁ À«) máyWÆc=Ô^¡W¨Â%Íi­(H0a¥Yi¾£ÂZnÕæ@q˜y¥…‹ˆÖF©½gù­~«ÃQ80}mâìü©_?»ç^[ønŠÓ}©Só›4~5‚Þ»Øj$c/ùÂÛê¼Û¼½l/×ëdŽxø“Ÿ¥ŸõÕÊ­¹»Ø®ÜÔa÷áÜÓôyCÂ?å· ?¶HV›=Ëá2aòÒZª¬>F.ã“Ý9¹4ŸÍ°ðôä¸Ï'Û'$Ù´@Nñ}Dݗe0Œ“x9ÊÁ«®Äù„¦cüOбƒŸòCƒügB¢2–µ/!‘%¹ò&ñ1<£glº0/ÕkÙÑ¥= Ёæ©.h ¾F™Bq˜…t!íE +4DìÀT‡¯÷Q}>ˆ£8k1µ2Ûm_óî`wxØú:0Y¼Ì3š‚9î1•/hWÅt׺…æ:l8±¿¶ÿ™—»º·ûÝjdíÓ;ÇF^º¶úâ„:r0Ù:W—nX’–äÒ±Þ=¿_VÄSMÏA-Æ@Ù¨= ¡†]ÆΌ>Ã=eFá8÷ÐÝL·c¿“© +8–ö» +\íÛ$`Ø1á à@ÀæìÈx6b5s2naÁD«±™Ü(DB 5„¡©r¥òo!»d÷ÙKìÄ>lOØy»+øÈ¢<Ã9ö(:*èÕúÙH#~”ËË&.‡£ô? +sƒÍ“ëÍ¥8«"ƒ!å4"9¢|c çÚ|(Ï 7ô™GÑ ¡#geÐüg\×<ŠµÔ–_Å\VæçøÓÇûϝnÍþÖÀ­{ï l¾y[þÝ:Ƕê©èšÚC{µl³"Öü𧇶L^¼øÂ8öLàÕ Ïͯ<°¡áƒªÈ™7.}êƒ.¨~8MŸ….0¡w¯!æáÔ¸=g9›|8E¸ÌÒ!C"bƒ˜N½ß§¦DH)6a$‘¦X巉›¦2išbh‘%«bì}ÌÁÁÝ×ö¢$þîD„M.3;I}Œhê#bFŒÄf=“`Xæõ!2§ó®mÓ:®ç´ –fÃ)z £ç'iñ^a_áúÙ~ŽI &dä8ØWl¯þŠº»P±[h/ùrÔÃV>½ÉÜÎ)n0i[à^ÐÛaЛ Pw“É:X…¢‹¢!u{´;/nŠ›ãîxNŸŽ^È>ë>§Œ›/»¯®«··MwEŒ˜)·AuˆN·"*kñ ~Uܟqe<‰–áµh-^S° E}!ڂZð6jk EmŽîÁ{Õ]…{£CÌçãBŸµÏ6”9äxƒ9.¼n=n;áx3ð–úV4ÉL3¦OÌ33ê̒ /Ôe¨?±„]) ³[eô›äÔ½8Çi‡]ôT€ëP¾v•@,‹%#1ŠÄb‰ØTŒ‰ùoÀ4ô@zÀXâ$Îa'ít•Nâ¤Á¢Ùó9*³Ós)‡® k[ˆ|I8âͳ:!K‘Y?ØqÞӈ 3C¨Ø1éÕìxØQԈ"Ö¢”ÔÓZ×棛v­jG+ïp¦vU{¦”¥µ®)ßÎiGzZâC§êï\8ó³¶K£åÕ{·mc^¼›ìjjŠÇ—mX䥶¾À*êRbcÿ­w:ªGZ®kjúe×旟ûC[OͶÎ]5¥Í‘…ž:Û°ïDwíêò`Ð3Ð çAN¤b3‰îQï±wóî©L3ÓÅö݆Nón±ËÞé^µ ÂPzR`ÕlYÍfi¯Â žÄ[P6&—Õõ0ـLÄQ¶+àœ‘W+O Œ¼ìt"1[#[®"›dóÙh[¿4 +’`Qq•SJeô‘±A ).à Œpà]Á-­ßª\OÊJAAk®2Fþ¡“vT0÷µãdƒxU˜~UwéUÈß]üCƒ9#˖‡¬¶ºTwCfp>¢”ܾ֮ îê«4mƔ\×±iåàúoV;بîÇ î‡)ëƒÃékiLÓ ‡¸íž>wÖ³ÙÁBÂWÀ§éóK¿hgúûÛ;Þ_Êøûü‹ýKVº˜ðCÊË{™uàa4èÌã`'¸“ÆG éLF΀Þ%u™4L9ÃÏîMˈi@g#™ ç®m°Î¦2\G5È°ž7p†þ¾€çO.ü~ƒØáÌãÅJÛQ›h([2È4ÕÕe—–wÌnåíâ‚"`_ÚÜÄut¡®—+Sþ`<¨û‚LН]š‡ç&Ï=äÊÃÆ'#‘EjˆÐ½^DA¡f3ºË±ÂEÐz£@!R¸D.¶¶ÎÏ +µ`)Å ½‰œ%æ-næÌën¼WŸßÙÑÙމõsR-)¤VCöjÈ’ªÃ´ÄÏ»·kt7vy>ÆxážòaèðQIùèpyyj§ Gpó$¤ú/0×Ð;:SmÃpAÓB/ÐÅY/(‹°ÃÀpjO¹=%k­â¨„³¸a*#Ž|­Íž]Jªjkj¢ +âÿ¦Lk2¤ª ƒì6+#ûA¥Œ@ (¡$±¹ž±Ò`¾Ûú’µ6jü®‘U éݗ44ªÁ®y4í‰ø»Nï>TüóÑËÅáËïÁ,|e8µ¼X]ÈÌÌõk0VjdÛ艄ö:™3ǙH™hôõôv®’ð^<.¯>ÿò­ñPR5ñþ„f#µšŸUrû«Kn^,¹š{Ü®åg¤2aâÊé˛¹\é{˸HÖÖ/®çÉ:q3aFÍ;¹Q2jÝ!n÷íçö“½–ýâ47MÞä§Å÷¸Sä]ï)ñ¯ÜYòw…\oq7É-ï-1jäºä£ì‹nðŠ¢Çh.ŒSp+ì›`ß"rÄOD'h!6ËF ´ÎlΣ“Š‰6„DŸ÷¥ËÃI¥Â@8lw8 £Á“‡·#GŸA‡ÌŠ%â½"óèšbö+æ>ó?ÍØüKÿ#;µüíæi̺xUǪ̀…~èxƒŠœB˨¹¤dF̵®È¨nۉˆ HÞúÿq”l;ѶЯ&m¾Š8D5M@õÓHR`7B:J5ݖ#üJá_+‚s¾QÌfÝò\øQ<ÛÎ×÷LX^Ãî£GXtŠ½òviŸtNfý)%՗ZƒÖàUºUúUìªøfý&~“°Q–6Õl ÿPÿ”ð”¸KIŠ}ûLº-¹—8Ÿ` ‰Opªd `& +’Ÿ„ƒ³š¢2® †“I£cVØét Ú°Š”g¨’SaŸJj&£š‘‰ÖtBN´uhV±Qÿ•X&Æ=ȓe"¾¦hz´'­ +U´ö¼Èœg0£:ËL–` ŸT¦œQBQ}e%ÊF+8NM&:)–9‚²œ_rÏ7§~πX ]”SÐB‰´ôÌPìr‘\[ÿ4¨Ã÷\43³Œ¦ã¡C3À†JtŒvµâÌhE…ö’dŒD´Â’Ž%ªÂ.²¼à^_-Qš(W‡]Õ2Œ±u2¬«eœ€u2®fÉ0®«•AÈ”X“2UJ´´üUS$-4ï ¡ÜWtPKÄZ_HÊõ4‘[TNQ• P&§úC-Ãkl›µÜ™*¯cñøÓ«G>¾X‘³!§·¦GF ^Z³çùïž­lÞýì¢ã¯¯íÎM[z|×Ü~ýN̬xòáél¨¡j뻁hÈ%M=öÍ_p,ÛúƒžÇ^vÜù¶ppKïîû ÚsÁ—Ÿè8š«%ˆ”ŒQŒÁŠá˜o·W<È´妬å‘®nÃOØ·8žÆ;ð~ ¿ØÌ o'^†u1±H”c@Ý$ |²î£þ}º°Ã<úxÒy@’ÇéÉ]¦LȔÇ1%f3¢1!¬'c¿µ@Ÿ¥Õ‚,¼Bhlñ» çò¹Kƒ‡«+´vÆÜ"C=”N |1”£„"§2¸Ü—Zg®Ý )GUL'µãýÝÕÛÄu‡ï½³Ïç¿9ŸÿžÏöùÝål'ŽãKr1+qÈ¡Ek²-ÍÔM°Q¶®T8a¤Ðj +•º¦0&"­T0©[Û©Ú¨Jǟya…°i•XËFm×­™ÔMeÀÆ(ƒªÅÎÞ{I +tª¬{~º{—Èß÷û¾ßïK…dÎãÐciw:¬s²3ÏxBxá%{¸"Þ<™²Á­3öÈðhtÒ¦ ‹"œMK‘($֓™›0·Èöº¢,ùǏÆÿôíÑK{ûÝVe}íòÑڋ¿Üqt½üý]¢Œ¹íÔÚþpd{íì¹JíÊÄðóÁÃÏ8uãU0pte8 dªÕp—ÜŠÝ)ŒÓkÝë–݉DžÝ‚}T Ž {{C'哉³õ‹ÁD’u„Àxì‰$Ìòœ"ãùÁ¡È^¤E¤d}>/”²á0ÃÇK}"˜‹4†h‰v±2û×#CñNhqIW»¥”ÊÚ>mFc5¡jŒP5F(ܲ}är–íenÌ1Æo³oãv9vñ¼Ãål„äñT@Úòò²#¡È¤rBr§Á.s>ê´IEN#-הuñ›B a\#yFK3Y! ³xÆÒ3™4 GøL.»ŸiLƒ£g'Î ŽS ÏŽÓ{Øjf|”"eÃG)ò©É¥(Ao&(E‰Éæÿ£è*f¨„{ú0ͨ˜Ÿ á.Ž]±T-ѐJ3*&C¸t‘ª ß-ƒõ€½ø‰ÚüZ3Ô4?N™Xm¡[\lŽ®yž¹~OŸW×A¦gùu¯+Õd´T§ŒtÔëRpE°ÿñj±žû¾i‡Õ «6ÖÚûîÒkƒ_G’Õõ–ÔÃ솹}íÍÕ÷f _+±7ý{“ †¬—mE3”2±,¢‚SE«¸¦¸…/GËҖƉè„t z@rç £îq7-6Çú‹åâNÛ ¶™¢ÍÃ>îž.²+yÌKô}U$¬i&u«ƒÔ­ÀAIANrä¤ê÷÷‹"¬ûDH”6&Ί6ÑFرÜÞ=DåVXnW©? êÒJâ¶yÙȟI äyúÎöu;æ¹Âò©^Ër”*Êæ +S’°àkóš2S9‡ÀëÙLC¦1Ãrܶꐿ¤ÁïȹòŒWːòu0Î —nݗgn‹,s†‡Û¤QÛÃ,¦È@6ç{~Ò|ÚQˆ¤Þw-j‚Øüh*¡Glç1í[ÕªãÃO½¿mÕÎn¥ûóÐ+ݝnšÙ^{èµ½ƒë¾ûÕ»¶nüL ³Øö}nó©þýëÚôî´žX߅ÒiS°¶vÉâ/_?øìoîÿb´!¤µaæ‰7>•ÚšË¿èµhŒ^™½v˜0¢›•Ù–H¶&­}“Rdð+@n€J¹S©^ÔÊì{ŒJª±n玾šðUÀW3ãÁ«_]ø*áDâîdêë›;asÜ™®Í!§pü¸x‘. @ lúTŽ|ÿ%7Ýbädk¸Ü»¯÷tïL¯-Ð;·Šýx qŹ‘ª*r©¦"7#µG‘— *² iE–‘¦+riíŠÜ‰4Œ€V_//éìt»]°9ŸÇe^ ¨ÐRÁ9¤TC-«ûÔÓêŒÊ©˜²bBïšÞé^6Õ z{tµ½ß\cBsrÅÚw¢¹Ï +WG°”„ájÕÒ͙æ¬`a†ÁƒúPñü¦¶ià:ø¤øѧÛÁü+à98Š} gp¹aäRlM†Qý•ñ…´TÝAµTÎ[~{0ˆ¸í¿ûƜ1D„îu7vßt ðtík·xÆ·#žÑ†[ë\9 +sÂڈ,B8¢¥ƒ¬l»„Öú×yE†H*²ˆTI‘ҜŠìGšèÇFÍG%HªFâI•H6òª¤:Ëü6~†ggy`ðýüž]ÍOó§y–·‘c<­@¾2ûÁ!ò.ÞÔ¬ù×üÚTmC3ˆ5P?ZƒØitABÊݘ jÓXôÃ#ó^M zŽ²êŸ‚ëpË' Ã RHõÛü”ìoâ5¶¶?\<îšòò2@´õ4ã,Â{à}pÜnMÀ½ÖAï!ßTÛÔ²7¼oµzE7`}ƒöÖï2㭓Ì~°Ï÷z+ïÆs2ířô62:(8»œ}ΝÌ+æÛ̳Îé–Üh‡mÖR«¿ç'àøœuqXzŠy‡9 ÎÂ7Ù Ìpü×uÙsÅ ·…M³Õ0À^æIïS­»MçKqZ êÔd)Ù³<Ą è36 Kr”‹ò i9ӑÄ>ª¿¥ ÉSԈBµ$[wp^‡Ì‘.‹Ô‚"g‘Zêî”Kv›M¶×Ñ®«(riæb¹0ŒêóñèÚÍ0xÒ0Ì a˜ ðšÝöƒé6m‹½zÜ®ÿ^5°M\wüýßÙñ±}¾Ø¾³Ï‰ïÎßI|w8à|à£i, Ðè€P¬ XÚҒ¤á3ëU ›h¥j£í¦ŒUV%„•L*Õ:* MSÇG¥1©t u«]Kâì½sR ª´$wïÿÎÒ)~ÿÿïËa³¹»ÝçÝ؝°Yl¶@ x\hinN¥’­MMétâxRàù²2k[í-/[ܺ®Y¬Ðmëžo”®.<à‚.páύZÍc:*©S!< +{:3bobºjøÑÇÎA‹Dƒ³AtÖZSÕKâ¨É¢,Qì<[*§ZØû¿¥ 9¡‚FΊü¹ÝjÍóì;dè* –hü8Qhº<´é$„LÌ1êém[c8´ºÌBí‘L›¥ÐY¨i[·Æp6 +WÞ)ùrÙ±éë£lÎ`Ý9 Z7âÎ!òdÄ܍°t7~’,%š'n “†âñ à ј‰3 ÿ—Ò½óÐ<3¨Ògnl+³áp§ÿW«§ú›ê*Šµ&dÔ©ß>@M¨ZmDðm…ô±:Ok—t- œÆÿ*zú;Ëâñ¤ $êáÅŽ‡Ü "”˜ÝØX\_±Ø'RU|”¸Ë@~‘ï,A]šøù3u:aˆ,bABÊjü¼I¯JG¥³R9(cpÀ¨solü^W… ×3²˜'z[gDd娑Ž Ä ¿‡½,G1c'°ÛŒÇð;†øºxäp8ÍQqšOæ¨8‡åõ…ûæ»ÄVwîÐ\DcÑGJVT_{‰¾ÏÈçbFbÉág-?–ûî}\·*î7Ϧͫ%¶<»gÃO¿×Ûmŗâó¥>æivâPmìœ<¾2â÷©[K\Tö)9Þ3nzp#;ïºRž´§Ú¢Û¸VhÕ:…-Ð%<£íÂkÚEáªpn .—N¾L_¤3B£¾X`zRHèL™`Õyž©Ai²kFM|Nh6èùìòlڅ¶ ;ƒ}úÚ/¼ ¿ŠêGÑaýPöDö}þ=a<û!E¸”ào ·‚׳wÑügz| ´ó‹´µÐɯҞâwß.èè7„º›0…CV¤ˆ’Õdâ“ìr”5³•l2µé|H" +¥ºæÓ^× 4ò¿ó¡`Ç»!]O¦ìúÄ5U‘$ù|B¦Z|].“‡,dÓW¸Xäñ.žkŠ4é%uN$æÞ-Ђ¨ŽV$ wÉ@H{sƒvµÆJ!m'¦…pßO…ï!.PÀŠë+ÏCéÆæÁ›X.‡ìBŽ›¾tšÏñº/GàYƒJW'“M\>ŒJjÐp| Ì¢©;b|…^Lé«bŸ»c% À?á#ÐVÇáø +mj\_ LýDzurÛó‘êx¼^êe¶­MU&ã÷®YÌíäЗ ÝûѹéÓ·H"[Š’ð;£cˆîEl,oxW‰!‰3ó+vT¼‚ÿŠ§±­BQ8–:\E¦Wah_£>Ú×(Çyc…S|§„¾nx’ÇÁépCvÎÁ˜ý(çVz½«³Ë°„ÎÞò’æ°³6ƒ£zìpš°›ÁæŒ4Hi8”¾žÆé +}…_–uÆ’L÷oF0…†1§™ ‚©õ¯Ï¢¶ä2h»{zkLÛAꏩ_Ηz=11Xj3âr3[lc[æê¨@é9åà‚\ò(Ç-GßྍÖr[ÐSÜ.î'pކÓÜEø¸O0ÐäՉzj ‡ŒÄY„§œªâò˜|‡S„ÍI„¼9J†Êçh92³ˆæ2̏Jˈ‡Ëq.‡Y?¹‚9}.Ìɑ×\*-ÿ=íËaÃ;Ëù”ôÍ:U¨À¡ªÈUF¿:e Jý"t3­tbà2¥Øä÷ÅÄr2Xtš[›+›­K'mŒ{vTîí·<:ù›/çÍÇj+£%Ó³î°>Ê‘ˆNsrGlGGYËvØi„}6K›Ý•BŒ?UæZ"ŒÆ`Ä°ŒÄèŒÁX™öJÚßP¾Aª4*q¥·…uHìqDØÑÞ¸Ál`¡wÙÄ2¶§æ.-ˆMÌO˜Ö0 ¢'>'JT$ÜåÞ AȀÏFª€•T¬Ó• &7ÎîÏ ÞBnVÍn`¢,^Éô>¯‘'‡åe©wä¼l2'À{Š»Š·‹7‹{><ÿÙè³û±/üÝT·ú£°m§p&öëÔ5ñZøj¬,˜dÕT"Ï%›Sºº6ùd²[P缋 N‡; ^­GRð‡ØþjìJòrêv¬,lD+Sv7¥R"¢MŽ¢õËQT)ÕVW¦òÑåQÚüÕ©@Àí6;‡BlH¡î5Ô®Ò,È7  õ„Š¦Ž«—TF­S Á”B0ÛD›Û|è6õÑ=œQÇ`û)yý†¯ø¨¼–µ0$˜Ì?Ds™è4ó;A̓V˜ “+)(ij8–æÃB<•Hó‰:ˆ…É-¬®ƒ¸­C3ÍÛ½µ?N¢A¡Ÿh³E©’šI #(iì6 P/ôR8Ö| ÃRhdÉYøhdHÌ°POxW±ÁáIJú©·‰>ûD¢ÏðïÑ?½tí÷s{6|³²ëà’½×­ÀýÅ­¢Ïó#}ÌfZuŒì:|ɽØéüùÀšƒ¤óQ’ºHçS¨cc$&Ð㊛‡6¨÷BâBôB†iý2ƒ…¯nŠ1pÄñÅh lÁ[býЏŸ‹<'mSvć`Pz%s ŽÅÏ$Îe¦cþ2i/ü0¶7ùZìð>{3s>sYÿ$3qq(!Ì¥Hwç6©Mú¦Ø“š³ÚŽÃaðGD¬ xJD$ÿ¹Iò‹ˆa9jàÚx,¦`ða ÿã»Üc£80¾3·Ïۻݽ×ÞË·{ëó=×¾[ûø.`¯”B 8ب`LJ©H)Tؖ‰F.(¤q“V +¤iJ]©¥)и'@ E…$¥R$ªöÔ? +T)MÕ¸qTWjElwfÎ$}Hµt;s{g¾ù¾ß×2 ãËe_á°&‚øçr +×Çíà‡¹ãä¨ètSi±åŽL,ÖeIBõ…÷˜E·•ñ`¯í-SÆiö¢0†Æ9¥ìÊHåzÅQ)ñDQ¶P5M¬¦BCM…5­„öܜ‚äT+˜˜ÎÃeî‰o5ZAosRa&~Ùn…°ÞÚÚµ„žlKŠ ]C—|sk‘J´XñŽ" L¤'@Ɛ¦ÆHÔ_ ’ˆ¿]˜¿ç_÷W3˜ÏýĨÑtþœRµY3h82ŠyÓ4 @¤öÿ¤Èa^+bDZdv/½¸T.ÆݚҔê)Qh½ñëç^~„v<»ïÓ5¾&áí«ÇÕv¯C–ÿOivŸúÚÄlj鉧·¹à àä“Žùp¯=¸|›fkw­vØû½V ŠJ¦3T–1{A/<µY°Î¾^é¬DQz84Ž GYÆÍHTîJÇÝãÒãòˆ6¢F¬gø§ÅI÷¤ô”!O¥/§ÿ‘bWK(¢ Ñ¬ëѰќӣÀHøôhÈH Jˆr +&3n!‡ºÁ'gñª¡ÉRȯ`7ExÛUåm„—¼ÅCÕ +Ûã÷ãì!9Äâã»çI EÈ/ýBwY±ÀˆuÜ:cݲhK“ÍŒ“ÍŒ“ÍŒ7{½|`ŸøHvù$üšOïù……Ï{îd“6!"Íì0"7ñ¹&ÑÕ(”7ïŸYÅ££›22NO³‘0 +'ÓÉ)ÞF)ž”+ÛD§¡$Û¨Œ˜Ä4 ÈAEÎá3ŠÎ"5Š,øŒüý,ɝʚ/~rþVÈñ>¸Uì3›ç®ýþŽ_û`n(õ·„c=ÏíþæoD‰Ã¤“ÉûõÑÅß]»ýÒԓ‡Þ‰MÉd¹elq¦÷Ú؆ñs7`ò@¼éÀ‹ÚÀkøtAïY§ÌêpÂûû·U¦¸gxSÒ¡ÊI$ +ÝÞj·²xýúPh·¢¨*Py±zJ„&B„&Þ(–Kdl-Ñ>O”þ潫ÏŽ‹Á ¡ŸGÎÿä˜SáéÈ%æ<{C5ö{Šûià„Êü;,öN©‡ æ±ÀÃÁqz¿ó Á ª[ƒ}Æ#ìcó7À?äÜ. Ûè£ú[™/±LÜ(ѝuÔ“d³\†Ï2*ƒÓ°ŒÆuƒ™añ?e7Q’wª5§:T΍ÿŨ„rœãu âóWW¯^½Š(·Ž\»ZÚ~ŠQJ(QYâћõ Õg—'mÊ±qžã ù 0,‹\VƒèYP—fQc…»Aü“¥Úêau^¥Õ­€è œ ̘x`G`$p0@fá_ÎǍ=φ°yÔà õêTh¥é®ždفÆ™˜(E0ýïuÙÆhýó?B4ˆ¨Ç°å ΐ·*ÛÞ*Û«Råy_aãó¾ª3ãÃwoÌÈÕ{mkq°ZžÀ&”Fbdq:Ђt™ym}²œ]J'—è´~  æ¶wæÁ° µµŒ‹éIºöGî~ƒ>2è×L2)ä[:¾òéžñ¶XYD¦€(º|››@ +¬:´†öÎ  3›ò{úlÙ[…iØ$XQZôB‘§ +H†Áj7âgR ¬›sñNs:-¶Êy¥¯êB("/”ÐxMh´?D“ŠP.lèm M±ÿb¼üc£6Ï8î×ç󏳓ø|¿|öýðùr¶“;Ÿ}\ΗÀù +Ò ’RX- èÂ֎PÖ JH…¦)•V­l‚I[«UP‚*uƒ,MáŸHk·N€´ý±‰J¨›4¡1‰U‚‘cïë;X¶iÒlÝûø}ýÞ+ù}ŸÏó<ß<]` ÎR—Ümè¥>ґzìµäjjˆ]'o"G¨zK`„‘FìM¥=ä.êvL“¿Už &È j"p€=Ä’ȇ”—­ãÄ[ô›‰7¬7ìéÒ÷©Óì;¡wÄÓÒ)ù¤ñë¤}Ž>ϜgÏKçä™ÄùäÖEê"ýq`^šµmߥï²÷“w•'ƬÝöXiš!*ò ©½éo›Änj7=Æø†˜õéuƐEl‘Ÿ±ž²}ÃÔ0½•õ€eV"ju'ºÒ%Êa™–×'1¡¿*ÛL‚`ƒÍ•šbK;º€Üúý€çøÈõ½‚¹~I$h† $`ݕJÑ AIa9dX]²!pp=¥ÉºSªÈÎüƒñ‹2PæìuÃ6M)˪2œ-K‰DŠ 9V’¦UÛ +Û¶U") +½IØ%Ø-…Ý0 ¸Äp6 iŠéÿ y¦Ïì‚Û[B!¦êW3í»4Yz»äÛPÚQ-{¥Û%ºôgúOÌFVþ…Ä^ÂL÷\Ö冹«œû Ú?ób´¯¶ÝºçoŠüâO¤ä¿|¤K<Ó$oªýp“¼=Ї—°ø¿a\ÚR|û oŠ@Œ>äÆüQՆ F´­–BbÃ&- +l͛€DÉQ[8¶ˆl¦ɐ®kÍ{É`‹Ól/u¸÷±T8ßxÝhü¶q¥³ñ¢É…×ôƒ¯ÄÞJ°_ +Tq¡x<ԅó•/$£Ú +H°Ö“=öË¾÷L<$¦år9[ÍY¤ð©—ž]¦…Úš„C]壋iü/¯Ú1ƒn÷¨îÀ0ÿGêš¯ÐÊ(A‚eÈô,Y]näܼÌ`EB‹Wp Ó$Õà…\ÐK3üýG€óƒ -ÎhUpûnÆ/À|Ãmïp,>ìðu7ïÖ}uäßKg{&°ÁWÔñü+æÔÓÙ³à,?“™Qg²gÍërörî²v©2WûœÿLþLùÜY¨_®+wÙÛõ„`ñŠ *y£hY+x[°•þLŸnç×bmVWêvýjø• ¾c¾jÏO[ĪünKÆÇdãÙèÊZ}HZ¥“B¸:‹»3g2gŠD‹@•ênWP+âA,S$äÚ +Y"%m…¬U4„¡‡`Ë Mx˜ƒ†ŠŠ̌bñjW…L¡Fò”LJ +\E7 a­*;~@Èþ¸ ÊqME«ZË助ò¼ +Ì0&Œœ‚m¥b…Å*f‚á5@u*è@¸“¤Ÿ«ZPb*ÀρQ0~À pÀ<~ÏíX­<­ìR|Ê2L}OÅÕyü—sný‡Áº³ J!˜Ââ„Z/²4…GR{ ©ÿ Ÿ¥m¼ CØ6XE_€;Á@(}«Fæ,Ð¥Z+}Pë  +{OfW~¯5ZGÚæÀ<æQÖñ¼¾§‚w‹°,ßæà0º!ÎɊ¬S„¿ìº¨£ÙQ4¾0uT#Š2㍠Q' Í눼€^ÞvYÁ1iÁQÁ©ÀE.t8zÓ0“B£4M¾iVþ{z}ta^ë}ËXæ÷-‡Å¬õt@9÷ÑØr–dâP¨9«9‚$o5È|yëâ¥j""3”ýeã¦)ô­o¤Ë¹•ãë€Ûøû‹§vâû‡ûí«ëqÅuà §³oëFü¯'gwÀ X&ŠÅ‚kÁs“U=¢tûr9?/< N‚©wwž¯˜È­mü”úŒH„êˆ=¹q‚ÜÏxºâú¬‚W¡Ÿ«õºövq{|Ø& +±C±ƒÚAýDlZ'ãþ8‰cv„ŠŠ=lûý~øF'2˜:)Cï4rEÛ~¸öS`„Úš1†íýä~j¿±¿{ܞ“ä1ê˜1Ù=i¿Ûý>xÏþ4y=yÃVŽ“SԔá.ƒ¦ LkŠœÆŒ¢Œ5¥aJLÊ©NMŒÅ Ì C÷§há¡ê좳 ʦ J×Dš–N§”ŒEçܛE>Üñd zp;<%¨º4ƒ{2Ž}ì)Éí‚ÐÖ«è¶îêÃú¸>©¿­Sú<~ꢅ ‰ów¶å%¨1$±¥4–rƒúM­Rh¥ 8-€òKi>7ƒÏlU«ê8t-/íìۇAÑ^…O0? +£` Lƒ¹0‡êBdCÿœs"ÇE%¡—]`úEŠÜò¿r”*WÁï%i×ƁÆ' mcaq)ÔÆ[YO„5|uÊÚ°È 0ì냹¦øµ¯/.6>|(WA¯ìZ– är…BçöÆøéöb¢Ç0|pË7íû[†­ð 6ó‹«Ô\´Û5LD¦Š9šeñÍ9Oæ0®ÜdVÀ7—£h +ìÿÑ£etxtdeonÙ¡Å3Á @?ùÛÅ:Äâ^Ñg‰GE\<1A_l¸8üìqsÒÄÍ^¸oó¾ÇÝ ÁL`Žæ°rÇõôÀ¿O€Ü\þ'×UÛÆUÇß»¯gûÎöùëâ8gß]œs>.‰“Öùp’.îœ5]¶64iKñjuS‹Ð†bWTt áҕ*í>¦UmGb•hÖïn <Ö­]!R™Ð(ˆj +6Œ‚h§J% ÿwÎVå{ïÏïù½w÷ûø¿7ðԀL:£'LÍ,™3&—1L¦dbS¦Ì7˜,"(i –]À;2±ºdº“dÐÓÛÝËN‡ËÁF½^Ï]bZG¾h@Eþ€Ws«¸>ÞϧUÔëHé¸+%úUYŞz(ú„•R +´‚¾VKK˞={€™ÀP\("ênƒ~Û,DÏog:a§íԊd»:çI÷èê2”©:͈Dp']L×À¥R´GD8ىéž&Z» vAí„Ú™FÿgC›aŸ&ˆo¼>ѕ¢Fô×!T¬¶u¯\Q£Ô(!p)å{B´½ÑGm jå +føنîU[¿kþõ?6Žš &™0“³Gž\߯ú]5^Y + LmïìÃßošì}øé'|µßúr¶sèk“ ÓÛëë[ûÚW¤Ú&gšµû­}Ÿ¼»·?Hܽ‡†^À¹ÚÖ|zíV`þÒÝ¥yö"ÿRP~¯Êü×bxbìǓ^=¬¶xp måé-‡?ÖÕÕÄ||ñ_¿½õ½R_{ö¥µ9>µØ´ø§+¯üröuAÈQֆFÀ= |û”ƒÃŸú$Š A¢lÓë$ycÊ` x$g)žŒ((þ™@™€àê9ê(ÑN$äÛÊ ^ªØ@™»DâSÝÙҖBqúöjÜyF làÆùqaÙT·I%;ø]| •Œ3p ¹¦ßDá=xO†'Ô­ñ|8¯î +Õþç3¾™ð+ø8s2~¿‰/“˵wÌ«ê·pX`Füýµƒz)¾'>ÿ|é&ÒáÒ@0PQî\䍒Á C6tcÌ ûš1Ž³FÙ¸fÜ4 ·±=ú{/+¦“DiæLÓ*ÓëOÃ&Eã7š„G¥ç%FJʨePM¡4‹Êè&rÒ½º3²7ŒEð‘Ž\ÀRÆ¿ `$Ȃ.t²õًÌw ¬ba]%W,,róV–5X©léž÷/SÌ5}4º3ʾ=.lnôööâ^\ÈQØ l*H§ë@÷ÎÒ¼,§11¿ï±UŸ;6½m}O +ñì[Xøà:ö<¿.‘L„vi±‘mǎßͶï†Ý-Ís<(”†Ú˜‡–±•Hf(²š…° *G`6ؐUlÁRDÊ’âI—(Ðt»7´ÞÉؐÔÃt„®¾ÎþE©QÃ]TóSé’§‡™‘ /®µ•µ3ª\I¸ðr†qò‹² NÈ1>•¯ÏûaÒE–¥CÕ©(ÎDóQ&ª‰ð7¢bk˜ÂQÁ‚i­s^/” ý…$›í>öæ„ AH¶Ûª6gUÅÍ*ÏÁ)‡.&—›¬€²À7.¢äRùôðp*I)r¿ÕžÊ'Ÿâžâp¥äÉd9I2ÉR’AI¥%dMðŽ Ö!BÖ¬'{\îI׸Ÿ´M’rrÁbtéÆë€v\ð}TDßîz\R?‚Žè¯’‹ä1á4J«ý±ÀP(Ú¨¬VcÑ! †‰\kÈ~jZ+nmÕXQC¢!é4Áð‡òJI9©°š2£0ÊGÍc¬õtS{ŠÖ燻„l{ö›U}„,c±˜X ÈÞA+Te[‘|O&# ‹s4š G³Ž,Š&b긅oµ…W%1×Kø.àb!þ î\5b?q×=e¬Úq ïòµ3Ÿa˜¹œ-ºyç­Ý£ ˍ}m^C©k?YhMnz`Ëìã[v¬Yu÷í·ñ𺟶…òîcê/^x_šJ~éÊÕߢ½ggQEÙo,#ºÉ¡€ßI^€ òؕÇLO¨#ƒ°ÒÀ $CÊÖJd|>DH¬3}™0„þLG[]¡á.,½o€àêyÊ®Sma 4 ˆ¢*—ËÙ°;NΕï™q4TBGAŽXÝV'¶ºˆêŒ:I¦BX&:™%,"yHŽ|—{™;űt*[£LLP8ƒZ öICØ-Àžî*85A“Ç£Åþ×­¹kÔÅs—r9k…½VX)…{¦Ö¿5œ«Í£|ð}–¯ÕUHÓÔ´’QÓ]•+;’rhÔ"4bM)»y¼¥=U'Ô:7Q¶Ö|!¼%B0ëˆÓ!ñ¡…iæa¿t@Þýs"|6ð;æÞ?Ê·˜³žäS°»iç›äŠw€Ó÷Ó ë¤<€'#ÝÎ5Ì°sTÛÀlpncŠÌt`ºö‡ãÎãÿ¥ºúc›¸îø½;û|¾8çóÅ?cÇöŸĹÄ!¶c‡I`™CH€´$xQAš:iJbV!M¤eŒ±NJÄÔuAé?eS÷GSjZS‰’MS»fD›4uZ¨„:i%뚶öý>›©sr÷}ï{ï½»{÷ý~?ŸX®XWÄß²eoÛî‹NaÃBˆ…C‹{·›¶bá-ß39™”Û…Ú¤ä•#®S®e×-—ÉåòÿÑDà n€˜¢6¡ùÐRò¸Çßðü"–wܟ·»ÉŒû”{Á͹ï;óI ‹›„[' †o"¬·^xMr™˜sW\»¡¤$C“8F’¥°Äݓˆ„Ob…½”‚uæ`dkiËܘMàù2MC*YvÀ'®=ã® ò   †L1¹37E&*NÄû}—/O\™{f¢7ôtC¡h‡¸Ëíݺ4¿­=‰>Íê;÷îñA=̨ßijêú֟ú‡ ü˜'îáþœ|óuf’{ÙxAq½]ÊrŒ.—Øm'²LßÁx1l*ôŒ–fzŽGgK ¦óiÏ÷½ ™í<½{aø£/y^ò.VMWÍOÅû^ú½áÕÒFévé^ÉßvuËg6T2ÿB(f ~ÆÍeÕ¢Ÿñ (Ù.5ÚD«µ©Éiæ5¢hÕGŸTÀ! ?‡ÓV@k4( …eíuíºÆiUrñÊDrÄ 5q¬²¬¾®^W9µ>‡Z˜¢ÂXûX$E¼E\ÅvLâ˜“8«D0šfrJ€†–2üÒ¨r]†ÍW;}dÌ7ïc}×Ø?0<$×Ó—DÞâÛOö··ÛGÞåR€wA8ç™.e„ä™I-¤–S\ʋøš²aJ¤2ùn~œŒã»5B¶BãýŠì¤O*8÷ ±i\ ÅIœÆ §9½'£ñÙøj|#nŠK8.ݯ`ÊCã#~<\J•ŒÒ+°çæN 4ØÒ%iá§{È'íé +»‰Ý=ë¾ Å¾úè ÁóÜ6$núŒî*{ÍhZ*BWŠãØ1Ž0œÌ±n¥¯%M-¬Êáí‘&cãm|Gî™Ã¥wÈs ëÄ7Îy“ɘPË7Ë[´±™,ߑ“sh'YÆꟜ“ïwA+oÖAaë3„ˆ‚¼YFÕ;ÇÃ`@‰ÊMõ–ÊN”ïo)K¢G»¥§Œ‰çr ‚þiƝ>Ô»;’ ´x¼ÄÕ¶wuw¥»8~Wt4Ú¡µEŸÒÆ$°#`†3#a¦ŸÂÌæB€ÓǴäx˜ z÷ȓ±CòÔ¡–^? ÷ï`övÃd¸˜Éì@êøNS_€ìëÜ`&ö‡™ÝžCDîKâã=>Ñlÿ߯ ¤<…`7G¡Í;dˆÑŒ¬ä; ÞP¨~š$Q  Xw°X‡ZëŠGæé¡ô +ʪLÄT¶‡Î"Û`…¯L:%üW{Ðό^åôôo’Ǜ9{ò»¹µW¿ÖRSÙß?15óíŸÿç×g†ˑt2O\Åcƒé±½Oïî~ø¯ÎTï±k•_u§/|Jö%~2ùÃ5ÃÌ[=Í¢™šËÍ;a‹‰3[gÌ=h{ÖëÕú­GC]¡Öo²gOœ¼x¨¿|rùpÿ—ÏwOh©ÈÎSCi·Û Ï4Bqú'¨¹,»PÇƖœ‰+‹‘¡è`ßی/ˆ5šиmP…ç•0H½QDË:¢j:Ӊj²ÙØ'Uº†ª{q ½úèßôBãA/ès w ;eºžN@…íj848âpĘ4¯=cXan&ËÄ-í& „ug'jA@Ý»w!(ëz’VyíÆvy-Yó¬ƒ@\ûŠ6œH+˜’z†;ÆÒ°(.鈉~E +¹"…eÑK]^êòR—×›ë!*u«Ô­R· +osVh|QÁ Ðøòm¼¦ë¹ž:jSЮ·×‘tÁ[€Œ\wм‚ ö9£-#榁7Û5{t>·˜3­äVs9.ɓ±Ütn]FŽ„o"è¨rvñMOcÅmb"([ÕD0Zå$££5ëؕfI8–eè[­r8dÑçXE²"»8+.‹7E“ˆEJÓ5ÒÒÇôi}V7Íë‹:»¢@,}UßÐMútÏ%P‡ò$”È,·jp3ޥϑÏSaˆ›OK…³9`xÍ ˜}bš--ϐ´ çẾâ•DˆF<Æ4D¬v×±ºÀšŠCÞB¥!x·÷d;A1’‘™ví›õ7IbÊxø_®«5¶më +óReIW"iÊ&)Û"eӖ-v”ãږ+Õ8v›ª‰×DNŒÍ­Û= +ìÇÀ€aÙÖìWþ ‰Š¢Ð ˆC±?kÝ4q± 5Š ؏¹È°­{`‚nÈڦƂ!-Š®QvΡ”¦%¤{¼ßùÎwîëöÇc!kvl××öw—æš»÷ ¦ ÙJw’¬+|úÖßÝ·øEÿÍ_±>ÇÉ +Øì-Llö=êYŽ£Å¦C{‚ìQY^†"þďyEp ô#œ»÷DÖ@$g DvV3BQˆ Äå`\%àG1 Än0^¿€££ £Íø`¼u¾ånWÛîöÆËämö&x€~0{,û„ácàÃ+“HÉ¢"¿ˆ H’jð õíeåÍ •%¸p¦{ 1Öö„„M>¥×9ÿÐC-£Z ß,¥º/1AZ—D|¨ Øفˆ†ÛûÀïÙѨ3˜ Hˆûùî,ðŸüZ..ä ÞåAŽ ïþæve{™ò‘–+˜ ‡­8«NÃYwn8aÛYpD æøøÕÓ»ƒúscA=8Dµï™é pmÿ@b4Ón‘3«v&;ËM®5`+%Aà­+ֈ²h cðÆÞI¬|¹2ú:ç 3á¾[2°-=µ{¢a°ƒ­«FÃX7naccpãgäøÚ;èzw™ +‘¶¦´œ¶@}™­ÖÇ[²âˆv×ë\×£ù™™|¾<ósWµ¹w¯×dÒ}#I– +ŸÆŽr>?ÓÌÞ²Kät¹Îö۔UA¼ý¥æ;>¨e—Z<Ñ( Ò,<¿›ç‘ ÉhÁójžñµŸ¶c؜°6o7i +ïÑ0þNS,œÅ)– æ¯|@>öô¾®…í²õÛ-Xºn˜îeÈ].ü4Í$“¹ø¥+ÅɄ»ôç» nÃ}>ù|ÿº+ÙpsÒ )ÐrÅ ¥;Grv5—™5qKR]KGóf¯=Ê#=›,é'Aàx²|NcÚ&{Ò/çƒcöç'Cž«ëi8ßµ„ÚNB­cY ›É6[±×ívȶqˆ½yû}Èa€½‘wŸÅ3wÜ$%V~XA)V> ìûÊ쵇oÂéƒØ‚øT©~ö‚´Ý{žð¶³¶¤A–T’R]nI lI*}™¤Ü?Ô'[},“ìE•ÃÚù „ H`>˜–…éKϽŸÁ͈[.»“¿]ÿÂÑ]Ùt¯úxÖðz>AÏêλå¦ýñW¯ÿëþÁÁñDäÈБ§ÅýÄÍ‚˜  +BÞ+†^máÇMSø7©´9B@¥’Q -ˆ€,A¼MAÃw‘0•ó,֒D” â¿×ƒàòÚ:Ák뙣é+Ô¤0ÕêŽéé¡zJö_Z&{]S¤¦ŠÂ°ÉéÕ8@òB”'Þ¡·^ŒIpBîŽÛ·Ü­­-”ºwÉwë2°&à\W\9é¹d•Ä.Iað{&úl¬oð³òsêÙ®ç¬s¥—b±’YJ?¦<¦>f}C9¦³ÎŠÑë™K<ýaòrè²üŽøŽ¼£þ§«³¢VŒŠ5mWJsòZìÛrgAÌ+ö=\(M³i%Ò­ÔÙ#Êa»cP9ŽÈה÷•ðƒêÖkÑ×bÿŒ…õhbõ[Ö>ñ~YŠ«²–Hó~9“´¤C¡zÇ¡ð’rX=¬I¦Üߟ±‰-Ú/L„i¦„b¹IøFß㌟߈IfŽsxtKÝpR7ðѯ£h&ã#âqÏ+M¢kHÖ žÙ†D’F'IÓë×™‰j—¦)¦•Î˜H•Ü@LŒfb¨TrƒS¹Bu235+„8ðŽc[)›‰¶ÚpŒ‰)ÆDf ¶¥±Žœ(ÇňAßdïù5ƒÿ.I€|Ó4bñ1~’‹78»Â¯rq•oq‘týœÁŒ´Ub%6‚S(žâ½àmyW¼ð‚ÇNz OôV¦K›ì;/eþ-ríãkËàØ .(k ysÏ™SÆ®JÙÄ-cRÀQÊåSIÏp“ßW.êl 0Z@ÙaÊVPžÂ¾K‘È|ŸµµãǗ…å5¶L—p\8ÉÊ+‚n“‚|ÅÌ þý>oD.‰§â¥8VjIªhPq¨^vA°¶!»Ä€:TÌY&'†s“ÙnIŠD4Êi0âLa²Â0þ聮*Þ-¬¾³Ÿwf‡ÙéG¾Y½~ý‰1Ǽ¯¹w¸w¤ùoÓ{¸éÍ vÇ夝îΫL ŸþxõO³]œ§úEÛ½™¿6ÿ|"[HƇukú½ìÉ敥iƒ9Ž׳ŸÝn¾WD¦Ù +K¦éfO·õ•ò‚ôUŠK,ˆ3q#Î`e6ÒïR†ÁÛŠ£ÐBÂã/ãþ C'ü#‚×RÄ©nh@ +ÇD‚µ3såò]YCN#•”JQ¬i‚a$t9 £ ‚/ˆèá\ïù”𯀏:çbCßÒoè!ÕKenkwif‚é‰/O-èÌ×ô}Uoèë00ÂG3‘ýl4#åS¹DUˤfá•"RL`N‚·–á$[&g&œ-p¶ÂWyƒ¯ó<Ì7zî’-|¯”?*Ëì8C¶#òimÒFÆ sb¾Y©xé¤e¤GT¦†Oÿ¯º8ÝO:$䟝Ô3Ei,ôKáHè­(¢/Q¶¹äãYé*­Z¯µù~ [|ÏxÌ¥Qî®â\{Ô\{¶øY5W¯Ò¸*¥J@©ÖRø´Z{^­_jíÀøÈ7ql-†ËÔ\šîÒt·èDZ¡¨à4¸ÿ£ÇyÅ>\îßõ-Z©_Ä5Š*­¡Òª1Ö°Ç(PnÞ~-XÃÎãpÿ7?ŽCm±Õÿ1`Ö±{ÌÂø¾PPÙó‡ë>Ž)ÔÙÁú±úSõP}Qšße ݏ”ï GPsì0¢-/ƒ°ºµ…W; ÝQ\Ÿ2[P‡ðîR}™²÷òË°<¬„#‡ë‹c×¼JˆWí +#®„0w©Í-Vé®JwÕìã]¿m…ïô!¹8 +ŒÿRo±x´†1kmãCê­Õ–Ž¶G½S*ðæô‡-´çíJIÐûBâ¡ÃG_æn¿-üŸíòmâ<ãø½w—óùGîοÎÎÙ>Ÿç|Iü+—à„5—ʸ¥„˜64­¢±&’  0J¢ªtk×­Ñþ(“VA'mêT$¨BµvQ·U«4D4U“º?ªýQiC%í?•640{Þ×q`Ú,ß{ßûá÷ìïó}>ÏvØr°åïÿãšìƒ[š¯zÈ +÷ÚÖê_ÉÌ"H¼> ¸i´£¥:ÒxMWƒ+ôÝ«ñ~]-@`9ã»uut,îÖÕÀ +#\Mºš_aÚ¯&†uuÖ#‰}™êðê¾m¼Þ_µÊz'OÙR£ûñ“êr9œ6Žm³î(äƒGèSr'cy ÍjË­­ Óûõ#¹%ߏfû—ûé~<'W÷'wïŽVkUz±ºT¥©ªT¥«×ïúäÞêôd}…>5k!¸‚fÎ$Ý RèC ¸÷ys·ufSHrü"ï*)`yàÇ¥6rß ½à¨/žt‰í©D:銅‘ ƅT,AÚj4¡”š20iA½•ÍQö»}¦]”Zµ$Ž%'ðÀG6§mœíÿw>%T›ñt«4qÆèG•]s1¹ÝÑ÷ÆVï`,à`C™ óðnšöìhv—m±®ñ>sowG¡Ò**„s3"òôí1yúùJeßÀ™Æ‰ MŽ&“)ᮡWg{,s§ÓhTöÀ$T¥Ça®`Eºúþ}¡d24¸<ßÕâaE1ÿ'+ћNf'Ë.QàE9-¡JD’:O,‰'~À?àå$¾LVðمó\nÙŸW‚àK+O—©¹8Bn!·ˆèA| €³Þd½‰h$hšœŽ½Í¯Ð©0Ìc#±HgV(¶Q‚-[ +IŠÉ¢M颉—ärPoߖA"ÿÆù‡„ Ø56mã`NÆYŒn_Äd…æýÅ$Oª'Oœ‚'®ÁË4ž’É”Ìã)Y6{©93B&"ä`„<(žÕ[v¡c3ÁgèºÙûJ›TºYssðX˜L˄L1ΘVÖäMœÿy³fN›³æ’ÙÖÍ"‹Ä‹ðiÙä–Í5“^6Ñ4L¬šL„—uU\aDË×u59çuUKDt5aõ$ +™ìp^-l S‰b‰€€ªüìǕ#š,8 6½VÉÁWOžp +8}; +b´•‡ëV&¶žiœÚí'“™´8ŽN¾0÷b#2%G ÓFgЗv*8Ïh0íϙëg"¡]™ $Dç"8×ìé$§F…ŹƒâÀòâI–œÆR¼SJQÍÊHô{ƒ¸«¥S;>ŽÏSðÅ!¬)…õÅù\!8‰àK8‡,«º\Q ‹”",.¨EäKàÆÖvÏ¢ýR~WþúØþûȧvÎówÚiß.ï÷ŸC¯Ù_? Ù¢VÑd£# »‹Qô‘ÿc…¶¢hßZ‡Åºü?RdÑkì4;Ë.±Ë,ÇÞvYpÐr]„gD©=Ò×óFu} +3]e¹soe¹ö؁+.uו(»ëñ“ïS®û« [ôþ*.#“¿¡¦H±”)ޒn…úÕ¡¾ñ@ ¢>ñ¤„4 +§).í}AŠ†d;DADÞvIC!¿3 Qm04Í” „yT‡F&-÷qú8wÚqZ8íy^><æ§êÐAócÙÒ»‚Í?úgß©-‚>}—ˆgÒfo__ Îq~Ÿk*M­=|âæÂÍӇ^øÓ^óð£_|æì·G™Ë¾wù»w/ýà³wN]8óÇÆgoýîëצ¡é¸§1ƼZËPe:¾¡5}ЮZtdñÎÁa)9‚ÞJct/ñ`¯&8s½Úâ5â»Q;;¦Ó𰧼ÞÀ-àGOJè«s¶ qaŠ¸0…@à°@nëÄpIIÎ5vuUúŒ5GÛ²ÖëTñþÝkXˆEÖd‡Ç଎èÖK<Ò«5k‡õ¥"°¦ÁYœ¡P‡‹qâÕààzHj:#j:&˜çZÓ6”ÝbŒK–bÅƳ;I±¦ÔÕZì@öiã¨ô¬òlìhöŒ4§,¨s±ãœòCãMñ åMõØO²Œ_É¿P~~Ǹ.+ø«qÛø·‘Õº¥Žu¾î=ï=ï[í¶íõ¢8/èª-GºÊe¡ ¨F™„¢#üX‰T$h³qB(DE£–]ŽŠ¢%DO£Et1ˆÇO¾H$ÍOÿÖÓÿ•ŸñKxÖ?Ò5²@œØ˜›¯®ß3¦pyÆI„õ¸u}èÖãø.ûØ6Î:ŽßïÎïgûÎw¶s>¿Ü¹~9¿ÅNâ¦é•2_·¾wU†„h3æ%,b¬¬i +lÓ(µ@l«˜h • T"H i-ÑJ3PX:,ê¼±ñGDU‡ê1ª²?V%å÷<¶³UHDºçyîÅÏ=¹ûÞïûùJfכ•tNîK÷eu&'c“ §t0‚y½£=‚ÙXQ|‹Ì4©€°¦µ!ª5R ±2”¿G¸Žö°"¢ð6pO*ÕÝ«CòÆxPùü‹»¾ógþޜÈnþ¶q 6uægG>õwöÎ÷Å2‘7}ŽÞºôdt=–^©ÀËè׿»øêR•Aòõ¡¼. ²rp¾««\ÖH‡Ö0(œŠª¬{’¯ÖãZ­G¤©F"1-HÔ§Q„Õh⥂È)áÈoQt +“EÙùGCÆ1ƒ3rNÅËa±j‘„ÛÆ|û?T*6ÿÐ#ў¿§ÈtYüí!÷17ëÆ ®”ÊM°dÑB‰ƒÒJÈ9M+ä?†IœŸ©ÔZ­úCF­C߄!vH°XKø–Íi`¼©r4/>Ÿ2 }K6ale<|!ÔE°) 7¸MÑ Þ1Žcœ˜Ç`9ÀQÖ +P`iMÓthè3:Ëè"&Ä%ýŠn×'ò?ŠŠk-ãM/ž¦ÊÛÓíz “åL¦Wðq§‘ïÐ8CîÐ:Q/ÝÔÕå¹^HëÖù½Ž˜§ôƺ?¥\1.”báx$-ͺg=§õ“©“i^*úr¥Ý¥Ñêxõ™ü3¥çý¿H­Þà®Ç¼y×`‚Yd AXX€â<³X^Õ +”Dd1šP5DUÇ'GNFÃää:IJ§|¼M0hgOÀ™r¥0È0䡪ߌD”n» Wȃeߔ¤ËÉw“ÿJrÉ.hñSLSŒÀ °ÁŠj¤¬¹ÀUš3`˜2§kütfô_íé}{ÛÓ·i8Z©?°þnêcf¹rþ.àÙ ½ŒçѺHlZ;ÈE¤Ræ´´ú|ü þrÑTlŽ)Œxóv»> bûv»3¦ÃŽˆ^)ënßz¦8Fkz,—×t1àpjd yW ?áDŒqæì1èv’½ð^î;ÎÅwr¶úL3ø©âÁÈ̱sÜÿcßLhF‰ÎÄf×ý05×ïE<.Âabx_IUÒß-NŸ.Ùëcš9=bºs,ÉâÅ1ï1U’$"³Œ‡Jts›^1!Õü:i!ç£&í"f¡`^6SÎ‹Ý¯e³¤È¹¤Î\‚„·ð’YÒ%ò›,AÀË“}x™àKòá}|x nJ€nLñÿýá³£å*ê:Y_¸¯¯S·(E¥UBUUÙ4„ÄHNeg’Ù§Ùþ9]ÿÁ¥Å¯}ö`2ÔçK&c?ylÛ¾/¬þ½¿ÿôsöV¢äåή¾qòË»û7æòå“?=:›ð¨°ã¥ï}ÆÜöèÌ&sßáõ ~kXðî¿ÙͶ‹LVº5,·$¬aq‹(Þ«÷ò†d°Ët(S#“‘›¨áÉÄùhX ÏÂK~#ó®’Ú :πlåJ«Ònv=ìÒ~åÞúéó +Ó6ô‰1¾¯Pœê "„ç‚d4Å/D!ôDvÞÎB)â½ù(Øi8°»ˆÍÙ© ÚqïÓ)ÈJ©ÿá࣠4JÈñØÇþW¼Ò"™påJ½¾$¶Äf †®_kôUƇ Øâ5ÇaœekñÙÀläµÐká…ȍˆs.ÇUõŽúƽã¾ÿ(v‡R … ‡”ˆÊi‚Ñ3À…º«åXÞa²èðåл”±Fßdø¸i•t4Ïr%~.Îƛ͞>$CCFåsò’|Eþ‡ì'b¿<ދ+äkß,Öo#;´±Nlfj+ËÄ:Å6žZ´O†ÒÙàÂ>eþé"c5” +P¦©RâÊRÃÐ7G`÷Õ«Õ\ò¾€‘jl-ï/|äH_Þvqõ/ÛW^»/Ÿ{l²:>É~)~bgöqâŒìÝen…;Åd؁®ªÂ†EÔãêb9¯çÈ®¾ÆCz¢›0—-™K•^¨J1rÔ“›ÔË¢8¸}ž\(¥{ÑÓ¯d¼îWñ’Ÿwºð>O¢§ËÃT®[øF;³£ÃV‘vK׊Ÿä¨}NË5ášrq.¯óŠ?éÃY;Sò]&öí認쩱T9¦J.WV§ÊÓ4˜êY\í-ª=‰ð!9ET{’dd»Ú ±…;´Y"B¬¡)ˆ!¶ˆ£ƒAR…n8gØÖó#Ú&}§¶S·«.y”$Ïäh"c¤\lq&\[u>w-À6Kö0™ ZùüÞÃóI°¿Ÿ9 ÀÌÁe°Á»he¤ˆš–¤‡ä™m`sNæˆèô®ìPtÙ׏ÝËihE(?TCôVë±MV¾Fjhb4&b‚cÄ@TŒÇ0Ɖ›Ñ-0Ô©ƒ4RöÙSÃ="·9‡“]uâž1ÌM +É°føWßïÿú7¶í=\Šì„-cµâWö˜s§VޙÛ ¤¿Þ¸ì¥Ìþ—íj‹ã*Ãsö6—½Ì™½ÍÌ®=;ëݹiwg\ï®ãY­´ƒÚ$5$UÔ@ŠV) +/­-…ªR,›jçYBåJ Ò> ;±ãZm) ¼¤äFi¤„Bi……(D•þ3cÓXûœïœ3÷sÎ÷ýßÿ•±"Ò¶6?5~(D?³/¤Á``ª¡+Á]eYªŽe߃ý$@Q¡„¾@„ [[="‚ °»Wž8¶È°ìH®‹gód}³™˜àçB:òG€ßªßPÉ}®×¾øOû>Ö¹sßñ—•Mû¦ô-9 wk9Þ!QèÛ¹vVÎ*ìWÔtUReµÐa]®“v¥¶Ü)|•™dŸâöKûåÉ æçÌOÙ_Þ(žy‹z“ù%{N>Wx³øs‰]åV¥5ùÂFqsäCé!÷Pú¼Ð8Ã"ò”•±Z>֞P±ы¶ô± {^zPœ‘Ajâïu¢® ZˆÚ’ߨ¯ ¼ùx \ûôž#ð·~ ̀¿¹Ä©ùdÄë“5@¶ +~’p)€Çe\F›‰˜‰cÇ2å\`$2p ؊v9ƒ U®º! ß VîÛ"i¡Z+[ÚÙ°vÖófI ¿®éjet'JN §X>®iA9ðèïá踃Yؒü×ÝèE`K=|}—-zYR¡úe¢¼«KLÄÔJ1>F¶y¯ç8¢‹·oÀoó1άS:DϧˆîIC~Jáא'A˜ –t6B™þÍ_­£:uRCZü¤‰Ìxp÷z½Q.Û BÐJò¬^¿×ÇwúþÃ?ëðgµx!m“M:Ôkç H0ÍPíãö öeûSíSó3í33ANXδýó®K­²m[ß–åR±‚í§ëuÝ՟ϋç¥ó:×öU÷G¨Cè0=ɬ0›‡­EzÏ ?ÒÍEkÞ~¿NNÖ6ðº¶n¾o_Ó®™i™7ìÐ±\Dd5Ú`͘ÕŸÄO +SÑgé£Ò³Öéø^”N˧+‹Ú¢>o‹ ìkâ‚N²ÇÐ+ø!œ€ÕÔ4ÑÀ +, + +V+eE¥¬ºBñ\JáK²¢”€T+Œi@0õ(Å I!ú5¢:Î&z$1Y̝vÅÇ KàÞ²èjr~ïB.ò ”#‡At"=!Ùí£J8Б$š‡0|õ·-ÉÈwÑŧ•,sãJÖpQùÖÎÖ_vþ©íÜžè‚žD”¡R}ûè× ]1Ö´°ˆ+ÙÜö}ôù¸šQBš–<ñèo¡Éíµph²™$ž±HQῂÂL„ïïzƄÎI-=Ò àVèÌÅF‡& ±J5!Ç!*³éW~‚KÄÆ[HïçÐRr)µ$,è ­›ñ›âmãv“åmÓâÕÄ w2þñ=Ô±ùçÇ#v/ÚÃ=aBï™nk´3?‚”Iýùµ–×9*Õ¦:'é¹øžæòsâOè3øŒp^ÚЕT”ǼÀ×K¸$”êg‰N‡ÃçØçǧ:‘]§P…÷~uMù¾ƒ[oI\„²É7(öð°kÛwOЧ×#_â+ÚfP“o:§7Å|ÞhµÚ\<‘h‚ý iYoµ[Ͷ–^Ê;Ú`Kó‰áYyJAŠ£½T™«„*KT‘5Ûv›û–e4§`¶gÛ¨ÒšLÓÕ¶–m·µDÞ0F›‰l³™€•—Ø„Ø449>áèN´è6?„†J°ŽM–¸ ¨lG¨ÑP”a.óÒKy”·µË(µ¢ÊH&ºšÀmO~[þ“|OŽåÐ8Õ¤hôÝå¶m€¬PMÔÜ]¡\ª:¼R¾Ô¬=ì ðv­_›@>p¯¿mÁjúîö‰‘òB½”][HÍD# $¥ÝYGÚÂwûdŽïúvûNF°ßŧ¶ E3¸›ê.¤pwöêUW™«4£Ç€3ý> ÕÓÔ4oŠ§87©É늪’îAû“ÀIRÙ!¡—ôŠ¸'‘Qèô2bªõÒñ-A5NZbE-“'w»·Ê»šÊ“€k™wiBdÞXM¤?âñiWWI`L ׁeôMÂr:!° Ť‹a(¢—v1æ]JÝ˹™@ò¤I(̹èy™œ;Îä\s4ëZP&ï²þÍò®å Prî)ðd‘< +¹ü‚ð…¶|ùGýW}é€/C¾ɋâ>"<{þ…Îäób®Üþ7ûUÛTÅïµÝÞëF¿ö¶ö½®[·vm×ײ­Ý÷R¶É¾Ø,Ȁ9'tñ1>¶¡‹F…@$BPŒøE&\"%ûË@bLä/ &QB01È:Ïë:F$Lˆ‰É;ͯ÷wOï}÷žs_Ï='¤h½^%4%úJYZ¡ä9væLaž+-kIsS¾‡)/q—¬›Œ6UÅWŌú}oD‚Áø·n»gͧ—w,¢À”mµ…Lùë¥L…%[þÐûññэÛ-¬Öµf›—u»u‚cxúîæ +ú¯¤Ç4·)2…Øüdd¢ìTök0âe¼ªlJ!*(Éœ f…² Ê*4” ¡ñÙbB¾!ÿBŸº¢Ëݳ!+)rxÁÌî 1!X(<¸ö(k! ”†ï%=ßwOP]˜ˆ J}URü±©9ºú3اÿ€8}z½©’¤Ë^Š7Ñëe²¥ ³6”¿¢Û›Âò¼Î‰œÄ˂äáÝ·ä‘+™rK™½Ñ2Àè7Š}Òzû@`„ՏŠÃÒNûHà€þ€xÇù·¤cò§øºô§å$²ðûõL"S•ô>J¦÷Î)JR±_/Ѐ€,'{ÙOSü¯ÕsjEÊ48W2Å÷*Ã@»õ¹ªÆR«U•lÁ~HÏ\ÕßÔ³Ïê·éÓkôcu|;ßÃkø1*l õùŠÑɝ'¬óPO€) +Ô؀.ý0ï=ªRå6ÊÔ['»·ONÝî¾M7éTÛ²Xä:êZ§&å™p¢D"|p÷ÝÜÔ*¡eދzîrf¶+¡Až/Oäâ‰r¶¬´<²&*Ù +Ɠ¸tәS™Á`ÞÕËæT._fü>/Æ_+?ÓQÓRQœWåÓç4º—Ä?1æ‰&k˜Þa¯Ã»,bîú,|ÚJÖmy†º»[öîüá,ã⮓ìÙ܅®tS:½½_jbÌ-Ý&Hh¯wð"yYgâœ_P/h²É¿ºj£5×ú’UcgügM¢=ûãG¾a!á¹Ö©îsZ«›3”¿¡b£+?uÆ´ +²-+SHMùµ¿@JK7¤Y$³oq®¿z馮M¬hQ™§,×hLåkƒ¡lÏöèîÞzÌÊî;”0¼0V"ì$\¢b1 Ýè¢@ªàY@/iï hœÁ˜Hoþ°T܃Èü° öc€ƒÆç¼<gÈî> `?àùðwòœŠâ@ ­fPv¨< TkÚt`ñëÀ€†u@ÓÅFË Líxˆ«ikÞzhýçh~Ìô“›>OCôÜ]dÿH%ð<­7Fó^¤õ^¥ýíû8Ðܦ=%/UñŸàŠ +*T¨P¡B… +*T¨P¡B…ŠÿÀ‚"4 +c$B +*šd›–MfK†™eµ‰’=ۑ£è]~9\XT\ +£¬¼¢²ªº¦691²¬¡±éÉåÍ-­mí+::ŸŠ®\õôê®5k×Í·âù‡oêqŠP¼b"Sµp¢5ˆ`º0Š#Nqzš~u‡êрNôÎh§¯Ýÿû‡·“þ}P4óèç„C_r¶†v‚$×’<…˜O99-Oj“œ…’\Cú¡$×?‘ä)Ä/64.mDäèÆÁ؎¶ØpçÖÁÞ-ª#»±­ä—dD±ƒˆaÚè{˜|²•ú½ØB,†~ìÂfê =ò¬Ç=Ž<¦óáùh+tä!Š°Št_ÑYj¨OÎaÓ/œ–˜Ò›mÑÇZÈù÷äïÇTGBoG8å1—8ƒfGò´Øëý?64_ë1ÖþΉ\bô»×•vüعµîœ:hªæ ÔUÎ/ñä¿*ô +endstream endobj 509 0 obj << /N 3 /Alternate /DeviceRGB /Length 2575 /Filter /FlateDecode >> stream +H‰œ–yTSwÇoɞ•°Ãc [€°5la‘QIBHØADED„ª•2ÖmtFOE.®c­Ö}êÒõ0êè8´׎8GNg¦Óïï÷9÷wïïÝß½÷ó '¥ªµÕ0 Ö ÏJŒÅb¤  + 2y­.-;!à’ÆK°ZÜ ü‹ž^i½"LÊÀ0ðÿ‰-×é @8(”µrœ;q®ª7èLöœy¥•&†Qëñq¶4±jž½ç|æ9ÚÄ +V³)gB£0ñiœWו8#©8wÕ©•õ8_Å٥ʨQãüÜ«QÊj@é&»A)/ÇÙgº>'K‚óÈtÕ;\ú” Ó¥$ÕºF½ZUnÀÜå˜(4TŒ%)뫔ƒ0C&¯”阤Z£“i˜¿óœ8¦Úbx‘ƒE¡ÁÁBÑ;…ú¯›¿P¦ÞÎӓ̹žAü om?çW= +€x¯Íú·¶Ò-Œ¯Àòæ[›Ëû0ñ¾¾øÎ}ø¦y)7ta¾¾õõõ>j¥ÜÇTÐ7úŸ¿@ï¼ÏÇtܛò`qÊ2™±Ê€™ê&¯®ª6ê±ZL®Ä„?â_øóyxg)˔z¥ÈçL­UáíÖ*ÔuµSkÿSeØO4?׸¸c¯¯Ø°.òò· åÒR´ ߁Þô-•’2ð5ßáÞüÜÏ ú÷Sá>Ó£V­š‹“då`r£¾n~ÏôY &à+`œ;ÂA4ˆÉ 䀰ÈA9Ð=¨- t°lÃ`;»Á~pŒƒÁ ðGp| ®[`Lƒ‡`<¯ "A ˆ YA+äùCb(Š‡R¡,¨*T2B-Ð +¨ꇆ¡Ðnè÷ÐQètº}MA ï —0Óal»Á¾°ŽSàx ¬‚kà&¸^Á£ð>ø0|>_ƒ'á‡ð,ÂG!"F$H:Rˆ”!z¤éF‘Qd?r 9‹\A&‘GÈ ”ˆrQ ¢áhš‹ÊÑ´íE‡Ñ]èaô4zBgÐ×Á–àE#H ‹*B=¡‹0HØIøˆp†p0MxJ$ùD1„˜D, V›‰½Ä­ÄÄãÄKÄ»ÄY‰dEò"EÒI2’ÔEÚBÚGúŒt™4MzN¦‘Èþär!YKî ’÷?%_&ß#¿¢°(®”0J:EAi¤ôQÆ(Ç()ӔWT6U@ æP+¨íÔ!ê~êêmêæD ¥eÒÔ´å´!ÚïhŸÓ¦h/èº']B/¢éëèҏӿ¢?a0nŒhF!ÃÀXÇØÍ8Åøšñ܌kæc&5S˜µ™˜6»lö˜Iaº2c˜K™MÌAæ!æEæ#…僰d¬VÖë(ëk–Íe‹Øél »—½‡}Ž}ŸCâ¸qâ9 +N'çÎ)Î].ÂuæJ¸rî +î÷ wšGä xR^¯‡÷[ÞoƜchžgÞ`>bþ‰ù$á»ñ¥ü*~ÿ ÿ:ÿ¥…EŒ…ÒbÅ~‹ËÏ,m,£-•–Ý–,¯Y¾´Â¬â­*­6X[ݱF­=­3­ë­·YŸ±~dó ·‘ÛtÛ´¹i ÛzÚfÙ6Û~`{ÁvÖÎÞ.ÑNg·Åî”Ý#{¾}´}…ý€ý§ö¸‘j‡‡ÏþŠ™c1X6„Æfm“Ž;'_9 œr:œ8Ýq¦:‹ËœœO:ϸ8¸¤¹´¸ìu¹éJq»–»nv=ëúÌMà–ï¶ÊmÜí¾ÀR 4 ö +n»3Ü£ÜkÜGݯz=Ä•[=¾ô„=ƒ<Ë=GTB(É/ÙSòƒ,]6*›-•–¾W:#—È7Ë*¢ŠÊe¿ò^YDYÙ}U„j£êAyTù`ù#µD=¬þ¶"©b{ųÊôÊ+¬Ê¯: !kJ4Gµm¥ötµ}uCõ%—®K7YV³©fFŸ¢ßY Õ.©=bàá?SŒîƕƩºÈº‘ºçõyõ‡Ø Ú† žkï5%4ý¦m–7Ÿlqlio™Z³lG+ÔZÚz²Í¹­³mzyâò]íÔöÊö?uøuôw|¿"űN»ÎåwW&®ÜÛe֥ﺱ*|ÕöÕèjõê‰5k¶¬yÝ­èþ¢Ç¯g°ç‡^yïkEk‡Öþ¸®lÝD_p߶õÄõÚõ×7DmØÕÏîoê¿»1mãál {àûMśΠnßLÝlÜ<9”úO¤[þ˜¸™$™™üšhšÕ›B›¯œœ‰œ÷dÒž@ž®ŸŸ‹Ÿú i Ø¡G¡¶¢&¢–££v£æ¤V¤Ç¥8¥©¦¦‹¦ý§n§à¨R¨Ä©7©©ªª««u«é¬\¬Ð­D­¸®-®¡¯¯‹°°u°ê±`±Ö²K²Â³8³®´%´œµµŠ¶¶y¶ð·h·à¸Y¸Ñ¹J¹Âº;ºµ».»§¼!¼›½½¾ +¾„¾ÿ¿z¿õÀpÀìÁgÁãÂ_ÂÛÃXÃÔÄQÄÎÅKÅÈÆFÆÃÇAÇ¿È=ȼÉ:ɹÊ8Ê·Ë6˶Ì5̵Í5͵Î6ζÏ7ϸÐ9кÑ<ѾÒ?ÒÁÓDÓÆÔIÔËÕNÕÑÖUÖØ×\×àØdØèÙlÙñÚvÚûۀÜ܊ÝݖÞÞ¢ß)߯à6à½áDáÌâSâÛãcãëäsäüå„æ æ–çç©è2è¼éFéÐê[êåëpëûì†ííœî(î´ï@ïÌðXðåñrñÿòŒóó§ô4ôÂõPõÞömöû÷Šøø¨ù8ùÇúWúçûwüü˜ý)ýºþKþÜÿmÿÿ ÷„óû +endstream endobj 510 0 obj << /Length 43 >> stream +ýýýþþþûúúʷÛ}zXn_>RM,@O.BfDY‚au¡„–ÖÈÑýþþ +endstream endobj 511 0 obj << /Length 25 >> stream +ýýýÿÿÿãÚàű¾É¶ÂɵÁɵÂîèì +endstream endobj 512 0 obj << /Length 4 >> stream +ýýý +endstream endobj 513 0 obj << /Length 43 >> stream +ýýýþÿÿýüý”x‰G%:cAVÑÁËÿÿÿýþþð½Y6LM+@¨Ÿþþþ +endstream endobj 514 0 obj << /Length 40 >> stream +ýýýÿÿÿìæêeEY];PàÖÜßßߖ––öööÓÆÎQ.C{^püúû +endstream endobj 515 0 obj << /Length 37 >> stream +ýýýÿÿÿàÖÜ]:OjJ]îçìþþþñññÙÍÔS0EmMaôïò +endstream endobj 516 0 obj << /Length 40 >> stream +ýýýÿÿÿüúû{]pS/EØÌÔÏÏϜœœ×××°»J%;•|‹þþþ +endstream endobj 517 0 obj << /Length 52 >> stream +ýýýÿÿÿ×ËÒM*?”{‹þþþÉÉɵµµœœœÄÄÄÔÔÔ¥¥¥÷÷÷üûüvXk^=Qëåé +endstream endobj 518 0 obj << /Length 46 >> stream +ýýýÿÿÿ³ ¬D6­˜¥ýþþþþþ­­­¿¿¿¼¼¼›››ôôô•{‹J&<Í¾Ç +endstream endobj 519 0 obj << /Length 43 >> stream +ýýýþþþÿÿÿ•|‹I$;ȹÂÛÛÛÑÑÑÅÅś››àààýþþ­˜¥E 7 +endstream endobj 520 0 obj << /Length 31 >> stream +ýýýÿÿÿÓÆÎQ.DkK_îçìàÖÜ^;Pa@Uëåé +endstream endobj 521 0 obj << /Length 37 >> stream +ýýýÿÿÿàÖÜa?TK)>­—¥þþþþÿþ‚“G$9uViïéí +endstream endobj 522 0 obj << /Length 37 >> stream +ýýýÿÿÿïéívViF$8ˆj~÷óõéáætThE"7Šmùõ÷ +endstream endobj 523 0 obj << /Length 34 >> stream +ýýýÿÿÿÓÆÎT2GU3HͽÈýþþ¸¤°K(=iH\ãØß +endstream endobj 524 0 obj << /Length 25 >> stream +ýýýÿÿÿÓÆÎQ.DkK_îçìàÖÜ^> stream +ýýýÿÿÿȹÂK'=lL`îçìÔÇÏV4I_=RàÖÜ +endstream endobj 526 0 obj << /Length 25 >> stream +ýýýÿÿÿÓÆÎS0E`=RàÖÜͽÈT1F +endstream endobj 527 0 obj << /Length 16 >> stream +ýýýÿÿÿÎÁÉX6KàØÝ +endstream endobj 528 0 obj << /Length 61 >> stream +ýýýÿÿÿõóômM`×ÌÓðð𤤤©©©“““ŽŽŽ¯¯¯þþþ»»»ŸŸŸ§§§   ¾¾¾·¦°uUiûúû +endstream endobj 529 0 obj << /Length 64 >> stream +ýýýþþþÿÿÿ…j{¤’Â¡¡¡«««‰‰‰©©©öööøøø®®®¥¥¥§§§¨¨¨šššÀÀÀŠq£‘œ +endstream endobj 530 0 obj << /Length 61 >> stream +ýýýÿÿÿÑÅÌkK^õóôñññ™™™£££žžž¨¨¨ùùùþþþÝÝÝ¡¡¡§§§   ÚÚÚãÜábCVëæé +endstream endobj 531 0 obj << /Length 67 >> stream +ýýýþÿÿÿþþ}_q­›¦ÿÿÿþþþ¹¹¹¡¡¡———àààØØ؁ÃÃý½½¢¢¢§§§   ÈÈÈýþþ“|‹š…’ +endstream endobj 532 0 obj << /Length 61 >> stream +ýýýÿÿÿ¤’…j{þþþÒÒÒ¡¡¡ŸŸŸÍÍÍÔÔÔÜÜܱ±±£££§§§¦¦¦¬¬¬øøøøöøoNbÁ±» +endstream endobj 533 0 obj << /Length 73 >> stream +ýýýÿÿÿ­›¦}_qÿþþþÿÿþþþùùù«««¤¤¤ªªª   šššÏÏÏöööŸŸŸ¨¨¨§§§ÐÐÐõóôiI]Ì¾Ç +endstream endobj 534 0 obj << /Length 58 >> stream +ýýýÿÿÿíèëcBVØÍÔïï¢¤¤¤§§§©©©•••ÀÀÀþþþ»»»¡¡¡ôôô¼¬¶rRfúøù +endstream endobj 535 0 obj << /Length 58 >> stream +ýýýþÿþÿÿÿ€dv¨–¢½½½•••´´´¦¦¦§§§ªªª÷÷÷þþþµµµ¡¡¡£££××׊q€š…’ +endstream endobj 536 0 obj << /Length 67 >> stream +ýýýÿÿÿÁ±»oNbøöøÏÏÏ¡¡¡¨¨¨ššš¶¶¶ðððôôôƒƒƒ’’’ªªª§§§   ÈÈÈëæébCVãÜá +endstream endobj 537 0 obj << /Length 64 >> stream +ýýýÿÿÿÝÕÚeEXíèëÞÞތŒŒ§§§¡¡¡›››¯¯¯ùùùþþþøøøØØب¨¨¦¦¦¥¥¥ñññØÍÔóðò +endstream endobj 538 0 obj << /Length 55 >> stream +ýýýÿÿÿøöøoNbÁ±»êêê¡¡¡§§§žžžÊÊÊþþþùùù¯¯¯¥¥¥¢¢¢¼¼¼§•¡†k| +endstream endobj 539 0 obj << /Length 55 >> stream +ýýýýþþÿÿÿ”}‹ÒÒÒ¡¡¡§§§­­­þþþøøø¬¬¬¦¦¦¢¢¢ïïïþÿÿÿþþ}_q­›¦ +endstream endobj 540 0 obj << /Length 61 >> stream +ýýýÿÿÿóðòeEXØÍÔ¿¿¿–––áááÈÈȗ——¶¶¶ÑÑÑ©©©¥¥¥§§§£££ñññÀ°ºxXlûùú +endstream endobj 541 0 obj << /Length 117 /Filter /FlateDecode >> stream +H‰f™ÿýýýÿÿÿãÜàhI\òðñþþþùùù   ²²²úúúªªª‘‘‘¨¨¨¤¤¤¹¹¹¿¿¿•••œœœ©©©§§§¡¡¡›››ÌÌÌßßߞžž¬¬¬ÅÅÅÆÆÆÂÂÂâââ×ÌÓmM`õóô ƒñJù +endstream endobj 542 0 obj << /Length 105 /Filter /FlateDecode >> stream +H‰Z¥ÿýýýÿÿÿøö÷rRf˽Æþþþúúú¦¦¦ÐÐÐûûûÎÎÎÕÕՑ‘‘¨¨¨›››ÇÇÇííퟟŸ™™™¢¢¢˜˜˜©©©§§§¸¸¸½½½———¶¶¶üüü¬š¥‡l} Ž`Bé +endstream endobj 543 0 obj << /Length 76 >> stream +ýýýÿÿÿÀ°ºxXlûùúèèèÜÜÜþþþúúú´´´¥¥¥§§§£££ÙÙÙØØب¨¨žžžááá¿¿¿¡¡¡™™™òðñhI\ãÜà +endstream endobj 544 0 obj << /Length 79 >> stream +ýýýÿÿÿóñójK^ÝÔÙÍÍ͘˜˜ÏÏÏèè褤¤©©©£££“““êêê½½½§§§¨¨¨   ¥¥¥°°°ùùùþþþ»«µ|]pýûü +endstream endobj 545 0 obj << /Length 99 /Filter /FlateDecode >> stream +H‰Á+Å À³öõM¨$/Tn¼„¿+ª +‰%œ€›°»ADb&¤cÛ_ÿ0ózï­5­µs.çB0ÆÌ9k­Þû”’RJ!¥Œ1ZkK)k-"úÿà>¯O€*é>m +endstream endobj 546 0 obj << /Length 79 >> stream +ýýýÿÿÿž‹—•€ææ梢¢þþþüüüººº¤¤¤§§§¦¦¦«««²²²ÎÎΪªª   »»»èè裣£œœœçççþÿÿþýþat¶¤¯ +endstream endobj 547 0 obj << /Length 73 >> stream +ýýýýþþÿÿÿy‡£›öööœœœºººïïï²²²ää䖖–ÄÄÄÎÎÎÖÖÖ¤¤¤§§§   ÉÉɎŽŽ¯¯¯úúúÂÂÂÜÜÜ +endstream endobj 548 0 obj << /Length 76 >> stream +ýýýÿÿÿ¤’…j{þþþòòò‹‹‹“““ÜÜÜ©©©ùùùüüüººº¤¤¤§§§¦¦¦£££¨¨¨ÆÆÆ×××÷÷÷ûùúxXlÀ°º +endstream endobj 549 0 obj << /Length 64 >> stream +ýýýÿÿÿ̾ÇiI]õóôÜÜÜ°°°üüüþþþººº¦¦¦™™™ŽŽŽŸŸŸ¨¨¨§§§ÆÆÆëåéhI\ +endstream endobj 550 0 obj << /Length 79 >> stream +ýýýþÿþÿÿÿ‚ew­š¦¸¸¸™™™ªªª‰‰‰¼¼¼ÜÜܘ˜˜ðððùùù±±±¥¥¥§§§©©©———‘‘‘ŸŸŸ­­­þþþýþþy‡™„‘ +endstream endobj 551 0 obj << /Length 64 >> stream +ýýýÿÿÿ¬š¥‡l}þþþ½½½“““¿¿¿óóóÞÞÞää䛛›ÃÃߟŸ§§§¦¦¦———ðððøö÷rRfË½Æ +endstream endobj 552 0 obj << /Length 64 >> stream +ýýýÿÿÿ×ÌÓmM`õóôþþþùùù°°°¤¤¤¦¦¦öööØØؚššÊÊÊðð𧧧   ÎÎÎãÜàhI\òðñ +endstream endobj 553 0 obj << /Length 67 >> stream +ýýýÿÿÿõóômM`×ÌÓÂÂ’’’¨¨¨¤¤¤ðððÌÌ̛››ØØØêêꧧ§©©©™™™¦¦¦£££¶¥°z[nýûü +endstream endobj 554 0 obj << /Length 61 >> stream +ýýýÿÿÿ®œ§xXlýüýþþþòòòõõõ±±±¥¥¥§§§¦¦¦¤¤¤ææ杝¢¢¢ÖÖÖõóôiI]Ì¾Ç +endstream endobj 555 0 obj << /Length 46 >> stream +ýýýÿÿÿôòôbAVó½êêꗗ—®®®ÐÐÐúúúæææ××פrRfüúû +endstream endobj 556 0 obj << /Length 55 >> stream +ýýýýþþÿÿÿ•€duþÿþþþþûûûÙÙÙÄÄÄÜÜÜÇÇǾ¾¾ÔÔÔù÷økJ^³¢­ +endstream endobj 557 0 obj << /Length 40 >> stream +ýýýÿÿÿ¹¨³dBWöôõÍÍ͜œœºººüüüþþþà×Ý\:OÙÎÕ +endstream endobj 558 0 obj << /Length 40 >> stream +ýýýÿÿÿ©˜£vWkýüýÂÂœœœ¡¡¡‰‰‰ôôôôòôbAVó½ +endstream endobj 559 0 obj << /Length 55 >> stream +ýýýÿÿÿà×Ü]> stream +ýýýþÿÿÿþÿz\nœ‡”ÿÿÿþþþ¼¼¼   ¸¸¸ÙÙÙßßßÞÞÞ§§§ùùùþÿþct›‡“ +endstream endobj 561 0 obj << /Length 37 >> stream +ýýýÿÿÿÙÎÕ\:Oà×ÝãããÖÖ֐ÊÊÊȹÂb@Uïêí +endstream endobj 562 0 obj << /Length 25 >> stream +ýýýÿÿÿàØÝX6KÎÁɹ©³_>Sõóô +endstream endobj 563 0 obj << /Length 28 >> stream +ýýýþÿþÿÿÿ€evw†þþþù÷øiH]¥‘ž +endstream endobj 564 0 obj << /Length 25 >> stream +ýýýÿÿÿœˆ”uViþüýõóô_>S¹©³ +endstream endobj 565 0 obj << /Length 40 >> stream +ýýýÿÿÿýüývWj Œ˜ÚÚÚÑÑÑ···­­­þþþþÿþ€evw† +endstream endobj 566 0 obj << /Length 34 >> stream +ýýýÿÿÿ¹¨³dBWöôõ÷÷÷———ËËËàØÝZ8MÓÇÏ +endstream endobj 567 0 obj << /Length 34 >> stream +ýýýÿÿÿïêî^;Qº©³óó󛛛ëë렌˜vWjýüý +endstream endobj 568 0 obj << /Length 79 >> stream +ýýýÿÿÿÜÓÙnObõòô½½½–––ïïïþþþ÷÷÷åååãã㤤¤˜˜˜¸¸¸šššŽŽŽªªª§§§¥¥¥°°°ùùùãÜàhI\òðñ +endstream endobj 569 0 obj << /Length 61 >> stream +ýýýÿÿÿ÷õöjJ^²¼èè蜜œ¾¾¾ïïï   ©©©¶¶¶ÅÅÅzzz°°°þþþ¥“žctþÿþ +endstream endobj 570 0 obj << /Length 52 >> stream +ýýýÿÿÿš…’Šq€þþþ¶¶¶ÆÆÆ÷÷÷©©©¥¥¥œœœçççÔÔÔöööüúûtTh²¡¬ +endstream endobj 571 0 obj << /Length 73 >> stream +ýýýÿÿÿØÍÔcBVíèëþþþ²²²žžžºººüüüïïï   §§§ªªªŒŒŒ¡¡¡¿¿¿òòò¹¹¹‰‰‰………“““¤¤¤÷÷÷ +endstream endobj 572 0 obj << /Length 52 >> stream +ýýýÿÿÿãÜábCVëæéþþþ»»»¢¢¢§§§óóóää䟟ŸÖÖÖÌ¿ÇeDYôòó +endstream endobj 573 0 obj << /Length 64 >> stream +ýýýÿÿÿûúûuUi·¦°íí훛›   §§§¤¤¤ÛÛÛ÷÷÷©©©¦¦¦¨¨¨¥¥¥žžžÈÈȚ…’Šq€þþþ +endstream endobj 574 0 obj << /Length 64 >> stream +ýýýÿÿÿž‰–†k{þþþ¸¸¸žžžŸŸŸÈÈÈûûû¤¤¤¦¦¦›››‘‘‘   §§§¢¢¢ºººúøùrRf¼¬¶ +endstream endobj 575 0 obj << /Length 55 >> stream +ýýýÿÿÿÒÅÍgF[ôñóþþþúúú¶¶¶“““ÔÔÔûûûçççóó󧧧õõõÞÕÚaATëæê +endstream endobj 576 0 obj << /Length 40 >> stream +ýýýÿÿÿš†’…jzþþþôôô¬¬¬ùùùœœœ¸¸¸ù÷økJ^³¢­ +endstream endobj 577 0 obj << /Length 40 >> stream +ýýýÿÿÿØÎÔ_?RìçêÇÇÇ¡¡¡€€€ðððÒÆÎa@Uíèë +endstream endobj 578 0 obj << /Length 43 >> stream +ýýýÿÿÿ÷õöiH]½­·øøø£££½½½åååöööþþþŸŠ—€duþÿþ +endstream endobj 579 0 obj << /Length 43 >> stream +ýýýÿÿÿöôõfEZ²¼ÁÁÁÏÏÏÖÖÖ   £££ööö¨–¢€dvþÿþ +endstream endobj 580 0 obj << /Length 43 >> stream +ýýýýþþÿÿÿ”}‹‹rþþþÍÍ͜œœÛÛÛ···üüüüúûtTh²¡¬ +endstream endobj 581 0 obj << /Length 34 >> stream +ýýýÿÿÿÒÆÍeDYîéìÆÆƗ——õõõØÎÔ_?Rìçê +endstream endobj 582 0 obj << /Length 111 /Filter /FlateDecode >> stream +H‰`ŸÿýýýÿÿÿŠ–¥‘žÇ¸ÁM*?N-AO.BF#8v†¦– C5þþþ´£®Q-DM,@J)=kJ_èâæ´µ´¥¥¥©ª©‘„ŒÛÏ×µ¤¯G$9iI]÷õö¼­¶êåèrƒ½­· ?6Ä +endstream endobj 583 0 obj << /Length 52 >> stream +ýýýýþþÿÿÿʹÄhF[B4•~Œœˆ”ctþÿþ÷õ÷hG[¸¨²Í¾Ç‚avbtýüý +endstream endobj 584 0 obj << /Length 40 >> stream +ýýýÿÿÿüûü}^q²¼iH]½­·ŸŠ—€duþÿþñìð]:OŸŒ˜ +endstream endobj 585 0 obj << /Length 37 >> stream +ýýýÿÿÿ¼­¶ðíïÕÉÑa@UíèëØÎÔ_?RìçêäÛáðëï +endstream endobj 586 0 obj << /Length 61 >> stream +ýýýÿÿÿéâç€`uL*?L+?cAU†gz÷÷÷ÛÑ×_?RìçêÍ¿È`>SíèìýþþÈ·ÂäÞádvôòó +endstream endobj 587 0 obj << /Length 70 >> stream +ýýýÿÿÿöôõeEYG%9cAVË»ÆÒÃÍȸÂøöø‚”õóôèâæ]> stream +ýýýÿÿÿ˼ŏn‚cBWK*>P.Ca?UÛÑ×ëç馑Ÿ«™¤rQeüúûôòôbAVó½ëæé³¼ýüü¦Œœø÷øèàåöôõþþþ +endstream endobj 589 0 obj << /Length 67 >> stream +ýýýÿÿÿÑÂËôòóøõ÷›‘R0DL+?Q/D¡†—½¬·Ä³¾nNb¯¨ýþþ”}‹‹rþþþòïñ¯»öóõ•yŠ +endstream endobj 590 0 obj << /Length 34 >> stream +ýýýþÿþ÷ôöÏ¿Éÿÿÿš†’Šq€þþþúøúpOc³¢­ +endstream endobj 591 0 obj << /Length 58 >> stream +ýýýÿÿÿž‰–†k{þþþùùù°°°¦¦¦¡¡¡˜˜˜–––   ÏÏÏÁÁÁŸŸŸ²²²øöønMa½¬¶ +endstream endobj 592 0 obj << /Length 61 >> stream +ýýýÿÿÿüúûtTh²¡¬þþþùùù°°°¥¥¥§§§žžžÁÁÁüüüººº¤¤¤¨¨¨···ÚÚښ…’Šq€ +endstream endobj 593 0 obj << /Length 73 >> stream +ýýýÿÿÿãÜábCVëæéÀÀÀššš¨¨¨§§§¤¤¤¸¸¸ûûûþþþúúú²²²¥¥¥òòòÇÇǞžž¡¡¡ÒÒÒ̾ÇiI]õóô +endstream endobj 594 0 obj << /Length 55 >> stream +ýýýÿÿÿØÍÔcBVíèëþþþúúú›››‚‚‚¾¾¾åå墢¢ŸŸŸ×××¼¼¼wwwûûû +endstream endobj 595 0 obj << /Length 25 >> stream +ýýýÿÿÿ÷õöjJ^²¼¢Ž›evþÿþ +endstream endobj 596 0 obj << /Length 25 >> stream +ýýýÿÿÿÒÅÍgF[ôñóÞÕÚaATëæê +endstream endobj 597 0 obj << /Length 37 >> stream +ýýýÿÿÿ÷õöiH]½­·þþþùùù­­­¨¨¨ŸŠ—€duþÿþ +endstream endobj 598 0 obj << /Length 31 >> stream +ýýýÿÿÿš…’Šq€þþþ¼¼¼ÕÕÕúøúpOc³¢­ +endstream endobj 599 0 obj << /Length 55 >> stream +ýýýþþþÿÿÿw†Šn€äÞâ´¢®þÿþ˜€äßâct›‡“ñîï’vˆäÝá³¼ÑÄÍðìï +endstream endobj 600 0 obj << /Length 73 >> stream +ýýýÿÿÿÑÄÌN,AP/C…eyž€“˜ztQg¸£°ýþþþüývWj–€Žþÿÿÿþÿ{^px‡þþþ¶¥°z[nýüýŽv…†l| +endstream endobj 601 0 obj << /Length 58 >> stream +ýýýÿÿÿξÉZ7MN,@¢ˆ™þýþþÿþÎÁÉX6KàØÝÎÀÉZ8MæßäåÞã¾®¸õóô];P± ª +endstream endobj 602 0 obj << /Length 55 >> stream +ýýýÿÿÿéáætThF%9nMaâØßþþþ…k{‹s‚ù÷øiH]¥‘žûûû÷õöÀ°ºS.EÒÅÍ +endstream endobj 603 0 obj << /Length 61 >> stream +ýýýÿÿÿòïñ†gzãÛଡ଼§X6Kôò󺩳^;QïêîÎÁÉU3Hß×ÜØÎÔ_?RìçêȹÃ^> stream +ýýýÿÿÿèàåȵÁôðóðëî[8N§“ þþþx‡{^pÿþÿþÿÿñíðùøù± ª]> stream +ýýýÿÿÿº©³^;QïêîàØÝX6KÎÁÉýþþ‘zˆ„jzŸ‰–³¡¬ +endstream endobj 606 0 obj << /Length 49 >> stream +ýýýÿÿÿ£’œxYlýüýù÷øiH]¥‘žþþþx‡{^pÿþÿþÿÿ÷õ÷hG[¸¨² +endstream endobj 607 0 obj << /Length 55 >> stream +ýýýþÿþþþþœ‚“D6«—¤ÿÿÿàØÝX6KÎÁɹ©³_>SõóôòîðÑÁˎu„lL_ù÷ø +endstream endobj 608 0 obj << /Length 64 >> stream +ýýýÿÿÿüûüz]oH&;K)=eEYöôõ•€ÿþÿþÿÿ÷õ÷fEZ´£®pQd§• ©—¢_=RÚÐÖ£Ž›ýþþ +endstream endobj 609 0 obj << /Length 76 >> stream +ýýýÿÿÿðìïÑÄ͸§²s…¬—¥O-BàØÝõòôa?T¾®¸¤œwXkýüýýþþ£›É¹Ãsƒ}]qíçëöõö«“¢ù÷øþÿÿ +endstream endobj 610 0 obj << /Length 64 >> stream +ýýýÿÿÿƵÀɹÄþÿþýüü„”çáå÷õ÷uViÖËÒ¾®·eDXöôõà×Ý\:OÙÎՁevÎÀÉ»¥³óðò +endstream endobj 611 0 obj << /Length 64 >> stream +ýýýÿÿÿàÖÜb@UD!7Ÿˆ—þþþÙÎÕ\:Oà×Ýó½`>TïêíûúûwWk§• ÕÈÐN+AŽoƒsQfºª´ +endstream endobj 612 0 obj << /Length 46 >> stream +ýýýÿÿÿõóô˜}Žóðò Œ˜vWjýüýïêî^;Qº©³ýþþ¡‹™R0D¥Œœ +endstream endobj 613 0 obj << /Length 43 >> stream +ýýýÿÿÿÝÓÙȸÂõóô_>S¹©³ Œ˜vWjýüý¹¨³iH]À¬¹ôñó +endstream endobj 614 0 obj << /Length 61 >> stream +ýýýÿÿÿìæêÑÁËûúûþþþýüývWj Œ˜þÿþ€evw†íè뻦´þýýúùúqSeF$8[> stream +ýýýþþþ÷õöûûûÿÿÿ¹©³_>SõóôàØÝZ8MÓÇÏÞÖÜ©”¡ÑÀËúùùÒÅÎjE\¹¦² +endstream endobj 616 0 obj << /Length 70 >> stream +ýýýÿÿÿ®œ§xXlýüýÄÄȌŒ•••©©©§§§¦¦¦¬¬¬øøø“““£££ååå¿¿¿   öööõóôiI]Ì¾Ç +endstream endobj 617 0 obj << /Length 46 >> stream +ýýýÿÿÿÀ°ºxXlûùúÍÍ͟ŸŸ§§§£££•••ÒÒÒØØØòðñhI\ãÜà +endstream endobj 618 0 obj << /Length 55 >> stream +ýýýÿÿÿž‹—•€ÆÆƝ§§§£££¦¦¦ôôôàà॥¥¤¤¤ÝÝÝþÿÿþýþat¶¤¯ +endstream endobj 619 0 obj << /Length 64 >> stream +ýýýþÿÿþýþat¶¤¯ÿÿÿ®®®|||………‚‚‚   õõõîîœ¨¨¨§§§›››¦¦¦¥¥¥ààà™„‘ +endstream endobj 620 0 obj << /Length 55 >> stream +ýýýÿÿÿéäçfHZñîðÖÖÖ¢¢¢§§§¨¨¨žžžŠŠŠ¤¤¤£££¸¸¸þþþ×ÌÓmM`õóô +endstream endobj 621 0 obj << /Length 46 >> stream +ýýýÿÿÿ­š¦‚ewþÿþþþþ¼¼¼   §§§¨¨¨———ÂÂÂøö÷rRfË½Æ +endstream endobj 622 0 obj << /Length 52 >> stream +ýýýýþþÿÿÿy‡£›ÛÛÛ¬¬¬²²²¡¡¡£££§§§¨¨¨–––ÐÐÐþþþŠq£‘œ +endstream endobj 623 0 obj << /Length 43 >> stream +ýýýÿÿÿøö÷rRf˽ÆÎÎΠ  §§§¦¦¦ªªª÷÷÷¬š¥‡l}þþþ +endstream endobj 624 0 obj << /Length 64 >> stream +ýýýÿÿÿõòônObÜÓÙþþþøøø®®®¥¥¥§§§¨¨¨œœœÂÂÂÁÁÁ“““¡¡¡———ááừµ|]pýûü +endstream endobj 625 0 obj << /Length 52 >> stream +ýýýÿÿÿÝÔÙjK^óñóÍÍ͟ŸŸ§§§žžžÈÈÈÄÄÄ£££˜˜˜ßßßãÜàhI\òðñ +endstream endobj 626 0 obj << /Length 67 >> stream +ýýýÿÿÿºª´€cuþýþþÿÿâââÒÒÒþþþººº¢¢¢§§§–––ÓÓÓìì죣£¨¨¨ÃÃÃõòônObÜÓÙ +endstream endobj 627 0 obj << /Length 67 >> stream +ýýýÿÿÿŸ˜™ƒÒÒҕ••ššš×××üüü§§§¦¦¦¨¨¨›››ÊÊÊÁÁÁ¢¢¢ÃÃÃþÿÿþýþat¶¤¯ +endstream endobj 628 0 obj << /Length 61 >> stream +ýýýÿÿÿóñòlM`âÛàââ⣣£§§§   ÞÞÞûûû¦¦¦©©©———°°°üüüþþþ¿¯¹}^qüûü +endstream endobj 629 0 obj << /Length 49 >> stream +ýýýÿÿÿÜÓÙnObõòôÊÊʟŸŸ§§§¨¨¨›››ÃÃÃþþþÙÙÙãÜàhI\òðñ +endstream endobj 630 0 obj << /Length 58 >> stream +ýýýÿÿÿ¶¤¯atþýþþÿÿèèèÀÀÀáááêêꤤ¤§§§©©©–––œœœÍÍÍöôõqQeÖËÒ +endstream endobj 631 0 obj << /Length 67 >> stream +ýýýþÿÿþýþ€cuºª´ÿÿÿþþþùùùªªª¤¤¤§§§¡¡¡½½½×××¢¢¢¦¦¦‹‹‹ƒƒƒ˜˜˜ßßߢ›–Ž +endstream endobj 632 0 obj << /Length 49 >> stream +ýýýÿÿÿ™ƒŸ˜ëë뢢¢¥¥¥ñññººº§§§¨¨¨™™™ÍÍÍþÿþ„hyµ¤® +endstream endobj 633 0 obj << /Length 43 >> stream +ýýýÿÿÿ×ÌÓmM`õóôööö§§§¦¦¦¨¨¨———ÍÍÍãÜàhI\òðñ +endstream endobj 634 0 obj << /Length 76 >> stream +ýýýÿÿÿãÜáfGZìçëþþþººº¢¢¢§§§óóóÙÙٞžž   ŸŸŸ¨¨¨¡¡¡ÒÒÒÁÁÁ£££´´´üüü×ÌÓhH\ôñó +endstream endobj 635 0 obj << /Length 70 >> stream +ýýýÿÿÿ­›¦}_qÿþþþÿÿÍÍ͟ŸŸ§§§óóóâââ¡¡¡¥¥¥¯¯¯þþþÜÜܛ››¨¨¨¾¾¾õóôiI]Ì¾Ç +endstream endobj 636 0 obj << /Length 99 /Filter /FlateDecode >> stream +H‰T«ÿýýýþþþÿÿÿ…j{¤’ââ⣣£§§§¨¨¨¡¡¡©©©èèèòòò¥¥¥žžžÖÖÖôôô———›››°°°üüüÑÑѝ„„„€€€ºººŠq£‘œ ‘8<¥ +endstream endobj 637 0 obj << /Length 76 >> stream +ýýýÿÿÿøöøoNbÁ±»ööö§§§¦¦¦óóóþþþ¸¸¸¬¬¬üüüÅÅؘ˜“““µµµ÷÷÷òòòÖÖÖ¢¢¢çç礒…j{ +endstream endobj 638 0 obj << /Length 73 >> stream +ýýýþÿþÿÿÿ€dv¨–¢ØØ؟ŸŸ§§§¨¨¨………‚‚‚ÎÎÎèèè»»»¤¤¤ÝÝÝïïï¡¡¡   þþþŠq€š…’ +endstream endobj 639 0 obj << /Length 73 >> stream +ýýýÿÿÿóðòeEXØÍÔÄÄ🟧§§¨¨¨•••¦¦¦“““¥¥¥¢¢¢ÖÖÖÒÒÒ¡¡¡›››ÀÀÀ¼¬¶rRfúøù +endstream endobj 640 0 obj << /Length 79 >> stream +ýýýÿÿÿš…’“|‹ýþþÕÕ՟ŸŸ§§§£££åååÊÊʲ²²þþþ×××ôôô÷÷÷¥¥¥›››úúúóó󐐐˜˜˜ÐÐÐýüýxXl®œ§ +endstream endobj 641 0 obj << /Length 70 >> stream +ýýýÿÿÿÁ±»oNbøöøøøø¬¬¬¦¦¦§§§¢¢¢ÖÖÖÙÙÙÄÄÄòòò¡¡¡£££êêê÷÷÷þþþëæébCVãÜá +endstream endobj 642 0 obj << /Length 96 /Filter /FlateDecode >> stream +H‰Q®ÿýýýÿÿÿõóômM`×ÌÓþþþùùù¥¥¥£££§§§¨¨¨ŠŠŠƒƒƒ‡‡‡©©©———“““²²²¢¢¢ôôôÁÁÁœœœ   ÝÝݶ¥°z[nýûü šü9è +endstream endobj 643 0 obj << /Length 46 >> stream +ýýýÿÿÿ¤’…j{þþþøøø­­­¥¥¥§§§¨¨¨ÃÃÃøöøoNbÁ±» +endstream endobj 644 0 obj << /Length 40 >> stream +ýýýþþþÿÿÿ‡l}¬š¥ÈÈȞžž§§§¥¥¥òòòýþþy‡™„‘ +endstream endobj 645 0 obj << /Length 40 >> stream +ýýýÿÿÿõóômM`×ÌÓààࢢ¢§§§   ÈÈȶ¥°z[nýûü +endstream endobj 646 0 obj << /Length 43 >> stream +ýýýÿÿÿ̾ÇiI]õóôïï¢§§§¨¨¨ÃÃÃãÜábCVëæé +endstream endobj 647 0 obj << /Length 61 >> stream +ýýýÿÿÿ×ÌÓmM`õóôçç碢¢§§§˜˜˜¥¥¥¿¿¿   ¦¦¦ˆˆˆ£££¨¨¨òòòãÜábCVëæé +endstream endobj 648 0 obj << /Length 61 >> stream +ýýýÿÿÿ§•¡†k|þþþËË˞žž§§§¨¨¨   ‘‘‘ªªªœœœ’’’£££¬¬¬õõõøöøoNbÁ±» +endstream endobj 649 0 obj << /Length 43 >> stream +ýýýÿÿÿóðòeEXØÍÔÔÔÔ¡¡¡§§§¦¦¦ŒŒŒÏÏÏ·¦°uUiûúû +endstream endobj 650 0 obj << /Length 52 >> stream +ýýýþÿÿÿþþ}_q­›¦ÿÿÿþþþ´´´¡¡¡§§§¥¥¥’’’°°°ïïïýþþy‡™„‘ +endstream endobj 651 0 obj << /Length 61 >> stream +ýýýÿÿÿ¹¦²N+@K*>U2HÎÀɧ“ [8NðëîàØÝX6KÎÁÉþþþ†k|§•¡ÒÅÎ[7N¼©µÙÎÕ +endstream endobj 652 0 obj << /Length 132 /Filter /FlateDecode >> stream +H‰uŠÿýýýÿÿÿ¿¯¹Z7LèáæŠq£‘œ˜ƒR.DwXkù÷øþþþûúú¿«¸ôòó·¦°uUiûúû÷ôö¸¡¯™zŠi}ɹكª—£ùøù«“¢ÚÑ×P.C¼¬¶Á±»¢›ïíîdGYòðñòïñ¼ª¶ÑÄÌÀ¯¹ þ R¤ +endstream endobj 653 0 obj << /Length 108 /Filter /FlateDecode >> stream +H‰]¢ÿýýýûûû÷õöÿÿÿùøùhH\’{‰Œuƒz]oÿþÿ¢‘›cAVèàåýþþª•£V5Iíè밝ª«—¤þÿÿþýþ~`r¶¥°æá䛅“ïíîlN`òïñþþþèå矊— ·ãD­ +endstream endobj 654 0 obj << /Length 102 /Filter /FlateDecode >> stream +H‰W¨ÿýýýþþþÿÿÿœ‚’¦ž»«µS0EáÙÞ³¢¬O+AÝÓ٘ØÏÕîèìȵÁÐÄˤþÿÿñíðüûûôñó˜}ŽúùúÞÖÛnObõòôŶ¿zZnûùú 0ÂAœ +endstream endobj 655 0 obj << /Length 132 /Filter /FlateDecode >> stream +H‰uŠÿýýýÿÿÿ¤”žgEZ§Œïêí¬™¥©–¢÷õö_>R¦“Ÿ÷òõýüý·£¯¢šy‡™„‘ùöø®•¥I%;®›§þÿþ‡k|À°º‡j|jK^È·Á‰j~ØÌÔ¬›¦«˜¤êäèbEWñïðþýþŒo¬“£’õóõ “™OŸ +endstream endobj 656 0 obj << /Length 102 /Filter /FlateDecode >> stream +H‰W¨ÿýýýÿÿÿ³¢­pOcúøúýþþ‘zˆ‡n}ÜÎ×tThüúû¾®·eDXöôõþþþ¦ŒœÊ»ÅäÙàxYlÀ°º×ÌÓpNcʻĉp€ Ž™¹¤±^;Q~`sûúû Þé< +endstream endobj 657 0 obj << /Length 111 /Filter /FlateDecode >> stream +H‰`ŸÿýýýÿÿÿãÛá|[o—yŒ€_sI&;š€þþþ£ŒšH%:›€‘åÞãbCVëæéÒÆÎ_?Sòïñýûü‡j|±ª×ÍÓqOdŲ¾tƒ«™¤Åµ¿dBW§ŽžôñóÔÈÐðìï Ü?c +endstream endobj 658 0 obj << /Length 123 /Filter /FlateDecode >> stream +H‰l“ÿýýýÿÿÿêä蝀“äÜáèãç”xŠ©”¡K'=ÕÊÑèàåŒmT1FÏÂÊøöøoNbÁ±»ÙÏÖV4IñìïgG[tSh˹ij«uViÁ­ºôñ󞋗©–¢ÔÈÏZ9MÅ´¿èß垊—‰i}ïéí ßòHO +endstream endobj 659 0 obj << /Length 123 /Filter /FlateDecode >> stream +H‰l“ÿýýýÿÿÿ§“ Y6LéãçùøùhH\’{‰õðókL_fEY–vŠ¼¨´ýþþèáædzÀɶÂȵÁ̺Æúùùþþþïì•öôõá×Þüûû²Ÿ¬çáå³¼eDXÚÏÖW3I‹r‚õóô¿«¸ûúú É­OŸ +endstream endobj 660 0 obj << /Length 102 /Filter /FlateDecode >> stream +H‰W¨ÿýýýÿÿÿðëîZ8M”}‹þþþ¤œY7M³«U2GK)=pNc˺ÅýþþÀ«¸gEZH';dBW˹Ū”¢£ˆ™…fy÷õöø÷øqQeÖËÒïìîhK\ðîï kÍ6ç +endstream endobj 661 0 obj << /Length 111 /Filter /FlateDecode >> stream +H‰`ŸÿýýýÿÿÿäÜá‡g{š|ìæ궣¯P,BÖÊÒþþþ“w‰«”£èáæxXlH&;_=R¿ª·ÿþþ¯—¦Y6LH';‰k~÷óõ¶ ®‹mþýþòðñfHZéäçÑÄÌoOcöôö KÂ?Í +endstream endobj 662 0 obj << /Length 105 /Filter /FlateDecode >> stream +H‰Z¥ÿýýýÿÿÿ®œ§yZmöñô÷ôöúøùiJ]~btòíðäÛáýþþ½ª¶U2GK)=–zŒñëï‡h|G%:cAVÑÁËþþþø÷øÕÆÏÝÕÚjK^óñó·¦°uUiûúû v‰>õ +endstream endobj 663 0 obj << /Length 114 /Filter /FlateDecode >> stream +H‰cœÿýýýþþþÿÿÿœ„“X5KäÛáðëî[8N¨”¡æÝãðêîq„M,@L+?oMcÀ¬¹þýþµž­fDYK*=U2G¢‡˜øõ÷âÜ୛¦À±ºìèëÿþÿ}^q¿¯¹öôõrSgÜÓØ ô‡AÞ +endstream endobj 664 0 obj << /Length 138 /Filter /FlateDecode >> stream +H‰{„ÿýýýÿÿÿðëî[:O‰n»«µS0EáÙÞîè촜«àÖÜþþþûúúʷÛ}zXn_>RM,@O.BP/CiF\…ey§‹×ÉÒýþþ¸¥±Ê¾Æx\môñóà×ݜ€’‚cwnObùøù°¼P-BH%:¾®¸Ê»ÄR/DÚÐÖ ‰iM* +endstream endobj 665 0 obj << /Length 153 /Filter /FlateDecode >> stream +H‰Šuÿýýýÿÿÿá×ÞνÈüûü«—¤A3£Œ›ø÷ødBW¬š¥÷ôöº£±~]qR1EN-AO.BU4HpNcuSh˜yŒ›}š|™{ŽyXlM,@Z8M‹k˺Åþþþóïñq„qƒýüýþÿÿèà屛©~`sþýþòîðbBVG$9¢Š™°Ÿªe@W̽Æ –SÇ +endstream endobj 666 0 obj << /Length 120 /Filter /FlateDecode >> stream +H‰i–ÿýýýÿÿÿôòóY7L§“ ýþþa@UǵÁwUjO+A´£­äÚàƒbwM,@K*>`?Sš|ÝÑÙþþþÖÈѐq…[9NV4I›~ðëïÀ°ºŸ‹—øõ÷üüüˆm~¨” ÛÍÖóïñÐÀÊûûû ÆSDî +endstream endobj 667 0 obj << /Length 129 /Filter /FlateDecode >> stream +H‰rÿýýýÿÿÿõòôhI\†ey½©¶ðìïa@UlJ_¥‹›˜„„iyþþþäÛáŽoƒV4HM,@cBVp„»¤³êäèåÜ⺢±Œl€^=QL+?_> stream +H‰l“ÿýýýþÿþýüü©ŸzYnP-C²Ÿ«ÿÿÿöôõfEZ²¼…j{§–¡÷ôö€^sƶÀª˜¤rQeýûü±š©¹©´ÚÏÖE!7“|Šù÷øpPdÆ·À×ÍÓhF[ÚÎ՞Œ—z]oðë±Šnºª´ Ï1G÷ +endstream endobj 669 0 obj << /Length 25 >> stream +ýýýþþþúøùʸÃçàåÿÿÿÀ¯¹Ã²½ +endstream endobj 670 0 obj << /Length 49 >> stream +ýýýÿÿÿ¸¥±H%:X5KÏÁÊþþþÀ­¹S1FS0F½ª¶Ë¼Æº¥³ýþþÐÄÌ­œ§ +endstream endobj 671 0 obj << /Length 73 >> stream +ýýýÿÿÿÓÈÏY5KÑÄÌõóõ^=Rt…øóö“ÕÉÐþÿÿÿþÿ{^p‡m}¿¯¹‚dwþýý¡†—ÙÍÔØÏՏu…þýþþÿþ +endstream endobj 672 0 obj << /Length 19 >> stream +ýýýÿÿÿÏÁʬ—¥Ä³¾íéì +endstream endobj 673 0 obj << /Type /ExtGState /SA false /SM 0.02 /TR2 /Default >> endobj 674 0 obj << /Length 16 >> stream +ýýýýþþúùúëäéýüý +endstream endobj 675 0 obj << /Length 16 >> stream +ýýýÿÿÿ¾®¸eAWIJ½ +endstream endobj 676 0 obj << /Length 96 /Filter /FlateDecode >> stream +H‰Q®ÿýýýþÿþûúû¬“£×ÊÒÿÿÿȺÃcAW§ŽžóðòÖËÒX7KåÞâöôõÕÇÐýþþ—‚„iyŶÀuUiüûûù÷øaATˆm~îëí|_qöôö ¬< +endstream endobj 677 0 obj << /Length 117 /Filter /FlateDecode >> stream +H‰f™ÿýýýÿÿÿ²¼“{Šïêí_=R¾®¸úøúpOc³¢­± «]8O¹§²tTh²¡¬íçëqQfæßäƒfx±ŸªúùúnNb¯¨ûùúat…fzûøú‹–š‡’õóômM`×ÌÓÛÎ×åÝâ ñõEE +endstream endobj 678 0 obj << /Length 123 /Filter /FlateDecode >> stream +H‰l“ÿýýýÿÿÿ©–¢ž‹—‡l}jJ]ùøùš†’…jzØÍÔkM_©“¡âØޛ‡“x†Á±»Šmÿþÿ‡k|º©³þÿþ}arŒ–Žt„—}ŽÔÉг£­öôõmM`×ÌÓhH\ôñóêãè[9NrTfûùú I"G, +endstream endobj 679 0 obj << /Length 135 /Filter /FlateDecode >> stream +H‰x‡ÿýýýÿÿÿÁ±»oOc³¡­O+AÖËÒÒÆÎa@UíèëõóôlL`Á¯º—{a?Ty‡þþþʹĉg|˜}Žüûüþÿÿ—‚…jz©‘ N)@°ž©º¥²–~Ž‰oöôõmM`×ÌÓÙÎÕ\;Oëæ鼬¶R/EkG]²¼ ³ÿL +endstream endobj 680 0 obj << /Length 120 /Filter /FlateDecode >> stream +H‰i–ÿýýýÿÿÿúøù‚dvÖËќ†“Š•ÞÕÚaATëæêŠq^> stream +ýýýþþþÿÿÿ…j{¤’ëæédEXØÍÕöóõĶ¿fEZöôõª˜¤rQeüúû×ÌÓhH\öôöøö÷sUg£‰šìåêñðñoRdóðò +endstream endobj 682 0 obj << /Length 99 /Filter /FlateDecode >> stream +H‰T«ÿýýýÿÿÿ¬˜¥c?UàÖÝ®œ§xXlÿþÿýüýuUi·¦°ÎÁÉX6KÏÀÊýþþ¾®·eDXöôõêåè_@SæßäþýýyZmº§³äÚàôóódGYïíî ¡<1 +endstream endobj 683 0 obj << /Length 120 /Filter /FlateDecode >> stream +H‰i–ÿýýýÿÿÿÛÐ×~\qßÕ۟‰—¨•¡®œ§xYm÷óö÷õöa?T¦’ŸÁ²»oNbúùúüûüqQd¹¨²€cu•}Œþþþëæé\;OÙÎÕöôö± «‡l}¬š¥õóômM`×ÌÓÕÊÐ~`súøú ^Ik +endstream endobj 684 0 obj << /Length 126 /Filter /FlateDecode >> stream +H‰oÿýýýÿÿÿçàå~^rgEZoOcëåéþþþ‹r›‡“»¦´úùúÚÐ×]> stream +ýýýÿÿÿÏÂÊN+AʼÅÏÂËL'>Á±»þÿÿýüý”x‰G%:cAVÑÁËýþþð½Y6LM*?­—¥þþþàÖݘz}_qù÷ù¤’…j{ +endstream endobj 686 0 obj << /Length 67 >> stream +ýýýÿÿÿØÌÔU2G_=RàÖÜ÷õöûûûñìð^> stream +ýýýÿÿÿÓÆÎS0Eb@UÕÇЬ”£ùøùþÿÿþþþ›„“\:OðëîÖÊÒO+A»«µïêí†g{vWjúùúpPd¸¥±Í½Çüüü +endstream endobj 688 0 obj << /Length 58 >> stream +ýýýÿÿÿÓÆÎU2GP-Bŵ¿áÙÞS1Fµ¢®þþþ›„“\:OðëîÐÂËÇ´ÀÞÕÛaBUæßäïêí +endstream endobj 689 0 obj << /Length 64 >> stream +ýýýÿÿÿñíðcCW];PàÖÜÁ±»J&<˼űžªO+AÖËÒþÿÿ÷õö»¥³îéìÆ´Àüüüĵ¾Y4K¾­¸ +endstream endobj 690 0 obj << /Length 70 >> stream +ýýýÿÿÿôðòÊ·Ãðëîøõ÷|]pH&;xWlŠi}´ ­ýþþ±žªM)?ÑÄÌ·¤°J%;˽ÆÏÃ˪™£þþþöôõæÞã +endstream endobj 691 0 obj << /Length 73 >> stream +ýýýÿÿÿíèì~^qÁ­ºðêîöòõ­“¤”tˆÉ¸ÃýþþãÚàU2Hœ…”þþþþÿÿÿþþ‚fwhH\ôïòÕÊÑ«›¥­—¥ÝÓÙ +endstream endobj 692 0 obj << /Length 58 >> stream +ýýýÿÿÿɺÃY6LÜÒØþÿÿÿþþ‚fwhH\ôïòäÛáX5Kœ„“þþþéå財¬íéìR0E®œ§ +endstream endobj 693 0 obj << /Length 70 >> stream +ýýýÿÿÿöóõ¶Ÿ®¼¦´üûüþþþÑÄÌK(=dCWëåéþÿÿÿþÿ}arrTgðëî\:O›„“®¨sSgüúûúùúı½ +endstream endobj 694 0 obj << /Length 96 /Filter /FlateDecode >> stream +H‰Q®ÿýýýÿÿÿ™„‘š‚‘ýþþþÿþûúú¬”£ñîððëî[8N§“ þþþx‡{^pÿþÿþÿÿ»«µÖÊÑåÝâÑÃÌtUh± ªüûûŵ¿dDXµ¤¯ <=" +endstream endobj 695 0 obj << /Length 70 >> stream +ýýýÿÿÿ´£­I$;°»íéë¾­¸§“ [8NðëîàØÝX6KÎÁÉÍ¿Èñíïöõö™}`@Tèâæýüüš~S/E¯ž© +endstream endobj 696 0 obj << /Length 73 >> stream +ýýýÿÿÿâÚßW6JO-B‘s†Ê¶Â•x‹à×Ýðëî[8N§“ þþþx‡{^pÿþÿþÿÿúøùjK^uVi÷óömM`ˆn~ÑÃÌ +endstream endobj 697 0 obj << /Length 73 >> stream +ýýýýþþÿÿÿžˆ–ÑÅÌúøúsƒìé맓 [8NðëîÕÉÑU2GÎÁÉ´¢­}[qÀ®¹òì𢏛‚fwòîñÒÆÍÐÁÊëåé +endstream endobj 698 0 obj << /Length 79 >> stream +ýýýÿÿÿìæêiI]J)=I'<~`süúû¾­·‡g{£‡™À­¹Ê¼ÅN+AÏÂÊ»«µS0EáÙÞþÿþöôõàÓۈm}žŠ—ÏÂËM)?ŶÀ +endstream endobj 699 0 obj << /Length 76 >> stream +ýýýþÿÿûúû‚“½§µº¢±eCXC 5¬˜¥ÿÿÿæÝãø÷øþþþùøùiI]sƒûùúnNaŒs‚œ‚“T0GÏÂʜ‡”F!8± ª +endstream endobj 700 0 obj << /Length 64 >> stream +ýýýÿÿÿ¶§°ãÜàÙÎÕhH\òðñóïòiH\š‚‘þþþþÿÿÿþÿ|`q°ž©eDYøö÷ÓÇÎ_?SÜÓÙÌ¿Ç +endstream endobj 701 0 obj << /Length 61 >> stream +ýýýÿÿÿÙÍÕË»ÅõñômNatViüûü»«µS0EáÙÞÏÂÊP,B­œ§X6KôòóöôõhG[ª–¢Ä¸À +endstream endobj 702 0 obj << /Length 58 >> stream +ýýýÿÿÿ«—¤B3­˜¦Á®ºÙÌÔþüýz]odCWóîñãÛàT1F™þþþ¼«¶˜íéìȺà +endstream endobj 703 0 obj << /Length 99 /Filter /FlateDecode >> stream +H‰T«ÿýýýÿÿÿñïðmObêåèñíðdCWW5JãÛàÓÆÎQ.DkK_îçìàÖÜ^> stream +H‰`ŸÿýýýÿÿÿÝÔÙjK^óñóþÿÿúùú“åÞâÑÄ̽§µ«‘¡•xŠüûüØÌÔS0FkK_îçìàÖÜ]:OjJ]ûûûº©´W4JèâæõôõdFXêåèÓÈϙƒ‘tThüúû ›zD… +endstream endobj 705 0 obj << /Length 76 >> stream +ýýýÿÿÿßÖÛZ9MôòôW5Jª˜£àÖÜ];PeEYìæêÓÆÎQ-CrSfõñôÎÀÉ[;OÛÏ×ÎÁÉgG\ûûûÒÄÌtTgfEZõóô +endstream endobj 706 0 obj << /Length 102 /Filter /FlateDecode >> stream +H‰W¨ÿýýýþþþÿÿÿ“z‰µ£®ÒÅÍJ'<‡m}úøù€atÐÄËÓÆÎR/DhG[ãØßS0E`=RàÖÜÜÐØÕÈП‰—rSfɸÃóðòŒtƒš…’»¥³øöøþÿÿ $@:â +endstream endobj 707 0 obj << /Length 79 >> stream +ýýýþÿÿÿþÿ~btgG[ôïòÿÿÿþüýwYl}`rïéívVjE#7…gz÷óöéáætTgF#8qƒøõ÷ûùúnOb~bsŒtƒ‰n~þþþ +endstream endobj 708 0 obj << /Length 102 /Filter /FlateDecode >> stream +H‰W¨ÿýýýÿÿÿáÙÞQ.D…”åÞâo‚ìæêá×ÞeCXK(=­—¥þþþþÿÿýüý“w‰F#8z[nðê—_=RîèìþýýtTg ‡—úøùʸÃ÷õ÷þÿþ u]=£ +endstream endobj 709 0 obj << /Length 114 /Filter /FlateDecode >> stream +H‰cœÿýýýÿÿÿçáåwVkÐÂËûùúpQduWiª’¡ÒÅÍôòó[9Nµ¤¯ÓÆÎS0F^;PÚÏÖÈ·ÂR/E`>SàÖÜ°»¿®¹ñìï•y‹eEXÀ«¸úùúþÿþ´£­I#: ‹™ýþþ ¤AÑ +endstream endobj 710 0 obj << /Length 108 /Filter /FlateDecode >> stream +H‰]¢ÿýýýÿÿÿçß䝀’£ˆ™ù÷ø­š¦N*@ÖËÒæÞã÷ôö¯¼ÔÇÏX5KS0FÈ·Âýþþ¸¤°K(=jJ^èà幨³€`tÀ¯ºûúúhH\µ ­þþþÚÐ×O+AÀ±º (§?v +endstream endobj 711 0 obj << /Length 76 >> stream +ýýýÿÿÿ÷õö`?S‡•þþþ̼Ʋ¡«îçìjJ]]:OàÖÜÒÅÍL)?dvýüýôñ󧎝ÔÇϦ‘žbt̽ÇgEZ§Žž÷ôö +endstream endobj 712 0 obj << /Length 76 >> stream +ýýýÿÿÿõóômM`×ÌÓ³ž¬N,AD!6¨” þÿþŠp€R/EÞÓÚ̾ÇK'=¨’ ýþþêåèaBUíèë÷öö`?SȹòŸ¬ÞÖÜ +endstream endobj 713 0 obj << /Length 76 >> stream +ýýýÿÿÿöôõgEZȺÃƶÀpƒ÷òõ§’ „hzþÿþ¼©µI$;ýþþ£ŽœK'=ÑÄÌÖËÒuViýüüß×ÜfGZòðñÙÍÕ˻Š+endstream endobj 714 0 obj << /Length 70 >> stream +ýýýÿÿÿüûüvXjeCX¬”£ÜÔÙ«˜¤ãÛàU2G“zŠþþþuWjdDXóîñþÿÿöôö¿ª·Ê¼Å…hzýüýíéìȺà +endstream endobj 715 0 obj << /Length 73 >> stream +ýýýÿÿÿûùúxXlÀ°ºßÕÛ¼¥´õòôóîñeEYoPcõñôåÝâ];Pbtýüý÷ôömMaÍÀÈtVisTg»¤²Œoù÷ø +endstream endobj 716 0 obj << /Length 64 >> stream +ýýýþþþÿÿÿ–J&<ÒÅÍÀ¯¹ÑÃÌüúû{^pQ.CÓÆÎÁ¯ºF"8•|ŒvWjœˆ•È¹ÃeFYȸÂóïò +endstream endobj 717 0 obj << /Length 96 /Filter /FlateDecode >> stream +H‰Q®ÿýýýÿÿÿõñôŸƒ•“uˆüûüîèìgG[S1E¤‰šª  †—þþþ•|‹J%;°»ýþþ­˜¥E!7·¥°ÐÃËJ&<¼¬¶§• nMaïéíûûû õ{5Ê +endstream endobj 718 0 obj << /Length 64 >> stream +ýýýÿÿÿ¢›w†þþþ×ËÒN+@t„þÿþüûüvXk^=Qëåéþÿÿÿþþ{]p©—¢µ¤¯F#8I&;¾®¸ +endstream endobj 719 0 obj << /Length 96 /Filter /FlateDecode >> stream +H‰Q®ÿýýýÿÿÿôïòvVj¼ªµíçìŒm€nKa¬“£üûüþÿþ·¥°E!7­˜¥ýþþþþþ•{‹J&<;ÇóðòoPdäÝâŠq€zˆüúûšþýþ k¾9˜ +endstream endobj 720 0 obj << /Length 61 >> stream +ýýýþÿþÿÿÿ„hyµ¤®þþþöööåååÐÐВ’’¡¡¡žžž¢¢¢¨¨¨§§§¥¥¥¦¦¦ÖÖ֞Œ— +endstream endobj 721 0 obj << /Length 79 >> stream +ýýýÿÿÿ©–¢ž‹—þþþÿþþ¯—¦Y7LM,?O.BC5¦– H&;z]oÝÔÚS1FM,@N+@̽ǭ§E"7I'> stream +ýýýÿÿÿ©–¢ž‹—ñëï•x‹Q/CN-AO.BC5¦– H&;z]oÎÀÉN+@M,@S1FÜÑØJ'<¾®¸þþþrƒ½­· +endstream endobj 723 0 obj << /Length 76 >> stream +ýýýÿÿÿ©–¢ž‹—ãÙßzYnM+@O.BC5¦– H&;z]oɺÃM*?N-AT3GáÙÞC 6 ™ÜÑØS1FM,@üûü€buÉ»Ä +endstream endobj 724 0 obj << /Length 105 /Filter /FlateDecode >> stream +H‰Z¥ÿýýýÿÿÿ©–¢ž‹—ìæêmMaK*>O.BC5¦– H&;z]oÝÔÚS1FM,@N-AJ'<¾®¸µ¤¯G$9ǸÁM*?L+?oOcž€“atR1Eþþþrƒ½­· RÏ,Á +endstream endobj 725 0 obj << /Length 138 /Filter /FlateDecode >> stream +H‰{„ÿýýýÿÿÿž‹—©–¢þþþúùùϾɵ­™zŽ—yŒvTigEZO.BC5¦– H&;z]oÿþÿôóôZ;ML*?G&:ctþüýǸÁM*?N-Aòðòv†F#8I';{]o§Žž¸¤°P.CM,@Z8M•wŠéáæ’y‰½¬· ¹C  +endstream endobj 726 0 obj << /Length 129 /Filter /FlateDecode >> stream +H‰rÿýýýÿÿÿž‹—©–¢Ç¸ÁM*?N-AO.BC5¦– H&;z]oÿþÿôóôZ;ML*?E"7”~Œþþþòðòýþþš…’D!6M,@N,AÓÆξ­¸xUkµœ¬ÒÁÌ£ˆ™U3IT2G‹l€ÑÁËüüürƒ½­· h¬@… +endstream endobj 727 0 obj << /Length 132 /Filter /FlateDecode >> stream +H‰uŠÿýýýÿÿÿŠ–¥‘žÑÄÌO-BM,@O.BC5¦– H&;z]oÝÔÚS1FE"7­§µ¤¯G$9N-AǸÁM*?M+@T3GáÙÞèàålL`J(=I'> stream +H‰T«ÿýýýÿÿÿª—£™ƒÒÂÌkJ_K*>C5¦– O.BH&;z]oÎÀÉN+@M,@L*?Z;MòðòF#8v†þþþÜÑØS1Fb@UàÖÜúøú~`sÕÊÐ }-« +endstream endobj 729 0 obj << /Length 105 /Filter /FlateDecode >> stream +H‰Z¥ÿýýýÿÿÿÕÊÐ~`súøúØØØÒÓÓÖÔ֑y‰Y8LM,@O.BH&;z]oüûüçàäV6IL+?F#8± «¸¥±K(=N-AM,?[9NŸ‚”êãçðíïoRdñïð ì'3ü +endstream endobj 730 0 obj << /Length 105 /Filter /FlateDecode >> stream +H‰Z¥ÿýýýÿÿÿáÚßtVhöóõÜÜܵµµÎË͛‚’Y7KM,@O.BH&;z]oüûüøöømNaJ(> stream +H‰W¨ÿýýýÿÿÿîëísVhôñóçççÞÞÞÏÏÏáâáÚ×ٙY7KM,@O.BH&;z]oüûüv†F#8K*>aBUõóôþþþ­—¥O-BN-AV4IŠj~ÝÑÙ Ó4i +endstream endobj 732 0 obj << /Length 111 /Filter /FlateDecode >> stream +H‰`ŸÿýýýÿÿÿÕÊÐ~`súøúòòòÊÇɓ}‹X6KM,@O.BH&;z]oüûüǸÁM*?N-AQ/D¡†—øõ÷äÜá_>SK*>D!6š…’ýþþN,AƒbwÒÂÍôñósVhîëí !*8‡ +endstream endobj 733 0 obj << /Length 105 /Filter /FlateDecode >> stream +H‰Z¥ÿýýýÿÿÿ½­·rƒþþþ¹£±R/E{^pã×Þ¶¥¯G$9N-AO.BH&;z]oèâæV6IL+?L*?Z;Mòðò¦– C5F#8v†Žqƒìåéúøú~`sÕÊÐ .®1‹ +endstream endobj 734 0 obj << /Length 105 /Filter /FlateDecode >> stream +H‰Z¥ÿýýýÿÿÿ½­·rƒþþþôðò°–§ƒcwoMbqPdN-AO.BH&;z]oÿþþúøúmNaJ(> stream +H‰`ŸÿýýýÿÿÿɻĀbuüûüùõ÷œ„“U4HM,@O.BH&;z]o­§E"7G$9«˜¤þÿþ‰oF$9F#8v†þþþ÷õöiI]J)=L+?fDYµž­þýþôñósVhîëí 6Î +endstream endobj 736 0 obj << /Length 105 /Filter /FlateDecode >> stream +H‰Z¥ÿýýýÿÿÿ½­·rƒþþþ¹£±Z7ML+?O.BH&;z]oýüý‰oF$9V6Içàä”~ŒE"7F#8v†öôõeEYK)=M,@Z8Mš}êãèôòórTfèãæ 1 +endstream endobj 737 0 obj << /Length 144 /Filter /FlateDecode >> stream +H‰~ÿýýýÿÿÿž‹—©–¢þþþ¿ª·[8MkK_¦‰›Ç³À˹Äþýþ»«µI%;N-AO.BC5¦– H&;z]oÿþþù÷øiI]J)=K)=eEYöôõ¾®¸J'> stream +H‰‡xÿýýýÿÿÿž‹—©–¢µ¤¯G$9N-AO.BK(=³¡­sVgJ)=F#8v†¦– C5þþþŸˆ—H%;L)>lUd§¨¨§§§êêê©©©¦¦¦©«ªŽ‰ïëíU4HqOdrPeb@UoMbkH^¦ßÔÛT2GM,@D 6«›¥z]oH&;¤‘œ»©´ …ECž +endstream endobj 739 0 obj << /Length 165 /Filter /FlateDecode >> stream +H‰–iÿýýýÿÿÿž‹—©–¢µ¤¯G$9N-AO.BL+?\•~Œá×ÝT2GM,@·§±G%9„izÿþÿ¤‘œ»©´ ™ÿQÔ +endstream endobj 740 0 obj << /Length 144 /Filter /FlateDecode >> stream +H‰~ÿýýýÿÿÿž‹—©–¢µ¤¯G$9N-AO.BG&:evýúü|_qH&;F#8v†¦– C5þþþþüýctL+?[9NÛÑ׺¼»¤¤¤§§§©«ªŽ‰ïëíz]oüûüþÿÿþýþs…J(=E"7š…’ãÙßS2FM,@·§±¤‘œ»©´ ƒIâ +endstream endobj 741 0 obj << /Length 150 /Filter /FlateDecode >> stream +H‰‡xÿýýýÿÿÿž‹—©–¢µ¤¯G$9N-AO.BI';ƒgymM`K*>F#8v†¦– C5þþþóîñkK_J(=L*>~lw£¤£ÎÏή®®¥¥¥©«ªŽ‰ïëíJ)=iI]÷õöÀ±ºëæéÖÊÒQ/DM,@¨˜¡z]oH&;G&:ctþüý¤‘œ»©´ û¯H© +endstream endobj 742 0 obj << /Length 64 >> stream +ýýýÿÿÿóðòmObèãæ¹¹¹}}}¦¦¦˜˜˜ŠŠŠ×××ÜÜÜ¢¢¢§§§¨¨¨¡¡¡~~~ºººÉ»Ä€buüûü +endstream endobj 743 0 obj << /Length 123 /Filter /FlateDecode >> stream +H‰l“ÿýýýÿÿÿž‹—©–¢Ç¸ÁM*?N-AO.BF#8v†¦– C5þþþL+?Z8MßÕÛþÿÿ°°°¥¥¥©«ª€ˆµ¤¯G$9J)=iI]÷õöÀ±ºëæéuUiŸ”š|—xŒª ûúûrƒ½­· 1Å? +endstream endobj 744 0 obj << /Length 129 /Filter /FlateDecode >> stream +H‰rÿýýýÿÿÿž‹—©–¢Ç¸ÁM*?N-AO.BT3GF#8v†¦– C5þþþQ0Dszäæå°°°¥¥¥©«ªŽ‰ïëíµ¤¯G$9J)=iI]÷õöÀ±ºëæéF$9sƒÑ¿ÊnNbH&;z]oýüý’y‰½¬· X·@ +endstream endobj 745 0 obj << /Length 123 /Filter /FlateDecode >> stream +H‰l“ÿýýýÿÿÿž‹—©–¢µ¤¯G$9N-AO.B·§±z]oH&;F#8v†¦– C5þþþ¾®¸J'¿­¸üýü¢¢¢§§§©«ªŽ‰ïëíüûü«œ¥íçëT3GM+@·¦°‰oF$9¤‘œ»©´ úó=] +endstream endobj 746 0 obj << /Length 132 /Filter /FlateDecode >> stream +H‰uŠÿýýýÿÿÿž‹—©–¢ÖÉÑfDYL+?O.BF#8¨” ª™£D 6v†¦– C5H&;z]oýüýE"7”~ŒþþþC 6 ™µ¤¯G$9N-AJ)=iI]÷õöþüýctG&:M,@O-BÑÅÍH%:°œ¨¤‘œ»©´ é;N +endstream endobj 747 0 obj << /Length 123 /Filter /FlateDecode >> stream +H‰l“ÿýýýÿÿÿž‹—©–¢þþþÀ«¸gEZL+?O.BM,@Q/DÖÊÒµ¤¯G$9N-AF#8v†¦– C5H&;z]oþýþK(=ó½J)=iI]÷õöS1FÜÑØ­§E"7K)=Šm€üûü¤‘œ»©´ NÌ8r +endstream endobj 748 0 obj << /Length 129 /Filter /FlateDecode >> stream +H‰rÿýýýÿÿÿž‹—©–¢þþþÀ«¸gEZL+?I(aBUõóôv†F#8ǸÁM*?[9N½©¶¤‘œ»©´ î|;& +endstream endobj 749 0 obj << /Length 117 /Filter /FlateDecode >> stream +H‰f™ÿýýýÿÿÿž‹—©–¢µ¤¯G$9N-AO.BI';vXjûùú¦– C5F#8v†H&;z]oüûüL+?X7KâÚßþþþJ)=iI]÷õöM*?ɺÃctG&:J(> stream +H‰oÿýýýÿÿÿž‹—©–¢µ¤¯G$9N-AO.BL+?V6Ièâæ‰oF$9F#8v†¦– C5H&;z]oüûüG%:sƒÜÜܤ¤¤§§§©«ªŽ‰ïëí©™£Z;ML*?¶¦°G&:ctþüý¤‘œ»©´ «!:ó +endstream endobj 751 0 obj << /Length 123 /Filter /FlateDecode >> stream +H‰l“ÿýýýÿÿÿž‹—©–¢µ¤¯G$9N-AO.BH&;z]oýüýv†F#8¦– C5üûüõóôaBUK*>Q0D—y‹ßÑÚÉÉɞŸž§§§©«ªŽ‰ïëí¸¨²Z;ML*?¶¦°E"7”~Œ¤‘œ»©´ éú< +endstream endobj 752 0 obj << /Length 132 /Filter /FlateDecode >> stream +H‰uŠÿýýýÿÿÿž‹—©–¢µ¤¯G$9N-AO.BM,@S1FÜÑئ– C5F#8v†H&;z]oüûü¹©³I%;G%:sƒþþþJ)=iI]÷õöK(=Ŷ¿qSeI'hG[š{_>SL+?O-BÑÄ̤‘œ»©´ 8– +endstream endobj 753 0 obj << /Length 123 /Filter /FlateDecode >> stream +H‰l“ÿýýýÿÿÿž‹—©–¢µ¤¯G$9N-AO.BF#8± «v†¦– C5H&;z]oüûüÑÄÌO-BM,@N,AÀ®¹Ê·ÃsTgI(<þþþJ(> stream +H‰f™ÿýýýÿÿÿîëísVhôñóþþþöööÎÎÎàààÞÞÞßààÚ×٘€U4HM,@O.BH&;z]oüûüâÚßX7KL+?I';vXjûùúÒÂÌkJ_K*>b@U³šªøõ÷ÕÊÑz[nù÷ø YÉAÏ +endstream endobj 755 0 obj << /Length 105 /Filter /FlateDecode >> stream +H‰Z¥ÿýýýÿÿÿ½­·rƒþþþÉÉÉ¿¿¿ŽŽŽÑÑÑ©©©ªªªööö»»»¢¢¢ììì¡¡¡ÌÌ̵µµ£££§§§šššŒŒŒ¨¨¨àà຺º‚‚‚÷õöwXkÛÒØ A# +endstream endobj 756 0 obj << /Length 79 >> stream +ýýýÿÿÿÏÂÊ}^qúùúçççããã²²²£££þþþÄÄꙙïïï«««¦¦¦¨¨¨žžž©©©§§§”””¢¢¢úúúóðòoRdîìí +endstream endobj 757 0 obj << /Length 61 >> stream +ýýýÿÿÿáÚßtVhöóõÞÞÞ   £££éééÓÓӛ››çç縸¸¤¤¤§§§¡¡¡êêêîëísVhôñó +endstream endobj 758 0 obj << /Length 96 /Filter /FlateDecode >> stream +H‰Q®ÿýýýÿÿÿª—£™ƒøøø£££¦¦¦ÊÊÊ¢¢¢¯¯¯ñññ§§§ää䨨¨¹¹¹þþþÖÖ֕••´´´ŸŸŸœœœàààüûü€buÉ»Ä Ɗ;ñ +endstream endobj 759 0 obj << /Length 79 >> stream +ýýýþþþÿÿÿrƒ½­·ãã㛛›œœœ¦¦¦µµµßßߞžž§§§¡¡¡ÓÓÓûûû¬¬¬ÖÖÖ£££©©©“““¨¨¨šššÒÒÒ¡Žšœ‰• +endstream endobj 760 0 obj << /Length 92 /Filter /FlateDecode >> stream +H‰Á± +€ Ðop¯-¡nñK”ÁE\ý"îì=ff‘µÖ¹í> stream +ýýýÿÿÿ ˜¢›ööö§§§¡¡¡³³³šššÓÓÓØØؤ¤¤ÒÒÒ°°°ÐÐÐøøø¬¬¬¦¦¦©©©óóóþþþ‹q¹¨² +endstream endobj 762 0 obj << /Length 61 >> stream +ýýýÿÿÿðíïkN`ÕÕÕÁÁÁ¨¨¨   ËËËÝÝݝ×××ÇÇǞžž§§§¡¡¡ÒÒÒÕÊÑz[nù÷ø +endstream endobj 763 0 obj << /Length 58 >> stream +ýýýÿÿÿº©³†i{þÿþØØØ£££§§§©©©———‚‚‚ŒŒŒ¨¨¨žžžááá÷õöwXkÛÒØ +endstream endobj 764 0 obj << /Length 49 >> stream +ýýýÿÿÿÏÃËxYlù÷øêêê¡¡¡§§§ÆÆƸ¸¸•••ºººþþþòïñlN`ïìí +endstream endobj 765 0 obj << /Length 67 >> stream +ýýýÿÿÿèãæmObóðòóóó£££™™™ÞÞÞðððàà॥¥¦¦¦§§§¨¨¨———ºººüüüþþþâÛßpQdôòó +endstream endobj 766 0 obj << /Length 64 >> stream +ýýýÿÿÿ¥’Ÿ—‚þþþûûû®®®öööÆÆƟŸŸ¨¨¨›››¦¦¦§§§¥¥¥¤¤¤÷÷÷þÿÿþýýƒfxÄ´¾ +endstream endobj 767 0 obj << /Length 67 >> stream +ýýýÿÿÿöóõtVháÚßþþþüüü³³³¶¶¶»»»‘‘‘´´´ÜÜÜ¢¢¢¿¿¿ÒÒÒ§§§±±±¿¯¹‚dwþýþþÿÿ +endstream endobj 768 0 obj << /Length 73 >> stream +ýýýÿÿÿûùú{\oʼŝûûûåå域ŸÅÅÅ©©©¨¨¨ÝÝÝ¥¥¥§§§¢¢¢žžžŠŠŠ÷÷÷¯œ¨”|‹ýþþ +endstream endobj 769 0 obj << /Length 52 >> stream +ýýýÿÿÿŠ–¥‘žçççóó󬬬¦¦¦   °°°¤¤¤§§§¡¡¡ÔÔÔþþþŽu„¯© +endstream endobj 770 0 obj << /Length 46 >> stream +ýýýþþþÿÿÿ‹q¹¨²õõõ···øøøÖÖÖ¤¤¤¢¢¢¾¾¾§§§žŒ— +endstream endobj 771 0 obj << /Length 73 >> stream +ýýýÿÿÿúùú}^qÏÂÊÊÊÊ£££©©©¥¥¥¬¬¬øøø±±±¢¢¢ëëëüüü···µµµ¨¨¨§§§¦¦¦¯œ¨”|‹ýþþ +endstream endobj 772 0 obj << /Length 117 /Filter /FlateDecode >> stream +H‰f™ÿýýýþþþÿÿÿrƒ½­·ûûû¶¶¶¨¨¨ÉÉÉÇÇÇÞÞÞÄÄÄÜÜÜßßßÕÕÕÖÖÖÑÑÑõõõÅÄÅlUcN,@O.BM+@Z:Nš’—©«ª£££˜˜˜©©©§§§   ÏÏÏ¥‘žŠ– hF| +endstream endobj 773 0 obj << /Length 117 /Filter /FlateDecode >> stream +H‰f™ÿýýýþþþÿÿÿv†´¢­ØØؾ¾¾ÀÀÀÂÂÂÇÇÇ×××ßßßàààËËËðððÎÎ͞žfWaP/CN-AO.BM+@aCU›”˜©ªª§§§¨¨¨¢¢¢mmm›››©©©ÖÖ֞‹—©–¢ ·lC) +endstream endobj 774 0 obj << /Length 111 /Filter /FlateDecode >> stream +H‰`Ÿÿýýýÿÿÿž‹—©–¢úúúïïïææ毯¯ÚÚÚ¶¶¶¨¨¨´´´ÜÜÜüüüþþþðð𥥥ž Ÿ¤˜ …cxN-AO.BeI[Š{…§¨§§§§‘‘‘¤¤¤ÛÛÛýþþ’{Š«˜£ dzCÍ +endstream endobj 775 0 obj << /Length 117 /Filter /FlateDecode >> stream +H‰f™ÿýýýÿÿÿüûü€buÉ»ÄñññÏÏÏßßßÔÔÔÜÜÜÚÚÚÓÓÓàààÈÈȼ¼¼éééÐÐВ’’œœœËË˚‘I&;O.BL*>cGX¤¡£©©©£££˜˜˜§§§ŸŸŸÊÊÊ©–¢ž‹— ¤fFí +endstream endobj 776 0 obj << /Length 126 /Filter /FlateDecode >> stream +H‰oÿýýýÿÿÿóðòoRdîìíþþþöööÎÎÎàààÞÞÞßßßÛÛÛº¹º‹uƒ[9MM,@O.BH&;z]oüûüýþþ¥žG%:N-AS3FiR`lL`¿ª·Ç´ÀƒbwQ0DgEZoƒÐÁËÕÊÐ~`súøú Á&E‡ +endstream endobj 777 0 obj << /Length 141 /Filter /FlateDecode >> stream +H‰~ÿýýýÿÿÿôñósVhîëíþþþöööÎÎÎàààÞÞÞßßßÕÕÕÊËÊÒÏьv…Z8MF$8z]oüûüôïòpPdI(cGX˜˜˜š•™u]l`?S{Zoš|›}˜yŒuThiG\oMbm¨žÇ³ÀéâæɻĀbu pVM® +endstream endobj 778 0 obj << /Length 123 /Filter /FlateDecode >> stream +H‰l“ÿýýýÿÿÿúøú~`sÕÊÐþþþÐÐÐØØØßßßÞÞÞÖÖÖÏÏÏÑÑÑâââÆÆÆäää½½½›››ª«ªž™œƒv~§š£¢ˆ™L*?N-AO.BK)>u_mª««¡¡¡¨¨¨ÃÃù¨²‹q [þI +endstream endobj 779 0 obj << /Length 135 /Filter /FlateDecode >> stream +H‰x‡ÿýýýÿÿÿ÷õöwXkÛÒØþþþôôôÉÉÉàààÞÞÞÒÒÒØØØÛÛÛÑÑÑ×ÔÖ©Ÿ`>SpNcrPe}\pž€“€`tM,@O.BN-AP.B”‰œœ£££¨¨¨©ª©–‘• ‘›Î»ÇɶÂȵÁʸÄôðó½­·rƒ ­OL +endstream endobj 780 0 obj << /Length 120 /Filter /FlateDecode >> stream +H‰i–ÿýýýÿÿÿ¢› ˜þþþøøø¼¼¼äää½½½———ÇÇǧ¥¦‡{‚{ˆ ‚•‡g{gG[bEW[p +endstream endobj 781 0 obj << /Length 73 >> stream +ýýýÿÿÿîìíoRdóðòôôô™™™¢¢¢óóóÃÃښš¹¹¹¨¨¨¡¡¡òòòÅÅŜœœ§§§¦¦¦¤¤¤õõõÜÓØrSgöôõ +endstream endobj 782 0 obj << /Length 76 >> stream +ýýýÿÿÿóðòoRdîìíæææëëë®®®ºººÍÍ͙™™ÃÃ󳳞žžÄÄĨ¨¨§§§£££±±±ûûûþþþÏÂÊ}^qúùú +endstream endobj 783 0 obj << /Length 76 >> stream +ýýýÿÿÿöôõrSgÜÓض¶¶¾¾¾Â¡¡¡ªªª÷÷÷ÔÔÔ   ¬¬¬øøøþþþóóóÀÀÀ¨¨¨§§§ÒÒÒ¾®¸‡k|þÿþ +endstream endobj 784 0 obj << /Length 70 >> stream +ýýýÿÿÿÜÓØrSgöôõóó󜜜ñññþþþûûû···¤¤¤ÃÃÃ¥¥¥¢¢¢ÙÙÙææ槧§£££åååîëísVhôñó +endstream endobj 785 0 obj << /Length 67 >> stream +ýýýÿÿÿ©–¢ž‹—çççÆÆÆÕÕ՗——ÅÅÅþþþ§§§ÈÈÈÍÍ͟ŸŸ¨¨¨åååþÿÿþýýƒfxÄ´¾ +endstream endobj 786 0 obj << /Length 61 >> stream +ýýýÿÿÿ¹¨²‹qþþþêêꞞž»»»õõõ¨¨¨¡¡¡ÔÔÔüüü±±±¢¢¢§§§ÂÂÂúøú~`sÕÊÐ +endstream endobj 787 0 obj << /Length 67 >> stream +ýýýÿÿÿÕÊÐ~`súøúñññÖÖÖþþþøøø­­­¬¬¬ÎÎΣ££¢¢¢×××±±±§§§ŸŸŸÊÊÊóðòoRdîìí +endstream endobj 788 0 obj << /Length 58 >> stream +ýýýÿÿÿ¾®¸‡k|þÿþõõõ¡¡¡»»»óóó¢¢¢ÖÖÖÝÝݧ§§¦¦¦ªªªòòòôòópQdâÛß +endstream endobj 789 0 obj << /Length 111 /Filter /FlateDecode >> stream +H‰`Ÿÿýýýÿÿÿ©–¢ž‹—ǸÁM*?N-AO.BF#8v†¦– C5þþþɼİœ©N+@K)>vYk¢¡¢¨©¨©ª©‘„ŒÛÏ×µ¤¯G$9J)=iI]÷õöÀ±ºëæérƒ½­· 4–6T +endstream endobj 790 0 obj << /Length 105 /Filter /FlateDecode >> stream +H‰Z¥ÿýýýÿÿÿèãæmObóðòÜÜÜ×××ßßßÞÞÞØØØ¿¿¿ÏÏÏ÷÷÷ÐÐл»»àààãØßjI^J)=O.BN-AR1E“ˆª¬«§§§¦¦¦©©©áÚßtVhöóõ .!? +endstream endobj 791 0 obj << /Length 105 /Filter /FlateDecode >> stream +H‰Z¥ÿýýýÿÿÿÏÃËxYlù÷øÛÛÛÖÖÖßßßÞÞÞÓÓÓ»»»ÔÔÔàààÈÈÈáááØØØåÝâdBWK*>O.BL*>dHY¦¥¦¨¨¨§§§   ôôôñïðoRdðíï /I@1 +endstream endobj 792 0 obj << /Length 108 /Filter /FlateDecode >> stream +H‰]¢ÿýýýÿÿÿº©³†i{þÿþþþþÆÆÆ°°°ÈÈÈáááÞÞÞÝÝÝÚÚÚ¶¶¶ØØØâââÃÃÃôïòpPdI(> stream +H‰l“ÿýýýÿÿÿóðòmObèãæþþþüüüÇÇǺººÚÚÚßßßÞÞÞàààÒÒÒ¸¸¸···®®®ÆÆÆõõõííí¾¾¾ðêî~_sK)=O.BN,@]>Qˆ©©©§§§¥¥¥²²²úúúɻĀbuüûü ÷{N¥ +endstream endobj 794 0 obj << /Length 111 /Filter /FlateDecode >> stream +H‰`Ÿÿýýýÿÿÿœ‰•¡Žšììì¾¾¾ÛÛÛßßßÞÞÞ×××ÜÜÜÖÖ֛˜šƒ‹‚‹myw_mxaoybp‹|…Ž€‰˜•¨¨¨©©©———ŽŽŽ§§§ŸŸŸÍÍÍþþþŽu„¯© éA +endstream endobj 795 0 obj << /Length 111 /Filter /FlateDecode >> stream +H‰`Ÿÿýýýþÿþÿÿÿ†i{º©³þþþúúú¾¾¾¹¹¹ªªª¨¨¨áááÞÞÞàààÒÒҙ™™ïïïìììýüý»¥³€_sZ8MM,@O.B_ASpXg€r{¤¢£§§§ÃÃތ— ë¬Bb +endstream endobj 796 0 obj << /Length 114 /Filter /FlateDecode >> stream +H‰cœÿýýýÿÿÿù÷øxYlÏÃËþþþûûûÉÉÉÖÖÖÊÊÊàààÞÞÞÛÛÛÐÐÐúúúÙÙÙåååëë뺤²^;QL+?O.BN-AQ0DkPa‘…Œ¨©¨§§§¤¤¤ºººüüü¯©Žu„ Eç +endstream endobj 797 0 obj << /Length 73 >> stream +ýýýÿÿÿ¥’Ÿ—‚ãããÙÙÙÞÞÞßßßÕÕÕØØØýüýƒfxH';O.BM+@Z> stream +H‰`ŸÿýýýÿÿÿâÛßpQdôòóþþþøøøÊÊÊÔÔÔßßßÞÞÞßàß­š¦cCWM+@O.BC5¦– çàäV6IL+?G&:ctþüýàÖÜb@UK*>Y8Lð¼ýþþèãærTf Æx=< +endstream endobj 799 0 obj << /Length 132 /Filter /FlateDecode >> stream +H‰uŠÿýýýÿÿÿÏÂÊ}^qúùúØØØÚÚÚÞÞÞàà྾¾ÁÁÁâââßß߯œ¨eDXM,@O.BD!6š…’ÖÊÒQ/DN-AN,A‡g{À©¸_sK*>J)=iI]÷õöôïòpPdI(> stream +H‰i–ÿýýýÿÿÿ½­·rƒþþþÞÞÞ×××ßßßÔÔÔÊÊÊÕÕÕÞßÞááᰝ©eDXM+@O.BF#8v†Ç¸ÁM*?N-AM,@V3IÈ·ÂøöømNaJ(<˜K*>cAVÖÉÒ÷õöwXkÛÒØ ±D@ +endstream endobj 801 0 obj << /Length 120 /Filter /FlateDecode >> stream +H‰i–ÿýýýÿÿÿðíïkN`ØØØ®®®¶¶¶¸¸¸«««¦¦¦ßßßÞÞÞßàß­š¦cCWM+@O.BC5¦– õóôaBUK*>F#8± «àÖÜb@UN-AS2F|gtš˜™ôôôÕÊÑz[nù÷ø \À@e +endstream endobj 802 0 obj << /Length 150 /Filter /FlateDecode >> stream +H‰‡xÿýýýÿÿÿŠ–¥‘žàààÏÏÏÞÞÞßßßÝÝÝ£‘vTiqOdrPesQf\;PM,@O.BL)>yerª«ª§¨§§§§¨¨¨£¡¢‘„Œˆw‚ybpt\kcFXbEW_ATiG\Z8MM-@N-AT4Hybq˜•¨©¨¤¤¤µµµúúúþþþŽu„¯© ƎJA +endstream endobj 803 0 obj << /Length 144 /Filter /FlateDecode >> stream +H‰~ÿýýýþþþÿÿÿ‹q¹¨²üüüÑÑѸ¸¸ËËËáááÞÞÞßßßßàß­š¦cCW@2¦•ŸãÛà\:OL*?O.BN-AT4Gw`nkPa`CUkI^uSh–x‹¢†˜Ç³À˹Äôðóþýþs…J(=gJ\–Œ’©ª©§§§ÆÆƞŒ— ‡`NÔ +endstream endobj 804 0 obj << /Length 132 /Filter /FlateDecode >> stream +H‰uŠÿýýýÿÿÿöóõtVháÚßþþþòòò÷÷÷¼¼¼ØØØßßßÞÞÞßàß­š¦cCWM+@O.BC5¦– üûüz]oH&;L*?[> stream +H‰l“ÿýýýÿÿÿûùú{\oʼÅþþþÉÉÉÖÖÖßßßÞÞÞßàß­š¦cCWM+@O.BC5¦– ¤‘œD!7H';yYmçÝãïéívWjJ)=N,@]>Q…s~¥£¤¨¨¨§§§¡¡¡ÒÒÒ¯œ¨”|‹ýþþ ÒBr +endstream endobj 806 0 obj << /Length 96 /Filter /FlateDecode >> stream +H‰Q®ÿýýýÿÿÿ«˜£’{Šýþþóóó¿¿¿ÛÛÛßßßÞÞÞàààÐÐШ¨¨ºººèèèââ❝¦¦¦§§§©©©›››‡‡‡£££ØØØûùú{\oʼÅ i=ì +endstream endobj 807 0 obj << /Length 64 >> stream +ýýýÿÿÿ–Ž¢›¾¾¾|||………„„„¨¨¨¤¤¤ššš§§§£££˜˜˜¦¦¦“““ÅÅÅþþþŽu„¯© +endstream endobj 808 0 obj << /Length 58 >> stream +ýýýþÿÿþýþ€cuºª´ÿÿÿþþþ¹¹¹¡¡¡§§§©©©———ŸŸŸ¨¨¨¦¦¦¤¤¤ðð𢏛–Ž +endstream endobj 809 0 obj << /Length 52 >> stream +ýýýÿÿÿöôõrSgÜÓØççç   §§§©©©•••¢¢¢¨¨¨ÖÖÖºª´€cuþýþþÿÿ +endstream endobj 810 0 obj << /Length 70 >> stream +ýýýÿÿÿ¯©Žu„þþþøøø¬¬¬¥¥¥§§§òòòüüü­­­¤¤¤¨¨¨žžž•••™™™ŸŸŸ¢¢¢¼¼¼ù÷ùwWjʼŠ+endstream endobj 811 0 obj << /Length 79 >> stream +ýýýÿÿÿøö÷sTgÐÄËÛÛۏ•••ØØØþþþúúú©©©£££§§§ªªª‘‘‘–––¨¨¨€€€ššš   ÷÷÷µ¤®„hyþÿþ +endstream endobj 812 0 obj << /Length 76 >> stream +ýýýÿÿÿéäçjL^òïñêê꣣£§§§¦¦¦ŸŸŸðððÃÃé©©™™™‘‘‘¡¡¡¨¨¨¬¬¬ÅÅÅ«««–––ÓÓÓÖËÒqQeöôõ +endstream endobj 813 0 obj << /Length 79 >> stream +ýýýÿÿÿʼÅwWjù÷ùåå圜œ•••¥¥¥¡¡¡ÈÈÈßßߚšš¨¨¨§§§©©©™™™”””   ¤¤¤ºººüüüþþþòïñjL^éäç +endstream endobj 814 0 obj << /Length 55 >> stream +ýýýÿÿÿéäçjL^òïñëë륥¥¦¦¦§§§©©©˜˜˜£££¨¨¨¡¡¡ÁÁÁÜÓØrSgöôõ +endstream endobj 815 0 obj << /Length 120 /Filter /FlateDecode >> stream +H‰i–ÿýýýÿÿÿòïñlN`ïìíþþþÒÒÒÕÕÕºººïïïøøøµµµÀÀÀàààÞÞÞßßßÔÔÔÝÝÝÍÍÍêêêÊÊÊËËˑ‘‘¤¤¤¨¨¨§§§©©©˜˜˜£££   ¿¿¿Ê¼ÅwWjù÷ù ¾Q +endstream endobj 816 0 obj << /Length 117 /Filter /FlateDecode >> stream +H‰f™ÿýýýÿÿÿÜÓØrSgöôõ×××ÑÑÑààุ¸©©©ÉÉÉÐÐÐÞÞÞßßßÖÖÖÕÕÕ÷÷÷ËËË¿¿¿¼¼¼þþþùùùòòò•••¦¦¦§§§˜˜˜£££¨¨¨¬¬¬øøøèãæmObóðò « P– +endstream endobj 817 0 obj << /Length 117 /Filter /FlateDecode >> stream +H‰f™ÿýýýÿÿÿĵ¿~`süûüþþþûûûÅÅÅØØØßßßàààÎÎκººÞÞÞáááÈÈÈ´´´ÙÙÙÐÐÐñññìììââ❝¦¦¦§§§©©©˜˜˜£££¨¨¨   ïïïôòópQdâÛß ë¬Pš +endstream endobj 818 0 obj << /Length 105 /Filter /FlateDecode >> stream +H‰Z¥ÿýýýÿÿÿøö÷sTgÐÄËêêêµµµÀÀÀöööùùù¼¼¼ÛÛÛßßßÞÞÞáááÈÈÈÆÆƟŸŸ»»»ûûûþþþ¦¦¦§§§©©©•••¢¢¢¨¨¨ÍÍÍ´£®Šo€ ëE÷ +endstream endobj 819 0 obj << /Length 76 >> stream +ýýýÿÿÿʼÅwWjù÷ùóóó£££ÍÍÍ×××½½½ñññÅÅźººéé钒’¦¦¦§§§©©©•••¢¢¢¨¨¨÷÷÷òïñjL^éäç +endstream endobj 820 0 obj << /Length 105 /Filter /FlateDecode >> stream +H‰Z¥ÿýýýÿÿÿ¯©Žu„þþþóóóÇÇÇÐÐв²²µµµÊÊÊÞÞÞ°°°ÙÙÙßßßËËËÑÑѶ¶¶õõõ¤¤¤¦¦¦§§§¨¨¨£££‹‹‹âââù÷ùwWjʼÅ §ÁD' +endstream endobj 821 0 obj << /Length 96 /Filter /FlateDecode >> stream +H‰Q®ÿýýýþÿþÿÿÿ„hyµ¤®éééàààþþþûûûªªªÐÐÐÞÞÞßßßÚÚÚ¬¬¬­­­äääÅÅŕ••¨¨¨§§§©©©˜˜˜£££¢¢¢žŒ— —­=± +endstream endobj 822 0 obj << /Length 73 >> stream +ýýýÿÿÿ ˜¢›ÜÜÜÉÉÉàààÞÞÞßßßØØØÅÅÅÝÝÝþþþøøø®®®¥¥¥§§§¨¨¨›››   ¡¡¡¿¿¿Šo€´£® +endstream endobj 823 0 obj << /Length 126 /Filter /FlateDecode >> stream +H‰oÿýýýÿÿÿª—£™ƒôôôÃÃÃÍÍÍÆÆƯ¯¯ÖÖÖßßßÞÞÞââⲞ«eDXM+?O.BF#8v†Ç¸ÁM*?N-AJ'<¾®¸þþþ”~ŒE"7H&;z]oüûüèáæZ9ML+?O-B­—¥€buÉ»Ä ó A“ +endstream endobj 824 0 obj << /Length 135 /Filter /FlateDecode >> stream +H‰x‡ÿýýýÿÿÿîëísVhôñóÜÑØS1FM,@O.BJ)=iI]É»ÄM*?N-AF#8v†¦– C5þþþÙÍÕË»ÅûûûÑÂÌÇ´ÀɶÂ˸ÄÁ¬¹oOc÷õöµ¤¯G$9L*?Z;MòðòǸÁH&;~`ròîð[=O¶¦° î¸F² +endstream endobj 825 0 obj << /Length 135 /Filter /FlateDecode >> stream +H‰x‡ÿýýýÿÿÿáÚßtVhöóõÜÑØS1FM,@O.BJ)=iJ]ÿþÿ Œ™E"7F#8v†¦– C5þþþÙÍÕË»ÅȹÂP-BG$9«˜¤µ¤¯N-AL*?Z;MòðòÖÊÒQ/DG&:‚fxóðò[=O²¡¬îëísVhôñó 7 Cg +endstream endobj 826 0 obj << /Length 135 /Filter /FlateDecode >> stream +H‰x‡ÿýýýÿÿÿÕÊÐ~`súøúÜÑØS1FM,@O.BK*>cDWñíðtVhI'cCWðë¯G$9N-AL*?Z;Mòðò“{ŠòíñY9L§—¡ðíïoRdñïð ä>B\ +endstream endobj 827 0 obj << /Length 138 /Filter /FlateDecode >> stream +H‰{„ÿýýýÿÿÿîìíoRdóðòÜÑØS1FM,@O.BJ)=iI]ûùúðìï[P¿¯¹J'<ÕÊÑz[nù÷ø =ÙA} +endstream endobj 828 0 obj << /Length 120 /Filter /FlateDecode >> stream +H‰i–ÿýýýÿÿÿ÷õöwXkÛÒØÜÑØS1FM,@O.BJ)=iI]ÑÄÌO-BF#8v†¦– C5ǸÁM*?N-AL*?Z;MòðòëåéeEYK)=µ¤¯G$9\>PíèëlM`¶¦°½­·rƒþþþ µ³7| +endstream endobj 829 0 obj << /Length 126 /Filter /FlateDecode >> stream +H‰oÿýýýÿÿÿôñósVhîëíÜÑØS1FM,@O.BJ)=iI]÷õö­§E"7F#8v†¦– C5ǸÁM*?N-AL*?Z;Mòðò÷òõyZmH';µ¤¯G$9\>PíèëlM`ô¾K(=ɻĀbuüûü ^ã;% +endstream endobj 830 0 obj << /Length 129 /Filter /FlateDecode >> stream +H‰rÿýýýÿÿÿóðòoRdîìíÜÑØS1FM,@O.BJ)=iI]ù÷øctG&:F#8v†¦– C5ǸÁM*?N-AL*?Z;Môòó‘v‡H&;µ¤¯G$9òðòK*>dEXíéìgH\K)=ȹÂÕÊÐ~`súøú ½Ú;º +endstream endobj 831 0 obj << /Length 159 /Filter /FlateDecode >> stream +H‰oÿýýýÿÿÿÕÊÐ~`súøúǸÁM*?N-AO.BL*?^@RÜÔÙY9ML+?F#8v†¦– C5þþþË»ÅÙÍÕôïòpPdI(aBUõóôõñóʸħŒ‘r…uShcBVE"7š…’ãÙßS2FM,@•~Œ›†“D!6ôñósVhîëí v³M« +endstream endobj 832 0 obj << /Length 105 /Filter /FlateDecode >> stream +H‰Z¥ÿýýýÿÿÿ©–¢ž‹—ǸÁM*?N-AO.BF#8v†¦– C5þþþÀ±ºëæéM,@V5Iš”˜“ˆÛÏ×µ¤¯G$9J)=iI]÷õöË»ÅÙÍÕûùú{\oʼÅ +¶4• +endstream endobj 833 0 obj << /Length 114 /Filter /FlateDecode >> stream +H‰cœÿýýýÿÿÿ©–¢ž‹—ǸÁM*?N-AO.BF#8v†¦– C5þþþÀ±ºïìîìæëa@UK*>O-BL*?ƒt}­°®‘„ŒÛÏ×µ¤¯G$9J)=iI]÷õö¾®¸åÞãrƒ½­· îP7È +endstream endobj 834 0 obj << /Length 111 /Filter /FlateDecode >> stream +H‰`Ÿÿýýýÿÿÿ©–¢ž‹—ǸÁM*?N-AO.BF#8v†¦– C5þþþ½®¸íèëv†G%:L)>r[j©©©©«ª‘„ŒÛÏ×µ¤¯G$9J)=iI]÷õöÀ±ºëæérƒ½­· JÐ6 +endstream endobj 835 0 obj << /Length 117 /Filter /FlateDecode >> stream +H‰f™ÿýýýÿÿÿ«˜£’{ŠÇ¸ÁM*?N-AO.BF#8v†¦– C5þþþÀ±ºëæé—}H%:L*>eJ[ˆÜÑص¤¯G$9J)=iI]÷õöË»ÅÙÍÕÖÊÒQ/DM,@úøú~`sÕÊÐ u½9. +endstream endobj 836 0 obj << /Length 147 /Filter /FlateDecode >> stream +H‰„{ÿýýýÿÿÿɻĀbuüûüǸÁM*?N-AO.BL*?dGY«˜¤J(=F#8v†¦– C5þþþË»ÅÙÍÕþÿþsƒG%:µ¤¯G$9M,@a?TtRgrPeqOdnLasQesQf\;PD 6¯ ©çßäS1F§—¡‰oF$9ôñósVhîëí FC¾ +endstream endobj 837 0 obj << /Length 129 /Filter /FlateDecode >> stream +H‰rÿýýýÿÿÿ½­·rƒÇ¸ÁM*?N-AO.BM,@_@S…jzI';F#8v†¦– C5þþþË»ÅÙÍÕ´ ­I&a@Uêã赤¯G$9J)=iI]÷õöÜÑØS1FuViŸ”cBVL+?ôòórTfèãæ OG; +endstream endobj 838 0 obj << /Length 117 /Filter /FlateDecode >> stream +H‰f™ÿýýýÿÿÿ½­·rƒÇ¸ÁM*?N-AO.BF#8v†¦– C5þþþ¾®¸åÞãóîñkK_J(=M+@bCVÞÕÛµ¤¯G$9J)=iI]÷õöË»ÅÙÍÕÜÑØS1FM,@úøú~`sÕÊÐ ¯ø: + +endstream endobj 839 0 obj << /Length 132 /Filter /FlateDecode >> stream +H‰uŠÿýýýÿÿÿ½­·rƒÇ¸ÁM*?N-AO.BT2G^=QM,@F#8v†¦– C5þþþË»ÅÙÍÕ×ËÓU3GM+@K(=󽵤¯G$9J)=iI]÷õöÐÁÊ̽ÇÜÑØS1FF$9Œr‚ϽÉèáæúøú~`sÕÊÐ ^@Ó +endstream endobj 840 0 obj << /Length 123 /Filter /FlateDecode >> stream +H‰l“ÿýýýÿÿÿúøú~`sÕÊÐÜÑØS1FM,@O.BJ)=iI]÷õöF#8v†¦– C5ǸÁM*?N-AL*?Z;Mòðò¾®¸J'<ó½K(=\=PïëîtViI'<w†›†“D!6´£®Šo€þþþ “Ý8] +endstream endobj 841 0 obj << /Length 70 >> stream +ýýýÿÿÿóðòoRdîìíôñó–~Y7KM,@O.BF#8v†µ¤¯G$9N-AS1FÜÑØJ)=jI^ãØßÏÂÊ}^qúùú +endstream endobj 842 0 obj << /Length 102 /Filter /FlateDecode >> stream +H‰W¨ÿýýýÿÿÿîìíoRdóðò÷ôö¨žZ8MM,?O.BF#8v†µ¤¯G$9N-AM,@S1FÜÑؾ®¸J'<þüýctG&:L+?\:OÙÍÕÜÓØrSgöôõ «¾/É +endstream endobj 843 0 obj << /Length 117 /Filter /FlateDecode >> stream +H‰f™ÿýýýÿÿÿÜÓØrSgöôõ÷ôö¨žZ8MM,?O.BF#8v†µ¤¯G$9N-AM,@S1FÜÑØǸÁM*?üûüz]oH&;Q0DŒmŸ”_=RL+?I';vXjûùúîëísVhôñó iZ6< +endstream endobj 844 0 obj << /Length 108 /Filter /FlateDecode >> stream +H‰]¢ÿýýýÿÿÿöôõrSgÜÓØþþþùùùÉÊÉáÞૐ¡Z8MM,?O.BF#8v†µ¤¯G$9N-AM,@S1FÜÑئ– C5”~ŒE"7J)=€auöñô¾®¸‡k|þÿþ »®5R +endstream endobj 845 0 obj << /Length 123 /Filter /FlateDecode >> stream +H‰l“ÿýýýÿÿÿ ˜¢›ÆÆÆÊÊÊÜÜÜ×××ßßßÞÞÞâã㸩³eCXM+?O.BF#8v†µ¤¯G$9N-AM,@S1FÜÑئ– C5H&;z]oüûü̽ÇN+@J(=…gz÷óöþþþ‹q¹¨² s.?1 +endstream endobj 846 0 obj << /Length 120 /Filter /FlateDecode >> stream +H‰i–ÿýýýýþþÿÿÿ’{Š«˜£ÚÚÚÖÖÖßßßÞÞÞÜÛÜ´¤®¨“ qƒ\;OM,@O.BF#8v†µ¤¯G$9N-AS1FÜÑØ ™C 6H&;z]oüûü¹©³I%;K*>dBXÜÐמ‹—©–¢ ×;¼ +endstream endobj 847 0 obj << /Length 117 /Filter /FlateDecode >> stream +H‰f™ÿýýýÿÿÿúùú}^qÏÂÊÜÜÜÀÀÀ§’Ÿ\;OL+?F#8v†O.Bµ¤¯G$9N-AM,@S1FÜÑØýþþš…’D!6G%9„izÿþÿþÿÿ¦– C5L*?ƒ“þþþþÿþ¯œ¨”|‹ Ê:Ó +endstream endobj 848 0 obj << /Length 120 /Filter /FlateDecode >> stream +H‰i–ÿýýýþþþÿÿÿrƒ½­·ÐÐÐ¥¥¥ÂÂÂàààßßߤœX7KgF[¤ˆšÏ¼È‡l}G%:O.BF#8v†µ¤¯G$9N-AM,@S1FÜÑØH&;z]oüûü± «U3H½ª¶ýþþ¡Žšœ‰• £Ä<ö +endstream endobj 849 0 obj << /Length 126 /Filter /FlateDecode >> stream +H‰oÿýýýÿÿÿÕÊÐ~`súøú­§E"7O.BF#8v†¾®¸J'> stream +H‰l“ÿýýýþþþÿÿÿŽu„¯©ÜÑØS1FM,@O.BJ)=iI]÷õöçàäV6IL+?F#8v†¦– C5L*?Z;Mòðòª™£D 6N-AG$9µ¤¯I'> stream +H‰cœÿýýýþþþÿÿÿrƒ½­·ÜÑØS1FM,@O.BJ)=iI]÷õöµ¤¯G$9N-AF#8v†¦– C5ÖÊÒQ/DL*?Z;Mòðòþÿþ‰oF$9kM_ñíðN+@̽ǥ‘žŠ– Ô­56 +endstream endobj 852 0 obj << /Length 138 /Filter /FlateDecode >> stream +H‰{„ÿýýýÿÿÿüûü~`sĵ¿ÜÑØS1FM,@O.BJ)=iI]÷õöv†F#8¦– C5ǸÁM*?N-AL*?Z;MòðòöôõeEYK)=G$9µ¤¯¹©³I%;L*>_ASðìïtViI'> stream +H‰~ÿýýýÿÿÿž‹—©–¢íçë‚bvN,@N-AJ)=iI]÷õöúøùqSeI'b@UàÖܒ{Š«˜£ I;>f +endstream endobj 854 0 obj << /Length 117 /Filter /FlateDecode >> stream +H‰f™ÿýýýÿÿÿ¾®¸‡k|þÿþþüýctG&:O.BF#8v†Ç¸ÁM*?N-AM,@S1FÜÑØC5¦– ÷õöiI]J)= ™C 6ìåêŠlK)>L+?hF[ʹÄýþþôòópQdâÛß „è8 +endstream endobj 855 0 obj << /Length 123 /Filter /FlateDecode >> stream +H‰l“ÿýýýÿÿÿ¹¨²‹qþþþîéì[ +endstream endobj 856 0 obj << /Length 126 /Filter /FlateDecode >> stream +H‰oÿýýýÿÿÿ¢› ˜äÚàƒbwI';hI\÷õöýþþž‰–E"7O.BF#8v†ÜÑØS1FM,@L*?Z;MòðòǸÁM*?N-A­§µ¤¯G$9C 6¢š„izG%9K*>b@UàÖÜþþþrƒ½­· ~‹:d +endstream endobj 857 0 obj << /Length 120 /Filter /FlateDecode >> stream +H‰i–ÿýýýÿÿÿ©–¢ž‹—éâçq„oLbrPeqOdpNceCWN-AO.BF#8v†ÜÑØS1FM,@L*?Z;MòðòǸÁM*?C5¦– K)=€atðèí¨–¡D!7qQeíçëüûü~`sĵ¿ [°6€ +endstream endobj 858 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 281 0 R /Length 15 /Filter /FlateDecode >> stream +H‰b`V ÀÏ +endstream endobj 859 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 287 0 R /Length 34 /Filter /FlateDecode >> stream +H‰b` !`dbfaecç€N.nF^ZZÈ`;֕ +endstream endobj 860 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 290 0 R /Length 28 /Filter /FlateDecode >> stream +H‰b` 9`dbfaaecg¤½U !" +endstream endobj 861 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 325 0 R /Length 44 /Filter /FlateDecode >> stream +H‰b` `dbfaecçàäâæá>~Av!ašÙÉ`v¹- +endstream endobj 862 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 322 0 R /Length 40 /Filter /FlateDecode >> stream +H‰b`  `dbfaecçàäbDˆqóðòñó "‰QGW¶ +endstream endobj 863 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 332 0 R /Length 37 /Filter /FlateDecode >> stream +H‰b` `dbfaecç`Ĕáäâæáåãǔ¡ +00| +endstream endobj 864 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 329 0 R /Length 39 /Filter /FlateDecode >> stream +H‰b` >`dbfaecçàÀ*ËÁÀÉÅÍÃËÇH› 0{ +endstream endobj 865 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 310 0 R /Length 36 /Filter /FlateDecode >> stream +H‰b` 6`dbfaecg§‚ƒ“‹›‡‰—êv3%Ùc +endstream endobj 866 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 317 0 R /Length 37 /Filter /FlateDecode >> stream +H‰b` 2`dbfaecdÇ«ˆƒ“‹›‡—‘Ú–3(¬l +endstream endobj 867 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 316 0 R /Length 36 /Filter /FlateDecode >> stream +H‰b` *`dbfaecg"¨‰ƒ“‹›‡°:@€ ÿU +endstream endobj 868 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 244 0 R /Length 36 /Filter /FlateDecode >> stream +H‰b` &`dbfaec'F);'7;/Uíg0'5j +endstream endobj 869 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 242 0 R /Length 34 /Filter /FlateDecode >> stream +H‰b` "`dbfaec$V5;'7±ª‰„F +endstream endobj 870 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 252 0 R /Length 35 /Filter /FlateDecode >> stream +H‰b` `dbfaed#Z=;'7#]À`K +endstream endobj 871 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 248 0 R /Length 34 /Filter /FlateDecode >> stream +H‰b` `dbfae$E#;'IZ€Ó; +endstream endobj 872 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 230 0 R /Length 30 /Filter /FlateDecode >> stream +H‰b` `dbfae$U;éšð€9) +endstream endobj 873 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 237 0 R /Length 32 /Filter /FlateDecode >> stream +H‰b` `dbfae$];'éÚp€1 +endstream endobj 874 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 234 0 R /Length 32 /Filter /FlateDecode >> stream +H‰b` `dbfae$G#;;9±€T- +endstream endobj 875 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 270 0 R /Length 32 /Filter /FlateDecode >> stream +H‰b`  +`dbfae$O+;'yZ1@€m1 +endstream endobj 876 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 267 0 R /Length 35 /Filter /FlateDecode >> stream +H‰b` `dbfae$K+;#'7yš1@€˜F +endstream endobj 877 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 278 0 R /Length 36 /Filter /FlateDecode >> stream +H‰b` `dbfae$O+;#'7yÚÑ@€QS +endstream endobj 878 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 275 0 R /Length 37 /Filter /FlateDecode >> stream +H‰b` 021³°2’©—ƒ‘‘“‹›‘‡ +.a0uT +endstream endobj 879 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 258 0 R /Length 43 /Filter /FlateDecode >> stream +H‰b` 021³°2‘¡‘‰‰‰ƒ“‹‰›‰‡—‡‰›r§0* +endstream endobj 880 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 334 0 R /Length 44 /Filter /FlateDecode >> stream +H‰b` 021³0²’®ƒ‘“‹›‘‘‡—‘r§0({ +endstream endobj 881 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 262 0 R /Length 44 /Filter /FlateDecode >> stream +H‰b` 021³0²’¡ƒ“‘‹›‡Èáåã`¤Ø- 0• +endstream endobj 882 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 398 0 R /Length 45 /Filter /FlateDecode >> stream +H‰b` 021³°2’®ƒ“‹›‡“—l ¿€ Æ €=¿ +endstream endobj 883 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 396 0 R /Length 44 /Filter /FlateDecode >> stream +H‰b`  021³°2‘¡‘ƒ“‹›‡—ª™‰_@IˆB×09®´ +endstream endobj 884 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 403 0 R /Length 43 /Filter /FlateDecode >> stream +H‰b`  021³0’£‘•ƒ“‘‹›ª›—‘_€,“@€,òŽ +endstream endobj 885 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 387 0 R /Length 45 /Filter /FlateDecode >> stream +H‰b` 021³0²’£“•ƒ“‹›‡—f¿€ #^=„@€4<£ +endstream endobj 886 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 392 0 R /Length 42 /Filter /FlateDecode >> stream +H‰b` 021³°2’©—ƒ“‹›®‘—ŸQ€"÷0-mŽ +endstream endobj 887 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 390 0 R /Length 39 /Filter /FlateDecode >> stream +H‰b` 021³0’«—•ƒ“‹¡Ÿ‘‡—\Ó  À#—o +endstream endobj 888 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 421 0 R /Length 41 /Filter /FlateDecode >> stream +H‰b` 021³0²’­›ƒ“‹!ÀÍÃËÇψ[ À'³} +endstream endobj 889 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 424 0 R /Length 43 /Filter /FlateDecode >> stream +H‰b` 021³°²‘¥•ƒ“‹›‡U7¿› .b09¯² +endstream endobj 890 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 409 0 R /Length 39 /Filter /FlateDecode >> stream +H‰b` 021³0’©••ƒ“‹›M˜—ŸL! À(6} +endstream endobj 891 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 416 0 R /Length 42 /Filter /FlateDecode >> stream +H‰b` 021³0²’©—ƒƒ“‹M;#/?#ùNb0,³Š +endstream endobj 892 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 350 0 R /Length 41 /Filter /FlateDecode >> stream +H‰b` 021³°2‘«›‰ƒ“‹]?/Ùf@€&Ét +endstream endobj 893 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 352 0 R /Length 39 /Filter /FlateDecode >> stream +H‰b` 021³0’¯›•ƒÝ.Fn^òMe0 ÷h +endstream endobj 894 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 353 0 R /Length 43 /Filter /FlateDecode >> stream +H‰b` 021³°²‘«›ƒ“‹›‡—]œ_@ ]x`;?º +endstream endobj 895 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 339 0 R /Length 39 /Filter /FlateDecode >> stream +H‰b` 021³0’«XÙØ98¸0Ìåæá%ß\€t_ +endstream endobj 896 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 344 0 R /Length 40 /Filter /FlateDecode >> stream +H‰b` 021³0²’©b;'#¦07#/¹†pa +endstream endobj 897 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 358 0 R /Length 37 /Filter /FlateDecode >> stream +H‰b` 021³0’©¬Ÿ•«Œœ\œd› `WF +endstream endobj 898 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 371 0 R /Length 41 /Filter /FlateDecode >> stream +H‰b` 021³0²’§b;'#6.nn.20#¾s +endstream endobj 899 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 377 0 R /Length 37 /Filter /FlateDecode >> stream +H‰b` 021³0’§j+;'v).nrÍ0ôS +endstream endobj 900 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 363 0 R /Length 38 /Filter /FlateDecode >> stream +H‰b` 021³0’¥XÙØ9p˜ÀÊÈÉÅM¦é‘L +endstream endobj 901 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 364 0 R /Length 36 /Filter /FlateDecode >> stream +H‰b` 021³0’¥n+;.98¹È4 À_= +endstream endobj 902 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 365 0 R /Length 38 /Filter /FlateDecode >> stream +H‰b` 021³0’£ÉV6vrŒœ\Üä™`O +endstream endobj 903 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 381 0 R /Length 37 /Filter /FlateDecode >> stream +H‰b` 021³0’£XÙØ9XqšÏÉÅMžùœK +endstream endobj 904 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 346 0 R /Length 33 /Filter /FlateDecode >> stream +H‰b` 021³0’¡hÀÊÈÆÎÁIŽN€0 +endstream endobj 905 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 408 0 R /Length 30 /Filter /FlateDecode >> stream +H‰b` 021³0’¡XÙØɲ À ª +endstream endobj 906 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 384 0 R /Length 33 /Filter /FlateDecode >> stream +H‰b` 021³0’®ÀÊÈÆÎÁI†F€0 +endstream endobj 907 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 85 0 R /Length 30 /Filter /FlateDecode >> stream +H‰b` 021³0’®4;XÙØɱ À ¡ +endstream endobj 908 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 81 0 R /Length 33 /Filter /FlateDecode >> stream +H‰b` 021³0’¬‹DÀÊÆÎÁÈIº>€ù0 +endstream endobj 909 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 89 0 R /Length 25 /Filter /FlateDecode >> stream +H‰b` 021³0’¬‹N¶ » +endstream endobj 910 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 86 0 R /Length 33 /Filter /FlateDecode >> stream +H‰b` 021³0±’ª‹dÀÄÆÎÁDº6€C+ +endstream endobj 911 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 69 0 R /Length 31 /Filter /FlateDecode >> stream +H‰b` 021³0’ª‰ ÀÈÊÆNº=  +endstream endobj 912 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 67 0 R /Length 31 /Filter /FlateDecode >> stream +H‰b` 021³0’ª‰ ÀÈÊÆNº=  +endstream endobj 913 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 77 0 R /Length 36 /Filter /FlateDecode >> stream +H‰b` 021³0’¨¡™•h͌œ\$Û`Ï= +endstream endobj 914 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 92 0 R /Length 36 /Filter /FlateDecode >> stream +H‰b` 021³0’¨¡™•h͌œ\$Û`Ï= +endstream endobj 915 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 111 0 R /Length 43 /Filter /FlateDecode >> stream +H‰b` 021³0’¦E;+#;'1j¹¹y‰R‰ µ] +endstream endobj 916 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 112 0 R /Length 38 /Filter /FlateDecode >> stream +H‰b` 021³0’¦U?+;‘0rrq“j@€ +H +endstream endobj 917 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 115 0 R /Length 45 /Filter /FlateDecode >> stream +H‰b` 021³0±’¤ØØ98¹¸yxù˜ˆSÏÄ/ H¤R807«¢ +endstream endobj 918 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 96 0 R /Length 41 /Filter /FlateDecode >> stream +H‰b` 021³0’¤Y3+;'7Ñ0òðò‘h@€%o +endstream endobj 919 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 93 0 R /Length 37 /Filter /FlateDecode >> stream +H‰b` 021³0’¤Y3+;')¸¸yH´ ÀðS +endstream endobj 920 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 103 0 R /Length 44 /Filter /FlateDecode >> stream +H‰b` 021³°’¢°±±sprqóðò±©ƒŸU@Dë ;K° +endstream endobj 921 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 100 0 R /Length 43 /Filter /FlateDecode >> stream +H‰b` 021³0’¢°²±sprqóðò±m¿€ iö6O¢ +endstream endobj 922 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 28 0 R /Length 38 /Filter /FlateDecode >> stream +H‰b` 021³0’¢U7+;')ú¹¸yH³ À6T +endstream endobj 923 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 31 0 R /Length 41 /Filter /FlateDecode >> stream +H‰b` 021³0’ ];+;')p1ró0ò’b@€“a +endstream endobj 924 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 34 0 R /Length 39 /Filter /FlateDecode >> stream +H‰b` 021³0’ C?+;')&0rqód#@€ùT +endstream endobj 925 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 16 0 R /Length 39 /Filter /FlateDecode >> stream +H‰b` 0213² M7++;'#Iz¸¸yHÒ`Y +endstream endobj 926 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 14 0 R /Length 40 /Filter /FlateDecode >> stream +H‰b` 021³0¯C;+;#'iš¸yyIP` Fa +endstream endobj 927 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 23 0 R /Length 36 /Filter /FlateDecode >> stream +H‰b` 021³0¯S?+;©ú98¹HÑ`= +endstream endobj 928 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 20 0 R /Length 41 /Filter /FlateDecode >> stream +H‰b` 021³0±­0±±spr‘f7/ ê $yi +endstream endobj 929 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 57 0 R /Length 44 /Filter /FlateDecode >> stream +H‰b` 021³0­ª‡• ¡…‘ƒ“‹D#¹yy‰W`#úi +endstream endobj 930 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 58 0 R /Length 45 /Filter /FlateDecode >> stream +H‰b` 021³0­ XÙØ98z¸¸yxùH4‚‘_@-7YŸ +endstream endobj 931 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 64 0 R /Length 52 /Filter /FlateDecode >> stream +H‰b` 0213²¥’…‘•¬…ƒ“‹›IŠ‡—8#¶òñ 0V78˜ +endstream endobj 932 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 51 0 R /Length 53 /Filter /FlateDecode >> stream +H‰b` 021³0©”•¬”‘ƒ“‹›‡¢‘—_@€Xë† +1 +­ ÀQiß +endstream endobj 933 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 39 0 R /Length 55 /Filter /FlateDecode >> stream +H‰b` 021³0¥’•ƒ“¤‡‹›‡—_@_ˆCXDTŒWœ8ȳ ‰õL +endstream endobj 934 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 49 0 R /Length 57 /Filter /FlateDecode >> stream +H‰b` 0213²£…‘•ƒÌädåâæáåãáæA¢L@µWHX„‘hÕx3< +endstream endobj 935 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 45 0 R /Length 54 /Filter /FlateDecode >> stream +H‰b` 021³0¥•ƒ“ ¬–‘›‡—ƒŸ‰2Ý@!aFbnŽ! +endstream endobj 936 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 191 0 R /Length 50 /Filter /FlateDecode >> stream +H‰b` 021³0¡Ž••ƒƒ“ ¬–‘›‡ °óc†Í|üDë0fG +endstream endobj 937 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 188 0 R /Length 51 /Filter /FlateDecode >> stream +H‰b` 021³0VÆÊÆÎÁÉÅÍÃVËÈËDžøˆ0ÓfA!a¢õ€D +endstream endobj 938 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 199 0 R /Length 53 /Filter /FlateDecode >> stream +H‰b` +021³0¡Ž‰•ƒ“ƒ‹¤˜‡‡— ð c:àa"Z@€ŸD +endstream endobj 939 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 195 0 R /Length 52 /Filter /FlateDecode >> stream +H‰b` +021³0¡Œ•ƒƒ“‹¤˜‡‡— ðñaC…ˆÕ`y‰2 +endstream endobj 940 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 176 0 R /Length 54 /Filter /FlateDecode >> stream +H‰b` +021³0¡Œ•ƒƒ“‹¨˜‘‡“—_…ˆ0›¡Â"¢Äê0¡p— +endstream endobj 941 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 183 0 R /Length 54 /Filter /FlateDecode >> stream +H‰b` 021331VÇÄÂÊÆÆÆÊÎÀâprq³!^&¢,C|ü‚Äê0a¨ +endstream endobj 942 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 180 0 R /Length 52 /Filter /FlateDecode >> stream +H‰b` 021³0£Ž•ƒ¬–‹›‡—øø¹¸ˆ² ÓTAF"µoÔ +endstream endobj 943 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 217 0 R /Length 54 /Filter /FlateDecode >> stream +H‰b` 021³0£Ž•ƒ“‹›‡‡—_€…ˆ1«©ÂÌ"Dê0„÷D +endstream endobj 944 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 214 0 R /Length 55 /Filter /FlateDecode >> stream +H‰b` 021³°VÆÆÎÁÉÅÍÃËÇÒÃ/ ($ B¼"ŒDY…ÍvQ1q"5¼ÆÑ +endstream endobj 945 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 225 0 R /Length 51 /Filter /FlateDecode >> stream +H‰b` 021³0£‰•ƒ“‹¤˜‘‡—…ˆ2‡õÂ"Dê0“Y +endstream endobj 946 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 222 0 R /Length 49 /Filter /FlateDecode >> stream +H‰b` 021³0¥•ƒ“‹‘Ìááåƒ~¢ôã2VPH˜8ý{%6 +endstream endobj 947 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 205 0 R /Length 48 /Filter /FlateDecode >> stream +H‰b` 021³0¥•ƒ“‹Âááåƒ~¢ôã2VPH˜8ýz¶5 +endstream endobj 948 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 206 0 R /Length 51 /Filter /FlateDecode >> stream +H‰b` 0213²¥•ƒÂæäbäæá…>~Fbôã2VPH˜8ýkF +endstream endobj 949 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 209 0 R /Length 53 /Filter /FlateDecode >> stream +H‰b` ™˜YX‰PÇÀÆÊÎÁÉVÊÊÍÃËÊÇ/‚BDéÇ„YED‰3 ÀHk +endstream endobj 950 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 136 0 R /Length 52 /Filter /FlateDecode >> stream +H‰b` ™˜Y‰PTÉÊÆQÉÈÁÉÅÍÃ˼üÄéÇi® 0Q&m° +endstream endobj 951 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 135 0 R /Length 54 /Filter /FlateDecode >> stream +H‰b` ™˜Y‰PTÉÊÆÎbp°srqóðòñ €€ qÚq›+,"L”|: +endstream endobj 952 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 143 0 R /Length 59 /Filter /FlateDecode >> stream +H‰b` ™˜Y«becç`38¹¹yxùøøø@@PH˜QD”° xÌ—`$F!@€ŸF’ +endstream endobj 953 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 140 0 R /Length 62 /Filter /FlateDecode >> stream +H‰b` ™˜Y˜+cbecçà*dââæaâåã€A!avNQ&1ÂFàâL’D8 À¶Æ +endstream endobj 954 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 124 0 R /Length 55 /Filter /FlateDecode >> stream +H‰b` ™˜Y‰PÆÊÆÎÁ TÈÈÅÍÃÈËÁül‚BœD˜€ÏpaQbL0—àw +endstream endobj 955 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 121 0 R /Length 52 /Filter /FlateDecode >> stream +H‰b` ™˜Y +cecçàä*däæáeäãàG‚D€× BÂ"Ä` Ê‡ +endstream endobj 956 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 131 0 R /Length 58 /Filter /FlateDecode >> stream +H‰b` ™˜Y+c`decgd`áàäâæadäáåƒ~n~AF" Àg¶°1F‘šg +endstream endobj 957 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 146 0 R /Length 56 /Filter /FlateDecode >> stream +H‰b` ™˜Y˜ª&V6v&&N.n&^>~(a'ÊÊ`¼â± +endstream endobj 958 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 162 0 R /Length 71 /Filter /FlateDecode >> stream +H‰b` ™˜Y ªb``ecç`dåäâæáåãaqA FVqaQ!I)iV"LÂê +YF"ô¢ +endstream endobj 959 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 166 0 R /Length 73 /Filter /FlateDecode >> stream +H‰b` ™˜Y ªb``ecç``ääâæáeçãçâaQ1Fq 0[PRJZFVŽãÐ]!¯ H„6€3‹ +endstream endobj 960 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 169 0 R /Length 63 /Filter /FlateDecode >> stream +H‰b` ™˜Y ª)decdçàäâææáåãá†~AA!Fan8àå#Ê> stream +H‰b` ™˜ *©caeadcçàäâæáåãçæ‚AF!a.$À-"J”‰È@L\B’M×Ù8 +endstream endobj 962 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 148 0 R /Length 64 /Filter /FlateDecode >> stream +H‰b` ™˜YX )V6vVVN.n^>~A!(àBâ’Rĉb¼´ Î0Ft5 +endstream endobj 963 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 157 0 R /Length 63 /Filter /FlateDecode >> stream +H‰b` ™˜Y )+decgd`äàäâäæáåãä‡A!~T ,"*FŒ‘(ƋKHv@€U¸ +endstream endobj 964 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 154 0 R /Length 64 /Filter /FlateDecode >> stream +H‰b` ™˜Y )+decgdààäâæáåãàà>a4 "*ÆAŒ‘(ƋKHv@€7Ù +endstream endobj 965 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 168 0 R /Length 65 /Filter /FlateDecode >> stream +H‰b` ™˜YX )6vN.Fn^F>~A!àB"¢ìlD‰ê1q F‚ª "Tß +endstream endobj 966 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 126 0 R /Length 64 /Filter /FlateDecode >> stream +H‰b` ™˜ ©V6v JN.n^VF>~A0(+ 1f"1Fq Â0´ +endstream endobj 967 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 145 0 R /Length 63 /Filter /FlateDecode >> stream +H‰b`À™˜YX ¨6vv6VN.n^>~^A0DÂ"¢lʉXÅÄ ; À+”è +endstream endobj 968 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 211 0 R /Length 65 /Filter /FlateDecode >> stream +H‰b`À™˜Y ¨V6vN JV.n^>~A!> åáCÂb¬¬Ä˜‰êq I‚.0 ”¦ +endstream endobj 969 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 220 0 R /Length 59 /Filter /FlateDecode >> stream +H‰b`À™˜Y ¨ªdec©dä`ãäâæáåãA!A ÌCœ‘¨æ‹ˆŠÔ`÷`x +endstream endobj 970 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 175 0 R /Length 59 /Filter /FlateDecode >> stream +H‰b`À™˜YX ¨6vN6°.n^>~AâÄÂ"ŒD‰êQ1q‚Ú _¶ +endstream endobj 971 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 189 0 R /Length 60 /Filter /FlateDecode >> stream +H‰b`À™˜ (*daec``ceçàdäâæáåãA!~L ,Bœ™(@TL\‚ 6€ý@– +endstream endobj 972 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 43 0 R /Length 63 /Filter /FlateDecode >> stream +H‰b`À ™˜Y˜ð+V6v BVVN.n^>~A!a Æ⠬ʉ˜$% : À9y +endstream endobj 973 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 55 0 R /Length 61 /Filter /FlateDecode >> stream +H‰b`À ™˜Yñ+*dec+däàäâæáeäãÄü"D‰a…¨£85ǐ +endstream endobj 974 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 33 0 R /Length 60 /Filter /FlateDecode >> stream +H‰b`À ™˜Yñ+V6vV°N.n^F>~AAA!aA,@D”(#1Ü"&.AH#@€À® +endstream endobj 975 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 101 0 R /Length 53 /Filter /FlateDecode >> stream +H‰b`À ™˜Yñ+A×ÁÊÆÎÈÁÈÉÅ <ܼÜ€‡Ÿ4#a&  +Ò`§ ± +endstream endobj 976 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 117 0 R /Length 54 /Filter /FlateDecode >> stream +H‰b`À ™˜Yð+ÁÐÂÊÆÎÈÁÉÅÍÍÍÅÃˍ ø8H4j0¿€ #5 T +endstream endobj 977 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 75 0 R /Length 50 /Filter /FlateDecode >> stream +H‰b`À ™˜ñ«À¢‡…•‘ƒ“““‹D¢n’^F>~B: ~æL +endstream endobj 978 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 80 0 R /Length 50 /Filter /FlateDecode >> stream +H‰b`À™˜YXñªÀXÙØ98¹¸yxxùxy°~’„,(DH'@€´ïÉ +endstream endobj 979 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 351 0 R /Length 49 /Filter /FlateDecode >> stream +H‰b`À™˜YñªÀ¦‰•8¹¸9°^’„ÌÇ/ ˆ_ @€‚€^ +endstream endobj 980 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 359 0 R /Length 52 /Filter /FlateDecode >> stream +H‰b`À™˜YñªÀ¦‰•ƒ“‹›››‡—ðñ ’j$Ô`!a®0©È¾ +endstream endobj 981 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 341 0 R /Length 46 /Filter /FlateDecode >> stream +H‰b`À™˜YñªÀ¡•ƒ“‹› àá%ÇD°©|üôrg. +endstream endobj 982 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 347 0 R /Length 51 /Filter /FlateDecode >> stream +H‰b`À™˜YðªÀXYÙØ988¹¸y0/ é&B]Ã/ Ȉ_ @€—»Š +endstream endobj 983 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 419 0 R /Length 48 /Filter /FlateDecode >> stream +H‰b`À™˜ñ*Àª‰…•ƒ“‹››‡ðò‘n"ð3 +Ð `‚fU +endstream endobj 984 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 402 0 R /Length 55 /Filter /FlateDecode >> stream +H‰b`À™˜Y˜ð)À¬lìœ\Ü<¼|üL‚|Bè€_X„4‘“¨(ÍñLT +endstream endobj 985 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 264 0 R /Length 55 /Filter /FlateDecode >> stream +H‰b`À™˜Yñ)ÀÔÁÊÆÎÁÉÅÍÃËÇÏ( È%„„EEI2Åt1qº ë†Z +endstream endobj 986 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 273 0 R /Length 53 /Filter /FlateDecode >> stream +H‰b`À™˜Yñ)ÀÔÁÊÆÎÁÉÅÍÃËÇÈÏ%À……H3ÕtaQüÚ §_¬ +endstream endobj 987 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 229 0 R /Length 57 /Filter /FlateDecode >> stream +H‰b`À™˜Yñ)@¬l쌌œ\Ü<¼¼|üŒ‚¼@ˆG˜1Ü#"*†_;@€ÎÓ +endstream endobj 988 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 243 0 R /Length 56 /Filter /FlateDecode >> stream +H‰b`À™˜Yñ)@SÎÊÆTÎÈÁÉÅÍÅÃËÇ͏…ˆ7ÃaQüî0ʑ +endstream endobj 989 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 311 0 R /Length 53 /Filter /FlateDecode >> stream +H‰b`À™˜Yð)@SÎÊÆΤ88¹¸yx¹ù°~FâÍô@PH¿~€¿çá +endstream endobj 990 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 307 0 R /Length 47 /Filter /FlateDecode >> stream +H‰b`À™˜ñÉãÐÅÂÊÆÆÎÁɅ ¸yxùH7øùð; ÀƒU +endstream endobj 991 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 301 0 R /Length 45 /Filter /FlateDecode >> stream +H‰b`À ™˜Y˜ðÈãL¬lìœ\ܘ€‡—óLæãÃo@€„rH +endstream endobj 992 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 295 0 R /Length 48 /Filter /FlateDecode >> stream +H‰b`À ™˜YñÈãÐÅÊÆÎÁÉǺ x8xI7Ål>~F| + uà. +endstream endobj 993 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 285 0 R /Length 49 /Filter /FlateDecode >> stream +H‰b`À ™˜YñÈc×ÄÊÆÎÁÉÅÍËøøI6Íp!a¼F¦t¨ +endstream endobj 994 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 292 0 R /Length 51 /Filter /FlateDecode >> stream +H‰b`À ™˜YñÈc×ÄÊÆÎÁÉÈÅÍË +øø…H5 ÝpaQ¼.0¢Æ£ +endstream endobj 995 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 323 0 R /Length 46 /Filter /FlateDecode >> stream +H‰b`À ™˜YñÈãÓÊÊƎØ88¹¸yÈ3f,/?^Xýí +endstream endobj 996 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 330 0 R /Length 52 /Filter /FlateDecode >> stream +H‰b`À ™˜YðÈãÓÊÊÆÎÁÉÅÁÜ<ì¼|üŒä™3V@P¯ cÏ +endstream endobj 997 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 309 0 R /Length 49 /Filter /FlateDecode >> stream +H‰b`À ™˜ñHã,¬lìœ\œÜ<¼h€_€,a@PHX¯› ¢ +endstream endobj 998 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 315 0 R /Length 45 /Filter /FlateDecode >> stream +H‰b`À ™˜ñHã,¬lìœ\Ü€‡—L!€‘_¯})H +endstream endobj 999 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 250 0 R /Length 49 /Filter /FlateDecode >> stream +H‰b`À ™˜Y˜pKãL¬lìLœ\Ü<\¼˜€›ƒtQLçãÃk@€¡o‹ +endstream endobj 1000 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 231 0 R /Length 54 /Filter /FlateDecode >> stream +H‰b`À ™˜YqKãÒÅÊÆÎÁÉÅÍÃËǏ +x…„EH7ÅtQ1Fq<òÃ@ø +endstream endobj 1001 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 239 0 R /Length 53 /Filter /FlateDecode >> stream +H‰b`À ™˜YqKc¬lìœ\Ü<¼|ü¼¨€W•Tã0Ü$$,"ŠG ÀÀ…ï +endstream endobj 1002 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 272 0 R /Length 49 /Filter /FlateDecode >> stream +H‰b`À ™˜™qKãÒÅÂÊÆÎÁÉÅÍÃˇ +øH7 ÃtA!a|¦šÓŠ +endstream endobj 1003 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 276 0 R /Length 48 /Filter /FlateDecode >> stream +H‰b`À ™˜YqKãÔÆÊÆÎÁÉÅÍÃˇ +øÈ0 ÝpA!a|¦š@ˆ +endstream endobj 1004 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 254 0 R /Length 57 /Filter /FlateDecode >> stream +H‰b`À ™˜YqKãÒÅÊÆÎÁÉÅÍÃËÇ/ (Ä/ ‚"¢bœ$›†aº¸„$>7ÃÍø +endstream endobj 1005 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 261 0 R /Length 67 /Filter /FlateDecode >> stream +H‰b`À ™˜YpKc,,¬lìœ\Ü<¼|ü¼œŒ‚B À)"*&Î(!)%ÀHšn’–‘Åg@€Üè= +endstream endobj 1006 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 404 0 R /Length 64 /Filter /FlateDecode >> stream +H‰b`À ™˜qËb×ÂÂÊÆÎÁÉÅÍÃÉËÇÏ À(ÈÉ|BœÂ"¢||b⤉f„¤> ¾ó +endstream endobj 1007 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 383 0 R /Length 58 /Filter /FlateDecode >> stream +H‰b`À ™˜qËb×ÂÂÊÊÆÎÁÉÅÆÍÃËÇÈÀÈ/ Ȋ ¸…„I5ˆ0ŠŠá3 Àƒ»\ +endstream endobj 1008 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 427 0 R /Length 60 /Filter /FlateDecode >> stream +H‰b`À™˜Y˜pÊbL¬lìœ\Ü<¼|ü|‚BÂ"¢lb(€C\B‚DCQm”Âç(€7º +endstream endobj 1009 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 418 0 R /Length 59 /Filter /FlateDecode >> stream +H‰b`À™˜Y˜pÊbL¬lìœL\Ü<¼|ü‚B<Â"Ü¢<È@TLœTCQmÄ§ À×W +endstream endobj 1010 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 415 0 R /Length 57 /Filter /FlateDecode >> stream +H‰b`À™˜YqÊâÐÃÊÆÎÁÉÅÈÍÃËÇ/ È#$ŒD€Ò$šŠbƒ¨£8ni€úB} +endstream endobj 1011 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 357 0 R /Length 56 /Filter /FlateDecode >> stream +H‰b`À™˜YqÊâÐÃÊÆÎÁÉÅÈÍÃËÇ/ ($,‚ 8DI5Å1qF ÜÒ¢£ +endstream endobj 1012 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 336 0 R /Length 57 /Filter /FlateDecode >> stream +H‰b`À™˜YqÊâÐÃÊÆÎÁÉÈÈÅÍÃËÇÈÏ! ˆ „„EDI4Ù1q <®0î©n +endstream endobj 1013 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 375 0 R /Length 55 /Filter /FlateDecode >> stream +H‰b`À™˜YqÊâÒÄÊÆÎÁÈÈÉÅÍÃËÇ/À#ˆ „„EH6ÉQ1q<Ú è0Z +endstream endobj 1014 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 370 0 R /Length 53 /Filter /FlateDecode >> stream +H‰b`À™˜YqÊâÒÄÊÆÎÈÁÉÅÍÃËÇ/À'ˆ  “l,’"¢bx´ïf +endstream endobj 1015 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 369 0 R /Length 54 /Filter /FlateDecode >> stream +H‰b`À™˜YqÊâÒÄÊÆÈÀÎÁÉÅÍÃËÇÈÏ+€ +‘l,’Â"¢x´ÖÔ, +endstream endobj 1016 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 345 0 R /Length 51 /Filter /FlateDecode >> stream +H‰b`À™˜YpÊ⌬l윜\ŒÜl> stream +H‰b`À™˜YpÊ⌬lìœ\܌<¼|üX—#Yæ‚ÍÆ£ À»Yì +endstream endobj 1018 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 83 0 R /Length 55 /Filter /FlateDecode >> stream +H‰b`À™˜qJbªfa…«fdcçàäâæadäåãÂøI0 ‹ˆâÑ `Ÿr¸ +endstream endobj 1019 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 91 0 R /Length 70 /Filter /FlateDecode >> stream +H‰b`À™˜qJbV6v¨rFN.Fn^>~A!aaQ1q I)i–•“W Ád4{•ðh09ž9 +endstream endobj 1020 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 68 0 R /Length 67 /Filter /FlateDecode >> stream +H‰b`À™˜qJ"V6vN.n^>ˆF~A!aQT &Î%! RÒ2ęŒÈ2ÊÉãÑ `q¥ +endstream endobj 1021 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 72 0 R /Length 66 /Filter /FlateDecode >> stream +H‰b`À™˜Y˜pI"&V6vN.n^>ˆz&~A!a *&.!)%-#+'-O”ÉØ­SPÄ£ À{æ¯ +endstream endobj 1022 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 106 0 R /Length 70 /Filter /FlateDecode >> stream +H‰b`À™˜Y˜pI"T±²±spprqópñòñ31220 ‹ˆbbâ’ìRÒ2²rò„MƘñh0¥)ý +endstream endobj 1023 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 114 0 R /Length 68 /Filter /FlateDecode >> stream +H‰b`À™˜YqI"T±²±³sprqsó°óòñ  + 32ŠˆŠaâ’RÒ2R²rò„MÆi£‚"ÍË2P +endstream endobj 1024 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 98 0 R /Length 69 /Filter /FlateDecode >> stream +H‰b`À™˜YqIÂ+;''7/¿€ °ˆ¨˜¸„¤ -#+'$/¯ HØdœîRRfdÅ) `#! +endstream endobj 1025 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 29 0 R /Length 73 /Filter /FlateDecode >> stream +H‰b`À™˜YqIÂ+;'''7/¿€  °ˆ¨˜8N !)%-#+'¯ ¨¤¬¢JÐx¬îRSgdÅ) `>€ +endstream endobj 1026 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 36 0 R /Length 77 /Filter /FlateDecode >> stream +H‰b`À™˜YqIÂ+;'''7/¿€ #£°ˆ¨n .!)%-#+'''¯ ¨¤¬¢ª¦NÐ4wih +áÖ`VB +endstream endobj 1027 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 15 0 R /Length 78 /Filter /FlateDecode >> stream +H‰b`À™˜YqIÂ+;''7/¿€ 0££¨˜ .!)%ÍÈ +ÖË*#+'’WPd!dÂ]JÊ*¸Ý`ãÜ +endstream endobj 1028 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 21 0 R /Length 72 /Filter /FlateDecode >> stream +H‰b`À™˜YqIÂ+;'7/??¿€ #£°ˆ(?> &.1•QRJ&È'#+GÐ.˜»äq«0Çe‘ +endstream endobj 1029 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 52 0 R /Length 65 /Filter /FlateDecode >> stream +H‰b`À™˜YqIÂÔ°²±sprqóð‚¿#£ /^ ," +2UŒQ\BI˜GJZ†mĸ ÀŸ@þ +endstream endobj 1030 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 59 0 R /Length 69 /Filter /FlateDecode >> stream +H‰b`À™˜YqIÂÔ°²±sprqC/#¿€ 7^À%$ 4U„QTLMF\BRJ„€… ;¥edq» ÀŽ¸! +endstream endobj 1031 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 44 0 R /Length 66 /Filter /FlateDecode >> stream +H‰b`À™˜YqIBT°²±sprqÃ/#¿€ 7~ $ 4•QDT SJ\BR +¿• [¥edq+0—Á/ +endstream endobj 1032 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 119 0 R /Length 78 /Filter /FlateDecode >> stream +H‰b`À™˜YqI‚°²±spr!7/#¿’—€ 0£ˆ¨’¸£$#/76 %-Ã(‰ÏVFY9yÜî0«vs +endstream endobj 1033 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 197 0 R /Length 72 /Filter /FlateDecode >> stream +H‰b`À™˜YqI‚äYÙØ98‘7 #/Š?#ƒ£ ’°£(£˜¸' )%-#ŠÏ^Y9yÜî0†Á/ +endstream endobj 1034 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 177 0 R /Length 73 /Filter /FlateDecode >> stream +H‰b`À™˜YpI2°0²²±s N.nF^dv>~F RA$1!aFFQ1œ@\BRŠ§ÍŒÒ2²¸e d¦É +endstream endobj 1035 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 185 0 R /Length 75 /Filter /FlateDecode >> stream +H‰b`À™˜YpH±²±sprq£^>~Ad!aF rQ1$1q FFa!tÝȀKRJš—»øedqÉ10ãFé +endstream endobj 1036 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 219 0 R /Length 78 /Filter /FlateDecode >> stream +H‰b`À™˜Y°I°0²²±s0rrqó ^>F~Ad!aF I¢bHbâŒ,Œ"ÂB> stream +H‰b`À™˜±Š³°²±s02r°s¢.nF^>d~A ¨J…„EEÅø8 6q ìöKJIc•€’3/ +endstream endobj 1038 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 201 0 R /Length 76 /Filter /FlateDecode >> stream +H‰b`À™˜±ˆ²°²±³sp22rr°£.nF^>d6~ ¨J……EDÑuc.n1,``—À&Y~‹ +endstream endobj 1039 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 208 0 R /Length 76 /Filter /FlateDecode >> stream +H‰b`À™˜1ÄXXÙØ9888¹¹89Ð7#/?²¿€ Ð T¥@½ Œ‚ü„»0†€@„QT ›8€Ù +endstream endobj 1040 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 134 0 R /Length 79 /Filter /FlateDecode >> stream +H‰b`À™˜QEXXÙØ98A€‹›‘‘›‹ ðð2òñ ‹ +Í`Aêe`à$DÅÄ1ÝÅÂ(!‰E + w +endstream endobj 1041 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 132 0 R /Length 82 /Filter /FlateDecode >> stream +H‰b`À™˜QXXÙØ!€ƒ“‘‘“ƒ pq3òðò!‹ð Í`æGˆõ20Šˆò£ë1q I)~Ýè@šQF‹0’ê7 +endstream endobj 1042 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 129 0 R /Length 92 /Filter /FlateDecode >> stream +H‰tŽW +€0CG‡Ûº÷öþGTP°}yB~€aB–MÙ€àì…ãÂ󩦂ðÜ@ËG]‚$•ìƒ,/€²ªïØ´úaœæEy²bÛõc*‡µ$' +endstream endobj 1043 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 164 0 R /Length 91 /Filter /FlateDecode >> stream +H‰b`À™˜QXXÙØ!€ƒ“‘‘“ƒ pqóðòñ£ 2 +1 *êE6 +ðó 3Š0ŠŠA¹â’RÒ2²rò +ŠJÊBPg1ª¨2b: + ¸N +endstream endobj 1044 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 171 0 R /Length 98 /Filter /FlateDecode >> stream +H‰tŽG€@B?:ö±½wïB5: M|+ @ôdšn˜–íp‰ëžË?øAÅâ%izWÏ-!/ÊïúBÄêFú¶ë Ã8q>ÍËzßaØvü¦C€»Ì +endstream endobj 1045 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 149 0 R /Length 101 /Filter /FlateDecode >> stream +H‰b`À™˜Á FV6vN.n^>~ddàGBÂ"¢bâ(B’RŒ ¨Jz¥eøø±Y9yFFE_IY…QUMÌæSV×;ˆQS‹—£ Jú +endstream endobj 1046 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 155 0 R /Length 95 /Filter /FlateDecode >> stream +H‰b`À™˜ #+;'##7/ð 02 + +ñ¡aQ1Nq! I) F¥B‚(F¡iYFF9ydí +Š0¥ìJʌ,@‡©¨2âr4@€_ +endstream endobj 1047 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 153 0 R /Length 96 /Filter /FlateDecode >> stream +H‰tŽY€ D;Š +.€"î»÷¿£&ÆLxíÌkJäAbˆâ„s‘f ä…äJeŘÚÚÚ8+Ù´·èT«Ò9åÐõ´zg1N˜—/_·ý–¾§é`CŠ +endstream endobj 1048 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 158 0 R /Length 95 /Filter /FlateDecode >> stream +H‰tÎW€ PÆv{ï÷?¢’h $¼¿-³YB `ـãzTb>‚¾XÄ Õ¤YŽˆ©=.P¨«eõœª›VOK]?ã4õ²nüŸ·ûñ„Ï ¦§É-À.é +endstream endobj 1049 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 156 0 R /Length 87 /Filter /FlateDecode >> stream +H‰b`À™˜YXÙØA€ƒ“‹‘‘›‡ +xùy0À/ ˆ!*$,‚¦¨Wn.—`dà‡ñÙ$¥¥eÈÊÉ32*(2âr4@€ù®l +endstream endobj 1050 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 152 0 R /Length 95 /Filter /FlateDecode >> stream +H‰b`À™˜YXÙØA€ƒ“‹‘‘›‡ +xùy0À/ È($̆*("Š¦¨W n.—ddà‡ñÙ¤¤edÁL9yE%veFFU5F\Žf0¿ô +endstream endobj 1051 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 147 0 R /Length 95 /Filter /FlateDecode >> stream +H‰tÎW€0 Ðè`”²÷æþw©ï+²ä$„XÀq2® ¿‰#þ#c…$Í̐åEY՟àì6ï^SÛõ€ŠåS¦Æéšf}Ym‡íir0‚ +endstream endobj 1052 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 151 0 R /Length 94 /Filter /FlateDecode >> stream +H‰tŽI€ i•MPÜ÷ÝÿÿÑ  uêLÒÕCHD1PÆ-B¦Pšhd9÷Ò (+ïÊê¦íúÁ2N3¬Ûyÿ)\—.dÝÞ´Ûý㮡§É#À)âÉ +endstream endobj 1053 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 159 0 R /Length 96 /Filter /FlateDecode >> stream +H‰tÎç +€0 FÑ~ŽÆYÛº÷|ÿg‹Šˆž_!„KûË—“áùˆN±I/J§x]²EYuÓ´ïîG!Õê^Èýp Ü!b¢i^°nø{ší 7? +endstream endobj 1054 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 167 0 R /Length 95 /Filter /FlateDecode >> stream +H‰tÎY€ Pª‚û®¸ëý﨣‘„÷ÙLÚ!Äž”qÑBòGIÊ-wš!/˜³²ª›Vëúºûíý“BêÛáé8͋Ù_±íæâ8ázš\ ß +endstream endobj 1055 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 172 0 R /Length 97 /Filter /FlateDecode >> stream +H‰tŽG +€@7¶µ¬½÷^ÿÿ@+Š‚s +C!äp< ˆ=‘UcW¦º˜ý°YŽ+½çaï$i†cûÙ}ÁòeU7·h»~÷ ‰rv6æ§É*Àhöè +endstream endobj 1056 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 170 0 R /Length 107 /Filter /FlateDecode >> stream +H‰b`À™˜YXÙØ!€ƒ“‹›Êfçåcdä`G@QAF!at Q1q I)iY9yF°ÙsQ€¢’2#ƒ +£ªš:ÌH M-mƒU‡QI‘]WOŸÑÀ—£ ƒo… +endstream endobj 1057 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 161 0 R /Length 99 /Filter /FlateDecode >> stream +H‰b`À™˜YXÙØ!€ƒ“‹ÊfçáedäãgG@QFA!t vaQ11q I)iF°ÙsQ›¬œ<PPTRVQUK©k0jjAlÖÖaÄåh€…×¹ +endstream endobj 1058 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 160 0 R /Length 101 /Filter /FlateDecode >> stream +H‰b`À™˜YXÙØ¡€ƒ“‹ÆæáedäãgG@Q >A!atvQ1qF I)iF°ÙHæ"Y9yF$((22*)«€¥øUÕÔÙÙ54µµu±; #d3 +endstream endobj 1059 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 165 0 R /Length 95 /Filter /FlateDecode >> stream +H‰b`À™˜YXÙØ¡€ƒÎæäbdäæaG@Q^F$MpÍ|ü¼‚BÂ"¢Œ`³ÅÄ1”€€„¤#’ ¤e.•“W`gWTRfTQeÄáf€ÙJ +endstream endobj 1060 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 163 0 R /Length 87 /Filter /FlateDecode >> stream +H‰b`À™˜YXÙرNFF.n,¢<@<Œœ:xùø…„EøÁf‹Ša5W\B’ÉRÒˆËÈʁ¼‚"£’2#730Ü'c +endstream endobj 1061 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 127 0 R /Length 81 /Filter /FlateDecode >> stream +H‰b`À™˜YXÙرNFF.n,¢<`¼|üZ…„EDÅÄÁ*$$±š+ %͈äY„ ¸¹ 2<ŒròŒ˜Î…€Ã*r +endstream endobj 1062 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 128 0 R /Length 80 /Filter /FlateDecode >> stream +H‰b`À™˜YXÙرNFF.n,¢<`¼|ü˜Ú…„EDÅÁ*Ä%°š+)%͈äY„ ¸¹ 2<ŒròŒ˜Î…€½ÿh +endstream endobj 1063 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 130 0 R /Length 80 /Filter /FlateDecode >> stream +H‰b`À™˜YXÙرNFF.n,¢<`¼|ü˜š…„EDÅÁ*Ä%°š+)%͈äY„ ¸¹ 2<ŒròŒ˜Î…€¿i +endstream endobj 1064 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 125 0 R /Length 81 /Filter /FlateDecode >> stream +H‰b`À™˜YXÙرNFF.n,¢<`¼|ü‚š„„EDÅÄÁ*$$±š+%-ÈäY9„ ¸¹ 2<Œò +Œ˜Î…€È‚ +endstream endobj 1065 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 120 0 R /Length 77 /Filter /FlateDecode >> stream +H‰b`À™˜YXÙرNFF.n,¢<`¼|X5ò  + 3‚Uˆˆb5WL\‚É’RpsAe¥ed1 £v) +endstream endobj 1066 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 122 0 R /Length 82 /Filter /FlateDecode >> stream +H‰tŽG€ » bïõÿŸ4!LÀ9nË +ñAQœ¤²¤ò¨…i–èÚ­5m×cÃèݝæ…σuƒý8¥¤u¸î÷®å`¹Ï‘ +endstream endobj 1067 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 123 0 R /Length 82 /Filter /FlateDecode >> stream +H‰tŽG€ » bïõÿŸ4!LÀ9nË +ñAQœ¤²¤ò¨…i–èºq{m×cÃèݝæ…σuƒý8¥¤u¸î÷®å`ºƒ‘ +endstream endobj 1068 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 141 0 R /Length 91 /Filter /FlateDecode >> stream +H‰tŽE€0Cäww¿ÿaÚ PxËÈ$ŒýM “8Y¶ÃŸ¸à\UCьb0$iöpÊ ˆDY‘b^ÔM‹Ûƒ®†QŽOó²Êî¶øø+9Ý) +endstream endobj 1069 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 142 0 R /Length 95 /Filter /FlateDecode >> stream +H‰tŽE€0C ҏ¶¸»ÜÿŠP؅·È"2Mûº˜#Ûq=z⤺Ṍbš¤ìÝ ,/ e¥fuÓâö Ž€®·¯h§™Hp,ë†Ïǒ]€é£d +endstream endobj 1070 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 144 0 R /Length 109 /Filter /FlateDecode >> stream +H‰tŽÛC@„ÿ¡ì Ejk«ŠÖû¿Ÿ»V|7“Ì!‘à¸x¾bFGÅN1¤äÆ=¯Ë,‡H²úoU‰Â6.µÚf¤¾6ÆÜÚ»±<žš|uý[¯Q:`œ¬$ø|g읖E€yƒ| +endstream endobj 1071 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 139 0 R /Length 106 /Filter /FlateDecode >> stream +H‰b`À™˜YYÙØ98¹¸yx9P?#£€ †¨X§°#ˆGWÂÁ.! ”c”’fǐY9FFyE%e°U5u M°”ª£¶‡ £®ž>#.G3q;_ +endstream endobj 1072 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 133 0 R /Length 97 /Filter /FlateDecode >> stream +H‰b`À™˜YYÙØ98¹¸yx9P?#£€ †¨X§°#˜GWÃ!!)ÅÈÀ(-#‹!rò +@I¥0#•”Åa†«m`TUSgÄåh€DVN +endstream endobj 1073 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 138 0 R /Length 95 /Filter /FlateDecode >> stream +H‰tŽE€0D;X?îZ\ïChx˱ c?@Q5è'Ó²—^x>„D’Í8Á5‘fü¢¼C™W’q êæ0ÛîiõÃ8‰{|öˆÂ˺áï4Û;ÑT +endstream endobj 1074 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 137 0 R /Length 98 /Filter /FlateDecode >> stream +H‰tŽW€ D+ì½a÷þ7” †÷¹³SÑô`;.õ|!£_¢HRª ®™tæ²²ª›¶ë]õIÄ À8±Ÿ àó‚õmÛöãäOø%Li"wéF“[€rî› +endstream endobj 1075 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 173 0 R /Length 94 /Filter /FlateDecode >> stream +H‰b`À™˜YYÙØ98¹¸yxù8¿#£ ‰ +‹ˆ"ÄÄ%$¥DÑT±KË )C>Y9FFy¸$§¢’2ÌpUQ!AF5u F\Žf0‹( +endstream endobj 1076 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 207 0 R /Length 91 /Filter /FlateDecode >> stream +H‰tŽG€0Ãfٝì=þÿEà€¨õъ¬bŽëÁBŠҌšäÀ8ýp[!Õ+tY¡n>+%ÐvŠþ ËÄl ã4/O|½> stream +H‰tŽG€0cꆞBïåÿoD‘9ŽlˌY€ãzðƒx#IÉ$ˁBЇËJ¥QV5š¶{§´’@?húá*0s£§™ßã˪IØö¶Óì`që¶ +endstream endobj 1078 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 210 0 R /Length 94 /Filter /FlateDecode >> stream +H‰tŽI€ C©'pž½ÿ!Յ¾eÓה±àùˆ“ˆ=$)'‡,¤¢gZhs¶¬€ºi-£  ë }p +ÌÝ°Ã8‰k|>$%±¬ØþN³]€Xwr +endstream endobj 1079 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 202 0 R /Length 94 /Filter /FlateDecode >> stream +H‰tŽG€0×Ô%Rè½ýÿqH„Ä-e¢„â$åLHH‘±G^¥âOªuAU7 ´õ[Öh ì×v‚·QÓ¼¼ã+¶Y•8N\§é`PTg +endstream endobj 1080 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 203 0 R /Length 93 /Filter /FlateDecode >> stream +H‰tŽÅ€@C§ØîîÎÿ!Mx§¦’”è(ªÝlZ6à¸üÁuÏg‰Ë Âè5â$!ˋo+*+©&êæ Û®Æ[‰i^óºa?ð÷™è``‰¿ +endstream endobj 1081 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 204 0 R /Length 88 /Filter /FlateDecode >> stream +H‰tŽGÀ 7NM€ôJÚÿ_åÄ +‰9ZcÙD 2äÊJi®ÀX§môƒŽøÓqR!˜—´a?¤å¬‰´¨ ·ØŸž… ®ϋÔg¢O€K¼ +endstream endobj 1082 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 213 0 R /Length 90 /Filter /FlateDecode >> stream +H‰tŽÇ€ Ÿkv»þÿ?*!aŽ›™d‰<#ÄIÊx–EY±QMËÌj‚®@„q²-©´£9´’ï0/ëÆ-a?N\7|Ÿ‰AP( +endstream endobj 1083 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 221 0 R /Length 93 /Filter /FlateDecode >> stream +H‰tŽE€0»XÑâÚâþÿ—–0ǵ,!@Óa˜µðü€)ˆöáQÓ,WBQV¸wꆾR”  íúo[ ¸Ìã4/Ê_·8Nü~&—6DÄ +endstream endobj 1084 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 226 0 R /Length 91 /Filter /FlateDecode >> stream +H‰tŽG€ Y»RTÀÞËÿߨ^À0ÇmYB| AÅIš!GA™… @pæð©eU[A*w§i»Œö€VÒm›†Ñä§Ëjìm?pâºáýLµos +endstream endobj 1085 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 224 0 R /Length 95 /Filter /FlateDecode >> stream +H‰tŽÇ€ D{©*öòÿ©\À˜ð.›}›Ù !1¤p#ˋ²ª›–XtŒþp– „Òæý€~øféh£Õ?퐂ƒÀŽ^Ló²n~ُ÷z^7¢É#À­³Q +endstream endobj 1086 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 215 0 R /Length 94 /Filter /FlateDecode >> stream +H‰b`À™˜YàV6v8àäbdäâä@ Qn^„¿#P« 0²2QFF1q tÝ ÀËÃÍÈÀ(*ãKJIËÈÂ4ËÉ+€LSTRfÄéf€îœ +endstream endobj 1087 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 216 0 R /Length 92 /Filter /FlateDecode >> stream +H‰b`À™˜YàV6v8àäbdäâä@ Qn^„¿#P+Š‡ #£°ˆ(ºn¸F1qŸ•QBR +Ĕ–‘e”9D^A‘§› ׶C +endstream endobj 1088 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 218 0 R /Length 93 /Filter /FlateDecode >> stream +H‰b`À™˜Y> stream +H‰b`À™˜Y„¿€ ÐF!a>te"¢bèºA€O\BRBJƕ‘•cÄp•¼‚"† öC +endstream endobj 1090 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 181 0 R /Length 75 /Filter /FlateDecode >> stream +H‰b`À™˜Y‘ù¬lìœ`ÀÅÍÈÈÍʼn@¢<¼|~A ŒBÂ|èÊDDÅÐucq IFLWIIË`ŠÂ@€Ëó¦ +endstream endobj 1091 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 182 0 R /Length 70 /Filter /FlateDecode >> stream +H‰b`À™˜YQEXÙØ98€‹›‘‘›‹ €Dyxùü@PÅ Ê°èƂBŒX\%"*†E ¢) +endstream endobj 1092 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 184 0 R /Length 77 /Filter /FlateDecode >> stream +H‰b`À™˜YQDXÙØ98¹¸yxxùùxyÐH”_@! $,4€QT C£¸ºnt )%͈ÍU2²Œr8ÝÌ`+ê +endstream endobj 1093 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 179 0 R /Length 79 /Filter /FlateDecode >> stream +H‰b`À™˜Y1YÙØ98¹¸¹¹xÐH”—! (ÄÈ Ì("Š¢LL\B’QJ]7*à—‘•“Çê*EFaœnf0'L¹ +endstream endobj 1094 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 174 0 R /Length 83 /Filter /FlateDecode >> stream +H‰b`À™˜Y˜P…˜XÙØ989¹¸yxùøр0“ˆ¨B@\B’ hŒ°Š2)i&&Y!A|@\NžI««˜•˜°J@@€Ø#5 +endstream endobj 1095 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 178 0 R /Length 83 /Filter /FlateDecode >> stream +H‰b`À™˜Y˜P…˜XÙØ988Ø9¹¸yxùøр€ “°B€OT h“¸Š2I)i&&Y~Ü@N^ »£˜•pI@€Œër +endstream endobj 1096 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 186 0 R /Length 80 /Filter /FlateDecode >> stream +H‰b`À ™˜‘¹,¬ŒlìœÀÅÍÃˇ +ø…„"¢b@Å%P”IJI32ÊȊðárò +Œ8ܤȨ¤ŒK r¹? +endstream endobj 1097 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 194 0 R /Length 84 /Filter /FlateDecode >> stream +H‰b`À ™˜V6v6N.nàáåã@‚BŒŒÂ"¢Q1qF FI)eÒ2²ŒŒrò +8€¨¢£N7É*«0â’€Òé +endstream endobj 1098 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 196 0 R /Length 82 /Filter /FlateDecode >> stream +H‰|Î7€ бvÀ~ÿCº!ƒò¶$Kˆ~!IÁ|à™yQ +îUuÓJõÒÐcÐLóëTÈY†U«oÛ~ òé¼îÈLže’ +endstream endobj 1099 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 198 0 R /Length 83 /Filter /FlateDecode >> stream +H‰b`À ™˜Yሊ‰KHJ  iYFF9yl@QI™·“UTÕðɳæÐ +endstream endobj 1100 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 193 0 R /Length 73 /Filter /FlateDecode >> stream +H‰b`À ™˜Y¡lV6vN.LÀÉÍÃËÇ‚ŒŒBÂ"ü€¨˜8ÐTF I)L9iFYÜ.j““‡» 0‡8 +endstream endobj 1101 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 187 0 R /Length 76 /Filter /FlateDecode >> stream +H‰b`À ™˜™á<V6vN.nnTÀÍËÇ/ BŒŒ"¢b‚€¸ØPFI)t¥Ò2²ròŒ8ÝÖ¥ ¨„O@€±• +endstream endobj 1102 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 192 0 R /Length 78 /Filter /FlateDecode >> stream +H‰b`À ™˜Y‘ø¬lìœ\Ü€‹‡—_@@@Pˆ‘QXDT?—€Ê()%,!#+'¯ ¨ÄˆÝ107)«¨ªá‘0Ž ‚ +endstream endobj 1103 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 190 0 R /Length 77 /Filter /FlateDecode >> stream +H‰b`À ™˜Y‘ø¬¬lìœØ7/¿#£ ~ ," +5”QL\.,)%-#+''¯ÀˆÕ-p7)*1*ã‘0,]Ž +endstream endobj 1104 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 46 0 R /Length 80 /Filter /FlateDecode >> stream +H‰b`À ™˜Y˜> stream +H‰b`À ™˜V6<€ƒ“‹›‡‡—_—”’–‘•“WPPR–QQU…u M-<.ÒbÔÖaÄ#Ï`ž;> +endstream endobj 1106 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 50 0 R /Length 59 /Filter /FlateDecode >> stream +H‰b`À ™˜V6|€ƒ¤˜‘‹›‡7àã„Eq;ˆATŒ[Ÿ<@€îØ +endstream endobj 1107 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 48 0 R /Length 66 /Filter /FlateDecode >> stream +H‰b`À ™˜Y LV6vN.€›‡›—_€Ÿ¤IPHX—Ä ¤¤ñ¹HFVŸ<@€õ· +endstream endobj 1108 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 40 0 R /Length 66 /Filter /FlateDecode >> stream +H‰b`À ™˜YalV6v€“‹›‡—Ÿ¬˜Q@PH—À $¥q;ˆQZFŸ<@€ªqî +endstream endobj 1109 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 41 0 R /Length 67 /Filter /FlateDecode >> stream +H‰b`À ™˜YalV6v€“‹›‡—“¢˜Q@PH+—À $¥xqºh´´Œ,>y€¡=Ö +endstream endobj 1110 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 42 0 R /Length 72 /Filter /FlateDecode >> stream +H‰b`À ™˜Y!LV6vN.n,€‡—_@]ˆQX„ ª˜QTL\ ”’–‘ÅääXñ¹HQI™<@€Rx’ +endstream endobj 1111 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 60 0 R /Length 72 /Filter /FlateDecode >> stream +H‰b`À ™˜Y!LV6vN.n,€‡—•‘Ÿ—•Q@ªÈEbâ’R҄€Œ¬+>É+0â“g0ñv• +endstream endobj 1112 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 61 0 R /Length 74 /Filter /FlateDecode >> stream +H‰b`À ™˜Y˜`V6vN.nTÀËÇ/ÀÄÀ$(Ȅª•UHXDTL$$¥¤¹d.Y9&tW &yy¼ò Øð[ +endstream endobj 1113 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 63 0 R /Length 67 /Filter /FlateDecode >> stream +H‰b`À™˜‘x,¬l쨀“‹—fn^>~A!aQ1q Iq)"€´ .ã@@–QNŸ<@€- +endstream endobj 1114 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 62 0 R /Length 62 /Filter /FlateDecode >> stream +H‰b`À™˜YàV6vNÀÅÍÃËLjC/¿€  ‹ˆ"8ø€˜8ã fJHJá“g`0ïA +endstream endobj 1115 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 53 0 R /Length 69 /Filter /FlateDecode >> stream +H‰b`À™˜Y¡lV6vN.n^(àãäaÄ¡UTL\$¥¤e$ˆ²r8̃*¯ ˆOž À¨”í +endstream endobj 1116 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 54 0 R /Length 76 /Filter /FlateDecode >> stream +H‰b`À™˜YalV6vN.nnvàåãÁ¦OTŒC\B8¥¤e$‰²rŒØ „¹A^AŸ<@€«4 +endstream endobj 1117 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 56 0 R /Length 71 /Filter /FlateDecode >> stream +H‰b`À™˜Y!LV6vN.n^>àáeÄ®MTL\BR + HËÈ¢ðq9yì& VPT«€ Àâû~ +endstream endobj 1118 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 38 0 R /Length 67 /Filter /FlateDecode >> stream +H‰b`À™˜Y¡LV6vN.n^0àãàÁª‹CTT ˆKHJ‰¥ñºGF–«•p`˜ñ– +endstream endobj 1119 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 19 0 R /Length 69 /Filter /FlateDecode >> stream +H‰b`À™˜Y˜ L&V6&vN.6n0àáåã`¦‡APHXDˆ‰K  a’Ø̈́&))¼ò \¢ + +endstream endobj 1120 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 24 0 R /Length 63 /Filter /FlateDecode >> stream +H‰b`À™˜‘x,¬lì ÀÁÉÅÉ͈] /¿:ÄÄ"¢Œ> stream +H‰b`À™˜YàV6vN.n^>~AVFZ„„EDс˜¸„$¦(—Âa(ÔhiY¼ + MB +endstream endobj 1122 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 18 0 R /Length 64 /Filter /FlateDecode >> stream +H‰b`À™˜YáV6vVN.n^FÜZXùø0 °aÀ/(ŠÛ\Ñbâx00°É~ +endstream endobj 1123 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 13 0 R /Length 49 /Filter /FlateDecode >> stream +H‰b`À™˜YñªÀ¢‡•prqó`Š¢^>üv1ò p @€‘' +endstream endobj 1124 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 17 0 R /Length 49 /Filter /FlateDecode >> stream +H‰b`À™˜YñªÀ¢‡•pprqcF\<øíbäåãÀo9@€®`õ +endstream endobj 1125 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 25 0 R /Length 49 /Filter /FlateDecode >> stream +H‰b`À™˜YXñªÀl¬ìœ˜€‹›‡‹02àãÀo« !ÇãÓy +endstream endobj 1126 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 32 0 R /Length 55 /Filter /FlateDecode >> stream +H‰b`À ™˜ñ«ÀÔÂÂÊÆÎÁÉÅÍÅќ¼|œ¼<ø¿€ ~«„…E9 Àaß +endstream endobj 1127 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 37 0 R /Length 56 /Filter /FlateDecode >> stream +H‰b`À ™˜Yð+Á¦‹•ƒ“‹›‡xùøy9ð!aü61ŠˆŠ1° ÀÉãG +endstream endobj 1128 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 35 0 R /Length 60 /Filter /FlateDecode >> stream +H‰b`À ™˜Yñ+ÁÔÃÊÆÎÁÉÅÈÈÍÃËü<‚ü|8‡¯°ˆ¨~sÅ%$ ¹ À%fX +endstream endobj 1129 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 27 0 R /Length 61 /Filter /FlateDecode >> stream +H‰b`À ™˜Yñ+ÁÔÃÊÆÎÁÉÅÈÀÈÍÉ<¼|üì8€¯ °ˆ(‹ÅÄ%¹ À‡A +endstream endobj 1130 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 26 0 R /Length 59 /Filter /FlateDecode >> stream +H‰b`À ™˜Yñ+Á¢‰•ƒ‘“‹›‡øøyqA!aQ1‚Ö0ŠK0JP`ãý +endstream endobj 1131 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 30 0 R /Length 56 /Filter /FlateDecode >> stream +H‰b`À ™˜Y˜ð+ÁXÙؙ˜88¹¸yxùøA€[@à"h “°0A5 ¢ó +endstream endobj 1132 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 65 0 R /Length 53 /Filter /FlateDecode >> stream +H‰b`À™˜ (Á¥“…•ƒ“‹¸yxùø9ñnABÖ ‹ˆt +@€±H +endstream endobj 1133 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 99 0 R /Length 52 /Filter /FlateDecode >> stream +H‰b`À™˜YX ¨Á¥•‘ƒ“‹xxùø¹ñA!FBÆ ‹ˆRÃ`ÈãM +endstream endobj 1134 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 104 0 R /Length 49 /Filter /FlateDecode >> stream +H‰b`À™˜Y ¨Á§•ƒ“‘ DãÜ<¼„laäã è€yÁn +endstream endobj 1135 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 102 0 R /Length 50 /Filter /FlateDecode >> stream +H‰b`À™˜Y ¨Á§•ƒ“‹›7àáåã h” 0A—„Ï• +endstream endobj 1136 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 94 0 R /Length 49 /Filter /FlateDecode >> stream +H‰b`À™˜YX ¨ÁØØ98¹¸yXyù¸p~A!a"¬`%¬ + À«Ñö +endstream endobj 1137 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 95 0 R /Length 46 /Filter /FlateDecode >> stream +H‰b` ™˜ ©Á§…•‘ƒ•àâæ!Æ^F>~Âê vÒb +endstream endobj 1138 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 97 0 R /Length 46 /Filter /FlateDecode >> stream +H‰b` ™˜YX )§Ÿƒ‘“‹7àáåãg$lŽ€ aUœ"Ï +endstream endobj 1139 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 105 0 R /Length 46 /Filter /FlateDecode >> stream +H‰b` ™˜Y )"d+;>ÀÁÉÅÈÍÀŃÏF^>~Âî0jáM +endstream endobj 1140 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 113 0 R /Length 48 /Filter /FlateDecode >> stream +H‰b` ™˜Y )ÂXÙØ98ñ.n^>~A<1 + ‹v@€•íÜ +endstream endobj 1141 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 118 0 R /Length 56 /Filter /FlateDecode >> stream +H‰b` ™˜YX )ÂXÙØ9888¹¸YYyxùøñ>.>A!a<±Šˆá €øý +endstream endobj 1142 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 116 0 R /Length 49 /Filter /FlateDecode >> stream +H‰b` ™˜ *¦…• Ø98¹¸9؈<¼¸-âã$ƒ-‘ +endstream endobj 1143 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 107 0 R /Length 48 /Filter /FlateDecode >> stream +H‰b` ™˜Y ªÂ¢•88¹¸9؉l¬¸íaäáå##¡ +endstream endobj 1144 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 108 0 R /Length 49 /Filter /FlateDecode >> stream +H‰b` ™˜Y ªÂ¢• 88¹¸9؉<¼ |8Mã$˜FÅ +endstream endobj 1145 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 110 0 R /Length 42 /Filter /FlateDecode >> stream +H‰b` ™˜Y ªÂ¢•4ÀÁɅÓ"FnF^–(£ +endstream endobj 1146 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 109 0 R /Length 45 /Filter /FlateDecode >> stream +H‰b` ™˜Y˜ªBL¬lìœ\$n^œöð1ñ ã€ÏZU +endstream endobj 1147 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 73 0 R /Length 44 /Filter /FlateDecode >> stream +H‰b` ™˜Y+C¬Œlì$N.nFÜnàáåÃ-‹«}ç +endstream endobj 1148 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 74 0 R /Length 42 /Filter /FlateDecode >> stream +H‰b` ™˜Y +CÑÂÊÆÎFààäÂc #7/1n0…¦{ +endstream endobj 1149 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 76 0 R /Length 40 /Filter /FlateDecode >> stream +H‰b` ™˜Y +CÑÂÊÆN"ààÄg#71n0“ϝ +endstream endobj 1150 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 71 0 R /Length 42 /Filter /FlateDecode >> stream +H‰b` ™˜Y˜+CL¬lì¤vN> stream +H‰b` ™˜YˆP,¬lì$N.nF|.àáåÃ'ª}Ú +endstream endobj 1152 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 70 0 R /Length 41 /Filter /FlateDecode >> stream +H‰b` ™˜Y‰P‡ÐÀÊÆNààäÂg#7/Q.0–Ÿ£ +endstream endobj 1153 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 78 0 R /Length 41 /Filter /FlateDecode >> stream +H‰b` ™˜Y‰P‡ÐÀÊÆNààäÂg#7/Q.0–Ÿ£ +endstream endobj 1154 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 87 0 R /Length 44 /Filter /FlateDecode >> stream +H‰b` ™˜YX‰Pl 윤.n^|ð±ò ç€Å$ +endstream endobj 1155 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 88 0 R /Length 54 /Filter /FlateDecode >> stream +H‰b` 0213²£ªœ•88¹¸‘x<¼ìh€_€¿‚BÂøUÀ@€¥>Ð +endstream endobj 1156 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 90 0 R /Length 54 /Filter /FlateDecode >> stream +H‰b` 021³0£¢š•pp"󸸡 ^>~ÍÉ.@ÀpFA!aâì0¦Ð +endstream endobj 1157 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 227 0 R /Length 65 /Filter /FlateDecode >> stream +H‰b` 021³0£XÙØ98‘;7/;˜ÍÇ/ aq +q ‹ˆ9bâ„Ìf””"Î~€çä‹ +endstream endobj 1158 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 79 0 R /Length 66 /Filter /FlateDecode >> stream +H‰b` 021³0£˜XÙؑ'7;/„ËÇ/ ad`—db$d½”4‘ÖDZ/ +endstream endobj 1159 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 84 0 R /Length 59 /Filter /FlateDecode >> stream +H‰b` 021³°¥¨–pr1¹y <^>~A!!NaF"Íj#R5@€£«· +endstream endobj 1160 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 82 0 R /Length 63 /Filter /FlateDecode >> stream +H‰b` 021³0¥’•prt2róðòðñs22 + p‹ˆ²gH¯˜¸‘¶¦²Å +endstream endobj 1161 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 397 0 R /Length 62 /Filter /FlateDecode >> stream +H‰b` 021³0¥’‘• pp‚tr1póðòñ  + 3Šˆ²‰ŠiØHq F.├…§ +endstream endobj 1162 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 386 0 R /Length 57 /Filter /FlateDecode >> stream +H‰b` +0213²§’•pp2‚Ź¸xxùø…„EDʼn³¬S\B’Xåš™¨ +endstream endobj 1163 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 391 0 R /Length 58 /Filter /FlateDecode >> stream +H‰b` +021³0¥•pr52ró02òòñ ð 2 + g+ÔHQ1¢ì€š} +endstream endobj 1164 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 425 0 R /Length 58 /Filter /FlateDecode >> stream +H‰b` +021³0¥•88¹¸9xxù€L~¸FFA!va¢ B2RTLœX-…#] +endstream endobj 1165 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 414 0 R /Length 63 /Filter /FlateDecode >> stream +H‰b` +021³0¡Ž‰•ƒ“‹›‡—‰Ÿƒ]@®‘IH˜]„—ƒ@”ILœh‹|i +endstream endobj 1166 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 349 0 R /Length 58 /Filter /FlateDecode >> stream +H‰b` 021³0TÄÊÆÎÁÉÅÍQÉÈËÇÁÉÉ/€ÐÇ((ÄÅ%LÐTCEDňÖ`v5 +endstream endobj 1167 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 335 0 R /Length 59 /Filter /FlateDecode >> stream +H‰b` 021³0RÃÊÆÎÁÁÁÉÅÍæóðòñs°³ ô1 + + ‹2ÝTQ1q¢µ€íM +endstream endobj 1168 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 376 0 R /Length 59 /Filter /FlateDecode >> stream +H‰b` 021³0âWÂÊÆÎÁ \ÜP…¬<¼|ü\¬¬SùØXqèÇe³0#ÑZ x& +endstream endobj 1169 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 379 0 R /Length 53 /Filter /FlateDecode >> stream +H‰b` 0213²àUÁÂÊÆÎÁÉÅÎÍÃÓÃËÇÍς_A{… ª‚€SlÏ +endstream endobj 1170 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 366 0 R /Length 47 /Filter /FlateDecode >> stream +H‰b` 021³0âUÁÊÆÎÁÉÈÅÍà SÇÈÇ/ ÈJ¬ äڋ  PY® +endstream endobj 1171 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 367 0 R /Length 40 /Filter /FlateDecode >> stream +H‰b` 021³0VÆÊÆÎÁÆJ¬¡ÄØËÉÅÈM´j€KQ +endstream endobj 1172 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 368 0 R /Length 36 /Filter /FlateDecode >> stream +H‰b` 0213²¡Œ•‘h3‰0Žƒ“ó ­3 +endstream endobj 1173 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 360 0 R /Length 31 /Filter /FlateDecode >> stream +H‰b` 021³0­šZ€‘•[ P +endstream endobj 1174 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 361 0 R /Length 32 /Filter /FlateDecode >> stream +H‰b` 021³0­šZ€‘•‘xå J +endstream endobj 1175 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 362 0 R /Length 35 /Filter /FlateDecode >> stream +H‰b` 021³°²±°©œZ€…ƒ“‹…õhD +endstream endobj 1176 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 378 0 R /Length 38 /Filter /FlateDecode >> stream +H‰b` 021³°²1«œJ€‘ƒ“‘‘‹›H‹ H +endstream endobj 1177 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 380 0 R /Length 39 /Filter /FlateDecode >> stream +H‰b` 021³0²²1©œZ€‘ƒ‘“‘‹›‡H‹ ¯U +endstream endobj 1178 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 372 0 R /Length 45 /Filter /FlateDecode >> stream +H‰b` 021³°²1±s0q¥žZ€‰‹›‡‰‰—_€‰( 0Œ• +endstream endobj 1179 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 373 0 R /Length 45 /Filter /FlateDecode >> stream +H‰b` 021³°²±sprq3£žj€‘‡—‘ŸQ@PH˜8‹ AÄ +endstream endobj 1180 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 374 0 R /Length 50 /Filter /FlateDecode >> stream +H‰b` ™˜YXÙØ98¹¸yx ©§&àcä`d"Îb€Xø +endstream endobj 1181 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 342 0 R /Length 54 /Filter /FlateDecode >> stream +H‰b` ™˜YXÙØ99¹¹yx i "`äã`d`— B@€_è4 +endstream endobj 1182 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 343 0 R /Length 53 /Filter /FlateDecode >> stream +H‰b` ™˜YXÙØ99¹¸yxù i "`ä`bd`a#Æf€_X +endstream endobj 1183 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 340 0 R /Length 50 /Filter /FlateDecode >> stream +H‰b` ™˜Y˜˜Xؙ٘88™¸¸™i `‡XÇÄÃËÇÏ$ HŒÍGsÌ +endstream endobj 1184 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 337 0 R /Length 53 /Filter /FlateDecode >> stream +H‰b` ™˜YXÙØ98¹¹yx ê `äãÚÆÈ+($Ä(,BŒÅW û +endstream endobj 1185 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 338 0 R /Length 55 /Filter /FlateDecode >> stream +H‰b` ™˜YXÙØ99¹¸ ê `äáåcäg— B @€T{5 +endstream endobj 1186 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 354 0 R /Length 51 /Filter /FlateDecode >> stream +H‰b` +021³°²±32r0sr§…bÀÈÍÃË´™_@IH˜Q„=A|à +endstream endobj 1187 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 355 0 R /Length 49 /Filter /FlateDecode >> stream +H‰b` 021³°2²1²sp2©…RÀÈÅÍÃÈÀÈËÇ/ ($,B”µ;EÚ +endstream endobj 1188 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 356 0 R /Length 49 /Filter /FlateDecode >> stream +H‰b` 021³°20²±s0«…2ÀÉÈÅÍÈÊÀÀÃËÇ/ ($L”µ3üÉ +endstream endobj 1189 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 348 0 R /Length 46 /Filter /FlateDecode >> stream +H‰b` 021IV6v¢õPX88¹XX¸yxùXø‰³ À-²² +endstream endobj 1190 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 382 0 R /Length 42 /Filter /FlateDecode >> stream +H‰b` 0213IV6F¢õPÙ98¹¸yx‰· À1c +endstream endobj 1191 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 413 0 R /Length 44 /Filter /FlateDecode >> stream +H‰b` 021³0)V6vF¢5‘98¹¸yxù˜ˆ· À#vs +endstream endobj 1192 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 417 0 R /Length 47 /Filter /FlateDecode >> stream +H‰b` 021³°²10°±sp²«‰ÀÆÅÍÃÆÀÆËÇ/ H¼}> stream +H‰b` 021³°²120°3rp2²©‹|ÀÈÅÍ´—‘_@‘hm7½¨ +endstream endobj 1194 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 407 0 R /Length 48 /Filter /FlateDecode >> stream +H‰b` +021³°²±ƒ™œ\ŒÄé¢0róð220òñ3 + +o@€:Ô³ +endstream endobj 1195 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 411 0 R /Length 52 /Filter /FlateDecode >> stream +H‰b` 021³°²±sp2r10róð)Ú>~AF!FaQF1q ‹H`hc8 +endstream endobj 1196 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 410 0 R /Length 52 /Filter /FlateDecode >> stream +H‰b` 021³020²²±39œ\ŒDi#0róð‚¬âã`&Ú:€?ÖÉ +endstream endobj 1197 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 426 0 R /Length 45 /Filter /FlateDecode >> stream +H‰b` 021³0)V6vF´‘89¹¸y€Vñòñƒ1± -Ǫ +endstream endobj 1198 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 422 0 R /Length 41 /Filter /FlateDecode >> stream +H‰b` 021³0’¡XÙØA6p0rr12róm@€(V +endstream endobj 1199 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 420 0 R /Length 50 /Filter /FlateDecode >> stream +H‰b` 021³0‚hV6vFô‘ 89¹¸yxxùù…„yˆÕ `:í +endstream endobj 1200 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 389 0 R /Length 50 /Filter /FlateDecode >> stream +H‰b` 021³°²1‚X윌Äk$0rqó02ð2òñ3 + + “`@€:èÇ +endstream endobj 1201 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 406 0 R /Length 53 /Filter /FlateDecode >> stream +H‰b` 021³°²±s0™œ\܌Dk$ð0òòñ 00 + + 󋈊‰“`@€W* +endstream endobj 1202 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 393 0 R /Length 53 /Filter /FlateDecode >> stream +H‰b` 021³02²²1‚Ø윌Dë$0rqó02òòñ  + ‹ˆŠ‘`@€H- +endstream endobj 1203 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 388 0 R /Length 55 /Filter /FlateDecode >> stream +H‰b` 0213²°²±s0ٜ\܌Dë$ð0òòñ 0 + + ‹ˆŠ‰KHJ‘`@€cög +endstream endobj 1204 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 385 0 R /Length 56 /Filter /FlateDecode >> stream +H‰b` 021³010±²±3yLœ\LÄj%0qóðmâã'Á"€T¿' +endstream endobj 1205 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 394 0 R /Length 55 /Filter /FlateDecode >> stream +H‰b` 021320²°²1‚8윌\Dë%póðòòp30òñ 0 + + ‹0’¢ ÀLœÿ +endstream endobj 1206 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 401 0 R /Length 53 /Filter /FlateDecode >> stream +H‰b` 02132²°²±3‚yœ\ŒDë%0rópMfäåãg&É€C\Ô +endstream endobj 1207 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 405 0 R /Length 59 /Filter /FlateDecode >> stream +H‰b` 021³°²±sprqó00pòòñsò­™xÀ) (4˜‡SXD”“SL\‚“ݏҙ +endstream endobj 1208 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 400 0 R /Length 57 /Filter /FlateDecode >> stream +H‰b` 021³°²±3rprq320òðò1¯™x[øæ + ‹ˆŠ12ŠKH’d @€pFO +endstream endobj 1209 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 395 0 R /Length 56 /Filter /FlateDecode >> stream +H‰b` 021³°²1²spr12póðò±2’ ›H;øÙÀ,!aFQ1&nR´gL +endstream endobj 1210 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 399 0 R /Length 49 /Filter /FlateDecode >> stream +H‰b` 021³°2‚l쌤ê&8¹¸y€¦2òò1ò  +‘j@€5¦´ +endstream endobj 1211 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 259 0 R /Length 54 /Filter /FlateDecode >> stream +H‰b` 021³°²±s00p2rqó0’¨ ñ¼|ü@3…„…EDÅÄ9IÓ`_”6 +endstream endobj 1212 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 260 0 R /Length 53 /Filter /FlateDecode >> stream +H‰b` 021³°2²±ƒÙœ\ŒÜ¤é'd<//#æãd%Ñ|€T| +endstream endobj 1213 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 265 0 R /Length 50 /Filter /FlateDecode >> stream +H‰b` 021³°2ÂylìŒø”“ 9¹¸&òðòñ 2 + ‹j<@€=äÚ +endstream endobj 1214 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 263 0 R /Length 50 /Filter /FlateDecode >> stream +H‰b` 021³0Ây¬l윌x”“ +¹¸yy4?ÐXFA!RM08ÿ´ +endstream endobj 1215 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 255 0 R /Length 57 /Filter /FlateDecode >> stream +H‰b` 021³°2²±sp2r¸Ü<¼Œ|$™€ð  + 3‚ÌR|ŒbâŒ$`ke, +endstream endobj 1216 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 256 0 R /Length 52 /Filter /FlateDecode >> stream +H‰b` 021³°²±spr1rƒ¸<¼|Œ¤™€Ïp~A°iŒBŒ"¢bd˜ `bN +endstream endobj 1217 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 257 0 R /Length 51 /Filter /FlateDecode >> stream +H‰b` 021³02²²1‚Øìœ\Œ$Ã`n^F>0‹_€‘QPˆ ƒ ?9· +endstream endobj 1218 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 266 0 R /Length 55 /Filter /FlateDecode >> stream +H‰b` 021³°22²±3‚yœ\ŒÜ¤šÃ`^> ¡ü‚ŒBÂ"Œ¢bŒ¤`U¡ + +endstream endobj 1219 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 274 0 R /Length 56 /Filter /FlateDecode >> stream +H‰b` 021³°²±sp2r¹Ü<܌¤š ð2òñ €Lbc— Ã\€j.@ +endstream endobj 1220 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 279 0 R /Length 56 /Filter /FlateDecode >> stream +H‰b` 021³0²²±s0‚¹œŒ\Ü<Œ¤‚Í\^>~FCPHXDTŒQ\‚ c cÚ6 +endstream endobj 1221 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 277 0 R /Length 55 /Filter /FlateDecode >> stream +H‰b` 021³02²²±3Bùœ\܌¤š‚i,/?ØFA!FaQ1q2L0Z +endstream endobj 1222 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 268 0 R /Length 51 /Filter /FlateDecode >> stream +H‰b` 0213² óYÙØ9H6ÍPN.nF0“—_€QPHX„‘ s @Ú +endstream endobj 1223 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 269 0 R /Length 62 /Filter /FlateDecode >> stream +H‰b` 021³020²²±spr¸yxùH6ð3 + +1‚Ìeg”`“”â"à €}Ey +endstream endobj 1224 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 271 0 R /Length 59 /Filter /FlateDecode >> stream +H‰b` 021³°²±sprq3òù<Œ¼|üŒ¤›ƒŒ‚BÂ`EDÅÅ%$¥È3 ÀŠ +ƒ +endstream endobj 1225 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 253 0 R /Length 55 /Filter /FlateDecode >> stream +H‰b` 021³°21±±3xLœ\ÜLdL<¼|LŒ`+¿“ °™ÆQ×í +endstream endobj 1226 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 235 0 R /Length 56 /Filter /FlateDecode >> stream +H‰b` 021³0²2²±3B¸œ\܌d™ÖÎÃËÇÒÎ( ($,Â(*&.A¦ibµ7 +endstream endobj 1227 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 236 0 R /Length 56 /Filter /FlateDecode >> stream +H‰b` 021312²°²1Bùìœ\ŒdÔÌÍÃËÖÌÈ/ ($,"*&.A¦a_Ø8 +endstream endobj 1228 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 238 0 R /Length 60 /Filter /FlateDecode >> stream +H‰b` 021³0²²±sprqóð²øøÉ3KHX¢U”QL\BRJZFVNž<³ ³ +endstream endobj 1229 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 233 0 R /Length 60 /Filter /FlateDecode >> stream +H‰b` 021³0‚hV6vF°'7#9Fñòññ5ò 0 + + ‹ˆŠ‰KHJI“c4Ÿ +endstream endobj 1230 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 228 0 R /Length 67 /Filter /FlateDecode >> stream +H‰b` 021³0i&V6v&&N.&&n^>&’Mbâæjcfgb’”’–!ËU@`“`¼ +endstream endobj 1231 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 232 0 R /Length 67 /Filter /FlateDecode >> stream +H‰b` 021³020²²±sp2rqó0…xùøI5GPHX¤‰QTL\BRJZ†QVNžQ> stream +H‰b` 021³°2²±s0rr1rs2‚„xxùøI1D€QPHX¬…QTL\BRŠAšQFVŽ$CP@€¦Gæ +endstream endobj 1233 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 247 0 R /Length 60 /Filter /FlateDecode >> stream +H‰b` 021³02²²±3Bùœ\܌> stream +H‰b` 021³°²±±sp21BDظ¸yxù؈ÔÏÆ/ ($ QÍ&"*ÆÆ&.Á&I¾{@ ÀŠÐ +endstream endobj 1235 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 251 0 R /Length 59 /Filter /FlateDecode >> stream +H‰b` 021³020²²±3„88¹¸yxñé‚>F~A!Fa¨Y"¢b⌒0>¹ À{Wb +endstream endobj 1236 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 246 0 R /Length 64 /Filter /FlateDecode >> stream +H‰b` 021³°2²±s0rr1BŸyxùøYñjkªg””b”–‘%¬/0Ÿà +endstream endobj 1237 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 241 0 R /Length 66 /Filter /FlateDecode >> stream +H‰b` 021³°2²±s0rrq3rÂDyxùøà\ì€SPHXDTŒÊc—”’–a”•“g$ß= `ÀÏ +endstream endobj 1238 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 245 0 R /Length 66 /Filter /FlateDecode >> stream +H‰b` 021³0²2²±31„X98¹¸yyqjbeäã‚©`e—d”’–aÄ©‹(`–Ú¿ +endstream endobj 1239 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 280 0 R /Length 67 /Filter /FlateDecode >> stream +H‰b` 021³°21±±s0q"D™¸¸yxùø™±ëc‚+—`’”’–‘e’“W`ª‡h`½' +endstream endobj 1240 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 314 0 R /Length 69 /Filter /FlateDecode >> stream +H‰b` 021³0²2²°±spr1"‰sóðòñ 2¢k`å—@V,)Å(-Ã(+'¯ ¨$D‘{ ß²† +endstream endobj 1241 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 319 0 R /Length 72 /Filter /FlateDecode >> stream +H‰b` 021³°2²±sp2rq3ò Ëðòñ  + ‹0"ÄDÅÄ%$%¥¤eb²rò +ŠJŒ ŒÊ*ªŒ ”€Éó +endstream endobj 1242 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 318 0 R /Length 83 /Filter /FlateDecode >> stream +H‰b` 021³0²²±3rpr1¢Iqóðòñ ð + ‹ˆŠ‰ŠK ò HJIË0È20ÊÉ+(*)«¨ª©khj12jëè2bµƒ`•ÿ{ +endstream endobj 1243 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 313 0 R /Length 76 /Filter /FlateDecode >> stream +H‰b` 021³02²²±3rpr1¢Hqóðòñ  +A€°ˆ¨˜8·X¤”´ P-£¬œ¼‚"£’²Š*£šº#V HN/¶ +endstream endobj 1244 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 308 0 R /Length 70 /Filter /FlateDecode >> stream +H‰b` 021³0²²±3rprqó0òb*àãAˆˆŠ‰KHU2JIËȊ32ÊÉ+0**)‹`è%÷§È +endstream endobj 1245 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 312 0 R /Length 66 /Filter /FlateDecode >> stream +H‰b` 021³01±²±3qpr1qó0Ařxùøx™°ëaâÊ + ‹ˆŠ‰KH210IIËàPK0§sÊ +endstream endobj 1246 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 320 0 R /Length 68 /Filter /FlateDecode >> stream +H‰b` 021³°²13³sp2sqó0CDy™ùø˜±ë`bf—`–”’–ab–•c–¡Ü% ¾1 +endstream endobj 1247 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 328 0 R /Length 75 /Filter /FlateDecode >> stream +H‰b` `dbfaddecddçàäbd`àæáåcädDR#$,"*`—`””’–‘•“gTPTRVaTUcÄa6i À òô +endstream endobj 1248 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 333 0 R /Length 72 /Filter /FlateDecode >> stream +H‰b` `dbfaedcgäàäâæ ðò12ò 0"«ˆ2Š‰3JHJIËÈÊ1Ê+(*)«¨ª1b5™T`Óò +endstream endobj 1249 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 331 0 R /Length 71 /Filter /FlateDecode >> stream +H‰b` `dbfaddecdçàdr¹¸yxùøQ + B…EDÅÄ%$¥¥eeåä•”±L20êÑ• +endstream endobj 1250 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 327 0 R /Length 68 /Filter /FlateDecode >> stream +H‰b` `dbfaecgä``à`ääâfäáåcDQÀ/ `fagd”d”’–‘•“gÄn(É À»b +endstream endobj 1251 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 321 0 R /Length 65 /Filter /FlateDecode >> stream +H‰b` `dbfa„0YÙØ9™8¹Qpóð22ðññ 0 + + 3ŠˆŠ12ŠK0JJIË0b3,`™Ù³ +endstream endobj 1252 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 326 0 R /Length 69 /Filter /FlateDecode >> stream +H‰b`  +`dbfaec‡pØ98¹ØÙ¹yxùøÙJ؅؅EDÅÄÙ%$¥Ø¥edÙÙåä•”Ù±›I0àÄ +endstream endobj 1253 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 324 0 R /Length 73 /Filter /FlateDecode >> stream +H‰¬ŽÅ€0ÀÜ݋KÙCŽë +Í/yE#`Ù8®‡?‰â$Ír +ʪnÚ¿v=Ã8ÉyaÝvŽó‚ûQ/f4Ÿ)„ +endstream endobj 1254 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 288 0 R /Length 72 /Filter /FlateDecode >> stream +H‰¬ŽÇ€ Àˆ‚½wE,°ÿŽzºù%¯á‚¤Šø$N Íò¢¬ nÚ®óÀ8Á¼¬›DïsœpÝÖáçàç`ÿŠ© +endstream endobj 1255 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 289 0 R /Length 73 /Filter /FlateDecode >> stream +H‰¬ŽG€ À6öŽ`/€þÿ“êŒO §LN Q Išñy^”PÕ m‡ê5fx3ã4³¬Û~œXçñÎ"\7a~ÿ„ +endstream endobj 1256 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 291 0 R /Length 70 /Filter /FlateDecode >> stream +H‰b`  +`dbfaddec±Ù98¹¸yxùø…„E€ÂŒ¢b⌒RŒÒ2Œ²ròŒ +ŠJŒÔ±ï(c +endstream endobj 1257 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 286 0 R /Length 69 /Filter /FlateDecode >> stream +H‰b` `dbfadec1Ù98¹¸yyùø……EE¢b⌒ÜRŒÒ2Œ²ròŒ +ŠJŒT² óŸl +endstream endobj 1258 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 282 0 R /Length 69 /Filter /FlateDecode >> stream +H‰b` `dbfaecd``gäàäâæáåcä`eɋKH2JIË0ÊÊ1Ê+(2*)«0RËn0 +Ð¥ +endstream endobj 1259 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 283 0 R /Length 53 /Filter /FlateDecode >> stream +H‰b` :`dbfadecçàäbäæáe䃈ò 2 + ‹ˆŠ‰KHJI3Rß^0•« +endstream endobj 1260 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 284 0 R /Length 50 /Filter /FlateDecode >> stream +H‰b` `dbfabecçàäâf‚1ñðò1ñ  + ‹ˆŠ‰K0ÑÄ^€wp7 +endstream endobj 1261 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 302 0 R /Length 54 /Filter /FlateDecode >> stream +H‰b` `dbfaecçàäâæaååcàg``deg•”b¥‰½ ”»~ +endstream endobj 1262 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 303 0 R /Length 49 /Filter /FlateDecode >> stream +H‰b` `dbfadecçàäbd`àæáåcdäàf§¥o¹& +endstream endobj 1263 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 305 0 R /Length 42 /Filter /FlateDecode >> stream +H‰b` )`dbfaed``cdçàäbäæaä +òñ3ÒÈ>€0Õ +endstream endobj 1264 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 300 0 R /Length 30 /Filter /FlateDecode >> stream +H‰b`  `dbfa…qXÙØYñ)¦É' +endstream endobj 1265 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 294 0 R /Length 24 /Filter /FlateDecode >> stream +H‰b` 7`dbfae¤‘ár +endstream endobj 1266 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 299 0 R /Length 23 /Filter /FlateDecode >> stream +H‰b` 7`dbfa¤•á¶ +endstream endobj 1267 0 obj << /Type /XObject /Subtype /Image /Width 207 /Height 1 /BitsPerComponent 8 /ColorSpace 297 0 R /Length 22 /Filter /FlateDecode >> stream +H‰b` 7`dbf¡™á] +endstream endobj 1 0 obj << /Type /Page /Parent 6 0 R /Resources 2 0 R /Contents 3 0 R /MediaBox [ 0 0 595 842 ] /CropBox [ 0 0 595 842 ] /Rotate 0 >> endobj 2 0 obj << /ProcSet [ /PDF /Text ] /Font << /TT2 296 0 R >> /ExtGState << /GS1 673 0 R >> /ColorSpace << /Cs6 293 0 R >> >> endobj 3 0 obj << /Length 950 /Filter /FlateDecode >> stream +H‰”UM£F½ó+êØD¢0`8n&Q4‘²ŠvH¢h7‡6´M'L7¡ø÷[ýaãñnVŠ|0Ÿ¯^½÷ªø¾Ú6‡ Úc”åâÿê†Ö5ì˚6Uºƒö%zxÔtÚ=‚îdôðÓs'¥ÐvQ’Ò4MKh_#òd@h0 +¤2¼30‡-ä Þ?=?>‚áqûw”•´Æ×ã‡èÑù£Ü‚}$Ú@—´$,Æ"{b¬jqW€ÍØÉϜ éŽNqjïa}_¨SIüWûs”„ZIF³òZ¯¸²Ï*Ç^ͽÌX¢fà0ó‘3Í-œ=uœ3º«n(gWˆÜCœ¸ä3aZ£è(´êqz#§yúöÚíîeG+ ®îQÍ/ ŽÀƒ$ßÑê‹Vv^0×uòÛû§8ÙÓùðî~_FËè FaVxן…Vó +J‚S&«iZޚo¢xÌ×At¼ZöHKÈn\z£ÿ8£Ñ‚Èë-³ý†WxÀ‰™nàšÂqƒnqë-šæàYF#÷DĈRÔ ñmó.F½»Çü †‡ª;9³%;nyÛ¤tJEÏmJ*b<j;û» q.]x¼·]lªøl’‰Ï—†¸ewæ²W³5šõ«UešÕÙy]Ð"»Qws:sò$ËÔ3Ãuș˜íÛýÒ+2§àm÷H+7+ÂÝo¿ÃŽõ1³ƒç[ôSpH!m–â=­ ï/â•ù ¿·‚ŠÀ4h…qÁÿIi-#Aõ%®7¿ˆƒÃ~«c}Å߅È2cœ-51BÙÀ³¸°ÙÄ +âÎg{žîš ןlÊâ¤W»ò«-åûP²3Ëm’FX¤FĆ`.ûeÄ­5ùì »éÅ»¸…4ºá%ua½®[ð¿VKÞ8“p…í‚q“+‚êII ÜûŠ¡äéèâ?°³é߅k«:á>r>Â÷Ÿ_N­óò>mÛZùHÐ œƒ€µ.óÖ5>‘8©°au…ž&Fí§ã ÎüSL7[m•k¿É¥a[àQ-cïH»‰›-^N°ÛŽ‹ÉøAæÀq‰(½E°nnHW÷_Àé`pÌq.ȊKÍGêv˜ý5$‹»£GUµåëÆüìžã·¼›oÐÝF÷ ü‰‰ÆÀŇëb\¿å×ÿ9@­˜Õ<'a }Àgœêı¤£}¡u¿€pØÒx»àawŠâ‰4a*ÐåÚáÝQ^崆¢jh>ò÷ýüØFŸJÀ!l +endstream endobj 4 0 obj << /S /D >> endobj 5 0 obj << /Nums [ 0 4 0 R ] >> endobj 6 0 obj << /Type /Pages /Kids [ 11 0 R 1 0 R ] /Count 2 >> endobj 7 0 obj << /CreationDate (D:20030702131359+01'00') /ModDate (D:20030702131359+01'00') /Producer (Acrobat Distiller 5.0 \(Windows\)) /Author (uniras) /Creator (PScript5.dll Version 5.2) /Title (Microsoft Word - Covering Letter.doc) >> endobj 8 0 obj << /Type /Metadata /Subtype /XML /Length 1089 >> stream + +Microsoft Word - Covering Letter.doc + + +endstream endobj xref 0 9 0000000000 65535 f +0000275342 00000 n +0000275492 00000 n +0000275629 00000 n +0000276652 00000 n +0000276682 00000 n +0000276724 00000 n +0000276795 00000 n +0000277038 00000 n +trailer << /Size 9 /ID[<60fee8f0a7aa5e5930d8ab5a36aee088><61d6746a07d1d4e2932a4e5f16fbc432>] >> startxref 173 %%EOF \ No newline at end of file diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/Makefile b/SecurityTests/clxutils/NISCC/TLS_SSL/Makefile new file mode 100644 index 00000000..04d3e1fe --- /dev/null +++ b/SecurityTests/clxutils/NISCC/TLS_SSL/Makefile @@ -0,0 +1,39 @@ +# +# Top-level Makefile for NISCC/TLS_SSL. Not compatible with Jasper tools or +# PB project files or Makefiles. Doesn't use SYMROOT, DSTROOT, etc., though +# it does require the LOCAL_BUILD_DIR env var to be set. +# +SHELL := /bin/zsh + +SUBDIRS= certDecode nisccSimpleClient skipThisNisccCert nisccCertVerify + +# default SRCROOT for clean target +SRCROOT ?= $(shell pwd) + +first: + @foreach i in $(SUBDIRS); \ + echo "=== Making $$i ==="; \ + cd $$i || exit 1; \ + make || exit 1; \ + cd ..; \ + end + +build: first + +sphinx: + make "SPHINX=-DSPHINX" + +install: first + +# this module doesn't need to install any headers +installhdrs: + +installsrc: + +clean: + @foreach i in $(SUBDIRS); \ + echo "=== Cleaning $$i ==="; \ + cd $$i || exit 1; \ + make clean || exit 1; \ + cd ..; \ + end diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/README.txt b/SecurityTests/clxutils/NISCC/TLS_SSL/README.txt new file mode 100644 index 00000000..5a58c9d9 --- /dev/null +++ b/SecurityTests/clxutils/NISCC/TLS_SSL/README.txt @@ -0,0 +1,214 @@ + Testing the NISCC SSL Certs + Last Update 12 Nov 2003 by dmitch + +Introduction +------------ +Per 3479950, the British NISCC has discovered a vulnerability in almost +all existing SSL implementation which can result in a Denial of Service +attack when certain badly formatted DER elements are sent by the client +the the server. Specifically the badly formatted element is the client +cert. NISCC has provided a huge array of test certs to verify this +problem. They've distrubuted this set of certs on a CD. + +This directory contains some of that CD, plus some X-specific tools +to test and verify. The bulk of the CD is in the form of 6 large tarred +and zipped bundles of bad certs. Those .tar.gz files are not in the +CVS repositoty because they are so big. When those files are expanded, +they result in hundreds of thousands of (bad) certs. Those certs are +not in the CVS repository either. + +Details of the failures we're testing for +----------------------------------------- +As of this writing, there are three specific bugs in the SecurityNssAsn1 +library which can all cause crashes when an app attempts to decode +certain badly formatted DER. All bugs are in +SecurityNssAsn1/nssDER/Source/secasn1d.c. + +First, when doing an SEC_ASN1_SAVE operation (e.g., saving the +still-encoded subject and issuer names in NSS_TBSCertificate.derIssuer and +NSS_TBSCertificate.derSubject), the code allocates a SECItem for the +whole blob solely based upon the length of the blob indicated in its +enclosing DER sequence or set. However when traversing the actual bits +being saved, each element is copied to the pre-allocated buffer according +to the length field of that element. Corruption and crash can result if +those inner length fields are bad and end up adding up to a size larger than +the preallocated SECItem buffer. The solution is to track the allocated size +of the buffer in sec_asn1d_state_struct.dest_alloc_len, which gets inherited +from parent to child state as does the dest field itself. Whenever an item +is appended to the dest SECItem, possible overflow is checked and the op +aborts if an overflow would result. + +Second, the sec_asn1d_reuse_encoding() routine is called after a +(successful) SEC_ASN1_SAVE op to "back up" to the forked location and +resume decoding it "for real", using the saved-off buffer - NOT the +caller's input. There was a bug here in that a "needBytes" error in the +sec_asn1d_reuse_encoding()'s call to SEC_ASN1DecoderUpdate() was ignored +and thrown out by the calling SEC_ASN1DecoderUpdate(), and processing +proceeds, with possibly hazardous and unpredicatable results. However +a "needBytes" error in the SEC_ASN1DecoderUpdate actually +called by sec_asn1d_reuse_encoding() must be fatal since all the data +is already present - we're not streaming when that update is called +because all of the data is already present in the saved-off buffer. The +solution is for sec_asn1d_reuse_encoding to detect the needBytes status and +convert it into decodeError, thus aborting the caller immediately. (Note +that this generally did not result in a crash, but in undetected decoding +errors.) + +The third bug involved the behavior of the decoding engine if incoming +encoded data claimed to have a very large length. Two problems can occur +in sec_asn1d_prepare_for_contents() in such a case. First of course is the +result of trying to malloc the large size. If state->contents_length is +2**32-1, for example, that malloc will almost certainly either fail or +take much longer than is appropriate. Then there is some arithmetic +involving appending subitems to the alloc_len which can result in +integer overflow: + + for (subitem = state->subitems_head; + subitem != NULL; subitem = subitem->next) + alloc_len += subitem->len; + } + +This bug is avoided by placing a somewhat arbitrary, but perfectly reasonable, +restriction in sec_asn1d_parse_more_length() - the routine which parses +such a huge length - that a 32-bit length value with the m.s. bit set is +invalid. + + +Testing overview +---------------- +There are two flavors of testing provided here. One uses a custom SSL +client, nisccSimpleClient, which performs actual SSL transactions with +an SSL server. The SSL server uses a good cert and requires client +authentication. The SSL client uses a bad cert. Both are based on +SecureTransport. A failure is indicated by the server crashing and +failing to respond to any more client requests. + +The other method of testing focusses exlusively on the failure mode, +which is the decoding and parsing of the bad certs. (The gross failure +mode in an SSL server noted in the previous paragraph is always caused +by the server crashing during the decoding of the client cert.) This testing +is performed by a program called certDecode which simply attempts to decode +every cert in cwd. This is way, way faster than setting up actual SSL +clients and doing SSL transactions. As a result, the entire suite of +"bad" client certs provided by NISCC (about 200,000 certs) has in fact +been verified by this program. Resources to perform 200,000 SSL client +trasnactions have not been marshalled as of this writing. In the opinion +of this author, simply verifying that a process can attempt to decode the +bad certs, without crashing, is sufficient for verifying that the +problem has been solved. + +Building the test programs +-------------------------- +The nisccSimpleClient program requires the presence of both the +clxutils/clAppUtils directory and the library it builds. The other +programs - certDecode and skipThisNisccCert - just link against +libCdsaUtils.a. None of these build in a way which is compatible with +Jasper Makefiles or PB project files. All you need to do is to set the +LOCAL_BUILD_DIR environment variable to point to the place where the +executables go. YOu can build each program individually by cd'ing to +the program directory and typing 'make', or just do a 'make' from +here (which is assumed to be clxutils/NISCC/TLS_SSL), which builds +all three. + +Testing using certDecode +------------------------ +The certDecode program is a standalone executable which uses the +SecurityNssAsn1 library to simply attempt to decode either every cert +in cwd, or the single cert specified in the cmd line. Build it by +doing 'make' in its directory. You must have the $LOCAL_BUILD_DIR +environment set. + +You need to obtain and untar one of the NISCC cert bundles. The two +of main concern are simple_client.tar.gz and resigned_client.tar.gz. +Each one of these explodes into about 100,000 certs taking up about +200 MB of disk space. To run the test, cd to the directory containing +100,000 certs and just run "certDecode" with no args. THe result will look +something like this: + + % tower.local:simple_client> certDecode + ....00000001...00000002...00000003...00000004...00000005... + 00000006...00000007...00000008...00000009...00000010...00000011... + 00000012...00000013...00000014...00000015...00000016...00000017... + ...etc.... + +It takes about 30 minutes to run thru all 100000 certs. Two things +will happen: either the program will crash, or you'll see this at the +end: + + 00106148...00106149...00106150...00106151...00106152...00106153... + 00106154...00106155...00106156...00106157...00106158...00106159... + 00106160 + certDecode did not crash. + % + +Test using nisccSimpleClient +---------------------------- + +WARNING this hasn't been tested in a long time (as of 7/18/06). The +nisccSimpleClient builds as of this date but the status of rest of this +is unknown. Stick to the certDecode test, above, which was verified as +of 7/18/06. + +This is much more complicated and takes way longer than the certDecode +test - so long that I still haven't run it with all 200,000 NISCC certs. +But to get started here's what you need to do. + +First you need to build the sslServer program, in clxutils/sslServer. See +the README in clxutils for build instructions. + +You also need the cspxutils/dbTool program. Your PATH variable needs +to include the directory where its executable lives (generally, this is +the same as your LOCAL_BUILD_DIR env var.) + +Then you need to build a custom Security.framework because certain errors +introduced by this test will cause the stock SecureTransport library to +(properly) abort client-side transactions before you get started due to +badly formatted certs. The tag for this Security.framework NISCC_ASN1; +that's a branch off of the PantherGM Security tree. Build the tree and +either install it or make sure your DYLD_FRAMEWORK_PATH env var points +to it for all subsequent testing. + +Now set up the SSL server keychain using the (good) NISCC-supplied server +cert and key. In the NISCC/TLS_SSL/testcases directory do the following: + + % rm -f ~/Library/Keychains/nisccServer + % certtool i server_crt.pem k=nisccServer r=server_key.pem c + +Run the sslServer app from the NISCC/TLS_SSL/testcases directory: + + % sslServer l k=nisccServer P=1200 a rootca.crt u=t + +The "a rootca.crt" tells SecureTransport that the cert which signed the +server's cert is a trusted root cert. The "u=t" tells the server to +request client authentication. If all is well, this program just keeps +on running, serving SSL requests, spewing forth to stdout (do not have +an unlimited scrollback buffer in your Terminal window or your root disk +will fill up.) + +Assuming that you'cve cd'd to the directory containing the nisccSslTest +script (clxutils/NISCC/TLS_SSL/) and that the directory containing the +untarred simple_client certs is in ./testcases/simple_client, just run +the nisccSslTest script with one argument, the port number you supplied +to the sslServer program above: + + % nisccSslTest 1200 + +This assumes that the following executables are accessible via your +PATH variable: dbTool, nisccSimpleClient, and skipThisNisccCert. + +When this is running OK you'll see an endless spew on stdout like this: + + cert 00001012... + ...DB /Volumes/Data_and_Apps/home/dmitch/Library/Keychains/nisccClient wiped clean + Starting nisccSimpleClient; args: localhost 1200 nisccClient + ===== nisccSimpleClient test PASSED ===== + cert 00001013... + ...DB /Volumes/Data_and_Apps/home/dmitch/Library/Keychains/nisccClient wiped clean + Starting nisccSimpleClient; args: localhost 1200 nisccClient + ===== nisccSimpleClient test PASSED ===== + cert 00001014... + ...DB /Volumes/Data_and_Apps/home/dmitch/Library/Keychains/nisccClient wiped clean + Starting nisccSimpleClient; args: localhost 13 1200 01 nisccClient + +...again, do not have an unlimited scrollback buffer in your Terminal +window or your root disk will fill up. diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/SSL_TLS.pdf b/SecurityTests/clxutils/NISCC/TLS_SSL/SSL_TLS.pdf new file mode 100755 index 0000000000000000000000000000000000000000..0b988e4f9d73d77e42909eeab13ab1e12619615f GIT binary patch literal 110436 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%0A@c35ib7?tbI67{UBhALYmf$UG6i={1E4b zO|a$`0NgEq55)YWRlYy-eqQN-kez-dVuTuiTOVYNUoQjH3oBNitxbJ^tI*zT4Zrt4 zlr;XhI=)09D9Yma|7ROa1Kc-Ih=L8A)L;_~(?$cF7X*

!&K2!er|rUdl+hnViT$ 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/certDecode/Makefile b/SecurityTests/clxutils/NISCC/TLS_SSL/certDecode/Makefile new file mode 100644 index 00000000..d9a1a16a --- /dev/null +++ b/SecurityTests/clxutils/NISCC/TLS_SSL/certDecode/Makefile @@ -0,0 +1,44 @@ +EXECUTABLE=certDecode +# C++ source (with .cpp extension) +CPSOURCE= certDecode.cpp +# C source (.c extension) +CSOURCE= +OFILES = $(CSOURCE:%.c=%.o) $(CPSOURCE:%.cpp=%.o) + +LOCAL_BUILD= $(shell echo $(LOCAL_BUILD_DIR)) + +# +# Executable in build folder +# +BUILT_TARGET= $(LOCAL_BUILD)/$(EXECUTABLE) + +CC=c++ + +FRAMEWORKS= -framework Security +FRAME_SEARCH= -F$(LOCAL_BUILD) +FINCLUDES= +PINCLUDES= +CINCLUDES= $(FINCLUDES) $(PINCLUDES) +WFLAGS= -Wno-four-char-constants -Wno-deprecated-declarations +CFLAGS= -g $(CINCLUDES) $(WFLAGS) $(FRAME_SEARCH) + +# +# This assumes final load with cc, not ld +# +LIBS= -lstdc++ +LIBPATH= -L$(LOCAL_BUILD) +LDFLAGS= $(LIBS) $(LIBPATH) $(FRAME_SEARCH) -lsecurity_cdsa_utils + +first: $(BUILT_TARGET) + +$(BUILT_TARGET): $(OFILES) + cc -o $(BUILT_TARGET) $(OFILES) $(FRAMEWORKS) $(LDFLAGS) + +clean: + rm -f *.o $(BUILT_TARGET) + +.c.o: + $(CC) $(CFLAGS) -c -o $*.o $< + +.cpp.o: + $(CC) $(CFLAGS) -c -o $*.o $< diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/certDecode/certDecode.cpp b/SecurityTests/clxutils/NISCC/TLS_SSL/certDecode/certDecode.cpp new file mode 100644 index 00000000..22c80bfc --- /dev/null +++ b/SecurityTests/clxutils/NISCC/TLS_SSL/certDecode/certDecode.cpp @@ -0,0 +1,163 @@ +/* + * Attempt to decode either one file, or every file in cwd, + * as a cert. Used to study vulnerability to NISCC cert DOS attacks. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +static void usage(char **argv) +{ + printf("usage: %s [-l(oop))] [certFile]\n", argv[0]); + exit(1); +} + +/* + * Known file names to NOT parse + */ +static const char *skipTheseFiles[] = +{ + /* standard entries */ + ".", + "..", + "CVS", + ".cvsignore", + /* the certs we know crash */ + #if 0 + "00000668", + "00000681", + "00001980", + "00002040", + "00002892", + "00007472", + "00008064", + "00008656", + "00009840", + "00010432", + "00011614", // trouble somewhere in this neighborhood + "00011615", + "00011616", + #endif + NULL +}; + +/* returns false if specified fileName is in skipTheseFiles[] */ +static bool shouldWeParse( + const char *fileName) // C string +{ + for(const char **stf=skipTheseFiles; *stf!=NULL; stf++) { + const char *tf = *stf; + if(!strcmp(fileName, *stf)) { + return false; + } + } + return true; +} + +/* + * Just try to decode - if SecAsn1Decode returns, good 'nuff. + * Returns true if it does (i.e. ignore decode error; we're trying + * to detect a crash when the decoder should return an error). + */ +bool decodeCert( + const void *certData, + size_t certDataLen) +{ + SecAsn1CoderRef coder = NULL; + NSS_Certificate nssCert; + NSS_SignedCertOrCRL certOrCrl; + + SecAsn1CoderCreate(&coder); + + /* first the full decode */ + memset(&nssCert, 0, sizeof(nssCert)); + SecAsn1Decode(coder, certData, certDataLen, kSecAsn1SignedCertTemplate, &nssCert); + + /* now the "just TBS and sig" decode - this is actually harder + * due to nested SEC_ASN1_SAVE ops */ + memset(&certOrCrl, 0, sizeof(NSS_SignedCertOrCRL)); + SecAsn1Decode(coder, certData, certDataLen, kSecAsn1SignedCertOrCRLTemplate, &certOrCrl); + + SecAsn1CoderRelease(coder); + return true; +} + +int main(int argc, char **argv) +{ + bool quiet = false; + unsigned char *certData; + unsigned certDataLen; + bool loop = false; + int filearg = 1; + + if(argc > 3 ) { + usage(argv); + } + if((argc > 1) && (argv[1][0] == '-')) { + switch(argv[1][1]) { + case 'l': + loop = true; + break; + default: + usage(argv); + } + filearg++; + argc--; + } + if(argc == 2) { + /* read & parse one file */ + char *oneFile = argv[filearg]; + if(readFile(oneFile, &certData, &certDataLen)) { + printf("\n***Error reading file %s. Aborting.\n", oneFile); + exit(1); + } + do { + if(!quiet) { + printf("...%s", oneFile); + fflush(stdout); + } + if(!decodeCert(certData, certDataLen)) { + printf("\n***GOT AN EXCEPTION ON %s\n", oneFile); + exit(1); + } + } while(loop); + free(certData); + exit(0); + } + DIR *dir = opendir("."); + if(dir == NULL) { + printf("Huh? Can't open . as a directory.\n"); + exit(1); + } + struct dirent *de = readdir(dir); + while(de != NULL) { + char filename[MAXNAMLEN + 1]; + memmove(filename, de->d_name, de->d_namlen); + filename[de->d_namlen] = '\0'; + if(shouldWeParse(filename)) { + if(!quiet) { + printf("...%s", filename); + fflush(stdout); + } + if(readFile(filename, &certData, &certDataLen)) { + printf("\n***Error reading file %s. Aborting.\n", filename); + exit(1); + } + if(!decodeCert(certData, certDataLen)) { + printf("\n***GOT AN EXCEPTION ON %s\n", filename); + exit(1); + } + free(certData); + } + de = readdir(dir); + } + closedir(dir); + printf("\ncertDecode did not crash.\n"); + return 0; +} + diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/dmitchNotes b/SecurityTests/clxutils/NISCC/TLS_SSL/dmitchNotes new file mode 100644 index 00000000..90684381 --- /dev/null +++ b/SecurityTests/clxutils/NISCC/TLS_SSL/dmitchNotes @@ -0,0 +1,121 @@ +testing the NISCC test cases + +-- testing client certs, use good server cert -------- + +1. Set up server KC + + % rm -f ~/Library/Keychains/nisccServer + % certtool i server_crt.pem k=nisccServer r=server_key.pem c + +2. Run server (from testcases dir) + + % sslServer l k=nisccServer P=1300 a rootca.crt u=t + + -- not u=t --> try auth + +3. Run client no auth + + % sv localhost P=1300 H a rootca.crt + + -- note 'H' - disable host name verify since server common name = + "Simple Server" + +4. Set up client keychain + + % rm -f ~/Library/Keychains/nisccClient + % certtool i client_crt.pem k=nisccClient r=client_key.pem c + +5. Run client w/auth + + % sv localhost P=1300 H a rootca.crt k=nisccClient + +6. Bad client + + # just once + % pemtool d client_key.pem client_key.der + # + % rm -f ~/Library/Keychains/nisccClient + % certtool i simple_client/00035377 k=nisccClient r=client_key.der c + % sv localhost P=1300 H k=nisccClient x + + ...note 'x' avoids client checking its own bogus cert, and we don't have to specify + an anchor + + result on client side = errSSLPeerCertUnknown + clientCertState = ClientCertRejected + + result on server side = errSSLXCertChainInvalid + clientCertState = ClientCertRejected + +7. Mods needed to uses these certs + + -- modified dbTool to allow importing a bad cert (via DL/DB, not Sec*) + -- wrote simple client app, clxutils/NISCC/TLS_SSL/nisccSimpleClient + + -- also SecureTransport needs the following mod to ignore bad certs on client side + +=================================================================== +RCS file: /cvs/root/Security/SecureTransport/sslKeychain.cpp,v +retrieving revision 1.5 +diff -u -r1.5 sslKeychain.cpp +--- sslKeychain.cpp 2003/04/25 19:40:18 1.5 ++++ sslKeychain.cpp 2003/11/10 21:20:14 +@@ -174,6 +174,11 @@ + /* FIXME = release keyRef? */ + + /* obtain public key from cert */ ++ /* ++ * FIXME : THIS IS TOTALLY UNNECESSARY WHEN PARSING OUR OWN CERTS, except ++ * for the "separate signing and encryptionj certs" case. For now, to ++ * facilitate NISCC testing, we ignore errors here. ++ */ + ortn = SecCertificateGetCLHandle(certRef, &clHand); + if(ortn) { + sslErrorLog("parseIncomingCerts: SecCertificateGetCLHandle err %d\n", +@@ -183,10 +188,12 @@ + certData.Data = thisSslCert->derCert.data; + certData.Length = thisSslCert->derCert.length; + crtn = CSSM_CL_CertGetKeyInfo(clHand, &certData, pubKey); ++ #if 0 + if(crtn) { + sslErrorLog("parseIncomingCerts: CSSM_CL_CertGetKeyInfo err\n"); + return (OSStatus)crtn; + } ++ #endif + + /* obtain keychain from key, CSP handle from keychain */ + ortn = SecKeychainItemCopyKeychain((SecKeychainItemRef)keyRef, &kcRef); + +........ + +...with this in place cert 00070004 causes anything parsing it to get a seg fault. + +........... + +problems found: + +1. Processing SEC_ASN1_SAVE, the destination item is mallocd once, with the length + of the top-level item to be saved. However data gets added to this item on a + leaf-by-leaf basis so that if the sizes of the leaves adds up to greater than + the stated/mallocd len of the otp-level item, overflow. + + -- verified by disabling the SAVE in TBS_Cert + -- fixed using sec_asn1d_state.dest_alloc_len field to track alloc size in + aggregate items + +.............. + +certs known to crash the Panther Security.framework: + + "00000668", + "00000681", + "00001980", + "00002040", + "00007472", + "00008064", + "00008656", + "00009840", + "00010432", + "00011614", + "00011615", + "00011616", diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/nisccCertVerify/Makefile b/SecurityTests/clxutils/NISCC/TLS_SSL/nisccCertVerify/Makefile new file mode 100644 index 00000000..30455ce4 --- /dev/null +++ b/SecurityTests/clxutils/NISCC/TLS_SSL/nisccCertVerify/Makefile @@ -0,0 +1,44 @@ +EXECUTABLE=nisccCertVerify +# C++ source (with .cpp extension) +CPSOURCE= nisccCertVerify.cpp +# C source (.c extension) +CSOURCE= +OFILES = $(CSOURCE:%.c=%.o) $(CPSOURCE:%.cpp=%.o) + +LOCAL_BUILD= $(shell echo $(LOCAL_BUILD_DIR)) + +# +# Executable in build folder +# +BUILT_TARGET= $(LOCAL_BUILD)/$(EXECUTABLE) + +CC= /usr/bin/cc + +FRAMEWORKS= -framework Security -framework CoreFoundation +FRAME_SEARCH= -F$(LOCAL_BUILD) +FINCLUDES= +PINCLUDES= +CINCLUDES= $(FINCLUDES) $(PINCLUDES) +WFLAGS= -Wno-four-char-constants -Wno-deprecated-declarations +CFLAGS= -g $(CINCLUDES) $(WFLAGS) $(FRAME_SEARCH) + +# +# This assumes final load with cc, not ld +# +LIBS= -lstdc++ -lCdsaUtils +LIBPATH= -L$(LOCAL_BUILD) +LDFLAGS= $(LIBS) $(LIBPATH) $(FRAME_SEARCH) + +first: $(BUILT_TARGET) + +$(BUILT_TARGET): $(OFILES) + cc -o $(BUILT_TARGET) $(FRAMEWORKS) $(OFILES) $(LDFLAGS) + +clean: + rm -f *.o $(BUILT_TARGET) + +.c.o: + $(CC) $(CFLAGS) -c -o $*.o $< + +.cpp.o: + $(CC) $(CFLAGS) -c -o $*.o $< diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/nisccCertVerify/nisccCertVerify.cpp b/SecurityTests/clxutils/NISCC/TLS_SSL/nisccCertVerify/nisccCertVerify.cpp new file mode 100644 index 00000000..948cdcf5 --- /dev/null +++ b/SecurityTests/clxutils/NISCC/TLS_SSL/nisccCertVerify/nisccCertVerify.cpp @@ -0,0 +1,194 @@ +/* + * Attempt to verify either one cert file, or every file in cwd, + * with specified issuer cert. Used to study vulnerability to + * NISCC cert DOS attacks. + */ +#include +#include +#include +#include +#include +#include +#include + +static void usage(char **argv) +{ + printf("usage: %s [-v(erbose)] issuerCertFile [certFile]\n", argv[0]); + exit(1); +} + +/* + * Known file names to NOT parse + */ +static const char *skipTheseFiles[] = +{ + /* standard entries */ + ".", + "..", + "CVS", + ".cvsignore", + NULL +}; + +/* returns false if specified fileName is in skipTheseFiles[] */ +static bool shouldWeParse( + const char *fileName) // C string +{ + for(const char **stf=skipTheseFiles; *stf!=NULL; stf++) { + const char *tf = *stf; + if(!strcmp(fileName, *stf)) { + return false; + } + } + return true; +} + +/* + * Just try to verify. Returns true on any reasonable outcome. + */ +static bool vfyCert( + CSSM_CL_HANDLE clHand, + CSSM_CC_HANDLE ccHand, + const unsigned char *certData, + unsigned certDataLen, + bool verbose) +{ + CSSM_DATA cdata = {certDataLen, (uint8 *)certData}; + CSSM_RETURN crtn; + + crtn = CSSM_CL_CertVerifyWithKey(clHand, ccHand, &cdata); + + /* hard-coded list of acceptable outcomes */ + switch(crtn) { + case CSSM_OK: + if(verbose) { + printf("-ok-"); + } + return true; + case CSSMERR_CL_VERIFICATION_FAILURE: + if(verbose) { + printf("-vfy_fail-"); + } + return true; + case CSSMERR_CL_UNKNOWN_FORMAT: + if(verbose) { + printf("-format-"); + } + return true; + default: + cuPrintError("CSSM_CL_CertVerifyWithKey", crtn); + return false; + } + return true; +} + +int main(int argc, char **argv) +{ + bool quiet = false; + unsigned char *certData; + unsigned certDataLen; + unsigned char *issuerData; + unsigned issuerDataLen; + DIR *dir; + struct dirent *de; + bool verbose = false; + int filearg = 1; + + if((argc < 2 ) || (argc > 4)) { + usage(argv); + } + if(argv[1][0] == '-') { + switch(argv[1][1]) { + case 'v': + verbose = true; + break; + default: + usage(argv); + } + filearg++; + argc--; + } + + CSSM_CSP_HANDLE cspHand = cuCspStartup(CSSM_TRUE); + CSSM_CL_HANDLE clHand = cuClStartup(); + if((cspHand == 0) || (clHand == 0)) { + exit(1); + } + + /* read issuer cert, extract its public key for quick verify */ + char *fn = argv[filearg++]; + if(readFile(fn, &issuerData, &issuerDataLen)) { + printf("\n***Error reading file %s. Aborting.\n", fn); + exit(1); + } + CSSM_DATA issuerCert = {issuerDataLen, issuerData}; + CSSM_KEY_PTR issuerPubKey; + CSSM_RETURN crtn = CSSM_CL_CertGetKeyInfo(clHand, &issuerCert, + &issuerPubKey); + if(crtn) { + cuPrintError("CSSM_CL_CertGetKeyInfo", crtn); + exit(1); + } + + /* a reusable signature context */ + CSSM_CC_HANDLE ccHand; + crtn = CSSM_CSP_CreateSignatureContext(cspHand, + CSSM_ALGID_SHA1WithRSA, + NULL, // AccessCred + issuerPubKey, + &ccHand); + if(crtn) { + cuPrintError("CSSM_CSP_CreateSignatureContext", crtn); + exit(1); + } + + if(argc == 3) { + /* read & parse one file */ + char *fn = argv[filearg++]; + if(!quiet) { + printf("...reading %s\n", fn); + } + if(readFile(fn, &certData, &certDataLen)) { + printf("\n***Error reading file %s. Aborting.\n", fn); + exit(1); + } + if(!vfyCert(clHand, ccHand, certData, certDataLen, verbose)) { + printf("\n***GOT AN EXCEPTION ON %s\n", fn); + exit(1); + } + goto done; + } + dir = opendir("."); + if(dir == NULL) { + printf("Huh? Can't open . as a directory.\n"); + exit(1); + } + de = readdir(dir); + while(de != NULL) { + char filename[MAXNAMLEN + 1]; + memmove(filename, de->d_name, de->d_namlen); + filename[de->d_namlen] = '\0'; + if(shouldWeParse(filename)) { + if(!quiet) { + printf("...%s", filename); + fflush(stdout); + } + if(readFile(filename, &certData, &certDataLen)) { + printf("\n***Error reading file %s. Aborting.\n", filename); + exit(1); + } + if(!vfyCert(clHand, ccHand, certData, certDataLen, verbose)) { + printf("\n***GOT AN EXCEPTION ON %s\n", filename); + exit(1); + } + free(certData); + } + de = readdir(dir); + } + closedir(dir); +done: + printf("\nisccCertVerify did not crash.\n"); + free(issuerData); + return 0; +} + diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/nisccSimpleClient/Makefile b/SecurityTests/clxutils/NISCC/TLS_SSL/nisccSimpleClient/Makefile new file mode 100644 index 00000000..91e42f8a --- /dev/null +++ b/SecurityTests/clxutils/NISCC/TLS_SSL/nisccSimpleClient/Makefile @@ -0,0 +1,182 @@ +# name of executable to build +EXECUTABLE=nisccSimpleClient +# C++ source (with .cpp extension) +CPSOURCE= nisccSimpleClient.cpp +# C source (.c extension) +CSOURCE= + +# +# Differs from standard clxutils since ../ is not clxutils.... +# +CL_UTIL_DIR=../../../ + +OUR_INCLUDES=-I$(CL_UTIL_DIR)/clAppUtils + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= -framework CoreFoundation +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +#include ../Makefile.cdsa +############################################################################ +# We just include our custom version of Makefile.cdsa intact right here.... +############################################################################ +# +# Common makefile fragment for dmitch's clxutils, nisccSimpleClient variant +# This is -included from project-specific Makefiles, assumed +# to be one directory down from this file. +# +# See Makefile.template for sample project-specific Makefile. +# + +# Defaults for variables provided by buildit +# +# Object files written to '.' unless OBJROOT specified +# +OBJROOT ?= . +SRCROOT ?= . +# +# Executables written to SYMROOT if specified, else to LOCAL_BUILD_DIR +# env var if specified, else to '.'. +# +SYMROOT ?= $(shell echo $(LOCAL_BUILD_DIR)) +LOCAL_BUILD=$(SYMROOT) +ifeq "" "$(LOCAL_BUILD)" + LOCAL_BUILD = . +endif + +# independent of SYMROOT +CLEAN_DIR=$(shell echo $(LOCAL_BUILD_DIR)) +ifeq "" "$(CLEAN_DIR)" + CLEAN_DIR = . +endif + +# +# DSTROOT only used for install +$ +DSTROOT ?= "" + +INSTALLDIR := $(DSTROOT)/usr/local/bin + +CLAPP_UTILS= ../../.. +UTIL_LIB_SRC= ../../../clAppUtils + +OFILES= $(CSOURCE:%.c=$(OBJROOT)/%.o) $(CPSOURCE:%.cpp=$(OBJROOT)/%.o) + +# +# Assume final load with cc, not ld +# +STD_LIBS=-lclutils -lcsputils +STD_LIBPATH= -L$(LOCAL_BUILD) $(UTILLIB_PATH) -L$(UTIL_LIB_SRC) +ALL_LIBS= $(STD_LIBS) $(PROJ_LIBS) +ALL_LIBPATHS= $(STD_LIBPATH) $(PROJ_LIBPATH) +PRIV_FRAMEWORK_PATH= /System/Library/PrivateFrameworks + +# +# Override this from the make command line to add e.g. -lMallocDebug +# +CMDLINE_LDFLAGS= + +ALL_LDFLAGS= $(CMDLINE_LDFLAGS) $(ALL_LIBS) $(ALL_LIBPATHS) $(PROJ_LDFLAGS) \ + -F$(LOCAL_BUILD) -F$(PRIV_FRAMEWORK_PATH) + +CC=c++ + +STD_FRAMEWORKS= -framework Security -framework CoreFoundation -framework security_cdsa_utils +ALL_FRAMEWORKS= $(STD_FRAMEWORKS) $(PROJ_FRAMEWORKS) + +# +# to get to headers in frameworks +# +STD_FINCLUDES= -F$(LOCAL_BUILD) -F$(PRIV_FRAMEWORK_PATH) +# +# the common headers for csputils +# +STD_INCLUDES= -I$(CLAPP_UTILS) $(UTILLIB_HDRS) -F$(PRIV_FRAMEWORK_PATH) +ALL_INCLUDES= $(STD_INCLUDES) $(PROJ_INCLUDES) +CINCLUDES= $(STD_FINCLUDES) $(ALL_INCLUDES) + +###WFLAGS= -Wno-four-char-constants -Wall -Werror -Wno-format +WFLAGS= -Wno-four-char-constants -Wall -Wno-format -Wno-deprecated-declarations + +STD_CFLAGS= -g $(VERBOSE) +DEBUG_CFLAGS= + +ALL_CFLAGS= $(CINCLUDES) $(STD_CFLAGS) $(PROJ_CFLAGS) $(WFLAGS) $(DEBUG_CFLAGS) + +# +# Executable in build folder +# +BUILT_TARGET= $(LOCAL_BUILD)/$(EXECUTABLE) + +first: UTIL_LIB $(PROJ_DEPENDS) $(BUILT_TARGET) + +build: first + +install: build + install -d -m 0755 $(INSTALLDIR) + install -p -m 0755 $(BUILT_TARGET) $(INSTALLDIR) + +installhdrs: + +# +# Executable might be in . if no LOCAL_BUILD_DIR specified +# +clean: + rm -f $(BUILT_TARGET) $(EXECUTABLE) + cd $(SRCROOT); rm -f $(OFILES) *.o + cd $(LOCAL_BUILD); rm -f $(EXECUTABLE) $(OTHER_TO_CLEAN) + rm -f $(CLEAN_DIR)/$(EXECUTABLE) + +UTIL_LIB: + (cd $(UTIL_LIB_SRC); make) + +$(BUILT_TARGET): $(OFILES) + $(CC) -o $(BUILT_TARGET) $(ALL_FRAMEWORKS) $^ $(ALL_LDFLAGS) + +$(OBJROOT)/%.o: %.c + $(CC) $(ALL_CFLAGS) -c -o $(OBJROOT)/$*.o $< + +$(OBJROOT)/%.o: %.cpp + $(CC) $(ALL_CFLAGS) -c -o $(OBJROOT)/$*.o $< + diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/nisccSimpleClient/nisccSimpleClient.cpp b/SecurityTests/clxutils/NISCC/TLS_SSL/nisccSimpleClient/nisccSimpleClient.cpp new file mode 100644 index 00000000..19c44cbb --- /dev/null +++ b/SecurityTests/clxutils/NISCC/TLS_SSL/nisccSimpleClient/nisccSimpleClient.cpp @@ -0,0 +1,177 @@ +/* + * nisccSimpleClient.cpp - just do one SSL client session expecting + * errSSLPeerCertUnknown and ClientCertRejected + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* skip certs larger than this - ST can't fragment protocol msgs (yet) */ +#define MAX_CERT_SIZE 16000 + +static void usage(char **argv) +{ + printf("Usage: %s hostname port keychain [q(uiet)]\n", argv[0]); + exit(1); +} + +#define IGNORE_SIGPIPE 1 +#if IGNORE_SIGPIPE +#include + +void sigpipe(int sig) +{ +} +#endif /* IGNORE_SIGPIPE */ + +SslAppTestParams clientDefaults = +{ + NULL, // hostName - user-provided + true, // skipHostNameCHeck + 0, // port - user-provided + NULL, NULL, // RingBuffers + false, // noProtSpec + kTLSProtocol1, + NULL, // acceptedProts - not used in this test + NULL, // myCerts - user-provided + NULL, // password - same as myCerts + false, // idIsTrustedRoot + true, // disableCertVerify - SPECIAL FOR THIS TEST + NULL, // anchorFile - not needed - right? + false, // replaceAnchors + kAlwaysAuthenticate, + false, // resumeEnable + NULL, // ciphers + false, // nonBlocking + NULL, // dhParams + 0, // dhParamsLen + errSSLPeerCertUnknown, // expectRtn + kTLSProtocol1, // expectVersion + kSSLClientCertRejected, + SSL_CIPHER_IGNORE, + false, // quiet - user-provided + false, // silent + false, // verbose + NULL, // lock + 0, // clientDone + false, // serverAbort + /* returned */ + kSSLProtocolUnknown, + SSL_NULL_WITH_NULL_NULL, + kSSLClientCertNone, + noHardwareErr + +}; + +static void testStartBanner( + char *testName, + int argc, + char **argv) +{ + printf("Starting %s; args: ", testName); + for(int i=1; i(errStr.c_str()); +} + + +int main(int argc, char **argv) +{ + int ourRtn = 0; + char *argp; + int errCount = 0; + + if(argc < 4) { + usage(argv); + } + + /* required args */ + clientDefaults.hostName = argv[1]; + clientDefaults.password = argv[1]; + clientDefaults.port = atoi(argv[2]); + clientDefaults.myCertKcName = argv[3]; + + /* optional args */ + for(int arg=4; arg /dev/null || exit(1) +foreach cert ( * ) + echo cert $cert... + skipThisNisccCert $cert + if($status == 1) then + echo "=skip=" + else + dbTool $FULL_CLIENT_KC D R + dbTool $FULL_CLIENT_KC i c=$cert k=../$CLIENT_KEY || exit(1) + nisccSimpleClient localhost $argv[1] $CLIENT_KC || exit(1) + endif +end +echo ===== NISCC SSL Test SUCCESS ===== + diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/skipThisNisccCert/Makefile b/SecurityTests/clxutils/NISCC/TLS_SSL/skipThisNisccCert/Makefile new file mode 100644 index 00000000..e4bd046a --- /dev/null +++ b/SecurityTests/clxutils/NISCC/TLS_SSL/skipThisNisccCert/Makefile @@ -0,0 +1,44 @@ +EXECUTABLE=skipThisNisccCert +# C++ source (with .cpp extension) +CPSOURCE= skipThisNisccCert.cpp +# C source (.c extension) +CSOURCE= +OFILES = $(CSOURCE:%.c=%.o) $(CPSOURCE:%.cpp=%.o) + +LOCAL_BUILD= $(shell echo $(LOCAL_BUILD_DIR)) + +# +# Executable in build folder +# +BUILT_TARGET= $(LOCAL_BUILD)/$(EXECUTABLE) + +CC= /usr/bin/cc + +FRAMEWORKS= +FRAME_SEARCH= -F$(LOCAL_BUILD) +FINCLUDES= +PINCLUDES= +CINCLUDES= $(FINCLUDES) $(PINCLUDES) +WFLAGS= -Wno-four-char-constants -Wno-deprecated-declarations +CFLAGS= -g $(CINCLUDES) $(WFLAGS) $(FRAME_SEARCH) + +# +# This assumes final load with cc, not ld +# +LIBS= -lstdc++ -lCdsaUtils -lnssasn1 +LIBPATH= -L$(LOCAL_BUILD) +LDFLAGS= $(LIBS) $(LIBPATH) $(FRAME_SEARCH) + +first: $(BUILT_TARGET) + +$(BUILT_TARGET): $(OFILES) + cc -o $(BUILT_TARGET) $(FRAMEWORKS) $(OFILES) $(LDFLAGS) + +clean: + rm -f *.o $(BUILT_TARGET) + +.c.o: + $(CC) $(CFLAGS) -c -o $*.o $< + +.cpp.o: + $(CC) $(CFLAGS) -c -o $*.o $< diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/skipThisNisccCert/skipThisNisccCert.cpp b/SecurityTests/clxutils/NISCC/TLS_SSL/skipThisNisccCert/skipThisNisccCert.cpp new file mode 100644 index 00000000..6e01e3a7 --- /dev/null +++ b/SecurityTests/clxutils/NISCC/TLS_SSL/skipThisNisccCert/skipThisNisccCert.cpp @@ -0,0 +1,104 @@ +/* + * skipThisNisccCert.cpp - decide whether to use specified NISCC cert + * in SSL client tests. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Currently, SecureTransport does not fragment protocol messages + * into record-size chunks. Max record size is 16K so our max cert + * size is a little less than that. + */ +#define MAX_CERT_SIZE (16 * 1024) + +static void usage(char **argv) +{ + printf("usage: %s file\n", argv[0]); + exit(1); +} + +/* + * Known file names to NOT parse + */ +static const char *skipTheseFiles[] = +{ + /* standard entries */ + ".", + "..", + "CVS", + /* the certs we know seem to be fine */ + #if 0 + /* handled OK by the client now */ + "00000023", + "00000098", + "00000116", + "00000117", + #endif + /* certs with undiagnosed problems */ + NULL +}; + +/* returns true if specified fileName is in skipTheseFiles[] */ +static bool shouldWeSkip( + const char *fullPath) // C string +{ + /* strip off leading path components */ + const char *lastSlash = NULL; + const char *cp; + for(cp=fullPath; *cp!=NULL; cp++) { + if(*cp == '/') { + lastSlash = cp; + } + } + if(lastSlash == NULL) { + /* no slashes, use full caller-specified filename */ + cp = fullPath; + } + else { + /* start one char after last '/' */ + cp++; + } + char fileName[MAXPATHLEN]; + strcpy(fileName, cp); + + for(const char **stf=skipTheseFiles; *stf!=NULL; stf++) { + const char *tf = *stf; + if(!strcmp(fileName, *stf)) { + return true; + } + } + return false; +} + +int main(int argc, char **argv) +{ + if(argc != 2 ) { + usage(argv); + } + + /* in hard-coded list of files to skip? */ + const char *filename = argv[1]; + if(shouldWeSkip(filename)) { + exit(1); + } + + /* file size too big? */ + struct stat sb; + if(stat(filename, &sb)) { + perror(filename); + exit(2); + } + if(sb.st_size > MAX_CERT_SIZE) { + exit(1); + } + + exit(0); +} + diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/testcases/client.crt b/SecurityTests/clxutils/NISCC/TLS_SSL/testcases/client.crt new file mode 100755 index 0000000000000000000000000000000000000000..adff3a42ae007432ee3bc521bb6015bf0d181f7f GIT binary patch literal 509 zcmXqLV*F{)#F)gy$Yj9F#;Mij(e|B}k&%^^!NAv$+klgeIh2J>n91GAP|iRG#NiSa z4bIFh$VpWQ%Fi!Ra4ap!$S=w)sf5Wh42ly=sQy5>xaI#=c=w9Y*wx~25s0?tWdJ01o|{95||AyZjp^}%^k zEOXeG?mG6yd&dp7&Oci(U9&RpSa~UI-!8G`%ySw#CY@@X+jV8{yy)F}(Q~+*GbMgK zv|N?qmUDIA+0Vh+#p2HmBt@5OW@2V!U_^EvFnF1P?s7ZE!22>hbQ zw>65d6>9H#IQhx{lTkOqY(j4p=NYp7VO#e)&Plg#rFE)P^VB8lr~ls<(4bws`S=V28sN&($+dRh^f+6zPc8t z1Dt?}lFEghiqyTHTe~h>oC-r}82aHks$@oN)xOR1Q!8^9=P(%+q_YA80RRC4fq?+A zf(G%R*AaPoB(_C0P*-Mh(^MtW9S4L;jP?rB9n+A|B>hC(ZFQ(DXW0;78II+xP@Dar(@2`r{I82D%8`(%=`8hU^gV+RN zXAU;dvPTuc!iTzoZskgv$lG0OqNbkhWak`($vAt13aa)>^+5tb0PaCp9q1vmzr>RS z#fJSUuFh+ySm!jof1?XA%Is>b-$bEz?H6woZG;!E)wvcziV4x$%8u6|EW|q^AJG8V z^8!Hthk8j)rgcvG6=iOg>6D29tRJURw3iNhRtNGiAy_Gu?iwt6=mP18J6@btS6VRB zI+m3N71}3}j$$Mdg(lwt0zg^&^ZVDJV)GiCEJ7|RkA$WXqZ4qyN|M@9a17)frfrNUmpfu{Hq v*^1o%kc)lkrn3+srv)y=_x7;=UbGOFE!OL-4TxJWf+Ci6rNB!kSND(ED literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/testcases/client_key.pem b/SecurityTests/clxutils/NISCC/TLS_SSL/testcases/client_key.pem new file mode 100755 index 00000000..da6c77da --- /dev/null +++ b/SecurityTests/clxutils/NISCC/TLS_SSL/testcases/client_key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDnT63C7VFJW3QC1Q3G6AYaH7iHXRsMZIcFsS03AqKJqW9ghZ3C +FbR1waAJkha44VAY+qX/4QJ2eXvBnhoEnAelusbsS7jYBon8tdLWOjeIqdJWvroW +pwOcgIiSyoWditS9nlu7LlucCkNpGPrhOapkRmzVvs3zUytzF+cwGRWkswIDAQAB +AoGBALGCBvGg1xF5eiS2RTVQV2Zy01Ql0h0HhEqM9grSHdOQ0CT9RNxtdagsZ9kQ +YBmO5r3Uk9EyZoZuodcqsgK5jm9dvS3qS8DEp/M7ubfpXhYya8x/u24W7kiRaBO9 +9ucoo90IwndRcia8D3gat6Y2ssHyjgSpndJZI0jC4fTg+AiBAkEA+InwEcUm76+K +0ThMiN4b2Uhi+Tk2j4PYBGFnDjbQskcVwcKHuoJu5UqayNtda6Kmnu1k5xyFyTh7 +gwqq9kr1QQJBAO5BWB3oIbO/xJMExYb9Ka7Oa6hY5zS9f6MLMcrsaq3fRKF37Rdv +E22EF6/VuRZCignR2sqO1yEsxDsiH9EA2PMCQQCHeklOpnVO+hVlbpbplIkBrB+n +UrSXDntWB/IxIVgple4aLHvoAumIO16cVldaMNM6lpUGFdonkY5iJBKFJt8BAkBZ ++/P716Bi8xqbLEIuKY+EphGjE3C/SpLaUXAM5B2mbZzOHy08nIcJ5cnMbzvoXFkm +PEwWFLzLmszCSLEbjuZhAkBUBdK70dVRqHhcxKnOTM+dgab4E9mK3P+Qi33pprMQ +IacFLsT39rEyOsgsmXO3xsbBy3FaXGYLsNpBl4FH/eVG +-----END RSA PRIVATE KEY----- diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/testcases/readme.txt b/SecurityTests/clxutils/NISCC/TLS_SSL/testcases/readme.txt new file mode 100755 index 00000000..3db83b45 --- /dev/null +++ b/SecurityTests/clxutils/NISCC/TLS_SSL/testcases/readme.txt @@ -0,0 +1,46 @@ +readme.txt This file. + +client.crt Binary DER certificate signed by the private key of rootca. +client_crt.pem PEM form of client.crt +client_key.pem PEM form of the private key corresponding to client.crt +simple_client.tar.gz Variations of client.crt in binary ~DER format. + Variations occur across the entire certificate. + 00000001-00106160 + tar file size: ~846M + tar.gz file size: ~10M +resigned_client.tar.gz Variations of client.crt in binary ~DER format. + Variations occur across the toBeSigned part of the certificate. + The signature block has been recreated. + 00000000-00099981 + tar file size: ~788M + tar.gz file size: ~22M + +server.crt Binary DER certificate signed by the private key of rootca. +server_crt.pem PEM form of server.crt +server_key.pem PEM form of the private key corresponding to server.crt +simple_server.tar.gz Variations of server.crt in binary ~DER format. + Variations occur across the entire certificate. + 00000001-00106167 + tar file size: ~844M + tar.gz file size: ~10M +resigned_server.tar.gz Variations of server.crt in binary ~DER format. + Variations occur across the toBeSigned part of the certificate. + The signature block has been recreated. + 00000000-00100068 + tar file size: ~789M + tar.gz file size: ~22M + +rootca.crt Binary Self-signed DER certificate. +rootca_crt.pem PEM form of rootca.crt +rootca_key.pem PEM form of the private key corresponding to rootca.crt +simple_rootca.tar.gz Variations of rootca.crt in binary ~DER format. + Variations occur across the entire certificate. + 00000001-00106190 + tar file size: ~862M + tar.gz file size: ~10M +resigned_rootca.tar.gz Variations of rootca.crt in binary ~DER format. + Variations occur across the toBeSigned part of the certificate. + The signature block has been recreated. + 00000000-00099959 + tar file size: ~806M + tar.gz file size: ~22M diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/testcases/rootca.crt b/SecurityTests/clxutils/NISCC/TLS_SSL/testcases/rootca.crt new file mode 100755 index 0000000000000000000000000000000000000000..d12da5ba97f1fed27af39eefaf28c50f9d09ee92 GIT binary patch literal 525 zcmXqLV&XJtVk}}}WH8`m!|uIF^=VQtPISJy$lA8olK3549gds=v~71X!eYioRdtyBwuHbZFwfU+dwSfe{b>Ev$M~} z7p$_F!}U@5lSg}~bIrGVx}9b_m0PCf$Dcp4R&m{(1FP&KSaYwiDoK6~IT+1&a_aVN z8NwysUt1n;W`4%0G23!S*vv|{wb5s`xiu#Xl`VSf%%S%vaDC?)ukS|5JnYt=nV1*hGgA932U zy=C`jiPmM@9=k6-mwzB4&M7k3vg+ywxzal^a- literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/testcases/rootca_crt.pem b/SecurityTests/clxutils/NISCC/TLS_SSL/testcases/rootca_crt.pem new file mode 100755 index 00000000..620f07e8 --- /dev/null +++ b/SecurityTests/clxutils/NISCC/TLS_SSL/testcases/rootca_crt.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICCTCCAXICAQAwDQYJKoZIhvcNAQEFBQAwTTELMAkGA1UEBhMCR0IxHjAcBgNV +BAoTFVNpbXBsZSBSb290IEF1dGhvcml0eTEeMBwGA1UEAxMVU2ltcGxlIFJvb3Qg +QXV0aG9yaXR5MB4XDTAyMTExODE3Mzc0MloXDTA3MTExODE3Mzc0MlowTTELMAkG +A1UEBhMCR0IxHjAcBgNVBAoTFVNpbXBsZSBSb290IEF1dGhvcml0eTEeMBwGA1UE +AxMVU2ltcGxlIFJvb3QgQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB +iQKBgQCnoMiNpA7im5ipCZI19GPXB12E5h27MBZQ/41z9c2bzV9wqjicCvEj8kiH +VUN89t4tiTa5I4SVb1/PxK0hrtzAqj9YBW3UBSIZ9VTBWwHJlbe2aBN09+s5x4MD +5gkomzm4Vpl5Bq1bzLZGg2MSdqLtQwgu4lGvicxK9zJjDAc78wIDAQABMA0GCSqG +SIb3DQEBBQUAA4GBAHX3Wl7HEGjAj4ooSeqG9kcn8aWR0GrT+3sL/UL+khKfJ66c +Qh/EQrS3hLvzGIWmC0i70ecf4pLjte52xFWDicEt5EAOCduoy8iHxyS0xrGCNP8I +YBVOt+bEgT0U9bbWw09uHkol2a+UMJSm1oc+yD/F8sN2Smw7YtCvC+jdo6G6 +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/testcases/rootca_key.pem b/SecurityTests/clxutils/NISCC/TLS_SSL/testcases/rootca_key.pem new file mode 100755 index 00000000..cd96d750 --- /dev/null +++ b/SecurityTests/clxutils/NISCC/TLS_SSL/testcases/rootca_key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQCnoMiNpA7im5ipCZI19GPXB12E5h27MBZQ/41z9c2bzV9wqjic +CvEj8kiHVUN89t4tiTa5I4SVb1/PxK0hrtzAqj9YBW3UBSIZ9VTBWwHJlbe2aBN0 +9+s5x4MD5gkomzm4Vpl5Bq1bzLZGg2MSdqLtQwgu4lGvicxK9zJjDAc78wIDAQAB +AoGACVVRdVl6HrHtKRRIWMq3uGRHl7u8UgzWYUIpXRiFjzQ7KSnBJycQ0CCQW0Cr +Fk0kh8KJEnvgyPU/j3Dy9tomnliJLpyAJ7EX8PcTTXu0pM0V2bzcDmdObjOuAvnA +JxuZLVl9f5LZDtHpDG0vVyE7dlMqElVGg36xMLo5lAdk6VkCQQDUHg2KBzCCvyOu +IDd+VRVItZR3zERDvfn9G14gO3mc2wp/RpDnpRkNWySa9KF2+4UdrND6qL+HZ0yb +B9DC+8yFAkEAyk6ICAKnEeG67MFNhu9RMGi2nrNsPbHPCrkfgqerOQActhSagRD7 +wGrk2wxFUkGkJ9rORVRGbWehTcNIn40sFwJAUpkhTI5gJYmoqzWAZoFbOGT822l/ +a6GepyDxFjwSrzHcdJNV+d4gU0MajfyUo3Bt9ZBGEFWFv4RKIFR6xnKmwQJBAIsF +pF081WpoYHfJ7mjHlFdb3gL48W0D/28zAABdEEC/XvuQ9Qu0jAwSaOpOaGS6TwBE +UHM8EpmkGSjDBej+rkkCQQCIRY00RWB6jDPKs5NnapFnttINsU9RFabijSguAdw9 +5HSRMe5PSFj0KJAuDeCRm9t83g6cEbBk3u9NyPYMks1U +-----END RSA PRIVATE KEY----- diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/testcases/server.crt b/SecurityTests/clxutils/NISCC/TLS_SSL/testcases/server.crt new file mode 100755 index 0000000000000000000000000000000000000000..f171d3a4fec32c993b55b6e968544f6967ad4843 GIT binary patch literal 509 zcmXqLV*F{)#F)gy$Y{XJ#;Mij(e|B}k&%^^!NAv$+klgeIh2J>n91GAP|iRG#NiSa z4bIFh$VpWQ%Fi!Ra4ap!$S=w)sf5WhCw^WO_jHr)cy7^(yF*38_`#LUQm9=yyzcNsXBB)xb%U-9lw8xMw8t{K z#Ik$(+{(9NUOtI-@Yr~H^}%0RsTsW=)^PS&=|&q#MjTjO<)y0o9RT@6xa 0 ) + switch ( "$argv[1]" ) + case q: + set QUIET = 1 + shift + breaksw + default: + echo Usage: anchorSourceTest directory + exit(1) + endsw +end + +# +# binaries we need +# +set CERTCRL=$BUILD_DIR/certcrl +set CERTS_FROM_DB=$BUILD_DIR/certsFromDb +foreach targ ($CERTCRL $CERTS_FROM_DB) + if(! -e $targ) then + echo === $targ is missing. Try building clxutil. + exit(1) + endif +end + +echo starting anchorSourceTest +# +# certcrl args: +# +# -c cert to eval +# -C use this as an anchor +# -a allow certs unverified by CRLs +# -f leaf cert is a CA +# -L silent +# +set TEST_FAILED=0 + +cd $CERTS_DIR +foreach certFile (*) + if ( ( -f "$certFile" ) && ( "$certFile" != X509Anchors) ) then + if($QUIET == 0) then + echo testing $certFile.... + endif +# $CERTCRL -c "$certFile" -C "$certFile" -a -f -L -T 20071217154316 + $CERTCRL -c "$certFile" -C "$certFile" -a -f -L + if($status != 0) then + echo "++++++++ Verification error on $certFile" + $CERTCRL -c "$certFile" -C "$certFile" -a -f -v + set TEST_FAILED=1 + endif + endif +end + +if($TEST_FAILED == 1) then + echo "anchorSourceTest FAILED" + exit(1) +endif + +if($QUIET == 0) then + echo "...anchorSourceTest complete" +endif diff --git a/SecurityTests/clxutils/anchorTest/anchorTest.cpp b/SecurityTests/clxutils/anchorTest/anchorTest.cpp new file mode 100644 index 00000000..8a3bde3e --- /dev/null +++ b/SecurityTests/clxutils/anchorTest/anchorTest.cpp @@ -0,0 +1,1125 @@ +/* + * anchorTest.cpp - test cert encode/decode using known good system + * anchors + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ENC_TBS_BLOB "encodedTbs.der" +#define DEC_TBS_BLOB "decodedTbs.der" + +static void usage(char **argv) +{ + printf("Usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" w -- writeBlobs\n"); + printf(" e -- allow expired roots\n"); + printf(" t -- use Trust Settings\n"); + printf(" q -- quiet\n"); + printf(" v -- verbose\n"); + exit(1); +} + +/* + * Certs for which we skip the "compare TBS blob" test, enumerated by + * DER-encoded issuer name. + * + * Get this formatted data from the extractCertFields program. + * + * All of these have non-standard KeyUsage encoding (legal but it's + * not the same as ours or everyone else's). + */ +/* + Country : HU + Locality : Budapest + Org : NetLock Halozatbiztonsagi Kft. + OrgUnit : Tanusitvanykiadok + Common Name : NetLock Expressz (Class C) Tanusitvanykiado + */ +static const uint8 anchor_46_derIssuer_bytes[] = { + 0x30, 0x81, 0x9b, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x48, 0x55, + 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, + 0x65, 0x73, 0x74, 0x31, 0x27, 0x30, 0x25, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1e, 0x4e, 0x65, + 0x74, 0x4c, 0x6f, 0x63, 0x6b, 0x20, 0x48, 0x61, + 0x6c, 0x6f, 0x7a, 0x61, 0x74, 0x62, 0x69, 0x7a, + 0x74, 0x6f, 0x6e, 0x73, 0x61, 0x67, 0x69, 0x20, + 0x4b, 0x66, 0x74, 0x2e, 0x31, 0x1a, 0x30, 0x18, + 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x11, 0x54, + 0x61, 0x6e, 0x75, 0x73, 0x69, 0x74, 0x76, 0x61, + 0x6e, 0x79, 0x6b, 0x69, 0x61, 0x64, 0x6f, 0x6b, + 0x31, 0x34, 0x30, 0x32, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x2b, 0x4e, 0x65, 0x74, 0x4c, 0x6f, + 0x63, 0x6b, 0x20, 0x45, 0x78, 0x70, 0x72, 0x65, + 0x73, 0x73, 0x7a, 0x20, 0x28, 0x43, 0x6c, 0x61, + 0x73, 0x73, 0x20, 0x43, 0x29, 0x20, 0x54, 0x61, + 0x6e, 0x75, 0x73, 0x69, 0x74, 0x76, 0x61, 0x6e, + 0x79, 0x6b, 0x69, 0x61, 0x64, 0x6f +}; +static const CSSM_DATA anchor_46_derIssuer = { 158, (uint8 *)anchor_46_derIssuer_bytes }; + +/* + Country : HU + State : Hungary + Locality : Budapest + Org : NetLock Halozatbiztonsagi Kft. + OrgUnit : Tanusitvanykiadok + Common Name : NetLock Kozjegyzoi (Class A) Tanusitvanykiado +*/ +static const uint8 anchor_53_derIssuer_bytes[] = { + 0x30, 0x81, 0xaf, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x48, 0x55, + 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x07, 0x48, 0x75, 0x6e, 0x67, 0x61, + 0x72, 0x79, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x13, 0x08, 0x42, 0x75, 0x64, + 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, 0x27, 0x30, + 0x25, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1e, + 0x4e, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x6b, 0x20, + 0x48, 0x61, 0x6c, 0x6f, 0x7a, 0x61, 0x74, 0x62, + 0x69, 0x7a, 0x74, 0x6f, 0x6e, 0x73, 0x61, 0x67, + 0x69, 0x20, 0x4b, 0x66, 0x74, 0x2e, 0x31, 0x1a, + 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, + 0x11, 0x54, 0x61, 0x6e, 0x75, 0x73, 0x69, 0x74, + 0x76, 0x61, 0x6e, 0x79, 0x6b, 0x69, 0x61, 0x64, + 0x6f, 0x6b, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x2d, 0x4e, 0x65, 0x74, + 0x4c, 0x6f, 0x63, 0x6b, 0x20, 0x4b, 0x6f, 0x7a, + 0x6a, 0x65, 0x67, 0x79, 0x7a, 0x6f, 0x69, 0x20, + 0x28, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x41, + 0x29, 0x20, 0x54, 0x61, 0x6e, 0x75, 0x73, 0x69, + 0x74, 0x76, 0x61, 0x6e, 0x79, 0x6b, 0x69, 0x61, + 0x64, 0x6f +}; +static const CSSM_DATA anchor_53_derIssuer = { 178, (uint8 *)anchor_53_derIssuer_bytes }; + +/* + Country : HU + Locality : Budapest + Org : NetLock Halozatbiztonsagi Kft. + OrgUnit : Tanusitvanykiadok + Common Name : NetLock Uzleti (Class B) Tanusitvanykiado +*/ +static const uint8 anchor_60_derIssuer_bytes[] = { + 0x30, 0x81, 0x99, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x48, 0x55, + 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, + 0x65, 0x73, 0x74, 0x31, 0x27, 0x30, 0x25, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1e, 0x4e, 0x65, + 0x74, 0x4c, 0x6f, 0x63, 0x6b, 0x20, 0x48, 0x61, + 0x6c, 0x6f, 0x7a, 0x61, 0x74, 0x62, 0x69, 0x7a, + 0x74, 0x6f, 0x6e, 0x73, 0x61, 0x67, 0x69, 0x20, + 0x4b, 0x66, 0x74, 0x2e, 0x31, 0x1a, 0x30, 0x18, + 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x11, 0x54, + 0x61, 0x6e, 0x75, 0x73, 0x69, 0x74, 0x76, 0x61, + 0x6e, 0x79, 0x6b, 0x69, 0x61, 0x64, 0x6f, 0x6b, + 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x29, 0x4e, 0x65, 0x74, 0x4c, 0x6f, + 0x63, 0x6b, 0x20, 0x55, 0x7a, 0x6c, 0x65, 0x74, + 0x69, 0x20, 0x28, 0x43, 0x6c, 0x61, 0x73, 0x73, + 0x20, 0x42, 0x29, 0x20, 0x54, 0x61, 0x6e, 0x75, + 0x73, 0x69, 0x74, 0x76, 0x61, 0x6e, 0x79, 0x6b, + 0x69, 0x61, 0x64, 0x6f +}; +static const CSSM_DATA anchor_60_derIssuer = { 156, (uint8 *)anchor_60_derIssuer_bytes }; + +/* + Country : TR + Locality : Ankara + Org : (c) 2005 TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş. + Common Name : TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı + Serial Number : 01 + Not Before : 10:27:17 May 13, 2005 + Not After : 10:27:17 Mar 22, 2015 +*/ +static const uint8 turk1_derIssuer_bytes[] = { + 0x30, 0x81, 0xb7, 0x31, 0x3f, 0x30, 0x3d, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0c, 0x36, 0x54, 0xc3, + 0x9c, 0x52, 0x4b, 0x54, 0x52, 0x55, 0x53, 0x54, + 0x20, 0x45, 0x6c, 0x65, 0x6b, 0x74, 0x72, 0x6f, + 0x6e, 0x69, 0x6b, 0x20, 0x53, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x6b, 0x61, 0x20, 0x48, 0x69, + 0x7a, 0x6d, 0x65, 0x74, 0x20, 0x53, 0x61, 0xc4, + 0x9f, 0x6c, 0x61, 0x79, 0xc4, 0xb1, 0x63, 0xc4, + 0xb1, 0x73, 0xc4, 0xb1, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x0c, 0x02, 0x54, + 0x52, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0c, 0x06, 0x41, 0x4e, 0x4b, 0x41, + 0x52, 0x41, 0x31, 0x56, 0x30, 0x54, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x4d, 0x28, 0x63, 0x29, + 0x20, 0x32, 0x30, 0x30, 0x35, 0x20, 0x54, 0xc3, + 0x9c, 0x52, 0x4b, 0x54, 0x52, 0x55, 0x53, 0x54, + 0x20, 0x42, 0x69, 0x6c, 0x67, 0x69, 0x20, 0xc4, + 0xb0, 0x6c, 0x65, 0x74, 0x69, 0xc5, 0x9f, 0x69, + 0x6d, 0x20, 0x76, 0x65, 0x20, 0x42, 0x69, 0x6c, + 0x69, 0xc5, 0x9f, 0x69, 0x6d, 0x20, 0x47, 0xc3, + 0xbc, 0x76, 0x65, 0x6e, 0x6c, 0x69, 0xc4, 0x9f, + 0x69, 0x20, 0x48, 0x69, 0x7a, 0x6d, 0x65, 0x74, + 0x6c, 0x65, 0x72, 0x69, 0x20, 0x41, 0x2e, 0xc5, + 0x9e, 0x2e +}; +static const CSSM_DATA turk1_derIssuer = { 186, (uint8 *)turk1_derIssuer_bytes }; + +/* + Country : TR + Locality : Ankara + Org : TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş. (c) Kasım 2005 + Common Name : TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı + Serial Number : 01 + Not Before : 10:07:57 Nov 7, 2005 + Not After : 10:07:57 Sep 16, 2015 +*/ +static const uint8 turk2_derIssuer_bytes[] = { + 0x30, 0x81, 0xbe, 0x31, 0x3f, 0x30, 0x3d, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0c, 0x36, 0x54, 0xc3, + 0x9c, 0x52, 0x4b, 0x54, 0x52, 0x55, 0x53, 0x54, + 0x20, 0x45, 0x6c, 0x65, 0x6b, 0x74, 0x72, 0x6f, + 0x6e, 0x69, 0x6b, 0x20, 0x53, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x6b, 0x61, 0x20, 0x48, 0x69, + 0x7a, 0x6d, 0x65, 0x74, 0x20, 0x53, 0x61, 0xc4, + 0x9f, 0x6c, 0x61, 0x79, 0xc4, 0xb1, 0x63, 0xc4, + 0xb1, 0x73, 0xc4, 0xb1, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x54, + 0x52, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0c, 0x06, 0x41, 0x6e, 0x6b, 0x61, + 0x72, 0x61, 0x31, 0x5d, 0x30, 0x5b, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x54, 0x54, 0xc3, 0x9c, + 0x52, 0x4b, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x42, 0x69, 0x6c, 0x67, 0x69, 0x20, 0xc4, 0xb0, + 0x6c, 0x65, 0x74, 0x69, 0xc5, 0x9f, 0x69, 0x6d, + 0x20, 0x76, 0x65, 0x20, 0x42, 0x69, 0x6c, 0x69, + 0xc5, 0x9f, 0x69, 0x6d, 0x20, 0x47, 0xc3, 0xbc, + 0x76, 0x65, 0x6e, 0x6c, 0x69, 0xc4, 0x9f, 0x69, + 0x20, 0x48, 0x69, 0x7a, 0x6d, 0x65, 0x74, 0x6c, + 0x65, 0x72, 0x69, 0x20, 0x41, 0x2e, 0xc5, 0x9e, + 0x2e, 0x20, 0x28, 0x63, 0x29, 0x20, 0x4b, 0x61, + 0x73, 0xc4, 0xb1, 0x6d, 0x20, 0x32, 0x30, 0x30, + 0x35 +}; +static const CSSM_DATA turk2_derIssuer = { 193, (uint8 *)turk2_derIssuer_bytes }; + +/* + Country : TR + Locality : Ankara + Org : TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş. (c) Aralık 2007 + Common Name : TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı + Serial Number : 01 + Not Before : 18:37:19 Dec 25, 2007 + Not After : 18:37:19 Dec 22, 2017 +*/ +static const uint8 turk3_derIssuer_bytes[] = { + 0x30, 0x81, 0xbf, 0x31, 0x3f, 0x30, 0x3d, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0c, 0x36, 0x54, 0xc3, + 0x9c, 0x52, 0x4b, 0x54, 0x52, 0x55, 0x53, 0x54, + 0x20, 0x45, 0x6c, 0x65, 0x6b, 0x74, 0x72, 0x6f, + 0x6e, 0x69, 0x6b, 0x20, 0x53, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x6b, 0x61, 0x20, 0x48, 0x69, + 0x7a, 0x6d, 0x65, 0x74, 0x20, 0x53, 0x61, 0xc4, + 0x9f, 0x6c, 0x61, 0x79, 0xc4, 0xb1, 0x63, 0xc4, + 0xb1, 0x73, 0xc4, 0xb1, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x54, + 0x52, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0c, 0x06, 0x41, 0x6e, 0x6b, 0x61, + 0x72, 0x61, 0x31, 0x5e, 0x30, 0x5c, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x55, 0x54, 0xc3, 0x9c, + 0x52, 0x4b, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, + 0x42, 0x69, 0x6c, 0x67, 0x69, 0x20, 0xc4, 0xb0, + 0x6c, 0x65, 0x74, 0x69, 0xc5, 0x9f, 0x69, 0x6d, + 0x20, 0x76, 0x65, 0x20, 0x42, 0x69, 0x6c, 0x69, + 0xc5, 0x9f, 0x69, 0x6d, 0x20, 0x47, 0xc3, 0xbc, + 0x76, 0x65, 0x6e, 0x6c, 0x69, 0xc4, 0x9f, 0x69, + 0x20, 0x48, 0x69, 0x7a, 0x6d, 0x65, 0x74, 0x6c, + 0x65, 0x72, 0x69, 0x20, 0x41, 0x2e, 0xc5, 0x9e, + 0x2e, 0x20, 0x28, 0x63, 0x29, 0x20, 0x41, 0x72, + 0x61, 0x6c, 0xc4, 0xb1, 0x6b, 0x20, 0x32, 0x30, + 0x30, 0x37 +}; +static const CSSM_DATA turk3_derIssuer = { 194, (uint8 *)turk3_derIssuer_bytes }; + +/* +Cert File Name: globalSignRoot.cer + Country : BE + Org : GlobalSign nv-sa + OrgUnit : Root CA + Common Name : GlobalSign Root CA +*/ +static const uint8 globalSignRoot_derIssuer_bytes[] = { + 0x30, 0x57, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x42, 0x45, 0x31, + 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x13, 0x10, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, + 0x53, 0x69, 0x67, 0x6e, 0x20, 0x6e, 0x76, 0x2d, + 0x73, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x13, 0x07, 0x52, 0x6f, 0x6f, + 0x74, 0x20, 0x43, 0x41, 0x31, 0x1b, 0x30, 0x19, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, + 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, + 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, + 0x41 +}; +static const CSSM_DATA globalSignRoot_derIssuer = { 89, (uint8 *)globalSignRoot_derIssuer_bytes }; + +/*********************** +Cert File Name: swisssign.der +Subject Name : + Country : CH + Org : SwissSign + Common Name : SwissSign CA (RSA IK May 6 1999 18:00:58) + Email addrs : ca@SwissSign.com + + This one has a bogus AuthorityKeyId, with a value of {0x30, 0} inside the octet string. + ***********************/ +static const uint8 swisssign_derIssuer_bytes[] = { + 0x30, 0x76, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x48, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x13, 0x09, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, + 0x69, 0x67, 0x6e, 0x31, 0x32, 0x30, 0x30, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x53, 0x77, + 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x20, + 0x43, 0x41, 0x20, 0x28, 0x52, 0x53, 0x41, 0x20, + 0x49, 0x4b, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x36, + 0x20, 0x31, 0x39, 0x39, 0x39, 0x20, 0x31, 0x38, + 0x3a, 0x30, 0x30, 0x3a, 0x35, 0x38, 0x29, 0x31, + 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, + 0x63, 0x61, 0x40, 0x53, 0x77, 0x69, 0x73, 0x73, + 0x53, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d + +}; +static const CSSM_DATA swisssign_derIssuer = { 120, (uint8 *)swisssign_derIssuer_bytes }; + +/* + * Simple class to hold arrays of fields. + */ +class FieldArray { +public: + /* + * Create from existing field array obtained from + * CSSM_CL_CertGetAllFields(). We'll do the CSSM_CL_FreeFields() + * in our destructor. + */ + FieldArray( + CSSM_FIELD *fields, + uint32 numFields, + CSSM_CL_HANDLE clHand); + + /* + * Create empty array of specified size. We don't own the fields + * themselves. + */ + FieldArray( + uint32 size); + + ~FieldArray(); + + /* + * Append a field - no realloc! + */ + void appendField(CSSM_FIELD &field); + + /* get specified field */ + CSSM_FIELD &fieldAt(uint32 index); + + /* get nth occurence of field matching specified OID */ + int fieldForOid( + const CSSM_OID &oid, + unsigned n, // n == 0 --> first one + CSSM_FIELD *&found); // RETURNED + + CSSM_FIELD *mFields; + uint32 mNumFields; // sizeof of *fields + uint32 mMallocdSize; // if NULL, read-only + CSSM_CL_HANDLE mClHand; +}; + +FieldArray::FieldArray( + CSSM_FIELD *fields, + uint32 numFields, + CSSM_CL_HANDLE clHand) +{ + mFields = fields; + mNumFields = numFields; + mMallocdSize = 0; + mClHand = clHand; +} + +FieldArray::FieldArray( + uint32 size) +{ + unsigned len = sizeof(CSSM_FIELD) * size; + mFields = (CSSM_FIELD_PTR)malloc(len); + memset(mFields, 0, len); + mNumFields = 0; + mMallocdSize = size; + mClHand = 0; +} + +FieldArray::~FieldArray() +{ + if(mMallocdSize != 0) { + /* + * Just free the array of fields we mallocd, not the fields + * themselves + */ + free(mFields); + } + else { + /* The CL mallocd these fields, tell it to free the whole thing */ + CSSM_RETURN crtn = CSSM_CL_FreeFields(mClHand, + mNumFields, &mFields); + if(crtn) { + printError("CSSM_CL_FreeFields", crtn); + } + } + mFields = NULL; + mNumFields = 0; + mMallocdSize = 0; +} + +void FieldArray::appendField( + CSSM_FIELD &field) +{ + if(mMallocdSize == 0) { + printf("***Attempt to append to a read-only FieldArray\n"); + exit(1); + } + if(mNumFields >= mMallocdSize) { + printf("***Attempt to append past present size of FieldArray\n"); + exit(1); + } + mFields[mNumFields] = field; + mNumFields++; +} + +CSSM_FIELD &FieldArray::fieldAt( + uint32 index) +{ + if(index >= mNumFields) { + printf("***Attempt to access past present size of FieldArray\n"); + exit(1); + } + return mFields[index]; +} + +/* get nth occurence of field matching specified OID */ +/* returns nonzero on error */ +int FieldArray::fieldForOid( + const CSSM_OID &oid, + unsigned n, // n == 0 --> first one + CSSM_FIELD *&found) // RETURNED +{ + unsigned foundDex = 0; + for(unsigned dex=0; dex; shouldn't need to skip! + &CSSMOID_PolicyMappings, + &CSSMOID_PolicyConstraints +}; +#define NUM_SKIPPED_EXTENS \ + (sizeof(skippedExtens) / sizeof(skippedExtens[0])) +#endif /* USE_SKIPPED_EXTENS */ + +static const CSSM_DATA *skippedCerts[] = { + &anchor_46_derIssuer, + &anchor_53_derIssuer, + &anchor_60_derIssuer, + &turk1_derIssuer, + &turk2_derIssuer, + &turk3_derIssuer, + &globalSignRoot_derIssuer, + &swisssign_derIssuer +}; +#define NUM_SKIPPED_CERTS (sizeof(skippedCerts) / sizeof(skippedCerts[0])) + +static bool skipThisCert( + const NSS_TBSCertificate &tbs) +{ + /* search by extension - currently unused */ + unsigned dex; + #if USE_SKIPPED_EXTENS + unsigned numExtens = nssArraySize((const void **)tbs.extensions); + /* skip this section if that's empty - compiler warning causes failure */ + for(dex=0; dexextnId; + for(unsigned skipDex=0; skipDex FieldType */ +typedef struct { + const CSSM_OID *oid; + FieldType type; +} FieldOidType; + +/* + * The CL-specific mapping table. + * This has to change whenever the CL is modified to add or delete + * an extension or field! + * For newbies, a tip: this basically has to stay in sync with the + * fieldFuncTable array in Security/AppleX509CL/CertFields.cpp. + */ +FieldOidType knownFields[] = { + { &CSSMOID_X509V1Version, FT_Normal }, + { &CSSMOID_X509V1SerialNumber, FT_Normal }, + { &CSSMOID_X509V1IssuerNameCStruct, FT_Normal }, + { &CSSMOID_X509V1SubjectNameCStruct, FT_Normal }, + { &CSSMOID_X509V1SignatureAlgorithmTBS, FT_Normal }, + { &CSSMOID_X509V1SignatureAlgorithm, FT_NotTBS }, + { &CSSMOID_X509V1ValidityNotBefore, FT_Normal }, + { &CSSMOID_X509V1ValidityNotAfter, FT_Normal }, + { &CSSMOID_X509V1CertificateIssuerUniqueId, FT_Normal }, + { &CSSMOID_X509V1CertificateSubjectUniqueId, FT_Normal }, + /* only one of these two can be set - use the SubjectPublicKeyInfo + * version */ + { &CSSMOID_X509V1SubjectPublicKeyCStruct, FT_Normal }, + { &CSSMOID_CSSMKeyStruct, FT_ReadOnly }, + { &CSSMOID_X509V1Signature, FT_NotTBS }, + { &CSSMOID_X509V1IssuerName, FT_ReadOnly }, // DER encoded + { &CSSMOID_X509V1SubjectName, FT_ReadOnly }, // DER encoded + { &CSSMOID_X509V1IssuerNameStd, FT_ReadOnly }, // DER encoded + { &CSSMOID_X509V1SubjectNameStd,FT_ReadOnly }, // DER encoded + + /* Extensions */ + { &CSSMOID_KeyUsage, FT_ExtenParsed }, + { &CSSMOID_BasicConstraints, FT_ExtenParsed }, + { &CSSMOID_ExtendedKeyUsage, FT_ExtenParsed } , + { &CSSMOID_SubjectKeyIdentifier, FT_ExtenParsed } , + { &CSSMOID_AuthorityKeyIdentifier, FT_ExtenParsed } , + { &CSSMOID_SubjectAltName, FT_ExtenParsed } , + { &CSSMOID_IssuerAltName, FT_ExtenParsed } , + { &CSSMOID_CertificatePolicies, FT_ExtenParsed } , + { &CSSMOID_NetscapeCertType, FT_ExtenParsed } , + { &CSSMOID_CrlDistributionPoints, FT_ExtenParsed }, + { &CSSMOID_AuthorityInfoAccess, FT_ExtenParsed }, + { &CSSMOID_SubjectInfoAccess, FT_ExtenParsed }, + { &CSSMOID_X509V3CertificateExtensionCStruct, FT_ExtenUnknown }, + { &CSSMOID_QC_Statements, FT_ExtenParsed }, + { &CSSMOID_NameConstraints, FT_ExtenParsed }, + { &CSSMOID_PolicyMappings, FT_ExtenParsed }, + { &CSSMOID_PolicyConstraints, FT_ExtenParsed }, +// { &CSSMOID_InhibitAnyPolicy, FT_ExtenParsed } //%%% FIXME: CSSMOID_InhibitAnyPolicy not exported!? +}; +#define NUM_KNOWN_FIELDS (sizeof(knownFields) / sizeof(knownFields[0])) + +static FieldType typeForOid( + const CSSM_OID &oid) +{ + for(unsigned dex=0; dexBERvalue.Data == NULL) || + (exten->value.parsedValue == NULL)) { /* actually, one of three variants */ + printf("***Malformed CSSM_X509_EXTENSION (1)\n"); + return 1; + } + + switch(exten->format) { + case CSSM_X509_DATAFORMAT_ENCODED: + if(type != FT_ExtenUnknown) { + doPrintCert(cert); + printf("***Entension format ENCODED, expected PARSED\n"); + if(testError(quiet)) { + return 1; + } + } + + /* + * Now make sure that the underlying extension ID isn't + * one that the CL was SUPPOSED to parse + */ + // %%% FIXME: need to investigate why these are not fully parsed: + if(appCompareCssmData(&exten->extnId, &CSSMOID_PolicyConstraints)) { + printf("...skipping policyConstraints extension per (fix me!)\n"); + break; + } + if(appCompareCssmData(&exten->extnId, &CSSMOID_PolicyMappings)) { + printf("...skipping policyMappings extension per (fix me!)\n"); + break; + } + + expectType = typeForOid(exten->extnId); + if(expectType != FT_Unknown) { + /* + * Swisscom root has an authorityKeyId extension with an illegal value, + * data inside the octet string is <30 00>, no context-specific wrapper + * or tag. + * Instead of a hopeless complaint about that cert, let's just tolerate it + * like this... + */ + if(appCompareCssmData(&exten->extnId, &CSSMOID_AuthorityKeyIdentifier) && + (exten->BERvalue.Length == 2) && + !memcmp(emptyAuthKeyId, exten->BERvalue.Data, 2)) { + printf("...skipping bogus swisssign AuthorityKeyId\n"); + break; + } + doPrintCert(cert); + printf("***underlying exten type %s, expect Unknown\n", + fieldTypeStr(expectType)); + if(testError(quiet)) { + return 1; + } + } + break; + + case CSSM_X509_DATAFORMAT_PARSED: + if(type != FT_ExtenParsed) { + doPrintCert(cert); + printf("***Entension format PARSED, expected ENCODED\n"); + if(testError(quiet)) { + return 1; + } + } + if(exten->value.parsedValue == NULL) { + doPrintCert(cert); + printf("***Parsed extension with NULL parsedValue\n"); + if(testError(quiet)) { + return 1; + } + } + break; + + default: + doPrintCert(cert); + printf("***Unknown Entension format %u\n", + exten->format); + if(testError(quiet)) { + return 1; + } + break; + + } /* switch(exten.format) */ + } + return 0; +} + +/* + * Here's the hard part. + * Given a raw cert and its components in two FieldArrays, crate a TBS + * cert from scratch from those fields and ensure that the result + * is the same as the raw TBS field in the original cert. + */ +static int buildTbs( + CSSM_CL_HANDLE clHand, + const CSSM_DATA &rawCert, + FieldArray &allFields, // on entry, standard fields + FieldArray &extenFields, // extensions only + CSSM_BOOL quiet, + CSSM_BOOL verbose, + CSSM_BOOL writeBlobs) +{ + /* + * First do raw BER-decode in two ways - one to get the + * extensions as they actuallly appear in the cert, and one + * to get the raw undecoded TBS. + */ + SecAsn1CoderRef coder; + OSStatus ortn = SecAsn1CoderCreate(&coder); + if(ortn) { + cssmPerror("SecAsn1CoderCreate", ortn); + return testError(quiet); + } + + NSS_SignedCertOrCRL signedCert; // with TBS as ASN_ANY + memset(&signedCert, 0, sizeof(signedCert)); + if(SecAsn1DecodeData(coder, &rawCert, kSecAsn1SignedCertOrCRLTemplate, + &signedCert)) { + doPrintCert(rawCert); + printf("***Error decoding cert to kSecAsn1SignedCertOrCRL\n"); + return testError(quiet); + } + + NSS_Certificate fullCert; // fully decoded + memset(&fullCert, 0, sizeof(fullCert)); + if(SecAsn1DecodeData(coder, &rawCert, kSecAsn1SignedCertTemplate, + &fullCert)) { + doPrintCert(rawCert); + printf("***Error decoding cert to kSecAsn1Certificate\n"); + return testError(quiet); + } + + NSS_TBSCertificate &tbs = fullCert.tbs; + unsigned numExtens = nssArraySize((const void **)tbs.extensions); + if(numExtens != extenFields.mNumFields) { + /* The CL told us the wrong number of extensions */ + doPrintCert(rawCert); + printf("***NSS says %u extens, CL says %u\n", numExtens, + (unsigned)extenFields.mNumFields); + return testError(quiet); + } + + if(skipThisCert(tbs)) { + if(verbose) { + printf(" ...skipping TBS blob check\n"); + } + SecAsn1CoderRelease(coder); + return 0; + } + + /* + * The CL returns extension fields in an order which differs from + * the order of the extensions in the actual cert (because it + * does a table-based lookup, field by field, when doing a + * CSSM_CL_CertGetAllFields()). We have to add the extensions + * from extenFields to allFields in the order they appear in + * OUR decoded fullCert. + */ + unsigned numUnknowns = 0; + for(unsigned dex=0; dexextnId; + FieldType type = typeForOid(oid); + CSSM_FIELD *found = NULL; + int rtn; + switch(type) { + case FT_ExtenParsed: + /* + * look for this exact extension + * NOTE we're assuming that only one copy of + * each specific parsed extension exists. The + * 509 spec does't specifically require this but + * I've never seen a case of multiple extensions + * of the same type in one cert. + */ + rtn = extenFields.fieldForOid(oid, 0, found); + break; + case FT_Unknown: + /* search for nth unparsed exten field */ + rtn = extenFields.fieldForOid( + CSSMOID_X509V3CertificateExtensionCStruct, + numUnknowns++, + found); + break; + default: + /* caller was already supposed to check this */ + doPrintCert(rawCert); + printf("***HEY! buildTBS was given a bogus extension!\n"); + return 1; + } + if(rtn) { + doPrintCert(rawCert); + printf("***buildTBS could not find extension in CL's fields\n"); + return testError(quiet); + } + + allFields.appendField(*found); + } /* processing extensions */ + + /* + * OK, the field array in allFields is ready to go down to + * the CL. + */ + CSSM_RETURN crtn; + CSSM_DATA clTbs = {0, NULL}; + crtn = CSSM_CL_CertCreateTemplate(clHand, + allFields.mNumFields, + allFields.mFields, + &clTbs); + if(crtn) { + doPrintCert(rawCert); + printError("CSSM_CL_CertCreateTemplate", crtn); + return testError(quiet); + } + + /* + * The moment of truth. Is that template identical to the + * raw undecoded TBS blob we got by decoding a NSS_SignedCertOrCRL? + */ + int ourRtn = 0; + if(!appCompareCssmData(&clTbs, &signedCert.tbsBlob)) { + doPrintCert(rawCert); + printf("***Encoded TBS does not match decoded TBS.\n"); + if(writeBlobs) { + writeFile(ENC_TBS_BLOB, clTbs.Data, clTbs.Length); + writeFile(DEC_TBS_BLOB, signedCert.tbsBlob.Data, + signedCert.tbsBlob.Length); + printf("...wrote TBS blobs to %s and %s\n", + ENC_TBS_BLOB, DEC_TBS_BLOB); + } + ourRtn = testError(quiet); + } + CSSM_FREE(clTbs.Data); + SecAsn1CoderRelease(coder); + return ourRtn; +} + +/* verify root with itself using TP */ +static int verifyRoot( + CSSM_TP_HANDLE tpHand, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + const CSSM_DATA &cert, + CSSM_BOOL allowExpired, + CSSM_BOOL useTrustSettings, + CSSM_BOOL quiet) +{ + BlobList blobs; + blobs.addBlob(cert, CSSM_TRUE); + int i; + + const char *certStatus; + if(useTrustSettings) { + /* + * CSSM_CERT_STATUS_IS_IN_INPUT_CERTS + * CSSM_CERT_STATUS_IS_ROOT + * CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_SYSTEM + * CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST + */ + certStatus = "0:0x314"; + } + else { + /* + * CSSM_CERT_STATUS_IS_IN_INPUT_CERTS (new since radar 3855635 was fixed) + * CSSM_CERT_STATUS_IS_IN_ANCHORS + * CSSM_CERT_STATUS_IS_ROOT + */ + certStatus = "0:0x1C"; + } + + /* try one with allowExpiredRoot false, then true on error and if so + * enabled to make sure we know what's going wrong */ + CSSM_BOOL expireEnable = CSSM_FALSE; + for(int dex=0; dex<2; dex++) { + i = certVerifySimple(tpHand, clHand, cspHand, + blobs, // certs + blobs, // and roots + CSSM_FALSE, // useSystemAnchors + CSSM_TRUE, // leaf is CA + expireEnable, + CVP_Basic, + NULL, // SSL host + CSSM_FALSE, // SSL client + NULL, // sender email + 0, // key use + NULL, // expected error str + 0, NULL, // per-cert errors + 1, &certStatus, // per-cert status + useTrustSettings, + quiet, + CSSM_FALSE); // verbose + if(i == 0) { + /* success */ + if(dex == 1) { + printf("...warning: expired root detected. Be aware.\n"); + } + return 0; + } + if(!allowExpired) { + /* no second chance */ + return i; + } + expireEnable = CSSM_TRUE; + if(useTrustSettings) { + /* now expect EXPIRED, IS_ROOT, IS_IN_INPUT_CERTS, TRUST_SETTINGS_FOUND_SYSTEM, + * CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST */ + certStatus = "0:0x315"; + } + else { + /* now expect EXPIRED, IS_ROOT, IS_IN_ANCHORS, IS_IN_INPUT_CERTS */ + certStatus = "0:0x1d"; + } + } + return i; +} + + +static int doTest( + CSSM_CL_HANDLE clHand, + CSSM_TP_HANDLE tpHand, + CSSM_CSP_HANDLE cspHand, + const CSSM_DATA &cert, + CSSM_BOOL allowExpired, + CSSM_BOOL quiet, + CSSM_BOOL verbose, + CSSM_BOOL writeBlobs, + CSSM_BOOL useTrustSettings) +{ + /* first see if this anchor self-verifies. */ + if(verifyRoot(tpHand, clHand, cspHand, cert, allowExpired, + useTrustSettings, quiet)) { + doPrintCert(cert); + printf("***This anchor does not self-verify!\n"); + return testError(quiet); + } + + /* have the CL parse it to the best of its ability */ + CSSM_FIELD_PTR certFields; + uint32 numFields; + CSSM_RETURN crtn = CSSM_CL_CertGetAllFields(clHand, &cert, &numFields, + &certFields); + if(crtn) { + printError("CSSM_CL_CertGetAllFields", crtn); + doPrintCert(cert); + printf("***The CL can not parse this anchor!\n"); + return testError(quiet); + } + + /* save, this object does the free fields when it goes out of scope */ + FieldArray parsed(certFields, numFields, clHand); + + /* + * We're going to build a TBSCert from these received fields. + * Extensions need to be processed specially because they + * come back from the CL ordered differently than they appear + * in the cert. + * + * First make two buckets for making copies of incoming fields. + */ + FieldArray forCreate(numFields); // for creating template + FieldArray extenFields(numFields); + + for(unsigned dex=0; dex 0 ) + switch ( "$argv[1]" ) + case q: + set QUIET = 1 + shift + breaksw + case t: + set TRUST_SETTINGS_ARG = -g + shift + breaksw + default: + echo Usage: intermedSourceTest directory + exit(1) + endsw +end + +# +# binaries we need +# +set CERTCRL=$BUILD_DIR/certcrl +set CERTS_FROM_DB=$BUILD_DIR/certsFromDb +foreach targ ($CERTCRL $CERTS_FROM_DB) + if(! -e $targ) then + echo === $targ is missing. Try building clxutil. + exit(1) + endif +end + +set SYSTEM_CERTS=/System/Library/Keychains/SystemCACertificates.keychain + +echo starting intermedSourceTest +# +# certcrl args: +# +# -c cert to eval +# -s use system anchors +# -a allow certs unverified by CRLs +# -n no network fetch of CRLs +# -N no network fetch of certs +# -f leaf cert is a CA +# -d SYSTEM_CERTS -- use additional certs from there +# -L silent +# -g use Trust Settings +# +cd $CERTS_DIR +foreach certFile (*) + if ( -f "$certFile" ) then + if($QUIET == 0) then + echo testing $certFile.... + endif + $CERTCRL -c "$certFile" -s -a -f -L -n -N -d $SYSTEM_CERTS $TRUST_SETTINGS_ARG + set ERR=$status + if($ERR == 1) then + echo "Note: $certFile is expired" + else + if($ERR != 0) then + echo "++++++++ Verification error on $certFile ($ERR)" + $CERTCRL -c "$certFile" -s -a -f -v -n -N -d $SYSTEM_CERTS $TRUST_SETTINGS_ARG + exit(1) + endif + endif +end + +if($QUIET == 0) then + echo "...intermedSourceTest complete" +endif + diff --git a/SecurityTests/clxutils/anchorTest/intermedTest b/SecurityTests/clxutils/anchorTest/intermedTest new file mode 100755 index 00000000..44532232 --- /dev/null +++ b/SecurityTests/clxutils/anchorTest/intermedTest @@ -0,0 +1,128 @@ +#! /bin/csh -f +# +# verify contents of /System/Library/Keychains/SystemCACertificates.keychain +# +set BUILD_DIR=$LOCAL_BUILD_DIR +set QUIET=NO +# +set CERT_KC=/System/Library/Keychains/SystemCACertificates.keychain +# +# the contents of SystemCACertificates gets dumped here as a pile of certs. +# We delete on successful exit, else we leave them there. +# +set CERTS_DIR=$BUILD_DIR/intermediateCerts +# +# binaries we need +# +set CERTCRL=$BUILD_DIR/certcrl +set CERTS_FROM_DB=$BUILD_DIR/certsFromDb +foreach targ ($CERTCRL $CERTS_FROM_DB) + if(! -e $targ) then + echo === $targ is missing. Try building clxutil. + exit(1) + endif +end + +# +set TRUST_SETTINGS_ARG= +# +while ( $#argv > 0 ) + switch ( "$argv[1]" ) + case q: + set QUIET=YES + shift + breaksw + case 't': + set TRUST_SETTINGS_ARG=-g + shift + breaksw + default: + echo "Usage: intermedTest [q(uiet)] [t(rustSettings)]" + exit(1) + endsw +end +# +echo Starting intermedTest + +if ($QUIET == NO) then + echo Initializing $CERTS_DIR... +endif +set cmd="rm -rf $CERTS_DIR" +if ($QUIET == NO) then + echo $cmd +endif +$cmd || exit(1) +set cmd="mkdir -p $CERTS_DIR" +if ($QUIET == NO) then + echo $cmd +endif +$cmd || exit(1) + +if ($QUIET == NO) then + echo Extracting certs from $CERT_KC... === +endif +set cmd="$CERTS_FROM_DB $CERT_KC f $CERTS_DIR/intermed q" +if ($QUIET == NO) then + echo $cmd +endif +$cmd || exit(1) + +# +# certcrl args: +# +# -s use system anchors +# -a allow certs unverified by CRLs +# -f leaf cert is a CA +# -L silent +# -g use Trust Settings +# +# We can also specify an evaluation date prior to the expiration of +# various intermediate certs via the EVAL_TIME string: +# +#set EVAL_TIME="-T 20081201000000" +#echo "### Verification date for intermedTest is 2008-12-01" +set EVAL_TIME="" + +set GOT_ERROR=0 +foreach certFile ($CERTS_DIR/*) + set cmd="$CERTCRL -c $certFile -s -a -f -L $TRUST_SETTINGS_ARG $EVAL_TIME" + if ($QUIET == NO) then + echo $cmd + endif + + set CERTNAM=`basename "$certFile"` + set CERTNUM=`echo -n "$CERTNAM" | sed -e 's/^intermed_\([0-9].*\)/\1/g'` + # skip DOD intermediates in this range as AIA fetch is timing out! + if($CERTNUM > 43 && $CERTNUM < 54) then + echo "******** Note: skipping $CERTNAM due to unreachable AIA location" + set ERR=0 + else + $cmd + set ERR=$status + endif + + if($ERR == 1) then + echo "******** Note: $CERTNAM is expired" + else + if($ERR != 0) then + echo "++++++++ Verification error on $CERTNAM" + $CERTCRL -c $certFile -s -a -f -v + set GOT_ERROR=1 + endif + endif +end + +if($GOT_ERROR == 1) then + echo ++++ TEST FAILED ++++ + exit(1) +endif + +set cmd="rm -rf $CERTS_DIR" +if ($QUIET == NO) then + echo $cmd +endif +# $cmd || exit(1) + +if ($QUIET == NO) then + echo "...intermedTest complete" +endif diff --git a/SecurityTests/clxutils/caVerify/Makefile b/SecurityTests/clxutils/caVerify/Makefile new file mode 100644 index 00000000..685de741 --- /dev/null +++ b/SecurityTests/clxutils/caVerify/Makefile @@ -0,0 +1,55 @@ +# name of executable to build +EXECUTABLE= caVerify +# C++ source (with .cpp extension) +CPSOURCE= caVerify.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= + +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= ssRootCert.der ssRootTBS.der ssSubjCert.der ssSubjTBS.der + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/clxutils/caVerify/caVerify.cpp b/SecurityTests/clxutils/caVerify/caVerify.cpp new file mode 100644 index 00000000..e19d3302 --- /dev/null +++ b/SecurityTests/clxutils/caVerify/caVerify.cpp @@ -0,0 +1,648 @@ +/* Copyright (c) 1998,2003-2006,2008 Apple Inc. + * + * caVerify.cpp + * + * Verify proper detection of basicConstraints.cA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* define nonzero to build on Puma */ +#define PUMA_BUILD 0 + +/* default key and signature algorithm */ +#define SIG_ALG_DEFAULT CSSM_ALGID_SHA1WithRSA +#define KEY_ALG_DEFAULT CSSM_ALGID_RSA + +#define NUM_CERTS_DEF 5 /* default is random from 2 to this */ +#define NUM_LOOPS_DEF 100 + +#if PUMA_BUILD +extern "C" { + void cssmPerror(const char *how, CSSM_RETURN error); +} +#endif /* PUMA_BUILD */ + +static void usage(char **argv) +{ + printf("Usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" n=numCerts (default=random from 2 to %d)\n", NUM_CERTS_DEF); + printf(" a=alg where alg is s(RSA/SHA1), 5(RSA/MD5), f(FEE/MD5), " + "F(FEE/SHA1), e(ECDSA), E(ANSI/ECDSA), 6(ECDSA/SHA256)\n"); + printf(" k=keySizeInBits\n"); + printf(" c (dump certs on error)\n"); + printf(" l=numLoops (default = %d)\n", NUM_LOOPS_DEF); + exit(1); +} + +void showCerts( + const CSSM_DATA *certs, + unsigned numCerts) +{ + unsigned i; + + for(i=0; i=0; dex--) { + thisCert = &certs[dex]; + + thisCert->Data = NULL; + thisCert->Length = 0; + + sprintf(nameStr, "%s%04d", nameBase, dex); + if(issuerName == NULL) { + /* last (root) cert - subject same as issuer */ + issuerName = CB_BuildX509Name(&nameOid, 1); + /* self-signed */ + signerKey = &privKeys[dex]; + } + else { + /* previous subject becomes current issuer */ + CB_FreeX509Name(issuerName); + issuerName = subjectName; + signerKey = &privKeys[dex+1]; + } + subjectName = CB_BuildX509Name(&nameOid, 1); + if((subjectName == NULL) || (issuerName == NULL)) { + printf("Error creating X509Names\n"); + crtn = CSSMERR_CSSM_MEMORY_ERROR; + break; + } + + /* + * not before/after in Y2k-compliant generalized time format. + * These come preformatted from our caller. + */ + notBefore = CB_BuildX509Time(0, notBeforeStr); + notAfter = CB_BuildX509Time(0, notAfterStr); + + /* + * Cook up cert template + * Note serial number would be app-specified in real world + */ + rawCert = CB_MakeCertTemplate(clHand, + 0x12345 + dex, // serial number + issuerName, + subjectName, + notBefore, + notAfter, + &pubKeys[dex], + sigAlg, + NULL, // subj unique ID + NULL, // issuer unique ID + extensions[dex], // extensions + numExtensions[dex]); // numExtensions + + if(rawCert == NULL) { + crtn = CSSM_ERRCODE_INTERNAL_ERROR; + break; + } + + /* Free the stuff we allocd to get here */ + CB_FreeX509Time(notBefore); + CB_FreeX509Time(notAfter); + + /**** sign the cert ****/ + /* 1. get a signing context */ + crtn = CSSM_CSP_CreateSignatureContext(cspHand, + sigAlg, + NULL, // no passphrase for now + signerKey, + &signContext); + if(crtn) { + printError("CreateSignatureContext", crtn); + break; + } + + /* 2. use CL to sign the cert */ + signedCert.Data = NULL; + signedCert.Length = 0; + crtn = CSSM_CL_CertSign(clHand, + signContext, + rawCert, // CertToBeSigned + NULL, // SignScope per spec + 0, // ScopeSize per spec + &signedCert); + if(crtn) { + printError("CSSM_CL_CertSign", crtn); + break; + } + + /* 3. delete signing context */ + crtn = CSSM_DeleteContext(signContext); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + break; + } + + /* + * CSSM_CL_CertSign() returned us a mallocd CSSM_DATA. Copy + * its fields to caller's cert. + */ + certs[dex] = signedCert; + + /* and the raw unsigned cert as well */ + appFreeCssmData(rawCert, CSSM_TRUE); + rtn = 0; + } + + /* free resources */ + if(issuerName != NULL) { + CB_FreeX509Name(issuerName); + } + if(subjectName != NULL) { + CB_FreeX509Name(subjectName); + } + return crtn; +} + +static int doTest( + CSSM_CSP_HANDLE cspHand, // CSP handle + CSSM_CL_HANDLE clHand, // CL handle + CSSM_TP_HANDLE tpHand, // TP handle + unsigned numCerts, // >= 2 + CSSM_KEY_PTR pubKeys, + CSSM_KEY_PTR privKeys, + CSSM_ALGORITHMS sigAlg, + CSSM_BOOL expectFail, + CSSM_BOOL dumpCerts, + CSSM_BOOL quiet) +{ + CSSM_DATA_PTR certs; + CSSM_X509_EXTENSION **extens; + unsigned *numExtens; + char *notBeforeStr = genTimeAtNowPlus(0); + char *notAfterStr = genTimeAtNowPlus(10000); + unsigned certDex; + CE_BasicConstraints *bc; + CSSM_X509_EXTENSION *thisExten; + CE_BasicConstraints *thisBc; + const char *failMode = "not set - internal error"; + CSSM_RETURN crtn; + unsigned badCertDex = 0; + + certs = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA) * numCerts); + memset(certs, 0, sizeof(CSSM_DATA) * numCerts); + + /* + * For now just zero or one extension per cert - basicConstraints. + * Eventually we'll want to test keyUsage as well. + */ + extens = (CSSM_X509_EXTENSION **)malloc(sizeof(CSSM_X509_EXTENSION *) * numCerts); + memset(extens, 0, sizeof(CSSM_X509_EXTENSION *) * numCerts); + numExtens = (unsigned *)malloc(sizeof(unsigned) * numCerts); + bc = (CE_BasicConstraints *)malloc(sizeof(CE_BasicConstraints) * numCerts); + + /* + * Set up all extensions for success + */ + for(certDex=0; certDexextnId = CSSMOID_BasicConstraints; + thisExten->critical = CSSM_TRUE; + thisExten->format = CSSM_X509_DATAFORMAT_PARSED; + thisExten->value.parsedValue = thisBc; + thisExten->BERvalue.Data = NULL; + thisExten->BERvalue.Length = 0; + + if(certDex == 0) { + /* leaf - flip coin to determine presence of basicConstraints */ + int coin = genRand(1,2); + if(coin == 1) { + /* basicConstraints, !cA */ + thisBc->cA = CSSM_FALSE; + thisBc->pathLenConstraintPresent = CSSM_FALSE; + thisBc->pathLenConstraint = 0; + } + else { + /* !basicConstraints, !cA by default */ + numExtens[certDex] = 0; + } + } + else if(certDex == (numCerts-1)) { + /* root - flip coin to determine presence of basicConstraints */ + int coin = genRand(1,2); + if(coin == 1) { + /* basicConstraints, cA */ + thisBc->cA = CSSM_TRUE; + /* flip coin to determine present of pathLenConstraint */ + coin = genRand(1,2); + if(coin == 1) { + thisBc->pathLenConstraintPresent = CSSM_FALSE; + thisBc->pathLenConstraint = 0; + } + else { + thisBc->pathLenConstraintPresent = CSSM_TRUE; + thisBc->pathLenConstraint = genRand(certDex-1, numCerts+1); + } + } + else { + /* !basicConstraints, cA by default */ + numExtens[certDex] = 0; + } + } + else { + /* intermediate = cA required */ + thisBc->cA = CSSM_TRUE; + /* flip coin to determine presence of pathLenConstraint */ + int coin = genRand(1,2); + if(coin == 1) { + thisBc->pathLenConstraintPresent = CSSM_FALSE; + thisBc->pathLenConstraint = 0; + } + else { + thisBc->pathLenConstraintPresent = CSSM_TRUE; + thisBc->pathLenConstraint = genRand(certDex-1, numCerts+1); + } + } + } + + if(expectFail) { + /* introduce a failure */ + if(numCerts == 2) { + /* only possible failure is explicit !cA in root */ + /* don't assume presence of BC exten */ + badCertDex = 1; + thisExten = extens[badCertDex]; + thisBc = &bc[badCertDex]; + thisBc->cA = CSSM_FALSE; + thisBc->pathLenConstraintPresent = CSSM_FALSE; + bc->pathLenConstraint = 0; + numExtens[badCertDex] = 1; + failMode = "Explicit !cA in root"; + } + else { + /* roll the dice to select an intermediate cert */ + badCertDex = genRand(1, numCerts-2); + thisExten = extens[badCertDex]; + if((thisExten == NULL) || (numExtens[badCertDex] == 0)) { + printf("***INTERNAL SCREWUP\n"); + exit(1); + } + thisBc = &bc[badCertDex]; + + /* + * roll die: fail by + * -- no BasicConstraints + * -- !cA + * -- bad pathLenConstraint + */ + int die = genRand(1,3); + if((die == 1) && + (badCertDex != 1)) { // last cA doesn't need pathLenConstraint + thisBc->pathLenConstraintPresent = CSSM_TRUE; + thisBc->pathLenConstraint = badCertDex - 2; // one short + failMode = "Short pathLenConstraint"; + } + else if(die == 2) { + thisBc->cA = CSSM_FALSE; + failMode = "Explicit !cA in intermediate"; + } + else { + /* no extension */ + numExtens[badCertDex] = 0; + failMode = "No BasicConstraints in intermediate"; + } + } + } + if(!quiet && expectFail) { + printf(" ...bad cert at index %d: %s\n", badCertDex, failMode); + } + + /* here we go - create cert chain */ + crtn = tpGenCertsExten(cspHand, + clHand, + sigAlg, + numCerts, + "caVerify", // nameBase + pubKeys, + privKeys, + extens, + numExtens, + certs, + notBeforeStr, + notAfterStr); + if(crtn) { + printError("tpGenCertsExten", crtn); + return crtn; // and leak like crazy + } + + CSSM_CERTGROUP cgrp; + memset(&cgrp, 0, sizeof(CSSM_CERTGROUP)); + cgrp.NumCerts = numCerts; + #if PUMA_BUILD + cgrp.CertGroupType = CSSM_CERTGROUP_ENCODED_CERT; + #else + /* Jaguar */ + cgrp.CertGroupType = CSSM_CERTGROUP_DATA; + #endif /* PUMA_BUILD */ + cgrp.CertType = CSSM_CERT_X_509v3; + cgrp.CertEncoding = CSSM_CERT_ENCODING_DER; + cgrp.GroupList.CertList = certs; + + #if PUMA_BUILD + crtn = tpCertGroupVerify(tpHand, + clHand, + cspHand, + NULL, // DlDbList + &CSSMOID_APPLE_X509_BASIC, // SSL requires built-in root match + &cgrp, + /* pass in OUR ROOT as anchors */ + (CSSM_DATA_PTR)&certs[numCerts-1], // anchorCerts + 1, + CSSM_TP_STOP_ON_POLICY, + CSSM_FALSE, // allowExpired + NULL); // vfyResult + #else + /* Jaguar */ + crtn = tpCertGroupVerify(tpHand, + clHand, + cspHand, + NULL, // DlDbList + &CSSMOID_APPLE_TP_SSL, // may want to parameterize this + NULL, // fieldOpts for server name + NULL, // actionDataPtr for allow expired + NULL, // policyOpts + &cgrp, + /* pass in OUR ROOT as anchors */ + (CSSM_DATA_PTR)&certs[numCerts-1], // anchorCerts + 1, + CSSM_TP_STOP_ON_POLICY, + NULL, // cssmTimeStr + NULL); // vfyResult + #endif /* PUMA_BUILD */ + if(expectFail) { + if(crtn != CSSMERR_TP_VERIFY_ACTION_FAILED) { + cssmPerror("***Expected error TP_VERIFY_ACTION_FAILED; got ", crtn); + printf(" Expected failure due to %s\n", failMode); + if(dumpCerts) { + showCerts(certs, numCerts); + writeCerts(certs, numCerts); + } + return testError(quiet); + } + } + else if(crtn) { + cssmPerror("Unexpected failure on tpCertGroupVerify", crtn); + if(dumpCerts) { + showCerts(certs, numCerts); + } + return testError(quiet); + } + + /* clean up */ + return 0; +} + +int main(int argc, char **argv) +{ + CSSM_CL_HANDLE clHand; // CL handle + CSSM_CSP_HANDLE cspHand; // CSP handle + CSSM_TP_HANDLE tpHand; + CSSM_KEY_PTR pubKeys; + CSSM_KEY_PTR privKeys; + CSSM_RETURN crtn; + int arg; + unsigned certDex; + unsigned loopNum; + unsigned maxCerts; + + /* user-spec'd variables */ + CSSM_ALGORITHMS keyAlg = KEY_ALG_DEFAULT; + CSSM_ALGORITHMS sigAlg = SIG_ALG_DEFAULT; + uint32 keySizeInBits = CSP_KEY_SIZE_DEFAULT; + unsigned numCerts = 0; // means random per loop + unsigned numLoops = NUM_LOOPS_DEF; + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL dumpCerts = CSSM_FALSE; + + for(arg=1; arg197;7#e;$!64Dw)FK7v)S{Biw9MqhlFa-(1;^5ojC_zT137VC15*P-12Y3KhyrrWKwKkZ zQ%h6JD1&rV2M8Mof{f=7<_b?N&dAJ5FUij{6foce39^f@2d5^Ml;oruN*IWN-6_KF zn44IYpQo3cp9^uHxPd50hFOHKyu4g55iV=cI3L;XjI0dIjlB#8jh#%5jSPz~?Ea^I ze44}Dd2`Y;pTxUmF4)zSS$6aMhkIRe*C);PJtXbAdPNb3L`6|X|I$sr!Vfq^h&j!? z7E_^7dw9;%g3p=No9{~6x5sX?)#_So=(0D*VCN==Q#aRoJDQ!V{!#U;<+^GO}nGs2Qlh_y&w^5>VIXCl?o>7;KOWQ^m-` zl4uaWFm^$-L8L*rL8usKW^Q77s(yNAnt`H$ya78Kt2Q4qlN5_c|I^D-ZEJe_vJanc z$hzVop;IlXXP_#k47DRCKRqAC4*jxXuo%cB)GWYU$Dmi;k~MW#YiafDzNWzWl6 +#include +#include /* private */ +#include /* private */ +#include +#include /* private */ + +static void usage(char **argv) +{ + printf("Usage:\n"); + printf(" %s certFileName [d(isable intermediates) [f filebase] [n(o cert dump)]\n", argv[0]); + exit(1); +} + +int main(int argc, char **argv) +{ + unsigned char *certData = NULL; // subject cert, raw data + unsigned certDataLen = 0; + OSStatus ortn; + SecTrustRef secTrust = NULL; + CFMutableArrayRef subjCerts = NULL; + SecPolicyRef policy = NULL; + SecPolicySearchRef policySearch = NULL; + SecTrustResultType secTrustResult; + CSSM_RETURN crtn = CSSM_OK; + CSSM_TP_APPLE_EVIDENCE_INFO *dummyEv; // not used + CFArrayRef certChain = NULL; // constructed chain + CFIndex numCerts; + bool disableLocalIntermediates = false; + char *fileBase = NULL; + bool enableCertDump = true; + + if(argc < 2) { + usage(argv); + } + if(readFile(argv[1], &certData, &certDataLen)) { + printf("***Error reading cert from %s. Aborting.\n", argv[1]); + exit(1); + } + for(int arg=2; arg 0)) { + char fname[200]; + sprintf(fname, "%s_%u", fileBase, i); + if(writeFile(fname, cd.Data, cd.Length)) { + printf("***Error writing to %s\n", fname); + } + else { + printf("...write %lu bytes to %s\n", cd.Length, fname); + } + } + } + } +errOut: + if(certData) { + /* mallocds by readFile() */ + free(certData); + } + if(secTrust) { + CFRelease(secTrust); + } + if(subjCerts) { + CFRelease(subjCerts); + } + if(policy) { + CFRelease(policy); + } + if(policySearch) { + CFRelease(policySearch); + } + return (int)ortn; +} diff --git a/SecurityTests/clxutils/certChain/keybank_v3.100.cer b/SecurityTests/clxutils/certChain/keybank_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..fe390de4a376c4ba9ed872b205d63da6ae34b53c GIT binary patch literal 1039 zcmXqLV&OJuVlG+0%*4pVB#^ED{^XasCbbh0zm`?y?F%vBW#iOp^Jx3d%gD&W%3#pA z%TV4xmW?@-g-cj0EVU>zI5Ry@A*86ZxJ1D(wWK`1DBDonKoq2aTbK`~Ku5tdFImsf z*uW4Xp#_rwikGAoYY6@zlxG*vN4Dc5vslJi$kT>x3@7oS4|4+@n3M zdOP8r+i&`lTp(O;lKED{ckhvlXRo)^g?!AIe$zqCQ0&!OzKVydeh18V zZjiKhJ+qY~U+l%xmK~D5`uXPaxCwW(w|7N{v_0WEv`#=;#(H00V}$tH z`6nI;m;HG(@hB5BBLm~&CPp!XCPpD}$jS<{Fc~m_!&R1_g@u`kb%B8!(0{V>EcOPr z2G$EK7nrx1W|Wi^Sn2C07v-QuI4DgRqof%~lFM~M7c(%%f*$$sZ?4HY zwQljI^XBu+uE#m#h^(^wrStUH>~}X_yeVa!kfhUhJaLlc-QuPLKJNa)^5z*r2dXF5 z1YNH>WGS$6@0q#ZX8!JZw|^$D|C-6+|97oOJT$S9T`c>5`--p}2Bv*1@0ZOLOikO@ cy;>nVsYYn=@^2?gZZO%E_jT<*>3R1I032;ebpQYW literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certChain/keybank_v3.101.cer b/SecurityTests/clxutils/certChain/keybank_v3.101.cer new file mode 100644 index 0000000000000000000000000000000000000000..8b066bffa87a57c8fcca07904f178d81905682e7 GIT binary patch literal 906 zcmXqLVs0~NVtT)TnTe5!Nuc7L$32N?g~F334{w#NzI)JsmyJ`a&7D}zD2 zA-4f18*?ZNn=n&ou%WntD2T%)%omnglo_0vo~NVWnU}0*Xl`H%lHeBBbIwUDE>DJm^4QSeJGDbFv;hPjFx!&Sxxh7eb2 z!F77(m82HsfnAZ9qY#{0RF+z#;OwZNs{nPlp{Id6M3X~#dAS}?I4)ylU@SgI~c)qc4D3hU)P&&;e>eelVN-u8TzO|fg}rjL7HO?P@b z%Y;kx%F39p4yt!=vL7_sRGM?-)b7Rq!qf|$S0#Tnu$!#$^w&pD>(ASL{Vc!7ct-6w zD0_KR*S`XTsZOW=X$N*k*;xHl@}IDYX?gG*f0O5{SvFPYGchwVFfMLjO>hz23iIhY#iEbz{J7M#3&|{ zQBqP+Y^AS{EvO7kK&HsE=o)AnXf9A+pxUMkQVvv|T$F(~& zm_^Kta269AC&V>QER1YiFo$t48gPT`;%8w2CTlhWLAWYLMyL>Kx@HDOfO71+Wh$(H z%Pwb0UEAfxwknICc|zKz4a*MAJ1Ms~G)$&)>UV=JICs~0Yww!s^{>EBI`f*% zcYpSypTwhl7WJ>;?qa*W^Gfzn*@#=>L5~$bUb-H2_37%!YQ?IytSkS-1+9X4=Oirf cx*7LGmPd1yFnem7{QfN`n}X-)F!d_~04tFr3IG5A literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certInCrl/Makefile b/SecurityTests/clxutils/certInCrl/Makefile new file mode 100644 index 00000000..0cb39b1d --- /dev/null +++ b/SecurityTests/clxutils/certInCrl/Makefile @@ -0,0 +1,54 @@ +# name of executable to build +EXECUTABLE= certInCrl +# C++ source (with .cpp extension) +CPSOURCE=certInCrl.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/clxutils/certInCrl/certInCrl.cpp b/SecurityTests/clxutils/certInCrl/certInCrl.cpp new file mode 100644 index 00000000..372dc44e --- /dev/null +++ b/SecurityTests/clxutils/certInCrl/certInCrl.cpp @@ -0,0 +1,90 @@ +/* + * certInCrl.c - simple "see if cert is in CRL" + */ +#include +#include +#include +#include +#include +#include +#include + +static void usage(char **argv) +{ + printf("Usage: %s certFile crlFile [l=loops]\n", argv[0]); + exit(1); +} + +int main(int argc, char **argv) +{ + CSSM_DATA cert; + CSSM_DATA crl; + int rtn; + CSSM_CL_HANDLE clHand; + CSSM_RETURN crtn; + int loops = 1; + int loop; + int arg; + + if(argc < 3) { + usage(argv); + } + for(arg=3; arg +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" -p -- pause for leaks check\n"); + printf(" -q -- quiet\n"); + /* etc. */ + exit(1); +} + +#define KEY_SIZE 1024 +#define KEY_ALG CSSM_ALGID_RSA +#define SIG_ALG CSSM_ALGID_SHA1WithRSA +#define CERT_FILE_OUT "/tmp/certLabelTest.cer" + +/* + * Here's the definitive string for Radar 3529689. + * BER tag = Teletex/T61, encoding = kCFStringEncodingISOLatin1. + * I hope Herr Petersen does not mind. + */ +static const unsigned char JurgenPetersen[] = +{ + 0x4a, 0xf8, 0x72, 0x67, 0x65, 0x6e, 0x20, 0x4e, + 0xf8, 0x72, 0x67, 0x61, 0x61, 0x72, 0x64, 0x20, + 0x50, 0x65, 0x74, 0x65, 0x72, 0x73, 0x65, 0x6e +}; + +/* + * Name/OID pair used in buildX509Name(). + * This logic is like the CB_BuildX509Name() code in clAppUtils/CertBuilderApp.cpp, + * with the addition of the berTag specification, and data is specified as a void * + * and size_t. + */ +typedef struct { + const void *nameVal; + CSSM_SIZE nameLen; + const CSSM_OID *oid; + CSSM_BER_TAG berTag; +} NameOid; + +/* + * Build up a CSSM_X509_NAME from an arbitrary list of name/OID/tag triplets. + * We do one a/v pair per RDN. + */ +static CSSM_X509_NAME *buildX509Name( + const NameOid *nameArray, + unsigned numNames) +{ + CSSM_X509_NAME *top = (CSSM_X509_NAME *)appMalloc(sizeof(CSSM_X509_NAME), 0); + if(top == NULL) { + return NULL; + } + top->numberOfRDNs = numNames; + top->RelativeDistinguishedName = + (CSSM_X509_RDN_PTR)appMalloc(sizeof(CSSM_X509_RDN) * numNames, 0); + if(top->RelativeDistinguishedName == NULL) { + return NULL; + } + CSSM_X509_RDN_PTR rdn; + const NameOid *nameOid; + unsigned nameDex; + for(nameDex=0; nameDexRelativeDistinguishedName[nameDex]; + nameOid = &nameArray[nameDex]; + rdn->numberOfPairs = 1; + rdn->AttributeTypeAndValue = (CSSM_X509_TYPE_VALUE_PAIR_PTR) + appMalloc(sizeof(CSSM_X509_TYPE_VALUE_PAIR), 0); + CSSM_X509_TYPE_VALUE_PAIR_PTR atvp = rdn->AttributeTypeAndValue; + if(atvp == NULL) { + return NULL; + } + appCopyCssmData(nameOid->oid, &atvp->type); + atvp->valueType = nameOid->berTag; + atvp->value.Length = nameOid->nameLen; + atvp->value.Data = (uint8 *)CSSM_MALLOC(nameOid->nameLen); + memmove(atvp->value.Data, nameOid->nameVal, nameOid->nameLen); + } + return top; +} + +/* just make these static and reuse them */ +static CSSM_X509_TIME *notBefore; +static CSSM_X509_TIME *notAfter; + +/* + * Core test routine. + * -- build a cert with issuer and subject as per specified name components + * -- extract inferred label + * -- compare inferred label to expected value + * -- if labelIsCommonName true, verify that SecCertificateCopyCommonName() yields + * the same string as inferred label + */ +static int doTest( + const char *testName, + bool quiet, + CSSM_CSP_HANDLE cspHand, + CSSM_CL_HANDLE clHand, + CSSM_KEY_PTR privKey, + CSSM_KEY_PTR pubKey, + + /* input names - one or two */ + const void *name1Val, + CSSM_SIZE name1Len, + CSSM_BER_TAG berTag1, + const CSSM_OID *name1Oid, + const void *name2Val, // optional + CSSM_SIZE name2Len, + CSSM_BER_TAG berTag2, + const CSSM_OID *name2Oid, + + /* expected label */ + CFStringRef expectedLabel, + bool labelIsCommonName) +{ + if(!quiet) { + printf("...%s\n", testName); + } + + /* build the subject/issuer name */ + NameOid nameArray[2] = { {name1Val, name1Len, name1Oid, berTag1 }, + {name2Val, name2Len, name2Oid, berTag2 } }; + unsigned numNames = name2Val ? 2 : 1; + + CSSM_X509_NAME *name = buildX509Name(nameArray, numNames); + if(name == NULL) { + printf("***buildX509Name screwup\n"); + return -1; + } + + /* build the cert template */ + CSSM_DATA_PTR certTemp = CB_MakeCertTemplate( + clHand, 0x123456, + name, name, + notBefore, notAfter, + pubKey, SIG_ALG, + NULL, NULL, // subject/issuer UniqueID + NULL, 0); // extensions + if(certTemp == NULL) { + printf("***CB_MakeCertTemplate screwup\n"); + return -1; + } + + /* sign the cert */ + CSSM_DATA signedCert = {0, NULL}; + CSSM_CC_HANDLE sigHand; + CSSM_RETURN crtn = CSSM_CSP_CreateSignatureContext(cspHand, + SIG_ALG, + NULL, // no passphrase for now + privKey, + &sigHand); + if(crtn) { + /* should never happen */ + cssmPerror("CSSM_CSP_CreateSignatureContext", crtn); + return 1; + } + crtn = CSSM_CL_CertSign(clHand, + sigHand, + certTemp, // CertToBeSigned + NULL, // SignScope per spec + 0, // ScopeSize per spec + &signedCert); + if(crtn) { + cssmPerror("CSSM_CL_CertSign", crtn); + return 1; + } + CSSM_DeleteContext(sigHand); + CSSM_FREE(certTemp->Data); + CSSM_FREE(certTemp); + + /* + * OK, we have a signed cert. + * Turn it into a SecCertificateRef and get the inferred label. + */ + OSStatus ortn; + SecCertificateRef certRef; + ortn = SecCertificateCreateFromData(&signedCert, + CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, + &certRef); + if(ortn) { + cssmPerror("SecCertificateCreateFromData", ortn); + return -1; + } + CFStringRef inferredLabel; + ortn = SecCertificateInferLabel(certRef, &inferredLabel); + if(ortn) { + cssmPerror("SecCertificateCreateFromData", ortn); + return -1; + } + CFComparisonResult res = CFStringCompare(inferredLabel, expectedLabel, 0); + if(res != kCFCompareEqualTo) { + fprintf(stderr, "*** label miscompare in test '%s' ***\n", testName); + fprintf(stderr, "expected label : "); + CFShow(expectedLabel); + fprintf(stderr, "inferred label : "); + CFShow(inferredLabel); + if(writeFile(CERT_FILE_OUT, signedCert.Data, signedCert.Length)) { + fprintf(stderr, "***Error writing cert to %s\n", CERT_FILE_OUT); + } + else { + fprintf(stderr, "...write %lu bytes to %s\n", (unsigned long)signedCert.Length, + CERT_FILE_OUT); + } + return -1; + } + + if(labelIsCommonName) { + CFStringRef commonName = NULL; + ortn = SecCertificateCopyCommonName(certRef, &commonName); + if(ortn) { + cssmPerror("SecCertificateCopyCommonName", ortn); + return -1; + } + res = CFStringCompare(inferredLabel, commonName, 0); + if(res != kCFCompareEqualTo) { + printf("*** CommonName miscompare in test '%s' ***\n", testName); + printf("Common Name : '"); + CFShow(commonName); + printf("'\n"); + printf("inferred label : '"); + CFShow(inferredLabel); + printf("'\n"); + if(writeFile(CERT_FILE_OUT, signedCert.Data, signedCert.Length)) { + printf("***Error writing cert to %s\n", CERT_FILE_OUT); + } + else { + printf("...write %lu bytes to %s\n", (unsigned long)signedCert.Length, + CERT_FILE_OUT); + } + return -1; + } + CFRelease(commonName); + } + CFRelease(certRef); + CSSM_FREE(signedCert.Data); + CB_FreeX509Name(name); + CFRelease(inferredLabel); + return 0; +} + +int main(int argc, char **argv) +{ + bool quiet = false; + bool doPause = false; + + int arg; + while ((arg = getopt(argc, argv, "pqh")) != -1) { + switch (arg) { + case 'q': + quiet = true; + break; + case 'p': + doPause = true; + break; + case 'h': + usage(argv); + } + } + if(optind != argc) { + usage(argv); + } + + testStartBanner("certLabelTest", argc, argv); + + CSSM_CL_HANDLE clHand = clStartup(); + CSSM_CSP_HANDLE cspHand = cspStartup(); + + /* create a key pair */ + CSSM_RETURN crtn; + CSSM_KEY pubKey; + CSSM_KEY privKey; + + crtn = cspGenKeyPair(cspHand, KEY_ALG, + "someLabel", 8, + KEY_SIZE, + &pubKey, CSSM_FALSE, CSSM_KEYUSE_ANY, CSSM_KEYBLOB_RAW_FORMAT_NONE, + &privKey, CSSM_FALSE, CSSM_KEYUSE_ANY, CSSM_KEYBLOB_RAW_FORMAT_NONE, + CSSM_FALSE); + if(crtn) { + printf("***Error generating RSA key pair. Aborting.\n"); + exit(1); + } + + /* common params, reused for each test */ + notBefore = CB_BuildX509Time(0); + notAfter = CB_BuildX509Time(100000); + + /* + * Grind thru test cases. + */ + int ourRtn; + + /* very basic */ + ourRtn = doTest("simple ASCII common name", quiet, + cspHand, clHand, &privKey, &pubKey, + "Simple Name", strlen("Simple Name"), BER_TAG_PRINTABLE_STRING, &CSSMOID_CommonName, + NULL, 0, BER_TAG_UNKNOWN, NULL, + CFSTR("Simple Name"), true); + if(ourRtn) { + exit(1); + } + + /* test concatentation of description */ + ourRtn = doTest("ASCII common name plus ASCII description", quiet, + cspHand, clHand, &privKey, &pubKey, + "Simple Name", strlen("Simple Name"), BER_TAG_PRINTABLE_STRING, &CSSMOID_CommonName, + "Description", strlen("Description"), BER_TAG_PRINTABLE_STRING, &CSSMOID_Description, + CFSTR("Simple Name (Description)"), false); + if(ourRtn) { + exit(1); + } + + /* basic, specifying UTF8 (should be same as PRINTABLE) */ + ourRtn = doTest("simple UTF8 common name", quiet, + cspHand, clHand, &privKey, &pubKey, + "Simple Name", strlen("Simple Name"), BER_TAG_PKIX_UTF8_STRING, &CSSMOID_CommonName, + NULL, 0, BER_TAG_UNKNOWN, NULL, + CFSTR("Simple Name"), true); + if(ourRtn) { + exit(1); + } + + /* label from org name instead of common name */ + ourRtn = doTest("label from OrgName", quiet, + cspHand, clHand, &privKey, &pubKey, + "Simple Name", strlen("Simple Name"), BER_TAG_PRINTABLE_STRING, &CSSMOID_OrganizationName, + NULL, 0, BER_TAG_UNKNOWN, NULL, + CFSTR("Simple Name"), false); + if(ourRtn) { + exit(1); + } + + /* label from orgUnit name instead of common name */ + ourRtn = doTest("label from OrgUnit", quiet, + cspHand, clHand, &privKey, &pubKey, + "Simple Name", strlen("Simple Name"), BER_TAG_PRINTABLE_STRING, &CSSMOID_OrganizationalUnitName, + NULL, 0, BER_TAG_UNKNOWN, NULL, + CFSTR("Simple Name"), false); + if(ourRtn) { + exit(1); + } + + /* label from orgUnit name, description is ignored (it's only used if the + * label comes from CommonName) */ + ourRtn = doTest("label from OrgUnit, description is ignored", quiet, + cspHand, clHand, &privKey, &pubKey, + "Simple Name", strlen("Simple Name"), BER_TAG_PRINTABLE_STRING, &CSSMOID_OrganizationalUnitName, + "Description", strlen("Description"), BER_TAG_PRINTABLE_STRING, &CSSMOID_Description, + CFSTR("Simple Name"), false); + if(ourRtn) { + exit(1); + } + + /* Radar 3529689: T61/Teletex, ISOLatin encoding, commonName only */ + CFStringRef t61Str = CFStringCreateWithBytes(NULL, JurgenPetersen, sizeof(JurgenPetersen), + kCFStringEncodingISOLatin1, true); + ourRtn = doTest("T61/Teletex name from Radar 3529689", quiet, + cspHand, clHand, &privKey, &pubKey, + JurgenPetersen, sizeof(JurgenPetersen), BER_TAG_TELETEX_STRING, &CSSMOID_CommonName, + NULL, 0, BER_TAG_UNKNOWN, NULL, + t61Str, true); + if(ourRtn) { + exit(1); + } + + /* Now convert that ISOLatin into Unicode and try with that */ + CFDataRef unicodeStr = CFStringCreateExternalRepresentation(NULL, t61Str, + kCFStringEncodingUnicode, 0); + if(unicodeStr == NULL) { + printf("***Error converting to Unicode\n"); + exit(1); + } + ourRtn = doTest("Unicode CommonName", quiet, + cspHand, clHand, &privKey, &pubKey, + CFDataGetBytePtr(unicodeStr), CFDataGetLength(unicodeStr), + BER_TAG_PKIX_BMP_STRING, &CSSMOID_CommonName, + NULL, 0, BER_TAG_UNKNOWN, NULL, + t61Str, true); + if(ourRtn) { + exit(1); + } + CFRelease(unicodeStr); + + /* Mix up ISOLatin Common Name and ASCII Description to ensure that the encodings + * of the two components are handled separately */ + CFMutableStringRef combo = CFStringCreateMutable(NULL, 0); + CFStringAppend(combo, t61Str); + CFStringAppendCString(combo, " (Description)", kCFStringEncodingASCII); + ourRtn = doTest("ISOLatin Common Name and ASCII Description", quiet, + cspHand, clHand, &privKey, &pubKey, + JurgenPetersen, sizeof(JurgenPetersen), BER_TAG_TELETEX_STRING, &CSSMOID_CommonName, + "Description", strlen("Description"), BER_TAG_PRINTABLE_STRING, &CSSMOID_Description, + combo, false); + if(ourRtn) { + exit(1); + } + CFRelease(combo); + CFRelease(t61Str); + + if(doPause) { + fpurge(stdin); + printf("Pausing for leaks testing; CR to continue: "); + getchar(); + } + if(!quiet) { + printf("...success\n"); + } + return 0; +} diff --git a/SecurityTests/clxutils/certSerialEncodeTest/Makefile b/SecurityTests/clxutils/certSerialEncodeTest/Makefile new file mode 100644 index 00000000..82188bf8 --- /dev/null +++ b/SecurityTests/clxutils/certSerialEncodeTest/Makefile @@ -0,0 +1,54 @@ +# name of executable to build +EXECUTABLE= certSerialEncodeTest +# C++ source (with .cpp extension) +CPSOURCE= certSerialEncodeTest.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= ssRootCert.der ssRootTBS.der ssSubjCert.der ssSubjTBS.der + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/clxutils/certSerialEncodeTest/certSerialEncodeTest.cpp b/SecurityTests/clxutils/certSerialEncodeTest/certSerialEncodeTest.cpp new file mode 100644 index 00000000..2027dde6 --- /dev/null +++ b/SecurityTests/clxutils/certSerialEncodeTest/certSerialEncodeTest.cpp @@ -0,0 +1,358 @@ +/* Copyright (c) 2006 Apple Computer, Inc. + * + * certSerialEncodeTest.cpp + * + * Verify proper encoding of unsigned integer as a DER_encoded signed integer. + * Verifies Radar 4471281. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SUBJ_KEY_LABEL "subjectKey" +#define ROOT_KEY_LABEL "rootKey" +/* default key and signature algorithm */ +#define SIG_ALG_DEFAULT CSSM_ALGID_SHA1WithRSA +#define SIG_OID_DEFAULT CSSMOID_SHA1WithRSA +#define KEY_ALG_DEFAULT CSSM_ALGID_RSA + +/* for write certs/keys option */ +#define ROOT_CERT_FILE_NAME "ssRootCert.cer" +#define SUBJ_CERT_FILE_NAME "ssSubjCert.cer" + +/* public key in ref form, TP supports this as of 1/30/02 */ +#define PUB_KEY_IS_REF CSSM_TRUE + +static void usage(char **argv) +{ + printf("Usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" w[rite certs]\n"); + printf(" p(ause for MallocDebug)\n"); + printf(" q(uiet)\n"); + exit(1); +} + +/* + * RDN components + */ +static CSSM_APPLE_TP_NAME_OID rootRdn[] = +{ + { "Apple Computer", &CSSMOID_OrganizationName }, + { "The Big Cheesy Debug Root", &CSSMOID_CommonName } +}; +#define NUM_ROOT_NAMES (sizeof(rootRdn) / sizeof(CSSM_APPLE_TP_NAME_OID)) + +/* test cases */ +typedef struct { + uint32 serialIn; /* --> CSSM_TP_SubmitCredRequest */ + CSSM_SIZE expectLen; + const uint8 *expect; +} SerialNumber; + +/* 0x7f */ +static const uint8 sn0_Data[1] = {0x7f}; +static const SerialNumber sn0 = {0x7f, 1, sn0_Data }; + +/* 0x80 */ +static const uint8 sn1_Data[2] = {0x00, 0x80}; +static const SerialNumber sn1 = {0x80, 2, sn1_Data }; + +/* 0x7ff */ +static const uint8 sn2_Data[2] = {0x07, 0xff}; +static const SerialNumber sn2 = {0x7ff, 2, sn2_Data }; + +/* 0x80ff */ +static const uint8 sn3_Data[3] = {0x00, 0x80, 0xff}; +static const SerialNumber sn3 = {0x80ff, 3, sn3_Data }; + +/* 0xfffffff */ +static const uint8 sn4_Data[4] = {0x0f, 0xff, 0xff, 0xff}; +static const SerialNumber sn4 = {0xfffffff, 4, sn4_Data }; + +/* 0x0fffffff */ +static const uint8 sn5_Data[4] = {0x0f, 0xff, 0xff, 0xff}; +static const SerialNumber sn5 = {0x0fffffff, 4, sn5_Data }; + +/* 0x80000000 */ +static const uint8 sn6_Data[5] = {0x00, 0x80, 0x00, 0x00, 0x00}; +static const SerialNumber sn6 = {0x80000000, 5, sn6_Data }; + +static const SerialNumber *serialNumbers[] = { + &sn0, &sn1, &sn2, &sn3, &sn4, &sn5, &sn6 +}; +#define NUM_SERIAL_NUMS (sizeof(serialNumbers) / sizeof(serialNumbers[0])) + +static int doTest( + CSSM_CL_HANDLE clHand, // CL handle + CSSM_CSP_HANDLE cspHand, // CSP handle + CSSM_TP_HANDLE tpHand, // TP handle + CSSM_KEY_PTR subjPubKey, + CSSM_KEY_PTR signerPrivKey, + uint32 serialNumIn, + CSSM_SIZE serialNumExpLen, + const uint8 *serialNumExp, + CSSM_BOOL quiet, + CSSM_BOOL writeBlobs) +{ + CSSM_DATA refId; // mallocd by CSSM_TP_SubmitCredRequest + CSSM_APPLE_TP_CERT_REQUEST certReq; + CSSM_TP_REQUEST_SET reqSet; + sint32 estTime; + CSSM_BOOL confirmRequired; + CSSM_TP_RESULT_SET_PTR resultSet; + CSSM_ENCODED_CERT *encCert; + CSSM_TP_CALLERAUTH_CONTEXT CallerAuthContext; + CSSM_FIELD policyId; + CSSM_RETURN crtn; + CSSM_DATA *signedRootCert; + int ourRtn = 0; + CSSM_DATA_PTR foundSerial = NULL; + CSSM_HANDLE resultHand = 0; + uint32 numFields; + + /* certReq for root */ + memset(&certReq, 0, sizeof(CSSM_APPLE_TP_CERT_REQUEST)); + certReq.cspHand = cspHand; + certReq.clHand = clHand; + certReq.serialNumber = serialNumIn; + certReq.numSubjectNames = NUM_ROOT_NAMES; + certReq.subjectNames = rootRdn; + certReq.numIssuerNames = 0; + certReq.issuerNames = NULL; + certReq.certPublicKey = subjPubKey; + certReq.issuerPrivateKey = signerPrivKey; + certReq.signatureAlg = CSSM_ALGID_SHA1WithRSA; + certReq.signatureOid = CSSMOID_SHA1WithRSA; + certReq.notBefore = 0; // now + certReq.notAfter = 10000; // seconds from now + certReq.numExtensions = 0; + certReq.extensions = NULL; + + reqSet.NumberOfRequests = 1; + reqSet.Requests = &certReq; + + /* a big CSSM_TP_CALLERAUTH_CONTEXT just to specify an OID */ + memset(&CallerAuthContext, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT)); + memset(&policyId, 0, sizeof(CSSM_FIELD)); + policyId.FieldOid = CSSMOID_APPLE_TP_LOCAL_CERT_GEN; + CallerAuthContext.Policy.NumberOfPolicyIds = 1; + CallerAuthContext.Policy.PolicyIds = &policyId; + + /* generate root cert */ + if(!quiet) { + printf("Creating root cert...\n"); + } + crtn = CSSM_TP_SubmitCredRequest(tpHand, + NULL, // PreferredAuthority + CSSM_TP_AUTHORITY_REQUEST_CERTISSUE, + &reqSet, + &CallerAuthContext, + &estTime, + &refId); + if(crtn) { + printError("CSSM_TP_SubmitCredRequest", crtn); + ourRtn = -1; + goto errOut; + } + crtn = CSSM_TP_RetrieveCredResult(tpHand, + &refId, + NULL, // CallerAuthCredentials + &estTime, + &confirmRequired, + &resultSet); + if(crtn) { + printError("CSSM_TP_RetrieveCredResult", crtn); + ourRtn = -1; + goto errOut; + } + if(resultSet == NULL) { + printf("***CSSM_TP_RetrieveCredResult returned NULL result set.\n"); + ourRtn = -1; + goto errOut; + } + encCert = (CSSM_ENCODED_CERT *)resultSet->Results; + signedRootCert = &encCert->CertBlob; + if(writeBlobs) { + writeFile(ROOT_CERT_FILE_NAME, signedRootCert->Data, signedRootCert->Length); + printf("...wrote %lu bytes to %s\n", signedRootCert->Length, + ROOT_CERT_FILE_NAME); + } + + /* make sure it self-verifies */ + crtn = CSSM_CL_CertVerify(clHand, 0 /* CCHandle */, + signedRootCert, signedRootCert, + NULL, 0); + if(crtn) { + cssmPerror("CSSM_CL_CertVerify", crtn); + printf("***Created cert does not self-verify\n"); + ourRtn = -1; + goto errOut; + } + + /* extract the field we're interested in verifying */ + crtn = CSSM_CL_CertGetFirstFieldValue(clHand, signedRootCert, + &CSSMOID_X509V1SerialNumber, &resultHand, &numFields, &foundSerial); + if(crtn) { + cssmPerror("CSSM_CL_CertGetFirstFieldValue(serialNumber)", crtn); + printf("***Can't obtain serial number\n"); + ourRtn = -1; + goto errOut; + } + CSSM_CL_CertAbortQuery(clHand, resultHand); + if(foundSerial->Length != serialNumExpLen) { + printf("***expected serialNumber len 0x%lu, got 0x%lu\n", + (unsigned long)serialNumExpLen, (unsigned long)foundSerial->Length); + ourRtn = -1; + goto errOut; + } + for(unsigned dex=0; dexData[dex] != serialNumExp[dex]) { + printf("***SerialNumber mismatch at index %u: exp %02X got %02X\n", + dex, (unsigned)serialNumExp[dex], + (unsigned)foundSerial->Data[dex]); + ourRtn = -1; + } + } + /* free retrieved serial number and the result set itself */ + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1SerialNumber, foundSerial); + CSSM_FREE(signedRootCert->Data); + CSSM_FREE(encCert); + CSSM_FREE(resultSet); + /* Per the spec, this is supposed to be Opaque to us and the TP is supposed to free + * it when it goes out of scope...but libsecurity_keychains's + * CertificateRequest::submitDotMac() frees this...that would have to change + * in order for the TP to free this properly. Someday maybe. No big deal. + */ + CSSM_FREE(refId.Data); +errOut: + return ourRtn; +} + +int main(int argc, char **argv) +{ + CSSM_CL_HANDLE clHand; // CL handle + CSSM_CSP_HANDLE cspHand; // CSP handle + CSSM_TP_HANDLE tpHand; // TP handle + CSSM_KEY rootPubKey; // root's RSA public key blob + CSSM_KEY rootPrivKey; // root's RSA private key - ref format + CSSM_RETURN crtn; + int arg; + unsigned dex; + int ourRtn = 0; + uint32 keySizeInBits = 512; + CSSM_BOOL doPause = CSSM_FALSE; + + /* user-spec'd variables */ + CSSM_BOOL writeBlobs = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + + for(arg=1; argserialIn); + } + ourRtn = doTest(clHand, cspHand, tpHand, + &rootPubKey, &rootPrivKey, + sn->serialIn, sn->expectLen, sn->expect, + quiet, writeBlobs); + if(ourRtn) { + break; + } + if(doPause) { + fpurge(stdin); + printf("Pausing for MallocDebug. a to abort, anything else to continue: "); + if(getchar() == 'a') { + break; + } + } + } + + cspFreeKey(cspHand, &rootPubKey); + cspFreeKey(cspHand, &rootPrivKey); + +abort: + if(cspHand != 0) { + CSSM_ModuleDetach(cspHand); + } + if(clHand != 0) { + CSSM_ModuleDetach(clHand); + } + if(tpHand != 0) { + CSSM_ModuleDetach(tpHand); + } + + if((ourRtn == 0) && !quiet) { + printf("certSerialEncodeTest test succeeded\n"); + } + return ourRtn; +} + + diff --git a/SecurityTests/clxutils/certTime/Makefile b/SecurityTests/clxutils/certTime/Makefile new file mode 100644 index 00000000..cfbe9701 --- /dev/null +++ b/SecurityTests/clxutils/certTime/Makefile @@ -0,0 +1,54 @@ +# name of executable to build +EXECUTABLE=certTime +# C++ source (with .cpp extension) +CPSOURCE= certTime.cpp extenCooker.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= -framework CoreFoundation + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/clxutils/certTime/anchor_0 b/SecurityTests/clxutils/certTime/anchor_0 new file mode 100644 index 0000000000000000000000000000000000000000..bcbddd2f3b1890d603d4b15a38386a1fe5248999 GIT binary patch literal 510 zcmXqLV*F*$#F)&)#JJdimyJ`a&7L6q z%T~h@p1<6F5ocOUn4Gz$boQ~tFRlM7 zI%VjF*7nSB0CQlyv#s%32iPt7BBlSF|>i$w0m3+uUVax5J$0xqstl775eef-j zEs8s?U7hy$pC3)kk`-4?JYUAmd%30R;nOJj N7K1sL=Py;g0RXU;zfAxD literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certTime/anchor_34 b/SecurityTests/clxutils/certTime/anchor_34 new file mode 100644 index 0000000000000000000000000000000000000000..d46fdbf75290f3e15abbe82b14fb562b6fcf912a GIT binary patch literal 1111 zcmXqLVhJ{AV&1cWnTe5!iILNQmyJ`a&7E-lI| zsZ_|!Q*cQvNmTGlEh*10$}U!L&rR|$)G^Qk>E#wyM$_w@lUQ7=V5Hy^}aTIpbmE~C!?5Da%xdYW?E))Vo9n)3CQAPu*G^QsRnZ5yp|RQ#s-##CI;q4rcvU& z2BwBa#)eSt@bPHleB?M}WMyD(>;=YSCsSi1!_66%_dhy+P|URQjqZBrJ;fs_=9Avd zw}WBZ zG1sIfXu2Vrq*mxJj)D>=$?fP5ydGB7XIy7qHMpuA?MZ8lT}UseRP$UzpXj&={(0JijR0P|-jhB+o4@kx^1oV5P5LUS6(OTAW%`QdC-8qL-YX zYba|V4N}4^ED{>xrwcN|EwiY&MAttlD>b>qKu(<3($c`(z|zpd*wDxzN}Sga$~7@C zHj5gx?rvgKLJnd^RtDxKMt%l^CPpr%CPqevbE_Kd7cWk%SY^l%I#qC6=!`{BgXr(CqYY+ljlL-z+fw_2l`4!?PF9zHIYVXlD7w?VJxXp2_U^JSDj! zE9)P3*~xuhl%AyTTrCw>ez2AOE^p5McWlSYvmECw=fD2@-4yZde_Hn~S$#yt@b2|( z7oU81e_yPBQ_$q=3$Ju8WY^pOkWt7W}Qv)-gm*uyOlfs^4qNCrKc}Owd-4!3P%-fU}~Jd z?*o5Jh(c0M=9P!O$9QKtGx7>e>#3N#KVZ>DmsMHk#jDQe^I!R)5*q)(M9eeIF2L<% za-oG`(vGB^pM%%tY}H;Qv`W&S^H$vR$;bLcIR1SwXpmUY*6Mqr_Ifw-zr3s8=ZdYF nq_aTz>70o{@>A}MPbogU`QX7qRt1KNy~07VE9}lP$e#cJidUEa literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certTime/anchor_76 b/SecurityTests/clxutils/certTime/anchor_76 new file mode 100644 index 0000000000000000000000000000000000000000..77e783a39ac84e67b76804a293f287933df5a9cf GIT binary patch literal 1492 zcmXqLV!dF{#Ij=nGZP~d6N}ZhfNld`HcqWJkGAi;jEtBr`ux z!LhU?BfluKq|#8&KnJ9ZSy&Zr0zUNya^k!Oh6culmWCF_KoBL)YXst&L%9R*z$Qi| zH>RRp-BHPSaBf zaZs`NF4cM`!sql7b*JeU<~Mg8e!|8a&9F33u7IWF(ZMTLtFN!MW|v^?``f(cRoYDn z>5Q(g;ZiepeSKSITXXZ?lq_p+@q<_U_oiA{O}$_nYUX#pGTcy0?nY#)XN1Cxy4CS@ z^Iu-`ebZdB@_5dTcbZbLr$UZytePrYDCecw z#e65r_23f8xO}s-hZk+w{x8PjQP7?rF3!&;>}FzSWMEv}#1v%E#N=mS%f_M2225G( zjEpRX2KolNFunm}n_@;uNkOrdzJ7jkae-c8X?__ff#s*A6$8^ws$Oz_t^q$V?Z^r< zGX7^_HDCr(z)+R~2`R8NF$w}Xyghd51EWFXZ-d4wFguu-3>uG1H695{ z&B;v6OHNe)rp%IzR0UiqF;yX{QXw&~QlTKRs07F=E-uYYEmlZOPEIW-ff$emHUMZy zoYn*fg18s6q57vQZhk#p;#e5O`)_nRYxHiC5sdk zB_@|-CZ`tbfYqb83z3;p6$0{swp8jFD8YTjC?*C9Ibgt*mzTrCO)n|eKo%4>d@N!t zBHiA(Z!c@^WRrYjX}R*l^p>pC@9!Hlt^>&{votO+L^Bp5Y*AOI?*%#{F8~z=Dc!S!21sOf%>3oaJKmKfb$fN$D@I z+>H%=oMAiXNG1G>J$Sw9j$p-wYq1BnUtMc7li8~4Oo*zbVPmzhQs6GPoQ1pR{bI@S zR4eJfRQ&pk!J=ocB9+>IO#jOF_tlw6OT>-@NxV`#xAEh%md2;MR<>z;a*m1>n!85s i=8C6WSOK)aiTW&Cy5CsxFu*cX^eV{R9Air5#8B literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certTime/anchor_80 b/SecurityTests/clxutils/certTime/anchor_80 new file mode 100644 index 0000000000000000000000000000000000000000..3a6ae297c879aeef6e9434d20f155201a9498f30 GIT binary patch literal 890 zcmXqLVlFdiVv1Y9%*4pV#9}4Q!fL?F#;Mij(e|B}k&%^^!649(+klgeIh2J>n90T4 zkjH=v#NiTV_V#r#+!G+qUTiI)6=OKU}bJuEmU^ z=B=T2vivvCccowL_?FtIIms+gqq zxFxU&UK@inh+b`unhu?G^UMqxBuKAM7(XH0E@$ zTsK|&AgLtf(fQNM=VtGGCeB-T`mN5i%bPE^w;idTyCm=QlO2~c56`j7pYzyH#9K+O z&g$@!FY9jaZeQ`k>L(L3BLm~&FoO^SAz=K;3NtePXW=kl15!+k3MGad6d62X+i-dt#19k0S7u~IeOWbs+V%eTaVOjt6wQ~G*?8k|!dL4zU#8qxS!TxXd71Mvo1dUZ_V2h7 z&kGl>{QvB*pCNG35jL0Hx6_MbzPjJ}D7dQpuhOmvHqV=y9~u^hD>5(1{+ep;d0*P7 zCEj4uf{$l;KIFC7GfXacnBA!pahU(A;pzAEzcs%%xOr~#MMKYB z8oyuN-tuNm);q0Tn=<1oCZ^jI^)u|RIjZ|$ZIkqsPJ!6t?*-oFaO+i1 z^U>%OZR4mvw{>kr?^d~abwAj=Ku>Nx`=sSQT=}oFu9fqBj%HKu?c2Y%OyUX;04e@k AI{*Lx literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certTime/anchor_9 b/SecurityTests/clxutils/certTime/anchor_9 new file mode 100644 index 0000000000000000000000000000000000000000..49386c3acb16dfc7fd56eca45252e80276635da9 GIT binary patch literal 1053 zcmXqLVv#gxVrFC#NGv$**%Lp*RrC3VWj6z&s|Eeg&#iN(bVMhXF?NjaIx3IRo#xrs%U3eKrTC7EfN$%!SI`FRSC5VJ}u zfo8iK8_0?CT3Q+!7yuCnM2Yhnn;DoJni(0JTAEr$4KL3&F)ATPCL=2Ya}y&!gFzD` z7gG}>Bg1+w-a}V)Zl~|meL6+`?$Uh^Hu&~$P7JfTR&)5vS-ZB=i#i@Xys;$n=+;O3 z4=!^Lh;y^-zB+B!)_jru0_W6)=drraHmnl9A%F8SlX>@A9rq7?jcm(#4R~IEx8YZi zy;J1&ZYk4==))(&GJTFp9GqCqeN~uY_MZ2LJ?z{P6k4^ePS|#~d%+o_yW9Udgl-Cu z30rrjx7_!*g70#}viBL2x+chRG=^{-UM8E02!?ppj>mUqq)g=Gg99KGn~Bc6L{O`83*o(C;g%>FAy9{nkp zup*wN_LI~%Ri{M$BVIe~I+>Um85og62$xvyPUb-;PZ_8OP(z;ynk7S+wD$~g8jO8 ztTs!G?YS-26jT&@&(ywea42NM3hU5?|HL%TI_)jVYq+iMvizJ&>=o$=GkE2krfg); zVYyJUn2A*>Ir(h!*53znld>~Q|Hc+L?) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "extenCooker.h" + +#define KEYSIZE_DEF 1024 +#define CL_KEY_VIA_GET_KEY 0 + +static void usage(char **argv) +{ + printf("Usage: %s op loops [options]\n", argv[0]); + printf("Op:\n"); + printf(" p parse\n"); + printf(" g parse & get all fields\n"); + #if CL_KEY_VIA_GET_KEY + printf(" t parse & get some fields, emulating TPCertInfo, GetKeyInfo\n"); + #else + printf(" t parse & get some fields, emulating TPCertInfo, fetchField(key)\n"); + #endif + printf(" c create\n"); + printf(" s create & sign\n"); + printf(" v verify\n"); + printf("Options:\n"); + printf(" b RSA blinding on\n"); + printf(" k=keysize (default = %d)\n", KEYSIZE_DEF); + exit(1); +} + +/* + * The certs we'll be parsing + */ +static const char *certNames[] = +{ + "anchor_0", // GTE CyberTrust Root, no extens + "anchor_9", // VeriSign, no extens + "anchor_34", // TrustCenter, 6 extens + "anchor_44", // USERTRUST, 5 extens, incl. cRLDistributionPoints + "anchor_76", // QuoVadis, 6 extens, incl. authorityInfoAccess + "anchor_80", // KMD-CA Kvalificeret3 6 extens +}; + +#define NUM_PARSED_CERTS (sizeof(certNames) / sizeof(certNames[0])) + +/* dummy RDN - subject and issuer - we aren't testing this */ +CB_NameOid dummyRdn[] = +{ + { "Apple Computer", &CSSMOID_OrganizationName }, + { "Doug Mitchell", &CSSMOID_CommonName } +}; +#define NUM_DUMMY_NAMES (sizeof(dummyRdn) / sizeof(CB_NameOid)) + +#define KEY_ALG CSSM_ALGID_RSA +#define SIG_ALG CSSM_ALGID_SHA1WithRSA +#define SUBJ_KEY_LABEL "subjectKey" + + +/* + * Set of extensions we'll be creating + */ +/* empty freeFcn means no extension-specific resources to free */ +#define NO_FREE NULL + +static ExtenTest extenTests[] = { + { kuCreate, kuCompare, NO_FREE, + sizeof(CE_KeyUsage), CSSMOID_KeyUsage, + "KeyUsage", 'k' }, + { ekuCreate, ekuCompare, NO_FREE, + sizeof(CE_ExtendedKeyUsage), CSSMOID_ExtendedKeyUsage, + "ExtendedKeyUsage", 'x' }, + { authKeyIdCreate, authKeyIdCompare, authKeyIdFree, + sizeof(CE_AuthorityKeyID), CSSMOID_AuthorityKeyIdentifier, + "AuthorityKeyID", 'a' }, + { genNamesCreate, genNamesCompare, genNamesFree, + sizeof(CE_GeneralNames), CSSMOID_SubjectAltName, + "SubjectAltName", 't' }, +}; + +#define MAX_EXTENSIONS (sizeof(extenTests) / sizeof(ExtenTest)) + +static int doParse( + CSSM_CL_HANDLE clHand, + const CSSM_DATA &cert, + unsigned loops) +{ + CSSM_HANDLE cacheHand; + CSSM_RETURN crtn; + + for(unsigned loop=0; loopKeyData.Data, 0); + appFree(subjPubKey, 0); + #else + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_CSSMKeyStruct, subjPubKeyData); + #endif + + crtn = CSSM_CL_CertAbortCache(clHand, cacheHand); + if(crtn) { + printError("CSSM_CL_CrlAbortCache", crtn); + return 1; + } + } + return 0; +} + +static int doGetFields( + CSSM_CL_HANDLE clHand, + const CSSM_DATA &cert, + unsigned loops) +{ + uint32 numFields; + CSSM_FIELD_PTR certFields; + CSSM_RETURN crtn; + + for(unsigned loop=0; loopData); + CSSM_FREE(rawCert); + } + return 0; +} + +typedef enum { + CTO_Parse, + CTO_GetFields, + CTO_GetSomeFields, + CTO_Create, // sign is an option for this one + CTO_Verify +} CT_Op; + +int main(int argc, char **argv) +{ + CSSM_CL_HANDLE clHand; + CSSM_CSP_HANDLE cspHand; + int arg; + int rtn; + char *argp; + unsigned i; + PresetParams params; + CSSM_DATA certData[NUM_PARSED_CERTS]; + + /* user-specificied params */ + CT_Op op; + unsigned loops = 0; + bool doSign = false; + const char *opStr = NULL; + bool rsaBlinding = false; + unsigned keySize = KEYSIZE_DEF; + + if(argc < 3) { + usage(argv); + } + switch(argv[1][0]) { + case 'p': + op = CTO_Parse; + opStr = "Parsed"; + break; + case 'g': + op = CTO_GetFields; + opStr = "Parsed with GetAllFields"; + break; + case 't': + op = CTO_GetSomeFields; + #if CL_KEY_VIA_GET_KEY + opStr = "Parsed with some GetFields and GetKeyInfo"; + #else + opStr = "Parsed with some GetFields"; + #endif + break; + case 'c': + op = CTO_Create; + opStr = "Created"; + break; + case 's': + op = CTO_Create; + opStr = "Created and Signed"; + doSign = true; + break; + case 'v': + op = CTO_Verify; + opStr = "Verified"; + break; + default: + usage(argv); + } + + loops = atoi(argv[2]); + for(arg=3; arg +#include +#include +#include "extenCooker.h" +#include +#include +#include +#include + +CSSM_BOOL randBool() +{ + unsigned r = genRand(1, 0x10000000); + return (r & 0x1) ? CSSM_TRUE : CSSM_FALSE; +} + +/* Fill a CSSM_DATA with random data. Its referent is allocd with malloc. */ +void randData( + CSSM_DATA_PTR data, + uint8 maxLen) +{ + data->Data = (uint8 *)malloc(maxLen); + simpleGenData(data, 1, maxLen); +} + +/* + * Various compare tests + */ +int compBool( + CSSM_BOOL pre, + CSSM_BOOL post, + const char *desc) +{ + if(pre == post) { + return 0; + } + printf("***Boolean miscompare on %s\n", desc); + /* in case a CSSM_TRUE isn't exactly right... */ + switch(post) { + case CSSM_FALSE: + case CSSM_TRUE: + break; + default: + printf("*** post value is %d expected %d\n", + (int)post, (int)pre); + break; + } + return 1; +} + +int compCssmData( + CSSM_DATA &d1, + CSSM_DATA &d2, + const char *desc) +{ + if(appCompareCssmData(&d1, &d2)) { + return 0; + } + printf("CSSM_DATA miscompare on %s\n", desc); + return 1; +} + +#pragma mark ----- individual extension tests ----- + +#pragma mark --- CE_KeyUsage --- +void kuCreate(void *arg) +{ + CE_KeyUsage *ku = (CE_KeyUsage *)arg; + + /* set two random valid bits */ + *ku = 0; + *ku |= 1 << genRand(7, 15); + *ku |= 1 << genRand(7, 15); +} + +unsigned kuCompare(const void *pre, const void *post) +{ + const CE_KeyUsage *kuPre = (CE_KeyUsage *)pre; + const CE_KeyUsage *kuPost = (CE_KeyUsage *)post; + if(*kuPre != *kuPost) { + printf("***Miscompare in CE_KeyUsage\n"); + return 1; + } + return 0; +} + +#pragma mark --- CE_BasicConstraints --- +void bcCreate(void *arg) +{ + CE_BasicConstraints *bc = (CE_BasicConstraints *)arg; + bc->cA = randBool(); + bc->pathLenConstraintPresent = randBool(); + if(bc->pathLenConstraintPresent) { + bc->pathLenConstraint = genRand(1,10); + } +} + +unsigned bcCompare(const void *pre, const void *post) +{ + const CE_BasicConstraints *bcpre = (CE_BasicConstraints *)pre; + const CE_BasicConstraints *bcpost = (CE_BasicConstraints *)post; + unsigned rtn = 0; + + rtn += compBool(bcpre->cA, bcpost->cA, "BasicConstraints.cA"); + rtn += compBool(bcpre->pathLenConstraintPresent, + bcpost->pathLenConstraintPresent, + "BasicConstraints.pathLenConstraintPresent"); + if(bcpre->pathLenConstraint != bcpost->pathLenConstraint) { + printf("BasicConstraints.pathLenConstraint mismatch\n"); + rtn++; + } + return rtn; +} + +#pragma mark --- CE_SubjectKeyID --- +void skidCreate(void *arg) +{ + CSSM_DATA_PTR skid = (CSSM_DATA_PTR)arg; + randData(skid, 16); +} + +unsigned skidCompare(const void *pre, const void *post) +{ + CSSM_DATA_PTR spre = (CSSM_DATA_PTR)pre; + CSSM_DATA_PTR spost = (CSSM_DATA_PTR)post; + return compCssmData(*spre, *spost, "SubjectKeyID"); +} + +void skidFree(void *arg) +{ + CSSM_DATA_PTR skid = (CSSM_DATA_PTR)arg; + free(skid->Data); +} + +#pragma mark --- CE_NetscapeCertType --- +void nctCreate(void *arg) +{ + CE_NetscapeCertType *nct = (CE_NetscapeCertType *)arg; + + /* set two random valid bits */ + *nct = 0; + *nct |= 1 << genRand(8, 15); + *nct |= 1 << genRand(8, 15); +} + +unsigned nctCompare(const void *pre, const void *post) +{ + const CE_NetscapeCertType *nPre = (CE_NetscapeCertType *)pre; + const CE_NetscapeCertType *nPost = (CE_NetscapeCertType *)post; + if(*nPre != *nPost) { + printf("***Miscompare in CE_NetscapeCertType\n"); + return 1; + } + return 0; +} + +#pragma mark --- CE_ExtendedKeyUsage --- + +/* a static array of meaningless OIDs, use 1.. NUM_SKU_OIDS */ +CSSM_OID ekuOids[] = { + CSSMOID_CrlNumber, + CSSMOID_CrlReason, + CSSMOID_HoldInstructionCode, + CSSMOID_InvalidityDate +}; +#define NUM_SKU_OIDS 4 + +void ekuCreate(void *arg) +{ + CE_ExtendedKeyUsage *eku = (CE_ExtendedKeyUsage *)arg; + eku->numPurposes = genRand(1, NUM_SKU_OIDS); + eku->purposes = ekuOids; +} + +unsigned ekuCompare(const void *pre, const void *post) +{ + CE_ExtendedKeyUsage *ekupre = (CE_ExtendedKeyUsage *)pre; + CE_ExtendedKeyUsage *ekupost = (CE_ExtendedKeyUsage *)post; + + if(ekupre->numPurposes != ekupost->numPurposes) { + printf("CE_ExtendedKeyUsage.numPurposes miscompare\n"); + return 1; + } + unsigned rtn = 0; + for(unsigned dex=0; dexnumPurposes; dex++) { + rtn += compCssmData(ekupre->purposes[dex], + ekupost->purposes[dex], "CE_ExtendedKeyUsage.purposes"); + } + return rtn; +} + + +#pragma mark --- general purpose X509 name generator --- + +/* Attr/Value pairs, pick one of NUM_ATTR_STRINGS */ +static char *attrStrings[] = { + (char *)"thisName", + (char *)"anotherName", + (char *)"someOtherName" +}; +#define NUM_ATTR_STRINGS 3 + +/* A/V type, pick one of NUM_ATTR_TYPES */ +static CSSM_OID attrTypes[] = { + CSSMOID_Surname, + CSSMOID_CountryName, + CSSMOID_OrganizationName, + CSSMOID_Description +}; +#define NUM_ATTR_TYPES 4 + +/* A/V tag, pick one of NUM_ATTR_TAGS */ +static char attrTags[] = { + BER_TAG_PRINTABLE_STRING, + BER_TAG_IA5_STRING, + BER_TAG_T61_STRING +}; +#define NUM_ATTR_TAGS 3 + +void rdnCreate( + CSSM_X509_RDN_PTR rdn) +{ + unsigned numPairs = genRand(1,4); + rdn->numberOfPairs = numPairs; + unsigned len = numPairs * sizeof(CSSM_X509_TYPE_VALUE_PAIR); + rdn->AttributeTypeAndValue = + (CSSM_X509_TYPE_VALUE_PAIR_PTR)malloc(len); + memset(rdn->AttributeTypeAndValue, 0, len); + + for(unsigned atvDex=0; atvDexAttributeTypeAndValue[atvDex]; + unsigned die = genRand(1, NUM_ATTR_TYPES); + pair.type = attrTypes[die - 1]; + die = genRand(1, NUM_ATTR_STRINGS); + char *str = attrStrings[die - 1]; + pair.value.Data = (uint8 *)str; + pair.value.Length = strlen(str); + die = genRand(1, NUM_ATTR_TAGS); + pair.valueType = attrTags[die - 1]; + } +} + +unsigned rdnCompare( + CSSM_X509_RDN_PTR rdn1, + CSSM_X509_RDN_PTR rdn2) +{ + if(rdn1->numberOfPairs != rdn2->numberOfPairs) { + printf("***Mismatch in numberOfPairs\n"); + return 1; + } + unsigned rtn = 0; + for(unsigned atvDex=0; atvDexnumberOfPairs; atvDex++) { + CSSM_X509_TYPE_VALUE_PAIR &p1 = + rdn1->AttributeTypeAndValue[atvDex]; + CSSM_X509_TYPE_VALUE_PAIR &p2 = + rdn2->AttributeTypeAndValue[atvDex]; + if(p1.valueType != p2.valueType) { + printf("***valueType miscompare\n"); + rtn++; + } + if(compCssmData(p1.type, p2.type, "ATV.type")) { + rtn++; + } + if(compCssmData(p1.value, p2.value, "ATV.value")) { + rtn++; + } + } + return rtn; +} + +void rdnFree( + CSSM_X509_RDN_PTR rdn) +{ + free(rdn->AttributeTypeAndValue); +} + +void x509NameCreate( + CSSM_X509_NAME_PTR x509Name) +{ + memset(x509Name, 0, sizeof(*x509Name)); + unsigned numRdns = genRand(1,4); + x509Name->numberOfRDNs = numRdns; + unsigned len = numRdns * sizeof(CSSM_X509_RDN); + x509Name->RelativeDistinguishedName = (CSSM_X509_RDN_PTR)malloc(len); + memset(x509Name->RelativeDistinguishedName, 0, len); + + for(unsigned rdnDex=0; rdnDexRelativeDistinguishedName[rdnDex]; + rdnCreate(&rdn); + } +} + +unsigned x509NameCompare( + const CSSM_X509_NAME_PTR n1, + const CSSM_X509_NAME_PTR n2) +{ + if(n1->numberOfRDNs != n2->numberOfRDNs) { + printf("***Mismatch in numberOfRDNs\n"); + return 1; + } + unsigned rtn = 0; + for(unsigned rdnDex=0; rdnDexnumberOfRDNs; rdnDex++) { + CSSM_X509_RDN &rdn1 = n1->RelativeDistinguishedName[rdnDex]; + CSSM_X509_RDN &rdn2 = n2->RelativeDistinguishedName[rdnDex]; + rtn += rdnCompare(&rdn1, &rdn2); + } + return rtn; +} + +void x509NameFree( + CSSM_X509_NAME_PTR n) +{ + for(unsigned rdnDex=0; rdnDexnumberOfRDNs; rdnDex++) { + CSSM_X509_RDN &rdn = n->RelativeDistinguishedName[rdnDex]; + rdnFree(&rdn); + } + free(n->RelativeDistinguishedName); +} + +#pragma mark --- general purpose GeneralNames generator --- + +#define SOME_URL_1 "http://foo.bar.com" +#define SOME_URL_2 "http://bar.foo.com" +#define SOME_DNS_1 "Some DNS" +#define SOME_DNS_2 "Another DNS" +unsigned char someIpAdr_1[] = {208, 161, 124, 209 }; +unsigned char someIpAdr_2[] = {10, 0, 61, 5}; + +void genNamesCreate(void *arg) +{ + CE_GeneralNames *names = (CE_GeneralNames *)arg; + names->numNames = genRand(1, 3); + // one at a time + //names->numNames = 1; + names->generalName = (CE_GeneralName *)malloc(names->numNames * + sizeof(CE_GeneralName)); + memset(names->generalName, 0, names->numNames * sizeof(CE_GeneralName)); + const char *src; + unsigned char *usrc; + + for(unsigned i=0; inumNames; i++) { + CE_GeneralName *name = &names->generalName[i]; + unsigned type = genRand(1, 5); + // unsigned type = 5; + switch(type) { + case 1: + name->nameType = GNT_URI; + name->berEncoded = CSSM_FALSE; + src = randBool() ? SOME_URL_1 : SOME_URL_2; + appCopyData(src, strlen(src), &name->name); + break; + + case 2: + name->nameType = GNT_RegisteredID; + name->berEncoded = CSSM_FALSE; + appCopyData(CSSMOID_SubjectDirectoryAttributes.Data, + CSSMOID_SubjectDirectoryAttributes.Length, + &name->name); + break; + + case 3: + name->nameType = GNT_DNSName; + name->berEncoded = CSSM_FALSE; + src = randBool() ? SOME_DNS_1 : SOME_DNS_2; + appCopyData(src, strlen(src), &name->name); + break; + + case 4: + name->nameType = GNT_IPAddress; + name->berEncoded = CSSM_FALSE; + usrc = randBool() ? someIpAdr_1 : someIpAdr_2; + appCopyData(usrc, 4, &name->name); + break; + + case 5: + { + /* X509_NAME, the hard one */ + name->nameType = GNT_DirectoryName; + name->berEncoded = CSSM_FALSE; + appSetupCssmData(&name->name, sizeof(CSSM_X509_NAME)); + x509NameCreate((CSSM_X509_NAME_PTR)name->name.Data); + } + } + } +} + +unsigned genNamesCompare(const void *pre, const void *post) +{ + const CE_GeneralNames *gnPre = (CE_GeneralNames *)pre; + const CE_GeneralNames *gnPost = (CE_GeneralNames *)post; + unsigned rtn = 0; + + if((gnPre == NULL) || (gnPost == NULL)) { + printf("***Bad GenNames pointer\n"); + return 1; + } + if(gnPre->numNames != gnPost->numNames) { + printf("***CE_GeneralNames.numNames miscompare\n"); + return 1; + } + for(unsigned dex=0; dexnumNames; dex++) { + CE_GeneralName *npre = &gnPre->generalName[dex]; + CE_GeneralName *npost = &gnPost->generalName[dex]; + if(npre->nameType != npost->nameType) { + printf("***CE_GeneralName.nameType miscompare\n"); + rtn++; + } + if(compBool(npre->berEncoded, npost->berEncoded, + "CE_GeneralName.berEncoded")) { + rtn++; + } + + /* nameType-specific compare */ + switch(npre->nameType) { + case GNT_RFC822Name: + rtn += compCssmData(npre->name, npost->name, + "CE_GeneralName.RFC822Name"); + break; + case GNT_DNSName: + rtn += compCssmData(npre->name, npost->name, + "CE_GeneralName.DNSName"); + break; + case GNT_URI: + rtn += compCssmData(npre->name, npost->name, + "CE_GeneralName.URI"); + break; + case GNT_IPAddress: + rtn += compCssmData(npre->name, npost->name, + "CE_GeneralName.RFIPAddressC822Name"); + break; + case GNT_RegisteredID: + rtn += compCssmData(npre->name, npost->name, + "CE_GeneralName.RegisteredID"); + break; + case GNT_DirectoryName: + rtn += x509NameCompare((CSSM_X509_NAME_PTR)npre->name.Data, + (CSSM_X509_NAME_PTR)npost->name.Data); + break; + default: + printf("****BRRZAP! genNamesCompare needs work\n"); + rtn++; + } + } + return rtn; +} + +void genNamesFree(void *arg) +{ + const CE_GeneralNames *gn = (CE_GeneralNames *)arg; + for(unsigned dex=0; dexnumNames; dex++) { + CE_GeneralName *n = (CE_GeneralName *)&gn->generalName[dex]; + switch(n->nameType) { + case GNT_DirectoryName: + x509NameFree((CSSM_X509_NAME_PTR)n->name.Data); + CSSM_FREE(n->name.Data); + break; + default: + CSSM_FREE(n->name.Data); + break; + } + } + free(gn->generalName); +} + +#pragma mark --- CE_CRLDistPointsSyntax --- +void cdpCreate(void *arg) +{ + CE_CRLDistPointsSyntax *cdp = (CE_CRLDistPointsSyntax *)arg; + //cdp->numDistPoints = genRand(1,3); + // one at a time + cdp->numDistPoints = 1; + unsigned len = sizeof(CE_CRLDistributionPoint) * cdp->numDistPoints; + cdp->distPoints = (CE_CRLDistributionPoint *)malloc(len); + memset(cdp->distPoints, 0, len); + + for(unsigned dex=0; dexnumDistPoints; dex++) { + CE_CRLDistributionPoint *pt = &cdp->distPoints[dex]; + + /* all fields optional */ + if(randBool()) { + CE_DistributionPointName *dpn = pt->distPointName = + (CE_DistributionPointName *)malloc( + sizeof(CE_DistributionPointName)); + memset(dpn, 0, sizeof(CE_DistributionPointName)); + + /* CE_DistributionPointName has two flavors */ + if(randBool()) { + dpn->nameType = CE_CDNT_FullName; + dpn->dpn.fullName = (CE_GeneralNames *)malloc( + sizeof(CE_GeneralNames)); + memset(dpn->dpn.fullName, 0, sizeof(CE_GeneralNames)); + genNamesCreate(dpn->dpn.fullName); + } + else { + dpn->nameType = CE_CDNT_NameRelativeToCrlIssuer; + dpn->dpn.rdn = (CSSM_X509_RDN_PTR)malloc( + sizeof(CSSM_X509_RDN)); + memset(dpn->dpn.rdn, 0, sizeof(CSSM_X509_RDN)); + rdnCreate(dpn->dpn.rdn); + } + } /* creating CE_DistributionPointName */ + + pt->reasonsPresent = randBool(); + if(pt->reasonsPresent) { + CE_CrlDistReasonFlags *cdr = &pt->reasons; + /* set two random valid bits */ + *cdr = 0; + *cdr |= 1 << genRand(0,7); + *cdr |= 1 << genRand(0,7); + } + + /* make sure at least one present */ + if((!pt->distPointName && !pt->reasonsPresent) || randBool()) { + pt->crlIssuer = (CE_GeneralNames *)malloc(sizeof(CE_GeneralNames)); + memset(pt->crlIssuer, 0, sizeof(CE_GeneralNames)); + genNamesCreate(pt->crlIssuer); + } + } +} + +unsigned cdpCompare(const void *pre, const void *post) +{ + CE_CRLDistPointsSyntax *cpre = (CE_CRLDistPointsSyntax *)pre; + CE_CRLDistPointsSyntax *cpost = (CE_CRLDistPointsSyntax *)post; + + if(cpre->numDistPoints != cpost->numDistPoints) { + printf("***CE_CRLDistPointsSyntax.numDistPoints miscompare\n"); + return 1; + } + unsigned rtn = 0; + for(unsigned dex=0; dexnumDistPoints; dex++) { + CE_CRLDistributionPoint *ptpre = &cpre->distPoints[dex]; + CE_CRLDistributionPoint *ptpost = &cpost->distPoints[dex]; + + if(ptpre->distPointName) { + if(ptpost->distPointName == NULL) { + printf("***NULL distPointName post decode\n"); + rtn++; + goto checkReason; + } + CE_DistributionPointName *dpnpre = ptpre->distPointName; + CE_DistributionPointName *dpnpost = ptpost->distPointName; + if(dpnpre->nameType != dpnpost->nameType) { + printf("***CE_DistributionPointName.nameType miscompare\n"); + rtn++; + goto checkReason; + } + if(dpnpre->nameType == CE_CDNT_FullName) { + rtn += genNamesCompare(dpnpre->dpn.fullName, dpnpost->dpn.fullName); + } + else { + rtn += rdnCompare(dpnpre->dpn.rdn, dpnpost->dpn.rdn); + } + + } + else if(ptpost->distPointName != NULL) { + printf("***NON NULL distPointName post decode\n"); + rtn++; + } + + checkReason: + if(ptpre->reasons != ptpost->reasons) { + printf("***CE_CRLDistributionPoint.reasons miscompare\n"); + rtn++; + } + + if(ptpre->crlIssuer) { + if(ptpost->crlIssuer == NULL) { + printf("***NULL crlIssuer post decode\n"); + rtn++; + continue; + } + CE_GeneralNames *gnpre = ptpre->crlIssuer; + CE_GeneralNames *gnpost = ptpost->crlIssuer; + rtn += genNamesCompare(gnpre, gnpost); + } + else if(ptpost->crlIssuer != NULL) { + printf("***NON NULL crlIssuer post decode\n"); + rtn++; + } + } + return rtn; +} + +void cdpFree(void *arg) +{ + CE_CRLDistPointsSyntax *cdp = (CE_CRLDistPointsSyntax *)arg; + for(unsigned dex=0; dexnumDistPoints; dex++) { + CE_CRLDistributionPoint *pt = &cdp->distPoints[dex]; + if(pt->distPointName) { + CE_DistributionPointName *dpn = pt->distPointName; + if(dpn->nameType == CE_CDNT_FullName) { + genNamesFree(dpn->dpn.fullName); + free(dpn->dpn.fullName); + } + else { + rdnFree(dpn->dpn.rdn); + free(dpn->dpn.rdn); + } + free(dpn); + } + + if(pt->crlIssuer) { + genNamesFree(pt->crlIssuer); + free(pt->crlIssuer); + } + } + free(cdp->distPoints); +} + +#pragma mark --- CE_AuthorityKeyID --- +void authKeyIdCreate(void *arg) +{ + CE_AuthorityKeyID *akid = (CE_AuthorityKeyID *)arg; + + /* all three fields optional */ + + akid->keyIdentifierPresent = randBool(); + if(akid->keyIdentifierPresent) { + randData(&akid->keyIdentifier, 16); + } + + akid->generalNamesPresent = randBool(); + if(akid->generalNamesPresent) { + akid->generalNames = + (CE_GeneralNames *)malloc(sizeof(CE_GeneralNames)); + memset(akid->generalNames, 0, sizeof(CE_GeneralNames)); + genNamesCreate(akid->generalNames); + } + + if(!akid->keyIdentifierPresent & !akid->generalNamesPresent) { + /* force at least one to be present */ + akid->serialNumberPresent = CSSM_TRUE; + } + else { + akid->serialNumberPresent = randBool(); + } + if(akid->serialNumberPresent) { + randData(&akid->serialNumber, 16); + } + +} + +unsigned authKeyIdCompare(const void *pre, const void *post) +{ + CE_AuthorityKeyID *akpre = (CE_AuthorityKeyID *)pre; + CE_AuthorityKeyID *akpost = (CE_AuthorityKeyID *)post; + unsigned rtn = 0; + + if(compBool(akpre->keyIdentifierPresent, akpost->keyIdentifierPresent, + "CE_AuthorityKeyID.keyIdentifierPresent")) { + rtn++; + } + else if(akpre->keyIdentifierPresent) { + rtn += compCssmData(akpre->keyIdentifier, + akpost->keyIdentifier, "CE_AuthorityKeyID.keyIdentifier"); + } + + if(compBool(akpre->generalNamesPresent, akpost->generalNamesPresent, + "CE_AuthorityKeyID.generalNamesPresent")) { + rtn++; + } + else if(akpre->generalNamesPresent) { + rtn += genNamesCompare(akpre->generalNames, + akpost->generalNames); + } + + if(compBool(akpre->serialNumberPresent, akpost->serialNumberPresent, + "CE_AuthorityKeyID.serialNumberPresent")) { + rtn++; + } + else if(akpre->serialNumberPresent) { + rtn += compCssmData(akpre->serialNumber, + akpost->serialNumber, "CE_AuthorityKeyID.serialNumber"); + } + return rtn; +} + +void authKeyIdFree(void *arg) +{ + CE_AuthorityKeyID *akid = (CE_AuthorityKeyID *)arg; + + if(akid->keyIdentifier.Data) { + free(akid->keyIdentifier.Data); + } + if(akid->generalNames) { + genNamesFree(akid->generalNames); // genNamesCreate mallocd + free(akid->generalNames); // we mallocd + } + if(akid->serialNumber.Data) { + free(akid->serialNumber.Data); + } +} + +#pragma mark --- CE_CertPolicies --- + +/* random OIDs, pick 1..NUM_CP_OIDS */ +static CSSM_OID cpOids[] = +{ + CSSMOID_EmailAddress, + CSSMOID_UnstructuredName, + CSSMOID_ContentType, + CSSMOID_MessageDigest +}; +#define NUM_CP_OIDS 4 + +/* CPS strings, pick one of NUM_CPS_STR */ +static char *someCPSs[] = +{ + (char *)"http://www.apple.com", + (char *)"https://cdnow.com", + (char *)"ftp:backwards.com" +}; +#define NUM_CPS_STR 3 + +/* make these looks like real sequences */ +static uint8 someUnotice[] = {0x30, 0x03, BER_TAG_BOOLEAN, 1, 0xff}; +static uint8 someOtherData[] = {0x30, 0x02, BER_TAG_NULL, 0}; + +void cpCreate(void *arg) +{ + CE_CertPolicies *cp = (CE_CertPolicies *)arg; + cp->numPolicies = genRand(1,3); + //cp->numPolicies = 1; + unsigned len = sizeof(CE_PolicyInformation) * cp->numPolicies; + cp->policies = (CE_PolicyInformation *)malloc(len); + memset(cp->policies, 0, len); + + for(unsigned polDex=0; polDexnumPolicies; polDex++) { + CE_PolicyInformation *pi = &cp->policies[polDex]; + unsigned die = genRand(1, NUM_CP_OIDS); + pi->certPolicyId = cpOids[die - 1]; + unsigned numQual = genRand(1,3); + pi->numPolicyQualifiers = numQual; + len = sizeof(CE_PolicyQualifierInfo) * numQual; + pi->policyQualifiers = (CE_PolicyQualifierInfo *) + malloc(len); + memset(pi->policyQualifiers, 0, len); + for(unsigned cpiDex=0; cpiDexpolicyQualifiers[cpiDex]; + if(randBool()) { + qi->policyQualifierId = CSSMOID_QT_CPS; + die = genRand(1, NUM_CPS_STR); + qi->qualifier.Data = (uint8 *)someCPSs[die - 1]; + qi->qualifier.Length = strlen((char *)qi->qualifier.Data); + } + else { + qi->policyQualifierId = CSSMOID_QT_UNOTICE; + if(randBool()) { + qi->qualifier.Data = someUnotice; + qi->qualifier.Length = 5; + } + else { + qi->qualifier.Data = someOtherData; + qi->qualifier.Length = 4; + } + } + } + } +} + +unsigned cpCompare(const void *pre, const void *post) +{ + CE_CertPolicies *cppre = (CE_CertPolicies *)pre; + CE_CertPolicies *cppost = (CE_CertPolicies *)post; + + if(cppre->numPolicies != cppost->numPolicies) { + printf("CE_CertPolicies.numPolicies mismatch\n"); + return 1; + } + unsigned rtn = 0; + for(unsigned polDex=0; polDexnumPolicies; polDex++) { + CE_PolicyInformation *pipre = &cppre->policies[polDex]; + CE_PolicyInformation *pipost = &cppost->policies[polDex]; + rtn += compCssmData(pipre->certPolicyId, pipost->certPolicyId, + "CE_PolicyInformation.certPolicyId"); + if(pipre->numPolicyQualifiers != pipost->numPolicyQualifiers) { + printf("CE_PolicyInformation.CE_PolicyInformation mismatch\n"); + rtn++; + continue; + } + + for(unsigned qiDex=0; qiDexnumPolicyQualifiers; qiDex++) { + CE_PolicyQualifierInfo *qipre = &pipre->policyQualifiers[qiDex]; + CE_PolicyQualifierInfo *qipost = &pipost->policyQualifiers[qiDex]; + rtn += compCssmData(qipre->policyQualifierId, + qipost->policyQualifierId, + "CE_PolicyQualifierInfo.policyQualifierId"); + rtn += compCssmData(qipre->qualifier, + qipost->qualifier, + "CE_PolicyQualifierInfo.qualifier"); + } + } + return rtn; +} + +void cpFree(void *arg) +{ + CE_CertPolicies *cp = (CE_CertPolicies *)arg; + for(unsigned polDex=0; polDexnumPolicies; polDex++) { + CE_PolicyInformation *pi = &cp->policies[polDex]; + free(pi->policyQualifiers); + } + free(cp->policies); +} diff --git a/SecurityTests/clxutils/certTime/extenCooker.h b/SecurityTests/clxutils/certTime/extenCooker.h new file mode 100644 index 00000000..8f450e29 --- /dev/null +++ b/SecurityTests/clxutils/certTime/extenCooker.h @@ -0,0 +1,162 @@ +/* + * extenCooker.h - module to cook up random (but reasonable) + * versions of cert extensions + */ + + +#ifndef _EXTEN_COOKER_H_ +#define _EXTEN_COOKER_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Define one extension test. + */ + +/* + * Cook up this extension with random, reasonable values. + * Incoming pointer refers to extension-specific C struct, mallocd + * and zeroed by main test routine. + */ +typedef void (*extenCreateFcn)(void *arg); + +/* + * Compare two instances of this extension. Return number of + * compare errors. + */ +typedef unsigned (*extenCompareFcn)( + const void *preEncode, + const void *postEncode); + +/* + * Free struct components mallocd in extenCreateFcn. Do not free + * the outer struct. + */ +typedef void (*extenFreeFcn)(void *arg); + +typedef struct { + /* three extension-specific functions */ + extenCreateFcn createFcn; + extenCompareFcn compareFcn; + extenFreeFcn freeFcn; + + /* size of C struct passed to all three functions */ + unsigned extenSize; + + /* the OID for this extension */ + CSSM_OID extenOid; + + /* description for error logging and blob writing */ + const char *extenDescr; + + /* command-line letter for this one */ + char extenLetter; + +} ExtenTest; + +/* + * extenCooker.cpp - module to cook up random (but reasonable) + * versions of cert extensions + */ + +#include +#include +#include "extenCooker.h" + +CSSM_BOOL randBool(); + +/* Fill a CSSM_DATA with random data. Its referent is allocd with malloc. */ +void randData( + CSSM_DATA_PTR data, + uint8 maxLen); + + +/* + * Various compare tests + */ +int compBool( + CSSM_BOOL pre, + CSSM_BOOL post, + char *desc); + + +int compCssmData( + CSSM_DATA &d1, + CSSM_DATA &d2, + char *desc); + + +#pragma mark --- CE_KeyUsage --- +void kuCreate(void *arg); +unsigned kuCompare(const void *pre, const void *post); +/* no free */ + +#pragma mark --- CE_BasicConstraints --- +void bcCreate(void *arg); +unsigned bcCompare(const void *pre, const void *post); +/* no free */ + +#pragma mark --- CE_SubjectKeyID --- +void skidCreate(void *arg); +unsigned skidCompare(const void *pre, const void *post); +void skidFree(void *arg); + +#pragma mark --- CE_NetscapeCertType --- +void nctCreate(void *arg); +unsigned nctCompare(const void *pre, const void *post); +/* no free */ + +#pragma mark --- CE_ExtendedKeyUsage --- +void ekuCreate(void *arg); +unsigned ekuCompare(const void *pre, const void *post); +/* no free */ + +#pragma mark --- general purpose X509 name generator --- +void rdnCreate( + CSSM_X509_RDN_PTR rdn); +unsigned rdnCompare( + CSSM_X509_RDN_PTR rdn1, + CSSM_X509_RDN_PTR rdn2); +void rdnFree( + CSSM_X509_RDN_PTR rdn); + +void x509NameCreate( + CSSM_X509_NAME_PTR x509Name); +unsigned x509NameCompare( + const CSSM_X509_NAME_PTR n1, + const CSSM_X509_NAME_PTR n2); +void x509NameFree( + CSSM_X509_NAME_PTR n); + +#pragma mark --- general purpose GeneralNames generator --- + +void genNamesCreate(void *arg); +unsigned genNamesCompare(const void *pre, const void *post); +void genNamesFree(void *arg); + +#pragma mark --- CE_CRLDistPointsSyntax --- +void cdpCreate(void *arg); +unsigned cdpCompare(const void *pre, const void *post); +void cdpFree(void *arg); + +#pragma mark --- CE_AuthorityKeyID --- +void authKeyIdCreate(void *arg); +unsigned authKeyIdCompare(const void *pre, const void *post); +void authKeyIdFree(void *arg); + +#pragma mark --- CE_CertPolicies --- +void cpCreate(void *arg); +unsigned cpCompare(const void *pre, const void *post); +void cpFree(void *arg); + +#ifdef __cplusplus +} +#endif + +#endif /* _EXTEN_COOKER_H_ */ diff --git a/SecurityTests/clxutils/certTime/runTime b/SecurityTests/clxutils/certTime/runTime new file mode 100755 index 00000000..eb2fbfc8 --- /dev/null +++ b/SecurityTests/clxutils/certTime/runTime @@ -0,0 +1,23 @@ +#! /bin/csh -f +# +# run certTime thru all six options +# +set LOOPS = 1000 +if( $#argv == 1 ) then + set LOOPS = "$argv[1]" +endif +# +# safely look for this required env var +# +setenv | grep LOCAL_BUILD_DIR > /dev/null +if($status != 0) then + echo Please set env var LOCAL_BUILD_DIR. + exit(1) +endif +# +$LOCAL_BUILD_DIR/certTime p $LOOPS +$LOCAL_BUILD_DIR/certTime g $LOOPS +$LOCAL_BUILD_DIR/certTime t $LOOPS +$LOCAL_BUILD_DIR/certTime c $LOOPS +$LOCAL_BUILD_DIR/certTime s $LOOPS +$LOCAL_BUILD_DIR/certTime v $LOOPS diff --git a/SecurityTests/clxutils/certcrl/Makefile b/SecurityTests/clxutils/certcrl/Makefile new file mode 100644 index 00000000..ba2a6619 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/Makefile @@ -0,0 +1,59 @@ +# name of executable to build +EXECUTABLE= certcrl +# C++ source (with .cpp extension) +CPSOURCE= certcrl.cpp script.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +# +# Optional files on which *.{c,cpp} depend +# +HDR_DEPENDS=../clAppUtils/certVerify.h + +include ../Makefile.cdsa diff --git a/SecurityTests/clxutils/certcrl/README.doc b/SecurityTests/clxutils/certcrl/README.doc new file mode 100644 index 0000000000000000000000000000000000000000..c9d1e6a34c36cbe45400e8df4ecedd915019a3ed GIT binary patch literal 50688 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include "script.h" + +static void usage(char **argv) +{ + printf("Usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" -c certFileName [...]\n"); + printf(" -C rootCertFileName [...]\n"); + printf(" -r crlFileName [...]\n"); + printf(" -d certDbName\n"); + printf(" -D crlDlDbName\n"); + printf(" -s (use system anchor certs)\n"); + printf(" -g (use Trust Settings)\n"); + printf(" -i (implicit anchors)\n"); + printf(" -l=loopCount (default = 1)\n"); + printf(" -f (leaf cert is a CA)\n"); + printf(" -w(rite CRLs to dlDbName)\n"); + printf("Policy options:\n"); + printf(" -y ssl|smime|swuSign|codeSign|pkgSign|resourceSign|iChat|pkinitServer|\n" + " pkinitClient|IPSec\n"); + printf(" -h sslHostName (implies SSL policy; default is basic)\n"); + printf(" -t SSL client side (implies SSL policy, default is server side)\n"); + printf(" -E senderEmail (implies SMIME policy unless iChat is specified)\n"); + printf("Revocation options:\n"); + printf(" -R revocationPolicy (crl|ocsp|both|none); default = none\n"); + printf(" -a (allow certs unverified by CRL or OCSP)\n"); + printf(" -A (require CRL verification if present in cert\n"); + printf(" -4 (require CRL verification for all certs)\n"); + printf(" -Q (require OCSP if present in cert)\n"); + printf(" -5 (require OCSP verification for all certs)\n"); + printf(" -u responderURI\n"); + printf(" -U responderCert\n"); + printf(" -H (OCSP cache disable)\n"); + printf(" -W (network OCSP disable)\n"); + printf(" -o generate OCSP nonce\n"); + printf(" -O require nonce in OCSP response\n"); + printf("Misc. options:\n"); + printf(" -n (no network fetch of CRLs)\n"); + printf(" -N (no network fetch of certs)\n"); + printf(" -k keyUsage (In HEX starting with 0x)\n"); + printf(" -T verifyTime (in CSSM_TIMESTRING format, like 20041217154316)\n"); + printf(" -e=expectedError (default is CSSM_OK)\n"); + printf(" -S scriptFile\n"); + printf(" -p (print script variable names)\n"); + printf(" -P (pause after each script test)\n"); + printf(" -v (verbose)\n"); + printf(" -q (quiet)\n"); + printf(" -L (silent)\n"); + exit(1); +} + + + +/* add files named by successive items in argv to blobList, up until the + * next '-' arg */ +static void gatherFiles( + BlobList &blobList, + char **argv, + int argc, + int &currArg) +{ + if((currArg == argc) || (argv[currArg][0] == '-')) { + /* need at least one file name */ + usage(argv); + } + while(currArgDBHandle); + if(crtn) { + printError("CSSM_DL_DbOpen", crtn); + printf("***Error opening DB %s. Aborting.\n", crlDbName); + return 1; + } + dlDbList.NumHandles++; + vfyArgs.dlDbList = &dlDbList; + } + for(loop=0; loop +#include +#include +#include +#include +#include +#include +#include +#include +#include "script.h" + +/* Line type returned from parseLine */ +typedef enum { + LT_Empty, // comments, whitespace + LT_TestName, + LT_DirName, + LT_Cert, + LT_Root, + LT_CRL, + LT_CertDb, + LT_CrlDb, + LT_ExpectError, // expected function return + LT_CertError, // per-cert error string + LT_CertStatus, // per-cert StatusBits + LT_SslHost, + LT_SslClient, + LT_SenderEmail, + LT_Policy, + LT_KeyUsage, + LT_RevokePolicy, + LT_RespURI, + LT_RespCert, + LT_EndOfSection, + LT_EndOfFile, + LT_BadLine, + LT_Globals, + LT_Echo, + LT_GenerateOcspNonce, + LT_RequireOcspNonce, + LT_AllowExpiredRoot, + LT_VerifyTime, + LT_ImplicitAnchors, + + /* variables which can be in globals or per-test */ + LT_AllowUnverified, + LT_CrlNetFetchEnable, + LT_CertNetFetchEnable, + LT_UseSystemAnchors, + LT_UseTrustSettings, + LT_LeafCertIsCA, + LT_CacheDisable, + LT_OcspNetFetchDisable, + LT_RequireOcspIfPresent, + LT_RequireCrlIfPresent, + LT_RequireCrlForAll, + LT_RequireOcspForAll +} LineType; + +/* table to map key names to LineType */ +typedef struct { + const char *keyName; + LineType lineType; +} KeyLineType; + +KeyLineType keyLineTypes[] = +{ + { "test", LT_TestName }, + { "dir", LT_DirName }, + { "cert", LT_Cert }, + { "root", LT_Root }, + { "crl", LT_CRL }, + { "certDb", LT_CertDb }, + { "crlDb", LT_CrlDb }, // no longer used + { "error", LT_ExpectError }, + { "certerror", LT_CertError }, + { "certstatus", LT_CertStatus }, + { "sslHost", LT_SslHost }, + { "sslClient", LT_SslClient }, + { "senderEmail", LT_SenderEmail }, + { "policy", LT_Policy }, + { "keyUsage", LT_KeyUsage }, + { "revokePolicy", LT_RevokePolicy }, + { "responderURI", LT_RespURI }, + { "responderCert", LT_RespCert }, + { "cacheDisable", LT_CacheDisable }, + { "echo", LT_Echo }, + { "globals", LT_Globals }, + { "end", LT_EndOfSection }, + { "allowUnverified", LT_AllowUnverified }, + { "requireCrlIfPresent",LT_RequireCrlIfPresent }, + { "crlNetFetchEnable", LT_CrlNetFetchEnable }, + { "certNetFetchEnable", LT_CertNetFetchEnable }, + { "ocspNetFetchDisable",LT_OcspNetFetchDisable }, + { "requireCrlForAll", LT_RequireCrlForAll }, + { "requireOcspForAll", LT_RequireOcspForAll }, + { "useSystemAnchors", LT_UseSystemAnchors }, + { "useTrustSettings", LT_UseTrustSettings }, + { "leafCertIsCA", LT_LeafCertIsCA }, + { "requireOcspIfPresent",LT_RequireOcspIfPresent }, + { "generateOcspNonce", LT_GenerateOcspNonce }, + { "requireOcspNonce", LT_RequireOcspNonce }, + { "allowExpiredRoot", LT_AllowExpiredRoot }, + { "verifyTime", LT_VerifyTime }, + { "implicitAnchors", LT_ImplicitAnchors }, +}; + +#define NUM_KEYS (sizeof(keyLineTypes) / sizeof(KeyLineType)) + +/* map policy string to CertVerifyPolicy */ +typedef struct { + const char *str; + CertVerifyPolicy policy; +} PolicyString; + +static const PolicyString policyStrings[] = +{ + { "basic", CVP_Basic }, + { "ssl", CVP_SSL }, + { "smime", CVP_SMIME }, + { "swuSign", CVP_SWUpdateSign }, + { "codeSign", CVP_AppleCodeSigning }, + { "pkgSign", CVP_PackageSigning }, + { "resourceSign", CVP_ResourceSigning }, + { "iChat", CVP_iChat }, + { "pkinitServer", CVP_PKINIT_Server }, + { "pkinitClient", CVP_PKINIT_Client }, + { "IPSec", CVP_IPSec }, + { NULL, (CertVerifyPolicy)0 } +}; + +/* skip whitespace (but not line terminators) */ +static void skipWhite( + const unsigned char *&cp, + unsigned &bytesLeft) +{ + while(bytesLeft != 0) { + switch(*cp) { + case ' ': + case '\t': + cp++; + bytesLeft--; + break; + default: + return; + } + } +} + +/* skip to next char after EOL */ +static void skipLine( + const unsigned char *&cp, + unsigned &bytesLeft) +{ + bool foundEol = false; + while(bytesLeft != 0) { + switch(*cp) { + case '\n': + case '\r': + foundEol = true; + cp++; + bytesLeft--; + break; + default: + if(foundEol) { + return; + } + cp++; + bytesLeft--; + break; + } + } +} + +/* skip to end of current token (i.e., find next whitespace or '=') */ +static void skipToken( + const unsigned char *&cp, + unsigned &bytesLeft, + bool isQuoted) +{ + while(bytesLeft != 0) { + char c = *cp; + if(isQuoted) { + if(c == '"') { + /* end of quoted string, return still pointing to it */ + return; + } + } + else { + if(isspace(c)) { + return; + } + if(c == '=') { + /* hopefully, end of key */ + return; + } + } + cp++; + bytesLeft--; + } +} + +/* + * Parse one line, return value (following "=" and whitespace) as + * mallocd C string. On return, scriptData points to next char after line + * terminator(s). + * + * The basic form of a line is + * [whitespace] key [whitespace] = [whitespace] value [whitespace] \n|\r... + * + * ...except for comments and blank lines. Comments contain '#' as the + * first non-whitespace char. + */ +#define CHECK_EOF(bytesLeft) \ + if(bytesLeft == 0) { \ + return LT_BadLine; \ + } + +#define MAX_KEY_LEN 80 + +static LineType parseLine( + const unsigned char *&cp, // IN/OUT + unsigned &bytesLeft, // IN/OUT bytes left in script + char *&value, // mallocd and RETURNED + CSSM_BOOL verbose) +{ + if(bytesLeft == 0) { + if(verbose) { + printf("...EOF reached\n"); + } + return LT_EndOfFile; + } + skipWhite(cp, bytesLeft); + if(bytesLeft == 0) { + return LT_Empty; + } + switch(*cp) { + case '#': + case '\n': + case '\r': + skipLine(cp, bytesLeft); + return LT_Empty; + } + + /* + * cp points to start of key + * get key value as NULL terminated C string + */ + const unsigned char *tokenStart = cp; + skipToken(cp, bytesLeft, false); + CHECK_EOF(bytesLeft); + unsigned tokenLen = cp - tokenStart; + char key[MAX_KEY_LEN]; + memmove(key, tokenStart, tokenLen); + key[tokenLen] = '\0'; + + /* parse key */ + LineType rtnType = LT_BadLine; + for(unsigned i=0; ikeyName, key)) { + rtnType = klt->lineType; + break; + } + } + + /* these keys have no value */ + bool noValue = false; + switch(rtnType) { + case LT_EndOfSection: + if(verbose) { + printf("...end of section\n"); + } + noValue = true; + break; + case LT_Globals: + noValue = true; + break; + case LT_BadLine: + printf("***unknown key '%s'\n", key); + noValue = true; + break; + default: + break; + } + if(noValue) { + /* done with line */ + skipLine(cp, bytesLeft); + return rtnType; + } + + /* get to start of value */ + skipWhite(cp, bytesLeft); + CHECK_EOF(bytesLeft); + if(rtnType == LT_Echo) { + /* echo: value is everything from this char to end of line */ + tokenStart = cp; + for( ; bytesLeft != 0; cp++, bytesLeft--) { + if((*cp == '\n') || (*cp == '\r')) { + break; + } + } + if(cp != tokenStart) { + tokenLen = cp - tokenStart; + value = (char *)malloc(tokenLen + 1); + memmove(value, tokenStart, tokenLen); + value[tokenLen] = '\0'; + } + else { + value = NULL; + } + skipLine(cp, bytesLeft); + return LT_Echo; + } + + /* all other line types: value is first token after '=' */ + if(*cp != '=') { + printf("===missing = after key\n"); + return LT_BadLine; + } + cp++; + bytesLeft--; + skipWhite(cp, bytesLeft); + CHECK_EOF(bytesLeft); + + /* cp points to start of value */ + bool isQuoted = false; + if(*cp == '"') { + cp++; + bytesLeft--; + CHECK_EOF(bytesLeft) + isQuoted = true; + } + tokenStart = cp; + skipToken(cp, bytesLeft, isQuoted); + /* cp points to next char after end of value */ + /* get value as mallocd C string */ + tokenLen = cp - tokenStart; + if(tokenLen == 0) { + value = NULL; + } + else { + value = (char *)malloc(tokenLen + 1); + memmove(value, tokenStart, tokenLen); + value[tokenLen] = '\0'; + } + skipLine(cp, bytesLeft); + if(verbose) { + printf("'%s' = '%s'\n", key, value); + } + return rtnType; +} + +/* describe fate of one run of runOneTest() */ +typedef enum { + OTR_Success, + OTR_Fail, + OTR_EndOfScript +} OneTestResult; + +/* parse boolean variable, in globals or per-test */ +OneTestResult parseVar( + LineType lineType, + const char *value, + ScriptVars &scriptVars) +{ + /* parse value */ + CSSM_BOOL cval; + if(!strcmp(value, "true")) { + cval = CSSM_TRUE; + } + else if(!strcmp(value, "false")) { + cval = CSSM_FALSE; + } + else { + printf("***boolean variables must be true or false, not '%s'\n", value); + return OTR_Fail; + } + + switch(lineType) { + case LT_AllowUnverified: + scriptVars.allowUnverified = cval; + break; + case LT_CrlNetFetchEnable: + scriptVars.crlNetFetchEnable = cval; + break; + case LT_CertNetFetchEnable: + scriptVars.certNetFetchEnable = cval; + break; + case LT_UseSystemAnchors: + scriptVars.useSystemAnchors = cval; + break; + case LT_UseTrustSettings: + scriptVars.useTrustSettings = cval; + break; + case LT_LeafCertIsCA: + scriptVars.leafCertIsCA = cval; + break; + case LT_CacheDisable: + scriptVars.cacheDisable = cval; + break; + case LT_OcspNetFetchDisable: + scriptVars.ocspNetFetchDisable = cval; + break; + case LT_RequireOcspIfPresent: + scriptVars.requireOcspIfPresent = cval; + break; + case LT_RequireCrlIfPresent: + scriptVars.requireCrlIfPresent = cval; + break; + case LT_RequireCrlForAll: + scriptVars.requireCrlForAll = cval; + break; + case LT_RequireOcspForAll: + scriptVars.requireOcspForAll = cval; + break; + default: + return OTR_Fail; + } + return OTR_Success; +} + +#if 0 +/* sure wish X had strnstr */ +static char *strnstr( + const char *big, + const char *little, + size_t len) +{ + const char *cp; + unsigned littleLen = strlen(little); + const char *end = big + len - littleLen; + char first = little[0]; + + for(cp=big; cpDLHandle = dlHand; + crtn = CSSM_DL_DbOpen(dlHand, + pathName, + NULL, // DbLocation + CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, + NULL, // CSSM_ACCESS_CREDENTIALS *AccessCred + NULL, // void *OpenParameters + &currDlDb->DBHandle); + if(crtn) { + printError("CSSM_DL_DbOpen", crtn); + printf("***Error opening DB %s. Aborting.\n", value); + return OTR_Fail; + } + break; + case LT_ExpectError: + if(vfyArgs.expectedErrStr != NULL) { + printf("***Duplicate expected error ignored\n"); + free(value); + } + else { + vfyArgs.expectedErrStr = value; // free after test + } + value = NULL; + break; + case LT_CertError: + vfyArgs.numCertErrors++; + vfyArgs.certErrors = (const char **)realloc(vfyArgs.certErrors, + vfyArgs.numCertErrors * sizeof(char *)); + vfyArgs.certErrors[vfyArgs.numCertErrors - 1] = value; + value = NULL; // free after test + break; + case LT_CertStatus: + vfyArgs.numCertStatus++; + vfyArgs.certStatus = (const char **)realloc(vfyArgs.certStatus, + vfyArgs.numCertStatus * sizeof(char *)); + vfyArgs.certStatus[vfyArgs.numCertStatus - 1] = value; + value = NULL; // // free after test + break; + case LT_SslHost: + vfyArgs.sslHost = value; + value = NULL; // free after test + vfyArgs.vfyPolicy = CVP_SSL; + break; + case LT_SenderEmail: + vfyArgs.senderEmail = value; + value = NULL; // free after test + if(vfyArgs.vfyPolicy == CVP_Basic) { + /* don't overwrite if it's already been set to e.g. iChat */ + vfyArgs.vfyPolicy = CVP_SMIME; + } + break; + case LT_Policy: + if(parsePolicyString(value, &vfyArgs.vfyPolicy)) { + printf("Bogus policyValue (%s)\n", value); + printPolicyStrings(); + return OTR_Fail; + } + break; + case LT_KeyUsage: + vfyArgs.intendedKeyUse = hexToBin(value); + break; + case LT_RevokePolicy: + if(!strcmp(value, "none")) { + vfyArgs.revokePolicy = CRP_None; + } + else if(!strcmp(value, "crl")) { + vfyArgs.revokePolicy = CRP_CRL; + } + else if(!strcmp(value, "ocsp")) { + vfyArgs.revokePolicy = CRP_OCSP; + } + else if(!strcmp(value, "both")) { + vfyArgs.revokePolicy = CRP_CRL_OCSP; + } + else { + printf("***Illegal revokePolicy (%s)\n.", value); + return OTR_Fail; + } + break; + case LT_RespURI: + vfyArgs.responderURI = value; + value = NULL; // free after test + break; + case LT_VerifyTime: + vfyArgs.vfyTime = value; + value = NULL; // free after test + break; + case LT_RespCert: + if(readFile(value, (unsigned char **)&vfyArgs.responderCert, + &vfyArgs.responderCertLen)) { + printf("***Error reading responderCert from %s\n", value); + return OTR_Fail; + } + break; + case LT_EndOfSection: + break; + case LT_EndOfFile: + /* only legal if we haven't gotten a test name */ + if(testName == NULL) { + return OTR_EndOfScript; + } + printf("***Premature end of file.\n"); + return OTR_Fail; + case LT_BadLine: + return OTR_Fail; + case LT_Globals: + result = fetchGlobals(scriptData, bytesLeft, scriptVars, verbose); + if(result != OTR_Success) { + printf("***Bad globals section\n"); + return OTR_Fail; + } + /* and start over with these variables */ + localVars = scriptVars; + break; + case LT_SslClient: + if(!strcmp(value, "true")) { + vfyArgs.sslClient = CSSM_TRUE; + } + else { + vfyArgs.sslClient = CSSM_FALSE; + } + vfyArgs.vfyPolicy = CVP_SSL; + break; + case LT_Echo: + if(!quiet) { + printf("%s\n", value); + } + break; + case LT_GenerateOcspNonce: + vfyArgs.generateOcspNonce = CSSM_TRUE; + break; + case LT_RequireOcspNonce: + vfyArgs.requireOcspRespNonce = CSSM_TRUE; + break; + case LT_AllowExpiredRoot: + if(!strcmp(value, "true")) { + vfyArgs.allowExpiredRoot = CSSM_TRUE; + } + else { + vfyArgs.allowExpiredRoot = CSSM_FALSE; + } + break; + case LT_ImplicitAnchors: + if(!strcmp(value, "true")) { + vfyArgs.implicitAnchors = CSSM_TRUE; + } + else { + vfyArgs.implicitAnchors = CSSM_FALSE; + } + break; + default: + /* hopefully a variable */ + result = parseVar(lineType, value, localVars); + if(result != OTR_Success) { + printf("**Bogus line in script %u bytes from EOF\n", + bytesLeft); + return OTR_Fail; + } + break; + + } + if(blobErr) { + return OTR_Fail; + } + if(value != NULL) { + free(value); + } + } while(lineType != LT_EndOfSection); + + /* some args: copy from ScriptVars -> CertVerifyArgs */ + vfyArgs.allowUnverified = localVars.allowUnverified; + vfyArgs.requireOcspIfPresent = localVars.requireOcspIfPresent; + vfyArgs.requireCrlIfPresent = localVars.requireCrlIfPresent; + vfyArgs.crlNetFetchEnable = localVars.crlNetFetchEnable; + vfyArgs.certNetFetchEnable = localVars.certNetFetchEnable; + vfyArgs.useSystemAnchors = localVars.useSystemAnchors; + vfyArgs.useTrustSettings = localVars.useTrustSettings; + vfyArgs.leafCertIsCA = localVars.leafCertIsCA; + vfyArgs.disableCache = localVars.cacheDisable; + vfyArgs.disableOcspNet = localVars.ocspNetFetchDisable; + vfyArgs.requireCrlForAll = localVars.requireCrlForAll; + vfyArgs.requireOcspForAll = localVars.requireOcspForAll; + vfyArgs.verbose = verbose; + + /* here we go */ + if(!quiet && (testName != NULL)) { + printf("%s\n", testName); + } + int rtn = certVerify(&vfyArgs); + + OneTestResult ourRtn = OTR_Success; + if(rtn) { + printf("***Failure on %s\n", testName); + if(testError(quiet)) { + ourRtn = OTR_Fail; + } + } + /* free the stuff that didn't get freed and the end of the + * main per-line loop */ + if(dirName != NULL) { + free(dirName); + } + if(vfyArgs.expectedErrStr != NULL) { + free((void *)vfyArgs.expectedErrStr); + } + if(vfyArgs.certErrors != NULL) { + for(unsigned i=0; istr; ps++) { + if(!strcmp(ps->str, str)) { + *policy = ps->policy; + return 0; + } + } + return 1; +} + +void printPolicyStrings() +{ + printf("Valid policy strings are:\n "); + const PolicyString *ps; + unsigned i=0; + for(ps=policyStrings; ps->str; ps++, i++) { + printf("%s", ps->str); + if(ps[1].str == NULL) { + break; + } + if((i % 6) == 5) { + printf(",\n "); + } + else { + printf(", "); + } + } + printf("\n"); +} + +void printScriptVars() +{ + printf("The list of script variables is as follows:\n"); + for(unsigned dex=0; dex + +/* + * Test variables which can be specified at the top level (on the + * call to runScript), or globally in a script, or within the scope + * of one test. + */ +typedef struct { + CSSM_BOOL allowUnverified; + CSSM_BOOL requireCrlIfPresent; + CSSM_BOOL requireOcspIfPresent; + CSSM_BOOL crlNetFetchEnable; + CSSM_BOOL certNetFetchEnable; + CSSM_BOOL useSystemAnchors; + CSSM_BOOL useTrustSettings; + CSSM_BOOL leafCertIsCA; + CSSM_BOOL cacheDisable; + CSSM_BOOL ocspNetFetchDisable; + CSSM_BOOL requireCrlForAll; + CSSM_BOOL requireOcspForAll; +} ScriptVars; + +extern "C" { +int runScript( + const char *fileName, + CSSM_TP_HANDLE tpHand, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + CSSM_DL_HANDLE dlHand, + ScriptVars *scriptVars, + CSSM_BOOL quiet, + CSSM_BOOL verbose, + CSSM_BOOL doPause); + +/* parse policy string; returns nonzero of not found */ +int parsePolicyString( + const char *str, + CertVerifyPolicy *policy); + +void printPolicyStrings(); +void printScriptVars(); + +} +#endif /* _SCRIPT_H_ */ diff --git a/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleCerts.scr b/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleCerts.scr new file mode 100644 index 00000000..697c8646 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleCerts.scr @@ -0,0 +1,34 @@ +# +# test Apple certs. Requires the root to be trusted somehow (it's not explicitly passed to +# the verifier here). . +# +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = true +useTrustSettings = true +end +# +test = Development +cert = AppleDevelopment.pem +cert = AppleSWUPDATE.pem +policy = swuSign +error = CSSMERR_APPLETP_CODE_SIGN_DEVELOPMENT +certerror=0:CSSMERR_APPLETP_CODE_SIGN_DEVELOPMENT +end +# +# +test = "Software Update" +cert = AppleSoftUpdate.pem +cert = AppleSWUPDATE.pem +policy = swuSign +end +# +test = "test the intermediate CA, wrong cert chain length" +cert = AppleSWUPDATE.pem +policy = swuSign +error = CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH +end +# + diff --git a/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleDevelopment.pem b/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleDevelopment.pem new file mode 100644 index 00000000..287d9d3b --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleDevelopment.pem @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFKjCCBBKgAwIBAgIBAjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMCVVMx +EzARBgNVBAoTCkFwcGxlIEluYy4xJjAkBgNVBAsTHUFwcGxlIENlcnRpZmljYXRp +b24gQXV0aG9yaXR5MTYwNAYDVQQDEy1BcHBsZSBTb2Z0d2FyZSBVcGRhdGUgQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDcwMjIzMjIxNjAyWhcNMTUwMTE0MjIx +NjAyWjBfMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQXBwbGUgSW5jLjEeMBwGA1UE +CxMVQXBwbGUgU29mdHdhcmUgVXBkYXRlMRswGQYDVQQDExJEZXZlbG9wbWVudCBV +cGRhdGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDEn+3Y1fgubxPE +vWAPoWKLQQYVR0zG2/YsIPjRz2HrgzupGiPIYV/zcj0JcOeQ64KdukUlJrhZXgpp +6O7NwOHU7fUN+tfj46boyrIsRGNz+pd0zNiAeXekDyUsYj/nbD4wlACGwxxmiFtB +toJuRwVON1j9GcwSCoQHUkFZXUyeiSRkrSAwmGLBI9jVsGDuauvbY5aZUWOEaP8E +rgIllUL8MruOb0ObQJGaBkl3jjzxnThGmLQ85Q0fDyHM48rPR7O81yROfzIjzmeX +UorMWFmXF4ObBpZL1XpDsVvPargm2J6CnZN+7Z3HmYs4wfy9ZX2MpvYk4ZiaXUp9 +XstIUxFLAgMBAAGjggHLMIIBxzAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIw +ADAYBgNVHSUBAf8EDjAMBgoqhkiG92NkBAEBMB0GA1UdDgQWBBQZr1Csr2Hh/8+u +t50EW0Dku4+UMzAfBgNVHSMEGDAWgBSLxSlK86/KoXKU9wZtR2NBsEeYITCCAQ8G +A1UdIASCAQYwggECMIH/BgkqhkiG92NkBQEwgfEwKQYIKwYBBQUHAgEWHWh0dHA6 +Ly93d3cuYXBwbGUuY29tL2FwcGxlY2EvMIHDBggrBgEFBQcCAjCBthqBs1JlbGlh +bmNlIG9uIHRoaXMgY2VydGlmaWNhdGUgYnkgYW55IHBhcnR5IGFzc3VtZXMgYWNj +ZXB0YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJkIHRlcm1zIGFu +ZCBjb25kaXRpb25zIG9mIHVzZSwgY2VydGlmaWNhdGUgcG9saWN5IGFuZCBjZXJ0 +aWZpY2F0aW9uIHByYWN0aWNlIHN0YXRlbWVudHMuMDoGA1UdHwQzMDEwL6AtoCuG +KWh0dHA6Ly93d3cuYXBwbGUuY29tL2FwcGxlY2Evc3d1cGRhdGUuY3JsMA0GCSqG +SIb3DQEBBQUAA4IBAQB5O5mfgkJ5uo5BEagc7UzNh5lfRAG48TW9RcdlsN4/NX6a +gWXYRS7Ohh7qho8xtlk1QzPGWNY4tQISwB7NzJWAsc2cZfvN3phy891qYgmy5nzB +IyedZH5CIwjdBweVZ1jkFne1noR6G4RJRQgm98YmdSbAJ3kvJjIBCfNzf1SlnPPh +EWhKEByElIPUvX+MZAC1b72RSO0sbKBc92c1qfojqxhm0Gqt4cDgoiWq09q3290m +mxk8Xdba3ZDQq5wGWuLnEitFiMzqp7l6ratCYVl7ZwyLA6UchN4DtsGhcWnKBXtV +2kq5fCqVeWQopLYuNkqqdi32wNoxCYaUaELQceez +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleQuickTime.pem b/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleQuickTime.pem new file mode 100644 index 00000000..e95e04f2 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleQuickTime.pem @@ -0,0 +1,94 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 103 (0x67) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Apple Computer, Inc., OU=Apple Computer Certificate Authority, CN=Apple Software Update Certificate Authority + Validity + Not Before: Feb 10 18:55:38 2005 GMT + Not After : Feb 10 18:55:38 2007 GMT + Subject: C=US, O=Apple Computer, Inc., OU=Apple Computer Software Update, CN=QuickTime + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bb:ae:7c:1c:fa:5b:0a:a3:21:f5:d1:96:34:c5: + 66:d6:cf:4a:36:aa:79:e1:91:3b:1d:cb:63:c2:c4: + 9b:08:99:68:36:06:ff:1b:27:13:6f:e9:24:94:89: + f2:74:6d:20:0c:cf:09:aa:66:5d:c8:57:de:91:e8: + 41:03:e1:ec:ae:9a:c9:95:65:21:2d:d0:64:04:4d: + 04:af:9b:b3:e3:32:15:6a:10:30:96:2f:83:31:74: + 51:27:79:f0:22:0e:76:3d:a1:65:63:ab:f3:35:4a: + 1c:b8:1a:0b:2b:4b:da:d0:85:a5:f3:c8:99:41:de: + 5a:3b:ae:d8:cc:e4:48:32:09 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature + X509v3 Extended Key Usage: + Apple Code Signing + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Subject Key Identifier: + 75:8E:18:0C:D1:21:60:E0:CC:45:B7:3D:7B:D2:04:F6:8F:1B:9E:DE + X509v3 Authority Key Identifier: + keyid:5E:21:5B:43:BD:5E:74:56:8A:D7:C7:E0:15:32:FD:0A:FD:E8:46:C2 + + X509v3 Certificate Policies: + Policy: 1.2.840.113635.100.5.1 + CPS: https://www.apple.com/certificateauthority/terms.html + User Notice: + Explicit Text: Reliance on this certificate by any party assumes acceptance of the then applicable standard terms and conditions of use, certificate policy and certification practice statements. + + X509v3 CRL Distribution Points: + URI:https://www.apple.com/certificateauthority/swupdate.crl + + Authority Information Access: + CA Issuers - URI:https://www.apple.com/certificateauthority/casigners.html + + Signature Algorithm: sha1WithRSAEncryption + d0:3c:83:d8:5d:fa:d6:5a:41:e4:e3:73:e1:9e:fc:57:b8:7d: + 81:35:c4:5d:14:b8:a0:34:97:fe:e9:2e:63:57:db:ef:6f:8c: + 5f:b0:af:33:2e:39:1f:3d:18:8a:22:bb:2c:50:57:9e:49:d6: + 53:7b:40:9b:25:81:91:9d:75:d4:1d:21:3e:0d:ef:ab:6b:ce: + 6d:48:2f:dd:22:27:da:d5:80:b4:1b:77:07:f8:1e:12:55:47: + 00:55:5b:ab:3e:4b:60:7e:dd:d9:11:a9:de:cf:57:5e:1e:2a: + 76:4f:4f:b2:e8:c3:df:4c:35:dc:41:8c:62:be:9d:a5:2c:2f: + f5:42:e2:68:a2:e0:21:8a:ef:ce:83:5a:7b:35:08:d8:d4:e5: + 5b:d1:29:52:33:64:5f:46:0d:e8:07:73:2c:68:5b:65:b9:f7: + 13:6a:15:f5:20:74:52:30:60:09:d9:83:3f:79:4a:e1:6e:72: + 44:c3:f6:42:f6:25:65:9f:3b:d7:80:96:22:f2:80:7e:8a:9e: + 71:4e:17:30:a6:d8:c1:f8:38:37:db:e2:f0:9e:6d:65:f5:4f: + 07:55:10:5c:ec:3f:06:b5:b7:14:4f:6a:99:68:87:6d:f5:b4: + e1:9f:0a:1f:50:c8:1c:fa:53:fe:81:6f:85:49:1c:7e:e5:69: + c4:a0:e1:4c +-----BEGIN CERTIFICATE----- +MIIFOjCCBCKgAwIBAgIBZzANBgkqhkiG9w0BAQUFADCBkTELMAkGA1UEBhMCVVMx +HTAbBgNVBAoTFEFwcGxlIENvbXB1dGVyLCBJbmMuMS0wKwYDVQQLEyRBcHBsZSBD +b21wdXRlciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxNDAyBgNVBAMTK0FwcGxlIFNv +ZnR3YXJlIFVwZGF0ZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDUwMjEwMTg1 +NTM4WhcNMDcwMjEwMTg1NTM4WjBpMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUQXBw +bGUgQ29tcHV0ZXIsIEluYy4xJzAlBgNVBAsTHkFwcGxlIENvbXB1dGVyIFNvZnR3 +YXJlIFVwZGF0ZTESMBAGA1UEAxMJUXVpY2tUaW1lMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQC7rnwc+lsKoyH10ZY0xWbWz0o2qnnhkTsdy2PCxJsImWg2Bv8b +JxNv6SSUifJ0bSAMzwmqZl3IV96R6EED4eyumsmVZSEt0GQETQSvm7PjMhVqEDCW +L4MxdFEnefAiDnY9oWVjq/M1Shy4GgsrS9rQhaXzyJlB3lo7rtjM5EgyCQIDAQAB +o4ICRjCCAkIwDgYDVR0PAQH/BAQDAgeAMBQGA1UdJQQNMAsGCSqGSIb3Y2QEATAM +BgNVHRMBAf8EAjAAMB0GA1UdDgQWBBR1jhgM0SFg4MxFtz170gT2jxue3jAfBgNV +HSMEGDAWgBReIVtDvV50VorXx+AVMv0K/ehGwjCCASkGA1UdIASCASAwggEcMIIB +GAYJKoZIhvdjZAUBMIIBCTBBBggrBgEFBQcCARY1aHR0cHM6Ly93d3cuYXBwbGUu +Y29tL2NlcnRpZmljYXRlYXV0aG9yaXR5L3Rlcm1zLmh0bWwwgcMGCCsGAQUFBwIC +MIG2GoGzUmVsaWFuY2Ugb24gdGhpcyBjZXJ0aWZpY2F0ZSBieSBhbnkgcGFydHkg +YXNzdW1lcyBhY2NlcHRhbmNlIG9mIHRoZSB0aGVuIGFwcGxpY2FibGUgc3RhbmRh +cmQgdGVybXMgYW5kIGNvbmRpdGlvbnMgb2YgdXNlLCBjZXJ0aWZpY2F0ZSBwb2xp +Y3kgYW5kIGNlcnRpZmljYXRpb24gcHJhY3RpY2Ugc3RhdGVtZW50cy4wSAYDVR0f +BEEwPzA9oDugOYY3aHR0cHM6Ly93d3cuYXBwbGUuY29tL2NlcnRpZmljYXRlYXV0 +aG9yaXR5L3N3dXBkYXRlLmNybDBVBggrBgEFBQcBAQRJMEcwRQYIKwYBBQUHMAKG +OWh0dHBzOi8vd3d3LmFwcGxlLmNvbS9jZXJ0aWZpY2F0ZWF1dGhvcml0eS9jYXNp +Z25lcnMuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA0DyD2F361lpB5ONz4Z78V7h9 +gTXEXRS4oDSX/ukuY1fb72+MX7CvMy45Hz0YiiK7LFBXnknWU3tAmyWBkZ111B0h +Pg3vq2vObUgv3SIn2tWAtBt3B/geElVHAFVbqz5LYH7d2RGp3s9XXh4qdk9PsujD +30w13EGMYr6dpSwv9ULiaKLgIYrvzoNaezUI2NTlW9EpUjNkX0YN6AdzLGhbZbn3 +E2oV9SB0UjBgCdmDP3lK4W5yRMP2QvYlZZ8714CWIvKAfoqecU4XMKbYwfg4N9vi +8J5tZfVPB1UQXOw/BrW3FE9qmWiHbfW04Z8KH1DIHPpT/oFvhUkcfuVpxKDhTA== +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleROOTCA.pem b/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleROOTCA.pem new file mode 100644 index 00000000..a27252d0 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleROOTCA.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEuzCCA6OgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQGEwJVUzET +MBEGA1UEChMKQXBwbGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxFjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwHhcNMDYwNDI1MjE0 +MDM2WhcNMzUwMjA5MjE0MDM2WjBiMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQXBw +bGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx +FjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDkkakJH5HbHkdQ6wXtXnmELes2oldMVeyLGYne+Uts9QerIjAC6Bg+ ++FAJ039BqJj50cpmnCRrEdCju+QbKsMflZ56DKRHi1vUFjczy8QPTc4UadHJGXL1 +XQ7Vf1+b8iUDulWPTV0N8WQ1IxVLFVkds5T39pyez1C6wVhQZ48ItCD3y6wsIG9w +tj8BMIy3Q88PnT3zK0koGsj+zrW5DtleHNbLPbU6rfQPDgCSC7EhFi501TwN22IW +q6NxkkdTVcGvL0Gz+PvjcM3mo0xFfh9Ma1CWQYnEdGILEINBhzOKgbEwWOxaBDKM +aLOPHd5lc/9nXmW8Sdh2nzMUZaF3lMktAgMBAAGjggF6MIIBdjAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUK9BpR5R2Cf70a40uQKb3 +R01/CF4wHwYDVR0jBBgwFoAUK9BpR5R2Cf70a40uQKb3R01/CF4wggERBgNVHSAE +ggEIMIIBBDCCAQAGCSqGSIb3Y2QFATCB8jAqBggrBgEFBQcCARYeaHR0cHM6Ly93 +d3cuYXBwbGUuY29tL2FwcGxlY2EvMIHDBggrBgEFBQcCAjCBthqBs1JlbGlhbmNl +IG9uIHRoaXMgY2VydGlmaWNhdGUgYnkgYW55IHBhcnR5IGFzc3VtZXMgYWNjZXB0 +YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJkIHRlcm1zIGFuZCBj +b25kaXRpb25zIG9mIHVzZSwgY2VydGlmaWNhdGUgcG9saWN5IGFuZCBjZXJ0aWZp +Y2F0aW9uIHByYWN0aWNlIHN0YXRlbWVudHMuMA0GCSqGSIb3DQEBBQUAA4IBAQBc +NplMLXi37Yyb3PN3m/J20ncwT8EfhYOFG5k9RzfyqZtAjizUsZAS2L70c5vu0mQP +y3lPNNiiPvl4/2vIB+x9OYOLUyDTOMSxv5pPCmv/K/xZpwUJfBdAVhEedNO3iyM7 +R6PVbyTi69G3cN8PReEnyvFteO3ntRcXqNx+IjXKJdXZD9Zr1KIkIxH3oayPc4Fg +xhtbCS+SsvhESPBgOJ4V9T0mZyCKM2r3DYLP3uujL/lTaltkwGMzd/c6ByxW69oP +IQ7aunMZT7XZNn/Bh1XZp5m5MkL72NVxnn6hUrcbvZNCJBIqxw8dtk2cXmPIS4AX +UKqK1drk/NAJBzewdXUh +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleSWUPDATE.pem b/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleSWUPDATE.pem new file mode 100644 index 00000000..3c194451 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleSWUPDATE.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEFjCCAv6gAwIBAgIBFDANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQGEwJVUzET +MBEGA1UEChMKQXBwbGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxFjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwHhcNMDcwMjE0MjEw +MzU0WhcNMTUwMjE0MjEwMzU0WjCBgjELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkFw +cGxlIEluYy4xJjAkBgNVBAsTHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MTYwNAYDVQQDEy1BcHBsZSBTb2Z0d2FyZSBVcGRhdGUgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCyAvI/7DYl +ejquD20OX8UUTXo6jgJPEMjZNomE23VEisGej5Q6uC0CQQvtPA3vHA0uCd/3KJa7 +w4t9GLiQaxPywd42cv97O49HehfyrhM04zCy3PiSlgE2jmebZ9gB7Mn+33GZ047X +nYz364A4SXtmIrzL0V66/HKsf4GCkepguLGQq+5fcNu5oEt0UXKarlBfz9p39PjS +AvglzdBum/NobcPEbNhNiKok+r/vit/HF5Qe5/wprxXd7qqjfmILFJHZuG/RbIaV +kdbPYyfhtrlww5c/JKk7htkbFWY1A13c3qHLokau7W364KKq/iiKu7O5u4qUEwqi +T1DLSqc5ycEPAgMBAAGjgbUwgbIwDgYDVR0PAQH/BAQDAgGGMBcGA1UdJQEB/wQN +MAsGCSqGSIb3Y2QEATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSLxSlK86/K +oXKU9wZtR2NBsEeYITAfBgNVHSMEGDAWgBQr0GlHlHYJ/vRrjS5ApvdHTX8IXjA2 +BgNVHR8ELzAtMCugKaAnhiVodHRwOi8vd3d3LmFwcGxlLmNvbS9hcHBsZWNhL3Jv +b3QuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQAsI+raTtVA/x889Y9EP1nU8j18KbfX +U/Fx7cBUZRxGs3AdjsDiwIbUyX1E8UgKYB9WdPQoKIjKhAz9ZSMXUX8Rp99Ag/75 +VoseR1xs3OV/bzvV1mJGYD3LkliZYAjiHElunsauiuT3nUXrI/vbHlZ8vlZmE+53 +JAjhT+pOsCpNRa51Wt9QjEcApqt/DXFnxZAVsrsJE4pVQ8iGJ8nMtAj6HdJAzv5m +VC+QB/yIq/G6ci6lEhAy8OC6x8d4DLtE6guVJpXsaIc5i3q6sFoOETHNwF2yNVoh +DA09GksP5j0FBLnJ1npFpvPp1UxsAt6mEofXfEceNFyODAyMouD7K8kL +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleSecUpdate.pem b/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleSecUpdate.pem new file mode 100644 index 00000000..4b309a49 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleSecUpdate.pem @@ -0,0 +1,95 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 101 (0x65) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Apple Computer, Inc., OU=Apple Computer Certificate Authority, CN=Apple Software Update Certificate Authority + Validity + Not Before: Feb 10 18:55:34 2005 GMT + Not After : Feb 10 18:55:34 2007 GMT + Subject: C=US, O=Apple Computer, Inc., OU=Apple Computer Software Update, CN=Security Update + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:df:2c:ae:16:89:2f:56:3d:46:5a:86:d7:50:c3: + 14:ee:64:39:63:ae:05:a5:5f:c8:7a:df:cd:b0:70: + dc:c7:56:87:31:8a:19:a7:97:45:20:8f:e8:94:5a: + 9b:ca:fe:98:0b:d5:53:63:7e:b5:e8:a1:74:00:fb: + 07:1f:fb:ed:0c:3c:d2:40:25:d9:44:41:c9:4c:cd: + f0:93:8b:60:52:39:d6:31:6a:10:13:d7:84:ff:80: + 33:63:d8:99:41:98:35:97:25:a5:d7:50:26:65:63: + 16:32:82:73:1f:f0:80:87:a5:70:8f:2c:92:12:25: + 25:b9:9f:35:a6:89:60:b7:7f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature + X509v3 Extended Key Usage: + Apple Code Signing + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Subject Key Identifier: + B8:B8:A1:D0:52:48:E8:5C:95:D7:46:7B:83:61:4B:32:A9:5E:85:23 + X509v3 Authority Key Identifier: + keyid:5E:21:5B:43:BD:5E:74:56:8A:D7:C7:E0:15:32:FD:0A:FD:E8:46:C2 + + X509v3 Certificate Policies: + Policy: 1.2.840.113635.100.5.1 + CPS: https://www.apple.com/certificateauthority/terms.html + User Notice: + Explicit Text: Reliance on this certificate by any party assumes acceptance of the then applicable standard terms and conditions of use, certificate policy and certification practice statements. + + X509v3 CRL Distribution Points: + URI:https://www.apple.com/certificateauthority/swupdate.crl + + Authority Information Access: + CA Issuers - URI:https://www.apple.com/certificateauthority/casigners.html + + Signature Algorithm: sha1WithRSAEncryption + 70:54:b0:e8:ea:c3:a4:7c:41:12:ee:56:38:dd:58:b9:a9:79: + e3:79:a4:f7:e7:df:72:b5:6d:ed:a5:d8:0e:3b:4f:d9:6a:32: + 08:cb:5c:18:f9:9d:b8:d8:99:d7:14:f9:dc:1d:0f:84:d2:b3: + 21:0b:c0:3b:15:00:cc:e7:c5:58:f5:91:a3:fb:96:a4:44:b9: + 05:2d:3f:8d:63:53:b1:22:46:65:0c:c4:d4:f2:6b:43:54:47: + d5:40:b5:0d:0c:b2:18:5b:70:1d:d4:3a:52:58:78:7f:5e:38: + 15:9b:0d:23:a0:3e:b4:fe:d3:1a:1a:2e:82:8c:d2:24:4e:3f: + d5:65:96:ae:3d:d3:68:0c:e2:39:94:ea:aa:1b:69:6d:ed:6e: + 5a:d5:c6:c2:31:1b:23:ac:b5:78:59:4c:c7:f8:a4:db:2f:0f: + 48:8f:29:30:18:9b:32:5f:2f:c8:94:6e:83:fe:9d:c1:47:bb: + 37:d1:85:2c:d3:8e:b8:e2:cb:7b:3e:ab:b4:28:2a:66:63:ce: + 00:d4:60:2e:d3:9c:0e:50:fe:cb:0c:2c:24:f9:73:1f:ac:10: + de:ee:9c:9b:86:d9:46:98:bc:f2:f0:ae:e3:04:06:69:49:fb: + 56:c7:bd:17:76:b7:6b:fa:32:77:3c:50:5c:c0:ce:fa:b7:93: + b3:c4:e2:c9 +-----BEGIN CERTIFICATE----- +MIIFQDCCBCigAwIBAgIBZTANBgkqhkiG9w0BAQUFADCBkTELMAkGA1UEBhMCVVMx +HTAbBgNVBAoTFEFwcGxlIENvbXB1dGVyLCBJbmMuMS0wKwYDVQQLEyRBcHBsZSBD +b21wdXRlciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxNDAyBgNVBAMTK0FwcGxlIFNv +ZnR3YXJlIFVwZGF0ZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDUwMjEwMTg1 +NTM0WhcNMDcwMjEwMTg1NTM0WjBvMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUQXBw +bGUgQ29tcHV0ZXIsIEluYy4xJzAlBgNVBAsTHkFwcGxlIENvbXB1dGVyIFNvZnR3 +YXJlIFVwZGF0ZTEYMBYGA1UEAxMPU2VjdXJpdHkgVXBkYXRlMIGfMA0GCSqGSIb3 +DQEBAQUAA4GNADCBiQKBgQDfLK4WiS9WPUZahtdQwxTuZDljrgWlX8h6382wcNzH +Vocxihmnl0Ugj+iUWpvK/pgL1VNjfrXooXQA+wcf++0MPNJAJdlEQclMzfCTi2BS +OdYxahAT14T/gDNj2JlBmDWXJaXXUCZlYxYygnMf8ICHpXCPLJISJSW5nzWmiWC3 +fwIDAQABo4ICRjCCAkIwDgYDVR0PAQH/BAQDAgeAMBQGA1UdJQQNMAsGCSqGSIb3 +Y2QEATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBS4uKHQUkjoXJXXRnuDYUsyqV6F +IzAfBgNVHSMEGDAWgBReIVtDvV50VorXx+AVMv0K/ehGwjCCASkGA1UdIASCASAw +ggEcMIIBGAYJKoZIhvdjZAUBMIIBCTBBBggrBgEFBQcCARY1aHR0cHM6Ly93d3cu +YXBwbGUuY29tL2NlcnRpZmljYXRlYXV0aG9yaXR5L3Rlcm1zLmh0bWwwgcMGCCsG +AQUFBwICMIG2GoGzUmVsaWFuY2Ugb24gdGhpcyBjZXJ0aWZpY2F0ZSBieSBhbnkg +cGFydHkgYXNzdW1lcyBhY2NlcHRhbmNlIG9mIHRoZSB0aGVuIGFwcGxpY2FibGUg +c3RhbmRhcmQgdGVybXMgYW5kIGNvbmRpdGlvbnMgb2YgdXNlLCBjZXJ0aWZpY2F0 +ZSBwb2xpY3kgYW5kIGNlcnRpZmljYXRpb24gcHJhY3RpY2Ugc3RhdGVtZW50cy4w +SAYDVR0fBEEwPzA9oDugOYY3aHR0cHM6Ly93d3cuYXBwbGUuY29tL2NlcnRpZmlj +YXRlYXV0aG9yaXR5L3N3dXBkYXRlLmNybDBVBggrBgEFBQcBAQRJMEcwRQYIKwYB +BQUHMAKGOWh0dHBzOi8vd3d3LmFwcGxlLmNvbS9jZXJ0aWZpY2F0ZWF1dGhvcml0 +eS9jYXNpZ25lcnMuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEAcFSw6OrDpHxBEu5W +ON1Yual543mk9+ffcrVt7aXYDjtP2WoyCMtcGPmduNiZ1xT53B0PhNKzIQvAOxUA +zOfFWPWRo/uWpES5BS0/jWNTsSJGZQzE1PJrQ1RH1UC1DQyyGFtwHdQ6Ulh4f144 +FZsNI6A+tP7TGhougozSJE4/1WWWrj3TaAziOZTqqhtpbe1uWtXGwjEbI6y1eFlM +x/ik2y8PSI8pMBibMl8vyJRug/6dwUe7N9GFLNOOuOLLez6rtCgqZmPOANRgLtOc +DlD+ywwsJPlzH6wQ3u6cm4bZRpi88vCu4wQGaUn7Vse9F3a3a/oydzxQXMDO+reT +s8TiyQ== +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleSherlock.pem b/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleSherlock.pem new file mode 100644 index 00000000..39a756ce --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleSherlock.pem @@ -0,0 +1,94 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 102 (0x66) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Apple Computer, Inc., OU=Apple Computer Certificate Authority, CN=Apple Software Update Certificate Authority + Validity + Not Before: Feb 10 18:55:36 2005 GMT + Not After : Feb 10 18:55:36 2007 GMT + Subject: C=US, O=Apple Computer, Inc., OU=Apple Computer Software Update, CN=Sherlock + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e9:35:95:82:34:0d:c8:79:a0:6f:78:a7:e6:9f: + 69:d3:c8:2c:92:86:50:2b:c4:29:53:b6:1d:fa:97: + 88:59:eb:68:d9:a9:83:a3:67:82:91:4c:99:20:24: + a1:80:60:1f:1a:20:f2:04:15:6b:79:66:4d:d7:af: + 3c:04:f6:b4:0d:d8:92:d3:20:52:a6:7c:14:a2:5d: + 6c:b0:64:87:fc:12:5a:33:c3:e8:73:8f:93:f1:e0: + 51:58:87:5d:07:8e:fa:04:cc:a4:f7:ea:9f:cd:dd: + 6e:68:23:9c:5c:0d:dc:30:1e:4a:21:d7:ab:6a:65: + 0b:80:24:7c:cf:19:7f:44:99 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature + X509v3 Extended Key Usage: + Apple Code Signing + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Subject Key Identifier: + EE:E7:02:1F:F8:46:A3:D7:15:1A:51:8B:F8:C1:1C:35:47:23:29:BC + X509v3 Authority Key Identifier: + keyid:5E:21:5B:43:BD:5E:74:56:8A:D7:C7:E0:15:32:FD:0A:FD:E8:46:C2 + + X509v3 Certificate Policies: + Policy: 1.2.840.113635.100.5.1 + CPS: https://www.apple.com/certificateauthority/terms.html + User Notice: + Explicit Text: Reliance on this certificate by any party assumes acceptance of the then applicable standard terms and conditions of use, certificate policy and certification practice statements. + + X509v3 CRL Distribution Points: + URI:https://www.apple.com/certificateauthority/swupdate.crl + + Authority Information Access: + CA Issuers - URI:https://www.apple.com/certificateauthority/casigners.html + + Signature Algorithm: sha1WithRSAEncryption + c1:1d:87:7f:61:c4:b0:a8:7d:1d:87:fa:48:4c:c4:77:cd:ba: + 46:2e:63:d0:41:e6:9c:c1:9c:57:15:26:4c:86:80:ff:68:d5: + 85:1e:d1:ce:67:2d:62:44:05:ec:7f:d0:0f:75:16:a9:f3:12: + 2e:7d:65:32:51:eb:26:17:25:80:f3:33:57:b0:3d:a9:89:e6: + ac:69:68:08:7a:7a:db:34:61:2c:4f:a9:cd:54:b0:d2:3e:a9: + bd:54:7a:cf:c0:a0:20:8e:61:52:0e:ba:77:21:f0:b4:91:ad: + f7:45:ee:a0:62:93:3b:4d:b5:c2:01:1f:11:03:3e:eb:58:05: + c7:44:7f:ae:be:fd:73:02:89:81:05:61:d2:62:00:8a:1b:e7: + bd:4c:68:2d:72:4a:ad:f3:70:b4:c7:0d:fa:fb:69:3b:bd:21: + 5d:9d:b9:a5:cc:b7:11:ed:af:77:c0:7e:4a:98:8d:c3:48:82: + 8d:97:6f:35:c8:f7:48:d5:cd:8b:7c:4c:d5:72:c4:0f:7d:de: + c9:f1:7a:d6:87:ab:39:14:db:16:7e:64:37:50:ce:bf:d9:7b: + 03:9d:ae:e8:64:bd:31:85:3d:63:53:a3:e6:ea:14:07:82:f7: + 10:aa:9c:38:92:cd:2c:1d:46:33:5f:50:41:82:6a:11:ee:78: + 42:c1:16:84 +-----BEGIN CERTIFICATE----- +MIIFOTCCBCGgAwIBAgIBZjANBgkqhkiG9w0BAQUFADCBkTELMAkGA1UEBhMCVVMx +HTAbBgNVBAoTFEFwcGxlIENvbXB1dGVyLCBJbmMuMS0wKwYDVQQLEyRBcHBsZSBD +b21wdXRlciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxNDAyBgNVBAMTK0FwcGxlIFNv +ZnR3YXJlIFVwZGF0ZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDUwMjEwMTg1 +NTM2WhcNMDcwMjEwMTg1NTM2WjBoMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUQXBw +bGUgQ29tcHV0ZXIsIEluYy4xJzAlBgNVBAsTHkFwcGxlIENvbXB1dGVyIFNvZnR3 +YXJlIFVwZGF0ZTERMA8GA1UEAxMIU2hlcmxvY2swgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBAOk1lYI0Dch5oG94p+afadPILJKGUCvEKVO2HfqXiFnraNmpg6Nn +gpFMmSAkoYBgHxog8gQVa3lmTdevPAT2tA3YktMgUqZ8FKJdbLBkh/wSWjPD6HOP +k/HgUViHXQeO+gTMpPfqn83dbmgjnFwN3DAeSiHXq2plC4AkfM8Zf0SZAgMBAAGj +ggJGMIICQjAOBgNVHQ8BAf8EBAMCB4AwFAYDVR0lBA0wCwYJKoZIhvdjZAQBMAwG +A1UdEwEB/wQCMAAwHQYDVR0OBBYEFO7nAh/4RqPXFRpRi/jBHDVHIym8MB8GA1Ud +IwQYMBaAFF4hW0O9XnRWitfH4BUy/Qr96EbCMIIBKQYDVR0gBIIBIDCCARwwggEY +BgkqhkiG92NkBQEwggEJMEEGCCsGAQUFBwIBFjVodHRwczovL3d3dy5hcHBsZS5j +b20vY2VydGlmaWNhdGVhdXRob3JpdHkvdGVybXMuaHRtbDCBwwYIKwYBBQUHAgIw +gbYagbNSZWxpYW5jZSBvbiB0aGlzIGNlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh +c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy +ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRlIHBvbGlj +eSBhbmQgY2VydGlmaWNhdGlvbiBwcmFjdGljZSBzdGF0ZW1lbnRzLjBIBgNVHR8E +QTA/MD2gO6A5hjdodHRwczovL3d3dy5hcHBsZS5jb20vY2VydGlmaWNhdGVhdXRo +b3JpdHkvc3d1cGRhdGUuY3JsMFUGCCsGAQUFBwEBBEkwRzBFBggrBgEFBQcwAoY5 +aHR0cHM6Ly93d3cuYXBwbGUuY29tL2NlcnRpZmljYXRlYXV0aG9yaXR5L2Nhc2ln +bmVycy5odG1sMA0GCSqGSIb3DQEBBQUAA4IBAQDBHYd/YcSwqH0dh/pITMR3zbpG +LmPQQeacwZxXFSZMhoD/aNWFHtHOZy1iRAXsf9APdRap8xIufWUyUesmFyWA8zNX +sD2pieasaWgIenrbNGEsT6nNVLDSPqm9VHrPwKAgjmFSDrp3IfC0ka33Re6gYpM7 +TbXCAR8RAz7rWAXHRH+uvv1zAomBBWHSYgCKG+e9TGgtckqt83C0xw36+2k7vSFd +nbmlzLcR7a93wH5KmI3DSIKNl281yPdI1c2LfEzVcsQPfd7J8XrWh6s5FNsWfmQ3 +UM6/2XsDna7oZL0xhT1jU6Pm6hQHgvcQqpw4ks0sHUYzX1BBgmoR7nhCwRaE +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleSignUpdate.pem b/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleSignUpdate.pem new file mode 100644 index 00000000..8c5919ec --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleSignUpdate.pem @@ -0,0 +1,95 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 104 (0x68) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Apple Computer, Inc., OU=Apple Computer Certificate Authority, CN=Apple Software Update Certificate Authority + Validity + Not Before: Feb 10 18:55:40 2005 GMT + Not After : Feb 10 18:55:40 2007 GMT + Subject: C=US, O=Apple Computer, Inc., OU=Apple Computer Software Update, CN=Signed Update + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b6:e1:d1:0a:c0:25:12:5e:ef:76:2a:a6:4a:c7: + 84:7c:00:71:0e:77:7a:1e:2a:75:69:d2:61:a9:3a: + 43:15:a9:00:7f:45:aa:2c:0f:00:89:af:6e:af:3e: + 60:8d:21:2b:5d:28:d7:48:63:16:df:4f:60:34:07: + a7:6a:30:bf:0b:12:bd:32:c9:77:5f:e5:de:c5:37: + 9b:27:c9:d1:1d:40:5c:ea:ff:40:ab:76:15:41:85: + 96:5f:d4:c9:53:e7:36:e9:e9:8a:07:09:e7:d6:a1: + e5:fe:ec:18:f7:91:ca:2a:5d:f6:d3:75:ab:6d:39: + e6:6e:b5:9b:fb:4f:ec:6b:57 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature + X509v3 Extended Key Usage: + Apple Code Signing + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Subject Key Identifier: + BC:25:56:53:1A:91:C0:99:1C:82:FB:C6:0D:0B:DB:AB:35:AD:75:3C + X509v3 Authority Key Identifier: + keyid:5E:21:5B:43:BD:5E:74:56:8A:D7:C7:E0:15:32:FD:0A:FD:E8:46:C2 + + X509v3 Certificate Policies: + Policy: 1.2.840.113635.100.5.1 + CPS: https://www.apple.com/certificateauthority/terms.html + User Notice: + Explicit Text: Reliance on this certificate by any party assumes acceptance of the then applicable standard terms and conditions of use, certificate policy and certification practice statements. + + X509v3 CRL Distribution Points: + URI:https://www.apple.com/certificateauthority/swupdate.crl + + Authority Information Access: + CA Issuers - URI:https://www.apple.com/certificateauthority/casigners.html + + Signature Algorithm: sha1WithRSAEncryption + be:8f:07:6d:58:35:e3:f3:13:7c:1d:1c:d1:7c:56:da:b3:a6: + 8f:68:f8:c5:cb:63:41:e5:93:69:4a:8d:fe:6a:4e:52:77:73: + bf:ed:6b:89:91:d0:dc:b2:81:b3:37:4c:d5:2c:4c:0d:41:80: + 19:39:be:5c:5d:6d:4c:fe:3d:4b:22:a3:03:70:64:e8:d1:e2: + e7:51:3f:d7:d3:fd:2d:d1:f3:35:bf:9a:0d:58:e3:6c:2d:a7: + 41:4a:13:44:0a:cd:aa:97:70:77:13:5e:98:41:56:cf:62:67: + 89:54:3c:9e:9a:52:36:83:a2:c6:28:db:a9:7e:41:66:92:88: + a8:8b:66:28:c8:b1:dd:f6:cd:36:06:d6:89:0e:8d:46:82:a5: + d9:75:ba:ac:a1:d6:60:4e:79:1e:cb:dc:88:70:c6:f1:25:91: + 90:4c:9f:db:8c:03:c0:c2:74:2f:88:4f:d2:43:06:3a:2c:a9: + 23:9f:17:c3:13:79:b6:20:5b:91:d8:f6:dc:64:9c:c1:48:b8: + 96:18:79:8f:65:0a:a3:0b:e2:14:b7:64:b6:ba:3d:9e:8a:13: + f8:7a:f0:b5:d5:7e:c4:ef:77:d2:2d:12:ff:94:f6:1e:51:f1: + f9:1c:6d:c0:78:13:ab:e1:b3:dd:99:1f:6e:23:cc:85:f3:0a: + bd:84:fb:c8 +-----BEGIN CERTIFICATE----- +MIIFPjCCBCagAwIBAgIBaDANBgkqhkiG9w0BAQUFADCBkTELMAkGA1UEBhMCVVMx +HTAbBgNVBAoTFEFwcGxlIENvbXB1dGVyLCBJbmMuMS0wKwYDVQQLEyRBcHBsZSBD +b21wdXRlciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxNDAyBgNVBAMTK0FwcGxlIFNv +ZnR3YXJlIFVwZGF0ZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDUwMjEwMTg1 +NTQwWhcNMDcwMjEwMTg1NTQwWjBtMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUQXBw +bGUgQ29tcHV0ZXIsIEluYy4xJzAlBgNVBAsTHkFwcGxlIENvbXB1dGVyIFNvZnR3 +YXJlIFVwZGF0ZTEWMBQGA1UEAxMNU2lnbmVkIFVwZGF0ZTCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAtuHRCsAlEl7vdiqmSseEfABxDnd6Hip1adJhqTpDFakA +f0WqLA8Aia9urz5gjSErXSjXSGMW309gNAenajC/CxK9Msl3X+XexTebJ8nRHUBc +6v9Aq3YVQYWWX9TJU+c26emKBwnn1qHl/uwY95HKKl3203WrbTnmbrWb+0/sa1cC +AwEAAaOCAkYwggJCMA4GA1UdDwEB/wQEAwIHgDAUBgNVHSUEDTALBgkqhkiG92Nk +BAEwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUvCVWUxqRwJkcgvvGDQvbqzWtdTww +HwYDVR0jBBgwFoAUXiFbQ71edFaK18fgFTL9Cv3oRsIwggEpBgNVHSAEggEgMIIB +HDCCARgGCSqGSIb3Y2QFATCCAQkwQQYIKwYBBQUHAgEWNWh0dHBzOi8vd3d3LmFw +cGxlLmNvbS9jZXJ0aWZpY2F0ZWF1dGhvcml0eS90ZXJtcy5odG1sMIHDBggrBgEF +BQcCAjCBthqBs1JlbGlhbmNlIG9uIHRoaXMgY2VydGlmaWNhdGUgYnkgYW55IHBh +cnR5IGFzc3VtZXMgYWNjZXB0YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0 +YW5kYXJkIHRlcm1zIGFuZCBjb25kaXRpb25zIG9mIHVzZSwgY2VydGlmaWNhdGUg +cG9saWN5IGFuZCBjZXJ0aWZpY2F0aW9uIHByYWN0aWNlIHN0YXRlbWVudHMuMEgG +A1UdHwRBMD8wPaA7oDmGN2h0dHBzOi8vd3d3LmFwcGxlLmNvbS9jZXJ0aWZpY2F0 +ZWF1dGhvcml0eS9zd3VwZGF0ZS5jcmwwVQYIKwYBBQUHAQEESTBHMEUGCCsGAQUF +BzAChjlodHRwczovL3d3dy5hcHBsZS5jb20vY2VydGlmaWNhdGVhdXRob3JpdHkv +Y2FzaWduZXJzLmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAL6PB21YNePzE3wdHNF8 +Vtqzpo9o+MXLY0Hlk2lKjf5qTlJ3c7/ta4mR0NyygbM3TNUsTA1BgBk5vlxdbUz+ +PUsiowNwZOjR4udRP9fT/S3R8zW/mg1Y42wtp0FKE0QKzaqXcHcTXphBVs9iZ4lU +PJ6aUjaDosYo26l+QWaSiKiLZijIsd32zTYG1okOjUaCpdl1uqyh1mBOeR7L3Ihw +xvElkZBMn9uMA8DCdC+IT9JDBjosqSOfF8MTebYgW5HY9txknMFIuJYYeY9lCqML +4hS3ZLa6PZ6KE/h68LXVfsTvd9ItEv+U9h5R8fkcbcB4E6vhs92ZH24jzIXzCr2E ++8g= +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleSoftUpdate.pem b/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleSoftUpdate.pem new file mode 100644 index 00000000..7116ae73 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/AppleCerts/AppleSoftUpdate.pem @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFJjCCBA6gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMCVVMx +EzARBgNVBAoTCkFwcGxlIEluYy4xJjAkBgNVBAsTHUFwcGxlIENlcnRpZmljYXRp +b24gQXV0aG9yaXR5MTYwNAYDVQQDEy1BcHBsZSBTb2Z0d2FyZSBVcGRhdGUgQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDcwMjIzMjIxNDA5WhcNMTUwMTE0MjIx +NDA5WjBcMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQXBwbGUgSW5jLjEeMBwGA1UE +CxMVQXBwbGUgU29mdHdhcmUgVXBkYXRlMRgwFgYDVQQDEw9Tb2Z0d2FyZSBVcGRh +dGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGRQ3tU+oM51gMFQ/m +mlmTWJr2OHI7qvLS8lkAvAUoo9l+cVzKNnKUBPtrNtC/JadC8mtayRtWjG1YUwQr +Ou878I2jFyT5HchKFVFCsfyS/4HZ23OPFC2CKPSM9TMLREY0/RPVrACs/jULPgwu +ItAoTy3W7ajVr+QcWd90xChgZ5BCFvaWlj3MnueQCGR344NH/i4j1xvxRmDPttqf +b6RSAm6WDsNK0Y5iqnPEjSGff9Kce8Vl0Djsg1vA+FP61Cv3tc8W8LReJlyqKeDb +ldRR9QVRDTfqiigwyhX7HY6DVgA4t4/6kBuce38gTG6NM9NkwQqYr1mGBfd2+KYg +qdCXAgMBAAGjggHKMIIBxjAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAX +BgNVHSUBAf8EDTALBgkqhkiG92NkBAEwHQYDVR0OBBYEFN6V7Gxjp8FXb5QtH8vo +V8530ydUMB8GA1UdIwQYMBaAFIvFKUrzr8qhcpT3Bm1HY0GwR5ghMIIBDwYDVR0g +BIIBBjCCAQIwgf8GCSqGSIb3Y2QFATCB8TApBggrBgEFBQcCARYdaHR0cDovL3d3 +dy5hcHBsZS5jb20vYXBwbGVjYS8wgcMGCCsGAQUFBwICMIG2GoGzUmVsaWFuY2Ug +b24gdGhpcyBjZXJ0aWZpY2F0ZSBieSBhbnkgcGFydHkgYXNzdW1lcyBhY2NlcHRh +bmNlIG9mIHRoZSB0aGVuIGFwcGxpY2FibGUgc3RhbmRhcmQgdGVybXMgYW5kIGNv +bmRpdGlvbnMgb2YgdXNlLCBjZXJ0aWZpY2F0ZSBwb2xpY3kgYW5kIGNlcnRpZmlj +YXRpb24gcHJhY3RpY2Ugc3RhdGVtZW50cy4wOgYDVR0fBDMwMTAvoC2gK4YpaHR0 +cDovL3d3dy5hcHBsZS5jb20vYXBwbGVjYS9zd3VwZGF0ZS5jcmwwDQYJKoZIhvcN +AQEFBQADggEBABtgcO6id2u6w481jEcvknC1KoVHG1W7PKukGWzzKtD4OYEspzpc +w5GYlLHIWaoZbGaNefjYvrFjE0S4jX6umimFN0Oo66r+NEKsqMIUTxiZmOSDVQkR +BiUupGxm8DbnnkKkcsC4522R6cEMtOr24jKbSg5vEoNBKwPHscb0jt7Wo/8iFzIu +QZ9IDrfc2QTGzAt7i5/ITqsLh0Z780u3omeRUOyZBAgxC5WRyosqoxvRxCtji7Ox +zv9kGjvp0QhPYODPS3479DvtkoEdawS//e+pHxx7e+UT8b9xw4+y6kpP842woyhC +CnCrV4p34+LD6pFWkGrWMquU9H1op1qKjSs= +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/AppleCodeSigning.scr b/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/AppleCodeSigning.scr new file mode 100644 index 00000000..aea48eab --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/AppleCodeSigning.scr @@ -0,0 +1,83 @@ +# +# Test Software Update Apple Code Signing cert verification policy. +# This used to be called the Code Signing POlicy; it was renamed on 8/15/06. +# +# The keychain CodeSignTest.keychain, in this directory, contains all the +# keys and certs used to generate these test cases. Password is CodeSignTest. +# +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +end + +test = "Full Code Signing verification success" +cert = csLeaf.cer +cert = csCA.cer +root = csRoot.cer +policy = swuSign +end + +test = "DEVELOPMENT detection" +cert = csDevLeaf.cer +cert = csCA.cer +root = csRoot.cer +policy = swuSign +error = APPLETP_CODE_SIGN_DEVELOPMENT +certerror = 0:APPLETP_CODE_SIGN_DEVELOPMENT +end + +test = "No ExtendedKeyUsage in Leaf" +cert = csLeafNoEKU.cer +cert = csCA.cer +root = csRoot.cer +policy = swuSign +error = APPLETP_CS_NO_EXTENDED_KEY_USAGE +certerror = 0:APPLETP_CS_NO_EXTENDED_KEY_USAGE +end + +test = "Bad ExtendedKeyUsage in Leaf" +cert = csLeafBadEKU.cer +cert = csCA.cer +root = csRoot.cer +policy = swuSign +error = APPLETP_INVALID_EXTENDED_KEY_USAGE +certerror = 0:APPLETP_INVALID_EXTENDED_KEY_USAGE +end + +test = "No ExtendedKeyUsage in Intermediate" +cert = csLeafNoEKUinInt.cer +cert = csCaNoEKU.cer +root = csRoot.cer +policy = swuSign +error = APPLETP_CS_NO_EXTENDED_KEY_USAGE +certerror = 1:APPLETP_CS_NO_EXTENDED_KEY_USAGE +end + +test = "Bad ExtendedKeyUsage in Intermediate" +cert = csLeafBadEKUinInt.cer +cert = csCaBadEKU.cer +root = csRoot.cer +policy = swuSign +error = APPLETP_INVALID_EXTENDED_KEY_USAGE +certerror = 1:APPLETP_INVALID_EXTENDED_KEY_USAGE +end + +test = "No BC in Intermediate" +cert = csLeafNoBcInInt.cer +cert = csCaNoBC.cer +root = csRoot.cer +policy = swuSign +error = CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS +certerror = 1:CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS +end + +test = "Short Path" +cert = csLeafShortPath.cer +root = csRoot.cer +policy = swuSign +error = CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH +end + + diff --git a/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/CodeSignTest.keychain b/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/CodeSignTest.keychain new file mode 100644 index 0000000000000000000000000000000000000000..bbf840c1b8600a419415ba243beae502aed5ca14 GIT binary patch literal 88764 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 KZyle!?*#znX1sC$ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csCaBadEKU.cer b/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csCaBadEKU.cer new file mode 100644 index 0000000000000000000000000000000000000000..c644630676d5d75ee2064dc0e942a06b93f51ff8 GIT binary patch literal 559 zcmXqLV$wEfVw|#onTe5!iBZ6Sn~hVe&7h;x2QszPvP zdY*!dt5c}ELQsBwiJ`cGC`g)%htIK~ASYG9IX}0cv?R62Ku(<3z|_FV(9F=p$k5O% zN}Sga#5I9(4Ll5W4YVO9tDu|gnFll>H#H?Qu_RT&$}4=$>||^&*`h}FXNvde7(?ZZa%N_@~_JAKl0tr)XeT%A$;2Z zgemLU1DEz4bo49^l6K_09jIOC-+1h*$AK@o_Wf)d?T^2BZ}aYy*`EG`?)#6jDMtvL bGs=D|T^7Gz!TEfA1w)9QMLf%Y@r0=W7y-F4 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csCaBadPLC.cer b/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csCaBadPLC.cer new file mode 100644 index 0000000000000000000000000000000000000000..c99f61d8740281ee8f9a150e93c6627f7dd2280f GIT binary patch literal 567 zcmXqLVlp;pVw|&pnTe5!iBZsin~hVe&7h;x2QszPvP zdY*!dt5c}ELQsBwiJ`cGC`g)%htIK~ASYG9IX}0cv?R62Ku(<3z|_FV(9F=p$k5m_ zN}Sga#5I9(4Ll5W4YVO9tDu|gnFll>H#H?Qu_RT&$}4=$>||L!LF{E5#rUi{ZT%f!scz_{4nz}7$r z=vP@`M#ldv90qJaiiwfYfDa_b4-#VmhJKrYIEb$b;`73zAvuMG5!rvNApbQoNb+f0 z{JhV^m9Bnux5Cl%%%bEsHbOU;)vCT|L0*NF_v+l_71!53nz^t2 z!pb`<*F5Z+dtS@4XHM&!`;xgFJQAlS$=`0AZkl?dqe$l$CuY%-u@}`<; zZ)$iH*_|a=>wA+cQ^z-FfnxlDOVM`&^yLDAcf7WFC}+EP^>QX=Mh3>kKz|zW0evdV z&&c?ng#{SSZ3f~XzAA{%3lH$*6c$Egzp#S*(#RmTs_vF&;Cq${ryl9JJF=V4eEM`= zQcuU^JPp&m4(<~hpS$t>)N4GqPmYtt@SFDPXczPKYgxtjz7L5oV?6aT@1%CP)Q1DF zCVaBLG*kMqPvMWW2`=Af2-kEjecSkYa;H>J&Bm$K=F#?@mywaxz`{`0K$?v?l!ci`#5q4DRUtSt zJx{^K)hX0nAt*n;#8BKo6eP{X!{=B~kdvz5oS$1zT9R61AScdiU}|7wXl7_)WMFC* zCC+OI;+jCY2JVJB23io4mC;T1%mbQ`o0^iDSdyyX=da-E9g5qc#`y-k2q!bLGB7vx zG8i;=GBq|bOl2~9-kNQvTk!iw;qI@x7Ekn86Av>inDj3^F?HS#n?S|HM?ZL;mM*Wf zeySE_kdS4mR3>qysrU8v^_Tn7o}{l@!L+OGv3mB8d@Z9%%O)D_5qPbvw7K}f+>l?h zswOovth#m2!*bS{1pc)Lj1SJUXEkbBRC(kiTlN06yO%!SnZYZ~#LURRxLD0V#Xtz? zRas$1#{VoF25dlziIKs84!iU+-#@H!Wi3wGU@iL?7*)lePK9g#xyN_YTagU9hh-FzEW@&>|My zd7qE#?P6GGki{(S9l*Y@^YWamJ$$q7_+6_j4~}bpuTyaSgNLt~)bX$9FJ&24mrvL% RZypn~IBG{@4)e>Gh5)}3!Vv%f literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csCaNoPLC.cer b/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csCaNoPLC.cer new file mode 100644 index 0000000000000000000000000000000000000000..dd6e567c1fbe25f9810b91a312e4102531b774c4 GIT binary patch literal 563 zcmXqLV$wHgVw|ynnTe5!iBZUan~hVe&7h;x2QszPvP zdY*!dt5c}ELQsBwiJ`cGC`g)%htIK~ASYG9IX}0cv?R62Ku(<3z|_FV(9F=p$k5av zN}Lx+8X1~Exd!frItE%0laVvNA9? z_A(eWb}}_KGVGGbZrP+cRW5SP?%#g)PuuqVHavXnKlkfByZN=$!k=D`-?r?p9?OG* ziPI(4=ro-bYSW_|3$v9T7c9D%Xbb@M49ukf literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csDevLeaf.cer b/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csDevLeaf.cer new file mode 100644 index 0000000000000000000000000000000000000000..88a966ccddcdb21f8e08ec822ea838e0baa6624d GIT binary patch literal 556 zcmXqLV$v{ZVw|{unTe5!iILNQn~hVe&7kaK=YszPvP zdY*!dt5c}Eg0rKcxPd50l8cAWv7jI)Rlzwwx1h8nwa7qDoY%nAz{t?d(8SQxz%WXj z7f2ZaIS{Uai=n20I>cO{CRB4>Qp-|v@(XfP^GXzaQWMi~+tN7SfEVFfMpg#q#$E=4 z#!jZjMusKVCVbbhS{VK_^}4&Z&p)@*W?ugGL;knG?!!#Xj0}v6tqd#-_<{bE z6=r1o&%$cJ%*e=Kzy}iG2MMq+GqE>-!%$Y0h0lP8jSC#~$tf(1jL2SN1$nKJ!SLJN zv_CNkeYvySb#}c@d3{0CJ#ouyzr2KAU$=XIA0OPX!(F?!BHU%cqU3dI?h1;o3X5d_ z&1?5Ky?}AqZRwsmOU(xxe@g7kPQLVFi5zQM>H?QyrJP+okKV+aCvUA6^tR$;IKbfR fp}+bX5&Bm$K=F#?@mywaxz|2tEK$49)l!ci`$T>eHRUtSt zJx{^K)hX0n!P(JJ+&~m0$;HFxSWu9Ys^FZTTToh(T4W$6&TC+5U}R`!Xkut$ViqON zYY5^3Ibg1Vg`up0G{jsHbaQ=D6Vq^;+&JHW7vVxiRtDzAUIv54PNv32hC>-=mbsV~{_eS-D)Hj1 z^`z4o-Tn%v)!t5EJN|Eh8HbhnR1f>FOw5c7jEgM|%nkT~ev=huWc<&RHyDV3_^K?t@Ze5PVPQn}87s(VjSRM1{7UTKA1_%P9i!dj^d?Sd^6hSY z(ZUHVTR$A@5)oik|GanA#*CJz%d7U@bh*mOW_I(0^}eYpzCjz=r(HZNrXbSzaN`WW zCL5#08IfYl?ZLO!#F&Bm$K=F#?@mywaxz|2tEK$49)l!ci`$T>eHRUtSt zJx{^K)hX0n!P(JJ+&~m0$;HFxSWu9Ys^FZTTToh(T4W$6&TC+5U}R`!Xkut-Y8WNX zYY5_+K)D7EhN=e25OZbF&Gku5OjB@jbWw2i4#jOl<9q{Ngi9G&8JHV;84MabnHn1z z4%^ijd{bR#v1h%-J!=lRgLY?T8}okLZoli|({FCA_N7be8rHr$%VMN=HFA=cMbMRn zC#GF^s&``g?Y7s2FD_nqzwNN?+4yt1TucQw(@sUL_g!54lA|r8!X+Z;zQ&uzM|v+F z&o`1h=KCZ@L4UsNq_D8C{8sIr@0@cq%a$G}O=_}dVrFDuTx?=sWWW#fqpUC^<9`-b z17=1>1_M5j06$28g_()H0ir;ag~Nc2jU`l8l>ymPtRPP{GN_Aaz52>OKk59oEoZg3 zq@HZ<^)I<0bL6#nYWeejQ@h#c^p;mw@E?5>Cslpbrt*V`)$?Y{8x0n@vmzFUrM{To zFJxR&oL6thbo|2o=NTc=o;y{-xt2b2DamFlm$V95|Hu5?^m|*ca@{-|@XWhV{vQ9b UIiH%`mZWYr@pjq~Y10=50Qcd$Z2$lO literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csLeafBadEKUinInt.cer b/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csLeafBadEKUinInt.cer new file mode 100644 index 0000000000000000000000000000000000000000..d63466e18ad4f0acd1702e7c346f735728c7ded2 GIT binary patch literal 579 zcmXqLVzM`AVqCF+nTe5!iBZgen~hVe&7igSKSszPvP zdY*!dt5c}Ef@fYyYEf=#N@ik7s)CcFi-N0nsG+!lC`dUM51(T}K~AcIbAE0?DNvn( zoH(z6sezH9nW2f1v8hRvIIkgyYXapOxEtyiXhCdJMz_f)H8BllgF{*_4^3ZsZ|kRzIkjR5KhFpmU)u06N96UVtk^S~br#-w$nkua`j^*#vo5_l%f!sc zz_{4Pz{-Fh=v7%^M#ldvtOm@Cj0^^RAOU`m01Gn{dxL>Eh_4Fb^TMMfIfaE0*>kKQ z&oweg&(lzFaR}0Ici_If^IOP|aKmpGZgVG3w7-;e{!pd%tLmriGi<`O(#i_My%GwJ zm4&_WF3`+Zy13W$$=a39g5pn_J{Q^_`Sok|onODcUKGi$=kY(3y5XqG;{?$vLG}VR mRu#KfXTIjY)V7cL>Gtm9bLEUBS;ZbT%a*g literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csLeafBadPLCinInt.cer b/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csLeafBadPLCinInt.cer new file mode 100644 index 0000000000000000000000000000000000000000..5237e720af7ee9f9f2e5586807c7460ccb2d1298 GIT binary patch literal 579 zcmXqLVzM`AVqCF+nTe5!iBZIWn~hVe&7igSKSszPvP zdY*!dt5c}Ef@fYyYEf=#N@ik7s)CcFi$Z{pv!S?wC`dUM51(T}K~AcIbAE0?DNvn( zoH(z6sezH9nW2f1v4LfjIIkgyYXapOxEtyiXhCdJMz_f)H8BllgFi4+ne_{W=Flb zd_<;2OmXFc-&dMXxA*3iJzv=0-pX}w=C`;oYp&oYo|FAuHe7W)T2*;bdj7xthYwzN zkGM7W+LjCc^EQiY`{dSkN^ua6MKV!IEb$b;`73zBsqnJ5!rLB zAkQ^2GtKd{XXA5C4A!3ga;Rl79DMoKKay|#mLCw^w(aqkNnU3g#EtW z;pN;=d+6^XPszsAVy?6ARO}O3GVg2E?Tg*B`Mg!{d%K#f9yYtui9hCx{Sch=JDa&+ oy+FO~wjF21dH>zWxNl5>7aszPvP zdY*!dt5c}Ef@fYyYEf=#N@ik7s)C=tf|IkMxPd50F&7V?V?jYqs)BQVZb2zfm4Tc% zuYsw7k)fHPiHU`wWt2FtA&6@N`_Fw$0s#04Pw4RW*!ig;I^i5z5y@7 z`HZX#%#FPa292Fejg1VifBo9W&t9QBX;W?H!+-Z`W7@ADV7a`%H$n7#>T}L#i>B7g z%<#6Z6E0_BJYKu%Z_-6!YKr7WtoFUGi={4);P>4R(oX2%i|yGrdW6FJ@6y$ zT}H#2h~gbn#UsPF@F-SzTYG(N3*VN!HJIsq?Us27sMA{|Dfmb^3spd8@?{9 lV><0C%>Ik*N&XR6q4@2qxpB&Bm$K=F#?@mywaxz|2tEK$49)l!ci`$T>eHRUtSt zJx{^K)hX0n!P(JJ+&~m0$;HFxSWu9Ys^FZTTToh(T4W$6&TC+5U}R`!XkuhwXb>gN zYY5_+K)D9?hAIY15Obx`&Gku5OjGdlS8(+X#ce_3d;?yDLm62am>YW;3>rI`8XFmw z?H2cbsuA{aRqR=#3l~3T3j8h5uz0)Pzo|>htkmzuq*(@+@9cV|#pNTvvb8L}Li^54 zfB)|_%ezkU&Q&Sf=wZ_r=ea!b`qBmdFZW%^c#-gDvsb(U?4i!I0*cc_XNY8U>AFuDp|L+{$GDR{mGcqtPRyI&H;0Jn9R+y3TKMSh? zGb1B|0Ut<3nm9~v3b4{F$LRE$U$oAUe^s}AP|vt9FQ773a$h`b1h z{py`#azi+r^+&7CR5_lzQY-K1$$gTaaoX_Zp|!u??!IQVuF}2t;IfZReA2hFT9JJ6?PZ`ImVidG~|qa=w$|Sjtl-JjunTe5!iBZ&mn~hVe&7vU7e)szPvP zdY*!dt5c}Ef@fYyYEf=#N@ik7s)C=tf~$9^p}2u4NHrG^pJPEmPO5@)er`c2P?>?8 zIIn@Jfsvt^p^1^Pv3Zm@uOWzQ0_7UG8EPA7LM&23x5y_oF%4>gLS`NimEg9galQdB z!UK$~49tza3DLs+&o6mH55|xdBxxry56w z7-f4N4Dt(Ti>wWJ`83Pjv|90Ihr3DW=I{U9ZyWOSPS_(icfGAfO-x=WrdID1^) zMLD+KJSzM!XI$_sUk;s3KRjCtehY7&tYXfWztrNNcd6f_kfqPF9FB(^b literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csLeafNoPLCinInt.cer b/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csLeafNoPLCinInt.cer new file mode 100644 index 0000000000000000000000000000000000000000..182640fc8b96219015ab5be1710c46f72acec149 GIT binary patch literal 577 zcmXqLVzM=8VqCU>nTe5!iBZ^qn~hVe&7vU7e)szPvP zdY*!dt5c}Ef@fYyYEf=#N@ik7s)C=tLV%C6p}2u4NHrG^pJPEmPO5@)er`c2P?>?8 zIIn@Jfsvt^p^1@^sX>%DuOWzQ0_7UG8EPA7LM&23x5y_oF%4>gLS`NimEg9galQdB z!UK$~49tza3q5-W z?iOG;KGDQC(JoB?3(pE){h3=k_J3M`^WcOWwusm1^;hqCGw#kg_0*j~bMlp9CT2zk z#>F-URtEe)pUMg|GX7^_HDG3BWH8_Z3GjmiSeTjE8w|ujd{q#i7ak$WDJ+c0o?``h zu92ZC#QKZR>Q5pZyVLUgS7twc`Dlr<;JXc5Ds&Z;7ueZus$J^%O zIWxXzCVsAOy`E}z>~`LvQ)^nx@}?at+0MLu-FNe^2ls?$?^C~jA!_{;|Bf$b7v6st nQhrGDBj*W`$6M#dS#K&^!n(C2GAJcrr)R)VN#k3W6RrUO@HNe` literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csLeafShortPath.cer b/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csLeafShortPath.cer new file mode 100644 index 0000000000000000000000000000000000000000..90f950759c59c47dc80a962977256a2fb7648961 GIT binary patch literal 540 zcmXqLVv;auVr*Q%%*4pV#K>U4&Bm$K=F#?@mywaxz`{`0K$?v?l!ci`#5q4DRUtSt zJx{^K)hX0nAt*n;#8BKo6eP{X!{=B~kdvz5oS$1zT9R61AScdiU}j)yXliI~Y+z&> zCC+OI;u=A@2F`{W25JzK<&jJd1(}?anwX|goRMEtqEL`nl7ZWj#`y-k2R*+8`8G>uRf2q^!4yoqb{C?fyoVEF( z?w_7nU)ZZZFAuRL_{ME%EyiCLhqd|sZ7MBWrmDg9&A9GC PNXdT{miU{N7q~+Jlp4KT literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csRoot.cer b/SecurityTests/clxutils/certcrl/testSubjects/AppleCodeSigning/csRoot.cer new file mode 100644 index 0000000000000000000000000000000000000000..34503798030d443b034ed2588eaaf5b1fc5d6812 GIT binary patch literal 523 zcmXqLVq!OFVk}s|%*4pV#K>mA&Bm$K=F#?@mywaxz`{`0K$?v?l!ci`#5q4DRUtSt zJx{^K)hX0nAt*n;#8BKo6eP{X!{=B~kdvz5oS$1zT9R61AScdiU}|7wXl7_)Xl!T^ zCC+OI;+jCY6qwvN-+&k4Mn+Z!=EhzIgT_v##zuz6KJ%kmy7hkTv%TcRs4}N4I;NB5 z{F&MH*+2cH_h+p6TAc7dM?xo{t!S10uCLoo%G9S!^@%<%9@SPAQhHZ>X>z5iw@=p0 ztGP?-yf+s`l<*3$`1oHJwa_+i4tgiBTIXEYlQnxPl+~{k9@I$Zo$)9x-TaFA{}grK ztiGQAhcXg2GBGnUFfLX$P&D8N28*mPBjbM-Rs&`rWxxj#;0Fn?0E3zh*$=EBKQuC= z?b>g6*6ezbtbx}n?M9~X;G#cg9Ze_yj=x-a=}&G-+VtkfimO*yKF_+YG_B~kn0-Jy z$Fey~qwgP>HZ$S137VC12Y2)Lo)*d zLlZ-jC~;mO)56dg$~AB`lroTj*dXYXm;y8iVv9mfYGNAk)-=vH;6*r`k(GhDv6sQ1 zv6HE>kzvE38$tow^m+RkU-}mX?67-fHh+$D>5Z6B<%_oL+{nbt$iTQ*(?H#TALvn8 zVMfOPEUX61jEoEhA|L@(7G8L$C#SG5BKw3Df# literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/CodePkgSigning/CodePkgSigning.scr b/SecurityTests/clxutils/certcrl/testSubjects/CodePkgSigning/CodePkgSigning.scr new file mode 100644 index 00000000..5f3565c6 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/CodePkgSigning/CodePkgSigning.scr @@ -0,0 +1,54 @@ +# +# Test Code Signing and Package Signing policies. +# This used to be called the Code Signing POlicy; it was renamed on 8/15/06. +# +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +end + +### policy = CSSMOID_APPLE_TP_CODE_SIGNING ### + +test = "Apple Code Signing success" +cert = CodeSignLeaf.cer +root = CodeSignRoot.cer +policy = codeSign +end + +test = "Apple Code Signing, no EKU, expect fail" +cert = NoEKULeaf.cer +root = CodeSignRoot.cer +policy = codeSign +error = CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE +end + +test = "Apple Code Signing, wrong EKU, expect fail" +cert = BadCodeSignLeaf.cer +root = CodeSignRoot.cer +policy = codeSign +error = CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE +end + +### policy = CSSMOID_APPLE_TP_PACKAGE_SIGNING ### + +test = "Package Signing success" +cert = CodeSignLeaf.cer +root = CodeSignRoot.cer +policy = pkgSign +end + +test = "Package Signing, no EKU, expect fail" +cert = NoEKULeaf.cer +root = CodeSignRoot.cer +policy = pkgSign +error = CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE +end + +test = "Package Signing, wrong EKU, expect fail" +cert = BadCodeSignLeaf.cer +root = CodeSignRoot.cer +policy = pkgSign +error = CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/CodePkgSigning/CodeSignLeaf.cer b/SecurityTests/clxutils/certcrl/testSubjects/CodePkgSigning/CodeSignLeaf.cer new file mode 100644 index 0000000000000000000000000000000000000000..9636102ccc962f85e5152fc33fc86ae169380360 GIT binary patch literal 545 zcmXqLVv;pzVr*N$%*4pV#K>sC&Bm$K=F#?@mywaxz`;<|K$wj=l!cjx$2mVGH8?Xp zFDO61#8BKo6eP^W!{=B~kdvz5oS$1zT9R61$Y;Or0WZSQjI0dIjlB#8jh#%5 zjSR2q?_T?@ojLh8&{WVLktt&H!ISJ|dp#%%0!*gkJ< z;+YH2_gXE|^;jm!yl#u{&+FxLe=f+3`S$R-U3tM|K29cPMh3>k8U|_x{6J623NteP zXJIv9W@KalhpVhA3y%R88;3RMTni`=v5mgHY>^iFq5*5r-if4^Rs{<~!T(T{?>7sNP7{&}R- zB17Gt8G;(`=7?J)Jh{-*x768*uhuiUDeLZCo%4!3TlYqJYTuLRTDI!`=jJ0$(S5%Y RYRi0Ihab<1OpsbG008H*y&3=j literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/CodePkgSigning/CodeSignRoot.cer b/SecurityTests/clxutils/certcrl/testSubjects/CodePkgSigning/CodeSignRoot.cer new file mode 100644 index 0000000000000000000000000000000000000000..a4501cd402da99766ca9f7025be5649570d112be GIT binary patch literal 523 zcmXqLVq!OFVk}s|%*4pV#K>U4&Bm$K=F#?@mywaxz`;<|K$wj=l!cjx$2mVGH8?Xp zFDO61#8BKo6eP^W!{=B~kdvz5oS$1zT9R61$Y;OsDH1u`uRjiFpB*w8rNfEVFrMpg#q#$E=4#!jZjMuvTvr&k^C{jB$b?f>@L zs-VQ_cOQCPRsSS==&!}p4CfQw`_715@La+r{#quevqcIWoUuifdO6E0K1xlV4voHtkU;}~|CPkdp^x9#vBmXHHW z7(&>xbevZ1w%w%XqPO&z$Vnzk!Ulo{{J>C=6=r1o&%$cJ45X0V%nEXIBg3St zll>pGw#_-T%VYHiKdqnceAedb5>p=-zp_f$#@9PFVBV}R@_WC|de$&mM1}99y8W6m zEypb%GA&G&Bm$K=F#?@mywaxz`;<|K$wj=l!cjx$2mVGH8?Xp zFDO61#8BKo6eP^W!{=B~kdvz5oS$1zT9R61$Y;O^;Y3e?YjJBSi zYOrv2gxuaX&ip+BlU`3})czoHBGTZ?*Ename +n +s +n +p crtn +p name->name +q diff --git a/SecurityTests/clxutils/certcrl/testSubjects/GarthCRL/CNTMTT68S21G224G.cer b/SecurityTests/clxutils/certcrl/testSubjects/GarthCRL/CNTMTT68S21G224G.cer new file mode 100644 index 0000000000000000000000000000000000000000..55fd93c7f45f25ce9f30e9c94bec311b289f471e GIT binary patch literal 1602 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/GarthCRL/InfoCamereRoot.cer b/SecurityTests/clxutils/certcrl/testSubjects/GarthCRL/InfoCamereRoot.cer new file mode 100644 index 0000000000000000000000000000000000000000..1acaa818b59ccc74541e89b2ddf39de04dbbca64 GIT binary patch literal 1364 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

h$@0!Ql%wfOf8ye`JY*6~UaLMD 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 IQ8!)i|2=L{WdHyG literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/ECCCA.cer b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/ECCCA.cer new file mode 100644 index 0000000000000000000000000000000000000000..a75af24207a7470db720bbbc2e08c792e3d8b4e1 GIT binary patch literal 386 zcmXqLVyrW0VpLne%*4pV#K>sC$;PhL=5fxJh0(ykkQ>Nl4rO5zW(o~96foceakzxp zgHlrzJQ7O``3-nMBFw^UuFlR1&W;8O;=BfC21W+PMn;B)rsh!+{6+?*W(KBk0W!>t zG!TY5iHVVo1MD_tMs{W=1{T%(fAqyyyj?5pxohRpdEMeFma6~nI?3-_T{+YLM6O1* z0GnLsS0UYLvem3J%WfUNvb|oSQ$2sF0%uOqk7KN71s59_=otvIaVE5RFt+`0Vq|1t zVP;}rH{bz!N>-SK)qt6i@xK8#h{q3-VroGO9cFh10~aO*15WAuhnr^hUToR;X!a7; z4JVCdKQ(oQ^E`aA?8Ig+PhBPjx7J0n2l*FGY5mIiJviz{qt@*D7iM3{xyT%Da2oE;71#CZ+O42%qnjf@PRIUofJvj>BLE0ZF_gwUpzBEfb}R?SxL{}v{NSd)S~srwGMS-s Oxyn>nnwoCA?*jmGacxxq literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/ECCp224.cer b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/ECCp224.cer new file mode 100644 index 0000000000000000000000000000000000000000..4d47ce45b9c18c1dd87cf3356545bd99065e61a3 GIT binary patch literal 388 zcmXqLVr(#IVpLne%*4pV#LCcEo4M71lZ{=g&EuRc3!{O7AvciA9LmBb%oG}IC}6+` z;&2JG2c@PccqEn>@*D7iM3{xyT%Da2oE;71#CZ+O42%qnjf@N}jZCA!TvIsLAcT;K zf(HB`6S;*sKqeL#8JQR=7|1~^5zopmN=eMqD^5#Ftkf$?P02_s(M!(HHSjYKfI6Cq zk&RWmk%d8#*@}T>qvQPKS--U+h;{?3YN zU#fCXo^kHE`=ygbLRe(xGrK4(7Bvty5M<*_X!Brf`{BgM$il+R#O8n$GR&R~25wA> z46n{i-~9QL^2gN^d`pNl4rO5zW(o~96foce zakzxpgHlrzJQ7O``3-nMBFw^UuFlR1&W;9h;=BfC21W+PMn*;khL%xat|^>r5JJdA zK?8n}iQK{*AQKCWOw9}x4CEk|h-c*&r6lI*6{jU7R_Ya{req|R=q2ap8blfhLmkb; z$i@M7Ju@Ravl9agQ`}K|-Ob@b|8Ci8JygHCYi8I6S$Es8*R|`4_SC+zKOKFee{s?V zo~t6Eu%_R$)+sla eIj5UDWzMhJ9IO{)eOG>9Z=SkuJKwy0$4UV{A#g+h literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/ECCp384.cer b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/ECCp384.cer new file mode 100644 index 0000000000000000000000000000000000000000..3049d0a88114cf612fd0521989561ead39968ba6 GIT binary patch literal 427 zcmXqLVq9*}#OSwxnTe5!iIt(THY?qLlZ{=g&EuRc3!{O7AvciA9LmBb%oG}IC}6+` z;&2JG2c@PccqEn>@*D7iM3{xyT%Da2oE;71#CZ+O42%qnjf{*8Of93pTvIsLAcT;K zf(HB`6S;*sKqeL#TbLLs7|1~^5zopmN=eMqD^5#Ftkf$?P02_s(M!(HH7GL>fI6Cq zk&RWmk%d8tIf;SAIfy$%Lwzgj8^&tmul;tJ-+xW+b~_|!q|v z+wJ{$cjc2qEA+0+m>7RUQCrqxOYV=CtTAp<+8!(W_a49bwDgKp^~7GYcORDRsJZuU z_q;Dn$!nJ%mR>AsAZ#GW#+lIO!Pxf0iII_og_()X0VxETJs1pJnG_l394HeN-{G>; zgQ;W#lgU0`w&$$OIv2jZc8zskQaSfs8j}JOYs=L;^ShS5=8WLm%2XKp{l43}EYS^T NYCd>}{Z^Rj2mq-JgSr3! literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/ECCp521.cer b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/ECCp521.cer new file mode 100644 index 0000000000000000000000000000000000000000..77e2e52ab759ac13e4326fea7a34444967628cfc GIT binary patch literal 465 zcmXqLVmxcm#8|q3nTe5!iIt(THfy^9CmXv~o5wj@7DfXDLvA3KIh2J>m?<>aP{4o> z#NiTV4@yl@@JK8%; zg$x8hCUOgNf=nzh1(~8?AP2EUJS)E_B{5I0I4vo$Qm-gAB_pv!FF8Ngpm8=(8^qa6 zjBKphjVuhx%#CdfER2O)BwjWr)G7DhcUUyF%znad%T<{!((y}Xc)fWmcyOIaOMKzB z^(9RCsfL{T)26Y#S>93TwI`v>^ZT;Us4vg*|14lEXq)`#__r-H%2!QX{c1yjUE`6R z?&&+u^m-)CvwnQQq4w*RO!>vHSu&<_IUQK@^1R-gWe$#61`3_wK5vc|2F#ahUo2`M zY#_+Snb79J*!IJTk&%UknTgE-DWI9%84O&Q6mmWIGjHwi2z36+bYse||0k8-|G&2C z$b{Pumb}_>KIH9RCWX)~2X&Hy>I&R`rN7^DWy*WaJB4ns9*I-5^HwCu{uGu60JLSC AnE(I) literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P256_Specified_SHA1.cer b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P256_Specified_SHA1.cer new file mode 100755 index 0000000000000000000000000000000000000000..83e2f29e4d06ecd7f9a397ab55ea55b5831a6310 GIT binary patch literal 574 zcmXqLVzM%5V!XD1nTe5!N#M!dMU_f!>*snE-rAF4P>^gO!p5%E=5fxJh1r0Uja8eE znMsP3!9dnf+CY+xIh2K2PKY6h!5;`i7~&ZM7>pQ98O#ji#CZ)24NQO-45Gw&4Gj#9 zjA2{@OG9%5Q;2pw23LkWh7^QmAS;-mfFYG3nIV%Q4Tw|0vcU`<42}$j29XBBP!};V zvT=Z&#>~jh?8Ly5b2jGq*+-SeSIrHsr_OrqDiD62EpW;2Q%p%anyhyHmV&My0#WHRX5OIFn%{!^>O?LnYj$E= r_p6gk3ew@TYuO7+-sml>|7Thy~B literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P256_Specified_SHA256.cer b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P256_Specified_SHA256.cer new file mode 100755 index 0000000000000000000000000000000000000000..a2c474e8210a8965b22b90ed81c0a6306aa3c693 GIT binary patch literal 589 zcmXqLV)8U-VtlZGnTe5!Nnnzcd12)0yv-hS4%(eo&|Y95!N#uD=5fxJh1r0YjWeOm zgE5tvg^7`s!9dnf+CY+xIh2K2PKY6h!5;`i7~&ZM7>pQ98O#ji#CZ)24NQO-45Gw& z4Gj#9jA2{@TSIFDONe$O23LkWh7^QmAS;-mfFYG3nIV%Q4Tw|0vcU`<431FaBMpS1 zE@NV3;{ZF6nUS5@iGd~OY|Qbqk1CC?nj2hCo%PyPApAUA;F8~`n38rjNBr8ng|XFl zUw^Cf0{Mv!{qsJYUG_K0ZsvP`iFx*1d_sJ2QPPVWFB>#oFlao>#;?uB$imoUF5GlK zy=`$YBTM5>gT`$vLe8m0C7EfN$%!SY!HKyAIjIaRQm%O^@c~ArX7RxVsmVae)Rg#O z4@aN?0}~?%v52@bI5W5a{pE<{PnHZ<=U^iR1_lO7U9G=T*ke_2jl4qp$@NnLO7E=F ze#5b~LQU w60dkwD!(}ZmF(Hvdp~B{lMM>H)zAI;4Bf`{h;0Oz%~`v3p{ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P256_combined_SHA256.cer b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P256_combined_SHA256.cer new file mode 100755 index 0000000000000000000000000000000000000000..ac61c0195e1fb57ccca571bab81c9b5d62c442d7 GIT binary patch literal 557 zcmXqLV$w8dVm!ZqnTe5!Ng(Xs-9z>_YZiO(&2uYVXJ~1_#m1r4=5fxJg_+4f)==6& zl8rf(g;`FBA&9{r2tyd+83GuL7)%+=4CKUl4GaxTfEWy-#CZ)342_IoTmx&Mapn;1 z1`MtYc?>BC%|MnjLq0<;LlQ$KP$m^D7tG+n;0QH5(mF8O_mDQRbO#IMa;7+Zb!^|v}Nke}$#KkviYWq*_G zX1@2Am}k$$C&U*QCB3-ul0oBngT^y#{Mu}cER0R&!cF(n+ZG2ivNY~6Xxz#o6(`kA7Er^7N4A-o0OTCni3!E;Rxh2FfoDL{m|F5@& gpI_bNn^5BTx9WTQFN^<7KR$lbvqx z2sx(~m1L%6CMTAp1}Ekg#r2{SQT6&uh4#S{gi;xJFB$caBQuR6zfnq z(_MQ${}yt*F?%o=xH2g+w66?!GB+@+U-KaUUV&U^X90oF9CI4Pq@w1_O)Hj}7Q&<; mtMqWTYM$a2u9VM5ZkI2K7mZrGq%mV-=)W7!yie@(nF;`o*RhoV literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P384_Specified_SHA256.cer b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P384_Specified_SHA256.cer new file mode 100755 index 0000000000000000000000000000000000000000..8c3692dce0c3a229c303db0971f6f6fcc1ce12a9 GIT binary patch literal 668 zcmXqLVwz#l#AL95nTe5!N#MF?YW8jm#*NN*5A8I+p&e!*!N#uD=5fxJh1r0YjWeOm zgE5tvg^7`s!9dnf+CY+xIh2K2PKY6h!5;`i7~&ZM7>pQ98O#ji#CZ)24NQO-45Gw& z4Gj#9jA2{@TSIFDONe$O23LkWh7_=7V+IQb6Cf*?p@1QkA(&9t@69 zoZ+gXyLhn-1;U>`^`A^^&p|SzjWlTT_QN2E^g-LvHL25EkGBqVW*u&At)Qo|N5rkMo zTp64hT!7woL<$C$#u={8!6pU_3=FjPSOg;AW0Uku8O+^Ihk?um7}uZ}`*aPgMB< D*o5BN literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P384_Specified_SHA384.cer b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P384_Specified_SHA384.cer new file mode 100755 index 0000000000000000000000000000000000000000..c87db9fc44894a58aeb9918bd0f5c033e585bcc5 GIT binary patch literal 669 zcmXqLVw!2t#AL95nTe5!N#K)KyLN4`@M5ozrZu;f^A{UPu(4~kd7QIlVK(4p<4kDt zU`%CZVPaxsFpxErHjrdv4rO7M6JiKr@CU*WhIobm1|tSj1~UUWab5#M0}~(ygD7!c zLjyx2V;I-K*3jC(5~AIR!IdG8AqA}2n8AX<1jq_zC}2osNM^`nNCVO3XJn?^K^wNTbu9uV^EdvVZ?b=J6C4=zYe21=%;#0Psg0tFbD7(s|d z#FfFB!3F4TN2Fk2X`JEe9Bg91z`#Ijk3}%@u^6luepDE;Wl3dGXBE-(w}B?~8{vo;;CkmuKIIJ7F+;G8niqDKhMsC%xUryyJr7w7oq?t^}U= z@%oX2v}lIehN20~)is|l1C<<$@VJ7#tZ44ay7zppIZ-WMkECWMNQZ zPGVpQu*|)~)VaiEf>oZ+gXyLhn-1;U>`^`A^^&p|SzjWlTT_QN2ah nhCkQ7+s*5XoE)>tagoZb`FqUQxz^a!{6GHBJJDnIi)R)9;?La{ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P384_combined_SHA256.cer b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P384_combined_SHA256.cer new file mode 100755 index 0000000000000000000000000000000000000000..bd0f2c7873feb94c67485574e97080bedd61a7ff GIT binary patch literal 636 zcmXqLVyZA`Vv=9L%*4pVB(UPZt4e{~#I??87w)Xl3uH6kV&l+i^EhYA!pvkKYbb3X z$;KSY!Yn7m5X9gQgdq&^3;_&A45kcb26E!O28ISEKnw;^;=G0ihDOFPu7S0orGYs_ zy8(kMLmop4ShF#M1%nBY<;;-Jkjs$7kO`DY1v~ROV^^Dg`=CWAKySd3H_Hlj^hZ4ul#p|4R zY)#dT-`4)pk-K(@;Czl#vn^ZhPFtgKV1ayK%SI`;_s^4yR$XGPJZQs~wys5>Wd6qg z^G)_IZenCHXkuhAX#C5@ug%8D!q{Xk+;l&^ZE-LoOXEv}#%C--&Z$KunQ58Hi6yDQ ziMa(isSGTVu6Zf(0mc?4@yYqQNtt=6De=J`jz*?t3`~q5#3JGf^sfs;FwlRX0EC1A zOXCbz=U@{91_lON`zwNxkHuiU@T0cS{vIn4 zeP2AZ@#KkQyFB|w^!IdG8AqA}26sX-0$O>jCU`S<1X2@hn1L9P$Y%qfdgCm2XLE~%# z0jQIh7=aFIWMNQdZfs*+mFagemb+QV(Clm|AxDt`zY^R zGC#U1G~|b&Z_3=VmorpO?aDK1FI&NJwzP}6Hd*K5>5Gi4B0uz=YAA0jKOcRdY17@N$6o9?H#Ee>X6X=0QIN=UN^Ij0ttWTs^%CzhlJC*~I9 zq%yEbxaOtA2bdZe#s?RqCIcl?Q{sa?91R(m7(s|d#FfFB!37vHjz}TJ(s<6*IoQmJ zfq`K#_?{t4?6g-v-7@7{8?Ka<>7|KR7Pl%*T$lEG!83;W(esimW1oj}ua>=+X?pp0 zT}?PgdY)7BitJS@Bx{bIXYB}|vt|SK)W+<=VBpH6z|C->-6L;eX3pM+A%2&d literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P521_combined_SHA1.cer b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/End_P521_combined_SHA1.cer new file mode 100755 index 0000000000000000000000000000000000000000..daba145ab3bd7be454246031174969685a1d02c7 GIT binary patch literal 725 zcmXqLV!CM1#8ke3nTe5!N#Ii9McXEa$17db?T<;!@^dlZWMkKA^EhYA!e}6CC~Y9g z#vIDREGNVe#NZEvAq?>h0SrbArVM5Va^k!Oh6W};3 z*Jfj6VQexNZn~e|wm6uPrHN4vC?UlnTLR z>{TlyYmT00?FgTbqU48vmv2In-vr#m1r4=5fxJg_*@b)==6& zl8rf(g;`FBA&9{r2tyd+83GuL7)%+=4CKUl4GaxTfEWy-#CZ)342_IoTmx%EO9OL= zb^``ihCGH8gk~VinIWGcmm!HE6DX4kmJ4R^U~mK)ZOC9`&^X&bfQ=pO6edPCR_#U> z24&{PHU<{P9@qb_<}K-y?h`i*dGutYbzSRD2xcj+}^3EmmqpLzgei-_u z%q@F4L*>-2Jfrrq6&zly7agQdXvyCSF@}}n+<4fa@qj_& zUN(MhHbxf4CUfDY`{`|qgBe*GR~j@fV-a#rEh@=O%S=uzNexcSEyzh_VBre#_Ya8= zFfuh`U}6Lz77T%CiB6c`v7D0OAx^xD?_b$(Y1I6l4Dy2mnd zv-0%#E2oo7c6Q`m`?5n}1@4Gpc4shfVN!58vbXA9zT>irroTqpLr*sJyaNc|CDoaoPGmGZWq@{dL}d>vR2+zMQ3Q`%@Tg0e!W%tN;K2 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/msEcc.scr b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/msEcc.scr new file mode 100644 index 00000000..abdf4ca9 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/msEcc.scr @@ -0,0 +1,83 @@ +# +# Verification of ECC certs created by Microsoft +# +globals +allowUnverified = true +end + +# +# some with combined digest OID, some with specified +# +test = "RootP256.cer root" +cert = RootP256.cer +root = RootP256.cer +verifyTime = 20060303001200 +end + +test = "End_P256_Specified_SHA1.cer" +cert = End_P256_Specified_SHA1.cer +root = RootP256.cer +verifyTime = 20060303001200 +end + +test = "End_P256_Specified_SHA256.cer" +cert = End_P256_Specified_SHA256.cer +root = RootP256.cer +verifyTime = 20060303001200 +end + +test = "End_P256_combined_SHA256.cer" +cert = End_P256_combined_SHA256.cer +root = RootP256.cer +verifyTime = 20060303001200 +end + +test = "End_P256_combined_SHA512.cer" +cert = End_P256_combined_SHA512.cer +root = RootP256.cer +verifyTime = 20060303001200 +end + +test = "End_P384_Specified_SHA256.cer" +cert = End_P384_Specified_SHA256.cer +root = RootP256.cer +verifyTime = 20060303001200 +end + +test = "End_P384_combined_SHA256.cer" +cert = End_P384_combined_SHA256.cer +root = RootP256.cer +verifyTime = 20060303001200 +end + +test = "End_P384_Specified_SHA384.cer" +cert = End_P384_Specified_SHA384.cer +root = RootP256.cer +verifyTime = 20060303001200 +end + +test = "End_P384_combined_SHA1.cer" +cert = End_P384_combined_SHA1.cer +root = RootP256.cer +verifyTime = 20060303001200 +end + +test = "End_P521_Specified_SHA1.cer" +cert = End_P521_Specified_SHA1.cer +root = RootP256.cer +verifyTime = 20060303001200 +end + +test = "End_P521_combined_SHA1.cer" +cert = End_P521_combined_SHA1.cer +root = RootP256.cer +verifyTime = 20060303001200 +end + +test = "End_P521_combined_SHA512.cer" +cert = End_P521_combined_SHA512.cer +root = RootP256.cer +verifyTime = 20060303001200 +end + + diff --git a/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/nssecc.scr b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/nssecc.scr new file mode 100644 index 00000000..ae606f71 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/nssecc.scr @@ -0,0 +1,41 @@ +# +# Verification of ECC certs created by NSS +# +globals +allowUnverified = true +end + +### +### certs created by NSS +### obtained from http://dev.experimentalstuff.com:8082/NSS_ECC_Certs.zip +### +test = "ECCCA.cer root" +cert = ECCCA.cer +root = ECCCA.cer +verifyTime = 20060303001200 +end + +test = "ECCp192.cer" +cert = ECCp192.cer +root = ECCCA.cer +verifyTime = 20060303001200 +end + +test = "ECCp256.cer" +cert = ECCp256.cer +root = ECCCA.cer +verifyTime = 20060303001200 +end + +test = "ECCp384.cer" +cert = ECCp384.cer +root = ECCCA.cer +verifyTime = 20060303001200 +end + +test = "ECCp521.cer" +cert = ECCp521.cer +root = ECCCA.cer +verifyTime = 20060303001200 +end + diff --git a/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/opensslEcc.scr b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/opensslEcc.scr new file mode 100644 index 00000000..03ebf715 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/opensslEcc.scr @@ -0,0 +1,46 @@ +# +# Verification of ECC certs created by OpenSSL +# +globals +allowUnverified = true +end + +# +# obtained from http://dev.experimentalstuff.com:8082/certs/ +# +test = "secp256r1ca.cer root" +cert = secp256r1ca.cer +root = secp256r1ca.cer +verifyTime = 20060303001200 +end + +test = "secp256r1server-secp256r1ca.cer" +cert = secp256r1server-secp256r1ca.cer +root = secp256r1ca.cer +verifyTime = 20060303001200 +end + +test = "secp384r1ca.cer root" +cert = secp384r1ca.cer +root = secp384r1ca.cer +verifyTime = 20060303001200 +end + +test = "secp384r1server-secp384r1ca.cer" +cert = secp384r1server-secp384r1ca.cer +root = secp384r1ca.cer +verifyTime = 20060303001200 +end + +test = "secp521r1ca.cer root" +cert = secp521r1ca.cer +root = secp521r1ca.cer +verifyTime = 20060303001200 +end + +test = "secp521r1server-secp521r1ca.cer" +cert = secp521r1server-secp521r1ca.cer +root = secp521r1ca.cer +verifyTime = 20060303001200 +end + diff --git a/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/secp256r1ca.cer b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/secp256r1ca.cer new file mode 100644 index 0000000000000000000000000000000000000000..76b4842f8f4b793bb6213bf9114e020b65fb1bfc GIT binary patch literal 825 zcmXqLVm38sV!FG4nTe5!iId@ILwumv;}t9hoNVk`Z64=rSr`o(=NNJW`OKj#Y{E>T z!7vU750kT_p_qXPNQRw<*Ehd3uOu-uPa!NbwcJq6Km{bu#UmSBny28KnOu}#Tv=R_ znp>>klbDoWlvt8ql$ly=C}SW6Qpe3B9FkgGqTuYPpi!KfTwr8sR%EDYsAQl3l4a(R zOi3-%ORXqKEy~PI1zM9+TvD2rrk9+bYal1iYhY?93{?cXkcJyXaeO9 zcIQVL2t$LKiII&19Olf7?95IKEO!p@_kMkAH#m|lHut9d93k;tDm!YV#l$b~ ztkBmxBEy(b{@{3}$GorCHdklWuMyfS7_Mm5zUG0G!yjIs#Z8Q?22G5N2C~2~l;vX) zV-fNAev_+e!orIQFFPGiDmZQ0ap9eqLE}Y`yfRDUNrT2?4OrDIY+SUYasD6=$|j`b z%LDR~Fbk^zGb7`Fq{PhZ&S2oeq)=J(qWscs=2ACz{_h8lzMd}}!u)8*Y4Zd1!ArUI rZEsgHDP*m?|K9OgSb}W!@y>*lzL|_GUobA8UHZ0X>Vvfo`r_;Wr~3Fk literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/secp256r1server-secp256r1ca.cer b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/secp256r1server-secp256r1ca.cer new file mode 100644 index 0000000000000000000000000000000000000000..33971fa1e41fdbcce7923652ace2c2dfcffe2ea2 GIT binary patch literal 578 zcmXqLVzM)6VtmTP$*|zAKTq-2LskZyZ0uTX9_MUX7!4Zd7;*#o%%Lo7!c3vTFb)R~ zle43tn1KjLhMkAkH@`HmBr!8jAuKbs+)&Lx1tiYJBO6?rr{J5JT$Ep2SzMBuTdd%d zn3P|XSdw3qnObZpV;}`m$IT-gl3HA%;OwZNQJk7wU}S1mWT%FIm#T9Z>;Qks^gmzW~! zs$q`PdXCD%)qJL2NHNRo!C>IZq)@-lC?zU+lj2Err5A~+8B=iN_xxmL_v^!?G{T>wTMwiN&X literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/secp384r1ca.cer b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/secp384r1ca.cer new file mode 100644 index 0000000000000000000000000000000000000000..0c1ba66f280f9d2251e619449b736dfda33ef5f9 GIT binary patch literal 887 zcmXqLVlFmlV*0g!nTe5!iId^bN{8cL6}^}YIN8{>+C0wLvM?Gn&N1W$@|i7UP)qRoh_MI3%^WM8VlnL8CY|xxm=Mq{vXyP{}|6B+JYr znUY$jms(MfT9lca3bZDtxTG{KO)oh=*Fa93*TB@!$iU3V(8$u%Bubpu(7?dZ&;-gI z?9MMU5P$|X6C)d|b|VXe5_1v*%dzQ(JyVk=S2?EddukPIe(G=U2L1r&{Yg*C?i5dd zvTAG2U$zDDRXb}c@79W5a9&>c|9RGzyIMnCjV@Q;uhQIMca8y zepR&Y@GY!P`m+B>yyJd0%%J zoA{WYFf?eq2$EN3X*_Arc&q`dnuU#vmNd>EHxk8`#xj0TN!47q`P=1>+kVW!Yv7>9$0 z$=T6R%s>Pr!_LF&n_rq&l9-vN5SE!*Zm4FU0utxqkqs`*Q}E49F3K;iEG|jSEmrVJ zOv*1xEXgm*Of5E)F^~eOaCTJCC{9f-Ft#u$GSoCwGEe}?GV@5Lq?YNW zRurTbW#*;=t;s1aDNRe$OU}@T-D zDkz*hTbQ?acE;)BFJtc~w5N$W-?^A@_05#?qGEB8SD*IuIPs|%Ke2HAvH~gEnKKy- z(wGbxW|iIg=4JE#Xw}WE1Dj-;q*k2vdRL*XBFeDy?vIem21dCS9cPR_8y6THW>S_Z z(zgU^*|W5A`K{IVQ`%$2qAKF%&NC1^xOU!Wtv8pune&>rUC5HXwj*HX!HI&7i|6-V I%3t~t0OUZ?7XSbN literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/secp521r1ca.cer b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/secp521r1ca.cer new file mode 100644 index 0000000000000000000000000000000000000000..cfca4889cd02f8e84db1f8add18d4fa94f48a3d8 GIT binary patch literal 962 zcmXqLV%}%a#H_G@nTe5!iId@?b{PMP$txNRIN8{>+C0wLvM?Gn&N1W$@|i7UP)qRoh_MI3%^WM8VlnL8CY|xxm!Ou*gu;P{}|6B+JYr znUY$jms(MfT9lca3bZDtxTG{KO)oh=*Fa93*TB@!$iU3V(8$u%G)kP;(7?dZ&;-gI z?9OkTZ6E**YbHiER_#U>24&{PHU<_3A(@GUYvSf{r^;n*hi;+@Yl z8gfh9BJyI8*UGc9WL00_q{q<)f7=z=kN$S~GH2v?G z<>sG%;=pmUPtCIIQ;r0C=%)%ZewjSo`^JpDPES^9Ci?zcA?oV0E9%`NwaL-u2bolS z4L^x&Ia=rSbM{542hRV>EWRVtiWqZ3L4oq4LAD5-cKD=@9Ra`G~m#QY`KV2V| zTas%R<*lwd+Xghl#?rBvaq|M3kOwLP`M=H=1oC9?c|82(R;nDarOA0>aq7;%19sm3 gcC1fbC#}5eS7@HxuV2aL?AIPVwA%IKPqfBe0QV?3761SM literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/secp521r1server-secp521r1ca.cer b/SecurityTests/clxutils/certcrl/testSubjects/NSS_ECC/secp521r1server-secp521r1ca.cer new file mode 100644 index 0000000000000000000000000000000000000000..2ceefe0c716984d661f78b2081ae78053bc46c7b GIT binary patch literal 714 zcmXqLVmfBf#H7K*$*|zAKTq-2Lp}zaZ0uTX9_MUX7!4Zd7;*#o%%Lo7!c3vTFb)R~ zle43tn1KjLhMkAkH@`HmBr!8jAuKbs+)&Lx1tiYJBO6?rr{J5JT$Ep2SzMBuTdd%d zn3P|XSdw3qnObZpV;}`m$IT-gl3HA%;OwZNQJk7wU}|JoWT%FIm#T9Z>;Qks^gmzIZ#=ydG zvVWh(S@iZi;`Ud&yR zz-d>aPmc$&T9QdhmjHob7K#KL1PD#6QlN#*RRfP zdHeL?>ykRjqn$y3&^UM`j^TlU;(&OW|HEFAYeJva3Ks{#O48up|B literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/Certificate Path.pdf b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/Certificate Path.pdf new file mode 100755 index 0000000000000000000000000000000000000000..c1bfd04cb2a4fc4cc46bb6b2918d7bd396eab318 GIT binary patch literal 729713 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 QbModd{^F~D{N0=X4`&KY9RL6T literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/makeCertScr b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/makeCertScr new file mode 100755 index 00000000..d33f4e7d --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/makeCertScr @@ -0,0 +1,22 @@ +#! /bin/tcsh -f +# +# Generate a certcrl script based on files in current directory. +# +set dirName=$cwd:t +echo test = $dirName +echo "dir =" $dirName +foreach i (End*.crt) + echo cert = \"$i\" +end +foreach i (Intermediate*.crt) + echo cert = \"$i\" +end +foreach i (*.crl) + echo "crl =" \"$i\" +end +foreach i (*Anchor*.crt) + echo root = \"$i\" +end +echo end +echo "" + diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/runCertScr b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/runCertScr new file mode 100755 index 00000000..1f2f875d --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/runCertScr @@ -0,0 +1,11 @@ +#! /bin/tcsh -f +# +# run makeCertScr on test*. +# +foreach i (test*) + cd $i + makeCertScr + cd .. +end + + diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test1/End Certificate CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test1/End Certificate CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7e64d6de14e15ff446e6b7579cd0e13aeaf6a06 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iILHOmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HPUF%&T1gYeixQj1G6^U@7P4TM1= z%)&e&MWw|h3XXZn8Tmy9a^k#}76yg}hK5E!(jZEl*94hskU%Z_#SKIu_Va}nrxqFN zItS<(7y^+&<9uX4GqN%;H}*0ZG-En=&qMl=y$p-FYc<<-9enI@TiB|#Se%Zw+KSb$T%LE_ aS^9zF(~m_J>$YY#Tnj&^;=NrcehvVq6xFu? literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test1/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test1/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test10/End Certificate CP.03.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test10/End Certificate CP.03.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..de392400383e0f533b7dfca9e248f27fa8126953 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iBZIWmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uC<0eS|;dIm-Ya^k#}76yg}hK5E!(jZEl*T4XYYmh*W{VrJS7dH@v*v}VQ zoLYqBg2wsCer9B4U~cSXFlg*#YHVaUoVgTPxbykzVKhGLXFXny)>@z zU;Uo0qmQ`N7xMUVX!AXpa(eBSoprj0tgO#G=dbsiikznLjr^Fwgc6JKLAG zTY2%J&N~~8O@DM6-OD(VzCzN1`Tdv3zxy7>99p$sDojbqdG|KeZ%Mv+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zUFQHj17ke{BXM3!O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aTf1 zJju0c*DohD7c)0DGH_pfZ~FS`>(86-vnvR0c#zuSr7E8N;OP#ba~B`3NIqZ9{v!3} zm5P>r*?o08SAN*6)5^#EODfsTJ=^1_#+7qYf4?v#i@lgT*RXGz!R2*#5A0n1e0`hE y1jEVZLNkJQzRH_yH=I<2cJ_ccRCs&dN88(u;JmY<7xX956)him-+ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test10/Intermediate Certificate CP.03.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test10/Intermediate Certificate CP.03.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..2d691abcee2895447f470d89b440eaad4d5b530f GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6Qi&JFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%E5)Jr)K_@HB$oQXy)qojDfkRi8A0)s6j5s!MtjH>`@Eh@##aN!>RGRU9(o?qj~oWTSZ4-$KAJ1O z{T83qkH1Gswwyg~oaw~w=at;#YpeXq#VvYEy8mjqUy)MmJFGrCi(Qs^XrbGZZdAI- zpktLn-^E7b{5K{=e7DRsO&_l{S@dze!H;Cuxa;dwVx;#PWg8yvW_w#Io|>U#@%`PO e%1yT6#W^i;s#o})#|4?ooh)N53i4UVE(`#Bm(0`v literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test10/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test10/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test11/End Certificate CP.03.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test11/End Certificate CP.03.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..6e14527d24ab20c6a6d5db795a4c361e03fb1f43 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iBZgemyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uC<0eS|;Kx7~%&TDC5U}#`yXapn;qQrSk4GhfTT!RF1?03Opzqo-Y#D2ce z;?yD}7c|aC_A?_Z19M|9gF#~_Q)45;mJL^Yc271eK4&cSsO8eyiT}S(_L13>8>lu_ z;=ra$YZvK$ocaFxWbd2v8dOLCMKA%dzyGzfWJyAWc zDq+v9gF?KlIgej0Rh#(xRAKtcf(kjyZ9b=ii)U7_1uaRQan<|sKk4)r?0ZxhM6*oR zC##=jVrFDuTpVN&01i%Ben!UsEG*1StPjA^AgjQ_Z@_E7&BmF~=E0cC%xJ)9APDrN zEFTLO3x~LG#e|2CCVdBoyR0$`FoGI5T9o)sn_nuLfb3;pG&2MJTC$nvO!E0XLJw?r zq~E%B>;J|_nbT&SC^Gb|Tp8`u(DHvzJKIVt?d&ZZ`wuP6J<5A*p|YgPXJ*dOHEV6p zrRDCHUbA-9;>eqmcYJl&9nE6#)il+7e@OS0NCnA@=YlzSF0DEBO0iZYQFO|a$Xo3H Y_4TIqt2`D6ZjG1w(2}sV+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zUFQHj17jc(=e4vnFf=eUGy;+aQR2KN7D(I$$_9#HV`W8Hm_d#M86m680<^1vqeY4D zwE3l?31}{6Zfs=hQ9p*@jh44za^zRt8_a8RySX1IaJYQ#E{2;3narW%cw3YwQ zC9Se;-6gPk$)1wHmv>A9pUeL+dG70GEzBTxeN)Y!;77lIH>_AE@G#DH@4<&X2~G0q zrI!@9{NCVy%;M+tii~W(znga+GVMRBV?Oh;P)D0sZiy~eLsQSx#|sMiqT}y>_d$4=48z)T0&kEp8aw! z2@`m7Ot11(L)p9y3sZR=Qez(!o}W?85M8`-Iop>LI~0=6bA(hpE4jRNY1_ZVb|sDl dx$y_ST9waL6xVi2IHT%uyDouc|3B#q&H(mv(H{T+ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test11/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test11/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test12/End Certificate CP.03.04.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test12/End Certificate CP.03.04.crt new file mode 100644 index 0000000000000000000000000000000000000000..158c6ae019c76327e96cf4438d304e9e5bc86b14 GIT binary patch literal 652 zcmXqLV(KtxV*I#(nTe5!iBZCUmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uC<0eS|;dIly23gWz$76yg}hK5E!(jZEL-^jq!07<|gfgBgOU~z%CfhfcU ze4)juMM!RFoR92lMpg#q#$E=4#!jZjMuweAf49hbMlbRYcsu>@k~2xp*B?h_?=Iv& z*{PAl`soqJrWYGmtlXiy$?;x`?Y8|@_oJ-(%5O})@gZsP?;FBBN6tHbnSV}pSwa3H zzJ@EDF4r$VagHwRH)4367@#O4SUdNR?&_ru?k6vkK?VWf0F~uuWc<&xW`W2jGiF_sVa`ro(7u)T3olR0>h^Q|Z}URU#?xyom{t3kBbpIr;K bJy-p@acNZg<#3+hYN=g6>}5OF*=Pa)s_54h literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test12/Intermediate CRL CP.03.04.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test12/Intermediate CRL CP.03.04.crl new file mode 100644 index 0000000000000000000000000000000000000000..7ce6928bb68dab8b652e28fb8ff93558af72a1b4 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zUFQHj17ke{6LDTkO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aPDm zm@kf$d02_&V&=w12BW6Rod=;k~z~ zpIu^MTbN19IQ-hRDJcE43{Q8Swz|2);g#IL;d0OQkWnE(I) literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test12/Intermediate Certificate CP.03.04.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test12/Intermediate Certificate CP.03.04.crt new file mode 100644 index 0000000000000000000000000000000000000000..a55333b634aa3dff08c5e2b2e3c6d4272ac47589 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6Qj5RFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%A$F zO;Sj;vbgnPOF6gg?M-1a*J}^`%s-=1%z5d0{#Hvnk6EwYMXmXz{XhSYJ9njhgT;x> zOw5c7jEj>E5)Jr)K_@HB$oQXy)qojDfkRi8A0)s6j5s!MtjH>`@Eh&!sU&;OPE z{^yHijq4r@<^Dc;axYFWfANu)3+m@pmL17dRx<5k;;2*%6Os&Swf-1o@?yqBLHC1Y zu4Z;$SMQKEe)xf5_iA%z?LS8uu9~d0*SpaY^u;r4J9p_D?(d=MbEV}{uKm0?=jbl+ gOY-g&3k#Q*7FqV+4SHR+@cf#;md{o)aa>Ua0CKj|FaQ7m literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test12/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test12/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test13/End Certificate CP.04.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test13/End Certificate CP.04.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d1ddf4b4451dfe7c2ca5c1ff50bec09804fff605 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iBZacmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uC<0eY5}Kx7~%&TDC5U}#`yXapn;qQrSkkhum46ve=mG6)oR92hMpg#q#$E=4#!jZjMur~^DNE1ytXJNJ=4b-s$=Wk4CSbzq3mDy7qRt{vLsl zDL!|LPRnF2l#+YU6c*pJsp{9uBUA5WO_kut>wEd<`pcqS+l7TX%+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zUFQHj0~0+1Lvdb9O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aOOx z-(MytvilmEix3ePie@ue5+lDOl z6E{O9TKwDP%(~~<%~(aJ)+wKD?zB!!tvYJ7lC4(LGx%cT#EZ>$%=xeWo-eqlbXr}i wxpBh#2&?N2%G2%gw*Fw#di+v&F*n<#(`gllewj-gKARQK#AI(Y^;Pv*005n+a literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test13/Intermediate Certificate CP.04.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test13/Intermediate Certificate CP.04.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..abc6fe537f3ea7d5fbeba95c2ab4ec6443b3a005 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6QiU7FB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%A8JHV;84MabnHn1zb_UGvGP2iY%6Wa~;SBu@A<@IZ^(U76oLV?_@l}bM zNm^zCER52XKjNDwzqz?cZ-tD+#NDoO45)W*`L)U0HsR01GhU*ub$OtH8oapl-4jvWa)i5zXUi|Xf^*EPbAqQGow+FFO5Is)b{^X+423_uRbHHn(%|+uklfSI zIxjGO$t0CEwKdgzDfX!)nrpVlY3cdCoY3EMk)xk=rl`MM{o5;L2Qu|cmQ0PP+pyr( dZq|*)OWu7nin_9Xb%NYI=Hi9=+oM9$q5;LP$|V2* literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test13/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test13/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test14/End Certificate CP.04.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test14/End Certificate CP.04.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..f43e03826174bd41f8cfeb0be4ba64c4e90333c8 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iBZOYmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbVklt12a@3yW)Dd%F3HSGH{>zkf`~A?J+am|E(chK~}e66I=QP z&VNaDTca-S(avAG{o9^wt*C$NJHMBNP88#cSQt<+@sS%(HP6X#q0sbNwo77%e z-Sd%&nUR5Uagad(IB;e885#exurM>RJ^)99tO5(a0j~i!8)rhB2V*KTqXDCVAkdSt zd@Nin9E-Q?dZ@SdSv5G^WtCZg0o1?|WO;1)y+vD{k-ZFzW@eyYmt6Uo{NA%TU+pQ6 z^6dA2JXYG=Q|O=5x}EKSzN15JRC?(zXUTnwK6!FHyLQ1b_u!13ih>4nTeeSM;d|*X z`$D!GY7ujOt-JQq#5a0@yR@~!%pL7>ei$gJ*Jqe&T9+^!l-kI;E7jsRPp3+7zofvT X^9uy0*VyNN?T?vx<7;(DKwbv`_Girn literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test14/Intermediate CRL CP.04.02.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test14/Intermediate CRL CP.04.02.crl new file mode 100644 index 0000000000000000000000000000000000000000..ae372f38b5606cc0841b4569e427cc68336bd1c9 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zUFQHj0~0+1BXM3!O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aRS1 zk1fBqXsa`ti xfzQYYSjP$ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test14/Intermediate Certificate CP.04.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test14/Intermediate Certificate CP.04.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..6e97ee2b80bcf50b5894ba6f7d879389e9611032 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6Qi^NFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%KOd2c?Dsr2|Dv<) zj-xj=3UU-Lf4U%D;oyySt=~2_%Mb3pbUb~*nS@;j()XtAdUWM2|Fy}yNo)4*l3L5nWca!9nsDQ_i)~kTT(@6P$sTX*IrW`;(X2xpM(Rw= zj0}v6lMNCL_<=zuE6m9FpM}+c8AyRcSC$_nzygdoHgK%SDzNYy@EUNlaVE5RFs3py z8Za6Nf;956aItU%Ssq({Z_!p~a5Ts&vjF3(fn)Wo*FO(E59vn^17NH(13mA){F(Xt z%qOgy{;pEKd5Z|?J4~Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test15/End Certificate CP.04.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test15/End Certificate CP.04.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..a2408315c5195bdd40c68bc3089f15e7cf853f68 GIT binary patch literal 654 zcmXqLV(KzzV*I>-nTe5!iBZmgmyJ`a&7D}zCjA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@6^4a7kr z%)$c6iG~Wg3eEv~1}1t2#tI4sa^k#}76yg}hK5E!(jZEl*94hskU)+bT(G!7+&~oK z2ENeZ)FMM&m>Ucl=Og=@k(GhDv6sQ1v6HE>kzt$bT~V!)6Kf7yw_BwzX+9Q{dXvj4 z{#i)h^*is`OXsG&?3TPE!dm6wX!Z2j^%)KOw%JYIV4`0hDCR8aUAJzP*1q#BZ%(=1 z>0at}tL#Vp$LvLl_07vBF)dzF931h8HTH?;qoWB?4}TRcv3rs9@8Y+u8=sdJ?Ph5- zIUw1bD5f_rpNW}~fpKw=K>#>NW%(Hy|Ff_#GqFAZM}@2c3%>!c0XG|GLYoI;Dl?-2 zqk$mMld^m)Tr3>I1svhd4Ifq+2!n)_S%8t$z%gIGMX&ekn#sss21YeA(60i@9zU$V z_bdvx4_tYIW2r(LX@RhGo@IH#sG&OLTf=GxG+qMy7!IfzTY dxn5Yihim---DRqiBia@hXRith>;VeC7F5YhSCO-AQ5I^Aq53z zM?(c&1t1-uXJDddU@XpSX=z|+U}$IrBn_g(c}*;kxC@jG6v2keim)()oG1)5NLHBz zXk!D%eEAl=-mhyWqq&>8v5{fV48Hi)afeExxi2jI5xzsqlJQG}V)eA;4h!ecF?^@{ zL+ZsuWow)HZJpOrUuCLu-&hu#ow}P#K{>PKz?1Utv!W{hINve3xuRmSk@SV#o7Y^( zJ~lD`3xiVW$0;|%TQ9LBUCwyRI9svNIeP7deTzQW%;0A1;@Ky2=1}+AxD}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HPUF%&T1gYeixQj1G6^U@7P4TM1= z%)&e&MWw|h3XXZn8Tmy9a^k#}76yg}hK5E!(jZEl*94hskV20ADOl{6HjsqaFQlO0 z>}aTk>TrAhM2?6-`1MS+ofGK?V7vT zfoJA{@?>d4WxKTMFI$z9PwHJs{IdA>RM)bL$}D0By|(x|{l2{0!rCuD$>IM(rpmHU z{kcLpxh}U_v{PTG6xE$@FjbiMeD2wc$&Xy_?d!D4>Q6j*!fxfWZ2eVoEVk1f)NAK0 zRy!xL(CqyMOU;+hnV1O0$oQXy)qojDfx}pqA0)s6j6ODS+{h}h z@EhT3WR+QfvDUz`de-Zohn|P@ zBZmPn?wNs}U#G^iP~fG-K rx&QJTpK6>>yY}u3+a1*-MZ9x1ZLld~xLTveRHVyT#C==wqM9fGLlMiL literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test15/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test15/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test16/End Certificate CP.04.04.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test16/End Certificate CP.04.04.crt new file mode 100644 index 0000000000000000000000000000000000000000..108a75d738119ecad9aea86ba2af7399308f72e1 GIT binary patch literal 657 zcmXqLV(K+$V*Iv%nTe5!iBZ9TmyJ`a&7D}zC*A-4f18*?ZNn=n&ou%V=Z zIEcd~ED)*}tf!#ho?n()l$V>DS7OLxzy*@x7G`$IcQF(&;DhkkLsE-NGV{_6r41xO zBFw@<&W?r(K%lFj;2fZ5U;;!2a^k#}76yg}hK5E!(jZEl*94hskbvq82?H^RGx)*I zAi)*l2BHvG@P!tq78&ZoUC=lm+3Sp~49tza3bk~ON~t@$VRYF?^T#M4fv$fDTw0-|fw_g+0`;d*j*pte%(Yu=896SoT6 zznN_z__u7ybKRpa=L60-aW_deWIeE?WKD@T4^U|**Fv0 zJQ!1%84VZ>1c9EE#LrRx8$MpKSr7y33Di&}%crrs_qkN1=amAskYV#GE$|BObJj%1$ zxovbaWqA)g4ZONW?IV-l^3I==_7$~8lpL(P=C<_9u}NER2MW5rZu!q4$M<9E>#Gk! kq{MrjUH<6DT`}X>zCe&y%RnfqD*4!lZ%&(+%X{4h0M60NdjJ3c literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test16/Intermediate CRL CP.04.04.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test16/Intermediate CRL CP.04.04.crl new file mode 100644 index 0000000000000000000000000000000000000000..d345a338e92c591759c3b3cd8dc2029828921c75 GIT binary patch literal 337 zcmXqLV)Qj=+|I>;VeC7F5YhT;aIAQ5I^K4(Wm z1ziQ_06hZ}AQI=bv@|d@Ff=p*k_J)Yye1Y%+y%-8ieQ6fMOc_Y&JzY2BCE^-w5@^T z(V~5?xE>vxhURAG#zqE@u+YO#B2RR@*UkEL^3y8&l@ie`H$-v*Vwo5uUaO{yT>h1C zPs>j8Uc%=p)7bE`#m;MIl$jg0pRK*Y*Bi3`P6KO5iP_gf8HdE4|GKquR{f&7*>+F3 y8>a6K(&n>Sz5MKp;Mt$ktV6=S-VwRK)tKA$c}UIFt_fG${SL1+Y7Dx<=?nmc%xRzi literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test16/Intermediate Certificate CP.04.04.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test16/Intermediate Certificate CP.04.04.crt new file mode 100644 index 0000000000000000000000000000000000000000..6f2a332ad9bf6ed6ce7527ce33c6150f0d300840 GIT binary patch literal 667 zcmXqLVw!Hy#Kf?GnTe5!iBaBwmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HPUF%&T1gYeixQj1G6^U@7P4TM1= z%)&e&MWw|h3XXZn8Tmy9a^k#}76yg}hK5E!(jZEl*94hskU)<8DOl_mHxPx`&*$uD zsGzIh9H3`l0z?Ll^O60`$jZRn*vnwh*vZt`$nY@!nbZ&WLt1|G%2%>1V(~a9%6s8X z!<@{Ybs~G7Y1ep&EfnlmJ>Yia%p-;i-!;U*OHK+{34CKJ@Zc;dpdhN6OTcs zMc+H^IPtVAN12!z85kEQ8zdU=1063b%*gnkh1Gx=NP)vwmLDX*0*pE~aJm=W=`FgQCx4mphvB1yj(|^QgFWeG)LSnkkwuRrkN?XG?L)L0Ai#^p5 oz0I)G<hnF;dd09rTCAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test17/End Certificate CP.04.05.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test17/End Certificate CP.04.05.crt new file mode 100644 index 0000000000000000000000000000000000000000..b9034087266a1717666a8854ebaf80fa406e7b7e GIT binary patch literal 652 zcmXqLV(KtxV*I#(nTe5!iBZXbmyJ`a&7D}zCTA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@8)4MagA z%))%mj)uC<0eS`|dIqKn3I=lGyp|RQh6aX)MnKXaN}SgOnM}4=$>||lmDM<8@NO5iHr|644n|^K64L@P{^RC^;OtB|=d**To zty*ceQ|0B}X&*1{auC{R6c#L>)@rET47mLi^hk-$nXd^ZIPH6P;fy z+qKok_kEbO&Glocyt@3p&VS$bc%M3=ygK93-}`^3#ASL{^Gx|CvT5#)#?mi)a+#PJ z85kD_83cd>RFykqM$lcb9)aKcB#pvRl!>;VeC7F5YhT;aIAQ5I^J_QA5 zM?+ob06hZ}Jp)s5UQ0^@LjyxYBOqxICC+PNfy7;)Y@i4>SXP9E8RR@+pdqr#EI`{D zIL<9tnfXKf*h(}vGdDIeXue`PRPx2(O~smddz0?69e$HDd*z2;`O&5qQp}5g{QN4$ zTpgJ5c+2X|w^aXbTUxnVtoL~Cha*dU&+XFsv^U|S!;1EZ1y6T~sb{JP)?Yn+sW`(e znKkFg&g)wHozy3PdiKGI%SvBSqPyIRJFPp;VxfmXrRdvu(Hl>WX7gl5-$>~I05$<@ A)Bpeg literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test17/Intermediate Certificate CP.04.05.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test17/Intermediate Certificate CP.04.05.crt new file mode 100644 index 0000000000000000000000000000000000000000..25e7b48e5375b4acd9111dfcede4da3b754c3778 GIT binary patch literal 667 zcmXqLVw!Hy#Kf?GnTe5!iBZvjmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HPUF%&T1gYeixQj1G6^U@7P4TM1= z%)&e&MWw|h3XXZn8Tmy9a^k#}76yg}hK5E!(jZEl*94hskU)<8DOl_mHxPx`&!?c^ z>}aU#9H3`lqGw=g&^RC2&y1`L%#FPa292Fejg1Tka-y>CXw-6k-N|v^@NMf{q5F3& z>dVgrs;x<$wepS1giFV+`!oN2yjz~((+<8Wl0JP1fQ!C6nu? q9)Dr+Zegtb>|oR91r~e%M!r9L*W!<Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test18/End Certificate CP.04.06.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test18/End Certificate CP.04.06.crt new file mode 100644 index 0000000000000000000000000000000000000000..2edb51394196d5d2df64dce06ad3690a512f4af8 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iBZLXmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%wMWktf%1aALbh5=j-YhV#s5_1(M+wW_HPUF%&T1gYeixT!TYA{oD;j4TM1= z%)&g$iH5q)0eS`|dIn|&a^k#}76yg}hK5E!(jZEl*94hskbuknP`zNF{rP37MR~cY zc_p~*Pc1IV%u6>EHxPx`&lg&pT7=|+#`(y8W@KexZtP_+XzXNaY-CuqXASf9O>YCk za^L&!l6|9adj3g!?wayL-#;(RdKT@jHchJbsLamn!fPE9g!#`jY4&DrkWgRqD*yg& z*{!ZW>@($GuV-J|JWHzg*V9k^m3Co$8Jd?SecxErYj$9r%J=dE3&bS~l&;E0t(_QQ zcc^pf7uDkK?VWf;FRTOWc<&+uo}c3Rwf+LK zmx0mD4D{>bgYy^+GE@RN+|B*&@1C{kO$VF6QeO`vF+r}XWJdF4^QN{hQaSodbQ1R+ z3rWl4JIeTOHW#S;XQ-Tg^rDoJK|0?a3wn^D<3tqH~?tE9G=$lp{ q>^Q5iPvKU7d&A??t2BCYo<~P<&*0mC=|;rQcMbQ2H@dQ>M*{%FfXr_I literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test18/Intermediate CRL CP.04.06.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test18/Intermediate CRL CP.04.06.crl new file mode 100644 index 0000000000000000000000000000000000000000..2948246d79e252f502e5ceab6c389b1c7cb9e204 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zUFQHj0~0+1GjU!^O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aOU+ z&rk9ET7Ln}#mtS33<^xv(TjF{yTh4Q`0<4nhtat@`wOqtbGqbar_H(mZL``Q5qs>uLf~@-#;Zp}vS;39WS6-M0IP##@c;k- literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test18/Intermediate Certificate CP.04.06.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test18/Intermediate Certificate CP.04.06.crt new file mode 100644 index 0000000000000000000000000000000000000000..eac3e8693adafb17bd6285413e5545549763f053 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6Qi;LFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%dhZza!2kwm^C{<#Mb8gynBZa z+HSa7!~A}6Q(*IN4}s(j+n9O3GUcZ)`MxShyW{0~MXUc!d|N-yuHHQDmqPH@2F9o9 z(|&5M7kF|a{!Pa9YU%TvO%H&KQQQIg&7(Dv#=U411WIm%JPE*Sb!17296b31r~k-UIT76&V)7( z##ClT14aWukVZZhE*6dp-1AdBzt&#>M}w>~3oyPKI9AVk{qxZCkbdMa0LD5q(DS)J z3U^$H=(dSBoE&pXx$2tzZr!rT#U;xOeYXZBFSHSPR%&))(o-kpho!x$b9a}wd5QX} zS3H}f?!2$#%`LL59mLzZsv4WSwAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test19/End Certificate CP.05.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test19/End Certificate CP.05.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..a9c7a1fc6a58ed944af8f396aa5fdf4db7a081a5 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iBZjfmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uC<0eS|edIp9Da^k#}7C_q2&AKA~0tPISJy$lA8olK354DbDTc+13m_8Z=F5ZEbY^?3t(ZOGJbS$7o=Sp7Ch zZjM;Mcj3u`69@AJ&5eaLY`>hJ8#;}-Awx9qMbV2_J7pr|45U=61->t>W)HHwX?>&X zd7|V?70+!N-rW-l>Kb1>nEWd0@PT>#!aD1|{F>HWV{a?HMQCH>g87q5PMj<)ayq5T z#LURRxH!ll034jM{EUqMSy-5vSRa6+K~{l<-+X{p5!v}n02ti zKcL##@z2D!n?6+Pu3Fc3>{NODkza8JbCl1i5-H{pnRJbSa6j79z|yLI2*|MFU3U&6!bxNnbdw3p%W?MhpJ Ux+Kl)6Z-GGcutaau^vYZ0C0cIB>(^b literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test19/Intermediate Certificate CP.05.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test19/Intermediate Certificate CP.05.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..eff60dd15751da6eebfa8e557ee621f29a92b7b6 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6QimDFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%A8JHV;84MabnHn1z*0i;AZdY7$^r7sn?y0^(D}Pikd26Ux}Oxk+(6@T!%L>i|BuyQ-t(kl z|NPvni-vUz!?yNczw@p@L8s?Ywb=BvKO;Q1%`?q3kSTvF>G^2R;&&#=W^3Q7tZ`qr zmWi2>fpKxNL81XaFz95385#exuo^G}DRAh@@`D6efDy+Ajulx27JdU>18z3Xgft7pCbdFXjaKXMoVW1Si3`3RwV zYH?aqm`@!`@OjEsrrIsd8GDuW85_eAy9fL3wd!pTWoA0iagd|wmP`_Bjn=#ZM#L?7U literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test19/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test19/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test2/End Certificate CP.01.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test2/End Certificate CP.01.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..f97da05098103782d905acc23299f725645a65c2 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iILfWmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uC<0eS|8dIm-Ya^k#}76yg}hK5E!(jZEl*94hskU)<8E?DdrHxPx`&lg&p zT7=|+#`(y8W@KexZtP_+XzXNaY-HHOxpvC0oT(S)&bf2%luY{1-VJUG9*EpMm0z2p z{O!)iH9qQBZ`=J_-f*v_F?;^!`t0!1d4E>9tqPF%YV+!5DQ5=j){=c^)OC5~zS{4b z-Ft6S<-h#n;(mV>JY32z_!--X7X<5h9s2P#^*P%u-GkyTPr}zkAKZ81%c3=s5A-E1 zchoa6GcqtP4l)P;2d6AQBjbM-7G@^a2jFOsRbb&a;5Fc8<4kDtU`%CZG+;Ck1bR}I zkA;hcqkiV3zQ>81e}KbXR+$ADK@A+w`W$Ba`%Za=>}6myGXwpqy+_tq>8axU3!7Ga z|HFGM>#pn*;fY&9ZpypHP7U>oxa-L|CwrcGhlqTc$(<`M&zBuzC_GobF5=44q;O3? z-+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zUFQHj14BInBXM3!O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aSTy zIn4I=o$?IL#mtS34Ab+bH3zO*T~d3u_;Hf}V_3U;PyaIM@izkO=CiozZ{ zovmMTZkFub@gS>_FWTZkgQAw1Ud-KPULCQkS-JDocVsar)W!aelPK6Aa5$)&I)?JwqiEl!|MxA_e%ABEAsFwkqR$={IDT=g`YM6Jdb8Z literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test2/Intermediate Certificate CP.01.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test2/Intermediate Certificate CP.01.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..0aba75048feb53b03423a62b6346b10f9fcba912 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d5E<~YacZ@Bw0-AgWMpM!Fo-kcHsEAq4rO5zW(o~9lrRtj zakzx}L-m676x{R6Qj79(Q}ap;c?`HfGTg$!1F3(azl!uc6wy{pp!o^_P!xY9+s1 z+kauj`(5X4eupyeY}WMS>umY`C`n9yZo7k6_Kz=V77-=sSGF#+^3E6b<}kOiO5tMb zTU0I5vHi!ntc$L*Ehne%=URQ+eD1GvA^he|oc+AUPj=+F9X#XT5Vd8mWP`dxizgE^ zBLm~&WP?Nleqhka3NtePXJIv922$YAmE{KsumB^D4IC@73M~8vyawECoC$3njH%3w z28;%RAdP%1Tr3>V`W$Ba`%ZZVjs{s}7GQieaIBv7`sbnNA^pf<0E~5Jpy%)C-Kd^_ zxjK$pnaf^h?fiMOq;na}%Y>Id_0UQ`>6OcWJUrmf->0@EYu7(x-Ep`2=;|ItZPzXx z>4Tytytd5`zRLQYqjwtDa!+@yrP)iKI33yk(zg0PkJ)^it)J)KX#H@*?1bFY(mjcj eAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test20/End Certificate CP.06.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test20/End Certificate CP.06.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..b26e77c19938e3b27650119bcbae36e06db95506 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iBZFVmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uC<0eS{zdIp9Da^k#}7C_q2&AKA~0tPISJy$lA8olK353@@su`tZ2EuHOEEQF-Nx+Z)!*mAUY`_2b*Wv8$y{ zn!TRnb~4mUY}$N|HaT;<=U*Q^#qwN$_F>%}tEOI- zIJtC*W8-Oy-F>d-KJ(QbT2cP{i0fJwdWMEtzWDo!jPFa3N#{VoV%uK8gz|kP9z`}39YrxIMnb79Jn99s(z-S-{^rS2w z3l|GVw!#*hueRs4!Qn2e%mR#{1`dt}wdr>IIL{(`85qsXK)>4C-46QJ6294}PkfKg ze9oKy3t$cm4sb)%1Tkm^DC*6;NQPTrk^Y_kqJmG?ryXcus zCl4QIwl7<}HEqt5vf7f%Cnx52wZ|^~#+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zUFQHj12a7XLvdb9O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aOx_ z)TZ0*<2;MzV&=w1hCHXZ-tVUCt)22N>^d^7ymKNm&(Uq%g85coHnb%ywp$u;FY1uZ zl?i8WJX`rHX@TaucbyOHA0A-d;q!LqKCk9#ZPQabzgTl8_b%YkU+^tqUdP<#EujKB xA?ymj7-nyItX_6N>4w{c`QF*iTZ#E{2;3narW%A8JHV;84MabnHn1zPCPhzlii=O*74)w|36&c9XReaZ9;|7tFnK8%etKt z3v744%%8cWWk(k8grNAM3HokI>ZfY1-JH8ug#FL9qi5^CTPz3;{94(SX7qi(!;Op5 zkGfr#FJ$&QDcN>A;_ls!vrbG4RHwuV&z_gbuAXtE_-u3&V~X~qN9!Z^Z&|fX;qg&b zCT2zk#>L47i3a?@ppzA5Wc<&ap7r|Yq30p}$YB7Cb!MRFFU~$8 zovuE)cIB%#SD9XiYNX!_uN1A@SMHXyW{z4 gwBN>LDo%0P-|*_`QM+Oh*1L6+pD)h4yvObq0Kv=E(*OVf literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test20/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test20/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test21/End Certificate CP.06.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test21/End Certificate CP.06.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..798e5cf17a5409a01bb1e1090934159ec7a0db27 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iBZddmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uC<0eS{zdIm-Ya^k#}76yg}hK5E!(jZEl*94hskU)<8E?DdrHxPx`&lg&p zT7=|+#`(y8W@KexZtP_+XzXNaY-Cu+{H31r=p${h$IFhp3r%R__4cYRFln56-15z} z?Y|?fr%d=g!#~n~{g1cZ%pq%MAABd}vtV-EkU;=AIA!@68UM4eFf*|}07rwY0t>$ZuK_n3XF{6?V=6PF0i%H+(37%! zELG7B(*8aOg)!YnVo(cOydWneTj1O2-A$LtwBxmDUly)$#p z8O-^2?vwFfojLpdEba2KoO}MJ@u`U&WqxvY?EIW7YfFBd|9l`I`H76RQqCbo@k@6S z^R&`Mixm$(c;;<*L~?6s!-wRV-`n(~)&;XPr-og5=yZFHlWnDj)Ha{VzM?+OOT_a} V^;$9&>bUl@=d|d(oZ;)-3jkZL%nJYj literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test21/Intermediate CRL CP.06.02.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test21/Intermediate CRL CP.06.02.crl new file mode 100644 index 0000000000000000000000000000000000000000..ea3cbb9d8f4ffa3fedcedc0bce4f085729c85d6f GIT binary patch literal 371 zcmXqLV$3&ayvfAKXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zUFQHj12a7XBXM3!O9Mj#Lqj7VX%HpOYhr=KHBd58U}DrlQe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGWYmONUVNjw70p-7jg1TmX$@ziM9M;D-h0^9DSTgs z(PP1q-`|A&_FdkXkzkV1zU0fBm3$jsC2-Vl&Uh265vT8!{qKL6OXK@3+SRA79zGhg z{K1{%rN4i(Iq(>%%ar<*TGWOLg<(H2o;GtTa-G*cmVjYYR3Qo literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test21/Intermediate Certificate CP.06.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test21/Intermediate Certificate CP.06.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..9082c4d77e3966e98440cc65357791394d717e71 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6Qia9FB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%=2m^(uzWO{#5uHc^-)yj0N#w-7d(3DpPXE3}jD%||pwB+wuPM&R3 z?zJq~7$}zFD^x8I8ntQ8^oZXF?h5V}mSdXxX# zGBGnUFfL9uNHpLF2A!-hBjbM-Rs&`r1rA+VevkkQFyh$2u_CL$!f(K9z|F>)(B{FI z%FJlMXdnpE$j8FP!jVxEW_j_A?pAO#$SSh{p0qb_5B#qM8Q1b*d;9BouRXFJK{ z9p}>p5f%D1Q-fSNN`E`}8-={$XJxNk!@qjH9XtOO4f`FcN3FVpm)!Xp82d}Db=hjs gtr}(dg5TJ#GTvZGsNC{o>f+R=!MAt&Zz@g#0A63uxBvhE literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test21/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test21/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test22/End Certificate IC.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test22/End Certificate IC.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d130c75063caab35448dbd74708d6611615de721 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iBZRZmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uCP&UyxhKx7~%&TDA_qzw&?fTTf`IIjsZ*C2r$`(3cuFK!?Tv7axrIJF4L z1&#BO{mjV9z}(o&V9?mf)Y!=I>&ew$I&5zhtCF}H4GvYtUtAD&dsD7ieAE53&g+^F zCrY-3pYP6$VmrIcsBv}p{+pZot{5!;($8_r<9+JoC7C-d47RUxv9jN^(s%Cd9ZdTw zFK0O{ZZHdX;dXCgmSM`^o0IDi^-5s#qHcwaU*3mazq6rwRt!tj#}L=%m6itsADm=j zW@KPo9Appx4o+EqM#ldvEX+)-55UnNtH8ot8ay$p<%+YhM+8aW5;*sohgg@>&EU6HjUvv0vahrs*cN{jdJ(%;_@HgCtH z6F*p9L+m%}{7QcyHk+?XwSo)5XL3P#Y{>p`?dgQYse;=RY__mO5 T#k)1NIo>4}r^EVm=AQ=u!4=Xk literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test22/Intermediate CRL IC.01.01.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test22/Intermediate CRL IC.01.01.crl new file mode 100644 index 0000000000000000000000000000000000000000..07e18398d45ed79ccd41ec09502d75ed3123fb63 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zT~B8{14AGZ=e4vnFf=eUGy;+aQR2KN7D(I$$_9#HV`W8Hm_d#M86m680<^1v<4cj7 z%GBSjuhCr0+}Owv-f%{IhRBCwRl+})_pna-c}Y;y!81H?ruqxNQ^%uctWD(iT>RvF zD}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HPUF%&T1gYeixQj1G6^U@7P4TM1= z%)&e&MWw|h3XXZn8Tmy9a^k#}76yg}hK5E!(jZEl*94hMp8Y9!?RR!G)b(`MGcW`q zgU0#DK4xTPU~cSXFlg*#YHVaUZ1vXjZ;)}0oM@qL^TEIKHxw^ZvVD|w+2-`x&^KCV zU38oxjY_S~%l%6Xv(o=;{#L3^=fFjulf348^xyAy3;y+?G2zMVZC0YM9CVN8x}`bq zzW0qqHq!jv`YIOHxczahE)Ns8D4sifZQenFYu|NU{(U$U>$yvK4~GJCz#@yj&8|$$ zj0}v6gA4+|fho(+$oQXy1sG3k;7E{FVBt65HQ;9BOlb39Ol4*?U^EZ}2C*z33l|H= zmm)WnslQuagF{_bnFSa<4IHayz5aRVc}PF9mw}PY4D{>FH1&&O-(FlMqYI5~u%=OlIpL&zD&t?YaVup;#+3)|v&o0=u*rIkO&rDyw$xFmm>V&d? zAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test23/End Certificate IC.02.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test23/End Certificate IC.02.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..787941b16500fbce62b8a7781dff64d73d5d6813 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iBZphmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uCP&Uyw$dIp9Da^k#}7C_q2&AKA~0tPISJy$lA8olK354A(A)J}|UWJ78VZwpu3QZd6x{)!!|Pe1B= zYAH!8ZR2|_6qcvCuYBgW<TP#M+b-^yfBF@}HhW$=!WBTu|5DtgRBAzzX7iSHydX{n+IbmGot~cfgsS6vV1ID zEFAYZ8O{1HDJp}*T~?U|7(opjt@duc%i8%;FuYs%k!>;10YALaSzK-erMdCq%Vtv!#1 UUpC6P5wW~Er|@|9v2BS)0N0byn*aa+ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test23/Intermediate CRL IC.02.01.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test23/Intermediate CRL IC.02.01.crl new file mode 100644 index 0000000000000000000000000000000000000000..2841be769083c8a3bf1e8bab2fad0dff1b84cd19 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zT~B8{10y{HLvdb9O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aP_* z-Fla`_pe8DF>_-hgW8Gv3w4iPS*%$Y;Kvq8T@b;;|PCg{KIZyP5x~5-wC( z6m}_a?z@FAL#irRvY&W<>tkHJn%i;bcaFn?{Y~91LXQ{EI3vy;b1?i#VcC&W`%X`p w?^HAO#SxLvNJCYL2OEuECo_LjU8cse{+#v^slR~xW=eYJ=S0Ae#_#E{2;3narW%A8JHV;84MabnHn1z?#-AXIp@uFYi75V0_Jh+ql`9)Ir?dcy$BN6&64=( zro`LlTO>~EEm;0*x4D=}t@%Bf-D@wGJ#J`P8NOpq!+7B zy*w{=qsy5wDQ5lobZMQYm{XjUi~F|OtKGP9GcU3!?YG19sXUf%tnVaRr%ylf%i7^K z6Ehx?#{!HsHgJ^4DzNYy@EUNlaVE5RFs3py z8Za6Nf^_k*aItW-+Pn2GYwuqVjssa`7GPvGaIBv7`sbnNA^pe!0E}{GpwFX(I)h%E z&YF{X{=*CYKNcT~jVJ7z;-C{?^FaA9#BVY z%BwbU7jm=QT>I59M>(ry$(E@z7IU27HE&AX{`f$8?%Ffn2JZ?sbR0IDA8}73{(Ign eWAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test24/End Certificate IC.02.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test24/End Certificate IC.02.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..0d145b2fac60ad34b45c3723c7521875db028f86 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iP6A-myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uCP&Uyw$Kx7~%&TDC5U}#`yXapn;qQrSkkhum4>DlC6>(uY7Y+_vS(0SH<-6G+GYL9sC zF)fIF8k2IS^;!Dt+4GO3zT~kod-LJ{=bY`?)80CNQ432sdd{?CZCUiB=FAlaY4;B5 z_A)UuGB7RaJb7Vvj8KgfkRtPBHwzO?J{I91EZN4=+{GDuKkPF|9H-|*4wYC z@UP=_#|s``7Wy?l|L5K&{(YJPzt+uEp2~+ocFR}(s9^Y<^-pVt$V)Cmk&v{u#jo6! zs9for#(hyqMSe$+!v2C)x-%cHKNle?d8(;1FU2==b;1X V&bium$FXl_l>x!iSI5tv004G=&}skx literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test24/Intermediate CRL IC.02.02.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test24/Intermediate CRL IC.02.02.crl new file mode 100644 index 0000000000000000000000000000000000000000..f608de6bb01cc4e935f44acb2c6f7c7d7f6ac3c9 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zT~B8{10x_3=e4vnFf=eUGy;+aQR2KN7D(I$$_9#HV`W8Hm_d#M86m680<^1vLt9QF z-+G(vGBg)6H#Ra@{+@nN`o|`>^C@iS4H?_nuSbz})mX=4D>9zc+0b`{XXQ z{Oxz<6P2r)Cw^x<7h)C6?%wEA?eOwv_l`Jz!{(Zcd;Gr}|4Tk8#4VArdr?G1mnWZr u{gi3jH*NZ+A6VNH@;Ax&R>Q=K8sU@wbtkDZ2$xA@vI-pWQQ_#E{2;3narW%bGv5)Kl$ne)+R=e@?Cw^4S-+ zqwr{+vf;)vFYhHC-k;jK>F&g}Q?z(erlfnHeS6qrN$~9p!3+g&3}tF1y)`=}UY~k- zdva;`B$vKQ_rp)}cW!r^)Oqc!v#01bQwiQ3>Xk2Uq`7x&eh`&7`C%u7bhDe8t?;yPF9$a@jnZz0W**ShpsF?NPq*!z$}GV6YT#Hs>-En=&qMl=!vGlT%s|gCx;W1y z=Gmm%caBY%STwuArBeS|=sw*S`Z)&a9>0&x+gry~pPhQTd)Mqe)pAqSH%;5d+PK}^ zuPS`C^_sP{DOT?uXZpOJb5Y^$Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test25/End Certificate IC.02.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test25/End Certificate IC.02.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..d1267018896f12d441990afce3693b7a9e584b11 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iP6Y_myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uCP&Uyw$dIrV@a^k#}76yg}hK5E!(jZEl*94hskU)<8E?DdrHxPx`&lg&p zT7=|+#`(y8W@KexZtP_+XzXNaY-HFtd-0u?U1qf|p>|<8(a)b0UJdt<{(I#AjPUS3 z9v0C%X1L#I&vtD2yGr5UH_crauicpT>>l%8gGS?GFRfM8&$*Izy*qMm-J)4{Gj%sk zyIvfs|K7B*b^095&vJ7jdXAh}wP1-&gPcYFB$l~84KC68j~%B!;JTZ*!}p2Je!kZ? z6jw7bGcqtP4l)P;2d6AQBjbM-7G@^a2jFOsRbb&a;5Fc8<4kDtU`%CZG+;Ck1bR}I zkA;hc!~5fHh5jYoKf&QHtIPt7pau@R0}0Q~J z$x~mN_$;(vky})8ga6u#%{|ITetHJ$#408*MQu7P{G_r|pfBk}{Tu^Mp$k(A1B7;Y zpMM#2G9%*CQRi7)^Ex?0>$Xc;i^&T8_4=N!v!-sI_q5=z%Yqy3+<$VVGHIGs$+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zT~B8{10y{HV{u+fO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aV6@ zBz(Kfz$Sp^V&=w1hR`QUTWwuk-8!dX{rzCbi8tv+Ypg_lO^#uk!u-G&{~;xSwn9dyZKj wc$3}KeNy%;Jv3K4Jkw-BdSWx5^d;XPbzcA5g=T;4;aH@nd0UAwF(T_B0DOyQ8UO$Q literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test25/Intermediate Certificate IC.02.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test25/Intermediate Certificate IC.02.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..5d06aac4a7fc4e9ad8ddb787e616c3dfdfe94896 GIT binary patch literal 659 zcmXqLV(K?&V*IgynTe5!iP6x2myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HPUF%&T1gYeixQj1G6^U@7P4TM1= z%)&e&MWw|h3XXZn8Tmy9a^k#}76yg}hK5E!(jZEl*94hMp8Y9!?RR!G)b(`MGceLK zFg9qMkL+VcRtDzAUIv54PNv32hTS^RbtjT^9ik=){Md4*p=14=xlx7w4rQ?dhx2Y- z3AtO*xAfbx>zpOW82BY51+@3=vHUT2$^S>!BqS{TA8mM0S+2mn@$?Djt0$#{r#Til z>M^b3+${9;cXNwy)PohRJCdc<>#y`hPuyUim080UxcbiHy3T`J-1p|QE=p@mY%^_T zVrFDuTpVi<4UPd>VHPF>25`8_@-s62XJG+G85=l0WEEKW4R{T>**Fv0JQ!1%84VZ> z1c9L~%g4gS!eMtH;oD^fHUV%1$SSh{W2%8;^{m%F4?Pd*NA^81zL|mEHk~eY(&YM& zz=c~yIe%8qVBT@@dPArFs>w3H?|PhIH|I~2EV6%hc&Bpr*S%}{INAihMK|u-a%0Nj zXFFf~`MJaAW6OmIdAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test26/End Certificate IC.02.04.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test26/End Certificate IC.02.04.crt new file mode 100644 index 0000000000000000000000000000000000000000..5abc96600e158d82f2c04db6fd349c21b3abde60 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iP6M>myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uCP&Uyw$dIly2a^k#}76yg}hK5E!(jZEl*94hskU)<8E?DdrHxPx`&lg&p zT7=|+#`(y8W@KexZtP_+XzXNaY-BjPpYV){)3qn*v-3y0KS495 z@9{jimHB1$Qw80IjnkL~vW|S&tp7TWMO0^A`nR~_Hvg8e%f9~o=-Jv!F2P?Ph(bT*EL$_mWFnocXn<9j2)zOZ(@` ztzXH+%*epFILIIX9GtTJjEw(TSeThuAAqAlR)K}zfY*SVjWeOmgE5tv(SXrF5a>x+ zJ{B$(4&}AJbG;wzGXsaatTGEQf*Lq_Eca+nlaXAB>}6myGXwqF&%ym_vHHBF`evtc zc$aC~@?7Rx`efCK$hI>(rGK8DymqVnH))g1^z>zGWHOTz!+6eF&Y7=Ub$aF7uKxix zayJ%jFuc8W^1CVgVqtq;A#S^AUX$B&@Y|{Cad?=6+)qrr%M_F^*n)FL7Ub Yb+7k(WgExz#4Ujb4p~piukNS-0Iz$~LjV8( literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test26/Intermediate CRL IC.02.04.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test26/Intermediate CRL IC.02.04.crl new file mode 100644 index 0000000000000000000000000000000000000000..9f2f1b0a8871077f1214bd06608191b88cd9d444 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zT~B8{10y{H6LDTkO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aR3^ z_h?U(kz9%9V&=w1hVW_E-)0McIy#TpW5V0`f2oW@{MMgj_-=MtZ|RiQ_u2Q#GO*q( zF8{Z&^Uultt(TlNob8=GT{3uPS36qYxvXX!H8DOsikZ>wm*Kk!@xg|VQ{T^JS6#B} w^~PVlC+@jzyrN?8+G&wj{!l08yWCM{Y90Ly}9QUCw| literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test26/Intermediate Certificate IC.02.04.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test26/Intermediate Certificate IC.02.04.crt new file mode 100644 index 0000000000000000000000000000000000000000..e9c273a05285fddce0b3e1e19f192cb15cd7d88d GIT binary patch literal 662 zcmXqLVwz;o#Q1vwGZP~d6Qi*KFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%XhzVdrodz?8TU+%eJkbwf?G?QTp~t z^O*}b+zwn?FzrW}pL5sI{T{dd4Qdj%&E;rV`{u-<*Qt!^zc*%?zHq*^EO9PJ{OaZ5 znLW%0gPyWUAkKgX7<972EUX61jEw)mK`YA-WU;USV~q_QC9(=E{06)R+-#f)Z61uN z%!~$%27(}6d@Nin96gqMw5Q2Pt^~({tTGEQvKly6&wBmy(DRUfAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test27/End Certificate IC.04.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test27/End Certificate IC.04.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..2147dbd3a69da6b32dabdb27daf0ac6cd6b82e50 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iP6k}myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uCP&UywWdIp9Da^k#}7C_q2&AKA~0tPISJy$lA8olK353}@#`dEL@T_vl_IeuR71-S>`_xS#rcb(pK_;o ze>Rc(ddnx!M&a88L*JVpzh&vGbyoej-(z?1(X)>sypN3B7I(fmB(mlkse?Cx#l&#&xL9)`p0!`{xUDFXKTuy>Fd4Hud8hmX<7Qo+ghOe;jD8{9{!WQ z*3T-e^mE-Z{g#gCxpPj1bM3Op+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zT~B8{0~0+1Lvdb9O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aQ%J z&wO8{zH>I3imo$!iZlKthJy#}9Uj8Q}DL`j~KL+RIb%toD_6%c}(g2 w2B8$qY`6T2Z#}J+WZN~!`>kVN^ZepIfr7SA6U?q0Irb{-k3(L$D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HPUF%&T1gYeixQj1G6^U@7P4TM1= z%)&e&MWw|h3XXZn8Tmy9a^k#}76yg}hK5E!(jZEl*94hMp8Y9!?RR!G)b(`MGceHu z+SoWB*~g5m49tza31c@M%hN^JR`|^B<1qS<}C5iRix$lyW zOw5c7jEiFpq78U}K_@HB!fL?G$oSuY8^q&hVF5-N8#q2>6_SUv0Y&qL2c`jLGPjBjS3w_BH7D$a?j zz5L(tc+c!>od33YK4W>nDt~EO(u9L|8;b&O<>a?6HcxnXeJP)HV6387ay4s&V5DsL z%5`$W--{Q&Xmxm6$E@^Jj%`-Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test28/End Certificate IC.05.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test28/End Certificate IC.05.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..c72c97b81b6a0e66aee0ab7654ed7743370011a7 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iP6GD}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uCP&Uyx>dIp9Da^k#}7C_q2&AKA~0tPISJy$lA8olK353_D|juFLHf_&o2E`O;wP#OwYA!mG`Go!d6M+j6b9 zp1pU)#b3Vc%P+KK7(`@$3!&-R`-HSFI?|fP| zL${G9(!+GJf0pQ@2{06)R+-#f)Z61uN%!~$%27*9O%JQ*r zv2b)&XuF8U@cspdyR0$`FoGI5)DwOErl;o0O@gN{t?=9R+SaS>b5qHVIjdQtUR_aQ*f(p^?nz-X*zg#WOV%jT9qdFV8O&#wnf6qVk^6TbUj_TJYWfLYH V=y3mHbF6!g?fN|%RIYm20RXKI&5Zy6 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test28/Intermediate CRL IC.05.01.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test28/Intermediate CRL IC.05.01.crl new file mode 100644 index 0000000000000000000000000000000000000000..35e87eb0bff68fc38e506d70cb68d71861f640c3 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zT~B8{15-T%Lvdb9O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aUJw zj&7F{m|KbFV&=w12JLNX$(J9;PgoiHM(&2czq!Qsl5H&0IHH`@RwlLPnyr1zx9CjN zsn{9izNOD5EUZ?ZsuXu|&YmM>`O7pnbpAY=J|pX~LeZIu&nBm0m~&dU@%C)_+9ss7 wk1cIx;*9O_o`FA}EYzCpEqacrHrPHhaaVLg-js?Hj24lt7Uny}m+)Hy0HD2N-T(jq literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test28/Intermediate Certificate IC.05.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test28/Intermediate Certificate IC.05.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..fee01f21e73415a4f10c1381d3206359ff1f0863 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6Qj8SFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%A8JHV;84MabnHn1z&fHzPtg-go8MememFZDduFkjTR~j$Mu3xI?wftvS z{F8_OH(&R5TVa~6dG&6S$Z4}qoBubaI;yRch*PUQ*w4E&r@TY+hTQwAc){I`OfRGZ zj_iJ7uEQF4v--lnjWITdKfU!Y^Dp{r9%j9x{JH6auKG_Cwm!2=aQIOW$}<15?A4o0 z%!~|-i<1o!4fugUCo9az_@9NB|H-@NbCg{3`)Q7GD^GSG(kq{- zG*_ktw*w;|#}stE1+7J~ID#w>7`!kOqUs*=48v epHJ;cYwJwNFa%8F985bFxEK$ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test28/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test28/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test29/End Certificate IC.05.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test29/End Certificate IC.05.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..e4e2dd07218757e58ad452c22252b6573477af38 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iP6e{myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uCP&Uyx>dIm-Ya^k#}76yg}hK5E!(jZEl*94hskU)<8E?DdrHxPx`&lg&p zT7=|+#`(y8W@KexZtP_+XzXNaY-Bk6CPMu3hpJf}J6{AS9}ufp_1t$w$v(ZXHRr4) z4XeK8_Q{>ihz#s|rtH^#car@HCJyUqo{WOIw|15`2PM|*5d6Ph?)C+acQ<~YX(|#8W1h1m XT$-6}UbmJ+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zT~B8{15-T%BXM3!O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aTfE z`{TO$U1UC*iLm}ZnI|nz+KY%*W{A>obM&iS^wR? za%o1$yttFE6#pje*!mo){^xJ#a~cIsH??}DIrYrxoD#E{2;3narW%4Pgx$|)F}xB{>e{_x;gb3n z?~J>A7Fzneom0staj;Upp(}Fvhl5e~#cs`er=@x4UV~pF$C8_#x-r{}Y%7>QF?fav zd0dQ>y}aW=d#P!Lf5)2grHd~|o%9jBG$H&#YV5uTyH5oy`!zZH@1K?{wtH_Z{of*) z%f!scz_>WUAkKgv7<972jEw(TSPhtglmRzLfS-j06l>rpkyT*fH{b<|b0)NTFs3py z8Za6Nf)w$waItWF`S-_l^}EP?a2&`gvj8Kjfn)Wo*FO(E59vn^0AQ3e1ATt!0L#pT z2+uWFvi?on_Skjn4BmAiX5BNk-alIGQpNhuYd^R6#D77&PAfQD)KY^gbEbOtd|qK= z$+*=0$fS$eN*9hhIcWQHEHG=;PW6}fF?v&`IDu`k;-?q?D+Bzq6fPdAZ3{^<-n&k| ds@}Lree$MTPO+-#iK5j(?FB)WZzcJk0RX=^(b)h1 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test29/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test29/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test3/End Certificate CP.01.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test3/End Certificate CP.01.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..9b0463a671c7af3c992a4785cdf9824d56dfef23 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iILTSmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uC<0eS|8dIrV@a^k#}76yg}hK5E!(jZEl*94hskU)<8E?DdrHxPx`&lg&p zT7=|+#`(y8W@KexZtP_+XzXNaY-G5=eC>kK?VWf;FRTOWc<&6>s%j7C=Vrt#DNz=HWDVA z6t*a+gfuexCFM_B(JxcKHhdQ6p0@QrBL6IMe7Wn3ok7a&Gb7hb*WwE>K*aT Xe;+=Xy7=kf+ho literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test3/Intermediate CRL CP.01.03.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test3/Intermediate CRL CP.01.03.crl new file mode 100644 index 0000000000000000000000000000000000000000..528f3237cc0c9b350dd3b517a3300268ba81a8af GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zUFQHj14BInV{u+fO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aU4T zi?y6`yD=Nh#mtS342zZbA3f!H;o0LyTdubh#=b2!-V|N^t>TFgd%?WUzpTp`?~5#( z;CjfI>CCQOk3*Ygu`ij%q`0`(@L*ukYl2 xq^GygYDv^&srTy^NUD^dog~NG)-oe9wBW6Jsf_jClMdhBOg(G1`QjrN2>_BOYO4SM literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test3/Intermediate Certificate CP.01.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test3/Intermediate Certificate CP.01.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..c8cfc05505090a639b40ef1f93e5c5f970657cab GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6C;ZOFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%x9+`aL7rp<(P zn<`dq&)>bXX5ZTU?Oj44#+&Uqt9yQ|QFx*ps~`UKOXxh0ClT?oR zPbOwY2FAt728jmzz@U>AW@P-&!fL<_q`;vo%MTJ@0Y)4fI96m8SojTi4Y=7j6WTl& zQ<)hJ7!3qL8u?hbSUAr6i?y6`yD=La4YJBC!1!w5SUv0Y&qL2c`jNu`80*YH&pW?Z zH6{A?9`nW4KliyPKD_BYCF`y04hFwG=X1ML-hWrQw%24DugrpyM;F|byEj>Amlog6 zv0fXJ@pOumu=#P>^Ci=Iw4!Fsu=J5w!n7yN#EplS`}C{Yr4!xdwh9F{@?B2YeYF4n hq?3oH*PL?-EHL8yF7lU$xk)0j@q8`QgPU8X0|1%4)LH-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test3/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test3/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test30/End Certificate IC.05.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test30/End Certificate IC.05.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..abdc0381f931d29ae44b26db4075550fdf14c369 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iP6S@myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uCP&Uyx>dIrV@a^k#}76yg}hK5E!(jZEl*94hskU)<8E?DdrHxPx`&lg&p zT7=|+#`(y8W@KexZtP_+XzXNaY-BiQSgMxwZi!>b=glwbmtIJ0*sj?SX{}g0&1vVx zQ&Tx^hpn$!_1w?(hm++DzSCzP|I0GdV4uS#6LmyBf_a8Q#07$$mA*|bg89$+o~QPMo6CN`??r91PN+^0wP1Tw9yGyT-fwtb=f{tcUdKg->_ z;2{$;BLm~&AcFvKaLV#CGX7^_VP;}|0FDM(1r~k-UIT76&V)7(##ClT14aWupeJSd zSh!d?8m*gjzg*3J0uFasWfourHE?|QGhL*kFLwgj%fM)62Kv=ex@iqh?Ro3H&djU6 zv-fu0_cvp7XPad%C7)~?#-?UG;pmf9tGahyu1Wfw_&vIo)&K7i59Qqo5%J6RzjK`G zGSfwUkG1H*P3r}01H^AF@tfD7=le&|$g}a=zl~SA@9q|+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zT~B8{15-T%V{u+fO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aTfD znJ&`Nmpg&xV&=w129=VRlb-}`u$2w^SF0X4!7$^3pK0;^tG5=_lx_0;6H%@$BT)Te zuh>gX<$ZT;Zv2sKu3eMAF@Wvb3r61a3ai463ezW9J~_ECscq+((r;TbH}r4iaGhSW wI{S^?)wL7(Oc+xh&s|-UDthSAx0ja_yVR<;Px@XX)6#u5A}ZlPoWs*H08hkesQ>@~ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test30/Intermediate Certificate IC.05.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test30/Intermediate Certificate IC.05.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..26fd2cb6a50c41233312a360ec7fafc5e2b45fda GIT binary patch literal 662 zcmXqLVwz;o#Q1vwGZP~d6Qi{OFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%FcZ^boAv;fa5?`nFSbG4IHayz5aRVc}PEU005($8R+w5#u*28 zGyL<3NXfrw{8E2G{j$JkuUW$a*(F}=?Up!m=Q)4g{7okgivE~9i|0ei^kZ+11#V)v zDU_HRDB+AqgDULcjZ^@2jzIeuq7hs~2MSt4X&p1yihr2Ja{ eu1MDA4x6U1U=jOg$9=s2NN#Ppa=+`WX(9mh+R<|W literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test30/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test30/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test31/End Certificate IC.06.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test31/End Certificate IC.06.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..cd766ef7f3c448f612b70a16f7c8ec15ff723a8f GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iP6r0myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uCP&UyxBdIp9Da^k#}7C_q2&AKA~0tPISJy$lA8olK353~xiNVs{#ve|dfAT(ji_tDJ=&j=q~Cb>Y#yDM=5N z<#+#E%u=graDC~Y)3(RtC(1XBTu|5DtgRBAzzX7iSHydX{n+IbmGot~cfgsS6vV1ID zEF2;eY-7@E1E+$+T~?U|7(opjR|IPN7ZuIdL-sN-nwf!qT`Iz4X=++{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zT~B8{12a7XLvdb9O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aS>9 z)b=kbny-iEV&=w1h9hROo!#``ywNoFj;!0F zS-+oJzI&wn_2OOrrK*olsy6k=vfIo%ST6HKTV!>?x%|TYk9BX_+AS9GuGMILlXE=A w>xb{3B}TEjbt*Y?kGxJ$I9a(jlGFLSH1p&wXX3dx%G$}t`+bqww=^ON07b55DgXcg literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test31/Intermediate Certificate IC.06.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test31/Intermediate Certificate IC.06.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..396947b15d9e01bbc91eb3e24f8e0049804a9635 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6QivGFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%A8JHV;84MabnHn1zp6$By*S7zlZuNBohYPx#*Mzq_S)Dp<_9Gk*AfuobE{32wJEbCo!GEP$Lmfil=Ftfg`I~Ocf@HTiZTXgAI+x1(8 z_nW3J7MJHNhLaSH7}a3n;qf)DO&FHi>Ia*vxQf@*mttRhhd*d$D>O-)-zQY zGchwVFfL9uNHpLF2A!-hBjbM-Rs&`r1rA+VevkkQGZPaFI96m8SojTi4Y=7j6WTl& zQ<)hJ7!3qL8u?hbSU9c-)b=kbny&|r23chmV0<-jte*Ay=b`5z{m5YejCE$9=d(s99&)<8)^}(}g=_f81n1?5&esb-QdTpDia3^es$)N`s zM$^)csaPI3y!eov<9^qT{@%+3HakbpR`A}qdr^P<)o)*0L)SIid%N@8S hb|!Bqem1#M_rv}kw{M*lPfG3u&OV^!e>Uet7XXd$+dcpQ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test31/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test31/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test32/End Certificate IC.06.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test32/End Certificate IC.06.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..3804a27b44c5cb9fffaa98144b4b62e7798af3b2 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iP6D;myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uCP&UyxBdIm-Ya^k#}76yg}hK5E!(jZEl*94hskU)<8E?DdrHxPx`&lg&p zT7=|+#`(y8W@KexZtP_+XzXNaY-BjeaW1~jRODv;pD5;&FFHzcUr)<;Ijiz*_aRO9 zeTl!AK6&x1j_qONx^tnYqh^+tfFVzfZCIXmWJ#KjvR+#X~9X2Cq++JzLR=U0d6K zGBGnUFfI-<2mlACEI%XTe-;*ICe{bwXpmK4;Wywl;AZ1YX!Br9Wo9&BG!O)OQkIW} zi-jY>{Bn!OS^a!)xXUWD03)b@IYozZ?ax1gNqis`RoQl8!{_u3=Ov24eb8PkmWJYLkdz4!j=&vP?T z`2uI=jXBYW&OF%rYPsJ3#5m^i5BphWC8{r%EVN(PyTq$P?}1~)nF{^q%ih22*}>6l U{#!;*EU9eLJ^75JSQ&$v00l6}&;S4c literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test32/Intermediate CRL IC.06.02.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test32/Intermediate CRL IC.06.02.crl new file mode 100644 index 0000000000000000000000000000000000000000..2e2e505a0195a7b1c71de49e18d430955bd22f67 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zT~B8{12a7XBXM3!O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aUqB zc3TI`+2DufV&=w12Gtk8Z&yv-&MC7;<$V6K`F`CJMx~iczFy0_{c65*3AT{x-ytc`w#wD2-cbz*OwU5tbg8RfBTorHacNb0v04*kFivR!s literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test32/Intermediate Certificate IC.06.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test32/Intermediate Certificate IC.06.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..6df3396b79ab1172d12c26692912fde73d2690f1 GIT binary patch literal 662 zcmXqLVwz;o#Q1vwGZP~d6QjKWFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW% z>R0RYvn^k3o$b?iH|W3O`r88M@{>;a-?_MM$@(MN#vFwqtcNOO3_T6l6Jx$gcI=rR z%EZjbz_>WUAkKgv7<972jEw(TSPhtglmRzLfS-khnTd%793`>}Ec^z%Kyl85HV?*B zW<~=>13{1?J{B$(j(4`*)&X-i_<`d{k3ILzHg6d2u4?BHN7v%$G&P z54}|@zHo2n_qjJ;&bI#}b7`sDyB)u$i)y`^D`m*!JNH7tqkONanvctE+NLwwF1cRD f#wf=>w@N+Jy6luwO2LPFi|(!O*rwXWv^Wg_mN(Kb literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test32/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test32/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test33/End Certificate IC.06.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test33/End Certificate IC.06.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..6ef1d03a8a388f3a3f804f65a8bfbde065b73661 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iP6b`myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uCP&UyxBdIrV@a^k#}76yg}hK5E!(jZEl*94hskU)<8E?DdrHxPx`&lg&p zT7=|+#`(y8W@KexZtP_+XzXNaY-HG0@FOd~EWB-6dRF?MBi0F5q+}GnCrG=4gAl=<%9A9>}6myGXwpqy63B#R&@00b#LV7 z-*{QtwT>a=sh*(iq;Eg=E;5Nb!K9L1wKdjVE=6;v&|R)olUG>mSofhN&qVCKHcL!; zM@)$8`=?ucRxUoGolp|C#UcFD)BXu|E}6eho{cPXier_?@H*B$e~w~J!>o>}zxpeE Xmh~U%I1<{ie?iJtbI(hw_Fe-3@+j0c literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test33/Intermediate CRL IC.06.03.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test33/Intermediate CRL IC.06.03.crl new file mode 100644 index 0000000000000000000000000000000000000000..4008e3d4680ec259e5b4de487dc6a497a5f8cbf9 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zT~B8{12a7XV{u+fO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aS4- zsvgJ<`*j%2#mtS33>sS1VQQv@E3PlyaY$+To>TpQKdJ~SO9`8CRSUY!3XeNlQC9h_ zDADaU>($EB_U&Akf)7qum?*P$`Uyj^;~8Fe>u%l)Y1md<77^rb@h|w9F7wRxGpY@& wd5;fYn8FgFY@XSzkXtl6C-5t)OQQboO?OvaW%#E{2;3narW%(wF1xB8vL<*a3*n-83vGx>O6 z@&VO+cY)Tr@)gPdPFcSYzyDxSVEkruFUjxJ^MYd5T~yc7 zI+OqLrhsUGPW^%W+R#$xH1Wz5R!8Y1rwK)B8x!QZ*Izz=R3R?2o8`QA%BA|2+rjKi z%!~|-ixUju4ETXTCo9az_@9N`aDxQ+Sy+Iv#s-cOSp^n;174swXF{6?V=6PF z0i%H+ND&_k7YoO7R@DQ!VZRQ8<3LuK1sGWk9II!&{(0zmNI!A_0Hd54=<^jbLh9I7 zUw41{Y~j8IwLdn03cBaLrBrf9p^5%VXTJ!32fczsFVDVZ%{*tSS-yl`FPv+AbG?1# zsr-(=7V$IJK4s}%`=Y$%Ykp()S3R}bB$plOnKJ9&9y`A0@go)m|JlbJenl$?=&}m_ dJaX|wBDcyb=XtkZSLeIf+{}FZ(aU&V3ILv?(CPpH literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test33/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test33/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test34/End Certificate PP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test34/End Certificate PP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..695de1cb44a45593b6ed8de1c2a8fef4fa8fa56b GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iP6P?myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uAc0eS|8Kx7~%&TDA_qzw&?fTTf`IIjsZ*C2r$`(3cuFK!?Tv7axrIJF4L z1&#BO{mjV9z}(o&V9?mf)Y!UPvpj@Z%**qy*zMV1*CpCIz^sYA}^}MV_)EcC-b!5I?rWd zW@KPo9Appx4o+EqM#ldvEX+)-55UnNtH8oP^&L;%q%6yUIs=pGtjSl=Sg`o^G<(a_rty@bm8jX zb=TE(avp0LJbf2oeChi9s76K=JBjPBY_sHU9zJB-wD^9`y6G~lLQmY+?#L8m-#2g5 zG&SbE(P7W(IRyALzkMs;ucE>~-ST01A-~v%B{M!f_g6~u*iyxwTDY&=N8&xF;EwMa S>OZeN{~lJb-^sRgW<3B#x5-BU literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test34/Intermediate CRL PP.01.01.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test34/Intermediate CRL PP.01.01.crl new file mode 100644 index 0000000000000000000000000000000000000000..a8d11e78881ff65acc0000de2046a881ca4c4b5f GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-GBf+14AGZ=e4vnFf=eUGy;+aQR2KN7D(I$$_9#HV`W8Hm_d#M86m680<^1v!#dRJ ziySjc37U(U8ygwqu3b0ul6MMNo--psm&f*%HKW^Gu5$T{lbfy`al7g8v^T@<)-DI3 z9`9dw?`EYmJXretUBH#k&(7YMFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%5S1vVJ z|C@V4=_(Gc75?(?x{9XXpYoGu(bW{?%MlVU%fvHuQZ^`*Sgk30Uw8K{YtO#e%2Fm~ zMh3>k$p(oA{J@}-6=r1o&%$cJ45YxJE6WcOU;#!P8#q>E6L#@8ZF|(9_qd``g1sGoq9II!&{(0zmNI!BI0ArmQ==p-usSo*# z-{^O6w_R&!|N2Ab$!3GzA6sTWn6=J*;{pXmp?tI dp~QNzUTDVz;}|2yDZ$Lrp7I}37Un6X0|5Li$x{FT literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test34/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test34/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test35/End Certificate PP.01.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test35/End Certificate PP.01.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..26846be188667b0d0f044d6849ec10182ed812f6 GIT binary patch literal 626 zcmXqLV#+gUV!Xb9nTe5!iP6n~myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uAc0eS|8dIm-Ya^k#}76yg}hK5E!(jZEl*94hskU)<8E?DdrHxPx`&lg&p zT7=|+#`(y8W@KexZtP_+XzXNaY-G4lFq!3A>HO-q4u&rjR>qzWesJ`!fBog{i*9f2 z_o%G#_?lZ;S-C%J)v3;k5FPmy;`d*fK2^H;L3gc7xILw~5n_o=8YC@sannHOh1qc=_5xZ1Fq&f2;Is$+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-GBf+14BInBXM3!O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aNgj zO`SSlf>Qv^#mtS34D;{lZM2t6xN~2oJ^i@<{BVy4Q}%Mr56?UQe4$2_!B4?e@{ej4 zO_tbM>ilbKz?|)o(g^PNt0TvK(;zunFi2sy=5`^v>d+JA+`cZ#Y8e0k literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test35/Intermediate Certificate PP.01.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test35/Intermediate Certificate PP.01.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..6a66418230a27039b45b37358b87913f9af100ac GIT binary patch literal 641 zcmXqLVyZQ0VtlrMnTe5!iP6=7myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HPUF%&T1gYeixQj1G6^U@7P4TM1= z%)&e&MWw|h3XXZn8Tmy9a^k#}76yg}hK5E!(jZEl*94hMp8Y9!?RR!G)C~yGGceRM zFfwSIkL+VcRtDzAUIv54PNv32h9!=y7p*urTse!ZYUHboDjnwhEb?v&dXnSn>W+{iiCI0g+a^zIBUwOsCc~5rkge2y_8-L(So(BBDppzA5Wc<&ip3l|H=LZhiu=Sy%3 zfP-6BnFSax4IHayz5aRVc}PF9UxBg94D=+Qbb9%U`Ri92)#y0~W;ev_&L}*r{9)R< z^?xJ$10Kw&4bPEgshp$sWv21^uAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test36/End Certificate PP.01.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test36/End Certificate PP.01.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..ee6ec5f4bc2f3b9cf5560eed02c3c629e0ab6a22 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iP6)5myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*jz+ox0eS|8dIrV@a^k#}76yg}hK5E!(jZEl*94hskU)<8E?DdrHxPx`&lg&p zT4acDLF0U6KQpp2FgNxx7&LY=H8wIF-ZI^P`YZFxACFn^yU$b-tI*)QyP_J=UW=jc;+}q~0rw%PpsDe(G}U<~@n`%rVcBWM8iBJlF2~O>zRm z+Hg@OW=00a#X$xE;NX)DFYntvdS#L2x{Qal?XWKbmzo3WG@4wnHlKUE>;(@fCYI>-R>8| zlyub3huyqzXic5W+GznDzYI5CcjbC1>c&cVSZvMX{d&=<$3vD^2Pu!e;onPBc)Bj%)x8pchgx23%vEPe@FDv>l XnZccP+L>{WQ1_#G+n+xcQVak9n5NDT literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test36/Intermediate CRL 1 PP.01.03.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test36/Intermediate CRL 1 PP.01.03.crl new file mode 100644 index 0000000000000000000000000000000000000000..d4ad1013d5729dbd068eaadac60d34b9cbf07de0 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-GBf+14BInV{u+fO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aRAT z?{wVxl`9X;#mtS33@1--TyOp9M#qerNa4d<6r>&`9%WO9a~lpstyi0R_>E|D_N`C}^9hR|NccJ^M^0BLc(dv5SqbCpdBtIt xGbWVID_2Xq=X|Yto5|rbF@KBnyDOSj#fbi_w=7~jtGeprokWS!eK!`J0{|-RYD544 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test36/Intermediate CRL 2 PP.01.03.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test36/Intermediate CRL 2 PP.01.03.crl new file mode 100644 index 0000000000000000000000000000000000000000..d45cedceef685ee994b5cf04bab7138bb27057fc GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-GBf+14BInV{u+fO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aQ+% z0uDOeIq?n6#mtS347n$+{61N=RAb49?|RCn%S$-y51*b`!y))IKhak8CYNO4yT^8q z&v1P|a7?gz@`UNql_w)R*Y_+_s@z@GcHJUFKdgQIldKc79(N`+J^po=?ZuSI-`@t$ yQ(N2lW##MdnHu;1B)wgFV9x~I2g?@xyY2S=$c}^3r7>S;edPOdzyCP%mvsOmM{;=p literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test36/Intermediate Certificate 1 PP.01.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test36/Intermediate Certificate 1 PP.01.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..a300e8d67e12164f5203f53e2240305720d7b923 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6QjEUFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%FYD}$E6R7zownZk>Xx=c z@7k5V(<9C&tZ$lP;J&@K<8ax5>07cQ>%O23chmV0<-jte*Ay=b`5z{m5YejCE$9=XYp+ zj@|g+^X3zYEzukr(>075?i`*YuzKT?Ym@SBZoOe5wygT|%tbrr2>ch^squZoq<8Ow zm$U8mOZn7YADwJwQkELE=tA?^FO!$sSgj~a{m-x6sXs?+uUc2;;b$xGa*1e>7XT2j+gbns literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test36/Intermediate Certificate 2 PP.01.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test36/Intermediate Certificate 2 PP.01.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..87c8253c3c68fcd3c0bb803c3038c8c7b456963c GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6QhR#FB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%~EZp>|;h&2Ij_I z27|^nk`;Yt4jKQ;72s;rNi6zEGXhsShwff6sz><@}DFO z>}r^oHr*3kwegU6Mc!M(Yk^y9orIX(A{E(MDz0?a-Y9+2$*`G;nUR5Uak4?80Y5P4 zWQ7?S|Ff_fFas%Y=*seg1XzF(#|DlSSp^n;16~7eHqL}L55`nxMgv9zL6Am17A_VJ zU5S8$PIpdx14o0bG7B)i8aRAT?{wVxl`9W941lrD4D|dISHG3zvX!RR2W?eBnxoP*~#m7N07lfqm?OfEkOS8dEwIM-IS Sx2J3B;%m)wy8inZwF3a5)6a$g literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test36/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test36/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test37/End Certificate PP.01.04.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test37/End Certificate PP.01.04.crt new file mode 100644 index 0000000000000000000000000000000000000000..e5c5ae8c784b6ddc26a6831bfe077b76eee06d09 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iP6V^myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*jz+ox0eS|8dIly2a^k#}76yg}hK5E!(jZEl*94hskU)<8E?DdrHxPx`&lg&p zT4acDLF0U6KQpp2FgNxx7&LY=H8wK5j(g3g)yE}XQPdiAc{%M?Pcx7gSvqGw> z-R>LACno;vatYdBA{}&?VX8!#+k-O+0H|1aF*p<*XGo<^yUGe?QYw4SB?DRP2 zof5Jyds2L^iJ=CtAM$zbQ0;S?%G8&!Qf@lMZlu?_6Hz zr^j|@R)S^TxiZZp&)T)>d5kMVmkJs22TgFC^!?tsO^k*Sr*E`g^w6x#dMG1PxZYNd V*KKNf_R+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-GBf+14BIn6LDTkO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aNuS z>VBzHdgX)WV&=w1hKaH}DmTsFNl^n+BR zPd%1Zedp@`{9gMe#@QQn6a)-i&Py-NdU$!=$AYb{eLs$L?pbzDP1wir^Uo8{+~&%< xG}~R3Y`Jsi)9rufw_lMIn<}yI5Q|rqg3biZp0(UOMfE*-H@d2?`fS_w3IP28YH$Dm literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test37/Intermediate CRL 2 PP.01.04.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test37/Intermediate CRL 2 PP.01.04.crl new file mode 100644 index 0000000000000000000000000000000000000000..724051124390034d35b75627d5a4c4ec008597f6 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-GBf+14BIn6LDTkO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aO1^ zyx#sq&_ol>#mtS341H5IVl}?V)?J(3V=AWN$hzjloaBX`tbarPwiTrPocim##Oms& z{Y^jgv&yG_dt#cx+-%zL!Ry!4#~w#CWH?*Z)fF9bx34`oXNOVhSz)8P&xgdX`$=q! wo#ox`)tBh#Gh?&l_3-0jI-P=7SdHzjO8ZRu+k9W}&m-3j3Q2bQji=WD01G5#!2kdN literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test37/Intermediate Certificate 1 PP.01.04.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test37/Intermediate Certificate 1 PP.01.04.crt new file mode 100644 index 0000000000000000000000000000000000000000..26b6b96053ecfa7dda9870551ece15646a54faf1 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6Qh>_FB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%Nl?+T*-FL5tB+Ne{iwq;i@Hzr40Y?eBf8h zqqHs|J-zR^V{{LH*cZbig-@NmS1N42=~{4i+OO;;>HParOGE_hUC+gPdYpeNeDr`e z6EhYQC;*kIQ5;*@>AZ;JD4+j_{QHqs g5$Z+%_wDVD+@SGq;<6cK^IVD&^LY-u<$Y2L0J9O+=Kufz literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test37/Intermediate Certificate 2 PP.01.04.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test37/Intermediate Certificate 2 PP.01.04.crt new file mode 100644 index 0000000000000000000000000000000000000000..c0e986a08e0184b8cba0176bbfb5355169d2d6b3 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6Qj2QFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%~EZp>|;h&2Ij_I z27|^n7fkr2Zq@ z&bUq4GFk7{o9%9!%?k719@{CqU$?sC@6~4=uk~t`%-*hpy0ZKr0Ty7yv4LYnR)K}zfY*SVjWeOmgE5tv(SXrF5Tuchg^Ptl za?R`QPXtXg!O@+r(>^OgPuM&g}uC+3$&0+oKMDsI|O& zW?e6HYrW{wzTPuRKb`Eh{OMELJZ+!6h05o2l?sOKi=2<=2Ft#cPbrBOGx0r?HS_(u SU5{24Z{N>Y@Ns{Bj2!?B3D39y literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test37/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test37/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test38/End Certificate PP.01.05.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test38/End Certificate PP.01.05.crt new file mode 100644 index 0000000000000000000000000000000000000000..9331b90a2e65f6bb50fb9036fe6e381c28eda96d GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iP7JHmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*jz+ox0eS|8dIqKja^k#}76yg}hK5E!(jZEl*94hskU)<8E?DdrHxPx`&lg&p zT4acDLF0U6KQpp2FgNxx7&LY=H8wKrX`G+fwXdmH_VjiJr$ElFeJ8z~ihrr^l@e%7 z$v)us-k|S&-^v&6C#RPtTzmH3S?qo2vuXcN6ok!>dD#%yJ7?Fc`6pH%luvreziQe$ z)tG%@UK?JqE#x}3xsm6GO1M3DnRUIqUiAv^C9JF7FX0g`Zat#%LG8$`+Y64jad>_U z)QDzcW@KPo9Appx4o+EqM#ldvEX+)-55UnNtH8oymoTS3I@+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-GBf+14BInQ*mBPO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aVn6 zES`1d21hZPi(@@;++)7Re|8|px*3yIO){pI zF82Irx65+R3d=;h&5wHjJYPHQ;e)AsuU`u8`owr+>$D{6m1@V`LQ;gA3@shcXrE)r^8K1*vS_-C}PI~v@nCYMcN7 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test38/Intermediate CRL 2 PP.01.05.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test38/Intermediate CRL 2 PP.01.05.crl new file mode 100644 index 0000000000000000000000000000000000000000..ae1d7d5e8fe0aecb105433de406e4fb13785302b GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-GBf+14BInQ*mBPO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aM)2 z)^{{D&X|GbV&=w1hN*L{+LQi&zPO(2s;PEpZcgzT^G^o?o3bNI w!C3Rkt!YQ4?cbG|^-c~pv{=jIEPVB=e7mfx=pvJJh8F#)r#AjOY#clb03ujr1ONa4 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test38/Intermediate Certificate 1 PP.01.05.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test38/Intermediate Certificate 1 PP.01.05.crt new file mode 100644 index 0000000000000000000000000000000000000000..c8ee614f43411d66817d982ecd5a498d6ba6297a GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6Qi#IFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%iMTt(~7mG89!b8iFG@3{Q({W zWy>u-zx(TB>chX?-Y&h?oFUWwhB&8ozTd^*w#(kB|AG@#-tzgmy!p9qn`7Sb58^fL z?TjC}n7VuS7{9UaQ@tF&e@~gLxXQuLB9oGT6nJ+kG=J!in8&(XJxD)xVp^O%XU#<> zW=00a#mNSV2K>OFlNDxU{LjK_zzn3op)1P|5?}#F92+=RWEEKW4R{T>**Fv0JQ!1% z84VZ>1VI}4Sh!d?`VK6fb>;>~F*q7zm05uC)xfcO*6W{#o`>`!hXF9wnSq{#E{2;3narW%~EZp>|;h&2Ij_I z27|^lSU=E#ziot|99qWVXmQ>V85p>lMHFxl#N_rtwa)nf!a&2EWb? zie71x7wyQK>(Wx6Hn;Uo;*PAlPu(?Nl{B<^CPD`S#6etTbuNmC%pfen_9MHsz>hc*QVLdb7Ff;#h)@UGcqtPPBut1;0Fes ztS}?ve->5)W*`L)U0HsR01GhU*ub$OtH8o{SG;96ft||j2mrd-f9Q`T$i^>f8l}Cy!>rjT)t_p zN{^eAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/End Certificate PP.01.06.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/End Certificate PP.01.06.crt new file mode 100644 index 0000000000000000000000000000000000000000..57263d4cb1b865e793e7a2a7d4d28c84d3f32805 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6JxLeFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%~EZp>|;h&2Ij_I z27|^cq(k96)gmUBFOSPu8~gjXebPk1fQVj)qs?T>R%d!_5| z<*6Mq(vGsrD^E^%#xFN%rI_iyolACBxhT6$s`gxZd(YvC)AE^^85tNCCmSRh@B@QR zR+y3TKMSh?Gmrv@t}H)DfQ6Zf^#M3mWEEKW4R{T>**Fv0JQ!1%84VZ>1VI}4Sh!d? z4FBJAS6iaZ0geV)Wfow3HE>+&G)ffX;9ra!2EbTn26~>4%iYDo$nMdO((}u1&E*i- zc!go@tBqG~o)LYM!K*#V(==1!#0wL%Rct?swuIa}70}qj$h~Po;{Auq4?VfQWBSYQ zq5tn_On3O`lMyxJk;A1YsqfcI9Td>6Z)XYcblsVJ_Ji#Q75CFGL>IU|<&5GN{Zgn~ T_Vs2O&r$Oa3uGk)ZVCec!$Zq1 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/Intermediate CRL 1 PP.01.06.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/Intermediate CRL 1 PP.01.06.crl new file mode 100644 index 0000000000000000000000000000000000000000..f2a01385e5cebba4c715db163b62cb2df7e97a2c GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-GBf+14BInGjU!^O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aQgZ zS9=8=zTAlBV&=w12A6$$ytD5YGTg{2xqs0AVFZ(NiSh2)y9849Y+vkrd1a-_jp=3k z>w9kciXGILV41J8}QHO*i00L7hXoB#j- literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/Intermediate CRL 2 PP.01.06.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/Intermediate CRL 2 PP.01.06.crl new file mode 100644 index 0000000000000000000000000000000000000000..b6672d85a046c2816274b562480e9ae30aba85d3 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-GBf+14BInGjU!^O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aM=w zr26>GTzVDF#mtS33`iWL~7q%sG1xsBC1f z=O~>P=_Ebf*LeD^mV|TB|H^CQ7evpjy}4WIhW%3}hx?}P0cCoTOBwf`&Uxs=b!EDI w@%2a3Cj~6JkzpF2yP*5IM9$iU^_Er>F7{vhXO?I6MEoODu~pICccyDR0Q@~?6951J literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/Intermediate CRL 3 PP.01.06.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/Intermediate CRL 3 PP.01.06.crl new file mode 100644 index 0000000000000000000000000000000000000000..453420be8d2426f5aa1c81bc9ffeb1898ddfc315 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~m z-GBf+14BInGjU!^O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aOU> z8YPNx@GnMlF>_-h!}970ezon~>w?8n7N7g^&g&BAf$5@I!ZE%XZDrRlXN6@O-ER8! zRl#X3*HtE|x6DpobRRm!+VY2=-I?eS!;rtqGNzAFx_(B?Ru3ji|!Y6k!S literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/Intermediate Certificate 1 PP.01.06.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/Intermediate Certificate 1 PP.01.06.crt new file mode 100644 index 0000000000000000000000000000000000000000..b7003f7ebd9a6325a2a9fdd249d5f7457ba9848e GIT binary patch literal 706 zcmXqLV%lfW#H7A}nTe5!i7~){myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HPUF%&T1gYeixQj1G6^U@7P4TM1= z%)&e&MWw|h3XXZn8Tmy9a^k#}76yg}hK5E!(jZEl*94hMp8Y9!?RR!G)C~yGGceRM zFf(YJkL+VcRtDzAUIv54PNv32hQ$>V3^M1+9A3QpmGsu9WpfYAn7pAWCU%Y+gUhQA z^_d~FttZT=eAo2S`ls7x!#!VF_BKZuA6?eQn=N#*n)%${xD}?6%|${^@1_?lciw%_ zppoImT}8GDa~nD@=2cggOz;u>{_5?fr(Wfs{{?I;ZB5rWv7vq=!_V^v*DEQUIw_DO z&cw{fz__@v+n}+-fFBrmvcimv|5;cKn1K{Hd}aAT0xZC&V>7S?DNtZBGcYmWX5&m~ z^I%M6W;9?#<}e|1n2|Xw27(~%d@Nin9JSr6y@C#3ZUo1dtTGEQVjDPC&wBmy(DRUf zD}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uAc0eS|8dIn|&a^k#}76yg}hK5E!(jZEl*94hM8~cqA_BYN)_Aw(X19M|9 zgF#~_Q)45;9^PFu0{@x6yCpVNlFxz9e_GcJC({|rRI1)9PU>ZR+5hor*^?WhdRnz^ zr@0J&tU4Sbe`W&TF9oF(gC}P_9A1ksE#5V=v9NEcSmEiujFMlmU!|-L9G2Vv*3tXn z`J$8S)jIT)pPC+F{m3z6*^4vRUWd9XX3q3F!xX$e(xLY5`Hz82%!~|-i)#(44fugU zCo9az_@9NWDXNDhuJ_7 zq=S!zi-kkrNUD#|%%xYs5hSb30*uK9j@s_kUO|U1HzJ1)Fg-8>gN0k|@~h<86D{U% zb8NXcsr*vlSq1JL-~XO`p!CPhzuxkQ(dD)GCik{1`W?G(uir(}yJr+<8DHzWxHLud zh2GDr*?wZrk~+&Lyq_D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*jz+ox0eS|8dIn|&a^k#}76yg}hK5E!(jZEl*94hM8~cqB_BYN)_Aw(X19M|9 zgF#~_Q)45;8mC2u7uRfD(r9CPd(N~^TX$|dJF#Z{dKc$ag?)=v9-la!URNWSdoo2t z*|BtGWK#P(-{dcAU#(w}wT8`pqIdPIa~}?_j9h+UE`y{*x5Dmavlv-jW*K~FC~dvn zoG{DTXye7DUti|rw%`48_GE8&c?SHz zppzA5Wc<&ZRtL<^4*EIe$O~8p5FViRPhR9K>EEoU+Vu&JD7BYYke;J z{-etzw)kt!6U!8wuWi&gap|5NI{NX^OFBgDJdTQ6^hmwA%MiqN`t%&`08T{JX#fBK literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test39/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test4/End Certificate CP.02.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test4/End Certificate CP.02.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..75d2fd50e37df29eefb90e7329023a77ab64b768 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iIKyAmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*jz+r90eS{TdIp9Da^k#}mO$Fj&}6myGXwoPF{al0?-n_&KPyh& zH=4}m$IP`beA=Rjk6roZO3pb~tL9y6IwpIkIe>51j(7t*FX0tg_j$V?u&(pz_ULr+ zJQLM1ZIAkn*ZaG#?p?6$i=$C|bfLtLi@Wbl^A(%l={UVKPqS>b{bUoHB|j~*&)z(I X+Vtu1y>T;@HtblJv`taVBeo6zbCuLb literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test4/Intermediate CRL 1 CP.02.01.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test4/Intermediate CRL 1 CP.02.01.crl new file mode 100644 index 0000000000000000000000000000000000000000..2f30c77b538a33291011b469476c08e0e810b7ab GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zUFQHj10y{HLvdb9O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aT`j z#T;FbRrUhS#mtS33{%9WhW@&_>d(ZM)Uyc@ORld^XQ}9|Syk}KH=-dxpyHbB%rA3R z2er>wbGYqH?L_XlVgv7Y(fJ)q&fZa4nwoD`9Jj3Yo>8)_>a&|7pFImS6fXta)ZTuz xdT+-iqgQo#OV)HBN?ak+SikIx>ZbXp<;uh6m|EyOKDO1p@Z+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* zUFQHj10y{HLvdb9O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aNj8 zs(B?mJ3AH4#mtS33@wc3ouy*dnw-6mde54RC+>;Jf@1w@Lrr6c2+N?)%0;tXOJ{vk zovCo^@7E&%`#R5TdAOvd@q4F^km+va8S(D%Q}xZQUer9DwRNfgue3Q!w0ozl<@K&9 vR5O|w@t~GFNc!E4NnTsD6u!%}1y=2A|8#@ti2hQY>`>v*X2mmU>Y-Bsj2~n+ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test4/Intermediate Certificate 1 CP.02.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test4/Intermediate Certificate 1 CP.02.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..f4e88d58cc91b46aa1abe84f839a3a4008b1095d GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6C;}eFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%E5)Jr)K_@HB$oQXy)qojDfkRi8A0)s6j5s!MtjH>`@Eh;*U)WR+Qf@zubwde-Zohn|P@BZmPn)|r8xw`Bg_ z>H1sjQmX#V_q!YGKJ}k{_UoU8>>jIQH@4~~^5@ckHj{3ZTBi#JN25S{@7qbgzmFF2H f6tmm#+27Fabz1AOJABC&mc37m#E{2;3narW%Du|VR|#(pD&{f+aHeay(pz}(o& zV9?mf)Y!gzq3ugtA~VPZJ{mv7Gxyxw6JvLj2P!|g!vH{ZAN zd@_A^=l#!Q{jGn(vwC*I)dkzq?cJxV8a^(a6MfZ&U#_L&)QP>jYr>{{N%-}@P4ZJW z`z`NF`9f*()m{~HYbTjL=6mm~t1_|Xk>u*2B~s#BlhZa7`R-(5W@KPooNSP2zz+;M zSz$)T|17Kq%s>hpy0ZKr0Ty7yv4LYnR)K}zfY*SVjWeOmgE5tv(SXrF5Tuchg^Pt_ zL9d!u!n3ne!Ot{PSb1P-kyD(}Ayvl{ z((y-Lv53Ux3ZGtAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/End Certificate PP.01.07.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/End Certificate PP.01.07.crt new file mode 100644 index 0000000000000000000000000000000000000000..24ce9e4d805e725778b358dc5d5b08e252419f78 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6JxjmFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%~EZp>|;h&2Ij_I z27|^U8(rObHatyXMfF`8T)FJ&|SmR zm6CDa7kIKg-M9SRjqm@2Onr9LGZ$T0vc!)ettj`FZJi%~w*Rj1RZIUmr+ZCj&^%pV zU!-3oxZ+!ZTbX{8@QZ&(R`?h%v^i#5r+V(@Wtrb+{OneW-AiR+W@KPooNSP2zz+;M zSz$)T|17Kq%s>hpy0ZKr0TyN^)(7BNkyT*fH{dnkX5&m~^I%M6W;9?j5Cm!DW8q@q z_^(%eEBxY#I&d_|DzgCNtAQiHXx%$G7w5gmVE~MEW}xTI;)_cT&CXg|Ve!w>_R(Jc z_P3VWOFMJtc1JbD*Rwjc_9tw5kzs1$9PjbG`Ec@A30L`K4a?GqAE7S~{ChopR@sfd z)TsaM0kfh%e)Nmd*lk>KKITx&f!)kvUW*@c#B8pq@3C%KbTo+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-GBf+14BInb8%ivO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aVW; zggg~;BcQvF#jC$u*0mrg5f(qBrrNB3!KO> z?5nc~2{mS1-F5qU$nIT>v=SAo`ZvVtR@O#_crM)j#HCjE;(_#?>J!{;?@Zd3&Gq`z w(Y@yd_P)&hD?eHSf*yZ_!<5&QI4mEbR>#DzN#JUXfi01CHe_y7O^ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/Intermediate CRL 2 PP.01.07.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/Intermediate CRL 2 PP.01.07.crl new file mode 100644 index 0000000000000000000000000000000000000000..dde5a124c9d4ab9279ebaae86c1a97ebd5a9eeed GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-GBf+14BInb8%ivO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aO=X zF`8bSaLxtI#mtS34E07EOsbw z=&QNeO1@IPS60_I^i7|8dAYa3UN63B`~ny+_ZPG;-1(tuuA@=E@$_`ncBjoYJpmr6XRZjml=ESI`ihmQ)459y0FXdruK)l5 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/Intermediate CRL 3 PP.01.07.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/Intermediate CRL 3 PP.01.07.crl new file mode 100644 index 0000000000000000000000000000000000000000..713fa4bbf1fcd5c90a3bf892fa3ccdab0cadb423 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~m z-GBf+14BInb8%ivO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aM)s z*1eN+ao&sOV&=w1hW`CMf{)~`WOgpy5+b(j>>BIK&n`aJWacg1zBBn??QK`f?H&uR zdR1L=w{AOkT7KT6m-4T6d|r7fZLd(j-+CZxcGb*rR(g=~^bd~n xCOrA^KzhF9^mNXy%Mp7rc5e-3Tx4L$sa&lgY}7Sl);H~sv#;%+7UaK{4FDfHXz>65 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/Intermediate Certificate 1 PP.01.07.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/Intermediate Certificate 1 PP.01.07.crt new file mode 100644 index 0000000000000000000000000000000000000000..5a8ac50060f0c3c96e00c5feacceffa3fb18e5f5 GIT binary patch literal 691 zcmXqLVp?y|#3ZqRnTe5!i7~{0myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HPUF%&T1gYeixQj1G6^U@7P4TM1= z%)&e&MWw|h3XXZn8Tmy9a^k#}76yg}hK5E!(jZEl*94hMp8Y9!?RR!G)C~yGGceRM zFgIwNkL+VcRtDzAUIv54PNv32hBtTTAFX5ZJF%*c@4R6rgU{u;ccL{Ta_krUww}gs zdv}hlocO-WI-i8~cN8f5)!5a(jj7D9dekGf?ETqP1<|s`1(nO(Iz0NrSJg~WoR-wx z7c%37a>X&BtKGXFybntjy^?axpGP?GaNV?TkyX>%FMV=tv&sLqO8>EYb?_D5Ex$yW zm>C%u7uOn88}I{zPF9$a@jnZz0W**ShpsF?NPq(?ER11)4jE*!d8*FJAn7OU&rtE|^pbVA&n&9dK{|F}Ed z^u^ZWcZF3h8Rpsw?Q!o@yc6;{V)Y;9QNb&vJXjR%JPo|B(e#M=eP l)`^AthD}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uAc0eS|8dIshOa^k#}76yg}hK5E!(jZEl*94hM8~cqA_BYN)_Aw(X19M|9 zgF#~_Q)45;YU}?shwn8uPZRdbjxD~;{eiiGC0*k9q#EHc>pvMGw+^Wn|M*gNAzIkw z@q>jPT2sCGJ-5xYX%A6lxcr5!Q#W|^g3mLj?hmhPny$8;tM%_1lanXix#VW3Z;h?3 z3E+BuY{_P&rjq~3J-ed4P8C}P$^1$U`z5K|%zL)znNoM_<=zu zE6m9FpM}+c8AyRcSC$_nzygdoHUnjl0tFTs11SS;HqL}L55`nxMgvA<4wHc(ND&_k z7Ym2yJVw)t6VADS<3v`O1sHh^9QswlA2*s`VnGfNU=m;khD82_{cDv^bj~YveaqQd z;xxt7^zBT2=_|5A&o&<@om;Tq-F)}iKR=5(HaXSrin+VG?HOySF|$CJvy%Bdj?Jl4 zzb$`|%1|n}cEQa13pTgug~+?+`k9_LDHbm^wQ*l9ymr;pxeKPS%s*>=G3k}V2PUEO UHnB~O>ApJR*J8c+@>@#v0Drv6O#lD@ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/Intermediate Certificate 3 PP.01.07.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/Intermediate Certificate 3 PP.01.07.crt new file mode 100644 index 0000000000000000000000000000000000000000..a0c673453ea66a365f6779510ee8ee3b9a34cd42 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6JwYGFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%~EZp>|;h&2Ij_I z27|^>vS0|ONIZE*8g+5PV}(9{U?oo^B$h*Se5b8 zq4mNm=b}o^Tix%Cj#-wl{S?~a{<>9q&PlI4j&!NNI$`R$U9*@zy}NfhOhnn>P+8j9 zz2*-WFA~=_{8RP+zxG4V@~Xxi3!i>_+ckOqqNX#me{R0idGGFDCT2zk#>L47i3a?@ zppzA5Wc<&usmGoul-Er$%kh6+jOzq7SOVJ+`hN?*}0@l8-~Yge}ueT ze)6q_vrEXC$!*?NE?>RAq@GIJy)z^E>5h;ly-9(*-9cG5ZVB-|Jo0+ISw27Sg#Sx9 TcCAV~sd~hs;Pg{FpBOIymwVQH literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test40/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test41/End Certificate PP.01.08.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test41/End Certificate PP.01.08.crt new file mode 100644 index 0000000000000000000000000000000000000000..b88e38eb9714f61d8869462d04709275ca3bafc3 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6JxXiFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%~EZp>|;h&2Ij_I z27|^4m_?#GR9{4psj(_bd`&Xi?pYMzGFnKpCILbn<()8fZ z$+nY^tUYV;=lG*DN7l_WlW>dO+Ts@0X6*Ou35VRq+VFpTeqClA&)?YIFg!G6#blnC z=^HvvE-wg{2;^<(ZdINb*U)uE`9hkF^sgtz@9+CP>$!a~)i;renUR5Uak4?80Y5P4 zWQ7?S|Ff_fFas%Y=*seg1X!4vSRa66MOJ}@-+F@?QC$np>TPRvG*`WwY+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-GBf+14BIn3vpgcO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aQII zzx`mnAASnW#mtS33~fHb!XMcf-+og+Z@x0>;dREHM|sZuNu0m@&pY16?pwaa={c|7 z99yjU=itK93wM(rKD~14+L@h;r@gQ#+_H>)3w!@JwcpL5dgb5WyEA-SzR@{n&C$=6 yI}@%hS1wtdH@Qpb!zYOe=bz^AZBmPCbvSlc=|+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-GBf+14BIn3vpgcO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aVWQ zibNYy9y~{LF>_-hgZYAh4KBh@8`f{W{WMVB?GeZ2hMPu?26JaB$?W{)_2A%srq=yp zb;YVRNyduL_S)Z_P$L8E(b^WmBQ_|Epo@dc*d1vnOXxkR-c-AQZ0G2OlbpQYW literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test41/Intermediate CRL 3 PP.01.08.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test41/Intermediate CRL 3 PP.01.08.crl new file mode 100644 index 0000000000000000000000000000000000000000..d26dc1b750579935cf36212393c7512bb82060d9 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~m z-GBf+14BIn3vpgcO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aNI_ z$ES$z*IJ6^V&=w1hDiw@x4-)NEi!Y-%4OeDCNKP7&sw|MTyd}NC-(O|atkc>=DuB@ z@aWTptELm?%isUGPMCN7JJIHKnzk;F4vUrj_dYBUYODHa&oVcuoR*KJJC2-7OFtQ) xemVZeiA;^+ttxX?9-L(Fwq4NuFn^rjb!EL<(^C!3{+t$QGBx&H{r4$mdjZCoYi9re literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test41/Intermediate Certificate 1 PP.01.08.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test41/Intermediate Certificate 1 PP.01.08.crt new file mode 100644 index 0000000000000000000000000000000000000000..4b96b2afb80c3ee53d02499846ffc3bab5abcd64 GIT binary patch literal 678 zcmXqLVp?R-#KgUTnTe5!i7~=}myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HPUF%&T1gYeixQj1G6^U@7P4TM1= z%)&e&MWw|h3XXZn8Tmy9a^k#}76yg}hK5E!(jZEl*94hMp8Y9!?RR!G)C~yGGceRM zurO$xkL+VcRtDzAUIv54PNv32hQrml?0V}ie%vb`Y0c7cwLE>2wA1mK9~q|o4wrtd zY{#^zTgCGF@iWhSO4=Q?3hv~6Y{@oc4tqP>U5I<~|EqiKCxou?*b;Z+qU)=sDZjVd z6)}kzNE)B4w3{@w!BOmY>#?7gl;&zg`+Z{Ol{jEHrNra%{I6RrikQyl?C29-FLLQC z6Eh#$HK+J5tIGx2kZUtQ{Xs}Rb~N3UIWMKS+9Q{dLGh`93a3Xzzhrt zvFUHkr+Rjp8IO5By|@2xS!TyhwVuDty4|9(Jimfv9{DDi$AzEE z|IMFKZSH+@8be0r?``2uulzN3t^d{Xu+7tcb4O87qjB>`S4W30{(BP*ni5Vd+xdBI jNb#qQyLPQsjk(dtSG#E{2;3narW%~EZp>|;h&2Ij_I z27|^fKlC z*ERMp{r|Z3+rLwLBqJkMFPzNgEc~h=(fGf|<2RA-8F(j}b@FLiMR|QPS+!-#T#E{2;3narW%~EZp>|;h&2Ij_I z27|^$o#9GcqtPPBut1;0Fes ztS}?ve->5)W*`L)U0HsR01GhU*ub$OtH8oMeT&Pp#Wm+xDred|^|&hC|P;N1JoaDveHb T9Mm{DXK(!1wbx3Ie*OUfa(UF3 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test41/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test41/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/End Certificate PP.01.09.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/End Certificate PP.01.09.crt new file mode 100644 index 0000000000000000000000000000000000000000..9815c5d5c56e0b274fafc6e7a3aab32c96c327de GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!i7~-|myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*jwZSR0eS|8dIpvTa^k#}76yg}hK5E!(jZEl*94hskU)<8E?DdrHxPx`&lg&p zT4acDLF0U6KQpp2FgNxx7&LY=H8wKr=0Y35DhE55i*HhFmUyTmoV#S2#%n17N}l(;Dv7`)UsclAdtc16wa z4W{?kiM8kYzBqK8VbkK?VWf;FRTOWc<&TI6lbxuYBJZ55qgq4MD(*EPo_ueD4kdw)55+UTLwf)gVQV$rctQ@C4iLC(u9k9$A literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/Intermediate CRL 1 PP.01.09.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/Intermediate CRL 1 PP.01.09.crl new file mode 100644 index 0000000000000000000000000000000000000000..d4f21dbe3274d46e315fb6394f367fe5a6925409 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-GBf+14BInOL1OHO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aSr9 zoVvNA#5xSk#mtS33=`a~RuuL{PQBsF7r!y5v%x!0U9)D#`~`+5mK2;``&5b3*V^y= ztL+C*M)1DA{MpvWI4{NYhQTSeulbB;8S**ar+4sOoUgZGp*XAgs@Yc!4fi&DLW_?N08bxj2><{9 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/Intermediate CRL 2 PP.01.09.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/Intermediate CRL 2 PP.01.09.crl new file mode 100644 index 0000000000000000000000000000000000000000..32906057a382748cd5ebf18e7299f4a92ff7f13e GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-GBf+14BInOL1OHO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aS90 zXC&ABTKWRb#mtS34B?k$KYZ(5&>8$T$zblwthIY|+}EvVT=M5|h2F=48*%S@EL$Gd zD+&hvc7MUDEt~$x?Q6@KmB})-2OVT3H?EI7Uus#f=Va09EZ(!J@^fz~@blC~-8YQ7 w;Ssmz(b+v>nligQ8=l0N|K76QXKsz$x|dUGgt^p1`Pa1FpOItFuI#rF02uOTGXMYp literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/Intermediate CRL 3 PP.01.09.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/Intermediate CRL 3 PP.01.09.crl new file mode 100644 index 0000000000000000000000000000000000000000..ee2b2b18c06419cd14ee2146d98624a6c004b1fc GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~m z-GBf+14BInOL1OHO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aPhP zimT7+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}r z-GBf+14BInOL1OHO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aS37 zofFce_qr0z#mtS33`^&x9-h*<(BHUXjrcRG&?rS$vCig()x6U@#h)eCe2Qg!abiYJ zR;N-Ar|b8Q>C)#d|8D6@u1-H${=p<%bUCxbKciv|kb(JmvVUiHXT296S4OXXD}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HPUF%&T1gYeixQj1G6^U@7P4TM1= z%)&e&MWw|h3XXZn8Tmy9a^k#}76yg}hK5E!(jZEl*94hMp8Y9!?RR!G)C~yGGceRM zurz3#kL+VcRtDzAUIv54PNv32hLbB*R!LcK+?mQ*!+(8J6oVD-gssyXq~L@sck+{>ZGGJ9p31?pv*Ex2?9`ezHcQcHMbkjtfSZjoq0NIa zm6_3i5t+k;%waYV1nJ;o;bP&K>T>GljuPuIa0JOJvjAhVfn)Wo*FO(E59vn^9bkH3 z1_sN#t#kIOoVgPAeUgpue8)a{*MNnmKFNG5XnD-`xveDizIh%?X2U_l?6+6KJVKre zt&O?4ukl$?F1O{{2d{4}{kL~Rr_bh!sn?e`vWHGKQL{-3(3zK3z50XTrMvp^FA`s} mR-L(5xay^!ahpxiF_+^dVd|#!dWM#VcXsV-KPc#>D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uAc0eS|8dIpvTa^k#}76yg}hK5E!(jZEl*94hM8~cqA_BYN)_Aw(X19M|9 zgF#~_Q)45;wLr_@&R0rr7aa?1ZfIJ{bYuQ6)m7&rfB)Fm_VSPc1E2K;sTKATYW{B` znE&sc`LKO{$|4uhDTn8_KRcbZ@RdTu(bK0l%)(B{FI%FJlMh|FO!5CkdW zW8q@qU{;)wT=Q$`3vissDzgA1uYqH#%c+|?O02_>0|b}^n1La&IeC%eYQNGoc6DCs zg7-C-)NEnw`R)|JXZ|{CPMGn_vp=tjhF+ZVns+6`1Ff4L@h3I#E{2;3narW%~EZp>|;h&2Ij_I z27|^usyn~gqQ=Rw&wQTp{aXUv?K=d6eFN_wI#f7!cJeN3zp}V0_OmH- literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/Intermediate Certificate 4 PP.01.09.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/Intermediate Certificate 4 PP.01.09.crt new file mode 100644 index 0000000000000000000000000000000000000000..5b6ffbd4e542ea441bf15b1e9174052ab824ab6c GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6JxvqFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%~EZp>|;h&2Ij_I z27|^lUB#{nK6MXK!n$N_{$iTQb*&xw?9~gA9 z!i$ZuK_n3XF{6?V=6PF0i%H+NFyH$7YoPI zqjN%<^j=qjqd``g1sGoq9H(Z*)#vujGDHpoV5~C(JzwM@dOg_rk8OU3i0(zq=71AT{BQ-Tg|tpVA7= zU3N-oS@)j?70pmrNBG1%(wE#e Qd7&bdZn^sGHdRMo03K7zKL7v# literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test42/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/End Certificate PP.06.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/End Certificate PP.06.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..9465ea5bf8c1866522d21cd4c6890ef6705a133f GIT binary patch literal 626 zcmXqLV#+gUV!Xb9nTe5!i80lHmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*jwZSR0eS{zdIp9Da^k#}7C_q2&CNcGW&$5Mb2_MhLrbc4gx#qkotCiCVN zvEF84W@KPoY-L~p4o+EqM#ldvEX+)-4-5o>o{{Ba;bP&~@1gK!kF)V>aQMn9vj8Ka zf#c+CZnHm|6el8k4H%uwKtDBG7P2Jvv3>k-+r96swt>;A^+BaiEP_W9uCn+80`UcdhHW08_g-r5I3X8`;? B%9sEE literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Intermediate CRL 1 PP.06.01.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Intermediate CRL 1 PP.06.01.crl new file mode 100644 index 0000000000000000000000000000000000000000..4ce26fdb9cead5f64d4e9f03e5fc005322a5ee9a GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-GBf+12a7XLvdb9O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aUeA z^d;P`@3BX7F>_-h1NZjzcFVWyeJcLju=48tvmJR;4>1~8{B@sh@PFfi=YPV)y{=r~ z=i)dK@htt$mlGR1GJ{O5FNB2{Ob#wP6ddl@yw-7A?`!3fr)DeL*0zLr%(r~YY+L+s w-~Xp2G4qc%w3mPRJ-__Qi~P8fn9DlfWcl~4c$j3kHHXE=bv-A0(_~gZ01FjqS^xk5 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Intermediate CRL 2 PP.06.01.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Intermediate CRL 2 PP.06.01.crl new file mode 100644 index 0000000000000000000000000000000000000000..9820bc6f6b44f6db67c4302937695ce2af2d4ce3 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-GBf+12a7XLvdb9O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aPyb zSFKp?TG@!^V&=w1hEBIfD|xT~6M4`l6(C`j^nasz>ZwUh3am!kr{4E}mi4!HYrzR0 zf9I8R4td`x-BXbHKp@ANO?2PX_qrhq=AF|NXQ{iG5%cTvi(B?Vg^yp|JH)hUWn83j xDc|oE_O}jJpRrzIT+#Hv^2@S&livM&qRjBL+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~m z-GBf+12a7XLvdb9O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aUGL z^i17l$kB-AV&=w12D2Xh`rk5{PBtCGV=l4O+V^=9^CG5-+~rFyn@eP{(YeSXra_g(rQuC;mykQ?nt<%od5W!^0M`=UDokhul94kpT~b9`OfLB=Po6-a#&ab05Mf%TL1t6 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Intermediate CRL 4 PP.06.01.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Intermediate CRL 4 PP.06.01.crl new file mode 100644 index 0000000000000000000000000000000000000000..4b4136209a8e53ed951386e3d5f9c924a13f042f GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}r z-GBf+12a7XLvdb9O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aPhQ z<~IAYNpT{Yi{2t!sy6lll8rbKQGTw)8;BE}z9O xwm(t8pLPF}t=Rco4~lxVr9GXO-NYqS6W literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Intermediate Certificate 1 PP.06.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Intermediate Certificate 1 PP.06.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..e18a4e1688ab3ef3948c8ffdbb33a7a1c83a675c GIT binary patch literal 679 zcmXqLVp?p_#Kg0JnTe5!i80ZDmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HPUF%&T1gYeixQj1G6^U@7P4TM1= z%)&e&MWw|h3XXZn8Tmy9a^k#}76yg}hK5E!(jZEl*94hMp8Y9!?RR!G)C~yGGceNw z+SoWB*~g5m49tza3 zvz6zCjXf?4${*EDPw4tlT60w8SJKYJRO1Wz_LaBRX>Lli5xE>SUt`(9%|0w|e73Zl zbDAA;;KJwb++#aDqoS_5Md_tl9)42A9rSx~a-;0Yn_ZhMeg#O^Z%O(ouuAq+I?Hw@ zW=00a#f1j>2K>OFlNDxU{LjK_zzn3op)1P|5?}#F92+=RWEEKW4R{T>**Fv0JQ!1% z84VZ>ct9FeK)MJVenURaM`RGhOVzo}c^WUfpE72Y`zbqfsiEY@lM}qBzc?@t0I)~WG5`Po literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Intermediate Certificate 2 PP.06.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Intermediate Certificate 2 PP.06.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..1521fce98b72caace22e15dab50da6483a7e368e GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6JwGAFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%DLFUrNej|kajq{Ox%*e{X+}O)t z(Ade;*vPPL-RwLUpNEnkIq&*&=zPffZL9Nh*?gl9fpW8!bWM1bqxb&1RY7ym)(>$! zNeaSCKCskYlv}oG&85`&Wv^Mk7i1WSrd`)Hc4N30aJ`6qVypEDo8LLT0`I!-Z#T8) zI-^&8GRtk%!EMhEh4U1w_Lgh?`t{HHN*0AD#>pSkxzcR^zGq@)WMEvJY>;Tc4-7h4 zVMfOPEUX61KnfhXviu+c7GT7&fn!Bhfra0I*MOUiGoj6cF_oFofYCq@q>+z>i-kkw zch!pJu9c18XpmKA0mfGYN1L0zgxmE!_Q+uXjCE$9=O+ZYnVawZzfAnC^dC|AjGVv* zj;3m>JPAjZu&>FsOB^0(MO!yt`zsXgd1O=H)GWb;Z60ekO3jYXUAxfCy1a0u_#E{2;3narW%DLFUrNeq)6Fjq{Ox%*e{X+}O)t z(Ade;*vPQ?=$}Q;GYtOE&VBtq%7pc9a*bp{ty|}xV+-!dG#}Re{jPAPd3JGv?f+?y zGEGIfed>+kmd(CrV#1$h{82;bolsfvx1!BX3W3+m!i?`8%1xNJXN}j9;3r#}%A^t{ zHkf3DF5$TPBlz%o$AwMvvJ?5XR((*MDc#EuBeC$P!Dq)^s!Ys`42+AD4H6Cbfk7uL z%*gnkh1Gx=NP$CFmLDX*0*p8|aIDBGu<#r38gR35CbW4lrZO`cFd7JgH1e@6yCAkfRYC4YJBC!1!w5Q2AZ8V!3N&BXSr3W1Si3d7qmX4LR5Qi^O;w<$g46XYPx4 z@kxfKKhIBTP*u&YW&CvQ*2QNfY;8*n7y1;SFrES$2zwa=;jFf#^BA&=P-@kArZ~U5qiwl(JTo0&R8J9SpgIV}PQJQR> PWvYyOx1+#E{2;3narW%DLFUrNeiMZKjq{Ox%*e{X+}O)t z(Ade;*vN43^$PEF*)Yiit7g1$*Z%clYw^m$Lje}D-S@o0?1RnHRM*vd=;`xW#%jc_ zdi&Liv+c0|hi@+oPT!m5vVU?{^y0@7Czyqtvi`-y#4~SCG<+v;Tc4-7h4 zVMfOPEUX61KnfhXviu+c7GT7&fn!Bhfra0I*MOUiGoj6cF_oFofYCq@q>+z>i-qIl zY;LnZn-nL4qd``g1sGoq9O-v@rtUK2XhaSJV5~C(JzuMU~q z7_DLay!rJ6AtrPFdr}W)%?$E!b7Qiv>HKhYM{ob@dYMz&8dur-A zvfxF>z0DPWw!Vn`ec^*3*TtVH@_(1RE1gOIUuSJlb;%*_kh-Dm7VcdPuXo-H+Nk^R R7x%vi<+Y`Y_D+}{1OOtY&Y1uJ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test43/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/End Certificate PP.06.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/End Certificate PP.06.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..5fc9bec784bbf17476b7f271a5855847978c7182 GIT binary patch literal 626 zcmXqLV#+gUV!Xb9nTe5!i80H7myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*jwZSR0eS{zdIm-Ya^k#}76yg}hK5E!(jZEl*94hskU)<8E?DdrHxPx`&lg&p zT4acDLF0U6KQpp2FgNxx7&LY=H8wI_(0(MCvb)Txr++>FqF|SB>y%A@xAX+RIknI6 zz}>Zi4?J8S+Uz}J{QrAO=$-5ui?zj5LU|fYIq#fi_PO^)^{ss}w=?rCr&_ziZVr2A zJ06+UTk-m+oyncAt{d0QT(eo^l8nYoo{{Ba;bP%1kiKBwVskhZ9KN#3EWn6p z;P`uK*^b`47rn?{14bt^&`jwPb>nU98!< z{v)nuerPtfE>4{jCbNDk)7Arj;@Orh{nPh6JD+jt&WR~pn`KrUjLtcBM}_IeufM;u z6<;q^ILmll;#16Q#hD?KpS@d+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-GBf+12a7XBXM3!O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aOJm z^4Cr(&wY;OV&=w127$SInrCb}T;{jxT26s%dFQK# xw|}P05;R_B8^tR>eST%N@V;xu9pwtXPx`j!ddr!KM%Usl{X4cM&`V(7G5`S$YkmL# literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/Intermediate CRL 2 PP.06.02.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/Intermediate CRL 2 PP.06.02.crl new file mode 100644 index 0000000000000000000000000000000000000000..780ef7c0f57d6d8a3b352d9ce5ca33dfdb64d9e8 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-GBf+12a7XBXM3!O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aOn< zLLdFOZ}9}p#mtS33`;g~#ed^W5}7}LPqz=JS6@Y@d_QHcb z#p~K6|*|m2;ceTR)=~ZGz wHR0S{iD_o#Y`&E>suBLzF3FmP-gkG5p0g#U*l|%nDMM5_|Mk_@r>E-x0NJ%>q5uE@ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/Intermediate CRL 3 PP.06.02.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/Intermediate CRL 3 PP.06.02.crl new file mode 100644 index 0000000000000000000000000000000000000000..5e5267ed9953f5995cf2d61496cacb251048c93a GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~m z-GBf+12a7XBXM3!O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aR$@ z6uOusn#zXeV&=w12H{Dy2PQS-SKkwFTqygBqgk(W&uQ(xe|O*B2>v;VYxNs`GvC_F zSO2H=y2T3x^&IPIa(WuOR=|AGTaP)>CyqF2D#fof>Z>*k@7h*v;9~M1eGX7yyW2c*flqAdd$q&sZFwA)h0F26L!~g&Q literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/Intermediate CRL 4 PP.06.02.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/Intermediate CRL 4 PP.06.02.crl new file mode 100644 index 0000000000000000000000000000000000000000..5d775f551545e503ca27eac40b637c1297cd9443 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}r z-GBf+12a7XBXM3!O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aV!5 zTDGG%??o?~i;WkXZ%Saq4~~g v2iLgE%1W|2NzKz*q4)Z&Lqo0k`^kClWcp>l&$!nU?D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HPUF%&T1gYeixQj1G6^U@7P4TM1= z%)&e&MWw|h3XXZn8Tmy9a^k#}76yg}hK5E!(jZEl*94hMp8Y9!?RR!G)C~yGGceOL zFfwSIkL+VcRtDzAUIv54PNv32hR4nGr$^2ayT)|DDm=&SL^NmR6t3*ju=6X@PJfbr zH}}RLuFYrWuD4&o?|=AX+#T2IIsLnK7fk7HaWg$IOW2R=TBU?(E5{1Pn)A_RDVei3 zx6RmBpfxYuxN^?#SK9GxQNQAAu3ZTXKeuz?=QEWHXGsX0oYpJ7$^FpOp6jkWXO3;K zW@2V!U|d{ikZ-^b3_4k1M#ldvtOm?L3LLt!{2&1qV8pS3V?|bhh2MbJfSZjoq0NIa zm6_3i(SQe}Q3a%{fsxff5X9qS;bP&a%*tOosXX^NI8tPlS%9(Ez_EJP>z{|7hx8+d z2rvyW1A~I~l5A48Ok~hJb0*`TjoP=P7sZQ;?%&1u*VFTRbwJsd&FpvL&**!+2owJJ zL`igMoqFvu#E{2;3narW%~EZp>|;h&2Ij_I z27|^Hn(Ht z-E%Fv3~?Dj;?I|>t$ld$)}|v@`!65q*s(4tySSrrb?Q|QmQyeFn5s_iXt1^k6<|n9 z13{2RJ{B$( z4vnzTM?dacJOM|8tTGEQz8W|xv+~zYD$jk690tHxX9jwHmp%V8wmotG#E{2;3narW%~EZp>|;h&2Ij_I z27|^XuuB) zI$2>x#{Vp=2FyST9J;dnAORL&#Ib>6MOJ}@-+i4_br|vhXF9wnSq`!Wp8G9ShV^7x1){)Y?_Iy z_I~?kQPF7ss9z*m+H;MjnfT0fCa3?wvremRY1ZxLQD@gk_PxTeqW%l#aoTmD=~ zKNga|a?;u#Uvf8|ayc5a`&i|(8wWgm&GvnlWMZz{+N*GWuJ94dSzIMY0?*vM_V8cr TY>&Lo?X9L_obUA+=Trj#mkiJT literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/Intermediate Certificate 4 PP.06.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/Intermediate Certificate 4 PP.06.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..76d6111ec16845f38c9cbed0dcc52d4a240c8969 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6Jw?UFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%~EZp>|;h&2Ij_I z27|^>c)fn8kmfKtu3_ipD47iVqRvFF>X9HG@A$3JPh>nvNV%~YTGBgTdONQ8}| z&cunW^KPtJz31qeo6R}}nXh-wu2&UYbi!S2YHi5s!$%jI_xz}4VrFDuT%2r>XuuB) zI$2>x#{Vp=2FyST9J;dnAORL&#Ib>6MOJ}@-+tZ-?jGO5Il?=G-)iP`K3cFeqW*8_$thE` SLj;Uo=d>I$s{XHVat;8HuFdNJ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test44/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/End Certificate PP.06.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/End Certificate PP.06.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..a2ddb0430cb006d8c615c61db2a43aea4d5ddeb9 GIT binary patch literal 626 zcmXqLV#+gUV!Xb9nTe5!i80@RmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*jwZSR0eS{zdIrV@a^k#}76yg}hK5E!(jZEl*94hskU)<8E?DdrHxPx`&lg&p zT4acDLF0U6KQpp2FgNxx7&LY=H8wIV2(nzR9mMDUT)V@|Ynj>;8SS(cKia;CC2?^* zU-Bt)n~cZ0;ghoz_ zd25-N85tNCTNzk@gHx8Dk?}tZ3o{ez0|P;zXJq+UxL7zcr%UL`h9KN#3EWn6p z;NY{${>&@uwielI!02QK`f1KJuHvj9(fR&c+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-GBf+12a7XV{u+fO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aP}p zsotCw#I+I4#mtS33{D$Qg~s-%eDXHE{6gqeYplqTqL5`tqGH@Lb6eJO&RHtW>G7@L zfXePvS@YR~je%Pp?~9F%UB0g(@3?-4V|1m({C?B+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-GBf+12a7XV{u+fO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aU<_ zK1lw*V%|G67c)0DGVnZ9?2Q-wtXn-JT6bcMQo{qTK(R;f4t#qk$z2}8c0uynl^GkB zInMYvPrvGl=H{p2&(Cetw)wSx$>N_zDfi5eb15=RUbfq2Phep{Q}>$PmvWA<=%~N^ xveU%;<9RU&J+6Iap-SOg(>GM=2z@oaIWKnEqldYU8|AcSow;b+wLVk85dcN+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~m z-GBf+12a7XV{u+fO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aRsc z*v>jz{n?G?V&=w12JJtO)^8AMy4rAAa6;Iwg>pxaf88F{|1hR9Z_&Qi7x(Qpas<6U z_jX-Xq24ooi|@}kE-coVQO(TQ9sX(Y_87Nr$rI5n?Vk>@gz|;7e%AKU5(@VA3;g#j xD221Gs^$9({W7T?3pd{VuybdT>AYLzcX!(BzYv>y@)!G*35x=>pM>si1^}MZYkdF! literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Intermediate CRL 4 PP.06.03.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Intermediate CRL 4 PP.06.03.crl new file mode 100644 index 0000000000000000000000000000000000000000..9e67a4a91d8a79651cf7b65685f115641377f548 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}r z-GBf+12a7XV{u+fO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aVi@ zvOn|6x~)ZXF>_-hLxI?W&mpb}2OR2;O|+jHZhQRQg*ORmUtMlbbC=k#M8{6pW`Veo znU8GN{rmkpMe}ZTF`T>F;l})SbJ*47Pkvwd)D=4v+G4qnKX=d)WABZ*Vle;eoTdEQ vZtl-cNyZd@@A+}&xN?M&JO9PL54{(!pVYr$Uc4(V`l*vvy`_s=>D+e!53ppI literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Intermediate Certificate 1 PP.06.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Intermediate Certificate 1 PP.06.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..90ee8e3fe9df723e264d214d48bdaf2536214cbb GIT binary patch literal 679 zcmXqLVp?p_#Kg0JnTe5!i80%NmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HPUF%&T1gYeixQj1G6^U@7P4TM1= z%)&e&MWw|h3XXZn8Tmy9a^k#}76yg}hK5E!(jZEl*94hMp8Y9!?RR!G)C~yGGceOL zFg9qMkL+VcRtDzAUIv54PNv32hSdS5dXCQ1@!I%n!|HFRSKiQE!M)e^N}SXfQR`p!vrYHSFa3N<@cksURdvg}qJlS#SmS;WR zvu~46JujP=v0<aVcb11-__ z3z?W185kEA8sr=B1A|Uhn33^63#$P$kOGIUEI&wq1sHK`;8>AWVBt65HQ;9BOlb39 zOl4*?U^L(XX;cB}YG7nB5Crk~Sh!d?Tra8KoE5~i5gaM9$}GUxYv5Qt>-En=&qMl= zLj;%xn1MmDEOX!Ug)fbcPx*X=YuZANrmy<9QfBAtdADDiv?#4y)o4n-!d|D4*GncF zT}~}C5j@a7w|c6Sjor7OiyRZ%4xg^_NtnL)!&DN1k6Wj9DXOt@~!*WnONr rV}8nC-pd4kIU03BG5V6??k!W5>IKy@)in;39dlAFFyG^SJnc9DkI>jq literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Intermediate Certificate 2 PP.06.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Intermediate Certificate 2 PP.06.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..7fc0467ca80842274239ddffc7978bdcfedc1887 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6Jw46FB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%~EZp>|;h&2Ij_I z27|^t*9BN ziqb5keywGayt{h!^(no)t+BHiz1aW9Unu#OC+4oD!DLz`%e{hpW^n|$OR~k>9Sfa|r%*epFIN2c4fFBri zvcimv|5;cKn1K{HbY=NL0xZCYV*|&EtO5(a0j~i!8)rhB2V*KTqXDCVAV?!03l|H= z+`iz`WSM)w(h8mFaKi)=V@%OEv)x3%KS6P!;bKRkC_dd@304X*2FDMaUr+I)CoZW4=R=7N?C(?Fd#<&c1b Sg$sm_e%QL~YUd`u5J>=P8_l!; literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Intermediate Certificate 3 PP.06.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Intermediate Certificate 3 PP.06.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..fb9500f12733c416623dbf5fc675cca0c870e821 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6JxFcFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%~EZp>|;h&2Ij_I z27|^-w({%A{rYK?zVI4K1YeK zJ6uv(a$M literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Intermediate Certificate 4 PP.06.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Intermediate Certificate 4 PP.06.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..60b6c913336fb57a1192423784c0e7569051af2b GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6JwqMFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%~EZp>|;h&2Ij_I z27|^6}ZQ`EyFMJvIBdr8! z55ew~JG@^i7A+Ug7gOB)l)Xyml-K#txL6}GHt{=atZr2tRuq=Ib9cYr@lz{(WFGW) zM5X3)T=DAF6KDx-)P1@`DCt}0<)tV8zW=esduxty=8HvLQj3|G85tNCCmSRh@B@QR zR+y3TKMSh?Gmrv@t}H)DfCU(FY~WatRbb&a;5Fc8<4kDtU`%CZG+;Ck1Zm`B;bP(7 zv&#O=E9xJL_!qXE$;f0ArmQ==n8%s{&3wj#H?tSkWMQ-eo#( zY|;^ibvF+?upgDWvXJj(VZy4tzvg7D*HiI1Dw(1b^L7mjcWiFStm-2Z=PWbmoZe)1 zK%BipU9_l1pv$V~eZ2pw7Os<54}LkaI&S5Z8#=Ql>Kt6U-z=<4)LfP$y`p4piI8w< R$x7AhoQu>{4|hnM0ss{h$3y@C literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test45/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/End Certificate PP.06.04.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/End Certificate PP.06.04.crt new file mode 100644 index 0000000000000000000000000000000000000000..39ebf20a38434208cf2245b98f715e773b50e649 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iLu0hmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*jwZSR0eS{zdIly2a^k#}76yg}hK5E!(jZEl*94hskU)<8E?DdrHxPx`&lg&p zT4acDLF0U6KQpp2FgNxx7&LY=H8wIln5veY9eu1UB5|Ubp~9)Ty=t|E8LiHTV!R*d zss}K?TpZf-Z`*1|Gr3;d8H*2o|7spsr=Z%zSmJbC?qdG`tm~UTrf-lsm>T$US9Wvj zA>Qy?0=<8fyDvW2k-f5D;^nScD-69=dm|rhj1@Wa`JseE`?B|^XT0GT-)$N)<5h8D z7B>?!BLm~&AcFvKaLV#CGX7^_VP;}|0FDM(1r~k-UIT76&V)7(##ClT14aWupeJSd zSh!d?EbdLQoZB*44;=2Y$}GSLYT#&8Gk?EOY9<%5mx0mD4D@SUchr@;A#2Vg-(3H` zq{;SX#-1JSYYVDu_hod3_7vDeYW`Yfy87<5!$;KX=6yW7tU!-7Bj5q+N0*C%k)Kz! zY?vu^|Ae#rI`+kPUo`d}wL7byW)@RB(^W_>Gvc?fT$RmK9?iFIbu&~`yQ_|7RRk|S WaeL$U{nzKDeD{wrQGX-U_6`7n($J;= literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Intermediate CRL 1 PP.06.04.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Intermediate CRL 1 PP.06.04.crl new file mode 100644 index 0000000000000000000000000000000000000000..f9a2236bcacda946d81a0ed3d41c657bb59d45af GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-GBf+12a7X6LDTkO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aPA` z)+|pjnIVAYV&=w12D>0JZyB*08*NsLH~%=_erj?-mfqv9H6hH&imV%_&O7x`{=upE zsc|R%KR-G1TZfcZIIB$0I wO%^wGem-ewYwnO>>o9L!pgwbRuhxmu3-9ip(|O6f-y$^IB-ZuiJJn280AYb>g8%>k literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Intermediate CRL 2 PP.06.04.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Intermediate CRL 2 PP.06.04.crl new file mode 100644 index 0000000000000000000000000000000000000000..02e82c48ad5a422739aa0ef325b6c4c698087117 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-GBf+12a7X6LDTkO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aOtUQY5V&=w12H`onr|TDoRsAV_f1}&!>U;0+Du$0{Gj3bTuE#48c;(Xh^<7NA zvo{*8F$_0%S2VbNU&$=hJ~K@C>Rs>apQo)iykPQY&Md=}F0*NuvSi~-KN}c`neDeI wb>9AS{=4Ie&34L}#%~G)?f&TK{EzMLobhJW?p?~QWhKVyi>~$MYYChN0L$lP$p8QV literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Intermediate CRL 3 PP.06.04.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Intermediate CRL 3 PP.06.04.crl new file mode 100644 index 0000000000000000000000000000000000000000..ddd59a80c42de9faa936a3ce7c69e6e349d7432c GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~m z-GBf+12a7X6LDTkO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aOf- zl_LLfF8zY$V&=w12CLlpvx{U4EKhjft=!^P%$FqX6MS$&=a)mK+Le=Le|uagoVG_z zC+ny4w_Q3jqEwf~mBfa~x^3JgUp)O!(d7h>ufd)TCBf5HDz2X18*B77S!B)TY@V>4 wvu_saO1OUWz8WPI~BZ*y#1WlT5!(u(U0leelO`0BtR2P5=M^ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Intermediate CRL 4 PP.06.04.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Intermediate CRL 4 PP.06.04.crl new file mode 100644 index 0000000000000000000000000000000000000000..3dedfb11ec3318a1b6f4911fe68f638b375c200c GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}r z-GBf+12a7X6LDTkO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aNu& z%-=7Rn#qOcV&=w1hI2)GtGrdFcTWp`JAKvM^ZjuKd#g9se9#gLym-m7l3nle=cK?+ zv0XZ;zx?l&?>%FnA}t{u;j^MDA+MB;{Q$r7GTxZ`yVJbqX5`H`4E>d(_2;bp@=%T6 vHbq=F19P~8GG|X&;c)Qy3&W)Czu33s>6XUZ&3om;%K0_zPJkS%hD}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HPUF%&T1gYeixQj1G6^U@7P4TM1= z%)&e&MWw|h3XXZn8Tmy9a^k#}76yg}hK5E!(jZEl*94hMp8Y9!?RR!G)C~yGGceOL zFfnMHkL+VcRtDzAUIv54PNv32hNBDRZ}`k~OMLn6MoW&L%CCMVhWENy#gYm+)>W_IbZ@ z;mgp4y&(dVwKZ}LJ=`~5w41KWzu4A41Due&y$M9a8tQne@`aFy(Vq!6|hn zW=00a#f1j>2K>OFlNDxU{LjK_zzn3op)1P|5?}#F92+=RWEEKW4R{T>**Fv0JQ!1% z84VZ>ct9FeK)M^(<=OB|PH z&ayZ1KEKL)TgIOUPdsK`d^1mVNmX{+A_Z03^B*5o-L0J=SjBchr0lM|`nK+;$p?xX pykgzXnciDJkvad#E{2;3narW%~EZp>|;h&2Ij_I z27|^HJeJ;b2&SB*)h&5UvXA*zpc7;%a#ur`(1s`ozyxgvATD`p@U6p zJ9ji!Klwkwxz=l4X6_sJ!X>vE+9#}G((v?bE9JkkeDRHCVPE>0m>C%u7bhDe8t?;y zPF9$a@jnZz0W**ShpsF?NPquzPn_E=;r(P2 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Intermediate Certificate 3 PP.06.04.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Intermediate Certificate 3 PP.06.04.crt new file mode 100644 index 0000000000000000000000000000000000000000..6e33faaaabf6508071e9f5e7c7155d296209c9ae GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6JwD9FB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%~EZp>|;h&2Ij_I z27|^OF zlNDxU{LjK_zzn3op)1P|5?}#F92+=RWEEKW4R{T>**Fv0JQ!1%84VZ>1VI}4Sh!d? zG8mO2|8Xw;0*(e*Wfow3HE?(=7vNj&Sa}pV41lrD4D`IrZAl*0wN|UE9|v)o@cSK_ zv&@H HSZFS3@jGw<-+;7cEdcEyNd8C-n$I=x6+uWn|8kG}seGM#xWi_30HIt(X zesf(YJN!oZ)%KR-mWRbf-u}w}yI@7trf=KrH-)ZKW_#=Z+lBkF%Il3SjHbPI>Mv~V RF83y$xhs*wSGFLv1_14V%qjo? literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Intermediate Certificate 4 PP.06.04.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test46/Intermediate Certificate 4 PP.06.04.crt new file mode 100644 index 0000000000000000000000000000000000000000..1b3fc57263eade24d53601f4c890b07edefa2e18 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6JxOfFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%~EZp>|;h&2Ij_I z27|^>GW>vD<1dN&K>VRXj~?+yWp^>^7>C+ zyX=_$_zCRc^ILn(WVZhi(X$H|9Czvouc}(oESnjeVr7~fxWD^S>D9WeH8-=jhMb_i53aCCafbGY?BMF*7nSE>1Q`G~fpY zovbh;<9`-b17;uv4qaJ(kN^uX;@H5kBCEi{Z@_E7&BmF~=E0cC%xJ)9APCaP$HK+J z(WqwrexcM%E^su+DzgCNtAQhfQ7Q5t=h838VE~MEW}xSVt@CH3Or2xcR&mo~q5Otg zVVk*^GMc^`>WHO1xL-BHtTy>^_V){~_VX_@=sg(hxrlitv-P#sHH#D$^WIsudqw4q zbXIRe-yhkg3tbM)?{jtgzBTjrMjh|El1H;!vre!0FZh+~hRTiAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test47/End Certificate PP.06.05.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test47/End Certificate PP.06.05.crt new file mode 100644 index 0000000000000000000000000000000000000000..7337bc5b57f552c36ccc817dfaf8f2446ee8b120 GIT binary patch literal 626 zcmXqLV#+gUV!Xb9nTe5!iLugvmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*jwZSR0eS{zdIqKja^k#}76yg}hK5E!(jZEl*94hskU)<8E?DdrHxPx`&lg&p zT4acDLF0U6KQpp2FgNxx7&LY=H8wKrnQG+ezrT8e&!5xMdv#)ZxIDb8o@-2bA2C~A z!~MYgU!^tMW!6p+v=n4ncO_JL#%fZznnZ5aGT9=o_dr>W|sz@oyD`Sxo>+#%!(;u(*47AuUXnOj=mdST_ z|Gdk@%*epF*vh~H9GtTJjEw(TSeThu9~cM%JtNDDYl=?laWg9Zl^=RIcq6exkkG)qcKKT1>ZFuhE{)JaI2NiDl6#1ofiTB6A zEbm`a?Edu!&pk8yu=@d?)XaX7qFAS*0_R7j2~X{+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-GBf+12a7XQ*mBPO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aNcQ z53Z8jymbzmiDLyY)aejX5#@N4nc`eU0r#mwvt2qqa@p;~lZSyJ~T7y0f-?abG8EXE$|r wy^#M^D+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-GBf+12a7XQ*mBPO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aP6h zHO@TywOR+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~m z-GBf+12a7XQ*mBPO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aU2A z`29ww)Lyf@pj z@>j}N!KB9d?^dRhkp4~5`>tDoCgKJ)LGZ+yqEMUg9H*`lw@1?qmO w1kdY}XMgpC^NG7AclsvTz1NuR=RG-9b=EZYXW3!NINt4leq~p^Tx#VA0Cl%#KL7v# literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test47/Intermediate CRL 4 PP.06.05.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test47/Intermediate CRL 4 PP.06.05.crl new file mode 100644 index 0000000000000000000000000000000000000000..925b78324d09879ac38329c52c1ec8591943fa2f GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}r z-GBf+12a7XQ*mBPO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aNJR zZK->~5$}oSV&=w1hPh^!3`93A__k*1qL&OOJAc?MnU&N~DyFxFS7W081^c&RKb!r- z8}9BrAP``)hl}^(q$ysv&9`LUtnzi;(|q<}|CQ?=QgyMjr|vgjZJ=?kLTceAH{S<) w_FVUkOiNZPZ4W9gKGL>Qt$M}Gb2f}=T@2>w9!b`X{o$tn?q$iJWins_0Ff(YqW}N^ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test47/Intermediate Certificate 1 PP.06.05.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test47/Intermediate Certificate 1 PP.06.05.crt new file mode 100644 index 0000000000000000000000000000000000000000..bf3e222391acfdf3f54cb5e5c4243e8d4a8bdf1a GIT binary patch literal 679 zcmXqLVp?p_#Kg0JnTe5!iLumxmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HPUF%&T1gYeixQj1G6^U@7P4TM1= z%)&e&MWw|h3XXZn8Tmy9a^k#}76yg}hK5E!(jZEl*94hMp8Y9!?RR!G)C~yGGceOL zFg0kLkL+VcRtDzAUIv54PNv32hBJ!Z0e>{~$^{P`U{L>Ls#C&dvwLgvrr@SW#nDl9 zPFtEDq-VG(&TyG0bN*+*)KBhv&g?SftySa{V`#Rtj5TcNN;H&-{(r(eammz{d5Z<7 zSu)8BKDb+G`nW!8*M-=b*~fxHTrY`emtV0D-1X1S(Ad6gi=gN9#hY&IWa=r1W_rxT z%*epFxX>WqfFBrivcimv|5;cKn1K{HbY=NL0xZCYV*|&EtO5(a0j~i!8)rhB2V*KT zqXDA<4@jd5NLK?RyMZ8x$H&6O!l9UbaFyidt#iPUBCE^-jJ*bq)w5pzJoG%IA2~#T zX@D6R6fDvcw%Z5T8+Q4sd#&%zTYtH+EimCir0CYwcgw%0zGN1-yMHGi?_bw|Q}Jxm zMe@QH9NYTaYD}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uAc0eS{zdIqKja^k#}76yg}hK5E!(jZEl*94hM8~cqA_BYN)_Aw(X19M|9 zgF#~_Q)45;_E)wN6U!pKd0#oMalXXcShs1$(pOKUOdV?W@NIeHc!Bpyy=)6t{FxP( z*LQyrn`+5*sOr^Wx0X4!J3DoqMb0T3PDm^LlbKrxwYC_={oC`tbUo`mutqU# zlE`s64i3fM<6p1vHL%Zch^r3WtF(K*o9)jVD({Ux&MK5>lj&t*W@KPoTxgJQzz+;M zSz$)T|17Kq%s>hpy0ZKr0Ty7yv4LYnR)K}zfY*SVjWeOmgE5tv(SXr_2c%I2q^p6E z$v_aq<744s;RspQIP>h+Y9Vl>$SSh{W3PcjG5g>u$<15mAcqJr4KM?PLU~Q#XYN4n zeWy8nzg8w4oPT)JyZ%Nk9TVA?n-#W*Y_KbRWoXKfHsOfB`i#9Ncz*0%n{}Y<#gR=f zx^q2NOQ}sf&+)%e>8x^}Ug4tCP4NrX9Ozvj{OPgyx$NGVPs?^Xd&!twv5c9S8FuJ- c()J(otoMc&pV%VasOY)mifV1yvcB+10Kdl2r~m)} literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test47/Intermediate Certificate 3 PP.06.05.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test47/Intermediate Certificate 3 PP.06.05.crt new file mode 100644 index 0000000000000000000000000000000000000000..62eb3b220c6c1806fa5c74ee2a00875168f9e436 GIT binary patch literal 679 zcmXqLVp?p_#Kg0JnTe5!iLu;(myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*jz+ox0eS{zdIqKja^k#}76yg}hK5E!(jZEl*94hM8~cqB_BYN)_Aw(X19M|9 zgF#~_Q)45;(I|n1w#=@HT;6P{X|al}x8`g;c>G}+Ti&|AEKfLCSm!V1tqP zF%Sgt_*l4DIL-Do;>xj*;A?k-h6?-}nqIbSx+ypv+vy?kAf2}AXilRZ-(`dy!p cGx@0RY-47lgSqGWN#E{2;3narW%~EZp>|;h&2Ij_I z27|^zdMoy@WC700V}N6VK+wzRqlJF}fN^ku%nB4F5G94mQ5aZ~%vnMw10 z+niqL9NV$KtU3BpuiswVA2kcLx0idqd%LjcLyupk*8PTuvk!_gF*7nSE>1Q`G~fpY zovbh;<9`-b17;uv4qaJ(kN^uX;@H5kBCEi{Z@_E7&BmF~=E0cC%xJ)9APCaP$HK+J zaVTp`-3yL*PjEEIDzgCNtAXR}gWqpt`|FaC!vGlT%s|iQuw7iV@Emg*A3pu z+!4O#zAs;dUEAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test48/End Certificate PP.08.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test48/End Certificate PP.08.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..933f279129189d90dbde8d14b3cfb418bd5d9224 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iLu&%myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uAc0eS`&dIp9Da^k#}7C_q2&AKA~0tPISJy$lA8olK354A*qm-AXuev+kQ=xzAn4uUlFq*_D1C;nSL!Gi$di zvql@cP@fs&q((*89YKmGgl39Q@yl5H)&69Tlh@06Z)OMS&-}u0_f%VVfWiOsKQ*5n zpUpUX@r-!(u&DMVJMYceYTg%RJ?<7ae7UahznpPZ*ov$voE!Ig zGBGnUFfI-<2mlACEI%XTe-;*ICe{bwXpmK4;Wywl;AZ1YX!Br9Wo9&BG!O)OQkIW} zi-jZ2oUfc$(nk#(?y|}(zzAyKSSY3?b6r|@IkK05(aa3=Yu0Y{>-7&VeeOE0t1;nK znQEbq?QQ0-4O7rH1bJ4|75p87ReD*6gTf#AQ& zawQS-3#{LI*qpvUI?eLeTJn3=|2%;LO>y?;?SEh73PgIoFgaZj{5Sbl((>AcN$aAs T1itEh%l;vzVzT7Q-xIX}1(3^W literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test48/Intermediate CRL PP.08.01.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test48/Intermediate CRL PP.08.01.crl new file mode 100644 index 0000000000000000000000000000000000000000..89ad99cd17e8ae7e01608426e623a09210193d1c GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-GBf+0}DL^Lvdb9O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aNh; zX~|rd)?JR~V&=w126xrJw;#QTv7N8Lz{GO+aN}*O*@arWA4naF`ZDQNrp-H}5><;y ziV9l;yMDP@N*n*G^>WZM*fUEYd$E;r3)>Ubm&^<9GAhh7Q(X4@V&vS&l7N=qB77nS wLihJpY8d?}e#E{2;3narW%A8JHV;84MabnHn1zR^Iw}HQrzS#PWUKhy5p9@=L$^yg7GrZtKH<>hQyN z)~6*uag$+QJN=+;Sxo7~q+{wSlXahPTmNw`>p$_K$T-Vb{sFtXAx}QX{C4dtIm|KM zk8(Fx=A@LZHs4y*S-kJV+`g?{)4#2GwuZS~D!lRLp^PQ&Y7ED-&vBQkblHAX)p^Xs z%*epFIN2c4fFBrivcimv|5;cKn1K{HbY=NL0xZCYV*|&EtO5(a0j~i!8)rhB2V*KT zqXDCVAV?!03l|H=LNP6w>(aW*!O())@gLgHudF<|vpFZF3 e8{5opOV`-%i>T0kz4p?@fExmeDAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test49/End Certificate PP.08.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test49/End Certificate PP.08.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..d0e4a26e66c3fbd2f32ad0cb456afc986e604db1 GIT binary patch literal 663 zcmXqLVw!Bw#Q0|cGZP~d6JxCbFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%5$WP@pa9DUWU=PEiRkGZ@m$~mv z6lPzV-{sNXxS`Z$_WUE(a+_a&iLm>@CFYX-OJ>V;9?(g#zC-*7WzS(m( zeM|qz3vc*dW*rdRyMbZ#Nyqlpj5p@GJ+@jc-177&`;i5I6x*`7BAL3?Zg98X;_BUV zyOW8Tk%4h>yg@8DIA!@68UM4eFf*|}Fi-}1Mpl7E#z4w|n~gJ}&4V$OnbCj|nZslt z2vWqy!o|YzqDRMf>9e<0;7E{FW&y@l1ILTVhXSfA66YZM9~kG%K#zz2U{O1}_4bDO zlhh}E&lTOmw@UalQ~l41j>6W6klkDEO-%Vc>3UQsW3fcww)Xf1ag6>yn-;6WXx-{>%^CXk2cTc=r{!3R^*z@DY+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-GBf+0}DL^BXM3!O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aQ4= zJ`_-0kvIp<#mtS33>+IjbQlPVHC9Nj?vSgJociO}yx?|*@Uxy(TV6&#eII*!Q-hMF zYTYd^$zH)-x85XXWx4!fm>Vyfen@D-Q@Lb|#J*!pZ&`vP53Fpyu%g*g`@UjO$;5^^ w8FFe~xl;dk#c=$3Ej&wppXcQ0r5h)IZDo9`}unbUp+0Efh8kN^Mx literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test49/Intermediate Certificate PP.08.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test49/Intermediate Certificate PP.08.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..037f68d8b0aebadabe7abba5ff45c5310a6a313c GIT binary patch literal 678 zcmXqLVp?R-#KgUTnTe5!iLu6jmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HPUF%&T1gYeixQj1G6^U@7P4TM1= z%)&e&MWw|h3XXZn8Tmy9a^k#}76yg}hK5E!(jZEl*94hMp8Y9!?RR!G)C~yGGqBJz zFfwSIkL+VcRtDzAUIv54PNv32hGk654zCX|26$x}UtV#Kdy&)+y?wW?Ia>=TOh3c6 z(c-VVL2*mJcJm_@`z7Jr;a#OKLr*#ya>!lxp85D>kgCPP+SxMdyca#Ht1r|sE%~DM zxJBsAzxz(BVp5jn8)nXU!LQu+_I&H^RW~y@IeH4i`E6b#doY&n;cj!CS+Mw!Vw*e@ zGb01z;sS#_1Abu8$qF+v{%2t|UWaiU;5d<0W&uWC1IOxFuYVqT9@38-AiyNR3=D}x zQIF@mnch1u{%dGR$UPs-Tq@CC?JxGP=8#z}*Y&SjYg(_WZ<1)-+&y9Mosyazwl^Pe zD@sqdtmNjZEs`iZvzOo3?dr8h9;~_FCY^QP!5ScHmUY}?-J)rhOiP?p15R#lJow~O iUq0tEozG#Nhb+{dt-N0G-}mH)E6%@#cmA?`aR>mB_0P`$ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test49/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test49/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test5/End Certificate CP.02.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test5/End Certificate CP.02.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..a3a65892327e819ad6d70735af61551933a183f1 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iIK~ImyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uC<0eS{TKx7~%&TDC5U}#`yXapn;qQrSkkhum4`f?d^SS&_yT1LNW#g8*=F%JMTZ{%2ufW@3E+js{r;7JdU>18z3XgfdxfAX>v9PYBpEWikA;9&d3f5op~N*US9z-VR$`c+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zUFQHj10x_3=e4vnFf=eUGy;+aQR2KN7D(I$$_9#HV`W8Hm_d#M86m680<^1vgY6gp z6~BHdWi%HvH#Rab>~yFvVvc+hQ|2rnn{rq3VcgG+J4>Xm+U$!w$!hS$bhbX%#E{2;3narW%N*GL85jYP zLF0U6A2YHtFgNxx7&LY=H8wIFSIZ34+`p{%+}19ww(1*(e?xh6Znmv0oS3j!Em6nM zc{ZC~&)f3Uw?f>J0)O<+-uKd3*nhWjf!}rumMq0pjTzEcq<{0yl!y`K&TU)zWJT=x z&RcKS-h1Me#P&jNLW!E6S@Y>hG`GcSr2)y4uTc_S$h?;aaqF%ACdb)^BBE zW@KPooNSP2zz+;MSz$)T|17Kq%s>hpy0ZKr0Ty7yv4LYnR)K}zfY*SVjWeOmgE5tv z(SXrF5Tuchg^PuQ?HB(QzkVrYa5Ts&vjF3(fn)Wo*FO(E59vn^17NH(13f?EP3!9H zn`@n&LsMc-o9U-Xo9^T@Zmf=9Rea=PY^@vHjM@*YJ(O%-+ohZ^HA-hY#vp9Sy0lQ3 zul&XFH788&rd||1ywdlnNba%y_7NVFAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test50/End Certificate PP.08.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test50/End Certificate PP.08.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..ed9b0a3ceb86c6f114efbe30e67b89f17f375ae1 GIT binary patch literal 645 zcmXqLVrn#KVtloLnTe5!iLu^*myJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uAc0eS`&dIrV@a^k#}76yg}hK5E!(jZEl*94hskU)<8E?DdrHxPx`&lg&p zT7=|+#`(y8W@KexZtP_+XzXNaY-HFiF7WG6^Ia#)El;1kI<6q+wn>ONj;nE&&Bxm0 zQ(baGzUhtC=^Y~PGcB&(F`k*T#d}-K27mh{jE2r)R=W~aU%XZ?Z+57*xZHMd-u+7J zKc(;Vc0EzcZH~CIs(I^#2Yy_g8*ebVrT0xN5j4#GUb59XRyI4Z<+Qrv36G!IE~mO< znV1Sb$6hh!7tO7Ym2$%n4I& zIM@6H2f3^=3ovdPII@G+PBKVryp8NzU<@+@y;-UB*XpI5(zK?Jf^FOr{yknLQ|23Y zO5x`Zwva#{%N)+HyLMz0&As~J=5jUHM;{8Kcc$h^Pul)U`lfN}L>ZOU=EwBkezY{| zb>lgFV7k)uV@tS$D|d*$UCU`#vG28U@V&DsK5susFU$U!rrr^DM%U+K+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-GBf+0}DL^V{u+fO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aT3p z*G@7>Y`l%;V&=w1hC;^|{J!Gr7f4z~x3WJ=oFvP- zI{D4&-%rA)s9)7wp{jhOLbk(E^z>R@-N62vA$jVNd-i_#{7HJJ?TV>=J)g w$5!**&ZNc1+)-lEHF<@`)Lr$_`CGb{OKNXS`|{33zxj&w5{^R;f4^D_0G)bfAOHXW literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test50/Intermediate Certificate PP.08.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test50/Intermediate Certificate PP.08.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..74c41f0216ba253f244a639ded0e31b0cac05e52 GIT binary patch literal 660 zcmXqLVwzyk#Q1XoGZP~d6JwnLFB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%q;FF)f^rNtM}jY7jr%?oKX3l ziJ6gsadDhMi~&C|=wyW%8UM4e8ZZMXaOleNg9KQB5yxgA2vVTH!ezi=z{bV`WHLa6 z_*l4DII@G+PBKVrybX>4S!EVrR5fs{p7r|Yq30p}$leD=I5W`SXWw40@l@M3v17u4 zgA)r|jRT+WH88v~u_N|Vq)M)pq5g*}SH=2C3h*7w+@kUc2h^YYUE$weO#aSRK)0f3R(iiAAu_f)v*e_rI)G X5$o~%!?@A*TCRe_-W!HNc_EAd*_Y9m literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test50/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test50/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test51/End Certificate PP.08.04.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test51/End Certificate PP.08.04.crt new file mode 100644 index 0000000000000000000000000000000000000000..12ebc74c72af2ddde995831401244a3c9edfb5db GIT binary patch literal 651 zcmXqLVrn;NV*IdxnTe5!iHV`nfR~L^tIebBJ1-+6D=ULRoFTUXCmVAp3!5-gXt1G# zff$IxCCneH7p$k?o?n()l$V>DS7OLxzy*@w7G`$IPcalQ;DhkkLsE-NGV{_6MGb^O zBFw@(&W?t<0Regj7J3FI26E!OmKFwv28M=4K++&eoYw@IYmh*W{VrJS7dH@v*v}VQ zoLYqBg2wsCer9B4U~cSXFlg*#YHVaUubQ^MK<--f?i6Xk#A2Q-;Ri*9<=frfu9Don z+~kYoKRb&++oo4LOApS`Yfv-UD7P$D{`{XS)x~D{%`I|=9f&pbn$sr{NFl0dxoF(Z&wyg*>d*e(zlvinR_|9Zg3Wz zcV%K`WMEtzWDo!jPFa3N#{VoV%uK8gz|kP9z`}39YrxIMnb79Jn99s(z+xZ>^rS2w z3l|H=%DoD2`ivv$z~L^d%mR#{296mG6W@5f{%(!zWneTj1O4jysVwBl#A!3MSBt1< z^j9cp%8Tuu&oh=Go3=0K|>NMF0Q* literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test51/Intermediate CRL PP.08.04.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test51/Intermediate CRL PP.08.04.crl new file mode 100644 index 0000000000000000000000000000000000000000..c887c9a2c8411392ca8a71a91da574bfb8db666c GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-GBf+0}DL^6LDTkO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aQS& zOnl?@`nxrniS>gTJ0i7pul(L{);aI)zKc1#jqR0wv2NC)dOJ%&^yS7iC;w*c`JYm^^yPSOb*-uZd`YXIQBK~OBryskn<}ZkU(j9lS0ss`$Y&8G? literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test51/Intermediate Certificate PP.08.04.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test51/Intermediate Certificate PP.08.04.crt new file mode 100644 index 0000000000000000000000000000000000000000..def7e90d1fa9c0a2f5409c7f2c3b7a88d30ce13d GIT binary patch literal 666 zcmXqLVwz^q#Q1*!GZP~d6B9#&0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzIna?_wxmzz5;6holylWagzCiW&%m zM3{wnLW)X@OB5XQk~8v)4CKUlEiDWT4Gay9fTTf`IIjsZmpuDZ@Y?U}Xs8H7@E5Eu@Zjq@YO*kB zhW7TWjL(!9g#N_v+AvRhc4Yr|&K`5t{>zo`x{IT`GUq+{cJ88u%gZIEdkythZ@GAV z(sjkfF)~J1@)JI8V=iGmrxyKXo8dXOrB6?+;+d~+#`3`X)^DawH&z{st#GdYz+zi) z`!W+VBLm~&WP?Nleqhka3NtePXJIv922$YAmE{KsumEF@4IC@73M~8vyawECoC$3n zjH%3w2FwP6AdP%1Tr3Bmf2=w3?^%CwmCT;MWfT literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test51/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test51/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test52/End Certificate PP.08.05.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test52/End Certificate PP.08.05.crt new file mode 100644 index 0000000000000000000000000000000000000000..0bd19185fdf8105e0c7e83c6496d88d21ebec2a8 GIT binary patch literal 651 zcmXqLVrn;NV*IdxnTe5!iHV`vfR~L^tIebBJ1-+6D=ULRoFTUXCmVAp3!5-gXt1G# zff$IxCCneH7p$k?o?n()l$V>DS7OLxzy*@w7G`$IPcalQ;DhkkLsE-NGV{_6MGb^O zBFw@(&W?t<0Regj7J3Gz26E!OmKFwv28M=4K++&eoYw@IYmh*W{VrJS7dH@v*v}VQ zoLYqBg2wsCer9B4U~cSXFlg*#YHVcK!8$Scz^jhmd-Ff2Cnav*ecWrt-p7@EMMGGK=2!ymz_qE$@Tt zIgK6nBECLT<&>5E+}!`=_1cs*Yj0^!-)-G^wIv`jx--iJ6gsadD7A05~{h`577iv#>BTu|5DtgRBAzzX7iSHydX{n+IbmGot~sfgsS6 zvV1IDEF1#2e9O*W4{!vByR0$`FoGI5Oy=#D`XLx0h3sWuG&2MJni}PBJNCg2jnFA} z!Mdql`_?Stli!fG!ePS9qF-m!8CM#_vZ@_iYq?kOR{94y-H5owN1rW=xY2hfbdTs( z5#!wI<&$H+-ttvae9g19RlQj3zlXFg_f}u;gJ;w7<2JsZVZ1=*Q{v+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-GBf+0}DL^Q*mBPO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aPbm z?Uwo>7$Jq`V&=w1hW!)Y%x%7D9e#}aTiKMh+W{+1?Dub6EAO6@Kl}X}@ro%|kA6Kf zb^4Z~$rJx9`1ZwSqjKR6#pmwsI;TG=G)J}__`Gbjx@D#0q*4RjhUe$jo7Mk1q%rwb y@%N4s-_HO1w0Gqn{aP*)$-N4u7leh^*<7?g@N@>dj8h+9<<(!|HIr8HbO8V^DQz$S literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test52/Intermediate Certificate PP.08.05.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test52/Intermediate Certificate PP.08.05.crt new file mode 100644 index 0000000000000000000000000000000000000000..3429d7cf765d1e24c9e70c8c415b7d0a2c8b1f6c GIT binary patch literal 666 zcmXqLVwz^q#Q1*!GZP~d6B9#|0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzIna?_wxmzz5;6holylWagzCiW&%m zM3{wnLW)X@OB5XQk~8v)4CKUlEiDWT4Gay9fTTf`IIjsZmpuDZ@Y?U}Xs8VFLdWU!7a6>k4C&r}$~I9PBmu zR4LMuc2Z#NcPGtrN&AIfO@5^^Gx2_+f_y=Cya~H<)tgUS&v$0%1dHgWq~)eJhy`wX z`jFLHPxkTtta`mpjyG>F8ZAt=$eXZLOJds&9+S`eDz6;(vU$1az0_K+XXl#Tf{Tj% znV1@mjqZ6XyNlCnB*NaWPi8+;+?2>GJU?f}1(&^T`xmSaKbGqmAKWI$to1KzLu!Rp ztGe;hH%Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test53/End Certificate PP.08.06.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test53/End Certificate PP.08.06.crt new file mode 100644 index 0000000000000000000000000000000000000000..9b99dc56259d7e7bc7c07fcc0dac66e224a9a00d GIT binary patch literal 677 zcmXqLVp?d>#Kg6LnTe5!iHV`rfR~L^tIebBJ1-+6D=ULRoFTUXCmVAp3!5-gXt1G# zff$IxCCneH7p$k?o?n()l$V>DS7OLxzy*@w7G`$IPcalQ;DhkkLsE-NGV{_6MGb^O zBFw@(&W?t<0Regj7J3F|26E!OmKFwv28M=4K++&eoYw@IYmh*W{VrJS7dH@v*v}VQ zoLYqBg2wsCer9B4U~cSXFlg*#YHVb9p4ndH+XSe(Vg|%DKcnX3e(yA{BT;iCsGE)4wlP$+z1ue$> ztGk()85tNC=NM#xgHx8Dk?}tZ3o{ez0|Nt~XJi#vG!4`ZxY;-p+B_IjnHdcjkvUAr z9A*PSkPbc;E*6e9`BPo)T+AE6F(RwX0*tx_j?ZU*t0Y$MIe;7(zy!by427Jc?bEzw zOY3c&_CEG@cHfQKhv&H;&kC1G>(^Y@rCr_^d#l9bIPa|H_ModRu4|uPEf>qxd{X;+ zmfcqF{F&y=mal&7UL5)FXsA%g?W^}@9lP|UyIpP7zuA&$EF3<%hmw!2U|YZZmVcUY dV4j29>01j!u3WD%kyyfSbhfnbzo_+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-GBf+0}DL^GjU!^O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aO_m z{jHK%z2^X$iXZduU4eZ#zUyDS7OLxzy*@w7G`$IcQF(&;DhkkLsE-NGV{_6MGb^O zBFw@(Aw{LdB?^vt$r<@Y26E!OmKFwv28M=4K++&eoYw@IOP>8Hc#ll+gRmKc4*C;{Nd+QIH?d&(d!J*8VQg~|V zQ6^?a2FAs;2Gs`qz@U>AW@P-&!fL<_q`;vo%MTJ@0mdAgfdNQ?0*j`Bx&b#EXF{6? zV=6PF0V6Vp37NxeAPCaI$HK+J@%ij;mBi{j2fz^|tIPt7$p((qvtIu^^gN^=Idp*O zff*PqS{c&EO*>x3u07cB^7X`ZpDq7YY=ie(n7kitv&)IhHZgil*=~YtGxK1Q(Fx>z7 p)XV*M|5%^Q>vS}jc1!ill3PF38D5oMa=LW+L0{j!ZAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test54/End Certificate PL.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test54/End Certificate PL.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..185f019cffd5c7619bbb78d4d399c0fad273ba30 GIT binary patch literal 651 zcmXqLVrn;NV*IdxnTe5!iHV`ZfR~L^tIebBJ1-+6D=ULRoFTUXCmVAp3!5-gXt1G# zff$IxCCneH7p$k?o?n()l$V>DS7OLxzy*@w7G`$IPcalQ;DhkkLsE-NGV{_6MGb^O zBFw@(&W=X90X}*LhCpN>C(dhW0i+ELjew*}4=$>||q9kzIr9DefI`WYF4T|fHSlWt1Zy>_{v{juZ|dyKSrQSq(%Q>vEo3jDA1cXX{> zpP3(h^9Aq8dAU|usek!hJwj)Fy?;JIsOPE1|Mhz>ZsFfwByO>5?Yk4(mw1Y>wFfIz zGBGnUFfI-<2mlACEI%XTe-;*ICe{bwXpmK4;Wywl;AZ1YX!Br9Wo9&BG!O)OQkIW} zi-m)u`wkz|#DzuRaF*$IPyKhQUg4OOd?{jAmw_UuV0|xSY>*|I3cB<7Hp< zxgNx&Usq`S6@1cVNBo%w1sl$b?y(B{`s>-tzO?CbDSZnMp1SvATU48dh`{gb%VypY zc=n_+GtD&J@YSRdV-vrO(z>ZHkQw`m6+Wj706 Vn#%R8BGzB%&~u~KT;u2AI{?N_)Vlxx literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test54/Intermediate CRL 1 PL.01.01.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test54/Intermediate CRL 1 PL.01.01.crl new file mode 100644 index 0000000000000000000000000000000000000000..5b1c4439c375ad33f5c3921e6e9c96a5dc8dbf78 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-2fjw14AGZ=e4vnFf=eUGy;+aQR2KN7D(I$$_9#HV`W8Hm_d#M86m680<^1vLn`_5 z!#S&KSD?9=xv`O<{Fvk?i`nbXEG|eB;#23`t*S30mcG?A;M(Dzv5{*zr%MzvOzqvU zCF_~6z`vZiWyfsuvMStW#Rw}_IcvY)x6r<6={-J%KJM1(r57ZR3Ql8={jghj$zfU3 ugx&F68WypwXCe+?+r5QVQ7m)MHIr*os~+>@z3sgeZe?PW@1oB=NdN%+EnyP? literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test54/Intermediate CRL 2 PL.01.01.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test54/Intermediate CRL 2 PL.01.01.crl new file mode 100644 index 0000000000000000000000000000000000000000..c531566a933ff6a8483c120097b402c25b8b151a GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-2fjw14AGZ=e4vnFf=eUGy;+aQR2KN7D(I$$_9#HV`W8Hm_d#M86m680<^1vV`kSq z!(gSjrD!f@Zfs;o37;c%<6PZ*O@Gg?B?s$|-~4lWw$G2;(|Tq3JhL@*&%asm_sAXj zH!>27HlK~j@Dy-hp3Lf(uwX8iMSzIqN39>NKX-jj-0^$Sd|AGYYD<16sL%Vc^|qC) vAydCuZk}OuS)~nTX2j$dbt~yU-o)$y)_?hyNS)@omC0|hUsPy literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test54/Intermediate Certificate 1 PL.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test54/Intermediate Certificate 1 PL.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..140ef06691fb469c0b20771fec0acdcf90071e7f GIT binary patch literal 669 zcmXqLVw!2t#Kg3KnTe5!iHV`jfR~L^tIebBJ1-+6D=ULRoFTUXCmVAp3!5-gXt1G# zff$IxCCneH7p$k?o?n()l$V>DS7OLxzy*@w7G`$IcQF(&;DhkkLsE-NGV{_6MGb^O zBFw@(Aw{LdB?^vt$r<@Y26E!OmKFwv28M=4K++&eoYw@IOP>8HczH55kg!R@2NwZEe>Yb1~Hc=v@`pf1Wd|4}; z9`K&}bSAc6b(iDCnJr8IY*E&l7yR;za`e(ZT}QqQUrozpcI^kag=^B84;H2OEZuk| zsCtd%ywv$JH`d+y^ow!&!VH_tKO86gE@t+8@tOVa!xh^LGta6^|F%DP)Lit6@X@lh zOw5c7jEmC@QVfKEK_@HB$oQXy!+;G)F)=cL16YIA?Y33UExwDzgBitbt?otk*veJrC(e4hCSvGXwoE z|99`h*Aup{`($Yl$HBRstKTnETR~j>*PK63L@o)M$?3c~`goQ4mtNqUj&OD;1@KuVrbDP_?Gj%H;C|;d$PiUfyvsQiQ)frg_{|R)rC_Hoc jdbY@0$o}5noAqXsB=wayu{2NEP@(p6weYnRo$I9l&*9Zd literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test54/Intermediate Certificate 2 PL.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test54/Intermediate Certificate 2 PL.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..506761d71dc09d527b508e3709d9a8f5322a53f2 GIT binary patch literal 666 zcmXqLVwz^q#Q1*!GZP~d6B9$b0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE;5y1AO!h41vf%PMp`$0!SMg8UaazC~;mBWG-#&H$vFoI3L-^jI0dIjlB#8 zjh#%5jSP2WuW01H71-D6Y&Tbb#VW5q52Q|R730f0vtE6fqgHdeRKU51I~(I;U$4HF zy{luzM9YKIKTb1T^JA~oj`FXq*KW#B^ZqI@u79c+a=dYd z$D*WO{`GHDwwgT;_w0zs2w!&ncy`A6v+pB9{f}pfmQOnURF{dFk%4h>vO%H&KQQQI zg&7(Dv#=U411WIm%JPE*Sb#Cd296b31r~k-UIT76&V)7(##ClT14aWukVZZhE*6fN zUH1%wmEx9yqd``g1sGoq98$@bAI@1_y8<~3fU(XD^t`2nu7!nLx$qLkw52|~Ba(ae zHHKcFd3ce2sl}PZqmj~*iY7c03%e`)HIH90`}67IMv*|XRhH$^N?zPPdB07~Rn(9xdrxJw3e;0N)4B)&Kwi literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test54/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test54/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test55/End Certificate PL.01.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test55/End Certificate PL.01.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..923d4c5a84a3e3ada34672fb2870b294328d970e GIT binary patch literal 666 zcmXqLVwz^q#Q1*!GZP~d6B9$X0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE?pH1AO!h4D}3*4CKUlEiDWT4Gay9fTTf`IIjsZmp1krBkXUSkL+VcRtDzA zUIv54PNv32hReUMTh0-w+!7^w_`K+&$?VC~l#Lh~SHH@icyG-Ix#DV0&dYut+f6KM zWkq-9EWUTm{q(wuc#pU2ZOvtyoNNwE5)Jr) zK_@HB$oQXy)qojDfkRi8A0)s6jJapvSdmp=;Wywl;AZ1YX!Br9Wo9&BG!O)7uE zT=vyJoL|@RJ`3sD8hApgN>uNCZP~9EZf~2d4<^q0H#Kdteo}+XvqpuWHMQ-$w`=vU zn_rxs`B-O@4e!6jR?`jE>^Zobhd-x&eqrxFiQBJtXxhws@I7;8+L{W3lh+xPS`Ck6 TwLf>fwj%KRM<*W3zytCC)o#(_ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test55/Intermediate CRL 1 PL.01.02.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test55/Intermediate CRL 1 PL.01.02.crl new file mode 100644 index 0000000000000000000000000000000000000000..371821e5e217e0ba942f1f80fa6b65a2973ae2d8 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-2fjw14BInBXM3!O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aOho zSD4*qV~Iv{F>_-hLyC8um`Pq7=eab#FO9DzJrd0k4-Jc4qskb#tmn71OWkV*)AIqo zvlI4J9N1p4{ojOS##g74HgJBguyS2;sJ`$(%8vf02f6tp9+h2Fexto{e%QMo(iLq} v16?I|ugK`Cbvw4Px$xVWpF1MXGB7mU>{3imRqyuVPwH*r<(fJ9MgLC#5r1XN literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test55/Intermediate CRL 2 PL.01.02.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test55/Intermediate CRL 2 PL.01.02.crl new file mode 100644 index 0000000000000000000000000000000000000000..9a242916e1c4c47b906b29b83ef2354fb4d42956 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-2fjw14BInBXM3!O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aRHM zaK~~vY|BG)F>_-hLp+<`q5WxV-faqarLpA39mNB0HmIs>Y}dH*F(F#s@1NkRZ{D#B zve*h7+FEb2`)uEqx%Zk_eDc}c`e{CE_%Eg2jkrB`i{stP7p85Q-}UcKg3$At)t|&a wY;@xPz;$)SDS7OLxzy*@w7G`$IcQF(&;DhkkLsE-NGV{_6MGb^O zBFw@(Aw{LdB?^vt$r<@Y26E!OmKFwv28M=4K++&eoYw@IOP>8HcmURhyN%HzI4*r~qs(Uc_po{N#aq5P%#tY!=Lb^dq0zE1Q+it7GPA&d4OoAyVv zUQ0LNsj1zP&0-rEbX%U)<=K_5CeP#kXb!w>Po0002Lm$2|Z5 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test55/Intermediate Certificate 2 PL.01.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test55/Intermediate Certificate 2 PL.01.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..982235a210c86c30e16bb716e98d55b2645697b8 GIT binary patch literal 666 zcmXqLVwz^q#Q1*!GZP~d6B9$10WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE;5y1AO!h4D}3*4CKUlEiDWT4Gay9fTTf`IIjsZmp1krA?$CQkL+VcRtDzA zUIv54PNv32hUp(4$#vZ)EHb*Z;fm%_vFhoNriE$NNl8K8N|od?JfDXDBil zl+Ctz8#woMzS}>~l$glm8z+JazSTM~pEp(f`|#|G->WYeyjEV##LURRxH#D$(SRQq zbh5&XjQ?3!4VZxxICN$CK>{qmm}3LSimU<)zX7iSHydX{n+IbmGot~cfgngD9}5=? z$4?XPST2WcdEjV}Rb~OkR|7|;^$N4wY%I~pVE~MEW}xQ}Rs0YOI5sD&<=TsnyWA#j zyQ69Qq-L46oZ*`khC{!9FsQ0}f1W3OHPvfF*4M-X)33XhN}ihiVuo?Ie#2RzhXpeq zY&JK(z<2uCX7(RJMiI^r(uy}ZsO@3@A3g6xZH{h&Q0g(u=&-ydRttBxCPC@hA9?5U SEdEh;Vsgbp@e+yLiUI%=AI&2G literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test55/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test55/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test56/End Certificate PL.01.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test56/End Certificate PL.01.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..d1dc821862c6442b0f76333ef6b4eccf50aaea9c GIT binary patch literal 651 zcmXqLVrn;NV*IdxnTe5!iHV`tfR~L^tIebBJ1-+6D=ULRoFTUXCmVAp3!5-gXt1G# zff$IxCCneH7p$k?o?n()l$V>DS7OLxzy*@w7G`$IPcalQ;DhkkLsE-NGV{_6MGb^O zBFw@(&W?t<0X}*LhI$6Z26E!OmKFwv28M=4K++&eoYw@IYmh*W{VrJS7dH@v*v}VQ zoLYqBg2wsCer9B4U~cSXFlg*#YHVcKuzf*o(}d6e<=@Zi5w8!HoxprALv`l8X-boL zTvB$O+4a&jqc?=Fz_?L+(!RzcpIyBqR$Q92=S2MF*4h_Kqi3B>VSSOdBf8~6U_ zSXINFk#V_nmE)PI&U_5N`8>b>;)>w^9lcpIYC`tq;PQzFDvn3gcAUxnen+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-2fjw14BInV{u+fO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aO_h ziKwp)eRUJf#mtS33@;)N>Xxp3Apd>AU;Y@Ei1uxv_wTIxcXKaKL4f4JX7NKFo2FWe zzij{i_IL2l;1?o>OBSzec)?cj^RnX;WAodB8*5yxb0DS7OLxzy*@w7G`$IcQF(&;DhkkLsE-NGV{_6MGb^O zBFw@(Aw{LdB?^vt$r<@Y26E!OmKFwv28M=4K++&eoYw@IOP>8Hc=xb;Wywl;AZ1Y zX!Br9Wo9&BG!O*oB0WyBF)~{O+4x|Kxb=oSjv< z{&%-b^;K2$J3pO&b+kyRjNjHTGnrC1iBzAkKXB=glN}YzCO%#r kerx{?1-8O>vKjlt&d*b>ll`6;)%oe*Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test57/End Certificate PL.01.04.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test57/End Certificate PL.01.04.crt new file mode 100644 index 0000000000000000000000000000000000000000..2f939384ada16211fa34834f5f35b4435b9e187f GIT binary patch literal 666 zcmXqLVwz^q#Q1*!GZP~d6B9$f0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE;5y1AO!h4D}354CKUlEiDWT4Gay9fTTf`IIjsZmp1krA?$CQkL+VcRtDzA zUIv54PNv32hU;zDi|fNXvu{7zn|yWy^SNE|dAu{e9c-NV{E|a8kK^1Rmo3#h--PjR z*5mD{NNw=`nfx$gQuf`o$#a-ApLbM!%2zw6Th7PzktKG2+g2~3d=Hmw(|b}p4^BK@ z#Q9(EyXleL2cL!O%9&-GiY1@gU1zu8@T_H74a&<3?6%rT-DhfKVrFDuT%2r>XuuB) zI$2>x#{Vp=2FyST9J;dnAORL&%sm6gimU<)zX7iSHydX{n+IbmGot~cfgngD9}5=? zhkRljQ~Vj}%iw5`Rb~OkR|7|lx23?%D~o!O!vGlT%s|h}vNx#;y57Gi7=Gu8`ErFH zKD$pn3Oys*Xljskn<;ABf*{eCT(?io{PSZ^mg$;hQr+pPTSI?k<@fS^uG}g-$Jp&X z_enp_^N(ylSyrZe`l?hmU;54US9>mBNxro6#aX@IK8-eO>@IwqDtm8nNQaDUkCe=} Tj5W>5)n~nzHn+-E?tTvd)4b8q literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test57/Intermediate CRL PL.01.04.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test57/Intermediate CRL PL.01.04.crl new file mode 100644 index 0000000000000000000000000000000000000000..a0be908ae3b676ee61550a208dfea524702a1185 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-2fjw14BIn6LDTkO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aQga zEd_2~S=5W>V&=w1hWwM^*RL!Mxsp+Q*@pM?}YF;5WSt~tK4^!4pk zZys20(5tmx#8(%&@?Gbv_Tc?XvK_@&yly@C_|eB(Q_oc&yD7Nm=48kBXLi=|8CRc| x>1_)3`cYnXRL{u2E9c>d*uB-)7z+(wn7@xGJ0@bqeslGT8A_d7RKt%b0RXGEYv2F? literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test57/Intermediate Certificate PL.01.04.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test57/Intermediate Certificate PL.01.04.crt new file mode 100644 index 0000000000000000000000000000000000000000..79f6d6b8ab260d0269cee9f45e73e699fb5aba2c GIT binary patch literal 669 zcmXqLVw!2t#Kg3KnTe5!iHV`lfR~L^tIebBJ1-+6D=ULRoFTUXCmVAp3!5-gXt1G# zff$IxCCneH7p$k?o?n()l$V>DS7OLxzy*@w7G`$IcQF(&;DhkkLsE-NGV{_6MGb^O zBFw@(Aw{LdB?^vt$r<@Y26E!OmKFwv28M=4K++&eoYw@IOP>8Hc4QwtY&NcAY-3U0^OH&4#r$$j@k!qN9%Qums2zCC^H)Pz~@^Mnqtxuv<>f0AR^WE!JWX6Y9C zZGz?AeU|t5jsJY~{rP!U!_6rL$0XvkUEG#O>XlrvJe|QHv8*~#-NeJ$hhLN-d*PKy i^?`ML+VxYpcO-kJmPp>Q_WuAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/End Certificate PL.01.05.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/End Certificate PL.01.05.crt new file mode 100644 index 0000000000000000000000000000000000000000..674009c8367dc0fbe0a1182ba6472729037c7434 GIT binary patch literal 651 zcmXqLVrn;NV*IdxnTe5!iHTvd0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE?pI1AO!h4D}354dldmEiDWT4Gay9fTTf`IIjsZ*C2r$`(3cuFK!?Tv7axr zIJL+S;ey8b$bM#IWngaXWiV*$WNK_=I21GEvqn1iiO0bwp6%Mm_+DX|2a~L3nk4px8!jP zc13{oC zW%*dRSUB=I^nz^{Eh_+ryR0$`FoGI5I79E{Tu=D34%y4VXl4fbHEz=JvUPKRsPko6 z++2L_j78=BrIRL_+>XEYEa1+9J1y+f|9)(ZTI{`Vw$ZA4Nivo5jJa9wodp)yO_1AxX0|2&Q({BI( literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/Intermediate CRL 1 PL.01.05.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/Intermediate CRL 1 PL.01.05.crl new file mode 100644 index 0000000000000000000000000000000000000000..aa9dc9d7f3584cc19b0b0fc039bfbad2e71d519e GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-2fjw14BInQ*mBPO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aU?t zpXJ@X!-);e#mtS34A1l|8(fYu^DX_tBX|4~LrB*QAKuux8$PXdV|KlB_p)5yQRQ=d zpW_{Lv<`)wjNACAMETq&lSD(cn6mmaenE1w>-q!*V|rd}u$n%(>AK>+DR+5K+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-2fjw14BInQ*mBPO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aPg_ z7Tf!!*5@XgiIf?n!28)uHnJNXO=q@^sWh50|2=@Yq|gc literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/Intermediate CRL 3 PL.01.05.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/Intermediate CRL 3 PL.01.05.crl new file mode 100644 index 0000000000000000000000000000000000000000..bec634480e1e6617fbcee52f425636bdeb66fe7d GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~m z-2fjw14BInQ*mBPO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aOyZ z@8w)i__Gep#mtS33@h6=iY_vmILq|S+bM3dT*ACgmMYbw>AEI?1rHR%*;YggYy)%II(QdA}YYNV^0sxg=YHt7l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/Intermediate Certificate 1 PL.01.05.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/Intermediate Certificate 1 PL.01.05.crt new file mode 100644 index 0000000000000000000000000000000000000000..42e983122fc9bb50110fce4989842e06736bff8d GIT binary patch literal 669 zcmXqLVw!2t#Kg3KnTe5!iHTu?0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzIna?_wxmzz5;6holylWagzCiW&%m zM3{wnLW)X@OB5XQk~8v)4CKUlEiDWT4Gay9fTTf`IIjsZmpuDZ@Y?U}Xs8?Dqi0~K zXJBg3I3L-^jI0dIjlB#8jh#%5jST;`Itrv!^r;!UTk^X6pbRh+$(!BHqNC0uQ) zt5xk^C*cqBiI=baJ!!A7lrPKOzmxZHJLji@WgQHgl{~W-@I0IU>aKa~{o4y_gQso( z&cw{fz_>WgAjLok7<972jEw(TI1Jc;6cZyGIDlpOL1HYx$YTRXjI06+zX7iSHydX{ zn+IbmGot~cfgngP9}5=?$Grcuyt{Wev4LYkR+$ADWepswXTAP;=y^y#axefRo*C$W zgDuQSJ%%dFB>FQyPi=c!7HS~+|LBDq7R6htizoUD2Ho@cyJp#zlOA`j)~~#s!0^e{ z$YNK7(#v>0#%DzCXi;ZTO> iLcYd-?jj4)MI5X$-L-!;+>mts=Xo}E#$;vIyl((;n9#2P literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/Intermediate Certificate 2 PL.01.05.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/Intermediate Certificate 2 PL.01.05.crt new file mode 100644 index 0000000000000000000000000000000000000000..08eb808c4fe70e3b19a594a3008c2422ebba8596 GIT binary patch literal 669 zcmXqLVw!2t#Kg3KnTe5!iHTvN0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE;5y1AO!h4D}354dldmEiDWT4Gay9fTTf`IIjsZmp1krA?$CQkL+VcRtDzA zUIv54PNv32hILv$B$w=3@ACf3XX%WmH%dM=@Z1W`nZEl=Uhbc`jc;wfu4fhem0KeG zDC?`V=+CeAbA3MdOg*0S>E_&DvVoy#Yb%WR^4qZ|SM{m)~6jRyS??bOq^OaudLDZwGBRW z{Qt7zeRVqdbKAqGO8;7N)A9ebUESucr>CEGP-cr;@NHg$2!qo63?U0=^YCk17O7ai VYk18jE1&AW?^M$#UbE0M%mBOK&0_!n literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/Intermediate Certificate 3 PL.01.05.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test58/Intermediate Certificate 3 PL.01.05.crt new file mode 100644 index 0000000000000000000000000000000000000000..6c5e6efaee70a159bbbe742865f8186cdfb37ad1 GIT binary patch literal 669 zcmXqLVw!2t#Kg3KnTe5!iHTv70WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE?pH1AO!h4D}354dldmEiDWT4Gay9fTTf`IIjsZmp1krBkXUSkL+VcRtDzA zUIv54PNv32hOGkI{(Lxg&!z^4HvYEWz z9-qVXXlh8}*VRlW`&b{(UUw#`z!T{rGzs{0fIE z=RZ}BezTCBqa;16IK(q0{=!B9tv6Rrm+gvKcQCAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/End Certificate PL.01.06.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/End Certificate PL.01.06.crt new file mode 100644 index 0000000000000000000000000000000000000000..da5ee9e694334535a867ab56f87c50b641291b00 GIT binary patch literal 666 zcmXqLVwz^q#Q1*!GZP~d6BEO9170>xtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;KgCeMfDgiB4@oU9$;?YP6g3bA zi7*TEI6E5a2KeY180s0A8OVwAT3Q$w8Wab6Q-E^X{LLD=6oAKAx@tPISJ zy$lA8olK3540l&EteCDGSHZGd**>~{GK2qw^-Z~^?geZ&S1-xTsNp_YmU^5~W|8@~ z^p_fYa*}MK?KvOzcTeAQx^%I~g99@cuP8`Un{ddZHv3szftL3&Ym3>&LiKZwd$Zi= zEb7U&Oq-L);TzMXm!PDp(^mN?-(qT3SpV7761T9(<@RE(b=*wMj0}v6lMNCL_<=zu zE6m9FpM}+c8AyRcSC$_nzygf9XW&?oRbb&a;5Fc8<4kDtU`%CZG+;Ck1Zm`B;bP&~ zmgl|ii|K(k;AoIlW&y@m1Bd*ogrH<0r%L270LD5q(DTWrAD5JMpT2aOTdeiaYnQv> zMV|F?3jSs@GIBqy5R~JU&W{l@<#()kH_1dsEq2Zn*0Y?^F&h@FNEH5_=+nTyK=-${ z%C1M@TU>UF^qjf3yFO^brDxuu+!czyELfKO@KM;t5fgJGIU=dfE2{DHzFF?tZ>8FU QtKFIQb#rFCS|gtT09|RqCIA2c literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/Intermediate CRL 1 PL.01.06.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/Intermediate CRL 1 PL.01.06.crl new file mode 100644 index 0000000000000000000000000000000000000000..eb7f0e883d2c9f88d6b185937a04df3fb63fad40 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-2fjw14BInGjU!^O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aQ&D zyIwIIjGKk#V&=w1hK^#>BhfRquXf&eYV#pmHJ#$)0Xr`~?tgEte5KiGdART4^48lT zHDAQ;Fl(^}v(7hsulDkD^=y@Dmw)rsZSzvh^THfnMogT=P;km6&gAp7{+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-2fjw14BInGjU!^O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aRC4 zdN)YSW^+b!F>_-h!w!?y=%Bvho{B4l>r2Hp{JEX9#CFqblZE%P0~hsOcrmwe&+K>e zHD{XmJX&nv*Xber*;pa>+Ovm?j~oiTnAPO}`OQX^POprzy|U+SoNwtnsCByY_-~RyLDuerQc8vw-OZkqrA literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/Intermediate CRL 3 PL.01.06.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/Intermediate CRL 3 PL.01.06.crl new file mode 100644 index 0000000000000000000000000000000000000000..cb7885c171d2beabbf32c89f6830648d00226aa0 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~m z-2fjw14BInGjU!^O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aU)v zB?Ki4IaQ*$n7Of$q2T+upAz4+lDBe8ywljIWa+@MdYYPhtI3OYCYEHwY1`dH3(ws9 zzLI6Bs)5<$hmLcmK43KX`d8Wh`?dB@abfkfOnwW^axW-Zdpy1%JS`>YNI8r3l$C$$ wHs&xUE4WYEu=mLf&k5(aYf^S<$7j~fRlc}G@63hi9wNbYCNtahO}3r}0KeH|PXGV_ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/Intermediate Certificate 1 PL.01.06.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/Intermediate Certificate 1 PL.01.06.crt new file mode 100644 index 0000000000000000000000000000000000000000..be0ee21f2e38efc8f52c5687ccd5616a6e02db1b GIT binary patch literal 669 zcmXqLVw!2t#Kg3KnTe5!iHTu~0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzIna?_wxmzz5;6holylWagzCiW&%m zM3{wnLW)X@OB5XQk~8v)4CKUlEiDWT4Gay9fTTf`IIjsZmpuDZ@Y?U}Xs8?Dqi0~K zXJBT~I3L-^jI0dIjlB#8jh#%5jSL4LG;}!j=&P$Oyzx5VkeGmDPMi0`_^iK|8JGV4 z6{5J_*YnD^`)0<%tr{P?O;7Vo{n`G$QFdGZmvHeFe=OEdPe1Xr@yAskj%2QqYsr@m zyYFf^-k@x#P|NE;B zFJxk7WMEvJW{_ea1PnS^VMfOPEF1=GK#GZx4IIF-{2(zFVC1oZBSuz%h2MbJfSZjo zq0NIam6_3i(LfNSmyd;ug(KIw>lMSnxLM$skX2>@Mp*;L>RGRU9(o?qj~ooZh-U`* zKYvR^56|IW^9xq5WV&=t%Ihijmfd1IU$BHLEa_OK%NIC7@7r&tcwzmF{EJUFsvgq& zl-pLR>C*e-=iynQhLK4>754?EUVYHN>Ce5MZePyXJg1*zueuabVW75NOEy}yO@8Um jX21OQ&zsNG7F}4q`9nf)y}^VhnT|Ua1UrPN-xdb|pn%t( literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/Intermediate Certificate 2 PL.01.06.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/Intermediate Certificate 2 PL.01.06.crt new file mode 100644 index 0000000000000000000000000000000000000000..a84a7ba5e0e82c6250b28ae97dbfe2e8f41c4c55 GIT binary patch literal 669 zcmXqLVw!2t#Kg3KnTe5!iHTvV0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE;5y1AO!h4D}4m4CKUlEiDWT4Gay9fTTf`IIjsZmp1krA?$CQkL+VcRtDzA zUIv54PNv32hJ*il>-|^1nSJDi@D9Tbx4lEYdgwfVe2 zRqkzh7Ta|lw~{6MZ%#@vm-=NDBv?@@*)-2Ex_mm1zlf-;*N0|BCT2zk#>Hs{DF#Bo zppzA5Wc<&3zr0W8Z85@P{I9ve7fWEEKW4R{T>**Fv0JQ!1%84VZ>1VMWF zSh!d?eBXLENX%w)2FHY~G7B)u8aQ&DyIwIIjGKiV48VwI2KwKe(P!Di;+?%k6s@(BYQ9TX$keq^|I?3=MmO z;|#8C=lhh!x6OR@z~RrXp6ZPYRh8_mzH^4&3_4s`z2m#$A@7x&N}qbQiPRM>le?7N WruJIy$GeQym-#7kZYmeco&o@Vs?K5n literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/Intermediate Certificate 3 PL.01.06.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/Intermediate Certificate 3 PL.01.06.crt new file mode 100644 index 0000000000000000000000000000000000000000..0b13f9f9b180ffb90de25efe04e1fc60793567ed GIT binary patch literal 669 zcmXqLVw!2t#Kg3KnTe5!iHTvF0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE?pH1AO!h4D}4m4CKUlEiDWT4Gay9fTTf`IIjsZmp1krBkXUSkL+VcRtDzA zUIv54PNv32hC^#-Offnh-?U`Q%FjA#%JY1!zcf6Ean7D7ke5<&P?2ZmA_ez{Q`^@* z^V(eW{#@~&o$56ePJbpoE_m=q^5v4RI`Jphe^p%*!aHx$XUEVF5(#?eq+L~8QY}AO z7N|uqo=TptD*7OGpV1q}vaaTnhm~h7(*J+JX5XviEb;qA2@YAOnV1_362R_WfowRHE{U8^=^=u&E||848VwI2KwJ(`r79XTvq~oV<&5I z@ANSDpL*u;+hdUdES?>c7P3n~#H;NBrvkzyzT=r;kTI9o$d)2cx XRNc6kpLp%1<+9eivrC(o%N_s#BFoca literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test59/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test6/End Certificate CP.02.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test6/End Certificate CP.02.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..1e68f0de17cd1e82529d3c50fe2c36c841114867 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iIK;EmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uC<0eS{TdIrV@a^k!u<_3lahK5E!(jW@RwLsz;B#>jj3l{su4MZXK^Mw|t z79qKyaXzx28Ce;a8+#cH8atU98yQZ9y$J3;B$A^!*=o6u!9zx|UY^Ix%oMe1zOxm5 z@Vq#4#qk}7&C+?(?JvG*wm2{;u}I8G(%EQ<`fY=$wi`~JIg(Q1KGEx=Rg*-7{g3o} zTFKrFf1KG?E&QWbAOIYkviyvU|5;d=nOGlyqd``Ih2MbJfSZjoq0NIam6_3i(LfOBNm)J? zE*6gBufHbEdt0Fb4tH5)7GMN5aB!#m`yz>% literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test6/Intermediate CRL CP.02.03.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test6/Intermediate CRL CP.02.03.crl new file mode 100644 index 0000000000000000000000000000000000000000..d87cd7e26c1526f3061765401d842c59b70b981a GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zUFQHj10y{HV{u+fO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aTL9 z{{4|;`(A+NV&=w1hADy(d;TPfb}NfKl6P{iHfHMR-u=LiOU&nA{7+7gOWGRqXZ|p+ zx}o;>YpYqHtMK11(_*S4B3?{U+8?}j(!|}NUpU(KvNGfZn=W#G5w}`*<6`OKQp@|N vc5V!)pCP&5^+K`gjx0ANw#E{2;3narW%##IH+x(!n(fTfI~e8uJo}BY`tlsp!jQhl%*{dn znV1yBI0E_w7lmGw# literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test6/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test6/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/End Certificate PL.01.07.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/End Certificate PL.01.07.crt new file mode 100644 index 0000000000000000000000000000000000000000..8741105ea83d8c09df9e4c8f74928e8de394422e GIT binary patch literal 651 zcmXqLVrn;NV*IdxnTe5!iHTv30WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE=Sc1AO!h4D}4m4dldmEiDWT4Gay9fTTf`IIjsZ*C2r$`(3cuFK!?Tv7axr zIJL+S;ey8b$bM#IWngaXWiV*$WNK_=m@B_ljpb~dQUTMR2Q~MNUT;&Mz4}6BfTROs z$ewS{nGfWY$~-D)=QLx=erUccVu!gMOUyg78|;g$W_nl!8t}djJGivrrR2TC6VCl{ zd|zYtxAYljS3!Ye_mXvTP4U`S7tfgOmiFLHR+Mnw_XjWDRh=w0INg2HewDoaPw~6k zepgIpVrFDuTpVN&01i%Ben!UsEG*1StPjA^AgjQ_Z@_E7&BmF~=E0cC%xJ)9APDrN zEFTLO3y0^_UEAv3x*i3GyR0$`FoGI5Cb$&N=5brsgzRNtG&2MJ${feI`z1pS*d zQ~H=K_w7u7QCXk7^Em*#DK4(=Fzu`yT%$X`A{t)=J^d z+t&+E>3f}f+4<}doetxy7|ZExfeZAW7=_JunRwXbjOsd`C+l|~lK-($`PylrMLQq7 Yx*7Uji9ud4V2|EEi_PMEWlv@T0IFQgwEzGB literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate CRL 1 PL.01.07.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate CRL 1 PL.01.07.crl new file mode 100644 index 0000000000000000000000000000000000000000..e778e911d1c752b1536aa89b7cf06dbcf809e232 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-2fjw14BInb8%ivO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aTF0 z5vq&**s}r6#mtS33~JX}l;it3E`9yGgC%6?6lLy*&rdIyn^AanW7sQU&jS~YzyDeL zBj{$$t;>IWUaY$(8p`PH#P?6iX!V5d#VfyfN;h3!TOj&zw!X*j4JY{*8VAmmNjTqT yU--gOS?sl;YAeg;3B^?rYir literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate CRL 2 PL.01.07.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate CRL 2 PL.01.07.crl new file mode 100644 index 0000000000000000000000000000000000000000..4f4ac6bc01669f9f36177a9e37c44edcf88a8782 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-2fjw14BInb8%ivO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aPz` z)fh^dZ=8kZV&=w120hg}mZe)OM w7Ux1e>e7T}zWj1|^|kHqwg)!5+n8*fzr4l%yoBiuyY~}p>lSzE>X%dj0F^vung9R* literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate CRL 3 PL.01.07.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate CRL 3 PL.01.07.crl new file mode 100644 index 0000000000000000000000000000000000000000..0b568e7cc87c4edf36835bb98ffcb0b25215c8a5 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~m z-2fjw14BInb8%ivO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aUS2 zs0E(c8~zT>#mtS344!?~%kL=*$-Ab9ytdUho13sbeVJG3g1<}MZmCU4XK1hd%I=t9 z+jMOGq?)tG{bK$!ZD_Drqc`oxVLs7^%NzgCUVGu+r07$zw{y;3F}|lPq1@1CS!lB)64cE0LoNkTmS$7 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate CRL 4 PL.01.07.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate CRL 4 PL.01.07.crl new file mode 100644 index 0000000000000000000000000000000000000000..4cf694a9873121d2c36b4d68dae84e6ac571eaf8 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}r z-2fjw14BInb8%ivO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aO7n z6wc;xTi1l%kY<@k$k?MJY=6bvp!#_T`Ffyq}v@Y`pM(o8c`P%YE}Z v#coGCFsl9$e00n+TSV%5&s~v?iA|kb@1*NW^uD_0H~&-ND+YG^%b+!5 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate Certificate 1 PL.01.07.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate Certificate 1 PL.01.07.crt new file mode 100644 index 0000000000000000000000000000000000000000..01d844201b8ccb3dd33574838146505f97efcfd5 GIT binary patch literal 669 zcmXqLVw!2t#Kg3KnTe5!iHTu`0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzIna?_wxmzz5;6holylWagzCiW&%m zM3{wnLW)X@OB5XQk~8v)4CKUlEiDWT4Gay9fTTf`IIjsZmpuDZ@Y?U}Xs8?Dqi0~K zXJBs7I3L-^jI0dIjlB#8jh#%5jSNpJg&t4#-nD9PI%D{A0O9z_V=QwD#=%}jf*#Do~(Yhn9C0J%D z6EhOLqv{D(5vm?JRzJuWaSoZ8L7(pZ@xq#Kh_p)4(&6 z%Ud2!_^F=FBUyR#_Qt9HtNHb=Wm!*pAg6z6HJ5Mgw@*KE;~AQND$C3lX4W$aFsN!d jxqEuYpBYXY!hJ8xMt!~-{rUNY332v|Ha`4y(%BCHpJL3M literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate Certificate 2 PL.01.07.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate Certificate 2 PL.01.07.crt new file mode 100644 index 0000000000000000000000000000000000000000..0054dc62264963fb5e2774865cc4ba503e28c123 GIT binary patch literal 669 zcmXqLVw!2t#Kg3KnTe5!iHTvR0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE;5y1AO!h4D}4m4dldmEiDWT4Gay9fTTf`IIjsZmp1krA?$CQkL+VcRtDzA zUIv54PNv32hTZ!WX4<(QN^lo^-}Uj+>4voarKi8%o$N7m$+eBAIyPLb7S<2G{faA{QA@__ zuHJ^VOLry-_g&mmvEbLu*dXN-`SR`UJ0lH^CR<;Lm@k=c()ndJ6EhrOY?Z0>^}`G7B)u8aTF05vq&**s}pS7=RJa4D|mkul4u&I}2nBE2A4V zlPT)H9P(oBDTo@I+at+~6OcjCeB<=Zq-@N|vBo&#jk;3y z2SM56c@d@4of)>zKk@%Y;tJ)u@9}yS2Q4q0)G&_W&po-?rL!Pn(>N)Gf_R literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate Certificate 4 PL.01.07.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Intermediate Certificate 4 PL.01.07.crt new file mode 100644 index 0000000000000000000000000000000000000000..c5eebca96031569bad4b3ea8d3ed77b8fdd5b827 GIT binary patch literal 666 zcmXqLVwz^q#Q1*!GZP~d6BEO1170>xtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;KgCeMfDgiB4@oU9$;?YP6g3bA zi7*TEI6E5a2KeY180s0A8_0?CT3Q$w8Wab6Q-E^X{LLD=6oAKAx@tPISJ zy$lA8olK354DXVIK3?2>iBp_+L*SXeo0eYo$r6e-E*CN=-qPBYzEfH$CRI^Emg`|^ z^nAOu>o?wMuUWcf9sAYZGTr|&F^{qmm}3LSimU<)zX7iSHydX{n+IbmGot~cfgngD9}5=? z#{`$c**tFRn!wQ@tIPt7uLh1aHfn)q_J+Sh4g+AUGXp)Zep_Z$p3BUePhCwmY1FvA z+0g1`CHcBw`md_G6MNpXalDSoPujh&El=>_1D>=W)lrKcANOW0Z{~`WG`U~0MzqUR`#euo T*|sg&tzum#r^Y*5#HIoO7J$*z literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test60/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/End Certificate PL.01.08.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/End Certificate PL.01.08.crt new file mode 100644 index 0000000000000000000000000000000000000000..7be023cafeb9026ed967cc78bc57cfe9ef880ee8 GIT binary patch literal 666 zcmXqLVwz^q#Q1*!GZP~d6BENi170>xtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;KgCeMfDgiB4@oU9$;?YP6g3bA zi7*TEI6Io?2KeY180r~V7|4n9T3Q$w8Wab6Q-E^X{LMcCgsAKAx@tPISJ zy$lA8olK3542PIgTDk75%6K@zWf#u{v3pOrHJa{-MIGJqGOWh<#XQ!}9LwjGpG#l1 z=$}wc#-l^G)_80>^x*Uw3;uc!uDMe$L`ZIqjF{Q>AW@P-&!fL<_q`;vo%MTJ@0mj@jaIDBGu<#r38gR35CbW4lrZO`cFd7JgH1e@< zv2biZuw<_7>2JQ^XpmKA0mfGYM=Sfbtt?@?rK0yVhdmd9+XEWEys4k} zg1xv~JEv}c}^ UT2waAJKOVHdwGG=s_E8~0YLxN2><{9 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/Intermediate CRL 1 PL.01.08.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/Intermediate CRL 1 PL.01.08.crl new file mode 100644 index 0000000000000000000000000000000000000000..05c2809aaea2415bf84d741a094d0ec25a8dcc53 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-2fjw14BIn3vpgcO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aO_S z-A(4-y2=2}#mtS34AKc&?oo2nsxCLlRn1YSaJ# literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/Intermediate CRL 2 PL.01.08.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/Intermediate CRL 2 PL.01.08.crl new file mode 100644 index 0000000000000000000000000000000000000000..d74b9168c218c3ef3a5f463f16d6938fcfb34d9e GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-2fjw14BIn3vpgcO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aN_8 z8keNx?(ju(F>_-hL;U{^J_o}$pDuUjRAsiE&OCfE(`B(y`JM*{ZV9<5F|QL{T;Ba6 z>{NA}@vVd$+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~m z-2fjw14BIn3vpgcO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aNVI z6CZiBZ7D``F>_-hgEw#8tBuWCTp?S_na-&&_3Nw21bjOixAD)f!r6(7FZ%DSh&+*V z_}TiFE6MDaEQP0>JguZ!e=YmqkzGqWTiRnb6f?XvlfR@gU3-2tTg2n$#`>!g#+SLe w`+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}r z-2fjw14BIn3vpgcO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aRSk z*ZnAK<*h+;F>_-hgG|xf;E*|m)?D8&gz)V?`n^`J=ZeFg5}xnUe=f6&FzePFe{%YO z;GaDv&+Kzc{^&(cz7??f)oI@A8IEk%)V8Rct7*LQr0b%cspfp|i;i|liEe5(Uu=AC w$i{LN&wKprxwY7dJ#lZhBp-_NU6dp0dUey!L%UiwCgn(6{k>K+@uc(?04h6ZtN;K2 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/Intermediate Certificate 1 PL.01.08.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/Intermediate Certificate 1 PL.01.08.crt new file mode 100644 index 0000000000000000000000000000000000000000..ba03f6c24abd60f26ae74d8f3f5834227b702949 GIT binary patch literal 669 zcmXqLVw!2t#Kg3KnTe5!iHTvZ0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzIna?_wxmzz5;6holylWagzCiW&%m zM3{wnLW)X@OB5XQk~8v)4CKUlEiDWT4Gay9fTTf`IIjsZmpuDZ@Y?U}Xs8?Dqi0~K zXJBE_I3L-^jI0dIjlB#8jh#%5jSQRiFZxoGV7=(M<+_a)<@dgbcZXV8bWX2XH*bpX zSu<{DwT&9@l{mi#scj10wnFyE@lO}TJ>#P1J9Nl5RJ>aBY4-mY!s`nn8+z5HRRug&7(Dvv3%&0VyU%HgEvT@`J=!fRV=rju=@57JdU>18z3X zgfPMm#gn z|Fyj@^%EL@PE_-GxcTfli?6q2;8%$ zRB4I1;N{&lTiUmnow&GYM)l7R26?89wVPs3-n=VQxbcb9wC1Ca9vdc#-s>rzyi4QV zjn&dN)3Ouye{m?;$I_+sxBN!dCa1owOtW=!{;}Ks`*KHKC+EYN?@Y{$42+A@3{nh) zfI%lK%*gnkg~NaiNHH-of&*BVA0);Cj661Q#K$(o$fDP)h;LeDf&0<7$0w?wIf>% zmqY%s@Rl`==U=azXl%UWs4Kh3ncrJ_|IE7i^-s!$bPtOc`+}?XrMYj@)ajGk)n2wG XGkT5C;|VdgdlxYaepn3gR8ef-r?rQxb%}CMiq`3*=8d@~!7~eg7G?M!?<${FD0*Sm zMdj!JEO`~S#$ZuK_n3XF{6?V=6PF0i%H+NG~4? z7Yj!MYvLo1wk^frn2=Rw0Y+H^N5n_tl9b#XzGxB84D`R?ty!wOH+;JAx$^qbOEw-$3GvwCUdE(=~0I RPQMTeaye1uI%h-eDFA?J#{~cY literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/Intermediate Certificate 4 PL.01.08.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test61/Intermediate Certificate 4 PL.01.08.crt new file mode 100644 index 0000000000000000000000000000000000000000..5962eedfade82d7605df4374c2fefdb53954bfd7 GIT binary patch literal 666 zcmXqLVwz^q#Q1*!GZP~d6BEM%170>xtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;KgCeMfDgiB4@oU9$;?YP6g3bA zi7*TEI6E5a2KeY180r~V7|4n9T3Q$w8Wab6Q-E^X{LLD=6oAKAx@tPISJ zy$lA8olK353`Zj#YXv<`H=o(Mvfnz{d9HMrag=g{fS&FgkPWnyMzU|gJRkZ8aU z3_4k1M#ldvtOm?L3LLt!{2&1qV9c?BV?|bhh2MbJfSZjoq0NIam6_3i(LfNSk&lIo zg(H}C-H)}wN86TSJIGSgu{v$EiwyIq_{I};Xt U*%aTe_}0&4{Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/End Certificate PL.01.09.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/End Certificate PL.01.09.crt new file mode 100644 index 0000000000000000000000000000000000000000..bff8ea4cbc80ff731c8f1e9ce76970ac3e61ab9c GIT binary patch literal 651 zcmXqLVrn;NV*IdxnTe5!iHTvE0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE=Sc1AO!h4D}2w4dldmEiDWT4Gay9fTTf`IIjsZ*C2r$`(3cuFK!?Tv7axr zIJL+S;ey8b$bM#IWngaXWiV*$WNK_=*w-BVZk6S~KhM8E%bFVM^{Ak=^7yltsR9iR z0uMvm)lx!FvwwZ=djDCX^%hq-4iER$+>vU}ZXBynE}LBJRyxP{KcnI|NA8aqOT1PU z2C6duxqTroV)MhlHw2XKEV+8>oWuIf=8aD$wr6{DCs>%TU%TP-+oD^$W7gCh6>4T} zs(ihhiJ6gsadD7A05~{h`577iv#>BTu|5DtgRBAzzX7iSHydX{n+IbmGot~cfgsS6 zvV1IDEF8>k1$&oFZT}4pcUff?U<5UAY`^kGdgIyhCS)%IqnR1#*UEkWzF3C~ygpr; z)wO83S@S}MlFN!-iKdAaz1IU*hMV8$Rt{Z0IrrcOj+XeTlKZE6rMi8+esq&dZho45 z<$WI&m%y7lzDYb={M&fLj|YnmW(Z}sXqG(WK3jh}`@+P1_I*n-EDBZT`tQ4cP(+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-2fjw14BInOL1OHO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aUp) zUES`3x9=Y4W&J3j@OJK!_w8N)6Le$p literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/Intermediate CRL 2 PL.01.09.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/Intermediate CRL 2 PL.01.09.crl new file mode 100644 index 0000000000000000000000000000000000000000..61e712f0d8a9ab65035cdd6d220375f7ddbb5624 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-2fjw14BInOL1OHO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aNhj zaF6|G{~;C4#mtS346BzfkGp-MO#X1^$IVf-rEQBm(uFSYBt_aas~uGCJ|Wk4?(l0R z-ogn_XC^qe=$h30TKuajbK?(#S%O=c_3XB+J7v-+!o<${p;Z3IkITakb2gm* w$$ICF1mlF9Et8Tj7H(VKWc#gZQQ)CYCyk}oJX8Kl?n#>Pl5v(%(M$FH0HBIz`~Uy| literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/Intermediate CRL 3 PL.01.09.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/Intermediate CRL 3 PL.01.09.crl new file mode 100644 index 0000000000000000000000000000000000000000..09707fd7bb11bbe57fd5b2c8a6f3609d1bb0e26c GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~m z-2fjw14BInOL1OHO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aO^O z^yHhYcFaI?F>_-h!`cNK*S*PD5_W38@Www%tdA<%Zf{^@Pb&ys`NKqThFovNmmBX+ z-FR#``$EsbPYc(qT2@%;!Hr@|NAbRH!sxl-?`+_SHb6sJe>kkY740dH4pYybcN literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/Intermediate CRL 4 PL.01.09.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/Intermediate CRL 4 PL.01.09.crl new file mode 100644 index 0000000000000000000000000000000000000000..997a057f26d6ea18d179c6bcb0b494e4711b5136 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}r z-2fjw14BInOL1OHO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aTFJ zc_Y2?YV7)RksYrT%*dhIAle)Axo3HFWnb>?S;|=qN=5s%dJ-^@c zn*AzMXJ0yx{ErJ~4Dy;bKUom`+R*WmgAUv6N5|NNRUiNHN&F(lzK=^ZOYnzj_QKhV wPM9AFE;w*tOBP!~uv<*_}azn^v*g#Xh}u z(cmIivc=sTyGyfo%>DUh{_1GUqM2*6Gac1u2xsU=*ecJsl|4uDQ0c5^#wE|K+8-a{ zxXi@N$iTQb%^<}<2pDv-!i!c0XG|G zLYoI;Dl?-2qk$kuFCPmR3&*>+tJ^)f4=(`6gsd_PFv=P@R?m9<^U(8PMm#gn z|7CC69Un7ma4byCK0iN_<>ydj(WC`>A2=TBzUcC@-fZo0 z=lRj4-*yQGCv~S+Yi(cQoWF8vxR#*RL6)47bt=-aGDj6E8HRrD9R6EVY literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/Intermediate Certificate 2 PL.01.09.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/Intermediate Certificate 2 PL.01.09.crt new file mode 100644 index 0000000000000000000000000000000000000000..a62d9a02625b90f7b371e2b2c302ec76fd23034c GIT binary patch literal 669 zcmXqLVw!2t#Kg3KnTe5!iHTvc0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE;5y1AO!h4D}2w4dldmEiDWT4Gay9fTTf`IIjsZmp1krA?$CQkL+VcRtDzA zUIv54PNv32hWFmTSz^-s+T6t_n|+zI%iQtStGaJrPk#-*TQ;NK&(!Ac*5$W;S^tRM z`PlRHw<}7~W}$q~b~=b2c^ca*^6lFz8SnXRcLbeQ?EW=VKKqfv$33dI*NJ@Cm)(@I zK4q3mm(u)6iDmBgb!R?5l(V$_IGt+&yHU&Y$k$G*W-goZ*ECmXJrgq{1LNW}gA@ZH zV9?15Gcx{X;V@tWQcR32-~g882Z^x&BaaOnF|rCQ{06)R+-#f)Z61uN%!~$%27(~H zd@Nin9E&%&$NsbbkP40oS!EVrlr?a?d%L>bll$-j`Nr0}Y?)VDNm?qu#pLhJGta%cc>jLO?Jp`%4t)3T zJSY|SCVraBY!%V+nT`QhM46|n3GZC=XQyrN>+pnQ_W~PRPDmZy{y+7#+t)YpcN4r6 ZRSHjuoHAPOc=Y?inJpD9w_nt&0RY^S+;IQ^ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/Intermediate Certificate 3 PL.01.09.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test62/Intermediate Certificate 3 PL.01.09.crt new file mode 100644 index 0000000000000000000000000000000000000000..aa91f3427c0b98654fd98c0ea78725185bb335c8 GIT binary patch literal 669 zcmXqLVw!2t#Kg3KnTe5!iHTu}0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE?pH1AO!h4D}2w4dldmEiDWT4Gay9fTTf`IIjsZmp1krBkXUSkL+VcRtDzA zUIv54PNv32h69J5@txbArT6Hu!2WB`&xockYM7v!v$SWM{`m^0MQ=95n@qTv@qX*X z>$@DfO!rADYTZ&Xd!JWb62CZpqtvs|MG_ZtDxYN~sy)el+$FximV=E`{BT;6v+~6= z`3zAPMK@fzzUG+*N0@n#EK}d#l6TW%Hi;*^yT&B)9?Lw!+KZugCjX%QfD@4gq zw7B8IA2l7V-1|8n7=AClmUu4PKC>+Oc(umtC(8q83Le})*KEl$n_%b30twN4veD{1 W#+x#y>96?Rvz~Fr#$O`YFxtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;KgCeMfDgiB4@oU9$;?YP6g3bA zi7*TEI6E5a2KeY180r~V8pw(BT3Q$w8Wab6Q-E^X{LLD=6oAKAx@tPISJ zy$lA8olK3542zroI(Thfof>}5&ExLrE0J>fuYTRrSi)a3`Mxl-`MxH zGf8=)^aK8LDoH0!@mtI`dHQ1N_X$}N>+j!IKXHzKm+uSBHq@7?QCorx@xQIB0Vq%tuxGB7SqHb^w! z2L_$2FeBrC7FGjhAO#LxS$>cJ3oz!`z_B8$z`}39YrxIMnb79Jn99s(z-S-{(#Xfc z#lo@u${Xp8XUm(w(IBhL0*tQ)j*kpI`6jC!Gmygo80*YH&r427dHum{YL1V+Ubgv# zC7VLhyeDVPAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/End Certificate PL.01.10.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/End Certificate PL.01.10.crt new file mode 100644 index 0000000000000000000000000000000000000000..16c1c687de91bce595b70a4cafc9991695d4d4f6 GIT binary patch literal 666 zcmXqLVwz^q#Q1*!GZP~d6BEN~170>xtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;KgCeMfDgiB4@oU9$;?YP6g3bA zi7*TEI6Io?2KeY180r}s7|4n9T3Q$w8Wab6Q-E^X{LMcCgsAKAx@tPISJ zy$lA8olK3540rdGtd`e#I9u+e#4fXy+yYDab($CYMEw6^QN3CEh}`sLY$1>H<}RA= zFXk^O{jFY!p>>_q*{iGa&9+?#n7L-L;?m}4jrJ_Q8sXpfUb&$EcZv6=@ZVvVXTSQf zNATaW9S@Y1(?c>HemOi&S>=>Ccka)7Ps(*?zF}|>`_XyNCec?QlZly;fpKxNL81Xa zFz95385#exuo^G}DRAh@@`D6efHC(B94oR4Ec^z%2Hb3%32h#XsmzQ9j0S=rjeIOz zEF4`b>?ikx=?Q?NK~|Xs7+(z>TOK4^OyIur3^@#dvCa(i`~o*;wg6qm@cj2rdj1tM z-P(6;OYYj8Mcb_M@4Yy=X5rWUsgAebM=y|-NNnu%*PXV@R+7b8&fl2tLzU`-Q+t<{ z=|3@8R#)bGC%U=whPvB<#l~gcZ?22S%=O^>nuuuA}f1WI! UmOq(i;laC)&lL8v%q#r_0H%-8Y5)KL literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/Intermediate CRL 1 PL.01.10.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/Intermediate CRL 1 PL.01.10.crl new file mode 100644 index 0000000000000000000000000000000000000000..40c4afc45008bd687747357d891daf81f110aaba GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-2fjw14BJS194tUO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aPtY zzn;`CIw*_gV&=w1hCVmTxfQ23-Dfhkl|SKZEp~VASK~g_(h8pg@*d289W)+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-2fjw14BJS194tUO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aNEi zOH7}5Z~2JkV&=w1hO#MFj-J`TX8LW7J=^XzPxw|k&zycSrr`Xx@^3D3(lR#H?;MVF z?prRu;Mjucga`py>ai`j0Fw@vqJTHpNJ>Pqc_T#bA?mhR7Wi8|KtW%BCRd(Tdu xF*$Ypug4STHYPbIQ!VaLEfwAe}+CQ%XxFFvgjbeTj{fRY+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~m z-2fjw14BJS194tUO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aT>0 zF7Mc}n9Bpr#mtS348Gyt3LM#%Npn;?=&ZO@xyISM`oKLN)*AQLLz>t7pRH`4v03fw zJk9uHCu;p}bG1G)>0#T`YL&&9CiB@{$nHxaW9SOi|0ynWE@vcdf4t@!-^-%7H(xmn wLLGWiFDw%OztY32yh7>cmME?nY;p4?xi2i9v}0xCxmOdn&Yqtq@P6hV0BlQU#sB~S literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/Intermediate CRL 4 PL.01.10.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/Intermediate CRL 4 PL.01.10.crl new file mode 100644 index 0000000000000000000000000000000000000000..71e6229074370b337663c8073c3cb891dbf58e1f GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}r z-2fjw14BJS194tUO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aTE* zNVb^3edigPiRP2RQN&)2-D+oNUSibW{)5wczrqIYpoTv7L#Xx`J~P*TqxTmm*3xHBWf?s+(sq0QG8Ui~s-t literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/Intermediate Certificate 1 PL.01.10.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/Intermediate Certificate 1 PL.01.10.crt new file mode 100644 index 0000000000000000000000000000000000000000..6b3f6eb4b2b21df2b8a191338f438be8b6d00f7d GIT binary patch literal 669 zcmXqLVw!2t#Kg3KnTe5!iHTvk0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzIna?_wxmzz5;6holylWagzCiW&%m zM3{wnLW)X@OB5XQk~8v)4CKUlEiDWT4Gay9fTTf`IIjsZmpuDZ@Y?U}Xs8?Dqi0~K z2ehzpKC+J)Ss9ocdl?KGJDD0A8P+#F+w~)8*10cS)eSO@AI|s1Y*>BJHadpSz;tVJ zv`P1SlY-(?_u4-CG5H29+YlgWZFNoc<@Wqi!T1? z<|#GH0+bi?y?el4&|Lt!7(AL%mR$E29DLUUjIDwJft5v7=RJa4D|n{ zeb<&PoxM5r$0v9Hn-_G0%GW*NWolNHzkc?4iY@De)%QK7ao%rhW#V_UiF}Z{qUYqR z+?*RuXFS}KPnU#Sd2?J?w|>zLm;Jhr4{u#`q4dg*$N$^x|F7bkY-_Zt{Li&}SB{_4 j6bOF4Yr%T4J(aFW)!G`G&%|G=Xl5U~m0#6-;K^|S|3KER literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/Intermediate Certificate 2 PL.01.10.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test63/Intermediate Certificate 2 PL.01.10.crt new file mode 100644 index 0000000000000000000000000000000000000000..f2e88f9fe07bef2679af1c3fbc7fd837e08ae3a1 GIT binary patch literal 669 zcmXqLVw!2t#Kg3KnTe5!iHTu_0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE;5y1AO!h4D}2R4CKUlEiDWT4Gay9fTTf`IIjsZmp1krA?$CQkL+VcRtDzA zUIv54PNv32hU2q+bmpFRm)P6GbI9YS@@JdX9&crolHKZ;IVl^8gdci6v*JPLv=_D( zwYn+hvyL|F&AD|n##u-7*xko`pS3MsnxE7>v8k$~@iY57lVmQ&<7%JYna7!~xw1gk zOjAs7_R54GvNQP07D|Q|R4Ynfer4akk$JUI+3fA%@w_L$ZJA%p#LURRxH!!q#Xtxc zbh5&XjQ?3U4A_7a6C(>afMxkXVl2SOV*^KwtO5(a0j~i!8)rhB2V*KTqXDCVAV@DC z3l|HAp?Qhv6Ynh_!7(AL%mR$E29A{UuP3#O4$2}212E#5f&Ta3Q>;A2dC!il>lSQb zzG)wOUFU5t-Pp`=wn6F25ypQkKIik_nLP?jd9-HEil~DdXQy`r`G)>*+F0~>yI8kt z;Jc^Zs}pC2S6MbsihgV6TFg5sa^-fTy~+h#ypt0@XD`sXvwH1aD^`sb{;Zk3qT{aC>#o%Qcoue+gZucljYl`HcHPGMxV!Sl)rK45Qb#}4 z?AYty)M@jlZNo~B;FPi>YZBxV__qHpc=1g9&$E`Av&o%2x1L2ZF*7nSE>1H@F%SX< zovbh;<9`+o12!PV#K;H^U|D{U7z;4+*uW7ZtH8oTLa;FyqAW&uW71Ban`iRlyXEgzAC0T}VjK>x4Zt}S1ieDSS_Xu53b ze$(G)*Y%xvnp2;msqyNi`|NY9HXIMxtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;KgCeMfDgiB4@oU9$;?YP6g3bA zi7*TEI6E5a2KeY180r}s7|4n9T3Q$w8Wab6Q-E^X{LLD=6oAKAx@tPISJ zy$lA8olK354C@%ubu?coFPZg@^-0R>6B>0a`ZKn3HSVfN+~$6)VUj`4`$Jrk9e*49 zUc0V1ps5vq{m%Q^qkDd5F!EUZWNO&->cMlChGi>n?`w099AWa1-VfA3P=$yKk9 z?(e(TS;fL;%)+#~X{S#6-rT2V8|(yCo@-ZIhj%(Ic)#LVn)A!sOw5c7jEj>E5)Jr) zK_@HB$oQXy)qojDfkRi8A0)s6j5#)NtjH>`@Eh&!sU`_vp_NM_><`F`p};dL(t zr|FaK@t9k^3^=v>iN5=`>b@-zJh$5HEp)2hE(`MUO8mOQO7?uuY0<`Kdyetn_;Px4 z_r}#MUs(U_vq}wGS8`}=Awwivci{4sLi;V>9rj*Q_4+BRZ2or*_TK7yvodD)6w3;` UZhs=Vbt|LFqJKI*Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test64/End Certificate RL.02.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test64/End Certificate RL.02.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..771423ecaf466ec4ad84a6f189a0dfbfe8a3f6ec GIT binary patch literal 651 zcmXqLVrn;NV*IdxnTe5!iHTvY0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE;5ygM9Q1jPwi)4dldmEiHhwp`j6wG>8)CH9_VYB#>jj3l{su4MZXK^Mw|t z79qKyaXzx28Ce;a8+#cH8atU98yPlD6r7{5dSmB0>ywh5{zqS$+}NgTay!uFZAC*S z?}YgCiH4O)uXnr;oFD&!{UiVHww1@b{;uU+D|Pzy|6LOjpKyK5yQglJuwO8$w69v> z_!YCY=|UA>(tb}{^JM;y_4zMCr$6mocXG+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-5?)510y{HLvdb9O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aPrf zT;8>aY4tZW7c)0DG924*{LIQ1*D^U*e0i7eZtK^#n7g3OPc!t2Z`lG{6){Wk75hwn z=I*?<#O%Oq&j`spy^^PX_kKlLb>Ug_e`hbBQ$4&_XTHfZO?gZHgLXD@PZqFt xaNc`uaL9ixpMuqcJGU)nt=TM-C@Q7$xtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;-^EbCfDgiB4@oU9$;?YP6g3bA zi7*TEgcOw)mnb;qC1>Op8OVwAT3Q$w8Wab6Q-E_wE+;I-e`(NH(YN6)}W z4`^fKd}JRpvNA9?_A(eWb}}_KGTdRVOD=r+|7yvcrN^DRqyHW-3;h=J?AOKJ&yo+U z;CiuajpPf4MVlu1tKEqIemSqK|F9;r?UywLoSzxcJ3oz!`z_B8$z`}39YrxIMnb79J zn99s(z-S-{(#Xfc#ln$#;qtCUOsl_vqd``g1sGoq9II!&{(0zmNI!BI0ArmQ=y{{H z=EZ%P;*K_V3*aP7^Lz+}&aLK~=8c_MUrndn!IoPhEYwatiwewWZ7I z{2p<%ZgrS^x^VJ}oeAe}>O1ATX)H()RPf~Kn~;9Ddj4_OE6b#v_|9JYvVkYGYW~jS iTenTC;`{aR^~Z1Vr%oFB?&Y>N{@x$mzB*<@Q4#?BX5X>^ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test64/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test64/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test65/End Certificate RL.03.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test65/End Certificate RL.03.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..29d51a7f9224c4c94e135759613262686ecb91fb GIT binary patch literal 651 zcmXqLVrn;NV*IdxnTe5!iHTu@0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE;5ygM9Q1jP(o*4dldmEiHhwp`j6wG>8)CH9_VYB#>jj3l{su4MZXK^Mw|t z79qKyaXzx28Ce;a8+#cH8atU98yU_^Y=89m%g^O&@8l%fe#+{58uO&0H~aSA$$H#3 z+$Mc(Ke3N9jB8=-?~^^evH#mAR3u+{deY<8v-ju9i*7d8XO!0cy?^~xryifEYs^z2 zMs2foKP=_0>y}o(bL^WXvGNw5qxe*>ss*zBUQUYxEmHztx_r#~?{Ijgden=g&KH(7 z?M%#!42+9|3IjbiEA;Bc2!W&uV}1IOWF^^%n*9(_diGBBE%fqo6hD{KAYJ8A!^R++V$ z{2#boyZ*(z<^CjeV}a4Llao$6L!epC3n^@!E_YYu-d*v8E{yIpAh%!<#PQ|Hztom_jLi>uUr*QJRJ X&n~j8nB|kU_5G2SsNX3ITJHh?{W{pk literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test65/Intermediate CRL RL.03.01.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test65/Intermediate CRL RL.03.01.crl new file mode 100644 index 0000000000000000000000000000000000000000..bd2d906ff9cd2b70076ce57852dff0c7d221a211 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-5?)517ke{Lvdb9O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aP-B z7APNGaXJgl#mtS343l{pl%rmsU+p);%TdPWo$9X{x5}<_v>r8I9=dZ;Z))Pnhm$>u z``_NaI_pV>c+%GJlO-`R|KB}xc4>L~?av*i*{e@~ejPKl`R9sHuiHO7dGz=B-XlkK y7OXD{kgji1y=;EQS$?8h@lKmx{e16|u3bES;I+d?{uS1HQ&W8Sgxtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;-^EbCfDgiB4@oU9$;?YP6g3bA zi7*TEgcOw)mnb;qC1>Op8OVwAT3Q$w8Wab6Q-E_wE+;I-e`(NH(YN6)}m z4`^fKd}JRpvNA9?_A(eWb}}_KGHjf<=g`q|tygw^H%}ee#>VzQ%b8X2g|>B9!(~%P zj{t*{mxBARlm;6JSo63W`6#ZR%WGER8oEP0meoXGdP;uu#@z*qV)wTTJzxL*#BY(S z8~zu~J#=mI$z|QkFL&Si9AW@P-&!fL<_q`;vo%MTJ@0md8~I96m8SojTi4Y=7j6WTl& zQ<)hJ7!3qL8u?hbSU3(BtCy@i@#rHs8f2AOfbrG9v3l0)pNF1@^dpA>FxHuYo|m#- zuyR6IgmQO{>6VWOOm-dreqW7-S%kZL6+dTsT*vI9+um01eI3kN^Mx literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test65/Intermediate Certificate 2 RL.03.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test65/Intermediate Certificate 2 RL.03.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..57c2e5914b9e25790100b511f444afcfec3a2154 GIT binary patch literal 666 zcmXqLVwz^q#Q1*!GZP~d6BEOF170>xtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;-^EbCfDgiB4@oU9$;?YP6g3bA zi7*TEgcOw)mnb;qC1>Op8OVwAT3Q$w8Wab6Q-E_wE+;I-e`(MUJQN6)}m z4`^fKd}JRpvNA9?_A(eWb}}_KGHl<|yE;U2W9-W}PiodNzf0az&Gy@F&W{*fxz8dm z1b@v82<8fNPJX!CBrY^g*>pA6mP>mLT31xY&kL_|={jY(aNFM>GV5E{y1wF+FrCc5 z`I7$U<(wX;GY%DdhNL>^Uvyd4{?%d8%XjY2FCSE%)VNGq-}1PAp15}GO?~yJmf38} znV1Jn^~syY&-f^qgeiR^L`D+ZZFvg-jaRUo7VksEclrnr|CTV^>fqNTiw6>`+D_( zuu}umq6>4iUh@lR%}X#;^S>##f=~YK;UA%=j~$Y}6v~ui_n=&7?Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test66/End Certificate RL.03.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test66/End Certificate RL.03.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..ccdb0e0862749e83426735b0ff8460e43beffe5a GIT binary patch literal 651 zcmXqLVrn;NV*IdxnTe5!iHTv80WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE;5ygM9Q1jP(qR4CKUlEiDWT4Gay9fTTf`IIjsZ*C2r$`(3cuFK!?Tv7axr zIJF4L1&#BO{mjV9z}(o&V9?mf)Y!;yHhRJ^)99tO5(a0j~i!8)rhB2V*KTqXDCVAkdSt zd@Nin9KFX*yF7?F^#L62vdS#L2x{P1?G*4b&EWSgWG@4wnHlKUmI+Ssb#LsJPcHO+ z+QN5Ut%OzaLXuUqV$2ftN3S0l_-iXJ;99z?Z)tDy)*lBKRKJ>;VeC7F5YhN1?-AQ5I^9%n~G z-5?)510y{HLvdb9O9Mj#Lqj7VX%HpOYhr=KHBdHCWMX32grv#GR@%kE;Mg3H#RabN?xe2+OT43OncXBvkPlh z`xu)R-&nWjr&jNk4a!rl?%MtEl3##+s}QSo;QOaDey`lT?e?nEM_1d&r(TPjtUCJ~ zugrbnhu1xtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;-^EbCfDgiB4@oU9$;?YP6g3bA zi7*TEgcOw)mnb;qC1>Op8OVwAT3Q$w8Wab6Q-E_wE+;I-e`(NH(YN6)}m z&%nr_aXzw-8Ce;a8+#cH8atU98yWVsyem$+!SbTGLww84f32V5eGbG%eVziVFk^JFRj>!{MX literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test66/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test66/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test67/End Certificate RL.03.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test67/End Certificate RL.03.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..85d5508dbce7a968795683b3fa58a20019042ef7 GIT binary patch literal 651 zcmXqLVrn;NV*IdxnTe5!iHTv00WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE;5ygM9Q1jDg5NPMp`$!obkL(9j4-8bpcnnjmux63DUN1&jUS2BHxA`9h0R zi;!Hnvx=!#P34>5iJ2z)d%GXpzZWC>>;VeC7F5YhN1?-AQ5I^9%n~G z-5?)510y{HLvdb9O9Mj#Lqj7VX%HpOYhr=KHBdHCWMX32f~3j-sLB9hm#ioYGZ!P{ z0-z$W-LfJq%pf0t?2%Pw0V-3@#~zq$Vld=Rb;^8X6W71mJ^$0;IIVR|!XC;l#r^6z SCsyk|QLm0nkP2>k!v_FwtZGgG literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test67/Intermediate CRL 2 RL.03.03.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test67/Intermediate CRL 2 RL.03.03.crl new file mode 100644 index 0000000000000000000000000000000000000000..15593fa840e0e7c1508b7f45f56bfc94b8e269f6 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-5?)517jc(=e4vnFf=eUGy;+aQR2KN7D(I$$_9#HV`W8Hm_d#M86m680<^1vqfGby zr5h!lU(j64+}OwvJ7wlcZRWRrE&lqEZW&zxNeqhnDQuCTyCwlfT`FlS* v>Z)73OoL9$|5F>AZyx_PZxtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;-^EbCfDgiB4@oU9$;?YP6g3bA zi7*TEgcOw)mnb;qC1>Op8OVwAT3Q$w8Wab6Q-E_wE+;I-e`(NH(YN6)|* zhzuI%Bm0<R52 zTXt^ycIiWnME$2YKW?90u`ep8%lGPDU%E-n&E?vxsMPlUOG!`TRu@J6*;wKnWD|Ei z=X8}U+t0Pab(6k-b~pSgq`Q)*;p&v6fIG`(Ong2&_Ti!Jzjc1BcE8}W?#^WYM2@?M znV17Mha7{oM|h;CeaI7GA9v9)Ff@5NJ@ zndSGM1zdU|+I{o#i*?f51I4dvy|-XA`XH5@xMIVN_ZIbMexKfwyR6%+M@Mhw!AUV!Z literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test67/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test67/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test68/End Certificate RL.05.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test68/End Certificate RL.05.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..bddd72da6190ee1400179f337cbfadeb3db187e5 GIT binary patch literal 651 zcmXqLVrn;NV*IdxnTe5!iHTvm0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE?pHgM9Q1O!W*54dldmEiHhwp`j6wG>8)CH9_VYB#>jj3l{su4MZXK^Mw|t z78xR3&^RC2&y1`L%#FPa292Fejg1U@O*6&*Wz4$mZrO15@X{l1SX0h&f3N3i`)3(- zX==|}BcmN{m$w_PzP0C=ug?Yv5!Gw0^QSESy@(-Jw#1J;Bgo?V@h+7klX7|HmAf2! z>R#~g?%me*?lT+JLeFYn_S(7sLASzfCQ}BkjIY&KyFm8&zfx!+STB>e3jqNoF%~kf;Q1X literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test68/Intermediate CRL 1 RL.05.01.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test68/Intermediate CRL 1 RL.05.01.crl new file mode 100644 index 0000000000000000000000000000000000000000..fdbf8ea0caeffe5cf4c5760f8554725078a7520c GIT binary patch literal 393 zcmXqLVr(^Ne9y$lXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-5?)515-T%Lvdb9O9Mj#Lqj7VX%HpOYhr=KHLx%+V`5_1hNQ{>sLDVQY?rJk3o{qc z#lmcy32h#XsZ5MKKo9(9VP;}vSfC73Bm&}t6fuX&DzgAx*}(CylJlG#>#;p(er0ZK zWN7!x5P!+wG)-^I`l_kPlS_qb+~0Wo+w{xPXL{|8c-@+#-dC4wTP^i&MlX|QoYKEt zk^B|$!i?t~vbHMkG5<30w5r1Eax-zCqjL7*Yb*H9zqWCG^YGmBM-EH&aJn}Ct?g)x l<6N`+c+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-5?)515-T%Lvdb9O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aO5| z-p(iyel-Zq#mtS33^kAEswrLJ2wAs=ZN7s;{1JbzupO-2PxsDVCo{t(so-sZ{_z6u}>yI}2 v&-%k$%)K%F?`QtdI5|cRt^T}5$!p>Vx7o=}iuCd1G74BCcTI86+{H`)ZJS@q literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test68/Intermediate Certificate 1 RL.05.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test68/Intermediate Certificate 1 RL.05.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..4bc8127b322d44fe0ad8e1ee96c1f1c378b98dad GIT binary patch literal 666 zcmXqLVwz^q#Q1*!GZP~d6BEN$170>xtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;-^EbCfDgiB4@oU9$;?YP6g3bA zi7*TEgcOw)mnb;qC1>Op8OVwAT3Q$w8Wab6Q-E_wE+;I-e`(NH(YN6)}i z4`^fKd}JRpvNA9?_A(eWb}}_KGCaS1-1nWs7k1&>b4i|km+OZ)U9Pn>{u9{9bdkTExi@iQ#8iQ$A~WX7n1?b=TgtvwdeM;w zZAXonm|h*;?ERZR>8|HD=}kVjS~u+CGIpx}+HUoYOJkc)LzT8mm{#*awQth`U4s7P zGchwVFfL9uNHpLF2A!-hBjbM-Rs&`r1rA+VevkkQFy`36u_CL$!f(K9z|F>)(B{FI z%FJlMXdnpE$j8FP!tt+?^PC*(u|42ukX2>@##aN!>RGRU9(o?qj~oWTSZ4-$e(TTg zJv(>A32xu8!lk?`eMXIw;_jK}mpB+JXR2Cg%;60U`Z8nMT8A9l%Zl-Bzp|$>y#4CL zuy113`58tVcRiLZiV_k{jeTLuKXcBpLqB{9Wj_8}5gfR<*8Y-(eX7%z{}Z2n=f4>v g;x^feV~b2%bw&_pQ|scG_`ee_`v`E`Y?$l;06zxNO#lD@ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test68/Intermediate Certificate 2 RL.05.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test68/Intermediate Certificate 2 RL.05.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..1ca8d5c3229d9053bcbc84ed1e45a1d0ee0e4f9f GIT binary patch literal 666 zcmXqLVwz^q#Q1*!GZP~d6BENW170>xtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;KgCeMfDgiB4@oU9$;?YP6g3bA zi7*TEI6E5Z2Kne2nCclA8pw(BT3P^ULqj7VX%HpOYl6(Bjr~Rl`y1yY`K+rIZ+~`&HGSO}3nOZcb-Zg`f7nUR5Uak4?80Y5P4 zWQ7?S|Ff_fFas%Y=*seg1XzGE#|DlSSp^n;16~7eHqL}L55`nxMgv9zL6Am17A_W! z$&0r$N`zkx0!M?aG7B)i8aVz{a-Nf8J+=oq41lrD4D@{16U*-}luRep3+ic|d7-^A z`S!;9&n!c~=VZlQ@D7wXE2W>zv6Un63iq7Hkvh{f-n&)BE?m5XX{*pRuh4Ac>p{+| zr!NqWIV-6D|EtZPBi5d8wrgF=QLhXvoFU!aENSo{X*NsH=If3b9{;YYrp=4?H;HCi SzWiQK^~ANQ;@e(3mjVFTcg>0b literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test68/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test68/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test69/End Certificate RL.05.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test69/End Certificate RL.05.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..00fc716dc15e4145547293021679cff67297f8b0 GIT binary patch literal 651 zcmXqLVrn;NV*IdxnTe5!iHTvS0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE;5ygM9Q1O!W+m4CKUlEiDWT4Gay9fTTf`IIjsZ*C2r$`(3cuFK!?Tv7axr zIJF4L1&#BO{mjV9z}(o&V9?mf)Y!%P)I7ASM;Wz5g5STcLn z27|9<%{Mzvp8sSOzjV6j{d>+YY^V0#>%2T&%|kU&N6c7M^mR%|>c&m0OiDNPPhXa1 z$jQXa$iTQb$RGe5oU;6kjQ?3!n3-4~fTKZHfra0I*MOUiGoj6cF_oFofYCq@=t)^V z7A_W!O}BU4nL5d7FF4#~m05rh)W8w3=f%PP8K=dOy$pDq^_dvYzO2RO~;QguFcC)Ri8 z{twOdItFh~)=b}I*xU2l=0@&Y`RaY>;VeC7F5YhN1?-AQ5I^9%n~G z-5?)515-T%BXM3!O9Mj#Lqj7VX%HpOYhr=KHLx%+V`5_1iKNN^sLDVQY?rJk3o{qc z#lmcy32h#XsZ5MKKo9(9VP;}vSfC73Bm&}t6fuX&DzgAx*}xI8=f%PP8K=e3{L0+e z$Pmo?;_Kq`X$P)~6nQp>m%d%CrKXbFp_q5&M;GrVo(W!7%Flc6)b;IXRTrGG?B2n> zhYJhLAN3{Nyn3>D*(Uw-p03u53^sC1+p@>+e8Y?WMcWwccPmS`=^mdImpyx*p4`h& lr~9JEHa(uP;Rfru;~_C^o4fbfRXkUIcx$x``^r4g%K+a2bKw90 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test69/Intermediate Certificate RL.05.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test69/Intermediate Certificate RL.05.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..6c19ee09e9306290605686f77cf5d5500dcaea33 GIT binary patch literal 666 zcmXqLVwz^q#Q1*!GZP~d6BEM@170>xtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;-^EbCfDgiB4@oU9$;?YP6g3bA zi7*TEgcOw)mnb;qC1>Op8OVwAT3Q$w8Wab6Q-E_wE+;I-e`(NH(YN6)}i z&%nr_aXzw-8Ce;a8+#cH8atU98yOZojzq@5u+C3v*bM1Ze^r!!S zx~s9;v_4b;y^{1NucdUx8`FH>HJsXC*Kf3R^@0`fHAo;QMY~6V8CD)U`eBQEc z%XcPbMh3>k$p(oA{J@}-6=r1o&%$cJ45YxJE6WcOU;)M)8#q>E6z{|7hx8+d0Wj8?fu0YI z3_0eqacQ2u*Yqd5Z6Cj>X^>Ps^8I7u$DO(l0&jnlS((3^OAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test7/End Certificate CP.02.04.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test7/End Certificate CP.02.04.crt new file mode 100644 index 0000000000000000000000000000000000000000..0f97e6f5a1c9ded1df1c8b1f7558876b203b38e2 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iILBMmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uC<0eS{TdIly2a^k$E1_p)(hK5E!(jZEl*Te#eYmh*W{VrJS7dH@v*v}VQ zoLYqBg2wsCer9B4U~cSXFlg*#YHVcK5dI`dVA~&^gE>4r#?O}tsa)F>lzVD-hi16W z*_KJ%2Y0`Swl@2+|K{51PMz#~gCi!)KX`nqlj@y2nRbb{*Y&X7bPajp^89bW)8?<+ zUn}phd!Au2>+JHkuMb(*-u~s-Qr~29y(jhKCFiJ%r@lyJ|DLzkH9z>wTPwwC%u7Y7*xfP+((pONuD3kx$7>jQ8!$SSb#8}J%%vvDT0c`&9jGa4`&2m(DR z%g4gS!m(rN`=^;Az6s!PmsMr~Mo+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zUFQHj10y{H6LDTkO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aN`D zmrtlP@Qg%rF>_-hL)e8yO6@A!O8X9G%(6W9*4HV2PhFj2YZ3d`hciyNzCCbTKfkP5 z>-jF(y8AEP4^CmUYpk7YShDZxtb-4C&#=CsEy(Ne;O;W{t3@>{8$DWmQ-T#fl%|#+ w@;N%AK1C=i%H74JVsEsT_&yuQ?QFs~XP^6Y<@{o2=BM$W84XfjWO*0^05Je&k^lez literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test7/Intermediate Certificate CP.02.04.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test7/Intermediate Certificate CP.02.04.crt new file mode 100644 index 0000000000000000000000000000000000000000..5c1ddd3e383a73b1f209a704147804f4e4effab8 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6C#E{2;3narW%OkkN9yLWQO_0K!LP72HAiP~3u{u$$o%X#~33Irr1_uQEJ zk%^g+fpKxNL81XaFz95385#exuo^G}DRAh@@`D6efDy+Ajulx27JdU>18z3XgfAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test70/End Certificate RL.06.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test70/End Certificate RL.06.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..c576960be17ad3e3d5eb65036c1df9ff116a110e GIT binary patch literal 651 zcmXqLVrn;NV*IdxnTe5!iHTv40WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE?pHgM9Q1%=8Ql4dldmEiHhwp`j6wG>8)CH9_VYB#>jj3l{su4MZXK^Mw|t z78xR3&^RC2&y1`L%#FPa292Fejg1U9LxhX@H{Fb0*>odicF2#H1@qoSw9MGBcb?qR z+kbv<+`4&r#fuxOW!WnBXC5(}%SspbN^jeobpfad?GBMJMD0M@Jr?exAe6Imq++JuZUheXTSD}nJ?EY zmtdO8#LURRxH!ll034jM{EUqMSy-5vSRa6+K~{l<-+%X4AdV6=qF=Q_TqnR1#*VvO{V)xzmC`_KU{v3&vmNbdyUM1AMH_>6ZNLq$~-#5Wo&Jcv@J>F X$I<#JihF*Uhi-|G(^lvBxb!ywPkPXQ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test70/Intermediate CRL 1 RL.06.01.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test70/Intermediate CRL 1 RL.06.01.crl new file mode 100644 index 0000000000000000000000000000000000000000..77dafb90941eb47ddd8448006481fa3c610d48b6 GIT binary patch literal 393 zcmXqLVr(^Ne9y$lXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-5?)512a7XLvdb9O9Mj#Lqj7VX%HpOYhr=KHBdHCWMX32jikx|sLB9hm#ioYGZ!P{ z0t*8(u-&pEEX*Ju2(xh}w0SV5GBNT1x&J|e3}DM;m05r~8#tcqh%bHBt`vdhSLVh> zhAH!o?h@l&)g9Wms584Jwa)F(;{qPxQumYx#`oOc%vx;3C1$YS=Ix~=x4SAT7BGn% z?NHNCKXhtt`j1kv%MX*LtWZB$v#(ES#-Y`}t~@uYU^bh~lk&yLwbwyA;?kNOE?eD` kJG`@fyN*3y;=8@gDClzG(Vr}*vOlOx_Wf^@VYYt?00&udS^xk5 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test70/Intermediate CRL 2 RL.06.01.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test70/Intermediate CRL 2 RL.06.01.crl new file mode 100644 index 0000000000000000000000000000000000000000..4e22f3966592aa4e298bda725905872cd414eaac GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n}* z-5?)512a7XLvdb9O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aUQ} zJ%9D~?u=t-E@p0QWKc>;n18`~xqRG_N8S(B_x2rWKRfpg!F!dwR5i zi5!=We_!S9VxcxAZ`06&Z|+XZ3)}cCxpsTWYTul-lPp9ZFr~h)?GRb1tvOd)#;j5L we&T#dW5!JF%n7TntDRy@e_qjd;NRmr3+<*wCRIi6-q_PJ&ofExtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;-^EbCfDgiB4@oU9$;?YP6g3bA zi7*TEgcOw)mnb;qC1>Op8OVwAT3Q$w8Wab6Q-E_wE+;I-e`(NH(YN6)}a z4`^fKd}JRpvNA9?_A(eWb}}_KGR%_6et1&kiSCi-yJXWWWRAsIrNmAM*YEngOhf14 z+FhSvLXxPN?pz>uVtb*JtVo9Thuc5xe}Z>zIEy=mI6IEmR6ZpM?lB4U&?m)Fj_^mElw$#+~yoNqEh znV1xtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;KgCeMfDgiB4@oU9$;?YP6g3bA zi7*TEI6E5Z2Kne2nCTf98pw(BT3P^ULqj7VX%HpOYl6(Bjr~Rl`y1yY`Ghp4IcC4si5z|Qa0SzcM Tz4XTNYXTp4vhaU6c5^oXk@(g| literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test70/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test70/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test71/End Certificate RL.06.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test71/End Certificate RL.06.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..0cc1718ee3c3e750611189704b4a587728e4ef10 GIT binary patch literal 651 zcmXqLVrn;NV*IdxnTe5!iHTvK0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE;5ygM9Q1%=8S54CKUlEiDWT4Gay9fTTf`IIjsZ*C2r$`(3cuFK!?Tv7axr zIJF4L1&#BO{mjV9z}(o&V9?mf)Y!=IJ=jKjKGVc0e@*P_Y&&{?di!wC-)^d0^=7tt zT0+E}syptckGo=am~z~WUgdT`{c-u%Pm9-iuUWZw@=w{%Ev%Kgk1jv_b6d7ORJ^)99tO5(a0j~i!8)rhB2V*KTqXDCVAkdSt zd@Nin96z$&&wQc(J`5c0vdS#L2x{O6jxy@E3Ek&|>}6myGXwqFYW8%~^*?u-xsQ7V zixh;_YZRC9I~i>`TR1mpZ>8e?Il5PhL<80_>x7m~x&QaHUgNs8e1hwIHk5u!Ir8^| za;x(qE#+?hl{@VBo$X)u^v0D(pO+-fI%J=|>gUg`=2ur_Pdop6(!M{RpZ{3kB;l{z YS$Rr%!&E-$s?FM$Dlcgp7sVt10BvyAi~s-t literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test71/Intermediate CRL RL.06.02.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test71/Intermediate CRL RL.06.02.crl new file mode 100644 index 0000000000000000000000000000000000000000..c34a95df1cc72084b6b37b1548ee24c6161fe972 GIT binary patch literal 393 zcmXqLVr(^Ne9y$lXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-5?)512a7XBXM3!O9Mj#Lqj7VX%HpOYhr=KHBdHCWMX32hos5?sLB9hm#ioYGZ!P{ z0t*8(u-&pEEX*Ju2(xh}w0SV5GBNT1x&J|e3}DM;m05r~8#scajQVXt_xYgtmASEz zfvLBDPTCf~4`<$HKGRTQN@xyWv@YpHKO^&T8;8_c{g(T!ukFvs6uPnCb6-&)k0W&9z+Fr_q|A#yRZ*A<1Evd)v@g=Z-P03d2^6aWAK literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test71/Intermediate Certificate RL.06.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test71/Intermediate Certificate RL.06.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..07076019cf9ba033e9e977f0970d1d2003624b31 GIT binary patch literal 666 zcmXqLVwz^q#Q1*!GZP~d6BEN;170>xtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;-^EbCfDgiB4@oU9$;?YP6g3bA zi7*TEgcOw)mnb;qC1>Op8OVwAT3Q$w8Wab6Q-E_wE+;I-e`(NH(YN6)}a z&%nr_aXzw-8Ce;a8+#cH8atU98ySwA^t|-#iJ{=;9S)ayvioN=ty z$Nu%qzRx(V*58zvKIP`ef5CY!LUZ1HYB5cW?&{~)ecO*NJgk!~cp=ccBiL3l!q2kmlUnNw$yrkl{hA%EHo?K?b$CnItjFu$ z3o|h@GB7SqHb^w!2L_$2FeBrC7FGjhAO#LxS$>cJ3oz!`z_B8$z`}39YrxIMnb79J zn99s(z-S-{(#Xfc#ljIBWz=sIy3Yq34YJBC!1!w5SUv0Y&qL2c`jNu`80*YH&(Bs? z$+Hg*p2jix;I(&G_)E@fO7OYg2!0lO`b>=FW``E3yNy-6J9R#`NS^w#!98PR2*Mju>-5E#4RvbBXdlr9()|UMT hHN-yOeP2G~<;1TU`zB_FTXvT8pV17y-tT2_6#$Wg*319^ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test71/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test71/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test72/End Certificate RL.07.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test72/End Certificate RL.07.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..6c61375d8775b9f5219d33cb04b29f044b897d02 GIT binary patch literal 651 zcmXqLVrn;NV*IdxnTe5!iHYHW0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE;5ygM9Q1%=HWm4dldmEiHhwp`j6wG>8)CH9_VYB#>jj3l{su4MZXK^Mw|t z79qKyaXzx28Ce;a8+#cH8atU98yQy5{uVd;%G;Yxt^vy(T8#_#3B9;n-Ip!*BaQ89 z!j(fymbXN?R+dk%<`vj6L*@E)jT6)Ox*o+{{&mDnx%EJSNkYQz6(@4Tzt0!vESanD zzx^#%%s=`<*?;?5~z=mStMt6IJbJe^^eD zdo>d?BLm~&AcFvKaLV#CGX7^_VP;}|0FDM(1r~k-UIT76&V)7(##ClT14aWupeJSd zSh!d?5(7V;TkX0d1|06P$}GSLYTzh7GVzhlhwKf=UIs=pGtjThk-i~ipHFrzG59?D z>P^G>b=r~q>CY!5)~^qGS$Zvc>fyWt3KJ)O2>W5vxb*P@?tM$mO_~3{`d)YL%WlOV z6JM>nrK|hldaPrB26L;C!}2Pj#j&euPu1NpC^fz!-?!Oz&I+~mX$RFbWYw8`q7NR| X)DAJ&UfBF+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-5?)519LqCLvdb93j;$SGy`ITC>Yn!2+UoeY@i4>R#t?C8RR&S5wglGK)V_^ijPcu zr1K$r1DcDO8ygv{)w1iO1LwVYv3h%gQ~x~6j_4xtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;-^EbCfDgiB4@oU9$;?YP6g3bA zi7*TEgcOw)mnb;qC1>Op8OVwAT3Q$w8Wab6Q-E_wE+;I-e`(NH(YN6)}q z4`^fKd}JRpvNA9?_A(eWb}}_KG8{Af=qbb53>>Lm%GFsk?Gx=X0&y_vp{6qS-wfcW1Kr$teBPcw;<;X;%s7 z43~)#HvK6x?zd*V;C|`UyL0n~husD)FB=tkPCqnSSSiR=v@G^ylc7F)&#qTxHA)ep zOw5c7jEj>E5)Jr)K_@HB$oQXy)qojDfkRi8A0)s6j5#)NtjH>`@Eh=a>Tb@TZ?-+agyWhTWj<@Le)^CtEE gO|TVQ;(o&Cga0iH559+td;ZpV0G0OA+yDRo literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test72/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test72/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test73/End Certificate RL.07.02.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test73/End Certificate RL.07.02.crt new file mode 100644 index 0000000000000000000000000000000000000000..9bae5325f1b1fc0af414851d02db9955a7a6705f GIT binary patch literal 651 zcmXqLVrn;NV*IdxnTe5!iHYHm0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE;5ygM9Q1%=HY64CKUlEiDWT4Gay9fTTf`IIjsZ*C2r$`(3cuFK!?Tv7axr zIJF4L1&#BO{mjV9z}(o&V9?mf)Y!=ID~VgWH{U~l|0R|uUYibvq=*{Mitbx3XbqdTni?`@O`zGhz6lwefscbs?W#?}0V+YEjxJjhz%*Q*_z&zl(Y_@RzgQcJhu z)`P#cOl?dzG-EsYyQem1?Ty02-tNKI1Y(M>TvusPIyiG*rgEeCg996#7rz&IYo;9U zdXR~kk%4h>kU;=AIA!@68UM4eFf*|}07rwY0t>$ZuK_n3XF{6?V=6PF0i%H+(37%! zEL2kE)1c$q0i6X Xk*}$&X|~ZN7O6)G%UM^+_DBE#*tyR~ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test73/Intermediate CRL RL.07.02.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test73/Intermediate CRL RL.07.02.crl new file mode 100644 index 0000000000000000000000000000000000000000..6b76dc0b8a32102600dafe687a35cccea4df8a6b GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-5?)519LqCBXM3+0|P@KGy`ITC>Yn!2+UoeY@i4>R#t?C8RR&S5wglGK)V_^+I}jo z+n{;yEt-p&8ygvPL$&T^?YEl!@|*fI=hpD^?Fl+p>Ym*BKI>71>+DMRX+PXcBBn(o z#9TAD;dUfMF?sIKz3=V5YrZiKji0~x_fE-OoicalFb1+`ZC;sm=;KLET@zlXL+kwf uO<6Bqxtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;-^EbCfDgiB4@oU9$;?YP6g3bA zi7*TEgcOw)mnb;qC1>Op8OVwAni?1w0->3Kfw4i9IIoEXh-+vBBn_g-vp)r|{mzbt zxt7pCbdFXjaKXMoV zW1Si3c{UbVHoNq$^$)jk&%D3pd|R(Ho9mm9UnwmXcb?44e_hwP>G#^X;+OS=IE{6# zB``j2Vt6T-w=TU&%vUw@iqrf8)1ym0u2i~L)s`>%bC~&-f_}ra+}8J;-v7^)NSq9r nz-hF>|HRa+d_(VG9TW8(mrqRX6Nz_Uy;n~6tMTLeKUn1eAUo0= literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test73/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test73/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test74/End Certificate RL.07.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test74/End Certificate RL.07.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..93e05bd1ee72d00e74a6466fff42f06ff96c2b7a GIT binary patch literal 651 zcmXqLVrn;NV*IdxnTe5!iHYHe0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE;5ygM9Q1%=HY64dldmEiDWT4Gay9fTTf`IIjsZ*C2r$`(3cuFK!?Tv7axr zIJF4L1&#BO{mjV9z}(o&V9?mf)Y!;yMiPv3;&9rPV8l}m&jjk2=dGAZJYytNbB07B8kWB>pF literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test74/Intermediate CRL RL.07.03.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test74/Intermediate CRL RL.07.03.crl new file mode 100644 index 0000000000000000000000000000000000000000..8733b183c855873ff3279790589e1655f34755d4 GIT binary patch literal 337 zcmXqLV)Qj=+|I>;VeC7F5YhN1?-AQ5I^9%n~G z-5?)519LqCV{u+fO9Mk7Gy`ITC<%Te15*Q#fT0msV1crMBG_PA5f)~U^FW5kDzgA> zYv71cy;+qgI3)HO=ZS)9v5zs6Pq0GfYc A=l}o! literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test74/Intermediate Certificate RL.07.03.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test74/Intermediate Certificate RL.07.03.crt new file mode 100644 index 0000000000000000000000000000000000000000..c9258148d991908a45e70af6a7144ad281805a74 GIT binary patch literal 666 zcmXqLVwz^q#Q1*!GZP~d6BEN>170>xtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;-^EbCfDgiB4@oU9$;?YP6g3bA zi7*TEgcOw)mnb;qC1>Op8OVwAT3Q$w8Wab6Q-E_wE+;I-e`(NH(YN6)}q z&%oHAaXzw-8Ce;a8+#cH8atU98yPcT;*?uyDIlV}e)?vURT<9`X1qJx zQl9vQBgVL7_Qi`gCarv$G}+UA?#%2*l6q%zQa0<#{d@6}`=FMg`Q<0f-_K0yJ9lAe zW9{vQ`zk)o3OJLW*q-8lLoW|_n-vFslYjRZ1+1T8YZ zJ2NpeGB7SqHb^w!2L_$2FeBrC7FGjhAO#LxS$>cJ3oz!`z_B8$z`}39YrxIMnb79J zn99s(z-S-{(#Xfc#ljJzdb27~a7qw38f2AOfbrG9v3l0)pNF1@^dpA>FxHuYo@e_h z;gXOTxXyClw#G0Ari#4DlXi1xilsg0+rOgY-2?^YCA*jX(wP1|Tt-*-9E;tblX{V- z{@u>BKe_JyFO~V7T`GMgDot&yNxtVN+4RNmK09|Vt0h+5;$PdooF7?-dzoL&^jfxK gnT_k0m4Ect$$wYhBv^T8QrhRTw8snq>noY~0S_wDUjP6A literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test74/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test74/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test75/End Certificate RL.08.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test75/End Certificate RL.08.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..7d8179be08ee4a024ea09b5eb699f89ca3e6694b GIT binary patch literal 651 zcmXqLVrn;NV*IdxnTe5!iHYHu0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE;5ygM9Q1Ec6Tv4dldmEiHhwp`j6wG>8)CH9_VYB#>jj3l{su4MZXK^Mw|t z79qKyaXzx28Ce;a8+#cH8atU98yW5koSJ5|(%fzP&e=`eTbYa>Px6@c)%^Vh)xUac zZ|h$^r`cKD`A}hr=4aQa6#fT?-XAXdtf2DQP9)}M@T`jy%w{lZ%iQmd3~*_EvSC;1 zZnu@6YF{+X&9Z(Xv77xw-`$O`H)Qg%PI)6UW3iC?`5J>{-<&m34wsI^9b!E-#d*WM z&UPkdMh3>kK?VWf;FRTOWc<&MzcJN=Xeq*KhjZJ4= zX}d(vssiQ4kZz@J#j{ND#wMYS8OCORuX5*T2deL3KCE#~G$i!3{szX7rX8(*?KOu* U@~XTdWP+dP{pcu}6Mxzp0GIj4?EnA( literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test75/Intermediate CRL RL.08.01.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test75/Intermediate CRL RL.08.01.crl new file mode 100644 index 0000000000000000000000000000000000000000..19f472c7f9c2759d2f520a9305be72fd315c9bf6 GIT binary patch literal 350 zcmXqLVvI6qJi^4tXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-5?)50}DL^Lvdb9O9Mj#Lqj7VX%HpOYhr=KU0`Hj05(=ugoPR6IOb4UX-3BX5H83> zS!EWW)eRhS2G!>mD(&P#^8j;WBf})ak_9fgPfNFT?^QT;Dn+n~{X|0hyp<0o>lN*0 z5pvrZ_U^8}xtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;-^EbCfDgiB4@oU9$;?YP6g3bA zi7*TEgcOw)mnb;qC1>Op8OVwAT3Q$w8Wab6Q-E_wE+;I-e`(NH(YN6)}Q z4`^fKd}JRpvNA9?_A(eWb}}_KGHgy0^zkg`4tX}Kyz|A{(n}=`T=iY?B7HsyZ02+F zWAlDq)y@>oXmMz}81hBd*m90zt#lFpwWYW29r&VJemSrw;&<2my$M$o-+kt4ouk3< zi+R?U=e}2t?2MJU5_FX}A}NF6uf~C>habFMznluUFlO4n!fesQ*=3C7NntJ(b~XG= z%!~|-i<1o!4fugUCo9az_@9N-En=&qMl=!vGlT%s|hJTu?r{ zj^m8L!yO_~`%|-7I-b}}Yc85`y|Cih2GtpB=1k(e_f_#WM}7Cc-0PE^w6xOOYvx|? z{dar0-8`Y4-?>GyrSd!@cg7@c4gPgEQCTDYB^N{tEyEKF%fp literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test75/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test75/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test76/End Certificate RL.09.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test76/End Certificate RL.09.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..bde477d893b7ad653e2c0a11d3aa32188f46eb23 GIT binary patch literal 651 zcmXqLVrn;NV*IdxnTe5!iHYHa0WTY;R+~rLcV0$DR#pasI74m&PB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzInapJFIrzz5;6holylWagzCiW&%m zM3{wnoE;5ygM9Q1EcFZw4dldmEiHhwp`j6wG>8)CH9_VYB#>jj3l{su4MZXK^Mw|t z79qKyaXzx28Ce;a8+#cH8atU98yQ}n_YdW)InYvP-}zbPqJVLRR3~RyyW9d<>o3<{ zy*?Lqv#uulTAb)JPlYM<7M4e(<_1>1D%SBc@O@v#Si0k3G@yj3;t(toK;a=LC zY>gi$`S!njYhj$1?DYIph@FS-u_9Odp4DeA)QU2MdH#HyHs`{GEmPjt_@dOEFJqEBicQSply*XFL6(iOQ_7 V7hmTIiP?XzJNEROY+K3dDF6kq(7XTu literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test76/Intermediate CRL RL.09.01.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test76/Intermediate CRL RL.09.01.crl new file mode 100644 index 0000000000000000000000000000000000000000..dbbbd43bee3b10761f08256c59c66acf4833310d GIT binary patch literal 352 zcmXqLVvI3pJjTSxXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G z-5?)514}&vLvdb9O9Mj#Lqj7VX%HpOYhr=KU0`Bh1U6PygoPR8IDViJvNDW}|5;cK zn41{?gUysxW&v8>z|k_};qGGw4#8+%U~X(=;PNd~SQY$l*F=v4Pga&L_2RXcS`l;O zTS>=e!3R&%Qy-UFFYn{t%Nh2uXyM^~8cwk;NBwf%CEOBPP@>XhEN!{MTxpHa4l#|Z z`=(8rbX2bHisL!<#Vc;CSiIC)Un1(bi00AD*Z-<6xn(FMZWZzI-e$h5ZaHxtu~Lg@4SqRtgH+MafaLmoNUaYENsF|p}~d{ z24Wx%moR^*Ua+2mdwyAJQC@CpUWp-(0T)PyTbS7;-^EbCfDgiB4@oU9$;?YP6g3bA zi7*TEgcOw)mnb;qC1>Op8OVwAT3Q$w8Wab6Q-E_wE+;I-e`(NH(YN6)}g z4`^fKd}JRpvNA9?_A(eWb}}_KGHm*(ulFzBAWVOe*mUb-yQNqy))?OVru19qZ)n9; z1&MY~sl`X;y-;xeq1U#-J@ezjE4S08xIMF(C+2)VmUZ)S*~fb}epoOmwdtZ(zl9aY zue+~QJmqiO$3`_M^~VLq{7gE{R{T?Mw%>IY2NstTB38!dkE@^k;96C`Lo3$i$;ObM zOw5c7jEj>E5)Jr)K_@HB$oQXy)qojDfkRi8A0)s6j5#)NtjH>`@Eh-` z^@g|2vzb3v_%iOao10S5U*}nB?7+C0Cn7vDh^5N>_2%Qzzq`+^WK7j`neUPCLu4Ue e<}CC0yV6_dZMyGv&uIBeUfHZFh5i4G*?9o`aLy|L literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test76/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test76/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test8/End Certificate CP.02.05.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test8/End Certificate CP.02.05.crt new file mode 100644 index 0000000000000000000000000000000000000000..cb99c2ac554c44e8ca22f34faf6efbde384b947a GIT binary patch literal 652 zcmXqLV(KtxV*I#(nTe5!iBZ6SmyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uC<0eS{TdIqKj3KINAK+3?-z|hbLNE$?m^O{&7aSam4ae)gK7l<2(LR`QX zTAW&hmDnd;#};S{z4>Y zmg((pGuMhVt=xIEYEQA3c3%1BgIaalYHp?p?$j`jTt9#FJ+DKP7Pm=TPuUyvs$!16 z#qQl|XLh{LJixrawVnOu+ER|65w_x8tv}oMT+=?hw$(u>Z7J7;O)?L-%KoSvwmf0xhk5s90s)~D)ad{K literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test8/Intermediate CRL CP.02.05.crl b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test8/Intermediate CRL CP.02.05.crl new file mode 100644 index 0000000000000000000000000000000000000000..d5ee3c3ce3eb7dd3bae060cedcb703d3f4546263 GIT binary patch literal 335 zcmXqLV)Qm>+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zUFQHj10y{HQ*mBPO9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aVDf zPE>xPr`(0+V&=w1hRCTLHv?xpnzrPU6O+Z|{~W7t&1}qhcE__;ZZCsguE6}()5Xs` zA3o7_i~rYdTYiw`)Lxzq9T(+{E8?5AcAQLk5dJjvxQ*n_0PRC}V}y3_>jrfe9(a;a w9vq<7Y+x+NxIt1Z{cQ5jUz@6)y$avw&5*2oVb<=6#?Cu8c*bn``HTG-0AQeJlK=n! literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test8/Intermediate Certificate CP.02.05.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test8/Intermediate Certificate CP.02.05.crt new file mode 100644 index 0000000000000000000000000000000000000000..d26979cdd6f04e0c115f14ad0a0a390f7d6ef106 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6C=L?FB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%3ndec#JADOJsL-dkp`;yt&P&fgst!WVr)dU?FY)QOHv z%!~|-i<1o!4fugUCo9az_@9NNJ%Mj?CaPuW*vM~xdpb^HY4M6+=i8}wK8vvb z-T(Y(>y}RkCh4%By?7*VQ_Hl2DHFGR-d2D86ZeNKZr#RPF5DuQ&#?J!>$zBqXyo~b!Kb8GnSf`3`p8I1toAr&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test9/End Certificate CP.03.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test9/End Certificate CP.03.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..4dd2352b4e5a95615f79fac3d8a2d245fa390cb5 GIT binary patch literal 650 zcmXqLVrnyJVtl`VnTe5!iBZUamyJ`a&7D}zCtA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HO>F%&T1gYeixQj1G6^U@7P4TM1= z%)&g*j)uC<0eS|;dIp9Da^k#}7C_q2&AKA~0tPISJy$lA8olK354D%1@E~_)VT&Q9AC@Aj56;AMu#;sfW+%dVUJF>Xx71RM9b; ziJ6gsadD7A05~{h`577iv#>BTu|5DtgRBAzzX7iSHydX{n+IbmGot~cfgsS6vV1ID zEF7P67j5GIV50>NcUff?U<5UAJW8^%vNl;%jqGJ$G&2MJ+7+a3VXNe{>9wpR-(#!4 z-dDpJrk)J1tUdVcG&}or+{(nrXu!+HsnzDu_MMlJk(HIfAkL86fRl|ml!Z;0DKywn!axkf;S%N# z)eF{BaL+GGEy~MH%_}kFG2jBpa0@fL>;VeC7F5YhN1?-AQ5I^9%n~G zUFQHj17ke{Lvdb9O9Mj#Lqj7VX%HpOYhr=KU7&2B2sTz$goPR8IFJ#t$}B*;8aN&$ zSy@?|EUHFxF>_-hLp_`PBL}uerw-nX3F}JAxl$wUyZG>;_N7zVRnuqq|MAT8-z9gs zequ%V{8vwJ%iaIzdVSVH4o_*7{*PDZzjTt;Kf5ARO^ZuNpK-#kv&K?;JcI;o`KNkw wU0ulIH<@M2;`fyogDj05GY;n)n@rn2r(oC4U-#Bb_j%)9-?>e{$L5zV09o*4rT_o{ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test9/Intermediate Certificate CP.03.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test9/Intermediate Certificate CP.03.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..c107dd756ca2c1518020f2bc979c49234b011f71 GIT binary patch literal 665 zcmXqLVw!5u#Q1LkGZP~d6QiI3FB_*;n@8JsUPeY%RtAGOLv903Hs(+kHesgFU_%K5 zF%XAKm_Jl6SWm${zbv&VFE=%>#E{2;3narW%YYDT&4D53&t6Ms)lVXxdz< zl_AbDN9juVmo@1=tw&fb^w|9FIeJT*pIP_#{+Vg(ECo34%~lI!%{eWyjoU_D{qmh+_lCimU<)zX7iSHydX{n+Ibm zGot~cfgngD9}5=?$D<@GD{GTQ)!=B5Rb~OkR|CiDS+9Q{dLGh`90tHxX9jxSFmQA5 z@*fEgU&@8;OM2MUQ#>WL>%f<}JEcom#hPE=nC2q=F#4HDK#-i!wWR`@mA}fS=4HQ{ ztYT^I$J_hixra>tgVP@Q3Dt%z8z%8Gj0h literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test9/Trust Anchor CP.01.01.crt b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/test9/Trust Anchor CP.01.01.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7dfd9d48f0460a72466c63c92a3ca4f8ce85c70 GIT binary patch literal 624 zcmXqLV#+aSV!XP5nTe5!iJ7r&z5y>Ar&gOs+jm|@Mpjk^gE&KO15P&PP!={}rqEzR z2?H?@hfA10R4-Uh!9Bk$wJ0w)HLt{w$AAkY!!6A0lJ8^^Tkg-6(V)r2(@D`ahOZ->w_RB(EIHoIWyO8^g zqMcjA8s1e*m5}<9T%cw-TT-E=cXv|!eVv82f21#1?Y?nF+DvHC>a}*y9tLeG6&8G> ZK6P30`O9a%_}$pGW9`~AQmM>;VeC7F5YhN1?-AQ5I^o{*x_ z;t~bNyyT4hB5__zO9Mj#Lqj7VX%HpOYhr=KHBd58U}989Qe*&BWB{>BR+NRAi;;1G zvVkJlYFQB$W{?L!*2pTe02MWGte*Ay=b`5z{b;^oZfs=W-kFuozF1Xsx6_~F*W-T| zwsYUxHmBi?`<*XS{yl$xVyAVMNZn6q_pCkpBOk1Hy|a1Fjt&ccNj43=sH^^~4i{~> z`8#5lyhCf$?=Oe%+Apm>9Ku_Zm$R{WNiI&Ts22MIDp6 Tx^k7bFjlxZtkivWmP-r(p|o-l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/X509tests/x509tests.scr b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/x509tests.scr new file mode 100644 index 00000000..f10f96ba --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/X509tests/x509tests.scr @@ -0,0 +1,969 @@ +# +# script input to certcrl for X509 tests +# +globals +requireCrlForAll = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +allowUnverified = true +end + +test = Test1 +dir = test1 +revokePolicy = crl +cert = "End Certificate CP.01.01.crt" +root = "Trust Anchor CP.01.01.crt" +crl = "Trust Anchor CRL CP.01.01.crl" +end +test = Test2 +dir = test2 +revokePolicy = crl +cert = "End Certificate CP.01.02.crt" +cert = "Intermediate Certificate CP.01.02.crt" +root = "Trust Anchor CP.01.01.crt" +crl = "Trust Anchor CRL CP.01.01.crl" +crl = "Intermediate CRL CP.01.02.crl" +error = TP_NOT_TRUSTED +certerror = 0:CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_CRL_NOT_TRUSTED +end +test = Test3 +dir = test3 +revokePolicy = crl +cert = "End Certificate CP.01.03.crt" +cert = "Intermediate Certificate CP.01.03.crt" +root = "Trust Anchor CP.01.01.crt" +crl = "Trust Anchor CRL CP.01.01.crl" +crl = "Intermediate CRL CP.01.03.crl" +error = CSSMERR_TP_NOT_TRUSTED +end + +test = Test4 +dir = test4 +revokePolicy = crl +cert = "End Certificate CP.02.01.crt" +cert = "Intermediate Certificate 1 CP.02.01.crt" +cert = "Intermediate Certificate 2 CP.02.01.crt" +crl = "Intermediate CRL 1 CP.02.01.crl" +crl = "Intermediate CRL 2 CP.02.01.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = Test5 +dir = test5 +revokePolicy = crl +cert = "End Certificate CP.02.02.crt" +root = "Trust Anchor CP.01.01.crt" +crl = "Trust Anchor CRL CP.01.01.crl" +crl = "Intermediate CRL CP.02.02.crl" +cert = "Intermediate Certificate CP.02.02.crt" +error = CSSMERR_TP_CERT_NOT_VALID_YET +end + +test = Test6 +dir = test6 +revokePolicy = crl +cert = "End Certificate CP.02.03.crt" +root = "Trust Anchor CP.01.01.crt" +crl = "Intermediate CRL CP.02.03.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +cert = "Intermediate Certificate CP.02.03.crt" +error = CSSMERR_TP_CERT_NOT_VALID_YET +end + +test = Test7 +dir = test7 +revokePolicy = crl +cert = "End Certificate CP.02.04.crt" +root = "Trust Anchor CP.01.01.crt" +crl = "Trust Anchor CRL CP.01.01.crl" +crl = "Intermediate CRL CP.02.04.crl" +cert = "Intermediate Certificate CP.02.04.crt" +end + +test = Test8 +dir = test8 +revokePolicy = crl +cert = "End Certificate CP.02.05.crt" +root = "Trust Anchor CP.01.01.crt" +crl = "Trust Anchor CRL CP.01.01.crl" +crl = "Intermediate CRL CP.02.05.crl" +cert = "Intermediate Certificate CP.02.05.crt" +error = CSSMERR_TP_CERT_NOT_VALID_YET +end + +test = Test9 +dir = test9 +revokePolicy = crl +cert = "End Certificate CP.03.01.crt" +root = "Trust Anchor CP.01.01.crt" +crl = "Trust Anchor CRL CP.01.01.crl" +crl = "Intermediate CRL CP.03.01.crl" +cert = "Intermediate Certificate CP.03.01.crt" +error = CSSMERR_TP_CERT_EXPIRED +end + +test = Test10 +dir = test10 +revokePolicy = crl +cert = "End Certificate CP.03.02.crt" +root = "Trust Anchor CP.01.01.crt" +crl = "Trust Anchor CRL CP.01.01.crl" +crl = "Intermediate CRL CP.03.02.crl" +cert = "Intermediate Certificate CP.03.02.crt" +error = CSSMERR_TP_CERT_EXPIRED +end + +test = Test11 +dir = test11 +revokePolicy = crl +cert = "End Certificate CP.03.03.crt" +root = "Trust Anchor CP.01.01.crt" +crl = "Trust Anchor CRL CP.01.01.crl" +crl = "Intermediate CRL CP.03.03.crl" +cert = "Intermediate Certificate CP.03.03.crt" +error = CSSMERR_TP_CERT_EXPIRED +end + +test = Test12 +dir = test12 +revokePolicy = crl +cert = "End Certificate CP.03.04.crt" +root = "Trust Anchor CP.01.01.crt" +crl = "Trust Anchor CRL CP.01.01.crl" +crl = "Intermediate CRL CP.03.04.crl" +cert = "Intermediate Certificate CP.03.04.crt" +end + +test = Test13 +dir = test13 +revokePolicy = crl +cert = "End Certificate CP.04.01.crt" +root = "Trust Anchor CP.01.01.crt" +crl = "Trust Anchor CRL CP.01.01.crl" +crl = "Intermediate CRL CP.04.01.crl" +cert = "Intermediate Certificate CP.04.01.crt" +error = CSSMERR_TP_NOT_TRUSTED +certerror = 0:CSSMERR_APPLETP_CRL_NOT_FOUND +end + +test = Test14 +dir = test14 +revokePolicy = crl +cert = "End Certificate CP.04.02.crt" +root = "Trust Anchor CP.01.01.crt" +crl = "Trust Anchor CRL CP.01.01.crl" +crl = "Intermediate CRL CP.04.02.crl" +cert = "Intermediate Certificate CP.04.02.crt" +error = CSSMERR_TP_NOT_TRUSTED +certerror = 0:CSSMERR_APPLETP_CRL_NOT_FOUND +end + +test = Test15 +dir = test15 +revokePolicy = crl +cert = "End Certificate CP.04.03.crt" +root = "Trust Anchor CP.01.01.crt" +crl = "Trust Anchor CRL CP.01.01.crl" +crl = "Intermediate CRL CP.04.03.crl" +cert = "Intermediate Certificate CP.04.03.crt" +end + +test = test16 +dir = test16 +revokePolicy = crl +cert = "End Certificate CP.04.04.crt" +cert = "Intermediate Certificate CP.04.04.crt" +crl = "Intermediate CRL CP.04.04.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test17 +dir = test17 +revokePolicy = crl +cert = "End Certificate CP.04.05.crt" +cert = "Intermediate Certificate CP.04.05.crt" +crl = "Intermediate CRL CP.04.05.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test18 +dir = test18 +revokePolicy = crl +cert = "End Certificate CP.04.06.crt" +cert = "Intermediate Certificate CP.04.06.crt" +crl = "Intermediate CRL CP.04.06.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test19 +dir = test19 +revokePolicy = crl +cert = "End Certificate CP.05.01.crt" +cert = "Intermediate Certificate CP.05.01.crt" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_CRL_NOT_FOUND +end + +test = test20 +dir = test20 +revokePolicy = crl +cert = "End Certificate CP.06.01.crt" +cert = "Intermediate Certificate CP.06.01.crt" +crl = "Intermediate CRL CP.06.01.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_TP_CERT_REVOKED +certerror = 1:CSSMERR_TP_CERT_REVOKED +end + +test = test21 +dir = test21 +revokePolicy = crl +cert = "End Certificate CP.06.02.crt" +cert = "Intermediate Certificate CP.06.02.crt" +crl = "Intermediate CRL CP.06.02.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_TP_CERT_REVOKED +certerror = 0:CSSMERR_TP_CERT_REVOKED +end + +test = test22 +dir = test22 +revokePolicy = crl +cert = "End Certificate IC.01.01.crt" +cert = "Intermediate Certificate IC.01.01.crt" +crl = "Intermediate CRL IC.01.01.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_TP_VERIFY_ACTION_FAILED +certerror = 1:CSSMERR_APPLETP_INVALID_CA +end + +test = test23 +dir = test23 +revokePolicy = crl +cert = "End Certificate IC.02.01.crt" +cert = "Intermediate Certificate IC.02.01.crt" +crl = "Intermediate CRL IC.02.01.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_TP_VERIFY_ACTION_FAILED +certerror = 1:CSSMERR_APPLETP_INVALID_CA +end + +test = test24 +dir = test24 +revokePolicy = crl +cert = "End Certificate IC.02.02.crt" +cert = "Intermediate Certificate IC.02.02.crt" +crl = "Intermediate CRL IC.02.02.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test25 +dir = test25 +revokePolicy = crl +cert = "End Certificate IC.02.03.crt" +cert = "Intermediate Certificate IC.02.03.crt" +crl = "Intermediate CRL IC.02.03.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_TP_VERIFY_ACTION_FAILED +certerror = 1:CSSMERR_APPLETP_INVALID_CA +end + +test = test26 +dir = test26 +revokePolicy = crl +cert = "End Certificate IC.02.04.crt" +cert = "Intermediate Certificate IC.02.04.crt" +crl = "Intermediate CRL IC.02.04.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test27 +dir = test27 +revokePolicy = crl +cert = "End Certificate IC.04.01.crt" +cert = "Intermediate Certificate IC.04.01.crt" +crl = "Intermediate CRL IC.04.01.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test28 +dir = test28 +revokePolicy = crl +cert = "End Certificate IC.05.01.crt" +cert = "Intermediate Certificate IC.05.01.crt" +crl = "Intermediate CRL IC.05.01.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_TP_VERIFY_ACTION_FAILED +certerror = 1:CSSMERR_APPLETP_INVALID_KEY_USAGE +end + +test = test29 +dir = test29 +revokePolicy = crl +cert = "End Certificate IC.05.02.crt" +cert = "Intermediate Certificate IC.05.02.crt" +crl = "Intermediate CRL IC.05.02.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_TP_VERIFY_ACTION_FAILED +certerror = 1:CSSMERR_APPLETP_INVALID_KEY_USAGE +end + +test = test30 +dir = test30 +revokePolicy = crl +cert = "End Certificate IC.05.03.crt" +cert = "Intermediate Certificate IC.05.03.crt" +crl = "Intermediate CRL IC.05.03.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test31 +dir = test31 +revokePolicy = crl +cert = "End Certificate IC.06.01.crt" +cert = "Intermediate Certificate IC.06.01.crt" +crl = "Intermediate CRL IC.06.01.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_APPLETP_CRL_NOT_FOUND +# for the issuer +certerror = 1:CSSMERR_APPLETP_INVALID_KEY_USAGE +# for the leaf +certerror = 0:CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_CRL_POLICY_FAIL +end + +test = test32 +dir = test32 +revokePolicy = crl +cert = "End Certificate IC.06.02.crt" +cert = "Intermediate Certificate IC.06.02.crt" +crl = "Intermediate CRL IC.06.02.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_APPLETP_CRL_NOT_FOUND +# for the issuer +certerror = 1:CSSMERR_APPLETP_INVALID_KEY_USAGE +# for the leaf +certerror = 0:CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_CRL_POLICY_FAIL +end + +test = test33 +dir = test33 +revokePolicy = crl +cert = "End Certificate IC.06.03.crt" +cert = "Intermediate Certificate IC.06.03.crt" +crl = "Intermediate CRL IC.06.03.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test34 +dir = test34 +revokePolicy = crl +echo FIXME: test34 needs policy work +cert = "End Certificate PP.01.01.crt" +cert = "Intermediate Certificate PP.01.01.crt" +crl = "Intermediate CRL PP.01.01.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test35 +dir = test35 +revokePolicy = crl +echo FIXME: test35 needs policy work +cert = "End Certificate PP.01.02.crt" +cert = "Intermediate Certificate PP.01.02.crt" +crl = "Intermediate CRL PP.01.02.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test36 +dir = test36 +revokePolicy = crl +echo FIXME: test36 needs policy work +cert = "End Certificate PP.01.03.crt" +cert = "Intermediate Certificate 1 PP.01.03.crt" +cert = "Intermediate Certificate 2 PP.01.03.crt" +crl = "Intermediate CRL 1 PP.01.03.crl" +crl = "Intermediate CRL 2 PP.01.03.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test37 +dir = test37 +revokePolicy = crl +echo FIXME: test37 needs policy work +cert = "End Certificate PP.01.04.crt" +cert = "Intermediate Certificate 1 PP.01.04.crt" +cert = "Intermediate Certificate 2 PP.01.04.crt" +crl = "Intermediate CRL 1 PP.01.04.crl" +crl = "Intermediate CRL 2 PP.01.04.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test38 +dir = test38 +revokePolicy = crl +echo FIXME: test38 needs policy work +cert = "End Certificate PP.01.05.crt" +cert = "Intermediate Certificate 1 PP.01.05.crt" +cert = "Intermediate Certificate 2 PP.01.05.crt" +crl = "Intermediate CRL 1 PP.01.05.crl" +crl = "Intermediate CRL 2 PP.01.05.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test39 +dir = test39 +revokePolicy = crl +echo FIXME: test39 needs policy work +cert = "End Certificate PP.01.06.crt" +cert = "Intermediate Certificate 1 PP.01.06.crt" +cert = "Intermediate Certificate 2 PP.01.06.crt" +cert = "Intermediate Certificate 3 PP.01.06.crt" +crl = "Intermediate CRL 1 PP.01.06.crl" +crl = "Intermediate CRL 2 PP.01.06.crl" +crl = "Intermediate CRL 3 PP.01.06.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +leafCertIsCA = true +end + +test = test40 +dir = test40 +revokePolicy = crl +echo FIXME: test40 needs policy work +cert = "End Certificate PP.01.07.crt" +cert = "Intermediate Certificate 1 PP.01.07.crt" +cert = "Intermediate Certificate 2 PP.01.07.crt" +cert = "Intermediate Certificate 3 PP.01.07.crt" +crl = "Intermediate CRL 1 PP.01.07.crl" +crl = "Intermediate CRL 2 PP.01.07.crl" +crl = "Intermediate CRL 3 PP.01.07.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +leafCertIsCA = true +end + +test = test41 +dir = test41 +revokePolicy = crl +echo FIXME: test41 needs policy work +cert = "End Certificate PP.01.08.crt" +cert = "Intermediate Certificate 1 PP.01.08.crt" +cert = "Intermediate Certificate 2 PP.01.08.crt" +cert = "Intermediate Certificate 3 PP.01.08.crt" +crl = "Intermediate CRL 1 PP.01.08.crl" +crl = "Intermediate CRL 2 PP.01.08.crl" +crl = "Intermediate CRL 3 PP.01.08.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +leafCertIsCA = true +end + +test = test42 +dir = test42 +revokePolicy = crl +echo FIXME: test42 needs policy work +cert = "End Certificate PP.01.09.crt" +cert = "Intermediate Certificate 1 PP.01.09.crt" +cert = "Intermediate Certificate 2 PP.01.09.crt" +cert = "Intermediate Certificate 3 PP.01.09.crt" +cert = "Intermediate Certificate 4 PP.01.09.crt" +crl = "Intermediate CRL 1 PP.01.09.crl" +crl = "Intermediate CRL 2 PP.01.09.crl" +crl = "Intermediate CRL 3 PP.01.09.crl" +crl = "Intermediate CRL 4 PP.01.09.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test43 +dir = test43 +revokePolicy = crl +echo FIXME: test43 needs policy work +cert = "End Certificate PP.06.01.crt" +cert = "Intermediate Certificate 1 PP.06.01.crt" +cert = "Intermediate Certificate 2 PP.06.01.crt" +cert = "Intermediate Certificate 3 PP.06.01.crt" +cert = "Intermediate Certificate 4 PP.06.01.crt" +crl = "Intermediate CRL 1 PP.06.01.crl" +crl = "Intermediate CRL 2 PP.06.01.crl" +crl = "Intermediate CRL 3 PP.06.01.crl" +crl = "Intermediate CRL 4 PP.06.01.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test44 +dir = test44 +revokePolicy = crl +echo FIXME: test44 needs policy work +cert = "End Certificate PP.06.02.crt" +cert = "Intermediate Certificate 1 PP.06.02.crt" +cert = "Intermediate Certificate 2 PP.06.02.crt" +cert = "Intermediate Certificate 3 PP.06.02.crt" +cert = "Intermediate Certificate 4 PP.06.02.crt" +crl = "Intermediate CRL 1 PP.06.02.crl" +crl = "Intermediate CRL 2 PP.06.02.crl" +crl = "Intermediate CRL 3 PP.06.02.crl" +crl = "Intermediate CRL 4 PP.06.02.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test45 +dir = test45 +revokePolicy = crl +echo FIXME: test45 needs policy work +cert = "End Certificate PP.06.03.crt" +cert = "Intermediate Certificate 1 PP.06.03.crt" +cert = "Intermediate Certificate 2 PP.06.03.crt" +cert = "Intermediate Certificate 3 PP.06.03.crt" +cert = "Intermediate Certificate 4 PP.06.03.crt" +crl = "Intermediate CRL 1 PP.06.03.crl" +crl = "Intermediate CRL 2 PP.06.03.crl" +crl = "Intermediate CRL 3 PP.06.03.crl" +crl = "Intermediate CRL 4 PP.06.03.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test46 +dir = test46 +revokePolicy = crl +echo FIXME: test46 needs policy work +cert = "End Certificate PP.06.04.crt" +cert = "Intermediate Certificate 1 PP.06.04.crt" +cert = "Intermediate Certificate 2 PP.06.04.crt" +cert = "Intermediate Certificate 3 PP.06.04.crt" +cert = "Intermediate Certificate 4 PP.06.04.crt" +crl = "Intermediate CRL 1 PP.06.04.crl" +crl = "Intermediate CRL 2 PP.06.04.crl" +crl = "Intermediate CRL 3 PP.06.04.crl" +crl = "Intermediate CRL 4 PP.06.04.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test47 +dir = test47 +revokePolicy = crl +echo FIXME: test47 needs policy work +cert = "End Certificate PP.06.05.crt" +cert = "Intermediate Certificate 1 PP.06.05.crt" +cert = "Intermediate Certificate 2 PP.06.05.crt" +cert = "Intermediate Certificate 3 PP.06.05.crt" +cert = "Intermediate Certificate 4 PP.06.05.crt" +crl = "Intermediate CRL 1 PP.06.05.crl" +crl = "Intermediate CRL 2 PP.06.05.crl" +crl = "Intermediate CRL 3 PP.06.05.crl" +crl = "Intermediate CRL 4 PP.06.05.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test48 +dir = test48 +revokePolicy = crl +echo FIXME: test48 needs policy work +cert = "End Certificate PP.08.01.crt" +cert = "Intermediate Certificate PP.08.01.crt" +crl = "Intermediate CRL PP.08.01.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test49 +dir = test49 +revokePolicy = crl +echo FIXME: test49 needs policy work +cert = "End Certificate PP.08.02.crt" +cert = "Intermediate Certificate PP.08.02.crt" +crl = "Intermediate CRL PP.08.02.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test50 +dir = test50 +revokePolicy = crl +echo FIXME: test50 needs policy work +cert = "End Certificate PP.08.03.crt" +cert = "Intermediate Certificate PP.08.03.crt" +crl = "Intermediate CRL PP.08.03.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test51 +dir = test51 +revokePolicy = crl +echo FIXME: test51 needs policy work +cert = "End Certificate PP.08.04.crt" +cert = "Intermediate Certificate PP.08.04.crt" +crl = "Intermediate CRL PP.08.04.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test52 +dir = test52 +revokePolicy = crl +echo FIXME: test52 needs policy work +cert = "End Certificate PP.08.05.crt" +cert = "Intermediate Certificate PP.08.05.crt" +crl = "Intermediate CRL PP.08.05.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test53 +dir = test53 +revokePolicy = crl +echo FIXME: test53 needs policy work +cert = "End Certificate PP.08.06.crt" +cert = "Intermediate Certificate PP.08.06.crt" +crl = "Intermediate CRL PP.08.06.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test54 +dir = test54 +revokePolicy = crl +cert = "End Certificate PL.01.01.crt" +cert = "Intermediate Certificate 1 PL.01.01.crt" +cert = "Intermediate Certificate 2 PL.01.01.crt" +crl = "Intermediate CRL 1 PL.01.01.crl" +crl = "Intermediate CRL 2 PL.01.01.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_TP_VERIFY_ACTION_FAILED +certerror = 2:CSSMERR_APPLETP_PATH_LEN_CONSTRAINT +end + +test = test55 +dir = test55 +revokePolicy = crl +cert = "End Certificate PL.01.02.crt" +cert = "Intermediate Certificate 1 PL.01.02.crt" +cert = "Intermediate Certificate 2 PL.01.02.crt" +crl = "Intermediate CRL 1 PL.01.02.crl" +crl = "Intermediate CRL 2 PL.01.02.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +certerror = 2:CSSMERR_APPLETP_PATH_LEN_CONSTRAINT +error = CSSMERR_TP_VERIFY_ACTION_FAILED +end + +test = test56 +dir = test56 +revokePolicy = crl +cert = "End Certificate PL.01.03.crt" +cert = "Intermediate Certificate PL.01.03.crt" +crl = "Intermediate CRL PL.01.03.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test57 +dir = test57 +revokePolicy = crl +cert = "End Certificate PL.01.04.crt" +cert = "Intermediate Certificate PL.01.04.crt" +crl = "Intermediate CRL PL.01.04.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +leafCertIsCA = true +end + +test = test58 +dir = test58 +revokePolicy = crl +cert = "End Certificate PL.01.05.crt" +cert = "Intermediate Certificate 1 PL.01.05.crt" +cert = "Intermediate Certificate 2 PL.01.05.crt" +cert = "Intermediate Certificate 3 PL.01.05.crt" +crl = "Intermediate CRL 1 PL.01.05.crl" +crl = "Intermediate CRL 2 PL.01.05.crl" +crl = "Intermediate CRL 3 PL.01.05.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_TP_VERIFY_ACTION_FAILED +certerror = 2:CSSMERR_APPLETP_PATH_LEN_CONSTRAINT +end + +test = test59 +dir = test59 +revokePolicy = crl +cert = "End Certificate PL.01.06.crt" +cert = "Intermediate Certificate 1 PL.01.06.crt" +cert = "Intermediate Certificate 2 PL.01.06.crt" +cert = "Intermediate Certificate 3 PL.01.06.crt" +crl = "Intermediate CRL 1 PL.01.06.crl" +crl = "Intermediate CRL 2 PL.01.06.crl" +crl = "Intermediate CRL 3 PL.01.06.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +leafCertIsCA = true +error = CSSMERR_TP_VERIFY_ACTION_FAILED +certerror = 2:CSSMERR_APPLETP_PATH_LEN_CONSTRAINT +end + +test = test60 +dir = test60 +revokePolicy = crl +cert = "End Certificate PL.01.07.crt" +cert = "Intermediate Certificate 1 PL.01.07.crt" +cert = "Intermediate Certificate 2 PL.01.07.crt" +cert = "Intermediate Certificate 3 PL.01.07.crt" +cert = "Intermediate Certificate 4 PL.01.07.crt" +crl = "Intermediate CRL 1 PL.01.07.crl" +crl = "Intermediate CRL 2 PL.01.07.crl" +crl = "Intermediate CRL 3 PL.01.07.crl" +crl = "Intermediate CRL 4 PL.01.07.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_TP_VERIFY_ACTION_FAILED +certerror = 3:CSSMERR_APPLETP_PATH_LEN_CONSTRAINT +end + +test = test61 +dir = test61 +revokePolicy = crl +cert = "End Certificate PL.01.08.crt" +cert = "Intermediate Certificate 1 PL.01.08.crt" +cert = "Intermediate Certificate 2 PL.01.08.crt" +cert = "Intermediate Certificate 3 PL.01.08.crt" +cert = "Intermediate Certificate 4 PL.01.08.crt" +crl = "Intermediate CRL 1 PL.01.08.crl" +crl = "Intermediate CRL 2 PL.01.08.crl" +crl = "Intermediate CRL 3 PL.01.08.crl" +crl = "Intermediate CRL 4 PL.01.08.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +leafCertIsCA = true +error = CSSMERR_TP_VERIFY_ACTION_FAILED +certerror = 3:CSSMERR_APPLETP_PATH_LEN_CONSTRAINT +end + +test = test62 +dir = test62 +revokePolicy = crl +cert = "End Certificate PL.01.09.crt" +cert = "Intermediate Certificate 1 PL.01.09.crt" +cert = "Intermediate Certificate 2 PL.01.09.crt" +cert = "Intermediate Certificate 3 PL.01.09.crt" +cert = "Intermediate Certificate 4 PL.01.09.crt" +crl = "Intermediate CRL 1 PL.01.09.crl" +crl = "Intermediate CRL 2 PL.01.09.crl" +crl = "Intermediate CRL 3 PL.01.09.crl" +crl = "Intermediate CRL 4 PL.01.09.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test63 +dir = test63 +revokePolicy = crl +cert = "End Certificate PL.01.10.crt" +cert = "Intermediate Certificate 1 PL.01.10.crt" +cert = "Intermediate Certificate 2 PL.01.10.crt" +cert = "Intermediate Certificate 3 PL.01.10.crt" +cert = "Intermediate Certificate 4 PL.01.10.crt" +crl = "Intermediate CRL 1 PL.01.10.crl" +crl = "Intermediate CRL 2 PL.01.10.crl" +crl = "Intermediate CRL 3 PL.01.10.crl" +crl = "Intermediate CRL 4 PL.01.10.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +leafCertIsCA = true +end + +test = test64 +dir = test64 +revokePolicy = crl +cert = "End Certificate RL.02.01.crt" +cert = "Intermediate Certificate RL.02.01.crt" +crl = "Intermediate CRL RL.02.01.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_CRL_NOT_TRUSTED +end + +test = test65 +dir = test65 +revokePolicy = crl +cert = "End Certificate RL.03.01.crt" +cert = "Intermediate Certificate 1 RL.03.01.crt" +cert = "Intermediate Certificate 2 RL.03.01.crt" +crl = "Intermediate CRL RL.03.01.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_CRL_NOT_FOUND +end + +test = test66 +dir = test66 +revokePolicy = crl +cert = "End Certificate RL.03.02.crt" +cert = "Intermediate Certificate RL.03.02.crt" +crl = "Intermediate CRL RL.03.02.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_CRL_NOT_FOUND +end + +test = test67 +dir = test67 +revokePolicy = crl +cert = "End Certificate RL.03.03.crt" +cert = "Intermediate Certificate RL.03.03.crt" +crl = "Intermediate CRL 1 RL.03.03.crl" +crl = "Intermediate CRL 2 RL.03.03.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test68 +dir = test68 +revokePolicy = crl +cert = "End Certificate RL.05.01.crt" +cert = "Intermediate Certificate 1 RL.05.01.crt" +cert = "Intermediate Certificate 2 RL.05.01.crt" +crl = "Intermediate CRL 1 RL.05.01.crl" +crl = "Intermediate CRL 2 RL.05.01.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 1:CSSMERR_APPLETP_UNKNOWN_CRL_EXTEN +end + +test = test69 +dir = test69 +revokePolicy = crl +cert = "End Certificate RL.05.02.crt" +cert = "Intermediate Certificate RL.05.02.crt" +crl = "Intermediate CRL RL.05.02.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_UNKNOWN_CRL_EXTEN +end + +test = test70 +dir = test70 +revokePolicy = crl +cert = "End Certificate RL.06.01.crt" +cert = "Intermediate Certificate 1 RL.06.01.crt" +cert = "Intermediate Certificate 2 RL.06.01.crt" +crl = "Intermediate CRL 1 RL.06.01.crl" +crl = "Intermediate CRL 2 RL.06.01.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 1:CSSMERR_APPLETP_UNKNOWN_CRL_EXTEN +end + +test = test71 +dir = test71 +revokePolicy = crl +cert = "End Certificate RL.06.02.crt" +cert = "Intermediate Certificate RL.06.02.crt" +crl = "Intermediate CRL RL.06.02.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_UNKNOWN_CRL_EXTEN +end + +test = test72 +dir = test72 +revokePolicy = crl +cert = "End Certificate RL.07.01.crt" +cert = "Intermediate Certificate RL.07.01.crt" +crl = "Intermediate CRL RL.07.01.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +# FIXME should be CSSMERR_APPLETP_CRL_EXPIRED +error = CSSMERR_APPLETP_CRL_NOT_FOUND +end + +test = test73 +dir = test73 +revokePolicy = crl +cert = "End Certificate RL.07.02.crt" +cert = "Intermediate Certificate RL.07.02.crt" +crl = "Intermediate CRL RL.07.02.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +# FIXME should be CSSMERR_APPLETP_CRL_EXPIRED +error = CSSMERR_APPLETP_CRL_NOT_FOUND +end + +test = test74 +dir = test74 +revokePolicy = crl +cert = "End Certificate RL.07.03.crt" +cert = "Intermediate Certificate RL.07.03.crt" +crl = "Intermediate CRL RL.07.03.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +end + +test = test75 +dir = test75 +revokePolicy = crl +cert = "End Certificate RL.08.01.crt" +cert = "Intermediate Certificate RL.08.01.crt" +crl = "Intermediate CRL RL.08.01.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_UNKNOWN_CRL_EXTEN +end + +test = test76 +dir = test76 +revokePolicy = crl +cert = "End Certificate RL.09.01.crt" +cert = "Intermediate Certificate RL.09.01.crt" +crl = "Intermediate CRL RL.09.01.crl" +crl = "Trust Anchor CRL CP.01.01.crl" +root = "Trust Anchor CP.01.01.crt" +error = CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_IDP_FAIL +end + diff --git a/SecurityTests/clxutils/certcrl/testSubjects/anchorAndDb/amazon_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/anchorAndDb/amazon_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..3439c8215e0c9d7296db295c8c85583d76bdc054 GIT binary patch literal 945 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 UIQMkd+^sKu{L;^X5o1vJf7UU*r~m)} literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/anchorAndDb/dbWithRoot.db b/SecurityTests/clxutils/certcrl/testSubjects/anchorAndDb/dbWithRoot.db new file mode 100644 index 0000000000000000000000000000000000000000..888a8b2f21e965a03c9ee85e662ead316d80f19d GIT binary patch literal 23736 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/anchorAndDb/root_1.cer b/SecurityTests/clxutils/certcrl/testSubjects/anchorAndDb/root_1.cer new file mode 100644 index 0000000000000000000000000000000000000000..b76137b1ca59e37a3febb8a4a766b20e83587d96 GIT binary patch literal 568 zcmXqLVlpvkVqC~1z_d24&d>E0H&pbJ3joReFS?(y`l?zIzg)lAHc z42;N514ajP9YgBfx`&(IYm&zE_vGHrM<5I)#;OIT_FL!{W#5OYx=gXRH4_?Q5v{6951o(Z^c= literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/bmpSslHost/bmpSslHost.scr b/SecurityTests/clxutils/certcrl/testSubjects/bmpSslHost/bmpSslHost.scr new file mode 100644 index 00000000..8fcf6fa7 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/bmpSslHost/bmpSslHost.scr @@ -0,0 +1,19 @@ +# +# test an SSL server certs with UNICODE-encoded commonName. +# certs obtained from https://stone.tees.ac.uk +# +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = true +end +test = stone. +cert = stone.tees_v3.100.cer +cert = stone.tees_v3.101.cer +cert = stone.tees_v3.102.cer +verifyTime = 20061201000000 +# common name has wildcard *.tees.ac.uk +sslHost = stone.tees.ac.uk +end + diff --git a/SecurityTests/clxutils/certcrl/testSubjects/bmpSslHost/loopStone.scr b/SecurityTests/clxutils/certcrl/testSubjects/bmpSslHost/loopStone.scr new file mode 100644 index 00000000..8ff25b8c --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/bmpSslHost/loopStone.scr @@ -0,0 +1,63 @@ +# test an SSL server certs with UNICODE-encoded commonName +# this version does the test a bunch of times, for use with certcrl's -P option +# and MallocDebug. +# +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = true +end + +test = stone +cert = stone.tees_v3.100.cer +cert = stone.tees_v3.101.cer +cert = stone.tees_v3.102.cer +# common name has wildcard *.tees.ac.uk +sslHost = foo.tees.ac.uk +end + +test = stone +cert = stone.tees_v3.100.cer +cert = stone.tees_v3.101.cer +cert = stone.tees_v3.102.cer +sslHost = foo.tees.ac.uk +end + +test = stone +cert = stone.tees_v3.100.cer +cert = stone.tees_v3.101.cer +cert = stone.tees_v3.102.cer +sslHost = foo.tees.ac.uk +end + +test = stone +cert = stone.tees_v3.100.cer +cert = stone.tees_v3.101.cer +cert = stone.tees_v3.102.cer +sslHost = foo.tees.ac.uk +end + +test = stone +cert = stone.tees_v3.100.cer +cert = stone.tees_v3.101.cer +cert = stone.tees_v3.102.cer +sslHost = foo.tees.ac.uk +end + +test = stone +cert = stone.tees_v3.100.cer +cert = stone.tees_v3.101.cer +cert = stone.tees_v3.102.cer +sslHost = foo.tees.ac.uk +end + +test = stone +cert = stone.tees_v3.100.cer +cert = stone.tees_v3.101.cer +cert = stone.tees_v3.102.cer +sslHost = foo.tees.ac.uk +end + + + diff --git a/SecurityTests/clxutils/certcrl/testSubjects/bmpSslHost/stone.tees_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/bmpSslHost/stone.tees_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..3dc890606008ba5268943ad713308cc3b4bdfbee GIT binary patch literal 894 zcmXqLVy-f1VoF-T%*4pV#LdV60)OvHCphbRPB7MG;v7Q+O4f zL^wd{{pP)Yrd@pbZP|M6E``P}AM0L5cad+sbz5rtZ#1uF`n4;ViJ6gsadBg#LA`+> z8)rhB2V>h0Cq_mV7G@?k2LnE!hh_O08UKU$EFZuTB&*CKVIbBZ;<0{CHjb{ z)dR{R2N5tmF*h+XGPFszd=YZ&Kk#E={i)B7@A_QKWb6g!mo7?nYCH{lvCQe`!M{Ja zUQO5EzW%!G)bkSs(x%0)K73_CaDGib3(MqtHc219J5E_SHTcp+wf??13zK7#@n0q> z9(8QzYzZ+|*<-L<{&9qRPikO7py}p6U4P|EO+45??B6m!Ym@%JjC!5SD;*4WH|kb% cJ4j}(`!WCJD%YLwbBpSo_kY*if7Y870PN;H*Z=?k literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/bmpSslHost/stone.tees_v3.101.cer b/SecurityTests/clxutils/certcrl/testSubjects/bmpSslHost/stone.tees_v3.101.cer new file mode 100644 index 0000000000000000000000000000000000000000..00a2112f0fa91d47a95bf689f6b6024738b5551b GIT binary patch literal 1051 zcmXqLVi7lJV*0;;nTe5!iJOH11b*4R`}o~}myJ`a&7D}zC$A-4f18*?ZN zn=q4;tD&TUIEcd~Ea0A#pOlyroSB}dkXNQ#oM@DF%e>}VF>&ZixSU8pb zY)Ji|^X;1E^kh|zw-c^){pn=iyXG~sSaQ{?#Xp+bNXPY zBI2=o#s27)OW__*5?@YKn0P~0^?tp9B}iJH#RwR~dJA+GXtil%l#~=$>FXyK<>;k@ zlUy+{$?4^#mgpA%lUXr1ZRr7J4FuUZ6WTl&+kQAPGC~~yN|3V3ED{D{4I&rQn!k3& zUD#Kjcl!$Scz=PBauS-~&l<3$q91=a(orI~qzGNPGw-d9<^nTTROMwtmLDIV!BIoT@*e_$$zg+IJ@k)=*rby zi%zEH+!a`SV|KabyJZe%^-av`7mKrUpN?3nw5-PTS#RvZ;6t;H-irNqgRj( z-Ay*!6YjA7-Sm_zR4#U2((n4mJEnb^ueN4UOv}xtT@PM-otnqOH7&(+G5@^gmC4Uf zD$dMaAU09;gviakciz~P2fK$kx71xre)?Ery^a5Y+AR{_uI~%y?!0~NVDqF&kLMU% zjPzMrI3d1`z2Jr46p@pk{1!JHiV|G;;>DvqOmp^I_*UJr2~2*s=SNLo-GUttJXWq> z%f!scz__?^ra|L0aGcBXGcx{XVF9KkHUoZOILiuy_^bxZK*~TCB*4ca#v*btt@&$b z+=YGhiI?uKIQ2`r%B$Ycz!)Sg&jO4f1C0f03sl;aGD=Dctn~Ghi*oeR!D*}*n8x(- zQcLtfNkNF`=-sz`01N3WI&YGcHdK$io3J-EfhImd8Q&m<>$ict`-)afbgXX z%ulzT?bvo}^MaKtj=YndyMSq3ZMYtD>i>!R-B>mA*B2l9veax&KL2iO)wf>*8K-Ga znI-e})xB#Gsi}tDNt2;aW MouSR|oOSRu0C~iO(f|Me literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/amazon_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/amazon_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..b62626c195503689b57319f83763e4c1148e34d4 GIT binary patch literal 1274 zcmXqLV)V=Ai&BA95m2v!v!jBpg1eD{ zoH(zcfq}W9sR0;70lCINu8EPcsimo9ltDVGw}cG@LFRJ^bA=}sXJqE3m*nRe3K;N# z1ldK{gHsbrN^(*SB@DzsB3vT;j=70d`CwN&)Q1zd?Q>Lvj&6W;G(9^42 zQ=_-I@m{a_&v$wLO~;=Iv4pM<&z#cpUN4|3H<&*6XQjLCdRYi zSe6xLVKQJa;0F3qmY;=%nTd6Qfh&k3&thj_V_>zwVu4wk2`IvV@f92v1POdycO%{8 zq8!x7gUh-b=>a7TTtLPsu-F=a5(0NZn+Idt4_8KZab^Q80}VC~Z8l(fV`pL%lfjo9 zz==#&l|{@z1g3?V5zb;VkOx_!%mR$329c%jxdqQ1aAaQWl{&#=lgxu~-CB2pGMHjU zMwTpt3dKt_^n6r1%Zfo_hI$~QP_r>}6C)$T3emq`cSUu~_;YVYK( zD1W8mn(w@AZ^X|^Y@heD`RPl`uKv3=iPsOj{#a!4#NYn8vBOHw`7RrJ_Zx34o4Pna zvA>^3E}dG)u6`!^e#(ofsoLM>3HrtJNivo#G%#Ze z`pEg<{FOp6-iBR5YV#(0%fvVP=v>IOK04Fzh)=)zKF?We6z#lXA4*)dbV*_nyLINq tTicFH%O0=Ge=WTJV{Y9gCJ$2^{aFjX?g@Rhq`K=~5_j>O2uB&6KmdRaqpbh{ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/amazon_v3.101.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/amazon_v3.101.cer new file mode 100644 index 0000000000000000000000000000000000000000..039c7cee794c5357472bf58c309238fde1b756cd GIT binary patch literal 1584 zcmXqLV$(5bVx78xnTe5!Ng&Vv*XEk4do4FA$rANS`U!R&ZYAjdi6Ibu5xWUa(;_Qy}PJ_M$?82p#$q;*sp(!JaalJEXLRKzgoxY zkU%SauUmXG9(5M&{PR7-=7_vy)oJm@&pd1S?<6Kk3vjc@X-X8vC7pJ@x6g1_A(Nz^ z+RDINJt>*Y_vZYq{ac;5=TA#bN6ePP)o|cXfl=sVgh07u5bVsM`PIu4JIL!mfYI&oA`bkp8t{m3FhTpCT2zk z#>GucD-D{MmKvC_acHvv(=P71eLU;+WU9cZIGi>`sTf#w4B1*&bzPzNU$<)FA%zaTl$SU25B4=7>42hzn4 zaytt!v$GlG!fa&ZVM#QIUl_X}+91*(+#pnp6PQKQQ}xp`(+m_1nWR`m z`k!8wYFpFWmwotrL)H}!37u+5Jp)xSnDsgN>G`PkmlcD>KqhH|tQTZaGEi6|XCPxJ zWgr0*048riaH=+Tb~G|DvCuWtH8lcfU|BvEF&2@f@3{rf9dKk`?3FsfW0TB-aNSyW zgU06|qm)@1?;AAUS=e}dN#l{>P%t$K)ZYBZetw1Ac7e+D-^)8qjv;4fVCl=;*vODv zqHi0#N`LwrHNiBge;@BTs!Lv~zj09J=Oc?SEBOiQERQObuKtmun=Y?;Nb$NzN3!>Z z+3Lv?e|%WXsIu*M|6^Mw?);E{SI*qN*1ErDs$5)>;K7@mbDVZ=y0S`lhLv){nMJcc i=Dj%IcTvhFPV(sW*`^zqlvSRx?zr0V_`$E8U*Z9tfd`oY literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/apple_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/apple_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..9fec8a21cbed06e88bc03e781a609afaa5955e5c GIT binary patch literal 1746 zcmaJ>Yfuws6wPinfrLkdgrEYlzGy&5z6}J3f-M0o6bfo2(m*L8E@5TejY$BlIMvwV z1GUvM;3&3OtB#dAeV~X)p-`x{$iv6bDWg@;`oPu)qf(35T@c5}O!wE`bMHOhz31Dr zz|QXgcHZ$SE)2o&B(I!-%#C+O+M^%6ej*?H@hWiR3xY}#N*=pG5RbwmypfPl|U zL-=AiO^bO0FE$X0-F3Ky&=Mvp7)_*%a?Bt2u?ZKkbUcABu@qQsXbNsCqAmH@JfI#c zP%gnOE37D;ixyaM)L=vNY&NrXu0l~%R3tBCSgj1J+(@rbSj+}gW()-3SR@E%o4I1e z3-(yjV6~#5X#6T0PA$Wip*jOeEHl^$nnJbOWK{cREE*dFrg^(z0E8>U!04lALM0Q1 zDnnIjm0Az%kUu5{9(CA|b{UmimJ^7101=zyiJfBsGq_5vbkxutxUzW<2~Vv8SlHXlc*p&o>Ahz5^GBZ&duml~; zq*5e7;i%R|TW~a&%63uw|vw(OUt{oC_7+eV3A&9fP zu%%>sK=m0-)3wyrgcvw$$BeuB(mQ`|y~Vo^|NFCVd*G=S(kV5vZfbe>?xk_F@8xwr zet6lbFDg5fR~YxM=0N4(RsC0usaYouS4)2xPASW4sBGIZ>+T`=J<$`d+ZR4va4x&` zSJ!~b8%W&eQ3q2h1~we_6g90Mgqt3kzAa0%`jF4gqY~98!5Y8TwPD%2(uO*#Uc1?< zY5T1|S~XY`dMsnHF7X@Lt@}TPbBkIo2#JcGkk07L0YUKs%aPj4;5@GEX_3gf$~GSd zN4Q}w3)jRq_b2tPUKme(c~Y$iyE)%y{=RG5d!MFfw54AB(7N=}#_HX3m952lFSIWT zo(FRw4z%A6=KwpL1xQA7KMw>4M!T3Q$`5%(O}p4wV4eVa;--lhWt@ObxEt1*eqsa$ zoKgSzxg%0U0t>an55U`gl_U2X()$n9HEmlv7r3yMA_U>WyecrC4g8S^paP*)Se2qA zgf$`K!FXLFWg|n37Shp*W4MxWlAOtbIJO@}q5&Qdx4o*5rP9K%N|JKxb~WPDLiRIe)U7^WX=d87N* znJ0=r7*I6ycU`%@EANrg^vp!Ir&XYp&&Vr|tVQ;`gK+*~wn-kH2q8$PMYc709i{m}Da2=4d=jZo z+caG5TeEeuVQ=lC{90XEbK}l4%MW@C^!Qv!Zz`u3pY5y999eU^wqvN-xhkr7b&4$c iJN1^yP1{BqyKK?2-W$zoSy)@Rd-T&7j!<|M()|b5dP%+j literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/apple_v3.101.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/apple_v3.101.cer new file mode 100644 index 0000000000000000000000000000000000000000..78e8174fd34066eeb7414c3a8d85f441d9648982 GIT binary patch literal 1570 zcmXqLVv{pyVr5&v%*4pVB%tGQcQWtS$iAO8GefEp-Z~rbvTc;+SR8Oj^Tf+VMECvRlUUGh}eo;Z90x)EN4zw^ZgZNe-!?&&# zC8>ESz@Q0B%*jlFcrrNHMpy1v}#`z2_Oq z#J8{0TD3xZk+ijda=h@yyBs}!BDb0wA8+k>obgsA{ao0#HM5JSx!msR*?jFo;pD#C zg&|(AizBo83j%eR=TEy)P*eCd6#Gax(9F~6;l&x6t(mSui_VH#z)t+Ka4?d$xwzsyGuc90pBHEZ_ty%f}+dBI4(KLbmL^d2p5gr-=M1pDi9;-Fx3a2p9>n z!inupo9S*$aa2^i&%iUm(4(s zjWeOmgR$+06C)#3C>Q1yMjn<#gZPE93!)7o4Z;mV#W;Z(Bt2C>Ju}Tf(LmmSosCtS zkC{n|MWp}fWvR9`y?xn-&o^XU@sQA|meey)6;p;fEhj%cAJs`^#b7azNtz%R39={| zC@hgPkTH}pkN^q*^Qj;>dm1}C8X1^a=o;#pSQyBIlq$1G7>G59)L%|re(3I--5(4% zKRa9gVp?x(XbcP-XfOgjV`!jnpbO(0Ft#b8hf{uXaRG{}3`{`gtFq`CXv0H=g^`U5 z5pIm=P={X&tE*3Vh)A8Nmi_aMYrfgSOPs}pY12vrP4>?;2uzPz(}`=4x3KDeniI!X1qoxl|Uz?lz3 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/cduniverse_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/cduniverse_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..7f4673521e12b4c34ec0d21b8040b3a4f0ce1bf4 GIT binary patch literal 1344 zcmXqLVzn`7Vo_PZ%*4pVB%pn`;CCnF=T9g@_nVzSk;F*`KXDDwV3zFa#7K2GBgcOw) zmnit9mXzlgWgA)>SV9ySg`^hc7AxeZDU=qcDkPRDWR#Q?6kF-*mzS68l>tpH2AZmu zoS&;-RFJ5kk*sN8YN%zP0n*GYtOz&VIVZ8WSix8!I5oMnC>2N*0re_4I~vG|^BR~L z8XB1!fI*Zvuc3i~p@FH9v8ko0WfX>&L=1#LW^)L0JLl)+r6!kTCYP2NLPgm{xWf~3 zax(MM)AEZ_V4_?i+|Divp?R4=D~nSNc@4P1UK3&Qb2KnCG&V4VaJA5VipPi229jVO ziU@%eC8v}^4F?5;LF0VncwuB^U~cRM#!V+vVG=J2|70Q!bGo4KG918x_BgCGPcZKc9wSr z%LgakbI(>xI{KZ7nUR5UaTDVugC@pv;G`le%)(^A01gvbeijyHCe{T8Emu(=0m^qnHf7Bn3{WvZ^d%1|l#m%#3grlYu> zD9RDx0`j~rNIE&S$RHPH2qOxzejPPL?-fvT7?)CoEH>G`NOmlcD>KqjFU2Fy*2 zj0`!e-vmspW=cJ|D|0%RR7v*RSBEOZHos6v*LUguA9 z8x&7g1~^UGTDvvCY?+kIq@Lha%Qu}pDe$7l?@v|d+>+PaTe;K28ZTdavH8ZW&pcnV zPUXL3ays*Jk>fh$OH;2YGwiv$(f>T-!c5EgJ@xOGONFXQd^eD@Sr%Cn{BBLy$_*yY zMiUNBeE#&zqJ_5SFLG;cXng9`BY#$H;|}Xz*E*gtN!%^|m+E5sNpK76Ip-u67b_Sm z1e7M_WF{*F6lLZn7F8-ZrxulDre!84mSpDVDL9svWaJlRmQ)(ZiSrtm8W zj4z8zn{u;QCqhzb$H_lcmJ_tfi)v);zTXIayx!?_y8+Xk=rsk;cDQWOHhn$$k~nMK zX}4=J!3&H6=a!^I{N$O%@G8#5Go|RuS%F8bTt7|TZSF{0xpYa?1-=>e5xm+#yW3XQ z>HXT|QPX={H=eO{Q7@Zy_m)KVllzor{*b=7H9U>Q*YwN8!f9J)a;VOpe!}Xr!p6Jv zX7G3=Z(nw91LL_Lle0eaj6a# z_&{3tL5^Vo<_|UlK{if^?M{r0P$5l_5d#AN85K^Mn+av27|_phTI06Y|No7Y{E>T z!G>Z6A|MWzFt2M~Nl|HWiH?G2Ub3E{rGYs}oLktSyu4g56(XmXms+A4l`}Ga1il9%xY8 zdF}RtRIMWKMR7cpPR`*98|wDl()lX)xZ>z#=q6Fdovkm7^uOtGck%u zLA7H^#Rl>q6O>sb48$5l;5PvcfD(1`NpY2h3&6O^l2T38w`jl{0g;{7~L(yZGf~+9+BKv5S9)n#`c~DuC-*zbtb4bwwBu2M*P;89wp10@txzcWAbUdX z%AAdLKPnUYSa-=OnBAM8cdx&ypjz#%;KS(9gK}JEBF>$=?6u70nwhq{Cf?Hx(tcFt z6PhL;7L>m9*pBI6(pK=!dYFIV(GtP;J49buDLlNiL9FV*i}*jzEBZJVJXcffJUyRd zO}~)Hji)MGzG!?C>{!R!_xD&v_X6YaQdOIe9+#Yc%z12+|62A)2-jg9&Pl%y9BAXw uSlwB8Y%P1q9);%Bm4N}dIgg&I{_AgDcXZ378Oz_4FW$Li4(Gc+W`6+%=#dcs literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/entrust_v3.101.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/entrust_v3.101.cer new file mode 100644 index 0000000000000000000000000000000000000000..5d16f8d329d31f0969cadc909b4f868a42c5135e GIT binary patch literal 1270 zcmXqLV)XDOu`!3Ta0zp} z=9Ltc7MJMdrIr{v7}$YCxkb#&%ggmr5iG&V2Yn15S{+Y{E>T!G>Z6A|MWzFfY^+9R<(4WIaPm19ONQ4bXjARFJ5USq$}Keo-RO zsZfum7NzDTry9x|$U?M=fxKsAU;y_X)NDNi9gqTMVO6M|3b;I_tKehkY|zB0gd97J ztPIRejQk8haW1ANMn;C|i*;@0-DABad`Pf&Zr|hjjV= z*>H*f8s`o?<71l`pxJ!!(_yXKH*Wi}oMCv~y=~f^J*$2Nm9reYE%{{KoWC~R%*M9Tgh4N)OvIH8IWEc`&uSOvPu$_gq7Z-?#tWHfJhZC^3E6 znR^PHo@OeUPT!uGCw+{}U1{^yWX|Hg+jp$4f9J}7uXp3>(*7?^%Lrv+W@KPo+{DNY3=wt%K493&@-s62XJG-R zZZ-pc5MLO?XEk63QU=Cs9NKKaG|tY*$f9llN{mpx0b`qZMoCG5mA-y{a&ZB2+BPr( znIg}kZJ=qOzCd+>a+@MlWpYstvO;}OGE7d?0}2~hgY+n{m;lqF0UHaD$zY&ipa!#z ziBU`nY6g}h22Mk=d@N!tB61&Bce4HPsIqJV+vX3Ni~d*WmB+X$ r-gIFw{JhV||0|af@1H-r#LB`pUGtdqse75-_BAn?uej~gTz3Kh(9g@> literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/firstamlink_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/firstamlink_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..f0d60b2b99d0e9565de5bdd976dcd50f4a8fa70c GIT binary patch literal 1647 zcmaJ>drVVT96t9!g;tb$S#k2ZPQfW_doIWn9dWfxX&l3Vu)zqUz1-HTw~yUhMCKG* zTpgK=;kGP`54woLmP}y=5_|-SIu|oXvhjz`DN*7w%sO>GFgoJS0ZV{Anw)db_x--# z>)c;2^s6>Pe?(!BA_C28N>vA|e7nJEwtB zDyoQ9F=SC8_Y7n(P&3nWM2Bb=WG`!R@!Yd84$~SYrnD=DG8uTclS_f~u!&+4 z#yxUH$9mSJC{?o6#S5(2q|bm!anT%v9G4D9f29bf!%QwSJtH$KGpiK(-kV&A7S6l4NxVTmqbfZEA*DCCZAIH8}-YZQG7`wD)`4m(0I@CFfA`h- z2dR$E+P$lL&gxX}LQmEG=7!@H*|A&V_wByW{{E1ApzAm1w${zE$rX&)~N@ zeoX#_zl@NGChj3E)2z258fEHfJ2yyBTOGSD)vA_Lh^Ra586 zXg1;LQ;gxM!b3GaQ+T8dyzGTDa1%2L;t5StWJC~7$C$yGga8T{CDY}w489Ot6ns9A z`ZOCaOBs`DGV<08eLCb|B?>G3Q@!~A)PCYyoQS3U#7XEUy3y)XX(|G_L|{ZBC_o^h z1uhGBO%gi8e|4=WlAiY{dRg$e718UKYmn55{42-3NrZ}%{6qmT0T-wNET{qs5YW>N z>}dCb^*}@n3(Sa>5f%|I0v=e=8S8kYbRh+{c#$_|vEGU-JUV+2V?_#lo){IQ9OUCb zD;yhVSqqG#d*Nsd7pO!}Tm{w_pj|>$iYT4~;k76-t_jy|LX3>;0&t?`LM#iaN2}-2 z<e%S#XVGXDhHFgxN8FTqDkfBjQ{*2kuQq9pHVeU#!5jU=3EVC<@MwvHdAO)~jLc zFOx#+U~KrhDPsIYPW&>UZzts^2vFMD)SF$*-ZFR%y#sgF!DVSu(woET!lI?7Yi}&I zUHjgCauX=yY$LyoT8)Cp_sI3=PGrk2S_T>ia5SGpEP(Y_DyC&E*?@+V)x3!DGUn cKF8c6&8hp(B&+zxj>TtgeW6=XB8}Yr8z^-3u>b%7 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/keybank_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/keybank_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..e97842ac173383def835942c5e9f55dac4673a21 GIT binary patch literal 1278 zcmXqLV)d#AN85K^Mn+av27|_} zhTI06Y|No7Y{E>T!G_`nq96{JFke_|QD$&vdY+DgXI`?Np}c`CNP=5f3?`uvQdC-8 zqTrWWQl4LwZD?&^2~l7al3J8otdO6kP+FX-kXWLSQBqP+Y^ASXUS6(O1~j!8XsTXv zey)B|L85|2vZjHhp}v7GNHepr8r*c}oW$Z{1!INa)a25lR3KFZ)T`j^sGzIhZe$=Q z&TD93Xk=sn0Z~A%A&_fqWNd0_Y8hpagX%3_18$J{9KtOA8JYQpLIwgLF1rY)b53em zYEEKailLwZKS+#Agu^?vQo$)PFWZpEfD0tVEyC;^>})7$AP(X&iwGnpC+C;ul@#k` zr&fYIV$e7rIb0c88JHV;fnnRp)Y!O;1f$=ihin1#uJ0URQ-{46ZYOsoqGT!CJbm1nUturaV&V6nig z%>)!{z(@-Y3xdReuDg+La#0Ry48mpIjr4$$1}-3D6j*ExK&gQ{q0NJ_?T0HPyEwCf zmVpKvhc+89(Xlfzipk(h6X294tI8r~AOh3E%m`;O8OVbyQD%`a5Ni-w`kq_x+yO`C z#a^isJT}QZ2-mH3Hz`kBxa}wG72>>GdD3ZGL$fR z)auQ9c=e})(d)M}*PmO&rdzvqmCwc94>r53oOpZ6|6AJ~YB*o+oOW-XD;^dxwgX8xR<~Ej^e#`{`I~kk&E*bP0Tj`oyU6o4y#eYOqq{ae|AkYVNN}ga_fBQ zuWKyV9yu4yEBY{5Vc*pi^QN|G9_nma&p3C(MW)xkKCRKd%NBn7koxYWOVl!xvd$!n zzvAXC>xp<6<(^%FV_kYSFHE6S?r2eMgLxjM7ZCx4ONN^LXfC zeLQ(%^o_=kMyl#Z#op%@vDR)i+*se6ww+i0PI;+pi}3w|DQgcl@Xy|B8u(z{gPE7# N9Wa?PvFy_E?*Lmur;Pvr literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/keybank_v3.101.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/keybank_v3.101.cer new file mode 100644 index 0000000000000000000000000000000000000000..039c7cee794c5357472bf58c309238fde1b756cd GIT binary patch literal 1584 zcmXqLV$(5bVx78xnTe5!Ng&Vv*XEk4do4FA$rANS`U!R&ZYAjdi6Ibu5xWUa(;_Qy}PJ_M$?82p#$q;*sp(!JaalJEXLRKzgoxY zkU%SauUmXG9(5M&{PR7-=7_vy)oJm@&pd1S?<6Kk3vjc@X-X8vC7pJ@x6g1_A(Nz^ z+RDINJt>*Y_vZYq{ac;5=TA#bN6ePP)o|cXfl=sVgh07u5bVsM`PIu4JIL!mfYI&oA`bkp8t{m3FhTpCT2zk z#>GucD-D{MmKvC_acHvv(=P71eLU;+WU9cZIGi>`sTf#w4B1*&bzPzNU$<)FA%zaTl$SU25B4=7>42hzn4 zaytt!v$GlG!fa&ZVM#QIUl_X}+91*(+#pnp6PQKQQ}xp`(+m_1nWR`m z`k!8wYFpFWmwotrL)H}!37u+5Jp)xSnDsgN>G`PkmlcD>KqhH|tQTZaGEi6|XCPxJ zWgr0*048riaH=+Tb~G|DvCuWtH8lcfU|BvEF&2@f@3{rf9dKk`?3FsfW0TB-aNSyW zgU06|qm)@1?;AAUS=e}dN#l{>P%t$K)ZYBZetw1Ac7e+D-^)8qjv;4fVCl=;*vODv zqHi0#N`LwrHNiBge;@BTs!Lv~zj09J=Oc?SEBOiQERQObuKtmun=Y?;Nb$NzN3!>Z z+3Lv?e|%WXsIu*M|6^Mw?);E{SI*qN*1ErDs$5)>;K7@mbDVZ=y0S`lhLv){nMJcc i=Dj%IcTvhFPV(sW*`^zqlvSRx?zr0V_`$E8U*Z9tfd`oY literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/keybank_v3.102.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/keybank_v3.102.cer new file mode 100644 index 0000000000000000000000000000000000000000..642b24a6ea071acc21607ae6211338962062ccfb GIT binary patch literal 774 zcmXqLVrDXEV#;O`sJ;1*{rn2K?E;nQzn6EK95di$xRnxarzoT`wYms4pdZy*cND+be|5K>fHT%zEYT2h{0lx-j< z&TDC5U}|V#00vRwyhauV76yh!#-^60mQlmPkB#$@V~&xPfw{347<-*ejg1Uv;w}ot z#$;YteR*e=&rJEq83uh~tqN|r?)Fz&6bDMk@49(;j>dR6MxK>mFe`4NoQhaWMD*g9x!1s1Kkzqdv;&U=^2u9L^m;7 zR_OWirxz5=JSGq|Wl6AaNUrvJ-dKn3l*`xO-3v>c6u<0&m*J8)R@J%8;|tTpRn=A`$9B8M&46fU30ng67aZS$_kaJ5Q? VZ$Ee!85?L^SrxHh?%d3Ye*uNI2VwvK literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/netfile.state.co_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/netfile.state.co_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..514939bca72459f54dbd5342772e661c316095ab GIT binary patch literal 1462 zcmXqLV%=oW#4>9EGZP~dlYmuRx)F=}*D0zt&+cu%ZU4}KmyJ`a&7D}zDf z9z$*ePB!LH7B*p~&|pJx15pr%OPDV#wJ0+ZAHEh*10$~Lq%u!JZu3P~->Emp`+Qz$J?RY)vR$S5f(D7MnqFE20GD+8KZ3^Y|Q zIX_pws31{6BU#hXz|hRV1f-c+SQl=(b53G$v4Szs_L9`1yu^~s{Jg{*h2Yd8pb-kr zjtaU8?#2dk;=DlJMur9u5C!C#0Qm++#-^60mQe2A?vk!rDi>enXUKqzWv_Dm))0-uZUdB@H5#Z23H>|iutzrewscrz2|UqtvWZ)f!ntZuK2WQ;)mk4AfeQKTYi=Y zI?ODaFsWUkeoDQr~Q@zO)BK!LK+yF-Xk~x!3>mN2;TX|cX(>8y{JMNq- zf4;FXB5PURYOUg!)^qOj&bLSOoZRMCn;ji?G3#b46Q9QB&Cg`pZ#Rm&dSB4X zx2`^!Q_(H4?aGJVl}yZx42+AL7&ik$WIZ_j$_leE888@d14C4npM`~)iFJX23y7n@ zVru|Oo7@R)9*k{2Tp8KLnGLiIG}t(_*??JqorzIQ244y_a0Hnm&thd@VPLkvWPwqe z0Z2J8JqL#c0TXAAuDh{ra#0Ry(uT^p8|wk3fR+J`P-RgxkcZjI%m`;Ov2jA2=ETBi zPy`cZWMoM*NHI`>@eLT;B%t=@Cl?o>*k)h@SH*Vb?xErNgvn~@>n=8k98^VX!z67$-BZO?Vv z8_yOji{Df%Gkr&$MB=4mlN6QKx$o;XU1E8)@b=oD4&QDV&a!>8*?3jt{p~v^C3><& zu2d?xq?s%K@z=ukv##l?!jt|7Z2Nj`(mwl_3rsuCh{%=59~BP0%k=a$V|c|4nVBDd z{M?bP*`ob7d27uV&4bfZ?rwd(>0et$!34{29vh=OoL}th_e3B(**LY@JlekVGBUEVG8ivxDx#B112j020G3fpO$BuU&+&`jm?D5)4d3AvqJ9aBfKd9m2$p32PilFnp ze$w5$w;n0Gc_xhQ-R4jQt$U)qg{MPKDRxLt?9*!53Sh8JCk-i$j*pStPqJsM(6$ z?T9r~nBx9Vf&Lek&9r>EZmE6e>^Zgnd=uDJ6~6Djp4qJ3G}+nwX0xMoHuq|;v=)D_ zzI$~hGy5{Gow8(`?X!87hp({PmIy_bBfl5;uF>;O5_6vK;iU#rq>};&se9TNzEF%3+FH5zp z>Fvute7+&;iid#= z#t8`mCl*FFE?8)AFamW!gMyKfMZ-YNKn2D(U~H3sTAQC-T!3ON#4dS|T?U#9)EB6> z!CaVJl!KyDzaTl$SU25N4=4c)cAyIdS%6+%B5NRRC}|)L6abb40KVY~|3hEA;FItjdBwI> zhx}{IZLYXgtc$J4zql)EkHG2(v!gvpqOJ+zijS^3ttej@dc&C|@LS$4k7uzy+g&c( zExCHlc-DO0XV?9vxlE19xwcp=m~V#jxg|Rer&Y1WBniBb7P?)lR~GR9{`G9>GhJs2 ze{FUMt1+%BpA!9*JNP$W{GN>8>$Tn)m{*ETR;~9H_#ggzf1b6m;=Rf{ZQ_x-&MDiM zrM17>GtEs>s;xW!`gTu-=-Z3;YtDN2{j%}8#b4(6oQli5BE5F|gz~H#k@=OY8GnU- h=u%93nws~w=JI{H*LC)66Mjo_UuI*Hu5g~Y0szx?6951J literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/netfile.state.co_v3.102.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/netfile.state.co_v3.102.cer new file mode 100644 index 0000000000000000000000000000000000000000..dc95f4e75c1ed7179d3fd1c466358a791072696e GIT binary patch literal 1236 zcmXqLV!2?@#A3OCnTe5!NkEn7#RG#xz4_Xm-&uWYe*87yW#iOp^Jx3d%gD&e%3u(0 z$Zf#M#vIDRCd?EXY$$FZ3gU1H^M$1rWd>)a=jkYT<|XSHnj4scB)En3oO2S3ixrF& z0!ou|GLsboiZXK(iz*eIQ;SM6(=wA2OEUBG6dX%SGV+TuODYZI#CZ+O3=It|48R~t zoY%+@$Tc@IHnlXhj526EMWhSl4P+rM5Q8~QA*86ZxJ1D(wWK`1DBIA=zyhMcP$OAW z!N|bCOaZ16;t2&^1-JYng+z$ks!~%FN{dq!^7C>k4P6bKL3){mZD3jyNb@JqYbbYI-<_I0Hm)+ewIBS`WcnG- zu{fnwRQ>D6wI>WaW0hWLty<=^x&Oz`(Cr(ydvE^NU&kK)=DqXnv?S5Q^9j65ZruCv z;BXR$ZHVw|&r^{ht!huT`=#f<{t!aTOFaF;#`1o`&L<2{?pke?{Li%Oi_N(QiKIu(%@36^iKK;*quXdgP(W&eB z=3cqzd?3B}u?R=qQ~UYFJB+!`$J(2;PwRRY{6bZfiJ6gsad8vlY+#5?H{b^bxvVfF z<9`-b17;v)U|u7XJggoV`h?K5$S(=S*mSKZ(sJ|^9@;7JS23gCG`wc z#gw5w%gImAM|DP7F<1;_k_p^8MiyX@7^uMb28?YIPy_OliwjT;Ft7s!fhr3q$3nf$ z%m`;O!CA~~oC$3njBP)hSQy#3AWTcAv&KAH*E_?QmE||@dtt>9x#f+k>G!Va|7qs~)*s6a@0G0BzH`yV T@K^G)yw~qK*(X$YZ0~;n-&vrF literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/one.scr b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/one.scr new file mode 100644 index 00000000..a115d007 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/one.scr @@ -0,0 +1,18 @@ +# +# CRL verfication of certs obtained from SSL sites +# +globals +certNetFetchEnable = false +crlNetFetchEnable = true +useSystemAnchors = true +# alternate these two on successful runs, flip either one for failure +allowUnverified = true +requireCrlIfPresent = false +end +echo "=================================" +test = "www.amazon.com" +revokePolicy = crl +cert = amazon_v3.100.cer +sslHost = www.amazon.com +requireCrlIfPresent = true +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/proteron_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/proteron_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..b39bb4f9f2046a117249b0e2d88a9956067a1605 GIT binary patch literal 842 zcmXqLVs)FR?K>|cBMU2oLE{laZUas>=1>+kVWucY zLs0`^5QjsUCp@*dB(*3{!8x%Y)lkSl03^&V%n9Nugyfg!8Oj<+gT%OmMM5$X%S%!f zob&UFOLIyx^U@WPlMOWt)IieQ!t&0kMJ1VOnaPPInfZAN!Kp=MnaQce3ND#tnZ-a6 zLrDX1kV< z!rb18dBusv3eK4&m4;#lA|O#NVcvkEd|+_o=jkZ;_&6guxxBnwuK+3sc1q)XsQTFGFs(5TkoxyWtgC9$?nSKcSA2=uH752>+|enHq4%*obhd@ zIn$r(*7uxGzk71( zgd84EsY$AfO{c7%Cip2V_f+WzwrdCP@;FV|H$CQ`df1{Fxt>3K&Tl*%?dpA+t?PWt q|DIWlA}TAzZ4>8D{cGDIFvEJHfj`U6EyoqLOZvV)n;dAJ@E8CaH4I$< literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/puretec_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/puretec_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..55867c92a1c8803ec48d6f608ec2c0f84d513e29 GIT binary patch literal 769 zcmXqLV)|>)#FVyxnTe5!iJ4U)&48DUQ>)FR?K>|cBP%O|fuA9_0Vf-CC<~h~Q)sZE zfB_$f!zIk_T3DKymRMn^YoHAh;TBebiYNr9CYKhaDmbSWm1L%6CMTApDma#wWaJlR zmQ)(ZiSrtm7#bLv8X6fJ8X83bxu!tc)X*5rH7G^0&&AbH!axjUI)^ZSP)2HIUQS|O zif%w!VosHzkbwY5hFzG`H$Sf=F)6XM$WX>W3gS9pLxs}36a_;C&%Bb)+qJ2 zUY=R9rE1P8=g%{(pGOB&>)-uXc}mqUX?Kdr>5rT?99uYrJ-;8hux`0(f#NgOe9aQ! zV^eGewrzKcR*<}Y{LhQK3sx}jNZn^*W@KPo+<4HSai4)88)rhB2V>h0Cq_mV7G@?k z2XKVQ@-s622k}`x7{~%WDa*$q#v*beckS=IXVKikE7*28t~{L*y?X0g11pfUJd3e` zp@IGa-38ihni(Y}1y=g{$wfJO>8bf8MWw|hddc~@Ac122VsK<8C+Y!t2J#@i$}GT0 zX%O*vmhn^j(x$1`-ESx>2>2V%m@xke#BNmAUmBDt&qXB}x8UuSfAD$u(&{+__HX?N`-V%oHTnTe5!NuVxyufYHM+BS=4M~d54$V(gWvT8uPey$-3&i+9GdWNzF(h#SL6sIPa7NzPX!i~sFEiq`Ej~pV5 ztPISJy$lA8olK3540mPQ&vn0dX3u;1`=GH~xR-C-$$NQsKYvSDIrq|)4yj7@Z$ICO z@IC+dzUrsq1e>OHKKuFVK0Q?AY+vG@^!P`Lr1=GtJsowi5i0I0RTP#SS{M}nkAG8p zZqx#MWM?`l5Tq29Nc>1a&r;edL@Ru_)o^%XyXgOw5c7jEfte z8#F#K-~oCJlJ(5 z$Pocdn#{l$a9yivyKwnK;|+Hf_k_Kd>r_u%+?YAR_RcqBSvFsue7w<+?PTs^raInh sg88`?-#(=U_x)X59=ow==k)uX@1|@oD!JD4Vcwyv7e4#e80?)30JF~)8vpm?<>a zP~1Qi#NiU=3rj7^49-l?(^2ruOV%?qH!uZBa0}}>=Oh*vD;O&TlqTh5CMyIKW#%Rp zRVp~A7L{bCWhN(L=zfI*ZvuOWzQWMph=X=)i| z;Dh9VC`Ut817(Nk>Sea^b5VB_3O?W{;QRpxX_-v&}Pk<6Dhxw z{}_3*PuZK_uuK0T%j5&be>jbmUvigd7an0gcIoUR{jZ$KXa9RFW!V4V`R9)9x<>bA zm_6fK%TRqJ#ml;-l=)M^q*}hDuZpWP%~}jgC;ZrdJf}mNZEDTQrz`H2F4U>YxPSGO zOnXFvBoi|u1LNYxe+G@e4TONMmlbAY{LjK+zy_q47#R$>L1O$YEWpTOGZ19sOlb39 zZ2RHF$OskE0LcroC>qEwku{Julr#{B1c3lB3d#~oQhgGWQge)T4NVOUK`P~0vdsFtF3>9hM+-=^feFYORTfdxL z0GWXi6S^k()xCvxFHMM_&wZ|JpKxIR-N%g2**XjD#`79T6kCrU@ ozNn@;!KVBy-#HJadPezRV0ej&6*#H0l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/verisign_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/verisign_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..149e878fd6cd13dc250c0a03ddf4793c399f8c61 GIT binary patch literal 1788 zcmaJ>Yfuwc6wYoo0SvE@5I~?Th{!X!%Oen>v^0PqNG-t>8Hc(io46XXn5Pdw2$D)8 zLd9XmS}@k4Qy)`xtV(^f9R|nJg4Pxsv}3V4R_ib*jusW$?t(Cc&UAn6cfNDZJ?A_3 zTwvpl0~=@9$%Y{q_ElWF_&oAZWO;orbXRvc(h9t|9ZWmu1;1KE^A zVhLfWFrt(OH5&;OH=%1yrb^>tiNtEPiY;_jBb`;OqADbYN*s+=#Q-Um2Bb_dTOgUq zF4y5kBbtQfY%~#iHK9h8xQTNTFARW`L@Aj3%4nEK!<59N z6j_R_4A`I;OaS;?UK|%fAX{n%46!FW4FUnPjj+Hyo6zA_+(2N#Ac(2PN8qQ##2_A} zOJQ0`5l63y!F+)?LvjReiOI6mv^1%!fZo89q4`3NEEyyxO`c6-cfmY4UB8Ah=t&$C z0U_h$CiGfHne`@|)T2t0uwoGaW$YfppyaevGzX{UT}Gn=XEO6FIoNXwZ=D`yq^%RYSs1@#|%6@jWa9C-*(I_^3739)@{1!x-nnJGJ%3w$R{kec)v1LN z{`Va7IM{NH>|u3vSDkg->H0B?W$)P-bMJ-kP~)!hfG=Zlk7qAOc+PXZui75QMpa85 zZORJSa)W}|5DPkBgKfYD*MK?)tz#%3sjCNdwYLALY4e1h9}IEOB^adV8EK()KG6kgb2rKE90Klt%{PDC4}mShu@0q-M$O( zn6iBkgbj0?Ad>-MNGeDHNlwfuu_rL=N^fh9GGA}fC8!KK*QK4ZCjuZ9(;UcV;!)&H z!0bP7wLK5AkLN&c0bCFZqPgz$)^Rv)FeD23zgK|vq_ZqU!a>+{2pgLDgSj44dEY@G z+JW|5fCK_jt*}UbIn*+ms@VMQSShvpN!srN7k&el={N{N)`7JkZW;r~9_HE`r7~8! zG)K4ax?%v&6#^%57vI+cO$k95fPOj@@d&}cut*<%=2 z=cZlm-uwvj_d8n=8|V0$9KLzF)4p<;yw=heG4c5sjeO*ez~e&4vo7A>4=VmV`C@;= zNB!=lgWkrvUg_IV&!(<#mWq3?xMd6p;)`z`%Hw_EKX{AlHDu|1PZd9!c{^%PV6b2U zM@~4}t?622$-?g*i#v|)cqMrDYxTf=_lXuujr0ct;@o@Xyzopx#|J*mE%K&InZXB_ z`jkCLxVgvKG3(%AB<`z4^|{@evLi|d=36nk@3TSDZ|lpxZ8uIY(>k8Zc3}Tx HJ+%J|DYQ_` literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/verisign_v3.101.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/verisign_v3.101.cer new file mode 100644 index 0000000000000000000000000000000000000000..78e8174fd34066eeb7414c3a8d85f441d9648982 GIT binary patch literal 1570 zcmXqLVv{pyVr5&v%*4pVB%tGQcQWtS$iAO8GefEp-Z~rbvTc;+SR8Oj^Tf+VMECvRlUUGh}eo;Z90x)EN4zw^ZgZNe-!?&&# zC8>ESz@Q0B%*jlFcrrNHMpy1v}#`z2_Oq z#J8{0TD3xZk+ijda=h@yyBs}!BDb0wA8+k>obgsA{ao0#HM5JSx!msR*?jFo;pD#C zg&|(AizBo83j%eR=TEy)P*eCd6#Gax(9F~6;l&x6t(mSui_VH#z)t+Ka4?d$xwzsyGuc90pBHEZ_ty%f}+dBI4(KLbmL^d2p5gr-=M1pDi9;-Fx3a2p9>n z!inupo9S*$aa2^i&%iUm(4(s zjWeOmgR$+06C)#3C>Q1yMjn<#gZPE93!)7o4Z;mV#W;Z(Bt2C>Ju}Tf(LmmSosCtS zkC{n|MWp}fWvR9`y?xn-&o^XU@sQA|meey)6;p;fEhj%cAJs`^#b7azNtz%R39={| zC@hgPkTH}pkN^q*^Qj;>dm1}C8X1^a=o;#pSQyBIlq$1G7>G59)L%|re(3I--5(4% zKRa9gVp?x(XbcP-XfOgjV`!jnpbO(0Ft#b8hf{uXaRG{}3`{`gtFq`CXv0H=g^`U5 z5pIm=P={X&tE*3Vh)A8Nmi_aMYrfgSOPs}pY12vrP4>?;2uzPz(}`=4x3KDeniI!X1qoxl|Uz?lz3 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/verisign_v3.102.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/verisign_v3.102.cer new file mode 100644 index 0000000000000000000000000000000000000000..bdef91b6b947e0576eb26cc7c15420003e5616aa GIT binary patch literal 1226 zcmXqLVmW5e#G=1|nTe5!Nx*cvVf*KHD|Vy0a}hkV>uwqFvT z0i{VfnaK(PMVYyYMU@K9sYNB3X_?81C7Jno3XY{E8Tmz-C6xwp;=BfChK2?f24D~+ z&TC`{fHT%zEYT2h{0lx=8bU;$BJsFAFx zU}RumrT|k3@q~h|f?Ix(LL$U%RjDZorNyZV`FS~&hOP$AAid1OHZUy;r1=wQw!5i8 z6QdGx05h^OFgG#sGXTZ8n3@HbnTf=c&k$R<)R9iv%hUFYmM`4!Ws&Nq^)i#vC7ym^V|hPe=M#n}cdfQc{%6|t#pd0E?$_qsZ@ye# z^Xc0M+x2%#CmKu2$~c@ZQIS-fd{gA#8m*w?{a0B$pY$fXci3b$pZ@2*SG&&t=+t$5 zbFW-`7=i@kS+oo^4Ad5=EKq7w$S5f(u+rC0F3Qm>1188~V1m?3&d=2^NKQ1? z1Bx2(fwb_0%wPc~cs2uD5MP1C%)rFJh>ZovWH104$Ht+}22AekOpIbOAR~)`W|o(i zqnepqPz+9DvV1IJEF$%nQhz}go<$j^G#51((yy5b?BQ!S}ypem*e4Ue4s^n6sumlcD>Kqi^M ztz%>X2Bd)sjBmi$CIK}dKe@O7#Q@}F3oI9y8ygw;Ro8jEl{Rkm;n{lV`aj=m%^E(A zsR<0+oV^W%j7SoS;ciZ Nb#;^9e^cYG1^`%gm3{yK literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/wellsfargo_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/wellsfargo_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..f95af0a019c93b52c2d16a6a8937eeca94efe99a GIT binary patch literal 1147 zcmXqLVktLhVt%lInTe5!Nx<>w*$Go^7J47-ayhzp(%oA5TXoPan^aNClq|7d?$+O-pkHm}LfX z;=G0i2BtuFfI$?HYY5^R8Jk*~T1FW(wi|LAaDr@O6J`nxHWW4x1aUZoxttSoGSl*l z@-h<*#SBD1g6tx^!HIbaZbgZC$(hB;`GyJxav*Uo5%KWUoSb3>x5T3Ke1*ik6b0w} z+=9fsN<$t4E|3at5oXU|cSC6dNf3`&LxPn2RtJy19M|9Fz`E> z8XFl-ZvJ_|%W0p~5v~PWAIz!j3~Jigxw+|%F0-~=`C*^h>E=ntstvbht6rX0SI0iJ z?%V3Dn2tB;u@nXfa{{Q{+@#Qr_6W?`+=_;Y=2c#U5}-i|Lj{>gT2 zEwxy;*_w0dE%#q$#zs8Om;d%^Y~ajXIlphtUmKl^KLweX85tNCH!-d?XkuIm4lY?? z7A6A*18$&yWcgWGn3-4?7}$U~@+_tXz(`-9zd*N5JENqez)D{~I4lSl={dT|MLDRk z36;&|u@xW&6(L{SX)H%KBmwa6e3rkRn4CCMORVcdckgD8UtgD^49%-qEERQ>eK zGy|a14cOUOwfUHtq*z3}vv+DtW8>LnI?mR&SoW3TIEj^p;XVpgBF u>su8mvMthbyZZ57t@NoTI^DIQ-`ER!9M64AVPHJ17xPQaqII2{$p!#~hi7#F literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/wellsfargo_v3.101.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/wellsfargo_v3.101.cer new file mode 100644 index 0000000000000000000000000000000000000000..62dbdbb2b3b54e2d3e508afa213fa12628ce40c4 GIT binary patch literal 903 zcmXqLVs18QVtTWHnTe5!Nx<#T>s?ze=<`oXn4xSxnZ4hDmyJ`a&7D}zD2 zA-4f18*?ZNn=n&ou%WntD2T%)%omnglo_0vo~NVWnU}0*Xl`H%lHeBBbIwUDE>DJm^4QSeJGDbFv;hPjFx!&Sxxh7eb2 z!F77(m82HsfnAZ9qY#{0RF+z#;OwZNs{nPlp{Id6M3X~#dAS}?I4)ylU@SgI~c)qc4D3hU)P&&;e>eelVN-u8TzO|fg}rjL7HO?P@b z%Y;kx%F39p4yt!=vL7_sRGM?-)b7Rq!qf|$S0#Tnu$!#$^w&pD>(ASL{Vc!7ct-6w zD0_KR*S`XTsZOW=X$N*k*;xHl@}IDYX?gG*f0O5{SvFPYGchwVFfMLjO>hz23iIhY#iEbz{J7M#3&|{ zQBqP+Y^AS{EvO7kK&Gg&=o)Clv@kQmSxju45ObYa7}>aBR&X#HaD#O5v#zI5Ry@A*86ZxJ1D(wWK`1DBDonKoq2aTbK`~Ku5tdFImsf z*uW4Xp#_rwikGAoJjSXtUB@E$$QqT6OYRkCv>O~^6)#v&^sRTdapLQYsis#NX4;(I z_Kc-VO>%o2(^NABbp?Gdw+z*uFEyRyMs%%!~|-i<=m? z8#FO)28Xw-Fbk6bgMkasC$b7Gwg%P)mTcS!Z61tmKU^8v#hDGX3^dp{wAp}3ke!K9 zOeUkGq@dVJUmsgw8gPS5;b&oCW@23cjtN;+7F`2vHcp6vPArUUTtK5(7@N$wn3-Y5 zGBd(iOh8>w%NQA1Gz`=XRA77q#x@C%qfYNHaIIOiM{iO*S>QG&4y}OG`?! zOifNQNHZ}rPBt{ig}INBhb7SHdbvu zW+o{Xk^ZNbrP|i?_GKSF-;j01LqexoQqMqDOd0Croc#2BR5zCugT+85p_U2Ez$6v- zdXk&cJHy@0sycgRn)+4*YAlhzw=VL^RqM1P`P^z-XJ0wEXKAE##nrOARf}3~NnUhV zS#ru~HLup&lwzs%nkoEOzU*7(b!o$|sl6TdWlV3lwDkSH@LWAx_^aZ6*7WatN;Vyz irp&(Wd|iBR-kY<9*ZG~oX1~=oNYCHA{pZRa{R#m1t$Qv2 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/xdss_v3.101.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlFromSsl/xdss_v3.101.cer new file mode 100644 index 0000000000000000000000000000000000000000..1c84d8b541b4514e216e61d43a5e7f5644757ded GIT binary patch literal 903 zcmXqLVs18QVtTWHnTe5!NkG-RtJT8k%;Sh3NAIpv%3ET<%f_kI=F#?@mywZ`mBAq1 zklTQhjX9KsO_(V(*ihU+6vW{Y<_k+L$_&m-&(l%x%uCiYG&e8>NpK76Ip-u67b_Sm z1e7M_WF{*F6lLZn7F8-ZrxulDre!84mSpDVDL9svWaJlRmQ)(ZiSt^T8<+qM0D~xT zUPD7e10xe7V^d30%P51!U54@ovJgwfV3sO`6qOd2DEOt8l;;;^!(7FU;VNSTLx`)i z;5t3?N>YpRz^+KlQ3y^gDoZU=aCTJCRe(C&(9^&jqRFAWyj%|`ommX@r(SY?uD)|X zFvz?4MFo0El?p+rX?hAio{mnQKAs_w3O*q&dK$@^mgWjD%M2RlBZns=D+6<5FM~m2 zCsSi1!;Pkf7uO`2YUNucEL9h!YCqh6h4u2DXJ*!`KKSHBZ+pJVrr0%f)5pE9raQfz zWx^$TWo67)2i3bb*$*0RD$O}^YWL!QVd{m>tCGJO*iF`W`s*X7_2=!rewN>3Jfn6T zl)b#E>tBJvRHxJbv;(`NY^;7N`A^uyv^;o@zsd8}ESswHnV1xVpxIw!3Sy+Gxl+8d8 zu8NTnDg=sBS$P(qLk!dws4P%wQvf*v=!WE?9MtG4NKQ1?1BxO?0x(fC14EyK@y(Nr zDa=kEi$5wavby*3*MN0jZ_UY*afGG6^^4vPr885{S{j{K{_?=-a!KPl>Ud3$k< z0;lf7Zx1C|EjHNl&#(V6kLgYuQ(K~+T72C6Npd_YOTJzx5I(PV*xA-oc3zWSQ2ZXd dV`-X$paKSB z1|m$1jBte(29{ujX!bKVHZnBsdw*J~_Gt4aiGMox+D|T-XdJ;|u2xX?<$dfygCvIZ zl}Ua6D!q3r(;SZmKaFVG=%W4i{>DO$OO`u@e0lzEX)GY9gdepi62}X}W@Q zkdH!1YH^8zv!kK7fhb6hi-*s#pdcqz!8t#-ptK~l$Ush<*TBrc#L(Q(($K)fAWEFq z5X3csat+K4WelVs#tNeuo0FQDhTGuA`3AfQ_c5|EFgNxx7&LY=H8wJwFzYIw)#Ish z#g8%XOxX>I|MR9_5B(@8%e1NJ(0o4UKRHRRHE-l@6*wPad%sL?(cdCP!+?ewRY9YXnjTTvSnXcvs2^Gir$Q#b!_(8lbx?k z0&Lc9Q{msUre;;}y@yWK+WV@C1e7FszO?X9x%KwyFEjNosmztncX+?O{Z*S?DyRIL oyT$6oAy0R^=!opD^;Xo7`eCWGz1e5g8|H=O?{|kE>-e_|0H8s-!~g&Q literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crlTime/crlTestRoot.cer b/SecurityTests/clxutils/certcrl/testSubjects/crlTime/crlTestRoot.cer new file mode 100644 index 0000000000000000000000000000000000000000..712983e69ec16a4f255730d868a098290b4824ad GIT binary patch literal 517 zcmXqLVq!FCV$52=%*4pV#K>U4&Bm$K=F#?@mywaxz|>I6K!S}ql!ci`&?PmgG+n_t z$VZ_hwYWsV+0jtkKolg$#lz=VP>_?V;GCaZP+F2&WFRNbYhY$zVrXt?X<%t;5+%-S z2;!PRx#Sw#INyL5;W|cE2Ij_I27|^(7a;Kcm~dj%LTX z{r}IWkYF*1dF}~&rl}1#wydhW$KdI_DMjOl#h=~J?z%J2K4NZEmiR>e?AE59JH=<; zyJhRo@p|-O%Co>kC+*KnJ8xaJn)UlB&%@>FLQ9+8%f1o$Bz{`>uFv-w-0911`9*k# z#cf=vCx1_xiJ6gsaj~+2q5(fJOk{-_8UM4e8ZZMX13r)dKS+QD7|3nNeqaUpp^+ic za*6-j4ToO6+Wt_r_u+4w>oca=e)(wPCAcg+;f+;WiEQtFrU%#g*9TwL*E^o!#k5*X z{Jh${+g@{Ie%qEXG~7s&;!F^h*s$%XOzw&*y@#u2B-@q0+9~8wrm(4|*oF6VX`*3k ix!zH&HCv~5FTM3w fail 20060418090559Z +# Test cert at revoke - 1 ==> OK 20060418090557Z +# Test cert at create with CRL ==> OK 20060417191040Z (before revocation, before CRL) +# Test cert at create w/o CRL ==> OK 20060417191040Z +# Test cert at create-1 w/o CRL - not yet valid 20060417191039Z +# Test cert at not after w/o CRL - OK 20160414191040Z +# Test cert at not after + 1 - fail 20160414191041Z +# +# Certs were generated from CA in keychain, crlKeychain.keychain, pwd = crlKeychain, +# in clxutils/makeCrl/testFiles. +# + +globals +certNetFetchEnable = false +crlNetFetchEnable = false +useSystemAnchors = false +allowUnverified = true +end + +test = "basic, no CRL" +requireCrlForAll = false +cert = crlTestLeaf.cer +root = crlTestRoot.cer +end + +# +# This is a handy place to test the corner cases of notBefore and notAfter. +# I don't believe these have ever been tested right to the second. +# +test = "basic, no CRL, at NotBefore" +requireCrlForAll = false +cert = crlTestLeaf.cer +root = crlTestRoot.cer +verifyTime = 20060417191040Z +end + +test = "basic, no CRL, before NotBefore, expect fail" +requireCrlForAll = false +cert = crlTestLeaf.cer +root = crlTestRoot.cer +verifyTime = 20060417191039Z +error = CSSMERR_TP_CERT_NOT_VALID_YET +# CSSM_CERT_STATUS_NOT_VALID_YET | CSSM_CERT_STATUS_IS_IN_INPUT_CERTS +certstatus = 0:0x06 +end + +# +# Note root was created before leaf so we assume it will be expired at +# the time of the leaf cert's NotAfter. +# +test = "basic, no CRL, at NotAfter" +requireCrlForAll = false +cert = crlTestLeaf.cer +root = crlTestRoot.cer +verifyTime = 20160414191040Z +allowExpiredRoot = true +end + +test = "basic, no CRL, at NotAfter plus 1, expect fail" +requireCrlForAll = false +cert = crlTestLeaf.cer +root = crlTestRoot.cer +verifyTime = 20160414191041Z +error = CSSMERR_TP_CERT_EXPIRED +# CSSM_CERT_STATUS_EXPIRED | CSSM_CERT_STATUS_IS_IN_INPUT_CERTS +certstatus = 0:0x05 +end + +# +# Begin CRL testing. +# +test = "CRL, prior to revocation, within CRL validity" +requireCrlForAll = true +revokePolicy = crl +cert = crlTestLeaf.cer +root = crlTestRoot.cer +crl = crl.crl +# One second before revocation +verifyTime = 20060418090557Z +end + +# +# This ensures that we verify the CRL itself at 'now' instead of the +# cert verification time. +# +test = "CRL, prior to revocation, before CRL validity" +requireCrlForAll = true +revokePolicy = crl +cert = crlTestLeaf.cer +root = crlTestRoot.cer +crl = crl.crl +# Leaf create/notBefore time, definitely before the CRL is valid. +verifyTime = 20060417191040Z +end + +test = "CRL, subsequent to revocation" +requireCrlForAll = true +revokePolicy = crl +cert = crlTestLeaf.cer +root = crlTestRoot.cer +crl = crl.crl +# Normal revocation case. +verifyTime = 20060418090559Z +error = CSSMERR_TP_CERT_REVOKED +certerror = 0:CSSMERR_TP_CERT_REVOKED +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crossSigned/SOA1-SOA2.pem b/SecurityTests/clxutils/certcrl/testSubjects/crossSigned/SOA1-SOA2.pem new file mode 100644 index 00000000..071f4e6c --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/crossSigned/SOA1-SOA2.pem @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFGjCCBAKgAwIBAgIUb912vFD5/QTVUhe9LipdbaECeGwwDQYJKoZIhvcNAQEF +BQAwgakxIDAeBgNVBAoMF0NoYWxsZW5nZS9SZXNwb25zZSwgTExDMR0wGwYJKoZI +hvcNAQkBFg5zb2ExQHVub21pLm5ldDEWMBQGA1UECBMNTWFzc2FjaHVzZXR0czES +MBAGA1UEBxMJQ2FtYnJpZGdlMQswCQYDVQQGEwJVUzENMAsGA1UEAxMEU09BMTEe +MBwGA1UECxMVVW5vbWkgQ2VydGlmaWNhdGUgU09BMB4XDTA2MDUyOTIwNTAxMVoX +DTA3MDUyOTIwNTAxMVowgakxIDAeBgNVBAoMF0NoYWxsZW5nZS9SZXNwb25zZSwg +TExDMR0wGwYJKoZIhvcNAQkBFg5zb2EyQHVub21pLm5ldDEWMBQGA1UECBMNTWFz +c2FjaHVzZXR0czESMBAGA1UEBxMJQ2FtYnJpZGdlMQswCQYDVQQGEwJVUzENMAsG +A1UEAxMEU09BMjEeMBwGA1UECxMVVW5vbWkgQ2VydGlmaWNhdGUgU09BMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuEWDBaXgzDJTUFWkXxx76N8kMMC4 +gJNxrQ2khgx6X3WosaQjjTl2ELyU3vb5j97xQKD6TgIXJ5h8ARXKPTg1oDFCnVV1 +HPxeLRZw5JE+QPfNfBEXAKKBN8onezfqn8GuR8B67WsDQ9++HEsfwa2Ezu76fkjB +iN3TujqB6xbwlyYY3nXkvvETEXQ3Sdqzuj6MpX1m/WeNNJAMxYT8SNN3fh1/S9+a +gj/35twKYmoXZnaWpoxryoef9j5vle/onU6Xuk/6FQZ3iqJ6ux9a1f9Wm4KluYaO +LnnMAF3e11YPJVKP9I/ou1dA4CCRiwxcPBrDNK2ZaSK9Kd+vXj192JpxrQIDAQAB +o4IBNjCCATIwgeIGA1UdHwSB2jCB1zCB1KAgoB6GHGh0dHA6Ly9jcmwudW5vbWku +bmV0L3NvYS5jcmyiga+kgawwgakxIDAeBgNVBAoMF0NoYWxsZW5nZS9SZXNwb25z +ZSwgTExDMR0wGwYJKoZIhvcNAQkBFg5zb2ExQHVub21pLm5ldDEWMBQGA1UECBMN +TWFzc2FjaHVzZXR0czESMBAGA1UEBxMJQ2FtYnJpZGdlMQswCQYDVQQGEwJVUzEN +MAsGA1UEAxMEU09BMTEeMBwGA1UECxMVVW5vbWkgQ2VydGlmaWNhdGUgU09BMA8G +A1UdEwEB/wQFMAMBAf8wHAYDVR0RAQH/BBIwEIEOc29hMkB1bm9taS5uZXQwHAYD +VR0SAQH/BBIwEIEOc29hMUB1bm9taS5uZXQwDQYJKoZIhvcNAQEFBQADggEBAGEP +LTA4uwlmXus311kXXuVuEIr1oUwhXhVDnE9hricbme1UQ5/NkI1yVEzbxKyPtUtS +EO9yu4TWN/q3OMcQ2Zv5ga5l41AxVeVo3zqU3K5AX81YkYKMKSfBEi+eW0lzy+eI +KhnWjoAuaYXdz6HbDrOjUmmQw+8Ix47U+Amo4ObeUkTa7GzLG6IomfCHKP7+fe5x +ehVT4VDmnJ03H+M2hAnpjRLrPs5M5JtlFcAHrKbDARhbN/50SUwu+8IqfI9ovWc5 +TJxSXC2qoc8QKgSjCw548nM7Da9NmcahSE1a4iGkzRilnRgf+p87BtD1SaYapnnt +hNtZL6VNsUU2f9XlDns= +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crossSigned/SOA2-SOA1.pem b/SecurityTests/clxutils/certcrl/testSubjects/crossSigned/SOA2-SOA1.pem new file mode 100644 index 00000000..1d540e11 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/crossSigned/SOA2-SOA1.pem @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFGjCCBAKgAwIBAgIUYrQuUHm57gkeYEDPwn8UKLjYrI4wDQYJKoZIhvcNAQEF +BQAwgakxIDAeBgNVBAoMF0NoYWxsZW5nZS9SZXNwb25zZSwgTExDMR0wGwYJKoZI +hvcNAQkBFg5zb2EyQHVub21pLm5ldDEWMBQGA1UECBMNTWFzc2FjaHVzZXR0czES +MBAGA1UEBxMJQ2FtYnJpZGdlMQswCQYDVQQGEwJVUzENMAsGA1UEAxMEU09BMjEe +MBwGA1UECxMVVW5vbWkgQ2VydGlmaWNhdGUgU09BMB4XDTA2MDUyOTIwNTA0N1oX +DTA3MDUyOTIwNTA0N1owgakxIDAeBgNVBAoMF0NoYWxsZW5nZS9SZXNwb25zZSwg +TExDMR0wGwYJKoZIhvcNAQkBFg5zb2ExQHVub21pLm5ldDEWMBQGA1UECBMNTWFz +c2FjaHVzZXR0czESMBAGA1UEBxMJQ2FtYnJpZGdlMQswCQYDVQQGEwJVUzENMAsG +A1UEAxMEU09BMTEeMBwGA1UECxMVVW5vbWkgQ2VydGlmaWNhdGUgU09BMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5i/VN4QcXCrDemAaFo4bRlAazVD6 +1daCxzISk7NF4ELpkN+aSJumKbz0OdoE+gOc4Fk1MSFswFXcVjgowPsT/dt1L6gV +AaEpYLbOLHf4dVb+fWJYI/AOM5JP6RaMTP3w57RNp8Gw6EZBCXFE7lQVzmipNwVt +Dm8yZ8vHv+m+h1MnmM8ehX3OUfYqzTcg1uMsWLqDA90UUglkdAjtYW4feL8+2zdb +p8k1BkHJ60X3JgHKTTZx2JZTqouabPEk8TgO07Yffo4FSzOLNYUtWhFsrzKoUWEz +cz3z/9M+BoQxal0WoFAmMvpWesbIg86ivThCyM3njNK1plG6eOPHnKoUcQIDAQAB +o4IBNjCCATIwgeIGA1UdHwSB2jCB1zCB1KAgoB6GHGh0dHA6Ly9jcmwudW5vbWku +bmV0L3NvYS5jcmyiga+kgawwgakxIDAeBgNVBAoMF0NoYWxsZW5nZS9SZXNwb25z +ZSwgTExDMR0wGwYJKoZIhvcNAQkBFg5zb2EyQHVub21pLm5ldDEWMBQGA1UECBMN +TWFzc2FjaHVzZXR0czESMBAGA1UEBxMJQ2FtYnJpZGdlMQswCQYDVQQGEwJVUzEN +MAsGA1UEAxMEU09BMjEeMBwGA1UECxMVVW5vbWkgQ2VydGlmaWNhdGUgU09BMA8G +A1UdEwEB/wQFMAMBAf8wHAYDVR0RAQH/BBIwEIEOc29hMUB1bm9taS5uZXQwHAYD +VR0SAQH/BBIwEIEOc29hMkB1bm9taS5uZXQwDQYJKoZIhvcNAQEFBQADggEBAJof +SEKxyUaCjdA3HQ55g2UbjvgPFJoduAv/z2WVfBE4enIzQoEl+j7vRJ5YvmB5doeC +1Shz5/qEr7WBmN4RbcVTMoYEEXwi/NvSgqqQ2ta6fO8tRhzPhH4hhFZnr/LxkkYp +/2cVuJWp1VS5cZZ521BFHXc+ERsZiKPog9CEV5LkAYwCdJUTTH2RENagdCugDRUX +wX1AkKod+mrv6dxXrcmeARqAr7lBgnW0AN/3GF37IG+syNEo8P5Y7YxcCmjiBO3E ++eabGjVlTRTDVyXLUWvAswBEX4Ousk2c7cY68sWw76iNjjdhdCfAIeLrEYcVqg5r +cwAnKtpeo50GXUmtp20= +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crossSigned/crossSigned.scr b/SecurityTests/clxutils/certcrl/testSubjects/crossSigned/crossSigned.scr new file mode 100644 index 00000000..0b4b9c0f --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/crossSigned/crossSigned.scr @@ -0,0 +1,44 @@ +# +# Test for cross-signed cert detect, Radar 4566041 +# WARNING this results in a hang when running with a Security.framework in which +# 4566041 is not fixed. +# +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +end + +test = "Plain in-memory cross signed detect" +cert = SOA1-SOA2.pem +cert = SOA2-SOA1.pem +# specify verify time so this test will always be valid +verifyTime = 20060601000000 +leafCertIsCA = true +error = CSSMERR_TP_NOT_TRUSTED +# verify we got both certs - IS_IN_INPUT_CERTS +certstatus = 1:0x4 +end + +test = "verify with DB containing one cert" +cert = SOA2-SOA1.pem +certDb = crossSigned1.db +# specify verify time so this test will always be valid +verifyTime = 20060601000000 +leafCertIsCA = true +error = CSSMERR_TP_NOT_TRUSTED +# verify we got both certs +certstatus = 1:0 +end + +test = "verify with DB containing both certs" +cert = SOA2-SOA1.pem +certDb = crossSignedBoth.db +# specify verify time so this test will always be valid +verifyTime = 20060601000000 +leafCertIsCA = true +error = CSSMERR_TP_NOT_TRUSTED +# verify we got both certs +certstatus = 1:0 +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crossSigned/crossSigned1.db b/SecurityTests/clxutils/certcrl/testSubjects/crossSigned/crossSigned1.db new file mode 100644 index 0000000000000000000000000000000000000000..ceeeaea105d13f2314c7e7cef73448ebeec22f19 GIT binary patch literal 24768 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 TMm literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/crossSigned/crossSignedBoth.db b/SecurityTests/clxutils/certcrl/testSubjects/crossSigned/crossSignedBoth.db new file mode 100644 index 0000000000000000000000000000000000000000..b9cfbd4ec7104e97db92ef9705985ae6241d0d30 GIT binary patch literal 27292 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/emptyCert/emptyCert.cer b/SecurityTests/clxutils/certcrl/testSubjects/emptyCert/emptyCert.cer new file mode 100644 index 00000000..e69de29b diff --git a/SecurityTests/clxutils/certcrl/testSubjects/emptyCert/emptyCert.scr b/SecurityTests/clxutils/certcrl/testSubjects/emptyCert/emptyCert.scr new file mode 100644 index 00000000..ec4c6404 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/emptyCert/emptyCert.scr @@ -0,0 +1,51 @@ +# +# Test for empty/bad cert handling, Radar 3116734. +# Without the fix for 3116734, this results in an assertion failure on +# debug Security.framework. +# +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +end + +test = "Basic good verify as sanity check" +cert = leaf.cer +cert = CA.cer +root = root.cer +# IS_IN_ANCHORS | IS_ROOT +certstatus = 2:0x18 +end + +test = "Throw in empty cert not as leaf, it should be ignored" +cert = leaf.cer +cert = CA.cer +cert = emptyCert.cer +root = root.cer +# IS_IN_ANCHORS | IS_ROOT +certstatus = 2:0x18 +end + +test = "Throw in text file not as leaf, it should be ignored" +cert = leaf.cer +cert = CA.cer +cert = emptyCert.scr +root = root.cer +# IS_IN_ANCHORS | IS_ROOT +certstatus = 2:0x18 +end + +test = "Empty cert as leaf, expect error" +cert = emptyCert.cer +cert = CA.cer +root = root.cer +error = CSSMERR_TP_INVALID_CERTIFICATE +end + +test = "Text file as leaf, expect error" +cert = emptyCert.cer +cert = CA.cer +root = root.cer +error = CSSMERR_TP_INVALID_CERTIFICATE +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/emptyCert/leaf.cer b/SecurityTests/clxutils/certcrl/testSubjects/emptyCert/leaf.cer new file mode 100644 index 0000000000000000000000000000000000000000..88dbb9aefc7f5a1dfe4fcebab6016e16fc76b746 GIT binary patch literal 523 zcmXqLVq!OFVk}s|%*4n9L^LMdN$}UWA(&Ss9ocdl?KGJDD0A84hnL z6t7=d=*7C^%;Nk!pXTsKe$Fpmtrp)^*_1Fxdi`aGZ*Mjp)QYITnCb-|M{k`arpduS?WEFyLms*h_O#DpXJTe#U|cM0AZWl3^rWmXBjbM-Rs&{6 zMh0Xzvx3~*$iNp7t!C+SvBL4qXRFWt>W@NA%VueAd-894x_wpE1rc4#Z>pW)KSOLh5LOaXKs!XN+u literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/emptyCert/root.cer b/SecurityTests/clxutils/certcrl/testSubjects/emptyCert/root.cer new file mode 100644 index 0000000000000000000000000000000000000000..de72763fd4aa5bfcbd79c3c58a3769b1362cf823 GIT binary patch literal 525 zcmXqLV&XJtVk}y~%*4pV#K>U4&Bm$K=F#?@mywaxz|m06K!uGtl!ci`wkSWpL?JD| zNFg(~ASW|9vqT{=FF6CqFG(#fF%<1*zlW;d3k~$VpXj&d)6UPChjQ)2@tml{?y&NtvixSElbfw{4l!Jx5|sj-pa?8|@k=XqDlxqbEQ z(bgE4n4j8Wm!`Ao9$=YPo|kcc#)tPB zA+C2G@nj!~6)5xF)24mgY%vovBLm}NVFN(}eqi{>3NtePXJIv922#jwW(B#qkztj^ zj7LkqR7|+D=kCp_Rs9*Ara~`%v~x87&8=IIeSMYOr|sEoF@b;0wPbAh8M_&^mh|mR zT5&e?*6Epsi$zKkBMVnnZE4@q*7wmMZl2SD1AS73wG%QWm@2MJkg=QfKwz=>15WiV g%S4k?GM{bnXBVrSoIES5tMX68Ik$=_C5~Z70R%0&k^lez literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/emptySubject/ca.pem b/SecurityTests/clxutils/certcrl/testSubjects/emptySubject/ca.pem new file mode 100644 index 00000000..a1a5c38d --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/emptySubject/ca.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBcTCCARugAwIBAgIBADANBgkqhkiG9w0BAQQFADANMQswCQYDVQQDEwJjYTAe +Fw0wNDExMzAyMjQ0MzJaFw0wNDEyMzAyMjQ0MzJaMA0xCzAJBgNVBAMTAmNhMFww +DQYJKoZIhvcNAQEBBQADSwAwSAJBAJ0sp+KTHpPYnpUcN89mMwTr776Shn+0Y+yY +dM2vjiosW6rfFsrdD08SnMYQ8Ionxol6MAi20z6Z3AMjfjDKKa8CAwEAAaNmMGQw +HQYDVR0OBBYEFMNr8lZYoti3GlgWyMHOf2QYVPyRMDUGA1UdIwQuMCyAFMNr8lZY +oti3GlgWyMHOf2QYVPyRoRGkDzANMQswCQYDVQQDEwJjYYIBADAMBgNVHRMEBTAD +AQH/MA0GCSqGSIb3DQEBBAUAA0EAN0fMcyqsfPey1v4WiqJ+ePA/RQ4qf8wS1PNO +e0l2V2NqKCeLBaBIS2BAat1Ml2939ju7HE0e8zd3XzDZSdI9Wg== +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/emptySubject/emptySubject.scr b/SecurityTests/clxutils/certcrl/testSubjects/emptySubject/emptySubject.scr new file mode 100644 index 00000000..6c901844 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/emptySubject/emptySubject.scr @@ -0,0 +1,21 @@ +# +# Test for empty subject detect, Radar 3901386 +# +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +end + +test = "Empty subject detect" +cert = user.pem +root = ca.pem +# specify verify time so this test will always be valid +verifyTime = 20041215000000 +# IS_IN_ANCHORS | IS_ROOT +certstatus = 1:0x18 +certerror = 0:CSSMERR_APPLETP_INVALID_EMPTY_SUBJECT +error = CSSMERR_TP_VERIFY_ACTION_FAILED +end + diff --git a/SecurityTests/clxutils/certcrl/testSubjects/emptySubject/user.pem b/SecurityTests/clxutils/certcrl/testSubjects/emptySubject/user.pem new file mode 100644 index 00000000..4d3fa499 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/emptySubject/user.pem @@ -0,0 +1,39 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: CN=ca + Validity + Not Before: Nov 30 22:44:32 2004 GMT + Not After : Dec 30 22:44:32 2004 GMT + Subject: + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (512 bit) + Modulus (512 bit): + 00:d6:a3:b4:a9:dd:5a:7a:e8:d5:94:da:c9:fe:9b: + 02:22:b0:d9:18:0e:40:74:32:e3:65:87:fd:87:19: + c0:bc:54:09:10:68:3a:ed:b2:0c:ce:aa:e2:04:85: + 54:ed:b6:fa:51:19:ee:10:56:d4:e6:84:fc:07:f8: + 89:19:2e:be:3b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Certificate Policies: + Policy: 1.2.3 + CPS: + + Signature Algorithm: sha1WithRSAEncryption + 7a:0a:79:3a:ce:ff:3e:d5:da:3b:ce:e8:f3:54:52:8a:e2:b9: + 32:0e:0c:3a:11:5c:06:ed:35:d0:8d:6d:66:85:46:31:47:e8: + 97:40:d4:02:26:25:f3:a7:d5:09:bb:44:df:05:54:9b:0c:e1: + 94:70:61:cc:9c:bf:66:bb:88:a1 +-----BEGIN CERTIFICATE----- +MIIBIDCBy6ADAgECAgEAMA0GCSqGSIb3DQEBBQUAMA0xCzAJBgNVBAMTAmNhMB4X +DTA0MTEzMDIyNDQzMloXDTA0MTIzMDIyNDQzMlowADBcMA0GCSqGSIb3DQEBAQUA +A0sAMEgCQQDWo7Sp3Vp66NWU2sn+mwIisNkYDkB0MuNlh/2HGcC8VAkQaDrtsgzO +quIEhVTttvpRGe4QVtTmhPwH+IkZLr47AgMBAAGjIzAhMB8GA1UdIAQYMBYwFAYC +KgMwDjAMBggrBgEFBQcCARYAMA0GCSqGSIb3DQEBBQUAA0EAegp5Os7/PtXaO87o +81RSiuK5Mg4MOhFcBu010I1tZoVGMUfol0DUAiYl86fVCbtE3wVUmwzhlHBhzJy/ +ZruIoQ== +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/.gdb_history b/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/.gdb_history new file mode 100644 index 00000000..3a71f49e --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/.gdb_history @@ -0,0 +1,12 @@ +b parseLine +run -S expiredCA.scr -v +li +b 232 +disa 1 +c +p bytesLeft +p cp +p cp-1 +n +p testName +q diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/AppleDevRoot.pem b/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/AppleDevRoot.pem new file mode 100644 index 00000000..8f7e9f9f --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/AppleDevRoot.pem @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIIF+DCCBOCgAwIBAgIBAjANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMCVVMx +HTAbBgNVBAoTFEFwcGxlIENvbXB1dGVyLCBJbmMuMTswOQYDVQQLEzJBcHBsZSBD +b21wdXRlciAoRGV2ZWxvcG1lbnQpIENlcnRpZmljYXRlIEF1dGhvcml0eTE3MDUG +A1UEAxMuQXBwbGUgUm9vdCAoRGV2ZWxvcG1lbnQpIENlcnRpZmljYXRlIEF1dGhv +cml0eTAeFw0wNTA5MDcwMTM2NDdaFw0yNTA5MDcwMTM2NDdaMIGiMQswCQYDVQQG +EwJVUzEdMBsGA1UEChMUQXBwbGUgQ29tcHV0ZXIsIEluYy4xOzA5BgNVBAsTMkFw +cGxlIENvbXB1dGVyIChEZXZlbG9wbWVudCkgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +MTcwNQYDVQQDEy5BcHBsZSBSb290IChEZXZlbG9wbWVudCkgQ2VydGlmaWNhdGUg +QXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwP5eK/7c +bk1SWQv/rjRAbR0uL6KNun+PZ1FaFHkxxEj3Cm4zhSO1vzyMeUmG+covjSctbzS7 +bB5K/8v5cp5Hc3hcPn9HYEfeDbhfht2ZFZ3/YGhrfeMyMioOwZg9MPRfjXC81rJd +BjBMTuQjdP+XqwTj2mGSsxxZEHl7HD1MAOMlZzLUnSPl98PcfKo5RnNfORjciow/ +erBn9GnBMmj6eoHbpnrp61j9/UEEAoX+dwcl9k95emzRzCBtj33Dk87l9R1GOapq +ubEZIofDAQhd/OYoW7rB6fbZR5mYJptrdeGFbxqapko7FNS8h03DpxiglxzLilk7 +p6/FKaaLJ/IW/QIDAQABo4ICNTCCAjEwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB +/wQFMAMBAf8wHQYDVR0OBBYEFFRX4ZVu29bx2jf2ZgFdtnB/PKi9MB8GA1UdIwQY +MBaAFFRX4ZVu29bx2jf2ZgFdtnB/PKi9MIIBKwYDVR0gBIIBIjCCAR4wggEaBgkq +hkiG92NkBQEwggELMEMGCCsGAQUFBwIBFjdodHRwOi8vY2VydGluZm8ubWFjLmNv +bS9jZXJ0aWZpY2F0ZWF1dGhvcml0eS90ZXJtcy5odG1sMIHDBggrBgEFBQcCAjCB +thqBs1JlbGlhbmNlIG9uIHRoaXMgY2VydGlmaWNhdGUgYnkgYW55IHBhcnR5IGFz +c3VtZXMgYWNjZXB0YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJk +IHRlcm1zIGFuZCBjb25kaXRpb25zIG9mIHVzZSwgY2VydGlmaWNhdGUgcG9saWN5 +IGFuZCBjZXJ0aWZpY2F0aW9uIHByYWN0aWNlIHN0YXRlbWVudHMuMEYGA1UdHwQ/ +MD0wO6A5oDeGNWh0dHA6Ly9jZXJ0aW5mby5tYWMuY29tL2NlcnRpZmljYXRlYXV0 +aG9yaXR5L3Jvb3QuY3JsMFcGCCsGAQUFBwEBBEswSTBHBggrBgEFBQcwAoY7aHR0 +cDovL2NlcnRpbmZvLm1hYy5jb20vY2VydGlmaWNhdGVhdXRob3JpdHkvY2FzaWdu +ZXJzLmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAGuUY1JhGll0A+awe3i6IWvEdP3N +ngmA4WZNbH/8mbYgLfG/JPF/gyzTY70tGZSw+m0x+vjWbIzHVmg8A0wuvEEtx0IE +y7GJjJ0cOTXpUQJ9AaV4nnRmbhe/Z6RZd46bBAEPERJIZjLfzFIrYjnKbEpgAjrm +t2kw6Apjp3MkhgduYcBYgZAYAw6oKaU4k//aTGjwD4WJBSXwmRpyLla1sUnNTZcR +tK6hwoJ0L2mygc1KMhDyvdvrWSM0ZsyxDXh3bkMk4NoUx94CQklZLoISbI7f87cQ +AZXm9pMRSXAWInzjflb2EZ1fgAgftELOuu2hUQkNqUNrjqRuUSx6tvWoffI= +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/NewDevCAIntermdiate.pem b/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/NewDevCAIntermdiate.pem new file mode 100644 index 00000000..f6a2129a --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/NewDevCAIntermdiate.pem @@ -0,0 +1,108 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 15 (0xf) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Apple Computer, Inc., OU=Apple Computer (Development) Certificate Authority, CN=Apple Root (Development) Certificate Authority + Validity + Not Before: Sep 7 23:25:28 2005 GMT + Not After : Dec 31 23:59:59 2008 GMT + Subject: C=US, O=Apple Computer, Inc., OU=Apple Computer (Development) Certificate Authority, CN=Apple .Mac (Development) Certificate Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:d1:cf:99:37:47:10:29:47:01:1c:cd:a6:a4:4e: + f5:9d:1c:b1:57:f3:8b:d0:45:ab:98:4e:7b:79:23: + 57:e8:4f:69:66:ce:3e:35:f3:b3:6c:09:ac:f0:1b: + 25:46:b3:0d:c3:f3:59:62:66:0c:69:c4:fe:44:98: + cf:2e:1b:4b:90:61:2a:b9:07:9c:6f:75:95:07:f9: + 8d:8b:0c:df:85:98:b3:3f:94:e1:f0:cf:fa:94:fe: + 3c:c9:8b:cf:a4:a5:f5:e8:95:f7:59:35:0f:3a:f6: + 70:85:a7:f3:19:ff:a2:8f:a7:0d:fb:a1:4a:89:c0: + 70:7f:5e:50:81:ca:9b:5f:62:17:88:b9:be:46:2e: + 4d:3e:bc:1e:6c:d4:6d:37:3d:0b:5b:9a:95:c4:ca: + 44:1e:75:7a:94:98:f9:91:6e:c6:09:08:ae:41:8e: + 5a:30:49:95:1b:14:a2:3d:aa:4d:b5:d1:fb:af:ef: + 6a:ec:ab:79:0a:65:46:90:4e:55:c2:12:d6:4d:45: + eb:91:13:19:66:86:67:f2:f0:de:20:02:1e:68:f9: + 44:9b:5d:72:e1:cf:80:c7:bf:dc:22:8d:a2:41:b1: + 15:46:2e:3e:60:f1:b3:9b:51:af:e1:0a:6f:19:04: + f0:98:c4:7f:54:a9:e7:b9:59:75:35:ff:fa:64:bf: + 71:91 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 36:11:78:76:AB:3C:86:69:DD:E8:0A:67:A4:FB:3B:B6:05:0B:19:F6 + X509v3 Authority Key Identifier: + keyid:54:57:E1:95:6E:DB:D6:F1:DA:37:F6:66:01:5D:B6:70:7F:3C:A8:BD + + X509v3 Certificate Policies: + Policy: 1.2.840.113635.100.5.2 + CPS: http://certinfo.mac.com/certificateauthority/terms.html + User Notice: + Explicit Text: Reliance on this certificate by any party assumes acceptance of the then applicable standard terms and conditions of use, certificate policy and certification practice statements. + + X509v3 CRL Distribution Points: + URI:http://certinfo.mac.com/certificateauthority/root.crl + + Authority Information Access: + CA Issuers - URI:http://certinfo.mac.com/certificateauthority/casigners.html + X509v3 Issuer Alternative Name - URI:http://certinfo.mac.com/certificateauthority/DevelopmentRootCert.pem + + Signature Algorithm: sha1WithRSAEncryption + 7d:ba:62:fb:05:85:52:b2:2d:8a:ec:6c:48:c6:f8:cb:2f:12: + c1:14:a7:46:44:72:99:c5:1e:fc:1b:a2:77:f8:05:7e:db:1f: + 59:c8:02:0f:30:58:06:2e:d0:35:b5:ac:6b:8c:64:88:7b:d5: + 57:86:41:5d:f2:cc:e1:f2:6d:32:fd:cc:d8:c2:55:ce:e5:67: + 4b:c5:f6:23:d6:48:a5:66:69:02:1c:fb:33:d9:14:5f:75:10: + 44:52:90:b4:c8:2b:5a:28:0f:50:12:db:06:a2:0d:d5:99:d7: + f7:f7:2d:1f:90:7e:e2:06:73:10:86:6f:f7:f6:21:c6:17:05: + 2f:c4:61:63:ad:af:9f:53:37:66:c9:7a:f5:a7:32:a2:33:95: + 0f:e1:26:8c:a8:26:e0:91:5c:5d:99:73:c0:05:72:37:3e:c7: + 3b:5f:4b:14:87:39:c1:68:92:10:40:7b:a4:f9:1a:20:80:bc: + 52:83:8b:f5:69:05:1a:ed:dc:2e:56:be:2f:1c:b9:40:aa:e8: + 3a:8e:4f:2b:52:2a:a1:fc:94:28:11:15:3c:d1:da:b1:f7:5c: + be:3b:f6:c1:20:70:ff:67:81:9f:ab:f3:d2:06:63:14:0d:04: + 87:a3:96:6b:18:71:df:b2:15:6f:d3:1b:d2:7b:fe:59:02:51: + cc:0c:05:2d +-----BEGIN CERTIFICATE----- +MIIGSDCCBTCgAwIBAgIBDzANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMCVVMx +HTAbBgNVBAoTFEFwcGxlIENvbXB1dGVyLCBJbmMuMTswOQYDVQQLEzJBcHBsZSBD +b21wdXRlciAoRGV2ZWxvcG1lbnQpIENlcnRpZmljYXRlIEF1dGhvcml0eTE3MDUG +A1UEAxMuQXBwbGUgUm9vdCAoRGV2ZWxvcG1lbnQpIENlcnRpZmljYXRlIEF1dGhv +cml0eTAeFw0wNTA5MDcyMzI1MjhaFw0wODEyMzEyMzU5NTlaMIGiMQswCQYDVQQG +EwJVUzEdMBsGA1UEChMUQXBwbGUgQ29tcHV0ZXIsIEluYy4xOzA5BgNVBAsTMkFw +cGxlIENvbXB1dGVyIChEZXZlbG9wbWVudCkgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +MTcwNQYDVQQDEy5BcHBsZSAuTWFjIChEZXZlbG9wbWVudCkgQ2VydGlmaWNhdGUg +QXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0c+ZN0cQ +KUcBHM2mpE71nRyxV/OL0EWrmE57eSNX6E9pZs4+NfOzbAms8BslRrMNw/NZYmYM +acT+RJjPLhtLkGEquQecb3WVB/mNiwzfhZizP5Th8M/6lP48yYvPpKX16JX3WTUP +OvZwhafzGf+ij6cN+6FKicBwf15QgcqbX2IXiLm+Ri5NPrwebNRtNz0LW5qVxMpE +HnV6lJj5kW7GCQiuQY5aMEmVGxSiPapNtdH7r+9q7Kt5CmVGkE5VwhLWTUXrkRMZ +ZoZn8vDeIAIeaPlEm11y4c+Ax7/cIo2iQbEVRi4+YPGzm1Gv4QpvGQTwmMR/VKnn +uVl1Nf/6ZL9xkQIDAQABo4IChTCCAoEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB +/wQFMAMBAf8wHQYDVR0OBBYEFDYReHarPIZp3egKZ6T7O7YFCxn2MB8GA1UdIwQY +MBaAFFRX4ZVu29bx2jf2ZgFdtnB/PKi9MIIBKwYDVR0gBIIBIjCCAR4wggEaBgkq +hkiG92NkBQIwggELMEMGCCsGAQUFBwIBFjdodHRwOi8vY2VydGluZm8ubWFjLmNv +bS9jZXJ0aWZpY2F0ZWF1dGhvcml0eS90ZXJtcy5odG1sMIHDBggrBgEFBQcCAjCB +thqBs1JlbGlhbmNlIG9uIHRoaXMgY2VydGlmaWNhdGUgYnkgYW55IHBhcnR5IGFz +c3VtZXMgYWNjZXB0YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJk +IHRlcm1zIGFuZCBjb25kaXRpb25zIG9mIHVzZSwgY2VydGlmaWNhdGUgcG9saWN5 +IGFuZCBjZXJ0aWZpY2F0aW9uIHByYWN0aWNlIHN0YXRlbWVudHMuMEYGA1UdHwQ/ +MD0wO6A5oDeGNWh0dHA6Ly9jZXJ0aW5mby5tYWMuY29tL2NlcnRpZmljYXRlYXV0 +aG9yaXR5L3Jvb3QuY3JsMIGmBggrBgEFBQcBAQSBmTCBljBHBggrBgEFBQcwAoY7 +aHR0cDovL2NlcnRpbmZvLm1hYy5jb20vY2VydGlmaWNhdGVhdXRob3JpdHkvY2Fz +aWduZXJzLmh0bWwwSwYDVR0ShkRodHRwOi8vY2VydGluZm8ubWFjLmNvbS9jZXJ0 +aWZpY2F0ZWF1dGhvcml0eS9EZXZlbG9wbWVudFJvb3RDZXJ0LnBlbTANBgkqhkiG +9w0BAQUFAAOCAQEAfbpi+wWFUrItiuxsSMb4yy8SwRSnRkRymcUe/Buid/gFftsf +WcgCDzBYBi7QNbWsa4xkiHvVV4ZBXfLM4fJtMv3M2MJVzuVnS8X2I9ZIpWZpAhz7 +M9kUX3UQRFKQtMgrWigPUBLbBqIN1ZnX9/ctH5B+4gZzEIZv9/YhxhcFL8RhY62v +n1M3Zsl69acyojOVD+EmjKgm4JFcXZlzwAVyNz7HO19LFIc5wWiSEEB7pPkaIIC8 +UoOL9WkFGu3cLla+Lxy5QKroOo5PK1IqofyUKBEVPNHasfdcvjv2wSBw/2eBn6vz +0gZjFA0Eh6OWaxhx37IVb9Mb0nv+WQJRzAwFLQ== +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/OriginalDevCAIntermediate.pem b/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/OriginalDevCAIntermediate.pem new file mode 100644 index 00000000..834b5c4d --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/OriginalDevCAIntermediate.pem @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIIF+DCCBOCgAwIBAgIBDDANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMCVVMx +HTAbBgNVBAoTFEFwcGxlIENvbXB1dGVyLCBJbmMuMTswOQYDVQQLEzJBcHBsZSBD +b21wdXRlciAoRGV2ZWxvcG1lbnQpIENlcnRpZmljYXRlIEF1dGhvcml0eTE3MDUG +A1UEAxMuQXBwbGUgUm9vdCAoRGV2ZWxvcG1lbnQpIENlcnRpZmljYXRlIEF1dGhv +cml0eTAeFw0wNTA5MDcyMzI1MjhaFw0wNzA5MDcyMzI1MjhaMIGiMQswCQYDVQQG +EwJVUzEdMBsGA1UEChMUQXBwbGUgQ29tcHV0ZXIsIEluYy4xOzA5BgNVBAsTMkFw +cGxlIENvbXB1dGVyIChEZXZlbG9wbWVudCkgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +MTcwNQYDVQQDEy5BcHBsZSAuTWFjIChEZXZlbG9wbWVudCkgQ2VydGlmaWNhdGUg +QXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0c+ZN0cQ +KUcBHM2mpE71nRyxV/OL0EWrmE57eSNX6E9pZs4+NfOzbAms8BslRrMNw/NZYmYM +acT+RJjPLhtLkGEquQecb3WVB/mNiwzfhZizP5Th8M/6lP48yYvPpKX16JX3WTUP +OvZwhafzGf+ij6cN+6FKicBwf15QgcqbX2IXiLm+Ri5NPrwebNRtNz0LW5qVxMpE +HnV6lJj5kW7GCQiuQY5aMEmVGxSiPapNtdH7r+9q7Kt5CmVGkE5VwhLWTUXrkRMZ +ZoZn8vDeIAIeaPlEm11y4c+Ax7/cIo2iQbEVRi4+YPGzm1Gv4QpvGQTwmMR/VKnn +uVl1Nf/6ZL9xkQIDAQABo4ICNTCCAjEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB +/wQFMAMBAf8wHQYDVR0OBBYEFDYReHarPIZp3egKZ6T7O7YFCxn2MB8GA1UdIwQY +MBaAFFRX4ZVu29bx2jf2ZgFdtnB/PKi9MIIBKwYDVR0gBIIBIjCCAR4wggEaBgkq +hkiG92NkBQIwggELMEMGCCsGAQUFBwIBFjdodHRwOi8vY2VydGluZm8ubWFjLmNv +bS9jZXJ0aWZpY2F0ZWF1dGhvcml0eS90ZXJtcy5odG1sMIHDBggrBgEFBQcCAjCB +thqBs1JlbGlhbmNlIG9uIHRoaXMgY2VydGlmaWNhdGUgYnkgYW55IHBhcnR5IGFz +c3VtZXMgYWNjZXB0YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJk +IHRlcm1zIGFuZCBjb25kaXRpb25zIG9mIHVzZSwgY2VydGlmaWNhdGUgcG9saWN5 +IGFuZCBjZXJ0aWZpY2F0aW9uIHByYWN0aWNlIHN0YXRlbWVudHMuMEYGA1UdHwQ/ +MD0wO6A5oDeGNWh0dHA6Ly9jZXJ0aW5mby5tYWMuY29tL2NlcnRpZmljYXRlYXV0 +aG9yaXR5L3Jvb3QuY3JsMFcGCCsGAQUFBwEBBEswSTBHBggrBgEFBQcwAoY7aHR0 +cDovL2NlcnRpbmZvLm1hYy5jb20vY2VydGlmaWNhdGVhdXRob3JpdHkvY2FzaWdu +ZXJzLmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAD4AeTcmbgTUe5Wxfjn4gNMSfVyw +/QEOVqeM+LKGjXBjEGwZT7tuRmOCL9jTot5nZUuHxTmsNTCDYZ3b1wy/AC5zUCtj +51YsqetA36sFNeu0SxyGfuOJc0RBCZJ21XRIP1TiO9sNn4wyOuhpXBhm/YZIiBpz +awFeTK0NID4fvRvqLlJjfYbkSI4VwI5a5GNHwfes4UttlXp6QMQldbFpFnTTJio1 +R+eGCAyTPmNB9JNHEfcpYNtmPB+hU7CtXNprHYPNIaUkkVdjUwbz9AsuLH6C20Wt +44I+pzkuBjIth67FHQ/E4wExcNtWPtp8mzWkMEgP87QYzotifH9hKMamSKY= +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/appleDevCAs.keychain b/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/appleDevCAs.keychain new file mode 100644 index 0000000000000000000000000000000000000000..4d833ebd5c82c83db71cfddcca04f28cec2a2e0f GIT binary patch literal 28012 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/dmitchtread.cer b/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/dmitchtread.cer new file mode 100644 index 0000000000000000000000000000000000000000..af2a56b01236a0face3fd9e5d2620b2174eac665 GIT binary patch literal 1483 zcmXqLVm)rq#Ik+?GZP~d6AQzWH=PE&Y@Awc9&O)w85vnw84Ma18FCwNvN4CUun9AT z1{=y6NP{?B!Xl0Z1v#k-&iT0or6s9FItre7$$Ey?29_XcZeb%-X$1|J)Uwo^{DR!n zyb?_X=hUK-%(Tqp#FA76$I_CF{G!Z~N<(u4Q;=q6VLgauJ>SG+Vl*1aiSrtm85$T^ z7@8Rx8W=}GxQ511u0b_Peh@I=gZP0xH!)c+IX~A>#6Sq*Fz%Gx%#!4clA_ea6hl=5 zWsoSZuuP_NMq-JAYhH3uWkE@1ejc*_3>xPnhbbc~19M|9FkCyC8XFnzR0du#WUXJw zKl7@eo=#zHRkMA^u5BT6PbPTII^wuGI{M(_z4a>m{_)>LV(Sj^Za=#~X_{NZV&g_T zH?R0Uca7KK9~Do3emYlot99e=e6PsO-M$Nx_CEUFvys;@yjuNlkcbV}2469MuiH{j z_)HsKeQ|B?JzpO6`_kOXh6i)pOqrM&85kEgF|9RdVp?gy1N4rpFeBrC7A6A*a3IL? zgLo{=OsoqGG(obeEJ_9nY#iEbz{J7M%mhs<$tf&IOlAW?HqL}L55~41PK=Bo-Runp zvLM}jEMhDo5%S>$7Oq>q*Bk9fJo#wn6NxSSvIg=XX=N4(1F;4XGr@|o)i!OJcVBR& zFZpe~jg?#Sn?d7Rn5{q~8y6Tf&Na}0i5M`p$z+t26j;Ib+u zzXX_IogMXnjxcCq)Bq`0U}<8M2Xdr=SR5W&tV}>Ihk*mkSxk&#Cd4}nnA>upPHH?1 zH-gEaahp`*=AhJ^%*4FpR0UuvEXl|$Rse?xG^-_5DkSDrDikCZl>k}A#ihBa#R`eZ z$*Bb;5It!?J*gm^rvM5YUwC!1_gVHLMF%y zsS2riWtm0!c_76Ko_-;Qn#lPHSVl27F)}i6WfWSi{d-b)zss~cIb}S5<5n%~jjesq z(lkquWyy=3?oZ|NfJF?$O5;s&4T)p*x-odj+M0Y1KDaT!yHq|PebHV#v z-getwbk)6PG1^=IASqkpP0yZ^#%eOA|G-D9xZ$$E^<}; z`7d*i(<&u8G83POdU@FTTPy8N$tn=t)V6Nnr&IL>nlcjKX0~1O4SA-~o#%Z%hcB3U p*$+lf5db4k^=JS9 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/expiredCA.scr b/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/expiredCA.scr new file mode 100644 index 00000000..839e13fc --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/expiredCA.scr @@ -0,0 +1,112 @@ +# +# test handling of expired Apple development CA certs, Radar 3622125. +# + +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +end + +# +# Original Dev CA expires Sep 7, 2007 +# New Dev CA expires Dec 31, 2008 +# leaf cert expires Oct 13, 2006 +# +# After initial sanity checks, we evaluate at a time after the +# original CA expired and before the new CA expires; we assume +# that the leaf is expired in all cases. +# + +test = "Old CA before it expires, expired leaf" +cert = dmitchtread.cer +cert = OriginalDevCAIntermediate.pem +root = AppleDevRoot.pem +verifyTime = 20061201000000 +error = CSSMERR_TP_CERT_EXPIRED +# leaf expired +# IS_IN_INPUT_CERTS | EXPIRED +certstatus = 0:0x05 +# IS_IN_INPUT_CERTS +certstatus = 1:0x04 +# IS_IN_ANCHORS IS_ROOT +certstatus = 2:0x18 +end + +test = "New CA before it expires, expired leaf" +cert = dmitchtread.cer +cert = NewDevCAIntermdiate.pem +root = AppleDevRoot.pem +verifyTime = 20061201000000 +error = CSSMERR_TP_CERT_EXPIRED +# leaf expired +# IS_IN_INPUT_CERTS | EXPIRED +certstatus = 0:0x05 +# Verify IS_IN_INPUT_CERTS +certstatus = 1:0x04 +# IS_IN_ANCHORS IS_ROOT +certstatus = 2:0x18 +end + +test = "Old CA after it expires, expired leaf" +cert = dmitchtread.cer +cert = OriginalDevCAIntermediate.pem +root = AppleDevRoot.pem +verifyTime = 20071201000000 +error = CSSMERR_TP_CERT_EXPIRED +# leaf expired +# IS_IN_INPUT_CERTS | EXPIRED +certstatus = 0:0x05 +# IS_IN_INPUT_CERTS | EXPIRED +certstatus = 1:0x05 +# IS_IN_ANCHORS IS_ROOT +certstatus = 2:0x18 +end + +test = "Old CA and new CA in input certs" +cert = dmitchtread.cer +cert = OriginalDevCAIntermediate.pem +cert = NewDevCAIntermdiate.pem +root = AppleDevRoot.pem +verifyTime = 20071201000000 +error = CSSMERR_TP_CERT_EXPIRED +# leaf expired +# IS_IN_INPUT_CERTS | EXPIRED +certstatus = 0:0x05 +# IS_IN_INPUT_CERTS, !EXPIRED +certstatus = 1:0x04 +# IS_IN_ANCHORS IS_ROOT +certstatus = 2:0x18 +end + +test = "Old CA input certs, both CAs in DlDb" +cert = dmitchtread.cer +cert = OriginalDevCAIntermediate.pem +root = AppleDevRoot.pem +certDb = appleDevCAs.keychain +verifyTime = 20071201000000 +error = CSSMERR_TP_CERT_EXPIRED +# leaf expired +# IS_IN_INPUT_CERTS | EXPIRED +certstatus = 0:0x05 +# Verify !IS_IN_INPUT_CERTS, !EXPIRED +certstatus = 1:0x0 +# IS_IN_ANCHORS IS_ROOT +certstatus = 2:0x18 +end + +test = "No CA input certs, both CAs in DlDb" +cert = dmitchtread.cer +root = AppleDevRoot.pem +certDb = appleDevCAs.keychain +verifyTime = 20071201000000 +error = CSSMERR_TP_CERT_EXPIRED +# leaf expired +# IS_IN_INPUT_CERTS | EXPIRED +certstatus = 0:0x05 +# !IS_IN_INPUT_CERTS, !EXPIRED +certstatus = 1:0x0 +# IS_IN_ANCHORS IS_ROOT +certstatus = 2:0x18 +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/one.scr b/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/one.scr new file mode 100644 index 00000000..16622629 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/expiredAppleCA/one.scr @@ -0,0 +1,35 @@ +# +# test handling of expired Apple development CA certs, Radar 3622125. +# + +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +end + +# +# Original Dev CA expires Sep 7, 2007 +# New Dev CA expires Dec 31, 2008 +# leaf cert expires Oct 13, 2006 +# +# After initial sanity checks, we evaluate at a time after the +# original CA expired and before the new CA expires; we assume +# that the leaf is expired in all cases. +# + +test = "No CA input certs, both CAs in DlDb" +cert = dmitchtread.cer +root = AppleDevRoot.pem +certDb = appleDevCAs.keychain +verifyTime = 20071201000000 +error = CSSMERR_TP_CERT_EXPIRED +# leaf expired +# IS_IN_INPUT_CERTS | EXPIRED +certstatus = 0:0x05 +# !IS_IN_INPUT_CERTS, !EXPIRED +certstatus = 1:0x0 +# IS_IN_ANCHORS IS_ROOT +certstatus = 2:0x18 +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/bothCAs.keychain b/SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/bothCAs.keychain new file mode 100644 index 0000000000000000000000000000000000000000..40486135eafc2ed579d8e76175315019e6e5681c GIT binary patch literal 24188 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/ecExpiredCA.cer b/SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/ecExpiredCA.cer new file mode 100644 index 0000000000000000000000000000000000000000..74cbc5d09b1fc9acd855ed5c9f14666c39a2a1d3 GIT binary patch literal 463 zcmXqLVmxio#AvdBnTe5!iILfWn~hVe&7IR2 zf^%w7i9$$fafw1uetwC8k_5kzfq|K!fuWJ1rJZR})yasHZLHTePM8Udb*o!M`_-PWLd9 zW@2V!U|cM0AZWl3^n$D~BjbM-Rs&`rh3sZlkeeGBCRZ)enHTrpvyV@(X0PUXVb%*T zO?*-<{zyOBGSfQHH}&bpx$D|@XuY=G-M@%6+aUk%wWHsR=AT-$@sSPN+Rf38ue)PT zpGloxqrtP|2*WqG_^TUASTyY9l0?qdvAQVR>He-iyzCEev*V?d3(X~)SSQ+>SWds; PGhg|FWME)sXkch$XlZC@Y7m7Y0F;X|P&AY`kcAi`hG~dTYGRr} z<9q{NguRTc49tza3g6#xfL6vPVaZVxN{+!Y?I`CruyF|oBf(kAG=Y? z#LURRxLDXg(10K430YxA#{Vp=2F#3%49IR~1-ZGAp?%x0mbFKdyylDlF!inbZ@tST zb;XUO2^JjZvl`~kaViLW@FIEdWXBoeUw&xJ%70q7O7y344cEz|*B5+V$T81VVcw~_ z>>ghJ(y1mtjHG?pS8e3n(P$?7m21&op(za0kBj`TD+_Fu&pI!4OswtEt-sI3nu3bB QthYEOE&rLXx#(LD0OrlFX8-^I literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/ecExpiredRoot.cer b/SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/ecExpiredRoot.cer new file mode 100644 index 0000000000000000000000000000000000000000..c269fe3c29cfd28d6ae6ca7e873e5f948f888cf8 GIT binary patch literal 465 zcmXqLVmxcm#AvpFnTe5!iILHOn~hVe&7IR2 zf^%w7i9$$fafw1uetwC8k_5kzfq|K!fuWJ1rJ}4=$>||{?%msodw(QH@z$K1b?&%eh|rx%`?eLc z>m^HjR%xjAYNx8`L*p3p zY;w(9zI3(1t-{^ABMdkA@g3|_T6kOcpwX!uTi+#N^&8u2zjMd6GBGnUFfJB05H#Qi zhJ~y!BjbM-Rs&`rh3sZlkeeGBRIinIuAfk1!dxi5?_>EvpPwy799kiJGIr#;Z0p~B z@bbNBjsmAPv&e03_WB?5^Hg8Fec^_Lm`YaXqPxP{_xG>cy1?x6Nu|b+i_V97CwF`F zDzN{acZN^=o8^WrA2sC8p6Gq@_SLzBs@98l;(4#sJX~_+{+;f>yOg^C)v8W~y|8k!nJfdmYJ0tS{)0RwqMSp#W^F(R18 zI6E3N&Ntvi*vrVuz}(o&V9?mf)Y!{IhUmNtXOea9xPt%8{{=OWzpS@@<27?!%v z|FZGQ(d(PsZN9zz)*E9bbb@Jza`OknH$UgArB+-`VA-OcwxDm(mhyWgyTkWAVdr)RATH7pis75Av0Yus$QJlG|2O~eetpFd;eU*x4e RX`3C@tP){Rct%j$8UP+%t6Km7 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/ecGoodLeaf.cer b/SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/ecGoodLeaf.cer new file mode 100644 index 0000000000000000000000000000000000000000..d77ef42eb7ef39ffa786cfe8e30741800394890b GIT binary patch literal 463 zcmXqLVmxio#AvdBnTe5!iIK&Cn~hVe&7IR2 zf^%w7i9$$fafyPnqk)nHzmb7~nW2H9k)frbp{YR>NWc&%U|_^fe$i%2{v+v|j?#CsHal&cqHE%O%Q^Sks{X37 zCs(c<_g%Urr@Phr!r>$P9ybTxdf^iEkLBe_f4LPKq)zX5zPNKCn{1Qhe5U%}CY$}5 zPanHc%EZjbz_?i0K+u36=m}Y2M#ldvtOm@Cj10(bW(B#qkwK;^-EwaImOv5pZL*h6 zE0Gr2m%O}=|63}vR^=A8BYT(L0|3ZwuNwdW literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/ecGoodRoot.cer b/SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/ecGoodRoot.cer new file mode 100644 index 0000000000000000000000000000000000000000..9d4453e48e07342c36ad98096e767e8baa93b3bf GIT binary patch literal 465 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 afx4Cr|9Rv2@7`1S>4$$80EFX5@%%rzJJ(MD literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/expiredCerts.scr b/SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/expiredCerts.scr new file mode 100644 index 00000000..fb7213b1 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/expiredCerts.scr @@ -0,0 +1,147 @@ +# +# test handling of expired certs, Radar 3622125. +# + +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +end + +test = "Basic sanity check" +cert = ecGoodLeaf.cer +cert = ecGoodCA.cer +root = ecGoodRoot.cer +# IS_IN_ANCHORS IS_ROOT +certstatus = 2:0x18 +end + +# +# verify that each of the three expired certs really is expired +# +test = "Verify expired leaf" +cert = ecExpiredLeaf.cer +cert = ecGoodCA.cer +root = ecGoodRoot.cer +error = CSSMERR_TP_CERT_EXPIRED +# EXPIRED IS_IN_INPUT_CERTS +certstatus = 0:0x5 +end + +test = "Verify expired CA" +cert = ecGoodLeaf.cer +cert = ecExpiredCA.cer +root = ecGoodRoot.cer +error = CSSMERR_TP_CERT_EXPIRED +# EXPIRED IS_IN_INPUT_CERTS +certstatus = 1:0x5 +end + +test = "Verify expired Root" +cert = ecGoodLeaf.cer +cert = ecGoodCA.cer +root = ecExpiredRoot.cer +error = CSSMERR_TP_CERT_EXPIRED +# EXPIRED CSSM_CERT_STATUS_IS_ROOT CSSM_CERT_STATUS_IS_IN_ANCHORS +certstatus = 2:0x19 +end + +# +# Verify expired cert recovery for each cert (not leaf though) +# +test = "Verify recovery from expired CA" +cert = ecGoodLeaf.cer +cert = ecExpiredCA.cer +cert = ecGoodCA.cer +root = ecGoodRoot.cer +# IS_IN_INPUT_CERTS +certstatus = 1:0x4 +# IS_IN_ANCHORS IS_ROOT +certstatus = 2:0x18 +end + +test = "Verify recovery from expired Root in input certs" +cert = ecGoodLeaf.cer +cert = ecGoodCA.cer +cert = ecExpiredRoot.cer +root = ecGoodRoot.cer +# IS_IN_INPUT_CERTS +certstatus = 1:0x4 +# IS_IN_ANCHORS IS_ROOT +certstatus = 2:0x18 +end + +test = "Verify recovery from expired Root in anchors" +cert = ecGoodLeaf.cer +cert = ecGoodCA.cer +root = ecExpiredRoot.cer +root = ecGoodRoot.cer +# IS_IN_INPUT_CERTS +certstatus = 1:0x4 +# IS_IN_ANCHORS IS_ROOT +certstatus = 2:0x18 +end + +# +# Verify recovery from expired cert in input with good one in DLDB +# +test = "Expired CA in input certs, good one in DLDB" +cert = ecGoodLeaf.cer +cert = ecExpiredCA.cer +root = ecGoodRoot.cer +# Verify !IS_IN_INPUT_CERTS +certstatus = 1:0x0 +certDb = goodCA.keychain +end + +test = "Expired root in input certs, good one in DLDB" +cert = ecGoodLeaf.cer +cert = ecGoodCA.cer +cert = ecExpiredRoot.cer +root = ecGoodRoot.cer +certDb = goodRoot.keychain +# IS_IN_INPUT_CERTS +certstatus = 1:0x4 +# IS_IN_ANCHORS IS_ROOT +certstatus = 2:0x18 +end + +# +# Verify recovery from expired cert in DLDB with good one in DLDB +# +test = "Expired CA in DLDB, good one in DLDB" +cert = ecGoodLeaf.cer +root = ecGoodRoot.cer +certDb = expiredCA.keychain +# Verify !IS_IN_INPUT_CERTS +certstatus = 1:0x0 +certDb = goodCA.keychain +end + +test = "Expired root in DLDB, good one in DLDB" +cert = ecGoodLeaf.cer +cert = ecGoodCA.cer +root = ecGoodRoot.cer +certDb = expiredRoot.keychain +certDb = goodRoot.keychain +# IS_IN_INPUT_CERTS +certstatus = 1:0x4 +# IS_IN_ANCHORS IS_ROOT +certstatus = 2:0x18 +end + +# +# Verify recovery with both good and expired CA in inputs AND DLDB +# +test = "Expired and good CA and root in both inputs and DLDBs" +cert = ecGoodLeaf.cer +cert = ecExpiredCA.cer +cert = ecExpiredRoot.cer +# throw this in too! +root = ecExpiredRoot.cer +root = ecGoodRoot.cer +certDb = expiredCA.keychain +certDb = expiredRoot.keychain +certDb = goodCA.keychain +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/expiredRoot.keychain b/SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/expiredRoot.keychain new file mode 100644 index 0000000000000000000000000000000000000000..67ebd047e16d5eb3671abaa3cba8d9c34bf1aa0b GIT binary patch literal 23232 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 O>mJzN4+zJP;`x6q-srgi literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/goodCA.keychain b/SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/goodCA.keychain new file mode 100644 index 0000000000000000000000000000000000000000..1c216d4ceeb8bf74cfdfad212a75b4c8e762f9ba GIT binary patch literal 23216 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 ZytX8`d?0!4_~r|xXC8YA5RMTH9-{C9%5_5``is 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/one.scr b/SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/one.scr new file mode 100644 index 00000000..b11b232e --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/expiredCerts/one.scr @@ -0,0 +1,25 @@ +# +# test handling of expired certs, Radar 3622125. +# + +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +end + +# +# Verify recovery with both good and expired CA in inputs AND DLDB +# +test = "Expired and good CA and root in both inputs and DLDBs" +cert = ecGoodLeaf.cer +cert = ecExpiredCA.cer +cert = ecExpiredRoot.cer +# throw this in too! +root = ecExpiredRoot.cer +root = ecGoodRoot.cer +certDb = expiredCA.keychain +certDb = expiredRoot.keychain +certDb = goodCA.keychain +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredRoot/applestore_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/expiredRoot/applestore_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..9fec8a21cbed06e88bc03e781a609afaa5955e5c GIT binary patch literal 1746 zcmaJ>Yfuws6wPinfrLkdgrEYlzGy&5z6}J3f-M0o6bfo2(m*L8E@5TejY$BlIMvwV z1GUvM;3&3OtB#dAeV~X)p-`x{$iv6bDWg@;`oPu)qf(35T@c5}O!wE`bMHOhz31Dr zz|QXgcHZ$SE)2o&B(I!-%#C+O+M^%6ej*?H@hWiR3xY}#N*=pG5RbwmypfPl|U zL-=AiO^bO0FE$X0-F3Ky&=Mvp7)_*%a?Bt2u?ZKkbUcABu@qQsXbNsCqAmH@JfI#c zP%gnOE37D;ixyaM)L=vNY&NrXu0l~%R3tBCSgj1J+(@rbSj+}gW()-3SR@E%o4I1e z3-(yjV6~#5X#6T0PA$Wip*jOeEHl^$nnJbOWK{cREE*dFrg^(z0E8>U!04lALM0Q1 zDnnIjm0Az%kUu5{9(CA|b{UmimJ^7101=zyiJfBsGq_5vbkxutxUzW<2~Vv8SlHXlc*p&o>Ahz5^GBZ&duml~; zq*5e7;i%R|TW~a&%63uw|vw(OUt{oC_7+eV3A&9fP zu%%>sK=m0-)3wyrgcvw$$BeuB(mQ`|y~Vo^|NFCVd*G=S(kV5vZfbe>?xk_F@8xwr zet6lbFDg5fR~YxM=0N4(RsC0usaYouS4)2xPASW4sBGIZ>+T`=J<$`d+ZR4va4x&` zSJ!~b8%W&eQ3q2h1~we_6g90Mgqt3kzAa0%`jF4gqY~98!5Y8TwPD%2(uO*#Uc1?< zY5T1|S~XY`dMsnHF7X@Lt@}TPbBkIo2#JcGkk07L0YUKs%aPj4;5@GEX_3gf$~GSd zN4Q}w3)jRq_b2tPUKme(c~Y$iyE)%y{=RG5d!MFfw54AB(7N=}#_HX3m952lFSIWT zo(FRw4z%A6=KwpL1xQA7KMw>4M!T3Q$`5%(O}p4wV4eVa;--lhWt@ObxEt1*eqsa$ zoKgSzxg%0U0t>an55U`gl_U2X()$n9HEmlv7r3yMA_U>WyecrC4g8S^paP*)Se2qA zgf$`K!FXLFWg|n37Shp*W4MxWlAOtbIJO@}q5&Qdx4o*5rP9K%N|JKxb~WPDLiRIe)U7^WX=d87N* znJ0=r7*I6ycU`%@EANrg^vp!Ir&XYp&&Vr|tVQ;`gK+*~wn-kH2q8$PMYc709i{m}Da2=4d=jZo z+caG5TeEeuVQ=lC{90XEbK}l4%MW@C^!Qv!Zz`u3pY5y999eU^wqvN-xhkr7b&4$c iJN1^yP1{BqyKK?2-W$zoSy)@Rd-T&7j!<|M()|b5dP%+j literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredRoot/applestore_v3.101.cer b/SecurityTests/clxutils/certcrl/testSubjects/expiredRoot/applestore_v3.101.cer new file mode 100644 index 0000000000000000000000000000000000000000..78e8174fd34066eeb7414c3a8d85f441d9648982 GIT binary patch literal 1570 zcmXqLVv{pyVr5&v%*4pVB%tGQcQWtS$iAO8GefEp-Z~rbvTc;+SR8Oj^Tf+VMECvRlUUGh}eo;Z90x)EN4zw^ZgZNe-!?&&# zC8>ESz@Q0B%*jlFcrrNHMpy1v}#`z2_Oq z#J8{0TD3xZk+ijda=h@yyBs}!BDb0wA8+k>obgsA{ao0#HM5JSx!msR*?jFo;pD#C zg&|(AizBo83j%eR=TEy)P*eCd6#Gax(9F~6;l&x6t(mSui_VH#z)t+Ka4?d$xwzsyGuc90pBHEZ_ty%f}+dBI4(KLbmL^d2p5gr-=M1pDi9;-Fx3a2p9>n z!inupo9S*$aa2^i&%iUm(4(s zjWeOmgR$+06C)#3C>Q1yMjn<#gZPE93!)7o4Z;mV#W;Z(Bt2C>Ju}Tf(LmmSosCtS zkC{n|MWp}fWvR9`y?xn-&o^XU@sQA|meey)6;p;fEhj%cAJs`^#b7azNtz%R39={| zC@hgPkTH}pkN^q*^Qj;>dm1}C8X1^a=o;#pSQyBIlq$1G7>G59)L%|re(3I--5(4% zKRa9gVp?x(XbcP-XfOgjV`!jnpbO(0Ft#b8hf{uXaRG{}3`{`gtFq`CXv0H=g^`U5 z5pIm=P={X&tE*3Vh)A8Nmi_aMYrfgSOPs}pY12vrP4>?;2uzPz(}`=4x3KDeniI!X1qoxl|Uz?lz3 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredRoot/expiredRoot.scr b/SecurityTests/clxutils/certcrl/testSubjects/expiredRoot/expiredRoot.scr new file mode 100644 index 00000000..dd02f036 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/expiredRoot/expiredRoot.scr @@ -0,0 +1,79 @@ +# test handling of expired root, per 3300879 +# +# This uses two certs we got from store.apple.com and an old expired root +# which verifies them. +# +# The leaf cert is going to expire on April 1 2007; the intermediate cert is +# going to expire on Oct 24, 2011. To replace them just grab new certs from +# store.apple.com, or any other site with a cert chain originating with +# Verisign's Class 3 Public Primary Certification Authority. +# +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +end +# +# Simulate pre-3300879 failure, expired root in anchors +# +test = test1 +echo Expired root as anchor +#cert = iproj_v3.100.cer +#cert = iproj_v3.101.cer +cert = applestore_v3.100.cer +cert = applestore_v3.101.cer +root = iproj_v3.102.cer +sslHost = store.apple.com +error = CSSMERR_TP_CERT_EXPIRED +# EXPIRED IS_IN_ANCHORS IS_ROOT +certstatus = 2:0x19 +end +# +# Simulate pre-3300879 failure, expired root not in anchors +# +test = test2 +echo Expired root not in (empty) anchors +cert = applestore_v3.100.cer +cert = applestore_v3.101.cer +cert = iproj_v3.102.cer +sslHost = store.apple.com +error = CSSMERR_TP_INVALID_ANCHOR_CERT +# EXPIRED IS_IN_INPUT_CERTS IS_ROOT +certstatus = 2:0x15 +end +# +# Ensure that this expired root successfully verifies the chain +# +test = test3 +echo Expired root passed as anchor, explicitly allowing expired root +cert = applestore_v3.100.cer +cert = applestore_v3.101.cer +root = iproj_v3.102.cer +allowExpiredRoot = true +sslHost = store.apple.com +end + +# +test = test4 +echo Expired root in input chain, should be ignored in favor of system anchor +useSystemAnchors = true +cert = applestore_v3.100.cer +cert = applestore_v3.101.cer +cert = iproj_v3.102.cer +sslHost = store.apple.com +# IS_IN_ANCHORS IS_ROOT +certstatus = 2:0x18 +end + +test = test5 +echo Expired root in input chain, should be ignored in favor of system anchor, Trust Settings +useSystemAnchors = true +useTrustSettings = true +cert = applestore_v3.100.cer +cert = applestore_v3.101.cer +cert = iproj_v3.102.cer +sslHost = store.apple.com +# IS_ROOT TRUST_SETTINGS_FOUND_SYSTEM TRUST_SETTINGS_TRUST +certstatus = 2:0x310 +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/expiredRoot/iproj_v3.102.cer b/SecurityTests/clxutils/certcrl/testSubjects/expiredRoot/iproj_v3.102.cer new file mode 100644 index 0000000000000000000000000000000000000000..3ed890b9d9a6ea0cc02bed7a23189c33f3d31c2d GIT binary patch literal 565 zcmXqLVlp&nVw}aq%CwMyfzg1MjZ>@5qwPB{BO?0D~wX*V53)7>G_GwiRS!BpB!%WdfTKI+Za#vZ0~d4;+gu> z?%m!}H@%a8RAW~h*YBR)pK*T6oaqt=eBaC8T;H_$S;~%wE o^he5GRBvgtjr4>!9hy%f#eSY+U;F0e-CLIoyZo=+crV@y0Pq6NtN;K2 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/gipCps/gipCps.scr b/SecurityTests/clxutils/certcrl/testSubjects/gipCps/gipCps.scr new file mode 100644 index 00000000..86185ac3 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/gipCps/gipCps.scr @@ -0,0 +1,28 @@ +# test verification of the odd cert from GIP_CPS - it's an intermediate +# cert in which subjectName == issuerName. This specifically verifies +# Radar 3374978. +# +# This is suppoedly a CRL signing cert, and ideally we'd actually use +# it to verify a CRL but I haven't found any CRLs associated with this +# organization. FOr now we just make sure that the TPO can verify the cert +# with the associated root in system anchors. +# +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = true +end +# +test = test1 +echo Verify the GIP-CPS CRL signing cert +cert = gipCps0.cer +leafCertIsCA = true +verifyTime = 20061201000000 +# verify leaf does NOT appear as a root (even though its subject and issuer +# names are the same.... IS_IN_INPUT_CERTS only. +certstatus = 0:0x04 +# ensure 2 certs come back and the second one is an anchor/root +# IS_IN_ANCHORS IS_ROOT +certstatus = 1:0x18 +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/gipCps/gipCps0.cer b/SecurityTests/clxutils/certcrl/testSubjects/gipCps/gipCps0.cer new file mode 100644 index 0000000000000000000000000000000000000000..4d9d663b0a7609c1705b0813fc419d58a04a9773 GIT binary patch literal 690 zcmXqLVp?a=#5ipMGZP~dlc0ftfguo?7@8TFSO7T;2E1&XT5TR}-+37sSy>qjYW;3>rI`8XFmADlO<_Q?kC?EtSHuo2@pwy!m#}e%vj@gTQ zcytX;emHqg*ZqE5=k9Z|_kFG|cZvD7S%z=&${kzsXS_eF{Ob4P%O#Fa9cTEca62+F zGcqtP&NN5|ds~*Dk?}tZ3n=6aWP!mT%f}+dB9if1#a7$3i1VEu(-AS(DGiLb)g=t% zLDI@B5(Z)oBF|U+?X~3;o3`#xX|nnR<;u9|n_CP-K?)RD_zZXqxY#(f8mk!Hnc10< zLjoB3%uS4p3~6en-rrVaE}ePq@hR~Q*Sf{BWUHjEF|Pb^OWy1ApKCQ!ysl+GH(USv zRnD^CTh3^e&ua6U>zn7HWt5(Oq47`N;s)`nvIk{1CO=&IkG0P5eK*ffgRu3Ryx$ow z>VCv@;ii#z)}Adkt3OqmC5HZyIPRHk9bMbgksOl9+1LCzJ^gXTs}C^`6YsF)ZJruq z?{R!CkMV1!4Q_ff(|Oz=S;iFd}R|?)y`@E|C#=usj~QdoX)NO zR9ng5o1#96o}AiS9gfZWvO~IH&bc$b&yzj=<=%AsvUQ0v`)g`w|5gKF+3wFG{`uq`d#9 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/hostNameDot/hostNameDot.scr b/SecurityTests/clxutils/certcrl/testSubjects/hostNameDot/hostNameDot.scr new file mode 100644 index 00000000..97012dfd --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/hostNameDot/hostNameDot.scr @@ -0,0 +1,65 @@ +# +# test fix for Radar 3996792: handling of host name with trailing dot ("www.apple.com.") +# +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +end + +## +## common name testing +## + +test = "CommonName in leaf, no dot, no dot in app-specified hostname" +cert = hostNameDotCommonName.cer +root = hostNameDotRoot.cer +sslHost = www.dmitch +end + +test = "CommonName in leaf, no dot, WITH dot in app-specified hostname" +cert = hostNameDotCommonName.cer +root = hostNameDotRoot.cer +sslHost = www.dmitch. +end + +test = "CommonName in leaf, WITH dot, no dot in app-specified hostname" +cert = hostNameDotCommonNameDot.cer +root = hostNameDotRoot.cer +sslHost = www.dmitch +end + +test = "CommonName in leaf, WITH dot, WITH dot in app-specified hostname" +cert = hostNameDotCommonNameDot.cer +root = hostNameDotRoot.cer +sslHost = www.dmitch. +end + +## +## SubjectAltName testing +## + +test = "SubjectAltName in leaf, no dot, no dot in app-specified hostname" +cert = hostNameDotSubjAltName.cer +root = hostNameDotRoot.cer +sslHost = www.dmitch +end + +test = "SubjectAltName in leaf, no dot, WITH dot in app-specified hostname" +cert = hostNameDotSubjAltName.cer +root = hostNameDotRoot.cer +sslHost = www.dmitch. +end + +test = "SubjectAltName in leaf, WITH dot, no dot in app-specified hostname" +cert = hostNameDotSubjAltNameDot.cer +root = hostNameDotRoot.cer +sslHost = www.dmitch +end + +test = "SubjectAltName in leaf, WITH dot, WITH dot in app-specified hostname" +cert = hostNameDotSubjAltNameDot.cer +root = hostNameDotRoot.cer +sslHost = www.dmitch. +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/hostNameDot/hostNameDotCommonName.cer b/SecurityTests/clxutils/certcrl/testSubjects/hostNameDot/hostNameDotCommonName.cer new file mode 100644 index 0000000000000000000000000000000000000000..ba06417af0975c353e2b8049397da1e5407faa71 GIT binary patch literal 564 zcmXqLVlpsjVw|~vnTe4Jhzz*dIJMe5+P?ELGO`+&8A=;SvN4CUF!KlnC8i`6DHvN? znweV~DHP@Bml%p0h=L@!c=#L(3UX2vobz)FN=s6U4CKUl4NMJ;3@nX|Oihdpqr`cQ zjSS3;%%NO^I749rL5R6r<>lpiDY=;?$r(7!Gt@KC0jcKZQAKq{a(-@Zex5>JVs5HJ zPHJMBLSDW?N`8q!<9q{Ngg+Qr8JHV;84MabnHn1zK4m}8n;Gb`eC^3M*8LpkRe$O* z&Qi-)pZ7_m=lzYwCGzKGZt63Z@`UJ0b3U3R;vDll;{SzhU;dt7@#=JIqyEw7Y;}Ft z_E>My*ncN(wnDG{`UcOY5~*qI+Zz5Ct#}%$kznm`rohW2@7KyQ?UkSR@PFfWSv-aJ z)~J!sb6Vw+!gc(;kxO5szc6`>o}uzZ`- zRh@nG%;uAe{WDH$U!P)WRIs3O-+7-cjnCJFXc~Qb*3I@LP*7q@Vv&Ne zrKOph&@@V% z*VxFw%*Y(dHHa}3F%W{7%Uxbxu9uRVS(2QghtohqZ39h^a&8_aRA(gT=jP_;DdZ*Q zrYhv5CZ;K*(%y2%8tC77TNP>AAiil+H*2`^C<_TO=ZnUR5Uv4(+~0YA_~vcimv|5;cKm>C%v41_@fsw_MPTx=ZLY>cd| z?97bF9$^J}q>*8AdWyL&?-8?-1FV`M@h>d?&bYh3FGujonwMwHxfyLQ-_tNN|7#-6 zAo*_3-tOXXWtlfK_y5}4+2XrDU;f0q*q<}L1%H^yZguaF+rz2eJ2Tw<-~Zl~FiYKY u-Id@(*YkhAiK%Z}yz_C&&oyBR6|ZXAlQz4H_e)vz1kbv(_|72%20j3jgThV# literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/hostNameDot/hostNameDotRoot.cer b/SecurityTests/clxutils/certcrl/testSubjects/hostNameDot/hostNameDotRoot.cer new file mode 100644 index 0000000000000000000000000000000000000000..093acc832d545cb5de0415e6be68e35b91ac9a0a GIT binary patch literal 503 zcmXqLV*G5-#2B-HnTe5!iIKs8n~hVe&7P*7q@Vv&Ne zrKOpB2)w^1kK%W?x&@O@3^XD#}sST%{QI$FH@~`0>)di>y;86+QCJ`fEPr z#qJMWulrRye@Wb0HfbIcZ*J(pSH6!tRc`A?zL>h~`}Zf` zuW)Nvx;XEH<-5yF%!~|-i-ipY4fuh9A}h?u_@9NFm<-^%4E&_ azjl{*Uo4ZDGSzuQ$m^W7D$++xEfN7B9lXQ< literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/hostNameDot/hostNameDotSubjAltName.cer b/SecurityTests/clxutils/certcrl/testSubjects/hostNameDot/hostNameDotSubjAltName.cer new file mode 100644 index 0000000000000000000000000000000000000000..77c155ef481b907ca30d62779f108e7cc54798b3 GIT binary patch literal 571 zcmXqLVlp>qVqCC*nTe5!iILfWn~hVe&7P*7q@Vv&Ne zrKOpx)GSJz z*VxFw%*Y(dHSoi!)zH|$5M(Adj~1$h#idDEjyWZMiMgo?c_1PuH8D*gFJB=gzr>(% zz5y@7-HfaZ%#FPa292Fejg1UfKVG}&zV;=%k8l4Lp=zT)Q>tYBUmFIeb7~jP-;)&j zWk<8R`k5>9GaM@R2hOj)8+Ui@rrwn8hYp;a?-~)|)tOQdGMR6$%N5sympWAUubt-0 z@?xFZo0ZGIiR^ni*_37Bi}u-1r^@DXew9&UPDoch!_d2SZ<=3f+)41_`IR9Sco zxY#(f*%(<_*_j!U{l^OOUn7HP+ov^5C#*#|h5U02UkEA8)8p7~|4sI!>;F$LzkS_) zdNIcpcG+3CQ^FE_5{iypGI36sBq)2K!o)c+>}~{ zc%z%n{_M}+sqJ_in{2H$d&1!xhbuoV(EP3w5iGv?S32*{_xma~T9tYQ2fjIZvJ3z} C^28GW literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/hostNameDot/hostNameDotSubjAltNameDot.cer b/SecurityTests/clxutils/certcrl/testSubjects/hostNameDot/hostNameDotSubjAltNameDot.cer new file mode 100644 index 0000000000000000000000000000000000000000..abf2ad97827675bb495b4dae7e6975c6e21585b4 GIT binary patch literal 569 zcmXqLVlp*oVw|^tnTe5!iIK&Cn~hVe&7P*7q@Vv&Ne zrKOpp&>%{j z*VxFw%*Y(dHSor%)zH8|4`e1ck2c+(dSC%u z7dsf(8Sn#rB`eIx_@9NTNE69V54AXwD*>A5fGxmUZiJ!XgbsHBWewH(Pw-o$8)LM3LYPi$q z+ZvB$7rX!M(c?VzccSZg_4a^5hYL5K{M+q&Y)0}@-!jebhYL)Pna}+b^!Kd8n$G{+ z7XNoGj(+-ETwtzRt4C(c7XJN#ll7eoe7?7T`0~z#^PZQEh1-cMo@zg~&6^#z8~_Ll B#<&0g literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/implicitAnchor/CA.cer b/SecurityTests/clxutils/certcrl/testSubjects/implicitAnchor/CA.cer new file mode 100644 index 0000000000000000000000000000000000000000..9199a301ba33b94a9c071ca5cc2cbdab533e706b GIT binary patch literal 523 zcmXqLVq!OFVk}s|%*4pV#K>sC&Bm$K=F#?@mywaxz|m06K!uGtl!ci`wkSWpL?JD| zNFg(~ASW|9vqT{=FF6CqFG(#fF%<1*zlW;d3k~$VpXj&d)6UPChjQ)2@t*TCLT#Xt#Sg|xFH85T6oH{eCMnUR%&xv`hQps|ywv5{eJ zbQ#|?bA~xz^Uoc3e9#ng?WUx<;qQyT=Dl9?^tiNPlD-K~pz>Z@_jOwvzojhCv|M{I z?sC`W6RU1 zbR{A!p6P5=mYlHb`qd3*8th&_I=cM(!&fIaO?=G6%*epFSlB?&fFI~ZSz$)T|17Kq z%s>j+&8#3dH!@_@2dvNdF{S2!>BW8ia>J@e@ov@8$wl|N6%9J) zoEEEOD|cd!iWGmseq3*Yq1*bzDAm84=kMZQxLbj1$}Z6}yNYXhC+|^PVRCGn<~4nj t{HwFqBxctbs&+rJ{@3@{)_Oza-0vQlMYiWP&i#_g5D5OlvhuHkDFFX7zykmP literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/implicitAnchor/implicitAnchor.scr b/SecurityTests/clxutils/certcrl/testSubjects/implicitAnchor/implicitAnchor.scr new file mode 100644 index 00000000..ddf09f0d --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/implicitAnchor/implicitAnchor.scr @@ -0,0 +1,35 @@ +# +# Test CSSM_TP_ACTION_IMPLICIT_ANCHORS, Radar 4569416 +# +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +end + +test = "Standard verification with root in anchors" +cert = leaf.cer +cert = CA.cer +# IS_IN_ANCHORS | IS_ROOT +certstatus = 2:0x18 +root = root.cer +end + +test = "Standard verification with root in input, expect fail" +cert = leaf.cer +cert = CA.cer +cert = root.cer +error = CSSMERR_TP_INVALID_ANCHOR_CERT +# IS_IN_INPUT_CERTS | IS_ROOT +certstatus = 2:0x14 +end + +test = "IMPLICIT_ANCHORS test" +cert = leaf.cer +cert = CA.cer +cert = root.cer +implicitAnchors = true +# IS_IN_INPUT_CERTS | IS_ROOT +certstatus = 2:0x14 +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/implicitAnchor/leaf.cer b/SecurityTests/clxutils/certcrl/testSubjects/implicitAnchor/leaf.cer new file mode 100644 index 0000000000000000000000000000000000000000..88dbb9aefc7f5a1dfe4fcebab6016e16fc76b746 GIT binary patch literal 523 zcmXqLVq!OFVk}s|%*4n9L^LMdN$}UWA(&Ss9ocdl?KGJDD0A84hnL z6t7=d=*7C^%;Nk!pXTsKe$Fpmtrp)^*_1Fxdi`aGZ*Mjp)QYITnCb-|M{k`arpduS?WEFyLms*h_O#DpXJTe#U|cM0AZWl3^rWmXBjbM-Rs&{6 zMh0Xzvx3~*$iNp7t!C+SvBL4qXRFWt>W@NA%VueAd-894x_wpE1rc4#Z>pW)KSOLh5LOaXKs!XN+u literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/implicitAnchor/root.cer b/SecurityTests/clxutils/certcrl/testSubjects/implicitAnchor/root.cer new file mode 100644 index 0000000000000000000000000000000000000000..de72763fd4aa5bfcbd79c3c58a3769b1362cf823 GIT binary patch literal 525 zcmXqLV&XJtVk}y~%*4pV#K>U4&Bm$K=F#?@mywaxz|m06K!uGtl!ci`wkSWpL?JD| zNFg(~ASW|9vqT{=FF6CqFG(#fF%<1*zlW;d3k~$VpXj&d)6UPChjQ)2@tml{?y&NtvixSElbfw{4l!Jx5|sj-pa?8|@k=XqDlxqbEQ z(bgE4n4j8Wm!`Ao9$=YPo|kcc#)tPB zA+C2G@nj!~6)5xF)24mgY%vovBLm}NVFN(}eqi{>3NtePXJIv922#jwW(B#qkztj^ zj7LkqR7|+D=kCp_Rs9*Ara~`%v~x87&8=IIeSMYOr|sEoF@b;0wPbAh8M_&^mh|mR zT5&e?*6Epsi$zKkBMVnnZE4@q*7wmMZl2SD1AS73wG%QWm@2MJkg=QfKwz=>15WiV g%S4k?GM{bnXBVrSoIES5tMX68Ik$=_C5~Z70R%0&k^lez literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ipSec/VPNTrialCA.cer b/SecurityTests/clxutils/certcrl/testSubjects/ipSec/VPNTrialCA.cer new file mode 100755 index 0000000000000000000000000000000000000000..65c03709789e346d0b4b7e9dd68a9a33bd9886dc GIT binary patch literal 1156 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 Wy?N!o@W_!b?9HL4dS{qClLP>sR4tGI literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/localTime/badCert_3 b/SecurityTests/clxutils/certcrl/testSubjects/localTime/badCert_3 new file mode 100644 index 0000000000000000000000000000000000000000..e1e346cb70df06b1c3aa28c3b71f091e07afdde1 GIT binary patch literal 805 zcmXqLVpcS0V&YuD%*4pV#K>U4%f_kI=F#?@mywZ$mBGN!klTQhjX9KsO_(Vo+fd0s z0mR`FmULDNSMcx-Q3y^=E-gy+OD$1wc2o$;&o41h6Bo3!G%zzZfB3eR;+Dh1XS|CZm@|6#o-2A7Gx_r2pObi1-g}&L*E+p+lGUnf zQ#XB*oM$(+raytHWU`n>=0EFqu@#eLs%(^BCR*kkHPDrBnZ#Q7yyT#h`%8n3i^X}& zlFtWRFj~>R)FDYk(Bk(w{a)h@-7otJes7p}JeK+0x2L^DHYfIkOgevR!u=Ds*Ry_n z9dPO*>l)TAjH1)NzP4DH`Mufsh0U_qr8>J*#Pomj85JxOx;E47d$#oA=YNh%pSYo4 zdeLPs<4qspb0ERCkLz;<+uzLH$CAr=n@taN>vZQ?Gvc5Xk`OF`$j7ie(Im!-c_&F5K zcaUXSzc^sK#2@Bsd1r1e<=y@D?ZzO7Y=*R#r+QzS-IJI7pBehuoj*=k$XwBE#}Aba zZ{jq*-dwzbyX0nrFW;4<({GH9gaicN2x%*hRJgF~{xOY5p`6pcOMjcY<8<#819tt3 zvgsctn$}%%^xtiHG3DsA=-wNwrHzGWZ53LctetCd<5e2Z9?2rD69&O&suboX|IvQy zc84W+E8p3*eNVKHyzhUsJ19-ndYatBB~5v+m(MxTvgl2+W{%LVaP@}M{2S^@AHQ6p bUB_&dXYt_86~{m41oy38_@FLz{#geASp7f~ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/localTime/badCert_4 b/SecurityTests/clxutils/certcrl/testSubjects/localTime/badCert_4 new file mode 100644 index 0000000000000000000000000000000000000000..384fb35d8194eb7450cf37227b52993e3b740c30 GIT binary patch literal 751 zcmXqLVtQ@R#CUlDGZP~N5E<~YacZ@Bw0-AgWMpAwFfcXbHsEAq4rO5zX3EGmR5MTk zakzwKoz=n>JiJ2`f>V=Ai&FhkOB9?P6@uNJ6@v2fOAOS+1uZQN%!~~nK-&;Viwhc9 z8X6dy8X22f8W@0u$Thx+Q3=_hjI0dIO^o~uK#y=SH8Cprs?_}lr}pS8sr<}T+AFm-@Ok0)tz}m}+nulzyx?0sQ%++0yt8(R(yoHu z(Q0=zZ5Vt7Z^`!0lP|d^>afS)B>(*%x-~a?=Pr0Kf5Un8g!2}H9PiEaYy8Y))tHul zxf0;q==u8Y_Guyp$wn8M&noUQpD1USx=yU=n`nY}p!Kw;k}nQ@U&h*KwW3}k!mj*q zBt!F;ua%w&%k`M;82`3Dy1#H%=gl7}T-q&XozJS8GQ=6Al`K5YQM$%cz3KXfsit|d zGaFt{TA&+s&0_afclFg$XZ8mNA9UN4|KhrDxZvFlrXKRE)n0}1?%*=mcAJTrk%198 zgn&^A3?W7a_o<>cUZ%}{ac$wl{OfgnHaE*>_&?}Mw>T54C-6tCn5Ada<(+%;a_1k< z+9T|vds+C?_gwogQq!-tZC^jrGt?$dz0bg|Qe{@PL{dh8xs|5lstd8H4<_H4KhM{H z%Dknz%6F^V#HSu;2si8XKe*3gofHFZ_l+Sk>W7Pa(P%LGpeCEhv8TXUu~ z?~W@d*{;CxV=0fyqjKq1yST`SX=1aBjGk=d5IEv-JXXxzs!@Eartq9^DfhcMjLxJ? zsG6E_DoN@2ac6IKZY#qF8r8ZQ-;K6R2%KdlufW>zHLh>PM3z@qzZgj}-e#K<5%Tw| VjrNt?fcX56YriX>|6}TO5&%b2AHVKyGGnazK7g zW^!g~aZrAKiJ`cGC`gKnhtIK~ASYG9IX}0cv?R62Ku(<3z|6qh(A>zt)Y!-%N}Sga z#5DnP4Wr03wQ;@yFT!n%tPISJy$lA8olK354D0#?)zXtIVmk$mo*Di+>Bwwl$uT)^ z($9dH^fha5^03ZxoTaB1(6!?3H~WLH_HJ}Own#@riE+x=ys|?bzaP(PJ$lDmA88^ zMu+N_e7+UBOw5c7jEjX01P%CsK_V;6$oQXy)qojDA-kCs$0!|eiW`W6q_}wa9199^QWc!@a|=pKQi}}a#CZ+O49pG9jSNgp3@xL?c@05a z6DZd}(~!@A2VyE~UcRe$C~l(~=Ns@M9K^`Vz}(o&V9?mf)Y!;y&O4%~K;uyJBm;>z zv#%sIE;zK>k1zbd-AHAZJd>*`*CWI42RffDbG|t>XWvJM^~KwR%%9&WwRQd*`cvNi zbDpo@OI@Lxi_X}pi3`mY(zG?5_vY2T1*_)Q39r0rmuus`YpUjo?MK#2U;IDsyxQOC zAB6ayJ@S%#C9zBH{DZPrGDnk{m>C%u7YiE*8t?->BP-0v_@9Nz5plP|9mNOLn6*tt{tWKc1w$woB?e%gp+UJ=>0CCN?quW16<|QA(j- zip9$6rwe+wIKOU|5O5Mz?);PS;$q^y*j2425C1FgIl;$~&KqI5)oy3Yy=xguxhi+* jt#oaka<sC&Bm$K=F#?@mywaxz{F6}K%9*^l!ci`AUCr(IUqkL zGdVN0I4D2A#8BKo6ePvP!{=B~kdvz5oS$1zT9R61AScdiU}j)$Xl`U+YHVr|CC+OI z;+jCYD5e&r7U!21C8q{wrsw&jCZ^#wwQ;@yFT!n%tPISJy$lA8olK354AYIZ*q>yD zbFVluqq6+Lk(Zk#D;K`?$!u*e5KYw0sb0Oe$mDa;zx)?bUboJzDt^RnbbRGj`S+T$ z7G8CYT)g^aO!+F-%HPIm46feB#Zw<#HJ)M4KKIhf?=jm!R~i|Vw5t=ZR<+0m?4BK3DR3mrEaOb=ncoX_LRggM za&~|C!z?&!XX8G`$S*|))y}`}j}Oi}xBcs{n=`)NlF6<5Txpnn*~rQM_w@*C)%j;H znx?lbE#Vk7b#vn5%$aSamgwc3jw*-%)U-Fb#^Z6yPw$> GuL1zpLAR;^ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/miscPolicies/rfc3280CodeSigningLeaf.cer b/SecurityTests/clxutils/certcrl/testSubjects/miscPolicies/rfc3280CodeSigningLeaf.cer new file mode 100644 index 0000000000000000000000000000000000000000..44b18b39cf5d96d87b276f91b859829901af8a37 GIT binary patch literal 526 zcmXqLV&XDrVk}<3%*4pV#K>&G&Bm$K=F#?@mywaxz{F6}K%9*^l!ci`AUCr(IUqkL zGdVN0I4D2A#8BKo6ePvP!{=B~kdvz5oS$1zT9R61AScdiU}j)$Xl`U+YGPsEVU}mBD~0xVv0o}wUvVL+!-;JfPe9wpupKWZ z1i3NSJooJu&#&|NGI_$R7cM`~iy5mPw0sun%}}}YM(tGIf-`m>89wqT_Ir9Ne$sJ$ zcGCE)kHXC4=hMRvtvx8Io6Rr#Gvv24)5=1xGmj5V-nRN{CKEFw1LI;112qGFpzmab z85#exuo^HkGBOwlg9KDrcnrAMIJDUqSy|bcnUOuh3i3!J1LKu-o|A87+eKJ)ld0O1b09RL6T literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/netFetch/JITC_Class3Mail_CA.crt b/SecurityTests/clxutils/certcrl/testSubjects/netFetch/JITC_Class3Mail_CA.crt new file mode 100644 index 0000000000000000000000000000000000000000..f537ab66e3e6721f308f21a04ae7986fce6bba69 GIT binary patch literal 1055 zcmXqLVv#mzVs2T$%*4pV#K>;I%f_kI=F#?@mywZ`mBAp(klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq=Y2ltFUL!ZKc-AEagO#LOI! zTN>vhhXf-l19M|9gF#~_Q)45;se6^`We!<)>$zZZS`&<2!qBfv>Q&CF7R zoXp}9>!i%Q#G*?TG@cvGYbh#fm-O4Jk@EhXpro~+_jGY_GKI5!h z_qEUZ>pH}@ZaD}zCnA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HPULE;5?dm5@5D1+pfg=M@vL!1?W z3KW3C3eGu+#l;H73PJh#B?``t26E!O1_lPkMuvtKrWPg!QR2LYK(3)BluK8)G|op3 z2}V{1=EhzIgT_v##zuyV0S{UvyZeQIq}2bddha;niP^29EcV{xS1p~Ld@%RQTC#?+$+PDZU0Kk3(?@He7glZly;fpM|E zfv$lpFj!^zSj1RFvgiN!X1n3VD%*}v$+8OX@8n3A`x)?nq=i{n4VW1j|0DYc7_-bk zk4*W*WF3A)^iZ6tkz>Dl$tCI1=5fnG`^mk9gwrL9bs-e%F zcj>PC_HX}#$!W*WOnEUolh1J4pDJ%=M!htPX*QkvqE@Usf9V=e>LFc~-ErI6r>X8r kVt&#r-nMXN>cKm#x>M}?r(X}2_I~%^gX1>2*02qa00)H0`~Uy| literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/netFetch/c3MailCaCrl.db b/SecurityTests/clxutils/certcrl/testSubjects/netFetch/c3MailCaCrl.db new file mode 100644 index 0000000000000000000000000000000000000000..52ea1431b59c4e7081e78e9070d6964db812db1b GIT binary patch literal 45988 zcmeHwd6=D5k@vmbeS1k~=_H->UAyn?C4wT{wHH7nBrQZp2Us^-*jm2Yfb>QxFzs2sj96#G|9}$Z++#icAe>@f&x)=AO zvDnC2vDneyiN%iH7>nJ0GyZ))=;RXmO3H%iK{^jTaEWz!M zf79riQ#Y;Mx^c@1r>tAE_2kj#9Fp&F~MG(tS8CY7wZt+q@OJ3j9PJI>zYlcI2Pf@wX`4q zi{m~XKeBkn?JhpYUkLnK+>b!z__qc;H{iJe&y9F)#B(E_8}ZzP=O#Qi;kgOV2|Oq8 zoWOGe&&_yl#&a{CoAKO&=N3G-;JF3Qt$1$5b1R-(@!W>zHaxfCxed;W@Vp4mi}1V{&x`TA7|)CGyadln@Vo@iOYq!* z=MFq~;JE|Oq7!$`wVh`IE#a==9>M)A++s&^iJizrow}d(@QZ!OW&ARi_3(3E1AgJH zhhO}XT-LtWd_DXN9Cye+-`YEr{@Um8i$3dVAAZwa)_>7wJ^YL2@QXg9@=Kf2U-@b6 zi$0_B%Umy;!!P=b$}e=w=kSX@qw>pKON{gTFZztiFLS+O4!`I#D!=G%Ndzc${=376~Pr2s$AF+pe_~-f` zv4?v2=lUP9hkE$u`X8}}didx1AF+pe_~-f`v4?v2=lUP9hkE$u`X8}}sQmN!pG+P6 z^Z6gd#K`T7ozL|@xjOh|oOAt8cOCrm`JbLT_~-LK`8xRL^FM_;_~-LKy>;-<=YRU@ z;GfU`^n-tHzB-@(5kDu_T>mowtRDWk{%2L4{B!-!)9U1(>wgZblYg%NIlNB(x&G(r zb@I>kKhLO>f3E*Iq7MG~{Eyg5)cK#!{~TEd|9t-Es5@!sIEquf_c+)B_u9 z*@ycZsC(pb!-iY$M$H4hyzLC!x8VLQY91%yeh2QKpxyzV_RCrKI1KfU^KswLng{q7 zfq!u;ZnWv@9gm_!0iGq`S%P*t&`!q`ZqO|S-O@8~qi;*m&a&fiUyU2>EHC1I4eswC zHA6d{v$*ern@i$87dQA^-1~7qiY-_bH+Z_hlSDg7w3GYS$NdYG%Br~c;Ra70 zJbAQ}M>~Zk+@LGmjQjCetoK;lXs7oP%pK_ZW@E9~M%;3Vt@xMtYw=mKZpC)xTCYEX z|1a1yF*QCrxodjeT8D{kh&;2qfDpeNN}jd7(By3x-#I~MktcGEhVVh<39VfR>z~BO zdgK{x`|8=*naOQ?W+!yO($*Qcq31~Qwt!A}tdGkBc{1SV?3&p*E>q(E9rNbmg|#iX zT=VJiG~gmr#wFLH1LP_u{}-7OTkDZ2W0Pyi0Wx*`B1>e7U#mx^#lcYKfn%3BhmA*) zDK_c1J>Q(40vd_QJ{=zC)#Wsgga_K zt&hS#-<*g%scF?C&uHhSvGd}67tTn5P;@9AsZ;Yqm zUqz0swZ&t5w(Xvn**m#?A}|<{DSDGyh4ml5x@$g}qBpDW3vcVm6Bn$R8sEJezss}e ztrK??S)wI$%MP3WWx_5lmty*~&y(Mu+k!5|8c@^FTu-(bCC&#x< zIdKk?zDd0;iahI^=t$%xP8r`eF@;}n2_`ltwYMm;#O7p9B_4>Z#jDRdZ)#Hg$ma2L zfP`})^|&Z9ZM+f>+<3+2W+ujGcS(k-@?^YO+)?D&c-ufP@>(Fz7KA*@c%@bsMV5_M z;(_okf~>L0S4^y%K4Ef}wr4V>epio7i3!5nF?#md6WeDe_fAkaaj_Yx=|z!gI$TKJ zwz1jqnOS&wH5oV0qQiVdd8Wffl-DvkEiuDMv$a-;D9idLu|US#Ha0Q6ds4=W2VADV zUi=|4OW0U7djJ5F{j^FFimBa(#ZAQ4BJo^It zrq5y>!HXWF5$yM#&|lHX22yjrXZ?38|Gvk!Ry= z1HGGzd2)&2h_YsNe5+~Ft>rlDGnuxL_CdwQfESFdtQI6^AP`QM(6=g2XHl8Y%cuqulW*bp*i4!Br zG`$@xmyo<9%2-Wrhsq^{Mq-nHmGCfME+O_Wm#nGza*5{xk0MLvKx92tE^%^1c`^o( zC;gIpzFb1`rh5AJRJnwVA&NZfo6MK=ZN6M$Lqu7oH)&U79W0kPHKIK0+o5uajS*#? z20EF8D7l2tM$w&(_o;G;O%dhUc-uhl=3<^)Vl1L88*h|cLiQ$6#%nU8s=oDor;=`Tty@%)G~t&dNYOPm=|p7n7l=tX~r z$|YV9QKrqwp>l~A)+y^yxx|a=ly#_F;>8hVje<^ecCcJxYeYGwt3%}yXGN4{w((TC z#CSw`W*bp*iER;On%)kUOKguQ$MklnTw(`giU0Sn5+0tEOYFlL8lE3MwCUpxidr}Yr*DoCwFf-Z-*7EB_|NQy`(;Q z?o5r7w_)P^**WqgZ+&S*d82M#_sqz6L|)^TP3!O@7^lon6#a9Y?yQc;X@h-i*t2sR z)#hYNeBK#R-f7Y=p4}07i`Py}&5j=^RB*{zZ~o5g=Y-*Ur0%-o5ehvT-jCv#B1JrIlS!WlN9*>wwk%9@p2 z4cD~P&E)4rxG%;1dOp7szyAUB@FlxMhP#RvPajjfc<0T-q5h>asETK zTrLe&N6vKMV;(qID=GLZ53JRS3jSvZ7KdwP1%K{=Lk9lL1JN_3d^7+{wUOeWf{z$j z8mSIfhZX#;4;HHmemexwBX<5<9$2jnIm&_GI*xDIuv{+F6yNKCrHY#3z*ihtDi4-MYPFIoWI!j5 zV1-(Gcfek*lx^O1HXWrbBelAld`gae;EQ2H=)0<}Ul&5DI9x6jt3`H6=UrqDm4+*{ zy3Ymd0LyA%{kl4oy-aY`yV!aK)>$^2zs3j4+ED*bR3=)-Y;fNDe{3KWGFYN{e_Fxv zNU2&X7CFUl4`r4HtJkE6mj=|lNm-&SFES5^8YH@@k>i-5C8Y)*xWjfUXT^(evYD0a$_u0*C z{v}|C12PNIbtLR?sWzJrhLq)zGHpp07b(lyQ2zrVWo?iR4d^;@ny(Jl)CmmeI#O_` zM5BF=vZHnQr5aUtvj>*VUA)?X=plm7NSTZ4RX$jyV|gXP3MQjgqbc4P$}Cl=&sG1& zr=$xS*zZ%)RrYgn72)U6QCji^Av@+nhuO~+2g>2nkh%2pJxYu~t?s&@p=uS;L&0l( zu)@yk+7!)K%T*d!-@iLbtUv@~iNq3N`|nkDv<~NMK}uIK**P73x{Aq8v+4hgv14f$ zt2#%0y0nWh!;xB*OQ!Ef+PVWPres~((ohB7o5R#qOwhu_F2|1LRvIdsh4lVSz~V@y zST5Jlk}Bj1?GhqvtvF;ZeKKGlEER2SzS*Z_msXv703|KtoDhUt;%uHBfVG;fxL&R! z^b^)(t#1!0i#E*O|8^k6Ax0F7j7Qr-N;p8ewebL~mV;n=mJeFs+Zuuh6YS@UeUMY! z`)dJ3b)`yiu*TK#qJR?S$yMC@ghx3b3MM#ob4OGsHO(y8`oFm;rrA^MO$4WkRp`?;~KjncHF75s)0TB=2fZ)Nj^ZhUNL3)P5ca$B|QLJG~Tt5fa zI!c6B$QYtyDSX?fBzyi(1dG`9*aoNYEu+NJ9^@(>IKh``d#rg@uH8K0dIwqHFh#$FmM!$O_Re)Y5p4x2F?>)3Uewm%wBW8m1i5PIDnK_(7v z0qK#>rps*%KgF!ZbtggaO~1~#8->& z&-1`R%lymQ5Y}6Cj;w z?z7t_w9#WnBBR4}-ka>^1oGb#O4lVo%&7AZ2O!kR&KKOigX~2rq=)&EOb4cjbM#%0 zy~5SeqwaTDYB4ozM^ttH>QUNmw@2NtQjX9w6mZu)>EunSq6 zDvrSJkX&$S52z0j%0XmIbU|)^ zXuVV&rqLEY;89v$mv?(E*H1(VT3!D!t|4d%8XaQhpMM~fi9MHgzTm1HY9Ywob;4 zCvcHZ$!x9g9t9zDI7knA_mL8rcX7~`;msi>7BM62g&t*)NW43wlr6Z<(M=&(95m1H z1qGqJ5%iu4xzVF6Goa+@R6&XOOdpb`|5VV}=@l^|L=OwQ*99`gY*ZmV>g&XJ4`Q>d zBkEDNMv$HFol$nI;t^Ob`|0vJH}6B0vPEr|!VxSn6DYV84xpq5HMZWnGmtri)SX>Y z7bGhVJ1+XVf=l+uZmD~ZdK;xgvZ+dbOE64q>n&e$`#9GnWT2eQ-j}d-@fqe73vVVn z`YD0e$?SDIKCB|4G`CiGlSgTpf1ch3(+fXDmtMHsqr^hgg+L$TD1&(PMvoGvtdt*8 z5R^zsO(AbEO6-d(=B(6*$i!7@Wow8&#IX;v%29Z|$BwSLhPvG@Qg&OIqe14$JzsZ} zDzm~=v-@`nDy5nCYeSipAx6XQ{|YH9!%WNymxYw&VOmJ{Z+%Lx&FDa1Qu*uL7{n}&42GN0qOG5UdIhOuTkG*R3rR4-AWCvN$G9P5niT16F}Vt#VO8Fk8T{0A*1ww7c8nzdIm>{8mI$%KI3GPl8Y;U zP0*!bL_XU5JAIJ0)TddH)GknvrG55kZlhq?jCLmIdYC$;T?uKKuvha&Xl9zHaPGh!am4MwVN);u@BlpaJwE*%0|#$ z85HPk1Vo&rDble3luZ+tq2@M-*O()u9Xgw?l;mV$)5P?k`&&9prDWhMxJ@W2%Up(q z391ea!KrdKH9bH>m}0~Ponp-d6bxdA+smlTGIpVkGJh#Gk2I!gxp%>pl9UqRREL@8 zf<;4v*s^Ksg{@(iz^xY2t?2<=5MoTQ+kLT5$xNX8eg~40+pEHhNGX~_kkk=lJl8uKs#H;VcQOml3mbx8qJ?Y@L2PVQ$$2^f$8JUY!dO5# zT(x~%?xzH$j#i{T^K=)e#$qc(4_4R|u){O(MLoeQJKaM;TNL8x%z8SPB4~_qY$*LfA!iWVHzIG=^9}i4B`M)vFvhESnMd zC3b0ADbXc(4DOG5-s({fays(#b+Y1+n{dI>g9&@^V!F4WG7(?l8QA%rD?*vb{&f}i z<~>Rj&fOgKyxF51v80r44GrN9p%pZGj2#(EnYFdvZVwE$LiAvGSAhk~wV9^}Q;-p% z=XF8r$h^7UdsCrIbU?@6oAg1}RJ-4=>{y>Dh|s)yG&vE?qnqX~jwL%5EVe>)R{!X; zGhZsWO_Qu*gi>_hX({)BqlD7ne@AFbIrVh}nLOvzt;svK8n%pTbvgB51kL%sm#xDR z@FIo#O}aH`33XO#DNhgPK#a+Csatm_vW_rx^I+9rm`HcHihG^2!iZ2nMdexNJ^PDb z?C2>Io^IXXP^K-JiZ7FyYVTr#A`?Yf*QM-#dNKzY&T?OHAjXbmh#j6%{#-#s*RbT3 z`@BbKS$g(o0i{$mRZCedB@M}#Dmdn#GXFy<9f+J-!JkqlC?)PIsJ?Cp$v8kR?VS3h zAxW&@D>?6xM9{^mf`NHN8Dq375O=B$Krh?~&NUjs^H$p-$#2Q7s& z7X5u0V-(a=x)vHhLOhLofOx5w{EWx-;f$1_t(}hwtg0|3hBWz zk1Ggv!AN{lW2&ffq6(y_i^xblALgkdQR1`J4&l=<8*CGMPNEbiO`RKk2oGnQfTA<(@p?d%=ekenb25}ur< zG0JX~d36`cZYRgGw|nf^>+8IqtDvY3MQ(!Uc%WsfIWAb(90o+E+P%Y3%Igww462ZP z+JQ*PP>!~mK=y+w6H10c%%yW_JDFCy=-wX6EZcg|e!yqvbmZs+z+Q!gP<6?$brdSJ zOS#L)E|eoo;qqM`C6Z02kldxDguzO(sg|r+5MGgCwU%i%*;|!T-o**5?CMx>-bL6c zGo$$u*_qp9Z}Hi=y~@5X0EZDfnKQiC1Fa^IU*^DJ#5Ww|qlM&``XHTu?m}gkF5%n- zbB1>ZGT{iA{pQp!xz3|zsQS#(FJYLVWEPaYF<{5;ie{7D?}1j($o(H{T{0HSmu?6t zt5~6`I(1fPT__1=ulFgbx|}*I*H0uTT!y-f9Fk)&a@a{_(l5!_D|TR}drW02r7f;& zgNBB~8g;7!Mafd=P*0nEmrrS$Z}BN@i}7>?v4&BfB74u_K4?p(iR{SKs;I!a&gUC_ zkUlxL%Yl+n4R8||;6U&KPC@ky1ljp4Qx3?) z`v&@u9(o3h2*p0e;_N={r=vs}&&lkeyKt0Ne8}9)v7<{kN3CPesJoEX+a(BOJc{RjIgZVe7pWnM>6*zFZej;q+QV{tpm z?jw~F8L6yU?Puzzq0I6yHJ|<`2V!d@`HlsYO-c!wFd7;|_cMK&%$L&ldh9TI*LvtSYO?XPi&73ADFj*vUNQ1QV&+sX2cc#e+DQz8XU_)Ss&Fk3HcRLVe9Bkw4 zxMOa;Ps#0n4;>3U1J3>0g1yUQN1E=slzo}9V}kMe-g27;2M#McZ7F-6PigFQR_JIkoi?QGw&zk0Mt1IDQx7{zGy?}{xnk8QFSH+PQR>Py+se}df{;2NLZEct|>p;8TRI9)%Je{|rW$b?tZ5#?5Ul-TzXUd!7uE|84;4)8=~__HZ4r3_ZA3m7`cN^Yp$s5b~+{byP$PBCcp)&j+*Q&Q)KCr zVe?o<+&CnE>#<`8@A{cNONZ$w?TAJ4Hz6h7O=v?IO$)_7krrF=VQavSHxtbKb4M!( z^Tt7aF4*L+Lz#F1M6Y;>f=(t5lxde<9Lj{Rqk)ZhGVNS?@`+HU)MFfb=HgH$PBL@e zANMHn21zM3^tch>6peb?ZVf#{;?D8Pfb;%Xz#g7T>ekRBlrU}@ZSq$kW$?;1ZJ`ID z3`v|uuH-L0N>g%9Yk)9r*&EVA(l;q3YzZg!n7XIFsGvYdnRG%6D#^C=nlazzJX6I2>TQB_mo)aL?9lrI^N(i&k^X3h2pjIc0oIdRQ? zwy8|XvBO}h$+NN#a(k6!Fco%~w@zG&aZ`4D=#*Mr^53;fPzW53C1x#NL-yJ+^_iga zIQT%#Cx7CzGxJZ~LrQ6Agk`kkk3&jqaCG8QpY~+dxU`c$@+r*){hJ2{+W|&c$*fR# z=ZJpjQ__ECPjR5^iSgMy^YcFlD3Kp)am5C|Fxm)Y!BR(b5 z*Ib`RX|XtcrGkhCcx7Qb(-R3I8sd$uuHsy8z>c6zub6&|$BwG9x**0)WR=Jj=^1hb zpPdRxU*SN6e7sSz4-_Q-RY6%DNRG7i^qWJN_yHP_Z<$jmtUE)l^yQ4T(;^#@*4^|N)&F?RqAF$TqU-q=Ij22 zl#*(espKvTk@$QEY(W=n`gLJH<;|n^^XneFo#E-S5b4-0ay=Aw3I0kQb(coN8p5u7 zBd7h`rj%05!SYtGn7+(!ol~5A(3eTduK#i%W!l)sJ()Njs10e{MDC4-;6xpmJ;qT= zVuFel8_KOz5awM5Hv^x>O=Y(;d$|=pB|TXB63WEpT|OM+8tT$uD*eRCFKRxcans2R ztS-yAsa>*waU#(wQDuwYLM$ z_d%9Ab4whElLs)lVa|K%CZ%*y(-Pgx86JC(RWinj6F}J3g^<%2r!vidrWoU#Ogndx zEo8DaM_a18pLvw_383sVDN|~M`<;yE{zD-AK(QLwztZzbsMsChtl;U$4*LSzuCjtCCQUv zp~`-k2ck^lz+8iZGDq^-z=2)r{GCk1Q))i$Q*ym`X+%&;3`!dsU_~@MKvxcB}8>=s6y8{qwm|-IM5eG`P=HBDF5oJyYC?)1|I&uM6t=MabY}SEN&Bgl$ zi!!>s!X8RKcEQX)t2-%DQcLL_+B%FI@3px@N#3TQva`&a-tJM_g3TODPzppAJJRNU z>VA{4!xRyWl~Q*TSpV*r7Gs<`RX29*5x6$hsmiNi?08M4 zIaRn`)bNzOOE(TqCiV#G88Yf=MdlzP53OzyJ1;V=?31Ral@Ao)AtegJ^dXy+QbrVR9Ig%7QJzxOrBCxIxm``|RZxNiJ~hnQe3!>=V^1-l zILctfT@z5E+(ujK`iui*M3_r^8CQ};*w(RU8+~@>V9B>ByUaU`K}|99GzHzC;25+zm2#!~9Efd$ZU~g}N{`Ya zY)b2ON{P~}SXgrej4!3Gm z&2xNqZvT_q%jgudve%`NOZ$n8-gQ2sK}u!XRw$)=8R!$c8`y|y{*7Um@Zo5kxULU7 zkTNaR)D4cZ+gak|8$xze@^zS*w1OBB(k(lklJY={hRN5GU0y8&FBg)ege_s-)GMYL z;}Ew{47U);Z3~?AFphe1>|Gwa4KsC?1M#UVtPXryNVT+*l=5}}rB(-~wtAHIsg2AE zkJ1hUr(UcecCZ+!B@&k?C|#2Bn9AfHK`E)v%rZ|V3{R(HU&xNLiE5vjr5wNj72V?9O7Q4YrkuVls3$TK|gW8gGp(o-2;bto*^}+Aku7<@R-wfT^Gp2 z!3idiDGMkBV>(rfGSW}` zn-9s|HcYf`8Fk8{jH5J#%y^W@tz7G=lY@TZO%o$**FQKA{Vd|Ia#&gNxjrQ~P03vf zVj&>L(A#uf?Xz1b?^jA!;x8*xAA^^@?iVLFboiLlXE< zLZHlxJ(-qKr|BvsiNct;ad=fgi7hCjOxG(t&^$xue>xBaI3zq)iAt3mh-#f2zM`v4 z6@8HDLFdmx_NtvVO1CK`v<5$GZwFdK5XbYlaZqm~T0-!#cRlJ@R3o= zyGV5xq_l<_*-yzT1I_CycI>c3`Vc02qB?w>fvS6%V;4&3-O7@>UMEphEW@DYM>DMzE6N@kv{lnlF_w}&!u;E>KrvtOJckxzbEL@-w= zdqX%j?UI&gTtk>+4dqGmpKce)0Nr_8*bssrU8Ooz*AU#dnqpGzQ$QRAu{xOAr-DI& zNFAVpBMd!B^>t2W@WJq;+NXl}h=wXe?UU@R9wgOlbUN_oxE$s3`?T}0WE{e=rLDH4 zl=cQ^`R6=JtWa%84a_wJQ{*t!z!WT57IcJT*Dw*hgQhKE+ajOSQubxv(1rxWff?23 zvVZYFJ2j8-JB`svxLmr57lSph zYcofw4Xs#5N&&5EwBjTWw3l=pnlm6zlXoq&`Hnw0N`iE29ls7h6yX>VI-c-ATQVKL z3P3sQq$BG1r3ae(T}ca(um@6IaVymY;ZuR|p4hZG)vZ()q@aCnV);v*OnjOie!>3a z&hnRdpna}qg)T1n^F#27bU`b0aVa>+u)Fkq+E1jK^075Fo2BpdLDnvozQ+UYY|PS| zJ>>N=lBN&&6F z-l<6`UgTji>||r7I#q&P2%Q>w9EcJN9iX}k1+7fcsS^j+DW6#8#C7V#DQLCdPMtW( zR8frPMyylUJ3*E@m!7E#L8^ty9+%A0=ldWVTB<$-#*HyqmcH~Eq;w$56zz{Fh%y@H zlL>kI!#>Es*Z!>lM9x4@+x|@twDWcC>X%?j;;dLTYFEFcAav!XxLutp@*2Djv+ZiT z`cHz)0NXVh3J3$GvueN7wXUF*dD}k{fY@^}&2Im&2U_8}T_cxk2xm3b&$nxkBFLrP zetj@Z9H8Wg+J2xi5fSkB5xF~S`+f-GWR7~91-hw66ox|VG)23n*?1)m?~NlwP9Y0) zQ?Hcv_iYyZ13QoG7pM2t&o8*z1MSpD%i|7|Tnm3Ng2_pnu1(Y;VDadwYpCThpOXHw zO&6?E+TS2*(*^55>@AfH~l(yWZlyaH?Z#Fnb zpYlPr-f{;)!~?`1T}Lgq`ylIJt#5RobO>(@nDDf|!3SAAXuXu|h^{ys$kuNqD4!9q zM7Q-dA*FmOKu2_oM+uFpmM#e>;V2nUT6JfNK#Jm){eguRwK}+cyz;c2ev4Y215q`n z=Cw2@?D7G0T{5j&a3e^YZ`F;hfUsF+l`U$DK&0GfUD9PpO0M@7U4}|&b?=rNI3i)k zAJfsXt7mYOVdt+4DRIm|19Z!^KFC+tE${L`i`p&M_#o>xEwno6d~m|8nU?JKQ570P z^Cy(uf%Y1r`QtvwyS-0UcYMt>MMr6e9NN}8nQ~4E zuiCkTPW&?)f+@=Tf2X>HCXg^sAN*=SiLDUFp3t;VC;{?aPeRi|#~%EZ)WnwpcC^nJ zm-xH~+FxBrd^P})j@#l=cOkQhB$B~2VM@k=Lxo#caWmbo^L6$zv1OOaRCfB1giVLf zp0Mc<(EfUJ!lvT@P=k~V6BA6gmiR!>dE`LsQp<~j*0Fy!t9y|LT3(mXh~Q)*qt?aM zWU9kz!`mzM^G#o5LjszCHGM%r_h|_G^izV1OZo}-t?5=1HGd!_7nh^7x7AJedNM7m zZ2HVRVB)HvOZaFE*HIHy=Ndxo*%?^F-^eZYn4eMkuZ8^aM?L9)1<{|i82|OFB%-SV&)bfX9WUsAVYT~>fNU7di zDea?$O`5TYOdOhH=t;aj=%@T4T#bfJA5`!F%0}HA%HJW!>t4Fb#OpkEyp(eNYA@!F6Q`H4FJ#AQB6PuuVtvP%ii{yId0VFF`Erp)Z3L3dK}X&Gd2jGGC@4o7J# zE^$%V5JC#){Z~OlsKRlI8+3amGNm-fSX@y`nNISw2ALBGVgflP60 z>R94`K7dl$8#PNeE$MVLa&?H7;Ay!!CPJAwg{X5B|3e@XonV&|I|529ccwA%-}{uz zSQ6Vq%HTa$Bb_SVu;DBPgH+@Dl~O?)kyx@DJ5CxQ)pq)fi_scrUu+S7!Ux%UBi%1# zqE5?xHoiM(C=5M~H+i7_b+W|i3PMZpRon(9w#);@e*{pvgdHE!EvoL{JkW~v@gI7i z{guCjhH{xBlyc0H>FW*v8=VJ}wS`@zRf!YF2VFvhWB%FbJeW~hD1Wv`iDH)8=WqyO z0BTDy(;?_vCGyUf9XzTHc03((EcuQ!#e{IyAJx#n5qtG zA<_s`8gz;!%BVh}cdm}O&ay(xncm){l?!OfGADcLU>yUqD!ifn2rc;0e%VJG@`9v8B!vgsY{RPFqP8& zU`1SlskV;#8ogpn))9ic$i!b!qt!{6P)h6@IB_vqTt;bUp5qcbLP~8teqjj0z%-+d zOXg2XB*mQf=P8KRQQx7K8f3|UQbB4dCRw_$qxc}7Aa!GpNtPafrg`z++7Mhiy?1=C z2ij@L_;~I>8;6mTCG7Y`=v@TvHd=i-q;X;$T+yT8sk35 zRopNDQ1yug%f%IcE~E&u4}!a5K>BAQ%Ce1kJ5_F z4SA2!{$gZ&lpxYANqJOePe_Rk9~{fFhWMnz#E?wGH zid&*O8?qi~IcZ${A7o09!SQ5W*$t_X5>+p??)Y&YrMcvWq)$l?)X+sxK2?cRRjQ<8 z0(L}vPJ6>jpOTgsKiZ?TcV7)F0!sW9GIMn!9wk=1Dx}k+w1XrK%R>-+JJP;qD zSN665#7=}W+|cTQmi#ufgdhx2&9k971f>S5G7~D)bq@XFJgOqq3hw>2p^b!xW{4vfEVYy=^Fw2f}L<(9%vNXj)5Xterg2o_A z(?ItD^aH=6t?{CZVkcjH?xo+n;Py9u@S7j|>OCjE>eV~$>V4~RpM2<%m3!{l^7RLA zeDk+1xazMRy&w7IoiDm#{cnEr^>dF~^XKNPPPk^j!QaI%!~RfBUVYm*0Qug7@CN;*#m{4_v-+@S@v3z4BiZ&w9tR7hE>*x4-=4 zPiHRv^T{u}^^3oon!H)QLoSY6zGKq+k~e{4XBMC0OXN;HeRR`?^`jd$dtV#3_S8dv ziQMXSr{GKEoczUdmJm8au?EHV;R7(78x62argn^UDNnl+1X>ZO-_%`T!79sdR5?`EFi!6)%n-RlMk(bHAqVCI2tJrf;Cwr(e^TeeSx=Yw{Ry9^=oi znHt}{J739f+O=!ezPL|fEdE1`gl$6k?l`9lnNPOOXK#PqR~{Jo{B6%~IrHbM{`%M> z_m6D+<%b?P_XF80K0A8D=uf(PH_SE+KlH%> zbn;!6vQ93?E%Wz3#g9neq(A>tZACnw^iQsM`2F3p(EaQbFw?8(R_OTCu>{{89DaZG zEXE7h6!M*g-~ZloaURcE0DgSQD`IU_N|)KW=&W0X`u~UX#01e!(TUeNSwh-+?Xoqx)j}Y@aw&%{@zje)B&%C0oF!|l4Z~kHD{-wXT z<;%+Jgu4dtY<-FU;)&{Ut6w{PbmMC-O+I?$)%hE5n{EBco;$7^yCL_o@5X-j{+q7* b?VBEt-}38y|NKPvXSXhXIe6`RrqBAn;}3a< literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/netFetch/ghoo.cer b/SecurityTests/clxutils/certcrl/testSubjects/netFetch/ghoo.cer new file mode 100644 index 0000000000000000000000000000000000000000..6d15d25fb4fb57eec55ce85d94be36d5de950c80 GIT binary patch literal 1134 zcmXqLV#zXSV!ph9nTe5!iAida0WTY;R+~rLcV0$DR#pasEJJPsPB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzIna?}Ee&@b)xRHBbi0F$>Fhd4@PE z02L?zg%zB05{ru!j1_znGjkN29S!8fc@2yVER75d&5ex>4WfWtQv+iopqQb#p=p#s zF*V%6YrqY0CrfCsv%8_Zfh@#nVj-@so;#|Q zj{l{W%&OK24Owd&d+OSXq!Sm;w4}-=-@K!0GxgTZhYyV2exA zK@*dJ0UyvKviyvU|5;d=nb-~($b0- zb6GwXF%}Wdb!n_U{>HZI?B99oetmXwo02UHj%is17JdUzkZ~roc`&9jF>-SnG{P60)?s*wRO!hs|(%7G*} z(t)%w5Q8EfB;=@Sl$>7*R1a1HVS@D}=K}>nDGjI!k=B5!lR@Ia28~-lPLXG6Tw~C< z(x7qKg2u%Q8W*%R&K*cs*(awKm1L%6CMTAp7NwTu1L@5CyqwJ966>VQyu_kP15J>t zRauk_6xg`5*%(!LJYO`t~a|-5IWiN{=ehvli$ef zn-w!ZXXf?ip~eAbY^$QKY-3VMqNGt literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/netFetch/net.scr b/SecurityTests/clxutils/certcrl/testSubjects/netFetch/net.scr new file mode 100644 index 00000000..d243b210 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/netFetch/net.scr @@ -0,0 +1,80 @@ +# test variations of {cert,net}fetchEnable +globals +allowUnverified = false +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +end +# +# everthing supplied locally, but the CRLs might be out of date +# Enable net-based refresh +# +test = test1 +echo Everything supplied explicitly, enabling CRL refresh +crlNetFetchEnable = true +cert = ghoo.cer +cert = JITC_Class3Mail_CA.crt +root = JITC_Class3_root_CA.cer +verifyTime = 20030601000000 +crlDb = c3MailCaCrl.db +end +# +# We have local CRLs; ensure we can get everything locally +# +test = test2 +echo Everything supplied explicitly, disable net access +crlNetFetchEnable = false +cert = ghoo.cer +cert = JITC_Class3Mail_CA.crt +root = JITC_Class3_root_CA.cer +crlDb = c3MailCaCrl.db +end +# +# get intermediate cert from net +# +test = test3 +echo force intermediate cert fetch from net +certNetFetchEnable = true +cert = ghoo.cer +# cert = JITC_Class3Mail_CA.crt +root = JITC_Class3_root_CA.cer +crlDb = c3MailCaCrl.db +end +# +# get CRLs from net +# +test = test4 +echo force CRL fetch from net +certNetFetchEnable = true +crlNetFetchEnable = true +cert = ghoo.cer +cert = JITC_Class3Mail_CA.crt +root = JITC_Class3_root_CA.cer +#crlDb = c3MailCaCrl.db +end +# +# get everything except anchor from net +# +test = test5 +echo Everything except leaf and anchor from net +certNetFetchEnable = true +crlNetFetchEnable = true +cert = ghoo.cer +#cert = JITC_Class3Mail_CA.crt +root = JITC_Class3_root_CA.cer +#crlDb = c3MailCaCrl.db +end +# +# get everything from net +# +test = test6 +echo Everything from net +certNetFetchEnable = true +crlNetFetchEnable = true +cert = ghoo.cer +#cert = JITC_Class3Mail_CA.crt +#root = JITC_Class3_root_CA.cer +#crlDb = c3MailCaCrl.db +error = CSSMERR_TP_INVALID_ANCHOR_CERT +end + diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/amazon_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/amazon_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..b62626c195503689b57319f83763e4c1148e34d4 GIT binary patch literal 1274 zcmXqLV)V=Ai&BA95m2v!v!jBpg1eD{ zoH(zcfq}W9sR0;70lCINu8EPcsimo9ltDVGw}cG@LFRJ^bA=}sXJqE3m*nRe3K;N# z1ldK{gHsbrN^(*SB@DzsB3vT;j=70d`CwN&)Q1zd?Q>Lvj&6W;G(9^42 zQ=_-I@m{a_&v$wLO~;=Iv4pM<&z#cpUN4|3H<&*6XQjLCdRYi zSe6xLVKQJa;0F3qmY;=%nTd6Qfh&k3&thj_V_>zwVu4wk2`IvV@f92v1POdycO%{8 zq8!x7gUh-b=>a7TTtLPsu-F=a5(0NZn+Idt4_8KZab^Q80}VC~Z8l(fV`pL%lfjo9 zz==#&l|{@z1g3?V5zb;VkOx_!%mR$329c%jxdqQ1aAaQWl{&#=lgxu~-CB2pGMHjU zMwTpt3dKt_^n6r1%Zfo_hI$~QP_r>}6C)$T3emq`cSUu~_;YVYK( zD1W8mn(w@AZ^X|^Y@heD`RPl`uKv3=iPsOj{#a!4#NYn8vBOHw`7RrJ_Zx34o4Pna zvA>^3E}dG)u6`!^e#(ofsoLM>3HrtJNivo#G%#Ze z`pEg<{FOp6-iBR5YV#(0%fvVP=v>IOK04Fzh)=)zKF?We6z#lXA4*)dbV*_nyLINq tTicFH%O0=Ge=WTJV{Y9gCJ$2^{aFjX?g@Rhq`K=~5_j>O2uB&6KmdRaqpbh{ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/amazon_v3.101.cer b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/amazon_v3.101.cer new file mode 100644 index 0000000000000000000000000000000000000000..039c7cee794c5357472bf58c309238fde1b756cd GIT binary patch literal 1584 zcmXqLV$(5bVx78xnTe5!Ng&Vv*XEk4do4FA$rANS`U!R&ZYAjdi6Ibu5xWUa(;_Qy}PJ_M$?82p#$q;*sp(!JaalJEXLRKzgoxY zkU%SauUmXG9(5M&{PR7-=7_vy)oJm@&pd1S?<6Kk3vjc@X-X8vC7pJ@x6g1_A(Nz^ z+RDINJt>*Y_vZYq{ac;5=TA#bN6ePP)o|cXfl=sVgh07u5bVsM`PIu4JIL!mfYI&oA`bkp8t{m3FhTpCT2zk z#>GucD-D{MmKvC_acHvv(=P71eLU;+WU9cZIGi>`sTf#w4B1*&bzPzNU$<)FA%zaTl$SU25B4=7>42hzn4 zaytt!v$GlG!fa&ZVM#QIUl_X}+91*(+#pnp6PQKQQ}xp`(+m_1nWR`m z`k!8wYFpFWmwotrL)H}!37u+5Jp)xSnDsgN>G`PkmlcD>KqhH|tQTZaGEi6|XCPxJ zWgr0*048riaH=+Tb~G|DvCuWtH8lcfU|BvEF&2@f@3{rf9dKk`?3FsfW0TB-aNSyW zgU06|qm)@1?;AAUS=e}dN#l{>P%t$K)ZYBZetw1Ac7e+D-^)8qjv;4fVCl=;*vODv zqHi0#N`LwrHNiBge;@BTs!Lv~zj09J=Oc?SEBOiQERQObuKtmun=Y?;Nb$NzN3!>Z z+3Lv?e|%WXsIu*M|6^Mw?);E{SI*qN*1ErDs$5)>;K7@mbDVZ=y0S`lhLv){nMJcc i=Dj%IcTvhFPV(sW*`^zqlvSRx?zr0V_`$E8U*Z9tfd`oY literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/apple_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/apple_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..9fec8a21cbed06e88bc03e781a609afaa5955e5c GIT binary patch literal 1746 zcmaJ>Yfuws6wPinfrLkdgrEYlzGy&5z6}J3f-M0o6bfo2(m*L8E@5TejY$BlIMvwV z1GUvM;3&3OtB#dAeV~X)p-`x{$iv6bDWg@;`oPu)qf(35T@c5}O!wE`bMHOhz31Dr zz|QXgcHZ$SE)2o&B(I!-%#C+O+M^%6ej*?H@hWiR3xY}#N*=pG5RbwmypfPl|U zL-=AiO^bO0FE$X0-F3Ky&=Mvp7)_*%a?Bt2u?ZKkbUcABu@qQsXbNsCqAmH@JfI#c zP%gnOE37D;ixyaM)L=vNY&NrXu0l~%R3tBCSgj1J+(@rbSj+}gW()-3SR@E%o4I1e z3-(yjV6~#5X#6T0PA$Wip*jOeEHl^$nnJbOWK{cREE*dFrg^(z0E8>U!04lALM0Q1 zDnnIjm0Az%kUu5{9(CA|b{UmimJ^7101=zyiJfBsGq_5vbkxutxUzW<2~Vv8SlHXlc*p&o>Ahz5^GBZ&duml~; zq*5e7;i%R|TW~a&%63uw|vw(OUt{oC_7+eV3A&9fP zu%%>sK=m0-)3wyrgcvw$$BeuB(mQ`|y~Vo^|NFCVd*G=S(kV5vZfbe>?xk_F@8xwr zet6lbFDg5fR~YxM=0N4(RsC0usaYouS4)2xPASW4sBGIZ>+T`=J<$`d+ZR4va4x&` zSJ!~b8%W&eQ3q2h1~we_6g90Mgqt3kzAa0%`jF4gqY~98!5Y8TwPD%2(uO*#Uc1?< zY5T1|S~XY`dMsnHF7X@Lt@}TPbBkIo2#JcGkk07L0YUKs%aPj4;5@GEX_3gf$~GSd zN4Q}w3)jRq_b2tPUKme(c~Y$iyE)%y{=RG5d!MFfw54AB(7N=}#_HX3m952lFSIWT zo(FRw4z%A6=KwpL1xQA7KMw>4M!T3Q$`5%(O}p4wV4eVa;--lhWt@ObxEt1*eqsa$ zoKgSzxg%0U0t>an55U`gl_U2X()$n9HEmlv7r3yMA_U>WyecrC4g8S^paP*)Se2qA zgf$`K!FXLFWg|n37Shp*W4MxWlAOtbIJO@}q5&Qdx4o*5rP9K%N|JKxb~WPDLiRIe)U7^WX=d87N* znJ0=r7*I6ycU`%@EANrg^vp!Ir&XYp&&Vr|tVQ;`gK+*~wn-kH2q8$PMYc709i{m}Da2=4d=jZo z+caG5TeEeuVQ=lC{90XEbK}l4%MW@C^!Qv!Zz`u3pY5y999eU^wqvN-xhkr7b&4$c iJN1^yP1{BqyKK?2-W$zoSy)@Rd-T&7j!<|M()|b5dP%+j literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/apple_v3.101.cer b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/apple_v3.101.cer new file mode 100644 index 0000000000000000000000000000000000000000..78e8174fd34066eeb7414c3a8d85f441d9648982 GIT binary patch literal 1570 zcmXqLVv{pyVr5&v%*4pVB%tGQcQWtS$iAO8GefEp-Z~rbvTc;+SR8Oj^Tf+VMECvRlUUGh}eo;Z90x)EN4zw^ZgZNe-!?&&# zC8>ESz@Q0B%*jlFcrrNHMpy1v}#`z2_Oq z#J8{0TD3xZk+ijda=h@yyBs}!BDb0wA8+k>obgsA{ao0#HM5JSx!msR*?jFo;pD#C zg&|(AizBo83j%eR=TEy)P*eCd6#Gax(9F~6;l&x6t(mSui_VH#z)t+Ka4?d$xwzsyGuc90pBHEZ_ty%f}+dBI4(KLbmL^d2p5gr-=M1pDi9;-Fx3a2p9>n z!inupo9S*$aa2^i&%iUm(4(s zjWeOmgR$+06C)#3C>Q1yMjn<#gZPE93!)7o4Z;mV#W;Z(Bt2C>Ju}Tf(LmmSosCtS zkC{n|MWp}fWvR9`y?xn-&o^XU@sQA|meey)6;p;fEhj%cAJs`^#b7azNtz%R39={| zC@hgPkTH}pkN^q*^Qj;>dm1}C8X1^a=o;#pSQyBIlq$1G7>G59)L%|re(3I--5(4% zKRa9gVp?x(XbcP-XfOgjV`!jnpbO(0Ft#b8hf{uXaRG{}3`{`gtFq`CXv0H=g^`U5 z5pIm=P={X&tE*3Vh)A8Nmi_aMYrfgSOPs}pY12vrP4>?;2uzPz(}`=4x3KDeniI!X1qoxl|Uz?lz3 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/cduniverse_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/cduniverse_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..7f4673521e12b4c34ec0d21b8040b3a4f0ce1bf4 GIT binary patch literal 1344 zcmXqLVzn`7Vo_PZ%*4pVB%pn`;CCnF=T9g@_nVzSk;F*`KXDDwV3zFa#7K2GBgcOw) zmnit9mXzlgWgA)>SV9ySg`^hc7AxeZDU=qcDkPRDWR#Q?6kF-*mzS68l>tpH2AZmu zoS&;-RFJ5kk*sN8YN%zP0n*GYtOz&VIVZ8WSix8!I5oMnC>2N*0re_4I~vG|^BR~L z8XB1!fI*Zvuc3i~p@FH9v8ko0WfX>&L=1#LW^)L0JLl)+r6!kTCYP2NLPgm{xWf~3 zax(MM)AEZ_V4_?i+|Divp?R4=D~nSNc@4P1UK3&Qb2KnCG&V4VaJA5VipPi229jVO ziU@%eC8v}^4F?5;LF0VncwuB^U~cRM#!V+vVG=J2|70Q!bGo4KG918x_BgCGPcZKc9wSr z%LgakbI(>xI{KZ7nUR5UaTDVugC@pv;G`le%)(^A01gvbeijyHCe{T8Emu(=0m^qnHf7Bn3{WvZ^d%1|l#m%#3grlYu> zD9RDx0`j~rNIE&S$RHPH2qOxzejPPL?-fvT7?)CoEH>G`NOmlcD>KqjFU2Fy*2 zj0`!e-vmspW=cJ|D|0%RR7v*RSBEOZHos6v*LUguA9 z8x&7g1~^UGTDvvCY?+kIq@Lha%Qu}pDe$7l?@v|d+>+PaTe;K28ZTdavH8ZW&pcnV zPUXL3ays*Jk>fh$OH;2YGwiv$(f>T-!c5EgJ@xOGONFXQd^eD@Sr%Cn{BBLy$_*yY zMiUNBeE#&zqJ_5SFLG;cXng9`BY#$H;|}Xz*E*gtN!%^|m+E5sNpK76Ip-u67b_Sm z1e7M_WF{*F6lLZn7F8-ZrxulDre!84mSpDVDL9svWaJlRmQ)(ZiSrtm8W zj4z8zn{u;QCqhzb$H_lcmJ_tfi)v);zTXIayx!?_y8+Xk=rsk;cDQWOHhn$$k~nMK zX}4=J!3&H6=a!^I{N$O%@G8#5Go|RuS%F8bTt7|TZSF{0xpYa?1-=>e5xm+#yW3XQ z>HXT|QPX={H=eO{Q7@Zy_m)KVllzor{*b=7H9U>Q*YwN8!f9J)a;VOpe!}Xr!p6Jv zX7G3=Z(nw91LL_Lle0eaj6a# z_&{3tL5^Vo<_|UlK{if^?M{r0P$5l_5!Sr7pQDabrZ|EX#wu;4SnHdLEyYKz+Pg?aXX;FU?A-m%{m!}P zJNKLm1(^m4#Df+oj^Vge_S06Vk_Bizb3M0J80P0Eflg8h17y-dLZ-%zd1M>}B2cKq z3vG;x=2Rj)S+b9K+X< zkuY2&O4Y$*#5{T_Z3QnE0YeUq2~)ugGF1;D3DcmyEKEg`2$EwEx?7*lECNmzgUQuF zMz)6KTr?;%Qx>+;#?WLCoG9-3tK}va<)SIZ_P>NA!fB6$JWBz1iCN0nkti|*29HV! zQEGM6sA^rU6$)6~ll8>>BvJvJC_#1wE?}6XFUojv*EH#yLup0ZUW`EL*SagM=#jv9_@cGO2AWkPa!5l&B~CjS7slV(jQzRCq)Pyo1zw;GM)308OpL@vgj2{#6y&0OKeNDC(^?6wKGyuD9$?G11Z)t9WubOe`O&5*I?eb zEQonR#~fM8UOVoInr}=w#2?3YI-TQ;(bzPH+G(bk3m^n64FQP0WSK&{+Jbp*IdPmo zI10_=STr2dgo_8-QL0aeGZ;dPfZefZF-`GwB|xtRZ=r!9w_twZt546C!pNB^o}p-9;>|o=L)&6z>T4o^4ItsuJ75gvo{jsx5V$r z5t{ZJUcb@xi}NE{gf;WK=Isl;H+`m~Eg0MAZB8p+a_877e{wojACO)Ua)>g1sbaXa5<;jP*mo?vj01 zOLM%%^(Xf||4bg{8C6MUiz>lxmC^~hGu z?Q# literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/certum_v3.101.cer b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/certum_v3.101.cer new file mode 100644 index 0000000000000000000000000000000000000000..ef36759a27a5cdc087a1a034e8a40cda860e3d0f GIT binary patch literal 1081 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 N9Wa?PvFy_E?*Lmur;Pvr literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/keybank_v3.101.cer b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/keybank_v3.101.cer new file mode 100644 index 0000000000000000000000000000000000000000..039c7cee794c5357472bf58c309238fde1b756cd GIT binary patch literal 1584 zcmXqLV$(5bVx78xnTe5!Ng&Vv*XEk4do4FA$rANS`U!R&ZYAjdi6Ibu5xWUa(;_Qy}PJ_M$?82p#$q;*sp(!JaalJEXLRKzgoxY zkU%SauUmXG9(5M&{PR7-=7_vy)oJm@&pd1S?<6Kk3vjc@X-X8vC7pJ@x6g1_A(Nz^ z+RDINJt>*Y_vZYq{ac;5=TA#bN6ePP)o|cXfl=sVgh07u5bVsM`PIu4JIL!mfYI&oA`bkp8t{m3FhTpCT2zk z#>GucD-D{MmKvC_acHvv(=P71eLU;+WU9cZIGi>`sTf#w4B1*&bzPzNU$<)FA%zaTl$SU25B4=7>42hzn4 zaytt!v$GlG!fa&ZVM#QIUl_X}+91*(+#pnp6PQKQQ}xp`(+m_1nWR`m z`k!8wYFpFWmwotrL)H}!37u+5Jp)xSnDsgN>G`PkmlcD>KqhH|tQTZaGEi6|XCPxJ zWgr0*048riaH=+Tb~G|DvCuWtH8lcfU|BvEF&2@f@3{rf9dKk`?3FsfW0TB-aNSyW zgU06|qm)@1?;AAUS=e}dN#l{>P%t$K)ZYBZetw1Ac7e+D-^)8qjv;4fVCl=;*vODv zqHi0#N`LwrHNiBge;@BTs!Lv~zj09J=Oc?SEBOiQERQObuKtmun=Y?;Nb$NzN3!>Z z+3Lv?e|%WXsIu*M|6^Mw?);E{SI*qN*1ErDs$5)>;K7@mbDVZ=y0S`lhLv){nMJcc i=Dj%IcTvhFPV(sW*`^zqlvSRx?zr0V_`$E8U*Z9tfd`oY literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/keybank_v3.102.cer b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/keybank_v3.102.cer new file mode 100644 index 0000000000000000000000000000000000000000..642b24a6ea071acc21607ae6211338962062ccfb GIT binary patch literal 774 zcmXqLVrDXEV#;O`sJ;1*{rn2K?E;nQzn6EK95di$xRnxarzoT`wYms4pdZy*cND+be|5K>fHT%zEYT2h{0lx-j< z&TDC5U}|V#00vRwyhauV76yh!#-^60mQlmPkB#$@V~&xPfw{347<-*ejg1Uv;w}ot z#$;YteR*e=&rJEq83uh~tqN|r?)Fz&6bDMk@49(;j>dR6MxK>mFe`4NoQhaWMD*g9x!1s1Kkzqdv;&U=^2u9L^m;7 zR_OWirxz5=JSGq|Wl6AaNUrvJ-dKn3l*`xO-3v>c6u<0&m*J8)R@J%8;|tTpRn=A`$9B8M&46fU30ng67aZS$_kaJ5Q? VZ$Ee!85?L^SrxHh?%d3Ye*uNI2VwvK literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/ocspssl.scr b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/ocspssl.scr new file mode 100644 index 00000000..b5aa5ba0 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/ocspssl.scr @@ -0,0 +1,137 @@ +# +# OCSP verfication of certs obtained from SSL sites +# +globals +certNetFetchEnable = false +useSystemAnchors = true +allowUnverified = true +# alternate these two on successful runs, flip either one for failure +requireOcspIfPresent = false +requireOcspForAll = false +cacheDisable = false +end +### +### all these (until further notice) do OCSP via ocsp.verisign.com +### +echo "=================================" +test = "www.amazon.com" +revokePolicy = ocsp +cert = amazon_v3.100.cer +cert = amazon_v3.101.cer +sslHost = www.amazon.com +requireOcspIfPresent = true +end +echo "=================================" +test = "www.cduniverse.com" +revokePolicy = ocsp +cert = cduniverse_v3.100.cer +cert = cduniverse_v3.101.cer +sslHost = www.cduniverse.com +requireOcspForAll = false +end +echo "=================================" +test = "store.apple.com, allowing unverified" +revokePolicy = ocsp +# leaf has ocsp accessMethod in AIA, intermediate doesn't +requireOcspIfPresent = true +cert = apple_v3.100.cer +cert = apple_v3.101.cer +sslHost = store.apple.com +certerror = 1:APPLETP_OCSP_UNAVAILABLE +end +echo "=================================" +test = "store.apple.com, require OCSP if present" +revokePolicy = ocsp +# leaf has ocsp accessMethod in AIA, intermediate doesn't +requireOcspIfPresent = true +cert = apple_v3.100.cer +cert = apple_v3.101.cer +sslHost = store.apple.com +certerror = 1:APPLETP_OCSP_UNAVAILABLE +end +echo "=================================" +test = "store.apple.com, require OCSP for all, fail" +revokePolicy = ocsp +# leaf has ocsp accessMethod in AIA, intermediate doesn't +requireOcspForAll = true +cert = apple_v3.100.cer +cert = apple_v3.101.cer +sslHost = store.apple.com +certerror = 1:APPLETP_OCSP_UNAVAILABLE +error = APPLETP_OCSP_UNAVAILABLE +end +echo "=================================" +test = "store.apple.com, require OCSP if present, disable net, fail" +revokePolicy = ocsp +# leaf has ocsp accessMethod in AIA, intermediate doesn't +requireOcspIfPresent = true +ocspNetFetchDisable = true +cacheDisable = true +cert = apple_v3.100.cer +cert = apple_v3.101.cer +sslHost = store.apple.com +certerror = 1:APPLETP_OCSP_UNAVAILABLE +error = APPLETP_OCSP_UNAVAILABLE +end +echo "=================================" +test = "www.verisign.com" +revokePolicy = ocsp +# leaf has ocsp accessMethod in AIA, 2nd intermediate doesn't +cert = verisign_v3.100.cer +cert = verisign_v3.101.cer +cert = verisign_v3.102.cer +sslHost = www.verisign.com +certerror = 2:APPLETP_OCSP_UNAVAILABLE +end +echo "=================================" +test = "accounts.key.com" +revokePolicy = ocsp +# leaf has ocsp accessMethod in AIA, intermediate doesn't +cert = keybank_v3.100.cer +cert = keybank_v3.101.cer +# +# This one is the root, which SSL server sent us. +# Leave it in for variety. +# +cert = keybank_v3.102.cer +sslHost = accounts.key.com +certerror = 1:APPLETP_OCSP_UNAVAILABLE +end +echo "=================================" +test = "secure.authorize.net" +revokePolicy = ocsp +# This started working on 10/19/07. +# The intermedaite has had an AIA for a while - maybe the URL it +# pointed to just didn't work before today? +# OLD COMMENT -- leaf has ocsp accessMethod in AIA, intermediate doesn't +cert = secauth_v3.100.cer +cert = secauth_v3.101.cer +sslHost = secure.authorize.net +# deleted 10/19/07 certerror = 1:APPLETP_OCSP_UNAVAILABLE +end +### +### OCSP via ocsp.thawte.com +### +# proteron deleted +# +# misc. others +# +echo "=================================" +test = "www.wellsfargo.com" +revokePolicy = ocsp +requireOcspIfPresent = true +cert = wellsfargo_v3.100.cer +cert = wellsfargo_v3.101.cer +sslHost = www.wellsfargo.com +end +echo "=================================" +test = "www.certum.pl" +revokePolicy = ocsp +requireOcspIfPresent = true +cert = certum_v3.100.cer +cert = certum_v3.101.cer +sslHost = www.certum.pl +# this, because we don't have the root, instead of APPLETP_OCSP_BAD_RESPONSE +# which Radar 4158052 causes +error = TP_NOT_TRUSTED +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/ocspsslNew.scr b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/ocspsslNew.scr new file mode 100644 index 00000000..ed8a5f95 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/ocspsslNew.scr @@ -0,0 +1,144 @@ +# +# OCSP verfication of certs obtained from SSL sites +# +globals +certNetFetchEnable = false +useSystemAnchors = true +# alternate these two on successful runs, flip either one for failure +allowUnverified = true +requireOcspIfPresent = false +cacheDisable = false +end +### +### all these (until further notice) do OCSP via ocsp.verisign.com +### +echo "=================================" +test = "www.amazon.com" +revokePolicy = ocsp +cert = amazon_v3.100.cer +sslHost = www.amazon.com +requireOcspIfPresent = true +end +echo "=================================" +test = "www.cduniverse.com" +revokePolicy = ocsp +cert = cduniverse_v3.000.cer +sslHost = www.cduniverse.com +allowUnverified = false +end +echo "=================================" +test = "store.apple.com, allowing unverified" +revokePolicy = ocsp +# leaf has ocsp accessMethod in AIA, intermediate doesn't +allowUnverified = true +cert = apple_v3.000.cer +cert = apple_v3.001.cer +sslHost = store.apple.com +certerror = 1:APPLETP_OCSP_UNAVAILABLE +end +echo "=================================" +test = "store.apple.com, require OCSP if present" +revokePolicy = ocsp +# leaf has ocsp accessMethod in AIA, intermediate doesn't +requireOcspIfPresent = true +cert = apple_v3.000.cer +cert = apple_v3.001.cer +sslHost = store.apple.com +certerror = 1:APPLETP_OCSP_UNAVAILABLE +end +echo "=================================" +test = "store.apple.com, require OCSP for all, fail" +revokePolicy = ocsp +# leaf has ocsp accessMethod in AIA, intermediate doesn't +allowUnverified = false +cert = apple_v3.000.cer +cert = apple_v3.001.cer +sslHost = store.apple.com +certerror = 1:APPLETP_OCSP_UNAVAILABLE +error = APPLETP_OCSP_UNAVAILABLE +end +echo "=================================" +test = "store.apple.com, require OCSP if present, disable net, fail" +revokePolicy = ocsp +# leaf has ocsp accessMethod in AIA, intermediate doesn't +requireOcspIfPresent = true +ocspNetFetchDisable = true +cacheDisable = true +cert = apple_v3.000.cer +cert = apple_v3.001.cer +sslHost = store.apple.com +certerror = 1:APPLETP_OCSP_UNAVAILABLE +error = APPLETP_OCSP_UNAVAILABLE +end +echo "=================================" +test = "www.verisign.com" +revokePolicy = ocsp +# leaf has ocsp accessMethod in AIA, intermediate doesn't +allowUnverified = true +cert = verisign_v3.100.cer +cert = verisign_v3.101.cer +# +# This one is the root, which SSL server sent us. +# Leave it in for variety. +# +cert = verisign_v3.102.cer +sslHost = www.verisign.com +certerror = 1:APPLETP_OCSP_UNAVAILABLE +end +echo "=================================" +test = "accounts2.keybank.com" +revokePolicy = ocsp +# leaf has ocsp accessMethod in AIA, intermediate doesn't +allowUnverified = true +cert = keybank_v3.100.cer +cert = keybank_v3.101.cer +# +# This one is the root, which SSL server sent us. +# Leave it in for variety. +# +cert = keybank_v3.102.cer +sslHost = accounts2.keybank.com +certerror = 1:APPLETP_OCSP_UNAVAILABLE +end +echo "=================================" +test = "secure.authorize.net" +revokePolicy = ocsp +# leaf has ocsp accessMethod in AIA, intermediate doesn't +allowUnverified = true +cert = secauth_v3.100.cer +cert = secauth_v3.101.cer +sslHost = secure.authorize.net +certerror = 1:APPLETP_OCSP_UNAVAILABLE +end +### +### OCSP via ocsp.thawte.com +### +echo "=================================" +test = "www.proteron.com" +revokePolicy = ocsp +requireOcspIfPresent = true +cert = proteron_v3.100.cer +sslHost = www.proteron.com +end +# +# misc. others +# +echo "=================================" +test = "www.wellsfargo.com" +revokePolicy = ocsp +requireOcspIfPresent = true +cert = wellsfargo_v3.100.cer +cert = wellsfargo_v3.101.cer +sslHost = www.wellsfargo.com +end +echo "=================================" +test = "www.certum.pl" +revokePolicy = ocsp +requireOcspIfPresent = true +cert = certum_v3.100.cer +cert = certum_v3.101.cer +sslHost = www.certum.pl +# this, because we don't have the root, instead of APPLETP_OCSP_BAD_RESPONSE +# which Radar 4158052 causes +error = TP_NOT_TRUSTED +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/one.scr b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/one.scr new file mode 100644 index 00000000..9f8ca7dc --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/one.scr @@ -0,0 +1,19 @@ +# one OCSP transaction test using amazon's verisign cert +# +globals +certNetFetchEnable = false +useSystemAnchors = true +# alternate these two on successful runs, flip either one for failure +allowUnverified = true +requireOcspIfPresent = false +cacheDisable = false +end +test = "secure.authorize.net" +revokePolicy = ocsp +# leaf has ocsp accessMethod in AIA, intermediate doesn't +allowUnverified = true +cert = secauth_v3.100.cer +cert = secauth_v3.101.cer +sslHost = secure.authorize.net +certerror = 1:APPLETP_OCSP_UNAVAILABLE +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/proteron_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/proteron_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..b39bb4f9f2046a117249b0e2d88a9956067a1605 GIT binary patch literal 842 zcmXqLVs)FR?K>|cBMU2oLE{laZUas>=1>+kVWucY zLs0`^5QjsUCp@*dB(*3{!8x%Y)lkSl03^&V%n9Nugyfg!8Oj<+gT%OmMM5$X%S%!f zob&UFOLIyx^U@WPlMOWt)IieQ!t&0kMJ1VOnaPPInfZAN!Kp=MnaQce3ND#tnZ-a6 zLrDX1kV< z!rb18dBusv3eK4&m4;#lA|O#NVcvkEd|+_o=jkZ;_&6guxxBnwuK+3sc1q)XsQTFGFs(5TkoxyWtgC9$?nSKcSA2=uH752>+|enHq4%*obhd@ zIn$r(*7uxGzk71( zgd84EsY$AfO{c7%Cip2V_f+WzwrdCP@;FV|H$CQ`df1{Fxt>3K&Tl*%?dpA+t?PWt q|DIWlA}TAzZ4>8D{cGDIFvEJHfj`U6EyoqLOZvV)n;dAJ@E8CaH4I$< literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/secauth_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/secauth_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..643c3cda0a3df332ef8521637ff2eba4203e1c6f GIT binary patch literal 845 zcmXqLV)is>V%oHTnTe5!NuVxyufYHM+BS=4M~d54$V(gWvT8uPey$-3&i+9GdWNzF(h#SL6sIPa7NzPX!i~sFEiq`Ej~pV5 ztPISJy$lA8olK3540mPQ&vn0dX3u;1`=GH~xR-C-$$NQsKYvSDIrq|)4yj7@Z$ICO z@IC+dzUrsq1e>OHKKuFVK0Q?AY+vG@^!P`Lr1=GtJsowi5i0I0RTP#SS{M}nkAG8p zZqx#MWM?`l5Tq29Nc>1a&r;edL@Ru_)o^%XyXgOw5c7jEfte z8#F#K-~oCJlJ(5 z$Pocdn#{l$a9yivyKwnK;|+Hf_k_Kd>r_u%+?YAR_RcqBSvFsue7w<+?PTs^raInh sg88`?-#(=U_x)X59=ow==k)uX@1|@oD!JD4Vcwyv7e4#e80?)30JF~)8vpm?<>a zP~1Qi#NiU=3rj7^49-l?(^2ruOV%?qH!uZBa0}}>=Oh*vD;O&TlqTh5CMyIKW#%Rp zRVp~A7L{bCWhN(L=zfI*ZvuOWzQWMph=X=)i| z;Dh9VC`Ut817(Nk>Sea^b5VB_3O?W{;QRpxX_-v&}Pk<6Dhxw z{}_3*PuZK_uuK0T%j5&be>jbmUvigd7an0gcIoUR{jZ$KXa9RFW!V4V`R9)9x<>bA zm_6fK%TRqJ#ml;-l=)M^q*}hDuZpWP%~}jgC;ZrdJf}mNZEDTQrz`H2F4U>YxPSGO zOnXFvBoi|u1LNYxe+G@e4TONMmlbAY{LjK+zy_q47#R$>L1O$YEWpTOGZ19sOlb39 zZ2RHF$OskE0LcroC>qEwku{Julr#{B1c3lB3d#~oQhgGWQge)T4NVOUK`P~0vdsFtF3>9hM+-=^feFYORTfdxL z0GWXi6S^k()xCvxFHMM_&wZ|JpKxIR-N%g2**XjD#`79T6kCrU@ ozNn@;!KVBy-#HJadPezRV0ej&6*#H0l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/thawte_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/thawte_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..caa65ced4ab857e702346512a3d3f293389762e6 GIT binary patch literal 827 zcmXqLVm3EuVp_0(nTe5!iP^4jvH>p}r&gOs+jm|@Miy2E10O?f15P&PP!={}rYJ{4 zRRd)Zhf7!{BqOoBBvrvVKd-nnrzA5kT|pzDq*7DCrzAzsP|QFCq>NdZ7pg4S-C4oe z(Lhd|*TBTU+|bOx(%9I*G788wMdBJXcA;7)Y9I_UheMbrJhiwawJ1-)Ik6zsP{=?4 zB+M?%3F0b*tI~hp(vEHU5#xmB2v z@jnZb0RwVG08=G1Fb3wN`MtOnAem}7gxaf-h&|*GQ=I5#WS^H<<4)0}@95^ra`Y3kdRv{Ka9(Qm~f{Ri8d{FGWOf25U^y#)YDBn_qj literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/thawte_v3.101.cer b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/thawte_v3.101.cer new file mode 100644 index 0000000000000000000000000000000000000000..14dfab308e727031d1a16fdce96388a53cb51805 GIT binary patch literal 807 zcmXqLVpcY2V(MAI%*4pV#A3j}z+}M7#;Mij(e|B}k&%^^!64p{+klgeIh2J>m?<>a zP~1Qi#NiU=3rj7^49-l?(^2ruOV%?qH!uZBa0}}>=Oh*vD;O&TlqTh5CMyIKW#%Rp zRVp~A7L{bCWhN(L=zfI*ZvuOWzQWMph=X=)i| z;Dh9VC`Ut817(Nk>Sea^b5VB_3O?W{;QRpxX_-v&}Pk<6Dhxw z{}_3*PuZK_uuK0T%j5&be>jbmUvigd7an0gcIoUR{jZ$KXa9RFW!V4V`R9)9x<>bA zm_6fK%TRqJ#ml;-l=)M^q*}hDuZpWP%~}jgC;ZrdJf}mNZEDTQrz`H2F4U>YxPSGO zOnXFvBoi|u1LNYxe+G@e4TONMmlbAY{LjK+zy_q47#R$>L1O$YEWpTOGZ19sOlb39 zZ2RHF$OskE0LcroC>qEwku{Julr#{B1c3lB3d#~oQhgGWQge)T4NVOUK`P~0vdsFtF3>9hM+-=^feFYORTfdxL z0GWXi6S^k()xCvxFHMM_&wZ|JpKxIR-N%g2**XjD#`79T6kCrU@ ozNn@;!KVBy-#HJadPezRV0ej&6*#H0l literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/verisign_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/verisign_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..149e878fd6cd13dc250c0a03ddf4793c399f8c61 GIT binary patch literal 1788 zcmaJ>Yfuwc6wYoo0SvE@5I~?Th{!X!%Oen>v^0PqNG-t>8Hc(io46XXn5Pdw2$D)8 zLd9XmS}@k4Qy)`xtV(^f9R|nJg4Pxsv}3V4R_ib*jusW$?t(Cc&UAn6cfNDZJ?A_3 zTwvpl0~=@9$%Y{q_ElWF_&oAZWO;orbXRvc(h9t|9ZWmu1;1KE^A zVhLfWFrt(OH5&;OH=%1yrb^>tiNtEPiY;_jBb`;OqADbYN*s+=#Q-Um2Bb_dTOgUq zF4y5kBbtQfY%~#iHK9h8xQTNTFARW`L@Aj3%4nEK!<59N z6j_R_4A`I;OaS;?UK|%fAX{n%46!FW4FUnPjj+Hyo6zA_+(2N#Ac(2PN8qQ##2_A} zOJQ0`5l63y!F+)?LvjReiOI6mv^1%!fZo89q4`3NEEyyxO`c6-cfmY4UB8Ah=t&$C z0U_h$CiGfHne`@|)T2t0uwoGaW$YfppyaevGzX{UT}Gn=XEO6FIoNXwZ=D`yq^%RYSs1@#|%6@jWa9C-*(I_^3739)@{1!x-nnJGJ%3w$R{kec)v1LN z{`Va7IM{NH>|u3vSDkg->H0B?W$)P-bMJ-kP~)!hfG=Zlk7qAOc+PXZui75QMpa85 zZORJSa)W}|5DPkBgKfYD*MK?)tz#%3sjCNdwYLALY4e1h9}IEOB^adV8EK()KG6kgb2rKE90Klt%{PDC4}mShu@0q-M$O( zn6iBkgbj0?Ad>-MNGeDHNlwfuu_rL=N^fh9GGA}fC8!KK*QK4ZCjuZ9(;UcV;!)&H z!0bP7wLK5AkLN&c0bCFZqPgz$)^Rv)FeD23zgK|vq_ZqU!a>+{2pgLDgSj44dEY@G z+JW|5fCK_jt*}UbIn*+ms@VMQSShvpN!srN7k&el={N{N)`7JkZW;r~9_HE`r7~8! zG)K4ax?%v&6#^%57vI+cO$k95fPOj@@d&}cut*<%=2 z=cZlm-uwvj_d8n=8|V0$9KLzF)4p<;yw=heG4c5sjeO*ez~e&4vo7A>4=VmV`C@;= zNB!=lgWkrvUg_IV&!(<#mWq3?xMd6p;)`z`%Hw_EKX{AlHDu|1PZd9!c{^%PV6b2U zM@~4}t?622$-?g*i#v|)cqMrDYxTf=_lXuujr0ct;@o@Xyzopx#|J*mE%K&InZXB_ z`jkCLxVgvKG3(%AB<`z4^|{@evLi|d=36nk@3TSDZ|lpxZ8uIY(>k8Zc3}Tx HJ+%J|DYQ_` literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/verisign_v3.101.cer b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/verisign_v3.101.cer new file mode 100644 index 0000000000000000000000000000000000000000..78e8174fd34066eeb7414c3a8d85f441d9648982 GIT binary patch literal 1570 zcmXqLVv{pyVr5&v%*4pVB%tGQcQWtS$iAO8GefEp-Z~rbvTc;+SR8Oj^Tf+VMECvRlUUGh}eo;Z90x)EN4zw^ZgZNe-!?&&# zC8>ESz@Q0B%*jlFcrrNHMpy1v}#`z2_Oq z#J8{0TD3xZk+ijda=h@yyBs}!BDb0wA8+k>obgsA{ao0#HM5JSx!msR*?jFo;pD#C zg&|(AizBo83j%eR=TEy)P*eCd6#Gax(9F~6;l&x6t(mSui_VH#z)t+Ka4?d$xwzsyGuc90pBHEZ_ty%f}+dBI4(KLbmL^d2p5gr-=M1pDi9;-Fx3a2p9>n z!inupo9S*$aa2^i&%iUm(4(s zjWeOmgR$+06C)#3C>Q1yMjn<#gZPE93!)7o4Z;mV#W;Z(Bt2C>Ju}Tf(LmmSosCtS zkC{n|MWp}fWvR9`y?xn-&o^XU@sQA|meey)6;p;fEhj%cAJs`^#b7azNtz%R39={| zC@hgPkTH}pkN^q*^Qj;>dm1}C8X1^a=o;#pSQyBIlq$1G7>G59)L%|re(3I--5(4% zKRa9gVp?x(XbcP-XfOgjV`!jnpbO(0Ft#b8hf{uXaRG{}3`{`gtFq`CXv0H=g^`U5 z5pIm=P={X&tE*3Vh)A8Nmi_aMYrfgSOPs}pY12vrP4>?;2uzPz(}`=4x3KDeniI!X1qoxl|Uz?lz3 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/verisign_v3.102.cer b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/verisign_v3.102.cer new file mode 100644 index 0000000000000000000000000000000000000000..bdef91b6b947e0576eb26cc7c15420003e5616aa GIT binary patch literal 1226 zcmXqLVmW5e#G=1|nTe5!Nx*cvVf*KHD|Vy0a}hkV>uwqFvT z0i{VfnaK(PMVYyYMU@K9sYNB3X_?81C7Jno3XY{E8Tmz-C6xwp;=BfChK2?f24D~+ z&TC`{fHT%zEYT2h{0lx=8bU;$BJsFAFx zU}RumrT|k3@q~h|f?Ix(LL$U%RjDZorNyZV`FS~&hOP$AAid1OHZUy;r1=wQw!5i8 z6QdGx05h^OFgG#sGXTZ8n3@HbnTf=c&k$R<)R9iv%hUFYmM`4!Ws&Nq^)i#vC7ym^V|hPe=M#n}cdfQc{%6|t#pd0E?$_qsZ@ye# z^Xc0M+x2%#CmKu2$~c@ZQIS-fd{gA#8m*w?{a0B$pY$fXci3b$pZ@2*SG&&t=+t$5 zbFW-`7=i@kS+oo^4Ad5=EKq7w$S5f(u+rC0F3Qm>1188~V1m?3&d=2^NKQ1? z1Bx2(fwb_0%wPc~cs2uD5MP1C%)rFJh>ZovWH104$Ht+}22AekOpIbOAR~)`W|o(i zqnepqPz+9DvV1IJEF$%nQhz}go<$j^G#51((yy5b?BQ!S}ypem*e4Ue4s^n6sumlcD>Kqi^M ztz%>X2Bd)sjBmi$CIK}dKe@O7#Q@}F3oI9y8ygw;Ro8jEl{Rkm;n{lV`aj=m%^E(A zsR<0+oV^W%j7SoS;ciZ Nb#;^9e^cYG1^`%gm3{yK literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/wellsfargo_v3.100.cer b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/wellsfargo_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..f95af0a019c93b52c2d16a6a8937eeca94efe99a GIT binary patch literal 1147 zcmXqLVktLhVt%lInTe5!Nx<>w*$Go^7J47-ayhzp(%oA5TXoPan^aNClq|7d?$+O-pkHm}LfX z;=G0i2BtuFfI$?HYY5^R8Jk*~T1FW(wi|LAaDr@O6J`nxHWW4x1aUZoxttSoGSl*l z@-h<*#SBD1g6tx^!HIbaZbgZC$(hB;`GyJxav*Uo5%KWUoSb3>x5T3Ke1*ik6b0w} z+=9fsN<$t4E|3at5oXU|cSC6dNf3`&LxPn2RtJy19M|9Fz`E> z8XFl-ZvJ_|%W0p~5v~PWAIz!j3~Jigxw+|%F0-~=`C*^h>E=ntstvbht6rX0SI0iJ z?%V3Dn2tB;u@nXfa{{Q{+@#Qr_6W?`+=_;Y=2c#U5}-i|Lj{>gT2 zEwxy;*_w0dE%#q$#zs8Om;d%^Y~ajXIlphtUmKl^KLweX85tNCH!-d?XkuIm4lY?? z7A6A*18$&yWcgWGn3-4?7}$U~@+_tXz(`-9zd*N5JENqez)D{~I4lSl={dT|MLDRk z36;&|u@xW&6(L{SX)H%KBmwa6e3rkRn4CCMORVcdckgD8UtgD^49%-qEERQ>eK zGy|a14cOUOwfUHtq*z3}vv+DtW8>LnI?mR&SoW3TIEj^p;XVpgBF u>su8mvMthbyZZ57t@NoTI^DIQ-`ER!9M64AVPHJ17xPQaqII2{$p!#~hi7#F literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/wellsfargo_v3.101.cer b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/wellsfargo_v3.101.cer new file mode 100644 index 0000000000000000000000000000000000000000..62dbdbb2b3b54e2d3e508afa213fa12628ce40c4 GIT binary patch literal 903 zcmXqLVs18QVtTWHnTe5!Nx<#T>s?ze=<`oXn4xSxnZ4hDmyJ`a&7D}zD2 zA-4f18*?ZNn=n&ou%WntD2T%)%omnglo_0vo~NVWnU}0*Xl`H%lHeBBbIwUDE>DJm^4QSeJGDbFv;hPjFx!&Sxxh7eb2 z!F77(m82HsfnAZ9qY#{0RF+z#;OwZNs{nPlp{Id6M3X~#dAS}?I4)ylU@SgI~c)qc4D3hU)P&&;e>eelVN-u8TzO|fg}rjL7HO?P@b z%Y;kx%F39p4yt!=vL7_sRGM?-)b7Rq!qf|$S0#Tnu$!#$^w&pD>(ASL{Vc!7ct-6w zD0_KR*S`XTsZOW=X$N*k*;xHl@}IDYX?gG*f0O5{SvFPYGchwVFfMLjO>hz23iIhY#iEbz{J7M#3&|{ zQBqP+Y^AS{EvO7kK&Gg&=o)Clv@kQmSxju45ObYa7}>aBR&X#HaD#O5v#zI5Ry@A*86ZxJ1D(wWK`1DBDonKoq2aTbK`~Ku5tdFImsf z*uW4Xp#_rwikGAoJjSXtUB@E$$QqT6OYRkCv>O~^6)#v&^sRTdapLQYsis#NX4;(I z_Kc-VO>%o2(^NABbp?Gdw+z*uFEyRyMs%%!~|-i<=m? z8#FO)28Xw-Fbk6bgMkasC$b7Gwg%P)mTcS!Z61tmKU^8v#hDGX3^dp{wAp}3ke!K9 zOeUkGq@dVJUmsgw8gPS5;b&oCW@23cjtN;+7F`2vHcp6vPArUUTtK5(7@N$wn3-Y5 zGBd(iOh8>w%NQA1Gz`=XRA77q#x@C%qfYNHaIIOiM{iO*S>QG&4y}OG`?! zOifNQNHZ}rPBt{ig}INBhb7SHdbvu zW+o{Xk^ZNbrP|i?_GKSF-;j01LqexoQqMqDOd0Croc#2BR5zCugT+85p_U2Ez$6v- zdXk&cJHy@0sycgRn)+4*YAlhzw=VL^RqM1P`P^z-XJ0wEXKAE##nrOARf}3~NnUhV zS#ru~HLup&lwzs%nkoEOzU*7(b!o$|sl6TdWlV3lwDkSH@LWAx_^aZ6*7WatN;Vyz irp&(Wd|iBR-kY<9*ZG~oX1~=oNYCHA{pZRa{R#m1t$Qv2 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/xdss_v3.101.cer b/SecurityTests/clxutils/certcrl/testSubjects/ocspFromSsl/xdss_v3.101.cer new file mode 100644 index 0000000000000000000000000000000000000000..1c84d8b541b4514e216e61d43a5e7f5644757ded GIT binary patch literal 903 zcmXqLVs18QVtTWHnTe5!NkG-RtJT8k%;Sh3NAIpv%3ET<%f_kI=F#?@mywZ`mBAq1 zklTQhjX9KsO_(V(*ihU+6vW{Y<_k+L$_&m-&(l%x%uCiYG&e8>NpK76Ip-u67b_Sm z1e7M_WF{*F6lLZn7F8-ZrxulDre!84mSpDVDL9svWaJlRmQ)(ZiSt^T8<+qM0D~xT zUPD7e10xe7V^d30%P51!U54@ovJgwfV3sO`6qOd2DEOt8l;;;^!(7FU;VNSTLx`)i z;5t3?N>YpRz^+KlQ3y^gDoZU=aCTJCRe(C&(9^&jqRFAWyj%|`ommX@r(SY?uD)|X zFvz?4MFo0El?p+rX?hAio{mnQKAs_w3O*q&dK$@^mgWjD%M2RlBZns=D+6<5FM~m2 zCsSi1!;Pkf7uO`2YUNucEL9h!YCqh6h4u2DXJ*!`KKSHBZ+pJVrr0%f)5pE9raQfz zWx^$TWo67)2i3bb*$*0RD$O}^YWL!QVd{m>tCGJO*iF`W`s*X7_2=!rewN>3Jfn6T zl)b#E>tBJvRHxJbv;(`NY^;7N`A^uyv^;o@zsd8}ESswHnV1xVpxIw!3Sy+Gxl+8d8 zu8NTnDg=sBS$P(qLk!dws4P%wQvf*v=!WE?9MtG4NKQ1?1BxO?0x(fC14EyK@y(Nr zDa=kEi$5wavby*3*MN0jZ_UY*afGG6^^4vPr885{S{j{K{_?=-a!KPl>Ud3$k< z0;lf7Zx1C|EjHNl&#(V6kLgYuQ(K~+T72C6Npd_YOTJzx5I(PV*xA-oc3zWSQ2ZXd dV`-X#JP!ppPa-cA> zGB7tW@-rATF>*0AF)}i2a-G@9V_@{_sOo87hD!a`C6Aw7=E!I0>TsGmH^4S*y~FNw z%cQb3j}nEW>h?d=yfgKY&enymK5fbE-L*Y!4hvgh$eMjz+vcq{I~BxSKGpH}eI z>l@mZZvMN+f7V;&ABXtYXC4x^UpZMbVbzMbKbJq<$Xj0&a=c-p>t{`dssm|J_3KvY zP5dYxeb;20aISuq#y71x*6%+GV$UD=@$cyzIhSqE6dNY$|BRW!T4=|1FJSAI6Luc_ z%XaKgJW-c|AC%hdI$3(MXAm3ZH_wv>IlK5<`~ zdc8>E1^=W6Ui-h43OkFm#dKd(_;g9;A2Sm(BLm~&CdLwAh!hy`10!Enn33^63#$P$ zkTT!~3GlP90Mpkq16dGdk8gV6Euo5A>N(9+B6WTl&+kQ9!vllQ-7}yPL z5JJ2x`eM2v8JWcj$%q`KP@Y(w zY>Fz6e@eo0W-Sftj5h^QlAoSTKP19o;l=%CN%)**M;%U)N7lDR4!M*ZIraXdkAeSk z^P5~tIZV_oH!ibleDS2LK&k4OrCai8ezm*bE*ut3kGkHpcY|OR!_Q-vF6~$(b-tSQ z#@eX%bg47fLY4^a`KoDlivPwzt?3s(`sG)bOzvI$o1xWrVnD;8`%kq_)m*A*0RWVLyYK)2 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocsp_openvalidation/Root_CA2.crt b/SecurityTests/clxutils/certcrl/testSubjects/ocsp_openvalidation/Root_CA2.crt new file mode 100644 index 0000000000000000000000000000000000000000..6160a38e57f34af50800d0fed929151053182ae7 GIT binary patch literal 1285 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 Y-IHGNym`y)$;}FW-bHtht&l$l0MTlN@&Et; literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/ocsp_openvalidation/User_CA2.crt b/SecurityTests/clxutils/certcrl/testSubjects/ocsp_openvalidation/User_CA2.crt new file mode 100644 index 0000000000000000000000000000000000000000..d382ea77b6ffae702679d2746459126edb4e21dd GIT binary patch literal 1160 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/derCerts/uee8k.der b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/derCerts/uee8k.der new file mode 100644 index 0000000000000000000000000000000000000000..fa886f1c296c7d7ce22e103aced7b0bbc3644c5c GIT binary patch literal 2718 zcmai0c{J2}A2u`g85)#*7#d3nzp)I-zGTVHT%y4+BNIj#L&~0g?WVGpeM^bT)+;;N zLdw3}>|{x{$ntXUd){;3bN_h%e7?_fKHtyh`JD4P4-m?n281$0vLIj(7|cY|ugu-6 zARUAUSm>E9M(9QCvVcHzbTmLHh#w6FnCKx`T6zvJ_8R&EAa)8MFr=}*g_ai5lITrA zTKJGCM5I2MLiBPc5=i(HprwIE0m7$JMi}2;BFgEzhZoY+%Y#ZHI}wq_cy}V258ydf zF~HdWR2h0W;oV4-JAaYF0P>V%hVlGKnt0vBlS%$~3dw`~rvP~#jsE`{8MG*XI;{hR zA^uSZ?}o&ZNtD0-lLjRJJ3kYM6G=Ilj_8gjx#0-}FQT`%I@!b5h3G|;B9W;lZ4v+h zE*1a-C;;+kSvgrW#)gXpjR7#Sz<(g1{J-u=0urZvKwzkUxMzAzM+d1z^rDcQNlvFu zoks(qj6#232#Agb63WPWvK2-qa40Q^=6Qor@_9IIgY;}k#n(CKZ00`ijSPn6gT5;; z`FXrDTZWXOh1t#n!-bHatCcU5$TNq5M%xa%L+AO;BICdLV-DRLb|eW2onqoH)_u8F zmWQQJ@=O;)t`txBbX&?2(p5w^lZ#XWFTuu!-mfVXrmFDP*ee$_!TI6=RW|r#-!6)h zEq^cM!-O0gcpAK{ip@{S9F^W!dcN)U>Yce5J9>KD=;M`^wU4|tH%&2o_8$hc6BY-8 z>zel-X_Ujo!4QeHprzs8Y@_p*<2;1#z^!HKzeN_V8Vo{u!&D(my9^;>Sf+ z(y^z7l3)3b`gfOQ%C+=8gZkF>*fLqK1q$zf8^YD9E=_OOG!8%6*`y=uJn{}VoBs`m z7BiQoL^?!7+-vLxwhP-xFMEELvp60t%ijebQ%BffRrwPNj?$3TYgW`iOPQmG|B_ts z_bqI8S`724ZDMUJn#{3mv6f%wBvGMML`#iIWC6DuO6)i%;!NAcy~HApXk0kNI784^ z86-HKvPm8|SgH;tU(tGf*8}6lMzhHrkeBphSW}+tyI-@Hmf~L(eLJUVE8cuJ=ZmWR z8~XOJko~Sw0Y*kIp6KztuHKwNH4Hf_W*HJ@2fZ;{mc$d=V6|p3a8!S>x54*nl=S{< z^w3UEOB-FRh^T4HgD1Sd-Pv%*rB|ly6=Y7{IU+K}BvY%^K@}Qpb*Ti=I{mxX_@QM`=9g5hgHn?Ha&fK*Gha22eM-#>G}v! z5Zm3TW9-@-*_40v)%s+=vp^*K5CJUY=W@ImJR;yEhh3}Niy1ji=5dos6{?WPLRra1 z^OZ=(m+Upf4oah}}zwpdBi9CTzTgeb9{3#@yZ1_d39U~S4^)YqG zja0wSGgt3r->Tm$Ne^Bjku1**wI*%Rj{-4eqf&o7g-aTRFXhUv5p#YO_I=0o9J^}S zD{{Y7;9RoG?|i&-?1!sNduMyR9eLL7(+}Oyeun^0!p2LeDp9M1L9^#cSmX*F#5zK! zDcNXzo=`6}d1rNoKg4T4(ZD>JJAIxe&AUHo|1H8|Fm!w8z#80ghb?-{uPtG>muB{P z8od2wIJdu;qGdGsyKV$ZB3q+=9I55dV5j+TS~cbxKO$G>==Rn_aR{Ftr8-4!iO&9h zO^6xR4ZQcfCkk~|-ia0Dx{l)Cm?pfo7I>3&^NVVc?^H$CMLAxJvZ*L-1sY zK1aml{$_rC@#mqAeVe0}IA9l#xN#9c=aNZ&mN-r~JjuhJsJ3q^?Op;@kc;6lu%Q6rjtqY7^Zc{ zvIJefXhPCuf|tM@=@o}^ONk4Hd{Y~q6Z)JQJHZYS z%-1FOgxc~^JoE+~RE|7P0R+0CZi>gCRmF=|oPzaqfw+kH>A5 zt@VDyx~-=aKbPF;KXQwMKNeHzTGBl5Ebh29yz(q5wq-?R7Yk5sf61i?Hu12)(49b3Ev}wk#Va(0}fw`2<)Y51pO8o2tO6n9x zt{R{MAWl*Rf|Zt&_H0^RV^x83q^G|D0RcbfA$EWA0xbYLr8z*LV_Gmk1F)W=GpC3a z0;c=p?+N21@W>8duFEHgpa?AHuZbvfg-Hh^0yOky3ER+rY8zSi&MTZz@|U q)3;(RfNE#fL^#Jjr 16K (RSAMaxKeySize, RSAMaxPublicExponent in com.apple.crypto). +# +# The easy way to set these is via the cspxutils/keySizePref program; compile it and +# run it like this as root: +# +# +# keySizePref set keysize 20000 +# keySizePref set pubexpsize 20000 +# +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +end + +test = "locally generated 6K keys" +cert = ssSubjCert.der +root = ssRootCert.der +verifyTime = 20060726000000 +end + +test = "test1, uee8k" +cert = uee8k.pem +cert = shintca.pem +root = shroot.pem +verifyTime = 20060726000000 +end + +test = "test1, uee16k.pem" +cert = uee16k.pem +cert = shintca.pem +root = shroot.pem +verifyTime = 20060726000000 +end + +test = "test2a, huge pkint8k.pem CA" +cert = eepkint1.pem +cert = pkint8k.pem +root = shroot.pem +verifyTime = 20060726000000 +end + +test = "test2a, bad pkint8k.pem CA, wrong root" +cert = eepkint1.pem +cert = pkint8k.pem +root = root.pem +error = CSSMERR_TP_NOT_TRUSTED +verifyTime = 20060726000000 +end + +test = "test2b, huge pkint16k.pem CA" +cert = eepkint2.pem +cert = pkint16k.pem +root = shroot.pem +verifyTime = 20060726000000 +end + +test = "test2b, bad pkint16k.pem CA, wrong root" +cert = eepkint2.pem +cert = pkint16k.pem +root = root.pem +error = CSSMERR_TP_NOT_TRUSTED +verifyTime = 20060726000000 +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/parasiteEnableLargeKeys.scr b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/parasiteEnableLargeKeys.scr new file mode 100644 index 00000000..ee3a5982 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/parasiteEnableLargeKeys.scr @@ -0,0 +1,71 @@ +# +# Test for NISCC Parasitic key bearing certs, with the RSAMaxKeySize set to > 16k. +# The easy way to set this is via the cspxutils/keySizePref program; compile it and +# run it like this as root: +# +# keySizePref set keysize 20000 +# +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +end + +test = "locally generated 6K keys" +cert = ssSubjCert.der +root = ssRootCert.der +verifyTime = 20060726000000 +end + +test = "test1, uee8k" +cert = uee8k.pem +cert = shintca.pem +root = shroot.pem +verifyTime = 20060726000000 +# bad public exponent +error = CSSMERR_TP_INVALID_CERTIFICATE +end + +test = "test1, uee16k.pem" +cert = uee16k.pem +cert = shintca.pem +root = shroot.pem +verifyTime = 20060726000000 +# bad public exponent +error = CSSMERR_TP_INVALID_CERTIFICATE +end + +test = "test2a, huge pkint8k.pem CA" +cert = eepkint1.pem +cert = pkint8k.pem +root = shroot.pem +verifyTime = 20060726000000 +# leaf is OK, other certs have pub exponent too large +error = CSSMERR_TP_NOT_TRUSTED +end + +test = "test2a, bad pkint8k.pem CA, wrong root" +cert = eepkint1.pem +cert = pkint8k.pem +root = root.pem +verifyTime = 20060726000000 +error = CSSMERR_TP_NOT_TRUSTED +end + +test = "test2b, huge pkint16k.pem CA" +cert = eepkint2.pem +cert = pkint16k.pem +root = shroot.pem +verifyTime = 20060726000000 +# leaf is OK, other certs have pub exponent too large +error = CSSMERR_TP_NOT_TRUSTED +end + +test = "test2b, bad pkint16k.pem CA, wrong root" +cert = eepkint2.pem +cert = pkint16k.pem +root = root.pem +verifyTime = 20060726000000 +error = CSSMERR_TP_NOT_TRUSTED +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/parasiteErrDetect.scr b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/parasiteErrDetect.scr new file mode 100644 index 00000000..3247c904 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/parasiteErrDetect.scr @@ -0,0 +1,70 @@ +# +# Test for NISCC Parasitic key bearing certs. +# This version runs with stock key size limits. +# +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +end + +test = "locally generated 6K keys" +cert = ssSubjCert.der +root = ssRootCert.der +# leaf cert has a bad public key +verifyTime = 20060726000000 +error = CSSMERR_TP_INVALID_CERTIFICATE +end + +test = "test1, uee8k" +cert = uee8k.pem +cert = shintca.pem +root = shroot.pem +# leaf cert has a bad public key +verifyTime = 20060726000000 +error = CSSMERR_TP_INVALID_CERTIFICATE +end + +test = "test1, uee16k.pem" +cert = uee16k.pem +cert = shintca.pem +root = shroot.pem +# leaf cert has a bad public key +verifyTime = 20060726000000 +error = CSSMERR_TP_INVALID_CERTIFICATE +end + +test = "test2a, huge pkint8k.pem CA" +cert = eepkint1.pem +cert = pkint8k.pem +root = shroot.pem +# leaf cert OK but subsequent certs have too-large keys +verifyTime = 20060726000000 +error = CSSMERR_TP_NOT_TRUSTED +end + +test = "test2a, bad pkint8k.pem CA, wrong root" +cert = eepkint1.pem +cert = pkint8k.pem +root = root.pem +verifyTime = 20060726000000 +error = CSSMERR_TP_NOT_TRUSTED +end + +test = "test2b, huge pkint16k.pem CA" +cert = eepkint2.pem +cert = pkint16k.pem +root = shroot.pem +# leaf cert OK but subsequent certs have too-large keys +verifyTime = 20060726000000 +error = CSSMERR_TP_NOT_TRUSTED +end + +test = "test2b, bad pkint16k.pem CA, wrong root" +cert = eepkint2.pem +cert = pkint16k.pem +root = root.pem +verifyTime = 20060726000000 +error = CSSMERR_TP_NOT_TRUSTED +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/pkint16k.pem b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/pkint16k.pem new file mode 100644 index 00000000..1e317432 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/pkint16k.pem @@ -0,0 +1,97 @@ +-----BEGIN CERTIFICATE----- +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 +z7CtowYF61a2kCaZZ85XZjpS9Ceef6Xz +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/pkint8k.pem b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/pkint8k.pem new file mode 100644 index 00000000..e8606d51 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/pkint8k.pem @@ -0,0 +1,54 @@ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/pkuser.pem b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/pkuser.pem new file mode 100644 index 00000000..7b581be9 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/pkuser.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDW472JN7o8tXMZzViVQhIY1Zk2+Spm+c3NTS/KcGwz15nkXHbE +oHuIV2lW4QiM+fM/pm6FP6Fx/zE+eRBjECKCrV+cBXpt9zKxyOBAayYb/aPTOayp +o+K5NwUxB9lSZdVlnb2h6KINJJ7dZEsehtP4NYLmqdhDCJqFhHYGq+3D7wIDAQAB +AoGABxG+7oCy08R0YOjsfRyLU93TCIfx6SlWp+ZeKB7CsIHrQiP4lEdjSPz3LjCB +A4JFilaDVEbfnMx0ZkW9UET7nZl4rsWG2kkTQKR0Vb4ZS4e/2RyrnJKLrDY1B1aB +fyu80++VIClzozL2SW+PjfjaMvVxfrKK5Vy5vEf1SkyHSAECQQD5KEK8LYYFavSe +P3Kc6fRH0K2KD6Bs1mjB9IQnbVQcoWu+UktKRR2fAP5oMPHVIwxAj4hiZSWOPL8h +rAlmJwDvAkEA3MqOOAJcURAz8JFYM/1EjvPRFSrmSYrMrAMxcaiWmXhofPpUaarA +MV+a2NaMlh+bu21qJgODKbs4pgu9aa9tAQJAVpnK0FNWYO2zBonxEV8z+/4pQ3J5 +BTtk//04LegPM0BcDbPW3YK2b/zNcHOKqtVavdnlwqV7bzvoBxEf1zS5WwJBAIsX +N7zlD88pi+7zQUOPO89qnb7eBbEytXlvkYhukmEgT4LcGK1wmh8AgYY0suAoDW1n +okVMVSbHAQrpvmuDzgECQG7KZ6wR2fUq7lJyak5maQp22f4Ds2fnyDw6xDJvpjEh +D7r2zyO0ta5hj7OKNPT158nN29mo5l5PFDC+DEJosao= +-----END RSA PRIVATE KEY----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/prsa16k.pem b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/prsa16k.pem new file mode 100644 index 00000000..6a68e435 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/prsa16k.pem @@ -0,0 +1,238 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +daIteqTVeQyC3yDk/uXh0HxF9cDFv+wAa/KW +-----END RSA PRIVATE KEY----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/prsa8k.pem b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/prsa8k.pem new file mode 100644 index 00000000..757ad960 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/prsa8k.pem @@ -0,0 +1,121 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIWKAIBAAKCBAEAq8BNlCMQBMAv5Kqy4eVmoQrQc/GcB+r80DsMNeZhPBGcLkxT +UfaRTOeB+O22rTpu4/1+TfVg99cjHFGHjet6Nv1twPYtZI7KJyhoWNCjV1T9rJek +UOiBO6nddcxUM2SbPSbzlKg9fiwM29e+7jenmT0auV88psIQG40wPhEQOXfLdDpb +HM8DyN00EQLiAuo+VaWYndov8emr9Wywu1InEjHi3E3OO8Tuzhq5Z1A2G1/I00SO +6NOAvcP5lUGxECgCsos9lhpwP0wmgB8FyS/E5KsFYepIiNy/JY4KygjyT1D12/pV +dJgjXNcyL/WdMeIfl0eezIX27ywDDlnqC+6PPbEH3UTZjLcDYltq5UED/2937y/4 +i0CY0eUmT3gXbjpFXwQLbrB32nrMr500xNCfC3e9zVsJWO5+Ivrr1126Puni9bnB +2Jf28wVuRZVzhVHmVl0xJ1IvdIdghoZ8wcww9afGaa7N+LENYv7qNXsC/3bZEQy3 +pd03Yi8D7UtXdn5UMv6TvC3senenw2Pog3W6wg7GqN6iVMRYNe8WaXYLdh3EuT2H +phhsJCf/ooYPxir5j6gTiV2FA06cH3c8AR/cmPNu0/zpuIBuO0Oze282chEA8wp9 +pJDy2EI1bnf6ufmamHq3iXCiwvSNUvei1T41tAbHg4H6y6weCAhyGYnc+cvPoqc/ +Nm6IiuoDg14LXOSvkBmLwFfuU9P+vyrPwHdGiC/6szHX9s3ExgWLJSZQxJGXGlZ5 +8W1dm7aa+aad3mcW7k6IuCytyr5zeNryTrw02qz0peXa+8SY9qCtm+NTRI8tk6cK +kjNIFj6nyERDT7smQSqVqjw2Jb8hXagomU506zU4qo9obppo0t9fSzZkWhpo5/2v +hEmL2lpg00Y8fZVkClmo/2m+VJkgfX8VJR//9EQ2fIyRut/WPJGjV+J/Oz/2UBA6 +WHHgIJgcPNvC43+yUh2HmE+dQ8VgPguJTWKdNLZQ5NzZgJbMs6Vpa5r1ukksnG+k +ZoIQhnd/7FgaMjhUzXpJObhrNgKDgrYxDAfO5tOIEfoSmay06ZZJrkN+H0S43sXo +t6XtMPe9KDhCRAnziuXBpmtz9dtuE3MwZJqd74n61KSx2D1S+fNxdRruqnX906GK +hwXQZIgDW/eI/1Xu5W5QHO2w797RZh6HEtdkAiF4aP/zgNkeYzRV7r35itn/lBls +LpkhsiugJFcziRuqLY2q+cCL1i7v8+QB4+MnRPcdmU7CYxfNjBu6/EzrYAMLfun3 +giN29Hx9HZegGHawZ97wm8YqHuOwDUfAlXqCxAGOQsoPh64dexDGTr/OFBEQ351M +6kokFQ2zL+cWC++kAlPQ1eHFBeHsnQNLp+cStwKCBAB4EcMKZiGUHWDm559OkG7d +XZrsnCWn+CEilEzVP8c2J4oLdVBgo4dAhBnlv3JfxUnPLQYC7GlpVBXXxZD0Btow +iq/aLuCeEC1NhemjM+5lovun0PBdzf9rQ184GK43FulXpcqW9v94Xbaau1v/9YcU +XtLyR4LRYH1xZPGuCz5lQ6oHQs2Xg4fsBQNYhkXClE3c5mS/Lt557eMcgXL6j0pS +lBib5gCac9GQ+rUdU9aC9fb8WALEeRGJ23jGjvfPAOSrmhDHroUYeic4VIlu8EeG +JCuhQb/cIENgwF5Ck+I+ikscHaNF/nD0kygDG0h0uJg06QVfhLmBUVVsAvmrzYgk +FDVjDgFr7yQc8eJks1getKBn1T6od9+yyyo0Gh/n2fDIv44B/NcQlCvQYh3e+vOl +v6nU18n6WnvBjKHK5M22QOUXxr1ILUJPXepBIhimJ6gSd0BdCV07RDcObRATOQ7Y +czRe9QvHxUMFVUHE+Hu5SvW0HUbC0kmMDVkkOHBKt0EpQHxhtJwRpBaAsBM9t7HE +lPummjlIX4FGIgfDkN1WH5PJMnmb+T9kFmpkpy/qCJ3ZqV7YZp+cVJA0Ciu+x4x/ +cx9ThaE9z9YjfYWNdhzrzPFaGnM9LqB2kqo1Q6kf+RdKJFpDN68yNChenF7WYiZf +rJC+r4moo6O/ZIABN3U/LssIsdFYaGa4T+bKSicYpw+AsBP9GOGB5VCFJBP+7rER +hLMZEFDekOY2Ce9ir45HeIkDfiAHNF0DfrDW+w9peY9sLOzYE6EVe5Afq3i5V5/9 +9TMlilf9KGXsbqpTVRIRjjW2pggzXf3eKyZpv8eKStGFdPyvXVtHVykhqSsehQZZ +RglKGjK7Efrd3GlAvs5rtn+BAiICvYNIb8ne0Jwrx57MDWRBJD1LXJvnKdg8jlC3 +gOkCyZuy/TTpj+dMG9/xcd1JFkH2gGCGClkrGyHGpSQZBkrJdhOkcR4dMcC93xlK +xT1yBDUHRFrxX+RVwTxgtRzp6KNrKuQNMriBTk/bnhoalTK18XonVE2t20fqW8a5 +MHGsGFV6kLnkMMv1DkCNTEg4f8gnVe7ZNoEEyTplVZgM720stn2gC0q6+VWHmKwg +JdR/r95RNZsHQhOoaA1wAAGJHOhZPk5bzSHiFw5dbY+LltxbPFhI8ots75ipqy32 +0f5sjBCWJz3L6UL8canJatjsn5CLxOwl9xAM6P4ekvt80303cfqDFz4/jRgSUS2Q +uxJcjBp2ZhDChWJmuQCI1Ilz37WhlElMmrPdjVqUmLkZYSt4OofWywLcux8WGr9g +x1ygEytMJMe9p04ujxdc6O2GxfbWM+sIWsNh7jZRFTB+o3TKmayJTXSN5JF0md8T +AoIEAQCACrA1tH4VjfVL+fV5ywrIJ7E0SvzLn6tQ3r1XW4Otqj3OrOoONh6IWICr +Mi/E2yiyn9XTaSo1byEDTEgANZQDQIfJ09YJ22wzDT+D0oNJiPpbqV8g6FJ9Lq3f +hTIdzOlPl9RVUTpmcOoEimuv8Lg+Zz0pfUMADCRW+jOcKFTUy6MDLfBZNW13zDy3 +2qGYYLJ+7Gu2rtFJaqhHIHD+rfiIhU22Tat3ZucoKpWt8DzAIrdjXkQAutL09CwR +plaJah2zwLRhPsGLuohgy37rDnV5qqHo3JsmjBkcqd1wY0YWri22DVtsnreBgz3U +eXvYC0GhbKryrWjnrOYHDuzNwWx8+g4eZCM8WDoK1QY3htlMFDLbi2k9NAPSCjyM +jRLJ1rC2lURGi+wv2UE5imLRy8bL3jArKo73PKTzzfr+YUFEU6bPXdueVBKnLzhv +ukL9qpOW95GYExDqHZULAZft3dVbNL858NgeHpT37W1N+zGDgePhF8ZN4h4v77SK +pcQz2tTzUPyn5VWJxyU0EKYhAV+oYre4VNNVEMfr0X58JnqoheY/PKZLyRZkhXLs +PT3D8HxuG+cxRKU3DD5URwjgmlCbUW3v9pe8Pe8QxONf9KMPzynfDt4MZPLjaJAL +sNv2wEoJQqkNbBo5cI/Vbwnz7GNSfeXqRI/987qa8iO16TOmCkF9W8SbddW3JVRn ++gSeSityUK9C2sCUm9vZ9ROVrQ7e3+0jlJZCIxX0j0uoFov6VrbPgchaH7oxRK7e +bekR4QrOCVmVBkWH9/gdsFeKLj2bkMbs+36p4PSuM1gXDeeA1V7LPqJySJwibWRH ++mmQjXlv+zBS/9jj4Ow9FlI4ygqigN5uT9CqifdKjeNH/giCQYR6arJINl8avK80 +OVVvrODXNCvZz6nboIxU7K1RL/KPJYItYl9j8eac5xFSegrSKcJZeix5nmhNZj5d +a4yaW5DVwaRwoxdflC9+qULdzrzN+SPxrtOBd3qm2LcfuyIQal7dJoZjRa9lz8uG +j/6eJNoLnhgQlEw++yPRtPLC/QzHs6/KMHKAMjBfBeKha4EDX06jb+EkMlKG3X80 +Nw64DeBngCkkNhNuDBGMTL9kWI2JOfb+7Z0uyWn3X5GCJvZ2KHaykK3Y5wRLTkm/ +1yrdBJUhE6SzBHjKHiPDq3fLkPEwmmRhFRDenxWSSqidTphO6+KIVgahMxBNePET +W2Y8g/dj5mvxQL+UOKRA1DVMyHR0ry+MsmZ6alQoKP86fWQjOMnn8G8GGQCzhPEs +qrRFobpoC4NAr8b2wK0t/75vyknMw/V1Fji/qdvkkzSEM61HgPJ4wczuXOexKv8A +VtToZyhHd8uOjt8a0YlHxm5MB6HLAoICAQDkbPadfxru1juQ0lbwElQljp+XcvLY +RaDpUmM8W8yPK9zYOt+lLzdpZzqWJRHZXO1J9jhCmW3HIeNDsh/Shb56kNFlsTBA +C/FJ9SgeFghHznAcHnhivSQUqepzd03OCZssJwZPIP5+bx7HdS9pGuTZuju50Ff5 +ZRJOZeg0TXbFwmB9Ym97e81zIlbQ1Ul94IYmxRHurlu5jAyOSHaz6mGcloiOVu0L +3zGn3TTp3Qvhl5p6GQUtHdi/NvU7MDaaRtIMPXYjJWlmFJL5jxX8FFng48y/pqKg +F77Sc9ZQnQTkEE5bdeccWoFVQLP5rNrgfT078i/eB9tgMUrpOb2R08oLigj6cSg0 +JjYm3DfnSqPFHmTL5IuB94xfP+ond68bc+9ru9KMp3gKE5yK9ppICQ8SFQ7cYli4 +wcAu976ke7QHL+RKTxUGXZRvYrAXCanPvXqRFXDUiLCSs8CKGJNYLo+gGbmldgkm +kB+KJrEPduiqJ1RwHTO0/K9XM4h98SyKM8Ee1pzDpkEvtYR6YbOfRZ7Vomt+iN4l +nxi4q+jUSVKCaP20VoTRky5f9fSzc/H6SdZVSk9zZ0kbbQvYiSBD7qOyfyXJsuBq ++fv8baZgNmo4MuQQE/mHlZOg65n+66oUiuENxhakW1kQ3eBByiO9t8LUnLs6KhX2 +9iQ+AaC83SW6lQKCAgEAwHvt4xwp2nZatFcK5GnCAokFV0klfspIw1Tt8oAInx3F +nKU8kKl+myv8FXU8E5zrV7+0fWSAVTaOiC90b3dF96ozMPYk8UyQ1GAWtlxIqfW4 +hw0LSBzxO/WaAkIoGClIdNFuo2hdofRtuofnUQAZzbf0bTlFLWxjQNQLXlOw5RtY +6WElkd8y4idOmEIDanNk5yfe8UxHlTTIGs7aB6Y8zToFWuhUDHlf7DflbxYUGqQz +k+k2nAm0oxhsBxcEWT0h0EEPtOgvHGysWIe7Q7tUrBk1eNSJsnMg1mQop4cQE0Xz +9GqXpui9QsPd1MICmzPFf5wKjMLyij6R/H0ptbfsNRy+nLWG5iOU1N0ANtzhxO0T +WqxqnO/tOoGNjAHjxm+AdMNPUOFySjrKJVewHhsgEnd/nEPuJ9RAXNxJ3T31xu/h +zKOmkxnHVhTFOm2HPkxMHGLc1nOdBwtnyzi5Q2iU3WVoENQLfLzVcgnMkjWprKXT +BAgwU4LgvlfunJ5vF0iEAlw2iv0kGzGFqZiWJokR8036rGz8t9PWPdKBgRyU17bT +8iN8+9368e6YatrBlpY0OhqDngxVJXzQonCV/c+1E6TVrjw92veZ6zA6F4mI8R8A +cHNqgm6Qlp+vEPwE2SDvUJgoLHG0SinWiK9hcCK7gclaeVLJLrG9dnR8rkvGkRsC +ggIBAKc2yOPExTsWhNzKOiloAy5CB4s+ZjcqLBv8YmVBhcAyoeLKfXS6iN6sSsRs +ZZQVr4yBHConwWXD/fjFydXui7fn/UzwDzZAcFCU4KVKeeCLO5fcbGSTe+KaukU1 +JFDEFXgHNsyC5bUPu8naPvxdlRU876GMej/isjk6Ipiz7P2rMozNVclP6QpIOMdn +ZiypxC0/WqJ6kG11qHDSejwJvS1IgRFp7qwZcGpNrPkTncAWYpnPbFxx/sLRlp9z +wu9/Yj2qVm+nD6ZY2edMHIxz4UfaUrfsiNitLomPoqOuBi03HpGpO/exLWpRVF31 +FYdntaewW2IDxnZrHjFEfU9CpWIDSd6lD9LuRNoNJGfwTS/jJ8ktHGKIGISylc8Z +1bg3tlvyWlQK2QkTwoIV1/PQgQInT1lZmSEpDE88/H5nwEz3Q6oyrHZaNElTVQZC +A4wxOPlVPdCzisH9sZqBUWI0e2bz4S2UjTWhDIwih37sVbhALisv3nDxjdfOvTSe ++Emyy+edZFyJ2nM9VeTZ720Z7ghwfvpvuCiIeA5Pz7TiU5b7gspkSgeu+UlNo1Dy +7SH7AV0L8vNZPJ7Q4/OHKhor9W4WcEWeVfbjxen2Ch+JFFwhVZqGVKbyqZ/1yDRR +nmD6x17gefO9g1kgyZbpC4f5eircIdqBZnkbRKxZM/YloRkTAoICAGrtwCs9lgHA +qG71Qluqp9n6tvhVjJMe+A+gOx5OsCfT0SbuTQb+dA3J8l0mFCIxSmW0nfi1HPN8 +7LoBxQQKvo6YbdBAXi4Ul4OqKWgswsLTDKV04FUDokYW0/l96OheGbAY0UHRShzM +ENDLiWKOPulmU7i4Tc5XfLz6GqMrreFmOCuRZVrUCkl4VoSv6yBNzJLtciGH0tX/ +vd4YcEYF2T75i4E2OyHoKsEoEDF5ZTUoDX4pb5qCOkuqe/2EakdpOPZz+dC5AvqI +THnojrSRlMBUDALqskwWQLBi5OC74IS/CD9oBhQH2JGFyT527x/lTaAUZDQa5hum +Why9wXSInjM1Xd3b2HZFq9Ni9pDa6v1r0f0xHPlekYuKnHJXa69IgTJ4fEZ5qBGz +Mk2qnJN+c7HLNWMcfEo62vIcjyVYoc9w/KdJFApNu/1L1BnKeitcpNZzKU7iXLZb +8UuimHyYuAujD6qc9kO5scOiujeKwltu4xvD86V5lb7dDxTNjsXEoGKoiLP173aG +f8aA5D4yqxONQjNXHueXhxoB5oHQj4f2UbWnZkg0SR9riyo21LU7DH3nc2COaFKF +4cVUsqfz733sydLLRit85vnSC8NZDXEUJYLNXq1Gw/hMBKy60DPkSeqMc9rkKSQ1 +qJnOB/6ylm9UKovK4rpxDU93VW6R3qinAoICAF8JSjPxZCDfJq9q14rZcIaJrw/z ++V0U28IMD2BCTqLwYglQEXD9aONdDWbQJlC19IWUuQAyIu5GTi3DA7sSbYdXXWMf +EV418orFrerds2AENx0GZ/cRNkJ6v3so2oZndNMY4FnPk3OO7Jor0n32X2/lS1ZG +0ZtBV4XDLY+FIKEyKHYCYz/h44GVrL7biR1nqM0cWDRelgIOabzoCndyP/O5IPjp +WDCx2jZwI7s6T7FEp3CB87/4T6Dmat+PPlbAnJaQtqClGTbekFFix5jLsUxvPDBI +ePpGSVmyw624fFdSXy6NiogPjHNUMKlBjC93aZGM1hL3IMLhc3JoRD/nb/bhPndF +Z5HUVveNrZHBJqp5cDOoy0REQmg+ckkHI1AjrAtt+mwqFpNzqibqRLSRDoCse9PQ +XNxi6TpvyrqFcM7DNc/lEOAJKCvyHtFJa5nYo0Xfm+bUAgQXEfE3Wjnu8V+SInMH +I9m41ty/qsUtsIf7UdPF6Io4E2BkglzuZW7CIhzHHczD07+FKx3Qi60t2WGZoaEX +/xmm6WJ/33p2vMhzb7rX+pA4LV5JvSmB5hhOzIXID/TvMFC3fn7qevZHztzlKkCu +WRWNgGPgFDE5adPTysZp0/o0HULPZ2FbOLrSajSAleef4OowVeo6YPIPyyTc77wd +7PV6VCK5IPzFauTz +-----END RSA PRIVATE KEY----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/root.pem b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/root.pem new file mode 100644 index 00000000..c72db0c4 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/root.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICazCCAdSgAwIBAgIJAIapODtu4lC7MA0GCSqGSIb3DQEBBQUAMDAxCzAJBgNV +BAYTAlVLMSEwHwYDVQQDDBhOSVNDQyBUZXN0IFN1aXRlIFJvb3QgQ0EwHhcNMDYw +NzA1MTMyMzI0WhcNMTYwNzAyMTMyMzI0WjAwMQswCQYDVQQGEwJVSzEhMB8GA1UE +AwwYTklTQ0MgVGVzdCBTdWl0ZSBSb290IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDGRDXC0puY9VW7WGUMrlbWebp6w7NZ1gkaDueFndEZMmOhy2zKJ63n +XbhT+lCTPOuRQggRXxOkMKBp/bNjr9B+gDBX7ZXoqXpfrOW5Bq2QVdACmZoCPlKu +qBJUbVJYnmTmFVqCcDSDp8ur8bTU73zPnad82Si4cRzHDeNbc6qX6QIDAQABo4GM +MIGJMB0GA1UdDgQWBBTvK4IKCKTCXimA0jEm8P6Yb06bPTAfBgNVHSMEGDAWgBTv +K4IKCKTCXimA0jEm8P6Yb06bPTAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjAs +BglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwDQYJ +KoZIhvcNAQEFBQADgYEAmxMB3REsGZTsdQGCwTCRo2TaKdv7bVt7LTxsrlThxkQx +YMCD5jQqS4OIgb8BSZ33U4orw/1yDdeQaJMPvLIh99Kb83tSmxBOKC2M1zOSo5dc +O9mKHisxF9Gd0a0kRSVXkvxEpfiZUf+KiuCBkBMA9+qYnflrXYW8K/EpwZrTYYI= +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/shintca.pem b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/shintca.pem new file mode 100644 index 00000000..f6eb5a30 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/shintca.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDETCCAnqgAwIBAgIJANE8GM83L39gMA0GCSqGSIb3DQEBBQUAMDAxCzAJBgNV +BAYTAlVLMSEwHwYDVQQDDBhOSVNDQyBUZXN0IFN1aXRlIFJvb3QgQ0EwHhcNMDYw +NzA1MTM0MzAzWhcNMTYwNzAxMTM0MzAzWjCCARwxCzAJBgNVBAYTAlVLMSkwJwYD +VQQDDCBOSVNDQyBUZXN0IFN1aXRlIEludGVybWVkaWF0ZSBDQTEkMCIGA1UECAwb +VGVzdCBTdGF0ZSBvciBQcm92aW5jZSBOYW1lMRswGQYDVQQHDBJUZXN0IExvY2Fs +aXR5IE5hbWUxIjAgBgNVBAoMGVRlc3QgT3JnYW5pemF0aW9uIE5hbWUgIzExIjAg +BgNVBAoMGVRlc3QgT3JnYW5pemF0aW9uIE5hbWUgIzIxJjAkBgNVBAsMHVRlc3Qg +T3JnYW5pemF0aW9uYWwgVW5pdCBOYW1lMS8wLQYJKoZIhvcNAQkBFiB0ZXN0ZW1h +aWxhZGRyZXNzQG5vd2hlcmUuaW52YWxpZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEA5GzD9U999DVDSodhjSe8zA0ywb+ILPJbdMY5w3ezO2nwT9eNXeMHEaZo +ZTf0hCRR9SSItC1VdqWtNxTH3FU4UJ+G+7tQ88EbfZeC4DUNtiBDgDPbv7a5aqaX +uWAGoh8rOMVtXOU9iEtsykCzmXzPWZr9GVZYx8dpPamqcmSwPTMCAwEAAaNFMEMw +HQYDVR0OBBYEFLkUe+/fyTGRS+KvoSBZnTYTw9LuMBIGA1UdEwEB/wQIMAYBAf8C +AQAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4GBAG4u4Y0RV5X6DkG/ +Y6INtyh5ZSpyLXNq/qaZVRqU9MR6vOmCPcYWhiwk5qZZmSc3LrMu8iFwFUM9xGg7 +cXftVLjPGNvP+pID750yGaYB4dW6Qz/kC52ocrnYCVaCuo330gohjlEvP2nZXOaP +if+dafdaxox9HciEqdofNaTeC3+J +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/shroot.pem b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/shroot.pem new file mode 100644 index 00000000..c929e1de --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/shroot.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICSDCCAbGgAwIBAgIJAJEbu0HhLX7VMA0GCSqGSIb3DQEBBQUAMDAxCzAJBgNV +BAYTAlVLMSEwHwYDVQQDDBhOSVNDQyBUZXN0IFN1aXRlIFJvb3QgQ0EwHhcNMDYw +NzA1MTM0MzAzWhcNMTYwNzAyMTM0MzAzWjAwMQswCQYDVQQGEwJVSzEhMB8GA1UE +AwwYTklTQ0MgVGVzdCBTdWl0ZSBSb290IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDGb6RviUn6PFdaRSnHm01Uhae6AYxYZrPw4MMfEo2YsgtSl4jFALjJ +/n1yKktD8E2m+Yd9c5EqBNNptdtptQ+Hw0wi1eXfTWszD4vuN4TyPWwzu5AqXZaU +0c0cgA+yxl4zs9sBee9S3ByG+iinNw66dOdOKiMnN1KlIbL1tlBzxwIDAQABo2ow +aDAdBgNVHQ4EFgQUiHYOIAYFenwAEGRi9uN6bUJF+eowDAYDVR0TBAUwAwEB/zAL +BgNVHQ8EBAMCAQYwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENl +cnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAA4GBAKdcrK9KxfAA2U121VkIPl7m0iLl +wVdrvWGw29HNCkylL9Y4IBc+3FYbnR0rXEIghSpJHUe0UxGEMVV4swWj+G9FCbKn +WmLZRKDQ6mLsJiW+jNOO+Zv78Ok3uTtHz8ro3+7YtfpMwp8QGx1Zw850pbMlZoiD +rj2vxXQ6sBA8CQl0 +-----END CERTIFICATE----- diff --git a/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/ssRootCert.der b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/ssRootCert.der new file mode 100644 index 0000000000000000000000000000000000000000..53767b1050f7c564d52df81c1c9a7fa5d1b26321 GIT binary patch literal 1767 zcmbW0c{J3E1I1@EHI^nL5+(*In#Xs>nyn|h#0ZU);g!h{8Dyt2p@y*x=Gk7Q!N{|Y zHO-5V@MJBF{H$4emWFI4%j@?$=ePX*`|F;2?>YC}e?9;W{t=)-$MT>MFa!caX&wS zG>8Dy-2K?hG|M%KOF|@9j0GAJSe5Aa4^*FBRVv}ZtBs3E;!3jY``bvk)1IbLcjkC5 z2&8prF69o@h`a9H<(3q@>VVtP7_3A)jNvdvye4sCEM52RlQ+83CEDVRoBIK2E2`u! zxqL-Eshj+H*&X9EPAbJejhF1z-}Gf)dxGBPV}A)%F_4=92V|I%o$bNna<5En)qYMf zvCj(Ni@F4Pe|G}w$Jv19CqTWa_Hx*&pqkSOXkFpc4Uf}aN|dckA|5mp z2Co{$sE?t8hMjidh=w^@ZpZs?)o32OE`32`U)f%j;f{a)=r~2cp;|x0=JlM0Z*XXb;qS|9 z8P@ex-c~#~b0GKHRGg}V?6C%LNAZ8c^E8ovN<+6}80`{Ep8lkVAw(9cY; z-C6jY>9m)uC}q#eksa|koNm!+zO?4qk3(?FUkio|ZY@p#X^bfAFMjypo7uk(3ramW zDWA&E^EWNxh+!QoRv$QL)onE$^?!ujrd2|p23I>7ml>p2SV4==vBn$?HKxzQgKaB(!ybn7F zz<=&XurL?Cg8>bI&FdU$kDnO4jrUQvcJEgt{)pno>1n9juERpi2(cIEr*!4S;M^9y zxRPusj4AIn_=enaBdd22QU~0)t;o(qZ8Hn?iz%f+y2@otf7=BY{fqv+%T4T=hoe2) z>P7Hk_v*9^pJPZ6T5C>pI3hHF4=adRxE>;ajm6HUhyHnxr(UaMHx~2UwsgzYM8@I% zBPKna5%!qx9#cK>z~lXPNt|=#2}a(HLDGRExwtxsXI8CwYg!fN4Q@%@K9rev6Z4OJ jj|lRoR|=fJSMH0S-J~^?I@_GTSLNk+_B?-tibDJiQ$sD% literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/ssSubjCert.der b/SecurityTests/clxutils/certcrl/testSubjects/parasiticKeys/ssSubjCert.der new file mode 100644 index 0000000000000000000000000000000000000000..258178bb9c039a7ec184567a94e9473e86d0ec60 GIT binary patch literal 1745 zcmV;?1}^z9f(Fenf&<5(0|Eg80s@C+Fbf6=Duzgg_YDC71u!x(7cdnD162eH6AnRe zaBO8DLvL+xb#!HNF&8iu1_MB+?HZV6bH8L_X zI5IR^7!NWqFg7qZGBz+VF*PtWS}-y(7%&zF162eH6AwXfaBO8DAVY6$aCLNLaxoS# z6b1uT1OpQdL~nIxAWdm>V`yb;Y%qcY5HJk}2`Yw2hW8Bt0RaU71A+qm05F0A_yU3g z?*QGBA8yklNq>#U6rQK#62V?Cgn$n+3dkm3m|0_YjE5WYiKUARs-_l*f2E;Yr~8p5 z-uOFYVh4Fh!B*M)>FhwI9b+iX?Ki6&Kgs;40=9C@#hW)~z;~biT{SGd*yp{wOX)@S_=V z1!NSbcY_nl;aXGYQ3gtJL^zdu)A)PXQtr57oA#ZsE7pV=f2vBU4fEb8^Qu8v+=W*BS}oR5mbS(fK4tYEcUc)}|1?oA=AC0zd&h4p0Oxq;qmm z>+I3U8UK;?f7BX@jhKSm1FJbH*wgIQoMC>wHP`b_(?58o*uku!+`x{Q+>+u32fl(i zra)Gsy4-W`q@Phcvt8N@Z^=@!a3w+tLKg{DY+|8{a%)u#%qZF(`a8}rTK76u+M{mY zVP|gCFLNX3+jzMUFfIP(fu2sg7IC~D-W}w`ndG3*yk(9)!ri`(;qhL*=HiW&Lrcbx zBgn?CVBmv#cHjpV!Ui=*>aD26x?$0TwRP8UKks?=zJk+hIwD!B zBx$5@)yB7m4p^4XM>S{+53WA)-%NpxmRZqZUb9HIC^;ID_DI8dBZP5rvM(ym)IU%Dy(*Y*O{AYrI1mq z@N8S9o0evaz)Q^|rHa;ZS&L zNQUe=@Go_k8SthjhaS zyiw`%EV~bDpi=z(L0jDFX`$^&o&H{2;p)94Io~c@=`8fzgh$~gCdU)}!=jMxO;lJm z2R?nbcYiAqmZ?Sr(TpeQ^$8MXH10m>!s7s7a7r9tnY!}Kv#_|Ht${R$%wwB%Uw>0N zJ%~6k<-6yiW&xk+P1nbjCsQ^uM<1N4?p3Sn`M>V}ep1X2R0u&uS2cVnC%H8rh^ zR!3pHf}{xmW?>Pt1ihBc2j|_9m^j@8l1^2|@V>Rk z+{E#%lT`Y+jj?tCy!S5xlQqW1paHCi_%9SHd_xNe!N{kKvh6ynBRIa#iy6JSo{VIB zIoIPcm2%Qc#0CqQG1%MqX5t-o%Qp%;Hz6S(W3Q+i?8y6L9nN}pg%)oeBY@+i2PjzJ~9@f>U&Ft64Vng@cZAFGrPkT8Wm n7zsu$MER%@?D$b{6dd})<$|i8pC%u z7YiE*8t?-{N>-SW@jnZz0W*+7b~7u;&5aC`kFv2%nZcmCOu)D) zMmepXuVCMs_Ic9LmuXCfL4G%jE2b=e1>?6v;oNgH({(r;P0Mt0|&tovhQ z+IN4hkH|iTO-DDaE|{k~Jtj$b%EQE~KJvHf?>m>d?T%kQd3(~DlKS*5T&*rL95YpI KxlTuj-v9tHA+2Ko literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/pkinitPolicy/noBC.cer b/SecurityTests/clxutils/certcrl/testSubjects/pkinitPolicy/noBC.cer new file mode 100644 index 0000000000000000000000000000000000000000..2ba5da33f640b8c1487669e52be52cdeb08a245f GIT binary patch literal 480 zcmXqLV!UI}#OS(!nTe5!iIK&Cn~hVe&7U~y_rnr?As zdR}UZLSDXtle3|?fhb6hi-*s#pdcqz!8t#-ptK~l$Ush<*TBrc$k5El$iUFpFbc>u zN8*xeY~y?bUWDrySs9ocdl?KGJDD0A84lN6|E=?N%65DA@Ra4cELWFs_j8$+a^%)8 z+PXC9c=_J6m$JcTKNvGtHwgxYzRNUNaMo2@(qT`R3*Q6{{vDEA9UFdcd%0|j!=cix zc{6u1uqaPE6>x)L`Hz);KKt2QvMR2MdFRF?M1( zRl(CQ1c|OmYxZS&ly>&&Tr>MaTpj``<=o5fiIckl@d&Kf literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/pkinitPolicy/noCA.cer b/SecurityTests/clxutils/certcrl/testSubjects/pkinitPolicy/noCA.cer new file mode 100644 index 0000000000000000000000000000000000000000..baac59fd1026bfa7a2efd3b377c72692cacc554b GIT binary patch literal 501 zcmXqLV*F^(#2B@JnTe5!iILHOn~hVe&7U~y_rnr?As zdR}UZLSDXtv!kK7fhb6hi-*s#pdcqz!8t#-ptK~l$Ush<*TBrc$k5El$iTqJI10!$ zN8*xeY~y?bUWDrySs9ocdl?KGJDD0A8Kwk2VLTKel056Z*?*5Hw#Pf-)OSpq{MU@r zdUoQqz}IRQ=dD=K6~IthGE2pMtH)74zOde{504(xP(IwOl;QIw@ujMwQe5h%Ckif{ zD@;?Cq~!Xvl^?vi<4gGcC8aD`iz>BBITTNLcs=-8aVkvp@GdElO#yOSl#D$-M=Jc- zzB?_FiJ6gsaj~$0paDNHOk{-_8UM4e8Za|5G9bH|73Ahd2CXM^WEK^sy!^C-?ZJAX zUC~`(!J0>t64@mCn?n*FKjKw*XmI;)>B5uW=DYT6tZd!IJw5v}^If$q@lapNY_p4yxa7GtGVSxB!z-1OH@aO~ Vx;K5#Xb`O5yGLU)M}T_Mk2Y~Y!Wgmk_@5_ z9<@-U`iH~fL18+gw4h?uR9kesQj}6#&{k(E9%!vdGb7!VlG2Xt-~QTt-|u~&@7Z^s z_kj+)9y$c&H7Fn9^Rc99mm8rF_nKL@xNJ~}AOZmoZkG8#FC1Nl;Ua!gx-0|+ae=oe zAj@pXB~%&{SfbHs7)m7zhts(uAJOD&gMk6b6wPSV8j@f%20chLGX(}(!`NgJIGZa& zMd2QV|Eh;mgM=^+%4M-~*_=4JJTFKn8yiAq48i2ZvQP*{2!?pz|0FmYBvG`^tRiGl zFk*!1G=<4z*67#%E7>3zI6~IXgQiGM1ToNogpQpQBH*D8#Gl9Jz4;CV;hoGnQ`hG- zPMsuAdHj4q03rxhN+P4anTbEJUOHh3A~rnjsNAL~684Gfx>~yOCizrs*%99~oGGxR zn~GYfA(yi_@X3rm?UJ>o=f-ktn4rTF-`*4Wyy`V&+bQ~s(UL#?td3+++_Ks{M*kv!wOv%_mwrn zs^-|_rKo#y+@>?d)#B_8r?=_WG@Wkjiux+c$2s$gpCBWF<2kkGR-Hm&(95JM01&>WUg!c2JeSAK&x4mI+&8D;(LQhhF6*yBs z0gp!hA!rKZ+W?`r0V6>(>>DdO9c2OpNm52;1VH@?fCbS5!f4d8Ym={~fQda-5wr?0 zta8}~y$X;9y-LHalnEHrz-*#kW&d{jUzwfa}YK$1aaO8{w^ z>5D*`)~2^mS{2Bo2nM7Rv{geEf<*?3R#94t204k)-poNy$LtNzUSBe?JWcn|HKPp= zc`$eG;eoxS>n=X-t+kgPu-pH4D{^27t(oO;0mpY577t@#OpUBYS{D7985-1T6Ki;s zgf!@+B(3!*QVXYW{eGAjn@IlPnqN&0WK7QON>y$zeOKCb`}eV~!ul`kDhN+?_)%5x z%E!Lf{jOSHmbM+5-oLT}Nh`?6b>GGMWf6~Rmwm5&t8&h@mJ+B)7@VT?3ij;|h>jHX zce^J9bmLXW(@uvp-E3anel_=s;$ZYfiE?V#a(czjMx`L){oK!<6lLI@Gj3PMxBIr0 zTrN8}&=7ge{k(nOg(3xgQCRooi(A%DOwGsZkG_W<^Zj6G*{P#-?lX6f->Cr3*6StZ zPQGo|{nZ^O3VCyOMz&@*oXlxx$?EwvAW9m1TjU? zkD?+~W*MCO1~lFLm;jR>Yw>C{x3Hocr?GL?=9PDwGPm?k~j{;zWNQ85Ec zNf|Uc9~GjZeN=$fM^Ty+MX_J~kkPiX#DDwfgWQ2(_tt3JJ%5!?c&q+;)gAulbuT&F zKeN{!_=$Q|=uX`HO3a-%PtL0=F)!=MUO3-pF_G4&o^ef@;;3D_n?C?O&vwl;I$l2aAC8)|DG`jy=r^-a&g z!t*WXwO<|%4O-q>e`(Vec3Zk->V;KWo#xomZ9ZKm?bF?$hr-(%6Gl-_^nSDvK3Ymo z4_0jJig1!$ZB5nX};TTvDi0aaip=2=2yTjwQ@v z76B!g3jhZ6|ATTMTmr%h(3SxYrV6M^L`AR@5IDCFi&fb}ro94lgcn4Rf$0-lm7+JO zDl&{LcLm{PcLfwdJpo`2vQSHcT(Vp#O-)X&s;WxrA3w=ntOb9zA|(M6tK zQP4kT6vz(uX_@jXD*sMYwpZwRP16TWFw-?I2aq2337pORsxWWB)N$l!4{*% zZp?uLYzMd|!DWJMf+!NHQsC_j??ja%<55vq;_XLrg7_j>?MUDO%tCB#ksu4>4`U-J&SJ@)5#I~1vcNnTF>gmQ#B)mo2@Y7kz#9XQZxp?&-JqczJV!c5GZ zd@(>?-t89?fKMGKzAcrGyEEFNceXWlZEW4twE0AFcvefy)Z&aYM{5qH?Pz%|`pWN= zCT#uc9k3*fft+U;gdkooT7-J~yOwnLY_* z<5wrv{WAUjjh&0G9pa`WuDYOK{NQ18N7~0{%zHy7?K++tzVMu3>E(>v2Zhc2#39n@ wG1E#Hv?*mNwGEk86dTPx# literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/qualCertStatment/badStatementId.cer b/SecurityTests/clxutils/certcrl/testSubjects/qualCertStatment/badStatementId.cer new file mode 100644 index 0000000000000000000000000000000000000000..248d08c38e51c429fe9c742b9cc8e1fe8bedf94b GIT binary patch literal 515 zcmXqLV*GE=#F(*wnTe5!iABgHtiphsjZ>@5qwPB{BO|MUp`o~eC>wJq3zsmTV?jYq zs)BQVZb4~DYLTIsfe1)~S(w))zcgLJH?t%;BQ+<-KuLn%$iTqNz|7Fd$k@Q#*fa_* zU~FJ$YGP;_MUJtJ^9^_rE@Nb6U~cSXFlg*#YHVa!V#9N_J^0#}xZQr=w>-7JBb6#3 zF#lYd+|$<$SNC79IB@Tf+a_H@oqyBjq*zZVX6t|YR#{Tvp204U)tfV?aUBS?;67+0 zvdp36XQck+hhGm{ZDg;FI&bM?%lzL`_xSlsi)Srrp5Uf3Y1OZ*5nkq1?|)ZX^a%Wx z%@*(tc_<{T7Z}XM%*epFSjj-aK#q+=n~jl`m7S59k?}tZzX2~&c(OAhdw~_?g+_*~ zNq_#E>E7Kx;i<&qyMpP8f1bT9eI(1KJR`8?;tkb3wO{|ed%rDm;aa8J&aCsYT9y=g z^=GjxNoTt}TQP6S93}S|&*n|NAs8yNf8EK?mx_y7uS)Nlbbz~L$*~{aon>W>kJNX? jYn(CulCb9D^Nt4z@x}7XB^GQ^m}A-c=)(3jt}`qFd`rAS literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/qualCertStatment/qualCertStatement.scr b/SecurityTests/clxutils/certcrl/testSubjects/qualCertStatment/qualCertStatement.scr new file mode 100644 index 00000000..79b5af7c --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/qualCertStatment/qualCertStatement.scr @@ -0,0 +1,32 @@ +# +# Test Qualified Cert Statement processing,, Radar 4449558 +# +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = true +useTrustSettings = true +end + +test = "Quo Vadis" +cert = ICA3.cer +leafCertIsCA = true +verifyTime = 20060701000000 +end + +# we don't know this root as an anchor yet, so use implicitAnchors +test = "Netlock" +cert = Netlock1.der +implicitAnchors = true +verifyTime = 20060701000000 +end + +# this one has a bogus statementID and should fail +test = "Bad statementId" +cert = badStatementId.cer +implicitAnchors = true +error = CSSMERR_TP_VERIFY_ACTION_FAILED +certerror = 0:CSSMERR_APPLETP_UNKNOWN_QUAL_CERT_STATEMENT +verifyTime = 20060613000000 +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/intermediate.cer b/SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/intermediate.cer new file mode 100644 index 0000000000000000000000000000000000000000..a09d0c437a0168dba834df9e31d2a36320fdca07 GIT binary patch literal 508 zcmXqLV*Fvy#F)5%nTe5!iILHOn~hVe&7Gr3tDh@)eAP!gZt0U*tF`(n${f~*3W#m)9ZXCQ|%pPt`D!p zue8@VJS=&)ymk566*XG37%qHyJ6U^+=F7v6#o}8{B^9*OzA?)7?CETu9U3e)aBG4Xzbmr%yFse!LDP9yhnbV7d#Z>YI4T**EU|p=(;UAJO}Nf z_Ui6^x$tOxw(;UAb!VU6R*vo8U1Alq|Jn7ht5Fs&S&wG-o{%c%`E|r1uP!+3i&sP4 u;YF8UyiaFmagOWa^!_~0kR?dZUx)4KQ|1NJ6tabX1UzBy)YS7VZ~*{bIkYVR literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/leaf.cer b/SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/leaf.cer new file mode 100644 index 0000000000000000000000000000000000000000..4a13b6757a5d51c02c36d23b1f9185364d4d5dbb GIT binary patch literal 540 zcmXqLVv;auVr*Q%%*4n9LAk+PJ)=I(fA0FZ`*u4jym3hT&~Wp##{!0RQrQ8n`p%2XlWmk%G;#%6uE@OF z^?QGh#`JejypCtA>D%v85U(9Pa;JE!&y)=AS$A1B?BCPbHFsLy zYCmtgG3r7xS$blGn0n&oM@Y16z8 V!K7nzWCfmVIxJ%xYI^bZdjKFsynO%w literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/leafBadEKU.cer b/SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/leafBadEKU.cer new file mode 100644 index 0000000000000000000000000000000000000000..c63a7d5cd30a03fa8ceabcd1ed7086154fd9f0f4 GIT binary patch literal 558 zcmXqLV$w2bVw}8ynTe5!iIK&Cn~hVe&7kc+ERsJnuv zUx;gvud9ovV~DGvxPd50l8cAWv7jI)Rlzwwx1h8nwa7qDoY%nA(9qDt$iT$X#5@Yf zHACVWcp2&&=t9g@gP0rS8tfk$t?CI{OpsSFVuTWH6l&nyknVzTM>K%&PuEzNW zya+clvNA9?_A(eWb}}_KGJNq^)V$}-2ZI@fTls2(B4*5DyZ7Kzi|wb(%+(eLUq{5h zVKLsB^WMBI=lIpXKiIbBaGW@kbE>2GKy#$yFO8xV4>xt2J8V55&}f-gEMwkvTI1-Z zb!-9?Cwtv`-Fe~0`I)~1O}!qgAD!agR?2_K#D3;3bTdW{& zH8L=Znp(A(m+xI#r2FppY)4(*<(-{VZ(m$){YX>h<*HPZgd5M-`~8@8vW|Jh-J(6Z z@tg~%b5Cc&<$#l5MwkpT%lkuD?0IHcTpYdue{#uDbE?i!=aiH^=h; literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/leafBadKU.cer b/SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/leafBadKU.cer new file mode 100644 index 0000000000000000000000000000000000000000..af6ac35adb51a13c61bd0e6251b4b3e0b50cac39 GIT binary patch literal 550 zcmXqLVp1|_V(ebP%*4pV#K>&G&Bm$K=F#?@mywaxz|2tEK$49)l!ci`$i>wu)Lp^T zFT^#-*VV<-F~rqS+&~m0$;HFxSWu9Ys^FZTTToh(T4W$6&TC+5XlQ6+WME=xWD*7B znjvuwoDDS$)F9@{L(C0w4fYQWa&}b+_H_4C&{fFGS18U*SMUzSZAs&N173t<8Ce;a z8+#cH8atU98yW6jud!{Jly>Vv_r1r{V~ju6+vai`>s0@ciCY!Yarkfy!w+ZUnTieb z`#-l#dysAZKvHu%%cYBQVdqZn7ihQQES;vr=I7J&`f|HN>oJ2VW~WjQPRnoH)^z*f zPsxl&ZJm`_X}%_TCU1k|93nZyrk{N?b#3IS1+6=J!^|2_R>By?dFI#`imezle>J)AAd8KKOTEZ7k%SpF->zo?C f>pbvX|8Jr7p8UY=zf4~LtbL&ye6^at`bZxDTZOx{ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/leafNoEKU.cer b/SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/leafNoEKU.cer new file mode 100644 index 0000000000000000000000000000000000000000..b24dda08215bc696b69f2bea0ea9305c81d1ec1d GIT binary patch literal 536 zcmXqLViGZEVys=j%*4pV#K>yE&Bm$K=F#?@ml4P@Gn6)vWMd9xVdfEXadirHSMc-; zaSifyb@6lzaWxb-5Cutc@$fko6y&5TIOpdUl$N9x8OVwA8kiay8k!gxm>Qc}L;<;G zNL&LiLwy5Xh`DMIbAw!i{X>JCT@`{o-Tf4F74q^Gii(Sp6^b*{^AudYLvh>HINyL5 z;bulw2Ij_I27|^+Gt#D;*PNJXeJqJ}cEOYt z_4QK}B^6SYygOg&TqxIa&(mmSnfC5w$3X{cvF>2OKfRx?=DDYCc=sXouIq_ag2yKL zcP+|#d)znqVK3te#>=Zi)F%oX^1kx_*xjb5WUbg3HS1KHr1O`JwM{2mI-Hr985tNC zD;UTb@B@7-E6m9FpM}+cnURqJ7|uWeeijyHCiVto53qtf(8y596f#@tT46=^nF<{< z)fD!3j%|Ngr}J#tyKQyYB^fQtr0CR*dWvff*IsKnDV-6c`_bo++wYt0_p;5Wb$T7U zzjW)ggXRafN7&n~_OG9*`iiIa$&WW|dT9=u#RLCEeEs!ws=-d_g7zu<R8R_<~AmxW4EPp%athynn9Zn)|I literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/resourceSigning.scr b/SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/resourceSigning.scr new file mode 100644 index 00000000..d45d833f --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/resourceSigning.scr @@ -0,0 +1,51 @@ +# +# Test Apple Resource Signing cert verification policy +# +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +end + +test = "Full Resource Signing verification success" +cert = leaf.cer +cert = intermediate.cer +root = root.cer +policy = resourceSign +verifyTime = 20061031000000 +end + +test = "No ExtendedKeyUsage in Leaf" +cert = leafNoEKU.cer +cert = intermediate.cer +root = root.cer +policy = resourceSign +verifyTime = 20061031000000 +error = CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE +certerror = 0:CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE +end + +test = "Bad ExtendedKeyUsage in Leaf" +cert = leafBadEKU.cer +cert = intermediate.cer +root = root.cer +policy = resourceSign +verifyTime = 20061031000000 +error = CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE +certerror = 0:CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE +end + +test = "Bad KeyUsage in Leaf" +cert = leafBadKU.cer +cert = intermediate.cer +root = root.cer +policy = resourceSign +verifyTime = 20061031000000 +error = TP_VERIFY_ACTION_FAILED +certerror = 0:APPLETP_INVALID_KEY_USAGE +end + + + + diff --git a/SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/root.cer b/SecurityTests/clxutils/certcrl/testSubjects/resourceSigning/root.cer new file mode 100644 index 0000000000000000000000000000000000000000..9ca08c081bbd3054f195b9bf67cbb9147a7aef28 GIT binary patch literal 466 zcmXqLVmxQi#Av>NnTe5!iIKs8n~hVe&7d!$4zORXG+|YHW%rHObL7-lGn$IcJ9d=iob#Sz zma*kMPiyxUNNjasv%4;Gr~9K|3#0DbovIeIvRyt)RBws8#_fEkBRSZ3aop!muP?3h zSRAm&|Fgcme(*M7b5YNOi{}XlE_}1+|MYp9agw*o9n?f8Cp?(kk)(Qb+ws;7vzeF~ z85ohB#|m;@BLm-p>5u+3XU+HH;T_XNq>j<8fMn`IsU}`^AW>d7n>hEJ{(jZwR$> z{WNOzdYZhg-i{vB+Od8IH<+=>Iq$rCNAK+%50FEk5l8uZYTR<}r4tfCO+1&(G_hpW@m{X8Vj|9AJ8 zRzoCCEBil*ClZ>AY2Cteb0r^*ZNE058(~|PAH8&RxNhkB_h)=JJNJz~`RsN2;K;{6 z&JP@~J)yZUxfrs&scU=f#reZJ)47GqgI}z3T%G$`?s{wV)=WP}5R0GP7M=<$aOak( z_^I;)hJ^U}2i-zl1$MDLdGnp|rBTPd*(;8QikaVvreEkbq)*}mroqOO*n7&#CRP?! zVkU9WfKf4D@(4*1xHb*VYJkXX&mb$wO%d-*SfK8OHl2R@@567&J1!XxJ zYjnB(=hMSBwMiN22IY9uu5?wZQe`V--~M)GtKllY6wbZMRe)9is8FlR$;Y8At4CmK zZ#bpT4An$pa5$UBFp>j5Y|O@hrHWQ1MSm=sqXk>nSa{0y&|oaj=8)GWRslaJK_pv@ z<&!KNeEUH98R&s7=(Otj2piyB0lpuU(IJo0R+=1O?w^EE&S>YH(Pwh^Zq3(B?fH~C9x8pX=(%tAhQ||k z_&-i`SsrK`{dQC5>}=^zzgoYMe~{n3f1`Y6Y`FII5$nd6w>S3KCvG?|IsS3pdgCvH z|LWwIuD#*!UK*P2mTm2~cgP>+EnTTyo^~$%Srj_(_tci)R7K0!h25jZWANpK76Ip-u67b_Sm z1e7M_WF{*F6lLZn7F8-ZrxulDre!84mSpDVDL9svWaJlRmQ)(ZiSt^T8<+qM0D~xT zUPD7e10xe7V^d30%P51!U54@ovJgwfV3sO`6qOd2DEOt8l;;;^!(7FU;VNSTLx`)i z;5t3?N>YpRz^+KlQ3y^gDoZU=aCTJCRe(C&(9^&jqRFAWyj%|`ommX@r(SY?uD)|X zFvz?4MFo0El?p+rX?hAio{mnQKAs_w3O*q&dK$@^mgWjD%M2RlBZns=D+6<5FM~m2 zCsSi1!;Pkf7uO`2YUNucEL9h!YCqh6h4u2DXJ*!`KKSHBZ+pJVrr0%f)5pE9raQfz zWx^$TWo67)2i3bb*$*0RD$O}^YWL!QVd{m>tCGJO*iF`W`s*X7_2=!rewN>3Jfn6T zl)b#E>tBJvRHxJbv;(`NY^;7N`A^uyv^;o@zsd8}ESswHnV1xVpxIw!3Sy+Gxl+8d8 zu8NTnDg=sBS$P(qLk!dws4P%wQvf*v=!WE?9MtG4NKQ1?1BxO?0x(fC14EyK@y(Nr zDa=kEi$5wavby*3*MN0jZ_UY*afGG6^^4vPr885{S{j{K{_?=-a!KPl>Ud3$k< z0;lf7Zx1C|EjHNl&#(V6kLgYuQ(K~+T72C6Npd_YOTJzx5I(PV*xA-oc3zWSQ2ZXd dV`-X%F(s zF1n;m)@ck`RQ#Af6k;;njKM{WbI$o=(LW|e*@rV`f2P@nA3w~@WFZ*OZBr;F-sJvx z&-v`UTvgI=|K!({rvB&i+ScdKzKyE2m2J6!+~3s{RbF0( zG8gFWs8OpP(Nq~s2e8Nn*a;qjVp5V}2+Ju!oTTf}Rt2Cp)D!_0VEBlYwj;XWXe&C% zxr{|VB(nk^;vj&5SDJyZa5=m)|2=Na0a6kzxhzV;r z4Sqas1s~(u$M~4wli&+_tSymNXEzj+p{BZO)QP%mHkAJk60?h#T{gSJ>2MxInftUJ zRVvxE230>pZ$X-51o;q#dRJ18VP0k~m6Yuwny zri!L7e_45|H_`jWU(ePZ`T!lnX!8{u3CSz`;yuG&D>8r_pHY3El2JQdAwKe-G5^tb^SHl z3v74O59ZCU+|X5=oX}mK4t})Q`rNB3HC0Bvn^he`S=DHsokoL3h02JzopjWw)?`&C zV$_nqhWu4p{o&jIm0R{w6%>WC)B{tNdM_AbC5T{AX231AgiwVcAd}#6!W*;@ zrM8m5Qz4cMg*k=z9*D_uLh9-0*rJy zMPN}Eg@v<#&Ed3zTL_WubWLHa1qKC0oh%OrSe&vbo9669opu-rxFCo*E9|79rIU8F zg0qWm-?ht*$n`{8WG7;z4Wdih>FiqTypRUK#c|+QAQIU^Nm=5k72IBb(8UbFsLStn z4Fwr*06a{e)7txiR`PiH{bLv@Sh#6+j08J$w&6a zni{fc&&vGF0vfG3w(L6h`|NpK76Ip-u67b_Sm z1e7M_WF{*F6lLZn7F8-ZrxulDre!84mSpDVDL9svWaJlRmQ)(ZiSt^T8<+qM0D~xT zUPD7e10xe7V^d30%P51!U54@ovJgwfV3sO`6qOd2DEOt8l;;;^!(7FU;VNSTLx`)i z;5t3?N>YpRz^+KlQ3y^gDoZU=aCTJCRe(C&(9^&jqRFAWyj%|`ommX@r(SY?uD)|X zFvz?4MFo0El?p+rX?hAio{mnQKAs_w3O*q&dK$@^mgWjD%M2RlBZns=D+6<5FM~m2 zCsSi1!;Pkf7uO`2YUNucEL9h!YCqh6h4u2DXJ*!`KKSHBZ+pJVrr0%f)5pE9raQfz zWx^$TWo67)2i3bb*$*0RD$O}^YWL!QVd{m>tCGJO*iF`W`s*X7_2=!rewN>3Jfn6T zl)b#E>tBJvRHxJbv;(`NY^;7N`A^uyv^;o@zsd8}ESswHnV1xVpxIw!3Sy+Gxl+8d8 zu8NTnDg=sBS$P(qLk!dws4P%wQvf*v=!WE?9MtG4NKQ1?1BxO?0x(fC14EyK@y(Nr zDa=kEi$5wavby*3*MN0jZ_UY*afGG6^^4vPr885{S{j{K{_?=-a!KPl>Ud3$k< z0;lf7Zx1C|EjHNl&#(V6kLgYuQ(K~+T72C6Npd_YOTJzx5I(PV*xA-oc3zWSQ2ZXd dV`-Xc|~`~NBa%z z9PYlc9fuEZ-TXL|qx7m}nZS{Xz5nNKXqj&Q=}DmU)+e0PVm{YJ-)0hJc;voJ$~A3= z@UdI{JIocele)i8KFieDpk{GFq|<1XG2s7UnOQP7wlDyl z5%YLwRH?``?v+({AKR~dvnKA&-tEGICdsPoFb=h&Yn(h!rhCiRzS_s88P zS1wI6|CZ>!>4;IwhdM`xzi!Ku{fs{?ee~s1^V1!R8=DOp8w?bH5h^RlB55GrD4Gb4 z)Z$`?)QZI1f}GT1z2y8{10IkHVMfOPEKCLr;6x+K58|;fGqD{okO#>svq%_-HHZ|r z*fr_px8L)+T>98nVUM%+(jOJiQ|Vn>QG6vaxFOF*C`sG8hOM3K;OQ zF^94+3$r^X7Ucv5I~vG|^IBROSQ=Uy7#diZm`9288e19~83U22rKx3+ay@d;Hs1->E%bs>#c$mn(FCS)1CGOZlrJH2+M0^Q$S4-=JaN#(;TlE+2Jv-!M9V zEF+)&=7xkd``(#wW(j}&&dNIZe%vn8u$zhhCF@T%KKqgLs@oP7|4TU zm02VV#2Q3iKA51srb3}=)@7ehPUe0}>*iVPHjo7=;A0VE5h=g4<>GdquCB%BT<4y9 zW3#~O@&5p%aAgMidcTR$vp-oKjVpd$h%*4pV#KdsYfRl|~tIgw_1q-u*kfDG99~*Nh3$rl0b7E1BOK`A( zoH(zgrGbT^xq+dfg^@*+IIpp#p^-5VnOd4!Mi~eg@)__z^spx7C%JeSG%-0DG%;?6 z7;DGG2;{6{YHVb9qjPr2`&nxGNy~RD``*`9J(zK6-b&YKvyW3crPkL9s?4?BX`}h# zx^jc@vU#pdyH}l=r@=aP!DjKYgWpw66PX+*sq@6G^LY9>&*J^Wi|5V%&2pH2Lf3TO z+{wp&h_1K4RbsXM$mFd%cbDbJuc+H&waS^RG38J4hw8!^zYbVb3P>4)+^~!LdWr3G zlczqy%coA;{qaenImd6I*4cJj#4@7KPtNcK*-*=3%Q znI8K4Q#POb(P(aOJ{hU*>eB724zIfY+WMAOFH^g@d-HX}EvhTl>=x_@mJyt^E%UkF zgo9Oo+P{3eE@dFaEXuI+zszKpbn}aweuU35@;d4D-};Rl6QeA1V+#XQV?+LxZ)c~> z%3B{DEiSX^&VYak0uSF(aEVg@3OLZGyj;gDL9m|KvO zTCA6xp9@ZQvcimv|5=y}7{CcvmLJ4pVP<0HFpvjnR%Vef5Ni-AaItIB%WuEub-DDh zt->B>?a3eIA*S=Oh_Q&M{g?DO9BG^p)?0U?AtUCzP0?L7qS@+>y)HMK!24G?U literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/smime/BobRSASignByCarl.cer b/SecurityTests/clxutils/certcrl/testSubjects/smime/BobRSASignByCarl.cer new file mode 100644 index 0000000000000000000000000000000000000000..ab5d69255a883b852722785b20b41f0a27658124 GIT binary patch literal 516 zcmXqLVq!38V$5B@%*4pVB;aO}eY}AoY>(jOJiW8Ag%=Ds*;uvtn3-f*84QFB1q}Gu zm_u2Zh1s1Gi*ka39S!8fc`YpsEDbFU3=J#|jH1MOjV%q0jDg71($q4_K+urifES{N z%_%<#q@{5_P=r&f&7`Gb01z;sk>@10JBGWrZ0T|FbX|Fo3-+%MaqQFf*|#7|4TUm02VV z#2Q3iKA51srb3}=)@7ehPUe0}>*iVPHjo7=;A0VE5qa@tNBWJ;)0Sv`7F?xyd1_Rf z*cKI}P-O=Cno}{$Iw|0Ol4G2Z1EH9P7YgVf+*?sGgRO9xYqMLJWT@=1LpZ}_NRd2|Rs5|V87g-&7xf0zQK9=(TP?8Rq rWc-hVH6XW|nSuGEuJ=EMq~i+ZtWL_eR~%n^uTc7;*3715sjuq*LRzzE literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/smime/CarlDSSCRLEmpty.crl b/SecurityTests/clxutils/certcrl/testSubjects/smime/CarlDSSCRLEmpty.crl new file mode 100644 index 0000000000000000000000000000000000000000..42af3a09a7e82043f0f8525db2da2692e5827f3b GIT binary patch literal 111 zcmXrWHPAEQWMkKA^EhY0!fYU9C}6Xin2s1G;oPY`&!GuAAC$R}$#wK_Po8T3wpb5-Ogu|Hi84ProMCww5%8dV+6pLT{ mKJDj%D>rguYHgWBn5v?;UyYVHc)tC8-7S^RTFrAz7XkocSU6b# literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/smime/CarlDSSCRLForCarl.crl b/SecurityTests/clxutils/certcrl/testSubjects/smime/CarlDSSCRLForCarl.crl new file mode 100644 index 0000000000000000000000000000000000000000..2a4e7949952048bbf8217d7db21238d75d8bd11c GIT binary patch literal 134 zcmXqLY&LK);ACUhYV$Z}!NP1HWGG<3$HpAW!Ys`0oLH3O5*#efYiVg5cz}3IC=ui9~fDZrPL8 SF1^39DVi&m{oAgUteODqekH2_ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/smime/CarlDSSSelf.cer b/SecurityTests/clxutils/certcrl/testSubjects/smime/CarlDSSSelf.cer new file mode 100644 index 0000000000000000000000000000000000000000..b47c682fdb240bf6db799e9fdefaca87578ab952 GIT binary patch literal 671 zcmXqLVw!Ex#1yrFnTe5!iILHOlZ{=g&EuQ}3$uZcp@0D&8*?ZNvoO1JVo{DuaIk@# zIIpFpfrX)&k&&r^sX>%Dud$_}kueaNTAEr$Vb#;bxZR+MQ5$A3BakD<)Y!3eavSw-xN-^*Nj&-o+$J_?s_0VHFnOQTTgN?KWg)6 zX{y~NI@L?;o7>yF-)3CeUDw6cwM(peX8@zed+jBYD8t=@`uBs+ahoKR+c7QK-xWJ!r@&RF z#s;2u;j_K>-rB~VRbuWRT0i&gotnVxJxX)uxU_R0Kl?%E=2pMh;(P1)PRd3Fe)V^$G>s}=RqqxkztTx;j>qe+ z%ET>K^@EjMlI7cWERJAP{h@i_{jLY4ADoUPrv}aDVs30@0EN)Z_7ZjGv;`Xvti7XC zy8B^{%bZ(^xxVhX8qyfhVbeTl5SAOuTimH74bDypDNjCGB fg5nE>fpO7qlBw0b(T2Hlijl97{JGBGZkwzDPOS%( literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/smime/CarlRSACRLEmpty.crl b/SecurityTests/clxutils/certcrl/testSubjects/smime/CarlRSACRLEmpty.crl new file mode 100644 index 0000000000000000000000000000000000000000..c3eb30466a936293eb279bdd22a60e5d2f55f565 GIT binary patch literal 202 zcmXqLJZ@lQz{|#|)#lOmotKf3g_XfT$WXw5kBvE$g;|*0Ik6}wDA-Y)*V59!!pOkD z+yDro&~z|2HZrU{s<=bArsVTh!8a_Q6ul7EIgMXw{H=5&-)KN$3Co literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/smime/CarlRSACRLForAll.crl b/SecurityTests/clxutils/certcrl/testSubjects/smime/CarlRSACRLForAll.crl new file mode 100644 index 0000000000000000000000000000000000000000..3708ccbf5930b76cb2c7428698839ab416b63934 GIT binary patch literal 311 zcmXqLVl*~roNK_##;Mij(e|B}k&%U!!9d7Rz<`g9Ih2K2nB6(CC?_b`QJmM((!j#V z+`!xb2%-!!4HTIK+)T2MH!y_l5xktIcSK?Uuj|nd|T(md}zE9w>j@%M|RJZxTC(m z-Q&_e$F6?5MZzp$h3_1j&Nun$`%ME18xQStiB9U26f#^{J?rwBw9|q&xdq(I*ZM2n qd|GetDf-Wpz@-so*77UdmdSrxcrSF}Tf>gb>HHj*uka*9%K-p=O>W%) literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/smime/CarlRSACRLForCarl.crl b/SecurityTests/clxutils/certcrl/testSubjects/smime/CarlRSACRLForCarl.crl new file mode 100644 index 0000000000000000000000000000000000000000..2ce8e4db5a8fc8d8d5f3b50f92a1fb72cb5de0be GIT binary patch literal 239 zcmXqLd}9!9z{|#|)#lOmotKf3g_XfT$WXw5kBvE$g;|*0Ik6}wDA-Y)*V59!!pPLX z+yDro43rHNnFQQSvX3_~gzXW$oToScQ-A_gkr7N0sy{g9c>gqG)sV%*Ho%7z!=FvaL z{(bSq>{cKC|IhCJxpTHyN3QnHhQgyhe;D(E!ZYP8lkW>D85|c5ox+-@#jrB^h*sK^ Vq;qD*hqRO3Rp)-bSMZJ@3;-IpSj+$b literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/smime/CarlRSASelf.cer b/SecurityTests/clxutils/certcrl/testSubjects/smime/CarlRSASelf.cer new file mode 100644 index 0000000000000000000000000000000000000000..ce6737d90a804bead6c9319ce0430a4ace09d048 GIT binary patch literal 495 zcmXqLVtj4T#2B)GnTe5!Nx;n{`*;IG*dD>ld3y6d1t=KsvT^Cxo>^b z+`WNv;#Hr@bhO(nm+!saD;50a3B%PFZx)$teETTikr8K?{rs7#{X6_t@2tH#E%lbz zf}{KR*11H#kNdJ*^K{eQH7+k#O`f93_e0{^iSW2jWk)^-{ zr{T|^*+Rh!zKSHwu03Vhd{-wD2hx3YSJO(d8AiZi=- literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/smime/DianeDHEncryptByCarl.cer b/SecurityTests/clxutils/certcrl/testSubjects/smime/DianeDHEncryptByCarl.cer new file mode 100644 index 0000000000000000000000000000000000000000..1b5ad08b52f5127f82ea74685eaa5433589cc5ea GIT binary patch literal 873 zcmXqLVoo(^Vpd(i%*4pV#KdsffRl|~tIgw_1q-u*kfDG99~*Nh3$rl0b7E1BOK`A( zoH(zgrGbT^xq*?PnW=e{IIpp#p^-5VnOd4!Mxp3&$xO^kb@4E0VsbQSV%!EX*p7)2 z$XUtM*vN1yZ{nd1dsjq!GE^+tE&oJd?}f>W>JlH??owtEyO3tN*ZM4LiN{Cgf~j9v zlXLa<&)WWf`hUya$+vx%6yBIJYs;rD+xgpLdrv)Dzm@+yYid(Qp7W(IEb+|UKLfs= z$YE96v)_zA=5SzE`ioMdw2FzzFaDW4m)us6Q(^G2BcXG&x=ILq90*51e}UM%jDaD0&T{r{`1*=*_?)nvBwED+(8j#c|xXx#H@jbk0} z8q=v0>Xxou9U9Q^;nGemLEkdhGJ772bw!cK-t2w8qI-tC$;G7=Qtl5SRBpF|^!%ZkC|H zm&+%26fKbNy#Hj6;@>Cp1FrS={Y;-O^1wv0-!>vh?oKSLpZ~Fr)`~TZIi}~@awm94 zcvHL1TZKK&+LJ%Z z8_0sR^RbArh`4|DKU-S6B1myXqFMOXAG6-wHgH4A8_fC)20Bb4wJCD)-k;y(o9JwM ll2Xubmvx|M5tE4btAjir&wj6(TXsr4@4~)MH)dz$0sxK~WF7zj literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/smime/DianeDSSSignByCarlInherit.cer b/SecurityTests/clxutils/certcrl/testSubjects/smime/DianeDSSSignByCarlInherit.cer new file mode 100644 index 0000000000000000000000000000000000000000..f323fc707a1a1ece2efc65e0bce15eb45e08a827 GIT binary patch literal 446 zcmXqLV%%lW#8|n2nTe5!iHYHo0Vf-~R-4B;3l?SrAwvNJJ~rl17G_~~=ft8Mm*8Ln zIdNV~O9Kl-a|0tFX%HpOYiwy~WDG>6mZp|b2EvAd2K*2`94?uOd8r^xjgt|^GBP)| zGB7nZGAv*auh4l{*BGp)m&n1taCTsj)UC)B#ri_3+c-|2davbD))mD0YA>tORsL^( z-L9{nX~D@SeA-{m}#s8t{Nr2s1MNXJIm600)RHKZwV|%*1xUKprHk%pzeR z)*w>gV%MaX-+s^Qa_M7Rg+0#NlRwHE$buB`v52vVq!`Ssjk)8>J<}>kUu=Iwz}<7& z5{Q6dW(JzB%Oq0A!_z3fWmd?h!v?Rrj@TRuGMhJ*NtEH(eDOnt-fQ$Mdu;{eXKnV~ I_ET^%0HW8CasU7T literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/smime/DianeRSASignByCarl.cer b/SecurityTests/clxutils/certcrl/testSubjects/smime/DianeRSASignByCarl.cer new file mode 100644 index 0000000000000000000000000000000000000000..8eacf0a70cd605f418a4f1f184fd79c7de416904 GIT binary patch literal 526 zcmXqLV&XDrVk}<3%*4pVB;aO}eY}AoY>(jOJiV*43?>-xvTsO$IyL5%WpmHJS)fxe?NhVUw=3HN%Rwiaf2FAq+25|;FKxfMeGcx{XVKQI+@2$Tj z4{`ti!43Fl(w#dGyZ$Zzv-JA(+p0C64UQ%+xA0o6s;JU%{6hZFkyezPPU3V7zRe zE7R^(XXa_JPF=8ByzJn2RntT!$4TluaqB#ue$KOaKk?#u^MA7(rk~I?oi}&#u^*!A z?QfM>Z9g)3>(1R}Ir1y&_E@cQ=4wp&ll-B&aK^6#7L@{0#vnKB;=W#D``qNIkMQ!T z({_J+l4#EHTj==jITOp-W}1HRP?=^d#8}t+hWp#51If!pkH$@HTU311)6Kjx;cq!B zr^oDqUK`eL=UjB^Yo)bC?|x?0-`A?p-}`gR0@o7lFV=INl1$Xq8~gJ44c0BIzk(^hbm2Yy&yUqA=E^_C#b1$rpN&JW`m!7%d z)|~@$IiIZmnK)6${fv9ueQo2i&*^WRdJLD;7N}FnyJGZ(e|5_DjxNs#1)7kN>O5lzu&YF6!&N*2RsD2K5H=zyu*H z$Rc4N)+mw+j^GT3)QZI1f}GT1z2y8{10Ik9VMfOPEKCLr;PfNQ58|;fGcj{Ov@3(O zH;5Ft*fr_px8L)+T>98nVUM%+z-}= H_#y)UWZWwy literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/smime/certsParsed b/SecurityTests/clxutils/certcrl/testSubjects/smime/certsParsed new file mode 100644 index 00000000..cdb0e9f7 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/smime/certsParsed @@ -0,0 +1,320 @@ +AliceDSSSignByCarlNoInherit.cer +Serial Number : 00 C8 +Issuer Name : + Common Name : CarlDSS +Subject Name : + Common Name : AliceDSS +Cert Sig Algorithm : dsaWithSha1 (1 2 840 10040 4 3) +Not Before : 01:10:49 Aug 17, 1999 +Not After : 23:59:59 Dec 31, 2039 +Pub Key Algorithm : dsa (1 2 840 10040 4 1) + alg params : 30 82 01 1E 02 81 81 00 ... +Pub key Bytes : Length 131 bytes : 02 81 80 5C E3 B9 5A 75 ... +CSSM Key : + Algorithm : DSA + Key Size : 1024 bits + Key Use : CSSM_KEYUSE_VERIFY +Signature : 47 bytes : 30 2D 02 15 00 98 B0 C6 ... +Extension struct : keyUsage (2 5 29 15) + Critical : TRUE + usage : DigitalSignature NonRepudiation +Extension struct : basicConstraints (2 5 29 19) + Critical : TRUE + CA : FALSE +Extension struct : subjectKeyIdentifier (2 5 29 14) + Critical : FALSE + Subject KeyID : BE 6C A1 B3 E3 C1 F7 ED ... +Extension struct : authorityKeyIdentifier (2 5 29 35) + Critical : FALSE + Auth KeyID : 70 44 3E 82 2E 6F 87 DE ... +Extension struct : subjectAltName (2 5 29 17) + Critical : FALSE + RFC822Name : aliceDss@examples.com + + +AliceRSASignByCarl.cer +Serial Number : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E C4 10 B3 B0 +Issuer Name : + Common Name : CarlRSA +Subject Name : + Common Name : AliceRSA +Cert Sig Algorithm : sha-1WithRSAEncryption (1 3 14 3 2 29) + alg params : 05 00 +Not Before : 01:08:47 Sep 19, 1999 +Not After : 23:59:59 Dec 31, 2039 +Pub Key Algorithm : rsaEncryption (1 2 840 113549 1 1 1) + alg params : 05 00 +Pub key Bytes : Length 140 bytes : 30 81 89 02 81 81 00 E0 ... +CSSM Key : + Algorithm : RSA + Key Size : 1024 bits + Key Use : CSSM_KEYUSE_VERIFY +Signature : 128 bytes : BF 34 32 E6 FC 6A 88 41 ... +Extension struct : keyUsage (2 5 29 15) + Critical : TRUE + usage : DigitalSignature NonRepudiation +Extension struct : basicConstraints (2 5 29 19) + Critical : TRUE + CA : FALSE +Extension struct : subjectKeyIdentifier (2 5 29 14) + Critical : FALSE + Subject KeyID : 77 D2 B4 D1 B7 4C 8A 8A ... +Extension struct : authorityKeyIdentifier (2 5 29 35) + Critical : FALSE + Auth KeyID : E9 E0 90 27 AC 78 20 7A ... + + +BobDHEncryptByCarl.cer +Serial Number : 00 C9 +Issuer Name : + Common Name : CarlDSS +Subject Name : + Common Name : bobDH +Cert Sig Algorithm : dsaWithSha1 (1 2 840 10040 4 3) +Not Before : 01:18:28 Aug 17, 1999 +Not After : 23:59:59 Dec 31, 2039 +Pub Key Algorithm : dhPublicNumber (1 2 840 10046 2 1) + alg params : 30 82 01 AA 02 81 81 00 ... +Pub key Bytes : Length 131 bytes : 02 81 80 6F D4 F6 CD 94 ... +CSSM Key : + Algorithm : Diffie-Hellman + Key Size : 1024 bits + Key Use : CSSM_KEYUSE_DERIVE +Signature : 47 bytes : 30 2D 02 14 15 EA 15 43 ... +Extension struct : keyUsage (2 5 29 15) + Critical : TRUE + usage : KeyAgreement +Extension struct : basicConstraints (2 5 29 19) + Critical : TRUE + CA : FALSE +Extension struct : subjectKeyIdentifier (2 5 29 14) + Critical : FALSE + Subject KeyID : 26 FF 19 48 C3 59 33 68 ... +Extension struct : authorityKeyIdentifier (2 5 29 35) + Critical : FALSE + Auth KeyID : 70 44 3E 82 2E 6F 87 DE ... +Extension struct : subjectAltName (2 5 29 17) + Critical : FALSE + RFC822Name : bobDh@examples.com + + +BobRSASignByCarl.cer +Serial Number : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E CD 5D 71 D0 +Issuer Name : + Common Name : CarlRSA +Subject Name : + Common Name : BobRSA +Cert Sig Algorithm : sha-1WithRSAEncryption (1 3 14 3 2 29) + alg params : 05 00 +Not Before : 01:09:02 Sep 19, 1999 +Not After : 23:59:59 Dec 31, 2039 +Pub Key Algorithm : rsaEncryption (1 2 840 113549 1 1 1) + alg params : 05 00 +Pub key Bytes : Length 140 bytes : 30 81 89 02 81 81 00 A9 ... +CSSM Key : + Algorithm : RSA + Key Size : 1024 bits + Key Use : CSSM_KEYUSE_WRAP +Signature : 128 bytes : 09 21 6A 3B 62 50 DF 62 ... +Extension struct : keyUsage (2 5 29 15) + Critical : TRUE + usage : KeyEncipherment +Extension struct : basicConstraints (2 5 29 19) + Critical : TRUE + CA : FALSE +Extension struct : subjectKeyIdentifier (2 5 29 14) + Critical : FALSE + Subject KeyID : E8 F4 B8 67 D8 B3 96 A4 ... +Extension struct : authorityKeyIdentifier (2 5 29 35) + Critical : FALSE + Auth KeyID : E9 E0 90 27 AC 78 20 7A ... + + +CarlDSSSelf.cer +Serial Number : 01 +Issuer Name : + Common Name : CarlDSS +Subject Name : + Common Name : CarlDSS +Cert Sig Algorithm : dsaWithSha1 (1 2 840 10040 4 3) +Not Before : 22:50:50 Aug 16, 1999 +Not After : 23:59:59 Dec 31, 2039 +Pub Key Algorithm : dsa (1 2 840 10040 4 1) + alg params : 30 82 01 1E 02 81 81 00 ... +Pub key Bytes : Length 132 bytes : 02 81 81 00 99 87 74 27 ... +CSSM Key : + Algorithm : DSA + Key Size : 1024 bits + Key Use : CSSM_KEYUSE_VERIFY +Signature : 47 bytes : 30 2D 02 14 6B A9 F0 4E ... +Extension struct : keyUsage (2 5 29 15) + Critical : TRUE + usage : DigitalSignature KeyCertSign CRLSign +Extension struct : basicConstraints (2 5 29 19) + Critical : TRUE + CA : TRUE +Extension struct : subjectKeyIdentifier (2 5 29 14) + Critical : FALSE + Subject KeyID : 70 44 3E 82 2E 6F 87 DE ... + + +CarlRSASelf.cer +Serial Number : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E 9F F2 50 20 +Issuer Name : + Common Name : CarlRSA +Subject Name : + Common Name : CarlRSA +Cert Sig Algorithm : sha1withRSAEncryption (1 2 840 113549 1 1 5) + alg params : 05 00 +Not Before : 07:00:00 Aug 18, 1999 +Not After : 23:59:59 Dec 31, 2039 +Pub Key Algorithm : rsaEncryption (1 2 840 113549 1 1 1) + alg params : 05 00 +Pub key Bytes : Length 140 bytes : 30 81 89 02 81 81 00 E4 ... +CSSM Key : + Algorithm : RSA + Key Size : 1024 bits + Key Use : CSSM_KEYUSE_VERIFY +Signature : 128 bytes : B7 9E D4 04 D3 ED 29 E4 ... +Extension struct : keyUsage (2 5 29 15) + Critical : TRUE + usage : DigitalSignature KeyCertSign CRLSign +Extension struct : basicConstraints (2 5 29 19) + Critical : TRUE + CA : TRUE +Extension struct : subjectKeyIdentifier (2 5 29 14) + Critical : FALSE + Subject KeyID : E9 E0 90 27 AC 78 20 7A ... + + +DianeDHEncryptByCarl.cer +Serial Number : 00 D3 +Issuer Name : + Common Name : CarlDSS +Subject Name : + Common Name : DianeDH +Cert Sig Algorithm : dsaWithSha1 (1 2 840 10040 4 3) +Not Before : 02:16:57 Aug 17, 1999 +Not After : 23:59:59 Dec 31, 2039 +Pub Key Algorithm : dhPublicNumber (1 2 840 10046 2 1) + alg params : 30 82 01 A9 02 81 81 00 ... +Pub key Bytes : Length 131 bytes : 02 81 80 60 5E 6E EF 61 ... +CSSM Key : + Algorithm : Diffie-Hellman + Key Size : 1024 bits + Key Use : CSSM_KEYUSE_DERIVE +Signature : 46 bytes : 30 2C 02 14 7D 64 1E 1F ... +Extension struct : keyUsage (2 5 29 15) + Critical : TRUE + usage : KeyAgreement +Extension struct : basicConstraints (2 5 29 19) + Critical : TRUE + CA : FALSE +Extension struct : subjectKeyIdentifier (2 5 29 14) + Critical : FALSE + Subject KeyID : 47 F3 4F CD 75 7D A8 52 ... +Extension struct : authorityKeyIdentifier (2 5 29 35) + Critical : FALSE + Auth KeyID : 70 44 3E 82 2E 6F 87 DE ... +Extension struct : subjectAltName (2 5 29 17) + Critical : FALSE + RFC822Name : dianeDh@examples.com + + +DianeDSSSignByCarlInherit.cer +Serial Number : 00 D2 +Issuer Name : + Common Name : CarlDSS +Subject Name : + Common Name : DianeDSS +Cert Sig Algorithm : dsaWithSha1 (1 2 840 10040 4 3) +Not Before : 02:08:10 Aug 17, 1999 +Not After : 23:59:59 Dec 31, 2039 +Pub Key Algorithm : dsa (1 2 840 10040 4 1) +Pub key Bytes : Length 132 bytes : 02 81 81 00 A0 00 17 78 ... +CSSM Key : + Algorithm : DSA + Key Size : 1024 bits + Key Use : CSSM_KEYUSE_VERIFY +Signature : 47 bytes : 30 2D 02 14 7E 0C 0C 81 ... +Extension struct : keyUsage (2 5 29 15) + Critical : TRUE + usage : DigitalSignature NonRepudiation +Extension struct : basicConstraints (2 5 29 19) + Critical : TRUE + CA : FALSE +Extension struct : subjectKeyIdentifier (2 5 29 14) + Critical : FALSE + Subject KeyID : 64 30 99 7D 5C DC 45 0B ... +Extension struct : authorityKeyIdentifier (2 5 29 35) + Critical : FALSE + Auth KeyID : 70 44 3E 82 2E 6F 87 DE ... +Extension struct : subjectAltName (2 5 29 17) + Critical : FALSE + RFC822Name : dianeDss@examples.com + + +DianeRSASignByCarl.cer +Serial Number : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E D5 9A 30 90 +Issuer Name : + Common Name : CarlRSA +Subject Name : + Common Name : DianeRSA +Cert Sig Algorithm : sha1withRSAEncryption (1 2 840 113549 1 1 5) + alg params : 05 00 +Not Before : 07:00:00 Aug 19, 1999 +Not After : 23:59:59 Dec 31, 2039 +Pub Key Algorithm : rsaEncryption (1 2 840 113549 1 1 1) + alg params : 05 00 +Pub key Bytes : Length 140 bytes : 30 81 89 02 81 81 00 D6 ... +CSSM Key : + Algorithm : RSA + Key Size : 1024 bits + Key Use : CSSM_KEYUSE_VERIFY CSSM_KEYUSE_WRAP +Signature : 128 bytes : 1D B3 51 B1 99 96 F0 44 ... +Extension struct : keyUsage (2 5 29 15) + Critical : TRUE + usage : DigitalSignature NonRepudiation KeyEncipherment +Extension struct : basicConstraints (2 5 29 19) + Critical : TRUE + CA : FALSE +Extension struct : subjectKeyIdentifier (2 5 29 14) + Critical : FALSE + Subject KeyID : 8C F3 CB 75 0E 8D 31 F6 ... +Extension struct : authorityKeyIdentifier (2 5 29 35) + Critical : FALSE + Auth KeyID : E9 E0 90 27 AC 78 20 7A ... + + +EricaDHEncryptByCarl.cer +Serial Number : 00 D4 +Issuer Name : + Common Name : CarlDSS +Subject Name : + Common Name : EricaDH +Cert Sig Algorithm : dsaWithSha1 (1 2 840 10040 4 3) +Not Before : 02:17:16 Aug 17, 1999 +Not After : 23:59:59 Dec 31, 2039 +Pub Key Algorithm : dhPublicNumber (1 2 840 10046 2 1) + alg params : 30 82 01 2B 02 81 81 00 ... +Pub key Bytes : Length 132 bytes : 02 81 81 00 D1 2B E4 1D ... +CSSM Key : + Algorithm : Diffie-Hellman + Key Size : 1024 bits + Key Use : CSSM_KEYUSE_DERIVE +Signature : 47 bytes : 30 2D 02 14 3E 51 42 08 ... +Extension struct : keyUsage (2 5 29 15) + Critical : TRUE + usage : KeyAgreement +Extension struct : basicConstraints (2 5 29 19) + Critical : TRUE + CA : FALSE +Extension struct : subjectKeyIdentifier (2 5 29 14) + Critical : FALSE + Subject KeyID : 8D 53 1D 61 55 7F 60 35 ... +Extension struct : authorityKeyIdentifier (2 5 29 35) + Critical : FALSE + Auth KeyID : 70 44 3E 82 2E 6F 87 DE ... +Extension struct : subjectAltName (2 5 29 17) + Critical : FALSE + RFC822Name : ericaDh@examples.com diff --git a/SecurityTests/clxutils/certcrl/testSubjects/smime/crlsParsed b/SecurityTests/clxutils/certcrl/testSubjects/smime/crlsParsed new file mode 100644 index 00000000..1b5b6b90 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/smime/crlsParsed @@ -0,0 +1,89 @@ +CarlDSSCRLEmpty.crl +TBS Sig Algorithm : dsaWithSha1 (1 2 840 10040 4 3) +Issuer Name : + Common Name : CarlDSS +This Update : 07:00:00 Aug 20, 1999 +Next Update : +Signature : 47 bytes : 30 2D 02 14 62 3F 36 17 ... + + +CarlDSSCRLForAll.crl +TBS Sig Algorithm : dsaWithSha1 (1 2 840 10040 4 3) +Issuer Name : + Common Name : CarlDSS +This Update : 07:00:00 Aug 27, 1999 +Next Update : +Num Revoked Certs : 5 +Revoked Cert 0 : + Serial number : 00 C8 + Revocation time : 07:00:00 Aug 22, 1999 +Revoked Cert 1 : + Serial number : 00 C9 + Revocation time : 07:00:00 Aug 22, 1999 +Revoked Cert 2 : + Serial number : 00 D3 + Revocation time : 07:00:00 Aug 22, 1999 +Revoked Cert 3 : + Serial number : 00 D2 + Revocation time : 07:00:00 Aug 22, 1999 +Revoked Cert 4 : + Serial number : 00 D4 + Revocation time : 07:00:00 Aug 24, 1999 +Signature : 46 bytes : 30 2C 02 14 7E 65 52 76 ... + + +CarlDSSCRLForCarl.crl +TBS Sig Algorithm : dsaWithSha1 (1 2 840 10040 4 3) +Issuer Name : + Common Name : CarlDSS +This Update : 07:00:00 Aug 25, 1999 +Next Update : +Num Revoked Certs : 1 +Revoked Cert 0 : + Serial number : 01 + Revocation time : 07:00:00 Aug 22, 1999 +Signature : 47 bytes : 30 2D 02 15 00 B3 1F C5 ... + + +CarlRSACRLEmpty.crl +TBS Sig Algorithm : md5withRSAEncryption (1 2 840 113549 1 1 4) + alg params : 05 00 +Issuer Name : + Common Name : CarlRSA +This Update : 07:00:00 Aug 20, 1999 +Next Update : +Signature : 128 bytes : A9 C5 21 B8 13 7C 74 F3 ... + + +CarlRSACRLForAll.crl +TBS Sig Algorithm : md5withRSAEncryption (1 2 840 113549 1 1 4) + alg params : 05 00 +Issuer Name : + Common Name : CarlRSA +This Update : 07:00:00 Aug 27, 1999 +Next Update : +Num Revoked Certs : 3 +Revoked Cert 0 : + Serial number : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E C4 10 B3 B0 + Revocation time : 07:00:00 Aug 22, 1999 +Revoked Cert 1 : + Serial number : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E D5 9A 30 90 + Revocation time : 07:00:00 Aug 22, 1999 +Revoked Cert 2 : + Serial number : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E CD 5D 71 D0 + Revocation time : 07:00:00 Aug 24, 1999 +Signature : 128 bytes : BF B3 97 AA 53 F0 32 21 ... + + +CarlRSACRLForCarl.crl +TBS Sig Algorithm : md5withRSAEncryption (1 2 840 113549 1 1 4) + alg params : 05 00 +Issuer Name : + Common Name : CarlRSA +This Update : 07:00:00 Aug 25, 1999 +Next Update : +Num Revoked Certs : 1 +Revoked Cert 0 : + Serial number : 46 34 6B C7 80 00 56 BC 11 D3 6E 2E 9F F2 50 20 + Revocation time : 07:00:00 Aug 22, 1999 +Signature : 128 bytes : 21 EF 21 D4 C1 1A 85 95 ... diff --git a/SecurityTests/clxutils/certcrl/testSubjects/smime/smime.scr b/SecurityTests/clxutils/certcrl/testSubjects/smime/smime.scr new file mode 100644 index 00000000..800f35d4 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/smime/smime.scr @@ -0,0 +1,436 @@ +# +# certcrl script to test certs and CRLs from S/MIME examples +# +# Examples obtained from +# http://www.ietf.org/internet-drafts/draft-ietf-smime-examples-09.txt +# +# This script tests every cert and CRL from the examples package, ensuring +# both successful (normal) operation and a variety of error cases for +# every cert. +# + +globals +allowUnverified = true +requireCrlForAll = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +end + +################################################### + +test = "Carl RSA root, Alice leaf" +revokePolicy = crl +cert = AliceRSASignByCarl.cer +root = CarlRSASelf.cer +crl = CarlRSACRLEmpty.crl +# note none of the RSA certs have email addresses in them +senderEmail = "alice@somewhere.net" +# Cert has DigitalSignature, NonRepudiation +keyUsage = 0x8000 +end + +################################################### + +test = "Carl RSA root, Alice Leaf, bad key use" +revokePolicy = crl +cert = AliceRSASignByCarl.cer +root = CarlRSASelf.cer +crl = CarlRSACRLEmpty.crl +# this CRL revokes the root, which TP does not check +crl = CarlRSACRLForCarl.crl +senderEmail = "alice@somewhere.net" +keyUsage = 0x01 +error = CSSMERR_TP_VERIFY_ACTION_FAILED +certerror = 0:CSSMERR_APPLETP_SMIME_BAD_KEY_USE +end + +################################################### + +test = "Carl RSA root, Alice Leaf, revoked" +revokePolicy = crl +cert = AliceRSASignByCarl.cer +root = CarlRSASelf.cer +crl = CarlRSACRLForAll.crl +senderEmail = "alice@somewhere.net" +error = CSSMERR_TP_CERT_REVOKED +certerror = 0:CSSMERR_TP_CERT_REVOKED +end + +################################################### + +test = "Carl RSA root, Alice Leaf, no CRL" +revokePolicy = crl +cert = AliceRSASignByCarl.cer +root = CarlRSASelf.cer +crl = CarlDSSCRLEmpty.crl +senderEmail = "alice@somewhere.net" +error = CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_CRL_NOT_FOUND +end + +################################################### + +test = "Carl RSA root, Diane leaf" +revokePolicy = crl +cert = DianeRSASignByCarl.cer +root = CarlRSASelf.cer +crl = CarlRSACRLEmpty.crl +# note none of the RSA certs have email addresses in them +senderEmail = "diane@somewhere.net" +# DigitalSignature NonRepudiation KeyEncipherment +keyUsage = 0xe000 +end + +################################################### + +test = "Carl RSA root, Diane leaf, bad key use" +revokePolicy = crl +cert = DianeRSASignByCarl.cer +root = CarlRSASelf.cer +crl = CarlRSACRLEmpty.crl +senderEmail = "diane@somewhere.net" +keyUsage = 0xf000 +error = CSSMERR_TP_VERIFY_ACTION_FAILED +certerror = 0:CSSMERR_APPLETP_SMIME_BAD_KEY_USE +end + +################################################### + +test = "Carl RSA root, Diane leaf, revoked" +revokePolicy = crl +cert = DianeRSASignByCarl.cer +root = CarlRSASelf.cer +crl = CarlRSACRLForAll.crl +senderEmail = "diane@somewhere.net" +error = CSSMERR_TP_CERT_REVOKED +certerror = 0:CSSMERR_TP_CERT_REVOKED +end + +################################################### + +test = "Carl RSA root, Diane leaf, no CRL" +revokePolicy = crl +cert = DianeRSASignByCarl.cer +root = CarlRSASelf.cer +crl = CarlDSSCRLEmpty.crl +senderEmail = "diane@somewhere.net" +error = CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_CRL_NOT_FOUND +end + +################################################### + +test = "Carl DSA root, Alice Leaf, full DSA params" +revokePolicy = crl +cert = AliceDSSSignByCarlNoInherit.cer +root = CarlDSSSelf.cer +crl = CarlDSSCRLEmpty.crl +senderEmail = aliceDss@examples.com +# Cert has DigitalSignature, NonRepudiation +keyUsage = 0x8000 +end + +################################################### + +test = "Carl DSA root, Alice Leaf, full DSA params, revoked" +revokePolicy = crl +cert = AliceDSSSignByCarlNoInherit.cer +root = CarlDSSSelf.cer +crl = CarlDSSCRLForAll.crl +senderEmail = aliceDss@examples.com +keyUsage = 0x8000 +error = CSSMERR_TP_CERT_REVOKED +certerror = 0:CSSMERR_TP_CERT_REVOKED +end + +################################################### + +test = "Carl DSA root, Alice Leaf, bad email address" +revokePolicy = crl +cert = AliceDSSSignByCarlNoInherit.cer +root = CarlDSSSelf.cer +crl = CarlDSSCRLEmpty.crl +senderEmail = bob@examples.com +keyUsage = 0x8000 +error = CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND +end + +################################################### + +test = "Carl DSA root, Bob DH Leaf" +revokePolicy = crl +cert = BobDHEncryptByCarl.cer +root = CarlDSSSelf.cer +crl = CarlDSSCRLEmpty.crl +senderEmail = bobDh@examples.com +# cert has KeyAgreement (only) +keyUsage = 0x900 +end + +################################################### + +test = "Carl DSA root, Bob DH Leaf, bad KeyUsage" +revokePolicy = crl +cert = BobDHEncryptByCarl.cer +root = CarlDSSSelf.cer +crl = CarlDSSCRLEmpty.crl +senderEmail = bobDh@examples.com +# cert has KeyAgreement (only) +keyUsage = 0x4000 +error = CSSMERR_TP_VERIFY_ACTION_FAILED +certerror = 0:CSSMERR_APPLETP_SMIME_BAD_KEY_USE +end + +################################################### + +test = "Carl DSA root, Bob DH Leaf, no CRL" +revokePolicy = crl +cert = BobDHEncryptByCarl.cer +root = CarlDSSSelf.cer +crl = CarlRSACRLForAll.crl +senderEmail = bobDh@examples.com +keyUsage = 0x900 +error = CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_CRL_NOT_FOUND +end + +################################################### + +test = "Carl DSA root, Bob DH Leaf, Revoked" +revokePolicy = crl +cert = BobDHEncryptByCarl.cer +root = CarlDSSSelf.cer +crl = CarlDSSCRLForAll.crl +senderEmail = bobDh@examples.com +keyUsage = 0x900 +error = CSSMERR_TP_CERT_REVOKED +certerror = 0:CSSMERR_TP_CERT_REVOKED +end + +################################################### + +test = "Carl DSA root, Erica DH Leaf" +revokePolicy = crl +cert = EricaDHEncryptByCarl.cer +root = CarlDSSSelf.cer +crl = CarlDSSCRLEmpty.crl +senderEmail = ericaDh@examples.com +# cert has KeyAgreement (only) +keyUsage = 0x900 +end + +################################################### + +test = "Carl DSA root, Erica DH Leaf, bad KeyUsage" +revokePolicy = crl +cert = EricaDHEncryptByCarl.cer +root = CarlDSSSelf.cer +crl = CarlDSSCRLEmpty.crl +senderEmail = ericaDh@examples.com +# cert has KeyAgreement (only) +keyUsage = 0x4000 +error = CSSMERR_TP_VERIFY_ACTION_FAILED +certerror = 0:CSSMERR_APPLETP_SMIME_BAD_KEY_USE +end + +################################################### + +test = "Carl DSA root, Erica DH Leaf, no CRL" +revokePolicy = crl +cert = EricaDHEncryptByCarl.cer +root = CarlDSSSelf.cer +crl = CarlRSACRLForAll.crl +senderEmail = ericaDh@examples.com +keyUsage = 0x900 +error = CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_CRL_NOT_FOUND +end + +################################################### + +test = "Carl DSA root, Erica DH Leaf, Revoked" +revokePolicy = crl +cert = EricaDHEncryptByCarl.cer +root = CarlDSSSelf.cer +crl = CarlDSSCRLForAll.crl +senderEmail = ericaDh@examples.com +keyUsage = 0x900 +error = CSSMERR_TP_CERT_REVOKED +certerror = 0:CSSMERR_TP_CERT_REVOKED +end + +################################################### + +test = "Carl RSA root, Bob leaf" +revokePolicy = crl +cert = BobRSASignByCarl.cer +root = CarlRSASelf.cer +crl = CarlRSACRLEmpty.crl +# note none of the RSA certs have email addresses in them +senderEmail = "bob@somewhere.net" +# Cert has KeyEncipherment +keyUsage = 0x2000 +end + +################################################### + +test = "Carl RSA root, Bob Leaf, bad key use" +revokePolicy = crl +cert = BobRSASignByCarl.cer +root = CarlRSASelf.cer +crl = CarlRSACRLEmpty.crl +senderEmail = "bob@somewhere.net" +keyUsage = 0x01 +error = CSSMERR_TP_VERIFY_ACTION_FAILED +certerror = 0:CSSMERR_APPLETP_SMIME_BAD_KEY_USE +end + +################################################### + +test = "Carl RSA root, Bob Leaf, revoked" +revokePolicy = crl +cert = BobRSASignByCarl.cer +root = CarlRSASelf.cer +crl = CarlRSACRLForAll.crl +senderEmail = "bob@somewhere.net" +error = CSSMERR_TP_CERT_REVOKED +certerror = 0:CSSMERR_TP_CERT_REVOKED +end + +################################################### + +test = "Carl RSA root, Bob Leaf, no CRL" +revokePolicy = crl +cert = BobRSASignByCarl.cer +root = CarlRSASelf.cer +crl = CarlDSSCRLEmpty.crl +senderEmail = "bob@somewhere.net" +error = CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_CRL_NOT_FOUND +end + +################################################### + +test = "Carl DSA root, Diane DH Leaf" +revokePolicy = crl +cert = DianeDHEncryptByCarl.cer +root = CarlDSSSelf.cer +crl = CarlDSSCRLEmpty.crl +senderEmail = dianeDh@examples.com +# cert has KeyAgreement (only) +keyUsage = 0x900 +end + +################################################### + +test = "Carl DSA root, Diane DH Leaf, bad KeyUsage" +revokePolicy = crl +cert = DianeDHEncryptByCarl.cer +root = CarlDSSSelf.cer +crl = CarlDSSCRLEmpty.crl +senderEmail = dianeDh@examples.com +# cert has KeyAgreement (only) +keyUsage = 0x4000 +error = CSSMERR_TP_VERIFY_ACTION_FAILED +certerror = 0:CSSMERR_APPLETP_SMIME_BAD_KEY_USE +end + +################################################### + +test = "Carl DSA root, Diane DH Leaf, no CRL" +revokePolicy = crl +cert = DianeDHEncryptByCarl.cer +root = CarlDSSSelf.cer +crl = CarlRSACRLForAll.crl +senderEmail = dianeDh@examples.com +keyUsage = 0x900 +error = CSSMERR_APPLETP_CRL_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_CRL_NOT_FOUND +end + +################################################### + +test = "Carl DSA root, Diane DH Leaf, Revoked" +revokePolicy = crl +cert = DianeDHEncryptByCarl.cer +root = CarlDSSSelf.cer +crl = CarlDSSCRLForAll.crl +senderEmail = dianeDh@examples.com +keyUsage = 0x900 +error = CSSMERR_TP_CERT_REVOKED +certerror = 0:CSSMERR_TP_CERT_REVOKED +end + +################################################### + +test = "Carl RSA root, Diane DH Leaf, no root" +revokePolicy = crl +cert = DianeDHEncryptByCarl.cer +root = CarlRSASelf.cer +crl = CarlDSSCRLEmpty.crl +senderEmail = dianeDh@examples.com +keyUsage = 0x900 +error = CSSMERR_TP_NOT_TRUSTED +certerror = 0:CSSMERR_APPLETP_CRL_NOT_TRUSTED +end + +################################################### + +test = "Carl DSA root, Diane Leaf, partial DSA params" +revokePolicy = crl +cert = DianeDSSSignByCarlInherit.cer +root = CarlDSSSelf.cer +crl = CarlDSSCRLEmpty.crl +# this CRL revokes the root, which TP does not check +crl = CarlDSSCRLForCarl.crl +senderEmail = dianeDss@examples.com +# Cert has DigitalSignature, NonRepudiation +keyUsage = 0x8000 +end + +################################################### + +test = "Carl DSA root, Diane Leaf, partial DSA params, revoked" +revokePolicy = crl +cert = DianeDSSSignByCarlInherit.cer +root = CarlDSSSelf.cer +crl = CarlDSSCRLForAll.crl +senderEmail = dianeDss@examples.com +# cert has DigitalSignature NonRepudiation +keyUsage = 0x8000 +error = CSSMERR_TP_CERT_REVOKED +certerror = 0:CSSMERR_TP_CERT_REVOKED +end + +################################################### + +test = "Carl DSA root, Diane Leaf, partial DSA params, bad key use" +revokePolicy = crl +cert = DianeDSSSignByCarlInherit.cer +root = CarlDSSSelf.cer +crl = CarlDSSCRLForAll.crl +senderEmail = dianeDss@examples.com +# cert has DigitalSignature NonRepudiation +keyUsage = 0x01 +error = CSSMERR_TP_VERIFY_ACTION_FAILED +certerror = 0:CSSMERR_APPLETP_SMIME_BAD_KEY_USE +end + +################################################### + +test = "Carl DSA root, Diane Leaf, partial DSA params, bad email address" +revokePolicy = crl +cert = DianeDSSSignByCarlInherit.cer +root = CarlDSSSelf.cer +crl = CarlDSSCRLForAll.crl +senderEmail = bobDss@examples.com +# cert has DigitalSignature NonRepudiation +keyUsage = 0x8000 +error = CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND +certerror = 0:CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND +end + + + diff --git a/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/buildAndTest b/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/buildAndTest new file mode 100755 index 00000000..f324cad4 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/buildAndTest @@ -0,0 +1,39 @@ +#! /bin/csh -f +# +# Build trust settings needed for test script trustSettings.scr; +# import those trust settings into current user domain; +# run trustSettings.scr; +# import empty trust settings back into user domain; + +# This requires user interaction to authenticate the trust settings import. +# +if ( $#argv != 0 ) then + echo "Usage: buildAndTest" + exit(1) +endif + +set RESTORE_SETTINGS=YES +set SAVED_SETTINGS=/tmp/savedSettings.plist + +echo "Saving existing Trust Settings, if any." +security trust-settings-export $SAVED_SETTINGS +if($status != 0) then + set RESTORE_SETTINGS=NO +endif + +./makeTrustSettings || exit(1) +echo Importing Trust Settings. This requires user authentication. +security trust-settings-import $LOCAL_BUILD_DIR/userTrustSettings.plist || exit(1) + +certcrl -S trustSettings.scr || exit(1) + +if($RESTORE_SETTINGS == YES) then + echo Restoring original Trust Settings. This requires user authentication. + security trust-settings-import $SAVED_SETTINGS || exit(1) + rm $SAVED_SETTINGS +else + echo Importing Empty Trust Settings. This requires user authentication. + security trust-settings-import emptyTrustSettings.plist || exit(1) +endif +echo == Fine == + diff --git a/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/crl.crl b/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/crl.crl new file mode 100644 index 0000000000000000000000000000000000000000..5e9e307494cb14fa19098a4232d2c8bbffca1a54 GIT binary patch literal 282 zcmXqLViYrIY%t(u$paKSB z1|m$1jBte(29{ujX!bKVHZnBsdw*J~_Gt4aiGMox+D|T-XdJ;|u2xX?<$dfygCvIZ zl}Ua6D!q3r(;SZmKaFVG=%W4i{>DO$OO`u@e0lzEX)GY9gdepi62}X}W@Q zkdH!1YH^8zv!kK7fhb6hi-*s#pdcqz!8t#-ptK~l$Ush<*TBrc#L(Q(($K)fAWEFq z5X3csat+K4WelVs#tNeuo0FQDhTGuA`3AfQ_c5|EFgNxx7&LY=H8wJwFzYIw)#Ish z#g8%XOxX>I|MR9_5B(@8%e1NJ(0o4UKRHRRHE-l@6*wPad%sL?(cdCP!+?ewRY9YXnjTTvSnXcvs2^Gir$Q#b!_(8lbx?k z0&Lc9Q{msUre;;}y@yWK+WV@C1e7FszO?X9x%KwyFEjNosmztncX+?O{Z*S?DyRIL oyT$6oAy0R^=!opD^;Xo7`eCWGz1e5g8|H=O?{|kE>-e_|0H8s-!~g&Q literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/crlTestRoot.cer b/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/crlTestRoot.cer new file mode 100644 index 0000000000000000000000000000000000000000..712983e69ec16a4f255730d868a098290b4824ad GIT binary patch literal 517 zcmXqLVq!FCV$52=%*4pV#K>U4&Bm$K=F#?@mywaxz|>I6K!S}ql!ci`&?PmgG+n_t z$VZ_hwYWsV+0jtkKolg$#lz=VP>_?V;GCaZP+F2&WFRNbYhY$zVrXt?X<%t;5+%-S z2;!PRx#Sw#INyL5;W|cE2Ij_I27|^(7a;Kcm~dj%LTX z{r}IWkYF*1dF}~&rl}1#wydhW$KdI_DMjOl#h=~J?z%J2K4NZEmiR>e?AE59JH=<; zyJhRo@p|-O%Co>kC+*KnJ8xaJn)UlB&%@>FLQ9+8%f1o$Bz{`>uFv-w-0911`9*k# z#cf=vCx1_xiJ6gsaj~+2q5(fJOk{-_8UM4e8ZZMX13r)dKS+QD7|3nNeqaUpp^+ic za*6-j4ToO6+Wt_r_u+4w>oca=e)(wPCAcg+;f+;WiEQtFrU%#g*9TwL*E^o!#k5*X z{Jh${+g@{Ie%qEXG~7s&;!F^h*s$%XOzw&*y@#u2B-@q0+9~8wrm(4|*oF6VX`*3k ix!zH&HCv~5FTM3w;I&Bm$K=F#?@mywaxz`{`0K$?v?l!ci`#5q4DRUtSt zJx{^K)hX0nAt*n;#8BKo6eP{X!{=B~kdvz5oS$1zT9R61AScdiU}|7wXl7^vf>GkU zh9EAO1LPW*8A=;SLQEDyH`&<{x4Dh;4R{eQWMpMvZtP_+XzXNaY-E^Kd1bNJyoaaG zo~aDqXm3)xsb2Ni@6u(P_Z-WZ)Nb|o{ML`WMW+sC9GUrBs*Mlw5nX@-$j3K&gcu(&ppC-vh{SE7(6~SJ-n$j)+#DU;^7SsxxlWR z1!bvc^P+6Z@*-u+!w<*nUaaTZ$;8aaz_{4Pz{)@f=rdViM#ldv90qJaiiwfIfDa_b z4-#VmhIN~P2#BxB!V3@a#vG72fxLB|1$Z&{(kdQ2G<2wzA)RH zldXOr^q+>E%Fir2y+Ss>*)CBWRTB1Q=G})XPHNQrJATt9^kl#K`?@|3ug|VYXUfy; KZyle!?*#znX1sC$ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/csLeaf.cer b/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/csLeaf.cer new file mode 100644 index 0000000000000000000000000000000000000000..23bf9adae0ffa0b8c944af01c0efe4f55ca22dd3 GIT binary patch literal 543 zcmXqLVv;s!Vr*H!%*4pV#K>X5&Bm$K=F#?@mywaxz|2tEK$49)l!ci`$T>eHRUtSt zJx{^K)hX0n!P(JJ+&~m0$;HFxSWu9Ys^FZTTToh(T4W$6&TC+5U}R`!Xkut$ViqON zYY5^3Ibg1Vg`up0G{jsHbaQ=D6Vq^;+&JHW7vVxiRtDzAUIv54PNv32hC>-=mbsV~{_eS-D)Hj1 z^`z4o-Tn%v)!t5EJN|Eh8HbhnR1f>FOw5c7jEgM|%nkT~ev=huWc<&RHyDV3_^K?t@Ze5PVPQn}87s(VjSRM1{7UTKA1_%P9i!dj^d?Sd^6hSY z(ZUHVTR$A@5)oik|GanA#*CJz%d7U@bh*mOW_I(0^}eYpzCjz=r(HZNrXbSzaN`WW zCL5#08IfYl?ZLO!U4&Bm$K=F#?@mywaxz`{`0K$?v?l!ci`#5q4DRUtSt zJx{^K)hX0nAt*n;#8BKo6eP{X!{=B~kdvz5oS$1zT9R61AScdiU}j)yXliI~Y+z&> zCC+OI;u=A@2F`{W25JzK<&jJd1(}?anwX|goRMEtqEL`nl7ZWj#`y-k2R*+8`8G>uRf2q^!4yoqb{C?fyoVEF( z?w_7nU)ZZZFAuRL_{ME%EyiCLhqd|sZ7MBWrmDg9&A9GC PNXdT{miU{N7q~+Jlp4KT literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/csRoot.cer b/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/csRoot.cer new file mode 100644 index 0000000000000000000000000000000000000000..34503798030d443b034ed2588eaaf5b1fc5d6812 GIT binary patch literal 523 zcmXqLVq!OFVk}s|%*4pV#K>mA&Bm$K=F#?@mywaxz`{`0K$?v?l!ci`#5q4DRUtSt zJx{^K)hX0nAt*n;#8BKo6eP{X!{=B~kdvz5oS$1zT9R61AScdiU}|7wXl7_)Xl!T^ zCC+OI;+jCY6qwvN-+&k4Mn+Z!=EhzIgT_v##zuz6KJ%kmy7hkTv%TcRs4}N4I;NB5 z{F&MH*+2cH_h+p6TAc7dM?xo{t!S10uCLoo%G9S!^@%<%9@SPAQhHZ>X>z5iw@=p0 ztGP?-yf+s`l<*3$`1oHJwa_+i4tgiBTIXEYlQnxPl+~{k9@I$Zo$)9x-TaFA{}grK ztiGQAhcXg2GBGnUFfLX$P&D8N28*mPBjbM-Rs&`rWxxj#;0Fn?0E3zh*$=EBKQuC= z?b>g6*6ezbtbx}n?M9~X;G#cg9Ze_yj=x-a=}&G-+VtkfimO*yKF_+YG_B~kn0-Jy z$Fey~qwgP>HZ$d z%8Sn1N%$v@$7d5?j~$MutKe^!b=`7>*!=Oe~M z&lQ|$FP7|;X4IZBw@3HVa~~U7wrC3$hG*>e#CC4mv((Y6d)c#PnVIjMKdCRZ7i3~) zWMEtj3?Bo2U|`4!Gcx{XVKra|Qpj#*1-ZGAq2{V|yhlx@_mwjF^Ub-F3R|A2JPBEG zKkklZ(k@e<<;LO-i7!01+dMW&URrZw#TJ54(bl2(QUmQ7exGbNMr3HO~p(hddki#4i`Du^Gb Lmu|hZX2K=_sbj26 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/dmitchAppleThawte.cer b/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/dmitchAppleThawte.cer new file mode 100644 index 0000000000000000000000000000000000000000..c0bed0075b5e30025f9970d5b6291619ec269f9c GIT binary patch literal 721 zcmXqLVmfQk#ALRBnTe5!iJ5=rV*_3`POUbNw(q=*j4Z4S21$n82Apinp)72|Oi_-8 zss_p+4wtY@NJe6LNveW#eqM2DPDy57x`IYPNu{QOPf3cNp^kwTNEx%RGE`YWYEf~1 zUSf`dTTyCiZenJRf@g7YDM**Iqk)__uYswdfsu)!nX$2{X%vuahQu{+GL$!vg_tJ> zH4ko#Z)$E*Y7tlg%-x)fVgf0-nI*{?4v7T?IjMTd`MCy7j7rE}V`ODuZerwT0E%-l zH8Cemp zR!_5tTU)E{-Ymu)^iJu-?THrZY&A9W_e|*fdW_L6;_`~*2!)oZ8&A%Qt1K*e@vElS zMNwf&(YlYnf^AsX6Bj89bA^X&zgxP7%X9gpg200*f)4Y$|F)SrGgb4Sn3-A9J4;II z9YeEk`0}+~ua{YyecGM!C3KTo6w6_Lp=p8pp6omkRGQc_<%-G*bD6%E-C_5(U)=g= z{i*6rhglL&lzdUxkkQs5xI!o){z-@Ot_>1_UYlk%XKU$KoH=at=4*Y1P^7kSe*F(; z`GYx2dhPs|yP4cu&cw{fz_?h~K-)kX7}BzWEFuO%jhMm61CkVGWc<&Sm(@3Kczp>HT$CLh^>p#9kO`ja)ef#=aaQ%7 z>$&vCO5U=Ple?d7&$U_CxR+hVRA%A>;M1& literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/emptyTrustSettings.plist b/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/emptyTrustSettings.plist new file mode 100644 index 00000000..e2b6ee1e --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/emptyTrustSettings.plist @@ -0,0 +1,10 @@ + + + + + trustList + + trustVersion + 1 + + diff --git a/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/localhost.cer b/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/localhost.cer new file mode 100644 index 0000000000000000000000000000000000000000..12a59c7435744d68bbe88c8970ff0c2096a50592 GIT binary patch literal 486 zcmXqLVti!K#OS?%nTe4Jhzz*dIJMe5+P?ELGO`-z844Q+vN4CUF!OMwq$ZW7D-`AD zml%p0h=K&Uc=#L(3UX2vobz)FN=s6U4CKUl4a^Ko4NQ#;jSNi9qJUg;B(8z3p^$+9 z#5~TN{N%)(jQnCe#x>42;6*rxk(GhDv6sQ1v6HE>k>Nm;zVZ50mJ;DBCwKj3%iZqK zXPI?t)|{2a$v$^vH!C*_*A`T5Qf~d*-@S6q;^}TjH|4zlp3uPhG^z4Hc#p#Vu<|tl z{pr5?oKJ=L`kt$W27g)gz2WKemzkC3&nj})ul4tR^iK1N*w=PVjVgiS3yV579eA~o z{rSb6xu=WlpNIcF$i&RZz_=I~JO=zg56KEMGX7^_HDG3BWI%Q^E6B}_4C;=%v)Dr? zbg#afIYlqb{%#Sgec;9!yisoNu2q`f+^YOcWD3VimKcst)2m|z|4!z4_n2Yp=4gNC ztJ9}nSP&c7@x-mMf2%cP#<`NSE@qKtUBU`1r9b~KoWJIqn}F~4o2#Zi*c$S4cGapc duE$>=P&72zGWh|A?8@l#sSp24F7YeU2LKm8v_}8{ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/makeTrustSettings b/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/makeTrustSettings new file mode 100755 index 00000000..c6806a86 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/makeTrustSettings @@ -0,0 +1,51 @@ +#! /bin/csh -f +# +# Build trust settings needed for the test script trustSettings.scr. +# The result is placed in userTrustSettings.plist in the build directory. +# +if ( $#argv != 0 ) then + echo "Usage: makeTrustSettings" + exit(1) +endif + +set BUILD_DIR=$LOCAL_BUILD_DIR +set TRUST_SETTINGS=userTrustSettings.plist +set TRUST_SETTINGS_PATH=$BUILD_DIR/$TRUST_SETTINGS + +echo Creating empty $TRUST_SETTINGS in build directory... +rm -f "$TRUST_SETTINGS_PATH" +security add-trusted-cert -o "$TRUST_SETTINGS_PATH" || exit(1) + +set SECTOOL=security +set SECCMD="$SECTOOL add-trusted-cert -i $TRUST_SETTINGS_PATH -o $TRUST_SETTINGS_PATH" +set cmd="$SECCMD -p ssl debugRoot.cer" +echo $cmd +$cmd || exit(1) + +# allowedError = CSSMERR_APPLETP_HOSTNAME_MISMATCH +set cmd="$SECCMD -p ssl -e -2147408896 -r unspecified localhost.cer " +echo $cmd +$cmd || exit(1) + +# allowedError = CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH +set cmd="$SECCMD -p swUpdate -e -2147408849 -r unspecified csLeafShortPath.cer" +echo $cmd +$cmd || exit(1) + +set cmd="$SECCMD -p swUpdate csRoot.cer" +echo $cmd +$cmd || exit(1) + +# allowedError = CSSMERR_TP_CERT_REVOKED +set cmd="$SECCMD -e -2147409652 -r unspecified crlTestLeaf.cer" +echo $cmd +$cmd || exit(1) + +set cmd="$SECCMD crlTestRoot.cer" +echo $cmd +$cmd || exit(1) + +# default root setting for SMIME : Deny +set cmd="$SECCMD -D -p smime -r deny" +echo $cmd +$cmd || exit(1) diff --git a/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/one.scr b/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/one.scr new file mode 100644 index 00000000..fd184338 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/one.scr @@ -0,0 +1,57 @@ +# +# TrustSettings tests/ +# +# This must be run with trustSettingsTest.keychain in your KC search path +# and TBD.plist as your per-user trust settings. +# +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +end + +test = "dmitch@apple.com Thawte, TrustSettings, generic" +useTrustSettings = true +useSystemAnchors = true +cert = dmitchAppleThawte.cer +cert = thawteCA.cer +# IS_ROOT | TRUST_SETTINGS_FOUND_SYSTEM | TRUST_SETTINGS_TRUST +certstatus = 2:0x310 +end + +test = "dmitch@apple.com Thawte, TrustSettings, generic" +useTrustSettings = true +useSystemAnchors = true +cert = dmitchAppleThawte.cer +cert = thawteCA.cer +# IS_ROOT | TRUST_SETTINGS_FOUND_SYSTEM | TRUST_SETTINGS_TRUST +certstatus = 2:0x310 +end + +test = "dmitch@apple.com Thawte, TrustSettings, generic" +useTrustSettings = true +useSystemAnchors = true +cert = dmitchAppleThawte.cer +cert = thawteCA.cer +# IS_ROOT | TRUST_SETTINGS_FOUND_SYSTEM | TRUST_SETTINGS_TRUST +certstatus = 2:0x310 +end + +test = "dmitch@apple.com Thawte, TrustSettings, generic" +useTrustSettings = true +useSystemAnchors = true +cert = dmitchAppleThawte.cer +cert = thawteCA.cer +# IS_ROOT | TRUST_SETTINGS_FOUND_SYSTEM | TRUST_SETTINGS_TRUST +certstatus = 2:0x310 +end + +test = "dmitch@apple.com Thawte, TrustSettings, generic" +useTrustSettings = true +useSystemAnchors = true +cert = dmitchAppleThawte.cer +cert = thawteCA.cer +# IS_ROOT | TRUST_SETTINGS_FOUND_SYSTEM | TRUST_SETTINGS_TRUST +certstatus = 2:0x310 +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/thawteCA.cer b/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/thawteCA.cer new file mode 100644 index 0000000000000000000000000000000000000000..e7133022d01cc80687d5338b5ce1bffab47184c6 GIT binary patch literal 835 zcmXqLVzxJEVp_3)nTe5!iILZUmyJ`a&7D}zDfMMG`_PB!LH7B*p~C`Ut4 z17Q${LzpK#wYVg;C{MvTu^`n@$Up!j%r49c;wpsXm**Ku8AyP{xP%2mG7`&6QWc!@ z^NLGzN;31(4K)nZKyuu|^3JJ6C7EfN$%!SI`FRS#sYPX($*IK(E}3PS#Xu256$2%Z zN@ihcs3`%dMaB7fi8%^xMX9N|iJ3VH&W?uK2AXhpb25s_6hIZ}ra=`slz`o!mzJmQ97NX1$}oT4i4t zc6z-HH~aIC@)ONew1m%VU;W%vZp*w+``>N}JNEq!4NNK5moM8rKlS2Kt&moJ50?7n z+b-H9vN*`4NERh*|INhA$iTR`af(6XL<1q9pJas@8UM3z7_b2;CPoGWXONgYi;aPm zfyDx|1tx7q86_nJR{HwMMLBwiaMp)}11!E^(dF!@2UKUk4KjqEg$0=I*np7-#H7?5BV9vd3*=A(rcY*IaC!7x3}}AEt#^iZaoU=6 z{`&Q6_8k&m=sa!8+qc)qp8U$8W0_hO748T{*|HuSdZ@HGb-?@88?69pms@_wAL*Qvs=HQ{VE(VTu(^ UcN8T}@2PCOEbI0^Ha^uK00|fm9{>OV literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/trustSettings.scr b/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/trustSettings.scr new file mode 100644 index 00000000..e5a64fb1 --- /dev/null +++ b/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/trustSettings.scr @@ -0,0 +1,176 @@ +# +# TrustSettings tests. +# +# This must be run with trustSettingsTest.keychain in your KC search path +# and userTrustSettings.plist as your per-user or admin trust settings. +# +# A script to recreate userTrustSettings.plist is in the makeTrustSettings +# script in this directory; the result can be imported into your user-domain +# settings via security trust-settings-import. +# +# See the buildAndTest script in this directory for al all-in-one op. +# +globals +allowUnverified = true +crlNetFetchEnable = false +certNetFetchEnable = false +useSystemAnchors = false +end + +# +# Note: with TrustSettings disabled, we pass in roots as root certs; +# with TrustSettings enabled, we pass roots as regular certs if we +# want success. +# + +# +# debugRoot and localhost, with allowed HOSTNAME_MISMATCH test +# +test = "Ensure localhost.cer fails with TrustSettings disabled" +useTrustSettings = false +cert = localhost.cer +cert = debugRoot.cer +sslHost = localhost +verifyTime = 20060601000000 +error = CSSMERR_TP_INVALID_ANCHOR_CERT +# IS_IN_INPUT_CERTS | IS_ROOT +certstatus = 1:0x14 +end + +test = "localhost.cer with TrustSettings enabled" +useTrustSettings = true +cert = localhost.cer +cert = debugRoot.cer +sslHost = localhost +verifyTime = 20060601000000 +# IS_IN_INPUT_CERTS +certstatus = 0:0x4 +# IS_IN_INPUT_CERTS | IS_ROOT | TRUST_SETTINGS_FOUND_USER | TRUST_SETTING_TRUST +certstatus = 1:0x254 +end + +test = "localhost.cer with allowedError HOSTNAME_MISMATCH" +useTrustSettings = true +cert = localhost.cer +cert = debugRoot.cer +sslHost = 127.0.0.1 +verifyTime = 20060601000000 +# IS_IN_INPUT_CERTS | TRUST_SETTINGS_FOUND_USER | TRUST_SETTINGS_IGNORED_ERROR +certstatus = 0:0x844 +# IS_IN_INPUT_CERTS | IS_ROOT | TRUST_SETTINGS_FOUND_USER | TRUST_SETTING_TRUST +certstatus = 1:0x254 +# Detected and logged but not a fatal error due to TrustSettings +certerror = 0:CSSMERR_APPLETP_HOSTNAME_MISMATCH +end + +# +# Software Update Signing with allowed CS_BAD_CERT_CHAIN_LENGTH test +# +test = "SWUSigning, normal, no TrustSettings" +useTrustSettings = false +cert = csLeaf.cer +cert = csCA.cer +root = csRoot.cer +policy = swuSign +verifyTime = 20060601000000 +# CSSM_CERT_STATUS_IS_IN_ANCHORS | IS_ROOT +certstatus = 2:0x18 +end + +test = "SWUSigning, normal, TrustSettings" +useTrustSettings = true +cert = csLeaf.cer +cert = csCA.cer +cert = csRoot.cer +policy = swuSign +verifyTime = 20060601000000 +# IS_IN_INPUT_CERTS | IS_ROOT | TRUST_SETTINGS_FOUND_USER | TRUST_SETTINGS_TRUST +certstatus = 2:254 +end + +# note no per-cert status of CS_BAD_CERT_CHAIN_LENGTH, it applies +# to the whole chain +test = "SWUSigning, allowed bad path length" +useTrustSettings = true +cert = csLeafShortPath.cer +cert = csRoot.cer +policy = swuSign +verifyTime = 20060601000000 +# IS_IN_INPUT_CERTS | IS_ROOT | TRUST_SETTINGS_FOUND_USER | TRUST_SETTINGS_TRUST +certstatus = 1:0x254 +# IS_IN_INPUT_CERTS | TRUST_SETTINGS_FOUND_USER | TRUST_SETTINGS_IGNORED_ERROR +certstatus = 0:0x844 +end + +# +# CRL testing with allowed CSSMERR_TP_CERT_REVOKED test +# see documentation in clxutils/makeCrl/testFiles/crlTime.scr for info +# on certs and CRLs. +# +test = "revoked by CRL, no TrustSettings, expect failure" +useTrustSettings = false +requireCrlForAll = true +revokePolicy = crl +cert = crlTestLeaf.cer +root = crlTestRoot.cer +crl = crl.crl +# Normal revocation case. +verifyTime = 20060418090559Z +error = CSSMERR_TP_CERT_REVOKED +certerror = 0:CSSMERR_TP_CERT_REVOKED +# CSSM_CERT_STATUS_IS_IN_ANCHORS | IS_ROOT +certstatus = 1:0x18 +end + +test = "revoked by CRL, TrustSettings, expect success" +useTrustSettings = true +requireCrlForAll = true +revokePolicy = crl +cert = crlTestLeaf.cer +cert = crlTestRoot.cer +crl = crl.crl +# Normal revocation case. +verifyTime = 20060418090559Z +# IS_IN_INPUT_CERTS | TRUST_SETTINGS_FOUND_USER | TRUST_SETTINGS_IGNORED_ERROR +certstatus = 0:0x844 +# IS_IN_INPUT_CERTS | IS_ROOT | TRUST_SETTINGS_FOUND_USER | TRUST_SETTINGS_TRUST +certstatus = 1:0x254 +certerror = 0:CSSMERR_TP_CERT_REVOKED +end + +# +# dmitch@apple.com Thawte with test of default setting = deny for SMIME +# +test = "dmitch@apple.com Thawte, no TrustSettings" +useTrustSettings = false +useSystemAnchors = true +cert = dmitchAppleThawte.cer +cert = thawteCA.cer +policy = smime +verifyTime = 20060601000000 +senderEmail = dmitch@apple.com +# CSSM_CERT_STATUS_IS_IN_ANCHORS | IS_ROOT +certstatus = 2:0x18 +end + +test = "dmitch@apple.com Thawte, TrustSettings, generic" +useTrustSettings = true +useSystemAnchors = true +cert = dmitchAppleThawte.cer +cert = thawteCA.cer +verifyTime = 20060601000000 +# IS_ROOT | TRUST_SETTINGS_FOUND_SYSTEM | TRUST_SETTINGS_TRUST +certstatus = 2:0x310 +end + +test = "dmitch@apple.com Thawte, TrustSettings, SMIME, fail due to default Deny setting" +useTrustSettings = true +useSystemAnchors = true +cert = dmitchAppleThawte.cer +cert = thawteCA.cer +senderEmail = dmitch@apple.com +verifyTime = 20060601000000 +# IS_ROOT | TRUST_SETTINGS_FOUND_USER | TRUST_SETTINGS_DENY +certstatus = 2:0x450 +error = CSSMERR_APPLETP_TRUST_SETTING_DENY +end diff --git a/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/trustSettingsTest.keychain b/SecurityTests/clxutils/certcrl/testSubjects/trustSettings/trustSettingsTest.keychain new file mode 100644 index 0000000000000000000000000000000000000000..ff99148a8a228306c6e49c79eaeb1df1637c5e99 GIT binary patch literal 30020 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 z + + + + trustList + + 1A6EE3F34707C575104855407F11366F252BDF4E + + issuerName + + MDUxGjAYBgNVBAMMEURlYnVnIENSTCB0ZXN0IENBMRcwFQYDVQQK + DA5BcHBsZSBDb21wdXRlcg== + + modDate + 2006-05-15T22:49:41Z + serialNumber + + AA== + + trustSettings + + + 2B2B62B84C339912D385727CDC9E4A325E66B848 + + issuerName + + MC4xEzARBgNVBAMMCmRlYnVnIHJvb3QxFzAVBgNVBAoMDkFwcGxl + IENvbXB1dGVy + + modDate + 2006-05-15T22:47:56Z + serialNumber + + Ag== + + trustSettings + + + kSecTrustSettingsAllowedError + -2147408896 + kSecTrustSettingsPolicy + + KoZIhvdjZAED + + kSecTrustSettingsResult + 4 + + + + 3D73463E8C498EF68455B2810A9C7143F7FABF14 + + issuerName + + MDgxHTAbBgNVBAMMFENvZGUgU2lnbiBERUJVRyBSb290MRcwFQYD + VQQKDA5BcHBsZSBDb21wdXRlcg== + + modDate + 2006-05-15T22:48:53Z + serialNumber + + Bg== + + trustSettings + + + kSecTrustSettingsPolicy + + KoZIhvdjZAEK + + + + + A252844C7A99EF1CDB285486B87A0775DD9452FF + + issuerName + + MDUxGjAYBgNVBAMMEURlYnVnIENSTCB0ZXN0IENBMRcwFQYDVQQK + DA5BcHBsZSBDb21wdXRlcg== + + modDate + 2006-05-15T22:49:20Z + serialNumber + + AQ== + + trustSettings + + + kSecTrustSettingsAllowedError + -2147409652 + kSecTrustSettingsResult + 4 + + + + E9A8529BA7C348D4909F90EBFED6A5D8F586B069 + + issuerName + + MDgxHTAbBgNVBAMMFENvZGUgU2lnbiBERUJVRyBSb290MRcwFQYD + VQQKDA5BcHBsZSBDb21wdXRlcg== + + modDate + 2006-05-15T22:48:34Z + serialNumber + + AA== + + trustSettings + + + kSecTrustSettingsAllowedError + -2147408849 + kSecTrustSettingsPolicy + + KoZIhvdjZAEK + + kSecTrustSettingsResult + 4 + + + + FD43367F400AB693F86D3E08C4D94CE4F4DFB587 + + issuerName + + MC4xEzARBgNVBAMMCmRlYnVnIHJvb3QxFzAVBgNVBAoMDkFwcGxl + IENvbXB1dGVy + + modDate + 2006-05-15T22:38:25Z + serialNumber + + AQ== + + trustSettings + + + kSecTrustSettingsPolicy + + KoZIhvdjZAED + + + + + kSecTrustRecordDefaultRootCert + + issuerName + + + modDate + 2006-05-17T17:40:36Z + serialNumber + + + trustSettings + + + kSecTrustSettingsPolicy + + KoZIhvdjZAEI + + kSecTrustSettingsResult + 3 + + + + + trustVersion + 1 + + diff --git a/SecurityTests/clxutils/certsFromDb/Makefile b/SecurityTests/clxutils/certsFromDb/Makefile new file mode 100644 index 00000000..9db0fe52 --- /dev/null +++ b/SecurityTests/clxutils/certsFromDb/Makefile @@ -0,0 +1,54 @@ +# name of executable to build +EXECUTABLE=certsFromDb +# C++ source (with .cpp extension) +CPSOURCE= certsFromDb.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/clxutils/certsFromDb/certsFromDb.cpp b/SecurityTests/clxutils/certsFromDb/certsFromDb.cpp new file mode 100644 index 00000000..7dd39b23 --- /dev/null +++ b/SecurityTests/clxutils/certsFromDb/certsFromDb.cpp @@ -0,0 +1,210 @@ +/* + * certsFromDb.cpp - extract all certs from a DB, write to files or parse to stdout. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void usage(char **argv) +{ + printf("Usage: \n"); + printf(" %s keychainFile f certFileBase [option...]\n", argv[0]); + printf(" %s keychainFile p(arse) [option...]\n", argv[0]); + printf("Options:\n"); + printf(" R fetch CRLs, not certs\n"); + printf(" P pause for MallocDebug one each item\n"); + printf(" q Quiet\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + int rtn; + CSSM_DL_DB_HANDLE dlDbHand; + CSSM_RETURN crtn; + char filePath[300]; + unsigned certNum=0; + CSSM_QUERY query; + CSSM_DB_UNIQUE_RECORD_PTR record = NULL; + CSSM_HANDLE resultHand; + CSSM_DATA theData = {0, NULL}; + char *fileBase = NULL; + CSSM_BOOL doPause = CSSM_FALSE; + CSSM_BOOL isCrl = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + int optarg = 3; + + if(argc < 3) { + usage(argv); + } + switch(argv[2][0]) { + case 'f': + if(argc < 4) { + usage(argv); + } + fileBase = argv[3]; + optarg = 4; + break; + case 'p': + /* default, parse mode */ + break; + default: + usage(argv); + } + for(int arg=optarg; arg +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NUM_CERTS_DEF 10 +#define NUM_DBS_DEF 3 +#define KEYGEN_ALG_DEF CSSM_ALGID_RSA +#define SIG_ALG_DEF CSSM_ALGID_SHA1WithRSA +#define LOOPS_DEF 10 +#define DB_NAME_BASE "cgConstruct" /* default */ +#define SECONDS_TO_LIVE (60 * 60 * 24) /* certs are valid for this long */ + +/* Read-only access not supported */ +#define PUBLIC_READ_ENABLE 0 + +static void usage(char **argv) +{ + printf("Usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" n=numCerts; default = %d\n", NUM_CERTS_DEF); + printf(" l=loops; default=%d; 0=forever\n", LOOPS_DEF); + printf(" a=alg (f=FEE/MD5, f=FEE/SHA1, e=FEE/ECDSA, r=RSA, E=ANSI ECDSA; default = RSA\n"); + printf(" K=keySizeInBits\n"); + #if TP_DB_ENABLE + printf(" d=numDBs, default = %d\n", NUM_DBS_DEF); + printf(" A(ll certs to DBs)\n"); + printf(" k (skip first DB when storing)\n"); + #if PUBLIC_READ_ENABLE + printf(" p(ublic access open on read)\n"); + #endif + #endif + printf(" f=fileNameBase (default = %s)\n", DB_NAME_BASE); + printf(" P(ause on each loop)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +#if TP_DB_ENABLE +static int doOpenDbs( + CSSM_DL_HANDLE dlHand, + const char *dbNameBase, + CSSM_DL_DB_HANDLE_PTR dlDbPtr, + unsigned numDbs, + CSSM_BOOL publicReadOnly, // ignored if !PUBLIC_READ_ENABLE + CSSM_BOOL quiet) +{ + unsigned i; + char dbName[20]; + CSSM_BOOL doCreate = (publicReadOnly ? CSSM_FALSE : CSSM_TRUE); + + for(i=0; iDLDBHandle, + dbList->NumHandles, + CSSM_FALSE, + quiet)) { // publicReadOnly: this is create/write + return 1; + } + } + /* else DBs are already open and stay that way */ + #endif + + /* + * Pick a random spot to break the cert chain - half the time use the + * whole chain, half the time break it. + */ + certsToUse = genRand(1, numCerts * 2); + if(certsToUse > numCerts) { + /* use the whole chain */ + certsToUse = numCerts; + } + if(verbose) { + printf(" ...numCerts %d certsToUse %d\n", numCerts, certsToUse); + } + + if(tpMakeRandCertGroup(clHand, + #if TP_DB_ENABLE + dbList, + #else + NULL, + #endif + certs, + certsToUse, + &certGroupFrag, + CSSM_TRUE, // firstCertIsSubject + verbose, + allInDbs, + skipFirstDb)) { + printf("Error in tpMakeRandCertGroup\n"); + return testError(quiet); + } + + if(certGroupFrag.NumCerts > certsToUse) { + printf("Error NOMAD sterlize\n"); + exit(1); + } + + #if TP_DB_ENABLE + if(publicRead) { + /* close existing DBs and open again read-only */ + + unsigned i; + CSSM_RETURN crtn; + + if(verbose) { + printf(" ...closing DBs\n"); + } + for(i=0; iNumHandles; i++) { + crtn = CSSM_DL_DbClose(dbList->DLDBHandle[i]); + if(crtn) { + printError("CSSM_DL_DbClose", crtn); + if(testError(quiet)) { + return 1; + } + } + } + if(verbose) { + printf(" ...opening DBs read-only\n"); + } + if(doOpenDbs(dlHand, + fileBaseName, + dbList->DLDBHandle, + dbList->NumHandles, + CSSM_TRUE, // publicReadOnly: this is read only + quiet)) { + return 1; + } + } + #endif + + /* + * Okay, some of the certs we were given are in the DB, some are in + * random places in certGroupFrag, some are nowhere (if certsToUse is + * less than numCerts). Have the TP construct us an ordered verified + * group. + */ + crtn = CSSM_TP_CertGroupConstruct( + tpHand, + clHand, + cspHand, + dbList, + NULL, // ConstructParams + &certGroupFrag, + &resultGroup); + if(crtn) { + printError("CSSM_TP_CertGroupConstruct", crtn); + return testError(quiet); + } + + /* vfy resultGroup is identical to unbroken part of chain */ + if(verbose) { + printf(" ...CSSM_TP_CertGroupConstruct returned %u certs\n", + (unsigned)resultGroup->NumCerts); + } + if(resultGroup->NumCerts != certsToUse) { + printf("***resultGroup->NumCerts was %u, expected %u\n", + (unsigned)resultGroup->NumCerts, (unsigned)certsToUse); + rtn = testError(quiet); + goto abort; + } + for(certDex=0; certDexGroupList.CertList[certDex])) { + printf("***certs[%d] miscompare\n", certDex); + rtn = testError(quiet); + goto abort; + } + } +abort: + /* free resurces */ + tpFreeCertGroup(&certGroupFrag, + CSSM_FALSE, // caller malloc'd the actual certs + CSSM_FALSE); // struct is on stack + tpFreeCertGroup(resultGroup, + CSSM_TRUE, // mallocd by TP + CSSM_TRUE); // ditto + #if TP_DB_ENABLE + if(dbList != NULL) { + unsigned i; + CSSM_RETURN crtn; + + if(verbose) { + printf(" ...deleting all certs from DBs\n"); + } + for(i=0; iNumHandles; i++) { + clDeleteAllCerts(dbList->DLDBHandle[i]); + } + if(publicRead) { + if(verbose) { + printf(" ...closing DBs\n"); + } + for(i=0; iNumHandles; i++) { + crtn = CSSM_DL_DbClose(dbList->DLDBHandle[i]); + if(crtn) { + printError("CSSM_DL_DbClose", crtn); + if(testError(quiet)) { + return 1; + } + } + } + } + } + #endif + return rtn; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + CSSM_TP_HANDLE tpHand = 0; + CSSM_CL_HANDLE clHand = 0; + CSSM_CSP_HANDLE cspHand = 0; + CSSM_DL_DB_LIST dbList = {0, NULL}; /* for storing certs */ + CSSM_DL_DB_LIST_PTR dbListPtr; /* pts to dbList or NULL */ + unsigned i; + char *notAfterStr; + char *notBeforeStr; + CSSM_DL_HANDLE dlHand; + + /* all three of these are arrays with numCert elements */ + CSSM_KEY_PTR pubKeys = NULL; + CSSM_KEY_PTR privKeys = NULL; + CSSM_DATA_PTR certs = NULL; + + /* Keys do NOT go in the cert DB */ + CSSM_DL_DB_HANDLE keyDb = {0, 0}; + + /* + * User-spec'd params + */ + unsigned loops = LOOPS_DEF; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + unsigned numCerts = NUM_CERTS_DEF; + uint32 keyGenAlg = KEYGEN_ALG_DEF; + uint32 sigAlg = SIG_ALG_DEF; + unsigned numDBs = NUM_DBS_DEF; + CSSM_BOOL allInDbs = CSSM_FALSE; + CSSM_BOOL skipFirstDb = CSSM_FALSE; + CSSM_BOOL publicRead = CSSM_FALSE; + CSSM_BOOL doPause = CSSM_FALSE; + uint32 keySizeInBits = CSP_KEY_SIZE_DEFAULT; + const char *fileBaseName = DB_NAME_BASE; + + for(arg=1; arg +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NUM_CERTS_DEF 10 +#define KEYGEN_ALG_DEF CSSM_ALGID_RSA +#define SIG_ALG_DEF CSSM_ALGID_SHA1WithRSA +#define LOOPS_DEF 10 +#define SECONDS_TO_LIVE (60 * 60 * 24) /* certs are valid for this long */ +//#define SECONDS_TO_LIVE 5 + +#define CERT_IN_DB 1 +#define DB_NAME "cgVerify.db" +#define DSA_PARAM_FILE "dsaParam512.der" + +/* + * How we define the "expected result". + */ +typedef enum { + ER_InvalidAnchor, // root in certGroup, not found in AnchorCerts + ER_RootInCertGroup, // root in certGroup, copy in AnchorCerts + ER_AnchorVerify, // end of chain verified by an anchor + ER_NoRoot, // no root, no anchor verify + ER_IncompleteKey // un-completable public key (all keys are partial), DSA + // ONLY +} ExpectResult; + +static void usage(char **argv) +{ + printf("Usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" n=numCerts; default = %d\n", NUM_CERTS_DEF); + printf(" l=loops; default=%d; 0=forever\n", LOOPS_DEF); + printf(" a=alg (f=FEE/MD5, F=FEE/SHA1, e=FEE/ECDSA, s=RSA/SHA1, m=RSA/MD5,\n"); + printf(" d=DSA, 4=RSA/SHA224, 6=RSA/SHA256, 3=RSA/SHA384, 5=RSA/SHA512,\n"); + printf(" E=ANSI/ECDSA, 7=ECDSA/SHA256; default = RSA/SHA1\n"); + printf(" k=keySizeInBits\n"); + printf(" d(isable DB)\n"); + printf(" P(ause on each loop)\n"); + printf(" N (no partial pub keys)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +static int doTest( + CSSM_TP_HANDLE tpHand, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + CSSM_DL_DB_HANDLE dlDb, + CSSM_DATA_PTR certs, + unsigned numCerts, + CSSM_KEY_PTR pubKeys, // for partial key detect + CSSM_BOOL useDb, + ExpectResult expectResult, + CSSM_BOOL verbose, + CSSM_BOOL quiet) +{ + unsigned cgEnd; // last cert in certGroupFrag + unsigned anchorStart; // first cert in anchorGroup + unsigned anchorEnd; // last cert in anchorGroup + CSSM_CERTGROUP certGroupFrag; // INPUT to CertGroupVerify + CSSM_CERTGROUP anchorCerts; // ditto + unsigned die; // random number + CSSM_DL_DB_LIST dbList; + CSSM_DL_DB_LIST_PTR dbListPtr; + CSSM_RETURN expErr; // expected rtn from GroupVfy() + int rtn = 0; + const char *expResStr; + uint32 expEvidenceSize; // expected evidenceSize + unsigned evidenceSize; // actual evidence size + CSSM_TP_VERIFY_CONTEXT_RESULT vfyResult; + CSSM_CERTGROUP_PTR outGrp = NULL; + CSSM_RETURN crtn; + CSSM_DL_DB_HANDLE_PTR dlDbPtr; + unsigned numAnchors; + + memset(&vfyResult, 0, sizeof(CSSM_TP_VERIFY_CONTEXT_RESULT)); + + if(useDb) { + dlDbPtr = &dlDb; + dbList.NumHandles = 1; + dbList.DLDBHandle = &dlDb; + dbListPtr = &dbList; + } + else { + /* not yet */ + dlDbPtr = NULL; + dbListPtr = NULL; + } + + /* the four test cases */ + switch(expectResult) { + case ER_InvalidAnchor: + /* root in certGroup, not found in AnchorCerts */ + cgEnd = numCerts - 1; // certGroupFrag is the whole pile + anchorStart = 0; // anchors = all except root + anchorEnd = numCerts - 2; + expErr = CSSMERR_TP_INVALID_ANCHOR_CERT; + expEvidenceSize = numCerts; + expResStr = "InvalidAnchor (root in certGroup but not in anchors)"; + break; + + case ER_RootInCertGroup: + /* root in certGroup, copy in AnchorCerts */ + cgEnd = numCerts - 1; // certGroupFrag = the whole pile + anchorStart = 0; // anchors = the whole pile + anchorEnd = numCerts - 1; + expErr = CSSM_OK; + expEvidenceSize = numCerts; + expResStr = "Good (root in certGroup AND in anchors)"; + break; + + case ER_AnchorVerify: + /* non-root end of chain verified by an anchor */ + /* break chain at random place other than end */ + /* die is the last cert in certGroupFrag */ + die = genRand(0, numCerts-2); + cgEnd = die; // certGroupFrag up to break point + anchorStart = 0; // anchors = all + anchorEnd = numCerts - 1; + if(pubKeys[die+1].KeyHeader.KeyAttr & CSSM_KEYATTR_PARTIAL) { + /* this will fail due to an unusable anchor */ + expErr = CSSMERR_TP_CERTIFICATE_CANT_OPERATE; + expResStr = "Root ONLY in anchors but has partial pub key"; + } + else { + expErr = CSSM_OK; + expResStr = "Good (root ONLY in anchors)"; + } + /* size = # certs in certGroupFrag, plus one anchor */ + expEvidenceSize = die + 2; + break; + + case ER_NoRoot: + /* no root, no anchor verify */ + /* break chain at random place other than end */ + /* die is the last cert in certGroupFrag */ + /* skip a cert, then anchors start at die + 2 */ + die = genRand(0, numCerts-2); + cgEnd = die; // certGroupFrag up to break point + anchorStart = die + 2; // anchors = n+1...numCerts-2 + // may be empty if n == numCerts-2 + anchorEnd = numCerts - 2; + if((die != 0) && // partial leaf not reported as partial! + (pubKeys[die].KeyHeader.KeyAttr & CSSM_KEYATTR_PARTIAL)) { + /* this will fail due to an unusable cert (this one) */ + expErr = CSSMERR_TP_CERTIFICATE_CANT_OPERATE; + expResStr = "Not Trusted (no root, no anchor verify), partial"; + } + else { + expErr = CSSMERR_TP_NOT_TRUSTED; + expResStr = "Not Trusted (no root, no anchor verify)"; + } + expEvidenceSize = die + 1; + break; + + case ER_IncompleteKey: + /* + * Anchor has incomplete pub key + * Root in certGroup, copy in AnchorCerts + * Avoid putting anchor in certGroupFrag because the TP will think + * it's NOT a root and it'll show up twice in the evidence - once + * from certGroupFrag (at which point the search for a root + * keeps going), and once from Anchors. + */ + cgEnd = numCerts - 2; // certGroupFrag = the whole pile less the anchor + anchorStart = 0; // anchors = the whole pile + anchorEnd = numCerts - 1; + expErr = CSSMERR_TP_CERTIFICATE_CANT_OPERATE; + expEvidenceSize = numCerts; + expResStr = "Partial public key in anchor"; + break; + } + + if(verbose) { + printf(" ...expectResult = %s\n", expResStr); + } + + /* cook up two cert groups */ + if(verbose) { + printf(" ...building certGroupFrag from certs[0..%d]\n", + cgEnd); + } + if(tpMakeRandCertGroup(clHand, + dbListPtr, + certs, // certGroupFrag always starts at 0 + cgEnd+1, // # of certs + &certGroupFrag, + CSSM_TRUE, // firstCertIsSubject + verbose, + CSSM_FALSE, // allInDbs + CSSM_FALSE)) { // skipFirstDb + printf("Error in tpMakeRandCertGroup\n"); + return 1; + } + + if(verbose) { + printf(" ...building anchorCerts from certs[%d..%d]\n", + anchorStart, anchorEnd); + } + if(anchorEnd > (numCerts - 1)) { + printf("anchorEnd overflow\n"); + exit(1); + } + if(anchorStart >= anchorEnd) { + /* legal in some corner cases, ==> empty enchors */ + numAnchors = 0; + } + else { + numAnchors = anchorEnd - anchorStart + 1; + } + /* anchors do not go in DB */ + if(tpMakeRandCertGroup(clHand, + NULL, + certs + anchorStart, + numAnchors, // # of certs + &anchorCerts, + CSSM_FALSE, // firstCertIsSubject + verbose, + CSSM_FALSE, // allInDbs + CSSM_FALSE)) { // skipFirstDb + printf("Error in tpMakeRandCertGroup\n"); + return 1; + } + + crtn = tpCertGroupVerify( + tpHand, + clHand, + cspHand, + dbListPtr, + &CSSMOID_APPLE_X509_BASIC, // policy + NULL, // fieldOpts + NULL, // actionData + NULL, // policyOpts + &certGroupFrag, + anchorCerts.GroupList.CertList, // passed as CSSM_DATA_PTR, not CERTGROUP.... + anchorCerts.NumCerts, + CSSM_TP_STOP_ON_POLICY, + NULL, // cssmTimeStr + &vfyResult); + + /* first verify format of result */ + if( (vfyResult.NumberOfEvidences != 3) || + (vfyResult.Evidence == NULL) || + (vfyResult.Evidence[0].EvidenceForm != CSSM_EVIDENCE_FORM_APPLE_HEADER) || + (vfyResult.Evidence[1].EvidenceForm != CSSM_EVIDENCE_FORM_APPLE_CERTGROUP) || + (vfyResult.Evidence[2].EvidenceForm != CSSM_EVIDENCE_FORM_APPLE_CERT_INFO) || + (vfyResult.Evidence[0].Evidence == NULL) || + (vfyResult.Evidence[1].Evidence == NULL) || + (vfyResult.Evidence[2].Evidence == NULL)) { + printf("***Malformed VerifyContextResult\n"); + rtn = testError(quiet); + if(rtn) { + return rtn; + } + } + if((vfyResult.Evidence != NULL) && (vfyResult.Evidence[1].Evidence != NULL)) { + outGrp = (CSSM_CERTGROUP_PTR)vfyResult.Evidence[1].Evidence; + evidenceSize = outGrp->NumCerts; + } + else { + /* in case no evidence returned */ + evidenceSize = 0; + } + + /* %%% since non-root anchors are permitted as of , + * the test assumptions have become invalid: these tests generate + * an anchors list which always includes the full chain, so by + * definition, the evidence chain will never be longer than 2, + * since the leaf's issuer is always an anchor. + * %%% need to revisit and rewrite these tests. -kcm + */ + if ((evidenceSize > 1) && (evidenceSize < expEvidenceSize) && + (crtn == CSSM_OK || crtn == CSSMERR_TP_CERTIFICATE_CANT_OPERATE)) { + /* ignore, for now */ + expErr = crtn; + expEvidenceSize = evidenceSize; + } + + if((crtn != expErr) || + (evidenceSize != expEvidenceSize)) { + printf("***Error on expectResult %s\n", expResStr); + printf(" err %s expErr %s\n", + cssmErrToStr(crtn), cssmErrToStr(expErr)); + printf(" evidenceSize %d expEvidenceSize %u\n", + evidenceSize, (unsigned)expEvidenceSize); + rtn = testError(quiet); + } + else { + rtn = 0; + } + + /* free resources */ + tpFreeCertGroup(&certGroupFrag, + CSSM_FALSE, // caller malloc'd the actual certs + CSSM_FALSE); // struct is on stack + tpFreeCertGroup(&anchorCerts, + CSSM_FALSE, // caller malloc'd the actual certs + CSSM_FALSE); // struct is on stack + freeVfyResult(&vfyResult); + if(useDb) { + clDeleteAllCerts(dlDb); + } + return rtn; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + CSSM_TP_HANDLE tpHand = 0; + CSSM_CL_HANDLE clHand = 0; + CSSM_CSP_HANDLE cspHand = 0; + CSSM_DL_DB_HANDLE dlDbHand = {0, 0}; + ExpectResult expectResult; + char *notAfterStr; + char *notBeforeStr; + unsigned i; + CSSM_DATA paramData; + CSSM_DATA_PTR paramDataP = NULL; + unsigned numTests = 4; + unsigned len; + + /* all three of these are arrays with numCert elements */ + CSSM_KEY_PTR pubKeys = NULL; + CSSM_KEY_PTR privKeys = NULL; + CSSM_DATA_PTR certs = NULL; + + /* Keys do NOT go in the cert DB */ + CSSM_DL_DB_HANDLE keyDb = {0, 0}; + CSSM_KEY savedRoot; // for ER_IncompleteKey + + /* + * User-spec'd params + */ + unsigned loops = LOOPS_DEF; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + unsigned numCerts = NUM_CERTS_DEF; + uint32 keyGenAlg = KEYGEN_ALG_DEF; + uint32 sigAlg = SIG_ALG_DEF; + #if CERT_IN_DB + CSSM_BOOL useDb = CSSM_TRUE; + #else + CSSM_BOOL useDb = CSSM_FALSE; + #endif + CSSM_BOOL doPause = CSSM_FALSE; + uint32 keySizeInBits = CSP_KEY_SIZE_DEFAULT; + CSSM_BOOL noPartialKeys = CSSM_FALSE; + char dbName[100]; /* DB_NAME_pid */ + + for(arg=1; args zTk_pg?`{jD)3y)IZjotNvX91rg6Ud!rw<8MY&0zm+Z zf94C;9Pq^S7GN1poM&qy&;B;DwUrC)*+Ur;(GZL}w`a`LX#xpu&h9 O?j%}%aai~eLZnw?l~APs literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/cgVerifyParsed/Makefile b/SecurityTests/clxutils/cgVerifyParsed/Makefile new file mode 100644 index 00000000..2c01039e --- /dev/null +++ b/SecurityTests/clxutils/cgVerifyParsed/Makefile @@ -0,0 +1,54 @@ +# name of executable to build +EXECUTABLE=cgVerifyParsed +# C++ source (with .cpp extension) +CPSOURCE= cgVerifyParsed.cpp tpVerifyParsed.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/clxutils/cgVerifyParsed/cgVerifyParsed.cpp b/SecurityTests/clxutils/cgVerifyParsed/cgVerifyParsed.cpp new file mode 100644 index 00000000..875390c7 --- /dev/null +++ b/SecurityTests/clxutils/cgVerifyParsed/cgVerifyParsed.cpp @@ -0,0 +1,699 @@ +/* + * cgVerifyParsed.cpp - basic test of TP's CertGroupVerify using parsed anchors + * + * ------- THIS TEST IS OBSOLETE; WE DON'T SUPPORT PARSED ANCHORS ---------- + * + * cook up array of n key pairs; + * cook up cert chain to go with them; + * main test loop { + * numCerts = total # of incoming certs; + * test one of four or five "expected result" cases { + * case root in certGroup but not found in AnchorCerts: + * certGroup = tpMakeRandCertGroup(certs[0..numCerts-1]; + * anchorCerts = tpMakeRandCertGroup[certs[0...numCerts-2]; + * expErr = CSSMERR_TP_INVALID_ANCHOR_CERT; + * expEvidenceSize = numCerts; + * case root in certGroup, found a copy in AnchorCerts: + * certGroup = tpMakeRandCertGroup(certs[0..numCerts-1]; + * anchorCerts = tpMakeRandCertGroup[certs[0...numCerts-1]; + * expErr = CSSM_OK; + * expEvidenceSize = numCerts; + * case verified by an AnchorCert: + * n = rand(1, numCerts-2); + * certGroup = tpMakeRandCertGroup(certs[0..n]); + * anchorCerts = tpMakeRandCertGroup[certs[0...numCerts-2]; + * expErr = CSSM_OK; + * expEvidenceSize = n+2; + * case no root found: + * n = rand(1, numCerts-3); + * certGroup = tpMakeRandCertGroup(certs[0..n]); + * anchorCerts = tpMakeRandCertGroup[certs[n+2...numCerts-2]; + * anchorCerts may be empty.... + * expErr = CSSMERR_TP_NOT_TRUSTED; + * expEvidenceSize = n+1; + * case incomplete public key (DSA only): + * root public keys is incomplete; + * certGroup = tpMakeRandCertGroup(certs[0..numCerts-1]; + * anchorCerts = tpMakeRandCertGroup[certs[0...numCerts-1]; + * expErr = CSSM_OK; + * expEvidenceSize = numCerts; + * } + * result = certGroupVerify(); + * verify expected result and getError(); + * delete certs from DB; + * } + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tpVerifyParsed.h" + +#define NUM_CERTS_DEF 10 +#define KEYGEN_ALG_DEF CSSM_ALGID_RSA +#define SIG_ALG_DEF CSSM_ALGID_SHA1WithRSA +#define LOOPS_DEF 10 +#define SECONDS_TO_LIVE (60 * 60 * 24) /* certs are valid for this long */ +//#define SECONDS_TO_LIVE 5 + +#define CERT_IN_DB 1 +#define DB_NAME "cgVerify.db" +#define DSA_PARAM_FILE "dsaParam512.der" + +/* + * How we define the "expected result". + */ +typedef enum { + ER_InvalidAnchor, // root in certGroup, not found in AnchorCerts + ER_RootInCertGroup, // root in certGroup, copy in AnchorCerts + ER_AnchorVerify, // end of chain verified by an anchor + ER_NoRoot, // no root, no anchor verify + ER_IncompleteKey // un-completable public key (all keys are partial), DSA + // ONLY +} ExpectResult; + +static void usage(char **argv) +{ + printf("Usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" n=numCerts; default = %d\n", NUM_CERTS_DEF); + printf(" l=loops; default=%d; 0=forever\n", LOOPS_DEF); + printf(" a=alg (f=FEE/MD5, F=FEE/SHA1, e=FEE/ECDSA, s=RSA/SHA1, m=RSA/MD5,\n"); + printf(" d=DSA; 6=RSA/SHA256, 3=RSA/SHA384, 5=RSA/SHA512; default = RSA/SHA1\n"); + printf(" k=keySizeInBits\n"); + printf(" d(isable DB)\n"); + printf(" P(ause on each loop)\n"); + printf(" N (no partial pub keys)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +static int doTest( + CSSM_TP_HANDLE tpHand, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + CSSM_DL_DB_HANDLE dlDb, + CSSM_DATA_PTR certs, + unsigned numCerts, + CSSM_KEY_PTR pubKeys, // for partial key detect + CSSM_BOOL useDb, + ExpectResult expectResult, + CSSM_BOOL verbose, + CSSM_BOOL quiet) +{ + unsigned cgEnd; // last cert in certGroupFrag + unsigned anchorStart; // first cert in anchorGroup + unsigned anchorEnd; // last cert in anchorGroup + CSSM_CERTGROUP certGroupFrag; // INPUT to CertGroupVerify + CSSM_CERTGROUP anchorCerts; // ditto + unsigned die; // random number + CSSM_DL_DB_LIST dbList; + CSSM_DL_DB_LIST_PTR dbListPtr; + CSSM_RETURN expErr; // expected rtn from GroupVfy() + int rtn = 0; + char *expResStr; + uint32 expEvidenceSize; // expected evidenceSize + unsigned evidenceSize; // actual evidence size + CSSM_TP_VERIFY_CONTEXT_RESULT vfyResult; + CSSM_CERTGROUP_PTR outGrp = NULL; + CSSM_RETURN crtn; + CSSM_DL_DB_HANDLE_PTR dlDbPtr; + unsigned numAnchors; + + memset(&vfyResult, 0, sizeof(CSSM_TP_VERIFY_CONTEXT_RESULT)); + + if(useDb) { + dlDbPtr = &dlDb; + dbList.NumHandles = 1; + dbList.DLDBHandle = &dlDb; + dbListPtr = &dbList; + } + else { + /* not yet */ + dlDbPtr = NULL; + dbListPtr = NULL; + } + + /* the four test cases */ + switch(expectResult) { + case ER_InvalidAnchor: + /* root in certGroup, not found in AnchorCerts */ + cgEnd = numCerts - 1; // certGroupFrag is the whole pile + anchorStart = 0; // anchors = all except root + anchorEnd = numCerts - 2; + expErr = CSSMERR_TP_INVALID_ANCHOR_CERT; + expEvidenceSize = numCerts; + expResStr = "InvalidAnchor (root in certGroup but not in anchors)"; + break; + + case ER_RootInCertGroup: + /* root in certGroup, copy in AnchorCerts */ + cgEnd = numCerts - 1; // certGroupFrag = the whole pile + anchorStart = 0; // anchors = the whole pile + anchorEnd = numCerts - 1; + expErr = CSSM_OK; + expEvidenceSize = numCerts; + expResStr = "Good (root in certGroup AND in anchors)"; + break; + + case ER_AnchorVerify: + /* non-root end of chain verified by an anchor */ + /* break chain at random place other than end */ + /* die is the last cert in certGroupFrag */ + die = genRand(0, numCerts-2); + cgEnd = die; // certGroupFrag up to break point + anchorStart = 0; // anchors = all + anchorEnd = numCerts - 1; + if(pubKeys[die+1].KeyHeader.KeyAttr & CSSM_KEYATTR_PARTIAL) { + /* this will fail due to an unusable anchor */ + expErr = CSSMERR_TP_CERTIFICATE_CANT_OPERATE; + expResStr = "Root ONLY in anchors but has partial pub key"; + } + else { + expErr = CSSM_OK; + expResStr = "Good (root ONLY in anchors)"; + } + /* size = # certs in certGroupFrag, plus one anchor */ + expEvidenceSize = die + 2; + break; + + case ER_NoRoot: + /* no root, no anchor verify */ + /* break chain at random place other than end */ + /* die is the last cert in certGroupFrag */ + /* skip a cert, then anchors start at die + 2 */ + die = genRand(0, numCerts-2); + cgEnd = die; // certGroupFrag up to break point + anchorStart = die + 2; // anchors = n+1...numCerts-2 + // may be empty if n == numCerts-2 + anchorEnd = numCerts - 2; + if((die != 0) && // partial leaf not reported as partial! + (pubKeys[die].KeyHeader.KeyAttr & CSSM_KEYATTR_PARTIAL)) { + /* this will fail due to an unusable cert (this one) */ + expErr = CSSMERR_TP_CERTIFICATE_CANT_OPERATE; + expResStr = "Not Trusted (no root, no anchor verify), partial"; + } + else { + expErr = CSSMERR_TP_NOT_TRUSTED; + expResStr = "Not Trusted (no root, no anchor verify)"; + } + expEvidenceSize = die + 1; + break; + + case ER_IncompleteKey: + /* + * Anchor has incomplete pub key + * Root in certGroup, copy in AnchorCerts + * Avoid putting anchor in certGroupFrag because the TP will think + * it's NOT a root and it'll show up twice in the evidence - once + * from certGroupFrag (at which point the search for a root + * keeps going), and once from Anchors. + */ + cgEnd = numCerts - 2; // certGroupFrag = the whole pile less the anchor + anchorStart = 0; // anchors = the whole pile + anchorEnd = numCerts - 1; + expErr = CSSMERR_TP_CERTIFICATE_CANT_OPERATE; + expEvidenceSize = numCerts; + expResStr = "Partial public key in anchor"; + break; + } + + if(verbose) { + printf(" ...expectResult = %s\n", expResStr); + } + + /* cook up two cert groups */ + if(verbose) { + printf(" ...building certGroupFrag from certs[0..%d]\n", + cgEnd); + } + if(tpMakeRandCertGroup(clHand, + dbListPtr, + certs, // certGroupFrag always starts at 0 + cgEnd+1, // # of certs + &certGroupFrag, + CSSM_TRUE, // firstCertIsSubject + verbose, + CSSM_FALSE, // allInDbs + CSSM_FALSE)) { // skipFirstDb + printf("Error in tpMakeRandCertGroup\n"); + return 1; + } + + if(verbose) { + printf(" ...building anchorCerts from certs[%d..%d]\n", + anchorStart, anchorEnd); + } + if(anchorEnd > (numCerts - 1)) { + printf("anchorEnd overflow\n"); + exit(1); + } + if(anchorStart >= anchorEnd) { + /* legal in some corner cases, ==> empty enchors */ + numAnchors = 0; + } + else { + numAnchors = anchorEnd - anchorStart + 1; + } + /* anchors do not go in DB */ + if(tpMakeRandCertGroup(clHand, + NULL, + certs + anchorStart, + numAnchors, // # of certs + &anchorCerts, + CSSM_FALSE, // firstCertIsSubject + verbose, + CSSM_FALSE, // allInDbs + CSSM_FALSE)) { // skipFirstDb + printf("Error in tpMakeRandCertGroup\n"); + return 1; + } + + crtn = tpCertGroupVerifyParsed( + tpHand, + clHand, + cspHand, + dbListPtr, + &CSSMOID_APPLE_X509_BASIC, // policy + NULL, // fieldOpts + NULL, // actionData + NULL, // policyOpts + &certGroupFrag, + anchorCerts.GroupList.CertList, // passed as CSSM_DATA_PTR, not CERTGROUP.... + anchorCerts.NumCerts, + CSSM_TP_STOP_ON_POLICY, + NULL, // cssmTimeStr + &vfyResult); + + /* first verify format of result */ + if( (vfyResult.NumberOfEvidences != 3) || + (vfyResult.Evidence == NULL) || + (vfyResult.Evidence[0].EvidenceForm != CSSM_EVIDENCE_FORM_APPLE_HEADER) || + (vfyResult.Evidence[1].EvidenceForm != CSSM_EVIDENCE_FORM_APPLE_CERTGROUP) || + (vfyResult.Evidence[2].EvidenceForm != CSSM_EVIDENCE_FORM_APPLE_CERT_INFO) || + (vfyResult.Evidence[0].Evidence == NULL) || + (vfyResult.Evidence[1].Evidence == NULL) || + (vfyResult.Evidence[2].Evidence == NULL)) { + printf("***Malformed VerifyContextResult\n"); + rtn = testError(quiet); + if(rtn) { + return rtn; + } + } + if((vfyResult.Evidence != NULL) && (vfyResult.Evidence[1].Evidence != NULL)) { + outGrp = (CSSM_CERTGROUP_PTR)vfyResult.Evidence[1].Evidence; + evidenceSize = outGrp->NumCerts; + } + else { + /* in case no evidence returned */ + evidenceSize = 0; + } + if((crtn != expErr) || + (evidenceSize != expEvidenceSize)) { + printf("***Error on expectResult %s\n", expResStr); + printf(" err %s expErr %s\n", + cssmErrToStr(crtn), cssmErrToStr(expErr)); + printf(" evidenceSize %d expEvidenceSize %lu\n", + evidenceSize, expEvidenceSize); + rtn = testError(quiet); + } + else { + rtn = 0; + } + + /* free resources */ + tpFreeCertGroup(&certGroupFrag, + CSSM_FALSE, // caller malloc'd the actual certs + CSSM_FALSE); // struct is on stack + tpFreeCertGroup(&anchorCerts, + CSSM_FALSE, // caller malloc'd the actual certs + CSSM_FALSE); // struct is on stack + freeVfyResult(&vfyResult); + if(useDb) { + clDeleteAllCerts(dlDb); + } + return rtn; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + CSSM_TP_HANDLE tpHand = 0; + CSSM_CL_HANDLE clHand = 0; + CSSM_CSP_HANDLE cspHand = 0; + CSSM_DL_DB_HANDLE dlDbHand = {0, 0}; + ExpectResult expectResult; + char *notAfterStr; + char *notBeforeStr; + unsigned i; + CSSM_DATA paramData; + CSSM_DATA_PTR paramDataP = NULL; + unsigned numTests = 4; + + /* all three of these are arrays with numCert elements */ + CSSM_KEY_PTR pubKeys = NULL; + CSSM_KEY_PTR privKeys = NULL; + CSSM_DATA_PTR certs = NULL; + + /* Keys do NOT go in the cert DB */ + CSSM_DL_DB_HANDLE keyDb = {0, 0}; + CSSM_KEY savedRoot; // for ER_IncompleteKey + + /* + * User-spec'd params + */ + unsigned loops = LOOPS_DEF; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + unsigned numCerts = NUM_CERTS_DEF; + uint32 keyGenAlg = KEYGEN_ALG_DEF; + uint32 sigAlg = SIG_ALG_DEF; + #if CERT_IN_DB + CSSM_BOOL useDb = CSSM_TRUE; + #else + CSSM_BOOL useDb = CSSM_FALSE; + #endif + CSSM_BOOL doPause = CSSM_FALSE; + uint32 keySizeInBits = CSP_KEY_SIZE_DEFAULT; + CSSM_BOOL noPartialKeys = CSSM_FALSE; + char dbName[100]; /* DB_NAME_pid */ + + for(arg=1; args zTk_pg?`{jD)3y)IZjotNvX91rg6Ud!rw<8MY&0zm+Z zf94C;9Pq^S7GN1poM&qy&;B;DwUrC)*+Ur;(GZL}w`a`LX#xpu&h9 O?j%}%aai~eLZnw?l~APs literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/cgVerifyParsed/tpVerifyParsed.cpp b/SecurityTests/clxutils/cgVerifyParsed/tpVerifyParsed.cpp new file mode 100644 index 00000000..5eb22641 --- /dev/null +++ b/SecurityTests/clxutils/cgVerifyParsed/tpVerifyParsed.cpp @@ -0,0 +1,178 @@ + /* + * tpVerifyParsed.cpp - wrapper for CSSM_TP_CertGroupVerify using parsd anchors. + */ + +#include +#include "tpVerifyParsed.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * The main task is converting a set of CSSM_DATA-style anchors into a + * SecParsedRootCertArrayRef. + */ + +/* raw cert --> SecParsedRootCert */ +static int parseRootCert( + CSSM_CL_HANDLE clHand, + const CSSM_DATA &certData, + SecParsedRootCert &parsedRoot) +{ + try { + CertParser cert(clHand, certData); + uint32 len = 0; + const void *p = cert.fieldForOid(CSSMOID_X509V1SubjectName, len); + appCopyData(p, len, &parsedRoot.subject); + + /* skip key and times, I think they are going away */ + appCopyCssmData(&certData, &parsedRoot.certData); + return 0; + } + catch(...) { + printf("CertParser threw!\n"); + return -1; + } +} + +static void freeParsedRoot( + SecParsedRootCert &parsedRoot) +{ + if(parsedRoot.subject.Data) { + CSSM_FREE(parsedRoot.subject.Data); + } + if(parsedRoot.certData.Data) { + CSSM_FREE(parsedRoot.certData.Data); + } +} + +static int createParsedCertArray( + CSSM_CL_HANDLE clHand, + unsigned numAnchorCerts, + CSSM_DATA_PTR anchorCerts, + SecParsedRootCertArrayRef *arrayRef) // RETURNED +{ + SecParsedRootCertArray *outArray = (SecParsedRootCertArray *)malloc(sizeof(*outArray)); + memset(outArray, 0, sizeof(*outArray)); + unsigned len = sizeof(SecParsedRootCert) * numAnchorCerts; + outArray->roots = (SecParsedRootCert *)malloc(len); + memset(outArray->roots, 0, len); + for(unsigned dex=0; dexroots[dex])) { + return -1; + } + } + outArray->numRoots = numAnchorCerts; + *arrayRef = outArray; + return 0; +} + +static void freeParsedCertArray( + SecParsedRootCertArrayRef arrayRef) +{ + for(unsigned dex=0; dexnumRoots; dex++) { + freeParsedRoot(arrayRef->roots[dex]); + } + free(arrayRef->roots); + free((void *)arrayRef); +} + +CSSM_RETURN tpCertGroupVerifyParsed( + CSSM_TP_HANDLE tpHand, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + CSSM_DL_DB_LIST_PTR dbListPtr, + const CSSM_OID *policy, // optional + const CSSM_DATA *fieldOpts, // optional + const CSSM_DATA *actionData, // optional + void *policyOpts, + const CSSM_CERTGROUP *certGroup, + CSSM_DATA_PTR anchorCerts, + unsigned numAnchorCerts, + CSSM_TP_STOP_ON stopOn, // CSSM_TP_STOP_ON_POLICY, etc. + CSSM_TIMESTRING cssmTimeStr,// optional + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR result) // optional, RETURNED +{ + /* main job is building a CSSM_TP_VERIFY_CONTEXT and its components */ + CSSM_TP_VERIFY_CONTEXT vfyCtx; + CSSM_TP_CALLERAUTH_CONTEXT authCtx; + + memset(&vfyCtx, 0, sizeof(CSSM_TP_VERIFY_CONTEXT)); + vfyCtx.Action = CSSM_TP_ACTION_DEFAULT; + if(actionData) { + vfyCtx.ActionData = *actionData; + } + else { + vfyCtx.ActionData.Data = NULL; + vfyCtx.ActionData.Length = 0; + } + vfyCtx.Cred = &authCtx; + + /* CSSM_TP_CALLERAUTH_CONTEXT components */ + /* + typedef struct cssm_tp_callerauth_context { + CSSM_TP_POLICYINFO Policy; + CSSM_TIMESTRING VerifyTime; + CSSM_TP_STOP_ON VerificationAbortOn; + CSSM_TP_VERIFICATION_RESULTS_CALLBACK CallbackWithVerifiedCert; + uint32 NumberOfAnchorCerts; + CSSM_DATA_PTR AnchorCerts; + CSSM_DL_DB_LIST_PTR DBList; + CSSM_ACCESS_CREDENTIALS_PTR CallerCredentials; + } CSSM_TP_CALLERAUTH_CONTEXT, *CSSM_TP_CALLERAUTH_CONTEXT_PTR; + */ + /* zero or one policy here */ + CSSM_FIELD policyId; + if(policy != NULL) { + policyId.FieldOid = (CSSM_OID)*policy; + authCtx.Policy.NumberOfPolicyIds = 1; + authCtx.Policy.PolicyIds = &policyId; + if(fieldOpts != NULL) { + policyId.FieldValue = *fieldOpts; + } + else { + policyId.FieldValue.Data = NULL; + policyId.FieldValue.Length = 0; + } + } + else { + authCtx.Policy.NumberOfPolicyIds = 0; + authCtx.Policy.PolicyIds = NULL; + } + authCtx.Policy.PolicyControl = policyOpts; + authCtx.VerifyTime = cssmTimeStr; // may be NULL + authCtx.VerificationAbortOn = stopOn; + authCtx.CallbackWithVerifiedCert = NULL; + + /* here's the difference between this and tpCertGroupVerify */ + SecParsedRootCertArrayRef arrayRef = NULL; + if(numAnchorCerts) { + if(createParsedCertArray(clHand, numAnchorCerts, anchorCerts, &arrayRef)) { + return -1; + } + authCtx.NumberOfAnchorCerts = APPLE_TP_PARSED_ANCHOR_INDICATOR; + authCtx.AnchorCerts = (CSSM_DATA_PTR)arrayRef; + } + else { + authCtx.NumberOfAnchorCerts = 0; + authCtx.AnchorCerts = NULL; + } + authCtx.DBList = dbListPtr; + authCtx.CallerCredentials = NULL; + + CSSM_RETURN crtn = CSSM_TP_CertGroupVerify(tpHand, + clHand, + cspHand, + certGroup, + &vfyCtx, + result); + + if(arrayRef) { + freeParsedCertArray(arrayRef); + } + return crtn; +} diff --git a/SecurityTests/clxutils/cgVerifyParsed/tpVerifyParsed.h b/SecurityTests/clxutils/cgVerifyParsed/tpVerifyParsed.h new file mode 100644 index 00000000..85225802 --- /dev/null +++ b/SecurityTests/clxutils/cgVerifyParsed/tpVerifyParsed.h @@ -0,0 +1,33 @@ + /* + * tpVerifyParsed.h - wrapper for CSSM_TP_CertGroupVerify using parsd anchors. + */ + +#ifndef _TP_VERIFY_PARSED_H_ +#define _TP_VERIFY_PARSED_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +CSSM_RETURN tpCertGroupVerifyParsed( + CSSM_TP_HANDLE tpHand, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + CSSM_DL_DB_LIST_PTR dbListPtr, + const CSSM_OID *policy, // optional + const CSSM_DATA *fieldOpts, // optional + const CSSM_DATA *actionData, // optional + void *policyOpts, + const CSSM_CERTGROUP *certGroup, + CSSM_DATA_PTR anchorCerts, + unsigned numAnchorCerts, + CSSM_TP_STOP_ON stopOn, // CSSM_TP_STOP_ON_POLICY, etc. + CSSM_TIMESTRING cssmTimeStr, // optional + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR result); // optional, RETURNED + +#ifdef __cplusplus +} +#endif + +#endif /* _TP_VERIFY_PARSED_H_ */ + diff --git a/SecurityTests/clxutils/clAppUtils/BlobList.cpp b/SecurityTests/clxutils/clAppUtils/BlobList.cpp new file mode 100644 index 00000000..53bd05b4 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/BlobList.cpp @@ -0,0 +1,92 @@ +/*** BlobList class for managing groups of raw certs and CRLs ***/ + +#include "BlobList.h" +#include +#include +#include +#include +#include +#include + +BlobList::~BlobList() +{ + for(uint32 dex=0; dexLength = blob.Length; + dst->Data = (uint8 *)malloc(dst->Length); + memmove(dst->Data, blob.Data, dst->Length); + } + else { + *dst = blob; + } +} + + +int BlobList::addFile(const char *fileName, + const char *dirName /* = NULL */) +{ + CSSM_DATA blob; + int rtn; + char *fullName; + unsigned blobDataLen; + unsigned char *blobData; + + if(dirName) { + int len = strlen(dirName) + strlen(fileName) + 2; + fullName = (char *)malloc(len); + sprintf(fullName, "%s/%s", dirName, fileName); + } + else { + fullName = (char *)fileName; + } + rtn = cspReadFile(fullName, &blobData, &blobDataLen); + if(rtn) { + printf("***Error reading file %s\n", fullName); + if(dirName) { + free(fullName); + } + return rtn; + } + + /* convert from PEM to DER if appropriate */ + if(isPem(blobData, blobDataLen)) { + unsigned derDataLen; + unsigned char *derData; + + if(pemDecode(blobData, blobDataLen, &derData, &derDataLen)) { + printf("***Error PEM-decoding file %s; using as raw data\n", fileName); + blob.Data = blobData; + blob.Length = blobDataLen; + } + else { + blob.Data = derData; + blob.Length = derDataLen; + free(blobData); + } + } + else { + /* raw file data is the stuff we'll use */ + blob.Data = blobData; + blob.Length = blobDataLen; + } + addBlob(blob); + if(dirName) { + free(fullName); + } + return 0; +} + diff --git a/SecurityTests/clxutils/clAppUtils/BlobList.h b/SecurityTests/clxutils/clAppUtils/BlobList.h new file mode 100644 index 00000000..e30770f9 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/BlobList.h @@ -0,0 +1,30 @@ +#ifndef _BLOBLIST_H_ +#define _BLOBLIST_H_ + +#include + +#ifndef NULL +#define NULL (0) +#endif + +/*** BlobList class for managing groups of raw certs and CRLs ***/ + +class BlobList +{ +public: + BlobList() + : mNumBlobs(0), mBlobList(NULL) { } + ~BlobList(); + /* blob is mallocd & copied; its referent is only copied if copyBlob is + * true and is always freed in ~BlobList */ + void addBlob(const CSSM_DATA &blob, CSSM_BOOL copyBlob = CSSM_FALSE); + int addFile(const char *fileName, const char *dirName = NULL); + uint32 numBlobs() { return mNumBlobs; } + CSSM_DATA_PTR blobList() { return mBlobList; } + +private: + uint32 mNumBlobs; + CSSM_DATA_PTR mBlobList; +}; + +#endif /* _BLOBLIST_H_ */ diff --git a/SecurityTests/clxutils/clAppUtils/CertBuilderApp.cpp b/SecurityTests/clxutils/clAppUtils/CertBuilderApp.cpp new file mode 100644 index 00000000..c3d33060 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/CertBuilderApp.cpp @@ -0,0 +1,376 @@ +/* + * CertBuilderApp.cpp - support for constructing certs, CDSA version + */ + +#include "clutils.h" +#include +#include "CertBuilderApp.h" +#include "timeStr.h" +#include +#include +#include +#include +#include +#include +#include +/* private header */ +#include + +/* + * Build up a CSSM_X509_NAME from an arbitrary list of name/OID pairs. + * We do one a/v pair per RDN. + */ +CSSM_X509_NAME *CB_BuildX509Name( + const CB_NameOid *nameArray, + unsigned numNames) +{ + CSSM_X509_NAME *top = (CSSM_X509_NAME *)appMalloc(sizeof(CSSM_X509_NAME), 0); + if(top == NULL) { + return NULL; + } + top->numberOfRDNs = numNames; + top->RelativeDistinguishedName = + (CSSM_X509_RDN_PTR)appMalloc(sizeof(CSSM_X509_RDN) * numNames, 0); + if(top->RelativeDistinguishedName == NULL) { + return NULL; + } + CSSM_X509_RDN_PTR rdn; + const CB_NameOid *nameOid; + unsigned nameDex; + for(nameDex=0; nameDexRelativeDistinguishedName[nameDex]; + nameOid = &nameArray[nameDex]; + rdn->numberOfPairs = 1; + rdn->AttributeTypeAndValue = (CSSM_X509_TYPE_VALUE_PAIR_PTR) + appMalloc(sizeof(CSSM_X509_TYPE_VALUE_PAIR), 0); + CSSM_X509_TYPE_VALUE_PAIR_PTR atvp = rdn->AttributeTypeAndValue; + if(atvp == NULL) { + return NULL; + } + appCopyCssmData(nameOid->oid, &atvp->type); + atvp->valueType = BER_TAG_PRINTABLE_STRING; + atvp->value.Length = strlen(nameOid->string); + atvp->value.Data = (uint8 *)CSSM_MALLOC(atvp->value.Length); + memmove(atvp->value.Data, nameOid->string, atvp->value.Length); + } + return top; +} + +/* free the CSSM_X509_NAME obtained from CB_BuildX509Name */ +void CB_FreeX509Name( + CSSM_X509_NAME *top) +{ + if(top == NULL) { + return; + } + unsigned nameDex; + CSSM_X509_RDN_PTR rdn; + for(nameDex=0; nameDexnumberOfRDNs; nameDex++) { + rdn = &top->RelativeDistinguishedName[nameDex]; + if(rdn->AttributeTypeAndValue) { + for(unsigned aDex=0; aDexnumberOfPairs; aDex++) { + CSSM_X509_TYPE_VALUE_PAIR_PTR atvp = + &rdn->AttributeTypeAndValue[aDex]; + CSSM_FREE(atvp->type.Data); + CSSM_FREE(atvp->value.Data); + } + CSSM_FREE(rdn->AttributeTypeAndValue); + } + } + CSSM_FREE(top->RelativeDistinguishedName); + CSSM_FREE(top); +} + +/* Obtain a CSSM_X509_TIME representing "now" plus specified seconds, or + * from a preformatted gen time string */ +CSSM_X509_TIME *CB_BuildX509Time( + unsigned secondsFromNow, /* ignored if timeStr non-NULL */ + const char *timeStr) /* optional, from genTimeAtNowPlus */ +{ + CSSM_X509_TIME *xtime = (CSSM_X509_TIME *)appMalloc(sizeof(CSSM_X509_TIME), 0); + if(xtime == NULL) { + return NULL; + } + xtime->timeType = BER_TAG_GENERALIZED_TIME; + char *ts; + if(timeStr == NULL) { + ts = genTimeAtNowPlus(secondsFromNow); + } + else { + ts = (char *)appMalloc(strlen(timeStr) + 1, 0); + strcpy(ts, timeStr); + } + xtime->time.Data = (uint8 *)ts; + xtime->time.Length = strlen(ts); + return xtime; +} + +/* Free CSSM_X509_TIME obtained in CB_BuildX509Time */ +void CB_FreeX509Time( + CSSM_X509_TIME *xtime) +{ + if(xtime == NULL) { + return; + } + freeTimeString((char *)xtime->time.Data); + appFree(xtime, 0); +} + +/* + * Encode an OID as a CSSM_X509_ALGORITHM_IDENTIFIER. + * Returns nonzero on error. + * Returned data is appMallocd's caller must appFree. + */ +int encodeParamOid( + const CSSM_OID *paramOid, + CSSM_DATA *params) +{ + SecAsn1CoderRef coder = NULL; + if(SecAsn1CoderCreate(&coder)) { + printf("***Error in SecAsn1CoderCreate()\n"); + return -1; + } + + CSSM_X509_ALGORITHM_IDENTIFIER algParams; + memset(&algParams, 0, sizeof(algParams)); + algParams.algorithm = *paramOid; + CSSM_DATA encoded = {0, NULL}; + int ourRtn = 0; + if(SecAsn1EncodeItem(coder, &algParams, kSecAsn1AlgorithmIDTemplate, + &encoded)) { + printf("***Error encoding CSSM_X509_ALGORITHM_IDENTIFIER\n"); + ourRtn = -1; + goto errOut; + } + + /* That data is in the coder's memory space: copy ou9t to caller */ + if(appCopyCssmData(&encoded, params)) { + printf("***encodeParamOid malloc failure\n"); + ourRtn = -1; + } +errOut: + SecAsn1CoderRelease(coder); + return ourRtn; +} + +/* + * Cook up an unsigned cert. + * This is just a wrapper for CSSM_CL_CertCreateTemplate(). + */ + +#define ALWAYS_SET_VERSION 0 + +CSSM_DATA_PTR CB_MakeCertTemplate( + /* required */ + CSSM_CL_HANDLE clHand, + uint32 serialNumber, + const CSSM_X509_NAME *issuerName, + const CSSM_X509_NAME *subjectName, + const CSSM_X509_TIME *notBefore, + const CSSM_X509_TIME *notAfter, + const CSSM_KEY_PTR subjectPubKey, + CSSM_ALGORITHMS sigAlg, // e.g., CSSM_ALGID_SHA1WithRSA + /* optional */ + const CSSM_DATA *subjectUniqueId, + const CSSM_DATA *issuerUniqueId, + CSSM_X509_EXTENSION *extensions, + unsigned numExtensions) +{ + CSSM_FIELD *certTemp; + unsigned fieldDex = 0; // index into certTemp + CSSM_DATA_PTR serialDER = NULL; // serial number, DER format + CSSM_DATA_PTR rawCert; // from CSSM_CL_CertCreateTemplate + unsigned version = 0; + CSSM_DATA_PTR versionDER = NULL; + unsigned extNum; + int setVersion = ALWAYS_SET_VERSION; + const CSSM_OID *paramOid = NULL; + + /* convert uint32-style algorithm to the associated struct */ + CSSM_X509_ALGORITHM_IDENTIFIER algId; + switch(sigAlg) { + case CSSM_ALGID_SHA1WithRSA: + algId.algorithm = CSSMOID_SHA1WithRSA; + break; + case CSSM_ALGID_MD5WithRSA: + algId.algorithm = CSSMOID_MD5WithRSA; + break; + case CSSM_ALGID_MD2WithRSA: + algId.algorithm = CSSMOID_MD2WithRSA; + break; + case CSSM_ALGID_FEE_MD5: + algId.algorithm = CSSMOID_APPLE_FEE_MD5; + break; + case CSSM_ALGID_FEE_SHA1: + algId.algorithm = CSSMOID_APPLE_FEE_SHA1; + break; + case CSSM_ALGID_SHA1WithECDSA: + algId.algorithm = CSSMOID_ECDSA_WithSHA1; + break; + case CSSM_ALGID_SHA1WithDSA: + algId.algorithm = CSSMOID_SHA1WithDSA_CMS; + break; + case CSSM_ALGID_SHA224WithRSA: + algId.algorithm = CSSMOID_SHA224WithRSA; + break; + case CSSM_ALGID_SHA256WithRSA: + algId.algorithm = CSSMOID_SHA256WithRSA; + break; + case CSSM_ALGID_SHA384WithRSA: + algId.algorithm = CSSMOID_SHA384WithRSA; + break; + case CSSM_ALGID_SHA512WithRSA: + algId.algorithm = CSSMOID_SHA512WithRSA; + break; + /* These specify the digest algorithm via an additional parameter OID */ + case CSSM_ALGID_SHA224WithECDSA: + algId.algorithm = CSSMOID_ECDSA_WithSpecified; + paramOid = &CSSMOID_SHA224; + break; + case CSSM_ALGID_SHA256WithECDSA: + algId.algorithm = CSSMOID_ECDSA_WithSpecified; + paramOid = &CSSMOID_SHA256; + break; + case CSSM_ALGID_SHA384WithECDSA: + algId.algorithm = CSSMOID_ECDSA_WithSpecified; + paramOid = &CSSMOID_SHA384; + break; + case CSSM_ALGID_SHA512WithECDSA: + algId.algorithm = CSSMOID_ECDSA_WithSpecified; + paramOid = &CSSMOID_SHA512; + break; + default: + printf("CB_MakeCertTemplate: unknown sig alg (%u)\n", (unsigned)sigAlg); + return NULL; + } + if(paramOid != NULL) { + /* not-quite-trivial encoding of digest algorithm */ + if(encodeParamOid(paramOid, &algId.parameters)) { + return NULL; + } + } + else { + algId.parameters.Data = NULL; + algId.parameters.Length = 0; + } + + /* + * version, we infer + * serialNumber thru subjectPubKey + */ + unsigned numFields = 7 + numExtensions; + if(numExtensions) { + version = 2; + } + if(subjectUniqueId) { + numFields++; + if(version == 0) { + version = 1; + } + } + if(issuerUniqueId) { + numFields++; + if(version == 0) { + version = 1; + } + } + if(version > 0) { + setVersion = 1; + } + if(setVersion) { + numFields++; + } + + certTemp = (CSSM_FIELD *)CSSM_MALLOC(sizeof(CSSM_FIELD) * numFields); + + /* version */ + if(setVersion) { + versionDER = intToDER(version); + certTemp[fieldDex].FieldOid = CSSMOID_X509V1Version; + certTemp[fieldDex++].FieldValue = *versionDER; + } + + /* serial number */ + serialDER = intToDER(serialNumber); + certTemp[fieldDex].FieldOid = CSSMOID_X509V1SerialNumber; + certTemp[fieldDex++].FieldValue = *serialDER; + + /* subject and issuer name */ + certTemp[fieldDex].FieldOid = CSSMOID_X509V1IssuerNameCStruct; + certTemp[fieldDex].FieldValue.Data = (uint8 *)issuerName; + certTemp[fieldDex++].FieldValue.Length = sizeof(CSSM_X509_NAME); + + certTemp[fieldDex].FieldOid = CSSMOID_X509V1SubjectNameCStruct; + certTemp[fieldDex].FieldValue.Data = (uint8 *)subjectName; + certTemp[fieldDex++].FieldValue.Length = sizeof(CSSM_X509_NAME); + + /* not before/after */ + certTemp[fieldDex].FieldOid = CSSMOID_X509V1ValidityNotBefore; + certTemp[fieldDex].FieldValue.Data = (uint8 *)notBefore; + certTemp[fieldDex++].FieldValue.Length = sizeof(CSSM_X509_TIME); + + certTemp[fieldDex].FieldOid = CSSMOID_X509V1ValidityNotAfter; + certTemp[fieldDex].FieldValue.Data = (uint8 *)notAfter; + certTemp[fieldDex++].FieldValue.Length = sizeof(CSSM_X509_TIME); + + /* the subject key */ + certTemp[fieldDex].FieldOid = CSSMOID_CSSMKeyStruct; + certTemp[fieldDex].FieldValue.Data = (uint8 *)subjectPubKey; + certTemp[fieldDex++].FieldValue.Length = sizeof(CSSM_KEY); + + /* signature algorithm */ + certTemp[fieldDex].FieldOid = CSSMOID_X509V1SignatureAlgorithmTBS; + certTemp[fieldDex].FieldValue.Data = (uint8 *)&algId; + certTemp[fieldDex++].FieldValue.Length = sizeof(CSSM_X509_ALGORITHM_IDENTIFIER); + + /* subject/issuer unique IDs */ + if(subjectUniqueId != 0) { + certTemp[fieldDex].FieldOid = CSSMOID_X509V1CertificateSubjectUniqueId; + certTemp[fieldDex++].FieldValue = *subjectUniqueId; + } + if(issuerUniqueId != 0) { + certTemp[fieldDex].FieldOid = CSSMOID_X509V1CertificateIssuerUniqueId; + certTemp[fieldDex++].FieldValue = *issuerUniqueId; + } + + for(extNum=0; extNumformat == CSSM_X509_DATAFORMAT_PARSED) { + certTemp[fieldDex].FieldOid = ext->extnId; + } + else { + certTemp[fieldDex].FieldOid = CSSMOID_X509V3CertificateExtensionCStruct; + } + certTemp[fieldDex].FieldValue.Data = (uint8 *)ext; + certTemp[fieldDex++].FieldValue.Length = sizeof(CSSM_X509_EXTENSION); + } + if(fieldDex != numFields) { + printf("CB_MakeCertTemplate numFields screwup\n"); + return NULL; + } + + /* + * OK, here we go + */ + rawCert = (CSSM_DATA_PTR)CSSM_MALLOC(sizeof(CSSM_DATA)); + rawCert->Data = NULL; + rawCert->Length = 0; + CSSM_RETURN crtn = CSSM_CL_CertCreateTemplate(clHand, + fieldDex, + certTemp, + rawCert); + if(crtn) { + printError("CSSM_CL_CertCreateTemplate", crtn); + appFreeCssmData(rawCert, CSSM_TRUE); + rawCert = NULL; + } + + /* free the stuff we mallocd to get here */ + appFreeCssmData(serialDER, CSSM_TRUE); + appFreeCssmData(versionDER, CSSM_TRUE); + CSSM_FREE(certTemp); + if((paramOid != NULL) && (algId.parameters.Data != NULL)) { + CSSM_FREE(algId.parameters.Data); + } + return rawCert; +} diff --git a/SecurityTests/clxutils/clAppUtils/CertBuilderApp.h b/SecurityTests/clxutils/clAppUtils/CertBuilderApp.h new file mode 100644 index 00000000..f02fd109 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/CertBuilderApp.h @@ -0,0 +1,65 @@ +/* + * CertBuilderApp.cpp - support for constructing certs, CDSA version + */ + +#ifndef _CERT_BUILDER_APP_H_ +#define _CERT_BUILDER_APP_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Name/OID pair used in CB_BuildX509Name + */ +typedef struct { + const char *string; + const CSSM_OID *oid; +} CB_NameOid; + +/* + * Build up a CSSM_X509_NAME from an arbitrary list of name/OID pairs. + * We do one a/v pair per RDN. + */ +CSSM_X509_NAME *CB_BuildX509Name( + const CB_NameOid *nameArray, + unsigned numNames); + +/* free the CSSM_X509_NAME obtained from CB_BuildX509Name */ +void CB_FreeX509Name( + CSSM_X509_NAME *top); + +/* Obtain a CSSM_X509_TIME representing "now" plus specified seconds, or +* from a preformatted gen time string */ +CSSM_X509_TIME *CB_BuildX509Time( + unsigned secondsFromNow, /* ignored if timeStr non-NULL */ + const char *timeStr=NULL); /* optional, from genTimeAtNowPlus */ + +/* Free CSSM_X509_TIME obtained in CB_BuildX509Time */ +void CB_FreeX509Time( + CSSM_X509_TIME *xtime); + +CSSM_DATA_PTR CB_MakeCertTemplate( + /* required */ + CSSM_CL_HANDLE clHand, + uint32 serialNumber, + const CSSM_X509_NAME *issuerName, + const CSSM_X509_NAME *subjectName, + const CSSM_X509_TIME *notBefore, + const CSSM_X509_TIME *notAfter, + const CSSM_KEY_PTR subjectPubKey, + CSSM_ALGORITHMS sigAlg, // e.g., CSSM_ALGID_SHA1WithRSA + /* optional */ + const CSSM_DATA *subjectUniqueId, + const CSSM_DATA *issuerUniqueId, + CSSM_X509_EXTENSION *extensions, + unsigned numExtensions); + +#ifdef __cplusplus +} +#endif +#endif /* _CERT_BUILDER_APP_H_ */ diff --git a/SecurityTests/clxutils/clAppUtils/CertParser.cpp b/SecurityTests/clxutils/clAppUtils/CertParser.cpp new file mode 100644 index 00000000..ca46f8aa --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/CertParser.cpp @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2003-2005 Apple Computer, Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please + * obtain a copy of the License at http://www.apple.com/publicsource and + * read it before using this file. + * + * This 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. + */ + +/* + * CertParser.h - cert parser with autorelease of fetched fields + * + * Created 24 October 2003 by Doug Mitchell + */ + +#include "CertParser.h" +#import + +#define CP_DEBUG 1 +#if CP_DEBUG +#define dprintf(args...) printf(args) +#else +#define dprintf(args...) +#endif + +#pragma mark --- CP_FetchedField --- + +class CP_FetchedField +{ +public: + /* construct one fetched field (which will be stored in CertParser's + * mFetchedFields) */ + CP_FetchedField( + const CSSM_OID &fieldOid, + CSSM_DATA_PTR fieldData, + CSSM_CL_HANDLE clHand); + + /* Free the field via CL */ + ~CP_FetchedField(); +private: + CSSM_OID mFieldOid; + CSSM_DATA_PTR mFieldData; + CSSM_CL_HANDLE mClHand; +}; + +CP_FetchedField::CP_FetchedField( + const CSSM_OID &fieldOid, + CSSM_DATA_PTR fieldData, + CSSM_CL_HANDLE clHand) + : mFieldOid(fieldOid), mFieldData(fieldData), mClHand(clHand) +{ +} + +/* Free the field via CL */ +CP_FetchedField::~CP_FetchedField() +{ + CSSM_CL_FreeFieldValue(mClHand, &mFieldOid, mFieldData); +} + +#pragma mark --- CertParser implementation --- + +/* Construct with or without data - you can add the data later with + * initWithData() to parse without exceptions */ +CertParser::CertParser() +{ + initFields(); +} + +CertParser::CertParser( + CSSM_CL_HANDLE clHand) +{ + initFields(); + mClHand = clHand; +} + +CertParser::CertParser( + CSSM_CL_HANDLE clHand, + const CSSM_DATA &certData) +{ + initFields(); + mClHand = clHand; + CSSM_RETURN crtn = initWithData(certData); + if(crtn) { + throw ((int)crtn); + } +} + +CertParser::CertParser( + SecCertificateRef secCert) +{ + initFields(); + OSStatus ortn = initWithSecCert(secCert); + if(ortn) { + throw ((int)ortn); + } +} + +/* frees all the fields we fetched */ +CertParser::~CertParser() +{ + if(mClHand && mCacheHand) { + CSSM_RETURN crtn = CSSM_CL_CertAbortCache(mClHand, mCacheHand); + if(crtn) { + /* almost certainly a bug */ + printf("Internal Error: CertParser error on free."); + cssmPerror("CSSM_CL_CertAbortCache", crtn); + } + } + vector::iterator iter; + for(iter=mFetchedFields.begin(); iter!=mFetchedFields.end(); iter++) { + delete *iter; + } +} + +/* common init for all constructors */ +void CertParser::initFields() +{ + mClHand = 0; + mCacheHand = 0; +} + +/*** NO MORE EXCEPTIONS ***/ + +/* + * No cert- or CDSA-related exceptions thrown by remainder. + * This is the core initializer: have the CL parse and cache the cert. + */ +CSSM_RETURN CertParser::initWithData( + const CSSM_DATA &certData) +{ + assert(mClHand != 0); + CSSM_RETURN crtn = CSSM_CL_CertCache(mClHand, &certData, &mCacheHand); + #if CP_DEBUG + if(crtn) { + cssmPerror("CSSM_CL_CertCache", crtn); + } + #endif + return crtn; +} + +OSStatus CertParser::initWithSecCert( + SecCertificateRef secCert) +{ + OSStatus ortn; + CSSM_DATA certData; + + assert(mClHand == 0); + ortn = SecCertificateGetCLHandle(secCert, &mClHand); + if(ortn) { + return ortn; + } + ortn = SecCertificateGetData(secCert, &certData); + if(ortn) { + return ortn; + } + return (OSStatus)initWithData(certData); +} + +CSSM_RETURN CertParser::initWithCFData( + CFDataRef cfData) +{ + CSSM_DATA cdata; + + cdata.Data = (uint8 *)CFDataGetBytePtr(cfData); + cdata.Length = CFDataGetLength(cfData); + return initWithData(cdata); +} + +/* + * Obtain atrbitrary field from cached cert. This class takes care of freeing + * the field in its destructor. + * + * Returns NULL if field not found (not exception). + * + * Caller optionally specifies field length to check - specifying zero means + * "don't care, don't check". Actual field length always returned in fieldLength. + */ +const void *CertParser::fieldForOid( + const CSSM_OID &oid, + CSSM_SIZE &fieldLength) // IN/OUT +{ + CSSM_RETURN crtn; + + uint32 NumberOfFields = 0; + CSSM_HANDLE resultHand = 0; + CSSM_DATA_PTR fieldData = NULL; + + assert(mClHand != 0); + assert(mCacheHand != 0); + crtn = CSSM_CL_CertGetFirstCachedFieldValue( + mClHand, + mCacheHand, + &oid, + &resultHand, + &NumberOfFields, + &fieldData); + if(crtn) { + /* not an error; just means that the cert doesn't have this field */ + return NULL; + } + assert(NumberOfFields == 1); + CSSM_CL_CertAbortQuery(mClHand, resultHand); + + if(fieldLength) { + if(fieldLength != fieldData->Length) { + /* FIXME what's a good way to log in this situation? */ + printf("***CertParser::fieldForOid: field length mismatch\n"); + return NULL; + } + } + /* Store the OID and the field for autorelease */ + CP_FetchedField *cpField = new CP_FetchedField(oid, fieldData, mClHand); + mFetchedFields.push_back(cpField); + fieldLength = fieldData->Length; + return fieldData->Data; +} + +/* + * Conveneince routine to fetch an extension we "know" the CL can parse. + * The return value gets cast to one of the CE_Data types. + */ +const void *CertParser::extensionForOid( + const CSSM_OID &oid) +{ + CSSM_SIZE len = sizeof(CSSM_X509_EXTENSION); + CSSM_X509_EXTENSION *cssmExt = + (CSSM_X509_EXTENSION *)fieldForOid(oid, len); + if(cssmExt) { + if(cssmExt->format != CSSM_X509_DATAFORMAT_PARSED) { + printf("***Badly formatted extension"); + return NULL; + } + return cssmExt->value.parsedValue; + } + else { + return NULL; + } +} + diff --git a/SecurityTests/clxutils/clAppUtils/CertParser.h b/SecurityTests/clxutils/clAppUtils/CertParser.h new file mode 100644 index 00000000..0bc6fef2 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/CertParser.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2003-2005 Apple Computer, Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please + * obtain a copy of the License at http://www.apple.com/publicsource and + * read it before using this file. + * + * This 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. + */ + +/* + * CertParser.h - cert parser with autorelease of fetched fields + * + * Created 24 October 2003 by Doug Mitchell + */ + +#ifndef _CERT_PARSER_H_ +#define _CERT_PARSER_H_ + +#include +#include + +using std::vector; + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * We store an vector<> of these as an "autorelease" pool of fetched fields. + */ +class CP_FetchedField; + +class CertParser +{ +public: + /* + * Construct with or without data - you can add the data later with + * initWithData() to parse without exceptions + */ + + CertParser(); // must be used with initWithSecCert to get clHand + CertParser( // use with initWithData + CSSM_CL_HANDLE clHand); + CertParser( + CSSM_CL_HANDLE clHand, + const CSSM_DATA &certData); + CertParser( + SecCertificateRef secCert); + + /* frees all the fields we fetched */ + ~CertParser(); + + /* + * No cert- or CDSA-related exceptions thrown by remainder + */ + CSSM_RETURN initWithData( + const CSSM_DATA &certData); + OSStatus initWithSecCert( + SecCertificateRef secCert); + CSSM_RETURN initWithCFData( + CFDataRef cfData); + + /* + * Obtain atrbitrary field from cached cert. This class takes care of freeing + * the field in its destructor. + * + * Returns NULL if field not found (not exception). + * + * Caller optionally specifies field length to check - specifying zero means + * "don't care, don't check". Actual field length always returned in fieldLength. + */ + const void *fieldForOid( + const CSSM_OID &oid, + CSSM_SIZE &fieldLength); // IN/OUT + + /* + * Conveneince routine to fetch an extension we "know" the CL can parse. + * The return value gets cast to one of the CE_Data types. + */ + const void *extensionForOid( + const CSSM_OID &oid); + +private: + void initFields(); + + CSSM_CL_HANDLE mClHand; + CSSM_HANDLE mCacheHand; // the parsed & cached cert + vector mFetchedFields; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _CERT_PARSER_H_ */ + diff --git a/SecurityTests/clxutils/clAppUtils/Makefile b/SecurityTests/clxutils/clAppUtils/Makefile new file mode 100644 index 00000000..84d858d6 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/Makefile @@ -0,0 +1,62 @@ +# name of executable to build +EXECUTABLE=libclutils.a +# C++ source (with .cpp extension) +CPSOURCE= BlobList.cpp CertBuilderApp.cpp CertParser.cpp \ + certVerify.cpp identPicker.cpp keyPicker.cpp printCertName.cpp \ + ringBufferIo.cpp sslRingBufferThreads.cpp sslServe.cpp sslClient.cpp \ + sslAppUtils.cpp timeStr.cpp tpUtils.cpp + + +# C source (.c extension) +CSOURCE= clutils.c ioSock.c + +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= -fvisibility=hidden + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.lib + +# some crucial dependencies that must cause recompilation +THREAD_OBJS= $(OBJROOT)/sslAppUtils.o $(OBJROOT)/sslClient.o $(OBJROOT)/sslServe.o + +$(THREAD_OBJS): sslThreading.h + +$(OBJROOT)/certVerify.o: certVerify.h + diff --git a/SecurityTests/clxutils/clAppUtils/certVerify.cpp b/SecurityTests/clxutils/clAppUtils/certVerify.cpp new file mode 100644 index 00000000..40954256 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/certVerify.cpp @@ -0,0 +1,692 @@ +/* + * certVerify.cpp - execute cert/CRL verify; display results + */ + +#include "certVerify.h" +#include "tpUtils.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int vfyCertErrors( + const CSSM_TP_VERIFY_CONTEXT_RESULT *vfyResult, + unsigned numCertErrors, + const char **certErrors, // e.g., "2:CSSMERR_TP_CERT_EXPIRED" + CSSM_BOOL quiet) +{ + if(numCertErrors == 0) { + return 0; + } + if(vfyResult->NumberOfEvidences != 3) { + printf("***vfyCertErrors: NumberOfEvidences is %u, expect 3\n", + (unsigned)vfyResult->NumberOfEvidences); + return 1; + } + + /* numCerts from evidence[1] */ + const CSSM_EVIDENCE *ev = &vfyResult->Evidence[1]; + const CSSM_CERTGROUP *grp = (const CSSM_CERTGROUP *)ev->Evidence; + unsigned numCerts = grp->NumCerts; + /* array of Apple-specific info from evidence[2] */ + ev = &vfyResult->Evidence[2]; + const CSSM_TP_APPLE_EVIDENCE_INFO *info = + (const CSSM_TP_APPLE_EVIDENCE_INFO *)ev->Evidence; + int ourRtn = 0; + + for(unsigned dex=0; dex (numCerts-1)) { + printf("***certerror specified for cert %u, but only %u certs" + " available\n", certNum, numCerts); + return 1; + } + str++; // pts to actual desired error string now + + /* + * There may be multiple per-cert statuses in the evidence; search all + * looking for a match + */ + const CSSM_TP_APPLE_EVIDENCE_INFO *thisInfo = &info[certNum]; + char *found = NULL; + for(unsigned i=0; iNumStatusCodes; i++) { + CSSM_RETURN actRtn = thisInfo->StatusCodes[i]; + const char *actRtnStr = cssmErrToStr(actRtn); + found = strstr(actRtnStr, str); + if(found) { + break; + } + } + if(found) { + if(!quiet) { + printf("...%s per-cert status received as expected\n", str); + } + } + else { + printf("***Per cert status %s not found\n", str); + ourRtn = 1; + /* might as well keep going */ + } + } + return ourRtn; +} + +static int vfyCertStatus( + const CSSM_TP_VERIFY_CONTEXT_RESULT *vfyResult, + unsigned numCertStatus, + const char **certStatus, // e.g., "1:0x18", leading 0x optional + CSSM_BOOL quiet) +{ + if(numCertStatus == 0) { + return 0; + } + if(vfyResult->NumberOfEvidences != 3) { + printf("***vfyCertStatus: NumberOfEvidences is %u, expect 3\n", + (unsigned)vfyResult->NumberOfEvidences); + return 1; + } + + /* numCerts from evidence[1] */ + const CSSM_EVIDENCE *ev = &vfyResult->Evidence[1]; + const CSSM_CERTGROUP *grp = (const CSSM_CERTGROUP *)ev->Evidence; + unsigned numCerts = grp->NumCerts; + /* array of Apple-specific info from evidence[2] */ + ev = &vfyResult->Evidence[2]; + const CSSM_TP_APPLE_EVIDENCE_INFO *info = + (const CSSM_TP_APPLE_EVIDENCE_INFO *)ev->Evidence; + int ourRtn = 0; + + for(unsigned dex=0; dex (numCerts-1)) { + printf("***certerror specified for cert %u, but only %u certs" + " available\n", certNum, numCerts); + return 1; + } + str++; // pts to actual desired status string now + unsigned certStat = hexToBin(str); + const CSSM_TP_APPLE_EVIDENCE_INFO *thisInfo = &info[certNum]; + if(certStat == thisInfo->StatusBits) { + if(!quiet) { + printf("...0x%x per-cert status received as expected\n", certStat); + } + } + else { + printf("***Expected per cert status 0x%x, got 0x%x\n", + (unsigned)certStat, (unsigned)thisInfo->StatusBits); + ourRtn = 1; + } + } + return ourRtn; +} + +/* + * Ensure that the policy being evaluated is accessible via + * SecPolicySearch*(). Not really part of the test, but a handy place + * to catch this common error before checking in TP changes. + */ +static int verifySecPolicy( + const CSSM_OID *oid) +{ + SecPolicySearchRef srchRef = NULL; + OSStatus ortn; + + ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3, oid, NULL, &srchRef); + if(ortn) { + cssmPerror("SecPolicySearchCreate", ortn); + return -1; + } + SecPolicyRef policyRef = NULL; + ortn = SecPolicySearchCopyNext(srchRef, &policyRef); + if(ortn) { + cssmPerror("SecPolicySearchCopyNext", ortn); + printf("***The TP policy used in this test is not accessible via SecPolicySearchCopyNext().\n"); + printf(" You probably forgot to add the policy to the theOidList table in PolicyCursor.cpp\n"); + printf(" in the libsecurity_keychain project.\n"); + } + CFRelease(srchRef); + if(policyRef) { + CFRelease(policyRef); + } + return ortn; +} + +int certVerify(CertVerifyArgs *vfyArgs) +{ + if(vfyArgs->version != CERT_VFY_ARGS_VERS) { + printf("***CertVerifyArgs.Version mismatch. Clean and rebuild.\n"); + return -1; + } + + /* main job is building a CSSM_TP_VERIFY_CONTEXT and its components */ + CSSM_TP_VERIFY_CONTEXT vfyCtx; + CSSM_TP_CALLERAUTH_CONTEXT authCtx; + CSSM_TP_VERIFY_CONTEXT_RESULT vfyResult; + CSSM_APPLE_TP_SSL_OPTIONS sslOpts; + CSSM_APPLE_TP_SMIME_OPTIONS smimeOpts; + + memset(&vfyCtx, 0, sizeof(CSSM_TP_VERIFY_CONTEXT)); + memset(&authCtx, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT)); + + /* CSSM_TP_CALLERAUTH_CONTEXT components */ + /* + typedef struct cssm_tp_callerauth_context { + CSSM_TP_POLICYINFO Policy; + CSSM_TIMESTRING VerifyTime; + CSSM_TP_STOP_ON VerificationAbortOn; + CSSM_TP_VERIFICATION_RESULTS_CALLBACK CallbackWithVerifiedCert; + uint32 NumberOfAnchorCerts; + CSSM_DATA_PTR AnchorCerts; + CSSM_DL_DB_LIST_PTR DBList; + CSSM_ACCESS_CREDENTIALS_PTR CallerCredentials; + } CSSM_TP_CALLERAUTH_CONTEXT, *CSSM_TP_CALLERAUTH_CONTEXT_PTR; + */ + /* up to 3 policies */ + CSSM_FIELD policyIds[3]; + CSSM_FIELD *policyPtr = &policyIds[0]; + uint32 numPolicies = 0; + memset(policyIds, 0, 3 * sizeof(CSSM_FIELD)); + + switch(vfyArgs->vfyPolicy) { + case CVP_SSL: + case CVP_IPSec: + if(vfyArgs->vfyPolicy == CVP_SSL) { + policyPtr->FieldOid = CSSMOID_APPLE_TP_SSL; + } + else { + policyPtr->FieldOid = CSSMOID_APPLE_TP_IP_SEC; + } + /* otherwise these policies are identical */ + /* sslOpts is optional */ + if((vfyArgs->sslHost != NULL) || vfyArgs->sslClient) { + memset(&sslOpts, 0, sizeof(sslOpts)); + sslOpts.Version = CSSM_APPLE_TP_SSL_OPTS_VERSION; + sslOpts.ServerName = vfyArgs->sslHost; + if(vfyArgs->sslHost != NULL) { + sslOpts.ServerNameLen = strlen(vfyArgs->sslHost) + 1; + } + if(vfyArgs->sslClient) { + sslOpts.Flags |= CSSM_APPLE_TP_SSL_CLIENT; + } + policyPtr->FieldValue.Data = (uint8 *)&sslOpts; + policyPtr->FieldValue.Length = sizeof(sslOpts); + } + break; + case CVP_SMIME: + case CVP_iChat: + if(vfyArgs->vfyPolicy == CVP_SMIME) { + policyPtr->FieldOid = CSSMOID_APPLE_TP_SMIME; + } + else { + policyPtr->FieldOid = CSSMOID_APPLE_TP_ICHAT; + } + /* otherwise these policies are identical */ + /* smimeOpts is optional */ + if(vfyArgs->senderEmail != NULL) { + smimeOpts.Version = CSSM_APPLE_TP_SMIME_OPTS_VERSION; + smimeOpts.IntendedUsage = vfyArgs->intendedKeyUse; + smimeOpts.SenderEmail = vfyArgs->senderEmail; + smimeOpts.SenderEmailLen = strlen(vfyArgs->senderEmail) + 1; + policyPtr->FieldValue.Data = (uint8 *)&smimeOpts; + policyPtr->FieldValue.Length = sizeof(smimeOpts); + } + break; + case CVP_Basic: + policyPtr->FieldOid = CSSMOID_APPLE_X509_BASIC; + break; + case CVP_SWUpdateSign: + /* no options */ + policyPtr->FieldOid = CSSMOID_APPLE_TP_SW_UPDATE_SIGNING; + break; + case CVP_ResourceSigning: + /* no options */ + policyPtr->FieldOid = CSSMOID_APPLE_TP_RESOURCE_SIGN; + break; + case CVP_PKINIT_Server: + /* no options */ + policyPtr->FieldOid = CSSMOID_APPLE_TP_PKINIT_SERVER; + break; + case CVP_PKINIT_Client: + /* no options */ + policyPtr->FieldOid = CSSMOID_APPLE_TP_PKINIT_CLIENT; + break; + case CVP_AppleCodeSigning: + /* no options */ + policyPtr->FieldOid = CSSMOID_APPLE_TP_CODE_SIGNING; + break; + case CVP_PackageSigning: + /* no options */ + policyPtr->FieldOid = CSSMOID_APPLE_TP_PACKAGE_SIGNING; + break; + default: + printf("***certVerify: bogus vfyPolicy\n"); + return 1; + } + if(verifySecPolicy(&policyPtr->FieldOid)) { + return -1; + } + policyPtr++; + numPolicies++; + + CSSM_APPLE_TP_CRL_OPTIONS crlOpts; + if((vfyArgs->revokePolicy == CRP_CRL) || (vfyArgs->revokePolicy == CRP_CRL_OCSP)) { + memset(&crlOpts, 0, sizeof(crlOpts)); + policyPtr->FieldOid = CSSMOID_APPLE_TP_REVOCATION_CRL; + + crlOpts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION; + crlOpts.CrlFlags = 0; + crlOpts.crlStore = NULL; + policyPtr->FieldValue.Data = (uint8 *)&crlOpts; + policyPtr->FieldValue.Length = sizeof(crlOpts); + if(vfyArgs->requireCrlForAll) { + crlOpts.CrlFlags |= CSSM_TP_ACTION_REQUIRE_CRL_PER_CERT; + } + if(vfyArgs->crlNetFetchEnable) { + crlOpts.CrlFlags |= CSSM_TP_ACTION_FETCH_CRL_FROM_NET; + } + if(vfyArgs->requireCrlIfPresent) { + crlOpts.CrlFlags |= CSSM_TP_ACTION_REQUIRE_CRL_IF_PRESENT; + } + crlOpts.crlStore = vfyArgs->crlDlDb; + policyPtr++; + numPolicies++; + } + + CSSM_APPLE_TP_OCSP_OPTIONS ocspOpts; + CSSM_DATA respUriData; + CSSM_DATA respCertData = {vfyArgs->responderCertLen, + (uint8 *)vfyArgs->responderCert}; + if((vfyArgs->revokePolicy == CRP_OCSP) || (vfyArgs->revokePolicy == CRP_CRL_OCSP)) { + memset(&ocspOpts, 0, sizeof(ocspOpts)); + policyPtr->FieldOid = CSSMOID_APPLE_TP_REVOCATION_OCSP; + + crlOpts.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION; + policyPtr->FieldValue.Data = (uint8 *)&ocspOpts; + policyPtr->FieldValue.Length = sizeof(ocspOpts); + if(vfyArgs->requireOcspForAll) { + ocspOpts.Flags |= CSSM_TP_ACTION_OCSP_REQUIRE_PER_CERT; + } + if(vfyArgs->requireOcspIfPresent) { + ocspOpts.Flags |= CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT; + } + if(vfyArgs->disableCache) { + ocspOpts.Flags |= (CSSM_TP_ACTION_OCSP_CACHE_READ_DISABLE | + CSSM_TP_ACTION_OCSP_CACHE_WRITE_DISABLE); + } + if(vfyArgs->disableOcspNet) { + ocspOpts.Flags |= CSSM_TP_ACTION_OCSP_DISABLE_NET; + } + if(vfyArgs->generateOcspNonce) { + ocspOpts.Flags |= CSSM_TP_OCSP_GEN_NONCE; + } + if(vfyArgs->requireOcspRespNonce) { + ocspOpts.Flags |= CSSM_TP_OCSP_REQUIRE_RESP_NONCE; + } + if(vfyArgs->responderURI != NULL) { + respUriData.Data = (uint8 *)vfyArgs->responderURI; + respUriData.Length = strlen(vfyArgs->responderURI); + ocspOpts.LocalResponder = &respUriData; + } + if(vfyArgs->responderCert != NULL) { + ocspOpts.LocalResponderCert = &respCertData; + } + /* other OCSP options here */ + policyPtr++; + numPolicies++; + } + + authCtx.Policy.NumberOfPolicyIds = numPolicies; + + authCtx.Policy.PolicyIds = policyIds; + authCtx.Policy.PolicyControl = NULL; + + authCtx.VerifyTime = vfyArgs->vfyTime; // may be NULL + authCtx.VerificationAbortOn = CSSM_TP_STOP_ON_POLICY; + authCtx.CallbackWithVerifiedCert = NULL; + + /* + * DLDBs - the caller's optional set, plus two more we open + * if trust settings are enabled and we're told to use system + * anchors. (System anchors are normally passed in via + * authCtx.AnchorCerts; they're passed in as DLDBs when + * using TrustSettings.) + */ + uint32 totalNumDbs = 0; + uint32 numCallerDbs = 0; + CSSM_BOOL weOpenedDbs = CSSM_FALSE; + if(vfyArgs->dlDbList != NULL) { + totalNumDbs = numCallerDbs = vfyArgs->dlDbList->NumHandles; + } + if(vfyArgs->useTrustSettings && vfyArgs->useSystemAnchors) { + /* we'll cook up two more DBs and possible append them */ + totalNumDbs += 2; + weOpenedDbs = CSSM_TRUE; + } + CSSM_DL_DB_HANDLE dlDbHandles[totalNumDbs]; + CSSM_DL_DB_LIST dlDbList; + CSSM_DL_HANDLE dlHand = 0; + for(unsigned dex=0; dexdlDbList->DLDBHandle[dex]; + } + if(weOpenedDbs) { + /* get a DL handle, somehow */ + if(numCallerDbs == 0) { + /* new DL handle */ + dlHand = cuDlStartup(); + dlDbHandles[0].DLHandle = dlHand; + dlDbHandles[1].DLHandle = dlHand; + } + else { + /* use the same one caller passed in */ + dlDbHandles[numCallerDbs].DLHandle = dlDbHandles[0].DLHandle; + dlDbHandles[numCallerDbs + 1].DLHandle = dlDbHandles[0].DLHandle; + } + /* now open two DBs */ + dlDbHandles[numCallerDbs].DBHandle = + cuDbStartupByName(dlDbHandles[numCallerDbs].DLHandle, + (char *)ADMIN_CERT_STORE_PATH, CSSM_FALSE, CSSM_TRUE); + dlDbHandles[numCallerDbs + 1].DBHandle = + cuDbStartupByName(dlDbHandles[numCallerDbs].DLHandle, + (char *)SYSTEM_ROOT_STORE_PATH, CSSM_FALSE, CSSM_TRUE); + } + dlDbList.DLDBHandle = dlDbHandles; + dlDbList.NumHandles = totalNumDbs; + authCtx.DBList = &dlDbList; + + CFArrayRef cfAnchors = NULL; + CSSM_DATA *cssmAnchors = NULL; + unsigned numAnchors = 0; + + if(vfyArgs->useSystemAnchors) { + if(!vfyArgs->useTrustSettings) { + /* standard system anchors - ingore error, I'm sure the + * current test will eventually fail */ + getSystemAnchors(&cfAnchors, &cssmAnchors, &numAnchors); + authCtx.NumberOfAnchorCerts = numAnchors; + authCtx.AnchorCerts = cssmAnchors; + } + } + else { + /* anchors are our caller's roots */ + if(vfyArgs->roots) { + authCtx.NumberOfAnchorCerts = vfyArgs->roots->numBlobs(); + authCtx.AnchorCerts = vfyArgs->roots->blobList(); + } + } + authCtx.CallerCredentials = NULL; + + if(vfyArgs->crls) { + /* cook up CRL group */ + CSSM_CRLGROUP_PTR cssmCrls = &vfyCtx.Crls; + cssmCrls->CrlType = CSSM_CRL_TYPE_X_509v1; + cssmCrls->CrlEncoding = CSSM_CRL_ENCODING_DER; + cssmCrls->NumberOfCrls = vfyArgs->crls->numBlobs(); + cssmCrls->GroupCrlList.CrlList = vfyArgs->crls->blobList(); + cssmCrls->CrlGroupType = CSSM_CRLGROUP_DATA; + } + + /* CSSM_APPLE_TP_ACTION_DATA */ + CSSM_APPLE_TP_ACTION_DATA tpAction; + tpAction.Version = CSSM_APPLE_TP_ACTION_VERSION; + tpAction.ActionFlags = 0; + if(vfyArgs->leafCertIsCA) { + tpAction.ActionFlags |= CSSM_TP_ACTION_LEAF_IS_CA; + } + if(vfyArgs->certNetFetchEnable) { + tpAction.ActionFlags |= CSSM_TP_ACTION_FETCH_CERT_FROM_NET; + } + if(vfyArgs->allowExpiredRoot) { + tpAction.ActionFlags |= CSSM_TP_ACTION_ALLOW_EXPIRED_ROOT; + } + if(!vfyArgs->allowUnverified) { + tpAction.ActionFlags |= CSSM_TP_ACTION_REQUIRE_REV_PER_CERT; + } + if(vfyArgs->useTrustSettings) { + tpAction.ActionFlags |= CSSM_TP_ACTION_TRUST_SETTINGS; + } + if(vfyArgs->implicitAnchors) { + tpAction.ActionFlags |= CSSM_TP_ACTION_IMPLICIT_ANCHORS; + } + + /* CSSM_TP_VERIFY_CONTEXT */ + vfyCtx.ActionData.Data = (uint8 *)&tpAction; + vfyCtx.ActionData.Length = sizeof(tpAction); + + vfyCtx.Action = CSSM_TP_ACTION_DEFAULT; + vfyCtx.Cred = &authCtx; + + /* cook up cert group */ + CSSM_CERTGROUP cssmCerts; + cssmCerts.CertType = CSSM_CERT_X_509v3; + cssmCerts.CertEncoding = CSSM_CERT_ENCODING_DER; + cssmCerts.NumCerts = vfyArgs->certs->numBlobs(); + cssmCerts.GroupList.CertList = vfyArgs->certs->blobList(); + cssmCerts.CertGroupType = CSSM_CERTGROUP_DATA; + + int ourRtn = 0; + CSSM_RETURN crtn = CSSM_TP_CertGroupVerify(vfyArgs->tpHand, + vfyArgs->clHand, + vfyArgs->cspHand, + &cssmCerts, + &vfyCtx, + &vfyResult); + if(vfyArgs->expectedErrStr != NULL) { + const char *actRtn; + if(crtn == CSSM_OK) { + /* cssmErrorString munges this to "[ok]" */ + actRtn = "CSSM_OK"; + } + else { + actRtn = cssmErrToStr(crtn); + } + char *found = strstr(actRtn, vfyArgs->expectedErrStr); + if(found) { + if(!vfyArgs->quiet) { + printf("...%s received as expected\n", vfyArgs->expectedErrStr); + } + } + else { + printf("***CSSM_TP_CertGroupVerify error\n"); + printf(" expected rtn : %s\n", vfyArgs->expectedErrStr); + printf(" actual rtn : %s\n", actRtn); + ourRtn = 1; + } + } + else { + if(crtn) { + if(!vfyArgs->quiet) { + printError("CSSM_TP_CertGroupVerify", crtn); + } + ourRtn = 1; + } + else if(!vfyArgs->quiet) { + printf("...verify successful\n"); + } + } + if(vfyArgs->certErrors) { + if(vfyCertErrors(&vfyResult, vfyArgs->numCertErrors, vfyArgs->certErrors, + vfyArgs->quiet)) { + ourRtn = 1; + } + } + if(vfyArgs->certStatus) { + if(vfyCertStatus(&vfyResult, vfyArgs->numCertStatus, vfyArgs->certStatus, + vfyArgs->quiet)) { + ourRtn = 1; + } + } + if(vfyArgs->verbose) { + dumpVfyResult(&vfyResult); + } + freeVfyResult(&vfyResult); + if(weOpenedDbs) { + /* close the DBs and maybe the DL we opened */ + CSSM_DL_DbClose(dlDbHandles[numCallerDbs]); + CSSM_DL_DbClose(dlDbHandles[numCallerDbs + 1]); + if(dlHand != 0) { + cuDlDetachUnload(dlHand); + } + } + if(cfAnchors) { + CFRelease(cfAnchors); + } + if(cssmAnchors) { + free(cssmAnchors); + } + return ourRtn; +} + +unsigned hexDigit(char digit) +{ + if((digit >= '0') && (digit <= '9')) { + return digit - '0'; + } + if((digit >= 'a') && (digit <= 'f')) { + return 10 + digit - 'a'; + } + if((digit >= 'A') && (digit <= 'F')) { + return 10 + digit - 'A'; + } + printf("***BAD HEX DIGIT (%c)\n", digit); + return 0; +} + +/* convert ASCII string in hex to unsigned */ +unsigned hexToBin(const char *hex) +{ + unsigned rtn = 0; + const char *cp = hex; + if((cp[0] == '0') && (cp[1] == 'x')) { + cp += 2; + } + if(strlen(cp) > 8) { + printf("***BAD HEX STRING (%s)\n", cp); + return 0; + } + while(*cp) { + rtn <<= 4; + rtn += hexDigit(*cp); + cp++; + } + return rtn; +} + +/* + * A slightly simplified version of certVerify: + * -- no CRLs (includes allowUnverified = CSSM_FALSE) + * -- revokePOlicy = None + * -- no DlDbs + * -- no net fetch + * -- time = now. + */ +int certVerifySimple( + CSSM_TP_HANDLE tpHand, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + BlobList &certs, + BlobList &roots, + CSSM_BOOL useSystemAnchors, + CSSM_BOOL leafCertIsCA, + CSSM_BOOL allowExpiredRoot, + CertVerifyPolicy vfyPolicy, + const char *sslHost, // optional, SSL policy + CSSM_BOOL sslClient, // normally server side + const char *senderEmail, // optional, SMIME + CE_KeyUsage intendedKeyUse, // optional, SMIME only + const char *expectedErrStr,// e.g., + // "CSSMERR_APPLETP_CRL_NOT_TRUSTED" + + /* + * expected per-cert errors + * format is certNum:errorString + * e.g., "1:CSSMERR_APPLETP_CRL_NOT_TRUSTED" + */ + unsigned numCertErrors, + const char **certErrors, // per-cert status + + /* + * Expected per-cert status (CSSM_TP_APPLE_EVIDENCE_INFO.StatusBits) + * format is certNum:status_in_hex + * e.g., "1:0x18", leading 0x optional + */ + unsigned numCertStatus, + const char **certStatus, + CSSM_BOOL useTrustSettings, + CSSM_BOOL quiet, + CSSM_BOOL verbose) +{ + CertVerifyArgs vfyArgs; + memset(&vfyArgs, 0, sizeof(vfyArgs)); + vfyArgs.version = CERT_VFY_ARGS_VERS; + vfyArgs.tpHand = tpHand; + vfyArgs.clHand = clHand; + vfyArgs.cspHand = cspHand; + vfyArgs.certs = &certs; + vfyArgs.roots = &roots; + vfyArgs.useSystemAnchors = useSystemAnchors; + vfyArgs.useTrustSettings = useTrustSettings; + vfyArgs.leafCertIsCA = leafCertIsCA; + vfyArgs.allowExpiredRoot = allowExpiredRoot; + vfyArgs.vfyPolicy = vfyPolicy; + vfyArgs.sslHost = sslHost; + vfyArgs.sslClient = sslClient; + vfyArgs.senderEmail = senderEmail; + vfyArgs.intendedKeyUse = intendedKeyUse; + vfyArgs.allowUnverified = CSSM_TRUE; + vfyArgs.expectedErrStr = expectedErrStr; + vfyArgs.numCertErrors = numCertErrors; + vfyArgs.certErrors = certErrors; + vfyArgs.numCertStatus = numCertStatus; + vfyArgs.certStatus = certStatus; + vfyArgs.quiet = quiet; + vfyArgs.verbose = verbose; + return certVerify(&vfyArgs); +} + diff --git a/SecurityTests/clxutils/clAppUtils/certVerify.h b/SecurityTests/clxutils/clAppUtils/certVerify.h new file mode 100644 index 00000000..7e047acc --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/certVerify.h @@ -0,0 +1,148 @@ +#ifndef _CERT_VERIFY_H_ +#define _CERT_VERIFY_H_ + +#include +#include +#include + +/* must be C++ since we use BlobList */ +extern "C" { + +/* Display verify results */ +void dumpVfyResult( + const CSSM_TP_VERIFY_CONTEXT_RESULT *vfyResult); + +typedef enum { + CVP_Basic = 0, + CVP_SSL, + CVP_SMIME, + CVP_SWUpdateSign, // was CVP_CodeSigning + CVP_ResourceSigning, + CVP_iChat, + CVP_IPSec, + CVP_PKINIT_Server, + CVP_PKINIT_Client, + CVP_AppleCodeSigning, // the Leopard version + CVP_PackageSigning +} CertVerifyPolicy; + +typedef enum { + CRP_None = 0, + CRP_CRL, + CRP_OCSP, + CRP_CRL_OCSP +} CertRevokePolicy; + +/* + * Since I never stop adding args to certVerify(), most of which have reasonable + * defaults, the inputs are now expressed like so. + */ +#define CERT_VFY_ARGS_VERS 5 /* increment every time you change this struct */ +typedef struct { + int version; /* must be CERT_VFY_ARGS_VERS */ + CSSM_TP_HANDLE tpHand; + CSSM_CL_HANDLE clHand; + CSSM_CSP_HANDLE cspHand; + BlobList *certs; + BlobList *roots; + BlobList *crls; + char *vfyTime; + + CSSM_BOOL certNetFetchEnable; + CSSM_BOOL useSystemAnchors; + CSSM_BOOL useTrustSettings; + CSSM_BOOL leafCertIsCA; + CSSM_BOOL allowExpiredRoot; + CSSM_BOOL implicitAnchors; + CSSM_DL_DB_LIST_PTR dlDbList; // optional + CertVerifyPolicy vfyPolicy; + + const char *sslHost; // optional; SSL policy + CSSM_BOOL sslClient; // normally server side + const char *senderEmail; // optional, SMIME + CE_KeyUsage intendedKeyUse; // optional, SMIME only + + /* revocation options */ + CertRevokePolicy revokePolicy; + CSSM_BOOL allowUnverified; // if false, at least one must succeed + + /* CRL options */ + CSSM_BOOL requireCrlIfPresent; + CSSM_BOOL requireCrlForAll; + CSSM_BOOL crlNetFetchEnable; + CSSM_DL_DB_HANDLE_PTR crlDlDb; // obsolete: write CRLs here + + /* OCSP options */ + const char *responderURI; // optional, OCSP only + const unsigned char *responderCert; // optional, OCSP only + unsigned responderCertLen;// optional, OCSP only + CSSM_BOOL disableCache; // both r and w for now + CSSM_BOOL disableOcspNet; + CSSM_BOOL requireOcspIfPresent; + CSSM_BOOL requireOcspForAll; + CSSM_BOOL generateOcspNonce; + CSSM_BOOL requireOcspRespNonce; + + const char *expectedErrStr;// e.g., + // "CSSMERR_APPLETP_CRL_NOT_TRUSTED" + + /* + * expected per-cert errors + * format is certNum:errorString + * e.g., "1:CSSMERR_APPLETP_CRL_NOT_TRUSTED" + */ + unsigned numCertErrors; + const char **certErrors; // per-cert status + + /* + * Expected per-cert status (CSSM_TP_APPLE_EVIDENCE_INFO.StatusBits) + * format is certNum:status_in_hex + * e.g., "1:0x18", leading 0x optional + */ + unsigned numCertStatus; + const char **certStatus; + CSSM_BOOL quiet; + CSSM_BOOL verbose; + +} CertVerifyArgs; + +/* perform one cert/crl verification */ +int certVerify(CertVerifyArgs *args); + +/* + * A slightly simplified version of certVerify: + * -- no CRLs + * -- no DlDbs + * -- no net fetch + * -- time = now + * -- no trust settings + */ +int certVerifySimple( + CSSM_TP_HANDLE tpHand, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + BlobList &certs, + BlobList &roots, + CSSM_BOOL useSystemAnchors, + CSSM_BOOL leafCertIsCA, + CSSM_BOOL allowExpiredRoot, + CertVerifyPolicy vfyPolicy, + const char *sslHost, // optional, SSL policy + CSSM_BOOL sslClient, // normally server side + const char *senderEmail, // optional, SMIME + CE_KeyUsage intendedKeyUse, // optional, SMIME only + const char *expectedErrStr,// e.g., + unsigned numCertErrors, + const char **certErrors, // per-cert status + unsigned numCertStatus, + const char **certStatus, + CSSM_BOOL useTrustSettings, + CSSM_BOOL quiet, + CSSM_BOOL verbose); + +/* convert ASCII string in hex to unsigned */ +unsigned hexToBin(const char *hex); + +} /* extern "C" */ + +#endif /* _DO_VERIFY_H_ */ diff --git a/SecurityTests/clxutils/clAppUtils/clutils.c b/SecurityTests/clxutils/clAppUtils/clutils.c new file mode 100644 index 00000000..516866a5 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/clutils.c @@ -0,0 +1,192 @@ +/* + * clutils.c - common CL app-level routines, X version + */ + +#include +#include +#include +#include "clutils.h" +#include /* apple, not intel */ +#include + +static CSSM_API_MEMORY_FUNCS memFuncs = { + appMalloc, + appFree, + appRealloc, + appCalloc, + NULL + }; + +static CSSM_VERSION vers = {2, 0}; + +/* + * Init CSSM and establish a session with the Apple CL. + */ +CSSM_CL_HANDLE clStartup() +{ + CSSM_CL_HANDLE clHand; + CSSM_RETURN crtn; + + if(cssmStartup() == CSSM_FALSE) { + return 0; + } + crtn = CSSM_ModuleLoad(&gGuidAppleX509CL, + CSSM_KEY_HIERARCHY_NONE, + NULL, // eventHandler + NULL); // AppNotifyCallbackCtx + if(crtn) { + printError("CSSM_ModuleLoad(AppleCL)", crtn); + return 0; + } + crtn = CSSM_ModuleAttach (&gGuidAppleX509CL, + &vers, + &memFuncs, // memFuncs + 0, // SubserviceID + CSSM_SERVICE_CL, // SubserviceFlags - Where is this used? + 0, // AttachFlags + CSSM_KEY_HIERARCHY_NONE, + NULL, // FunctionTable + 0, // NumFuncTable + NULL, // reserved + &clHand); + if(crtn) { + printError("CSSM_ModuleAttach(AppleCL)", crtn); + return 0; + } + else { + return clHand; + } +} + +void clShutdown( + CSSM_CL_HANDLE clHand) +{ + CSSM_RETURN crtn; + + crtn = CSSM_ModuleDetach(clHand); + if(crtn) { + printf("Error detaching from AppleCL\n"); + printError("CSSM_ModuleDetach", crtn); + return; + } + crtn = CSSM_ModuleUnload(&gGuidAppleX509CL, NULL, NULL); + if(crtn) { + printf("Error unloading AppleCL\n"); + printError("CSSM_ModuleUnload", crtn); + } +} + +/* + * Init CSSM and establish a session with the Apple TP. + */ +CSSM_TP_HANDLE tpStartup() +{ + CSSM_TP_HANDLE tpHand; + CSSM_RETURN crtn; + + if(cssmStartup() == CSSM_FALSE) { + return 0; + } + crtn = CSSM_ModuleLoad(&gGuidAppleX509TP, + CSSM_KEY_HIERARCHY_NONE, + NULL, // eventHandler + NULL); // AppNotifyCallbackCtx + if(crtn) { + printError("CSSM_ModuleLoad(AppleTP)", crtn); + return 0; + } + crtn = CSSM_ModuleAttach (&gGuidAppleX509TP, + &vers, + &memFuncs, // memFuncs + 0, // SubserviceID + CSSM_SERVICE_TP, // SubserviceFlags + 0, // AttachFlags + CSSM_KEY_HIERARCHY_NONE, + NULL, // FunctionTable + 0, // NumFuncTable + NULL, // reserved + &tpHand); + if(crtn) { + printError("CSSM_ModuleAttach(AppleTP)", crtn); + return 0; + } + else { + return tpHand; + } +} + +void tpShutdown( + CSSM_TP_HANDLE tpHand) +{ + CSSM_RETURN crtn; + + crtn = CSSM_ModuleDetach(tpHand); + if(crtn) { + printf("Error detaching from AppleTP\n"); + printError("CSSM_ModuleDetach", crtn); + return; + } + crtn = CSSM_ModuleUnload(&gGuidAppleX509TP, NULL, NULL); + if(crtn) { + printf("Error unloading AppleTP\n"); + printError("CSSM_ModuleUnload", crtn); + } +} + + +/* + * Cook up a CSSM_DATA with specified integer, DER style (minimum number of + * bytes, big-endian). + */ +CSSM_DATA_PTR intToDER(unsigned theInt) +{ + CSSM_DATA_PTR DER_Data = (CSSM_DATA_PTR)CSSM_MALLOC(sizeof(CSSM_DATA)); + + if(theInt < 0x100) { + DER_Data->Length = 1; + DER_Data->Data = (uint8 *)CSSM_MALLOC(1); + DER_Data->Data[0] = (unsigned char)(theInt); + } + else if(theInt < 0x10000) { + DER_Data->Length = 2; + DER_Data->Data = (uint8 *)CSSM_MALLOC(2); + DER_Data->Data[0] = (unsigned char)(theInt >> 8); + DER_Data->Data[1] = (unsigned char)(theInt); + } + else if(theInt < 0x1000000) { + DER_Data->Length = 3; + DER_Data->Data = (uint8 *)CSSM_MALLOC(3); + DER_Data->Data[0] = (unsigned char)(theInt >> 16); + DER_Data->Data[1] = (unsigned char)(theInt >> 8); + DER_Data->Data[2] = (unsigned char)(theInt); + } + else { + DER_Data->Length = 4; + DER_Data->Data = (uint8 *)CSSM_MALLOC(4); + DER_Data->Data[0] = (unsigned char)(theInt >> 24); + DER_Data->Data[1] = (unsigned char)(theInt >> 16); + DER_Data->Data[2] = (unsigned char)(theInt >> 8); + DER_Data->Data[3] = (unsigned char)(theInt); + } + return DER_Data; +} + +/* + * Convert a CSSM_DATA_PTR, referring to a DER-encoded int, to a + * uint32. + */ +uint32 DER_ToInt(const CSSM_DATA *DER_Data) +{ + uint32 rtn = 0; + unsigned i = 0; + + while(i < DER_Data->Length) { + rtn |= DER_Data->Data[i]; + if(++i == DER_Data->Length) { + break; + } + rtn <<= 8; + } + return rtn; +} + diff --git a/SecurityTests/clxutils/clAppUtils/clutils.h b/SecurityTests/clxutils/clAppUtils/clutils.h new file mode 100644 index 00000000..c0cf82b5 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/clutils.h @@ -0,0 +1,31 @@ +/* + * clutils.h - common CL app-level routines, X version + */ + +#ifndef _CL_APP_UTILS_CLUTILS_H_ +#define _CL_APP_UTILS_CLUTILS_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +CSSM_CL_HANDLE clStartup(); +void clShutdown( + CSSM_CL_HANDLE clHand); + +CSSM_TP_HANDLE tpStartup(); +void tpShutdown( + CSSM_TP_HANDLE tpHand); + + +CSSM_DATA_PTR intToDER(unsigned theInt); +uint32 DER_ToInt(const CSSM_DATA *DER_Data); + +#ifdef __cplusplus +} +#endif + +#endif /* _CL_APP_UTILS_CLUTILS_H_ */ diff --git a/SecurityTests/clxutils/clAppUtils/crlUtils.cpp b/SecurityTests/clxutils/clAppUtils/crlUtils.cpp new file mode 100644 index 00000000..e126955b --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/crlUtils.cpp @@ -0,0 +1,318 @@ +/* + * crlUtils.cpp - CRL CL/TP/DL utilities. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* private API */ + +/* crlAddCrlToDb() removed due to build problem; obsoleted in favor of + * cuAddCrlToDb() in security_cdsa_utils + */ +#define CRL_ADD_TO_DB 0 + +#if CRL_ADD_TO_DB +#include /* private */ + /* SecInferLabelFromX509Name() */ + +/* + * Update an existing DLDB to be CRL-capable. + */ +static CSSM_RETURN crlAddCrlSchema( + CSSM_DL_DB_HANDLE dlDbHand) +{ + return CSSM_DL_CreateRelation(dlDbHand, + CSSM_DL_DB_RECORD_X509_CRL, + "CSSM_DL_DB_RECORD_X509_CRL", + Security::KeychainCore::Schema::X509CrlSchemaAttributeCount, + Security::KeychainCore::Schema::X509CrlSchemaAttributeList, + Security::KeychainCore::Schema::X509CrlSchemaIndexCount, + Security::KeychainCore::Schema::X509CrlSchemaIndexList); +} + +static void crlInferCrlLabel( + const CSSM_X509_NAME *x509Name, + CSSM_DATA *label) // not mallocd; contents are + // from the x509Name +{ + /* use private API for common "infer label" logic */ + const CSSM_DATA *printValue = SecInferLabelFromX509Name(x509Name); + if(printValue == NULL) { + /* punt! */ + label->Data = (uint8 *)"X509 CRL"; + label->Length = 8; + } + else { + *label = *printValue; + } +} + +/* + * Search extensions for specified OID, assumed to have underlying + * value type of uint32; returns the value and true if found. + */ +static bool crlSearchNumericExtension( + const CSSM_X509_EXTENSIONS *extens, + const CSSM_OID *oid, + uint32 *val) +{ + for(uint32 dex=0; dexnumberOfExtensions; dex++) { + const CSSM_X509_EXTENSION *exten = &extens->extensions[dex]; + if(!appCompareCssmData(&exten->extnId, oid)) { + continue; + } + if(exten->format != CSSM_X509_DATAFORMAT_PARSED) { + printf("***Malformed extension\n"); + continue; + } + *val = *((uint32 *)exten->value.parsedValue); + return true; + } + return false; +} + +/* + * Add a CRL to an existing DL/DB. + */ +#define MAX_CRL_ATTRS 8 + +CSSM_RETURN crlAddCrlToDb( + CSSM_DL_DB_HANDLE dlDbHand, + CSSM_CL_HANDLE clHand, + const CSSM_DATA *crl) +{ + CSSM_DB_ATTRIBUTE_DATA attrs[MAX_CRL_ATTRS]; + CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; + CSSM_DB_ATTRIBUTE_DATA_PTR attr = &attrs[0]; + CSSM_DATA crlTypeData; + CSSM_DATA crlEncData; + CSSM_DATA printNameData; + CSSM_RETURN crtn; + CSSM_DB_UNIQUE_RECORD_PTR recordPtr; + CSSM_DATA_PTR issuer; // mallocd by CL + CSSM_DATA_PTR crlValue; // ditto + uint32 numFields; + CSSM_HANDLE result; + CSSM_CRL_ENCODING crlEnc = CSSM_CRL_ENCODING_DER; + const CSSM_X509_SIGNED_CRL *signedCrl; + const CSSM_X509_TBS_CERTLIST *tbsCrl; + CSSM_CRL_TYPE crlType; + CSSM_DATA thisUpdateData = {0, NULL}; + CSSM_DATA nextUpdateData = {0, NULL}; + char *thisUpdate, *nextUpdate; + unsigned timeLen; + uint32 crlNumber; + uint32 deltaCrlNumber; + CSSM_DATA crlNumberData; + CSSM_DATA deltaCrlNumberData; + bool crlNumberPresent = false; + bool deltaCrlPresent = false; + + /* get normalized issuer name as Issuer attr */ + crtn = CSSM_CL_CrlGetFirstFieldValue(clHand, + crl, + &CSSMOID_X509V1IssuerName, + &result, + &numFields, + &issuer); + if(crtn) { + printError("CSSM_CL_CrlGetFirstFieldValue(Issuer)", crtn); + return crtn; + } + CSSM_CL_CrlAbortQuery(clHand, result); + + /* get parsed CRL from the CL */ + crtn = CSSM_CL_CrlGetFirstFieldValue(clHand, + crl, + &CSSMOID_X509V2CRLSignedCrlCStruct, + &result, + &numFields, + &crlValue); + if(crtn) { + printError("CSSM_CL_CrlGetFirstFieldValue(Issuer)", crtn); + return crtn; + } + CSSM_CL_CrlAbortQuery(clHand, result); + if(crlValue == NULL) { + printf("***CSSM_CL_CrlGetFirstFieldValue: value error (1)\n"); + return CSSMERR_CL_INVALID_CRL_POINTER; + } + if((crlValue->Data == NULL) || + (crlValue->Length != sizeof(CSSM_X509_SIGNED_CRL))) { + printf("***CSSM_CL_CrlGetFirstFieldValue: value error (2)\n"); + return CSSMERR_CL_INVALID_CRL_POINTER; + } + signedCrl = (const CSSM_X509_SIGNED_CRL *)crlValue->Data; + tbsCrl = &signedCrl->tbsCertList; + + /* CrlType inferred from version */ + if(tbsCrl->version.Length == 0) { + /* should never happen... */ + crlType = CSSM_CRL_TYPE_X_509v1; + } + else { + uint8 vers = tbsCrl->version.Data[tbsCrl->version.Length - 1]; + switch(vers) { + case 0: + crlType = CSSM_CRL_TYPE_X_509v1; + break; + case 1: + crlType = CSSM_CRL_TYPE_X_509v2; + break; + default: + printf("***Unknown version in CRL (%u)\n", vers); + crlType = CSSM_CRL_TYPE_X_509v1; + break; + } + } + crlTypeData.Data = (uint8 *)&crlType; + crlTypeData.Length = sizeof(CSSM_CRL_TYPE); + /* encoding more-or-less assumed here */ + crlEncData.Data = (uint8 *)&crlEnc; + crlEncData.Length = sizeof(CSSM_CRL_ENCODING); + + /* printName inferred from issuer */ + crlInferCrlLabel(&tbsCrl->issuer, &printNameData); + + /* cook up CSSM_TIMESTRING versions of this/next update */ + thisUpdate = x509TimeToCssmTimestring(&tbsCrl->thisUpdate, &timeLen); + if(thisUpdate == NULL) { + printf("***Badly formatted thisUpdate\n"); + } + else { + thisUpdateData.Data = (uint8 *)thisUpdate; + thisUpdateData.Length = timeLen; + } + nextUpdate = x509TimeToCssmTimestring(&tbsCrl->nextUpdate, &timeLen); + if(nextUpdate == NULL) { + printf("***Badly formatted nextUpdate\n"); + } + else { + nextUpdateData.Data = (uint8 *)nextUpdate; + nextUpdateData.Length = timeLen; + } + + /* optional CrlNumber and DeltaCrlNumber */ + if(crlSearchNumericExtension(&tbsCrl->extensions, + &CSSMOID_CrlNumber, + &crlNumber)) { + crlNumberData.Data = (uint8 *)&crlNumber; + crlNumberData.Length = sizeof(uint32); + crlNumberPresent = true; + } + if(crlSearchNumericExtension(&tbsCrl->extensions, + &CSSMOID_DeltaCrlIndicator, + &deltaCrlNumber)) { + deltaCrlNumberData.Data = (uint8 *)&deltaCrlNumber; + deltaCrlNumberData.Length = sizeof(uint32); + deltaCrlPresent = true; + } + /* we spec six attributes, skipping alias and URI */ + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = "CrlType"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32; + attr->NumberOfValues = 1; + attr->Value = &crlTypeData; + attr++; + + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = "CrlEncoding"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32; + attr->NumberOfValues = 1; + attr->Value = &crlEncData; + attr++; + + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = "PrintName"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + attr->NumberOfValues = 1; + attr->Value = &printNameData; + attr++; + + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = "Issuer"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + attr->NumberOfValues = 1; + attr->Value = issuer; + attr++; + + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = "ThisUpdate"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + attr->NumberOfValues = 1; + attr->Value = &thisUpdateData; + attr++; + + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = "NextUpdate"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + attr->NumberOfValues = 1; + attr->Value = &nextUpdateData; + attr++; + + /* now the optional attributes */ + if(crlNumberPresent) { + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = "CrlNumber"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32; + attr->NumberOfValues = 1; + attr->Value = &crlNumberData; + attr++; + } + if(deltaCrlPresent) { + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = "DeltaCrlNumber"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32; + attr->NumberOfValues = 1; + attr->Value = &deltaCrlNumberData; + attr++; + } + + recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_X509_CRL; + recordAttrs.SemanticInformation = 0; + recordAttrs.NumberOfAttributes = attr - attrs; + recordAttrs.AttributeData = attrs; + + crtn = CSSM_DL_DataInsert(dlDbHand, + CSSM_DL_DB_RECORD_X509_CRL, + &recordAttrs, + crl, + &recordPtr); + if(crtn == CSSMERR_DL_INVALID_RECORDTYPE) { + /* gross hack of inserting this "new" schema that + * Keychain didn't specify */ + crtn = crlAddCrlSchema(dlDbHand); + if(crtn == CSSM_OK) { + /* Retry with a fully capable DLDB */ + crtn = CSSM_DL_DataInsert(dlDbHand, + CSSM_DL_DB_RECORD_X509_CRL, + &recordAttrs, + crl, + &recordPtr); + } + } + if(crtn) { + printError("CSSM_DL_DataInsert", crtn); + } + else { + CSSM_DL_FreeUniqueRecord(dlDbHand, recordPtr); + } + + /* free all the stuff we allocated to get here */ + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1IssuerName, issuer); + CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V2CRLSignedCrlCStruct, + crlValue); + free(thisUpdate); + free(nextUpdate); + return crtn; +} + +#endif /* CRL_ADD_TO_DB */ diff --git a/SecurityTests/clxutils/clAppUtils/crlUtils.h b/SecurityTests/clxutils/clAppUtils/crlUtils.h new file mode 100644 index 00000000..6d951b50 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/crlUtils.h @@ -0,0 +1,28 @@ +/* + * crlUtils.cpp - CRL CL/TP/DL utilities. + */ + +#ifndef _CRL_UTILS_H_ +#define _CRL_UTILS_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Add a CRL to an existing DL/DB. + */ +#define MAX_CRL_ATTRS 8 + +CSSM_RETURN crlAddCrlToDb( + CSSM_DL_DB_HANDLE dlDbHand, + CSSM_CL_HANDLE clHand, + const CSSM_DATA *crl); + +#ifdef __cplusplus +} +#endif + +#endif /* _CRL_UTILS_H_ */ diff --git a/SecurityTests/clxutils/clAppUtils/identPicker.cpp b/SecurityTests/clxutils/clAppUtils/identPicker.cpp new file mode 100644 index 00000000..0b4ad3ac --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/identPicker.cpp @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2003-2008 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please + * obtain a copy of the License at http://www.apple.com/publicsource and + * read it before using this file. + * + * This 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. + */ + +/* + * identPicker.cp - Given a keychain, select from possible multiple + * SecIdentityRefs via stdio UI, and cook up a + * CFArray containing that identity and all certs needed + * for cert verification by an SSL peer. The resulting + * CFArrayRef is suitable for passing to SSLSetCertificate(). + */ + +#include "identPicker.h" +#include "sslAppUtils.h" +#include +#include +#include +#include + +/* + * Safe gets(). + * -- guaranteed no buffer overflow + * -- guaranteed NULL-terminated string + * -- handles empty string (i.e., response is just CR) properly + */ +void getString( + char *buf, + unsigned bufSize) +{ + unsigned dex; + char c; + char *cp = buf; + + for(dex=0; dexcount != 1)) { + printf("***Unexpected result fetching label attr\n"); + crtn = strdup("Unnamed KeychainItem"); + goto errOut; + } + /* We're assuming 8-bit ASCII attribute data here... */ + attr = attrList->attr; + crtn = (char *)malloc(attr->length + 1); + memmove(crtn, attr->data, attr->length); + crtn[attr->length] = '\0'; + +errOut: + SecKeychainItemFreeAttributesAndData(attrList, NULL); + return crtn; +} + +/* + * Get the final term of a keychain's path as a C string. Caller must free() + * the result. + */ +char *kcFileName( + SecKeychainRef kcRef) +{ + char fullPath[MAXPATHLEN + 1]; + OSStatus ortn; + UInt32 pathLen = MAXPATHLEN; + + ortn = SecKeychainGetPath(kcRef, &pathLen, fullPath); + if(ortn) { + cssmPerror("SecKeychainGetPath", ortn); + return strdup("orphan keychain"); + } + + /* NULL terminate the path string and search for final '/' */ + fullPath[pathLen] = '\0'; + char *lastSlash = NULL; + char *thisSlash = fullPath; + do { + thisSlash = strchr(thisSlash, '/'); + if(thisSlash == NULL) { + /* done */ + break; + } + thisSlash++; + lastSlash = thisSlash; + } while(thisSlash != NULL); + if(lastSlash == NULL) { + /* no slashes, odd, but handle it */ + return strdup(fullPath); + } + else { + return strdup(lastSlash); + } +} + +/* + * Obtain the final term of a keychain item's keychain path as a C string. + * Caller must free() the result. + * May well return NULL indicating the item has no keychain (e.g. az floating cert). + */ +char *kcItemKcFileName(SecKeychainItemRef itemRef) +{ + OSStatus ortn; + SecKeychainRef kcRef = NULL; + + ortn = SecKeychainItemCopyKeychain(itemRef, &kcRef); + if(ortn) { + return NULL; + } + char *rtnStr = kcFileName(kcRef); + CFRelease(kcRef); + return rtnStr; +} + +/* + * Given an array of SecIdentityRefs: + * -- display a printable name of each identity's cert; + * -- prompt user to select which one to use; + * + * Returns CFIndex of desired identity. A return of <0 indicates + * "none - abort". + */ +static CFIndex pickIdent( + CFArrayRef idArray) +{ + CFIndex count = CFArrayGetCount(idArray); + CFIndex dex; + OSStatus ortn; + + if(count == 0) { + printf("***sslIdentPicker screwup: no identities found\n"); + return -1; + } + for(dex=0; dex= 0) && (ires < count)) { + return (CFIndex)ires; + } + printf("***Invalid entry. Type a number between 0 and %ld\n", + count-1); + } + return -1; +} + +OSStatus sslSimpleIdentPicker( + SecKeychainRef kcRef, // NULL means use default list + SecIdentityRef *ident) // RETURNED +{ + OSStatus ortn; + CFMutableArrayRef idArray = NULL; // holds all SecIdentityRefs found + + /* Search for all identities */ + *ident = NULL; + SecIdentitySearchRef srchRef = nil; + ortn = SecIdentitySearchCreate(kcRef, + 0, // keyUsage - any + &srchRef); + if(ortn) { + cssmPerror("SecIdentitySearchCreate", (CSSM_RETURN)ortn); + printf("Cannot find signing key in keychain.\n"); + return ortn; + } + + /* get all identities, stuff them into idArray */ + SecIdentityRef identity = nil; + idArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + do { + ortn = SecIdentitySearchCopyNext(srchRef, &identity); + if(ortn != noErr) { + break; + } + CFArrayAppendValue(idArray, identity); + + /* the array has the retain count we need */ + CFRelease(identity); + } while(ortn == noErr); + CFRelease(srchRef); + + switch(ortn) { + case errSecItemNotFound: + if(CFArrayGetCount(idArray) == 0) { + printf("No signing keys found in keychain.\n"); + return errSecItemNotFound; + } + else { + /* found at least one; proceed */ + break; + } + default: + cssmPerror("SecIdentitySearchCopyNext", (CSSM_RETURN)ortn); + printf("Cannot find signing key in keychain.\n"); + return ortn; + } + + /* + * If there is just one, use it without asking + */ + CFIndex whichId; + if(CFArrayGetCount(idArray) == 1) { + whichId = 0; + } + else { + whichId = pickIdent(idArray); + if(whichId < 0) { + return CSSMERR_CSSM_USER_CANCELED; + } + } + + /* keep this one, free the rest */ + identity = (SecIdentityRef)CFArrayGetValueAtIndex(idArray, whichId); + CFRetain(identity); + CFRelease(idArray); + *ident = identity; + return noErr; +} + +OSStatus sslIdentPicker( + SecKeychainRef kcRef, // NULL means use default list + SecCertificateRef trustedAnchor, // optional additional trusted anchor + bool includeRoot, // true --> root is appended to outArray + // false --> root not included + const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL + CFArrayRef *outArray) // created and RETURNED +{ + OSStatus ortn; + SecIdentityRef identity; + + ortn = sslSimpleIdentPicker(kcRef, &identity); + if(ortn) { + return ortn; + } + return sslCompleteCertChain(identity, trustedAnchor, includeRoot, + vfyPolicy, outArray); +} + diff --git a/SecurityTests/clxutils/clAppUtils/identPicker.h b/SecurityTests/clxutils/clAppUtils/identPicker.h new file mode 100644 index 00000000..5b137cc0 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/identPicker.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2003-2007 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please + * obtain a copy of the License at http://www.apple.com/publicsource and + * read it before using this file. + * + * This 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. + */ + +/* + * identPicker.h - Given a keychain, select from possible multiple + * SecIdentityRefs via stdio UI, and cook up a + * CFArray containing that identity and all certs needed + * for cert verification by an SSL peer. The resulting + * CFArrayRef is suitable for passing to SSLSetCertificate(). + */ + +#ifndef _IDENT_PICKER_H_ +#define _IDENT_PICKER_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Get the final term of a keychain's path as a C string. Caller must free() + * the result. + */ +char *kcFileName( + SecKeychainRef kcRef); + +/* + * Obtain the printable name of a SecKeychainItemRef as a C string. + * Caller must free() the result. + */ +char *kcItemPrintableName( + SecKeychainItemRef itemRef); + +/* + * Obtain the final term of a keychain item's keychain path as a C string. + * Caller must free() the result. + * May well return NULL indicating the item has no keychain (e.g. az floating cert). + */ +char *kcItemKcFileName(SecKeychainItemRef itemRef); + +/* + * Safe gets(). + * -- guaranteed no buffer overflow + * -- guaranteed NULL-terminated string + * -- handles empty string (i.e., response is just CR) properly + */ +void getString( + char *buf, + unsigned bufSize); + +/* + * IdentityPicker, returns full cert chain, optionally including root. + */ +OSStatus sslIdentPicker( + SecKeychainRef kc, // NULL means use default list + SecCertificateRef trustedAnchor, // optional additional trusted anchor + bool includeRoot, // true --> root is appended to outArray + // false --> root not included + const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL + CFArrayRef *outArray); // created and RETURNED + +/* + * Simple version, just returns a SecIdentityRef. + */ +OSStatus sslSimpleIdentPicker( + SecKeychainRef kc, // NULL means use default list + SecIdentityRef *ident); // RETURNED + +#ifdef __cplusplus +} +#endif + +#endif /* _IDENT_PICKER_H_ */ + diff --git a/SecurityTests/clxutils/clAppUtils/ioSock.c b/SecurityTests/clxutils/clAppUtils/ioSock.c new file mode 100644 index 00000000..1a3d5e98 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/ioSock.c @@ -0,0 +1,480 @@ +/* + * io_sock.c - SecureTransport sample I/O module, X sockets version + */ + +#include "ioSock.h" +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* debugging for this module */ +#define SSL_OT_DEBUG 1 + +/* log errors to stdout */ +#define SSL_OT_ERRLOG 1 + +/* trace all low-level network I/O */ +#define SSL_OT_IO_TRACE 0 + +/* if SSL_OT_IO_TRACE, only log non-zero length transfers */ +#define SSL_OT_IO_TRACE_NZ 1 + +/* pause after each I/O (only meaningful if SSL_OT_IO_TRACE == 1) */ +#define SSL_OT_IO_PAUSE 0 + +/* print a stream of dots while I/O pending */ +#define SSL_OT_DOT 1 + +/* dump some bytes of each I/O (only meaningful if SSL_OT_IO_TRACE == 1) */ +#define SSL_OT_IO_DUMP 0 +#define SSL_OT_IO_DUMP_SIZE 1024 + +/* indicate errSSLWouldBlock with a '.' */ +#define SSL_DISPL_WOULD_BLOCK 0 + +/* general, not-too-verbose debugging */ +#if SSL_OT_DEBUG +#define dprintf(s) printf s +#else +#define dprintf(s) +#endif + +/* errors --> stdout */ +#if SSL_OT_ERRLOG +#define eprintf(s) printf s +#else +#define eprintf(s) +#endif + +/* trace completion of every r/w */ +#if SSL_OT_IO_TRACE +static void tprintf( + const char *str, + UInt32 req, + UInt32 act, + const UInt8 *buf) +{ + #if SSL_OT_IO_TRACE_NZ + if(act == 0) { + return; + } + #endif + printf("%s(%u): moved (%u) bytes\n", str, (unsigned)req, (unsigned)act); + #if SSL_OT_IO_DUMP + { + unsigned i; + + for(i=0; i= (SSL_OT_IO_DUMP_SIZE - 1)) { + break; + } + if((i % 32) == 31) { + putchar('\n'); + } + } + printf("\n"); + } + #endif + #if SSL_OT_IO_PAUSE + { + char instr[20]; + printf("CR to continue: "); + gets(instr); + } + #endif +} + +#else +#define tprintf(str, req, act, buf) +#endif /* SSL_OT_IO_TRACE */ + +/* + * If SSL_OT_DOT, output a '.' every so often while waiting for + * connection. This gives user a chance to do something else with the + * UI. + */ + +#if SSL_OT_DOT + +static time_t lastTime = (time_t)0; +#define TIME_INTERVAL 3 + +static void outputDot() +{ + time_t thisTime = time(0); + + if((thisTime - lastTime) >= TIME_INTERVAL) { + printf("."); fflush(stdout); + lastTime = thisTime; + } +} +#else +#define outputDot() +#endif + + +/* + * One-time only init. + */ +void initSslOt() +{ + +} + +/* + * Connect to server. + */ +#define GETHOST_RETRIES 3 + +OSStatus MakeServerConnection( + const char *hostName, + int port, + int nonBlocking, // 0 or 1 + otSocket *socketNo, // RETURNED + PeerSpec *peer) // RETURNED +{ + struct sockaddr_in addr; + struct hostent *ent; + struct in_addr host; + int sock = 0; + + *socketNo = NULL; + if (hostName[0] >= '0' && hostName[0] <= '9') + { + host.s_addr = inet_addr(hostName); + } + else { + unsigned dex; + /* seeing a lot of soft failures here that I really don't want to track down */ + for(dex=0; dexh_addr, sizeof(struct in_addr)); + } + sock = socket(AF_INET, SOCK_STREAM, 0); + addr.sin_addr = host; + addr.sin_port = htons((u_short)port); + + addr.sin_family = AF_INET; + if (connect(sock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) != 0) + { printf("connect returned error\n"); + return ioErr; + } + + if(nonBlocking) { + /* OK to do this after connect? */ + int rtn = fcntl(sock, F_SETFL, O_NONBLOCK); + if(rtn == -1) { + perror("fctnl(O_NONBLOCK)"); + return ioErr; + } + } + + peer->ipAddr = addr.sin_addr.s_addr; + peer->port = htons((u_short)port); + *socketNo = (otSocket)sock; + return noErr; +} + +/* + * Set up an otSocket to listen for client connections. Call once, then + * use multiple AcceptClientConnection calls. + */ +OSStatus ListenForClients( + int port, + int nonBlocking, // 0 or 1 + otSocket *socketNo) // RETURNED +{ + struct sockaddr_in addr; + struct hostent *ent; + int len; + int sock; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if(sock < 1) { + perror("socket"); + return ioErr; + } + + ent = gethostbyname("localhost"); + if (!ent) { + perror("gethostbyname"); + return ioErr; + } + memcpy(&addr.sin_addr, ent->h_addr, sizeof(struct in_addr)); + + addr.sin_port = htons((u_short)port); + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_family = AF_INET; + len = sizeof(struct sockaddr_in); + if (bind(sock, (struct sockaddr *) &addr, len)) { + int theErr = errno; + perror("bind"); + if(theErr == EADDRINUSE) { + return opWrErr; + } + else { + return ioErr; + } + } + if(nonBlocking) { + int rtn = fcntl(sock, F_SETFL, O_NONBLOCK); + if(rtn == -1) { + perror("fctnl(O_NONBLOCK)"); + return ioErr; + } + } + + for(;;) { + int rtn = listen(sock, 1); + switch(rtn) { + case 0: + *socketNo = (otSocket)sock; + rtn = noErr; + break; + case EWOULDBLOCK: + continue; + default: + perror("listen"); + rtn = ioErr; + break; + } + return rtn; + } + /* NOT REACHED */ + return 0; +} + +/* + * Accept a client connection. + */ + +/* + * Currently we always get back a different peer port number on successive + * connections, no matter what the client is doing. To test for resumable + * session support, force peer port = 0. + */ +#define FORCE_ACCEPT_PEER_PORT_ZERO 1 + +OSStatus AcceptClientConnection( + otSocket listenSock, // obtained from ListenForClients + otSocket *acceptSock, // RETURNED + PeerSpec *peer) // RETURNED +{ + struct sockaddr_in addr; + int sock; + socklen_t len; + + len = sizeof(struct sockaddr_in); + do { + sock = accept((int)listenSock, (struct sockaddr *) &addr, &len); + if (sock < 0) { + if(errno == EAGAIN) { + /* nonblocking, no connection yet */ + continue; + } + else { + perror("accept"); + return ioErr; + } + } + else { + break; + } + } while(1); + *acceptSock = (otSocket)sock; + peer->ipAddr = addr.sin_addr.s_addr; + #if FORCE_ACCEPT_PEER_PORT_ZERO + peer->port = 0; + #else + peer->port = ntohs(addr.sin_port); + #endif + return noErr; +} + +/* + * Shut down a connection. + */ +void endpointShutdown( + otSocket socket) +{ + close((int)socket); +} + +/* + * R/W. Called out from SSL. + */ +OSStatus SocketRead( + SSLConnectionRef connection, + void *data, /* owned by + * caller, data + * RETURNED */ + size_t *dataLength) /* IN/OUT */ +{ + UInt32 bytesToGo = *dataLength; + UInt32 initLen = bytesToGo; + UInt8 *currData = (UInt8 *)data; + int sock = (int)((long)connection); + OSStatus rtn = noErr; + UInt32 bytesRead; + ssize_t rrtn; + + *dataLength = 0; + + for(;;) { + bytesRead = 0; + /* paranoid check, ensure errno is getting written */ + errno = -555; + rrtn = recv(sock, currData, bytesToGo, 0); + if (rrtn <= 0) { + if(rrtn == 0) { + /* closed, EOF */ + rtn = errSSLClosedGraceful; + break; + } + int theErr = errno; + switch(theErr) { + case ENOENT: + /* + * Undocumented but I definitely see this. + * Non-blocking sockets only. Definitely retriable + * just like an EAGAIN. + */ + dprintf(("SocketRead RETRYING on ENOENT, rrtn %d\n", + (int)rrtn)); + /* normal... */ + //rtn = errSSLWouldBlock; + /* ...for temp testing.... */ + rtn = ioErr; + break; + case ECONNRESET: + /* explicit peer abort */ + rtn = errSSLClosedAbort; + break; + case EAGAIN: + /* nonblocking, no data */ + rtn = errSSLWouldBlock; + break; + default: + dprintf(("SocketRead: read(%u) error %d, rrtn %d\n", + (unsigned)bytesToGo, theErr, (int)rrtn)); + rtn = ioErr; + break; + } + /* in any case, we're done with this call if rrtn <= 0 */ + break; + } + bytesRead = rrtn; + bytesToGo -= bytesRead; + currData += bytesRead; + + if(bytesToGo == 0) { + /* filled buffer with incoming data, done */ + break; + } + } + *dataLength = initLen - bytesToGo; + tprintf("SocketRead", initLen, *dataLength, (UInt8 *)data); + + #if SSL_OT_DOT || (SSL_OT_DEBUG && !SSL_OT_IO_TRACE) + if((rtn == 0) && (*dataLength == 0)) { + /* keep UI alive */ + outputDot(); + } + #endif + #if SSL_DISPL_WOULD_BLOCK + if(rtn == errSSLWouldBlock) { + printf("."); fflush(stdout); + } + #endif + return rtn; +} + +int oneAtATime = 0; + +OSStatus SocketWrite( + SSLConnectionRef connection, + const void *data, + size_t *dataLength) /* IN/OUT */ +{ + size_t bytesSent = 0; + int sock = (int)((long)connection); + int length; + size_t dataLen = *dataLength; + const UInt8 *dataPtr = (UInt8 *)data; + OSStatus ortn; + + if(oneAtATime && (*dataLength > 1)) { + size_t i; + size_t outLen; + size_t thisMove; + + outLen = 0; + for(i=0; i 0) && + ( (bytesSent += length) < dataLen) ); + + if(length <= 0) { + int theErr = errno; + switch(theErr) { + case EAGAIN: + ortn = errSSLWouldBlock; break; + case EPIPE: + /* as of Leopard 9A312 or so, the error formerly seen as EPIPE is + * now reported as ECONNRESET. This happens when we're catching + * SIGPIPE and we write to a socket which has been closed by the peer. + */ + case ECONNRESET: + ortn = errSSLClosedAbort; break; + default: + dprintf(("SocketWrite: write(%u) error %d\n", + (unsigned)(dataLen - bytesSent), theErr)); + ortn = ioErr; + break; + } + } + else { + ortn = noErr; + } + tprintf("SocketWrite", dataLen, bytesSent, dataPtr); + *dataLength = bytesSent; + return ortn; +} diff --git a/SecurityTests/clxutils/clAppUtils/ioSock.h b/SecurityTests/clxutils/clAppUtils/ioSock.h new file mode 100644 index 00000000..c01f8f11 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/ioSock.h @@ -0,0 +1,88 @@ +/* + * ioSock.h - socket-based I/O routines for SecureTransport tests + */ + +#ifndef _IO_SOCK_H_ +#define _IO_SOCK_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Opaque reference to an Open Transport connection. + */ +typedef int otSocket; + +/* + * info about a peer returned from MakeServerConnection() and + * AcceptClientConnection(). + */ +typedef struct +{ UInt32 ipAddr; + int port; +} PeerSpec; + +/* + * Ont-time only init. + */ +void initSslOt(); + +/* + * Connect to server. + */ +extern OSStatus MakeServerConnection( + const char *hostName, + int port, + int nonBlocking, // 0 or 1 + otSocket *socketNo, // RETURNED + PeerSpec *peer); // RETURNED + +/* + * Set up an otSocket to listen for client connections. Call once, then + * use multiple AcceptClientConnection calls. + */ +OSStatus ListenForClients( + int port, + int nonBlocking, // 0 or 1 + otSocket *socketNo); // RETURNED + +/* + * Accept a client connection. Call endpointShutdown() for each successful; + * return from this function. + */ +OSStatus AcceptClientConnection( + otSocket listenSock, // obtained from ListenForClients + otSocket *acceptSock, // RETURNED + PeerSpec *peer); // RETURNED + +/* + * Shut down a connection. + */ +void endpointShutdown( + otSocket socket); + +/* + * R/W. Called out from SSL. + */ +OSStatus SocketRead( + SSLConnectionRef connection, + void *data, /* owned by + * caller, data + * RETURNED */ + size_t *dataLength); /* IN/OUT */ + +OSStatus SocketWrite( + SSLConnectionRef connection, + const void *data, + size_t *dataLength); /* IN/OUT */ + +#ifdef __cplusplus +} +#endif + +#endif /* _IO_SOCK_H_ */ diff --git a/SecurityTests/clxutils/clAppUtils/keyPicker.cpp b/SecurityTests/clxutils/clAppUtils/keyPicker.cpp new file mode 100644 index 00000000..a8bbf5f0 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/keyPicker.cpp @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2004-2006 Apple Computer, 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@ + */ + +/* + * keyPicker.cpp - select a key pair from a keychain + */ + +#include "keyPicker.h" +#include +#include +#include +#include +#include /* for kcFileName() */ +#include + +/* + * Obtain either public key hash or PrintName for a given SecKeychainItem. Works on public keys, + * private keys, identities, and certs. Caller must release the returned result. + */ +OSStatus getKcItemAttr( + SecKeychainItemRef kcItem, + WhichAttr whichAttr, + CFDataRef *rtnAttr) /* RETURNED */ +{ + /* main job is to figure out which attrType to ask for, and from what Sec item */ + SecKeychainItemRef attrFromThis; + SecKeychainAttrType attrType = 0; + OSStatus ortn; + bool releaseKcItem = false; + + CFTypeID cfId = CFGetTypeID(kcItem); + if(cfId == SecIdentityGetTypeID()) { + /* switch over to cert */ + ortn = SecIdentityCopyCertificate((SecIdentityRef)kcItem, + (SecCertificateRef *)&attrFromThis); + if(ortn) + cssmPerror("SecIdentityCopyCertificate", ortn); + return ortn; + kcItem = attrFromThis; + releaseKcItem = true; + cfId = SecCertificateGetTypeID(); + } + + if(cfId == SecCertificateGetTypeID()) { + switch(whichAttr) { + case WA_Hash: + attrType = kSecPublicKeyHashItemAttr; + break; + case WA_PrintName: + attrType = kSecLabelItemAttr; + break; + default: + printf("getKcItemAttr: WhichAttr\n"); + return paramErr; + } + } + else if(cfId == SecKeyGetTypeID()) { + switch(whichAttr) { + case WA_Hash: + attrType = kSecKeyLabel; + break; + case WA_PrintName: + attrType = kSecKeyPrintName; + break; + default: + printf("getKcItemAttr: WhichAttr\n"); + return paramErr; + } + } + + SecKeychainAttributeInfo attrInfo; + attrInfo.count = 1; + attrInfo.tag = &attrType; + attrInfo.format = NULL; // ??? + SecKeychainAttributeList *attrList = NULL; + + ortn = SecKeychainItemCopyAttributesAndData( + kcItem, + &attrInfo, + NULL, // itemClass + &attrList, + NULL, // don't need the data + NULL); + if(releaseKcItem) { + CFRelease(kcItem); + } + if(ortn) { + cssmPerror("SecKeychainItemCopyAttributesAndData", ortn); + return paramErr; + } + SecKeychainAttribute *attr = attrList->attr; + *rtnAttr = CFDataCreate(NULL, (UInt8 *)attr->data, attr->length); + SecKeychainItemFreeAttributesAndData(attrList, NULL); + return noErr; +} + +/* + * Class representing one key in the keychain. + */ +class PickerKey +{ +public: + PickerKey(SecKeyRef keyRef); + ~PickerKey(); + + bool isUsed() { return mIsUsed;} + void isUsed(bool u) { mIsUsed = u; } + bool isPrivate() { return mIsPrivate; } + CFDataRef getPrintName() { return mPrintName; } + CFDataRef getPubKeyHash() { return mPubKeyHash; } + SecKeyRef keyRef() { return mKeyRef; } + + PickerKey *partnerKey() { return mPartner; } + void partnerKey(PickerKey *pk) { mPartner = pk; } + char *kcFile() { return mKcFile; } + +private: + SecKeyRef mKeyRef; + CFDataRef mPrintName; + CFDataRef mPubKeyHash; + bool mIsPrivate; // private/public key + bool mIsUsed; // has been spoken for + PickerKey *mPartner; // other member of public/private pair + char *mKcFile; // file name of keychain this lives on +}; + +PickerKey::PickerKey(SecKeyRef keyRef) + : mKeyRef(NULL), + mPrintName(NULL), + mPubKeyHash(NULL), + mIsPrivate(false), + mIsUsed(false), + mPartner(NULL), + mKcFile(NULL) +{ + if(CFGetTypeID(keyRef) != SecKeyGetTypeID()) { + throw std::invalid_argument("not a key"); + } + + OSStatus ortn = getKcItemAttr((SecKeychainItemRef)keyRef, WA_Hash, &mPubKeyHash); + if(ortn) { + throw std::invalid_argument("pub key hash not available"); + } + ortn = getKcItemAttr((SecKeychainItemRef)keyRef, WA_PrintName, &mPrintName); + if(ortn) { + throw std::invalid_argument("pub key hash not available"); + } + + const CSSM_KEY *cssmKey; + ortn = SecKeyGetCSSMKey(keyRef, &cssmKey); + if(ortn) { + /* should never happen */ + cssmPerror("SecKeyGetCSSMKey", ortn); + throw std::invalid_argument("SecKeyGetCSSMKey error"); + } + if(cssmKey->KeyHeader.KeyClass == CSSM_KEYCLASS_PRIVATE_KEY) { + mIsPrivate = true; + } + + /* stash name of the keychain this lives on */ + SecKeychainRef kcRef; + ortn = SecKeychainItemCopyKeychain((SecKeychainItemRef)keyRef, &kcRef); + if(ortn) { + cssmPerror("SecKeychainItemCopyKeychain", ortn); + mKcFile = strdup("Unnamed keychain"); + } + else { + mKcFile = kcFileName(kcRef); + } + + mKeyRef = keyRef; + CFRetain(mKeyRef); +} + +PickerKey::~PickerKey() +{ + if(mKeyRef) { + CFRelease(mKeyRef); + } + if(mPubKeyHash) { + CFRelease(mPubKeyHash); + } + if(mPrintName) { + CFRelease(mPrintName); + } + if(mKcFile) { + free(mKcFile); + } +} + +typedef std::vector KeyVector; + +/* + * add PickerKey objects of specified type to a KeyVector. + */ +static void getPickerKeys( + SecKeychainRef kcRef, + SecItemClass itemClass, // actually CSSM_DL_DB_RECORD_{PRIVATE,PRIVATE}_KEY for now + KeyVector &keyVector) +{ + SecKeychainSearchRef srchRef = NULL; + SecKeychainItemRef kcItem; + + OSStatus ortn = SecKeychainSearchCreateFromAttributes(kcRef, + itemClass, + NULL, // any attrs + &srchRef); + if(ortn) { + cssmPerror("SecKeychainSearchCreateFromAttributes", ortn); + return; + } + do { + ortn = SecKeychainSearchCopyNext(srchRef, &kcItem); + if(ortn) { + break; + } + try { + PickerKey *pickerKey = new PickerKey((SecKeyRef)kcItem); + keyVector.push_back(pickerKey); + } + catch(...) { + printf("**** key item that failed PickerKey construct ***\n"); + /* but keep going */ + } + } while(ortn == noErr); + CFRelease(srchRef); +} + +/* + * Print contents of a CFData assuming it's printable + */ +static void printCfData(CFDataRef cfd) +{ + CFIndex len = CFDataGetLength(cfd); + const UInt8 *cp = CFDataGetBytePtr(cfd); + for(CFIndex dex=0; dex privKeys; + std::vector pubKeys; + getPickerKeys(kcRef, CSSM_DL_DB_RECORD_PRIVATE_KEY, privKeys); + getPickerKeys(kcRef, CSSM_DL_DB_RECORD_PUBLIC_KEY, pubKeys); + + /* now interate thru private keys, looking for a partner for each one */ + int numPairs = 0; + unsigned numPrivKeys = privKeys.size(); + unsigned numPubKeys = pubKeys.size(); + + for(unsigned privDex=0; privDexgetPubKeyHash(); + for(unsigned pubDex=0; pubDexisUsed()) { + /* already spoken for */ + continue; + } + if(!CFEqual(privHash, pubPk->getPubKeyHash())) { + /* public key hashes don't match */ + continue; + } + + /* got a match */ + pubPk->partnerKey(privPk); + privPk->partnerKey(pubPk); + pubPk->isUsed(true); + privPk->isUsed(true); + + /* display */ + printf("[%d] privKey : ", numPairs); printCfData(privPk->getPrintName()); printf("\n"); + printf(" pubKey : "); printCfData(pubPk->getPrintName());printf("\n"); + printf(" keychain : %s\n", privPk->kcFile()); + + numPairs++; + } + } + + if(numPairs == 0) { + printf("*** keyPicker: no key pairs found.\n"); + return paramErr; + } + + OSStatus ortn = noErr; + int ires; + while(1) { + fpurge(stdin); + printf("\nEnter key pair number or CR to quit : "); + fflush(stdout); + char resp[64]; + getString(resp, sizeof(resp)); + if(resp[0] == '\0') { + ortn = CSSMERR_CSSM_USER_CANCELED; + break; + } + ires = atoi(resp); + if((ires < 0) || (ires >= numPairs)) { + printf("***Invalid entry. Type a number between 0 and %d\n", numPairs-1); + continue; + } + break; + } + + if(ortn == noErr) { + /* find the ires'th partnered private key */ + int goodOnes = 0; + for(unsigned privDex=0; privDexisUsed()) { + continue; + } + if(goodOnes == ires) { + /* this is it */ + *privKey = privPk->keyRef(); + *pubKey = privPk->partnerKey()->keyRef(); + } + goodOnes++; + } + } + + /* clean out PickerKey arrays */ + for(unsigned privDex=0; privDex + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Obtain either public key hash or PrintName for a given SecKeychainItem. Works on public keys, + * private keys, identities, and certs. Caller must release the returned result. + */ +typedef enum { + WA_Hash, + WA_PrintName +} WhichAttr; + +OSStatus getKcItemAttr( + SecKeychainItemRef kcItem, + WhichAttr whichAttr, + CFDataRef *rtnAttr); // RETURNED + +OSStatus keyPicker( + SecKeychainRef kcRef, // NULL means the default list + SecKeyRef *pubKey, // RETURNED + SecKeyRef *privKey); // RETURNED + + +#ifdef __cplusplus +} +#endif + +#endif /* _KEY_PICKER_H_ */ + diff --git a/SecurityTests/clxutils/clAppUtils/printCertName.cpp b/SecurityTests/clxutils/clAppUtils/printCertName.cpp new file mode 100644 index 00000000..2069ed11 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/printCertName.cpp @@ -0,0 +1,186 @@ +#include +#include "printCertName.h" +#include +#include + +static CSSM_CL_HANDLE gClHand = 0; + +static CSSM_CL_HANDLE getClHand() +{ + if(gClHand) { + return gClHand; + } + gClHand = clStartup(); + return gClHand; +} + +static void printString( + const CSSM_DATA *str) +{ + unsigned i; + char *cp = (char *)str->Data; + for(i=0; iLength; i++) { + printf("%c", *cp++); + } + printf("\n"); +} + +static void printData( + const CSSM_DATA *cd) +{ + for(unsigned dex=0; dexLength; dex++) { + printf("%02X", cd->Data[dex]); + if((dex % 4) == 3) { + printf(" "); + } + } + printf("\n"); +} + +/* + * Print an CSSM_X509_TYPE_VALUE_PAIR + */ +static void printAtv( + const CSSM_X509_TYPE_VALUE_PAIR_PTR atv) +{ + const CSSM_OID *oid = &atv->type; + const char *fieldName = "Other"; + if(appCompareCssmData(oid, &CSSMOID_CountryName)) { + fieldName = "Country "; + } + else if(appCompareCssmData(oid, &CSSMOID_OrganizationName)) { + fieldName = "Org "; + } + else if(appCompareCssmData(oid, &CSSMOID_LocalityName)) { + fieldName = "Locality "; + } + else if(appCompareCssmData(oid, &CSSMOID_OrganizationalUnitName)) { + fieldName = "OrgUnit "; + } + else if(appCompareCssmData(oid, &CSSMOID_CommonName)) { + fieldName = "Common Name "; + } + else if(appCompareCssmData(oid, &CSSMOID_Surname)) { + fieldName = "Surname "; + } + else if(appCompareCssmData(oid, &CSSMOID_Title)) { + fieldName = "Title "; + } + else if(appCompareCssmData(oid, &CSSMOID_Surname)) { + fieldName = "Surname "; + } + else if(appCompareCssmData(oid, &CSSMOID_StateProvinceName)) { + fieldName = "State "; + } + else if(appCompareCssmData(oid, &CSSMOID_CollectiveStateProvinceName)) { + fieldName = "Coll. State "; + } + else if(appCompareCssmData(oid, &CSSMOID_EmailAddress)) { + /* deprecated, used by Thawte */ + fieldName = "Email addrs "; + } + else { + fieldName = "Other name "; + } + printf(" %s : ", fieldName); + switch(atv->valueType) { + case BER_TAG_PRINTABLE_STRING: + case BER_TAG_IA5_STRING: + case BER_TAG_T61_STRING: // mostly printable.... + case BER_TAG_PKIX_UTF8_STRING: // ditto + printString(&atv->value); + break; + default: + printData(&atv->value); + break; + } +} + +/* + * Print contents of a CSSM_X509_NAME. + */ +static void printName( + const char *title, + const CSSM_X509_NAME *name) +{ + printf(" %s:\n", title); + unsigned numRdns = name->numberOfRDNs; + for(unsigned rdnDex=0; rdnDexRelativeDistinguishedName[rdnDex]; + unsigned numAtvs = rdn->numberOfPairs; + for(unsigned atvDex=0; atvDexAttributeTypeAndValue[atvDex]); + } + } +} + +static void printOneCertName( + CSSM_CL_HANDLE clHand, + CSSM_HANDLE cacheHand, + const char *title, + const CSSM_OID *oid) +{ + CSSM_HANDLE resultHand = 0; + CSSM_DATA_PTR field = NULL; + uint32 numFields; + CSSM_RETURN crtn; + + crtn = CSSM_CL_CertGetFirstCachedFieldValue(clHand, cacheHand, + oid, &resultHand, &numFields, &field); + if(crtn) { + printf("***Error parsing cert\n"); + cssmPerror("CSSM_CL_CertGetFirstCachedFieldValue", crtn); + return; + } + printName(title, (CSSM_X509_NAME_PTR)field->Data); + CSSM_CL_FreeFieldValue(clHand, oid, field); + CSSM_CL_CertAbortQuery(clHand, resultHand); +} + +/* + * Print subject and/or issuer of a cert. + */ +void printCertName( + const unsigned char *cert, + unsigned certLen, + WhichName whichName) +{ + CSSM_CL_HANDLE clHand = getClHand(); + CSSM_HANDLE cacheHand; + CSSM_DATA certData = {certLen, (uint8 *)cert}; + CSSM_RETURN crtn; + bool printSubj = false; + bool printIssuer = false; + + switch(whichName) { + case NameBoth: + printSubj = true; + printIssuer = true; + break; + case NameSubject: + printSubj = true; + break; + case NameIssuer: + printIssuer = true; + break; + default: + printf("***BRRZAP! Illegal whichName argument\n"); + return; + } + + crtn = CSSM_CL_CertCache(clHand, &certData, &cacheHand); + if(crtn) { + printf("***Error parsing cert\n"); + cssmPerror("CSSM_CL_CertCache", crtn); + return; + } + + if(printSubj) { + printOneCertName(clHand, cacheHand, "Subject", &CSSMOID_X509V1SubjectNameCStruct); + } + if(printIssuer) { + printOneCertName(clHand, cacheHand, "Issuer", &CSSMOID_X509V1IssuerNameCStruct); + } + CSSM_CL_CertAbortCache(clHand, cacheHand); + return; +} diff --git a/SecurityTests/clxutils/clAppUtils/printCertName.h b/SecurityTests/clxutils/clAppUtils/printCertName.h new file mode 100644 index 00000000..bbae5140 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/printCertName.h @@ -0,0 +1,27 @@ +#ifndef _PRINT_CERT_NAME_H_ +#define _PRINT_CERT_NAME_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Print subject and/or issuer of a cert. + */ +typedef enum { + NameBoth = 0, + NameSubject, + NameIssuer +} WhichName; + +extern void printCertName( + const unsigned char *cert, + unsigned certLen, + WhichName whichName); + +#ifdef __cplusplus +} +#endif + +#endif /* _PRINT_CERT_NAME_H_ */ + diff --git a/SecurityTests/clxutils/clAppUtils/ringBufferIo.cpp b/SecurityTests/clxutils/clAppUtils/ringBufferIo.cpp new file mode 100644 index 00000000..8a4b8bb0 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/ringBufferIo.cpp @@ -0,0 +1,330 @@ +/* + * Ring buffer I/O for sslThroughput test. + */ + +#include "ringBufferIo.h" +#include +#include +#include +#include + +/* synchronizes multi-threaded access to printf() */ +pthread_mutex_t printfMutex = PTHREAD_MUTEX_INITIALIZER; + +/* initialize a RingBuffer */ +void ringBufSetup( + RingBuffer *ring, + const char *bufName, + size_t numElements, + size_t bufSize) +{ + unsigned dex; + + memset(ring, 0, sizeof(*ring)); + ring->numElements = numElements; + ring->elements = (RingElement *)malloc(sizeof(RingElement) * numElements); + memset(ring->elements, 0, sizeof(RingElement) * numElements); + for(dex=0; dexelements[dex]; + elt->buf = (unsigned char *)malloc(bufSize); + elt->capacity = bufSize; + } + ring->writerDex = 0; + ring->readerDex = 0; + ring->bufName = bufName; +} + +#define LOG_RING 0 +#define LOG_RING_DUMP 0 +#if LOG_RING + +static void logRingWrite( + RingBuffer *ring, + size_t written, + unsigned dex, + void *from) +{ + pthread_mutex_lock(&printfMutex); + printf("+++ wrote %4u bytes to %s buf %2u\n", + (unsigned)written, ring->bufName, dex); + #if LOG_RING_DUMP + { + unsigned i; + unsigned char *cp = (unsigned char *)from; + + for(i=0; ibufName, dex); + #if LOG_RING_DUMP + { + unsigned i; + unsigned char *cp = (unsigned char *)to; + + for(i=0; ibufName, dex); + pthread_mutex_unlock(&printfMutex); +} + +static void logRingClose( + RingBuffer *ring, + char *readerOrWriter) +{ + pthread_mutex_lock(&printfMutex); + printf("=== %s CLOSED by %s\n", + ring->bufName, readerOrWriter); + pthread_mutex_unlock(&printfMutex); +} + +static void logRingReset( + RingBuffer *ring) +{ + pthread_mutex_lock(&printfMutex); + printf("=== %s RESET\n", ring->bufName); + pthread_mutex_unlock(&printfMutex); +} + +#else /* LOG_RING */ +#define logRingWrite(r, w, d, t) +#define logRingRead(r, b, d, t) +#define logRingStall(r, row, d) +#define logRingClose(r, row) +#define logRingReset(r) +#endif /* LOG_RING */ + +void ringBufferReset( + RingBuffer *ring) +{ + unsigned dex; + for(dex=0; dexnumElements; dex++) { + RingElement *elt = &ring->elements[dex]; + elt->validBytes = 0; + elt->readOffset = 0; + } + ring->writerDex = 0; + ring->readerDex = 0; + ring->closed = false; + logRingReset(ring); +} + +/* + * The "I/O" callbacks for SecureTransport. + * The SSLConnectionRef is a RingBuffers *. + */ +OSStatus ringReadFunc( + SSLConnectionRef connRef, + void *data, + size_t *dataLen) /* IN/OUT */ +{ + RingBuffer *ring = ((RingBuffers *)connRef)->rdBuf; + + if(ring->writerDex == ring->readerDex) { + if(ring->closed) { + /* + * Handle race condition: we saw a stall, then writer filled a + * RingElement and then set closed. Make sure we read the data before + * handling the close event. + */ + if(ring->writerDex == ring->readerDex) { + /* writer closed: ECONNRESET */ + *dataLen = 0; + return errSSLClosedAbort; + } + /* else proceed to read data */ + } + else { + /* read stalled, writer thread is writing to our next element */ + *dataLen = 0; + return errSSLWouldBlock; + } + } + + unsigned char *outp = (unsigned char *)data; + size_t toMove = *dataLen; + size_t haveMoved = 0; + + /* we own ring->elements[ring->readerDex] */ + do { + /* + * Read as much data as there is in the buffer, or + * toMove, whichever is less + */ + RingElement *elt = &ring->elements[ring->readerDex]; + size_t thisMove = elt->validBytes; + if(thisMove > toMove) { + thisMove = toMove; + } + memmove(outp, elt->buf + elt->readOffset, thisMove); + logRingRead(ring, thisMove, ring->readerDex, outp); + if(thisMove == 0) { + /* should never happen */ + printf("***thisMove 0!\n"); + return internalComponentErr; + } + elt->validBytes -= thisMove; + elt->readOffset += thisMove; + toMove -= thisMove; + haveMoved += thisMove; + outp += thisMove; + + if(elt->validBytes == 0) { + /* + * End of this buffer - advance to next one and keep going if it's + * not in use + */ + unsigned nextDex; + elt->readOffset = 0; + /* increment and wrap must be atomic from the point of + * view of readerDex */ + nextDex = ring->readerDex + 1; + if(nextDex == ring->numElements) { + nextDex = 0; + } + ring->readerDex = nextDex; + } + if(toMove == 0) { + /* caller got what they want */ + break; + } + if(ring->readerDex == ring->writerDex) { + logRingStall(ring, "reader ", ring->readerDex); + /* stalled */ + break; + } + } while(toMove); + + OSStatus ortn = noErr; + if(haveMoved != *dataLen) { + if((haveMoved == 0) && ring->closed) { + /* writer closed: ECONNRESET */ + ortn = errSSLClosedAbort; + } + else { + ortn = errSSLWouldBlock; + } + } + *dataLen = haveMoved; + return ortn; +} + +/* + * This never returns errSSLWouldBlock - we block (spinning) if + * we stall because we run into the reader's element. + * Also, each call to this function uses up at least one + * RingElement - we don't coalesce multiple writes into one + * RingElement. + * + * On entry, writerDex is the element we're going to write to. + * On exit, writerDex is the element we're going to write to next, + * and we might stall before we update it as such. + */ +OSStatus ringWriteFunc( + SSLConnectionRef connRef, + const void *data, + size_t *dataLen) /* IN/OUT */ +{ + RingBuffer *ring = ((RingBuffers *)connRef)->wrtBuf; + unsigned char *inp = (unsigned char *)data; + size_t toMove = *dataLen; + size_t haveMoved = 0; + unsigned nextDex; + OSStatus ortn = noErr; + + /* we own ring->elements[ring->writerDex] */ + do { + RingElement *elt = &ring->elements[ring->writerDex]; + elt->validBytes = 0; + + size_t thisMove = toMove; + if(thisMove > elt->capacity) { + thisMove = elt->capacity; + } + memmove(elt->buf, inp, thisMove); + logRingWrite(ring, thisMove, ring->writerDex, inp); + + elt->validBytes = thisMove; + toMove -= thisMove; + haveMoved += thisMove; + inp += thisMove; + + /* move on to next element, when it becomes available */ + nextDex = ring->writerDex + 1; + if(nextDex == ring->numElements) { + nextDex = 0; + } + if(nextDex == ring->readerDex) { + logRingStall(ring, "writer", nextDex); + while(nextDex == ring->readerDex) { + /* if(ring->closed) { + break; + } */ + ; + /* else stall */ + } + } + /* we own nextDex */ + ring->writerDex = nextDex; + if(ring->closed) { + break; + } + } while(toMove); + if(ring->closed && (haveMoved == 0)) { + /* reader closed socket: EPIPE */ + ortn = errSSLClosedAbort; + } + *dataLen = haveMoved; + return ortn; +} + +/* close both sides of a RingBuffers */ +void ringBuffersClose( + RingBuffers *rbs) +{ + if(rbs == NULL) { + return; + } + if(rbs->rdBuf) { + logRingClose(rbs->rdBuf, "reader"); + rbs->rdBuf->closed = true; + } + if(rbs->wrtBuf) { + logRingClose(rbs->wrtBuf, "writer"); + rbs->wrtBuf->closed = true; + } +} + diff --git a/SecurityTests/clxutils/clAppUtils/ringBufferIo.h b/SecurityTests/clxutils/clAppUtils/ringBufferIo.h new file mode 100644 index 00000000..5235fdc8 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/ringBufferIo.h @@ -0,0 +1,101 @@ +/* + * Ring buffer I/O for sslThroughput test. + */ + +#ifndef _RING_BUFFER_IO_ +#define _RING_BUFFER_IO_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Reasonable defaults for Ring Buffer params */ +#define DEFAULT_NUM_RB_BUFS 16 +#define DEFAULT_BUF_RB_SIZE 2048 /* in the ring buffers */ + + +/* one element in a ring buffer */ +typedef struct { + size_t validBytes; // bytes written and not yet consumed + size_t readOffset; // next byte to be read from this offset + size_t capacity; // mallocd size of buf + unsigned char *buf; +} RingElement; + +/* + * A ring buffer shared between one writer thread and one reader thread. + * Per the DeMoney Theorem, we don't need to provide any locking between + * the two threads if we have the appropriate protocol, which is as follows: + * + * -- the RingElements at which the reader and writer are currently + * processing are indicated by readerDex and writerDex. + * -- the writer thread never advances writerDex to a RingElement + * currently in use by the reader thread. + * -- the reader thread can advance to a RingElement in use by + * the writer thread, but it can't read from that RingElement + * until the writer thread has advanced past that RingElement. + */ +typedef struct { + size_t numElements; + RingElement *elements; + unsigned writerDex; // writer thread is working on this one + unsigned readerDex; // read thread is working on this one + const char *bufName; // e.g. serverToClient + + /* + * Flag to emulate closing of socket. There's only one since the thread + * that sets this presumably will not be reading from or writing to + * this RingBuffer again; the "other" thread will detect this and abort + * as appropriate. + */ + bool closed; +} RingBuffer; + +/* + * A pair of RingBuffer ptrs suitable for use as the SSLConnectionRef + * for ringReadFunc() and ringWriteFunc(). + */ +typedef struct { + RingBuffer *rdBuf; + RingBuffer *wrtBuf; +} RingBuffers; + +void ringBufSetup( + RingBuffer *ring, + const char *bufName, + size_t numElements, + size_t bufSize); + +void ringBufferReset( + RingBuffer *ring); + +/* + * The "I/O" callbacks for SecureTransport. + * The SSLConnectionRef is a RingBuffers *. + */ +OSStatus ringReadFunc( + SSLConnectionRef connRef, + void *data, + size_t *dataLen); /* IN/OUT */ +OSStatus ringWriteFunc( + SSLConnectionRef connRef, + const void *data, + size_t *dataLen); /* IN/OUT */ + +/* close both sides of a RingBuffers */ +void ringBuffersClose( + RingBuffers *rbs); + +/* to coordinate stdio from multi threads */ +extern pthread_mutex_t printfMutex; + +#ifdef __cplusplus +} +#endif + +#endif /* _RING_BUFFER_IO_ */ diff --git a/SecurityTests/clxutils/clAppUtils/sslAppUtils.cpp b/SecurityTests/clxutils/clAppUtils/sslAppUtils.cpp new file mode 100644 index 00000000..69b15508 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/sslAppUtils.cpp @@ -0,0 +1,1653 @@ + +#include "sslAppUtils.h" +#include "sslThreading.h" +#include "identPicker.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include // for Sec errors +#include + +/* Set true when PR-3074739 is merged to TOT */ +#define NEW_SSL_ERRS_3074739 1 + +const char *sslGetCipherSuiteString(SSLCipherSuite cs) +{ + static char noSuite[40]; + + switch(cs) { + case SSL_NULL_WITH_NULL_NULL: + return "SSL_NULL_WITH_NULL_NULL"; + case SSL_RSA_WITH_NULL_MD5: + return "SSL_RSA_WITH_NULL_MD5"; + case SSL_RSA_WITH_NULL_SHA: + return "SSL_RSA_WITH_NULL_SHA"; + case SSL_RSA_EXPORT_WITH_RC4_40_MD5: + return "SSL_RSA_EXPORT_WITH_RC4_40_MD5"; + case SSL_RSA_WITH_RC4_128_MD5: + return "SSL_RSA_WITH_RC4_128_MD5"; + case SSL_RSA_WITH_RC4_128_SHA: + return "SSL_RSA_WITH_RC4_128_SHA"; + case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: + return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5"; + case SSL_RSA_WITH_IDEA_CBC_SHA: + return "SSL_RSA_WITH_IDEA_CBC_SHA"; + case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"; + case SSL_RSA_WITH_DES_CBC_SHA: + return "SSL_RSA_WITH_DES_CBC_SHA"; + case SSL_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_RSA_WITH_3DES_EDE_CBC_SHA"; + case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"; + case SSL_DH_DSS_WITH_DES_CBC_SHA: + return "SSL_DH_DSS_WITH_DES_CBC_SHA"; + case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA"; + case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"; + case SSL_DH_RSA_WITH_DES_CBC_SHA: + return "SSL_DH_RSA_WITH_DES_CBC_SHA"; + case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA"; + case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"; + case SSL_DHE_DSS_WITH_DES_CBC_SHA: + return "SSL_DHE_DSS_WITH_DES_CBC_SHA"; + case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA: + return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; + case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"; + case SSL_DHE_RSA_WITH_DES_CBC_SHA: + return "SSL_DHE_RSA_WITH_DES_CBC_SHA"; + case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; + case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: + return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5"; + case SSL_DH_anon_WITH_RC4_128_MD5: + return "SSL_DH_anon_WITH_RC4_128_MD5"; + case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA"; + case SSL_DH_anon_WITH_DES_CBC_SHA: + return "SSL_DH_anon_WITH_DES_CBC_SHA"; + case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA"; + case SSL_FORTEZZA_DMS_WITH_NULL_SHA: + return "SSL_FORTEZZA_DMS_WITH_NULL_SHA"; + case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA: + return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA"; + case SSL_RSA_WITH_RC2_CBC_MD5: + return "SSL_RSA_WITH_RC2_CBC_MD5"; + case SSL_RSA_WITH_IDEA_CBC_MD5: + return "SSL_RSA_WITH_IDEA_CBC_MD5"; + case SSL_RSA_WITH_DES_CBC_MD5: + return "SSL_RSA_WITH_DES_CBC_MD5"; + case SSL_RSA_WITH_3DES_EDE_CBC_MD5: + return "SSL_RSA_WITH_3DES_EDE_CBC_MD5"; + case SSL_NO_SUCH_CIPHERSUITE: + return "SSL_NO_SUCH_CIPHERSUITE"; + case TLS_RSA_WITH_AES_128_CBC_SHA: + return "TLS_RSA_WITH_AES_128_CBC_SHA"; + case TLS_DH_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; + case TLS_DH_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; + case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; + case TLS_RSA_WITH_AES_256_CBC_SHA: + return "TLS_RSA_WITH_AES_256_CBC_SHA"; + case TLS_DH_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; + case TLS_DH_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; + case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; + case TLS_DH_anon_WITH_AES_256_CBC_SHA: + return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; + + /* ECDSA */ + case TLS_ECDH_ECDSA_WITH_NULL_SHA: + return "TLS_ECDH_ECDSA_WITH_NULL_SHA"; + case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: + return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"; + case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"; + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"; + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"; + case TLS_ECDHE_ECDSA_WITH_NULL_SHA: + return "TLS_ECDHE_ECDSA_WITH_NULL_SHA"; + case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"; + case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"; + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"; + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"; + case TLS_ECDH_RSA_WITH_NULL_SHA: + return "TLS_ECDH_RSA_WITH_NULL_SHA"; + case TLS_ECDH_RSA_WITH_RC4_128_SHA: + return "TLS_ECDH_RSA_WITH_RC4_128_SHA"; + case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"; + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"; + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"; + case TLS_ECDHE_RSA_WITH_NULL_SHA: + return "TLS_ECDHE_RSA_WITH_NULL_SHA"; + case TLS_ECDHE_RSA_WITH_RC4_128_SHA: + return "TLS_ECDHE_RSA_WITH_RC4_128_SHA"; + case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"; + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"; + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"; + case TLS_ECDH_anon_WITH_NULL_SHA: + return "TLS_ECDH_anon_WITH_NULL_SHA"; + case TLS_ECDH_anon_WITH_RC4_128_SHA: + return "TLS_ECDH_anon_WITH_RC4_128_SHA"; + case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA: + return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"; + case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: + return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"; + case TLS_ECDH_anon_WITH_AES_256_CBC_SHA: + return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"; + + default: + sprintf(noSuite, "Unknown (%d)", (unsigned)cs); + return noSuite; + } +} + +/* + * Given a SSLProtocolVersion - typically from SSLGetProtocolVersion - + * return a string representation. + */ +const char *sslGetProtocolVersionString(SSLProtocol prot) +{ + static char noProt[20]; + + switch(prot) { + case kSSLProtocolUnknown: + return "kSSLProtocolUnknown"; + case kSSLProtocol2: + return "kSSLProtocol2"; + case kSSLProtocol3: + return "kSSLProtocol3"; + case kSSLProtocol3Only: + return "kSSLProtocol3Only"; + case kTLSProtocol1: + return "kTLSProtocol1"; + case kTLSProtocol1Only: + return "kTLSProtocol1Only"; + default: + sprintf(noProt, "Unknown (%d)", (unsigned)prot); + return noProt; + } +} + +/* + * Return string representation of SecureTransport-related OSStatus. + */ +const char *sslGetSSLErrString(OSStatus err) +{ + static char noErrStr[20]; + + switch(err) { + case noErr: + return "noErr"; + case memFullErr: + return "memFullErr"; + case paramErr: + return "paramErr"; + case unimpErr: + return "unimpErr"; + case ioErr: + return "ioErr"; + case badReqErr: + return "badReqErr"; + case errSSLProtocol: + return "errSSLProtocol"; + case errSSLNegotiation: + return "errSSLNegotiation"; + case errSSLFatalAlert: + return "errSSLFatalAlert"; + case errSSLWouldBlock: + return "errSSLWouldBlock"; + case errSSLSessionNotFound: + return "errSSLSessionNotFound"; + case errSSLClosedGraceful: + return "errSSLClosedGraceful"; + case errSSLClosedAbort: + return "errSSLClosedAbort"; + case errSSLXCertChainInvalid: + return "errSSLXCertChainInvalid"; + case errSSLBadCert: + return "errSSLBadCert"; + case errSSLCrypto: + return "errSSLCrypto"; + case errSSLInternal: + return "errSSLInternal"; + case errSSLModuleAttach: + return "errSSLModuleAttach"; + case errSSLUnknownRootCert: + return "errSSLUnknownRootCert"; + case errSSLNoRootCert: + return "errSSLNoRootCert"; + case errSSLCertExpired: + return "errSSLCertExpired"; + case errSSLCertNotYetValid: + return "errSSLCertNotYetValid"; + case errSSLClosedNoNotify: + return "errSSLClosedNoNotify"; + case errSSLBufferOverflow: + return "errSSLBufferOverflow"; + case errSSLBadCipherSuite: + return "errSSLBadCipherSuite"; + /* TLS/Panther addenda */ + case errSSLPeerUnexpectedMsg: + return "errSSLPeerUnexpectedMsg"; + case errSSLPeerBadRecordMac: + return "errSSLPeerBadRecordMac"; + case errSSLPeerDecryptionFail: + return "errSSLPeerDecryptionFail"; + case errSSLPeerRecordOverflow: + return "errSSLPeerRecordOverflow"; + case errSSLPeerDecompressFail: + return "errSSLPeerDecompressFail"; + case errSSLPeerHandshakeFail: + return "errSSLPeerHandshakeFail"; + case errSSLPeerBadCert: + return "errSSLPeerBadCert"; + case errSSLPeerUnsupportedCert: + return "errSSLPeerUnsupportedCert"; + case errSSLPeerCertRevoked: + return "errSSLPeerCertRevoked"; + case errSSLPeerCertExpired: + return "errSSLPeerCertExpired"; + case errSSLPeerCertUnknown: + return "errSSLPeerCertUnknown"; + case errSSLIllegalParam: + return "errSSLIllegalParam"; + case errSSLPeerUnknownCA: + return "errSSLPeerUnknownCA"; + case errSSLPeerAccessDenied: + return "errSSLPeerAccessDenied"; + case errSSLPeerDecodeError: + return "errSSLPeerDecodeError"; + case errSSLPeerDecryptError: + return "errSSLPeerDecryptError"; + case errSSLPeerExportRestriction: + return "errSSLPeerExportRestriction"; + case errSSLPeerProtocolVersion: + return "errSSLPeerProtocolVersion"; + case errSSLPeerInsufficientSecurity: + return "errSSLPeerInsufficientSecurity"; + case errSSLPeerInternalError: + return "errSSLPeerInternalError"; + case errSSLPeerUserCancelled: + return "errSSLPeerUserCancelled"; + case errSSLPeerNoRenegotiation: + return "errSSLPeerNoRenegotiation"; + case errSSLHostNameMismatch: + return "errSSLHostNameMismatch"; + case errSSLConnectionRefused: + return "errSSLConnectionRefused"; + case errSSLDecryptionFail: + return "errSSLDecryptionFail"; + case errSSLBadRecordMac: + return "errSSLBadRecordMac"; + case errSSLRecordOverflow: + return "errSSLRecordOverflow"; + case errSSLBadConfiguration: + return "errSSLBadConfiguration"; + + /* some from the Sec layer */ + case errSecNotAvailable: return "errSecNotAvailable"; + case errSecReadOnly: return "errSecReadOnly"; + case errSecAuthFailed: return "errSecAuthFailed"; + case errSecNoSuchKeychain: return "errSecNoSuchKeychain"; + case errSecInvalidKeychain: return "errSecInvalidKeychain"; + case errSecDuplicateItem: return "errSecDuplicateItem"; + case errSecItemNotFound: return "errSecItemNotFound"; + case errSecNoSuchAttr: return "errSecNoSuchAttr"; + case errSecInvalidItemRef: return "errSecInvalidItemRef"; + case errSecInvalidSearchRef: return "errSecInvalidSearchRef"; + case errSecNoSuchClass: return "errSecNoSuchClass"; + case errSecNoDefaultKeychain: return "errSecNoDefaultKeychain"; + case errSecWrongSecVersion: return "errSecWrongSecVersion"; + case errSessionInvalidId: return "errSessionInvalidId"; + case errSessionInvalidAttributes: return "errSessionInvalidAttributes"; + case errSessionAuthorizationDenied: return "errSessionAuthorizationDenied"; + case errSessionInternal: return "errSessionInternal"; + case errSessionInvalidFlags: return "errSessionInvalidFlags"; + case errSecInvalidTrustSettings: return "errSecInvalidTrustSettings"; + case errSecNoTrustSettings: return "errSecNoTrustSettings"; + + default: + if(err < (CSSM_BASE_ERROR + + (CSSM_ERRORCODE_MODULE_EXTENT * 8))) { + /* assume CSSM error */ + return cssmErrToStr(err); + } + else { + sprintf(noErrStr, "Unknown (%d)", (unsigned)err); + return noErrStr; + } + } +} + +void printSslErrStr( + const char *op, + OSStatus err) +{ + printf("*** %s: %s\n", op, sslGetSSLErrString(err)); +} + +const char *sslGetClientCertStateString(SSLClientCertificateState state) +{ + static char noState[20]; + + switch(state) { + case kSSLClientCertNone: + return "ClientCertNone"; + case kSSLClientCertRequested: + return "CertRequested"; + case kSSLClientCertSent: + return "ClientCertSent"; + case kSSLClientCertRejected: + return "ClientCertRejected"; + default: + sprintf(noState, "Unknown (%d)", (unsigned)state); + return noState; + } + +} + +const char *sslGetClientAuthTypeString(SSLClientAuthenticationType authType) +{ + static char noType[20]; + + switch(authType) { + case SSLClientAuthNone: + return "None"; + case SSLClientAuth_RSASign: + return "RSASign"; + case SSLClientAuth_DSSSign: + return "DSSSign"; + case SSLClientAuth_RSAFixedDH: + return "RSAFixedDH"; + case SSLClientAuth_DSS_FixedDH: + return "DSS_FixedDH"; + case SSLClientAuth_ECDSASign: + return "ECDSASign"; + case SSLClientAuth_RSAFixedECDH: + return "RSAFixedECDH"; + case SSLClientAuth_ECDSAFixedECDH: + return "ECDSAFixedECDH"; + default: + sprintf(noType, "Unknown (%d)", (unsigned)authType); + return noType; + } +} + +/* + * Convert a keychain name (which may be NULL) into the CFArrayRef required + * by SSLSetCertificate. This is a bare-bones example of this operation, + * since it requires and assumes that there is exactly one SecIdentity + * in the keychain - i.e., there is exactly one matching cert/private key + * pair. A real world server would probably search a keychain for a SecIdentity + * matching some specific criteria. + */ +CFArrayRef getSslCerts( + const char *kcName, // may be NULL, i.e., use default + CSSM_BOOL encryptOnly, + CSSM_BOOL completeCertChain, + const char *anchorFile, // optional trusted anchor + SecKeychainRef *pKcRef) // RETURNED +{ + SecKeychainRef kcRef = nil; + OSStatus ortn; + + *pKcRef = nil; + + /* pick a keychain */ + if(kcName) { + ortn = SecKeychainOpen(kcName, &kcRef); + if(ortn) { + printf("SecKeychainOpen returned %d.\n", (int)ortn); + printf("Cannot open keychain at %s. Aborting.\n", kcName); + return NULL; + } + } + else { + /* use default keychain */ + ortn = SecKeychainCopyDefault(&kcRef); + if(ortn) { + printf("SecKeychainCopyDefault returned %d; aborting.\n", (int)ortn); + return nil; + } + } + *pKcRef = kcRef; + return sslKcRefToCertArray(kcRef, encryptOnly, completeCertChain, + NULL, // SSL policy + anchorFile); +} + +/* + * Determine if specified SecCertificateRef is a self-signed cert. + * We do this by comparing the subject and issuerr names; no cryptographic + * verification is performed. + * + * Returns true if the cert appears to be a root. + */ +static bool isCertRefRoot( + SecCertificateRef certRef) +{ + /* just search for the two attrs we want */ + UInt32 tags[2] = {kSecSubjectItemAttr, kSecIssuerItemAttr}; + SecKeychainAttributeInfo attrInfo; + attrInfo.count = 2; + attrInfo.tag = tags; + attrInfo.format = NULL; + SecKeychainAttributeList *attrList = NULL; + SecKeychainAttribute *attr1 = NULL; + SecKeychainAttribute *attr2 = NULL; + bool brtn = false; + + OSStatus ortn = SecKeychainItemCopyAttributesAndData( + (SecKeychainItemRef)certRef, + &attrInfo, + NULL, // itemClass + &attrList, + NULL, // length - don't need the data + NULL); // outData + if(ortn) { + cssmPerror("SecKeychainItemCopyAttributesAndData", ortn); + /* may want to be a bit more robust here, but this should + * never happen */ + return false; + } + /* subsequent errors to errOut: */ + + if((attrList == NULL) || (attrList->count != 2)) { + printf("***Unexpected result fetching label attr\n"); + goto errOut; + } + + /* rootness is just byte-for-byte compare of the two names */ + attr1 = &attrList->attr[0]; + attr2 = &attrList->attr[1]; + if(attr1->length == attr2->length) { + if(memcmp(attr1->data, attr2->data, attr1->length) == 0) { + brtn = true; + } + } +errOut: + SecKeychainItemFreeAttributesAndData(attrList, NULL); + return brtn; +} + + +/* + * Given a SecIdentityRef, do our best to construct a complete, ordered, and + * verified cert chain, returning the result in a CFArrayRef. The result is + * suitable for use when calling SSLSetCertificate(). + */ +OSStatus sslCompleteCertChain( + SecIdentityRef identity, + SecCertificateRef trustedAnchor, // optional additional trusted anchor + bool includeRoot, // include the root in outArray + const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL + CFArrayRef *outArray) // created and RETURNED +{ + CFMutableArrayRef certArray; + SecTrustRef secTrust = NULL; + SecPolicyRef policy = NULL; + SecPolicySearchRef policySearch = NULL; + SecTrustResultType secTrustResult; + CSSM_TP_APPLE_EVIDENCE_INFO *dummyEv; // not used + CFArrayRef certChain = NULL; // constructed chain + CFIndex numResCerts; + + certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(certArray, identity); + + /* + * Case 1: identity is a root; we're done. Note that this case + * overrides the includeRoot argument. + */ + SecCertificateRef certRef; + OSStatus ortn = SecIdentityCopyCertificate(identity, &certRef); + if(ortn) { + /* should never happen */ + cssmPerror("SecIdentityCopyCertificate", ortn); + return ortn; + } + bool isRoot = isCertRefRoot(certRef); + if(isRoot) { + *outArray = certArray; + CFRelease(certRef); + return noErr; + } + + /* + * Now use SecTrust to get a complete cert chain, using all of the + * user's keychains to look for intermediate certs. + * NOTE this does NOT handle root certs which are not in the system + * root cert DB. (The above case, where the identity is a root cert, does.) + */ + CFMutableArrayRef subjCerts = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks); + CFArraySetValueAtIndex(subjCerts, 0, certRef); + + /* the array owns the subject cert ref now */ + CFRelease(certRef); + + /* Get a SecPolicyRef for SSL cert chain verification */ + ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3, + vfyPolicy ? vfyPolicy : &CSSMOID_APPLE_TP_SSL, + NULL, // value + &policySearch); + if(ortn) { + cssmPerror("SecPolicySearchCreate", ortn); + goto errOut; + } + ortn = SecPolicySearchCopyNext(policySearch, &policy); + if(ortn) { + cssmPerror("SecPolicySearchCopyNext", ortn); + goto errOut; + } + + /* build a SecTrustRef for specified policy and certs */ + ortn = SecTrustCreateWithCertificates(subjCerts, + policy, &secTrust); + if(ortn) { + cssmPerror("SecTrustCreateWithCertificates", ortn); + goto errOut; + } + + if(trustedAnchor) { + /* + * Tell SecTrust to trust this one in addition to the current + * trusted system-wide anchors. + */ + CFMutableArrayRef newAnchors; + CFArrayRef currAnchors; + + ortn = SecTrustCopyAnchorCertificates(&currAnchors); + if(ortn) { + /* should never happen */ + cssmPerror("SecTrustCopyAnchorCertificates", ortn); + goto errOut; + } + newAnchors = CFArrayCreateMutableCopy(NULL, + CFArrayGetCount(currAnchors) + 1, + currAnchors); + CFRelease(currAnchors); + CFArrayAppendValue(newAnchors, trustedAnchor); + ortn = SecTrustSetAnchorCertificates(secTrust, newAnchors); + CFRelease(newAnchors); + if(ortn) { + cssmPerror("SecTrustSetAnchorCertificates", ortn); + goto errOut; + } + } + /* evaluate: GO */ + ortn = SecTrustEvaluate(secTrust, &secTrustResult); + if(ortn) { + cssmPerror("SecTrustEvaluate", ortn); + goto errOut; + } + switch(secTrustResult) { + case kSecTrustResultUnspecified: + /* cert chain valid, no special UserTrust assignments */ + case kSecTrustResultProceed: + /* cert chain valid AND user explicitly trusts this */ + break; + default: + /* + * Cert chain construction failed. + * Just go with the single subject cert we were given. + */ + printf("***Warning: could not construct completed cert chain\n"); + ortn = noErr; + goto errOut; + } + + /* get resulting constructed cert chain */ + ortn = SecTrustGetResult(secTrust, &secTrustResult, &certChain, &dummyEv); + if(ortn) { + cssmPerror("SecTrustEvaluate", ortn); + goto errOut; + } + + /* + * Copy certs from constructed chain to our result array, skipping + * the leaf (which is already there, as a SecIdentityRef) and possibly + * a root. + */ + numResCerts = CFArrayGetCount(certChain); + if(numResCerts < 2) { + /* + * Can't happen: if subject was a root, we'd already have returned. + * If chain doesn't verify to a root, we'd have bailed after + * SecTrustEvaluate(). + */ + printf("***sslCompleteCertChain screwup: numResCerts %d\n", + (int)numResCerts); + ortn = noErr; + goto errOut; + } + if(!includeRoot) { + /* skip the last (root) cert) */ + numResCerts--; + } + for(CFIndex dex=1; dexacceptedProts) { + printf(" Allowed SSL versions : %s\n", params->acceptedProts); + } + else { + printf(" Attempted SSL version : %s\n", + sslGetProtocolVersionString(params->tryVersion)); + } + printf(" Result : %s\n", sslGetSSLErrString(params->ortn)); + printf(" Negotiated SSL version : %s\n", + sslGetProtocolVersionString(params->negVersion)); + printf(" Negotiated CipherSuite : %s\n", + sslGetCipherSuiteString(params->negCipher)); + if(params->certState != kSSLClientCertNone) { + printf(" Client Cert State : %s\n", + sslGetClientCertStateString(params->certState)); + } +} + +/* print a '.' every few seconds to keep UI alive while connecting */ +static CFAbsoluteTime lastTime = (CFAbsoluteTime)0.0; +#define TIME_INTERVAL 3.0 + +void sslOutputDot() +{ + CFAbsoluteTime thisTime = CFAbsoluteTimeGetCurrent(); + + if(lastTime == 0.0) { + /* avoid printing first time thru */ + lastTime = thisTime; + return; + } + if((thisTime - lastTime) >= TIME_INTERVAL) { + printf("."); fflush(stdout); + lastTime = thisTime; + } +} + +/* main server pthread body */ +static void *sslServerThread(void *arg) +{ + SslAppTestParams *testParams = (SslAppTestParams *)arg; + OSStatus status; + + status = sslAppServe(testParams); + pthread_exit((void*)status); + /* NOT REACHED */ + return (void *)status; +} + +/* + * Run one session, with the server in a separate thread. + * On entry, serverParams->port is the port we attempt to run on; + * the server thread may overwrite that with a different port if it's + * unable to open the port we specify. Whatever is left in + * serverParams->port is what's used for the client side. + */ +#define CLIENT_WAIT_SECONDS 1 +int sslRunSession( + SslAppTestParams*serverParams, + SslAppTestParams *clientParams, + const char *testDesc) +{ + pthread_t serverPthread; + OSStatus clientRtn; + void *serverRtn; + + if(testDesc && !clientParams->quiet) { + printf("===== %s =====\n", testDesc); + } + + /* + * Workaround for Radar 4619502: resolve references to Security.framework + * here, in main thread, before we fork off the server thread. + */ + SecKeychainRef defaultKc = NULL; + SecKeychainCopyDefault(&defaultKc); + /* end workaround */ + + if(pthread_mutex_init(&serverParams->pthreadMutex, NULL)) { + printf("***Error initializing mutex; aborting.\n"); + return -1; + } + if(pthread_cond_init(&serverParams->pthreadCond, NULL)) { + printf("***Error initializing pthreadCond; aborting.\n"); + return -1; + } + serverParams->serverReady = false; // server sets true + + int result = pthread_create(&serverPthread, NULL, + sslServerThread, serverParams); + if(result) { + printf("***Error starting up server thread; aborting.\n"); + return result; + } + + /* wait for server to set up a socket we can connect to */ + if(pthread_mutex_lock(&serverParams->pthreadMutex)) { + printf("***Error acquiring server lock; aborting.\n"); + return -1; + } + while(!serverParams->serverReady) { + if(pthread_cond_wait(&serverParams->pthreadCond, &serverParams->pthreadMutex)) { + printf("***Error waiting server thread; aborting.\n"); + return -1; + } + } + pthread_mutex_unlock(&serverParams->pthreadMutex); + pthread_cond_destroy(&serverParams->pthreadCond); + pthread_mutex_destroy(&serverParams->pthreadMutex); + + clientParams->port = serverParams->port; + clientRtn = sslAppClient(clientParams); + /* server doesn't shut down its socket until it sees this */ + serverParams->clientDone = 1; + result = pthread_join(serverPthread, &serverRtn); + if(result) { + printf("***pthread_join returned %d, aborting\n", result); + return result; + } + + if(serverParams->verbose) { + sslShowResult("server", serverParams); + } + if(clientParams->verbose) { + sslShowResult("client", clientParams); + } + + /* verify results */ + int ourRtn = 0; + ourRtn += sslVerifyRtn("server", serverParams->expectRtn, serverParams->ortn); + ourRtn += sslVerifyRtn("client", clientParams->expectRtn, clientParams->ortn); + ourRtn += sslVerifyProtVers("server", serverParams->expectVersion, + serverParams->negVersion); + ourRtn += sslVerifyProtVers("client", clientParams->expectVersion, + clientParams->negVersion); + ourRtn += sslVerifyClientCertState("server", serverParams->expectCertState, + serverParams->certState); + ourRtn += sslVerifyClientCertState("client", clientParams->expectCertState, + clientParams->certState); + if(serverParams->ortn == noErr) { + ourRtn += sslVerifyCipher("server", serverParams->expectCipher, + serverParams->negCipher); + } + if(clientParams->ortn == noErr) { + ourRtn += sslVerifyCipher("client", clientParams->expectCipher, + clientParams->negCipher); + } + + if(defaultKc) { + /* for workaround for Radar 4619502 */ + CFRelease(defaultKc); + } + return ourRtn; +} + +/* + * Add all of the roots in a given KC to SSL ctx's trusted anchors. + */ +OSStatus sslAddTrustedRoots( + SSLContextRef ctx, + SecKeychainRef keychain, + bool *foundOne) // RETURNED, true if we found + // at least one root cert +{ + OSStatus ortn; + SecCertificateRef secCert; + SecKeychainSearchRef srch; + + *foundOne = false; + ortn = SecKeychainSearchCreateFromAttributes(keychain, + kSecCertificateItemClass, + NULL, // any attrs + &srch); + if(ortn) { + printSslErrStr("SecKeychainSearchCreateFromAttributes", ortn); + return ortn; + } + + /* + * Only use root certs. Not an error if we don't find any. + */ + do { + ortn = SecKeychainSearchCopyNext(srch, + (SecKeychainItemRef *)&secCert); + if(ortn) { + break; + } + + /* see if it's a root */ + if(!isCertRefRoot(secCert)) { + continue; + } + + /* Tell Secure Transport to trust this one. */ + ortn = addTrustedSecCert(ctx, secCert, false); + if(ortn) { + /* fatal */ + printSslErrStr("addTrustedSecCert", ortn); + return ortn; + } + CFRelease(secCert); + *foundOne = true; + } while(ortn == noErr); + CFRelease(srch); + return noErr; +} + +/* + * Wrapper for sslIdentPicker, with optional trusted anchor specified as a filename. + */ +OSStatus sslIdentityPicker( + SecKeychainRef kcRef, // NULL means use default list + const char *trustedAnchor, // optional additional trusted anchor + bool includeRoot, // true --> root is appended to outArray + // false --> root not included + const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL + CFArrayRef *outArray) // created and RETURNED +{ + SecCertificateRef trustedCert = NULL; + OSStatus ortn; + + if(trustedAnchor) { + ortn = sslReadAnchor(trustedAnchor, &trustedCert); + if(ortn) { + printf("***Error reading %s. sslIdentityPicker proceeding with no anchor.\n", + trustedAnchor); + trustedCert = NULL; + } + } + ortn = sslIdentPicker(kcRef, trustedCert, includeRoot, vfyPolicy, outArray); + if(trustedCert) { + CFRelease(trustedCert); + } + return ortn; +} + +/* + * Given a keychain name, convert it into a full path using the "SSL regression + * test suite algorithm". The Sec layer by default locates root root's keychains + * in different places depending on whether we're actually logged in as root + * or running via e.g. cron, so we force the location of root keychains to + * a hard-coded path. User keychain names we leave alone. + * This has to be kept in sync with the sslKcSetup script fragment in + * sslScripts. + */ +void sslKeychainPath( + const char *kcName, + char *kcPath) // allocd by caller, MAXPATHLEN +{ + if(kcName[0] == '\0') { + kcPath[0] = '\0'; + } + else if(geteuid() == 0) { + /* root */ + const char *buildDir = getenv("LOCAL_BUILD_DIR"); + if(buildDir == NULL) { + buildDir = ""; + } + sprintf(kcPath, "%s/Library/Keychains/%s", buildDir, kcName); + } + else { + /* user, leave alone */ + strcpy(kcPath, kcName); + } +} + +/* Verify presence of required file. Returns nonzero if not found. */ +int sslCheckFile(const char *path) +{ + struct stat sb; + + if(stat(path, &sb)) { + printf("***Can't find file %s.\n", path); + printf(" Try running in the build directory, perhaps after running the\n" + " makeLocalCert script.\n"); + return 1; + } + return 0; +} + +/* Stringify a SSL_ECDSA_NamedCurve */ +extern const char *sslCurveString( + SSL_ECDSA_NamedCurve namedCurve) +{ + static char unk[100]; + + switch(namedCurve) { + case SSL_Curve_None: return "Curve_None"; + case SSL_Curve_secp256r1: return "secp256r1"; + case SSL_Curve_secp384r1: return "secp384r1"; + case SSL_Curve_secp521r1: return "secp521r1"; + default: + sprintf(unk, "Unknown <%d>", (int)namedCurve); + return unk; + } +} + diff --git a/SecurityTests/clxutils/clAppUtils/sslAppUtils.h b/SecurityTests/clxutils/clAppUtils/sslAppUtils.h new file mode 100644 index 00000000..ec009c1e --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/sslAppUtils.h @@ -0,0 +1,159 @@ +#ifndef _SSLS_APP_UTILS_H_ +#define _SSLS_APP_UTILS_H_ 1 + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* disable some Panther-only features */ +#define JAGUAR_BUILD 0 + +const char *sslGetCipherSuiteString(SSLCipherSuite cs); +const char *sslGetProtocolVersionString(SSLProtocol prot); +const char *sslGetSSLErrString(OSStatus err); +void printSslErrStr(const char *op, OSStatus err); +const char *sslGetClientCertStateString(SSLClientCertificateState state); +const char *sslGetClientAuthTypeString(SSLClientAuthenticationType authType); + +CFArrayRef getSslCerts( + const char *kcName, // may be NULL, i.e., use default + CSSM_BOOL encryptOnly, + CSSM_BOOL completeCertChain, + const char *anchorFile, // optional trusted anchor + SecKeychainRef *pKcRef); // RETURNED +OSStatus sslCompleteCertChain( + SecIdentityRef identity, + SecCertificateRef trustedAnchor, // optional additional trusted anchor + bool includeRoot, // include the root in outArray + const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL + CFArrayRef *outArray); // created and RETURNED +CFArrayRef sslKcRefToCertArray( + SecKeychainRef kcRef, + CSSM_BOOL encryptOnly, + CSSM_BOOL completeCertChain, + const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL policy to complete + const char *trustedAnchorFile); + +OSStatus addTrustedSecCert( + SSLContextRef ctx, + SecCertificateRef secCert, + CSSM_BOOL replaceAnchors); +OSStatus sslReadAnchor( + const char *anchorFile, + SecCertificateRef *certRef); +OSStatus sslAddTrustedRoot( + SSLContextRef ctx, + const char *anchorFile, + CSSM_BOOL replaceAnchors); + +/* + * Assume incoming identity contains a root (e.g., created by + * certtool) and add that cert to ST's trusted anchors. This + * enables ST's verify of the incoming chain to succeed without + * a kludgy "AllowAnyRoot" specification. + */ +OSStatus addIdentityAsTrustedRoot( + SSLContextRef ctx, + CFArrayRef identArray); + +OSStatus sslAddTrustedRoots( + SSLContextRef ctx, + SecKeychainRef keychain, + bool *foundOne); + +void sslOutputDot(); + +/* + * Lists of SSLCipherSuites used in sslSetCipherRestrictions. + */ +extern const SSLCipherSuite suites40[]; +extern const SSLCipherSuite suitesDES[]; +extern const SSLCipherSuite suitesDES40[]; +extern const SSLCipherSuite suites3DES[]; +extern const SSLCipherSuite suitesRC4[]; +extern const SSLCipherSuite suitesRC4_40[]; +extern const SSLCipherSuite suitesRC2[]; +extern const SSLCipherSuite suitesAES128[]; +extern const SSLCipherSuite suitesAES256[]; +extern const SSLCipherSuite suitesDH[]; +extern const SSLCipherSuite suitesDHAnon[]; +extern const SSLCipherSuite suitesDH_RSA[]; +extern const SSLCipherSuite suitesDH_DSS[]; +extern const SSLCipherSuite suites_SHA1[]; +extern const SSLCipherSuite suites_MD5[]; +extern const SSLCipherSuite suites_ECDHE[]; +extern const SSLCipherSuite suites_ECDH[]; + +/* + * Given an SSLContextRef and an array of SSLCipherSuites, terminated by + * SSL_NO_SUCH_CIPHERSUITE, select those SSLCipherSuites which the library + * supports and do a SSLSetEnabledCiphers() specifying those. + */ +OSStatus sslSetEnabledCiphers( + SSLContextRef ctx, + const SSLCipherSuite *ciphers); + +/* + * Specify restricted sets of cipherspecs and protocols. + */ +OSStatus sslSetCipherRestrictions( + SSLContextRef ctx, + char cipherRestrict); + +#ifndef SPHINX +OSStatus sslSetProtocols( + SSLContextRef ctx, + const char *acceptedProts, + SSLProtocol tryVersion); // only used if acceptedProts NULL +#endif + +int sslVerifyRtn( + const char *whichSide, // "client" or "server" + OSStatus expectRtn, + OSStatus gotRtn); +int sslVerifyProtVers( + const char *whichSide, // "client" or "server" + SSLProtocol expectProt, + SSLProtocol gotProt); +int sslVerifyClientCertState( + const char *whichSide, // "client" or "server" + SSLClientCertificateState expectState, + SSLClientCertificateState gotState); +int sslVerifyCipher( + const char *whichSide, // "client" or "server" + SSLCipherSuite expectCipher, + SSLCipherSuite gotCipher); + + +/* + * Wrapper for sslIdentPicker, with optional trusted anchor specified as a filename. + */ +OSStatus sslIdentityPicker( + SecKeychainRef kcRef, // NULL means use default list + const char *trustedAnchor, // optional additional trusted anchor + bool includeRoot, // true --> root is appended to outArray + // false --> root not included + const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL + CFArrayRef *outArray); // created and RETURNED + +void sslKeychainPath( + const char *kcName, + char *kcPath); // allocd by caller, MAXPATHLEN + +/* Verify presence of required file. Returns nonzero if not found. */ +int sslCheckFile(const char *path); + +/* Stringify a SSL_ECDSA_NamedCurve */ +extern const char *sslCurveString( + SSL_ECDSA_NamedCurve namedCurve); + +#ifdef __cplusplus +} +#endif + +#endif /* _SSLS_APP_UTILS_H_ */ diff --git a/SecurityTests/clxutils/clAppUtils/sslClient.cpp b/SecurityTests/clxutils/clAppUtils/sslClient.cpp new file mode 100644 index 00000000..053f8cf7 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/sslClient.cpp @@ -0,0 +1,212 @@ +/* + * sslClient.cpp : perform one SSL client side sesssion + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* when true, keep listening until server disconnects */ +#define KEEP_CONNECTED 1 + +#define CLIENT_GETMSG "GET / HTTP/1.0\r\n\r\n" + +#define READBUF_LEN 256 + +/* relies on SSLSetProtocolVersionEnabled */ +OSStatus sslAppClient( + SslAppTestParams *params) +{ + PeerSpec peerId; + otSocket sock = 0; + OSStatus ortn; + SSLContextRef ctx = NULL; + SecKeychainRef clientKc = nil; + CFArrayRef clientCerts = nil; + RingBuffers ringBufs = {params->serverToClientRing, params->clientToServerRing}; + + sslThrDebug("Client", "starting"); + params->negVersion = kSSLProtocolUnknown; + params->negCipher = SSL_NULL_WITH_NULL_NULL; + params->ortn = noHardwareErr; + + if(params->serverToClientRing == NULL) { + /* first make sure requested server is there */ + ortn = MakeServerConnection(params->hostName, params->port, + params->nonBlocking, &sock, &peerId); + if(ortn) { + printf("MakeServerConnection returned %d; aborting\n", (int)ortn); + return ortn; + } + } + + /* + * Set up a SecureTransport session. + */ + ortn = SSLNewContext(false, &ctx); + if(ortn) { + printSslErrStr("SSLNewContext", ortn); + goto cleanup; + } + if(params->serverToClientRing) { + ortn = SSLSetIOFuncs(ctx, ringReadFunc, ringWriteFunc); + if(ortn) { + printSslErrStr("SSLSetIOFuncs", ortn); + goto cleanup; + } + ortn = SSLSetConnection(ctx, (SSLConnectionRef)&ringBufs); + if(ortn) { + printSslErrStr("SSLSetConnection", ortn); + goto cleanup; + } + } + else { + ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite); + if(ortn) { + printSslErrStr("SSLSetIOFuncs", ortn); + goto cleanup; + } + ortn = SSLSetConnection(ctx, (SSLConnectionRef)sock); + if(ortn) { + printSslErrStr("SSLSetConnection", ortn); + goto cleanup; + } + } + if(!params->skipHostNameCheck) { + ortn = SSLSetPeerDomainName(ctx, params->hostName, + strlen(params->hostName) + 1); + if(ortn) { + printSslErrStr("SSLSetPeerDomainName", ortn); + goto cleanup; + } + } + + /* remainder of setup is optional */ + if(params->anchorFile) { + ortn = sslAddTrustedRoot(ctx, params->anchorFile, params->replaceAnchors); + if(ortn) { + goto cleanup; + } + } + if(!params->noProtSpec) { + ortn = sslSetProtocols(ctx, params->acceptedProts, params->tryVersion); + if(ortn) { + goto cleanup; + } + } + if(params->resumeEnable) { + ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec)); + if(ortn) { + printSslErrStr("SSLSetPeerID", ortn); + goto cleanup; + } + } + if(params->disableCertVerify) { + ortn = SSLSetEnableCertVerify(ctx, false); + if(ortn) { + printSslErrStr("SSLSetEnableCertVerify", ortn); + goto cleanup; + } + } + if(params->ciphers != NULL) { + ortn = sslSetEnabledCiphers(ctx, params->ciphers); + if(ortn) { + goto cleanup; + } + } + if(params->myCertKcName) { + clientCerts = getSslCerts(params->myCertKcName, CSSM_FALSE, CSSM_FALSE, NULL, &clientKc); + if(clientCerts == nil) { + exit(1); + } + if(params->password) { + ortn = SecKeychainUnlock(clientKc, strlen(params->password), + (void *)params->password, true); + if(ortn) { + printf("SecKeychainUnlock returned %d\n", (int)ortn); + /* oh well */ + } + } + if(params->idIsTrustedRoot) { + /* assume this is a root we want to implicitly trust */ + ortn = addIdentityAsTrustedRoot(ctx, clientCerts); + if(ortn) { + goto cleanup; + } + } + ortn = SSLSetCertificate(ctx, clientCerts); + if(ortn) { + printSslErrStr("SSLSetCertificate", ortn); + goto cleanup; + } + } + do { + ortn = SSLHandshake(ctx); + if((ortn == errSSLWouldBlock) && !params->silent) { + /* keep UI responsive */ + sslOutputDot(); + } + } while (ortn == errSSLWouldBlock); + + SSLGetClientCertificateState(ctx, ¶ms->certState); + SSLGetNegotiatedCipher(ctx, ¶ms->negCipher); + SSLGetNegotiatedProtocolVersion(ctx, ¶ms->negVersion); + + if(ortn != noErr) { + goto cleanup; + } + + /* send a GET msg */ + size_t actLen; + ortn = SSLWrite(ctx, CLIENT_GETMSG, strlen(CLIENT_GETMSG), &actLen); + if(ortn) { + printSslErrStr("SSLWrite", ortn); + goto cleanup; + } + + #if KEEP_CONNECTED + + /* + * Consume any server data and wait for server to disconnect + */ + char readBuf[READBUF_LEN]; + do { + ortn = SSLRead(ctx, readBuf, READBUF_LEN, &actLen); + } while (ortn == errSSLWouldBlock); + + /* convert normal "shutdown" into zero err rtn */ + if(ortn == errSSLClosedGraceful) { + ortn = noErr; + } + #endif /* KEEP_CONNECTED */ + +cleanup: + if(ctx) { + OSStatus cerr = SSLClose(ctx); + if(ortn == noErr) { + ortn = cerr; + } + } + if(sock) { + endpointShutdown(sock); + } + ringBuffersClose(&ringBufs); /* tolerates NULLs */ + if(ctx) { + SSLDisposeContext(ctx); + } + params->ortn = ortn; + sslThrDebug("Client", "done"); + return ortn; +} diff --git a/SecurityTests/clxutils/clAppUtils/sslRingBufferThreads.cpp b/SecurityTests/clxutils/clAppUtils/sslRingBufferThreads.cpp new file mode 100644 index 00000000..fc805202 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/sslRingBufferThreads.cpp @@ -0,0 +1,304 @@ +/* + * sslRingBufferThreads.cpp - SecureTransport client and server thread + * routines which use ringBufferIo for I/O (no sockets). + */ + +#include "sslRingBufferThreads.h" +#include +#include +#include +#include +#include +#include + +#define LOG_TOP_IO 0 +#if LOG_TOP_IO + +static void logWrite( + char *who, + size_t written) +{ + pthread_mutex_lock(&printfMutex); + printf("+++ %s wrote %4lu bytes\n", who, (unsigned long)written); + pthread_mutex_unlock(&printfMutex); +} + +static void logRead( + char *who, + size_t bytesRead) +{ + pthread_mutex_lock(&printfMutex); + printf("+++ %s read %4lu bytes\n", who, (unsigned long)bytesRead); + pthread_mutex_unlock(&printfMutex); +} + +#else /* LOG_TOP_IO */ +#define logWrite(who, w) +#define logRead(who, r) +#endif /* LOG_TOP_IO */ + +/* client thread - handshake and write a ton of data */ +void *sslRbClientThread(void *arg) +{ + SslRingBufferArgs *sslArgs = (SslRingBufferArgs *)arg; + OSStatus ortn; + SSLContextRef ctx = NULL; + RingBuffers ringBufs = {sslArgs->ringRead, sslArgs->ringWrite}; + unsigned toMove = 0; + unsigned thisMove; + + ortn = SSLNewContext(false, &ctx); + if(ortn) { + printSslErrStr("SSLNewContext", ortn); + goto cleanup; + } + ortn = SSLSetIOFuncs(ctx, ringReadFunc, ringWriteFunc); + if(ortn) { + printSslErrStr("SSLSetIOFuncs", ortn); + goto cleanup; + } + ortn = SSLSetConnection(ctx, (SSLConnectionRef)&ringBufs); + if(ortn) { + printSslErrStr("SSLSetConnection", ortn); + goto cleanup; + } + ortn = SSLSetEnabledCiphers(ctx, &sslArgs->cipherSuite, 1); + if(ortn) { + printSslErrStr("SSLSetEnabledCiphers", ortn); + goto cleanup; + } + if(sslArgs->idArray) { + ortn = SSLSetCertificate(ctx, sslArgs->idArray); + if(ortn) { + printSslErrStr("SSLSetCertificate", ortn); + goto cleanup; + } + } + if(sslArgs->trustedRoots) { + ortn = SSLSetTrustedRoots(ctx, sslArgs->trustedRoots, true); + if(ortn) { + printSslErrStr("SSLSetTrustedRoots", ortn); + goto cleanup; + } + } + SSLSetProtocolVersionEnabled(ctx, kSSLProtocolAll, false); + ortn = SSLSetProtocolVersionEnabled(ctx, sslArgs->prot, true); + if(ortn) { + printSslErrStr("SSLSetProtocolVersionEnabled", ortn); + goto cleanup; + } + + /* tell main thread we're ready; wait for sync flag */ + sslArgs->iAmReady = true; + while(!(*sslArgs->goFlag)) { + if(*sslArgs->abortFlag) { + goto cleanup; + } + } + + /* GO handshake */ + sslArgs->startHandshake = CFAbsoluteTimeGetCurrent(); + do { + ortn = SSLHandshake(ctx); + if(*sslArgs->abortFlag) { + goto cleanup; + } + } while (ortn == errSSLWouldBlock); + + if(ortn) { + printSslErrStr("SSLHandshake", ortn); + goto cleanup; + } + + SSLGetNegotiatedCipher(ctx, &sslArgs->negotiatedCipher); + SSLGetNegotiatedProtocolVersion(ctx, &sslArgs->negotiatedProt); + + sslArgs->startData = CFAbsoluteTimeGetCurrent(); + + toMove = sslArgs->xferSize; + + if(toMove == 0) { + sslArgs->endData = sslArgs->startData; + goto cleanup; + } + + /* GO data xfer */ + do { + thisMove = sslArgs->chunkSize; + if(thisMove > toMove) { + thisMove = toMove; + } + size_t moved; + ortn = SSLWrite(ctx, sslArgs->xferBuf, thisMove, &moved); + /* should never fail - implemented as blocking */ + if(ortn) { + printSslErrStr("SSLWrite", ortn); + goto cleanup; + } + logWrite("client", moved); + if(!sslArgs->runForever) { + toMove -= moved; + } + if(*sslArgs->abortFlag) { + goto cleanup; + } + } while(toMove || sslArgs->runForever); + + sslArgs->endData = CFAbsoluteTimeGetCurrent(); + +cleanup: + if(ortn) { + *sslArgs->abortFlag = true; + } + if(*sslArgs->abortFlag && sslArgs->pauseOnError) { + /* abort for any reason - freeze! */ + testError(CSSM_FALSE); + } + if(ctx) { + SSLClose(ctx); + SSLDisposeContext(ctx); + } + if(ortn) { + printf("***Client thread returning %lu\n", (unsigned long)ortn); + } + pthread_exit((void*)ortn); + /* NOT REACHED */ + return (void *)ortn; + +} + +/* server function - like clientThread except it runs from the main thread */ +/* handshake and read a ton of data */ +OSStatus sslRbServerThread(SslRingBufferArgs *sslArgs) +{ + OSStatus ortn; + SSLContextRef ctx = NULL; + RingBuffers ringBufs = {sslArgs->ringRead, sslArgs->ringWrite}; + unsigned toMove = 0; + unsigned thisMove; + + ortn = SSLNewContext(true, &ctx); + if(ortn) { + printSslErrStr("SSLNewContext", ortn); + goto cleanup; + } + ortn = SSLSetIOFuncs(ctx, ringReadFunc, ringWriteFunc); + if(ortn) { + printSslErrStr("SSLSetIOFuncs", ortn); + goto cleanup; + } + ortn = SSLSetConnection(ctx, (SSLConnectionRef)&ringBufs); + if(ortn) { + printSslErrStr("SSLSetConnection", ortn); + goto cleanup; + } + ortn = SSLSetEnabledCiphers(ctx, &sslArgs->cipherSuite, 1); + if(ortn) { + printSslErrStr("SSLSetEnabledCiphers", ortn); + goto cleanup; + } + if(sslArgs->idArray) { + ortn = SSLSetCertificate(ctx, sslArgs->idArray); + if(ortn) { + printSslErrStr("SSLSetCertificate", ortn); + goto cleanup; + } + } + if(sslArgs->trustedRoots) { + ortn = SSLSetTrustedRoots(ctx, sslArgs->trustedRoots, true); + if(ortn) { + printSslErrStr("SSLSetTrustedRoots", ortn); + goto cleanup; + } + } + SSLSetProtocolVersionEnabled(ctx, kSSLProtocolAll, false); + ortn = SSLSetProtocolVersionEnabled(ctx, sslArgs->prot, true); + if(ortn) { + printSslErrStr("SSLSetProtocolVersionEnabled", ortn); + goto cleanup; + } + + /* tell client thread we're ready; wait for sync flag */ + sslArgs->iAmReady = true; + while(!(*sslArgs->goFlag)) { + if(*sslArgs->abortFlag) { + goto cleanup; + } + } + + /* GO handshake */ + sslArgs->startHandshake = CFAbsoluteTimeGetCurrent(); + do { + ortn = SSLHandshake(ctx); + if(*sslArgs->abortFlag) { + goto cleanup; + } + } while (ortn == errSSLWouldBlock); + + if(ortn) { + printSslErrStr("SSLHandshake", ortn); + goto cleanup; + } + + SSLGetNegotiatedCipher(ctx, &sslArgs->negotiatedCipher); + SSLGetNegotiatedProtocolVersion(ctx, &sslArgs->negotiatedProt); + + sslArgs->startData = CFAbsoluteTimeGetCurrent(); + + toMove = sslArgs->xferSize; + + if(toMove == 0) { + sslArgs->endData = sslArgs->startData; + goto cleanup; + } + + /* GO data xfer */ + do { + thisMove = sslArgs->xferSize; + if(thisMove > toMove) { + thisMove = toMove; + } + size_t moved; + ortn = SSLRead(ctx, sslArgs->xferBuf, thisMove, &moved); + switch(ortn) { + case noErr: + break; + case errSSLWouldBlock: + /* cool, try again */ + ortn = noErr; + break; + default: + break; + } + if(ortn) { + printSslErrStr("SSLRead", ortn); + goto cleanup; + } + logRead("server", moved); + if(!sslArgs->runForever) { + toMove -= moved; + } + if(*sslArgs->abortFlag) { + goto cleanup; + } + } while(toMove || sslArgs->runForever); + + sslArgs->endData = CFAbsoluteTimeGetCurrent(); + +cleanup: + if(ortn) { + *sslArgs->abortFlag = true; + } + if(*sslArgs->abortFlag && sslArgs->pauseOnError) { + /* abort for any reason - freeze! */ + testError(CSSM_FALSE); + } + if(ctx) { + SSLClose(ctx); + SSLDisposeContext(ctx); + } + if(ortn) { + printf("***Server thread returning %lu\n", (unsigned long)ortn); + } + return ortn; +} diff --git a/SecurityTests/clxutils/clAppUtils/sslRingBufferThreads.h b/SecurityTests/clxutils/clAppUtils/sslRingBufferThreads.h new file mode 100644 index 00000000..5046d9ee --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/sslRingBufferThreads.h @@ -0,0 +1,67 @@ +/* + * sslRingBufferThreads.h - SecureTransport client and server thread + * routines which use ringBufferIo for I/O (no sockets). + */ + +#include +#include +#include + +#ifndef _SSL_RING_BUFFER_THREADS_H_ +#define _SSL_RING_BUFFER_THREADS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * arguments to client thread and server pseudothread + */ +typedef struct { + CFArrayRef idArray; /* required for server, optional for client */ + CFArrayRef trustedRoots; /* generally from server's idArray */ + unsigned xferSize; /* total bytes for client to write and server to + * read */ + void *xferBuf; /* move to/from here */ + unsigned chunkSize; /* size of xferBuf; client writes this much at + * a time */ + bool runForever; /* if true, ignore xferSize and move data forever + * or until error */ + SSLCipherSuite cipherSuite; + SSLProtocol prot; + RingBuffer *ringWrite; /* I/O writes to this... */ + RingBuffer *ringRead; /* ...and reads from this */ + + /* client's goFlag is &(server's iAmReady); vice versa */ + bool iAmReady; /* this thread is ready for handshake */ + bool *goFlag; /* when both threads see this, they start + * their handshakes */ + bool *abortFlag; /* anyone sets this on error */ + /* everyone aborts when they see this true */ + bool pauseOnError; /* call testError() on error */ + + /* returned on success */ + SSLProtocol negotiatedProt; + SSLCipherSuite negotiatedCipher; + + CFAbsoluteTime startHandshake; + CFAbsoluteTime startData; + CFAbsoluteTime endData; +} SslRingBufferArgs; + +/* + * Client thread - handshake and write sslArgs->xferSize bytes of data. + */ +void *sslRbClientThread(void *arg); + +/* + * Server function - like clientThread except it runs from the main thread. + * handshake and read sslArgs->xferSize bytes of data. + */ +OSStatus sslRbServerThread(SslRingBufferArgs *sslArgs); + +#ifdef __cplusplus +} +#endif + +#endif /* _SSL_RING_BUFFER_THREADS_H_*/ diff --git a/SecurityTests/clxutils/clAppUtils/sslServe.cpp b/SecurityTests/clxutils/clAppUtils/sslServe.cpp new file mode 100644 index 00000000..c529238d --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/sslServe.cpp @@ -0,0 +1,380 @@ +/* + * sslServe.cpp : perform one server side sesssion + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define BIND_RETRIES 50 + +#define SERVER_MESSAGE "HTTP/1.0 200 OK\015\012\015\012" \ + "SecureTransport Test Server" \ + "

Secure connection established.

" \ + "Message from the 'sslServe' test library.\015\012" \ + "\015\012" + +#define READBUF_LEN 256 + +/* + * When true, delay setting the serverReady semaphore until we've finished + * setting up our SSLContext. This is a workaround for known thread-unsafety + * related to module attach and detach and context create/destroy: + * + * Crash in KCCursorImpl::next + * module/context handles not thread safe + */ +#define SERVER_READY_DELAY 1 + +/* + * params->lock is held for us by runSession() - we use it as a semapahore by + * unlocking it when we've created a port to listen on. + * This is generally run from a thread via sslRunSession() and + * sslServerThread() in sslAppUtils.cpp. + */ +OSStatus sslAppServe( + SslAppTestParams *params) +{ + otSocket listenSock = 0; + otSocket acceptSock = 0; + PeerSpec peerId; + OSStatus ortn = noErr; + SSLContextRef ctx = NULL; + SecKeychainRef serverKc = nil; + CFArrayRef serverCerts = nil; + RingBuffers ringBufs = {params->clientToServerRing, params->serverToClientRing}; + + sslThrDebug("Server", "starting"); + params->negVersion = kSSLProtocolUnknown; + params->negCipher = SSL_NULL_WITH_NULL_NULL; + params->ortn = noHardwareErr; + + if(params->serverToClientRing == NULL) { + /* set up a socket on which to listen */ + for(unsigned retry=0; retryport, params->nonBlocking, + &listenSock); + switch(ortn) { + case noErr: + break; + case opWrErr: + /* port already in use - try another */ + params->port++; + if(params->verbose || THREADING_DEBUG) { + printf("...retrying ListenForClients at port %d\n", + params->port); + } + break; + default: + break; + } + if(ortn != opWrErr) { + break; + } + } + } + + #if !SERVER_READY_DELAY + /* let main thread know a socket is ready */ + if(pthread_mutex_lock(¶ms->pthreadMutex)) { + printf("***Error acquiring server lock; aborting.\n"); + return -1; + } + params->serverReady = true; + if(pthread_cond_broadcast(¶ms->pthreadCond)) { + printf("***Error waking main thread; aborting.\n"); + return -1; + } + if(pthread_mutex_unlock(¶ms->pthreadMutex)) { + printf("***Error acquiring server lock; aborting.\n"); + return -1; + } + + if(ortn) { + printf("ListenForClients returned %d; aborting\n", (int)ortn); + return ortn; + } + + if(params->serverToClientRing == NULL) { + /* wait for a connection */ + if(params->verbose) { + printf("Waiting for client connection..."); + fflush(stdout); + } + ortn = AcceptClientConnection(listenSock, &acceptSock, &peerId); + if(ortn) { + printf("AcceptClientConnection returned %d; aborting\n", (int)ortn); + return ortn; + } + } + #endif /* SERVER_READY_DELAY */ + + /* + * Set up a SecureTransport session. + */ + ortn = SSLNewContext(true, &ctx); + if(ortn) { + printSslErrStr("SSLNewContext", ortn); + goto cleanup; + } + + #if !SERVER_READY_DELAY + if(params->serverToClientRing) { + /* RingBuffer I/O */ + ortn = SSLSetIOFuncs(ctx, ringReadFunc, ringWriteFunc); + if(ortn) { + printSslErrStr("SSLSetIOFuncs", ortn); + goto cleanup; + } + ortn = SSLSetConnection(ctx, (SSLConnectionRef)&ringBufs); + if(ortn) { + printSslErrStr("SSLSetConnection", ortn); + goto cleanup; + } + } + else { + /* normal socket I/O */ + ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite); + if(ortn) { + printSslErrStr("SSLSetIOFuncs", ortn); + goto cleanup; + } + ortn = SSLSetConnection(ctx, (SSLConnectionRef)acceptSock); + if(ortn) { + printSslErrStr("SSLSetConnection", ortn); + goto cleanup; + } + } + #endif /* SERVER_READY_DELAY */ + + if(params->anchorFile) { + ortn = sslAddTrustedRoot(ctx, params->anchorFile, + params->replaceAnchors); + if(ortn) { + goto cleanup; + } + } + if(params->myCertKcName != NULL) { + /* if not, better be trying anonymous diff-hellman... :-) */ + serverCerts = getSslCerts(params->myCertKcName, CSSM_FALSE, CSSM_FALSE, NULL, + &serverKc); + if(serverCerts == nil) { + exit(1); + } + if(params->password) { + ortn = SecKeychainUnlock(serverKc, strlen(params->password), + (void *)params->password, true); + if(ortn) { + printf("SecKeychainUnlock returned %d\n", (int)ortn); + /* oh well */ + } + } + if(params->idIsTrustedRoot) { + /* assume this is a root we want to implicitly trust */ + ortn = addIdentityAsTrustedRoot(ctx, serverCerts); + if(ortn) { + goto cleanup; + } + } + ortn = SSLSetCertificate(ctx, serverCerts); + if(ortn) { + printSslErrStr("SSLSetCertificate", ortn); + goto cleanup; + } + } + + if(params->disableCertVerify) { + ortn = SSLSetEnableCertVerify(ctx, false); + if(ortn) { + printSslErrStr("SSLSetEnableCertVerify", ortn); + goto cleanup; + } + } + if(!params->noProtSpec) { + ortn = sslSetProtocols(ctx, params->acceptedProts, params->tryVersion); + if(ortn) { + goto cleanup; + } + } + if(params->resumeEnable) { + ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec)); + if(ortn) { + printSslErrStr("SSLSetPeerID", ortn); + goto cleanup; + } + } + if(params->ciphers != NULL) { + ortn = sslSetEnabledCiphers(ctx, params->ciphers); + if(ortn) { + goto cleanup; + } + } + if(params->authenticate != kNeverAuthenticate) { + ortn = SSLSetClientSideAuthenticate(ctx, params->authenticate); + if(ortn) { + printSslErrStr("SSLSetClientSideAuthenticate", ortn); + goto cleanup; + } + } + if(params->dhParams) { + ortn = SSLSetDiffieHellmanParams(ctx, params->dhParams, + params->dhParamsLen); + if(ortn) { + printSslErrStr("SSLSetDiffieHellmanParams", ortn); + goto cleanup; + } + } + + #if SERVER_READY_DELAY + /* let main thread know server is fully functional */ + if(pthread_mutex_lock(¶ms->pthreadMutex)) { + printf("***Error acquiring server lock; aborting.\n"); + ortn = internalComponentErr; + goto cleanup; + } + params->serverReady = true; + if(pthread_cond_broadcast(¶ms->pthreadCond)) { + printf("***Error waking main thread; aborting.\n"); + ortn = internalComponentErr; + goto cleanup; + } + if(pthread_mutex_unlock(¶ms->pthreadMutex)) { + printf("***Error acquiring server lock; aborting.\n"); + ortn = internalComponentErr; + goto cleanup; + } + + if(params->serverToClientRing == NULL) { + /* wait for a connection */ + if(params->verbose) { + printf("Waiting for client connection..."); + fflush(stdout); + } + ortn = AcceptClientConnection(listenSock, &acceptSock, &peerId); + if(ortn) { + printf("AcceptClientConnection returned %d; aborting\n", (int)ortn); + return ortn; + } + } + + /* Last part of SSLContext setup, now that we're connected to the client */ + if(params->serverToClientRing) { + /* RingBuffer I/O */ + ortn = SSLSetIOFuncs(ctx, ringReadFunc, ringWriteFunc); + if(ortn) { + printSslErrStr("SSLSetIOFuncs", ortn); + goto cleanup; + } + ortn = SSLSetConnection(ctx, (SSLConnectionRef)&ringBufs); + if(ortn) { + printSslErrStr("SSLSetConnection", ortn); + goto cleanup; + } + } + else { + /* normal socket I/O */ + ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite); + if(ortn) { + printSslErrStr("SSLSetIOFuncs", ortn); + goto cleanup; + } + ortn = SSLSetConnection(ctx, (SSLConnectionRef)acceptSock); + if(ortn) { + printSslErrStr("SSLSetConnection", ortn); + goto cleanup; + } + } + + #endif /* SERVER_READY_DELAY */ + + /* Perform SSL/TLS handshake */ + do { + ortn = SSLHandshake(ctx); + if((ortn == errSSLWouldBlock) && !params->silent) { + /* keep UI responsive */ + sslOutputDot(); + } + } while (ortn == errSSLWouldBlock); + + SSLGetClientCertificateState(ctx, ¶ms->certState); + SSLGetNegotiatedCipher(ctx, ¶ms->negCipher); + SSLGetNegotiatedProtocolVersion(ctx, ¶ms->negVersion); + + if(params->verbose) { + printf("\n"); + } + if(ortn) { + goto cleanup; + } + + /* wait for one complete line */ + char readBuf[READBUF_LEN]; + size_t length; + while(ortn == noErr) { + length = READBUF_LEN; + ortn = SSLRead(ctx, readBuf, length, &length); + if (ortn == errSSLWouldBlock) { + /* keep trying */ + ortn = noErr; + continue; + } + if(length == 0) { + /* keep trying */ + continue; + } + + /* poor person's line completion scan */ + for(unsigned i=0; iclientDone && !params->serverAbort && (ortn == params->expectRtn)) { + usleep(100); + } + if(acceptSock) { + endpointShutdown(acceptSock); + } + ringBuffersClose(&ringBufs); /* tolerates NULLs */ + if(listenSock) { + endpointShutdown(listenSock); + } + if(ctx) { + SSLDisposeContext(ctx); + } + params->ortn = ortn; + sslThrDebug("Server", "done"); + return ortn; +} diff --git a/SecurityTests/clxutils/clAppUtils/sslThreading.h b/SecurityTests/clxutils/clAppUtils/sslThreading.h new file mode 100644 index 00000000..24ddbccc --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/sslThreading.h @@ -0,0 +1,174 @@ +/* + * sslThreading.h - support for two-threaded SSL client/server tests. + */ + +#ifndef _SSL_THREADING_H_ +#define _SSL_THREADING_H_ 1 + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* "Don't bother verifying" values */ +#define SSL_PROTOCOL_IGNORE ((SSLProtocol)0x123456) +#define SSL_CLIENT_CERT_IGNORE ((SSLClientCertificateState)0x234567) +#define SSL_CIPHER_IGNORE ((SSLCipherSuite)0x345678) + +/* + * Test params passed to both sslClient() and sslServer() + */ +typedef struct { + + /* client side only */ + const char *hostName; + bool skipHostNameCheck; + + /* common */ + unsigned short port; + RingBuffer *serverToClientRing; + RingBuffer *clientToServerRing; + + bool noProtSpec; // if true, don't set protocol in either + // fashion + SSLProtocol tryVersion; // only used if acceptedProts + // NULL + const char *acceptedProts; + const char *myCertKcName; // required for server, + // optional for client + const char *password; // optional, to unlock keychain + bool idIsTrustedRoot; // cert in KC is trusted root + bool disableCertVerify; + const char *anchorFile; // to add/replace anchors + bool replaceAnchors; + SSLAuthenticate authenticate; + bool resumeEnable; + const SSLCipherSuite *ciphers; // optional array of allowed ciphers, + // terminated with SSL_NO_SUCH_CIPHERSUITE + bool nonBlocking; + const unsigned char *dhParams; // optional Diffie-Hellman params + unsigned dhParamsLen; + + /* expected results */ + OSStatus expectRtn; + SSLProtocol expectVersion; + SSLClientCertificateState expectCertState; + SSLCipherSuite expectCipher; + + /* UI parameters */ + bool quiet; + bool silent; + bool verbose; + + /* + * Server semaphore: + * + * -- main thread inits and sets serverReady false + * -- main thread starts up server thread + * -- server thread inits and sets up a socket for listening + * -- server thread sets serverReady true and does pthread_cond_broadcast + */ + pthread_mutex_t pthreadMutex; + pthread_cond_t pthreadCond; + bool serverReady; + + /* + * To ensure error abort is what we expect instead of just + * "peer closed their socket", server avoids closing down the + * socket until client sets this flag. It's just polled, no + * locking. Setting the serverAbort flag skips this + * step to facilitate testing cases where server explicitly + * drops connection (e.g. in response to an unacceptable + * ClientHello). + */ + unsigned clientDone; + bool serverAbort; + + /* + * Returned and also verified by sslRunSession(). + * Conditions in which expected value NOT verified are listed + * in following comments. + * + * NegCipher is only verified if (ortn == noErr). + */ + SSLProtocol negVersion; // SSL_PROTOCOL_IGNORE + SSLCipherSuite negCipher; // SSL_CIPHER_IGNORE + SSLClientCertificateState certState; // SSL_CLIENT_CERT_IGNORE + OSStatus ortn; // always checked + +} SslAppTestParams; + +/* client and server in sslClient.cpp and sslServe.cpp */ +OSStatus sslAppClient( + SslAppTestParams *params); +OSStatus sslAppServe( + SslAppTestParams *params); + +/* + * Run one session, with the server in a separate thread. + * On entry, serverParams->port is the port we attempt to run on; + * the server thread may overwrite that with a different port if it's + * unable to open the port we specify. Whatever is left in + * serverParams->port is what's used for the client side. + */ +int sslRunSession( + SslAppTestParams *serverParams, + SslAppTestParams *clientParams, + const char *testDesc); + +void sslShowResult( + const char *whichSide, // "client" or "server" + SslAppTestParams *params); + + +/* + * Macros which do the repetetive setup/run work + */ +#define SSL_THR_SETUP(serverParams, clientParams, clientDefaults, serverDefault) \ +{ \ + unsigned short serverPort; \ + serverPort = serverParams.port + 1; \ + clientParams = clientDefaults; \ + serverParams = serverDefaults; \ + serverParams.port = serverPort; \ +} + +#define SSL_THR_RUN(serverParams, clientParams, desc, ourRtn) \ +{ \ + thisRtn = sslRunSession(&serverParams, &clientParams, desc); \ + ourRtn += thisRtn; \ + if(thisRtn) { \ + if(testError(clientParams.quiet)) { \ + goto done; \ + } \ + } \ +} + +#define SSL_THR_RUN_NUM(serverParams, clientParams, desc, ourRtn, testNum) \ +{ \ + thisRtn = sslRunSession(&serverParams, &clientParams, desc);\ + ourRtn += thisRtn; \ + if(thisRtn) { \ + printf("***Error on test %u\n", testNum); \ + if(testError(clientParams.quiet)) { \ + goto done; \ + } \ + } \ +} + +#define THREADING_DEBUG 0 +#if THREADING_DEBUG + +#define sslThrDebug(side, end) \ + printf("^^^%s thread %p %s\n", side, pthread_self(), end) +#else /* THREADING_DEBUG */ +#define sslThrDebug(side, end) +#endif /* THREADING_DEBUG */ +#ifdef __cplusplus +} +#endif + +#endif /* _SSL_THREADING_H_ */ diff --git a/SecurityTests/clxutils/clAppUtils/timeStr.cpp b/SecurityTests/clxutils/clAppUtils/timeStr.cpp new file mode 100644 index 00000000..73e5a12e --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/timeStr.cpp @@ -0,0 +1,290 @@ +#include "timeStr.h" +#include +#include +#include +#include +#include /* for Mutex */ +#include + +/* + * Given a string containing either a UTC-style or "generalized time" + * time string, convert to a struct tm (in GMT/UTC). Returns nonzero on + * error. + */ +int appTimeStringToTm( + const char *str, + unsigned len, + struct tm *tmp) +{ + char szTemp[5]; + unsigned isUtc; + unsigned x; + unsigned i; + char *cp; + + if((str == NULL) || (len == 0) || (tmp == NULL)) { + return 1; + } + + /* tolerate NULL terminated or not */ + if(str[len - 1] == '\0') { + len--; + } + switch(len) { + case UTC_TIME_STRLEN: // 2-digit year, not Y2K compliant + isUtc = 1; + break; + case GENERALIZED_TIME_STRLEN: // 4-digit year + isUtc = 0; + break; + default: // unknown format + return 1; + } + + cp = (char *)str; + + /* check that all characters except last are digits */ + for(i=0; i<(len - 1); i++) { + if ( !(isdigit(cp[i])) ) { + return 1; + } + } + + /* check last character is a 'Z' */ + if(cp[len - 1] != 'Z' ) { + return 1; + } + + /* YEAR */ + szTemp[0] = *cp++; + szTemp[1] = *cp++; + if(!isUtc) { + /* two more digits */ + szTemp[2] = *cp++; + szTemp[3] = *cp++; + szTemp[4] = '\0'; + } + else { + szTemp[2] = '\0'; + } + x = atoi( szTemp ); + if(isUtc) { + /* + * 2-digit year. + * 0 <= year < 50 : assume century 21 + * 50 <= year < 70 : illegal per PKIX + * 70 < year <= 99 : assume century 20 + */ + if(x < 50) { + x += 2000; + } + else if(x < 70) { + return 1; + } + else { + /* century 20 */ + x += 1900; + } + } + /* by definition - tm_year is year - 1900 */ + tmp->tm_year = x - 1900; + + /* MONTH */ + szTemp[0] = *cp++; + szTemp[1] = *cp++; + szTemp[2] = '\0'; + x = atoi( szTemp ); + /* in the string, months are from 1 to 12 */ + if((x > 12) || (x <= 0)) { + return 1; + } + /* in a tm, 0 to 11 */ + tmp->tm_mon = x - 1; + + /* DAY */ + szTemp[0] = *cp++; + szTemp[1] = *cp++; + szTemp[2] = '\0'; + x = atoi( szTemp ); + /* 1..31 in both formats */ + if((x > 31) || (x <= 0)) { + return 1; + } + tmp->tm_mday = x; + + /* HOUR */ + szTemp[0] = *cp++; + szTemp[1] = *cp++; + szTemp[2] = '\0'; + x = atoi( szTemp ); + if((x > 23) || (x < 0)) { + return 1; + } + tmp->tm_hour = x; + + /* MINUTE */ + szTemp[0] = *cp++; + szTemp[1] = *cp++; + szTemp[2] = '\0'; + x = atoi( szTemp ); + if((x > 59) || (x < 0)) { + return 1; + } + tmp->tm_min = x; + + /* SECOND */ + szTemp[0] = *cp++; + szTemp[1] = *cp++; + szTemp[2] = '\0'; + x = atoi( szTemp ); + if((x > 59) || (x < 0)) { + return 1; + } + tmp->tm_sec = x; + return 0; +} + +/* common time routine used by utcAtNowPlus and genTimeAtNowPlus */ +#define MAX_TIME_STR_LEN 30 + +static Mutex timeMutex; // protects time(), gmtime() + +char *appTimeAtNowPlus(int secFromNow, + timeSpec spec) +{ + struct tm utc; + char *outStr; + time_t baseTime; + + timeMutex.lock(); + baseTime = time(NULL); + baseTime += (time_t)secFromNow; + utc = *gmtime(&baseTime); + timeMutex.unlock(); + + outStr = (char *)CSSM_MALLOC(MAX_TIME_STR_LEN); + + switch(spec) { + case TIME_UTC: + /* UTC - 2 year digits - code which parses this assumes that + * (2-digit) years between 0 and 49 are in century 21 */ + if(utc.tm_year >= 100) { + utc.tm_year -= 100; + } + sprintf(outStr, "%02d%02d%02d%02d%02d%02dZ", + utc.tm_year /* + 1900 */, utc.tm_mon + 1, + utc.tm_mday, utc.tm_hour, utc.tm_min, utc.tm_sec); + break; + case TIME_GEN: + sprintf(outStr, "%04d%02d%02d%02d%02d%02dZ", + /* note year is relative to 1900, hopefully it'll have four valid + * digits! */ + utc.tm_year + 1900, utc.tm_mon + 1, + utc.tm_mday, utc.tm_hour, utc.tm_min, utc.tm_sec); + break; + case TIME_CSSM: + sprintf(outStr, "%04d%02d%02d%02d%02d%02d", + /* note year is relative to 1900, hopefully it'll have + * four valid digits! */ + utc.tm_year + 1900, utc.tm_mon + 1, + utc.tm_mday, utc.tm_hour, utc.tm_min, utc.tm_sec); + break; + } + return outStr; +} + +/* + * Malloc and return UTC (2-digit year) time string, for time with specified + * offset from present. This uses the stdlib gmtime(), which is not thread safe. + * Even though this function protects the call with a lock, the TP also uses + * gmtime. It also does the correct locking for its own calls to gmtime()Êbut + * the is no way to synchronize TP's calls to gmtime() with the calls to this + * one other than only using this one when no threads might be performing TP ops. + */ +char *utcAtNowPlus(int secFromNow) +{ + return appTimeAtNowPlus(secFromNow, TIME_UTC); +} + +/* + * Same thing, generalized time (4-digit year). + */ +char *genTimeAtNowPlus(int secFromNow) +{ + return appTimeAtNowPlus(secFromNow, TIME_GEN); +} + +/* + * Free the string obtained from the above. + */ +void freeTimeString(char *timeStr) +{ + CSSM_FREE(timeStr); +} + +/* + * Convert a CSSM_X509_TIME, which can be in any of three forms (UTC, + * generalized, or CSSM_TIMESTRING) into a CSSM_TIMESTRING. Caller + * must free() the result. Returns NULL if x509time is badly formed. + */ +char *x509TimeToCssmTimestring( + const CSSM_X509_TIME *x509Time, + unsigned *rtnLen) // for caller's convenience +{ + int len = x509Time->time.Length; + const char *inStr = (char *)x509Time->time.Data; // not NULL terminated! + char *rtn; + + *rtnLen = 0; + if((len == 0) || (inStr == NULL)) { + return NULL; + } + rtn = (char *)malloc(CSSM_TIME_STRLEN + 1); + rtn[0] = '\0'; + switch(len) { + case UTC_TIME_STRLEN: + { + /* infer century and prepend to output */ + char tmp[3]; + int year; + tmp[0] = inStr[0]; + tmp[1] = inStr[1]; + tmp[2] = '\0'; + year = atoi(tmp); + + /* + * 0 <= year < 50 : assume century 21 + * 50 <= year < 70 : illegal per PKIX + * 70 < year <= 99 : assume century 20 + */ + if(year < 50) { + /* century 21 */ + strcpy(rtn, "20"); + } + else if(year < 70) { + free(rtn); + return NULL; + } + else { + /* century 20 */ + strcpy(rtn, "19"); + } + memmove(rtn + 2, inStr, len - 1); // don't copy the Z + break; + } + case CSSM_TIME_STRLEN: + memmove(rtn, inStr, len); // trivial case + break; + case GENERALIZED_TIME_STRLEN: + memmove(rtn, inStr, len - 1); // don't copy the Z + break; + + default: + free(rtn); + return NULL; + } + rtn[CSSM_TIME_STRLEN] = '\0'; + *rtnLen = CSSM_TIME_STRLEN; + return rtn; +} + diff --git a/SecurityTests/clxutils/clAppUtils/timeStr.h b/SecurityTests/clxutils/clAppUtils/timeStr.h new file mode 100644 index 00000000..7d1548a2 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/timeStr.h @@ -0,0 +1,65 @@ +#ifndef _TIME_STR_H_ +#define _TIME_STR_H_ + +#include +#include + +#define UTC_TIME_STRLEN 13 +#define CSSM_TIME_STRLEN 14 /* no trailing 'Z' */ +#define GENERALIZED_TIME_STRLEN 15 + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Given a string containing either a UTC-style or "generalized time" + * time string, convert to a struct tm (in GMT/UTC). Returns nonzero on + * error. + */ +int appTimeStringToTm( + const char *str, + unsigned len, + struct tm *tmp); + +typedef enum { + TIME_UTC, + TIME_CSSM, + TIME_GEN +} timeSpec; + +/* Caller must CSSM_FREE() the resulting string */ +char *appTimeAtNowPlus(int secFromNow, + timeSpec timeSpec); + +/*** for backwards compatibility ***/ + +/* + * Malloc and return UTC (2-digit year) time string, for time with specified + * offset from present. This uses the stdlib gmtime(), which is not thread safe. + * Even though this function protects the call with a lock, the TP also uses + * gmtime. It also does the correct locking for its own calls to gmtime()Êbut + * the is no way to synchronize TP's calls to gmtime() with the calls to this + * one other than only using this one when no threads might be performing TP ops. + */ +char *utcAtNowPlus(int secFromNow); + +/* + * Same thing, generalized time (4-digit year). + */ +char *genTimeAtNowPlus(int secFromNow); + +/* + * Free the string obtained from the above. + */ +void freeTimeString(char *timeStr); + +char *x509TimeToCssmTimestring( + const CSSM_X509_TIME *x509Time, + unsigned *rtnLen); // for caller's convenience + +#ifdef __cplusplus +} +#endif + +#endif /* _TIME_STR_H_ */ diff --git a/SecurityTests/clxutils/clAppUtils/tpUtils.cpp b/SecurityTests/clxutils/clAppUtils/tpUtils.cpp new file mode 100644 index 00000000..1e5e83d2 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/tpUtils.cpp @@ -0,0 +1,1215 @@ +/* + * tpUtils.cpp - TP and cert group test support + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Currently, DBs created with SecKeychainCreateNew() do not contain + * the schema for CSSM_DL_DB_RECORD_X509_CERTIFICATE records. Keychain + * code (Certificate::add()) does this on the fly, I don't know why. + * To avoid dependencies on KC - other than SecKeychainCreateNew - we'll + * emulate that "add this schema on the fly" logic here. + * + * Turn this option off if and when Radar 2927378 is approved and + * integrated into Security TOT. + */ +#define FAKE_ADD_CERT_SCHEMA 1 +#if FAKE_ADD_CERT_SCHEMA + +/* defined in SecKeychainAPIPriv.h */ +// static const int kSecAlias = 'alis'; + +/* Macro to declare a CSSM_DB_SCHEMA_ATTRIBUTE_INFO */ +#define SCHEMA_ATTR_INFO(id, name, type) \ + { id, (char *)name, {0, NULL}, CSSM_DB_ATTRIBUTE_FORMAT_ ## type } + +/* Too bad we can't get this from inside of the Security framework. */ +static CSSM_DB_SCHEMA_ATTRIBUTE_INFO certSchemaAttrInfo[] = +{ + SCHEMA_ATTR_INFO(kSecCertTypeItemAttr, "CertType", UINT32), + SCHEMA_ATTR_INFO(kSecCertEncodingItemAttr, "CertEncoding", UINT32), + SCHEMA_ATTR_INFO(kSecLabelItemAttr, "PrintName", BLOB), + SCHEMA_ATTR_INFO(kSecAlias, "Alias", BLOB), + SCHEMA_ATTR_INFO(kSecSubjectItemAttr, "Subject", BLOB), + SCHEMA_ATTR_INFO(kSecIssuerItemAttr, "Issuer", BLOB), + SCHEMA_ATTR_INFO(kSecSerialNumberItemAttr, "SerialNumber", BLOB), + SCHEMA_ATTR_INFO(kSecSubjectKeyIdentifierItemAttr, "SubjectKeyIdentifier", BLOB), + SCHEMA_ATTR_INFO(kSecPublicKeyHashItemAttr, "PublicKeyHash", BLOB) +}; +#define NUM_CERT_SCHEMA_ATTRS \ + (sizeof(certSchemaAttrInfo) / sizeof(CSSM_DB_SCHEMA_ATTRIBUTE_INFO)) + +/* Macro to declare a CSSM_DB_SCHEMA_INDEX_INFO */ +#define SCHEMA_INDEX_INFO(id, indexNum, indexType) \ + { id, CSSM_DB_INDEX_ ## indexType, CSSM_DB_INDEX_ON_ATTRIBUTE } + + +static CSSM_DB_SCHEMA_INDEX_INFO certSchemaIndices[] = +{ + SCHEMA_INDEX_INFO(kSecCertTypeItemAttr, 0, UNIQUE), + SCHEMA_INDEX_INFO(kSecIssuerItemAttr, 0, UNIQUE), + SCHEMA_INDEX_INFO(kSecSerialNumberItemAttr, 0, UNIQUE), + SCHEMA_INDEX_INFO(kSecCertTypeItemAttr, 1, NONUNIQUE), + SCHEMA_INDEX_INFO(kSecSubjectItemAttr, 2, NONUNIQUE), + SCHEMA_INDEX_INFO(kSecIssuerItemAttr, 3, NONUNIQUE), + SCHEMA_INDEX_INFO(kSecSerialNumberItemAttr, 4, NONUNIQUE), + SCHEMA_INDEX_INFO(kSecSubjectKeyIdentifierItemAttr, 5, NONUNIQUE), + SCHEMA_INDEX_INFO(kSecPublicKeyHashItemAttr, 6, NONUNIQUE) +}; +#define NUM_CERT_INDICES \ + (sizeof(certSchemaIndices) / sizeof(CSSM_DB_SCHEMA_INDEX_INFO)) + + +CSSM_RETURN tpAddCertSchema( + CSSM_DL_DB_HANDLE dlDbHand) +{ + return CSSM_DL_CreateRelation(dlDbHand, + CSSM_DL_DB_RECORD_X509_CERTIFICATE, + "CSSM_DL_DB_RECORD_X509_CERTIFICATE", + NUM_CERT_SCHEMA_ATTRS, + certSchemaAttrInfo, + NUM_CERT_INDICES, + certSchemaIndices); +} +#endif /* FAKE_ADD_CERT_SCHEMA */ + +/* + * Given a raw cert, extract DER-encoded normalized subject and issuer names. + */ +static CSSM_DATA_PTR tpGetNormSubject( + CSSM_CL_HANDLE clHand, + const CSSM_DATA *rawCert) +{ + CSSM_RETURN crtn; + CSSM_HANDLE searchHand = CSSM_INVALID_HANDLE; + uint32 numFields; + CSSM_DATA_PTR fieldValue; + + crtn = CSSM_CL_CertGetFirstFieldValue(clHand, + rawCert, + &CSSMOID_X509V1SubjectName, + &searchHand, + &numFields, + &fieldValue); + if(crtn) { + printError("CSSM_CL_CertGetFirstFieldValue", crtn); + return NULL; + } + CSSM_CL_CertAbortQuery(clHand, searchHand); + return fieldValue; +} + +static CSSM_DATA_PTR tpGetNormIssuer( + CSSM_CL_HANDLE clHand, + const CSSM_DATA *rawCert) +{ + CSSM_RETURN crtn; + CSSM_HANDLE searchHand = CSSM_INVALID_HANDLE; + uint32 numFields; + CSSM_DATA_PTR fieldValue; + + crtn = CSSM_CL_CertGetFirstFieldValue(clHand, + rawCert, + &CSSMOID_X509V1IssuerName, + &searchHand, + &numFields, + &fieldValue); + if(crtn) { + printError("CSSM_CL_CertGetFirstFieldValue", crtn); + return NULL; + } + CSSM_CL_CertAbortQuery(clHand, searchHand); + return fieldValue; +} + + +#define SERIAL_NUMBER_BASE 0x33445566 + +/* + * Given an array of certs and an uninitialized CSSM_CERTGROUP, place the + * certs into the certgroup and optionally into one of a list of DBs in + * random order. Optionally the first cert in the array is placed in the + * first element of certgroup. Only error is memory error. It's legal to + * pass in an empty cert array. + */ +CSSM_RETURN tpMakeRandCertGroup( + CSSM_CL_HANDLE clHand, + CSSM_DL_DB_LIST_PTR dbList, + const CSSM_DATA_PTR certs, + unsigned numCerts, + CSSM_CERTGROUP_PTR certGroup, + CSSM_BOOL firstCertIsSubject, // true: certs[0] goes to head + // of certGroup + CSSM_BOOL verbose, + CSSM_BOOL allInDbs, // all certs go to DBs + CSSM_BOOL skipFirstDb) // no certs go to db[0] +{ + unsigned startDex = 0; // where to start processing + unsigned certDex; // into certs and certGroup + unsigned die; + CSSM_RETURN crtn; + + #if TP_DB_ENABLE + if((dbList == NULL) && (allInDbs | skipFirstDb)) { + printf("need dbList for allInDbs or skipFirstDb\n"); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + if(skipFirstDb && (dbList->NumHandles == 1)) { + printf("Need more than one DB for skipFirstDb\n"); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + #else + if(dbList != NULL) { + printf("TP/DB not supported yet\n"); + return CSSMERR_CSSM_INTERNAL_ERROR; + } + #endif + + certGroup->NumCerts = 0; + certGroup->CertGroupType = CSSM_CERTGROUP_DATA; + certGroup->CertType = CSSM_CERT_X_509v3; + certGroup->CertEncoding = CSSM_CERT_ENCODING_DER; + if(numCerts == 0) { + /* legal */ + certGroup->GroupList.CertList = NULL; + return CSSM_OK; + } + + /* make CertList big enough for all certs */ + certGroup->GroupList.CertList = (CSSM_DATA_PTR)CSSM_CALLOC(numCerts, sizeof(CSSM_DATA)); + if(certGroup->GroupList.CertList == NULL) { + printf("Memory error!\n"); + return CSSMERR_CSSM_MEMORY_ERROR; + } + if(firstCertIsSubject) { + certGroup->GroupList.CertList[0] = certs[0]; + certGroup->NumCerts = 1; + startDex = 1; + } + for(certDex=startDex; certDexNumHandles != 0) ) && + ( (die == 1) || allInDbs) ) { + /* put this cert in one of the DBs */ + if(skipFirstDb) { + die = genRand(1, dbList->NumHandles-1); + } + else { + die = genRand(0, dbList->NumHandles-1); + } + if(verbose) { + printf(" ...cert %d to DB[%d]\n", certDex, die); + } + crtn = tpStoreRawCert(dbList->DLDBHandle[die], + clHand, + &certs[certDex]); + if(crtn) { + return crtn; + } + } + else { + /* find a random unused place in certGroupFrag */ + CSSM_DATA_PTR certData; + + while(1) { + die = genRand(0, numCerts-1); + certData = &certGroup->GroupList.CertList[die]; + if(certData->Data == NULL) { + *certData = certs[certDex]; + certGroup->NumCerts++; + if(verbose) { + printf(" ...cert %d to frag[%d]\n", + certDex, die); + } + break; + } + /* else try again and hope we don't spin forever */ + } + } /* random place in certGroup */ + } /* main loop */ + + if(dbList != NULL) { + /* + * Since we put some of the certs in dlDb rather than in certGroup, + * compact the contents of certGroup. Its NumCerts is correct, + * but some of the entries in CertList are empty. + */ + unsigned i; + + for(certDex=0; certDexGroupList.CertList[certDex].Data == NULL) { + /* find next non-NULL cert */ + for(i=certDex+1; iGroupList.CertList[i].Data != NULL) { + if(verbose) { + printf(" ...frag[%d] to frag[%d]\n", + i, certDex); + } + certGroup->GroupList.CertList[certDex] = + certGroup->GroupList.CertList[i]; + certGroup->GroupList.CertList[i].Data = NULL; + break; + } + } + } + } + } + return CSSM_OK; +} + +/* + * Store a cert in specified DL/DB. All attributes are optional except + * as noted (right?). + */ +CSSM_RETURN tpStoreCert( + CSSM_DL_DB_HANDLE dlDb, + const CSSM_DATA_PTR cert, + /* REQUIRED fields */ + CSSM_CERT_TYPE certType, // e.g. CSSM_CERT_X_509v3 + uint32 serialNum, + const CSSM_DATA *issuer, // (shouldn't this be subject?) + // normalized & encoded + /* OPTIONAL fields */ + CSSM_CERT_ENCODING certEncoding, // e.g. CSSM_CERT_ENCODING_DER + const CSSM_DATA *printName, + const CSSM_DATA *subject) // normalized & encoded +{ + CSSM_DB_ATTRIBUTE_DATA attrs[6]; + CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; + CSSM_DB_ATTRIBUTE_DATA_PTR attr = &attrs[0]; + CSSM_DB_UNIQUE_RECORD_PTR recordPtr = NULL; + CSSM_DATA certTypeData; + CSSM_DATA certEncData; + CSSM_DATA_PTR serialNumData; + uint32 numAttributes; + + if(issuer == NULL) { + printf("***For now, must specify cert issuer when storing\n"); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + + /* how many attributes are we storing? */ + numAttributes = 4; // certType, serialNum, issuer, certEncoding + if(printName != NULL) { + numAttributes++; + } + if(subject != NULL) { + numAttributes++; + } + + /* cook up CSSM_DB_RECORD_ATTRIBUTE_DATA */ + recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_X509_CERTIFICATE; + recordAttrs.SemanticInformation = 0; + recordAttrs.NumberOfAttributes = numAttributes; + recordAttrs.AttributeData = attrs; + + /* grind thru the attributes - first the required ones plus certEncoding */ + certTypeData.Data = (uint8 *)&certType; + certTypeData.Length = sizeof(CSSM_CERT_TYPE); + certEncData.Data = (uint8 *)&certEncoding; + certEncData.Length = sizeof(CSSM_CERT_ENCODING); + serialNumData = intToDER(serialNum); + + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = (char *)"CertType"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32; + attr->NumberOfValues = 1; + attr->Value = &certTypeData; + attr++; + + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = (char *)"CertEncoding"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_UINT32; + attr->NumberOfValues = 1; + attr->Value = &certEncData; + attr++; + + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = (char *)"SerialNumber"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + attr->NumberOfValues = 1; + attr->Value = serialNumData; + attr++; + + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = (char *)"Issuer"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + attr->NumberOfValues = 1; + attr->Value = (CSSM_DATA_PTR)issuer; + attr++; + + /* now the options */ + if(printName != NULL) { + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = (char *)"PrintName"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + attr->NumberOfValues = 1; + attr->Value = (CSSM_DATA_PTR)printName; + attr++; + } + if(subject != NULL) { + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = (char *)"Subject"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + attr->NumberOfValues = 1; + attr->Value = (CSSM_DATA_PTR)subject; + attr++; + } + + /* Okay, here we go */ + CSSM_RETURN crtn = CSSM_DL_DataInsert(dlDb, + CSSM_DL_DB_RECORD_X509_CERTIFICATE, + &recordAttrs, + cert, + &recordPtr); + #if FAKE_ADD_CERT_SCHEMA + if(crtn == CSSMERR_DL_INVALID_RECORDTYPE) { + /* gross hack of inserting this "new" schema that Keychain didn't specify */ + crtn = tpAddCertSchema(dlDb); + if(crtn == CSSM_OK) { + /* Retry with a fully capable DLDB */ + crtn = CSSM_DL_DataInsert(dlDb, + CSSM_DL_DB_RECORD_X509_CERTIFICATE, + &recordAttrs, + cert, + &recordPtr); + } + } + #endif /* FAKE_ADD_CERT_SCHEMA */ + + /* free resources allocated to get this far */ + appFreeCssmData(serialNumData, CSSM_TRUE); + if(recordPtr != NULL) { + CSSM_DL_FreeUniqueRecord(dlDb, recordPtr); + } + if(crtn) { + printError("CSSM_DL_DataInsert", crtn); + } + return crtn; +} + +/* + * Store a cert when we don't already know the required fields. We'll + * extract them or make them up. + */ +CSSM_RETURN tpStoreRawCert( + CSSM_DL_DB_HANDLE dlDb, + CSSM_CL_HANDLE clHand, + const CSSM_DATA_PTR cert) +{ + CSSM_DATA_PTR normSubj; + CSSM_DATA_PTR normIssuer; + CSSM_DATA printName; + CSSM_RETURN crtn; + static uint32 fakeSerialNum = 0; + + normSubj = tpGetNormSubject(clHand, cert); + normIssuer = tpGetNormIssuer(clHand, cert); + if((normSubj == NULL) || (normIssuer == NULL)) { + return CSSM_ERRCODE_INTERNAL_ERROR; + } + printName.Data = (uint8 *)"Some Printable Name"; + printName.Length = strlen((char *)printName.Data); + crtn = tpStoreCert(dlDb, + cert, + CSSM_CERT_X_509v3, + fakeSerialNum++, + normIssuer, + CSSM_CERT_ENCODING_DER, + &printName, + normSubj); + appFreeCssmData(normSubj, CSSM_TRUE); + appFreeCssmData(normIssuer, CSSM_TRUE); + return crtn; +} + +/* + * Generate numKeyPairs key pairs of specified algorithm and size. + * Key labels will be 'keyLabelBase' concatenated with a 4-digit + * decimal number. + */ +CSSM_RETURN tpGenKeys( + CSSM_CSP_HANDLE cspHand, + CSSM_DL_DB_HANDLE dbHand, /* keys go here */ + unsigned numKeyPairs, + uint32 keyGenAlg, /* CSSM_ALGID_RSA, etc. */ + uint32 keySizeInBits, + const char *keyLabelBase, /* C string */ + CSSM_KEY_PTR pubKeys, /* array of keys RETURNED here */ + CSSM_KEY_PTR privKeys, /* array of keys RETURNED here */ + CSSM_DATA_PTR paramData) /* optional DSA params */ +{ + CSSM_RETURN crtn; + unsigned i; + char label[80]; + unsigned labelLen = strlen(keyLabelBase); + + memset(pubKeys, 0, numKeyPairs * sizeof(CSSM_KEY)); + memset(privKeys, 0, numKeyPairs * sizeof(CSSM_KEY)); + memmove(label, keyLabelBase, labelLen); + + for(i=0; i=0; dex--) { + thisCert = &certs[dex]; + + thisCert->Data = NULL; + thisCert->Length = 0; + + sprintf(nameStr, "%s%04d", nameBase, dex); + if(issuerName == NULL) { + /* last (root) cert - subject same as issuer */ + issuerName = CB_BuildX509Name(&nameOid, 1); + /* self-signed */ + signerKey = &privKeys[dex]; + } + else { + /* previous subject becomes current issuer */ + CB_FreeX509Name(issuerName); + issuerName = subjectName; + signerKey = &privKeys[dex+1]; + } + subjectName = CB_BuildX509Name(&nameOid, 1); + if((subjectName == NULL) || (issuerName == NULL)) { + printf("Error creating X509Names\n"); + crtn = CSSMERR_CSSM_MEMORY_ERROR; + break; + } + + /* + * not before/after in Y2k-compliant generalized time format. + * These come preformatted from our caller. + */ + notBefore = CB_BuildX509Time(0, notBeforeStr); + notAfter = CB_BuildX509Time(0, notAfterStr); + + /* + * Cook up cert template + * Note serial number would be app-specified in real world + */ + rawCert = CB_MakeCertTemplate(clHand, + SERIAL_NUMBER_BASE + dex, // serial number + issuerName, + subjectName, + notBefore, + notAfter, + &pubKeys[dex], + sigAlg, + NULL, // subj unique ID + NULL, // issuer unique ID + &exten, // extensions + (dex == 0) ? 0 : 1);// numExtensions + + if(rawCert == NULL) { + crtn = CSSM_ERRCODE_INTERNAL_ERROR; + break; + } + + /* Free the stuff we allocd to get here */ + CB_FreeX509Time(notBefore); + CB_FreeX509Time(notAfter); + + /**** sign the cert ****/ + /* 1. get a signing context */ + crtn = CSSM_CSP_CreateSignatureContext(cspHand, + sigAlg, + NULL, // no passphrase for now + signerKey, + &signContext); + if(crtn) { + printError("CreateSignatureContext", crtn); + break; + } + + /* 2. use CL to sign the cert */ + signedCert.Data = NULL; + signedCert.Length = 0; + crtn = CSSM_CL_CertSign(clHand, + signContext, + rawCert, // CertToBeSigned + NULL, // SignScope per spec + 0, // ScopeSize per spec + &signedCert); + if(crtn) { + printError("CSSM_CL_CertSign", crtn); + break; + } + + /* 3. Optionally store the cert in DL */ + if((storeArray != NULL) && storeArray[dex].DBHandle != 0) { + crtn = tpStoreRawCert(storeArray[dex], + clHand, + &signedCert); + if(crtn) { + break; + } + } + + /* 4. delete signing context */ + crtn = CSSM_DeleteContext(signContext); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + break; + } + + /* + * CSSM_CL_CertSign() returned us a mallocd CSSM_DATA. Copy + * its fields to caller's cert. + */ + certs[dex] = signedCert; + + /* and the raw unsigned cert as well */ + appFreeCssmData(rawCert, CSSM_TRUE); + rtn = 0; + } + + /* free resources */ + if(issuerName != NULL) { + CB_FreeX509Name(issuerName); + } + if(subjectName != NULL) { + CB_FreeX509Name(subjectName); + } + return crtn; +} + +/* compare two CSSM_CERTGROUPs, returns CSSM_TRUE on success */ +CSSM_BOOL tpCompareCertGroups( + const CSSM_CERTGROUP *grp1, + const CSSM_CERTGROUP *grp2) +{ + unsigned i; + CSSM_DATA_PTR d1; + CSSM_DATA_PTR d2; + + if(grp1->NumCerts != grp2->NumCerts) { + return CSSM_FALSE; + } + for(i=0; iNumCerts; i++) { + d1 = &grp1->GroupList.CertList[i]; + d2 = &grp2->GroupList.CertList[i]; + + /* these are all errors */ + if((d1->Data == NULL) || + (d1->Length == 0) || + (d2->Data == NULL) || + (d2->Length == 0)) { + printf("compareCertGroups: bad cert group!\n"); + return CSSM_FALSE; + } + if(d1->Length != d2->Length) { + return CSSM_FALSE; + } + if(memcmp(d1->Data, d2->Data, d1->Length)) { + return CSSM_FALSE; + } + } + return CSSM_TRUE; +} + +/* free a CSSM_CERT_GROUP */ +void tpFreeCertGroup( + CSSM_CERTGROUP_PTR certGroup, + CSSM_BOOL freeCertData, // free individual CertList.Data + CSSM_BOOL freeStruct) // free the overall CSSM_CERTGROUP +{ + unsigned dex; + + if(certGroup == NULL) { + return; + } + + if(freeCertData) { + /* free the individual cert Data fields */ + for(dex=0; dexNumCerts; dex++) { + appFreeCssmData(&certGroup->GroupList.CertList[dex], CSSM_FALSE); + } + } + + /* and the array of CSSM_DATAs */ + if(certGroup->GroupList.CertList) { + CSSM_FREE(certGroup->GroupList.CertList); + } + + if(freeStruct) { + CSSM_FREE(certGroup); + } +} + +CSSM_RETURN clDeleteAllCerts(CSSM_DL_DB_HANDLE dlDb) +{ + CSSM_QUERY query; + CSSM_DB_UNIQUE_RECORD_PTR record = NULL; + CSSM_RETURN crtn; + CSSM_HANDLE resultHand; + CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; + + recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_X509_CERTIFICATE; + recordAttrs.NumberOfAttributes = 0; + recordAttrs.AttributeData = NULL; + + /* just search by recordType, no predicates */ + query.RecordType = CSSM_DL_DB_RECORD_X509_CERTIFICATE; + query.Conjunctive = CSSM_DB_NONE; + query.NumSelectionPredicates = 0; + query.SelectionPredicate = NULL; + query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? + query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? + query.QueryFlags = 0; // CSSM_QUERY_RETURN_DATA...FIXME - used? + + crtn = CSSM_DL_DataGetFirst(dlDb, + &query, + &resultHand, + &recordAttrs, + NULL, // No data + &record); + switch(crtn) { + case CSSM_OK: + break; // proceed + case CSSMERR_DL_ENDOFDATA: + /* OK, no certs */ + return CSSM_OK; + default: + printError("DataGetFirst", crtn); + return crtn; + } + + crtn = CSSM_DL_DataDelete(dlDb, record); + if(crtn) { + printError("CSSM_DL_DataDelete", crtn); + return crtn; + } + CSSM_DL_FreeUniqueRecord(dlDb, record); + + /* now the rest of them */ + for(;;) { + crtn = CSSM_DL_DataGetNext(dlDb, + resultHand, + &recordAttrs, + NULL, + &record); + switch(crtn) { + case CSSM_OK: + crtn = CSSM_DL_DataDelete(dlDb, record); + if(crtn) { + printError("CSSM_DL_DataDelete", crtn); + return crtn; + } + CSSM_DL_FreeUniqueRecord(dlDb, record); + break; // and go again + case CSSMERR_DL_ENDOFDATA: + /* normal termination */ + break; + default: + printError("DataGetNext", crtn); + return crtn; + } + if(crtn != CSSM_OK) { + break; + } + } + CSSM_DL_DataAbortQuery(dlDb, resultHand); + return CSSM_OK; +} + +/* + * Wrapper for CSSM_TP_CertGroupVerify. What an ugly API. + */ +CSSM_RETURN tpCertGroupVerify( + CSSM_TP_HANDLE tpHand, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + CSSM_DL_DB_LIST_PTR dbListPtr, + const CSSM_OID *policy, // optional + const CSSM_DATA *fieldOpts, // optional + const CSSM_DATA *actionData, // optional + void *policyOpts, + const CSSM_CERTGROUP *certGroup, + CSSM_DATA_PTR anchorCerts, + unsigned numAnchorCerts, + CSSM_TP_STOP_ON stopOn, // CSSM_TP_STOP_ON_POLICY, etc. + CSSM_TIMESTRING cssmTimeStr,// optional + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR result) // optional, RETURNED +{ + /* main job is building a CSSM_TP_VERIFY_CONTEXT and its components */ + CSSM_TP_VERIFY_CONTEXT vfyCtx; + CSSM_TP_CALLERAUTH_CONTEXT authCtx; + + memset(&vfyCtx, 0, sizeof(CSSM_TP_VERIFY_CONTEXT)); + vfyCtx.Action = CSSM_TP_ACTION_DEFAULT; + if(actionData) { + vfyCtx.ActionData = *actionData; + } + else { + vfyCtx.ActionData.Data = NULL; + vfyCtx.ActionData.Length = 0; + } + vfyCtx.Cred = &authCtx; + + /* CSSM_TP_CALLERAUTH_CONTEXT components */ + /* + typedef struct cssm_tp_callerauth_context { + CSSM_TP_POLICYINFO Policy; + CSSM_TIMESTRING VerifyTime; + CSSM_TP_STOP_ON VerificationAbortOn; + CSSM_TP_VERIFICATION_RESULTS_CALLBACK CallbackWithVerifiedCert; + uint32 NumberOfAnchorCerts; + CSSM_DATA_PTR AnchorCerts; + CSSM_DL_DB_LIST_PTR DBList; + CSSM_ACCESS_CREDENTIALS_PTR CallerCredentials; + } CSSM_TP_CALLERAUTH_CONTEXT, *CSSM_TP_CALLERAUTH_CONTEXT_PTR; + */ + /* zero or one policy here */ + CSSM_FIELD policyId; + if(policy != NULL) { + policyId.FieldOid = (CSSM_OID)*policy; + authCtx.Policy.NumberOfPolicyIds = 1; + authCtx.Policy.PolicyIds = &policyId; + if(fieldOpts != NULL) { + policyId.FieldValue = *fieldOpts; + } + else { + policyId.FieldValue.Data = NULL; + policyId.FieldValue.Length = 0; + } + } + else { + authCtx.Policy.NumberOfPolicyIds = 0; + authCtx.Policy.PolicyIds = NULL; + } + authCtx.Policy.PolicyControl = policyOpts; + authCtx.VerifyTime = cssmTimeStr; // may be NULL + authCtx.VerificationAbortOn = stopOn; + authCtx.CallbackWithVerifiedCert = NULL; + authCtx.NumberOfAnchorCerts = numAnchorCerts; + authCtx.AnchorCerts = anchorCerts; + authCtx.DBList = dbListPtr; + authCtx.CallerCredentials = NULL; + + return CSSM_TP_CertGroupVerify(tpHand, + clHand, + cspHand, + certGroup, + &vfyCtx, + result); +} + +/* + * Open, optionally create, KC-style DLDB. + */ +#define KC_DB_PATH "Library/Keychains" /* relative to home */ + +CSSM_RETURN tpKcOpen( + CSSM_DL_HANDLE dlHand, + const char *kcName, + const char *pwd, // optional to avoid UI + CSSM_BOOL doCreate, + CSSM_DB_HANDLE *dbHand) // RETURNED +{ + char kcPath[300]; + const char *kcFileName = kcName; + char *userHome = getenv("HOME"); + + if(userHome == NULL) { + /* well, this is probably not going to work */ + userHome = (char *)""; + } + sprintf(kcPath, "%s/%s/%s", userHome, KC_DB_PATH, kcFileName); + return dbCreateOpen(dlHand, kcPath, + doCreate, CSSM_FALSE, pwd, dbHand); +} + +/* + * Free the contents of a CSSM_TP_VERIFY_CONTEXT_RESULT returned from + * CSSM_TP_CertGroupVerify(). + */ +CSSM_RETURN freeVfyResult( + CSSM_TP_VERIFY_CONTEXT_RESULT *ctx) +{ + int numCerts = -1; + CSSM_RETURN crtn = CSSM_OK; + + for(unsigned i=0; iNumberOfEvidences; i++) { + CSSM_EVIDENCE_PTR evp = &ctx->Evidence[i]; + switch(evp->EvidenceForm) { + case CSSM_EVIDENCE_FORM_APPLE_HEADER: + /* Evidence = (CSSM_TP_APPLE_EVIDENCE_HEADER *) */ + appFree(evp->Evidence, NULL); + evp->Evidence = NULL; + break; + case CSSM_EVIDENCE_FORM_APPLE_CERTGROUP: + { + /* Evidence = CSSM_CERTGROUP_PTR */ + CSSM_CERTGROUP_PTR cgp = (CSSM_CERTGROUP_PTR)evp->Evidence; + numCerts = cgp->NumCerts; + tpFreeCertGroup(cgp, CSSM_TRUE, CSSM_TRUE); + evp->Evidence = NULL; + break; + } + case CSSM_EVIDENCE_FORM_APPLE_CERT_INFO: + { + /* Evidence = array of CSSM_TP_APPLE_EVIDENCE_INFO */ + if(numCerts < 0) { + /* Haven't gotten a CSSM_CERTGROUP_PTR! */ + printf("***Malformed VerifyContextResult (2)\n"); + crtn = CSSMERR_TP_INTERNAL_ERROR; + break; + } + CSSM_TP_APPLE_EVIDENCE_INFO *evInfo = + (CSSM_TP_APPLE_EVIDENCE_INFO *)evp->Evidence; + for(unsigned k=0; k<(unsigned)numCerts; k++) { + /* Dispose of StatusCodes, UniqueRecord */ + CSSM_TP_APPLE_EVIDENCE_INFO *thisEvInfo = + &evInfo[k]; + if(thisEvInfo->StatusCodes) { + appFree(thisEvInfo->StatusCodes, NULL); + } + if(thisEvInfo->UniqueRecord) { + CSSM_RETURN crtn = + CSSM_DL_FreeUniqueRecord(thisEvInfo->DlDbHandle, + thisEvInfo->UniqueRecord); + if(crtn) { + printError("CSSM_DL_FreeUniqueRecord", crtn); + printf(" Record %p\n", thisEvInfo->UniqueRecord); + break; + } + thisEvInfo->UniqueRecord = NULL; + } + } /* for each cert info */ + appFree(evp->Evidence, NULL); + evp->Evidence = NULL; + break; + } /* CSSM_EVIDENCE_FORM_APPLE_CERT_INFO */ + } /* switch(evp->EvidenceForm) */ + } /* for each evidence */ + if(ctx->Evidence) { + appFree(ctx->Evidence, NULL); + ctx->Evidence = NULL; + } + return crtn; +} + +/* Display verify results */ +static void statusBitTest( + CSSM_TP_APPLE_CERT_STATUS certStatus, + uint32 bit, + const char *str) +{ + if(certStatus & bit) { + printf("%s ", str); + } +} + +void printCertInfo( + unsigned numCerts, // from CertGroup + const CSSM_TP_APPLE_EVIDENCE_INFO *info) +{ + CSSM_TP_APPLE_CERT_STATUS cs; + + for(unsigned i=0; iStatusBits; + printf(" cert %u:\n", i); + printf(" StatusBits : 0x%x", (unsigned)cs); + if(cs) { + printf(" ( "); + statusBitTest(cs, CSSM_CERT_STATUS_EXPIRED, "EXPIRED"); + statusBitTest(cs, CSSM_CERT_STATUS_NOT_VALID_YET, + "NOT_VALID_YET"); + statusBitTest(cs, CSSM_CERT_STATUS_IS_IN_INPUT_CERTS, + "IS_IN_INPUT_CERTS"); + statusBitTest(cs, CSSM_CERT_STATUS_IS_IN_ANCHORS, + "IS_IN_ANCHORS"); + statusBitTest(cs, CSSM_CERT_STATUS_IS_ROOT, "IS_ROOT"); + statusBitTest(cs, CSSM_CERT_STATUS_IS_FROM_NET, "IS_FROM_NET"); + statusBitTest(cs, CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_USER, + "TRUST_SETTINGS_FOUND_USER"); + statusBitTest(cs, CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_ADMIN, + "TRUST_SETTINGS_FOUND_ADMIN"); + statusBitTest(cs, CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_SYSTEM, + "TRUST_SETTINGS_FOUND_SYSTEM"); + statusBitTest(cs, CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST, + "TRUST_SETTINGS_TRUST"); + statusBitTest(cs, CSSM_CERT_STATUS_TRUST_SETTINGS_DENY, + "TRUST_SETTINGS_DENY"); + statusBitTest(cs, CSSM_CERT_STATUS_TRUST_SETTINGS_IGNORED_ERROR, + "TRUST_SETTINGS_IGNORED_ERROR"); + printf(")\n"); + } + else { + printf("\n"); + } + printf(" NumStatusCodes : %u ", + (unsigned)thisInfo->NumStatusCodes); + for(unsigned j=0; jNumStatusCodes; j++) { + printf("%s ", + cssmErrToStr(thisInfo->StatusCodes[j])); + } + printf("\n"); + printf(" Index: %u\n", (unsigned)thisInfo->Index); + } + return; +} + +/* we really only need CSSM_EVIDENCE_FORM_APPLE_CERT_INFO */ +#define SHOW_ALL_VFY_RESULTS 0 + +void dumpVfyResult( + const CSSM_TP_VERIFY_CONTEXT_RESULT *vfyResult) +{ + unsigned numEvidences = vfyResult->NumberOfEvidences; + unsigned numCerts = 0; + printf("Returned evidence:\n"); + for(unsigned dex=0; dexEvidence[dex]; + #if SHOW_ALL_VFY_RESULTS + printf(" Evidence %u:\n", dex); + #endif + switch(ev->EvidenceForm) { + case CSSM_EVIDENCE_FORM_APPLE_HEADER: + { + #if SHOW_ALL_VFY_RESULTS + const CSSM_TP_APPLE_EVIDENCE_HEADER *hdr = + (const CSSM_TP_APPLE_EVIDENCE_HEADER *)(ev->Evidence); + printf(" Form = HEADER; Version = %u\n", hdr->Version); + #endif + break; + } + case CSSM_EVIDENCE_FORM_APPLE_CERTGROUP: + { + const CSSM_CERTGROUP *grp = + (const CSSM_CERTGROUP *)ev->Evidence; + numCerts = grp->NumCerts; + #if SHOW_ALL_VFY_RESULTS + /* parse the rest of this eventually */ + /* Note we depend on this coming before the CERT_INFO */ + printf(" Form = CERTGROUP; numCerts = %u\n", numCerts); + #endif + break; + } + case CSSM_EVIDENCE_FORM_APPLE_CERT_INFO: + { + const CSSM_TP_APPLE_EVIDENCE_INFO *info = + (const CSSM_TP_APPLE_EVIDENCE_INFO *)ev->Evidence; + printCertInfo(numCerts, info); + break; + } + default: + printf("***UNKNOWN Evidence form (%u)\n", + (unsigned)ev->EvidenceForm); + break; + } + } +} + +/* + * Obtain system anchors in CF and in CSSM_DATA form. + * Caller must CFRelease the returned rootArray and + * free() the returned CSSM_DATA array, but not its + * contents - SecCertificates themselves own that. + */ +OSStatus getSystemAnchors( + CFArrayRef *rootArray, /* RETURNED */ + CSSM_DATA **anchors, /* RETURNED */ + unsigned *numAnchors) /* RETURNED */ +{ + OSStatus ortn; + CFArrayRef cfAnchors; + CSSM_DATA *cssmAnchors; + + ortn = SecTrustSettingsCopyUnrestrictedRoots(false, false, true, + &cfAnchors); + if(ortn) { + cssmPerror("SecTrustSettingsCopyUnrestrictedRoots", ortn); + return ortn; + } + unsigned _numAnchors = CFArrayGetCount(cfAnchors); + cssmAnchors = (CSSM_DATA *)malloc(sizeof(CSSM_DATA) * _numAnchors); + unsigned dex; + for(dex=0; dex<_numAnchors; dex++) { + SecCertificateRef root = (SecCertificateRef)CFArrayGetValueAtIndex( + cfAnchors, dex); + ortn = SecCertificateGetData(root, &cssmAnchors[dex]); + if(ortn) { + cssmPerror("SecCertificateGetData", ortn); + return ortn; + } + } + *rootArray = cfAnchors; + *anchors = cssmAnchors; + *numAnchors = _numAnchors; + return noErr; +} + +/* get a SecCertificateRef from a file */ +SecCertificateRef certFromFile( + const char *fileName) +{ + unsigned char *cp = NULL; + unsigned len = 0; + if(readFile(fileName, &cp, &len)) { + printf("***Error reading file %s\n", fileName); + return NULL; + } + SecCertificateRef certRef; + CSSM_DATA certData = {len, cp}; + OSStatus ortn = SecCertificateCreateFromData(&certData, + CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &certRef); + if(ortn) { + cssmPerror("SecCertificateCreateFromData", ortn); + return NULL; + } + free(cp); + return certRef; +} + diff --git a/SecurityTests/clxutils/clAppUtils/tpUtils.h b/SecurityTests/clxutils/clAppUtils/tpUtils.h new file mode 100644 index 00000000..e8dd72fe --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/tpUtils.h @@ -0,0 +1,181 @@ +/* + * tpUtils.h - TP and cert group test support + */ + +#ifndef _TP_UTILS_H_ +#define _TP_UTILS_H_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define TP_DB_ENABLE 1 + +/* + * Given an array of certs and an uninitialized CSSM_CERTGROUP, place the + * certs into the certgroup and optionally into one of a list of DBs in + * random order. Optionaly the first cert in the array is placed in the + * first element of certgroup. Only error is memory error. It's legal to + * pass in an empty cert array. + */ +CSSM_RETURN tpMakeRandCertGroup( + CSSM_CL_HANDLE clHand, + CSSM_DL_DB_LIST_PTR dbList, + const CSSM_DATA_PTR certs, + unsigned numCerts, + CSSM_CERTGROUP_PTR certGroup, + CSSM_BOOL firstCertIsSubject, // true: certs[0] goes to head + // of certGroup + CSSM_BOOL verbose, + CSSM_BOOL allInDbs, // all certs go to DBs + CSSM_BOOL skipFirstDb); // no certs go to db[0] + +CSSM_RETURN tpStoreCert( + CSSM_DL_DB_HANDLE dlDb, + const CSSM_DATA_PTR cert, + /* REQUIRED fields */ + CSSM_CERT_TYPE certType, // e.g. CSSM_CERT_X_509v3 + uint32 serialNum, + const CSSM_DATA *issuer, // (shouldn't this be subject?) + // normalized & encoded + /* OPTIONAL fields */ + CSSM_CERT_ENCODING certEncoding, // e.g. CSSM_CERT_ENCODING_DER + const CSSM_DATA *printName, + const CSSM_DATA *subject); // normalized & encoded + +/* + * Store a cert when we don't already know the required fields. We'll + * extract them. + */ +CSSM_RETURN tpStoreRawCert( + CSSM_DL_DB_HANDLE dlDb, + CSSM_CL_HANDLE clHand, + const CSSM_DATA_PTR cert); + +/* + * Generate numKeyPairs key pairs of specified algorithm and size. + * Key labels will be 'keyLabelBase' concatenated with a 4-digit + * decimal number. + */ +CSSM_RETURN tpGenKeys( + CSSM_CSP_HANDLE cspHand, + CSSM_DL_DB_HANDLE dbHand, /* keys go here */ + unsigned numKeyPairs, + uint32 keyGenAlg, /* CSSM_ALGID_RSA, etc. */ + uint32 keySizeInBits, + const char *keyLabelBase, /* C string */ + CSSM_KEY_PTR pubKeys, /* array of keys RETURNED here */ + CSSM_KEY_PTR privKeys, /* array of keys RETURNED here */ + CSSM_DATA_PTR paramData = NULL); // optional DSA params + +/* + * Generate a cert chain using specified key pairs. The last cert in the + * chain (certs[numCerts-1]) is a root cert, self-signed. + */ +CSSM_RETURN tpGenCerts( + CSSM_CSP_HANDLE cspHand, + CSSM_CL_HANDLE clHand, + unsigned numCerts, + uint32 sigAlg, /* CSSM_ALGID_SHA1WithRSA, etc. */ + const char *nameBase, /* C string */ + CSSM_KEY_PTR pubKeys, /* array of public keys */ + CSSM_KEY_PTR privKeys, /* array of private keys */ + CSSM_DATA_PTR certs, /* array of certs RETURNED here */ + const char *notBeforeStr, /* from genTimeAtNowPlus() */ + const char *notAfterStr); /* from genTimeAtNowPlus() */ + +/* + * Generate a cert chain using specified key pairs. The last cert in the + * chain (certs[numCerts-1]) is a root cert, self-signed. Store + * the certs indicated by corresponding element on storeArray. If + * storeArray[n].DLHandle == 0, the cert is not stored. + */ +CSSM_RETURN tpGenCertsStore( + CSSM_CSP_HANDLE cspHand, + CSSM_CL_HANDLE clHand, + unsigned numCerts, + uint32 sigAlg, /* CSSM_ALGID_SHA1WithRSA, etc. */ + const char *nameBase, /* C string */ + CSSM_KEY_PTR pubKeys, /* array of public keys */ + CSSM_KEY_PTR privKeys, /* array of private keys */ + CSSM_DL_DB_HANDLE *storeArray, /* array of certs stored here */ + CSSM_DATA_PTR certs, /* array of certs RETURNED here */ + const char *notBeforeStr, /* from genTimeAtNowPlus() */ + const char *notAfterStr); /* from genTimeAtNowPlus() */ + +/* free a CSSM_CERT_GROUP */ +void tpFreeCertGroup( + CSSM_CERTGROUP_PTR certGroup, + CSSM_BOOL freeCertData, // free individual CertList.Data + CSSM_BOOL freeStruct); // free the overall CSSM_CERTGROUP + +CSSM_BOOL tpCompareCertGroups( + const CSSM_CERTGROUP *grp1, + const CSSM_CERTGROUP *grp2); + +CSSM_RETURN clDeleteAllCerts(CSSM_DL_DB_HANDLE dlDb); + +/* + * Wrapper for CSSM_TP_CertGroupVerify. + */ +CSSM_RETURN tpCertGroupVerify( + CSSM_TP_HANDLE tpHand, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + CSSM_DL_DB_LIST_PTR dbListPtr, + const CSSM_OID *policy, // optional + const CSSM_DATA *fieldOpts, // optional + const CSSM_DATA *actionData, // optional + void *policyOpts, + const CSSM_CERTGROUP *certGroup, + CSSM_DATA_PTR anchorCerts, + unsigned numAnchorCerts, + CSSM_TP_STOP_ON stopOn, // CSSM_TP_STOP_ON_POLICY, etc. + CSSM_TIMESTRING cssmTimeStr,// optional + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR result); // RETURNED + +CSSM_RETURN tpKcOpen( + CSSM_DL_HANDLE dlHand, + const char *kcName, + const char *pwd, // optional to avoid UI + CSSM_BOOL doCreate, + CSSM_DB_HANDLE *dbHand); // RETURNED + +CSSM_RETURN freeVfyResult( + CSSM_TP_VERIFY_CONTEXT_RESULT *ctx); + +void printCertInfo( + unsigned numCerts, // from CertGroup + const CSSM_TP_APPLE_EVIDENCE_INFO *info); + +void dumpVfyResult( + const CSSM_TP_VERIFY_CONTEXT_RESULT *vfyResult); + +/* + * Obtain system anchors in CF and in CSSM_DATA form. + * Caller must CFRelease the returned rootArray and + * free() the returned CSSM_DATA array, but not its + * contents - SecCertificates themselves own that. + */ +OSStatus getSystemAnchors( + CFArrayRef *rootArray, /* RETURNED */ + CSSM_DATA **anchors, /* RETURNED */ + unsigned *numAnchors); /* RETURNED */ + +/* get a SecCertificateRef from a file */ +SecCertificateRef certFromFile( + const char *fileName); + +#ifdef __cplusplus +} +#endif +#endif /* _TP_UTILS_H_ */ + diff --git a/SecurityTests/clxutils/clTool/Makefile b/SecurityTests/clxutils/clTool/Makefile new file mode 100644 index 00000000..354e9deb --- /dev/null +++ b/SecurityTests/clxutils/clTool/Makefile @@ -0,0 +1,54 @@ +# name of executable to build +EXECUTABLE=clTool +# C++ source (with .cpp extension) +CPSOURCE= clTool.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lMallocDebug +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/clxutils/clTool/clTool.cpp b/SecurityTests/clxutils/clTool/clTool.cpp new file mode 100644 index 00000000..e634628e --- /dev/null +++ b/SecurityTests/clxutils/clTool/clTool.cpp @@ -0,0 +1,312 @@ +/* + * clTool.cpp - menu-driven CL exerciser + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * A list of OIDs we inquire about. + */ +static const CSSM_OID *knownOids[] = +{ + &CSSMOID_X509V1Version, // not always present + &CSSMOID_X509V1SerialNumber, + &CSSMOID_X509V1IssuerNameCStruct, + &CSSMOID_X509V1SubjectNameCStruct, + &CSSMOID_CSSMKeyStruct, + &CSSMOID_X509V1SubjectPublicKeyCStruct, + &CSSMOID_X509V1ValidityNotBefore, + &CSSMOID_X509V1ValidityNotAfter, + &CSSMOID_X509V1SignatureAlgorithmTBS, + &CSSMOID_X509V1SignatureAlgorithm, + &CSSMOID_X509V1Signature, + &CSSMOID_X509V3CertificateExtensionCStruct, + &CSSMOID_KeyUsage, + &CSSMOID_BasicConstraints, + &CSSMOID_ExtendedKeyUsage, + &CSSMOID_CertificatePolicies, + &CSSMOID_NetscapeCertType +}; + +#define NUM_KNOWN_OIDS (sizeof(knownOids) / sizeof(CSSM_OID *)) + +static const char *oidNames[] = +{ + "CSSMOID_X509V1Version", + "CSSMOID_X509V1SerialNumber", + "CSSMOID_X509V1IssuerNameCStruct", + "CSSMOID_X509V1SubjectNameCStruct", + "CSSMOID_CSSMKeyStruct", + "CSSMOID_X509V1SubjectPublicKeyCStruct", + "CSSMOID_X509V1ValidityNotBefore", + "CSSMOID_X509V1ValidityNotAfter", + "CSSMOID_X509V1SignatureAlgorithmTBS", + "CSSMOID_X509V1SignatureAlgorithm", + "CSSMOID_X509V1Signature", + "CSSMOID_X509V3CertificateExtensionCStruct", + "CSSMOID_KeyUsage", + "CSSMOID_BasicConstraints", + "CSSMOID_ExtendedKeyUsage", + "CSSMOID_CertificatePolicies", + "CSSMOID_NetscapeCertType" +}; + +static void usage(char **argv) +{ + printf("Usage: %s certFile\n", argv[0]); + exit(1); +} + +int main(int argc, char **argv) +{ + CSSM_DATA certData = {0, NULL}; + CSSM_CL_HANDLE clHand = CSSM_INVALID_HANDLE; + CSSM_HANDLE cacheHand = CSSM_INVALID_HANDLE; + CSSM_HANDLE searchHand = CSSM_INVALID_HANDLE; + char resp; + CSSM_RETURN crtn; + unsigned fieldDex; + CSSM_DATA_PTR fieldValue; + uint32 numFields; + CSSM_FIELD field; + CSSM_FIELD_PTR fieldPtr; + OidParser parser; + unsigned len; + + if(argc != 2) { + usage(argv); + } + if(readFile(argv[1], &certData.Data, &len)) { + printf("Can't read file %s' aborting.\n", argv[1]); + exit(1); + } + certData.Length = len; + + while(1) { + fpurge(stdin); + printf("a load/attach\n"); + printf("d detach/unload\n"); + printf("c cache the cert\n"); + printf("u uncache the cert\n"); + printf("g get field (uncached)\n"); + printf("G get field (cached)\n"); + printf("f get all fields, then free\n"); + printf("q quit\n"); + printf("Enter command: "); + resp = getchar(); + switch(resp) { + case 'a': + if(clHand != CSSM_INVALID_HANDLE) { + printf("***Multiple attaches; expect leaks\n"); + } + clHand = clStartup(); + if(clHand == CSSM_INVALID_HANDLE) { + printf("***Error attaching to CL.\n"); + } + else { + printf("...ok\n"); + } + break; + + case 'd': + /* + * Notes: + * -- this should cause the CL to free up all cached certs + * no matter what - even if we've done multiple certCache + * ops. However the plugin framework doesn't delete the + * session object on detach (yet) so expect leaks in + * that case. + * -- we don't clear out cacheHand or searchHand here; this + * allows verification of proper handling of bogus handles. + */ + clShutdown(clHand); + clHand = CSSM_INVALID_HANDLE; + printf("...ok\n"); + break; + + case 'c': + /* cache the cert */ + if(cacheHand != CSSM_INVALID_HANDLE) { + printf("***NOTE: a cert is already cached. Expect leaks.\n"); } + crtn = CSSM_CL_CertCache(clHand, &certData, &cacheHand); + if(crtn) { + printError("CSSM_CL_CertCache", crtn); + } + else { + printf("...ok\n"); + } + break; + + case 'u': + /* abort cache */ + crtn = CSSM_CL_CertAbortCache(clHand, cacheHand); + if(crtn) { + printError("CSSM_CL_CertAbortCache", crtn); + } + else { + cacheHand = CSSM_INVALID_HANDLE; + printf("...ok\n"); + } + break; + + case 'g': + /* get one field (uncached) */ + fieldDex = genRand(0, NUM_KNOWN_OIDS - 1); + crtn = CSSM_CL_CertGetFirstFieldValue(clHand, + &certData, + knownOids[fieldDex], + &searchHand, + &numFields, + &fieldValue); + if(crtn) { + printf("***Error fetching field %s\n", oidNames[fieldDex]); + printError("CSSM_CL_CertGetFirstFieldValue", crtn); + break; + } + printf("%s: %u fields found\n", oidNames[fieldDex], (unsigned)numFields); + field.FieldValue = *fieldValue; + field.FieldOid = *(knownOids[fieldDex]); + printCertField(field, parser, CSSM_TRUE); + crtn = CSSM_CL_FreeFieldValue(clHand, knownOids[fieldDex], fieldValue); + if(crtn) { + printError("CSSM_CL_FreeFieldValue", crtn); + /* keep going */ + } + for(unsigned i=1; i 0 ) + switch ( "$argv[1]" ) + case s: + set QUICK_TEST = 1 + shift + breaksw + case l: + set QUICK_TEST = 0 + shift + breaksw + case v: + set VERB = v + shift + breaksw + case n: + set NO_SSL = 1 + shift + breaksw + case f: + set SSL_PING_ENABLE = + set FULL_SSL = YES + shift + breaksw + case t: + set DO_THREAD = 0 + shift + breaksw + case k: + set SKIP_BASIC = 1 + shift + breaksw + case q: + set QUIET = q + set CERTCRL_QUIET = -q + set PINGSSL_QUIET = s + shift + breaksw + default: + cat cltpdvt_usage + exit(1) + endsw +end + +# +# Select 'quick' or 'normal' test params +# +# Note that we disable DB storage of certs in cgVerify and cgConstruct, to avoid +# messing with user's ~/Library/Keychains. +# +if($QUICK_TEST == 1) then + set CGCONSTRUCT_ARGS="d=0" + set CGVERIFY_ARGS="d" + set CGVERIFY_DSA_ARGS="l=20 d" + set CAVERIFY_ARGS= + set EXTENTEST_ARGS= + if($NO_SSL == 1) then + set THREADTEST_ARGS="ecvsyfF l=10" + else + set THREADTEST_ARGS="l=10" + endif + set THREADPING_ARGS="ep o=mr3 l=5" + set P12REENCODE_ARGS="l=2" +else + set CGCONSTRUCT_ARGS="l=100 d=0" + set CGVERIFY_ARGS="l=100 d" + set CAVERIFY_ARGS="l=500" + set CGVERIFY_DSA_ARGS="l=500 d" + set EXTENTEST_ARGS="l=100" + if($NO_SSL == 1) then + set THREADTEST_ARGS="l=100 ecvsyfF" + else + set THREADTEST_ARGS="l=100" + endif + set THREADPING_ARGS="ep o=mr3 l=10" + set P12REENCODE_ARGS="l=10" +endif +# +set CLXUTILS=`pwd` + +if($SKIP_BASIC == 0) then + # + # test RSA, FEE, ECDSA with the following two... + # + $BUILD_DIR/cgConstruct $CGCONSTRUCT_ARGS $QUIET $VERB || exit(1) + $BUILD_DIR/cgConstruct $CGCONSTRUCT_ARGS a=f $QUIET $VERB || exit(1) + $BUILD_DIR/cgConstruct $CGCONSTRUCT_ARGS a=E $QUIET $VERB || exit(1) + $BUILD_DIR/cgVerify $CGVERIFY_ARGS n=2 $QUIET $VERB || exit(1) + $BUILD_DIR/cgVerify $CGVERIFY_ARGS $QUIET $VERB || exit(1) + $BUILD_DIR/cgVerify $CGVERIFY_ARGS a=e $QUIET $VERB || exit(1) + $BUILD_DIR/cgVerify $CGVERIFY_ARGS a=5 $QUIET $VERB || exit(1) + $BUILD_DIR/cgVerify $CGVERIFY_ARGS a=E $QUIET $VERB || exit(1) + # + # And one run for DSA partial key processing; run in the test + # dir to pick up DSA params + # + cd $CLXUTILS/cgVerify + $BUILD_DIR/cgVerify $CGVERIFY_DSA_ARGS a=d $QUIET $VERB || exit(1) + $BUILD_DIR/caVerify $CAVERIFY_ARGS $QUIET $VERB || exit(1) + $BUILD_DIR/caVerify a=E $CAVERIFY_ARGS $QUIET $VERB || exit(1) +endif + +# +# Anchor and intermediate test: once with normal anchors, one with +# Trust Settings. +# +### +### Allow expired anchors until Radar 6133507 is fixed +### +echo "### Warning: allowing expired roots in anchorTest..." +$BUILD_DIR/anchorTest e $QUIET $VERB || exit(1) +$BUILD_DIR/anchorTest t e $QUIET $VERB || exit(1) +$CLXUTILS/anchorTest/intermedTest $QUIET || exit(1) +$CLXUTILS/anchorTest/intermedTest t $QUIET || exit(1) +$BUILD_DIR/trustAnchors $QUIET || exit(1) + +cd $CLXUTILS +./updateCerts + +$BUILD_DIR/certSerialEncodeTest $QUIET || exit(1) + +# +# certcrl script tests require files relative to cwd +# +cd $CLXUTILS/certcrl/testSubjects/X509tests +$BUILD_DIR/certcrl -S x509tests.scr $CERTCRL_QUIET || exit(1) +cd $CLXUTILS/certcrl/testSubjects/smime +$BUILD_DIR/certcrl -S smime.scr $CERTCRL_QUIET || exit(1) +# +# disable expiredRoot test since it makes assumptions about +# store.apple.com which are no longer true %%%FIXME! +#cd $CLXUTILS/certcrl/testSubjects/expiredRoot +#$BUILD_DIR/certcrl -S expiredRoot.scr $CERTCRL_QUIET || exit(1) +# +cd $CLXUTILS/certcrl/testSubjects/expiredCerts +$BUILD_DIR/certcrl -S expiredCerts.scr $CERTCRL_QUIET || exit(1) +# +cd $CLXUTILS/certcrl/testSubjects/anchorAndDb +$BUILD_DIR/certcrl -S anchorAndDb.scr $CERTCRL_QUIET || exit(1) +# +cd $CLXUTILS/certcrl/testSubjects/hostNameDot +$BUILD_DIR/certcrl -S hostNameDot.scr $CERTCRL_QUIET || exit(1) +# +# one with normal anchors, one with Trust Settings +cd $CLXUTILS/certcrl/testSubjects/AppleCerts +$BUILD_DIR/certcrl -S AppleCerts.scr $CERTCRL_QUIET || exit(1) +$BUILD_DIR/certcrl -S AppleCerts.scr -g $CERTCRL_QUIET || exit(1) +# +# one with normal anchors, one with Trust Settings +# This will fail if you have userTrustSettings.plist, from ../trustSettings, +# installed! +# Note this should eventually be renamed to something like SWUpdateSigning... +cd $CLXUTILS/certcrl/testSubjects/AppleCodeSigning +$BUILD_DIR/certcrl -S AppleCodeSigning.scr $CERTCRL_QUIET || exit(1) +$BUILD_DIR/certcrl -S AppleCodeSigning.scr -g $CERTCRL_QUIET || exit(1) +# +cd $CLXUTILS/certcrl/testSubjects/CodePkgSigning +$BUILD_DIR/certcrl -S CodePkgSigning.scr $CERTCRL_QUIET || exit(1) +# +cd $CLXUTILS/certcrl/testSubjects/localTime +$BUILD_DIR/certcrl -S localTime.scr $CERTCRL_QUIET || exit(1) +# +# one with normal anchors, one with Trust Settings +cd $CLXUTILS/certcrl/testSubjects/serverGatedCrypto +$BUILD_DIR/certcrl -S sgc.scr $CERTCRL_QUIET || exit(1) +$BUILD_DIR/certcrl -S sgc.scr -g $CERTCRL_QUIET || exit(1) +# +cd $CLXUTILS/certcrl/testSubjects/crlTime +$BUILD_DIR/certcrl -S crlTime.scr $CERTCRL_QUIET || exit(1) +cd $CLXUTILS/certcrl/testSubjects/implicitAnchor +$BUILD_DIR/certcrl -S implicitAnchor.scr $CERTCRL_QUIET || exit(1) +cd $CLXUTILS/certcrl/testSubjects/crossSigned +$BUILD_DIR/certcrl -S crossSigned.scr $CERTCRL_QUIET || exit(1) +cd $CLXUTILS/certcrl/testSubjects/emptyCert +$BUILD_DIR/certcrl -S emptyCert.scr $CERTCRL_QUIET || exit(1) +cd $CLXUTILS/certcrl/testSubjects/emptySubject +$BUILD_DIR/certcrl -S emptySubject.scr $CERTCRL_QUIET || exit(1) +cd $CLXUTILS/certcrl/testSubjects/qualCertStatment +$BUILD_DIR/certcrl -S qualCertStatement.scr $CERTCRL_QUIET || exit(1) +cd $CLXUTILS/certcrl/testSubjects/ipSec +$BUILD_DIR/certcrl -S ipSec.scr $CERTCRL_QUIET || exit(1) +# +# ECDSA certs, lots of 'em +# +cd $CLXUTILS/certcrl/testSubjects/NSS_ECC +$BUILD_DIR/certcrl -S nssecc.scr $CERTCRL_QUIET || exit(1) +$BUILD_DIR/certcrl -S msEcc.scr $CERTCRL_QUIET || exit(1) +$BUILD_DIR/certcrl -S opensslEcc.scr $CERTCRL_QUIET || exit(1) + +# +# CRL/OCSP tests +# once each with normal anchors, one with Trust Settings +# +# Until Verisign gets their CRL server fixed, we have to allow the disabling of the +# CRL test.... +# +if($NO_SSL == 0) then + cd $CLXUTILS + if($FULL_SSL == YES) then + cd $CLXUTILS/certcrl/testSubjects/crlFromSsl + $BUILD_DIR/certcrl -S crlssl.scr $CERTCRL_QUIET || exit(1) + $BUILD_DIR/certcrl -S crlssl.scr -g $CERTCRL_QUIET || exit(1) + endif + cd $CLXUTILS/certcrl/testSubjects/ocspFromSsl + # this test makes assumptions about store.apple.com which are no longer + # true, so need to disable the test for now. %%%FIXME! + #$BUILD_DIR/certcrl -S ocspssl.scr $CERTCRL_QUIET || exit(1) + #$BUILD_DIR/certcrl -S ocspssl.scr -g $CERTCRL_QUIET || exit(1) +endif +# +$BUILD_DIR/extenTest $EXTENTEST_ARGS $QUIET $VERB || exit(1) +$BUILD_DIR/extenTestTp $EXTENTEST_ARGS $QUIET $VERB || exit(1) +$BUILD_DIR/sslSubjName $QUIET $VERB || exit(1) +$BUILD_DIR/smimePolicy $QUIET $VERB || exit(1) +$BUILD_DIR/certLabelTest $CERTCRL_QUIET || exit(1) + +# +# extendAttrTest has to be run from specific directory for access to keys and certs +# +cd $CLXUTILS/extendAttrTest +$BUILD_DIR/extendAttrTest -k $BUILD_DIR/eat.keychain $CERTCRL_QUIET || exit(1) + +# +# threadTest relies on a cert file in cwd +# +if($DO_THREAD == 1) then + cd $CLXUTILS/threadTest + $BUILD_DIR/threadTest $THREADTEST_ARGS $QUIET $VERB || exit(1) +endif +# +# CMS tests have to be run from specific directory for access to keychain and certs +# +cd $CLXUTILS/newCmsTool/blobs +./cmstestHandsoff $CERTCRL_QUIET || exit(1) +./cmsEcdsaHandsoff $CERTCRL_QUIET || exit(1) + +# +# This one uses a number of p12 files in cwd +# +# we may never see this again.... +# +# echo ==== skipping p12Reencode for now, but I really want this back === +# cd $CLXUTILS/p12Reencode +# ./doReencode $P12REENCODE_ARGS $QUIET || exit(1) +# + +# +# Import/export tests, always run from here with no default ACL (to avoid UI). +# +cd $CLXUTILS/importExport +./importExport n $QUIET || exit(1) + +# sslEcdsa test removed pending validation of tls.secg.org server +# +# $BUILD_DIR/sslEcdsa $CERTCRL_QUIET || exit(1) + +# +# Full SSL tests run: +# -- once with blocking socket I/O +# -- once with nonblocking socket I/O +# -- once with RingBuffer I/O, no verifyPing +# +if($NO_SSL == 0) then + cd $CLXUTILS/sslScripts + ./makeLocalCert a || exit(1) + ./ssldvt $SSL_PING_ENABLE $QUIET $VERB || exit(1) + ./ssldvt $SSL_PING_ENABLE $QUIET $VERB b || exit(1) + ./ssldvt n $QUIET $VERB R || exit(1) + ./removeLocalCerts +endif +if($FULL_SSL == YES) then + $BUILD_DIR/threadTest $THREADPING_ARGS $QUIET $VERB || exit(1) +endif + +echo ==== cltpdvt success ==== + diff --git a/SecurityTests/clxutils/cltpdvt_usage b/SecurityTests/clxutils/cltpdvt_usage new file mode 100644 index 00000000..9d6d12cb --- /dev/null +++ b/SecurityTests/clxutils/cltpdvt_usage @@ -0,0 +1,10 @@ +Usage: cltpdvt [options] +Options: + l long test + v verbose output + q quiet output + n no SSL (not even local loopback tests) + f full SSL test + k skip basic cert group tests + t no threadTest + h help diff --git a/SecurityTests/clxutils/clxutils.pbproj/project.pbxproj b/SecurityTests/clxutils/clxutils.pbproj/project.pbxproj new file mode 100644 index 00000000..ae3b00db --- /dev/null +++ b/SecurityTests/clxutils/clxutils.pbproj/project.pbxproj @@ -0,0 +1,70 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 38; + objects = { + 055C346A044F0AF9006A3C68 = { + children = ( + ); + isa = PBXGroup; + refType = 4; + }; + 055C346C044F0AF9006A3C68 = { + buildRules = ( + ); + buildSettings = { + COPY_PHASE_STRIP = NO; + }; + isa = PBXBuildStyle; + name = Development; + }; + 055C346D044F0AF9006A3C68 = { + buildRules = ( + ); + buildSettings = { + COPY_PHASE_STRIP = YES; + }; + isa = PBXBuildStyle; + name = Deployment; + }; + 055C346E044F0AF9006A3C68 = { + buildStyles = ( + 055C346C044F0AF9006A3C68, + 055C346D044F0AF9006A3C68, + ); + hasScannedForEncodings = 1; + isa = PBXProject; + mainGroup = 055C346A044F0AF9006A3C68; + projectDirPath = ""; + targets = ( + 055C346F044F0B1B006A3C68, + ); + }; + 055C346F044F0B1B006A3C68 = { + buildArgumentsString = "$ACTION \"SRCROOT=$SRCROOT\" \"OBJROOT=$OBJROOT\" \"DSTROOT=$DSTROOT\" \"SRCROOT=$SRCROOT\""; + buildPhases = ( + ); + buildSettings = { + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = cspxutils; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; + }; + buildToolPath = /usr/bin/gnumake; + dependencies = ( + ); + isa = PBXLegacyTarget; + name = clxutils; + passBuildSettingsInEnvironment = 1; + productName = cspxutils; + settingsToExpand = 6; + settingsToPassInEnvironment = 287; + settingsToPassOnCommandLine = 280; + }; + }; + rootObject = 055C346E044F0AF9006A3C68; +} diff --git a/SecurityTests/clxutils/cmsTime/Makefile b/SecurityTests/clxutils/cmsTime/Makefile new file mode 100644 index 00000000..54390884 --- /dev/null +++ b/SecurityTests/clxutils/cmsTime/Makefile @@ -0,0 +1,58 @@ +# name of executable to build +EXECUTABLE=cmsTime +# C++ source (with .cpp extension) +CPSOURCE= cmsTime.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= -framework CoreFoundation +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +# +# Optional files on which *.{c,cpp} depend +# +HDR_DEPENDS=../clAppUtils/certVerify.h + +include ../Makefile.cdsa diff --git a/SecurityTests/clxutils/cmsTime/cmsTime.cpp b/SecurityTests/clxutils/cmsTime/cmsTime.cpp new file mode 100644 index 00000000..b87102aa --- /dev/null +++ b/SecurityTests/clxutils/cmsTime/cmsTime.cpp @@ -0,0 +1,156 @@ +/* + * cmsTime.cpp - measure performance of CMS decode & verify + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LOOPS_DEF 100 +#define SIGNED_FILE "noRoot.p7" + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" -l loops -- loops; default %d; 0=forever\n", LOOPS_DEF); + printf(" -i inFile -- input file; default is %s\n", SIGNED_FILE); + printf(" -K -- set empty KC list\n"); + /* etc. */ + exit(1); +} + +/* perform one CMS decode */ +static OSStatus doDecode( + const void *cmsData, + size_t cmsDataLen, + SecPolicyRef policyRef, + CFArrayRef kcArray) /* optional */ + +{ + OSStatus ortn; + CMSDecoderRef cmsDecoder = NULL; + + CMSDecoderCreate(&cmsDecoder); + if(kcArray) { + ortn = CMSDecoderSetSearchKeychain(cmsDecoder, kcArray); + if(ortn) { + cssmPerror("CMSDecoderSetSearchKeychain", ortn); + return ortn; + } + } + ortn = CMSDecoderUpdateMessage(cmsDecoder, cmsData, cmsDataLen); + if(ortn) { + cssmPerror("CMSDecoderUpdateMessage", ortn); + return ortn; + } + ortn = CMSDecoderFinalizeMessage(cmsDecoder); + if(ortn) { + cssmPerror("CMSDecoderFinalizeMessage", ortn); + return ortn; + } + + CMSSignerStatus signerStatus; + ortn = CMSDecoderCopySignerStatus(cmsDecoder, 0, policyRef, true, &signerStatus, NULL, NULL); + if(ortn) { + cssmPerror("CMSDecoderCopySignerStatus", ortn); + return ortn; + } + if(signerStatus != kCMSSignerValid) { + printf("***Bad signerStatus (%d)\n", (int)signerStatus); + ortn = -1; + } + CFRelease(cmsDecoder); + return ortn; +} + +int main(int argc, char **argv) +{ + unsigned dex; + + CFArrayRef emptyKCList = NULL; + unsigned char *blob = NULL; + unsigned blobLen; + SecPolicyRef policyRef = NULL; + + /* user-spec'd variables */ + unsigned loops = LOOPS_DEF; + char *blobFile = SIGNED_FILE; + bool emptyList = false; /* specify empty KC list */ + + extern char *optarg; + int arg; + while ((arg = getopt(argc, argv, "l:i:Kh")) != -1) { + switch (arg) { + case 'l': + loops = atoi(optarg); + break; + case 'i': + blobFile = optarg; + break; + case 'K': + emptyList = true; + emptyKCList = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); + break; + case 'h': + usage(argv); + } + } + if(optind != argc) { + usage(argv); + } + + if(readFile(blobFile, &blob, &blobLen)) { + printf("***Error reading %s\n", blobFile); + exit(1); + } + /* cook up reusable policy object */ + SecPolicySearchRef policySearch = NULL; + OSStatus ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3, + &CSSMOID_APPLE_X509_BASIC, + NULL, // policy opts + &policySearch); + if(ortn) { + cssmPerror("SecPolicySearchCreate", ortn); + exit(1); + } + ortn = SecPolicySearchCopyNext(policySearch, &policyRef); + if(ortn) { + cssmPerror("SecPolicySearchCopyNext", ortn); + exit(1); + } + CFRelease(policySearch); + + CFAbsoluteTime startTimeFirst; + CFAbsoluteTime endTimeFirst; + CFAbsoluteTime startTimeMulti; + CFAbsoluteTime endTimeMulti; + + /* GO */ + startTimeFirst = CFAbsoluteTimeGetCurrent(); + if(doDecode(blob, blobLen, policyRef, emptyKCList)) { + exit(1); + } + endTimeFirst = CFAbsoluteTimeGetCurrent(); + + startTimeMulti = CFAbsoluteTimeGetCurrent(); + for(dex=0; dexm&MMbLuzJ{t5Yq70WTdj4fMeX<~-2ft;PNy^d;hotZ-*?Y`yZ794 z?stKnX6>0jC;u4}vV=`~pobv{V*qQK1@9dy>|j9wqX3Xe@1{o#2XyKb93}7!0wvU_ zPPtlz%2aY6wHC!yiQ2Uq!ka#bNKtG514h1v5(->}{(ro=#D9N?P8l2~BW)}&!WYO# zXrjUp3{zQcKLX|m2M|K8IAM?gY79c-z|s)R9k|lSfX?AYD`e>ej*8VPU1~C+RINs* zNQkvl(fNej8=D3^%`hs*br>eWwK}y*mW+mKaXdw)Oh&_Xx>WO9;t=3Co(TjP@b$xl ze7-;+B}3t;5WI^yfk{L4?1t-&l!?Go5^(Jx;Pu{FLv}Xu6eW?U2$pFy$+&l-It3UZ zm(fduEGSeX#G;USI&6d>N^^nU_C^)N#d7x+)a+ec1>1d49}@bUu_CPPx}w{jt|%A7 ziy9Wp2#PTNN?*CREMUdHb(6z#>=+9lx^&(s4wy{K%BncJrRd2SD0Io?`otw@ZfSGZ z&J}Cd5I;Z9DxB?%mS`IvJzpe3EM--$9C~bYYhP*uJ-lwKCaOcu4zAezDqkRmGg+PG zN}_PPgXcp^PDE_ozD>W>&JaF6BJYoB@sJ{?Shi(R$8NWEE=-l>mRxbG_vaSf+r0Q@ zYtO-3P2HI-rw~~u(U0y|njNZwT#6j>MQce4(rLKLXl3-G{1lIcloWGt{X{FBBp=1C3&4InU}j3$)S3e{ks zI5*6+uxK7v{3_wDeDA>WtGjzE?qy!@o!h^VU6m9ky;HqCdP{hdN5>vS>^^Ttcunta zW*X6ToFwv1X>8dl}aFxHWHl$88=kQfHBZt{)OK#2o#L7NndFJ%88pIKVLr z%Zf857S|EDR)vaX8XU6)Hs-V?$J!jC(du*+<^b%?IXZ{^59wo5fQNaG!EqAfT0*%> znJ6QaY8AQ&*QO~GaUD8anWof{8O#m1n2}V@#D8^$I0WN?sUtQd<;>L#+sA9wuziAw zLHi9#+iV{`@W=eY;2`aTnM0v3Uoc%TUHVomY^WH`wAo#TLXz!`FsX?zYeg}-m=_D$ zy33`GiW8}bX2*B;2C5w&v|o4<_t+t=J$p=`?D6rai_n!j5<0jBCrYPn9H%Mj>-vqC zC*3n^&Ej)SB8KHpkDQ8yZl0V=ysN(((`QnT@%}twA7ptvSP#pu)zu!UzoeECeABQX08=WWYvT0J_T&a9=Bj%3({i z$}|~)&zB|O$-Z6~KVUR#q(03Snp4mt$+^$)KF_RP)v%hC-PCaGy<`Ob&` z5IXJgsu22|=;un%k2RuK`+krmoVp%3VSR3M`9#WT2ZoW@=`JZrID2FAnppS3zTKZq zFDgJI@%Ykjo;~~U>oZmh8lT?xyJO=JCx}S@aj|oT@muE!f}3v5mnVe|ERV+{F(ceX zTIe*{{DAUph-awpyy>zgBP1ZbHgcR(F~&$>36TwGWCp?Pkg+$P+HI*p3l9vOoKg|B zKf@wsowNyL(5!hh2!V|LHVBsVHrMe1jWK+Ou(p92Sd!^2ayY7YlNLmb5M|6uePwwd zt1Ld!>DF>@P0+dGnIuHw%+@t*Hj(;sBs z2s*ScZeE>sX|$E~CyvYVi16d$und0g^VQpGYjf9sD6h$pU*VTGRlbZ(vbZ{7=&JJ< Dt{_-E literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/cmsTime/withRoot.p7 b/SecurityTests/clxutils/cmsTime/withRoot.p7 new file mode 100644 index 0000000000000000000000000000000000000000..8966e8108df67495621c6246e285efc9ef8c7db6 GIT binary patch literal 6648 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 M4P72wB(}K!2W%#YqW}N^ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/cmstool/Makefile b/SecurityTests/clxutils/cmstool/Makefile new file mode 100644 index 00000000..27c9d3cf --- /dev/null +++ b/SecurityTests/clxutils/cmstool/Makefile @@ -0,0 +1,48 @@ +# name of executable to build +EXECUTABLE=cmstool +# C++ source (with .cpp extension) +CPSOURCE= cmstool.cpp +# C source (.c extension) +CSOURCE= + +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/clxutils/cmstool/cmstool.cpp b/SecurityTests/clxutils/cmstool/cmstool.cpp new file mode 100644 index 00000000..ac24ef92 --- /dev/null +++ b/SecurityTests/clxutils/cmstool/cmstool.cpp @@ -0,0 +1,1220 @@ +/* + * cmstool.cpp - manipluate CMS messages, intended to be an alternate for the + * currently useless cms command in /usr/bin/security + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void usage(char **argv) +{ + printf("Usage: %s cmd [option ...]\n", argv[0]); + printf("cmd values:\n"); + printf(" sign -- create signedData\n"); + printf(" envel -- create envelopedData\n"); + printf(" signEnv -- create nested EnvelopedData(signedData(data))\n"); + printf(" parse -- parse a CMS message file\n"); + printf("Options:\n"); + printf(" -i infile\n"); + printf(" -o outfile\n"); + printf(" -k keychain -- Keychain to search for certs\n"); + printf(" -p -- Use identity picker\n"); + printf(" -r recipient -- specify recipient of enveloped data\n"); + printf(" -c -- parse signer cert\n"); + printf(" -v sign|encr -- verify message is signed/encrypted\n"); + printf(" -e eContentType -- a(uthData)|r(keyData)\n"); + printf(" -d detached -- infile contains detached content (sign only)\n"); + printf(" -D detachedContent -- detached content (parse only)\n"); + printf(" -q -- quiet\n"); + exit(1); +} + +/* high level op */ +typedef enum { + CTO_Sign, + CTO_Envelop, + CTO_SignEnvelop, + CTO_Parse +} CT_Op; + +/* to verify */ +typedef enum { + CTV_None, + CTV_Sign, + CTV_Envelop, + CTV_SignEnvelop +} CT_Vfy; + +/* additional OIDS to specify as eContentType */ +#define OID_PKINIT 0x2B, 6, 1, 5, 2, 3 +#define OID_PKINIT_LEN 6 + +static const uint8 OID_PKINIT_AUTH_DATA[] = {OID_PKINIT, 1}; +static const uint8 OID_PKINIT_DH_KEY_DATA[] = {OID_PKINIT, 2}; +static const uint8 OID_PKINIT_RKEY_DATA[] = {OID_PKINIT, 3}; +static const uint8 OID_PKINIT_KP_CLIENTAUTH[] = {OID_PKINIT, 3}; +static const uint8 OID_PKINIT_KPKDC[] = {OID_PKINIT, 5}; + +static const CSSM_OID CSSMOID_PKINIT_AUTH_DATA = + {OID_PKINIT_LEN+1, (uint8 *)OID_PKINIT_AUTH_DATA}; +static const CSSM_OID CSSMOID_PKINIT_DH_KEY_DATA = + {OID_PKINIT_LEN+1, (uint8 *)OID_PKINIT_DH_KEY_DATA}; +static const CSSM_OID CSSMOID_PKINIT_RKEY_DATA = + {OID_PKINIT_LEN+1, (uint8 *)OID_PKINIT_RKEY_DATA}; +static const CSSM_OID CSSMOID_PKINIT_KP_CLIENTAUTH = + {OID_PKINIT_LEN+1, (uint8 *)OID_PKINIT_KP_CLIENTAUTH}; +static const CSSM_OID CSSMOID_PKINIT_KPKDC = + {OID_PKINIT_LEN+1, (uint8 *)OID_PKINIT_KPKDC}; + +typedef struct { + CSSM_OID contentType; + CSSM_DATA content; +} SimpleContentInfo; + +const SecAsn1Template SimpleContentInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SimpleContentInfo) }, + { SEC_ASN1_OBJECT_ID, offsetof(SimpleContentInfo, contentType) }, + { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(SimpleContentInfo, content), + kSecAsn1AnyTemplate }, + { 0, } +}; + +/* + * Obtain the content of a contentInfo, This basically strips off the contentType OID + * and returns a mallocd copy of the ASN_ANY content. + */ +static OSStatus ContentInfoContent( + const unsigned char *contentInfo, + unsigned contentInfoLen, + unsigned char **content, /* mallocd and RETURNED */ + unsigned *contentLen) /* RETURNED */ +{ + SecAsn1CoderRef coder = NULL; + OSStatus ortn; + SimpleContentInfo decodedInfo; + + ortn = SecAsn1CoderCreate(&coder); + if(ortn) { + return ortn; + } + memset(&decodedInfo, 0, sizeof(decodedInfo)); + ortn = SecAsn1Decode(coder, contentInfo, contentInfoLen, + SimpleContentInfoTemplate, &decodedInfo); + if(ortn) { + goto errOut; + } + if(decodedInfo.content.Data == NULL) { + printf("***Error decoding contentInfo: no content\n"); + ortn = internalComponentErr; + goto errOut; + } + *content = (unsigned char *)malloc(decodedInfo.content.Length); + memmove(*content, decodedInfo.content.Data, decodedInfo.content.Length); + *contentLen = decodedInfo.content.Length; +errOut: + SecAsn1CoderRelease(coder); + return ortn; +} + +/* + * Find a cert in specified keychain or keychain list matching specified + * email address. We happen to knopw that the email address is stored with the + * kSecKeyAlias attribute. + */ +static OSStatus findCert( + const char *emailAddress, + CFTypeRef kcArArray, // kc, array, or even NULL + SecCertificateRef *cert) +{ + OSStatus ortn; + SecKeychainSearchRef srch; + SecKeychainAttributeList attrList; + SecKeychainAttribute attr; + + attr.tag = kSecKeyAlias; + attr.length = strlen(emailAddress); + attr.data = (void *)emailAddress; + attrList.count = 1; + attrList.attr = &attr; + + ortn = SecKeychainSearchCreateFromAttributes(kcArArray, + kSecCertificateItemClass, + &attrList, + &srch); + if(ortn) { + cssmPerror("SecKeychainSearchCreateFromAttributes", ortn); + return ortn; + } + + ortn = SecKeychainSearchCopyNext(srch, (SecKeychainItemRef *)cert); + if(ortn) { + printf("***No certs founmd matching recipient %s. Aborting.\n", + emailAddress); + return ortn; + } + CFRelease(srch); + return noErr; +} + +static void evalSecTrust( + SecTrustRef secTrust, + bool quiet) +{ + OSStatus ortn; + SecTrustResultType secTrustResult; + + ortn = SecTrustEvaluate(secTrust, &secTrustResult); + if(ortn) { + /* should never happen */ + cssmPerror("SecTrustEvaluate", ortn); + return; + } + switch(secTrustResult) { + case kSecTrustResultUnspecified: + /* cert chain valid, no special UserTrust assignments */ + case kSecTrustResultProceed: + /* cert chain valid AND user explicitly trusts this */ + if(!quiet) { + fprintf(stderr, "Successful\n"); + } + return; + case kSecTrustResultDeny: + case kSecTrustResultConfirm: + /* + * Cert chain may well have verified OK, but user has flagged + * one of these certs as untrustable. + */ + printf("Not trusted per user-specified Trust level\n"); + return; + default: + { + /* get low-level TP error */ + OSStatus tpStatus; + ortn = SecTrustGetCssmResultCode(secTrust, &tpStatus); + if(ortn) { + cssmPerror("SecTrustGetCssmResultCode", ortn); + return; + } + switch(tpStatus) { + case CSSMERR_TP_INVALID_ANCHOR_CERT: + fprintf(stderr, "Untrusted root\n"); + return; + case CSSMERR_TP_NOT_TRUSTED: + /* no root, not even in implicit SSL roots */ + fprintf(stderr, "No root cert found\n"); + return; + case CSSMERR_TP_CERT_EXPIRED: + fprintf(stderr, "Expired cert\n"); + return; + case CSSMERR_TP_CERT_NOT_VALID_YET: + fprintf(stderr, "Cert not valid yet\n"); + break; + default: + printf("Other cert failure: "); + cssmPerror("", tpStatus); + return; + } + } + } /* SecTrustEvaluate error */ + +} +static OSStatus parseSignedData( + SecCmsSignedDataRef signedData, + SecArenaPoolRef arena, /* used for detached content only */ + const unsigned char *detachedData, + unsigned detachedDataLen, + CT_Vfy vfyOp, + bool quiet, + bool parseSignerCert) +{ + Boolean b; + b = SecCmsSignedDataHasDigests(signedData); + if(!quiet) { + printf(" has digests : %s\n", b ? "true" : "false"); + } + + SecTrustRef secTrust = NULL; + OSStatus ortn; + SecPolicyRef policy = NULL; + SecPolicySearchRef policySearch = NULL; + + ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3, + &CSSMOID_APPLE_X509_BASIC, + NULL, + &policySearch); + if(ortn) { + cssmPerror("SecPolicySearchCreate", ortn); + return ortn; + } + ortn = SecPolicySearchCopyNext(policySearch, &policy); + if(ortn) { + cssmPerror("SecPolicySearchCopyNext", ortn); + return ortn; + } + + int numSigners = SecCmsSignedDataSignerInfoCount(signedData); + if(!quiet) { + printf(" num signers : %d\n", numSigners); + } + for(int dex=0; dex "); + /* FIXME - does this make sense? Error? */ + } + } + else if(detachedData != NULL) { + /* digest the detached content */ + SECAlgorithmID **digestAlgorithms = SecCmsSignedDataGetDigestAlgs(signedData); + SecCmsDigestContextRef digcx = SecCmsDigestContextStartMultiple(digestAlgorithms); + CSSM_DATA **digests = NULL; + + SecCmsDigestContextUpdate(digcx, detachedData, detachedDataLen); + ortn = SecCmsDigestContextFinishMultiple(digcx, arena, &digests); + if(ortn) { + fprintf(stderr, "SecCmsDigestContextFinishMultiple() returned %d\n", (int)ortn); + } + else { + SecCmsSignedDataSetDigests(signedData, digestAlgorithms, digests); + } + } + else { + fprintf(stderr, " "); + } + ortn = SecCmsSignedDataVerifySignerInfo(signedData, dex, NULL, + policy, &secTrust); + if(ortn) { + fprintf(stderr, "vfSignerInfo() returned %d\n", (int)ortn); + fprintf(stderr, " vfy status : "); + } + if(secTrust == NULL) { + fprintf(stderr, "***NO SecTrust available!\n"); + } + else { + evalSecTrust(secTrust, quiet); + } + + SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, dex); + CFStringRef emailAddrs = SecCmsSignerInfoGetSignerCommonName(signerInfo); + char emailStr[1000]; + if(!quiet) { + fprintf(stderr, " signer : "); + } + if(emailAddrs == NULL) { + fprintf(stderr, "<>\n"); + } + else { + if(!CFStringGetCString(emailAddrs, emailStr, 1000, kCFStringEncodingASCII)) { + fprintf(stderr, "*** Error converting email address to C string\n"); + } + else if(!quiet) { + + fprintf(stderr, "%s\n", emailStr); + } + } + if(parseSignerCert) { + SecCertificateRef signer; + signer = SecCmsSignerInfoGetSigningCertificate(signerInfo, NULL); + if(signer) { + CSSM_DATA certData; + ortn = SecCertificateGetData(signer, &certData); + if(ortn) { + fprintf(stderr, "***Error getting signing cert data***\n"); + cssmPerror("SecCertificateGetData", ortn); + } + else { + printf("========== Signer Cert==========\n\n"); + printCert(certData.Data, certData.Length, CSSM_FALSE); + printf("========== End Signer Cert==========\n\n"); + } + } + else { + fprintf(stderr, "***Error getting signing cert ***\n"); + } + } + } + return ortn; +} + +static OSStatus doParse( + const unsigned char *data, + unsigned dataLen, + const unsigned char *detachedData, + unsigned detachedDataLen, + CT_Vfy vfyOp, + bool parseSignerCert, + bool quiet, + unsigned char **outData, // mallocd and RETURNED + unsigned *outDataLen) // RETURNED +{ + if((data == NULL) || (dataLen == 0)) { + fprintf(stderr, "***Parse requires input file. Aborting.\n"); + return paramErr; + } + + SecArenaPoolRef arena = NULL; + SecArenaPoolCreate(1024, &arena); + SecCmsMessageRef cmsMsg = NULL; + SecCmsDecoderRef decoder; + OSStatus ortn; + OSStatus ourRtn = noErr; + bool foundOneSigned = false; + bool foundOneEnveloped = false; + + ortn = SecCmsDecoderCreate(arena, NULL, NULL, NULL, NULL, NULL, NULL, &decoder); + if(ortn) { + cssmPerror("SecCmsDecoderCreate", ortn); + return ortn; + } + ortn = SecCmsDecoderUpdate(decoder, data, dataLen); + if(ortn) { + cssmPerror("SecCmsDecoderUpdate", ortn); + return ortn; + } + ortn = SecCmsDecoderFinish(decoder, &cmsMsg); + if(ortn) { + cssmPerror("SecCmsDecoderFinish", ortn); + return ortn; + } + + Boolean b = SecCmsMessageIsSigned(cmsMsg); + switch(vfyOp) { + case CTV_None: + break; + case CTV_Sign: + if(!b) { + fprintf(stderr, "***Expected SignedData, but !SecCmsMessageIsSigned()\n"); + ourRtn = -1; + } + break; + case CTV_SignEnvelop: + if(!b) { + fprintf(stderr, "***Expected Signed&Enveloped, but !SecCmsMessageIsSigned()\n"); + ourRtn = -1; + } + break; + case CTV_Envelop: + if(b) { + fprintf(stderr, "***Expected EnvelopedData, but SecCmsMessageIsSigned() " + "TRUE\n"); + ourRtn = -1; + } + break; + } + int numContentInfos = SecCmsMessageContentLevelCount(cmsMsg); + if(!quiet) { + fprintf(stderr, "=== CMS message info ===\n"); + fprintf(stderr, " Signed : %s\n", b ? "true" : "false"); + b = SecCmsMessageIsEncrypted(cmsMsg); + fprintf(stderr, " Encrypted : %s\n", b ? "true" : "false"); + b = SecCmsMessageContainsCertsOrCrls(cmsMsg); + fprintf(stderr, " certs/crls : %s\n", b ? "present" : "not present"); + fprintf(stderr, " Num ContentInfos : %d\n", numContentInfos); + } + + /* FIXME needs work for CTV_SignEnvelop */ + OidParser oidParser; + for(int dex=0; dexLength == 0) { + printf("***EMPTY***\n"); + } + else { + char str[OID_PARSER_STRING_SIZE]; + oidParser.oidParse(typeOid->Data, typeOid->Length, str); + printf("%s\n", str); + } + } + SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci); + switch(tag) { + case SEC_OID_PKCS7_SIGNED_DATA: + { + switch(vfyOp) { + case CTV_None: // caller doesn't care + case CTV_Sign: // got what we wanted + break; + case CTV_Envelop: + fprintf(stderr, "***Expected EnvelopedData, got SignedData\n"); + ourRtn = -1; + break; + case CTV_SignEnvelop: + printf("CTV_SignEnvelop code on demand\n"); + break; + } + foundOneSigned = true; + SecCmsSignedDataRef sd = + (SecCmsSignedDataRef) SecCmsContentInfoGetContent(ci); + parseSignedData(sd, arena, + detachedData, detachedDataLen, + vfyOp, quiet, parseSignerCert); + break; + } + case SEC_OID_PKCS7_DATA: + case SEC_OID_OTHER: + break; + case SEC_OID_PKCS7_ENVELOPED_DATA: + foundOneEnveloped = true; + if(vfyOp == CTV_Sign) { + fprintf(stderr, "***Expected SignedData, EnvelopedData\n"); + ourRtn = -1; + break; + } + case SEC_OID_PKCS7_ENCRYPTED_DATA: + switch(vfyOp) { + case CTV_None: + break; + case CTV_Sign: + fprintf(stderr, "***Expected SignedData, got EncryptedData\n"); + ourRtn = -1; + break; + case CTV_Envelop: + fprintf(stderr, "***Expected EnvelopedData, got EncryptedData\n"); + ourRtn = -1; + break; + case CTV_SignEnvelop: + printf("CTV_SignEnvelop code on demand\n"); + break; + } + break; + default: + fprintf(stderr, " other content type TBD\n"); + } + } + if(outData) { + CSSM_DATA_PTR odata = SecCmsMessageGetContent(cmsMsg); + if(odata == NULL) { + fprintf(stderr, "***No inner content available\n"); + } + else { + *outData = (unsigned char *)malloc(odata->Length); + memmove(*outData, odata->Data, odata->Length); + *outDataLen = odata->Length; + } + } + if(arena) { + SecArenaPoolFree(arena, false); + } + switch(vfyOp) { + case CTV_None: + break; + case CTV_Sign: + if(!foundOneSigned) { + fprintf(stderr, "Expected signed, never saw a SignedData\n"); + ourRtn = -1; + } + break; + case CTV_Envelop: + if(!foundOneEnveloped) { + fprintf(stderr, "Expected enveloped, never saw an EnvelopedData\n"); + ourRtn = -1; + } + break; + case CTV_SignEnvelop: + if(!foundOneSigned) { + fprintf(stderr, "Expected signed, never saw a SignedData\n"); + ourRtn = -1; + } + if(!foundOneEnveloped) { + fprintf(stderr, "Expected enveloped, never saw an EnvelopedData\n"); + ourRtn = -1; + } + break; + } + /* free decoder? cmsMsg? */ + return ourRtn; +} + +/* + * Common encode routine. + */ +#if 1 +/* the simple way, when 3655861 is fixed */ +static OSStatus encodeCms( + SecCmsMessageRef cmsMsg, + const unsigned char *inData, // add in this + unsigned inDataLen, + unsigned char **outData, // mallocd and RETURNED + unsigned *outDataLen) // RETURNED +{ + SecArenaPoolRef arena = NULL; + SecArenaPoolCreate(1024, &arena); + CSSM_DATA cdataIn = {inDataLen, (uint8 *)inData}; + CSSM_DATA cdataOut = {0, NULL}; + + OSStatus ortn = SecCmsMessageEncode(cmsMsg, &cdataIn, arena, &cdataOut); + if((ortn == noErr) && (cdataOut.Length != 0)) { + *outData = (unsigned char *)malloc(cdataOut.Length); + memmove(*outData, cdataOut.Data, cdataOut.Length); + *outDataLen = cdataOut.Length; + } + else { + cssmPerror("SecCmsMessageEncode", ortn); + *outData = NULL; + *outDataLen = 0; + } + SecArenaPoolFree(arena, false); + return ortn; +} + +#else + +/* the hard way back when SecCmsMessageEncode() didn't work */ +static OSStatus encodeCms( + SecCmsMessageRef cmsMsg, + const unsigned char *inData, // add in this + unsigned inDataLen, + unsigned char **outData, // mallocd and RETURNED + unsigned *outDataLen) // RETURNED +{ + SecArenaPoolRef arena = NULL; + SecArenaPoolCreate(1024, &arena); + SecCmsEncoderRef cmsEnc = NULL; + CSSM_DATA output = { 0, NULL }; + OSStatus ortn; + + ortn = SecCmsEncoderCreate(cmsMsg, + NULL, NULL, // no callback + &output, arena, // data goes here + NULL, NULL, // no password callback (right?) + NULL, NULL, // decrypt key callback + NULL, NULL, // detached digests + &cmsEnc); + if(ortn) { + cssmPerror("SecKeychainItemCopyKeychain", ortn); + goto errOut; + } + ortn = SecCmsEncoderUpdate(cmsEnc, (char *)inData, inDataLen); + if(ortn) { + cssmPerror("SecCmsEncoderUpdate", ortn); + goto errOut; + } + ortn = SecCmsEncoderFinish(cmsEnc); + if(ortn) { + cssmPerror("SecCMsEncoderFinish", ortn); + goto errOut; + } + + /* Did we get any data? */ + if(output.Length) { + *outData = (unsigned char *)malloc(output.Length); + memmove(*outData, output.Data, output.Length); + *outDataLen = output.Length; + } + else { + *outData = NULL; + *outDataLen = 0; + } +errOut: + if(arena) { + SecArenaPoolFree(arena, false); + } + return ortn; +} + +#endif + +static OSStatus doSign( + SecIdentityRef signerId, + const unsigned char *inData, + unsigned inDataLen, + bool detachedContent, + const CSSM_OID *eContentType, // OPTIONAL + unsigned char **outData, // mallocd and RETURNED + unsigned *outDataLen) // RETURNED +{ + if((inData == NULL) || (inDataLen == 0) || (outData == NULL)) { + fprintf(stderr, "***Sign requires input file. Aborting.\n"); + return paramErr; + } + if(signerId == NULL) { + fprintf(stderr, "***Sign requires a signing identity. Aborting.\n"); + return paramErr; + } + + SecCmsMessageRef cmsMsg = NULL; + SecCmsContentInfoRef contentInfo = NULL; + SecCmsSignedDataRef signedData = NULL; + SecCertificateRef ourCert = NULL; + SecCmsSignerInfoRef signerInfo; + OSStatus ortn; + SecKeychainRef ourKc = NULL; + + ortn = SecIdentityCopyCertificate(signerId, &ourCert); + if(ortn) { + cssmPerror("SecIdentityCopyCertificate", ortn); + return ortn; + } + ortn = SecKeychainItemCopyKeychain((SecKeychainItemRef)ourCert, &ourKc); + if(ortn) { + cssmPerror("SecKeychainItemCopyKeychain", ortn); + goto errOut; + } + + // build chain of objects: message->signedData->data + cmsMsg = SecCmsMessageCreate(NULL); + if(cmsMsg == NULL) { + fprintf(stderr, "***Error creating SecCmsMessageRef\n"); + ortn = -1; + goto errOut; + } + signedData = SecCmsSignedDataCreate(cmsMsg); + if(signedData == NULL) { + printf("***Error creating SecCmsSignedDataRef\n"); + ortn = -1; + goto errOut; + } + contentInfo = SecCmsMessageGetContentInfo(cmsMsg); + ortn = SecCmsContentInfoSetContentSignedData(cmsMsg, contentInfo, signedData); + if(ortn) { + cssmPerror("SecCmsContentInfoSetContentSignedData", ortn); + goto errOut; + } + contentInfo = SecCmsSignedDataGetContentInfo(signedData); + if(eContentType != NULL) { + ortn = SecCmsContentInfoSetContentOther(cmsMsg, contentInfo, + NULL /* data */, + detachedContent, + eContentType); + if(ortn) { + cssmPerror("SecCmsContentInfoSetContentData", ortn); + goto errOut; + } + } + else { + ortn = SecCmsContentInfoSetContentData(cmsMsg, contentInfo, NULL /* data */, + detachedContent); + if(ortn) { + cssmPerror("SecCmsContentInfoSetContentData", ortn); + goto errOut; + } + } + + /* + * create & attach signer information + */ + signerInfo = SecCmsSignerInfoCreate(cmsMsg, signerId, SEC_OID_SHA1); + if (signerInfo == NULL) { + fprintf(stderr, "***Error on SecCmsSignerInfoCreate\n"); + ortn = -1; + goto errOut; + } + /* we want the cert chain included for this one */ + /* FIXME - what's the significance of the usage? */ + ortn = SecCmsSignerInfoIncludeCerts(signerInfo, SecCmsCMCertChain, certUsageEmailSigner); + if(ortn) { + cssmPerror("SecCmsSignerInfoIncludeCerts", ortn); + goto errOut; + } + + /* other options go here - signing time, etc. */ + + ortn = SecCmsSignerInfoAddSMIMEEncKeyPrefs(signerInfo, ourCert, ourKc); + if(ortn) { + cssmPerror("SecCmsSignerInfoAddSMIMEEncKeyPrefs", ortn); + goto errOut; + } + ortn = SecCmsSignedDataAddCertificate(signedData, ourCert); + if(ortn) { + cssmPerror("SecCmsSignedDataAddCertificate", ortn); + goto errOut; + } + + ortn = SecCmsSignedDataAddSignerInfo(signedData, signerInfo); + if(ortn) { + cssmPerror("SecCmsSignedDataAddSignerInfo", ortn); + goto errOut; + } + + /* go */ + ortn = encodeCms(cmsMsg, inData, inDataLen, outData, outDataLen); +errOut: + /* free resources */ + if(cmsMsg) { + SecCmsMessageDestroy(cmsMsg); + } + if(ourCert) { + CFRelease(ourCert); + } + if(ourKc) { + CFRelease(ourKc); + } + return ortn; +} + +static OSStatus doEncrypt( + SecCertificateRef recipCert, // eventually more than one + const unsigned char *inData, + unsigned inDataLen, + unsigned char **outData, // mallocd and RETURNED + unsigned *outDataLen) // RETURNED +{ + if((inData == NULL) || (inDataLen == 0) || (outData == NULL)) { + fprintf(stderr, "***Encrypt requires input file. Aborting.\n"); + return paramErr; + } + if(recipCert == NULL) { + fprintf(stderr, "***Encrypt requires a recipient certificate. Aborting.\n"); + return paramErr; + } + + SecCmsMessageRef cmsMsg = NULL; + SecCmsContentInfoRef contentInfo = NULL; + SecCmsEnvelopedDataRef envelopedData = NULL; + SecCmsRecipientInfoRef recipientInfo = NULL; + OSStatus ortn; + SecCertificateRef allCerts[2] = { recipCert, NULL}; + + SECOidTag algorithmTag; + int keySize; + + ortn = SecSMIMEFindBulkAlgForRecipients(allCerts, &algorithmTag, &keySize); + if(ortn) { + cssmPerror("SecSMIMEFindBulkAlgForRecipients", ortn); + return ortn; + } + + // build chain of objects: message->envelopedData->data + cmsMsg = SecCmsMessageCreate(NULL); + if(cmsMsg == NULL) { + fprintf(stderr, "***Error creating SecCmsMessageRef\n"); + ortn = -1; + goto errOut; + } + envelopedData = SecCmsEnvelopedDataCreate(cmsMsg, algorithmTag, keySize); + if(envelopedData == NULL) { + fprintf(stderr, "***Error creating SecCmsEnvelopedDataRef\n"); + ortn = -1; + goto errOut; + } + contentInfo = SecCmsMessageGetContentInfo(cmsMsg); + ortn = SecCmsContentInfoSetContentEnvelopedData(cmsMsg, contentInfo, envelopedData); + if(ortn) { + cssmPerror("SecCmsContentInfoSetContentEnvelopedData", ortn); + goto errOut; + } + contentInfo = SecCmsEnvelopedDataGetContentInfo(envelopedData); + ortn = SecCmsContentInfoSetContentData(cmsMsg, contentInfo, NULL /* data */, false); + if(ortn) { + cssmPerror("SecCmsContentInfoSetContentData", ortn); + goto errOut; + } + + /* + * create & attach recipient information + */ + recipientInfo = SecCmsRecipientInfoCreate(cmsMsg, recipCert); + ortn = SecCmsEnvelopedDataAddRecipient(envelopedData, recipientInfo); + if(ortn) { + cssmPerror("SecCmsEnvelopedDataAddRecipient", ortn); + goto errOut; + } + + + /* go */ + ortn = encodeCms(cmsMsg, inData, inDataLen, outData, outDataLen); +errOut: + /* free resources */ + if(cmsMsg) { + SecCmsMessageDestroy(cmsMsg); + } + return ortn; +} + +/* create nested message: msg = EnvelopedData(SignedData(inData)) */ +static OSStatus doSignEncrypt( + SecCertificateRef recipCert, // encryption recipient + SecIdentityRef signerId, // signer + const CSSM_OID *eContentType, // OPTIONAL - for signedData + const unsigned char *inData, + unsigned inDataLen, + unsigned char **outData, // mallocd and RETURNED + unsigned *outDataLen) // RETURNED +{ + if((inData == NULL) || (inDataLen == 0) || (outData == NULL)) { + fprintf(stderr, "***Sign/Encrypt requires input file. Aborting.\n"); + return paramErr; + } + if(recipCert == NULL) { + fprintf(stderr, "***Sign/Encrypt requires a recipient certificate. Aborting.\n"); + return paramErr; + } + if(signerId == NULL) { + fprintf(stderr, "***Sign/Encrypt requires a signer Identity. Aborting.\n"); + return paramErr; + } + + OSStatus ortn; + unsigned char *signedData = NULL; + unsigned signedDataLen = 0; + SecCmsMessageRef cmsMsg = NULL; + SecCmsContentInfoRef contentInfo = NULL; + SecCmsEnvelopedDataRef envelopedData = NULL; + SecCmsRecipientInfoRef recipientInfo = NULL; + SecCertificateRef allCerts[2] = { recipCert, NULL}; + SECOidTag algorithmTag; + int keySize; + + /* first get a SignedData */ + ortn = doSign(signerId, inData, inDataLen, + false, /* can't do detached content here */ + eContentType, + &signedData, &signedDataLen); + if(ortn) { + printf("***Error generating inner signedData. Aborting.\n"); + return ortn; + } + + /* extract just the content - don't need the whole ContentINfo */ + unsigned char *signedDataContent = NULL; + unsigned signedDataContentLen = 0; + ortn = ContentInfoContent(signedData, signedDataLen, &signedDataContent, &signedDataContentLen); + if(ortn) { + goto errOut; + } + + /* now wrap that in an EnvelopedData */ + ortn = SecSMIMEFindBulkAlgForRecipients(allCerts, &algorithmTag, &keySize); + if(ortn) { + cssmPerror("SecSMIMEFindBulkAlgForRecipients", ortn); + return ortn; + } + + // build chain of objects: message->envelopedData->data + cmsMsg = SecCmsMessageCreate(NULL); + if(cmsMsg == NULL) { + fprintf(stderr, "***Error creating SecCmsMessageRef\n"); + ortn = -1; + goto errOut; + } + envelopedData = SecCmsEnvelopedDataCreate(cmsMsg, algorithmTag, keySize); + if(envelopedData == NULL) { + fprintf(stderr, "***Error creating SecCmsEnvelopedDataRef\n"); + ortn = -1; + goto errOut; + } + contentInfo = SecCmsMessageGetContentInfo(cmsMsg); + ortn = SecCmsContentInfoSetContentEnvelopedData(cmsMsg, contentInfo, envelopedData); + if(ortn) { + cssmPerror("SecCmsContentInfoSetContentEnvelopedData", ortn); + goto errOut; + } + contentInfo = SecCmsEnvelopedDataGetContentInfo(envelopedData); + + /* here's the difference: we override the 'data' content with a SignedData type, + * but we fool the smime lib into thinking it's a plain old data so it doesn't try + * to encode the SignedData */ + ortn = SecCmsContentInfoSetContentOther(cmsMsg, contentInfo, + NULL /* data */, + false, + &CSSMOID_PKCS7_SignedData); + if(ortn) { + cssmPerror("SecCmsContentInfoSetContentData", ortn); + goto errOut; + } + + /* + * create & attach recipient information + */ + recipientInfo = SecCmsRecipientInfoCreate(cmsMsg, recipCert); + ortn = SecCmsEnvelopedDataAddRecipient(envelopedData, recipientInfo); + if(ortn) { + cssmPerror("SecCmsEnvelopedDataAddRecipient", ortn); + goto errOut; + } + + + /* go */ + ortn = encodeCms(cmsMsg, signedDataContent, signedDataContentLen, outData, outDataLen); +errOut: + /* free resources */ + if(cmsMsg) { + SecCmsMessageDestroy(cmsMsg); + } + if(signedData) { + free(signedData); + } + if(signedDataContent) { + free(signedDataContent); + } + return ortn; +} + +int main(int argc, char **argv) +{ + if(argc < 2) { + usage(argv); + } + + CT_Op op; + bool needId = false; + if(!strcmp(argv[1], "sign")) { + op = CTO_Sign; + needId = true; + } + else if(!strcmp(argv[1], "envel")) { + op = CTO_Envelop; + } + else if(!strcmp(argv[1], "signEnv")) { + op = CTO_SignEnvelop; + needId = true; + } + else if(!strcmp(argv[1], "parse")) { + op = CTO_Parse; + } + else { + fprintf(stderr, "***Unrecognized cmd.\n"); + usage(argv); + } + + extern int optind; + extern char *optarg; + int arg; + + /* optional args */ + const char *keychainName = NULL; + char *inFileName = NULL; + char *outFileName = NULL; + bool detachedContent = false; + char *detachedFile = NULL; + bool useIdPicker = false; + char *recipient = NULL; + bool quiet = false; + bool parseSignerCert = false; + CT_Vfy vfyOp = CTV_None; + const CSSM_OID *eContentType = NULL; + + optind = 2; + while ((arg = getopt(argc, argv, "i:o:k:pr:e:dD:qcv:")) != -1) { + switch (arg) { + case 'i': + inFileName = optarg; + break; + case 'o': + outFileName = optarg; + break; + case 'k': + keychainName = optarg; + break; + case 'p': + useIdPicker = true; + break; + case 'r': + recipient = optarg; + break; + case 'c': + parseSignerCert = true; + break; + case 'v': + if(!strcmp(optarg, "sign")) { + vfyOp = CTV_Sign; + } + else if(!strcmp(optarg, "encr")) { + vfyOp = CTV_Envelop; + } + else if(!strcmp(optarg, "signEnv")) { + vfyOp = CTV_SignEnvelop; + } + else { + usage(argv); + } + break; + case 'e': + switch(optarg[0]) { + case 'a': + eContentType = &CSSMOID_PKINIT_AUTH_DATA; + break; + case 'r': + eContentType = &CSSMOID_PKINIT_RKEY_DATA; + break; + default: + usage(argv); + } + break; + case 'd': + if(op != CTO_Sign) { + printf("-d only valid for op sign\n"); + exit(1); + } + detachedContent = true; + break; + case 'D': + if(op != CTO_Parse) { + printf("-D only valid for op sign\n"); + exit(1); + } + detachedFile = optarg; + break; + case 'q': + quiet = true; + break; + default: + case '?': + usage(argv); + } + } + if(optind != argc) { + /* getopt does not return '?' */ + usage(argv); + } + + SecIdentityRef idRef = NULL; + SecKeychainRef kcRef = NULL; + SecCertificateRef recipientCert = NULL; + unsigned char *inData = NULL; + unsigned inDataLen = 0; + unsigned char *outData = NULL; + unsigned outDataLen = 0; + unsigned char *detachedData = NULL; + unsigned detachedDataLen = 0; + OSStatus ortn; + + if(inFileName) { + if(readFile(inFileName, &inData, &inDataLen)) { + fprintf(stderr, "***Error reading infile %s. Aborting.\n", inFileName); + exit(1); + } + } + if(detachedFile) { + if(readFile(detachedFile, &detachedData, &detachedDataLen)) { + fprintf(stderr, "***Error reading detachedFile %s. Aborting.\n", detachedFile); + exit(1); + } + } + if(keychainName) { + ortn = SecKeychainOpen(keychainName, &kcRef); + if(ortn) { + cssmPerror("SecKeychainOpen", ortn); + exit(1); + } + } + if(useIdPicker) { + ortn = sslSimpleIdentPicker(kcRef, &idRef); + if(ortn) { + fprintf(stderr, "***Error obtaining identity via picker. Aborting.\n"); + exit(1); + } + } + else if(needId) { + /* use first identity in specified keychain */ + CFArrayRef array = sslKcRefToCertArray(kcRef, CSSM_FALSE, CSSM_FALSE, + NULL, // no verify policy + NULL); + if(array == NULL) { + fprintf(stderr, "***Error finding a signing cert. Aborting.\n"); + exit(1); + } + idRef = (SecIdentityRef)CFArrayGetValueAtIndex(array, 0); + if(idRef == NULL) { + fprintf(stderr, "***No identities found. Aborting.\n"); + exit(1); + } + CFRetain(idRef); + CFRelease(array); + } + if(recipient) { + ortn = findCert(recipient, kcRef, &recipientCert); + if(ortn) { + exit(1); + } + } + + switch(op) { + case CTO_Sign: + ortn = doSign(idRef, inData, inDataLen, + detachedContent, eContentType, + &outData, &outDataLen); + break; + case CTO_Envelop: + if(recipientCert == NULL) { + if(idRef == NULL) { + printf("***Need a recipient or an identity to encrypt\n"); + exit(1); + } + ortn = SecIdentityCopyCertificate(idRef, &recipientCert); + if(ortn) { + cssmPerror("SecIdentityCopyCertificate", ortn); + exit(1); + } + } + ortn = doEncrypt(recipientCert, inData, inDataLen, &outData, &outDataLen); + break; + case CTO_SignEnvelop: + ortn = doSignEncrypt(recipientCert, idRef, eContentType, + inData, inDataLen, &outData, &outDataLen); + break; + case CTO_Parse: + ortn = doParse(inData, inDataLen, + detachedData, detachedDataLen, + vfyOp, parseSignerCert, quiet, + &outData, &outDataLen); + break; + } + if(ortn) { + goto errOut; + } + if(outData && outFileName) { + if(writeFile(outFileName, outData, outDataLen)) { + fprintf(stderr, "***Error writing to %s.\n", outFileName); + ortn = -1; + } + else { + if(!quiet) { + fprintf(stderr, "...wrote %u bytes to %s.\n", outDataLen, outFileName); + } + } + } + else if(outData) { + fprintf(stderr, "...generated %u bytes but no place to write it.\n", outDataLen); + } + else if(outFileName) { + fprintf(stderr, "...nothing to write to file %s.\n", outFileName); + /* assume this is an error, caller wanted something */ + ortn = -1; + } +errOut: + return ortn; +} diff --git a/SecurityTests/clxutils/cmstool/testSubjects/ptext1.txt b/SecurityTests/clxutils/cmstool/testSubjects/ptext1.txt new file mode 100644 index 00000000..9e29cf13 --- /dev/null +++ b/SecurityTests/clxutils/cmstool/testSubjects/ptext1.txt @@ -0,0 +1,772 @@ +/* + * cmstool.cpp - manipluate CMS messages, intended to be an alternate for the + * currently useless cms command in /usr/bin/security + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void usage(char **argv) +{ + printf("Usage: %s cmd [option ...]\n", argv[0]); + printf("cmd values:\n"); + printf(" sign -- create signedData\n"); + printf(" envel -- create envelopedData\n"); + printf(" parse -- parse a CMS message file\n"); + printf("Options:\n"); + printf(" -i infile\n"); + printf(" -o outfile\n"); + printf(" -k keychain -- Keychain to search for certs\n"); + printf(" -p -- Use identity picker\n"); + printf(" -r recipient -- specify recipient of enveloped data\n"); + printf(" -c -- parse signer cert\n"); + printf(" -q -- quiet\n"); + exit(1); +} + +typedef enum { + CTO_Sign, + CTO_Envelop, + CTO_Parse +} CT_Op; + +/* + * Find a cert in specified keychain or keychain list matching specified + * email address. We happen to knopw that the email address is stored with the + * kSecAliasItemAttr attribute. + */ +static OSStatus findCert( + const char *emailAddress, + CFTypeRef kcArArray, // kc, array, or even NULL + SecCertificateRef *cert) +{ + OSStatus ortn; + SecKeychainSearchRef srch; + SecKeychainAttributeList attrList; + SecKeychainAttribute attr; + + attr.tag = kSecAliasItemAttr; + attr.length = strlen(emailAddress); + attr.data = (void *)emailAddress; + attrList.count = 1; + attrList.attr = &attr; + + ortn = SecKeychainSearchCreateFromAttributes(kcArArray, + kSecCertificateItemClass, + &attrList, + &srch); + if(ortn) { + cssmPerror("SecKeychainSearchCreateFromAttributes", ortn); + return ortn; + } + + ortn = SecKeychainSearchCopyNext(srch, (SecKeychainItemRef *)cert); + if(ortn) { + printf("***No certs founmd matching recipient %s. Aborting.\n"); + return ortn; + } + CFRelease(srch); + return noErr; +} + +static void evalSecTrust( + SecTrustRef secTrust) +{ + OSStatus ortn; + SecTrustResultType secTrustResult; + + ortn = SecTrustEvaluate(secTrust, &secTrustResult); + if(ortn) { + /* should never happen */ + cssmPerror("SecTrustEvaluate", ortn); + return; + } + switch(secTrustResult) { + case kSecTrustResultUnspecified: + /* cert chain valid, no special UserTrust assignments */ + case kSecTrustResultProceed: + /* cert chain valid AND user explicitly trusts this */ + fprintf(stderr, "Successful\n"); + return; + case kSecTrustResultDeny: + case kSecTrustResultConfirm: + /* + * Cert chain may well have verified OK, but user has flagged + * one of these certs as untrustable. + */ + printf("Not trusted per user-specified Trust level\n"); + return; + default: + { + /* get low-level TP error */ + OSStatus tpStatus; + ortn = SecTrustGetCssmResultCode(secTrust, &tpStatus); + if(ortn) { + cssmPerror("SecTrustGetCssmResultCode", ortn); + return; + } + switch(tpStatus) { + case CSSMERR_TP_INVALID_ANCHOR_CERT: + fprintf(stderr, "Untrusted root\n"); + return; + case CSSMERR_TP_NOT_TRUSTED: + /* no root, not even in implicit SSL roots */ + fprintf(stderr, "No root cert found\n"); + return; + case CSSMERR_TP_CERT_EXPIRED: + fprintf(stderr, "Expired cert\n"); + return; + case CSSMERR_TP_CERT_NOT_VALID_YET: + fprintf(stderr, "Cert not valid yet\n"); + break; + default: + printf("Other cert failure: "); + cssmPerror("", tpStatus); + return; + } + } + } /* SecTrustEvaluate error */ + +} +static OSStatus parseSignedData( + SecCmsSignedDataRef signedData, + bool parseSignerCert) +{ + Boolean b; + b = SecCmsSignedDataHasDigests(signedData); + printf(" has digests : %s\n", b ? "true" : "false"); + + SecTrustRef secTrust = NULL; + OSStatus ortn; + SecPolicyRef policy = NULL; + SecPolicySearchRef policySearch = NULL; + + ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3, + &CSSMOID_APPLE_X509_BASIC, + NULL, + &policySearch); + if(ortn) { + cssmPerror("SecPolicySearchCreate", ortn); + return ortn; + } + ortn = SecPolicySearchCopyNext(policySearch, &policy); + if(ortn) { + cssmPerror("SecPolicySearchCopyNext", ortn); + return ortn; + } + + int numSigners = SecCmsSignedDataSignerInfoCount(signedData); + printf(" num signers : %d\n", numSigners); + for(int dex=0; dex>\n"); + } + SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, dex); + CFStringRef emailAddrs = SecCmsSignerInfoGetSignerCommonName(signerInfo); + char emailStr[1000]; + fprintf(stderr, " signer : "); + if(emailAddrs == NULL) { + printf("<>\n"); + } + else { + if(!CFStringGetCString(emailAddrs, emailStr, 1000, kCFStringEncodingASCII)) { + printf("*** Error converting email address to C string\n"); + } + else { + printf("%s\n", emailStr); + } + } + if(parseSignerCert) { + SecCertificateRef signer; + signer = SecCmsSignerInfoGetSigningCertificate(signerInfo, NULL); + if(signer) { + CSSM_DATA certData; + ortn = SecCertificateGetData(signer, &certData); + if(ortn) { + fprintf(stderr, "***Error getting signing cert data***\n"); + cssmPerror("SecCertificateGetData", ortn); + } + else { + printf("========== Signer Cert==========\n\n"); + printCert(certData.Data, certData.Length, CSSM_FALSE); + printf("========== End Signer Cert==========\n\n"); + } + } + else { + fprintf(stderr, "***Error getting signing cert ***\n"); + } + } + } + return ortn; +} + +static OSStatus doParse( + const unsigned char *data, + unsigned dataLen, + bool parseSignerCert, + unsigned char **outData, // mallocd and RETURNED + unsigned *outDataLen) // RETURNED +{ + if((data == NULL) || (dataLen == 0)) { + printf("***Parse requires input file. Aborting.\n"); + return paramErr; + } + + SecArenaPoolRef arena = NULL; + SecArenaPoolCreate(1024, &arena); + SecCmsMessageRef cmsMsg = NULL; + SecCmsDecoderRef decoder; + OSStatus ortn; + + ortn = SecCmsDecoderCreate(arena, NULL, NULL, NULL, NULL, NULL, NULL, &decoder); + if(ortn) { + cssmPerror("SecCmsDecoderCreate", ortn); + return ortn; + } + ortn = SecCmsDecoderUpdate(decoder, data, dataLen); + if(ortn) { + cssmPerror("SecCmsDecoderUpdate", ortn); + return ortn; + } + ortn = SecCmsDecoderFinish(decoder, &cmsMsg); + if(ortn) { + cssmPerror("SecCmsDecoderFinish", ortn); + return ortn; + } + + Boolean b = SecCmsMessageIsSigned(cmsMsg); + printf("=== CMS message info ===\n"); + printf(" Signed : %s\n", b ? "true" : "false"); + b = SecCmsMessageIsEncrypted(cmsMsg); + printf(" Encrypted : %s\n", b ? "true" : "false"); + b = SecCmsMessageContainsCertsOrCrls(cmsMsg); + printf(" certs/crls : %s\n", b ? "present" : "not present"); + int numContentInfos = SecCmsMessageContentLevelCount(cmsMsg); + printf(" Num ContentInfos : %d\n", numContentInfos); + + OidParser oidParser; + for(int dex=0; dexLength == 0) { + printf("***EMPTY***\n"); + } + else { + char str[OID_PARSER_STRING_SIZE]; + oidParser.oidParse(typeOid->Data, typeOid->Length, str); + printf("%s\n", str); + } + SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci); + switch(tag) { + case SEC_OID_PKCS7_SIGNED_DATA: + { + SecCmsSignedDataRef sd = + (SecCmsSignedDataRef) SecCmsContentInfoGetContent(ci); + parseSignedData(sd, parseSignerCert); + break; + } + case SEC_OID_PKCS7_DATA: + case SEC_OID_PKCS7_ENVELOPED_DATA: + case SEC_OID_PKCS7_ENCRYPTED_DATA: + break; + default: + printf(" other content type TBD\n"); + } + } + if(outData) { + CSSM_DATA_PTR odata = SecCmsMessageGetContent(cmsMsg); + if(odata == NULL) { + printf("***No inner content available\n"); + } + else { + *outData = (unsigned char *)malloc(odata->Length); + memmove(*outData, odata->Data, odata->Length); + *outDataLen = odata->Length; + } + } + if(arena) { + SecArenaPoolFree(arena, false); + } + /* free decoder? cmsMsg? */ + return noErr; +} + +/* + * Common encode routine. + */ +#if 0 +/* the simple way, when 3655861 is fixed */ +static OSStatus encodeCms( + SecCmsMessageRef cmsMsg, + const unsigned char *inData, // add in this + unsigned inDataLen, + unsigned char **outData, // mallocd and RETURNED + unsigned *outDataLen) // RETURNED +{ + SecArenaPoolRef arena = NULL; + SecArenaPoolCreate(1024, &arena); + CSSM_DATA cdataIn = {inDataLen, (uint8 *)inData}; + CSSM_DATA cdataOut = {0, NULL}; + + OSStatus ortn = SecCmsMessageEncode(cmsMsg, &cdataIn, arena, &cdataOut); + if((ortn == noErr) && (cdataOut.Length != 0)) { + *outData = (unsigned char *)malloc(cdataOut.Length); + memmove(*outData, cdataOut.Data, cdataOut.Length); + *outDataLen = cdataOut.Length; + } + else { + *outData = NULL; + *outDataLen = 0; + } + SecArenaPoolFree(arena, false); + return ortn; +} + +#else + +static OSStatus encodeCms( + SecCmsMessageRef cmsMsg, + const unsigned char *inData, // add in this + unsigned inDataLen, + unsigned char **outData, // mallocd and RETURNED + unsigned *outDataLen) // RETURNED +{ + SecArenaPoolRef arena = NULL; + SecArenaPoolCreate(1024, &arena); + SecCmsEncoderRef cmsEnc = NULL; + CSSM_DATA output = { 0, NULL }; + OSStatus ortn; + + ortn = SecCmsEncoderCreate(cmsMsg, + NULL, NULL, // no callback + &output, arena, // data goes here + NULL, NULL, // no password callback (right?) + NULL, NULL, // decrypt key callback + NULL, NULL, // detached digests + &cmsEnc); + if(ortn) { + cssmPerror("SecKeychainItemCopyKeychain", ortn); + goto errOut; + } + ortn = SecCmsEncoderUpdate(cmsEnc, (char *)inData, inDataLen); + if(ortn) { + cssmPerror("SecCmsEncoderUpdate", ortn); + goto errOut; + } + ortn = SecCmsEncoderFinish(cmsEnc); + if(ortn) { + cssmPerror("SecCMsEncoderFinish", ortn); + goto errOut; + } + + /* Did we get any data? */ + if(output.Length) { + *outData = (unsigned char *)malloc(output.Length); + memmove(*outData, output.Data, output.Length); + *outDataLen = output.Length; + } + else { + *outData = NULL; + *outDataLen = 0; + } +errOut: + if(arena) { + SecArenaPoolFree(arena, false); + } + return ortn; +} + +#endif + +static OSStatus doSign( + SecIdentityRef signerId, + const unsigned char *inData, + unsigned inDataLen, + unsigned char **outData, // mallocd and RETURNED + unsigned *outDataLen) // RETURNED +{ + if((inData == NULL) || (inDataLen == 0) || (outData == NULL)) { + printf("***Sign requires input file. Aborting.\n"); + return paramErr; + } + if(signerId == NULL) { + printf("***Sign requires a signing identity. Aborting.\n"); + return paramErr; + } + + SecCmsMessageRef cmsMsg = NULL; + SecCmsContentInfoRef contentInfo = NULL; + SecCmsSignedDataRef signedData = NULL; + SecCertificateRef ourCert = NULL; + SecCmsSignerInfoRef signerInfo; + OSStatus ortn; + SecKeychainRef ourKc = NULL; + + ortn = SecIdentityCopyCertificate(signerId, &ourCert); + if(ortn) { + cssmPerror("SecIdentityCopyCertificate", ortn); + return ortn; + } + ortn = SecKeychainItemCopyKeychain((SecKeychainItemRef)ourCert, &ourKc); + if(ortn) { + cssmPerror("SecKeychainItemCopyKeychain", ortn); + goto errOut; + } + + // build chain of objects: message->signedData->data + cmsMsg = SecCmsMessageCreate(NULL); + if(cmsMsg == NULL) { + printf("***Error creating SecCmsMessageRef\n"); + ortn = -1; + goto errOut; + } + signedData = SecCmsSignedDataCreate(cmsMsg); + if(signedData == NULL) { + printf("***Error creating SecCmsSignedDataRef\n"); + ortn = -1; + goto errOut; + } + contentInfo = SecCmsMessageGetContentInfo(cmsMsg); + ortn = SecCmsContentInfoSetContentSignedData(cmsMsg, contentInfo, signedData); + if(ortn) { + cssmPerror("SecCmsContentInfoSetContentSignedData", ortn); + goto errOut; + } + contentInfo = SecCmsSignedDataGetContentInfo(signedData); + ortn = SecCmsContentInfoSetContentData(cmsMsg, contentInfo, NULL /* data */, false); + if(ortn) { + cssmPerror("SecCmsContentInfoSetContentData", ortn); + goto errOut; + } + + /* + * create & attach signer information + */ + signerInfo = SecCmsSignerInfoCreate(cmsMsg, signerId, SEC_OID_SHA1); + if (signerInfo == NULL) { + printf("***Error on SecCmsSignerInfoCreate\n"); + ortn = -1; + goto errOut; + } + /* we want the cert chain included for this one */ + /* FIXME - what's the significance of the usage? */ + ortn = SecCmsSignerInfoIncludeCerts(signerInfo, SecCmsCMCertChain, certUsageEmailSigner); + if(ortn) { + cssmPerror("SecCmsSignerInfoIncludeCerts", ortn); + goto errOut; + } + + /* other options go here - signing time, etc. */ + + ortn = SecCmsSignerInfoAddSMIMEEncKeyPrefs(signerInfo, ourCert, ourKc); + if(ortn) { + cssmPerror("SecCmsSignerInfoAddSMIMEEncKeyPrefs", ortn); + goto errOut; + } + ortn = SecCmsSignedDataAddCertificate(signedData, ourCert); + if(ortn) { + cssmPerror("SecCmsSignedDataAddCertificate", ortn); + goto errOut; + } + + ortn = SecCmsSignedDataAddSignerInfo(signedData, signerInfo); + if(ortn) { + cssmPerror("SecCmsSignedDataAddSignerInfo", ortn); + goto errOut; + } + + /* go */ + ortn = encodeCms(cmsMsg, inData, inDataLen, outData, outDataLen); +errOut: + /* free resources */ + if(cmsMsg) { + SecCmsMessageDestroy(cmsMsg); + } + if(ourCert) { + CFRelease(ourCert); + } + if(ourKc) { + CFRelease(ourKc); + } + return ortn; +} + +static OSStatus doEncrypt( + SecCertificateRef recipCert, // eventually more than one + const unsigned char *inData, + unsigned inDataLen, + unsigned char **outData, // mallocd and RETURNED + unsigned *outDataLen) // RETURNED +{ + if((inData == NULL) || (inDataLen == 0) || (outData == NULL)) { + printf("***Sign requires input file. Aborting.\n"); + return paramErr; + } + if(recipCert == NULL) { + printf("***Encrypt requires a recipient certificate. Aborting.\n"); + return paramErr; + } + + SecCmsMessageRef cmsMsg = NULL; + SecCmsContentInfoRef contentInfo = NULL; + SecCmsEnvelopedDataRef envelopedData = NULL; + SecCmsRecipientInfoRef recipientInfo = NULL; + OSStatus ortn; + SecCertificateRef allCerts[2] = { recipCert, NULL}; + + SECOidTag algorithmTag; + int keySize; + + ortn = SecSMIMEFindBulkAlgForRecipients(allCerts, &algorithmTag, &keySize); + if(ortn) { + cssmPerror("SecSMIMEFindBulkAlgForRecipients", ortn); + return ortn; + } + + // build chain of objects: message->envelopedData->data + cmsMsg = SecCmsMessageCreate(NULL); + if(cmsMsg == NULL) { + printf("***Error creating SecCmsMessageRef\n"); + ortn = -1; + goto errOut; + } + envelopedData = SecCmsEnvelopedDataCreate(cmsMsg, algorithmTag, keySize); + if(envelopedData == NULL) { + printf("***Error creating SecCmsEnvelopedDataRef\n"); + ortn = -1; + goto errOut; + } + contentInfo = SecCmsMessageGetContentInfo(cmsMsg); + ortn = SecCmsContentInfoSetContentEnvelopedData(cmsMsg, contentInfo, envelopedData); + if(ortn) { + cssmPerror("SecCmsContentInfoSetContentEnvelopedData", ortn); + goto errOut; + } + contentInfo = SecCmsEnvelopedDataGetContentInfo(envelopedData); + ortn = SecCmsContentInfoSetContentData(cmsMsg, contentInfo, NULL /* data */, false); + if(ortn) { + cssmPerror("SecCmsContentInfoSetContentData", ortn); + goto errOut; + } + + /* + * create & attach recipient information + */ + recipientInfo = SecCmsRecipientInfoCreate(cmsMsg, recipCert); + ortn = SecCmsEnvelopedDataAddRecipient(envelopedData, recipientInfo); + if(ortn) { + cssmPerror("SecCmsEnvelopedDataAddRecipient", ortn); + goto errOut; + } + + + /* go */ + ortn = encodeCms(cmsMsg, inData, inDataLen, outData, outDataLen); +errOut: + /* free resources */ + if(cmsMsg) { + SecCmsMessageDestroy(cmsMsg); + } + return ortn; +} + +int main(int argc, char **argv) +{ + if(argc < 2) { + usage(argv); + } + + CT_Op op; + bool needId = false; + if(!strcmp(argv[1], "sign")) { + op = CTO_Sign; + needId = true; + } + else if(!strcmp(argv[1], "envel")) { + op = CTO_Envelop; + } + else if(!strcmp(argv[1], "parse")) { + op = CTO_Parse; + } + else { + printf("***Unrecognized cmd.\n"); + usage(argv); + } + + extern int optind; + extern char *optarg; + int arg; + int ourRtn = 0; + + /* optional args */ + const char *keychainName = NULL; + char *inFileName = NULL; + char *outFileName = NULL; + bool useIdPicker = false; + char *recipient = NULL; + bool quiet = false; + bool parseSignerCert = false; + + optind = 2; + while ((arg = getopt(argc, argv, "i:o:k:pr:qc")) != -1) { + switch (arg) { + case 'i': + inFileName = optarg; + break; + case 'o': + outFileName = optarg; + break; + case 'k': + keychainName = optarg; + break; + case 'p': + useIdPicker = true; + break; + case 'r': + recipient = optarg; + break; + case 'c': + parseSignerCert = true; + break; + case 'q': + quiet = true; + break; + default: + case '?': + usage(argv); + } + } + if(optind != argc) { + /* getopt does not return '?' */ + usage(argv); + } + + SecIdentityRef idRef = NULL; + SecKeychainRef kcRef = NULL; + SecCertificateRef recipientCert; + unsigned char *inData = NULL; + unsigned inDataLen = 0; + unsigned char *outData = NULL; + unsigned outDataLen = 0; + OSStatus ortn; + + if(inFileName) { + if(readFile(inFileName, &inData, &inDataLen)) { + printf("***Error reading infile %s. Aborting.\n", inFileName); + exit(1); + } + } + if(keychainName) { + ortn = SecKeychainOpen(keychainName, &kcRef); + if(ortn) { + cssmPerror("SecKeychainOpen", ortn); + exit(1); + } + } + if(useIdPicker) { + ortn = sslSimpleIdentPicker(kcRef, &idRef); + if(ortn) { + printf("Error obtaining idenity via picker. Aborting.\n"); + exit(1); + } + } + else if(needId) { + /* use first identity in specified keychain */ + CFArrayRef array = sslKcRefToCertArray(kcRef, CSSM_FALSE, CSSM_FALSE, NULL); + if(array == NULL) { + printf("***Error finding a signing cert. Aborting.\n"); + exit(1); + } + idRef = (SecIdentityRef)CFArrayGetValueAtIndex(array, 0); + if(idRef == NULL) { + printf("***No identities found. Aborting.\n"); + exit(1); + } + CFRetain(idRef); + CFRelease(array); + } + if(recipient) { + ortn = findCert(recipient, kcRef, &recipientCert); + if(ortn) { + exit(1); + } + } + + switch(op) { + case CTO_Sign: + ortn = doSign(idRef, inData, inDataLen, &outData, &outDataLen); + break; + case CTO_Envelop: + ortn = doEncrypt(recipientCert, inData, inDataLen, &outData, &outDataLen); + break; + case CTO_Parse: + ortn = doParse(inData, inDataLen, parseSignerCert, &outData, &outDataLen); + break; + } + if(ortn) { + goto errOut; + } + if(outData && outFileName) { + if(writeFile(outFileName, outData, outDataLen)) { + printf("***Error writing to %s.\n", outFileName); + } + else { + printf("...wrote %lu bytes to %s.\n", outDataLen, outFileName); + } + } + else if(outData) { + printf("...generated %lu bytes but no place to write it.\n", outDataLen); + } + else if(outFileName) { + printf("...nothing to write to file %s.\n", outFileName); + } +errOut: + return ourRtn; +} \ No newline at end of file diff --git a/SecurityTests/clxutils/cmstool/testSubjects/signed1.cms b/SecurityTests/clxutils/cmstool/testSubjects/signed1.cms new file mode 100644 index 0000000000000000000000000000000000000000..b48b04d2d450f8335c5959a67e8f13dc9f5e4ea8 GIT binary patch literal 23230 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 0 ) + switch ( "$argv[1]" ) + case q: + set QUIET = -q + shift + breaksw + default: + echo Usage: vfyCms \[q\(uiet\)\] + exit(1) + endsw +end +# +# signed1.cms is ptext1 wrapped in a signedData +# +set TMP_PTEXT=/tmp/ptext_tmp +$LOCAL_BUILD_DIR/cmstool parse -i signed1.cms -o $TMP_PTEXT -v sign $QUIET || exit(1) +cmp ptext1.txt $TMP_PTEXT +if ($status != 0) then + echo ### Data miscompare: plaintext signed1.cms recovered $TMP_PTEXT + exit(1) +endif diff --git a/SecurityTests/clxutils/crlTool/Makefile b/SecurityTests/clxutils/crlTool/Makefile new file mode 100644 index 00000000..fe3d898c --- /dev/null +++ b/SecurityTests/clxutils/crlTool/Makefile @@ -0,0 +1,54 @@ +# name of executable to build +EXECUTABLE=crlTool +# C++ source (with .cpp extension) +CPSOURCE= crlTool.cpp crlNetwork.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= -framework LDAP + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/clxutils/crlTool/crlNetwork.cpp b/SecurityTests/clxutils/crlTool/crlNetwork.cpp new file mode 100644 index 00000000..240824cd --- /dev/null +++ b/SecurityTests/clxutils/crlTool/crlNetwork.cpp @@ -0,0 +1,253 @@ +/* + * crlNetwork.cpp - Network support for crlTool + */ + +#include "crlNetwork.h" +#include +#include +#include +#include +#include +#include + +#define ocspdErrorLog(args...) printf(args) + +#pragma mark ----- LDAP fetch ----- + +/* + * LDAP attribute names, used if not present in URI. + */ +#define LDAP_ATTR_CERT "cacertificate;binary" +#define LDAP_ATTR_CRL "certificaterevocationlist;binary" + +/* + * Default LDAP options. + */ +#define LDAP_REFERRAL_DEFAULT LDAP_OPT_ON + +static CSSM_RETURN ldapRtnToCssm( + int rtn) +{ + switch(rtn) { + case LDAP_SERVER_DOWN: + case LDAP_TIMEOUT: + case LDAP_CONNECT_ERROR: + return CSSMERR_APPLETP_CRL_SERVER_DOWN; + case LDAP_PARAM_ERROR: + case LDAP_FILTER_ERROR: + return CSSMERR_APPLETP_CRL_BAD_URI; + default: + return CSSMERR_APPLETP_CRL_NOT_FOUND; + } +} + +static CSSM_RETURN ldapFetch( + const CSSM_DATA &url, + LF_Type lfType, + CSSM_DATA &fetched) // mallocd and RETURNED +{ + BerValue **value = NULL; + LDAPURLDesc *urlDesc = NULL; + int rtn; + LDAPMessage *msg = NULL; + LDAP *ldap = NULL; + LDAPMessage *entry = NULL; + bool mallocdString = false; + char *urlStr; + int numEntries; + CSSM_RETURN ourRtn = CSSM_OK; + /* attr input to ldap_search_s() */ + char *attrArray[2]; + char **attrArrayP = NULL; + + /* don't assume URL string is NULL terminated */ + if(url.Data[url.Length - 1] == '\0') { + urlStr = (char *)url.Data; + } + else { + urlStr = (char *)malloc(url.Length + 1); + memmove(urlStr, url.Data, url.Length); + urlStr[url.Length] = '\0'; + mallocdString = true; + } + + /* break up the URL into something usable */ + rtn = ldap_url_parse(urlStr, &urlDesc); + if(rtn) { + ocspdErrorLog("ldap_url_parse returned %d", rtn); + return CSSMERR_APPLETP_CRL_BAD_URI; + } + + /* + * Determine what attr we're looking for. + */ + if((urlDesc->lud_attrs != NULL) && // attrs present in URL + (urlDesc->lud_attrs[0] != NULL) && // at least one attr present + (urlDesc->lud_attrs[1] == NULL)) { + /* + * Exactly one attr present in the caller-specified URL; + * assume that this is exactly what we want. + */ + attrArrayP = &urlDesc->lud_attrs[0]; + } + else { + /* use caller-specified attr */ + switch(lfType) { + case LT_Crl: + attrArray[0] = (char *)LDAP_ATTR_CRL; + break; + case LT_Cert: + attrArray[0] = (char *)LDAP_ATTR_CERT; + break; + default: + printf("***ldapFetch screwup: bogus lfType (%d)\n", + (int)lfType); + return CSSMERR_CSSM_INTERNAL_ERROR; + } + attrArray[1] = NULL; + attrArrayP = &attrArray[0]; + } + + /* establish connection */ + rtn = ldap_initialize(&ldap, urlStr); + if(rtn) { + ocspdErrorLog("ldap_initialize returned %d\n", rtn); + return ldapRtnToCssm(rtn); + } + /* subsequent errors to cleanup: */ + rtn = ldap_simple_bind_s(ldap, NULL, NULL); + if(rtn) { + ocspdErrorLog("ldap_simple_bind_s returned %d\n", rtn); + ourRtn = ldapRtnToCssm(rtn); + goto cleanup; + } + + rtn = ldap_set_option(ldap, LDAP_OPT_REFERRALS, LDAP_REFERRAL_DEFAULT); + if(rtn) { + ocspdErrorLog("ldap_set_option(referrals) returned %d\n", rtn); + ourRtn = ldapRtnToCssm(rtn); + goto cleanup; + } + + rtn = ldap_search_s( + ldap, + urlDesc->lud_dn, + LDAP_SCOPE_SUBTREE, + urlDesc->lud_filter, + urlDesc->lud_attrs, + 0, // attrsonly + &msg); + if(rtn) { + ocspdErrorLog("ldap_search_s returned %d\n", rtn); + ourRtn = ldapRtnToCssm(rtn); + goto cleanup; + } + + /* + * We require exactly one entry (for now). + */ + numEntries = ldap_count_entries(ldap, msg); + if(numEntries != 1) { + ocspdErrorLog("tpCrlViaLdap: numEntries %d\n", numEntries); + ourRtn = CSSMERR_APPLETP_CRL_NOT_FOUND; + goto cleanup; + } + + entry = ldap_first_entry(ldap, msg); + value = ldap_get_values_len(ldap, msg, attrArrayP[0]); + if(value == NULL) { + ocspdErrorLog("Error on ldap_get_values_len\n"); + ourRtn = CSSMERR_APPLETP_CRL_NOT_FOUND; + goto cleanup; + } + + fetched.Length = value[0]->bv_len; + fetched.Data = (uint8 *)malloc(fetched.Length); + memmove(fetched.Data, value[0]->bv_val, fetched.Length); + + ldap_value_free_len(value); + ourRtn = CSSM_OK; +cleanup: + if(msg) { + ldap_msgfree(msg); + } + if(mallocdString) { + free(urlStr); + } + ldap_free_urldesc(urlDesc); + rtn = ldap_unbind(ldap); + if(rtn) { + ocspdErrorLog("Error %d on ldap_unbind\n", rtn); + /* oh well */ + } + return ourRtn; +} + +#pragma mark ----- HTTP fetch via GET ----- + +/* fetch via HTTP */ +static CSSM_RETURN httpFetch( + const CSSM_DATA &url, + CSSM_DATA &fetched) // mallocd in alloc space and RETURNED +{ + /* trim off possible NULL terminator */ + CSSM_DATA theUrl = url; + if(theUrl.Data[theUrl.Length - 1] == '\0') { + theUrl.Length--; + } + CFURLRef cfUrl = CFURLCreateWithBytes(NULL, + theUrl.Data, theUrl.Length, + kCFStringEncodingUTF8, // right? + //kCFStringEncodingASCII, // right? + NULL); // this is absolute path + if(cfUrl == NULL) { + ocspdErrorLog("CFURLCreateWithBytes returned NULL\n"); + return CSSMERR_APPLETP_CRL_BAD_URI; + } + CFDataRef urlData = NULL; + SInt32 errorCode; + Boolean brtn = CFURLCreateDataAndPropertiesFromResource(NULL, + cfUrl, + &urlData, + NULL, // no properties + NULL, + &errorCode); + CFRelease(cfUrl); + if(!brtn) { + ocspdErrorLog("CFURLCreateDataAndPropertiesFromResource err: %d\n", + (int)errorCode); + if(urlData) { + return CSSMERR_APPLETP_NETWORK_FAILURE; + } + } + if(urlData == NULL) { + ocspdErrorLog("CFURLCreateDataAndPropertiesFromResource: no data\n"); + return CSSMERR_APPLETP_NETWORK_FAILURE; + } + CFIndex len = CFDataGetLength(urlData); + fetched.Data = (uint8 *)malloc(len); + fetched.Length = len; + memmove(fetched.Data, CFDataGetBytePtr(urlData), len); + CFRelease(urlData); + return CSSM_OK; +} + +/* Fetch cert or CRL from net, we figure out the schema */ +CSSM_RETURN crlNetFetch( + const CSSM_DATA *url, + LF_Type lfType, + CSSM_DATA *fetched) // mallocd in alloc space and RETURNED +{ + if(url->Length < 5) { + return CSSMERR_APPLETP_CRL_BAD_URI; + } + if(!strncmp((char *)url->Data, "ldap:", 5)) { + return ldapFetch(*url, lfType, *fetched); + } + if(!strncmp((char *)url->Data, "http:", 5) || + !strncmp((char *)url->Data, "https:", 6)) { + return httpFetch(*url, *fetched); + } + return CSSMERR_APPLETP_CRL_BAD_URI; +} + diff --git a/SecurityTests/clxutils/crlTool/crlNetwork.h b/SecurityTests/clxutils/crlTool/crlNetwork.h new file mode 100644 index 00000000..592ec5c0 --- /dev/null +++ b/SecurityTests/clxutils/crlTool/crlNetwork.h @@ -0,0 +1,30 @@ +/* + * crlNetwork.h - Network support for crlTool + */ + +#ifndef _CRL_NETWORK_H_ +#define _CRL_NETWORK_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Fetch cert or CRL from net, we figure out the schema */ + +typedef enum { + LT_Crl = 1, + LT_Cert +} LF_Type; + +CSSM_RETURN crlNetFetch( + const CSSM_DATA *url, + LF_Type lfType, + CSSM_DATA *fetched); // mallocd and RETURNED + +#ifdef __cplusplus +} +#endif + +#endif /* _CRL_NETWORK_H_ */ diff --git a/SecurityTests/clxutils/crlTool/crlTool.cpp b/SecurityTests/clxutils/crlTool/crlTool.cpp new file mode 100644 index 00000000..54050bb3 --- /dev/null +++ b/SecurityTests/clxutils/crlTool/crlTool.cpp @@ -0,0 +1,232 @@ +/* + * crlTool.cpp + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "crlNetwork.h" +#include +#define LOOPS_DEF 100 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" -c certFile -- obtain CRL via net from this cert\n"); + printf(" -C crlFile -- CRL from this file\n"); + printf(" -p -- parse the CRL\n"); + printf(" -o outFile -- write the fetched CRL to this file\n"); + printf(" -v -- verbose CRL dump\n"); + /* etc. */ + exit(1); +} + +static int fetchCrlViaGeneralNames( + const CE_GeneralNames *names, + unsigned char **crl, // mallocd and RETURNED + size_t *crlLen) // RETURNED +{ + CSSM_DATA crlData = {0, NULL}; + CSSM_RETURN crtn; + + for(unsigned nameDex=0; nameDexnumNames; nameDex++) { + CE_GeneralName *name = &names->generalName[nameDex]; + switch(name->nameType) { + case GNT_URI: + if(name->name.Length < 5) { + continue; + } + if(strncmp((char *)name->name.Data, "ldap:", 5) && + strncmp((char *)name->name.Data, "http:", 5) && + strncmp((char *)name->name.Data, "https:", 6)) { + /* eventually handle other schemes here */ + continue; + } + + /* OK, we can do this */ + crtn = crlNetFetch(&name->name, LT_Crl, &crlData); + if(crtn) { + printf("...net fetch error\n"); + return 1; + } + *crl = crlData.Data; + *crlLen = crlData.Length; + return 0; + + default: + printf("fetchCrlViaGeneralNames: unknown" + "nameType (%u)", (unsigned)name->nameType); + break; + } + } + printf("...GNT_URI name not found in GeneralNames\n"); + return 1; +} + +static int fetchCrl( + CertParser &cert, + unsigned char **crl, // mallocd and RETURNED + size_t *crlLen) // RETURNED +{ + CE_CRLDistPointsSyntax *dps = (CE_CRLDistPointsSyntax *) + cert.extensionForOid(CSSMOID_CrlDistributionPoints); + + *crl = NULL; + *crlLen = 0; + if(dps == NULL) { + /* not an error, just indicate NULL return */ + printf("***No CrlDistributionPoints in this cert.\n"); + return 0; + } + for(unsigned dex=0; dexnumDistPoints; dex++) { + + CE_CRLDistributionPoint *dp = &dps->distPoints[dex]; + if(dp->distPointName == NULL) { + continue; + } + switch(dp->distPointName->nameType) { + case CE_CDNT_NameRelativeToCrlIssuer: + printf("...CE_CDNT_NameRelativeToCrlIssuer not implemented\n"); + break; + + case CE_CDNT_FullName: + { + CE_GeneralNames *names = dp->distPointName->dpn.fullName; + int rtn = fetchCrlViaGeneralNames(names, crl, crlLen); + if(rtn == 0) { + return 0; + } + /* else try again if there's another name */ + break; + } /* CE_CDNT_FullName */ + + default: + /* not yet */ + printf("unknown distPointName->nameType (%u)\n", + (unsigned)dp->distPointName->nameType); + break; + } /* switch distPointName->nameType */ + } /* for each distPoints */ + printf("...CrlDistributionPoints found, but nothing we can use.\n"); + return 0; +} + +int main(int argc, char **argv) +{ + char *certFile = NULL; + char *crlFile = NULL; + unsigned char *certData; + unsigned certDataLen; + bool doParse = false; + char *outFile = NULL; + CSSM_BOOL verbose = CSSM_FALSE; + unsigned char *crl = NULL; + size_t crlLen = 0; + int rtn = -1; + + if(argc < 2) { + usage(argv); + } + + extern char *optarg; + int arg; + while ((arg = getopt(argc, argv, "c:C:po:vh")) != -1) { + switch (arg) { + case 'c': + certFile = optarg; + break; + case 'C': + crlFile = optarg; + break; + case 'p': + doParse = true; + break; + case 'o': + outFile = optarg; + break; + case 'v': + verbose = CSSM_TRUE; + break; + case 'h': + usage(argv); + } + } + if(optind != argc) { + usage(argv); + } + if((certFile != NULL) && (crlFile != NULL)) { + printf("***crlFile and certFile are mutually exclusive.\n"); + usage(argv); + } + if((certFile == NULL) && (crlFile == NULL)) { + printf("***Must specify either certFile or crlFile\n"); + usage(argv); + } + + CSSM_RETURN crtn; + CSSM_CL_HANDLE clHand = clStartup(); + CertParser parser(clHand); + + if(crlFile) { + unsigned len; + if(readFile(crlFile, &crl, &len)) { + printf("***Error reading %s. Aborting.\n", crlFile); + exit(1); + } + crlLen = len; + } + if(certFile) { + if(readFile(certFile, &certData, &certDataLen)) { + printf("***Error reading %s. Aborting.\n", certFile); + exit(1); + } + CSSM_DATA cdata = {certDataLen, certData}; + crtn = parser.initWithData(cdata); + if(crtn) { + printf("Error parsing cert %s. Aborting.\n", certFile); + exit(1); + } + rtn = fetchCrl(parser, &crl, &crlLen); + if(rtn) { + printf("***aborting.\n"); + exit(1); + } + } + + if(doParse) { + if(crl == NULL) { + printf("...parse specified but no CRL found.\n"); + } + else { + if(certFile != NULL) { + printf("============== CRL for cert %s ==============\n", certFile); + } + printCrl(crl, crlLen, verbose); + if(certFile != NULL) { + printf("============== end of CRL ==============\n"); + } + } + } + if(outFile) { + if(crl == NULL) { + printf("...outFile specified but no CRL found.\n"); + } + else { + if(writeFile(outFile, crl, crlLen)) { + printf("***Error writing CRL to %s.\n", outFile); + rtn = 1; + } + else { + printf("...wrote %u bytes to %s\n", (unsigned)crlLen, outFile); + } + } + } + return rtn; +} diff --git a/SecurityTests/clxutils/dotMacArchive/Makefile b/SecurityTests/clxutils/dotMacArchive/Makefile new file mode 100644 index 00000000..e8d9946a --- /dev/null +++ b/SecurityTests/clxutils/dotMacArchive/Makefile @@ -0,0 +1,50 @@ +EXECUTABLE=dotMacArchive +# C++ source (with .cpp extension) +CPSOURCE= dotMacArchive.cpp dotMacTpAttach.cpp identSearch.cpp +# C source (.c extension) +CSOURCE= +OFILES = $(CSOURCE:%.c=%.o) $(CPSOURCE:%.cpp=%.o) + +LOCAL_BUILD= $(shell echo $(LOCAL_BUILD_DIR)) + +CC=c++ + +FRAMEWORKS= -framework Security -framework CoreFoundation +#FRAME_SEARCH= -F$(LOCAL_BUILD) +FRAME_SEARCH= -F$(LOCAL_BUILD) +FINCLUDES= +PINCLUDES= +CINCLUDES= $(FINCLUDES) $(PINCLUDES) +WFLAGS= -Wno-four-char-constants -Wno-deprecated-declarations +DEBUG_CFLAGS?= +CMDLINE_LDFLAGS?= +CFLAGS= -g $(CINCLUDES) $(WFLAGS) $(FRAME_SEARCH) $(DEBUG_CFLAGS) + +# +# This assumes final load with cc, not ld +# +LIBS= -lstdc++ +LIBPATH= +LDFLAGS= $(LIBS) $(LIBPATH) $(FRAME_SEARCH) $(CMDLINE_LDFLAGS) -lsecurity_cdsa_utils + +first: $(EXECUTABLE) + +install: + +$(EXECUTABLE): $(OFILES) + $(CC) -o $(EXECUTABLE) $(FRAMEWORKS) $(OFILES) $(LDFLAGS) + +64bit: + make "DEBUG_CFLAGS=-arch ppc64" "CMDLINE_LDFLAGS=-arch ppc64" + +64bitFat: + make "DEBUG_CFLAGS=-arch ppc64" "CMDLINE_LDFLAGS=-arch ppc64" + +clean: + rm -f *.o $(EXECUTABLE) + +%.o: %.c + $(CC) $(CFLAGS) -c -o $*.o $< + +%.o: %.cpp + $(CC) $(CFLAGS) -c -o $*.o $< diff --git a/SecurityTests/clxutils/dotMacArchive/dotMacArchive.cpp b/SecurityTests/clxutils/dotMacArchive/dotMacArchive.cpp new file mode 100644 index 00000000..2b46fd4e --- /dev/null +++ b/SecurityTests/clxutils/dotMacArchive/dotMacArchive.cpp @@ -0,0 +1,546 @@ +/* + * dotMacArchive.cpp - test and demonstrate use of dotmacp_tp.bundle to + * manipulate Identity archives ont he .mac server. + */ +#include +#include +#include +//#include +#include +#include "identSearch.h" +#include "dotMacTpAttach.h" +#include +#include +#include +#include + +/* + * Defaults for the test setup du jour + */ +#define USER_DEFAULT "dmitch_new" +#define PWD_DEFAULT "password" +#define ARCHIVE_NAME_DEFAULT "dmitch_new" +#define HOST_DEFAULT "certmgmt.mac.com" + +/* + * Type of archive op + */ +typedef enum { + AO_List, + AO_Store, + AO_Fetch, + AO_Remove +} ArchiveOp; + +static void usage(char **argv) +{ + printf("usage: %s op [options]\n", argv[0]); + printf("Op:\n"); + printf(" l -- list archive contents\n"); + printf(" s -- store archive\n"); + printf(" f -- fetch archive\n"); + printf(" r -- remove archive(s)\n"); + printf("Options:\n"); + printf(" -u username -- Default is %s\n", USER_DEFAULT); + printf(" -Z password -- default is %s\n", PWD_DEFAULT); + printf(" -n archiveName -- default is %s\n", ARCHIVE_NAME_DEFAULT); + printf(" -k keychain -- Source/destination of archive\n"); + printf(" -H hostname -- Alternate .mac server host name (default %s)\n", + HOST_DEFAULT); + printf(" -o outFile -- write P12 blob to outFile\n"); + printf(" -z p12Phrase -- PKCS12 passphrase (default is GUI prompt)\n"); + printf(" -M -- Pause for MallocDebug\n"); + printf(" -l -- loop\n"); + exit(1); +} + +/* print a string in the form of a CSSM_DATA */ +static void printString( + const CSSM_DATA *str) +{ + for(unsigned dex=0; dexLength; dex++) { + printf("%c", str->Data[dex]); + } +} + + +/* + * Post a .mac archive request, with a small number of options. + */ +static CSSM_RETURN dotMacPostArchiveRequest( + ArchiveOp op, + CSSM_TP_HANDLE tpHand, + /* required fields for all ops */ + const CSSM_DATA *userName, // REQUIRED, C string + const CSSM_DATA *password, // REQUIRED, C string + + /* optional (per op, that is...) fields */ + const CSSM_DATA *hostName, // optional alternate host + const CSSM_DATA *archiveName, // required for store, fetch, remove + const CSSM_DATA *timeString, // required for store + const CSSM_DATA *pfxIn, // required for store + CSSM_DATA *pfxOut, // required and RETURNED for fetch + unsigned *numArchives, // required and RETURNED for list + DotMacArchive **archives) // required and RETURNED for list +{ + CSSM_RETURN crtn; + CSSM_TP_AUTHORITY_ID tpAuthority; + CSSM_TP_AUTHORITY_ID *tpAuthPtr = NULL; + CSSM_NET_ADDRESS tpNetAddrs; + CSSM_APPLE_DOTMAC_TP_ARCHIVE_REQUEST archReq; + CSSM_TP_REQUEST_SET reqSet; + CSSM_TP_CALLERAUTH_CONTEXT callerAuth; + sint32 estTime; + CSSM_DATA refId = {0, NULL}; + CSSM_FIELD policyField; + const CSSM_OID *opOid = NULL; + + if((tpHand == 0) || (userName == NULL) || (password == NULL)) { + printf("dotMacPostArchiveRequest: illegal common args\n"); + return paramErr; + } + switch(op) { + case AO_List: + if((numArchives == NULL) || (archives == NULL)) { + printf("dotMacPostArchiveRequest: illegal AO_List args\n"); + return paramErr; + } + opOid = &CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_LIST; + break; + case AO_Store: + if((archiveName == NULL) || (timeString == NULL) || (pfxIn == NULL)) { + printf("dotMacPostArchiveRequest: illegal AO_Store args\n"); + return paramErr; + } + opOid = &CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_STORE; + break; + case AO_Fetch: + if((archiveName == NULL) || (pfxOut == NULL)) { + printf("dotMacPostArchiveRequest: illegal AO_Fetch args\n"); + return paramErr; + } + opOid = &CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_FETCH; + break; + case AO_Remove: + if(archiveName == NULL) { + printf("dotMacPostArchiveRequest: illegal AO_Remove args\n"); + return paramErr; + } + opOid = &CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_REMOVE; + break; + } + + /* + * The main job here is bundling up the arguments into a + * CSSM_APPLE_DOTMAC_TP_ARCHIVE_REQUEST + */ + memset(&archReq, 0, sizeof(archReq)); + archReq.version = CSSM_DOT_MAC_TP_ARCHIVE_REQ_VERSION; + archReq.userName = *userName; + archReq.password = *password; + if(archiveName) { + archReq.archiveName = *archiveName; + } + if(timeString) { + archReq.timeString = *timeString; + } + if(pfxIn) { + archReq.pfx = *pfxIn; + } + + /* remaining arguments for TP call... */ + if((hostName != NULL) && (hostName->Data != NULL)) { + tpAuthority.AuthorityCert = NULL; + tpAuthority.AuthorityLocation = &tpNetAddrs; + tpNetAddrs.AddressType = CSSM_ADDR_NAME; + tpNetAddrs.Address = *hostName; + tpAuthPtr = &tpAuthority; + } + + reqSet.NumberOfRequests = 1; + reqSet.Requests = &archReq; + + policyField.FieldOid = *opOid; + policyField.FieldValue.Data = NULL; + policyField.FieldValue.Length = 0; + memset(&callerAuth, 0, sizeof(callerAuth)); + callerAuth.Policy.NumberOfPolicyIds = 1; + callerAuth.Policy.PolicyIds = &policyField; + + crtn = CSSM_TP_SubmitCredRequest (tpHand, + tpAuthPtr, + CSSM_TP_AUTHORITY_REQUEST_CERTISSUE, // CSSM_TP_AUTHORITY_REQUEST_TYPE + &reqSet, // const CSSM_TP_REQUEST_SET *RequestInput, + &callerAuth, + &estTime, // sint32 *EstimatedTime, + &refId); // CSSM_DATA_PTR ReferenceIdentifier + if(crtn) { + cssmPerror("CSSM_TP_SubmitCredRequest", crtn); + } + + /* success: post-process */ + switch(op) { + case AO_List: + *numArchives = archReq.numArchives; + *archives = archReq.archives; + break; + case AO_Store: + break; + case AO_Fetch: + *pfxOut = archReq.pfx; + break; + case AO_Remove: + break; + } + + return CSSM_OK; +} + +static void cStringToCssmData( + const char *cstr, + CSSM_DATA *cdata) +{ + if(cstr) { + cdata->Data = (uint8 *)cstr; + cdata->Length = strlen(cstr); + } + else { + cdata->Data = NULL; + cdata->Length = 0; + } +} + +int main(int argc, char **argv) +{ + SecKeychainRef kcRef = NULL; + CSSM_RETURN crtn; + CSSM_TP_HANDLE tpHand = 0; + OSStatus ortn; + + /* user-spec'd variables */ + ArchiveOp op = AO_List; + char *keychainName = NULL; + const char *userName = USER_DEFAULT; + const char *password = PWD_DEFAULT; + const char *archName = ARCHIVE_NAME_DEFAULT; + const char *hostName = HOST_DEFAULT; + char *outFile = NULL; + bool doPause = false; + bool loop = false; + char *p12Phrase = NULL; + + if(argc < 2) { + usage(argv); + } + switch(argv[1][0]) { + case 'l': + op = AO_List; + break; + case 's': + op = AO_Store; + break; + case 'f': + op = AO_Fetch; + break; + case 'r': + op = AO_Remove; + break; + default: + usage(argv); + } + + extern char *optarg; + extern int optind; + optind = 2; + int arg; + while ((arg = getopt(argc, argv, "u:Z:n:k:H:Nlo:z:")) != -1) { + switch (arg) { + case 'u': + userName = optarg; + break; + case 'Z': + password = optarg; + break; + case 'n': + archName = optarg; + break; + case 'k': + keychainName = optarg; + break; + case 'M': + doPause = true; + break; + case 'H': + hostName = optarg; + break; + case 'l': + loop = true; + break; + case 'o': + outFile = optarg; + break; + case 'z': + p12Phrase = optarg; + break; + case 'h': + usage(argv); + } + } + if(optind != argc) { + usage(argv); + } + + if(doPause) { + fpurge(stdin); + printf("Pausing for MallocDebug attach; CR to continue: "); + getchar(); + } + + if(keychainName != NULL) { + /* pick a keychain (optional) */ + ortn = SecKeychainOpen(keychainName, &kcRef); + if(ortn) { + cssmPerror("SecKeychainOpen", ortn); + exit(1); + } + + /* make sure it's there since a successful SecKeychainOpen proves nothing */ + SecKeychainStatus kcStat; + ortn = SecKeychainGetStatus(kcRef, &kcStat); + if(ortn) { + cssmPerror("SecKeychainGetStatus", ortn); + exit(1); + } + } + + /* bundle up our crufty C string args into CSSM_DATAs needed at the TP SPI */ + CSSM_DATA userNameData; + CSSM_DATA passwordData; + CSSM_DATA hostNameData; + CSSM_DATA archNameData; + CSSM_DATA timeStringData; + + cStringToCssmData(userName, &userNameData); + cStringToCssmData(password, &passwordData); + cStringToCssmData(hostName, &hostNameData); + cStringToCssmData(archName, &archNameData); + + /* time in seconds since the epoch, sprintf'd in base 10 */ + char timeStr[20]; + time_t nowTime = time(NULL); + printf("...nowTime = %lu\n", nowTime); + //nowTime += (60 * 60 * 24 * 26); // fails + nowTime += (60 * 60 * 24 * 25); // works + printf("...expirationTime = %lu\n", nowTime); + sprintf(timeStr, "%lu", nowTime); + timeStringData.Data = (uint8 *)timeStr; + timeStringData.Length = strlen(timeStr); + + /* other data needed by dotMacPostArchiveRequest() */ + CFDataRef p12 = NULL; + CSSM_DATA pfxInData = {0, NULL}; + CSSM_DATA pfxOutData = {0, NULL}; + unsigned numArchives = 0; + DotMacArchive *archives = NULL; + + /* Store op: get identity in p12 form */ + if(op == AO_Store) { + CFStringRef cfPhrase = NULL; + + /* Cert attribute - email address - contains the "@mac.com" */ + char emailAddr[500]; + strcpy(emailAddr, userName); + // nope strcat(emailAddr, "@mac.com"); + + /* find an identity for that email address */ + SecIdentityRef idRef = NULL; + OSStatus ortn = findIdentity(emailAddr, strlen(emailAddr), kcRef, &idRef); + if(ortn) { + printf("***Could not find an identity to store. Aborting.\n"); + goto errOut; + } + + /* convert that identity to p12 */ + SecKeyImportExportParameters keyParams; + memset(&keyParams, 0, sizeof(keyParams)); + keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; + if(p12Phrase) { + cfPhrase = CFStringCreateWithCString(NULL, p12Phrase, + kCFStringEncodingUTF8); + keyParams.passphrase = cfPhrase; + } + else { + keyParams.flags = kSecKeySecurePassphrase; + } + keyParams.alertTitle = CFSTR(".mac Identity Backup"); + keyParams.alertPrompt = + CFSTR("Enter passphrase for encrypting your .mac private key"); + ortn = SecKeychainItemExport(idRef, kSecFormatPKCS12, kSecItemPemArmour, + &keyParams, &p12); + if(ortn) { + cssmPerror("SecKeychainItemExport", crtn); + printf("***Error obtaining .mac identity in PKCS12 format. Aborting.\n"); + goto errOut; + } + + pfxInData.Data = (uint8 *)CFDataGetBytePtr(p12); + pfxInData.Length = CFDataGetLength(p12); + printf("...preparing to store archive of %lu bytes\n", pfxInData.Length); + + if(outFile) { + if(writeFile(outFile, pfxInData.Data, pfxInData.Length)) { + printf("***Error writing P12 to %s\n", outFile); + } + else { + printf("...wrote %lu bytes to %s\n", pfxInData.Length, outFile); + } + } + if(cfPhrase) { + CFRelease(cfPhrase); + } + } + + /* attach to the TP */ + tpHand = dotMacTpAttach(); + if(tpHand == 0) { + printf("***Error attaching to .mac TP; aborting.\n"); + ortn = -1; + goto errOut; + } + + /* go */ + crtn = dotMacPostArchiveRequest(op, tpHand, &userNameData, &passwordData, + hostName ? &hostNameData : NULL, + &archNameData, + &timeStringData, + &pfxInData, + &pfxOutData, + &numArchives, + &archives); + if(crtn) { + printf("***Error performing archive request; aborting.\n"); + goto errOut; + } + + /* post-request processing */ + + switch(op) { + case AO_List: + { + printf("=== List request complete; numArchives = %u ===\n", numArchives); + for(unsigned dex=0; dexarchiveName); + printf("\n"); + + printf(" time : "); + printString(&dmarch->timeString); + printf("\n"); + + /* now free what the TP allocated on our behalf */ + APP_FREE(dmarch->archiveName.Data); + APP_FREE(dmarch->timeString.Data); + } + APP_FREE(archives); + break; + } + + case AO_Store: + printf("=== archive \'%s\' backup complete ===\n", archName); + break; + case AO_Fetch: + { + bool didSomething = false; + if(pfxOutData.Length == 0) { + printf("***Archive fetch claimed to succeed, but no data seen\n"); + ortn = -1; + goto errOut; + } + + /* + * OK, we have a blob of PKCS12 data. Import to keychain and/or write it + * to a file. + */ + printf("=== %lu bytes of archive fetched ===\n", pfxOutData.Length); + if(outFile) { + if(writeFile(outFile, pfxOutData.Data, pfxOutData.Length)) { + printf("***Error writing P12 to %s\n", outFile); + } + else { + printf("...wrote %lu bytes to %s\n", pfxOutData.Length, outFile); + didSomething = true; + } + } + if(kcRef) { + /* Note we avoid importing to default keychain - user must really want + * to perform this step */ + CFDataRef p12Data = CFDataCreate(NULL, pfxOutData.Data, pfxOutData.Length); + SecExternalFormat extForm = kSecFormatPKCS12; + SecKeyImportExportParameters keyParams; + memset(&keyParams, 0, sizeof(keyParams)); + keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; + CFStringRef cfPhrase = NULL; + if(p12Phrase) { + cfPhrase = CFStringCreateWithCString(NULL, p12Phrase, + kCFStringEncodingUTF8); + keyParams.passphrase = cfPhrase; + } + else { + keyParams.flags = kSecKeySecurePassphrase; + } + keyParams.alertTitle = CFSTR(".mac Identity Restore"); + keyParams.alertPrompt = + CFSTR("Enter passphrase for decrypting your .mac private key"); + + /* go... */ + ortn = SecKeychainItemImport(p12Data, + NULL, // filename - passing kSecFormatPKCS12 is definitely enough + &extForm, + NULL, // itemType - import'll figure it out + 0, // SecItemImportExportFlags + &keyParams, + kcRef, + NULL); // we don't want any items returned + if(ortn) { + cssmPerror("SecKeychainItemImport", ortn); + printf("***Error importing p12 into keychain %s\n", keychainName); + } + else { + printf("...archive successfully imported into keychain %s\n", + keychainName); + didSomething = true; + } + if(cfPhrase) { + CFRelease(cfPhrase); + } + } + if(!didSomething) { + printf("...note we got an archive from the server but didn't have a " + "place to put it.\n"); + } + break; + } + case AO_Remove: + printf("=== Archive %s removed ===\n", archName); + break; + } + + if(doPause) { + fpurge(stdin); + printf("Pausing at end of test for MallocDebug attach; CR to continue: "); + getchar(); + } + +errOut: + if(kcRef) { + CFRelease(kcRef); + } + + if(tpHand) { + dotMacTpDetach(tpHand); + } + return ortn; +} + diff --git a/SecurityTests/clxutils/dotMacArchive/dotMacTpAttach.cpp b/SecurityTests/clxutils/dotMacArchive/dotMacTpAttach.cpp new file mode 100644 index 00000000..db24f80a --- /dev/null +++ b/SecurityTests/clxutils/dotMacArchive/dotMacTpAttach.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2004 Apple Computer, 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@ + */ + +/* + * dotMacTpAttach.cpp - attach/detach to/from loadable .mac TP + */ + +#include "dotMacTpAttach.h" +#include + +/* SPI; the framework actually contains a static lib we link against */ +#include + +static CSSM_VERSION vers = {2, 0}; +static const CSSM_GUID dummyGuid = { 0xFADE, 0, 0, { 1,2,3,4,5,6,7,0 }}; + +static CSSM_API_MEMORY_FUNCS memFuncs = { + cuAppMalloc, + cuAppFree, + cuAppRealloc, + cuAppCalloc, + NULL +}; + +/* load & attach; returns 0 on error */ +CSSM_TP_HANDLE dotMacTpAttach() +{ + CSSM_TP_HANDLE tpHand; + CSSM_RETURN crtn; + + if(cuCssmStartup() == CSSM_FALSE) { + return 0; + } + crtn = CSSM_ModuleLoad(&gGuidAppleDotMacTP, + CSSM_KEY_HIERARCHY_NONE, + NULL, // eventHandler + NULL); // AppNotifyCallbackCtx + if(crtn) { + cuPrintError("CSSM_ModuleLoad(AppleTP)", crtn); + return 0; + } + crtn = CSSM_ModuleAttach (&gGuidAppleDotMacTP, + &vers, + &memFuncs, // memFuncs + 0, // SubserviceID + CSSM_SERVICE_TP, // SubserviceFlags + 0, // AttachFlags + CSSM_KEY_HIERARCHY_NONE, + NULL, // FunctionTable + 0, // NumFuncTable + NULL, // reserved + &tpHand); + if(crtn) { + cuPrintError("CSSM_ModuleAttach(AppleTP)", crtn); + return 0; + } + else { + return tpHand; + } +} + +/* detach & unload */ +void dotMacTpDetach(CSSM_TP_HANDLE tpHand) +{ + CSSM_RETURN crtn = CSSM_ModuleDetach(tpHand); + if(crtn) { + return; + } + CSSM_ModuleUnload(&gGuidAppleDotMacTP, NULL, NULL); +} + diff --git a/SecurityTests/clxutils/dotMacArchive/dotMacTpAttach.h b/SecurityTests/clxutils/dotMacArchive/dotMacTpAttach.h new file mode 100644 index 00000000..98d908cb --- /dev/null +++ b/SecurityTests/clxutils/dotMacArchive/dotMacTpAttach.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2004 Apple Computer, 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@ + */ + +/* + * dotMacTpAttach.h - attach/detach to/from loadable .mac TP + */ + +#ifndef _DOT_MAC_TP_ATTACH_H_ +#define _DOT_MAC_TP_ATTACH_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* load & attach; returns 0 on error */ +CSSM_TP_HANDLE dotMacTpAttach(); + +/* detach & unload */ +void dotMacTpDetach(CSSM_TP_HANDLE tpHand); + +#ifdef __cplusplus +} +#endif + +#endif /* _DOT_MAC_TP_ATTACH_H_ */ + diff --git a/SecurityTests/clxutils/dotMacArchive/identSearch.cpp b/SecurityTests/clxutils/dotMacArchive/identSearch.cpp new file mode 100644 index 00000000..a049820e --- /dev/null +++ b/SecurityTests/clxutils/dotMacArchive/identSearch.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2004-2005 Apple Computer, 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@ + */ + +/* + * identSearch.cpp - search for identity whose cert has specified email address + */ + +#include "identSearch.h" +#include /* for kSecAlias */ + +/* + * Does the specified identity's cert have the specified email address? Returns + * true if so. + */ +bool idHasEmail( + SecIdentityRef idRef, + const void *emailAddress, // UTF8 encoded email address + unsigned emailAddressLen) +{ + SecCertificateRef certRef; + OSStatus ortn; + bool ourRtn = false; + + ortn = SecIdentityCopyCertificate(idRef, &certRef); + if(ortn) { + /* should never happen */ + cssmPerror("SecIdentityCopyCertificate", ortn); + return ortn; + } + + /* + * Fetch one attribute - the alias (which is always the "best attempt" at + * finding an email address within a cert). + */ + UInt32 oneTag = kSecAlias; + SecKeychainAttributeInfo attrInfo; + attrInfo.count = 1; + attrInfo.tag = &oneTag; + attrInfo.format = NULL; + SecKeychainAttributeList *attrList = NULL; + SecKeychainAttribute *attr = NULL; + + ortn = SecKeychainItemCopyAttributesAndData((SecKeychainItemRef)certRef, + &attrInfo, + NULL, // itemClass + &attrList, + NULL, // length - don't need the data + NULL); // outData + if(ortn || (attrList == NULL) || (attrList->count != 1)) { + /* I don't *think* this should ever happen... */ + cssmPerror("SecKeychainItemCopyAttributesAndData", ortn); + goto errOut; + } + attr = attrList->attr; + if(attr->length == emailAddressLen) { + if(!memcmp(attr->data, emailAddress, emailAddressLen)) { + ourRtn = true; + } + } +errOut: + SecKeychainItemFreeAttributesAndData(attrList, NULL); + CFRelease(certRef); + return ourRtn; +} + +/* public function */ +OSStatus findIdentity( + const void *emailAddress, // UTF8 encoded email address + unsigned emailAddressLen, + SecKeychainRef kcRef, // keychain to search, or NULL to search all + SecIdentityRef *idRef) // RETURNED +{ + OSStatus ortn; + + /* Search for all identities */ + SecIdentitySearchRef srchRef = nil; + ortn = SecIdentitySearchCreate(kcRef, + 0, // keyUsage - any + &srchRef); + if(ortn) { + /* should never happen */ + cssmPerror("SecIdentitySearchCreate", ortn); + return ortn; + } + + SecIdentityRef foundId = NULL; + do { + SecIdentityRef thisId; + ortn = SecIdentitySearchCopyNext(srchRef, &thisId); + if(ortn != noErr) { + break; + } + /* email addres match? */ + if(idHasEmail(thisId, emailAddress, emailAddressLen)) { + foundId = thisId; + break; + } + else { + /* we're done with thie identity */ + CFRelease(thisId); + } + } while(ortn == noErr); + CFRelease(srchRef); + if(foundId) { + *idRef = foundId; + return noErr; + } + else { + return errSecItemNotFound; + } +} + diff --git a/SecurityTests/clxutils/dotMacArchive/identSearch.h b/SecurityTests/clxutils/dotMacArchive/identSearch.h new file mode 100644 index 00000000..3f759e5a --- /dev/null +++ b/SecurityTests/clxutils/dotMacArchive/identSearch.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2004 Apple Computer, 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@ + */ + +/* + * identSearch.h - search for identity whose cert has specified email address + */ + +#ifndef _IDENT_SEARCH_H_ +#define _IDENT_SEARCH_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + * Find an identity whose cert has specified email address. + * Returns errSecItemNotFound if no matching identity found, noErr if + * we found one. + */ +OSStatus findIdentity( + const void *emailAddress, // UTF8 encoded email address + unsigned emailAddressLen, + SecKeychainRef kcRef, // keychain to search, or NULL to search all + SecIdentityRef *idRef); // RETURNED + +#ifdef __cplusplus +} +#endif + +#endif /* _IDENT_SEARCH_H_ */ + diff --git a/SecurityTests/clxutils/dotMacRequest/Makefile b/SecurityTests/clxutils/dotMacRequest/Makefile new file mode 100644 index 00000000..d3a12c99 --- /dev/null +++ b/SecurityTests/clxutils/dotMacRequest/Makefile @@ -0,0 +1,54 @@ +# name of executable to build +EXECUTABLE=dotMacRequest +# C++ source (with .cpp extension) +CPSOURCE= dotMacRequest.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/clxutils/dotMacRequest/README b/SecurityTests/clxutils/dotMacRequest/README new file mode 100644 index 00000000..5b88e9f5 --- /dev/null +++ b/SecurityTests/clxutils/dotMacRequest/README @@ -0,0 +1,23 @@ + dotMacRequest notes + +8/21/05 + +Request with live server now working. Use a real paid account. + +To request a cert + +dotMacRequest i -u dmitch77 -k dotMacKeychain.keychain -Z <<...dot mac password here>> + +To revoke, go to www.mac.com, log in, click your account name in upper right, authenticate +again, click "Secure iChat" in lower right, revoke the cert. You have to log out and log +back in each time you do this in order to see a newly generated cert after you revoke one. + +7/25/05 + +Request and renew work as of 7/25/05. +Renew requires the same key pair as the original, so: + -- renew only works when your current cert really is still current + -- run with -p (pick key pair) to select correct key pair + -- must delete old/current cert before running since the old + and new certs have the same DB attrs. + \ No newline at end of file diff --git a/SecurityTests/clxutils/dotMacRequest/dotMacRequest.cpp b/SecurityTests/clxutils/dotMacRequest/dotMacRequest.cpp new file mode 100644 index 00000000..e610eed4 --- /dev/null +++ b/SecurityTests/clxutils/dotMacRequest/dotMacRequest.cpp @@ -0,0 +1,624 @@ +/* + * dotMacRequest.cpp - simple illustration of using SecCertificateRequestCreate() and + * SecCertificateRequestSubmit to post a request for a .mac cert. + */ +#include +#include +#include +#include +#include +#include + +/* + * Defaults for the test setup du jour + */ +#define USER_DEFAULT "dmitch10" +#define PWD_DEFAULT "password" +#define HOST_DEFAULT "certmgmt.mac.com" + +/* + * Type of cert to request + */ +typedef enum { + CRT_Identity, /* actually, now "iChat encryption", not "identity" */ + CRT_EmailSign, + CRT_EmailEncrypt +} CertRequestType; + +static void usage(char **argv) +{ + printf("usage: %s op [options]\n", argv[0]); + printf("Op:\n"); + printf(" i -- generate iChat encryption cert\n"); + printf(" s -- generate email signing cert\n"); + printf(" e -- generate email encrypting cert\n"); + printf(" I -- search/retrieve request for iChat encryption cert\n"); + printf(" S -- search/retrieve request for signing cert\n"); + printf(" E -- search/retrieve request for encrypting cert\n"); + printf(" p -- pending request poll (via -u)\n"); + printf("Options:\n"); + printf(" -u username -- Default is %s\n", USER_DEFAULT); + printf(" -Z password -- default is %s\n", PWD_DEFAULT); + printf(" -p -- pick key pair from existing (default is generate)\n"); + printf(" -k keychain -- Source/destination of keys\n"); + printf(" -r -- Renew (default is new)\n"); + printf(" -a -- async (default is synchronous)\n"); + printf(" -H hostname -- Alternate .mac server host name (default %s)\n", + HOST_DEFAULT); + printf(" -M -- Pause for MallocDebug\n"); + printf(" -l -- loop\n"); + exit(1); +} + +/* print a string int he form of a CSSM_DATA */ +static void printString( + const CSSM_DATA *str) +{ + for(unsigned dex=0; dexLength; dex++) { + printf("%c", str->Data[dex]); + } +} + +/* basic "generate keypair" routine */ +static OSStatus genKeyPair( + SecKeychainRef kcRef, // optional, NULL means the default list + SecKeyRef *pubKey, // RETURNED + SecKeyRef *privKey) // RETURNED +{ + OSStatus ortn; + + ortn = SecKeyCreatePair(kcRef, + DOT_MAC_KEY_ALG, + DOT_MAC_KEY_SIZE, + 0, // context handle + /* public key usage and attrs */ + CSSM_KEYUSE_ANY, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE, + /* private key usage and attrs */ + CSSM_KEYUSE_ANY, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE | + CSSM_KEYATTR_SENSITIVE, + NULL, // initial access + pubKey, + privKey); + if(ortn) { + cssmPerror("SecKeyCreatePair", ortn); + } + return ortn; +} + +/* max number of oid/value pairs */ +#define MAX_ATTRS 5 + +/* + * search for a pending .mac cert request, get current status. + */ +static OSStatus dotMacGetPendingRequest( + /* required fields */ + const char *userName, // REQUIRED, C string + const char *password, // REQUIRED, C string + CertRequestType requestType, + + /* optional fields */ + const char *hostName, // C string + SecKeychainRef keychain) // destination of created cert (if !async) +{ + SecCertificateRequestAttribute attrs[MAX_ATTRS]; + SecCertificateRequestAttribute *attrp = attrs; + SecCertificateRequestAttributeList attrList; + + attrList.count = 0; + attrList.attr = attrs; + + /* user name */ + attrp->oid = CSSMOID_DOTMAC_CERT_REQ_VALUE_USERNAME; + attrp->value.Data = (uint8 *)userName; + attrp->value.Length = strlen(userName); + attrp++; + attrList.count++; + + /* password */ + attrp->oid = CSSMOID_DOTMAC_CERT_REQ_VALUE_PASSWORD; + attrp->value.Data = (uint8 *)password; + attrp->value.Length = strlen(password); + attrp++; + attrList.count++; + + /* options */ + + if(hostName) { + attrp->oid = CSSMOID_DOTMAC_CERT_REQ_VALUE_HOSTNAME; + attrp->value.Data = (uint8 *)hostName; + attrp->value.Length = strlen(hostName); + attrp++; + attrList.count++; + } + + /* map CertRequestType to a policy OID */ + const CSSM_OID *policy; + switch(requestType) { + case CRT_Identity: + policy = &CSSMOID_DOTMAC_CERT_REQ_IDENTITY; + break; + case CRT_EmailSign: + policy = &CSSMOID_DOTMAC_CERT_REQ_EMAIL_SIGN; + break; + case CRT_EmailEncrypt: + policy = &CSSMOID_DOTMAC_CERT_REQ_EMAIL_ENCRYPT; + break; + default: + printf("GAK! Bad cert type.\n"); + return -1; + } + OSStatus ortn; + SecCertificateRequestRef certReq = NULL; + SecCertificateRef certRef = NULL; + sint32 estTime; + + printf("...calling SecCertificateFindRequest\n"); + ortn = SecCertificateFindRequest(policy, + CSSM_CERT_X_509v3, + CSSM_TP_AUTHORITY_REQUEST_CERTISSUE, + NULL, NULL, // no keys needed + &attrList, + &certReq); + if(ortn) { + cssmPerror("SecCertificateFindRequest", ortn); + return ortn; + } + + printf("...calling SecCertificateRequestGetResult\n"); + ortn = SecCertificateRequestGetResult(certReq, keychain, &estTime, &certRef); + if(ortn) { + cssmPerror("SecCertificateRequestGetResult", ortn); + } + else { + printf("...SecCertificateRequestGetResult succeeded; estTime %d; cert %s\n", + (int)estTime, certRef ? "OBTAINED" : "NOT OBTAINED"); + } + if(certRef) { + CFRelease(certRef); + } + if(certReq) { + CFRelease(certReq); + } + return ortn; +} + +/* + * Do an "is there a pending request for this user?" poll. + * That function - via SecCertificateFindRequest() always returns an error; + * *we* only return an error if the result is something other than the + * expected two results: + * CSSMERR_APPLE_DOTMAC_REQ_IS_PENDING + * CSSMERR_APPLE_DOTMAC_NO_REQ_PENDING + */ +static OSStatus dotMacPostPendingReqPoll( + const char *userName, + const char *password, + const char *hostName) +{ + SecCertificateRequestAttribute attrs[MAX_ATTRS]; + SecCertificateRequestAttribute *attrp = attrs; + SecCertificateRequestAttributeList attrList; + uint8 oneBit = 1; + + attrList.count = 0; + attrList.attr = attrs; + + /* user name, required */ + attrp->oid = CSSMOID_DOTMAC_CERT_REQ_VALUE_USERNAME; + attrp->value.Data = (uint8 *)userName; + attrp->value.Length = strlen(userName); + attrp++; + attrList.count++; + + /* password, required */ + attrp->oid = CSSMOID_DOTMAC_CERT_REQ_VALUE_PASSWORD; + attrp->value.Data = (uint8 *)password; + attrp->value.Length = strlen(password); + attrp++; + attrList.count++; + + /* the "poll the server" indicator */ + attrp->oid = CSSMOID_DOTMAC_CERT_REQ_VALUE_IS_PENDING; + /* true ::= any nonzero data */ + attrp->value.Data = &oneBit; + attrp->value.Length = 1; + attrp++; + attrList.count++; + + /* options */ + + if(hostName) { + attrp->oid = CSSMOID_DOTMAC_CERT_REQ_VALUE_HOSTNAME; + attrp->value.Data = (uint8 *)hostName; + attrp->value.Length = strlen(hostName); + attrp++; + attrList.count++; + } + + /* policy, not technically needed; use this one by convention */ + const CSSM_OID *policy = &CSSMOID_DOTMAC_CERT_REQ_IDENTITY; + + OSStatus ortn; + SecCertificateRequestRef certReq = NULL; + + printf("...calling SecCertificateFindRequest\n"); + ortn = SecCertificateFindRequest(policy, + CSSM_CERT_X_509v3, + CSSM_TP_AUTHORITY_REQUEST_CERTISSUE, + NULL, NULL, // no keys needed + &attrList, + &certReq); + + switch(ortn) { + case CSSMERR_APPLE_DOTMAC_REQ_IS_PENDING: + printf("...result: REQ_IS_PENDING\n"); + ortn = noErr; + break; + case CSSMERR_APPLE_DOTMAC_NO_REQ_PENDING: + printf("...result: NO_REQ_PENDING\n"); + ortn = noErr; + break; + case noErr: + /* should never happen */ + printf("...UNEXPECTED SUCCESS on SecCertificateFindRequest\n"); + ortn = internalComponentErr; + if(certReq != NULL) { + /* Somehow, it got created */ + CFRelease(certReq); + } + break; + default: + cssmPerror("SecCertificateFindRequest", ortn); + break; + } + return ortn; +} + +/* + * Post a .mac cert request, with a small number of options. + */ +static OSStatus dotMacPostCertRequest( + /* required fields */ + const char *userName, // REQUIRED, C string + const char *password, // REQUIRED, C string + SecKeyRef privKey, // REQUIRED + SecKeyRef pubKey, + CertRequestType requestType, + bool renew, // false: new cert + // true : renew existing + bool async, // false: wait for result + // true : just post request and return + /* optional fields */ + const char *hostName, // C string + SecKeychainRef keychain) // destination of created cert (if !async) +{ + + /* the main job here is bundling up the arguments in an array of OID/value pairs */ + SecCertificateRequestAttribute attrs[MAX_ATTRS]; + SecCertificateRequestAttribute *attrp = attrs; + SecCertificateRequestAttributeList attrList; + uint8 oneBit = 1; + + attrList.count = 0; + attrList.attr = attrs; + + /* user name */ + attrp->oid = CSSMOID_DOTMAC_CERT_REQ_VALUE_USERNAME; + attrp->value.Data = (uint8 *)userName; + attrp->value.Length = strlen(userName); + attrp++; + attrList.count++; + + /* password */ + attrp->oid = CSSMOID_DOTMAC_CERT_REQ_VALUE_PASSWORD; + attrp->value.Data = (uint8 *)password; + attrp->value.Length = strlen(password); + attrp++; + attrList.count++; + + /* options */ + + if(hostName) { + attrp->oid = CSSMOID_DOTMAC_CERT_REQ_VALUE_HOSTNAME; + attrp->value.Data = (uint8 *)hostName; + attrp->value.Length = strlen(hostName); + attrp++; + attrList.count++; + } + + if(renew) { + attrp->oid = CSSMOID_DOTMAC_CERT_REQ_VALUE_RENEW; + /* true ::= any nonzero data */ + attrp->value.Data = &oneBit; + attrp->value.Length = 1; + attrp++; + attrList.count++; + } + + if(async) { + attrp->oid = CSSMOID_DOTMAC_CERT_REQ_VALUE_ASYNC; + /* true ::= any nonzero data */ + attrp->value.Data = &oneBit; + attrp->value.Length = 1; + attrp++; + attrList.count++; + } + + /* map CertRequestType to a policy OID */ + const CSSM_OID *policy; + switch(requestType) { + case CRT_Identity: + policy = &CSSMOID_DOTMAC_CERT_REQ_IDENTITY; + break; + case CRT_EmailSign: + policy = &CSSMOID_DOTMAC_CERT_REQ_EMAIL_SIGN; + break; + case CRT_EmailEncrypt: + policy = &CSSMOID_DOTMAC_CERT_REQ_EMAIL_ENCRYPT; + break; + default: + printf("GAK! Bad cert type.\n"); + return -1; + } + OSStatus ortn; + SecCertificateRequestRef certReq = NULL; + + ortn = SecCertificateRequestCreate(policy, + CSSM_CERT_X_509v3, + CSSM_TP_AUTHORITY_REQUEST_CERTISSUE, + privKey, + pubKey, + &attrList, + &certReq); + if(ortn) { + cssmPerror("SecCertificateRequestCreate", ortn); + return ortn; + } + + printf("...submitting request to .mac server\n"); + sint32 estTime = 0; + ortn = SecCertificateRequestSubmit(certReq, &estTime); + switch(ortn) { + case CSSMERR_APPLE_DOTMAC_REQ_REDIRECT: + { + /* + * A special case; the server is redirecting the calling app to + * a URL which we fetch and report like so: + */ + CSSM_DATA url = {0, NULL}; + ortn = SecCertificateRequestGetData(certReq, &url); + if(ortn) { + cssmPerror("SecCertificateRequestGetData", ortn); + printf("***APPLE_DOTMAC_REQ_REDIRECT obtained but no URL availalble.\n"); + } + else { + printf("***APPLE_DOTMAC_REQ_REDIRECT obtained; redirect URL is: "); + printString(&url); + printf("\n"); + } + break; + } + + case CSSM_OK: + printf("...cert request submitted; estimatedTime %d.\n", (int)estTime); + break; + default: + cssmPerror("SecCertificateRequestSubmit", ortn); + break; + } + if(ortn || async) { + /* we're done */ + CFRelease(certReq); + return ortn; + } + + /* + * Running synchronously, and the submit succeeded. Try to get a result. + * In the real world this would be polled, every so often.... + */ + SecCertificateRef certRef = NULL; + printf("...attempting to get result of cert request...\n"); + ortn = SecCertificateRequestGetResult(certReq, keychain, &estTime, &certRef); + if(ortn) { + cssmPerror("SecCertificateRequestGetResult", ortn); + } + else { + printf("...SecCertificateRequestGetResult succeeded; estTime %d; cert %s\n", + (int)estTime, certRef ? "OBTAINED" : "NOT OBTAINED"); + } + if(certRef) { + CFRelease(certRef); + CFRelease(certReq); + } + return ortn; +} + +#define ALWAYS_DO_SUBMIT 0 + + +int main(int argc, char **argv) +{ + SecKeyRef pubKeyRef = NULL; + SecKeyRef privKeyRef = NULL; + SecKeychainRef kcRef = NULL; + OSStatus ortn; + + /* user-spec'd variables */ + bool genKeys = true; /* true: generate; false: pick 'em */ + char *keychainName = NULL; + char *userName = USER_DEFAULT; + char *password = PWD_DEFAULT; + char *hostName = NULL; /* leave as the default! = HOST_DEFAULT; */ + /* + * WARNING: doing a renew operation requires that you delete your *current* + * .mac cert from the destination keychain. The DB attrs of the old and new certs + * are the same! + */ + bool doRenew = false; + CertRequestType reqType = CRT_Identity; + bool doPause = false; + bool async = false; + bool doSearch = false; /* false: post cert request + * true : search for existing request, get + * status for it */ + bool loop = false; + bool doPendingReqPoll = false; + + if(argc < 2) { + usage(argv); + } + switch(argv[1][0]) { + case 'i': + reqType = CRT_Identity; + break; + case 's': + reqType = CRT_EmailSign; + break; + case 'e': + reqType = CRT_EmailEncrypt; + break; + case 'I': + doSearch = true; + reqType = CRT_Identity; + break; + case 'S': + doSearch = true; + reqType = CRT_EmailSign; + break; + case 'E': + doSearch = true; + reqType = CRT_EmailEncrypt; + break; + case 'p': + doPendingReqPoll = true; + break; + default: + usage(argv); + } + + extern char *optarg; + extern int optind; + optind = 2; + int arg; + while ((arg = getopt(argc, argv, "u:Z:pk:rMH:al")) != -1) { + switch (arg) { + case 'u': + userName = optarg; + break; + case 'Z': + password = optarg; + break; + case 'p': + genKeys = false; + break; + case 'k': + keychainName = optarg; + break; + case 'r': + doRenew = true; + break; + case 'M': + doPause = true; + break; + case 'H': + hostName = optarg; + break; + case 'a': + async = true; + break; + case 'l': + loop = true; + break; + case 'h': + default: + usage(argv); + } + } + if(optind != argc) { + usage(argv); + } + + if(doPause) { + fpurge(stdin); + printf("Pausing for MallocDebug attach; CR to continue: "); + getchar(); + } + + if(keychainName != NULL) { + /* pick a keychain (optional) */ + ortn = SecKeychainOpen(keychainName, &kcRef); + if(ortn) { + cssmPerror("SecKeychainOpen", ortn); + exit(1); + } + + /* make sure it's there since a successful SecKeychainOpen proves nothing */ + SecKeychainStatus kcStat; + ortn = SecKeychainGetStatus(kcRef, &kcStat); + if(ortn) { + cssmPerror("SecKeychainGetStatus", ortn); + exit(1); + } + } + + if((!doSearch || ALWAYS_DO_SUBMIT) && !doPendingReqPoll) { + /* get a key pair, somehow */ + if(genKeys) { + ortn = genKeyPair(kcRef, &pubKeyRef, &privKeyRef); + } + else { + ortn = keyPicker(kcRef, &pubKeyRef, &privKeyRef); + } + if(ortn) { + printf("Can't proceed without a keypair. Aborting.\n"); + exit(1); + } + } + + /* go */ + do { + if(doSearch) { + #if ALWAYS_DO_SUBMIT + /* debug only */ + dotMacPostCertRequest(userName, password, privKeyRef, pubKeyRef, + reqType, doRenew, async, hostName, kcRef); + #endif + + /* end */ + ortn = dotMacGetPendingRequest(userName, password, reqType, hostName, kcRef); + } + else if(doPendingReqPoll) { + ortn = dotMacPostPendingReqPoll(userName, password, hostName); + } + else { + ortn = dotMacPostCertRequest(userName, password, privKeyRef, pubKeyRef, + reqType, doRenew, async, hostName, kcRef); + } + if(doPause) { + fpurge(stdin); + printf("Pausing for MallocDebug attach; CR to continue: "); + getchar(); + } + } while(loop); + if(privKeyRef) { + CFRelease(privKeyRef); + } + if(pubKeyRef) { + CFRelease(pubKeyRef); + } + if(kcRef) { + CFRelease(kcRef); + } + + if(doPause) { + fpurge(stdin); + printf("Pausing at end of test for MallocDebug attach; CR to continue: "); + getchar(); + } + + return ortn; +} + diff --git a/SecurityTests/clxutils/dotMacTool/MDS b/SecurityTests/clxutils/dotMacTool/MDS new file mode 100644 index 00000000..6fc69f9f --- /dev/null +++ b/SecurityTests/clxutils/dotMacTool/MDS @@ -0,0 +1,6 @@ +{87191ca1-0fc9-11d4-849a000502b52122} d *AppleDL +{87191ca2-0fc9-11d4-849a000502b52122} cm *AppleCSP +{87191ca3-0fc9-11d4-849a000502b52122} cdm *AppleCSPDL +{87191ca4-0fc9-11d4-849a000502b52122} Cm *AppleX509CL +{87191ca5-0fc9-11d4-849a000502b52122} tm *AppleX509TP +{87191ca7-0fc9-11d4-849a000502b52122} tm /Volumes/Data_and_Apps/build/build/security_apple_dotmac_tp.bundle diff --git a/SecurityTests/clxutils/dotMacTool/Makefile b/SecurityTests/clxutils/dotMacTool/Makefile new file mode 100644 index 00000000..aef0a64e --- /dev/null +++ b/SecurityTests/clxutils/dotMacTool/Makefile @@ -0,0 +1,59 @@ +EXECUTABLE=dotMacTool +# C++ source (with .cpp extension) +CPSOURCE= dotMacTool.cpp keyPicker.cpp +# C source (.c extension) +CSOURCE= +OFILES = $(CSOURCE:%.c=%.o) $(CPSOURCE:%.cpp=%.o) + +LOCAL_BUILD= $(shell echo $(LOCAL_BUILD_DIR)) + +CC=c++ +VARIANT_SUFFIX= + +FRAMEWORKS=-framework Security$(VARIANT_SUFFIX) -framework CoreFoundation +FRAME_SEARCH= -F$(LOCAL_BUILD) -F/usr/local/SecurityPieces/Frameworks +FINCLUDES= +PINCLUDES= +CINCLUDES= $(FINCLUDES) $(PINCLUDES) +###WFLAGS= -Wno-four-char-constants -Wall -Werror +WFLAGS= -Wno-four-char-constants -Wall -Wno-deprecated-declarations +DEBUG_CFLAGS?= +CMDLINE_LDFLAGS?= +CFLAGS= -g $(CINCLUDES) $(WFLAGS) $(FRAME_SEARCH) $(DEBUG_CFLAGS) + +# +# This assumes final load with cc, not ld +# +LIBS= -lstdc++ +LIBPATH= -L$(LOCAL_BUILD) +LDFLAGS= $(LIBS) $(LIBPATH) $(FRAME_SEARCH) $(CMDLINE_LDFLAGS) -lsecurity_cdsa_utils -lsecurity_utilities + +# +# Executable in build folder +# +BUILT_TARGET= $(LOCAL_BUILD)/$(EXECUTABLE) + +first: $(BUILT_TARGET) + +install: + +debug: + make "VARIANT_SUFFIX=,_debug" + +64bit: + make "DEBUG_CFLAGS=-arch ppc64" "CMDLINE_LDFLAGS=-arch ppc64" + +64bitFat: + make "DEBUG_CFLAGS=-arch ppc -arch ppc64" "CMDLINE_LDFLAGS=-arch ppc -arch ppc64" + +$(BUILT_TARGET): $(OFILES) + $(CC) -o $(BUILT_TARGET) $(OFILES) $(FRAMEWORKS) $(LDFLAGS) + +clean: + rm -f *.o $(EXECUTABLE) + +%.o: %.c + $(CC) $(CFLAGS) -c -o $*.o $< + +%.o: %.cpp + $(CC) $(CFLAGS) -c -o $*.o $< diff --git a/SecurityTests/clxutils/dotMacTool/README b/SecurityTests/clxutils/dotMacTool/README new file mode 100644 index 00000000..6790e2e0 --- /dev/null +++ b/SecurityTests/clxutils/dotMacTool/README @@ -0,0 +1,107 @@ +dotMacTool notes May 4 2004 + +-- for now you need this in /etc/hosts: + +# for INT2 +17.207.20.182 int-cert certmgmt.mac.com certinfo.mac.com + +# or, for INT1 +17.207.43.109 qa-cert certmgmt.mac.com certinfo.mac.com + +-- A good way to run tcpdump to show HTTP traffic on port 2150: + + tcpdump -i en0 -s 0 -A -q tcp port 2150 + +-- renew cert for existing account doug1 with password 123456: + +tower.local:dotMacTool> dotMacTool g -g -u doug1 -Z 123456 -k foobar -r -o /tmp/c2.pem +<<>> +...cert acquisition complete +...2496 bytes of Cert written to /tmp/c2.pem + +============================================== + +-- demo queued response and retrieval + -- set FORCE_SUCCESS_QUEUED to 1 in dotMacTpRpcGlue.cpp, this turns a full + success RPC into a successQueued RPC + +tower.local:dotMacTool> dotMacTool g -g -u doug1 -Z 123456 -k foobar -r -o /tmp/refid.pem +<<>> +...Forcing REQ_QUEUED status +...cert acquisition complete +...105 bytes of Cert written to /tmp/refid.pem + +...then lookup.... + +tower.local:dotMacTool> dotMacTool l -f /tmp/refid.pem -o /tmp/cert.pem +<<>> +...cert retrieval complete +...10010 bytes of cert data written to /tmp/cert.pem + +============================================== + +TO DO +----- + +-- DOT_MAC_LOOKUP_ID_PATH* consts in dotMacTp.h will change to allow loopkup of one + specific cert +-- DOT_MAC_SIGN_HOST_NAME and DOT_MAC_LOOKUP_HOST will change to avoid the port 2150 + +.......... + +Aug 10 testing + +-- use INT1 environment + +Ê # in /etc/hosts: + 17.207.20.58 int1-idiskng certmgmt.mac.com certinfo.mac.com + + -- lookup via http://certinfo.mac.com:2150/lookup + -- request via certmgmt.mac.com + +-- provision http://17.207.20.58:2150/_provision/Public/account + -- account dmitch4 pwd password + -- signed up for IDEN + + # note no more @mac.com for user name + % dotMacTool g -g -u dmitch4 -Z password -k foobar -o /tmp/refid -H certmgmt.mac.com:2150 +...Forcing REQ_QUEUED status +...Cert request QUEUED +...77 bytes of RefId written to /tmp/refid + + # note we can't specify alternate host for lookup, have to use !NDEBUG config of .mac TP + % dotMacTool l -f /tmp/refid -k foobar + + -- account dmitch5 pwd password + -- signed up for EMAIL SIGN + + % dotMacRequest s -u dmitch5 -Z password -k foobar -H certmgmt.mac.com:2150 -a + -- request had method sign.email + -- response had FailedNotSupportedForAccount + + # try again with ID cert, it works + % dotMacRequest i -u dmitch5 -Z password -k foobar -H certmgmt.mac.com:2150 -a + + # get result, nothing in prefs - yep, OK, we ran async + + + -- dmitch6 password, async, OK + -- dmitch7, password + ... + dmitch10 pwd password + + % dotMacRequest i -u dmitch10 -Z password -k foobar -H certmgmt.mac.com:2150 + ...works! + + dmitch11 password + +1/10/05 + +name dmitch_int2 pwd "password" + +% dotMacTool g -g -u dmitch_int2 -Z password -k newDotMac.keychain -o /tmp/refid +...worked + +name dmitch_new pwd password, got a cert +name dmitch_new2 pwd password + diff --git a/SecurityTests/clxutils/dotMacTool/dotMacTool.cpp b/SecurityTests/clxutils/dotMacTool/dotMacTool.cpp new file mode 100644 index 00000000..4596b389 --- /dev/null +++ b/SecurityTests/clxutils/dotMacTool/dotMacTool.cpp @@ -0,0 +1,728 @@ +/* + * dotMacTool.cpp - .mac TP exerciser + */ + +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include + +#include "keyPicker.h" +#include + +#define USER_DEFAULT "dmitchtest@mac.com" +#define PWD_DEF "123456" + +static void usage(char **argv) +{ + printf("usage: %s op [options]\n", argv[0]); + printf("Op:\n"); + printf(" g generate identity cert\n"); + printf(" G generate email signing cert\n"); + printf(" e generate email encrypting cert\n"); + printf(" l lookup cert (requires -f)\n"); + printf(" L lookup identity cert (via -u)\n"); + printf(" M lookup email signing cert (via -u)\n"); + printf(" N lookup encrypting cert (via -u)\n"); + printf("Options:\n"); + printf(" -g Generate keypair\n"); + printf(" -p pick key pair from existing\n"); + printf(" -u username Default = %s\n", USER_DEFAULT); + printf(" -Z password Specify password immediately\n"); + printf(" -z Use default password %s\n", PWD_DEF); + printf(" -k keychain Source/destination of keys and certs\n"); + printf(" -c filename Write CSR to filename\n"); + printf(" -C filename Use existing CSR (no keygen)\n"); + printf(" -f refIdFile RefId file for cert lookup\n"); + printf(" -n Do NOT post the CSR to the .mac server\n"); + printf(" -H hostname Alternate .mac server host name (default %s)\n", + DOT_MAC_SIGN_HOST_NAME); + printf(" -o outFile Write output cert or refId (if any) to outFile\n"); + printf(" -r Renew (default is new)\n"); + printf(" -M Pause for MallocDebug\n"); + printf(" -q Quiet\n"); + printf(" -v Verbose\n"); + printf(" -h Usage\n"); + exit(1); +} + +static CSSM_VERSION vers = {2, 0}; + +static CSSM_API_MEMORY_FUNCS memFuncs = { + cuAppMalloc, + cuAppFree, + cuAppRealloc, + cuAppCalloc, + NULL + }; + +static CSSM_TP_HANDLE dotMacStartup() +{ + CSSM_TP_HANDLE tpHand; + CSSM_RETURN crtn; + + if(cuCssmStartup() == CSSM_FALSE) { + return 0; + } + crtn = CSSM_ModuleLoad(&gGuidAppleDotMacTP, + CSSM_KEY_HIERARCHY_NONE, + NULL, // eventHandler + NULL); // AppNotifyCallbackCtx + if(crtn) { + cuPrintError("CSSM_ModuleLoad(DotMacTP)", crtn); + return 0; + } + crtn = CSSM_ModuleAttach (&gGuidAppleDotMacTP, + &vers, + &memFuncs, // memFuncs + 0, // SubserviceID + CSSM_SERVICE_TP, // SubserviceFlags + 0, // AttachFlags + CSSM_KEY_HIERARCHY_NONE, + NULL, // FunctionTable + 0, // NumFuncTable + NULL, // reserved + &tpHand); + if(crtn) { + cuPrintError("CSSM_ModuleAttach(DotMacTP)", crtn); + return 0; + } + else { + return tpHand; + } +} + +/* print text, safely */ +static void snDumpText( + const unsigned char *rcvBuf, + unsigned len) +{ + char *cp = (char *)rcvBuf; + unsigned i; + char c; + + for(i=0; i", ((unsigned)c) & 0xff); + } + break; + } + + } +} + +static OSStatus genKeyPair( + SecKeychainRef kcRef, // NULL means the default list + SecKeyRef *pubKey, // RETURNED + SecKeyRef *privKey) // RETURNED +{ + OSStatus ortn; + + ortn = SecKeyCreatePair(kcRef, + DOT_MAC_KEY_ALG, + DOT_MAC_KEY_SIZE, + 0, // context handle + /* public key usage and attrs */ + CSSM_KEYUSE_ANY, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE, + /* private key usage and attrs */ + CSSM_KEYUSE_ANY, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE | + CSSM_KEYATTR_SENSITIVE, + NULL, // initial access + pubKey, + privKey); + if(ortn) { + cssmPerror("SecKeyCreatePair", ortn); + } + return ortn; +} + +/* Lookup via ReferenceID, obtained from CSSM_TP_SubmitCredRequest() */ +OSStatus doLookupViaRefId( + CSSM_TP_HANDLE tpHand, + unsigned char *refId, + unsigned refIdLen, + char *outFile, + bool verbose) +{ + CSSM_DATA refIdData = { refIdLen, refId }; + sint32 EstimatedTime; + CSSM_BOOL ConfirmationRequired; + CSSM_TP_RESULT_SET_PTR resultSet = NULL; + CSSM_RETURN crtn; + + crtn = CSSM_TP_RetrieveCredResult(tpHand, &refIdData, NULL, + &EstimatedTime, &ConfirmationRequired, &resultSet); + if(crtn) { + cssmPerror("CSSM_TP_RetrieveCredResult", crtn); + return crtn; + } + if(resultSet == NULL) { + printf("***CSSM_TP_RetrieveCredResult OK, but no result set\n"); + return -1; + } + if(resultSet->NumberOfResults != 1) { + printf("***CSSM_TP_RetrieveCredResult OK, NumberOfResults (%u)\n", + (unsigned)resultSet->NumberOfResults); + return -1; + } + if(resultSet->Results == NULL) { + printf("***CSSM_TP_RetrieveCredResult OK, but empty result set\n"); + return -1; + } + CSSM_DATA_PTR certData = (CSSM_DATA_PTR)resultSet->Results; + + printf("...cert retrieval complete\n"); + if(outFile) { + if(!writeFile(outFile, certData->Data, certData->Length)) { + printf("...%lu bytes of cert data written to %s\n", + certData->Length, outFile); + } + else { + printf("***Error writing cert to %s\n", outFile); + crtn = ioErr; + } + } + else if(verbose) { + unsigned char *der; + unsigned derLen; + if(pemDecode(certData->Data, certData->Length, &der, &derLen)) { + printf("***Error PEM decoding returned cert\n"); + } + else { + printCert(der, derLen, CSSM_FALSE); + free(der); + } + } + return noErr; +} + +/* +* Lookup via user name, a greatly simplified form of CSSM_TP_SubmitCredRequest() +*/ +OSStatus doLookupViaUserName( + CSSM_TP_HANDLE tpHand, + const CSSM_OID *opOid, + const char *userName, + const char *hostName, // optional + char *outFile, + bool verbose) +{ + CSSM_APPLE_DOTMAC_TP_CERT_REQUEST certReq; + CSSM_TP_AUTHORITY_ID tpAuthority; + CSSM_TP_AUTHORITY_ID *tpAuthPtr = NULL; + CSSM_NET_ADDRESS tpNetAddrs; + CSSM_TP_REQUEST_SET reqSet; + CSSM_FIELD policyField; + CSSM_DATA certData = {0, NULL}; + sint32 estTime; + CSSM_TP_CALLERAUTH_CONTEXT callerAuth; + + memset(&certReq, 0, sizeof(certReq)); + certReq.userName.Data = (uint8 *)userName; + certReq.userName.Length = strlen(userName); + if(hostName != NULL) { + tpAuthority.AuthorityCert = NULL; + tpAuthority.AuthorityLocation = &tpNetAddrs; + tpNetAddrs.AddressType = CSSM_ADDR_NAME; + tpNetAddrs.Address.Data = (uint8 *)hostName; + tpNetAddrs.Address.Length = strlen(hostName); + tpAuthPtr = &tpAuthority; + }; + + certReq.version = CSSM_DOT_MAC_TP_REQ_VERSION; + reqSet.NumberOfRequests = 1; + reqSet.Requests = &certReq; + policyField.FieldOid = *opOid; + policyField.FieldValue.Data = NULL; + policyField.FieldValue.Length = 0; + memset(&callerAuth, 0, sizeof(callerAuth)); + callerAuth.Policy.NumberOfPolicyIds = 1; + callerAuth.Policy.PolicyIds = &policyField; + + CSSM_RETURN crtn = CSSM_TP_SubmitCredRequest (tpHand, + tpAuthPtr, + CSSM_TP_AUTHORITY_REQUEST_CERTLOOKUP, + &reqSet, // const CSSM_TP_REQUEST_SET *RequestInput, + &callerAuth, + &estTime, // sint32 *EstimatedTime, + &certData); // CSSM_DATA_PTR ReferenceIdentifier + + if(crtn) { + cssmPerror("CSSM_TP_SubmitCredRequest(lookup)", crtn); + return crtn; + } + + printf("...cert lookup complete\n"); + if(outFile) { + if(!writeFile(outFile, certData.Data, certData.Length)) { + printf("...%lu bytes of cert data written to %s\n", + certData.Length, outFile); + } + else { + printf("***Error writing cert to %s\n", outFile); + crtn = ioErr; + } + } + if(verbose) { + /* This one returns the cert in DER format, we might revisit that */ + printCert(certData.Data, certData.Length, CSSM_FALSE); + } + return crtn; +} + +#define FULL_EMAIL_ADDRESS 1 + +int main(int argc, char **argv) +{ + CSSM_RETURN crtn; + CSSM_TP_AUTHORITY_ID tpAuthority; + CSSM_TP_AUTHORITY_ID *tpAuthPtr = NULL; + CSSM_NET_ADDRESS tpNetAddrs; + CSSM_APPLE_DOTMAC_TP_CERT_REQUEST certReq; + CSSM_TP_REQUEST_SET reqSet; + CSSM_CSP_HANDLE cspHand = 0; + CSSM_X509_TYPE_VALUE_PAIR tvp; + char pwdBuf[1000]; + CSSM_TP_CALLERAUTH_CONTEXT callerAuth; + sint32 estTime; + CSSM_DATA refId = {0, NULL}; + OSStatus ortn; + SecKeyRef pubKeyRef = NULL; + SecKeyRef privKeyRef = NULL; + const CSSM_KEY *privKey = NULL; + const CSSM_KEY *pubKey = NULL; + SecKeychainRef kcRef = NULL; + CSSM_FIELD policyField; + + /* user-spec'd variables */ + bool genKeys = false; + bool pickKeys = false; + char *keychainName = NULL; + char *csrOutName = NULL; + char *csrInName = NULL; + const char *userName = USER_DEFAULT; + char *password = NULL; + char *hostName = NULL; + bool doNotPost = false; + bool doRenew = false; + const CSSM_OID *opOid = NULL; + char *outFile = NULL; + bool quiet = false; + bool verbose = false; + bool lookupViaRefId = false; + bool lookupViaUserName = false; + char *refIdFile = NULL; + bool doPause = false; + + if(argc < 2) { + usage(argv); + } + switch(argv[1][0]) { + case 'L': + lookupViaUserName = true; + /* drop thru */ + case 'g': + opOid = &CSSMOID_DOTMAC_CERT_REQ_IDENTITY; + break; + + case 'M': + lookupViaUserName = true; + /* drop thru */ + case 'G': + opOid = &CSSMOID_DOTMAC_CERT_REQ_EMAIL_SIGN; + break; + + case 'N': + lookupViaUserName = true; + /* drop thru */ + case 'e': + opOid = &CSSMOID_DOTMAC_CERT_REQ_EMAIL_ENCRYPT; + break; + + case 'l': + lookupViaRefId = true; + break; + default: + usage(argv); + } + + extern char *optarg; + extern int optind; + optind = 2; + int arg; + while ((arg = getopt(argc, argv, "gpk:c:u:Z:H:nzrC:o:hf:Mqv")) != -1) { + switch (arg) { + case 'g': + genKeys = true; + break; + case 'p': + pickKeys = true; + break; + case 'u': + userName = optarg; + break; + case 'Z': + password = optarg; + break; + case 'z': + password = (char *)PWD_DEF; + break; + case 'k': + keychainName = optarg; + break; + case 'c': + csrOutName = optarg; + break; + case 'C': + csrInName = optarg; + break; + case 'H': + hostName = optarg; + break; + case 'n': + doNotPost = true; + break; + case 'r': + doRenew = true; + break; + case 'o': + outFile = optarg; + break; + case 'f': + refIdFile = optarg; + break; + case 'M': + doPause = true; + break; + case 'v': + verbose = true; + break; + case 'q': + quiet = true; + break; + case 'h': + usage(argv); + } + } + + if(doPause) { + fpurge(stdin); + printf("Pausing for MallocDebug attach; CR to continue: "); + getchar(); + } + + CSSM_TP_HANDLE tpHand = dotMacStartup(); + if(tpHand == 0) { + printf("Error attaching to the .mac TP. Check your MDS file.\n"); + exit(1); + } + + if(lookupViaRefId) { + if(refIdFile == NULL) { + printf("I need a refIdFile to do a lookup.\n"); + usage(argv); + } + unsigned char *refId; + unsigned refIdLen; + int irtn = readFile(refIdFile, &refId, &refIdLen); + if(irtn) { + printf("***Error reading refId from %s. Aborting.\n", refIdFile); + exit(1); + } + ortn = doLookupViaRefId(tpHand, refId, refIdLen, outFile, verbose); + free(refId); + goto done; + } + if(lookupViaUserName) { + ortn = doLookupViaUserName(tpHand, opOid, userName, hostName, outFile, verbose); + goto done; + } + if(!pickKeys && !genKeys && (csrInName == NULL)) { + printf("***You must specify either the -p (pick keys) or -g (generate keys)" + " arguments, or provide a CSR (-C).\n"); + exit(1); + } + + memset(&certReq, 0, sizeof(certReq)); + + /* all of the subsequest argument are superfluous for lookupViaUserName, except for + * the user name itself, which has a default */ + if(keychainName != NULL) { + /* pick a keychain (optional) */ + ortn = SecKeychainOpen(keychainName, &kcRef); + if(ortn) { + cssmPerror("SecKeychainOpen", ortn); + exit(1); + } + + /* make sure it's there since a successful SecKeychainOpen proves nothing */ + SecKeychainStatus kcStat; + ortn = SecKeychainGetStatus(kcRef, &kcStat); + if(ortn) { + cssmPerror("SecKeychainGetStatus", ortn); + goto done; + } + } + + if(password == NULL) { + const char *pwdp = getpass("Enter .mac password: "); + if(pwdp == NULL) { + printf("Aboerting.\n"); + ortn = paramErr; + goto done; + } + memmove(pwdBuf, pwdp, strlen(pwdp) + 1); + password = pwdBuf; + } + certReq.password.Data = (uint8 *)password; + certReq.password.Length = strlen(password); + certReq.userName.Data = (uint8 *)userName; + certReq.userName.Length = strlen(userName); + + if(csrInName) { + unsigned len; + if(readFile(csrInName, &certReq.csr.Data, &len)) { + printf("***Error reading CSR from %s. Aborting.\n", csrInName); + exit(1); + } + certReq.csr.Length = len; + certReq.flags |= CSSM_DOTMAC_TP_EXIST_CSR; + } + else { + /* + * All the stuff the TP needs to actually generate a CSR. + * + * Get a key pair, somehow. + */ + if(genKeys) { + ortn = genKeyPair(kcRef, &pubKeyRef, &privKeyRef); + } + else { + ortn = keyPicker(kcRef, &pubKeyRef, &privKeyRef); + } + if(ortn) { + printf("Can't proceed without a keypair. Aborting.\n"); + exit(1); + } + ortn = SecKeyGetCSSMKey(pubKeyRef, &pubKey); + if(ortn) { + cssmPerror("SecKeyGetCSSMKey", ortn); + goto done; + } + ortn = SecKeyGetCSSMKey(privKeyRef, &privKey); + if(ortn) { + cssmPerror("SecKeyGetCSSMKey", ortn); + goto done; + } + ortn = SecKeyGetCSPHandle(privKeyRef, &cspHand); + if(ortn) { + cssmPerror("SecKeyGetCSPHandle", ortn); + goto done; + } + + /* CSSM_X509_TYPE_VALUE_PAIR - one pair for now */ + // tvp.type = CSSMOID_EmailAddress; + tvp.type = CSSMOID_CommonName; + tvp.valueType = BER_TAG_PRINTABLE_STRING; + #if FULL_EMAIL_ADDRESS + { + unsigned nameLen = strlen(userName); + tvp.value.Data = (uint8 *)malloc(nameLen + strlen("@mac.com") + 1); + strcpy((char *)tvp.value.Data, userName); + strcpy((char *)tvp.value.Data + nameLen, "@mac.com"); + tvp.value.Length = strlen((char *)tvp.value.Data); + } + #else + tvp.value.Data = (uint8 *)userName; + tvp.value.Length = strlen(userName); + #endif + } + /* set up args for CSSM_TP_SubmitCredRequest */ + if(hostName != NULL) { + tpAuthority.AuthorityCert = NULL; + tpAuthority.AuthorityLocation = &tpNetAddrs; + tpNetAddrs.AddressType = CSSM_ADDR_NAME; + tpNetAddrs.Address.Data = (uint8 *)hostName; + tpNetAddrs.Address.Length = strlen(hostName); + tpAuthPtr = &tpAuthority; + }; + + certReq.version = CSSM_DOT_MAC_TP_REQ_VERSION; + if(!csrInName) { + certReq.cspHand = cspHand; + certReq.clHand = cuClStartup(); + certReq.numTypeValuePairs = 1; + certReq.typeValuePairs = &tvp; + certReq.publicKey = (CSSM_KEY_PTR)pubKey; + certReq.privateKey = (CSSM_KEY_PTR)privKey; + } + if(doNotPost) { + certReq.flags |= CSSM_DOTMAC_TP_DO_NOT_POST; + } + if(csrOutName != NULL) { + certReq.flags |= CSSM_DOTMAC_TP_RETURN_CSR; + } + if(doRenew) { + certReq.flags |= CSSM_DOTMAC_TP_SIGN_RENEW; + } + + reqSet.NumberOfRequests = 1; + reqSet.Requests = &certReq; + + policyField.FieldOid = *opOid; + policyField.FieldValue.Data = NULL; + policyField.FieldValue.Length = 0; + memset(&callerAuth, 0, sizeof(callerAuth)); + callerAuth.Policy.NumberOfPolicyIds = 1; + callerAuth.Policy.PolicyIds = &policyField; + if(!csrInName) { + ortn = SecKeyGetCredentials(privKeyRef, + CSSM_ACL_AUTHORIZATION_SIGN, + kSecCredentialTypeDefault, + const_cast(&callerAuth.CallerCredentials)); + if(ortn) { + cssmPerror("SecKeyGetCredentials", crtn); + goto done; + } + } + + crtn = CSSM_TP_SubmitCredRequest (tpHand, + tpAuthPtr, + CSSM_TP_AUTHORITY_REQUEST_CERTISSUE, // CSSM_TP_AUTHORITY_REQUEST_TYPE + &reqSet, // const CSSM_TP_REQUEST_SET *RequestInput, + &callerAuth, + &estTime, // sint32 *EstimatedTime, + &refId); // CSSM_DATA_PTR ReferenceIdentifier + switch(crtn) { + case CSSM_OK: + case CSSMERR_APPLE_DOTMAC_REQ_QUEUED: + { + /* + * refId should be a cert or RefId + */ + const char *itemType = "Cert"; + const char *statStr = "OK"; + if(crtn != CSSM_OK) { + itemType = "RefId"; + statStr = "Cert"; + } + if((refId.Data == NULL) || (refId.Length == 0)) { + printf("CSSM_TP_SubmitCredRequest returned %s but no data\n", statStr); + break; + } + if(crtn == CSSM_OK) { + printf("...cert acquisition complete\n"); + } + else { + printf("...Cert request QUEUED\n"); + } + if(outFile) { + if(!writeFile(outFile, refId.Data, refId.Length)) { + if(!quiet) { + printf("...%lu bytes of %s written to %s\n", + refId.Length, itemType, outFile); + } + } + else { + printf("***Error writing %s to %s\n", itemType, outFile); + crtn = ioErr; + } + } + else if(verbose) { + if(crtn == CSSM_OK) { + unsigned char *der; + unsigned derLen; + if(pemDecode(refId.Data, refId.Length, &der, &derLen)) { + printf("***Error PEM decoding returned cert\n"); + } + else { + printCert(der, derLen, CSSM_FALSE); + free(der); + } + } + else { + printf("RefId data:\n"); + snDumpText(refId.Data, refId.Length); + } + } + break; + } + case CSSMERR_APPLE_DOTMAC_REQ_REDIRECT: + if((refId.Data == NULL) || (refId.Length == 0)) { + printf("CSSM_TP_SubmitCredRequest returned REDIRECT but no data\n"); + break; + } + printf("...cert acquisition : REDIRECTED to: "); + snDumpText(refId.Data, refId.Length); + printf("\n"); + break; + default: + cssmPerror("CSSM_TP_SubmitCredRequest", crtn); + break; + } + if(csrOutName) { + if((certReq.csr.Data == NULL) || (certReq.csr.Length == 0)) { + printf("***Asked for CSR but didn't get one\n"); + ortn = paramErr; + goto done; + } + if(writeFile(csrOutName, certReq.csr.Data, certReq.csr.Length)) { + printf("***Error writing CSR to %s.\n", csrOutName); + } + else { + printf("...%lu bytes written as CSR to %s\n", certReq.csr.Length, csrOutName); + } + } +done: + /* cleanup */ + CSSM_ModuleDetach(tpHand); + if(certReq.clHand) { + CSSM_ModuleDetach(certReq.clHand); + } + if(kcRef) { + CFRelease(kcRef); + } + if(csrInName) { + free(certReq.csr.Data); + } + if(privKeyRef) { + CFRelease(privKeyRef); + } + if(pubKeyRef) { + CFRelease(pubKeyRef); + } + if(refId.Data) { + cuAppFree(refId.Data, NULL); + } + if(doPause) { + fpurge(stdin); + printf("Pausing for MallocDebug measurement; CR to continue: "); + getchar(); + } + + return ortn; +} diff --git a/SecurityTests/clxutils/dotMacTool/keyPicker.cpp b/SecurityTests/clxutils/dotMacTool/keyPicker.cpp new file mode 100644 index 00000000..d83c8f6c --- /dev/null +++ b/SecurityTests/clxutils/dotMacTool/keyPicker.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2004 Apple Computer, 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@ + */ + +/* + * keyPicker.cpp - select a key pair from a keychain + */ + +#include "keyPicker.h" +#include + +OSStatus keyPicker( + SecKeychainRef kcRef, // NULL means the default list + SecKeyRef *pubKey, // RETURNED + SecKeyRef *privKey) // RETURNED +{ + printf("We'll implement the key picker real soon now.\n"); + return unimpErr; +} diff --git a/SecurityTests/clxutils/dotMacTool/keyPicker.h b/SecurityTests/clxutils/dotMacTool/keyPicker.h new file mode 100644 index 00000000..30a89ea9 --- /dev/null +++ b/SecurityTests/clxutils/dotMacTool/keyPicker.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2004 Apple Computer, 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@ + */ + +/* + * keyPicker.h - select a key pair from a keychain + */ + +#ifndef _KEY_PICKER_H_ +#define _KEY_PICKER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +OSStatus keyPicker( + SecKeychainRef kcRef, // NULL means the default list + SecKeyRef *pubKey, // RETURNED + SecKeyRef *privKey); // RETURNED + + +#ifdef __cplusplus +} +#endif + +#endif /* _KEY_PICKER_H_ */ + diff --git a/SecurityTests/clxutils/dumpasn1.cfg b/SecurityTests/clxutils/dumpasn1.cfg new file mode 100644 index 00000000..5be72adb --- /dev/null +++ b/SecurityTests/clxutils/dumpasn1.cfg @@ -0,0 +1,3634 @@ +# dumpasn1 Object Identifier configuration file, available from +# http://www.cs.auckland.ac.nz/~pgut001/dumpasn1.cfg. This is read by +# dumpasn1.c and is used to display information on Object Identifiers found in +# ASN.1 objects. This is merely a list of things which you might conceivably +# find in use somewhere, and should in no way be taken as a guide to which OIDs +# to use - many of these will never been seen in the wild, or should be shot on +# sight if encountered. +# +# The format of this file is as follows: +# +# - All blank lines and lines beginning with a '#' are ignored. +# - OIDs are described by a set of attributes, of which at least the 'OID' and +# 'Description' must be present. Optional attributes are a 'Comment' and a +# 'Warning' (to indicate that dumpasn1 will display a warning if this OID is +# encountered). +# - Attributes are listed one per line. The first attribute should be an 'OID' +# attribute since this is used to denote the start of a new OID description. +# The other attributes may be given in any order. +# +# See the rest of this file for examples of what an OID description should look +# like. + +# Some unknown X.500 attributes spec from the UK + +OID = 06 09 09 92 26 89 93 F2 2C 01 03 +Comment = Some oddball X.500 attribute collection +Description = rfc822Mailbox (0 9 2342 19200300 1 3) + +# RFC 2247, How to Kludge an FQDN as a DN (or words to that effect) + +OID = 06 0A 09 92 26 89 93 F2 2C 64 01 01 +Comment = Men are from Mars, this OID is from Pluto +Description = domainComponent (0 9 2342 19200300 100 1 25) + +# Certificates Australia + +OID = 06 0A 2A 24 A4 97 A3 53 01 64 01 01 +Comment = Certificates Australia CA +Description = Certificates Australia policyIdentifier (1 2 36 75878867 1 100 1 1) + +# Signet + +OID = 06 09 2A 24 A0 F2 A0 7D 01 01 02 +Comment = Signet CA +Description = Signet personal (1 2 36 68980861 1 1 2) + +OID = 06 09 2A 24 A0 F2 A0 7D 01 01 03 +Comment = Signet CA +Description = Signet business (1 2 36 68980861 1 1 3) + +OID = 06 09 2A 24 A0 F2 A0 7D 01 01 04 +Comment = Signet CA +Description = Signet legal (1 2 36 68980861 1 1 4) + +OID = 06 09 2A 24 A0 F2 A0 7D 01 01 0A +Comment = Signet CA +Description = Signet pilot (1 2 36 68980861 1 1 10) + +OID = 06 09 2A 24 A0 F2 A0 7D 01 01 0B +Comment = Signet CA +Description = Signet intraNet (1 2 36 68980861 1 1 11) + +OID = 06 09 2A 24 A0 F2 A0 7D 01 01 14 +Comment = Signet CA +Description = Signet securityPolicy (1 2 36 68980861 1 1 20) + +# Mitsubishi + +OID = 06 0B 2A 83 08 8C 1A 4B 3D 01 01 01 +Comment = Mitsubishi security algorithm +Description = symmetric-encryption-algorithm (1 2 392 200011 61 1 1 1) + +OID = 06 0C 2A 83 08 8C 9A 4B 3D 01 01 01 01 +Comment = Mitsubishi security algorithm +Description = misty1-cbc (1 2 392 200011 61 1 1 1 1) + +# SEIS + +OID = 06 05 2A 85 70 22 01 +Comment = SEIS Project +Description = seis-cp (1 2 752 34 1) + +OID = 06 06 2A 85 70 22 01 01 +Comment = SEIS Project certificate policies +Description = SEIS high-assurnace certificatePolicy (1 2 752 34 1 1) + +OID = 06 06 2A 85 70 22 01 02 +Comment = SEIS Project certificate policies +Description = SEIS GAK certificatePolicy (1 2 752 34 1 2) + +OID = 06 05 2A 85 70 22 02 +Comment = SEIS Project +Description = SEIS pe (1 2 752 34 2) + +OID = 06 05 2A 85 70 22 03 +Comment = SEIS Project +Description = SEIS at (1 2 752 34 3) + +OID = 06 06 2A 85 70 22 03 01 +Comment = SEIS Project attribute +Description = SEIS at-personalIdentifier (1 2 752 34 3 1) + +# ANSI X9.57 + +OID = 06 06 2A 86 48 CE 38 01 +Comment = ANSI X9.57 +Description = module (1 2 840 10040 1) + +OID = 06 07 2A 86 48 CE 38 01 01 +Comment = ANSI X9.57 module +Description = x9f1-cert-mgmt (1 2 840 10040 1 1) + +OID = 06 06 2A 86 48 CE 38 02 +Comment = ANSI X9.57 +Description = holdinstruction (1 2 840 10040 2) + +OID = 06 07 2A 86 48 CE 38 02 01 +Comment = ANSI X9.57 hold instruction +Description = holdinstruction-none (1 2 840 10040 2 1) + +OID = 06 07 2A 86 48 CE 38 02 02 +Comment = ANSI X9.57 hold instruction +Description = callissuer (1 2 840 10040 2 2) + +OID = 06 07 2A 86 48 CE 38 02 03 +Comment = ANSI X9.57 hold instruction +Description = reject (1 2 840 10040 2 3) + +OID = 06 07 2A 86 48 CE 38 02 04 +Comment = ANSI X9.57 hold instruction +Description = pickupToken (1 2 840 10040 2 4) + +OID = 06 06 2A 86 48 CE 38 03 +Comment = ANSI X9.57 +Description = attribute (1 2 840 10040 3) + +OID = 06 06 2A 86 48 CE 38 03 01 +Comment = ANSI X9.57 attribute +Description = countersignature (1 2 840 10040 3 1) + +OID = 06 06 2A 86 48 CE 38 03 02 +Comment = ANSI X9.57 attribute +Description = attribute-cert (1 2 840 10040 3 2) + +OID = 06 06 2A 86 48 CE 38 04 +Comment = ANSI X9.57 +Description = algorithm (1 2 840 10040 4) + +# this is specified in sm_cms +OID = 06 07 2A 86 48 CE 38 04 01 +Comment = ANSI X9.57 algorithm +Description = dsa (1 2 840 10040 4 1) + +OID = 06 07 2A 86 48 CE 38 04 02 +Comment = ANSI X9.57 algorithm +Description = dsa-match (1 2 840 10040 4 2) + +OID = 06 07 2A 86 48 CE 38 04 03 +Comment = ANSI X9.57 algorithm +Description = dsaWithSha1 (1 2 840 10040 4 3) + +# ANSI X9.62 + +OID = 06 06 2A 86 48 CE 3D 01 +Comment = ANSI X9.62. This OID may also be assigned as ecdsa-with-SHA1 +Description = fieldType (1 2 840 10045 1) + +OID = 06 07 2A 86 48 CE 3D 01 01 +Comment = ANSI X9.62 field type +Description = prime-field (1 2 840 10045 1 1) + +OID = 06 07 2A 86 48 CE 3D 01 02 +Comment = ANSI X9.62 field type +Description = characteristic-two-field (1 2 840 10045 1 2) + +OID = 06 09 2A 86 48 CE 3D 01 02 03 +Comment = ANSI X9.62 field type +Description = characteristic-two-basis (1 2 840 10045 1 2 3) + +OID = 06 0A 2A 86 48 CE 3D 01 02 03 01 +Comment = ANSI X9.62 field basis +Description = qnBasis (1 2 840 10045 1 2 3 1) + +OID = 06 0A 2A 86 48 CE 3D 01 02 03 02 +Comment = ANSI X9.62 field basis +Description = tpBasis (1 2 840 10045 1 2 3 2) + +OID = 06 0A 2A 86 48 CE 3D 01 02 03 03 +Comment = ANSI X9.62 field basis +Description = ppBasis (1 2 840 10045 1 2 3 3) + +OID = 06 07 2A 86 48 CE 3D 01 02 +Comment = ANSI X9.62 +Description = public-key-type (1 2 840 10045 1 2) + +# this seems bogus - (1 2 840 10045 2 1) is used now +OID = 06 08 2A 86 48 CE 3D 01 02 01 +Comment = ANSI X9.62 public key type +Description = ecPublicKey (1 2 840 10045 1 2 1) + +# The definition for the following OID is somewhat confused, and is given as +# keyType, publicKeyType, and public-key-type, all within 4 lines of text. +# ecPublicKey is defined using the ID publicKeyType, so this is what's used +# here. +OID = 06 06 2A 86 48 CE 3D 02 +Comment = ANSI X9.62 +Description = publicKeyType (1 2 840 10045 2) + +OID = 06 07 2A 86 48 CE 3D 02 01 +Comment = ANSI X9.62 public key type +Description = ecPublicKey (1 2 840 10045 2 1) + +# ANSI X9.42 + +OID = 06 07 2A 86 48 CE 3E 02 +Comment = ANSI X9.42 +Description = number-type (1 2 840 10046 2) + +OID = 06 07 2A 86 48 CE 3E 02 01 +Comment = ANSI X9.42 number-type +Description = dhPublicNumber (1 2 840 10046 2 1) + +# Nortel Secure Networks/Entrust + +OID = 06 07 2A 86 48 86 F6 7D 07 +Description = nsn (1 2 840 113533 7) + +OID = 06 08 2A 86 48 86 F6 7D 07 41 +Description = nsn-ce (1 2 840 113533 7 65) + +OID = 06 09 2A 86 48 86 F6 7D 07 41 00 +Comment = Nortel Secure Networks ce (1 2 840 113533 7 65) +Description = entrustVersInfo (1 2 840 113533 7 65 0) + +OID = 06 08 2A 86 48 86 F6 7D 07 42 +Description = nsn-alg (1 2 840 113533 7 66) + +OID = 06 09 2A 86 48 86 F6 7D 07 42 03 +Comment = Nortel Secure Networks alg (1 2 840 113533 7 66) +Description = cast3CBC (1 2 840 113533 7 66 3) + +OID = 06 09 2A 86 48 86 F6 7D 07 42 0A +Comment = Nortel Secure Networks alg (1 2 840 113533 7 66) +Description = cast5CBC (1 2 840 113533 7 66 10) + +OID = 06 09 2A 86 48 86 F6 7D 07 42 0B +Comment = Nortel Secure Networks alg (1 2 840 113533 7 66) +Description = cast5MAC (1 2 840 113533 7 66 11) + +OID = 06 09 2A 86 48 86 F6 7D 07 42 0C +Comment = Nortel Secure Networks alg (1 2 840 113533 7 66) +Description = pbeWithMD5AndCAST5-CBC (1 2 840 113533 7 66 12) + +OID = 06 09 2A 86 48 86 F6 7D 07 42 0D +Comment = Nortel Secure Networks alg (1 2 840 113533 7 66) +Description = passwordBasedMac (1 2 840 113533 7 66 13) + +OID = 06 08 2A 86 48 86 F6 7D 07 43 +Description = nsn-oc (1 2 840 113533 7 67) + +OID = 06 09 2A 86 48 86 F6 7D 07 43 0C +Comment = Nortel Secure Networks oc (1 2 840 113533 7 67) +Description = entrustUser (1 2 840 113533 7 67 0) + +OID = 06 08 2A 86 48 86 F6 7D 07 44 +Description = nsn-at (1 2 840 113533 7 68) + +OID = 06 09 2A 86 48 86 F6 7D 07 44 00 +Comment = Nortel Secure Networks at (1 2 840 113533 7 68) +Description = entrustCAInfo (1 2 840 113533 7 68 0) + +OID = 06 09 2A 86 48 86 F6 7D 07 44 0A +Comment = Nortel Secure Networks at (1 2 840 113533 7 68) +Description = attributeCertificate (1 2 840 113533 7 68 10) + +# PKCS #1 + +OID = 06 08 2A 86 48 86 F7 0D 01 01 +Description = pkcs-1 (1 2 840 113549 1 1) + +OID = 06 09 2A 86 48 86 F7 0D 01 01 01 +Comment = PKCS #1 +Description = rsaEncryption (1 2 840 113549 1 1 1) + +OID = 06 09 2A 86 48 86 F7 0D 01 01 02 +Comment = PKCS #1 +Description = md2withRSAEncryption (1 2 840 113549 1 1 2) + +OID = 06 09 2A 86 48 86 F7 0D 01 01 03 +Comment = PKCS #1 +Description = md4withRSAEncryption (1 2 840 113549 1 1 3) + +OID = 06 09 2A 86 48 86 F7 0D 01 01 04 +Comment = PKCS #1 +Description = md5withRSAEncryption (1 2 840 113549 1 1 4) + +OID = 06 09 2A 86 48 86 F7 0D 01 01 05 +Comment = PKCS #1 +Description = sha1withRSAEncryption (1 2 840 113549 1 1 5) + +# There is some confusion over the identity of the following OID. The OAEP +# one is more recent, but independant vendors have already used the RIPEMD +# one, however it's likely that SET will be a bigger hammer so we report it +# as that. +OID = 06 09 2A 86 48 86 F7 0D 01 01 06 +Comment = PKCS #1. This OID may also be assigned as ripemd160WithRSAEncryption +Description = rsaOAEPEncryptionSET (1 2 840 113549 1 1 6) +# ripemd160WithRSAEncryption (1 2 840 113549 1 1 6) + +# PKCS #3 + +OID = 06 08 2A 86 48 86 F7 0D 01 03 +Description = pkcs-3 (1 2 840 113549 1 3) + +OID = 06 09 2A 86 48 86 F7 0D 01 03 01 +Comment = PKCS #3 +Description = dhKeyAgreement (1 2 840 113549 1 3 1) + +# PKCS #5 + +OID = 06 09 2A 86 48 86 F7 0D 01 05 +Description = pkcs-5 (1 2 840 113549 1 5) + +OID = 06 09 2A 86 48 86 F7 0D 01 05 01 +Comment = PKCS #5 +Description = pbeWithMD2AndDES-CBC (1 2 840 113549 1 5 1) + +OID = 06 09 2A 86 48 86 F7 0D 01 05 03 +Comment = PKCS #5 +Description = pbeWithMD5AndDES-CBC (1 2 840 113549 1 5 3) + +OID = 06 09 2A 86 48 86 F7 0D 01 05 04 +Comment = PKCS #5 +Description = pbeWithMD2AndRC2-CBC (1 2 840 113549 1 5 4) + +OID = 06 09 2A 86 48 86 F7 0D 01 05 06 +Comment = PKCS #5 +Description = pbeWithMD5AndRC2-CBC (1 2 840 113549 1 5 6) + +OID = 06 09 2A 86 48 86 F7 0D 01 05 09 +Comment = PKCS #5, used in BSAFE only +Description = pbeWithMD5AndXOR (1 2 840 113549 1 5 9) +Warning + +OID = 06 09 2A 86 48 86 F7 0D 01 05 0A +Comment = PKCS #5 +Description = pbeWithSHA1AndDES-CBC (1 2 840 113549 1 5 10) + +OID = 06 09 2A 86 48 86 F7 0D 01 05 0B +Comment = PKCS #5 +Description = pbeWithSHA1AndRC2-CBC (1 2 840 113549 1 5 11) + +OID = 06 09 2A 86 48 86 F7 0D 01 05 0C +Comment = PKCS #5 +Description = id-PBKDF2 (1 2 840 113549 1 5 12) + +OID = 06 09 2A 86 48 86 F7 0D 01 05 0D +Comment = PKCS #5 +Description = id-PBES2 (1 2 840 113549 1 5 13) + +OID = 06 09 2A 86 48 86 F7 0D 01 05 0E +Comment = PKCS #5 +Description = id-PBMAC1 (1 2 840 113549 1 5 14) + +# PKCS #7 + +OID = 06 09 2A 86 48 86 F7 0D 01 07 +Description = pkcs-7 (1 2 840 113549 1 7) + +OID = 06 09 2A 86 48 86 F7 0D 01 07 01 +Comment = PKCS #7 +Description = data (1 2 840 113549 1 7 1) + +OID = 06 09 2A 86 48 86 F7 0D 01 07 02 +Comment = PKCS #7 +Description = signedData (1 2 840 113549 1 7 2) + +OID = 06 09 2A 86 48 86 F7 0D 01 07 03 +Comment = PKCS #7 +Description = envelopedData (1 2 840 113549 1 7 3) + +OID = 06 09 2A 86 48 86 F7 0D 01 07 04 +Comment = PKCS #7 +Description = signedAndEnvelopedData (1 2 840 113549 1 7 4) + +OID = 06 09 2A 86 48 86 F7 0D 01 07 05 +Comment = PKCS #7 +Description = digestedData (1 2 840 113549 1 7 5) + +OID = 06 09 2A 86 48 86 F7 0D 01 07 06 +Comment = PKCS #7 +Description = encryptedData (1 2 840 113549 1 7 6) + +OID = 06 09 2A 86 48 86 F7 0D 01 07 07 +Comment = PKCS #7 experimental +Description = dataWithAttributes (1 2 840 113549 1 7 7) +Warning + +OID = 06 09 2A 86 48 86 F7 0D 01 07 08 +Comment = PKCS #7 experimental +Description = encryptedPrivateKeyInfo (1 2 840 113549 1 7 8) +Warning + +# PKCS #9 + +OID = 06 09 2A 86 48 86 F7 0D 01 09 +Description = pkcs-9 (1 2 840 113549 1 9) + +OID = 06 09 2A 86 48 86 F7 0D 01 09 01 +Comment = PKCS #9 (1 2 840 113549 1 9). Deprecated, use an altName extension instead +Description = emailAddress (1 2 840 113549 1 9 1) + +OID = 06 09 2A 86 48 86 F7 0D 01 09 02 +Comment = PKCS #9 (1 2 840 113549 1 9) +Description = unstructuredName (1 2 840 113549 1 9 2) + +OID = 06 09 2A 86 48 86 F7 0D 01 09 03 +Comment = PKCS #9 (1 2 840 113549 1 9) +Description = contentType (1 2 840 113549 1 9 3) + +OID = 06 09 2A 86 48 86 F7 0D 01 09 04 +Comment = PKCS #9 (1 2 840 113549 1 9) +Description = messageDigest (1 2 840 113549 1 9 4) + +OID = 06 09 2A 86 48 86 F7 0D 01 09 05 +Comment = PKCS #9 (1 2 840 113549 1 9) +Description = signingTime (1 2 840 113549 1 9 5) + +OID = 06 09 2A 86 48 86 F7 0D 01 09 06 +Comment = PKCS #9 (1 2 840 113549 1 9) +Description = countersignature (1 2 840 113549 1 9 6) + +OID = 06 09 2A 86 48 86 F7 0D 01 09 07 +Comment = PKCS #9 (1 2 840 113549 1 9) +Description = challengePassword (1 2 840 113549 1 9 7) + +OID = 06 09 2A 86 48 86 F7 0D 01 09 08 +Comment = PKCS #9 (1 2 840 113549 1 9) +Description = unstructuredAddress (1 2 840 113549 1 9 8) + +OID = 06 09 2A 86 48 86 F7 0D 01 09 09 +Comment = PKCS #9 (1 2 840 113549 1 9) +Description = extendedCertificateAttributes (1 2 840 113549 1 9 9) + +OID = 06 09 2A 86 48 86 F7 0D 01 09 0A +Comment = PKCS #9 (1 2 840 113549 1 9) experimental +Description = issuerAndSerialNumber (1 2 840 113549 1 9 10) +Warning + +OID = 06 09 2A 86 48 86 F7 0D 01 09 0B +Comment = PKCS #9 (1 2 840 113549 1 9) experimental +Description = passwordCheck (1 2 840 113549 1 9 11) +Warning + +OID = 06 09 2A 86 48 86 F7 0D 01 09 0C +Comment = PKCS #9 (1 2 840 113549 1 9) experimental +Description = publicKey (1 2 840 113549 1 9 12) +Warning + +OID = 06 09 2A 86 48 86 F7 0D 01 09 0D +Comment = PKCS #9 (1 2 840 113549 1 9) experimental +Description = signingDescription (1 2 840 113549 1 9 13) +Warning + +OID = 06 09 2A 86 48 86 F7 0D 01 09 0E +Comment = PKCS #9 (1 2 840 113549 1 9) experimental +Description = extensionReq (1 2 840 113549 1 9 14) + +# PKCS #9 for use with S/MIME + +OID = 06 09 2A 86 48 86 F7 0D 01 09 0F +Comment = PKCS #9 (1 2 840 113549 1 9). This OID was formerly assigned as symmetricCapabilities, then reassigned as SMIMECapabilities, then renamed to the current name +Description = sMIMECapabilities (1 2 840 113549 1 9 15) + +OID = 06 0A 2A 86 48 86 F7 0D 01 09 0F 01 +Comment = sMIMECapabilities (1 2 840 113549 1 9 15) +Description = preferSignedData (1 2 840 113549 1 9 15 1) + +OID = 06 0A 2A 86 48 86 F7 0D 01 09 0F 02 +Comment = sMIMECapabilities (1 2 840 113549 1 9 15) +Description = canNotDecryptAny (1 2 840 113549 1 9 15 2) + +OID = 06 0A 2A 86 48 86 F7 0D 01 09 0F 03 +Comment = sMIMECapabilities (1 2 840 113549 1 9 15). Deprecated, use (1 2 840 113549 1 9 16 2 1) instead +Description = receiptRequest (1 2 840 113549 1 9 15 3) +Warning + +OID = 06 0A 2A 86 48 86 F7 0D 01 09 0F 04 +Comment = sMIMECapabilities (1 2 840 113549 1 9 15). Deprecated, use (1 2 840 113549 1 9 16 1 1) instead +Description = receipt (1 2 840 113549 1 9 15 4) +Warning + +OID = 06 0A 2A 86 48 86 F7 0D 01 09 0F 05 +Comment = sMIMECapabilities (1 2 840 113549 1 9 15). Deprecated, use (1 2 840 113549 1 9 16 2 4) instead +Description = contentHints (1 2 840 113549 1 9 15 5) +Warning + +OID = 06 0A 2A 86 48 86 F7 0D 01 09 0F 06 +Comment = sMIMECapabilities (1 2 840 113549 1 9 15). Deprecated, use (1 2 840 113549 1 9 16 2 3) instead +Description = mlExpansionHistory (1 2 840 113549 1 9 15 6) +Warning + +OID = 06 09 2A 86 48 86 F7 0D 01 09 10 +Comment = PKCS #9 (1 2 840 113549 1 9) +Description = id-sMIME (1 2 840 113549 1 9 16) + +OID = 06 0A 2A 86 48 86 F7 0D 01 09 10 00 +Comment = id-sMIME (1 2 840 113549 1 9 16) +Description = id-mod (1 2 840 113549 1 9 16 0) + +OID = 06 0B 2A 86 48 86 F7 0D 01 09 10 00 01 +Comment = S/MIME Modules (1 2 840 113549 1 9 16 0) +Description = id-mod-cms (1 2 840 113549 1 9 16 0 1) + +OID = 06 0B 2A 86 48 86 F7 0D 01 09 10 00 02 +Comment = S/MIME Modules (1 2 840 113549 1 9 16 0) +Description = id-mod-ess (1 2 840 113549 1 9 16 0 2) + +OID = 06 0A 2A 86 48 86 F7 0D 01 09 10 01 +Comment = id-sMIME (1 2 840 113549 1 9 16) +Description = id-ct (1 2 840 113549 1 9 16 1) + +OID = 06 0B 2A 86 48 86 F7 0D 01 09 10 01 01 +Comment = S/MIME Content Types (1 2 840 113549 1 9 16 1) +Description = id-ct-receipt (1 2 840 113549 1 9 16 1 1) + +OID = 06 0A 2A 86 48 86 F7 0D 01 09 10 02 +Comment = id-sMIME (1 2 840 113549 1 9 16) +Description = id-aa (1 2 840 113549 1 9 16 2) + +OID = 06 0B 2A 86 48 86 F7 0D 01 09 10 02 01 +Comment = S/MIME Authenticated Attributes (1 2 840 113549 1 9 16 2) +Description = id-aa-receiptRequest (1 2 840 113549 1 9 16 2 1) + +OID = 06 0B 2A 86 48 86 F7 0D 01 09 10 02 02 +Comment = S/MIME Authenticated Attributes (1 2 840 113549 1 9 16 2) +Description = id-aa-securityLabel (1 2 840 113549 1 9 16 2 2) + +OID = 06 0B 2A 86 48 86 F7 0D 01 09 10 02 03 +Comment = S/MIME Authenticated Attributes (1 2 840 113549 1 9 16 2) +Description = id-aa-mlExpandHistory (1 2 840 113549 1 9 16 2 3) + +OID = 06 0B 2A 86 48 86 F7 0D 01 09 10 02 04 +Comment = S/MIME Authenticated Attributes (1 2 840 113549 1 9 16 2) +Description = id-aa-contentHint (1 2 840 113549 1 9 16 2 4) + +OID = 06 0B 2A 86 48 86 F7 0D 01 09 10 02 05 +Comment = S/MIME Authenticated Attributes (1 2 840 113549 1 9 16 2) +Description = id-aa-msgSigDigest (1 2 840 113549 1 9 16 2 5) + +OID = 06 0B 2A 86 48 86 F7 0D 01 09 10 02 07 +Comment = S/MIME Authenticated Attributes (1 2 840 113549 1 9 16 2) +Description = id-aa-contentIdentifier (1 2 840 113549 1 9 16 2 7) + +OID = 06 0B 2A 86 48 86 F7 0D 01 09 10 02 08 +Comment = S/MIME Authenticated Attributes (1 2 840 113549 1 9 16 2) +Description = id-aa-macValue (1 2 840 113549 1 9 16 2 8) + +OID = 06 0B 2A 86 48 86 F7 0D 01 09 10 02 09 +Comment = S/MIME Authenticated Attributes (1 2 840 113549 1 9 16 2) +Description = id-aa-equivalentLabels (1 2 840 113549 1 9 16 2 9) + +OID = 06 0B 2A 86 48 86 F7 0D 01 09 10 02 0A +Comment = S/MIME Authenticated Attributes (1 2 840 113549 1 9 16 2) +Description = id-aa-contentReference (1 2 840 113549 1 9 16 2 10) + +# PKCS #9 for use with PKCS #12 + +OID = 06 09 2A 86 48 86 F7 0D 01 09 14 +Comment = PKCS #9 (1 2 840 113549 1 9) +Description = friendlyName (for PKCS #12) (1 2 840 113549 1 9 20) + +OID = 06 09 2A 86 48 86 F7 0D 01 09 15 +Comment = PKCS #9 (1 2 840 113549 1 9) +Description = localKeyID (for PKCS #12) (1 2 840 113549 1 9 21) + +OID = 06 09 2A 86 48 86 F7 0D 01 09 16 +Comment = PKCS #9 (1 2 840 113549 1 9) +Description = certTypes (for PKCS #12) (1 2 840 113549 1 9 22) + +OID = 06 0A 2A 86 48 86 F7 0D 01 09 16 01 +Comment = PKCS #9 (1 2 840 113549 1 9) +Description = x509Certificate (for PKCS #12) (1 2 840 113549 1 9 22 1) + +OID = 06 0A 2A 86 48 86 F7 0D 01 09 16 02 +Comment = PKCS #9 (1 2 840 113549 1 9) +Description = sdsiCertificate (for PKCS #12) (1 2 840 113549 1 9 22 2) + +OID = 06 09 2A 86 48 86 F7 0D 01 09 17 +Comment = PKCS #9 (1 2 840 113549 1 9) +Description = crlTypes (for PKCS #12) (1 2 840 113549 1 9 23) + +OID = 06 0A 2A 86 48 86 F7 0D 01 09 17 01 +Comment = PKCS #9 (1 2 840 113549 1 9) +Description = x509Crl (for PKCS #12) (1 2 840 113549 1 9 23 1) + +# PKCS #12. Note that current PKCS #12 implementations tend to be strange and +# peculiar, with implementors misusing OIDs or basing their work on earlier PFX +# drafts or defining their own odd OIDs. In addition the PFX/PKCS #12 spec +# itself is full of errors and inconsistencies, and a number of OIDs have been +# redefined in different drafts (often multiple times), which doesn't make the +# implementors job any easier. + +OID = 06 08 2A 86 48 86 F7 0D 01 0C +Description = pkcs-12 (1 2 840 113549 1 12) + +OID = 06 09 2A 86 48 86 F7 0D 01 0C 01 +Comment = This OID was formerly assigned as PKCS #12 modeID +Description = pkcs-12-PbeIds (1 2 840 113549 1 12 1) + +OID = 06 0A 2A 86 48 86 F7 0D 01 0C 01 01 +Comment = PKCS #12 PbeIds (1 2 840 113549 1 12 1). This OID was formerly assigned as pkcs-12-OfflineTransportMode +Description = pbeWithSHAAnd128BitRC4 (1 2 840 113549 1 12 1 1) + +OID = 06 0A 2A 86 48 86 F7 0D 01 0C 01 02 +Comment = PKCS #12 PbeIds (1 2 840 113549 1 12 2). This OID was formerly assigned as pkcs-12-OnlineTransportMode +Description = pbeWithSHAAnd40BitRC4 (1 2 840 113549 1 12 1 2) + +OID = 06 0A 2A 86 48 86 F7 0D 01 0C 01 03 +Comment = PKCS #12 PbeIds (1 2 840 113549 1 12 3) +Description = pbeWithSHAAnd3-KeyTripleDES-CBC (1 2 840 113549 1 12 1 3) + +OID = 06 0A 2A 86 48 86 F7 0D 01 0C 01 04 +Comment = PKCS #12 PbeIds (1 2 840 113549 1 12 3) +Description = pbeWithSHAAnd2-KeyTripleDES-CBC (1 2 840 113549 1 12 1 4) + +OID = 06 0A 2A 86 48 86 F7 0D 01 0C 01 05 +Comment = PKCS #12 PbeIds (1 2 840 113549 1 12 3) +Description = pbeWithSHAAnd128BitRC2-CBC (1 2 840 113549 1 12 1 5) + +OID = 06 0A 2A 86 48 86 F7 0D 01 0C 01 06 +Comment = PKCS #12 PbeIds (1 2 840 113549 1 12 3) +Description = pbeWithSHAAnd40BitRC2-CBC (1 2 840 113549 1 12 1 6) + +OID = 06 09 2A 86 48 86 F7 0D 01 0C 02 +Comment = Deprecated +Description = pkcs-12-ESPVKID (1 2 840 113549 1 12 2) +Warning + +OID = 06 0A 2A 86 48 86 F7 0D 01 0C 02 01 +Comment = PKCS #12 ESPVKID (1 2 840 113549 1 12 2). Deprecated, use (1 2 840 113549 1 12 3 5) instead +Description = pkcs-12-PKCS8KeyShrouding (1 2 840 113549 1 12 2 1) +Warning + +# The following appear to have been redefined yet again at 12 10 in the latest +# PKCS #12 spec. +OID = 06 09 2A 86 48 86 F7 0D 01 0C 03 +Description = pkcs-12-BagIds (1 2 840 113549 1 12 3) + +OID = 06 0A 2A 86 48 86 F7 0D 01 0C 03 01 +Comment = PKCS #12 BagIds (1 2 840 113549 1 12 3) +Description = pkcs-12-keyBagId (1 2 840 113549 1 12 3 1) + +OID = 06 0A 2A 86 48 86 F7 0D 01 0C 03 02 +Comment = PKCS #12 BagIds (1 2 840 113549 1 12 3) +Description = pkcs-12-certAndCRLBagId (1 2 840 113549 1 12 3 2) + +OID = 06 0A 2A 86 48 86 F7 0D 01 0C 03 03 +Comment = PKCS #12 BagIds (1 2 840 113549 1 12 3) +Description = pkcs-12-secretBagId (1 2 840 113549 1 12 3 3) + +OID = 06 0A 2A 86 48 86 F7 0D 01 0C 03 04 +Comment = PKCS #12 BagIds (1 2 840 113549 1 12 3) +Description = pkcs-12-safeContentsId (1 2 840 113549 1 12 3 4) + +OID = 06 0A 2A 86 48 86 F7 0D 01 0C 03 05 +Comment = PKCS #12 BagIds (1 2 840 113549 1 12 3) +Description = pkcs-12-pkcs-8ShroudedKeyBagId (1 2 840 113549 1 12 3 5) + +OID = 06 09 2A 86 48 86 F7 0D 01 0C 04 +Comment = Deprecated +Description = pkcs-12-CertBagID (1 2 840 113549 1 12 4) +Warning + +OID = 06 0A 2A 86 48 86 F7 0D 01 0C 04 01 +Comment = PKCS #12 CertBagID (1 2 840 113549 1 12 4). This OID was formerly assigned as pkcs-12-X509CertCRLBag +Description = pkcs-12-X509CertCRLBagID (1 2 840 113549 1 12 4 1) + +OID = 06 0A 2A 86 48 86 F7 0D 01 0C 04 02 +Comment = PKCS #12 CertBagID (1 2 840 113549 1 12 4). This OID was formerly assigned as pkcs-12-SDSICertBag +Description = pkcs-12-SDSICertBagID (1 2 840 113549 1 12 4 2) + +# The following are from PFX. The ... 5 1 values have been reassigned to OIDs +# with incompatible algorithms at ... 1, the 5 2 values seem to have vanished. +OID = 06 09 2A 86 48 86 F7 0D 01 0C 05 +Description = pkcs-12-OID (1 2 840 113549 1 12 5) +Warning + +OID = 06 0A 2A 86 48 86 F7 0D 01 0C 05 01 +Comment = PKCS #12 OID (1 2 840 113549 1 12 5). Deprecated, use the partially compatible (1 2 840 113549 1 12 1) OIDs instead +Description = pkcs-12-PBEID (1 2 840 113549 1 12 5 1) +Warning + +OID = 06 0B 2A 86 48 86 F7 0D 01 0C 05 01 01 +Comment = PKCS #12 OID PBEID (1 2 840 113549 1 12 5 1). Deprecated, use (1 2 840 113549 1 12 1 1) instead +Description = pkcs-12-PBEWithSha1And128BitRC4 (1 2 840 113549 1 12 5 1 1) +Warning + +OID = 06 0B 2A 86 48 86 F7 0D 01 0C 05 01 02 +Comment = PKCS #12 OID PBEID (1 2 840 113549 1 12 5 1). Deprecated, use (1 2 840 113549 1 12 1 2) instead +Description = pkcs-12-PBEWithSha1And40BitRC4 (1 2 840 113549 1 12 5 1 2) +Warning + +OID = 06 0B 2A 86 48 86 F7 0D 01 0C 05 01 03 +Comment = PKCS #12 OID PBEID (1 2 840 113549 1 12 5 1). Deprecated, use the incompatible but similar (1 2 840 113549 1 12 1 3) or (1 2 840 113549 1 12 1 4) instead +Description = pkcs-12-PBEWithSha1AndTripleDESCBC (1 2 840 113549 1 12 5 1 3) +Warning + +OID = 06 0B 2A 86 48 86 F7 0D 01 0C 05 01 04 +Comment = PKCS #12 OID PBEID (1 2 840 113549 1 12 5 1). Deprecated, use (1 2 840 113549 1 12 1 5) instead +Description = pkcs-12-PBEWithSha1And128BitRC2CBC (1 2 840 113549 1 12 5 1 4) +Warning + +OID = 06 0B 2A 86 48 86 F7 0D 01 0C 05 01 05 +Comment = PKCS #12 OID PBEID (1 2 840 113549 1 12 5 1). Deprecated, use (1 2 840 113549 1 12 1 6) instead +Description = pkcs-12-PBEWithSha1And40BitRC2CBC (1 2 840 113549 1 12 5 1 5) +Warning + +OID = 06 0B 2A 86 48 86 F7 0D 01 0C 05 01 06 +Comment = PKCS #12 OID PBEID (1 2 840 113549 1 12 5 1). Deprecated, use the incompatible but similar (1 2 840 113549 1 12 1 1) or (1 2 840 113549 1 12 1 2) instead +Description = pkcs-12-PBEWithSha1AndRC4 (1 2 840 113549 1 12 5 1 6) +Warning + +OID = 06 0B 2A 86 48 86 F7 0D 01 0C 05 01 07 +Comment = PKCS #12 OID PBEID (1 2 840 113549 1 12 5 1). Deprecated, use the incompatible but similar (1 2 840 113549 1 12 1 5) or (1 2 840 113549 1 12 1 6) instead +Description = pkcs-12-PBEWithSha1AndRC2CBC (1 2 840 113549 1 12 5 1 7) +Warning + +OID = 06 0A 2A 86 48 86 F7 0D 01 0C 05 02 +Description = pkcs-12-EnvelopingID (1 2 840 113549 1 12 5 2). Deprecated, use the conventional PKCS #1 OIDs instead +Warning + +OID = 06 0B 2A 86 48 86 F7 0D 01 0C 05 02 01 +Comment = PKCS #12 OID EnvelopingID (1 2 840 113549 1 12 5 2). Deprecated, use the conventional PKCS #1 OIDs instead +Description = pkcs-12-RSAEncryptionWith128BitRC4 (1 2 840 113549 1 12 5 2 1) +Warning + +OID = 06 0B 2A 86 48 86 F7 0D 01 0C 05 02 02 +Comment = PKCS #12 OID EnvelopingID (1 2 840 113549 1 12 5 2). Deprecated, use the conventional PKCS #1 OIDs instead +Description = pkcs-12-RSAEncryptionWith40BitRC4 (1 2 840 113549 1 12 5 2 2) +Warning + +OID = 06 0B 2A 86 48 86 F7 0D 01 0C 05 02 03 +Comment = PKCS #12 OID EnvelopingID (1 2 840 113549 1 12 5 2). Deprecated, use the conventional PKCS #1 OIDs instead +Description = pkcs-12-RSAEncryptionWithTripleDES (1 2 840 113549 1 12 5 2 3) +Warning + +OID = 06 0A 2A 86 48 86 F7 0D 01 0C 05 03 +Description = pkcs-12-SignatureID (1 2 840 113549 1 12 5 3). Deprecated, use the conventional PKCS #1 OIDs instead +Warning + +OID = 06 0B 2A 86 48 86 F7 0D 01 0C 05 03 01 +Comment = PKCS #12 OID SignatureID (1 2 840 113549 1 12 5 3). Deprecated, use the conventional PKCS #1 OIDs instead +Description = pkcs-12-RSASignatureWithSHA1Digest (1 2 840 113549 1 12 5 3 1) +Warning + +# Yet *another* redefinition of the PKCS #12 "bag" ID's, now in a different +# order than the last redefinition at ... 12 3. +OID = 06 09 2A 86 48 86 F7 0D 01 0C 0A +Description = pkcs-12Version1 (1 2 840 113549 1 12 10) + +OID = 06 0A 2A 86 48 86 F7 0D 01 0C 0A 01 +Description = pkcs-12BadIds (1 2 840 113549 1 12 10 1) + +OID = 06 0B 2A 86 48 86 F7 0D 01 0C 0A 01 01 +Comment = PKCS #12 BagIds (1 2 840 113549 1 12 10 1) +Description = pkcs-12-keyBag (1 2 840 113549 1 12 10 1 1) + +OID = 06 0B 2A 86 48 86 F7 0D 01 0C 0A 01 02 +Comment = PKCS #12 BagIds (1 2 840 113549 1 12 10 1) +Description = pkcs-12-pkcs-8ShroudedKeyBag (1 2 840 113549 1 12 10 1 2) + +OID = 06 0B 2A 86 48 86 F7 0D 01 0C 0A 01 03 +Comment = PKCS #12 BagIds (1 2 840 113549 1 12 10 1) +Description = pkcs-12-certBag (1 2 840 113549 1 12 10 1 3) + +OID = 06 0B 2A 86 48 86 F7 0D 01 0C 0A 01 04 +Comment = PKCS #12 BagIds (1 2 840 113549 1 12 10 1) +Description = pkcs-12-crlBag (1 2 840 113549 1 12 10 1 4) + +OID = 06 0B 2A 86 48 86 F7 0D 01 0C 0A 01 05 +Comment = PKCS #12 BagIds (1 2 840 113549 1 12 10 1) +Description = pkcs-12-secretBag (1 2 840 113549 1 12 10 1 5) + +OID = 06 0B 2A 86 48 86 F7 0D 01 0C 0A 01 06 +Comment = PKCS #12 BagIds (1 2 840 113549 1 12 10 1) +Description = pkcs-12-safeContentsBag (1 2 840 113549 1 12 10 1 6) + +# RSADSI digest algorithms + +OID = 06 08 2A 86 48 86 F7 0D 02 +Description = digestAlgorithm (1 2 840 113549 2) + +OID = 06 08 2A 86 48 86 F7 0D 02 02 +Comment = RSADSI digestAlgorithm (1 2 840 113549 2) +Description = md2 (1 2 840 113549 2 2) + +OID = 06 08 2A 86 48 86 F7 0D 02 04 +Comment = RSADSI digestAlgorithm (1 2 840 113549 2) +Description = md4 (1 2 840 113549 2 4) + +OID = 06 08 2A 86 48 86 F7 0D 02 05 +Comment = RSADSI digestAlgorithm (1 2 840 113549 2) +Description = md5 (1 2 840 113549 2 5) + +# RSADSI encryption algorithms + +OID = 06 08 2A 86 48 86 F7 0D 03 +Description = encryptionAlgorithm (1 2 840 113549 3) + +OID = 06 08 2A 86 48 86 F7 0D 03 02 +Comment = RSADSI encryptionAlgorithm (1 2 840 113549 3) +Description = rc2CBC (1 2 840 113549 3 2) + +OID = 06 08 2A 86 48 86 F7 0D 03 03 +Comment = RSADSI encryptionAlgorithm (1 2 840 113549 3) +Description = rc2ECB (1 2 840 113549 3 3) + +OID = 06 08 2A 86 48 86 F7 0D 03 04 +Comment = RSADSI encryptionAlgorithm (1 2 840 113549 3) +Description = rc4 (1 2 840 113549 3 4) + +OID = 06 08 2A 86 48 86 F7 0D 03 05 +Comment = RSADSI encryptionAlgorithm (1 2 840 113549 3) +Description = rc4WithMAC (1 2 840 113549 3 5) + +OID = 06 08 2A 86 48 86 F7 0D 03 06 +Comment = RSADSI encryptionAlgorithm (1 2 840 113549 3) +Description = desx-CBC (1 2 840 113549 3 6) + +OID = 06 08 2A 86 48 86 F7 0D 03 07 +Comment = RSADSI encryptionAlgorithm (1 2 840 113549 3) +Description = des-EDE3-CBC (1 2 840 113549 3 7) + +OID = 06 08 2A 86 48 86 F7 0D 03 08 +Comment = RSADSI encryptionAlgorithm (1 2 840 113549 3) +Description = rc5CBC (1 2 840 113549 3 8) + +OID = 06 08 2A 86 48 86 F7 0D 03 09 +Comment = RSADSI encryptionAlgorithm (1 2 840 113549 3) +Description = rc5-CBCPad (1 2 840 113549 3 9) + +OID = 06 08 2A 86 48 86 F7 0D 03 0A +Comment = RSADSI encryptionAlgorithm (1 2 840 113549 3). Formerly called CDMFCBCPad +Description = desCDMF (1 2 840 113549 3 10) + +# Ascom Systech + +OID = 06 0A 2B 06 01 04 01 81 3C 07 01 01 +Comment = Ascom Systech +Description = ascom (1 3 6 1 4 1 188 7 1 1) + +OID = 06 0B 2B 06 01 04 01 81 3C 07 01 01 01 +Comment = Ascom Systech +Description = ideaECB (1 3 6 1 4 1 188 7 1 1 1) + +# Microsoft + +OID = 06 08 2A 86 48 86 F7 14 04 03 +Comment = Microsoft +Description = microsoftExcel (1 2 840 113556 4 3) + +OID = 06 08 2A 86 48 86 F7 14 04 04 +Comment = Microsoft +Description = titledWithOID (1 2 840 113556 4 4) + +OID = 06 08 2A 86 48 86 F7 14 04 05 +Comment = Microsoft +Description = microsoftPowerPoint (1 2 840 113556 4 5) + +OID = 06 0A 2B 06 01 04 01 82 37 02 01 04 +Comment = Microsoft code signing +Description = spcIndirectDataContext (1 3 6 1 4 1 311 2 1 4) + +OID = 06 0A 2B 06 01 04 01 82 37 02 01 0A +Comment = Microsoft code signing. Also known as policyLink +Description = spcAgencyInfo (1 3 6 1 4 1 311 2 1 10) + +OID = 06 0A 2B 06 01 04 01 82 37 02 01 0B +Comment = Microsoft code signing +Description = spcStatementType (1 3 6 1 4 1 311 2 1 11) + +OID = 06 0A 2B 06 01 04 01 82 37 02 01 0C +Comment = Microsoft code signing +Description = spcSpOpusInfo (1 3 6 1 4 1 311 2 1 12) + +OID = 06 0A 2B 06 01 04 01 82 37 02 01 0E +Comment = Microsoft +Description = certExtensions (1 3 6 1 4 1 311 2 1 14) + +OID = 06 0A 2B 06 01 04 01 82 37 02 01 0F +Comment = Microsoft code signing +Description = spcPelmageData (1 3 6 1 4 1 311 2 1 15) + +OID = 06 0A 2B 06 01 04 01 82 37 02 01 14 +Comment = Microsoft code signing. Also known as "glue extension" +Description = spcLink (type 1) (1 3 6 1 4 1 311 2 1 20) + +OID = 06 0A 2B 06 01 04 01 82 37 02 01 15 +Comment = Microsoft +Description = individualCodeSigning (1 3 6 1 4 1 311 2 1 21) + +OID = 06 0A 2B 06 01 04 01 82 37 02 01 16 +Comment = Microsoft +Description = commercialCodeSigning (1 3 6 1 4 1 311 2 1 22) + +OID = 06 0A 2B 06 01 04 01 82 37 02 01 19 +Comment = Microsoft code signing. Also known as "glue extension" +Description = spcLink (type 2) (1 3 6 1 4 1 311 2 1 25) + +OID = 06 0A 2B 06 01 04 01 82 37 02 01 1A +Comment = Microsoft code signing +Description = spcMinimalCriteriaInfo (1 3 6 1 4 1 311 2 1 26) + +OID = 06 0A 2B 06 01 04 01 82 37 02 01 1B +Comment = Microsoft code signing +Description = spcFinancialCriteriaInfo (1 3 6 1 4 1 311 2 1 27) + +OID = 06 0A 2B 06 01 04 01 82 37 02 01 1C +Comment = Microsoft code signing. Also known as "glue extension" +Description = spcLink (type 3) (1 3 6 1 4 1 311 2 1 28) + +OID = 06 0A 2B 06 01 04 01 82 37 03 02 01 +Comment = Microsoft code signing +Description = timestampCountersignature (1 3 6 1 4 1 311 3 2 1) + +OID = 06 0A 2B 06 01 04 01 82 37 0A 01 +Comment = Microsoft PKCS #7 contentType +Description = certTrustList (1 3 6 1 4 1 311 10 1) + +OID = 06 0A 2B 06 01 04 01 82 37 0A 02 +Comment = Microsoft +Description = nextUpdateLocation (1 3 6 1 4 1 311 10 2) + +OID = 06 0A 2B 06 01 04 01 82 37 0A 03 01 +Comment = Microsoft enhanced key usage +Description = certTrustListSigning (1 3 6 1 4 1 311 10 3 1) + +OID = 06 0A 2B 06 01 04 01 82 37 0A 03 02 +Comment = Microsoft enhanced key usage +Description = timeStampSigning (1 3 6 1 4 1 311 10 3 2) + +OID = 06 0A 2B 06 01 04 01 82 37 0A 03 03 +Comment = Microsoft enhanced key usage +Description = serverGatedCrypto (1 3 6 1 4 1 311 10 3 3) + +OID = 06 0A 2B 06 01 04 01 82 37 0A 03 04 +Comment = Microsoft enhanced key usage +Description = encryptedFileSystem (1 3 6 1 4 1 311 10 3 4) + +OID = 06 0A 2B 06 01 04 01 82 37 0A 04 01 +Comment = Microsoft attribute +Description = yesnoTrustAttr (1 3 6 1 4 1 311 10 4 1) + +# UNINETT + +OID = 06 0A 2B 06 01 04 01 92 7C 0A 01 01 +Comment = UNINETT PCA +Description = UNINETT policyIdentifier (1 3 6 1 4 1 2428 10 1 1) + +# ICE-TEL + +OID = 06 08 2B 06 01 04 01 95 18 0A +Comment = ICE-TEL CA +Description = ICE-TEL policyIdentifier (1 3 6 1 4 1 2712 10) + +OID = 06 0A 2B 06 01 04 01 95 62 01 01 01 +Comment = ICE-TEL CA policy +Description = ICE-TEL Italian policyIdentifier (1 3 6 1 4 1 2786 1 1 1) + +# cryptlib + +OID = 06 09 2B 06 01 04 01 97 55 20 01 +Comment = cryptlib +Description = cryptlibEnvelope (1 3 6 1 4 1 3029 32 1) + +OID = 06 09 2B 06 01 04 01 97 55 20 02 +Comment = cryptlib +Description = cryptlibPrivateKey (1 3 6 1 4 1 3029 32 2) + +OID = 06 0B 2B 06 01 04 01 97 55 2A D7 24 01 +Comment = cryptlib special MPEG-of-cat OID +Description = mpeg-1 (1 3 6 1 4 1 3029 42 11172 1) + +# PKIX + +OID = 06 06 2B 06 01 05 05 07 +Comment = PKIX base +Description = pkix (1 3 6 1 5 5 7) + +OID = 06 07 2B 06 01 05 05 07 01 +Comment = PKIX +Description = privateExtension (1 3 6 1 5 5 7 1) + +OID = 06 08 2B 06 01 05 05 07 01 01 +Comment = PKIX private extension +Description = authorityInfoAccess (1 3 6 1 5 5 7 1 1) + +OID = 06 07 2B 06 01 05 05 07 02 +Comment = PKIX +Description = policyQualifierIds (1 3 6 1 5 5 7 2) + +OID = 06 08 2B 06 01 05 05 07 02 01 +Comment = PKIX policy qualifier +Description = cps (1 3 6 1 5 5 7 2 1) + +OID = 06 08 2B 06 01 05 05 07 02 02 +Comment = PKIX policy qualifier +Description = unotice (1 3 6 1 5 5 7 2 2) + +OID = 06 07 2B 06 01 05 05 07 03 +Comment = PKIX +Description = keyPurpose (1 3 6 1 5 5 7 3) + +OID = 06 08 2B 06 01 05 05 07 03 01 +Comment = PKIX key purpose +Description = serverAuth (1 3 6 1 5 5 7 3 1) + +OID = 06 08 2B 06 01 05 05 07 03 02 +Comment = PKIX key purpose +Description = clientAuth (1 3 6 1 5 5 7 3 2) + +OID = 06 08 2B 06 01 05 05 07 03 03 +Comment = PKIX key purpose +Description = codeSigning (1 3 6 1 5 5 7 3 3) + +OID = 06 08 2B 06 01 05 05 07 03 04 +Comment = PKIX key purpose +Description = emailProtection (1 3 6 1 5 5 7 3 4) + +OID = 06 08 2B 06 01 05 05 07 03 05 +Comment = PKIX key purpose +Description = ipsecEndSystem (1 3 6 1 5 5 7 3 5) + +OID = 06 08 2B 06 01 05 05 07 03 06 +Comment = PKIX key purpose +Description = ipsecTunnel (1 3 6 1 5 5 7 3 6) + +OID = 06 08 2B 06 01 05 05 07 03 07 +Comment = PKIX key purpose +Description = ipsecUser (1 3 6 1 5 5 7 3 7) + +OID = 06 08 2B 06 01 05 05 07 03 08 +Comment = PKIX key purpose +Description = timeStamping (1 3 6 1 5 5 7 3 8) + +OID = 06 08 2B 06 01 05 05 07 03 08 +Comment = PKIX key purpose +Description = OCSPSigning (1 3 6 1 5 5 7 3 9) + +OID = 06 07 2B 06 01 05 05 07 04 +Comment = PKIX +Description = cmpInformationTypes (1 3 6 1 5 5 7 4) + +OID = 06 08 2B 06 01 05 05 07 04 01 +Comment = PKIX CMP information +Description = caProtEncCert (1 3 6 1 5 5 7 4 1) + +OID = 06 08 2B 06 01 05 05 07 04 02 +Comment = PKIX CMP information +Description = signKeyPairTypes (1 3 6 1 5 5 7 4 2) + +OID = 06 08 2B 06 01 05 05 07 04 03 +Comment = PKIX CMP information +Description = encKeyPairTypes (1 3 6 1 5 5 7 4 3) + +OID = 06 08 2B 06 01 05 05 07 04 04 +Comment = PKIX CMP information +Description = preferredSymmAlg (1 3 6 1 5 5 7 4 4) + +OID = 06 08 2B 06 01 05 05 07 04 05 +Comment = PKIX CMP information +Description = caKeyUpdateInfo (1 3 6 1 5 5 7 4 5) + +OID = 06 08 2B 06 01 05 05 07 04 06 +Comment = PKIX CMP information +Description = currentCRL (1 3 6 1 5 5 7 4 6) + +OID = 06 08 2B 06 01 05 05 07 30 01 +Comment = PKIX authority info access descriptor +Description = ocsp (1 3 6 1 5 5 7 48 1) + +OID = 06 08 2B 06 01 05 05 07 30 02 +Comment = PKIX authority info access descriptor +Description = caIssuers (1 3 6 1 5 5 7 48 2) + +# ISAKMP + +OID = 06 08 2B 06 01 05 05 08 01 01 +Comment = ISAKMP HMAC algorithm +Description = HMAC-MD5 (1 3 6 1 5 5 8 1 1) + +OID = 06 08 2B 06 01 05 05 08 01 02 +Comment = ISAKMP HMAC algorithm +Description = HMAC-SHA (1 3 6 1 5 5 8 1 2) + +OID = 06 08 2B 06 01 05 05 08 01 03 +Comment = ISAKMP HMAC algorithm +Description = HMAC-Tiger (1 3 6 1 5 5 8 1 3) + +# DEC (via ECMA) + +OID = 06 07 2B 0C 02 87 73 07 01 +Comment = DASS algorithm +Description = decEncryptionAlgorithm (1 3 12 2 1011 7 1) + +OID = 06 08 2B 0C 02 87 73 07 01 02 +Comment = DASS encryption algorithm +Description = decDEA (1 3 12 2 1011 7 1 2) + +OID = 06 07 2B 0C 02 87 73 07 02 +Comment = DASS algorithm +Description = decHashAlgorithm (1 3 12 2 1011 7 2) + +OID = 06 07 2B 0C 02 87 73 07 02 01 +Comment = DASS hash algorithm +Description = decMD2 (1 3 12 2 1011 7 2 1) + +OID = 06 07 2B 0C 02 87 73 07 02 02 +Comment = DASS hash algorithm +Description = decMD4 (1 3 12 2 1011 7 2 2) + +OID = 06 07 2B 0C 02 87 73 07 03 +Comment = DASS algorithm +Description = decSignatureAlgorithm (1 3 12 2 1011 7 3) + +OID = 06 07 2B 0C 02 87 73 07 03 01 +Comment = DASS signature algorithm +Description = decMD2withRSA (1 3 12 2 1011 7 3 1) + +OID = 06 07 2B 0C 02 87 73 07 03 02 +Comment = DASS signature algorithm +Description = decMD4withRSA (1 3 12 2 1011 7 3 2) + +OID = 06 07 2B 0C 02 87 73 07 03 03 +Comment = DASS signature algorithm +Description = decDEAMAC (1 3 12 2 1011 7 3 3) + +# NIST Open Systems Environment (OSE) Implementor's Workshop (OIW), +# specialising in oddball and partially-defunct OIDs + +OID = 06 05 2B 0E 02 1A 05 +Comment = Unsure about this OID +Description = sha (1 3 14 2 26 5) + +OID = 06 06 2B 0E 03 02 01 01 +Comment = X.509. Unsure about this OID +Description = rsa (1 3 14 3 2 1 1) + +OID = 06 05 2B 0E 03 02 02 +Comment = Oddball OIW OID +Description = md4WitRSA (1 3 14 3 2 2) + +OID = 06 05 2B 0E 03 02 03 +Comment = Oddball OIW OID +Description = md5WithRSA (1 3 14 3 2 3) + +OID = 06 05 2B 0E 03 02 04 +Comment = Oddball OIW OID +Description = md4WithRSAEncryption (1 3 14 3 2 4) + +OID = 06 06 2B 0E 03 02 02 01 +Comment = X.509. Deprecated +Description = sqmod-N (1 3 14 3 2 2 1) +Warning + +OID = 06 06 2B 0E 03 02 03 01 +Comment = X.509. Deprecated +Description = sqmod-NwithRSA (1 3 14 3 2 3 1) +Warning + +OID = 06 05 2B 0E 03 02 06 +Description = desECB (1 3 14 3 2 6) + +OID = 06 05 2B 0E 03 02 07 +Description = desCBC (1 3 14 3 2 7) + +OID = 06 05 2B 0E 03 02 08 +Description = desOFB (1 3 14 3 2 8) + +OID = 06 05 2B 0E 03 02 09 +Description = desCFB (1 3 14 3 2 9) + +OID = 06 05 2B 0E 03 02 0A +Description = desMAC (1 3 14 3 2 10) + +OID = 06 05 2B 0E 03 02 0B +Comment = ISO 9796-2, also X9.31 Part 1 +Description = rsaSignature (1 3 14 3 2 11) + +# this is used by BSAFE +OID = 06 05 2B 0E 03 02 0C +Comment = OIW?, supposedly from an incomplete version of SDN.702 (doesn't match final SDN.702) +Description = dsa-bsafe (1 3 14 3 2 12) +Warning + +OID = 06 05 2B 0E 03 02 0D +Comment = Oddball OIW OID. Incorrectly used by JDK 1.1 in place of (1 3 14 3 2 27) +# Their response was that they know it's wrong, but noone uses SHA0 so it won't +# cause any problems, right? Note: BSAFE uses this as well! +Description = dsaWithSHA-bsafe (1 3 14 3 2 13) +Warning + +# The various mdWithRSASIsignature OIDs are for the ANSI X9.31 draft and use +# ISO 9796-2 padding rules. This work was derailed during the PKP brouhaha and +# is still in progress +OID = 06 05 2B 0E 03 02 0E +Comment = Oddball OIW OID using 9796-2 padding rules +Description = mdc2WithRSASignature (1 3 14 3 2 14) + +OID = 06 05 2B 0E 03 02 0F +Comment = Oddball OIW OID using 9796-2 padding rules +Description = shaWithRSASignature (1 3 14 3 2 15) + +OID = 06 05 2B 0E 03 02 10 +Comment = Oddball OIW OID. Deprecated, use a plain DH OID instead +Description = dhWithCommonModulus (1 3 14 3 2 16) +Warning + +OID = 06 05 2B 0E 03 02 11 +Comment = Oddball OIW OID. Mode is ECB +Description = desEDE (1 3 14 3 2 17) + +OID = 06 05 2B 0E 03 02 12 +Comment = Oddball OIW OID +Description = sha (1 3 14 3 2 18) + +OID = 06 05 2B 0E 03 02 13 +Comment = Oddball OIW OID, DES-based hash, planned for X9.31 Part 2 +Description = mdc-2 (1 3 14 3 2 19) + +OID = 06 05 2B 0E 03 02 14 +Comment = Oddball OIW OID. Deprecated, use a plain DSA OID instead +Description = dsaCommon (1 3 14 3 2 20) +Warning + +OID = 06 05 2B 0E 03 02 15 +Comment = Oddball OIW OID. Deprecated, use a plain dsaWithSHA OID instead +Description = dsaCommonWithSHA (1 3 14 3 2 21) +Warning + +OID = 06 05 2B 0E 03 02 16 +Comment = Oddball OIW OID +Description = rsaKeyTransport (1 3 14 3 2 22) + +OID = 06 05 2B 0E 03 02 17 +Comment = Oddball OIW OID +Description = keyed-hash-seal (1 3 14 3 2 23) + +OID = 06 05 2B 0E 03 02 18 +Comment = Oddball OIW OID using 9796-2 padding rules +Description = md2WithRSASignature (1 3 14 3 2 24) + +OID = 06 05 2B 0E 03 02 19 +Comment = Oddball OIW OID using 9796-2 padding rules +Description = md5WithRSASignature (1 3 14 3 2 25) + +OID = 06 05 2B 0E 03 02 1A +Comment = OIW +Description = sha1 (1 3 14 3 2 26) + +# Yet another multiply-assigned OID +OID = 06 05 2B 0E 03 02 1B +Comment = OIW. This OID may also be assigned as ripemd-160 +Description = dsaWithSHA1 (1 3 14 3 2 27) + +OID = 06 05 2B 0E 03 02 1C +Comment = OIW +Description = dsaWithCommonSHA1 (1 3 14 3 2 28) + +OID = 06 05 2B 0E 03 02 1D +Comment = Oddball OIW OID +Description = sha-1WithRSAEncryption (1 3 14 3 2 29) + +OID = 06 05 2B 0E 03 03 01 +Comment = Oddball OIW OID +Description = simple-strong-auth-mechanism (1 3 14 3 3 1) + +OID = 06 06 2B 0E 07 02 01 01 +Comment = Unsure about this OID +Description = ElGamal (1 3 14 7 2 1 1) + +OID = 06 06 2B 0E 07 02 03 01 +Comment = Unsure about this OID +Description = md2WithRSA (1 3 14 7 2 3 1) + +OID = 06 06 2B 0E 07 02 03 02 +Comment = Unsure about this OID +Description = md2WithElGamal (1 3 14 7 2 3 2) + +# Teletrust + +OID = 06 03 2B 24 01 +Comment = Teletrust document +Description = document (1 3 36 1) + +OID = 06 04 2B 24 01 01 +Comment = Teletrust document +Description = finalVersion (1 3 36 1 1) + +OID = 06 04 2B 24 01 02 +Comment = Teletrust document +Description = draft (1 3 36 1 2) + +OID = 06 03 2B 24 02 +Comment = Teletrust sio +Description = sio (1 3 36 2) + +OID = 06 04 2B 24 02 01 +Comment = Teletrust sio +Description = certificate (1 3 36 2 1) + +OID = 06 04 2B 24 02 01 +Comment = Teletrust sio +Description = sedu (1 3 36 2 1) + +OID = 06 03 2B 24 03 +Comment = Teletrust algorithm +Description = algorithm (1 3 36 3) + +OID = 06 04 2B 24 03 01 +Comment = Teletrust algorithm +Description = encryptionAlgorithm (1 3 36 3 1) + +OID = 06 05 2B 24 03 01 01 +Comment = Teletrust encryption algorithm +Description = des (1 3 36 3 1 1) + +OID = 06 06 2B 24 03 01 01 01 +Comment = Teletrust encryption algorithm +Description = desECB_pad (1 3 36 3 1 1 1) + +OID = 06 07 2B 24 03 01 01 01 01 +Comment = Teletrust encryption algorithm +Description = desECB_ISOpad (1 3 36 3 1 1 1 1) + +OID = 06 07 2B 24 03 01 01 02 01 +Comment = Teletrust encryption algorithm +Description = desCBC_pad (1 3 36 3 1 1 2 1) + +OID = 06 08 2B 24 03 01 01 02 01 01 +Comment = Teletrust encryption algorithm +Description = desCBC_ISOpad (1 3 36 3 1 1 2 1 1) + +OID = 06 05 2B 24 03 01 03 +Comment = Teletrust encryption algorithm +Description = des_3 (1 3 36 3 1 3) + +OID = 06 07 2B 24 03 01 03 01 01 +Comment = Teletrust encryption algorithm. EDE triple DES +Description = des_3ECB_pad (1 3 36 3 1 3 1 1) + +OID = 06 08 2B 24 03 01 03 01 01 01 +Comment = Teletrust encryption algorithm. EDE triple DES +Description = des_3ECB_ISOpad (1 3 36 3 1 3 1 1 1) + +OID = 06 07 2B 24 03 01 03 02 01 +Comment = Teletrust encryption algorithm. EDE triple DES +Description = des_3CBC_pad (1 3 36 3 1 3 2 1) + +OID = 06 08 2B 24 03 01 03 02 01 01 +Comment = Teletrust encryption algorithm. EDE triple DES +Description = des_3CBC_ISOpad (1 3 36 3 1 3 2 1 1) + +OID = 06 05 2B 24 03 01 02 +Comment = Teletrust encryption algorithm +Description = idea (1 3 36 3 1 2) + +OID = 06 06 2B 24 03 01 02 01 +Comment = Teletrust encryption algorithm +Description = ideaECB (1 3 36 3 1 2 1) + +OID = 06 07 2B 24 03 01 02 01 01 +Comment = Teletrust encryption algorithm +Description = ideaECB_pad (1 3 36 3 1 2 1 1) + +OID = 06 08 2B 24 03 01 02 01 01 01 +Comment = Teletrust encryption algorithm +Description = ideaECB_ISOpad (1 3 36 3 1 2 1 1 1) + +OID = 06 06 2B 24 03 01 02 02 +Comment = Teletrust encryption algorithm +Description = ideaCBC (1 3 36 3 1 2 2) + +OID = 06 07 2B 24 03 01 02 02 01 +Comment = Teletrust encryption algorithm +Description = ideaCBC_pad (1 3 36 3 1 2 2 1) + +OID = 06 08 2B 24 03 01 02 02 01 01 +Comment = Teletrust encryption algorithm +Description = ideaCBC_ISOpad (1 3 36 3 1 2 2 1 1) + +OID = 06 06 2B 24 03 01 02 03 +Comment = Teletrust encryption algorithm +Description = ideaOFB (1 3 36 3 1 2 3) + +OID = 06 06 2B 24 03 01 02 04 +Comment = Teletrust encryption algorithm +Description = ideaCFB (1 3 36 3 1 2 4) + +OID = 06 05 2B 24 03 01 04 +Comment = Teletrust encryption algorithm +Description = rsaEncryption (1 3 36 3 1 4) + +OID = 06 08 2B 24 03 01 04 84 00 11 +Comment = Teletrust encryption algorithm +Description = rsaEncryptionWithlmod512expe17 (1 3 36 3 1 4 512 17) + +OID = 06 05 2B 24 03 01 05 +Comment = Teletrust encryption algorithm +Description = bsi-1 (1 3 36 3 1 5) + +OID = 06 06 2B 24 03 01 05 01 +Comment = Teletrust encryption algorithm +Description = bsi_1ECB_pad (1 3 36 3 1 5 1) + +OID = 06 06 2B 24 03 01 05 02 +Comment = Teletrust encryption algorithm +Description = bsi_1CBC_pad (1 3 36 3 1 5 2) + +OID = 06 07 2B 24 03 01 05 02 01 +Comment = Teletrust encryption algorithm +Description = bsi_1CBC_PEMpad (1 3 36 3 1 5 2 1) + +OID = 06 04 2B 24 03 02 +Comment = Teletrust algorithm +Description = hashAlgorithm (1 3 36 3 2) + +OID = 06 05 2B 24 03 02 01 +Comment = Teletrust hash algorithm +Description = ripemd160 (1 3 36 3 2 1) + +OID = 06 05 2B 24 03 02 02 +Comment = Teletrust hash algorithm +Description = ripemd128 (1 3 36 3 2 2) + +OID = 06 05 2B 24 03 02 03 +Comment = Teletrust hash algorithm +Description = ripemd256 (1 3 36 3 2 3) + +OID = 06 05 2B 24 03 02 04 +Comment = Teletrust hash algorithm +Description = mdc2singleLength (1 3 36 3 2 4) + +OID = 06 05 2B 24 03 02 05 +Comment = Teletrust hash algorithm +Description = mdc2doubleLength (1 3 36 3 2 5) + +OID = 06 04 2B 24 03 03 +Comment = Teletrust algorithm +Description = signatureAlgorithm (1 3 36 3 3) + +OID = 06 05 2B 24 03 03 01 +Comment = Teletrust signature algorithm +Description = rsaSignature (1 3 36 3 3 1) + +OID = 06 06 2B 24 03 03 01 01 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1 (1 3 36 3 3 1 1) + +# What *were* they thinking? +OID = 06 09 2B 24 03 03 01 01 84 00 02 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l512_l2 (1 3 36 3 3 1 1 512 2) +OID = 06 09 2B 24 03 03 01 01 85 00 02 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l640_l2 (1 3 36 3 3 1 1 640 2) +OID = 06 09 2B 24 03 03 01 01 86 00 02 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l768_l2 (1 3 36 3 3 1 1 768 2) +OID = 06 09 2B 24 03 03 01 01 87 00 02 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l896_l2 (1 3 36 3 3 1 1 892 2) +OID = 06 09 2B 24 03 03 01 01 88 00 02 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l1024_l2 (1 3 36 3 3 1 1 1024 2) +OID = 06 09 2B 24 03 03 01 01 84 00 03 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l512_l3 (1 3 36 3 3 1 1 512 3) +OID = 06 09 2B 24 03 03 01 01 85 00 03 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l640_l3 (1 3 36 3 3 1 1 640 3) +OID = 06 09 2B 24 03 03 01 01 86 00 03 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l768_l3 (1 3 36 3 3 1 1 768 3) +OID = 06 09 2B 24 03 03 01 01 87 00 03 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l896_l3 (1 3 36 3 3 1 1 896 3) +OID = 06 09 2B 24 03 03 01 01 88 00 03 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l1024_l3 (1 3 36 3 3 1 1 1024 3) +OID = 06 09 2B 24 03 03 01 01 84 00 05 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l512_l5 (1 3 36 3 3 1 1 512 5) +OID = 06 09 2B 24 03 03 01 01 85 00 05 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l640_l5 (1 3 36 3 3 1 1 640 5) +OID = 06 09 2B 24 03 03 01 01 86 00 05 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l768_l5 (1 3 36 3 3 1 1 768 5) +OID = 06 09 2B 24 03 03 01 01 87 00 05 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l896_l5 (1 3 36 3 3 1 1 896 5) +OID = 06 09 2B 24 03 03 01 01 88 00 05 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l1024_l5 (1 3 36 3 3 1 1 1024 5) +OID = 06 09 2B 24 03 03 01 01 84 00 09 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l512_l9 (1 3 36 3 3 1 1 512 9) +OID = 06 09 2B 24 03 03 01 01 85 00 09 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l640_l9 (1 3 36 3 3 1 1 640 9) +OID = 06 09 2B 24 03 03 01 01 86 00 09 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l768_l9 (1 3 36 3 3 1 1 768 9) +OID = 06 09 2B 24 03 03 01 01 87 00 09 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l896_l9 (1 3 36 3 3 1 1 896 9) +OID = 06 09 2B 24 03 03 01 01 88 00 09 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l1024_l9 (1 3 36 3 3 1 1 1024 9) +OID = 06 09 2B 24 03 03 01 01 84 00 11 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l512_l11 (1 3 36 3 3 1 1 512 11) +OID = 06 09 2B 24 03 03 01 01 85 00 11 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l640_l11 (1 3 36 3 3 1 1 640 11) +OID = 06 09 2B 24 03 03 01 01 86 00 11 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l768_l11 (1 3 36 3 3 1 1 768 11) +OID = 06 09 2B 24 03 03 01 01 87 00 11 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l896_l11 (1 3 36 3 3 1 1 896 11) +OID = 06 09 2B 24 03 03 01 01 88 00 11 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithsha1_l1024_l11 (1 3 36 3 3 1 1 1024 11) + +OID = 06 06 2B 24 03 03 01 02 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160 (1 3 36 3 3 1 2) + +OID = 06 09 2B 24 03 03 01 02 84 00 02 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l512_l2 (1 3 36 3 3 1 2 512 2) +OID = 06 09 2B 24 03 03 01 02 85 00 02 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l640_l2 (1 3 36 3 3 1 2 640 2) +OID = 06 09 2B 24 03 03 01 02 86 00 02 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l768_l2 (1 3 36 3 3 1 2 768 2) +OID = 06 09 2B 24 03 03 01 02 87 00 02 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l896_l2 (1 3 36 3 3 1 2 892 2) +OID = 06 09 2B 24 03 03 01 02 88 00 02 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l1024_l2 (1 3 36 3 3 1 2 1024 2) +OID = 06 09 2B 24 03 03 01 02 84 00 03 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l512_l3 (1 3 36 3 3 1 2 512 3) +OID = 06 09 2B 24 03 03 01 02 85 00 03 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l640_l3 (1 3 36 3 3 1 2 640 3) +OID = 06 09 2B 24 03 03 01 02 86 00 03 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l768_l3 (1 3 36 3 3 1 2 768 3) +OID = 06 09 2B 24 03 03 01 02 87 00 03 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l896_l3 (1 3 36 3 3 1 2 896 3) +OID = 06 09 2B 24 03 03 01 02 88 00 03 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l1024_l3 (1 3 36 3 3 1 2 1024 3) +OID = 06 09 2B 24 03 03 01 02 84 00 05 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l512_l5 (1 3 36 3 3 1 2 512 5) +OID = 06 09 2B 24 03 03 01 02 85 00 05 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l640_l5 (1 3 36 3 3 1 2 640 5) +OID = 06 09 2B 24 03 03 01 02 86 00 05 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l768_l5 (1 3 36 3 3 1 2 768 5) +OID = 06 09 2B 24 03 03 01 02 87 00 05 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l896_l5 (1 3 36 3 3 1 2 896 5) +OID = 06 09 2B 24 03 03 01 02 88 00 05 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l1024_l5 (1 3 36 3 3 1 2 1024 5) +OID = 06 09 2B 24 03 03 01 02 84 00 09 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l512_l9 (1 3 36 3 3 1 2 512 9) +OID = 06 09 2B 24 03 03 01 02 85 00 09 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l640_l9 (1 3 36 3 3 1 2 640 9) +OID = 06 09 2B 24 03 03 01 02 86 00 09 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l768_l9 (1 3 36 3 3 1 2 768 9) +OID = 06 09 2B 24 03 03 01 02 87 00 09 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l896_l9 (1 3 36 3 3 1 2 896 9) +OID = 06 09 2B 24 03 03 01 02 88 00 09 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l1024_l9 (1 3 36 3 3 1 2 1024 9) +OID = 06 09 2B 24 03 03 01 02 84 00 11 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l512_l11 (1 3 36 3 3 1 2 512 11) +OID = 06 09 2B 24 03 03 01 02 85 00 11 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l640_l11 (1 3 36 3 3 1 2 640 11) +OID = 06 09 2B 24 03 03 01 02 86 00 11 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l768_l11 (1 3 36 3 3 1 2 768 11) +OID = 06 09 2B 24 03 03 01 02 87 00 11 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l896_l11 (1 3 36 3 3 1 2 896 11) +OID = 06 09 2B 24 03 03 01 02 88 00 11 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithripemd160_l1024_l11 (1 3 36 3 3 1 2 1024 11) + +OID = 06 06 2B 24 03 03 01 03 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithrimpemd128 (1 3 36 3 3 1 3) + +OID = 06 06 2B 24 03 03 01 04 +Comment = Teletrust signature algorithm +Description = rsaSignatureWithrimpemd256 (1 3 36 3 3 1 4) + +OID = 06 05 2B 24 03 03 02 +Comment = Teletrust signature algorithm +Description = ecsieSign (1 3 36 3 3 2) + +OID = 06 06 2B 24 03 03 02 01 +Comment = Teletrust signature algorithm +Description = ecsieSignWithsha1 (1 3 36 3 3 2 1) + +OID = 06 06 2B 24 03 03 02 02 +Comment = Teletrust signature algorithm +Description = ecsieSignWithripemd160 (1 3 36 3 3 2 2) + +OID = 06 06 2B 24 03 03 02 03 +Comment = Teletrust signature algorithm +Description = ecsieSignWithmd2 (1 3 36 3 3 2 3) + +OID = 06 06 2B 24 03 03 02 04 +Comment = Teletrust signature algorithm +Description = ecsieSignWithmd5 (1 3 36 3 3 2 4) + +OID = 06 04 2B 24 03 04 +Comment = Teletrust algorithm +Description = signatureScheme (1 3 36 3 4) + +OID = 06 05 2B 24 03 04 01 +Comment = Teletrust signature scheme +Description = sigS_ISO9796-1 (1 3 36 3 4 1) + +OID = 06 05 2B 24 03 04 02 +Comment = Teletrust signature scheme +Description = sigS_ISO9796-2 (1 3 36 3 4 2) + +OID = 06 05 2B 24 03 04 02 01 +Comment = Teletrust signature scheme. Unsure what this is supposed to be +Description = sigS_ISO9796-2Withred (1 3 36 3 4 2 1) + +OID = 06 06 2B 24 03 04 02 02 +Comment = Teletrust signature scheme. Unsure what this is supposed to be +Description = sigS_ISO9796-2Withrsa (1 3 36 3 4 2 2) + +OID = 06 06 2B 24 03 04 02 03 +Comment = Teletrust signature scheme. 9796-2 with random number in padding field +Description = sigS_ISO9796-2Withrnd (1 3 36 3 4 2 3) + +OID = 06 03 2B 24 04 +Comment = Teletrust attribute +Description = attribute (1 3 36 4) + +OID = 06 03 2B 24 05 +Comment = Teletrust policy +Description = policy (1 3 36 5) + +OID = 06 03 2B 24 06 +Comment = Teletrust API +Description = api (1 3 36 6) + +OID = 06 04 2B 24 06 01 +Comment = Teletrust API +Description = manufacturer-specific_api (1 3 36 6 1) + +OID = 06 05 2B 24 06 01 01 +Comment = Teletrust API +Description = utimaco-api (1 3 36 6 1 1) + +OID = 06 04 2B 24 06 02 +Comment = Teletrust API +Description = functionality-specific_api (1 3 36 6 2) + +OID = 06 03 2B 24 07 +Comment = Teletrust key management +Description = keymgmnt (1 3 36 7) + +OID = 06 04 2B 24 07 01 +Comment = Teletrust key management +Description = keyagree (1 3 36 7 1) + +OID = 06 05 2B 24 07 01 01 +Comment = Teletrust key management +Description = bsiPKE (1 3 36 7 1 1) + +OID = 06 04 2B 24 07 02 +Comment = Teletrust key management +Description = keytrans (1 3 36 7 2) + +OID = 06 04 2B 24 07 02 01 +Comment = Teletrust key management. 9796-2 with key stored in hash field +Description = encISO9796-2Withrsa (1 3 36 7 2 1) + +# Thawte + +OID = 06 04 2B 65 01 04 +Comment = Thawte +Description = thawte-ce (1 3 101 1 4) + +OID = 06 05 2B 65 01 04 01 +Comment = Thawte certificate extension +Description = strongExtranet (1 3 101 1 4 1) + +# X.520 + +OID = 06 03 55 04 00 +Comment = X.520 id-at (2 5 4) +Description = objectClass (2 5 4 0) + +OID = 06 03 55 04 01 +Comment = X.520 id-at (2 5 4) +Description = aliasedEntryName (2 5 4 1) + +OID = 06 03 55 04 02 +Comment = X.520 id-at (2 5 4) +Description = knowledgeInformation (2 5 4 2) + +OID = 06 03 55 04 03 +Comment = X.520 id-at (2 5 4) +Description = commonName (2 5 4 3) + +OID = 06 03 55 04 04 +Comment = X.520 id-at (2 5 4) +Description = surname (2 5 4 4) + +OID = 06 03 55 04 05 +Comment = X.520 id-at (2 5 4) +Description = serialNumber (2 5 4 5) + +OID = 06 03 55 04 06 +Comment = X.520 id-at (2 5 4) +Description = countryName (2 5 4 6) + +OID = 06 03 55 04 07 +Comment = X.520 id-at (2 5 4) +Description = localityName (2 5 4 7) + +OID = 06 04 55 04 07 01 +Comment = X.520 id-at (2 5 4) +Description = collectiveLocalityName (2 5 4 7 1) + +OID = 06 03 55 04 08 +Comment = X.520 id-at (2 5 4) +Description = stateOrProvinceName (2 5 4 8) + +OID = 06 04 55 04 08 01 +Comment = X.520 id-at (2 5 4) +Description = collectiveStateOrProvinceName (2 5 4 8 1) + +OID = 06 03 55 04 09 +Comment = X.520 id-at (2 5 4) +Description = streetAddress (2 5 4 9) + +OID = 06 04 55 04 09 01 +Comment = X.520 id-at (2 5 4) +Description = collectiveStreetAddress (2 5 4 9 1) + +OID = 06 03 55 04 0A +Comment = X.520 id-at (2 5 4) +Description = organizationName (2 5 4 10) + +OID = 06 04 55 04 0A 01 +Comment = X.520 id-at (2 5 4) +Description = collectiveOrganizationName (2 5 4 10 1) + +OID = 06 03 55 04 0B +Comment = X.520 id-at (2 5 4) +Description = organizationalUnitName (2 5 4 11) + +OID = 06 04 55 04 0B 01 +Comment = X.520 id-at (2 5 4) +Description = collectiveOrganizationalUnitName (2 5 4 11 1) + +OID = 06 03 55 04 0C +Comment = X.520 id-at (2 5 4) +Description = title (2 5 4 12) + +OID = 06 03 55 04 0D +Comment = X.520 id-at (2 5 4) +Description = description (2 5 4 13) + +OID = 06 03 55 04 0E +Comment = X.520 id-at (2 5 4) +Description = searchGuide (2 5 4 14) + +OID = 06 03 55 04 0F +Comment = X.520 id-at (2 5 4) +Description = businessCategory (2 5 4 15) + +OID = 06 03 55 04 10 +Comment = X.520 id-at (2 5 4) +Description = postalAddress (2 5 4 16) + +OID = 06 04 55 04 10 01 +Comment = X.520 id-at (2 5 4) +Description = collectivePostalAddress (2 5 4 16 1) + +OID = 06 03 55 04 11 +Comment = X.520 id-at (2 5 4) +Description = postalCode (2 5 4 17) + +OID = 06 04 55 04 11 01 +Comment = X.520 id-at (2 5 4) +Description = collectivePostalCode (2 5 4 17 1) + +OID = 06 03 55 04 12 +Comment = X.520 id-at (2 5 4) +Description = postOfficeBox (2 5 4 18) + +OID = 06 04 55 04 12 01 +Comment = X.520 id-at (2 5 4) +Description = collectivePostOfficeBox (2 5 4 18 1) + +OID = 06 03 55 04 13 +Comment = X.520 id-at (2 5 4) +Description = physicalDeliveryOfficeName (2 5 4 19) + +OID = 06 04 55 04 13 01 +Comment = X.520 id-at (2 5 4) +Description = collectivePhysicalDeliveryOfficeName (2 5 4 19 1) + +OID = 06 03 55 04 14 +Comment = X.520 id-at (2 5 4) +Description = telephoneNumber (2 5 4 20) + +OID = 06 04 55 04 14 01 +Comment = X.520 id-at (2 5 4) +Description = collectiveTelephoneNumber (2 5 4 20 1) + +OID = 06 03 55 04 15 +Comment = X.520 id-at (2 5 4) +Description = telexNumber (2 5 4 21) + +OID = 06 04 55 04 15 01 +Comment = X.520 id-at (2 5 4) +Description = collectiveTelexNumber (2 5 4 21 1) + +OID = 06 03 55 04 16 +Comment = X.520 id-at (2 5 4) +Description = teletexTerminalIdentifier (2 5 4 22) + +OID = 06 04 55 04 16 01 +Comment = X.520 id-at (2 5 4) +Description = collectiveTeletexTerminalIdentifier (2 5 4 22 1) + +OID = 06 03 55 04 17 +Comment = X.520 id-at (2 5 4) +Description = facsimileTelephoneNumber (2 5 4 23) + +OID = 06 04 55 04 17 01 +Comment = X.520 id-at (2 5 4) +Description = collectiveFacsimileTelephoneNumber (2 5 4 23 1) + +OID = 06 03 55 04 18 +Comment = X.520 id-at (2 5 4) +Description = x121Address (2 5 4 24) + +OID = 06 03 55 04 19 +Comment = X.520 id-at (2 5 4) +Description = internationalISDNNumber (2 5 4 25) + +OID = 06 04 55 04 19 01 +Comment = X.520 id-at (2 5 4) +Description = collectiveInternationalISDNNumber (2 5 4 25 1) + +OID = 06 03 55 04 1A +Comment = X.520 id-at (2 5 4) +Description = registeredAddress (2 5 4 26) + +OID = 06 03 55 04 1B +Comment = X.520 id-at (2 5 4) +Description = destinationIndicator (2 5 4 27) + +OID = 06 03 55 04 1C +Comment = X.520 id-at (2 5 4) +Description = preferredDeliveryMehtod (2 5 4 28) + +OID = 06 03 55 04 1D +Comment = X.520 id-at (2 5 4) +Description = presentationAddress (2 5 4 29) + +OID = 06 03 55 04 1E +Comment = X.520 id-at (2 5 4) +Description = supportedApplicationContext (2 5 4 30) + +OID = 06 03 55 04 1F +Comment = X.520 id-at (2 5 4) +Description = member (2 5 4 31) + +OID = 06 03 55 04 20 +Comment = X.520 id-at (2 5 4) +Description = owner (2 5 4 32) + +OID = 06 03 55 04 21 +Comment = X.520 id-at (2 5 4) +Description = roleOccupant (2 5 4 33) + +OID = 06 03 55 04 22 +Comment = X.520 id-at (2 5 4) +Description = seeAlso (2 5 4 34) + +OID = 06 03 55 04 23 +Comment = X.520 id-at (2 5 4) +Description = userPassword (2 5 4 35) + +OID = 06 03 55 04 24 +Comment = X.520 id-at (2 5 4) +Description = userCertificate (2 5 4 36) + +OID = 06 03 55 04 25 +Comment = X.520 id-at (2 5 4) +Description = caCertificate (2 5 4 37) + +OID = 06 03 55 04 26 +Comment = X.520 id-at (2 5 4) +Description = authorityRevocationList (2 5 4 38) + +OID = 06 03 55 04 27 +Comment = X.520 id-at (2 5 4) +Description = certificateRevocationList (2 5 4 39) + +OID = 06 03 55 04 28 +Comment = X.520 id-at (2 5 4) +Description = crossCertificatePair (2 5 4 40) + +OID = 06 03 55 04 29 +Comment = X.520 id-at (2 5 4) +Description = name (2 5 4 41) + +OID = 06 03 55 04 2A +Comment = X.520 id-at (2 5 4) +Description = givenName (2 5 4 42) + +OID = 06 03 55 04 2B +Comment = X.520 id-at (2 5 4) +Description = initials (2 5 4 43) + +OID = 06 03 55 04 2C +Comment = X.520 id-at (2 5 4) +Description = generationQualifier (2 5 4 44) + +OID = 06 03 55 04 2D +Comment = X.520 id-at (2 5 4) +Description = uniqueIdentifier (2 5 4 45) + +OID = 06 03 55 04 2E +Comment = X.520 id-at (2 5 4) +Description = dnQualifier (2 5 4 46) + +OID = 06 03 55 04 2F +Comment = X.520 id-at (2 5 4) +Description = enhancedSearchGuide (2 5 4 47) + +OID = 06 03 55 04 30 +Comment = X.520 id-at (2 5 4) +Description = protocolInformation (2 5 4 48) + +OID = 06 03 55 04 31 +Comment = X.520 id-at (2 5 4) +Description = distinguishedName (2 5 4 49) + +OID = 06 03 55 04 32 +Comment = X.520 id-at (2 5 4) +Description = uniqueMember (2 5 4 50) + +OID = 06 03 55 04 33 +Comment = X.520 id-at (2 5 4) +Description = houseIdentifier (2 5 4 51) + +OID = 06 03 55 04 34 +Comment = X.520 id-at (2 5 4) +Description = supportedAlgorithms (2 5 4 52) + +OID = 06 03 55 04 35 +Comment = X.520 id-at (2 5 4) +Description = deltaRevocationList (2 5 4 53) + +OID = 06 03 55 04 3A +Comment = X.520 id-at (2 5 4) +Description = crossCertificatePair (2 5 4 58) + +# X500 algorithms + +OID = 06 02 55 08 +Description = X.500-Algorithms (2 5 8) + +OID = 06 03 55 08 01 +Description = X.500-Alg-Encryption (2 5 8 1) + +OID = 06 04 55 08 01 01 +Comment = X.500 algorithms. Ambiguous, since no padding rules specified +Description = rsa (2 5 8 1 1) +Warning + +# X.509. Some of the smaller values are from early X.509 drafts with +# cross-pollination from X9.55 and are now deprecated. Alternative OIDs are +# marked if these are known. In some cases there are multiple generations of +# superseded OIDs + +OID = 06 03 55 1D 01 +Comment = X.509 id-ce (2 5 29). Deprecated, use (2 5 29 35) instead +Description = authorityKeyIdentifier (2 5 29 1) +Warning + +OID = 06 03 55 1D 02 +Comment = X.509 id-ce (2 5 29). Obsolete, use keyUsage/extKeyUsage instead +Description = keyAttributes (2 5 29 2) +Warning + +OID = 06 03 55 1D 03 +Comment = X.509 id-ce (2 5 29). Deprecated, use (2 5 29 32) instead +Description = certificatePolicies (2 5 29 3) +Warning + +OID = 06 03 55 1D 04 +Comment = X.509 id-ce (2 5 29). Obsolete, use keyUsage/extKeyUsage instead +Description = keyUsageRestriction (2 5 29 4) +Warning + +OID = 06 03 55 1D 05 +Comment = X.509 id-ce (2 5 29). Deprecated, use (2 5 29 33) instead +Description = policyMapping (2 5 29 5) +Warning + +OID = 06 03 55 1D 06 +Comment = X.509 id-ce (2 5 29). Obsolete, use nameConstraints instead +Description = subtreesConstraint (2 5 29 6) +Warning + +OID = 06 03 55 1D 07 +Comment = X.509 id-ce (2 5 29). Deprecated, use (2 5 29 17) instead +Description = subjectAltName (2 5 29 7) +Warning + +OID = 06 03 55 1D 08 +Comment = X.509 id-ce (2 5 29). Deprecated, use (2 5 29 18) instead +Description = issuerAltName (2 5 29 8) +Warning + +OID = 06 03 55 1D 09 +Comment = X.509 id-ce (2 5 29) +Description = subjectDirectoryAttributes (2 5 29 9) + +OID = 06 03 55 1D 0A +Comment = X.509 id-ce (2 5 29). Deprecated, use (2 5 29 19) instead +Description = basicConstraints (2 5 29 10) +Warning + +OID = 06 03 55 1D 0B +Comment = X.509 id-ce (2 5 29). Deprecated, use (2 5 29 30) instead +Description = nameConstraints (2 5 29 11) +Warning + +OID = 06 03 55 1D 0C +Comment = X.509 id-ce (2 5 29). Deprecated, use (2 5 29 36) instead +Description = policyConstraints (2 5 29 12) +Warning + +OID = 06 03 55 1D 0D +Comment = X.509 id-ce (2 5 29). Deprecated, use (2 5 29 19) instead +Description = basicConstraints (2 5 29 13) +Warning + +OID = 06 03 55 1D 0E +Comment = X.509 id-ce (2 5 29) +Description = subjectKeyIdentifier (2 5 29 14) + +OID = 06 03 55 1D 0F +Comment = X.509 id-ce (2 5 29) +Description = keyUsage (2 5 29 15) + +OID = 06 03 55 1D 10 +Comment = X.509 id-ce (2 5 29) +Description = privateKeyUsagePeriod (2 5 29 16) + +OID = 06 03 55 1D 11 +Comment = X.509 id-ce (2 5 29) +Description = subjectAltName (2 5 29 17) + +OID = 06 03 55 1D 12 +Comment = X.509 id-ce (2 5 29) +Description = issuerAltName (2 5 29 18) + +OID = 06 03 55 1D 13 +Comment = X.509 id-ce (2 5 29) +Description = basicConstraints (2 5 29 19) + +OID = 06 03 55 1D 14 +Comment = X.509 id-ce (2 5 29) +Description = cRLNumber (2 5 29 20) + +OID = 06 03 55 1D 15 +Comment = X.509 id-ce (2 5 29) +Description = cRLReason (2 5 29 21) + +OID = 06 03 55 1D 16 +Comment = X.509 id-ce (2 5 29). Deprecated, alternative OID uncertain +Description = expirationDate (2 5 29 22) +Warning + +OID = 06 03 55 1D 17 +Comment = X.509 id-ce (2 5 29) +Description = instructionCode (2 5 29 23) + +OID = 06 03 55 1D 18 +Comment = X.509 id-ce (2 5 29) +Description = invalidityDate (2 5 29 24) + +OID = 06 03 55 1D 19 +Comment = X.509 id-ce (2 5 29). Deprecated, use (2 5 29 31) instead +Description = cRLDistributionPoints (2 5 29 25) deprecated +Warning + +OID = 06 03 55 1D 1A +Comment = X.509 id-ce (2 5 29). Deprecated, use (2 5 29 28) instead +Description = issuingDistributionPoint (2 5 29 26) +Warning + +OID = 06 03 55 1D 1B +Comment = X.509 id-ce (2 5 29) +Description = deltaCRLIndicator (2 5 29 27) + +OID = 06 03 55 1D 1C +Comment = X.509 id-ce (2 5 29) +Description = issuingDistributionPoint (2 5 29 28) + +OID = 06 03 55 1D 1D +Comment = X.509 id-ce (2 5 29) +Description = certificateIssuer (2 5 29 29) + +OID = 06 03 55 1D 1E +Comment = X.509 id-ce (2 5 29) +Description = nameConstraints (2 5 29 30) + +OID = 06 03 55 1D 1F +Comment = X.509 id-ce (2 5 29) +Description = cRLDistributionPoints (2 5 29 31) + +OID = 06 03 55 1D 20 +Comment = X.509 id-ce (2 5 29) +Description = certificatePolicies (2 5 29 32) + +OID = 06 03 55 1D 21 +Comment = X.509 id-ce (2 5 29) +Description = policyMappings (2 5 29 33) + +OID = 06 03 55 1D 22 +Comment = X.509 id-ce (2 5 29). Deprecated, use (2 5 29 36) instead +Description = policyConstraints (2 5 29 34) +Warning + +OID = 06 03 55 1D 23 +Comment = X.509 id-ce (2 5 29) +Description = authorityKeyIdentifier (2 5 29 35) + +OID = 06 03 55 1D 24 +Comment = X.509 id-ce (2 5 29) +Description = policyConstraints (2 5 29 36) + +OID = 06 03 55 1D 25 +Comment = X.509 id-ce (2 5 29) +Description = extKeyUsage (2 5 29 37) + +OID = 06 04 55 1D 25 00 +Comment = X.509 id-ce (2 5 29) +Description = anyExtendedKeyUsage (2 5 29 37 0) + + +# DMS-SDN-702 + +OID = 06 09 60 86 48 01 65 02 01 01 01 +Comment = DMS-SDN-702 +Description = sdnsSignatureAlgorithm (2 16 840 1 101 2 1 1 1) + +OID = 06 09 60 86 48 01 65 02 01 01 02 +Comment = DMS-SDN-702. Formerly known as mosaicSignatureAlgorithm, this OID is better known as dsaWithSHA-1. +Description = fortezzaSignatureAlgorithm (2 16 840 1 101 2 1 1 2) + +OID = 06 09 60 86 48 01 65 02 01 01 03 +Comment = DMS-SDN-702 +Description = sdnsConfidentialityAlgorithm (2 16 840 1 101 2 1 1 3) + +OID = 06 09 60 86 48 01 65 02 01 01 04 +Comment = DMS-SDN-702. Formerly known as mosaicConfidentialityAlgorithm +Description = fortezzaConfidentialityAlgorithm (2 16 840 1 101 2 1 1 4) + +OID = 06 09 60 86 48 01 65 02 01 01 05 +Comment = DMS-SDN-702 +Description = sdnsIntegrityAlgorithm (2 16 840 1 101 2 1 1 5) + +OID = 06 09 60 86 48 01 65 02 01 01 06 +Comment = DMS-SDN-702. Formerly known as mosaicIntegrityAlgorithm +Description = fortezzaIntegrityAlgorithm (2 16 840 1 101 2 1 1 6) + +OID = 06 09 60 86 48 01 65 02 01 01 07 +Comment = DMS-SDN-702 +Description = sdnsTokenProtectionAlgorithm (2 16 840 1 101 2 1 1 7) + +OID = 06 09 60 86 48 01 65 02 01 01 08 +Comment = DMS-SDN-702. Formerly know as mosaicTokenProtectionAlgorithm +Description = fortezzaTokenProtectionAlgorithm (2 16 840 1 101 2 1 1 8) + +OID = 06 09 60 86 48 01 65 02 01 01 09 +Comment = DMS-SDN-702 +Description = sdnsKeyManagementAlgorithm (2 16 840 1 101 2 1 1 9) + +OID = 06 09 60 86 48 01 65 02 01 01 0A +Comment = DMS-SDN-702. Formerly known as mosaicKeyManagementAlgorithm +Description = fortezzaKeyManagementAlgorithm (2 16 840 1 101 2 1 1 10) + +OID = 06 09 60 86 48 01 65 02 01 01 0B +Comment = DMS-SDN-702 +Description = sdnsKMandSigAlgorithm (2 16 840 1 101 2 1 1 11) + +OID = 06 09 60 86 48 01 65 02 01 01 0C +Comment = DMS-SDN-702. Formerly known as mosaicKMandSigAlgorithm +Description = fortezzaKMandSigAlgorithm (2 16 840 1 101 2 1 1 12) + +OID = 06 09 60 86 48 01 65 02 01 01 0D +Comment = DMS-SDN-702 +Description = SuiteASignatureAlgorithm (2 16 840 1 101 2 1 1 13) + +OID = 06 09 60 86 48 01 65 02 01 01 0E +Comment = DMS-SDN-702 +Description = SuiteAConfidentialityAlgorithm (2 16 840 1 101 2 1 1 14) + +OID = 06 09 60 86 48 01 65 02 01 01 0F +Comment = DMS-SDN-702 +Description = SuiteAIntegrityAlgorithm (2 16 840 1 101 2 1 1 15) + +OID = 06 09 60 86 48 01 65 02 01 01 10 +Comment = DMS-SDN-702 +Description = SuiteATokenProtectionAlgorithm (2 16 840 1 101 2 1 1 16) + +OID = 06 09 60 86 48 01 65 02 01 01 11 +Comment = DMS-SDN-702 +Description = SuiteAKeyManagementAlgorithm (2 16 840 1 101 2 1 1 17) + +OID = 06 09 60 86 48 01 65 02 01 01 12 +Comment = DMS-SDN-702 +Description = SuiteAKMandSigAlgorithm (2 16 840 1 101 2 1 1 18) + +OID = 06 09 60 86 48 01 65 02 01 01 13 +Comment = DMS-SDN-702. Formerly known as mosaicUpdatedSigAlgorithm +Description = fortezzaUpdatedSigAlgorithm (2 16 840 1 101 2 1 1 19) + +OID = 06 09 60 86 48 01 65 02 01 01 14 +Comment = DMS-SDN-702. Formerly known as mosaicKMandUpdSigAlgorithms +Description = fortezzaKMandUpdSigAlgorithms (2 16 840 1 101 2 1 1 20) + +OID = 06 09 60 86 48 01 65 02 01 01 15 +Comment = DMS-SDN-702. Formerly known as mosaicUpdatedIntegAlgorithm +Description = fortezzaUpdatedIntegAlgorithm (2 16 840 1 101 2 1 1 21) + +OID = 06 09 60 86 48 01 65 02 01 01 16 +Comment = DMS-SDN-702. Formerly known as mosaicKeyEncryptionAlgorithm +Description = keyExchangeAlgorithm (2 16 840 1 101 2 1 1 22) + +# CSOR (GAK-FIPS) + +OID = 06 07 60 86 48 01 65 03 01 +Comment = CSOR GAK +Description = slabel (2 16 840 1 101 3 1) +Warning + +OID = 06 07 60 86 48 01 65 03 02 +Comment = CSOR GAK +Description = pki (2 16 840 1 101 3 2) +Warning + +OID = 06 08 60 86 48 01 65 03 02 01 +Comment = CSOR GAK policy +Description = GAK policyIdentifier (2 16 840 1 101 3 2 1) +Warning + +OID = 06 08 60 86 48 01 65 03 02 02 +Comment = CSOR GAK extended key usage +Description = GAK (2 16 840 1 101 3 2 2) +Warning + +OID = 06 09 60 86 48 01 65 03 02 02 01 +Comment = CSOR GAK extended key usage +Description = kRAKey (2 16 840 1 101 3 2 2 1) +Warning + +OID = 06 08 60 86 48 01 65 03 02 03 +Comment = CSOR GAK extensions +Description = extensions (2 16 840 1 101 3 2 3) +Warning + +OID = 06 09 60 86 48 01 65 03 02 03 01 +Comment = CSOR GAK extensions +Description = kRTechnique (2 16 840 1 101 3 2 3 1) +Warning + +OID = 06 09 60 86 48 01 65 03 02 03 02 +Comment = CSOR GAK extensions +Description = kRecoveryCapable (2 16 840 1 101 3 2 3 2) +Warning + +OID = 06 09 60 86 48 01 65 03 02 03 03 +Comment = CSOR GAK extensions +Description = kR (2 16 840 1 101 3 2 3 3) +Warning + +OID = 06 08 60 86 48 01 65 03 02 04 +Comment = CSOR GAK +Description = keyrecoveryschemes (2 16 840 1 101 3 2 4) +Warning + +OID = 06 08 60 86 48 01 65 03 02 05 +Comment = CSOR GAK +Description = krapola (2 16 840 1 101 3 2 5) +Warning + +OID = 06 07 60 86 48 01 65 03 03 +Comment = CSOR GAK +Description = arpa (2 16 840 1 101 3 3) +Warning + +# Novell + +OID = 06 09 60 86 48 01 86 F8 37 01 09 +Comment = Novell +Description = pki (2 16 840 1 113719 1 9) + +OID = 06 0A 60 86 48 01 86 F8 37 01 09 04 +Comment = Novell PKI +Description = pkiAttributeType (2 16 840 1 113719 1 9 4) + +OID = 06 0B 60 86 48 01 86 F8 37 01 09 04 01 +Comment = Novell PKI attribute type +Description = registeredAttributes (2 16 840 1 113719 1 9 4 1) + +OID = 06 0B 60 86 48 01 86 F8 37 01 09 04 02 +Comment = Novell PKI attribute type +Description = relianceLimit (2 16 840 1 113719 1 9 4 2) + +# Netscape + +OID = 06 08 60 86 48 01 86 F8 42 01 +Comment = Netscape +Description = cert-extension (2 16 840 1 113730 1) + +OID = 06 09 60 86 48 01 86 F8 42 01 01 +Comment = Netscape certificate extension +Description = netscape-cert-type (2 16 840 1 113730 1 1) + +OID = 06 09 60 86 48 01 86 F8 42 01 02 +Comment = Netscape certificate extension +Description = netscape-base-url (2 16 840 1 113730 1 2) + +OID = 06 09 60 86 48 01 86 F8 42 01 03 +Comment = Netscape certificate extension +Description = netscape-revocation-url (2 16 840 1 113730 1 3) + +OID = 06 09 60 86 48 01 86 F8 42 01 04 +Comment = Netscape certificate extension +Description = netscape-ca-revocation-url (2 16 840 1 113730 1 4) + +OID = 06 09 60 86 48 01 86 F8 42 02 05 +Comment = Netscape certificate extension +Description = netscape-cert-sequence (2 16 840 1 113730 2 5) + +OID = 06 09 60 86 48 01 86 F8 42 02 06 +Comment = Netscape certificate extension +Description = netscape-cert-url (2 16 840 1 113730 2 6) + +OID = 06 09 60 86 48 01 86 F8 42 01 07 +Comment = Netscape certificate extension +Description = netscape-cert-renewal-url (2 16 840 1 113730 1 7) + +OID = 06 09 60 86 48 01 86 F8 42 01 08 +Comment = Netscape certificate extension +Description = netscape-ca-policy-url (2 16 840 1 113730 1 8) + +OID = 06 09 60 86 48 01 86 F8 42 01 09 +Comment = Netscape certificate extension +Description = HomePage-url (2 16 840 1 113730 1 9) + +OID = 06 09 60 86 48 01 86 F8 42 01 0A +Comment = Netscape certificate extension +Description = EntityLogo (2 16 840 1 113730 1 10) + +OID = 06 09 60 86 48 01 86 F8 42 01 0B +Comment = Netscape certificate extension +Description = UserPicture (2 16 840 1 113730 1 11) + +OID = 06 09 60 86 48 01 86 F8 42 01 0C +Comment = Netscape certificate extension +Description = netscape-ssl-server-name (2 16 840 1 113730 1 12) + +OID = 06 09 60 86 48 01 86 F8 42 01 0D +Comment = Netscape certificate extension +Description = netscape-comment (2 16 840 1 113730 1 13) + +OID = 06 08 60 86 48 01 86 F8 42 02 +Comment = Netscape +Description = data-type (2 16 840 1 113730 2) + +OID = 06 09 60 86 48 01 86 F8 42 02 01 +Comment = Netscape data type +Description = GIF (2 16 840 1 113730 2 1) + +OID = 06 09 60 86 48 01 86 F8 42 02 02 +Comment = Netscape data type +Description = JPEG (2 16 840 1 113730 2 2) + +OID = 06 09 60 86 48 01 86 F8 42 02 03 +Comment = Netscape data type +Description = URL (2 16 840 1 113730 2 3) + +OID = 06 09 60 86 48 01 86 F8 42 02 04 +Comment = Netscape data type +Description = HTML (2 16 840 1 113730 2 4) + +OID = 06 09 60 86 48 01 86 F8 42 02 05 +Comment = Netscape data type +Description = CertSeq (2 16 840 1 113730 2 5) + +OID = 06 08 60 86 48 01 86 F8 42 03 +Comment = Netscape +Description = directory (2 16 840 1 113730 3) + +OID = 06 09 60 86 48 01 86 F8 42 03 01 +Comment = Netscape directory +Description = ldapDefinitions (2 16 840 1 113730 3 1) + +OID = 06 0A 60 86 48 01 86 F8 42 03 01 01 +Comment = Netscape LDAP definitions +Description = carLicense (2 16 840 1 113730 3 1 1) + +OID = 06 0A 60 86 48 01 86 F8 42 03 01 02 +Comment = Netscape LDAP definitions +Description = departmentNumber (2 16 840 1 113730 3 1 2) + +OID = 06 0A 60 86 48 01 86 F8 42 03 01 03 +Comment = Netscape LDAP definitions +Description = employeeNumber (2 16 840 1 113730 3 1 3) + +OID = 06 0A 60 86 48 01 86 F8 42 03 01 04 +Comment = Netscape LDAP definitions +Description = employeeType (2 16 840 1 113730 3 1 4) + +OID = 06 0A 60 86 48 01 86 F8 42 03 02 02 +Comment = Netscape LDAP definitions +Description = inetOrgPerson (2 16 840 1 113730 3 2 2) + +OID = 06 09 60 86 48 01 86 F8 42 04 01 +Comment = Netscape +Description = serverGatedCrypto (2 16 840 1 113730 4 1) + +# Verisign + +OID = 06 0A 60 86 48 01 86 F8 45 01 06 03 +Comment = Verisign +Description = Unknown Verisign extension (2 16 840 1 113733 1 6 3) + +OID = 06 0A 60 86 48 01 86 F8 45 01 06 06 +Comment = Verisign +Description = Unknown Verisign extension (2 16 840 1 113733 1 6 6) + +OID = 06 0B 60 86 48 01 86 F8 45 01 07 01 01 +Comment = Verisign +Description = Verisign certificatePolicy (2 16 840 1 113733 1 7 1 1) + +OID = 06 0C 60 86 48 01 86 F8 45 01 07 01 01 01 +Comment = Verisign +Description = Unknown Verisign policy qualifier (2 16 840 1 113733 1 7 1 1 1) + +OID = 06 0C 60 86 48 01 86 F8 45 01 07 01 01 02 +Comment = Verisign +Description = Unknown Verisign policy qualifier (2 16 840 1 113733 1 7 1 1 2) + +OID = 06 0A 60 86 48 01 86 F8 45 01 08 01 +Comment = Verisign +Description = Verisign SGC CA? (2 16 840 1 113733 1 8 1) + +# SET + +OID = 06 03 67 2A 00 +Comment = SET +Description = contentType (2 23 42 0) + +OID = 06 04 67 2A 00 00 +Comment = SET contentType +Description = PANData (2 23 42 0 0) + +OID = 06 04 67 2A 00 01 +Comment = SET contentType +Description = PANToken (2 23 42 0 1) + +OID = 06 04 67 2A 00 02 +Comment = SET contentType +Description = PANOnly (2 23 42 0 2) + +# And on and on and on for another 80-odd OIDs which I'm not going to type in + +OID = 06 03 67 2A 01 +Comment = SET +Description = msgExt (2 23 42 1) + +OID = 06 03 67 2A 02 +Comment = SET +Description = field (2 23 42 2) + +OID = 06 04 67 2A 02 00 +Comment = SET field +Description = fullName (2 23 42 2 0) + +OID = 06 04 67 2A 02 01 +Comment = SET field +Description = givenName (2 23 42 2 1) + +OID = 06 04 67 2A 02 02 +Comment = SET field +Description = familyName (2 23 42 2 2) + +OID = 06 04 67 2A 02 03 +Comment = SET field +Description = birthFamilyName (2 23 42 2 3) + +OID = 06 04 67 2A 02 04 +Comment = SET field +Description = placeName (2 23 42 2 4) + +OID = 06 04 67 2A 02 05 +Comment = SET field +Description = identificationNumber (2 23 42 2 5) + +OID = 06 04 67 2A 02 06 +Comment = SET field +Description = month (2 23 42 2 6) + +OID = 06 04 67 2A 02 07 +Comment = SET field +Description = date (2 23 42 2 7) + +OID = 06 04 67 2A 02 08 +Comment = SET field +Description = address (2 23 42 2 8) + +OID = 06 04 67 2A 02 09 +Comment = SET field +Description = telephone (2 23 42 2 9) + +OID = 06 04 67 2A 02 0A +Comment = SET field +Description = amount (2 23 42 2 10) + +OID = 06 04 67 2A 02 0B +Comment = SET field +Description = accountNumber (2 23 42 2 7 11) + +OID = 06 04 67 2A 02 0C +Comment = SET field +Description = passPhrase (2 23 42 2 7 12) + +OID = 06 03 67 2A 03 +Comment = SET +Description = attribute (2 23 42 3) + +OID = 06 04 67 2A 03 00 +Comment = SET attribute +Description = cert (2 23 42 3 0) + +OID = 06 05 67 2A 03 00 00 +Comment = SET cert attribute +Description = rootKeyThumb (2 23 42 3 0 0) + +OID = 06 05 67 2A 03 00 01 +Comment = SET cert attribute +Description = additionalPolicy (2 23 42 3 0 1) + +OID = 06 03 67 2A 04 +Comment = SET +Description = algorithm (2 23 42 4) + +OID = 06 03 67 2A 05 +Comment = SET +Description = policy (2 23 42 5) + +OID = 06 04 67 2A 05 00 +Comment = SET policy +Description = root (2 23 42 5 0) + +OID = 06 03 67 2A 06 +Comment = SET +Description = module (2 23 42 6) + +OID = 06 03 67 2A 07 +Comment = SET +Description = certExt (2 23 42 7) + +OID = 06 04 67 2A 07 00 +Comment = SET cert extension +Description = hashedRootKey (2 23 42 7 0) + +OID = 06 04 67 2A 07 01 +Comment = SET cert extension +Description = certificateType (2 23 42 7 1) + +OID = 06 04 67 2A 07 02 +Comment = SET cert extension +Description = merchantData (2 23 42 7 2) + +OID = 06 04 67 2A 07 03 +Comment = SET cert extension +Description = cardCertRequired (2 23 42 7 3) + +OID = 06 04 67 2A 07 04 +Comment = SET cert extension +Description = tunneling (2 23 42 7 4) + +OID = 06 04 67 2A 07 05 +Comment = SET cert extension +Description = setExtensions (2 23 42 7 5) + +OID = 06 04 67 2A 07 06 +Comment = SET cert extension +Description = setQualifier (2 23 42 7 6) + +OID = 06 03 67 2A 08 +Comment = SET +Description = brand (2 23 42 8) + +OID = 06 04 67 2A 08 01 +Comment = SET brand +Description = IATA-ATA (2 23 42 8 1) + +OID = 06 04 67 2A 08 04 +Comment = SET brand +Description = VISA (2 23 42 8 4) + +OID = 06 04 67 2A 08 05 +Comment = SET brand +Description = MasterCard (2 23 42 8 5) + +OID = 06 04 67 2A 08 1E +Comment = SET brand +Description = Diners (2 23 42 8 30) + +OID = 06 04 67 2A 08 22 +Comment = SET brand +Description = AmericanExpress (2 23 42 8 34) + +OID = 06 05 67 2A 08 AE 7B +Comment = SET brand +Description = Novus (2 23 42 8 6011) + +OID = 06 03 67 2A 09 +Comment = SET +Description = vendor (2 23 42 9) + +OID = 06 04 67 2A 09 00 +Comment = SET vendor +Description = GlobeSet (2 23 42 9 0) + +OID = 06 04 67 2A 09 01 +Comment = SET vendor +Description = IBM (2 23 42 9 1) + +OID = 06 04 67 2A 09 02 +Comment = SET vendor +Description = CyberCash (2 23 42 9 2) + +OID = 06 04 67 2A 09 03 +Comment = SET vendor +Description = Terisa (2 23 42 9 3) + +OID = 06 04 67 2A 09 04 +Comment = SET vendor +Description = RSADSI (2 23 42 9 4) + +OID = 06 04 67 2A 09 05 +Comment = SET vendor +Description = VeriFone (2 23 42 9 5) + +OID = 06 04 67 2A 09 06 +Comment = SET vendor +Description = TrinTech (2 23 42 9 6) + +OID = 06 04 67 2A 09 07 +Comment = SET vendor +Description = BankGate (2 23 42 9 7) + +OID = 06 04 67 2A 09 08 +Comment = SET vendor +Description = GTE (2 23 42 9 8) + +OID = 06 04 67 2A 09 09 +Comment = SET vendor +Description = CompuSource (2 23 42 9 9) + +OID = 06 04 67 2A 09 0A +Comment = SET vendor +Description = Griffin (2 23 42 9 10) + +OID = 06 04 67 2A 09 0B +Comment = SET vendor +Description = Certicom (2 23 42 9 11) + +OID = 06 04 67 2A 09 0C +Comment = SET vendor +Description = OSS (2 23 42 9 12) + +OID = 06 04 67 2A 09 0D +Comment = SET vendor +Description = TenthMountain (2 23 42 9 13) + +OID = 06 04 67 2A 09 0E +Comment = SET vendor +Description = Antares (2 23 42 9 14) + +OID = 06 04 67 2A 09 0F +Comment = SET vendor +Description = ECC (2 23 42 9 15) + +OID = 06 04 67 2A 09 10 +Comment = SET vendor +Description = Maithean (2 23 42 9 16) + +OID = 06 04 67 2A 09 11 +Comment = SET vendor +Description = Netscape (2 23 42 9 17) + +OID = 06 04 67 2A 09 12 +Comment = SET vendor +Description = Verisign (2 23 42 9 18) + +OID = 06 04 67 2A 09 13 +Comment = SET vendor +Description = BlueMoney (2 23 42 9 19) + +OID = 06 04 67 2A 09 14 +Comment = SET vendor +Description = Lacerte (2 23 42 9 20) + +OID = 06 04 67 2A 09 15 +Comment = SET vendor +Description = Fujitsu (2 23 42 9 21) + +OID = 06 04 67 2A 09 16 +Comment = SET vendor +Description = eLab (2 23 42 9 22) + +OID = 06 04 67 2A 09 17 +Comment = SET vendor +Description = Entrust (2 23 42 9 23) + +OID = 06 04 67 2A 09 18 +Comment = SET vendor +Description = VIAnet (2 23 42 9 24) + +OID = 06 04 67 2A 09 19 +Comment = SET vendor +Description = III (2 23 42 9 25) + +OID = 06 04 67 2A 09 1A +Comment = SET vendor +Description = OpenMarket (2 23 42 9 26) + +OID = 06 04 67 2A 09 1B +Comment = SET vendor +Description = Lexem (2 23 42 9 27) + +OID = 06 04 67 2A 09 1C +Comment = SET vendor +Description = Intertrader (2 23 42 9 28) + +OID = 06 04 67 2A 09 1D +Comment = SET vendor +Description = Persimmon (2 23 42 9 29) + +OID = 06 04 67 2A 09 1E +Comment = SET vendor +Description = NABLE (2 23 42 9 30) + +OID = 06 04 67 2A 09 1F +Comment = SET vendor +Description = espace-net (2 23 42 9 31) + +OID = 06 04 67 2A 09 20 +Comment = SET vendor +Description = Hitachi (2 23 42 9 32) + +OID = 06 04 67 2A 09 21 +Comment = SET vendor +Description = Microsoft (2 23 42 9 33) + +OID = 06 04 67 2A 09 22 +Comment = SET vendor +Description = NEC (2 23 42 9 34) + +OID = 06 04 67 2A 09 23 +Comment = SET vendor +Description = Mitsubishi (2 23 42 9 35) + +OID = 06 04 67 2A 09 24 +Comment = SET vendor +Description = NCR (2 23 42 9 36) + +OID = 06 04 67 2A 09 25 +Comment = SET vendor +Description = e-COMM (2 23 42 9 37) + +OID = 06 04 67 2A 09 26 +Comment = SET vendor +Description = Gemplus (2 23 42 9 38) + +OID = 06 03 67 2A 0A +Comment = SET +Description = national (2 23 42 10) + +OID = 06 05 67 2A 0A 81 40 +Comment = SET national +Description = Japan (2 23 42 10 192) + +# Draft SET. These were invented for testing in pre-1.0 drafts, but have +# been used nonetheless by implementors + +OID = 06 04 86 8D 6F 02 +Comment = SET. Deprecated, use (2 23 42 7 0) instead +Description = hashedRootKey (2 54 1775 2) +Warning + +OID = 06 04 86 8D 6F 03 +Comment = SET. Deprecated, use (2 23 42 7 0) instead +Description = certificateType (2 54 1775 3) +Warning + +OID = 06 04 86 8D 6F 04 +Comment = SET. Deprecated, use (2 23 42 7 0) instead +Description = merchantData (2 54 1775 4) +Warning + +OID = 06 04 86 8D 6F 05 +Comment = SET. Deprecated, use (2 23 42 7 0) instead +Description = cardCertRequired (2 54 1775 5) +Warning + +OID = 06 04 86 8D 6F 06 +Comment = SET. Deprecated, use (2 23 42 7 0) instead +Description = tunneling (2 54 1775 6) +Warning + +OID = 06 04 86 8D 6F 07 +Comment = SET. Deprecated, use (2 23 42 7 0) instead +Description = setQualifier (2 54 1775 7) +Warning + +OID = 06 04 86 8D 6F 63 +Comment = SET. Deprecated, use (2 23 42 7 0) instead +Description = set-data (2 54 1775 99) +Warning + +# Apple + +OID = 06 06 2A 86 48 86 F7 63 +Comment = Apple Computer, Inc. +Description = apple (1 2 840 113635) + +OID = 6 07 2A 86 48 86 F7 63 64 +Comment = Apple Data Security +Description = appleDataSecurity (1 2 840 113635 100) + +OID = 06 08 2A 86 48 86 F7 63 64 01 +Comment = Apple Trust Policy +Description = appleTrustPolicy (1 2 840 113635 100 1) + +OID = 06 08 2A 86 48 86 F7 63 64 02 +Comment = Apple Security Algorithms +Description = appleSecurityAlgorithm (1 2 840 113635 100 2) + +OID = 06 09 2A 86 48 86 F7 63 64 02 01 +Comment = Apple FEE +Description = fee (1 2 840 113635 100 2 1) + +OID = 06 09 2A 86 48 86 F7 63 64 02 02 +Comment = Apple ASC +Description = asc (1 2 840 113635 100 2 2) + +OID = 06 09 2A 86 48 86 F7 63 64 02 03 +Comment = Apple FEE/MD5 signature +Description = feeMD5 (1 2 840 113635 100 2 3) + +OID = 06 09 2A 86 48 86 F7 63 64 02 04 +Comment = Apple FEE/SHA1 signature +Description = feeSHA1 (1 2 840 113635 100 2 4) + +OID = 06 09 2A 86 48 86 F7 63 64 02 05 +Comment = Apple FEED encryption +Description = appleFeed (1 2 840 113635 100 2 5) + +OID = 06 09 2A 86 48 86 F7 63 64 02 06 +Comment = Apple FEEDExp signature +Description = appleFeedExp (1 2 840 113635 100 2 6) + +OID = 06 09 2A 86 48 86 F7 63 64 02 07 +Comment = Apple FEE/ECDSA signature +Description = feeECDSA (1 2 840 113635 100 2 7) + +OID = 06 08 2A 86 48 86 F7 63 64 03 +Comment = Apple .Mac Certificate arc +Description = appleDotMacCertificate (OID 1 2 840 113635 100 3) + +OID = 06 09 2A 86 48 86 F7 63 64 03 02 +Comment = Apple .Mac Certificate Extension arc +Description = dotMacCertificateExtension (OID 1 2 840 113635 100 3 2) + +OID = 06 0A 2A 86 48 86 F7 63 64 03 02 01 +Comment = Apple .Mac Certificate Identity Extension +Description = dotMacCertExtensionIdentity (OID 1 2 840 113635 100 3 2 1) + +OID = 06 0A 2A 86 48 86 F7 63 64 03 02 02 +Comment = Apple .Mac Certificate Email Sign Extension +Description = dotMacCertExtensionEmailSign (OID 1 2 840 113635 100 3 2 2) + +OID = 06 0A 2A 86 48 86 F7 63 64 03 02 03 +Comment = Apple .Mac Certificate Email Encrypt Extension +Description = dotMacCertExtensionEmailEncrypt (OID 1 2 840 113635 100 3 2 3) + +OID = 06 08 2A 86 48 86 F7 63 64 04 +Comment = Apple Extended Key Usage arc +Description = appleExtendedKeyUsage (OID 1 2 840 113635 100 4) + +OID = 06 09 2A 86 48 86 F7 63 64 04 01 +Comment = Apple Code Signing Extended Key Usage +Description = appleCodeSigning (OID 1 2 840 113635 100 4 1) + +OID = 06 0A 2A 86 48 86 F7 63 64 04 01 02 +Comment = Apple Software Update Signing Extended Key Usage +Description = appleSoftwareUpdateSigning (OID 1 2 840 113635 100 4 1 2) + +OID = 06 0A 2A 86 48 86 F7 63 64 04 01 03 +Comment = Apple Third Party Code Signing Extended Key Usage +Description = appleThirdPartyCodeSigning (OID 1 2 840 113635 100 4 1 3) + +OID = 06 0A 2A 86 48 86 F7 63 64 04 01 04 +Comment = Apple Resource Signing Extended Key Usage +Description = appleResourceSigning (OID 1 2 840 113635 100 4 1 4) + +OID = 06 0A 2A 86 48 86 F7 63 64 04 01 01 +Comment = Apple Code Signing DEVELOPMENT Extended Key Usage +Description = appleCodeSigningDevelopment (OID 1 2 840 113635 100 4 1 1) + +OID = 06 09 2A 86 48 86 F7 63 64 04 02 +Comment = Apple iChat Signing Extended Key Usage +Description = appleiChatSigning (OID 1 2 840 113635 100 4 2) + +OID = 06 09 2A 86 48 86 F7 63 64 04 03 +Comment = Apple Code Signing Extended Key Usage +Description = appleiChatEncryption (OID 1 2 840 113635 100 4 3) + +OID = 06 09 2A 86 48 86 F7 63 64 04 04 +Comment = Apple System Identity Extended Key Usage +Description = appleSystemIdentity (OID 1 2 840 113635 100 4 4) + +OID = 06 08 2A 86 48 86 F7 63 64 05 +Comment = Apple Certificate Policy arc +Description = Apple Certificate Policy arc (OID 1 2 840 113635 100 5) + +OID = 06 09 2A 86 48 86 F7 63 64 05 01 +Comment = Apple Certificate Policy +Description = Apple Certificate Policy (OID 1 2 840 113635 100 5 1) + +OID = 06 09 2A 86 48 86 F7 63 64 05 02 +Comment = Apple .Mac Certificate Policy +Description = Apple .Mac Certificate Policy (OID 1 2 840 113635 100 5 2) + +# Extended key usage +OID = 06 04 55 1D 25 03 +Comment = Code Signing +Description = id-kp-codeSigning (OID 2 5 29 37 3) + +# Intel's CDSA-specific SHA1withECDSA +OID = 06 0B 60 86 48 01 86 F8 4D 02 02 05 51 +Comment = CDSA SHA1 with ECDSA +Description = sha1WithECDSA (OID 2 16 840 1 113741 2 2 5 81) + +# Microsoft Cert Authority Renewal Version +OID = 06 09 2B 06 01 04 01 82 37 15 01 +Comment = Microsoft Cert Authority Renewal Version +Description = certSrv-ca-version (OID 1 3 6 1 4 1 311 21 1) + +# Fictitious US DOD CRL entry extension +OID = 06 09 60 86 48 01 65 02 01 0C 02 +Comment = Fictitious US DOD CRL entry extension +Description = id-test-extension (OID 2 16 840 1 101 2 1 12 2) + +# Microsoft Kerberos +OID = 06 09 2A 86 48 82 F7 12 01 02 02 +Comment = Microsoft SPNEGO/Kerberos +Description = microsoft-kerberos (OID 1 2 840 48018 1 2 2) + +# Kerberos V5 +OID = 06 09 2A 86 48 86 F7 12 01 02 02 +Comment = Kerberos V5 +Description = kerberos-v5 (OID 1 2 840 113554 1 2 2) + +# IANA SPNEGO, RFC 2478 +OID = 06 06 2B 06 01 05 05 02 +Comment = IANA SPNEGO +Description = spnego (OID 1 3 6 1 5 5 2) + +# MIT user-to-user kerberos +OID = 06 0A 2A 86 48 86 F7 12 01 02 02 03 +Comment = MIT User-to-user Kerberos +Description = user-to-user-kerberos (OID 1.2.840.113554.1.2.2.3) + +OID = 06 0A 2B 06 01 04 01 82 37 02 02 0A +Comment = Microsoft NTLMSSP +Description = ntlmssp (OID 1.3.6.1.4.1.311.2.2.10) + +# AES base +OID = 06 08 60 86 48 01 65 03 04 01 +Comment = aes +Description = aes (OID 2 16 840 1 101 3 4 1) + +# AES, 128 bit key +OID = 06 09 60 86 48 01 65 03 04 01 01 +Comment = id-aes128-ECB +Description = id-aes128-ECB (OID 2 16 840 1 101 3 4 1 1) + +OID = 06 09 60 86 48 01 65 03 04 01 02 +Comment = id-aes128-CBC +Description = id-aes128-CBC (OID 2 16 840 1 101 3 4 1 2) + +OID = 06 09 60 86 48 01 65 03 04 01 03 +Comment = id-aes128-OFB +Description = id-aes128-OFB (OID 2 16 840 1 101 3 4 1 3) + +OID = 06 09 60 86 48 01 65 03 04 01 04 +Comment = id-aes128-CFB +Description = id-aes128-CFB (OID 2 16 840 1 101 3 4 1 4) + +# AES, 192 bit key +OID = 06 09 60 86 48 01 65 03 04 01 15 +Comment = id-aes192-ECB +Description = id-aes192-ECB (OID 2 16 840 1 101 3 4 1 21) + +OID = 06 09 60 86 48 01 65 03 04 01 16 +Comment = id-aes192-CBC +Description = id-aes192-CBC (OID 2 16 840 1 101 3 4 1 22) + +OID = 06 09 60 86 48 01 65 03 04 01 17 +Comment = id-aes192-OFB +Description = id-aes192-OFB (OID 2 16 840 1 101 3 4 1 23) + +OID = 06 09 60 86 48 01 65 03 04 01 18 +Comment = id-aes192-CFB +Description = id-aes192-CFB (OID 2 16 840 1 101 3 4 1 24) + +# AES, 256 bit key +OID = 06 09 60 86 48 01 65 03 04 01 29 +Comment = id-aes256-ECB +Description = id-aes256-ECB (OID 2 16 840 1 101 3 4 1 41) + +OID = 06 09 60 86 48 01 65 03 04 01 2A +Comment = id-aes256-CBC +Description = id-aes256-CBC (OID 2 16 840 1 101 3 4 1 42) + +OID = 06 09 60 86 48 01 65 03 04 01 2B +Comment = id-aes256-OFB +Description = id-aes256-OFB (OID 2 16 840 1 101 3 4 1 43) + +OID = 06 09 60 86 48 01 65 03 04 01 2C +Comment = id-aes256-CFB +Description = id-aes256-CFB (OID 2 16 840 1 101 3 4 1 44) + +OID = 06 08 2B 06 01 04 01 82 37 14 +Comment = Microsoft Enrollment Infrastructure +Description = MicrosoftEnrollmentInfrastructure (OID 1 3 6 1 4 1 311 20) + +OID = 06 09 2B 06 01 04 01 82 37 14 01 +Comment = Auto-Enroll CTL Usage +Description = msCtlUsage (OID 1 3 6 1 4 1 311 20 1) + +OID = 06 09 2B 06 01 04 01 82 37 14 02 +Comment = Enrollment Certificate Type +Description = msCertType (OID 1 3 6 1 4 1 311 20 2) + +OID = 06 0A 2B 06 01 04 01 82 37 14 02 01 +Comment = Enrollment Agent +Description = msEnrollmentAgent (OID 1 3 6 1 4 1 311 20 2 1) + +OID = 06 0A 2B 06 01 04 01 82 37 14 02 02 +Comment = Smartcard Logon +Description = msSmartCardLogon (OID 1 3 6 1 4 1 311 20 2 2) + +OID = 06 0A 2B 06 01 04 01 82 37 14 02 03 +Comment = NT Principal Name +Description = NTPrincipalName (OID 1 3 6 1 4 1 311 20 2 3) + +OID = 06 08 2B 06 01 05 05 07 01 03 +Comment = Qualified Certificate Statements +Description = id-pe-qcStatements (OID 1 3 6 1 5 5 7 1 3) + +OID = 06 07 2B 06 01 05 05 07 0B +Comment = Qualified Certificate Statements +Description = id-qcs (OID 1 3 6 1 5 5 7 11) + +# addenda for Qualified Cert Statements + +OID = 06 07 2B 06 01 05 05 07 01 +Comment = Qualified Certificate Statements +Description = id-pe (OID 1 3 6 1 5 5 7 1) + +OID = 06 07 2B 06 01 05 05 07 09 +Comment = Personal Data Attributes +Description = id-pda (OID 1 3 6 1 5 5 7 9) + +OID = 06 08 2B 06 01 05 05 07 09 +Comment = Personal Data Attributes +Description = id-pda-dateOfBirth (OID 1 3 6 1 5 5 7 9 1) + +OID = 06 08 2B 06 01 05 05 07 09 +Comment = Personal Data Attributes +Description = id-pda-placeOfBirth (OID 1 3 6 1 5 5 7 9 2) + +OID = 06 08 2B 06 01 05 05 07 09 +Comment = Personal Data Attributes +Description = id-pda-gender (OID 1 3 6 1 5 5 7 9 3) + +OID = 06 08 2B 06 01 05 05 07 09 +Comment = Personal Data Attributes +Description = id-pda-countryOfCitizenship (OID 1 3 6 1 5 5 7 9 4) + +OID = 06 08 2B 06 01 05 05 07 09 +Comment = Personal Data Attributes +Description = id-pda-countryOfResidence (OID 1 3 6 1 5 5 7 9 5) + +OID = 06 08 2B 06 01 05 05 07 0B 01 +Comment = Qualified Certificate Statement QCSyntax-v1 +Description = id-qcs-pkixQCSyntax-v1 (OID 1 3 6 1 5 5 7 11 1) + +OID = 06 08 2B 06 01 05 05 07 0B 02 +Comment = Qualified Certificate Statement QCSyntax-v2 +Description = id-qcs-pkixQCSyntax-v2 (OID 1 3 6 1 5 5 7 11 2) + +# end Qualified Cert Statements addenda + +OID = 06 06 04 00 8E 46 01 01 +Comment = qcs QcCompliance +Description = id-etsi-qcs-QcCompliance (OID 0 4 0 1862 1 1) + +OID = 06 09 60 86 48 01 65 03 04 02 04 +Comment = SHA224 +Description = id-sha224 (OID 2 16 840 1 101 3 4 2 4 + +OID = 06 09 60 86 48 01 65 03 04 02 01 +Comment = SHA256 +Description = id-sha256 (OID 2 16 840 1 101 3 4 2 1 + +OID = 06 09 60 86 48 01 65 03 04 02 02 +Comment = SHA384 +Description = id-sha384 (OID 2 16 840 1 101 3 4 2 2 + +OID = 06 09 60 86 48 01 65 03 04 02 03 +Comment = SHA512 +Description = id-sha512 (OID 2 16 840 1 101 3 4 2 3 + +OID = 06 09 2A 86 48 86 F7 0D 01 01 0E +Comment = PKCS #1 +Description = sha224WithRSAEncryption (1 2 840 113549 1 1 14) + +OID = 06 09 2A 86 48 86 F7 0D 01 01 0B +Comment = PKCS #1 +Description = sha256WithRSAEncryption (1 2 840 113549 1 1 11) + +OID = 06 09 2A 86 48 86 F7 0D 01 01 0C +Comment = PKCS #1 +Description = sha384WithRSAEncryption (1 2 840 113549 1 1 12) + +OID = 06 09 2A 86 48 86 F7 0D 01 01 0D +Comment = PKCS #1 +Description = sha512WithRSAEncryption (1 2 840 113549 1 1 13) + +OID = 06 09 2A 86 48 86 F7 0D 01 01 06 +Comment = PKCS #1 +Description = rsaEncryptionWithOAEPPaddingSET (1 2 840 113549 1 1 6) + +OID = 06 09 2A 86 48 86 F7 0D 01 01 07 +Comment = PKCS #1 +Description = rsaEncryptionWithOAEPPadding (1 2 840 113549 1 1 7) + +OID = 06 09 2A 86 48 86 F7 0D 01 01 09 +Comment = PKCS #1 +Description = id-pSpecified (1 2 840 113549 1 1 9) + +OID = 06 09 2A 86 48 86 F7 0D 01 01 0A +Comment = PKCS #1 +Description = id-RSASSA-PSS (1 2 840 113549 1 1 10) + +# TP policy OIDS +OID = 06 09 2A 86 48 86 F7 63 64 01 01 +Comment = Apple iSign +Description = iSignTP (1 2 840 113635 100 1 1) + +OID = 06 09 2A 86 48 86 F7 63 64 01 02 +Comment = Apple Basic X509 TP +Description = Apple Basic X509 TP (1 2 840 113635 100 1 2) + +OID = 06 09 2A 86 48 86 F7 63 64 01 03 +Comment = Apple TP +Description = Apple SSL TP (1 2 840 113635 100 1 3) + +OID = 06 09 2A 86 48 86 F7 63 64 01 06 +Comment = Apple TP +Description = Apple CRL TP (1 2 840 113635 100 1 6) + +OID = 06 09 2A 86 48 86 F7 63 64 01 07 +Comment = Apple TP +Description = Apple OCSP TP (1 2 840 113635 100 1 7) + +OID = 06 09 2A 86 48 86 F7 63 64 01 08 +Comment = Apple TP +Description = Apple SMIME TP (1 2 840 113635 100 1 8) + +OID = 06 09 2A 86 48 86 F7 63 64 01 09 +Comment = Apple TP +Description = Apple EAP TP (1 2 840 113635 100 1 9) + +OID = 06 09 2A 86 48 86 F7 63 64 01 0A +Comment = Apple TP +Description = Apple SW Update Signing TP (1 2 840 113635 100 1 10) + +OID = 06 09 2A 86 48 86 F7 63 64 01 0B +Comment = Apple TP +Description = Apple IPSec TP (1 2 840 113635 100 1 11) + +OID = 06 09 2A 86 48 86 F7 63 64 01 0C +Comment = Apple TP +Description = Apple iChat TP (1 2 840 113635 100 1 12) + +OID = 06 09 2A 86 48 86 F7 63 64 01 0D +Comment = Apple TP +Description = Apple Resource Signing TP (1 2 840 113635 100 1 13) + +OID = 06 09 2A 86 48 86 F7 63 64 01 0E +Comment = Apple TP +Description = Apple Kerberos PKINIT Client TP (1 2 840 113635 100 1 14) + +OID = 06 09 2A 86 48 86 F7 63 64 01 0F +Comment = Apple TP +Description = Apple Kerberos PKINIT Server TP (1 2 840 113635 100 1 15) + +OID = 06 09 2A 86 48 86 F7 63 64 01 10 +Comment = Apple TP +Description = Apple Code Signing TP (1 2 840 113635 100 1 16) + +# Kerberos/PKINIT +OID = 06 07 2B 06 01 05 02 03 01 +Comment = Kerberos/PKINIT +Description = id-pkinit-authData (1 3 6 1 5 2 3 1) + +OID = 06 07 2B 06 01 05 02 03 02 +Comment = Kerberos/PKINIT +Description = id-pkinit-DHKeyData (1 3 6 1 5 2 3 2) + +OID = 06 07 2B 06 01 05 02 03 03 +Comment = Kerberos/PKINIT +Description = id-pkinit-rkeyData (1 3 6 1 5 2 3 3) + +OID = 06 07 2B 06 01 05 02 03 04 +Comment = Kerberos/PKINIT +Description = id-pkinit-KPClientAuth (1 3 6 1 5 2 3 4) + +OID = 06 07 2B 06 01 05 02 03 05 +Comment = Kerberos/PKINIT +Description = id-pkinit-KPKdc (1 3 6 1 5 2 3 5) + +# S/MIME signed attributes +OID = 06 0B 2A 86 48 86 F7 0D 01 09 10 02 0B +Comment = EncryptionKeyPreference +Description = Encryption Key Preference (1 2 840 113549 1 9 16 2 11) + +OID = 06 09 2B 06 01 04 01 82 37 10 04 +Comment = EncryptionKeyPreference, MS +Description = Encryption Key Preference, MS version (1 3 6 1 4 1 311 16 4) + +OID = 06 09 2A 86 48 86 F7 0D 01 09 05 +Comment = S/MIME Signing Time +Description = S/MIME Signing Time (1 2 840 113549 1 9 5) + +OID = 06 09 2A 86 48 86 F7 63 64 01 0E +Comment = Apple PKINIT Client Policy +Description = Apple PKINIT Client Policy ( 1.2.840.113635.100.1.14 ) + +OID = 06 09 2A 86 48 86 F7 63 64 01 0F +Comment = Apple PKINIT Server Policy +Description = Apple PKINIT Server Policy ( 1.2.840.113635.100.1.15 ) + +# More ANSI X9.62 + +OID = 06 06 2A 86 48 CE 3D 03 +Comment = ANSI X9.62 +Description = ellipticCurve (1 2 840 10045 3) + +OID = 06 07 2A 86 48 CE 3D 03 00 +Comment = ANSI X9.62 +Description = c-TwoCurve (1 2 840 10045 3 0) + +OID = 06 07 2A 86 48 CE 3D 03 01 +Comment = ANSI X9.62 +Description = primeCurve (1 2 840 10045 3 1) + +OID = 06 08 2A 86 48 CE 3D 03 00 01 +Comment = ANSI X9.62 +Description = c2pnb163v1 (1 2 840 10045 3 0 1) + +OID = 06 08 2A 86 48 CE 3D 03 00 02 +Comment = ANSI X9.62 +Description = c2pnb163v2 (1 2 840 10045 3 0 2) + +OID = 06 08 2A 86 48 CE 3D 03 00 03 +Comment = ANSI X9.62 +Description = c2pnb163v3 (1 2 840 10045 3 0 3) + +OID = 06 08 2A 86 48 CE 3D 03 00 04 +Comment = ANSI X9.62 +Description = c2pnb176w1 (1 2 840 10045 3 0 4) + +OID = 06 08 2A 86 48 CE 3D 03 00 05 +Comment = ANSI X9.62 +Description = c2tnb191v1 (1 2 840 10045 3 0 5) + +OID = 06 08 2A 86 48 CE 3D 03 00 06 +Comment = ANSI X9.62 +Description = c2tnb191v2 (1 2 840 10045 3 0 6) + +OID = 06 08 2A 86 48 CE 3D 03 00 07 +Comment = ANSI X9.62 +Description = c2tnb191v3 (1 2 840 10045 3 0 7) + +OID = 06 08 2A 86 48 CE 3D 03 00 08 +Comment = ANSI X9.62 +Description = c2onb191v4 (1 2 840 10045 3 0 8) + +OID = 06 08 2A 86 48 CE 3D 03 00 09 +Comment = ANSI X9.62 +Description = c2onb191v5 (1 2 840 10045 3 0 9) + +OID = 06 08 2A 86 48 CE 3D 03 00 0A +Comment = ANSI X9.62 +Description = c2pnb208w1 (1 2 840 10045 3 0 10) + +OID = 06 08 2A 86 48 CE 3D 03 00 0B +Comment = ANSI X9.62 +Description = c2tnb239v1 (1 2 840 10045 3 0 11) + +OID = 06 08 2A 86 48 CE 3D 03 00 0C +Comment = ANSI X9.62 +Description = c2tnb239v2 (1 2 840 10045 3 0 12) + +OID = 06 08 2A 86 48 CE 3D 03 00 0D +Comment = ANSI X9.62 +Description = c2tnb239v3 (1 2 840 10045 3 0 13) + +OID = 06 08 2A 86 48 CE 3D 03 00 0E +Comment = ANSI X9.62 +Description = c2onb239v4 (1 2 840 10045 3 0 14) + +OID = 06 08 2A 86 48 CE 3D 03 00 0F +Comment = ANSI X9.62 +Description = c2onb239v5 (1 2 840 10045 3 0 15) + +OID = 06 08 2A 86 48 CE 3D 03 00 10 +Comment = ANSI X9.62 +Description = c2pnb272w1 (1 2 840 10045 3 0 16) + +OID = 06 08 2A 86 48 CE 3D 03 00 11 +Comment = ANSI X9.62 +Description = c2pnb304w1 (1 2 840 10045 3 0 17) + +OID = 06 08 2A 86 48 CE 3D 03 00 12 +Comment = ANSI X9.62 +Description = c2tnb359v1 (1 2 840 10045 3 0 18) + +OID = 06 08 2A 86 48 CE 3D 03 00 13 +Comment = ANSI X9.62 +Description = c2pnb368w1 (1 2 840 10045 3 0 19) + +OID = 06 08 2A 86 48 CE 3D 03 00 14 +Comment = ANSI X9.62 +Description = c2tnb431r1 (1 2 840 10045 3 0 20) + +# this one renamed from prime192v1 (in X9.62) to secp192r1 +# (Certicom SEC 2) +OID = 06 08 2A 86 48 CE 3D 03 01 01 +Comment = ANSI X9.62 +Description = secp192r1 (1 2 840 10045 3 1 1) + +OID = 06 08 2A 86 48 CE 3D 03 01 02 +Comment = ANSI X9.62 +Description = prime192v2 (1 2 840 10045 3 1 2) + +OID = 06 08 2A 86 48 CE 3D 03 01 03 +Comment = ANSI X9.62 +Description = prime192v3 (1 2 840 10045 3 1 3) + +OID = 06 08 2A 86 48 CE 3D 03 01 04 +Comment = ANSI X9.62 +Description = prime239v1 (1 2 840 10045 3 1 4) + +OID = 06 08 2A 86 48 CE 3D 03 01 05 +Comment = ANSI X9.62 +Description = prime239v2 (1 2 840 10045 3 1 5) + +OID = 06 08 2A 86 48 CE 3D 03 01 06 +Comment = ANSI X9.62 +Description = prime239v3 (1 2 840 10045 3 1 6) + +# X9.62: prime256v1 Certicom SEC 2: +OID = 06 08 2A 86 48 CE 3D 03 01 07 +Comment = ANSI X9.62 +Description = secp256r1 (1 2 840 10045 3 1 7) + +OID = 06 06 2A 86 48 CE 3D 04 +Comment = ANSI X9.62 +Description = ecSigType (1 2 840 10045 4) + +OID = 06 07 2A 86 48 CE 3D 04 01 +Comment = ANSI X9.62 +Description = ecdsa-with-SHA1 (1 2 840 10045 4 1) + +OID = 06 08 2A 86 48 CE 3D 04 03 01 +Comment = FPKI +Description = ecdsa-with-SHA224 (1 2 840 10045 4 3 1) + +OID = 06 08 2A 86 48 CE 3D 04 03 02 +Comment = FPKI +Description = ecdsa-with-SHA256 (1 2 840 10045 4 3 2) + +OID = 06 08 2A 86 48 CE 3D 04 03 03 +Comment = FPKI +Description = ecdsa-with-SHA384 (1 2 840 10045 4 3 3) + +OID = 06 08 2A 86 48 CE 3D 04 03 04 +Comment = FPKI +Description = ecdsa-with-SHA512 (1 2 840 10045 4 3 4) + +# +# This one is used when the disgest algorithm is explicitly +# specified in a separate alg parameter +# +OID = 06 07 2A 86 48 CE 3D 04 03 +Comment = FPKI +Description = ecdsa-with-specified (1 2 840 10045 4 3) + +# +# Certicom Elliptic Curves from SEC 2 +# +OID = 06 03 2B 81 04 +Comment = Certicom SEC 2 +Description = certicom-arc (1 3 132) + +OID = 06 04 2B 81 04 00 +Comment = Certicom SEC 2 +Description = ellipticCurve (1 3 132 0) + +OID = 06 05 2B 81 04 00 06 +Comment = Certicom SEC 2 +Description = secp112r1 (1 3 132 0 6) + +OID = 06 05 2B 81 04 00 07 +Comment = Certicom SEC 2 +Description = secp112r2 (1 3 132 0 7) + +OID = 06 05 2B 81 04 00 1C +Comment = Certicom SEC 2 +Description = secp128r1 (1 3 132 0 28) + +OID = 06 05 2B 81 04 00 1D +Comment = Certicom SEC 2 +Description = secp128r2 (1 3 132 0 29) + +OID = 06 05 2B 81 04 00 09 +Comment = Certicom SEC 2 +Description = secp160k1 (1 3 132 0 9) + +OID = 06 05 2B 81 04 00 08 +Comment = Certicom SEC 2 +Description = secp160r1 (1 3 132 0 8) + +OID = 06 05 2B 81 04 00 1E +Comment = Certicom SEC 2 +Description = secp160r2 (1 3 132 0 30) + +OID = 06 05 2B 81 04 00 1F +Comment = Certicom SEC 2 +Description = secp192k1 (1 3 132 0 31) + +# note secp192r1 defined above in the ANSI X9.62 arc + +OID = 06 05 2B 81 04 00 20 +Comment = Certicom SEC 2 +Description = secp224k1 (1 3 132 0 32) + +OID = 06 05 2B 81 04 00 21 +Comment = Certicom SEC 2 +Description = secp224r1 (1 3 132 0 33) + +OID = 06 05 2B 81 04 00 0A +Comment = Certicom SEC 2 +Description = secp256k1 (1 3 132 0 10) + +# note secp256r1 defined above in the ANSI X9.62 arc + +OID = 06 05 2B 81 04 00 22 +Comment = Certicom SEC 2 +Description = secp384r1 (1 3 132 0 34) + +OID = 06 05 2B 81 04 00 23 +Comment = Certicom SEC 2 +Description = secp521r1 (1 3 132 0 35) + +# characteristic 2 curves + +OID = 06 05 2B 81 04 00 04 +Comment = Certicom SEC 2 +Description = sect113r1 (1 3 132 0 4) + +OID = 06 05 2B 81 04 00 05 +Comment = Certicom SEC 2 +Description = sect113r2 (1 3 132 0 5) + +OID = 06 05 2B 81 04 00 16 +Comment = Certicom SEC 2 +Description = sect131r1 (1 3 132 0 22) + +OID = 06 05 2B 81 04 00 17 +Comment = Certicom SEC 2 +Description = sect131r2 (1 3 132 0 23) + +OID = 06 05 2B 81 04 00 01 +Comment = Certicom SEC 2 +Description = sect163k1 (1 3 132 0 1) + +OID = 06 05 2B 81 04 00 02 +Comment = Certicom SEC 2 +Description = sect163r1 (1 3 132 0 2) + +OID = 06 05 2B 81 04 00 0F +Comment = Certicom SEC 2 +Description = sect163r2 (1 3 132 0 15) + +OID = 06 05 2B 81 04 00 18 +Comment = Certicom SEC 2 +Description = sect193r1 (1 3 132 0 24) + +OID = 06 05 2B 81 04 00 19 +Comment = Certicom SEC 2 +Description = sect193r2 (1 3 132 0 25) + +OID = 06 05 2B 81 04 00 1A +Comment = Certicom SEC 2 +Description = sect233k1 (1 3 132 0 26) + +OID = 06 05 2B 81 04 00 1B +Comment = Certicom SEC 2 +Description = sect233r1 (1 3 132 0 27) + +OID = 06 05 2B 81 04 00 03 +Comment = Certicom SEC 2 +Description = sect239k1 (1 3 132 0 3) + +OID = 06 05 2B 81 04 00 10 +Comment = Certicom SEC 2 +Description = sect283k1 (1 3 132 0 16) + +OID = 06 05 2B 81 04 00 11 +Comment = Certicom SEC 2 +Description = sect283r1 (1 3 132 0 17) + +OID = 06 05 2B 81 04 00 24 +Comment = Certicom SEC 2 +Description = sect409k1 (1 3 132 0 36) + +OID = 06 05 2B 81 04 00 25 +Comment = Certicom SEC 2 +Description = sect409r1 (1 3 132 0 37) + +OID = 06 05 2B 81 04 00 26 +Comment = Certicom SEC 2 +Description = sect571k1 (1 3 132 0 38) + +OID = 06 05 2B 81 04 00 27 +Comment = Certicom SEC 2 +Description = sect571r1 (1 3 132 0 39) + +# X9.63 addendum for ECDH + +OID = 06 07 2B 81 05 10 86 48 3F +Comment = X9.63 +Description = x9-63 (1 3 133 16 840 63) + +OID = 06 08 2B 81 05 10 86 48 3F 00 +Comment = X9.63 +Description = x9-63-scheme (1 3 133 16 840 63 0) + +OID = 06 09 2B 81 05 10 86 48 3F 00 02 +Comment = X9.63 +Description = dhSinglePass-stdDH-sha1kdf-scheme (1 3 133 16 840 63 0 2) + +OID = 06 09 2B 81 05 10 86 48 3F 00 03 +Comment = X9.63 +Description = dhSinglePass-cofactorDH-sha1kdf-scheme (1 3 133 16 840 63 0 3) + +OID = 06 09 2B 81 05 10 86 48 3F 00 10 +Comment = X9.63 +Description = mqvSinglePass-sha1kdf-scheme (1 3 133 16 840 63 0 16) + +# End of Fahnenstange diff --git a/SecurityTests/clxutils/extenGrab/Makefile b/SecurityTests/clxutils/extenGrab/Makefile new file mode 100644 index 00000000..629138bd --- /dev/null +++ b/SecurityTests/clxutils/extenGrab/Makefile @@ -0,0 +1,54 @@ +# name of executable to build +EXECUTABLE=extenGrab +# C++ source (with .cpp extension) +CPSOURCE= extenGrab.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/clxutils/extenGrab/extenGrab.cpp b/SecurityTests/clxutils/extenGrab/extenGrab.cpp new file mode 100644 index 00000000..01410d34 --- /dev/null +++ b/SecurityTests/clxutils/extenGrab/extenGrab.cpp @@ -0,0 +1,124 @@ +/* + * extenGrab - write the unparsed extension blobs of a specified + * cert to files for external examination + */ +#include +#include +#include +#include +#include +#include +#include +#include + +static void usage(char **argv) +{ + printf("Usage: %s certFile outFileBase [r for CRL, default is cert]\n", + argv[0]); + exit(1); +} + +/* + * How many items in a NULL-terminated array of pointers? + */ +static unsigned nssArraySize( + const void **array) +{ + unsigned count = 0; + if (array) { + while (*array++) { + count++; + } + } + return count; +} + +int main(int argc, char **argv) +{ + if(argc < 3) { + usage(argv); + } + + bool doCert = true; + NSS_Certificate signedCert; + NSS_Crl signedCrl; + void *decodeTarget; + const SecAsn1Template *templ; + NSS_CertExtension ***extenp; + + for(int arg=3; argextnId.Data, exten->extnId.Length, oidStr); + printf("Extension %u : %s\n", dex, oidStr); + sprintf(outFileName, "%s_%u", outBase, dex); + if(writeFile(outFileName, exten->value.Data, exten->value.Length)) { + printf("***Error writing %s. Aborting.\n", + outFileName); + exit(1); + } + else { + printf("...wrote %lu bytes to %s\n", + exten->value.Length, outFileName); + } + } + SecAsn1CoderRelease(coder); + printf("..done.\n"); + return 0; +} diff --git a/SecurityTests/clxutils/extenTest/Makefile b/SecurityTests/clxutils/extenTest/Makefile new file mode 100644 index 00000000..ef2b67c7 --- /dev/null +++ b/SecurityTests/clxutils/extenTest/Makefile @@ -0,0 +1,54 @@ +# name of executable to build +EXECUTABLE=extenTest +# C++ source (with .cpp extension) +CPSOURCE= extenTest.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/clxutils/extenTest/extenTest.cpp b/SecurityTests/clxutils/extenTest/extenTest.cpp new file mode 100644 index 00000000..48f3f889 --- /dev/null +++ b/SecurityTests/clxutils/extenTest/extenTest.cpp @@ -0,0 +1,1546 @@ +/* + * extenTest - verify encoding and decoding of extensions. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define KEY_ALG CSSM_ALGID_RSA +#define SIG_ALG CSSM_ALGID_SHA1WithRSA +#define KEY_SIZE_BITS CSP_RSA_KEY_SIZE_DEFAULT +#define SUBJ_KEY_LABEL "subjectKey" + +#define LOOPS_DEF 10 + +static void usage(char **argv) +{ + printf("Usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" e=extenSpec (default = all)\n"); + printf(" k keyUsage\n"); + printf(" b basicConstraints\n"); + printf(" x extendedKeyUsage\n"); + printf(" s subjectKeyId\n"); + printf(" a authorityKeyId\n"); + printf(" t SubjectAltName\n"); + printf(" i IssuerAltName\n"); + printf(" c certPolicies\n"); + printf(" n netscapeCertType\n"); + printf(" p CRLDistributionPoints\n"); + printf(" A AuthorityInfoAccess\n"); + printf(" S SubjectInfoAccess\n"); + printf(" q QualifiedCertStatements\n"); + printf(" w(rite blobs)\n"); + printf(" f=fileName (default is extension-specific file name)\n"); + printf(" d(isplay certs)\n"); + printf(" l=loops (default = %d)\n", LOOPS_DEF); + printf(" p(ause on each loop)\n"); + printf(" P(ause on each cert)\n"); + exit(1); +} + +/* dummy RDN - subject and issuer - we aren't testing this */ +CB_NameOid dummyRdn[] = +{ + { "Apple Computer", &CSSMOID_OrganizationName }, + { "Doug Mitchell", &CSSMOID_CommonName } +}; +#define NUM_DUMMY_NAMES (sizeof(dummyRdn) / sizeof(CB_NameOid)) + +/* + * Static components we reuse for each encode/decode. + */ +static CSSM_X509_NAME *dummyName; +static CSSM_X509_TIME *notBefore; // UTC-style "not before" time +static CSSM_X509_TIME *notAfter; // UTC-style "not after" time +static CSSM_KEY subjPrivKey; +static CSSM_KEY subjPubKey; + +static CSSM_BOOL randBool() +{ + unsigned r = genRand(1, 0x10000000); + return (r & 0x1) ? CSSM_TRUE : CSSM_FALSE; +} + +/* Fill a CSSM_DATA with random data. Its referent is allocd with malloc. */ +static void randData( + CSSM_DATA_PTR data, + uint8 maxLen) +{ + data->Data = (uint8 *)malloc(maxLen); + simpleGenData(data, 1, maxLen); +} + +/* + * Various compare tests + */ +int compBool( + CSSM_BOOL pre, + CSSM_BOOL post, + const char *desc) +{ + if(pre == post) { + return 0; + } + printf("***Boolean miscompare on %s\n", desc); + /* in case a CSSM_TRUE isn't exactly right... */ + switch(post) { + case CSSM_FALSE: + case CSSM_TRUE: + break; + default: + printf("*** post value is %d expected %d\n", + (int)post, (int)pre); + break; + } + return 1; +} + +static int compCssmData( + CSSM_DATA &d1, + CSSM_DATA &d2, + const char *desc) +{ + if(appCompareCssmData(&d1, &d2)) { + return 0; + } + printf("CSSM_DATA miscompare on %s\n", desc); + return 1; +} + +#pragma mark ----- individual extension tests ----- + +#pragma mark --- CE_KeyUsage --- +static void kuCreate(void *arg) +{ + CE_KeyUsage *ku = (CE_KeyUsage *)arg; + + /* set two random valid bits */ + *ku = 0; + *ku |= 1 << genRand(7, 15); + *ku |= 1 << genRand(7, 15); +} + +static unsigned kuCompare(const void *pre, const void *post) +{ + const CE_KeyUsage *kuPre = (CE_KeyUsage *)pre; + const CE_KeyUsage *kuPost = (CE_KeyUsage *)post; + if(*kuPre != *kuPost) { + printf("***Miscompare in CE_KeyUsage\n"); + return 1; + } + return 0; +} + +#pragma mark --- CE_BasicConstraints --- +static void bcCreate(void *arg) +{ + CE_BasicConstraints *bc = (CE_BasicConstraints *)arg; + bc->cA = randBool(); + bc->pathLenConstraintPresent = randBool(); + if(bc->pathLenConstraintPresent) { + bc->pathLenConstraint = genRand(1,10); + } +} + +static unsigned bcCompare(const void *pre, const void *post) +{ + const CE_BasicConstraints *bcpre = (CE_BasicConstraints *)pre; + const CE_BasicConstraints *bcpost = (CE_BasicConstraints *)post; + unsigned rtn = 0; + + rtn += compBool(bcpre->cA, bcpost->cA, "BasicConstraints.cA"); + rtn += compBool(bcpre->pathLenConstraintPresent, + bcpost->pathLenConstraintPresent, + "BasicConstraints.pathLenConstraintPresent"); + if(bcpre->pathLenConstraint != bcpost->pathLenConstraint) { + printf("BasicConstraints.pathLenConstraint mismatch\n"); + rtn++; + } + return rtn; +} + +#pragma mark --- CE_SubjectKeyID --- +static void skidCreate(void *arg) +{ + CSSM_DATA_PTR skid = (CSSM_DATA_PTR)arg; + randData(skid, 16); +} + +static unsigned skidCompare(const void *pre, const void *post) +{ + CSSM_DATA_PTR spre = (CSSM_DATA_PTR)pre; + CSSM_DATA_PTR spost = (CSSM_DATA_PTR)post; + return compCssmData(*spre, *spost, "SubjectKeyID"); +} + +static void skidFree(void *arg) +{ + CSSM_DATA_PTR skid = (CSSM_DATA_PTR)arg; + free(skid->Data); +} + +#pragma mark --- CE_NetscapeCertType --- +static void nctCreate(void *arg) +{ + CE_NetscapeCertType *nct = (CE_NetscapeCertType *)arg; + + /* set two random valid bits */ + *nct = 0; + *nct |= 1 << genRand(8, 15); + *nct |= 1 << genRand(8, 15); +} + +static unsigned nctCompare(const void *pre, const void *post) +{ + const CE_NetscapeCertType *nPre = (CE_NetscapeCertType *)pre; + const CE_NetscapeCertType *nPost = (CE_NetscapeCertType *)post; + if(*nPre != *nPost) { + printf("***Miscompare in CE_NetscapeCertType\n"); + return 1; + } + return 0; +} + +#pragma mark --- CE_ExtendedKeyUsage --- + +/* a static array of meaningless OIDs, use 1.. NUM_SKU_OIDS */ +CSSM_OID ekuOids[] = { + CSSMOID_CrlNumber, + CSSMOID_CrlReason, + CSSMOID_HoldInstructionCode, + CSSMOID_InvalidityDate +}; +#define NUM_SKU_OIDS 4 + +static void ekuCreate(void *arg) +{ + CE_ExtendedKeyUsage *eku = (CE_ExtendedKeyUsage *)arg; + eku->numPurposes = genRand(1, NUM_SKU_OIDS); + eku->purposes = ekuOids; +} + +static unsigned ekuCompare(const void *pre, const void *post) +{ + CE_ExtendedKeyUsage *ekupre = (CE_ExtendedKeyUsage *)pre; + CE_ExtendedKeyUsage *ekupost = (CE_ExtendedKeyUsage *)post; + + if(ekupre->numPurposes != ekupost->numPurposes) { + printf("CE_ExtendedKeyUsage.numPurposes miscompare\n"); + return 1; + } + unsigned rtn = 0; + for(unsigned dex=0; dexnumPurposes; dex++) { + rtn += compCssmData(ekupre->purposes[dex], + ekupost->purposes[dex], "CE_ExtendedKeyUsage.purposes"); + } + return rtn; +} + + +#pragma mark --- general purpose X509 name generator --- + +/* Attr/Value pairs, pick one of NUM_ATTR_STRINGS */ +static char *attrStrings[] = { + (char *)"thisName", + (char *)"anotherName", + (char *)"someOtherName" +}; +#define NUM_ATTR_STRINGS 3 + +/* A/V type, pick one of NUM_ATTR_TYPES */ +static CSSM_OID attrTypes[] = { + CSSMOID_Surname, + CSSMOID_CountryName, + CSSMOID_OrganizationName, + CSSMOID_Description +}; +#define NUM_ATTR_TYPES 4 + +/* A/V tag, pick one of NUM_ATTR_TAGS */ +static char attrTags[] = { + BER_TAG_PRINTABLE_STRING, + BER_TAG_IA5_STRING, + BER_TAG_T61_STRING +}; +#define NUM_ATTR_TAGS 3 + +static void rdnCreate( + CSSM_X509_RDN_PTR rdn) +{ + unsigned numPairs = genRand(1,4); + rdn->numberOfPairs = numPairs; + unsigned len = numPairs * sizeof(CSSM_X509_TYPE_VALUE_PAIR); + rdn->AttributeTypeAndValue = + (CSSM_X509_TYPE_VALUE_PAIR_PTR)malloc(len); + memset(rdn->AttributeTypeAndValue, 0, len); + + for(unsigned atvDex=0; atvDexAttributeTypeAndValue[atvDex]; + unsigned die = genRand(1, NUM_ATTR_TYPES); + pair.type = attrTypes[die - 1]; + die = genRand(1, NUM_ATTR_STRINGS); + char *str = attrStrings[die - 1]; + pair.value.Data = (uint8 *)str; + pair.value.Length = strlen(str); + die = genRand(1, NUM_ATTR_TAGS); + pair.valueType = attrTags[die - 1]; + } +} + +static unsigned rdnCompare( + CSSM_X509_RDN_PTR rdn1, + CSSM_X509_RDN_PTR rdn2) +{ + if(rdn1->numberOfPairs != rdn2->numberOfPairs) { + printf("***Mismatch in numberOfPairs\n"); + return 1; + } + unsigned rtn = 0; + for(unsigned atvDex=0; atvDexnumberOfPairs; atvDex++) { + CSSM_X509_TYPE_VALUE_PAIR &p1 = + rdn1->AttributeTypeAndValue[atvDex]; + CSSM_X509_TYPE_VALUE_PAIR &p2 = + rdn2->AttributeTypeAndValue[atvDex]; + if(p1.valueType != p2.valueType) { + printf("***valueType miscompare\n"); + rtn++; + } + if(compCssmData(p1.type, p2.type, "ATV.type")) { + rtn++; + } + if(compCssmData(p1.value, p2.value, "ATV.value")) { + rtn++; + } + } + return rtn; +} + +static void rdnFree( + CSSM_X509_RDN_PTR rdn) +{ + free(rdn->AttributeTypeAndValue); +} + +static void x509NameCreate( + CSSM_X509_NAME_PTR x509Name) +{ + memset(x509Name, 0, sizeof(*x509Name)); + unsigned numRdns = genRand(1,4); + x509Name->numberOfRDNs = numRdns; + unsigned len = numRdns * sizeof(CSSM_X509_RDN); + x509Name->RelativeDistinguishedName = (CSSM_X509_RDN_PTR)malloc(len); + memset(x509Name->RelativeDistinguishedName, 0, len); + + for(unsigned rdnDex=0; rdnDexRelativeDistinguishedName[rdnDex]; + rdnCreate(&rdn); + } +} + +static unsigned x509NameCompare( + const CSSM_X509_NAME_PTR n1, + const CSSM_X509_NAME_PTR n2) +{ + if(n1->numberOfRDNs != n2->numberOfRDNs) { + printf("***Mismatch in numberOfRDNs\n"); + return 1; + } + unsigned rtn = 0; + for(unsigned rdnDex=0; rdnDexnumberOfRDNs; rdnDex++) { + CSSM_X509_RDN &rdn1 = n1->RelativeDistinguishedName[rdnDex]; + CSSM_X509_RDN &rdn2 = n2->RelativeDistinguishedName[rdnDex]; + rtn += rdnCompare(&rdn1, &rdn2); + } + return rtn; +} + +static void x509NameFree( + CSSM_X509_NAME_PTR n) +{ + for(unsigned rdnDex=0; rdnDexnumberOfRDNs; rdnDex++) { + CSSM_X509_RDN &rdn = n->RelativeDistinguishedName[rdnDex]; + rdnFree(&rdn); + } + free(n->RelativeDistinguishedName); +} + +#pragma mark --- general purpose GeneralNames generator --- + +#define SOME_URL_1 "http://foo.bar.com" +#define SOME_URL_2 "http://bar.foo.com" +#define SOME_DNS_1 "Some DNS" +#define SOME_DNS_2 "Another DNS" +unsigned char someIpAdr_1[] = {208, 161, 124, 209 }; +unsigned char someIpAdr_2[] = {10, 0, 61, 5}; + +static void genNameCreate(CE_GeneralName *name) +{ + unsigned type = genRand(1, 5); + const char *src; + unsigned char *usrc; + switch(type) { + case 1: + name->nameType = GNT_URI; + name->berEncoded = CSSM_FALSE; + src = randBool() ? SOME_URL_1 : SOME_URL_2; + appCopyData(src, strlen(src), &name->name); + break; + + case 2: + name->nameType = GNT_RegisteredID; + name->berEncoded = CSSM_FALSE; + appCopyData(CSSMOID_SubjectDirectoryAttributes.Data, + CSSMOID_SubjectDirectoryAttributes.Length, + &name->name); + break; + + case 3: + name->nameType = GNT_DNSName; + name->berEncoded = CSSM_FALSE; + src = randBool() ? SOME_DNS_1 : SOME_DNS_2; + appCopyData(src, strlen(src), &name->name); + break; + + case 4: + name->nameType = GNT_IPAddress; + name->berEncoded = CSSM_FALSE; + usrc = randBool() ? someIpAdr_1 : someIpAdr_2; + appCopyData(usrc, 4, &name->name); + break; + + case 5: + { + /* X509_NAME, the hard one */ + name->nameType = GNT_DirectoryName; + name->berEncoded = CSSM_FALSE; + appSetupCssmData(&name->name, sizeof(CSSM_X509_NAME)); + x509NameCreate((CSSM_X509_NAME_PTR)name->name.Data); + } + } +} + +static void genNamesCreate(void *arg) +{ + CE_GeneralNames *names = (CE_GeneralNames *)arg; + names->numNames = genRand(1, 3); + // one at a time + //names->numNames = 1; + names->generalName = (CE_GeneralName *)malloc(names->numNames * + sizeof(CE_GeneralName)); + memset(names->generalName, 0, names->numNames * sizeof(CE_GeneralName)); + + for(unsigned i=0; inumNames; i++) { + CE_GeneralName *name = &names->generalName[i]; + genNameCreate(name); + } +} + +static unsigned genNameCompare( + CE_GeneralName *npre, + CE_GeneralName *npost) +{ + unsigned rtn = 0; + if(npre->nameType != npost->nameType) { + printf("***CE_GeneralName.nameType miscompare\n"); + rtn++; + } + if(compBool(npre->berEncoded, npost->berEncoded, + "CE_GeneralName.berEncoded")) { + rtn++; + } + + /* nameType-specific compare */ + switch(npre->nameType) { + case GNT_RFC822Name: + rtn += compCssmData(npre->name, npost->name, + "CE_GeneralName.RFC822Name"); + break; + case GNT_DNSName: + rtn += compCssmData(npre->name, npost->name, + "CE_GeneralName.DNSName"); + break; + case GNT_URI: + rtn += compCssmData(npre->name, npost->name, + "CE_GeneralName.URI"); + break; + case GNT_IPAddress: + rtn += compCssmData(npre->name, npost->name, + "CE_GeneralName.RFIPAddressC822Name"); + break; + case GNT_RegisteredID: + rtn += compCssmData(npre->name, npost->name, + "CE_GeneralName.RegisteredID"); + break; + case GNT_DirectoryName: + rtn += x509NameCompare((CSSM_X509_NAME_PTR)npre->name.Data, + (CSSM_X509_NAME_PTR)npost->name.Data); + break; + default: + printf("****BRRZAP! genNamesCompare needs work\n"); + rtn++; + } + return rtn; +} + +static unsigned genNamesCompare(const void *pre, const void *post) +{ + const CE_GeneralNames *gnPre = (CE_GeneralNames *)pre; + const CE_GeneralNames *gnPost = (CE_GeneralNames *)post; + unsigned rtn = 0; + + if((gnPre == NULL) || (gnPost == NULL)) { + printf("***Bad GenNames pointer\n"); + return 1; + } + if(gnPre->numNames != gnPost->numNames) { + printf("***CE_GeneralNames.numNames miscompare\n"); + return 1; + } + for(unsigned dex=0; dexnumNames; dex++) { + CE_GeneralName *npre = &gnPre->generalName[dex]; + CE_GeneralName *npost = &gnPost->generalName[dex]; + rtn += genNameCompare(npre, npost); + } + return rtn; +} + + +static void genNameFree(CE_GeneralName *n) +{ + switch(n->nameType) { + case GNT_DirectoryName: + x509NameFree((CSSM_X509_NAME_PTR)n->name.Data); + CSSM_FREE(n->name.Data); + break; + default: + CSSM_FREE(n->name.Data); + break; + } +} + + +static void genNamesFree(void *arg) +{ + const CE_GeneralNames *gn = (CE_GeneralNames *)arg; + for(unsigned dex=0; dexnumNames; dex++) { + CE_GeneralName *n = (CE_GeneralName *)&gn->generalName[dex]; + genNameFree(n); + } + free(gn->generalName); +} + +#pragma mark --- CE_CRLDistPointsSyntax --- +static void cdpCreate(void *arg) +{ + CE_CRLDistPointsSyntax *cdp = (CE_CRLDistPointsSyntax *)arg; + //cdp->numDistPoints = genRand(1,3); + // one at a time + cdp->numDistPoints = 1; + unsigned len = sizeof(CE_CRLDistributionPoint) * cdp->numDistPoints; + cdp->distPoints = (CE_CRLDistributionPoint *)malloc(len); + memset(cdp->distPoints, 0, len); + + for(unsigned dex=0; dexnumDistPoints; dex++) { + CE_CRLDistributionPoint *pt = &cdp->distPoints[dex]; + + /* all fields optional */ + if(randBool()) { + CE_DistributionPointName *dpn = pt->distPointName = + (CE_DistributionPointName *)malloc( + sizeof(CE_DistributionPointName)); + memset(dpn, 0, sizeof(CE_DistributionPointName)); + + /* CE_DistributionPointName has two flavors */ + if(randBool()) { + dpn->nameType = CE_CDNT_FullName; + dpn->dpn.fullName = (CE_GeneralNames *)malloc( + sizeof(CE_GeneralNames)); + memset(dpn->dpn.fullName, 0, sizeof(CE_GeneralNames)); + genNamesCreate(dpn->dpn.fullName); + } + else { + dpn->nameType = CE_CDNT_NameRelativeToCrlIssuer; + dpn->dpn.rdn = (CSSM_X509_RDN_PTR)malloc( + sizeof(CSSM_X509_RDN)); + memset(dpn->dpn.rdn, 0, sizeof(CSSM_X509_RDN)); + rdnCreate(dpn->dpn.rdn); + } + } /* creating CE_DistributionPointName */ + + pt->reasonsPresent = randBool(); + if(pt->reasonsPresent) { + CE_CrlDistReasonFlags *cdr = &pt->reasons; + /* set two random valid bits */ + *cdr = 0; + *cdr |= 1 << genRand(0,7); + *cdr |= 1 << genRand(0,7); + } + + /* make sure at least one present */ + if((!pt->distPointName && !pt->reasonsPresent) || randBool()) { + pt->crlIssuer = (CE_GeneralNames *)malloc(sizeof(CE_GeneralNames)); + memset(pt->crlIssuer, 0, sizeof(CE_GeneralNames)); + genNamesCreate(pt->crlIssuer); + } + } +} + +static unsigned cdpCompare(const void *pre, const void *post) +{ + CE_CRLDistPointsSyntax *cpre = (CE_CRLDistPointsSyntax *)pre; + CE_CRLDistPointsSyntax *cpost = (CE_CRLDistPointsSyntax *)post; + + if(cpre->numDistPoints != cpost->numDistPoints) { + printf("***CE_CRLDistPointsSyntax.numDistPoints miscompare\n"); + return 1; + } + unsigned rtn = 0; + for(unsigned dex=0; dexnumDistPoints; dex++) { + CE_CRLDistributionPoint *ptpre = &cpre->distPoints[dex]; + CE_CRLDistributionPoint *ptpost = &cpost->distPoints[dex]; + + if(ptpre->distPointName) { + if(ptpost->distPointName == NULL) { + printf("***NULL distPointName post decode\n"); + rtn++; + goto checkReason; + } + CE_DistributionPointName *dpnpre = ptpre->distPointName; + CE_DistributionPointName *dpnpost = ptpost->distPointName; + if(dpnpre->nameType != dpnpost->nameType) { + printf("***CE_DistributionPointName.nameType miscompare\n"); + rtn++; + goto checkReason; + } + if(dpnpre->nameType == CE_CDNT_FullName) { + rtn += genNamesCompare(dpnpre->dpn.fullName, dpnpost->dpn.fullName); + } + else { + rtn += rdnCompare(dpnpre->dpn.rdn, dpnpost->dpn.rdn); + } + + } + else if(ptpost->distPointName != NULL) { + printf("***NON NULL distPointName post decode\n"); + rtn++; + } + + checkReason: + if(ptpre->reasons != ptpost->reasons) { + printf("***CE_CRLDistributionPoint.reasons miscompare\n"); + rtn++; + } + + if(ptpre->crlIssuer) { + if(ptpost->crlIssuer == NULL) { + printf("***NULL crlIssuer post decode\n"); + rtn++; + continue; + } + CE_GeneralNames *gnpre = ptpre->crlIssuer; + CE_GeneralNames *gnpost = ptpost->crlIssuer; + rtn += genNamesCompare(gnpre, gnpost); + } + else if(ptpost->crlIssuer != NULL) { + printf("***NON NULL crlIssuer post decode\n"); + rtn++; + } + } + return rtn; +} + +static void cdpFree(void *arg) +{ + CE_CRLDistPointsSyntax *cdp = (CE_CRLDistPointsSyntax *)arg; + for(unsigned dex=0; dexnumDistPoints; dex++) { + CE_CRLDistributionPoint *pt = &cdp->distPoints[dex]; + if(pt->distPointName) { + CE_DistributionPointName *dpn = pt->distPointName; + if(dpn->nameType == CE_CDNT_FullName) { + genNamesFree(dpn->dpn.fullName); + free(dpn->dpn.fullName); + } + else { + rdnFree(dpn->dpn.rdn); + free(dpn->dpn.rdn); + } + free(dpn); + } + + if(pt->crlIssuer) { + genNamesFree(pt->crlIssuer); + free(pt->crlIssuer); + } + } + free(cdp->distPoints); +} + +#pragma mark --- CE_AuthorityKeyID --- +static void authKeyIdCreate(void *arg) +{ + CE_AuthorityKeyID *akid = (CE_AuthorityKeyID *)arg; + + /* all three fields optional */ + + akid->keyIdentifierPresent = randBool(); + if(akid->keyIdentifierPresent) { + randData(&akid->keyIdentifier, 16); + } + + akid->generalNamesPresent = randBool(); + if(akid->generalNamesPresent) { + akid->generalNames = + (CE_GeneralNames *)malloc(sizeof(CE_GeneralNames)); + memset(akid->generalNames, 0, sizeof(CE_GeneralNames)); + genNamesCreate(akid->generalNames); + } + + if(!akid->keyIdentifierPresent & !akid->generalNamesPresent) { + /* force at least one to be present */ + akid->serialNumberPresent = CSSM_TRUE; + } + else { + akid->serialNumberPresent = randBool(); + } + if(akid->serialNumberPresent) { + randData(&akid->serialNumber, 16); + } + +} + +static unsigned authKeyIdCompare(const void *pre, const void *post) +{ + CE_AuthorityKeyID *akpre = (CE_AuthorityKeyID *)pre; + CE_AuthorityKeyID *akpost = (CE_AuthorityKeyID *)post; + unsigned rtn = 0; + + if(compBool(akpre->keyIdentifierPresent, akpost->keyIdentifierPresent, + "CE_AuthorityKeyID.keyIdentifierPresent")) { + rtn++; + } + else if(akpre->keyIdentifierPresent) { + rtn += compCssmData(akpre->keyIdentifier, + akpost->keyIdentifier, "CE_AuthorityKeyID.keyIdentifier"); + } + + if(compBool(akpre->generalNamesPresent, akpost->generalNamesPresent, + "CE_AuthorityKeyID.generalNamesPresent")) { + rtn++; + } + else if(akpre->generalNamesPresent) { + rtn += genNamesCompare(akpre->generalNames, + akpost->generalNames); + } + + if(compBool(akpre->serialNumberPresent, akpost->serialNumberPresent, + "CE_AuthorityKeyID.serialNumberPresent")) { + rtn++; + } + else if(akpre->serialNumberPresent) { + rtn += compCssmData(akpre->serialNumber, + akpost->serialNumber, "CE_AuthorityKeyID.serialNumber"); + } + return rtn; +} + +static void authKeyIdFree(void *arg) +{ + CE_AuthorityKeyID *akid = (CE_AuthorityKeyID *)arg; + + if(akid->keyIdentifier.Data) { + free(akid->keyIdentifier.Data); + } + if(akid->generalNames) { + genNamesFree(akid->generalNames); // genNamesCreate mallocd + free(akid->generalNames); // we mallocd + } + if(akid->serialNumber.Data) { + free(akid->serialNumber.Data); + } +} + +#pragma mark --- CE_CertPolicies --- + +/* random OIDs, pick 1..NUM_CP_OIDS */ +static CSSM_OID cpOids[] = +{ + CSSMOID_EmailAddress, + CSSMOID_UnstructuredName, + CSSMOID_ContentType, + CSSMOID_MessageDigest +}; +#define NUM_CP_OIDS 4 + +/* CPS strings, pick one of NUM_CPS_STR */ +static char *someCPSs[] = +{ + (char *)"http://www.apple.com", + (char *)"https://cdnow.com", + (char *)"ftp:backwards.com" +}; +#define NUM_CPS_STR 3 + +/* make these looks like real sequences */ +static uint8 someUnotice[] = {0x30, 0x03, BER_TAG_BOOLEAN, 1, 0xff}; +static uint8 someOtherData[] = {0x30, 0x02, BER_TAG_NULL, 0}; + +static void cpCreate(void *arg) +{ + CE_CertPolicies *cp = (CE_CertPolicies *)arg; + cp->numPolicies = genRand(1,3); + //cp->numPolicies = 1; + unsigned len = sizeof(CE_PolicyInformation) * cp->numPolicies; + cp->policies = (CE_PolicyInformation *)malloc(len); + memset(cp->policies, 0, len); + + for(unsigned polDex=0; polDexnumPolicies; polDex++) { + CE_PolicyInformation *pi = &cp->policies[polDex]; + unsigned die = genRand(1, NUM_CP_OIDS); + pi->certPolicyId = cpOids[die - 1]; + unsigned numQual = genRand(1,3); + pi->numPolicyQualifiers = numQual; + len = sizeof(CE_PolicyQualifierInfo) * numQual; + pi->policyQualifiers = (CE_PolicyQualifierInfo *) + malloc(len); + memset(pi->policyQualifiers, 0, len); + for(unsigned cpiDex=0; cpiDexpolicyQualifiers[cpiDex]; + if(randBool()) { + qi->policyQualifierId = CSSMOID_QT_CPS; + die = genRand(1, NUM_CPS_STR); + qi->qualifier.Data = (uint8 *)someCPSs[die - 1]; + qi->qualifier.Length = strlen((char *)qi->qualifier.Data); + } + else { + qi->policyQualifierId = CSSMOID_QT_UNOTICE; + if(randBool()) { + qi->qualifier.Data = someUnotice; + qi->qualifier.Length = 5; + } + else { + qi->qualifier.Data = someOtherData; + qi->qualifier.Length = 4; + } + } + } + } +} + +static unsigned cpCompare(const void *pre, const void *post) +{ + CE_CertPolicies *cppre = (CE_CertPolicies *)pre; + CE_CertPolicies *cppost = (CE_CertPolicies *)post; + + if(cppre->numPolicies != cppost->numPolicies) { + printf("CE_CertPolicies.numPolicies mismatch\n"); + return 1; + } + unsigned rtn = 0; + for(unsigned polDex=0; polDexnumPolicies; polDex++) { + CE_PolicyInformation *pipre = &cppre->policies[polDex]; + CE_PolicyInformation *pipost = &cppost->policies[polDex]; + rtn += compCssmData(pipre->certPolicyId, pipost->certPolicyId, + "CE_PolicyInformation.certPolicyId"); + if(pipre->numPolicyQualifiers != pipost->numPolicyQualifiers) { + printf("CE_PolicyInformation.CE_PolicyInformation mismatch\n"); + rtn++; + continue; + } + + for(unsigned qiDex=0; qiDexnumPolicyQualifiers; qiDex++) { + CE_PolicyQualifierInfo *qipre = &pipre->policyQualifiers[qiDex]; + CE_PolicyQualifierInfo *qipost = &pipost->policyQualifiers[qiDex]; + rtn += compCssmData(qipre->policyQualifierId, + qipost->policyQualifierId, + "CE_PolicyQualifierInfo.policyQualifierId"); + rtn += compCssmData(qipre->qualifier, + qipost->qualifier, + "CE_PolicyQualifierInfo.qualifier"); + } + } + return rtn; +} + +static void cpFree(void *arg) +{ + CE_CertPolicies *cp = (CE_CertPolicies *)arg; + for(unsigned polDex=0; polDexnumPolicies; polDex++) { + CE_PolicyInformation *pi = &cp->policies[polDex]; + free(pi->policyQualifiers); + } + free(cp->policies); +} + +#pragma mark --- CE_AuthorityInfoAccess --- + +/* random OIDs, pick 1..NUM_AI_OIDS */ +static CSSM_OID aiOids[] = +{ + CSSMOID_AD_OCSP, + CSSMOID_AD_CA_ISSUERS, + CSSMOID_AD_TIME_STAMPING, + CSSMOID_AD_CA_REPOSITORY +}; +#define NUM_AI_OIDS 4 + +static void aiaCreate(void *arg) +{ + CE_AuthorityInfoAccess *aia = (CE_AuthorityInfoAccess *)arg; + aia->numAccessDescriptions = genRand(1,3); + unsigned len = aia->numAccessDescriptions * sizeof(CE_AccessDescription); + aia->accessDescriptions = (CE_AccessDescription *)malloc(len); + memset(aia->accessDescriptions, 0, len); + + for(unsigned dex=0; dexnumAccessDescriptions; dex++) { + CE_AccessDescription *ad = &aia->accessDescriptions[dex]; + int die = genRand(1, NUM_AI_OIDS); + ad->accessMethod = aiOids[die - 1]; + genNameCreate(&ad->accessLocation); + } +} + +static unsigned aiaCompare(const void *pre, const void *post) +{ + CE_AuthorityInfoAccess *apre = (CE_AuthorityInfoAccess *)pre; + CE_AuthorityInfoAccess *apost = (CE_AuthorityInfoAccess *)post; + unsigned rtn = 0; + + if(apre->numAccessDescriptions != apost->numAccessDescriptions) { + printf("***CE_AuthorityInfoAccess.numAccessDescriptions miscompare\n"); + return 1; + } + for(unsigned dex=0; dexnumAccessDescriptions; dex++) { + CE_AccessDescription *adPre = &apre->accessDescriptions[dex]; + CE_AccessDescription *adPost = &apost->accessDescriptions[dex]; + if(compCssmData(adPre->accessMethod, adPost->accessMethod, + "CE_AccessDescription.accessMethod")) { + rtn++; + } + rtn += genNameCompare(&adPre->accessLocation, &adPost->accessLocation); + } + return rtn; +} + +static void aiaFree(void *arg) +{ + CE_AuthorityInfoAccess *aia = (CE_AuthorityInfoAccess *)arg; + for(unsigned dex=0; dexnumAccessDescriptions; dex++) { + CE_AccessDescription *ad = &aia->accessDescriptions[dex]; + genNameFree(&ad->accessLocation); + } + free(aia->accessDescriptions); +} + +#pragma mark --- CE_QC_Statements --- + +/* a static array of CE_QC_Statement.statementId */ +static const CSSM_OID qcsOids[] = { + CSSMOID_OID_QCS_SYNTAX_V1, + CSSMOID_OID_QCS_SYNTAX_V2, + CSSMOID_ETSI_QCS_QC_COMPLIANCE, +}; +#define NUM_QCS_OIDS 3 +#define WHICH_QCS_V2 1 + +static void qcsCreate(void *arg) +{ + CE_QC_Statements *qcss = (CE_QC_Statements *)arg; + //unsigned numQcs = genRand(1,3); + unsigned numQcs = 1; + qcss->numQCStatements = numQcs; + qcss->qcStatements = (CE_QC_Statement *)malloc(numQcs * sizeof(CE_QC_Statement)); + memset(qcss->qcStatements, 0, numQcs * sizeof(CE_QC_Statement)); + + for(unsigned dex=0; dexqcStatements[dex]; + unsigned whichOid = genRand(0, NUM_QCS_OIDS-1); + qcs->statementId = qcsOids[whichOid]; + + /* three legal combos of (semanticsInfo, otherInfo), constrained by whichOid */ + unsigned coin = genRand(1, 2); + switch(coin) { + case 1: + /* nothing */ + break; + case 2: + { + /* + * CSSMOID_OID_QCS_SYNTAX_V2 --> semanticsInfo + * other --> otherInfo + */ + if(whichOid == WHICH_QCS_V2) { + CE_SemanticsInformation *si = (CE_SemanticsInformation *)malloc( + sizeof(CE_SemanticsInformation)); + qcs->semanticsInfo = si; + memset(si, 0, sizeof(CE_SemanticsInformation)); + + /* flip a coin; heads --> semanticsIdentifier */ + coin = genRand(1, 2); + if(coin == 2) { + si->semanticsIdentifier = (CSSM_OID *)malloc(sizeof(CSSM_OID)); + *si->semanticsIdentifier = qcsOids[0]; + } + + /* flip a coin; heads --> nameRegistrationAuthorities */ + /* also gen this one if semanticsInfo is empty */ + coin = genRand(1, 2); + if((coin == 2) || (si->semanticsIdentifier == NULL)) { + si->nameRegistrationAuthorities = (CE_NameRegistrationAuthorities *) + malloc(sizeof(CE_NameRegistrationAuthorities)); + genNamesCreate(si->nameRegistrationAuthorities); + } + } + else { + /* ASN_ANY - just take an encoded NULL */ + CSSM_DATA *otherInfo = (CSSM_DATA *)malloc(sizeof(CSSM_DATA)); + otherInfo->Data = (uint8 *)malloc(2); + otherInfo->Data[0] = 5; + otherInfo->Data[1] = 0; + otherInfo->Length = 2; + qcs->otherInfo = otherInfo; + } + break; + } + } + } +} + +static unsigned qcsCompare(const void *pre, const void *post) +{ + CE_QC_Statements *qpre = (CE_QC_Statements *)pre; + CE_QC_Statements *qpost = (CE_QC_Statements *)post; + uint32 numQcs = qpre->numQCStatements; + if(numQcs != qpost->numQCStatements) { + printf("***numQCStatements miscompare\n"); + return 1; + } + + unsigned rtn = 0; + for(unsigned dex=0; dexqcStatements[dex]; + CE_QC_Statement *qcsPost = &qpost->qcStatements[dex]; + if(compCssmData(qcsPre->statementId, qcsPost->statementId, + "CE_QC_Statement.statementId")) { + rtn++; + } + if(qcsPre->semanticsInfo) { + if(qcsPost->semanticsInfo == NULL) { + printf("***semanticsInfo in pre but not in post\n"); + rtn++; + } + else { + CE_SemanticsInformation *siPre = qcsPre->semanticsInfo; + CE_SemanticsInformation *siPost = qcsPost->semanticsInfo; + if((siPre->semanticsIdentifier == NULL) != (siPost->semanticsIdentifier == NULL)) { + printf("***mismatch in presence of semanticsIdentifier\n"); + rtn++; + } + else if(siPre->semanticsIdentifier) { + if(compCssmData(*siPre->semanticsIdentifier, *siPost->semanticsIdentifier, + "CE_SemanticsInformation.semanticsIdentifier")) { + rtn++; + } + } + if((siPre->nameRegistrationAuthorities == NULL) != + (siPost->nameRegistrationAuthorities == NULL)) { + printf("***mismatch in presence of nameRegistrationAuthorities\n"); + rtn++; + } + else if(siPre->nameRegistrationAuthorities) { + rtn += genNamesCompare(siPre->nameRegistrationAuthorities, + siPost->nameRegistrationAuthorities); + } + } + } + else if(qcsPost->semanticsInfo != NULL) { + printf("***semanticsInfo in post but not in pre\n"); + rtn++; + } + if(qcsPre->otherInfo) { + if(qcsPost->otherInfo == NULL) { + printf("***otherInfo in pre but not in post\n"); + rtn++; + } + else { + if(compCssmData(*qcsPre->otherInfo, *qcsPre->otherInfo, + "CE_QC_Statement.otherInfo")) { + rtn++; + } + } + } + else if(qcsPost->otherInfo != NULL) { + printf("***otherInfo in post but not in pre\n"); + rtn++; + } + } + return rtn; +} + +static void qcsFree(void *arg) +{ + CE_QC_Statements *qcss = (CE_QC_Statements *)arg; + uint32 numQcs = qcss->numQCStatements; + for(unsigned dex=0; dexqcStatements[dex]; + if(qcs->semanticsInfo) { + CE_SemanticsInformation *si = qcs->semanticsInfo; + if(si->semanticsIdentifier) { + free(si->semanticsIdentifier); + } + if(si->nameRegistrationAuthorities) { + genNamesFree(si->nameRegistrationAuthorities); + free(si->nameRegistrationAuthorities); + } + free(qcs->semanticsInfo); + } + if(qcs->otherInfo) { + free(qcs->otherInfo->Data); + free(qcs->otherInfo); + } + } + free(qcss->qcStatements); +} + +#pragma mark --- test definitions --- + +/* + * Define one extension test. + */ + +/* + * Cook up this extension with random, reasonable values. + * Incoming pointer refers to extension-specific C struct, mallocd + * and zeroed by main test routine. + */ +typedef void (*extenCreateFcn)(void *arg); + +/* + * Compare two instances of this extension. Return number of + * compare errors. + */ +typedef unsigned (*extenCompareFcn)( + const void *preEncode, + const void *postEncode); + +/* + * Free struct components mallocd in extenCreateFcn. Do not free + * the outer struct. + */ +typedef void (*extenFreeFcn)(void *arg); + +typedef struct { + /* three extension-specific functions */ + extenCreateFcn createFcn; + extenCompareFcn compareFcn; + extenFreeFcn freeFcn; + + /* size of C struct passed to all three functions */ + unsigned extenSize; + + /* the OID for this extension */ + CSSM_OID extenOid; + + /* description for error logging and blob writing */ + const char *extenDescr; + + /* command-line letter for this one */ + char extenLetter; + +} ExtenTest; + +/* empty freeFcn means no extension-specific resources to free */ +#define NO_FREE NULL + +static ExtenTest extenTests[] = { + { kuCreate, kuCompare, NO_FREE, + sizeof(CE_KeyUsage), CSSMOID_KeyUsage, + "KeyUsage", 'k' }, + { bcCreate, bcCompare, NO_FREE, + sizeof(CE_BasicConstraints), CSSMOID_BasicConstraints, + "BasicConstraints", 'b' }, + { ekuCreate, ekuCompare, NO_FREE, + sizeof(CE_ExtendedKeyUsage), CSSMOID_ExtendedKeyUsage, + "ExtendedKeyUsage", 'x' }, + { skidCreate, skidCompare, skidFree, + sizeof(CSSM_DATA), CSSMOID_SubjectKeyIdentifier, + "SubjectKeyID", 's' }, + { authKeyIdCreate, authKeyIdCompare, authKeyIdFree, + sizeof(CE_AuthorityKeyID), CSSMOID_AuthorityKeyIdentifier, + "AuthorityKeyID", 'a' }, + { genNamesCreate, genNamesCompare, genNamesFree, + sizeof(CE_GeneralNames), CSSMOID_SubjectAltName, + "SubjectAltName", 't' }, + { genNamesCreate, genNamesCompare, genNamesFree, + sizeof(CE_GeneralNames), CSSMOID_IssuerAltName, + "IssuerAltName", 'i' }, + { nctCreate, nctCompare, NO_FREE, + sizeof(CE_NetscapeCertType), CSSMOID_NetscapeCertType, + "NetscapeCertType", 'n' }, + { cdpCreate, cdpCompare, cdpFree, + sizeof(CE_CRLDistPointsSyntax), CSSMOID_CrlDistributionPoints, + "CRLDistPoints", 'p' }, + { cpCreate, cpCompare, cpFree, + sizeof(CE_CertPolicies), CSSMOID_CertificatePolicies, + "CertPolicies", 'c' }, + { aiaCreate, aiaCompare, aiaFree, + sizeof(CE_AuthorityInfoAccess), CSSMOID_AuthorityInfoAccess, + "AuthorityInfoAccess", 'A' }, + { aiaCreate, aiaCompare, aiaFree, + sizeof(CE_AuthorityInfoAccess), CSSMOID_SubjectInfoAccess, + "SubjectInfoAccess", 'S' }, + { qcsCreate, qcsCompare, qcsFree, + sizeof(CE_QC_Statements), CSSMOID_QC_Statements, + "QualifiedCertStatements", 'q' }, +}; + +#define NUM_EXTEN_TESTS (sizeof(extenTests) / sizeof(ExtenTest)) + +static void printExten( + CSSM_X509_EXTENSION &extn, + bool preEncode, + OidParser &parser) +{ + CSSM_FIELD field; + field.FieldOid = extn.extnId; + field.FieldValue.Data = (uint8 *)&extn; + field.FieldValue.Length = sizeof(CSSM_X509_EXTENSION); + printf("=== %s:\n", preEncode ? "PRE-ENCODE" : "POST-DECODE" ); + printCertField(field, parser, CSSM_TRUE); +} + +static int doTest( + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + ExtenTest &extenTest, + bool writeBlobs, + const char *constFileName, // all blobs to this file if non-NULL + bool displayExtens, + OidParser &parser) +{ + /* + * 1. Cook up a random and reasonable instance of the C struct + * associated with this extension. + */ + void *preEncode = CSSM_MALLOC(extenTest.extenSize); + memset(preEncode, 0, extenTest.extenSize); + extenTest.createFcn(preEncode); + + /* + * Cook up the associated CSSM_X509_EXTENSION. + */ + CSSM_X509_EXTENSION extnPre; + + extnPre.extnId = extenTest.extenOid; + extnPre.critical = randBool(); + extnPre.format = CSSM_X509_DATAFORMAT_PARSED; + extnPre.value.parsedValue = preEncode; + extnPre.BERvalue.Data = NULL; + extnPre.BERvalue.Length = 0; + + /* encode the extension in a TBSCert */ + CSSM_DATA_PTR rawCert = CB_MakeCertTemplate(clHand, + 0x12345678, // serial number + dummyName, + dummyName, + notBefore, + notAfter, + &subjPubKey, + SIG_ALG, + NULL, // subjUniqueId + NULL, // issuerUniqueId + &extnPre, // extensions + 1); // numExtensions + if(rawCert == NULL) { + printf("Error generating template; aborting.\n"); + /* show what we tried to encode */ + printExten(extnPre, true, parser); + return 1; + } + + /* sign the cert */ + CSSM_DATA signedCert = {0, NULL}; + CSSM_CC_HANDLE sigHand; + CSSM_RETURN crtn = CSSM_CSP_CreateSignatureContext(cspHand, + SIG_ALG, + NULL, // no passphrase for now + &subjPrivKey, + &sigHand); + if(crtn) { + printError("CreateSignatureContext", crtn); + return 1; + } + + crtn = CSSM_CL_CertSign(clHand, + sigHand, + rawCert, // CertToBeSigned + NULL, // SignScope per spec + 0, // ScopeSize per spec + &signedCert); + if(crtn) { + printError("CSSM_CL_CertSign", crtn); + /* show what we tried to encode */ + printExten(extnPre, true, parser); + return 1; + } + CSSM_DeleteContext(sigHand); + + if(writeBlobs) { + char fileName[200]; + if(constFileName) { + strcpy(fileName, constFileName); + } + else { + sprintf(fileName, "%scert.der", extenTest.extenDescr); + } + writeFile(fileName, signedCert.Data, signedCert.Length); + printf("...wrote %lu bytes to %s\n", signedCert.Length, fileName); + } + + /* snag the same extension from the encoded cert */ + CSSM_DATA_PTR postField; + CSSM_HANDLE resultHand; + uint32 numFields; + + crtn = CSSM_CL_CertGetFirstFieldValue(clHand, + &signedCert, + &extenTest.extenOid, + &resultHand, + &numFields, + &postField); + if(crtn) { + printf("****Extension field not found on decode for %s\n", + extenTest.extenDescr); + printError("CSSM_CL_CertGetFirstFieldValue", crtn); + + /* show what we tried to encode and decode */ + printExten(extnPre, true, parser); + return 1; + } + + if(numFields != 1) { + printf("****GetFirstFieldValue: expect 1 value, got %u\n", + (unsigned)numFields); + return 1; + } + CSSM_CL_CertAbortQuery(clHand, resultHand); + + /* verify the fields we generated */ + CSSM_X509_EXTENSION *extnPost = (CSSM_X509_EXTENSION *)postField->Data; + if((extnPost == NULL) || + (postField->Length != sizeof(CSSM_X509_EXTENSION))) { + printf("***Malformed CSSM_X509_EXTENSION (1) after decode\n"); + return 1; + } + int rtn = 0; + rtn += compBool(extnPre.critical, extnPost->critical, + "CSSM_X509_EXTENSION.critical"); + rtn += compCssmData(extnPre.extnId, extnPost->extnId, + "CSSM_X509_EXTENSION.extnId"); + + if(extnPost->format != CSSM_X509_DATAFORMAT_PARSED) { + printf("***Expected CSSM_X509_DATAFORMAT_PARSED (%x(x), got %x(x)\n", + CSSM_X509_DATAFORMAT_PARSED, extnPost->format); + } + if(extnPost->value.parsedValue == NULL) { + printf("***no parsedValue pointer!\n"); + return 1; + } + + /* down to extension-specific compare */ + rtn += extenTest.compareFcn(preEncode, extnPost->value.parsedValue); + + if(rtn) { + /* print preencode only on error */ + printExten(extnPre, true, parser); + } + if(displayExtens || rtn) { + printExten(*extnPost, false, parser); + } + + /* free the allocated data */ + if(extenTest.freeFcn) { + extenTest.freeFcn(preEncode); + } + CSSM_CL_FreeFieldValue(clHand, &extenTest.extenOid, postField); + CSSM_FREE(rawCert->Data); + CSSM_FREE(rawCert); + CSSM_FREE(signedCert.Data); + CSSM_FREE(preEncode); + return rtn; +} + +static void doPause(bool pause) +{ + if(!pause) { + return; + } + fpurge(stdin); + printf("CR to continue "); + getchar(); +} + +int main(int argc, char **argv) +{ + CSSM_CL_HANDLE clHand; + CSSM_CSP_HANDLE cspHand; + CSSM_RETURN crtn; + int arg; + int rtn; + OidParser parser; + char *argp; + unsigned i; + + /* user-specificied params */ + unsigned minExtenNum = 0; + unsigned maxExtenNum = NUM_EXTEN_TESTS-1; + bool writeBlobs = false; + bool displayExtens = false; + bool quiet = false; + unsigned loops = LOOPS_DEF; + bool pauseLoop = false; + bool pauseCert = false; + const char *constFileName = NULL; + + for(arg=1; arg +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define KEY_ALG CSSM_ALGID_RSA +#define SIG_ALG CSSM_ALGID_SHA1WithRSA +#define SIG_OID CSSMOID_SHA1WithRSA +#define KEY_SIZE_BITS CSP_RSA_KEY_SIZE_DEFAULT +#define SUBJ_KEY_LABEL "subjectKey" + +#define LOOPS_DEF 10 + +static void usage(char **argv) +{ + printf("Usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" e=extenSpec (default = all)\n"); + printf(" k keyUsage\n"); + printf(" b basicConstraints\n"); + printf(" x extendedKeyUsage\n"); + printf(" s subjectKeyId\n"); + printf(" a authorityKeyId\n"); + printf(" t SubjectAltName\n"); + printf(" i IssuerAltName\n"); + printf(" c certPolicies\n"); + printf(" n netscapeCertType\n"); + printf(" p CRLDistributionPoints\n"); + printf(" A AuthorityInfoAccess\n"); + printf(" S SubjectInfoAccess\n"); + printf(" w(rite blobs)\n"); + printf(" f=fileName (default is extension-specific file name)\n"); + printf(" d(isplay certs)\n"); + printf(" l=loops (default = %d)\n", LOOPS_DEF); + printf(" p(ause on each loop)\n"); + printf(" P(ause on each cert)\n"); + exit(1); +} + +/* subject and issuer - we aren't testing this */ +CSSM_APPLE_TP_NAME_OID dummyRdn[] = +{ + { "Apple Computer", &CSSMOID_OrganizationName }, + { "Doug Mitchell", &CSSMOID_CommonName } +}; +#define NUM_DUMMY_NAMES (sizeof(dummyRdn) / sizeof(CB_NameOid)) + +/* + * Static components we reuse for each encode/decode. + */ +static CSSM_KEY subjPrivKey; +static CSSM_KEY subjPubKey; + +static CSSM_BOOL randBool() +{ + unsigned r = genRand(1, 0x10000000); + return (r & 0x1) ? CSSM_TRUE : CSSM_FALSE; +} + +/* Fill a CSSM_DATA with random data. Its referent is allocd with malloc. */ +static void randData( + CSSM_DATA_PTR data, + uint8 maxLen) +{ + data->Data = (uint8 *)malloc(maxLen); + simpleGenData(data, 1, maxLen); +} + +/* + * Various compare tests + */ +int compBool( + CSSM_BOOL pre, + CSSM_BOOL post, + const char *desc) +{ + if(pre == post) { + return 0; + } + printf("***Boolean miscompare on %s\n", desc); + /* in case a CSSM_TRUE isn't exactly right... */ + switch(post) { + case CSSM_FALSE: + case CSSM_TRUE: + break; + default: + printf("*** post value is %d expected %d\n", + (int)post, (int)pre); + break; + } + return 1; +} + +static int compCssmData( + CSSM_DATA &d1, + CSSM_DATA &d2, + const char *desc) +{ + if(appCompareCssmData(&d1, &d2)) { + return 0; + } + printf("CSSM_DATA miscompare on %s\n", desc); + return 1; +} + +#pragma mark ----- individual extension tests ----- + +#pragma mark --- CE_KeyUsage --- +static void kuCreate(void *arg) +{ + CE_KeyUsage *ku = (CE_KeyUsage *)arg; + + /* set two random valid bits */ + *ku = 0; + *ku |= 1 << genRand(7, 15); + *ku |= 1 << genRand(7, 15); +} + +static unsigned kuCompare(const void *pre, const void *post) +{ + const CE_KeyUsage *kuPre = (CE_KeyUsage *)pre; + const CE_KeyUsage *kuPost = (CE_KeyUsage *)post; + if(*kuPre != *kuPost) { + printf("***Miscompare in CE_KeyUsage\n"); + return 1; + } + return 0; +} + +#pragma mark --- CE_BasicConstraints --- +static void bcCreate(void *arg) +{ + CE_BasicConstraints *bc = (CE_BasicConstraints *)arg; + bc->cA = randBool(); + bc->pathLenConstraintPresent = randBool(); + if(bc->pathLenConstraintPresent) { + bc->pathLenConstraint = genRand(1,10); + } +} + +static unsigned bcCompare(const void *pre, const void *post) +{ + const CE_BasicConstraints *bcpre = (CE_BasicConstraints *)pre; + const CE_BasicConstraints *bcpost = (CE_BasicConstraints *)post; + unsigned rtn = 0; + + rtn += compBool(bcpre->cA, bcpost->cA, "BasicConstraints.cA"); + rtn += compBool(bcpre->pathLenConstraintPresent, + bcpost->pathLenConstraintPresent, + "BasicConstraints.pathLenConstraintPresent"); + if(bcpre->pathLenConstraint != bcpost->pathLenConstraint) { + printf("BasicConstraints.pathLenConstraint mismatch\n"); + rtn++; + } + return rtn; +} + +#pragma mark --- CE_SubjectKeyID --- +static void skidCreate(void *arg) +{ + CSSM_DATA_PTR skid = (CSSM_DATA_PTR)arg; + randData(skid, 16); +} + +static unsigned skidCompare(const void *pre, const void *post) +{ + CSSM_DATA_PTR spre = (CSSM_DATA_PTR)pre; + CSSM_DATA_PTR spost = (CSSM_DATA_PTR)post; + return compCssmData(*spre, *spost, "SubjectKeyID"); +} + +static void skidFree(void *arg) +{ + CSSM_DATA_PTR skid = (CSSM_DATA_PTR)arg; + free(skid->Data); +} + +#pragma mark --- CE_NetscapeCertType --- +static void nctCreate(void *arg) +{ + CE_NetscapeCertType *nct = (CE_NetscapeCertType *)arg; + + /* set two random valid bits */ + *nct = 0; + *nct |= 1 << genRand(8, 15); + *nct |= 1 << genRand(8, 15); +} + +static unsigned nctCompare(const void *pre, const void *post) +{ + const CE_NetscapeCertType *nPre = (CE_NetscapeCertType *)pre; + const CE_NetscapeCertType *nPost = (CE_NetscapeCertType *)post; + if(*nPre != *nPost) { + printf("***Miscompare in CE_NetscapeCertType\n"); + return 1; + } + return 0; +} + +#pragma mark --- CE_ExtendedKeyUsage --- + +/* a static array of meaningless OIDs, use 1.. NUM_SKU_OIDS */ +CSSM_OID ekuOids[] = { + CSSMOID_CrlNumber, + CSSMOID_CrlReason, + CSSMOID_HoldInstructionCode, + CSSMOID_InvalidityDate +}; +#define NUM_SKU_OIDS 4 + +static void ekuCreate(void *arg) +{ + CE_ExtendedKeyUsage *eku = (CE_ExtendedKeyUsage *)arg; + eku->numPurposes = genRand(1, NUM_SKU_OIDS); + eku->purposes = ekuOids; +} + +static unsigned ekuCompare(const void *pre, const void *post) +{ + CE_ExtendedKeyUsage *ekupre = (CE_ExtendedKeyUsage *)pre; + CE_ExtendedKeyUsage *ekupost = (CE_ExtendedKeyUsage *)post; + + if(ekupre->numPurposes != ekupost->numPurposes) { + printf("CE_ExtendedKeyUsage.numPurposes miscompare\n"); + return 1; + } + unsigned rtn = 0; + for(unsigned dex=0; dexnumPurposes; dex++) { + rtn += compCssmData(ekupre->purposes[dex], + ekupost->purposes[dex], "CE_ExtendedKeyUsage.purposes"); + } + return rtn; +} + + +#pragma mark --- general purpose X509 name generator --- + +/* Attr/Value pairs, pick one of NUM_ATTR_STRINGS */ +static char *attrStrings[] = { + (char *)"thisName", + (char *)"anotherName", + (char *)"someOtherName" +}; +#define NUM_ATTR_STRINGS 3 + +/* A/V type, pick one of NUM_ATTR_TYPES */ +static CSSM_OID attrTypes[] = { + CSSMOID_Surname, + CSSMOID_CountryName, + CSSMOID_OrganizationName, + CSSMOID_Description +}; +#define NUM_ATTR_TYPES 4 + +/* A/V tag, pick one of NUM_ATTR_TAGS */ +static char attrTags[] = { + BER_TAG_PRINTABLE_STRING, + BER_TAG_IA5_STRING, + BER_TAG_T61_STRING +}; +#define NUM_ATTR_TAGS 3 + +static void rdnCreate( + CSSM_X509_RDN_PTR rdn) +{ + unsigned numPairs = genRand(1,4); + rdn->numberOfPairs = numPairs; + unsigned len = numPairs * sizeof(CSSM_X509_TYPE_VALUE_PAIR); + rdn->AttributeTypeAndValue = + (CSSM_X509_TYPE_VALUE_PAIR_PTR)malloc(len); + memset(rdn->AttributeTypeAndValue, 0, len); + + for(unsigned atvDex=0; atvDexAttributeTypeAndValue[atvDex]; + unsigned die = genRand(1, NUM_ATTR_TYPES); + pair.type = attrTypes[die - 1]; + die = genRand(1, NUM_ATTR_STRINGS); + char *str = attrStrings[die - 1]; + pair.value.Data = (uint8 *)str; + pair.value.Length = strlen(str); + die = genRand(1, NUM_ATTR_TAGS); + pair.valueType = attrTags[die - 1]; + } +} + +static unsigned rdnCompare( + CSSM_X509_RDN_PTR rdn1, + CSSM_X509_RDN_PTR rdn2) +{ + if(rdn1->numberOfPairs != rdn2->numberOfPairs) { + printf("***Mismatch in numberOfPairs\n"); + return 1; + } + unsigned rtn = 0; + for(unsigned atvDex=0; atvDexnumberOfPairs; atvDex++) { + CSSM_X509_TYPE_VALUE_PAIR &p1 = + rdn1->AttributeTypeAndValue[atvDex]; + CSSM_X509_TYPE_VALUE_PAIR &p2 = + rdn2->AttributeTypeAndValue[atvDex]; + if(p1.valueType != p2.valueType) { + printf("***valueType miscompare\n"); + rtn++; + } + if(compCssmData(p1.type, p2.type, "ATV.type")) { + rtn++; + } + if(compCssmData(p1.value, p2.value, "ATV.value")) { + rtn++; + } + } + return rtn; +} + +static void rdnFree( + CSSM_X509_RDN_PTR rdn) +{ + free(rdn->AttributeTypeAndValue); +} + +static void x509NameCreate( + CSSM_X509_NAME_PTR x509Name) +{ + memset(x509Name, 0, sizeof(*x509Name)); + unsigned numRdns = genRand(1,4); + x509Name->numberOfRDNs = numRdns; + unsigned len = numRdns * sizeof(CSSM_X509_RDN); + x509Name->RelativeDistinguishedName = (CSSM_X509_RDN_PTR)malloc(len); + memset(x509Name->RelativeDistinguishedName, 0, len); + + for(unsigned rdnDex=0; rdnDexRelativeDistinguishedName[rdnDex]; + rdnCreate(&rdn); + } +} + +static unsigned x509NameCompare( + const CSSM_X509_NAME_PTR n1, + const CSSM_X509_NAME_PTR n2) +{ + if(n1->numberOfRDNs != n2->numberOfRDNs) { + printf("***Mismatch in numberOfRDNs\n"); + return 1; + } + unsigned rtn = 0; + for(unsigned rdnDex=0; rdnDexnumberOfRDNs; rdnDex++) { + CSSM_X509_RDN &rdn1 = n1->RelativeDistinguishedName[rdnDex]; + CSSM_X509_RDN &rdn2 = n2->RelativeDistinguishedName[rdnDex]; + rtn += rdnCompare(&rdn1, &rdn2); + } + return rtn; +} + +static void x509NameFree( + CSSM_X509_NAME_PTR n) +{ + for(unsigned rdnDex=0; rdnDexnumberOfRDNs; rdnDex++) { + CSSM_X509_RDN &rdn = n->RelativeDistinguishedName[rdnDex]; + rdnFree(&rdn); + } + free(n->RelativeDistinguishedName); +} + +#pragma mark --- general purpose GeneralNames generator --- + +#define SOME_URL_1 (char *)"http://foo.bar.com" +#define SOME_URL_2 (char *)"http://bar.foo.com" +#define SOME_DNS_1 (char *)"Some DNS" +#define SOME_DNS_2 (char *)"Another DNS" +unsigned char someIpAdr_1[] = {208, 161, 124, 209 }; +unsigned char someIpAdr_2[] = {10, 0, 61, 5}; + +static void genNameCreate(CE_GeneralName *name) +{ + unsigned type = genRand(1, 5); + const char *src; + unsigned char *usrc; + switch(type) { + case 1: + name->nameType = GNT_URI; + name->berEncoded = CSSM_FALSE; + src = randBool() ? SOME_URL_1 : SOME_URL_2; + appCopyData(src, strlen(src), &name->name); + break; + + case 2: + name->nameType = GNT_RegisteredID; + name->berEncoded = CSSM_FALSE; + appCopyData(CSSMOID_SubjectDirectoryAttributes.Data, + CSSMOID_SubjectDirectoryAttributes.Length, + &name->name); + break; + + case 3: + name->nameType = GNT_DNSName; + name->berEncoded = CSSM_FALSE; + src = randBool() ? SOME_DNS_1 : SOME_DNS_2; + appCopyData(src, strlen(src), &name->name); + break; + + case 4: + name->nameType = GNT_IPAddress; + name->berEncoded = CSSM_FALSE; + usrc = randBool() ? someIpAdr_1 : someIpAdr_2; + appCopyData(usrc, 4, &name->name); + break; + + case 5: + { + /* X509_NAME, the hard one */ + name->nameType = GNT_DirectoryName; + name->berEncoded = CSSM_FALSE; + appSetupCssmData(&name->name, sizeof(CSSM_X509_NAME)); + x509NameCreate((CSSM_X509_NAME_PTR)name->name.Data); + } + } +} + +static void genNamesCreate(void *arg) +{ + CE_GeneralNames *names = (CE_GeneralNames *)arg; + names->numNames = genRand(1, 3); + // one at a time + //names->numNames = 1; + names->generalName = (CE_GeneralName *)malloc(names->numNames * + sizeof(CE_GeneralName)); + memset(names->generalName, 0, names->numNames * sizeof(CE_GeneralName)); + + for(unsigned i=0; inumNames; i++) { + CE_GeneralName *name = &names->generalName[i]; + genNameCreate(name); + } +} + +static unsigned genNameCompare( + CE_GeneralName *npre, + CE_GeneralName *npost) +{ + unsigned rtn = 0; + if(npre->nameType != npost->nameType) { + printf("***CE_GeneralName.nameType miscompare\n"); + rtn++; + } + if(compBool(npre->berEncoded, npost->berEncoded, + "CE_GeneralName.berEncoded")) { + rtn++; + } + + /* nameType-specific compare */ + switch(npre->nameType) { + case GNT_RFC822Name: + rtn += compCssmData(npre->name, npost->name, + "CE_GeneralName.RFC822Name"); + break; + case GNT_DNSName: + rtn += compCssmData(npre->name, npost->name, + "CE_GeneralName.DNSName"); + break; + case GNT_URI: + rtn += compCssmData(npre->name, npost->name, + "CE_GeneralName.URI"); + break; + case GNT_IPAddress: + rtn += compCssmData(npre->name, npost->name, + "CE_GeneralName.RFIPAddressC822Name"); + break; + case GNT_RegisteredID: + rtn += compCssmData(npre->name, npost->name, + "CE_GeneralName.RegisteredID"); + break; + case GNT_DirectoryName: + rtn += x509NameCompare((CSSM_X509_NAME_PTR)npre->name.Data, + (CSSM_X509_NAME_PTR)npost->name.Data); + break; + default: + printf("****BRRZAP! genNamesCompare needs work\n"); + rtn++; + } + return rtn; +} + +static unsigned genNamesCompare(const void *pre, const void *post) +{ + const CE_GeneralNames *gnPre = (CE_GeneralNames *)pre; + const CE_GeneralNames *gnPost = (CE_GeneralNames *)post; + unsigned rtn = 0; + + if((gnPre == NULL) || (gnPost == NULL)) { + printf("***Bad GenNames pointer\n"); + return 1; + } + if(gnPre->numNames != gnPost->numNames) { + printf("***CE_GeneralNames.numNames miscompare\n"); + return 1; + } + for(unsigned dex=0; dexnumNames; dex++) { + CE_GeneralName *npre = &gnPre->generalName[dex]; + CE_GeneralName *npost = &gnPost->generalName[dex]; + rtn += genNameCompare(npre, npost); + } + return rtn; +} + + +static void genNameFree(CE_GeneralName *n) +{ + switch(n->nameType) { + case GNT_DirectoryName: + x509NameFree((CSSM_X509_NAME_PTR)n->name.Data); + CSSM_FREE(n->name.Data); + break; + default: + CSSM_FREE(n->name.Data); + break; + } +} + + +static void genNamesFree(void *arg) +{ + const CE_GeneralNames *gn = (CE_GeneralNames *)arg; + for(unsigned dex=0; dexnumNames; dex++) { + CE_GeneralName *n = (CE_GeneralName *)&gn->generalName[dex]; + genNameFree(n); + } + free(gn->generalName); +} + +#pragma mark --- CE_CRLDistPointsSyntax --- +static void cdpCreate(void *arg) +{ + CE_CRLDistPointsSyntax *cdp = (CE_CRLDistPointsSyntax *)arg; + //cdp->numDistPoints = genRand(1,3); + // one at a time + cdp->numDistPoints = 1; + unsigned len = sizeof(CE_CRLDistributionPoint) * cdp->numDistPoints; + cdp->distPoints = (CE_CRLDistributionPoint *)malloc(len); + memset(cdp->distPoints, 0, len); + + for(unsigned dex=0; dexnumDistPoints; dex++) { + CE_CRLDistributionPoint *pt = &cdp->distPoints[dex]; + + /* all fields optional */ + if(randBool()) { + CE_DistributionPointName *dpn = pt->distPointName = + (CE_DistributionPointName *)malloc( + sizeof(CE_DistributionPointName)); + memset(dpn, 0, sizeof(CE_DistributionPointName)); + + /* CE_DistributionPointName has two flavors */ + if(randBool()) { + dpn->nameType = CE_CDNT_FullName; + dpn->dpn.fullName = (CE_GeneralNames *)malloc( + sizeof(CE_GeneralNames)); + memset(dpn->dpn.fullName, 0, sizeof(CE_GeneralNames)); + genNamesCreate(dpn->dpn.fullName); + } + else { + dpn->nameType = CE_CDNT_NameRelativeToCrlIssuer; + dpn->dpn.rdn = (CSSM_X509_RDN_PTR)malloc( + sizeof(CSSM_X509_RDN)); + memset(dpn->dpn.rdn, 0, sizeof(CSSM_X509_RDN)); + rdnCreate(dpn->dpn.rdn); + } + } /* creating CE_DistributionPointName */ + + pt->reasonsPresent = randBool(); + if(pt->reasonsPresent) { + CE_CrlDistReasonFlags *cdr = &pt->reasons; + /* set two random valid bits */ + *cdr = 0; + *cdr |= 1 << genRand(0,7); + *cdr |= 1 << genRand(0,7); + } + + /* make sure at least one present */ + if((!pt->distPointName && !pt->reasonsPresent) || randBool()) { + pt->crlIssuer = (CE_GeneralNames *)malloc(sizeof(CE_GeneralNames)); + memset(pt->crlIssuer, 0, sizeof(CE_GeneralNames)); + genNamesCreate(pt->crlIssuer); + } + } +} + +static unsigned cdpCompare(const void *pre, const void *post) +{ + CE_CRLDistPointsSyntax *cpre = (CE_CRLDistPointsSyntax *)pre; + CE_CRLDistPointsSyntax *cpost = (CE_CRLDistPointsSyntax *)post; + + if(cpre->numDistPoints != cpost->numDistPoints) { + printf("***CE_CRLDistPointsSyntax.numDistPoints miscompare\n"); + return 1; + } + unsigned rtn = 0; + for(unsigned dex=0; dexnumDistPoints; dex++) { + CE_CRLDistributionPoint *ptpre = &cpre->distPoints[dex]; + CE_CRLDistributionPoint *ptpost = &cpost->distPoints[dex]; + + if(ptpre->distPointName) { + if(ptpost->distPointName == NULL) { + printf("***NULL distPointName post decode\n"); + rtn++; + goto checkReason; + } + CE_DistributionPointName *dpnpre = ptpre->distPointName; + CE_DistributionPointName *dpnpost = ptpost->distPointName; + if(dpnpre->nameType != dpnpost->nameType) { + printf("***CE_DistributionPointName.nameType miscompare\n"); + rtn++; + goto checkReason; + } + if(dpnpre->nameType == CE_CDNT_FullName) { + rtn += genNamesCompare(dpnpre->dpn.fullName, dpnpost->dpn.fullName); + } + else { + rtn += rdnCompare(dpnpre->dpn.rdn, dpnpost->dpn.rdn); + } + + } + else if(ptpost->distPointName != NULL) { + printf("***NON NULL distPointName post decode\n"); + rtn++; + } + + checkReason: + if(ptpre->reasons != ptpost->reasons) { + printf("***CE_CRLDistributionPoint.reasons miscompare\n"); + rtn++; + } + + if(ptpre->crlIssuer) { + if(ptpost->crlIssuer == NULL) { + printf("***NULL crlIssuer post decode\n"); + rtn++; + continue; + } + CE_GeneralNames *gnpre = ptpre->crlIssuer; + CE_GeneralNames *gnpost = ptpost->crlIssuer; + rtn += genNamesCompare(gnpre, gnpost); + } + else if(ptpost->crlIssuer != NULL) { + printf("***NON NULL crlIssuer post decode\n"); + rtn++; + } + } + return rtn; +} + +static void cdpFree(void *arg) +{ + CE_CRLDistPointsSyntax *cdp = (CE_CRLDistPointsSyntax *)arg; + for(unsigned dex=0; dexnumDistPoints; dex++) { + CE_CRLDistributionPoint *pt = &cdp->distPoints[dex]; + if(pt->distPointName) { + CE_DistributionPointName *dpn = pt->distPointName; + if(dpn->nameType == CE_CDNT_FullName) { + genNamesFree(dpn->dpn.fullName); + free(dpn->dpn.fullName); + } + else { + rdnFree(dpn->dpn.rdn); + free(dpn->dpn.rdn); + } + free(dpn); + } + + if(pt->crlIssuer) { + genNamesFree(pt->crlIssuer); + free(pt->crlIssuer); + } + } + free(cdp->distPoints); +} + +#pragma mark --- CE_AuthorityKeyID --- +static void authKeyIdCreate(void *arg) +{ + CE_AuthorityKeyID *akid = (CE_AuthorityKeyID *)arg; + + /* all three fields optional */ + + akid->keyIdentifierPresent = randBool(); + if(akid->keyIdentifierPresent) { + randData(&akid->keyIdentifier, 16); + } + + akid->generalNamesPresent = randBool(); + if(akid->generalNamesPresent) { + akid->generalNames = + (CE_GeneralNames *)malloc(sizeof(CE_GeneralNames)); + memset(akid->generalNames, 0, sizeof(CE_GeneralNames)); + genNamesCreate(akid->generalNames); + } + + if(!akid->keyIdentifierPresent & !akid->generalNamesPresent) { + /* force at least one to be present */ + akid->serialNumberPresent = CSSM_TRUE; + } + else { + akid->serialNumberPresent = randBool(); + } + if(akid->serialNumberPresent) { + randData(&akid->serialNumber, 16); + } + +} + +static unsigned authKeyIdCompare(const void *pre, const void *post) +{ + CE_AuthorityKeyID *akpre = (CE_AuthorityKeyID *)pre; + CE_AuthorityKeyID *akpost = (CE_AuthorityKeyID *)post; + unsigned rtn = 0; + + if(compBool(akpre->keyIdentifierPresent, akpost->keyIdentifierPresent, + "CE_AuthorityKeyID.keyIdentifierPresent")) { + rtn++; + } + else if(akpre->keyIdentifierPresent) { + rtn += compCssmData(akpre->keyIdentifier, + akpost->keyIdentifier, "CE_AuthorityKeyID.keyIdentifier"); + } + + if(compBool(akpre->generalNamesPresent, akpost->generalNamesPresent, + "CE_AuthorityKeyID.generalNamesPresent")) { + rtn++; + } + else if(akpre->generalNamesPresent) { + rtn += genNamesCompare(akpre->generalNames, + akpost->generalNames); + } + + if(compBool(akpre->serialNumberPresent, akpost->serialNumberPresent, + "CE_AuthorityKeyID.serialNumberPresent")) { + rtn++; + } + else if(akpre->serialNumberPresent) { + rtn += compCssmData(akpre->serialNumber, + akpost->serialNumber, "CE_AuthorityKeyID.serialNumber"); + } + return rtn; +} + +static void authKeyIdFree(void *arg) +{ + CE_AuthorityKeyID *akid = (CE_AuthorityKeyID *)arg; + + if(akid->keyIdentifier.Data) { + free(akid->keyIdentifier.Data); + } + if(akid->generalNames) { + genNamesFree(akid->generalNames); // genNamesCreate mallocd + free(akid->generalNames); // we mallocd + } + if(akid->serialNumber.Data) { + free(akid->serialNumber.Data); + } +} + +#pragma mark --- CE_CertPolicies --- + +/* random OIDs, pick 1..NUM_CP_OIDS */ +static CSSM_OID cpOids[] = +{ + CSSMOID_EmailAddress, + CSSMOID_UnstructuredName, + CSSMOID_ContentType, + CSSMOID_MessageDigest +}; +#define NUM_CP_OIDS 4 + +/* CPS strings, pick one of NUM_CPS_STR */ +static char *someCPSs[] = +{ + (char *)"http://www.apple.com", + (char *)"https://cdnow.com", + (char *)"ftp:backwards.com" +}; +#define NUM_CPS_STR 3 + +/* make these looks like real sequences */ +static uint8 someUnotice[] = {0x30, 0x03, BER_TAG_BOOLEAN, 1, 0xff}; +static uint8 someOtherData[] = {0x30, 0x02, BER_TAG_NULL, 0}; + +static void cpCreate(void *arg) +{ + CE_CertPolicies *cp = (CE_CertPolicies *)arg; + cp->numPolicies = genRand(1,3); + //cp->numPolicies = 1; + unsigned len = sizeof(CE_PolicyInformation) * cp->numPolicies; + cp->policies = (CE_PolicyInformation *)malloc(len); + memset(cp->policies, 0, len); + + for(unsigned polDex=0; polDexnumPolicies; polDex++) { + CE_PolicyInformation *pi = &cp->policies[polDex]; + unsigned die = genRand(1, NUM_CP_OIDS); + pi->certPolicyId = cpOids[die - 1]; + unsigned numQual = genRand(1,3); + pi->numPolicyQualifiers = numQual; + len = sizeof(CE_PolicyQualifierInfo) * numQual; + pi->policyQualifiers = (CE_PolicyQualifierInfo *) + malloc(len); + memset(pi->policyQualifiers, 0, len); + for(unsigned cpiDex=0; cpiDexpolicyQualifiers[cpiDex]; + if(randBool()) { + qi->policyQualifierId = CSSMOID_QT_CPS; + die = genRand(1, NUM_CPS_STR); + qi->qualifier.Data = (uint8 *)someCPSs[die - 1]; + qi->qualifier.Length = strlen((char *)qi->qualifier.Data); + } + else { + qi->policyQualifierId = CSSMOID_QT_UNOTICE; + if(randBool()) { + qi->qualifier.Data = someUnotice; + qi->qualifier.Length = 5; + } + else { + qi->qualifier.Data = someOtherData; + qi->qualifier.Length = 4; + } + } + } + } +} + +static unsigned cpCompare(const void *pre, const void *post) +{ + CE_CertPolicies *cppre = (CE_CertPolicies *)pre; + CE_CertPolicies *cppost = (CE_CertPolicies *)post; + + if(cppre->numPolicies != cppost->numPolicies) { + printf("CE_CertPolicies.numPolicies mismatch\n"); + return 1; + } + unsigned rtn = 0; + for(unsigned polDex=0; polDexnumPolicies; polDex++) { + CE_PolicyInformation *pipre = &cppre->policies[polDex]; + CE_PolicyInformation *pipost = &cppost->policies[polDex]; + rtn += compCssmData(pipre->certPolicyId, pipost->certPolicyId, + "CE_PolicyInformation.certPolicyId"); + if(pipre->numPolicyQualifiers != pipost->numPolicyQualifiers) { + printf("CE_PolicyInformation.CE_PolicyInformation mismatch\n"); + rtn++; + continue; + } + + for(unsigned qiDex=0; qiDexnumPolicyQualifiers; qiDex++) { + CE_PolicyQualifierInfo *qipre = &pipre->policyQualifiers[qiDex]; + CE_PolicyQualifierInfo *qipost = &pipost->policyQualifiers[qiDex]; + rtn += compCssmData(qipre->policyQualifierId, + qipost->policyQualifierId, + "CE_PolicyQualifierInfo.policyQualifierId"); + rtn += compCssmData(qipre->qualifier, + qipost->qualifier, + "CE_PolicyQualifierInfo.qualifier"); + } + } + return rtn; +} + +static void cpFree(void *arg) +{ + CE_CertPolicies *cp = (CE_CertPolicies *)arg; + for(unsigned polDex=0; polDexnumPolicies; polDex++) { + CE_PolicyInformation *pi = &cp->policies[polDex]; + free(pi->policyQualifiers); + } + free(cp->policies); +} + +#pragma mark --- CE_AuthorityInfoAccess --- + +/* random OIDs, pick 1..NUM_AI_OIDS */ +static CSSM_OID aiOids[] = +{ + CSSMOID_AD_OCSP, + CSSMOID_AD_CA_ISSUERS, + CSSMOID_AD_TIME_STAMPING, + CSSMOID_AD_CA_REPOSITORY +}; +#define NUM_AI_OIDS 4 + +static void aiaCreate(void *arg) +{ + CE_AuthorityInfoAccess *aia = (CE_AuthorityInfoAccess *)arg; + aia->numAccessDescriptions = genRand(1,3); + unsigned len = aia->numAccessDescriptions * sizeof(CE_AccessDescription); + aia->accessDescriptions = (CE_AccessDescription *)malloc(len); + memset(aia->accessDescriptions, 0, len); + + for(unsigned dex=0; dexnumAccessDescriptions; dex++) { + CE_AccessDescription *ad = &aia->accessDescriptions[dex]; + int die = genRand(1, NUM_AI_OIDS); + ad->accessMethod = aiOids[die - 1]; + genNameCreate(&ad->accessLocation); + } +} + +static unsigned aiaCompare(const void *pre, const void *post) +{ + CE_AuthorityInfoAccess *apre = (CE_AuthorityInfoAccess *)pre; + CE_AuthorityInfoAccess *apost = (CE_AuthorityInfoAccess *)post; + unsigned rtn = 0; + + if(apre->numAccessDescriptions != apost->numAccessDescriptions) { + printf("***CE_AuthorityInfoAccess.numAccessDescriptions miscompare\n"); + return 1; + } + for(unsigned dex=0; dexnumAccessDescriptions; dex++) { + CE_AccessDescription *adPre = &apre->accessDescriptions[dex]; + CE_AccessDescription *adPost = &apost->accessDescriptions[dex]; + if(compCssmData(adPre->accessMethod, adPost->accessMethod, + "CE_AccessDescription.accessMethod")) { + rtn++; + } + rtn += genNameCompare(&adPre->accessLocation, &adPost->accessLocation); + } + return rtn; +} + +static void aiaFree(void *arg) +{ + CE_AuthorityInfoAccess *aia = (CE_AuthorityInfoAccess *)arg; + for(unsigned dex=0; dexnumAccessDescriptions; dex++) { + CE_AccessDescription *ad = &aia->accessDescriptions[dex]; + genNameFree(&ad->accessLocation); + } + free(aia->accessDescriptions); +} + +#pragma mark --- test definitions --- + +/* + * Define one extension test. + */ + +/* + * Cook up this extension with random, reasonable values. + * Incoming pointer refers to extension-specific C struct, mallocd + * and zeroed by main test routine. + */ +typedef void (*extenCreateFcn)(void *arg); + +/* + * Compare two instances of this extension. Return number of + * compare errors. + */ +typedef unsigned (*extenCompareFcn)( + const void *preEncode, + const void *postEncode); + +/* + * Free struct components mallocd in extenCreateFcn. Do not free + * the outer struct. + */ +typedef void (*extenFreeFcn)(void *arg); + +typedef struct { + /* three extension-specific functions */ + extenCreateFcn createFcn; + extenCompareFcn compareFcn; + extenFreeFcn freeFcn; + + /* size of C struct passed to all three functions */ + unsigned extenSize; + + /* the CE_DataType for this extension, used on encode */ + CE_DataType extenType; + + /* the OID for this extension, tested on decode */ + CSSM_OID extenOid; + + /* description for error logging and blob writing */ + const char *extenDescr; + + /* command-line letter for this one */ + char extenLetter; + +} ExtenTest; + +/* empty freeFcn means no extension-specific resources to free */ +#define NO_FREE NULL + +static ExtenTest extenTests[] = { + { kuCreate, kuCompare, NO_FREE, + sizeof(CE_KeyUsage), + DT_KeyUsage, CSSMOID_KeyUsage, + "KeyUsage", 'k' }, + { bcCreate, bcCompare, NO_FREE, + sizeof(CE_BasicConstraints), + DT_BasicConstraints, CSSMOID_BasicConstraints, + "BasicConstraints", 'b' }, + { ekuCreate, ekuCompare, NO_FREE, + sizeof(CE_ExtendedKeyUsage), + DT_ExtendedKeyUsage, CSSMOID_ExtendedKeyUsage, + "ExtendedKeyUsage", 'x' }, + { skidCreate, skidCompare, skidFree, + sizeof(CSSM_DATA), + DT_SubjectKeyID, CSSMOID_SubjectKeyIdentifier, + "SubjectKeyID", 's' }, + { authKeyIdCreate, authKeyIdCompare, authKeyIdFree, + sizeof(CE_AuthorityKeyID), + DT_AuthorityKeyID, CSSMOID_AuthorityKeyIdentifier, + "AuthorityKeyID", 'a' }, + { genNamesCreate, genNamesCompare, genNamesFree, + sizeof(CE_GeneralNames), + DT_SubjectAltName, CSSMOID_SubjectAltName, + "SubjectAltName", 't' }, + { genNamesCreate, genNamesCompare, genNamesFree, + sizeof(CE_GeneralNames), + DT_IssuerAltName, CSSMOID_IssuerAltName, + "IssuerAltName", 'i' }, + { nctCreate, nctCompare, NO_FREE, + sizeof(CE_NetscapeCertType), + DT_NetscapeCertType, CSSMOID_NetscapeCertType, + "NetscapeCertType", 'n' }, + { cdpCreate, cdpCompare, cdpFree, + sizeof(CE_CRLDistPointsSyntax), + DT_CrlDistributionPoints, CSSMOID_CrlDistributionPoints, + "CRLDistPoints", 'p' }, + { cpCreate, cpCompare, cpFree, + sizeof(CE_CertPolicies), + DT_CertPolicies, CSSMOID_CertificatePolicies, + "CertPolicies", 'c' }, + { aiaCreate, aiaCompare, aiaFree, + sizeof(CE_AuthorityInfoAccess), + DT_AuthorityInfoAccess, CSSMOID_AuthorityInfoAccess, + "AuthorityInfoAccess", 'A' }, + #if 0 + /* TP doesn't have this, neither does certextensions.h! */ + { aiaCreate, aiaCompare, aiaFree, + sizeof(CE_AuthorityInfoAccess), CSSMOID_SubjectInfoAccess, + "SubjectInfoAccess", 'S' }, + #endif +}; + +#define NUM_EXTEN_TESTS (sizeof(extenTests) / sizeof(ExtenTest)) + +static void printExtenPre( + CE_DataAndType *extenData, + CSSM_OID *extenOid, + OidParser &parser) +{ + CSSM_FIELD field; + CSSM_X509_EXTENSION extn; + + /* + * Convert pre-digested into CSSM_X509_EXTENSION that + * printCertField() can understand + */ + extn.extnId = *extenOid; + extn.critical = extenData->critical; + extn.format = CSSM_X509_DATAFORMAT_PARSED; + extn.value.parsedValue = &extenData->extension; + field.FieldOid = *extenOid; + field.FieldValue.Data = (uint8 *)&extn; + field.FieldValue.Length = sizeof(CSSM_X509_EXTENSION); + printf("=== PRE-ENCODE:\n"); + printCertField(field, parser, CSSM_TRUE); +} + + +static void printExten( + CSSM_X509_EXTENSION &extn, + OidParser &parser) +{ + CSSM_FIELD field; + field.FieldOid = extn.extnId; + field.FieldValue.Data = (uint8 *)&extn; + field.FieldValue.Length = sizeof(CSSM_X509_EXTENSION); + printf("=== POST-DECODE:\n"); + printCertField(field, parser, CSSM_TRUE); +} + +static int doTest( + CSSM_CL_HANDLE clHand, + CSSM_TP_HANDLE tpHand, + CSSM_CSP_HANDLE cspHand, + ExtenTest &extenTest, + bool writeBlobs, + const char *constFileName, // all blobs to this file if non-NULL + bool displayExtens, + OidParser &parser) +{ + CSSM_APPLE_TP_CERT_REQUEST certReq; + CSSM_TP_REQUEST_SET reqSet; + sint32 estTime; + CSSM_BOOL confirmRequired; + CSSM_TP_RESULT_SET_PTR resultSet; + CSSM_ENCODED_CERT *encCert; + CSSM_TP_CALLERAUTH_CONTEXT CallerAuthContext; + CSSM_FIELD policyId; + CE_DataAndType extPre; + CSSM_RETURN crtn; + CSSM_DATA refId; // mallocd by CSSM_TP_SubmitCredRequest + CSSM_DATA signedCert = {0, NULL}; + + memset(&certReq, 0, sizeof(certReq)); + memset(&extPre, 0, sizeof(extPre)); + + /* + * Cook up a random and reasonable instance of the C struct + * associated with this extension. + */ + extenTest.createFcn(&extPre.extension); + + /* + * Cook up the associated CSSM_X509_EXTENSION. + */ + extPre.type = extenTest.extenType; + extPre.critical = randBool(); + + /* + * Now the cert request proper. + */ + certReq.cspHand = cspHand; + certReq.clHand = clHand; + certReq.serialNumber = 0x8765; + certReq.numSubjectNames = NUM_DUMMY_NAMES; + certReq.subjectNames = dummyRdn; + certReq.numIssuerNames = NUM_DUMMY_NAMES; + certReq.issuerNames = dummyRdn; + certReq.certPublicKey = &subjPubKey; + certReq.issuerPrivateKey = &subjPrivKey; + certReq.signatureAlg = CSSM_ALGID_SHA1WithRSA; + certReq.signatureOid = SIG_OID; + certReq.notBefore = 0; // now + certReq.notAfter = 10000; // seconds from now + certReq.numExtensions = 1; + certReq.extensions = &extPre; + + reqSet.NumberOfRequests = 1; + reqSet.Requests = &certReq; + + /* a big CSSM_TP_CALLERAUTH_CONTEXT just to specify an OID */ + memset(&CallerAuthContext, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT)); + memset(&policyId, 0, sizeof(CSSM_FIELD)); + policyId.FieldOid = CSSMOID_APPLE_TP_LOCAL_CERT_GEN; + CallerAuthContext.Policy.NumberOfPolicyIds = 1; + CallerAuthContext.Policy.PolicyIds = &policyId; + + /* GO */ + crtn = CSSM_TP_SubmitCredRequest(tpHand, + NULL, // PreferredAuthority + CSSM_TP_AUTHORITY_REQUEST_CERTISSUE, + &reqSet, + &CallerAuthContext, + &estTime, + &refId); + if(crtn) { + printError("CSSM_TP_SubmitCredRequest", crtn); + /* show what we tried to encode and decode */ + printExtenPre(&extPre, &extenTest.extenOid, parser); + return 1; + } + crtn = CSSM_TP_RetrieveCredResult(tpHand, + &refId, + NULL, // CallerAuthCredentials + &estTime, + &confirmRequired, + &resultSet); // leaks..... + if(crtn) { + printError("CSSM_TP_RetrieveCredResult", crtn); + /* show what we tried to encode and decode */ + printExtenPre(&extPre, &extenTest.extenOid, parser); + return 1; + } + if(resultSet == NULL) { + printf("***CSSM_TP_RetrieveCredResult returned NULL result set.\n"); + /* show what we tried to encode and decode */ + printExtenPre(&extPre, &extenTest.extenOid, parser); + return 1; + } + encCert = (CSSM_ENCODED_CERT *)resultSet->Results; + signedCert = encCert->CertBlob; + + if(writeBlobs) { + char fileName[200]; + if(constFileName) { + strcpy(fileName, constFileName); + } + else { + sprintf(fileName, "%scert.der", extenTest.extenDescr); + } + writeFile(fileName, signedCert.Data, signedCert.Length); + printf("...wrote %lu bytes to %s\n", signedCert.Length, fileName); + } + + /* snag the same extension from the encoded cert */ + CSSM_DATA_PTR postField; + CSSM_HANDLE resultHand; + uint32 numFields; + + crtn = CSSM_CL_CertGetFirstFieldValue(clHand, + &signedCert, + &extenTest.extenOid, + &resultHand, + &numFields, + &postField); + if(crtn) { + printf("****Extension field not found on decode for %s\n", + extenTest.extenDescr); + printError("CSSM_CL_CertGetFirstFieldValue", crtn); + + /* show what we tried to encode and decode */ + printExtenPre(&extPre, &extenTest.extenOid, parser); + return 1; + } + + if(numFields != 1) { + printf("****GetFirstFieldValue: expect 1 value, got %u\n", + (unsigned)numFields); + return 1; + } + CSSM_CL_CertAbortQuery(clHand, resultHand); + + /* verify the fields we generated */ + CSSM_X509_EXTENSION *extnPost = (CSSM_X509_EXTENSION *)postField->Data; + if((extnPost == NULL) || + (postField->Length != sizeof(CSSM_X509_EXTENSION))) { + printf("***Malformed CSSM_X509_EXTENSION (1) after decode\n"); + return 1; + } + int rtn = 0; + rtn += compBool(extPre.critical, extnPost->critical, + "CSSM_X509_EXTENSION.critical"); + rtn += compCssmData(extenTest.extenOid, extnPost->extnId, + "CSSM_X509_EXTENSION.extnId"); + + if(extnPost->format != CSSM_X509_DATAFORMAT_PARSED) { + printf("***Expected CSSM_X509_DATAFORMAT_PARSED (%x(x), got %x(x)\n", + CSSM_X509_DATAFORMAT_PARSED, extnPost->format); + } + if(extnPost->value.parsedValue == NULL) { + printf("***no parsedValue pointer!\n"); + return 1; + } + + /* down to extension-specific compare */ + rtn += extenTest.compareFcn(&extPre.extension, extnPost->value.parsedValue); + + if(rtn) { + /* print preencode only on error */ + printExtenPre(&extPre, &extenTest.extenOid, parser); + } + if(displayExtens || rtn) { + printExten(*extnPost, parser); + } + + /* free the allocated data */ + if(extenTest.freeFcn) { + extenTest.freeFcn(&extPre.extension); + } + CSSM_CL_FreeFieldValue(clHand, &extenTest.extenOid, postField); + CSSM_FREE(signedCert.Data); + CSSM_FREE(encCert); + CSSM_FREE(resultSet); + return rtn; +} + +static void doPause(bool pause) +{ + if(!pause) { + return; + } + fpurge(stdin); + printf("CR to continue "); + getchar(); +} + +int main(int argc, char **argv) +{ + CSSM_CL_HANDLE clHand; + CSSM_TP_HANDLE tpHand; + CSSM_CSP_HANDLE cspHand; + CSSM_RETURN crtn; + int arg; + int rtn; + OidParser parser; + char *argp; + unsigned i; + + /* user-specificied params */ + unsigned minExtenNum = 0; + unsigned maxExtenNum = NUM_EXTEN_TESTS-1; + bool writeBlobs = false; + bool displayExtens = false; + bool quiet = false; + unsigned loops = LOOPS_DEF; + bool pauseLoop = false; + bool pauseCert = false; + const char *constFileName = NULL; + + for(arg=1; argaXzx&8Ce;a8+#cH8atU98yQYS=H830 zzWJu`Tz;gC=V?)aIh9>a`;T9&6V`lqGeNDT`=sdhgI%wa&0dvBlv>2CX$$^#|AxQm z{=nK*Yj35OKRR zOVsUmpP0RTwe+9IP2NHY*=rTdd$)c*-O0qv$iTR`i7~~Xi7^2jAF{$MOa=@F+(5s` z^0TloGqEl(umN%8SxgO#4Gb6PFVJn%&L}AP&@#|qeKGy_Egc>{JfR&73JCMgz?{->9v+Sc^;WgkA@ zkafjFLZ@0%&p=g78EQvPetJHN9r|U(U@?$Ms9Auyjv=$i;pnY8%{PMgt|v@qX7}~( z`k{Q7L;J6k#w@jOdQUqQa?khN$=Vc^ziO(4#NlHRM$TGYU+unDE^@nj{9tv7;w69o z>s1A!(mvl9rwJ4Xt)7e& Nk8i%VD)H!PW&nH?DSH3_ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/extendAttrTest/extendAttrTest.cpp b/SecurityTests/clxutils/extendAttrTest/extendAttrTest.cpp new file mode 100644 index 00000000..ee4fc2dd --- /dev/null +++ b/SecurityTests/clxutils/extendAttrTest/extendAttrTest.cpp @@ -0,0 +1,526 @@ +/* + * extendAttrTest.cpp + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEFAULT_KC_NAME "extendAttr.keychain" + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" -k keychain -- default is %s\n", DEFAULT_KC_NAME); + printf(" -n -- don't delete attributes or keychain\n"); + printf(" -q -- quiet\n"); + exit(1); +} + +/* RSA keys, both in OpenSSL format */ +#define PUB_KEY "rsakey_pub.der" +#define PRIV_KEY "rsakey_priv.der" +#define CERT_FILE "amazon_v3.100.cer" +#define PWD_SERVICE "some service" +#define PWD_ACCOUNT "some account" +#define PWD_PWD "some password" + +/* set up unique extended attributes for each tested item */ +typedef struct { + CFStringRef attr1Name; + const char *attr1Value; + CFStringRef attr2Name; + const char *attr2Value; +} ItemAttrs; + +static const ItemAttrs pubKeyAttrs = { + CFSTR("one pub key Attribute"), + "some pub key value", + CFSTR("another pub key Attribute"), + "another pub key value" +}; + +static const ItemAttrs privKeyAttrs = { + CFSTR("one priv key Attribute"), + "some priv key value", + CFSTR("another priv key Attribute"), + "another priv key value" +}; + +static const ItemAttrs certAttrs = { + CFSTR("one cert Attribute"), + "some cert value", + CFSTR("another cert Attribute"), + "another cert value" +}; + +static const ItemAttrs pwdAttrs = { + CFSTR("one pwd Attribute"), + "some pwd value", + CFSTR("another pwd Attribute"), + "another pwd value" +}; + +#define CFRELEASE(cf) if(cf) { CFRelease(cf); } + +/* import file as key into specified keychain */ +static int doImportKey( + const char *fileName, + SecExternalFormat format, + SecExternalItemType itemType, + SecKeychainRef kcRef, + SecKeyRef *keyRef) // RETURNED +{ + unsigned char *item = NULL; + unsigned itemLen = 0; + + if(readFile(fileName, &item, &itemLen)) { + printf("***Error reading %s. \n", fileName); + } + CFDataRef cfd = CFDataCreate(NULL, (const UInt8 *)item, itemLen); + free(item); + SecKeyImportExportParameters params; + memset(¶ms, 0, sizeof(params)); + params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; + params.keyUsage = CSSM_KEYUSE_ANY; + params.keyAttributes = CSSM_KEYATTR_PERMANENT; + if(itemType == kSecItemTypePrivateKey) { + params.keyAttributes |= CSSM_KEYATTR_SENSITIVE; + } + CFArrayRef outArray = NULL; + OSStatus ortn; + ortn = SecKeychainItemImport(cfd, NULL, &format, &itemType, 0, ¶ms, kcRef, &outArray); + if(ortn) { + cssmPerror("SecKeychainItemImport", ortn); + } + CFRelease(cfd); + if(ortn) { + return -1; + } + if((outArray == NULL) || (CFArrayGetCount(outArray) == 0)) { + printf("SecKeychainItemImport succeeded, but no returned items\n"); + return -1; + } + *keyRef = (SecKeyRef)CFArrayGetValueAtIndex(outArray, 0); + if(CFGetTypeID(*keyRef) != SecKeyGetTypeID()) { + printf("***Unknown type returned after import\n"); + return -1; + } + CFRetain(*keyRef); + CFRelease(outArray); + return 0; +} + +/* import file as cert into specified keychain */ +static int doImportCert( + const char *fileName, + SecKeychainRef kcRef, + SecCertificateRef *certRef) // RETURNED +{ + unsigned char *item = NULL; + unsigned itemLen = 0; + + if(readFile(fileName, &item, &itemLen)) { + printf("***Error reading %s. \n", fileName); + return -1; + } + CSSM_DATA certData = {itemLen, (uint8 *)item}; + OSStatus ortn = SecCertificateCreateFromData(&certData, + CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, certRef); + if(ortn) { + cssmPerror("SecCertificateCreateFromData", ortn); + return -1; + } + ortn = SecCertificateAddToKeychain(*certRef, kcRef); + if(ortn) { + cssmPerror("SecCertificateAddToKeychain", ortn); + return -1; + } + return 0; +} + +/* + * Verify specified attr does not exist + * set it + * make sure we get it back + */ +int testOneAttr( + SecKeychainItemRef itemRef, + CFStringRef attrName, + CFDataRef attrVal, + bool quiet) +{ + OSStatus ortn; + CFDataRef fetchedVal = NULL; + int ourRtn = 0; + + if(!quiet) { + printf(" ...verifying attribute doesn't exist\n"); + } + ortn = SecKeychainItemCopyExtendedAttribute(itemRef, attrName, &fetchedVal); + if(ortn != errSecNoSuchAttr) { + printf("***First SecKeychainItemCopyExtendedAttribute returned %d, expected %d\n", + (int)ortn, (int)errSecNoSuchAttr); + ourRtn = -1; + goto errOut; + } + if(!quiet) { + printf(" ...setting attribute\n"); + } + ortn = SecKeychainItemSetExtendedAttribute(itemRef, attrName, attrVal); + if(ortn) { + cssmPerror("SecKeychainItemSetExtendedAttribute", ortn); + ourRtn = -1; + goto errOut; + } + if(!quiet) { + printf(" ...verify attribute\n"); + } + ortn = SecKeychainItemCopyExtendedAttribute(itemRef, attrName, &fetchedVal); + if(ortn) { + cssmPerror("SecKeychainItemCopyExtendedAttribute", ortn); + ourRtn = -1; + goto errOut; + } + if(!CFEqual(fetchedVal, attrVal)) { + printf("***Mismatch in set and fetched attribute\n"); + ourRtn = -1; + } +errOut: + CFRELEASE(fetchedVal); + return ourRtn; +} + +/* + * Set two distinct extended attributes; + * Ensure that each comes back via SecKeychainItemCopyExtendedAttribute(); + * Ensure that both come back via SecKeychainItemCopyAllExtendedAttributes(); + */ +int doTest(SecKeychainItemRef itemRef, + const ItemAttrs &itemAttrs, + bool quiet) +{ + CFDataRef attrVal1 = CFDataCreate(NULL, + (const UInt8 *)itemAttrs.attr1Value, strlen(itemAttrs.attr1Value)); + if(testOneAttr(itemRef, itemAttrs.attr1Name, attrVal1, quiet)) { + return -1; + } + CFDataRef attrVal2 = CFDataCreate(NULL, + (const UInt8 *)itemAttrs.attr2Value, strlen(itemAttrs.attr2Value)); + if(testOneAttr(itemRef, itemAttrs.attr2Name, attrVal2, quiet)) { + return -1; + } + + if(!quiet) { + printf(" ...verify both attributes via CopyAllExtendedAttributes()\n"); + } + /* make sure they both come back in SecKeychainItemCopyAllExtendedAttributes */ + CFArrayRef attrNames = NULL; + CFArrayRef attrValues = NULL; + OSStatus ortn = SecKeychainItemCopyAllExtendedAttributes(itemRef, &attrNames, &attrValues); + if(ortn) { + cssmPerror("SecKeychainItemCopyAllExtendedAttributes", ortn); + return -1; + } + CFIndex numNames = CFArrayGetCount(attrNames); + CFIndex numValues = CFArrayGetCount(attrValues); + if((numNames != 2) || (numValues != 2)) { + printf("***Bad array count after SecKeychainItemCopyAllExtendedAttributes\n"); + printf(" numNames %ld numValues %ld; expected 2 for both\n", + (long)numNames, (long)numValues); + return -1; + } + bool found1 = false; + bool found2 = false; + for(CFIndex dex=0; dex>XT^UiC6n+Wgu$0 zMQ?Hfvrao+Fb0^&%~Dli4N3`nAn^%5u`8c_%>n}f009C(IWhxs&2vVFNNpHN zyf)-Z{&r~p-ZE1SA$5YOOVXWEK-`kk4AfjYRQL1>&iN6Myyp5_C<*4+TN%l@0wDnX zcP`YL&V)s+6EH(QFK2c-1}ptUMsN)Ytd&RUluZ*F zz(kO1s?c&3Q}c~wW-|gI0F%rXgQSgpwZBL0w5epq|Nu!d+WV5@7Ww`DIA}B R^Yh8xd=Pf4{W5R-3g?8okwO3f literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/extendAttrTest/rsakey_pub.der b/SecurityTests/clxutils/extendAttrTest/rsakey_pub.der new file mode 100644 index 0000000000000000000000000000000000000000..c7f6f03acaf244723adf97e6028f47c38e25f544 GIT binary patch literal 94 zcmV-k0HOadTrdp=2`Yw2hW8Bt0RaU714{rfNCH6s`pgS|(WoZv@h@@md?yf?Ejq$T z;C-a(lW5_ISNmyYAZofrZ*l^&PCH&O2AIgrQdMCMN(p-)@d-b%E1!MM0s{d60U +#include +#include +#include +#include "singleItemPicker.h" +#include +#include +#include + +#define DEFAULT_ATTR_NAME "someAttr" + +static void usage(char **argv) +{ + printf("usage: %s op [options]\n", argv[0]); + printf("Op: set, get, delete, getall, dump\n"); + printf("Options:\n"); + printf(" -t itemType -- type = priv|pub|cert; default is public\n"); + printf(" -k keychain -- default is default KC list\n"); + printf(" -p -- use item picker; default is first matching item in keychain\n"); + printf(" -a attrName -- default is %s\n", DEFAULT_ATTR_NAME); + printf(" -A attrValue\n"); + printf(" -n -- no values retrieved on op getall\n"); + printf(" -l -- loop/pause for malloc debug\n"); + exit(1); +} + +#define CFRELEASE(cf) if(cf) { CFRelease(cf); } + +/* + * Print contents of a CFData assuming it's printable + */ +static void printCfData(CFDataRef cfd) +{ + CFIndex len = CFDataGetLength(cfd); + const UInt8 *cp = CFDataGetBytePtr(cfd); + for(CFIndex dex=0; dex>"); + return; + } + const char *cp = (const char *)CFDataGetBytePtr(strData); + CFIndex len = CFDataGetLength(strData); + for(CFIndex dex=0; dexlength; + const char *cp = (const char *)kca->data; + for(unsigned dex=0; dexname; nvp++) { + if(recordType == nvp->value) { + printf("%s", nvp->name); + return; + } + } + printf("Unknown recordType (0x%x)\n", (unsigned)recordType); + return; +} + + +static int dumpExtendAttrRecords( + SecKeychainRef kcRef) +{ + OSStatus ortn; + SecKeychainSearchRef srchRef = NULL; + + ortn = SecKeychainSearchCreateFromAttributes(kcRef, + CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE, + NULL, // no attrs - give me everything + &srchRef); + if(ortn) { + cssmPerror("SecKeychainSearchCreateFromAttributes", ortn); + return -1; + } + + SecKeychainItemRef itemRef = NULL; + unsigned numItems = 0; + for(;;) { + ortn = SecKeychainSearchCopyNext(srchRef, &itemRef); + if(ortn) { + if(ortn == errSecItemNotFound) { + /* normal end of search */ + break; + } + else { + cssmPerror("SecKeychainSearchCopyNext", ortn); + break; + } + } + + /* get some info about the EA record - RecordType (that it's bound to) and + * AttributeName */ + UInt32 tags[2] = { kExtendedAttrRecordTypeAttr, kExtendedAttrAttributeNameAttr }; + UInt32 formats[2] = {0}; + SecKeychainAttributeList *attrList = NULL; + SecKeychainAttributeInfo attrInfo = {2, tags, formats}; + ortn = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, + NULL, &attrList, NULL, NULL); + if(ortn) { + cssmPerror("SecKeychainItemCopyAttributesAndData", ortn); + return -1; + } + printf("Extended Attribute %u:\n", numItems); + for(unsigned dex=0; dex<2; dex++) { + SecKeychainAttribute *attr = &attrList->attr[dex]; + switch(attr->tag) { + case kExtendedAttrRecordTypeAttr: + printf(" Record type : "); + printRecordType(attr->data); + printf("\n"); + break; + + case kExtendedAttrAttributeNameAttr: + printf(" Attribute Name : "); + printAttribute(attr); + printf("\n"); + break; + break; + default: + /* should never happen, right? */ + printf("***Unexpected attr tag when parsing an ExtendedAttr record\n"); + return -1; + } + } + numItems++; + SecKeychainItemFreeAttributesAndData(attrList, NULL); + CFRelease(itemRef); + } + if(numItems == 0) { + printf("...no Extended Attribute records found.\n"); + } + CFRelease(srchRef); + return 0; +} + +typedef enum { + OP_None, + OP_Set, + OP_Get, + OP_Delete, + OP_GetAll, + OP_Dump // search for EXTENDED_ATTRIBUTE records, dump contents +} Op; + +int main(int argc, char **argv) +{ + const char *attrName = DEFAULT_ATTR_NAME; + const char *attrValue = NULL; + const char *kcName = NULL; + KP_ItemType itemType = KPI_PublicKey; + bool takeFirst = true; + bool noValues = false; + bool loopPause = false; + Op op = OP_None; + + if(argc < 2) { + usage(argv); + } + if(!strcmp(argv[1], "set")) { + op = OP_Set; + } + else if(!strcmp(argv[1], "get")) { + op = OP_Get; + } + else if(!strcmp(argv[1], "delete")) { + op = OP_Delete; + } + else if(!strcmp(argv[1], "getall")) { + op = OP_GetAll; + } + else if(!strcmp(argv[1], "dump")) { + op = OP_Dump; + } + else { + usage(argv); + + } + + extern int optind; + optind = 2; + extern char *optarg; + int arg; + while ((arg = getopt(argc, argv, "t:k:pa:A:nlh")) != -1) { + switch (arg) { + case 't': + if(!strcmp(optarg, "priv")) { + itemType = KPI_PrivateKey; + } + else if(!strcmp(optarg, "pub")) { + itemType = KPI_PublicKey; + } + else if(!strcmp(optarg, "cert")) { + itemType = KPI_Cert; + } + else { + printf("***Bad itemType specification.\n"); + usage(argv); + } + break; + case 'k': + kcName = optarg; + break; + case 'p': + takeFirst = false; + break; + case 'a': + attrName = optarg; + break; + case 'A': + attrValue = optarg; + break; + case 'n': + noValues = true; + break; + case 'l': + loopPause = true; + break; + case 'h': + usage(argv); + } + } + if(optind != argc) { + usage(argv); + } + + if((op == OP_Set) && (attrValue == NULL)) { + printf("***I Need an attribute values (-A) to set\n"); + exit(1); + } + + OSStatus ortn; + SecKeychainItemRef theItem = NULL; + SecKeychainRef kcRef = NULL; + + if(kcName) { + ortn = SecKeychainOpen(kcName, &kcRef); + if(ortn) { + cssmPerror("SecKeychainOpen", ortn); + exit(1); + } + } + + if(op == OP_Dump) { + /* we're ready to roll */ + return dumpExtendAttrRecords(kcRef); + } + ortn = singleItemPicker(kcRef, itemType, takeFirst, &theItem); + if(ortn) { + printf("***Error picking item. Aborting.\n"); + exit(1); + } + + CFStringRef attrNameStr = NULL; + CFDataRef attrValueData = NULL; + if(op != OP_GetAll) { + attrNameStr = CFStringCreateWithCString(NULL, attrName, kCFStringEncodingASCII); + } + + do { + switch(op) { + case OP_Set: + attrValueData = CFDataCreate(NULL, (const UInt8 *)attrValue, strlen(attrValue)); + ortn = SecKeychainItemSetExtendedAttribute(theItem, attrNameStr, attrValueData); + if(ortn) { + cssmPerror("SecKeychainItemSetExtendedAttribute", ortn); + } + else { + printf("attribute '%s' set to '%s'.\n", attrName, attrValue); + } + break; + case OP_Get: + ortn = SecKeychainItemCopyExtendedAttribute(theItem, + attrNameStr, &attrValueData); + if(ortn) { + cssmPerror("SecKeychainItemCopyExtendedAttribute", ortn); + } + else { + printf("Attribute '%s' found; value = '", attrName); + printCfData(attrValueData); + printf("'\n"); + } + break; + case OP_Delete: + ortn = SecKeychainItemSetExtendedAttribute(theItem, attrNameStr, NULL); + if(ortn) { + cssmPerror("SecKeychainItemSetExtendedAttribute", ortn); + } + else { + printf("attribute '%s' deleted.\n", attrName); + } + break; + case OP_GetAll: + { + CFArrayRef nameArray = NULL; + CFArrayRef valuesArray = NULL; + CFArrayRef *valuesArrayPtr = noValues ? NULL : &valuesArray; + + ortn = SecKeychainItemCopyAllExtendedAttributes(theItem, + &nameArray, valuesArrayPtr); + if(ortn) { + cssmPerror("SecKeychainItemCopyAllExtendedAttributes", ortn); + break; + } + if(nameArray == NULL) { + printf("***NULL nameArray after successful " + "SecKeychainItemCopyAllExtendedAttributes\n"); + ortn = -1; + break; + } + if(!noValues) { + if(valuesArray == NULL) { + printf("***NULL valuesArray after successful " + "SecKeychainItemCopyAllExtendedAttributes\n"); + ortn = -1; + break; + } + } + ortn = printAttrs(nameArray, valuesArray); + CFRELEASE(nameArray); + CFRELEASE(valuesArray); + break; + } + case OP_Dump: + /* already handled this; satisfy compiler */ + break; + case OP_None: + printf("***BRRRZAP!\n"); + exit(1); + } + if(ortn) { + break; + } + CFRELEASE(attrValueData); + attrValueData = NULL; + + if(loopPause) { + fpurge(stdin); + printf("End of loop; a to abort, anything else to continue: "); + if(getchar() == 'a') { + break; + } + } + } while(loopPause); + return ortn ? -1 : 0; +} diff --git a/SecurityTests/clxutils/extendAttrTool/singleItemPicker.cpp b/SecurityTests/clxutils/extendAttrTool/singleItemPicker.cpp new file mode 100644 index 00000000..792860da --- /dev/null +++ b/SecurityTests/clxutils/extendAttrTool/singleItemPicker.cpp @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2004,2006 Apple Computer, 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@ + */ + +/* + * singleItemPicker.cpp - select a key or cert from a keychain + */ + +#include +#include +#include +#include +#include +#include /* for kcFileName() */ +#include /* for getKcItemAttr() */ +#include +#include "singleItemPicker.h" + +/* + * Class representing one item in the keychain. + */ +class SimplePickerItem +{ +public: + SimplePickerItem(SecKeychainItemRef itemRef); + ~SimplePickerItem(); + + CFDataRef getPrintName() { return mPrintName; } + SecKeychainItemRef itemRef() { return mItemRef; } + char *kcFile() { return mKcFile; } + +private: + SecKeychainItemRef mItemRef; + CFDataRef mPrintName; + char *mKcFile; // file name of keychain this lives on +}; + +SimplePickerItem::SimplePickerItem(SecKeychainItemRef itemRef) + : mItemRef(itemRef), + mPrintName(NULL), + mKcFile(NULL) +{ + OSStatus ortn = getKcItemAttr(itemRef, WA_PrintName, &mPrintName); + if(ortn) { + throw std::invalid_argument("printName attr not available"); + } + + /* stash name of the keychain this lives on */ + SecKeychainRef kcRef; + ortn = SecKeychainItemCopyKeychain(itemRef, &kcRef); + if(ortn) { + cssmPerror("SecKeychainItemCopyKeychain", ortn); + mKcFile = strdup("Unnamed keychain"); + } + else { + mKcFile = kcFileName(kcRef); + } + + mItemRef = mItemRef; + CFRetain(mItemRef); +} + +SimplePickerItem::~SimplePickerItem() +{ + if(mItemRef) { + CFRelease(mItemRef); + } + if(mPrintName) { + CFRelease(mPrintName); + } + if(mKcFile) { + free(mKcFile); + } +} + +typedef std::vector ItemVector; + +/* + * add SimplePickerItem objects of specified type to a ItemVector. + */ +static void getPickerItems( + SecKeychainRef kcRef, + SecItemClass itemClass, // CSSM_DL_DB_RECORD_{PRIVATE,PRIVATE}_KEY, etc. + ItemVector &itemVector) +{ + SecKeychainSearchRef srchRef = NULL; + SecKeychainItemRef kcItem; + + OSStatus ortn = SecKeychainSearchCreateFromAttributes(kcRef, + itemClass, + NULL, // any attrs + &srchRef); + if(ortn) { + cssmPerror("SecKeychainSearchCreateFromAttributes", ortn); + return; + } + do { + ortn = SecKeychainSearchCopyNext(srchRef, &kcItem); + if(ortn) { + break; + } + try { + SimplePickerItem *pickerItem = new SimplePickerItem(kcItem); + itemVector.push_back(pickerItem); + } + catch(...) { + printf("**** item failed SimplePickerItem constructor ***\n"); + /* but keep going */ + } + /* SimplePickerKey holds a ref */ + CFRelease(kcItem); + } while(ortn == noErr); + CFRelease(srchRef); +} + +/* + * Print contents of a CFData assuming it's printable + */ +static void printCfData(CFDataRef cfd) +{ + CFIndex len = CFDataGetLength(cfd); + const UInt8 *cp = CFDataGetBytePtr(cfd); + for(CFIndex dex=0; dex items; + + switch(itemType) { + case KPI_PrivateKey: + itemClass = kSecPrivateKeyItemClass; + break; + case KPI_PublicKey: + itemClass = kSecPublicKeyItemClass; + break; + case KPI_Cert: + itemClass = kSecCertificateItemClass; + break; + default: + printf("***BRRZAP! Wrong ItemType for singleItemPicker()\n"); + return paramErr; + } + /* First create a arrays of all of the items, parsed and ready for use */ + getPickerItems(kcRef, itemClass, items); + numItems = items.size(); + + if(numItems == 0) { + printf("...singleItemPicker: no keys found\n"); + return errSecItemNotFound; + } + if(takeFirst) { + *itemRef = items[0]->itemRef(); + CFRetain(*itemRef); + goto done; + } + + for(dex=0; dexgetPrintName()); + printf("\n"); + printf(" keychain : %s\n", pi->kcFile()); + } + while(1) { + fpurge(stdin); + printf("\nEnter item number or CR to quit : "); + fflush(stdout); + char resp[64]; + getString(resp, sizeof(resp)); + if(resp[0] == '\0') { + ortn = CSSMERR_CSSM_USER_CANCELED; + break; + } + ires = atoi(resp); + if((ires < 0) || (ires >= numItems)) { + printf("***Invalid entry. Type a number between 0 and %d\n", numItems); + continue; + } + break; + } + + if(ortn == noErr) { + *itemRef = items[ires]->itemRef(); + CFRetain(*itemRef); + } + +done: + /* clean out SimplePickerItem array */ + for(dex=0; dex + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + KPI_PrivateKey, + KPI_PublicKey, + KPI_Cert +} KP_ItemType; + +OSStatus singleItemPicker( + SecKeychainRef kcRef, // NULL means the default list + KP_ItemType itemType, + bool takeFirst, // take first key found + SecKeychainItemRef *keyRef); // RETURNED + + +#ifdef __cplusplus +} +#endif + +#endif /* _SINGLE_ITEM_PICKER_H_ */ + diff --git a/SecurityTests/clxutils/extractCertFields/Makefile b/SecurityTests/clxutils/extractCertFields/Makefile new file mode 100644 index 00000000..c128b3d0 --- /dev/null +++ b/SecurityTests/clxutils/extractCertFields/Makefile @@ -0,0 +1,54 @@ +# name of executable to build +EXECUTABLE=extractCertFields +# C++ source (with .cpp extension) +CPSOURCE= extractCertFields.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/clxutils/extractCertFields/extractCertFields.cpp b/SecurityTests/clxutils/extractCertFields/extractCertFields.cpp new file mode 100644 index 00000000..6ec190c5 --- /dev/null +++ b/SecurityTests/clxutils/extractCertFields/extractCertFields.cpp @@ -0,0 +1,211 @@ +/* + * Parse a cert, dump its subject name (in normalized DER-encoded form), + * key size, and public key blob to stdout. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WRITE_NAME_FILE 1 + +/* allow checking various DER encoded fields */ +#define SUBJECT_NAME_OID CSSMOID_X509V1SubjectName /* normalized */ +// #define SUBJECT_NAME_OID CSSMOID_X509V1SubjectNameStd /* non normalized */ + +/* + * Print the contents of a CSSM_DATA, like so: + * + * static const uint8 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

?UjI?ttje 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

!VmZO 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%0D7vT`&m9#rIT0x=P^u|RwiEmhrNCw! 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

  • 45Q&D>z(R7i?L@P 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

    >gHN5Di`9}=JWE=;UYT^UeA2A~ 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 LW@q4(SOq)ZSjrc6_8SpMI5 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

    } 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 P74>a5H1)=ZGZHH-8rdTxk1)@)2I=aPi8pjN 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%0A{b>MPZ+8n=fm!Mh@reqX&^I7ADf4TbyQ8(AdTC4 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�%*3r9Q&hzBNY$o!dV!O? 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 z�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%0ABWM9Hshz~i>xlF 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

    8n5EzrV-O|KRuk?f=vH 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 z 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

    >AZ=lEy89+%9 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


    tY(F|E<;bk&y~Hs4HubX#+*=@O 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�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 z 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 z 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

    S_q7u%HA`kDZD zr5L2JuF8ur{!!!=$SN&S(85(NNa${?*a0)Yp(>$YMA;0~dsuhUzDb!0;Kiia*~19w zEo*M*)Bu>XTd>YB#x`nkkh96R4aGz%)J=%jMy;DI*u`M&M@?=B&BG~mT!&_7z0&>9TD9Ywd%avq?I9h*;-m%n=rZc7be%c(sdxo#6Yt^W6sUw>Ig7r zy)d}~3UW*FuNfKCX)9Nj*IO-$YP$57ot)8l0QsD~tL9#GJ-+?y)_U5=p2-mSwiwnO zr;Sad!?hE7Pg z7BdO*z>RCAn||dAHB9m;hF%!5+OFyO13*K7Ht|{{7I|8k78<)6n>uFCa*4F&gH9V( z?1jQ`Qwt~i^>;H}6sKp33#hD%qz-)-yVYjMu*OOX^bfw)ZA;Mf%?T$|T29lGZ2N4;cBe*}3l1M)rfm$X^(TFyt zEH<*=`ojWz0}YS_5`j4VlM0@ZDvxJv9`F^?nT+O&rN?x6*i?~hL(`oTS}>s$WthJi zFp;Ysr+6KB4fc_m%Urhhpmt_35<=m)UVl#>7x>z0-h919;{Rw6ixR zR_rHU#CM>C1`7iK6J$f`FJb0dNy=(e_fAj(KxXwjlPlnnR4fiaXef|`kdW*+iycfS z)%7dD$a{FRFYH3E+UPJ?3;E?PH15b#n1Y8Ir~%ao>+FU#wodlk2xrX; zii@*zOS5y+3#h=Q!FA43=W~-qR>YFTypm}tX0(`!Jdx$EiezzAK)`*1%&er?nwyvy zW2C+qihX(?c0i6r zVfI_j?^H>M6cz7>OQ%9Vnjv(jP7}D@(<+cgRi^|%V4%ZC#Um%CJ~XQUuE^rj{L<3m zEF+QQ#!QjG*`LBlKc@~7lTB45OIE*1$L_kY;&hO5lH5>w$R3$Ue7?Sf>~-K!9VCUg zI){U-JCC$Dh*Kj_WYzc?-V%&hX+MV7OS^!ddH~H{ucQEPv*|+^Lv1JkPqb{kqC~_< zo9^elNMHDvH|03dhj;x1={{KGVzHkft*tL`Z$RvllEN3s^c-^doMQ zWJYaT-|BQjwx}>G4L;9+u&RL3zuCJ!D_Sc(60YGptT^|o4Co{rOS@34OJcVXdqUlH z$rI;2G#vC-si|3qUz2jeykjl7rFs&rK{zI;)*J~vneqD}vLYn#UmNa4g8<;(Q32)M zi6dcSx>(m2-dGAP9$?RIX&EYQyF6J#_iqi49cE5%_Bsc>g=AS*b}=r`dVSI zJDl?>^z1AIXI(%f zGK+Li7m%J(VsqZwX%E(H*D znjQ?DT~{|*G`(KZ6k0$qi89qfq#2j_)+o{(m*(bX7Z;1OFkcXRBM^mMCwOs3gc~oo z?n98mZ30GQj%Uybmvd@-3^{t8FAydNfH=*6FxsIEHH@Fk&J|COhx_=LQ3xBFfOoDQ zvv}y}Q3%vIx*B63cq|*&6=k8BfLWx*P2MT&3V1=7Mj#9EIWK!z(M6+m;s+24$tRL{ z;7)!V$x8ZMipX}aw<6YHW5;}7uc(~aAkt}Mq8!S=7~SURN27sVxpZ8vpZV&cK?<#n zS*-fDRAP+SAsJ`5vB^QwJUnni^AdzqsDPakNu#7t!0Q|f%H-61NtgE&x?Q)8yUK&^ z>=OIXC0GU(4jSGSWJr+#c4y2ml0@=LCQ6X5J!#ky&1m*^vG+43mIB%8U> zB#r{O>@t-=HDJhKqG+RjuTrNk0NycnzSRPKRCa}`K*&I+T9T$xzjdi$C!7W%2^hcO z?kEK&^O(ajVbBurIHC=oIPWIX2T8)ZZa-TR%W^C9kil?!d}m(7obRq|u0K;)M^omy z5Dgbeo)xrRE!QTwHd;kdsbFQCf|!&FFT{t{O+q@TwB@l)Cn@=m2dVihLK11>agT#NDfdy3Jy^7HIj05CC^w~i~zbgd1xdk(66C+#&S|9G6HaQhuA5Rtw;ZH zW1%BdBNo}tI6t>M zu@Yaw!IX<;wL-V3t9NLOMlANcyXPpNBf%F&p}ivaW{Cl zw6~#D38i=xUo6l`HS~;)K}Qz9 z2OR*XR!aX#x@`+l*tIwz=46wZe*QEs0%h&A&o%afR1~SaEg`yYFh$4MqvlPr9UGU0 zaIelb%QjDfQQkr;mY73W;J9tMuGw3@psdpiD2p%$n`zLaqZ7$RS-ah6B4Kv|3+?oQ zyU&j+ft{UOo?BSF39;uaZK)IyM{7h?uJ!UWq8c}T<%Eb0U_Pa)!Q05o=ETs@wn;Jl#IB?BG8Fy&os%!&qpnnwAM2QaH}#? zZ{mFx{fbL;qm&Nn5*;_RHIbJWMEJVuIuY_yH3e!d-OkF`=a$IDrDRDPBgo?Fs*2HU z8bk&n$SXh<+p$d>j=ErDC8~d?g*io93*3n4zj2HpC8Ee70(4cjDbkBt@06@i9YlPrN0) z0`8ce)L1E@cw%r2p7Oe=7ptY$oezK*tIt~fWaJ`aeg*PcvkH%o&o1>UP^f^GCy1W< zygD=_!nD;OHIHV3-VD5So%l5uxbC^iLx*g%^nR|0Hp}#izxcJgboC; zt8)NtOiJiGF%!Nkh8-esAzM!OTvIq)B%6{yL5~%*281ku0-8*VArg_`1+`4{-8eUd z2a7BiM4i=L>dLAz_dctjMCO8K#>WsYf?z%gzmR1_6^m$mWwjzEnzFDqkWA9B(Qgp7 zVynkB2n5tUBwk|=MZ6H2A`U2I&Z5bI)EvO>oThk592_O|96^*U<4(q)wVzb3AXl|c zEj~;F!9%u24&qu!(qMZS>Q$gIEk%TuGz- zcj#2g^YO~&*0b9i&#&&F@9vFfcRE^3DdCUSPNo7%>BaPfYSy>vwd^9|O9|_qc(Db+ zx{aTwlDbCMDFves6@00wOebnnFJ+Wvmj1W0@1{I&Kp6Xn8Z&y~#OUsODc}MRBY^kex0{a0l+^jiGmViBz;_n6QYxMu;dGI z!YKQNI1$z64E0ZPwQY(rbD|$D!g$k6>giP4n>S~QtFzNcs9QTk5wbm4-q%a*lFAfW zIXXKKXcdK1FNlpO*zTd1-EE55W5pSC7k5nKll`L)>)3=QTa%K`}lRT?J;hgk_CR2utM#3O`6 z7G(e-W1}_82+NM3EoumACrL|tJ)g$@K7itLhMet)16aO@r0i-7GkwKEv&n~HI-)7XR(U4g$JiBvqvbdln?X(kE z3+a{>wuy#tR9u+cty-oL2RlI)4bpfDo2r2ABV)U9AG$Wr0s=ldk%z5xI4X3sNsgg@ z3jII_4KaE^HnEwp@it<=n_lvTRT}+6Tdh(PsL873S{jRJNDCg)CaLuU9~0Oj$V*Mp zCvtHk@ziINQJq}Gb-k|4uJ(WY&4}_z+?TwVOsC2B2YDV@`8Wgx5S6x&Q4HlG&`Y&( zjAnl3aJ{?ddlx$QS3s>gRs+D&NEJKNgY=H&%g6y5CsJzRvplJ{PoF_`uYtVnA z`c%$09cpoA^~TcdJYrnSUaC<+#dPXnS(+H)AzqcGmPSfe;ox92v@AJ~j*s=HD+8>< zGvQ$A@{ec=tSgx5Ng|8kl$zjkO){2R^@x^wkWNliIwC0{E95qn)A0S^LcuYX3Vy5} z0vy+jJch=7@-#5qL_KbsmSZztK@6PWYFq;|Oh9|lpU|SMCLpkIIc_It>P-Gew+zyN z>j(4}4GVqPk-#(<$0dbLm9ML*5KBWqea%F&1OYdT1lHi#gqZuhfC;+UY#cXTY)Py7 z662qat7PZN#z#RoPZuYQxY^@dr;sv@94fH^l8O3$jF}E>3dJ=Er9^v!&U5ca6L@4$ zFtwv)@b>2CC#~%QGhq1r#tG^%Vjpn16pr8|Rp5CFK>~n#qn80!Vc07GmmLt5j!q>4 zI!)@nLVjVcJ4YB!Q68bJ`=MHZLp zM)yk9n!1Y*o2sS>e^7RztU?Xa=AU!gZzf&Q3@(ses2fl}c1Y<-{lw!}(6|%+4$>7guL)POJn`GV(J7=9jqIzS_>JHtpt)ReGi( zq)ft<VNl!=->v1F@ z5RNIa7?Ola8FFaG5%S=m-JnxQVqUR`W=sKvtb-ScnnH0vSE?Npw8vn+xZB5`hHY-G zZ@jfrsMQ$K5H0GiP~yy-;EBAE$^jTJ?mNu*iQ;&2OMPFY#3{kr8M%fdJ}s%YU8YZ< zhG{1@JMn!8ij4bWB~zIQ1o2857K@yfYP}fvQ@R!K*%Rd1jrAJ~%kvP-g3WCJg1o7{ zRiS{3Q4?lSA$wk=2~yFZ0yYegl(B<|tvK@dkkTNJI-&~Lc#^8X9)OhQjNZs4TZy#o zOLc>Tj!Izb*wqEGqsC%=)y|LDy}W7G#{Ali)y11Pd`pP+q%F3eHhH%q71>QdQ!h12 z30lG7(-W~w(v?|>N9pF{L)9ED6Jf|xGZPRA)<;7^bZ(9g5s_}K3>i+M2K4iUEa1h& z@LodN7dvr=te7nks$}B4(EwGY{AA&>nrkT0R1onCwE-p`5o!_mCZ6e7p3yu_lc=3_ zh}P){xA>l@M^_R5KtDBY&Rjn_DZx&tyHwRWHBhyF54B_3=r?!eWyP5!SR|yKsP3p; zvIQ;@9U$isZTo_CJsj3`A*VOW8HVtM`Pt%)wKd4;DMNAYPHP)4N*4lzBL(Y;=&3@> zMWv#vE_SW3jUb0ztxN&>R#`OyPN>w_5&`ZJIp3cFH}_~{AuM1~sr zRJ$xyzYpq9PqZ7y_z(foLk3}CERKichQW0wK`s1wq!@5F-b)76o&5?w)USJUUk)RV z8MEIbU{DYXi}NNKg(vg%ULgfKUS6gcYPelIrXAKDZzYx(K^CxNJ}C;Shroehk$)Hm zDD)CoehN>$dUDcwoKH@QL5P=#qyc{=f5Zjv-MS{qMp{M14K>|l#o5XY)k~xgsxQ*V zjlf>zvVs|~8pXFU(gR{+Cy_v~=>Q2><2w(I(bBUfHPj*5QZf}kskksTR+mi3dxNDY zy@lUOxQS)LjSHiYucWxSPYr3AWoNL?+UCy1I<`<@Rr)d=N$q`4 z#4Hz(ZVUG86{qkCT$&sNyX#}g$(2;0suzpuWB~ArQtyq!kaFp8*X)M0Rj>SvM$=L*ewE)yrAS?#;bb#rBGaZ|0GBH7i{fYtA7B8HFf+UaST#Ub z$SF?ei%q`Td zfe$F&x_fTrdRaQ)K52(wE1}Yf?79&N_h>bs*dx}jejrV@_&nRjBd$U8Tg@&_5j|ov zryUVxh)5u(CmEFUlja@V$rqfU^d}M-n24?txb%eb6a^7{YUQ9;M`KrTMaon$j-=}d zFkX!ot?OEE1YdJ1KLSWc3-K_(#wdLkH==sLrX{R;EyI!^!i?vqAP^Gcbgtydkj!o+ z3b7;1&l-fl7}rUJM2RCw)TLjRmUfak1tV_}m=xcoIp&h2VV)&x403Fb0d+Jl;Gp_Prom%}*f zjUk@XxB(R`6417|(oO`2%b;B%CnXKACNPo*fh-t+8Pd8`&$bm4qY+5jf|1JZR17CM z@XM_$(sBit@~yX?K`%X!K4H}kA4tby35QcVS|L%VAocL!;~lK4rEyiWam+<)yi0s*G}$8?w;51`@~ODQYU)m@3?;?3Hk6JR}~Ph%;;Cbig{1jD*e+?#7da zGeK?vszHt^A@rD5%<#1wq~3k9L22`2!C!a{!Nhf|Bf7q`P7iTw4|(=>S8?UAmLtCE zn7XXX@3+Gn*>1dmwn2!`#ilDqEB@EueL*X!^toHKAv4y=#RT7lP)RR)G{| zK{nqKgiwJb#DEjt9+fC&3aDddaTOa1Zt2%Z)4)YR@~C?b41BD4X<=r5W_e~2Xyh+u zCeVcfyUXmAE4w8DPoxY$Vwp?>k7Oj(2TCRqsR+<$Ru9-;O{kiw*OZ+w68=+YKuj>j zFDWC5uS%cU2kW+nltw0n1TPCaJ}4qABP6s}XcEF#g=ZKqp+N1;i2Q|-z6h$*J0V1> zLlP)lHUY?h7oWe40j?b&jMu zatiiR!AtfgIw^|9p&nHghuCK=;QSdnV4vB>T#OycJ4=G~n_({yOhwY%j!@Hb-zoPN=y9)V) zypmIJP6wqdoN}weL@;NLdQbjlzGm~*oo6;T);ssbUvTC7~--7VT&sZ@)m6mA8 z&hg-e*JEkYYz9hzkY+S&;c>AH6%`yBs)SIs(%HQI5Fw(~cBI#Mqr^w!tjlR{n1@D& z+i_;5xUhhRD034la-Nwis#A&ZvZSdH{)0$)2+Zqt9bgbWuT)do=8=b>@(bk6HTMmv zWNCcN#m|J?cLC%9Qs~)AJX^(b!69m@<6%_6`DI4r_-|J*VXdVhy)ME+p^gSpt0r{0 zZJ1u`ktjp-%PF9E+ltaefW+mnJ9ezdhCO!?g8J)wqM8apCs0r7FzcdhrIzgmpuCOB zK)N{v(;+P?K9Z3%1l9`BVCdD7(ugYm!n zf-%l=1+i6W1!Tvhbx(@_WGy|YGpfkMLPO_Ud5V<~JHvA1f~F<%u*mdJS+$91PR&@U#`TiI zNW+uP#h!jv4xUbJj)>z%+!T!^iaY_Qu7Nn?gsWCAz+B1cPw`YkIb zwHOinNHe-%Ngfz>cmxYHK@woyn9c}B9l_SSZuxvme-)?a7M5m~it`gIPFNYGF)aAV zf?14OZt(f}7{V!5D}@EUL=l_<^mXw_hl)s4g(r7GLSCTV0%|bqf3K~zpLE*ohQ5io zwx=(ZVST*x+Jm+RtO-+^nwl!eFln<|-5>G-)z z$zd-!or;xFLs$t6eP)_vL9R*B<(m?n2Xv6A4%+{y2_kI38H0n_)II^fRd1ApAyLl| zsa$P{x;|CzQj2G#g6bs}G^0Df+}sls2^ebO>nWVTQr+YVS!?!)hj>tGmTNGJ*%IVS z_nr>YYMe9?@FJ@Tb_DN7jLat%{d=o|lCNbb(!1In4WA?Qo=Fz^1R-vrpQ>bJm~s~u z7B)7f*`7Hj?-33M#7kJgbU6lzeu zgqv35@Ou4tgwOlAIHpev`aPOIyW1&*Q>>v?KR^2cD5}*HC7IA&%B^f`wM!T zh~?5HL)smqMkC1MWTOtt2*_rLUR6gFES}<(x8POpRL0TKa-me>9J9y#>Z8UGXBFKNM1FlaH80k_r?qs|-z0 zZ3Ut1ib=rn{U=3ue1)hSZlR8(Sdh^^v^mG98oua#_g)B0~ur#VTtObEspwJeg z&DxlUQ6G&*Tdbnlr9-fi&m!6Y#kk#UluuA*gI1HLcI_M_bFW9BX%6kj^TvT(hI)#i zJAq?@*jxx=$moUO>T?J63@HsU8FmMflLz;OAjU2rQ-|%N+H1<~$ycTzmV;iNFBOg? zdpQv@IU&f2%PqYKp}sn1c~YwxPtGL8QDEdFN{oxkvrEgxrFD_eIy__%CC*`3LTz(e z3;ab-(AD|bg_-5W;^LwyFQor;(!~-pO?EH^`Vl%v1rx3j3SO$aEYWtYAgA$_h93CwXsARs8JjAAmuj?E^1J^^tqQ*qm+l3Rfz+~dyi+E z$2?e_pku2DmxN;)I3oLJpiLH@h?D`4UB$BL2jJq*$e7RZ}hlG^sVG+C@KerBK;UV}4GrmB-`r9S)jBSymE@+i(N%%5o zr1EJgKbfE=783l3GO3N)8#FFrVkHich$Pz4+ZKd3DUhNZ9+obU2=rh>O9-K&WtgKp z_L9+04LQ%oZ3+^b)77qkyPp39O~eze%IZPIL?AlAzFuJ)j4AQi&fyDL&t$RgvRN(#utH>$mSm(l_&wE4OR6LS3HxUYdUJ+`@ScfGZb{W zbxq>cQsLH-9M<2m$aI%fJd8Pht-yc|k31kBegp`dF+Kz3#?yzdAk^&_k;fz;L)< zebLE=$Hz59BBE`h<_(J@TbpFXE9~KPl1Z2e6??B!Ab%MhN+~}kOn0Jx2ZuBbZLSw>| zp~SI*8t9cT*I9eOBasFtT0f4dnc9~lqF5Y=ghz_tB2gZqtTLFuet9!1cX#CHJ+P&&*kXmG4bVqd8*c{7(7I-x>u(EOx%VfE$H;8F4TT*sLXfM=CDo6IC zkFikA=A%2$-@N_oRtLdXOJeF;K^CMbE}@??3xQR*crQlan8;SmlT+uC0T&b@Ljge)-g3pWE;BfnPq!Y_+oc!j55|IgnJukgf)Y7Wrr8bS3s_&Fb|58| zAthjpxa5|a6KJ&+Co>DuAG1wDQ*9Y;D8x;bSj`eP1R{~o{LxaLV!YOE+;3LfZTPDi zC)mO!{%uMV3oC}`hD#ijLQ7!l{D*K_rR!pA^%PhrnguC$sin}ua6__gq4vi$)Zinm zvj^#4RSlfjt)$Bc0~XU}cabU@MiA7|X|U1`gD>RB+=PILGwj8eX-mW=O*H_fXdy}> z8V;X>D#(G!t{P4v(2$WGFd<>QBn5F^$APmT5(|6zWakrYemdM(uu^%n^YX=3R~ zh|AiQ6Uq{k`tafblf0gzwS~llrwvM|b^j!hIa+K!>E^LFeQj<%xBATH`txgVSiQTt zwzF}!Q@et-#H$s;R*YiNWKyWsYRLVrg<^?>;SdJ3$3$t{sBMP?*YqtvD|6aF%-nUj1`w2SWi9{@Cpkf%Mp}_#23%ZOb5!lb=luD(pJyxqe zNH?))?za9*FCNt{frF~@>SnUor{prqRW!S2S4lCl>e?^)JAc@2A78(A?f(7yQ}<`5 z8qI@isQ7fPxV*e{&2I~VdpVw>W$9AXQe0>1u{(f>+o-qvM&eie?5Eq!%=Gm1HJRmF z);6NAW&MNO>(0}&zO=MBGrLfnM~i??>A-6OVy=gsknL?FkAp8Rl_lCsCR0D-o4r810YN$aC#b>}sZjElS#u4x)%LFPJt@kVR6 zW*Ht1A@Dyvkx0tyCk~&be}<<3zDOv(B3(0^F?Vn!ckS3bKn$amxq#@OVHw5WN1F2ppygX?PCDYE2t^^TkhW8dj0e3x7VJ%wXwC678o4w zOkPMh&tQIl8-rbjr9L?FIXoY=N`lmTU6pmI-3}j!y@UHQKIVNur?pN|CVO^!V>`sT&levjNkHu;huvHAw+Qe30+|b4hhSyqZU($ld$5@~&_yeLYXY8O8DGvit zEcS+HuU1eNwCAE)41gWcGOEjRkaMZEg9N&b&VA<0ZnW_;lr4*Uc$PcjShg$<-HSN~ z!y83HIv|}pPE=?MX--?;dNXJEpwyF@;LDF)@LBR+Q$aOF`Y~X%l7&97gCHUGDO=E{ zI_c2Qj0d}W?+1&B?Z>(j;SYoHSXv;Bzfxfcbj{~oNvNe)aXQQza$SN+Lw;4&gCBaE zhNxHFM~M{_wT<{sbTCm|(BPJe#aXle3+`Wc+)Dx++Njx!|I?Z=Ecd5!Zrprm34nt< zGExBWSrIebm;odKsZ>fqK*x~ifDuUpBFAP313J?gO9W7!hH0S{M=R{0rJA7KwcZW1 z^f?U|2t8x+be+0+bEddDJH234dDhU*wX_FU_j;*aiV$B&7L*M2uW1kh8@{3cgJj9j z3UnE-!SFRc7F-{l=AE6pY6H5vu{H_o$s`Rz(=)~C*JxY}`3WeS?^ahR%Q_sfqZ|h- zl2j!GvGyc1AtFXS$g+e`!jlgD?3eqo7ZH{qQu>;EF1!bQ@uXS2Z*n!E*+YPfQfLB8 zjD%y(gvoecWcRR<*g*}Ihj!mt*~1g&KBJCD-B`DfeZbCeC(lXEU+ppPjO9iiT#A&g zSeMHnDI62zco)S4q)}DeL#2baRqOi=_yv!YBk?!%K4SG{j8!>8+@3oljC-++`?ygD-LE!LUgxNU z+Mp$Cf?K#(EyX%MH};%N0ve)AY3@CRikn{D^S`%_!VFUL3vE>Gn-cdA?);a@vU$ARVdwOX(~a6 z7&Gsq37M!t?$UBzjMu8r3oT`{5rNjeU(p81(3Etsdc}A{D3V_-Xcx@~SQS#;82HAv zIj%S76^w`4`7M?-vazVvA(5`l^|nw$pY^##<1?cH@rFIKE?+UVP_1Ni+I#d%-01#| zvW_ZfLai}i8fVx2Nc5tycQt_HuOIi`?ZhF?j=sef(I5S_67;t4g)m&o7i90@PYZ$G zZGKMBpMcUFz{-O39zeLUzYqQKv<+r*G~u{4iuMJwOH1>!YeiI>^IKB(CO5F3dHDv+ zCNGfn;GWBQDb>2qqUO~3K|M$@Lx7LcP6d&}wX1~}DwSj6<}TPjDKKAQP##0;JoZ>v>!xG`3E;I*#n)#z3=R%`?pFr~o=pm?<=4$%W$v zHi{|4WGx$a6kfCus-4UYsDe_tIT#OKL&!?& zdXh*%dzE5(`u-_)J6w9jBt>j)t#7>b`R&cm@30#4CI&L>5R2eJbY;7Gk99T$$qvL2 z-UKal=I;8*(JtsH;2WVRsfZ(1stpM8oquR%9}DoX`rhKq(#+!W>K;VrSbua zA`$LGPvsm(s#*62j9U8lLl;dQnyNJmXS071SHkC4xnuvp9kSmC?8tz1r6D z;-H{{(T)kdXzXM4>d8q*JtoMO+yJQUN*d#yo1A37Dtj!Wxs)(b6lJJ_kU`FLgT(73 z>S(7a*QfTF>TPuo>`KL3#C1d1J~)J&iz@j1%#G4+G-@j5d!0Qe+5=J;b&&GP+Fu!c%}d98ULU3P{hpabtCDeQkQlH`cLga(n=y z4xHpLTRuI3M>nPy7T4#OS%?7o^Y~MTGi*H;e=~VFGm(71I5mqdWE(F+(J4a$*ks*Y zqAld6!rq2JKlnSEKvkFu>huCVJ8Su328`rSTa{ZGuv{qt7erwcQ!vp40vVEdkkq4?#W8U33B5XJd#ku8aAc&A>Y-Q7I83IW+8g~-T zgd$nFLc0;0R3i-ut0p_BJdl#7EwpB9i1-L~6uPJCk^8zl>^5XO7$FKnGfS#P$x~!} zkj)nCD`KudbPz~_j}0oYZZoNe7(_13Oif=(T;vsxxP_-+hKnx6!ouR*!tzX!lzV-3 zXLVa==uW=nDO(7nbYL@pFL4kWN3FI7?K?+F*$MQdi4wK0wmFhzC_DEXC&)1pD<-S_ z5vR3v9Y%z>t;PZcnV|0YSh-TG9x=FE2LMo_1T?^@R7k9lY5>lnaOoZIAR)eF*(J^o zh-EH&;!|4vzNE<4e(2Ht9Jy^+FjnE#1~RPe>Oq?t1!g5eYNXkVY}(I)6^RW~ zxI_wjrwX8W(lb&il5E9aQ6W-+THvQxlM#|S#U?5Qs_R*z#+FBm0`v%=*B;25%W;XxkdR#94c)zh@qh|m ztyfz|1-y`c3vn?{W63%aks%-wn6D+=6^ug( zhd6He-r@fH=i|+IS)F9{W~o{O;})(8%^mlKEP^pH$XC`rI#RN1lF}8R3PP$;k+;Ep zk8v2t+9jQB)J~LDs(H-7p%M`Wf(!>W1jGuIRwISS#}bqR_m~h9yzj~$g>;CHg_QtJiY*Gj#0!frddTx!J} zg~tp|);u|;+yirZ;@~h4kA%@?)xDD%s$X2wT4$p-ZpTOuy+usgUpSsmU4ae-qt~;K_^ZI$*oS>`<~ak@nTl5q4G+05T8eLs|m(l z3UK7DfU~9Ip-CS&kP19Gz(0LCiq|JX7=f@g=pKXy`{7i$R}oGJ$#^=!!~{zq!-%Tn z#=(WX2j`>^yoevE!_VAoa>XW@FmXWDdi^GOhBS&X%f07x^y^D)T!&shMn1vE;N2OFv zsDj98^ax~-GHMx%OVe{pOUtw)DlW(8A5pZdF7>OY9n_QzV^q#Tth^g!1$G)Js^EvP z1~ma;Ap-_(Y7?-JxTZ=Z4!HhPg*)(5L;3^(HE4*&%-auq(?4E1nkuZHNIk5!lXlBh z$aW}RQl1(gyD1E~M0*6N<@Ln9By1uJKW~DhQ9Yc7oL3Z_qI8}&n@aNo!#QycssfPOojqaT35E_S76K8B8Vlr5 zL}HK=@u(zqDphBx7fqnWlVS>`gGswDN}eWGlE3F96`m*?$ovNp)B=rwp+7j=7#R*{5BLJ8#aP_g2eG7CR-_6Cs+AgiN>5M;VU5Rw@+ zNEbrr53pXYMZy$Gfr>&m>c1E6;4B1A z{-u}1`Ujw_nT-%@T#tAcFO{4_}sR2JbFEIA9J$;8)A zHy&aN4k|Df2pGI@H~&fG)3ph6r%uFqK5ZLW=+n2>8oX^98AU5bw_}vm-u1cO4 z24%Vewk&=L96N1;@}b{s@LG|KpbB2?m7)~-JW##pTRBlGMd~UDxBw3z%bn!z%miBw;h`2O^#w3RT{RN)dNB)Gk zOsK8`xzzkvDYOb2dt}Yp00go)?hx+J+1PPx34_{jj4M%hv^_@IXP)UeofjoU&Fs;` zq-ykTga(TFxtlXL=GI}Juoa&T%ScL~UAQ8!xo+5MU0}w?Iv-}aVmxTXi+SuKGvR$j zoX9RaEMwhRT3x+SBw*}l&I2%AIAbfNcMDCHwfbCDm7R?KyZLJ>Ov0>Ij%0U zJ3P!ndTdMbiyI|oWJjEd{ENPXT_#-AD*KY^0&$_n=mtk*9lyneccUcOjS*#swiq;% zap)F-1sSX(k{1SK9?sCF@QPW6!cHi$0z4?hRIuUkmsqR@EQD0T+Z7n?5uimkfV@hd zgYy=;O%vG4=jqE7;E{J7qc$DbpkrTv5%f{|C-K!@3H}FREt00<#z8~_+{vE9BsV-@ zMPHpNxIZLifSXnnb6n;KyTWnm2~ZNOPr?^e#b-QyJ{o{SLhlwzShz1txQoz-h6*!~ zb*KW2q*dJa{2V~>`hquIcvze5qf)Ay#YC<|EL-wO;^74QlPZXtRDwrHT^T(hhl&$| z2&+*VHJ+FRGese1ka5)ogg|p$IfsV?js7+jI`f?S%v2w_@nWlS^LXP<2>W*fbq)gD z@Q`3CkmM%y4DkLzb|aI@6@w72=f!y!C)A zcs2tRAh%+tZB|ID%A>ha4)UakSPsy~fz8G1by5Ie6{9Gbu&1ce{p>>SrAIcRiNmA&5GE}4m60ueK7ll{>h2;kh+D!s>xwA=V;GI$`GIJryAAkZ z17dXSl?+2lhG@w--LU@<#E;c?y;v{T#2tqTX*NJqw9Qe7mhc(|#VUsfPiA#jrkPRt5yWdXPMY|@bZXji-C)M3 zoZMM$A^n83UMHtAo*p(1TK6%cZZto)3RTgs7!uNgr3%TIR96@l29bne>y+>Cl#e8j z^%Am7X4o(QFR6}6nFH9`{YrF9FY}|Wi3$N4g^%ooXX{le{LC$`Ld(Na3aG2Vct5c9 zI<=t8P2Yk?AAKL2*4LR!N-jmz<_={!2?M`zK` zh&bpE(O~0YY0eaG&cQ;HOdv3K$=OOseEk<71;wC-;F#SNazbZUCFZW(J14-Yn67uw z!m6;g#_@xcA~c!>3&fmcJXLr@h>OMwh?!0c7g5+z3!HC7c+Lbd zXtpX;AY;Bbs9SsY)%blwMM^7J_$VlqVyn|sD?i$RSWP4Wc>3OKA>VH0UNi2YC+31E zXnkK`FTB~PEXIx6z7+UvlAoANlVF6nEMQWEDE$s{1XHPa5Fn{ zzTxT+vF?glIUCJMvutAwaRA5pCX$_zxHl$noQ>Zu6B^;*@@aDFkERRH|M9-u&aiE! zY$TrbFJ=9J*y|=+1h+0j-}b#SQ3j1E9&H+z$Im%dd1-cWX=Y}28A!;jj8bV#djFh} zQdu2XP&W3dRa?Y!pF*QCt+2r(D}&jCTCcTpi6JvzivX|P~;Bnoh&)Vb&KOTjIa z@_k-ZpMa=Yy=QseKHW!REOuA?p$XSA17bP z*+q3N^YlCO(!NLw);q$8u2w*S(kJ^0w{Ami zyH~B;*J2HhGU0;TPd&z{+896y#BrCAN^sadsxgKeKg){>O#pqjQGUQn!v|KzpSbw* z@F1`Y$8yxd2DScgJu|Zg4gMNz*w;q0F35A!i}UkOpr6e2;)4ELoSBy2`5FE^!3Sm* zkoGt|`^0o{ZeeleiNgG7rtdw<3G03p3QvF-^?a~YMg@i#bjp(b4L|I>jz*W1^R5k(2D|N0Av!C#Fq^9!xQuwK9c( z=Ibc}adFvmf%UO@sQ3Mkgu_$psL%Z`F3e=e{}=cF6cEq<>Q~;`di^Jk|0Q1QPuzUN z`d$3{=}$cIQ5zroG5F~}{qfrm@z2K|tlnCE;)x&mz~aZf>p$Z6k80h0{f#Gn_~$=^ zzs%lwW@qDx&;Qm}mA`BH!H+!qHSe#y=b!)J2R`)U|Mu5^{y%)A(D;G%ulUC&-}lpB z`M>_+H^2W^KJ?+=`|UsY&wu)-e~R}$^^^X=y(gad=s(#+UC|eR^|#(~>+npcK)35*X z$IkzQ-MO!-e)Nq`{;W5yzxg9S^_%~4?aIghz3==tzx-vdoqYFef8n2e_$R;l6W;x? ztAFWDzwr-$_r2GC|L1=8zwYmU%s<@w;0HhHCU^~T>iQbee>tt zEgyX1r+(lE7yp+}|F7@)yi{JU=&Ap#`@iV^UZ~WD7 z{L-u6@ZY}lcRn!vfe+99(x1HdfBwPmdgoLB<3DYD&%b!_lYa8&{_f|#d;7CKd*j}_ zzw615zx%$Q`SDNr{;&P^|NRet;-7uh&-}`VzxYdlT^{1}>{qKDLtG@Uh|KeM!<9}uQYrpb`f9|LM@Dpdh=tn>CQ&)ay?}_T>tH137 z-~Wq0{$u~)qdxNIKk&Y9-Tac*{j)FrJKy#>U;h&mAKdwgU-_HIpZ)$X8e97d@BcgB zQ+VU&e#fOx`GNO-+WS7?J)ie++duGSZ~X1&{`{xcf96-e?eK@+@s>+p^H1OU#<@@U zg^mC6)qnIU-}3q!?|S~<{=220`#(ST|M-`!?|N|ZnP2<0lY5``zR%lS{0rZ6_`!o; zy7_g#F!RyVU-iz(CqCmF|MM@s_KWU)jg@<*%FjrYqZD`aS>Tzx%TNzrFdM^*{aRul@f%;g|o~ z@4xh>iSL{Jq|LwenT^Rm_doo`FMh^rwtxMje`3D;J0JPXcfI;Y-|@bWU%Rw*@b~}R zZ+zfq-}Oze{oo(GY2yF-oWK4R-`@Vy-<){I&;HSCXFl+ezxwJQ{N26!;qILey{GnV zzkTaZ-u%H|Sp74b@7?*F_UGSNtbWv&{=a|lBU7LH^lyFrU%pd*@S|V-gFn6TqtE?b z`NO|go__MHf9d-U-!$>Refz(f|EAyh^vnPH?WGUB?z{i^)y@C%uRi)-TaU-F~hyYxff{h^=wmLL10zxOlW z@r|GLXTIYb3vYkjPo8|%U;fIkd+rOj-u3(6@M#C1{1^Xy?XSG|#lN=xo4@fJZ~U$0 ze|Piezx#Xt(Zr{H^56QH^8e4?cK|k3?f<7xpo6_-$R$8qup>!#X`y=nrKJs1prmcu z2HGSf=|p^GDMR+&Wp8AP2r7c8D9RENYxZd@Mw>_*Ig?_u#*EKe%q&a;WVe4hQGpJV@fA21f1=aNGo{X;o&-9GzCj zeAaYtD(a>{4CUnd0xHj`L6#NrrN+@u%)50lHq5!Qn9YyH) zX{2Y+|M+Q)MV1t+PWRuPhm#Y8YOx&Ge|;+Iv>X**8H}Gw6?-7Sw3^_?GR-kItPUJQ zGPe05)}*2sH1Na8(;P!0T*y^(ccbwasX$5rgDK*4kY{9hRyF1u8EF}SuL1mkGl&d~ z@{11OXJF1le4r^rN3jv;pg0X4;AzsOxpN8Zm772rc^*bnVK$H+F&^rPPLXj#=n`)5 z0Q}#b6F(*lz&+dqxX0lW_n^evAWmj;bp&l?a&lS3A;TFy-< zx7F6aD{Ow}35fL-AWCcmVfh*pNK+bM#KMs$R6<2KTmZMcC))}Zm;tOV0~M?g7tu9* z)vfznWRBse;=1Zl*?;a;mGl3h-Vx*%fUW;gXHWdU3jeQNygW$eGczTWc3{Qptm zUY+~Bdhw;=D11lDB`3$BRINdyM^0}dm~dJl6+Y$M5!N2o_3j_sBs# zZpuZ-_cnpM=H!Itdwc2(h?~sd3U#@x^el@Fa_R-&Q7JiRo6wG zHx#PYa`CD(E-s4mW_?<$Z*Zj{I6j-eEjbqg6lx%#4loy-O)sH2s%4?)}z(hyC`H}(^rOPS{Mc3`rQo#4twaHW(MG^|7< zQV^ReOK=e`q>eK5yDA%zt42<)(6eFr5&2nrbJd)3_qg;R&O$2O^H4`g&N~5R{$4UT z5t(C9?$2eS#-QHFMHT3|?t~6b6a~cO0-i<(aSD)UBGL5fFVh#8CC!S3(8^gnmP`SW zOsuqsh0Kiw1PcOG^=2v8YKI|-ppZ6Y=m#Nstw7DH_*(srFkv)iA#Uu!zh$i7g#I|D zbg&xWH$u{U2z_k?U2EYPOe#x`a_kEH2c*gJ!GFH^&krNmO5tEumTU35DA+>24hxK6 zzv5fsl#rYKWj(BhRt9~I?(1pgK8Br%Nx{k9$3*L(%foGZG9mc&nv z;iN~J3j1GvEGN$_BsJk$6tqQ+1SlIM?qC6oQ)l5E;5UJfqsFcYMrnp7JSS(rXF=o; zFTv(ARO*dLRaDRp;*X2f#T9aM;9PIp5ikXk71$FrIhlBbumL=FnN=2ky0rfWbq+G0 zgdc=j_rNtYfyq=evZlvr*TcaE#Red;#qdtK*-U(%fE8E^*HlNjx1%Gb z!_!Ar#0F8NAh|iLEeGdHJM79IZ0kGeYeoZv-B9HkQ1}^}fhUwXxJV*EfG5yW)|*4u zjx2Nu!lyt$0auFX4`YjJoEiC1m9-46G$J^`>f1=;`5sggo|Th6){u zX*32zJ+&I~;ET@CQ+u$V_}ylY@zCdLsSYhM+#nvZJVpQtV7l5&l$}HJpVrtD;G=#K zXdy?fn6#*EgZKH=&=s5rP@<;Z7=%@^AqaU|eOLZS3xFzfO(l0|w4_U5U$OrdUSUCG z4|b}8xLiZF8^tPG`6_y{O{tFf^MC#ti~LVzLr4~>fq*|7s6Kf7pSRq{`*HlA4H#?X zV+H$PGeMtLvwevD_x1OCy#H1pthKk5?Ej+&eOk@no@D-^cNvRzR$! zw_cW1jfz7$eT48&=`21S|v6kN2gm>LH{!^3^ zA0NwF+K@UPwzBj8$U&c0>$vavFBkvm}|AMt~v+>>H20ltAAaw$s;=O=>}=%}iSjt&N0zA;29@8#|vASLe& zZ-5Sw%B0MXWA%}Lo3BYXWwD?6&si)~iG9J3iC7{SIq3^Lj(x=$4QV0LN>rS_Qm%sQ zY*ZRt1amxU7qF2BCa{%=OJJ)aNLRfbb^dDw=f4sdJp9zEJpVZ9-Z1u*_5b_(%OCUq zhX?or-08$0dD`LIn$%BdR=^;MfD>K`NB0OrvKq?>>lQ z1tY?#st0>KBPCStD@2+BpDW7br_d)WB2vYp=-^omK$MMK2@iF%DiyvPwCuCG*=BfD z^cn|}WOV^~Oi)TrO&5ZmR=n0I1S%4s`EUzvK-j>T!C^5`A<}+`ROG+J{cHdjL7Xzk zUqgNt13dn^oa9_2?G(D90cf_mrxQGNj_B$~1?mw)q2@wZ)9^@o>jqy4`wi{1aYuws zH%`O4D&Qh1|D9C00=_t^U6O###&8AjPrz03-tcEx4KV--gKQ=kfSH86^0g`aNX#5$ z9!{sv)q_C{g**X=Q3x6ef@rt9&SKWQ%CBi%2wnF zCZMENAmg6qX8;Cko$;7R2FfumX0vuAH=>+1*a6jB-moJ61p z{A9L&1V40H#>!Lp?$#k(jM~J*%Z;C<1$YEh{0VSLPY=QQ;RxOg+-cenxDriSo-7>I zEj``SGFvZlfcNBj& z&C4~PKOR+VSBiMoG8kZ)0KtLk)#7Jdc(SpVzTm?AMakk8zeE9qyO;dw8f=-BEA@BroU~U>Nm@S~H!RhX?xLbpR zL9nn4A`V77Zo7WV)@aUc_8cVv6Uac+0a=TVCv0p~zuU6(BVs zr_hS0TZtPs{2#FlC^f7$SY2$9dTg%ct4mksN_65dT1za$qmnBTCp-m7g6e58wFxU_ zp>?U5EL+KocxqobiYLGi*zFh=}Abwa8y`{;*1DVHaF_Vz{BMU%ZM;NNy_0jhf~JJC3E<{GB%1E7&Vj|7&e3p4@*KMCP_+s+?Jr) zQ5cz22()5)U79*On^HsswT`3DdR02rfELs|lL3|75UFQ@ivS3W4ZRh0aYLk}y{4q3 z$!4wk4lt!=;FaH#|T&_s*2~?!WyuDG~ zN+wI;izk48l2C!jiWHKvQ&`xFF@+7ELP0Aj-kzD73@PLuQd;G5KTcq;@<8kXHcSaQ zX#mZJ8_3VZyl@#R)KLL-6gLEXDp(pq>GBOK>YYoq=~&!ZpJ0lh;;8&-h;)eBfc`8h z_hfT=4<>yU0@Om})GDQFFiC}xE%!&Dak;b)KlNBtm`7D&145m? z`j5ydti}T33;CTbKP(R*zTLP0H7a501uPZ|WLgke+$w+`XFwYwRbU;DhMz3m%3zI| zQn^&bOnS>ulLOgcSBA*AEa450k8GyqTAr4v5;Y-e^FJ_Efjs;Jr)sV{O6EG`jdBUm z)9St64p@6Nik8%8lmV2K1~rpYUHUtBltw)%aC}foMtTABm;c$UOYqQ z!^EfJG0tTn@nx5-xbLb3zF&u{X8g>Aq>!?N15&={*EXzD!=6FizM7V2(k>}w$4+LM0Ry-;`Wbbw~m!}u(H!^n=QTBFsm&teojwt3x zNzSPXtUjpRcV9uLELbV1n1&TdMH%>Fc4jp3!Ktu-f{6?QIQd1JmztwVPlry#ua=S@ z9~BMQQ7p^&VDhlc3=^w@^`&ArtOYDGQlXCkdx7|t&n3aQp>;?86jG@L*-Gkd5xSzI z3CpE@lsx}W;9n92afyFP=3mNQlEi-*$G=1gR|;|kGy<9zO6FG}`^BiW>O7UZB}qk` z7MQ#!%ZbyDALx6gYCl`r&fSepzEQASMVzQF@$wL=mG7FHN$)>btjARS= zDPW~FibAR(E0Wcw-yi=O?gQ-~b;~J>tqdkAaJWT+rGQI{Uj=(o1pws23>sCoI~S`) z&o`7yQ(=3p@CRoOXuO}5Td;mJo0>GUjhb~DNmbCEZ=xrG*hO7)hlwpI|@D{EwC3ang6P6>Xf{h^n&of(x z1lhRE=;T?i(1KC})V2Z!E4SjW_g5{+)PdDgR~3PbBq14&h(}OA&Y{C@dWfZQoB_b7&_v-LRV%o&EVI)b83QLNJ<@s-HR9NJIxPej0d?O5jDe}zN z>PcxJ`x>$!T37{`wN{TbT@yklU;&C6rj!b69iOWp+KiBEq~27AaOl4|IB_4+_sCQ(2Ig07y?WPqF|v(BI1#=~O;6X;0B()KwR4J&Y|e#^CAh3L26Zmb_ddM7+*k^kdjMo2(nlY0EDVFeXl9j-X4LBp zrU#v%x5C{o(A@`yzKSMTJyF4C)&4X^HdD*6mDua^jb0hqDr1%xTBV|l4uiB(r}xU! znbf4GR4DDj2~pMd`S?Rk4#cV|UJ{RNeMzq^Owpu=gp;odntO^oC5=4}xM0g{s(Kt& z8yMiuP_%*_wtX7%wbTaKU9?oa;Ncz_80d~?%Dw#v#MN6Pl?Wk0_2C|f$S-%uS%iAk zU1l;v#i}01OSIU^GNO-6G=RthAYNGP3e}K#V8-N2j~U3Y$f8srX5mYmcF124Ma*Lp z|9>>{bsy0P!H-p#9vDsK=_-h;`3)07SsanL4s!!BGMAu6OQzbq97qs#xu9yudTc_1 z*?<>tMfn-lxITO|88Y1wIEIY>bQG}>3dadcVm1YDW*!oE$~;v&=`d($vg+n9sP3+mGj1 zSyY`5g=5O;lQsF+SeOW+JYt1MnJo?E>`XNq9w1U!Ka)4ZR7cD;8(+yu0eRG@(;}jV zWKD`h)1mAD%&z08Xa~-D6Ed8E@@S0|9Y$@B%|;Y~{TQqi3j>A2i6BaWbqB@uEly?n z%mlMsqnBFim7ZnvLJSP?e=4;JE0QtAyC6k)@8d&^qiLsdYxTDp z&Ioa%qavYp5@o`9;k&HEA|ZUPdb8_>j$~?za&)yzMPgK7ZivMtt`Nf>XNEvcZ+ur! z5(?BHhbl_3faT!HD7}TKJA=`arz6}06A~UqDF%d&q*AGAf)2PLnHqH}<5wEoDalPe%e*S@oIra&V`J%g4Z*5;IwuH)OFtdQx zcp(azF+(rJ$RZ3#?KL(xNAIPOGc@Z9{?jApp@>nK(nV)F{}LuR*vnh1sX(78UVLO&^#b0Vu$>EWLtm+^hO9X8iQBl^RbpmMdRy( zs{_1@6qoE3r{v=BM%=?m!5SkGrfj5(sLKe!!dDNE zG-3RhX0fK)Qf%E24vk({tAryiF@a0SHDx0SqLy(1`iPjCqu1!+sfK3skhq}NRYEtU zT#e8TLBeg~Wc@!gc>W3U42r($blJ6v8S%{I$Y^|w0l|Le_1CbpD@{N#z+|=_DX0Y` zY!cQi)VpeM*Uc$R*JNt)b-MIg1vm^8*@g5JP6=1x!;Ku_VKU@}RAcdB*-b&F_DvJ#A?h?Zx(@qvXU29rw2UhRoX zX1G+17Ikw9)df&oZ9N|~DIi7R0l6lGP;tq*Imq@eG%vq~X|1EZ2$C=@DWKzNJ`lKpaYA;X5o1cVKZ@$q(HIuf~idyI8SrM$L~p>YFa z9_n-t6($!hOs))CmkqY$JwX3OJ3U(MXrTVWvtFB|eXwV;Czt2R#cNPjg{oec0Z9#- z=18(YLNZ)Hkgtg8%Vb85Yz}19eK4;7P+Kn&_6MZsbwg)ZBd0tK?3J~;*|Y~qYHUF* z8p0mYJFm)3*XUCC33*ajDYfD|=?+G|HvCuc83+(Qea&7mR}}-6{%ukViE#C?h_3rh6?eC0$2>| zh=ciCMR|FP<0&3>q7?+MSk$}Fw>we6en0IeEpFMA!NEM%D}qD)>0Ed$7*p%fAxM9hjkj7`mppBv_(3=1C+g}~Jap|p#iUvxAT z;SeIB`Qw}@RLhaG3zMvP_1+b(UdrkX@#As9(FsZM<{UF2@kI$VU>RwM6J-f8AyRQu z&2_KDYdq-(mfP&JB41d3Pd~@VS28h)Yhk!7T9#Gai}0s0eG!KZ;mq{=(*J0V629UR*MJ z4Ngc@#w83CGY(0OKn7qrEM$r6`+>Y*l=o)Vl!fi7(9;q6wmmZ;W zX&O^u-{iQ+5M`pb%YgpT^osCl;d%}!a%u!p*Zj090hCD#U_qTBVEHI~8L-e&(_jHu z5-0)y7NLT8I$_@bs~Q3V!N z2pqP*7Vrr8RQvlT6gv0H%tc*5D-@R_+o>#yD^Xf_oPgmq4z4OUjXzb!M2IYXjm8LF zI5{uk(nAzJE@;!++h{~JTUD|;Gek}$*=b7=?x9Z4ML=#%Z>!ZjZE(v=?k<;sF38K! z1>t%kUNt?HG8iUqqe^3-v@I6dfNAw8LQZ9y_hgzLc7F?DLCh~GH0lI)@QxU?7Xk)M!&w0!87h8dX zIJB22R|>2#SQ#nWAo%XKHbXq5Xdt&4CT?KjU_mb6r2xJ(0559_963g3!?CL|f2_w! zf}-V#5sT!)INbV?iMo7dx2MFaFdA zV6QN%rIeKyt+&=1ECj`*c;U7(0I~*-c(-t;`8xA8Op_!HO`NW^9?9#P4{dNEB{e)M zCT<`X9~Kif0wpK7D=FfwG)i>cW7o>_-^vzA!w0`Mi9 z7K8D_TJa#g#2JmbYA(Q2t^j%CjsBE5YPDVLj4-4AKV!chVX-J;P?m;PwAtVqR2Vx| zEvB7%`3DY-we7l0eO*2brfzi)!VRQ(kVsF!2{Isz48m4%D7X zW=QnMn2StANMGfKNfv&n^lt1Z)iTO97h|`D6x4ZEsYrafV7spn^ZyZ2kVtVJ1@CDL z;)?9ms>~H8Y@~RCsR$T!nDjq3{zMK)@wNJ|Wr(R1~yS3=$CiLnPI+Vk$6wGMSsiKoSN?E|>dq zdQAcJalsqR%jD()w(#me_Cef82pfU-wkiT@K@d@(evDcA5(KVF>$h7wzA_PIWzeJn zC5+<)mBKvzazzIpwS-p%YDSs*yP~LAap`$F71VKvnn&Tkig@~c%7m10`|>UcaC7*3 zBVYpM5|IIbz`lqqjUHK_n9N~F41j5GZZQh+F&}x_z9IiVM0>`DBOKyetsyYT5-KtCFE#hC+)`RJI&<){kbXhp3C9W2ZSPLCXR;2dfI@U8;t6$u8W zMNt-byjYkn`EyvX56WR7GZ6t|2uU^+BHRby$w8oZA*VqjHkDx9;l|a0 z8z|t|Qn0T)vYgXs92-f<%tvp^92PPJe>-(l@#Mk_xhVMUR9rab1VSSQ5mgS3>Qti< z0bw0ez!R(TTUgod2~qm|e)GF!Rfd@-*uYl)WIWQoA?`rh$Ac68XM+%g6^@SZn?uN~ zJ~~6Ewnb;$k3(0MbejvgGIaJPboRISi)^Z^h39JE+hLm?P9c2;>{&Jn9diP+A^r&W zmVnRnI9BV)YSLor_I=Kx6}=EQl8Z;qHq{)#ai=Zh#_F&?z*;mZAzcckl-1cp_Bj-! zqdDfN(y}PGmO2OWNU6!8zCvoG?IRTe=Yc~nGy`ENzD8{alFHIJW1$fZ2PkM=kM@9B z9K1p4e6bVq@F6M|4M|m6&~6kUp`ejmEtQ%^w-f5mm=9h~lSwtu45%_5mm~VZ=zH`+ zMHpR?+Mx49imn+>JfN&MSA^4ppgKj>-)DELz;vIryWcWCJAUD<47 zQ8R8BmxLf7BUEVAUvM4jDiYILLqB>bBW;8@S_BMms&r5?P%OSe6c7-&!OB6vZK2g= zqD4?vA^gh>)8fd>h%nf`h{xxNFk;=gEVvXn_#RN!1{O@hQyRP<2rf!(!r!M?8B7$C zAkb8}RPi-NL@+#JGR21g`#_y>GGf#^v{K@Rf~MvgvoN|5oh{Ma3>DlmQN|E~oMc|m z8Y!_4$`^I$0TRcm5z7S6qK+b6bOs|X&(OzaGN{Q>BbHu4iAY>#(rG;{DD)V?#n@`*miO}~Ive0u8G^^7V;9-ij9j8YmjT8) zRAtZtsI`vdM9?THC?BR;M6?k#V?3R4bJ+U`AwVoKC4tXFw#X(|17WY0dO#wFnBg*H z1Ty#%k4VRjpnWRNh)dChl%>C+9GjN05~x5Hjx2~6Af-@>;6MpEC(wzl zs_KBp)d6+1ohUJBMP;*%Rz`3M{f%5$!T^q1WH98RY!RAyE%Il=og8(h%7f+6Ba~}= zu7=nm=oPDGK%~u-m79}lq`EogdYRE`MDKxe!oQlX<|1@CV3?FY=#FxMETWR`Lqw%n zKt&*WCRGDt^cGvgGTO30hfyS!C?8Km_KlyJWRLaa&=i&`&>Pk0TVi4bsf?)bss0}(Yh{#= z2a!+35Npnyza|R4<@JO6=mphOYAg(e*sY+Y`}FAV^hr5WIzt&(`q5tf#-Tc zuH>_GAPo}F=0Isl#56+T=5Lb5xuUfLlr<1eBz>t-JDVO=C)BR|hE%o}pm$2MjfLL< zOAWia;kM-`>m&2^Me~x1Z9FU&AQ?SDL2oFre>jdk%veHypju_Q@tX8}5HM&K;JhYC z|J0L);S=mS2%XB$LahO!UU&m6fN2=&tSF|D$Of92ttl#kitEV@&}A}hMMvx!cqo== zK&R4lcM!*1gGXwi2fc!*B778XX4GE7*lJ`A0CS;=tJ73QP*!kTf`w5>%8!oEFQgcI zp&Br2;i}U@>kyO>W&`REd?%epRVR8w`8}>|d;b9lS&@yVQr%$)xQq^dDYQrn zflPnU0S%S)sAZBiM5BW_(Zo^rW*`!qMFtQAy;uk%$jhApBTHs3Fjl3_MZ;XG_Gd7< z!ejzOg(3<(C1WLBo&$^`ECmi*85~VW%@Kq_9oV#4v?B{8jY}bhI0#%O%3tWoz)9j_ zolrU3eX0Vb9>m)6=!{p?UV_NH9*(v+8D`bIwpg&Od`o8XfXV<8spP~EaC1LqbNk_1 z#@HAnvjW2qi;ZI6IfBxQGJr-HN?_AA0*~O9041aMu;5VFYDjV6eZpWe38K6SE`m&a zlpITy{cx2+0g`L2|1ecW;Mau^O+E3)4TBZ1fcokPcftLkRdJ9(d3zGOhG;jP0#6jq zK(ezaHzA9PEUUF(Ftpva%61HtMMSFVFzH7};s2`a=;K|fEfVvB=tYUpM%dp>Tm+0A z2#3hw1|n=3oVnI1ZdfX`8P1nnP%;wjOj%G!(qP$!4g|@O&`q?!K=ok;Y_-7vod+JX z3=`x7c+AF;$p$8LT^dt{NJxZfl9y*F6N(o_dGjQq)-&)6I-_XxAgf^l0cKvIH1ua- zws&Fi9@!d{d(x}b1`m_YgI=v|J$ND%Et&!{$r0^9QxK;JQG!6qBm7h=WBA8G|kz<$;++iNf9~mXyaDsw##XneuHh zVCJ&5Qji5Qh#@L4BM+QFkc6;!l0PsBBmm-=B9z{pEScm**6JX>@FpmHLW6H6yYTms zHJ-=H{*Y9(TrwnXgerN~5qY-R>ME!+Z1W^pRfjlRvyqz7ziqjQkIcufQVI$XGE&3% zAC!Vfoyj8t1T+x^wX=l<)S|@*kAhR1OoQq|HIY1$n8D<;(=iv()(Dx>h~!X%AcnH6 zOo*G=s?44-ik z3968WNqr~6sLqCs6r3M1Ebz;i;9>!~sbNq8!t#zzBP^Hj>ab=!2yHW0Z()zgDddLc zmUYa;l9i)B{;3lRYKsC@pz4DN5_N&Ae&~o+iLReaHoYJ&2CnB!cgu^m_R*9**&XtG znkVoQmTOiZn6!EoPZB}V;N2tKAq38Xf=)*ARCMxI8?fU3Zkh!j9#(B8AQF|PB@l+5gZs}ZqIyQvy{nQz# zh)@U%jsds~_Yt`D|Cr2bPADPUSef`N7QBTHSRTrxu*j%nddL2#ml33K{A-DG;H08~ zRIG|2IP%Lku~xAADHe*qUkut1t)@{(9p}wAN*y{x3E&hXq(tbN=g<}Q>*PTL;Cw?^ zD#!>B1hH|%o~-95eQ-LDMOvZ@gwRBmMn`yt%_kcY6eus)oiw0ztnOpBs*nt@a!RI? z1<1-DE9zR`2j@QvI89FNFhD&WHJEvw&n6DW0$ww8@3V{w!bqHgk%FvdUL>=7 zftv;*KL#zn%rVUjPVh1!Rs;efacZFh8W+nd31*t5UYk|aB)$z!4uiDK&TpOL82Et! zwN^+Q1JvNY%k<2|SRUQO=FW zLLt5@NsWL8D2_er61+J^Eknv2o+bFo6u!QGRPw4Ud7~o}O(i`@{(}=9v=Gb`JqrtS zbZ}57qKF^BS-X&oPaYT^QJ1hu(`p$HU}&d|iiibWBSgYV1uWEOq1?4zPi6v7NGXt2 zRi4xvnlC$00ZO_uehM$XK?4h!D;En-aH4q-E-pt;Ml}|ar=;4(wR)T*1`dS0530>d zo~i2+v^gwXd@KUM`I8ON0+mV%Q$Wkoh<%{83&aliS1N#E0>wyZ(3w4xOVE;urdEN( zi*xaOczZvZ@P9#yGpe#-10v~{2_d}0OYLPv4}}VvDS8T)s}%h}2qDMm;C}_ncIT4V zi5{rScjpo)HXu=f;vBWec#~-vb%|yKErb@L4mJaxpgI`6#;UY3Icg}#WspVqPT%F} zozfg80BM27fZAER{8dmLY@hpIK)7lE4thFVu@GS@IHJ(nHCm5&AwZtd7`t+ zlRscpi>@$Z7#R5zv;U}vdYP8xe10E)kx(O;$|;g9M)=3N@`oJtZOc?<)C-jvZOX19 z(@pFF&Od-95DE{bv_j!g{`4rCC5#`4w1HNMEH;zQYfvtPFP3^%*5D%AgLsQYtU5c7 z)mV2oB1p>vwc9iqs8@xSZ~N@2=2?)07E0Z;4m|Ka&Z)J zgwRVWb;jb4z}Yx0f`Gx!$fKjyA^m}3JTNeBfd7vf5)r`W&bcO{zAH?g@JrGV*%Y8B zq(}(mqdZ-uaE!ymh$K2BVwL%G=?1e?Z}h;-C2L4-CNv2|CS_6VLz!49rgIF9h)7@$ zrs+jQCD7a=(d!JhQZAw}4Qvr{oUoLZ34B7XjgTcv8naL!!i&^IYxTz*fLKuo8B?`w z1E@e*h^Tm$TaviFy!#*j68=$|Yz5fI9|Jn;e3^m=L+S{GVZ-Y{IUvynRVEkCYPGT? zTXwwolU3$CQHm*M9wL5IDa;;9jc=W7|t~_et z{0Uo=3?&bScoyOs$S0!8D|1{VA(g|(xgco@5zp0US(Q%JYG=f$qR|Mo<)&jYT+yGS z5Es-D$Uy=UpMx%9FWajB0(`vXFr-!nA5`W8RU;opl*bVA@zxHE6117*I)bkd{~A45 zjugXOYrXSNa0YM50!BRU(AYzpgH7v$b zpjoK=Y^en!Fe0J^Wvjgk)!)SmO}3k1h);Z2QvWD484puN#4^n=B9>SuO83hcH3jQcQ)559@SH^fRR=dV)Jc(s} zjfFX>hKL~$>w`lDPfd< zP-W*rl8Zrgd!E|S=7@RM_nj;JXXDfcv(mw@x=%8jyU>DzP9f%w%`oHu#Yj@9{`h?E zzR~spRw+8%GZ?(u^CiKI#hV+=0Ja^QC09gHOgba1?8p+v(%*wk9(|z8>SO|VsDE=5 z@@NS%+%pe2D8ms{I#3tbPMj~5!pelRk;~4!T&*Osh%;1U_6+t8{Mw7sV>5K{wexsr zEMveGuv({$Kxu|?AyVWKAW0I{r`1|F*UD?a@VHJML(omwmGpu!&eh#j$U>rbnsifE zh&Q4Gg&HM33Yj|vP@}g&h|C?jiz(L_B6k-n;Nv^g9nut$Sw2MW+7mU)6UDi+o#V+F zFY*BANa!(BY4%x^H`xaoM$kssE$sS-)vv%~>n%-Rp=;0IC;X&_Q};k)uc;GYgL|9q0aS&SmZ7p*8rSB5ht zopNCyTq1G|5w0Y>TOw$X;;KVhG1X8p!468gt&Za@*+QTnf^3ozSx#kD7?}F$vb4NP z8y5$~nPlfrYSNN7h%GnM`=iP%r&G@ z^hG36#z>8Xe*@9x1TqxKFli7`l#Bcc+=$!w&@_X3EP0otMzrIDgOu_uhz-F#0OE<7 zh61F86+q_(JZO=Chl-QxVMc%j0j?=}Tpr?oDXfzSB*hdVS(1-x!xIsV#H{5RP~a&n z81-jRMO%e{IIu2MO`@(~ENq$XM}Y&tSbR2FgY^)xq4F@(Lb@u4Kx6}2K_MXy&A7C+ zI$eg?JeY(Df>+}w6~*bT%1l9Qtm3d*3BqOMXIL>1)@5TOP0ol?ru3M(8kDqTa-VqjI2OqRydm7U50q*{At z4eZJ~jf>sElW|PdWPW;hNM)l$M0SM>Qc_z%#%LpSs13px0(*`~s8MMHVhGg-tU~YP zPl;emui#`-D1ptWF0{Ng|`_&zmKk;X6*Mh6@M0%ddS)gefZAv-)J z$iUp{4hyr7yBwXTAVXw?NST=s)uqZ-aIAa)IWn6$Z}dDUJA#)vg8Ko+qR44?pMY{> z3Bo|RLs$8%d|-icM{f_?Sy`E@Y<0ED2lGQdjC+80xxwgkf$fwh29*yL023k_Xei2! zMR6sNkSbWB7d90e$lLkAPMIN`Kd4MAD*u_;l6fx6b8R7D4|_@_0GJ(Kn?|7LTS7gg<}bBI1fIoYCK zAme159RI`AB>(6CQjx*L+B22qz$rRYiYh&Yz{Y6IBf&|A=4prvmXMO;@8`>2(cF){ z(s#bzc<=A)tMEhou*_Q`ll#m46%tPNNKdWi%_PGcI8HK7t*!D7Rza=GEB+^c4CYTp zFlk&k?Q{U+6Go)O4NQ(oQl{V-Dx(G}Q(_Ym`m@8vpI~;1>1ouc$vvG0My)2*9e=h0qQTS52%(gE8NBkfDH%vANl6=T z-Gvgr=~d&I5Q#z~P?K5ihb`qTtMHJtnZk?i)L;_#tI{n!C9Q1Vyn|iJPm|fQVGRUf zG0z*807h&CTJyhx3>BPzQZs6F`ZAdh9q&rdKk&xp{CoR*`$#z78l6QYgZ&>r|CQ|j z1FM;;+;ojD1#w(jH2y=J2&tMP#P3J{<-{AT>A$y3?(6@U{)_Od&DWT?=zu^~TS*Ja zeD;`9_J_A!|FpN0Na{)4>1+C3QqOnM+->i*Jhy(*`L1I-zPW$@(n0MrLq6$Rw6*@6 zCl4PSx9rWYc3kpb?UBFY*Ncv2Ix?{tv?YpzTdrj|tWb?F31wVdP zP*QsAg)=^lJIp;fsO6aUjT;YeT^|@4+dL_*D+jPZ2N&o?WER8f!1f$$aJ+^%8x()e{!Bezte< zz;wy;_4~|B?lW@q)2Z81gI8s!ix#b0x4LA}n%CBE=>F`aR>}q=rnMRwG3DKv10yuK zIb+8iS*FQ&dHtt_1>q+*@7Q|by}=D%Jh<=OhTrWe%3afD;o47EeqOL-@rhO&gW5m+ zTV%bUh*|4fL_YuJyu~A1{`T?8;%{1dj$UP$ICKBDgc&`QeFi=;GOFw8h~Wnh1Wb*5 zBiV0M^R)AOjhml*bIyqAoj!h|`?W@EgQqO{)=s(gT%V|j)5G39upR+nnErAA|EVPWaSiKSDflunygx^iXdwr!9XZ3R<2sTsB4{{tg1orPx-Z`&Oem=6qwuf zXx5=N@^Szweq=LI;C|;{?&n|j{CmrNy&uc}b%G-N`EM*4ESX;_A=#fj_1Ljvy!>CE zm;dQ^NxfK-|9@z5?T&CQX`DR8%y2^yuW|97^s(+8=DxGha4I`! z?b)rSe!E7zczI{udp{Jter->|0MC_YzCKX&zV^uHw_ko{;ESL9bT_#1p!N<88#tss z^K9|tQB(glY5K&O&*wWelq|GgC~4?4dj66|OO}mTxzKUV@?qLd zmh857Y&c?PBS&Y))k}x(l-N7(KbGrYx4zYGySc+pz0~Mc=OgwX3_B$`a(eaUAy+QG zX@5cTxv|0e)y^k&H)!)>OG&F=e_7c2&iB9lw&dS`e*Z`G#%_5fEf1$kuD;>yrb~(V zSL0vf1~eFSt#5(Tf3AP`NAtBIbN(vrqdj`J>t}wW-TtMvcWAjd`uVPDe;YsEd*i)1 z-J=>O`ZsG+YT4n|9ZaHjO){AXBKjr6nerHIs!!@7l?Id>2nL+7o4ydlqz2lIO7+mkR z*P?}+?L7Op$r-RNqlN!#OAmeZ`Eir?(t~4{@16c?%aP|6_%BzyzpBq4onPzp%8%-~ zfw^z>3H&A}_V8W3$>|>d(WtD$IVD`bSGSthj9T_XyZJ>Ma=*UnaAoI`E8V}E?sIpmwAFn)+!Q)p|uno8vxr)Sb7q-{914zT1?365Z$)TM|r5Qn%O{ zMl8sDaz=YaY`4jZq<5qv?PqR%@&&(dzuqt}y4N=w7Y!Nv&8B4;+rQboD(~BE4PoT^ zzhRPF@tGeKS^S9dJ|IC@pd~0M8EN2k>-vrhFm$R;e{lB06S0VGk`M0+Ju=Kab z@?Tvb954SJfPS}L)c=;3F3%`6JMU-`OwOZgB=t*UU-|TJ*}M0Z^@fZgSub{@>{NEI z;U8r6=$GTUy8f8yoa`1hH6zwq{6y?XoGXAk-8&TG{%`kDOsYlnFlo9mw) z+#<$h;xiMRX1p+K^0?xGEvGD+Hg9g%+4d_}FK_yT&w#%CQ#ycW1;@VAW zwq@hOm+Yp`-F@RU76!|IUSuhdy}y*tt(% zy|(r9^ZP!!cJ$**Uv&E9yKmpTaP;Q&FVBB};*Fobzw+l-o9`}bFg5dqYkdkYZvD@% zLtb3{div#t{jwcejER`l>cYz&WC4=0zz&yh}fZs*|^?M}`3wB@yecw3?=HJ-y~+``1QheYdUO zi+fhR61+mO?cGg7R&EadI(Ky3yb-5HhdljZ_j8AhN1PV_b?1kKCBwelyl+B6w~H_J z@oqk+YNPzq3-3$NteRk2ydoq@+x?Xhk%EunxoXpy_ zX2{ItFMY7`m0roaJ5TsN`;{gB{fDfWusQ2;u(xx&e;+z@>Bi*zMu$RH{r=M@19nUq zviNSm$gf^l+I#e?Ejyb&`f$svc?<7M?X>;tNgoY)>$QIudfq;=Va?}zU;9tX(x2vU zSy^DZd#H1`BpnA!WU zce>kqH(lOsZeq}%>CO9fC{)`I(LNzvJgDudO^ah&hDu+EELz@uap$RpJyvAw8-8n9 z((%Ka7d5@SZPLn=8-bhF8qW{kxMu3RhwavC-pa}C5%GWE`ZGUC#61O$)x@_O(dHCC1{g2Q5a_7;a4w>6` zkC?e*&*AOEHt#Gxe`V9IpH?lo^2PjE>5*;w(#Hnw+<$UK!S@?{&i6XL@$z%B?M<#e zxALp?PZZx9w`aoo{+@?&kH6>H@Y^~4Up(Tw=*W+oe%D^^wd1vyI^I6=+M1p}ZTjZ# z2|qOY&j)8;+}p-|!lYM5gwMKp;!5<$U9Ugucl5=RdvDzP`PhvLY&?>{GC+qkB_DpCakKfKlw#)hLT&(NtZIS{0Km2wfF~;N0 zhsvQjcP*fn|2Y278j7{^p6CD1BEDli{6D3o@cF_D1TQc?n4ieog6(-ZfUdQb1BOnL zy%5e#yP3E~s)^qE-sY!1-TqS}N43Ph>l<^TJI<+h@@dvWT#C9hrdK0cxNUje$lZh?i}M&^UN~@vDmm zbURircV6sU(qrAlU%yyw)5a^{Mpt_byH;iQ?AGIXc;A zdw%OS6Zgk%`%AU;=6uch@JoMXxkv5}UXhx+{KHwZN*ZJgSzLG^c44Ak>bwKDiue6`esHsh0qd^L`?lBig#KLUWu z%Kr*Kx%{#J*9^bfe8ZoAJBgj7xKskS51z%Jc0uZ=UnKSFMLrJWs?A;a?~Pq!=ijy< zk=2s!cm5T!a{S*1F5$=g-wKAc^_D;XyCjYj{|Sx{5x|-X2=SlvyQE&S;Qw89fcbwj zB`zHI+&jY-Y$+_+ab@3g9Z&3cKYM8P&7w2+94EfK=;z#>J@WgHF}Cj>y(K}j_^VT* z|M%@L_Wk+7z#Sib|I)pr$NEKWZEQ8it*P^$FFJcGc<%kqzs$#$|NF|32K4y+R{+bJ z{)*1Ozl!mHcK9(qv-Uma`!x;ef97~KcK%UrJ_WTw^E7Gd6g~2_be0s5`<#D;qFnr! z%->u7`25!e#_;_AfFz#cKVkVN5ujbWQa86!PtQ_s@6x2C(u|B!y}oq(_|jRkN|!G$ zUA3xo-MZ2jUo3s&jnWe*U@$2C=%doV{t`pSs+zRmM~FxKXDP?A_|I}tBB8wJpyDVI z*`;Ii26S&crQm(-tOic8(w5V^b54^cocSrDO_TbKA{*6j;`Ho{nKK$TbDkSH*SXo) znAWW$mM&jrw<3Azsv&EVHmqJZYeZuQJLg6VcH22Lj$Lzb%i2|kCX_^O+B&SI{my7- zJNuS#E8boA(&|@V+q`7MyDQIK+I;%#<-;F;eD1=P8LgZfoQ(Ryxz(v<@10rs{@J4! zU%LJ2#UFqE{;ywu|KX$8Bf7Vq-u!y#q$!OYo_zZ4_dn^Ic>QbN6PZ7Cjnw?q;nM!R z7GorhnhxvH-NAX|f*F7GD~%dZ_}sZak`Y(bcL7N99?=l<)!JZo*I4n<-IrG9@aHFN3ndy?xz-a zeev*s!$V#Ap6;XB-Ex1&UF&=z_9wsc+l<{yFRaQv{r%nBUwv{|yP@gq-fCTDziihZ zR!`Xc)w!6dzj}V~r~mC6XH>?vqZhqwycRp(wf6^~w*2F#%j=p=+xKtdA2%-^Tsp&g6=Y=ep?pzR5^!(May;2Wtn1A+MWcQGbi{5&2 z`hf9{H=c1^qPev^YxA~SE3#ku=GMy0aPF&Brf`Ytq&%0dU#+fptEZhJ>h!71XY=~a z3zZZ%4Rc+q=s6@y;ut%xZHvOIjgs?r`+hrhbK^;APfVL}x92w-XLbnvHgc8cpjpzb ze=prGUA$tZz5TwcU!B?1VxOPO;=ey1e}Ce9^pQdK z>HEXu#(h&7{c4eM+}0TP{yX*^-1pJh_@C4+gAzX+-Qm`_gdY~}IuP}X>Z`qE_mgYep_@#--GoR?=O94NA@Pu_PskNlxDPhaq9kqU-aDjeQNj3bKBjMzi792 z#rE5;P6_hU?TdErq)0C;I=%Ch>#R@h-+Sh|dgarT_9~XWKka((ukZW3H_~|K+5epW z_5INwYJOYA9Xh(~-2wi)eoKpwS$$yn$@PKXw;i0nZT1Vp7j9d&V~KCUhQ&`Uh#$Q` zHLJ(ZFLye1>8ZD_@6GYd|IB0h&+2gtzw`TK;=jL4U3hDJle=S&*6WjZJt8Qs%L|83 zX83h^Hf_er&z^4U`N@~<{^R!k_NC3V+qS)tP%=^XU;j@Q$_OG~@tAWdj+IU(WlzkfZu;fWeIf>lMc z{y+ciQTRWL@<7@&%E=g0DB2?+h3Y3+5tY2|wazhVapRblDmwq>JcDwekA9*?Dh1dHhB_99gKR+E_ zIB(Vz&oQ$WKkc&M$hUuObGK{M)>-Q595AMJ%T}LV{wO%SZ})E9Cidw)xM%BE^MgCI zZ(o>~1Ir>?6O#kznPudFr#rNdmaN@6(WxX@F{R0YPGd?WzbK?9^v_=pnRg;=z@Sfh z8qPP8H00bI+BaNx>xkcrbD!up@05c?7jSD=3y0QACxv!t7koK?;=i19c~c}gdG-1| znb)C6YwVzJ_-wl=#SOJit@C=$(%MhXZ!^376GdIt=%=pK85ido>$Pt!?b2m+_Vm2^ zjf)rPi(Z>Lb$!CL9j?yOCM{bwkvM;FPI6H)B0e^-{iuldB`q&qYw}UI5gFYBeI=iL zbmQEOo9AxzaByh)$K6(c-TmX=o{_hYES-DpHOB@~Z*I+>obtxxzqx_2Ex6E0v)Vfk zJDnxxieKO&+Hz;dT=#Z#UQ-&?N?~_1dVc%lFM8`GCnnWv--&xOvECG zVOP&*;Z=8;>KpF{EgeQ?f4oofZl~~Or%lHOZ#}n35qH4eDfH_%_qjATDPy@F7dD^m z5K!Ff`mL!;5*=f2J0;Z{b>!0e@tsvBx0wf@a7_7PcyXlvi%$KXEqv>@)T^_KdVHGm z=a@I1Z;<5r^{e&n^i#gz+%_HM^5jk@UXZV9@ZN_b7A_k7&HN>|^S=0Ib93eAcV@5a ze(S?+7b5$F`hFR|XIGQ8XB|vgH}gVfJ(*R)MUQ`{rEJ+~{n9@hIdmD3SKxPa{Ha&l zy%)Cdc1a)mTOMn#zdn4_D>JrTa`#&>exy2P#pwRuL>()Yboub3PwGEA++}D&+O&46 zgppm9E$!Nx_6#5E;c>Eq078{<#$eJm5gs_H)Z*qw#!F;puDKGOPo0L ziRjL;8DaJ()*VQ(>sGY5UbI8dn0EcvPkZ^8MEUHkby?3ItUp*aKkj6={N(G(mU*#; zTxDbX#A{uX0~NW+3;td#yJ%O^LiTB4myyGZGlzcNU`>JP&MnEZY`@UKc3<9|o)!4g zjE_|Fa}Uqh=+I*c_vt9-l0(BAanH5C*n0jiUoUO z3+&pj-Gy9Zii04`~H>2DF=ppw_=8F?4_0Cl?QLGKG3pH z$1w>f125dLYaY5sYxlBjURa~Wo!O?@T;a{MD1!R_8aE;QVaw#hDQ=%D!ClG*{T5?ZzJ_tbJ|A*@%WO?-_9H z=VteQjOu-?-h_U~BVGSB>5C4Fn*Mphz1f`pQ=amE=g4uhzhb*ycTEG={c=?!}-Sf^(f?j;~+>|w? z3ca20R!JLsy`=qbJ?y7tUvKj1*>--7uQ|86;-w0>TiobIrld*MnCV@=C~p5&bKiS$ zKjh6h(&e|2`kDPoPIS}-tbH=uZSoU4&phAw{Fn|>uDI0sz`7>UO6fWK61!u*gY=Vk zq_qFx?cxsmN?J9~lGwjhQtb5gv?nete50A{Y)QlEUNd_xx>CRWSqHzov(uvnOzqrw zUj3~Xw>;b9i_foJX+N)-lB?HXda<4R7(0jdT)nLuTQ=$*^X~WRV`Elb;7TQLPr56= zR<9s=YUk%-?V8N{x!w}xoQ@X~kKR)so913n+@N9TLC4^0W1A;7OCBA)u-VzEV>@Rh zPCOdgA=?4yqc47M`;zz_2j{qGw@&Wpu_gYP-H)M94*%lAKC;D4LnSMR>~}uVRKMp( z`!lQMJEykJI^N-@H+va<21WZHjacC&F{z(?qLW>a%=fvdW265(Jv{lx@IkF_l&6nXpGA)(@B?I_f9&t4XXFtvu|{ps+2^XaXA;|_jTTdg`dCIr^NBVrsmBG_uRUe z8k@NB^vSV@MyCIEWqH%N%ZlguFOLpPFPOc4(Y`TLo_4X{=Ni=^?sjntF6-7S>)Wh6 z`=;c{lJGVCzE(6j|J#DR?67pVsgmv=4|Z+EWsY`jJ}D$=-5f>w6L(vO9%y{_i{<~$ z9yPT4t&R14CQC9S8?^Qf4Coi++abj6%X*zcKX5p(du-vWBRWV9z4ZK@_wyuo8`RHA z@~zjsxW41%&_>cdlP>r1E*$H7_2bqVNBsuO?KghYXOiGqzGv3AT(tk-)PG968VwnDett{kiSD~b)SLc?Y+VocDKpcbn0ln`ySei3 zm$fPwp3pw8$Ej0uvo`OrZ``4I@ukANog=@IG>ly#{UEQn;T7fBPd4TqJui2A**nrs z_d?P^htX42%KiQAUB0@`wL91B{P{hZ;}*0!d28zX9WvtYzN86k7;|_+kCNiH2VUsc z^lsrx&H-Bc-;StW8!@lwm!~>6STtr~lbs*O?ftB@IJ?z6NsoNauKRN1&z`3=sW+C} z*9*;X%q!ux-VP1>@^;kI?!$bzmAfY%*yEV9EBc##&v14DZoh2maVxlyZpDR2*`$UU zM>8i*TbG7L(R+e>zTRu)pQnRm-N*OdV<&rO&r_{l{q6G0A0P5s_Qtv&?Uy(n`)E$9 z=KI$L3|r1=d?Za;U;23W=$nmRSy$X|VXK$+ZrZgWu%lgC#|h(|?<_qO-Te50<;U$; zcFc)*^*{ALKX~u$Gk%{v+4}gTOHUqK@!=AW9N(j_>h85lZ0vF99o-vm_1m+-{>SDW zFYlbRM&4SxW9JJyKhrm_-}IfA#%3(=iF1AB`i()`W-R?JcVcn>+s>UjT_5>py`iP4 zTZ>)1rmvr}@(2AEPhfZ^^o-Vw)v3t9ap`!)}i$W@4I{&?hyXn&2`t~4`;ZNx_7%&GjC>eYF<@7w>Vp{Z-bTOyjdJCBBm0=vK0Q z^p@D9U;j1rjzh$l=%zx!uM41aHwygpc+vB7Tj7*k$o+ZLhut=ij# z4r)}g!8vcSVi4*CvmUG`w0b zK(0^z*R&x8Q~F0gADP>{QQw6UyR%99(C!`1w(eXksTXSZW2>O8$C_w|1vf15zqVhJ zv9Mv%hKSFaXM3OReCk%z<&p`*0;Yd(CoK9y$5Ov9MzonPN$)D@q?fcVmb5x%=fF+b zu`GDzye2=~p0YMA*ZI8Plw`Z_C2kS(nw+Wkl;_6&ALK^vaGRZbJ3T0LR+|=*=iDTb z;dX^l-REaT-f)}qTuJjGn?3g>`@Fp{Bs{=R*}nhvn>oKmJG2`XJtB5?^u}qe_t^cB zKW1<2tT$r2w>vh-;h5ce@348T`{v3V*Ebw~dP?uD&Ash6)>pRd`^N9?uU&XvKc^nyVRG+Ms?ITE15FOVT`2yBuVtrxw*}wGg_sT-kjFE%_&J> zPs6HTb?r;+yET$HFQ0dF>$KEmlcNvYwVyY=9rxUT!db5b*j=42>B!B9?jD}4TMNTs`FL^GG1u@efpgBkJlAQ^({1*qOKvaemo{(S-Rb&M z3rbqeSf12x*VMt^)(hOUsYlo!4gMb5$vbiGu!1G?md~wsZ0@My>21#Wcbp-KoIJ|m zT8gPqGB4Kdg|EA|E}1pzQc$bgeWw_sC-EC zH!JE=lf1-vLyfck%}x1t^EDHuJyUPqs%K7in&97W(i4FrdkzeKPWEjJyXTI}`u{)n z-UF(sbz2)=Ng$LY7zqi4CLp~?M?gV3NRuXA1Ox;HqzfV%dg!5d3{|=`=_tMT4g%7P z6-4Y?{_r~S>YZe= zPWs3Le9;3u{OAiPB3?#l`pr!lH+`%5ay|CRJrqyb3TI1T|Es?j5{ahLqt4-4H7{kAIT}IK#^=pi&W|9 zlsJP-+S-nN0G9%pJcR%F@g>CkhmS6+T6qZXkP(|H2(ln%UrUe99;2)6R!5 zWCDwkJ!Y8;j`!X4vWTaHq3H=R?{(sR3-Zh~T~A9Y=Tqf$IrbNEo!=80FjZ@$%OoTf zh-q*#-~hZv$*luL;~P;#ab&`$6HC4)7=bKGqz>~;n2AE@lb-Xi$I{1SyQ(sE@o%Pz z7G#oGYk+1fkQ51=z(p~RXEypiyqpnr+1#Bxf`}r5ka{M=AjG9$DI+l%N3g3HQgMmw z?g@P8huvazi6j-d!hAo@C3OvsQEL9 zk^sulS86GwQdkp~@_H1e0nWpzxGWa4vSpz(OB$&w>%Y_-6Xt0z_@>^T$omMS?k*%9 z?GPggiVlY7+TZCaZIFvrQDx;DtM2POyA$WkSVGxe3x!qgyH_?cL^NyML9K#pqYBBG zB7D+81kVA6OY{7kJ2`&Wyn=Qq zqSUQ=Lp5cHHe(VNE+;`KZ^K}Mk>%XdbLPJczS z0{KN!YUIP1hjPehTeSQeJb?qq~wHfu0geH8In;PNP#)bvhT2 zS4zie)V!qbU~bqAIL3{uwS){03}3CD*N||eV0{%eMLu@RY^=GiV#BwhStatcNMwhv zKbIZ^OF#gPS|!8nWy7QRc}na!K(C=luOVF-0Yeugo2N_JY=Wpk9s?i9FC@~S=2Q{n zWg=OFbT~XSAtq*;T=^_ywM*T7vC!#w&R<(1wkOFs$@LT_#_1&&DmJX*nN3L14*&gI(G zC&?g#?26B(J){$-0avE+l!fqRRRzV-mDTBwCXoJa=-sn(mrdg$CJxBFpp2 zJ=aPdnfhs&!>;*Zr#RK@mE&;uGWT*Xh|ntUTkx*pX|vZ%iJaWy>G_sJ*QO2VPcNVQ zB33z~@knG8m0L@S%fgGLr~ZV#M-Er1D`T&jP?h?s?6H(N56%g>PIEga1YBEfW!94=&N(x+Y`kZ=$h$K4Jzya@yM>-GxnN4XG_>yPvN7^{)^3Abh0e@TS*9dr zB3WTWKz?APV(x+GGz1BV?Jnu*t`VL&@fs?*8FBHRQLj zentO+@5&|Cy{MHNw&7cb%1maLU48sl_FlZ&x-Zm@W*>O5{6hLWrJv;z6KsWg&-K#F zEmf-xKlz0>6$}3NUfqg#*+=1?a(-Q{`vuB%gK%cYH@`cERjJ=<^Ua}-$vrjpKWmEq zgN@@q&;R}x{_mgXe?3ST??2<~{sYZ~gsAur^!R^CGx00@pI>l5Z@G~epFEsM%*6j^ zPUt^y(LXQ!AJo9Vk^lRn_WxJse?`vzBmS>A>HPnn^}qjvR{vYmzvTaT0imDq-$=zj zVDRyY6UQjjF%#1<3(K*n=#MHOMa5$^wPRh~AJA|X7ROdr$5*c&dwCt-zI_}QcbuAf zTw8lwSNEeFh=dC_ICwlddOR_4ytH(@w|D&0Pk${9`Z@3SLl!CTXU+5X^*?^9(V}F* z9V)3A5$i}GR->R@@uZK$iEFv+)y~pPQ3d({B`c%3Du_)%gbyA9=o#6e$=F1lbZCL@ zuZ8TwV!~LMi_Mu6o;V(W7wdcC3>}!vJ5rq&MF!Rpqydn;6dDw~NPtF=9!&0-tij7b z4p!tp2_SecR`MW#lLBynmM6Cf$mga7-~vzpQ_;hN0iXg9fQh@OiJJ+42!H@)uI^{* zeW#fL(Cj?d&JyR!D*wpX>4S;WQ#1VSohoTl;jSt*_I1u%r+FVigs<`&RFs0WFg%we zHM4C`I!(g0GvMrz6O`?z=>q`OZ&VT*itP06+j{2iJY%d3*9NmL))tM7Fz6NNRR^iU z=!LDbkfI*01Kd0uuAB1{8-0SsrnNVg2OpQsJ+khKWYNOh{BMAZ{MYgSqwgo7^-EtR zk-q#6$IuUku4{jRP5+y3{pGiRp8qHPmjw3xcjy1bB&A440{*Q3{fh$s2S0y_|GNP8 z2mTW&P)R2Me|)DO4?B>G{nFFLkJH76(*aTupaTgD_8%VP@ACOS+5r9$|CNLT#m}#m z`^2ray3+Z13h;vV3U6cvCkSppt#aBm{UkGzgaZ{Ry>D9Hqa=FK@#*7E69Kynp6T~q zL8=L$bqp?<;mnKowN`m=PS4+#^RTsavj{q4@p0g54n`g8g>M}m#Bj_^ThV|Q{VL^8P0YgogQ}4Jai_js)f?jLy2f4NarVfERPlp z-`D86b@J^`oNE`?_2Y9DnJA77*oH-sA))Fx`*Y#3$Icm2I#K3AQLRh$5$395_yI=o z+AZz(b<&MI-#*pUHyrMai>m**iuwm<|NrNo|1JH$=RZ08MN-?p=>J82-|9SrF|ADIiSBm(Z_*XVI{O{v{`Oo=ZB*cH5|NN8x<$vB~{)zonT}ia0 z_MU(I8U988FHTxH{Qdl&#QyRp{_7vt`@hq|e@-a-TTDN~qGv>fjlAvIG)V-=Y%*+O zVzMIAvf|P|XeY&lg>KpkQ~&3J{*hATw}nWE{vjcM;Vt-`#wGqxwiu^aq z`x^-J?+7E==?|Fa?_cgW5FdX_s*J3N*dLYpcQ`}8BSi8K3HckC$?r7(#~l0rm@fae z6wyEC**~Ai{+*Vk{*Zcp*!nlldj7U7vH#qqfA?I;?@0LFApN5|*S};gen;x>MbCe_ zU-sM0i;Mq`iT;h||4siAKl^JD|BMOow;%EEdR`Uke`mD$^P2x{8u%ykKLdNWTO>B< zTONLY@S*?3{EtKmOX7z7HU6upl*HLT*Z+S|>;K;E!p^s@**FV3{!A&3zL%LB+_Z&-}aI}L;l~>@&D$le%rFbKi2;S{{j*H-+rxs8UIrM!2dx4 zgctiW|NC$2_m5mC>-Gb*!`?&o=B;Z^_O5m|3M3u?zcV&&ZqD{UszGG`p@aA{=KqMc z|M%VdJMsU|W`qCnOZ@ZrmpCgW`j7cvQPDr^KmKDi|6kqk%l>~WSQpr~1xS?~NbB;F zD;CGIv*+$rj*w{oC@K5;`d$t|Yinz)EF6Cj1d_fuIO0H{x!Kuc35ng^9lCOxAN3+6 zQa}~|;faz$749)J22r>dTmlr+F6wXCKyF)?v)@VaMgl>4sM`sK?nWMxN8u0Ezi&kT>u zTzA~q*dRgM9vyu+U}yjK`Nh)G(!s&ImoHzowzLfAzA)zj$53Z z_V?d@{rdI$Pd|P8_N}^DdcU9}yW99TOWzh)?(x)nU#9Vs2i3L1EFu;*!#` z@`}nwRn;}Mb&u;C8k?G1THBsHZSUyp>h9_7>mL{#8Xg%P8=sh*nx2`Rn_pObwzRzR ze06PoV{>bJXLs+#%U7@8yxl)|cliG3!^cmbzkL1n)AwTlLd~pEMeGQsMDbhpSLJqv zBTs8)X;kO+L@|ipSn99N?~7woj%2=AQ!tRoYglSIP*XUR%17Uyv;dqWOAoVCV&L>t zVuy&+Gpu60c!u*e_H0ZCCA!9yfE0O_?&<4kaE54Vb7XRfagi21CyQ3fvVkHp&zN@_ zS7NH9b4+eCBgp#iw*e>?7^-u4Edp(RV#Rvy&e7qnw@@h1vG2Q$omXzZ5m@?u z0n?0`CFUvKCA0{Xh$OdQja>Nmj(OBY_`G}dNp(FiCz{L3Ws7F-gjH}l>UZm zg=qi9Kt~M-H_aqF8JX+udXz{n??$x5tm8(E^mg$^?D-G78*vIyzDDTx0$G?#2BWd5F+h8B!=<7C@vU9QT_mh{lyPUNMzs=q@RDw52Kh1 z3XpgVGdipQ6O3j?grcfSQNe`;FnDVlT|+3OwLQ44#)b|K3qdos4fc#Nw+3N4fly>y zS;&*1fuSJ8C^HHL>zZ3YD@52+E(r}lM zP-x{RQQn!=t6d_PO;FZ+jA9F%UU=5um_VovJ^%#!iSEl1e&bI>R~>e*K6QdXb$n-E z(shcULJnx9V{*D1RpOI(_12P!^R7Er*JcpQt2CbbGSB!n5Q0V!+?9mx_H{o#imPS{od9_ zcod=9y-V7(s@>I6BQ8iRDXX8YD=1{o^%hT+U`VKKxNUGS9v_5^4v&N(@C+#_Kv+07l>tjYr92>H=Y^%% zqOxH4EK-l0iYj0TM*<9J+hSV`LwP2{qpHTn_Tb4U36tO zw#zmvwXclzTcnI=w2y>qZGp}A715BGNJ*@$X{p&8-zZE&C_6>PV&7Rju&KJsAC-gif8!jssG9uKH z+$9;yjr^NSX8^2#!w)R`{~Azjprip68WI^E6cHDb5EUO2nwm-o#ixZOpol0$UOq80 zw+NqGT3k_FUJ;v|SpJ|SDUMhOZALzM0)st46y`leb~hvX^ShsRkM{KpP3A{bmJJS+ zjz3Fko$l|2VbEyoE&!lAhml*m%w5P$W;EtKhM5`DfjQn0Te482xe^wDDGz)(82sd0FEd_0tjcq*6+Ozh z8J%p|%EiSmZwa?67*cBRQ82vf4!}M?=%tnTp%oMHuYB!%& zWAXJzmZEF?7|EPVmux>gyP(Uhj+E=LlVQ}2=2D6Cz8Y^lb)g=+HyL}{NfLFz&fV^r z!8%SnI@z?j2bGi~L^g6hsU!T7_-UQXqvq}J$@G*q0I!q_J4@d2XJN~>!y+4^bum2i z?>*q|t%RDLtOA9)=(99(s1fn%;h7RaR9MFKqQ>#b5`nr_u>t;vb{VDIIsIZ$+=*TZ z5nP?`WChOz_unY58kRbz@vGiAo#eXL|LVFn(9qxzlJkZ}1V_h32E`>Ng@q@@CdZ^D zB*x=Wxp8^!>W)7udubEQw67Fe`@Y?@qnLd+=s`jmFgmx#Q@Xvj#HIB;ERK= z`fpuri-bu7?Esry4K+WA0N)#RP`-TnoRqfFh|>5y1(OWAhla(Iah$i`ZB|)loQXYW z63HSkeO(N8j?dbW51~X}A$Y7K3(3f}lA_e@@p&~^w`>7Fe-YfTVsbXj(} zcZFpuR>ZLgASzkZb|+xZRa_3rU^TKh3^_xQ^rH7hRX^Fc3g;U-}f?@Gnqnpb{eQxn`{YC9IwGh=y4Mv5c0NKq=$eM&n#Rq+cQ-Guwc@}eyt z<9osA+gE;SD6k)Mlrg-rTd1-lms#yGBy|c z1*-Lw2l$@ub7&WLFiyr)HQ&p7RTJq}BPcXttVCH^=}TK7FicJR%Lps>V=Vf6NB-?a zO$;+LG8mQ_nwbd;MdoEkJjg^NLeR_=;rY2)K?q_{UTsimW^ou24hMoEouQorkdT2+ zOa$`?d@P6#UJ!=p90~#83_&a1L6gkE6C>MUuujJMf%#3i4U7?v-ly#)X!QzvmbLJjsPe?Hswai$LT&K$=GMFG{hbZ>Ua-=%`t+xXdIxu_GCi!$Yog+4 z5fxDz=Im4K<7Vi({xY#GC|BAzO$N_am99+wWNMs{{#1v`0a^4Nw1ppfO?D2TxOIvp=t2G;jjZKxLK_)g(Q&X*3YV3)ph>eS4|LPObLkKh?K%9 zg@v3B43lYUXVeNMbakIk)rLG*?%UP9cJ}SdJnKUHWkI_ng1Qr3HsfNeXmE8$=)91> zj{f}hkrHL0Dh1Rg`%PwyAbv|I_}!fw_Rj)XXHJp%^HNY@>~3XM`_^@}qwD7yXS~)k z!^&}rKBT7&p0hsf8CE540~>^x;Rxa#mlF7^3+@);hJ`%T!iaU3~q+CT`2 z_-iec!J&99EQ$>LxAFB9h!u$aYbQmrZ4eY678y*M^~S`85fUS8k`hx=lcHiG30c{3 z$srjJ(xE6+Zd!OuX;MjUdP&{m>S7e4xxTXg$)ot%hIstrnzq!svc`tqo~C9*`*7m; zWc%zSVH~-I1 zL8Ddc+*~CZG~*c@(ai=*gXNFToOc2B!m(T_kcXwKYMx|0?kZ-Jo3iG6(yS`>BH1$c zHa&Ec9K@G;J>=<4=Sv1jt8xZj%aF7{FfQt3ylfAE1BXQ-#5oJw(aNEZI09dwUJ!~0 zb7gLAbDTALZ5B^)%=7J)#+k*jEalg;F-3`6<`HL^aF(Bvg4asbK?>TkIDydKQ=;Yp z)M6WRc;DNRU5m)A#wr)@0Gg4w!*1LI?`^pjgW~PPyenlaFjGb{0!IE!h2~?C4Ny!V zk83F%XIB_Zz%5CrnZtCf#!&f@&R36TI7EL+c4c~bQ&V&QnY7OhhmYav0w&u5UZT*| zeG2Pcm!o`-+_2<6DX-1UNpwi-t?F-rQzzWKf|AOIgGXq8kY|ekDO;(ujAQEKzG9Rh!uP zh}(vuFgJYCu@RfG$SL4JQpzkKc%)C!|Kwz7Le%FN6Fn~{gvO%zS+UK+AUk>b*qcM4 zMUyul7uwlbQpsJM34bl)cm3{_lOLxIEptB_S=hL4KaVW8ms(C+2q4#w?Pe&wdNBg? zr6^7fqmd0laV@al(M4=;K8Q6_MHeStE;PE67I9>pm4Eb@+nZd5GhQmZoZLw6_Q{?& zi`yWkB7U~&j0eVAlGCgj7B=sTjSFq9Ez6$VGb?`Fwa%GRZ%ckSrbT@ZrfWHFJ!hy1 zO{QbZbf#TAy`GBwfC}rm-PoJCPmWj1t_k#tbix&9w1Z(Chy8}|b6)^X!c(7_ z&8m*4jlosYA}!X2)x0&7!VT1eG0yDld=9f0S5JQdV0RSzk|zr?$%YrjClxmag{ZZfH|q@59z772|`g$eAZC zbH#15h>4lmx<$nEP2}=4Y;U{m)yC%Qt>v;etBY^neOM|Pdp;Mw@uEIZ`FbuflzeA5 zdn5VHD%f)xF5eyQ8W>8=Aj(Q+%B~Ehp?E6UYMN`^98b%xi?goY>~%#5GQ!jKxOIZg zu)Eqi)?^HOBQ=ayaqhOmK??MC1u}0qCStzE${uM*26x3WkeI*tP^T$qPCZEYmQlSa zTWA!);ru1pnLJ|;$4{(gz6&jCl~^_-U#(wZn7#=G2p~st zr$7imO($ZarpPlykkEgg`T7(U8#N=a5X zSvenn`Q>verrWVu-Zwko3?i4l^M5_Gh_XIQZy6x#V+R-q6s>$edJi624D|Un3bNr> z7kFJH`H0E)vzPKuc?jXSwJ$wiiBd^+W|HbyugSn2eJ89O-SoA!p28H>ajc`&J;aO& z)-Ec>5ERHfD@7^1GBTTU$(ri+1Dh`kk|xsLBhX|qoeKIZ4(3fE)(+1_P3dkReI8~S zBpl4Ms-uj#=a0iiOKxN1&vuE!dtW!q^DC_Ivba~PKD->q zEg$;ad5+I-CQ+s`)cE53nku8aZVq-UX`f5Y+V}gwOloikJ2l3{>-ERQ^N#3&(;3Wk z#ny37O?HKz0p2Dy*`b9g6NbF^_Ur;p!J5}1)N43wTpvk(pfz^|OETk%i4NGJITyy1 z>zB8TS@gHkyJ$_Rzj#|(u*k~NJ1;b)%<(y=qmw(#ueuCwqEI{|)zWf({Lz zvw?eW^(M;aETB`4QY44ntv*jUA3TQVxNaEz^mUeU{yFYPSz<%zkB4G%UL)V4hF%SG z5G2;i548ps@U)Tak3$ZrCZ?9|)^PTT7}kkiI#GLKy3kQfORz?vB9hnAGsb)F;ax-& zpUNq))=X?j%mBA-aD~)@hX1+`!+))xf1b1aeJK9+oFzRYGb@`kZwYx2ig-W_C2fX; zVTusJ=ptrxMD+voqu`R7Fl13~2&%p;q_C*Fs-{12o}DyG&2lm z4nabe*MjM`=_2;F`sC!4ysJ?B;etmp+6x@f9z&HMfo3Gdd4Xa+>y_ za7ll&dm2MU%StZcO5YlrkqSwbEeM5(Dpu+H#T$81&dp3=fku~a`cTAXLV-9$a@o-8 z!KUq{)BJZo-R6H=y6gtK&9sc1Q{3`sdxa5`-cu}5^`0UujZ0<3JPJ?$;Nq|HVU~hP zvoAOA&b**|{sWV!1LY2hPp{R6jp4pYtkT$|d=|dta>;%v(Ew@K1AP+IBQh*j# z7Y%|TJ@tU+TfN%$sF0*Yc8Zx$cLW4$)Qbx}Tj;&$T55;86ho%^fg^lPVfE@Q4za<) zQ3aM7Bi*w{Ac@={8*5%;mpvT-d5vzsVa@bmK;vR+6`E`&<_py%5Q*1zD`3BMN1{KI zCFXEFith#AY?SR<(?fQTPAAF-A&g%fB#^J19-i^v-YY7IkzXA6D>MC%jacf7zghrJ zk%j}UzYYh%A*AJBXizvlGAb%KHl7d`8 zhZ&){Rfva=N(+!k*b`&}3G4o82MW>JTH5~vgMqa-)+P0|j!#td51^NrSD3NP==BXO zu)03JG_o|dxw?j3LyyB(!uZE@0;H&PJIt4}Lu58ik9IYDOt1}VOe1gUJ4mMl`GiFt`*Jyj7aOrqmo{P_u zYaC?EbjHiqXQwFv5`52l-mP3FMtMq#@<{xR1#Y8Nu0=JKH6$8(L@T(P+NB+iwW5Xd z*XOO~vbbNajPiKZFwm)~d1S8VsOV1Z=M#YccynPg{DiAeX|w1{qicOL2#hyZ_^=5* zO?%sAE0^B_ju4ESu`BEM(ZTzr#GKw&__schg+NT%e?e za8d3tOfoDZta7j@P42}K7jA?DeJllN74j{y--V5SHGFSsO16Nvpd zu!+HNmGFvy|02Iv2#&Vs$t~e$SZ0#{;j%##^}{KOTbd=Wl{B3-Pb!f6Vi6L&>3YSF zsQFIDs+4}P)O~pAm})YK@paBjnFo`6)^1WEd9;mMV2IO!Ag;{nvyiV0deNrwlG!Mi z>BlPFY(IPBP_4l0!Bs)ZHR3nN#KK%76LankH{H~1{w{d+&7E;}=qUC~kgJI4_7hXb zn|a^s<_n$`1@J9eR+@1cc0Xp~IOS&E&|Cd+(eEYw1joTEo-*68i}Ktpb2~iS=+~`V zst-`|P*t__%hLBw9mjW39kBZy$B1$ps!$GW(OB2H)xqQ%H#;v0jadfkNNpP_uPM=~ z9mWcO#~bQOtvk+7h}D(n4GWYyifIP7!8i0pnHD?Q)VuF`!sM`6B`w|r!JxsoEW%_& zTs|;xEjEdBGLl+APO79pO~?4ZR^eZMtiu1%J^qi>VkCk&of#IIk)9QTN=JmkaxkdE z9OjURB?K6}riL!0wx&D;U4zYTfHR^ip4K-oK8me=Oj=wcgKHufY9LR_5!jjn((Zp# z=mY|?5{}$}GxQGzZ4hlH!V&EwZ)}#IPqi&=hV3sr59XFA1At|sDMTA2P~`MX9v}z7 zzd8geRs_(AQ3dx}D~39ZQNLy+P+6s!){2DCy)RplhM^_3&pW#7HJH(xjWSxV={11p zg0@xo%2v)n4D_AP(^7_ZCF!u* zpZ!Q!)`KZYQ3mMk2f5^%gax{pkMA~@QnX>Tiz|s#^+J0qBP|VYpSSx{{Az8S2|xfG zNbBdlXWQRP=0-tL2m~tQZ^_)^EN!HUG8!!}T=th_Zcv4ayt1-}1~XQ}=*ch1+%#x= zXU}Ypp`qO4iJz0X1yF76j_$cxRSglW>frj1WbSgscBiVq%bstl$Me?CW$HhYxw$xm z02DGH@2y&;k%Z@bM(s;UO6I1;FDl&>dH++CbTuc2!H~eP)>}ykRXdW=`+t7&#(S@a^_CXx0uZf0HOT*4ov45GaAALjBT8gJlK$}*mrd6WBgYV0H z#PaC~G1O|9)H?|fpvxwuB0h6?AAb!qZ`Xj~$TEIg#M zBU9qG3_sv1;XI~1*UuIlPHtJBqRRcn(cXs0emOeniT-WQyITAu?NmC0B1?Fl!tRY^ zXIIrxu(!)a&I|{4N{6(?_=Q9;oAl>R8hu-+QD%s3j|#b=gxyG%r*YVoAYX33pqykK zb8ebL_Xt{>P@fmHGIG0(yHPQVR89qK+NC(VbJ{mb61&W}(;RYUOHZQYSM^l#&K?~x zmAqNT?om;fe@QA!48l33b7a&xCD*G7#DV15s*_@&rS)t1VtE;*IepE81vNvRk@>X| zO1!U|*IV@}48U|qUd;WAboN!9VNQHy{hHfXbL_v%*gB8b+^iB8ZXJivf(5y5Wt*ye zwtu3@aZ~WPrm~r$>cKXvx~&IAc=SHZXt&3_`|t}ozk#74s~WJY*W~WI_hvQY;)$SC zDl#OFLj!W2zEgY*K_}KRE`J&)rR`56Fa|WH5!8qp4uH&igS;KiGTH z@S}78G}O!GXv~TyK$1)=xTc-~D##W^?ivO1nz(a9C~WrPGa)Ima6qVcN?*O=vV^8Q% z@N%O78S6d1;Eg)-V&jG3s-@iu)T=-vBf4vZFvPa_bJRs+-G6{ro6iXbvv zKCetQAiD@9EAIm_%j(^kNMxm$lzIZE(}VXOuCS%e;jXQYJAW`Fve#1vHmAEInThRK z3VpR5m+Jc{{8j3>c!_PkxV!G>Gq4T)fq9DUF`rLA2P2x=Wub()#VP9#jPtlpp!Q=F zmPo?X?QbW~sfzcQTH!fmHmJNl0tTw=pv@F@pVl4)V3Eon_<=|&ob8<`%Ph`E4xJBs zgduI43X~DI8_!jWrg{o;omNe)LWZ=5g8{|XJR=~p$-zv5W1UJ^^7Eh#qKU^1|Xl(718H+!LU*kfE%F7r(3QQW_V126IdCl%pAexAS z-1^+1$nXevB!Pn-G%0+b;_&a&V$u-bKS#kqm+^Xo^_%n!(3^`ogwM_yRIoI?{VQXE ztZlpMw`8ACdbEdFows5_~IQ2^4xKy=s15{ku{M=vr2$o(!KMwSKrk);-If+@6zQJFvPC)mU7G% z&{#UM#-CLp51Y&n4}PWa2%}UiGv$kJ7np6{x$w=U2DIkS`uSUL>zk8DkGNclPDf$Q zSz7tDPFDUDBGYci3bUKP3L;mr5N0j6A3T1`Bi&82xHJ9#Gdea^S9*55=F z&lxGxtHBlMjg zwaNpky!9wUPJF`osZC`5tjWM^vK9F!A2>wX3+K-LJm7>)U#M{$B;NB`&}UxF#tvEt za&*((-+xV%mVlH+letbc4(tX=j}vGL?YC~*?ySd`h_+=ga5m!#P9po&mrq~6ov|_Y z;!-owCFhVVW(*yf5R%U1R2jo>&Xf^9FxPXYND3$Bhu9gs#-c@4besSdboOgaQ4&t; z5ftXdWM-R62LdX2*6@Yk}&LY58Lp!%6bdbUi9_hMN`cfgZBKB zR}SXSHQwc%x&>Z1vSFMpk-GB~74=+(Xu z9O$*-J3-;3Kq5Co-GS;!*cnplNQZE3`R0bJS#1WZriEziirb$J3A490-3>N%)c=5T z_Y)7ZF%7*iC1H*aF*!WvpC}~{IeSSx)VeP;JwHs*QOdC(RQ^XMfS6r7~bE>*Y3OjKiwXLlK9K-K+pViR_;i#or z>(ZjQc1H~ddG_9zNe?W)L%*KKlDKwC&)wzYJ0{*;XO#3|RQ;%~C z4ADlM0-Q<$&rRbRkg+2SqDCo#v$;a84A_?4*thtYC=F*WMUf9_gwj>JN4_raL^<0S zqUP0vk2<3u5i$DP5g&5JsTbnYkg?4DS6FMJuFUAZ7L5sTkEf3y*YhA4t;dV-QR{94 z5e%Y&dyJe;2~R#TCc8)Q%MjcO`EJlAs-#neHwMx=iC39A12QpAYl#0l;+66*N$wFHAr^t%~f!+)B zXtT8212OM?GovHo?)#kHj^JbJj>t5fA-tYu9L7e!>ZgBN6HAZH>aXUW zXiB}epqrZ>Gq}eg&z>>M$3=zxdu#!Dl&Mc22Bb(|=gur3})#o(r5*9M281#)aI%>4O1MT_JLLq9; z5#A{DorGDNybA-d&C=KrTC{O|q2rgBvVkO_2r;<@6vq64rp@W6Hq5X5iu_6mml#D) zmBwy<%Aou5&_Ys0JBT}T5)$zu{>)2E^r5M0Vs(GQfnVMc6@w}p zv$bj|mwvn>`$_zr^5z%m_ZK2~G|S0o5xOm(lHRZj%-wky{a>Yn{Xf>^nWSoA9Oz$^ z`-VepP)Ha|J1gUF<-R3QZ53q^11kupQRQFCeQls9ZFvn21AS47lNJ=x!kxdA`=)kl z*K(W^U8NX4!F#E3;pcMShut;goTt<^S3j(3>cRD;U;ilgEea;TG#E~H{>J%F>~B~b zDJ(c%5xA>17enGD+5#Cb$%S@kBza}#(hd>ID%YYMeedt&|0yM!#2bvU zH*&&RweMc6E7o@=v+=#AhPn>sV)N6`X&=8HeM+mIVCq*#0=6ra!hFJT_6I@~WAC2i z;2eZ-T|G9~Z!~|m0wRvLzgQmnIB|{>I#DkopxQmdsC1@V@7-y&7&6hkyPs|&L;)ANlE39^JnfZG-dP!Qhdx(8GhB$avQhQilEnFRP)$UmAxnJudtK4dp?J? zIDTCvobH6?cZJWPFG(fg#@C{KyZ8;nv11xPSn1!Fcy z2D7@|er%|FSFbx!74Oz=EiBeGd_otW*iQbz41XFSle4c77Nyz_NYG(P%$Bj;;4X>_ ztxyx{t9B78>iXIxi)Pv}dt{c>UVa;?5_INk^e5*%aXyzRiP%hnnruIrN~@WLoF;Ea zF!(&#L?^{5U-K=q$6NpFhFY8&wK=UAXu@B1Be7rKW7w?K0-blGh z_F}7MpTEi(xWa~0prBR=TsFIqN2F~4Zc}8@RodSW@sVVRKI6YCPY6L3^TXbDOG6ca zV-WqkMJJUar)FvT1xKd+{=3*J01y|Xdzh6THdNJojr%|ueAK2T+KMS7DAUkCdlnjd zQt(v>#@bo+-Gp^pRS^B9wC0*dLGkkj)zXD*2P218<>F%?GJ+_WX|8wr#N}60?30eD zBc&7P96weK8g1P^Q_>?}WnXGKmRUM>a2@OmW_5D91++pY>s#zHJpkMLpf# zj?z6}MbJ$M5cM8DoUyc7G5c82xqBay0|p&&xOGw`*M4kA!KYVGZPY>DgHc32f)d6u zt$CcDUPJX+*IAc4lC$?eW<#EnCEaTVgUJX%t1O&IkiRC7Om_S6?dPK~BaH*d@d+N4 z4uCHCLc22cC9abl!#Ve9WLNV)F5i7epE%wMwtD7&i~77lDvHF*mGAc!x9i&hQ)0t$ z@vVY+6#`4xjHTHeOVy;5tpMkC#jnY4Y{@hfXas$#VFkL^SlnR#_pG_OvJinH1-)Qp z9At5NhhoPws5%cBYS&h#clH?@g^X$QJ%g26i$QC^s*008a5d~x+OSC`Dg`OB@11nHYpK$fS)VKs1 zo5Ssd8+TQa)7F;MfF>FL92X`_0aWfW3*}N6kZL}N;quDke)$RD6%0HE)n*u@t5QQ= zTk8{wwaM98ssdStcgPZMnxlR7*cr=RFQZXluG@SdEh}0#2JtoS>#JlZEI~=cyPYqr zBoiontzkcX)+Co!7`Y*(fJCe+kVE4~Tx@GIrdx|R1g%Gu>=HAOBHc1PB6z1ehDcbk z19|sFJXOdc5|zeHfvLj#8hGZsD0h%Op*ZSKZJV)PzZO)lX8r{JdxY-#lPJ#tzM2+WZPvK$A~pBWEi zWT3Hhpw-NXRtn4v^2mi*1EeRLF6^8thRKnULEQ{#kQ@-TV{!#{X+ZOqE|8>aU#u^r zho{DgLBfhjgod)XXx5;zvs^FPs_qz8(At(>W>L}qOa(yeNaQMyZ!oN8%r(R&BX6`h z8HsnO#<~JzF9n`|<{*&g)Zn0O_EDN=%fKlfBBG+%qxWJXhJ}djkW2V>S{mG=K`K2M zs|e8~!<=$aUb4LY3fW~*w-NI3#4^b0bz5=)W2p5iv7eL7L`Ed=2@Mg+0Bm_u#Ty|^ zy+JKH-5!}Q=M({x#+zKO3_i~+?!1{PXJja5Q%I-$z;D|!y5-=@BN9m7m|V?d&qetn z5iF8)K&4+y0DCo=S;e}NaqkLhiArTs`nDHa0A0r@A` f&S^I(Ws8a5cGm0!?i~ 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∨0>FQDtWeMpkT4)R`xh?!PY;0TFNo2if*t|E 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 +#include +#include +#include +#include +#include +#include +#include "cfSimpleGet.h" + +#define MAX_PATH_LEN 256 +#define MAX_URL_LEN 1024 +#define MAX_THREADS 100 + +#define DEBUG_PRINT 0 +#if DEBUG_PRINT +#define dprintf(args...) printf(args) +#else +#define dprintf(args...) +#endif + +/* + * Until Radar 2731877 (CFURLCreateWithBytes chokes on '|') is fixed, we skip the + * fetching of anything with that character. + */ +#define SKIP_MULTI_QUERIES 1 + +/* + * List of servers known to NOT support SSL; if images from these servers are + * needed, get them via http:. + */ +static const char *nonSslSites[] = { + "cover2.cduniverse.com", + "a248.e.akamai.net", + NULL +}; + +/* return nonzero if specified host is in nonSslSites */ +static int isHostNonSsl( + const char *host) +{ + const char **nss = nonSslSites; + while(*nss != NULL) { + if(!strcmp(*nss, host)) { + return 1; + } + nss++; + } + return 0; +} + +/* + * Used to force single-threaded access to URLSimpleDownload. + */ +static Mutex urlLock; + +static void urlThreadLock() +{ + urlLock.lock(); +} + +static void urlThreadUnlock() +{ + urlLock.unlock(); +} + +/* + * Parameters for one thread, which fetches the contents of one URL (in this + * case, an image source). + */ +typedef struct { + /* in */ + const char *host; + char path[MAX_PATH_LEN]; + bool isSsl; + bool useCfNet; + int singleThread; + int quiet; + pthread_t pthr; + unsigned threadNum; + + /* out */ + OSStatus ortn; + unsigned bytesRead; +} ThreadParams; + +static void usage(char **argv) +{ + printf("%s hostname path [options]\n", argv[0]); + printf("Options:\n"); + printf(" u (URLAccess; default is CFNetwork)\n"); + printf(" s connect via SSL\n"); + printf(" t single thread access to URLSimpleDownload\n"); + printf(" q quiet\n"); + exit(1); +} + +static void printUrl( + const char *host, + const char *path, + int isSsl) +{ + if(isSsl) { + printf("https://%s%s", host, path); + } + else { + printf("http://%s%s", host, path); + } +} + +/* + * Given a hostname, path, and SSL flag, fetch the data, optionally + * returning it in the form of a CFDataRef. + */ +static OSStatus fetchUrl( + const char *host, + const char *path, + bool isSsl, + bool useCfNet, + int singleThread, + unsigned *bytesRead, // RETURNED, always + CFDataRef *cfData) // optional, RETURNED +{ + char url[MAX_URL_LEN]; + char *scheme; + OSStatus ortn; + + *bytesRead = 0; + if(isSsl) { + scheme = "https://"; + } + else { + scheme = "http://"; + } + sprintf(url, "%s%s%s", scheme, host, path); + if(singleThread) { + urlThreadLock(); + } + if(useCfNet) { + CFDataRef cd = cfSimpleGet(url); + if(cd) { + /* always report this */ + *bytesRead = CFDataGetLength(cd); + if(cfData) { + /* optional */ + *cfData = cd; + } + else { + /* caller doesn't want */ + CFRelease(cd); + } + ortn = noErr; + } + else { + printf("implied ioErr from cfnet\n"); + ortn = ioErr; + } + } + else { + /* original URLAccess mechanism */ + + Handle h = NewHandle(0); + ortn = URLSimpleDownload(url, + NULL, + h, + 0, //kURLDisplayProgressFlag, + NULL, //eventCallback, + NULL); // userContext + *bytesRead = GetHandleSize(h); + if((cfData != NULL) && (ortn == noErr)) { + CFDataRef cd = CFDataCreate(NULL, (UInt8 *)*h, *bytesRead); + *cfData = cd; + } + if(ortn) { + printf("%d returned from URLSimpleDownload\n", (int)ortn); + } + DisposeHandle(h); + } + if(singleThread) { + urlThreadUnlock(); + } + dprintf("...read %d bytes from %s\n", (int)(*bytesRead), url); + return ortn; +} + +/* + * Main pthread body, fetches source for one image. + */ +static void *imageThread(void *arg) +{ + ThreadParams *params = (ThreadParams *)arg; + + params->ortn = fetchUrl(params->host, + params->path, + params->isSsl, + params->useCfNet, + params->singleThread, + ¶ms->bytesRead, + NULL); // don't want the data + pthread_exit(NULL); + /* NOT REACHED */ + return NULL; +} + +/* + * Given a Handle supposedly associated with a page of HTML, do an el-cheapo parse + * of the HTML looking for IMG SRC tags. Fork off a thread for each image. Wait for + * each thread to complete. Returns total number of errors of any kind found. + */ +static int fetchImages( + CFDataRef cfData, + const char *host, + const char *origPath, + int isSsl, + bool useCfNet, + int singleThread, + int quiet) +{ + char *mungedHtml; + Size mungedLen; + char *cp; + char *imageNameStart; + char *imageNameEnd; + unsigned imageNameLen; + ThreadParams *params = NULL; // big array + ThreadParams *thisThread; + unsigned threadDex; + int prtn; + unsigned numThreads = 0; // valid entries in params[] + int totalErrors = 0; + char *basePath = NULL; + + /* + * If the original path ends in '/', use it as basePath. + * Else strip off trailing component. + */ + unsigned origPathLen = strlen(origPath); + basePath = strdup(origPath); + if(origPath[origPathLen - 1] != '/') { + /* trim */ + unsigned basePathLen = origPathLen; + for(char *cp=basePath + origPathLen - 1; cp > basePath; cp--) { + basePathLen--; + if(*cp == '/') { + /* found the last one - string ends here */ + cp[1] = '\0'; + break; + } + } + } + /* re-alloc the raw source as a NULL-terminated C string for easy str-based + * parsing */ + mungedLen = CFDataGetLength(cfData); + if(mungedLen == 0) { + printf("***size() of main page is zero!\n"); + return 0; + } + mungedLen++; + mungedHtml = (char *)malloc(mungedLen); + memmove(mungedHtml, CFDataGetBytePtr(cfData), mungedLen-1); + mungedHtml[mungedLen - 1] = '\0'; + + /* create a ThreadParams array big enough for most purposes */ + params = (ThreadParams *)malloc(sizeof(ThreadParams) * MAX_THREADS); + + /* start of el cheapo parse. Upper-case all "img src" into "IMG SRC". */ + for(;;) { + cp = strstr(mungedHtml, "img src"); + if(cp == NULL) { + break; + } + memmove(cp, "IMG SRC", 7); + cp += 7; + } + + /* convert all '\' to '/' - some URLs (e.g. from cduniverse.com) out there + * use the backslash, but CF's URL can't deal with it */ + for(;;) { + cp = strchr(mungedHtml, '\\'); + if(cp == NULL) { + break; + } + *cp = '/'; + } + + /* search for "IMG SRC", fork off thread to fetch each one's image */ + cp = mungedHtml; + for(;;) { + cp = strstr(cp, "IMG SRC="); + if(cp == NULL) { + break; + } + + /* get ptr to start of image file name */ + cp += 8; + if(*cp == '"') { + /* e.g., */ + imageNameStart = ++cp; + imageNameEnd = strchr(imageNameStart, '"'); + } + else { + /* e.g., */ + char *nextSpace; + imageNameStart = cp; + imageNameEnd = strchr(imageNameStart, '>'); + nextSpace = strchr(imageNameStart, ' '); + if((imageNameEnd == NULL) || (imageNameEnd > nextSpace)) { + imageNameEnd = nextSpace; + } + } + if(imageNameEnd == NULL) { + printf("***Bad HTML - missing quote/bracket after image file name\n"); + continue; + } + cp = imageNameEnd; + + /* fill in a ThreadParams */ + thisThread = ¶ms[numThreads]; + thisThread->host = host; + thisThread->isSsl = isSsl; + thisThread->useCfNet = useCfNet; + thisThread->singleThread = singleThread; + thisThread->threadNum = numThreads; + thisThread->quiet = quiet; + thisThread->ortn = -1; + + /* path may be relative to basePath or a fully qualified URL */ + imageNameLen = imageNameEnd - imageNameStart; + if(imageNameStart[0] == '/') { + /* absolute path, use as is */ + memmove(thisThread->path, imageNameStart, imageNameLen); + thisThread->path[imageNameLen] = '\0'; + } + else if(strncmp(imageNameStart, "http", 4) == 0) { + /* skip "http://" or "https://"; host name goes from after + * tha until next '/' */ + const char *hostStart = strstr(imageNameStart, "//"); + if((hostStart == NULL) || (hostStart > (imageNameEnd-2))) { + /* hmmm...punt */ + continue; + } + hostStart += 2; + const char *hostEnd = strchr(hostStart, '/'); + if(hostEnd >= imageNameEnd) { + /* punt */ + continue; + } + /* we're gonna leak this host string for now */ + unsigned hostLen = hostEnd - hostStart; + char *hostStr = (char *)malloc(hostLen + 1); + memmove(hostStr, hostStart, hostLen); + hostStr[hostLen] = '\0'; + thisThread->host = (const char *)hostStr; + /* remainder is path */ + /* FIXME - may have to deal with port number, currently in host string */ + memmove(thisThread->path, hostEnd, imageNameEnd-hostEnd); + thisThread->path[imageNameEnd-hostEnd] = '\0'; + + if(isSsl && isHostNonSsl(hostStr)) { + /* some sites, e.g., cdu1.cduniverse.com, reference images + * which are NOT available via SSL */ + thisThread->isSsl = 0; + } + } + else { + /* path := basePath | relativePath */ + unsigned basePathLen = strlen(basePath); + memmove(thisThread->path, basePath, basePathLen); + memmove(thisThread->path + basePathLen, imageNameStart, imageNameLen); + thisThread->path[basePathLen + imageNameLen] = '\0'; + } + + #if SKIP_MULTI_QUERIES + if(strchr(thisThread->path, '|')) { + /* CFURLCreateWithBytes will choke, so will URLSimpleDownload */ + continue; + } + #endif + + /* fork off a thread to fetch it */ + if(!quiet) { + printf(" "); + printUrl(thisThread->host, thisThread->path, thisThread->isSsl); + printf(": thread %u : forking imageThread\n", + thisThread->threadNum); + } + prtn = pthread_create(&thisThread->pthr, + NULL, + imageThread, + thisThread); + if(prtn) { + printf("***Error creating pthread (%d)\n", prtn); + totalErrors++; + break; + } + numThreads++; + if(numThreads == MAX_THREADS) { + /* OK, that's enough */ + break; + } + } + free(mungedHtml); + + /* wait for each thread to complete */ + if(!quiet) { + printf(" waiting for image threads to complete...\n"); + } + for(threadDex=0; threadDexpthr, &status); + if(prtn) { + printf("***pthread_join returned %d, aborting\n", prtn); + totalErrors++; + break; + } + if(!quiet || thisThread->ortn) { + printf(" "); + printUrl(thisThread->host, thisThread->path, thisThread->isSsl); + printf(": thread %u : fetch result %d, read %d bytes\n", + thisThread->threadNum, + (int)thisThread->ortn, thisThread->bytesRead); + } + if(thisThread->ortn) { + totalErrors++; + } + } + free(params); + return totalErrors; +} + +int main(int argc, char **argv) +{ + bool isSsl = false; + bool useCfNet = true; + int singleThread = 0; + int quiet = 0; + OSStatus ortn; + int arg; + CFDataRef cfData; + char *host; + char *path; + int ourRtn = 0; + + if(argc < 3) { + usage(argv); + } + host = argv[1]; + path = argv[2]; + for(arg=3; arg 1) ? "errors" : "error", host); + } + return ourRtn; +} diff --git a/SecurityTests/clxutils/userTrustTest/Makefile b/SecurityTests/clxutils/userTrustTest/Makefile new file mode 100644 index 00000000..f091380f --- /dev/null +++ b/SecurityTests/clxutils/userTrustTest/Makefile @@ -0,0 +1,58 @@ +# name of executable to build +EXECUTABLE=userTrustTest +# C++ source (with .cpp extension) +CPSOURCE= userTrustTest.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +# +# Optional files on which *.{c,cpp} depend +# +HDR_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/clxutils/userTrustTest/amazon_v3.100.cer b/SecurityTests/clxutils/userTrustTest/amazon_v3.100.cer new file mode 100644 index 0000000000000000000000000000000000000000..6adab1e777dfde6f6c3cbdc91de916fb24a1cfca GIT binary patch literal 945 zcmXqLVqR;|#4NRdnTe5!Ng!s6&O7Izls2hFU#~OmiDES1W#iOp^Jx3d%gD&e%3u(0 z$Zf#M#vIDRCd?EXY^Y!$2jXxEiw6ZeD!3$;Bq{`_CYKgvmQ?B}c;+SR8R{A6fK+e` ztAZs`f$~LVsYMFTsYNB3X_?81C7Jno3XY{E8TlYx26E!O2BwBaM#ctU5C!C#fw)G- zrk19bQ3mO#4iGjF1R2jE%oUzkoROKAUXq_@C}6+`5@Z))4^B-iDalDSlrRtjyHkYU zF*mU)KTj_?KNsRYaRX7146_Jdd3m{BB3#y>aXzx&8Ce;a8+#cH8atU98yQYS=H830 zzWJu`Tz;gC=V?)aIh9>a`;T9&6V`lqGeNDT`=sdhgI%wa&0dvBlv>2CX$$^#|AxQm z{=nK*Yj35OKRR zOVsUmpP0RTwe+9IP2NHY*=rTdd$)c*-O0qv$iTR`i7~~Xi7^2jAF{$MOa=@F+(5s` z^0TloGqEl(umN%8SxgO#4Gb6PFVJn%&L}AP&@#|qeKGy_Egc>{JfR&73JCMgz?{->9v+Sc^;WgkA@ zkafjFLZ@0%&p=g78EQvPetJHN9r|U(U@?$Ms9Auyjv=$i;pnY8%{PMgt|v@qX7}~( z`k{Q7L;J6k#w@jOdQUqQa?khN$=Vc^ziO(4#NlHRM$TGYU+unDE^@nj{9tv7;w69o z>s1A!(mvl9rwJ4Xt)7e& Nk8i%VD)H!PW&nH?DSH3_ literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/userTrustTest/userTrustTest.cpp b/SecurityTests/clxutils/userTrustTest/userTrustTest.cpp new file mode 100644 index 00000000..7b87318d --- /dev/null +++ b/SecurityTests/clxutils/userTrustTest/userTrustTest.cpp @@ -0,0 +1,244 @@ +/* + * userTrustTest.cpp - simple test of SecTrustSetUserTrustLegacy() and + * SecTrustGetUserTrust() + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IGNORE_EXISTING_STATE 0 + +static void usage(char **argv) +{ + printf("usage: %s [options] known_good_leaf_cert [ca_cert...]\n", argv[0]); + printf("Options:\n"); + printf(" -q -- quiet\n"); + exit(1); +} + +static char *secTrustResultStr( + SecTrustResultType result) +{ + static char unknownStr[100]; + + switch(result) { + case kSecTrustResultInvalid: return "kSecTrustResultInvalid"; + case kSecTrustResultProceed: return "kSecTrustResultProceed"; + case kSecTrustResultConfirm: return "kSecTrustResultConfirm"; + case kSecTrustResultDeny: return "kSecTrustResultDeny"; + case kSecTrustResultUnspecified: return "kSecTrustResultUnspecified"; + case kSecTrustResultRecoverableTrustFailure: + return "kSecTrustResultRecoverableTrustFailure"; + case kSecTrustResultFatalTrustFailure: return "kSecTrustResultFatalTrustFailure"; + case kSecTrustResultOtherError: return "kSecTrustResultOtherError"; + default: + sprintf(unknownStr, "UNKNOWN ResultType (%d)\n", + (int)result); + return unknownStr; + } +} + +/* do a SecTrustEvaluate, ensure resultType is as specified */ +static int doEval( + CFArrayRef certs, + SecPolicyRef policy, + SecTrustResultType expectedResult, + bool quiet) +{ + OSStatus ortn; + SecTrustRef trustRef = NULL; + SecTrustResultType result; + int ourRtn = 0; + + ortn = SecTrustCreateWithCertificates(certs, policy, &trustRef); + if(ortn) { + cssmPerror("SecTrustCreateWithCertificates", ortn); + return -1; + } + ortn = SecTrustEvaluate(trustRef, &result); + if(ortn) { + /* shouldn't fail no matter what resultType we expect */ + cssmPerror("SecTrustEvaluate", ortn); + ourRtn = -1; + goto errOut; + } + if(expectedResult == result) { + if(!quiet) { + printf("...got %s as expected\n", secTrustResultStr(result)); + } + } + else { + printf("***Expected %s, got %s\n", secTrustResultStr(expectedResult), + secTrustResultStr(result)); + ourRtn = -1; + } +errOut: + CFRelease(trustRef); + return ourRtn; +} + +/* Do a SecTrustGetUserTrust(), ensure result is as specified */ +static int doGetUserTrust( + SecCertificateRef certRef, + SecPolicyRef policy, + SecTrustResultType expectedResult) +{ + SecTrustResultType foundResult; + OSStatus ortn = SecTrustGetUserTrust(certRef, policy, &foundResult); + if(ortn) { + cssmPerror("SecTrustGetUserTrust", ortn); + return -1; + } + if(foundResult != expectedResult) { + printf("***Expected current resultType %s; found %s\n", + secTrustResultStr(expectedResult), secTrustResultStr(foundResult)); + return -1; + } + return 0; +} + +/* Do SecTrustSetUserTrustLegacy() followed by SecTrustGetUserTrust() */ +static int doSetVerifyUserTrust( + SecCertificateRef certRef, + SecPolicyRef policy, + SecTrustResultType result) +{ + OSStatus ortn; + ortn = SecTrustSetUserTrustLegacy(certRef, policy, result); + if(ortn) { + cssmPerror("SecTrustSetUserTrustLegacy", ortn); + return -1; + } + return doGetUserTrust(certRef, policy, result); +} + +static int doTest( + CFArrayRef certArray, + SecPolicyRef policy, + bool quiet) +{ + int ourRtn = 0; + SecCertificateRef leafCert = (SecCertificateRef)CFArrayGetValueAtIndex( + certArray, 0); + + if(!quiet) { + printf("Verifying cert is good as is...\n"); + } + ourRtn = doEval(certArray, policy, kSecTrustResultUnspecified, quiet); + if(ourRtn && !IGNORE_EXISTING_STATE) { + return ourRtn; + } + + if(!quiet) { + printf("Verifying cert currently has kSecTrustResultUnspecified...\n"); + } + if(doGetUserTrust(leafCert, policy, kSecTrustResultUnspecified)) { + ourRtn = -1; + /* but keep going */ + } + + if(!quiet) { + printf("setting and verifying SecTrustResultDeny...\n"); + } + if(doSetVerifyUserTrust(leafCert, policy, kSecTrustResultDeny)) { + ourRtn = -1; + } + + if(!quiet) { + printf("Verify cert with SecTrustResultDeny...\n"); + } + ourRtn = doEval(certArray, policy, kSecTrustResultDeny, quiet); + if(ourRtn) { + ourRtn = -1; + } + + if(!quiet) { + printf("setting and verifying kSecTrustResultConfirm...\n"); + } + if(doSetVerifyUserTrust(leafCert, policy, kSecTrustResultConfirm)) { + ourRtn = -1; + } + + if(!quiet) { + printf("Verify cert with kSecTrustResultConfirm...\n"); + } + ourRtn = doEval(certArray, policy, kSecTrustResultConfirm, quiet); + if(ourRtn) { + ourRtn = -1; + } + + if(!quiet) { + printf("setting and verifying kSecTrustResultUnspecified...\n"); + } + if(doSetVerifyUserTrust(leafCert, policy, kSecTrustResultUnspecified)) { + ourRtn = -1; + } + + if(!quiet) { + printf("Verify cert with kSecTrustResultUnspecified...\n"); + } + ourRtn = doEval(certArray, policy, kSecTrustResultUnspecified, quiet); + + if(!quiet) { + printf("Verify SecTrustSetUserTrust(kSecTrustResultConfirm) fails...\n"); + } + /* verify Radar 4642125 - this should fail, not crash */ + OSStatus ortn = SecTrustSetUserTrust(leafCert, policy, kSecTrustResultConfirm); + if(ortn != unimpErr) { + printf("***SecTrustSetUserTrust returned %ld; expected %ld (unimpErr)\n", + (long)ortn, (long)unimpErr); + ourRtn = -1; + } + return ourRtn; +} + +int main(int argc, char **argv) +{ + bool quiet = false; + + int arg; + while ((arg = getopt(argc, argv, "qh")) != -1) { + switch (arg) { + case 'q': + quiet = true; + break; + case 'h': + usage(argv); + } + } + + unsigned numCerts = argc - optind; + if(numCerts == 0) { + usage(argv); + } + CFMutableArrayRef certArray = CFArrayCreateMutable(NULL, 0, + &kCFTypeArrayCallBacks); + for(int dex=optind; dexTM;J*S^3O}zB;*(2>HhOEM*k|hhSS)`wTblb#r`m_f*-u}@u9tcZT#h>~- zd(pYw7v}reO|a7PQmu$$l?dCO8LJVvO83|W^NE3zmIpR7F*7nSE^cC6ZP3KH+<*`0 z5m|ml#{VoV%uH+t4CFz4WfowBHHbX&J+VrUM>2nUREg(o*$BxM67CFOpUd*Gh_Q&Q z6lOoos91SA?0gzm@HMu}+($o&fa6(KfrZ}y6l9zUZ61uNOpM%|290eXgN0b?4Qkt} zb5arutn~FWQ&Nic@-j>GQZkDZ^>QcjZ;98t!iWdjBX$ajBp?cj&dMv48)!w zVP{8GqvZTjplYxJ2otO$IUgtpN@YM*h;#;2oeUBWHfY=oa)>-j<7$J(6$Xt<7c?$f z&^W)Xan1lb%04-@s3bEjGdZy&wJ5bLA4q5B=jCJ;mslrd<|P(YBBv%`_F@JmBQuQ$ z=Pe5S*B&(x-y!-FlE hW=Y!kPO&oU5%}Fhd4@PE z02L?zg%zB05{ru!j1_znGjkN29S!8fc@2yVER75d&5ex>4WfWtQv+iopqQb#p=p#s zF*V%6YrqY0CrfCsv%8_Zfh@#nVj-@so;#|Q zj{l{W%&OK24Owd&d+OSXq!Sm;w4}-=-@K!0GxgTZhYyV2exA zK@*dJ0UyvKviyvU|5;d=nb-~($b0- zb6GwXF%}Wdb!n_U{>HZI?B99oetmXwo02UHj%is17JdUzkZ~roc`&9jF>-SnG{P60)?s*wRO!hs|(%7G*} z(t)%w5Q8EfB;=@Sl$>7*R1a1HVS@D}=K}>nDGjI!k=B5!lR@Ia28~-lPLXG6Tw~C< z(x7qKg2u%Q8W*%R&K*cs*(awKm1L%6CMTAp7NwTu1L@5CyqwJ966>VQyu_kP15J>t zRauk_6xg`5*%(!LJYO`t~a|-5IWiN{=ehvli$ef zn-w!ZXXf?ip~eAbY^$QKY-3VMqNGt literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/vfyCacCert/certs/joe2.ID.cer b/SecurityTests/clxutils/vfyCacCert/certs/joe2.ID.cer new file mode 100644 index 0000000000000000000000000000000000000000..9391e5c03b0bdca562cecfa500db3e058f3b1d7c GIT binary patch literal 962 zcmXqLV%}%a#H_x6nTe5!iHRlOfR~L^tIebBJ1-+6D=ULRm?5_TCmVAp3!5-gXt1G# zff$IxCCneH7p$k?o?n()l$V>DS7OLxzy*@w7G`$IcR}I>czYTO8t{YUn1wlH<_3j85kEgF_sxLF%}u{0sSM(&&c?ng@u`k?SO$ih_B27jHCvU z>6`Y$5xg@UN#%CZ4QozR|#v<}ZJ?5e1y}~M8(dZ`esYZGKS8Wyo z$E~aa3%>!c0XG|GLYoI;Dib3&r$G)#n-EK?L2_GSPD)~dmA-yvN=mU_US^42N@j7Q zUT$WNesZ3waf-9Cs*!=G3y^SjR5eP@F9nJLQvi$!Od232P!N=SfT|D)2q>Nm5)U?L zoC&f{o~3c3L1UjmWA}o_js=aaZH-Mdx7t2AwWuUBEi*Z>B(*5DEFVZ`=I7;P7MEBj zW#%OoRU#)0VD4ZBrijMe!k=N^Y?TghMQS)KD~xz~Xj+MWeR;|M=dG3e&jRKK_A^cp z<1%s2Zk-qWZE{z-Zn`k_Q@Bp?M`Nf;+h_h8tAeGDwXqmazH9a9qQK#(PL=J~S5MBCoavgq9{`PYFR%ar literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/vfyCacCert/certs/joe2.encrypt.cer b/SecurityTests/clxutils/vfyCacCert/certs/joe2.encrypt.cer new file mode 100644 index 0000000000000000000000000000000000000000..c020d46a5aeda697b2b5842ef09127ea2f03ec15 GIT binary patch literal 1004 zcmXqLVt!%J#2mPQnTe5!iHYNy0WTY;R+~rLcV0$DR#pas2t#fIPB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzIna?}Ee&@b)wmHV_2KF$;4!8!PxG zX67h3I~vG|^BNc#7#bTIfI$?HYl6fzsHBF?2v>y$`x&Yks6gBy>lEbg?&0X`8l>mt zAM6_7p%T!>Z@I|=DyjS z|M0H6_k*$>oyn`(|J{iFZFY3x4RwuuD{jW-+X$WBA!K1tT9~Y`USEP?xtVtRDxLzi z8iNU|S$lF9%f8AK6U@GPTBTif#sjK?XLOmv&?>{R_~-o z`#1B*eBcZ3F})zoAo*&NIukP^1LNW*#(4%!jI#{*fc}x?XJq`(!otkNssQ$%tRRc5 zfpnv!Q&E0;Mq+Mik)Bt6szXMhUS48ZrCx4kj)6Q#mof`5G8;rz9_*Vb(VS>l(q3G2C^Upd@N!tA|gK@L}bjppi*V6m=#};qx0^~Hc4UWmiYdG9$wmofu z^R|;azCGTz=45_`*}M2pQiieql9#8?O;Pn@y}Wd?WY1@}cOlM?>~HLx?)%iI{p0oR ipI^;&-5VBV8(GjBy1%rO`%v4z2g2H7&$w?kiva+dut2>4 literal 0 HcmV?d00001 diff --git a/SecurityTests/clxutils/vfyCacCert/certs/joe2.sign.cer b/SecurityTests/clxutils/vfyCacCert/certs/joe2.sign.cer new file mode 100644 index 0000000000000000000000000000000000000000..6412eb6715dd52954a5c6b4dcb65948e26ce1ffb GIT binary patch literal 1072 zcmXqLV$m^ZVxGEynTe5!iHYN?0WTY;R+~rLcV0$DR#pas2t#fIPB!LH7B*p~&|pIe z12GVXOPD`YFIZ2(J-;lqC@(iPuf&kYfD0tUEzIna?}Ee&@b)wmHV_2KF$;4!8!PxG zX67h3I~vG|^BNc#7#bTIfI$?HYl6fzsHBF?2v>y$`x&Yks6gBy>lEbg?&0X`8l>mt zAM6_7p%JDv$Z~(?0Uhy; zEGJlUHc#`}n|yeGzLBob(PYJ`xesO?K4`H2`@_HW0rR4J{DQ2ct{;@Dm%5#5x*#BZ z75n`MSz9umzjQsdBY5t_nu}|q!o*i}-9F}jh-K=v3(AKzxo4-{oD-3hxUWRUblaKo zt|QyRr%_{06)R+-#f)Z61uNOpM%|2Du<@LM&+pDQ!tPDTxJE`ueFU#d>*}C3-2D z#ff^knK}B&d8)=K&c>=n2B0VgQqGR5M#=f5Kv7^KfH8ro1H=Rhf>IDr6(S7*#gjqe z!3K@9K=#SAG)^*T>^EraSVQyu_kP10|5#R6$`5$_-rFY>X_7P39s@Ol%xLHY+PTGmC)>NR1$it$}r;q*GCT zdPZVyYLT8-eyT%8p +#include +#include +#include /* private */ +//#include "clutils.h" +#include /* private cssmErrorString() */ +#include +#include +#include + +/* + * More-or-less hard-coded locations of system-wide keychains containing + * intermediate certs (which are required for this operation) and + * CRLs (which is optional; it's just a cache for performance reasons). + */ +#define X509_CERT_DB "/System/Library/Keychains/X509Certificates" +#define X509_CRL_DB "/private/var/db/crls/crlcache.db" + +static void usage(char **argv) +{ + printf("Usage: %s certFileName [options]\n", argv[0]); + printf("Options:\n"); + printf(" a allow unverified certs\n"); + printf(" d disable CRL verification\n"); + printf(" n no network fetch of CRLs\n"); + exit(1); +} + +/*** Display verify results ***/ + +static void statusBitTest( + CSSM_TP_APPLE_CERT_STATUS certStatus, + uint32 bit, + const char *str) +{ + if(certStatus & bit) { + printf("%s ", str); + } +} + +static void printCertInfo( + unsigned numCerts, // from CertGroup + const CSSM_TP_APPLE_EVIDENCE_INFO *info) +{ + CSSM_TP_APPLE_CERT_STATUS cs; + + for(unsigned i=0; iStatusBits; + printf(" cert %u:\n", i); + printf(" StatusBits : 0x%x", (unsigned)cs); + if(cs) { + printf(" ( "); + statusBitTest(cs, CSSM_CERT_STATUS_EXPIRED, "EXPIRED"); + statusBitTest(cs, CSSM_CERT_STATUS_NOT_VALID_YET, + "NOT_VALID_YET"); + statusBitTest(cs, CSSM_CERT_STATUS_IS_IN_INPUT_CERTS, + "IS_IN_INPUT_CERTS"); + statusBitTest(cs, CSSM_CERT_STATUS_IS_IN_ANCHORS, + "IS_IN_ANCHORS"); + statusBitTest(cs, CSSM_CERT_STATUS_IS_ROOT, "IS_ROOT"); + statusBitTest(cs, CSSM_CERT_STATUS_IS_FROM_NET, "IS_FROM_NET"); + printf(")\n"); + } + else { + printf("\n"); + } + printf(" NumStatusCodes : %u ", + thisInfo->NumStatusCodes); + for(unsigned j=0; jNumStatusCodes; j++) { + printf("%s ", + cssmErrorString(thisInfo->StatusCodes[j]).c_str()); + } + printf("\n"); + printf(" Index: %u\n", thisInfo->Index); + } + return; +} + +/* we really only need CSSM_EVIDENCE_FORM_APPLE_CERT_INFO */ +#define SHOW_ALL_VFY_RESULTS 0 + +static void dumpVfyResult( + const CSSM_TP_VERIFY_CONTEXT_RESULT *vfyResult) +{ + unsigned numEvidences = vfyResult->NumberOfEvidences; + unsigned numCerts = 0; + printf("Returned evidence:\n"); + for(unsigned dex=0; dexEvidence[dex]; + #if SHOW_ALL_VFY_RESULTS + printf(" Evidence %u:\n", dex); + #endif + switch(ev->EvidenceForm) { + case CSSM_EVIDENCE_FORM_APPLE_HEADER: + { + #if SHOW_ALL_VFY_RESULTS + const CSSM_TP_APPLE_EVIDENCE_HEADER *hdr = + (const CSSM_TP_APPLE_EVIDENCE_HEADER *)(ev->Evidence); + printf(" Form = HEADER; Version = %u\n", hdr->Version); + #endif + break; + } + case CSSM_EVIDENCE_FORM_APPLE_CERTGROUP: + { + const CSSM_CERTGROUP *grp = (const CSSM_CERTGROUP *)ev->Evidence; + numCerts = grp->NumCerts; + #if SHOW_ALL_VFY_RESULTS + /* parse the rest of this eventually */ + /* Note we depend on this coming before the CERT_INFO */ + printf(" Form = CERTGROUP; numCerts = %u\n", numCerts); + #endif + break; + } + case CSSM_EVIDENCE_FORM_APPLE_CERT_INFO: + { + const CSSM_TP_APPLE_EVIDENCE_INFO *info = + (const CSSM_TP_APPLE_EVIDENCE_INFO *)ev->Evidence; + printCertInfo(numCerts, info); + break; + } + default: + printf("***UNKNOWN Evidence form (%u)\n", + (unsigned)ev->EvidenceForm); + break; + } + } +} + +/* free a CSSM_CERT_GROUP */ +void tpFreeCertGroup( + CSSM_CERTGROUP_PTR certGroup, + CSSM_BOOL freeCertData, // free individual CertList.Data + CSSM_BOOL freeStruct) // free the overall CSSM_CERTGROUP +{ + unsigned dex; + + if(certGroup == NULL) { + return; + } + + if(freeCertData) { + /* free the individual cert Data fields */ + for(dex=0; dexNumCerts; dex++) { + APP_FREE(certGroup->GroupList.CertList[dex].Data); + } + } + + /* and the array of CSSM_DATAs */ + if(certGroup->GroupList.CertList) { + APP_FREE(certGroup->GroupList.CertList); + } + + if(freeStruct) { + APP_FREE(certGroup); + } +} + + +/* + * Free the contents of a CSSM_TP_VERIFY_CONTEXT_RESULT returned from + * CSSM_TP_CertGroupVerify(). + */ +CSSM_RETURN freeVfyResult( + CSSM_TP_VERIFY_CONTEXT_RESULT *ctx) +{ + int numCerts = -1; + CSSM_RETURN crtn = CSSM_OK; + + for(unsigned i=0; iNumberOfEvidences; i++) { + CSSM_EVIDENCE_PTR evp = &ctx->Evidence[i]; + switch(evp->EvidenceForm) { + case CSSM_EVIDENCE_FORM_APPLE_HEADER: + /* Evidence = (CSSM_TP_APPLE_EVIDENCE_HEADER *) */ + APP_FREE(evp->Evidence); + evp->Evidence = NULL; + break; + case CSSM_EVIDENCE_FORM_APPLE_CERTGROUP: + { + /* Evidence = CSSM_CERTGROUP_PTR */ + CSSM_CERTGROUP_PTR cgp = (CSSM_CERTGROUP_PTR)evp->Evidence; + numCerts = cgp->NumCerts; + tpFreeCertGroup(cgp, CSSM_TRUE, CSSM_TRUE); + evp->Evidence = NULL; + break; + } + case CSSM_EVIDENCE_FORM_APPLE_CERT_INFO: + { + /* Evidence = array of CSSM_TP_APPLE_EVIDENCE_INFO */ + if(numCerts < 0) { + /* Haven't gotten a CSSM_CERTGROUP_PTR! */ + printf("***Malformed VerifyContextResult (2)\n"); + crtn = CSSMERR_TP_INTERNAL_ERROR; + break; + } + CSSM_TP_APPLE_EVIDENCE_INFO *evInfo = + (CSSM_TP_APPLE_EVIDENCE_INFO *)evp->Evidence; + for(unsigned k=0; k<(unsigned)numCerts; k++) { + /* Dispose of StatusCodes, UniqueRecord */ + CSSM_TP_APPLE_EVIDENCE_INFO *thisEvInfo = + &evInfo[k]; + if(thisEvInfo->StatusCodes) { + APP_FREE(thisEvInfo->StatusCodes); + } + if(thisEvInfo->UniqueRecord) { + CSSM_RETURN crtn = + CSSM_DL_FreeUniqueRecord(thisEvInfo->DlDbHandle, + thisEvInfo->UniqueRecord); + if(crtn) { + cuPrintError("CSSM_DL_FreeUniqueRecord", crtn); + break; + } + thisEvInfo->UniqueRecord = NULL; + } + } /* for each cert info */ + APP_FREE(evp->Evidence); + evp->Evidence = NULL; + break; + } /* CSSM_EVIDENCE_FORM_APPLE_CERT_INFO */ + } /* switch(evp->EvidenceForm) */ + } /* for each evidence */ + if(ctx->Evidence) { + APP_FREE(ctx->Evidence); + ctx->Evidence = NULL; + } + return crtn; +} + +static int testError(CSSM_BOOL quiet) +{ + char resp; + + if(quiet) { + printf("\n***Test aborting.\n"); + exit(1); + } + fpurge(stdin); + printf("a to abort, c to continue: "); + resp = getchar(); + return (resp == 'a'); +} + +/* + * The heart of CAC certification verification. + */ +int vfyCert( + CSSM_TP_HANDLE tpHand, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + const void * certData, + unsigned certLength, + + /* these three booleans will eventually come from system preferences */ + bool enableCrlCheck, + bool requireFullCrlVerify, + bool enableFetchFromNet, + CSSM_DL_DB_HANDLE_PTR certKeychain, + CSSM_DL_DB_HANDLE_PTR crlKeychain) +{ + /* main job is building a CSSM_TP_VERIFY_CONTEXT and its components */ + CSSM_TP_VERIFY_CONTEXT vfyCtx; + CSSM_TP_CALLERAUTH_CONTEXT authCtx; + CSSM_TP_VERIFY_CONTEXT_RESULT vfyResult; + + memset(&vfyCtx, 0, sizeof(CSSM_TP_VERIFY_CONTEXT)); + memset(&authCtx, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT)); + + /* CSSM_TP_CALLERAUTH_CONTEXT components */ + /* + typedef struct cssm_tp_callerauth_context { + CSSM_TP_POLICYINFO Policy; + CSSM_TIMESTRING VerifyTime; + CSSM_TP_STOP_ON VerificationAbortOn; + CSSM_TP_VERIFICATION_RESULTS_CALLBACK CallbackWithVerifiedCert; + uint32 NumberOfAnchorCerts; + CSSM_DATA_PTR AnchorCerts; + CSSM_DL_DB_LIST_PTR DBList; + CSSM_ACCESS_CREDENTIALS_PTR CallerCredentials; + } CSSM_TP_CALLERAUTH_CONTEXT, *CSSM_TP_CALLERAUTH_CONTEXT_PTR; + */ + /* two policies */ + CSSM_FIELD policyIds[2]; + CSSM_APPLE_TP_CRL_OPTIONS crlOpts; + policyIds[0].FieldOid = CSSMOID_APPLE_X509_BASIC; + policyIds[0].FieldValue.Data = NULL; + policyIds[0].FieldValue.Length = 0; + if(enableCrlCheck) { + policyIds[1].FieldOid = CSSMOID_APPLE_TP_REVOCATION_CRL; + policyIds[1].FieldValue.Data = (uint8 *)&crlOpts; + policyIds[1].FieldValue.Length = sizeof(crlOpts); + crlOpts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION; + crlOpts.CrlFlags = 0; + if(requireFullCrlVerify) { + crlOpts.CrlFlags |= CSSM_TP_ACTION_REQUIRE_CRL_PER_CERT; + } + if(enableFetchFromNet) { + crlOpts.CrlFlags |= CSSM_TP_ACTION_FETCH_CRL_FROM_NET; + } + /* optional, may well not exist */ + /* FIXME: as of 12/4/02 this field is ignored by the TP + * and may well go away from the CSSM_APPLE_TP_CRL_OPTIONS + * struct. */ + crlOpts.crlStore = crlKeychain; + + authCtx.Policy.NumberOfPolicyIds = 2; + } + else { + /* No CRL checking */ + authCtx.Policy.NumberOfPolicyIds = 1; + } + authCtx.Policy.PolicyIds = policyIds; + authCtx.Policy.PolicyControl = NULL; + + authCtx.VerifyTime = NULL; + authCtx.VerificationAbortOn = CSSM_TP_STOP_ON_POLICY; + authCtx.CallbackWithVerifiedCert = NULL; + + /* anchors */ + const CSSM_DATA *anchors; + uint32 anchorCount; + OSStatus ortn; + ortn = SecTrustGetCSSMAnchorCertificates(&anchors, &anchorCount); + if(ortn) { + printf("SecTrustGetCSSMAnchorCertificates returned %u\n", ortn); + return -1; + } + authCtx.NumberOfAnchorCerts = anchorCount; + authCtx.AnchorCerts = const_cast(anchors); + + /* DBList of intermediate certs and CRLs */ + CSSM_DL_DB_HANDLE handles[2]; + unsigned numDbs = 0; + if(certKeychain != NULL) { + handles[0] = *certKeychain; + numDbs++; + } + if(crlKeychain != NULL) { + handles[numDbs] = *crlKeychain; + numDbs++; + } + CSSM_DL_DB_LIST dlDbList; + dlDbList.NumHandles = numDbs; + dlDbList.DLDBHandle = &handles[0]; + + authCtx.DBList = &dlDbList; + authCtx.CallerCredentials = NULL; + + /* CSSM_TP_VERIFY_CONTEXT */ + vfyCtx.ActionData.Data = NULL; + vfyCtx.ActionData.Length = 0; + vfyCtx.Action = CSSM_TP_ACTION_DEFAULT; + vfyCtx.Cred = &authCtx; + + /* cook up cert group */ + CSSM_CERTGROUP cssmCerts; + cssmCerts.CertType = CSSM_CERT_X_509v3; + cssmCerts.CertEncoding = CSSM_CERT_ENCODING_DER; + cssmCerts.NumCerts = 1; + CSSM_DATA cert; + cert.Data = (uint8 *)certData; + cert.Length = certLength; + cssmCerts.GroupList.CertList = &cert; + cssmCerts.CertGroupType = CSSM_CERTGROUP_DATA; + + CSSM_RETURN crtn = CSSM_TP_CertGroupVerify(tpHand, + clHand, + cspHand, + &cssmCerts, + &vfyCtx, + &vfyResult); + if(crtn) { + cuPrintError("CSSM_TP_CertGroupVerify", crtn); + } + else { + printf("...verify successful\n"); + } + dumpVfyResult(&vfyResult); + freeVfyResult(&vfyResult); + if(crtn) { + return testError(0); + } + else { + return 0; + } +} + +int main(int argc, char **argv) +{ + int rtn; + CSSM_RETURN crtn; + CSSM_DL_HANDLE dlHand; + CSSM_CSP_HANDLE cspHand; + CSSM_CL_HANDLE clHand; + CSSM_TP_HANDLE tpHand; + CSSM_DL_DB_HANDLE certKeychain; + CSSM_DL_DB_HANDLE crlKeychain; + CSSM_DL_DB_HANDLE_PTR certKeychainPtr = NULL; + CSSM_DL_DB_HANDLE_PTR crlKeychainPtr = NULL; + unsigned char *certData; + unsigned certLength; + bool requireFullCrlVerify = true; + bool enableFetchFromNet = true; + bool enableCrlCheck = true; + int arg; + char *argp; + + if(argc < 2) { + usage(argv); + } + for(arg=2; arg +#include +#include +#include +#include +#include +#include + +static void usage(char **argv) +{ + printf("Usage: %s rootCertFile [subjCertFile]\n", argv[0]); + exit(1); +} + +int main(int argc, char **argv) +{ + CSSM_DATA rootCert; + CSSM_DATA subjCert; + int rtn; + CSSM_CL_HANDLE clHand; + CSSM_RETURN crtn; + char *subjName; + unsigned len; + + if((argc < 2) || (argc > 3)) { + usage(argv); + } + rtn = readFile(argv[1], &rootCert.Data, &len); + if(rtn) { + printf("Error reading %s; %s\n", argv[1], strerror(rtn)); + exit(1); + } + rootCert.Length = len; + + if(argc == 2) { + subjName = argv[1]; // vfy a root cert + } + else { + subjName = argv[2]; + } + rtn = readFile(subjName, &subjCert.Data, (unsigned *)&subjCert.Length); + if(rtn) { + printf("Error reading %s; %s\n", argv[1], strerror(rtn)); + exit(1); + } + clHand = clStartup(); + if(clHand == CSSM_INVALID_HANDLE) { + return 1; + } + crtn = CSSM_CL_CertVerify( + clHand, + CSSM_INVALID_HANDLE, // CCHandle + &subjCert, + &rootCert, + NULL, // VerifyScope + 0); // ScopeSize + if(crtn) { + printError("CSSM_CL_CertVerify", crtn); + } + else { + printf("cert %s verifies OK\n", subjName); + } + return 0; +} + diff --git a/SecurityTests/clxutils/vfyCertChain/Makefile b/SecurityTests/clxutils/vfyCertChain/Makefile new file mode 100644 index 00000000..380feb20 --- /dev/null +++ b/SecurityTests/clxutils/vfyCertChain/Makefile @@ -0,0 +1,54 @@ +# name of executable to build +EXECUTABLE=vfyCertChain +# C++ source (with .cpp extension) +CPSOURCE= vfyCertChain.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/clxutils/vfyCertChain/vfyCertChain.cpp b/SecurityTests/clxutils/vfyCertChain/vfyCertChain.cpp new file mode 100644 index 00000000..8d4f08bc --- /dev/null +++ b/SecurityTests/clxutils/vfyCertChain/vfyCertChain.cpp @@ -0,0 +1,426 @@ +/* + * Gather up user-specified raw cert files, attempt to verify as a + * cert chain + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void usage(char **argv) +{ + printf("Usage: %s [options] certFile ..., leaf first\n", argv[0]); + printf("Options:\n"); + printf(" -s SSL policy (default is basic)\n"); + printf(" -e allow expired cert\n"); + printf(" -E allow expired root\n"); + printf(" -S serverName\n"); + printf(" -t timeBaseString (default = now)\n"); + printf(" -T use SecTrustEvaluate\n"); + printf(" -v verbose\n"); + exit(1); +} + +static void printResult( + CSSM_RETURN crtn) +{ + switch(crtn) { + case CSSM_OK: + printf(" ...successful verification\n"); + break; + case CSSMERR_TP_INVALID_CERTIFICATE: + printf(" ...invalid leaf cert\n"); + break; + case CSSMERR_TP_INVALID_ANCHOR_CERT: + printf(" ...cert chain valid (unknown root)\n"); + break; + case CSSMERR_TP_NOT_TRUSTED: + printf(" ...no root cert found\n"); + break; + case CSSMERR_TP_VERIFICATION_FAILURE: + printf(" ...bad root cert\n"); + break; + case CSSMERR_TP_VERIFY_ACTION_FAILED: + printf(" ...policy verification failed\n"); + break; + case CSSMERR_TP_CERT_EXPIRED: + printf(" ...expired cert in chain\n"); + break; + case CSSMERR_TP_CERT_NOT_VALID_YET: + printf(" ...not-yet-valid cert in chain\n"); + break; + default: + printError("tpCertGroupVerify", crtn); + break; + } + +} +int main(int argc, char **argv) +{ + CSSM_CL_HANDLE clHand; // CL handle + CSSM_TP_HANDLE tpHand; // TP handle + CSSM_CSP_HANDLE cspHand = 0; // CSP handle + CSSM_DATA_PTR rawCerts = NULL; + unsigned numCerts; // num certs in *rawCerts + unsigned i; + CSSM_CERTGROUP cgrp; + const CSSM_OID *policyId = &CSSMOID_APPLE_X509_BASIC; + uint32 evidenceSize = 0; + CSSM_TP_VERIFY_CONTEXT_RESULT vfyResult; + CSSM_CERTGROUP_PTR outGrp = NULL; + int fileArg; + CSSM_RETURN crtn; + CSSM_BOOL allowExpiredCert = CSSM_FALSE; + bool allowExpiredRoot = false; + bool useSecTrust = false; + int arg; + CSSM_APPLE_TP_SSL_OPTIONS sslOpts; + CSSM_APPLE_TP_ACTION_DATA tpAction; + char *serverName = NULL; + bool verbose = false; + unsigned numEvidences = 0; + CSSM_DATA fieldOpts; + CSSM_DATA_PTR fieldOptsPtr = NULL; + CSSM_DATA actionData; + CSSM_DATA_PTR actionDataPtr = NULL; + char *cssmTimeStr = NULL; + SecTrustRef theTrust = NULL; + + if(argc < 2) { + usage(argv); + } + for(arg=1; argData, &len)) { + printf("Error reading %s=n", argv[fileArg]); + exit(1); + } + c->Length = len; + fileArg++; + } + + if(useSecTrust) { + SecPolicyRef policy = NULL; + SecPolicySearchRef policySearch = NULL; + SecCertificateRef cert; // only lives in CFArrayRefs + SecTrustResultType secTrustResult; + OSStatus ortn; + const char *evalResStr = NULL; + CSSM_TP_APPLE_EVIDENCE_INFO *evidence = NULL; + + /* convert raw certs to a CFArray of SecCertificateRefs */ + CFMutableArrayRef certGroup = CFArrayCreateMutable(NULL, numCerts, + &kCFTypeArrayCallBacks); + for(i=0; iData, actionDataPtr->Length); + + ortn = SecTrustSetParameters(theTrust, CSSM_TP_ACTION_DEFAULT, + actionData); + if(ortn) { + printf("SecTrustSetParameters returned %s\n", sslGetSSLErrString(ortn)); + exit(1); + } + CFRelease(actionData); + } + + /* + * Here we go; hand it over to SecTrust/TP. + */ + ortn = SecTrustEvaluate(theTrust, &secTrustResult); + if(ortn) { + printf("SecTrustEvaluate returned %s\n", sslGetSSLErrString(ortn)); + exit(1); + } + crtn = CSSM_OK; + switch(secTrustResult) { + case kSecTrustResultInvalid: + /* should never happen */ + evalResStr = "kSecTrustResultInvalid"; + break; + case kSecTrustResultProceed: + /* cert chain valid AND user explicitly trusts this */ + evalResStr = "kSecTrustResultProceed"; + break; + case kSecTrustResultConfirm: + /* + * Cert chain may well have verified OK, but user has flagged + * one of these certs as untrustable. + */ + evalResStr = "kSecTrustResultConfirm"; + break; + case kSecTrustResultDeny: + /* + * Cert chain may well have verified OK, but user has flagged + * one of these certs as untrustable. + */ + evalResStr = "kSecTrustResultDeny"; + break; + case kSecTrustResultUnspecified: + /* cert chain valid, no special UserTrust assignments */ + evalResStr = "kSecTrustResultUnspecified"; + break; + case kSecTrustResultRecoverableTrustFailure: + /* ? */ + evalResStr = "kSecTrustResultRecoverableTrustFailure"; + break; + case kSecTrustResultFatalTrustFailure: + /* ? */ + evalResStr = "kSecTrustResultFatalTrustFailure"; + break; + case kSecTrustResultOtherError: + /* ? */ + evalResStr = "kSecTrustResultOtherError"; + break; + default: + break; + } + printf("...SecTrustEvaluate result : "); + if(evalResStr != NULL) { + printf("%s\n", evalResStr); + } + else { + printf("UNKNOWN (%d)\n", (int)secTrustResult); + } + /* get low-level TP return code */ + OSStatus ocrtn; + ortn = SecTrustGetCssmResultCode(theTrust, &ocrtn); + if(ortn) { + printf("SecTrustGetCssmResultCode returned %s\n", sslGetSSLErrString(ortn)); + /*...keep going */ + } + else { + printResult(ocrtn); + } + CFArrayRef dummy; + ortn = SecTrustGetResult(theTrust, &secTrustResult, &dummy, + &evidence); + if(ortn) { + printf("SecTrustGetResult returned %s\n", sslGetSSLErrString(ortn)); + /*...keep going */ + } + else { + unsigned numEvidences = CFArrayGetCount(dummy); + if(numEvidences && verbose) { + printCertInfo(numEvidences, evidence); + } + } + } + else { + /* connect to CL, TP, and CSP */ + cspHand = cspStartup(); + if(cspHand == 0) { + exit(1); + } + /* subsequent errors to abort: */ + clHand = clStartup(); + if(clHand == 0) { + goto abort; + } + tpHand = tpStartup(); + if(tpHand == 0) { + goto abort; + } + + /* + * Cook up a cert group - TP wants leaf first + */ + memset(&cgrp, 0, sizeof(CSSM_CERTGROUP)); + cgrp.NumCerts = numCerts; + cgrp.CertGroupType = CSSM_CERTGROUP_DATA; + cgrp.CertType = CSSM_CERT_X_509v3; + cgrp.CertEncoding = CSSM_CERT_ENCODING_DER; + cgrp.GroupList.CertList = rawCerts; + + crtn = tpCertGroupVerify( + tpHand, + clHand, + cspHand, + NULL, // dbListPtr + policyId, + fieldOptsPtr, + actionDataPtr, + NULL, // policyOpts + &cgrp, + NULL, // anchorCerts + 0, // NumAnchorCerts + CSSM_TP_STOP_ON_POLICY, + cssmTimeStr, + &vfyResult); // verify result + printResult(crtn); + if((vfyResult.Evidence != NULL) && (vfyResult.Evidence->Evidence != NULL)) { + numEvidences = vfyResult.NumberOfEvidences; + if(numEvidences == 3) { + /* i.e., normal case */ + outGrp = (CSSM_CERTGROUP_PTR)vfyResult.Evidence[1].Evidence; + evidenceSize = outGrp->NumCerts; + } + else { + printf("***Expected numEvidences 3, got %u\n", numEvidences); + evidenceSize = 0; + } + } + printf(" num input certs %d; evidenceSize %u\n", + numCerts, (unsigned)evidenceSize); + if((numEvidences > 0) && verbose) { + dumpVfyResult(&vfyResult); + } + freeVfyResult(&vfyResult); + } + +abort: + if(rawCerts != NULL) { + /* mallocd by readFile() */ + for(i=0; i +#include + +/* Read a line from stdin into buffer as a null terminated string. If buffer is + non NULL use at most buffer_size bytes and return a pointer to buffer. Otherwise + return a newly malloced buffer. + if EOF is read this function returns NULL. */ +char * +readline(char *buffer, int buffer_size) +{ + int ix = 0, bytes_malloced = 0; + + if (!buffer) + { + bytes_malloced = 64; + buffer = (char *)malloc(bytes_malloced); + buffer_size = bytes_malloced; + } + + for (;;++ix) + { + int ch; + + if (ix == buffer_size - 1) + { + if (!bytes_malloced) + break; + bytes_malloced += bytes_malloced; + buffer = (char *)realloc(buffer, bytes_malloced); + buffer_size = bytes_malloced; + } + + ch = getchar(); + if (ch == EOF) + { + if (bytes_malloced) + free(buffer); + return NULL; + } + if (ch == '\n') + break; + buffer[ix] = ch; + } + + /* 0 terminate buffer. */ + buffer[ix] = '\0'; + + return buffer; +} + +void +print_buffer_hex(FILE *stream, UInt32 length, const void *data) +{ + unsigned i; + const unsigned char *cp = (const unsigned char *)data; + + printf("\n "); + for(i=0; i= ' ' && ch <= '~' && ch != '\\') + { + fputc(ch, stream); + } + else + { + fputc('\\', stream); + fputc('0' + ((ch >> 6) & 7), stream); + fputc('0' + ((ch >> 3) & 7), stream); + fputc('0' + ((ch >> 0) & 7), stream); + } + } +} + +void +print_buffer(FILE *stream, UInt32 length, const void *data) +{ + uint8 *p = (uint8 *) data; + Boolean ascii = TRUE; // unless we determine otherwise + UInt32 ix; + for (ix = 0; ix < length; ++ix) { + int ch = *p++; + if ((ch < ' ') || (ch > '~')) { + if((ch == 0) && (ix == (length - 1))) { + /* ignore trailing null */ + length--; + break; + } + ascii = FALSE; + break; + } + } + + if (ascii) { + fputc('"', stream); + print_buffer_ascii(stream, length, data); + fputc('"', stream); + } + else { + print_buffer_hex(stream, length, data); + } +} + +void +print_cfdata(FILE *stream, CFDataRef data) +{ + if (data) + return print_buffer(stream, CFDataGetLength(data), CFDataGetBytePtr(data)); + else + fprintf(stream, ""); +} + +void +print_cfstring(FILE *stream, CFStringRef string) +{ + if (!string) + fprintf(stream, ""); + else + { + const char *utf8 = CFStringGetCStringPtr(string, kCFStringEncodingUTF8); + if (utf8) + fprintf(stream, "%s", utf8); + else + { + CFRange rangeToProcess = CFRangeMake(0, CFStringGetLength(string)); + while (rangeToProcess.length > 0) + { + UInt8 localBuffer[256]; + CFIndex usedBufferLength; + CFIndex numChars = CFStringGetBytes(string, rangeToProcess, + kCFStringEncodingUTF8, '?', FALSE, localBuffer, + sizeof(localBuffer), &usedBufferLength); + if (numChars == 0) + break; // Failed to convert anything... + + fprintf(stream, "%.*s", (int)usedBufferLength, localBuffer); + rangeToProcess.location += numChars; + rangeToProcess.length -= numChars; + } + } + } +} + + +int +print_access(FILE *stream, SecAccessRef access, Boolean interactive) +{ + CFArrayRef aclList = NULL; + CFIndex aclix, aclCount; + int result = 0; + OSStatus status; + + status = SecAccessCopyACLList(access, &aclList); + if (status) + { + cssmPerror("SecAccessCopyACLList", status); + result = 1; + goto loser; + } + + aclCount = CFArrayGetCount(aclList); + fprintf(stream, "access: %lu entries\n", aclCount); + for (aclix = 0; aclix < aclCount; ++aclix) + { + CFArrayRef applicationList = NULL; + CFStringRef description = NULL; + CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector = {}; + CFIndex appix, appCount; + + SecACLRef acl = (SecACLRef)CFArrayGetValueAtIndex(aclList, aclix); + CSSM_ACL_AUTHORIZATION_TAG tags[64]; // Pick some upper limit + uint32 tagix, tagCount = sizeof(tags) / sizeof(*tags); + status = SecACLGetAuthorizations(acl, tags, &tagCount); + if (status) + { + cssmPerror("SecACLGetAuthorizations", status); + result = 1; + goto loser; + } + + fprintf(stream, " entry %lu:\n authorizations (%lu):", aclix, (unsigned long)tagCount); + for (tagix = 0; tagix < tagCount; ++tagix) + { + CSSM_ACL_AUTHORIZATION_TAG tag = tags[tagix]; + switch (tag) + { + case CSSM_ACL_AUTHORIZATION_ANY: + fputs(" any", stream); + break; + case CSSM_ACL_AUTHORIZATION_LOGIN: + fputs(" login", stream); + break; + case CSSM_ACL_AUTHORIZATION_GENKEY: + fputs(" genkey", stream); + break; + case CSSM_ACL_AUTHORIZATION_DELETE: + fputs(" delete", stream); + break; + case CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED: + fputs(" export_wrapped", stream); + break; + case CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR: + fputs(" export_clear", stream); + break; + case CSSM_ACL_AUTHORIZATION_IMPORT_WRAPPED: + fputs(" import_wrapped", stream); + break; + case CSSM_ACL_AUTHORIZATION_IMPORT_CLEAR: + fputs(" import_clear", stream); + break; + case CSSM_ACL_AUTHORIZATION_SIGN: + fputs(" sign", stream); + break; + case CSSM_ACL_AUTHORIZATION_ENCRYPT: + fputs(" encrypt", stream); + break; + case CSSM_ACL_AUTHORIZATION_DECRYPT: + fputs(" decrypt", stream); + break; + case CSSM_ACL_AUTHORIZATION_MAC: + fputs(" mac", stream); + break; + case CSSM_ACL_AUTHORIZATION_DERIVE: + fputs(" derive", stream); + break; + case CSSM_ACL_AUTHORIZATION_DBS_CREATE: + fputs(" dbs_create", stream); + break; + case CSSM_ACL_AUTHORIZATION_DBS_DELETE: + fputs(" dbs_delete", stream); + break; + case CSSM_ACL_AUTHORIZATION_DB_READ: + fputs(" db_read", stream); + break; + case CSSM_ACL_AUTHORIZATION_DB_INSERT: + fputs(" db_insert", stream); + break; + case CSSM_ACL_AUTHORIZATION_DB_MODIFY: + fputs(" db_modify", stream); + break; + case CSSM_ACL_AUTHORIZATION_DB_DELETE: + fputs(" db_delete", stream); + break; + case CSSM_ACL_AUTHORIZATION_CHANGE_ACL: + fputs(" change_acl", stream); + break; + case CSSM_ACL_AUTHORIZATION_CHANGE_OWNER: + fputs(" change_owner", stream); + break; + default: + fprintf(stream, " tag=%lu", (unsigned long)tag); + break; + } + } + fputc('\n', stream); + + status = SecACLCopySimpleContents(acl, &applicationList, &description, &promptSelector); + if (status) + { + cssmPerror("SecACLCopySimpleContents", status); + continue; + } + + if (promptSelector.flags & CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE) + fputs(" require-password\n", stream); + else + fputs(" don't-require-password\n", stream); + + fputs(" description: ", stream); + print_cfstring(stream, description); + fputc('\n', stream); + + if (applicationList) + { + appCount = CFArrayGetCount(applicationList); + fprintf(stream, " applications (%lu):\n", appCount); + } + else + { + appCount = 0; + fprintf(stream, " applications: \n"); + } + + for (appix = 0; appix < appCount; ++appix) + { + const UInt8* bytes; + SecTrustedApplicationRef app = (SecTrustedApplicationRef)CFArrayGetValueAtIndex(applicationList, appix); + CFDataRef data = NULL; + fprintf(stream, " %lu: ", appix); + status = SecTrustedApplicationCopyData(app, &data); + if (status) + { + cssmPerror("SecTrustedApplicationCopyData", status); + continue; + } + + bytes = CFDataGetBytePtr(data); + if (bytes && bytes[0] == 0x2f) { + fprintf(stream, "%s", (const char *)bytes); + if ((status = SecTrustedApplicationValidateWithPath(app, (const char *)bytes)) == noErr) { + fprintf(stream, " (OK)"); + } else { + fprintf(stream, " (status %ld)", status); + } + fprintf(stream, "\n"); + } else { + print_cfdata(stream, data); + fputc('\n', stream); + } + if (data) + CFRelease(data); + } + + + if (interactive) + { + char buffer[10] = {}; + if(applicationList != NULL) { + fprintf(stderr, "NULL out this application list? "); + if (readline(buffer, sizeof(buffer)) && buffer[0] == 'y') + { + /* + * This makes the ops in this entry wide-open, no dialog or confirmation + * other than requiring the keychain be open. + */ + fprintf(stderr, "setting app list to NULL\n"); + status = SecACLSetSimpleContents(acl, NULL, description, &promptSelector); + if (status) + { + cssmPerror("SecACLSetSimpleContents", status); + continue; + } + } + else { + fprintf(stderr, "Set this application list to empty array? "); + if (readline(buffer, sizeof(buffer)) && buffer[0] == 'y') + { + /* + * This means "always get confirmation, from all apps". + */ + fprintf(stderr, "setting app list to empty array\n"); + status = SecACLSetSimpleContents(acl, + CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks), + description, &promptSelector); + if (status) + { + cssmPerror("SecACLSetSimpleContents", status); + continue; + } + } + } + } + else { + fprintf(stderr, "Remove this acl? "); + if (readline(buffer, sizeof(buffer)) && buffer[0] == 'y') + { + /* + * This make ths ops in this entry completely inaccessible. + */ + fprintf(stderr, "removing acl\n"); + status = SecACLRemove(acl); + if (status) + { + cssmPerror("SecACLRemove", status); + continue; + } + } + } + } + if (description) + CFRelease(description); + if (applicationList) + CFRelease(applicationList); + + } + +loser: + if (aclList) + CFRelease(aclList); + + return result; +} + +/* Simluate what StickyRecord is trying to do.... */ + +/* + * Given an Access object: + * -- extract the ACL for the specified CSSM_ACL_AUTHORIZATION_TAG. We expect there + * to exactly one of these - if the form of a default ACL changes we'll have to + * revisit this. + * -- set the ACL's app list to the provided CFArray, which may be NULL (meaning + * "any app can access this, no problem"), an empty array (meaning "always + * prompt"), or an actual app list. + * -- set or clear the PROMPT_REQUIRE_PASSPHRASE bit per the requirePassphrase + * argument + */ +static OSStatus srUpdateAcl( + SecAccessRef accessRef, + CSSM_ACL_AUTHORIZATION_TAG whichAcl, // e.g. CSSM_ACL_AUTHORIZATION_DECRYPT + CFArrayRef appArray, + bool requirePassphrase) +{ + OSStatus ortn; + CFArrayRef aclList = NULL; + + ortn = SecAccessCopySelectedACLList(accessRef, whichAcl, &aclList); + if(ortn) { + cssmPerror("SecAccessCopySelectedACLList", ortn); + return ortn; + } + + if(CFArrayGetCount(aclList) != 1) { + printf("StickyRecord::updateAcl - unexpected ACL list count (%d)", + (int)CFArrayGetCount(aclList)); + return internalComponentErr; + } + SecACLRef acl = (SecACLRef)CFArrayGetValueAtIndex(aclList, 0); + + CFArrayRef applicationList = NULL; + CFStringRef description = NULL; + CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector = {}; + ortn = SecACLCopySimpleContents(acl, &applicationList, &description, &promptSelector); + if(ortn) { + cssmPerror("SecACLCopySimpleContents", ortn); + return ortn; + } + if(applicationList != NULL) { + CFRelease(applicationList); + } + if(requirePassphrase) { + promptSelector.flags |= CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE; + } + else { + promptSelector.flags &= ~CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE; + } + /* update */ + ortn = SecACLSetSimpleContents(acl, appArray, description, &promptSelector); + + /* we got this from SecACLCopySimpleContents - release it regardless */ + if(description != NULL) { + CFRelease(description); + } + if(ortn) { + cssmPerror("SecACLSetSimpleContents", ortn); + } + if(aclList != NULL) { + CFRelease(aclList); + } + return ortn; +} + +OSStatus stickyRecordUpdateAcl( + SecAccessRef accessRef) +{ + OSStatus ortn; + + printf("...updating ACL to simulate a StickyRecord\n"); + + /* First: decrypt. Wide open (NULL app list), !REQUIRE_PASSPHRASE. */ + ortn = srUpdateAcl(accessRef, CSSM_ACL_AUTHORIZATION_DECRYPT, NULL, false); + if(ortn) { + return ortn; + } + + /* encrypt: always ask (empty app list, require passphrase */ + CFArrayRef nullArray = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); + return srUpdateAcl(accessRef, CSSM_ACL_AUTHORIZATION_ENCRYPT, nullArray, true); + +} diff --git a/SecurityTests/cspxutils/acltool/aclUtils.h b/SecurityTests/cspxutils/acltool/aclUtils.h new file mode 100644 index 00000000..ef0970e7 --- /dev/null +++ b/SecurityTests/cspxutils/acltool/aclUtils.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2004-2005 Apple Computer, 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@ + */ + +/* + * aclUtils.h - ACL utility functions, copied from the SecurityTool project. + */ + +#ifndef _ACL_UTILS_H_ +#define _ACL_UTILS_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +char *readline(char *buffer, int buffer_size); +void print_buffer_hex(FILE *stream, UInt32 length, const void *data); +void print_buffer_ascii(FILE *stream, UInt32 length, const void *data); +void print_buffer(FILE *stream, UInt32 length, const void *data); +void print_cfdata(FILE *stream, CFDataRef data); +void print_cfstring(FILE *stream, CFStringRef string); +int print_access(FILE *stream, SecAccessRef access, Boolean interactive); + +OSStatus stickyRecordUpdateAcl( + SecAccessRef accessRef); + +#ifdef __cplusplus +} +#endif + +#endif /* _ACL_UTILS_H_ */ + diff --git a/SecurityTests/cspxutils/acltool/acltool.cpp b/SecurityTests/cspxutils/acltool/acltool.cpp new file mode 100644 index 00000000..9c6a5d69 --- /dev/null +++ b/SecurityTests/cspxutils/acltool/acltool.cpp @@ -0,0 +1,327 @@ +/* + * acltool.cpp - display and manipluate ACLs on SecKeychainItems + */ + +#include +#include +#include +#include +#include +#include "aclUtils.h" + +static void usage(char **argv) +{ + printf("usage: %s op [options]\n", argv[0]); + printf("op:\n"); + printf(" d -- display ACL\n"); + printf(" a -- add ACL\n"); + printf(" l -- lookup, dump label; no ACL operation\n"); + printf(" m -- modify data (only allowed for password items; must specify -p)\n"); + printf("Options:\n"); + printf(" -k keychain\n"); + printf(" -t itemType : k=privateKey, b=publicKey s=sessionKey, p=password; default is sessionKey\n"); + printf(" -l label_or_printName\n"); + printf(" -p new_password_data\n"); + printf(" -d -- dump data\n"); + printf(" -e -- edit ACL entries\n"); + printf(" -s -- simulate StickyRecord ACL\n"); + /* etc. */ + exit(1); +} + + +/* print an item's label and (optionally) its data */ +static OSStatus printItemLabelAndData( + SecKeychainItemRef itemRef, + SecItemAttr labelAttr, + bool dumpData) +{ + SecKeychainAttributeList attrList; + SecKeychainAttribute attr; + UInt32 length = 0; + void *outData = NULL; + + attr.tag = labelAttr; + attr.length = 0; + attr.data = NULL; + attrList.count = 1; + attrList.attr = &attr; + + OSStatus ortn = SecKeychainItemCopyContent(itemRef, + NULL, // itemClass - we know + &attrList, // for label + dumpData ? &length : 0, + dumpData ? &outData : NULL); + if(ortn) { + cssmPerror("SecKeychainItemCopyContent", ortn); + printf("***Error fetching label %s\n", dumpData ? "and data" : ""); + return ortn; + } + + if(attr.data == NULL) { + printf("**No label attribute found\n"); + } + else { + printf("Label: "); + print_buffer(stdout, attr.length, attr.data); + printf("\n"); + } + if(dumpData) { + if(outData == NULL) { + printf("***Asked for data but none found\n"); + } + else { + printf("Data : "); + print_buffer(stdout, length, outData); + printf("\n"); + } + } + SecKeychainItemFreeContent(&attrList, outData); + return noErr; +} + +/* + * Lookup by itemClass and optional label. Then do one or more of: + * + * -- dump label (always done) + * -- dump ACLs + * -- edit acl + * -- dump data + * -- set (modify) data + */ +static OSStatus dumpAcls( + SecKeychainRef kcRef, + + /* item specification */ + SecItemClass itemClass, + SecItemAttr labelAttr, // to look up by label if specified + const char *label, + + /* what we do with the item(s) found */ + bool dumpData, + bool dumpAcl, + bool editAcl, + bool simulateStickyRecord, + const unsigned char *newData, // if non-NULL, set/modify new data + unsigned newDataLen) +{ + OSStatus ortn; + SecKeychainSearchRef srchRef; + SecKeychainAttributeList attrList; + SecKeychainAttributeList *attrListP = NULL; + SecKeychainAttribute attr; + unsigned numFound = 0; + + /* searching by label, or blindly? */ + if(label) { + attr.tag = labelAttr; + attr.length = strlen(label); + attr.data = (void *)label; + attrList.count = 1; + attrList.attr = &attr; + attrListP = &attrList; + } + ortn = SecKeychainSearchCreateFromAttributes(kcRef, + itemClass, + attrListP, + &srchRef); + if(ortn) { + cssmPerror("SecKeychainSearchCreateFromAttributes", ortn); + return ortn; + } + for(;;) { + SecKeychainItemRef itemRef; + ortn = SecKeychainSearchCopyNext(srchRef, &itemRef); + if(ortn) { + if(ortn == errSecItemNotFound) { + /* normal search end */ + ortn = noErr; + } + else { + cssmPerror("SecKeychainSearchCopyNext", ortn); + } + break; + } + + printf("Item %u:\n", numFound++); + printItemLabelAndData(itemRef, labelAttr, dumpData); + + if(newData) { + ortn = SecKeychainItemModifyAttributesAndData(itemRef, + NULL, // attrList - we don't change any attrs + newDataLen, + newData); + if(ortn) { + cssmPerror("SecKeychainItemModifyAttributesAndData", ortn); + printf("***Cannot modify data of this item***\n"); + goto endOfLoop; + } + } + if(dumpAcl) { + SecAccessRef accessRef = nil; + ortn = SecKeychainItemCopyAccess(itemRef, &accessRef); + if(ortn) { + cssmPerror("SecKeychainItemCopyAccess", ortn); + printf("***No SecAccessRef found***\n"); + goto endOfLoop; + } + print_access(stdout, accessRef, editAcl); + if(simulateStickyRecord) { + ortn = stickyRecordUpdateAcl(accessRef); + if(ortn) { + goto endOfLoop; + } + } + if(editAcl || simulateStickyRecord) { + ortn = SecKeychainItemSetAccess(itemRef, accessRef); + if(ortn) { + cssmPerror("SecKeychainItemSetAccess", ortn); + } + } + } +endOfLoop: + CFRelease(itemRef); + if(ortn) { + break; + } + } + CFRelease(srchRef); + printf("...%u items found\n", numFound); + return ortn; +} + +typedef enum { + AO_Dump, + AO_Add, + AO_Lookup, + AO_ModifyPassword +} AclOp; + +int main(int argc, char **argv) +{ + /* user spec'd variables */ + const char *kcName = NULL; + const char *labelOrName = NULL; // attribute type varies per + AclOp op = AO_Dump; + SecItemClass itemClass = CSSM_DL_DB_RECORD_SYMMETRIC_KEY; + /* FIXME why does this work like this for keys? doc says kSecKeyPrintName but that doesn't work */ + SecItemAttr labelAttr = kSecLabelItemAttr; + bool dumpData = false; + bool editAcl = false; + bool dumpAcl = true; + bool simulateStickyRecord = false; + const char *newPassword = NULL; + unsigned newPasswordLen = 0; + + SecKeychainRef kcRef = nil; + OSStatus ortn; + + if(argc < 2) { + usage(argv); + } + switch(argv[1][0]) { + case 'd': + op = AO_Dump; + break; + case 'a': + op = AO_Add; + break; + case 'l': + op = AO_Lookup; + dumpAcl = false; + break; + case 'm': + op = AO_ModifyPassword; + dumpAcl = false; + break; + default: + usage(argv); + } + + extern char *optarg; + int arg; + extern int optind; + optind = 2; + while ((arg = getopt(argc, argv, "k:t:l:dep:sh")) != -1) { + switch (arg) { + case 'k': + kcName = optarg; + break; + case 't': + switch(optarg[0]) { + case 'k': + itemClass = CSSM_DL_DB_RECORD_PRIVATE_KEY; + break; + case 's': + itemClass = CSSM_DL_DB_RECORD_SYMMETRIC_KEY; + break; + case 'b': + itemClass = CSSM_DL_DB_RECORD_PUBLIC_KEY; + break; + case 'p': + itemClass = kSecGenericPasswordItemClass; + labelAttr = kSecLabelItemAttr; + break; + default: + usage(argv); + } + break; + case 'l': + labelOrName = optarg; + break; + case 'd': + dumpData = true; + break; + case 'e': + editAcl = true; + break; + case 'p': + newPassword = optarg; + newPasswordLen = strlen(newPassword); + break; + case 's': + simulateStickyRecord = true; + break; + case 'h': + usage(argv); + } + } + if(optind != argc) { + usage(argv); + } + if(op == AO_ModifyPassword) { + if(itemClass != kSecGenericPasswordItemClass) { + printf("***You can only modify data on a password item.\n"); + exit(1); + } + if(newPassword == NULL) { + printf("***You must supply new password data for this operation.\n"); + exit(1); + } + } + if(kcName) { + ortn = SecKeychainOpen(kcName, &kcRef); + if(ortn) { + cssmPerror("SecKeychainOpen", ortn); + printf("***Error opening keychain %s. Aborting.\n", kcName); + exit(1); + } + } + + switch(op) { + case AO_Dump: + case AO_Lookup: + case AO_ModifyPassword: + ortn = dumpAcls(kcRef, itemClass, labelAttr, labelOrName, dumpData, dumpAcl, editAcl, + simulateStickyRecord, (unsigned char *)newPassword, newPasswordLen); + break; + case AO_Add: + printf("Add ACL op to be implemented real soon now\n"); + ortn = -1; + break; + } + if(kcRef) { + CFRelease(kcRef); + } + return (int)ortn; +} diff --git a/SecurityTests/cspxutils/aesVect/Makefile b/SecurityTests/cspxutils/aesVect/Makefile new file mode 100644 index 00000000..0b310023 --- /dev/null +++ b/SecurityTests/cspxutils/aesVect/Makefile @@ -0,0 +1,57 @@ +# name of executable to build +EXECUTABLE= aesVect +# C++ source (with .cpp extension) +CPSOURCE= +# C source (.c extension) +#CSOURCE= aesVect.c _rijndael-alg-ref.c _rijndaelApi.c enDecryptRef.c enDecryptTest.c \ +# enDecryptCsp.c rijndael.c +CSOURCE= aesVect.c enDecryptRef.c enDecryptTest.c enDecryptCsp.c rijndael.c + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +#PROJ_CFLAGS= -F/System/Library/PrivateFrameworks +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/aesVect/aesVect.c b/SecurityTests/cspxutils/aesVect/aesVect.c new file mode 100644 index 00000000..53933ebc --- /dev/null +++ b/SecurityTests/cspxutils/aesVect/aesVect.c @@ -0,0 +1,179 @@ +/* + * aesVect.c - generate NIST-compatible test vectors for various AES implementations. + * + * Written by Doug Mitchell. + */ + +#include +#include +#include +#include "enDecrypt.h" +#include "rijndael-alg-ref.h" +#include + +static void usage(char **argv) +{ + printf("usage: %s r|t|c vectorStyle [options]\n", argv[0]); + printf("r=reference t=testImple c=CSP\n"); + printf("vectorStyle:\n"); + printf(" k Variable key KAT\n"); + printf(" p Variable plaintext KAT\n"); + printf("options:\n"); + printf(" k=keySizeInBits (default = 128)\n"); + printf(" i=max value of i (default = max per context)\n"); + printf(" h(elp)\n"); + exit(1); +} + +static void setBit( + unsigned char *val, + unsigned valBytes, + unsigned i) +{ + unsigned whichByte; + unsigned whichBit; + + i--; + whichByte = i / 8; + whichBit = 7 - (i % 8); + memset(val, 0, valBytes); + val[whichByte] = 1 << whichBit; +} + +static void printBigNum( + const char *name, + unsigned char *val, + unsigned valBytes) +{ + unsigned i; + printf("%s=", name); + for(i=0; i +#include + +/* + * encrypt/decrypt using test implementation. + */ +CSSM_RETURN encryptDecryptTest( + CSSM_BOOL forEncrypt, + uint32 keyBits, + uint32 blockSizeInBits, + const uint8 *key, // raw key bytes + const uint8 *inText, + uint32 inTextLen, // in bytes + uint8 *outText); + +/* + * encrypt/decrypt using reference AES. + */ +CSSM_RETURN encryptDecryptRef( + CSSM_BOOL forEncrypt, + uint32 keyBits, + uint32 blockSizeInBits, + const uint8 *key, // raw key bytes + const uint8 *inText, + uint32 inTextLen, // in bytes + uint8 *outText); + +/* + * encrypt/decrypt using CSP. + */ +CSSM_RETURN encryptDecryptCsp( + CSSM_BOOL forEncrypt, + uint32 keyBits, + uint32 blockSizeInBits, + const uint8 *key, // raw key bytes + const uint8 *inText, + uint32 inTextLen, // in bytes + uint8 *outText); + +typedef CSSM_RETURN (*encrDecrFcn) ( + CSSM_BOOL forEncrypt, + uint32 keyBits, + uint32 blockSizeInBits, + const uint8 *key, // raw key bytes + const uint8 *inText, + uint32 inTextLen, // in bytes + uint8 *outText); diff --git a/SecurityTests/cspxutils/aesVect/enDecryptCsp.c b/SecurityTests/cspxutils/aesVect/enDecryptCsp.c new file mode 100644 index 00000000..5f44a6f9 --- /dev/null +++ b/SecurityTests/cspxutils/aesVect/enDecryptCsp.c @@ -0,0 +1,84 @@ +/* + * encrypt/decrypt using CSP implementation of AES. + */ +#include "enDecrypt.h" +#include +#include "cspwrap.h" +#include "common.h" +#include + +static CSSM_CSP_HANDLE cspHand = 0; + +CSSM_RETURN encryptDecryptCsp( + CSSM_BOOL forEncrypt, + uint32 keySizeInBits, + uint32 blockSizeInBits, + const uint8 *key, // raw key bytes + const uint8 *inText, + uint32 inTextLen, + uint8 *outText) +{ + CSSM_KEY_PTR symKey; // mallocd by cspGenSymKey or a ptr + // to refKey + CSSM_RETURN crtn; + CSSM_DATA inData; + CSSM_DATA outData; + + if(cspHand == 0) { + /* attach first time thru */ + cspHand = cspDlDbStartup(CSSM_TRUE, NULL); + if(cspHand == 0) { + return CSSMERR_CSSM_MODULE_NOT_LOADED; + } + } + + /* cook up a raw symmetric key */ + symKey = cspGenSymKey(cspHand, + CSSM_ALGID_AES, + "noLabel", + 8, + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + keySizeInBits, + CSSM_FALSE); // ref key + if(symKey == NULL) { + return CSSM_ERRCODE_INTERNAL_ERROR; + } + memmove(symKey->KeyData.Data, key, keySizeInBits / 8); + + inData.Data = (uint8 *)inText; + inData.Length = inTextLen; + outData.Data = outText; + outData.Length = inTextLen; + + if(forEncrypt) { + crtn = cspEncrypt(cspHand, + CSSM_ALGID_AES, + CSSM_ALGMODE_ECB, + CSSM_PADDING_NONE, + symKey, + NULL, // no second key + 0, // effectiveKeyBits + 0, // rounds + NULL, // iv + &inData, + &outData, + CSSM_FALSE); // mallocCtext + } + else { + crtn = cspDecrypt(cspHand, + CSSM_ALGID_AES, + CSSM_ALGMODE_ECB, + CSSM_PADDING_NONE, + symKey, + NULL, // no second key + 0, // effectiveKeyBits + 0, // rounds + NULL, // iv + &inData, + &outData, + CSSM_FALSE); // mallocPtext + } + cspFreeKey(cspHand, symKey); + return crtn; + +} diff --git a/SecurityTests/cspxutils/aesVect/enDecryptRef.c b/SecurityTests/cspxutils/aesVect/enDecryptRef.c new file mode 100644 index 00000000..5f91b127 --- /dev/null +++ b/SecurityTests/cspxutils/aesVect/enDecryptRef.c @@ -0,0 +1,56 @@ +#include "enDecrypt.h" +#include "rijndaelApi.h" /* reference */ + +/* + * encrypt/decrypt using reference AES. + */ +CSSM_RETURN encryptDecryptRef( + CSSM_BOOL forEncrypt, + uint32 keySizeInBits, + uint32 blockSizeInBits, + const uint8 *key, // raw key bytes + const uint8 *inText, + uint32 inTextLen, + uint8 *outText) +{ + keyInstance aesKey; + cipherInstance aesCipher; + int artn; + + artn = _makeKey(&aesKey, + forEncrypt ? DIR_ENCRYPT : DIR_DECRYPT, + keySizeInBits, + blockSizeInBits, + (BYTE *)key); + if(artn <= 0) { + printf("***AES makeKey returned %d\n", artn); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + artn = _cipherInit(&aesCipher, + MODE_ECB, + blockSizeInBits, + NULL); + if(artn <= 0) { + printf("***AES cipherInit returned %d\n", artn); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + if(forEncrypt) { + artn = _blockEncrypt(&aesCipher, + &aesKey, + (BYTE *)inText, + inTextLen * 8, + (BYTE *)outText); + } + else { + artn = _blockDecrypt(&aesCipher, + &aesKey, + (BYTE *)inText, + inTextLen * 8, + (BYTE *)outText); + } + if(artn <= 0) { + printf("***AES Reference encrypt/decrypt returned %d\n", artn); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + return CSSM_OK; +} diff --git a/SecurityTests/cspxutils/aesVect/enDecryptTest.c b/SecurityTests/cspxutils/aesVect/enDecryptTest.c new file mode 100644 index 00000000..ccbcd90d --- /dev/null +++ b/SecurityTests/cspxutils/aesVect/enDecryptTest.c @@ -0,0 +1,42 @@ +#include "enDecrypt.h" +#include "std_defs.h" +#include +#include + +/* + * encrypt/decrypt using Gladman version of AES. + */ + +CSSM_RETURN encryptDecryptTest( + CSSM_BOOL forEncrypt, + uint32 keySizeInBits, + uint32 blockSizeInBits, + const uint8 *key, // raw key bytes + const uint8 *inText, + uint32 inTextLen, + uint8 *outText) +{ + u4byte aesKey[8]; + uint8 *inPtr = (uint8 *)inText; + uint8 *outPtr = outText; + uint32 blockSizeInBytes = blockSizeInBits / 8; + uint32 blocks = inTextLen / blockSizeInBytes; + + if(blockSizeInBits != 128) { + printf("***This AES implementation supports only 128 bit blocks.\n"); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + memmove(aesKey, key, keySizeInBits / 8); + set_key(aesKey, keySizeInBits); + for( ; blocks > 0; blocks--) { + if(forEncrypt) { + rEncrypt((u4byte *)inPtr, (u4byte *)outPtr); + } + else { + rDecrypt((u4byte *)inPtr, (u4byte *)outPtr); + } + inPtr += blockSizeInBytes; + outPtr += blockSizeInBytes; + } + return CSSM_OK; +} diff --git a/SecurityTests/cspxutils/aesVect/makeVectors b/SecurityTests/cspxutils/aesVect/makeVectors new file mode 100755 index 00000000..cdb5ceb5 --- /dev/null +++ b/SecurityTests/cspxutils/aesVect/makeVectors @@ -0,0 +1,31 @@ +#! /bin/csh -f +# +# Create an AES vector text file, using aesVect, which will be compared against +# ecb_vk.txt or ecb_vt.txt. +# +# usage: makeVectors r|t vectorStyle headerFile outFile +# +if ( $#argv != 4 ) then + echo Usage: makeVectors r\|t vectorStyle headerFile outFile + exit(1) +endif +# +# start with header +# +set outFile=$argv[4] +set separator="==========" + +cat $argv[3] > $outFile +# +# run thru all three key sizes +# +aesVect $argv[1] $argv[2] k=128 >> $outFile +echo $separator >> $outFile +echo "" >> $outFile +aesVect $argv[1] $argv[2] k=192 >> $outFile +echo $separator >> $outFile +echo "" >> $outFile +aesVect $argv[1] $argv[2] k=256 >> $outFile +echo $separator >> $outFile + + diff --git a/SecurityTests/cspxutils/aesVect/rijndael.c b/SecurityTests/cspxutils/aesVect/rijndael.c new file mode 100644 index 00000000..f953beda --- /dev/null +++ b/SecurityTests/cspxutils/aesVect/rijndael.c @@ -0,0 +1,427 @@ + + + +/* This is an independent implementation of the encryption algorithm: */ +/* */ +/* RIJNDAEL by Joan Daemen and Vincent Rijmen */ +/* */ +/* which is a candidate algorithm in the Advanced Encryption Standard */ +/* programme of the US National Institute of Standards and Technology. */ +/* */ +/* Copyright in this implementation is held by Dr B R Gladman but I */ +/* hereby give permission for its free direct or derivative use subject */ +/* to acknowledgment of its origin and compliance with any conditions */ +/* that the originators of the algorithm place on its exploitation. */ +/* */ +/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 */ + +/* Timing data for Rijndael (rijndael.c) + +Algorithm: rijndael (rijndael.c) + +128 bit key: +Key Setup: 305/1389 cycles (encrypt/decrypt) +Encrypt: 374 cycles = 68.4 mbits/sec +Decrypt: 352 cycles = 72.7 mbits/sec +Mean: 363 cycles = 70.5 mbits/sec + +192 bit key: +Key Setup: 277/1595 cycles (encrypt/decrypt) +Encrypt: 439 cycles = 58.3 mbits/sec +Decrypt: 425 cycles = 60.2 mbits/sec +Mean: 432 cycles = 59.3 mbits/sec + +256 bit key: +Key Setup: 374/1960 cycles (encrypt/decrypt) +Encrypt: 502 cycles = 51.0 mbits/sec +Decrypt: 498 cycles = 51.4 mbits/sec +Mean: 500 cycles = 51.2 mbits/sec + +*/ + +#include "std_defs.h" + +/* enable of block/word/byte swapping macros */ +#define USE_SWAP_MACROS 1 + +static char *alg_name[] = { (char *)"rijndael", (char *)"rijndael.c", (char *)"rijndael" }; + +char **cipher_name() +{ + return alg_name; +} + +#define LARGE_TABLES + +u1byte pow_tab[256]; +u1byte log_tab[256]; +u1byte sbx_tab[256]; +u1byte isb_tab[256]; +u4byte rco_tab[ 10]; +u4byte ft_tab[4][256]; +u4byte it_tab[4][256]; + +#ifdef LARGE_TABLES + u4byte fl_tab[4][256]; + u4byte il_tab[4][256]; +#endif + +u4byte tab_gen = 0; + +u4byte k_len; +u4byte e_key[64]; +u4byte d_key[64]; + +#define ff_mult(a,b) (a && b ? pow_tab[(log_tab[a] + log_tab[b]) % 255] : 0) + +#define f_rn(bo, bi, n, k) \ + bo[n] = ft_tab[0][byte(bi[n],0)] ^ \ + ft_tab[1][byte(bi[(n + 1) & 3],1)] ^ \ + ft_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n) + +#define i_rn(bo, bi, n, k) \ + bo[n] = it_tab[0][byte(bi[n],0)] ^ \ + it_tab[1][byte(bi[(n + 3) & 3],1)] ^ \ + it_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n) + +#ifdef LARGE_TABLES + +#define ls_box(x) \ + ( fl_tab[0][byte(x, 0)] ^ \ + fl_tab[1][byte(x, 1)] ^ \ + fl_tab[2][byte(x, 2)] ^ \ + fl_tab[3][byte(x, 3)] ) + +#define f_rl(bo, bi, n, k) \ + bo[n] = fl_tab[0][byte(bi[n],0)] ^ \ + fl_tab[1][byte(bi[(n + 1) & 3],1)] ^ \ + fl_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n) + +#define i_rl(bo, bi, n, k) \ + bo[n] = il_tab[0][byte(bi[n],0)] ^ \ + il_tab[1][byte(bi[(n + 3) & 3],1)] ^ \ + il_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n) + +#else + +#define ls_box(x) \ + ((u4byte)sbx_tab[byte(x, 0)] << 0) ^ \ + ((u4byte)sbx_tab[byte(x, 1)] << 8) ^ \ + ((u4byte)sbx_tab[byte(x, 2)] << 16) ^ \ + ((u4byte)sbx_tab[byte(x, 3)] << 24) + +#define f_rl(bo, bi, n, k) \ + bo[n] = (u4byte)sbx_tab[byte(bi[n],0)] ^ \ + rotl(((u4byte)sbx_tab[byte(bi[(n + 1) & 3],1)]), 8) ^ \ + rotl(((u4byte)sbx_tab[byte(bi[(n + 2) & 3],2)]), 16) ^ \ + rotl(((u4byte)sbx_tab[byte(bi[(n + 3) & 3],3)]), 24) ^ *(k + n) + +#define i_rl(bo, bi, n, k) \ + bo[n] = (u4byte)isb_tab[byte(bi[n],0)] ^ \ + rotl(((u4byte)isb_tab[byte(bi[(n + 3) & 3],1)]), 8) ^ \ + rotl(((u4byte)isb_tab[byte(bi[(n + 2) & 3],2)]), 16) ^ \ + rotl(((u4byte)isb_tab[byte(bi[(n + 1) & 3],3)]), 24) ^ *(k + n) + +#endif + +void gen_tabs(void) +{ u4byte i, t; + u1byte p, q; + + /* log and power tables for GF(2**8) finite field with */ + /* 0x11b as modular polynomial - the simplest prmitive */ + /* root is 0x11, used here to generate the tables */ + + for(i = 0,p = 1; i < 256; ++i) + { + pow_tab[i] = (u1byte)p; log_tab[p] = (u1byte)i; + + p = p ^ (p << 1) ^ (p & 0x80 ? 0x01b : 0); + } + + log_tab[1] = 0; p = 1; + + for(i = 0; i < 10; ++i) + { + rco_tab[i] = p; + + p = (p << 1) ^ (p & 0x80 ? 0x1b : 0); + } + + /* note that the affine byte transformation matrix in */ + /* rijndael specification is in big endian format with */ + /* bit 0 as the most significant bit. In the remainder */ + /* of the specification the bits are numbered from the */ + /* least significant end of a byte. */ + + for(i = 0; i < 256; ++i) + { + p = (i ? pow_tab[255 - log_tab[i]] : 0); q = p; + q = (q >> 7) | (q << 1); p ^= q; + q = (q >> 7) | (q << 1); p ^= q; + q = (q >> 7) | (q << 1); p ^= q; + q = (q >> 7) | (q << 1); p ^= q ^ 0x63; + sbx_tab[i] = (u1byte)p; isb_tab[p] = (u1byte)i; + } + + for(i = 0; i < 256; ++i) + { + p = sbx_tab[i]; + +#ifdef LARGE_TABLES + + t = p; fl_tab[0][i] = t; + fl_tab[1][i] = rotl(t, 8); + fl_tab[2][i] = rotl(t, 16); + fl_tab[3][i] = rotl(t, 24); +#endif + t = ((u4byte)ff_mult(2, p)) | + ((u4byte)p << 8) | + ((u4byte)p << 16) | + ((u4byte)ff_mult(3, p) << 24); + + ft_tab[0][i] = t; + ft_tab[1][i] = rotl(t, 8); + ft_tab[2][i] = rotl(t, 16); + ft_tab[3][i] = rotl(t, 24); + + p = isb_tab[i]; + +#ifdef LARGE_TABLES + + t = p; il_tab[0][i] = t; + il_tab[1][i] = rotl(t, 8); + il_tab[2][i] = rotl(t, 16); + il_tab[3][i] = rotl(t, 24); +#endif + t = ((u4byte)ff_mult(14, p)) | + ((u4byte)ff_mult( 9, p) << 8) | + ((u4byte)ff_mult(13, p) << 16) | + ((u4byte)ff_mult(11, p) << 24); + + it_tab[0][i] = t; + it_tab[1][i] = rotl(t, 8); + it_tab[2][i] = rotl(t, 16); + it_tab[3][i] = rotl(t, 24); + } + + tab_gen = 1; +}; + +#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b) + +#define imix_col(y,x) \ + u = star_x(x); \ + v = star_x(u); \ + w = star_x(v); \ + t = w ^ (x); \ + (y) = u ^ v ^ w; \ + (y) ^= rotr(u ^ t, 8) ^ \ + rotr(v ^ t, 16) ^ \ + rotr(t,24) + +/* initialise the key schedule from the user supplied key */ + +#define loop4(i) \ +{ t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \ + t ^= e_key[4 * i]; e_key[4 * i + 4] = t; \ + t ^= e_key[4 * i + 1]; e_key[4 * i + 5] = t; \ + t ^= e_key[4 * i + 2]; e_key[4 * i + 6] = t; \ + t ^= e_key[4 * i + 3]; e_key[4 * i + 7] = t; \ +} + +#define loop6(i) \ +{ t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \ + t ^= e_key[6 * i]; e_key[6 * i + 6] = t; \ + t ^= e_key[6 * i + 1]; e_key[6 * i + 7] = t; \ + t ^= e_key[6 * i + 2]; e_key[6 * i + 8] = t; \ + t ^= e_key[6 * i + 3]; e_key[6 * i + 9] = t; \ + t ^= e_key[6 * i + 4]; e_key[6 * i + 10] = t; \ + t ^= e_key[6 * i + 5]; e_key[6 * i + 11] = t; \ +} + +#define loop8(i) \ +{ t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \ + t ^= e_key[8 * i]; e_key[8 * i + 8] = t; \ + t ^= e_key[8 * i + 1]; e_key[8 * i + 9] = t; \ + t ^= e_key[8 * i + 2]; e_key[8 * i + 10] = t; \ + t ^= e_key[8 * i + 3]; e_key[8 * i + 11] = t; \ + t = e_key[8 * i + 4] ^ ls_box(t); \ + e_key[8 * i + 12] = t; \ + t ^= e_key[8 * i + 5]; e_key[8 * i + 13] = t; \ + t ^= e_key[8 * i + 6]; e_key[8 * i + 14] = t; \ + t ^= e_key[8 * i + 7]; e_key[8 * i + 15] = t; \ +} + +u4byte *set_key(const u4byte in_key[], const u4byte key_len) +{ u4byte i, t, u, v, w; + + if(!tab_gen) + + gen_tabs(); + + k_len = (key_len + 31) / 32; + + #if USE_SWAP_MACROS + get_key(e_key, key_len); + #else + e_key[0] = in_key[0]; e_key[1] = in_key[1]; + e_key[2] = in_key[2]; e_key[3] = in_key[3]; + #endif + + switch(k_len) + { + case 4: t = e_key[3]; + for(i = 0; i < 10; ++i) + loop4(i); + break; + + case 6: + #if USE_SWAP_MACROS + t = e_key[5]; + #else + /* done in get_key macros in USE_SWAP_MACROS case */ + e_key[4] = in_key[4]; t = e_key[5] = in_key[5]; + #endif + for(i = 0; i < 8; ++i) + loop6(i); + break; + + case 8: + #if USE_SWAP_MACROS + t = e_key[7]; + #else + e_key[4] = in_key[4]; e_key[5] = in_key[5]; + e_key[6] = in_key[6]; t = e_key[7] = in_key[7]; + #endif + for(i = 0; i < 7; ++i) + loop8(i); + break; + } + + d_key[0] = e_key[0]; d_key[1] = e_key[1]; + d_key[2] = e_key[2]; d_key[3] = e_key[3]; + + for(i = 4; i < 4 * k_len + 24; ++i) + { + imix_col(d_key[i], e_key[i]); + } + + return e_key; +}; + +/* encrypt a block of text */ + +#define f_nround(bo, bi, k) \ + f_rn(bo, bi, 0, k); \ + f_rn(bo, bi, 1, k); \ + f_rn(bo, bi, 2, k); \ + f_rn(bo, bi, 3, k); \ + k += 4 + +#define f_lround(bo, bi, k) \ + f_rl(bo, bi, 0, k); \ + f_rl(bo, bi, 1, k); \ + f_rl(bo, bi, 2, k); \ + f_rl(bo, bi, 3, k) + +void rEncrypt(const u4byte in_blk[4], u4byte out_blk[4]) +{ u4byte b0[4], b1[4], *kp; + + #if USE_SWAP_MACROS + u4byte swap_block[4]; + get_block(swap_block); + b0[0] = swap_block[0] ^ e_key[0]; b0[1] = swap_block[1] ^ e_key[1]; + b0[2] = swap_block[2] ^ e_key[2]; b0[3] = swap_block[3] ^ e_key[3]; + #else + b0[0] = in_blk[0] ^ e_key[0]; b0[1] = in_blk[1] ^ e_key[1]; + b0[2] = in_blk[2] ^ e_key[2]; b0[3] = in_blk[3] ^ e_key[3]; + #endif + + kp = e_key + 4; + + if(k_len > 6) + { + f_nround(b1, b0, kp); f_nround(b0, b1, kp); + } + + if(k_len > 4) + { + f_nround(b1, b0, kp); f_nround(b0, b1, kp); + } + + f_nround(b1, b0, kp); f_nround(b0, b1, kp); + f_nround(b1, b0, kp); f_nround(b0, b1, kp); + f_nround(b1, b0, kp); f_nround(b0, b1, kp); + f_nround(b1, b0, kp); f_nround(b0, b1, kp); + f_nround(b1, b0, kp); f_lround(b0, b1, kp); + + #if USE_SWAP_MACROS + put_block(b0); + #else + out_blk[0] = b0[0]; out_blk[1] = b0[1]; + out_blk[2] = b0[2]; out_blk[3] = b0[3]; + #endif +}; + +/* decrypt a block of text */ + +#define i_nround(bo, bi, k) \ + i_rn(bo, bi, 0, k); \ + i_rn(bo, bi, 1, k); \ + i_rn(bo, bi, 2, k); \ + i_rn(bo, bi, 3, k); \ + k -= 4 + +#define i_lround(bo, bi, k) \ + i_rl(bo, bi, 0, k); \ + i_rl(bo, bi, 1, k); \ + i_rl(bo, bi, 2, k); \ + i_rl(bo, bi, 3, k) + +void rDecrypt(const u4byte in_blk[4], u4byte out_blk[4]) +{ u4byte b0[4], b1[4], *kp; + + #if USE_SWAP_MACROS + u4byte swap_block[4]; + get_block(swap_block); + b0[0] = swap_block[0] ^ e_key[4 * k_len + 24]; + b0[1] = swap_block[1] ^ e_key[4 * k_len + 25]; + b0[2] = swap_block[2] ^ e_key[4 * k_len + 26]; + b0[3] = swap_block[3] ^ e_key[4 * k_len + 27]; + #else + b0[0] = in_blk[0] ^ e_key[4 * k_len + 24]; + b0[1] = in_blk[1] ^ e_key[4 * k_len + 25]; + b0[2] = in_blk[2] ^ e_key[4 * k_len + 26]; + b0[3] = in_blk[3] ^ e_key[4 * k_len + 27]; + #endif + + kp = d_key + 4 * (k_len + 5); + + if(k_len > 6) + { + i_nround(b1, b0, kp); i_nround(b0, b1, kp); + } + + if(k_len > 4) + { + i_nround(b1, b0, kp); i_nround(b0, b1, kp); + } + + i_nround(b1, b0, kp); i_nround(b0, b1, kp); + i_nround(b1, b0, kp); i_nround(b0, b1, kp); + i_nround(b1, b0, kp); i_nround(b0, b1, kp); + i_nround(b1, b0, kp); i_nround(b0, b1, kp); + i_nround(b1, b0, kp); i_lround(b0, b1, kp); + + #if USE_SWAP_MACROS + put_block(b0); + #else + out_blk[0] = b0[0]; out_blk[1] = b0[1]; + out_blk[2] = b0[2]; out_blk[3] = b0[3]; + #endif +}; diff --git a/SecurityTests/cspxutils/aesVect/std_defs.h b/SecurityTests/cspxutils/aesVect/std_defs.h new file mode 100644 index 00000000..9b7965d2 --- /dev/null +++ b/SecurityTests/cspxutils/aesVect/std_defs.h @@ -0,0 +1,151 @@ + + + +/* 1. Standard types for AES cryptography source code */ + +typedef unsigned char u1byte; /* an 8 bit unsigned character type */ +typedef unsigned short u2byte; /* a 16 bit unsigned integer type */ +typedef unsigned long u4byte; /* a 32 bit unsigned integer type */ + +typedef signed char s1byte; /* an 8 bit signed character type */ +typedef signed short s2byte; /* a 16 bit signed integer type */ +typedef signed long s4byte; /* a 32 bit signed integer type */ + +/* 2. Standard interface for AES cryptographic routines */ + +/* These are all based on 32 bit unsigned values and will therefore */ +/* require endian conversions for big-endian architectures */ + +#ifdef __cplusplus + extern "C" + { +#endif + + char **cipher_name(void); + u4byte *set_key(const u4byte in_key[], const u4byte key_len); + void rEncrypt(const u4byte in_blk[4], u4byte out_blk[4]); + void rDecrypt(const u4byte in_blk[4], u4byte out_blk[4]); + +#ifdef __cplusplus + }; +#endif + +/* 3. Basic macros for speeding up generic operations */ + +/* Circular rotate of 32 bit values */ + +#ifdef _MSC_VER + +# include +# pragma intrinsic(_lrotr,_lrotl) +# define rotr(x,n) _lrotr(x,n) +# define rotl(x,n) _lrotl(x,n) + +#else + +#define rotr(x,n) (((x) >> ((int)(n))) | ((x) << (32 - (int)(n)))) +#define rotl(x,n) (((x) << ((int)(n))) | ((x) >> (32 - (int)(n)))) + +#endif + +/* Invert byte order in a 32 bit variable */ + +#define bswap(x) ((rotl(x, 8) & 0x00ff00ff) | (rotr(x, 8) & 0xff00ff00)) + +/* Extract byte from a 32 bit quantity (little endian notation) */ + +#define byte(x,n) ((u1byte)((x) >> (8 * n))) + +/* For inverting byte order in input/output 32 bit words if needed */ +#ifdef __ppc__ +#define BYTE_SWAP +#endif + +#ifdef BLOCK_SWAP +#define BYTE_SWAP +#define WORD_SWAP +#endif + +#ifdef BYTE_SWAP +#define io_swap(x) bswap(x) +#else +#define io_swap(x) (x) +#endif + +/* For inverting the byte order of input/output blocks if needed */ + +#ifdef WORD_SWAP + +#define get_block(x) \ + ((u4byte*)(x))[0] = io_swap(in_blk[3]); \ + ((u4byte*)(x))[1] = io_swap(in_blk[2]); \ + ((u4byte*)(x))[2] = io_swap(in_blk[1]); \ + ((u4byte*)(x))[3] = io_swap(in_blk[0]) + +#define put_block(x) \ + out_blk[3] = io_swap(((u4byte*)(x))[0]); \ + out_blk[2] = io_swap(((u4byte*)(x))[1]); \ + out_blk[1] = io_swap(((u4byte*)(x))[2]); \ + out_blk[0] = io_swap(((u4byte*)(x))[3]) + +#define get_key(x,len) \ + ((u4byte*)(x))[4] = ((u4byte*)(x))[5] = \ + ((u4byte*)(x))[6] = ((u4byte*)(x))[7] = 0; \ + switch((((len) + 63) / 64)) { \ + case 2: \ + ((u4byte*)(x))[0] = io_swap(in_key[3]); \ + ((u4byte*)(x))[1] = io_swap(in_key[2]); \ + ((u4byte*)(x))[2] = io_swap(in_key[1]); \ + ((u4byte*)(x))[3] = io_swap(in_key[0]); \ + break; \ + case 3: \ + ((u4byte*)(x))[0] = io_swap(in_key[5]); \ + ((u4byte*)(x))[1] = io_swap(in_key[4]); \ + ((u4byte*)(x))[2] = io_swap(in_key[3]); \ + ((u4byte*)(x))[3] = io_swap(in_key[2]); \ + ((u4byte*)(x))[4] = io_swap(in_key[1]); \ + ((u4byte*)(x))[5] = io_swap(in_key[0]); \ + break; \ + case 4: \ + ((u4byte*)(x))[0] = io_swap(in_key[7]); \ + ((u4byte*)(x))[1] = io_swap(in_key[6]); \ + ((u4byte*)(x))[2] = io_swap(in_key[5]); \ + ((u4byte*)(x))[3] = io_swap(in_key[4]); \ + ((u4byte*)(x))[4] = io_swap(in_key[3]); \ + ((u4byte*)(x))[5] = io_swap(in_key[2]); \ + ((u4byte*)(x))[6] = io_swap(in_key[1]); \ + ((u4byte*)(x))[7] = io_swap(in_key[0]); \ + } + +#else + +#define get_block(x) \ + ((u4byte*)(x))[0] = io_swap(in_blk[0]); \ + ((u4byte*)(x))[1] = io_swap(in_blk[1]); \ + ((u4byte*)(x))[2] = io_swap(in_blk[2]); \ + ((u4byte*)(x))[3] = io_swap(in_blk[3]) + +#define put_block(x) \ + out_blk[0] = io_swap(((u4byte*)(x))[0]); \ + out_blk[1] = io_swap(((u4byte*)(x))[1]); \ + out_blk[2] = io_swap(((u4byte*)(x))[2]); \ + out_blk[3] = io_swap(((u4byte*)(x))[3]) + +#define get_key(x,len) \ + ((u4byte*)(x))[4] = ((u4byte*)(x))[5] = \ + ((u4byte*)(x))[6] = ((u4byte*)(x))[7] = 0; \ + switch((((len) + 63) / 64)) { \ + case 4: \ + ((u4byte*)(x))[6] = io_swap(in_key[6]); \ + ((u4byte*)(x))[7] = io_swap(in_key[7]); \ + case 3: \ + ((u4byte*)(x))[4] = io_swap(in_key[4]); \ + ((u4byte*)(x))[5] = io_swap(in_key[5]); \ + case 2: \ + ((u4byte*)(x))[0] = io_swap(in_key[0]); \ + ((u4byte*)(x))[1] = io_swap(in_key[1]); \ + ((u4byte*)(x))[2] = io_swap(in_key[2]); \ + ((u4byte*)(x))[3] = io_swap(in_key[3]); \ + } + +#endif diff --git a/SecurityTests/cspxutils/aesVect/testVectors b/SecurityTests/cspxutils/aesVect/testVectors new file mode 100755 index 00000000..03dc641e --- /dev/null +++ b/SecurityTests/cspxutils/aesVect/testVectors @@ -0,0 +1,27 @@ +#! /bin/csh -f +# +# Generate AES test vectors for Known Asnwers Test, compare against NIST standards. +## +if ( $#argv != 1 ) then + echo Usage: testVectors r\|t\|c + exit(1) +endif +# +# header, known vectors, output file +# +set vk_hdr=ecb_vk.hdr +set vk_ref=ecb_vk.txt +set vk_out=/tmp/vk_out +# +set vt_hdr=ecb_vt.hdr +set vt_ref=ecb_vt.txt +set vt_out=/tmp/vt_out +# +echo Generating Variable Key Known Answer Test vectors in $vk_out.... +./makeVectors $argv[1] k $vk_hdr $vk_out || exit(1) +echo Generating Variable Text Known Answer Test vectors in $vt_out.... +./makeVectors $argv[1] p $vt_hdr $vt_out || exit(1) +echo Comparing against reference vectors.... +diff $vk_out $vk_ref || exit(1) +diff $vt_out $vt_ref || exit(1) +echo === Known Answer Test PASSED === diff --git a/SecurityTests/cspxutils/ascTool/Makefile b/SecurityTests/cspxutils/ascTool/Makefile new file mode 100644 index 00000000..03b510c6 --- /dev/null +++ b/SecurityTests/cspxutils/ascTool/Makefile @@ -0,0 +1,55 @@ +# name of executable to build +EXECUTABLE=ascTool +# C++ source (with .cpp extension) +CPSOURCE= ascTool.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= -framework CoreFoundation + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +#PROJ_LDFLAGS= -lMallocDebug +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/ascTool/ascTool.cpp b/SecurityTests/cspxutils/ascTool/ascTool.cpp new file mode 100644 index 00000000..b2b0a5e0 --- /dev/null +++ b/SecurityTests/cspxutils/ascTool/ascTool.cpp @@ -0,0 +1,291 @@ +/* + * ascCrypt.c - simple ASC (ComCryption) encrypt/decrypt utility + */ + +#include "cspwrap.h" +#include "common.h" +#include +#include +#include +#include +#include +#include +#include +#include + +static void usage(char **argv) +{ + printf("usage:\n"); + printf(" %s op password inFile outFile [k=keysize] [o=optimize]\n", argv[0]); + printf(" op:\n"); + printf(" e encrypt\n"); + printf(" d decrypt\n"); + printf(" optimize:\n"); + printf(" d default\n"); + printf(" s size\n"); + printf(" e Security\n"); + printf(" t time\n"); + printf(" z time+size\n"); + printf(" a ASCII\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + int rtn; + uint32 keySizeInBytes = CSP_ASC_KEY_SIZE_DEFAULT / 8; + uint32 optimize = CSSM_ASC_OPTIMIZE_DEFAULT; + char *password; // ASCII password from cmd line + char *inFileName; // from cmd line + unsigned char *inFile; // raw infile data + unsigned inFileSize; // in bytes + char *outFileName; // from cmd line + CSSM_CSP_HANDLE cspHand; + CSSM_RETURN crtn; + int doEncrypt = 0; + CSSM_DATA passwordData; + CSSM_DATA saltData = {8, (uint8 *)"someSalt"}; + CSSM_DATA inData; // data to encrypt/decrypt, from inFile + CSSM_DATA outData = {0, NULL};// result data, written to outFile + CSSM_KEY_PTR symKey; + int arg; + char *argp; + CFAbsoluteTime start, end; + CSSM_CC_HANDLE ccHand; // crypto context + CSSM_DATA remData = {0, NULL}; + CSSM_SIZE bytesProcessed; + CSSM_DATA iv = {0, NULL}; + + if(argc < 5) { + usage(argv); + } + + /* gather up cmd line args */ + switch(argv[1][0]) { + case 'e': + doEncrypt = 1; + break; + case 'd': + doEncrypt = 0; + break; + default: + usage(argv); + } + password = argv[2]; + passwordData.Data = (uint8 *)password; + passwordData.Length = strlen(password); + inFileName = argv[3]; + outFileName = argv[4]; + + /* optional args */ + for(arg=5; arg +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "bsafeUtils.h" +#include +#include "cspdlTesting.h" + +/* + * Defaults. + */ +#define OLOOPS_DEF 10 /* outer loops, one set of keys per loop */ +#define SIG_LOOPS_DEF 100 /* sig loops */ +#define ENC_LOOPS_DEF 100 /* encrypt/decrypt loops */ +#define MAX_TEXT_SIZE 1025 + +#define LOOP_NOTIFY 20 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" a=algorithm (r=RSA; d=DSA; default=both)\n"); + printf(" l=outerloops (default=%d; 0=forever)\n", OLOOPS_DEF); + printf(" s=sigLoops (default=%d)\n", SIG_LOOPS_DEF); + printf(" e=encryptLoops (default=%d)\n", ENC_LOOPS_DEF); + printf(" k=keySizeInBits; default is random\n"); + printf(" S (sign/verify only)\n"); + printf(" E (encrypt/decrypt only)\n"); + printf(" r (generate ref keys)\n"); + printf(" R (generate public ref keys)\n"); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +static const char *algToStr(CSSM_ALGORITHMS sigAlg) +{ + switch(sigAlg) { + case CSSM_ALGID_RSA: return "RSA"; + case CSSM_ALGID_DSA: return "DSA"; + case CSSM_ALGID_SHA1WithRSA: return "SHA1WithRSA"; + case CSSM_ALGID_MD5WithRSA: return "MD5WithRSA"; + case CSSM_ALGID_SHA1WithDSA: return "SHA1WithDSA"; + default: + printf("***Unknown sigAlg\n"); + exit(1); + } + /* NOT REACHED */ + return ""; +} + +/* + * CDSA private key decrypt with blinding option. + */ +static CSSM_RETURN _cspDecrypt(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEED, etc. + uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for symmetric algs + CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc. + CSSM_BOOL blinding, + const CSSM_KEY *key, // public or session key + const CSSM_DATA *ctext, + CSSM_DATA_PTR ptext) // RETURNED +{ + CSSM_CC_HANDLE cryptHand; + CSSM_RETURN crtn; + CSSM_RETURN ocrtn = CSSM_OK; + CSSM_SIZE bytesDecrypted; + CSSM_DATA remData = {0, NULL}; + + cryptHand = genCryptHandle(cspHand, + algorithm, + mode, + padding, + key, + NULL, // pubKey, + NULL, // iv, + 0, // effectiveKeySizeInBits, + 0); // rounds + if(cryptHand == 0) { + return CSSMERR_CSP_INTERNAL_ERROR; + } + if(blinding) { + CSSM_CONTEXT_ATTRIBUTE newAttr; + newAttr.AttributeType = CSSM_ATTRIBUTE_RSA_BLINDING; + newAttr.AttributeLength = sizeof(uint32); + newAttr.Attribute.Uint32 = 1; + crtn = CSSM_UpdateContextAttributes(cryptHand, 1, &newAttr); + if(crtn) { + printError("CSSM_UpdateContextAttributes", crtn); + return crtn; + } + } + + crtn = CSSM_DecryptData(cryptHand, + ctext, + 1, + ptext, + 1, + &bytesDecrypted, + &remData); + if(crtn == CSSM_OK) { + // NOTE: We return the proper length in ptext.... + ptext->Length = bytesDecrypted; + + // FIXME - sometimes get mallocd RemData here, but never any valid data + // there...side effect of CSPFullPluginSession's buffer handling logic; + // but will we ever actually see valid data in RemData? So far we never + // have.... + if(remData.Data != NULL) { + appFree(remData.Data, NULL); + } + } + else { + printError("CSSM_DecryptData", crtn); + ocrtn = crtn; + } + crtn = CSSM_DeleteContext(cryptHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = crtn; + } + return ocrtn; +} + +/* sign with RSA blinging option */ +static CSSM_RETURN _cspSign(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. + CSSM_KEY_PTR key, // private key + const CSSM_DATA *text, + CSSM_BOOL rsaBlinding, + CSSM_DATA_PTR sig) // RETURNED +{ + CSSM_CC_HANDLE sigHand; + CSSM_RETURN crtn; + CSSM_RETURN ocrtn = CSSM_OK; + const CSSM_DATA *ptext; + CSSM_DATA digest = {0, NULL}; + CSSM_ALGORITHMS digestAlg = CSSM_ALGID_NONE; + + /* handle special cases for raw sign */ + switch(algorithm) { + case CSSM_ALGID_SHA1: + digestAlg = CSSM_ALGID_SHA1; + algorithm = CSSM_ALGID_RSA; + break; + case CSSM_ALGID_MD5: + digestAlg = CSSM_ALGID_MD5; + algorithm = CSSM_ALGID_RSA; + break; + case CSSM_ALGID_DSA: + digestAlg = CSSM_ALGID_SHA1; + algorithm = CSSM_ALGID_DSA; + break; + default: + break; + } + if(digestAlg != CSSM_ALGID_NONE) { + crtn = cspDigest(cspHand, + digestAlg, + CSSM_FALSE, // mallocDigest + text, + &digest); + if(crtn) { + return crtn; + } + /* sign digest with raw RSA/DSA */ + ptext = &digest; + } + else { + ptext = text; + } + crtn = CSSM_CSP_CreateSignatureContext(cspHand, + algorithm, + NULL, // passPhrase + key, + &sigHand); + if(crtn) { + printError("CSSM_CSP_CreateSignatureContext (1)", crtn); + return crtn; + } + if(rsaBlinding) { + CSSM_CONTEXT_ATTRIBUTE newAttr; + newAttr.AttributeType = CSSM_ATTRIBUTE_RSA_BLINDING; + newAttr.AttributeLength = sizeof(uint32); + newAttr.Attribute.Uint32 = 1; + crtn = CSSM_UpdateContextAttributes(sigHand, 1, &newAttr); + if(crtn) { + printError("CSSM_UpdateContextAttributes", crtn); + return crtn; + } + } + crtn = CSSM_SignData(sigHand, + ptext, + 1, + digestAlg, + sig); + if(crtn) { + printError("CSSM_SignData", crtn); + ocrtn = crtn; + } + crtn = CSSM_DeleteContext(sigHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = crtn; + } + if(digest.Data != NULL) { + CSSM_FREE(digest.Data); + } + return ocrtn; +} + + +/* + * Sign/verify test. + * + * for specified numLoops { + * generate random text; + * sign with BSAFE priv key, verify with CDSA pub key; + * sign with CDSA priv key, verify with BSAFE pub key; + * } + */ +static int sigTest( + CSSM_CSP_HANDLE cspHand, + unsigned numLoops, + + /* one matched key pair */ + BU_KEY bsafePrivKey, + CSSM_KEY_PTR cdsaPubKey, + + /* another matched key pair */ + CSSM_KEY_PTR cdsaPrivKey, + BU_KEY bsafePubKey, + + CSSM_DATA_PTR ptext, + unsigned maxPtextSize, + CSSM_ALGORITHMS sigAlg, + CSSM_BOOL rsaBlinding, + CSSM_BOOL quiet, + CSSM_BOOL verbose) +{ + CSSM_RETURN crtn; + CSSM_DATA sig = {0, NULL}; + unsigned loop; + uint32 keySizeInBits = cdsaPrivKey->KeyHeader.LogicalKeySizeInBits; + + if(!quiet) { + printf(" ...sig alg %s keySize %u\n", algToStr(sigAlg), (unsigned)keySizeInBits); + } + for(loop=0; loopKeyHeader.LogicalKeySizeInBits, + (unsigned long)ptext->Length); + } + } + + /* sign with BSAFE, verify with CDSA */ + crtn = buSign(bsafePrivKey, + sigAlg, + ptext, + keySizeInBits, + &sig); + if(crtn) { + return testError(quiet); + } + crtn = cspSigVerify(cspHand, + sigAlg, + cdsaPubKey, + ptext, + &sig, + CSSM_OK); + if(crtn) { + printf("***ERROR: Sign with BSAFE, vfy with CDSA, alg %s\n", + algToStr(sigAlg)); + if(testError(quiet)) { + return 1; + } + } + appFreeCssmData(&sig, CSSM_FALSE); + + /* sign with CDSA, verify with BSAFE */ + crtn = _cspSign(cspHand, + sigAlg, + cdsaPrivKey, + ptext, + rsaBlinding, + &sig); + if(crtn) { + return testError(quiet); + } + crtn = buVerify(bsafePubKey, + sigAlg, + ptext, + &sig); + if(crtn) { + printf("***ERROR: Sign with CDSA, vfy with BSAFE, alg %s\n", + algToStr(sigAlg)); + if(testError(quiet)) { + return 1; + } + } + appFreeCssmData(&sig, CSSM_FALSE); + } + return CSSM_OK; +} + +/* + * RSA Encrypt/decrypt test. + * + * for specified numLoops { + * generate random text; + * encrypt with BSAFE pub key, decrypt with CDSA priv key, verify; + * encrypt with CDSA pub key, decrypt with BSAFE priv key, verify; + * } + */ +static int encryptTest( + CSSM_CSP_HANDLE cspHand, + unsigned numLoops, + + /* one matched key pair */ + BU_KEY bsafePrivKey, + CSSM_KEY_PTR cdsaPubKey, + + /* another matched key pair */ + CSSM_KEY_PTR cdsaPrivKey, + BU_KEY bsafePubKey, + + CSSM_DATA_PTR ptext, + unsigned maxPtextSize, + CSSM_BOOL rsaBlinding, + CSSM_BOOL quiet, + CSSM_BOOL verbose) +{ + CSSM_RETURN crtn; + CSSM_DATA ctext = {0, NULL}; + CSSM_DATA rptext = {0, NULL}; + unsigned loop; + unsigned actKeySizeBytes; + + actKeySizeBytes = cdsaPrivKey->KeyHeader.LogicalKeySizeInBits / 8; + if(actKeySizeBytes < 12) { + printf("***Key with %u key bits is too small for RSA encrypt\n", + (unsigned)cdsaPrivKey->KeyHeader.LogicalKeySizeInBits); + return 1; + } + if(maxPtextSize > (actKeySizeBytes - 11)) { + maxPtextSize = actKeySizeBytes - 11; + } + if(!quiet) { + printf(" ...encr alg RSA\n"); + } + for(loop=0; loopKeyHeader.LogicalKeySizeInBits, + (unsigned long)ptext->Length); + } + } + + /* encrypt with BSAFE, decrypt with CDSA */ + crtn = buEncryptDecrypt(bsafePubKey, + CSSM_TRUE, // encrypt + CSSM_ALGID_RSA, + CSSM_ALGMODE_NONE, + NULL, // iv + cdsaPrivKey->KeyHeader.LogicalKeySizeInBits, + 0, // rounds + ptext, + &ctext); + if(crtn) { + return testError(quiet); + } + crtn = _cspDecrypt(cspHand, + CSSM_ALGID_RSA, + CSSM_ALGMODE_NONE, + CSSM_PADDING_PKCS1, + rsaBlinding, + cdsaPrivKey, + &ctext, + &rptext); + if(crtn) { + printf("***ERROR: encrypt with BSAFE, decrypt with CDSA\n"); + return testError(quiet); + } + if(!appCompareCssmData(ptext, &rptext)) { + printf("***DATA MISCOMPARE: encrypt with BSAFE, decrypt with CDSA\n"); + return testError(quiet); + } + appFreeCssmData(&ctext, CSSM_FALSE); + appFreeCssmData(&rptext, CSSM_FALSE); + + /* encrypt with CDSA, decrypt with BSAFE */ + crtn = cspEncrypt(cspHand, + CSSM_ALGID_RSA, + CSSM_ALGMODE_NONE, + CSSM_PADDING_PKCS1, + cdsaPubKey, + NULL, // (FEE) pub key + 0, // effectiveKeyBits + 0, // rounds + NULL, // IV + ptext, + &ctext, + CSSM_FALSE); // mallocCtext + if(crtn) { + return testError(quiet); + } + crtn = buEncryptDecrypt(bsafePrivKey, + CSSM_FALSE, // encrypt + CSSM_ALGID_RSA, + CSSM_ALGMODE_NONE, + NULL, // iv + cdsaPrivKey->KeyHeader.LogicalKeySizeInBits, + 0, // rounds + &ctext, + &rptext); + if(crtn) { + printf("***ERROR: encrypt with CDSA, decrypt with BSAFE\n"); + return testError(quiet); + } + if(!appCompareCssmData(ptext, &rptext)) { + printf("***DATA MISCOMPARE: encrypt with CDSA, decrypt with BSAFE\n"); + return testError(quiet); + } + appFreeCssmData(&ctext, CSSM_FALSE); + appFreeCssmData(&rptext, CSSM_FALSE); + } + return CSSM_OK; +} + +static int doTest( + CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS keyAlg, // RSA/DSA + CSSM_ALGORITHMS sigAlg, + unsigned sigLoops, // may be zero + unsigned encrLoops, // ditto; it will be zero for DSA + CSSM_BOOL rsaBlinding, + CSSM_DATA_PTR ptext, + unsigned maxPtextSize, + uint32 keySizeInBits, // 0 --> random per alg + CSSM_BOOL pubRefKeys, + CSSM_BOOL privRefKeys, + CSSM_BOOL bareCsp, // for other workarounds + CSSM_BOOL quiet, + CSSM_BOOL verbose) +{ + CSSM_KEY cdsaGenPubKey; + CSSM_KEY cdsaGenPrivKey; // only used to create bsafeDerivePrivKey + CSSM_KEY cdsaTempKey; // raw key if privRefKeys true + CSSM_KEY cdsaDerivePrivKey; // same as bsafeGenPrivKey + BU_KEY bsafeGenPubKey; + BU_KEY bsafeGenPrivKey; // only used to create cdsaDerivePrivKey + BU_KEY bsafeDerivePrivKey; // same as cdsaGenPrivKey + unsigned actKeySizeBits; + CSSM_RETURN crtn; + int rtn; + + if(!keySizeInBits) { + /* random key size */ + actKeySizeBits = randKeySizeBits(keyAlg, OT_Encrypt); + } + else { + /* caller/user specified */ + actKeySizeBits = keySizeInBits; + } + if(verbose) { + printf(" ...generating %s key pair, keySize %d bits...\n", + algToStr(keyAlg), actKeySizeBits); + } + + /* + * Generate two keypairs + */ + if(keyAlg == CSSM_ALGID_DSA) { + CSSM_BOOL doGenParams; + + if(bareCsp || CSPDL_DSA_GEN_PARAMS) { + doGenParams = CSSM_TRUE; + } + else { + /* CSPDL - no gen params */ + doGenParams = CSSM_FALSE; + } + crtn = cspGenDSAKeyPair(cspHand, + "foo", + 3, + actKeySizeBits, + &cdsaGenPubKey, + pubRefKeys, + CSSM_KEYUSE_ANY, + CSSM_KEYBLOB_RAW_FORMAT_NONE, + &cdsaGenPrivKey, + privRefKeys, + CSSM_KEYUSE_SIGN, + CSSM_KEYBLOB_RAW_FORMAT_NONE, + doGenParams, // genParams + NULL); // params + } + else { + crtn = cspGenKeyPair(cspHand, + keyAlg, + "foo", + 3, + actKeySizeBits, + &cdsaGenPubKey, + pubRefKeys, + CSSM_KEYUSE_ANY, + CSSM_KEYBLOB_RAW_FORMAT_NONE, + &cdsaGenPrivKey, + privRefKeys, + CSSM_KEYUSE_ANY, + CSSM_KEYBLOB_RAW_FORMAT_NONE, + CSSM_FALSE); // genSeed not used + } + if(crtn) { + return testError(quiet); + } + crtn = buGenKeyPair(actKeySizeBits, + keyAlg, + &bsafeGenPubKey, + &bsafeGenPrivKey); + if(crtn) { + return testError(quiet); + } + + /* + * Convert private keys to other library. + * NOTE: the reason we're only converting private keys is solely due to the + * fact that BSAFE does not handle PKCS1 formatted public key blobs. Very odd. + * But it's too much of a pain to re-implement that wheel here, and SSL and + * cert handling in general verify the CSP's PKCS1-style public key handling. + */ + if(privRefKeys) { + /* first generate a temporary raw CDSA key */ + crtn = buBsafePrivKeyToCdsa(keyAlg, + actKeySizeBits, + bsafeGenPrivKey, + &cdsaTempKey); + if(crtn) { + return testError(quiet); + } + + /* convert it to the ref key we'll actually use */ + crtn = cspRawKeyToRef(cspHand, &cdsaTempKey, &cdsaDerivePrivKey); + cspFreeKey(cspHand, &cdsaTempKey); + } + else { + crtn = buBsafePrivKeyToCdsa(keyAlg, + actKeySizeBits, + bsafeGenPrivKey, + &cdsaDerivePrivKey); + } + if(crtn) { + return testError(quiet); + } + if(privRefKeys) { + /* we have a CDSA priv ref key; convert it to raw format */ + crtn = cspRefKeyToRaw(cspHand, &cdsaGenPrivKey, &cdsaTempKey); + if(crtn) { + return testError(quiet); + } + /* now convert it to BSAFE */ + crtn = buCdsaPrivKeyToBsafe(&cdsaTempKey, &bsafeDerivePrivKey); + cspFreeKey(cspHand, &cdsaTempKey); + } + else { + crtn = buCdsaPrivKeyToBsafe(&cdsaGenPrivKey, &bsafeDerivePrivKey); + } + if(crtn) { + return testError(quiet); + } + + if(sigLoops) { + rtn = sigTest(cspHand, + sigLoops, + bsafeDerivePrivKey, + &cdsaGenPubKey, + &cdsaDerivePrivKey, + bsafeGenPubKey, + ptext, + maxPtextSize, + sigAlg, + rsaBlinding, + quiet, + verbose); + if(rtn) { + return rtn; + } + } + + if(encrLoops) { + rtn = encryptTest(cspHand, + encrLoops, + bsafeDerivePrivKey, + &cdsaGenPubKey, + &cdsaDerivePrivKey, + bsafeGenPubKey, + ptext, + maxPtextSize, + rsaBlinding, + quiet, + verbose); + if(rtn) { + return rtn; + } + } + + /* free all six keys */ + buFreeKey(bsafeGenPubKey); + buFreeKey(bsafeGenPrivKey); + buFreeKey(bsafeDerivePrivKey); + cspFreeKey(cspHand, &cdsaGenPubKey); + cspFreeKey(cspHand, &cdsaGenPrivKey); + cspFreeKey(cspHand, &cdsaDerivePrivKey); + return 0; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + CSSM_DATA ptext; + CSSM_CSP_HANDLE cspHand; + int i; + int rtn = 0; + + /* + * User-spec'd params + */ + uint32 keySizeInBits = 0; + unsigned oloops = OLOOPS_DEF; + unsigned sigLoops = SIG_LOOPS_DEF; + unsigned encrLoops = ENC_LOOPS_DEF; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + unsigned pauseInterval = 0; + CSSM_BOOL bareCsp = CSSM_TRUE; + CSSM_BOOL doDSA = CSSM_TRUE; + CSSM_BOOL doRSA = CSSM_TRUE; + CSSM_BOOL pubRefKeys = CSSM_FALSE; + CSSM_BOOL privRefKeys = CSSM_FALSE; + + for(arg=1; arg +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include +#include + +/* + * Defaults. + */ +#define ENC_LOOPS_DEF 1000 +#define KEYSIZE_DEF 1024 +#define PTEXT_SIZE 20 /* e.g., a SHA1 digest */ + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" a=algorithm (r=RSA; f=FEED; F=FEEDExp; default=RSA)\n"); + printf(" l=numLoop (default=%d)\n", ENC_LOOPS_DEF); + printf(" k=keySizeInBits; default=%d\n", KEYSIZE_DEF); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" b (RSA blinding enabled)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + + +int main(int argc, char **argv) +{ + int arg; + char *argp; + CSSM_CSP_HANDLE cspHand; + unsigned i; + CSSM_KEY pubKey; + CSSM_KEY privKey; + CSSM_DATA_PTR ptext; // different for each loop + CSSM_DATA_PTR ctext; // ditto + CSSM_DATA_PTR rptext; // ditto + CSSM_RETURN crtn; + CFAbsoluteTime start, end; + CSSM_CC_HANDLE ccHand; + unsigned ctextSize; + CSSM_ACCESS_CREDENTIALS creds; + CSSM_SIZE processed; + CSSM_DATA remData; + + /* + * User-spec'd params + */ + uint32 keySizeInBits = KEYSIZE_DEF; + unsigned encLoops = ENC_LOOPS_DEF; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL bareCsp = CSSM_TRUE; + CSSM_BOOL rsaBlinding = CSSM_FALSE; + CSSM_ALGORITHMS keyAlg = CSSM_ALGID_RSA; + CSSM_ALGORITHMS encrAlg = CSSM_ALGID_RSA; + CSSM_PADDING padding = CSSM_PADDING_PKCS1; + + for(arg=1; arg +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "cspdlTesting.h" + +#define USAGE_NAME "noUsage" +#define USAGE_NAME_LEN (strlen(USAGE_NAME)) +#define USAGE2_NAME "noUsage2" +#define USAGE2_NAME_LEN (strlen(USAGE2_NAME)) +#define LOOPS_DEF 10 +#define MIN_EXP 2 /* for data size 10**exp */ +#define DEFAULT_MAX_EXP 2 +#define MAX_EXP 4 + +/* + * Enumerate algs our own way to allow iteration. + */ +#define ALG_RSA 1 +#define ALG_FEED 2 +#define ALG_FEEDEXP 3 +#define ALG_FEE_CFILE 4 +#define ALG_FIRST ALG_RSA +#define ALG_LAST ALG_FEEDEXP +#define MAX_DATA_SIZE (10000 + 100) /* bytes */ +#define FEE_PASSWD_LEN 32 /* private data length in bytes, FEE only */ + +#define DUMP_KEY_DATA 0 + +/* + * RSA encryption now allows arbitrary plaintext size. BSAFE was limited to + * primeSize - 11. + */ +#define RSA_PLAINTEXT_LIMIT 0 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" a=algorithm (f=FEED; x=FEEDExp; c=FEE_Cfile; r=RSA; default=all)\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" n=minExp (default=%d)\n", MIN_EXP); + printf(" x=maxExp (default=%d, max=%d)\n", DEFAULT_MAX_EXP, MAX_EXP); + printf(" k=keySize\n"); + printf(" P=primeType (m=Mersenne, f=FEE, g=general; FEE only)\n"); + printf(" C=curveType (m=Montgomery, w=Weierstrass, g=general; FEE only)\n"); + printf(" e(xport)\n"); + printf(" r(eference keys only)\n"); + printf(" K (skip decrypt)\n"); + printf(" N(o padding, RSA only)\n"); + printf(" S (no staging)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" p (pause on each loop)\n"); + printf(" u (quick; small keys)\n"); + printf(" t=plainTextSize; default=random\n"); + printf(" z(ero data)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +static int doTest(CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS alg, // CSSM_ALGID_xxx + CSSM_PADDING padding, + CSSM_DATA_PTR ptext, + CSSM_BOOL verbose, + CSSM_BOOL quiet, + uint32 keySizeInBits, // may be 0, i.e., default per alg + uint32 primeType, // FEE only + uint32 curveType, // ditto + CSSM_BOOL pubIsRef, + CSSM_KEYBLOB_FORMAT rawPubForm, + CSSM_BOOL privIsRef, + CSSM_KEYBLOB_FORMAT rawPrivForm, + CSSM_BOOL secondPubIsRaw, // FEED via CSPDL: 2nd key must be raw + CSSM_BOOL stagedEncr, + CSSM_BOOL stagedDecr, + CSSM_BOOL mallocPtext, // only meaningful if !stagedDecr + CSSM_BOOL mallocCtext, // only meaningful if !stagedEncr + CSSM_BOOL skipDecrypt, + CSSM_BOOL genSeed) // FEE keys only +{ + // these two are always generated + CSSM_KEY recvPubKey; + CSSM_KEY recvPrivKey; + // these two are for two-key FEE algorithms only + CSSM_KEY sendPubKey; + CSSM_KEY sendPrivKey; + // these two are optionally created by cspRefKeyToRaw if (FEED && secondPubIsRaw) + CSSM_KEY sendPubKeyRaw; + CSSM_KEY recvPubKeyRaw; + CSSM_BOOL rawPubKeysCreated = CSSM_FALSE; + + /* two-key FEE, CSP : &{send,recv}PubKey + * two-key FEE, CSPDL: &{send,recv}PubKeyRaw + * else : NULL, &recvPubKey + */ + CSSM_KEY_PTR sendPubKeyPtr = NULL; + CSSM_KEY_PTR recvPubKeyPtr = NULL; + + CSSM_DATA ctext = {0, NULL}; + CSSM_DATA rptext = {0, NULL}; + CSSM_RETURN crtn; + int rtn = 0; + uint32 keyGenAlg; + uint32 mode = CSSM_ALGMODE_NONE; // FIXME - does this need testing? + CSSM_BOOL twoKeys = CSSM_FALSE; + + switch(alg) { + case CSSM_ALGID_FEED: + case CSSM_ALGID_FEECFILE: + twoKeys = CSSM_TRUE; + /* drop thru */ + case CSSM_ALGID_FEEDEXP: + keyGenAlg = CSSM_ALGID_FEE; + break; + case CSSM_ALGID_RSA: + keyGenAlg = CSSM_ALGID_RSA; + break; + default: + printf("bogus algorithm\n"); + return 1; + } + + /* one key pair for all algs except CFILE and FEED, which need two */ + if(keyGenAlg == CSSM_ALGID_FEE) { + uint8 passwd[FEE_PASSWD_LEN]; + CSSM_DATA pwdData = {FEE_PASSWD_LEN, passwd}; + CSSM_DATA_PTR pwdDataPtr; + if(genSeed) { + simpleGenData(&pwdData, FEE_PASSWD_LEN, FEE_PASSWD_LEN); + pwdDataPtr = &pwdData; + } + else { + pwdDataPtr = NULL; + } + /* + * Note we always generate public keys per the pubIsRef argument, even if + * secondPubIsRaw is true, 'cause the CSPDL can't generate raw keys. + */ + rtn = cspGenFEEKeyPair(cspHand, + USAGE_NAME, + USAGE_NAME_LEN, + keySizeInBits, + primeType, + curveType, + &recvPubKey, + pubIsRef, + CSSM_KEYUSE_ANY, + CSSM_KEYBLOB_RAW_FORMAT_NONE, + &recvPrivKey, + privIsRef, + CSSM_KEYUSE_ANY, + CSSM_KEYBLOB_RAW_FORMAT_NONE, + pwdDataPtr); + if(rtn) { + /* leak */ + return testError(quiet); + } + if(twoKeys) { + rtn = cspGenFEEKeyPair(cspHand, + USAGE2_NAME, + USAGE2_NAME_LEN, + keySizeInBits, + primeType, + curveType, + &sendPubKey, + pubIsRef, + CSSM_KEYUSE_ANY, + CSSM_KEYBLOB_RAW_FORMAT_NONE, + &sendPrivKey, + privIsRef, + CSSM_KEYUSE_ANY, + CSSM_KEYBLOB_RAW_FORMAT_NONE, + pwdDataPtr); + if(rtn) { + /* leak recv*Key */ + return testError(quiet); + } + } + if(twoKeys) { + if(secondPubIsRaw && pubIsRef) { + /* + * Convert ref public keys to raw - they're going into a Context; the + * SecurityServer doesn't deal with ref keys there. + * Leak all sorts of stuff on any error here. + */ + crtn = cspRefKeyToRaw(cspHand, &sendPubKey, &sendPubKeyRaw); + if(crtn) { + return testError(quiet); + } + crtn = cspRefKeyToRaw(cspHand, &recvPubKey, &recvPubKeyRaw); + if(crtn) { + return testError(quiet); + } + /* two keys, CSPDL */ + sendPubKeyPtr = &sendPubKeyRaw; + recvPubKeyPtr = &recvPubKeyRaw; + rawPubKeysCreated = CSSM_TRUE; + } + else { + /* two keys, CSP */ + sendPubKeyPtr = &sendPubKey; + recvPubKeyPtr = &recvPubKey; + } + } + else { + /* one key pair, standard config */ + sendPubKeyPtr = NULL; + recvPubKeyPtr = &recvPubKey; + } + } + else { + CSSM_KEYBLOB_FORMAT expectPubForm = rawPubForm; + CSSM_KEYBLOB_FORMAT expectPrivForm = rawPrivForm; + + rtn = cspGenKeyPair(cspHand, + keyGenAlg, + USAGE_NAME, + USAGE_NAME_LEN, + keySizeInBits, + &recvPubKey, + pubIsRef, + twoKeys ? CSSM_KEYUSE_ANY : CSSM_KEYUSE_ENCRYPT, + rawPubForm, + &recvPrivKey, + privIsRef, + twoKeys ? CSSM_KEYUSE_ANY : CSSM_KEYUSE_DECRYPT, + rawPrivForm, + genSeed); + if(rtn) { + return testError(quiet); + } + /* one key pair, standard config */ + sendPubKeyPtr = NULL; + recvPubKeyPtr = &recvPubKey; + + /* verify defaults - only for RSA */ + if(!pubIsRef) { + if(rawPubForm == CSSM_KEYBLOB_RAW_FORMAT_NONE) { + expectPubForm = CSSM_KEYBLOB_RAW_FORMAT_PKCS1; + } + if(recvPubKey.KeyHeader.Format != expectPubForm) { + printf("***Bad raw RSA pub key format - exp %u got %u\n", + (unsigned)expectPubForm, + (unsigned)recvPubKey.KeyHeader.Format); + if(testError(quiet)) { + return 1; + } + } + } + if(!privIsRef) { + if(rawPrivForm == CSSM_KEYBLOB_RAW_FORMAT_NONE) { + expectPrivForm = CSSM_KEYBLOB_RAW_FORMAT_PKCS8; + } + if(recvPrivKey.KeyHeader.Format != expectPrivForm) { + printf("***Bad raw RSA priv key format - exp %u got %u\n", + (unsigned)expectPrivForm, + (unsigned)recvPrivKey.KeyHeader.Format); + if(testError(quiet)) { + return 1; + } + } + } + } + #if DUMP_KEY_DATA + dumpBuffer("Pub Key Data", recvPubKey.KeyData.Data, recvPubKey.KeyData.Length); + dumpBuffer("Priv Key Data", recvPrivKey.KeyData.Data, recvPrivKey.KeyData.Length); + #endif + if(stagedEncr) { + crtn = cspStagedEncrypt(cspHand, + alg, + mode, + padding, + /* Two keys: second must be pub */ + twoKeys ? &sendPrivKey : &recvPubKey, + twoKeys ? recvPubKeyPtr : NULL, + 0, // effectiveKeySize + 0, // cipherBlockSize + 0, // rounds + NULL, // initVector + ptext, + &ctext, + CSSM_TRUE); // multi + } + else { + crtn = cspEncrypt(cspHand, + alg, + mode, + padding, + /* Two keys: second must be pub */ + twoKeys ? &sendPrivKey : &recvPubKey, + twoKeys ? recvPubKeyPtr : NULL, + 0, // effectiveKeySize + 0, // rounds + NULL, // initVector + ptext, + &ctext, + mallocCtext); + } + if(crtn) { + rtn = testError(quiet); + goto abort; + } + if(verbose) { + printf(" ..ptext size %lu ctext size %lu\n", + (unsigned long)ptext->Length, (unsigned long)ctext.Length); + } + if(skipDecrypt) { + goto abort; + } + if(stagedDecr) { + crtn = cspStagedDecrypt(cspHand, + alg, + mode, + padding, + /* Two keys: second must be pub */ + &recvPrivKey, + sendPubKeyPtr, + 0, // effectiveKeySize + 0, // cipherBlockSize + 0, // rounds + NULL, // initVector + &ctext, + &rptext, + CSSM_TRUE); // multi + } + else { + crtn = cspDecrypt(cspHand, + alg, + mode, + padding, + &recvPrivKey, + sendPubKeyPtr, + 0, // effectiveKeySize + 0, // rounds + NULL, // initVector + &ctext, + &rptext, + mallocPtext); + } + if(crtn) { + rtn = testError(quiet); + goto abort; + } + /* compare ptext, rptext */ + if(ptext->Length != rptext.Length) { + printf("Ptext length mismatch: expect %lu, got %lu\n", + (unsigned long)ptext->Length, (unsigned long)rptext.Length); + rtn = testError(quiet); + if(rtn) { + goto abort; + } + } + if(memcmp(ptext->Data, rptext.Data, ptext->Length)) { + printf("***data miscompare\n"); + rtn = testError(quiet); + } +abort: + /* free keys */ + if(cspFreeKey(cspHand, &recvPubKey)) { + printf("Error freeing recvPubKey\n"); + rtn = 1; + } + if(cspFreeKey(cspHand, &recvPrivKey)) { + printf("Error freeing recvPrivKey\n"); + rtn = 1; + } + if(twoKeys) { + if(cspFreeKey(cspHand, &sendPubKey)) { + printf("Error freeing sendPubKey\n"); + rtn = 1; + } + if(cspFreeKey(cspHand, &sendPrivKey)) { + printf("Error freeing sendPrivKey\n"); + rtn = 1; + } + if(rawPubKeysCreated) { + if(cspFreeKey(cspHand, &sendPubKeyRaw)) { + printf("Error freeing sendPubKeyRaw\n"); + rtn = 1; + } + if(cspFreeKey(cspHand, &recvPubKeyRaw)) { + printf("Error freeing recvPubKeyRaw\n"); + rtn = 1; + } + } + } + /* free rptext, ctext */ + appFreeCssmData(&rptext, CSSM_FALSE); + appFreeCssmData(&ctext, CSSM_FALSE); + return rtn; +} + +static const char *formStr( + CSSM_KEYBLOB_FORMAT form) +{ + switch(form) { + case CSSM_KEYBLOB_RAW_FORMAT_NONE: return "NONE"; + case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: return "PKCS1"; + case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: return "PKCS8"; + case CSSM_KEYBLOB_RAW_FORMAT_X509: return "X509"; + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: return "SSH1"; + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2: return "SSH2"; + default: + printf("***BRRRZAP! formStr needs work\n"); + exit(1); + } +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + CSSM_DATA ptext; + CSSM_CSP_HANDLE cspHand; + CSSM_BOOL pubIsRef = CSSM_TRUE; + CSSM_BOOL privIsRef = CSSM_TRUE; + CSSM_BOOL stagedEncr; + CSSM_BOOL stagedDecr; + const char *algStr; + uint32 encAlg; // CSSM_ALGID_xxx + unsigned currAlg; // ALG_xxx + int i; + CSSM_BOOL mallocCtext; + CSSM_BOOL mallocPtext; + int rtn = 0; + CSSM_BOOL genSeed; // for FEE key gen + CSSM_PADDING padding; + CSSM_KEYBLOB_FORMAT rawPubFormat = CSSM_KEYBLOB_RAW_FORMAT_NONE; + CSSM_KEYBLOB_FORMAT rawPrivFormat = CSSM_KEYBLOB_RAW_FORMAT_NONE; + + /* + * User-spec'd params + */ + unsigned loops = LOOPS_DEF; + CSSM_BOOL verbose = CSSM_FALSE; + unsigned minExp = MIN_EXP; + unsigned maxExp = DEFAULT_MAX_EXP; + CSSM_BOOL quiet = CSSM_FALSE; + uint32 keySizeInBits = CSP_KEY_SIZE_DEFAULT; + CSSM_BOOL keySizeSpec = CSSM_FALSE; + unsigned minAlg = ALG_FIRST; + uint32 maxAlg = ALG_LAST; + CSSM_BOOL skipDecrypt = CSSM_FALSE; + CSSM_BOOL bareCsp = CSSM_TRUE; + CSSM_BOOL doPause = CSSM_FALSE; + CSSM_BOOL smallKeys = CSSM_FALSE; + uint32 primeType = CSSM_FEE_PRIME_TYPE_DEFAULT; // FEE only + uint32 curveType = CSSM_FEE_CURVE_TYPE_DEFAULT; // FEE only + uint32 ptextSize = 0; // 0 means random + dataType dtype = DT_Random; + CSSM_BOOL refKeysOnly = CSSM_FALSE; + CSSM_BOOL noPadding = CSSM_FALSE; + CSSM_BOOL stagingEnabled = CSSM_TRUE; + + for(arg=1; arg MAX_EXP) { + usage(argv); + } + break; + case 'k': + keySizeInBits = atoi(&argv[arg][2]); + keySizeSpec = CSSM_TRUE; + break; + case 'K': + skipDecrypt = CSSM_TRUE; + break; + case 't': + ptextSize = atoi(&argp[2]); + break; + case 'D': + bareCsp = CSSM_FALSE; + #if CSPDL_ALL_KEYS_ARE_REF + refKeysOnly = CSSM_TRUE; + #endif + break; + case 'u': + smallKeys = CSSM_TRUE; + break; + case 'N': + noPadding = CSSM_TRUE; + break; + case 'z': + dtype = DT_Zero; + break; + case 'v': + verbose = CSSM_TRUE; + break; + case 'r': + refKeysOnly = CSSM_TRUE; + break; + case 'S': + stagingEnabled = CSSM_FALSE; + break; + case 'p': + doPause = CSSM_TRUE; + break; + case 'q': + quiet = CSSM_TRUE; + break; + case 'C': + switch(argp[2]) { + case 'm': + curveType = CSSM_FEE_CURVE_TYPE_MONTGOMERY; + break; + case 'w': + curveType = CSSM_FEE_CURVE_TYPE_WEIERSTRASS; + break; + default: + usage(argv); + } + break; + case 'P': + switch(argp[2]) { + case 'm': + primeType = CSSM_FEE_PRIME_TYPE_MERSENNE; + break; + case 'f': + primeType = CSSM_FEE_PRIME_TYPE_FEE; + break; + case 'g': + primeType = CSSM_FEE_PRIME_TYPE_GENERAL; + break; + default: + usage(argv); + } + break; + case 'h': + default: + usage(argv); + } + } + ptext.Data = (uint8 *)CSSM_MALLOC(MAX_DATA_SIZE); + + /* length set in test loop */ + if(ptext.Data == NULL) { + printf("Insufficient heap\n"); + exit(1); + } + if(noPadding) { + if(ptextSize == 0) { + printf("**WARNING NoPad mode will fail with random plaintext size\n"); + } + if(!keySizeSpec) { + printf("**WARNING NoPad mode will fail with random key size\n"); + } + else { + uint32 keyBytes = keySizeInBits / 8; + if(ptextSize != keyBytes) { + /* + * FIXME: I actually do not understand why this fails, but + * doing raw RSA encryption with ptextSize != keySize results + * in random-looking failures, probably based on the plaintext + * itself (it doesn't fail with zero data). + */ + printf("***WARNING NoPad mode requires plaintext size = key size\n"); + } + } + } + printf("Starting asymTest; args: "); + for(i=1; i +#include +#include +#include +#include "cspwrap.h" +#include "common.h" + +static CSSM_API_MEMORY_FUNCS memFuncs = { + appMalloc, + appFree, + appRealloc, + appCalloc, + NULL + }; + +static CSSM_VERSION vers = {2, 0}; + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options: \n"); + printf(" l (do ModuleLoad on each loop)\n"); + printf(" u (do Module{Load,Unload} on each loop)\n"); + printf(" d (CSP/DL; default = bare CSP)\n"); + printf(" t (TP)\n"); + printf(" c (CL)\n"); + exit(1); +} + +static int doPause(const char *state) +{ + char resp; + + fpurge(stdin); + printf("%s\n", state); + printf("q to abort, anything else to continue: "); + resp = getchar(); + return(resp == 'q'); +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + CSSM_HANDLE modHand = 0; + void *foo; + CSSM_SERVICE_TYPE svcType = CSSM_SERVICE_CSP; + const CSSM_GUID *guid = &gGuidAppleCSP; + const char *modName = "AppleCSP"; + CSSM_RETURN crtn; + CSSM_BOOL doLoad = CSSM_FALSE; + CSSM_BOOL doUnload = CSSM_FALSE; + + /* force link against malloc */ + foo = malloc(1); + for(arg=1; arg +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "cspdlTesting.h" +/* + * Enumerate algs our own way to allow iteration. + */ +typedef unsigned privAlg; +enum { + ALG_ASC = 1, + ALG_DES, + ALG_RC2, + ALG_RC4, + ALG_RC5, + ALG_3DES, + ALG_AES, + ALG_RSA, + ALG_FEE, + ALG_ECDSA, + ALG_DSA +}; + +#define SYM_FIRST ALG_ASC +#define SYM_LAST ALG_AES +#define ASYM_FIRST ALG_RSA +#define ASYM_LAST ALG_ECDSA /* DSA if we're patient */ + +/* + * ops expressed at bitfields + */ +#define OP_SIGN 0x0001 +#define OP_VERIFY 0x0002 +#define OP_ENCRYPT 0x0004 +#define OP_DECRYPT 0x0008 +#define OP_GENMAC 0x0010 +#define OP_VFYMAC 0x0020 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" s(ymmetric only)\n"); + printf(" a(symmetric only)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +/* + * Common, flexible, error-tolerant symmetric key generator. + */ +static int genSymKey( + CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR symKey, + uint32 alg, + const char *keyAlgStr, + uint32 keySizeInBits, + CSSM_KEYATTR_FLAGS keyAttr, + CSSM_KEYUSE keyUsage, + CSSM_RETURN expectRtn, + CSSM_BOOL quiet, + CSSM_BOOL freeKey, // true: free the key on exit + const char *testStr) +{ + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + CSSM_DATA dummyLabel = {4, (uint8 *)"foo"}; + int irtn; + + memset(symKey, 0, sizeof(CSSM_KEY)); + crtn = CSSM_CSP_CreateKeyGenContext(cspHand, + alg, + keySizeInBits, // keySizeInBits + NULL, // Seed + NULL, // Salt + NULL, // StartDate + NULL, // EndDate + NULL, // Params + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateKeyGenContext", crtn); + return testError(quiet); + } + crtn = CSSM_GenerateKey(ccHand, + keyUsage, + keyAttr, + &dummyLabel, + NULL, // ACL + symKey); + if(crtn != expectRtn) { + printf("***Testing %s for alg %s:\n", testStr, keyAlgStr); + printf(" CSSM_GenerateKey: expect %s\n", cssmErrToStr(expectRtn)); + printf(" CSSM_GenerateKey: got %s\n", cssmErrToStr(crtn)); + irtn = testError(quiet); + } + else { + irtn = 0; + } + CSSM_DeleteContext(ccHand); + if(freeKey && (crtn == CSSM_OK)) { + cspFreeKey(cspHand, symKey); + } + return irtn; +} + +/* + * Common, flexible, error-tolerant key pair generator. + */ +static int genKeyPair( + CSSM_CSP_HANDLE cspHand, + uint32 algorithm, + const char *keyAlgStr, + uint32 keySizeInBits, + CSSM_KEY_PTR pubKey, + CSSM_KEYATTR_FLAGS pubKeyAttr, + CSSM_KEYUSE pubKeyUsage, + CSSM_KEY_PTR privKey, + CSSM_KEYATTR_FLAGS privKeyAttr, + CSSM_KEYUSE privKeyUsage, + CSSM_RETURN expectRtn, + CSSM_BOOL quiet, + CSSM_BOOL freeKeys, // true: free the keys on exit + const char *testStr) +{ + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + CSSM_DATA keyLabelData = {4, (uint8 *)"foo"}; + int irtn; + + memset(pubKey, 0, sizeof(CSSM_KEY)); + memset(privKey, 0, sizeof(CSSM_KEY)); + + crtn = CSSM_CSP_CreateKeyGenContext(cspHand, + algorithm, + keySizeInBits, + NULL, // Seed + NULL, // Salt + NULL, // StartDate + NULL, // EndDate + NULL, // Params + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateKeyGenContext", crtn); + return testError(quiet); + } + + /* post-context-create algorithm-specific stuff */ + switch(algorithm) { + case CSSM_ALGID_RSA: + break; + + case CSSM_ALGID_DSA: + /* + * extra step - generate params - this just adds some + * info to the context + */ + { + CSSM_DATA dummy = {0, NULL}; + crtn = CSSM_GenerateAlgorithmParams(ccHand, + keySizeInBits, &dummy); + if(crtn) { + printError("CSSM_GenerateAlgorithmParams", crtn); + return testError(quiet); + } + appFreeCssmData(&dummy, CSSM_FALSE); + } + break; + default: + break; + } + + crtn = CSSM_GenerateKeyPair(ccHand, + pubKeyUsage, + pubKeyAttr, + &keyLabelData, + pubKey, + privKeyUsage, + privKeyAttr, + &keyLabelData, // same labels + NULL, // CredAndAclEntry + privKey); + if(crtn != expectRtn) { + printf("***Testing %s for alg %s:\n", testStr, keyAlgStr); + printf(" CSSM_GenerateKeyPair: expect %s\n", cssmErrToStr(expectRtn)); + printf(" CSSM_GenerateKeyPair: got %s\n", cssmErrToStr(crtn)); + irtn = testError(quiet); + } + else { + irtn = 0; + } + CSSM_DeleteContext(ccHand); + if(freeKeys && (crtn == CSSM_OK)) { + cspFreeKey(cspHand, pubKey); + cspFreeKey(cspHand, privKey); + } + return irtn; +} + +/* + * Perform NULL wrap, generally expecting an error (either + * CSSMERR_CSP_INVALID_KEYATTR_MASK, if the raw key bits should be inaccessible, + * or CSSMERR_CSP_INVALID_KEY_REFERENCE, if the key's header has been munged.) + */ +int nullWrapTest( + CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR key, + CSSM_BOOL quiet, + CSSM_RETURN expectRtn, + const char *keyAlgStr, + const char *testStr) +{ + CSSM_CC_HANDLE ccHand; + CSSM_RETURN crtn; + CSSM_ACCESS_CREDENTIALS creds; + CSSM_KEY wrappedKey; // should not get created + int irtn; + + memset(&wrappedKey, 0, sizeof(CSSM_KEY)); + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + crtn = CSSM_CSP_CreateSymmetricContext(cspHand, + CSSM_ALGID_NONE, + CSSM_ALGMODE_NONE, + &creds, // passPhrase, + NULL, // wrappingKey, + NULL, // IV + CSSM_PADDING_NONE, + 0, // Params + &ccHand); + if(crtn) { + printError("cspWrapKey/CreateContext", crtn); + return testError(quiet); + } + crtn = CSSM_WrapKey(ccHand, + &creds, + key, + NULL, // DescriptiveData + &wrappedKey); + if(crtn != expectRtn) { + printf("***Testing %s for alg %s:\n", testStr, keyAlgStr); + printf(" CSSM_WrapKey: expect %s\n", cssmErrToStr(expectRtn)); + printf(" CSSM_WrapKey: got %s\n", cssmErrToStr(crtn)); + irtn = testError(quiet); + } + else { + irtn = 0; + } + CSSM_DeleteContext(ccHand); + return irtn; +} + +/* + * Attempt to wrap incoming key with a DES key that we generate. Expect + * CSSMERR_CSP_INVALID_KEYATTR_MASK since the unwrapped key is marked + * !EXTRACTABLE. + */ +#define WRAPPING_KEY_ALG CSSM_ALGID_DES +#define WRAPPING_KEY_SIZE CSP_DES_KEY_SIZE_DEFAULT + +static int badWrapTest( + CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR unwrappedKey, + CSSM_KEYBLOB_FORMAT wrapForm, + CSSM_BOOL quiet, + const char *keyAlgStr, + const char *testStr) +{ + CSSM_CC_HANDLE ccHand; + CSSM_RETURN crtn; + CSSM_ACCESS_CREDENTIALS creds; + CSSM_KEY wrappedKey; // should not get created + CSSM_KEY wrappingKey; + int irtn; + + /* first generate a DES wrapping key */ + if(genSymKey(cspHand, &wrappingKey, CSSM_ALGID_DES, "DES", + CSP_DES_KEY_SIZE_DEFAULT, + CSSM_KEYATTR_RETURN_REF, + CSSM_KEYUSE_ANY, CSSM_OK, quiet, + CSSM_FALSE, "not a test case")) { + return 1; + } + + memset(&wrappedKey, 0, sizeof(CSSM_KEY)); + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + + /* symmetric wrapping context */ + crtn = CSSM_CSP_CreateSymmetricContext(cspHand, + CSSM_ALGID_DES, + CSSM_ALGMODE_CBCPadIV8, + &creds, // passPhrase, + &wrappingKey, + NULL, // IV + CSSM_PADDING_PKCS5, + 0, // Params + &ccHand); + if(crtn) { + printError("cspWrapKey/CreateContext", crtn); + return testError(quiet); + } + + /* do it, demand error */ + crtn = CSSM_WrapKey(ccHand, + &creds, + unwrappedKey, + NULL, // DescriptiveData + &wrappedKey); + if(crtn != CSSMERR_CSP_INVALID_KEYATTR_MASK) { + printf("***Testing %s for alg %s:\n", testStr, keyAlgStr); + printf(" CSSM_WrapKey: expect CSSMERR_CSP_INVALID_KEYATTR_MASK, got %s\n", + cssmErrToStr(crtn)); + irtn = testError(quiet); + } + else { + irtn = 0; + } + CSSM_DeleteContext(ccHand); + cspFreeKey(cspHand, &wrappingKey); + return irtn; +} + + +/* + * Note for these op stubs, the data, mode, padding, etc. are unimportant as + * the ops are expected to fail during key extraction. + */ +static int badEncrypt( + CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR key, + const char *keyAlgStr, + CSSM_ALGORITHMS opAlg, + CSSM_RETURN expectRtn, + CSSM_BOOL quiet, + const char *goodUseStr, + const char *badUseStr) +{ + CSSM_CC_HANDLE cryptHand; + CSSM_DATA ptext = {4, (uint8 *)"foo"}; + CSSM_DATA ctext = {0, NULL}; + CSSM_DATA remData = {0, NULL}; + CSSM_RETURN crtn; + CSSM_SIZE bytesEncrypted; + int irtn; + + cryptHand = genCryptHandle(cspHand, opAlg, CSSM_ALGMODE_NONE, CSSM_PADDING_NONE, + key, NULL /* key2 */, NULL /* iv */, 0, 0); + if(cryptHand == 0) { + return testError(quiet); + } + crtn = CSSM_EncryptData(cryptHand, &ptext, 1, &ctext, 1, &bytesEncrypted, &remData); + if(crtn != expectRtn) { + printf("***Testing %s key w/%s during %s:\n", keyAlgStr, goodUseStr, badUseStr); + printf(" CSSM_EncryptData: expect %s\n", cssmErrToStr(expectRtn)); + printf(" CSSM_EncryptData: got %s\n", cssmErrToStr(crtn)); + irtn = testError(quiet); + } + else { + irtn = 0; + } + /* assume no ctext or remdata - OK? */ + CSSM_DeleteContext(cryptHand); + return irtn; +} + +static int badDecrypt( + CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR key, + const char *keyAlgStr, + CSSM_ALGORITHMS opAlg, + CSSM_RETURN expectRtn, + CSSM_BOOL quiet, + const char *goodUseStr, + const char *badUseStr) +{ + CSSM_CC_HANDLE cryptHand; + CSSM_DATA ctext = {4, (uint8 *)"foo"}; + CSSM_DATA ptext = {0, NULL}; + CSSM_DATA remData = {0, NULL}; + CSSM_RETURN crtn; + CSSM_SIZE bytesDecrypted; + int irtn; + + + cryptHand = genCryptHandle(cspHand, opAlg, CSSM_ALGMODE_NONE, CSSM_PADDING_NONE, + key, NULL /* key2 */, NULL /* iv */, 0, 0); + if(cryptHand == 0) { + return testError(quiet); + } + crtn = CSSM_DecryptData(cryptHand, &ctext, 1, &ptext, 1, &bytesDecrypted, &remData); + if(crtn != expectRtn) { + printf("***Testing %s key w/%s during %s:\n", keyAlgStr, goodUseStr, badUseStr); + printf(" CSSM_DecryptData: expect %s\n", cssmErrToStr(expectRtn)); + printf(" CSSM_DecryptData: got %s\n", cssmErrToStr(crtn)); + irtn = testError(quiet); + } + else { + irtn = 0; + } + /* assume no ptext or remdata - OK? */ + CSSM_DeleteContext(cryptHand); + return irtn; +} + +/* + * Given a reference key (any class, any alg), attempt to perform null wrap after + * munging various fields in the header. Every attempt should result in + * CSSMERR_CSP_INVALID_KEY_REFERENCE. + */ +static int badHdrTest( + CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR key, + CSSM_BOOL quiet, + const char *keyAlgStr) +{ + CSSM_KEYHEADER *hdr = &key->KeyHeader; + CSSM_KEYHEADER savedHdr = *hdr; + + hdr->HeaderVersion++; + if(nullWrapTest(cspHand, key, quiet, CSSMERR_CSP_INVALID_KEY_REFERENCE, + keyAlgStr, "Munged hdr(HeaderVersion)")) { + return 1; + } + *hdr = savedHdr; + + hdr->CspId.Data1++; + if(nullWrapTest(cspHand, key, quiet, CSSMERR_CSP_INVALID_KEY_REFERENCE, + keyAlgStr, "Munged hdr(CspId.Data1)")) { + return 1; + } + *hdr = savedHdr; + + /* can't test BlobType for Format, they're known to differ */ + + hdr->AlgorithmId++; + if(nullWrapTest(cspHand, key, quiet, CSSMERR_CSP_INVALID_KEY_REFERENCE, + keyAlgStr, "Munged hdr(AlgorithmId)")) { + return 1; + } + *hdr = savedHdr; + + /* have to come up with valid KeyClass here */ + switch(hdr->KeyClass) { + case CSSM_KEYCLASS_PUBLIC_KEY: + hdr->KeyClass = CSSM_KEYCLASS_PRIVATE_KEY; break; + case CSSM_KEYCLASS_PRIVATE_KEY: + hdr->KeyClass = CSSM_KEYCLASS_SESSION_KEY; break; + case CSSM_KEYCLASS_SESSION_KEY: + hdr->KeyClass = CSSM_KEYCLASS_PUBLIC_KEY; break; + default: + printf("***BRZZAP! badHdrTest needs work\n"); + exit(1); + } + if(nullWrapTest(cspHand, key, quiet, CSSMERR_CSP_INVALID_KEY_REFERENCE, + keyAlgStr, "Munged hdr(KeyClass)")) { + return 1; + } + *hdr = savedHdr; + + hdr->LogicalKeySizeInBits++; + if(nullWrapTest(cspHand, key, quiet, CSSMERR_CSP_INVALID_KEY_REFERENCE, + keyAlgStr, "Munged hdr(LogicalKeySizeInBits)")) { + return 1; + } + *hdr = savedHdr; + + hdr->KeyAttr++; + if(nullWrapTest(cspHand, key, quiet, CSSMERR_CSP_INVALID_KEY_REFERENCE, + keyAlgStr, "Munged hdr(KeyAttr)")) { + return 1; + } + *hdr = savedHdr; + + hdr->StartDate.Day[0]++; + if(nullWrapTest(cspHand, key, quiet, CSSMERR_CSP_INVALID_KEY_REFERENCE, + keyAlgStr, "Munged hdr(StartDate.Day)")) { + return 1; + } + *hdr = savedHdr; + + hdr->EndDate.Year[1]++; + if(nullWrapTest(cspHand, key, quiet, CSSMERR_CSP_INVALID_KEY_REFERENCE, + keyAlgStr, "Munged hdr(EndDate.Year)")) { + return 1; + } + *hdr = savedHdr; + + hdr->WrapAlgorithmId++; + if(nullWrapTest(cspHand, key, quiet, CSSMERR_CSP_INVALID_KEY_REFERENCE, + keyAlgStr, "Munged hdr(WrapAlgorithmId)")) { + return 1; + } + *hdr = savedHdr; + + hdr->WrapMode++; + if(nullWrapTest(cspHand, key, quiet, CSSMERR_CSP_INVALID_KEY_REFERENCE, + keyAlgStr, "Munged hdr(WrapMode)")) { + return 1; + } + *hdr = savedHdr; + + return 0; +} + +/* + * Given some op alg, return a different op alg which is of the same class + * but should not work with an opAlg-related key. + */ +CSSM_ALGORITHMS badOpAlg( + CSSM_ALGORITHMS opAlg) +{ + switch(opAlg) { + /* symmetric block ciphers */ + case CSSM_ALGID_DES: return CSSM_ALGID_3DES_3KEY_EDE; + case CSSM_ALGID_3DES_3KEY_EDE: return CSSM_ALGID_RC2; + case CSSM_ALGID_RC2: return CSSM_ALGID_RC5; + case CSSM_ALGID_RC5: return CSSM_ALGID_AES; + case CSSM_ALGID_AES: return CSSM_ALGID_DES; + + /* symmetric stream ciphers */ + case CSSM_ALGID_ASC: return CSSM_ALGID_RC4; + case CSSM_ALGID_RC4: return CSSM_ALGID_ASC; + + /* asymmetric ciphers */ + case CSSM_ALGID_RSA: return CSSM_ALGID_FEEDEXP; + case CSSM_ALGID_FEEDEXP: return CSSM_ALGID_RSA; + + /* digital signature */ + case CSSM_ALGID_SHA1WithRSA: return CSSM_ALGID_SHA1WithDSA; + case CSSM_ALGID_SHA1WithDSA: return CSSM_ALGID_SHA1WithECDSA; + case CSSM_ALGID_SHA1WithECDSA: return CSSM_ALGID_SHA1WithRSA; + + default: printf("***BRRZAP! badOpAlg needs work.\n"); exit(1); + } + /* NOT REACHED */ + return 0; +} + +/* + * -- Generate symmetric key with specified alg and usage; + * -- Verify that it can't be used for any of the ops specified + * in badOpFlags using goodEncrAlg/goodSignAlg; + * -- Verify that it can't be used for goodOp/badAlg; + * + * Used by symUsageTest(). + * + */ +#define SYM_USAGE_ENABLE 1 + +static int badSymUsage( + CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS keyAlg, // alg of the key + const char *keyAlgStr, + uint32 keySizeInBits, + CSSM_KEYUSE keyUse, // gen key with this usage + CSSM_ALGORITHMS goodEncrAlg, // key is good for this encryption alg + CSSM_ALGORITHMS goodSignAlg, // key is good for this sign alg (may not be used) + unsigned badOpFlags, // array of (OP_DECRYPT,...) + unsigned goodOp, // one good op... + CSSM_ALGORITHMS badAlg, // ..which fails for this alg + CSSM_BOOL quiet, + const char *useStr) +{ + CSSM_KEY symKey; + int irtn; + + if(genSymKey(cspHand, &symKey, keyAlg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_REF, keyUse, CSSM_OK, quiet, CSSM_FALSE, useStr)) { + return 1; + } + #if SYM_USAGE_ENABLE + if(!quiet) { + printf(" ...testing key usage\n"); + } + if(badOpFlags & OP_ENCRYPT) { + irtn = badEncrypt(cspHand, &symKey, keyAlgStr, goodEncrAlg, + CSSMERR_CSP_KEY_USAGE_INCORRECT, quiet, useStr, "ENCRYPT"); + if(irtn) { + goto abort; + } + } + if(badOpFlags & OP_DECRYPT) { + irtn = badDecrypt(cspHand, &symKey, keyAlgStr, goodEncrAlg, + CSSMERR_CSP_KEY_USAGE_INCORRECT, quiet, useStr, "DECRYPT"); + if(irtn) { + goto abort; + } + } + #endif /* SYM_USAGE_ENABLE */ + + /* now do a good op with an incorrect algorithm */ + if(!quiet) { + printf(" ...testing key/algorithm match\n"); + } + if(goodOp & OP_ENCRYPT) { + irtn = badEncrypt(cspHand, &symKey, keyAlgStr, badAlg, + CSSMERR_CSP_ALGID_MISMATCH, quiet, useStr, "ENCRYPT w/bad alg"); + if(irtn) { + goto abort; + } + } + if(goodOp & OP_DECRYPT) { + irtn = badDecrypt(cspHand, &symKey, keyAlgStr, badAlg, + CSSMERR_CSP_ALGID_MISMATCH, quiet, useStr, "DECRYPT w/bad alg"); + if(irtn) { + goto abort; + } + } +abort: + cspFreeKey(cspHand, &symKey); + return irtn; +} + +/* + * Verify symmetric key usage behavior: + * + * gen key with KEYUSE_ENCRYPT + * make sure you can't use it for decrypt + * make sure you can't use it for encrypting with other alg + * gen key with KEYUSE_DECRYPT + * make sure you can't use it for encrypt + * make sure you can't use it for decrypting with other alg + * gen key with KEYUSE_SIGN (mac) + * make sure you can't use it for encrypt or decrypt + * gen key with KEYUSE_VERIFY (mac verify) + * make sure you can't use it for encrypt or decrypt + */ +int symUsageTest( + CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS keyAlg, + const char *keyAlgStr, + CSSM_ALGORITHMS encrAlg, + CSSM_ALGORITHMS signAlg, + uint32 keySizeInBits, + CSSM_BOOL quiet) +{ + if(!quiet) { + printf(" ...testing encrypt-enabled key\n"); + } + if(badSymUsage(cspHand, keyAlg, keyAlgStr, keySizeInBits, CSSM_KEYUSE_ENCRYPT, + encrAlg, signAlg, OP_DECRYPT, OP_ENCRYPT, badOpAlg(encrAlg), + quiet, "ENCRYPT")) { + return 1; + } + if(!quiet) { + printf(" ...testing decrypt-enabled key\n"); + } + if(badSymUsage(cspHand, keyAlg, keyAlgStr, keySizeInBits, CSSM_KEYUSE_DECRYPT, + encrAlg, signAlg, OP_ENCRYPT, OP_DECRYPT, badOpAlg(encrAlg), + quiet, "DECRYPT")) { + return 1; + } + return 0; +} + +/* + * Verify symmetric key attribute behavior: + * + * check that you can not gen a key with { + * CSSM_KEYATTR_ALWAYS_SENSITIVE + * CSSM_KEYATTR_NEVER_EXTRACTABLE + * CSSM_KEYATTR_PERMANENT + * CSSM_KEYATTR_PRIVATE + * CSSM_KEYATTR_RETURN_DATA | !CSSM_KEYATTR_EXTRACTABLE + * CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_SENSITIVE + * CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_RETURN_REF + * } + */ +int symAttrTest( + CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS alg, + const char *keyAlgStr, + uint32 keySizeInBits, + CSSM_BOOL bareCsp, + CSSM_BOOL quiet) +{ + CSSM_KEY key; + + if(!quiet) { + printf(" ...testing key attr\n"); + } + if(bareCsp || CSPDL_ALWAYS_SENSITIVE_CHECK) { + if(genSymKey(cspHand, &key, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_ALWAYS_SENSITIVE, + CSSM_KEYUSE_ANY, CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, + CSSM_TRUE, "ALWAYS_SENSITIVE")) { + return 1; + } + } + if(bareCsp || CSPDL_NEVER_EXTRACTABLE_CHECK) { + if(genSymKey(cspHand, &key, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_NEVER_EXTRACTABLE, + CSSM_KEYUSE_ANY, CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, + CSSM_TRUE, "NEVER_EXTRACTABLE")) { + return 1; + } + } + /* + * bare CSP : CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK + * CSPDL : CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE + */ + if(genSymKey(cspHand, &key, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT, + CSSM_KEYUSE_ANY, + bareCsp ? CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK : + CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE, + quiet, + CSSM_TRUE, "PERMANENT")) { + return 1; + } + if(genSymKey(cspHand, &key, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PRIVATE, + CSSM_KEYUSE_ANY, CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK, quiet, + CSSM_TRUE, "PRIVATE")) { + return 1; + } + if(bareCsp) { + /* CSPDL doesn't support RETURN_DATA */ + if(genSymKey(cspHand, &key, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_DATA /* and !extractable */, + CSSM_KEYUSE_ANY, + CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, + CSSM_TRUE, "RETURN_DATA | !EXTRACTABLE")) { + return 1; + } + if(genSymKey(cspHand, &key, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_SENSITIVE, + CSSM_KEYUSE_ANY, CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, + CSSM_TRUE, "RETURN_DATA | SENSITIVE")) { + return 1; + } + if(genSymKey(cspHand, &key, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_RETURN_REF, + CSSM_KEYUSE_ANY, CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, + CSSM_TRUE, "RETURN_DATA | RETURN_REF")) { + return 1; + } + } + return 0; +} + +/* + * Verify proper symmetric key null wrap operation. + * + * gen ref key, CSSM_KEYATTR_SENSITIVE, vfy you can't do null wrap; + * gen ref key, !CSSM_KEYATTR_EXTRACTABLE, vfy you can't do null wrap; + */ +int symNullWrapTest( + CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS alg, + const char *keyAlgStr, + uint32 keySizeInBits, + CSSM_BOOL quiet) +{ + CSSM_KEY key; + + if(!quiet) { + printf(" ...testing access to inaccessible key bits via NULL wrap\n"); + } + + /* gen ref key, CSSM_KEYATTR_SENSITIVE, vfy you can't do null wrap */ + if(genSymKey(cspHand, &key, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE, + CSSM_KEYUSE_ANY, CSSM_OK, quiet, + CSSM_FALSE, "SENSITIVE | RETURN_REF")) { + return 1; + } + if(nullWrapTest(cspHand, &key, quiet, CSSMERR_CSP_INVALID_KEYATTR_MASK, + keyAlgStr, "KEYATTR_SENSITIVE")) { + return 1; + } + cspFreeKey(cspHand, &key); + + /* gen ref key, !CSSM_KEYATTR_EXTRACTABLE, vfy you can't do null wrap */ + if(genSymKey(cspHand, &key, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_REF /* !CSSM_KEYATTR_EXTRACTABLE */, + CSSM_KEYUSE_ANY, CSSM_OK, quiet, + CSSM_FALSE, "!EXTRACTABLE | RETURN_REF")) { + return 1; + } + if(nullWrapTest(cspHand, &key, quiet, CSSMERR_CSP_INVALID_KEYATTR_MASK, + keyAlgStr, "!EXTRACTABLE")) { + return 1; + } + cspFreeKey(cspHand, &key); + + return 0; +} + +/* + * Verify proper symmetric key wrap !EXTRACTABLE handling. + * + * Gen unwrapped ref key, !CSSM_KEYATTR_EXTRACTABLE; + * Gen wrapping key - a simple DES key; + * vfy you can't wrap unwrappedKey with wrappingKey; + */ +int symBadWrapTest( + CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS alg, + const char *keyAlgStr, + uint32 keySizeInBits, + CSSM_BOOL quiet) +{ + CSSM_KEY unwrappedKey; + + if(!quiet) { + printf(" ...testing access to !EXTRACTABLE key bits via PKCS7 wrap\n"); + } + + /* gen ref key, CSSM_KEYATTR_SENSITIVE, !EXTRACTABLE */ + if(genSymKey(cspHand, &unwrappedKey, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE, + CSSM_KEYUSE_ANY, CSSM_OK, quiet, + CSSM_FALSE, "SENSITIVE | RETURN_REF")) { + return 1; + } + if(badWrapTest(cspHand, + &unwrappedKey, + CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7, + quiet, keyAlgStr, + "!EXTRACTABLE wrap")) { + return 1; + } + cspFreeKey(cspHand, &unwrappedKey); + return 0; +} + +/* + * Verify proper asymmetric key wrap !EXTRACTABLE handling. + * + * Gen unwrapped ref key, !CSSM_KEYATTR_EXTRACTABLE; + * Gen wrapping key - a simple DES key; + * vfy you can't wrap unwrappedKey with wrappingKey; + */ +int asymBadWrapTest( + CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS alg, + const char *keyAlgStr, + uint32 keySizeInBits, + CSSM_BOOL quiet) +{ + CSSM_KEY pubKey; + CSSM_KEY privKey; + + if(!quiet) { + printf(" ...testing access to !EXTRACTABLE key bits via CUSTOM wrap\n"); + } + + /* gen ref key, CSSM_KEYATTR_SENSITIVE, !EXTRACTABLE */ + if(genKeyPair(cspHand, alg, keyAlgStr, keySizeInBits, + &pubKey, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE, + CSSM_KEYUSE_ANY, + &privKey, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE, + CSSM_KEYUSE_ANY, + CSSM_OK, quiet, CSSM_FALSE, "RETURN_REF | SENSITIVE")) { + return 1; + } + if(badWrapTest(cspHand, + &privKey, + CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM, + quiet, keyAlgStr, + "!EXTRACTABLE wrap")) { + return 1; + } + cspFreeKey(cspHand, &privKey); + cspFreeKey(cspHand, &pubKey); + return 0; +} + +/* + * Generate a ref key, munge various fields in the header, verify that attempts + * to use the munged key result in CSSMERR_CSP_INVALID_KEY_REFERENCE. + */ +int symHeaderTest( + CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS keyAlg, + const char *keyAlgStr, + CSSM_ALGORITHMS encrAlg, + CSSM_ALGORITHMS signAlg, + uint32 keySizeInBits, + CSSM_BOOL quiet) +{ + CSSM_KEY key; + + if(!quiet) { + printf(" ...testing munged ref key header\n"); + } + if(genSymKey(cspHand, &key, keyAlg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE, + CSSM_KEYUSE_ANY, CSSM_OK, quiet, + CSSM_FALSE, "RETURN_REF")) { + return 1; + } + if(badHdrTest(cspHand, &key, quiet, keyAlgStr)) { + return 1; + } + cspFreeKey(cspHand, &key); + return 0; +} + +/* + * Generate key pair, specified pub key attr and expected result, standard + * "good" priv key attr. Used by asymAttrTest(). + */ +static int pubKeyAttrTest( + CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS alg, + const char *keyAlgStr, + uint32 keySizeInBits, + CSSM_KEYATTR_FLAGS pubKeyAttr, + CSSM_RETURN expectRtn, + CSSM_BOOL quiet, + const char *testStr) +{ + CSSM_KEY pubKey; + CSSM_KEY privKey; + + return genKeyPair(cspHand, alg, keyAlgStr, keySizeInBits, + &pubKey, pubKeyAttr, CSSM_KEYUSE_ANY, + &privKey, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE, CSSM_KEYUSE_ANY, + expectRtn, quiet, CSSM_TRUE, testStr); +} + +/* + * Generate key pair, specified priv key attr and expected result, standard + * "good" pub key attr. Used by asymAttrTest(). + */ +static int privKeyAttrTest( + CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS alg, + const char *keyAlgStr, + uint32 keySizeInBits, + CSSM_KEYATTR_FLAGS privKeyAttr, + CSSM_RETURN expectRtn, + CSSM_BOOL quiet, + const char *testStr) +{ + CSSM_KEY pubKey; + CSSM_KEY privKey; + + return genKeyPair(cspHand, alg, keyAlgStr, keySizeInBits, + &pubKey, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE, + CSSM_KEYUSE_ANY, + &privKey, privKeyAttr, CSSM_KEYUSE_ANY, + expectRtn, quiet, CSSM_TRUE, testStr); +} + +/* + * Verify asymmetric key attribute behavior. + * + * check that you can't gen pub key with { + * CSSM_KEYATTR_ALWAYS_SENSITIVE + * CSSM_KEYATTR_NEVER_EXTRACTABLE + * CSSM_KEYATTR_PERMANENT + * CSSM_KEYATTR_PRIVATE + * CSSM_KEYATTR_RETURN_DATA | !CSSM_KEYATTR_EXTRACTABLE + * CSSM_KEYATTR_RETURN_REF | !CSSM_KEYATTR_EXTRACTABLE + * CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_SENSITIVE + * CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE + * } + * check that you can't gen priv key with { + * CSSM_KEYATTR_ALWAYS_SENSITIVE + * CSSM_KEYATTR_NEVER_EXTRACTABLE + * CSSM_KEYATTR_PERMANENT + * CSSM_KEYATTR_PRIVATE + * CSSM_KEYATTR_RETURN_DATA | !CSSM_KEYATTR_EXTRACTABLE + * CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_SENSITIVE + * } + */ +static int asymAttrTest( + CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS alg, + const char *keyAlgStr, + uint32 keySizeInBits, + CSSM_BOOL bareCsp, + CSSM_BOOL quiet) +{ + #if CSPDL_ALL_KEYS_ARE_PERMANENT + printf(" ...SKIPING asymAttrTest due to Radar 3732910\n"); + return 0; + #endif + if(!quiet) { + printf(" ...testing key attr\n"); + } + if(bareCsp || CSPDL_ALWAYS_SENSITIVE_CHECK) { + if(pubKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_ALWAYS_SENSITIVE, + CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, "ALWAYS_SENSITIVE pub")) { + return 1; + } + } + if(bareCsp || CSPDL_NEVER_EXTRACTABLE_CHECK) { + if(pubKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_NEVER_EXTRACTABLE, + CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, "NEVER_EXTRACTABLE pub")) { + return 1; + } + } + if(pubKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT | + CSSM_KEYATTR_EXTRACTABLE, + bareCsp ? + /* bare CSP - permanent is checked first, this is the error */ + CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK : + /* CSPDL - SS strips off permanent, then does key gen (so we'd + * better specify EXTRACTABLE!), *then* checks for DLDB. */ + CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE, + quiet, "PERMANENT pub")) { + return 1; + } + if(pubKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PRIVATE | + CSSM_KEYATTR_EXTRACTABLE, + CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK, quiet, "PRIVATE pub")) { + return 1; + } + if(bareCsp) { + /* CSPDL doesn't support RETURN_DATA */ + if(pubKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_DATA /* | !CSSM_KEYATTR_EXTRACTABLE */, + CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, + "RETURN_DATA | !EXTRACTABLE pub")) { + return 1; + } + } + /* pub key should always be extractable */ + if(pubKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_REF /* | !CSSM_KEYATTR_EXTRACTABLE */, + CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, + "RETURN_REF | !EXTRACTABLE pub")) { + return 1; + } + /* pub keys can't be sensitive */ + if(bareCsp) { + /* CSPDL doesn't support RETURN_DATA */ + if(pubKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_SENSITIVE, + CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, "RETURN_DATA | SENSITIVE pub")) { + return 1; + } + } + if(pubKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE, + CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, "RETURN_REF | !SENSITIVE pub")) { + return 1; + } + + /* priv key attr tests */ + if(bareCsp || CSPDL_ALWAYS_SENSITIVE_CHECK) { + if(privKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_ALWAYS_SENSITIVE, + CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, "ALWAYS_SENSITIVE priv")) { + return 1; + } + } + if(bareCsp || CSPDL_NEVER_EXTRACTABLE_CHECK) { + if(privKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_NEVER_EXTRACTABLE, + CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, "NEVER_EXTRACTABLE priv")) { + return 1; + } + } + if(privKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT, + bareCsp ? CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK : + CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE, + quiet, "PERMANENT priv")) { + return 1; + } + if(privKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PRIVATE, + CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK, quiet, "PRIVATE priv")) { + return 1; + } + if(bareCsp) { + /* CSPDL doesn't support RETURN_DATA */ + if(privKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_DATA /* | CSSM_KEYATTR_EXTRACTABLE */, + CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, + "RETURN_DATA | !EXTRACTABLE priv")) { + return 1; + } + if(privKeyAttrTest(cspHand, alg, keyAlgStr, keySizeInBits, + CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_SENSITIVE, + CSSMERR_CSP_INVALID_KEYATTR_MASK, quiet, "RETURN_DATA | SENSITIVE priv")) { + return 1; + } + } + return 0; +} + +/* + * Verify asymmetric key null wrap behavior: + * gen ref key, CSSM_KEYATTR_SENSITIVE, vfy you can't do null wrap; + * gen ref key, !CSSM_KEYATTR_EXTRACTABLE, vfy you can't do null wrap; + */ +static int asymNullWrapTest( + CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS alg, + const char *keyAlgStr, + uint32 keySizeInBits, + CSSM_BOOL quiet) +{ + CSSM_KEY pubKey; + CSSM_KEY privKey; + + if(!quiet) { + printf(" ...testing access to inaccessible key bits via NULL wrap\n"); + } + /* gen priv ref key, CSSM_KEYATTR_SENSITIVE, vfy you can't do null wrap */ + if(genKeyPair(cspHand, alg, keyAlgStr, keySizeInBits, + &pubKey, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE, + CSSM_KEYUSE_ANY, + &privKey, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE, + CSSM_KEYUSE_ANY, + CSSM_OK, quiet, CSSM_FALSE, "RETURN_REF | SENSITIVE")) { + return 1; + } + if(nullWrapTest(cspHand, &privKey, quiet, CSSMERR_CSP_INVALID_KEYATTR_MASK, + keyAlgStr, "SENSITIVE")) { + return 1; + } + cspFreeKey(cspHand, &privKey); + cspFreeKey(cspHand, &pubKey); + + /* gen priv ref key, !CSSM_KEYATTR_EXTRACTABLE, vfy you can't do null wrap */ + if(genKeyPair(cspHand, alg, keyAlgStr, keySizeInBits, + &pubKey, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE, + CSSM_KEYUSE_ANY, + &privKey, CSSM_KEYATTR_RETURN_REF /* | !EXTRACTABLE */, CSSM_KEYUSE_ANY, + CSSM_OK, quiet, CSSM_FALSE, "RETURN_REF | !EXTRACTABLE")) { + return 1; + } + if(nullWrapTest(cspHand, &privKey, quiet, CSSMERR_CSP_INVALID_KEYATTR_MASK, + keyAlgStr, "!EXTRACTABLE")) { + return 1; + } + cspFreeKey(cspHand, &privKey); + cspFreeKey(cspHand, &pubKey); + return 0; +} + +/* + * Generate public and private ref keys, munge various fields in the header, + * verify that attempts to use the munged key result in + * CSSMERR_CSP_INVALID_KEY_REFERENCE. + */ +int asymHeaderTest( + CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS keyAlg, + const char *keyAlgStr, + CSSM_ALGORITHMS encrAlg, + CSSM_ALGORITHMS signAlg, + uint32 keySizeInBits, + CSSM_BOOL quiet) +{ + CSSM_KEY privKey; + CSSM_KEY pubKey; + + if(!quiet) { + printf(" ...testing munged ref key header\n"); + } + if(genKeyPair(cspHand, keyAlg, keyAlgStr, keySizeInBits, + &pubKey, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE, + CSSM_KEYUSE_ANY, + &privKey, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE, + CSSM_KEYUSE_ANY, + CSSM_OK, quiet, CSSM_FALSE, "RETURN_REF")) { + return 1; + } + if(badHdrTest(cspHand, &privKey, quiet, keyAlgStr)) { + return 1; + } + if(badHdrTest(cspHand, &pubKey, quiet, keyAlgStr)) { + return 1; + } + cspFreeKey(cspHand, &privKey); + cspFreeKey(cspHand, &pubKey); + return 0; +} + +/* map one of our private privAlgs (ALG_DES, etc.) to associated CSSM info. */ +void privAlgToCssm( + privAlg palg, + CSSM_ALGORITHMS *keyAlg, + CSSM_ALGORITHMS *signAlg, // CSSM_ALGID_NONE means incapable (e.g., DES) + CSSM_ALGORITHMS *encrAlg, // CSSM_ALGID_NONE means incapable (e.g., DSA) + uint32 *keySizeInBits, + const char **keyAlgStr) +{ + *signAlg = *encrAlg = CSSM_ALGID_NONE; // default + switch(palg) { + case ALG_ASC: + *encrAlg = *keyAlg = CSSM_ALGID_ASC; + *keySizeInBits = CSP_ASC_KEY_SIZE_DEFAULT; + *keyAlgStr = "ASC"; + break; + case ALG_DES: + *encrAlg = *keyAlg = CSSM_ALGID_DES; + *keySizeInBits = CSP_DES_KEY_SIZE_DEFAULT; + *keyAlgStr = "DES"; + break; + case ALG_3DES: + *encrAlg = CSSM_ALGID_3DES_3KEY_EDE; + *keyAlg = CSSM_ALGID_3DES_3KEY; + *keySizeInBits = CSP_DES3_KEY_SIZE_DEFAULT; + *keyAlgStr = "3DES"; + break; + case ALG_RC2: + *encrAlg = *keyAlg = CSSM_ALGID_RC2; + *keySizeInBits = CSP_RC2_KEY_SIZE_DEFAULT; + *keyAlgStr = "RC2"; + break; + case ALG_RC4: + *encrAlg = *keyAlg = CSSM_ALGID_RC4; + *keySizeInBits = CSP_RC4_KEY_SIZE_DEFAULT; + *keyAlgStr = "RC4"; + break; + case ALG_RC5: + *encrAlg = *keyAlg = CSSM_ALGID_RC5; + *keySizeInBits = CSP_RC5_KEY_SIZE_DEFAULT; + *keyAlgStr = "RC5"; + break; + case ALG_AES: + *encrAlg = *keyAlg = CSSM_ALGID_AES; + *keySizeInBits = CSP_AES_KEY_SIZE_DEFAULT; + *keyAlgStr = "AES"; + break; + case ALG_RSA: + *keyAlg = CSSM_ALGID_RSA; + *encrAlg = CSSM_ALGID_RSA; + *signAlg = CSSM_ALGID_SHA1WithRSA; + *keySizeInBits = CSP_RSA_KEY_SIZE_DEFAULT; + *keyAlgStr = "RSA"; + break; + case ALG_DSA: + *keyAlg = CSSM_ALGID_DSA; + *signAlg = CSSM_ALGID_SHA1WithDSA; + *keySizeInBits = CSP_DSA_KEY_SIZE_DEFAULT; + *keyAlgStr = "DSA"; + break; + case ALG_FEE: + *keyAlg = CSSM_ALGID_FEE; + *signAlg = CSSM_ALGID_SHA1WithECDSA; + *encrAlg = CSSM_ALGID_FEEDEXP; + *keySizeInBits = CSP_FEE_KEY_SIZE_DEFAULT; + *keyAlgStr = "FEE"; + break; + case ALG_ECDSA: + *keyAlg = CSSM_ALGID_ECDSA; + *signAlg = CSSM_ALGID_SHA1WithECDSA; + *keySizeInBits = CSP_ECDSA_KEY_SIZE_DEFAULT; + *keyAlgStr = "ECDSA"; + break; + default: + printf("***BRRZAP! privAlgToCssm needs work\n"); + exit(1); + } + return; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + CSSM_CSP_HANDLE cspHand; + CSSM_ALGORITHMS keyAlg; // CSSM_ALGID_xxx of the key + CSSM_ALGORITHMS signAlg; // CSSM_ALGID_xxx of the associated signing op + CSSM_ALGORITHMS encrAlg; // CSSM_ALGID_xxx of the associated encrypt op + privAlg palg; + uint32 keySizeInBits; + int rtn; + int i; + const char *keyAlgStr; + + /* + * User-spec'd params + */ + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL doSym = CSSM_TRUE; + CSSM_BOOL doAsym = CSSM_TRUE; + CSSM_BOOL bareCsp = CSSM_TRUE; + + for(arg=1; arg +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "cspdlTesting.h" + +#define USAGE_NAME "noUsage" +#define USAGE_NAME_LEN (strlen(USAGE_NAME)) + +/* + * HMAC/SHA1 can not do multiple updates with BSAFE (though the CSP's current + * internal implementation can.) + * Fixed in Puma; the bug was in BSAFE. + */ +#define HMACSHA_MULTI_UPDATES 1 + +/* + * Defaults. + */ +#define LOOPS_DEF 10 +#define MIN_EXP 2 /* for data size 10**exp */ +#define DEFAULT_MAX_EXP 2 +#define MAX_EXP 5 +#define INCR_DEFAULT 0 /* munge every incr bytes - zero means + * "adjust per ptext size" */ + +/* + * Enumerate algs our own way to allow iteration. + */ +#define ALG_SHA1HMAC 1 +#define ALG_MD5HMAC 2 +#define ALG_FIRST ALG_SHA1HMAC +#define ALG_LAST ALG_MD5HMAC +#define MAX_DATA_SIZE (100000 + 100) /* bytes */ + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" n=minExp (default=%d)\n", MIN_EXP); + printf(" x=maxExp (default=%d, max=%d)\n", DEFAULT_MAX_EXP, MAX_EXP); + printf(" i=increment (default=%d)\n", INCR_DEFAULT); + printf(" r(eference keys only)\n"); + printf(" m (CSM mallocs MAC)\n"); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +#define LOG_FREQ 20 +static int doTest(CSSM_CSP_HANDLE cspHand, + uint32 macAlg, // CSSM_ALGID_xxx mac algorithm + CSSM_DATA_PTR ptext, + CSSM_BOOL verbose, + CSSM_BOOL quiet, + unsigned keySize, + unsigned incr, + CSSM_BOOL stagedGen, + CSSM_BOOL stagedVerify, + CSSM_BOOL mallocMac, + CSSM_BOOL refKey) +{ + CSSM_KEY_PTR symmKey; + CSSM_DATA mac = {0, NULL}; + unsigned length; + unsigned byte; + unsigned char *data; + unsigned char origData; + unsigned char bits; + int rtn = 0; + CSSM_RETURN crtn; + uint32 keyGenAlg; + unsigned loop = 0; + + switch(macAlg) { + case CSSM_ALGID_SHA1HMAC: + keyGenAlg = CSSM_ALGID_SHA1HMAC; + break; + case CSSM_ALGID_MD5HMAC: + keyGenAlg = CSSM_ALGID_MD5HMAC; + break; + default: + printf("bogus algorithm\n"); + return 1; + } + symmKey = cspGenSymKey(cspHand, + keyGenAlg, + "noLabel", + 7, + CSSM_KEYUSE_SIGN | CSSM_KEYUSE_VERIFY, + keySize, + refKey); + if(symmKey == NULL) { + rtn = testError(quiet); + goto abort; + } + if(stagedGen) { + crtn = cspStagedGenMac(cspHand, + macAlg, + symmKey, + ptext, + mallocMac, + CSSM_TRUE, // multi + &mac); + } + else { + crtn = cspGenMac(cspHand, + macAlg, + symmKey, + ptext, + &mac); + } + if(crtn) { + rtn = 1; + goto abort; + } + if(stagedVerify) { + crtn = cspStagedMacVerify(cspHand, + macAlg, + symmKey, + ptext, + &mac, + CSSM_TRUE, // multi + CSSM_OK); // expectedResult + } + else { + crtn = cspMacVerify(cspHand, + macAlg, + symmKey, + ptext, + &mac, + CSSM_OK); + } + if(crtn) { + printf("**Unexpected BAD MAC\n"); + return testError(quiet); + } + data = (unsigned char *)ptext->Data; + length = ptext->Length; + for(byte=0; byte MAX_EXP) { + usage(argv); + } + break; + case 'i': + incr = atoi(&argp[2]); + break; + case 'p': + pauseInterval = atoi(&argp[2]); + break; + case 'D': + bareCsp = CSSM_FALSE; + #if CSPDL_ALL_KEYS_ARE_REF + refKeysOnly = CSSM_TRUE; + #endif + break; + case 'r': + refKeysOnly = CSSM_TRUE; + break; + case 'm': + cspMallocs = CSSM_TRUE; + break; + case 'v': + verbose = CSSM_TRUE; + break; + case 'q': + quiet = CSSM_TRUE; + break; + case 'h': + default: + usage(argv); + } + } + ptext.Data = (uint8 *)CSSM_MALLOC(MAX_DATA_SIZE); + /* length set in test loop */ + if(ptext.Data == NULL) { + printf("Insufficient heap\n"); + exit(1); + } + printf("Starting badmac; args: "); + for(i=1; i +#include +#include +#include +#include +#include "cspwrap.h" +#include +#include "cspwrap.h" +#include "common.h" +#include "cspdlTesting.h" + +#define USAGE_NAME "noUsage" +#define USAGE_NAME_LEN (strlen(USAGE_NAME)) + +/* + * Defaults. + */ +#define LOOPS_DEF 10 +#define MIN_EXP 2 /* for data size 10**exp */ +#define DEFAULT_MAX_EXP 2 +#define MAX_EXP 5 +#define INCR_DEFAULT 0 /* munge every incr bytes - zero means + * "adjust per ptext size" */ +#define FEE_PASSWD_LEN 32 /* private data length in bytes, FEE only */ + + +/* + * Enumerate algs our own way to allow iteration. + */ +#define ALG_FEE_MD5 1 +#define ALG_FEE_SHA1 2 +#define ALG_ECDSA 3 +#define ALG_ANSI_ECDSA 4 +#define ALG_RSA 5 +#define ALG_DSA 6 +#define ALG_RAW_RSA_SHA1 7 +#define ALG_RAW_DSA_SHA1 8 +#define ALG_RSA_SHA224 9 +#define ALG_RSA_SHA256 10 +#define ALG_RSA_SHA384 11 +#define ALG_RSA_SHA512 12 +#define ALG_ECDSA_SHA256 13 +#define ALG_ECDSA_SHA384 14 +#define ALG_ECDSA_SHA512 15 + + +#define ALG_FIRST ALG_FEE_MD5 +#define ALG_LAST ALG_ECDSA_SHA512 +#define MAX_DATA_SIZE (100000 + 100) /* bytes */ + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" a=algorithm (f=FEE/MD5; F=FEE/SHA1; e=ECDSA; r=RSA; d=DSA; R=raw RSA; \n"); + printf(" D=raw DSA; 2=RSA/SHA224; 6=RSA/SHA256; 3=RSA/SHA384; 5=RSA/SHA512; default=all)\n"); + printf(" E=ECDSA/ANSI; 7=ECDSA/SHA256; 8=ECDSA/SHA384; 9=ECDSA/512; default=all\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" n=minExp (default=%d)\n", MIN_EXP); + printf(" x=maxExp (default=%d, max=%d)\n", DEFAULT_MAX_EXP, MAX_EXP); + printf(" k=keySize (r=random; default fixed per algorithm)\n"); + printf(" i=increment (default=%d)\n", INCR_DEFAULT); + printf(" R(ef keys only)\n"); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" P=primeType (m=Mersenne, f=FEE, g=general; FEE only)\n"); + printf(" C=curveType (m=Montgomery, w=Weierstrass, g=general; FEE only)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +#define LOG_FREQ 20 + +static int doTest(CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS sigAlg, // CSSM_ALGID_xxx signature algorithm + CSSM_ALGORITHMS keyGenAlg, + CSSM_DATA_PTR ptext, + CSSM_BOOL verbose, + CSSM_BOOL quiet, + CSSM_BOOL randKeySize, + uint32 keySize, + unsigned incr, + CSSM_BOOL pubIsRef, + CSSM_KEYBLOB_FORMAT pubFormat, + CSSM_BOOL privIsRef, + CSSM_KEYBLOB_FORMAT privFormat, + CSSM_BOOL stagedSign, + CSSM_BOOL stagedVerify, + CSSM_BOOL genSeed, + uint32 primeType, // CSSM_FEE_PRIME_TYPE_xxx, FEE only + uint32 curveType, // CSSM_FEE_CURVE_TYPE_xxx, FEE only + CSSM_BOOL genParams) // DSA only +{ + CSSM_KEY pubKey; + CSSM_KEY privKey; + CSSM_DATA sig = {0, NULL}; + unsigned length; + unsigned byte; + unsigned char *data; + unsigned char origData; + unsigned char bits; + int rtn = 0; + CSSM_RETURN crtn; + unsigned loop = 0; + + if(keyGenAlg == CSSM_ALGID_FEE) { + uint8 passwd[FEE_PASSWD_LEN]; + CSSM_DATA pwdData = {FEE_PASSWD_LEN, passwd}; + CSSM_DATA_PTR pwdDataPtr; + + if(randKeySize) { + /* random params for this op */ + randFeeKeyParams(sigAlg, &keySize, &primeType, &curveType); + } + /* else use caller's size, primeType, curveType */ + + if(genSeed) { + simpleGenData(&pwdData, FEE_PASSWD_LEN, FEE_PASSWD_LEN); + pwdDataPtr = &pwdData; + } + else { + pwdDataPtr = NULL; + } + if(verbose) { + printf(" key size %u primeType %s curveType %s\n", + (unsigned)keySize, primeTypeStr(primeType), curveTypeStr(curveType)); + } /* verbose */ + rtn = cspGenFEEKeyPair(cspHand, + USAGE_NAME, + USAGE_NAME_LEN, + keySize, + primeType, + curveType, + &pubKey, + pubIsRef, + CSSM_KEYUSE_VERIFY, + pubFormat, + &privKey, + privIsRef, + CSSM_KEYUSE_SIGN, + privFormat, + pwdDataPtr); + } /* FEE */ + else { + if(randKeySize) { + keySize = randKeySizeBits(keyGenAlg, OT_Sign); + } + if(verbose) { + printf(" key size %u\n", (unsigned)keySize); + } + if(keyGenAlg == CSSM_ALGID_DSA) { + rtn = cspGenDSAKeyPair(cspHand, + USAGE_NAME, + USAGE_NAME_LEN, + keySize, + &pubKey, + pubIsRef, + CSSM_KEYUSE_VERIFY, + pubFormat, + &privKey, + privIsRef, + CSSM_KEYUSE_SIGN, + privFormat, + genParams, + NULL); + } + else { + rtn = cspGenKeyPair(cspHand, + keyGenAlg, + USAGE_NAME, + USAGE_NAME_LEN, + keySize, + &pubKey, + pubIsRef, + CSSM_KEYUSE_VERIFY, + pubFormat, + &privKey, + privIsRef, + CSSM_KEYUSE_SIGN, + privFormat, + genSeed); + } + } + if(rtn) { + rtn = testError(quiet); + goto abort; + } + if(stagedSign) { + crtn = cspStagedSign(cspHand, + sigAlg, + &privKey, + ptext, + CSSM_TRUE, // multi + &sig); + } + else { + crtn = cspSign(cspHand, + sigAlg, + &privKey, + ptext, + &sig); + } + if(crtn) { + rtn = 1; + goto abort; + } + if(stagedVerify) { + crtn = cspStagedSigVerify(cspHand, + sigAlg, + &pubKey, + ptext, + &sig, + CSSM_TRUE, // multi + CSSM_OK); + } + else { + crtn = cspSigVerify(cspHand, + sigAlg, + &pubKey, + ptext, + &sig, + CSSM_OK); + } + if(crtn) { + printf("**Unexpected BAD signature\n"); + return testError(quiet); + } + data = (unsigned char *)ptext->Data; + length = ptext->Length; + for(byte=0; byte MAX_EXP) { + usage(argv); + } + break; + case 'k': + if(argp[2] == 'r') { + randKeySize = CSSM_TRUE; + } + else { + keySizeInBits = atoi(&argp[2]); + } + break; + case 'i': + incr = atoi(&argp[2]); + break; + case 'p': + pauseInterval = atoi(&argp[2]); + break; + case 'R': + refKeysOnly = CSSM_TRUE; + break; + case 'C': + switch(argp[2]) { + case 'm': + curveType = CSSM_FEE_CURVE_TYPE_MONTGOMERY; + break; + case 'w': + curveType = CSSM_FEE_CURVE_TYPE_WEIERSTRASS; + break; + default: + usage(argv); + } + break; + case 'P': + switch(argp[2]) { + case 'm': + primeType = CSSM_FEE_PRIME_TYPE_MERSENNE; + break; + case 'f': + primeType = CSSM_FEE_PRIME_TYPE_FEE; + break; + case 'g': + primeType = CSSM_FEE_PRIME_TYPE_GENERAL; + break; + default: + usage(argv); + } + break; + case 'D': + bareCsp = CSSM_FALSE; + #if CSPDL_ALL_KEYS_ARE_REF + refKeysOnly = CSSM_TRUE; + #endif + break; + case 'v': + verbose = CSSM_TRUE; + break; + case 'q': + quiet = CSSM_TRUE; + break; + case 'h': + default: + usage(argv); + } + } + ptext.Data = (uint8 *)CSSM_MALLOC(MAX_DATA_SIZE); + /* length set in test loop */ + if(ptext.Data == NULL) { + printf("Insufficient heap\n"); + exit(1); + } + printf("Starting badsig; args: "); + for(i=1; i +#include +#include +#include +#include + +static void report( + const char *name, + CCOperation op, + CCAlgorithm alg, + size_t definedSize) +{ + char key[4]; + size_t cryptorLength = 0; + CCCryptorStatus crtn; + CCCryptorRef cryptorRef; + char buf[1]; + + crtn = CCCryptorCreateFromData(op, alg, 0, key, 4, NULL, + buf, 1, &cryptorRef, &cryptorLength); + switch(crtn) { + case kCCSuccess: + printf("***Unuexpected success on CCCryptorCreate()\n"); + return; + case kCCBufferTooSmall: + break; + default: + printf("***Unexpected result on CCCryptorCreate: expect %d got %d\n", + (int)kCCBufferTooSmall, (int)crtn); + return; + } + printf("%s : %lu bytes\n", name, (unsigned long)cryptorLength); + if(definedSize < cryptorLength) { + printf("***Defined context size (%u) is less than reported!\n", + (unsigned)definedSize); + } +} + +int main(int argc, char **argv) +{ + report("kCCAlgorithmAES128 ", kCCEncrypt, kCCAlgorithmAES128, kCCContextSizeAES128); + report("kCCAlgorithmDES ", kCCEncrypt, kCCAlgorithmDES, kCCContextSizeDES); + report("kCCAlgorithm3DES ", kCCEncrypt, kCCAlgorithm3DES, kCCContextSize3DES); + report("kCCAlgorithmCAST ", kCCEncrypt, kCCAlgorithmCAST, kCCContextSizeCAST); + report("kCCAlgorithmRC4 ", kCCEncrypt, kCCAlgorithmRC4, kCCContextSizeRC4); + return 0; +} + +/* + +sizeof(CCCryptor) = 24 including the spiCtx[] array +sizeof(struct _CCCryptContext) = 60 including algCtx[] +sizeof(DES_key_schedule) = 128 +sizeof(DES3_Schedule) = 384 +sizeof(GAesKey) = 516 +sizeof(_ccHmacContext) = 180 + +*/ diff --git a/SecurityTests/cspxutils/ccHmacClone/Makefile b/SecurityTests/cspxutils/ccHmacClone/Makefile new file mode 100644 index 00000000..34f91f91 --- /dev/null +++ b/SecurityTests/cspxutils/ccHmacClone/Makefile @@ -0,0 +1,60 @@ +# name of executable to build +EXECUTABLE=ccHmacClone +# C++ source (with .cpp extension) +CPSOURCE= ccHmacClone.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +#PROJ_LIBS= -lcommonCrypto -lcrypto +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= -I$(LOCAL_BUILD)/include + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= -F/System/Library/PrivateFrameworks + +# +# Optional link flags (using cc, not ld) +# +#PROJ_LDFLAGS= -lMallocDebug -lBSafe +# +# this is for linking against a custom libSystem...this is where it goes. +# You also need to do a setenv DYLD_LIBRARY_PATH /tmp/System/Debug to run. +#PROJ_LDFLAGS= -L/tmp/System/Debug +PROJ_LDFLAGS= + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/ccHmacClone/ccHmacClone.cpp b/SecurityTests/cspxutils/ccHmacClone/ccHmacClone.cpp new file mode 100644 index 00000000..f63fd13a --- /dev/null +++ b/SecurityTests/cspxutils/ccHmacClone/ccHmacClone.cpp @@ -0,0 +1,422 @@ +/* + * ccHmacClone - test CommonCrypto's clone context for HMAC. + * + * Written 3/30/2006 by Doug Mitchell. + */ + +#include +#include +#include +#include "common.h" +#include +#include + +/* + * Defaults. + */ +#define LOOPS_DEF 200 + +#define MIN_DATA_SIZE 8 +#define MAX_DATA_SIZE 10000 /* bytes */ +#define MIN_KEY_SIZE 1 +#define MAX_KEY_SIZE 256 /* bytes */ +#define LOOP_NOTIFY 20 + +/* + * Enumerate algs our own way to allow iteration. + */ +typedef enum { + ALG_MD5 = 1, + ALG_SHA1, + ALG_SHA224, + ALG_SHA256, + ALG_SHA384, + ALG_SHA512, +} HmacAlg; +#define ALG_FIRST ALG_MD5 +#define ALG_LAST ALG_SHA512 + +#define LOG_SIZE 0 +#if LOG_SIZE +#define logSize(s) printf s +#else +#define logSize(s) +#endif + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" a=algorithm (5=MD5; s=SHA1; 4=SHA224; 2=SHA256; 3=SHA384; 1=SHA512; default=all)\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" k=keySizeInBytes\n"); + printf(" m=maxPtextSize (default=%d)\n", MAX_DATA_SIZE); + printf(" n=minPtextSize (default=%d)\n", MIN_DATA_SIZE); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" s (all ops single-shot, not staged)\n"); + printf(" S (all ops staged)\n"); + printf(" z (keys and plaintext all zeroes)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +/* + * Given an initialized CCHmacContext, feed it some data and get the result. + */ +static void hmacRun( + CCHmacContext *ctx, + bool randomUpdates, + const unsigned char *ptext, + size_t ptextLen, + void *dataOut) +{ + while(ptextLen) { + size_t thisMoveIn; /* input to CCryptUpdate() */ + + if(randomUpdates) { + thisMoveIn = genRand(1, ptextLen); + } + else { + thisMoveIn = ptextLen; + } + logSize(("###ptext segment (1) len %lu\n", (unsigned long)thisMoveIn)); + CCHmacUpdate(ctx, ptext, thisMoveIn); + ptext += thisMoveIn; + ptextLen -= thisMoveIn; + } + CCHmacFinal(ctx, dataOut); +} + + +#define MAX_HMAC_SIZE CC_SHA512_DIGEST_LENGTH + +static int doTest(const uint8_t *ptext, + size_t ptextLen, + CCHmacAlgorithm hmacAlg, + uint32 keySizeInBytes, + bool stagedOrig, + bool stagedClone, + bool quiet, + bool verbose) +{ + uint8_t keyBytes[MAX_KEY_SIZE]; + uint8_t hmacOrig[MAX_HMAC_SIZE]; + uint8_t hmacClone[MAX_HMAC_SIZE]; + int rtn = 0; + CCHmacContext ctxOrig; + CCHmacContext ctxClone; + unsigned die; /* 0..3 indicates when to clone */ + unsigned loopNum = 0; + size_t hmacLen; + bool didClone = false; + + switch(hmacAlg) { + case kCCHmacAlgSHA1: + hmacLen = CC_SHA1_DIGEST_LENGTH; + break; + case kCCHmacAlgMD5: + hmacLen = CC_MD5_DIGEST_LENGTH; + break; + case kCCHmacAlgSHA224: + hmacLen = CC_SHA224_DIGEST_LENGTH; + break; + case kCCHmacAlgSHA256: + hmacLen = CC_SHA256_DIGEST_LENGTH; + break; + case kCCHmacAlgSHA384: + hmacLen = CC_SHA384_DIGEST_LENGTH; + break; + case kCCHmacAlgSHA512: + hmacLen = CC_SHA512_DIGEST_LENGTH; + break; + default: + printf("***BRRRZAP!\n"); + exit(1); + } + + /* random key */ + appGetRandomBytes(keyBytes, keySizeInBytes); + + /* cook up first context */ + CCHmacInit(&ctxOrig, hmacAlg, keyBytes, keySizeInBytes); + + /* roll the dice */ + die = genRand(0, 3); + + /* + * In this loop we do updates to the ctxOrig up until we + * clone it, then we use hmacRun to finish both of them. + */ + while(ptextLen) { + if((die == loopNum) || !stagedOrig) { + /* make the clone now */ + if(verbose) { + printf(" ...cloning at loop %u\n", loopNum); + } + ctxClone = ctxOrig; + didClone = true; + + /* do all of the clone's updates and final here */ + hmacRun(&ctxClone, stagedClone, ptext, ptextLen, hmacClone); + + /* now do all remaining updates and final for original */ + hmacRun(&ctxOrig, stagedOrig, ptext, ptextLen, hmacOrig); + + /* we're all done, time to check the HMAC values */ + break; + } /* making clone */ + + /* feed some data into cryptorOrig */ + size_t thisMove; + if(stagedOrig) { + thisMove = genRand(1, ptextLen); + } + else { + thisMove = ptextLen; + } + logSize(("###ptext segment (2) len %lu\n", (unsigned long)thisMove)); + CCHmacUpdate(&ctxOrig, ptext, thisMove); + ptext += thisMove; + ptextLen -= thisMove; + loopNum++; + } + + /* + * It's possible to get here without cloning or doing any finals, + * if we ran thru multiple updates and finished ptextLen for cryptorOrig + * before we hit the cloning spot. + */ + if(!didClone) { + if(!quiet) { + printf("...ctxOrig finished before we cloned; skipping test\n"); + } + return 0; + } + if(memcmp(hmacOrig, hmacClone, hmacLen)) { + printf("***data miscompare\n"); + rtn = testError(quiet); + } + return rtn; +} + +bool isBitSet(unsigned bit, unsigned word) +{ + if(bit > 31) { + printf("We don't have that many bits\n"); + exit(1); + } + unsigned mask = 1 << bit; + return (word & mask) ? true : false; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + uint8 *ptext; + size_t ptextLen; + bool stagedOrig; + bool stagedClone; + const char *algStr; + CCHmacAlgorithm hmacAlg; + int i; + int currAlg; // ALG_xxx + uint32 keySizeInBytes; + int rtn = 0; + + /* + * User-spec'd params + */ + bool keySizeSpec = false; // false: use rand key size + HmacAlg minAlg = ALG_FIRST; + HmacAlg maxAlg = ALG_LAST; + unsigned loops = LOOPS_DEF; + bool verbose = false; + size_t minPtextSize = MIN_DATA_SIZE; + size_t maxPtextSize = MAX_DATA_SIZE; + bool quiet = false; + unsigned pauseInterval = 0; + bool stagedSpec = false; // true means caller fixed stagedOrig and stagedClone + + for(arg=1; arg +#include +#include +#include "common.h" +#include +#include +#include + +/* SHA2-based HMAC testing disabled until openssl provides it */ +#define HMAC_SHA2_ENABLE 0 + +/* + * Defaults. + */ +#define LOOPS_DEF 200 + +#define MIN_DATA_SIZE 8 +#define MAX_DATA_SIZE 10000 /* bytes */ +#define MIN_KEY_SIZE 1 +#define MAX_KEY_SIZE 256 /* bytes */ +#define LOOP_NOTIFY 20 + +/* + * Enumerate algs our own way to allow iteration. + */ +typedef enum { + ALG_MD5 = 1, + ALG_SHA1, + ALG_SHA224, + ALG_SHA256, + ALG_SHA384, + ALG_SHA512, +} HmacAlg; +#define ALG_FIRST ALG_MD5 +#if HMAC_SHA2_ENABLE +#define ALG_LAST ALG_SHA512 +#else +#define ALG_LAST ALG_SHA1 +#endif /* HMAC_SHA2_ENABLE */ + +#define LOG_SIZE 0 +#if LOG_SIZE +#define logSize(s) printf s +#else +#define logSize(s) +#endif + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" a=algorithm (5=MD5; s=SHA1; 4=SHA224; 2=SHA256; 3=SHA384; 1=SHA512; default=all)\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" k=keySizeInBytes\n"); + printf(" m=maxPtextSize (default=%d)\n", MAX_DATA_SIZE); + printf(" n=minPtextSize (default=%d)\n", MIN_DATA_SIZE); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" s (all ops single-shot, not staged)\n"); + printf(" z (keys and plaintext all zeroes)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +/* + * Test harness for CCCryptor/HMAC with lots of options. + */ +static void doHmacCC( + CCHmacAlgorithm hmacAlg, bool randUpdates, + const void *keyBytes, size_t keyLen, + const uint8_t *inText, size_t inTextLen, + uint8_t *outText) /* returned, caller mallocs */ +{ + CCHmacContext ctx; + size_t toMove; /* total to go */ + const uint8 *inp; + + if(!randUpdates) { + /* one shot */ + CCHmac(hmacAlg, keyBytes, keyLen, inText, inTextLen, outText); + return; + } + + /* random multi updates */ + CCHmacInit(&ctx, hmacAlg, keyBytes, keyLen); + + toMove = inTextLen; /* total to go */ + inp = (const uint8 *)inText; + + while(toMove) { + uint32 thisMoveIn; /* input to CCryptUpdate() */ + + thisMoveIn = genRand(1, toMove); + logSize(("###ptext segment len %lu\n", (unsigned long)thisMoveIn)); + CCHmacUpdate(&ctx, inp, thisMoveIn); + inp += thisMoveIn; + toMove -= thisMoveIn; + } + + CCHmacFinal(&ctx, outText); +} + +/* + * Produce HMAC with reference implementation (currently, openssl) + */ +static int doHmacRef( + CCHmacAlgorithm hmacAlg, + const void *keyBytes, size_t keyLen, + const uint8_t *inText, size_t inTextLen, + uint8_t *outText, size_t *outTextLen) /* caller mallocs */ +{ + const EVP_MD *md; + + switch(hmacAlg) { + case kCCHmacAlgMD5: + md = EVP_md5(); + break; + case kCCHmacAlgSHA1: + md = EVP_sha1(); + break; + #if HMAC_SHA2_ENABLE + case kCCHmacAlgSHA224: + md = EVP_sha224(); + break; + case kCCHmacAlgSHA256: + md = EVP_sha256(); + break; + case kCCHmacAlgSHA384: + md = EVP_sha384(); + break; + case kCCHmacAlgSHA512: + md = EVP_sha512(); + break; + #endif /* HMAC_SHA2_ENABLE */ + default: + printf("***Bad hmacAlg (%d)\n", (int)hmacAlg); + return -1; + } + unsigned md_len = *outTextLen; + HMAC(md, keyBytes, (int)keyLen, + (const unsigned char *)inText, (int)inTextLen, + (unsigned char *)outText, &md_len); + *outTextLen = md_len; + return 0; +} + + +#define LOG_FREQ 20 +#define MAX_HMAC_SIZE CC_SHA512_DIGEST_LENGTH + +static int doTest(const uint8_t *ptext, + size_t ptextLen, + CCHmacAlgorithm hmacAlg, + uint32 keySizeInBytes, + bool staged, + bool allZeroes, + bool quiet) +{ + uint8_t keyBytes[MAX_KEY_SIZE]; + uint8_t hmacCC[MAX_HMAC_SIZE]; + size_t hmacCCLen; + uint8_t hmacRef[MAX_HMAC_SIZE]; + size_t hmacRefLen; + int rtn = 0; + + if(allZeroes) { + memset(keyBytes, 0, keySizeInBytes); + } + else { + /* random key */ + appGetRandomBytes(keyBytes, keySizeInBytes); + } + + hmacCCLen = MAX_HMAC_SIZE; + doHmacCC(hmacAlg, staged, + keyBytes, keySizeInBytes, + ptext, ptextLen, + hmacCC); + + hmacRefLen = MAX_HMAC_SIZE; + rtn = doHmacRef(hmacAlg, + keyBytes, keySizeInBytes, + ptext, ptextLen, + hmacRef, &hmacRefLen); + if(rtn) { + rtn = testError(quiet); + if(rtn) { + goto abort; + } + } + + if(memcmp(hmacRef, hmacCC, hmacRefLen)) { + printf("***data miscompare\n"); + rtn = testError(quiet); + } +abort: + return rtn; +} + +bool isBitSet(unsigned bit, unsigned word) +{ + if(bit > 31) { + printf("We don't have that many bits\n"); + exit(1); + } + unsigned mask = 1 << bit; + return (word & mask) ? true : false; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + uint8 *ptext; + size_t ptextLen; + bool staged; + const char *algStr; + CCHmacAlgorithm hmacAlg; + int i; + int currAlg; // ALG_xxx + uint32 keySizeInBytes; + int rtn = 0; + + /* + * User-spec'd params + */ + bool keySizeSpec = false; // false: use rand key size + HmacAlg minAlg = ALG_FIRST; + HmacAlg maxAlg = ALG_LAST; + unsigned loops = LOOPS_DEF; + bool verbose = false; + size_t minPtextSize = MIN_DATA_SIZE; + size_t maxPtextSize = MAX_DATA_SIZE; + bool quiet = false; + unsigned pauseInterval = 0; + bool stagedSpec = false; // ditto for stagedEncr and stagedDecr + bool allZeroes = false; + + for(arg=1; arg +#include +#include +#include "common.h" +#include +#include +#include + +/* + * Defaults. + */ +#define LOOPS_DEF 200 +#define MIN_DATA_SIZE 1 +#define MAX_DATA_SIZE 10000 /* bytes */ +#define LOOP_NOTIFY 20 + +/* + * Enumerate algs our own way to allow iteration. + */ +typedef enum { + ALG_MD2 = 1, + ALG_MD4, + ALG_MD5, + ALG_SHA1, + ALG_SHA224, + ALG_SHA256, + ALG_SHA384, + ALG_SHA512 +} HashAlg; +#define ALG_FIRST ALG_MD2 +#define ALG_LAST ALG_SHA512 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" l=loops (default %d)\n", LOOPS_DEF); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +/* the context pointers are void * here for polymorphism later on */ +typedef int (*initFcn)(void *ctx); +typedef int (*updateFcn)(void *ctx, const void *data, CC_LONG len); +typedef int (*finalFcn)(unsigned char *md, void *ctx); +typedef unsigned char (*oneShotFcn)(const void *data, CC_LONG len, unsigned char *md); + +typedef struct { + HashAlg alg; + const char *algName; + size_t digestSize; + initFcn init; + updateFcn update; + finalFcn final; + oneShotFcn oneShot; +} CommonDigestInfo; + +/* casts are necessary to cover the void* context args */ +static const CommonDigestInfo digests[] = +{ + { ALG_MD2, "MD2", CC_MD2_DIGEST_LENGTH, + (initFcn)CC_MD2_Init, (updateFcn)CC_MD2_Update, + (finalFcn)CC_MD2_Final, (oneShotFcn)CC_MD2 + }, + { ALG_MD4, "MD4", CC_MD4_DIGEST_LENGTH, + (initFcn)CC_MD4_Init, (updateFcn)CC_MD4_Update, + (finalFcn)CC_MD4_Final, (oneShotFcn)CC_MD4 + }, + { ALG_MD5, "MD5", CC_MD5_DIGEST_LENGTH, + (initFcn)CC_MD5_Init, (updateFcn)CC_MD5_Update, + (finalFcn)CC_MD5_Final, (oneShotFcn)CC_MD5 + }, + { ALG_SHA1, "SHA1", CC_SHA1_DIGEST_LENGTH, + (initFcn)CC_SHA1_Init, (updateFcn)CC_SHA1_Update, + (finalFcn)CC_SHA1_Final, (oneShotFcn)CC_SHA1 + }, + { ALG_SHA224, "SHA224", CC_SHA224_DIGEST_LENGTH, + (initFcn)CC_SHA224_Init, (updateFcn)CC_SHA224_Update, + (finalFcn)CC_SHA224_Final, (oneShotFcn)CC_SHA224 + }, + { ALG_SHA256, "SHA256", CC_SHA256_DIGEST_LENGTH, + (initFcn)CC_SHA256_Init, (updateFcn)CC_SHA256_Update, + (finalFcn)CC_SHA256_Final, (oneShotFcn)CC_SHA256 + }, + { ALG_SHA384, "SHA384", CC_SHA384_DIGEST_LENGTH, + (initFcn)CC_SHA384_Init, (updateFcn)CC_SHA384_Update, + (finalFcn)CC_SHA384_Final, (oneShotFcn)CC_SHA384 + }, + { ALG_SHA512, "SHA512", CC_SHA512_DIGEST_LENGTH, + (initFcn)CC_SHA512_Init, (updateFcn)CC_SHA512_Update, + (finalFcn)CC_SHA512_Final, (oneShotFcn)CC_SHA512 + }, +}; +#define NUM_DIGESTS (sizeof(digests) / sizeof(digests[0])) + +static const CommonDigestInfo *findDigestInfo(unsigned alg) +{ + unsigned dex; + for(dex=0; dexinit(ctx); + while(ptextLen) { + thisMove = genRand(1, ptextLen); + digestInfo->update(ctx, ptext, thisMove); + ptext += thisMove; + ptextLen -= thisMove; + } + digestInfo->final(md, ctx); +} + +static int doTest( + const CommonDigestInfo *digestInfo, + const unsigned char *ptext, + unsigned ptextLen, + bool quiet) +{ + unsigned char mdStaged[MAX_DIGEST_SIZE]; + unsigned char mdOneShot[MAX_DIGEST_SIZE]; + + digestInfo->oneShot(ptext, ptextLen, mdOneShot); + doStaged(digestInfo, ptext, ptextLen, mdStaged); + if(memcmp(mdStaged, mdOneShot, digestInfo->digestSize)) { + printf("***Digest miscompare for %s\n", digestInfo->algName); + if(testError(quiet)) { + return 1; + } + } + return 0; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + uint8 *ptext; + size_t ptextLen; + unsigned currAlg; + const CommonDigestInfo *digestInfo; + int rtn = 0; + int i; + + /* + * User-spec'd params + */ + unsigned loops = LOOPS_DEF; + bool quiet = false; + + for(arg=1; argalgName); + } + for(loop=1; ; loop++) { + ptextLen = genRand(MIN_DATA_SIZE, MAX_DATA_SIZE); + appGetRandomBytes(ptext, ptextLen); + if(!quiet) { + if((loop % LOOP_NOTIFY) == 0) { + printf("..loop %d ptextLen %lu\n", + loop, (unsigned long)ptextLen); + } + } + + if(doTest(digestInfo, ptext, ptextLen, quiet)) { + rtn = 1; + break; + } + if(loops && (loop == loops)) { + break; + } + } /* main loop */ + if(rtn) { + break; + } + + } /* for algs */ + + if((rtn == 0) && !quiet) { + printf("%s test complete\n", argv[0]); + } + free(ptext); + return rtn; +} + + diff --git a/SecurityTests/cspxutils/ccOpensslCompat/Makefile b/SecurityTests/cspxutils/ccOpensslCompat/Makefile new file mode 100644 index 00000000..d745e1f4 --- /dev/null +++ b/SecurityTests/cspxutils/ccOpensslCompat/Makefile @@ -0,0 +1,55 @@ +EXECUTABLE=ccOpensslCompat +# C++ source (with .cpp extension) +CPSOURCE= ccOpensslCompat.cpp digestOpenssl.cpp digestCommonCrypto.cpp +# C source (.c extension) +CSOURCE= + +### all of the rest is optional. + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= -lcrypto +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= -I$(LOCAL_BUILD)/include + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/ccOpensslCompat/ccOpensslCompat.cpp b/SecurityTests/cspxutils/ccOpensslCompat/ccOpensslCompat.cpp new file mode 100644 index 00000000..d3a6d8b7 --- /dev/null +++ b/SecurityTests/cspxutils/ccOpensslCompat/ccOpensslCompat.cpp @@ -0,0 +1,188 @@ +/* + * ccOpensslCompat.cpp - verify that the compatibility macros at the end of CommonDigest.h + * result in openssl-compatible calls + */ + +#include +#include +#include +#include +#include "digestCommonExtern.h" +#include "common.h" + +#define MAX_DIGEST_LEN 64 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" q -- quiet\n"); + /* etc. */ + exit(1); +} + +int main(int argc, char **argv) +{ + int quiet = false; + int arg; + char *argp; + + for(arg=1; arg. + * + * SHA2 functions are declared, but not implemented + * + * For now we'll have to redirect openssl SHA2 calls manually just to get this + * program to build and run correctly. (We could just disable all of the SHA2 + * code but we still get a benefit from compiling openssl-style code). + */ +#define OPENSSL_SHA2_IMPLEMENTED 0 + +#include "digestCommonExtern.h" + +#ifdef COMMON_DIGEST_FOR_OPENSSL + +/* redirecting to CommonDigest */ + +#define doMD2 md2cc +#define doMD4 md4cc +#define doMD5 md5cc +#define doSHA1 sha1cc +#define doSHA224 sha224cc +#define doSHA256 sha256cc +#define doSHA384 sha384cc +#define doSHA512 sha512cc + +#else /* !COMMON_DIGEST_FOR_OPENSSL */ + +/* openssl */ + +#define doMD2 md2os +#define doMD4 md4os +#define doMD5 md5os +#define doSHA1 sha1os +#define doSHA224 sha224os +#define doSHA256 sha256os +#define doSHA384 sha384os +#define doSHA512 sha512os + +#if !OPENSSL_SHA2_IMPLEMENTED + +/* Hack: redirect SHA2 calls after all */ + +#include + +#define SHA256_CTX CC_SHA256_CTX +#define SHA224_Init(c) CC_SHA224_Init(c) +#define SHA224_Update(c,d,l) CC_SHA224_Update(c,d,l) +#define SHA224_Final(m, c) CC_SHA224_Final(m,c) + +#define SHA256_Init(c) CC_SHA256_Init(c) +#define SHA256_Update(c,d,l) CC_SHA256_Update(c,d,l) +#define SHA256_Final(m, c) CC_SHA256_Final(m,c) + +#define SHA512_CTX CC_SHA512_CTX +#define SHA384_Init(c) CC_SHA384_Init(c) +#define SHA384_Update(c,d,l) CC_SHA384_Update(c,d,l) +#define SHA384_Final(m, c) CC_SHA384_Final(m,c) + +#define SHA512_Init(c) CC_SHA512_Init(c) +#define SHA512_Update(c,d,l) CC_SHA512_Update(c,d,l) +#define SHA512_Final(m, c) CC_SHA512_Final(m,c) + +#endif /* OPENSSL_SHA2_IMPLEMENTED */ + + +#endif /* COMMON_DIGEST_FOR_OPENSSL */ + +/* all functions return nonzero on error */ + +int doMD2(const void *p, unsigned long len, unsigned char *md) +{ + /* OPenSSL MD2 is not orthogonal: the pointer is a const unsigned char * */ + MD2_CTX ctx; + const unsigned char *cp = (const unsigned char *)p; + + if(!MD2_Init(&ctx)) { + return -1; + } + if(!MD2_Update(&ctx, cp, len)) { + return -1; + } + if(!MD2_Final(md, &ctx)) { + return -1; + } + return 0; +} + +int doMD4(const void *p, unsigned long len, unsigned char *md) +{ + MD4_CTX ctx; + if(!MD4_Init(&ctx)) { + return -1; + } + if(!MD4_Update(&ctx, p, len)) { + return -1; + } + if(!MD4_Final(md, &ctx)) { + return -1; + } + return 0; +} + +int doMD5(const void *p, unsigned long len, unsigned char *md) +{ + MD5_CTX ctx; + if(!MD5_Init(&ctx)) { + return -1; + } + if(!MD5_Update(&ctx, p, len)) { + return -1; + } + if(!MD5_Final(md, &ctx)) { + return -1; + } + return 0; +} + +int doSHA1(const void *p, unsigned long len, unsigned char *md) +{ + SHA_CTX ctx; + if(!SHA1_Init(&ctx)) { + return -1; + } + if(!SHA1_Update(&ctx, p, len)) { + return -1; + } + if(!SHA1_Final(md, &ctx)) { + return -1; + } + return 0; +} + +int doSHA224(const void *p, unsigned long len, unsigned char *md) +{ + SHA256_CTX ctx; + if(!SHA224_Init(&ctx)) { + return -1; + } + if(!SHA224_Update(&ctx, p, len)) { + return -1; + } + if(!SHA224_Final(md, &ctx)) { + return -1; + } + return 0; +} + +int doSHA256(const void *p, unsigned long len, unsigned char *md) +{ + SHA256_CTX ctx; + if(!SHA256_Init(&ctx)) { + return -1; + } + if(!SHA256_Update(&ctx, p, len)) { + return -1; + } + if(!SHA256_Final(md, &ctx)) { + return -1; + } + return 0; +} + +int doSHA384(const void *p, unsigned long len, unsigned char *md) +{ + SHA512_CTX ctx; + if(!SHA384_Init(&ctx)) { + return -1; + } + if(!SHA384_Update(&ctx, p, len)) { + return -1; + } + if(!SHA384_Final(md, &ctx)) { + return -1; + } + return 0; +} + +int doSHA512(const void *p, unsigned long len, unsigned char *md) +{ + SHA512_CTX ctx; + if(!SHA512_Init(&ctx)) { + return -1; + } + if(!SHA512_Update(&ctx, p, len)) { + return -1; + } + if(!SHA512_Final(md, &ctx)) { + return -1; + } + return 0; +} diff --git a/SecurityTests/cspxutils/ccOpensslCompat/digestCommonCrypto.cpp b/SecurityTests/cspxutils/ccOpensslCompat/digestCommonCrypto.cpp new file mode 100644 index 00000000..72671cdb --- /dev/null +++ b/SecurityTests/cspxutils/ccOpensslCompat/digestCommonCrypto.cpp @@ -0,0 +1,7 @@ +/* + * digestOpenssl.cpp - use the common code in digestCommon.h as CommonCrypto calls + */ + +#define COMMON_DIGEST_FOR_OPENSSL 1 +#include +#include "digestCommon.h" diff --git a/SecurityTests/cspxutils/ccOpensslCompat/digestCommonExtern.h b/SecurityTests/cspxutils/ccOpensslCompat/digestCommonExtern.h new file mode 100644 index 00000000..5c8b0498 --- /dev/null +++ b/SecurityTests/cspxutils/ccOpensslCompat/digestCommonExtern.h @@ -0,0 +1,39 @@ +/* + * digestCommonExtern.h - extern declarations of the functions resulting from both kinds of + * instantiations of the code in digestCommon.h + */ + +#ifndef _DIGEST_COMMON_EXTERN_H_ +#define _DIGEST_COMMON_EXTERN_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Openssl versions */ + +extern int md2os(const void *p, unsigned long len, unsigned char *md); +extern int md4os(const void *p, unsigned long len, unsigned char *md); +extern int md5os(const void *p, unsigned long len, unsigned char *md); +extern int sha1os(const void *p, unsigned long len, unsigned char *md); +extern int sha224os(const void *p, unsigned long len, unsigned char *md); +extern int sha256os(const void *p, unsigned long len, unsigned char *md); +extern int sha384os(const void *p, unsigned long len, unsigned char *md); +extern int sha512os(const void *p, unsigned long len, unsigned char *md); + +/* The CommonDigest versions */ + +extern int md2cc(const void *p, unsigned long len, unsigned char *md); +extern int md4cc(const void *p, unsigned long len, unsigned char *md); +extern int md5cc(const void *p, unsigned long len, unsigned char *md); +extern int sha1cc(const void *p, unsigned long len, unsigned char *md); +extern int sha224cc(const void *p, unsigned long len, unsigned char *md); +extern int sha256cc(const void *p, unsigned long len, unsigned char *md); +extern int sha384cc(const void *p, unsigned long len, unsigned char *md); +extern int sha512cc(const void *p, unsigned long len, unsigned char *md); + +#ifdef __cplusplus +} +#endif + +#endif /* _CC_COMMON_DIGEST_H_ */ diff --git a/SecurityTests/cspxutils/ccOpensslCompat/digestOpenssl.cpp b/SecurityTests/cspxutils/ccOpensslCompat/digestOpenssl.cpp new file mode 100644 index 00000000..94a84efe --- /dev/null +++ b/SecurityTests/cspxutils/ccOpensslCompat/digestOpenssl.cpp @@ -0,0 +1,14 @@ +/* + * digestOpenssl.cpp - use the common code in digestCommon.h as actual openssl calls + */ + +#include +#include +#include +#include +/* No OpenSSL implementation nor prototypes for the SHA-2 functions. + #include */ +#include + +#include "digestCommon.h" + diff --git a/SecurityTests/cspxutils/ccPerform/Makefile b/SecurityTests/cspxutils/ccPerform/Makefile new file mode 100644 index 00000000..da6654f5 --- /dev/null +++ b/SecurityTests/cspxutils/ccPerform/Makefile @@ -0,0 +1,56 @@ +# name of executable to build +EXECUTABLE=ccPerform +# C++ source (with .cpp extension) +CPSOURCE= ccPerform.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= -I$(LOCAL_BUILD)/include + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +# this is for linking against a custom libSystem...this is where it goes. +# You also need to do a setenv DYLD_LIBRARY_PATH /tmp/System/Debug to run. +PROJ_LDFLAGS= -L$(LOCAL_BUILD) + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/ccPerform/ccPerform.cpp b/SecurityTests/cspxutils/ccPerform/ccPerform.cpp new file mode 100644 index 00000000..01eed2a5 --- /dev/null +++ b/SecurityTests/cspxutils/ccPerform/ccPerform.cpp @@ -0,0 +1,240 @@ +/* + * ccPerform.cpp - measure performance of CommonCrypto encryption + */ + +#include +#include +#include +#include +#include +#include +#include "common.h" +#include + +#define LOOPS_DEF 1000 +#define BUFSIZE_DEF 10240 +#define MAX_KEY_SIZE kCCKeySizeMaxRC4 /* bytes */ + + +/* + * Enumerate algs our own way to allow iteration. + */ +typedef enum { + ALG_AES_128, + ALG_AES_192, + ALG_AES_256, + ALG_DES, + ALG_3DES, + ALG_CAST, + ALG_RC4 +} SymAlg; +#define ALG_FIRST ALG_AES_128 +#define ALG_LAST ALG_RC4 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" -a alg -- alg : d=DES; 3=3DES; a=AES128; n=AES192; A=AES256;\n"); + printf(" c=CAST; 4=RC4; default=all\n"); + printf(" -l loops -- loops; default %u\n", LOOPS_DEF); + printf(" -b bufsize -- buffer size; default %u\n", BUFSIZE_DEF); + printf(" -e -- ECB mode; default is CBC\n"); + + exit(1); +} + +static void printCCError(const char *str, OSStatus ortn) +{ + printf("***%s returned %ld\n", str, (long)ortn); +} + +int main(int argc, char **argv) +{ + unsigned loops = LOOPS_DEF; + unsigned bufSize = BUFSIZE_DEF; + unsigned algFirst = ALG_FIRST; + unsigned algLast = ALG_LAST; + bool ecbMode = false; + extern char *optarg; + int arg; + while ((arg = getopt(argc, argv, "a:l:b:eh")) != -1) { + switch (arg) { + case 'a': + switch(optarg[0]) { + case 'a': + algFirst = algLast = ALG_AES_128; + break; + case 'n': + algFirst = algLast = ALG_AES_192; + break; + case 'A': + algFirst = algLast = ALG_AES_256; + break; + case 'd': + algFirst = algLast = ALG_DES; + break; + case '3': + algFirst = algLast = ALG_3DES; + break; + case 'c': + algFirst = algLast = ALG_CAST; + case '4': + algFirst = algLast = ALG_RC4; + } + break; + case 'l': + loops = atoi(optarg); + break; + case 'b': + bufSize = atoi(optarg); + break; + case 'e': + ecbMode = true; + break; + case 'h': + usage(argv); + } + } + if(optind != argc) { + usage(argv); + } + + /* + * encrypt and decrypt on workBuf + * save original ptext in saveBuf, compare at end as sanity check + * for ECB only + */ + unsigned char *workBuf = (unsigned char *)malloc(bufSize); + unsigned char *saveBuf = (unsigned char *)malloc(bufSize); + if((workBuf == NULL) || (saveBuf == NULL)) { + printf("***malloc failure\n"); + exit(1); + } + appGetRandomBytes(workBuf, bufSize); + memmove(saveBuf, workBuf, bufSize); + + uint8_t keyBytes[MAX_KEY_SIZE]; + size_t keyLength; + + appGetRandomBytes(keyBytes, MAX_KEY_SIZE); + + CCCryptorRef cryptor; + CCAlgorithm alg; + CCOptions options = 0; + OSStatus ortn; + + if(ecbMode) { + options |= kCCOptionECBMode; + } + + unsigned currAlg; + for(currAlg=algFirst; currAlg<=algLast; currAlg++) { + const char *algStr = NULL; + + switch(currAlg) { + case ALG_DES: + keyLength = kCCKeySizeDES; + alg = kCCAlgorithmDES; + algStr = "DES "; + break; + case ALG_3DES: + keyLength = kCCKeySize3DES; + alg = kCCAlgorithm3DES; + algStr = "3DES"; + break; + case ALG_AES_128: + keyLength = kCCKeySizeAES128; + alg = kCCAlgorithmAES128; + algStr = "AES128"; + break; + case ALG_AES_192: + keyLength = kCCKeySizeAES192; + alg = kCCAlgorithmAES128; + algStr = "AES192"; + break; + case ALG_AES_256: + keyLength = kCCKeySizeAES256; + alg = kCCAlgorithmAES128; + algStr = "AES256"; + break; + case ALG_CAST: + keyLength = kCCKeySizeMaxCAST; + alg = kCCAlgorithmCAST; + algStr = "CAST"; + break; + case ALG_RC4: + keyLength = kCCKeySizeMaxRC4; + alg = kCCAlgorithmRC4; + algStr = "RC4"; + break; + } + + printf("Algorithm: %s keySize: %u mode: %s loops: %u bufSize: %u\n", + algStr, (unsigned)keyLength, ecbMode ? "ECB" : "CBC", + (unsigned)loops, (unsigned)bufSize); + + CFAbsoluteTime start, end; + unsigned loop; + size_t thisMoved; + + /* encrypt: GO */ + start = CFAbsoluteTimeGetCurrent(); + + ortn = CCCryptorCreate(kCCEncrypt, alg, options, + keyBytes, keyLength, NULL, &cryptor); + if(ortn) { + printCCError("CCCryptorCreate", ortn); + exit(1); + } + + for(loop=0; loop +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "bsafeUtils.h" +#include "ssleayUtils.h" +#include "rijndaelApi.h" +#include +#include + +/* + * Defaults. + */ +#define LOOPS_DEF 200 + +#define MIN_DATA_SIZE 8 +#define MAX_DATA_SIZE 10000 /* bytes */ +#define MAX_KEY_SIZE MAX_KEY_SIZE_RC245_BYTES /* bytes */ +#define LOOP_NOTIFY 20 + +#define NO_PAD_MODE CSSM_ALGMODE_ECB /* doesn't work for BSAFE */ +#define NO_PAD_MODE_BSAFE CSSM_ALGMODE_CBC_IV8 + +/* + * Enumerate algs our own way to allow iteration. + */ +typedef enum { + ALG_AES_128 = 1, /* 128 bit block, 128 bit key */ + ALG_AES_192, /* 128 bit block, 192 bit key */ + ALG_AES_256, /* 128 bit block, 256 bit key */ + ALG_DES, + ALG_3DES, + ALG_CAST, + ALG_RC4, + /* not supported by CommonCrypto */ + ALG_RC2, + ALG_RC5, + ALG_BFISH +} SymAlg; +#define ALG_FIRST ALG_AES_128 +#define ALG_LAST ALG_RC4 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" a=algorithm (d=DES; 3=3DES3; a=AES128; n=AES192; A=AES256; c=CAST;\n"); + printf(" 4=RC4; default=all)\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" k=keySizeInBits\n"); + printf(" e(ncrypt only)\n"); + printf(" m=maxPtextSize (default=%d)\n", MAX_DATA_SIZE); + printf(" n=minPtextSize (default=%d)\n", MIN_DATA_SIZE); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" s (all ops single-shot, not staged)\n"); + printf(" o (no padding, disable CBC if possible)\n"); + printf(" z (keys and plaintext all zeroes)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +/* + * encrypt/decrypt using reference BSAFE. + */ +static CSSM_RETURN encryptDecryptBSAFE( + CSSM_BOOL forEncrypt, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE encrMode, + const CSSM_DATA *iv, //Êoptional per mode + uint32 keySizeInBits, + uint32 effectiveKeyBits, // optional per key alg + uint32 rounds, // ditto + const CSSM_DATA *key, // raw key bytes + const CSSM_DATA *inText, + CSSM_DATA_PTR outText) // mallocd and returned +{ + CSSM_RETURN crtn; + BU_KEY buKey; + + crtn = buGenSymKey(keySizeInBits, key, &buKey); + if(crtn) { + return crtn; + } + crtn = buEncryptDecrypt(buKey, + forEncrypt, // forEncrypt + encrAlg, + encrMode, + iv, + effectiveKeyBits, + rounds, + inText, + outText); + buFreeKey(buKey); + return crtn; +} + +/* + * encrypt/decrypt using reference ssleay. + */ +static CSSM_RETURN encryptDecryptEAY( + CSSM_BOOL forEncrypt, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE encrMode, + const CSSM_DATA *iv, // optional per mode + uint32 keySizeInBits, + const CSSM_DATA *key, // raw key bytes, Length ignored + const CSSM_DATA *inText, + CSSM_DATA_PTR outText) // mallocd and returned +{ + CSSM_RETURN crtn; + EAY_KEY eayKey; + CSSM_DATA ckey = *key; + ckey.Length = keySizeInBits / 8; + + crtn = eayGenSymKey(encrAlg, forEncrypt, &ckey, &eayKey); + if(crtn) { + return crtn; + } + crtn = eayEncryptDecrypt(eayKey, + forEncrypt, + encrAlg, + encrMode, + iv, + inText, + outText); + eayFreeKey(eayKey); + return crtn; +} + +/* + * encrypt/decrypt using reference AES. + */ +static CSSM_RETURN encryptDecryptAES( + CSSM_BOOL forEncrypt, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE encrMode, + const CSSM_DATA *iv, //Êoptional per mode + uint32 keySizeInBits, + uint32 effectiveKeyBits, // optional per key alg + uint32 cipherBlockSize, + uint32 rounds, // ditto + const CSSM_DATA *key, // raw key bytes + const CSSM_DATA *inText, + CSSM_DATA_PTR outText) // mallocd and returned +{ + keyInstance aesKey; + cipherInstance aesCipher; + BYTE mode; + int artn; + BYTE *ivPtr; + + if(cipherBlockSize == 0) { + cipherBlockSize = MIN_AES_BLOCK_BITS; + } + switch(encrMode) { + case CSSM_ALGMODE_CBC_IV8: + mode = MODE_CBC; + ivPtr = iv->Data; + break; + case CSSM_ALGMODE_ECB: + mode = MODE_ECB; + ivPtr = NULL; + break; + default: + printf("***AES reference implementation doesn't do padding (yet)\n"); + return CSSM_OK; + } + /* fixme - adjust for padding if necessary */ + outText->Data = (uint8 *)CSSM_MALLOC(inText->Length); + outText->Length = inText->Length; + artn = _makeKey(&aesKey, + forEncrypt ? DIR_ENCRYPT : DIR_DECRYPT, + keySizeInBits, + cipherBlockSize, + key->Data); + if(artn <= 0) { + printf("***AES makeKey returned %d\n", artn); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + artn = _cipherInit(&aesCipher, + mode, + cipherBlockSize, + ivPtr); + if(artn <= 0) { + printf("***AES cipherInit returned %d\n", artn); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + if(forEncrypt) { + artn = _blockEncrypt(&aesCipher, + &aesKey, + (BYTE *)inText->Data, + inText->Length * 8, + (BYTE *)outText->Data); + } + else { + artn = _blockDecrypt(&aesCipher, + &aesKey, + (BYTE *)inText->Data, + inText->Length * 8, + (BYTE *)outText->Data); + } + if(artn <= 0) { + printf("***AES encrypt/decrypt returned %d\n", artn); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + return CSSM_OK; +} + +/* + * Encrypt/decrypt, one-shot, using one of the various reference implementations. + */ +static CSSM_RETURN encryptDecryptRef( + CSSM_BOOL forEncrypt, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE encrMode, + const CSSM_DATA *iv, // optional per mode + uint32 keySizeInBits, + uint32 effectiveKeyBits, // optional per key alg + uint32 cipherBlockSize, + uint32 rounds, // ditto + const CSSM_DATA *key, // raw key bytes + const CSSM_DATA *inText, + CSSM_DATA_PTR outText) // mallocd and returned +{ + switch(encrAlg) { + case CSSM_ALGID_AES: + return encryptDecryptAES( + forEncrypt, + encrAlg, + encrMode, + iv, + keySizeInBits, + effectiveKeyBits, + cipherBlockSize, + rounds, + key, + inText, + outText); + case CSSM_ALGID_BLOWFISH: + case CSSM_ALGID_CAST: + return encryptDecryptEAY( + forEncrypt, + encrAlg, + encrMode, + iv, + keySizeInBits, + key, + inText, + outText); + default: + return encryptDecryptBSAFE( + forEncrypt, + encrAlg, + encrMode, + iv, + keySizeInBits, + effectiveKeyBits, + rounds, + key, + inText, + outText); + } +} + +/* + * encrypt/decrypt using CommonCrypto. + */ +static CSSM_RETURN encryptDecryptCC( + CSSM_BOOL forEncrypt, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE encrMode, + CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc. + uint32 cipherBlockSize, + CSSM_BOOL multiUpdates, // false:single update, true:multi updates + const CSSM_DATA *iv, // optional per mode + uint32 keySizeInBits, + const CSSM_DATA *key, // raw key bytes + const CSSM_DATA *inText, + CSSM_DATA_PTR outText) // mallocd and returned +{ + CCCryptorRef cryptor = NULL; + uint8 *intext = inText->Data; + uint32 intextLen = inText->Length; + uint8 *outtext; + size_t outtextLen; /* mallocd size of outtext */ + size_t outBytes = 0; /* bytes actually produced in outtext */ + CCCryptorStatus crtn; + uint32 blockSize; + + /* convert crypt params from CDSA to CommonCrypto */ + CCAlgorithm ccAlg; + CCOperation ccOp = forEncrypt ? kCCEncrypt : kCCDecrypt; + CCOptions ccOpts = 0; + uint8 *ccIv = NULL; + + switch(encrAlg) { + case CSSM_ALGID_DES: + ccAlg = kCCAlgorithmDES; + blockSize = kCCBlockSizeDES; + break; + case CSSM_ALGID_3DES_3KEY_EDE: + ccAlg = kCCAlgorithm3DES; + blockSize = kCCBlockSize3DES; + break; + case CSSM_ALGID_AES: + ccAlg = kCCAlgorithmAES128; + blockSize = kCCBlockSizeAES128; + break; + case CSSM_ALGID_CAST: + ccAlg = kCCAlgorithmCAST; + blockSize = kCCBlockSizeCAST; + break; + case CSSM_ALGID_RC4: + ccAlg = kCCAlgorithmRC4; + blockSize = 0; + break; + default: + printf("***BRRZAP! Unknown algorithm in encryptDecryptCC()\n"); + return -1; + } + if(padding != CSSM_PADDING_NONE) { + ccOpts |= kCCOptionPKCS7Padding; + } + switch(encrMode) { + case CSSM_ALGMODE_CBC_IV8: + /* testing DES against BSAFE */ + ccOpts = 0; + ccIv = iv->Data; + break; + case CSSM_ALGMODE_ECB: + ccIv = NULL; + break; + case CSSM_ALGMODE_CBCPadIV8: + /* padding and cbc */ + ccIv = iv->Data; + break; + case CSSM_ALGMODE_NONE: + /* stream cipher */ + ccIv = NULL; + ccOpts = 0; + break; + default: + printf("***Bad mode (%lu)\n", (unsigned long)encrMode); + return 1; + } + if(ccIv == NULL) { + ccOpts |= kCCOptionECBMode; + } + + /* alloc outtext - round up to next cipherblock boundary for encrypt */ + if(blockSize) { + unsigned blocks; + if(forEncrypt) { + blocks = (intextLen + blockSize) / blockSize; + } + else { + blocks = intextLen / blockSize; + } + outtextLen = blocks * blockSize; + } + else { + outtextLen = intextLen; + } + + outtext = (uint8 *)CSSM_MALLOC(outtextLen); + memset(outtext, 0x55, outtextLen); + + if(!multiUpdates) { + /* one shot */ + crtn = CCCrypt(ccOp, ccAlg, ccOpts, + key->Data, keySizeInBits / 8, ccIv, + intext, intextLen, + outtext, outtextLen, &outtextLen); + if(crtn) { + printf("***CCCrypt returned %ld\n", (long)crtn); + return crtn; + } + outText->Data = outtext; + outText->Length = outtextLen; + return kCCSuccess; + } + + /* staged, random sized updates */ + crtn = CCCryptorCreate(ccOp, ccAlg, ccOpts, + key->Data, keySizeInBits / 8, ccIv, + &cryptor); + if(crtn) { + printf("***CCCryptorInit returned %ld\n", (long)crtn); + return crtn; + } + + size_t toMove = intextLen; /* total to go */ + size_t thisMoveOut; /* output from CCCryptUpdate()/CCCryptFinal() */ + uint8 *outp = outtext; + uint8 *inp = intext; + + while(toMove) { + uint32 thisMoveIn; /* input to CCryptUpdate() */ + + thisMoveIn = genRand(1, toMove); + crtn = CCCryptorUpdate(cryptor, inp, thisMoveIn, + outp, outtextLen, &thisMoveOut); + if(crtn) { + printf("***CCCryptorUpdate returned %ld\n", (long)crtn); + goto errOut; + } + inp += thisMoveIn; + toMove -= thisMoveIn; + outp += thisMoveOut; + outtextLen -= thisMoveOut; + outBytes += thisMoveOut; + } + crtn = CCCryptorFinal(cryptor, outp, outtextLen, &thisMoveOut); + if(crtn) { + printf("***CCCryptorFinal returned %ld\n", (long)crtn); + goto errOut; + } + outBytes += thisMoveOut; + outText->Data = outtext; + outText->Length = outBytes; + crtn = kCCSuccess; +errOut: + if(cryptor) { + CCCryptorRelease(cryptor); + } + return crtn; +} + +#define LOG_FREQ 20 + +static int doTest( + const CSSM_DATA *ptext, + const CSSM_DATA *keyData, + const CSSM_DATA *iv, + uint32 keyAlg, // CSSM_ALGID_xxx of the key + uint32 encrAlg, // encrypt/decrypt + uint32 encrMode, + uint32 padding, + uint32 keySizeInBits, + uint32 efectiveKeySizeInBits, + uint32 cipherBlockSize, + CSSM_BOOL stagedEncr, + CSSM_BOOL stagedDecr, + CSSM_BOOL quiet, + CSSM_BOOL encryptOnly) +{ + CSSM_DATA ctextRef = {0, NULL}; // ciphertext, reference + CSSM_DATA ctextTest = {0, NULL}; // ciphertext, test + CSSM_DATA rptext = {0, NULL}; // recovered plaintext + int rtn = 0; + CSSM_RETURN crtn; + uint32 rounds = 0; + + if(encrAlg == CSSM_ALGID_RC5) { + /* roll the dice, pick one of three values for rounds */ + unsigned die = genRand(1,3); + switch(die) { + case 1: + rounds = 8; + break; + case 2: + rounds = 12; + break; + case 3: + rounds = 16; + break; + } + } + + /* + * encrypt with each method; + * verify ciphertexts compare; + * decrypt with test code; + * verify recovered plaintext and incoming plaintext compare; + */ + crtn = encryptDecryptRef(CSSM_TRUE, + encrAlg, + encrMode, + iv, + keySizeInBits, + efectiveKeySizeInBits, + cipherBlockSize, + rounds, + keyData, + ptext, + &ctextRef); + if(crtn) { + return testError(quiet); + } + crtn = encryptDecryptCC(CSSM_TRUE, + encrAlg, + encrMode, + padding, + cipherBlockSize, + stagedEncr, + iv, + keySizeInBits, + keyData, + ptext, + &ctextTest); + if(crtn) { + return testError(quiet); + } + + /* ensure both methods resulted in same ciphertext */ + if(ctextRef.Length != ctextTest.Length) { + printf("Ctext length mismatch (1)\n"); + rtn = testError(quiet); + if(rtn) { + goto abort; + } + } + if(memcmp(ctextRef.Data, ctextTest.Data, ctextTest.Length)) { + printf("Ctext miscompare\n"); + rtn = testError(quiet); + if(rtn) { + goto abort; + } + } + + if(encryptOnly) { + rtn = 0; + goto abort; + } + + /* decrypt with the test method */ + crtn = encryptDecryptCC(CSSM_FALSE, + encrAlg, + encrMode, + padding, + cipherBlockSize, + stagedDecr, + iv, + keySizeInBits, + keyData, + &ctextTest, + &rptext); + if(crtn) { + return testError(quiet); + } + if(rptext.Length != ptext->Length) { + printf("ptext length mismatch (1)\n"); + rtn = testError(quiet); + if(rtn) { + goto abort; + } + } + if(memcmp(rptext.Data, ptext->Data, ptext->Length)) { + printf("ptext miscompare\n"); + const unsigned char *cp = (const unsigned char *)rptext.Data; + printf("rptext %p: %02X %02X %02X %02X...\n", + cp, cp[0], cp[1], cp[2], cp[3]); + rtn = testError(quiet); + } + else { + rtn = 0; + } +abort: + if(ctextTest.Data) { + CSSM_FREE(ctextTest.Data); + } + if(ctextRef.Length) { + CSSM_FREE(ctextRef.Data); + } + if(rptext.Length) { + CSSM_FREE(rptext.Data); + } + return rtn; +} + + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + CSSM_DATA ptext; + CSSM_BOOL stagedEncr; + CSSM_BOOL stagedDecr; + const char *algStr; + uint32 keyAlg; // CSSM_ALGID_xxx of the key + uint32 encrAlg; // CSSM_ALGID_xxx of encr/decr + int i; + unsigned currAlg; // ALG_xxx + uint32 actKeySizeInBits; + uint32 effectKeySizeInBits; + int rtn = 0; + uint32 blockSize; // for noPadding case + CSSM_DATA keyData; + CSSM_DATA initVector; + uint32 minTextSize; + + /* + * User-spec'd params + */ + CSSM_BOOL keySizeSpec = CSSM_FALSE; // false: use rand key size + unsigned minAlg = ALG_FIRST; + unsigned maxAlg = ALG_LAST; + unsigned loops = LOOPS_DEF; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + unsigned pauseInterval = 0; + uint32 mode; + uint32 padding; + CSSM_BOOL noPadding = CSSM_FALSE; + CSSM_BOOL encryptOnly = CSSM_FALSE; + uint32 cipherBlockSize = 0; // AES only, bits, 0 ==> default + unsigned maxPtextSize = MAX_DATA_SIZE; + unsigned minPtextSize = MIN_DATA_SIZE; + CSSM_BOOL oneShotOnly = CSSM_FALSE; + CSSM_BOOL allZeroes = CSSM_FALSE; + + for(arg=1; arg align ptext */ + ptext.Length = (ptext.Length / blockSize) * blockSize; + } + if(allZeroes) { + memset(ptext.Data, 0, ptext.Length); + memset(keyData.Data, 0, MAX_KEY_SIZE); + keyData.Length = MAX_KEY_SIZE; + } + else { + simpleGenData(&keyData, MAX_KEY_SIZE, MAX_KEY_SIZE); + } + + if(!keySizeSpec) { + /* + * CommonCrypto's AES does one key size only + */ + if(keyAlg != CSSM_ALGID_AES) { + effectKeySizeInBits = randKeySizeBits(keyAlg, OT_Encrypt); + /* + * generate keys with well aligned sizes; effectiveKeySize + * differs only if not well aligned + */ + actKeySizeInBits = (effectKeySizeInBits + 7) & ~7; + } + } + /* else constant, spec'd by user, may be 0 (default per alg) */ + /* mix up staging */ + if(oneShotOnly) { + stagedEncr = CSSM_FALSE; + stagedDecr = CSSM_FALSE; + } + else { + stagedEncr = (loop & 1) ? CSSM_TRUE : CSSM_FALSE; + stagedDecr = (loop & 2) ? CSSM_TRUE : CSSM_FALSE; + } + if(!quiet) { + if(verbose || ((loop % LOOP_NOTIFY) == 0)) { + if(cipherBlockSize) { + printf("..loop %d text size %lu keySizeBits %u" + " blockSize %u stagedEncr %d stagedDecr %d mode %s pad %s\n", + loop, (unsigned long)ptext.Length, (unsigned)effectKeySizeInBits, + (unsigned)cipherBlockSize, (int)stagedEncr, (int)stagedDecr, + modeStr, padStr); + } + else { + printf("..loop %d text size %lu keySizeBits %u" + " stagedEncr %d stagedDecr %d mode %s pad %s\n", + loop, (unsigned long)ptext.Length, (unsigned)effectKeySizeInBits, + (int)stagedEncr, (int)stagedDecr, modeStr, padStr); + } + } + } + + if(doTest(&ptext, + &keyData, + &initVector, + keyAlg, + encrAlg, + mode, + padding, + actKeySizeInBits, + actKeySizeInBits, // FIXME - test effective key size + cipherBlockSize, + stagedEncr, + stagedDecr, + quiet, + encryptOnly)) { + rtn = 1; + break; + } + if(pauseInterval && ((loop % pauseInterval) == 0)) { + char c; + fpurge(stdin); + printf("Hit CR to proceed, q to abort: "); + c = getchar(); + if(c == 'q') { + goto testDone; + } + } + if(loops && (loop == loops)) { + break; + } + } /* main loop */ + if(rtn) { + break; + } + + } /* for algs */ + +testDone: + if(pauseInterval) { + fpurge(stdin); + printf("ModuleDetach/Unload complete; hit CR to exit: "); + getchar(); + } + if((rtn == 0) && !quiet) { + printf("%s test complete\n", argv[0]); + } + CSSM_FREE(ptext.Data); + CSSM_FREE(keyData.Data); + return rtn; +} + + diff --git a/SecurityTests/cspxutils/ccSymTest/Makefile b/SecurityTests/cspxutils/ccSymTest/Makefile new file mode 100644 index 00000000..24179763 --- /dev/null +++ b/SecurityTests/cspxutils/ccSymTest/Makefile @@ -0,0 +1,56 @@ +# name of executable to build +EXECUTABLE=ccSymTest +# C++ source (with .cpp extension) +CPSOURCE= ccSymTest.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= -I$(LOCAL_BUILD)/include + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +# this is for linking against a custom libSystem...this is where it goes. +# You also need to do a setenv DYLD_LIBRARY_PATH /tmp/System/Debug to run. +PROJ_LDFLAGS= -L$(LOCAL_BUILD) + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/ccSymTest/ccSymTest.cpp b/SecurityTests/cspxutils/ccSymTest/ccSymTest.cpp new file mode 100644 index 00000000..83401500 --- /dev/null +++ b/SecurityTests/cspxutils/ccSymTest/ccSymTest.cpp @@ -0,0 +1,777 @@ +/* Copyright (c) 2006,2008 Apple Inc. + * + * ccSymTest.c - test CommonCrypto symmetric encrypt/decrypt. + */ +#include +#include +#include +#include +#include "common.h" +#include + +/* + * Defaults. + */ +#define LOOPS_DEF 500 +#define MIN_DATA_SIZE 8 +#define MAX_DATA_SIZE 10000 /* bytes */ +#define MAX_KEY_SIZE kCCKeySizeMaxRC4 /* bytes */ +#define MAX_BLOCK_SIZE kCCBlockSizeAES128 /* bytes */ +#define LOOP_NOTIFY 250 + +/* + * Enumerate algs our own way to allow iteration. + */ +typedef enum { + ALG_AES_128 = 1, /* 128 bit block, 128 bit key */ + ALG_AES_192, /* 128 bit block, 192 bit key */ + ALG_AES_256, /* 128 bit block, 256 bit key */ + ALG_DES, + ALG_3DES, + ALG_CAST, + ALG_RC4, + /* these aren't in CommonCrypto (yet?) */ + ALG_RC2, + ALG_RC5, + ALG_BFISH, + ALG_ASC, + ALG_NULL /* normally not used */ +} SymAlg; +#define ALG_FIRST ALG_AES_128 +#define ALG_LAST ALG_RC4 + + +#define LOG_SIZE 0 +#if LOG_SIZE +#define logSize(s) printf s +#else +#define logSize(s) +#endif + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" a=algorithm (d=DES; 3=3DES; a=AES128; n=AES192; A=AES256; \n"); + printf(" c=CAST; 4=RC4; default=all)\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" m=maxPtextSize (default=%d)\n", MAX_DATA_SIZE); + printf(" n=minPtextSize (default=%d)\n", MIN_DATA_SIZE); + printf(" k=keySizeInBytes\n"); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" o (no padding, well-aligned plaintext)\n"); + printf(" e (ECB only)\n"); + printf(" E (CBC only, no ECB)\n"); + printf(" u (no multi-update ops)\n"); + printf(" U (only multi-update ops)\n"); + printf(" x (always allocate context)\n"); + printf(" X (never allocate context)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +static void printCCError(const char *str, CCCryptorStatus crtn) +{ + const char *errStr; + char unknownStr[200]; + + switch(crtn) { + case kCCSuccess: errStr = "kCCSuccess"; break; + case kCCParamError: errStr = "kCCParamError"; break; + case kCCBufferTooSmall: errStr = "kCCBufferTooSmall"; break; + case kCCMemoryFailure: errStr = "kCCMemoryFailure"; break; + case kCCAlignmentError: errStr = "kCCAlignmentError"; break; + case kCCDecodeError: errStr = "kCCDecodeError"; break; + case kCCUnimplemented: errStr = "kCCUnimplemented"; break; + default: + sprintf(unknownStr, "Unknown(%ld)\n", (long)crtn); + errStr = unknownStr; + break; + } + printf("***%s returned %s\n", str, errStr); +} + +/* max context size */ +#define CC_MAX_CTX_SIZE kCCContextSizeRC4 + +/* + * We write a marker at end of expected output and at end of caller-allocated + * CCCryptorRef, and check at the end to make sure they weren't written + */ +#define MARKER_LENGTH 8 +#define MARKER_BYTE 0x7e + +/* + * Test harness for CCCryptor with lots of options. + */ +CCCryptorStatus doCCCrypt( + bool forEncrypt, + CCAlgorithm encrAlg, + bool doCbc, + bool doPadding, + const void *keyBytes, size_t keyLen, + const void *iv, + bool randUpdates, + bool inPlace, /* !doPadding only */ + size_t ctxSize, /* if nonzero, we allocate ctx */ + bool askOutSize, + const uint8_t *inText, size_t inTextLen, + uint8_t **outText, size_t *outTextLen) /* both returned, WE malloc */ +{ + CCCryptorRef cryptor = NULL; + CCCryptorStatus crtn; + CCOperation op = forEncrypt ? kCCEncrypt : kCCDecrypt; + CCOptions options = 0; + uint8_t *outBuf = NULL; /* mallocd output buffer */ + uint8_t *outp; /* running ptr into outBuf */ + const uint8 *inp; /* running ptr into inText */ + size_t outLen; /* bytes remaining in outBuf */ + size_t toMove; /* bytes remaining in inText */ + size_t thisMoveOut; /* output from CCCryptUpdate()/CCCryptFinal() */ + size_t outBytes; /* total bytes actually produced in outBuf */ + char ctx[CC_MAX_CTX_SIZE]; /* for CCCryptorCreateFromData() */ + uint8_t *textMarker = NULL; /* 8 bytes of marker here after expected end of + * output */ + char *ctxMarker = NULL; /* ditto for caller-provided context */ + unsigned dex; + size_t askedOutSize; /* from the lib */ + size_t thisOutLen; /* dataOutAvailable we use */ + + if(ctxSize > CC_MAX_CTX_SIZE) { + printf("***HEY! Adjust CC_MAX_CTX_SIZE!\n"); + exit(1); + } + if(!doCbc) { + options |= kCCOptionECBMode; + } + if(doPadding) { + options |= kCCOptionPKCS7Padding; + } + + /* just hack this one */ + outLen = inTextLen; + if(forEncrypt) { + outLen += MAX_BLOCK_SIZE; + } + + outBuf = (uint8_t *)malloc(outLen + MARKER_LENGTH); + + /* library should not touch this memory */ + textMarker = outBuf + outLen; + memset(textMarker, MARKER_BYTE, MARKER_LENGTH); + + /* subsequent errors to errOut: */ + + if(inPlace) { + memmove(outBuf, inText, inTextLen); + inp = outBuf; + } + else { + inp = inText; + } + + if(!randUpdates) { + /* one shot */ + if(askOutSize) { + crtn = CCCrypt(op, encrAlg, options, + keyBytes, keyLen, iv, + inp, inTextLen, + outBuf, 0, &askedOutSize); + if(crtn != kCCBufferTooSmall) { + printf("***Did not get kCCBufferTooSmall as expected\n"); + printf(" alg %d inTextLen %lu cbc %d padding %d keyLen %lu\n", + (int)encrAlg, (unsigned long)inTextLen, (int)doCbc, (int)doPadding, + (unsigned long)keyLen); + printCCError("CCCrypt", crtn); + crtn = -1; + goto errOut; + } + outLen = askedOutSize; + } + crtn = CCCrypt(op, encrAlg, options, + keyBytes, keyLen, iv, + inp, inTextLen, + outBuf, outLen, &outLen); + if(crtn) { + printCCError("CCCrypt", crtn); + goto errOut; + } + *outText = outBuf; + *outTextLen = outLen; + goto errOut; + } + + /* random multi updates */ + if(ctxSize) { + size_t ctxSizeCreated; + + if(askOutSize) { + crtn = CCCryptorCreateFromData(op, encrAlg, options, + keyBytes, keyLen, iv, + ctx, 0 /* ctxSize */, + &cryptor, &askedOutSize); + if(crtn != kCCBufferTooSmall) { + printf("***Did not get kCCBufferTooSmall as expected\n"); + printCCError("CCCryptorCreateFromData", crtn); + crtn = -1; + goto errOut; + } + ctxSize = askedOutSize; + } + crtn = CCCryptorCreateFromData(op, encrAlg, options, + keyBytes, keyLen, iv, + ctx, ctxSize, &cryptor, &ctxSizeCreated); + if(crtn) { + printCCError("CCCryptorCreateFromData", crtn); + return crtn; + } + ctxMarker = ctx + ctxSizeCreated; + memset(ctxMarker, MARKER_BYTE, MARKER_LENGTH); + } + else { + crtn = CCCryptorCreate(op, encrAlg, options, + keyBytes, keyLen, iv, + &cryptor); + if(crtn) { + printCCError("CCCryptorCreate", crtn); + return crtn; + } + } + + toMove = inTextLen; /* total to go */ + outp = outBuf; + outBytes = 0; /* bytes actually produced in outBuf */ + + while(toMove) { + uint32 thisMoveIn; /* input to CCryptUpdate() */ + + thisMoveIn = genRand(1, toMove); + logSize(("###ptext segment len %lu\n", (unsigned long)thisMoveIn)); + if(askOutSize) { + thisOutLen = CCCryptorGetOutputLength(cryptor, thisMoveIn, false); + } + else { + thisOutLen = outLen; + } + crtn = CCCryptorUpdate(cryptor, inp, thisMoveIn, + outp, thisOutLen, &thisMoveOut); + if(crtn) { + printCCError("CCCryptorUpdate", crtn); + goto errOut; + } + inp += thisMoveIn; + toMove -= thisMoveIn; + outp += thisMoveOut; + outLen -= thisMoveOut; + outBytes += thisMoveOut; + } + + if(doPadding) { + /* Final is not needed if padding is disabled */ + if(askOutSize) { + thisOutLen = CCCryptorGetOutputLength(cryptor, 0, true); + } + else { + thisOutLen = outLen; + } + crtn = CCCryptorFinal(cryptor, outp, thisOutLen, &thisMoveOut); + } + else { + thisMoveOut = 0; + crtn = kCCSuccess; + } + + if(crtn) { + printCCError("CCCryptorFinal", crtn); + goto errOut; + } + + outBytes += thisMoveOut; + *outText = outBuf; + *outTextLen = outBytes; + crtn = kCCSuccess; + + for(dex=0; dex 31) { + printf("We don't have that many bits\n"); + exit(1); + } + unsigned mask = 1 << bit; + return (word & mask) ? true : false; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + uint8 *ptext; + size_t ptextLen; + bool stagedEncr; + bool stagedDecr; + bool doPadding; + bool doCbc; + bool nullIV; + const char *algStr; + CCAlgorithm encrAlg; + int i; + int currAlg; // ALG_xxx + uint32 minKeySizeInBytes; + uint32 maxKeySizeInBytes; + uint32 keySizeInBytes; + int rtn = 0; + uint32 blockSize; // for noPadding case + size_t ctxSize; // always set per alg + size_t ctxSizeUsed; // passed to doTest + bool askOutSize; // inquire output size each op + + /* + * User-spec'd params + */ + bool keySizeSpec = false; // false: use rand key size + SymAlg minAlg = ALG_FIRST; + SymAlg maxAlg = ALG_LAST; + unsigned loops = LOOPS_DEF; + bool verbose = false; + size_t minPtextSize = MIN_DATA_SIZE; + size_t maxPtextSize = MAX_DATA_SIZE; + bool quiet = false; + unsigned pauseInterval = 0; + bool paddingSpec = false; // true: user calls doPadding, const + bool cbcSpec = false; // ditto for doCbc + bool stagedSpec = false; // ditto for stagedEncr and stagedDecr + bool inPlace = false; // en/decrypt in place for ECB + bool allocCtxSpec = false; // use allocCtx + bool allocCtx = false; // allocate context ourself + + for(arg=1; arg ALG_LAST) { + /* we left them in the switch but we can't use them */ + usage(argv); + } + break; + case 'l': + loops = atoi(&argp[2]); + break; + case 'n': + minPtextSize = atoi(&argp[2]); + break; + case 'm': + maxPtextSize = atoi(&argp[2]); + break; + case 'k': + minKeySizeInBytes = maxKeySizeInBytes = atoi(&argp[2]); + keySizeSpec = true; + break; + case 'x': + allocCtxSpec = true; + allocCtx = true; + break; + case 'X': + allocCtxSpec = true; + allocCtx = false; + break; + case 'v': + verbose = true; + break; + case 'q': + quiet = true; + break; + case 'p': + pauseInterval = atoi(&argp[2]);; + break; + case 'o': + doPadding = false; + paddingSpec = true; + break; + case 'e': + doCbc = false; + cbcSpec = true; + break; + case 'E': + doCbc = true; + cbcSpec = true; + break; + case 'u': + stagedEncr = false; + stagedDecr = false; + stagedSpec = true; + break; + case 'U': + stagedEncr = true; + stagedDecr = true; + stagedSpec = true; + break; + case 'h': + default: + usage(argv); + } + } + ptext = (uint8 *)malloc(maxPtextSize); + if(ptext == NULL) { + printf("Insufficient heap space\n"); + exit(1); + } + /* ptext length set in test loop */ + + printf("Starting ccSymTest; args: "); + for(i=1; i 0 ) + switch ( "$argv[1]" ) + case q: + set QUIET = q + shift + breaksw + default: + cat cspdvt_usage + exit(1) + endsw +end +set CSPXUTILS=`pwd` +#TODO $BUILD_DIR/ccSymCompat $QUIET || exit(1) +#TODO $BUILD_DIR/ccSymCompat o $QUIET || exit(1) +$BUILD_DIR/ccSymTest $QUIET || exit(1) +$BUILD_DIR/ccHmacCompat $QUIET || exit(1) +$BUILD_DIR/ccHmacClone $QUIET || exit(1) +$BUILD_DIR/ccOneShot $QUIET || exit(1) +$BUILD_DIR/ccOpensslCompat $QUIET || exit(1) + +echo ===== ccdvt success ===== diff --git a/SecurityTests/cspxutils/ccmake b/SecurityTests/cspxutils/ccmake new file mode 100755 index 00000000..9e761ac6 --- /dev/null +++ b/SecurityTests/cspxutils/ccmake @@ -0,0 +1,46 @@ +#! /bin/csh -f +# +# make all CommonCrypto tests (from scratch). +# +set DO_CLEAN=NO +set LOCAL_CC= + +set TARGETS= (ccSymCompat \ + ccSymTest \ + ccHmacCompat \ + ccHmacClone \ + ccOneShot \ + ccCtxSize \ + ccPerform \ + ccOpensslCompat ) + +while ( $#argv > 0 ) + switch ( "$argv[1]" ) + case clean: + set DO_CLEAN=YES + shift + breaksw + case local: + set LOCAL_CC="-lcommonCrypto -L$LOCAL_BUILD_DIR" + shift + breaksw + default: + echo "Usage: ccmake [clean] [local]" + exit(1) + endsw +end + +set CSPXUTILS=`pwd` + +foreach targ ($TARGETS) + if($DO_CLEAN == YES) then + echo ====== Cleaning $targ ====== + cd $CSPXUTILS/$targ + make clean || exit(1) + else + echo ====== Building $targ ====== + cd $CSPXUTILS/$targ + make PROJ_LDFLAGS="$LOCAL_CC" || exit(1) + endif +end + diff --git a/SecurityTests/cspxutils/clearPubKeyTest/Makefile b/SecurityTests/cspxutils/clearPubKeyTest/Makefile new file mode 100644 index 00000000..e7e04731 --- /dev/null +++ b/SecurityTests/cspxutils/clearPubKeyTest/Makefile @@ -0,0 +1,56 @@ +# name of executable to build +EXECUTABLE=clearPubKeyTest +# C++ source (with .cpp extension) +CPSOURCE=clearPubKeyTest.cpp +# C source (.c extension) +CSOURCE= + +### all of the rest is optional. + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/clearPubKeyTest/clearPubKeyTest.cpp b/SecurityTests/cspxutils/clearPubKeyTest/clearPubKeyTest.cpp new file mode 100644 index 00000000..81c73e4a --- /dev/null +++ b/SecurityTests/cspxutils/clearPubKeyTest/clearPubKeyTest.cpp @@ -0,0 +1,395 @@ +/* + * clearPubKeyTest.cpp + * + * Test CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT. This cannot be run on a handsoff environment; + * it forces Keychain unlock dialogs. + */ + +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" + +#define KEYCHAIN_NAME "/tmp/clearPubKey.keychain" +#define KEYCHAIN_PWD "pwd" +#define KEY_ALG CSSM_ALGID_RSA +#define KEYSIZE 1024 +#define ENCRALG CSSM_ALGID_RSA + +static void usage(char **argv) +{ + printf("usage: %s -v(erbose)\n", argv[0]); + exit(1); +} + +static void printNoDialog() +{ + printf("*** If you get a keychain unlock dialog here the test is failing ***\n"); +} + +static void printExpectDialog() +{ + printf("*** You MUST get a keychain unlock dialog here (password = '%s') ***\n", + KEYCHAIN_PWD); +} + +static bool didGetDialog() +{ + fpurge(stdin); + printf("Enter 'y' if you just got a keychain unlock dialog: "); + if(getchar() == 'y') { + return 1; + } + printf("***Well, you really should have. Test failed.\n"); + return 0; +} + +static void verboseDisp(bool verbose, const char *str) +{ + if(verbose) { + printf("...%s\n", str); + } +} + +/* generate key pair, optionally storing the public key in encrypted form */ +static int genKeyPair( + bool pubKeyIsEncrypted, + SecKeychainRef kcRef, + SecKeyRef *pubKeyRef, + SecKeyRef *privKeyRef) +{ + /* gather keygen args */ + CSSM_ALGORITHMS keyAlg = KEY_ALG; + uint32 keySizeInBits = KEYSIZE; + CSSM_KEYUSE pubKeyUsage = CSSM_KEYUSE_ANY; + uint32 pubKeyAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT; + if(pubKeyIsEncrypted) { + pubKeyAttr |= CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT; + } + CSSM_KEYUSE privKeyUsage = CSSM_KEYUSE_ANY; + uint32 privKeyAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | + CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_SENSITIVE; + + OSStatus ortn = SecKeyCreatePair(kcRef, keyAlg, keySizeInBits, 0, + pubKeyUsage, pubKeyAttr, + privKeyUsage, privKeyAttr, + NULL, // default initial access for now + pubKeyRef, privKeyRef); + if(ortn) { + cssmPerror("SecKeyCreatePair", ortn); + return 1; + } + return 0; +} + +/* encrypt something with a public key */ +static int pubKeyEncrypt( + SecKeyRef pubKeyRef) +{ + const CSSM_KEY *cssmKey; + OSStatus ortn; + CSSM_CSP_HANDLE cspHand; + + ortn = SecKeyGetCSSMKey(pubKeyRef, &cssmKey); + if(ortn) { + cssmPerror("SecKeyGetCSSMKey", ortn); + return -1; + } + ortn = SecKeyGetCSPHandle(pubKeyRef, &cspHand); + if(ortn) { + cssmPerror("SecKeyGetCSPHandle", ortn); + return -1; + } + + char *ptext = "something to encrypt"; + CSSM_DATA ptextData = {strlen(ptext), (uint8 *)ptext}; + CSSM_DATA ctextData = { 0, NULL }; + CSSM_RETURN crtn; + + crtn = cspEncrypt(cspHand, CSSM_ALGID_RSA, + 0, CSSM_PADDING_PKCS1, // mode/pad + cssmKey, NULL, + 0, 0, // effect/rounds + NULL, // IV + &ptextData, &ctextData, CSSM_FALSE); + if(crtn) { + return -1; + } + /* slighyly hazardous, allocated by CSPDL's allocator */ + free(ctextData.Data); + return 0; +} + +int main(int argc, char **argv) +{ + bool verbose = false; + + int arg; + while ((arg = getopt(argc, argv, "vh")) != -1) { + switch (arg) { + case 'v': + verbose = true; + break; + case 'h': + usage(argv); + } + } + if(optind != argc) { + usage(argv); + } + + printNoDialog(); + + /* initial setup */ + verboseDisp(verbose, "deleting keychain"); + unlink(KEYCHAIN_NAME); + + verboseDisp(verbose, "creating keychain"); + SecKeychainRef kcRef = NULL; + OSStatus ortn = SecKeychainCreate(KEYCHAIN_NAME, + strlen(KEYCHAIN_PWD), KEYCHAIN_PWD, + false, NULL, &kcRef); + if(ortn) { + cssmPerror("SecKeychainCreate", ortn); + exit(1); + } + + /* + * 1. Generate key pair with cleartext public key. + * Ensure we can use the public key when keychain is locked with no + * user interaction. + */ + + /* generate key pair, cleartext public key */ + verboseDisp(verbose, "creating key pair, cleartext public key"); + SecKeyRef pubKeyRef = NULL; + SecKeyRef privKeyRef = NULL; + if(genKeyPair(false, kcRef, &pubKeyRef, &privKeyRef)) { + exit(1); + } + + /* Use generated cleartext public key with locked keychain */ + verboseDisp(verbose, "locking keychain, exporting public key"); + SecKeychainLock(kcRef); + CFDataRef exportData = NULL; + ortn = SecKeychainItemExport(pubKeyRef, kSecFormatOpenSSL, 0, NULL, &exportData); + if(ortn) { + cssmPerror("SecKeychainCreate", ortn); + exit(1); + } + CFRelease(exportData); + + verboseDisp(verbose, "locking keychain, encrypting with public key"); + SecKeychainLock(kcRef); + if(pubKeyEncrypt(pubKeyRef)) { + exit(1); + } + + /* reset */ + verboseDisp(verbose, "deleting keys"); + ortn = SecKeychainItemDelete((SecKeychainItemRef)pubKeyRef); + if(ortn) { + cssmPerror("SecKeychainItemDelete", ortn); + exit(1); + } + ortn = SecKeychainItemDelete((SecKeychainItemRef)privKeyRef); + if(ortn) { + cssmPerror("SecKeychainItemDelete", ortn); + exit(1); + } + CFRelease(pubKeyRef); + CFRelease(privKeyRef); + + /* + * 2. Generate key pair with encrypted public key. + * Ensure that user interaction is required when we use the public key + * when keychain is locked. + */ + + verboseDisp(verbose, "programmatically unlocking keychain"); + ortn = SecKeychainUnlock(kcRef, strlen(KEYCHAIN_PWD), KEYCHAIN_PWD, TRUE); + if(ortn) { + cssmPerror("SecKeychainItemDelete", ortn); + exit(1); + } + + /* generate key pair, encrypted public key */ + verboseDisp(verbose, "creating key pair, encrypted public key"); + if(genKeyPair(true, kcRef, &pubKeyRef, &privKeyRef)) { + exit(1); + } + + /* Use generated encrypted public key with locked keychain */ + verboseDisp(verbose, "locking keychain, exporting public key"); + SecKeychainLock(kcRef); + printExpectDialog(); + ortn = SecKeychainItemExport(pubKeyRef, kSecFormatOpenSSL, 0, NULL, &exportData); + if(ortn) { + cssmPerror("SecKeychainCreate", ortn); + exit(1); + } + /* we'll use that exported blob later to test import */ + if(!didGetDialog()) { + exit(1); + } + + verboseDisp(verbose, "locking keychain, encrypting with public key"); + SecKeychainLock(kcRef); + printExpectDialog(); + if(pubKeyEncrypt(pubKeyRef)) { + exit(1); + } + if(!didGetDialog()) { + exit(1); + } + + /* reset */ + printNoDialog(); + verboseDisp(verbose, "locking keychain"); + SecKeychainLock(kcRef); + verboseDisp(verbose, "deleting keys"); + ortn = SecKeychainItemDelete((SecKeychainItemRef)pubKeyRef); + if(ortn) { + cssmPerror("SecKeychainItemDelete", ortn); + exit(1); + } + ortn = SecKeychainItemDelete((SecKeychainItemRef)privKeyRef); + if(ortn) { + cssmPerror("SecKeychainItemDelete", ortn); + exit(1); + } + CFRelease(pubKeyRef); + CFRelease(privKeyRef); + + /* + * 3. Import public key, storing in cleartext. Ensure that the import + * doesn't require unlock, and ensure we can use the public key + * when keychain is locked with no user interaction. + */ + + printNoDialog(); + verboseDisp(verbose, "locking keychain"); + SecKeychainLock(kcRef); + + /* import public key - default is in the clear */ + verboseDisp(verbose, "importing public key, store in the clear (default)"); + CFArrayRef outArray = NULL; + SecExternalFormat format = kSecFormatOpenSSL; + SecExternalItemType type = kSecItemTypePublicKey; + ortn = SecKeychainItemImport(exportData, + NULL, &format, &type, + 0, NULL, + kcRef, &outArray); + if(ortn) { + cssmPerror("SecKeychainItemImport", ortn); + exit(1); + } + CFRelease(exportData); + if(CFArrayGetCount(outArray) != 1) { + printf("***Unexpected outArray size (%ld) after import\n", + (long)CFArrayGetCount(outArray)); + exit(1); + } + pubKeyRef = (SecKeyRef)CFArrayGetValueAtIndex(outArray, 0); + if(CFGetTypeID(pubKeyRef) != SecKeyGetTypeID()) { + printf("***Unexpected item type after import\n"); + exit(1); + } + + /* Use imported cleartext public key with locked keychain */ + verboseDisp(verbose, "locking keychain, exporting public key"); + SecKeychainLock(kcRef); + exportData = NULL; + ortn = SecKeychainItemExport(pubKeyRef, kSecFormatOpenSSL, 0, NULL, &exportData); + if(ortn) { + cssmPerror("SecKeychainItemExport", ortn); + exit(1); + } + /* we'll use exportData again */ + + verboseDisp(verbose, "locking keychain, encrypting with public key"); + SecKeychainLock(kcRef); + if(pubKeyEncrypt(pubKeyRef)) { + exit(1); + } + + /* reset */ + verboseDisp(verbose, "deleting key"); + ortn = SecKeychainItemDelete((SecKeychainItemRef)pubKeyRef); + if(ortn) { + cssmPerror("SecKeychainItemDelete", ortn); + exit(1); + } + CFRelease(pubKeyRef); + + /* + * Import public key, storing in encrypted form. + * Ensure that user interaction is required when we use the public key + * when keychain is locked. + */ + + /* import public key, encrypted in the keychain */ + SecKeyImportExportParameters impExpParams; + memset(&impExpParams, 0, sizeof(impExpParams)); + impExpParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; + impExpParams.keyAttributes = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | + CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT; + verboseDisp(verbose, "importing public key, store encrypted"); + printExpectDialog(); + outArray = NULL; + format = kSecFormatOpenSSL; + type = kSecItemTypePublicKey; + ortn = SecKeychainItemImport(exportData, + NULL, &format, &type, + 0, &impExpParams, + kcRef, &outArray); + if(ortn) { + cssmPerror("SecKeychainItemImport", ortn); + exit(1); + } + if(!didGetDialog()) { + exit(1); + } + CFRelease(exportData); + if(CFArrayGetCount(outArray) != 1) { + printf("***Unexpected outArray size (%ld) after import\n", + (long)CFArrayGetCount(outArray)); + exit(1); + } + pubKeyRef = (SecKeyRef)CFArrayGetValueAtIndex(outArray, 0); + if(CFGetTypeID(pubKeyRef) != SecKeyGetTypeID()) { + printf("***Unexpected item type after import\n"); + exit(1); + } + + /* Use imported encrypted public key with locked keychain */ + verboseDisp(verbose, "locking keychain, exporting public key"); + SecKeychainLock(kcRef); + printExpectDialog(); + ortn = SecKeychainItemExport(pubKeyRef, kSecFormatOpenSSL, 0, NULL, &exportData); + if(ortn) { + cssmPerror("SecKeychainItemExport", ortn); + exit(1); + } + if(!didGetDialog()) { + exit(1); + } + CFRelease(exportData); + + verboseDisp(verbose, "locking keychain, encrypting with public key"); + SecKeychainLock(kcRef); + printExpectDialog(); + if(pubKeyEncrypt(pubKeyRef)) { + exit(1); + } + if(!didGetDialog()) { + exit(1); + } + + SecKeychainDelete(kcRef); + printf("...test succeeded.\n"); + return 0; +} diff --git a/SecurityTests/cspxutils/contextReuse/Makefile b/SecurityTests/cspxutils/contextReuse/Makefile new file mode 100644 index 00000000..8ead19ca --- /dev/null +++ b/SecurityTests/cspxutils/contextReuse/Makefile @@ -0,0 +1,55 @@ +# name of executable to build +EXECUTABLE=contextReuse +# C++ source (with .cpp extension) +CPSOURCE= contextReuse.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= -lcrypto +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= -F/System/Library/PrivateFrameworks + +# +# Optional link flags (using cc, not ld) +# +#PROJ_LDFLAGS= -lMallocDebug -lBSafe +PROJ_LDFLAGS= + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/contextReuse/contextReuse.cpp b/SecurityTests/cspxutils/contextReuse/contextReuse.cpp new file mode 100644 index 00000000..993d1799 --- /dev/null +++ b/SecurityTests/cspxutils/contextReuse/contextReuse.cpp @@ -0,0 +1,739 @@ +/* + * contextReuse.cpp + * + * Verify proper operation of symmetric CSP algorithms when CSSM_CC_HANDLE + * (crypto context) is reused. Tests specifically for Radar 4551700, which + * dealt with a problem with the Gladman AES implementation handling the + * same context for an encrypt followed by a decrypt; other situations + * are tested here (e.g. encrypt followed by another encrypt including CBC) + * as well as all CSP symmetric algorithms. + */ + +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include +#include "cspdlTesting.h" + +/* + * Defaults. + */ +#define LOOPS_DEF 200 + +#define MIN_DATA_SIZE 8 +#define MAX_DATA_SIZE 10000 /* bytes */ +#define MAX_KEY_SIZE MAX_KEY_SIZE_RC245_BYTES /* bytes */ +#define LOOP_NOTIFY 20 + +#define RAW_MODE CSSM_ALGMODE_ECB /* doesn't work for BSAFE */ +#define RAW_MODE_STREAM CSSM_ALGMODE_NONE +#define COOKED_MODE CSSM_ALGMODE_CBCPadIV8 + +#define RAW_MODE_STR "ECB" +#define RAW_MODE_STREAM_STR "None" +#define COOKED_MODE_STR "CBC/Pad" + +/* + * Enumerate algs our own way to allow iteration. + */ +typedef enum { + ALG_ASC = 1, // not tested - no reference available + ALG_DES = 1, + ALG_RC2, + ALG_RC4, + ALG_RC5, + ALG_3DES, + ALG_AES, + ALG_AES192, /* 192 bit block */ + ALG_AES256, /* 256 bit block */ + ALG_BFISH, + ALG_CAST +} SymAlg; +#define ALG_FIRST ALG_ASC +#define ALG_LAST ALG_CAST + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" a=algorithm (d=DES; 3=3DES3; 2=RC2; 4=RC4; 5=RC5; a=AES; A=AES192; \n"); + printf(" 6=AES256; b=Blowfish; c=CAST; s=ASC; default=all)\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" k=keySizeInBits\n"); + printf(" m=maxPtextSize (default=%d)\n", MAX_DATA_SIZE); + printf(" n=minPtextSize (default=%d)\n", MIN_DATA_SIZE); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +#define LOG_STAGED_OPS 0 +#if LOG_STAGED_OPS +#define soprintf(s) printf s +#else +#define soprintf(s) +#endif + +/* + * Multipurpose encrypt. Like cspStagedEncrypt(), but it takes a + * context handle and doesn't have as many options. + */ +static CSSM_RETURN stagedEncrypt( + CSSM_CSP_HANDLE cspHand, + CSSM_CC_HANDLE cryptHand, + uint32 algorithm, // CSSM_ALGID_FEED, etc. + uint32 cipherBlockSizeBytes,// optional + const CSSM_DATA *iv, // init vector, optional + const CSSM_DATA *ptext, + CSSM_DATA_PTR ctext, // mallocd by caller, must be big enough! + CSSM_BOOL multiUpdates) // false:single update, true:multi updates +{ + CSSM_RETURN crtn; + CSSM_SIZE bytesEncrypted; // per update + CSSM_SIZE bytesEncryptedTotal = 0; + CSSM_RETURN ocrtn = CSSM_OK; // 'our' crtn + unsigned toMove; // remaining + unsigned thisMove; // bytes to encrypt on this update + CSSM_DATA thisPtext; // running ptr into ptext + CSSM_DATA thisCtext; // running ptr into ctext + CSSM_BOOL restoreErr = CSSM_FALSE; + CSSM_RETURN savedErr = CSSM_OK; + CSSM_SIZE ctextLen; + + if(cipherBlockSizeBytes) { + crtn = AddContextAttribute(cryptHand, + CSSM_ATTRIBUTE_BLOCK_SIZE, + sizeof(uint32), + CAT_Uint32, + NULL, + cipherBlockSizeBytes); + if(crtn) { + printError("CSSM_UpdateContextAttributes", crtn); + ocrtn = crtn; + goto abort; + } + } + + thisPtext = *ptext; + thisCtext = *ctext; + memset(ctext->Data, 0, ctext->Length); + ctextLen = ctext->Length; + + crtn = CSSM_EncryptDataInit(cryptHand); + if(crtn) { + printError("CSSM_EncryptDataInit", crtn); + ocrtn = crtn; + goto abort; + } + + toMove = ptext->Length; + while(toMove) { + if(multiUpdates) { + thisMove = genRand(1, toMove); + } + else { + /* just do one pass thru this loop */ + thisMove = toMove; + } + thisPtext.Length = thisMove; + crtn = CSSM_EncryptDataUpdate(cryptHand, + &thisPtext, + 1, + &thisCtext, + 1, + &bytesEncrypted); + if(crtn) { + printError("CSSM_EncryptDataUpdate", crtn); + ocrtn = crtn; + goto abort; + } + soprintf(("*** EncryptDataUpdate: ptextLen 0x%x bytesEncrypted 0x%x\n", + (unsigned)thisMove, (unsigned)bytesEncrypted)); + + // NOTE: We return the proper length in ctext.... + ctextLen -= bytesEncrypted; // bump out ptr + thisCtext.Length = ctextLen; + thisCtext.Data += bytesEncrypted; + bytesEncryptedTotal += bytesEncrypted; + thisPtext.Data += thisMove; // bump in ptr + toMove -= thisMove; + } + /* OK, one more */ + crtn = CSSM_EncryptDataFinal(cryptHand, &thisCtext); + if(crtn) { + printError("CSSM_EncryptDataFinal", crtn); + savedErr = crtn; + restoreErr = CSSM_TRUE; + goto abort; + } + soprintf(("*** EncryptDataFinal: bytesEncrypted 0x%x\n", + (unsigned)thisCtext.Length)); + bytesEncryptedTotal += thisCtext.Length; + ctext->Length = bytesEncryptedTotal; +abort: + if(restoreErr) { + /* give caller the error from the encrypt */ + ocrtn = savedErr; + } + return ocrtn; +} + +/* + * Multipurpose decrypt. Like cspStagedDecrypt(), but it takes a + * context handle and doesn't have as many options. + */ +CSSM_RETURN stagedDecrypt( + CSSM_CSP_HANDLE cspHand, + CSSM_CC_HANDLE cryptHand, + uint32 algorithm, // CSSM_ALGID_FEED, etc. + uint32 cipherBlockSizeBytes,// optional + const CSSM_DATA *iv, // init vector, optional + const CSSM_DATA *ctext, + CSSM_DATA_PTR ptext, // mallocd by caller, must be big enough! + CSSM_BOOL multiUpdates) // false:single update, true:multi updates +{ + CSSM_RETURN crtn; + CSSM_SIZE bytesDecrypted; // per update + CSSM_SIZE bytesDecryptedTotal = 0; + CSSM_RETURN ocrtn = CSSM_OK; // 'our' crtn + unsigned toMove; // remaining + unsigned thisMove; // bytes to decrypt on this update + CSSM_DATA thisCtext; // running ptr into ptext + CSSM_DATA thisPtext; // running ptr into ctext + CSSM_SIZE ptextLen; + + if(cipherBlockSizeBytes) { + crtn = AddContextAttribute(cryptHand, + CSSM_ATTRIBUTE_BLOCK_SIZE, + sizeof(uint32), + CAT_Uint32, + NULL, + cipherBlockSizeBytes); + if(crtn) { + printError("CSSM_UpdateContextAttributes", crtn); + ocrtn = crtn; + goto abort; + } + } + + thisCtext = *ctext; + thisPtext = *ptext; + memset(ptext->Data, 0, ptext->Length); + ptextLen = ptext->Length; + + crtn = CSSM_DecryptDataInit(cryptHand); + if(crtn) { + printError("CSSM_DecryptDataInit", crtn); + ocrtn = crtn; + goto abort; + } + + toMove = ctext->Length; + while(toMove) { + if(multiUpdates) { + thisMove = genRand(1, toMove); + } + else { + /* just do one pass thru this loop */ + thisMove = toMove; + } + thisCtext.Length = thisMove; + crtn = CSSM_DecryptDataUpdate(cryptHand, + &thisCtext, + 1, + &thisPtext, + 1, + &bytesDecrypted); + if(crtn) { + printError("CSSM_DecryptDataUpdate", crtn); + ocrtn = crtn; + goto abort; + } + soprintf(("*** DecryptDataUpdate: ctextLen 0x%x bytesDecrypted 0x%x\n", + (unsigned)thisMove, (unsigned)bytesDecrypted)); + + // NOTE: We return the proper length in ptext.... + ptextLen -= bytesDecrypted; // bump out ptr + thisPtext.Length = ptextLen; + thisPtext.Data += bytesDecrypted; + bytesDecryptedTotal += bytesDecrypted; + thisCtext.Data += thisMove; // bump in ptr + toMove -= thisMove; + } + /* OK, one more */ + crtn = CSSM_DecryptDataFinal(cryptHand, &thisPtext); + if(crtn) { + printError("CSSM_DecryptDataFinal", crtn); + ocrtn = crtn; + goto abort; + } + soprintf(("*** DecryptDataFinal: bytesEncrypted 0x%x\n", + (unsigned)thisPtext.Length)); + bytesDecryptedTotal += thisPtext.Length; + ptext->Length = bytesDecryptedTotal; +abort: + return ocrtn; +} + +static int doTest( + CSSM_CSP_HANDLE cspHand, + const CSSM_DATA *ptext, + const CSSM_DATA *ctext1, + const CSSM_DATA *ctext2, + const CSSM_DATA *rptext, + const CSSM_DATA *keyData, + const CSSM_DATA *iv, + uint32 keyAlg, // CSSM_ALGID_xxx of the key + uint32 encrAlg, // encrypt/decrypt + uint32 encrMode, + uint32 padding, + uint32 keySizeInBits, + uint32 cipherBlockSizeBytes, + CSSM_BOOL quiet) +{ + CSSM_DATA lctext1; + CSSM_DATA lctext2; + CSSM_DATA lrptext; + int rtn = 0; + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand1 = 0; + CSSM_CC_HANDLE ccHand2 = 0; + CSSM_KEY key1; + CSSM_KEY key2; + uint8 dummy[cipherBlockSizeBytes]; + CSSM_DATA dummyData = {cipherBlockSizeBytes, dummy}; + + /* + * generate two equivalent keys key1 and key2; + * generate two CC handles ccHand1, ccHand2; + * encrypt dummy data with ccHand1 to get it cooked; + * encrypt ptext with ccHand1 ==> ctext1; + * encrypt ptext with ccHand2 ==> ctext2; + * Compare ctext1 and ctext2; + * decrypt ctext1 with ccHand1, compare with ptext; + */ + crtn = cspGenSymKeyWithBits(cspHand, keyAlg, CSSM_KEYUSE_ANY, + keyData, keySizeInBits / 8, &key1); + if(crtn) { + return crtn; + } + crtn = cspGenSymKeyWithBits(cspHand, keyAlg, CSSM_KEYUSE_ANY, + keyData, keySizeInBits / 8, &key2); + if(crtn) { + return crtn; + } + ccHand1 = genCryptHandle(cspHand, + encrAlg, + encrMode, + padding, + &key1, + NULL, // pubKey + iv, + 0, // effectiveKeySizeInBits + 0); // rounds + if(ccHand1 == 0) { + return CSSMERR_CSP_INTERNAL_ERROR; + } + ccHand2 = genCryptHandle(cspHand, + encrAlg, + encrMode, + padding, + &key2, + NULL, // pubKey + iv, + 0, // effectiveKeySizeInBits + 0); // rounds + if(ccHand2 == 0) { + return CSSMERR_CSP_INTERNAL_ERROR; + } + + /* dummy encrypt to heat up ccHand1 */ + appGetRandomBytes(dummy, sizeof(dummy)); + lctext1 = *ctext1; + crtn = stagedEncrypt(cspHand, ccHand1, encrAlg, cipherBlockSizeBytes, + iv, &dummyData, &lctext1, CSSM_FALSE); + if(crtn) { + return crtn; + } + + /* encrypt ptext with ccHand1 and ccHand2, compare ctext */ + lctext1 = *ctext1; + crtn = stagedEncrypt(cspHand, ccHand1, encrAlg, cipherBlockSizeBytes, + iv, ptext, &lctext1, CSSM_TRUE); + if(crtn) { + return crtn; + } + lctext2 = *ctext2; + crtn = stagedEncrypt(cspHand, ccHand2, encrAlg, cipherBlockSizeBytes, + iv, ptext, &lctext2, CSSM_TRUE); + if(crtn) { + return crtn; + } + if(!appCompareCssmData(&lctext1, &lctext2)) { + printf("***Ciphertext miscompare\n"); + if(testError(quiet)) { + return 1; + } + } + + /* decrypt with ccHand1, compare with ptext */ + lrptext = *rptext; + crtn = stagedDecrypt(cspHand, ccHand1, encrAlg, cipherBlockSizeBytes, + iv, &lctext1, &lrptext, CSSM_TRUE); + if(crtn) { + return crtn; + } + if(!appCompareCssmData(&lctext1, &lctext2)) { + printf("***Plaintext miscompare\n"); + if(testError(quiet)) { + return 1; + } + } + + if(ccHand1) { + CSSM_DeleteContext(ccHand1); + } + if(ccHand2) { + CSSM_DeleteContext(ccHand2); + } + return rtn; +} + + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + CSSM_DATA ptext; + CSSM_DATA ctext1; + CSSM_DATA ctext2; + CSSM_DATA rptext; + CSSM_CSP_HANDLE cspHand; + const char *algStr; + uint32 keyAlg; // CSSM_ALGID_xxx of the key + uint32 encrAlg; // CSSM_ALGID_xxx of encr/decr + unsigned currAlg; // ALG_xxx + uint32 keySizeInBits; + int rtn = 0; + CSSM_DATA keyData; + CSSM_DATA initVector; + uint32 minTextSize; + uint32 rawMode; + uint32 cookedMode; + const char *rawModeStr; + const char *cookedModeStr; + uint32 algBlockSizeBytes; + + /* + * User-spec'd params + */ + CSSM_BOOL keySizeSpec = CSSM_FALSE; // false: use rand key size + unsigned minAlg = ALG_FIRST; + unsigned maxAlg = ALG_LAST; + unsigned loops = LOOPS_DEF; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + unsigned pauseInterval = 0; + uint32 padding; + CSSM_BOOL bareCsp = CSSM_TRUE; + unsigned maxPtextSize = MAX_DATA_SIZE; + unsigned minPtextSize = MIN_DATA_SIZE; + + for(arg=1; arg +#include +#include "cputime.h" +#include + +#define WAIT_TIME_SEC 1.0 + +int main() +{ + CPUTime cputimeStart, cputimeEnd; + CFAbsoluteTime start; + + printf("Resolution on this machine: %f nanoseconds\n", + CPUTimeDeltaUs(0ULL, 1ULL) * 1000.0); + + start = CFAbsoluteTimeGetCurrent(); + cputimeStart = CPUTimeRead(); + while((CFAbsoluteTimeGetCurrent() - start) < WAIT_TIME_SEC) { + ; + } + cputimeEnd = CPUTimeRead(); + + printf("Waited %f sec; elapsed CPUTime %f s\n", + WAIT_TIME_SEC, CPUTimeDeltaSec(cputimeStart, cputimeEnd)); + printf("cputimeStart %08X:%08X cputimeEnd %08X:%08X\n", + (unsigned)(cputimeStart >> 32), + (unsigned)(cputimeStart & 0xffffffffULL), + (unsigned)(cputimeEnd >> 32), + (unsigned)(cputimeEnd & 0xffffffffULL)); + printf("cputime raw delta %lu\n", + (unsigned long)(cputimeEnd - cputimeStart)); + + return 0; +} diff --git a/SecurityTests/cspxutils/cryptTool/Makefile b/SecurityTests/cspxutils/cryptTool/Makefile new file mode 100644 index 00000000..e1ab44d8 --- /dev/null +++ b/SecurityTests/cspxutils/cryptTool/Makefile @@ -0,0 +1,55 @@ +# name of executable to build +EXECUTABLE=cryptTool +# C++ source (with .cpp extension) +CPSOURCE= +# C source (.c extension) +CSOURCE= cryptTool.c + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= ptext + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +#PROJ_LDFLAGS= -lMallocDebug +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/cryptTool/README b/SecurityTests/cspxutils/cryptTool/README new file mode 100644 index 00000000..5493a4b8 --- /dev/null +++ b/SecurityTests/cspxutils/cryptTool/README @@ -0,0 +1,55 @@ + cryptTool Info + last update 4/24/2001 + +This directory contains a program, cryptTool, intended to illustrate +the use of the CDSA API to perform simple symmetric encryption +and decryption. The program consists of one source file, cryptTool.c. + +See the README in the parent directory (CDSA_Examples) for information +on building this program. + +The cryptTool program is a command-line utility which does the +following: + + create a symmetric key derived from a user-specified password; + read a user-specified input file; + either encrypt or decrypt that file using a the key generated + above and a user-specified encryption algorithm; + write the result out to a user-specified output file; + +Several different symmetric encryption algorithms are supported, +illustrating the use of both stream and block ciphers. + +Running cryptTool with no command-line arguments gives usage +instructions, like so: + + localhost> ./cryptTool + usage: + ./cryptTool op password keySize inFile outFile [a=algorithm] + op: + e encrypt + d decrypt + algorithm: + 4 RC4 (default if no algorithm specified) + c ASC/ComCryption + d DES + a AES + +All arguments except for the last one are required. A description of the +arguments follows. + + op Indicates whether to encrypt (e) or decrypt (d) + password A user-specified ASCII string which is used to derive a + symmetric key. + keySize The key size in bytes. This is variable for stream ciphers + and fixed for block ciphers. + inFile The name of the file to encrypt or decrypt. + outFile The name of the file to which the result of the encrypt or + decrypt is written. + algorithm An optional algorithm. + +A shell script, runCrypt, is also provided which illustrates the actual +usage of cryptTool to encrypt a file and decrypt the result. Run this +script with no arguments to show a typical sequence of operations. The +runCrypt script and the cryptTool executable must be in the same +directory. diff --git a/SecurityTests/cspxutils/cryptTool/cryptTool.c b/SecurityTests/cspxutils/cryptTool/cryptTool.c new file mode 100644 index 00000000..e4037952 --- /dev/null +++ b/SecurityTests/cspxutils/cryptTool/cryptTool.c @@ -0,0 +1,415 @@ +/* + File: cryptTool.c + + Description: simple encrypt/decrypt utility to demonstrate CDSA API + used for symmetric encryption + + Author: dmitch + + Copyright: Copyright (c) 2001,2003,2005-2006 Apple Computer, Inc. All Rights Reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple + Computer, Inc. ("Apple") in consideration of your agreement to + the following terms, and your use, installation, modification + or redistribution of this Apple software constitutes acceptance + of these terms. If you do not agree with these terms, please + do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following + terms, and subject to these terms, Apple grants you a personal, + non-exclusive license, under Apple's copyrights in this + original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with + or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in + its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all + such redistributions of the Apple Software. Neither the + name, trademarks, service marks or logos of Apple Computer, + Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from + Apple. Except as expressly stated in this notice, no other + rights or licenses, express or implied, are granted by Apple + herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works + in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. + APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE + OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, + INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION + AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING + NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE + HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "common.h" +#include +#include +#include +#include + +static void usage(char **argv) +{ + printf("usage:\n"); + printf(" %s op password keySize inFile outFile [a=algorithm]\n", argv[0]); + printf(" op:\n"); + printf(" e encrypt\n"); + printf(" d decrypt\n"); + printf(" algorithm:\n"); + printf(" 4 RC4 (default if no algorithm specified)\n"); + printf(" c ASC/ComCryption\n"); + printf(" d DES\n"); + printf(" a AES\n"); + exit(1); +} + +/* + * Derive symmetric key. + */ +static CSSM_RETURN ctDeriveKey(CSSM_CSP_HANDLE cspHand, + uint32 keyAlg, // CSSM_ALGID_RC5, etc. + const char *keyLabel, + unsigned keyLabelLen, + uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + uint32 keySizeInBits, + CSSM_DATA_PTR password, // in PKCS-5 lingo + CSSM_DATA_PTR salt, // ditto + uint32 iterationCnt, // ditto + CSSM_KEY_PTR key) +{ + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + uint32 keyAttr; + CSSM_DATA dummyLabel; + CSSM_PKCS5_PBKDF2_PARAMS pbeParams; + CSSM_DATA pbeData; + CSSM_ACCESS_CREDENTIALS creds; + + memset(key, 0, sizeof(CSSM_KEY)); + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand, + CSSM_ALGID_PKCS5_PBKDF2, + keyAlg, + keySizeInBits, + &creds, + NULL, // BaseKey + iterationCnt, + salt, + NULL, // seed + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateDeriveKeyContext", crtn); + return crtn; + } + keyAttr = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_REF | + CSSM_KEYATTR_SENSITIVE; + dummyLabel.Length = keyLabelLen; + dummyLabel.Data = (uint8 *)keyLabel; + + /* passing in password is pretty strange....*/ + pbeParams.Passphrase = *password; + pbeParams.PseudoRandomFunction = CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1; + pbeData.Data = (uint8 *)&pbeParams; + pbeData.Length = sizeof(pbeParams); + crtn = CSSM_DeriveKey(ccHand, + &pbeData, + keyUsage, + keyAttr, + &dummyLabel, + NULL, // cred and acl + key); + if(crtn) { + printError("CSSM_DeriveKey", crtn); + return crtn; + } + crtn = CSSM_DeleteContext(ccHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + } + return crtn; +} + + +int main(int argc, char **argv) +{ + int rtn; + uint32 keySizeInBytes; // from cmd line + char *password; // ASCII password from cmd line + char *inFileName; // from cmd line + unsigned char *inFile; // raw infile data + unsigned inFileSize; // in bytes + char *outFileName; // from cmd line + CSSM_CSP_HANDLE cspHand; + CSSM_RETURN crtn; + int doEncrypt = 0; + CSSM_DATA passwordData; + CSSM_DATA saltData = {8, (uint8 *)"someSalt"}; + CSSM_DATA inData; // data to encrypt/decrypt, from inFile + CSSM_DATA outData = {0, NULL};// result data, written to outFile + CSSM_CC_HANDLE ccHand; // crypto context + CSSM_DATA remData = {0, NULL}; + CSSM_SIZE bytesProcessed; + CSSM_KEY symKey; + char algSpec = '4'; + CSSM_ALGORITHMS keyAlg = 0; + CSSM_ALGORITHMS encrAlg = 0; + CSSM_ENCRYPT_MODE encrMode = 0; + CSSM_PADDING padding = 0; + /* max of 16 bytes of init vector for the algs we use */ + CSSM_DATA initVect = {16, (uint8 *)"someStrangeInitVector"}; + CSSM_DATA_PTR initVectPtr = NULL; + + if(argc < 6) { + usage(argv); + } + + /* gather up cmd line args */ + switch(argv[1][0]) { + case 'e': + doEncrypt = 1; + break; + case 'd': + doEncrypt = 0; + break; + default: + usage(argv); + } + password = argv[2]; + passwordData.Data = (uint8 *)password; + passwordData.Length = strlen(password); + keySizeInBytes = atoi(argv[3]); + if(keySizeInBytes == 0) { + printf("keySize of 0 illegal\n"); + exit(1); + } + inFileName = argv[4]; + outFileName = argv[5]; + + /* optional algorithm specifier */ + if(argc == 7) { + if(argv[6][0] != 'a') { + usage(argv); + } + algSpec = argv[6][2]; + } + + /* algorithm-specific parameters */ + switch(algSpec) { + case '4': + /* RC4 stream cipher - no padding, no IV, variable key size */ + keyAlg = CSSM_ALGID_RC4; + encrAlg = CSSM_ALGID_RC4; + encrMode = CSSM_ALGMODE_NONE; + padding = CSSM_PADDING_NONE; + break; + case 'c': + /* ComCryption stream cipher - no padding, no IV, variable key size */ + keyAlg = CSSM_ALGID_ASC; + encrAlg = CSSM_ALGID_ASC; + encrMode = CSSM_ALGMODE_NONE; + padding = CSSM_PADDING_NONE; + break; + case 'd': + /* DES block cipher, block size = 8 bytes, fixed key size */ + if(keySizeInBytes != 8) { + printf("***DES must have key size of 8 bytes\n"); + exit(1); + } + keyAlg = CSSM_ALGID_DES; + encrAlg = CSSM_ALGID_DES; + encrMode = CSSM_ALGMODE_CBCPadIV8; + padding = CSSM_PADDING_PKCS7; + initVect.Length = 8; + initVectPtr = &initVect; + break; + case 'a': + /* AES block cipher, block size = 16 bytes, fixed key size */ + if(keySizeInBytes != 16) { + printf("***AES must have key size of 8 bytes\n"); + exit(1); + } + keyAlg = CSSM_ALGID_AES; + encrAlg = CSSM_ALGID_AES; + encrMode = CSSM_ALGMODE_CBCPadIV8; + padding = CSSM_PADDING_PKCS7; + initVect.Length = 16; + initVectPtr = &initVect; + break; + default: + usage(argv); + } + + /* read inFile from disk */ + rtn = readFile(inFileName, &inFile, &inFileSize); + if(rtn) { + printf("Error reading %s: %s\n", inFileName, strerror(rtn)); + exit(1); + } + inData.Data = inFile; + inData.Length = inFileSize; + + /* attach to CSP */ + cspHand = cspStartup(); + if(cspHand == 0) { + exit(1); + } + + /* + * Derive an actual encryption/decryption key from the password ASCII text. + * We could use the ASCII text directly as key material but using the DeriveKey + * function is much more secure (besides being an industry-standard way to + * convert an ASCII password into binary key material). + */ + crtn = ctDeriveKey(cspHand, + keyAlg, + "someLabel", // keyLabel, not important + 9, // keyLabelLen + doEncrypt ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT, + keySizeInBytes * 8, // keySizeInBits, + &passwordData, + &saltData, + 1000, // iterCount, 1000 is the minimum + &symKey); + if(crtn) { + exit(1); + } + + /* + * Cook up a symmetric encrypt/decrypt context using the key we just derived + */ + crtn = CSSM_CSP_CreateSymmetricContext(cspHand, + encrAlg, // encryption algorithm + encrMode, // mode + NULL, // access cred + &symKey, + initVectPtr, // InitVector + padding, // Padding + NULL, // Params + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateSymmetricContext", crtn); + exit(1); + } + + /* + * Do the encrypt/decrypt. + * We do this with the init/update/final sequence only to demonstrate its + * usage. + */ + if(doEncrypt) { + crtn = CSSM_EncryptDataInit(ccHand); + if(crtn) { + printError("CSSM_EncryptDataInit", crtn); + exit(1); + } + + /* this step can be performed an arbitrary number of times, with + * the appropriate housekeeping of inData and outData */ + crtn = CSSM_EncryptDataUpdate(ccHand, + &inData, + 1, + &outData, + 1, + &bytesProcessed); + if(crtn) { + printError("CSSM_EncryptDataUpdate", crtn); + exit(1); + } + outData.Length = bytesProcessed; + + /* one call more to clean up */ + crtn = CSSM_EncryptDataFinal(ccHand, &remData); + if(crtn) { + printError("CSSM_EncryptDataFinal", crtn); + exit(1); + } + if(remData.Length != 0) { + /* append remaining data to outData */ + uint32 newLen = outData.Length + remData.Length; + outData.Data = (uint8 *)appRealloc(outData.Data, + newLen, + NULL); + memmove(outData.Data + outData.Length, remData.Data, remData.Length); + outData.Length = newLen; + appFree(remData.Data, NULL); + } + } + else { + crtn = CSSM_DecryptDataInit(ccHand); + if(crtn) { + printError("CSSM_DecryptDataInit", crtn); + exit(1); + } + + /* this step can be performed an arbitrary number of times, with + * the appropriate housekeeping of inData and outData */ + crtn = CSSM_DecryptDataUpdate(ccHand, + &inData, + 1, + &outData, + 1, + &bytesProcessed); + if(crtn) { + printError("CSSM_DecryptDataUpdate", crtn); + exit(1); + } + outData.Length = bytesProcessed; + + /* one call more to clean up */ + crtn = CSSM_DecryptDataFinal(ccHand, &remData); + if(crtn) { + printError("CSSM_DecryptDataFinal", crtn); + exit(1); + } + if(remData.Length != 0) { + /* append remaining data to outData */ + uint32 newLen = outData.Length + remData.Length; + outData.Data = (uint8 *)appRealloc(outData.Data, + newLen, + NULL); + memmove(outData.Data + outData.Length, remData.Data, remData.Length); + outData.Length = newLen; + appFree(remData.Data, NULL); + } + } + if(crtn == CSSM_OK) { + rtn = writeFile(outFileName, outData.Data, outData.Length); + if(rtn) { + printf("Error writing %s: %s\n", outFileName, strerror(rtn)); + exit(1); + } + else { + printf("SUCCESS: inFile length %u bytes, outFile length %u bytes\n", + inFileSize, (unsigned)outData.Length); + } + } + /* free resources */ + crtn = CSSM_DeleteContext(ccHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + } + crtn = CSSM_FreeKey(cspHand, + NULL, // access cred + &symKey, + CSSM_FALSE); // don't delete since it wasn't permanent + if(crtn) { + printError("CSSM_FreeKey", crtn); + } + free(inFile); // mallocd by readFile() + + /* this was mallocd by CSP */ + appFree(outData.Data, NULL); + CSSM_ModuleDetach(cspHand); + return rtn; +} + diff --git a/SecurityTests/cspxutils/cryptTool/runCrypt b/SecurityTests/cspxutils/cryptTool/runCrypt new file mode 100755 index 00000000..a77f52b0 --- /dev/null +++ b/SecurityTests/cspxutils/cryptTool/runCrypt @@ -0,0 +1,27 @@ +#! /bin/csh -f +# +# Simple script to demonstrate usage of cryptTool. +# +# create a simple text file; dump its contents; +# encrypt the file using RC4; +# dump the binary contents of the resulting ciphertext; +# decrypt using RC4; +# dump the resulting plaintext file; +# +set PLAINTEXT_FILE=ptext +set CIPHERTEXT_FILE=ctext +set RECOVERED_FILE=rptext +# +echo Creating plaintext.... +echo "This is a simple plaintext file for demonstration." > $PLAINTEXT_FILE +echo Contents of plaintext: +cat $PLAINTEXT_FILE +echo Encrypting plaintext... +./cryptTool e foobar 16 $PLAINTEXT_FILE $CIPHERTEXT_FILE +echo Contents of ciphertext: +/usr/bin/hexdump $CIPHERTEXT_FILE +echo Decrypting.... +./cryptTool d foobar 16 $CIPHERTEXT_FILE $RECOVERED_FILE +echo Contents of recovered text: +cat $RECOVERED_FILE +echo Done. diff --git a/SecurityTests/cspxutils/cspdvt b/SecurityTests/cspxutils/cspdvt new file mode 100755 index 00000000..73a76968 --- /dev/null +++ b/SecurityTests/cspxutils/cspdvt @@ -0,0 +1,185 @@ +#! /bin/csh -f +# +# run CSP/X regression tests. +# +set BUILD_DIR=$LOCAL_BUILD_DIR +# +set QUICK_TEST = 1 +set QUIET= +set VERB= +# +# CSPDL null for bare CSP, 'D' for CSPDL combo +# +set CSPDL= +set RAWCSP=YES +# +# note the 's' option is here for backwards compatibility; the short +# option is now the default. +# +while ( $#argv > 0 ) + switch ( "$argv[1]" ) + case s: + set QUICK_TEST = 1 + shift + breaksw + case l: + set QUICK_TEST = 0 + shift + breaksw + case v: + set VERB = v + shift + breaksw + case q: + set QUIET = q + shift + breaksw + case D: + set CSPDL = D + set RAWCSP = NO + shift + breaksw + default: + cat cspdvt_usage + exit(1) + endsw +end +# +# Select 'quick' or 'normal' test params +# +if($QUICK_TEST == 1) then + set SIGTEST_ARGS= + set BADSIG_ARGS="l=4 i=10" + set MACTEST_ARGS= + set BADMAC_ARGS= + set DSAPARTIAL_ARGS= + set HASHTEST_ARGS="l=100" + set HASHCLONE_ARGS= + set SYMTEST_ARGS= + set ASYMTEST_ARGS="u" + set MINIWRAP_ARGS="l=4" + set WRAPTEST_ARGS="l=2 k" + set PBETEST_ARGS="l=4" + set KEYHASH_ARGS= + set KEYHASH_ASYM_ARGS= + set KEYSTORE_ARGS= + set SYMDELTA_ARGS= + set SYMCOMPAT_ARGS= + set HASHCOMPAT_ARGS= + set ASYMCOMPAT_ARGS="l=2 k=512" + set MACCOMPAT_ARGS= + set BADATTR_ARGS= + set RAWSIG_ARGS="l=2 i=2 s" + set DHTEST_ARGS="i=dhParams_512.der" + set ECDHTEST_ARGS= +else + set SIGTEST_ARGS= + set BADSIG_ARGS="l=20 k=r" + set DSAPARTIAL_ARGS="l=100" + set MACTEST_ARGS= + set BADMAC_ARGS="l=100" + set HASHTEST_ARGS="l=1000" + set HASHCLONE_ARGS="l=200" + set SYMTEST_ARGS="l=500" + set ASYMTEST_ARGS= + set MINIWRAP_ARGS= + set WRAPTEST_ARGS= + set PBETEST_ARGS= + set KEYHASH_ARGS= + set KEYHASH_ASYM_ARGS= + set KEYSTORE_ARGS= + set SYMDELTA_ARGS="l=50" + set SYMCOMPAT_ARGS= + set HASHCOMPAT_ARGS="l=1000" + set ASYMCOMPAT_ARGS="l=10" + set MACCOMPAT_ARGS="l=1000" + set BADATTR_ARGS= + set RAWSIG_ARGS= + set DHTEST_ARGS="k=1024" + set ECDHTEST_ARGS="l=100" +endif +# +# First, test the basic Digest, MAC, and symmetrict algorithms in libSystem. +# +set CSPXUTILS=`pwd` +if($RAWCSP == YES) then + ./ccdvt $QUIET || exit(1) +endif +# +# Basic digest and MAC tests +# +$BUILD_DIR/hashTest $HASHTEST_ARGS $QUIET $VERB $CSPDL || exit(1) +if($RAWCSP == YES) then + $BUILD_DIR/hashClone $HASHCLONE_ARGS $QUIET $VERB $CSPDL || exit(1) +endif +#TODO $BUILD_DIR/hashCompat $HASHCOMPAT_ARGS $QUIET $VERB $CSPDL || exit(1) +$BUILD_DIR/sha2VectorsCdsa $QUIET $CSPDL || exit(1) +#TODO $BUILD_DIR/macCompat $MACCOMPAT_ARGS $QUIET $VERB $CSPDL || exit(1) +$BUILD_DIR/macTest $MACTEST_ARGS $QUIET $VERB $CSPDL || exit(1) +$BUILD_DIR/badmac $BADMAC_ARGS $QUIET $VERB $CSPDL || exit(1) +# +# Basic symmetric encryption tests +# +# symTest - once with padding, once without +$BUILD_DIR/symTest $SYMTEST_ARGS $QUIET $VERB $CSPDL || exit(1) +$BUILD_DIR/symTest $SYMTEST_ARGS $QUIET $VERB $CSPDL o || exit(1) +# +# symCompat - once with the full set of algorithms +# +#TODO $BUILD_DIR/symCompat $SYMCOMPAT_ARGS $QUIET $VERB $CSPDL || exit(1) +# +# And one specifically to test AES padding mode (which uses ssleay instead of +# the NIST reference implementation) +# +$BUILD_DIR/symCompat $SYMCOMPAT_ARGS a=a y $QUIET $VERB $CSPDL || exit(1) +$BUILD_DIR/contextReuse $QUIET $VERB $CSPDL || exit(1) +# +# Signature tests +# +# One for RSA +$BUILD_DIR/sigtest $SIGTEST_ARGS $QUIET $VERB $CSPDL || exit(1) +# Several for for ECDSA, with some keys in blob form for raw CSP only +$BUILD_DIR/sigtest a=E $SIGTEST_ARGS $QUIET $VERB $CSPDL || exit(1) +if($RAWCSP == YES) then + $BUILD_DIR/sigtest a=7 b r $SIGTEST_ARGS $QUIET $VERB $CSPDL || exit(1) + $BUILD_DIR/sigtest a=8 k=256 b $SIGTEST_ARGS $QUIET $VERB $CSPDL || exit(1) + $BUILD_DIR/sigtest a=9 k=521 b r $SIGTEST_ARGS $QUIET $VERB $CSPDL || exit(1) +else + $BUILD_DIR/sigtest a=7 $SIGTEST_ARGS $QUIET $VERB $CSPDL || exit(1) + $BUILD_DIR/sigtest a=8 k=256 $SIGTEST_ARGS $QUIET $VERB $CSPDL || exit(1) + $BUILD_DIR/sigtest a=9 k=521 $SIGTEST_ARGS $QUIET $VERB $CSPDL || exit(1) +endif +# this one tests all algorithms with random key sizes +$BUILD_DIR/badsig $BADSIG_ARGS $QUIET $VERB $CSPDL || exit(1) +# +# Misc. CSP tests +# +$BUILD_DIR/keyDate $QUIET $VERB $CSPDL || exit(1) +$BUILD_DIR/keyHash $KEYHASH_ARGS $QUIET $VERB $CSPDL || exit(1) +cd $CSPXUTILS/keyHashAsym +$BUILD_DIR/keyHashAsym $KEYHASH_ASYM_ARGS $QUIET $VERB $CSPDL || exit(1) +if($RAWCSP == NO) then + $BUILD_DIR/keyStore $KEYSTORE_ARGS $QUIET $VERB || exit(1) +endif +if($RAWCSP == YES) then + $BUILD_DIR/dhTest $DHTEST_ARGS $QUIET $VERB $CSPDL || exit(1) +endif +# +# One run for ECDH, one for ECDH_X963_KDF +# +$BUILD_DIR/ecdhTest $ECDHTEST_ARGS $QUIET $VERB $CSPDL || exit(1) +$BUILD_DIR/ecdhTest X $ECDHTEST_ARGS $QUIET $VERB $CSPDL || exit(1) +# this requires param files in cwd +cd $CSPXUTILS/dsaPartial +$BUILD_DIR/dsaPartial $DSAPARTIAL_ARGS $QUIET $VERB $CSPDL || exit(1) +$BUILD_DIR/symDelta $SYMDELTA_ARGS $QUIET $VERB $CSPDL || exit(1) +$BUILD_DIR/asymTest $ASYMTEST_ARGS $QUIET $VERB $CSPDL || exit(1) +$BUILD_DIR/miniWrap $MINIWRAP_ARGS $QUIET $VERB $CSPDL || exit(1) +$BUILD_DIR/wrapTest $WRAPTEST_ARGS $QUIET $VERB $CSPDL || exit(1) +$BUILD_DIR/pbeTest $PBETEST_ARGS $QUIET $VERB $CSPDL || exit(1) +#TODO $BUILD_DIR/asymCompat $ASYMCOMPAT_ARGS $QUIET $VERB $CSPDL || exit(1) +#TODO $BUILD_DIR/badattr $BADATTR_ARGS $QUIET $VERB $CSPDL || exit(1) +$BUILD_DIR/rawSig $RAWSIG_ARGS $QUIET $VERB $CSPDL || exit(1) +$BUILD_DIR/ssl2Padding $QUIET $VERB $CSPDL || exit(1) + +echo ===== cspdvt success ===== diff --git a/SecurityTests/cspxutils/cspdvt_usage b/SecurityTests/cspxutils/cspdvt_usage new file mode 100644 index 00000000..1b97bda5 --- /dev/null +++ b/SecurityTests/cspxutils/cspdvt_usage @@ -0,0 +1,7 @@ +Usage: cspdvt [options] +Options: + l long test + v verbose output + q quiet output + D CSPDL combo; default = bare CSP + h help diff --git a/SecurityTests/cspxutils/cspxutils.pbproj/project.pbxproj b/SecurityTests/cspxutils/cspxutils.pbproj/project.pbxproj new file mode 100644 index 00000000..848c69ba --- /dev/null +++ b/SecurityTests/cspxutils/cspxutils.pbproj/project.pbxproj @@ -0,0 +1,71 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 38; + objects = { + 055C346A044F0AF9006A3C68 = { + children = ( + ); + isa = PBXGroup; + refType = 4; + }; + 055C346C044F0AF9006A3C68 = { + buildRules = ( + ); + buildSettings = { + COPY_PHASE_STRIP = NO; + }; + isa = PBXBuildStyle; + name = Development; + }; + 055C346D044F0AF9006A3C68 = { + buildRules = ( + ); + buildSettings = { + COPY_PHASE_STRIP = YES; + }; + isa = PBXBuildStyle; + name = Deployment; + }; + 055C346E044F0AF9006A3C68 = { + buildStyles = ( + 055C346C044F0AF9006A3C68, + 055C346D044F0AF9006A3C68, + ); + hasScannedForEncodings = 1; + isa = PBXProject; + mainGroup = 055C346A044F0AF9006A3C68; + projectDirPath = ""; + targets = ( + 055C346F044F0B1B006A3C68, + ); + }; + 055C346F044F0B1B006A3C68 = { + buildArgumentsString = "$ACTION \"SRCROOT=$SRCROOT\" \"OBJROOT=$OBJROOT\" \"DSTROOT=$DSTROOT\" \"SRCROOT=$SRCROOT\""; + buildPhases = ( + ); + buildSettings = { + OPTIMIZATION_CFLAGS = ""; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = cspxutils; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; + }; + buildToolPath = /usr/bin/gnumake; + dependencies = ( + ); + isa = PBXLegacyTarget; + name = cspxutils; + passBuildSettingsInEnvironment = 1; + productName = cspxutils; + settingsToExpand = 6; + settingsToPassInEnvironment = 287; + settingsToPassOnCommandLine = 280; + }; + }; + rootObject = 055C346E044F0AF9006A3C68; +} diff --git a/SecurityTests/cspxutils/dbTool/Makefile b/SecurityTests/cspxutils/dbTool/Makefile new file mode 100644 index 00000000..53bb91cd --- /dev/null +++ b/SecurityTests/cspxutils/dbTool/Makefile @@ -0,0 +1,55 @@ +# name of executable to build +EXECUTABLE=dbTool +# C++ source (with .cpp extension) +CPSOURCE= dbTool.cpp dbAttrs.cpp dbCert.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +#PROJ_LDFLAGS= -lMallocDebug +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/dbTool/dbAttrs.cpp b/SecurityTests/cspxutils/dbTool/dbAttrs.cpp new file mode 100644 index 00000000..1f83765a --- /dev/null +++ b/SecurityTests/cspxutils/dbTool/dbAttrs.cpp @@ -0,0 +1,444 @@ +/* Copyright (c) 2002-2003,2006,2008 Apple Inc. + * + * dbAttrs.cpp - Apple DL/DB/Keychain attributes and name/value pairs. + * The attribute lists here are not necessarily complete lists + * of the attrs in any given schema; they are only the ones we want + * to examine with dbTool. + */ + +#include "dbAttrs.h" +#include +#include +#include +#include + +/* declare a CSSM_DB_ATTRIBUTE_INFO with NAME_AS_STRING */ +#define DB_ATTRIBUTE(name, type) \ + { CSSM_DB_ATTRIBUTE_NAME_AS_STRING, \ + {(char *)#name}, \ + CSSM_DB_ATTRIBUTE_FORMAT_ ## type \ + } + +/* declare a CSSM_DB_ATTRIBUTE_INFO with NAME_AS_INTEGER */ +#define DB_INT_ATTRIBUTE(name, type) \ + { CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, \ + { (char *)name }, \ + CSSM_DB_ATTRIBUTE_FORMAT_ ## type \ + } + + +/* declare one entry in a table of nameValuePairs */ +#define NVP(attr) {attr, #attr} + +/* the NULL entry which terminates all nameValuePair tables */ +#define NVP_END {0, NULL} + +/* declare a RelationInfo */ +#define RELATION_INFO(relationId, attributes, nameValues) \ + { relationId, \ + #relationId, \ + sizeof(attributes) / sizeof(CSSM_DB_ATTRIBUTE_INFO), \ + attributes, \ + nameValues } + +/* CSSM_DB_RECORDTYPE names */ +const NameValuePair recordTypeNames[] = +{ + NVP(CSSM_DL_DB_SCHEMA_INFO), + NVP(CSSM_DL_DB_SCHEMA_INDEXES), + NVP(CSSM_DL_DB_SCHEMA_ATTRIBUTES), + NVP(CSSM_DL_DB_SCHEMA_PARSING_MODULE), + NVP(CSSM_DL_DB_RECORD_ANY), + NVP(CSSM_DL_DB_RECORD_CERT), + NVP(CSSM_DL_DB_RECORD_CRL), + NVP(CSSM_DL_DB_RECORD_POLICY), + NVP(CSSM_DL_DB_RECORD_GENERIC), + NVP(CSSM_DL_DB_RECORD_PUBLIC_KEY), + NVP(CSSM_DL_DB_RECORD_PRIVATE_KEY), + NVP(CSSM_DL_DB_RECORD_SYMMETRIC_KEY), + NVP(CSSM_DL_DB_RECORD_ALL_KEYS), + /* Apple-specific */ + NVP(CSSM_DL_DB_RECORD_GENERIC_PASSWORD), + NVP(CSSM_DL_DB_RECORD_INTERNET_PASSWORD), + NVP(CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD), + NVP(CSSM_DL_DB_RECORD_X509_CERTIFICATE), + NVP(CSSM_DL_DB_RECORD_X509_CRL), + NVP(CSSM_DL_DB_RECORD_USER_TRUST), + /* private to AppleCSPDL */ + NVP(DBBlobRelationID), + /* private to Sec layer */ + NVP(CSSM_DL_DB_RECORD_UNLOCK_REFERRAL), + NVP(CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE), + NVP_END +}; + +/* CSSM_CERT_TYPE names */ +const NameValuePair certTypeNames[] = +{ + NVP(CSSM_CERT_UNKNOWN), + NVP(CSSM_CERT_X_509v1), + NVP(CSSM_CERT_X_509v2), + NVP(CSSM_CERT_X_509v3), + NVP(CSSM_CERT_PGP), + NVP(CSSM_CERT_SPKI), + NVP(CSSM_CERT_SDSIv1), + NVP(CSSM_CERT_Intel), + NVP(CSSM_CERT_X_509_ATTRIBUTE), + NVP(CSSM_CERT_X9_ATTRIBUTE), + NVP(CSSM_CERT_TUPLE), + NVP(CSSM_CERT_ACL_ENTRY), + NVP(CSSM_CERT_MULTIPLE), + NVP_END +}; + +/* CSSM_CERT_ENCODING names */ +const NameValuePair certEncodingNames[] = +{ + NVP(CSSM_CERT_ENCODING_UNKNOWN), + NVP(CSSM_CERT_ENCODING_CUSTOM), + NVP(CSSM_CERT_ENCODING_BER), + NVP(CSSM_CERT_ENCODING_DER), + NVP(CSSM_CERT_ENCODING_NDR), + NVP(CSSM_CERT_ENCODING_SEXPR), + NVP(CSSM_CERT_ENCODING_PGP), + NVP(CSSM_CERT_ENCODING_MULTIPLE), + NVP_END +}; + +/* CSSM_CRL_TYPE names */ +const NameValuePair crlTypeNames[] = +{ + NVP(CSSM_CRL_TYPE_UNKNOWN), + NVP(CSSM_CRL_TYPE_X_509v1), + NVP(CSSM_CRL_TYPE_X_509v2), + NVP(CSSM_CRL_TYPE_SPKI), + NVP(CSSM_CRL_TYPE_MULTIPLE), + NVP_END +}; + +/* CSSM_CRL_ENCODING names */ +const NameValuePair crlEncodingNames[] = +{ + NVP(CSSM_CRL_ENCODING_UNKNOWN), + NVP(CSSM_CRL_ENCODING_CUSTOM), + NVP(CSSM_CRL_ENCODING_BER), + NVP(CSSM_CRL_ENCODING_DER), + NVP(CSSM_CRL_ENCODING_BLOOM), + NVP(CSSM_CRL_ENCODING_SEXPR), + NVP(CSSM_CRL_ENCODING_MULTIPLE), + NVP_END +}; + + +/* CSSM_ALGORITHMS names */ +const NameValuePair algIdNames[] = +{ + NVP(CSSM_ALGID_NONE), + NVP(CSSM_ALGID_DES), + NVP(CSSM_ALGID_DESX), + NVP(CSSM_ALGID_3DES_3KEY_EDE), + NVP(CSSM_ALGID_3DES_3KEY), + NVP(CSSM_ALGID_RC2), + NVP(CSSM_ALGID_RC5), + NVP(CSSM_ALGID_RC4), + NVP(CSSM_ALGID_RSA), + NVP(CSSM_ALGID_DSA), + NVP(CSSM_ALGID_FEE), + NVP_END +}; + +/* CSSM_DL_DB_SCHEMA_INFO */ +static const CSSM_DB_ATTRIBUTE_INFO schemaInfoAttrs[] = { + DB_ATTRIBUTE(RelationID, UINT32), + DB_ATTRIBUTE(RelationName, STRING), +}; + +static const NameValuePair *schemaInfoNvp[] = { + recordTypeNames, + NULL +}; + +const RelationInfo schemaInfoRelation = + RELATION_INFO(CSSM_DL_DB_SCHEMA_INFO, + schemaInfoAttrs, + schemaInfoNvp); + +/* CSSM_DL_DB_RECORD_ALL_KEYS (partial) */ +static const CSSM_DB_ATTRIBUTE_INFO allKeysAttrs[] = { + DB_ATTRIBUTE(KeyClass, UINT32), + DB_ATTRIBUTE(KeyType, UINT32), + DB_ATTRIBUTE(PrintName, BLOB), + DB_ATTRIBUTE(Alias, BLOB), + DB_ATTRIBUTE(Permanent, UINT32), + DB_ATTRIBUTE(Private, UINT32), + DB_ATTRIBUTE(Modifiable, UINT32), + DB_ATTRIBUTE(Label, BLOB), + DB_ATTRIBUTE(ApplicationTag, BLOB), + DB_ATTRIBUTE(KeyCreator, BLOB), + DB_ATTRIBUTE(KeySizeInBits, UINT32), + DB_ATTRIBUTE(EffectiveKeySize, UINT32), + DB_ATTRIBUTE(StartDate, BLOB), + DB_ATTRIBUTE(EndDate, BLOB), + DB_ATTRIBUTE(Sensitive, UINT32), + DB_ATTRIBUTE(AlwaysSensitive, UINT32), + DB_ATTRIBUTE(Extractable, UINT32), + DB_ATTRIBUTE(NeverExtractable, UINT32), + DB_ATTRIBUTE(Encrypt, UINT32), + DB_ATTRIBUTE(Decrypt, UINT32), + DB_ATTRIBUTE(Derive, UINT32), + DB_ATTRIBUTE(Sign, UINT32), + DB_ATTRIBUTE(Verify, UINT32), + DB_ATTRIBUTE(SignRecover, UINT32), + DB_ATTRIBUTE(VerifyRecover, UINT32), + DB_ATTRIBUTE(Wrap, UINT32), + DB_ATTRIBUTE(Unwrap, UINT32), +}; + +static const NameValuePair *allKeysNvp[] = { + recordTypeNames, /* KeyClass - in this context, + * a subset of these */ + algIdNames, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +const RelationInfo allKeysRelation = + RELATION_INFO(CSSM_DL_DB_RECORD_ALL_KEYS, + allKeysAttrs, + allKeysNvp); + +/* CSSM_DL_DB_RECORD_ANY, with the few attrs that all records have in common */ +static const CSSM_DB_ATTRIBUTE_INFO anyRecordAttrs[] = { + DB_ATTRIBUTE(PrintName, BLOB) +}; + +static const NameValuePair *anyRecordNvp[] = { + NULL +}; + +const RelationInfo anyRecordRelation = + RELATION_INFO(CSSM_DL_DB_RECORD_ANY, + anyRecordAttrs, + anyRecordNvp); + +/* CSSM_DL_DB_RECORD_CERT - obsolete */ +static const CSSM_DB_ATTRIBUTE_INFO certRecordAttrs[] = { + DB_ATTRIBUTE(CertType, UINT32), + DB_ATTRIBUTE(CertEncoding, UINT32), + DB_ATTRIBUTE(PrintName, BLOB), + DB_ATTRIBUTE(Alias, BLOB), + DB_ATTRIBUTE(CertIdentity, BLOB), + DB_ATTRIBUTE(KeyLabel, BLOB) +}; + +static const NameValuePair *certRecordNvp[] = { + certTypeNames, + certEncodingNames, + NULL, + NULL, + NULL, + NULL +}; + +const RelationInfo certRecordRelation = + RELATION_INFO(CSSM_DL_DB_RECORD_CERT, + certRecordAttrs, + certRecordNvp); + +/* Apple-specific CSSM_DL_DB_RECORD_X509_CERTIFICATE */ +static const CSSM_DB_ATTRIBUTE_INFO x509CertRecordAttrs[] = { + DB_ATTRIBUTE(CertType, UINT32), + DB_ATTRIBUTE(CertEncoding, UINT32), + DB_ATTRIBUTE(PrintName, BLOB), + DB_ATTRIBUTE(Alias, BLOB), + DB_ATTRIBUTE(Subject, BLOB), + DB_ATTRIBUTE(Issuer, BLOB), + DB_ATTRIBUTE(SerialNumber, BLOB), + DB_ATTRIBUTE(SubjectKeyIdentifier, BLOB), + DB_ATTRIBUTE(PublicKeyHash, BLOB) +}; + +static const NameValuePair *x509CertRecordNvp[] = { + certTypeNames, + certEncodingNames, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +const RelationInfo x509CertRecordRelation = + RELATION_INFO(CSSM_DL_DB_RECORD_X509_CERTIFICATE, + x509CertRecordAttrs, + x509CertRecordNvp); + + +/* Apple-specific CSSM_DL_DB_RECORD_X509_CRL */ +static const CSSM_DB_ATTRIBUTE_INFO x509CrlRecordAttrs[] = { + DB_ATTRIBUTE(CrlType, UINT32), + DB_ATTRIBUTE(CrlEncoding, UINT32), + DB_ATTRIBUTE(PrintName, BLOB), + DB_ATTRIBUTE(Alias, BLOB), + DB_ATTRIBUTE(Issuer, BLOB), + DB_ATTRIBUTE(ThisUpdate, BLOB), + DB_ATTRIBUTE(NextUpdate, BLOB), + DB_ATTRIBUTE(URI, BLOB), + DB_ATTRIBUTE(CrlNumber, UINT32), + DB_ATTRIBUTE(DeltaCrlNumber, UINT32), +}; + +static const NameValuePair *x509CrlRecordNvp[] = { + crlTypeNames, + crlEncodingNames, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +const RelationInfo x509CrlRecordRelation = + RELATION_INFO(CSSM_DL_DB_RECORD_X509_CRL, + x509CrlRecordAttrs, + x509CrlRecordNvp); + + +/* generic keychain template, when recordType unknown */ +static const CSSM_DB_ATTRIBUTE_INFO genericKcAttrs[] = { + DB_INT_ATTRIBUTE(kSecInvisibleItemAttr, SINT32), + DB_ATTRIBUTE(PrintName, BLOB), + DB_INT_ATTRIBUTE(kSecDescriptionItemAttr, BLOB), + DB_INT_ATTRIBUTE(kSecTypeItemAttr, UINT32), + /* more to come */ +}; + +static const NameValuePair *genericKcNvp[] = { + NULL, + NULL, + NULL, + NULL, + NULL +}; + +const RelationInfo genericKcRelation = + RELATION_INFO(0, // not used! + genericKcAttrs, + genericKcNvp); + +/* UserTrust */ +static const CSSM_DB_ATTRIBUTE_INFO userTrustAttrs[] = { + DB_ATTRIBUTE(TrustedCertificate, BLOB), + DB_ATTRIBUTE(TrustedPolicy, BLOB), + DB_ATTRIBUTE(PrintName, BLOB), +}; + +static const NameValuePair *userTrustNvp[] = { + NULL, + NULL, + NULL, + NULL, +}; + +const RelationInfo userTrustRelation = + RELATION_INFO(CSSM_DL_DB_RECORD_USER_TRUST, + userTrustAttrs, + userTrustNvp); + +/* remainder added after the schema were publicly available via Schema.h */ + +/* unlock referral record */ + +using namespace Security; +using namespace KeychainCore; + +static const CSSM_DB_ATTRIBUTE_INFO unlockReferralRecordAttrs[] = +{ + Schema::kUnlockReferralType, + Schema::kUnlockReferralDbName, + Schema::kUnlockReferralDbGuid, + Schema::kUnlockReferralDbSSID, + Schema::kUnlockReferralDbSSType, + Schema::kUnlockReferralDbNetname, + Schema::kUnlockReferralKeyLabel, + Schema::kUnlockReferralKeyAppTag, + Schema::kUnlockReferralPrintName, + Schema::kUnlockReferralAlias +}; + +const NameValuePair referralTypeNames[] = +{ + NVP(CSSM_APPLE_UNLOCK_TYPE_KEY_DIRECT), + NVP(CSSM_APPLE_UNLOCK_TYPE_WRAPPED_PRIVATE), + NVP_END +}; + + +static const NameValuePair *referralNvp[] = { + referralTypeNames, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +const RelationInfo referralRecordRelation = + RELATION_INFO(CSSM_DL_DB_RECORD_UNLOCK_REFERRAL, + unlockReferralRecordAttrs, + referralNvp); + +/* extended attribute record */ +static const CSSM_DB_ATTRIBUTE_INFO extendedAttrRecordAttrs[] = +{ + Schema::kExtendedAttributeRecordType, + Schema::kExtendedAttributeItemID, + Schema::kExtendedAttributeAttributeName, + Schema::kExtendedAttributeModDate, + Schema::kExtendedAttributeAttributeValue +}; + +static const NameValuePair *extendedAttrNvp[] = { + recordTypeNames, + NULL, + NULL, + NULL, + NULL +}; + +const RelationInfo extendedAttrRelation = + RELATION_INFO(CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE, + extendedAttrRecordAttrs, + extendedAttrNvp); + diff --git a/SecurityTests/cspxutils/dbTool/dbAttrs.h b/SecurityTests/cspxutils/dbTool/dbAttrs.h new file mode 100644 index 00000000..a628e184 --- /dev/null +++ b/SecurityTests/cspxutils/dbTool/dbAttrs.h @@ -0,0 +1,52 @@ +/* Copyright (c) 2002-2003,2006 Apple Computer, Inc. + * + * dbAttrs.h - Apple DL/DB/Keychain attributes and name/value pairs + */ + +#ifndef _DB_ATTRS_H_ +#define _DB_ATTRS_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* entry in a table to map a uint32 to a string */ +typedef struct { + uint32 value; + const char *name; +} NameValuePair; + +/* all the info we need about one Relation (schema) */ +typedef struct { + CSSM_DB_RECORDTYPE DataRecordType; + const char *relationName; + uint32 NumberOfAttributes; + const CSSM_DB_ATTRIBUTE_INFO *AttributeInfo; + const NameValuePair **nameValues; +} RelationInfo; + +extern const NameValuePair recordTypeNames[]; + +extern const RelationInfo schemaInfoRelation; +extern const RelationInfo allKeysRelation; +extern const RelationInfo anyRecordRelation; +extern const RelationInfo genericKcRelation; +extern const RelationInfo certRecordRelation; +extern const RelationInfo x509CertRecordRelation; +extern const RelationInfo x509CrlRecordRelation; +extern const RelationInfo userTrustRelation; +extern const RelationInfo referralRecordRelation; +extern const RelationInfo extendedAttrRelation; + +/* + * DBBlob record type, private to CSPDL. + */ +#define DBBlobRelationID (CSSM_DB_RECORDTYPE_APP_DEFINED_START + 0x8000) + +#ifdef __cplusplus +} +#endif + +#endif /* _DB_ATTRS_H_ */ diff --git a/SecurityTests/cspxutils/dbTool/dbCert.cpp b/SecurityTests/cspxutils/dbTool/dbCert.cpp new file mode 100644 index 00000000..aa73443d --- /dev/null +++ b/SecurityTests/cspxutils/dbTool/dbCert.cpp @@ -0,0 +1,508 @@ +/* + * Copyright (c) 2003-2005,2008 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please + * obtain a copy of the License at http://www.apple.com/publicsource and + * read it before using this file. + * + * This 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. + */ + +/* + * dbCert.cpp - import a possibly bad cert along with its private key + */ + +#include "dbCert.h" +#include +#include +#include +#include +#include +#include +#include +#include + +/* Copied from clxutils/clAppUtils/tpUtils */ +/* defined in SecKeychainAPIPriv.h */ +static const int kSecAliasItemAttr = 'alis'; + +/* Macro to declare a CSSM_DB_SCHEMA_ATTRIBUTE_INFO */ +#define SCHEMA_ATTR_INFO(id, name, type) \ + { id, (char *)name, {0, NULL}, CSSM_DB_ATTRIBUTE_FORMAT_ ## type } + +/* Too bad we can't get this from inside of the Security framework. */ +static CSSM_DB_SCHEMA_ATTRIBUTE_INFO certSchemaAttrInfo[] = +{ + SCHEMA_ATTR_INFO(kSecCertTypeItemAttr, "CertType", UINT32), + SCHEMA_ATTR_INFO(kSecCertEncodingItemAttr, "CertEncoding", UINT32), + SCHEMA_ATTR_INFO(kSecLabelItemAttr, "PrintName", BLOB), + SCHEMA_ATTR_INFO(kSecAliasItemAttr, "Alias", BLOB), + SCHEMA_ATTR_INFO(kSecSubjectItemAttr, "Subject", BLOB), + SCHEMA_ATTR_INFO(kSecIssuerItemAttr, "Issuer", BLOB), + SCHEMA_ATTR_INFO(kSecSerialNumberItemAttr, "SerialNumber", BLOB), + SCHEMA_ATTR_INFO(kSecSubjectKeyIdentifierItemAttr, "SubjectKeyIdentifier", BLOB), + SCHEMA_ATTR_INFO(kSecPublicKeyHashItemAttr, "PublicKeyHash", BLOB) +}; +#define NUM_CERT_SCHEMA_ATTRS \ + (sizeof(certSchemaAttrInfo) / sizeof(CSSM_DB_SCHEMA_ATTRIBUTE_INFO)) + +/* Macro to declare a CSSM_DB_SCHEMA_INDEX_INFO */ +#define SCHEMA_INDEX_INFO(id, indexNum, indexType) \ + { id, CSSM_DB_INDEX_ ## indexType, CSSM_DB_INDEX_ON_ATTRIBUTE } + + +static CSSM_DB_SCHEMA_INDEX_INFO certSchemaIndices[] = +{ + SCHEMA_INDEX_INFO(kSecCertTypeItemAttr, 0, UNIQUE), + SCHEMA_INDEX_INFO(kSecIssuerItemAttr, 0, UNIQUE), + SCHEMA_INDEX_INFO(kSecSerialNumberItemAttr, 0, UNIQUE), + SCHEMA_INDEX_INFO(kSecCertTypeItemAttr, 1, NONUNIQUE), + SCHEMA_INDEX_INFO(kSecSubjectItemAttr, 2, NONUNIQUE), + SCHEMA_INDEX_INFO(kSecIssuerItemAttr, 3, NONUNIQUE), + SCHEMA_INDEX_INFO(kSecSerialNumberItemAttr, 4, NONUNIQUE), + SCHEMA_INDEX_INFO(kSecSubjectKeyIdentifierItemAttr, 5, NONUNIQUE), + SCHEMA_INDEX_INFO(kSecPublicKeyHashItemAttr, 6, NONUNIQUE) +}; +#define NUM_CERT_INDICES \ + (sizeof(certSchemaIndices) / sizeof(CSSM_DB_SCHEMA_INDEX_INFO)) + + +CSSM_RETURN tpAddCertSchema( + CSSM_DL_DB_HANDLE dlDbHand) +{ + return CSSM_DL_CreateRelation(dlDbHand, + CSSM_DL_DB_RECORD_X509_CERTIFICATE, + "CSSM_DL_DB_RECORD_X509_CERTIFICATE", + NUM_CERT_SCHEMA_ATTRS, + certSchemaAttrInfo, + NUM_CERT_INDICES, + certSchemaIndices); +} + + +/* copied verbatim from certTool */ + +/* + * Find private key by label, modify its Label attr to be the + * hash of the associated public key. + */ +static CSSM_RETURN setPubKeyHash( + CSSM_CSP_HANDLE cspHand, + CSSM_DL_DB_HANDLE dlDbHand, + const char *keyLabel, // look up by this + CSSM_DATA *rtnKeyDigest) // optionally RETURNED, if so, + // caller owns and must cuAppFree +{ + CSSM_QUERY query; + CSSM_SELECTION_PREDICATE predicate; + CSSM_DB_UNIQUE_RECORD_PTR record = NULL; + CSSM_RETURN crtn; + CSSM_DATA labelData; + CSSM_HANDLE resultHand; + + labelData.Data = (uint8 *)keyLabel; + labelData.Length = strlen(keyLabel) + 1; // incl. NULL + query.RecordType = CSSM_DL_DB_RECORD_PRIVATE_KEY; + query.Conjunctive = CSSM_DB_NONE; + query.NumSelectionPredicates = 1; + predicate.DbOperator = CSSM_DB_EQUAL; + + predicate.Attribute.Info.AttributeNameFormat = + CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + predicate.Attribute.Info.Label.AttributeName = (char *)"Label"; + predicate.Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + /* hope this cast is OK */ + predicate.Attribute.Value = &labelData; + query.SelectionPredicate = &predicate; + + query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? + query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? + query.QueryFlags = 0; // CSSM_QUERY_RETURN_DATA; // FIXME - used? + + /* build Record attribute with one attr */ + CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; + CSSM_DB_ATTRIBUTE_DATA attr; + attr.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr.Info.Label.AttributeName = (char *)"Label"; + attr.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + + recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_PRIVATE_KEY; + recordAttrs.NumberOfAttributes = 1; + recordAttrs.AttributeData = &attr; + + CSSM_DATA recordData = {0, NULL}; + crtn = CSSM_DL_DataGetFirst(dlDbHand, + &query, + &resultHand, + &recordAttrs, + &recordData, + &record); + /* abort only on success */ + if(crtn != CSSM_OK) { + cuPrintError("CSSM_DL_DataGetFirst", crtn); + return crtn; + } + + CSSM_KEY_PTR keyToDigest = (CSSM_KEY_PTR)recordData.Data; + CSSM_DATA_PTR keyDigest = NULL; + CSSM_CC_HANDLE ccHand; + crtn = CSSM_CSP_CreatePassThroughContext(cspHand, + keyToDigest, + &ccHand); + if(crtn) { + cuPrintError("CSSM_CSP_CreatePassThroughContext", crtn); + return crtn; + } + crtn = CSSM_CSP_PassThrough(ccHand, + CSSM_APPLECSP_KEYDIGEST, + NULL, + (void **)&keyDigest); + if(crtn) { + cuPrintError("CSSM_CSP_PassThrough(PUBKEYHASH)", crtn); + return -1; + } + CSSM_FreeKey(cspHand, NULL, keyToDigest, CSSM_FALSE); + CSSM_DeleteContext(ccHand); + + /* + * Replace Label attr data with hash. + * NOTE: the module which allocated this attribute data - a DL - + * was loaded and attached by the Sec layer, not by us. Thus + * we can't use the memory allocator functions *we* used when + * attaching to the CSPDL - we have to use the ones + * which the Sec layer registered with the DL. + */ + CSSM_API_MEMORY_FUNCS memFuncs; + crtn = CSSM_GetAPIMemoryFunctions(dlDbHand.DLHandle, &memFuncs); + if(crtn) { + cuPrintError("CSSM_GetAPIMemoryFunctions(DLHandle)", crtn); + /* oh well, leak and continue */ + } + else { + memFuncs.free_func(attr.Value->Data, memFuncs.AllocRef); + memFuncs.free_func(attr.Value, memFuncs.AllocRef); + } + attr.Value = keyDigest; + + /* modify key attributes */ + crtn = CSSM_DL_DataModify(dlDbHand, + CSSM_DL_DB_RECORD_PRIVATE_KEY, + record, + &recordAttrs, + NULL, // DataToBeModified + CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + if(crtn) { + cuPrintError("CSSM_DL_DataModify(PUBKEYHASH)", crtn); + return crtn; + } + crtn = CSSM_DL_DataAbortQuery(dlDbHand, resultHand); + if(crtn) { + cuPrintError("CSSM_DL_DataAbortQuery", crtn); + /* let's keep going in this case */ + } + crtn = CSSM_DL_FreeUniqueRecord(dlDbHand, record); + if(crtn) { + cuPrintError("CSSM_DL_FreeUniqueRecord", crtn); + /* let's keep going in this case */ + crtn = CSSM_OK; + } + + /* free resources */ + if(rtnKeyDigest) { + *rtnKeyDigest = *keyDigest; + } + else { + cuAppFree(keyDigest->Data, NULL); + /* FIXME - don't we have to free keyDigest itself? */ + } + return CSSM_OK; +} + +static CSSM_RETURN importPrivateKey( + CSSM_DL_DB_HANDLE dlDbHand, + CSSM_CSP_HANDLE cspHand, + const char *privKeyFileName, + CSSM_ALGORITHMS keyAlg, + CSSM_BOOL pemFormat, // of the file + CSSM_KEYBLOB_FORMAT keyFormat, // of the key blob itself, NONE means + // use default + CSSM_DATA *keyHash) // OPTIONALLY RETURNED - if so, caller + // owns and must cuAppFree() +{ + unsigned char *derKey = NULL; + unsigned derKeyLen; + unsigned char *pemKey = NULL; + unsigned pemKeyLen; + CSSM_KEY wrappedKey; + CSSM_KEY unwrappedKey; + CSSM_ACCESS_CREDENTIALS creds; + CSSM_CC_HANDLE ccHand = 0; + CSSM_RETURN crtn; + CSSM_DATA labelData; + CSSM_KEYHEADER_PTR hdr = &wrappedKey.KeyHeader; + CSSM_DATA descData = {0, NULL}; + CSSM_CSP_HANDLE rawCspHand = 0; + const char *privKeyLabel = NULL; + + /* + * Validate specified format for clarity + */ + switch(keyAlg) { + case CSSM_ALGID_RSA: + switch(keyFormat) { + case CSSM_KEYBLOB_RAW_FORMAT_NONE: + keyFormat = CSSM_KEYBLOB_RAW_FORMAT_PKCS1; // default + break; + case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: + case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: + break; + default: + printf("***RSA Private key must be in PKCS1 or PKCS8 " + "format\n"); + return CSSMERR_CSSM_INTERNAL_ERROR; + } + privKeyLabel = "Imported RSA key"; + break; + case CSSM_ALGID_DSA: + switch(keyFormat) { + case CSSM_KEYBLOB_RAW_FORMAT_NONE: + keyFormat = CSSM_KEYBLOB_RAW_FORMAT_OPENSSL; + // default + break; + case CSSM_KEYBLOB_RAW_FORMAT_FIPS186: + case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL: + case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: + break; + default: + printf("***DSA Private key must be in openssl, FIPS186, " + "or PKCS8 format\n"); + return CSSMERR_CSSM_INTERNAL_ERROR; + } + privKeyLabel = "Imported DSA key"; + break; + case CSSM_ALGID_DH: + switch(keyFormat) { + case CSSM_KEYBLOB_RAW_FORMAT_NONE: + keyFormat = CSSM_KEYBLOB_RAW_FORMAT_PKCS8; // default + break; + case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: + break; + default: + printf("***Diffie-Hellman Private key must be in" + "PKCS8 format.\n"); + return CSSMERR_CSSM_INTERNAL_ERROR; + } + privKeyLabel = "Imported Diffie-Hellman key"; + break; + } + if(readFile(privKeyFileName, &pemKey, &pemKeyLen)) { + printf("***Error reading private key from file %s. Aborting.\n", + privKeyFileName); + return CSSMERR_CSSM_INTERNAL_ERROR; + } + /* subsequent errors to done: */ + if(pemFormat) { + int rtn = pemDecode(pemKey, pemKeyLen, &derKey, &derKeyLen); + if(rtn) { + printf("***%s: Bad PEM formatting. Aborting.\n", + privKeyFileName); + crtn = CSSMERR_CSP_INVALID_KEY; + goto done; + } + } + else { + derKey = pemKey; + derKeyLen = pemKeyLen; + } + + /* importing a raw key into the CSPDL involves a NULL unwrap */ + memset(&unwrappedKey, 0, sizeof(CSSM_KEY)); + memset(&wrappedKey, 0, sizeof(CSSM_KEY)); + + /* set up the imported key to look like a CSSM_KEY */ + hdr->HeaderVersion = CSSM_KEYHEADER_VERSION; + hdr->BlobType = CSSM_KEYBLOB_RAW; + hdr->AlgorithmId = keyAlg; + hdr->KeyClass = CSSM_KEYCLASS_PRIVATE_KEY; + hdr->KeyAttr = CSSM_KEYATTR_EXTRACTABLE; + hdr->KeyUsage = CSSM_KEYUSE_ANY; + hdr->Format = keyFormat; + wrappedKey.KeyData.Data = derKey; + wrappedKey.KeyData.Length = derKeyLen; + + /* get key size in bits from raw CSP */ + rawCspHand = cuCspStartup(CSSM_TRUE); + if(rawCspHand == 0) { + printf("***Error attaching to CSP. Aborting.\n"); + crtn = CSSMERR_CSSM_INTERNAL_ERROR; + goto done; + } + CSSM_KEY_SIZE keySize; + crtn = CSSM_QueryKeySizeInBits(rawCspHand, CSSM_INVALID_HANDLE, &wrappedKey, &keySize); + if(crtn) { + cuPrintError("CSSM_QueryKeySizeInBits",crtn); + goto done; + } + hdr->LogicalKeySizeInBits = keySize.LogicalKeySizeInBits; + + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + crtn = CSSM_CSP_CreateSymmetricContext(cspHand, + CSSM_ALGID_NONE, // unwrapAlg + CSSM_ALGMODE_NONE, // unwrapMode + &creds, + NULL, // unwrappingKey + NULL, // initVector + CSSM_PADDING_NONE, // unwrapPad + 0, // Params + &ccHand); + if(crtn) { + cuPrintError("CSSM_CSP_CreateSymmetricContext", crtn); + goto done; + } + + /* add DL/DB to context */ + CSSM_CONTEXT_ATTRIBUTE newAttr; + newAttr.AttributeType = CSSM_ATTRIBUTE_DL_DB_HANDLE; + newAttr.AttributeLength = sizeof(CSSM_DL_DB_HANDLE); + newAttr.Attribute.Data = (CSSM_DATA_PTR)&dlDbHand; + crtn = CSSM_UpdateContextAttributes(ccHand, 1, &newAttr); + if(crtn) { + cuPrintError("CSSM_UpdateContextAttributes", crtn); + goto done; + } + + /* do the NULL unwrap */ + labelData.Data = (uint8 *)privKeyLabel; + labelData.Length = strlen(privKeyLabel) + 1; + crtn = CSSM_UnwrapKey(ccHand, + NULL, // PublicKey + &wrappedKey, + CSSM_KEYUSE_ANY, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT | + CSSM_KEYATTR_SENSITIVE |CSSM_KEYATTR_EXTRACTABLE, + &labelData, + NULL, // CredAndAclEntry + &unwrappedKey, + &descData); // required + if(crtn != CSSM_OK) { + cuPrintError("CSSM_UnwrapKey", crtn); + goto done; + } + + /* one more thing: bind this private key to its public key */ + crtn = setPubKeyHash(cspHand, dlDbHand, privKeyLabel, keyHash); + + /* We don't need the unwrapped key any more */ + CSSM_FreeKey(cspHand, + NULL, // access cred + &unwrappedKey, + CSSM_FALSE); // delete + +done: + if(ccHand) { + CSSM_DeleteContext(ccHand); + } + if(derKey) { + free(derKey); // mallocd by readFile() */ + } + if(pemFormat && pemKey) { + free(pemKey); + } + if(rawCspHand) { + CSSM_ModuleDetach(rawCspHand); + } + return crtn; +} + + +CSSM_RETURN importBadCert( + CSSM_DL_HANDLE dlHand, + const char *dbFileName, + const char *certFile, + const char *keyFile, + CSSM_ALGORITHMS keyAlg, + CSSM_BOOL pemFormat, // of the file + CSSM_KEYBLOB_FORMAT keyFormat, // of the key blob itself, NONE means + // use default + CSSM_BOOL verbose) +{ + CSSM_DL_DB_HANDLE dlDbHand = {dlHand, 0}; + CSSM_RETURN crtn; + CSSM_DATA keyDigest = {0, NULL}; + CSSM_DATA certData = {0, NULL}; + unsigned len; + + CSSM_CSP_HANDLE cspHand = cuCspStartup(CSSM_FALSE); + if(cspHand == 0) { + printf("***Error attaching to CSPDL. Aborting.\n"); + return CSSMERR_CSSM_ADDIN_LOAD_FAILED; + } + + /* + * 1. Open the (already existing) DB. + */ + dlDbHand.DBHandle = cuDbStartupByName(dlHand, + (char *)dbFileName, // bogus non-const prototype + CSSM_FALSE, // do NOT create it + CSSM_FALSE); // quiet + if(dlDbHand.DBHandle == 0) { + printf("Error opening %s. Aborting.\n", dbFileName); + return CSSMERR_DL_DATASTORE_DOESNOT_EXIST; + } + + /* + * Import key to DB, snagging its key digest along the way. + */ + crtn = importPrivateKey(dlDbHand, cspHand, + keyFile, keyAlg, pemFormat, keyFormat, + &keyDigest); + if(crtn) { + printf("***Error importing key %s. Aborting.\n", keyFile); + goto errOut; + } + + /* + * Now the cert. + */ + if(readFile(certFile, &certData.Data, &len)) { + printf("***Error reading cert from %s. Aborting.\n", certFile); + goto errOut; + } + certData.Length = len; + crtn = cuAddCertToDb(dlDbHand, &certData, + CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, + certFile, // printName + &keyDigest); + if(crtn == CSSMERR_DL_INVALID_RECORDTYPE) { + /* virgin DB, no cert schema: add schema and retry */ + crtn = tpAddCertSchema(dlDbHand); + if(crtn == CSSM_OK) { + crtn = cuAddCertToDb(dlDbHand, &certData, + CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, + certFile, // printName + &keyDigest); + } + } + if(crtn) { + printf("***Error importing cert %s. Aborting.\n", certFile); + } +errOut: + if(keyDigest.Data) { + cuAppFree(keyDigest.Data, NULL); + } + if(dlDbHand.DBHandle) { + CSSM_DL_DbClose(dlDbHand); + } + if(certData.Data) { + free(certData.Data); + } + return crtn; +} diff --git a/SecurityTests/cspxutils/dbTool/dbCert.h b/SecurityTests/cspxutils/dbTool/dbCert.h new file mode 100644 index 00000000..a6f633af --- /dev/null +++ b/SecurityTests/cspxutils/dbTool/dbCert.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please + * obtain a copy of the License at http://www.apple.com/publicsource and + * read it before using this file. + * + * This 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. + */ + +/* + * dbCert.h - import a possibly bad cert along with its private key + */ + +#ifndef _DB_CERT_H_ +#define _DB_CERT_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +CSSM_RETURN importBadCert( + CSSM_DL_HANDLE dlHand, + const char *dbFileName, + const char *certFile, + const char *keyFile, + CSSM_ALGORITHMS keyAlg, + CSSM_BOOL pemFormat, // of the file + CSSM_KEYBLOB_FORMAT keyFormat, // of the key blob itself, NONE means + // use default + CSSM_BOOL verbose); + +#ifdef __cplusplus +} +#endif + +#endif /* _DB_CERT_H_ */ + diff --git a/SecurityTests/cspxutils/dbTool/dbTool.cpp b/SecurityTests/cspxutils/dbTool/dbTool.cpp new file mode 100644 index 00000000..937d88ea --- /dev/null +++ b/SecurityTests/cspxutils/dbTool/dbTool.cpp @@ -0,0 +1,747 @@ +/* Copyright (c) 2002-2006 Apple Computer, Inc. + * + * dbTool.cpp - DL/DB tool. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "dbAttrs.h" +#include "dbCert.h" +#include "cspdlTesting.h" + + +static void usage(char **argv) +{ + printf("usage: %s dbFileName command [options]\n", argv[0]); + printf("Commands:\n"); + printf(" r Dump Schema Relations\n"); + printf(" k Dump all keys\n"); + printf(" c Dump certs\n"); + printf(" a Dump all records\n"); + printf(" d Delete records (interactively)\n"); + printf(" D Delete records (noninteractively, requires really arg)\n"); + printf(" i Import bad cert and its (good) private key\n"); + printf("Options:\n"); + printf(" v verbose\n"); + printf(" q quiet\n"); + printf(" R really! (for D command)\n"); + printf(" d dump data\n"); + printf(" c=certFile\n"); + printf(" k=keyFile\n"); + exit(1); +} + + +static unsigned indentVal = 0; +static void indentIncr() +{ + indentVal += 3; +} + +static void indentDecr() +{ + if(indentVal) { + indentVal -= 3; + } +} + +static void doIndent() +{ + unsigned i; + for(i=0; iAttributeNameFormat) { + case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: + { + char *attrName = attrInfo->Label.AttributeName; + printf("%s", attrName); + int len = strlen(attrName); + if(len > NORM_KEY_LEN) { + return; + } + int numSpaces = NORM_KEY_LEN - len; + for(int i=0; iLabel.AttributeID); + for(unsigned i=0; i<4; i++) { + putchar(*cp++); + } + printf(" "); + break; + } + default: + printf("Unknown attribute name format (%u)\n", + (unsigned)attrInfo->AttributeNameFormat); + break; + } +} + +/* + * Attempt to print a numeric value as a string, per a NameValuePair table. + * If the value is in fact a collection of legal values (per the nameValues + * array), the value will just be printed in hex. + */ +static void printValueAsString( + unsigned val, + const NameValuePair *nameValues) +{ + if(nameValues != NULL) { + while(nameValues->name != NULL) { + if(nameValues->value == val) { + printf("%s", nameValues->name); + return; + } + nameValues++; + } + } + /* Oh well */ + printf("0x%x", val); +} + +static void safePrint( + uint8 *cp, + uint32 len) +{ + for(unsigned i=0; iData; + for(unsigned i=0; iLength; i++) { + if(*cp == 0) { + if(i != (dp->Length - 1)) { + /* data contains NULL character before end */ + printable = false; + } + /* else end of string */ + break; + } + if(!isprint(*cp)) { + printable = false; + break; + } + cp++; + } + return printable; +} + +#define MAX_BLOB_TO_PRINT 12 +static void printBlob( + const CSSM_DATA *data) +{ + unsigned toPrint = data->Length; + if(toPrint > MAX_BLOB_TO_PRINT) { + toPrint = MAX_BLOB_TO_PRINT; + } + for(unsigned i=0; iData[i]; + printf("%02X ", dat); + } + if(toPrint < data->Length) { + printf("..."); + } +} + +static void printAttrData( + const CSSM_DB_ATTRIBUTE_INFO *attrInfo, + const CSSM_DATA *attrData, + const NameValuePair *nameValues) // optional +{ + void *data = attrData->Data; + + switch(attrInfo->AttributeFormat) { + + case CSSM_DB_ATTRIBUTE_FORMAT_STRING: + putchar('\''); + safePrint(attrData->Data, attrData->Length); + putchar('\''); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: + case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: + { + unsigned val = *(unsigned *)data; + printValueAsString(val, nameValues); + break; + } + case CSSM_DB_ATTRIBUTE_FORMAT_BLOB: + { + printf("BLOB length %u : ", (unsigned)attrData->Length); + /* see if it happens to be a printable string */ + if(isPrintable(attrData)) { + putchar('\''); + safePrint(attrData->Data, attrData->Length); + putchar('\''); + } + else { + printBlob(attrData); + } + break; + } + case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32: + { + printf("multi_int["); + uint32 numInts = attrData->Length / sizeof(uint32); + uint32 *uip = (uint32 *)data; + for(unsigned i=0; i 0) { + printf(", "); + } + printValueAsString(*uip++, nameValues); + } + printf("]"); + break; + } + case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE: + putchar('\''); + safePrint(attrData->Data, attrData->Length); + putchar('\''); + break; + + default: + printf("***UNKNOWN FORMAT (%u), Length %u", + (unsigned)attrInfo->AttributeFormat, (unsigned)attrData->Length); + break; + } +} + +/* free attribute(s) allocated by DL */ +static void freeAttrs( + CSSM_DB_RECORD_ATTRIBUTE_DATA *recordAttrs) +{ + unsigned i; + + for(i=0; iNumberOfAttributes; i++) { + CSSM_DB_ATTRIBUTE_DATA_PTR attrData = &recordAttrs->AttributeData[i]; + if(attrData == NULL) { + /* fault of caller, who allocated the CSSM_DB_ATTRIBUTE_DATA */ + printf("***freeAttrs screwup: NULL attrData\n"); + return; + } + unsigned j; + for(j=0; jNumberOfValues; j++) { + CSSM_DATA_PTR data = &attrData->Value[j]; + if(data == NULL) { + /* fault of MDS, who said there was a value here */ + printf("***freeAttrs screwup: NULL data\n"); + return; + } + CSSM_FREE(data->Data); + data->Data = NULL; + data->Length = 0; + } + CSSM_FREE(attrData->Value); + attrData->Value = NULL; + } +} + +static void dumpDataBlob( + const CSSM_DATA *datap) +{ + doIndent(); + printf("Record data length %lu ", datap->Length); + if(datap->Length != 0) { + printf(" : "); + printBlob(datap); + } + printf("\n"); +} + +static void dumpRecordAttrs( + const CSSM_DB_RECORD_ATTRIBUTE_DATA *recordAttrs, + const NameValuePair **nameValues, // parallel to recordAttrs + const CSSM_DATA *recordData = NULL) // optional data +{ + unsigned valNum; + unsigned dex; + + for(dex=0; dexNumberOfAttributes; dex++) { + const CSSM_DB_ATTRIBUTE_DATA *attrData = &recordAttrs->AttributeData[dex]; + doIndent(); + printName(&attrData->Info); + printf(": "); + if(attrData->NumberOfValues == 0) { + printf("<>\n"); + continue; + } + for(valNum=0; valNumNumberOfValues; valNum++) { + printAttrData(&attrData->Info, &attrData->Value[valNum], nameValues[dex]); + if(valNum < (attrData->NumberOfValues - 1)) { + printf(", "); + } + } + printf("\n"); + } + if(recordData) { + dumpDataBlob(recordData); + } +} + +static void dumpRelation( + CSSM_DL_DB_HANDLE dlDbHand, + const RelationInfo *relInfo, + CSSM_BOOL dumpData) +{ + CSSM_QUERY query; + CSSM_DB_UNIQUE_RECORD_PTR record = NULL; + CSSM_RETURN crtn; + CSSM_HANDLE resultHand; + CSSM_DB_ATTRIBUTE_DATA *attrs; + CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; + unsigned attrDex; + unsigned recNum = 0; + uint32 numAttrs = relInfo->NumberOfAttributes; + CSSM_DATA data = {0, NULL}; + CSSM_DATA_PTR datap = NULL; + + if(dumpData) { + datap = &data; + } + + /* build an attr array from known schema */ + attrs = (CSSM_DB_ATTRIBUTE_DATA *)CSSM_MALLOC( + sizeof(CSSM_DB_ATTRIBUTE_DATA) * numAttrs); + memset(attrs, 0, sizeof(CSSM_DB_ATTRIBUTE_DATA) * numAttrs); + for(attrDex=0; attrDexAttributeInfo[attrDex]; + } + recordAttrs.DataRecordType = relInfo->DataRecordType; + recordAttrs.NumberOfAttributes = numAttrs; + recordAttrs.AttributeData = attrs; + + /* just search by recordType, no predicates */ + query.RecordType = relInfo->DataRecordType; + query.Conjunctive = CSSM_DB_NONE; + query.NumSelectionPredicates = 0; + query.SelectionPredicate = NULL; + query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? + query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? + query.QueryFlags = 0; // CSSM_QUERY_RETURN_DATA...FIXME - used? + + crtn = CSSM_DL_DataGetFirst(dlDbHand, + &query, + &resultHand, + &recordAttrs, + datap, + &record); + switch(crtn) { + case CSSM_OK: + break; // proceed + case CSSMERR_DL_ENDOFDATA: + printf("%s: no record found\n", relInfo->relationName); + CSSM_FREE(attrs); + return; + default: + printError("DataGetFirst", crtn); + CSSM_FREE(attrs); + return; + } + printf("%s:\n", relInfo->relationName); + printf(" record %d; numAttrs %d:\n", + recNum++, (int)recordAttrs.NumberOfAttributes); + indentIncr(); + + dumpRecordAttrs(&recordAttrs, relInfo->nameValues, datap); + CSSM_DL_FreeUniqueRecord(dlDbHand, record); + freeAttrs(&recordAttrs); + if(datap) { + CSSM_FREE(datap->Data); + } + + /* now the rest of them */ + /* hopefully we don't have to re-init the recordAttr array */ + for(;;) { + crtn = CSSM_DL_DataGetNext(dlDbHand, + resultHand, + &recordAttrs, + datap, + &record); + switch(crtn) { + case CSSM_OK: + printf(" record %d; numAttrs %d:\n", + recNum++, (int)recordAttrs.NumberOfAttributes); + dumpRecordAttrs(&recordAttrs, relInfo->nameValues, datap); + CSSM_DL_FreeUniqueRecord(dlDbHand, record); + freeAttrs(&recordAttrs); + if(datap) { + CSSM_FREE(datap->Data); + } + break; // and go again + case CSSMERR_DL_ENDOFDATA: + /* normal termination */ + break; + default: + printError("DataGetNext", crtn); + break; + } + if(crtn != CSSM_OK) { + break; + } + } + indentDecr(); + CSSM_FREE(attrs); +} + +/* + * Given a record type and a CSSM_DB_UNIQUE_RECORD, fetch and parse all the + * attributes we can. + */ +static void fetchParseRecord( + CSSM_DL_DB_HANDLE dlDbHand, + CSSM_DB_RECORD_ATTRIBUTE_DATA *inRecordAttrs, + CSSM_DB_UNIQUE_RECORD_PTR record, + const CSSM_DATA_PTR datap, + CSSM_BOOL dumpData) +{ + const RelationInfo *relInfo = NULL; + + /* infer RelationInfo from recordType */ + switch(inRecordAttrs->DataRecordType) { + case CSSM_DL_DB_RECORD_PUBLIC_KEY: + case CSSM_DL_DB_RECORD_PRIVATE_KEY: + case CSSM_DL_DB_RECORD_SYMMETRIC_KEY: + relInfo = &allKeysRelation; + break; + case CSSM_DL_DB_RECORD_GENERIC_PASSWORD: + case CSSM_DL_DB_RECORD_INTERNET_PASSWORD: + case CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD: + relInfo = &genericKcRelation; + break; + case CSSM_DL_DB_RECORD_CERT: + relInfo = &certRecordRelation; + break; + case CSSM_DL_DB_RECORD_X509_CERTIFICATE: + relInfo = &x509CertRecordRelation; + break; + case CSSM_DL_DB_RECORD_X509_CRL: + relInfo = &x509CrlRecordRelation; + break; + case CSSM_DL_DB_RECORD_USER_TRUST: + relInfo = &userTrustRelation; + break; + case CSSM_DL_DB_RECORD_UNLOCK_REFERRAL: + relInfo = &referralRecordRelation; + break; + case CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE: + relInfo = &extendedAttrRelation; + break; + case DBBlobRelationID: + relInfo = NULL; + doIndent(); + printf("--- No attributes ---\n"); + if(dumpData) { + dumpDataBlob(datap); + } + return; + default: + doIndent(); + printf("<>\n"); + if(dumpData) { + doIndent(); + printf("Record blob (length %ld): ", datap->Length); + printBlob(datap); + printf("\n"); + } + return; + } + + CSSM_DB_ATTRIBUTE_DATA *attrs = NULL; + CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; + unsigned attrDex; + uint32 numAttrs = relInfo->NumberOfAttributes; + CSSM_RETURN crtn; + CSSM_DATA recordData = {0, NULL}; + CSSM_DATA_PTR recordDataP = dumpData ? &recordData : NULL; + + /* build an attr array from known schema */ + attrs = (CSSM_DB_ATTRIBUTE_DATA *)CSSM_MALLOC( + sizeof(CSSM_DB_ATTRIBUTE_DATA) * numAttrs); + memset(attrs, 0, sizeof(CSSM_DB_ATTRIBUTE_DATA) * numAttrs); + for(attrDex=0; attrDexAttributeInfo[attrDex]; + } + + /* from inRecordAttrs, not the relInfo, which could be a typeless template */ + recordAttrs.DataRecordType = relInfo->DataRecordType; + recordAttrs.NumberOfAttributes = numAttrs; + recordAttrs.AttributeData = attrs; + + crtn = CSSM_DL_DataGetFromUniqueRecordId(dlDbHand, + record, + &recordAttrs, + recordDataP); + if(crtn) { + printError("CSSM_DL_DataGetFromUniqueRecordId", crtn); + goto abort; + } + dumpRecordAttrs(&recordAttrs, relInfo->nameValues, recordDataP); + freeAttrs(&recordAttrs); + if(recordData.Data) { + CSSM_FREE(recordData.Data); + } +abort: + if(attrs) { + CSSM_FREE(attrs); + } + return; +} + +static void deleteRecord( + CSSM_DL_DB_HANDLE dlDbHand, + CSSM_DB_UNIQUE_RECORD_PTR record, + CSSM_BOOL interact) +{ + if(interact) { + fpurge(stdin); + printf("\nDelete this record [y/anything] ? "); + char resp = getchar(); + if(resp != 'y') { + return; + } + } + CSSM_RETURN crtn; + crtn = CSSM_DL_DataDelete(dlDbHand, record); + if(crtn) { + printError("CSSM_DL_DataDelete", crtn); + } + else if(interact) { + printf("...record deleted\n\n"); + } +} + +/* + * In this case we search for CSSM_DL_DB_RECORD_ANY. The current schema results + * in no single attribute which all interesting records have in common, so we + * can't grab any attributes at GetFirst/GetNext time. Instead we have + * to deal with the returned record per its record type. + */ +static void dumpAllRecords( + CSSM_DL_DB_HANDLE dlDbHand, + CSSM_BOOL deleteAll, + CSSM_BOOL interact, + CSSM_BOOL dumpData) +{ + CSSM_QUERY query; + CSSM_DB_UNIQUE_RECORD_PTR record = NULL; + CSSM_RETURN crtn; + CSSM_HANDLE resultHand; + CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; + CSSM_DATA data = {0, NULL}; + CSSM_DATA_PTR datap = NULL; + + if(dumpData) { + datap = &data; + } + + recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_ANY; + recordAttrs.NumberOfAttributes = 0; + recordAttrs.AttributeData = NULL; + + /* just search by recordType, no predicates */ + query.RecordType = CSSM_DL_DB_RECORD_ANY; + query.Conjunctive = CSSM_DB_NONE; + query.NumSelectionPredicates = 0; + query.SelectionPredicate = NULL; + query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? + query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? + query.QueryFlags = 0; // CSSM_QUERY_RETURN_DATA...FIXME - used? + + crtn = CSSM_DL_DataGetFirst(dlDbHand, + &query, + &resultHand, + &recordAttrs, + datap, + &record); + switch(crtn) { + case CSSM_OK: + break; // proceed + case CSSMERR_DL_ENDOFDATA: + printf("CSSM_DL_DB_RECORD_ANY: no record found\n"); + return; + default: + printError("DataGetFirst", crtn); + return; + } + + /* could be anything; check it out */ + if(interact) { + doIndent(); + printValueAsString(recordAttrs.DataRecordType, recordTypeNames); + printf("\n"); + indentIncr(); + fetchParseRecord(dlDbHand, &recordAttrs, record, datap, dumpData); + indentDecr(); + } + if(deleteAll && (recordAttrs.DataRecordType != DBBlobRelationID)) { + /* NEVER delete a DBBlob */ + deleteRecord(dlDbHand, record, interact); + } + CSSM_DL_FreeUniqueRecord(dlDbHand, record); + + /* now the rest of them */ + /* hopefully we don't have to re-init the recordAttr array */ + for(;;) { + crtn = CSSM_DL_DataGetNext(dlDbHand, + resultHand, + &recordAttrs, + datap, + &record); + switch(crtn) { + case CSSM_OK: + if(interact) { + doIndent(); + printValueAsString(recordAttrs.DataRecordType, recordTypeNames); + printf("\n"); + indentIncr(); + fetchParseRecord(dlDbHand, &recordAttrs, record, datap, dumpData); + indentDecr(); + } + if(deleteAll && (recordAttrs.DataRecordType != DBBlobRelationID)) { + /* NEVER delete a DBBlob */ + deleteRecord(dlDbHand, record, interact); + } + CSSM_DL_FreeUniqueRecord(dlDbHand, record); + break; // and go again + case CSSMERR_DL_ENDOFDATA: + /* normal termination */ + break; + default: + printError("DataGetNext", crtn); + break; + } + if(crtn != CSSM_OK) { + break; + } + } +} + +int main( + int argc, + char **argv) +{ + int arg; + char *argp; + char *dbFileName; + char cmd; + CSSM_DL_DB_HANDLE dlDbHand; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + char *certFile = NULL; + char *keyFile = NULL; + CSSM_BOOL interact = CSSM_TRUE; + CSSM_BOOL dumpData = CSSM_FALSE; + + /* should be cmd line opts */ + CSSM_ALGORITHMS keyAlg = CSSM_ALGID_RSA; + CSSM_BOOL pemFormat = CSSM_FALSE; + CSSM_KEYBLOB_FORMAT keyFormat = CSSM_KEYBLOB_RAW_FORMAT_NONE; + CSSM_RETURN crtn = CSSM_OK; + + if(argc < 3) { + usage(argv); + } + dbFileName = argv[1]; + cmd = argv[2][0]; + + for(arg=3; arg +#include +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "cspdlTesting.h" + + +static void usage(char **argv) +{ + printf("usage: %s dbFileName alg class keysize [options]\n", argv[0]); + printf(" alg : rsa|dsa|dh|ecdsa\n"); + printf(" class : priv|pub\n"); + printf("Options:\n"); + printf(" -q quiet\n"); + exit(1); +} + +static const char *recordTypeStr( + CSSM_DB_RECORDTYPE recordType) +{ + static char unk[100]; + + switch(recordType) { + case CSSM_DL_DB_RECORD_PRIVATE_KEY: + return "Private Key"; + case CSSM_DL_DB_RECORD_PUBLIC_KEY: + return "Public Key"; + case CSSM_DL_DB_RECORD_SYMMETRIC_KEY: + return "Symmetric Key"; + default: + sprintf(unk, "**Unknown record type %u\n", (unsigned)recordType); + return unk; + } +} + +/* + * Search for specified record type; verify there is exactly one or zero + * of them as specified. + * Verify key algorthm and key size. Returns nonzero on error. + */ +static int doVerify( + CSSM_DL_DB_HANDLE dlDbHand, + unsigned numRecords, // zero or one + CSSM_DB_RECORDTYPE recordType, + uint32 keySize, + CSSM_ALGORITHMS keyAlg) +{ + CSSM_QUERY query; + CSSM_DB_UNIQUE_RECORD_PTR record = NULL; + CSSM_RETURN crtn; + CSSM_HANDLE resultHand; + CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; + + /* no predicates, all records of specified type, no attrs, get the key */ + query.RecordType = recordType; + query.Conjunctive = CSSM_DB_NONE; + query.NumSelectionPredicates = 0; + query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? + query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? + query.QueryFlags = 0; // CSSM_QUERY_RETURN_DATA; // FIXME - used? + + recordAttrs.DataRecordType = recordType; + recordAttrs.NumberOfAttributes = 0; + recordAttrs.AttributeData = NULL; + + CSSM_DATA recordData = {0, NULL}; + + crtn = CSSM_DL_DataGetFirst(dlDbHand, + &query, + &resultHand, + &recordAttrs, + &recordData, + &record); + switch(crtn) { + case CSSM_OK: + if(numRecords == 0) { + printf("***Expected zero records of type %s, found one\n", + recordTypeStr(recordType)); + CSSM_DL_FreeUniqueRecord(dlDbHand, record); + CSSM_DL_DataAbortQuery(dlDbHand, resultHand); + return 1; + } + break; // proceed + case CSSMERR_DL_ENDOFDATA: + if(numRecords == 0) { + /* cool */ + return 0; + } + printf("**Error: no records of type %s found\n", + recordTypeStr(recordType)); + return 1; + default: + printError("DataGetFirst", crtn); + return 1; + } + + CSSM_KEY_PTR theKey = (CSSM_KEY_PTR)recordData.Data; + int ourRtn = 0; + CSSM_KEYHEADER &hdr = theKey->KeyHeader; + if(hdr.AlgorithmId != keyAlg) { + printf("***Algorithm mismatch: expect %u, got %u\n", + (unsigned)keyAlg, (unsigned)hdr.AlgorithmId); + ourRtn++; + } + if(hdr.LogicalKeySizeInBits != keySize) { + printf("***Key Size: expect %u, got %u\n", + (unsigned)keySize, (unsigned)hdr.LogicalKeySizeInBits); + ourRtn++; + } + CSSM_DL_FreeUniqueRecord(dlDbHand, record); + + /* see if there are any more */ + crtn = CSSM_DL_DataGetNext(dlDbHand, + resultHand, + &recordAttrs, + NULL, + &record); + if(crtn == CSSM_OK) { + printf("***More than 1 record of type %s found\n", + recordTypeStr(recordType)); + ourRtn++; + CSSM_DL_FreeUniqueRecord(dlDbHand, record); + } + CSSM_DL_DataAbortQuery(dlDbHand, resultHand); + return ourRtn; +} + +int main( + int argc, + char **argv) +{ + int arg; + char *argp; + char *dbFileName; + CSSM_ALGORITHMS keyAlg; + CSSM_DB_RECORDTYPE recordType; + uint32 keySize; + CSSM_DL_DB_HANDLE dlDbHand; + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_RETURN crtn = CSSM_OK; + + if(argc < 5) { + usage(argv); + } + dbFileName = argv[1]; + + /* key algorithm */ + if(!strcmp(argv[2], "rsa")) { + keyAlg = CSSM_ALGID_RSA; + } + else if(!strcmp(argv[2], "dsa")) { + keyAlg = CSSM_ALGID_DSA; + } + else if(!strcmp(argv[2], "dh")) { + keyAlg = CSSM_ALGID_DH; + } + else if(!strcmp(argv[2], "ecdsa")) { + keyAlg = CSSM_ALGID_ECDSA; + } + else { + usage(argv); + } + + /* key class */ + if(!strcmp(argv[3], "priv")) { + recordType = CSSM_DL_DB_RECORD_PRIVATE_KEY; + } + else if(!strcmp(argv[3], "pub")) { + recordType = CSSM_DL_DB_RECORD_PUBLIC_KEY; + } + else { + usage(argv); + } + + keySize = atoi(argv[4]); + + for(arg=5; arg +#include +#include +#include "cspwrap.h" +#include "common.h" +#include +#include +#include "cspdlTesting.h" + +#define USAGE_DEF "noUsage" +#define LOOPS_DEF 10 +#define KEY_SIZE_DEF 512 +#define DERIVE_KEY_SIZE 128 +#define DERIVE_KEY_ALG CSSM_ALGID_AES +#define ENCR_ALG CSSM_ALGID_AES +#define ENCR_MODE CSSM_ALGMODE_CBCPadIV8 +#define ENCR_PADDING CSSM_PADDING_PKCS7 +#define MAX_PTEXT_SIZE 1024 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" k=keySize (default = %d)\n", KEY_SIZE_DEF); + printf(" l=loops (0=forever)\n"); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" o=fileName (dump key and param blobs to filename)\n"); + printf(" i=filename (obtain param blobs from filename\n"); + printf(" q(uiet)\n"); + printf(" v(erbose))\n"); + exit(1); +} + +/* + * Translate blob format to strings. + */ +typedef struct { + CSSM_KEYBLOB_FORMAT form; + const char *str; +} BlobDesc; + +static const BlobDesc BlobDescs[] = { + { CSSM_KEYBLOB_RAW_FORMAT_NONE, "NONE" }, + { CSSM_KEYBLOB_RAW_FORMAT_PKCS3, "PKCS3" }, + { CSSM_KEYBLOB_RAW_FORMAT_PKCS8, "PKCS8" }, + { CSSM_KEYBLOB_RAW_FORMAT_X509, "X509" }, +}; +#define NUM_BLOB_DESCS (sizeof(BlobDescs) / sizeof(BlobDesc)) + +static const char *blobFormStr( + CSSM_KEYBLOB_FORMAT form) +{ + for(unsigned i=0; iform == form) { + return bdp->str; + } + } + return "***UNKNOWN BLOB FORM"""; +} + +/* + * Generate a Diffie-Hellman key pair. Optionally allows specification of + * algorithm parameters, and optionally returns algorithm parameters if + * we generate them. + */ +static int dhKeyGen( + CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR pubKey, + CSSM_BOOL pubIsRef, + CSSM_KEYBLOB_FORMAT pubForm, // NONE, PKCS3, X509 + CSSM_KEYBLOB_FORMAT expectPubForm, // PKCS3, X509 + CSSM_KEY_PTR privKey, + CSSM_BOOL privIsRef, + CSSM_KEYBLOB_FORMAT privForm, // NONE, PKCS3, PKCS8 + CSSM_KEYBLOB_FORMAT expectPrivForm, // PKCS3, PKCS8 + const CSSM_DATA *inParams, // optional + CSSM_DATA_PTR outParams, // optional, we malloc + uint32 keySizeInBits, + CSSM_BOOL quiet) +{ + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + CSSM_DATA labelData = { strlen(USAGE_DEF), (uint8 *)USAGE_DEF }; + + if(inParams && outParams) { + printf("***dhKeyGen: inParams and outParams are mutually " + "exclusive.\n"); + return -1; + } + memset(pubKey, 0, sizeof(CSSM_KEY)); + memset(privKey, 0, sizeof(CSSM_KEY)); + + crtn = CSSM_CSP_CreateKeyGenContext(cspHand, + CSSM_ALGID_DH, + keySizeInBits, + NULL, // Seed + NULL, // Salt + NULL, // StartDate + NULL, // EndDate + inParams, // Params, may be NULL + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateKeyGenContext", crtn); + return testError(quiet); + } + + if((inParams == NULL) && (outParams != NULL)) { + /* explicitly generate params and return them to caller */ + outParams->Data = NULL; + outParams->Length = 0; + crtn = CSSM_GenerateAlgorithmParams(ccHand, + keySizeInBits, outParams); + if(crtn) { + printError("CSSM_GenerateAlgorithmParams", crtn); + return testError(quiet); + } + } + + if((privForm != CSSM_KEYBLOB_RAW_FORMAT_NONE) && !privIsRef) { + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT, + sizeof(uint32), + CAT_Uint32, + NULL, + privForm); + if(crtn) { + printError("AddContextAttribute(CSSM_ATTRIBUTE_PRIVATE_KEY_" + "FORMAT)", crtn); + return crtn; + } + } + if((pubForm != CSSM_KEYBLOB_RAW_FORMAT_NONE) && !pubIsRef) { + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT, + sizeof(uint32), + CAT_Uint32, + NULL, + pubForm); + if(crtn) { + printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY_" + "FORMAT)", crtn); + return crtn; + } + } + + uint32 privAttr; + uint32 pubAttr = CSSM_KEYATTR_EXTRACTABLE; + if(pubIsRef) { + pubAttr |= CSSM_KEYATTR_RETURN_REF; + } + else { + pubAttr |= CSSM_KEYATTR_RETURN_DATA; + } + if(privIsRef) { + privAttr = CSSM_KEYATTR_RETURN_REF; + } + else { + privAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + } + crtn = CSSM_GenerateKeyPair(ccHand, + /* + * Public key specification. We specify raw key format + * here since we have to have access to the raw public key + * bits in order to perform D-H key exchange. + */ + CSSM_KEYUSE_DERIVE, // only legal use of a Diffie-Hellman key + pubAttr, + &labelData, + pubKey, + /* private key specification */ + CSSM_KEYUSE_DERIVE, + privAttr, + &labelData, // same labels + NULL, // CredAndAclEntry + privKey); + if(crtn) { + printError("CSSM_GenerateKeyPair", crtn); + return testError(quiet); + } + if(!privIsRef && (privKey->KeyHeader.Format != expectPrivForm)) { + printf("***Expected priv format %s got %s\n", + blobFormStr(expectPrivForm), + blobFormStr(privKey->KeyHeader.Format)); + return testError(quiet); + } + if(!pubIsRef && (pubKey->KeyHeader.Format != expectPubForm)) { + printf("***Expected pub format %s got %s\n", + blobFormStr(expectPubForm), + blobFormStr(pubKey->KeyHeader.Format)); + return testError(quiet); + } + CSSM_DeleteContext(ccHand); + return crtn; +} + +/* + * Perform Diffie-Hellman key exchange. + * Given "our" private key (in the form of a CSSM_KEY) and "their" public + * key (in the form of a raw blob of bytes), cook up a symmetric key. + */ +static int dhKeyExchange( + CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR myPrivKey, + CSSM_KEY_PTR theirPubKey, + CSSM_KEY_PTR derivedKey, // RETURNED + uint32 deriveKeySizeInBits, + CSSM_ALGORITHMS derivedKeyAlg, + uint32 derivedKeyUsage, + uint32 derivedKeyAttr, + CSSM_BOOL quiet) +{ + CSSM_RETURN crtn; + CSSM_ACCESS_CREDENTIALS creds; + CSSM_CC_HANDLE ccHand; + CSSM_DATA labelData = + { strlen(USAGE_DEF), (uint8 *)USAGE_DEF }; + + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + memset(derivedKey, 0, sizeof(CSSM_KEY)); + + crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand, + CSSM_ALGID_DH, + derivedKeyAlg, + deriveKeySizeInBits, + &creds, + myPrivKey, // BaseKey + 0, // IterationCount + 0, // Salt + 0, // Seed + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateDeriveKeyContext", crtn); + return testError(quiet); + } + + /* + * Public key passed in as CSSM_DATA *Param - only if + * the pub key is in raw PKCS3 form + */ + CSSM_DATA nullParam = {0, NULL}; + CSSM_DATA_PTR paramPtr; + CSSM_KEYHEADER &hdr = theirPubKey->KeyHeader; + if((hdr.BlobType == CSSM_KEYBLOB_RAW) && + (hdr.Format == CSSM_KEYBLOB_RAW_FORMAT_PKCS3)) { + /* simple case */ + paramPtr = &theirPubKey->KeyData; + } + else { + /* add this pub key as a context attr */ + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PUBLIC_KEY, + sizeof(CSSM_KEY), + CAT_Ptr, + (void *)theirPubKey, + 0); + if(crtn) { + printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY)", + crtn); + return crtn; + } + paramPtr = &nullParam; + } + + crtn = CSSM_DeriveKey(ccHand, + paramPtr, + derivedKeyUsage, + derivedKeyAttr, + &labelData, + NULL, // cread/acl + derivedKey); + if(crtn) { + printError("CSSM_DeriveKey", crtn); + } + CSSM_DeleteContext(ccHand); + return crtn; +} + +static CSSM_DATA someIv = {16, (uint8 *)"Some enchanted init vector" }; + +/* + * Encrypt ptext with myDeriveKey ==> ctext + * decrypt ctext with theirDeriveKey ==> rptext + * ensure ptext == rptext + */ +static int doEncryptTest( + CSSM_CSP_HANDLE cspHand, + const CSSM_DATA *ptext, + CSSM_KEY_PTR myDeriveKey, + CSSM_KEY_PTR theirDeriveKey, + CSSM_ALGORITHMS encrAlg, + uint32 encrMode, + CSSM_PADDING encrPadding, + CSSM_BOOL quiet) +{ + CSSM_DATA ctext = {0, NULL}; + CSSM_DATA rptext = {0, NULL}; + CSSM_RETURN crtn; + + crtn = cspEncrypt(cspHand, + encrAlg, + encrMode, + encrPadding, + myDeriveKey, + NULL, // 2nd key + 0, // effective key size + 0, // rounds + &someIv, + ptext, + &ctext, + CSSM_FALSE); // mallocCtext + if(crtn) { + return testError(quiet); + } + crtn = cspDecrypt(cspHand, + encrAlg, + encrMode, + encrPadding, + theirDeriveKey, + NULL, // 2nd key + 0, // effective key size + 0, // rounds + &someIv, + &ctext, + &rptext, + CSSM_FALSE); // mallocCtext + if(crtn) { + return testError(quiet); + } + if(!appCompareCssmData(ptext, &rptext)) { + printf("***DATA MISCOMPARE***\n"); + return testError(quiet); + } + appFree(ctext.Data, NULL); + appFree(rptext.Data, NULL); + return 0; +} + +int doTest( + CSSM_CSP_HANDLE cspHand, + const CSSM_DATA *ptext, + CSSM_BOOL pubIsRef, + CSSM_KEYBLOB_FORMAT pubForm, // NONE, PKCS3, X509 + CSSM_KEYBLOB_FORMAT expectPubForm, // PKCS3, X509 + CSSM_BOOL privIsRef, + CSSM_KEYBLOB_FORMAT privForm, // NONE, PKCS3, PKCS8 + CSSM_KEYBLOB_FORMAT expectPrivForm, // PKCS3, PKCS8 + CSSM_BOOL sym1IsRef, + CSSM_BOOL sym2IsRef, + const CSSM_DATA *inParams, // optional + CSSM_DATA_PTR outParams, // optional + uint32 keySizeInBits, + CSSM_BOOL quiet) +{ + CSSM_KEY myPriv; + CSSM_KEY myPub; + CSSM_KEY theirPriv; + CSSM_KEY theirPub; + int rtn = 0; + + /* generate two key pairs */ + if(dhKeyGen(cspHand, + &myPub, + pubIsRef, + pubForm, + expectPubForm, + &myPriv, + privIsRef, + privForm, + expectPrivForm, + inParams, + outParams, + keySizeInBits, + quiet)) { + return 1; + } + + /* note this MUST match the params either specified or generated + * in previous call */ + if((inParams == NULL) && (outParams == NULL)) { + printf("***BRRZAP! Must provide a way to match D-H parameters!\n"); + exit(1); + } + const CSSM_DATA *theParams = inParams; + if(theParams == NULL) { + theParams = outParams; + } + if(dhKeyGen(cspHand, + &theirPub, + pubIsRef, + /* let's always use default for this pair */ + CSSM_KEYBLOB_RAW_FORMAT_NONE, + CSSM_KEYBLOB_RAW_FORMAT_PKCS3, // we know this is the default + &theirPriv, + privIsRef, + /* let's always use default for this pair */ + CSSM_KEYBLOB_RAW_FORMAT_NONE, + CSSM_KEYBLOB_RAW_FORMAT_PKCS3, // we know this is the default + theParams, + NULL, // outParams + keySizeInBits, + quiet)) { + return 1; + } + + /* derive two keys, ensure they match */ + CSSM_KEY myDerive; + CSSM_KEY theirDerive; + uint32 myDeriveAttr; + uint32 theirDeriveAttr; + if(sym1IsRef) { + myDeriveAttr = CSSM_KEYATTR_RETURN_REF; + } + else { + myDeriveAttr = + CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + } + if(sym2IsRef) { + theirDeriveAttr = CSSM_KEYATTR_RETURN_REF; + } + else { + theirDeriveAttr = + CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + } + if(dhKeyExchange(cspHand, + &myPriv, + &theirPub, + &myDerive, + DERIVE_KEY_SIZE, + DERIVE_KEY_ALG, + CSSM_KEYUSE_ENCRYPT, + myDeriveAttr, + quiet)) { + return testError(quiet); + } + if(dhKeyExchange(cspHand, + &theirPriv, + &myPub, + &theirDerive, + DERIVE_KEY_SIZE, + DERIVE_KEY_ALG, + CSSM_KEYUSE_DECRYPT, + theirDeriveAttr, + quiet)) { + return testError(quiet); + } + + if(doEncryptTest(cspHand, + ptext, + &myDerive, + &theirDerive, + ENCR_ALG, + ENCR_MODE, + ENCR_PADDING, + quiet)) { + return 1; + } + + cspFreeKey(cspHand, &myPub); + cspFreeKey(cspHand, &myPriv); + cspFreeKey(cspHand, &theirPub); + cspFreeKey(cspHand, &theirPriv); + cspFreeKey(cspHand, &myDerive); + cspFreeKey(cspHand, &theirDerive); + return rtn; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + CSSM_CSP_HANDLE cspHand; + unsigned loop; + int i; + CSSM_DATA inParams = {0, NULL}; + CSSM_DATA outParams = {0, NULL}; + CSSM_DATA_PTR inParamPtr = NULL; + CSSM_DATA_PTR outParamPtr = NULL; + CSSM_DATA ptext; + CSSM_BOOL pubIsRef; + CSSM_BOOL privIsRef; + CSSM_BOOL sym1IsRef; + CSSM_BOOL sym2IsRef; + CSSM_KEYBLOB_FORMAT pubForm; // NONE, PKCS3, X509 + CSSM_KEYBLOB_FORMAT expectPubForm; // PKCS3, X509 + CSSM_KEYBLOB_FORMAT privForm; // NONE, PKCS3, PKCS8 + CSSM_KEYBLOB_FORMAT expectPrivForm; // PKCS3, PKCS8 + + /* user-spec'd parameters */ + unsigned keySize = KEY_SIZE_DEF; + unsigned pauseInterval = 0; + unsigned loops = LOOPS_DEF; + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL bareCsp = CSSM_TRUE; + char *inFileName = NULL; + char *outFileName = NULL; + + for(arg=1; argEEmsmSY~68UIS qAu0iZ4uD@iG^#3=3Wc#i7UvKss$%81A>WzP@|N?o!ZTd60s#Udt|AHm literal 0 HcmV?d00001 diff --git a/SecurityTests/cspxutils/dhTest/Makefile b/SecurityTests/cspxutils/dhTest/Makefile new file mode 100644 index 00000000..1c885a6f --- /dev/null +++ b/SecurityTests/cspxutils/dhTest/Makefile @@ -0,0 +1,61 @@ +# name of executable to build +EXECUTABLE=dhTest +# C++ source (with .cpp extension) +CPSOURCE= dhTest.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +#PROJ_LDFLAGS= -lMallocDebug +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PARAM_FILE_NAME= dhParams_512.der +PARAM_FILE= $(LOCAL_BUILD)/$(PARAM_FILE_NAME) +PROJ_DEPENDS= $(PARAM_FILE) + +include ../Makefile.cdsa + +$(PARAM_FILE): $(PARAM_FILE_NAME) + cp -p $(PARAM_FILE_NAME) $(LOCAL_BUILD) + diff --git a/SecurityTests/cspxutils/dhTest/README b/SecurityTests/cspxutils/dhTest/README new file mode 100644 index 00000000..54f8b996 --- /dev/null +++ b/SecurityTests/cspxutils/dhTest/README @@ -0,0 +1,63 @@ + Diffie-Hellman Sample Code Info + last update 4/24/02 dmitch + +Introduction +------------ +This directory contains a program which demonstrates how to +write code performing Diffie-HEllman key generation and key exchange +using the CDSA API. One command-line executable program, called dhTest, +currently resides here. + +Building +-------- + +See the README in the parent directory (CDSA_Examples) for +information on building this program. + +Running rsatool +--------------- + +DhTest is a UNIX command-line program which performs a the following +sequence a specified number of times: + + 1. generate a D-H key pair, optionally using D-H parameters + stored in a file. Call this key pair "myPublic" and + "myPrivate". + 2. Optionally store the D-H parameters generated in step 1 + in a file. + 3. Generate another D-H key pair using the same D-H parameters + as used (or generated) in step 1. Call this key pair + "theirPublic" and "theirPrivate". + 4. Perform a D-H key exchange operations using myPrivate and + theirPublic, resulting in symmetric key myDerive. + 5. Perform a D-H key exchange operations using myPublic and + theirPrivate, resulting in symmetric key theirDerive. + 6. Ensure that the key bits in myDerive and theirDerive + are identical. + +Run the program with the single 'h' command line argument for +usage information. + +Two functions are of particular interest for the purposes of +illustrating Diffie-Hellman operation. One, dhKeyGen(), performs +D-H key pair generation, using optional existing D-H parameters +and optionally returning D-H parameters if they were generated +by this function (i.e., if they were not supplied to the function +as input). D-H parameters are expressed at the CDSA API as an +opaque blob in the form of a CSSM_DATA. The generation of D-H +parameters is very time consuming - it takes about 90 seconds +to calculate the parameters for 1024 bit D-H keys on an 800 MHz G4. +Therefore any application which will be performing a number of key +pair generations should establish a common set of D-H parameters +to be shared between the two parties. Public disclosure of the +D-H parameters does not compromise the security of D-H key exchange +at all. + +The second function of interest is dhKeyExchange(), which takes as +its input one private key (e.g., "myPrivate") and one public key +blob in the form of a CSSM_DATA. That public key blob is obtained +from the peer when performing D-H key exchange. The result of +this function is a CSSM_KEY, derivedKey. This derived key is +typically used to perform symmetric encryption. See the cryptTool +example in this same package for illustration of symmetric +encryption. diff --git a/SecurityTests/cspxutils/dhTest/dhParams_512.der b/SecurityTests/cspxutils/dhTest/dhParams_512.der new file mode 100644 index 0000000000000000000000000000000000000000..371b79371500605f13e6c1349250ba92c2a8a061 GIT binary patch literal 84 zcmV-a0IUBnQU(YrhDe6@4FLl%MglEEmsmSY~68UIS qAu0iZ4uD@iG^#3=3Wc#i7UvKss$%81A>WzP@|N?o!ZTd60s#Udt|AHm literal 0 HcmV?d00001 diff --git a/SecurityTests/cspxutils/dhTest/dhTest.cpp b/SecurityTests/cspxutils/dhTest/dhTest.cpp new file mode 100644 index 00000000..3017eebf --- /dev/null +++ b/SecurityTests/cspxutils/dhTest/dhTest.cpp @@ -0,0 +1,468 @@ +/* + * dhTest - simple Diffie-Hellman exerciser. + */ +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include +#include + +#define USAGE_DEF "noUsage" +#define LOOPS_DEF 10 +#define KEY_SIZE_DEF 512 +#define DERIVE_KEY_SIZE 128 +#define DERIVE_KEY_ALG CSSM_ALGID_AES + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" k=keySize (default = %d)\n", KEY_SIZE_DEF); + printf(" l=loops (0=forever)\n"); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" o=fileName (dump key and param blobs to filename)\n"); + printf(" i=filename (obtain param blobs from filename)\n"); + printf(" 8 (private key in PKCS8 format, default is PKCS3)\n"); + printf(" x (public key in X509 format, default is PKCS3)\n"); + printf(" f (public key is ref form; default is raw)\n"); + printf(" q(uiet)\n"); + printf(" v(erbose))\n"); + exit(1); +} + +/* + * Generate a Diffie-Hellman key pair. Optionally allows specification of + * algorithm parameters, and optionally returns algorithm parameters if + * we generate them. + */ +static int dhKeyGen( + CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR pubKey, + CSSM_KEY_PTR privKey, + const CSSM_DATA *inParams, // optional + CSSM_DATA_PTR outParams, // optional, we malloc + uint32 keySizeInBits, + CSSM_KEYBLOB_FORMAT privForm, + CSSM_KEYBLOB_FORMAT pubForm, + CSSM_BOOL pubIsRef, + CSSM_BOOL quiet) +{ + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + CSSM_DATA labelData = { strlen(USAGE_DEF), (uint8 *)USAGE_DEF }; + + if(inParams && outParams) { + printf("***dhKeyGen: inParams and outParams are mutually " + "exclusive.\n"); + return -1; + } + memset(pubKey, 0, sizeof(CSSM_KEY)); + memset(privKey, 0, sizeof(CSSM_KEY)); + + crtn = CSSM_CSP_CreateKeyGenContext(cspHand, + CSSM_ALGID_DH, + keySizeInBits, + NULL, // Seed + NULL, // Salt + NULL, // StartDate + NULL, // EndDate + inParams, // Params, may be NULL + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateKeyGenContext", crtn); + return testError(quiet); + } + + if((inParams == NULL) && (outParams != NULL)) { + /* explicitly generate params and return them to caller */ + outParams->Data = NULL; + outParams->Length = 0; + crtn = CSSM_GenerateAlgorithmParams(ccHand, + keySizeInBits, outParams); + if(crtn) { + printError("CSSM_GenerateAlgorithmParams", crtn); + return testError(quiet); + } + } + + uint32 privAttr = CSSM_KEYATTR_RETURN_REF; + uint32 pubAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + if(privForm != CSSM_KEYBLOB_RAW_FORMAT_NONE) { + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT, + sizeof(uint32), + CAT_Uint32, + NULL, + privForm); + if(crtn) { + printError("AddContextAttribute(CSSM_ATTRIBUTE_PRIVATE_KEY" + "_FORMAT)", crtn); + return crtn; + } + privAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + } + if(pubIsRef) { + pubAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; + } + else if(pubForm != CSSM_KEYBLOB_RAW_FORMAT_NONE) { + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT, + sizeof(uint32), + CAT_Uint32, + NULL, + pubForm); + if(crtn) { + printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY" + "_FORMAT)", crtn); + return crtn; + } + } + crtn = CSSM_GenerateKeyPair(ccHand, + CSSM_KEYUSE_DERIVE, // only legal use of a Diffie-Hellman key + pubAttr, + &labelData, + pubKey, + /* private key specification */ + CSSM_KEYUSE_DERIVE, + privAttr, + &labelData, // same labels + NULL, // CredAndAclEntry + privKey); + if(crtn) { + printError("CSSM_GenerateKeyPair", crtn); + return testError(quiet); + } + + CSSM_DeleteContext(ccHand); + return crtn; +} + +/* + * Perform Diffie-Hellman key exchange. + * Given "our" private key (in the form of a CSSM_KEY) and "their" public + * key (in the form of a raw blob of bytes), cook up a symmetric key. + */ +static int dhKeyExchange( + CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR myPrivKey, + CSSM_KEY_PTR theirPubKey, + CSSM_KEY_PTR derivedKey, // RETURNED + uint32 deriveKeySizeInBits, + CSSM_ALGORITHMS derivedKeyAlg, + uint32 derivedKeyUsage, + uint32 derivedKeyAttr, + CSSM_BOOL quiet) +{ + CSSM_RETURN crtn; + CSSM_ACCESS_CREDENTIALS creds; + CSSM_CC_HANDLE ccHand; + CSSM_DATA labelData = { strlen(USAGE_DEF), (uint8 *)USAGE_DEF }; + + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + memset(derivedKey, 0, sizeof(CSSM_KEY)); + + crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand, + CSSM_ALGID_DH, + derivedKeyAlg, + deriveKeySizeInBits, + &creds, + myPrivKey, // BaseKey + 0, // IterationCount + 0, // Salt + 0, // Seed + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateDeriveKeyContext", crtn); + return testError(quiet); + } + + /* + * Public key passed in as CSSM_DATA *Param - only if + * the pub key is in raw PKCS3 form + */ + CSSM_DATA nullParam = {0, NULL}; + CSSM_DATA_PTR paramPtr; + CSSM_KEYHEADER &hdr = theirPubKey->KeyHeader; + if((hdr.BlobType == CSSM_KEYBLOB_RAW) && + (hdr.Format == CSSM_KEYBLOB_RAW_FORMAT_PKCS3)) { + /* simple case */ + paramPtr = &theirPubKey->KeyData; + } + else { + /* add this pub key as a context attr */ + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PUBLIC_KEY, + sizeof(CSSM_KEY), + CAT_Ptr, + (void *)theirPubKey, + 0); + if(crtn) { + printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY)", + crtn); + return crtn; + } + paramPtr = &nullParam; + } + crtn = CSSM_DeriveKey(ccHand, + paramPtr, + derivedKeyUsage, + derivedKeyAttr, + &labelData, + NULL, // cread/acl + derivedKey); + if(crtn) { + printError("CSSM_DeriveKey", crtn); + } + CSSM_DeleteContext(ccHand); + return crtn; +} + +int doTest( + CSSM_CSP_HANDLE cspHand, + const CSSM_DATA *inParams, // optional + CSSM_DATA_PTR outParams, // optional + uint32 keySizeInBits, + CSSM_KEYBLOB_FORMAT privForm, + CSSM_KEYBLOB_FORMAT pubForm, + CSSM_BOOL pubIsRef, + CSSM_BOOL quiet) +{ + CSSM_KEY myPriv; + CSSM_KEY myPub; + CSSM_KEY theirPriv; + CSSM_KEY theirPub; + int rtn = 0; + + /* generate two key pairs */ + if(dhKeyGen(cspHand, + &myPub, + &myPriv, + inParams, + outParams, + keySizeInBits, + privForm, + pubForm, + pubIsRef, + quiet)) { + return 1; + } + + /* note this MUST match the params either specified or generated in previous + * call */ + if((inParams == NULL) && (outParams == NULL)) { + printf("***BRRZAP! Must provide a way to match D-H parameters!\n"); + exit(1); + } + const CSSM_DATA *theParams = inParams; + if(theParams == NULL) { + theParams = outParams; + } + if(dhKeyGen(cspHand, + &theirPub, + &theirPriv, + theParams, + NULL, // outParams + keySizeInBits, + privForm, + pubForm, + pubIsRef, + quiet)) { + return 1; + } + + /* derive two keys, ensure they match */ + CSSM_KEY myDerive; + CSSM_KEY theirDerive; + if(dhKeyExchange(cspHand, + &myPriv, + &theirPub, + &myDerive, + DERIVE_KEY_SIZE, + DERIVE_KEY_ALG, + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, + quiet)) { + return testError(quiet); + } + if(dhKeyExchange(cspHand, + &theirPriv, + &myPub, + &theirDerive, + DERIVE_KEY_SIZE, + DERIVE_KEY_ALG, + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, + quiet)) { + return testError(quiet); + } + + if(!appCompareCssmData(&myDerive.KeyData, &theirDerive.KeyData)) { + printf("***Key Exchange data miscompare***\n"); + rtn = testError(quiet); + } + cspFreeKey(cspHand, &myPub); + cspFreeKey(cspHand, &myPriv); + cspFreeKey(cspHand, &theirPub); + cspFreeKey(cspHand, &theirPriv); + cspFreeKey(cspHand, &myDerive); + cspFreeKey(cspHand, &theirDerive); + return rtn; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + CSSM_CSP_HANDLE cspHand; + unsigned loop; + int i; + CSSM_DATA inParams = {0, NULL}; + CSSM_DATA outParams = {0, NULL}; + CSSM_DATA_PTR inParamPtr = NULL; + CSSM_DATA_PTR outParamPtr = NULL; + + /* user-spec'd parameters */ + unsigned keySize = KEY_SIZE_DEF; + unsigned pauseInterval = 0; + unsigned loops = LOOPS_DEF; + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL bareCsp = CSSM_TRUE; + char *inFileName = NULL; + char *outFileName = NULL; + /* default: "use default blob form", i.e., PKCS3 */ + CSSM_KEYBLOB_FORMAT privForm = CSSM_KEYBLOB_RAW_FORMAT_NONE; + CSSM_KEYBLOB_FORMAT pubForm = CSSM_KEYBLOB_RAW_FORMAT_NONE; + CSSM_BOOL pubIsRef = CSSM_FALSE; + + for(arg=1; args zTk_pg?`{jD)3y)IZjotNvX91rg6Ud!rw<8MY&0zm+Z zf94C;9Pq^S7GN1poM&qy&;B;DwUrC)*+Ur;(GZL}w`a`LX#xpu&h9 O?j%}%aai~eLZnw?l~APs literal 0 HcmV?d00001 diff --git a/SecurityTests/cspxutils/dsaPartial/dsaParam512_2.der b/SecurityTests/cspxutils/dsaPartial/dsaParam512_2.der new file mode 100644 index 0000000000000000000000000000000000000000..4a9ede96618b7d43a1fd666cd3a94eb57928497d GIT binary patch literal 160 zcmV;R0AK$wft>7Y%$hE(c`jC-KiDxnhg8~%*sG0T$yA3OouL&XrJtyMt;<&C?0zm+X zg}2;Z34ad`YwH0LVM}$A(`4su;_RuPE&pg3!V|mgp4KwvJ*>ejHwAeioClZ=Vd{Or O7QMNvsJ<=-e6aas8A$yA literal 0 HcmV?d00001 diff --git a/SecurityTests/cspxutils/dsaPartial/dsaPartial.cpp b/SecurityTests/cspxutils/dsaPartial/dsaPartial.cpp new file mode 100644 index 00000000..1434162d --- /dev/null +++ b/SecurityTests/cspxutils/dsaPartial/dsaPartial.cpp @@ -0,0 +1,724 @@ +/* + * dsaPartial.cpp - test for partial DSA public handling + */ +#include +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include +#include "nssAppUtils.h" + +/* + * generate key pairs with one set of parameters, dsa1Priv and dsa1Pub; + * genenate another pair with a different set of params, dsa2Priv and + * dsa2Pub; + * manually cook up dsa1PubPartial from dsa1Pub; + * manually cook up dsa2PubPartial from dsa2Pub; + * + * with all legal and/or specified combos of {ref,raw} keys { + * sign with dsa1Priv; + * vfy with dsa1Pub; + * vfy with dsa1PubPartial: CSSMERR_CSP_APPLE_DSA_PUBLIC_KEY_INCOMPLETE + * vfy with dsa1PubPartial and dsa1Pub (attrs) + * vfy with dsa2PubPartial and dsa1Pub (attrs) --> vfy fail + * vfy with dsa1PubPartial and dsa2Pub (attrs) --> vfy fail + * merge dsa1PubPartial + dsa1Pub --> merged; + * vfy with merged, should be good + * merge dsa1PubPartial + dsa2Pub -->merged; + * vfy with merged; vfy fail; + * } + */ + +/* + * Static parameter files. + * + * Regenerate these every once in a while with rsatool: + * + * # rsatool g a=d k=/tmp/foo M=dsaParam512_1.der + */ +#define PARAMS_512_1 "dsaParam512_1.der" +#define PARAMS_512_2 "dsaParam512_2.der" + +#define MAX_PTEXT_SIZE 512 +#define KEY_ALG CSSM_ALGID_DSA +#define SIG_ALG CSSM_ALGID_SHA1WithDSA +#define LOOPS_DEF 32 +#define KEY_SIZE_DEF 512 + +static void usage(char **argv) +{ + printf("Usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" l=loops\n"); + printf(" p(ause on loop)\n"); + printf(" q(uiet)\n"); + printf(" v(erbose)\n"); + printf(" D (CSPDL)\n"); + printf(" r (all keys are raw)\n"); + printf(" f (all keys are ref)\n"); + exit(1); +} + +/* + * Generate DSA key pair with required alg parameters. + */ +static CSSM_RETURN genDsaKeyPair( + CSSM_CSP_HANDLE cspHand, + uint32 keySize, // in bits + CSSM_KEY_PTR pubKey, // mallocd by caller + CSSM_BOOL pubIsRef, // true - reference key, false - data + CSSM_KEY_PTR privKey, // mallocd by caller + CSSM_BOOL privIsRef, // true - reference key, false - data + const CSSM_DATA *params) +{ + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + CSSM_DATA keyLabelData; + uint32 pubAttr; + uint32 privAttr; + + if(params == NULL) { + return CSSMERR_CSSM_INVALID_POINTER; + } + + keyLabelData.Data = (uint8 *)"foobar", + keyLabelData.Length = 6; + memset(pubKey, 0, sizeof(CSSM_KEY)); + memset(privKey, 0, sizeof(CSSM_KEY)); + + crtn = CSSM_CSP_CreateKeyGenContext(cspHand, + CSSM_ALGID_DSA, + keySize, + NULL, // Seed + NULL, // Salt + NULL, // StartDate + NULL, // EndDate + params, + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateKeyGenContext", crtn); + return crtn; + } + + /* cook up attribute bits */ + if(pubIsRef) { + pubAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; + } + else { + pubAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + } + if(privIsRef) { + privAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; + } + else { + privAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + } + + crtn = CSSM_GenerateKeyPair(ccHand, + CSSM_KEYUSE_VERIFY, + pubAttr, + &keyLabelData, + pubKey, + CSSM_KEYUSE_SIGN, + privAttr, + &keyLabelData, // same labels + NULL, // CredAndAclEntry + privKey); + if(crtn) { + printError("CSSM_GenerateKeyPair", crtn); + } + CSSM_DeleteContext(ccHand); + return crtn; +} + + +/* + * Create new public key by merging specified partial key and + * parameter-bearing key. All keys can be in any format (though + * it's the caller's responsibility to avoid using a ref paramKey + * with the CSPDL). + */ +static CSSM_RETURN dsaMergeParams( + CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *partialKey, + const CSSM_KEY *paramKey, + CSSM_KEY &fullKey, // RETURNED + bool fullIsRef) // ref/raw +{ + /* + * First step is a null wrap or unwrap depending on + * format of partialKey. + */ + CSSM_CC_HANDLE ccHand; + CSSM_RETURN crtn; + CSSM_ACCESS_CREDENTIALS creds; + CSSM_DATA label = {10, (uint8 *)"dummyLabel"}; + CSSM_DATA descrData = {0, NULL}; + const CSSM_KEYHEADER &hdr = partialKey->KeyHeader; + + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + crtn = CSSM_CSP_CreateSymmetricContext(cspHand, + CSSM_ALGID_NONE, + CSSM_ALGMODE_NONE, + &creds, + NULL, // wrapping key + NULL, // initVector + CSSM_PADDING_NONE, + 0, // Params + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateSymmetricContext", crtn); + return crtn; + } + + /* add in paramKey */ + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PARAM_KEY, + sizeof(CSSM_KEY), + CAT_Ptr, + paramKey, + 0); + if(crtn) { + printError("AddContextAttribute", crtn); + return crtn; + } + + /* go */ + CSSM_KEY targetKey; + memset(&targetKey, 0, sizeof(targetKey)); + if(hdr.BlobType == CSSM_KEYBLOB_RAW) { + /* raw --> ref : null unwrap */ + crtn = CSSM_UnwrapKey(ccHand, + NULL, // PublicKey + partialKey, + hdr.KeyUsage, // same as original + CSSM_KEYATTR_EXTRACTABLE |CSSM_KEYATTR_RETURN_REF, + &label, + NULL, // CredAndAclEntry + &targetKey, + &descrData); // required + if(crtn) { + printError("dsaMergeParams CSSM_UnwrapKey (1)", crtn); + return crtn; + } + } + else { + /* ref --> raw : null wrap */ + crtn = CSSM_WrapKey(ccHand, + &creds, + partialKey, + NULL, // DescriptiveData + &targetKey); + if(crtn) { + printError("dsaMergeParams CSSM_WrapKey (1)", crtn); + return crtn; + } + } + + if(targetKey.KeyHeader.KeyAttr & CSSM_KEYATTR_PARTIAL) { + printf("***merged key still has CSSM_KEYATTR_PARTIAL\n"); + return CSSMERR_CSSM_INTERNAL_ERROR; + } + + CSSM_KEYBLOB_TYPE targetBlob; + if(fullIsRef) { + targetBlob = CSSM_KEYBLOB_REFERENCE; + } + else { + targetBlob = CSSM_KEYBLOB_RAW; + } + + if(targetKey.KeyHeader.BlobType == targetBlob) { + /* we're done */ + fullKey = targetKey; + CSSM_DeleteContext(ccHand); + return CSSM_OK; + } + + /* + * We're going to reuse the context, but since the parameter merge + * has already been done, remove the CSSM_ATTRIBUTE_PARAM_KEY + * attribute. + */ + CSSM_CONTEXT_ATTRIBUTE attr; + memset(&attr, 0, sizeof(attr)); + attr.AttributeType = CSSM_ATTRIBUTE_PARAM_KEY; + crtn = CSSM_DeleteContextAttributes(ccHand, 1, &attr); + if(crtn) { + printError("CSSM_DeleteContextAttributes", crtn); + return crtn; + } + + /* one more conversion */ + if(targetBlob == CSSM_KEYBLOB_REFERENCE) { + /* raw --> ref : null unwrap */ + crtn = CSSM_UnwrapKey(ccHand, + NULL, // PublicKey + &targetKey, + hdr.KeyUsage, // same as original + CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_REF, + &label, + NULL, // CredAndAclEntry + &fullKey, + &descrData); // required + if(crtn) { + printError("dsaMergeParams CSSM_UnwrapKey (2)", crtn); + return crtn; + } + } + else { + /* ref --> raw : null wrap */ + crtn = CSSM_WrapKey(ccHand, + &creds, + &targetKey, + NULL, // DescriptiveData + &fullKey); + if(crtn) { + printError("dsaMergeParams CSSM_WrapKey (2)", crtn); + return crtn; + } + } + CSSM_FreeKey(cspHand, NULL, &targetKey, CSSM_FALSE); + CSSM_DeleteContext(ccHand); + return CSSM_OK; +} + +/* + * Custom cspSigVerify with optional CSSM_ATTRIBUTE_PARAM_KEY + */ +CSSM_RETURN sigVerify(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_SHA1WithDSA, etc. + CSSM_KEY_PTR key, // public key + CSSM_KEY_PTR paramKey, // optional parameter key + const CSSM_DATA *ptext, + const CSSM_DATA *sig, + CSSM_RETURN expectResult, + const char *op, + CSSM_BOOL verbose) +{ + CSSM_CC_HANDLE sigHand; + CSSM_RETURN ocrtn = CSSM_OK; + CSSM_RETURN crtn; + + if(verbose) { + printf(" ...%s\n", op); + } + crtn = CSSM_CSP_CreateSignatureContext(cspHand, + algorithm, + NULL, // passPhrase + key, + &sigHand); + if(crtn) { + printError("CSSM_CSP_CreateSignatureContext", crtn); + return crtn; + } + if(paramKey) { + crtn = AddContextAttribute(sigHand, + CSSM_ATTRIBUTE_PARAM_KEY, + sizeof(CSSM_KEY), + CAT_Ptr, + paramKey, + 0); + if(crtn) { + printError("AddContextAttribute", crtn); + return crtn; + } + } + crtn = CSSM_VerifyData(sigHand, + ptext, + 1, + CSSM_ALGID_NONE, + sig); + if(crtn != expectResult) { + if(!crtn) { + printf("%s: Unexpected good Sig Verify (expect %s)\n", + op, cssmErrToStr(expectResult)); + ocrtn = CSSMERR_CSSM_INTERNAL_ERROR; + } + else { + printError(op, crtn); + ocrtn = crtn; + } + } + CSSM_DeleteContext(sigHand); + return ocrtn; +} + +static int doTest( + CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR privKey_0, + CSSM_KEY_PTR pubKeyBase_0, + CSSM_KEY_PTR pubKeyPartial_0, + CSSM_KEY_PTR pubKeyParam_0, // full, raw format if CSPDL + CSSM_KEY_PTR pubKeyPartial_1, + CSSM_KEY_PTR pubKeyParam_1, // full, raw format if CSPDL + bool mergedIsRef, + CSSM_BOOL quiet, + CSSM_BOOL verbose) +{ + uint8 ptextBuf[MAX_PTEXT_SIZE]; + CSSM_DATA ptext = {0, ptextBuf}; + simpleGenData(&ptext, 1, MAX_PTEXT_SIZE); + CSSM_DATA sig = {0, NULL}; + CSSM_RETURN crtn; + + /* the single sign op for this routine */ + crtn = cspSign(cspHand, SIG_ALG, privKey_0, &ptext, &sig); + if(crtn) { + return testError(quiet); + } + + /* normal verify with full key */ + crtn = sigVerify(cspHand, SIG_ALG, pubKeyBase_0, NULL, + &ptext, &sig, CSSM_OK, "vfy with full key", verbose); + if(crtn) { + return testError(quiet); + } + + /* good verify with partial key plus params */ + crtn = sigVerify(cspHand, SIG_ALG, pubKeyPartial_0, pubKeyParam_0, + &ptext, &sig, CSSM_OK, "vfy with partial key and params", + verbose); + if(crtn) { + if(testError(quiet)) { + return 1; + } + } + + /* partial key failure */ + crtn = sigVerify(cspHand, SIG_ALG, pubKeyPartial_0, NULL, + &ptext, &sig, + CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE, + "vfy with partial key no params", verbose); + if(crtn) { + if(testError(quiet)) { + return 1; + } + } + + /* partial key, wrong params */ + crtn = sigVerify(cspHand, SIG_ALG, pubKeyPartial_0, pubKeyParam_1, + &ptext, &sig, + CSSMERR_CSP_VERIFY_FAILED, + "vfy with partial key wrong params", verbose); + if(crtn) { + if(testError(quiet)) { + return 1; + } + } + + /* wrong partial key, good params */ + crtn = sigVerify(cspHand, SIG_ALG, pubKeyPartial_1, pubKeyParam_0, + &ptext, &sig, + CSSMERR_CSP_VERIFY_FAILED, + "vfy with wrong partial key, good params", verbose); + if(crtn) { + if(testError(quiet)) { + return 1; + } + } + + /* + * Test merge via wrap/unwrap. + * First, a good merged key. + */ + CSSM_KEY merged; + crtn = dsaMergeParams(cspHand, + pubKeyPartial_0, + pubKeyParam_0, + merged, + mergedIsRef); + if(crtn) { + return testError(quiet); + } + crtn = sigVerify(cspHand, SIG_ALG, &merged, NULL, + &ptext, &sig, CSSM_OK, "vfy with good merged key", verbose); + if(crtn) { + return testError(quiet); + } + CSSM_FreeKey(cspHand, NULL, &merged, CSSM_FALSE); + + /* now with a badly merged key (with the wrong params) */ + crtn = dsaMergeParams(cspHand, + pubKeyPartial_0, + pubKeyParam_1, + merged, + mergedIsRef); + if(crtn) { + return testError(quiet); + } + crtn = sigVerify(cspHand, SIG_ALG, &merged, NULL, + &ptext, &sig, + CSSMERR_CSP_VERIFY_FAILED, + "vfy with merged key wrong params", verbose); + if(crtn) { + if(testError(quiet)) { + return 1; + } + } + CSSM_FreeKey(cspHand, NULL, &merged, CSSM_FALSE); + + CSSM_FREE(sig.Data); + return CSSM_OK; +} + + +int main(int argc, char **argv) +{ + char *argp; + CSSM_CSP_HANDLE cspHand; + CSSM_RETURN crtn; + + /* user spec'd variables */ + unsigned loops = LOOPS_DEF; + CSSM_BOOL doPause = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL rawCSP = CSSM_TRUE; + CSSM_BOOL verbose = CSSM_FALSE; + uint32 keySize = KEY_SIZE_DEF; + CSSM_BOOL allRaw = CSSM_FALSE; + CSSM_BOOL allRef = CSSM_FALSE; + + for(int arg=1; arg these were created as ref keys + !allRaw && // allRaw --> don't want ref keys + !allRef) { // allRef --> these were created as ref keys + if(cspRawKeyToRef(cspHand, &dsa1Pub, &dsa1PubRef) || + cspRawKeyToRef(cspHand, &dsa2Pub, &dsa2PubRef)) { + exit(1); + } + } + if(!rawCSP || !allRaw) { + /* these were created in raw form unconditionally */ + if(cspRawKeyToRef(cspHand, &dsa1PubPartial, + &dsa1PubPartialRef) || + cspRawKeyToRef(cspHand, &dsa2PubPartial, + &dsa2PubPartialRef)) { + exit(1); + } + + /* verify that these came back with the partial flag set */ + if(!(dsa1PubPartialRef.KeyHeader.KeyAttr & + CSSM_KEYATTR_PARTIAL)) { + printf("***CSSM_KEYATTR_PARTIAL not set after null unwrap" + " of partial DSA key\n"); + if(testError(quiet)) { + exit(1); + } + } + if(!(dsa2PubPartialRef.KeyHeader.KeyAttr & + CSSM_KEYATTR_PARTIAL)) { + printf("***CSSM_KEYATTR_PARTIAL not set after null unwrap" + " of partial DSA key\n"); + if(testError(quiet)) { + exit(1); + } + } + } + + int rtn = 0; + for(unsigned loop=0; loop +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" + +#define LOOPS_DEF 32 +#define KEY_SIZE_DEF 256 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" k=keySize (default = %d)\n", KEY_SIZE_DEF); + printf(" X (X9.63 key derivation)\n"); + printf(" l=loops (0=forever)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" q(uiet)\n"); + printf(" v(erbose))\n"); + exit(1); +} + +#define LABEL_DEF "noLabel" +#define MAX_SHARED_INFO_LEN 400 +#define MAX_DERIVED_SIZE 1024 + +static int doECDH( + CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR privKey, + /* + * pubKey: + * Ref form - use key as pubKey as is + * X509 form - use as is + * OCTET_STRING form - use key data as Param + */ + CSSM_KEY_PTR pubKey, + CSSM_BOOL bareCsp, // false --> derive ref key and NULL-wrap it + CSSM_BOOL x963KDF, + CSSM_DATA *sharedInfo, + uint32 deriveSizeInBits, + CSSM_BOOL quiet, + CSSM_BOOL verbose, + + /* result RETURNED here */ + CSSM_KEY_PTR derivedKey) + +{ + CSSM_DATA paramData = {0, NULL}; + CSSM_KEY_PTR contextPubKey = NULL; + CSSM_KEYHEADER_PTR hdr = &pubKey->KeyHeader; + + if((hdr->BlobType == CSSM_KEYBLOB_RAW) && + (hdr->Format == CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING)) { + paramData = pubKey->KeyData; + } + else { + contextPubKey = pubKey; + } + + /* create key derivation context */ + CSSM_RETURN crtn; + CSSM_ACCESS_CREDENTIALS creds; + CSSM_CC_HANDLE ccHand; + + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + + CSSM_ALGORITHMS deriveAlg; + if(x963KDF) { + deriveAlg = CSSM_ALGID_ECDH_X963_KDF; + } + else { + deriveAlg = CSSM_ALGID_ECDH; + } + + crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand, + deriveAlg, + CSSM_ALGID_RC4, // doesn't matter, just give us the bits + deriveSizeInBits, + &creds, + privKey, // BaseKey + 0, // IterationCount + sharedInfo, // Salt + 0, // Seed + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateDeriveKeyContext", crtn); + return testError(quiet); + } + + if(contextPubKey != NULL) { + /* add pub key as a context attr */ + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PUBLIC_KEY, + sizeof(CSSM_KEY), + CAT_Ptr, + (void *)contextPubKey, + 0); + if(crtn) { + printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY)", + crtn); + return crtn; + } + } + + /* D-H derive key */ + CSSM_DATA labelData = { strlen(LABEL_DEF), (uint8 *)LABEL_DEF }; + CSSM_KEYATTR_FLAGS keyAttr = bareCsp ? + (CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE) : + (CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE); + memset(derivedKey, 0, sizeof(CSSM_KEY)); + crtn = CSSM_DeriveKey(ccHand, + ¶mData, + CSSM_KEYUSE_ANY, + keyAttr, + &labelData, + NULL, // cread/acl + derivedKey); + if(crtn) { + printError("CSSM_DeriveKey", crtn); + } + CSSM_DeleteContext(ccHand); + if(crtn) { + return testError(quiet); + } + + if(!bareCsp) { + /* Got a ref key, give caller raw */ + CSSM_KEY refKey = *derivedKey; + crtn = cspRefKeyToRaw(cspHand, &refKey, derivedKey); + cspFreeKey(cspHand, &refKey); + } + return 0; +} + +/* define public key style */ +typedef enum { + PKT_Ref, /* ref key */ + PKT_Wrap, /* generate ref key, wrap to OCTET_STRING */ + PKT_X509, /* raw key X509 format */ + PKT_Octet /* generate to OCTET_STRING form */ +} PubKeyType; + +#define BoolStr(v) (v ? "true " : "false") + +static const char *KeyStypeStr( + PubKeyType keyType) +{ + switch(keyType) { + case PKT_Ref: return "Ref"; + case PKT_Wrap: return "Ref->Wrap"; + case PKT_X509: return "X509"; + case PKT_Octet: return "X9.62"; + default: return "BRRZAP"; + } +} + +static int doTest( + CSSM_CSP_HANDLE cspHand, + CSSM_BOOL ourKeysRef, /* our keys are reference */ + CSSM_BOOL theirPrivKeyRef, /* their private key is reference */ + PubKeyType theirPubKeyType, + unsigned keySizeBits, + CSSM_BOOL bareCsp, + CSSM_BOOL x963KDF, + CSSM_BOOL useSharedInfo, /* use the optional SharedInfo for x963KDF */ + CSSM_BOOL verbose, + CSSM_BOOL quiet) +{ + + CSSM_RETURN crtn; + CSSM_KEY ourPriv; + CSSM_KEY ourPub; + bool ourKeysGend = false; + bool theirKeysGend = false; + bool wrappedTheirPub = false; + bool wrappedOurPub = false; + bool derivedKey1 = false; + bool derivedKey2 = false; + CSSM_DATA sharedInfo = {0, NULL}; + uint32 deriveSizeInBits; + + if(x963KDF) { + /* arbitrary derived size */ + deriveSizeInBits = genRand(1, MAX_DERIVED_SIZE); + } + else { + deriveSizeInBits = keySizeBits; + } + if(useSharedInfo) { + /* length should be totally arbitrary */ + appSetupCssmData(&sharedInfo, MAX_SHARED_INFO_LEN); + simpleGenData(&sharedInfo, 1, MAX_SHARED_INFO_LEN); + } + + + if(!quiet) { + if(x963KDF) { + printf("...sharedInfoLen %4lu deriveSize %4lu ", + (unsigned long)sharedInfo.Length, (unsigned long)deriveSizeInBits); + } + else { + printf("..."); + } + printf("ourRef %s theirPrivRef %s theirPub %s\n", + BoolStr(ourKeysRef), BoolStr(theirPrivKeyRef), + KeyStypeStr(theirPubKeyType)); + } + + crtn = cspGenKeyPair(cspHand, CSSM_ALGID_ECDSA, + LABEL_DEF, strlen(LABEL_DEF), keySizeBits, + &ourPub, ourKeysRef, CSSM_KEYUSE_DERIVE, CSSM_KEYBLOB_RAW_FORMAT_NONE, + &ourPriv, ourKeysRef, CSSM_KEYUSE_DERIVE, CSSM_KEYBLOB_RAW_FORMAT_NONE, + CSSM_FALSE); + if(crtn) { + return testError(quiet); + } + ourKeysGend = true; + + CSSM_KEY theirPriv; + CSSM_KEY theirPub; /* the generated one */ + CSSM_KEY theirWrappedPub; /* optional NULL unwrap */ + CSSM_KEY_PTR theirPubPtr; + CSSM_KEY ourWrappedPub; /* optional NULL unwrap */ + CSSM_KEY_PTR ourPubPtr; + CSSM_KEY derived1; + CSSM_KEY derived2; + CSSM_BOOL pubIsRef = CSSM_FALSE; + CSSM_KEYBLOB_FORMAT blobForm = CSSM_KEYBLOB_RAW_FORMAT_NONE; + int ourRtn = 0; + + switch(theirPubKeyType) { + case PKT_Ref: + case PKT_Wrap: + pubIsRef = CSSM_TRUE; + break; + case PKT_X509: + pubIsRef = CSSM_FALSE; + break; + case PKT_Octet: + pubIsRef = CSSM_FALSE; + blobForm = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; + break; + } + + crtn = cspGenKeyPair(cspHand, CSSM_ALGID_ECDSA, + LABEL_DEF, strlen(LABEL_DEF), keySizeBits, + &theirPub, pubIsRef, CSSM_KEYUSE_DERIVE, CSSM_KEYBLOB_RAW_FORMAT_NONE, + &theirPriv, theirPrivKeyRef, CSSM_KEYUSE_DERIVE, CSSM_KEYBLOB_RAW_FORMAT_NONE, + CSSM_FALSE); + if(crtn) { + ourRtn = testError(quiet); + goto errOut; + } + + if(theirPubKeyType == PKT_Wrap) { + /* + * This test mode is here mainly to ring out the key wrap and + * OCTET_STRING format functionality in the CrypkitCSP, it's + * not really relevant to ECDH... + */ + crtn = cspRefKeyToRawWithFormat(cspHand, &theirPub, + CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING, &theirWrappedPub); + if(crtn) { + ourRtn = testError(quiet); + goto errOut; + } + theirPubPtr = &theirWrappedPub; + wrappedTheirPub = true; + } + else { + theirPubPtr = &theirPub; + } + + if(!bareCsp) { + /* + * For CSPDL, convert our pub key to OCTET_STRING format so it + * is sent as a Param - can't send a ref key (or any other pub + * key) in the context + */ + crtn = cspRefKeyToRawWithFormat(cspHand, &ourPub, + CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING, &ourWrappedPub); + if(crtn) { + ourRtn = testError(quiet); + goto errOut; + } + ourPubPtr = &ourWrappedPub; + wrappedOurPub = true; + } + else { + ourPubPtr = &ourPub; + } + + /* + * Here we go, do the two sides of D-H key agreement, results to + * to CSSM_KEYs. + */ + ourRtn = doECDH(cspHand, &ourPriv, theirPubPtr, bareCsp, + x963KDF, useSharedInfo ? &sharedInfo : NULL, + deriveSizeInBits, quiet, verbose, &derived1); + if(ourRtn) { + goto errOut; + } + ourRtn = doECDH(cspHand, &theirPriv, ourPubPtr, bareCsp, + x963KDF, useSharedInfo ? &sharedInfo : NULL, + deriveSizeInBits, quiet, verbose, &derived2); + if(ourRtn) { + goto errOut; + } + + if(!appCompareCssmData(&derived1.KeyData, &derived2.KeyData)) { + printf("***Data Miscompare on ECDH key derivation\n"); + } +errOut: + if(ourKeysGend) { + cspFreeKey(cspHand, &ourPub); + cspFreeKey(cspHand, &ourPriv); + } + if(theirKeysGend) { + cspFreeKey(cspHand, &theirPub); + cspFreeKey(cspHand, &theirPriv); + } + if(wrappedTheirPub) { + cspFreeKey(cspHand, &theirWrappedPub); + } + if(wrappedOurPub) { + cspFreeKey(cspHand, &ourWrappedPub); + } + if(derivedKey1) { + cspFreeKey(cspHand, &derived1); + } + if(derivedKey2) { + cspFreeKey(cspHand, &derived2); + } + if(sharedInfo.Data != NULL) { + appFreeCssmData(&sharedInfo, CSSM_FALSE); + } + return ourRtn; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + CSSM_CSP_HANDLE cspHand; + unsigned loop; + int ourRtn = 0; + + unsigned keySize = KEY_SIZE_DEF; + unsigned loops = LOOPS_DEF; + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL bareCsp = CSSM_TRUE; + CSSM_BOOL x963KDF = CSSM_FALSE; + + for(arg=1; arg 0 ) + switch ( "$argv[1]" ) + case s: + set QUICK_TEST = 1 + shift + breaksw + default: + if("$argv[1]" == "C=m") then + set WEIERSTRASS = 0 + endif + set CMD_ARGS = "$CMD_ARGS $argv[1]" + shift + breaksw + endsw +end +# +# Select 'quick' or 'normal' test params +# +if($QUICK_TEST == 1) then + set SIGTEST_ARGS= + set BADSIG_ARGS="l=4 i=10" + set ASYMTEST_ARGS= +else + set SIGTEST_ARGS= + set BADSIG_ARGS="l=20" + set ASYMTEST_ARGS= +endif +# +cd $BUILD_DIR +# +# sigtest - FEE/MD5, FEE/SHA1 for all curves; ECDSA for Weierstrass only +# +sigtest a=f $SIGTEST_ARGS $CMD_ARGS || exit(1) +sigtest a=F $SIGTEST_ARGS $CMD_ARGS || exit(1) +if($WEIERSTRASS == 1) then + sigtest a=e $SIGTEST_ARGS $CMD_ARGS || exit(1) +endif +# +# badsig - FEE/MD5, FEE/SHA1 for all curves; ECDSA for Weierstrass only +# +badsig a=f $BADSIG_ARGS $CMD_ARGS || exit(1) +badsig a=F $BADSIG_ARGS $CMD_ARGS || exit(1) +if($WEIERSTRASS == 1) then + badsig a=e $BADSIG_ARGS $CMD_ARGS || exit(1) +endif +# +# asymtest - FEED, FEEDExp for all curves +# +asymTest a=f $ASYMTEST_ARGS $CMD_ARGS || exit(1) +asymTest a=x $ASYMTEST_ARGS $CMD_ARGS || exit(1) diff --git a/SecurityTests/cspxutils/feedvt b/SecurityTests/cspxutils/feedvt new file mode 100755 index 00000000..145be9aa --- /dev/null +++ b/SecurityTests/cspxutils/feedvt @@ -0,0 +1,22 @@ +#! /bin/csh -f +# +# run FEE tests for CSP/X. +# +set BUILD_DIR=$LOCAL_BUILD_DIR +# +set CMD_ARGS= +# +while ( $#argv > 0 ) + set CMD_ARGS = "$CMD_ARGS $argv[1]" + shift +end +# +# run thru the known curves +# +./feeCurve $CMD_ARGS k=31 C=m || exit(1) +./feeCurve $CMD_ARGS k=31 C=w || exit(1) +./feeCurve $CMD_ARGS k=127 C=m || exit(1) +./feeCurve $CMD_ARGS k=128 C=w || exit(1) +./feeCurve $CMD_ARGS k=161 C=w || exit(1) +./feeCurve $CMD_ARGS k=161 P=g || exit(1) +./feeCurve $CMD_ARGS k=192 C=w || exit(1) diff --git a/SecurityTests/cspxutils/genErrorStrings/Makefile b/SecurityTests/cspxutils/genErrorStrings/Makefile new file mode 100644 index 00000000..1fbd4479 --- /dev/null +++ b/SecurityTests/cspxutils/genErrorStrings/Makefile @@ -0,0 +1,35 @@ +EXECUTABLE=genErrorStrings +# C++ source (with .cpp extension) +CPSOURCE= genErrorStrings.cpp +# C source (.c extension) +CSOURCE=fileIo.c +OFILES = $(CSOURCE:%.c=%.o) $(CPSOURCE:%.cpp=%.o) + +FRAMEWORKS= +FRAME_SEARCH= +FINCLUDES= +PINCLUDES= +CINCLUDES= $(FINCLUDES) $(PINCLUDES) +WFLAGS= -Wno-four-char-constants -Wno-deprecated-declarations +CFLAGS= -g $(CINCLUDES) $(WFLAGS) $(FRAME_SEARCH) + +# +# This assumes final load with cc, not ld +# +LIBS= -lstdc++ +LIBPATH= +LDFLAGS= $(LIBS) $(LIBPATH) $(FRAME_SEARCH) + +first: $(EXECUTABLE) + +$(EXECUTABLE): $(OFILES) + $(CC) -o $(EXECUTABLE) $(FRAMEWORKS) $(OFILES) $(LDFLAGS) + +clean: + rm -f *.o $(EXECUTABLE) + +.c.o: + $(CC) $(CFLAGS) -c -o $*.o $< + +.cpp.o: + $(CC) $(CFLAGS) -c -o $*.o $< diff --git a/SecurityTests/cspxutils/genErrorStrings/fileIo.c b/SecurityTests/cspxutils/genErrorStrings/fileIo.c new file mode 100644 index 00000000..3f666ac0 --- /dev/null +++ b/SecurityTests/cspxutils/genErrorStrings/fileIo.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include +#include +#include +#include "fileIo.h" + +int writeFile( + const char *fileName, + const unsigned char *bytes, + unsigned numBytes) +{ + int rtn; + int fd; + + fd = open(fileName, O_RDWR | O_CREAT | O_TRUNC, 0600); + if(fd <= 0) { + return errno; + } + rtn = lseek(fd, 0, SEEK_SET); + if(rtn < 0) { + return errno; + } + rtn = write(fd, bytes, (size_t)numBytes); + if(rtn != (int)numBytes) { + if(rtn >= 0) { + printf("writeFile: short write\n"); + } + rtn = EIO; + } + else { + rtn = 0; + } + close(fd); + return rtn; +} + +/* + * Read entire file. + */ +int readFile( + const char *fileName, + unsigned char **bytes, // mallocd and returned + unsigned *numBytes) // returned +{ + int rtn; + int fd; + char *buf; + struct stat sb; + unsigned size; + + *numBytes = 0; + *bytes = NULL; + fd = open(fileName, O_RDONLY, 0); + if(fd <= 0) { + return errno; + } + rtn = fstat(fd, &sb); + if(rtn) { + goto errOut; + } + size = sb.st_size; + buf = (char *)malloc(size); + if(buf == NULL) { + rtn = ENOMEM; + goto errOut; + } + rtn = lseek(fd, 0, SEEK_SET); + if(rtn < 0) { + goto errOut; + } + rtn = read(fd, buf, (size_t)size); + if(rtn != (int)size) { + if(rtn >= 0) { + printf("readFile: short read\n"); + } + rtn = EIO; + } + else { + rtn = 0; + *bytes = (unsigned char *)buf; + *numBytes = size; + } +errOut: + close(fd); + return rtn; +} diff --git a/SecurityTests/cspxutils/genErrorStrings/fileIo.h b/SecurityTests/cspxutils/genErrorStrings/fileIo.h new file mode 100644 index 00000000..4c74ac12 --- /dev/null +++ b/SecurityTests/cspxutils/genErrorStrings/fileIo.h @@ -0,0 +1,20 @@ +/* + * Read entire file. + */ +#ifdef __cplusplus +extern "C" { +#endif + +int readFile( + const char *fileName, + unsigned char **bytes, // mallocd and returned + unsigned *numBytes); // returned + +int writeFile( + const char *fileName, + const unsigned char *bytes, + unsigned numBytes); + +#ifdef __cplusplus +} +#endif diff --git a/SecurityTests/cspxutils/genErrorStrings/genErrorStrings.cpp b/SecurityTests/cspxutils/genErrorStrings/genErrorStrings.cpp new file mode 100644 index 00000000..35e6e8dc --- /dev/null +++ b/SecurityTests/cspxutils/genErrorStrings/genErrorStrings.cpp @@ -0,0 +1,211 @@ +/* + * genErrorStrings.cpp - parse supplied files, generate error table from + * them of the following form: + * + * typedef struct { + * CSSM_RETURN errCode; + * const char *errStr; + * } ErrString; + * + * ErrString errStrings[] = { + * { CSSMERR_CSSM_INTERNAL_ERROR, "CSSMERR_CSSM_INTERNAL_ERROR" }, + * ... + * { CSSMERR_CSP_FUNCTION_FAILED, "CSSMERR_CSP_FUNCTION_FAILED" } + * }; + * + * The error table is written to stdout. + */ + +#include +#include +#include +#include +#include +#include "fileIo.h" + +#define MAX_LINE_LEN 256 + +static void usage(char **argv) +{ + printf("usage: %s inFile [inFile...]\n", argv[0]); + exit(1); +} + +static void writePreamble( + FILE *f) +{ + fprintf(f, "/*\n"); + fprintf(f, " * This file autogenerated by genErrorStrings. Do not edit. \n"); + fprintf(f, " */\n\n"); + fprintf(f, "#include \n\n"); + fprintf(f, "typedef struct {\n"); + fprintf(f, "\tCSSM_RETURN errCode;\n"); + fprintf(f, "\tconst char *errStr;\n"); + fprintf(f, "} ErrString;\n\n"); + fprintf(f, "static const ErrString errStrings[] = {\n"); +} + +static void writePostamble( + FILE *f) +{ + /* generate a null entry as terminator */ + fprintf(f, "\t{0, NULL}\n"); + fprintf(f, "};\n"); +} + +static void writeToken( + const char *token, + FILE *f) +{ + printf("\t{ %s,\"%s\"},\n", token, token); +} + +/* skip whitespace (but not line terminators) */ +static void skipWhite( + const char *&cp, + unsigned &bytesLeft) +{ + while(bytesLeft != 0) { + switch(*cp) { + case ' ': + case '\t': + cp++; + bytesLeft--; + break; + default: + return; + } + } +} + +static void getLine( + const char *&cp, // IN/OUT + unsigned &bytesLeft, // IN/OUT bytes left + char *lineBuf) +{ + char *outp = lineBuf; + char *endOfOut = outp + MAX_LINE_LEN - 2; + while(bytesLeft != 0) { + switch(*cp) { + case '\n': + case '\r': + cp++; + bytesLeft--; + *outp = 0; + return; + default: + *outp++ = *cp++; + bytesLeft--; + break; + } + if(outp == endOfOut) { + printf("***getLine: line length exceeded!\n"); + break; + } + } + /* end of file */ + *outp = 0; +} + +/* incoming line is NULL terminated even if it's empty */ +static bool isLineEmpty( + const char *cp) +{ + for( ; *cp; cp++) { + switch(*cp) { + case ' ': + case '\t': + break; + default: + return false; + } + } + return true; +} + +/* process one file */ +static void processFile( + const char *fileName, + const char *in, + unsigned inLen, + FILE *f) +{ + char lineBuf[MAX_LINE_LEN]; + unsigned lineLen; + const char *cp; + const char *endOfToken; + char tokenBuf[MAX_LINE_LEN]; + unsigned tokenLen; + const char *lastSlash = fileName; + const char *nextSlash; + + while((nextSlash = strchr(lastSlash, '/')) != NULL) { + lastSlash = nextSlash + 1; + } + fprintf(f, "\t/* Error codes from %s */\n", lastSlash); + + while(inLen != 0) { + /* get one line, NULL terminated */ + getLine(in, inLen, lineBuf); + if(isLineEmpty(lineBuf)) { + continue; + } + + /* skip leading whitespace */ + lineLen = strlen(lineBuf); + cp = lineBuf; + skipWhite(cp, lineLen); + + /* interesting? */ + if(strncmp((char *)cp, "CSSMERR_", 8)) { + continue; + } + + /* + * cp is the start of the CSSMERR_ token + * find end of token + */ + endOfToken = cp + 8; + for(;;) { + if(isalnum(*endOfToken) || (*endOfToken == '_')) { + endOfToken++; + continue; + } + else { + break; + } + } + + /* endOfToken is one past the end of the CSSMERR_ token */ + tokenLen = endOfToken - cp; + memmove(tokenBuf, cp, tokenLen); + tokenBuf[tokenLen] = '\0'; + + /* write the stuff */ + writeToken(tokenBuf, f); + } +} + +int main(int argc, char **argv) +{ + unsigned char *inFile; + unsigned inFileLen; + int dex; + + if(argc < 2) { + usage(argv); + } + + writePreamble(stdout); + writeToken("CSSM_OK", stdout); + for(dex=1; dex $DST || exit(1) + +echo "=== Error strings generated in $DST. ===" diff --git a/SecurityTests/cspxutils/genKeyPair/Makefile b/SecurityTests/cspxutils/genKeyPair/Makefile new file mode 100644 index 00000000..6b20de55 --- /dev/null +++ b/SecurityTests/cspxutils/genKeyPair/Makefile @@ -0,0 +1,55 @@ +# name of executable to build +EXECUTABLE=genKeyPair +# C++ source (with .cpp extension) +CPSOURCE= genKeyPair.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +#PROJ_LDFLAGS= -lMallocDebug +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/genKeyPair/genKeyPair.cpp b/SecurityTests/cspxutils/genKeyPair/genKeyPair.cpp new file mode 100644 index 00000000..8d9bba78 --- /dev/null +++ b/SecurityTests/cspxutils/genKeyPair/genKeyPair.cpp @@ -0,0 +1,238 @@ +/* + * genKeyPair.cpp - create a key pair, store in specified keychain + */ +#include +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" + +static void usage(char **argv) +{ + printf("usage: %s keychain [options]\n", argv[0]); + printf("Options:\n"); + printf(" -l label -- no default\n"); + printf(" -a r|f|d -- algorithm RSA/FEE/DSA, default = RSA\n"); + printf(" -k bits -- key size in bits, default is 1024/128/512 for RSA/FEE/DSA\n"); + exit(1); +} + +/* + * Generate key pair of arbitrary algorithm. + * FEE keys will have random private data. + * Like the cspGenKeyPair() in cspwrap.c except this provides a DLDB handle. + */ +static CSSM_RETURN genKeyPair(CSSM_CSP_HANDLE cspHand, + CSSM_DL_DB_HANDLE dlDbHand, + uint32 algorithm, + const char *keyLabel, + unsigned keyLabelLen, + uint32 keySize, // in bits + CSSM_KEY_PTR pubKey, // mallocd by caller + uint32 pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + CSSM_KEY_PTR privKey, // mallocd by caller + uint32 privKeyUsage) // CSSM_KEYUSE_DECRYPT, etc. +{ + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + CSSM_DATA keyLabelData; + uint32 pubAttr; + uint32 privAttr; + CSSM_RETURN ocrtn = CSSM_OK; + + /* pre-context-create algorithm-specific stuff */ + switch(algorithm) { + case CSSM_ALGID_FEE: + if(keySize == CSP_KEY_SIZE_DEFAULT) { + keySize = CSP_FEE_KEY_SIZE_DEFAULT; + } + break; + case CSSM_ALGID_RSA: + if(keySize == CSP_KEY_SIZE_DEFAULT) { + keySize = CSP_RSA_KEY_SIZE_DEFAULT; + } + break; + case CSSM_ALGID_DSA: + if(keySize == CSP_KEY_SIZE_DEFAULT) { + keySize = CSP_DSA_KEY_SIZE_DEFAULT; + } + break; + default: + printf("cspGenKeyPair: Unknown algorithm\n"); + break; + } + keyLabelData.Data = (uint8 *)keyLabel, + keyLabelData.Length = keyLabelLen; + memset(pubKey, 0, sizeof(CSSM_KEY)); + memset(privKey, 0, sizeof(CSSM_KEY)); + + crtn = CSSM_CSP_CreateKeyGenContext(cspHand, + algorithm, + keySize, + NULL, // Seed + NULL, // Salt + NULL, // StartDate + NULL, // EndDate + NULL, // Params + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateKeyGenContext", crtn); + ocrtn = crtn; + goto abort; + } + /* cook up attribute bits */ + pubAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT; + privAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT; + + /* post-context-create algorithm-specific stuff */ + switch(algorithm) { + case CSSM_ALGID_DSA: + /* + * extra step - generate params - this just adds some + * info to the context + */ + { + CSSM_DATA dummy = {0, NULL}; + crtn = CSSM_GenerateAlgorithmParams(ccHand, + keySize, &dummy); + if(crtn) { + printError("CSSM_GenerateAlgorithmParams", crtn); + return crtn; + } + appFreeCssmData(&dummy, CSSM_FALSE); + } + break; + default: + break; + } + + /* add in DL/DB to context */ + crtn = cspAddDlDbToContext(ccHand, dlDbHand.DLHandle, dlDbHand.DBHandle); + if(crtn) { + ocrtn = crtn; + goto abort; + } + + crtn = CSSM_GenerateKeyPair(ccHand, + pubKeyUsage, + pubAttr, + &keyLabelData, + pubKey, + privKeyUsage, + privAttr, + &keyLabelData, // same labels + NULL, // CredAndAclEntry + privKey); + if(crtn) { + printError("CSSM_GenerateKeyPair", crtn); + ocrtn = crtn; + goto abort; + } +abort: + if(ccHand != 0) { + crtn = CSSM_DeleteContext(ccHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; + } + } + return ocrtn; +} + +int main(int argc, char **argv) +{ + char *kcName = NULL; + char *label = NULL; + CSSM_ALGORITHMS keyAlg = CSSM_ALGID_RSA; + unsigned keySizeInBits = CSP_KEY_SIZE_DEFAULT; + + if(argc < 2) { + usage(argv); + } + kcName = argv[1]; + + extern char *optarg; + extern int optind; + + optind = 2; + int arg; + while ((arg = getopt(argc, argv, "l:a:k:h")) != -1) { + switch (arg) { + case 'l': + label = optarg; + break; + case 'a': + switch(optarg[0]) { + case 'r': + keyAlg = CSSM_ALGID_RSA; + break; + case 'f': + keyAlg = CSSM_ALGID_FEE; + break; + case 'd': + keyAlg = CSSM_ALGID_DSA; + break; + default: + usage(argv); + } + break; + case 'k': + keySizeInBits = atoi(optarg); + break; + default: + usage(argv); + } + } + if(optind != argc) { + usage(argv); + } + + SecKeychainRef kcRef = nil; + OSStatus ortn; + + ortn = SecKeychainOpen(kcName, &kcRef); + if(ortn) { + cssmPerror("SecKeychainOpen", ortn); + exit(1); + } + + CSSM_CSP_HANDLE cspHand = 0; + CSSM_DL_DB_HANDLE dlDbHand = {0, 0}; + ortn = SecKeychainGetCSPHandle(kcRef, &cspHand); + if(ortn) { + cssmPerror("SecKeychainGetCSPHandle", ortn); + exit(1); + } + ortn = SecKeychainGetDLDBHandle(kcRef, &dlDbHand); + if(ortn) { + cssmPerror("SecKeychainGetDLDBHandle", ortn); + exit(1); + } + + CSSM_KEY privKey; + CSSM_KEY pubKey; + CSSM_RETURN crtn; + + crtn = genKeyPair(cspHand, dlDbHand, + keyAlg, + label, (label ? strlen(label) : 0), + keySizeInBits, + &pubKey, + CSSM_KEYUSE_ANY, // may want to parameterize + &privKey, + CSSM_KEYUSE_ANY); // may want to parameterize + if(crtn) { + printf("**Error creating key pair.\n"); + } + else { + printf("...key pair created in keychain %s.\n", kcName); + } + + cspFreeKey(cspHand, &privKey); + cspFreeKey(cspHand, &pubKey); + CFRelease(kcRef); + return 0; +} diff --git a/SecurityTests/cspxutils/hashClone/Makefile b/SecurityTests/cspxutils/hashClone/Makefile new file mode 100644 index 00000000..14df35d3 --- /dev/null +++ b/SecurityTests/cspxutils/hashClone/Makefile @@ -0,0 +1,55 @@ +# name of executable to build +EXECUTABLE=hashClone +# C++ source (with .cpp extension) +CPSOURCE= +# C source (.c extension) +CSOURCE= hashClone.c + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +#PROJ_LDFLAGS= -lMallocDebug +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/hashClone/hashClone.c b/SecurityTests/cspxutils/hashClone/hashClone.c new file mode 100644 index 00000000..9a05928a --- /dev/null +++ b/SecurityTests/cspxutils/hashClone/hashClone.c @@ -0,0 +1,354 @@ +/* + * hashClone.c - test CSSM_DigestDataClone function + */ + +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" + +/* + * Defaults + */ +#define LOOPS_DEF 50 +#define MAX_PTEXT (8 * 1024) +#define MIN_PTEXT 16 +#define LOOP_NOTIFY 20 + +/* + * Enumerated algs + */ +typedef unsigned privAlg; +enum { + ALG_MD5 = 1, + ALG_SHA1, + ALG_MD2, + ALG_SHA224, + ALG_SHA256, + ALG_SHA384, + ALG_SHA512 +}; + +#define ALG_FIRST ALG_MD5 +#define ALG_LAST ALG_SHA512 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" a=algorithm (s=SHA1; m=MD5; M=MD2; 4=SHA224; 2=SHA256; 3=SHA384; 5=SHA512; " + "default=all\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +static int doTest(CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS alg, + const char *algStr, + CSSM_DATA_PTR ptext, + CSSM_BOOL verbose, + CSSM_BOOL quiet) +{ + CSSM_CC_HANDLE digHand1 = 0; // reference + CSSM_CC_HANDLE digHand2 = 0; // to be cloned + CSSM_CC_HANDLE digHand3 = 0; // cloned from digHand2 + CSSM_DATA dig1 = {0, NULL}; + CSSM_DATA dig2 = {0, NULL}; + CSSM_DATA dig3 = {0, NULL}; + CSSM_RETURN crtn; + unsigned thisMove; // this update + unsigned toMove; // total to go + unsigned totalRequest; // originally requested + CSSM_DATA thisText; // actually passed to update + + /* cook up two digest contexts */ + crtn = CSSM_CSP_CreateDigestContext(cspHand, + alg, + &digHand1); + if(crtn) { + printError("CSSM_CSP_CreateDigestContext (1)", crtn); + return testError(quiet); + } + crtn = CSSM_CSP_CreateDigestContext(cspHand, + alg, + &digHand2); + if(crtn) { + printError("CSSM_CSP_CreateDigestContext (2)", crtn); + return testError(quiet); + } + crtn = CSSM_DigestDataInit(digHand1); + if(crtn) { + printError("CSSM_DigestDataInit (1)", crtn); + return testError(quiet); + } + crtn = CSSM_DigestDataInit(digHand2); + if(crtn) { + printError("CSSM_DigestDataInit (2)", crtn); + return testError(quiet); + } + + /* do some random updates to first two digests, until we've digested + * at least half of the requested data */ + totalRequest = ptext->Length; + toMove = ptext->Length; + thisText.Data = ptext->Data; + while(toMove > (totalRequest / 2)) { + thisMove = genRand((MIN_PTEXT / 2), toMove); + thisText.Length = thisMove; + if(verbose) { + printf(" ..updating digest1, digest2 with %d bytes\n", thisMove); + } + crtn = CSSM_DigestDataUpdate(digHand1, &thisText, 1); + if(crtn) { + printError("CSSM_DigestDataUpdate (1)", crtn); + return testError(quiet); + } + crtn = CSSM_DigestDataUpdate(digHand2, &thisText, 1); + if(crtn) { + printError("CSSM_DigestDataUpdate (2)", crtn); + return testError(quiet); + } + thisText.Data += thisMove; + toMove -= thisMove; + } + + /* digest3 := clone(digest2) */ + crtn = CSSM_DigestDataClone(digHand2, &digHand3); + if(crtn) { + printError("CSSM_DigestDataClone", crtn); + return testError(quiet); + } + + /* finish off remaining ptext, updating all 3 digests identically */ + while(toMove) { + thisMove = genRand(1, toMove); + thisText.Length = thisMove; + if(verbose) { + printf(" ..updating all three digests with %d bytes\n", thisMove); + } + crtn = CSSM_DigestDataUpdate(digHand1, &thisText, 1); + if(crtn) { + printError("CSSM_DigestDataUpdate (3)", crtn); + return testError(quiet); + } + crtn = CSSM_DigestDataUpdate(digHand2, &thisText, 1); + if(crtn) { + printError("CSSM_DigestDataUpdate (4)", crtn); + return testError(quiet); + } + crtn = CSSM_DigestDataUpdate(digHand3, &thisText, 1); + if(crtn) { + printError("CSSM_DigestDataUpdate (5)", crtn); + return testError(quiet); + } + thisText.Data += thisMove; + toMove -= thisMove; + } + + /* obtain all three digests */ + crtn = CSSM_DigestDataFinal(digHand1, &dig1); + if(crtn) { + printError("CSSM_DigestDataFinal (1)", crtn); + return testError(quiet); + } + crtn = CSSM_DigestDataFinal(digHand2, &dig2); + if(crtn) { + printError("CSSM_DigestDataFinal (2)", crtn); + return testError(quiet); + } + crtn = CSSM_DigestDataFinal(digHand3, &dig3); + if(crtn) { + printError("CSSM_DigestDataFinal (3)", crtn); + return testError(quiet); + } + + /* ensure all three digests identical */ + if(!appCompareCssmData(&dig1, &dig2)) { + printf("***Digest miscompare(dig1, dig2)***\n"); + if(testError(quiet)) { + return 1; + } + } + if(!appCompareCssmData(&dig2, &dig3)) { + printf("***Digest miscompare(dig2, dig3)***\n"); + if(testError(quiet)) { + return 1; + } + } + + /* free resources */ + appFreeCssmData(&dig1, CSSM_FALSE); + appFreeCssmData(&dig2, CSSM_FALSE); + appFreeCssmData(&dig3, CSSM_FALSE); + CSSM_DeleteContext(digHand1); + CSSM_DeleteContext(digHand2); + CSSM_DeleteContext(digHand3); + return 0; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + CSSM_DATA ptext; + CSSM_CSP_HANDLE cspHand; + const char *algStr; + privAlg alg; // ALG_MD5, etc. + CSSM_ALGORITHMS cssmAlg; // CSSM_ALGID_MD5, etc. + int j; + + /* + * User-spec'd params + */ + unsigned loops = LOOPS_DEF; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + unsigned minAlg = ALG_FIRST; + unsigned maxAlg = ALG_LAST; + unsigned pauseInterval = 0; + CSSM_BOOL bareCsp = CSSM_TRUE; + + for(arg=1; arg +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "bsafeUtils.h" +#include + +/* + * Defaults. + */ +#define LOOPS_DEF 200 +#define MIN_EXP 2 /* for data size 10**exp */ +#define DEFAULT_MAX_EXP 4 +#define MAX_EXP 5 + +#define MAX_DATA_SIZE (100000 + 100) /* bytes */ +#define LOOP_NOTIFY 20 + +/* + * Enumerate algs our own way to allow iteration. + */ +enum { + ALG_SHA1 = 1, + ALG_MD5, + ALG_MD2 +}; + +#define ALG_FIRST ALG_SHA1 +#define ALG_LAST ALG_MD2 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" a=algorithm (s=SHA1; 5=MD5; 2=MD2; default=all\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" n=minExp (default=%d)\n", MIN_EXP); + printf(" x=maxExp (default=%d, max=%d)\n", DEFAULT_MAX_EXP, MAX_EXP); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +/* + * generate digest using reference BSAFE. + */ +static CSSM_RETURN genDigestBSAFE( + CSSM_ALGORITHMS hashAlg, + const CSSM_DATA *inText, + CSSM_DATA_PTR outText) // mallocd and returned +{ + CSSM_RETURN crtn; + + crtn = buGenDigest(hashAlg, + inText, + outText); + return crtn; +} + +/* + * Generate digest using CSP. + */ +static CSSM_RETURN genDigestCSSM( + CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS hashAlg, + const CSSM_DATA *inText, + CSSM_DATA_PTR outText) // mallocd and returned if doGen +{ + + outText->Data = NULL; + outText->Length = 0; + return cspStagedDigest(cspHand, + hashAlg, + CSSM_TRUE, // mallocDigest + CSSM_TRUE, // multiUpdates + inText, + outText); +} + +#define LOG_FREQ 20 + +static int doTest(CSSM_CSP_HANDLE cspHand, + const CSSM_DATA *ptext, + uint32 hashAlg, + CSSM_BOOL quiet) +{ + CSSM_DATA hashRef = {0, NULL}; // digest, BSAFE reference + CSSM_DATA hashTest = {0, NULL}; // digest, CSP test + int rtn = 0; + CSSM_RETURN crtn; + + /* + * generate with each method; + * verify digests compare; + */ + crtn = genDigestBSAFE(hashAlg, + ptext, + &hashRef); + if(crtn) { + return testError(quiet); + } + crtn = genDigestCSSM(cspHand, + hashAlg, + ptext, + &hashTest); + if(crtn) { + return testError(quiet); + } + + /* ensure both methods resulted in same hash */ + if(hashRef.Length != hashTest.Length) { + printf("hash length mismatch (1)\n"); + rtn = testError(quiet); + if(rtn) { + goto abort; + } + } + if(memcmp(hashRef.Data, hashTest.Data, hashTest.Length)) { + printf("hash miscompare\n"); + rtn = testError(quiet); + } + else { + rtn = 0; + } +abort: + if(hashTest.Length) { + CSSM_FREE(hashTest.Data); + } + if(hashRef.Length) { + CSSM_FREE(hashRef.Data); + } + return rtn; +} + + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + CSSM_DATA ptext; + CSSM_CSP_HANDLE cspHand; + const char *algStr; + uint32 hashAlg; // CSSM_ALGID_xxx + int i; + unsigned currAlg; // ALG_xxx + int rtn = 0; + + /* + * User-spec'd params + */ + unsigned minAlg = ALG_FIRST; + unsigned maxAlg = ALG_LAST; + unsigned loops = LOOPS_DEF; + CSSM_BOOL verbose = CSSM_FALSE; + unsigned minExp = MIN_EXP; + unsigned maxExp = DEFAULT_MAX_EXP; + CSSM_BOOL quiet = CSSM_FALSE; + unsigned pauseInterval = 0; + CSSM_BOOL bareCsp = CSSM_TRUE; + + + for(arg=1; arg MAX_EXP) { + usage(argv); + } + break; + case 'v': + verbose = CSSM_TRUE; + break; + case 'D': + bareCsp = CSSM_FALSE; + break; + case 'q': + quiet = CSSM_TRUE; + break; + case 'p': + pauseInterval = atoi(&argp[2]);; + break; + case 'h': + default: + usage(argv); + } + } + if(minExp > maxExp) { + printf("***minExp must be <= maxExp\n"); + usage(argv); + } + ptext.Data = (uint8 *)CSSM_MALLOC(MAX_DATA_SIZE); + if(ptext.Data == NULL) { + printf("Insufficient heap space\n"); + exit(1); + } + /* ptext length set in test loop */ + + printf("Starting hashCompat; args: "); + for(i=1; i +#include +#include +#include +#include +#include "cspwrap.h" +#include +#include +#include "cspwrap.h" +#include "common.h" + +/* + * Defaults. + */ +#define LOOPS_DEF 50 +#define MIN_EXP 2 /* for data size 10**exp */ +#define DEFAULT_MAX_EXP 3 +#define MAX_EXP 5 +#define INCR_DEFAULT 0 /* munge every incr bytes - zero means + * "adjust per ptext size" */ +typedef enum { + ALG_MD2 = 1, + ALG_MD5, + ALG_SHA1, + ALG_SHA224, + ALG_SHA256, + ALG_SHA384, + ALG_SHA512 +}; + +#define ALG_FIRST ALG_MD2 +#define ALG_LAST ALG_SHA512 +#define MAX_DATA_SIZE (100000 + 100) /* bytes */ +#define LOOP_NOTIFY 20 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" a=algorithm (s=SHA1; m=MD5; M=MD2; 4=SHA224; 2=SHA256; 3=SHA384; 5=SHA512; " + "default=all\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" n=minExp (default=%d)\n", MIN_EXP); + printf(" x=maxExp (default=%d, max=%d)\n", DEFAULT_MAX_EXP, MAX_EXP); + printf(" i=increment (default=%d)\n", INCR_DEFAULT); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" z (zero data)\n"); + printf(" I (incrementing data)\n"); + printf(" g (good digest only)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +#define LOG_FREQ 20 + +static int doTest(CSSM_CSP_HANDLE cspHand, + uint32 alg, + CSSM_DATA_PTR ptext, + CSSM_BOOL verbose, + CSSM_BOOL quiet, + CSSM_BOOL mallocDigest, + unsigned incr, + CSSM_BOOL goodOnly) +{ + CSSM_DATA refDigest = {0, NULL}; + CSSM_DATA testDigest = {0, NULL}; + unsigned length; + unsigned byte; + unsigned char *data; + unsigned char origData; + unsigned char bits; + int rtn = 0; + CSSM_RETURN crtn; + unsigned loop = 0; + + /* + * generate digest in one shot; + * generate digest with multiple random-sized updates; + * verify digests compare; + * for various bytes of ptext { + * corrupt ptext byte; + * generate digest in one shot; + * verify digest is different; + * restore corrupted byte; + * } + */ + crtn = cspDigest(cspHand, + alg, + mallocDigest, + ptext, + &refDigest); + if(crtn) { + rtn = testError(quiet); + goto abort; + } + crtn = cspStagedDigest(cspHand, + alg, + mallocDigest, + CSSM_TRUE, // multi updates + ptext, + &testDigest); + if(crtn) { + rtn = testError(quiet); + goto abort; + } + if(refDigest.Length != testDigest.Length) { + printf("Digest length mismatch (1)\n"); + rtn = testError(quiet); + goto abort; + } + if(memcmp(refDigest.Data, testDigest.Data, refDigest.Length)) { + printf("Digest miscompare (1)\n"); + rtn = testError(quiet); + if(rtn) { + goto abort; + } + } + if(goodOnly) { + rtn = 0; + goto abort; + } + appFreeCssmData(&testDigest, CSSM_FALSE); + testDigest.Length = 0; + data = (unsigned char *)ptext->Data; + length = ptext->Length; + for(byte=0; byte MAX_EXP) { + usage(argv); + } + break; + case 'i': + incr = atoi(&argp[2]); + break; + case 'p': + pauseInterval = atoi(&argp[2]);; + break; + case 'v': + verbose = CSSM_TRUE; + break; + case 'q': + quiet = CSSM_TRUE; + break; + case 'D': + bareCsp = CSSM_FALSE; + break; + case 'z': + dt = DT_Zero; + break; + case 'I': + dt = DT_Increment; + break; + case 'g': + goodOnly = CSSM_TRUE; + break; + case 'h': + default: + usage(argv); + } + } + ptext.Data = (uint8 *)CSSM_MALLOC(MAX_DATA_SIZE); + /* length set in test loop */ + if(ptext.Data == NULL) { + printf("Insufficient heap\n"); + exit(1); + } + + printf("Starting hashTest; args: "); + for(i=1; i 10/06/98 ap Changed to compile with C++. + + To Do: +*/ + +/* Copyright (c) 1998,2004-2005 Apple Computer, Inc. All Rights Reserved. + * + * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT + * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL + * EXPOSE YOU TO LIABILITY. + *************************************************************************** + * + * MD5.c + */ + +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +/* + * Revision History + * ---------------- + * 06 Feb 1997 Doug Mitchell at Apple + * Fixed endian-dependent cast in MD5Final() + * Made byteReverse() tolerant of platform-dependent alignment + * restrictions + */ + +#include "MD5.h" +#undef __LITTLE_ENDIAN__ +#undef __BIG_ENDIAN__ +#define __BIG_ENDIAN__ + +#include +#include + +static inline void intToByteRep(int i, unsigned char *buf) +{ + *buf++ = (unsigned char)((i >> 24) & 0xff); + *buf++ = (unsigned char)((i >> 16) & 0xff); + *buf++ = (unsigned char)((i >> 8) & 0xff); + *buf = (unsigned char)(i & 0xff); +} + +#define MD5_DEBUG 0 + +#if MD5_DEBUG +static inline void dumpCtx(struct MD5Context *ctx, char *label) +{ + int i; + + printf("%s\n", label); + printf("buf = "); + for(i=0; i<4; i++) { + printf("%x:", ctx->buf[i]); + } + printf("\nbits: %d:%d\n", ctx->bits[0], ctx->bits[1]); + printf("in[]:\n "); + for(i=0; i<64; i++) { + printf("%02x:", ctx->in[i]); + if((i % 16) == 15) { + printf("\n "); + } + } + printf("\n"); +} +#else // MD5_DEBUG +#define dumpCtx(ctx, label) +#endif // MD5_DEBUG + +static void MD5Transform(uint32 buf[4], uint32 const in[16]); + +#ifdef __LITTLE_ENDIAN__ +#define byteReverse(buf, len) /* Nothing */ +#else +static void byteReverse(unsigned char *buf, unsigned longs); + +#ifndef ASM_MD5 +/* + * Note: this code is harmless on little-endian machines. + */ +static void byteReverse(unsigned char *buf, unsigned longs) +{ +#if old_way + /* + * this code is NOT harmless on big-endian machine which require + * natural alignment. + */ + uint32 t; + do { + t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(uint32 *) buf = t; + buf += 4; + } while (--longs); +#else // new_way + + unsigned char t; + do { + t = buf[0]; + buf[0] = buf[3]; + buf[3] = t; + t = buf[1]; + buf[1] = buf[2]; + buf[2] = t; + buf += 4; + } while (--longs); +#endif // old_way +} +#endif // ASM_MD5 +#endif // __LITTLE_ENDIAN__ + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void MD5Init(struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) +{ + uint32 t; + + dumpCtx(ctx, "MD5.c update top"); + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + dumpCtx(ctx, "update - return from transform (1)"); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + dumpCtx(ctx, "update - return from transform (2)"); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void MD5Final(struct MD5Context *ctx, unsigned char *digest) +{ + unsigned count; + unsigned char *p; + + dumpCtx(ctx, "final top"); + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + #if MD5_DEBUG + printf("in[%d] = %x\n", count, ctx->in[count]); + #endif + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + dumpCtx(ctx, "final, before pad"); + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + bzero(p, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + bzero(ctx->in, 56); + } else { + /* Pad block to 56 bytes */ + bzero(p, count - 8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + #ifdef __LITTLE_ENDIAN__ + /* l.s. byte of bits[0] --> in[56] */ + ((uint32 *) ctx->in)[14] = ctx->bits[0]; + ((uint32 *) ctx->in)[15] = ctx->bits[1]; + #else + /* l.s. byte of bits[0] --> in[60] */ + intToByteRep(ctx->bits[0], &ctx->in[56]); + intToByteRep(ctx->bits[1], &ctx->in[60]); + #endif + + dumpCtx(ctx, "last transform"); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + memcpy(digest, ctx->buf, MD5_DIGEST_SIZE); + dumpCtx(ctx, "final end"); + + bzero(ctx, sizeof(*ctx)); /* In case it's sensitive */ +} + +#ifndef ASM_MD5 + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void MD5Transform(uint32 buf[4], uint32 const in[16]) +{ + register uint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#endif // ASM_MD5 diff --git a/SecurityTests/cspxutils/hashTime/MD5.h b/SecurityTests/cspxutils/hashTime/MD5.h new file mode 100644 index 00000000..29e17df1 --- /dev/null +++ b/SecurityTests/cspxutils/hashTime/MD5.h @@ -0,0 +1,63 @@ +/* + File: MD5.h + + Written by: Colin Plumb + + Copyright: Copyright (c) 1998,2004 Apple Computer, Inc. All Rights Reserved. + + Change History (most recent first): + + <8> 10/06/98 ap Changed to compile with C++. + + To Do: +*/ + +/* Copyright (c) 1998,2004 Apple Computer, Inc. All Rights Reserved. + * + * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT + * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL + * EXPOSE YOU TO LIABILITY. + *************************************************************************** + * + * MD5.h + * derived and used without need for permission from public domain source + */ + +#ifndef _CK_MD5_H_ +#define _CK_MD5_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __alpha +typedef unsigned int uint32; +#elif defined (macintosh) +typedef unsigned int uint32; +#else +#include +//typedef unsigned long uint32; +#endif + +struct MD5Context { + uint32 buf[4]; + uint32 bits[2]; // bits[0] is low 32 bits of bit count + unsigned char in[64]; +}; + +#define MD5_DIGEST_SIZE 16 /* in bytes */ +#define MD5_BLOCK_SIZE 64 /* in bytes */ + +void MD5Init(struct MD5Context *context); +void MD5Update(struct MD5Context *context, unsigned char const *buf, + unsigned len); +void MD5Final(struct MD5Context *context, unsigned char *digest); + +#ifdef __cplusplus +} +#endif + +#endif /*_CK_MD5_H_*/ diff --git a/SecurityTests/cspxutils/hashTime/Makefile b/SecurityTests/cspxutils/hashTime/Makefile new file mode 100644 index 00000000..618a7c95 --- /dev/null +++ b/SecurityTests/cspxutils/hashTime/Makefile @@ -0,0 +1,56 @@ +# name of executable to build +EXECUTABLE=hashTime +# C++ source (with .cpp extension) +CPSOURCE=hashTime.cpp +# C source (.c extension) +CSOURCE= MD5.c SHA1_priv.c SHA1.c + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= -lcrypto +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +# temp for old cputime +PROJ_FRAMEWORKS=-framework IOKit + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES=-I$(LOCAL_BUILD)/include + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS=-Os + +# +# Optional link flags (using cc, not ld) +# +#PROJ_LDFLAGS= -lMallocDebug +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/hashTime/SHA1.c b/SecurityTests/cspxutils/hashTime/SHA1.c new file mode 100644 index 00000000..89844dce --- /dev/null +++ b/SecurityTests/cspxutils/hashTime/SHA1.c @@ -0,0 +1,176 @@ +/* Copyright (c) 1998,2004 Apple Computer, Inc. All Rights Reserved. + * + * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT + * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL + * EXPOSE YOU TO LIABILITY. + *************************************************************************** + * + * SHA1.c - generic, portable SHA-1 hash object + * + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 07 Jan 1998 Doug Mitchell at Apple + * Created. + */ + +#include "SHA1.h" +#include "SHA1_priv.h" +#include + +/* for now map falloc to malloc, FIXME */ +#include +#define fmalloc(s) malloc(s) +#define ffree(p) free(p) + +/* + * Private data for this object. A sha1Obj handle is cast to a pointer + * to one of these. + */ +typedef struct { + SHS_INFO context; + int isDone; + + /* + * For storing partial blocks + */ + BYTE dataBuf[SHS_BLOCKSIZE]; + unsigned bufBytes; // valid bytes in dataBuf[p] +} sha1Inst; + +/* + * Alloc and init an empty sha1 object. + */ +sha1Obj sha1Alloc(void) +{ + sha1Inst *sinst; + + sinst = (sha1Inst *)fmalloc(sizeof(sha1Inst)); + if(sinst == NULL) { + return NULL; + } + shsInit(&sinst->context); + sha1Reinit((sha1Obj)sinst); + return (sha1Obj)sinst; +} + +/* + * Reusable init function. + */ +void sha1Reinit(sha1Obj sha1) +{ + sha1Inst *sinst = (sha1Inst *) sha1; + + shsInit(&sinst->context); + sinst->isDone = 0; + sinst->bufBytes = 0; +} + +/* + * Free an sha1 object. + */ +void sha1Free(sha1Obj sha1) +{ + sha1Inst *sinst = (sha1Inst *) sha1; + + memset(sha1, 0, sizeof(sha1Inst)); + ffree(sinst); +} + +/* + * Add some data to the sha1 object. + */ +void sha1AddData(sha1Obj sha1, + const unsigned char *data, + unsigned dataLen) +{ + sha1Inst *sinst = (sha1Inst *) sha1; + unsigned toMove; + unsigned blocks; + + if(sinst->isDone) { + /* + * Log some kind of error here... + */ + return; + } + + /* + * First deal with partial buffered block + */ + if(sinst->bufBytes != 0) { + toMove = SHS_BLOCKSIZE - sinst->bufBytes; + if(toMove > dataLen) { + toMove = dataLen; + } + memmove(sinst->dataBuf+sinst->bufBytes, data, toMove); + data += toMove; + dataLen -= toMove; + sinst->bufBytes += toMove; + if(sinst->bufBytes == SHS_BLOCKSIZE) { + shsUpdate(&sinst->context, sinst->dataBuf, SHS_BLOCKSIZE); + sinst->bufBytes = 0; + } + } + + /* + * Now the bulk of the data, in a multiple of full blocks + */ + blocks = dataLen / SHS_BLOCKSIZE; + toMove = blocks * SHS_BLOCKSIZE; + if(toMove != 0) { + shsUpdate(&sinst->context, data, toMove); + data += toMove; + dataLen -= toMove; + } + + /* + * Store any remainder in dataBuf + */ + if(dataLen != 0) { + memmove(sinst->dataBuf, data, dataLen); + sinst->bufBytes = dataLen; + } +} + +/* + * Obtain a pointer to completed message digest, and the length of the digest. + */ +unsigned char *sha1Digest(sha1Obj sha1) +{ + sha1Inst *sinst = (sha1Inst *) sha1; + + if(!sinst->isDone) { + /* + * Deal with partial resid block + */ + if(sinst->bufBytes != 0) { + shsUpdate(&sinst->context, sinst->dataBuf, + sinst->bufBytes); + sinst->bufBytes = 0; + } + shsFinal(&sinst->context); + sinst->isDone = 1; + } + /* + * FIXME - should do explicit conversion to char array....? + */ + return (unsigned char *)sinst->context.digest; +} + +/* As above, with copy. */ +void sha1GetDigest(sha1Obj sha1, + unsigned char *digest) +{ + unsigned char *dig = sha1Digest(sha1); + memmove(digest, dig, SHS_DIGESTSIZE); +} + +unsigned sha1DigestLen(void) +{ + return SHS_DIGESTSIZE; +} diff --git a/SecurityTests/cspxutils/hashTime/SHA1.h b/SecurityTests/cspxutils/hashTime/SHA1.h new file mode 100644 index 00000000..8a8a04de --- /dev/null +++ b/SecurityTests/cspxutils/hashTime/SHA1.h @@ -0,0 +1,76 @@ +/* Copyright (c) 1998,2004 Apple Computer, Inc. All Rights Reserved. + * + * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT + * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL + * EXPOSE YOU TO LIABILITY. + *************************************************************************** + * + * SHA1.h - generic, portable SHA-1 hash object + * + * Revision History + * ---------------- + * 05 Jan 1998 Doug Mitchell at Apple + * Created. + */ + +#ifndef _CK_SHA1_H_ +#define _CK_SHA1_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SHA1_DIGEST_SIZE 20 /* in bytes */ +#define SHA1_BLOCK_SIZE 64 /* in bytes */ + +/* + * Opaque sha1 object handle. + */ +typedef void *sha1Obj; + +/* + * Alloc and init an empty sha1 object. + */ +sha1Obj sha1Alloc(void); + +/* + * reinitialize an sha1 object for reuse. + */ +void sha1Reinit(sha1Obj sha1); + +/* + * Free an sha1 object. + */ +void sha1Free(sha1Obj sha1); + +/* + * Add some data to the sha1 object. + */ +void sha1AddData(sha1Obj sha1, + const unsigned char *data, + unsigned dataLen); + +/* + * Obtain a pointer to completed message digest. This disables further calls + * to sha1AddData(). This pointer is NOT malloc'd; the associated data + * persists only as long as this object does. + */ +unsigned char *sha1Digest(sha1Obj sha1); + +/* As above, with copy. */ +void sha1GetDigest(sha1Obj sha1, + unsigned char *digest); + +/* + * Obtain the length of the message digest. + */ +unsigned sha1DigestLen(void); + +#ifdef __cplusplus +} +#endif + +#endif /*_CK_SHA1_H_*/ diff --git a/SecurityTests/cspxutils/hashTime/SHA1_priv.c b/SecurityTests/cspxutils/hashTime/SHA1_priv.c new file mode 100644 index 00000000..75a55367 --- /dev/null +++ b/SecurityTests/cspxutils/hashTime/SHA1_priv.c @@ -0,0 +1,311 @@ +/* Copyright (c) 1998,2004-2005 Apple Computer, Inc. All Rights Reserved. + * + * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT + * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL + * EXPOSE YOU TO LIABILITY. + *************************************************************************** + * + * SHA1_priv.c - low-level SHA-1 hash algorithm. + * + * Revision History + * ---------------- + * 05 Jan 1998 Doug Mitchell at Apple + * Created, based on source by Peter C. Gutmann. + * Mods: made reentrant, added NIST fix to expand(), eliminated + * unnecessary copy to local W[] array. + */ + + +/* NIST proposed Secure Hash Standard. + + Written 2 September 1992, Peter C. Gutmann. + This implementation placed in the public domain. + + Comments to pgut1@cs.aukuni.ac.nz */ + + +#include "SHA1_priv.h" +#include + +/* The SHS f()-functions */ + +#define f1(x,y,z) ( ( x & y ) | ( ~x & z ) ) /* Rounds 0-19 */ +#define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ +#define f3(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) ) /* Rounds 40-59 */ +#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ + +/* The SHS Mysterious Constants */ + +#define K1 0x5A827999L /* Rounds 0-19 */ +#define K2 0x6ED9EBA1L /* Rounds 20-39 */ +#define K3 0x8F1BBCDCL /* Rounds 40-59 */ +#define K4 0xCA62C1D6L /* Rounds 60-79 */ + +/* SHS initial values */ + +#define h0init 0x67452301L +#define h1init 0xEFCDAB89L +#define h2init 0x98BADCFEL +#define h3init 0x10325476L +#define h4init 0xC3D2E1F0L + +/* 32-bit rotate - kludged with shifts */ + +#define S(n,X) ( ( X << n ) | ( X >> ( 32 - n ) ) ) + +/* The initial expanding function */ + +/* + * 06 Jan 1998. Added left circular shift per NIST FIPS-180-1 (at + * http://www.nist.gov/itl/div897/pubs/fip180-1.htm). Also see + * B. Schneier, Applied Cryptography, Second Edition, section 18.7 + * for info on this addenda to the original NIST spec. + */ +#define expand(count) { \ + W[count] = W[count - 3] ^ W[count - 8] ^ W[count - 14] ^ W[count - 16]; \ + W[count] = S(1, W[count]); \ +} + +/* The four SHS sub-rounds */ + +#define subRound1(count) \ + { \ + temp = S( 5, A ) + f1( B, C, D ) + E + W[ count ] + K1; \ + E = D; \ + D = C; \ + C = S( 30, B ); \ + B = A; \ + A = temp; \ + } + +#define subRound2(count) \ + { \ + temp = S( 5, A ) + f2( B, C, D ) + E + W[ count ] + K2; \ + E = D; \ + D = C; \ + C = S( 30, B ); \ + B = A; \ + A = temp; \ + } + +#define subRound3(count) \ + { \ + temp = S( 5, A ) + f3( B, C, D ) + E + W[ count ] + K3; \ + E = D; \ + D = C; \ + C = S( 30, B ); \ + B = A; \ + A = temp; \ + } + +#define subRound4(count) \ + { \ + temp = S( 5, A ) + f4( B, C, D ) + E + W[ count ] + K4; \ + E = D; \ + D = C; \ + C = S( 30, B ); \ + B = A; \ + A = temp; \ + } + +/* Initialize the SHS values */ + +void shsInit( SHS_INFO *shsInfo ) + { + /* Set the h-vars to their initial values */ + shsInfo->digest[ 0 ] = h0init; + shsInfo->digest[ 1 ] = h1init; + shsInfo->digest[ 2 ] = h2init; + shsInfo->digest[ 3 ] = h3init; + shsInfo->digest[ 4 ] = h4init; + + /* Initialise bit count */ + shsInfo->countLo = shsInfo->countHi = 0L; + } + +/* Perform the SHS transformation. Note that this code, like MD5, seems to + break some optimizing compilers - it may be necessary to split it into + sections, eg based on the four subrounds */ + +static void shsTransform( SHS_INFO *shsInfo ) +{ + LONG *W, temp; + LONG A, B, C, D, E; + + /* Step A. Copy the data buffer into the local work buffer. */ + /* 07 Jan 1998, dmitch: skip this bogus move, and let the caller + * copy data directly into the W[] array. To minimize changes, + * we'll just increase the size of shsInfo->data[] and make W + * a pointer here. + */ + W = shsInfo->data; + + /* Step B. Expand the 16 words into 64 temporary data words */ + + /* + * Note: I tried optimizing this via a for loop, and for some reason, + * the "optimized" version ran slower on PPC than the original + * unrolled version. The optimized version does run faster on i486 than + * the unrolled version. + * + * Similarly, the set of subRounds, below, runs slower on i486 when + * optimized via 4 'for' loops. The "optimized" version of that is + * a wash on PPC. + * + * Conclusion: leave both of 'em unrolled. We could ifdef per machine, + * but this would get messy once we had more than two architectures. + * We may want to revisit this. --dpm + */ + expand( 16 ); expand( 17 ); expand( 18 ); expand( 19 ); expand( 20 ); + expand( 21 ); expand( 22 ); expand( 23 ); expand( 24 ); expand( 25 ); + expand( 26 ); expand( 27 ); expand( 28 ); expand( 29 ); expand( 30 ); + expand( 31 ); expand( 32 ); expand( 33 ); expand( 34 ); expand( 35 ); + expand( 36 ); expand( 37 ); expand( 38 ); expand( 39 ); expand( 40 ); + expand( 41 ); expand( 42 ); expand( 43 ); expand( 44 ); expand( 45 ); + expand( 46 ); expand( 47 ); expand( 48 ); expand( 49 ); expand( 50 ); + expand( 51 ); expand( 52 ); expand( 53 ); expand( 54 ); expand( 55 ); + expand( 56 ); expand( 57 ); expand( 58 ); expand( 59 ); expand( 60 ); + expand( 61 ); expand( 62 ); expand( 63 ); expand( 64 ); expand( 65 ); + expand( 66 ); expand( 67 ); expand( 68 ); expand( 69 ); expand( 70 ); + expand( 71 ); expand( 72 ); expand( 73 ); expand( 74 ); expand( 75 ); + expand( 76 ); expand( 77 ); expand( 78 ); expand( 79 ); + + /* Step C. Set up first buffer */ + A = shsInfo->digest[ 0 ]; + B = shsInfo->digest[ 1 ]; + C = shsInfo->digest[ 2 ]; + D = shsInfo->digest[ 3 ]; + E = shsInfo->digest[ 4 ]; + + /* Step D. Serious mangling, divided into four sub-rounds */ + subRound1( 0 ); subRound1( 1 ); subRound1( 2 ); subRound1( 3 ); + subRound1( 4 ); subRound1( 5 ); subRound1( 6 ); subRound1( 7 ); + subRound1( 8 ); subRound1( 9 ); subRound1( 10 ); subRound1( 11 ); + subRound1( 12 ); subRound1( 13 ); subRound1( 14 ); subRound1( 15 ); + subRound1( 16 ); subRound1( 17 ); subRound1( 18 ); subRound1( 19 ); + subRound2( 20 ); subRound2( 21 ); subRound2( 22 ); subRound2( 23 ); + subRound2( 24 ); subRound2( 25 ); subRound2( 26 ); subRound2( 27 ); + subRound2( 28 ); subRound2( 29 ); subRound2( 30 ); subRound2( 31 ); + subRound2( 32 ); subRound2( 33 ); subRound2( 34 ); subRound2( 35 ); + subRound2( 36 ); subRound2( 37 ); subRound2( 38 ); subRound2( 39 ); + subRound3( 40 ); subRound3( 41 ); subRound3( 42 ); subRound3( 43 ); + subRound3( 44 ); subRound3( 45 ); subRound3( 46 ); subRound3( 47 ); + subRound3( 48 ); subRound3( 49 ); subRound3( 50 ); subRound3( 51 ); + subRound3( 52 ); subRound3( 53 ); subRound3( 54 ); subRound3( 55 ); + subRound3( 56 ); subRound3( 57 ); subRound3( 58 ); subRound3( 59 ); + subRound4( 60 ); subRound4( 61 ); subRound4( 62 ); subRound4( 63 ); + subRound4( 64 ); subRound4( 65 ); subRound4( 66 ); subRound4( 67 ); + subRound4( 68 ); subRound4( 69 ); subRound4( 70 ); subRound4( 71 ); + subRound4( 72 ); subRound4( 73 ); subRound4( 74 ); subRound4( 75 ); + subRound4( 76 ); subRound4( 77 ); subRound4( 78 ); subRound4( 79 ); + + /* Step E. Build message digest */ + shsInfo->digest[ 0 ] += A; + shsInfo->digest[ 1 ] += B; + shsInfo->digest[ 2 ] += C; + shsInfo->digest[ 3 ] += D; + shsInfo->digest[ 4 ] += E; +} + +#ifdef __LITTLE_ENDIAN__ + +/* When run on a little-endian CPU we need to perform byte reversal on an + array of longwords. It is possible to make the code endianness- + independant by fiddling around with data at the byte level, but this + makes for very slow code, so we rely on the user to sort out endianness + at compile time */ + +static void byteReverse( LONG *buffer, int byteCount ) + + { + LONG value; + int count; + + byteCount /= sizeof( LONG ); + for( count = 0; count < byteCount; count++ ) + { + value = ( buffer[ count ] << 16 ) | ( buffer[ count ] >> 16 ); + buffer[ count ] = ( ( value & 0xFF00FF00L ) >> 8 ) | ( ( value & 0x00FF00FFL ) << 8 ); + } + } + +#else /* __LITTLE_ENDIAN__ */ + +/* + * Nop for big-endian machines + */ +#define byteReverse( buffer, byteCount ) + +#endif /* __LITTLE_ENDIAN__ */ + + +/* Update SHS for a block of data. This code assumes that the buffer size + is a multiple of SHS_BLOCKSIZE bytes long, which makes the code a lot + more efficient since it does away with the need to handle partial blocks + between calls to shsUpdate() */ + +void shsUpdate( + SHS_INFO *shsInfo, + const BYTE *buffer, + int count) + + { + /* Update bitcount */ + if( ( shsInfo->countLo + ( ( LONG ) count << 3 ) ) < shsInfo->countLo ) + shsInfo->countHi++; /* Carry from low to high bitCount */ + shsInfo->countLo += ( ( LONG ) count << 3 ); + shsInfo->countHi += ( ( LONG ) count >> 29 ); + + /* Process data in SHS_BLOCKSIZE chunks */ + while( count >= SHS_BLOCKSIZE ) + { + memcpy( shsInfo->data, buffer, SHS_BLOCKSIZE ); + byteReverse( shsInfo->data, SHS_BLOCKSIZE ); + shsTransform( shsInfo ); + buffer += SHS_BLOCKSIZE; + count -= SHS_BLOCKSIZE; + } + + /* Handle any remaining bytes of data. This should only happen once + on the final lot of data */ + memcpy( shsInfo->data, buffer, count ); + } + +void shsFinal(SHS_INFO *shsInfo) + { + int count; + LONG lowBitcount = shsInfo->countLo, highBitcount = shsInfo->countHi; + + /* Compute number of bytes mod 64 */ + count = ( int ) ( ( shsInfo->countLo >> 3 ) & 0x3F ); + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + ( ( BYTE * ) shsInfo->data )[ count++ ] = 0x80; + + /* Pad out to 56 mod 64 */ + if( count > 56 ) + { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset( ( BYTE * ) &shsInfo->data + count, 0, 64 - count ); + byteReverse( shsInfo->data, SHS_BLOCKSIZE ); + shsTransform( shsInfo ); + + /* Now fill the next block with 56 bytes */ + memset( &shsInfo->data, 0, 56 ); + } + else + /* Pad block to 56 bytes */ + memset( ( BYTE * ) &shsInfo->data + count, 0, 56 - count ); + byteReverse( shsInfo->data, SHS_BLOCKSIZE ); + + /* Append length in bits and transform */ + shsInfo->data[ 14 ] = highBitcount; + shsInfo->data[ 15 ] = lowBitcount; + + shsTransform( shsInfo ); + byteReverse( shsInfo->digest, SHS_DIGESTSIZE ); + } diff --git a/SecurityTests/cspxutils/hashTime/SHA1_priv.h b/SecurityTests/cspxutils/hashTime/SHA1_priv.h new file mode 100644 index 00000000..b208044d --- /dev/null +++ b/SecurityTests/cspxutils/hashTime/SHA1_priv.h @@ -0,0 +1,54 @@ +/* Copyright (c) 1998,2004 Apple Computer, Inc. All Rights Reserved. + * + * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT + * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL + * EXPOSE YOU TO LIABILITY. + *************************************************************************** + * + * SHA1_priv.h - private low-level API for SHA-1 hash algorithm + * + * Revision History + * ---------------- + * 22 Aug 96 Doug Mitchell at NeXT + * Created. + */ + +/* Useful defines/typedefs */ + +#ifndef _CK_SHA1_PRIV_H_ +#define _CK_SHA1_PRIV_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned char BYTE; +typedef unsigned long LONG; + +/* The SHS block size and message digest sizes, in bytes */ + +#define SHS_BLOCKSIZE 64 +#define SHS_DIGESTSIZE 20 + +/* The structure for storing SHS info */ + +typedef struct { + LONG digest[ 5 ]; /* Message digest */ + LONG countLo, countHi; /* 64-bit bit count */ + LONG data[ 80 ]; /* SHS data buffer */ + } SHS_INFO; + +extern void shsInit(SHS_INFO *shsInfo); +extern void shsUpdate(SHS_INFO *shsInfo, + const BYTE *buffer, + int count); +extern void shsFinal(SHS_INFO *shsInfo); + +#ifdef __cplusplus +} +#endif + +#endif /* _CK_SHA1_PRIV_H_ */ diff --git a/SecurityTests/cspxutils/hashTime/hashTime.cpp b/SecurityTests/cspxutils/hashTime/hashTime.cpp new file mode 100644 index 00000000..d928a44a --- /dev/null +++ b/SecurityTests/cspxutils/hashTime/hashTime.cpp @@ -0,0 +1,723 @@ +/* + * hashTime.cpp - measure performance of digest ops + */ + +#include +#include +#include +#include +#include "cputime.h" +#include "cspwrap.h" +#include "common.h" +#include +#include +#include +#include "MD5.h" /* CryptKit version used Panther and prior */ +#include "SHA1.h" /* ditto */ + +/* enumerate digest algorithms our way */ +typedef int HT_Alg; +enum { + HA_MD5 = 0, + HA_SHA1, + HA_SHA224, + HA_SHA256, + HA_SHA384, + HA_SHA512 +}; + +#define FIRST_ALG HA_MD5 +#define LAST_ALG HA_SHA512 + +static void usage(char **argv) +{ + printf("Usage: %s [option ...]\n", argv[0]); + printf("Options:\n"); + printf(" t=testspec; default=all\n"); + printf(" test specs: c : digest context setup/teardown\n"); + printf(" b : basic single block digest\n"); + printf(" d : digest lots of data\n"); + printf(" a=alg; default=all\n"); + printf(" algs: m : MD5\n"); + printf(" s : SHA1\n"); + printf(" 4 : SHA224\n"); + printf(" 2 : SHA256\n"); + printf(" 3 : SHA384\n"); + printf(" 5 : SHA512\n"); + printf(" l=loops (only valid if testspec is given)\n"); + printf(" o (use openssl implementations, MD5 and SHA1 only)\n"); + printf(" c (use CommonCrypto implementation)\n"); + printf(" k (use CryptKit implementations, MD5 and SHA1 only\n"); + printf(" v verify digest by printing it\n"); + exit(1); +} + +static void dumpDigest( + const unsigned char *digest, + unsigned len) +{ + for(unsigned dex=0; dexloops; loop++) { + crtn = CSSM_CSP_CreateDigestContext(params->cspHand, + params->algId, &ccHand); + if(crtn) { + return crtn; + } + crtn = CSSM_DeleteContext(ccHand); + if(crtn) { + return crtn; + } + } + timeSpentMs = CPUTimeDeltaMs(startTime, CPUTimeRead()); + printf(" context setup/delete : %u ops in %.2f ms; %f ms/op\n", + params->loops, timeSpentMs, timeSpentMs / (double)params->loops); + return CSSM_OK; +} + +/* Minimal CSP init/digest/final */ +#define BASIC_BLOCK_SIZE 64 // to digest in bytes +#define MAX_DIGEST_SIZE 64 // we provide, no malloc below CSSM + +static CSSM_RETURN hashBasic( + TestParams *params) +{ + CSSM_CC_HANDLE ccHand; + CSSM_RETURN crtn; + unsigned loop; + CPUTime startTime; + double timeSpentMs; + uint8 ptext[BASIC_BLOCK_SIZE]; + uint8 digest[MAX_DIGEST_SIZE]; + CSSM_DATA ptextData = {BASIC_BLOCK_SIZE, ptext}; + CSSM_DATA digestData = {MAX_DIGEST_SIZE, digest}; + + /* we reuse this one inside the loop */ + crtn = CSSM_CSP_CreateDigestContext(params->cspHand, + params->algId, &ccHand); + if(crtn) { + return crtn; + } + + /* random data, const thru the loops */ + appGetRandomBytes(ptext, BASIC_BLOCK_SIZE); + + /* start critical timing loop */ + startTime = CPUTimeRead(); + for(loop=0; looploops; loop++) { + crtn = CSSM_DigestDataInit(ccHand); + if(crtn) { + return crtn; + } + crtn = CSSM_DigestDataUpdate(ccHand, &ptextData, 1); + if(crtn) { + return crtn; + } + crtn = CSSM_DigestDataFinal(ccHand, &digestData); + if(crtn) { + return crtn; + } + } + CSSM_DeleteContext(ccHand); + timeSpentMs = CPUTimeDeltaMs(startTime, CPUTimeRead()); + printf(" Digest one %u byte block : %u ops in %.2f ms; %f ms/op\n", + BASIC_BLOCK_SIZE, params->loops, + timeSpentMs, timeSpentMs / (double)params->loops); + return CSSM_OK; +} + +/* Lots of data */ +#define PTEXT_SIZE 1000 // to digest in bytes +#define INNER_LOOPS 1000 + +static CSSM_RETURN hashDataRate( + TestParams *params) +{ + CSSM_CC_HANDLE ccHand; + CSSM_RETURN crtn; + unsigned loop; + unsigned iloop; + CPUTime startTime; + double timeSpent, timeSpentMs; + uint8 ptext[PTEXT_SIZE]; + uint8 digest[MAX_DIGEST_SIZE]; + CSSM_DATA ptextData = {PTEXT_SIZE, ptext}; + CSSM_DATA digestData = {MAX_DIGEST_SIZE, digest}; + + /* we reuse this one inside the loop */ + crtn = CSSM_CSP_CreateDigestContext(params->cspHand, + params->algId, &ccHand); + if(crtn) { + return crtn; + } + + /* random data, const thru the loops */ + initPtext(ptext, PTEXT_SIZE); + + /* start critical timing loop */ + startTime = CPUTimeRead(); + for(loop=0; looploops; loop++) { + crtn = CSSM_DigestDataInit(ccHand); + if(crtn) { + return crtn; + } + for(iloop=0; ilooploops * bytesPerLoop; + + /* careful, KByte = 1024, ms = 1/1000 */ + printf(" Digest %.0f bytes : %u ops in %.2f ms; %f ms/op, %.0f KBytes/s\n", + bytesPerLoop, params->loops, + timeSpentMs, timeSpentMs / (double)params->loops, + ((float)totalBytes / 1024.0) / timeSpent); + if(params->dumpDigest) { + dumpDigest(digest, digestData.Length); + } + return CSSM_OK; +} + +/* Lots of data, openssl version */ + +typedef union { + MD5_CTX md5; + SHA_CTX sha; +} OS_CTX; + +typedef void (*initFcn)(void *digestCtx); +typedef void (*updateFcn)(void *digestCtx, const void *data, unsigned long len); +typedef void (*finalFcn)(unsigned char *digest, void *digestCtx); + +static CSSM_RETURN hashDataRateOpenssl( + TestParams *params) +{ + OS_CTX ctx; + initFcn initPtr = NULL; + updateFcn updatePtr = NULL; + finalFcn finalPtr = NULL; + unsigned loop; + unsigned iloop; + CPUTime startTime; + double timeSpent, timeSpentMs; + uint8 ptext[PTEXT_SIZE]; + uint8 digest[MAX_DIGEST_SIZE]; + unsigned digestLen = 16; + + /* we reuse this one inside the loop */ + switch(params->algId) { + case CSSM_ALGID_SHA1: + initPtr = (initFcn)SHA1_Init; + updatePtr = (updateFcn)SHA1_Update; + finalPtr = (finalFcn)SHA1_Final; + digestLen = 20; + break; + case CSSM_ALGID_MD5: + initPtr = (initFcn)MD5_Init; + updatePtr = (updateFcn)MD5_Update; + finalPtr = (finalFcn)MD5_Final; + break; + default: + printf("***Sorry, Openssl can only do SHA1 and MD5.\n"); + return 1; + } + + /* random data, const thru the loops */ + initPtext(ptext, PTEXT_SIZE); + + /* start critical timing loop */ + startTime = CPUTimeRead(); + for(loop=0; looploops; loop++) { + initPtr(&ctx); + for(iloop=0; ilooploops * bytesPerLoop; + + /* careful, KByte = 1024, ms = 1/1000 */ + printf(" Digest %.0f bytes : %u ops in %.2f ms; %f ms/op, %.0f KBytes/s\n", + bytesPerLoop, params->loops, + timeSpentMs, timeSpentMs / (double)params->loops, + ((float)totalBytes / 1024.0) / timeSpent); + if(params->dumpDigest) { + dumpDigest(digest, digestLen); + } + return CSSM_OK; +} + +/* Lots of data, CommonCrypto version (not thru CSP) */ + +typedef union { + CC_MD5_CTX md5; + CC_SHA1_CTX sha; + CC_SHA256_CTX sha256; + CC_SHA512_CTX sha512; +} CC_CTX; + +typedef void (*ccUpdateFcn)(void *digestCtx, const void *data, CC_LONG len); +typedef void (*ccFinalFcn)(unsigned char *digest, void *digestCtx); + +static CSSM_RETURN hashDataRateCommonCrypto( + TestParams *params) +{ + CC_CTX ctx; + ccUpdateFcn updatePtr = NULL; + ccFinalFcn finalPtr = NULL; + initFcn initPtr = NULL; + unsigned loop; + unsigned iloop; + CPUTime startTime; + double timeSpent, timeSpentMs; + uint8 ptext[PTEXT_SIZE]; + uint8 digest[MAX_DIGEST_SIZE]; + unsigned digestLen = 16; + + /* we reuse this one inside the loop */ + switch(params->algId) { + case CSSM_ALGID_SHA1: + initPtr = (initFcn)CC_SHA1_Init; + updatePtr = (ccUpdateFcn)CC_SHA1_Update; + finalPtr = (ccFinalFcn)CC_SHA1_Final; + digestLen = CC_SHA1_DIGEST_LENGTH; + break; + case CSSM_ALGID_SHA224: + initPtr = (initFcn)CC_SHA224_Init; + updatePtr = (ccUpdateFcn)CC_SHA224_Update; + finalPtr = (ccFinalFcn)CC_SHA224_Final; + digestLen = CC_SHA224_DIGEST_LENGTH; + break; + case CSSM_ALGID_SHA256: + initPtr = (initFcn)CC_SHA256_Init; + updatePtr = (ccUpdateFcn)CC_SHA256_Update; + finalPtr = (ccFinalFcn)CC_SHA256_Final; + digestLen = CC_SHA256_DIGEST_LENGTH; + break; + case CSSM_ALGID_SHA384: + initPtr = (initFcn)CC_SHA384_Init; + updatePtr = (ccUpdateFcn)CC_SHA384_Update; + finalPtr = (ccFinalFcn)CC_SHA384_Final; + digestLen = CC_SHA384_DIGEST_LENGTH; + break; + case CSSM_ALGID_SHA512: + initPtr = (initFcn)CC_SHA512_Init; + updatePtr = (ccUpdateFcn)CC_SHA512_Update; + finalPtr = (ccFinalFcn)CC_SHA512_Final; + digestLen = CC_SHA512_DIGEST_LENGTH; + break; + case CSSM_ALGID_MD5: + initPtr = (initFcn)CC_MD5_Init; + updatePtr = (ccUpdateFcn)CC_MD5_Update; + finalPtr = (ccFinalFcn)CC_MD5_Final; + digestLen = CC_MD5_DIGEST_LENGTH; + break; + default: + printf("***BRRRZAP!\n"); + return 1; + } + + /* random data, const thru the loops */ + initPtext(ptext, PTEXT_SIZE); + + /* start critical timing loop */ + startTime = CPUTimeRead(); + for(loop=0; looploops; loop++) { + initPtr(&ctx); + for(iloop=0; ilooploops * bytesPerLoop; + + /* careful, KByte = 1024, ms = 1/1000 */ + printf(" Digest %.0f bytes : %u ops in %.2f ms; %f ms/op, %.0f KBytes/s\n", + bytesPerLoop, params->loops, + timeSpentMs, timeSpentMs / (double)params->loops, + ((float)totalBytes / 1024.0) / timeSpent); + if(params->dumpDigest) { + dumpDigest(digest, digestLen); + } + return CSSM_OK; +} + +/* Lots of data, CryptKit version */ + +/* cryptkit final routines are not orthoganal, fix up here */ +static void ckSha1Final( + unsigned char *digest, + void *ctx) +{ + sha1GetDigest((sha1Obj)ctx, digest); +} + +static void ckMD5Final( + unsigned char *digest, + void *ctx) +{ + MD5Final((struct MD5Context *)ctx, digest); +} + +typedef void (*ckUpdateFcn)(void *digestCtx, const void *data, unsigned len); +typedef void (*ckFinalFcn)(unsigned char *digest, void *digestCtx); + +static CSSM_RETURN hashDataRateCryptKit( + TestParams *params) +{ + ckUpdateFcn updatePtr = NULL; + ckFinalFcn finalPtr = NULL; + initFcn initPtr = NULL; + struct MD5Context md5; + sha1Obj sha; + void *ctx; + + unsigned loop; + unsigned iloop; + CPUTime startTime; + double timeSpent, timeSpentMs; + uint8 ptext[PTEXT_SIZE]; + uint8 digest[MAX_DIGEST_SIZE]; + unsigned digestLen = 16; + + /* we reuse this one inside the loop */ + switch(params->algId) { + case CSSM_ALGID_SHA1: + sha = sha1Alloc(); + ctx = sha; + initPtr = (initFcn)sha1Reinit; + updatePtr = (ckUpdateFcn)sha1AddData; + finalPtr = (ckFinalFcn)ckSha1Final; + digestLen = 20; + break; + case CSSM_ALGID_MD5: + ctx = &md5; + initPtr = (initFcn)MD5Init; + updatePtr = (ckUpdateFcn)MD5Update; + finalPtr = (ckFinalFcn)ckMD5Final; + break; + default: + printf("***Sorry, CryptKit can only do SHA1 and MD5.\n"); + return 1; + } + + /* random data, const thru the loops */ + initPtext(ptext, PTEXT_SIZE); + + /* start critical timing loop */ + startTime = CPUTimeRead(); + for(loop=0; looploops; loop++) { + initPtr(ctx); + for(iloop=0; ilooploops * bytesPerLoop; + + /* careful, KByte = 1024, ms = 1/1000 */ + printf(" Digest %.0f bytes : %u ops in %.2f ms; %f ms/op, %.0f KBytes/s\n", + bytesPerLoop, params->loops, + timeSpentMs, timeSpentMs / (double)params->loops, + ((float)totalBytes / 1024.0) / timeSpent); + if(params->dumpDigest) { + dumpDigest(digest, digestLen); + } + return CSSM_OK; +} + +typedef CSSM_RETURN (*testRunFcn)(TestParams *testParams); + +/* + * Static declaration of a test + */ +typedef struct { + const char *testName; + unsigned loops; + testRunFcn run; + char testSpec; // for t=xxx cmd line opt +} TestDefs; + +static TestDefs testDefs[] = +{ + { "Digest context setup/teardown", + 100000, + hashContext, + 'c', + }, + { "Basic single block digest", + 100000, + hashBasic, + 'b', + }, + { "Large data digest", + 1000, + hashDataRate, + 'd', + }, +}; + +static TestDefs testDefsOpenSSL[] = +{ + { "Digest context setup/teardown", + 100000, + NULL, // not implemented + 'c', + }, + { "Basic single block digest", + 100000, + NULL, // not implemented + 'b', + }, + { "Large data digest, OpenSSL", + 1000, + hashDataRateOpenssl, + 'd', + }, +}; + +static TestDefs testDefsCommonCrypto[] = +{ + { "Digest context setup/teardown", + 100000, + NULL, // not implemented + 'c', + }, + { "Basic single block digest", + 100000, + NULL, // not implemented + 'b', + }, + { "Large data digest, CommonCrypto", + 1000, + hashDataRateCommonCrypto, + 'd', + }, +}; + +static TestDefs testDefsCryptKit[] = +{ + { "Digest context setup/teardown", + 100000, + NULL, // not implemented + 'c', + }, + { "Basic single block digest", + 100000, + NULL, // not implemented + 'b', + }, + { "Large data digest, CryptKit", + 1000, + hashDataRateCryptKit, + 'd', + }, +}; + + +static void algToAlgId( + HT_Alg alg, + CSSM_ALGORITHMS *algId, + const char **algStr) +{ + switch(alg) { + case HA_MD5: + *algId = CSSM_ALGID_MD5; + *algStr = "MD5"; + break; + case HA_SHA1: + *algId = CSSM_ALGID_SHA1; + *algStr = "SHA1"; + break; + case HA_SHA224: + *algId = CSSM_ALGID_SHA224; + *algStr = "SHA224"; + break; + case HA_SHA256: + *algId = CSSM_ALGID_SHA256; + *algStr = "SHA256"; + break; + case HA_SHA384: + *algId = CSSM_ALGID_SHA384; + *algStr = "SHA384"; + break; + case HA_SHA512: + *algId = CSSM_ALGID_SHA512; + *algStr = "SHA512"; + break; + default: + printf("***algToAlgId screwup\n"); + exit(1); + } +} + +#define NUM_TESTS (sizeof(testDefs) / sizeof(testDefs[0])) + +int main(int argc, char **argv) +{ + TestParams testParams; + TestDefs *testDef; + TestDefs *ourTestDefs = testDefs; + CSSM_RETURN crtn; + int arg; + char *argp; + unsigned cmdLoops = 0; // can be specified in cmd line + // if not, use TestDefs.loops + char testSpec = '\0'; // allows specification of one test + // otherwise run all + HT_Alg alg; + const char *algStr; + int firstAlg = FIRST_ALG; + int lastAlg = LAST_ALG; + + memset(&testParams, 0, sizeof(testParams)); + + for(arg=1; argtestSpec != testSpec)) { + continue; + } + if(testDef->run == NULL) { + continue; + } + printf("%s:\n", testDef->testName); + if(cmdLoops) { + /* user specified */ + testParams.loops = cmdLoops; + } + else { + /* default */ + testParams.loops = testDef->loops; + } + for(alg=firstAlg; alg<=lastAlg; alg++) { + algToAlgId(alg, &testParams.algId, &algStr); + printf(" === %s ===\n", algStr); + crtn = testDef->run(&testParams); + if(crtn) { + exit(1); + } + } + } + return 0; +} diff --git a/SecurityTests/cspxutils/hashTimeLibCrypt/Makefile b/SecurityTests/cspxutils/hashTimeLibCrypt/Makefile new file mode 100644 index 00000000..825a8ab3 --- /dev/null +++ b/SecurityTests/cspxutils/hashTimeLibCrypt/Makefile @@ -0,0 +1,55 @@ +# name of executable to build +EXECUTABLE=hashTimeLibCrypt +# C++ source (with .cpp extension) +CPSOURCE=hashTimeLibCrypt.cpp pbkdDigest.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= -lcrypto +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +#PROJ_LDFLAGS= -lMallocDebug +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/hashTimeLibCrypt/hashTimeLibCrypt.cpp b/SecurityTests/cspxutils/hashTimeLibCrypt/hashTimeLibCrypt.cpp new file mode 100644 index 00000000..f8cfd3b5 --- /dev/null +++ b/SecurityTests/cspxutils/hashTimeLibCrypt/hashTimeLibCrypt.cpp @@ -0,0 +1,272 @@ +/* + * hashTimeLibCrypt.cpp - measure performance of libcrypt digest ops. + * + * Thjis is obsolete; hashTime does this a lot better,a dn it also measures raw + * CommonCrypto and CryptKit versions. + */ + +#include +#include +#include +#include +#include +#include "cputime.h" +#include "cspwrap.h" +#include "common.h" +#include "pbkdDigest.h" + +/* enumerate digest algorithms our way */ +typedef int HT_Alg; +enum { + HA_MD5 = 0, + HA_SHA1 +}; + +#define FIRST_ALG HA_MD5 +#define LAST_ALG HA_SHA1 + +static void usage(char **argv) +{ + printf("Usage: %s [option ...]\n", argv[0]); + printf("Options:\n"); + printf(" t=testspec; default=all\n"); + printf(" test specs: c digest context setup/teardown\n"); + printf(" b basic single block digest\n"); + printf(" d digest lots of data\n"); + printf(" l=loops (only valid if testspec is given)\n"); + exit(1); +} + +/* passed to each test */ +typedef struct { + unsigned loops; + bool isSha; +} TestParams; + +/* just digest context setup/teardown */ +/* returns nonzero on error */ +static int hashContext( + TestParams *params) +{ + unsigned loop; + CPUTime startTime; + double timeSpentMs; + DigestCtx ctx; + int rtn; + + startTime = CPUTimeRead(); + for(loop=0; looploops; loop++) { + rtn = DigestCtxInit(&ctx, params->isSha); + if(!rtn) { + return -1; + } + } + timeSpentMs = CPUTimeDeltaMs(startTime, CPUTimeRead()); + + printf(" context setup/delete : %u ops in %.2f ms; %f ms/op\n", + params->loops, timeSpentMs, timeSpentMs / (double)params->loops); + return 0; +} + +/* Minimal init/digest/final */ +#define BASIC_BLOCK_SIZE 64 // to digest in bytes +#define MAX_DIGEST_SIZE 20 // we provide, no malloc below CSSM + +static int hashBasic( + TestParams *params) +{ + unsigned loop; + CPUTime startTime; + double timeSpentMs; + uint8 ptext[BASIC_BLOCK_SIZE]; + uint8 digest[MAX_DIGEST_SIZE]; + DigestCtx ctx; + int rtn; + + /* random data, const thru the loops */ + appGetRandomBytes(ptext, BASIC_BLOCK_SIZE); + + /* start critical timing loop */ + startTime = CPUTimeRead(); + for(loop=0; looploops; loop++) { + rtn = DigestCtxInit(&ctx, params->isSha); + if(!rtn) { + return -1; + } + rtn = DigestCtxUpdate(&ctx, ptext, BASIC_BLOCK_SIZE); + if(!rtn) { + return -1; + } + rtn = DigestCtxFinal(&ctx, digest); + if(!rtn) { + return -1; + } + } + DigestCtxFree(&ctx); + timeSpentMs = CPUTimeDeltaMs(startTime, CPUTimeRead()); + printf(" Digest one %u byte block : %u ops in %.2f ms; %f ms/op\n", + BASIC_BLOCK_SIZE, params->loops, + timeSpentMs, timeSpentMs / (double)params->loops); + return 0; +} + +/* Lots of data */ +#define PTEXT_SIZE 1000 // to digest in bytes +#define INNER_LOOPS 1000 + +static int hashDataRate( + TestParams *params) +{ + unsigned loop; + unsigned iloop; + CPUTime startTime; + double timeSpent, timeSpentMs; + uint8 ptext[PTEXT_SIZE]; + uint8 digest[MAX_DIGEST_SIZE]; + DigestCtx ctx; + int rtn; + + /* random data, const thru the loops */ + appGetRandomBytes(ptext, PTEXT_SIZE); + + /* start critical timing loop */ + startTime = CPUTimeRead(); + for(loop=0; looploops; loop++) { + rtn = DigestCtxInit(&ctx, params->isSha); + if(!rtn) { + return -1; + } + for(iloop=0; ilooploops * bytesPerLoop; + + /* careful, KByte = 1024, ms = 1/1000 */ + printf(" Digest %.0f bytes : %u ops in %.2f ms; %f ms/op, %.0f KBytes/s\n", + bytesPerLoop, params->loops, + timeSpentMs, timeSpentMs / (double)params->loops, + ((float)totalBytes / 1024.0) / timeSpent); + return 0; +} + + +typedef int (*testRunFcn)(TestParams *testParams); + +/* + * Static declaration of a test + */ +typedef struct { + const char *testName; + unsigned loops; + testRunFcn run; + char testSpec; // for t=xxx cmd line opt +} TestDefs; + +static TestDefs testDefs[] = +{ + { "Digest context setup/teardown", + 100000, + hashContext, + 'c', + }, + { "Basic single block digest", + 100000, + hashBasic, + 'b', + }, + { "Large data digest", + 1000, + hashDataRate, + 'd', + }, +}; + +static void algToAlgId( + HT_Alg alg, + bool *isSha, + const char **algStr) +{ + switch(alg) { + case HA_MD5: + *isSha = false; + *algStr = "MD5"; + break; + case HA_SHA1: + *isSha = true; + *algStr = "SHA1"; + break; + default: + printf("***algToAlgId screwup\n"); + exit(1); + } +} + +#define NUM_TESTS (sizeof(testDefs) / sizeof(testDefs[0])) + +int main(int argc, char **argv) +{ + TestParams testParams; + TestDefs *testDef; + int rtn; + int arg; + char *argp; + unsigned cmdLoops = 0; // can be specified in cmd line + // if not, use TestDefs.loops + char testSpec = '\0'; // allows specification of one test + // otherwise run all + HT_Alg alg; + const char *algStr; + + for(arg=1; argtestSpec != testSpec)) { + continue; + } + printf("%s:\n", testDef->testName); + if(cmdLoops) { + /* user specified */ + testParams.loops = cmdLoops; + } + else { + /* default */ + testParams.loops = testDef->loops; + } + for(alg=FIRST_ALG; alg<=LAST_ALG; alg++) { + algToAlgId(alg, &testParams.isSha, &algStr); + printf(" === %s ===\n", algStr); + rtn = testDef->run(&testParams); + if(rtn) { + printf("Test returned error\n"); + exit(1); + } + } + } + return 0; +} diff --git a/SecurityTests/cspxutils/hashTimeLibCrypt/pbkdDigest.cpp b/SecurityTests/cspxutils/hashTimeLibCrypt/pbkdDigest.cpp new file mode 100644 index 00000000..aca055e7 --- /dev/null +++ b/SecurityTests/cspxutils/hashTimeLibCrypt/pbkdDigest.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2003-2005 Apple Computer, Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please + * obtain a copy of the License at http://www.apple.com/publicsource and + * read it before using this file. + * + * This 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. + */ +/* + * pbkdDigest.cpp - SHA1/MD5 digest object + */ + +#include "pbkdDigest.h" +#include +#include + +/* the casts are necessary to cover the polymorphous context types */ +DigestOps Md5Ops = { + (DigestInitFcn)MD5_Init, + (DigestUpdateFcn)MD5_Update, + (DigestFinalFcn)MD5_Final +}; +DigestOps Sha1Ops = { + (DigestInitFcn)SHA1_Init, + (DigestUpdateFcn)SHA1_Update, + (DigestFinalFcn)SHA1_Final +}; + +/* Ops on a DigestCtx */ +int DigestCtxInit( + DigestCtx *ctx, + CSSM_BOOL isSha1) +{ + if(isSha1) { + ctx->ops = &Sha1Ops; + } + else { + ctx->ops = &Md5Ops; + } + ctx->isSha1 = isSha1; + return ctx->ops->init(&ctx->dig); +} + +void DigestCtxFree( + DigestCtx *ctx) +{ + memset(ctx, 0, sizeof(DigestCtx)); +} + +int DigestCtxUpdate( + DigestCtx *ctx, + const void *textPtr, + uint32 textLen) +{ + return ctx->ops->update(&ctx->dig, textPtr, textLen); +} + +int DigestCtxFinal( + DigestCtx *ctx, + void *digest) +{ + return ctx->ops->final(digest, &ctx->dig); +} diff --git a/SecurityTests/cspxutils/hashTimeLibCrypt/pbkdDigest.h b/SecurityTests/cspxutils/hashTimeLibCrypt/pbkdDigest.h new file mode 100644 index 00000000..fcb582d2 --- /dev/null +++ b/SecurityTests/cspxutils/hashTimeLibCrypt/pbkdDigest.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2003-2005 Apple Computer, Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please + * obtain a copy of the License at http://www.apple.com/publicsource and + * read it before using this file. + * + * This 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. + */ +/* + * pbkdDigest.h - SHA1/MD5 digest object + */ + +#ifndef _PBKD_DIGEST_H_ +#define _PBKD_DIGEST_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define kSHA1DigestSize SHA_DIGEST_LENGTH +#define kSHA1BlockSize SHA_CBLOCK + +#define kMD5DigestSize MD5_DIGEST_LENGTH +#define kMD5BlockSize MD5_CBLOCK + +typedef int (*DigestInitFcn)(void *ctx); +typedef int (*DigestUpdateFcn)(void *ctx, const void *data, unsigned long len); +typedef int (*DigestFinalFcn)(void *md, void *c); + +/* callouts to libcrypt */ +typedef struct { + DigestInitFcn init; + DigestUpdateFcn update; + DigestFinalFcn final; +} DigestOps; + +typedef struct { + union { + SHA_CTX sha1Context; + MD5_CTX md5Context; + } dig; + DigestOps *ops; + CSSM_BOOL isSha1; +} DigestCtx; + +/* Ops on a DigestCtx */ +int DigestCtxInit( + DigestCtx *ctx, + CSSM_BOOL isSha1); +void DigestCtxFree( + DigestCtx *ctx); +int DigestCtxUpdate( + DigestCtx *ctx, + const void *textPtr, + uint32 textLen); +int DigestCtxFinal( + DigestCtx *ctx, + void *digest); + +#ifdef __cplusplus +} +#endif + +#endif /* _PBKD_DIGEST_H_ */ + diff --git a/SecurityTests/cspxutils/hashTimeSA/MD5.c b/SecurityTests/cspxutils/hashTimeSA/MD5.c new file mode 100644 index 00000000..9ae199eb --- /dev/null +++ b/SecurityTests/cspxutils/hashTimeSA/MD5.c @@ -0,0 +1,367 @@ +/* + File: MD5.c + + Written by: Colin Plumb + + Copyright: Copyright (c) 1998,2004-2005 Apple Computer, Inc. All Rights Reserved. + + Change History (most recent first): + + <7> 10/06/98 ap Changed to compile with C++. + + To Do: +*/ + +/* Copyright (c) 1998,2004-2005 Apple Computer, Inc. All Rights Reserved. + * + * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT + * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL + * EXPOSE YOU TO LIABILITY. + *************************************************************************** + * + * MD5.c + */ + +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +/* + * Revision History + * ---------------- + * 06 Feb 1997 Doug Mitchell at Apple + * Fixed endian-dependent cast in MD5Final() + * Made byteReverse() tolerant of platform-dependent alignment + * restrictions + */ + +#include "MD5.h" +//#include "platform.h" +#undef __LITTLE_ENDIAN__ +#undef __BIG_ENDIAN__ +#define __BIG_ENDIAN__ + +#include +#include + +static inline void intToByteRep(int i, unsigned char *buf) +{ + *buf++ = (unsigned char)((i >> 24) & 0xff); + *buf++ = (unsigned char)((i >> 16) & 0xff); + *buf++ = (unsigned char)((i >> 8) & 0xff); + *buf = (unsigned char)(i & 0xff); +} + +#define MD5_DEBUG 0 + +#if MD5_DEBUG +static inline void dumpCtx(struct MD5Context *ctx, char *label) +{ + int i; + + printf("%s\n", label); + printf("buf = "); + for(i=0; i<4; i++) { + printf("%x:", ctx->buf[i]); + } + printf("\nbits: %d:%d\n", ctx->bits[0], ctx->bits[1]); + printf("in[]:\n "); + for(i=0; i<64; i++) { + printf("%02x:", ctx->in[i]); + if((i % 16) == 15) { + printf("\n "); + } + } + printf("\n"); +} +#else // MD5_DEBUG +#define dumpCtx(ctx, label) +#endif // MD5_DEBUG + +static void MD5Transform(uint32 buf[4], uint32 const in[16]); + +#ifdef __LITTLE_ENDIAN__ +#define byteReverse(buf, len) /* Nothing */ +#else +static void byteReverse(unsigned char *buf, unsigned longs); + +#ifndef ASM_MD5 +/* + * Note: this code is harmless on little-endian machines. + */ +static void byteReverse(unsigned char *buf, unsigned longs) +{ +#if old_way + /* + * this code is NOT harmless on big-endian machine which require + * natural alignment. + */ + uint32 t; + do { + t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(uint32 *) buf = t; + buf += 4; + } while (--longs); +#else // new_way + + unsigned char t; + do { + t = buf[0]; + buf[0] = buf[3]; + buf[3] = t; + t = buf[1]; + buf[1] = buf[2]; + buf[2] = t; + buf += 4; + } while (--longs); +#endif // old_way +} +#endif // ASM_MD5 +#endif // __LITTLE_ENDIAN__ + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void MD5Init(struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) +{ + uint32 t; + + dumpCtx(ctx, "MD5.c update top"); + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + dumpCtx(ctx, "update - return from transform (1)"); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + dumpCtx(ctx, "update - return from transform (2)"); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void MD5Final(struct MD5Context *ctx, unsigned char *digest) +{ + unsigned count; + unsigned char *p; + + dumpCtx(ctx, "final top"); + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + #if MD5_DEBUG + printf("in[%d] = %x\n", count, ctx->in[count]); + #endif + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + dumpCtx(ctx, "final, before pad"); + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + bzero(p, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + bzero(ctx->in, 56); + } else { + /* Pad block to 56 bytes */ + bzero(p, count - 8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + #ifdef __LITTLE_ENDIAN__ + /* l.s. byte of bits[0] --> in[56] */ + ((uint32 *) ctx->in)[14] = ctx->bits[0]; + ((uint32 *) ctx->in)[15] = ctx->bits[1]; + #else + /* l.s. byte of bits[0] --> in[60] */ + intToByteRep(ctx->bits[0], &ctx->in[56]); + intToByteRep(ctx->bits[1], &ctx->in[60]); + #endif + + dumpCtx(ctx, "last transform"); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + memcpy(digest, ctx->buf, MD5_DIGEST_SIZE); + dumpCtx(ctx, "final end"); + + bzero(ctx, sizeof(*ctx)); /* In case it's sensitive */ +} + +#ifndef ASM_MD5 + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void MD5Transform(uint32 buf[4], uint32 const in[16]) +{ + register uint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#endif // ASM_MD5 diff --git a/SecurityTests/cspxutils/hashTimeSA/MD5.h b/SecurityTests/cspxutils/hashTimeSA/MD5.h new file mode 100644 index 00000000..29e17df1 --- /dev/null +++ b/SecurityTests/cspxutils/hashTimeSA/MD5.h @@ -0,0 +1,63 @@ +/* + File: MD5.h + + Written by: Colin Plumb + + Copyright: Copyright (c) 1998,2004 Apple Computer, Inc. All Rights Reserved. + + Change History (most recent first): + + <8> 10/06/98 ap Changed to compile with C++. + + To Do: +*/ + +/* Copyright (c) 1998,2004 Apple Computer, Inc. All Rights Reserved. + * + * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT + * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL + * EXPOSE YOU TO LIABILITY. + *************************************************************************** + * + * MD5.h + * derived and used without need for permission from public domain source + */ + +#ifndef _CK_MD5_H_ +#define _CK_MD5_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __alpha +typedef unsigned int uint32; +#elif defined (macintosh) +typedef unsigned int uint32; +#else +#include +//typedef unsigned long uint32; +#endif + +struct MD5Context { + uint32 buf[4]; + uint32 bits[2]; // bits[0] is low 32 bits of bit count + unsigned char in[64]; +}; + +#define MD5_DIGEST_SIZE 16 /* in bytes */ +#define MD5_BLOCK_SIZE 64 /* in bytes */ + +void MD5Init(struct MD5Context *context); +void MD5Update(struct MD5Context *context, unsigned char const *buf, + unsigned len); +void MD5Final(struct MD5Context *context, unsigned char *digest); + +#ifdef __cplusplus +} +#endif + +#endif /*_CK_MD5_H_*/ diff --git a/SecurityTests/cspxutils/hashTimeSA/Makefile b/SecurityTests/cspxutils/hashTimeSA/Makefile new file mode 100644 index 00000000..c3b60c0a --- /dev/null +++ b/SecurityTests/cspxutils/hashTimeSA/Makefile @@ -0,0 +1,42 @@ +EXECUTABLE=hashTimeSA +# C++ source (with .cpp extension) +CPSOURCE= hashTimeSA.cpp +# C source (.c extension) +CSOURCE= SHA1_priv.c MD5.c SHA1.c +OFILES = $(CSOURCE:%.c=%.o) $(CPSOURCE:%.cpp=%.o) + +LOCAL_BUILD= $(shell echo $(LOCAL_BUILD_DIR)) + +FRAMEWORKS= -framework CoreFoundation +FRAME_SEARCH= +FINCLUDES= +PINCLUDES= -I$(LOCAL_BUILD)/include +CINCLUDES= $(FINCLUDES) $(PINCLUDES) +WFLAGS= -Wno-four-char-constants -Wno-deprecated-declarations +CFLAGS= -g $(CINCLUDES) $(WFLAGS) $(FRAME_SEARCH) -Os + +# +# This assumes final load with cc, not ld +# +###LIBS= -lstdc++ -lcommonCrypto +LIBS= -lstdc++ +LIBPATH= -L$(LOCAL_BUILD) -L/usr/local/lib/system +LDFLAGS= $(LIBS) $(LIBPATH) $(FRAME_SEARCH) + +first: $(EXECUTABLE) + +$(EXECUTABLE): $(OFILES) + $(CC) -o $(EXECUTABLE) $(FRAMEWORKS) $(OFILES) $(LDFLAGS) + +clean: + rm -f *.o $(EXECUTABLE) + +installhdrs: + +install: + +%.o: %.c + $(CC) $(CFLAGS) -c -o $*.o $< + +%.o: %.cpp + $(CC) $(CFLAGS) -c -o $*.o $< diff --git a/SecurityTests/cspxutils/hashTimeSA/SHA1.c b/SecurityTests/cspxutils/hashTimeSA/SHA1.c new file mode 100644 index 00000000..89844dce --- /dev/null +++ b/SecurityTests/cspxutils/hashTimeSA/SHA1.c @@ -0,0 +1,176 @@ +/* Copyright (c) 1998,2004 Apple Computer, Inc. All Rights Reserved. + * + * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT + * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL + * EXPOSE YOU TO LIABILITY. + *************************************************************************** + * + * SHA1.c - generic, portable SHA-1 hash object + * + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 07 Jan 1998 Doug Mitchell at Apple + * Created. + */ + +#include "SHA1.h" +#include "SHA1_priv.h" +#include + +/* for now map falloc to malloc, FIXME */ +#include +#define fmalloc(s) malloc(s) +#define ffree(p) free(p) + +/* + * Private data for this object. A sha1Obj handle is cast to a pointer + * to one of these. + */ +typedef struct { + SHS_INFO context; + int isDone; + + /* + * For storing partial blocks + */ + BYTE dataBuf[SHS_BLOCKSIZE]; + unsigned bufBytes; // valid bytes in dataBuf[p] +} sha1Inst; + +/* + * Alloc and init an empty sha1 object. + */ +sha1Obj sha1Alloc(void) +{ + sha1Inst *sinst; + + sinst = (sha1Inst *)fmalloc(sizeof(sha1Inst)); + if(sinst == NULL) { + return NULL; + } + shsInit(&sinst->context); + sha1Reinit((sha1Obj)sinst); + return (sha1Obj)sinst; +} + +/* + * Reusable init function. + */ +void sha1Reinit(sha1Obj sha1) +{ + sha1Inst *sinst = (sha1Inst *) sha1; + + shsInit(&sinst->context); + sinst->isDone = 0; + sinst->bufBytes = 0; +} + +/* + * Free an sha1 object. + */ +void sha1Free(sha1Obj sha1) +{ + sha1Inst *sinst = (sha1Inst *) sha1; + + memset(sha1, 0, sizeof(sha1Inst)); + ffree(sinst); +} + +/* + * Add some data to the sha1 object. + */ +void sha1AddData(sha1Obj sha1, + const unsigned char *data, + unsigned dataLen) +{ + sha1Inst *sinst = (sha1Inst *) sha1; + unsigned toMove; + unsigned blocks; + + if(sinst->isDone) { + /* + * Log some kind of error here... + */ + return; + } + + /* + * First deal with partial buffered block + */ + if(sinst->bufBytes != 0) { + toMove = SHS_BLOCKSIZE - sinst->bufBytes; + if(toMove > dataLen) { + toMove = dataLen; + } + memmove(sinst->dataBuf+sinst->bufBytes, data, toMove); + data += toMove; + dataLen -= toMove; + sinst->bufBytes += toMove; + if(sinst->bufBytes == SHS_BLOCKSIZE) { + shsUpdate(&sinst->context, sinst->dataBuf, SHS_BLOCKSIZE); + sinst->bufBytes = 0; + } + } + + /* + * Now the bulk of the data, in a multiple of full blocks + */ + blocks = dataLen / SHS_BLOCKSIZE; + toMove = blocks * SHS_BLOCKSIZE; + if(toMove != 0) { + shsUpdate(&sinst->context, data, toMove); + data += toMove; + dataLen -= toMove; + } + + /* + * Store any remainder in dataBuf + */ + if(dataLen != 0) { + memmove(sinst->dataBuf, data, dataLen); + sinst->bufBytes = dataLen; + } +} + +/* + * Obtain a pointer to completed message digest, and the length of the digest. + */ +unsigned char *sha1Digest(sha1Obj sha1) +{ + sha1Inst *sinst = (sha1Inst *) sha1; + + if(!sinst->isDone) { + /* + * Deal with partial resid block + */ + if(sinst->bufBytes != 0) { + shsUpdate(&sinst->context, sinst->dataBuf, + sinst->bufBytes); + sinst->bufBytes = 0; + } + shsFinal(&sinst->context); + sinst->isDone = 1; + } + /* + * FIXME - should do explicit conversion to char array....? + */ + return (unsigned char *)sinst->context.digest; +} + +/* As above, with copy. */ +void sha1GetDigest(sha1Obj sha1, + unsigned char *digest) +{ + unsigned char *dig = sha1Digest(sha1); + memmove(digest, dig, SHS_DIGESTSIZE); +} + +unsigned sha1DigestLen(void) +{ + return SHS_DIGESTSIZE; +} diff --git a/SecurityTests/cspxutils/hashTimeSA/SHA1.h b/SecurityTests/cspxutils/hashTimeSA/SHA1.h new file mode 100644 index 00000000..8a8a04de --- /dev/null +++ b/SecurityTests/cspxutils/hashTimeSA/SHA1.h @@ -0,0 +1,76 @@ +/* Copyright (c) 1998,2004 Apple Computer, Inc. All Rights Reserved. + * + * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT + * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL + * EXPOSE YOU TO LIABILITY. + *************************************************************************** + * + * SHA1.h - generic, portable SHA-1 hash object + * + * Revision History + * ---------------- + * 05 Jan 1998 Doug Mitchell at Apple + * Created. + */ + +#ifndef _CK_SHA1_H_ +#define _CK_SHA1_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SHA1_DIGEST_SIZE 20 /* in bytes */ +#define SHA1_BLOCK_SIZE 64 /* in bytes */ + +/* + * Opaque sha1 object handle. + */ +typedef void *sha1Obj; + +/* + * Alloc and init an empty sha1 object. + */ +sha1Obj sha1Alloc(void); + +/* + * reinitialize an sha1 object for reuse. + */ +void sha1Reinit(sha1Obj sha1); + +/* + * Free an sha1 object. + */ +void sha1Free(sha1Obj sha1); + +/* + * Add some data to the sha1 object. + */ +void sha1AddData(sha1Obj sha1, + const unsigned char *data, + unsigned dataLen); + +/* + * Obtain a pointer to completed message digest. This disables further calls + * to sha1AddData(). This pointer is NOT malloc'd; the associated data + * persists only as long as this object does. + */ +unsigned char *sha1Digest(sha1Obj sha1); + +/* As above, with copy. */ +void sha1GetDigest(sha1Obj sha1, + unsigned char *digest); + +/* + * Obtain the length of the message digest. + */ +unsigned sha1DigestLen(void); + +#ifdef __cplusplus +} +#endif + +#endif /*_CK_SHA1_H_*/ diff --git a/SecurityTests/cspxutils/hashTimeSA/SHA1_priv.c b/SecurityTests/cspxutils/hashTimeSA/SHA1_priv.c new file mode 100644 index 00000000..276fdb65 --- /dev/null +++ b/SecurityTests/cspxutils/hashTimeSA/SHA1_priv.c @@ -0,0 +1,313 @@ +/* Copyright (c) 1998,2004 Apple Computer, Inc. All Rights Reserved. + * + * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT + * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL + * EXPOSE YOU TO LIABILITY. + *************************************************************************** + * + * SHA1_priv.c - low-level SHA-1 hash algorithm. + * + * Revision History + * ---------------- + * 05 Jan 1998 Doug Mitchell at Apple + * Created, based on source by Peter C. Gutmann. + * Mods: made reentrant, added NIST fix to expand(), eliminated + * unnecessary copy to local W[] array. + */ + + +/* NIST proposed Secure Hash Standard. + + Written 2 September 1992, Peter C. Gutmann. + This implementation placed in the public domain. + + Comments to pgut1@cs.aukuni.ac.nz */ + + +#include "SHA1_priv.h" +#include + +/* The SHS f()-functions */ + +#define f1(x,y,z) ( ( x & y ) | ( ~x & z ) ) /* Rounds 0-19 */ +#define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ +#define f3(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) ) /* Rounds 40-59 */ +#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ + +/* The SHS Mysterious Constants */ + +#define K1 0x5A827999L /* Rounds 0-19 */ +#define K2 0x6ED9EBA1L /* Rounds 20-39 */ +#define K3 0x8F1BBCDCL /* Rounds 40-59 */ +#define K4 0xCA62C1D6L /* Rounds 60-79 */ + +/* SHS initial values */ + +#define h0init 0x67452301L +#define h1init 0xEFCDAB89L +#define h2init 0x98BADCFEL +#define h3init 0x10325476L +#define h4init 0xC3D2E1F0L + +/* 32-bit rotate - kludged with shifts */ + +#define S(n,X) ( ( X << n ) | ( X >> ( 32 - n ) ) ) + +/* The initial expanding function */ + +/* + * 06 Jan 1998. Added left circular shift per NIST FIPS-180-1 (at + * http://www.nist.gov/itl/div897/pubs/fip180-1.htm). Also see + * B. Schneier, Applied Cryptography, Second Edition, section 18.7 + * for info on this addenda to the original NIST spec. + */ +#define expand(count) { \ + W[count] = W[count - 3] ^ W[count - 8] ^ W[count - 14] ^ W[count - 16]; \ + W[count] = S(1, W[count]); \ +} + +/* The four SHS sub-rounds */ + +#define subRound1(count) \ + { \ + temp = S( 5, A ) + f1( B, C, D ) + E + W[ count ] + K1; \ + E = D; \ + D = C; \ + C = S( 30, B ); \ + B = A; \ + A = temp; \ + } + +#define subRound2(count) \ + { \ + temp = S( 5, A ) + f2( B, C, D ) + E + W[ count ] + K2; \ + E = D; \ + D = C; \ + C = S( 30, B ); \ + B = A; \ + A = temp; \ + } + +#define subRound3(count) \ + { \ + temp = S( 5, A ) + f3( B, C, D ) + E + W[ count ] + K3; \ + E = D; \ + D = C; \ + C = S( 30, B ); \ + B = A; \ + A = temp; \ + } + +#define subRound4(count) \ + { \ + temp = S( 5, A ) + f4( B, C, D ) + E + W[ count ] + K4; \ + E = D; \ + D = C; \ + C = S( 30, B ); \ + B = A; \ + A = temp; \ + } + +/* Initialize the SHS values */ + +void shsInit( SHS_INFO *shsInfo ) + { + /* Set the h-vars to their initial values */ + shsInfo->digest[ 0 ] = h0init; + shsInfo->digest[ 1 ] = h1init; + shsInfo->digest[ 2 ] = h2init; + shsInfo->digest[ 3 ] = h3init; + shsInfo->digest[ 4 ] = h4init; + + /* Initialise bit count */ + shsInfo->countLo = shsInfo->countHi = 0L; + } + +/* Perform the SHS transformation. Note that this code, like MD5, seems to + break some optimizing compilers - it may be necessary to split it into + sections, eg based on the four subrounds */ + +static void shsTransform( SHS_INFO *shsInfo ) +{ + LONG *W, temp; + LONG A, B, C, D, E; + + /* Step A. Copy the data buffer into the local work buffer. */ + /* 07 Jan 1998, dmitch: skip this bogus move, and let the caller + * copy data directly into the W[] array. To minimize changes, + * we'll just increase the size of shsInfo->data[] and make W + * a pointer here. + */ + W = shsInfo->data; + + /* Step B. Expand the 16 words into 64 temporary data words */ + + /* + * Note: I tried optimizing this via a for loop, and for some reason, + * the "optimized" version ran slower on PPC than the original + * unrolled version. The optimized version does run faster on i486 than + * the unrolled version. + * + * Similarly, the set of subRounds, below, runs slower on i486 when + * optimized via 4 'for' loops. The "optimized" version of that is + * a wash on PPC. + * + * Conclusion: leave both of 'em unrolled. We could ifdef per machine, + * but this would get messy once we had more than two architectures. + * We may want to revisit this. --dpm + */ + expand( 16 ); expand( 17 ); expand( 18 ); expand( 19 ); expand( 20 ); + expand( 21 ); expand( 22 ); expand( 23 ); expand( 24 ); expand( 25 ); + expand( 26 ); expand( 27 ); expand( 28 ); expand( 29 ); expand( 30 ); + expand( 31 ); expand( 32 ); expand( 33 ); expand( 34 ); expand( 35 ); + expand( 36 ); expand( 37 ); expand( 38 ); expand( 39 ); expand( 40 ); + expand( 41 ); expand( 42 ); expand( 43 ); expand( 44 ); expand( 45 ); + expand( 46 ); expand( 47 ); expand( 48 ); expand( 49 ); expand( 50 ); + expand( 51 ); expand( 52 ); expand( 53 ); expand( 54 ); expand( 55 ); + expand( 56 ); expand( 57 ); expand( 58 ); expand( 59 ); expand( 60 ); + expand( 61 ); expand( 62 ); expand( 63 ); expand( 64 ); expand( 65 ); + expand( 66 ); expand( 67 ); expand( 68 ); expand( 69 ); expand( 70 ); + expand( 71 ); expand( 72 ); expand( 73 ); expand( 74 ); expand( 75 ); + expand( 76 ); expand( 77 ); expand( 78 ); expand( 79 ); + + /* Step C. Set up first buffer */ + A = shsInfo->digest[ 0 ]; + B = shsInfo->digest[ 1 ]; + C = shsInfo->digest[ 2 ]; + D = shsInfo->digest[ 3 ]; + E = shsInfo->digest[ 4 ]; + + /* Step D. Serious mangling, divided into four sub-rounds */ + subRound1( 0 ); subRound1( 1 ); subRound1( 2 ); subRound1( 3 ); + subRound1( 4 ); subRound1( 5 ); subRound1( 6 ); subRound1( 7 ); + subRound1( 8 ); subRound1( 9 ); subRound1( 10 ); subRound1( 11 ); + subRound1( 12 ); subRound1( 13 ); subRound1( 14 ); subRound1( 15 ); + subRound1( 16 ); subRound1( 17 ); subRound1( 18 ); subRound1( 19 ); + subRound2( 20 ); subRound2( 21 ); subRound2( 22 ); subRound2( 23 ); + subRound2( 24 ); subRound2( 25 ); subRound2( 26 ); subRound2( 27 ); + subRound2( 28 ); subRound2( 29 ); subRound2( 30 ); subRound2( 31 ); + subRound2( 32 ); subRound2( 33 ); subRound2( 34 ); subRound2( 35 ); + subRound2( 36 ); subRound2( 37 ); subRound2( 38 ); subRound2( 39 ); + subRound3( 40 ); subRound3( 41 ); subRound3( 42 ); subRound3( 43 ); + subRound3( 44 ); subRound3( 45 ); subRound3( 46 ); subRound3( 47 ); + subRound3( 48 ); subRound3( 49 ); subRound3( 50 ); subRound3( 51 ); + subRound3( 52 ); subRound3( 53 ); subRound3( 54 ); subRound3( 55 ); + subRound3( 56 ); subRound3( 57 ); subRound3( 58 ); subRound3( 59 ); + subRound4( 60 ); subRound4( 61 ); subRound4( 62 ); subRound4( 63 ); + subRound4( 64 ); subRound4( 65 ); subRound4( 66 ); subRound4( 67 ); + subRound4( 68 ); subRound4( 69 ); subRound4( 70 ); subRound4( 71 ); + subRound4( 72 ); subRound4( 73 ); subRound4( 74 ); subRound4( 75 ); + subRound4( 76 ); subRound4( 77 ); subRound4( 78 ); subRound4( 79 ); + + /* Step E. Build message digest */ + shsInfo->digest[ 0 ] += A; + shsInfo->digest[ 1 ] += B; + shsInfo->digest[ 2 ] += C; + shsInfo->digest[ 3 ] += D; + shsInfo->digest[ 4 ] += E; +} + +#ifdef __LITTLE_ENDIAN__ + +/* When run on a little-endian CPU we need to perform byte reversal on an + array of longwords. It is possible to make the code endianness- + independant by fiddling around with data at the byte level, but this + makes for very slow code, so we rely on the user to sort out endianness + at compile time */ + +static void byteReverse( buffer, byteCount ) + LONG *buffer; + int byteCount; + + { + LONG value; + int count; + + byteCount /= sizeof( LONG ); + for( count = 0; count < byteCount; count++ ) + { + value = ( buffer[ count ] << 16 ) | ( buffer[ count ] >> 16 ); + buffer[ count ] = ( ( value & 0xFF00FF00L ) >> 8 ) | ( ( value & 0x00FF00FFL ) << 8 ); + } + } + +#else /* __LITTLE_ENDIAN__ */ + +/* + * Nop for big-endian machines + */ +#define byteReverse( buffer, byteCount ) + +#endif /* __LITTLE_ENDIAN__ */ + + +/* Update SHS for a block of data. This code assumes that the buffer size + is a multiple of SHS_BLOCKSIZE bytes long, which makes the code a lot + more efficient since it does away with the need to handle partial blocks + between calls to shsUpdate() */ + +void shsUpdate( + SHS_INFO *shsInfo, + const BYTE *buffer, + int count) + + { + /* Update bitcount */ + if( ( shsInfo->countLo + ( ( LONG ) count << 3 ) ) < shsInfo->countLo ) + shsInfo->countHi++; /* Carry from low to high bitCount */ + shsInfo->countLo += ( ( LONG ) count << 3 ); + shsInfo->countHi += ( ( LONG ) count >> 29 ); + + /* Process data in SHS_BLOCKSIZE chunks */ + while( count >= SHS_BLOCKSIZE ) + { + memcpy( shsInfo->data, buffer, SHS_BLOCKSIZE ); + byteReverse( shsInfo->data, SHS_BLOCKSIZE ); + shsTransform( shsInfo ); + buffer += SHS_BLOCKSIZE; + count -= SHS_BLOCKSIZE; + } + + /* Handle any remaining bytes of data. This should only happen once + on the final lot of data */ + memcpy( shsInfo->data, buffer, count ); + } + +void shsFinal(SHS_INFO *shsInfo) + { + int count; + LONG lowBitcount = shsInfo->countLo, highBitcount = shsInfo->countHi; + + /* Compute number of bytes mod 64 */ + count = ( int ) ( ( shsInfo->countLo >> 3 ) & 0x3F ); + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + ( ( BYTE * ) shsInfo->data )[ count++ ] = 0x80; + + /* Pad out to 56 mod 64 */ + if( count > 56 ) + { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset( ( BYTE * ) &shsInfo->data + count, 0, 64 - count ); + byteReverse( shsInfo->data, SHS_BLOCKSIZE ); + shsTransform( shsInfo ); + + /* Now fill the next block with 56 bytes */ + memset( &shsInfo->data, 0, 56 ); + } + else + /* Pad block to 56 bytes */ + memset( ( BYTE * ) &shsInfo->data + count, 0, 56 - count ); + byteReverse( shsInfo->data, SHS_BLOCKSIZE ); + + /* Append length in bits and transform */ + shsInfo->data[ 14 ] = highBitcount; + shsInfo->data[ 15 ] = lowBitcount; + + shsTransform( shsInfo ); + byteReverse( shsInfo->digest, SHS_DIGESTSIZE ); + } diff --git a/SecurityTests/cspxutils/hashTimeSA/SHA1_priv.h b/SecurityTests/cspxutils/hashTimeSA/SHA1_priv.h new file mode 100644 index 00000000..b208044d --- /dev/null +++ b/SecurityTests/cspxutils/hashTimeSA/SHA1_priv.h @@ -0,0 +1,54 @@ +/* Copyright (c) 1998,2004 Apple Computer, Inc. All Rights Reserved. + * + * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT + * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, + * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL + * EXPOSE YOU TO LIABILITY. + *************************************************************************** + * + * SHA1_priv.h - private low-level API for SHA-1 hash algorithm + * + * Revision History + * ---------------- + * 22 Aug 96 Doug Mitchell at NeXT + * Created. + */ + +/* Useful defines/typedefs */ + +#ifndef _CK_SHA1_PRIV_H_ +#define _CK_SHA1_PRIV_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned char BYTE; +typedef unsigned long LONG; + +/* The SHS block size and message digest sizes, in bytes */ + +#define SHS_BLOCKSIZE 64 +#define SHS_DIGESTSIZE 20 + +/* The structure for storing SHS info */ + +typedef struct { + LONG digest[ 5 ]; /* Message digest */ + LONG countLo, countHi; /* 64-bit bit count */ + LONG data[ 80 ]; /* SHS data buffer */ + } SHS_INFO; + +extern void shsInit(SHS_INFO *shsInfo); +extern void shsUpdate(SHS_INFO *shsInfo, + const BYTE *buffer, + int count); +extern void shsFinal(SHS_INFO *shsInfo); + +#ifdef __cplusplus +} +#endif + +#endif /* _CK_SHA1_PRIV_H_ */ diff --git a/SecurityTests/cspxutils/hashTimeSA/hashTimeSA.cpp b/SecurityTests/cspxutils/hashTimeSA/hashTimeSA.cpp new file mode 100644 index 00000000..04cd2993 --- /dev/null +++ b/SecurityTests/cspxutils/hashTimeSA/hashTimeSA.cpp @@ -0,0 +1,420 @@ +/* + * hashTimeSA.cpp - measure performance of digest ops, standalone version (no + * dependency on Security.framewortk or on CommonCrypto portion of libSystem). + */ + +#include +#include +#include +#include /* static lib used in Tiger */ +#include "MD5.h" /* CryptKit version used in Panther and prior */ +#include "SHA1.h" /* ditto */ +#include /* for ALGID values */ +#include /* more ALGID values */ +#include + +/* enumerate digest algorithms our way */ +typedef int HT_Alg; +enum { + HA_MD5 = 0, + HA_SHA1, + HA_SHA224, + HA_SHA256, + HA_SHA384, + HA_SHA512 +}; + +#define FIRST_ALG HA_MD5 +#define LAST_ALG HA_SHA512 + +static void usage(char **argv) +{ + printf("Usage: %s c|k [option ...]\n", argv[0]); + printf(" c=CommonCrypto; k=CryptKit\n"); + printf("Options:\n"); + printf(" a=alg; default=all\n"); + printf(" algs: m : MD5\n"); + printf(" s : SHA1\n"); + printf(" 4 : SHA224\n"); + printf(" 2 : SHA256\n"); + printf(" 3 : SHA384\n"); + printf(" 5 : SHA512\n"); + printf(" l=loops (only valid if testspec is given)\n"); + printf(" v verify digest by printing it\n"); + exit(1); +} + +static void dumpDigest( + const unsigned char *digest, + unsigned len) +{ + for(unsigned dex=0; dexalgId) { + case CSSM_ALGID_SHA1: + sha = sha1Alloc(); + ctx = sha; + initPtr = (ckInitFcn)sha1Reinit; + updatePtr = (ckUpdateFcn)sha1AddData; + finalPtr = (ckFinalFcn)ckSha1Final; + digestLen = 20; + break; + case CSSM_ALGID_MD5: + ctx = &md5; + initPtr = (ckInitFcn)MD5Init; + updatePtr = (ckUpdateFcn)MD5Update; + finalPtr = (ckFinalFcn)MD5Final; + break; + default: + printf("***Sorry, CryptKit can only do SHA1 and MD5.\n"); + return 1; + } + + /* random data, const thru the loops */ + initPtext(ptext, PTEXT_SIZE); + + /* start critical timing loop */ + startTime = CFAbsoluteTimeGetCurrent(); + for(loop=0; looploops; loop++) { + initPtr(ctx); + for(iloop=0; ilooploops * bytesPerLoop; + + /* careful, KByte = 1024, ms = 1/1000 */ + printf(" Digest %.0f bytes : %u ops in %.2f ms; %f ms/op, %.0f KBytes/s\n", + bytesPerLoop, params->loops, + timeSpentMs, timeSpentMs / (double)params->loops, + ((float)totalBytes / 1024.0) / timeSpent); + if(params->dumpDigest) { + dumpDigest(digest, digestLen); + } + return CSSM_OK; +} + +typedef union { + CC_MD5_CTX md5; + CC_SHA1_CTX sha; + CC_SHA256_CTX sha256; + CC_SHA512_CTX sha512; +} CC_CTX; + +typedef void (*ccInitFcn)(void *digestCtx); +typedef void (*ccUpdateFcn)(void *digestCtx, const void *data, CC_LONG len); +typedef void (*ccFinalFcn)(unsigned char *digest, void *digestCtx); + +static CSSM_RETURN hashDataRateCommonCrypto( + TestParams *params) +{ + CC_CTX ctx; + ccUpdateFcn updatePtr = NULL; + ccFinalFcn finalPtr = NULL; + ccInitFcn initPtr = NULL; + unsigned loop; + unsigned iloop; + double startTime, endTime; + double timeSpent, timeSpentMs; + uint8 ptext[PTEXT_SIZE]; + uint8 digest[MAX_DIGEST_SIZE]; + unsigned digestLen = 16; + + /* we reuse this one inside the loop */ + switch(params->algId) { + case CSSM_ALGID_SHA1: + initPtr = (ccInitFcn)CC_SHA1_Init; + updatePtr = (ccUpdateFcn)CC_SHA1_Update; + finalPtr = (ccFinalFcn)CC_SHA1_Final; + digestLen = 20; + break; + case CSSM_ALGID_SHA224: + initPtr = (ccInitFcn)CC_SHA224_Init; + updatePtr = (ccUpdateFcn)CC_SHA224_Update; + finalPtr = (ccFinalFcn)CC_SHA224_Final; + digestLen = 28; + break; + case CSSM_ALGID_SHA256: + initPtr = (ccInitFcn)CC_SHA256_Init; + updatePtr = (ccUpdateFcn)CC_SHA256_Update; + finalPtr = (ccFinalFcn)CC_SHA256_Final; + digestLen = 32; + break; + case CSSM_ALGID_SHA384: + initPtr = (ccInitFcn)CC_SHA384_Init; + updatePtr = (ccUpdateFcn)CC_SHA384_Update; + finalPtr = (ccFinalFcn)CC_SHA384_Final; + digestLen = 48; + break; + case CSSM_ALGID_SHA512: + initPtr = (ccInitFcn)CC_SHA512_Init; + updatePtr = (ccUpdateFcn)CC_SHA512_Update; + finalPtr = (ccFinalFcn)CC_SHA512_Final; + digestLen = 64; + break; + case CSSM_ALGID_MD5: + initPtr = (ccInitFcn)CC_MD5_Init; + updatePtr = (ccUpdateFcn)CC_MD5_Update; + finalPtr = (ccFinalFcn)CC_MD5_Final; + digestLen = 16; + break; + default: + printf("***BRRRZAP!\n"); + return 1; + } + + /* random data, const thru the loops */ + initPtext(ptext, PTEXT_SIZE); + + /* start critical timing loop */ + startTime = CFAbsoluteTimeGetCurrent(); + for(loop=0; looploops; loop++) { + initPtr(&ctx); + for(iloop=0; ilooploops * bytesPerLoop; + + /* careful, KByte = 1024, ms = 1/1000 */ + printf(" Digest %.0f bytes : %u ops in %.2f ms; %f ms/op, %.0f KBytes/s\n", + bytesPerLoop, params->loops, + timeSpentMs, timeSpentMs / (double)params->loops, + ((float)totalBytes / 1024.0) / timeSpent); + if(params->dumpDigest) { + dumpDigest(digest, digestLen); + } + return CSSM_OK; +} + +typedef CSSM_RETURN (*testRunFcn)(TestParams *testParams); + +/* + * Static declaration of a test + */ +typedef struct { + const char *testName; + unsigned loops; + testRunFcn run; + char testSpec; // for t=xxx cmd line opt +} TestDefs; + +static TestDefs testDefsCryptKit = +{ "Large data digest, CryptKit", + 1000, + hashDataRateCryptKit, + 'd', +}; + +static TestDefs testDefsCommonCrypto = +{ "Large data digest, CommonCrypto", + 1000, + hashDataRateCommonCrypto, + 'd', +}; + +static void algToAlgId( + HT_Alg alg, + CSSM_ALGORITHMS *algId, + const char **algStr) +{ + switch(alg) { + case HA_MD5: + *algId = CSSM_ALGID_MD5; + *algStr = "MD5"; + break; + case HA_SHA1: + *algId = CSSM_ALGID_SHA1; + *algStr = "SHA1"; + break; + case HA_SHA224: + *algId = CSSM_ALGID_SHA224; + *algStr = "SHA224"; + break; + case HA_SHA256: + *algId = CSSM_ALGID_SHA256; + *algStr = "SHA256"; + break; + case HA_SHA384: + *algId = CSSM_ALGID_SHA384; + *algStr = "SHA384"; + break; + case HA_SHA512: + *algId = CSSM_ALGID_SHA512; + *algStr = "SHA512"; + break; + default: + printf("***algToAlgId screwup\n"); + exit(1); + } +} + +int main(int argc, char **argv) +{ + TestParams testParams; + TestDefs *testDefs = NULL; + CSSM_RETURN crtn; + int arg; + char *argp; + unsigned cmdLoops = 0; // can be specified in cmd line + // if not, use TestDefs.loops + HT_Alg alg; + const char *algStr; + int firstAlg = FIRST_ALG; + int lastAlg = LAST_ALG; + + memset(&testParams, 0, sizeof(testParams)); + + if(argc < 2) { + usage(argv); + } + switch(argv[1][0]) { + case 'c': + testDefs = &testDefsCommonCrypto; + break; + case 'k': + testDefs = &testDefsCryptKit; + break; + default: + usage(argv); + } + + for(arg=2; argtestName); + if(cmdLoops) { + /* user specified */ + testParams.loops = cmdLoops; + } + else { + /* default */ + testParams.loops = testDefs->loops; + } + if((lastAlg > HA_SHA1) && (testDefs == &testDefsCryptKit)) { + /* CryptKit can only do MD5 and SHA1 */ + lastAlg = HA_SHA1; + } + for(alg=firstAlg; alg<=lastAlg; alg++) { + algToAlgId(alg, &testParams.algId, &algStr); + printf(" === %s ===\n", algStr); + crtn = testDefs->run(&testParams); + if(crtn) { + printf("***Error detected in test, somehow....aborting.\n"); + exit(1); + } + } + return 0; +} diff --git a/SecurityTests/cspxutils/keyDate/Makefile b/SecurityTests/cspxutils/keyDate/Makefile new file mode 100644 index 00000000..8e59ebea --- /dev/null +++ b/SecurityTests/cspxutils/keyDate/Makefile @@ -0,0 +1,57 @@ +# +# sample Makefile fragment for csputils projects. +# + +### fill in these: + +# name of executable to build +EXECUTABLE=keyDate +# C++ source (with .cpp extension) +CPSOURCE=keyDate.cpp +# C source (.c extension) +CSOURCE= + +### all of the rest is optional. + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= -framework CoreFoundation + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/keyDate/keyDate.cpp b/SecurityTests/cspxutils/keyDate/keyDate.cpp new file mode 100644 index 00000000..683efca0 --- /dev/null +++ b/SecurityTests/cspxutils/keyDate/keyDate.cpp @@ -0,0 +1,1415 @@ +/* + * keyDate.cpp - test handling of KeyHeader.{StartDate,EndDate} + */ +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include + +/* + * Enumerate algs our own way to allow iteration. + */ +typedef unsigned privAlg; +enum { + ALG_ASC = 1, + ALG_DES, + ALG_AES, + ALG_BFISH, + ALG_RSA, +}; + +#define SYM_FIRST ALG_ASC +#define SYM_LAST ALG_BFISH +#define ASYM_FIRST ALG_RSA +#define ASYM_LAST ALG_RSA + +#define KD_DB_NAME "keyDate.db" +#define KD_KEY_LABEL "keyStoreKey" + +static CSSM_DATA keyLabelData = {12, (uint8 *)KD_KEY_LABEL}; + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" s(ymmetric only)\n"); + printf(" a(symmetric only)\n"); + printf(" t (key store only)\n"); + printf(" D (CSPDL; default is bare CSP)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +#pragma mark - +#pragma mark --- Utilities --- + +/* + * Set a CSSM_DATE to "today plus delta days". Delta can be positive + * or negative. + */ +static void setDate( + CSSM_DATE &cdate, + int deltaDays) +{ + CFAbsoluteTime cfTime = CFAbsoluteTimeGetCurrent(); + float fdelta = 60.0 * 60.0 * 24.0 * deltaDays; + cfTime += fdelta; + CFDateRef cfDate = CFDateCreate(NULL, cfTime); + CssmUniformDate cud(cfDate); + CFRelease(cfDate); + cdate = cud; +} + +/* + * Compare two CSSM_DATEs. Returns nonzero on error. + */ +static int compareDates( + const CSSM_DATE *refDate, // what we tried to set, or NULL + const CSSM_DATE *keyDate, + const char *op, + CSSM_BOOL quiet) +{ + if(refDate == NULL) { + /* make sure key date is empty */ + bool isZero = true; + unsigned char *cp = (unsigned char *)keyDate; + for(unsigned i=0; iDLHandle, + dlDbHand->DBHandle); + if(crtn) { + return testError(quiet); + } + } + crtn = CSSM_GenerateKey(ccHand, + keyUsage, + keyAttr, + &keyLabelData, + NULL, // ACL + symKey); + if(crtn) { + printError("CSSM_GenerateKey", crtn); + return testError(quiet); + } + CSSM_DeleteContext(ccHand); + + CSSM_KEYHEADER &hdr = symKey->KeyHeader; + CSSM_DATE *cdp = NULL; + if(setStartDate) { + cdp = &startDate; + } + if(compareDates(cdp, &hdr.StartDate, keyAlgStr, quiet)) { + return 1; + } + if(setEndDate) { + cdp = &endDate; + } + else { + cdp = NULL; + } + if(compareDates(cdp, &hdr.EndDate, keyAlgStr, quiet)) { + return 1; + } + return 0; +} + +/* + * Common, flexible, error-tolerant key pair generator. + */ +static int genKeyPair( + CSSM_CSP_HANDLE cspHand, + uint32 algorithm, + const char *keyAlgStr, + uint32 keySizeInBits, + CSSM_KEY_PTR pubKey, + CSSM_KEYATTR_FLAGS pubKeyAttr, + CSSM_KEYUSE pubKeyUsage, + CSSM_KEY_PTR privKey, + CSSM_KEYATTR_FLAGS privKeyAttr, + CSSM_KEYUSE privKeyUsage, + CSSM_BOOL quiet, + bool setStartDate, + int startDeltaDays, + bool setEndDate, + int endDeltaDays, + CSSM_DL_DB_HANDLE *dlDbHand = NULL) // optional +{ + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + CSSM_DATE startDate; + CSSM_DATE endDate; + + if(setStartDate) { + setDate(startDate, startDeltaDays); + } + if(setEndDate) { + setDate(endDate, endDeltaDays); + } + + memset(pubKey, 0, sizeof(CSSM_KEY)); + memset(privKey, 0, sizeof(CSSM_KEY)); + + crtn = CSSM_CSP_CreateKeyGenContext(cspHand, + algorithm, + keySizeInBits, + NULL, // Seed + NULL, // Salt + setStartDate ? &startDate : NULL, + setEndDate ? &endDate : NULL, + NULL, // Params + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateKeyGenContext", crtn); + return testError(quiet); + } + + if(dlDbHand) { + /* add in DL/DB to context */ + crtn = cspAddDlDbToContext(ccHand, dlDbHand->DLHandle, + dlDbHand->DBHandle); + if(crtn) { + return testError(quiet); + } + } + + crtn = CSSM_GenerateKeyPair(ccHand, + pubKeyUsage, + pubKeyAttr, + &keyLabelData, + pubKey, + privKeyUsage, + privKeyAttr, + &keyLabelData, // same labels + NULL, // CredAndAclEntry + privKey); + if(crtn) { + printError("CSSM_GenerateKeyPair", crtn); + return testError(quiet); + } + CSSM_DeleteContext(ccHand); + CSSM_KEYHEADER &pubHdr = pubKey->KeyHeader; + CSSM_KEYHEADER &privHdr = privKey->KeyHeader; + CSSM_DATE *cdp = NULL; + if(setStartDate) { + cdp = &startDate; + } + if(compareDates(cdp, &pubHdr.StartDate, keyAlgStr, quiet)) { + return 1; + } + if(compareDates(cdp, &privHdr.StartDate, keyAlgStr, quiet)) { + return 1; + } + if(setEndDate) { + cdp = &endDate; + } + else { + cdp = NULL; + } + if(compareDates(cdp, &pubHdr.EndDate, keyAlgStr, quiet)) { + return 1; + } + if(compareDates(cdp, &privHdr.EndDate, keyAlgStr, quiet)) { + return 1; + } + return 0; +} + +/* map one of our private privAlgs (ALG_DES, etc.) to associated CSSM info. */ +void privAlgToCssm( + privAlg palg, + CSSM_ALGORITHMS *keyAlg, + CSSM_ALGORITHMS *signAlg, // CSSM_ALGID_NONE means incapable + // (e.g., DES) + CSSM_ALGORITHMS *encrAlg, // CSSM_ALGID_NONE means incapable + CSSM_ENCRYPT_MODE *encrMode, + CSSM_PADDING *encrPad, + uint32 *keySizeInBits, + const char **keyAlgStr) +{ + *signAlg = *encrAlg = CSSM_ALGID_NONE; // default + *encrMode = CSSM_ALGMODE_NONE; + *encrPad = CSSM_PADDING_NONE; + switch(palg) { + case ALG_ASC: + *encrAlg = *keyAlg = CSSM_ALGID_ASC; + *keySizeInBits = CSP_ASC_KEY_SIZE_DEFAULT; + *keyAlgStr = "ASC"; + break; + case ALG_DES: + *encrAlg = *keyAlg = CSSM_ALGID_DES; + *keySizeInBits = CSP_DES_KEY_SIZE_DEFAULT; + *keyAlgStr = "DES"; + *encrMode = CSSM_ALGMODE_CBCPadIV8; + *encrPad = CSSM_PADDING_PKCS7; + break; + case ALG_AES: + *encrAlg = *keyAlg = CSSM_ALGID_AES; + *keySizeInBits = CSP_AES_KEY_SIZE_DEFAULT; + *keyAlgStr = "AES"; + *encrMode = CSSM_ALGMODE_CBCPadIV8; + *encrPad = CSSM_PADDING_PKCS7; + break; + case ALG_BFISH: + *encrAlg = *keyAlg = CSSM_ALGID_BLOWFISH; + *keySizeInBits = CSP_BFISH_KEY_SIZE_DEFAULT; + *keyAlgStr = "Blowfish"; + *encrMode = CSSM_ALGMODE_CBCPadIV8; + *encrPad = CSSM_PADDING_PKCS7; + break; + case ALG_RSA: + *keyAlg = CSSM_ALGID_RSA; + *encrAlg = CSSM_ALGID_RSA; + *signAlg = CSSM_ALGID_SHA1WithRSA; + *keySizeInBits = 512; + *keyAlgStr = "RSA"; + *encrPad = CSSM_PADDING_PKCS1; + break; + default: + printf("***BRRZAP! privAlgToCssm needs work\n"); + exit(1); + } + return; +} + +#pragma mark - +#pragma mark --- basic ops to detect INVALID_KEY_{START,END}_DATE --- + +#define PTEXT_SIZE 64 +#define IV_SIZE 16 + +static int doEncrypt( + CSSM_CSP_HANDLE cspHand, + const char *algStr, + CSSM_KEY_PTR key, // session, public + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE encrMode, + CSSM_PADDING encrPad, + CSSM_RETURN expRtn, // expected result + CSSM_BOOL quiet) +{ + uint8 ptextData[PTEXT_SIZE]; + CSSM_DATA ptext = {PTEXT_SIZE, ptextData}; + uint8 someIvData[IV_SIZE]; + CSSM_DATA someIv = {IV_SIZE, someIvData}; + + simpleGenData(&ptext, PTEXT_SIZE, PTEXT_SIZE); + simpleGenData(&someIv, IV_SIZE, IV_SIZE); + + CSSM_CC_HANDLE cryptHand = 0; + CSSM_RETURN crtn; + CSSM_ACCESS_CREDENTIALS creds; + + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + + if(key->KeyHeader.KeyClass == CSSM_KEYCLASS_SESSION_KEY) { + crtn = CSSM_CSP_CreateSymmetricContext(cspHand, + encrAlg, + encrMode, + NULL, // access cred + key, + &someIv, + encrPad, + NULL, // Params + &cryptHand); + if(crtn) { + printError("CSSM_CSP_CreateSymmetricContext", crtn); + return testError(quiet); + } + } + else if(key->KeyHeader.KeyClass == CSSM_KEYCLASS_PUBLIC_KEY) { + crtn = CSSM_CSP_CreateAsymmetricContext(cspHand, + encrAlg, + &creds, // access + key, + encrPad, + &cryptHand); + if(crtn) { + printError("CSSM_CSP_CreateAsymmetricContext", crtn); + return testError(quiet); + } + } + else { + printf("***BRRZAP! Only encrypt with session and public keys\n"); + exit(1); + } + + CSSM_DATA ctext = {0, NULL}; + CSSM_DATA remData = {0, NULL}; + CSSM_SIZE bEncr; + int irtn = 0; + + crtn = CSSM_EncryptData(cryptHand, + &ptext, + 1, + &ctext, + 1, + &bEncr, + &remData); + if(crtn != expRtn) { + if(expRtn == CSSM_OK) { + printError("CSSM_EncryptData", crtn); + printf("Unexpected error encrypting with %s\n", algStr); + } + else { + printf("***Encrypt with %s: expected %s, got %s.\n", + algStr, cssmErrToStr(expRtn), + cssmErrToStr(crtn)); + } + irtn = testError(quiet); + } + appFreeCssmData(&ctext, CSSM_FALSE); + appFreeCssmData(&remData, CSSM_FALSE); + CSSM_DeleteContext(cryptHand); + return irtn; +} + +/* + * Decrypt bad cipher text. If the key is bad the CSP won't even get + * to the ciphertext. Bad ciphertext can result in a number of errors, + * in some cases it can even result in complete success, which we handle + * OK if the key is supposed to be good. + */ + +typedef enum { + DR_BadStartDate, // must be CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE + DR_BadEndDate, // must be CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE + DR_BadData // CSSMERR_CSP_INVALID_DATA. etc. +} DecrResult; + +#define CTEXT_SIZE (PTEXT_SIZE ) + +static int doDecrypt( + CSSM_CSP_HANDLE cspHand, + const char *algStr, + CSSM_KEY_PTR key, // session, private + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE encrMode, + CSSM_PADDING encrPad, + DecrResult expResult, + CSSM_BOOL quiet) +{ + uint8 ctextData[CTEXT_SIZE]; + CSSM_DATA ctext = {CTEXT_SIZE, ctextData}; + uint8 someIvData[IV_SIZE]; + CSSM_DATA someIv = {IV_SIZE, someIvData}; + + /* + * I have not found a way to guarantee decrypt failure here, no matter + * what ctext and IV I specify. We can't just do an encrypt and + * munge because we might be testing a bad (expired) key. + * We might have to redesign, first generating a good key, then an + * expired key from it...? Until then this test is loose about + * handling "key is good" detection. + */ + memset(ctextData, 0, CTEXT_SIZE); // guaranteed bad padding + memset(someIvData, 0, IV_SIZE); + + CSSM_CC_HANDLE cryptHand = 0; + CSSM_RETURN crtn; + CSSM_ACCESS_CREDENTIALS creds; + + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + + if(key->KeyHeader.KeyClass == CSSM_KEYCLASS_SESSION_KEY) { + crtn = CSSM_CSP_CreateSymmetricContext(cspHand, + encrAlg, + encrMode, + NULL, // access cred + key, + &someIv, + encrPad, + NULL, // Params + &cryptHand); + if(crtn) { + printError("CSSM_CSP_CreateSymmetricContext", crtn); + return testError(quiet); + } + } + else if(key->KeyHeader.KeyClass == CSSM_KEYCLASS_PRIVATE_KEY) { + crtn = CSSM_CSP_CreateAsymmetricContext(cspHand, + encrAlg, + &creds, // access + key, + encrPad, + &cryptHand); + if(crtn) { + printError("CSSM_CSP_CreateAsymmetricContext", crtn); + return testError(quiet); + } + } + else { + printf("***BRRZAP! Only decrypt with session and private" + " keys\n"); + exit(1); + } + + CSSM_DATA ptext = {0, NULL}; + CSSM_DATA remData = {0, NULL}; + CSSM_SIZE bDecr; + int irtn = 0; + + crtn = CSSM_DecryptData(cryptHand, + &ctext, + 1, + &ptext, + 1, + &bDecr, + &remData); + switch(expResult) { + case DR_BadStartDate: + if(crtn != CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE) { + printf("***Decrypt with %s: expected INVALID_KEY_START_DATE, " + "got %s.\n", algStr, cssmErrToStr(crtn)); + irtn = testError(quiet); + } + break; + case DR_BadEndDate: + if(crtn != CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE) { + printf("***Decrypt with %s: expected INVALID_KEY_END_DATE, " + "got %s.\n", algStr, cssmErrToStr(crtn)); + irtn = testError(quiet); + } + break; + case DR_BadData: + switch(crtn) { + case CSSM_OK: // good data, seen sometimes + case CSSMERR_CSP_INVALID_DATA: // common case + case CSSMERR_CSP_INTERNAL_ERROR: // default case in CSP's + // throwRsaDsa() :-( + break; + default: + printf("***Decrypt with %s: expected INVALID_DATA or OK, " + "got %s.\n", + algStr, cssmErrToStr(crtn)); + irtn = testError(quiet); + break; + } + break; + } + appFreeCssmData(&ptext, CSSM_FALSE); + appFreeCssmData(&remData, CSSM_FALSE); + CSSM_DeleteContext(cryptHand); + return irtn; +} + +static int doSign( + CSSM_CSP_HANDLE cspHand, + const char *algStr, + CSSM_KEY_PTR key, // private + CSSM_ALGORITHMS sigAlg, + CSSM_RETURN expRtn, // expected result + CSSM_BOOL quiet) +{ + uint8 ptextData[PTEXT_SIZE]; + CSSM_DATA ptext = {PTEXT_SIZE, ptextData}; + CSSM_DATA sig = {0, NULL}; + + simpleGenData(&ptext, PTEXT_SIZE, PTEXT_SIZE); + + CSSM_CC_HANDLE cryptHand = 0; + CSSM_RETURN crtn; + + crtn = CSSM_CSP_CreateSignatureContext(cspHand, + sigAlg, + NULL, // passPhrase + key, + &cryptHand); + if(crtn) { + printError("CSSM_CSP_CreateSignatureContext (1)", crtn); + return testError(quiet); + } + int irtn = 0; + crtn = CSSM_SignData(cryptHand, + &ptext, + 1, + CSSM_ALGID_NONE, + &sig); + if(crtn != expRtn) { + if(expRtn == CSSM_OK) { + printError("CSSM_SignData", crtn); + printf("Unexpected error signing with %s\n", algStr); + } + else { + printf("***Sign with %s: expected %s, got %s.\n", + algStr, cssmErrToStr(expRtn), + cssmErrToStr(crtn)); + } + irtn = testError(quiet); + } + appFreeCssmData(&sig, CSSM_FALSE); + CSSM_DeleteContext(cryptHand); + return irtn; +} + +/* + * Verify bad signature. If the key is bad the CSP won't even get + * to the sig verify. Otherwise expect KD_VERIFY_FAIL_ERR. + */ +#define KD_VERIFY_FAIL_ERR CSSMERR_CSP_VERIFY_FAILED + +static int doVerify( + CSSM_CSP_HANDLE cspHand, + const char *algStr, + CSSM_KEY_PTR key, // private + CSSM_ALGORITHMS sigAlg, + CSSM_RETURN expRtn, // expected result + CSSM_BOOL quiet) +{ + uint8 ptextData[PTEXT_SIZE]; + CSSM_DATA ptext = {PTEXT_SIZE, ptextData}; + uint8 sigData[PTEXT_SIZE]; + CSSM_DATA sig = {PTEXT_SIZE, sigData}; + + simpleGenData(&ptext, PTEXT_SIZE, PTEXT_SIZE); + memset(sigData, 0, PTEXT_SIZE); + + CSSM_CC_HANDLE cryptHand = 0; + CSSM_RETURN crtn; + + crtn = CSSM_CSP_CreateSignatureContext(cspHand, + sigAlg, + NULL, // passPhrase + key, + &cryptHand); + if(crtn) { + printError("CSSM_CSP_CreateSignatureContext (2)", crtn); + return testError(quiet); + } + int irtn = 0; + crtn = CSSM_VerifyData(cryptHand, + &ptext, + 1, + CSSM_ALGID_NONE, + &sig); + if(crtn != expRtn) { + if(expRtn == CSSM_OK) { + printError("CSSM_VerifyData", crtn); + printf("Unexpected error verifying with %s\n", algStr); + } + else { + printf("***Verify with %s: expected %s, got %s.\n", + algStr, cssmErrToStr(expRtn), + cssmErrToStr(crtn)); + } + irtn = testError(quiet); + } + CSSM_DeleteContext(cryptHand); + return irtn; +} + + +#pragma mark - +#pragma mark -- test suites --- + +int doSymTests( + CSSM_CSP_HANDLE cspHand, + privAlg palg, + CSSM_BOOL refKeys, + CSSM_BOOL quiet) +{ + CSSM_ALGORITHMS keyAlg; + CSSM_ALGORITHMS signAlg; + CSSM_ALGORITHMS encrAlg; + CSSM_ENCRYPT_MODE encrMode; + CSSM_PADDING encrPad; + uint32 keySizeInBits; + const char *keyAlgStr; + + privAlgToCssm(palg, &keyAlg, &signAlg, &encrAlg, &encrMode, + &encrPad, &keySizeInBits, &keyAlgStr); + + CSSM_KEY symKey; + int irtn; + CSSM_KEYATTR_FLAGS keyAttr; + if(refKeys) { + keyAttr = CSSM_KEYATTR_RETURN_REF; + } + else { + keyAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + } + + if(!quiet) { + printf("...testing %s with %s keys\n", keyAlgStr, + refKeys ? "Ref" : "Raw"); + printf(" ...verifying empty Dates\n"); + } + irtn = genSymKey(cspHand, &symKey, keyAlg, keyAlgStr, keySizeInBits, + keyAttr, CSSM_KEYUSE_ANY, quiet, + CSSM_FALSE, 0, // no StartDate + CSSM_FALSE, 0); // no EndDate + if(irtn) { + return irtn; + } + irtn = doEncrypt(cspHand, keyAlgStr, &symKey, encrAlg, encrMode, + encrPad, CSSM_OK, quiet); + if(irtn) { + printf("***Failure on encrypting with empty Key Dates\n"); + return irtn; + } + irtn = doDecrypt(cspHand, keyAlgStr, &symKey, encrAlg, encrMode, + encrPad, DR_BadData, quiet); + if(irtn) { + printf("***Failure on decrypting with empty Key Dates\n"); + return irtn; + } + cspFreeKey(cspHand, &symKey); + + if(!quiet) { + printf(" ...verifying Good Dates\n"); + } + irtn = genSymKey(cspHand, &symKey, keyAlg, keyAlgStr, keySizeInBits, + keyAttr, CSSM_KEYUSE_ANY, quiet, + CSSM_TRUE, 0, // StartDate = today + CSSM_TRUE, 1); // EndDate = tomorrow + if(irtn) { + return irtn; + } + irtn = doEncrypt(cspHand, keyAlgStr, &symKey, encrAlg, encrMode, + encrPad, CSSM_OK, quiet); + if(irtn) { + printf("***Failure on encrypting with good Key Dates\n"); + return irtn; + } + irtn = doDecrypt(cspHand, keyAlgStr, &symKey, encrAlg, encrMode, + encrPad, DR_BadData, quiet); + if(irtn) { + printf("***Failure on decrypting with good Key Dates\n"); + return irtn; + } + cspFreeKey(cspHand, &symKey); + + if(!quiet) { + printf(" ...verifying Bad StartDate\n"); + } + irtn = genSymKey(cspHand, &symKey, keyAlg, keyAlgStr, keySizeInBits, + keyAttr, CSSM_KEYUSE_ANY, quiet, + CSSM_TRUE, 1, // StartDate = tomorrow + CSSM_TRUE, 1); // EndDate = tomorrow + if(irtn) { + return irtn; + } + irtn = doEncrypt(cspHand, keyAlgStr, &symKey, encrAlg, encrMode, + encrPad, CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE, quiet); + if(irtn) { + printf("***Failure on encrypting with bad StartDate\n"); + return irtn; + } + irtn = doDecrypt(cspHand, keyAlgStr, &symKey, encrAlg, encrMode, + encrPad, DR_BadStartDate, quiet); + if(irtn) { + printf("***Failure on decrypting with bad StartDate\n"); + return irtn; + } + cspFreeKey(cspHand, &symKey); + + if(!quiet) { + printf(" ...verifying Bad EndDate\n"); + } + irtn = genSymKey(cspHand, &symKey, keyAlg, keyAlgStr, keySizeInBits, + keyAttr, CSSM_KEYUSE_ANY, quiet, + CSSM_TRUE, 0, // StartDate = today + CSSM_TRUE, -1); // EndDate = yesterday + if(irtn) { + return irtn; + } + irtn = doEncrypt(cspHand, keyAlgStr, &symKey, encrAlg, encrMode, + encrPad, CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE, quiet); + if(irtn) { + printf("***Failure on encrypting with bad StartDate\n"); + return irtn; + } + irtn = doDecrypt(cspHand, keyAlgStr, &symKey, encrAlg, encrMode, + encrPad, DR_BadEndDate, quiet); + if(irtn) { + printf("***Failure on decrypting with bad EndDate\n"); + return irtn; + } + cspFreeKey(cspHand, &symKey); + + return 0; +} + +int doAsymTests( + CSSM_CSP_HANDLE cspHand, + privAlg palg, + CSSM_BOOL refKeys, + CSSM_BOOL quiet) +{ + CSSM_ALGORITHMS keyAlg; + CSSM_ALGORITHMS sigAlg; + CSSM_ALGORITHMS encrAlg; + CSSM_ENCRYPT_MODE encrMode; + CSSM_PADDING encrPad; + uint32 keySizeInBits; + const char *keyAlgStr; + + privAlgToCssm(palg, &keyAlg, &sigAlg, &encrAlg, &encrMode, + &encrPad, &keySizeInBits, &keyAlgStr); + + CSSM_KEY pubKey; + CSSM_KEY privKey; + int irtn; + CSSM_KEYATTR_FLAGS pubKeyAttr = CSSM_KEYATTR_EXTRACTABLE; + CSSM_KEYATTR_FLAGS privKeyAttr = CSSM_KEYATTR_EXTRACTABLE; + if(refKeys) { + pubKeyAttr |= CSSM_KEYATTR_RETURN_REF; + privKeyAttr |= CSSM_KEYATTR_RETURN_REF; + } + else { + pubKeyAttr |= CSSM_KEYATTR_RETURN_DATA; + privKeyAttr |= CSSM_KEYATTR_RETURN_DATA; + } + + if(!quiet) { + printf("...testing %s with %s keys\n", keyAlgStr, + refKeys ? "Ref" : "Raw"); + printf(" ...verifying empty Dates\n"); + } + irtn = genKeyPair(cspHand, keyAlg, keyAlgStr, keySizeInBits, + &pubKey, pubKeyAttr, CSSM_KEYUSE_ANY, + &privKey, privKeyAttr, CSSM_KEYUSE_ANY, + quiet, + CSSM_FALSE, 0, // no StartDate + CSSM_FALSE, 0); // no EndDate + if(irtn) { + return irtn; + } + irtn = doEncrypt(cspHand, keyAlgStr, &pubKey, encrAlg, encrMode, + encrPad, CSSM_OK, quiet); + if(irtn) { + printf("***Failure on encrypting with empty Key Dates\n"); + return irtn; + } + irtn = doDecrypt(cspHand, keyAlgStr, &privKey, encrAlg, encrMode, + encrPad, DR_BadData, quiet); + if(irtn) { + printf("***Failure on decrypting with empty Key Dates\n"); + return irtn; + } + irtn = doSign(cspHand, keyAlgStr, &privKey, sigAlg, + CSSM_OK, quiet); + if(irtn) { + printf("***Failure on signing with empty Key Dates\n"); + return irtn; + } + irtn = doVerify(cspHand, keyAlgStr, &pubKey, sigAlg, + KD_VERIFY_FAIL_ERR, quiet); + if(irtn) { + printf("***Failure on verifying with empty Key Dates\n"); + return irtn; + } + cspFreeKey(cspHand, &pubKey); + cspFreeKey(cspHand, &privKey); + + if(!quiet) { + printf(" ...verifying Good Dates\n"); + } + irtn = genKeyPair(cspHand, keyAlg, keyAlgStr, keySizeInBits, + &pubKey, pubKeyAttr, CSSM_KEYUSE_ANY, + &privKey, privKeyAttr, CSSM_KEYUSE_ANY, + quiet, + CSSM_TRUE, 0, // StartDate = today + CSSM_TRUE, 1); // EndDate = tomorrow + if(irtn) { + return irtn; + } + irtn = doEncrypt(cspHand, keyAlgStr, &pubKey, encrAlg, encrMode, + encrPad, CSSM_OK, quiet); + if(irtn) { + printf("***Failure on encrypting with good Key Dates\n"); + return irtn; + } + irtn = doDecrypt(cspHand, keyAlgStr, &privKey, encrAlg, encrMode, + encrPad, DR_BadData, quiet); + if(irtn) { + printf("***Failure on decrypting with Good Key Dates\n"); + return irtn; + } + irtn = doSign(cspHand, keyAlgStr, &privKey, sigAlg, + CSSM_OK, quiet); + if(irtn) { + printf("***Failure on signing with Good Key Dates\n"); + return irtn; + } + irtn = doVerify(cspHand, keyAlgStr, &pubKey, sigAlg, + KD_VERIFY_FAIL_ERR, quiet); + if(irtn) { + printf("***Failure on verifying with Good Key Dates\n"); + return irtn; + } + cspFreeKey(cspHand, &pubKey); + cspFreeKey(cspHand, &privKey); + + if(!quiet) { + printf(" ...verifying Bad StartDate\n"); + } + irtn = genKeyPair(cspHand, keyAlg, keyAlgStr, keySizeInBits, + &pubKey, pubKeyAttr, CSSM_KEYUSE_ANY, + &privKey, privKeyAttr, CSSM_KEYUSE_ANY, + quiet, + CSSM_TRUE, 1, // StartDate = tomorrow + CSSM_TRUE, 1); // EndDate = tomorrow + if(irtn) { + return irtn; + } + irtn = doEncrypt(cspHand, keyAlgStr, &pubKey, encrAlg, encrMode, + encrPad, CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE, quiet); + if(irtn) { + printf("***Failure on encrypting with bad StartDate\n"); + return irtn; + } + irtn = doDecrypt(cspHand, keyAlgStr, &privKey, encrAlg, encrMode, + encrPad, DR_BadStartDate, quiet); + if(irtn) { + printf("***Failure on decrypting with bad StartDate\n"); + return irtn; + } + irtn = doSign(cspHand, keyAlgStr, &privKey, sigAlg, + CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE, quiet); + if(irtn) { + printf("***Failure on signing with bad StartDate\n"); + return irtn; + } + irtn = doVerify(cspHand, keyAlgStr, &pubKey, sigAlg, + CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE, quiet); + if(irtn) { + printf("***Failure on verifying with bad StartDate\n"); + return irtn; + } + cspFreeKey(cspHand, &pubKey); + cspFreeKey(cspHand, &privKey); + + if(!quiet) { + printf(" ...verifying Bad EndDate\n"); + } + irtn = genKeyPair(cspHand, keyAlg, keyAlgStr, keySizeInBits, + &pubKey, pubKeyAttr, CSSM_KEYUSE_ANY, + &privKey, privKeyAttr, CSSM_KEYUSE_ANY, + quiet, + CSSM_TRUE, 0, // StartDate = today + CSSM_TRUE, -1); // EndDate = yesterday + if(irtn) { + return irtn; + } + irtn = doEncrypt(cspHand, keyAlgStr, &pubKey, encrAlg, encrMode, + encrPad, CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE, quiet); + if(irtn) { + printf("***Failure on encrypting with bad EndDate\n"); + return irtn; + } + irtn = doDecrypt(cspHand, keyAlgStr, &privKey, encrAlg, encrMode, + encrPad, DR_BadEndDate, quiet); + if(irtn) { + printf("***Failure on decrypting with bad EndDate\n"); + return irtn; + } + irtn = doSign(cspHand, keyAlgStr, &privKey, sigAlg, + CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE, quiet); + if(irtn) { + printf("***Failure on signing with bad EndDate\n"); + return irtn; + } + irtn = doVerify(cspHand, keyAlgStr, &pubKey, sigAlg, + CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE, quiet); + if(irtn) { + printf("***Failure on verifying with bad EndDate\n"); + return irtn; + } + cspFreeKey(cspHand, &pubKey); + cspFreeKey(cspHand, &privKey); + + return 0; +} + +/* + * fetch stored key from DB, ensure it has same start/end date + */ +static int fetchStoredKey( + CSSM_DL_DB_HANDLE dlDbHand, + CT_KeyType lookupType, + CSSM_KEY_PTR compareKey, + const char *op, + CSSM_BOOL quiet, + CSSM_KEY_PTR *lookupKey) // RETURNED +{ + CSSM_KEY_PTR lookup = cspLookUpKeyByLabel(dlDbHand.DLHandle, + dlDbHand.DBHandle, + &keyLabelData, + lookupType); + if(lookup == NULL) { + printf("%s: Error looking up key in DB\n", op); + return testError(quiet); + } + if(compareDates(&compareKey->KeyHeader.StartDate, + &lookup->KeyHeader.StartDate, + op, quiet)) { + return 1; + } + *lookupKey = lookup; + return 0; +} + +int doStoreTests( + CSSM_CSP_HANDLE cspHand, // must be CSPDL + CSSM_DL_DB_HANDLE dlDbHand, + privAlg palg, + CSSM_BOOL isAsym, + CSSM_BOOL quiet) +{ + CSSM_ALGORITHMS keyAlg; + CSSM_ALGORITHMS signAlg; + CSSM_ALGORITHMS encrAlg; + CSSM_ENCRYPT_MODE encrMode; + CSSM_PADDING encrPad; + uint32 keySizeInBits; + const char *keyAlgStr; + + privAlgToCssm(palg, &keyAlg, &signAlg, &encrAlg, &encrMode, + &encrPad, &keySizeInBits, &keyAlgStr); + + CSSM_KEY symKey; + CSSM_KEY privKey; + CSSM_KEY pubKey; + int irtn; + CSSM_KEY_PTR lookupKey = NULL; // obtained from DB + CSSM_KEY_PTR compareKey; // &symKey or &pubKey + CT_KeyType lookupType; + CSSM_KEYATTR_FLAGS pubKeyAttr = + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | + CSSM_KEYATTR_PERMANENT; + CSSM_KEYATTR_FLAGS privKeyAttr = + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT; + + if(!quiet) { + printf("...testing %s key storage\n", keyAlgStr); + printf(" ...verifying empty Dates\n"); + } + if(isAsym) { + lookupType = CKT_Public; + compareKey = &pubKey; + irtn = genKeyPair(cspHand, keyAlg, keyAlgStr, keySizeInBits, + &pubKey, pubKeyAttr, CSSM_KEYUSE_ANY, + &privKey, privKeyAttr, CSSM_KEYUSE_ANY, + quiet, + CSSM_FALSE, 0, // no StartDate + CSSM_FALSE, 0, // no EndDate + &dlDbHand); + } + else { + lookupType = CKT_Session; + compareKey = &symKey; + irtn = genSymKey(cspHand, &symKey, keyAlg, keyAlgStr, + keySizeInBits, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT, + CSSM_KEYUSE_ANY, quiet, + CSSM_FALSE, 0, // no StartDate + CSSM_FALSE, 0, // no EndDate + &dlDbHand); + } + if(irtn) { + return irtn; + } + + /* + * fetch stored key from DB, ensure it has same start/end date + */ + if(fetchStoredKey(dlDbHand, lookupType, + compareKey, "Store key with empty Dates", quiet, + &lookupKey)) { + return 1; + } + + /* quickie test, use it for encrypt */ + irtn = doEncrypt(cspHand, keyAlgStr, lookupKey, encrAlg, encrMode, + encrPad, CSSM_OK, quiet); + if(irtn) { + printf("***Failure on encrypt, lookup with empty Key Dates\n"); + return irtn; + } + + /* free and delete everything */ + if(isAsym) { + cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle, + &keyLabelData, &pubKey); + cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle, + &keyLabelData, &privKey); + } + else { + cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle, + &keyLabelData, &symKey); + } + cspFreeKey(cspHand, lookupKey); + + /*********************/ + + if(!quiet) { + printf(" ...verifying Good Dates\n"); + } + if(isAsym) { + lookupType = CKT_Public; + compareKey = &pubKey; + irtn = genKeyPair(cspHand, keyAlg, keyAlgStr, keySizeInBits, + &pubKey, pubKeyAttr, CSSM_KEYUSE_ANY, + &privKey, privKeyAttr, CSSM_KEYUSE_ANY, + quiet, + CSSM_TRUE, 0, // StartDate = today + CSSM_TRUE, 1, // EndDate = tomorrow + &dlDbHand); + } + else { + lookupType = CKT_Session; + compareKey = &symKey; + irtn = genSymKey(cspHand, &symKey, keyAlg, keyAlgStr, + keySizeInBits, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT, + CSSM_KEYUSE_ANY, quiet, + CSSM_TRUE, 0, // StartDate = today + CSSM_TRUE, 1, // EndDate = tomorrow + &dlDbHand); + } + if(irtn) { + return irtn; + } + + /* + * fetch stored key from DB, ensure it has same start/end date + */ + if(fetchStoredKey(dlDbHand, lookupType, + compareKey, "Store key with Good Dates", quiet, + &lookupKey)) { + return 1; + } + + /* quickie test, use it for encrypt */ + irtn = doEncrypt(cspHand, keyAlgStr, lookupKey, encrAlg, encrMode, + encrPad, CSSM_OK, quiet); + if(irtn) { + printf("***Failure on encrypt, lookup with Good Key Dates\n"); + return irtn; + } + + /* free and delete everything */ + if(isAsym) { + cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle, + &keyLabelData, &pubKey); + cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle, + &keyLabelData, &privKey); + } + else { + cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle, + &keyLabelData, &symKey); + } + cspFreeKey(cspHand, lookupKey); + + /*********************/ + + if(!quiet) { + printf(" ...verifying Bad StartDate\n"); + } + if(isAsym) { + lookupType = CKT_Public; + compareKey = &pubKey; + irtn = genKeyPair(cspHand, keyAlg, keyAlgStr, keySizeInBits, + &pubKey, pubKeyAttr, CSSM_KEYUSE_ANY, + &privKey, privKeyAttr, CSSM_KEYUSE_ANY, + quiet, + CSSM_TRUE, 1, // StartDate = tomorrow + CSSM_TRUE, 1, // EndDate = tomorrow + &dlDbHand); + } + else { + lookupType = CKT_Session; + compareKey = &symKey; + irtn = genSymKey(cspHand, &symKey, keyAlg, keyAlgStr, + keySizeInBits, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT, + CSSM_KEYUSE_ANY, quiet, + CSSM_TRUE, 1, // StartDate = tomorrow + CSSM_TRUE, 1, // EndDate = tomorrow + &dlDbHand); + } + if(irtn) { + return irtn; + } + + /* + * fetch stored key from DB, ensure it has same start/end date + */ + if(fetchStoredKey(dlDbHand, lookupType, + compareKey, "Store key with Bad StartDate", quiet, + &lookupKey)) { + return 1; + } + + /* quickie test, use it for encrypt */ + irtn = doEncrypt(cspHand, keyAlgStr, lookupKey, encrAlg, encrMode, + encrPad, CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE, quiet); + if(irtn) { + printf("***Failure on encrypt, lookup with Bad Start Dates\n"); + return irtn; + } + + /* free and delete everything */ + if(isAsym) { + cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle, + &keyLabelData, &pubKey); + cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle, + &keyLabelData, &privKey); + } + else { + cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle, + &keyLabelData, &symKey); + } + cspFreeKey(cspHand, lookupKey); + + /*********************/ + + if(!quiet) { + printf(" ...verifying Bad EndDate\n"); + } + if(isAsym) { + lookupType = CKT_Public; + compareKey = &pubKey; + irtn = genKeyPair(cspHand, keyAlg, keyAlgStr, keySizeInBits, + &pubKey, pubKeyAttr, CSSM_KEYUSE_ANY, + &privKey, privKeyAttr, CSSM_KEYUSE_ANY, + quiet, + CSSM_TRUE, 0, // StartDate = today + CSSM_TRUE, -1, // EndDate = yesterday + &dlDbHand); + } + else { + lookupType = CKT_Session; + compareKey = &symKey; + irtn = genSymKey(cspHand, &symKey, keyAlg, keyAlgStr, + keySizeInBits, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT, + CSSM_KEYUSE_ANY, quiet, + CSSM_TRUE, 0, // StartDate = today + CSSM_TRUE, -1, // EndDate = yesterday + &dlDbHand); + } + if(irtn) { + return irtn; + } + + /* + * fetch stored key from DB, ensure it has same start/end date + */ + if(fetchStoredKey(dlDbHand, lookupType, + compareKey, "Store key with Bad EndDate", quiet, + &lookupKey)) { + return 1; + } + + /* quickie test, use it for encrypt */ + irtn = doEncrypt(cspHand, keyAlgStr, lookupKey, encrAlg, encrMode, + encrPad, CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE, quiet); + if(irtn) { + printf("***Failure on encrypt, lookup with Bad End Dates\n"); + return irtn; + } + + /* free and delete everything */ + if(isAsym) { + cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle, + &keyLabelData, &pubKey); + cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle, + &keyLabelData, &privKey); + } + else { + cspDeleteKey(cspHand, dlDbHand.DLHandle, dlDbHand.DBHandle, + &keyLabelData, &symKey); + } + cspFreeKey(cspHand, lookupKey); + + return 0; +} + + +int main(int argc, char **argv) +{ + CSSM_CSP_HANDLE cspHand; + int irtn; + CSSM_DL_DB_HANDLE dlDbHand = {0, 0}; + char dbName[100]; /* KD_DB_NAME_pid */ + + /* user-spec'd variables */ + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL doSym = CSSM_TRUE; + CSSM_BOOL doAsym = CSSM_TRUE; + CSSM_BOOL doKeyStore = CSSM_TRUE; + CSSM_BOOL bareCsp = CSSM_TRUE; + + int arg; + for(arg=1; arg +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "cspdlTesting.h" + +#define USAGE_NAME "noUsage" +#define USAGE_NAME_LEN (strlen(USAGE_NAME)) +#define LOOPS_DEF 10 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" p(ause on each loop)\n"); + printf(" q(uiet)\n"); + printf(" v(erbose))\n"); + exit(1); +} + +static void dumpBuf(uint8 *buf, + unsigned len) +{ + unsigned i; + + printf(" "); + for(i=0; iKeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) { + printf("Hey! this only works on ref keys!!\n"); + exit(1); + } + + /* get raw key */ + crtn = cspWrapKey(cspHand, + refKey, + NULL, // wrappingKey + CSSM_ALGID_NONE, + CSSM_ALGMODE_NONE, + CSSM_KEYBLOB_WRAPPED_FORMAT_NONE, + CSSM_PADDING_NONE, + NULL, // iv + NULL, // descData + &rawKey); + if(crtn) { + return testError(quiet); + } + + /* hash of both keys */ + crtn = cspKeyHash(cspHand, refKey, &refHash); + if(crtn) { + return testError(quiet); + } + else { + if(verbose) { + printf(" ...Ref key hash:\n "); + dumpBuf(refHash->Data, refHash->Length); + } + } + crtn = cspKeyHash(rawCspHand, &rawKey, &rawHash); + if(crtn) { + return testError(quiet); + } + else { + if(verbose) { + printf(" ...Raw key hash:\n "); + dumpBuf(rawHash->Data, rawHash->Length); + } + } + if(!appCompareCssmData(refHash, rawHash)) { + printf("***Key Hash Miscompare!\n"); + return testError(quiet); + } + appFreeCssmData(refHash, CSSM_TRUE); + appFreeCssmData(rawHash, CSSM_TRUE); + cspFreeKey(cspHand, &rawKey); + return 0; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + CSSM_CSP_HANDLE cspHand; + CSSM_CSP_HANDLE rawCspHand; + int rtn = 0; + CSSM_KEY pubKey; + CSSM_KEY privKey; + CSSM_KEY_PTR symKey; + int i; + + /* + * User-spec'd params + */ + unsigned loops = LOOPS_DEF; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL bareCsp = CSSM_TRUE; + CSSM_BOOL doPause = CSSM_FALSE; + + for(arg=1; argEEmsmSY~68UIS qAu0iZ4uD@iG^#3=3Wc#i7UvKss$%81A>WzP@|N?o!ZTd60s#Udt|AHm literal 0 HcmV?d00001 diff --git a/SecurityTests/cspxutils/keyHashAsym/dsaParams_512.der b/SecurityTests/cspxutils/keyHashAsym/dsaParams_512.der new file mode 100644 index 0000000000000000000000000000000000000000..fb8048624d53d856dc39206ce90330dab8b19cfd GIT binary patch literal 160 zcmV;R0AK$wft>IV#7xd=}zR{|9P%ioK5w1=zowXfw6rFwlF0wA zh~j3vP8^dz89QA$t29sDqX}^M(xoT +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "cspdlTesting.h" +#include + +#define USAGE_NAME "noUsage" +#define USAGE_NAME_LEN (strlen(USAGE_NAME)) +#define LOOPS_DEF 10 + +#define DSA_PARAM_FILE "dsaParams_512.der" +#define DH_PARAM_FILE "dhParams_512.der" + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" p(ause on each loop)\n"); + printf(" q(uiet)\n"); + printf(" v(erbose))\n"); + exit(1); +} + +static CSSM_DATA dsa512Params; +static CSSM_DATA dh512Params; + +/* + * Describe parameters for one test iteration. + */ +typedef struct { + CSSM_ALGORITHMS keyAlg; + CSSM_KEYBLOB_FORMAT pubKeyForm; + CSSM_KEYBLOB_FORMAT privKeyForm; + uint32 keySizeInBits; + CSSM_DATA *algParams; // optional +} KeyHashTest; + +KeyHashTest KeyHashTestParams[] = +{ + /* RSA */ + { CSSM_ALGID_RSA, + CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE, + 512, NULL + }, + { CSSM_ALGID_RSA, + CSSM_KEYBLOB_RAW_FORMAT_PKCS1, CSSM_KEYBLOB_RAW_FORMAT_NONE, + 512, NULL + }, + { CSSM_ALGID_RSA, + CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_NONE, + 512, NULL + }, + { CSSM_ALGID_RSA, + CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_PKCS1, + 512, NULL + }, + { CSSM_ALGID_RSA, + CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_PKCS8, + 512, NULL + }, + + /* ECDSA */ + { CSSM_ALGID_ECDSA, + CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE, + 192, NULL + }, + { CSSM_ALGID_ECDSA, + CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_PKCS8, + 256, NULL + }, + { CSSM_ALGID_ECDSA, + CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_PKCS8, + 384, NULL + }, + { CSSM_ALGID_ECDSA, + CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_PKCS8, + 521, NULL + }, + + /* DSA */ + { CSSM_ALGID_DSA, + CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE, + 512, &dsa512Params + }, + { CSSM_ALGID_DSA, + CSSM_KEYBLOB_RAW_FORMAT_FIPS186, CSSM_KEYBLOB_RAW_FORMAT_NONE, + 512, &dsa512Params + }, + { CSSM_ALGID_DSA, + CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_NONE, + 512, &dsa512Params + }, + { CSSM_ALGID_DSA, + CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_FIPS186, + 512, &dsa512Params + }, + { CSSM_ALGID_DSA, + CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_OPENSSL, + 512, &dsa512Params + }, + { CSSM_ALGID_DSA, + CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_PKCS8, + 512, &dsa512Params + }, + { CSSM_ALGID_DSA, + CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_PKCS8, + 512, &dsa512Params + }, + + /* Diffie-Hellman */ + { CSSM_ALGID_DH, + CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE, + 512, &dh512Params + }, + { CSSM_ALGID_DH, + CSSM_KEYBLOB_RAW_FORMAT_PKCS3, CSSM_KEYBLOB_RAW_FORMAT_NONE, + 512, &dh512Params + }, + { CSSM_ALGID_DH, + CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_PKCS3, + 512, &dh512Params + }, + { CSSM_ALGID_DH, + CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_PKCS8, + 512, &dh512Params + }, + { CSSM_ALGID_DH, + CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_NONE, + 512, &dh512Params + }, + { CSSM_ALGID_DH, + CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_PKCS8, + 512, &dh512Params + }, + + /* FEE */ + { CSSM_ALGID_FEE, + CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE, + 127, NULL + }, + { CSSM_ALGID_FEE, + CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING, CSSM_KEYBLOB_RAW_FORMAT_NONE, + 128, NULL + }, + { CSSM_ALGID_FEE, + CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING, + 161, NULL + }, + { CSSM_ALGID_FEE, + CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING, + CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING, + 192, NULL + }, + +}; +#define NUM_TEST_PARAMS\ + (sizeof(KeyHashTestParams) / sizeof(KeyHashTestParams[0])) + +static void dumpBuf(uint8 *buf, + unsigned len) +{ + unsigned i; + + printf(" "); + for(i=0; ikeyAlg), + formStr(testParam->pubKeyForm), + formStr(testParam->privKeyForm)); + +} + +/* + * Generate key pair of specified alg and raw format. + * Alg params are optional, though they are expected to be here + * for DH and DSA. + */ +static CSSM_RETURN genKeyPair( + CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS keyAlg, + uint32 keySize, // in bits + CSSM_KEY_PTR pubKey, + CSSM_KEYBLOB_FORMAT pubFormat, + CSSM_KEY_PTR privKey, + CSSM_KEYBLOB_FORMAT privFormat, + const CSSM_DATA *inParams) // optional +{ + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + CSSM_DATA keyLabelData; + CSSM_RETURN ocrtn = CSSM_OK; + + keyLabelData.Data = (uint8 *)USAGE_NAME, + keyLabelData.Length = USAGE_NAME_LEN; + memset(pubKey, 0, sizeof(CSSM_KEY)); + memset(privKey, 0, sizeof(CSSM_KEY)); + + crtn = CSSM_CSP_CreateKeyGenContext(cspHand, + keyAlg, + keySize, + NULL, // Seed + NULL, // Salt + NULL, // StartDate + NULL, // EndDate + inParams, // Params, may be NULL + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateKeyGenContext", crtn); + return crtn; + } + + /* optional format specifiers */ + if(pubFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE) { + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT, + sizeof(uint32), + CAT_Uint32, + NULL, + pubFormat); + if(crtn) { + printError("AddContextAttribute(" + "CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn); + return crtn; + } + } + if(privFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE) { + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT, + sizeof(uint32), + CAT_Uint32, + NULL, + privFormat); + if(crtn) { + printError("AddContextAttribute(" + "CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT)", crtn); + return crtn; + } + } + CSSM_KEYATTR_FLAGS attrFlags = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + crtn = CSSM_GenerateKeyPair(ccHand, + CSSM_KEYUSE_DERIVE, + attrFlags, + &keyLabelData, + pubKey, + CSSM_KEYUSE_DERIVE, + attrFlags, + &keyLabelData, // same labels + NULL, // CredAndAclEntry + privKey); + if(crtn) { + printError("CSSM_GenerateKeyPair", crtn); + ocrtn = crtn; + } + if(ccHand != 0) { + crtn = CSSM_DeleteContext(ccHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; + } + } + return ocrtn; +} + +/* + * Given two keys (presumably, in this test, one a raw key and + * one an equivalent ref key), calculate the key digest of both of them + * and ensure they're the same. + */ +static int compareKeyHashes( + const CSSM_DATA *key1Hash, + const char *key1Descr, + const CSSM_DATA *key2Hash, + const char *key2Descr, + CSSM_BOOL verbose) +{ + if(appCompareCssmData(key1Hash, key2Hash)) { + return 0; + } + printf("***Key Digest miscompare (%s,%s)***\n", key1Descr, key2Descr); + if(!verbose) { + printf("...%s hash:\n", key1Descr); + dumpBuf(key1Hash->Data, key1Hash->Length); + printf("...%s hash:\n", key2Descr); + dumpBuf(key2Hash->Data, key2Hash->Length); + } + return 1; +} + +/* + * Given a KeyHashTest: + * -- cook up key pair, raw, specified formats + * -- NULL unwrap each raw to ref; + * -- obtain four key digests; + * -- ensure all digests match; + */ +static int doTest( + CSSM_CSP_HANDLE rawCspHand, // generate keys here + CSSM_CSP_HANDLE refCspHand, // null unwrap here + KeyHashTest *testParam, + CSSM_BOOL verbose, + CSSM_BOOL quiet) +{ + CSSM_RETURN crtn; + CSSM_KEY pubKey; + CSSM_KEY privKey; + CSSM_KEY pubKeyRef; + CSSM_KEY privKeyRef; + CSSM_DATA_PTR rawPubHash; + CSSM_DATA_PTR rawPrivHash; + CSSM_DATA_PTR refPubHash; + CSSM_DATA_PTR refPrivHash; + int rtn = 0; + + /* generate key pair, specified raw form */ + crtn = genKeyPair(rawCspHand, + testParam->keyAlg, + testParam->keySizeInBits, + &pubKey, + testParam->pubKeyForm, + &privKey, + testParam->privKeyForm, + testParam->algParams); + if(crtn) { + return testError(quiet); + } + + /* null unwrap both raw keys to ref form */ + crtn = cspRawKeyToRef(refCspHand, &pubKey, &pubKeyRef); + if(crtn) { + return testError(quiet); + } + crtn = cspRawKeyToRef(refCspHand, &privKey, &privKeyRef); + if(crtn) { + return testError(quiet); + } + + /* calculate four key digests */ + crtn = cspKeyHash(rawCspHand, &pubKey, &rawPubHash); + if(crtn) { + return testError(quiet); + } + crtn = cspKeyHash(rawCspHand, &privKey, &rawPrivHash); + if(crtn) { + return testError(quiet); + } + crtn = cspKeyHash(refCspHand, &pubKeyRef, &refPubHash); + if(crtn) { + return testError(quiet); + } + crtn = cspKeyHash(refCspHand, &privKeyRef, &refPrivHash); + if(crtn) { + return testError(quiet); + } + + if(verbose) { + printf("...raw pub key hash:\n"); + dumpBuf(rawPubHash->Data, rawPubHash->Length); + printf("...ref pub key hash:\n"); + dumpBuf(refPubHash->Data, refPubHash->Length); + printf("...raw priv key hash:\n"); + dumpBuf(rawPrivHash->Data, rawPrivHash->Length); + printf("...ref priv key hash:\n"); + dumpBuf(refPrivHash->Data, refPrivHash->Length); + } + + /* compare */ + rtn += compareKeyHashes(rawPubHash, "Raw public", + refPubHash, "Ref public", verbose); + rtn += compareKeyHashes(rawPrivHash, "Raw private", + refPrivHash, "Ref private", verbose); + rtn += compareKeyHashes(refPubHash, "Ref public", + refPrivHash, "Ref private", verbose); + if(rtn) { + rtn = testError(quiet); + } + cspFreeKey(rawCspHand, &pubKey); + cspFreeKey(rawCspHand, &privKey); + cspFreeKey(refCspHand, &pubKeyRef); + cspFreeKey(refCspHand, &privKeyRef); + appFreeCssmData(rawPubHash, CSSM_TRUE); + appFreeCssmData(rawPrivHash, CSSM_TRUE); + appFreeCssmData(refPubHash, CSSM_TRUE); + appFreeCssmData(refPrivHash, CSSM_TRUE); + return rtn; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + CSSM_CSP_HANDLE rawCspHand; // always Raw CSP + CSSM_CSP_HANDLE refCspHand; // CSPDL if !bareCsp + int rtn = 0; + int i; + unsigned len; + + /* + * User-spec'd params + */ + unsigned loops = LOOPS_DEF; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL bareCsp = CSSM_TRUE; + CSSM_BOOL doPause = CSSM_FALSE; + + for(arg=1; arg +#include +#include +#include +#include +#include + +#define kRSAKeySizePrefsDomain "com.apple.crypto" +#define kRSAMaxKeySizePref CFSTR("RSAMaxKeySize") +#define kRSAMacPublicExponentPref CFSTR("RSAMaxPublicExponent") + +static void usage(char **argv) +{ + printf("usage: \n"); + printf(" %s set keysize|pubexpsize \n", argv[0]); + printf(" %s get keysize|pubexpsize\n", argv[0]); + printf(" %s illegal -- set illegally large values for both\n", argv[0]); + exit(1); +} + +int main(int argc, char **argv) +{ + bool doSet = false; + CFStringRef which = NULL; + char *cWhich = NULL; + int ourRtn = 0; + bool doIllegal = false; + + if(argc < 2) { + usage(argv); + } + if(!strcmp(argv[1], "set")) { + doSet = true; + if(argc != 4) { + usage(argv); + } + } + else if(!strcmp(argv[1], "get")) { + if(argc != 3) { + usage(argv); + } + } + else if(!strcmp(argv[1], "illegal")) { + if(argc != 2) { + usage(argv); + } + doIllegal = true; + } + else { + usage(argv); + } + if(!doIllegal) { + if(!strcmp(argv[2], "keysize")) { + which = kRSAMaxKeySizePref; + cWhich = "Max Key Size"; + } + else if(!strcmp(argv[2], "pubexpsize")) { + which = kRSAMacPublicExponentPref; + cWhich = "Max Public Exponent"; + } + else { + usage(argv); + } + } + + if(doSet || doIllegal) { + MutableDictionary *prefs = NULL; + UInt32 iVal = 0; + try { + prefs = new MutableDictionary(kRSAKeySizePrefsDomain, Dictionary::US_System); + } + catch(...) { + /* create a new one */ + prefs = new MutableDictionary(); + } + + if(doIllegal) { + SInt64 bigBad = 0x100000000LL; + CFNumberRef cfVal = CFNumberCreate(NULL, kCFNumberSInt64Type, &bigBad); + prefs->setValue(kRSAMaxKeySizePref, cfVal); + prefs->setValue(kRSAMacPublicExponentPref, cfVal); + } + else { + iVal = atoi(argv[3]); + if(iVal == 0) { + /* this means "remove" */ + prefs->removeValue(which); + } + else { + CFNumberRef cfVal = CFNumberCreate(NULL, kCFNumberSInt32Type, &iVal); + prefs->setValue(which, cfVal); + } + } + bool success = prefs->writePlistToPrefs(kRSAKeySizePrefsDomain, + Dictionary::US_System); + if(success) { + if(doIllegal) { + printf("Both prefs set to 0x100000000LL\n"); + } + else if(iVal == 0) { + printf("%s preference removed.\n", cWhich); + } + else { + printf("%s set to %lu\n", cWhich, (unsigned long) iVal); + } + } + else { + printf("***Error setting %s\n", cWhich); + ourRtn = -1; + } + delete prefs; + } + else { + try { + Dictionary prefs(kRSAKeySizePrefsDomain, Dictionary::US_System); + CFNumberRef cfVal = (CFNumberRef)prefs.getValue(which); + if(cfVal == NULL) { + printf("...no %s pref found\n", cWhich); + return 0; + } + if(CFGetTypeID(cfVal) != CFNumberGetTypeID()) { + printf("***Badly formatted %s pref (1)\n", cWhich); + return -1; + } + UInt32 u; + if(!CFNumberGetValue(cfVal, kCFNumberSInt32Type, &u)) { + printf("***Badly formatted %s pref (2)\n", cWhich); + } + printf("%s preference is currently %lu\n", cWhich, (unsigned long)u); + } + catch(...) { + printf("...no %s prefs found\n", kRSAKeySizePrefsDomain); + } + } + return 0; +} diff --git a/SecurityTests/cspxutils/keyStore/Makefile b/SecurityTests/cspxutils/keyStore/Makefile new file mode 100755 index 00000000..5f52885b --- /dev/null +++ b/SecurityTests/cspxutils/keyStore/Makefile @@ -0,0 +1,55 @@ +# name of executable to build +EXECUTABLE=keyStore +# C++ source (with .cpp extension) +CPSOURCE= +# C source (.c extension) +CSOURCE= keyStore.c + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +#PROJ_LDFLAGS= -lMallocDebug +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/keyStore/keyStore.c b/SecurityTests/cspxutils/keyStore/keyStore.c new file mode 100644 index 00000000..7a40b68c --- /dev/null +++ b/SecurityTests/cspxutils/keyStore/keyStore.c @@ -0,0 +1,816 @@ +/* Copyright (c) 2001,2003-2006,2008 Apple Inc. + * + * keyStore.c - basic key pair store/lookup routines. + * + * create key pair, varying pub is permanent, priv is permanent; + * sign some data with priv; + * lookUpPub = lookup pub by label; + * vfy with lookUpPub; + * lookUpPriv = lookup priv by label; + * if(privIsPerm) { + * ensure lookUpPriv == priv; + * freeKey(lookUpPriv); + * obtainedPriv = obtainPubFromPriv(lookUpPub); + * ensure obtainedPriv == priv; + * freeKey(obtainedPriv); + * delete priv; // cspwrap does implicit freeKey here... + * } + * else { + * free priv; + * } + * lookUpPriv = lookup priv by label; verify fail; + * lookUpPriv = obtainPubFromPriv(pub); verify fail; + * freeKey(lookUpPub); + * if pub is permament { + * lookUpPub = lookup pub by label; verify OK; + * deleteKey(lookUpPub); + * lookUpPub = lookup pub by label; verify fail; + * } + * lookUpPub = lookup pub by label; verify fail; + */ + +#include +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "cspdlTesting.h" + +#define LOOPS_DEF 10 +#define MAX_DATA_SIZE 100 +#define DB_NAME "keyStore.db" + +/* can't lookup non-permanent keys! */ +#define FORCE_PUB_PERMANENT 0 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" r(RSA; default = FEE)\n"); + printf(" p(ermanent keys, implies l=1)\n"); + printf(" k=keyChainFile\n"); + printf(" n(o sign/verify)\n"); + printf(" N(o lookup of nonexistent keys)\n"); + printf(" x (privKey always extractable)\n"); + printf(" P(ause for MallocDebug)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +#define FEE_PRIV_DATA_SIZE 20 + +/* + * NULL wrap, error tolerant. + */ +CSSM_RETURN cspNullWrapKey( + CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *refKey, + CSSM_KEY_PTR rawKey) // RETURNED on success, caller must FreeKey +{ + CSSM_CC_HANDLE ccHand; + CSSM_RETURN crtn; + CSSM_ACCESS_CREDENTIALS creds; + CSSM_DATA descData = {0, 0}; + + memset(rawKey, 0, sizeof(CSSM_KEY)); + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + crtn = CSSM_CSP_CreateSymmetricContext(cspHand, + CSSM_ALGID_NONE, + CSSM_ALGMODE_NONE, + &creds, // passPhrase, + NULL, // wrappingKey, + NULL, // initVector, + CSSM_PADDING_NONE, + 0, // Params + &ccHand); + if(crtn) { + printError("cspNullWrapKey/CreateContext", crtn); + return crtn; + } + crtn = CSSM_WrapKey(ccHand, + &creds, + refKey, + &descData, // DescriptiveData + rawKey); + if(CSSM_DeleteContext(ccHand)) { + printf("CSSM_DeleteContext failure\n"); + } + return crtn; +} + + +/* + * Generate key pair, default size. This is like cspGenKeyPair in cspwrap.c, + * tweaked for this test To allow varying permanent attribute. + */ +static CSSM_RETURN genKeyPair(CSSM_CSP_HANDLE cspHand, + CSSM_DL_HANDLE dlHand, + CSSM_DB_HANDLE dbHand, + const CSSM_DATA_PTR keyLabel, + CSSM_KEY_PTR pubKey, // mallocd by caller + uint32 pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + uint32 pubKeyAttr, + CSSM_KEY_PTR privKey, // mallocd by caller + uint32 privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc. + uint32 privKeyAttr, + uint32 keyGenAlg) +{ + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + CSSM_RETURN ocrtn = CSSM_OK; + uint32 keySize; + + if(keyGenAlg == CSSM_ALGID_FEE) { + keySize = CSP_FEE_KEY_SIZE_DEFAULT; + } + else { + keySize = CSP_RSA_KEY_SIZE_DEFAULT; + } + memset(pubKey, 0, sizeof(CSSM_KEY)); + memset(privKey, 0, sizeof(CSSM_KEY)); + + crtn = CSSM_CSP_CreateKeyGenContext(cspHand, + keyGenAlg, + keySize, + NULL, // Seed + NULL, // Salt + NULL, // StartDate + NULL, // EndDate + NULL, // Params + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateKeyGenContext", crtn); + ocrtn = crtn; + goto abort; + } + + /* add in DL/DB to context */ + crtn = cspAddDlDbToContext(ccHand, dlHand, dbHand); + if(crtn) { + ocrtn = crtn; + goto abort; + } + crtn = CSSM_GenerateKeyPair(ccHand, + pubKeyUsage, + pubKeyAttr, + keyLabel, + pubKey, + privKeyUsage, + privKeyAttr, + keyLabel, // same labels + NULL, // cred/acl + privKey); + if(crtn) { + printError("CSSM_GenerateKeyPair", crtn); + ocrtn = crtn; + goto abort; + } + + /* basic checks...*/ + if(privKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) { + printf("privKey blob type: exp %u got %u\n", + CSSM_KEYBLOB_REFERENCE, (unsigned)privKey->KeyHeader.BlobType); + } + if(pubKeyAttr & CSSM_KEYATTR_RETURN_REF) { + if(pubKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) { + printf("pubKey blob type: exp %u got %u\n", + CSSM_KEYBLOB_REFERENCE, (unsigned)privKey->KeyHeader.BlobType); + ocrtn = -1; + goto abort; + } + } + else { + if(pubKey->KeyHeader.BlobType != CSSM_KEYBLOB_RAW) { + printf("pubKey blob type: exp %u got %u\n", + CSSM_KEYBLOB_RAW, (unsigned)privKey->KeyHeader.BlobType); + ocrtn = -1; + goto abort; + } + } + +abort: + if(ccHand != 0) { + crtn = CSSM_DeleteContext(ccHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = crtn; + } + } + return ocrtn; +} + +#define KEY_LABEL "testKey" + +/* + * when true, keyref in key obtained from DL differs from + * keyref in key from CSP + */ +#define DL_REF_KEYS_DIFFER 1 + +/* + * ObtainPrivateKeyFromPublicKey doesn't work yet + */ +#define DO_OBTAIN_FROM_PUB CSPDL_OBTAIN_PRIV_FROM_PUB + +/* we're assumed to be logged in for access to private objects */ +static int doTest(CSSM_CSP_HANDLE cspHand, + CSSM_DL_HANDLE dlHand, + CSSM_DB_HANDLE dbHand, + CSSM_BOOL pubIsPerm, // pub is permanent + CSSM_BOOL privIsPerm, // priv is permanent + CSSM_BOOL privIsExtractable, + CSSM_BOOL permKeys, // leave them in the KC + CSSM_BOOL doSignVerify, + CSSM_BOOL doFailedLookup, + CSSM_DATA_PTR ptext, + CSSM_BOOL verbose, + CSSM_BOOL quiet, + uint32 keyGenAlg, + uint32 sigAlg) +{ + CSSM_KEY pubKey; // from GenerateKeyPair + CSSM_KEY privKey; + CSSM_KEY_PTR lookUpPub; // from cspLookUpKeyByLabel, etc. + CSSM_KEY_PTR lookUpPriv; + CSSM_RETURN crtn; + CSSM_DATA sig; + CSSM_DATA labelData; + CSSM_KEY obtainedPriv; + uint32 pubAttr; + uint32 privAttr; + CSSM_KEY rawPrivKey; + labelData.Data = (uint8 *)KEY_LABEL; + labelData.Length = strlen(KEY_LABEL); + CSSM_BOOL doLookup; + + /* create key pair */ + if(verbose) { + printf(" ...generating key pair (pubIsPerm %d privIsPerm %d privIsExtract" + " %d)\n", (int)pubIsPerm, (int)privIsPerm, (int)privIsExtractable); + } + pubAttr = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_REF; + if(pubIsPerm) { + pubAttr |= CSSM_KEYATTR_PERMANENT; + } + + /* + * To use a NULL wrap to test detection of !EXTRACTABLE, we're relying on + * being able to create !SENSITIVE private keys. We'll make 'em sensitive + * if we're not trying to null wrap them. + */ + privAttr = CSSM_KEYATTR_RETURN_REF; + if(privIsPerm) { + privAttr |= CSSM_KEYATTR_PERMANENT; + } + if(privIsExtractable) { + privAttr |= CSSM_KEYATTR_EXTRACTABLE; + } + else { + privAttr |= CSSM_KEYATTR_SENSITIVE; + } + #if CSPDL_KEYATTR_PRIVATE + privAttr |= CSSM_KEYATTR_PRIVATE; + #endif + crtn = genKeyPair(cspHand, + dlHand, + dbHand, + &labelData, + &pubKey, + CSSM_KEYUSE_VERIFY, // pubKeyUsage + pubAttr, + &privKey, + CSSM_KEYUSE_SIGN, + privAttr, + keyGenAlg); + if(crtn) { + return testError(quiet); + } + + /* lookUpPub = lookup pub by label; */ + doLookup = CSSM_TRUE; + if(verbose) { + if(pubIsPerm) { + printf(" ...lookup pub by label\n"); + } + else { + if(doFailedLookup) { + printf(" ...lookup (nonexistent) pub by label\n"); + } + else { + doLookup = CSSM_FALSE; + lookUpPub = NULL; + } + } + } + if(doLookup) { + lookUpPub = cspLookUpKeyByLabel(dlHand, dbHand, &labelData, CKT_Public); + } + if(pubIsPerm) { + if(lookUpPub == NULL) { + printf("lookup pub by label failed\n"); + return testError(quiet); + } + + /* sign some data with priv; */ + sig.Data = NULL; + sig.Length = 0; + if(doSignVerify) { + if(cspSign(cspHand, + sigAlg, + &privKey, + ptext, + &sig)) { + return testError(quiet); + } + } + /* verify header compare */ + if(memcmp(&lookUpPub->KeyHeader, &pubKey.KeyHeader, + sizeof(CSSM_KEYHEADER))) { + printf("**pubKey header miscompare\n"); + return testError(quiet); + } + + /* vfy with lookUpPub; */ + if(doSignVerify) { + if(cspSigVerify(cspHand, + sigAlg, + lookUpPub, + ptext, + &sig, + CSSM_OK)) { + return testError(quiet); + } + + CSSM_FREE(sig.Data); + sig.Data = NULL; + sig.Data = 0; + } + } + else { + if(doLookup && (lookUpPub != NULL)) { + printf("***Unexpected success on cspLookUpKeyByLabel(pub, not perm)\n"); + return testError(quiet); + } + } + + /* + * Ensure proper behavior of extractable bit + */ + if(verbose) { + printf(" ...null wrap %s private key\n", + privIsExtractable ? "EXTRACTABLE" : "!EXTRACTABLE"); + } + crtn = cspNullWrapKey(cspHand, &privKey, &rawPrivKey); + if(privIsExtractable) { + if(crtn) { + printError("Null Wrap(extractable private key)", crtn); + return testError(quiet); + } + if(verbose) { + printf(" ...free rawPrivKey\n"); + } + cspFreeKey(cspHand, &rawPrivKey); + } + else { + if(crtn != CSSMERR_CSP_INVALID_KEYATTR_MASK) { + printError("Null Wrap of !extractable private key: expected " + "INVALID_KEYATTR_MASK, got", crtn); + if(crtn == CSSM_OK) { + cspFreeKey(cspHand, &rawPrivKey); + } + return testError(quiet); + } + } + /* lookUpPriv = lookup priv by label; ensure == privKey; */ + doLookup = CSSM_TRUE; + if(verbose) { + if(privIsPerm) { + printf(" ...lookup priv by label\n"); + } + else { + if(doFailedLookup) { + printf(" ...lookup (nonexistent) priv by label\n"); + } + else { + doLookup = CSSM_FALSE; + lookUpPriv = NULL; + } + } + } + if(doLookup) { + lookUpPriv = cspLookUpKeyByLabel(dlHand, dbHand, &labelData, CKT_Private); + } + if(privIsPerm) { + if(lookUpPriv == NULL) { + printf("lookup priv by label failed\n"); + return testError(quiet); + } + + /* note we "know" that both keys are ref keys...*/ + if(lookUpPriv->KeyData.Length != privKey.KeyData.Length) { + printf("priv key data length mismatch\n"); + return testError(quiet); + } + #if DL_REF_KEYS_DIFFER + if(!memcmp(lookUpPriv->KeyData.Data, privKey.KeyData.Data, + privKey.KeyData.Length)) { + printf("priv key ref data mismatch\n"); + return testError(quiet); + } + #else /* DL_REF_KEYS_DIFFER */ + if(memcmp(lookUpPriv->KeyData.Data, privKey.KeyData.Data, + privKey.KeyData.Length)) { + printf("unexpected priv key ref data match\n"); + return testError(quiet); + } + #endif /* DL_REF_KEYS_DIFFER */ + + /* verify header compare in any case */ + if(memcmp(&lookUpPriv->KeyHeader, &privKey.KeyHeader, + sizeof(CSSM_KEYHEADER))) { + printf("**privKey header miscompare\n"); + return testError(quiet); + } + + /* sign with lookUpPriv, verify with pubKey */ + sig.Data = NULL; + sig.Length = 0; + if(doSignVerify) { + if(verbose) { + printf(" ...sign with lookup priv\n"); + } + if(cspSign(cspHand, + sigAlg, + lookUpPriv, + ptext, + &sig)) { + return testError(quiet); + } + if(verbose) { + printf(" ...verify with pub\n"); + } + if(cspSigVerify(cspHand, + sigAlg, + &pubKey, + ptext, + &sig, + CSSM_OK)) { + printf("***sign with lookUpPriv, vfy with pub FAILED\n"); + return testError(quiet); + } + CSSM_FREE(sig.Data); + sig.Data = NULL; + sig.Data = 0; + } + + /* free lookUpPriv from cache, but it's permanent */ + if(verbose) { + printf(" ...free lookupPriv\n"); + } + if(cspFreeKey(cspHand, lookUpPriv)) { + printf("Error on cspFreeKey(lookUpPriv)\n"); + return testError(quiet); + } + CSSM_FREE(lookUpPriv); // mallocd during lookup + lookUpPriv = NULL; + + #if DO_OBTAIN_FROM_PUB + /* obtainedPriv = obtainPubFromPriv(pub); ensure == priv; */ + if(verbose) { + printf(" ...ObtainPrivateKeyFromPublicKey\n"); + } + obtainedPriv.KeyData.Data = NULL; + obtainedPriv.KeyData.Length = 0; + crtn = CSSM_CSP_ObtainPrivateKeyFromPublicKey(cspHand, + lookUpPub, + &obtainedPriv); + if(crtn) { + printError("ObtainPrivateKeyFromPublicKey", crtn); + return testError(quiet); + } + + /* free obtainedPriv from cache, but it's permanent */ + if(verbose) { + printf(" ...free obtainedPriv\n"); + } + if(cspFreeKey(cspHand, &obtainedPriv)) { + printf("Error on cspFreeKey(obtainedPriv)\n"); + return testError(quiet); + } + + #endif /* DO_OBTAIN_FROM_PUB */ + + if(!permKeys) { + /* delete priv - implies freeKey as well */ + if(verbose) { + printf(" ...delete privKey\n"); + } + crtn = cspDeleteKey(cspHand, dlHand, dbHand, &labelData, &privKey); + if(crtn) { + printf("Error deleting priv\n"); + return testError(quiet); + } + + /* lookUpPriv = lookup priv by label; verify fail; */ + if(doFailedLookup) { + if(verbose) { + printf(" ...lookup (nonexistent) priv by label\n"); + } + lookUpPriv = cspLookUpKeyByLabel(dlHand, dbHand, &labelData, CKT_Private); + if(lookUpPriv != NULL) { + printf("Unexpected success on cspLookUpKeyByLabel(priv)\n"); + return testError(quiet); + } + } + else { + lookUpPriv = NULL; + } + } + } + else if(doLookup) { + /* !privIsPerm - just free it and it's all gone */ + if(lookUpPriv != NULL) { + printf("***Unexpected success on cspLookUpKeyByLabel(priv, not perm)\n"); + return testError(quiet); + } + if(verbose) { + printf(" ...free privKey\n"); + } + if(cspFreeKey(cspHand, &privKey)) { + printf("Error on cspFreeKey(privKey)\n"); + return testError(quiet); + } + } + /* CSP, DL have no knowledge of privKey or its variations */ + + /* obtainedPriv = obtainPubFromPriv(pub); verify fail;*/ + /* Note this should be safe even if DO_OBTAIN_FROM_PUB == 0 */ + obtainedPriv.KeyData.Data = NULL; + obtainedPriv.KeyData.Length = 0; + if(verbose) { + printf(" ...obtain (nonexistent) priv by public\n"); + } + crtn = CSSM_CSP_ObtainPrivateKeyFromPublicKey(cspHand, + &pubKey, + &obtainedPriv); + switch(crtn) { + case CSSM_OK: + printf("Unexpected success on ObtainPrivateKeyFromPublicKey\n"); + return testError(quiet); + case CSSMERR_CSP_PRIVATE_KEY_NOT_FOUND: + break; + #if !CSPDL_OBTAIN_PRIV_FROM_PUB + case CSSMERR_CSP_FUNCTION_NOT_IMPLEMENTED: + /* OK */ + break; + #endif + default: + printf("Unexpected err ObtainPrivateKeyFromPublicKey\n"); + printError("got this", crtn); + return testError(quiet); + } + + /* free one or both copies of pub as appropriate */ + if(verbose) { + printf(" ...free pubKey\n"); + } + crtn = cspFreeKey(cspHand, &pubKey); + if(crtn) { + printf("Error freeing pubKey\n"); + return testError(quiet); + } + if(pubIsPerm) { + if(verbose) { + printf(" ...free lookUpPub\n"); + } + crtn = cspFreeKey(cspHand, lookUpPub); + if(crtn) { + printf("Error freeing lookUpPub\n"); + return testError(quiet); + } + } + if(lookUpPub) { + CSSM_FREE(lookUpPub); // mallocd by lookup in any case + } + + if(pubIsPerm) { + /* pub should still be there in DL */ + /* lookUpPub = lookup pub by label; verify OK; */ + if(verbose) { + printf(" ...lookup pub by label (2)\n"); + } + lookUpPub = cspLookUpKeyByLabel(dlHand, dbHand, &labelData, CKT_Public); + if(lookUpPub == NULL) { + printf("lookup pub by label (2) failed\n"); + return testError(quiet); + } + + if(!permKeys) { + /* now really delete it */ + if(verbose) { + printf(" ...delete lookUpPub\n"); + } + crtn = cspDeleteKey(cspHand, dlHand, dbHand, &labelData, lookUpPub); + if(crtn) { + printf("Error deleting lookUpPub\n"); + return testError(quiet); + } + CSSM_FREE(lookUpPub); // mallocd by lookup + } + } + /* else freeKey should have removed all trace */ + + if(!permKeys && doFailedLookup) { + /* lookUpPub = lookup pub by label; verify fail; */ + if(verbose) { + printf(" ...lookup (nonexistent) pub by label\n"); + } + lookUpPub = cspLookUpKeyByLabel(dlHand, dbHand, &labelData, CKT_Public); + if(lookUpPub != NULL) { + printf("Unexpected success on cspLookUpKeyByLabel(pub) (2)\n"); + return testError(quiet); + } + } + return 0; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + CSSM_DATA ptext; + CSSM_CSP_HANDLE cspHand; + CSSM_DB_HANDLE dbHand; + CSSM_DL_HANDLE dlHand; + CSSM_BOOL pubIsPerm; + CSSM_BOOL privIsPerm; + CSSM_BOOL privIsExtractable; + uint32 keyGenAlg = CSSM_ALGID_FEE; + uint32 sigAlg = CSSM_ALGID_FEE_MD5; + int rtn = 0; + CSSM_RETURN crtn; + + /* + * User-spec'd params + */ + unsigned loops = LOOPS_DEF; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL permKeys = CSSM_FALSE; + char dbName[100]; /* DB_NAME_pid */ + CSSM_BOOL useExistDb = CSSM_FALSE; + CSSM_BOOL doPause = CSSM_FALSE; + CSSM_BOOL doSignVerify = CSSM_TRUE; + CSSM_BOOL doFailedLookup = CSSM_TRUE; + CSSM_BOOL privAlwaysExtractable = CSSM_FALSE; + + dbName[0] = '\0'; + + for(arg=1; arg +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "cspdlTesting.h" + +#define LOOPS_DEF 10 +#define DB_NAME "keyStore.db" + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" r(RSA; default = FEE)\n"); + printf(" k=keyChainFile\n"); + printf(" P(ause for MallocDebug)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +#define FEE_PRIV_DATA_SIZE 20 + +/* + * Generate key pair, default size. This is like cspGenKeyPair in cspwrap.c, + * tweaked for this test To allow varying permanent attribute. + */ +static CSSM_RETURN genKeyPair(CSSM_CSP_HANDLE cspHand, + CSSM_DL_HANDLE dlHand, + CSSM_DB_HANDLE dbHand, + const CSSM_DATA_PTR keyLabel, + CSSM_KEY_PTR pubKey, // mallocd by caller + uint32 pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + uint32 pubKeyAttr, + CSSM_KEY_PTR privKey, // mallocd by caller + uint32 privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc. + uint32 privKeyAttr, + uint32 keyGenAlg) +{ + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + CSSM_RETURN ocrtn = CSSM_OK; + uint32 keySize; + + if(keyGenAlg == CSSM_ALGID_FEE) { + keySize = CSP_FEE_KEY_SIZE_DEFAULT; + } + else { + keySize = CSP_RSA_KEY_SIZE_DEFAULT; + } + memset(pubKey, 0, sizeof(CSSM_KEY)); + memset(privKey, 0, sizeof(CSSM_KEY)); + + crtn = CSSM_CSP_CreateKeyGenContext(cspHand, + keyGenAlg, + keySize, + NULL, // Seed + NULL, // Salt + NULL, // StartDate + NULL, // EndDate + NULL, // Params + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateKeyGenContext", crtn); + ocrtn = crtn; + goto abort; + } + + /* add in DL/DB to context */ + crtn = cspAddDlDbToContext(ccHand, dlHand, dbHand); + if(crtn) { + ocrtn = crtn; + goto abort; + } + crtn = CSSM_GenerateKeyPair(ccHand, + pubKeyUsage, + pubKeyAttr, + keyLabel, + pubKey, + privKeyUsage, + privKeyAttr, + keyLabel, // same labels + NULL, // cred/acl + privKey); + if(crtn) { + printError("CSSM_GenerateKeyPair", crtn); + ocrtn = crtn; + goto abort; + } + + /* basic checks...*/ + if(privKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) { + printf("privKey blob type: exp %u got %u\n", + CSSM_KEYBLOB_REFERENCE, (unsigned)privKey->KeyHeader.BlobType); + } + if(pubKeyAttr & CSSM_KEYATTR_RETURN_REF) { + if(pubKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) { + printf("pubKey blob type: exp %u got %u\n", + CSSM_KEYBLOB_REFERENCE, (unsigned)privKey->KeyHeader.BlobType); + ocrtn = -1; + goto abort; + } + } + else { + if(pubKey->KeyHeader.BlobType != CSSM_KEYBLOB_RAW) { + printf("pubKey blob type: exp %u got %u\n", + CSSM_KEYBLOB_RAW, (unsigned)privKey->KeyHeader.BlobType); + ocrtn = -1; + goto abort; + } + } + +abort: + if(ccHand != 0) { + crtn = CSSM_DeleteContext(ccHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = crtn; + } + } + return ocrtn; +} + +#define KEY_LABEL "testKey" + +static int doTest(CSSM_CSP_HANDLE cspHand, + CSSM_DL_HANDLE dlHand, + CSSM_DB_HANDLE dbHand, + CSSM_BOOL pubIsPerm, // pub is permanent + CSSM_BOOL privIsPerm, // priv is permanent + CSSM_BOOL privIsExtractable, + CSSM_BOOL permKeys, // leave them in the KC + CSSM_BOOL verbose, + CSSM_BOOL quiet, + uint32 keyGenAlg) +{ + CSSM_KEY pubKey; // from GenerateKeyPair + CSSM_KEY privKey; + CSSM_KEY_PTR lookUpPub; // from cspLookUpKeyByLabel, etc. + CSSM_KEY_PTR lookUpPriv; + CSSM_RETURN crtn; + CSSM_DATA labelData; + uint32 pubAttr; + uint32 privAttr; + labelData.Data = (uint8 *)KEY_LABEL; + labelData.Length = strlen(KEY_LABEL); + + /* create key pair */ + if(verbose) { + printf(" ...generating key pair (pubIsPerm %d privIsPerm %d privIsExtract" + " %d)\n", (int)pubIsPerm, (int)privIsPerm, (int)privIsExtractable); + } + pubAttr = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_REF; + if(pubIsPerm) { + pubAttr |= CSSM_KEYATTR_PERMANENT; + } + + /* + * To use a NULL wrap to test detection of !EXTRACTABLE, we're relying on + * being able to create !SENSITIVE private keys. We'll make 'em sensitive + * if we're not trying to null wrap them. + */ + privAttr = CSSM_KEYATTR_RETURN_REF; + if(privIsPerm) { + privAttr |= CSSM_KEYATTR_PERMANENT; + } + if(privIsExtractable) { + privAttr |= CSSM_KEYATTR_EXTRACTABLE; + } + else { + privAttr |= CSSM_KEYATTR_SENSITIVE; + } + #if CSPDL_KEYATTR_PRIVATE + privAttr |= CSSM_KEYATTR_PRIVATE; + #endif + crtn = genKeyPair(cspHand, + dlHand, + dbHand, + &labelData, + &pubKey, + CSSM_KEYUSE_VERIFY, // pubKeyUsage + pubAttr, + &privKey, + CSSM_KEYUSE_SIGN, + privAttr, + keyGenAlg); + if(crtn) { + return testError(quiet); + } + + /* lookUpPub = lookup pub by label; */ + if(verbose) { + if(pubIsPerm) { + printf(" ...lookup pub by label\n"); + } + else { + printf(" ...lookup (nonexistent) pub by label\n"); + } + } + lookUpPub = cspLookUpKeyByLabel(dlHand, dbHand, &labelData, CKT_Public); + if(pubIsPerm) { + if(lookUpPub == NULL) { + printf("lookup pub by label failed\n"); + return testError(quiet); + } + } + else { + if(lookUpPub != NULL) { + printf("***Unexpected success on cspLookUpKeyByLabel(pub, not perm)\n"); + return testError(quiet); + } + } + + /* lookUpPriv = lookup priv by label; ensure == privKey; */ + if(verbose) { + if(privIsPerm) { + printf(" ...lookup priv by label\n"); + } + else { + printf(" ...lookup (nonexistent) priv by label\n"); + } + } + lookUpPriv = cspLookUpKeyByLabel(dlHand, dbHand, &labelData, CKT_Private); + if(privIsPerm) { + if(lookUpPriv == NULL) { + printf("lookup priv by label failed\n"); + return testError(quiet); + } + + /* free lookUpPriv from cache, but it's permanent */ + if(verbose) { + printf(" ...free lookupPriv\n"); + } + if(cspFreeKey(cspHand, lookUpPriv)) { + printf("Error on cspFreeKey(lookUpPriv)\n"); + return testError(quiet); + } + CSSM_FREE(lookUpPriv); // mallocd during lookup + lookUpPriv = NULL; + + if(!permKeys) { + /* delete priv - implies freeKey as well */ + if(verbose) { + printf(" ...delete privKey\n"); + } + crtn = cspDeleteKey(cspHand, dlHand, dbHand, &labelData, &privKey); + if(crtn) { + printf("Error deleting priv\n"); + return testError(quiet); + } + } + } + else { + /* !privIsPerm - just free it and it's all gone */ + if(lookUpPriv != NULL) { + printf("***Unexpected success on cspLookUpKeyByLabel(priv, not perm)\n"); + return testError(quiet); + } + if(cspFreeKey(cspHand, &privKey)) { + printf("Error on cspFreeKey(privKey)\n"); + return testError(quiet); + } + } + /* CSP, DL have no knowledge of privKey or its variations */ + + /* free one or both copies of pub as appropriate */ + if(verbose) { + printf(" ...free pubKey\n"); + } + crtn = cspFreeKey(cspHand, &pubKey); + if(crtn) { + printf("Error freeing pubKey\n"); + return testError(quiet); + } + if(pubIsPerm) { + if(verbose) { + printf(" ...free lookUpPub\n"); + } + crtn = cspFreeKey(cspHand, lookUpPub); + if(crtn) { + printf("Error freeing lookUpPub\n"); + return testError(quiet); + } + } + CSSM_FREE(lookUpPub); // mallocd by lookup in any case + + if(pubIsPerm) { + /* pub should still be there in DL */ + /* lookUpPub = lookup pub by label; verify OK; */ + if(verbose) { + printf(" ...lookup pub by label (2)\n"); + } + lookUpPub = cspLookUpKeyByLabel(dlHand, dbHand, &labelData, CKT_Public); + if(lookUpPub == NULL) { + printf("lookup pub by label (2) failed\n"); + return testError(quiet); + } + + if(!permKeys) { + /* now really delete it */ + if(verbose) { + printf(" ...delete lookUpPub\n"); + } + crtn = cspDeleteKey(cspHand, dlHand, dbHand, &labelData, lookUpPub); + if(crtn) { + printf("Error deleting lookUpPub\n"); + return testError(quiet); + } + CSSM_FREE(lookUpPub); // mallocd by lookup + } + } + /* else freeKey should have removed all trace */ + + if(!permKeys) { + /* lookUpPub = lookup pub by label; verify fail; */ + if(verbose) { + printf(" ...lookup (nonexistent) pub by label\n"); + } + lookUpPub = cspLookUpKeyByLabel(dlHand, dbHand, &labelData, CKT_Public); + if(lookUpPub != NULL) { + printf("Unexpected success on cspLookUpKeyByLabel(pub) (2)\n"); + return testError(quiet); + } + } + return 0; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + CSSM_CSP_HANDLE cspHand; + CSSM_DB_HANDLE dbHand; + CSSM_DL_HANDLE dlHand; + CSSM_BOOL pubIsPerm; + CSSM_BOOL privIsPerm; + CSSM_BOOL privIsExtractable; + uint32 keyGenAlg = CSSM_ALGID_FEE; + int rtn = 0; + CSSM_RETURN crtn; + + /* + * User-spec'd params + */ + unsigned loops = LOOPS_DEF; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL permKeys = CSSM_FALSE; + char dbName[100]; /* DB_NAME_pid */ + CSSM_BOOL useExistDb = CSSM_FALSE; + CSSM_BOOL doPause = CSSM_FALSE; + + dbName[0] = '\0'; + + for(arg=1; arg +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "bsafeUtils.h" +#include +#include "cspdlTesting.h" +#include + +/* + * Defaults. + */ +#define LOOPS_DEF 200 +#define MIN_EXP 2 /* for data size 10**exp */ +#define DEFAULT_MAX_EXP 4 +#define MAX_EXP 5 + +#define MAX_DATA_SIZE (100000 + 100) /* bytes */ +#define MIN_KEY_SIZE 20 /* bytes - should be smaller */ +#define MAX_KEY_SIZE 64 /* bytes */ +#define LOOP_NOTIFY 20 + +/* + * Enumerate algs our own way to allow iteration. + */ +#define ALG_MD5 1 +#define ALG_SHA1 2 +#define ALG_SHA1_LEGACY 3 +#define ALG_FIRST ALG_MD5 +#define ALG_LAST ALG_SHA1_LEGACY + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" n=minExp (default=%d)\n", MIN_EXP); + printf(" x=maxExp (default=%d, max=%d)\n", DEFAULT_MAX_EXP, MAX_EXP); + printf(" k=keySizeInBytes\n"); + printf(" P=plainTextLen\n"); + printf(" z (keys and plaintext all zeroes)\n"); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +/* + * generate MAC using reference BSAFE with either one update + * (updateSizes == NULL) or specified set of update sizes. + */ +static CSSM_RETURN genMacBSAFE( + CSSM_ALGORITHMS macAlg, + const CSSM_DATA *key, // raw key bytes + const CSSM_DATA *inText, + unsigned *updateSizes, // NULL --> random updates + // else null-terminated list of sizes + CSSM_DATA_PTR outText) // mallocd and returned +{ + CSSM_RETURN crtn; + BU_KEY buKey; + + crtn = buGenSymKey(key->Length * 8, key, &buKey); + if(crtn) { + return crtn; + } + crtn = buGenMac(buKey, + macAlg, + inText, + updateSizes, + outText); + buFreeKey(buKey); + return crtn; +} + +/* + * Produce HMACMD5 with openssl. + */ +static int doHmacMD5Ref( + const CSSM_DATA *key, // raw key bytes + const CSSM_DATA *inText, + CSSM_DATA_PTR outText) // mallocd and returned +{ + const EVP_MD *md = EVP_md5(); + unsigned md_len = 16; + appSetupCssmData(outText, 16); + HMAC(md, key->Data, (int)key->Length, + inText->Data, inText->Length, + (unsigned char *)outText->Data, &md_len); + return 0; +} + +/* + * Generate MAC, CSP, specified set of update sizes + */ +static CSSM_RETURN cspGenMacWithSizes(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, + CSSM_KEY_PTR key, // session key + const CSSM_DATA *text, + unsigned *updateSizes, // null-terminated list of sizes + CSSM_DATA_PTR mac) // RETURNED +{ + CSSM_CC_HANDLE macHand; + CSSM_RETURN crtn; + CSSM_DATA currData = *text; + + crtn = CSSM_CSP_CreateMacContext(cspHand, + algorithm, + key, + &macHand); + if(crtn) { + printError("CSSM_CSP_CreateMacContext", crtn); + return crtn; + } + crtn = CSSM_GenerateMacInit(macHand); + if(crtn) { + printError("CSSM_GenerateMacInit", crtn); + goto abort; + } + /* CSP mallocs */ + mac->Data = NULL; + mac->Length = 0; + + while(*updateSizes) { + currData.Length = *updateSizes; + crtn = CSSM_GenerateMacUpdate(macHand, + &currData, + 1); + if(crtn) { + printError("CSSM_GenerateMacUpdate", crtn); + goto abort; + } + currData.Data += *updateSizes; + updateSizes++; + } + crtn = CSSM_GenerateMacFinal(macHand, mac); + if(crtn) { + printError("CSSM_GenerateMacFinal", crtn); + } +abort: + crtn = CSSM_DeleteContext(macHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + } + return crtn; +} + +/* + * Verify MAC, CSP, specified set of update sizes + */ +static CSSM_RETURN cspVfyMacWithSizes(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, + CSSM_KEY_PTR key, // session key + const CSSM_DATA *text, + unsigned *updateSizes, // null-terminated list of sizes + const CSSM_DATA *mac) +{ + CSSM_CC_HANDLE macHand; + CSSM_RETURN crtn; + CSSM_DATA currData = *text; + + crtn = CSSM_CSP_CreateMacContext(cspHand, + algorithm, + key, + &macHand); + if(crtn) { + printError("CSSM_CSP_CreateMacContext", crtn); + return crtn; + } + crtn = CSSM_VerifyMacInit(macHand); + if(crtn) { + printError("CSSM_VerifyMacInit", crtn); + goto abort; + } + + while(*updateSizes) { + currData.Length = *updateSizes; + crtn = CSSM_VerifyMacUpdate(macHand, + &currData, + 1); + if(crtn) { + printError("CSSM_GenerateMacUpdate", crtn); + goto abort; + } + currData.Data += *updateSizes; + updateSizes++; + } + crtn = CSSM_VerifyMacFinal(macHand, mac); + if(crtn) { + printError("CSSM_GenerateMacFinal", crtn); + } +abort: + crtn = CSSM_DeleteContext(macHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + } + return crtn; +} + +/* + * Generate or verify MAC using CSP with either random-sized staged updates + * (updateSizes == NULL) or specified set of update sizes. + */ +static CSSM_RETURN genMacCSSM( + CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS macAlg, + CSSM_ALGORITHMS keyAlg, + CSSM_BOOL doGen, + const CSSM_DATA *key, // raw key bytes + CSSM_BOOL genRaw, // first generate raw key (CSPDL) + const CSSM_DATA *inText, + unsigned *updateSizes, // NULL --> random updates + // else null-terminated list of sizes + CSSM_DATA_PTR outText) // mallocd and returned if doGen +{ + CSSM_KEY_PTR symKey; + CSSM_KEY refKey; // in case of genRaw + CSSM_BOOL refKeyGenerated = CSSM_FALSE; + CSSM_RETURN crtn; + + if(genRaw) { + crtn = cspGenSymKeyWithBits(cspHand, + keyAlg, + CSSM_KEYUSE_SIGN | CSSM_KEYUSE_VERIFY, + key, + key->Length, + &refKey); + if(crtn) { + return crtn; + } + symKey = &refKey; + refKeyGenerated = CSSM_TRUE; + } + else { + /* cook up a raw symmetric key */ + symKey = cspGenSymKey(cspHand, + keyAlg, + "noLabel", + 8, + CSSM_KEYUSE_SIGN | CSSM_KEYUSE_VERIFY, + key->Length * 8, + CSSM_FALSE); // ref key + if(symKey == NULL) { + return CSSM_ERRCODE_INTERNAL_ERROR; + } + if(symKey->KeyData.Length != key->Length) { + printf("***Generated key size error (exp %lu, got %lu)\n", + key->Length, symKey->KeyData.Length); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + memmove(symKey->KeyData.Data, key->Data, key->Length); + } + if(doGen) { + /* CSP mallocs */ + outText->Data = NULL; + outText->Length = 0; + } + + /* go for it */ + if(doGen) { + if(updateSizes) { + crtn = cspGenMacWithSizes(cspHand, + macAlg, + symKey, + inText, + updateSizes, + outText); + } + else { + crtn = cspStagedGenMac(cspHand, + macAlg, + symKey, + inText, + CSSM_TRUE, // multiUpdates + CSSM_FALSE, // mallocMac + outText); + } + } + else { + if(updateSizes) { + crtn = cspVfyMacWithSizes(cspHand, + macAlg, + symKey, + inText, + updateSizes, + outText); + } + else { + crtn = cspMacVerify(cspHand, + macAlg, + symKey, + inText, + outText, + CSSM_OK); + } + } + cspFreeKey(cspHand, symKey); + if(!refKeyGenerated) { + /* key itself mallocd by cspGenSymKey */ + CSSM_FREE(symKey); + } + return crtn; +} + +#define LOG_FREQ 20 +#define MAX_FIXED_UPDATES 5 + +static int doTest(CSSM_CSP_HANDLE cspHand, + const CSSM_DATA *ptext, + const CSSM_DATA *keyData, + CSSM_BOOL genRaw, // first generate raw key (CSPDL) + uint32 macAlg, + uint32 keyAlg, + CSSM_BOOL fixedUpdates, // for testing CSSM_ALGID_SHA1HMAC_LEGACY + CSSM_BOOL quiet) +{ + CSSM_DATA macRef = {0, NULL}; // MAC, BSAFE reference + CSSM_DATA macTest = {0, NULL}; // MAC, CSP test + int rtn = 0; + CSSM_RETURN crtn; + unsigned updateSizes[MAX_FIXED_UPDATES+1]; + unsigned *updateSizesPtr; + + if(fixedUpdates) { + /* calculate up to MAX_FIXED_UPDATES update sizes which add up to + * ptext->Length */ + int i; + unsigned bytesToGo = ptext->Length; + + memset(updateSizes, 0, sizeof(unsigned) * (MAX_FIXED_UPDATES+1)); + for(i=0; i MAX_EXP) { + usage(argv); + } + break; + case 'v': + verbose = CSSM_TRUE; + break; + case 'D': + bareCsp = CSSM_FALSE; + #if CSPDL_ALL_KEYS_ARE_REF + genRaw = CSSM_TRUE; + #endif + break; + case 'q': + quiet = CSSM_TRUE; + break; + case 'p': + pauseInterval = atoi(&argp[2]); + break; + case 'z': + allZeroes = CSSM_TRUE; + break; + case 'k': + keySizeSpecd = atoi(&argp[2]); + break; + case 'P': + ptextLenSpecd = atoi(&argp[2]); + break; + case 'h': + default: + usage(argv); + } + } + if(minExp > maxExp) { + printf("***minExp must be <= maxExp\n"); + usage(argv); + } + ptext.Data = (uint8 *)CSSM_MALLOC(MAX_DATA_SIZE); + if(ptext.Data == NULL) { + printf("Insufficient heap space\n"); + exit(1); + } + /* ptext length set in test loop */ + + keyData.Data = (uint8 *)CSSM_MALLOC(MAX_KEY_SIZE); + if(keyData.Data == NULL) { + printf("Insufficient heap space\n"); + exit(1); + } + /* key length set in test loop */ + + printf("Starting macCompat; args: "); + for(i=1; i +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#define DATA_SIZE_DEF 100 +#define LOOPS_DEF 10 + +#define KEY_ALG_DEF CSSM_ALGID_SHA1HMAC +#define MAC_ALG_DEF CSSM_ALGID_SHA1HMAC + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" d=dataSize (default = %d)\n", DATA_SIZE_DEF); + printf(" l=loops (0=forever)\n"); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" m (HMACMD5; default is HMACSHA1)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" q(uiet)\n"); + printf(" v(erbose))\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + CSSM_CSP_HANDLE cspHand; + CSSM_CC_HANDLE macHand; + CSSM_RETURN crtn; + CSSM_DATA randData; + CSSM_KEY_PTR symmKey; + CSSM_DATA macData = {0, NULL}; + unsigned loop; + int i; + unsigned dataSize = DATA_SIZE_DEF; + unsigned pauseInterval = 0; + unsigned loops = LOOPS_DEF; + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL bareCsp = CSSM_TRUE; + CSSM_ALGORITHMS macAlg = MAC_ALG_DEF; + CSSM_ALGORITHMS keyAlg = KEY_ALG_DEF; + + for(arg=1; arg +#include +#include +#include +#include // for TP OIDs +#include "common.h" +#include + +/* the memory functions themselves are in utilLib/common.c. */ +static CSSM_MEMORY_FUNCS memFuncs = { + appMalloc, + appFree, + appRealloc, + appCalloc, + NULL + }; + +static void usage(char **argv) +{ + printf("Usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" k keep connected and go again\n"); + exit(1); +} + +#define NORM_KEY_LEN 10 + +/* print a key name, padding out to NORM_KEY_LEN columns */ +static void printName( + const char *attrName) +{ + printf(" %s", attrName); + int len = strlen(attrName); + if(len > NORM_KEY_LEN) { + return; + } + int numSpaces = NORM_KEY_LEN - len; + for(int i=0; iLength; dex++) { + printf("%c", attrValue->Data[dex]); + } + printf("'\n"); +} + +/* Print one attribute value */ +static void dumpAttr( + CSSM_DB_ATTRIBUTE_FORMAT attrForm, + const CSSM_DATA *attrData) +{ + if((attrData == NULL) || (attrData->Data == NULL)) { + printf("\n"); + return; + } + void *data = attrData->Data; + switch(attrForm) { + case CSSM_DB_ATTRIBUTE_FORMAT_STRING: + printValue(attrData); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: // not really supported in MDS + case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: + { + unsigned val = *(unsigned *)data; + printf("0x%x\n", val); + break; + } + case CSSM_DB_ATTRIBUTE_FORMAT_BLOB: + { + printf("BLOB length %u : ", (unsigned)attrData->Length); + for(unsigned i=0; iLength; i++) { + unsigned dat = attrData->Data[i]; + printf("%02X ", dat); + } + printf("\n"); + break; + } + case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32: + { + printf("multi_int["); + uint32 numInts = attrData->Length / sizeof(uint32); + uint32 *uip = (uint32 *)data; + for(unsigned i=0; i 0) { + printf(", "); + } + printf("0x%x", (unsigned)*uip++); + } + printf("]\n"); + break; + } + default: + printf("***UNKNOWN FORMAT (%u), Length %u\n", + (unsigned)attrForm, (unsigned)attrData->Length); + break; + } +} + +/* + * Vanilla "dump one record" routine. Assumes format of all attribute labels + * as string. + */ +static void dumpRecord( + const CSSM_DB_RECORD_ATTRIBUTE_DATA *recordAttrs) +{ + unsigned dex; + for(dex=0; dexNumberOfAttributes; dex++) { + const CSSM_DB_ATTRIBUTE_DATA *attrData = &recordAttrs->AttributeData[dex]; + if(attrData->Info.AttributeNameFormat != + CSSM_DB_ATTRIBUTE_NAME_AS_STRING) { + printf("***BAD ATTR_NAME FORMAT (%u)\n", + (unsigned)attrData->Info.AttributeNameFormat); + continue; + } + const char *attrName = attrData->Info.Label.AttributeName; + printName(attrName); + printf(": "); + for(unsigned attrNum=0; attrNumNumberOfValues; attrNum++) { + dumpAttr(attrData->Info.AttributeFormat, + &attrData->Value[attrNum]); + } + if(attrData->NumberOfValues == 0) { + printf("<>\n"); + } + } +} + +/* free attribute(s) allocated by MDS */ +static void freeAttrs( + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR recordAttrs) +{ + unsigned i; + + for(i=0; iNumberOfAttributes; i++) { + CSSM_DB_ATTRIBUTE_DATA_PTR attrData = &recordAttrs->AttributeData[i]; + if(attrData == NULL) { + /* fault of caller, who allocated the CSSM_DB_ATTRIBUTE_DATA */ + printf("***freeAttrs screwup: NULL attrData\n"); + return; + } + unsigned j; + for(j=0; jNumberOfValues; j++) { + CSSM_DATA_PTR data = &attrData->Value[j]; + if(data == NULL) { + /* fault of MDS, who said there was a value here */ + printf("***freeAttrs screwup: NULL data\n"); + return; + } + appFree(data->Data, NULL); + data->Data = NULL; + data->Length = 0; + } + appFree(attrData->Value, NULL); + attrData->Value = NULL; + } +} + +/* + * Core MDS lookup routine. Used in two situations. It's called by main() to perform + * a lookup in the CDSA Directory Database based one one key/value pair; this + * call fetches one attribute from the associated record - the GUID ("ModuleID" + * in MDS lingo). Then the function calls itself to do a lookup in the Object DB, + * based on that GUID, in order to fetch the path of the module associated with + * that GUID. The first call (from main()) corresponds to an application's + * typical use of MDS. The recursive call, which does a lookup in the Object + * DB, corresponds to CSSM's typical use of MDS, which is to map a GUID to a + * bundle path. + * + * The ModuleID and Path of all modules satisfying the initial search criteria + * are displayed on stdout. + * + * Caller specifies one search attribute, by name, value,Êand value format. + * Whether this is the first or second (recursive) call is indicated by the + * cdsaLookup argument. That determines both the DB to search and the attribute + * to fetch (ModuleID or Path). + */ +static void doLookup( + MDS_FUNCS *mdsFuncs, + + /* Two DBs and a flag indicating which one to use */ + MDS_DB_HANDLE objDlDb, + MDS_DB_HANDLE cdsaDlDb, + bool cdsaLookup, // true - use cdsaDlDb; false - objDlDb + + /* Record type, a.k.a. Relation, e.g. MDS_CDSADIR_CSP_PRIMARY_RECORDTYPE */ + CSSM_DB_RECORDTYPE recordType, + + /* key, value, valForm, and valOp are the thing we search on */ + /* Note CSSM_DB_ATTRIBUTE_NAME_FORMAT - the format of the attribute name - + * is always CSSM_DB_ATTRIBUTE_NAME_AS_STRING for MDS. */ + const char *key, // e.g. "AlgType" + const void *valPtr, + unsigned valLen, + CSSM_DB_ATTRIBUTE_FORMAT valForm, // CSSM_DB_ATTRIBUTE_FORMAT_STRING, etc. + CSSM_DB_OPERATOR valOp, // normally CSSM_DB_EQUAL + + /* for display only */ + const char *srchStr) +{ + CSSM_QUERY query; + CSSM_DB_UNIQUE_RECORD_PTR record = NULL; + CSSM_HANDLE resultHand; + CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; + CSSM_SELECTION_PREDICATE predicate; + CSSM_DATA predData; + CSSM_DB_ATTRIBUTE_DATA outAttr; + CSSM_DB_ATTRIBUTE_INFO_PTR attrInfo; + CSSM_RETURN crtn; + MDS_DB_HANDLE dlDb; + const char *attrName; + + if(cdsaLookup) { + /* first call, fetching guid from the CDSA Directory DB */ + dlDb = cdsaDlDb; + attrName = "ModuleID"; + } + else { + /* recursive call, fetching path from Object DB */ + dlDb = objDlDb; + attrName = "Path"; + } + + /* We want one attributes back, name and format specified by caller */ + recordAttrs.DataRecordType = recordType; + recordAttrs.SemanticInformation = 0; + recordAttrs.NumberOfAttributes = 1; + recordAttrs.AttributeData = &outAttr; + + memset(&outAttr, 0, sizeof(CSSM_DB_ATTRIBUTE_DATA)); + attrInfo = &outAttr.Info; + attrInfo->AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attrInfo->Label.AttributeName = (char *)attrName; + attrInfo->AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_STRING; + + /* one predicate - the caller's key and CSSM_DB_OPERATOR */ + predicate.DbOperator = valOp; + predicate.Attribute.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + predicate.Attribute.Info.Label.AttributeName = (char *)key; + predicate.Attribute.Info.AttributeFormat = valForm; + predData.Data = (uint8 *)valPtr; + predData.Length = valLen; + predicate.Attribute.Value = &predData; + predicate.Attribute.NumberOfValues = 1; + + query.RecordType = recordType; + query.Conjunctive = CSSM_DB_NONE; + query.NumSelectionPredicates = 1; + query.SelectionPredicate = &predicate; + query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? + query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? + query.QueryFlags = 0; // CSSM_QUERY_RETURN_DATA...FIXME - used? + + crtn = mdsFuncs->DataGetFirst(dlDb, + &query, + &resultHand, + &recordAttrs, + NULL, // No data + &record); + switch(crtn) { + case CSSM_OK: + break; // proceed + case CSSMERR_DL_ENDOFDATA: + printf("%s: no record found\n", srchStr); + return; + default: + printError("DataGetFirst", crtn); + return; + } + /* dump this record, one attribute */ + if(srchStr) { + /* not done on recursive call */ + printf("%s found:\n", srchStr); + } + dumpRecord(&recordAttrs); + mdsFuncs->FreeUniqueRecord(dlDb, record); + + if(srchStr != NULL) { + /* + * Now do a lookup in Object DB of this guid, looking for path. + * Apps normally don't do this; this is what CSSM does when given + * the GUID of a module. + */ + if(outAttr.Value == NULL) { + printf("***Screwup: DataGetFirst worked, but no outAttr\n"); + return; + } + doLookup(mdsFuncs, + objDlDb, + cdsaDlDb, + false, // use objDlDb + MDS_OBJECT_RECORDTYPE, + "ModuleID", // key + outAttr.Value->Data, // valPtr, ModuleID, as string + outAttr.Value->Length, // valLen + CSSM_DB_ATTRIBUTE_FORMAT_STRING, + CSSM_DB_EQUAL, + NULL); // srchStr + } + freeAttrs(&recordAttrs); + + /* now the rest of them */ + for(;;) { + crtn = mdsFuncs->DataGetNext(dlDb, + resultHand, + &recordAttrs, + NULL, + &record); + switch(crtn) { + case CSSM_OK: + dumpRecord(&recordAttrs); + mdsFuncs->FreeUniqueRecord(cdsaDlDb, record); + if(srchStr != NULL) { + if(outAttr.Value == NULL) { + printf("***Screwup: DataGetNext worked, but no outAttr\n"); + return; + } + doLookup(mdsFuncs, + objDlDb, + cdsaDlDb, + false, // use objDlDb + MDS_OBJECT_RECORDTYPE, + "ModuleID", // key + outAttr.Value->Data, // valPtr, ModuleID, as string + outAttr.Value->Length, // valLen + CSSM_DB_ATTRIBUTE_FORMAT_STRING, + CSSM_DB_EQUAL, + NULL); // srchStr + } + freeAttrs(&recordAttrs); + break; // and go again + case CSSMERR_DL_ENDOFDATA: + /* normal termination */ + break; + default: + printError("DataGetNext", crtn); + break; + } + if(crtn != CSSM_OK) { + break; + } + } +} + +int main(int argc, char **argv) +{ + MDS_FUNCS mdsFuncs; + MDS_HANDLE mdsHand; + CSSM_RETURN crtn; + int arg; + CSSM_DB_HANDLE dbHand = 0; + MDS_DB_HANDLE objDlDb; + MDS_DB_HANDLE cdsaDlDb; + bool keepConnected = false; + uint32 val; + + for(arg=2; arg +#include + +/* + * There appears to be a bug in AppleDatabase which prevents our assigning + * schema to the meta-tables. + */ +#define DEFINE_META_TABLES 0 + +// +// Schema for the lone table in the Object Directory Database. +// +static const CSSM_DB_ATTRIBUTE_INFO objectAttrs[] = { + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(Manifest, BLOB), + DB_ATTRIBUTE(ModuleName, STRING), + DB_ATTRIBUTE(Path, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + + /* not in the CDSA spec; denotes a plugin which is statically linked to CSSM */ + DB_ATTRIBUTE(BuiltIn, UINT32), +}; + +static const CSSM_DB_INDEX_INFO objectIndex[] = { + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING) +}; + +const RelationInfo kObjectRelation = + RELATION_INFO(MDS_OBJECT_RECORDTYPE, + objectAttrs, + objectIndex); + +// +// Schema for the various tables in the CDSA Directory Database. +// + +// CSSM Relation. +static const CSSM_DB_ATTRIBUTE_INFO cssmAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(CDSAVersion, STRING), + DB_ATTRIBUTE(Vendor, STRING), + DB_ATTRIBUTE(Desc, STRING), + DB_ATTRIBUTE(NativeServices, UINT32), +}; + +static const CSSM_DB_INDEX_INFO cssmIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING) +}; + +// KRMM Relation. +static const CSSM_DB_ATTRIBUTE_INFO krmmAttrs[] = +{ + DB_ATTRIBUTE(CSSMGuid, STRING), + DB_ATTRIBUTE(PolicyType, UINT32), + DB_ATTRIBUTE(PolicyName, STRING), + DB_ATTRIBUTE(PolicyPath, STRING), + DB_ATTRIBUTE(PolicyInfo, BLOB), + DB_ATTRIBUTE(PolicyManifest, BLOB), + /* + * This attribute is not defined in the CDSA spec. It's only here, in the schema, + * to avoid throwing exceptions when searching a DB for any records associated + * with a specified GUID - in all other schemas, a guid is specified as a + * ModuleID. + */ + DB_ATTRIBUTE(ModuleID, STRING), +}; + +static const CSSM_DB_INDEX_INFO krmmIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(CSSMGuid, STRING), + UNIQUE_INDEX_ATTRIBUTE(PolicyType, UINT32) +}; + +// EMM Relation. +static const CSSM_DB_ATTRIBUTE_INFO emmAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(Manifest, BLOB), + DB_ATTRIBUTE(ModuleName, STRING), + DB_ATTRIBUTE(Path, STRING), + DB_ATTRIBUTE(CDSAVersion, STRING), + DB_ATTRIBUTE(EMMSpecVersion, STRING), + DB_ATTRIBUTE(Desc, STRING), + DB_ATTRIBUTE(PolicyStmt, BLOB), + DB_ATTRIBUTE(EmmVersion, STRING), + DB_ATTRIBUTE(EmmVendor, STRING), + DB_ATTRIBUTE(EmmType, UINT32), // does this need a name/value table? +}; + +static const CSSM_DB_INDEX_INFO emmIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING) +}; + +// Primary EMM Service Provider Relation. +static const CSSM_DB_ATTRIBUTE_INFO emmPrimaryAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(ServiceType, UINT32), + DB_ATTRIBUTE(Manifest, BLOB), + DB_ATTRIBUTE(ModuleName, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + DB_ATTRIBUTE(Vendor, STRING), + DB_ATTRIBUTE(SampleTypes, MULTI_UINT32), + DB_ATTRIBUTE(AclSubjectTypes, MULTI_UINT32), + DB_ATTRIBUTE(AuthTags, MULTI_UINT32), + DB_ATTRIBUTE(EmmSpecVersion, STRING), +}; + +static const CSSM_DB_INDEX_INFO emmPrimaryIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32), + UNIQUE_INDEX_ATTRIBUTE(ServiceType, UINT32) +}; + +// Common Relation. +static const CSSM_DB_ATTRIBUTE_INFO commonAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(Manifest, BLOB), + DB_ATTRIBUTE(ModuleName, STRING), + DB_ATTRIBUTE(Path, STRING), + DB_ATTRIBUTE(CDSAVersion, STRING), + DB_ATTRIBUTE(Desc, STRING), + DB_ATTRIBUTE(DynamicFlag, UINT32), + DB_ATTRIBUTE(MultiThreadFlag, UINT32), + DB_ATTRIBUTE(ServiceMask, UINT32), +}; + +static const CSSM_DB_INDEX_INFO commonIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING) +}; + +// CSP Primary Relation. +static const CSSM_DB_ATTRIBUTE_INFO cspPrimaryAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(Manifest, BLOB), + DB_ATTRIBUTE(ModuleName, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + DB_ATTRIBUTE(Vendor, STRING), + DB_ATTRIBUTE(CspType, UINT32), + DB_ATTRIBUTE(CspFlags, UINT32), + DB_ATTRIBUTE(CspCustomFlags, UINT32), + DB_ATTRIBUTE(UseeTags, MULTI_UINT32), + DB_ATTRIBUTE(SampleTypes, MULTI_UINT32), + DB_ATTRIBUTE(AclSubjectTypes, MULTI_UINT32), + DB_ATTRIBUTE(AuthTags, MULTI_UINT32), +}; + +static const CSSM_DB_INDEX_INFO cspPrimaryIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) +}; + +// CSP Capabilities Relation. +static const CSSM_DB_ATTRIBUTE_INFO cspCapabilitiesAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(UseeTag, UINT32), + DB_ATTRIBUTE(ContextType, UINT32), + DB_ATTRIBUTE(AlgType, UINT32), + DB_ATTRIBUTE(GroupId, UINT32), + DB_ATTRIBUTE(AttributeType, UINT32), + DB_ATTRIBUTE(AttributeValue, MULTI_UINT32), + DB_ATTRIBUTE(Description, STRING), +}; + +static const CSSM_DB_INDEX_INFO cspCapabilitiesIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32), + UNIQUE_INDEX_ATTRIBUTE(UseeTag, UINT32), + UNIQUE_INDEX_ATTRIBUTE(ContextType, UINT32), + UNIQUE_INDEX_ATTRIBUTE(AlgType, UINT32), + UNIQUE_INDEX_ATTRIBUTE(GroupId, UINT32), + UNIQUE_INDEX_ATTRIBUTE(AttributeType, STRING) +}; + +// special case "subschema" for parsing CSPCapabilities. These arrays correspond +// dictionaries within a CSPCapabilities info file; they are not part of +// our DB's schema. They are declared only to streamline the +// MDSAttrParser::parseCspCapabilitiesRecord function. No index info is needed. + +// top-level info, applied to the dictionary for the whole file. +static const CSSM_DB_ATTRIBUTE_INFO kAttributesCSPCapabilitiesDict1[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), +}; +const RelationInfo CSPCapabilitiesDict1RelInfo = + RELATION_INFO( + MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE, // actually a don't care + kAttributesCSPCapabilitiesDict1, + NULL); // no index + +// "Capabilities" is an array of dictionaries of these +static const CSSM_DB_ATTRIBUTE_INFO kAttributesCSPCapabilitiesDict2[] = +{ + DB_ATTRIBUTE(AlgType, UINT32), + DB_ATTRIBUTE(ContextType, UINT32), + DB_ATTRIBUTE(UseeTag, UINT32), + DB_ATTRIBUTE(Description, STRING), +}; +const RelationInfo CSPCapabilitiesDict2RelInfo = + RELATION_INFO( + MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE, // actually a don't care + kAttributesCSPCapabilitiesDict2, + NULL); // no index + +// Within a Capabilities array, the Attributes array is an array of +// Dictionaries of these. +static const CSSM_DB_ATTRIBUTE_INFO kAttributesCSPCapabilitiesDict3[] = +{ + DB_ATTRIBUTE(AttributeType, UINT32), + DB_ATTRIBUTE(AttributeValue, MULTI_UINT32), +}; +const RelationInfo CSPCapabilitiesDict3RelInfo = + RELATION_INFO( + MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE, // actually a don't care + kAttributesCSPCapabilitiesDict3, + NULL); + + + +// CSP Encapsulated Products Relation. +static const CSSM_DB_ATTRIBUTE_INFO cspEncapsulatedAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(ProductDesc, STRING), + DB_ATTRIBUTE(ProductVendor, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + DB_ATTRIBUTE(ProductFlags, UINT32), + DB_ATTRIBUTE(CustomFlags, UINT32), + DB_ATTRIBUTE(StandardDesc, STRING), + DB_ATTRIBUTE(StandardVersion, STRING), + DB_ATTRIBUTE(ReaderDesc, STRING), + DB_ATTRIBUTE(ReaderVendor, STRING), + DB_ATTRIBUTE(ReaderVersion, STRING), + DB_ATTRIBUTE(ReaderFirmwareVersion, STRING), + DB_ATTRIBUTE(ReaderFlags, UINT32), + DB_ATTRIBUTE(ReaderCustomFlags, UINT32), + DB_ATTRIBUTE(ReaderSerialNumber, STRING), +}; + +static const CSSM_DB_INDEX_INFO cspEncapsulatedIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) +}; + +// CSP Smartcardinfo Relation. +static const CSSM_DB_ATTRIBUTE_INFO cspSmartCardAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(ScDesc, STRING), + DB_ATTRIBUTE(ScVendor, STRING), + DB_ATTRIBUTE(ScVersion, STRING), + DB_ATTRIBUTE(ScFirmwareVersion, STRING), + DB_ATTRIBUTE(ScFlags, UINT32), + DB_ATTRIBUTE(ScCustomFlags, UINT32), + DB_ATTRIBUTE(ScSerialNumber, STRING), +}; +static const CSSM_DB_INDEX_INFO cspSmartCardIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32), + UNIQUE_INDEX_ATTRIBUTE(ScDesc, STRING), + UNIQUE_INDEX_ATTRIBUTE(ScVendor, STRING), + UNIQUE_INDEX_ATTRIBUTE(ScVersion, STRING), + UNIQUE_INDEX_ATTRIBUTE(ScFirmwareVersion, STRING), + UNIQUE_INDEX_ATTRIBUTE(ScFlags, UINT32) +}; + +// DL Primary Relation. +static const CSSM_DB_ATTRIBUTE_INFO dlPrimaryAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(Manifest, BLOB), + DB_ATTRIBUTE(ModuleName, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + DB_ATTRIBUTE(Vendor, STRING), + DB_ATTRIBUTE(DLType, UINT32), + DB_ATTRIBUTE(QueryLimitsFlag, UINT32), // a completely bogus attr; see spec + DB_ATTRIBUTE(SampleTypes, MULTI_UINT32), + DB_ATTRIBUTE(AclSubjectTypes, MULTI_UINT32), + DB_ATTRIBUTE(AuthTags, MULTI_UINT32), + DB_ATTRIBUTE(ConjunctiveOps, MULTI_UINT32), + DB_ATTRIBUTE(RelationalOps, MULTI_UINT32), +}; +static const CSSM_DB_INDEX_INFO dlPrimaryIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) +}; + +// DL Encapsulated Products Relation. +static const CSSM_DB_ATTRIBUTE_INFO dlEncapsulatedAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(ProductDesc, STRING), + DB_ATTRIBUTE(ProductVendor, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + DB_ATTRIBUTE(ProductFlags, UINT32), + DB_ATTRIBUTE(StandardDesc, STRING), + DB_ATTRIBUTE(StandardVersion, STRING), + DB_ATTRIBUTE(Protocol, UINT32), + DB_ATTRIBUTE(RetrievalMode, UINT32), +}; + +static const CSSM_DB_INDEX_INFO dlEncapsulatedIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) +}; + +// CL Primary Relation. +static const CSSM_DB_ATTRIBUTE_INFO clPrimaryAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(Manifest, BLOB), + DB_ATTRIBUTE(ModuleName, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + DB_ATTRIBUTE(Vendor, STRING), + DB_ATTRIBUTE(CertTypeFormat, UINT32), + DB_ATTRIBUTE(CrlTypeFormat, UINT32), + DB_ATTRIBUTE(CertFieldNames, BLOB), + DB_ATTRIBUTE(BundleTypeFormat, MULTI_UINT32), + DB_ATTRIBUTE(XlationTypeFormat, MULTI_UINT32), + DB_ATTRIBUTE(TemplateFieldNames, BLOB), +}; + +static const CSSM_DB_INDEX_INFO clPrimaryIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) +}; + +// CL Encapsulated Products Relation. +static const CSSM_DB_ATTRIBUTE_INFO clEncapsulatedAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(ProductDesc, STRING), + DB_ATTRIBUTE(ProductVendor, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + DB_ATTRIBUTE(ProductFlags, UINT32), + DB_ATTRIBUTE(StandardDesc, STRING), + DB_ATTRIBUTE(StandardVersion, STRING), +}; + +static const CSSM_DB_INDEX_INFO clEncapsulatedIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) +}; + +// TP Primary Relation. +static const CSSM_DB_ATTRIBUTE_INFO tpPrimaryAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(Manifest, BLOB), + DB_ATTRIBUTE(ModuleName, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + DB_ATTRIBUTE(Vendor, STRING), + DB_ATTRIBUTE(CertTypeFormat, UINT32), + DB_ATTRIBUTE(SampleTypes, MULTI_UINT32), + DB_ATTRIBUTE(AclSubjectTypes, MULTI_UINT32), + DB_ATTRIBUTE(AuthTags, MULTI_UINT32), +}; + +static const CSSM_DB_INDEX_INFO tpPrimaryIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) +}; + +// TP Policy-OIDs Relation. +static const CSSM_DB_ATTRIBUTE_INFO tpPolicyOidsAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(OID, BLOB), + DB_ATTRIBUTE(Value, BLOB), +}; + +static const CSSM_DB_INDEX_INFO tpPolicyOidsIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32), + UNIQUE_INDEX_ATTRIBUTE(OID, BLOB) +}; + +// special case "subschema" for parsing tpPolicyOidsAttrs. These arrays correspond +// dictionaries within a tpPolicyOidsAttrs info file; they are not part of +// our DB's schema. They are declared only to streamline the +// MDSAttrParser::parseTpPolicyOidsRecord function. No index info is needed. + +// top-level info, applied to the dictionary for the whole file. +static const CSSM_DB_ATTRIBUTE_INFO tpPolicyOidsDict1[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), +}; +const RelationInfo TpPolicyOidsDict1RelInfo = + RELATION_INFO( + MDS_CDSADIR_TP_OIDS_RECORDTYPE, // actually a don't care + tpPolicyOidsDict1, + NULL); // no index + +// One element of the "Policies" array maps to one of these. +static const CSSM_DB_ATTRIBUTE_INFO tpPolicyOidsDict2[] = +{ + DB_ATTRIBUTE(OID, BLOB), + DB_ATTRIBUTE(Value, BLOB), +}; +const RelationInfo TpPolicyOidsDict2RelInfo = + RELATION_INFO( + MDS_CDSADIR_TP_OIDS_RECORDTYPE, // actually a don't care + tpPolicyOidsDict2, + NULL); // no index + +// TP Encapsulated Products Relation. +static const CSSM_DB_ATTRIBUTE_INFO tpEncapsulatedAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(ProductDesc, STRING), + DB_ATTRIBUTE(ProductVendor, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + DB_ATTRIBUTE(ProductFlags, UINT32), // vendor-specific, right? + DB_ATTRIBUTE(AuthorityRequestType, MULTI_UINT32), + DB_ATTRIBUTE(StandardDesc, STRING), + DB_ATTRIBUTE(StandardVersion, STRING), + DB_ATTRIBUTE(ProtocolDesc, STRING), + DB_ATTRIBUTE(ProtocolFlags, UINT32), + DB_ATTRIBUTE(CertClassName, STRING), + DB_ATTRIBUTE(RootCertificate, BLOB), + DB_ATTRIBUTE(RootCertTypeFormat, UINT32), +}; +static const CSSM_DB_INDEX_INFO tpEncapsulatedIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) +}; + +#if DEFINE_META_TABLES +// MDS Schema Relations (meta) Relation. +static const CSSM_DB_ATTRIBUTE_INFO mdsSchemaRelationsAttrs[] = +{ + DB_ATTRIBUTE(RelationID, UINT32), + DB_ATTRIBUTE(RelationName, STRING), +}; + +static const CSSM_DB_INDEX_INFO mdsSchemaRelationsIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(RelationID, UINT32), +}; + +// MDS Schema Attributes (meta) Relation. +static const CSSM_DB_ATTRIBUTE_INFO mdsSchemaAttributesAttrs[] = +{ + DB_ATTRIBUTE(RelationID, UINT32), + DB_ATTRIBUTE(AttributeID, UINT32), + DB_ATTRIBUTE(AttributeNameFormat, UINT32), + DB_ATTRIBUTE(AttributeName, STRING), + DB_ATTRIBUTE(AttributeNameID, BLOB), + DB_ATTRIBUTE(AttributeFormat, UINT32), +}; + +static const CSSM_DB_INDEX_INFO mdsSchemaAttributesIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(RelationID, UINT32), + UNIQUE_INDEX_ATTRIBUTE(AttributeID, UINT32) +}; + +// MDS Schema Indexes (meta) Relation. +static const CSSM_DB_ATTRIBUTE_INFO mdsSchemaIndexesAttrs[] = +{ + DB_ATTRIBUTE(RelationID, UINT32), + DB_ATTRIBUTE(IndexID, UINT32), + DB_ATTRIBUTE(AttributeID, UINT32), + DB_ATTRIBUTE(IndexType, UINT32), + DB_ATTRIBUTE(IndexedDataLocation, UINT32), +}; + +static const CSSM_DB_INDEX_INFO mdsSchemaIndexesIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(RelationID, UINT32), + UNIQUE_INDEX_ATTRIBUTE(IndexID, UINT32) +}; + +#endif /* DEFINE_META_TABLES */ + +// AC Primary Relation. +static const CSSM_DB_ATTRIBUTE_INFO acPrimaryAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(Manifest, BLOB), + DB_ATTRIBUTE(ModuleName, STRING), + DB_ATTRIBUTE(ProductVersion, STRING), + DB_ATTRIBUTE(Vendor, STRING), +}; + +static const CSSM_DB_INDEX_INFO acPrimaryIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) +}; + +// KR Primary Relation. +static const CSSM_DB_ATTRIBUTE_INFO krPrimaryAttrs[] = +{ + DB_ATTRIBUTE(ModuleID, STRING), + DB_ATTRIBUTE(SSID, UINT32), + DB_ATTRIBUTE(Manifest, BLOB), + DB_ATTRIBUTE(ModuleName, STRING), + DB_ATTRIBUTE(CompatCSSMVersion, STRING), + DB_ATTRIBUTE(Version, STRING), + DB_ATTRIBUTE(Vendor, STRING), + DB_ATTRIBUTE(Description, STRING), + DB_ATTRIBUTE(ConfigFileLocation, STRING), +}; + +static const CSSM_DB_INDEX_INFO krPrimaryIndex[] = +{ + UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), + UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) +}; + +// list of all built-in schema for the CDSA Directory DB. +const RelationInfo kMDSRelationInfo[] = +{ + RELATION_INFO(MDS_CDSADIR_CSSM_RECORDTYPE, + cssmAttrs, + cssmIndex), + RELATION_INFO(MDS_CDSADIR_KRMM_RECORDTYPE, + krmmAttrs, + krmmIndex), + RELATION_INFO(MDS_CDSADIR_EMM_RECORDTYPE, + emmAttrs, + emmIndex), + RELATION_INFO(MDS_CDSADIR_EMM_PRIMARY_RECORDTYPE, + emmPrimaryAttrs, + emmPrimaryIndex), + RELATION_INFO(MDS_CDSADIR_COMMON_RECORDTYPE, + commonAttrs, + commonIndex), + RELATION_INFO(MDS_CDSADIR_CSP_PRIMARY_RECORDTYPE, + cspPrimaryAttrs, + cspPrimaryIndex), + RELATION_INFO(MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE, + cspCapabilitiesAttrs, + cspCapabilitiesIndex), + RELATION_INFO(MDS_CDSADIR_CSP_ENCAPSULATED_PRODUCT_RECORDTYPE, + cspEncapsulatedAttrs, + cspEncapsulatedIndex), + RELATION_INFO(MDS_CDSADIR_CSP_SC_INFO_RECORDTYPE, + cspSmartCardAttrs, + cspSmartCardIndex), + RELATION_INFO(MDS_CDSADIR_DL_PRIMARY_RECORDTYPE, + dlPrimaryAttrs, + dlPrimaryIndex), + RELATION_INFO(MDS_CDSADIR_DL_ENCAPSULATED_PRODUCT_RECORDTYPE, + dlEncapsulatedAttrs, + dlEncapsulatedIndex), + RELATION_INFO(MDS_CDSADIR_CL_PRIMARY_RECORDTYPE, + clPrimaryAttrs, + clPrimaryIndex), + RELATION_INFO(MDS_CDSADIR_CL_ENCAPSULATED_PRODUCT_RECORDTYPE, + clEncapsulatedAttrs, + clEncapsulatedIndex), + RELATION_INFO(MDS_CDSADIR_TP_PRIMARY_RECORDTYPE, + tpPrimaryAttrs, + tpPrimaryIndex), + RELATION_INFO(MDS_CDSADIR_TP_OIDS_RECORDTYPE, + tpPolicyOidsAttrs, + tpPolicyOidsIndex), + RELATION_INFO(MDS_CDSADIR_TP_ENCAPSULATED_PRODUCT_RECORDTYPE, + tpEncapsulatedAttrs, + tpEncapsulatedIndex), + #if DEFINE_META_TABLES + RELATION_INFO(MDS_CDSADIR_MDS_SCHEMA_RELATIONS, + mdsSchemaRelationsAttrs, + mdsSchemaRelationsIndex), + RELATION_INFO(MDS_CDSADIR_MDS_SCHEMA_ATTRIBUTES, + mdsSchemaAttributesAttrs, + mdsSchemaAttributesIndex), + RELATION_INFO(MDS_CDSADIR_MDS_SCHEMA_INDEXES, + mdsSchemaIndexesAttrs, + mdsSchemaIndexesIndex), + #endif /* DEFINE_META_TABLES */ + RELATION_INFO(MDS_CDSADIR_AC_PRIMARY_RECORDTYPE, + acPrimaryAttrs, + acPrimaryIndex), + RELATION_INFO(MDS_CDSADIR_KR_PRIMARY_RECORDTYPE, + krPrimaryAttrs, + krPrimaryIndex) +}; + +const unsigned kNumMdsRelations = sizeof(kMDSRelationInfo) / sizeof(RelationInfo); + +// Map a CSSM_DB_RECORDTYPE to a RelationInfo *. +extern const RelationInfo *MDSRecordTypeToRelation( + CSSM_DB_RECORDTYPE recordType) +{ + const RelationInfo *relInfo = kMDSRelationInfo; + unsigned dex; + + for(dex=0; dexDataRecordType == recordType) { + return relInfo; + } + relInfo++; + } + if(recordType == MDS_OBJECT_RECORDTYPE) { + return &kObjectRelation; + } + return NULL; +} + +// same as above, based on record type as string. +extern const RelationInfo *MDSRecordTypeNameToRelation( + const char *recordTypeName) +{ + const RelationInfo *relInfo = kMDSRelationInfo; + unsigned dex; + + for(dex=0; dexrelationName)) { + return relInfo; + } + relInfo++; + } + return NULL; +} + diff --git a/SecurityTests/cspxutils/mdsdump/MDSSchema.h b/SecurityTests/cspxutils/mdsdump/MDSSchema.h new file mode 100644 index 00000000..c33e877a --- /dev/null +++ b/SecurityTests/cspxutils/mdsdump/MDSSchema.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2000-2001,2004,2008 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please obtain + * a copy of the License at http://www.apple.com/publicsource and read it before + * using this file. + * + * This 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. + */ + + +// +// MDSSchema.h - COPIED FROM libsecurity_mds since this is not exported from +// Security.framework + +// +// Declarations of structures which define the schema, including attributes +// and indexes, for the standard tables that are part of the MDS database. +// + +#ifndef _MDSSCHEMA_H +#define _MDSSCHEMA_H + +#include + +// Structure used to store information which is needed to create +// a relation with indexes. The info in one of these structs maps to one +// record type in a CSSM_DBINFO - both record attribute info and index info. +// The nameValues field refers to an array of MDSNameValuePair array pointers +// which are used to convert attribute values from strings to uint32s via +// MDS_StringToUint32. The nameValues array is parallel to the AttributeInfo +// array. +struct RelationInfo { + CSSM_DB_RECORDTYPE DataRecordType; + const char *relationName; + uint32 NumberOfAttributes; + const CSSM_DB_ATTRIBUTE_INFO *AttributeInfo; + uint32 NumberOfIndexes; + const CSSM_DB_INDEX_INFO *IndexInfo; +}; + +// Macros used to simplify declarations of attributes and indexes. + +// declare a CSSM_DB_ATTRIBUTE_INFO +#define DB_ATTRIBUTE(name, type) \ + { CSSM_DB_ATTRIBUTE_NAME_AS_STRING, \ + {(char *)#name}, \ + CSSM_DB_ATTRIBUTE_FORMAT_ ## type \ + } + +// declare a CSSM_DB_INDEX_INFO +#define UNIQUE_INDEX_ATTRIBUTE(name, type) \ + { CSSM_DB_INDEX_UNIQUE, \ + CSSM_DB_INDEX_ON_ATTRIBUTE, \ + { CSSM_DB_ATTRIBUTE_NAME_AS_STRING, \ + {(char *)#name}, \ + CSSM_DB_ATTRIBUTE_FORMAT_ ## type \ + } \ + } + +// declare a RelationInfo +#define RELATION_INFO(relationId, attributes, indexes) \ + { relationId, \ + #relationId, \ + sizeof(attributes) / sizeof(CSSM_DB_ATTRIBUTE_INFO), \ + attributes, \ + sizeof(indexes) / sizeof(CSSM_DB_INDEX_INFO), \ + indexes } + +// Object directory DB - one built-in schema. +extern const RelationInfo kObjectRelation; + +// list of all built-in schema for the CDSA Directory DB. +extern const RelationInfo kMDSRelationInfo[]; +extern const unsigned kNumMdsRelations; // size of kMDSRelationInfo[] + +// special case "subschema" for parsing CSPCapabilities. +extern const RelationInfo CSPCapabilitiesDict1RelInfo; +extern const RelationInfo CSPCapabilitiesDict2RelInfo; +extern const RelationInfo CSPCapabilitiesDict3RelInfo; + +// special case "subschema" for parsing TPPolicyOids. +extern const RelationInfo TpPolicyOidsDict1RelInfo; +extern const RelationInfo TpPolicyOidsDict2RelInfo; + +// Map a CSSM_DB_RECORDTYPE to a RelationInfo *. +extern const RelationInfo *MDSRecordTypeToRelation( + CSSM_DB_RECORDTYPE recordType); + +// same as above, based on record type as string. +extern const RelationInfo *MDSRecordTypeNameToRelation( + const char *recordTypeName); + +#endif // _MDSSCHEMA_H diff --git a/SecurityTests/cspxutils/mdsdump/Makefile b/SecurityTests/cspxutils/mdsdump/Makefile new file mode 100644 index 00000000..8c8c64c8 --- /dev/null +++ b/SecurityTests/cspxutils/mdsdump/Makefile @@ -0,0 +1,54 @@ +# name of executable to build +EXECUTABLE=mdsdump +# C++ source (with .cpp extension) +CPSOURCE= mdsdump.cpp MDSSchema.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= -framework CoreFoundation + +# +# project-specific includes, with leading -I +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +#PROJ_LDFLAGS= -lMallocDebug +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/mdsdump/mdsdump.cpp b/SecurityTests/cspxutils/mdsdump/mdsdump.cpp new file mode 100644 index 00000000..15d50cc4 --- /dev/null +++ b/SecurityTests/cspxutils/mdsdump/mdsdump.cpp @@ -0,0 +1,558 @@ +/* + * mdsdump.cpp - dump contents of system MDS databases + */ + + /**** FIXME this uses a private API not currently exported in any way from + **** Security project + ****/ + +#include +#include +#include +#include +#include +#include +#include "MDSSchema.h" +#include + +#define MAX_MDS_ATTRS 32 + +static CSSM_MEMORY_FUNCS memFuncs = { + appMalloc, + appFree, + appRealloc, + appCalloc, + NULL + }; + +static void showInfoTypes() +{ + printf(" o Object records\n"); + printf(" C CSSM records\n"); + printf(" p Plugin Common records\n"); + printf(" c CSP records\n"); + printf(" l CL records\n"); + printf(" t TP records\n"); + printf(" d DL records\n"); + printf(" a All records from Object DB\n"); + printf(" A All records from CDSA directory DB\n"); +} + +static void usage(char **argv) +{ + printf("Usage: %s info_type [options...]\n", argv[0]); + printf("info_type values:\n"); + showInfoTypes(); + printf(" h help\n"); + printf("Options:\n"); + printf(" i perform MDS_Install()\n"); + printf(" v verbose\n"); + printf(" k keep connected and go again\n"); + exit(1); +} + +#define NORM_KEY_LEN 20 + +/* print a key name, padding out to NORM_KEY_LEN columns */ +static void printName( + const char *attrName) +{ + printf(" %s", attrName); + int len = strlen(attrName); + if(len > NORM_KEY_LEN) { + return; + } + int numSpaces = NORM_KEY_LEN - len; + for(int i=0; iname != NULL) { + if(nameValues->value == val) { + printf("%s", nameValues->name); + return; + } + nameValues++; + } + } + /* Oh well */ + printf("0x%x", val); +} +#endif + +/* print value string, surrounded by single quotes, then a newline */ +static void printValue( + const CSSM_DATA *attrValue) +{ + printf("'"); + for(uint32 dex=0; dexLength; dex++) { + printf("%c", attrValue->Data[dex]); + } + printf("'\n"); +} + +/* Print one attribute value */ +static void dumpAttr( + CSSM_DB_ATTRIBUTE_FORMAT attrForm, + const CSSM_DATA *attrData) +{ + if((attrData == NULL) || (attrData->Data == NULL)) { + printf("\n"); + return; + } + void *data = attrData->Data; + switch(attrForm) { + case CSSM_DB_ATTRIBUTE_FORMAT_STRING: + printValue(attrData); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: // not really supported in MDS + case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: + { + unsigned val = *(unsigned *)data; + printf("0x%x\n", val); + break; + } + case CSSM_DB_ATTRIBUTE_FORMAT_BLOB: + { + printf("BLOB length %u : ", (unsigned)attrData->Length); + for(unsigned i=0; iLength; i++) { + unsigned dat = attrData->Data[i]; + printf("%02X ", dat); + } + printf("\n"); + break; + } + case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32: + { + printf("multi_int["); + uint32 numInts = attrData->Length / sizeof(uint32); + uint32 *uip = (uint32 *)data; + for(unsigned i=0; i 0) { + printf(", "); + } + printf("0x%x", (unsigned)(*uip++)); + } + printf("]\n"); + break; + } + default: + printf("***UNKNOWN FORMAT (%u), Length %u\n", + (unsigned)attrForm, (unsigned)attrData->Length); + break; + } +} + +/* + * Vanilla "dump one record" routine. Assumes format of all attribute labels + * as string. Uses a MDSNameValuePair ptr array in parallel to the attributes + * themselves to facilitate displaying numeric values as strings (e.g. + * "CSSM_ALGID_SHA1") where possible. + */ +static void dumpRecord( + const CSSM_DB_RECORD_ATTRIBUTE_DATA *recordAttrs) +{ + unsigned dex; + for(dex=0; dexNumberOfAttributes; dex++) { + const CSSM_DB_ATTRIBUTE_DATA *attrData = &recordAttrs->AttributeData[dex]; + if(attrData->Info.AttributeNameFormat != CSSM_DB_ATTRIBUTE_NAME_AS_STRING) { + printf("***BAD ATTR_NAME FORMAT (%u)\n", + (unsigned)attrData->Info.AttributeNameFormat); + continue; + } + const char *attrName = attrData->Info.Label.AttributeName; + printName(attrName); + printf(": "); + /* note currently in MDS NumberOfValues is always one or zero */ + for(unsigned attrNum=0; attrNumNumberOfValues; attrNum++) { + dumpAttr(attrData->Info.AttributeFormat, + &attrData->Value[attrNum]); + } + if(attrData->NumberOfValues == 0) { + printf("<>\n"); + } + } +} + +/* free attribute(s) allocated by MDS */ +static void freeAttrs( + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR recordAttrs) +{ + unsigned i; + + for(i=0; iNumberOfAttributes; i++) { + CSSM_DB_ATTRIBUTE_DATA_PTR attrData = &recordAttrs->AttributeData[i]; + if(attrData == NULL) { + /* fault of caller, who allocated the CSSM_DB_ATTRIBUTE_DATA */ + printf("***freeAttrs screwup: NULL attrData\n"); + return; + } + unsigned j; + for(j=0; jNumberOfValues; j++) { + CSSM_DATA_PTR data = &attrData->Value[j]; + if(data == NULL) { + /* fault of MDS, who said there was a value here */ + printf("***freeAttrs screwup: NULL data\n"); + return; + } + appFree(data->Data, NULL); + data->Data = NULL; + data->Length = 0; + } + appFree(attrData->Value, NULL); + attrData->Value = NULL; + } +} + +/* + * Fetch and display all records of specified CSSM_DB_RECORDTYPE. + */ +static void fetchAllAttrs( + MDS_FUNCS *mdsFuncs, + MDS_DB_HANDLE dlDb, + CSSM_DB_RECORDTYPE recordType) +{ + CSSM_QUERY query; + CSSM_DB_UNIQUE_RECORD_PTR record = NULL; + CSSM_RETURN crtn; + CSSM_HANDLE resultHand; + CSSM_DB_ATTRIBUTE_DATA attrs[MAX_MDS_ATTRS]; + CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; + const RelationInfo *relInfo; + + relInfo = MDSRecordTypeToRelation(recordType); + if(relInfo == NULL) { + printf("***UNKNOWN recordType %d\n", (int)recordType); + return; + } + + /* build an attr array from schema so we get all known attrs */ + memset(attrs, 0, sizeof(CSSM_DB_ATTRIBUTE_DATA) * MAX_MDS_ATTRS); + unsigned attrDex; + for(attrDex=0; attrDexNumberOfAttributes; attrDex++) { + attrs[attrDex].Info = relInfo->AttributeInfo[attrDex]; + } + recordAttrs.DataRecordType = recordType; + recordAttrs.NumberOfAttributes = relInfo->NumberOfAttributes; + recordAttrs.AttributeData = attrs; + + /* just search by recordType, no predicates */ + query.RecordType = recordType; + query.Conjunctive = CSSM_DB_NONE; + query.NumSelectionPredicates = 0; + query.SelectionPredicate = NULL; + query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? + query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? + query.QueryFlags = 0; // CSSM_QUERY_RETURN_DATA...FIXME - used? + + crtn = mdsFuncs->DataGetFirst(dlDb, + &query, + &resultHand, + &recordAttrs, + NULL, // No data + &record); + switch(crtn) { + case CSSM_OK: + break; // proceed + case CSSMERR_DL_ENDOFDATA: + printf("%s: no record found\n", relInfo->relationName); + return; + default: + printError("DataGetFirst", crtn); + return; + } + unsigned recNum = 0; + printf("%s:\n", relInfo->relationName); + printf(" record %d; numAttrs %d:\n", + recNum++, (int)recordAttrs.NumberOfAttributes); + + dumpRecord(&recordAttrs); + mdsFuncs->FreeUniqueRecord(dlDb, record); + freeAttrs(&recordAttrs); + + /* now the rest of them */ + /* hopefully we don't have to re-init the recordAttr array */ + for(;;) { + crtn = mdsFuncs->DataGetNext(dlDb, + resultHand, + &recordAttrs, + NULL, + &record); + switch(crtn) { + case CSSM_OK: + printf(" record %d; numAttrs %d:\n", + recNum++, (int)recordAttrs.NumberOfAttributes); + dumpRecord(&recordAttrs); + mdsFuncs->FreeUniqueRecord(dlDb, record); + freeAttrs(&recordAttrs); + break; // and go again + case CSSMERR_DL_ENDOFDATA: + /* normal termination */ + break; + default: + printError("DataGetNext", crtn); + break; + } + if(crtn != CSSM_OK) { + break; + } + } +} + +/* + * This is different - it's schema-independent. Fetch all records from specified + * DlDb which contain a ModuleID attribute. + */ +static void fetchAllRecords( + MDS_FUNCS *mdsFuncs, + MDS_DB_HANDLE dlDb) +{ + CSSM_QUERY query; + CSSM_DB_UNIQUE_RECORD_PTR record = NULL; + CSSM_RETURN crtn; + CSSM_HANDLE resultHand; + CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; + CSSM_DB_ATTRIBUTE_DATA theAttr; + CSSM_DB_ATTRIBUTE_INFO_PTR attrInfo = &theAttr.Info; + CSSM_DATA attrValue = {0, NULL}; + + recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_ANY; + recordAttrs.SemanticInformation = 0; + recordAttrs.NumberOfAttributes = 1; + recordAttrs.AttributeData = &theAttr; + + attrInfo->AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attrInfo->Label.AttributeName = (char *)"ModuleID"; + attrInfo->AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_STRING; + + theAttr.NumberOfValues = 1; + theAttr.Value = &attrValue; + + /* just search by recordType, no predicates */ + query.RecordType = CSSM_DL_DB_RECORD_ANY; + query.Conjunctive = CSSM_DB_NONE; + query.NumSelectionPredicates = 0; + query.SelectionPredicate = NULL; + query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? + query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? + query.QueryFlags = 0; // CSSM_QUERY_RETURN_DATA...FIXME - used? + + crtn = mdsFuncs->DataGetFirst(dlDb, + &query, + &resultHand, + &recordAttrs, + NULL, // No data + &record); + switch(crtn) { + case CSSM_OK: + break; // proceed + case CSSMERR_DL_ENDOFDATA: + printf("no record found\n"); + return; + default: + printError("DataGetFirst", crtn); + return; + } + unsigned recNum = 0; + printf("Records containing a ModuleID attribute:\n"); + printf(" record %d:\n", recNum++); + + dumpRecord(&recordAttrs); + mdsFuncs->FreeUniqueRecord(dlDb, record); + freeAttrs(&recordAttrs); + + /* now the rest of them */ + /* hopefully we don't have to re-init the recordAttr array */ + for(;;) { + crtn = mdsFuncs->DataGetNext(dlDb, + resultHand, + &recordAttrs, + NULL, + &record); + switch(crtn) { + case CSSM_OK: + printf(" record %d:\n", recNum++); + dumpRecord(&recordAttrs); + mdsFuncs->FreeUniqueRecord(dlDb, record); + freeAttrs(&recordAttrs); + break; // and go again + case CSSMERR_DL_ENDOFDATA: + /* normal termination */ + break; + default: + printError("DataGetNext", crtn); + break; + } + if(crtn != CSSM_OK) { + break; + } + } +} + +static void doInstall( + MDS_HANDLE mdsHand) +{ + CFAbsoluteTime start, end; + + start = CFAbsoluteTimeGetCurrent(); + CSSM_RETURN crtn = MDS_Install(mdsHand); + end = CFAbsoluteTimeGetCurrent(); + if(crtn) { + printError("MDS_Install", crtn); + } + else { + printf("MDS_Install took %gs\n", end - start); + } +} + +int main(int argc, char **argv) +{ + MDS_FUNCS mdsFuncs; + MDS_HANDLE mdsHand; + CSSM_RETURN crtn; + int arg; + char op; + char *dbName; + CSSM_DB_HANDLE dbHand = 0; + MDS_DB_HANDLE dlDb; + bool verbose = 0; + bool keepConnected = false; + bool install = false; + + if(argc < 2) { + usage(argv); + } + op = argv[1][0]; + if(op == 'h') { + usage(argv); + } + for(arg=2; arg +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "cspdlTesting.h" + +/* + * Temporary hack to use CSSM_KEYBLOB_WRAPPED_FORMAT_{PKCS7,PKCS8}, which + * are no longer supported as of 7/28/00 + */ +#define PKCS8_FORMAT_ENABLE 1 +#define PKCS7_FORMAT_ENABLE 0 + +#define ENCR_USAGE_NAME "noLabel" +#define ENCR_USAGE_NAME_LEN (strlen(ENCR_USAGE_NAME)) +#define WRAP_USAGE_NAME "noWrapLabel" +#define WRAP_USAGE_NAME_LEN (strlen(WRAP_USAGE_NAME)) +#define LOOPS_DEF 10 +#define MAX_PTEXT_SIZE 1000 +#define LOOP_PAUSE 10 + +/* + * A new restriction for X: when wrapping using an RSA key, you can't + * wrap a key which is bigger than the RSA key itself because the + * wrap (Encrypt) is a one-shot deal, unlike the OS9 CSP which + * handled multiple chunks. This only effectively restricts the + * use of an RSA key to wrap symmetric keys, which doesn't seem like + * an unreasonable restriction. + */ +#define RSA_WRAP_RESTRICTION 1 + +/* + * Currently the CSP can use wrapping keys flagged exclusively for wrapping + * (CSSM_KEYUSE_{WRAP,UNWRAP} for the actual wrap sinceÊthe wrap/unwrap op is + * done with an encrypt/decrypt op. The WrapKey op doesn't even see the + * wrapping key - it's in the context we pass it. Thus for now wrap/unwrap + * keys have to be marked with CSSM_KEYUSE_ANY. + */ +#define WRAP_USAGE_ANY 0 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" f (only wrap RSA private key)\n"); + printf(" d (only wrap DES key)\n"); + printf(" S (do symmetric wrap only)\n"); + printf(" a (do asymmetric wrap only)\n"); + printf(" n (do null wrap only)\n"); + printf(" m (dump malloc info)\n"); + printf(" r (ref keys only)\n"); + printf(" w (wrap only)\n"); + printf(" e (export)\n"); + printf(" q (quiet)\n"); + printf(" k (force PKCS7/8)\n"); + #if PKCS7_FORMAT_ENABLE || PKCS8_FORMAT_ENABLE + printf(" K (skip PKCS7/8) (pkcs normally enable)\n"); + #else + printf(" K (allow PKCS7/8) (pkcs normally disabled)\n"); + #endif /* PKCS_FORMAT_ENABLE */ + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" p(ause every %d loops)\n", LOOP_PAUSE); + printf(" h(elp)\n"); + exit(1); +} + +/* not all algs need this, pass it in anyway */ +CSSM_DATA initVector = {8, (uint8 *)"someVect"}; + +/* + * local verbose wrap/unwrap functions. + */ +/* wrap key function. */ +static CSSM_RETURN wrapKey(CSSM_CSP_HANDLE cspHand, + const CSSM_KEY_PTR unwrappedKey, // must be ref + const CSSM_KEY_PTR wrappingKey, + CSSM_ALGORITHMS wrapAlg, + CSSM_ENCRYPT_MODE wrapMode, + CSSM_KEYBLOB_FORMAT wrapFormat, // NONE, PKCS7, PKCS8 + CSSM_PADDING wrapPad, + CSSM_KEY_PTR wrappedKey) // RETURNED +{ + CSSM_CC_HANDLE ccHand; + CSSM_RETURN crtn; + CSSM_RETURN crtn2; + #if WRAP_KEY_REQUIRES_CREDS + CSSM_ACCESS_CREDENTIALS creds; + #endif + + #if 0 + if(unwrappedKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) { + printf("Hey! you can only wrap a reference key!\n"); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + #endif + memset(wrappedKey, 0, sizeof(CSSM_KEY)); + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + /* special case for NULL wrap - no wrapping key */ + if((wrappingKey == NULL) || + (wrappingKey->KeyHeader.KeyClass == CSSM_KEYCLASS_SESSION_KEY)) { + crtn = CSSM_CSP_CreateSymmetricContext(cspHand, + wrapAlg, + wrapMode, + &creds, // accessCred + wrappingKey, + &initVector, + wrapPad, // Padding + NULL, // Reserved + &ccHand); + if(crtn) { + printError("cspWrapKey/CreateContext", crtn); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + } + else { + crtn = CSSM_CSP_CreateAsymmetricContext(cspHand, + wrapAlg, + &creds, // passPhrase + wrappingKey, + wrapPad, // Padding + &ccHand); + if(crtn) { + printError("cspWrapKey/CreateContext", crtn); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + /* CMS requires 8-byte IV */ + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_INIT_VECTOR, + sizeof(CSSM_DATA), + CAT_Ptr, + &initVector, + 0); + if(crtn) { + printError("CSSM_UpdateContextAttributes", crtn); + return crtn; + } + } + if(wrapFormat != CSSM_KEYBLOB_WRAPPED_FORMAT_NONE) { + /* only add this attribute if it's not the default */ + CSSM_CONTEXT_ATTRIBUTE attr; + attr.AttributeType = CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT; + attr.AttributeLength = sizeof(uint32); + attr.Attribute.Uint32 = wrapFormat; + crtn = CSSM_UpdateContextAttributes( + ccHand, + 1, + &attr); + if(crtn) { + printError("CSSM_UpdateContextAttributes", crtn); + return crtn; + } + } + crtn = CSSM_WrapKey(ccHand, + #if WRAP_KEY_REQUIRES_CREDS + &creds, + #else + NULL, // AccessCred + #endif + unwrappedKey, + NULL, // DescriptiveData + wrappedKey); + if(crtn != CSSM_OK) { + printError("CSSM_WrapKey", crtn); + } + if((crtn2 = CSSM_DeleteContext(ccHand))) { + printError("CSSM_DeleteContext", crtn2); + } + return crtn; +} + +/* unwrap key function. */ +static CSSM_RETURN unwrapKey(CSSM_CSP_HANDLE cspHand, + const CSSM_KEY_PTR wrappedKey, + const CSSM_KEY_PTR unwrappingKey, + CSSM_ALGORITHMS unwrapAlg, + CSSM_ENCRYPT_MODE unwrapMode, + CSSM_PADDING unwrapPad, + CSSM_KEY_PTR unwrappedKey, // RETURNED + const unsigned char *keyLabel, + unsigned keyLabelLen) +{ + CSSM_CC_HANDLE ccHand; + CSSM_RETURN crtn; + CSSM_RETURN crtn2; + CSSM_DATA labelData; + uint32 keyAttr; + CSSM_DATA descData = { 0, NULL }; + CSSM_ACCESS_CREDENTIALS creds; + + memset(unwrappedKey, 0, sizeof(CSSM_KEY)); + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + if((unwrappingKey == NULL) || + (unwrappingKey->KeyHeader.KeyClass == CSSM_KEYCLASS_SESSION_KEY)) { + crtn = CSSM_CSP_CreateSymmetricContext(cspHand, + unwrapAlg, + unwrapMode, + &creds, // accessCreds + unwrappingKey, + &initVector, + unwrapPad, // Padding + 0, // Reserved + &ccHand); + if(crtn) { + printError("cspUnwrapKey/CreateContext", crtn); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + } + else { + crtn = CSSM_CSP_CreateAsymmetricContext(cspHand, + unwrapAlg, + &creds, // passPhrase, + unwrappingKey, + unwrapPad, // Padding + &ccHand); + if(crtn) { + printError("cspUnwrapKey/CreateContext", crtn); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + /* CMS requires 8-byte IV */ + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_INIT_VECTOR, + sizeof(CSSM_DATA), + CAT_Ptr, + &initVector, + 0); + if(crtn) { + printError("CSSM_UpdateContextAttributes", crtn); + return crtn; + } + } + labelData.Data = (uint8 *)keyLabel; + labelData.Length = keyLabelLen; + + /* + * New keyAttr - clear some old bits, make sure we ask for ref key + */ + keyAttr = wrappedKey->KeyHeader.KeyAttr; + keyAttr &= ~(CSSM_KEYATTR_ALWAYS_SENSITIVE | CSSM_KEYATTR_NEVER_EXTRACTABLE); + keyAttr |= CSSM_KEYATTR_RETURN_REF; + crtn = CSSM_UnwrapKey(ccHand, + NULL, // PublicKey + wrappedKey, + CSSM_KEYUSE_ANY, // FIXME + keyAttr, + &labelData, + NULL, // CredAndAclEntry + unwrappedKey, + &descData); // required + if(crtn != CSSM_OK) { + printError("CSSM_UnwrapKey", crtn); + } + if((crtn2 = CSSM_DeleteContext(ccHand))) { + printError("CSSM_DeleteContext", crtn2); + } + return crtn; +} + +#define UNWRAPPED_LABEL "unwrapped thing" +#define NULL_TEST 0 +#if NULL_TEST + +static int doTest(CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR encrKey, + CSSM_KEY_PTR decrKey, // we wrap this one + CSSM_KEY_PTR wrappingKey, // ...using this key, NULL for null wrap + CSSM_KEY_PTR unwrappingKey, + CSSM_ALGORITHMS wrapAlg, + CSSM_ENCRYPT_MODE wrapMode, + CSSM_PADDING wrapPad, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE encrMode, + CSSM_PADDING encrPad, + CSSM_BOOL wrapOnly, + uint32 maxPtextSize, // max size to encrypt + CSSM_BOOL quiet) +{ + return 0; +} +#else /* NULL_TEST */ +/* + * NULL Wrapping decrKey - a private key - only works for DEBUG CSPs. + * We'll always wrap decrKey, except for NULL wrap when + * NULL_WRAP_DECR_KEY is false. + */ +#define NULL_WRAP_DECR_KEY 1 + +static int doTest(CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR encrKey, // we wrap this one + CSSM_KEY_PTR decrKey, // ...or this one, depending on WRAP_DECR_KEY + CSSM_KEY_PTR wrappingKey, // ...using this key, NULL for null wrap + CSSM_KEY_PTR unwrappingKey, + CSSM_ALGORITHMS wrapAlg, + CSSM_ENCRYPT_MODE wrapMode, + CSSM_KEYBLOB_FORMAT wrapFormat, // NONE, PKCS7, PKCS8 + CSSM_PADDING wrapPad, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE encrMode, + CSSM_PADDING encrPad, + CSSM_BOOL wrapOnly, + uint32 maxPtextSize, // max size to encrypt + CSSM_BOOL quiet) +{ + CSSM_DATA ptext; + CSSM_DATA ctext; + CSSM_DATA rptext; + CSSM_KEY wrappedKey; + CSSM_KEY unwrappedKey; + CSSM_RETURN crtn; + CSSM_KEY_PTR realEncrKey; // encrKey or &unwrappedKey + CSSM_KEY_PTR realDecrKey; // decrKey or &unwrappedKey + + /* wrap decrKey or encrKey using wrappingKey ==> wrappedKey */ + if((wrappingKey == NULL) && !NULL_WRAP_DECR_KEY) { + /* NULL wrap of pub key */ + crtn = wrapKey(cspHand, + encrKey, + wrappingKey, + wrapAlg, + wrapMode, + wrapFormat, + wrapPad, + &wrappedKey); + realEncrKey = &unwrappedKey; + realDecrKey = decrKey; + } + else { + /* normal case, wrap priv key (may be NULL if NULL_WRAP_DECR_KEY) */ + crtn = wrapKey(cspHand, + decrKey, + wrappingKey, + wrapAlg, + wrapMode, + wrapFormat, + wrapPad, + &wrappedKey); + realEncrKey = encrKey; + realDecrKey = &unwrappedKey; + } + + if(crtn) { + return testError(quiet); + } + if((wrappingKey != NULL) && // skip for NULL wrap + (wrapFormat != CSSM_KEYBLOB_WRAPPED_FORMAT_NONE)) { + /* don't want default, verify we got what we want */ + if(wrappedKey.KeyHeader.Format != wrapFormat) { + printf("wrapped key format mismatch: expect %u; got %u\n", + (unsigned)wrapFormat, (unsigned)wrappedKey.KeyHeader.Format); + if(testError(quiet)) { + return 1; + } + } + } + if(wrapOnly) { + cspFreeKey(cspHand, &wrappedKey); + goto done; + } + /* unwrap wrappedKey using unwrappingKey ==> unwrappedKey; */ + crtn = unwrapKey(cspHand, + &wrappedKey, + unwrappingKey, + wrapAlg, + wrapMode, + wrapPad, + &unwrappedKey, + (uint8 *)UNWRAPPED_LABEL, + 15); + if(crtn) { + return testError(quiet); + } + + /* cook up ptext */ + ptext.Data = (uint8 *)CSSM_MALLOC(maxPtextSize); + simpleGenData(&ptext, 1, maxPtextSize); + /* encrypt using realEncrKey ==> ctext */ + ctext.Data = NULL; + ctext.Length = 0; + crtn = cspEncrypt(cspHand, + encrAlg, + encrMode, + encrPad, + realEncrKey, + NULL, // no 2nd key + 0, // effectiveKeySize + 0, // rounds + &initVector, + &ptext, + &ctext, + CSSM_TRUE); // mallocCtext + if(crtn) { + return testError(quiet); + } + + /* decrypt ctext with realDecrKey ==> rptext; */ + rptext.Data = NULL; + rptext.Length = 0; + crtn = cspDecrypt(cspHand, + encrAlg, + encrMode, + encrPad, + realDecrKey, + NULL, // no 2nd key + 0, // effectiveKeySize + 0, // rounds + &initVector, + &ctext, + &rptext, + CSSM_TRUE); + if(crtn) { + return testError(quiet); + } + + /* compare ptext vs. rptext; */ + if(ptext.Length != rptext.Length) { + printf("ptext length mismatch\n"); + return testError(quiet); + } + if(memcmp(ptext.Data, rptext.Data, ptext.Length)) { + printf("***data miscompare\n"); + return testError(quiet); + } + /* free resources */ + cspFreeKey(cspHand, &wrappedKey); + cspFreeKey(cspHand, &unwrappedKey); + CSSM_FREE(ptext.Data); + CSSM_FREE(ctext.Data); + CSSM_FREE(rptext.Data); +done: + return 0; +} +#endif /* NULL_TEST */ + +int main(int argc, char **argv) +{ + int arg; + char *argp; + int i; + CSSM_CSP_HANDLE cspHand; + CSSM_RETURN crtn; + CSSM_KEY origPub; // we generate if !desSubj + CSSM_KEY origPriv; + CSSM_KEY_PTR origSess; // we generate if desSubj + CSSM_KEY_PTR origEncrKey; // pts to origPub or origSess + CSSM_KEY_PTR origDecrKey; // pts to origPriv or origSess + CSSM_ALGORITHMS encrAlg; + CSSM_ENCRYPT_MODE encrMode; + CSSM_PADDING encrPad; + int rtn = 0; + CSSM_BOOL genRsaKey; + uint32 maxPtextSize; + CSSM_BOOL encrIsRef = CSSM_TRUE; + CSSM_BOOL decrIsRef = CSSM_TRUE; + CSSM_KEYBLOB_FORMAT wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_NONE; + unsigned loop; + + /* user-specified vars */ + unsigned loops = LOOPS_DEF; + CSSM_BOOL pause = CSSM_FALSE; + CSSM_BOOL doSymmWrap = CSSM_TRUE; + CSSM_BOOL doAsymmWrap = CSSM_TRUE; + CSSM_BOOL doNullWrap = CSSM_TRUE; + CSSM_BOOL doSymmEncrOnly = CSSM_FALSE; + CSSM_BOOL doAsymmEncrOnly = CSSM_FALSE; + CSSM_BOOL wrapOnly = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL bareCsp = CSSM_TRUE; + CSSM_BOOL forcePkcs = CSSM_FALSE; + CSSM_BOOL refKeysOnly = CSSM_FALSE; + #if PKCS_FORMAT_ENABLE + CSSM_BOOL skipPkcs = CSSM_FALSE; + #else + CSSM_BOOL skipPkcs = CSSM_TRUE; + #endif + + for(arg=1; arg PKCS7 */ + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7; + } + else { + /* default */ + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_NONE; + } + if(doTest(cspHand, + origEncrKey, + origDecrKey, + wrapKey, + wrapKey, + CSSM_ALGID_DES, // wrapAlg + CSSM_ALGMODE_CBCPadIV8, // wrapMode + wrapFormat, + CSSM_PADDING_PKCS5, // wrapPad + encrAlg, + encrMode, + encrPad, + wrapOnly, + maxPtextSize, + quiet)) { + rtn = 1; + goto testDone; + } + cspFreeKey(cspHand, wrapKey); + CSSM_FREE(wrapKey); // mallocd by cspGenSymKey + wrapKey = NULL; + } + if(doAsymmWrap && + !(RSA_WRAP_RESTRICTION && (origEncrKey != origDecrKey))) { + /* skip wrapping asymmetric key with asymmetric key */ + CSSM_KEY wrapPrivKey; + CSSM_KEY wrapPubKey; + + if(!quiet) { + printf(" ...Doing asymmetric wrap\n"); + } + crtn = cspGenKeyPair(cspHand, + CSSM_ALGID_RSA, + WRAP_USAGE_NAME, + WRAP_USAGE_NAME_LEN, + CSP_RSA_KEY_SIZE_DEFAULT, + &wrapPubKey, + CSSM_TRUE, // both are ref + WRAP_USAGE_ANY ? CSSM_KEYUSE_ANY : CSSM_KEYUSE_WRAP, + CSSM_KEYBLOB_RAW_FORMAT_NONE, + &wrapPrivKey, + CSSM_TRUE, // FIXME privIsRef + WRAP_USAGE_ANY ? CSSM_KEYUSE_ANY : CSSM_KEYUSE_UNWRAP, + CSSM_KEYBLOB_RAW_FORMAT_NONE, + CSSM_FALSE); // genSeed + if(crtn) { + rtn = 1; + goto testDone; + } + if(forcePkcs) { + /* asymmetric wrapping key ==> PKCS8 */ + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8; + } + else { + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_NONE; + } + if(doTest(cspHand, + origEncrKey, + origDecrKey, + &wrapPubKey, + &wrapPrivKey, + CSSM_ALGID_RSA, // wrapAlg + CSSM_ALGMODE_NONE, // wrapMode + wrapFormat, + CSSM_PADDING_PKCS1, // wrapPad + encrAlg, + encrMode, + encrPad, + wrapOnly, + maxPtextSize, + quiet)) { + rtn = 1; + goto testDone; + } + cspFreeKey(cspHand, &wrapPubKey); + cspFreeKey(cspHand, &wrapPrivKey); + } + //if(doNullWrap && (origDecrKey != origEncrKey)) { + if(doNullWrap) { + /* with X, we can do NULL wrap/unwrap of any key */ + if(!quiet) { + printf(" ...Doing NULL wrap\n"); + } + if(doTest(cspHand, + origEncrKey, + origDecrKey, + NULL, + NULL, + CSSM_ALGID_NONE, // wrapAlg + CSSM_ALGMODE_NONE, // wrapMode + CSSM_KEYBLOB_WRAPPED_FORMAT_NONE, + CSSM_PADDING_NONE, // wrapPad + encrAlg, + encrMode, + encrPad, + wrapOnly, + maxPtextSize, + quiet)) { + rtn = 1; + goto testDone; + } + } + + if(origSess != NULL) { + cspFreeKey(cspHand, origSess); + CSSM_FREE(origSess); + } + if(genRsaKey) { + cspFreeKey(cspHand, &origPub); + cspFreeKey(cspHand, &origPriv); + } + if(loops && (loop == loops)) { + break; + } + } +testDone: + CSSM_ModuleDetach(cspHand); + if((rtn == 0) && !quiet) { + printf("%s test complete\n", argv[0]); + } + return rtn; +} diff --git a/SecurityTests/cspxutils/pbeTest/Makefile b/SecurityTests/cspxutils/pbeTest/Makefile new file mode 100644 index 00000000..82a48f6c --- /dev/null +++ b/SecurityTests/cspxutils/pbeTest/Makefile @@ -0,0 +1,54 @@ +# name of executable to build +EXECUTABLE=pbeTest +# C++ source (with .cpp extension) +CPSOURCE= +# C source (.c extension) +CSOURCE= pbeTest.c + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/pbeTest/pbeTest.c b/SecurityTests/cspxutils/pbeTest/pbeTest.c new file mode 100644 index 00000000..ddce2c73 --- /dev/null +++ b/SecurityTests/cspxutils/pbeTest/pbeTest.c @@ -0,0 +1,1270 @@ +/* Copyright (c) 1998,2003-2005,2008 Apple Inc. + * + * pbeTest.c - test CSP PBE-style DeriveKey(). + * + * Revision History + * ---------------- + * 15 May 2000 Doug Mitchell + * Ported to X/CDSA2. + * 13 Aug 1998 Doug Mitchell at NeXT + * Created. + */ +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "cspdlTesting.h" + +/* we need to know a little bit about AES for this test.... */ +#define AES_BLOCK_SIZE 16 /* bytes */ + +/* + * Defaults. + */ +#define LOOPS_DEF 10 +#define MIN_PTEXT_SIZE AES_BLOCK_SIZE /* for non-padding tests */ +#define MAX_PTEXT_SIZE 1000 +#define MAX_PASSWORD_SIZE 64 +#define MAX_SALT_SIZE 32 +#define MIN_ITER_COUNT 1000 +#define MAX_ITER_COUNT 2000 +#define MAX_IV_SIZE AES_BLOCK_SIZE + +/* min values not currently exported by CSP */ +#define APPLE_PBE_MIN_PASSWORD 8 +#define APPLE_PBE_MIN_SALT 8 + +/* static IV for derive algorithms which don't create one */ +CSSM_DATA staticIv = {MAX_IV_SIZE, (uint8 *)"someIvOrOther..."}; + +/* + * Enumerate algs our own way to allow iteration. + */ +typedef unsigned privAlg; +enum { + /* PBE algs */ + pbe_pbkdf2 = 1, + // other unsupported for now + pbe_PKCS12 = 1, + pbe_MD5, + pbe_MD2, + pbe_SHA1, + + /* key gen algs */ + pka_ASC, + pka_RC4, + pka_DES, + pka_RC2, + pka_RC5, + pka_3DES, + pka_AES +}; + +#define PBE_ALG_FIRST pbe_pbkdf2 +#define PBE_ALG_LAST pbe_pbkdf2 +#define ENCR_ALG_FIRST pka_ASC +#define ENCR_ALG_LAST pka_AES +#define ENCR_ALG_LAST_EXPORT pka_RC5 + +/* + * Args passed to each test + */ +typedef struct { + CSSM_CSP_HANDLE cspHand; + CSSM_ALGORITHMS keyAlg; + CSSM_ALGORITHMS encrAlg; + uint32 keySizeInBits; + uint32 effectiveKeySizeInBits; // 0 means not used + const char *keyAlgStr; + CSSM_ENCRYPT_MODE encrMode; + CSSM_PADDING encrPad; + CSSM_ALGORITHMS deriveAlg; + const char *deriveAlgStr; + CSSM_DATA_PTR ptext; + CSSM_DATA_PTR password; + CSSM_DATA_PTR salt; + uint32 iterCount; + CSSM_BOOL useInitVector; // encrypt needs an IV + uint32 ivSize; + CSSM_BOOL genInitVector; // DeriveKey generates an IV + CSSM_BOOL useRefKey; + CSSM_BOOL quiet; +} testArgs; + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" e(xport)\n"); + printf(" r(epeatOnly)\n"); + printf(" z(ero length password)\n"); + printf(" p(ause after each loop)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +/* + * Given a privAlg value, return various associated stuff. + */ +static void algInfo(privAlg alg, // pbe_MD5, etc. + CSSM_ALGORITHMS *cdsaAlg, // CSSM_ALGID_MD5_PBE, etc. RETURNED + // key alg for key gen algs + CSSM_ALGORITHMS *encrAlg, // encrypt/decrypt alg for key + // gen algs + CSSM_ENCRYPT_MODE *mode, // RETURNED + CSSM_PADDING *padding, // RETURNED + CSSM_BOOL *useInitVector, // RETURNED, for encrypt/decrypt + uint32 *ivSize, // RETURNED, in bytes + CSSM_BOOL *genInitVector, // RETURNED, for deriveKey + const char **algStr) // RETURNED +{ + /* default or irrelevant fields */ + *mode = CSSM_ALGMODE_NONE; + *useInitVector = CSSM_FALSE; + *genInitVector = CSSM_FALSE; // DeriveKey doesn't do this now + *padding = CSSM_PADDING_PKCS1; + *ivSize = 8; // thje usual size, if needed + *encrAlg = CSSM_ALGID_NONE; + + switch(alg) { + case pbe_pbkdf2: + *cdsaAlg = CSSM_ALGID_PKCS5_PBKDF2; + *algStr = "PBKDF2"; + return; + /* these are not supported */ + #if 0 + case pbe_PKCS12: + *cdsaAlg = CSSM_ALGID_SHA1_PBE_PKCS12; + *algStr = "PKCS12"; + return; + case pbe_MD5: + *cdsaAlg = CSSM_ALGID_MD5_PBE; + *algStr = "MD5"; + return; + case pbe_MD2: + *cdsaAlg = CSSM_ALGID_MD2_PBE; + *algStr = "MD2"; + return; + case pbe_SHA1: + *cdsaAlg = CSSM_ALGID_SHA1_PBE; + *algStr = "SHA1"; + return; + case pka_ASC: + *cdsaAlg = CSSM_ALGID_ASC; + *algStr = "ASC"; + return; + #endif + case pka_DES: + *cdsaAlg = *encrAlg = CSSM_ALGID_DES; + *useInitVector = CSSM_TRUE; + *mode = CSSM_ALGMODE_CBCPadIV8; + *algStr = "DES"; + return; + case pka_3DES: + *cdsaAlg = CSSM_ALGID_3DES_3KEY; + *encrAlg = CSSM_ALGID_3DES_3KEY_EDE; + *useInitVector = CSSM_TRUE; + *mode = CSSM_ALGMODE_CBCPadIV8; + *algStr = "3DES"; + return; + case pka_AES: + *cdsaAlg = *encrAlg = CSSM_ALGID_AES; + *useInitVector = CSSM_TRUE; + *mode = CSSM_ALGMODE_CBCPadIV8; + *padding = CSSM_PADDING_PKCS5; + *ivSize = AES_BLOCK_SIZE; // per the default block size + *algStr = "AES"; + return; + case pka_RC2: + *cdsaAlg = *encrAlg = CSSM_ALGID_RC2; + *useInitVector = CSSM_TRUE; + *mode = CSSM_ALGMODE_CBCPadIV8; + *algStr = "RC2"; + return; + case pka_RC4: + *cdsaAlg = *encrAlg = CSSM_ALGID_RC4; + /* initVector false */ + *mode = CSSM_ALGMODE_NONE; + *algStr = "RC4"; + return; + case pka_RC5: + *cdsaAlg = *encrAlg = CSSM_ALGID_RC5; + *algStr = "RC5"; + *mode = CSSM_ALGMODE_CBCPadIV8; + *useInitVector = CSSM_TRUE; + return; + case pka_ASC: + *cdsaAlg = *encrAlg = CSSM_ALGID_ASC; + /* initVector false */ + *algStr = "ASC"; + *mode = CSSM_ALGMODE_NONE; + return; + default: + printf("BRRZZZT! Update algInfo()!\n"); + testError(CSSM_TRUE); + } +} + +/* a handy "compare two CSSM_DATAs" ditty */ +static CSSM_BOOL compareData(const CSSM_DATA_PTR d1, + const CSSM_DATA_PTR d2) +{ + if(d1->Length != d2->Length) { + return CSSM_FALSE; + } + if(memcmp(d1->Data, d2->Data, d1->Length)) { + return CSSM_FALSE; + } + return CSSM_TRUE; +} + +/* generate random one-bit byte */ +static uint8 randBit() +{ + return 1 << genRand(0, 7); +} + +/* + * Writer debug - assertion failure when ctext[1].Data is NULL + * but length is nonzero + */ +#define SAFE_CTEXT_ARRAY 0 + +/* + * Encrypt ptext using specified key, IV, effectiveKeySizeInBits + */ +static int encryptCom(CSSM_CSP_HANDLE cspHand, + const char *testName, + CSSM_DATA_PTR ptext, + CSSM_KEY_PTR key, + CSSM_ALGORITHMS alg, + CSSM_ENCRYPT_MODE mode, + CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc. + CSSM_DATA_PTR iv, // may be NULL + uint32 effectiveKeySizeInBits, // may be 0 + CSSM_DATA_PTR ctext, // RETURNED + CSSM_BOOL quiet) +{ + CSSM_CC_HANDLE cryptHand; + CSSM_RETURN crtn; + CSSM_SIZE bytesEncrypted; + CSSM_DATA remData; + int rtn; + #if SAFE_CTEXT_ARRAY + CSSM_DATA safeCtext[2]; + safeCtext[0] = *ctext; + safeCtext[1].Data = NULL; + safeCtext[1].Length = 10; // lie, but shouldn't use this! + #else + // printf("+++ ctext[0] = %d:0x%x; ctext[1] = %d:0x%x\n", + // ctext[0].Length, ctext[0].Data, + // ctext[1].Length, ctext[1].Data); + #endif + + cryptHand = genCryptHandle(cspHand, + alg, + mode, + padding, + key, + NULL, // no 2nd key + iv, // InitVector + effectiveKeySizeInBits, + 0); // rounds + if(cryptHand == 0) { + return testError(quiet); + } + + remData.Data = NULL; + remData.Length = 0; + crtn = CSSM_EncryptData(cryptHand, + ptext, + 1, + #if SAFE_CTEXT_ARRAY + &safeCtext[0], + #else + ctext, + #endif + 1, + &bytesEncrypted, + &remData); + #if SAFE_CTEXT_ARRAY + *ctext = safeCtext[0]; + #endif + + if(crtn) { + printError("CSSM_EncryptData", crtn); + rtn = testError(quiet); + goto done; + } + if(remData.Length != 0) { + //printf("***WARNING: nonzero remData on encrypt!\n"); + /* new for CDSA2 - possible remData even if we ask the CSP to + * malloc ctext */ + ctext->Data = (uint8 *)appRealloc(ctext->Data, bytesEncrypted, NULL); + memmove(ctext->Data + ctext->Length, + remData.Data, + bytesEncrypted - ctext->Length); + appFreeCssmData(&remData, CSSM_FALSE); + } + /* new for CDSA 2 */ + ctext->Length = bytesEncrypted; + rtn = 0; +done: + if(CSSM_DeleteContext(cryptHand)) { + printError("CSSM_DeleteContext", 0); + rtn = 1; + } + return rtn; +} + +/* + * Decrypt ctext using specified key, IV, effectiveKeySizeInBits + */ +static int decryptCom(CSSM_CSP_HANDLE cspHand, + const char *testName, + CSSM_DATA_PTR ctext, + CSSM_KEY_PTR key, + CSSM_ALGORITHMS alg, + CSSM_ENCRYPT_MODE mode, + CSSM_PADDING padding, + CSSM_DATA_PTR iv, // may be NULL + uint32 effectiveKeySizeInBits, // may be 0 + CSSM_DATA_PTR ptext, // RETURNED + CSSM_BOOL quiet) +{ + CSSM_CC_HANDLE cryptHand; + CSSM_RETURN crtn; + CSSM_SIZE bytesDecrypted; + CSSM_DATA remData; + int rtn; + + cryptHand = genCryptHandle(cspHand, + alg, + mode, + padding, + key, + NULL, // no 2nd key + iv, // InitVector + effectiveKeySizeInBits, + 0); // rounds + if(cryptHand == 0) { + return testError(quiet); + } + remData.Data = NULL; + remData.Length = 0; + crtn = CSSM_DecryptData(cryptHand, + ctext, + 1, + ptext, + 1, + &bytesDecrypted, + &remData); + if(crtn) { + printError("CSSM_DecryptData", crtn); + rtn = testError(quiet); + goto done; + } + if(remData.Length != 0) { + //printf("***WARNING: nonzero remData on decrypt!\n"); + /* new for CDSA2 - possible remData even if we ask the CSP to + * malloc ptext */ + ptext->Data = (uint8 *)appRealloc(ptext->Data, bytesDecrypted, NULL); + memmove(ptext->Data + ptext->Length, + remData.Data, + bytesDecrypted - ptext->Length); + appFreeCssmData(&remData, CSSM_FALSE); + } + /* new for CDSA 2 */ + ptext->Length = bytesDecrypted; + rtn = 0; +done: + if(CSSM_DeleteContext(cryptHand)) { + printError("CSSM_DeleteContext", 0); + rtn = 1; + } + return rtn; +} + +/* + * Common test portion + * encrypt ptext with key1, iv1 + * encrypt ptext with key2, iv2 + * compare 2 ctexts; expect failure; + */ + +#define TRAP_WRITER_ERR 1 + +static int testCommon(CSSM_CSP_HANDLE cspHand, + const char *testName, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE encrMode, + CSSM_PADDING encrPad, + uint32 effectiveKeySizeInBits, + CSSM_DATA_PTR ptext, + CSSM_KEY_PTR key1, + CSSM_DATA_PTR iv1, + CSSM_KEY_PTR key2, + CSSM_DATA_PTR iv2, + CSSM_BOOL quiet) +{ + CSSM_DATA ctext1; + CSSM_DATA ctext2; + ctext1.Data = NULL; + ctext1.Length = 0; + ctext2.Data = NULL; + ctext2.Length = 0; + if(encryptCom(cspHand, + testName, + ptext, + key1, + encrAlg, + encrMode, + encrPad, + iv1, + effectiveKeySizeInBits, + &ctext1, + quiet)) { + return 1; + } + #if TRAP_WRITER_ERR + if(ctext2.Data != NULL){ + printf("Hey! encryptCom(ptext, ctext1 modified ctext2!\n"); + if(testError(quiet)) { + return 1; + } + } + #endif + if(encryptCom(cspHand, + testName, + ptext, + key2, + encrAlg, + encrMode, + encrPad, + iv2, + effectiveKeySizeInBits, + &ctext2, + quiet)) { + return 1; + } + if(compareData(&ctext1, &ctext2)) { + printf("***%s: Unexpected Data compare!\n", testName); + return testError(quiet); + } + appFreeCssmData(&ctext1, CSSM_FALSE); + appFreeCssmData(&ctext2, CSSM_FALSE); + return 0; +} + +/** + ** inidividual tests. + **/ +#define KEY_LABEL1 "noLabel1" +#define KEY_LABEL2 "noLabel2" +#define KEY_LABEL_LEN strlen(KEY_LABEL1) +#define REPEAT_ON_ERROR 1 + +/* test repeatability - the only test here which actually decrypts */ +static int repeatTest(testArgs *targs) +{ + /* + generate two keys with same params; + encrypt ptext with key1; + decrypt ctext with key2; + compare; expect success; + */ + CSSM_KEY_PTR key1; + CSSM_KEY_PTR key2; + CSSM_DATA iv1; + CSSM_DATA iv2; + CSSM_DATA_PTR ivp1; + CSSM_DATA_PTR ivp2; + CSSM_DATA ctext; + CSSM_DATA rptext; + CSSM_BOOL gotErr = CSSM_FALSE; + + if(targs->useInitVector) { + if(targs->genInitVector) { + ivp1 = &iv1; + ivp2 = &iv2; + } + else { + staticIv.Length = targs->ivSize; + ivp1 = ivp2 = &staticIv; + } + } + else { + ivp1 = ivp2 = NULL; + } + /* these need to be init'd regardless */ + iv1.Data = NULL; + iv1.Length = 0; + iv2.Data = NULL; + iv2.Length = 0; + ctext.Data = NULL; + ctext.Length = 0; + rptext.Data = NULL; + rptext.Length = 0; +repeatDerive: + key1 = cspDeriveKey(targs->cspHand, + targs->deriveAlg, + targs->keyAlg, + KEY_LABEL1, + KEY_LABEL_LEN, + CSSM_KEYUSE_ENCRYPT, + targs->keySizeInBits, + targs->useRefKey, + targs->password, + targs->salt, + targs->iterCount, + &iv1); + if(key1 == NULL) { + return testError(targs->quiet); + } + key2 = cspDeriveKey(targs->cspHand, + targs->deriveAlg, + targs->keyAlg, + KEY_LABEL2, + KEY_LABEL_LEN, + CSSM_KEYUSE_DECRYPT, + targs->keySizeInBits, + targs->useRefKey, + targs->password, + targs->salt, + targs->iterCount, + &iv2); + if(key2 == NULL) { + return testError(targs->quiet); + } +repeatEnc: + if(encryptCom(targs->cspHand, + "repeatTest", + targs->ptext, + key1, + targs->encrAlg, + targs->encrMode, + targs->encrPad, + ivp1, + targs->effectiveKeySizeInBits, + &ctext, + targs->quiet)) { + return 1; + } + if(decryptCom(targs->cspHand, + "repeatTest", + &ctext, + key2, + targs->encrAlg, + targs->encrMode, + targs->encrPad, + ivp2, + targs->effectiveKeySizeInBits, + &rptext, + targs->quiet)) { + return 1; + } + if(gotErr || !compareData(targs->ptext, &rptext)) { + printf("***Data miscompare in repeatTest\n"); + if(REPEAT_ON_ERROR) { + char str; + + gotErr = CSSM_TRUE; + fpurge(stdin); + printf("Repeat enc/dec (r), repeat derive (d), continue (c), abort (any)? "); + str = getchar(); + switch(str) { + case 'r': + appFreeCssmData(&ctext, CSSM_FALSE); + appFreeCssmData(&rptext, CSSM_FALSE); + goto repeatEnc; + case 'd': + appFreeCssmData(&ctext, CSSM_FALSE); + appFreeCssmData(&rptext, CSSM_FALSE); + appFreeCssmData(&iv1, CSSM_FALSE); + appFreeCssmData(&iv2, CSSM_FALSE); + cspFreeKey(targs->cspHand, key1); + cspFreeKey(targs->cspHand, key2); + goto repeatDerive; + case 'c': + break; + default: + return 1; + } + } + else { + return testError(targs->quiet); + } + } + appFreeCssmData(&ctext, CSSM_FALSE); + appFreeCssmData(&rptext, CSSM_FALSE); + appFreeCssmData(&iv1, CSSM_FALSE); + appFreeCssmData(&iv2, CSSM_FALSE); + cspFreeKey(targs->cspHand, key1); + cspFreeKey(targs->cspHand, key2); + CSSM_FREE(key1); + CSSM_FREE(key2); + return 0; +} + +/* ensure iterCount alters key */ +static int iterTest(testArgs *targs) +{ + /* + generate key1(iterCount), key2(iterCount+1); + encrypt ptext with key1; + encrypt ptext with key2; + compare 2 ctexts; expect failure; + */ + CSSM_KEY_PTR key1; + CSSM_KEY_PTR key2; + CSSM_DATA iv1; + CSSM_DATA iv2; + CSSM_DATA_PTR ivp1; + CSSM_DATA_PTR ivp2; + if(targs->useInitVector) { + if(targs->genInitVector) { + ivp1 = &iv1; + ivp2 = &iv2; + } + else { + staticIv.Length = targs->ivSize; + ivp1 = ivp2 = &staticIv; + } + } + else { + ivp1 = ivp2 = NULL; + } + /* these need to be init'd regardless */ + iv1.Data = NULL; + iv1.Length = 0; + iv2.Data = NULL; + iv2.Length = 0; + key1 = cspDeriveKey(targs->cspHand, + targs->deriveAlg, + targs->keyAlg, + KEY_LABEL1, + KEY_LABEL_LEN, + CSSM_KEYUSE_ENCRYPT, + targs->keySizeInBits, + targs->useRefKey, + targs->password, + targs->salt, + targs->iterCount, + &iv1); + if(key1 == NULL) { + return testError(targs->quiet); + } + key2 = cspDeriveKey(targs->cspHand, + targs->deriveAlg, + targs->keyAlg, + KEY_LABEL2, + KEY_LABEL_LEN, + CSSM_KEYUSE_ENCRYPT, + targs->keySizeInBits, + targs->useRefKey, + targs->password, + targs->salt, + targs->iterCount + 1, // the changed param + &iv2); + if(key2 == NULL) { + return testError(targs->quiet); + } + if(testCommon(targs->cspHand, + "iterTest", + targs->encrAlg, + targs->encrMode, + targs->encrPad, + targs->effectiveKeySizeInBits, + targs->ptext, + key1, + ivp1, + key2, + ivp2, + targs->quiet)) { + return 1; + } + appFreeCssmData(&iv1, CSSM_FALSE); + appFreeCssmData(&iv2, CSSM_FALSE); + cspFreeKey(targs->cspHand, key1); + cspFreeKey(targs->cspHand, key2); + CSSM_FREE(key1); + CSSM_FREE(key2); + return 0; +} + +/* ensure password alters key */ +static int passwordTest(testArgs *targs) +{ + /* + generate key1(password), key2(munged password); + encrypt ptext with key1; + encrypt ptext with key2; + compare 2 ctexts; expect failure; + */ + CSSM_KEY_PTR key1; + CSSM_KEY_PTR key2; + CSSM_DATA iv1; + CSSM_DATA iv2; + CSSM_DATA_PTR ivp1; + CSSM_DATA_PTR ivp2; + uint32 mungeDex; + uint32 mungeBits; + if(targs->useInitVector) { + if(targs->genInitVector) { + ivp1 = &iv1; + ivp2 = &iv2; + } + else { + staticIv.Length = targs->ivSize; + ivp1 = ivp2 = &staticIv; + } + } + else { + ivp1 = ivp2 = NULL; + } + /* these need to be init'd regardless */ + iv1.Data = NULL; + iv1.Length = 0; + iv2.Data = NULL; + iv2.Length = 0; + key1 = cspDeriveKey(targs->cspHand, + targs->deriveAlg, + targs->keyAlg, + KEY_LABEL1, + KEY_LABEL_LEN, + CSSM_KEYUSE_ENCRYPT, + targs->keySizeInBits, + targs->useRefKey, + targs->password, + targs->salt, + targs->iterCount, + &iv1); + if(key1 == NULL) { + return testError(targs->quiet); + } + /* munge password */ + mungeDex = genRand(0, targs->password->Length - 1); + mungeBits = randBit(); + targs->password->Data[mungeDex] ^= mungeBits; + key2 = cspDeriveKey(targs->cspHand, + targs->deriveAlg, + targs->keyAlg, + KEY_LABEL2, + KEY_LABEL_LEN, + CSSM_KEYUSE_ENCRYPT, + targs->keySizeInBits, + targs->useRefKey, + targs->password, // the changed param + targs->salt, + targs->iterCount, + &iv2); + if(key2 == NULL) { + return testError(targs->quiet); + } + if(testCommon(targs->cspHand, + "passwordTest", + targs->encrAlg, + targs->encrMode, + targs->encrPad, + targs->effectiveKeySizeInBits, + targs->ptext, + key1, + ivp1, + key2, + ivp2, + targs->quiet)) { + return 1; + } + /* restore */ + targs->password->Data[mungeDex] ^= mungeBits; + appFreeCssmData(&iv1, CSSM_FALSE); + appFreeCssmData(&iv2, CSSM_FALSE); + cspFreeKey(targs->cspHand, key1); + cspFreeKey(targs->cspHand, key2); + CSSM_FREE(key1); + CSSM_FREE(key2); + return 0; +} + +/* ensure salt alters key */ +static int saltTest(testArgs *targs) +{ + /* + generate key1(seed), key2(munged seed); + encrypt ptext with key1; + encrypt ptext with key2; + compare 2 ctexts; expect failure; + */ + CSSM_KEY_PTR key1; + CSSM_KEY_PTR key2; + CSSM_DATA iv1; + CSSM_DATA iv2; + CSSM_DATA_PTR ivp1; + CSSM_DATA_PTR ivp2; + uint32 mungeDex; + uint32 mungeBits; + if(targs->useInitVector) { + if(targs->genInitVector) { + ivp1 = &iv1; + ivp2 = &iv2; + } + else { + staticIv.Length = targs->ivSize; + ivp1 = ivp2 = &staticIv; + } + } + else { + ivp1 = ivp2 = NULL; + } + /* these need to be init'd regardless */ + iv1.Data = NULL; + iv1.Length = 0; + iv2.Data = NULL; + iv2.Length = 0; + key1 = cspDeriveKey(targs->cspHand, + targs->deriveAlg, + targs->keyAlg, + KEY_LABEL1, + KEY_LABEL_LEN, + CSSM_KEYUSE_ENCRYPT, + targs->keySizeInBits, + targs->useRefKey, + targs->password, + targs->salt, + targs->iterCount, + &iv1); + if(key1 == NULL) { + return testError(targs->quiet); + } + /* munge salt */ + mungeDex = genRand(0, targs->salt->Length - 1); + mungeBits = randBit(); + targs->salt->Data[mungeDex] ^= mungeBits; + key2 = cspDeriveKey(targs->cspHand, + targs->deriveAlg, + targs->keyAlg, + KEY_LABEL2, + KEY_LABEL_LEN, + CSSM_KEYUSE_ENCRYPT, + targs->keySizeInBits, + targs->useRefKey, + targs->password, + targs->salt, // the changed param + targs->iterCount, + &iv2); + if(key2 == NULL) { + return testError(targs->quiet); + } + if(testCommon(targs->cspHand, + "saltTest", + targs->encrAlg, + targs->encrMode, + targs->encrPad, + targs->effectiveKeySizeInBits, + targs->ptext, + key1, + ivp1, + key2, + ivp2, + targs->quiet)) { + return 1; + } + /* restore */ + targs->salt->Data[mungeDex] ^= mungeBits; + appFreeCssmData(&iv1, CSSM_FALSE); + appFreeCssmData(&iv2, CSSM_FALSE); + cspFreeKey(targs->cspHand, key1); + cspFreeKey(targs->cspHand, key2); + CSSM_FREE(key1); + CSSM_FREE(key2); + return 0; +} + +/* ensure initVector alters ctext. This isn't testing PBE per se, but + * it's a handy place to verify this function. */ +static int initVectTest(testArgs *targs) +{ + /* + generate key1; + encrypt ptext with key1 and initVector; + encrypt ptext with key1 and munged initVector; + compare 2 ctexts; expect failure; + */ + CSSM_KEY_PTR key1; + CSSM_DATA iv1; + CSSM_DATA iv2; + uint32 mungeDex; + uint32 mungeBits; + + if(targs->genInitVector) { + iv1.Data = NULL; + iv1.Length = 0; + } + else { + iv1 = staticIv; + } + key1 = cspDeriveKey(targs->cspHand, + targs->deriveAlg, + targs->keyAlg, + KEY_LABEL1, + KEY_LABEL_LEN, + CSSM_KEYUSE_ENCRYPT, + targs->keySizeInBits, + targs->useRefKey, + targs->password, + targs->salt, + targs->iterCount, + &iv1); + if(key1 == NULL) { + return testError(targs->quiet); + } + + /* get munged copy of iv */ + iv2.Data = (uint8 *)CSSM_MALLOC(iv1.Length); + iv2.Length = iv1.Length; + memmove(iv2.Data, iv1.Data, iv1.Length); + mungeDex = genRand(0, iv1.Length - 1); + mungeBits = randBit(); + iv2.Data[mungeDex] ^= mungeBits; + if(testCommon(targs->cspHand, + "initVectTest", + targs->encrAlg, + targs->encrMode, + targs->encrPad, + targs->effectiveKeySizeInBits, + targs->ptext, + key1, + &iv1, + key1, + &iv2, // the changed param + targs->quiet)) { + return 1; + } + if(targs->genInitVector) { + appFreeCssmData(&iv1, CSSM_FALSE); + } + appFreeCssmData(&iv2, CSSM_FALSE); + cspFreeKey(targs->cspHand, key1); + CSSM_FREE(key1); + return 0; +} + +#if 0 +/* only one algorithm supported */ +/* ensure deriveAlg alters key */ +static int deriveAlgTest(testArgs *targs) +{ + /* + generate key1(deriveAlg), key2(some other deriveAlg); + encrypt ptext with key1; + encrypt ptext with key2; + compare 2 ctexts; expect failure; + */ + CSSM_KEY_PTR key1; + CSSM_KEY_PTR key2; + CSSM_DATA iv1; + CSSM_DATA iv2; + CSSM_DATA_PTR ivp1; + CSSM_DATA_PTR ivp2; + uint32 mungeAlg; + + if(targs->useInitVector) { + if(targs->genInitVector) { + ivp1 = &iv1; + ivp2 = &iv2; + } + else { + staticIv.Length = targs->ivSize; + ivp1 = ivp2 = &staticIv; + } + } + else { + ivp1 = ivp2 = NULL; + } + + /* these need to be init'd regardless */ + iv1.Data = NULL; + iv1.Length = 0; + iv2.Data = NULL; + iv2.Length = 0; + key1 = cspDeriveKey(targs->cspHand, + targs->deriveAlg, + targs->keyAlg, + KEY_LABEL1, + KEY_LABEL_LEN, + CSSM_KEYUSE_ENCRYPT, + targs->keySizeInBits, + targs->useRefKey, + targs->password, + targs->salt, + targs->iterCount, + &iv1); + if(key1 == NULL) { + return testError(quiet); + } + + /* munge deriveAlg */ + switch(targs->deriveAlg) { + case CSSM_ALGID_MD5_PBE: + mungeAlg = CSSM_ALGID_MD2_PBE; + break; + case CSSM_ALGID_MD2_PBE: + mungeAlg = CSSM_ALGID_SHA1_PBE; + break; + case CSSM_ALGID_SHA1_PBE: + mungeAlg = CSSM_ALGID_SHA1_PBE_PKCS12; + break; + case CSSM_ALGID_SHA1_PBE_PKCS12: + mungeAlg = CSSM_ALGID_MD5_PBE; + break; + default: + printf("BRRRZZZT! Update deriveAlgTest()!\n"); + return testError(quiet); + } + key2 = cspDeriveKey(targs->cspHand, + mungeAlg, // the changed param + targs->keyAlg, + KEY_LABEL2, + KEY_LABEL_LEN, + CSSM_KEYUSE_ENCRYPT, + targs->keySizeInBits, + targs->useRefKey, + targs->password, // the changed param + targs->salt, + targs->iterCount, + &iv2); + if(key2 == NULL) { + return testError(quiet); + } + if(testCommon(targs->cspHand, + "deriveAlgTest", + targs->encrAlg, + targs->encrMode, + targs->encrPad, + targs->effectiveKeySizeInBits, + targs->ptext, + key1, + ivp1, + key2, + ivp2, + targs->quiet)) { + return 1; + } + appFreeCssmData(&iv1, CSSM_FALSE); + appFreeCssmData(&iv2, CSSM_FALSE); + cspFreeKey(targs->cspHand, key1); + cspFreeKey(targs->cspHand, key2); + CSSM_FREE(key1); + CSSM_FREE(key2); + return 0; +} +#endif + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + CSSM_DATA ptext; + testArgs targs; + CSSM_DATA pwd; + CSSM_DATA salt; + privAlg pbeAlg; + privAlg encrAlg; + privAlg lastEncrAlg; + int rtn = 0; + CSSM_BOOL fooBool; + CSSM_BOOL refKeysOnly = CSSM_FALSE; + int i; + + /* + * User-spec'd params + */ + unsigned loops = LOOPS_DEF; + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL doPause = CSSM_FALSE; + CSSM_BOOL doExport = CSSM_FALSE; + CSSM_BOOL repeatOnly = CSSM_FALSE; + CSSM_BOOL bareCsp = CSSM_TRUE; + CSSM_BOOL zeroLenPassword = CSSM_FALSE; + + #if macintosh + argc = ccommand(&argv); + #endif + for(arg=1; arg +#include +#include +#include +#include +#include +#include "common.h" +#include +#include +#include +using namespace std; + +/* + * Default values + */ +#define ALG_DEFAULT CSSM_ALGID_AES +#define ALG_STR_DEFAULT "AES" +#define CHAIN_DEFAULT CSSM_TRUE +#define KEY_SIZE_DEFAULT 128 + +#define BEGIN_FUNCTION try { + +#define END_FUNCTION } \ + catch (const CssmError &e) \ + { \ + cssmPerror(__PRETTY_FUNCTION__, e.error); \ + } \ + catch (...) \ + { \ + fprintf(stderr, "%s: failed\n", __PRETTY_FUNCTION__); \ + } \ + +static void usage(char **argv) +{ + printf("usage: %s iterations bufsize [options]\n", argv[0]); + printf(" Options:\n"); + printf(" a=algorithm (s=ASC; d=DES; 3=3DES; 2=RC2; 4=RC4; 5=RC5;\n"); + printf(" a=AES; b=Blowfish; c=CAST; n=NULL; default=AES)\n"); + printf(" k=keySizeInBits\n"); + printf(" b=blockSizeInBits\n"); + printf(" e (ECB mode; default is CBC)\n"); + printf(" i (re-set IV in each loop)\n"); + printf(" v(erbose)\n"); + printf(" h(elp)\n"); + exit(1); +} + +static void +cdsaSetupContexts(int iterations, + auto_ptr &encrypt, + auto_ptr &decrypt, + CSSM_ALGORITHMS keyAlg, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE encrMode, + uint32 keySizeInBits, + uint32 blockSizeInBits) // optional +{ + BEGIN_FUNCTION + Security::CssmClient::CSP csp(gGuidAppleCSP); + //CssmData keyData((uint8 *)"1234567812345678", 16); + Security::CssmClient::GenerateKey keyGenerator(csp, keyAlg, keySizeInBits); + Security::CssmClient::Key key = keyGenerator(Security::CssmClient::KeySpec( + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE)); + for (int ix=0; ix < iterations; ++ix) + { + encrypt.reset(new Security::CssmClient::Encrypt(csp, encrAlg)); + encrypt->mode(encrMode); + encrypt->key(key); + if(blockSizeInBits) { + encrypt->add(CSSM_ATTRIBUTE_BLOCK_SIZE, blockSizeInBits / 8); + } + //encrypt->activate(); + + decrypt.reset(new Security::CssmClient::Decrypt(csp, encrAlg)); + decrypt->mode(encrMode); + decrypt->key(key); + if(blockSizeInBits) { + decrypt->add(CSSM_ATTRIBUTE_BLOCK_SIZE, blockSizeInBits / 8); + } + //decrypt->activate(); + } + END_FUNCTION +} + +static void +cdsaEncrypt(int iterations, Security::CssmClient::Encrypt &encrypt, + uint8 *inBuf, uint32 bufLen, uint8 *outBuf, bool useIv, uint32 blockSizeBytes, + CSSM_BOOL resetIv) +{ + BEGIN_FUNCTION + CssmData iv((uint8 *)"12345678123456781234567812345678", blockSizeBytes); + CssmData inData(inBuf, bufLen); + CssmData outData(outBuf, bufLen); + CssmData nullData(reinterpret_cast(NULL) + 1, 0); + if(useIv) { + encrypt.initVector(iv); + } + if(useIv && resetIv) { + for (int ix=0; ix < iterations; ++ix) + { + encrypt.initVector(iv); + encrypt.encrypt(inData, outData, nullData); + } + } + else { + for (int ix=0; ix < iterations; ++ix) + { + encrypt.encrypt(inData, outData, nullData); + } + } + END_FUNCTION +} + +static void +cdsaDecrypt(int iterations, Security::CssmClient::Decrypt &decrypt, + uint8 *inBuf, uint32 bufLen, uint8 *outBuf, bool useIv, uint32 blockSizeBytes, + CSSM_BOOL resetIv) +{ + BEGIN_FUNCTION + CssmData iv((uint8 *)"12345678123456781234567812345678", blockSizeBytes); + CssmData inData(inBuf, bufLen); + CssmData outData(outBuf, bufLen); + CssmData nullData(reinterpret_cast(NULL) + 1, 0); + if(useIv) { + decrypt.initVector(iv); + } + if(useIv && resetIv) { + for (int ix=0; ix < iterations; ++ix) + { + decrypt.initVector(iv); + decrypt.decrypt(inData, outData, nullData); + } + } + else { + for (int ix=0; ix < iterations; ++ix) + { + decrypt.decrypt(inData, outData, nullData); + } + } + END_FUNCTION +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + CSSM_ENCRYPT_MODE mode; + uint32 blockSizeBytes = 8; + + /* + * User-spec'd params + */ + CSSM_BOOL chainEnable = CHAIN_DEFAULT; + uint32 keySizeInBits = KEY_SIZE_DEFAULT; + uint32 blockSizeInBits = 0; + const char *algStr = ALG_STR_DEFAULT; + uint32 keyAlg = ALG_DEFAULT; // CSSM_ALGID_xxx of the key + uint32 encrAlg = ALG_DEFAULT; // CSSM_ALGID_xxx for encrypt + int iterations; + int bufSize; + CSSM_BOOL resetIv = CSSM_FALSE; + CSSM_BOOL verbose = false; + + if(argc < 3) { + usage(argv); + } + iterations = atoi(argv[1]); + bufSize = atoi(argv[2]); + for(arg=3; arg buffer(bufSize), plain(bufSize); + auto_ptr encrypt(NULL); + auto_ptr decrypt(NULL); + + uint8 *bp = buffer.get(); + for(int ix=0; ix +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include +#include +#include + +using namespace std; + +/* + * Default values + */ +#define ALG_DEFAULT CSSM_ALGID_AES +#define ALG_STR_DEFAULT "AES" +#define CHAIN_DEFAULT CSSM_TRUE +#define ALG_MODE_DEFAULT CSSM_ALGMODE_CBC_IV8 +#define ALG_MODE_STR_DEFAULT "CBC" +#define KEY_SIZE_DEFAULT 128 +#define BLOCK_SIZE_DEFAULT 16 + +static void usage(char **argv) +{ + printf("usage: %s iterations bufsize [options]\n", argv[0]); + printf(" Options:\n"); + printf(" a=algorithm (s=ASC; d=DES; 3=3DES; 2=RC2; 4=RC4; 5=RC5;\n"); + printf(" a=AES; b=Blowfish; c=CAST; n=NULL; default=AES)\n"); + printf(" k=keySizeInBits\n"); + printf(" e (ECB mode; default is CBC)\n"); + printf(" c (re-create context in each loop)\n"); + printf(" v(erbose)\n"); + printf(" h(elp)\n"); + exit(1); +} + +static int doEncrypt( + CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR symKey, + CSSM_BOOL resetContext, + unsigned iterations, + uint8 blockSizeBytes, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE encrMode, + const CSSM_DATA *ptext, // pre-allocd + CSSM_DATA *ctext) +{ + CSSM_CC_HANDLE ccHand = 0; + char *someIv = "some Initialization vector"; + CSSM_DATA iv = {blockSizeBytes, (uint8 *)someIv}; + CSSM_DATA remData = {0, NULL}; + CSSM_SIZE moved; + CSSM_RETURN crtn; + + for(unsigned dex=0; dex /dev/null +if($status != 0) then + echo Please set env var LOCAL_BUILD_DIR. + exit(1) +endif +set BUILD_DIR=$LOCAL_BUILD_DIR +# +if( ( ! -e $BUILD_DIR/perform ) || \ + ( ! -e $BUILD_DIR/certTime) || \ + ( ! -e $CLXUTILS/certTime)) then + echo === You do not seem to have all of the required executables. + echo === Please build all of cspxutils and clxutils. + echo === See the README files in those directories for info. + exit(1) +endif +# +cd $CSPXUTILS/perform +set cmd="./doPerform 1000 10240" +echo $cmd +$cmd || exit(1) +echo ============================================================== +cd $BUILD_DIR +set cmd="./hashTime" +echo $cmd +$cmd || exit(1) +echo ============================================================== +cd $BUILD_DIR +set cmd="./sigPerform a=r l=1000 k=1024" +echo $cmd +$cmd || exit(1) +echo ============================================================== +set cmd="./asymPerform k=1024" +echo $cmd +$cmd || exit(1) +echo ============================================================== +cd $CLXUTILS/certTime || exit(1) +set cmd="./runTime" +echo $cmd +$cmd || exit(1) +echo ============================================================== +cd $CLXUTILS/kcTime || exit(1) +set cmd="$BUILD_DIR/kcTime" +echo $cmd +$cmd || exit(1) +echo ============================================================== +cd $CLXUTILS/secTime || exit(1) +set cmd="$BUILD_DIR/secTime" +echo $cmd +$cmd || exit(1) +echo ============================================================== +echo Performance suite complete. diff --git a/SecurityTests/cspxutils/pubKeyTool/Makefile b/SecurityTests/cspxutils/pubKeyTool/Makefile new file mode 100644 index 00000000..b23914db --- /dev/null +++ b/SecurityTests/cspxutils/pubKeyTool/Makefile @@ -0,0 +1,57 @@ +# +# sample Makefile fragment for csputils projects. +# + +### fill in these: + +# name of executable to build +EXECUTABLE=pubKeyTool +# C++ source (with .cpp extension) +CPSOURCE= pubKeyTool.cpp +# C source (.c extension) +CSOURCE= + +### all of the rest is optional. + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/pubKeyTool/derive_pub.der b/SecurityTests/cspxutils/pubKeyTool/derive_pub.der new file mode 100644 index 0000000000000000000000000000000000000000..21144dfe27e56bc6de259280ce8b79f43eb71f35 GIT binary patch literal 140 zcmV;70CWE^fr$cvfdIu)|5OYt!rK*nXlt6jG3`ZCTu6tPt+{2gB}tIGqbgD*AyX^^ z^jqK@iAn7tvNC{`GH~NFy)aBHw;y=kIap9bj_Njkt?HznBvPumPHsMeyG6S6HOg;2 u;Qlg#wl+E(qEUZi^<=VVarfWi`DJlt!r%S;nCzBsm=@n2c#8r90RRE5wnAh8 literal 0 HcmV?d00001 diff --git a/SecurityTests/cspxutils/pubKeyTool/pubKeyTool.cpp b/SecurityTests/cspxutils/pubKeyTool/pubKeyTool.cpp new file mode 100644 index 00000000..ce53b0eb --- /dev/null +++ b/SecurityTests/cspxutils/pubKeyTool/pubKeyTool.cpp @@ -0,0 +1,672 @@ +/* + * pubKeyTool.cpp - calculate public key hash of arbitrary keys and certs; derive + * public key from a private key or a cert. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" -k priv_key_file -- private key file to read\n"); + printf(" -b pub_key_file -- public key file to read\n"); + printf(" -c cert_file -- cert file to read\n"); + printf(" -d -- print public key digest\n"); + printf(" -o out_file -- write public key to out_file\n"); + printf(" -f pkcs1|pkcs8|x509 -- input key format\n"); + printf(" -- default is PKCS8 for private key, PKCS1 for" + " public\n"); + printf(" -K keychain -- import pub key to this keychain; workaround " + "for Radar 4191851)\n"); + exit(1); +} + +/* Convert raw key blob into a respectable CSSM_KEY. */ +static CSSM_RETURN inferCssmKey( + const CSSM_DATA &keyBlob, + bool isPrivKey, + CSSM_KEYBLOB_FORMAT keyForm, + CSSM_CSP_HANDLE cspHand, + CSSM_KEY &outKey) +{ + memset(&outKey, 0, sizeof(CSSM_KEY)); + outKey.KeyData = keyBlob; + CSSM_KEYHEADER &hdr = outKey.KeyHeader; + hdr.HeaderVersion = CSSM_KEYHEADER_VERSION; + /* CspId blank */ + hdr.BlobType = CSSM_KEYBLOB_RAW; + hdr.AlgorithmId = CSSM_ALGID_RSA; + hdr.KeyAttr = CSSM_KEYATTR_EXTRACTABLE; + hdr.Format = keyForm; + hdr.KeyClass = isPrivKey ? CSSM_KEYCLASS_PRIVATE_KEY : CSSM_KEYCLASS_PUBLIC_KEY; + hdr.KeyUsage = CSSM_KEYUSE_ANY; + hdr.WrapAlgorithmId = CSSM_ALGID_NONE; + hdr.WrapMode = CSSM_ALGMODE_NONE; + /* + * LogicalKeySizeInBits - ask the CSP + */ + CSSM_KEY_SIZE keySize; + CSSM_RETURN crtn; + crtn = CSSM_QueryKeySizeInBits(cspHand, CSSM_INVALID_HANDLE, &outKey, + &keySize); + if(crtn) { + cssmPerror("CSSM_QueryKeySizeInBits", crtn); + return crtn; + } + hdr.LogicalKeySizeInBits = keySize.LogicalKeySizeInBits; + return CSSM_OK; +} + +/* + * Given any key in either blob or reference format, + * obtain the associated public key's SHA-1 hash. + */ +static CSSM_RETURN keyDigest( + CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *key, + CSSM_DATA_PTR *hashData) /* struct and contents cuAppMalloc'd and RETURNED */ +{ + CSSM_CC_HANDLE ccHand; + CSSM_RETURN crtn; + CSSM_DATA_PTR dp; + + *hashData = NULL; + + /* validate input params */ + if((key == NULL) || + (hashData == NULL)) { + printf("keyHash: bogus args\n"); + return CSSMERR_CSSM_INTERNAL_ERROR; + } + + /* cook up a context for a passthrough op */ + crtn = CSSM_CSP_CreatePassThroughContext(cspHand, + key, + &ccHand); + if(ccHand == 0) { + cssmPerror("CSSM_CSP_CreatePassThroughContext", crtn); + return crtn; + } + + /* now it's up to the CSP */ + crtn = CSSM_CSP_PassThrough(ccHand, + CSSM_APPLECSP_KEYDIGEST, + NULL, + (void **)&dp); + if(crtn) { + cssmPerror("CSSM_CSP_PassThrough(KEYDIGEST)", crtn); + } + else { + *hashData = dp; + crtn = CSSM_OK; + } + CSSM_DeleteContext(ccHand); + return crtn; +} + +/* + * Here's a tricky one. Given a private key, obtain the correspoding public key. + * This uses a private key blob format that's used internally in the CSP + * to generate key digests. + */ + +/* + * this magic const copied from BinaryKey.h + */ +#define CSSM_KEYBLOB_RAW_FORMAT_DIGEST \ + (CSSM_KEYBLOB_RAW_FORMAT_VENDOR_DEFINED + 0x12345) + +static CSSM_RETURN pubKeyFromPrivKey( + CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *privKey, // assumed to be raw format + CSSM_KEY *pubKey) +{ + /* first convert to reference key */ + CSSM_KEY refKey; + CSSM_RETURN crtn; + crtn = cspRawKeyToRef(cspHand, privKey, &refKey); + if(crtn) { + return crtn; + } + + /* now a NULL wrap with the magic format attribute */ + CSSM_CC_HANDLE ccHand; + CSSM_ACCESS_CREDENTIALS creds; + CSSM_DATA descData = {0, 0}; + + crtn = CSSM_CSP_CreateSymmetricContext(cspHand, + CSSM_ALGID_NONE, + CSSM_ALGMODE_NONE, + NULL, // passPhrase, + NULL, // key + NULL, // initVector, + CSSM_PADDING_NONE, + NULL, // Reserved + &ccHand); + if(crtn) { + cssmPerror("CSSM_CSP_CreateSymmetricContext", crtn); + return crtn; + } + crtn = AddContextAttribute(ccHand, + /* + * The output of the WrapKey is a private key as far as the CSP is + * concerned, at the level that this attribute is used anyway.... + */ + CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT, + sizeof(uint32), + CAT_Uint32, + NULL, + CSSM_KEYBLOB_RAW_FORMAT_DIGEST); + if(crtn) { + cssmPerror("CSSM_CSP_CreateSymmetricContext", crtn); + goto errOut; + } + memset(pubKey, 0, sizeof(CSSM_KEY)); + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + crtn = CSSM_WrapKey(ccHand, + &creds, + &refKey, + &descData, + pubKey); + if(crtn) { + cssmPerror("CSSM_WrapKey", crtn); + goto errOut; + } + + /* now: presto chango - don't do this at home! */ + pubKey->KeyHeader.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY; +errOut: + CSSM_FreeKey(cspHand, NULL, &refKey, CSSM_FALSE); + CSSM_DeleteContext(ccHand); + return crtn; +} + +/* + * Import a key into a DLDB. + */ +static CSSM_RETURN importToDlDb( + CSSM_CSP_HANDLE cspHand, + CSSM_DL_DB_HANDLE_PTR dlDbHand, + const CSSM_KEY *rawPubKey, + CSSM_DATA_PTR labelData, + CSSM_KEY_PTR importedKey) +{ + CSSM_CC_HANDLE ccHand = 0; + CSSM_RETURN crtn; + uint32 keyAttr; + CSSM_ACCESS_CREDENTIALS creds; + CSSM_CONTEXT_ATTRIBUTE newAttr; + CSSM_DATA descData = {0, 0}; + + memset(importedKey, 0, sizeof(CSSM_KEY)); + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + crtn = CSSM_CSP_CreateSymmetricContext(cspHand, + CSSM_ALGID_NONE, + CSSM_ALGMODE_NONE, + &creds, + NULL, // unwrappingKey + NULL, // initVector + CSSM_PADDING_NONE, + 0, // Params + &ccHand); + if(crtn) { + cssmPerror("CSSM_CSP_CreateSymmetricContext", crtn); + return crtn; + } + keyAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT; + + /* Add DLDB to context */ + newAttr.AttributeType = CSSM_ATTRIBUTE_DL_DB_HANDLE; + newAttr.AttributeLength = sizeof(CSSM_ATTRIBUTE_DL_DB_HANDLE); + newAttr.Attribute.Data = (CSSM_DATA_PTR)dlDbHand; + crtn = CSSM_UpdateContextAttributes(ccHand, 1, &newAttr); + if(crtn) { + cssmPerror("CSSM_UpdateContextAttributes", crtn); + goto errOut; + } + + /* import */ + crtn = CSSM_UnwrapKey(ccHand, + NULL, // PublicKey + rawPubKey, + CSSM_KEYUSE_ANY, + keyAttr, + labelData, + NULL, // CredAndAclEntry + importedKey, + &descData); // required + if(crtn) { + cssmPerror("CSSM_UnwrapKey", crtn); + } +errOut: + if(ccHand) { + CSSM_DeleteContext(ccHand); + } + return crtn; +} + +/* + * Free memory via specified plugin's app-level allocator + */ +void impExpFreeCssmMemory( + CSSM_HANDLE hand, + void *p) +{ + CSSM_API_MEMORY_FUNCS memFuncs; + CSSM_RETURN crtn = CSSM_GetAPIMemoryFunctions(hand, &memFuncs); + if(crtn) { + return; + } + memFuncs.free_func(p, memFuncs.AllocRef); +} + +/* + * Key attrribute names and values. + * + * This is where the public key hash goes. + */ +#define SEC_KEY_HASH_ATTR_NAME "Label" + +/* + * This is where the publicly visible name goes. + */ +#define SEC_KEY_PRINT_NAME_ATTR_NAME "PrintName" + +/* + * Look up public key by label + * Set label to new specified label (SHA1 digest) + * Set print name to new specified user-visible name + */ +static CSSM_RETURN setPubKeyLabel( + CSSM_CSP_HANDLE cspHand, // where the key lives + CSSM_DL_DB_HANDLE *dlDbHand, // ditto + const CSSM_DATA *existKeyLabel, // existing label, a random string, for lookup + const CSSM_DATA *keyDigest, // SHA1 digest, the new label + const CSSM_DATA *newPrintName) // new user-visible name +{ + CSSM_QUERY query; + CSSM_SELECTION_PREDICATE predicate; + CSSM_DB_UNIQUE_RECORD_PTR record = NULL; + CSSM_RETURN crtn; + CSSM_HANDLE resultHand = 0; + + /* + * Look up the key in the DL. + */ + query.RecordType = CSSM_DL_DB_RECORD_PUBLIC_KEY; + query.Conjunctive = CSSM_DB_NONE; + query.NumSelectionPredicates = 1; + predicate.DbOperator = CSSM_DB_EQUAL; + + predicate.Attribute.Info.AttributeNameFormat = + CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + predicate.Attribute.Info.Label.AttributeName = (char *)"Label"; + predicate.Attribute.Info.AttributeFormat = + CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + /* hope this cast is OK */ + predicate.Attribute.Value = (CSSM_DATA_PTR)existKeyLabel; + query.SelectionPredicate = &predicate; + + query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? + query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? + query.QueryFlags = 0; // CSSM_QUERY_RETURN_DATA; // FIXME - used? + + /* build Record attribute with two attrs */ + CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; + CSSM_DB_ATTRIBUTE_DATA attr[2]; + + attr[0].Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr[0].Info.Label.AttributeName = (char *)SEC_KEY_HASH_ATTR_NAME; + attr[0].Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + attr[1].Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr[1].Info.Label.AttributeName = (char *)SEC_KEY_PRINT_NAME_ATTR_NAME; + attr[1].Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + + recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_PUBLIC_KEY; + recordAttrs.NumberOfAttributes = 2; + recordAttrs.AttributeData = attr; + + crtn = CSSM_DL_DataGetFirst(*dlDbHand, + &query, + &resultHand, + &recordAttrs, + NULL, // theData + &record); + /* abort only on success */ + if(crtn != CSSM_OK) { + cssmPerror("CSSM_DL_DataGetFirst", crtn); + goto errOut; + } + + /* + * Update existing attr data. + * NOTE: the module which allocated this attribute data - a DL - + * was loaded and attached by the keychain layer, not by us. Thus + * we can't use the memory allocator functions *we* used when + * attaching to the CSP - we have to use the ones + * which the client registered with the DL. + */ + impExpFreeCssmMemory(dlDbHand->DLHandle, attr[0].Value->Data); + impExpFreeCssmMemory(dlDbHand->DLHandle, attr[0].Value); + impExpFreeCssmMemory(dlDbHand->DLHandle, attr[1].Value->Data); + impExpFreeCssmMemory(dlDbHand->DLHandle, attr[1].Value); + attr[0].Value = const_cast(keyDigest); + attr[1].Value = const_cast(newPrintName); + + crtn = CSSM_DL_DataModify(*dlDbHand, + CSSM_DL_DB_RECORD_PUBLIC_KEY, + record, + &recordAttrs, + NULL, // DataToBeModified + CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + if(crtn) { + cssmPerror("CSSM_DL_DataModify", crtn); + } +errOut: + /* free resources */ + if(resultHand) { + CSSM_DL_DataAbortQuery(*dlDbHand, resultHand); + } + if(record) { + CSSM_DL_FreeUniqueRecord(*dlDbHand, record); + } + return crtn; +} + +#define SHA1_LABEL_LEN 20 +#define IMPORTED_KEY_NAME "Imported Public Key" + +/* + * Import a public key into a keychain, with proper Label attribute setting. + * A workaround for Radar 4191851. + */ +static int pubKeyImport( + const char *kcName, + const CSSM_KEY *pubKey, + CSSM_CSP_HANDLE rawCspHand) /* raw CSP handle for calculating digest */ +{ + CSSM_CSP_HANDLE cspHand; + CSSM_DL_DB_HANDLE dlDbHand; + OSStatus ortn; + CSSM_RETURN crtn; + SecKeychainRef kcRef = NULL; + int ourRtn = 0; + CSSM_DATA_PTR digest = NULL; + CSSM_KEY importedKey; + CSSM_DATA newPrintName = + { (uint32)strlen(IMPORTED_KEY_NAME), (uint8 *)IMPORTED_KEY_NAME}; + + /* NULL unwrap stuff */ + uint8 tempLabel[SHA1_LABEL_LEN]; + CSSM_DATA labelData = {SHA1_LABEL_LEN, tempLabel}; + + ortn = SecKeychainOpen(kcName, &kcRef); + if(ortn) { + cssmPerror("SecKeychainOpen", ortn); + return -1; + } + /* subsequent errors to errOut: */ + + /* Get CSSM handles */ + ortn = SecKeychainGetCSPHandle(kcRef, &cspHand); + if(ortn) { + cssmPerror("SecKeychainGetCSPHandle", ortn); + ourRtn = -1; + goto errOut; + } + ortn = SecKeychainGetDLDBHandle(kcRef, &dlDbHand); + if(ortn) { + cssmPerror("SecKeychainGetCSPHandle", ortn); + ourRtn = -1; + goto errOut; + } + + /* public key hash from raw CSP */ + crtn = keyDigest(rawCspHand, pubKey, &digest); + if(crtn) { + ourRtn = -1; + goto errOut; + } + + /* random label for initial storage and later retrieval */ + appGetRandomBytes(tempLabel, SHA1_LABEL_LEN); + + /* import the key into the keychain's DLDB */ + memset(&importedKey, 0, sizeof(CSSM_KEY)); + crtn = importToDlDb(cspHand, &dlDbHand, pubKey, &labelData, &importedKey); + if(crtn) { + ourRtn = -1; + goto errOut; + } + + /* don't need this */ + CSSM_FreeKey(cspHand, NULL, &importedKey, CSSM_FALSE); + + /* update the label and printName attributes */ + crtn = setPubKeyLabel(cspHand, &dlDbHand, &labelData, digest, &newPrintName); + if(crtn) { + ourRtn = -1; + } +errOut: + CFRelease(kcRef); + if(digest) { + APP_FREE(digest->Data); + APP_FREE(digest); + } + return ourRtn; +} + +int main(int argc, char **argv) +{ + char *privKeyFile = NULL; + char *pubKeyFile = NULL; + char *certFile = NULL; + char *outFile = NULL; + bool printDigest = false; + CSSM_KEYBLOB_FORMAT keyForm = CSSM_KEYBLOB_RAW_FORMAT_NONE; + char *kcName = NULL; + + if(argc < 3) { + usage(argv); + } + extern char *optarg; + int arg; + while ((arg = getopt(argc, argv, "k:b:c:do:f:K:h")) != -1) { + switch (arg) { + case 'k': + privKeyFile = optarg; + break; + case 'b': + pubKeyFile = optarg; + break; + case 'c': + certFile = optarg; + break; + case 'd': + printDigest = true; + break; + case 'o': + outFile = optarg; + break; + case 'f': + if(!strcmp("pkcs1", optarg)) { + keyForm = CSSM_KEYBLOB_RAW_FORMAT_PKCS1; + } + else if(!strcmp("pkcs8", optarg)) { + keyForm = CSSM_KEYBLOB_RAW_FORMAT_PKCS8; + } + else if(!strcmp("x509", optarg)) { + keyForm = CSSM_KEYBLOB_RAW_FORMAT_X509; + } + break; + case 'K': + kcName = optarg; + break; + case 'h': + usage(argv); + } + } + if(optind != argc) { + usage(argv); + } + + CSSM_DATA privKeyBlob = {0, NULL}; + CSSM_DATA pubKeyBlob = {0, NULL}; + CSSM_KEY thePrivKey; // constructed + CSSM_KEY thePubKey; // null-wrapped + CSSM_KEY_PTR pubKey = NULL; + CSSM_KEY_PTR privKey = NULL; + CSSM_RETURN crtn; + CSSM_CL_HANDLE clHand = 0; + CSSM_CSP_HANDLE cspHand = cuCspStartup(CSSM_TRUE); + + /* gather input */ + if(privKeyFile) { + /* key blob from a file ==> a private CSSM_KEY */ + + if(pubKeyFile || certFile) { + printf("****Specify exactly one of {cert_file, priv_key_file, " + "pub_key_file}.\n"); + exit(1); + } + unsigned len; + if(readFile(privKeyFile, &privKeyBlob.Data, &len)) { + printf("***Error reading private key from %s. Aborting.\n", privKeyFile); + exit(1); + } + privKeyBlob.Length = len; + if(keyForm == CSSM_KEYBLOB_RAW_FORMAT_NONE) { + /* default for private keys */ + keyForm = CSSM_KEYBLOB_RAW_FORMAT_PKCS8; + } + crtn = inferCssmKey(privKeyBlob, true, keyForm, cspHand, thePrivKey); + if(crtn) { + goto errOut; + } + privKey = &thePrivKey; + } + if(pubKeyFile) { + /* key blob from a file ==> a public CSSM_KEY */ + + if(privKeyFile || certFile) { + printf("****Specify exactly one of {cert_file, priv_key_file, " + "pub_key_file}.\n"); + exit(1); + } + + unsigned len; + if(readFile(pubKeyFile, &pubKeyBlob.Data, &len)) { + printf("***Error reading public key from %s. Aborting.\n", pubKeyFile); + exit(1); + } + pubKeyBlob.Length = len; + if(keyForm == CSSM_KEYBLOB_RAW_FORMAT_NONE) { + /* default for public keys */ + keyForm = CSSM_KEYBLOB_RAW_FORMAT_PKCS1; + } + crtn = inferCssmKey(pubKeyBlob, false, keyForm, cspHand, thePubKey); + if(crtn) { + goto errOut; + } + pubKey = &thePubKey; + } + if(certFile) { + /* cert from a file ==> a public CSSM_KEY */ + + if(privKeyFile || pubKeyFile) { + printf("****Specify exactly one of {cert_file, priv_key_file, " + "pub_key_file}.\n"); + exit(1); + } + + CSSM_DATA certData = {0, NULL}; + unsigned len; + if(readFile(certFile, &certData.Data, &len)) { + printf("***Error reading cert from %s. Aborting.\n", certFile); + exit(1); + } + certData.Length = len; + + /* Extract public key - that's what we will be using later */ + clHand = cuClStartup(); + crtn = CSSM_CL_CertGetKeyInfo(clHand, &certData, &pubKey); + if(crtn) { + cssmPerror("CSSM_CL_CertGetKeyInfo", crtn); + goto errOut; + } + } + + /* now do something useful */ + if(printDigest) { + CSSM_KEY_PTR theKey = privKey; + if(theKey == NULL) { + /* maybe we got public key from a cert */ + theKey = pubKey; + } + if(theKey == NULL) { + printf("***Can't calculate digest because I don't have a key or a clue.\n"); + goto errOut; + } + CSSM_DATA_PTR dig = NULL; + crtn = keyDigest(cspHand, theKey, &dig); + if(crtn) { + printf("Sorry, can't get the digest for this key.\n"); + goto errOut; + } + if((dig == NULL) || (dig->Length == 0)) { + printf("Screwup calculating digest.\n"); + goto errOut; + } + printf("Key Digest:\n"); + for(unsigned dex=0; dexLength; dex++) { + printf("%02X ", dig->Data[dex]); + } + printf("\n"); + APP_FREE(dig->Data); + APP_FREE(dig); + } + + if(outFile || kcName) { + /* get a public key if we don't already have one */ + if(pubKey == NULL) { + if(privKey == NULL) { + printf("***PubKey file name specified but no privKey or cert. " + "Aborting.\n"); + goto errOut; + } + crtn = pubKeyFromPrivKey(cspHand, privKey, &thePubKey); + if(crtn) { + goto errOut; + } + pubKey = &thePubKey; + } + } + if(outFile) { + if(writeFile(outFile, pubKey->KeyData.Data, pubKey->KeyData.Length)) { + printf("***Error writing to %s.\n", outFile); + } + else { + printf("...%lu bytes written to %s.\n", pubKey->KeyData.Length, outFile); + } + } + if(kcName) { + if(pubKeyImport(kcName, pubKey, cspHand) == 0) { + printf("....public key %s imported to %s\n", pubKeyFile, kcName); + } + else { + printf("***Error importing public key %s to %s\n", pubKeyFile, kcName); + } + } +errOut: + /* clean up here if you must */ + return 0; +} diff --git a/SecurityTests/cspxutils/pubKeyTool/rsa_priv.der b/SecurityTests/cspxutils/pubKeyTool/rsa_priv.der new file mode 100644 index 0000000000000000000000000000000000000000..ce17ceb7da687c58713a2a21318bbe92599f7a20 GIT binary patch literal 635 zcmV->0)+iAf&zB}0RS)!1_>&LNQUpVK9OMT>=3B0)c@5#Zv!N3@pOi z6@6%Hn!YjZMN(WyhnKCnWwIqnkh`NQQY9f%ECcjg;2eob?IE%XK7zYNy7V>5Z$04tGJ>`?Ivk==e`EDzvS)Gk-{SdY zac08b{rs5hmT#CA-yV320s{d60Rn-5QN_k*_b;i0j}T07qfG>LwvV0+w46ut7tqe3 z0O+xTeNIEvD&B0Wl44;7kj=3II>i}W?iYjF8$H0zm-g zw}*K39%J;~|3<@8k!1D>pF~ft)(R#!)*K1Nvmt10gP0xR5=U217tq7LBi-30MXaxu zr~@AIaJ{S}z7od*K>*tFt)8CxLT%MQlxF|X{c$NUZDN8#%hH)yl!V{6z3DZ&PFIz)Uv$=n@B2mbw)hsJA@*%fg-pV%TWvJ;sK_h#ou)ou^f zbUi~Ev8CM|UTxV9a&%70@+MsDH2MUUeVEDr^t845lH6o?;Y8;z*bs#nD{3;C7#nx73R-HMfo24k| z=J<&MK>(s^vn~}+3H5LjwvJ;LXIN17wS@`Q +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" + +#define RAND_ALG CSSM_ALGID_APPLE_YARROW +#define BUFSIZE 32 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + exit(1); +} + +static void dumpBuf(uint8 *buf, + unsigned len) +{ + unsigned i; + + printf(" "); + for(i=0; i gen a new one + // else use this + CSSM_CRYPTO_DATA_PTR seed, // optional + unsigned len, + CSSM_BOOL weMalloc) +{ + CSSM_RETURN crtn; + CSSM_DATA data = {0, NULL}; + + /* optional existing context */ + if(ccHand == 0) { + crtn = CSSM_CSP_CreateRandomGenContext( + cspHand, + RAND_ALG, + seed, + len, + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateRandomGenContext", crtn); + return; + } + } + + /* who mallocs the data? */ + if(weMalloc) { + data.Data = (uint8 *)appMalloc(len, NULL); + if(data.Data == NULL) { + printf("***malloc failure\n"); + return; + } + data.Length = len; + } + + /* go for it */ + crtn = CSSM_GenerateRandom(ccHand, &data); + if(crtn) { + printError("CSSM_GenerateRandom", crtn); + return; + } + + dumpBuf(data.Data, data.Length); + appFree(data.Data, NULL); + return; +} + +#define SEED_SIZE 32 + +/* + * CryptoData callback for optional random seed. + */ +CSSM_RETURN seedCallback( + CSSM_DATA_PTR OutData, + void *CallerCtx) +{ + int i, j; + static unsigned char seed[SEED_SIZE]; + + OutData->Length = SEED_SIZE; + OutData->Data = seed; + for(i=SEED_SIZE, j=0; i>0; i--, j++) { + seed[j] = i; + } + return CSSM_OK; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + CSSM_CSP_HANDLE cspHand; + CSSM_CC_HANDLE ccHand = 0; + CSSM_RETURN crtn; + CSSM_BOOL bareCsp = CSSM_TRUE; + char resp = 'n'; + // initial op = get random data + CSSM_BOOL weMalloc = CSSM_FALSE; + unsigned char seed[SEED_SIZE]; + CSSM_CRYPTO_DATA cseed; + int i; + unsigned reqLen = 16; + CSSM_BOOL explicitSeed; + + for(arg=1; arg +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "bsafeUtils.h" +#include + +/* + * Defaults. + */ +#define OLOOPS_DEF 10 /* outer loops, one key pair per loop */ +#define ILOOPS_DEF 10 /* sig loops */ +#define MAX_TEXT_SIZE 1024 + +#define LOOP_NOTIFY 20 +#define DO_MULTI_UPDATE CSSM_TRUE + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" a=alg (r=RSA, d=DSA; default=RSA)\n"); + printf(" l=outerloops (default=%d; 0=forever)\n", OLOOPS_DEF); + printf(" i=innerLoops (default=%d)\n", ILOOPS_DEF); + printf(" k=keySizeInBits; default is random\n"); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned oloop; + unsigned iloop; + CSSM_DATA ptext = {0, NULL}; + CSSM_CSP_HANDLE cspHand; + int i; + int rtn = 0; + uint32 keySizeInBits = 0; + CSSM_KEY pubKey; + CSSM_KEY privKey; + CSSM_DATA sig = {0, NULL}; + CSSM_DATA digest = {0, NULL}; + CSSM_RETURN crtn; + const char *digestStr; + + /* + * User-spec'd params + */ + CSSM_BOOL keySizeSpec = CSSM_FALSE; + unsigned oloops = OLOOPS_DEF; + unsigned iloops = ILOOPS_DEF; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + unsigned pauseInterval = 0; + CSSM_BOOL bareCsp = CSSM_TRUE; + CSSM_ALGORITHMS rawSigAlg = CSSM_ALGID_RSA; + + for(arg=1; arg +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "bsafeUtils.h" +#include "cspdlTesting.h" +#include + +/* + * Defaults. + */ +#define OLOOPS_DEF 10 /* outer loops, one key pair per loop */ +#define ILOOPS_DEF 10 /* sig loops */ +#define MAX_TEXT_SIZE 1024 + +#define LOOP_NOTIFY 20 + +/* + * Enumerate algs our own way to allow iteration. + */ +#define ALG_RSA_MD5 1 +#define ALG_RSA_SHA1 2 +#define ALG_RSA_MD2 3 +#define ALG_FEE_MD5 4 +#define ALG_FEE_SHA1 5 +#define ALG_ECDSA_SHA1 6 +#define ALG_DSA_SHA1 7 +#define ALG_ANSI_ECDSA_SHA1 8 +#define ALG_ECDSA_SHA256 9 +#define ALG_ECDSA_SHA384 10 +#define ALG_ECDSA_SHA512 11 +#define ALG_FIRST ALG_RSA_MD5 +#define ALG_LAST ALG_ECDSA_SHA512 + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" a=alg (5=RSA/MD5; 2=RSA/MD2; R=RSA/SHA1; d=DSA/SHA1; f=FEE/MD5; F=FEE/SHA1; \n"); + printf(" e=ECDSA/SHA1; E=ANSI_ECDSA/SHA1; 7=ECDSA/SHA256; 8=ECDSA/SHA384; 9=ECDSA/512; default=all)\n"); + printf(" l=outerloops (default=%d; 0=forever)\n", OLOOPS_DEF); + printf(" i=innerLoops (default=%d)\n", ILOOPS_DEF); + printf(" k=keySizeInBits; default is random\n"); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" s(mall keys)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned oloop; + unsigned iloop; + CSSM_DATA ptext = {0, NULL}; + CSSM_CSP_HANDLE cspHand; + int i; + int rtn = 0; + uint32 keySizeInBits = 0; + CSSM_KEY pubKey; + CSSM_KEY privKey; + CSSM_DATA sig = {0, NULL}; + CSSM_DATA digest = {0, NULL}; + CSSM_RETURN crtn; + unsigned currAlg; + + /* current alg (e.g. ALG_FEE_SHA1) parsed to come up with these */ + CSSM_ALGORITHMS digestAlg; + CSSM_ALGORITHMS rawSigAlg; + CSSM_ALGORITHMS sigAlg; + CSSM_ALGORITHMS keyGenAlg; + const char *sigAlgStr; + + /* + * User-spec'd params + */ + CSSM_BOOL keySizeSpec = CSSM_FALSE; + unsigned oloops = OLOOPS_DEF; + unsigned iloops = ILOOPS_DEF; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + unsigned pauseInterval = 0; + CSSM_BOOL bareCsp = CSSM_TRUE; + unsigned minAlg = ALG_FIRST; + uint32 maxAlg = ALG_LAST; + CSSM_BOOL smallKeys = CSSM_FALSE; + + for(arg=1; arg rsatool +usage: ./rsatool op [options] + op: + g generate key pair + e encrypt + d decrypt + s sign + v verify + S SHA-1 digest + M MD5 digest + options: + k=keyfileBase keys are keyFileBase_pub.der, keyFileBase_priv.der) + p=plainFile + c=cipherFile + s=sigfile + b=keySizeInBits (default 512) + w (swap key class) + r (raw sign/verify) + P (no padding) + a=alg d=DSA r=RSA, e=ECDSA, default = RSA +localhost> + + +Some examples: +-------------- + +To perform any operations using RSA, one must first have a key pair. +You generate them like so: + +localhost> rsatool g k=mykey b=1024 +...wrote 140 bytes to mykey_pub.der +...wrote 636 bytes to mykey_priv.der +localhostl> + +This generates a 1024-bit key pair, places the public key +in mykey_pub.der, and the private key in mykey_priv.der. + +Now, say you want to encrypt a file. You encrypt with a public key. +So first we create a file to encrypt: + +localhost:> cat > plaintext +this is what we will encrypt +localhostl> + +Now we encrypt it, placing the result in ciphertext: + +localhost> rsatool e k=mykey p=plaintext c=ciphertext +...wrote 128 bytes to ciphertext +localhost> + +The result looks like this: + +localhost> hexdump ciphertext +0000000 8272 4ff9 d7ab 8ff0 3dee 543d 3f36 3d89 +0000010 ef80 f958 3b4f 1be1 bde8 6557 c215 9728 +0000020 4262 0c6a b81b 5782 444d 225c db3e 17d7 +0000030 7079 d3af 7e1e c215 2b14 bf35 20f7 ed33 +0000040 f311 6258 fd85 6679 e0bb ae33 4b26 c1f8 +0000050 4f33 ac24 1972 e048 915c 8386 5fc3 7f56 +0000060 e7b3 9b4a ad6b a192 84c3 fa6e 25ba 91a0 +0000070 05ef fe42 ebba 0290 99b1 5cc9 5e36 7954 +0000080 +localhost> + +We decrypt it like so: + +localhost> rsatool d k=mykey p=recovered c=ciphertext +...wrote 29 bytes to recovered +localhost> + +Yielding: + +localhost> cat recovered +this is what we will encrypt +localhost> + +To generate a digital signature, putting the signature in sigfile: + +localhost> rsatool s k=mykey p=plaintext s=sigfile +...wrote 128 bytes to sigfile +localhost> + +To verify the signature: + +localhost> rsatool v k=mykey p=plaintext s=sigfile +...signature verifies OK +localhost> + +Note what happens if we specify a file other than 'plaintext' to +verify with plaintext's signature: + +localhost> rsatool v k=mykey p=ciphertext s=sigfile +CSSM_VerifyData: CSP_VERIFY_FAILED +sigVerify: CSP_VERIFY_FAILED +localhost> diff --git a/SecurityTests/cspxutils/rsatool/rsatool.c b/SecurityTests/cspxutils/rsatool/rsatool.c new file mode 100644 index 00000000..234662d5 --- /dev/null +++ b/SecurityTests/cspxutils/rsatool/rsatool.c @@ -0,0 +1,1182 @@ +/* + * rsatool.c - RSA/DSA/ECDSA key pair generator, en/decrypt, sign/verify with file I/O + */ + +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include + +/* For 3141770 - defined true when PR-3074739 merged to TOT Security */ +#define OPENSSL_ENABLE 1 + +#define USAGE_NAME "noUsage" +#define USAGE_NAME_LEN (strlen(USAGE_NAME)) +#define DEFAULT_KEY_SIZE_BITS 512 + +typedef struct { + CSSM_ALGORITHMS alg; + uint32 keySizeInBits; + CSSM_CSP_HANDLE cspHand; + char *keyFileName; + char *outKeyFileName; // for pub key convert + char *plainFileName; + char *sigFileName; + char *cipherFileName; + char *dsaParamFileIn; + char *dsaParamFileOut; + CSSM_BOOL swapKeyClass; + CSSM_BOOL rawSign; + CSSM_BOOL noPad; + CSSM_BOOL quiet; + CSSM_KEYBLOB_FORMAT pubKeyFormat; // FORMAT_NONE ==> default + CSSM_KEYBLOB_FORMAT privKeyFormat; // FORMAT_NONE ==> default + CSSM_KEYBLOB_FORMAT outPubKeyFormat;// FORMAT_NONE ==> default, for pub key convert + CSSM_ALGORITHMS digestAlg; // optional digest alg for raw sign/verify +} opParams; + +static void usage(char **argv) +{ + printf("usage: %s op [options]\n", argv[0]); + printf(" op:\n"); + printf(" g generate key pair\n"); + printf(" e encrypt\n"); + printf(" d decrypt\n"); + printf(" s sign\n"); + printf(" v verify\n"); + printf(" S SHA-1 digest\n"); + printf(" M MD5 digest\n"); + printf(" C convert public key format\n"); + printf(" options:\n"); + printf(" k=keyfileBase keys are keyFileBase_pub.der, " + "keyFileBase_priv.der)\n"); + printf(" K=outputPublicKey\n"); + printf(" p=plainFile\n"); + printf(" c=cipherFile\n"); + printf(" s=sigfile\n"); + printf(" z=keySizeInBits (default %d)\n", DEFAULT_KEY_SIZE_BITS); + printf(" w (swap key class)\n"); + printf(" r (raw sign/verify)\n"); + printf(" P (no padding)\n"); + printf(" d=digestAlg digestAlg: s(SHA1) 5(MD5) for raw signing\n"); + printf(" m=dsaParamFileIn\n"); + printf(" M=dsaParamFileOut (must specify one of dsaParamFile{In,Out}\n"); + printf(" b=[1xboOL] (pub key in PKCS1/X509/BSAFE/OpenSSH1/OpenSSH2/OpenSSL form)\n"); + printf(" RSA = {PKCS1,X509,OpenSSH1,OpenSSH2} default = PKCS1\n"); + printf(" DSA = {BSAFE,X509,OpenSSH2} default = X509\n"); + printf(" ECDSA = {X509, OpenSSL} default = X509\n"); + printf(" Note: RSA and DSA public keys in OpenSSL form are X509.\n"); + printf(" v=[18sbo] (priv key in PKCS1/PKCS8/OpenSSH/BSAFE/OpenSSL form)\n"); + printf(" RSA = {PKCS1,PKCS8,OpenSSH1} default = PKCS8\n"); + printf(" DSA = {BSAFE,OpenSSL,PKCS8} default = OpenSSL\n"); + printf(" ECDSA = {PKCS8,OpenSSL} default = OpenSSL}\n"); + printf(" Note: RSA private key in OpenSSL form is PKCS1.\n"); + printf(" B=[1xboO] output public key format\n"); + printf(" a=alg d=DSA, r=RSA, e=ECDSA; default = RSA\n"); + printf(" q(uiet)\n"); + exit(1); +} + +/* NULL wrap a key to specified format. */ +static CSSM_RETURN nullWrapKey(CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *refKey, + CSSM_KEYBLOB_FORMAT blobFormat, + CSSM_KEY_PTR rawKey) // RETURNED +{ + CSSM_CC_HANDLE ccHand; + CSSM_RETURN crtn; + CSSM_ACCESS_CREDENTIALS creds; + CSSM_DATA descData = {0, 0}; + + memset(rawKey, 0, sizeof(CSSM_KEY)); + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + crtn = CSSM_CSP_CreateSymmetricContext(cspHand, + CSSM_ALGID_NONE, + CSSM_ALGMODE_NONE, + &creds, // passPhrase + NULL, // unwrappingKey + NULL, // initVector + CSSM_PADDING_NONE, + 0, // Params + &ccHand); + if(crtn) { + printError("cspWrapKey/CreateContext", crtn); + return crtn; + } + if(blobFormat != CSSM_KEYBLOB_WRAPPED_FORMAT_NONE) { + /* only add this attribute if it's not the default */ + CSSM_ATTRIBUTE_TYPE attrType; + + switch(refKey->KeyHeader.KeyClass) { + case CSSM_KEYCLASS_SESSION_KEY: + attrType = CSSM_ATTRIBUTE_SYMMETRIC_KEY_FORMAT; + break; + case CSSM_KEYCLASS_PUBLIC_KEY: + attrType = CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT; + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + attrType = CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT; + break; + default: + printf("***Bogus KeyClass in nullWrapKey\n"); + return -1; + } + CSSM_CONTEXT_ATTRIBUTE attr; + attr.AttributeType = attrType; + attr.AttributeLength = sizeof(uint32); + attr.Attribute.Uint32 = blobFormat; + crtn = CSSM_UpdateContextAttributes( + ccHand, + 1, + &attr); + if(crtn) { + printError("CSSM_UpdateContextAttributes", crtn); + return crtn; + } + } + crtn = CSSM_WrapKey(ccHand, + &creds, + refKey, + &descData, + rawKey); + if(crtn != CSSM_OK) { + printError("CSSM_WrapKey", crtn); + } + if(CSSM_DeleteContext(ccHand)) { + printf("CSSM_DeleteContext failure\n"); + } + return crtn; +} + +/* + * Sign/verify optional "no padding" context attr + */ +static CSSM_RETURN sigSign(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. + CSSM_KEY_PTR key, // private key + const CSSM_DATA *text, + CSSM_DATA_PTR sig, + uint32 digestAlg, // optional for raw signing + CSSM_BOOL noPad) // true --> add PADDING_NONE to context +{ + CSSM_CC_HANDLE sigHand; + CSSM_RETURN crtn; + + crtn = CSSM_CSP_CreateSignatureContext(cspHand, + algorithm, + NULL, // passPhrase + key, + &sigHand); + if(crtn) { + printError("CSSM_CSP_CreateSignatureContext", crtn); + return crtn; + } + if(noPad) { + crtn = AddContextAttribute(sigHand, + CSSM_ATTRIBUTE_PADDING, + sizeof(uint32), + CAT_Uint32, + NULL, + CSSM_PADDING_NONE); + if(crtn) { + return crtn; + } + } + crtn = CSSM_SignData(sigHand, + text, + 1, + digestAlg, + sig); + if(crtn) { + printError("CSSM_SignData", crtn); + } + CSSM_DeleteContext(sigHand); + return crtn; +} + +static CSSM_RETURN sigVerify(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. + CSSM_KEY_PTR key, // public key + const CSSM_DATA *text, + const CSSM_DATA *sig, + uint32 digestAlg, // optional for raw signing + CSSM_BOOL noPad) // true --> add PADDING_NONE to context +{ + CSSM_CC_HANDLE sigHand; + CSSM_RETURN crtn; + + crtn = CSSM_CSP_CreateSignatureContext(cspHand, + algorithm, + NULL, // passPhrase + key, + &sigHand); + if(crtn) { + printError("CSSM_CSP_CreateSignatureContext", crtn); + return crtn; + } + if(noPad) { + crtn = AddContextAttribute(sigHand, + CSSM_ATTRIBUTE_PADDING, + sizeof(uint32), + CAT_Uint32, + NULL, + CSSM_PADDING_NONE); + if(crtn) { + return crtn; + } + } + crtn = CSSM_VerifyData(sigHand, + text, + 1, + digestAlg, + sig); + if(crtn) { + printError("CSSM_VerifyData", crtn); + } + CSSM_DeleteContext(sigHand); + return crtn; +} + +/* + * Generate DSA key pair. Algorithm parameters are + * either specified by caller via inParams, or are generated here + * and returned to caller in outParams. Exactly one of (inParams, + * outParams) must be non-NULL. + */ +static CSSM_RETURN genDsaKeyPair( + CSSM_CSP_HANDLE cspHand, + const char *keyLabel, + unsigned keyLabelLen, + uint32 keySize, // in bits + CSSM_KEY_PTR pubKey, // mallocd by caller + CSSM_BOOL pubIsRef, // true - reference key, false - data + uint32 pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + CSSM_KEYBLOB_FORMAT pubFormat, // Optional. Some algorithms (currently, FEE) + // provide for multiple key blob formats. + // Specify 0 or CSSM_KEYBLOB_RAW_FORMAT_NONE + // to get the default format. + CSSM_KEY_PTR privKey, // mallocd by caller + CSSM_BOOL privIsRef, // true - reference key, false - data + uint32 privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc. + CSSM_KEYBLOB_FORMAT privFormat, // optional 0 ==> default + const CSSM_DATA *inParams, // optional + CSSM_DATA_PTR outParams) // optional, we malloc +{ + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + CSSM_DATA keyLabelData; + uint32 pubAttr; + uint32 privAttr; + CSSM_RETURN ocrtn = CSSM_OK; + + /* Caller must specify either inParams or outParams, not both */ + if(inParams && outParams) { + return CSSMERR_CSSM_INVALID_POINTER; + } + if(!inParams && !outParams) { + return CSSMERR_CSSM_INVALID_POINTER; + } + + keyLabelData.Data = (uint8 *)keyLabel, + keyLabelData.Length = keyLabelLen; + memset(pubKey, 0, sizeof(CSSM_KEY)); + memset(privKey, 0, sizeof(CSSM_KEY)); + + crtn = CSSM_CSP_CreateKeyGenContext(cspHand, + CSSM_ALGID_DSA, + keySize, + NULL, // Seed + NULL, // Salt + NULL, // StartDate + NULL, // EndDate + inParams, // Params, may be NULL + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateKeyGenContext", crtn); + return crtn; + } + /* cook up attribute bits */ + if(pubIsRef) { + pubAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; + } + else { + pubAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + } + if(privIsRef) { + privAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; + } + else { + privAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + } + + if(outParams) { + /* explicitly generate params and return them to caller */ + outParams->Data = NULL; + outParams->Length = 0; + crtn = CSSM_GenerateAlgorithmParams(ccHand, + keySize, outParams); + if(crtn) { + printError("CSSM_GenerateAlgorithmParams", crtn); + CSSM_DeleteContext(ccHand); + return crtn; + } + } + + /* optional format specifiers */ + if(pubFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE) { + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT, + sizeof(uint32), + CAT_Uint32, + NULL, + pubFormat); + if(crtn) { + printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn); + return crtn; + } + } + if(privFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE) { + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT, + sizeof(uint32), + CAT_Uint32, + NULL, + privFormat); + if(crtn) { + printError("AddContextAttribute(CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT)", crtn); + return crtn; + } + } + crtn = CSSM_GenerateKeyPair(ccHand, + pubKeyUsage, + pubAttr, + &keyLabelData, + pubKey, + privKeyUsage, + privAttr, + &keyLabelData, // same labels + NULL, // CredAndAclEntry + privKey); + if(crtn) { + printError("CSSM_GenerateKeyPair", crtn); + ocrtn = crtn; + } + if(ccHand != 0) { + crtn = CSSM_DeleteContext(ccHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; + } + } + return ocrtn; +} + +/* + * Given keyFileBase, obtain name of public or private name. Output names + * mallocd by caller. + */ +#define KEY_FILE_NAME_MAX_LEN 256 + +static void rtKeyFileName( + const char *keyFileBase, + CSSM_BOOL isPub, + char *outFileName) +{ + if(isPub) { + sprintf(outFileName, "%s_pub.der", keyFileBase); + } + else { + sprintf(outFileName, "%s_priv.der", keyFileBase); + } +} + +/* + * Given keyFileBase and key type, init a CSSM_KEY. + */ +static int rt_readKey( + CSSM_CSP_HANDLE cspHand, + const char *keyFileBase, + CSSM_BOOL isPub, + CSSM_ALGORITHMS alg, + CSSM_KEYBLOB_FORMAT format, // FORMAT_NONE ==> default + CSSM_KEY_PTR key) +{ + char fileName[KEY_FILE_NAME_MAX_LEN]; + int irtn; + CSSM_DATA_PTR keyData = &key->KeyData; + CSSM_KEYHEADER_PTR hdr = &key->KeyHeader; + CSSM_RETURN crtn; + CSSM_KEY_SIZE keySize; + unsigned len; + + memset(key, 0, sizeof(CSSM_KEY)); + rtKeyFileName(keyFileBase, isPub, fileName); + irtn = readFile(fileName, &keyData->Data, &len); + if(irtn) { + printf("***error %d reading key file %s\n", irtn, fileName); + return irtn; + } + keyData->Length = len; + hdr->HeaderVersion = CSSM_KEYHEADER_VERSION; + hdr->BlobType = CSSM_KEYBLOB_RAW; + hdr->Format = format; + hdr->AlgorithmId = alg; + hdr->KeyClass = isPub ? CSSM_KEYCLASS_PUBLIC_KEY : + CSSM_KEYCLASS_PRIVATE_KEY; + hdr->KeyAttr = CSSM_KEYATTR_EXTRACTABLE; + hdr->KeyUsage = CSSM_KEYUSE_ANY; + + /* ask the CSP for key size */ + crtn = CSSM_QueryKeySizeInBits(cspHand, 0, key, &keySize); + if(crtn) { + printError("CSSM_QueryKeySizeInBits", crtn); + return 1; + } + hdr->LogicalKeySizeInBits = keySize.LogicalKeySizeInBits; + return 0; +} + +static int rt_generate(opParams *op) +{ + CSSM_RETURN crtn; + CSSM_KEY pubKey; + CSSM_KEY privKey; + char fileName[KEY_FILE_NAME_MAX_LEN]; + int irtn; + CSSM_DATA paramIn = {0, NULL}; + CSSM_DATA paramOut = {0, NULL}; + CSSM_DATA_PTR paramInPtr = NULL; + CSSM_DATA_PTR paramOutPtr = NULL; + + if(op->keyFileName == NULL) { + printf("***Need a keyFileName to generate key pair.\n"); + return 1; + } + memset(&pubKey, 0, sizeof(CSSM_KEY)); + memset(&privKey, 0, sizeof(CSSM_KEY)); + + if(op->alg == CSSM_ALGID_DSA) { + /* must specify either inParams or outParams, not both */ + if(op->dsaParamFileIn && op->dsaParamFileOut) { + printf("***DSA key generation requires one parameter file spec.\n"); + return 1; + } + if(!op->dsaParamFileIn && !op->dsaParamFileOut) { + printf("***DSA key generation requires one parameter file spec.\n"); + return 1; + } + if(op->dsaParamFileIn) { + /* caller-specified params */ + unsigned len; + irtn = readFile(op->dsaParamFileIn, ¶mIn.Data, &len); + if(irtn) { + printf("***Error reading DSA params from %s. Aborting.\n", + op->dsaParamFileIn); + } + paramIn.Length = len; + paramInPtr = ¶mIn; + } + else { + /* generate params --> paramOut */ + paramOutPtr = ¶mOut; + } + crtn = genDsaKeyPair(op->cspHand, + USAGE_NAME, + USAGE_NAME_LEN, + op->keySizeInBits, + &pubKey, + CSSM_FALSE, // not ref + CSSM_KEYUSE_VERIFY, // not really important + op->pubKeyFormat, + &privKey, + CSSM_FALSE, // not ref + CSSM_KEYUSE_SIGN, + op->privKeyFormat, + paramInPtr, + paramOutPtr); + if(crtn) { + return 1; + } + if(paramOutPtr) { + irtn = writeFile(op->dsaParamFileOut, paramOut.Data, paramOut.Length); + if(irtn) { + printf("***Error writing DSA params to %s. Aborting.\n", + op->dsaParamFileOut); + return 1; + } + if(!op->quiet) { + printf("...wrote %lu bytes to %s\n", paramOut.Length, + op->dsaParamFileOut); + } + CSSM_FREE(paramOut.Data); + } + else { + /* mallocd by readFile() */ + free(paramIn.Data); + } + } + else { + /* RSA, ECDSA */ + crtn = cspGenKeyPair(op->cspHand, + op->alg, + USAGE_NAME, + USAGE_NAME_LEN, + op->keySizeInBits, + &pubKey, + CSSM_FALSE, // not ref + CSSM_KEYUSE_VERIFY, // not really important + op->pubKeyFormat, + &privKey, + CSSM_FALSE, // not ref + CSSM_KEYUSE_SIGN, + op->privKeyFormat, + CSSM_FALSE); // genSeed, not used here + if(crtn) { + return 1; + } + } + + /* write the blobs */ + rtKeyFileName(op->keyFileName, CSSM_TRUE, fileName); + irtn = writeFile(fileName, pubKey.KeyData.Data, pubKey.KeyData.Length); + if(irtn) { + printf("***Error %d writing to %s\n", irtn, fileName); + return irtn; + } + if(!op->quiet) { + printf("...wrote %lu bytes to %s\n", pubKey.KeyData.Length, fileName); + } + rtKeyFileName(op->keyFileName, CSSM_FALSE, fileName); + irtn = writeFile(fileName, privKey.KeyData.Data, privKey.KeyData.Length); + if(irtn) { + printf("***Error %d writing to %s\n", irtn, fileName); + return irtn; + } + if(!op->quiet) { + printf("...wrote %lu bytes to %s\n", privKey.KeyData.Length, fileName); + } + cspFreeKey(op->cspHand, &pubKey); + cspFreeKey(op->cspHand, &privKey); + return 0; +} + +/* encrypt using public key */ +static int rt_encrypt(opParams *op) +{ + CSSM_KEY pubKey; + int irtn; + CSSM_DATA ptext; + CSSM_DATA ctext; + CSSM_RETURN crtn; + CSSM_BOOL isPub; + CSSM_ENCRYPT_MODE mode = CSSM_ALGMODE_NONE; + CSSM_KEYBLOB_FORMAT format = op->pubKeyFormat; + unsigned len; + + if(op->keyFileName == NULL) { + printf("***Need a keyFileName to encrypt.\n"); + return 1; + } + if((op->plainFileName == NULL) || (op->cipherFileName == NULL)) { + printf("***Need plainFileName and cipherFileName to encrypt.\n"); + return 1; + } + if(op->swapKeyClass) { + isPub = CSSM_FALSE; + mode = CSSM_ALGMODE_PRIVATE_KEY; + format = op->privKeyFormat; + } + else { + isPub = CSSM_TRUE; + } + irtn = rt_readKey(op->cspHand, op->keyFileName, isPub, op->alg, + format, &pubKey); + if(irtn) { + return irtn; + } + irtn = readFile(op->plainFileName, &ptext.Data, &len); + if(irtn) { + printf("***Error reading %s\n", op->plainFileName); + return irtn; + } + ptext.Length = len; + ctext.Data = NULL; + ctext.Length = 0; + + crtn = cspEncrypt(op->cspHand, + op->alg, + mode, + op->noPad ? CSSM_PADDING_NONE : CSSM_PADDING_PKCS1, + &pubKey, + NULL, + 0, // effectiveKeySize + 0, // rounds + NULL, // initVector + &ptext, + &ctext, + CSSM_FALSE); // mallocCtext + if(crtn) { + printError("cspEncrypt", crtn); + return 1; + } + irtn = writeFile(op->cipherFileName, ctext.Data, ctext.Length); + if(irtn) { + printf("***Error writing %s\n", op->cipherFileName); + } + else { + if(!op->quiet) { + printf("...wrote %lu bytes to %s\n", ctext.Length, op->cipherFileName); + } + } + + free(pubKey.KeyData.Data); // allocd by rt_readKey --> readFile + free(ptext.Data); // allocd by readFile + appFreeCssmData(&ctext, CSSM_FALSE); // by CSP + return irtn; +} + +/* decrypt using private key */ +static int rt_decrypt(opParams *op) +{ + CSSM_KEY privKey; + int irtn; + CSSM_DATA ptext; + CSSM_DATA ctext; + CSSM_RETURN crtn; + CSSM_BOOL isPub; + CSSM_ENCRYPT_MODE mode = CSSM_ALGMODE_NONE; + CSSM_KEYBLOB_FORMAT format = op->privKeyFormat; + unsigned len; + + if(op->keyFileName == NULL) { + printf("***Need a keyFileName to decrypt.\n"); + return 1; + } + if((op->plainFileName == NULL) || (op->cipherFileName == NULL)) { + printf("***Need plainFileName and cipherFileName to decrypt.\n"); + return 1; + } + if(op->swapKeyClass) { + isPub = CSSM_TRUE; + mode = CSSM_ALGMODE_PUBLIC_KEY; + format = op->pubKeyFormat; + } + else { + isPub = CSSM_FALSE; + } + irtn = rt_readKey(op->cspHand, op->keyFileName, isPub, op->alg, + format, &privKey); + if(irtn) { + return irtn; + } + irtn = readFile(op->cipherFileName, &ctext.Data, &len); + if(irtn) { + printf("***Error reading %s\n", op->cipherFileName); + return irtn; + } + ctext.Length = len; + ptext.Data = NULL; + ptext.Length = 0; + + crtn = cspDecrypt(op->cspHand, + op->alg, + mode, + op->noPad ? CSSM_PADDING_NONE : CSSM_PADDING_PKCS1, + &privKey, + NULL, + 0, // effectiveKeySize + 0, // rounds + NULL, // initVector + &ctext, + &ptext, + CSSM_FALSE); // mallocCtext + if(crtn) { + return 1; + } + irtn = writeFile(op->plainFileName, ptext.Data, ptext.Length); + if(irtn) { + printf("***Error writing %s\n", op->cipherFileName); + } + else { + if(!op->quiet) { + printf("...wrote %lu bytes to %s\n", ptext.Length, op->plainFileName); + } + } + free(privKey.KeyData.Data); // allocd by rt_readKey --> readFile + free(ctext.Data); // allocd by readFile + appFreeCssmData(&ptext, CSSM_FALSE); // by CSP + return irtn; +} + +static int rt_sign(opParams *op) +{ + CSSM_KEY privKey; + int irtn; + CSSM_DATA ptext; + CSSM_DATA sig; + CSSM_RETURN crtn; + CSSM_ALGORITHMS alg; + unsigned len; + + if(op->keyFileName == NULL) { + printf("***Need a keyFileName to sign.\n"); + return 1; + } + if((op->plainFileName == NULL) || (op->sigFileName == NULL)) { + printf("***Need plainFileName and sigFileName to sign.\n"); + return 1; + } + irtn = rt_readKey(op->cspHand, op->keyFileName, CSSM_FALSE, op->alg, + op->privKeyFormat, &privKey); + if(irtn) { + return irtn; + } + irtn = readFile(op->plainFileName, &ptext.Data, &len); + if(irtn) { + printf("***Error reading %s\n", op->plainFileName); + return irtn; + } + ptext.Length = len; + sig.Data = NULL; + sig.Length = 0; + switch(op->alg) { + case CSSM_ALGID_RSA: + if(op->rawSign) { + alg = CSSM_ALGID_RSA; + } + else { + alg = CSSM_ALGID_SHA1WithRSA; + } + break; + case CSSM_ALGID_DSA: + alg = CSSM_ALGID_SHA1WithDSA; + break; + case CSSM_ALGID_ECDSA: + if(op->rawSign) { + alg = CSSM_ALGID_ECDSA; + } + else { + alg = CSSM_ALGID_SHA1WithECDSA; + } + break; + default: + printf("Hey! Try another alg!\n"); + exit(1); + } + crtn = sigSign(op->cspHand, + alg, + &privKey, + &ptext, + &sig, + op->digestAlg, + op->noPad); + if(crtn) { + printError("cspSign", crtn); + return 1; + } + irtn = writeFile(op->sigFileName, sig.Data, sig.Length); + if(irtn) { + printf("***Error writing %s\n", op->sigFileName); + } + else if(!op->quiet) { + printf("...wrote %lu bytes to %s\n", sig.Length, op->sigFileName); + } + free(privKey.KeyData.Data); // allocd by rt_readKey --> readFile + free(ptext.Data); // allocd by readFile + appFreeCssmData(&sig, CSSM_FALSE); // by CSP + return irtn; +} + +static int rt_verify(opParams *op) +{ + CSSM_KEY pubKey; + int irtn; + CSSM_DATA ptext; + CSSM_DATA sig; + CSSM_RETURN crtn; + CSSM_ALGORITHMS alg; + unsigned len; + + if(op->keyFileName == NULL) { + printf("***Need a keyFileName to verify.\n"); + return 1; + } + if((op->plainFileName == NULL) || (op->sigFileName == NULL)) { + printf("***Need plainFileName and sigFileName to verify.\n"); + return 1; + } + irtn = rt_readKey(op->cspHand, op->keyFileName, CSSM_TRUE, op->alg, + op->pubKeyFormat, &pubKey); + if(irtn) { + return irtn; + } + irtn = readFile(op->plainFileName, &ptext.Data, &len); + if(irtn) { + printf("***Error reading %s\n", op->plainFileName); + return irtn; + } + ptext.Length = len; + irtn = readFile(op->sigFileName, &sig.Data, (unsigned *)&sig.Length); + if(irtn) { + printf("***Error reading %s\n", op->sigFileName); + return irtn; + } + switch(op->alg) { + case CSSM_ALGID_RSA: + if(op->rawSign) { + alg = CSSM_ALGID_RSA; + } + else { + alg = CSSM_ALGID_SHA1WithRSA; + } + break; + case CSSM_ALGID_DSA: + alg = CSSM_ALGID_SHA1WithDSA; + break; + case CSSM_ALGID_ECDSA: + if(op->rawSign) { + alg = CSSM_ALGID_ECDSA; + } + else { + alg = CSSM_ALGID_SHA1WithECDSA; + } + break; + default: + printf("Hey! Try another alg!\n"); + exit(1); + } + crtn = sigVerify(op->cspHand, + alg, + &pubKey, + &ptext, + &sig, + op->digestAlg, + op->noPad); + if(crtn) { + printError("sigVerify", crtn); + irtn = 1; + } + else if(!op->quiet){ + printf("...signature verifies OK\n"); + irtn = 0; + } + free(pubKey.KeyData.Data); // allocd by rt_readKey --> readFile + free(ptext.Data); // allocd by readFile + free(sig.Data); // ditto + return irtn; +} + +static int rt_digest(opParams *op) +{ + int irtn; + CSSM_DATA ptext; + CSSM_DATA digest = {0, NULL}; + CSSM_RETURN crtn; + unsigned len; + + if((op->plainFileName == NULL) || (op->sigFileName == NULL)) { + printf("***Need plainFileName and sigFileName to digest.\n"); + return 1; + } + irtn = readFile(op->plainFileName, &ptext.Data, &len); + if(irtn) { + printf("***Error reading %s\n", op->plainFileName); + return irtn; + } + ptext.Length = len; + crtn = cspDigest(op->cspHand, + op->alg, + CSSM_FALSE, // mallocDigest - let CSP do it + &ptext, + &digest); + if(crtn) { + printError("cspDigest", crtn); + return 1; + } + irtn = writeFile(op->sigFileName, digest.Data, digest.Length); + if(irtn) { + printf("***Error writing %s\n", op->sigFileName); + } + else if(!op->quiet){ + printf("...wrote %lu bytes to %s\n", digest.Length, op->sigFileName); + } + free(ptext.Data); // allocd by readFile + appFreeCssmData(&digest, CSSM_FALSE); // by CSP + return irtn; +} + +static int rt_convertPubKey(opParams *op) +{ + CSSM_RETURN crtn; + int irtn; + CSSM_KEY pubKeyIn; + CSSM_KEY pubKeyOut; + CSSM_KEY refKey; + char fileName[KEY_FILE_NAME_MAX_LEN]; + + if((op->keyFileName == NULL) || (op->outKeyFileName == NULL)) { + printf("***I need input and output key file names for public key concersion.\n"); + return 1; + } + irtn = rt_readKey(op->cspHand, op->keyFileName, CSSM_TRUE, op->alg, + op->pubKeyFormat, &pubKeyIn); + if(irtn) { + return irtn; + } + crtn = cspRawKeyToRef(op->cspHand, &pubKeyIn, &refKey); + if(crtn) { + printf("***Error on NULL unwrap of %s\n", op->keyFileName); + return -1; + } + crtn = nullWrapKey(op->cspHand, &refKey, op->outPubKeyFormat, &pubKeyOut); + if(crtn) { + printf("***Error on NULL wrap\n"); + return 1; + } + + /* write the blobs */ + rtKeyFileName(op->outKeyFileName, CSSM_TRUE, fileName); + irtn = writeFile(fileName, pubKeyOut.KeyData.Data, pubKeyOut.KeyData.Length); + if(irtn) { + printf("***Error %d writing to %s\n", irtn, fileName); + return irtn; + } + if(!op->quiet) { + printf("...wrote %lu bytes to %s\n", pubKeyOut.KeyData.Length, fileName); + } + cspFreeKey(op->cspHand, &pubKeyOut); + free(pubKeyIn.KeyData.Data); + cspFreeKey(op->cspHand, &refKey); + return 0; +} + +/* parse public key format character */ +static CSSM_KEYBLOB_FORMAT parsePubKeyFormat(char c, char **argv) +{ + switch(c) { + case '1': + return CSSM_KEYBLOB_RAW_FORMAT_PKCS1; + case 'x': + return CSSM_KEYBLOB_RAW_FORMAT_X509; + case 'b': + return CSSM_KEYBLOB_RAW_FORMAT_FIPS186; + case 'o': + return CSSM_KEYBLOB_RAW_FORMAT_OPENSSH; + case 'O': + return CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2; + case 'L': + /* This is the "parse a private+public key as public only" option */ + return CSSM_KEYBLOB_RAW_FORMAT_OPENSSL; + default: + usage(argv); + } + /* not reached */ + return -1; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + int rtn; + opParams op; + + if(argc < 2) { + usage(argv); + } + memset(&op, 0, sizeof(opParams)); + op.keySizeInBits = DEFAULT_KEY_SIZE_BITS; + op.alg = CSSM_ALGID_RSA; + op.swapKeyClass = CSSM_FALSE; + op.rawSign = CSSM_FALSE; + op.noPad = CSSM_FALSE; + + for(arg=2; arg +#include +#include +#include +#include "cputime.h" +#include "common.h" + +static void usage(char **argv) +{ + printf("Usage: %s bytecount [q(uiet)]\n", argv[0]); + exit(1); +} + +#define BUFSIZE (8 * 1024) + +int main(int argc, char **argv) +{ + bool quiet = false; + unsigned byteCount; + + if(argc < 2) { + usage(argv); + } + byteCount = atoi(argv[1]); + for(int arg=2; arg BUFSIZE) { + thisMove = BUFSIZE; + } + else { + thisMove = toMove; + } + toMove -= thisMove; + CC_SHA1_Update(&ctx1, text, thisMove); + } while(toMove); + CC_SHA1_Final(dig1, &ctx1); + timeSpentMs = CPUTimeDeltaMs(startTime, CPUTimeRead()); + printf("SHA1: Digest %u bytes : %.2f ms\n", byteCount, timeSpentMs); + + /* SHA256 */ + if(!quiet) { + printf("...testing SHA256\n"); + } + + CC_SHA256_CTX ctx256; + unsigned char dig256[CC_SHA256_DIGEST_LENGTH]; + toMove = byteCount; + CC_SHA256_Init(&ctx256); + + /* start critical timing loop */ + startTime = CPUTimeRead(); + do { + if(toMove > BUFSIZE) { + thisMove = BUFSIZE; + } + else { + thisMove = toMove; + } + toMove -= thisMove; + CC_SHA256_Update(&ctx256, text, thisMove); + } while(toMove); + CC_SHA256_Final(dig256, &ctx256); + timeSpentMs = CPUTimeDeltaMs(startTime, CPUTimeRead()); + printf("SHA256: Digest %u bytes : %.2f ms\n", byteCount, timeSpentMs); + + /* SHA256 */ + if(!quiet) { + printf("...testing SHA512\n"); + } + + CC_SHA512_CTX ctx512; + unsigned char dig512[CC_SHA512_DIGEST_LENGTH]; + toMove = byteCount; + CC_SHA512_Init(&ctx512); + + /* start critical timing loop */ + startTime = CPUTimeRead(); + do { + if(toMove > BUFSIZE) { + thisMove = BUFSIZE; + } + else { + thisMove = toMove; + } + toMove -= thisMove; + CC_SHA512_Update(&ctx512, text, thisMove); + } while(toMove); + CC_SHA512_Final(dig512, &ctx512); + timeSpentMs = CPUTimeDeltaMs(startTime, CPUTimeRead()); + printf("SHA512: Digest %u bytes : %.2f ms\n", byteCount, timeSpentMs); + + return 0; +} diff --git a/SecurityTests/cspxutils/sha2Vectors/Makefile b/SecurityTests/cspxutils/sha2Vectors/Makefile new file mode 100644 index 00000000..d97513b1 --- /dev/null +++ b/SecurityTests/cspxutils/sha2Vectors/Makefile @@ -0,0 +1,49 @@ +EXECUTABLE=sha2Vectors +# C++ source (with .cpp extension) +CPSOURCE= sha2Vectors.cpp +# C source (.c extension) +CSOURCE= +OFILES = $(CSOURCE:%.c=%.o) $(CPSOURCE:%.cpp=%.o) + +LOCAL_BUILD= $(shell echo $(LOCAL_BUILD_DIR)) + +VARIANT_SUFFIX= + +FRAMEWORKS= +FRAME_SEARCH= -F$(LOCAL_BUILD) +FINCLUDES= +PINCLUDES= -I$(LOCAL_BUILD)/include +CINCLUDES= $(FINCLUDES) $(PINCLUDES) +WFLAGS= -Wno-four-char-constants -Wno-deprecated-declarations +CFLAGS= -g $(CINCLUDES) $(WFLAGS) $(FRAME_SEARCH) + +# +# This assumes final load with cc, not ld +# +#LIBS= -lstdc++ -lcommonCrypto$(VARIANT_SUFFIX) +LIBS= -lstdc++ + +# this is temporary +LIBPATH= -L$(LOCAL_BUILD) -L/usr/local/lib/system +LDFLAGS= $(LIBS) $(LIBPATH) $(FRAME_SEARCH) + +first: $(EXECUTABLE) + +$(EXECUTABLE): $(OFILES) + $(CC) -o $(EXECUTABLE) $(FRAMEWORKS) $(OFILES) $(LDFLAGS) + +debug: + make "VARIANT_SUFFIX=_debug" + +clean: + rm -f *.o $(EXECUTABLE) + +installhdrs: + +install: + +%.o: %.c + $(CC) $(CFLAGS) -c -o $*.o $< + +%.o: %.cpp + $(CC) $(CFLAGS) -c -o $*.o $< diff --git a/SecurityTests/cspxutils/sha2Vectors/sha2Vectors.cpp b/SecurityTests/cspxutils/sha2Vectors/sha2Vectors.cpp new file mode 100644 index 00000000..dec315bf --- /dev/null +++ b/SecurityTests/cspxutils/sha2Vectors/sha2Vectors.cpp @@ -0,0 +1,361 @@ +/* + * Verify SHA2 against FIPS test vectors. + */ + +#include +#include +#include +#include + +static void usage(char **argv) +{ + printf("Usage: %s [q(uiet)]\n", argv[0]); + exit(1); +} + +/* + * These test vectors came from FIPS Processing Standards Publication 180-2, + * 2002 August 1. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +/* SHA256 vectors */ +static const char *v1_256_text = "abc"; +static int v1_256_textLen=3; +static unsigned const char v1_256_digest[] = { + 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, + 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, + 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, + 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad +}; + +static const char *v2_256_text = "abcdbcdecdefdefgefghfghighijhi" + "jkijkljklmklmnlmnomnopnopq"; +#define v2_256_textLen strlen(v2_256_text) +static unsigned const char v2_256_digest[] = { + 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 +}; + +/* Vector 3: text = one million 'a' characters */ +static unsigned const char v3_256_digest[] = { + 0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92, + 0x81, 0xa1, 0xc7, 0xe2, 0x84, 0xd7, 0x3e, 0x67, + 0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97, 0x20, 0x0e, + 0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0 +}; + +/* SHA384 vectors */ +static const char *v1_384_text = "abc"; +static int v1_384_textLen=3; +static unsigned const char v1_384_digest[] = { + 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, + 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07, + 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63, + 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed, + 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23, + 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 +}; + +static const char *v2_384_text = "abcdefghbcdefghicdefghijdefghij" + "kefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqr" + "lmnopqrsmnopqrstnopqrstu"; +#define v2_384_textLen strlen(v2_384_text) +static unsigned const char v2_384_digest[] = { + 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8, + 0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47, + 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2, + 0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12, + 0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9, + 0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39 +}; + +/* Vector 3: text = one million 'a' characters */ +static unsigned const char v3_384_digest[] = { + 0x9d, 0x0e, 0x18, 0x09, 0x71, 0x64, 0x74, 0xcb, + 0x08, 0x6e, 0x83, 0x4e, 0x31, 0x0a, 0x4a, 0x1c, + 0xed, 0x14, 0x9e, 0x9c, 0x00, 0xf2, 0x48, 0x52, + 0x79, 0x72, 0xce, 0xc5, 0x70, 0x4c, 0x2a, 0x5b, + 0x07, 0xb8, 0xb3, 0xdc, 0x38, 0xec, 0xc4, 0xeb, + 0xae, 0x97, 0xdd, 0xd8, 0x7f, 0x3d, 0x89, 0x85 +}; + +/* SHA512 vectors */ +static const char *v1_512_text = "abc"; +static int v1_512_textLen=3; +static unsigned const char v1_512_digest[] = { + 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, + 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, + 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, + 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, + 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, + 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, + 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, + 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f +}; + +static const char *v2_512_text = "abcdefghbcdefghicdefghijdefgh" + "ijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmn" + "opqrlmnopqrsmnopqrstnopqrstu"; +#define v2_512_textLen strlen(v2_512_text) +static unsigned const char v2_512_digest[] = { + 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, + 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f, + 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, + 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, + 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, + 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a, + 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, + 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 +}; + +/* Vector 3: one million 'a' characters */ +static unsigned const char v3_512_digest[] = { + 0xe7, 0x18, 0x48, 0x3d, 0x0c, 0xe7, 0x69, 0x64, + 0x4e, 0x2e, 0x42, 0xc7, 0xbc, 0x15, 0xb4, 0x63, + 0x8e, 0x1f, 0x98, 0xb1, 0x3b, 0x20, 0x44, 0x28, + 0x56, 0x32, 0xa8, 0x03, 0xaf, 0xa9, 0x73, 0xeb, + 0xde, 0x0f, 0xf2, 0x44, 0x87, 0x7e, 0xa6, 0x0a, + 0x4c, 0xb0, 0x43, 0x2c, 0xe5, 0x77, 0xc3, 0x1b, + 0xeb, 0x00, 0x9c, 0x5c, 0x2c, 0x49, 0xaa, 0x2e, + 0x4e, 0xad, 0xb2, 0x17, 0xad, 0x8c, 0xc0, 0x9b +}; + +/* + * SHA224 vectors, not part of the FIPS standard; these were obtained from RFC 3874. + */ +static const char *v1_224_text = "abc"; +static int v1_224_textLen=3; +static unsigned const char v1_224_digest[] = { + 0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8, 0x22, + 0x86, 0x42, 0xa4, 0x77, 0xbd, 0xa2, 0x55, 0xb3, + 0x2a, 0xad, 0xbc, 0xe4, 0xbd, 0xa0, 0xb3, 0xf7, + 0xe3, 0x6c, 0x9d, 0xa7 +}; + +static const char *v2_224_text = "abcdbcdecdefdefgefghfghighi" + "jhijkijkljklmklmnlmnomnopnopq"; +static int v2_224_textLen=56; +static unsigned const char v2_224_digest[] = { + 0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76, 0xcc, + 0x5d, 0xba, 0x5d, 0xa1, 0xfd, 0x89, 0x01, 0x50, + 0xb0, 0xc6, 0x45, 0x5c, 0xb4, 0xf5, 0x8b, 0x19, + 0x52, 0x52, 0x25, 0x25 +}; + +/* Vector 3: one million 'a' characters */ +static unsigned const char v3_224_digest[] = { + 0x20, 0x79, 0x46, 0x55, 0x98, 0x0c, 0x91, 0xd8, + 0xbb, 0xb4, 0xc1, 0xea, 0x97, 0x61, 0x8a, 0x4b, + 0xf0, 0x3f, 0x42, 0x58, 0x19, 0x48, 0xb2, 0xee, + 0x4e, 0xe7, 0xad, 0x67 +}; + +static void dumpBuffer( + const char *bufName, // optional + const unsigned char *buf, + unsigned len) +{ + unsigned i; + + if(bufName) { + printf("%s\n", bufName); + } + printf(" "); + for(i=0; i +#include +#include +#include "cspwrap.h" +#include "common.h" +/* this is for hard-coded lengths only */ +#include + +static void usage(char **argv) +{ + printf("Usage: %s [option...]\n", argv[0]); + printf("Options:\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" q(uiet)\n"); + exit(1); +} + +/* + * These test vectors came from FIPS Processing Standards Publication 180-2, + * 2002 August 1. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +/* SHA256 vectors */ +static const char *v1_256_text = "abc"; +static int v1_256_textLen=3; +static unsigned const char v1_256_digest[] = { + 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, + 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, + 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, + 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad +}; + +static const char *v2_256_text = "abcdbcdecdefdefgefghfghighijhi" + "jkijkljklmklmnlmnomnopnopq"; +#define v2_256_textLen strlen(v2_256_text) +static unsigned const char v2_256_digest[] = { + 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 +}; + +/* Vector 3: text = one million 'a' characters */ +static unsigned const char v3_256_digest[] = { + 0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92, + 0x81, 0xa1, 0xc7, 0xe2, 0x84, 0xd7, 0x3e, 0x67, + 0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97, 0x20, 0x0e, + 0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0 +}; + +/* SHA384 vectors */ +static const char *v1_384_text = "abc"; +static int v1_384_textLen=3; +static unsigned const char v1_384_digest[] = { + 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, + 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07, + 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63, + 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed, + 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23, + 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 +}; + +static const char *v2_384_text = "abcdefghbcdefghicdefghijdefghij" + "kefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqr" + "lmnopqrsmnopqrstnopqrstu"; +#define v2_384_textLen strlen(v2_384_text) +static unsigned const char v2_384_digest[] = { + 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8, + 0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47, + 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2, + 0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12, + 0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9, + 0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39 +}; + +/* Vector 3: text = one million 'a' characters */ +static unsigned const char v3_384_digest[] = { + 0x9d, 0x0e, 0x18, 0x09, 0x71, 0x64, 0x74, 0xcb, + 0x08, 0x6e, 0x83, 0x4e, 0x31, 0x0a, 0x4a, 0x1c, + 0xed, 0x14, 0x9e, 0x9c, 0x00, 0xf2, 0x48, 0x52, + 0x79, 0x72, 0xce, 0xc5, 0x70, 0x4c, 0x2a, 0x5b, + 0x07, 0xb8, 0xb3, 0xdc, 0x38, 0xec, 0xc4, 0xeb, + 0xae, 0x97, 0xdd, 0xd8, 0x7f, 0x3d, 0x89, 0x85 +}; + +/* SHA512 vectors */ +static const char *v1_512_text = "abc"; +static int v1_512_textLen=3; +static unsigned const char v1_512_digest[] = { + 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, + 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, + 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, + 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, + 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, + 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, + 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, + 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f +}; + +static const char *v2_512_text = "abcdefghbcdefghicdefghijdefgh" + "ijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmn" + "opqrlmnopqrsmnopqrstnopqrstu"; +#define v2_512_textLen strlen(v2_512_text) +static unsigned const char v2_512_digest[] = { + 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, + 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f, + 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, + 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, + 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, + 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a, + 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, + 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 +}; + +/* Vector 3: one million 'a' characters */ +static unsigned const char v3_512_digest[] = { + 0xe7, 0x18, 0x48, 0x3d, 0x0c, 0xe7, 0x69, 0x64, + 0x4e, 0x2e, 0x42, 0xc7, 0xbc, 0x15, 0xb4, 0x63, + 0x8e, 0x1f, 0x98, 0xb1, 0x3b, 0x20, 0x44, 0x28, + 0x56, 0x32, 0xa8, 0x03, 0xaf, 0xa9, 0x73, 0xeb, + 0xde, 0x0f, 0xf2, 0x44, 0x87, 0x7e, 0xa6, 0x0a, + 0x4c, 0xb0, 0x43, 0x2c, 0xe5, 0x77, 0xc3, 0x1b, + 0xeb, 0x00, 0x9c, 0x5c, 0x2c, 0x49, 0xaa, 0x2e, + 0x4e, 0xad, 0xb2, 0x17, 0xad, 0x8c, 0xc0, 0x9b +}; + +/* + * SHA224 vectors, not part of the FIPS standard; these were obtained from RFC 3874. + */ +static const char *v1_224_text = "abc"; +static int v1_224_textLen=3; +static unsigned const char v1_224_digest[] = { + 0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8, 0x22, + 0x86, 0x42, 0xa4, 0x77, 0xbd, 0xa2, 0x55, 0xb3, + 0x2a, 0xad, 0xbc, 0xe4, 0xbd, 0xa0, 0xb3, 0xf7, + 0xe3, 0x6c, 0x9d, 0xa7 +}; + +static const char *v2_224_text = "abcdbcdecdefdefgefghfghighi" + "jhijkijkljklmklmnlmnomnopnopq"; +static int v2_224_textLen=56; +static unsigned const char v2_224_digest[] = { + 0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76, 0xcc, + 0x5d, 0xba, 0x5d, 0xa1, 0xfd, 0x89, 0x01, 0x50, + 0xb0, 0xc6, 0x45, 0x5c, 0xb4, 0xf5, 0x8b, 0x19, + 0x52, 0x52, 0x25, 0x25 +}; + +/* Vector 3: one million 'a' characters */ +static unsigned const char v3_224_digest[] = { + 0x20, 0x79, 0x46, 0x55, 0x98, 0x0c, 0x91, 0xd8, + 0xbb, 0xb4, 0xc1, 0xea, 0x97, 0x61, 0x8a, 0x4b, + 0xf0, 0x3f, 0x42, 0x58, 0x19, 0x48, 0xb2, 0xee, + 0x4e, 0xe7, 0xad, 0x67 +}; + +static void dumpBuffer( + const char *bufName, // optional + const unsigned char *buf, + unsigned len) +{ + unsigned i; + + if(bufName) { + printf("%s\n", bufName); + } + printf(" "); + for(i=0; i +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include +#include + +/* + * Defaults. + */ +#define SIG_LOOPS_DEF 1000 /* sig loops */ +#define KEYSIZE_DEF 512 +#define PTEXT_SIZE 20 /* e.g., a SHA1 digest */ + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" a=algorithm (r=RSA; d=DSA; s=SHA1/RSA; f=FEE/SHA1; F=FEE/MD5; e=ECDSA;\n"); + printf(" E=ECDSA/ANSI; default=RSA)\n"); + printf(" l=numLoop (default=%d)\n", SIG_LOOPS_DEF); + printf(" k=keySizeInBits; default=%d\n", KEYSIZE_DEF); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" b (RSA blinding enabled)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + + +int main(int argc, char **argv) +{ + int arg; + char *argp; + CSSM_CSP_HANDLE cspHand; + unsigned i; + CSSM_KEY pubKey; + CSSM_KEY privKey; + CSSM_DATA_PTR ptext; // different for each sign/vfy + CSSM_DATA_PTR sig; // ditto + unsigned sigSize; + CSSM_RETURN crtn; + CFAbsoluteTime start, end; + CSSM_CC_HANDLE sigHand; + + /* + * User-spec'd params + */ + uint32 keySizeInBits = KEYSIZE_DEF; + unsigned sigLoops = SIG_LOOPS_DEF; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL bareCsp = CSSM_TRUE; + CSSM_ALGORITHMS sigAlg = CSSM_ALGID_RSA; + CSSM_ALGORITHMS keyAlg = CSSM_ALGID_RSA; + CSSM_ALGORITHMS digestAlg = CSSM_ALGID_SHA1; + CSSM_BOOL rsaBlinding = CSSM_FALSE; + + for(arg=1; arg +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include + +#define DATA_SIZE_DEF 100 +#define USAGE_DEF "noUsage" +#define LOOPS_DEF 10 +#define FEE_PASSWD_LEN 32 /* private data length in bytes, FEE only */ + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" a=algorithm\n"); + printf(" f=FEE/MD5 F=FEE/SHA1 e=ECDSA r=RSA/MD5 2=RSA/MD2 \n"); + printf(" s=RSA/SHA1 d=DSA R=rawRSA (No digest) \n"); + printf(" 4=RSA/SHA224 6=RSA/SHA256 3=RSA/SHA384 5=RSA/SHA512;\n"); + printf(" E=ECDSA/ANSI; 7=ECDSA/SHA256; 8=ECDSA/SHA384; 9=ECDSA/512; default=RSA/SHA1\n"); + printf(" d=dataSize (default = %d)\n", DATA_SIZE_DEF); + printf(" k=keySize\n"); + printf(" b (pub is blob)\n"); + printf(" r (priv is blob)\n"); + printf(" B=[1xboOt] (pub key in PKCS1/X509/BSAFE/OpenSSH1/OpenSSH2/Octet form)\n"); + printf(" RSA = {PKCS1,X509,OpenSSH1,OpenSSH2} default = PKCS1\n"); + printf(" DSA = {BSAFE,X509,OpenSSH2} default = X509\n"); + printf(" ECDSA = {X509, Only!} default = X509\n"); + printf(" P=primeType (m=Mersenne, f=FEE, g=general; FEE only)\n"); + printf(" C=curveType (m=Montgomery, w=Weierstrass, a=ANSI; FEE only)\n"); + printf(" l=loops (0=forever)\n"); + printf(" s(ign only)\n"); + printf(" V(erify only)\n"); + printf(" c(ontexts only)\n"); + printf(" S (we generate seed, for FEE only)\n"); + printf(" n(o padding; default is PKCS1)\n"); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" L (dump key and signature blobs)\n"); + printf(" o (key blobs in OCTET_STRING format)\n"); + printf(" q(uiet)\n"); + printf(" v(erbose))\n"); + exit(1); +} + +/* parse public key format character */ +static CSSM_KEYBLOB_FORMAT parsePubKeyFormat(char c, char **argv) +{ + switch(c) { + case '1': + return CSSM_KEYBLOB_RAW_FORMAT_PKCS1; + case 'x': + return CSSM_KEYBLOB_RAW_FORMAT_X509; + case 'b': + return CSSM_KEYBLOB_RAW_FORMAT_FIPS186; + case 'o': + return CSSM_KEYBLOB_RAW_FORMAT_OPENSSH; + case 'O': + return CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2; + default: + usage(argv); + } + /* not reached */ + return -1; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + CSSM_CSP_HANDLE cspHand; + CSSM_CC_HANDLE pubSigHand; + CSSM_CC_HANDLE privSigHand; + CSSM_RETURN crtn; + CSSM_DATA randData = {0, NULL}; + CSSM_KEY privKey; + CSSM_KEY pubKey; + CSSM_DATA sigData = {0, NULL}; + unsigned loop; + int i; + unsigned dataSize = DATA_SIZE_DEF; + unsigned keySize = CSP_KEY_SIZE_DEFAULT; + uint32 sigAlg = CSSM_ALGID_SHA1WithRSA; + uint32 keyGenAlg = CSSM_ALGID_RSA; + unsigned pauseInterval = 0; + unsigned loops = LOOPS_DEF; + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL pubIsRef = CSSM_TRUE; + CSSM_BOOL privIsRef = CSSM_TRUE; + CSSM_BOOL doSign = CSSM_TRUE; + CSSM_BOOL doVerify = CSSM_TRUE; + CSSM_BOOL contextsOnly = CSSM_FALSE; + CSSM_BOOL noPadding = CSSM_FALSE; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL bareCsp = CSSM_TRUE; + CSSM_BOOL genSeed = CSSM_FALSE; + CSSM_BOOL dumpBlobs = CSSM_FALSE; + CSSM_KEYBLOB_FORMAT privKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_NONE; + CSSM_KEYBLOB_FORMAT pubKeyFormat = CSSM_KEYBLOB_RAW_FORMAT_NONE; + uint32 primeType = CSSM_FEE_PRIME_TYPE_DEFAULT; // FEE only + uint32 curveType = CSSM_FEE_CURVE_TYPE_DEFAULT; // FEE only + + for(arg=1; arg +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define dprintf(s...) printf(s) + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" -i inFile\n"); + printf(" -o outFile\n"); + printf(" -v -- private key input; default is public\n"); + printf(" -V -- private key output; default is public\n"); + printf(" -d -- DSA; default is RSA\n"); + printf(" -r -- parse & print inFile\n"); + printf(" -f ssh1|ssh2 -- input format; default = ssh2\n"); + printf(" -F ssh1|ssh2 -- output format; default = ssh2\n"); + printf(" -p password\n"); + printf(" -P -- no password; private keys in the clear\n"); + printf(" -c comment\n"); + exit(1); +} + +static const char *authfile_id_string = "SSH PRIVATE KEY FILE FORMAT 1.1\n"; + +/* from openssh cipher.h */ +#define SSH_CIPHER_NONE 0 /* no encryption */ +#define SSH_CIPHER_IDEA 1 /* IDEA CFB */ +#define SSH_CIPHER_DES 2 /* DES CBC */ +#define SSH_CIPHER_3DES 3 /* 3DES CBC */ +#define SSH_CIPHER_BROKEN_TSS 4 /* TRI's Simple Stream encryption CBC */ +#define SSH_CIPHER_BROKEN_RC4 5 /* Alleged RC4 */ +#define SSH_CIPHER_BLOWFISH 6 +#define SSH_CIPHER_RESERVED 7 + +#define SSH2_RSA_HEADER "ssh-rsa" +#define SSH2_DSA_HEADER "ssh-dss" + +#pragma mark --- commmon code --- + +static uint32_t readUint32( + const unsigned char *&cp, // IN/OUT + unsigned &len) // IN/OUT +{ + uint32_t r = 0; + + for(unsigned dex=0; dex=0; dex--) { + buf[dex] = ui & 0xff; + ui >>= 8; + } + CFDataAppendBytes(cfOut, buf, sizeof(uint32_t)); +} + +static void appendUint16( + CFMutableDataRef cfOut, + uint16_t ui) +{ + UInt8 buf[sizeof(uint16_t)]; + + buf[1] = ui & 0xff; + ui >>= 8; + buf[0] = ui; + CFDataAppendBytes(cfOut, buf, sizeof(uint16_t)); +} + +/* parse text as decimal, return BIGNUM */ +static BIGNUM *parseDecimalBn( + const unsigned char *cp, + unsigned len) +{ + for(unsigned dex=0; dex '9')) { + return NULL; + } + } + char *str = (char *)malloc(len + 1); + memmove(str, cp, len); + str[len] = '\0'; + BIGNUM *bn = NULL; + BN_dec2bn(&bn, str); + free(str); + return bn; +} + +/* Read BIGNUM, OpenSSH-1 version */ +static BIGNUM *readBigNum( + const unsigned char *&cp, // IN/OUT + unsigned &remLen) // IN/OUT +{ + if(remLen < sizeof(uint16_t)) { + dprintf("readBigNum: short record(1)\n"); + return NULL; + } + uint16_t numBits = readUint16(cp, remLen); + unsigned bytes = (numBits + 7) / 8; + if(remLen < bytes) { + dprintf("readBigNum: short record(2)\n"); + return NULL; + } + BIGNUM *bn = BN_bin2bn(cp, bytes, NULL); + if(bn == NULL) { + dprintf("readBigNum: BN_bin2bn error\n"); + return NULL; + } + cp += bytes; + remLen -= bytes; + return bn; +} + +/* Write BIGNUM, OpenSSH-1 version */ +static int appendBigNum( + CFMutableDataRef cfOut, + const BIGNUM *bn) +{ + /* 16 bits of numbits */ + unsigned numBits = BN_num_bits(bn); + appendUint16(cfOut, numBits); + + /* serialize the bytes */ + int numBytes = (numBits + 7) / 8; + unsigned char outBytes[numBytes]; // gcc is so cool... + int moved = BN_bn2bin(bn, outBytes); + if(moved != numBytes) { + dprintf("appendBigNum: BN_bn2bin() screwup\n"); + return -1; + } + CFDataAppendBytes(cfOut, (UInt8 *)outBytes, numBytes); + return 0; +} + +/* read BIGNUM, OpenSSH-2 mpint version */ +static BIGNUM *readBigNum2( + const unsigned char *&cp, // IN/OUT + unsigned &remLen) // IN/OUT +{ + if(remLen < 4) { + dprintf("readBigNum2: short record(1)\n"); + return NULL; + } + uint32_t bytes = readUint32(cp, remLen); + if(remLen < bytes) { + dprintf("readBigNum2: short record(2)\n"); + return NULL; + } + BIGNUM *bn = BN_bin2bn(cp, bytes, NULL); + if(bn == NULL) { + dprintf("readBigNum2: BN_bin2bn error\n"); + return NULL; + } + cp += bytes; + remLen -= bytes; + return bn; +} + +/* write BIGNUM, OpenSSH v2 format (with a 4-byte byte count) */ +static int appendBigNum2( + CFMutableDataRef cfOut, + const BIGNUM *bn) +{ + if(bn == NULL) { + dprintf("appendBigNum2: NULL bn"); + return -1; + } + if (BN_is_zero(bn)) { + appendUint32(cfOut, 0); + return 0; + } + if(bn->neg) { + dprintf("appendBigNum2: negative numbers not supported\n"); + return -1; + } + int numBytes = BN_num_bytes(bn); + unsigned char buf[numBytes]; + int moved = BN_bn2bin(bn, buf); + if(moved != numBytes) { + dprintf("appendBigNum: BN_bn2bin() screwup\n"); + return -1; + } + bool appendZero = false; + if(buf[0] & 0x80) { + /* prepend leading zero to make it positive */ + appendZero = true; + numBytes++; // to encode the correct 4-byte length + } + appendUint32(cfOut, (uint32_t)numBytes); + if(appendZero) { + UInt8 z = 0; + CFDataAppendBytes(cfOut, &z, 1); + numBytes--; // to append the correct number of bytes + } + CFDataAppendBytes(cfOut, buf, numBytes); + memset(buf, 0, numBytes); + return 0; +} + +/* Write BIGNUM, OpenSSH-1 decimal (public key) version */ +static int appendBigNumDec( + CFMutableDataRef cfOut, + const BIGNUM *bn) +{ + char *buf = BN_bn2dec(bn); + if(buf == NULL) { + dprintf("appendBigNumDec: BN_bn2dec() error"); + return -1; + } + CFDataAppendBytes(cfOut, (const UInt8 *)buf, strlen(buf)); + OPENSSL_free(buf); + return 0; +} + +/* write string, OpenSSH v2 format (with a 4-byte byte count) */ +static void appendString( + CFMutableDataRef cfOut, + const char *str, + unsigned strLen) +{ + appendUint32(cfOut, (uint32_t)strLen); + CFDataAppendBytes(cfOut, (UInt8 *)str, strLen); +} + +/* skip whitespace */ +static void skipWhite( + const unsigned char *&cp, + unsigned &bytesLeft) +{ + while(bytesLeft != 0) { + if(isspace((int)(*cp))) { + cp++; + bytesLeft--; + } + else { + return; + } + } +} + +/* find next whitespace or EOF - if EOF, rtn pointer points to one past EOF */ +static const unsigned char *findNextWhite( + const unsigned char *cp, + unsigned &bytesLeft) +{ + while(bytesLeft != 0) { + if(isspace((int)(*cp))) { + return cp; + } + cp++; + bytesLeft--; + } + return cp; +} + + +/* + * Calculate d mod{p-1,q-1} + * Used when decoding OpenSSH-1 private RSA key. + */ +static int +rsa_generate_additional_parameters(RSA *rsa) +{ + BIGNUM *aux; + BN_CTX *ctx; + + if((rsa->dmq1 = BN_new()) == NULL) { + dprintf("rsa_generate_additional_parameters: BN_new failed"); + return -1; + } + if((rsa->dmp1 = BN_new()) == NULL) { + dprintf("rsa_generate_additional_parameters: BN_new failed"); + return -1; + } + if ((aux = BN_new()) == NULL) { + dprintf("rsa_generate_additional_parameters: BN_new failed"); + return -1; + } + if ((ctx = BN_CTX_new()) == NULL) { + dprintf("rsa_generate_additional_parameters: BN_CTX_new failed"); + BN_clear_free(aux); + return -1; + } + + BN_sub(aux, rsa->q, BN_value_one()); + BN_mod(rsa->dmq1, rsa->d, aux, ctx); + + BN_sub(aux, rsa->p, BN_value_one()); + BN_mod(rsa->dmp1, rsa->d, aux, ctx); + + BN_clear_free(aux); + BN_CTX_free(ctx); + return 0; +} + +#pragma mark --- OpenSSH-1 crypto --- + +static int ssh1DES3Crypt( + unsigned char cipher, + bool doEncrypt, + const unsigned char *inText, + unsigned inTextLen, + const char *password, // C string + unsigned char *outText, // data RETURNED here, caller mallocs + unsigned *outTextLen) // RETURNED +{ + switch(cipher) { + case SSH_CIPHER_3DES: + break; + case SSH_CIPHER_NONE: + /* cleartext RSA private key, e.g. host key. */ + memmove(outText, inText, inTextLen); + *outTextLen = inTextLen; + return 0; + default: + /* who knows how we're going to figure these out */ + printf("***Unsupported cipher (%u)\n", cipher); + return -1; + } + + /* key starts with MD5(password) */ + unsigned char pwdDigest[CC_MD5_DIGEST_LENGTH]; + CC_MD5(password, strlen(password), pwdDigest); + + /* three keys from that, like so: */ + unsigned char k1[kCCKeySizeDES]; + unsigned char k2[kCCKeySizeDES]; + unsigned char k3[kCCKeySizeDES]; + memmove(k1, pwdDigest, kCCKeySizeDES); + memmove(k2, pwdDigest + kCCKeySizeDES, kCCKeySizeDES); + memmove(k3, pwdDigest, kCCKeySizeDES); + + CCOperation op1_3; + CCOperation op2; + if(doEncrypt) { + op1_3 = kCCEncrypt; + op2 = kCCDecrypt; + } + else { + op1_3 = kCCDecrypt; + op2 = kCCEncrypt; + } + + /* the openssh v1 pseudo triple DES. Each DES pass has its own CBC. */ + size_t moved = 0; + + CCCryptorStatus cstat = CCCrypt(op1_3, kCCAlgorithmDES, + 0, // no padding + k1, kCCKeySizeDES, + NULL, // IV + inText, inTextLen, + outText, inTextLen, &moved); + if(cstat) { + dprintf("***ssh1DES3Crypt: CCCrypt()(1) returned %u\n", (unsigned)cstat); + return -1; + } + cstat = CCCrypt(op2, kCCAlgorithmDES, + 0, // no padding - SSH does that itself + k2, kCCKeySizeDES, + NULL, // IV + outText, moved, + outText, inTextLen, &moved); + if(cstat) { + dprintf("***ssh1DES3Crypt: CCCrypt()(2) returned %u\n", (unsigned)cstat); + return -1; + } + cstat = CCCrypt(op1_3, kCCAlgorithmDES, + 0, // no padding - SSH does that itself + k3, kCCKeySizeDES, + NULL, // IV + outText, moved, + outText, inTextLen, &moved); + if(cstat) { + dprintf("***ssh1DES3Crypt: CCCrypt()(3) returned %u\n", (unsigned)cstat); + return -1; + } + + *outTextLen = moved; + return 0; +} + +#pragma mark --- OpenSSH-1 decode --- + +/* Decode OpenSSH-1 RSA private key */ +static int decodeSSH1RSAPrivKey( + const unsigned char *key, + unsigned keyLen, + char *password, + RSA *rsa, // returned + char **comment) // returned +{ + const unsigned char *cp = key; // running pointer + unsigned remLen = keyLen; + unsigned len = strlen(authfile_id_string); + + /* length: ID string, NULL, Cipher, 4-byte spare */ + if(remLen < (len + 6)) { + dprintf("decodeSSH1RSAPrivKey: short record(1)\n"); + return -1; + } + + /* ID string plus a NULL */ + if(memcmp(authfile_id_string, cp, len)) { + dprintf("decodeSSH1RSAPrivKey: bad header\n"); + return -1; + } + cp += (len + 1); + remLen -= (len + 1); + + /* cipher */ + unsigned char cipherSpec = *cp; + switch(cipherSpec) { + case SSH_CIPHER_NONE: + if(password != NULL) { + dprintf("decodeSSH1RSAPrivKey: Attempt to decrypt plaintext key\n"); + return -1; + } + break; + case SSH_CIPHER_3DES: + if(password == NULL) { + dprintf("decodeSSH1RSAPrivKey: Encrypted key with no decryptKey\n"); + return -1; + } + break; + default: + /* I hope we don't see any other values here */ + dprintf("decodeOpenSSHv1PrivKey: unknown cipherSpec (%u)\n", cipherSpec); + return -1; + } + + /* skip cipher, spares */ + cp += 5; + remLen -= 5; + + /* + * Clear text public key: + * uint32 bits + * bignum n + * bignum e + */ + if(remLen < sizeof(uint32_t)) { + dprintf("decodeSSH1RSAPrivKey: bad len(1)\n"); + return -1; + } + /* skip over keybits */ + readUint32(cp, remLen); + rsa->n = readBigNum(cp, remLen); + if(rsa->n == NULL) { + dprintf("decodeSSH1RSAPrivKey: error decoding n\n"); + return -1; + } + rsa->e = readBigNum(cp, remLen); + if(rsa->e == NULL) { + dprintf("decodeSSH1RSAPrivKey: error decoding e\n"); + return -1; + } + + /* comment string: 4-byte length and the string w/o NULL */ + if(remLen < sizeof(uint32_t)) { + dprintf("decodeSSH1RSAPrivKey: bad len(2)\n"); + return -1; + } + uint32_t commentLen = readUint32(cp, remLen); + if(commentLen > remLen) { + dprintf("decodeSSH1RSAPrivKey: bad len(3)\n"); + return -1; + } + *comment = (char *)malloc(commentLen + 1); + memmove(*comment, cp, commentLen); + (*comment)[commentLen] = '\0'; + cp += commentLen; + remLen -= commentLen; + + /* everything that remains is ciphertext */ + unsigned char ptext[remLen]; + unsigned ptextLen = 0; + if(ssh1DES3Crypt(cipherSpec, false, cp, remLen, password, ptext, &ptextLen)) { + dprintf("decodeSSH1RSAPrivKey: decrypt error\n"); + return -1; + } + /* subsequent errors to errOut: */ + + int ourRtn = 0; + + /* plaintext contents: + + [0-1] -- random bytes + [2-3] -- copy of [01] for passphrase validity checking + buffer_put_bignum(d) + buffer_put_bignum(iqmp) + buffer_put_bignum(q) + buffer_put_bignum(p) + pad to block size + */ + cp = ptext; + remLen = ptextLen; + if(remLen < 4) { + dprintf("decodeSSH1RSAPrivKey: bad len(4)\n"); + ourRtn = -1; + goto errOut; + } + if((cp[0] != cp[2]) || (cp[1] != cp[3])) { + /* decrypt fail */ + dprintf("decodeSSH1RSAPrivKey: check byte error\n"); + ourRtn = -1; + goto errOut; + } + cp += 4; + remLen -= 4; + + /* remainder comprises private portion of RSA key */ + rsa->d = readBigNum(cp, remLen); + if(rsa->d == NULL) { + dprintf("decodeSSH1RSAPrivKey: error decoding d\n"); + return -1; + } + rsa->iqmp = readBigNum(cp, remLen); + if(rsa->iqmp == NULL) { + dprintf("decodeSSH1RSAPrivKey: error decoding iqmp\n"); + return -1; + } + rsa->q = readBigNum(cp, remLen); + if(rsa->q == NULL) { + dprintf("decodeSSH1RSAPrivKey: error decoding q\n"); + return -1; + } + rsa->p = readBigNum(cp, remLen); + if(rsa->p == NULL) { + dprintf("decodeSSH1RSAPrivKey: error decoding p\n"); + return -1; + } + + /* calculate d mod{p-1,q-1} */ + ourRtn = rsa_generate_additional_parameters(rsa); + +errOut: + memset(ptext, 0, ptextLen); + return ourRtn; +} + +/* Decode OpenSSH-1 RSA public key */ +static int decodeSSH1RSAPubKey( + const unsigned char *key, + unsigned keyLen, + RSA *rsa, // returned + char **comment) // returned +{ + const unsigned char *cp = key; // running pointer + unsigned remLen = keyLen; + + *comment = NULL; + skipWhite(cp, remLen); + + /* + * cp points to start of size_in_bits in ASCII decimal' we really don't care about + * this field. Find next space. + */ + cp = findNextWhite(cp, remLen); + if(remLen == 0) { + dprintf("decodeSSH1RSAPubKey: short key (1)\n"); + return -1; + } + skipWhite(cp, remLen); + if(remLen == 0) { + dprintf("decodeSSH1RSAPubKey: short key (2)\n"); + return -1; + } + + /* + * cp points to start of e + */ + const unsigned char *ep = findNextWhite(cp, remLen); + if(remLen == 0) { + dprintf("decodeSSH1RSAPubKey: short key (3)\n"); + return -1; + } + unsigned len = ep - cp; + rsa->e = parseDecimalBn(cp, len); + if(rsa->e == NULL) { + return -1; + } + cp += len; + remLen -= len; + + skipWhite(cp, remLen); + if(remLen == 0) { + dprintf("decodeSSH1RSAPubKey: short key (4)\n"); + return -1; + } + + /* cp points to start of n */ + ep = findNextWhite(cp, remLen); + len = ep - cp; + rsa->n = parseDecimalBn(cp, len); + if(rsa->n == NULL) { + return -1; + } + cp += len; + remLen -= len; + skipWhite(cp, remLen); + if(remLen == 0) { + /* no comment; we're done */ + return 0; + } + + ep = findNextWhite(cp, remLen); + len = ep - cp; + if(len == 0) { + return 0; + } + *comment = (char *)malloc(len + 1); + memmove(*comment, cp, len); + if((*comment)[len - 1] == '\n') { + /* normal case closes with a newline, not part of the comment */ + len--; + } + (*comment)[len] = '\0'; + return 0; + +} + +#pragma mark --- OpenSSH-1 encode --- + +/* Encode OpenSSH-1 RSA private key */ +static int encodeSSH1RSAPrivKey( + RSA *rsa, + const char *password, + const char *comment, + unsigned char **outKey, // mallocd and RETURNED + unsigned *outKeyLen) // RETURNED +{ + CFMutableDataRef cfOut = CFDataCreateMutable(NULL, 0); + + /* ID string including NULL */ + CFDataAppendBytes(cfOut, (const UInt8 *)authfile_id_string, strlen(authfile_id_string) + 1); + + /* one byte cipher */ + UInt8 cipherSpec = SSH_CIPHER_3DES; + CFDataAppendBytes(cfOut, &cipherSpec, 1); + + /* spares */ + UInt8 spares[4] = {0}; + CFDataAppendBytes(cfOut, spares, 4); + + /* + * Clear text public key: + * uint32 bits + * bignum n + * bignum e + */ + uint32_t keybits = RSA_size(rsa) * 8; + appendUint32(cfOut, keybits); + appendBigNum(cfOut, rsa->n); + appendBigNum(cfOut, rsa->e); + + /* comment string: 4-byte length and the string w/o NULL */ + if(comment) { + uint32_t len = strlen(comment); + appendUint32(cfOut, len); + CFDataAppendBytes(cfOut, (const UInt8 *)comment, len); + } + + /* + * Remainder is encrypted, consisting of + * + * [0-1] -- random bytes + * [2-3] -- copy of [01] for passphrase validity checking + * buffer_put_bignum(d) + * buffer_put_bignum(iqmp) + * buffer_put_bignum(q) + * buffer_put_bignum(p) + * pad to block size + */ + CFMutableDataRef ptext = CFDataCreateMutable(NULL, 0); + + /* [0..3] check bytes */ + UInt8 checkBytes[4]; + DevRandomGenerator rng = DevRandomGenerator(); + rng.random(checkBytes, 2); + checkBytes[2] = checkBytes[0]; + checkBytes[3] = checkBytes[1]; + CFDataAppendBytes(ptext, checkBytes, 4); + + /* d, iqmp, q, p */ + appendBigNum(ptext, rsa->d); + appendBigNum(ptext, rsa->iqmp); + appendBigNum(ptext, rsa->q); + appendBigNum(ptext, rsa->p); + + /* encrypt it */ + unsigned ptextLen = CFDataGetLength(ptext); + unsigned padding = 0; + unsigned rem = ptextLen & 0x7; + if(rem) { + padding = 8 - rem; + } + UInt8 padByte = 0; + for(unsigned dex=0; dex + * e, bignum in decimal + * + * n, bignum in decimal + * + * optional comment + * newline + */ + int ourRtn = 0; + unsigned numBits = BN_num_bits(rsa->n); + char bitString[20]; + UInt8 c = ' '; + + snprintf(bitString, sizeof(bitString), "%u ", numBits); + CFDataAppendBytes(cfOut, (const UInt8 *)bitString, strlen(bitString)); + if(appendBigNumDec(cfOut, rsa->e)) { + ourRtn = -1; + goto errOut; + } + CFDataAppendBytes(cfOut, &c, 1); + if(appendBigNumDec(cfOut, rsa->n)) { + ourRtn = -1; + goto errOut; + } + if(comment != NULL) { + CFDataAppendBytes(cfOut, &c, 1); + CFDataAppendBytes(cfOut, (UInt8 *)comment, strlen(comment)); + } + c = '\n'; + CFDataAppendBytes(cfOut, &c, 1); + *outKeyLen = CFDataGetLength(cfOut); + *outKey = (unsigned char *)malloc(*outKeyLen); + memmove(*outKey, CFDataGetBytePtr(cfOut), *outKeyLen); +errOut: + CFRelease(cfOut); + return ourRtn; +} + +#pragma mark --- OpenSSH-2 public key decode --- + +/* + * Decode components from an SSHv2 public key. + * Also verifies the leading header, e.g. "ssh-rsa". + * The returned decodedBlob is algorithm-specific. + */ +static int parseSSH2PubKey( + const unsigned char *key, + unsigned keyLen, + const char *header, // SSH2_RSA_HEADER, SSH2_DSA_HEADER + unsigned char **decodedBlob, // mallocd and RETURNED + unsigned *decodedBlobLen, // RETURNED + char **comment) // optionally mallocd and RETURNED, NULL terminated +{ + unsigned len = strlen(header); + const unsigned char *endOfKey = key + keyLen; + *decodedBlob = NULL; + *comment = NULL; + + /* ID string plus at least one space */ + if(keyLen < (len + 1)) { + dprintf("parseSSH2PubKey: short record(1)\n"); + return -1; + } + + if(memcmp(header, key, len)) { + dprintf("parseSSH2PubKey: bad header (1)\n"); + return -1; + } + key += len; + if(*key++ != ' ') { + dprintf("parseSSH2PubKey: bad header (2)\n"); + return -1; + } + keyLen -= (len + 1); + + /* key points to first whitespace after header */ + skipWhite(key, keyLen); + if(keyLen == 0) { + dprintf("parseSSH2PubKey: short key\n"); + return -1; + } + + /* key is start of base64 blob */ + const unsigned char *encodedBlob = key; + const unsigned char *endBlob = findNextWhite(key, keyLen); + unsigned encodedBlobLen = endBlob - encodedBlob; + + /* decode base 64 */ + *decodedBlob = cuDec64(encodedBlob, encodedBlobLen, decodedBlobLen); + if(*decodedBlob == NULL) { + dprintf("parseSSH2PubKey: base64 decode error\n"); + return -1; + } + + /* skip over the encoded blob and possible whitespace after it */ + key = endBlob; + keyLen = endOfKey - endBlob; + skipWhite(key, keyLen); + if(keyLen == 0) { + /* nothing remains, no comment, no error */ + return 0; + } + + /* optional comment */ + *comment = (char *)malloc(keyLen + 1); + memmove(*comment, key, keyLen); + if((*comment)[keyLen - 1] == '\n') { + /* normal case closes with a newline, not part of the comment */ + keyLen--; + } + (*comment)[keyLen] = '\0'; + return 0; +} + +static int decodeSSH2RSAPubKey( + const unsigned char *key, + unsigned keyLen, + RSA *rsa, // returned + char **comment) // returned +{ + /* + * Verify header + * get base64-decoded blob plus optional comment + */ + unsigned char *decodedBlob = NULL; + unsigned decodedBlobLen = 0; + if(parseSSH2PubKey(key, keyLen, SSH2_RSA_HEADER, &decodedBlob, &decodedBlobLen, comment)) { + return -1; + } + /* subsequent errors to errOut: */ + + /* + * The inner base64-decoded blob, consisting of + * ssh-rsa + * e + * n + */ + uint32_t decLen; + unsigned len; + int ourRtn = 0; + + key = decodedBlob; + keyLen = decodedBlobLen; + if(keyLen < 12) { + /* three length fields at least */ + dprintf("decodeSSH2RSAPubKey: short record(2)\n"); + ourRtn = -1; + goto errOut; + } + decLen = readUint32(key, keyLen); + len = strlen(SSH2_RSA_HEADER); + if(decLen != len) { + dprintf("decodeSSH2RSAPubKey: bad header (2)\n"); + ourRtn = -1; + goto errOut; + } + if(memcmp(SSH2_RSA_HEADER, key, len)) { + dprintf("decodeSSH2RSAPubKey: bad header (1)\n"); + return -1; + } + key += len; + keyLen -= len; + + rsa->e = readBigNum2(key, keyLen); + if(rsa->e == NULL) { + ourRtn = -1; + goto errOut; + } + rsa->n = readBigNum2(key, keyLen); + if(rsa->n == NULL) { + ourRtn = -1; + goto errOut; + } + +errOut: + free(decodedBlob); + return ourRtn; +} + +static int decodeSSH2DSAPubKey( + const unsigned char *key, + unsigned keyLen, + DSA *dsa, // returned + char **comment) // returned +{ + /* + * Verify header + * get base64-decoded blob plus optional comment + */ + unsigned char *decodedBlob = NULL; + unsigned decodedBlobLen = 0; + if(parseSSH2PubKey(key, keyLen, SSH2_DSA_HEADER, &decodedBlob, &decodedBlobLen, comment)) { + return -1; + } + /* subsequent errors to errOut: */ + + /* + * The inner base64-decoded blob, consisting of + * ssh-dss + * p + * q + * g + * pub_key + */ + uint32_t decLen; + int ourRtn = 0; + unsigned len; + + key = decodedBlob; + keyLen = decodedBlobLen; + if(keyLen < 20) { + /* five length fields at least */ + dprintf("decodeSSH2DSAPubKey: short record(2)\n"); + ourRtn = -1; + goto errOut; + } + decLen = readUint32(key, keyLen); + len = strlen(SSH2_DSA_HEADER); + if(decLen != len) { + dprintf("decodeSSH2DSAPubKey: bad header (2)\n"); + ourRtn = -1; + goto errOut; + } + if(memcmp(SSH2_DSA_HEADER, key, len)) { + dprintf("decodeSSH2DSAPubKey: bad header (1)\n"); + return -1; + } + key += len; + keyLen -= len; + + dsa->p = readBigNum2(key, keyLen); + if(dsa->p == NULL) { + ourRtn = -1; + goto errOut; + } + dsa->q = readBigNum2(key, keyLen); + if(dsa->q == NULL) { + ourRtn = -1; + goto errOut; + } + dsa->g = readBigNum2(key, keyLen); + if(dsa->g == NULL) { + ourRtn = -1; + goto errOut; + } + dsa->pub_key = readBigNum2(key, keyLen); + if(dsa->pub_key == NULL) { + ourRtn = -1; + goto errOut; + } + +errOut: + free(decodedBlob); + return ourRtn; +} + +#pragma mark --- OpenSSH-2 public key encode --- + +static int encodeSSH2RSAPubKey( + RSA *rsa, + const char *comment, + unsigned char **outKey, // mallocd and RETURNED + unsigned *outKeyLen) // RETURNED +{ + unsigned char *b64 = NULL; + unsigned b64Len; + UInt8 c; + + /* + * First, the inner base64-encoded blob, consisting of + * ssh-rsa + * e + * n + */ + CFMutableDataRef cfOut = CFDataCreateMutable(NULL, 0); + int ourRtn = 0; + appendString(cfOut, SSH2_RSA_HEADER, strlen(SSH2_RSA_HEADER)); + ourRtn = appendBigNum2(cfOut, rsa->e); + if(ourRtn) { + goto errOut; + } + ourRtn = appendBigNum2(cfOut, rsa->n); + if(ourRtn) { + goto errOut; + } + + /* base64 encode that */ + b64 = cuEnc64((unsigned char *)CFDataGetBytePtr(cfOut), CFDataGetLength(cfOut), &b64Len); + + /* cuEnc64 added newline and NULL, which we really don't want */ + b64Len -= 2; + + /* Now start over, dropping that base64 into a public blob. */ + CFDataSetLength(cfOut, 0); + CFDataAppendBytes(cfOut, (UInt8 *)SSH2_RSA_HEADER, strlen(SSH2_RSA_HEADER)); + c = ' '; + CFDataAppendBytes(cfOut, &c, 1); + CFDataAppendBytes(cfOut, b64, b64Len); + + /* optional comment */ + if(comment) { + CFDataAppendBytes(cfOut, &c, 1); + CFDataAppendBytes(cfOut, (UInt8 *)comment, strlen(comment)); + } + + /* finish it with a newline */ + c = '\n'; + CFDataAppendBytes(cfOut, &c, 1); + + *outKeyLen = (unsigned)CFDataGetLength(cfOut); + *outKey = (unsigned char *)malloc(*outKeyLen); + memmove(*outKey, CFDataGetBytePtr(cfOut), *outKeyLen); + +errOut: + CFRelease(cfOut); + if(b64) { + free(b64); + } + return ourRtn; +} + +static int encodeSSH2DSAPubKey( + DSA *dsa, + const char *comment, + unsigned char **outKey, // mallocd and RETURNED + unsigned *outKeyLen) // RETURNED +{ + unsigned char *b64 = NULL; + unsigned b64Len; + UInt8 c; + + /* + * First, the inner base64-encoded blob, consisting of + * ssh-dss + * p + * q + * g + * pub_key + */ + CFMutableDataRef cfOut = CFDataCreateMutable(NULL, 0); + int ourRtn = 0; + appendString(cfOut, SSH2_DSA_HEADER, strlen(SSH2_DSA_HEADER)); + ourRtn = appendBigNum2(cfOut, dsa->p); + if(ourRtn) { + goto errOut; + } + ourRtn = appendBigNum2(cfOut, dsa->q); + if(ourRtn) { + goto errOut; + } + ourRtn = appendBigNum2(cfOut, dsa->g); + if(ourRtn) { + goto errOut; + } + ourRtn = appendBigNum2(cfOut, dsa->pub_key); + if(ourRtn) { + goto errOut; + } + + /* base64 encode that */ + b64 = cuEnc64((unsigned char *)CFDataGetBytePtr(cfOut), CFDataGetLength(cfOut), &b64Len); + + /* cuEnc64 added newline and NULL, which we really don't want */ + b64Len -= 2; + + /* Now start over, dropping that base64 into a public blob. */ + CFDataSetLength(cfOut, 0); + CFDataAppendBytes(cfOut, (UInt8 *)SSH2_DSA_HEADER, strlen(SSH2_DSA_HEADER)); + c = ' '; + CFDataAppendBytes(cfOut, &c, 1); + CFDataAppendBytes(cfOut, b64, b64Len); + + /* optional comment */ + if(comment) { + CFDataAppendBytes(cfOut, &c, 1); + CFDataAppendBytes(cfOut, (UInt8 *)comment, strlen(comment)); + } + + /* finish it with a newline */ + c = '\n'; + CFDataAppendBytes(cfOut, &c, 1); + + *outKeyLen = (unsigned)CFDataGetLength(cfOut); + *outKey = (unsigned char *)malloc(*outKeyLen); + memmove(*outKey, CFDataGetBytePtr(cfOut), *outKeyLen); + +errOut: + CFRelease(cfOut); + if(b64) { + free(b64); + } + return ourRtn; +} + + +#pragma mark --- print RSA/DSA keys --- + +static void printBNLong( + BN_ULONG bnl) +{ + /* for now assume it's 32 bits */ + unsigned i = bnl >> 24; + printf("%02X ", i); + i = (bnl >> 16) & 0xff; + printf("%02X ", i); + i = (bnl >> 8) & 0xff; + printf("%02X ", i); + i = bnl & 0xff; + printf("%02X ", i); +} + +static void printBN( + const char *label, + BIGNUM *bn) +{ + printf("%s: %d bits: bn->top %d: ", label, BN_num_bits(bn), bn->top); + for(int dex=bn->top-1; dex>=0; dex--) { + printBNLong(bn->d[dex]); + } + printf("\n"); +} +static void printRSA( + RSA *rsa) +{ + if(rsa->n) { + printBN(" n", rsa->n); + } + if(rsa->e) { + printBN(" e", rsa->e); + } + if(rsa->d) { + printBN(" d", rsa->d); + } + if(rsa->p) { + printBN(" p", rsa->p); + } + if(rsa->q) { + printBN(" q", rsa->q); + } + if(rsa->dmp1) { + printBN("dmp1", rsa->dmp1); + } + if(rsa->dmq1) { + printBN("dmq1", rsa->dmq1); + } + if(rsa->iqmp) { + printBN("iqmp", rsa->iqmp); + } +} + +/* only public keys here */ +static void printDSA( + DSA *dsa) +{ + if(dsa->p) { + printBN(" p", dsa->p); + } + if(dsa->q) { + printBN(" q", dsa->q); + } + if(dsa->g) { + printBN(" g", dsa->g); + } + if(dsa->pub_key) { + printBN(" pub", dsa->pub_key); + } +} + +/* parse format string, returns nonzero on error */ +static int parseFormat( + const char *formatStr, + bool *isSSH1) +{ + if(!strcmp(formatStr, "ssh1")) { + *isSSH1 = true; + return 0; + } + else if(!strcmp(formatStr, "ssh2")) { + *isSSH1 = false; + return 0; + } + else { + return -1; + } +} + +#pragma mark --- main --- + +/* parse format string */ +int main(int argc, char **argv) +{ + char *inFile = NULL; + char *outFile = NULL; + bool privKeyIn = false; + bool privKeyOut = false; + char *password = NULL; + char *comment = NULL; + bool doPrint = false; + bool isDSA = false; + bool inputSSH1 = false; + bool outputSSH1 = false; + bool clearPrivKeys = false; + + int ourRtn = 0; + + extern char *optarg; + int arg; + while ((arg = getopt(argc, argv, "i:o:vVdrf:F:p:Pc:h")) != -1) { + switch (arg) { + case 'i': + inFile = optarg; + break; + case 'o': + outFile = optarg; + break; + case 'v': + privKeyIn = true; + break; + case 'V': + privKeyOut = true; + break; + case 'd': + isDSA = true; + break; + case 'r': + doPrint = true; + break; + case 'f': + if(parseFormat(optarg, &inputSSH1)) { + usage(argv); + } + break; + case 'F': + if(parseFormat(optarg, &outputSSH1)) { + usage(argv); + } + break; + case 'p': + password = optarg; + break; + case 'P': + clearPrivKeys = true; + break; + case 'c': + comment = optarg; + break; + case 'h': + default: + usage(argv); + } + } + + if(inFile == NULL) { + printf("***You must specify an input file.\n"); + usage(argv); + } + if((privKeyIn && !inputSSH1) || (privKeyOut && !outputSSH1)) { + printf("***Private keys in SSH2 format are handled elsewhere - Wrapped OpenSSL.\n"); + exit(1); + } + if((privKeyIn || privKeyOut) && (password == NULL) & !clearPrivKeys) { + printf("***Private key handling requires a password or the -P option.\n"); + usage(argv); + } + unsigned char *inKey = NULL; + unsigned inKeyLen = 0; + if(readFile(inFile, &inKey, &inKeyLen)) { + printf("Error reading %s. Aborting.\n", inFile); + exit(1); + } + + RSA *rsa = NULL; + DSA *dsa = NULL; + + /* parse incoming key */ + if(isDSA) { + if(inputSSH1) { + printf("***SSHv1 did not support DSA keys.\n"); + exit(1); + } + /* already verified that this is not SSH2 & priv (Wrapped OpenSSL) */ + dsa = DSA_new(); + if(decodeSSH2DSAPubKey(inKey, inKeyLen, dsa, &comment)) { + printf("***Error decoding SSH2 DSA public key.\n"); + exit(1); + } + } + else { + rsa = RSA_new(); + if(privKeyIn) { + /* already verified that this is SSH1 (SSH2 is Wrapped OpenSSL) */ + if(decodeSSH1RSAPrivKey(inKey, inKeyLen, password, rsa, &comment)) { + printf("***Error decoding SSH1 RSA Private key.\n"); + exit(1); + } + } + else { + if(inputSSH1) { + if(decodeSSH1RSAPubKey(inKey, inKeyLen, rsa, &comment)) { + printf("***Error decoding SSH1 RSA Public key.\n"); + exit(1); + } + } + else { + if(decodeSSH2RSAPubKey(inKey, inKeyLen, rsa, &comment)) { + printf("***Error decoding SSH2 RSA Public key.\n"); + exit(1); + } + } + } + } + + /* optionally display the key */ + if(doPrint) { + if(isDSA) { + printf("DSA key:\n"); + printDSA(dsa); + printf("Comment: %s\n", comment); + } + else { + printf("RSA key:\n"); + printRSA(rsa); + printf("Comment: %s\n", comment); + } + } + + /* optionally convert to (optionally different) output format */ + + if(outFile) { + unsigned char *outKey = NULL; + unsigned outKeyLen = 0; + + if(isDSA) { + if(outputSSH1 || privKeyOut) { + printf("***DSA: Only public SSHv2 keys allowed.\n"); + exit(1); + } + if(encodeSSH2DSAPubKey(dsa, comment, &outKey, &outKeyLen)) { + printf("***Error encoding DSA public key.\n"); + exit(1); + } + } + else { + if(privKeyOut) { + /* already verified that this is SSH1 (SSH2 is Wrapped OpenSSL) */ + if(encodeSSH1RSAPrivKey(rsa, password, comment, &outKey, &outKeyLen)) { + printf("***Error encoding RSA private key.\n"); + exit(1); + } + } + else { + if(outputSSH1) { + if(encodeSSH1RSAPubKey(rsa, comment, &outKey, &outKeyLen)) { + printf("***Error encoding RSA public key.\n"); + exit(1); + } + } + else { + if(encodeSSH2RSAPubKey(rsa, comment, &outKey, &outKeyLen)) { + printf("***Error encoding RSA public key.\n"); + exit(1); + } + } + } /* RSA public */ + } /* RSA */ + + if(writeFile(outFile, outKey, outKeyLen)) { + printf("***Error writing to %s.\n", outFile); + ourRtn = -1; + } + else { + printf("...wrote %u bytes to %s.\n", outKeyLen, outFile); + } + free(outKey); + } + else if(!doPrint) { + printf("...parsed a key but you didn't ask me to do anything with it.\n"); + } + if(rsa) { + RSA_free(rsa); + } + if(dsa) { + DSA_free(dsa); + } + + return 0; +} diff --git a/SecurityTests/cspxutils/ssl2Padding/Makefile b/SecurityTests/cspxutils/ssl2Padding/Makefile new file mode 100644 index 00000000..1d7b135f --- /dev/null +++ b/SecurityTests/cspxutils/ssl2Padding/Makefile @@ -0,0 +1,55 @@ +# name of executable to build +EXECUTABLE=ssl2Padding +# C++ source (with .cpp extension) +CPSOURCE= ssl2Padding.cpp +# C source (.c extension) +CSOURCE= + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +#PROJ_LDFLAGS= -lMallocDebug +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/ssl2Padding/ssl2Padding.cpp b/SecurityTests/cspxutils/ssl2Padding/ssl2Padding.cpp new file mode 100644 index 00000000..3c842a7d --- /dev/null +++ b/SecurityTests/cspxutils/ssl2Padding/ssl2Padding.cpp @@ -0,0 +1,394 @@ +/* Copyright (c) 2005-2006 Apple Computer, Inc. + * + * ssl2Padding.cpp - test CSSM_PADDING_APPLE_SSLv2. + */ + + + /* + * This table illustrates the combinations of: + * + * -- SSLv2 (v2) and SSLv3/TLSv1 (v3+) enables (0/1) on the client and server side + * -- the resulting negotiated protocols (including those forced by a man-in-the-middle + * attacker, denoted by (m)) + * -- the padding generated by the client (client pad) + * -- the padding style checked by the server (server pad) + * -- and the end results + * + * client server + * ------ ------ + * v2 v3+ v2 v3+ negotiate client pad server pad result + * -- -- -- -- --------- ---------- ---------- ------ + * 0 0 x x impossible + * x x 0 0 impossible + * 0 1 0 1 v3+ PKCS1 PKCS1 normal + * 0 1 0 1 v2 (m) Attack fails, client rejects server hello + * 0 1 1 0 fail incompatible + * 0 1 1 1 v3+ PKCS1 PKCS1 normal + * 0 1 1 1 v2 (m) Attack fails, client rejects server hello + * 1 0 0 1 fail incompatible + * 1 0 1 0 v2 PKCS1 PKCS1 normal, both sides are dumb SSL2 + * 1 0 1 0 v3+ Attack fails, server rejects client hello + * 1 0 1 1 v2 PKCS1 SSLv2 normal, dumb client + * 1 0 1 1 v3+ (m) Attack fails, client rejects server hello + * 1 1 0 1 v3+ PKCS1 PKCS1 normal + * 1 1 0 1 v2 (m) Attack fails, server rejects SSL2 handshake + * 1 1 1 0 v2 SSLv2 PKCS1 normal, dumb server + * 1 1 1 0 v3+ (m) Attack fails, server rejects SSL3 handshakes + * 1 1 1 1 v3+ PKCS1 PKCS1 normal + * 1 1 1 1 v2 (m) SSLv2 SSLv2 Attack fails due to SSLv2 pad detect + * + * The client generates SSLv2 padding if it's capable of v3+ but is currently operating + * in v2 per negotiation. + * + * The server checks for SSLv2 padding if it's capable of v3+ but is currently operating + * in v2 per negotiation. If SSLv2 padding is seen, fail. + */ + +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "cspdlTesting.h" + +#define USAGE_NAME "noUsage" +#define USAGE_NAME_LEN (strlen(USAGE_NAME)) +#define LOOPS_DEF 10 + +#define KEY_SIZE_DEF 1024 +#define KEY_SIZE_SMALL 512 + +#define PTEXT_LEN 32 /* bytes */ + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" k=keySizeInBits; default=%d\n", KEY_SIZE_DEF); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" p (pause on each loop)\n"); + printf(" u (quick; small keys)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +/* special-purpose generate-context, encrypt, and decrypt routines just for this test */ +static int genRsaCryptContext( + CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR key, + CSSM_PADDING padding, + CSSM_BOOL quiet, + CSSM_CC_HANDLE &ccHand) // RETURNED +{ + CSSM_RETURN crtn; + CSSM_ACCESS_CREDENTIALS creds; + + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + crtn = CSSM_CSP_CreateAsymmetricContext(cspHand, + CSSM_ALGID_RSA, + &creds, // access + key, + padding, + &ccHand); + if(crtn) { + cssmPerror("CSSM_CSP_CreateAsymmetricContext", crtn); + return testError(quiet); + } + return 0; +} + +static int doRsaEncrypt( + CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR key, + CSSM_PADDING padding, + CSSM_BOOL quiet, + CSSM_DATA *ptext, + CSSM_DATA *ctext) +{ + CSSM_CC_HANDLE ccHand; + int rtn; + CSSM_RETURN crtn; + CSSM_SIZE bytesMoved; + CSSM_DATA remData = {0, NULL}; + + rtn = genRsaCryptContext(cspHand, key, padding, quiet, ccHand); + if(rtn) { + return rtn; + } + crtn = CSSM_EncryptData(ccHand, + ptext, + 1, + ctext, + 1, + &bytesMoved, + &remData); + CSSM_DeleteContext(ccHand); + if(crtn == CSSM_OK) { + /* + * Deal with remData - its contents are included in bytesMoved. + */ + if(remData.Length != 0) { + /* malloc and copy a new one */ + uint8 *newCdata = (uint8 *)appMalloc(bytesMoved, NULL); + memmove(newCdata, ctext->Data, ctext->Length); + memmove(newCdata+ctext->Length, remData.Data, remData.Length); + CSSM_FREE(ctext->Data); + ctext->Data = newCdata; + } + ctext->Length = bytesMoved; + return 0; + } + else { + cssmPerror("CSSM_EncryptData", crtn); + return testError(quiet); + } +} + +static int doRsaDecrypt( + CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR key, + CSSM_PADDING padding, + CSSM_BOOL quiet, + CSSM_RETURN expectRtn, + CSSM_DATA *ctext, + CSSM_DATA *rptext) +{ + CSSM_CC_HANDLE ccHand; + int rtn; + CSSM_RETURN crtn; + CSSM_SIZE bytesMoved; + CSSM_DATA remData = {0, NULL}; + + rtn = genRsaCryptContext(cspHand, key, padding, quiet, ccHand); + if(rtn) { + return rtn; + } + crtn = CSSM_DecryptData(ccHand, + ctext, + 1, + rptext, + 1, + &bytesMoved, + &remData); + CSSM_DeleteContext(ccHand); + if(crtn != expectRtn) { + printf(" CSSM_DecryptData: expect %s\n", cssmErrToStr(expectRtn)); + printf(" CSSM_DecryptData: got %s\n", cssmErrToStr(crtn)); + return testError(quiet); + } + if(crtn) { + /* no need to process further */ + return 0; + } + if(crtn == CSSM_OK) { + /* + * Deal with remData - its contents are included in bytesMoved. + */ + if(remData.Length != 0) { + /* malloc and copy a new one */ + uint8 *newRpdata = (uint8 *)appMalloc(bytesMoved, NULL); + memmove(newRpdata, rptext->Data, rptext->Length); + memmove(newRpdata+rptext->Length, remData.Data, remData.Length); + CSSM_FREE(rptext->Data); + rptext->Data = newRpdata; + } + rptext->Length = bytesMoved; + return 0; + } + else { + cssmPerror("CSSM_DecryptData", crtn); + return testError(quiet); + } +} + +/* + * encrypt with specified pad + * decrypt with specified pad, verify expected result (which may be failure) + */ +static int doTest( + CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR pubKey, + CSSM_KEY_PTR privKey, + CSSM_PADDING encrPad, + CSSM_PADDING decrPad, + CSSM_BOOL quiet, + CSSM_RETURN expectResult) +{ + int rtn; + uint8 ptext[PTEXT_LEN]; + CSSM_DATA ptextData = {PTEXT_LEN, ptext}; + CSSM_DATA ctext = {0, NULL}; + CSSM_DATA rptext = {0, NULL}; + + simpleGenData(&ptextData, PTEXT_LEN, PTEXT_LEN); + rtn = doRsaEncrypt(cspHand, pubKey, encrPad, quiet, &ptextData, &ctext); + if(rtn) { + goto errOut; + } + rtn = doRsaDecrypt(cspHand, privKey, decrPad, quiet, expectResult, &ctext, &rptext); + if(rtn) { + goto errOut; + } + if(expectResult == CSSM_OK) { + if(memcmp(rptext.Data, ptextData.Data, PTEXT_LEN)) { + printf("***Data miscomapare after decrypt\n"); + rtn = testError(quiet); + } + } +errOut: + if(ctext.Data) { + CSSM_FREE(ctext.Data); + } + if(rptext.Data) { + CSSM_FREE(rptext.Data); + } + return rtn; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + CSSM_CSP_HANDLE cspHand; + int rtn = 0; + + /* + * User-spec'd params + */ + unsigned loops = LOOPS_DEF; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + uint32 keySizeInBits = KEY_SIZE_DEF; + CSSM_BOOL bareCsp = CSSM_TRUE; + CSSM_BOOL doPause = CSSM_FALSE; + + for(arg=1; arg +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "bsafeUtils.h" +#include "ssleayUtils.h" +#include "rijndaelApi.h" +#include +#include "cspdlTesting.h" + +/* + * Defaults. + */ +#define LOOPS_DEF 200 + +#define MIN_DATA_SIZE 8 +#define MAX_DATA_SIZE 10000 /* bytes */ +#define MAX_KEY_SIZE MAX_KEY_SIZE_RC245_BYTES /* bytes */ +#define LOOP_NOTIFY 20 + +#define RAW_MODE CSSM_ALGMODE_ECB /* doesn't work for BSAFE */ +#define RAW_MODE_BSAFE CSSM_ALGMODE_CBC_IV8 + +#define COOKED_MODE CSSM_ALGMODE_CBCPadIV8 +#define RAW_MODE_STREAM CSSM_ALGMODE_NONE + +#define RAW_MODE_STR "ECB" +#define RAW_MODE_BSAFE_STR "CBC/noPad" +#define COOKED_MODE_STR "CBC/Pad" +#define RAW_MODE_STREAM_STR "None" + +/* + * Enumerate algs our own way to allow iteration. + */ +typedef enum { + // ALG_ASC = 1, // not tested - no reference available + ALG_DES = 1, + ALG_RC2, + ALG_RC4, + ALG_RC5, + ALG_3DES, + ALG_AES, + ALG_AES192, /* 192 bit block */ + ALG_AES256, /* 256 bit block */ + ALG_BFISH, + ALG_CAST +} SymAlg; +#define ALG_FIRST ALG_DES +#define ALG_LAST ALG_CAST + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" a=algorithm (d=DES; 3=3DES3; 2=RC2; 4=RC4; 5=RC5; a=AES; A=AES192; \n"); + printf(" 6=AES256; b=Blowfish; c=CAST; default=all)\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" k=keySizeInBits\n"); + printf(" e(ncrypt only)\n"); + printf(" m=maxPtextSize (default=%d)\n", MAX_DATA_SIZE); + printf(" n=minPtextSize (default=%d)\n", MIN_DATA_SIZE); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" s (all ops single-shot, not staged)\n"); + printf(" o (raw - no padding or CBC if possible)\n"); + printf(" O (cooked - padding and CBC if possible)\n"); + printf(" z (keys and plaintext all zeroes)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" y (use ssleay EVP; AES128 only)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +/* + * encrypt/decrypt using reference BSAFE. + */ +static CSSM_RETURN encryptDecryptBSAFE( + CSSM_BOOL forEncrypt, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE encrMode, + const CSSM_DATA *iv, //Êoptional per mode + uint32 keySizeInBits, + uint32 effectiveKeyBits, // optional per key alg + uint32 rounds, // ditto + const CSSM_DATA *key, // raw key bytes + const CSSM_DATA *inText, + CSSM_DATA_PTR outText) // mallocd and returned +{ + CSSM_RETURN crtn; + BU_KEY buKey; + + crtn = buGenSymKey(keySizeInBits, key, &buKey); + if(crtn) { + return crtn; + } + crtn = buEncryptDecrypt(buKey, + forEncrypt, // forEncrypt + encrAlg, + encrMode, + iv, + effectiveKeyBits, + rounds, + inText, + outText); + buFreeKey(buKey); + return crtn; +} + +/* + * encrypt/decrypt using reference ssleay. + */ +static CSSM_RETURN encryptDecryptEAY( + CSSM_BOOL forEncrypt, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE encrMode, + const CSSM_DATA *iv, //Êoptional per mode + uint32 keySizeInBits, + const CSSM_DATA *key, // raw key bytes, Length ignored + const CSSM_DATA *inText, + CSSM_DATA_PTR outText) // mallocd and returned +{ + CSSM_RETURN crtn; + EAY_KEY eayKey; + CSSM_DATA ckey = *key; + ckey.Length = keySizeInBits / 8; + + crtn = eayGenSymKey(encrAlg, forEncrypt, &ckey, &eayKey); + if(crtn) { + return crtn; + } + crtn = eayEncryptDecrypt(eayKey, + forEncrypt, + encrAlg, + encrMode, + iv, + inText, + outText); + eayFreeKey(eayKey); + return crtn; +} + +/* + * encrypt/decrypt using reference AES. + */ +static CSSM_RETURN encryptDecryptAES( + CSSM_BOOL forEncrypt, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE encrMode, + const CSSM_DATA *iv, //Êoptional per mode + uint32 keySizeInBits, + uint32 effectiveKeyBits, // optional per key alg + uint32 cipherBlockSize, + uint32 rounds, // ditto + const CSSM_DATA *key, // raw key bytes + const CSSM_DATA *inText, + CSSM_DATA_PTR outText) // mallocd and returned +{ + keyInstance aesKey; + cipherInstance aesCipher; + BYTE mode; + int artn; + BYTE *ivPtr; + + if(cipherBlockSize == 0) { + cipherBlockSize = MIN_AES_BLOCK_BITS; + } + switch(encrMode) { + case CSSM_ALGMODE_CBC_IV8: + mode = MODE_CBC; + ivPtr = iv->Data; + break; + case CSSM_ALGMODE_ECB: + mode = MODE_ECB; + ivPtr = NULL; + break; + default: + printf("***AES reference implementation doesn't do padding (yet)\n"); + return CSSM_OK; + } + /* fixme - adjust for padding if necessary */ + outText->Data = (uint8 *)CSSM_MALLOC(inText->Length); + outText->Length = inText->Length; + artn = _makeKey(&aesKey, + forEncrypt ? DIR_ENCRYPT : DIR_DECRYPT, + keySizeInBits, + cipherBlockSize, + key->Data); + if(artn <= 0) { + printf("***AES makeKey returned %d\n", artn); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + artn = _cipherInit(&aesCipher, + mode, + cipherBlockSize, + ivPtr); + if(artn <= 0) { + printf("***AES cipherInit returned %d\n", artn); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + if(forEncrypt) { + artn = _blockEncrypt(&aesCipher, + &aesKey, + (BYTE *)inText->Data, + inText->Length * 8, + (BYTE *)outText->Data); + } + else { + artn = _blockDecrypt(&aesCipher, + &aesKey, + (BYTE *)inText->Data, + inText->Length * 8, + (BYTE *)outText->Data); + } + if(artn <= 0) { + printf("***AES encrypt/decrypt returned %d\n", artn); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + return CSSM_OK; +} + +/* + * Encrypt/decrypt, one-shot, using one of the various reference implementations. + */ +static CSSM_RETURN encryptDecryptRef( + CSSM_BOOL forEncrypt, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE encrMode, + const CSSM_DATA *iv, // optional per mode + uint32 keySizeInBits, + uint32 effectiveKeyBits, // optional per key alg + uint32 cipherBlockSize, + uint32 rounds, // ditto + CSSM_BOOL useEvp, // AES only + const CSSM_DATA *key, // raw key bytes + const CSSM_DATA *inText, + CSSM_DATA_PTR outText) // mallocd and returned +{ + switch(encrAlg) { + case CSSM_ALGID_AES: + if(useEvp && (cipherBlockSize == 128)) { + return (CSSM_RETURN)evpEncryptDecrypt(encrAlg, forEncrypt, + key, keySizeInBits, encrMode, iv, inText, outText); + } + else { + return encryptDecryptAES( + forEncrypt, + encrAlg, + encrMode, + iv, + keySizeInBits, + effectiveKeyBits, + cipherBlockSize, + rounds, + key, + inText, + outText); + } + case CSSM_ALGID_BLOWFISH: + case CSSM_ALGID_CAST: + return encryptDecryptEAY( + forEncrypt, + encrAlg, + encrMode, + iv, + keySizeInBits, + key, + inText, + outText); + default: + if(useEvp && (encrAlg == CSSM_ALGID_DES)) { + return (CSSM_RETURN)evpEncryptDecrypt(encrAlg, forEncrypt, + key, keySizeInBits, encrMode, iv, inText, outText); + } + else { + return encryptDecryptBSAFE( + forEncrypt, + encrAlg, + encrMode, + iv, + keySizeInBits, + effectiveKeyBits, + rounds, + key, + inText, + outText); + } + } +} + +/* + * encrypt/decrypt using CSSM. + */ +static CSSM_RETURN encryptDecryptCSSM( + CSSM_CSP_HANDLE cspHand, + CSSM_BOOL forEncrypt, + CSSM_ALGORITHMS keyAlg, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE encrMode, + CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc. + + CSSM_BOOL multiUpdates, // false:single update, true:multi updates + const CSSM_DATA *iv, //Êoptional per mode + uint32 keySizeInBits, + uint32 effectiveKeyBits, // optional per key alg + uint32 cipherBlockSize, + uint32 rounds, // ditto + const CSSM_DATA *key, // raw key bytes + const CSSM_DATA *inText, + CSSM_BOOL genRaw, // first generate raw key (CSPDL) + CSSM_DATA_PTR outText) // mallocd and returned +{ + CSSM_KEY_PTR symKey; // mallocd by cspGenSymKey or a ptr + // to refKey + CSSM_KEY refKey; // in case of genRaw + CSSM_BOOL refKeyGenerated = CSSM_FALSE; + unsigned keyBytes = (keySizeInBits + 7) / 8; + CSSM_RETURN crtn; + + if(genRaw) { + crtn = cspGenSymKeyWithBits(cspHand, + keyAlg, + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + key, + keyBytes, + &refKey); + if(crtn) { + return crtn; + } + symKey = &refKey; + refKeyGenerated = CSSM_TRUE; + } + else { + /* cook up a raw symmetric key */ + symKey = cspGenSymKey(cspHand, + keyAlg, + "noLabel", + 8, + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + keySizeInBits, + CSSM_FALSE); // ref key + if(symKey == NULL) { + return CSSM_ERRCODE_INTERNAL_ERROR; + } + if(symKey->KeyData.Length != keyBytes) { + printf("***Generated key size error (exp %d, got %lu)\n", + keyBytes, symKey->KeyData.Length); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + memmove(symKey->KeyData.Data, key->Data, keyBytes); + } + outText->Data = NULL; + outText->Length = 0; + + if(keySizeInBits == effectiveKeyBits) { + effectiveKeyBits = 0; + } + + /* go for it */ + if(forEncrypt) { + crtn = cspStagedEncrypt(cspHand, + encrAlg, + encrMode, + padding, + symKey, + NULL, // no second key + effectiveKeyBits, + cipherBlockSize / 8, + rounds, + iv, + inText, + outText, + multiUpdates); + } + else { + crtn = cspStagedDecrypt(cspHand, + encrAlg, + encrMode, + padding, + symKey, + NULL, // no second key + effectiveKeyBits, + cipherBlockSize / 8, + rounds, + iv, + inText, + outText, + multiUpdates); + } + cspFreeKey(cspHand, symKey); + if(!refKeyGenerated) { + /* key itself mallocd by cspGenSymKey */ + CSSM_FREE(symKey); + } + return crtn; +} + +#define LOG_FREQ 20 + +static int doTest(CSSM_CSP_HANDLE cspHand, + const CSSM_DATA *ptext, + const CSSM_DATA *keyData, + const CSSM_DATA *iv, + uint32 keyAlg, // CSSM_ALGID_xxx of the key + uint32 encrAlg, // encrypt/decrypt + uint32 encrMode, + uint32 padding, + uint32 keySizeInBits, + uint32 efectiveKeySizeInBits, + uint32 cipherBlockSize, + CSSM_BOOL useEvp, // AES only + CSSM_BOOL stagedEncr, + CSSM_BOOL stagedDecr, + CSSM_BOOL quiet, + CSSM_BOOL encryptOnly, + CSSM_BOOL genRaw) // first generate raw key (CSPDL) +{ + CSSM_DATA ctextRef = {0, NULL}; // ciphertext, reference + CSSM_DATA ctextTest = {0, NULL}; // ciphertext, test + CSSM_DATA rptext = {0, NULL}; // recovered plaintext + int rtn = 0; + CSSM_RETURN crtn; + uint32 rounds = 0; + + if(encrAlg == CSSM_ALGID_RC5) { + /* roll the dice, pick one of three values for rounds */ + unsigned die = genRand(1,3); + switch(die) { + case 1: + rounds = 8; + break; + case 2: + rounds = 12; + break; + case 3: + rounds = 16; + break; + } + } + + /* + * encrypt with each method; + * verify ciphertexts compare; + * decrypt with test code; + * verify recovered plaintext and incoming plaintext compare; + */ + crtn = encryptDecryptRef(CSSM_TRUE, + encrAlg, + encrMode, + iv, + keySizeInBits, + efectiveKeySizeInBits, + cipherBlockSize, + rounds, + useEvp, + keyData, + ptext, + &ctextRef); + if(crtn) { + return testError(quiet); + } + crtn = encryptDecryptCSSM(cspHand, + CSSM_TRUE, + keyAlg, + encrAlg, + encrMode, + padding, + stagedEncr, + iv, + keySizeInBits, + efectiveKeySizeInBits, + cipherBlockSize, + rounds, + keyData, + ptext, + genRaw, + &ctextTest); + if(crtn) { + return testError(quiet); + } + + /* ensure both methods resulted in same ciphertext */ + if(ctextRef.Length != ctextTest.Length) { + printf("Ctext length mismatch (1)\n"); + rtn = testError(quiet); + if(rtn) { + goto abort; + } + } + if(memcmp(ctextRef.Data, ctextTest.Data, ctextTest.Length)) { + printf("Ctext miscompare\n"); + rtn = testError(quiet); + if(rtn) { + goto abort; + } + } + + if(encryptOnly) { + rtn = 0; + goto abort; + } + + /* decrypt with the test method */ + crtn = encryptDecryptCSSM(cspHand, + CSSM_FALSE, + keyAlg, + encrAlg, + encrMode, + padding, + stagedDecr, + iv, + keySizeInBits, + efectiveKeySizeInBits, + cipherBlockSize, + rounds, + keyData, + &ctextTest, + genRaw, + &rptext); + if(crtn) { + return testError(quiet); + } + if(rptext.Length != ptext->Length) { + printf("ptext length mismatch (1)\n"); + rtn = testError(quiet); + if(rtn) { + goto abort; + } + } + if(memcmp(rptext.Data, ptext->Data, ptext->Length)) { + printf("ptext miscompare\n"); + rtn = testError(quiet); + } + else { + rtn = 0; + } +abort: + if(ctextTest.Length) { + CSSM_FREE(ctextTest.Data); + } + if(ctextRef.Length) { + CSSM_FREE(ctextRef.Data); + } + if(rptext.Length) { + CSSM_FREE(rptext.Data); + } + return rtn; +} + + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + CSSM_DATA ptext; + CSSM_CSP_HANDLE cspHand; + CSSM_BOOL stagedEncr; + CSSM_BOOL stagedDecr; + const char *algStr; + uint32 keyAlg; // CSSM_ALGID_xxx of the key + uint32 encrAlg; // CSSM_ALGID_xxx of encr/decr + int i; + unsigned currAlg; // ALG_xxx + uint32 actKeySizeInBits; + uint32 effectKeySizeInBits; + int rtn = 0; + CSSM_DATA keyData; + CSSM_DATA initVector; + CSSM_BOOL genRaw = CSSM_FALSE; // first generate raw key (CSPDL) + uint32 minTextSize; + uint32 rawMode; + uint32 cookedMode; + const char *rawModeStr; + const char *cookedModeStr; + uint32 algBlockSize; + + /* + * User-spec'd params + */ + CSSM_BOOL keySizeSpec = CSSM_FALSE; // false: use rand key size + unsigned minAlg = ALG_FIRST; + unsigned maxAlg = ALG_LAST; + unsigned loops = LOOPS_DEF; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + unsigned pauseInterval = 0; + uint32 padding; + CSSM_BOOL bareCsp = CSSM_TRUE; + CSSM_BOOL encryptOnly = CSSM_FALSE; + unsigned maxPtextSize = MAX_DATA_SIZE; + unsigned minPtextSize = MIN_DATA_SIZE; + CSSM_BOOL oneShotOnly = CSSM_FALSE; + CSSM_BOOL allZeroes = CSSM_FALSE; + CSSM_BOOL rawCookedSpecd = CSSM_FALSE; // when true, use allRaw only + CSSM_BOOL allRaw = CSSM_FALSE; + CSSM_BOOL useEvp = CSSM_FALSE; + + for(arg=1; arg +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "cspdlTesting.h" + +/* we need to know a little bit about AES for this test.... */ +#define AES_BLOCK_SIZE 16 /* bytes */ + +/* + * Defaults. + */ +#define LOOPS_DEF 10 +#define MIN_PTEXT_SIZE AES_BLOCK_SIZE /* for non-padding tests */ +#define MAX_PTEXT_SIZE 1000 +#define MAX_IV_SIZE AES_BLOCK_SIZE + +/* + * Enumerate algs our own way to allow iteration. + */ +typedef unsigned privAlg; +enum { + pka_ASC, + pka_RC4, + pka_DES, + pka_RC2, + pka_RC5, + pka_3DES, + pka_AES +}; + +/* + * Ditto for modes. ALGMODE_NONE not iterated, it's a special case for + * RC4 and ASC. + */ +typedef unsigned privMode; +enum { + pma_CBC_PadIV8, + pma_CBC_IV8, // no pad - requires well-aligned ptext + pma_ECB, // no IV, no pad - requires well-aligned ptext +}; + +#define ENCR_ALG_FIRST pka_ASC +#define ENCR_ALG_LAST pka_AES + +#define ENCR_MODE_FIRST pma_CBC_PadIV8 +#define ENCR_MODE_LAST pma_ECB + +/* + * Args passed to each test and to testCommon; these completely define + * the paramters for one encryption op. + */ +typedef struct { + CSSM_CSP_HANDLE cspHand; + CSSM_ALGORITHMS keyAlg; + CSSM_ALGORITHMS encrAlg; + uint32 keySizeInBits; + uint32 effectiveKeySizeInBits; // 0 means not used + uint32 rounds; // ditto + const char *keyAlgStr; + CSSM_ENCRYPT_MODE encrMode; + const char *encrModeStr; + CSSM_PADDING encrPad; + CSSM_DATA_PTR ptext; + CSSM_BOOL useInitVector; // encrypt needs an IV + CSSM_BOOL useRefKey; + CSSM_DATA initVector; // Data mallocd and init in main() + CSSM_KEY_PTR key; // gen'd in main + CSSM_BOOL verbose; + CSSM_BOOL quiet; +} testArgs; + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" e(xport)\n"); + printf(" r(epeatOnly)\n"); + printf(" p(ause after each loop)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +/* + * Given a privAlg value, return various associated stuff. + */ +static void algInfo(privAlg alg, // pka_DES, etc. + CSSM_ALGORITHMS *keyAlg, // CSSM_ALGID_DES, etc. RETURNED + // key alg for key gen algs + CSSM_ALGORITHMS *encrAlg, // encrypt/decrypt alg for key + // gen algs + const char **algStr, // RETURNED + CSSM_SIZE *ivSize) // RETURNED +{ + *ivSize = 8; + switch(alg) { + case pka_DES: + *keyAlg = *encrAlg = CSSM_ALGID_DES; + *algStr = "DES"; + return; + case pka_3DES: + *keyAlg = CSSM_ALGID_3DES_3KEY; + *encrAlg = CSSM_ALGID_3DES_3KEY_EDE; + *algStr = "3DES"; + return; + case pka_RC2: + *keyAlg = *encrAlg = CSSM_ALGID_RC2; + *algStr = "RC2"; + return; + case pka_RC4: + *keyAlg = *encrAlg = CSSM_ALGID_RC4; + /* initVector false */ + *ivSize = 0; + *algStr = "RC4"; + return; + case pka_RC5: + *keyAlg = *encrAlg = CSSM_ALGID_RC5; + *algStr = "RC5"; + return; + case pka_AES: + *keyAlg = *encrAlg = CSSM_ALGID_AES; + *algStr = "AES"; + *ivSize = AES_BLOCK_SIZE; + return; + case pka_ASC: + *keyAlg = *encrAlg = CSSM_ALGID_ASC; + /* initVector false */ + *ivSize = 0; + *algStr = "ASC"; + return; + default: + printf("BRRZZZT! Update algInfo()!\n"); + testError(CSSM_TRUE); + } +} + +/* given a privMode, return related info */ +static void modeInfo( + CSSM_ALGORITHMS alg, + privMode mode, + CSSM_ENCRYPT_MODE *cdsaMode, + const char **modeStr, + CSSM_PADDING *pad, // PKCS5 or NONE + CSSM_BOOL *useInitVector) // RETURNED, for encrypt/decrypt +{ + *useInitVector = CSSM_FALSE; + + /* first deal with modeless algorithms */ + switch(alg) { + case CSSM_ALGID_RC4: + case CSSM_ALGID_ASC: + *cdsaMode = CSSM_ALGMODE_NONE; + *modeStr = "NONE"; + *pad = CSSM_PADDING_NONE; + return; + default: + break; + } + + switch(mode) { + case pma_CBC_PadIV8: + *cdsaMode = CSSM_ALGMODE_CBCPadIV8; + *modeStr = "CBCPadIV8"; + *useInitVector = CSSM_TRUE; + *pad = CSSM_PADDING_PKCS5; + return; + case pma_CBC_IV8: + *cdsaMode = CSSM_ALGMODE_CBC_IV8; + *modeStr = "CBC_IV8"; + *useInitVector = CSSM_TRUE; + *pad = CSSM_PADDING_NONE; + return; + case pma_ECB: + *cdsaMode = CSSM_ALGMODE_ECB; + *modeStr = "ECB"; + *pad = CSSM_PADDING_NONE; + return; + default: + printf("BRRZZZT! Update modeInfo()!\n"); + testError(CSSM_TRUE); + } +} + +/* + * Given alg and mode, determine alignment of ptext size. 0 means no + * alignment necessary. + */ +uint32 alignInfo( + CSSM_ALGORITHMS alg, + CSSM_ENCRYPT_MODE mode) +{ + switch(alg) { + case CSSM_ALGID_RC4: + case CSSM_ALGID_ASC: + return 0; + default: + break; + } + + switch(mode) { + case CSSM_ALGMODE_CBC_IV8: + case CSSM_ALGMODE_ECB: + if(alg == CSSM_ALGID_AES) { + return AES_BLOCK_SIZE; + } + else { + return 8; + } + default: + return 0; + } +} + +/* a handy "compare two CSSM_DATAs" ditty */ +static CSSM_BOOL compareData(const CSSM_DATA_PTR d1, + const CSSM_DATA_PTR d2) +{ + if(d1->Length != d2->Length) { + return CSSM_FALSE; + } + if(memcmp(d1->Data, d2->Data, d1->Length)) { + return CSSM_FALSE; + } + return CSSM_TRUE; +} + +/* generate random one-bit byte */ +static uint8 randBit() +{ + return 1 << genRand(0, 7); +} + +/* + * Copy a key. + */ +static void copyCssmKey( + const CSSM_KEY_PTR key1, + CSSM_KEY_PTR key2) +{ + key2->KeyHeader = key1->KeyHeader; + key2->KeyData.Data = NULL; + key2->KeyData.Length = 0; + appCopyCssmData(&key1->KeyData, &key2->KeyData); +} + +/* + * Encrypt ptext using specified parameters + */ +static int encryptCom(CSSM_CSP_HANDLE cspHand, + const char *testName, + CSSM_DATA_PTR ptext, + CSSM_KEY_PTR key, + CSSM_ALGORITHMS alg, + CSSM_ENCRYPT_MODE mode, + CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc. + CSSM_DATA_PTR iv, // may be NULL + uint32 effectiveKeySizeInBits, // may be 0 + uint32 rounds, // ditto + CSSM_DATA_PTR ctext, // RETURNED + CSSM_BOOL quiet) +{ + CSSM_CC_HANDLE cryptHand; + CSSM_RETURN crtn; + CSSM_SIZE bytesEncrypted; + CSSM_DATA remData; + int rtn; + + cryptHand = genCryptHandle(cspHand, + alg, + mode, + padding, + key, + NULL, // no 2nd key + iv, // InitVector + effectiveKeySizeInBits, + rounds); + if(cryptHand == 0) { + return testError(quiet); + } + + remData.Data = NULL; + remData.Length = 0; + crtn = CSSM_EncryptData(cryptHand, + ptext, + 1, + ctext, + 1, + &bytesEncrypted, + &remData); + + if(crtn) { + printError("CSSM_EncryptData", crtn); + rtn = testError(quiet); + goto done; + } + if(remData.Length != 0) { + ctext->Data = (uint8 *)appRealloc(ctext->Data, bytesEncrypted, NULL); + memmove(ctext->Data + ctext->Length, + remData.Data, + bytesEncrypted - ctext->Length); + appFreeCssmData(&remData, CSSM_FALSE); + } + ctext->Length = bytesEncrypted; + rtn = 0; +done: + if(CSSM_DeleteContext(cryptHand)) { + printError("CSSM_DeleteContext", 0); + rtn = 1; + } + return rtn; +} + +/* + * Common test portion + * encrypt ptext with args in targ1; + * encrypt ptext with args in targ2; + * compare 2 ctexts; expect failure; + */ +static int testCommon(const char *testName, + testArgs *targs1, + testArgs *targs2) +{ + CSSM_DATA ctext1 = {0, NULL}; + CSSM_DATA ctext2 = {0, NULL}; + + if(encryptCom(targs1->cspHand, + testName, + targs1->ptext, + targs1->key, + targs1->encrAlg, + targs1->encrMode, + targs1->encrPad, + &targs1->initVector, + targs1->effectiveKeySizeInBits, + targs1->rounds, + &ctext1, + targs1->quiet)) { + return 1; + } + if(encryptCom(targs2->cspHand, + testName, + targs2->ptext, + targs2->key, + targs2->encrAlg, + targs2->encrMode, + targs2->encrPad, + &targs2->initVector, + targs2->effectiveKeySizeInBits, + targs2->rounds, + &ctext2, + targs2->quiet)) { + return 1; + } + if(compareData(&ctext1, &ctext2)) { + printf("***%s: Unexpected Data compare!\n", testName); + return testError(targs1->quiet); + } + appFreeCssmData(&ctext1, CSSM_FALSE); + appFreeCssmData(&ctext2, CSSM_FALSE); + return 0; +} + +/** + ** inidividual tests. + **/ +#define KEY_LABEL1 "noLabel1" +#define KEY_LABEL2 "noLabel2" +#define KEY_LABEL_LEN strlen(KEY_LABEL1) +#define REPEAT_ON_ERROR 1 + +/* + * Ensure initVector alters ctext. + */ +static int initVectTest(testArgs *targs) +{ + uint32 mungeDex; + uint32 mungeBits; + testArgs mungeArgs = *targs; + CSSM_DATA mungeIV; + + if(targs->verbose) { + printf(" ...modifying init vector\n"); + } + + /* get munged copy of iv */ + mungeIV.Length = targs->initVector.Length; + mungeIV.Data = (uint8 *)CSSM_MALLOC(mungeIV.Length); + memmove(mungeIV.Data, targs->initVector.Data, mungeIV.Length); + mungeArgs.initVector = mungeIV; + mungeDex = genRand(0, mungeIV.Length - 1); + mungeBits = randBit(); + mungeIV.Data[mungeDex] ^= mungeBits; + if(testCommon("initVectTest", targs, &mungeArgs)) { + return 1; + } + appFreeCssmData(&mungeIV, CSSM_FALSE); + return 0; +} + +/* + * Ensure effectiveKeySizeInBits alters ctext. RC2 only. + */ +static int effectSizeTest(testArgs *targs) +{ + testArgs mungeArgs = *targs; + + if(targs->verbose) { + printf(" ...modifying effective key size\n"); + } + mungeArgs.effectiveKeySizeInBits -= 8; + return testCommon("effectSizeTest", targs, &mungeArgs); +} + +/* + * Ensure rounds alters ctext. RC5 only. + */ +static int roundsTest(testArgs *targs) +{ + testArgs mungeArgs = *targs; + + if(targs->verbose) { + printf(" ...modifying rounds\n"); + } + switch(targs->rounds) { + case 8: + mungeArgs.rounds = 12; + break; + case 12: + mungeArgs.rounds = 16; + break; + case 16: + mungeArgs.rounds = 8; + break; + default: + printf("***ACK! roundsTest needs work!\n"); + return 1; + } + return testCommon("roundsTest", targs, &mungeArgs); +} + + +/* + * ensure encryption algorithm alters ctext. + */ +static int encrAlgTest(testArgs *targs) +{ + testArgs mungeArgs = *targs; + CSSM_KEY mungeKey = *targs->key; + + /* come up with different encrypt alg - not all work */ + switch(targs->encrAlg) { + case CSSM_ALGID_DES: // fixed size key + case CSSM_ALGID_3DES_3KEY_EDE: + default: + return 0; + case CSSM_ALGID_RC4: // no IV + mungeArgs.encrAlg = CSSM_ALGID_ASC; + break; + case CSSM_ALGID_ASC: // no IV + mungeArgs.encrAlg = CSSM_ALGID_RC4; + break; + case CSSM_ALGID_RC2: + mungeArgs.encrAlg = CSSM_ALGID_RC5; + break; + case CSSM_ALGID_RC5: + mungeArgs.encrAlg = CSSM_ALGID_RC2; + break; + case CSSM_ALGID_AES: + mungeArgs.encrAlg = CSSM_ALGID_RC5; + mungeArgs.initVector.Length = 8; + break; + } + + /* we're assuming this is legal - a shallow copy of a key, followed by a blind + * reassignment of its algorithm... */ + mungeKey.KeyHeader.AlgorithmId = mungeArgs.encrAlg; + mungeArgs.key = &mungeKey; + + if(targs->verbose) { + printf(" ...modifying encryption alg\n"); + } + + return testCommon("encrAlgTest", targs, &mungeArgs); +} + +/* + * ensure encryption mode alters ctext. + */ +static int encrModeTest(testArgs *targs) +{ + testArgs mungeArgs = *targs; + + /* come up with different encrypt mode - not all work */ + switch(targs->encrMode) { + case CSSM_ALGMODE_NONE: // i.e., RC4, ASC + case CSSM_ALGMODE_CBCPadIV8: // others, only one which does + // padding + return 0; + case CSSM_ALGMODE_CBC_IV8: + mungeArgs.encrMode = CSSM_ALGMODE_ECB; + mungeArgs.useInitVector = CSSM_FALSE; + break; + case CSSM_ALGMODE_ECB: + mungeArgs.encrMode = CSSM_ALGMODE_CBC_IV8; + mungeArgs.useInitVector = CSSM_TRUE; + break; + default: + printf("Update encrModeTest\n"); + return 1; + } + if(targs->verbose) { + printf(" ...modifying encryption mode\n"); + } + + return testCommon("encrModeTest", targs, &mungeArgs); +} + +/* + * Ensure ptext alters ctext. + */ +static int ptextTest(testArgs *targs) +{ + uint32 mungeDex; + uint32 mungeBits; + testArgs mungeArgs = *targs; + CSSM_DATA mungePtext; + + if(targs->verbose) { + printf(" ...modifying plaintext\n"); + } + + /* get munged copy of ptext */ + mungePtext.Length = targs->ptext->Length; + mungePtext.Data = (uint8 *)CSSM_MALLOC(mungePtext.Length); + memmove(mungePtext.Data, targs->ptext->Data, mungePtext.Length); + mungeArgs.ptext = &mungePtext; + mungeDex = genRand(0, mungePtext.Length - 1); + mungeBits = randBit(); + mungePtext.Data[mungeDex] ^= mungeBits; + if(testCommon("ptextTest", targs, &mungeArgs)) { + return 1; + } + appFreeCssmData(&mungePtext, CSSM_FALSE); + return 0; +} + +/* + * Ensure key alters ctext. Requires raw key, of course. + */ +static int keyTest(testArgs *targs) +{ + uint32 mungeDex; + uint32 mungeBits; + testArgs mungeArgs = *targs; + CSSM_KEY mungeKey; + unsigned minBit; + unsigned maxByte; + + if(targs->verbose) { + printf(" ...modifying key\n"); + } + + /* get munged copy of key */ + copyCssmKey(targs->key, &mungeKey); + mungeArgs.key = &mungeKey; + + maxByte = mungeKey.KeyData.Length - 1; + if(targs->effectiveKeySizeInBits) { + /* skip MS byte - partially used */ + maxByte--; + } + mungeDex = genRand(0, maxByte); + + minBit = 0; + switch(targs->keyAlg) { + case CSSM_ALGID_DES: + case CSSM_ALGID_DESX: + case CSSM_ALGID_3DES_3KEY: + /* skip lsb - DES parity bit */ + minBit++; + break; + default: + break; + } + mungeBits = 1 << genRand(minBit, 7); + mungeKey.KeyData.Data[mungeDex] ^= mungeBits; + if(testCommon("keyTest", targs, &mungeArgs)) { + return 1; + } + appFreeCssmData(&mungeKey.KeyData, CSSM_FALSE); + return 0; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + CSSM_DATA ptext; + CSSM_DATA initVector; + testArgs targs; + privAlg encrAlg; + int rtn = 0; + privMode pmode; + uint32 origLen; + uint32 alignRequired; + CSSM_BOOL refKeys = CSSM_FALSE; + int i; + + /* + * User-spec'd params + */ + unsigned loops = LOOPS_DEF; + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL doPause = CSSM_FALSE; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL repeatOnly = CSSM_FALSE; + CSSM_BOOL bareCsp = CSSM_TRUE; + + for(arg=1; arghb{Te!}}jq2ew4VW{c0E22orzEQLQp$}? z3)0-hGLVF&aluu?(SWt17)uJ9qWx4S-Wyh}Aso5+4gqp|a8tzm1p{Z*eL7pIia-_Q zlhaHJI1Hr?9$EiG#UnyBwAeU^Kfuz|RF z5z9XXS0&GXCpKUbDN&s#Y`0yi{w|5?nw0HNLy20uEBGu~^(y3v;t)ksFq^*F`hOH* zdnXa!Bb_(aVHcx^U$w7oXi`fE!bn;fAvZsKc&7l;`EfVV8*(-~8Xp0JSc`*xwlSj{ z#5SLtq4Oldydw8b1v<;WJ(j7geqS9uPdFsB^|QUF$_rZOUr}1-(%*iQ>vFAE#AZ<5 zt?|J#(B|W_)V*e$gdy!DbN0;dvpfOXg1tkF$U|O#GDITSmM(^Rvtk`;>cyc6pm8&O WLZUFvb1hY1%-!Dt-)<_c0X&R~{)1Qm literal 0 HcmV?d00001 diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/ctext_AES192 b/SecurityTests/cspxutils/symReference/blobs/G4/ctext_AES192 new file mode 100644 index 0000000000000000000000000000000000000000..72345c05b87b6ca6803ce12a52fa7ad148dc242f GIT binary patch literal 264 zcmV+j0r&nqHgoW%j}eU?xb*`c+4m-?=TI=tHmd(ugeo&mAf5t(*4v?9;6^VIFOHuJ z(PxRC1anPC%E#%z6>pQJXy#NC z&sBB>4AnmME@)UUrhzZX;dqb0v0(te_q@ribrFb*HzXw*BMhaL3LHU??fUg)?e}m3 zJXI>@Fxyer737jdc9T?*rrh-K^HsIJ7kRIj%%H-Gh$y&;@zmEmXEHaR-U?Zm*_O$< O{cq}wx|^yQRk`|SwSc(* literal 0 HcmV?d00001 diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/ctext_AES256 b/SecurityTests/cspxutils/symReference/blobs/G4/ctext_AES256 new file mode 100644 index 0000000000000000000000000000000000000000..88ba45e72815ec46d71bbaa85b26a2b832d17c77 GIT binary patch literal 288 zcmV+*0pI>`If^|ZdEkvk4@*0y046_^!oRBMJvs5a3|z6{cHk1B(E-G(K;(r)e@@EM z2dHM0z#Q05M%A3>lJz4G>kd#UJH?Q@vo{k#egP(YVh8vW3Xq?=6SziaARCJV{9~c% zUf(&X(!<4hz8LTUEA!c`GH#2lVofjfZViGB-?512Mz6i*M-|iCL;nwfFJ?mwgL=lW=c;+ zw5WcAY!aKtM~k4S>*2k7!ni90rY- mD+6#HX2FZ)U(H&1-~qD+nTaGXF{$mQ6eN8PI)-8s83tfBHV+xnEB&uc`yzHUl()-lyDyymp3Jz7uT z>ZzACMjKO-9iN3?I?Wp4vTdF5x>-SbuW#{72hI`e=rw{Q9^LhJgHtbi<9nAb d_j>*9%bs!knA7~*yhxJm?ZY{q*REUq1pwAsl@tH~ literal 0 HcmV?d00001 diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/ctext_Blowfish b/SecurityTests/cspxutils/symReference/blobs/G4/ctext_Blowfish new file mode 100644 index 0000000000000000000000000000000000000000..328b82af876bcb3ba9feb2916ed674128a471339 GIT binary patch literal 264 zcmV+j0r&nV140mm-?uN%L#rXYmxZ~9bdCDQ72TyRW}i15+Yy#sI_eM~hyePM8!LU4 zu9+!>uzeECQCc~BC-wZ2aK;90m91c&F69LCo#7s){AMkqcVZ~Irnx~R?**6du`pec zeKs)!%2}y-adaY-GrT3Vc_p9(FBFY*Y^&5Vi#7{V3Xpa^T^c|bI{;6ZFSzNdL37+k z31^2ªGL©©[) •Éèsr@È" +s¦qŽ1$Úh8–@)ë3ï#Íî`p\+ö£v©ézQ1‡€àªN:û½÷¨ëåâQœ¯ê,іû_T íBÚZLUAšý«.`g@M ˆ¬RSL ¶ €kOýˆ.è9 +t Ûÿ':7pØS§å͕g©Žp|}(+÷Ã+bðç.<±/†ö¾±†aíÏÎ۟{`ç”d6%}kóüf#>LrDœDÑÝ:xЉ \ No newline at end of file diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/ctext_DES b/SecurityTests/cspxutils/symReference/blobs/G4/ctext_DES new file mode 100644 index 0000000000000000000000000000000000000000..ee4e21256689801ba4ae3598901317c7e7217741 GIT binary patch literal 264 zcmV+j0r&prheOK3r%r9zgdLQI8_C(~B-a*=`YJ}a)2A+ir4B)6JXsQ<6DPO=>t!93 z9oExA4uAj!Iek`2|193EQJTb3k_A!KrQzo9Up*J7b#oS;=wW)zl{ zP_VR#(`3R+CmvzTRSqeQur1-7yT6zsWXWo^-m%WGRPmJ)DHttH(3*l+PG;zj`ye^I z$`cDD&;MVTh?|28jQT8NKW}^dm%5add_2-jb>EzP!cDcIuxd%inP}w8l>b#eeqo$0 OlDzR(o_s%;F)Cn)?SzQ{ literal 0 HcmV?d00001 diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/ctext_RC4 b/SecurityTests/cspxutils/symReference/blobs/G4/ctext_RC4 new file mode 100644 index 00000000..68fc480e --- /dev/null +++ b/SecurityTests/cspxutils/symReference/blobs/G4/ctext_RC4 @@ -0,0 +1,3 @@ +dS$4X{˜ÂËùm +:2cf“8B +?|_ÃQRŪC8úT&Øô£!Qô@Òc„:%ÆN7âí|9C1šÇ*_DÊäáQ⇾j½²:õqZèÛ"€Â1â,©Áñ8 +,«8*nœ•ç6 ÷p$yÞq‹¥œ¨{B—4<9ç1øC@ÀÈ÷0¤¢Üè‚/ވý¾H@ãúL/{;[€[,X4Sºmêœb‚žçXçGš#K©µ.žè²N{ˆOó]n¾òqMÏ8†5öãjrÒA†ïsß-~”dý./œNíÒ5‹|(Še¤õæºÄ?ƒõº>}îý,ÃØç˜!ed"ß| \ No newline at end of file diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/ctext_RC5 b/SecurityTests/cspxutils/symReference/blobs/G4/ctext_RC5 new file mode 100644 index 0000000000000000000000000000000000000000..0331a835208c4fb5fa1efd1fd467a60e594b5282 GIT binary patch literal 264 zcmV+j0r&o?zB|6@+B0UdaPCUWE5t5#BWGu#5MN;%sufY{fcUoD+nwj3_}5Nzt7~|FypjFhBTZC!F{= zfP^~NKH}~+CsFK=CPWJgE0YXRQJJQT(wzH<+J#BW@wm^ejqWe`UT_HwTq3}Zjq1i= zQRt@W!sX2@m@+K^i>^O0&tsx&@JV{bwALXVC?6EOHhkyNLkU!}088p_godM6n=&d7 zu#E-CWP>}qESxY30oPqL=Vka_4=BKtaaou1n`3G}-t5mRD8lf!$+p6 O@k*BgV@IY4$8APt(}MT_ literal 0 HcmV?d00001 diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/iv_3DES b/SecurityTests/cspxutils/symReference/blobs/G4/iv_3DES new file mode 100644 index 00000000..387aad25 --- /dev/null +++ b/SecurityTests/cspxutils/symReference/blobs/G4/iv_3DES @@ -0,0 +1 @@ +\SòwŠ£5 \ No newline at end of file diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/iv_AES b/SecurityTests/cspxutils/symReference/blobs/G4/iv_AES new file mode 100644 index 00000000..826dba4c --- /dev/null +++ b/SecurityTests/cspxutils/symReference/blobs/G4/iv_AES @@ -0,0 +1 @@ +Ï»Ù[è˜áHg²æþú6 \ No newline at end of file diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/iv_AES192 b/SecurityTests/cspxutils/symReference/blobs/G4/iv_AES192 new file mode 100644 index 00000000..5f9bae54 --- /dev/null +++ b/SecurityTests/cspxutils/symReference/blobs/G4/iv_AES192 @@ -0,0 +1 @@ +£~-…ÚËÕdfJ©SŠ­¯3¯¤œ£W \ No newline at end of file diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/iv_AES256 b/SecurityTests/cspxutils/symReference/blobs/G4/iv_AES256 new file mode 100644 index 00000000..afd5ef70 --- /dev/null +++ b/SecurityTests/cspxutils/symReference/blobs/G4/iv_AES256 @@ -0,0 +1 @@ +“È)U Hü$?Ô-å$7³²wŒîS9À1çhÂïœM& \ No newline at end of file diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/iv_Blowfish b/SecurityTests/cspxutils/symReference/blobs/G4/iv_Blowfish new file mode 100644 index 00000000..e63798ae --- /dev/null +++ b/SecurityTests/cspxutils/symReference/blobs/G4/iv_Blowfish @@ -0,0 +1 @@ +ÿ§Šxº \ No newline at end of file diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/iv_CAST b/SecurityTests/cspxutils/symReference/blobs/G4/iv_CAST new file mode 100644 index 00000000..be426a14 --- /dev/null +++ b/SecurityTests/cspxutils/symReference/blobs/G4/iv_CAST @@ -0,0 +1 @@ +¾›Ýy¼À¶ \ No newline at end of file diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/iv_DES b/SecurityTests/cspxutils/symReference/blobs/G4/iv_DES new file mode 100644 index 00000000..02773e89 --- /dev/null +++ b/SecurityTests/cspxutils/symReference/blobs/G4/iv_DES @@ -0,0 +1 @@ +q&m—ïUb \ No newline at end of file diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/iv_RC2 b/SecurityTests/cspxutils/symReference/blobs/G4/iv_RC2 new file mode 100644 index 00000000..432dc174 --- /dev/null +++ b/SecurityTests/cspxutils/symReference/blobs/G4/iv_RC2 @@ -0,0 +1 @@ +/øÚT±rþI \ No newline at end of file diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/iv_RC5 b/SecurityTests/cspxutils/symReference/blobs/G4/iv_RC5 new file mode 100644 index 00000000..12de1166 --- /dev/null +++ b/SecurityTests/cspxutils/symReference/blobs/G4/iv_RC5 @@ -0,0 +1 @@ +aík'PKÑ \ No newline at end of file diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/key_3DES b/SecurityTests/cspxutils/symReference/blobs/G4/key_3DES new file mode 100644 index 0000000000000000000000000000000000000000..80364d7120aee71d3d665a8802e3d7bb60117cac GIT binary patch literal 24 gcmd5vcC0hhN8F8}}l literal 0 HcmV?d00001 diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/key_AES b/SecurityTests/cspxutils/symReference/blobs/G4/key_AES new file mode 100644 index 00000000..e89c4311 --- /dev/null +++ b/SecurityTests/cspxutils/symReference/blobs/G4/key_AES @@ -0,0 +1 @@ +ή${ã„t2›jÞè#—Ò \ No newline at end of file diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/key_AES192 b/SecurityTests/cspxutils/symReference/blobs/G4/key_AES192 new file mode 100644 index 00000000..1b51a329 --- /dev/null +++ b/SecurityTests/cspxutils/symReference/blobs/G4/key_AES192 @@ -0,0 +1 @@ +~Þ£¬Wßy ò3 á<""c€½cÖJ¸ë?Aÿ˜¬*ZIÏÞ[æ¼‡ú4ɪR 5¤ÉÖrÞG³¶b(º'H* ù¸WÆÛ¶:f“Ú脉»!}¿pªÜg«*‰AºOŠO’pº­£iÞÙÂû‘÷Ë~ý,«¸¦8IÈÅWG’ròšw'`~øÙx"ì½ýwÅMíÙÞ[çüßÇã—œžŒÚ,F  ÛTd£6&”nð.µ\ÙÃXlnjG½2!âr7id(•#ƒq/’…›B½ +8&E0¥rFši…OP¢L©åN75öM] \ No newline at end of file diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/ptext_AES b/SecurityTests/cspxutils/symReference/blobs/G4/ptext_AES new file mode 100644 index 0000000000000000000000000000000000000000..f24f578c4be91241c4ae5a2cdd1067c749f25472 GIT binary patch literal 256 zcmV+b0ssEzSO!dn7?f9&7Zhx7Fen#EobV;)zNy@qF0tQE+W!-aokxQG1ruEd>inNy z@|puFy8@WP5jX_ZLRvqDM;2`uc$asHKY)%C3GZ)Ap|vZqofM~-$%)>_1PKR|5xTUo zyx*jHs|vb|CDf(uvV-ola`7QV*33?a9vDfE@(}&1o9-P--R>fz7qG~Fo6uGGn zh#yZ&FbqAHG{1tsfksb&8OuJM*b(3Q-&|oD5r-B-?t3M#h26Zg8L`r9CHa8y-Y!>8 z#FxYN!!0AyEtknD0W#|Mm|g0EUBz9A}i_ckGq&l1h%e8!dxHs=JHX%$Pp G`u3uD(tX*jPx!7v|h4v96xl0sN4 z(b9A7(8$Nn5}AHm#&jy5J_@G?G+C$FCEqs|%?qDI;r2g2B7Z62~5TwgEqA9@jZw)5d);tprk3lbZmtD>K5pLG9l48Dr;K zL>TG&)wcD4xe@#qgrX%YUg>V`qHr2)N*=X$9kD9}0(I2;;Qm?C#{o$E4fH%TSFYU% G^K?XzqJj_r literal 0 HcmV?d00001 diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/ptext_AES256 b/SecurityTests/cspxutils/symReference/blobs/G4/ptext_AES256 new file mode 100644 index 0000000000000000000000000000000000000000..8767dc0811565bcb73cd185255ed5b12f073c9be GIT binary patch literal 256 zcmV+b0ssEWS_c*ZbU3r6uD)Mb3`EjIt*b5%R>%$*SLVLf!an+he6`TKotM29>nxB| zMx&l!fb@=i!-cVeJrzqShWpysS+$d>G64Zkr&8=oauT9ncKwBmX+mEqR?~Gg1rki$ zaPtu-R&7uE01H5PX`hi3mE7Oq^KqPu$SR{q@rXtaC+%b`3U+MON?}~_Hqxe$kmj5+ z?C{gOniDw`eF_E|H{Yg~hBh8D>fLofz~KBaY|my*vzTn}TG^RalSF|f3eDCvl})mO zj!M(X8PL1}{X(HnoB0=ziIPs#hmR(;2LL6X=+OD+KrFcZEe5&@P?=WH*w2T4{Q_8> G&?B+VM17F} literal 0 HcmV?d00001 diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/ptext_ASC b/SecurityTests/cspxutils/symReference/blobs/G4/ptext_ASC new file mode 100644 index 00000000..f968dc0d --- /dev/null +++ b/SecurityTests/cspxutils/symReference/blobs/G4/ptext_ASC @@ -0,0 +1,3 @@ +¶àèÿiÒ{±;<‡± +¾\·û9¯êõ„îjëk8%ü™o/ò°Q,å'ñ +›&62º BÖåf¡NjOW»sîAÔ¯CüU—~€í“¦ˆÒ«ë/–Ôù(î²jíVg&K÷d ®j›òЋh`ÒóJX8 \ No newline at end of file diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/ptext_CAST b/SecurityTests/cspxutils/symReference/blobs/G4/ptext_CAST new file mode 100644 index 0000000000000000000000000000000000000000..3d5757fbdca4ff7328db8fc590d2406b789cadb1 GIT binary patch literal 256 zcmV+b0ssCHXcv+)sGDJorF=MSgCvOVe?rNV_0@{=`bSi0a6}<{7chPn>aU z`79tiotokK8?EiW@B-(bNAEVN4I@WX;h=GePUpL`?dAm*O`j&8{+&lsVlKP7p(D%> zcUdU19RAjO_~nAtR2jEJ2{sT zg}5d&4w}*xPvIWmVI5l?EMe^=!OPKn_(U`ab^~3MSCfeS=2tSi0JB;#Jj)-}{z>)8 zUWlmzL(ueZIh!yv6rhoEofBE)4!Rw@KqWBf{G1rjz7NCzD33WXK~=_qDtW*3P1^g< zE3U+~(^~lmd7319cTS6m1H;+sRFFDdd#A_FR-~k6BuiekB*JRLUzQ4sG&P~seSKGs zz(?R`Qsd6OW=PxI Gt#wedh_Tk9F@{@p2|Yejm?nfGugNCPN(yLwGzI-rH}e6 GYxP9p!H0kV literal 0 HcmV?d00001 diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/ptext_RC4 b/SecurityTests/cspxutils/symReference/blobs/G4/ptext_RC4 new file mode 100644 index 0000000000000000000000000000000000000000..8745f0969a6706ebb7d41d94a63acdf164790d06 GIT binary patch literal 256 zcmV+b0ssCr*2`fn;e$2^nc-K}yhpN0=m7VE)|yHPQ=3fdd*}5MQxU0E&I{KRMMcgq zOwdZb#ZLfT0t{!O40ncC6#9{$VSUwckg{Z>N*0wCnL5Ze?L94d!1E4zH7+^ez*$L_J%@8m+LrJo?iv` zTem}BFe)(qnqO37jbLsa6w)w3Lb6ipdc%RcL?9~>dw^%OGxqs3dQtEtP}}%XVK~*w Gl_LefA9@`C literal 0 HcmV?d00001 diff --git a/SecurityTests/cspxutils/symReference/blobs/G4/ptext_RC5 b/SecurityTests/cspxutils/symReference/blobs/G4/ptext_RC5 new file mode 100644 index 0000000000000000000000000000000000000000..6dfa4f441537bbd007972028cb26dcbbfa783122 GIT binary patch literal 256 zcmV+b0ssC;#z##d^gBzyS->1B+Bg$;(ln~YY}$qstf7skbi^LBjAsPk5r~;M>H6d= zVp6Wgb~0*@4h(7ge_w7Q*LJV`M$Na4H1la`0dTqIw7~mw)NCgvJ$+Jg2yz3CA9wU7 zDoJDQi$x7mtt>gDBXcsUKv~1M0q!QAaer;Uc>rx9*+B(wCxS4L^=;eJ_*2sgxeE2o zF->?|hx^dzt|%He9eQD&^Z4e8XA_QyLhfD5NXRXjaH;YygX-!ug!8*?&?Omg9!&-i zEG2T&_=^@JHv<0pHfT2nzb!55!SRdeW!=vPF7;FJ{nG~H{Nkuu!^|Q3xml}YlZ@WK GfUs +#include +#include +#include +#include +#include "cspwrap.h" +#include +#include "common.h" +#include +#include "cspdlTesting.h" +#include + +/* + * Defaults. + */ +#define LOOPS_DEF 200 +#define PTEXT_SIZE_DEF 256 +#define BLOCK_SIZE_MAX 32 /* bytes */ + +/* + * Enumerate algs our own way to allow iteration. + */ +typedef enum { + ALG_ASC = 0, /* first must be 0 */ + ALG_DES, + ALG_RC2, + ALG_RC4, + ALG_RC5, + ALG_3DES, + ALG_AES, + ALG_AES192, + ALG_AES256, + ALG_BFISH, + ALG_CAST +} SymAlg; + +#define ALG_FIRST ALG_ASC +#define ALG_LAST ALG_CAST + +static void usage(char **argv) +{ + printf("usage: %s e|d dirName [options]\n", argv[0]); + printf(" e=encrypt, d=decrypt; blobs read/written in dirName\n"); + printf(" Options:\n"); + printf(" a=algorithm (d=DES; 3=3DES3; 2=RC2; 4=RC4; 5=RC5; a=AES; b=Blowfish; \n"); + printf(" c=CAST; s=ASC, default=all)\n"); + printf(" p=ptextSize (default=%d)\n", PTEXT_SIZE_DEF); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +/* + * map SymAlg to test params + */ +typedef struct { + SymAlg alg; + const char *algStr; + CSSM_ALGORITHMS cssmAlg; + CSSM_ENCRYPT_MODE mode; + CSSM_PADDING padding; + CSSM_SIZE keySizeBits; + CSSM_SIZE ivLen; // in bytes +} SymAlgParams; + +static const SymAlgParams symAlgParams[] = +{ + { ALG_ASC, "ASC", CSSM_ALGID_ASC, CSSM_ALGMODE_NONE, CSSM_PADDING_NONE, + CSP_ASC_KEY_SIZE_DEFAULT, 0 }, + { ALG_DES, "DES", CSSM_ALGID_DES, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5, + CSP_DES_KEY_SIZE_DEFAULT, 8 }, + { ALG_RC2, "RC2", CSSM_ALGID_RC2, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5, + CSP_RC2_KEY_SIZE_DEFAULT, 8 }, + { ALG_RC4, "RC4", CSSM_ALGID_RC4, CSSM_ALGMODE_NONE, CSSM_PADDING_NONE, + CSP_RC4_KEY_SIZE_DEFAULT, 0 }, + { ALG_RC5, "RC5", CSSM_ALGID_RC5, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5, + CSP_RC5_KEY_SIZE_DEFAULT, 8 }, + { ALG_3DES, "3DES", CSSM_ALGID_3DES_3KEY_EDE, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5, + CSP_DES3_KEY_SIZE_DEFAULT, 8 }, + { ALG_AES, "AES", CSSM_ALGID_AES, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5, + CSP_AES_KEY_SIZE_DEFAULT, 16 }, + { ALG_AES192, "AES192", CSSM_ALGID_AES, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5, + 192, 24 }, + { ALG_AES256, "AES256", CSSM_ALGID_AES, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5, + 256, 32 }, + { ALG_BFISH, "Blowfish", CSSM_ALGID_BLOWFISH, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5, + CSP_BFISH_KEY_SIZE_DEFAULT, 8 }, + { ALG_CAST, "CAST", CSSM_ALGID_CAST, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5, + CSP_CAST_KEY_SIZE_DEFAULT, 8 } +}; + +static void genFileNames( + const char *algStr, + char *keyFile, + char *ptextFile, + char *ctextFile, + char *ivFile) +{ + sprintf(keyFile, "key_%s", algStr); + sprintf(ptextFile, "ptext_%s", algStr); + sprintf(ctextFile, "ctext_%s", algStr); + sprintf(ivFile, "iv_%s", algStr); +} + +/* encrypt, write blobs (key, plaintext, ciphertext, optional IV) to disk */ +static int doEncrypt( + CSSM_CSP_HANDLE cspHand, + const SymAlgParams *algParams, + CSSM_DATA *ptext, // mallocd, length valid, we fill data + CSSM_BOOL quiet, + CSSM_BOOL verbose) +{ + CSSM_KEY_PTR symKey = NULL; + CSSM_KEY rawKey; + CSSM_RETURN crtn; + CSSM_DATA ctext = {0, NULL}; + uint8 iv[BLOCK_SIZE_MAX]; + CSSM_DATA ivd = {BLOCK_SIZE_MAX, iv}; + CSSM_DATA *ivp = NULL; + uint32 blockSize = 0; + char keyFile[FILENAME_MAX]; + char ptextFile[FILENAME_MAX]; + char ctextFile[FILENAME_MAX]; + char ivFile[FILENAME_MAX]; + + if(!quiet) { + printf("...encrypting, alg %s\n", algParams->algStr); + } + + /* generate reference key (works with CSPDL) */ + symKey = cspGenSymKey(cspHand, algParams->cssmAlg, + "noLabel", 7, + CSSM_KEYUSE_ANY, algParams->keySizeBits, CSSM_TRUE); + if(symKey == NULL) { + printf("***Error generating key for alg %s size %u bits\n", + algParams->algStr, (unsigned)algParams->keySizeBits); + return testError(quiet); + } + + /* get key in raw format (to get the raw blob we write to disk) */ + crtn = cspRefKeyToRaw(cspHand, symKey, &rawKey); + if(crtn) { + printf("***Error generating raw key for alg %s size %u bits\n", + algParams->algStr, (unsigned)algParams->keySizeBits); + return testError(quiet); + } + + appGetRandomBytes(ptext->Data, (unsigned)ptext->Length); + + /* + * Hack: we only need to specify block size for AES192 and AES256, which + * we detect by their having an ivLen of greater than 16. + */ + if(algParams->ivLen > 16) { + blockSize = algParams->ivLen; + } + if(algParams->ivLen) { + appGetRandomBytes(iv, algParams->ivLen); + ivd.Length = algParams->ivLen; + ivp = &ivd; + } + + crtn = cspStagedEncrypt(cspHand, + algParams->cssmAlg, algParams->mode, algParams->padding, + symKey, NULL, + 0, blockSize, 0, + ivp, ptext, + &ctext, + CSSM_FALSE); + if(crtn) { + printf("***Error encrypting for alg %s size %u bits\n", + algParams->algStr, (unsigned)algParams->keySizeBits); + return testError(quiet); + } + + /* write: key, IV, ptext, ctext */ + genFileNames(algParams->algStr, keyFile, ptextFile, ctextFile, ivFile); + if(writeFile(keyFile, rawKey.KeyData.Data, (unsigned)rawKey.KeyData.Length) || + writeFile(ptextFile, ptext->Data, (unsigned)ptext->Length) || + writeFile(ctextFile, ctext.Data, (unsigned)ctext.Length)) { + printf("***Error writing result of alg %s size %u bits\n", + algParams->algStr, (unsigned)algParams->keySizeBits); + return testError(quiet); + } + if(ivp != NULL) { + if(writeFile(ivFile, ivp->Data, (unsigned)ivp->Length)) { + printf("***Error writing IV for alg %s size %u bits\n", + algParams->algStr, (unsigned)algParams->keySizeBits); + return testError(quiet); + } + } + + /* Free resources */ + CSSM_FreeKey(cspHand, NULL, symKey, CSSM_FALSE); + CSSM_FreeKey(cspHand, NULL, &rawKey, CSSM_FALSE); + CSSM_FREE(ctext.Data); + return 0; +} + +/* read blobs (key, plaintext, ciphertext, optional IV) from disk, decrypt, compare plaintext */ +static int doDecrypt( + CSSM_CSP_HANDLE cspHand, + const SymAlgParams *algParams, + CSSM_BOOL quiet, + CSSM_BOOL verbose) +{ + CSSM_KEY symKey; + uint8 *symKeyBits; + unsigned symKeyLen; // in bytes + CSSM_DATA symKeyData; + CSSM_RETURN crtn; + uint8 *ctextChars; + unsigned ctextLen = 0; + CSSM_DATA ctext; + CSSM_DATA rptext = {0, NULL}; // recovered/decrytped + uint8 *refPTextChars; + unsigned refPtextLen; + CSSM_DATA refPtext = {0, NULL}; // expected + uint8 *iv = NULL; + unsigned ivLen; + CSSM_DATA ivd = {BLOCK_SIZE_MAX, iv}; + CSSM_DATA *ivp = NULL; + uint32 blockSize = 0; + char keyFile[FILENAME_MAX]; + char ptextFile[FILENAME_MAX]; + char ctextFile[FILENAME_MAX]; + char ivFile[FILENAME_MAX]; + + if(!quiet) { + printf("...decrypting, alg %s\n", algParams->algStr); + } + + /* + * Hack: we only need to specify block size for AES192 and AES256, which + * we detect by their having an ivLen of greater than 16. + */ + if(algParams->ivLen > 16) { + blockSize = algParams->ivLen; + } + if(algParams->ivLen) { + ivp = &ivd; + ivd.Length = algParams->ivLen; + } + + /* read: key, IV, ptext, ctext */ + genFileNames(algParams->algStr, keyFile, ptextFile, ctextFile, ivFile); + if(readFile(keyFile, &symKeyBits, &symKeyLen) || + readFile(ptextFile, &refPTextChars, &refPtextLen) || + readFile(ctextFile, &ctextChars, &ctextLen)) { + printf("***Error reading reference blobs for alg %s size %u bits\n", + algParams->algStr, (unsigned)algParams->keySizeBits); + return testError(quiet); + } + if(ivp != NULL) { + if(readFile(ivFile, &iv, &ivLen)) { + printf("***Error writing IV for alg %s size %u bits\n", + algParams->algStr, (unsigned)algParams->keySizeBits); + return testError(quiet); + } + if(ivLen != algParams->ivLen) { + printf("***Unexpected IV length: expect %u found %u\n", + (unsigned)algParams->ivLen, (unsigned)ivLen); + if(testError(quiet)) { + return 1; + } + } + ivd.Data = iv; + } + ctext.Data = ctextChars; + ctext.Length = ctextLen; + refPtext.Data = refPTextChars; + refPtext.Length = refPtextLen; + + /* generate key */ + symKeyData.Data = symKeyBits; + symKeyData.Length = symKeyLen; + + crtn = cspGenSymKeyWithBits(cspHand, algParams->cssmAlg, + CSSM_KEYUSE_ANY, &symKeyData, symKeyLen, &symKey); + if(crtn) { + printf("***Error creating key for alg %s keySize %u\n", + algParams->algStr, (unsigned)algParams->keySizeBits); + return testError(quiet); + } + + crtn = cspStagedDecrypt(cspHand, + algParams->cssmAlg, algParams->mode, algParams->padding, + &symKey, NULL, + 0, blockSize, 0, + ivp, &ctext, + &rptext, + CSSM_FALSE); + if(crtn) { + printf("***Error decrypting for alg %s size %u bits\n", + algParams->algStr, (unsigned)algParams->keySizeBits); + return testError(quiet); + } + + /* moment of truth */ + if(!appCompareCssmData(&rptext, &refPtext)) { + printf("***DATA MISCOMPARE AFTER DECRYPT alg %s size %u bits\n", + algParams->algStr, (unsigned)algParams->keySizeBits); + return testError(quiet); + } + + /* Free resources */ + CSSM_FreeKey(cspHand, NULL, &symKey, CSSM_FALSE); + free(symKeyBits); // mallocd by readFile() + free(refPTextChars); + free(ctextChars); + CSSM_FREE(rptext.Data); // mallocd by CSP + if(iv) { + free(iv); + } + return 0; +} + + +int main(int argc, char **argv) +{ + int arg; + char *argp; + CSSM_DATA ptext; + CSSM_CSP_HANDLE cspHand; + unsigned currAlg; // ALG_xxx + int rtn = 0; + + /* + * User-spec'd params + */ + unsigned minAlg = ALG_FIRST; + unsigned maxAlg = ALG_LAST; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL bareCsp = CSSM_TRUE; + bool encrypt = false; + unsigned ptextSize = PTEXT_SIZE_DEF; + char *dirName; + + if(argc < 3) { + usage(argv); + } + switch(argv[1][0]) { + case 'e': + encrypt = true; + break; + case 'd': + encrypt = false; + break; + default: + usage(argv); + } + dirName = argv[2]; + + for(arg=3; arg +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "cspdlTesting.h" + +/* + * Defaults. + */ +#define LOOPS_DEF 50 +#define MIN_PTEXT_SIZE 8 +#define MAX_PTEXT_SIZE 0x10000 + +/* + * Enumerate algs our own way to allow iteration. + */ +typedef enum { + ALG_ASC = 1, + ALG_DES, + ALG_RC2, + ALG_RC4, + ALG_RC5, + ALG_3DES, + ALG_AES, + ALG_BFISH, + ALG_CAST, + ALG_NULL /* normally not used */ +} SymAlg; +#define ALG_FIRST ALG_ASC +#define ALG_LAST ALG_CAST + +#define PBE_ENABLE 0 +#define PWD_LENGTH_MAX 64 +#define MAX_DATA_SIZE (100000 + 100) /* bytes */ +#define LOOP_NOTIFY 20 + +#define LOG_SIZE 0 +#if LOG_SIZE +#define logSize(s) printf s +#else +#define logSize(s) +#endif + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" a=algorithm (s=ASC; d=DES; 3=3DES; 2=RC2; 4=RC4; 5=RC5; a=AES;\n"); + printf(" b=Blowfish; c=CAST; n=Null; default=all)\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" n=minPtextSize (default=%d)\n", MIN_PTEXT_SIZE); + printf(" x=maxPtextSize (default=%d)\n", MAX_PTEXT_SIZE); + printf(" k=keySizeInBits\n"); + printf(" r(eference keys only)\n"); + printf(" e(xport)\n"); + printf(" d (no DB open)\n"); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" o (no padding, well-aligned plaintext)\n"); + printf(" u (no multi-update ops)\n"); + printf(" U (only multi-update ops)\n"); + printf(" m (CSP mallocs out bufs)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" K (key gen only)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +/* constant seed data */ +static CSSM_DATA seedData = {8, (uint8 *)"12345678"}; + +/* alternate between two derivation algs, with different digest sizes */ +#define PBE_DERIVE_ALG_ODD CSSM_ALGID_PKCS5_PBKDF1_MD5 +#define PBE_DERIVE_ALG_EVEN CSSM_ALGID_PKCS5_PBKDF1_SHA1 + +/* + * When expectEqualText is true, encrypt/decrypt in place. + */ +#define EQUAL_TEXT_IN_PLACE 1 + +static int doTest(CSSM_CSP_HANDLE cspHand, + CSSM_DATA_PTR ptext, + uint32 keyAlg, // CSSM_ALGID_xxx of the key + uint32 encrAlg, // encrypt/decrypt + uint32 mode, + uint32 padding, + uint32 effectiveKeySizeInBits, + CSSM_BOOL refKey, + CSSM_DATA_PTR pwd, // password- NULL means use a random key data + CSSM_BOOL stagedEncr, + CSSM_BOOL stagedDecr, + CSSM_BOOL mallocPtext, // only meaningful if !stagedDecr + CSSM_BOOL mallocCtext, // only meaningful if !stagedEncr + CSSM_BOOL quiet, + CSSM_BOOL keyGenOnly, + CSSM_BOOL expectEqualText) // ptext size must == ctext size +{ + CSSM_KEY_PTR symKey = NULL; + CSSM_DATA ctext = {0, NULL}; + CSSM_DATA rptext = {0, NULL}; + CSSM_RETURN crtn; + int rtn = 0; + uint32 keySizeInBits; + CSSM_DATA initVector; + uint32 rounds = 0; + + /* generate keys with well aligned sizes; effectiveKeySize specified in encrypt + * only if not well aligned */ + keySizeInBits = (effectiveKeySizeInBits + 7) & ~7; + if(keySizeInBits == effectiveKeySizeInBits) { + effectiveKeySizeInBits = 0; + } + + if(encrAlg == CSSM_ALGID_RC5) { + /* roll the dice, pick one of three values for rounds */ + unsigned die = genRand(1,3); + switch(die) { + case 1: + rounds = 8; + break; + case 2: + rounds = 12; + break; + case 3: + rounds = 16; + break; + } + } + + if(pwd == NULL) { + /* random key */ + symKey = cspGenSymKey(cspHand, + keyAlg, + "noLabel", + 7, + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + keySizeInBits, + refKey); + } + else { + /* this code isn't tested */ + uint32 pbeAlg; + initVector.Data = NULL; // we're going to ignore this + initVector.Length = 0; + /* one of two random PBE algs */ + if(ptext->Data[0] & 1) { + pbeAlg = PBE_DERIVE_ALG_ODD; + } + else { + pbeAlg = PBE_DERIVE_ALG_EVEN; + } + symKey = cspDeriveKey(cspHand, + pbeAlg, + keyAlg, + "noLabel", + 7, + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + keySizeInBits, + refKey, + pwd, + &seedData, + 1, // iteration count + &initVector); + if(initVector.Data != NULL) { + CSSM_FREE(initVector.Data); + } + } + if(symKey == NULL) { + rtn = testError(quiet); + goto abort; + } + if(keyGenOnly) { + rtn = 0; + goto abort; + } + + /* not all algs need this, pass it in anyway */ + initVector.Data = (uint8 *)"someStrangeInitVect"; + switch(encrAlg) { + case CSSM_ALGID_AES: + case CSSM_ALGID_NONE: + initVector.Length = 16; + break; + default: + initVector.Length = 8; + break; + } + if(stagedEncr) { + crtn = cspStagedEncrypt(cspHand, + encrAlg, + mode, + padding, + symKey, + NULL, // second key unused + effectiveKeySizeInBits, + 0, // cipherBlockSize + rounds, + &initVector, + ptext, + &ctext, + CSSM_TRUE); // multi + } + else { + const CSSM_DATA *ptextPtr = ptext; + if(expectEqualText && mallocCtext && CSPDL_NOPAD_ENFORCE_SIZE) { + /* + * !pad test: ensure this works when ctextlen == ptextlen by + * mallocing ourself right now (instead of cspEncrypt doing it + * after doing a CSSM_QuerySize()) + */ + ctext.Data = (uint8 *)appMalloc(ptext->Length, NULL); + if(ctext.Data == NULL) { + printf("memmory failure\n"); + rtn = testError(quiet); + goto abort; + } + ctext.Length = ptext->Length; + #if EQUAL_TEXT_IN_PLACE + /* encrypt in place */ + memmove(ctext.Data, ptext->Data, ptext->Length); + ptextPtr = &ctext; + #endif + } + crtn = cspEncrypt(cspHand, + encrAlg, + mode, + padding, + symKey, + NULL, // second key unused + effectiveKeySizeInBits, + rounds, + &initVector, + ptextPtr, + &ctext, + mallocCtext); + } + if(crtn) { + rtn = testError(quiet); + goto abort; + } + if(expectEqualText && (ptext->Length != ctext.Length)) { + printf("***ctext/ptext length mismatch: ptextLen %lu ctextLen %lu\n", + ptext->Length, ctext.Length); + rtn = testError(quiet); + if(rtn) { + goto abort; + } + } + logSize(("###ctext len %lu\n", ctext.Length)); + if(stagedDecr) { + crtn = cspStagedDecrypt(cspHand, + encrAlg, + mode, + padding, + symKey, + NULL, // second key unused + effectiveKeySizeInBits, + 0, // cipherBlockSize + rounds, + &initVector, + &ctext, + &rptext, + CSSM_TRUE); // multi + } + else { + const CSSM_DATA *ctextPtr = &ctext; + if(expectEqualText && mallocPtext && CSPDL_NOPAD_ENFORCE_SIZE) { + /* + * !pad test: ensure this works when ctextlen == ptextlen by + * mallocing ourself right now (instead of cspDecrypt doing it + * after doing a CSSM_QuerySize()) + */ + rptext.Data = (uint8 *)appMalloc(ctext.Length, NULL); + if(rptext.Data == NULL) { + printf("memmory failure\n"); + rtn = testError(quiet); + goto abort; + } + rptext.Length = ctext.Length; + #if EQUAL_TEXT_IN_PLACE + /* decrypt in place */ + memmove(rptext.Data, ctext.Data, ctext.Length); + ctextPtr = &rptext; + #endif + } + crtn = cspDecrypt(cspHand, + encrAlg, + mode, + padding, + symKey, + NULL, // second key unused + effectiveKeySizeInBits, + rounds, + &initVector, + ctextPtr, + &rptext, + mallocPtext); + } + if(crtn) { + rtn = testError(quiet); + goto abort; + } + logSize(("###rptext len %lu\n", rptext.Length)); + /* compare ptext, rptext */ + if(ptext->Length != rptext.Length) { + printf("Ptext length mismatch: expect %lu, got %lu\n", ptext->Length, rptext.Length); + rtn = testError(quiet); + if(rtn) { + goto abort; + } + } + if(memcmp(ptext->Data, rptext.Data, ptext->Length)) { + printf("***data miscompare\n"); + rtn = testError(quiet); + } +abort: + /* free key if we have it*/ + if(symKey != NULL) { + if(cspFreeKey(cspHand, symKey)) { + printf("Error freeing privKey\n"); + rtn = 1; + } + CSSM_FREE(symKey); + } + /* free rptext, ctext */ + appFreeCssmData(&rptext, CSSM_FALSE); + appFreeCssmData(&ctext, CSSM_FALSE); + return rtn; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + CSSM_DATA ptext; + CSSM_CSP_HANDLE cspHand; + CSSM_BOOL stagedEncr; + CSSM_BOOL stagedDecr; + CSSM_BOOL mallocCtext; + CSSM_BOOL mallocPtext; + CSSM_BOOL refKey; + const char *algStr; + uint32 keyAlg; // CSSM_ALGID_xxx of the key + uint32 encrAlg; // CSSM_ALGID_xxx of the encrypt/decrypt/sign + int i; + int currAlg; // ALG_xxx + CSSM_DATA_PTR pPwd; + CSSM_DATA pwd; + uint32 actKeySizeInBits; + int rtn = 0; + uint32 blockSize; // for noPadding case + CSSM_BOOL expectEqualText; + + /* + * User-spec'd params + */ + CSSM_BOOL keySizeSpec = CSSM_FALSE; // false: use rand key size + SymAlg minAlg = ALG_FIRST; + SymAlg maxAlg = ALG_LAST; + unsigned loops = LOOPS_DEF; + CSSM_BOOL verbose = CSSM_FALSE; + unsigned minPtextSize = MIN_PTEXT_SIZE; + unsigned maxPtextSize = MAX_PTEXT_SIZE; + CSSM_BOOL quiet = CSSM_FALSE; + unsigned pauseInterval = 0; + uint32 mode; + uint32 padding; + CSSM_BOOL noDbOpen = CSSM_FALSE; + CSSM_BOOL bareCsp = CSSM_TRUE; + CSSM_BOOL keyGenOnly = CSSM_FALSE; + CSSM_BOOL noPadding = CSSM_FALSE; + CSSM_BOOL multiEnable = CSSM_TRUE; + CSSM_BOOL multiOnly = CSSM_FALSE; + CSSM_BOOL refKeysOnly = CSSM_FALSE; + CSSM_BOOL cspMallocs = CSSM_FALSE; + + #if macintosh + argc = ccommand(&argv); + #endif + for(arg=1; arg maxPtextSize) { + printf("***minPtextSize must be <= maxPtextSize\n"); + usage(argv); + } + pwd.Data = (uint8 *)CSSM_MALLOC(PWD_LENGTH_MAX); + ptext.Data = (uint8 *)CSSM_MALLOC(maxPtextSize); + if(ptext.Data == NULL) { + printf("Insufficient heap space\n"); + exit(1); + } + /* ptext length set in test loop */ + printf("Starting symTest; args: "); + for(i=1; i align ptext */ + ptext.Length = ((ptext.Length + blockSize - 1) / blockSize) * blockSize; + } + if(!keySizeSpec) { + actKeySizeInBits = randKeySizeBits(keyAlg, OT_Encrypt); + } + /* else constant, spec'd by user, may be 0 (default per alg) */ + /* mix up some random and derived keys, as well as staging and "who does + * the malloc?" */ + pPwd = (loop & 1) ? &pwd : NULL; + if(multiEnable) { + if(multiOnly) { + stagedEncr = stagedDecr = CSSM_TRUE; + } + else { + stagedEncr = (loop & 2) ? CSSM_TRUE : CSSM_FALSE; + stagedDecr = (loop & 4) ? CSSM_TRUE : CSSM_FALSE; + } + } + else { + stagedEncr = CSSM_FALSE; + stagedDecr = CSSM_FALSE; + } + if(!stagedEncr && !cspMallocs) { + mallocCtext = (ptext.Data[0] & 1) ? CSSM_TRUE : CSSM_FALSE; + } + else { + mallocCtext = CSSM_FALSE; + } + if(!stagedDecr && !cspMallocs) { + mallocPtext = (ptext.Data[0] & 2) ? CSSM_TRUE : CSSM_FALSE; + } + else { + mallocPtext = CSSM_FALSE; + } + if(refKeysOnly) { + refKey = CSSM_TRUE; + } + else { + refKey = (ptext.Data[0] & 4) ? CSSM_TRUE : CSSM_FALSE; + } + #if !PBE_ENABLE + pPwd = NULL; + #endif + if(!quiet) { + if(verbose || ((loop % LOOP_NOTIFY) == 0)) { + printf("..loop %d text size %lu keySizeBits %u\n", + loop, (unsigned long)ptext.Length, (unsigned)actKeySizeInBits); + if(verbose) { + printf(" refKey %d derive %d stagedEncr %d stagedDecr %d mallocCtext %d " + "mallocPtext %d\n", + (int)refKey, (pPwd == NULL) ? 0 : 1, (int)stagedEncr, (int)stagedDecr, + (int)mallocCtext, (int)mallocPtext); + } + } + } + #if PBE_ENABLE + if(pPwd != NULL) { + /* PBE - cook up random password */ + simpleGenData(pPwd, APPLE_PBE_MIN_PASSWORD, PWD_LENGTH_MAX); + } + #endif + + if(doTest(cspHand, + &ptext, + keyAlg, + encrAlg, + mode, + padding, + actKeySizeInBits, + refKey, + pPwd, + stagedEncr, + stagedDecr, + mallocPtext, + mallocCtext, + quiet, + keyGenOnly, + expectEqualText)) { + rtn = 1; + break; + } + if(pauseInterval && ((loop % pauseInterval) == 0)) { + char c; + fpurge(stdin); + printf("Hit CR to proceed, q to abort: "); + c = getchar(); + if(c == 'q') { + goto testDone; + } + } + if(loops && (loop == loops)) { + break; + } + } /* main loop */ + if(rtn) { + break; + } + + } /* for algs */ + +testDone: + cspShutdown(cspHand, bareCsp); + if(pauseInterval) { + fpurge(stdin); + printf("ModuleDetach/Unload complete; hit CR to exit: "); + getchar(); + } + if((rtn == 0) && !quiet) { + printf("%s test complete\n", argv[0]); + } + CSSM_FREE(pwd.Data); + CSSM_FREE(ptext.Data); + return rtn; +} diff --git a/SecurityTests/cspxutils/testall b/SecurityTests/cspxutils/testall new file mode 100755 index 00000000..6b273491 --- /dev/null +++ b/SecurityTests/cspxutils/testall @@ -0,0 +1,67 @@ +#! /bin/csh -f +# +# Run all normal configurations of cspdvt and cltpdvt. +# +# safely look for this required env var +# +setenv | grep LOCAL_BUILD_DIR > /dev/null +if($status != 0) then + echo Please set env var LOCAL_BUILD_DIR. + exit(1) +endif + +# Setup HOME environment with an unlocked login.keychain +setenv HOME "${LOCAL_BUILD_DIR}/home" +# Cleanup after a possible previous test run +rm -rf "${LOCAL_BUILD_DIR}/home" +echo Creating virtual home directory in "$HOME"... +mkdir -p "${HOME}/Library/Preferences" || exit(1) +setenv PATH "${LOCAL_BUILD_DIR}:${PATH}" +# +# Avoid Sec layer overriding what we're trying to do here.... +# +set USERNAME=`whoami` +if($USERNAME == root) then + set LOGIN_KEYCHAIN="${LOCAL_BUILD_DIR}/home/Library/Keychains/login.keychain" +else + set LOGIN_KEYCHAIN=login.keychain +endif +echo Creating virtual login keychain in "$LOGIN_KEYCHAIN"... +security create -p test "$LOGIN_KEYCHAIN" +security set-keychain-settings "$LOGIN_KEYCHAIN" || exit(1) + +set BUILD_DIR=$LOCAL_BUILD_DIR + +set FULL_SSL= +while ( $#argv > 0 ) + switch ( "$argv[1]" ) + case f: + set FULL_SSL=f + shift + breaksw + default: + echo Usage: testall \[f\(ull SSL tests\)\] + exit(1) + endsw +end + +# +# Verify existence of a few random executables before we start. +# +if( ( ! -e $BUILD_DIR/wrapTest ) || \ + ( ! -e $BUILD_DIR/hashTest ) || \ + ( ! -e $BUILD_DIR/sslViewer ) || \ + ( ! -e $BUILD_DIR/threadTest) ) then + echo === You do not seem to have all of the required executables. + echo === Please run \"make all\". + exit(1) +endif + + +echo ===== Running raw CSP regression test ===== +./cspdvt q || exit(1) +echo ===== Running CSPDL regression test ===== +./cspdvt q D || exit(1) +echo ===== Running CL/TP regression test ===== +cd ../clxutils; ./cltpdvt q $FULL_SSL || exit(1) +echo ===== Full CSP/CL/TP regression test SUCCEEDED ===== diff --git a/SecurityTests/cspxutils/utilLib/Makefile b/SecurityTests/cspxutils/utilLib/Makefile new file mode 100644 index 00000000..a2833233 --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/Makefile @@ -0,0 +1,59 @@ +# name of executable to build +EXECUTABLE=libcsputils.a +# C++ source (with .cpp extension) +CPSOURCE= commonCpp.cpp nssAppUtils.cpp ssleayUtils.cpp +# C source (.c extension) +CSOURCE= common.c cspwrap.c fileIo.c bsafeUtils.c t_stdlib.c rijndael-alg-ref.c \ + rijndaelApi.c cputime.c + +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +#PROJ_CFLAGS= -Os +PROJ_CFLAGS= -fvisibility=hidden + +# +# Optional link flags (using cc, not ld) +# +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.lib + +# Special case for this object file...normally we ignore header dependencies, but +# this header is auto generated on a regular basis. +$(OBJROOT)/commonCpp.o: commonCpp.cpp cssmErrorStrings.h + $(CC) $(ALL_CFLAGS) -c -o $(OBJROOT)/commonCpp.o commonCpp.cpp diff --git a/SecurityTests/cspxutils/utilLib/boxes-ref.h b/SecurityTests/cspxutils/utilLib/boxes-ref.h new file mode 100644 index 00000000..b3036019 --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/boxes-ref.h @@ -0,0 +1,85 @@ +static const word8 Logtable[256] = { + 0, 0, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3, +100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193, +125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120, +101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142, +150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56, +102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16, +126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186, + 43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87, +175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232, + 44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160, +127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183, +204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157, +151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209, + 83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171, + 68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165, +103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7, +}; + +static const word8 Alogtable[256] = { + 1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53, + 95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170, +229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49, + 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205, + 76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, +131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, +181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163, +254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160, +251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65, +195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, +159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, +155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84, +252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202, + 69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, + 18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, + 57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1, +}; + +static const word8 S[256] = { + 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, +202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, +183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21, + 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, + 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, + 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, +208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, + 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210, +205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, + 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, +224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, +231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, +186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, +112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, +225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, +140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22, +}; + +static const word8 Si[256] = { + 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251, +124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203, + 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78, + 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37, +114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146, +108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132, +144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6, +208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107, + 58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115, +150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110, + 71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27, +252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244, + 31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95, + 96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, +160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97, + 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125, +}; + +static const word8 iG[4][4] = { +{ 0x0e, 0x09, 0x0d, 0x0b }, +{ 0x0b, 0x0e, 0x09, 0x0d }, +{ 0x0d, 0x0b, 0x0e, 0x09 }, +{ 0x09, 0x0d, 0x0b, 0x0e } +}; + +static const word32 rcon[30] = { + 0x01,0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, }; diff --git a/SecurityTests/cspxutils/utilLib/bsafeUtils.c b/SecurityTests/cspxutils/utilLib/bsafeUtils.c new file mode 100644 index 00000000..9038a26a --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/bsafeUtils.c @@ -0,0 +1,1009 @@ +/* + * bsafeUtils.c - common routines for CDSA/BSAFE compatibility testing + */ + + +#include +#include +#include +#include +//#include +//#include +#include "bsafeUtils.h" +#include +#include "common.h" + +/* + * Convert between BSAFE ITEM and CSSM_DATA + */ +#if 0 +static inline void buItemToCssmData( + const ITEM *item, + CSSM_DATA_PTR cdata) +{ + cdata->Data = item->data; + cdata->Length = item->len; +} + +static inline void buCssmDataToItem( + const CSSM_DATA *cdata, + ITEM *item) +{ + item->data = cdata->Data; + item->len = cdata->Length; +} + +/* + * BSafe's Chooser table - all we'll ever need. + */ +/*static*/ B_ALGORITHM_METHOD *BSAFE_ALGORITHM_CHOOSER[] = { + // digests + &AM_SHA, + &AM_MD5, + &AM_MD2, + + // organizational + &AM_CBC_ENCRYPT, + &AM_CBC_DECRYPT, + &AM_ECB_ENCRYPT, + &AM_ECB_DECRYPT, + &AM_OFB_ENCRYPT, + &AM_OFB_DECRYPT, + + // DES & variants + &AM_DES_ENCRYPT, + &AM_DES_DECRYPT, + &AM_DESX_ENCRYPT, + &AM_DESX_DECRYPT, + &AM_DES_EDE_ENCRYPT, + &AM_DES_EDE_DECRYPT, + + // RCn stuff + &AM_RC2_CBC_ENCRYPT, + &AM_RC2_CBC_DECRYPT, + &AM_RC2_ENCRYPT, + &AM_RC2_DECRYPT, + &AM_RC4_ENCRYPT, + &AM_RC4_DECRYPT, + &AM_RC5_ENCRYPT, + &AM_RC5_DECRYPT, + &AM_RC5_CBC_ENCRYPT, + &AM_RC5_CBC_DECRYPT, + + // RSA + &AM_RSA_STRONG_KEY_GEN, + &AM_RSA_KEY_GEN, + &AM_RSA_CRT_ENCRYPT_BLIND, + &AM_RSA_CRT_DECRYPT_BLIND, + &AM_RSA_ENCRYPT, + &AM_RSA_DECRYPT, + + // DSA + &AM_DSA_PARAM_GEN, + &AM_DSA_KEY_GEN, + + // signatures + &AM_DSA_SIGN, + &AM_DSA_VERIFY, + + // random number generation + &AM_MD5_RANDOM, + &AM_SHA_RANDOM, + + // sentinel + (B_ALGORITHM_METHOD *)NULL_PTR +}; + +/* + * Convert a BSAFE return to a CSSM error and optionally print the error msg with + * the op in which the error occurred. + */ +static CSSM_RETURN buBsafeErrToCssm( + int brtn, + const char *op) +{ + const char *errStr = NULL; + CSSM_RETURN crtn; + + switch (brtn) { + case 0: + return CSSM_OK; + case BE_ALLOC: + crtn = CSSMERR_CSSM_MEMORY_ERROR; + errStr = "BE_ALLOC"; + break; + case BE_SIGNATURE: + crtn = CSSMERR_CSP_VERIFY_FAILED; + errStr = "BE_SIGNATURE"; + break; + case BE_OUTPUT_LEN: + crtn = CSSMERR_CSP_OUTPUT_LENGTH_ERROR; + errStr = "BE_OUTPUT_LEN"; + break; + case BE_INPUT_LEN: + crtn = CSSMERR_CSP_INPUT_LENGTH_ERROR; + errStr = "BE_INPUT_LEN"; + break; + case BE_EXPONENT_EVEN: + crtn = CSSMERR_CSP_INVALID_KEY; + errStr = "BE_EXPONENT_EVEN"; + break; + case BE_EXPONENT_LEN: + crtn = CSSMERR_CSP_INVALID_KEY; + errStr = "BE_EXPONENT_LEN"; + break; + case BE_EXPONENT_ONE: + crtn = CSSMERR_CSP_INVALID_KEY; + errStr = "BE_EXPONENT_ONE"; + break; + case BE_DATA: + crtn = CSSMERR_CSP_INVALID_DATA; + errStr = "BE_DATA"; + break; + case BE_INPUT_DATA: + crtn = CSSMERR_CSP_INVALID_DATA; + errStr = "BE_INPUT_DATA"; + break; + case BE_WRONG_KEY_INFO: + crtn = CSSMERR_CSP_INVALID_KEY; + errStr = "BE_WRONG_KEY_INFO"; + break; + default: + //@@@ translate BSafe errors intelligently + crtn = CSSM_ERRCODE_INTERNAL_ERROR; + errStr = "Other BSAFE error"; + break; + } + if(op != NULL) { + printf("%s: BSAFE error %d (%s)\n", op, brtn, errStr); + } + return crtn; +} + +/* + * Non-thread-safe global random B_ALGORITHM_OBJ and a reusable init for it. + */ +static B_ALGORITHM_OBJ bsafeRng = NULL; +#define BSAFE_RANDSIZE 64 + +static B_ALGORITHM_OBJ buGetRng() +{ + int brtn; + uint8 seed[BSAFE_RANDSIZE]; + + if(bsafeRng != NULL) { + return bsafeRng; + } + brtn = B_CreateAlgorithmObject(&bsafeRng); + if(brtn) { + buBsafeErrToCssm(brtn, "B_CreateAlgorithmObject(&bsafeRng)"); + return NULL; + } + brtn = B_SetAlgorithmInfo(bsafeRng, AI_X962Random_V0, NULL_PTR); + if(brtn) { + buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo(bsafeRng)"); + return NULL; + } + brtn = B_RandomInit(bsafeRng, BSAFE_ALGORITHM_CHOOSER, NULL); + if(brtn) { + buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo(bsafeRng)"); + return NULL; + } + appGetRandomBytes(seed, BSAFE_RANDSIZE); + brtn = B_RandomUpdate(bsafeRng, seed, BSAFE_RANDSIZE, NULL); + if(brtn) { + buBsafeErrToCssm(brtn, "B_RandomUpdate"); + return NULL; + } + return bsafeRng; +} +#endif + +/* + * Create a symmetric key. + */ +CSSM_RETURN buGenSymKey( + uint32 keySizeInBits, + const CSSM_DATA *keyData, + BU_KEY *key) // RETURNED +{ +#if 0 + int brtn; + B_KEY_OBJ bkey = NULL; + ITEM item; + unsigned keyBytes = (keySizeInBits + 7) / 8; + + if(keyBytes > keyData->Length) { + /* note it's OK to give us too much key data */ + printf("***buGenSymKey: Insufficient keyData\n"); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + + /* create a BSAFE key */ + brtn = B_CreateKeyObject(&bkey); + if(brtn) { + return buBsafeErrToCssm(brtn, "B_CreateKeyObject"); + } + + /* assign data to the key */ + item.data = keyData->Data; + item.len = keyBytes; + brtn = B_SetKeyInfo(bkey, KI_Item, (POINTER)&item); + if(brtn) { + return buBsafeErrToCssm(brtn, "B_SetKeyInfo"); + } + else { + *key = bkey; + return CSSM_OK; + } +#endif + return 0; +} + +/* + * Create asymmetric key pair. + * FIXME - additional params (e.g. DSA params, RSA exponent)? + */ +CSSM_RETURN buGenKeyPair( + uint32 keySizeInBits, + CSSM_ALGORITHMS keyAlg, // CSSM_ALGID_{RSA,DSA} + BU_KEY *pubKey, // RETURNED + BU_KEY *privKey) // RETURNED +{ +#if 0 // NO MORE BSAFE + int brtn; + B_KEY_OBJ bPubkey = NULL; + B_KEY_OBJ bPrivkey = NULL; + B_ALGORITHM_OBJ keypairGen = NULL; + const char *op = NULL; + A_RSA_KEY_GEN_PARAMS params; + unsigned char exp[1] = { 3 }; + B_ALGORITHM_OBJ genDsaAlg = NULL; + B_ALGORITHM_OBJ dsaResult = NULL; + B_DSA_PARAM_GEN_PARAMS dsaParams; + A_DSA_PARAMS *kParams = NULL; + + /* create algorithm object */ + brtn = B_CreateAlgorithmObject(&keypairGen); + if(brtn) { + return CSSMERR_CSSM_MEMORY_ERROR; + } + + /* create two BSAFE keys */ + brtn = B_CreateKeyObject(&bPubkey); + if(brtn) { + op ="B_CreateKeyObject"; + goto abort; + } + brtn = B_CreateKeyObject(&bPrivkey); + if(brtn) { + op ="B_CreateKeyObject"; + goto abort; + } + switch(keyAlg) { + case CSSM_ALGID_RSA: + { + /* set RSA-specific params */ + params.modulusBits = keySizeInBits; + /* hack - parameterize? */ + params.publicExponent.data = exp; + params.publicExponent.len = 1; + brtn = B_SetAlgorithmInfo(keypairGen, AI_RSAKeyGen, + (POINTER)¶ms); + if(brtn) { + op ="B_SetAlgorithmInfo(AI_RSAKeyGen)"; + } + break; + } + case CSSM_ALGID_DSA: + { + /* jump through hoops generating parameters */ + brtn = B_CreateAlgorithmObject(&genDsaAlg); + if(brtn) { + op ="B_CreateAlgorithmObject"; + break; + } + dsaParams.primeBits = keySizeInBits; + brtn = B_SetAlgorithmInfo(genDsaAlg, AI_DSAParamGen, (POINTER)&dsaParams); + if(brtn) { + op = "B_SetAlgorithmInfo(AI_DSAParamGen)"; + break; + } + brtn = B_GenerateInit(genDsaAlg, BSAFE_ALGORITHM_CHOOSER, NULL); + if(brtn) { + op = "B_GenerateInit(AI_DSAParamGen)"; + break; + } + brtn = B_CreateAlgorithmObject(&dsaResult); + if(brtn) { + op = "B_CreateAlgorithmObject"; + break; + } + brtn = B_GenerateParameters(genDsaAlg, dsaResult, buGetRng(), NULL); + if(brtn) { + op = "B_GenerateParameters"; + break; + } + + /* dsaResult now has the parameters, which we must extract and then + * apply to the keypairGen object. Cool, huh? */ + brtn = B_GetAlgorithmInfo((POINTER *)&kParams, dsaResult, AI_DSAKeyGen); + if(brtn) { + op = "B_GetAlgorithmInfo(AI_DSAKeyGen)"; + break; + } + brtn = B_SetAlgorithmInfo(keypairGen, AI_DSAKeyGen, (POINTER)kParams); + if(brtn) { + op ="B_SetAlgorithmInfo(AI_DSAKeyGen)"; + } + break; + } + default: + printf("buGenKeyPair: algorithm not supported\n"); + return CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED; + } + if(brtn) { + goto abort; + } + + /* keypairGen all set to go. */ + brtn = B_GenerateInit(keypairGen, + BSAFE_ALGORITHM_CHOOSER, + (A_SURRENDER_CTX *)NULL); + if(brtn) { + op = "B_GenerateInit"; + goto abort; + } + brtn = B_GenerateKeypair(keypairGen, + bPubkey, + bPrivkey, + buGetRng(), + NULL); + if(brtn) { + op = "B_GenerateInit"; + } +abort: + B_DestroyAlgorithmObject(&keypairGen); + B_DestroyAlgorithmObject(&genDsaAlg); + B_DestroyAlgorithmObject(&dsaResult); + if(brtn) { + B_DestroyKeyObject(&bPubkey); + B_DestroyKeyObject(&bPrivkey); + return buBsafeErrToCssm(brtn, op); + } + else { + *pubKey = bPubkey; + *privKey = bPrivkey; + return CSSM_OK; + } +#endif + return CSSM_OK; +} + +/* + * Free a key created in buGenSymKey or buGenKeyPair + */ +CSSM_RETURN buFreeKey( + BU_KEY key) +{ +#if 0 // NO MORE BSAFE + B_KEY_OBJ bkey = (B_KEY_OBJ)key; + B_DestroyKeyObject(&bkey); +#endif + return CSSM_OK; +} + +/* + * encrypt/decrypt + */ +CSSM_RETURN buEncryptDecrypt( + BU_KEY key, + CSSM_BOOL forEncrypt, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE mode, // CSSM_ALGMODE_CBC, etc. + const CSSM_DATA *iv, //Êoptional per mode + uint32 effectiveKeyBits, // optional per key alg (actually just RC2) + // for RSA, key size in bits + uint32 rounds, // optional, RC5 only + const CSSM_DATA *inData, + CSSM_DATA_PTR outData) // mallocd and RETURNED +{ +#if 0 // NO MORE BSAFE + B_ALGORITHM_OBJ alg; + int brtn; + char fbCipher = 1; + uint32 blockSize = 0; + unsigned outBufLen; + unsigned bytesMoved; + CSSM_RETURN crtn; + char useIv; + + // these variables are used in the switch below and need to + // live until after setAlgorithm() + ITEM bsIv; + B_BLK_CIPHER_W_FEEDBACK_PARAMS spec; + A_RC5_PARAMS rc5Params; + A_RC2_PARAMS rc2Params; + + brtn = B_CreateAlgorithmObject(&alg); + if(brtn) { + return buBsafeErrToCssm(brtn, "B_CreateAlgorithmObject"); + } + + /* per-alg setup */ + switch(encrAlg) { + case CSSM_ALGID_RC4: + /* the easy one */ + brtn = B_SetAlgorithmInfo(alg, AI_RC4, NULL); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo"); + goto abort; + } + fbCipher = 0; + break; + + case CSSM_ALGID_RSA: + /* assume encrypt via publicm decrypt via private */ + if(forEncrypt) { + brtn = B_SetAlgorithmInfo(alg, AI_PKCS_RSAPublic, NULL); + } + else { + brtn = B_SetAlgorithmInfo(alg, AI_PKCS_RSAPrivate, NULL); + } + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo(RSA)"); + goto abort; + } + blockSize = (effectiveKeyBits + 7) / 8; + fbCipher = 0; + break; + + /* common code using AI_FeebackCipher */ + case CSSM_ALGID_DES: + spec.encryptionMethodName = (POINTER)"des"; + blockSize = 8; + break; + case CSSM_ALGID_DESX: + spec.encryptionMethodName = (POINTER)"desx"; + blockSize = 8; + break; + case CSSM_ALGID_3DES_3KEY_EDE: + spec.encryptionMethodName = (POINTER)"des_ede"; + blockSize = 8; + break; + case CSSM_ALGID_RC5: + spec.encryptionMethodName = (POINTER)"rc5"; + spec.encryptionParams = (POINTER)&rc5Params; + rc5Params.version = 0x10; + rc5Params.rounds = rounds; + rc5Params.wordSizeInBits = 32; + blockSize = 8; + break; + case CSSM_ALGID_RC2: + spec.encryptionMethodName = (POINTER)"rc2"; + spec.encryptionParams = (POINTER)&rc2Params; + rc2Params.effectiveKeyBits = effectiveKeyBits; + blockSize = 8; + break; + /* add other non-AI_FeebackCipher algorithms here */ + default: + printf("buEncryptDecrypt: unknown algorithm\n"); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + if(fbCipher) { + useIv = 1; // default, except for ECB + switch(mode) { + case CSSM_ALGMODE_CBCPadIV8: + spec.feedbackMethodName = (POINTER)"cbc"; + spec.paddingMethodName = (POINTER)"pad"; + break; + case CSSM_ALGMODE_CBC_IV8: + spec.feedbackMethodName = (POINTER)"cbc"; + spec.paddingMethodName = (POINTER)"nopad"; + break; + case CSSM_ALGMODE_OFB_IV8: + spec.feedbackMethodName = (POINTER)"cbc"; + spec.paddingMethodName = (POINTER)"nopad"; + break; + case CSSM_ALGMODE_ECB: + /* this does not seem to work yet - need info from + * RSA. Specify block size as the feedbackParams (per manual) + * and get a memmove error trying to copy from address 8; specify + * an IV and get BSAFE error 524 (BE_INPUT_DATA) error on the + * EncryptInit. + */ + spec.feedbackMethodName = (POINTER)"ecb"; + spec.paddingMethodName = (POINTER)"nopad"; + //useIv = 0; + //spec.feedbackParams = (POINTER)8; + break; + default: + printf("buEncryptDecrypt: unknown mode\n"); + return CSSM_ERRCODE_INTERNAL_ERROR; + } + if(useIv && (iv != NULL)) { + buCssmDataToItem(iv, &bsIv); + spec.feedbackParams = (POINTER)&bsIv; + } + + brtn = B_SetAlgorithmInfo(alg, AI_FeedbackCipher, (POINTER)&spec); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo"); + goto abort; + } + } + + /* + * OK, one way or another we have an algorithm object. Set up + * output buffer. + */ + if(forEncrypt) { + outBufLen = inData->Length + blockSize; + } + else { + outBufLen = inData->Length; + } + outData->Length = 0; + outData->Data = NULL; + crtn = appSetupCssmData(outData, outBufLen); + if(crtn) { + goto abort; + } + if(forEncrypt) { + brtn = B_EncryptInit(alg, + (B_KEY_OBJ)key, + BSAFE_ALGORITHM_CHOOSER, + (A_SURRENDER_CTX *)NULL); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_EncryptInit"); + goto abort; + } + brtn = B_EncryptUpdate(alg, + outData->Data, + &bytesMoved, + outBufLen, + inData->Data, + inData->Length, + buGetRng(), // randAlg + NULL); // surrender + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_EncryptInit"); + goto abort; + } + outData->Length = bytesMoved; + brtn = B_EncryptFinal(alg, + outData->Data + bytesMoved, + &bytesMoved, + outBufLen - outData->Length, + buGetRng(), // randAlg + NULL); // surrender + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_EncryptFinal"); + goto abort; + } + outData->Length += bytesMoved; + crtn = CSSM_OK; + } + else { + brtn = B_DecryptInit(alg, + (B_KEY_OBJ)key, + BSAFE_ALGORITHM_CHOOSER, + (A_SURRENDER_CTX *)NULL); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_DecryptInit"); + goto abort; + } + brtn = B_DecryptUpdate(alg, + outData->Data, + &bytesMoved, + outBufLen, + inData->Data, + inData->Length, + NULL, // randAlg + NULL); // surrender + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_DecryptUpdate"); + goto abort; + } + outData->Length = bytesMoved; + brtn = B_DecryptFinal(alg, + outData->Data + bytesMoved, + &bytesMoved, + outBufLen - outData->Length, + NULL, // randAlg + NULL); // surrender + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_DecryptFinal"); + goto abort; + } + outData->Length += bytesMoved; + crtn = CSSM_OK; + } +abort: + B_DestroyAlgorithmObject(&alg); +#endif + return 0; //crtn; +} + +#if 0 +/* CSSM sig alg --> B_INFO_TYPE */ +static CSSM_RETURN cssmSigAlgToInfoType( + CSSM_ALGORITHMS cssmAlg, + B_INFO_TYPE *infoType) +{ + switch(cssmAlg) { + case CSSM_ALGID_SHA1WithRSA: + *infoType = AI_SHA1WithRSAEncryption; + break; + case CSSM_ALGID_MD5WithRSA: + *infoType = AI_MD5WithRSAEncryption; + break; + case CSSM_ALGID_SHA1WithDSA: + *infoType = AI_DSAWithSHA1; + break; + default: + printf("cssmSigAlgToInfoType: unknown algorithm\n"); + return CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED; + } + return CSSM_OK; +} +#endif + +/* + * Sign/verify + */ +CSSM_RETURN buSign( + BU_KEY key, + CSSM_ALGORITHMS sigAlg, + const CSSM_DATA *ptext, + uint32 keySizeInBits, // to set up sig + CSSM_DATA_PTR sig) // mallocd and RETURNED +{ +#if 0 // NO MORE BSAFE + B_ALGORITHM_OBJ alg = NULL; + int brtn; + B_INFO_TYPE infoType; + CSSM_RETURN crtn; + unsigned sigBytes; + + brtn = B_CreateAlgorithmObject(&alg); + if(brtn) { + return buBsafeErrToCssm(brtn, "B_CreateAlgorithmObject"); + } + crtn = cssmSigAlgToInfoType(sigAlg, &infoType); + if(crtn) { + return crtn; + } + brtn = B_SetAlgorithmInfo(alg, infoType, NULL); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo"); + goto abort; + } + brtn = B_SignInit(alg, (B_KEY_OBJ)key, BSAFE_ALGORITHM_CHOOSER, NULL); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_SignInit"); + goto abort; + } + brtn = B_SignUpdate(alg, ptext->Data, ptext->Length, NULL); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_SignUpdate"); + goto abort; + } + + /* prepare for sig, size of key */ + sigBytes = (keySizeInBits + 7) / 8; + sig->Data = (uint8 *)CSSM_MALLOC(sigBytes); + sig->Length = sigBytes; + + brtn = B_SignFinal(alg, sig->Data, &sigBytes, sigBytes, buGetRng(), NULL); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_SignFinal"); + goto abort; + } + sig->Length = sigBytes; + crtn = CSSM_OK; +abort: + B_DestroyAlgorithmObject(&alg); +#endif + return 0;//; +} + +CSSM_RETURN buVerify( + BU_KEY key, + CSSM_ALGORITHMS sigAlg, + const CSSM_DATA *ptext, + const CSSM_DATA *sig) // mallocd and RETURNED +{ +#if 0 // NO MORE BSAFE + B_ALGORITHM_OBJ alg = NULL; + int brtn; + B_INFO_TYPE infoType; + CSSM_RETURN crtn; + + brtn = B_CreateAlgorithmObject(&alg); + if(brtn) { + return buBsafeErrToCssm(brtn, "B_CreateAlgorithmObject"); + } + crtn = cssmSigAlgToInfoType(sigAlg, &infoType); + if(crtn) { + return crtn; + } + brtn = B_SetAlgorithmInfo(alg, infoType, NULL); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo"); + goto abort; + } + brtn = B_VerifyInit(alg, (B_KEY_OBJ)key, BSAFE_ALGORITHM_CHOOSER, NULL); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_VerifyInit"); + goto abort; + } + brtn = B_VerifyUpdate(alg, ptext->Data, ptext->Length, NULL); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_VerifyUpdate"); + goto abort; + } + brtn = B_VerifyFinal(alg, sig->Data, sig->Length, buGetRng(), NULL); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_VerifyFinal"); + goto abort; + } + crtn = CSSM_OK; +abort: + B_DestroyAlgorithmObject(&alg); + return crtn; +#endif + return 0; +} + +/* + * generate MAC either one update (updateSizes == NULL) or + * specified set of update sizes. + */ +#define MAX_MAC_SIZE 20 + +CSSM_RETURN buGenMac( + BU_KEY key, // any key, any size + CSSM_ALGORITHMS macAlg, // only CSSM_ALGID_SHA1HMAC for now + const CSSM_DATA *ptext, + unsigned *updateSizes, // NULL --> random updates + // else null-terminated list of sizes + CSSM_DATA_PTR mac) // mallocd and RETURNED +{ +#if 0 // NO MORE BSAFE + B_ALGORITHM_OBJ alg = NULL; + int brtn; + CSSM_RETURN crtn; + B_DIGEST_SPECIFIER digestInfo; + B_INFO_TYPE infoType; + unsigned macBytes; + + brtn = B_CreateAlgorithmObject(&alg); + if(brtn) { + return buBsafeErrToCssm(brtn, "B_CreateAlgorithmObject"); + } + switch(macAlg) { + case CSSM_ALGID_SHA1HMAC: + case CSSM_ALGID_SHA1HMAC_LEGACY: + digestInfo.digestInfoType = AI_SHA1; + infoType = AI_HMAC; + break; + default: + printf("buGenMac: alg not supported\n"); + return CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED; + } + digestInfo.digestInfoParams = NULL; + brtn = B_SetAlgorithmInfo(alg, infoType, (POINTER)&digestInfo); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo"); + goto abort; + } + brtn = B_DigestInit(alg, (B_KEY_OBJ)key, BSAFE_ALGORITHM_CHOOSER, NULL); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_DigestInit"); + goto abort; + } + if(updateSizes) { + uint8 *currData = ptext->Data; + while(*updateSizes) { + brtn = B_DigestUpdate(alg, currData, *updateSizes, NULL); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_DigestUpdate"); + goto abort; + } + currData += *updateSizes; + updateSizes++; + } + } + else { + /* one-shot */ + brtn = B_DigestUpdate(alg, ptext->Data, ptext->Length, NULL); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_DigestUpdate"); + goto abort; + } + } + /* prepare for mac, magically gleaned max size */ + macBytes = MAX_MAC_SIZE; + mac->Data = (uint8 *)CSSM_MALLOC(macBytes); + mac->Length = macBytes; + + brtn = B_DigestFinal(alg, mac->Data, &macBytes, macBytes, NULL); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_DigestFinal"); + goto abort; + } + mac->Length = macBytes; + crtn = CSSM_OK; +abort: + B_DestroyAlgorithmObject(&alg); + return crtn; +#endif + return 0; +} + +/* generate digest */ +#define MAX_DIGEST_SIZE 20 + +CSSM_RETURN buGenDigest( + CSSM_ALGORITHMS macAlg, // CSSM_ALGID_SHA1, etc. */ + const CSSM_DATA *ptext, + CSSM_DATA_PTR digest) // mallocd and RETURNED +{ +#if 0 // NO MORE BSAFE + B_ALGORITHM_OBJ alg = NULL; + int brtn; + CSSM_RETURN crtn; + B_INFO_TYPE infoType; + unsigned hashBytes; + + brtn = B_CreateAlgorithmObject(&alg); + if(brtn) { + return buBsafeErrToCssm(brtn, "B_CreateAlgorithmObject"); + } + switch(macAlg) { + case CSSM_ALGID_SHA1: + infoType = AI_SHA1; + break; + case CSSM_ALGID_MD5: + infoType = AI_MD5; + break; + case CSSM_ALGID_MD2: + infoType = AI_MD2; + break; + default: + printf("buGenDigest: alg not supported\n"); + return CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED; + } + brtn = B_SetAlgorithmInfo(alg, infoType, NULL); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_SetAlgorithmInfo"); + goto abort; + } + brtn = B_DigestInit(alg, NULL, BSAFE_ALGORITHM_CHOOSER, NULL); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_DigestInit"); + goto abort; + } + brtn = B_DigestUpdate(alg, ptext->Data, ptext->Length, NULL); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_DigestUpdate"); + goto abort; + } + + /* prepare for digest, magically gleaned max size */ + hashBytes = MAX_DIGEST_SIZE; + digest->Data = (uint8 *)CSSM_MALLOC(hashBytes); + digest->Length = hashBytes; + + brtn = B_DigestFinal(alg, digest->Data, &hashBytes, hashBytes, NULL); + if(brtn) { + crtn = buBsafeErrToCssm(brtn, "B_DigestFinal"); + goto abort; + } + digest->Length = hashBytes; + crtn = CSSM_OK; +abort: + B_DestroyAlgorithmObject(&alg); + return crtn; +#else + return 0; +#endif +} + +/* + * Convert between BSAFE and CDSA private keys + */ +CSSM_RETURN buBsafePrivKeyToCdsa( + CSSM_ALGORITHMS keyAlg, + uint32 keySizeInBits, + BU_KEY bsafePrivKey, + CSSM_KEY_PTR cdsaPrivKey) +{ +#if 0 // NO MORE BSAFE + B_INFO_TYPE infoType; + ITEM *keyBlob; + int brtn; + CSSM_KEYBLOB_FORMAT format; + CSSM_KEYHEADER_PTR hdr = &cdsaPrivKey->KeyHeader; + + /* what kind of info? */ + switch(keyAlg) { + case CSSM_ALGID_RSA: + infoType = KI_PKCS_RSAPrivateBER; + format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8; + break; + case CSSM_ALGID_DSA: + infoType = KI_DSAPrivateBER; + format = CSSM_KEYBLOB_RAW_FORMAT_FIPS186; + break; + default: + printf("***buBsafePrivKeyToCdsa: bogus keyAlg\n"); + return CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED; + } + + /* get the blob */ + brtn = B_GetKeyInfo((POINTER *)&keyBlob, + (B_KEY_OBJ)bsafePrivKey, + infoType); + if(brtn) { + return buBsafeErrToCssm(brtn, "B_GetKeyInfo"); + } + + /* copy blob to CDSA key */ + cdsaPrivKey->KeyData.Data = (uint8 *)CSSM_MALLOC(keyBlob->len); + cdsaPrivKey->KeyData.Length = keyBlob->len; + memmove(cdsaPrivKey->KeyData.Data, keyBlob->data, keyBlob->len); + + /* set up CSSM key header */ + memset(hdr, 0, sizeof(CSSM_KEYHEADER)); + hdr->HeaderVersion = CSSM_KEYHEADER_VERSION; + hdr->BlobType = CSSM_KEYBLOB_RAW; + hdr->Format = format; + hdr->AlgorithmId = keyAlg; + hdr->KeyClass = CSSM_KEYCLASS_PRIVATE_KEY; + hdr->LogicalKeySizeInBits = keySizeInBits; + hdr->KeyAttr = CSSM_KEYATTR_EXTRACTABLE; + hdr->KeyUsage = CSSM_KEYUSE_ANY; +#endif + return CSSM_OK; +} + +CSSM_RETURN buCdsaPrivKeyToBsafe( + CSSM_KEY_PTR cdsaPrivKey, + BU_KEY *bsafePrivKey) +{ +#if 0 // NO MORE BSAFE + int brtn; + B_KEY_OBJ privKey = NULL; + ITEM keyBlob; + B_INFO_TYPE infoType; + + /* what kind of info? */ + switch(cdsaPrivKey->KeyHeader.AlgorithmId) { + case CSSM_ALGID_RSA: + infoType = KI_PKCS_RSAPrivateBER; + break; + case CSSM_ALGID_DSA: + infoType = KI_DSAPrivateBER; + break; + default: + printf("***buCdsaPrivKeyToCssm: bogus keyAlg\n"); + return CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED; + } + + /* create caller's key, assign blob to it */ + brtn = B_CreateKeyObject(&privKey); + if(brtn) { + return buBsafeErrToCssm(brtn, "B_CreateKeyObject"); + } + buCssmDataToItem(&cdsaPrivKey->KeyData, &keyBlob); + brtn = B_SetKeyInfo(privKey, infoType, (POINTER)&keyBlob); + if(brtn) { + return buBsafeErrToCssm(brtn, "B_SetKeyInfo"); + } + *bsafePrivKey = privKey; +#endif + return CSSM_OK; +} + diff --git a/SecurityTests/cspxutils/utilLib/bsafeUtils.h b/SecurityTests/cspxutils/utilLib/bsafeUtils.h new file mode 100644 index 00000000..8ed52346 --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/bsafeUtils.h @@ -0,0 +1,109 @@ +/* + * bsafeUtils.h - common routines for CDSA/BSAFE compatibility testing + */ + +/* + * Clients of this module do not need to know about or see anything from the + * BSAFE headers. + */ +#ifndef _BSAFE_UTILS_H_ +#define _BSAFE_UTILS_H_ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Actually the same as a B_KEY_OBJ, but our callers don't need to know that */ +typedef void *BU_KEY; + +/* + * Create a symmetric key. + */ +CSSM_RETURN buGenSymKey( + uint32 keySizeInBits, + const CSSM_DATA *keyData, + BU_KEY *key); // RETURNED + +/* + * Create asymmetric key pair. + * FIXME - additional params (e.g. DSA params, RSA exponent)? + */ +CSSM_RETURN buGenKeyPair( + uint32 keySizeInBits, + CSSM_ALGORITHMS keyAlg, // CSSM_ALGID_{RSA,DSA} + BU_KEY *pubKey, // RETURNED + BU_KEY *privKey); // RETURNED + +/* + * Free a key created in buGenSymKey or buGenKeyPair + */ +CSSM_RETURN buFreeKey( + BU_KEY key); + +/* + * encrypt/decrypt + */ +CSSM_RETURN buEncryptDecrypt( + BU_KEY key, + CSSM_BOOL forEncrypt, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE mode, // CSSM_ALGMODE_CBC, etc. + const CSSM_DATA *iv, //Êoptional per mode + uint32 effectiveKeyBits, // optional per key alg (actually just RC2) + // for RSA, key size in bits + uint32 rounds, // optional, RC5 only + const CSSM_DATA *inData, + CSSM_DATA_PTR outData); // mallocd and RETURNED + +/* + * Sign/verify + */ +CSSM_RETURN buSign( + BU_KEY key, + CSSM_ALGORITHMS sigAlg, + const CSSM_DATA *ptext, + uint32 keySizeInBits, // to set up sig + CSSM_DATA_PTR sig); // mallocd and RETURNED + +CSSM_RETURN buVerify( + BU_KEY key, + CSSM_ALGORITHMS sigAlg, + const CSSM_DATA *ptext, + const CSSM_DATA *sig); // mallocd and RETURNED + +/* + * generate MAC either one update (updateSizes == NULL) or + * specified set of update sizes. + */ +CSSM_RETURN buGenMac( + BU_KEY key, // any key, any size + CSSM_ALGORITHMS macAlg, // only CSSM_ALGID_SHA1HMAC for now + const CSSM_DATA *ptext, + unsigned *updateSizes, // NULL --> random updates + // else null-terminated list of sizes + CSSM_DATA_PTR mac); // mallocd and RETURNED + +/* generate digest */ +CSSM_RETURN buGenDigest( + CSSM_ALGORITHMS macAlg, // CSSM_ALGID_SHA1, etc. */ + const CSSM_DATA *ptext, + CSSM_DATA_PTR digest); // mallocd and RETURNED + +/* + * Convert between BSAFE and CDSA private keys + */ +CSSM_RETURN buBsafePrivKeyToCdsa( + CSSM_ALGORITHMS keyAlg, + uint32 keySizeInBits, + BU_KEY bsafePrivKey, + CSSM_KEY_PTR cdsaPrivKey); +CSSM_RETURN buCdsaPrivKeyToBsafe( + CSSM_KEY_PTR cdsaPrivKey, + BU_KEY *bsafePrivKey); + +#ifdef __cplusplus +} +#endif + +#endif /* _BSAFE_UTILS_H_ */ diff --git a/SecurityTests/cspxutils/utilLib/common.c b/SecurityTests/cspxutils/utilLib/common.c new file mode 100644 index 00000000..5e337bef --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/common.c @@ -0,0 +1,624 @@ +/* Copyright (c) 1997,2003-2005,2008 Apple Inc. + * + * common.c - Common CSP test code + * + * Revision History + * ---------------- + * 4 May 2000 Doug Mitchell + * Ported to X/CDSA2. + * 6 Jul 1998 Doug Mitchell at Apple + * Added clStartup(). + * 12 Aug 1997 Doug Mitchell at Apple + * Created. + */ + +#include +#include +#include +#include +#include "common.h" +#include /* apple, not intel */ +#include + +static CSSM_VERSION vers = {2, 0}; +//const static uint32 guidPrefix = 0xFADE; +const CSSM_GUID testGuid = { 0xFADE, 0, 0, { 1,2,3,4,5,6,7,0 }}; + +/* + * We can't enable this until all of these are fixed and integrated: + * 2890978 CSP + * 2927474 CSPDL + * 2928357 TP + */ +#define DETECT_MALLOC_ABUSE 1 + +#if DETECT_MALLOC_ABUSE + +/* + * This set of allocator functions detects when we free something + * which was mallocd by CDSA or a plugin using something other than + * our callback malloc/realloc/calloc. With proper runtime support + * (which is present in Jaguar 6C35), the reverse is also detected + * by malloc (i.e., we malloc something and CDSA or a plugin frees + * it). + */ +#define APP_MALLOC_MAGIC 'Util' + +void * appMalloc (CSSM_SIZE size, void *allocRef) { + void *ptr; + + /* scribble magic number in first four bytes */ + ptr = malloc(size + 4); + *(uint32 *)ptr = APP_MALLOC_MAGIC; + ptr = (char *)ptr + 4; + + return ptr; +} + +void appFree (void *ptr, void *allocRef) { + if(ptr == NULL) { + return; + } + ptr = (char *)ptr - 4; + if(*(uint32 *)ptr != APP_MALLOC_MAGIC) { + printf("ERROR: appFree() freeing a block that we didn't allocate!\n"); + return; // this free is not safe + } + *(uint32 *)ptr = 0; + free(ptr); +} + +/* Realloc - adjust both original pointer and size */ +void * appRealloc (void *ptr, CSSM_SIZE size, void *allocRef) { + if(ptr == NULL) { + /* no ptr, no existing magic number */ + return appMalloc(size, allocRef); + } + ptr = (char *)ptr - 4; + if(*(uint32 *)ptr != APP_MALLOC_MAGIC) { + printf("ERROR: appRealloc() on a block that we didn't allocate!\n"); + } + *(uint32 *)ptr = 0; + ptr = realloc(ptr, size + 4); + *(uint32 *)ptr = APP_MALLOC_MAGIC; + ptr = (char *)ptr + 4; + return ptr; +} + +/* Have to do this manually */ +void * appCalloc (uint32 num, CSSM_SIZE size, void *allocRef) { + uint32 memSize = num * size; + + void *ptr = appMalloc(memSize, allocRef); + memset(ptr, 0, memSize); + return ptr; +} + +#else /* DETECT_MALLOC_ABUSE */ +/* + * Standard app-level memory functions required by CDSA. + */ +void * appMalloc (CSSM_SIZE size, void *allocRef) { + return( malloc(size) ); +} +void appFree (void *mem_ptr, void *allocRef) { + free(mem_ptr); + return; +} +void * appRealloc (void *ptr, CSSM_SIZE size, void *allocRef) { + return( realloc( ptr, size ) ); +} +void * appCalloc (uint32 num, CSSM_SIZE size, void *allocRef) { + return( calloc( num, size ) ); +} +#endif /* DETECT_MALLOC_ABUSE */ + +static CSSM_API_MEMORY_FUNCS memFuncs = { + appMalloc, + appFree, + appRealloc, + appCalloc, + NULL + }; + +/* + * Init CSSM; returns CSSM_FALSE on error. Reusable. + */ +static CSSM_BOOL cssmInitd = CSSM_FALSE; +CSSM_BOOL cssmStartup() +{ + CSSM_RETURN crtn; + CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE; + + if(cssmInitd) { + return CSSM_TRUE; + } + crtn = CSSM_Init (&vers, + CSSM_PRIVILEGE_SCOPE_NONE, + &testGuid, + CSSM_KEY_HIERARCHY_NONE, + &pvcPolicy, + NULL /* reserved */); + if(crtn != CSSM_OK) + { + printError("CSSM_Init", crtn); + return CSSM_FALSE; + } + else { + cssmInitd = CSSM_TRUE; + return CSSM_TRUE; + } +} + +/* + * Init CSSM and establish a session with the Apple CSP. + */ +CSSM_CSP_HANDLE cspStartup() +{ + return cspDlDbStartup(CSSM_TRUE, NULL); +} + +/* like cspStartup, but also returns DB handle. If incoming dbHandPtr + * is NULL, no DB startup. */ +CSSM_CSP_HANDLE cspDbStartup( + CSSM_DB_HANDLE *dbHandPtr) +{ + return cspDlDbStartup(CSSM_TRUE, NULL); +} + +CSSM_CSP_HANDLE cspDlDbStartup( + CSSM_BOOL bareCsp, // true ==> CSP, false ==> CSP/DL + CSSM_DB_HANDLE *dbHandPtr) // optional - TO BE DELETED +{ + CSSM_CSP_HANDLE cspHand; + CSSM_RETURN crtn; + const CSSM_GUID *guid; + char *modName; + + if(dbHandPtr) { + *dbHandPtr = 0; + } + if(cssmStartup() == CSSM_FALSE) { + return 0; + } + if(bareCsp) { + guid = &gGuidAppleCSP; + modName = (char*) "AppleCSP"; + } + else { + guid = &gGuidAppleCSPDL; + modName = (char *) "AppleCSPDL"; + } + crtn = CSSM_ModuleLoad(guid, + CSSM_KEY_HIERARCHY_NONE, + NULL, // eventHandler + NULL); // AppNotifyCallbackCtx + if(crtn) { + char outStr[100]; + sprintf(outStr, "CSSM_ModuleLoad(%s)", modName); + printError(outStr, crtn); + return 0; + } + crtn = CSSM_ModuleAttach (guid, + &vers, + &memFuncs, // memFuncs + 0, // SubserviceID + CSSM_SERVICE_CSP, + 0, // AttachFlags + CSSM_KEY_HIERARCHY_NONE, + NULL, // FunctionTable + 0, // NumFuncTable + NULL, // reserved + &cspHand); + if(crtn) { + char outStr[100]; + sprintf(outStr, "CSSM_ModuleAttach(%s)", modName); + printError(outStr, crtn); + return 0; + } + return cspHand; +} + +/* + * Detach and unload from a CSP. + */ +CSSM_RETURN cspShutdown( + CSSM_CSP_HANDLE cspHand, + CSSM_BOOL bareCsp) // true ==> CSP, false ==> CSP/DL +{ + CSSM_RETURN crtn; + const CSSM_GUID *guid; + char *modName; + + if(bareCsp) { + guid = &gGuidAppleCSP; + modName = (char *) "AppleCSP"; + } + else { + guid = &gGuidAppleCSPDL; + modName = (char *) "AppleCSPDL"; + } + crtn = CSSM_ModuleDetach(cspHand); + if(crtn) { + printf("Error detaching from %s\n", modName); + printError("CSSM_ModuleDetach", crtn); + return crtn; + } + crtn = CSSM_ModuleUnload(guid, NULL, NULL); + if(crtn) { + printf("Error unloading %s\n", modName); + printError("CSSM_ModuleUnload", crtn); + } + return crtn; +} + +/* Attach to DL side of CSPDL */ +CSSM_DL_HANDLE dlStartup() +{ + CSSM_DL_HANDLE dlHand = 0; + CSSM_RETURN crtn; + + if(cssmStartup() == CSSM_FALSE) { + return 0; + } + crtn = CSSM_ModuleLoad(&gGuidAppleCSPDL, + CSSM_KEY_HIERARCHY_NONE, + NULL, // eventHandler + NULL); // AppNotifyCallbackCtx + if(crtn) { + printError("CSSM_ModuleLoad(Apple CSPDL)", crtn); + return 0; + } + crtn = CSSM_ModuleAttach (&gGuidAppleCSPDL, + &vers, + &memFuncs, // memFuncs + 0, // SubserviceID + CSSM_SERVICE_DL, + 0, // AttachFlags + CSSM_KEY_HIERARCHY_NONE, + NULL, // FunctionTable + 0, // NumFuncTable + NULL, // reserved + &dlHand); + if(crtn) { + printError("CSSM_ModuleAttach(Apple CSPDL)", crtn); + return 0; + } + return dlHand; +} + +/* + * Delete a DB. + */ +#define DELETE_WITH_AUTHENT 0 +CSSM_RETURN dbDelete( + CSSM_DL_HANDLE dlHand, // from dlStartup() + const char *dbName) +{ + return CSSM_DL_DbDelete(dlHand, dbName, NULL, NULL); +} + +/* + * open a DB, ensure it's empty. + */ +CSSM_DB_HANDLE dbStartup( + CSSM_DL_HANDLE dlHand, // from dlStartup() + const char *dbName) +{ + CSSM_DB_HANDLE dbHand = 0; + + CSSM_RETURN crtn = dbCreateOpen(dlHand, dbName, + CSSM_TRUE, // create + CSSM_TRUE, // delete + NULL, // pwd + &dbHand); + if(crtn == CSSM_OK) { + return dbHand; + } + else { + return 0; + } +} + +#if 0 +/* + * Attach to existing DB or create an empty new one. + */ +CSSM_DB_HANDLE dbStartupByName(CSSM_DL_HANDLE dlHand, + char *dbName, + CSSM_BOOL doCreate) +{ + CSSM_RETURN crtn; + CSSM_DB_HANDLE dbHand; + + /* try to open existing DB in either case */ + + crtn = CSSM_DL_DbOpen(dlHand, + dbName, + NULL, // DbLocation + CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, + NULL, // CSSM_ACCESS_CREDENTIALS *AccessCred + NULL, // void *OpenParameters + &dbHand); + if(dbHand != 0) { + return dbHand; + } + if(!doCreate) { + printf("***no such data base (%s)\n", dbName); + printError("CSSM_DL_DbOpen", crtn); + return 0; + } + /* have to create one */ + return dbStartup(dlHand, dbName); +} +#endif + +/* + * routines which convert various types to untyped byte arrays. + */ +void intToBytes(unsigned i, unsigned char *buf) +{ + *buf++ = (unsigned char)((i >> 24) & 0xff); + *buf++ = (unsigned char)((i >> 16) & 0xff); + *buf++ = (unsigned char)((i >> 8) & 0xff); + *buf = (unsigned char)(i & 0xff); +} +void shortToBytes(unsigned short s, unsigned char *buf) +{ + *buf++ = (unsigned char)((s >> 8) & 0xff); + *buf = (unsigned char)(s & 0xff); +} +unsigned bytesToInt(const unsigned char *buf) { + unsigned result; + result = (((unsigned)buf[0] << 24) & 0xff000000) | + (((unsigned)buf[1] << 16) & 0x00ff0000) | + (((unsigned)buf[2] << 8) & 0xff00) | + (((unsigned)buf[3]) & 0xff); + return result; +} +unsigned short bytesToShort(const unsigned char *buf) { + unsigned short result; + result = (((unsigned short)buf[0] << 8) & 0xff00) | + (((unsigned short)buf[1]) & 0xff); + return result; +} + +/* + * Given a context specified via a CSSM_CC_HANDLE, add a new + * CSSM_CONTEXT_ATTRIBUTE to the context as specified by AttributeType, + * AttributeLength, and an untyped pointer. + * + * This is currently used to add a second CSSM_KEY attribute when performing + * ops with algorithm CSSM_ALGID_FEED and CSSM_ALGID_FEECFILE. + */ +CSSM_RETURN AddContextAttribute(CSSM_CC_HANDLE CCHandle, + uint32 AttributeType, + uint32 AttributeLength, + ContextAttrType attrType, + /* specify exactly one of these */ + const void *AttributePtr, + uint32 attributeInt) +{ + CSSM_CONTEXT_ATTRIBUTE newAttr; + CSSM_RETURN crtn; + + newAttr.AttributeType = AttributeType; + newAttr.AttributeLength = AttributeLength; + if(attrType == CAT_Uint32) { + newAttr.Attribute.Uint32 = attributeInt; + } + else { + newAttr.Attribute.Data = (CSSM_DATA_PTR)AttributePtr; + } + crtn = CSSM_UpdateContextAttributes(CCHandle, 1, &newAttr); + if(crtn) { + printError("CSSM_UpdateContextAttributes", crtn); + } + return crtn; +} + +/* + * Set up a CSSM data. + */ +CSSM_RETURN appSetupCssmData( + CSSM_DATA_PTR data, + uint32 numBytes) +{ + if(data == NULL) { + printf("Hey! appSetupCssmData with NULL Data!\n"); + return CSSMERR_CSSM_INTERNAL_ERROR; + } + data->Data = (uint8 *)CSSM_MALLOC(numBytes); + if(data->Data == NULL) { + return CSSMERR_CSSM_MEMORY_ERROR; + } + data->Length = numBytes; + return CSSM_OK; +} + +/* + * Free the data referenced by a CSSM data, and optionally, the struct itself. + */ +void appFreeCssmData(CSSM_DATA_PTR data, + CSSM_BOOL freeStruct) +{ + if(data == NULL) { + return; + } + if(data->Length != 0) { + CSSM_FREE(data->Data); + } + if(freeStruct) { + CSSM_FREE(data); + } + else { + data->Length = 0; + data->Data = NULL; + } +} + +/* + * Copy src to dst, mallocing dst. + */ +CSSM_RETURN appCopyCssmData(const CSSM_DATA *src, + CSSM_DATA_PTR dst) +{ + return appCopyData(src->Data, src->Length, dst); +} + +/* copy raw data to a CSSM_DATA, mallocing dst. */ +CSSM_RETURN appCopyData(const void *src, + uint32 len, + CSSM_DATA_PTR dst) +{ + dst->Length = 0; + if(len == 0) { + dst->Data = NULL; + return CSSM_OK; + } + dst->Data = (uint8 *)CSSM_MALLOC(len); + if(dst->Data == NULL) { + return CSSM_ERRCODE_MEMORY_ERROR; + } + dst->Length = len; + memcpy(dst->Data, src, len); + return CSSM_OK; +} + +CSSM_BOOL appCompareCssmData(const CSSM_DATA *d1, + const CSSM_DATA *d2) +{ + if(d1->Length != d2->Length) { + return CSSM_FALSE; + } + if(memcmp(d1->Data, d2->Data, d1->Length)) { + return CSSM_FALSE; + } + return CSSM_TRUE; +} + +/* min <= return <= max */ +unsigned genRand(unsigned min, unsigned max) +{ + unsigned i; + if(min == max) { + return min; + } + appGetRandomBytes(&i, 4); + return (min + (i % (max - min + 1))); +} + +void simpleGenData(CSSM_DATA_PTR dbuf, unsigned minBufSize, unsigned maxBufSize) +{ + unsigned len = genRand(minBufSize, maxBufSize); + appGetRandomBytes(dbuf->Data, len); + dbuf->Length = len; +} + +#define MIN_OFFSET 0 +#define MAX_OFFSET 99 +#define MIN_ASCII 'a' +#define MAX_ASCII 'z' + +/* + * Calculate random data size, fill dataPool with that many random bytes. + * + * (10**minExp + MIN_OFFSET) <= size <= (10**maxExp + MAX_OFFSET) + */ +unsigned genData(unsigned char *dataPool, + unsigned minExp, + unsigned maxExp, + dataType type) +{ + int exp; + int offset; + int size; + char *cp; + int i; + char ac; + + /* + * Calculate "random" size : (10 ** (random exponent)) + random offset + */ + exp = genRand(minExp, maxExp); + offset = genRand(MIN_OFFSET, MAX_OFFSET); + size = 1; + while(exp--) { // size = 10 ** exp + size *= 10; + } + size += offset; + switch(type) { + case DT_Zero: + bzero(dataPool, size); + break; + case DT_Increment: + { + int i; + for(i=0; i MAX_ASCII) { + ac = MIN_ASCII; + } + } + break; + case DT_Random: + appGetRandomBytes(dataPool, size); + break; + } + return size; +} + +void dumpBuffer( + const char *bufName, // optional + unsigned char *buf, + unsigned len) +{ + unsigned i; + + if(bufName) { + printf("%s\n", bufName); + } + printf(" "); + for(i=0; i + +#ifdef __cplusplus +extern "C" { +#endif + +#undef COMMON_CSSM_MEMORY +#define COMMON_CSSM_MEMORY 0 + +#if COMMON_CSSM_MEMORY +#define CSSM_MALLOC(size) CSSM_Malloc(size) +#define CSSM_FREE(ptr) CSSM_Free(ptr) +#define CSSM_CALLOC(num, size) CSSM_Calloc(num, size) +#define CSSM_REALLOC(ptr, newSize) CSSM_Realloc(ptr, newSize) +/* used in cspwrap when allocating memory on app's behalf */ +#define appMalloc(size, allocRef) CSSM_Malloc(size) + +#else /* !COMMON_CSSM_MEMORY */ + +void * appMalloc (CSSM_SIZE size, void *allocRef); +void appFree (void *mem_ptr, void *allocRef); +void * appRealloc (void *ptr, CSSM_SIZE size, void *allocRef); +void * appCalloc (uint32 num, CSSM_SIZE size, void *allocRef); + +#define CSSM_MALLOC(size) appMalloc(size, NULL) +#define CSSM_FREE(ptr) appFree(ptr, NULL) +#define CSSM_CALLOC(num, size) appCalloc(num, size, NULL) +#define CSSM_REALLOC(ptr, newSize) appRealloc(ptr, newSize, NULL) + +#endif /* COMMON_CSSM_MEMORY */ + +/* + * As of 23 March 1999, there is no longer a "default DB" available for + * generating keys. This is the standard DB handle created when + * calling cspStartup(). + */ +extern CSSM_DB_HANDLE commonDb; + +/* + * Init CSSM; returns CSSM_FALSE on error. Reusable. + */ +extern CSSM_BOOL cssmStartup(); + +/* various flavors of "start up the CSP with optional DB open" */ +CSSM_CSP_HANDLE cspStartup(); // bare bones CSP +CSSM_CSP_HANDLE cspDbStartup( // bare bones CSP, DB open + CSSM_DB_HANDLE *dbHandPtr); +CSSM_DL_HANDLE dlStartup(); +CSSM_CSP_HANDLE cspDlDbStartup( // one size fits all + CSSM_BOOL bareCsp, // true ==> CSP, false ==> CSP/DL + CSSM_DB_HANDLE *dbHandPtr); // optional +CSSM_RETURN cspShutdown( + CSSM_CSP_HANDLE cspHand, + CSSM_BOOL bareCsp); // true ==> CSP, false ==> CSP/DL +CSSM_RETURN dbDelete( + CSSM_DL_HANDLE dlHand, // from dlStartup() + const char *dbName); +CSSM_DB_HANDLE dbStartup( + CSSM_DL_HANDLE dlHand, // from dlStartup() + const char *dbName); +CSSM_RETURN dbCreateOpen( + CSSM_DL_HANDLE dlHand, // from dlStartup() + const char *dbName, + CSSM_BOOL doCreate, // if false, must already exist + CSSM_BOOL deleteExist, + const char *pwd, // optional + CSSM_DB_HANDLE *dbHand); + +extern void intToBytes(unsigned i, unsigned char *buf); +void shortToBytes(unsigned short s, unsigned char *buf); +unsigned bytesToInt(const unsigned char *buf); +unsigned short bytesToShort(const unsigned char *buf); + +/* specify either 32-bit integer or a pointer as an added attribute value */ +typedef enum { + CAT_Uint32, + CAT_Ptr +} ContextAttrType; + +CSSM_RETURN AddContextAttribute(CSSM_CC_HANDLE CCHandle, + uint32 AttributeType, + uint32 AttributeLength, + ContextAttrType attrType, + /* specify exactly one of these */ + const void *AttributePtr, + uint32 attributeInt); +void printError(const char *op, CSSM_RETURN err); +CSSM_RETURN appSetupCssmData( + CSSM_DATA_PTR data, + uint32 numBytes); +void appFreeCssmData(CSSM_DATA_PTR data, + CSSM_BOOL freeStruct); +CSSM_RETURN appCopyCssmData(const CSSM_DATA *src, + CSSM_DATA_PTR dst); +/* copy raw data to a CSSM_DATAm mallocing dst. */ +CSSM_RETURN appCopyData(const void *src, + uint32 len, + CSSM_DATA_PTR dst); + +/* returns CSSM_TRUE on success, else CSSM_FALSE */ +CSSM_BOOL appCompareCssmData(const CSSM_DATA *d1, + const CSSM_DATA *d2); + +const char *cssmErrToStr(CSSM_RETURN err); + +/* + * Calculate random data size, fill dataPool with that many random bytes. + */ +typedef enum { + DT_Random, + DT_Increment, + DT_Zero, + DT_ASCII +} dataType; + +unsigned genData(unsigned char *dataPool, + unsigned minExp, + unsigned maxExp, + dataType type); +void simpleGenData(CSSM_DATA_PTR dbuf, unsigned minBufSize, unsigned maxBufSize); +unsigned genRand(unsigned min, unsigned max); +extern void appGetRandomBytes(void *buf, unsigned len); + +void dumpBuffer( + const char *bufName, // optional + unsigned char *buf, + unsigned len); + +int testError(CSSM_BOOL quiet); + +void testStartBanner( + const char *testName, + int argc, + char **argv); + +#ifdef __cplusplus +} + +#endif +#endif /* _UTIL_LIB_COMMON_H_*/ + + diff --git a/SecurityTests/cspxutils/utilLib/commonCpp.cpp b/SecurityTests/cspxutils/utilLib/commonCpp.cpp new file mode 100644 index 00000000..f53415a5 --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/commonCpp.cpp @@ -0,0 +1,160 @@ +// +// throw C++-dependent stuff in here +// +#include +#include +#include "common.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "cssmErrorStrings.h" /* generated error string table */ + +/* + * Log CSSM error. + */ +void printError(const char *op, CSSM_RETURN err) +{ + cssmPerror(op, err); +} + +const char *cssmErrToStr(CSSM_RETURN err) +{ + const ErrString *esp; + + for(esp=errStrings; esp->errStr!=NULL; esp++) { + if(esp->errCode == err) { + return esp->errStr; + } + } + + static char outbuf[512]; + sprintf(outbuf, "UNKNOWN ERROR CODE %d", (int)err); + return outbuf; +} + + +/* + * Open a DB, optionally: + * + * -- ensuring it's empty + * -- creating it + * -- Specifying optional password to avoid SecurityAgent UI. + */ +CSSM_RETURN dbCreateOpen( + CSSM_DL_HANDLE dlHand, // from dlStartup() + const char *dbName, + CSSM_BOOL doCreate, // if false, must already exist + CSSM_BOOL deleteExist, + const char *pwd, // optional + CSSM_DB_HANDLE *dbHand) +{ + CSSM_RETURN crtn; + CSSM_DBINFO dbInfo; + + if(deleteExist) { + /* first delete possible existing DB, ignore error */ + crtn = dbDelete(dlHand, dbName); + switch(crtn) { + /* only allowed error is "no such file" */ + case CSSM_OK: + case CSSMERR_DL_DATASTORE_DOESNOT_EXIST: + break; + default: + printError("CSSM_DL_DbDelete", crtn); + return crtn; + } + if(!doCreate) { + printf("***Hey! dbCreateOpen with deleteExist and !doCreate\n"); + exit(1); + } + } + else { + /* + * Try to open existing DB. This does not have a means + * to specify password (yet). + */ + crtn = CSSM_DL_DbOpen(dlHand, + dbName, + NULL, // DbLocation + CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, + NULL, // CSSM_ACCESS_CREDENTIALS *AccessCred + NULL, // void *OpenParameters + dbHand); + if(crtn == CSSM_OK) { + return crtn; + } + if(!doCreate) { + printError("CSSM_DL_DbOpen", crtn); + printf("Error opening %s\n", dbName); + return crtn; + } + } + memset(&dbInfo, 0, sizeof(CSSM_DBINFO)); + + /* now create it */ + if(pwd) { + /* + * This glorious code copied from crlRefresh. I didn't pretend + * to understand it when I put it there either. + */ + Allocator &alloc = Allocator::standard(); + CssmClient::AclFactory::PasswordChangeCredentials + pCreds((StringData(pwd)), alloc); + const AccessCredentials* aa = pCreds; + TypedList subject(alloc, CSSM_ACL_SUBJECT_TYPE_ANY); + AclEntryPrototype protoType(subject); + AuthorizationGroup &authGroup = protoType.authorization(); + CSSM_ACL_AUTHORIZATION_TAG tag = CSSM_ACL_AUTHORIZATION_ANY; + authGroup.NumberOfAuthTags = 1; + authGroup.AuthTags = &tag; + + const ResourceControlContext rcc(protoType, + const_cast(aa)); + + crtn = CSSM_DL_DbCreate(dlHand, + dbName, + NULL, // DbLocation + &dbInfo, + // &Security::KeychainCore::Schema::DBInfo, + CSSM_DB_ACCESS_PRIVILEGED, + &rcc, // CredAndAclEntry + NULL, // OpenParameters + dbHand); + } + else { + crtn = CSSM_DL_DbCreate(dlHand, + dbName, + NULL, // DbLocation + &dbInfo, + // &Security::KeychainCore::Schema::DBInfo, + CSSM_DB_ACCESS_PRIVILEGED, + NULL, // CredAndAclEntry + NULL, // OpenParameters + dbHand); + } + if(crtn) { + printError("CSSM_DL_DbCreate", crtn); + } + return crtn; +} + +/* + * *The* way for all tests to get random data. + */ +void appGetRandomBytes(void *buf, unsigned len) +{ + try { + Security::DevRandomGenerator devRand(false); + devRand.random(buf, len); + } + catch(...) { + printf("***Hey! DevRandomGenerator threw an exception!\n"); + /* Yes, exit - I'd really like to catch one of these */ + exit(1); + } +} diff --git a/SecurityTests/cspxutils/utilLib/cputime.c b/SecurityTests/cspxutils/utilLib/cputime.c new file mode 100644 index 00000000..0238f048 --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/cputime.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include "cputime.h" + +/* + * This returns the frequency of the TBR in cycles per second. + */ +static double GetTBRFreq(void) { + mach_timebase_info_data_t tinfo; + mach_timebase_info(&tinfo); + + double machRatio = (double)tinfo.numer / (double)tinfo.denom; + return machRatio; +} + +/* + * Return TBR Frequency, getting it lazily once. May not be thread safe. + */ +static double TbrFreqLocal = 0.0; // ration for NANOSECONDS +static double tbrFreq() +{ + if(TbrFreqLocal == 0.0) { + TbrFreqLocal = GetTBRFreq(); + printf("machRatio %e\n", TbrFreqLocal); + } + return TbrFreqLocal; +} + +// seconds +double CPUTimeDeltaSec(CPUTime from, CPUTime to) +{ + CPUTime delta = to - from; + return (double)delta * (tbrFreq() * (double)1e-9); +} + +// milliseconds +double CPUTimeDeltaMs(CPUTime from, CPUTime to) +{ + CPUTime delta = to - from; + return (double)delta * (tbrFreq() * (double)1e-6); +} + +// microseconds +double CPUTimeDeltaUs(CPUTime from, CPUTime to) +{ + CPUTime delta = to - from; + return (double)delta * (tbrFreq() * (double)1e-3); +} + +/* + * Calculate the average of an array of doubles. The lowest and highest values + * are discarded if there are more than two samples. Typically used to get an + * average of a set of values returned from CPUTimeDelta*(). + */ +double CPUTimeAvg( + const double *array, + unsigned arraySize) +{ + double sum = 0; + double lowest = array[0]; + double highest = array[0]; + + for(unsigned dex=0; dex highest) { + highest = curr; + } + } + if(arraySize > 2) { + sum -= lowest; + sum -= highest; + arraySize -= 2; + } + return sum / (double)arraySize; +} diff --git a/SecurityTests/cspxutils/utilLib/cputime.h b/SecurityTests/cspxutils/utilLib/cputime.h new file mode 100644 index 00000000..5bc08c46 --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/cputime.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please + * obtain a copy of the License at http://www.apple.com/publicsource and + * read it before using this file. + * + * This 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. + */ + +/* + * cputime.h - high resolution timing module + * + * This module uses a highly machine-dependent mechanism to get timestamps + * directly from CPU registers, without the overhead of a system call. The + * timestamps are exported as type CPUTime and you should not concern yourself + * with exactly what that is. + * + * We provide routines to convert a difference between two CPUTimes as a double, + * in seconds, milliseconds, and microseconds. Th + * + * The cost (time) of getting a timestamp (via CPUTimeRead()) generally takes + * two or fewer times the resolution period, i.e., less than 80 ns on a 100 MHz + * bus machine, often 40 ns. + * + * The general usage of this module is as follows: + * + * { + * set up test scenario; + * CPUTime startTime = CPUTimeRead(); + * ...critical timed code here... + * CPUTime endTime = CPUTimeRead(); + * double elapsedMilliseconds = CPUTimeDeltaMs(startTime, endTime); + * } + * + * It's crucial to place the CPUTimeDelta*() call OUTSIDE of the critical timed + * area. It's really cheap to snag the timestamps, but it's not at all cheap + * to convert the difference between two timestamps to a double. + */ + +#ifndef _CPUTIME_H_ +#define _CPUTIME_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + + +typedef uint64_t CPUTime; + +/* + * Obtain machine-dependent, high resolution, cheap-to-read timestamp. + */ +#define CPUTimeRead() mach_absolute_time() + +/* + * Convert difference between two CPUTimes into various units. + * Implemented as separate functions to preserve as much precision as possible + * before required machine-dependent "divide by clock frequency". + */ +extern double CPUTimeDeltaSec(CPUTime from, CPUTime to); // seconds +extern double CPUTimeDeltaMs(CPUTime from, CPUTime to); // milliseconds +extern double CPUTimeDeltaUs(CPUTime from, CPUTime to); // microseconds + +/* + * Calculate the average of an array of doubles. The lowest and highest values + * are discarded if there are more than two samples. Typically used to get an + * average of a set of values returned from CPUTimeDelta*(). + */ +double CPUTimeAvg( + const double *array, + unsigned arraySize); + +#ifdef __cplusplus +} +#endif + +#endif /* _CPUTIME_H_ */ + diff --git a/SecurityTests/cspxutils/utilLib/cspdlTesting.h b/SecurityTests/cspxutils/utilLib/cspdlTesting.h new file mode 100755 index 00000000..4020528b --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/cspdlTesting.h @@ -0,0 +1,100 @@ +/* + * cspdlTesting.h - workaround flags for testing CSPDL using CSP-oriented tests. + */ + +#ifndef _CSPDL_TESTING_H_ +#define _CSPDL_TESTING_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * All generated keys must be reference keys. + */ +#define CSPDL_ALL_KEYS_ARE_REF 1 + +/* + * 2nd/public key in two-key FEE ops must be raw. This is because the Security + * Server doesn't go in and deal with ref keys which are only found in a + * Context. + */ +#define CSPDL_2ND_PUB_KEY_IS_RAW 1 + +/* + * Ease off on restriction of ptext size == ctext size in case of symmetric + * en/decrypt with no padding. The sizes will be equal, but we can't ensure + * that by mallocing exactly the right amount after because CSPDL doesn't + * give an exact (proper) outputSize in this case (yet). + */ +#define CSPDL_NOPAD_ENFORCE_SIZE 1 + +/* + * CSPDL can't do SHA1HMAC_LEGACY with bug-for-bug compatibility with + * BSAFE (sinceÊthe bug-for-bug feature involves doing actual HMAC updates + * exactly as the app presents them). + */ +#define CSPDL_SHA1HMAC_LEGACY_ENABLE 0 + +/* + * CSPDL does not support DSA GenerateAlgorithmParameters. Let the secure CSP + * do it implicitly during key gen. + */ +#define CSPDL_DSA_GEN_PARAMS 0 + +/* + * Can't generate keys with CSSM_KEYATTR_PRIVATE. Is this a bug or a feature? + * Nobody pays any attention to this except the CSP, which rejects it. Shouldn't + * either CSPDL or SS look at this and strip it off before sending the request + * down to the CSP? + */ +#define CSPDL_KEYATTR_PRIVATE 0 + +/* + * ObtainPrivateKeyFromPublic key not implemented yet (if ever). + */ +#define CSPDL_OBTAIN_PRIV_FROM_PUB 0 + +/*** Workarounds for badattr test only ***/ + +/* + * Munged header fields in a ref key should result in CSP_INVALID_KEY_REFERENCE, + * but work fine. + */ +#define CSPDL_MUNGE_HEADER_CHECK 0 + +/* + * ALWAYS_SENSITIVE, NEVER_EXTRACTABLE are ignored, should result in + * CSP_INVALID_KEYATTR_MASK at key gen time. + * FIXED per Radar 2879872. + */ +#define CSPDL_ALWAYS_SENSITIVE_CHECK 1 +#define CSPDL_NEVER_EXTRACTABLE_CHECK 1 + +/*** end of badattr workarounds ***/ + +/* + * certtool can't generate keypair + * + * Until this is fixed - actually the underlying problem is in securityd - + * CSPDL can not generate a key pair without private and public both being + * PERMANENT. + */ +#define CSPDL_ALL_KEYS_ARE_PERMANENT 0 + + +/*** + *** Other differences/bugs/oddities. + ***/ + +/* + * 1. SS wraps (encrypt) public keys when encoding them, thus the CSP has to allow + * wrapping of public keys. This may not be what we really want. See + * AppleCSP/AppleCSP/wrapKey.cpp for workaround per ALLOW_PUB_KEY_WRAP. + */ + +#ifdef __cplusplus +} +#endif + +#endif /* _CSPDL_TESTING_H_ */ diff --git a/SecurityTests/cspxutils/utilLib/cspwrap.c b/SecurityTests/cspxutils/utilLib/cspwrap.c new file mode 100644 index 00000000..0a86659e --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/cspwrap.c @@ -0,0 +1,3279 @@ +/* Copyright (c) 1997,2003-2006,2008,2010,2013 Apple Inc. + * + * cspwrap.c - wrappers to simplify access to CDSA + * + * Revision History + * ---------------- + * 3 May 2000 Doug Mitchell + * Ported to X/CDSA2. + * 12 Aug 1997 Doug Mitchell at Apple + * Created. + */ + +#include +#include +#include "cspwrap.h" +#include "common.h" +#include +#include +#include +/* MCF hack */ +// #include +#include +/* end MCF */ + +#ifndef NULL +#define NULL ((void *)0) +#endif /* NULL */ +#ifndef MAX +#define MAX(a,b) ((a > b) ? a : b) +#define MIN(a,b) ((a < b) ? a : b) +#endif + +#pragma mark --------- Key Generation --------- + +/* + * Key generation + */ +#define FEE_PRIV_DATA_SIZE 20 +/* + * Debug/test only. BsafeCSP only (long since disabled, in Puma). + * This results in quicker but less secure RSA key generation. + */ +#define RSA_WEAK_KEYS 0 + +/* + * Force bad data in KeyData prior to generating, deriving, or + * wrapping key to ensure that the CSP ignores incoming + * KeyData. + */ +static void setBadKeyData( + CSSM_KEY_PTR key) +{ + key->KeyData.Data = (uint8 *)0xeaaaeaaa; // bad ptr + key->KeyData.Length = 1; // no key can fit here +} + +/* + * Generate key pair of arbitrary algorithm. + * FEE keys will have random private data. + */ +CSSM_RETURN cspGenKeyPair(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, + const char *keyLabel, + unsigned keyLabelLen, + uint32 keySize, // in bits + CSSM_KEY_PTR pubKey, // mallocd by caller + CSSM_BOOL pubIsRef, // true - reference key, false - data + uint32 pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + CSSM_KEYBLOB_FORMAT pubFormat, // Optional. Specify 0 or CSSM_KEYBLOB_RAW_FORMAT_NONE + // to get the default format. + CSSM_KEY_PTR privKey, // mallocd by caller + CSSM_BOOL privIsRef, // true - reference key, false - data + uint32 privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc. + CSSM_KEYBLOB_FORMAT privFormat, // optional 0 ==> default + CSSM_BOOL genSeed) // FEE only. True: we generate seed and CSP + // will hash it. False: CSP generates random + // seed. +{ + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + CSSM_DATA privData = {0, NULL}; // mallocd for FEE + CSSM_CRYPTO_DATA privCData; + CSSM_CRYPTO_DATA_PTR privCDataPtr = NULL; + CSSM_DATA keyLabelData; + uint32 pubAttr; + uint32 privAttr; + CSSM_RETURN ocrtn = CSSM_OK; + + if(keySize == CSP_KEY_SIZE_DEFAULT) { + keySize = cspDefaultKeySize(algorithm); + } + + /* pre-context-create algorithm-specific stuff */ + switch(algorithm) { + case CSSM_ALGID_FEE: + if(genSeed) { + /* cook up random privData */ + privData.Data = (uint8 *)CSSM_MALLOC(FEE_PRIV_DATA_SIZE); + privData.Length = FEE_PRIV_DATA_SIZE; + appGetRandomBytes(privData.Data, FEE_PRIV_DATA_SIZE); + privCData.Param = privData; + privCData.Callback = NULL; + privCDataPtr = &privCData; + } + /* else CSP generates random seed/key */ + break; + case CSSM_ALGID_RSA: + break; + case CSSM_ALGID_DSA: + break; + case CSSM_ALGID_ECDSA: + break; + default: + printf("cspGenKeyPair: Unknown algorithm\n"); + /* but what the hey */ + privCDataPtr = NULL; + break; + } + keyLabelData.Data = (uint8 *)keyLabel, + keyLabelData.Length = keyLabelLen; + memset(pubKey, 0, sizeof(CSSM_KEY)); + memset(privKey, 0, sizeof(CSSM_KEY)); + setBadKeyData(pubKey); + setBadKeyData(privKey); + + crtn = CSSM_CSP_CreateKeyGenContext(cspHand, + algorithm, + keySize, + privCDataPtr, // Seed + NULL, // Salt + NULL, // StartDate + NULL, // EndDate + NULL, // Params + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateKeyGenContext", crtn); + ocrtn = crtn; + goto abort; + } + /* cook up attribute bits */ + if(pubIsRef) { + pubAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; + } + else { + pubAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + } + if(privIsRef) { + privAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; + } + else { + privAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + } + + /* post-context-create algorithm-specific stuff */ + switch(algorithm) { + case CSSM_ALGID_RSA: + + #if RSA_WEAK_KEYS + { + /* for testing, speed up key gen by using the + * undocumented "CUSTOM" key gen mode. This + * results in the CSP using AI_RsaKeyGen instead of + * AI_RSAStrongKeyGen. + */ + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_MODE, + sizeof(uint32), + CAT_Uint32, + NULL, + CSSM_ALGMODE_CUSTOM); + if(crtn) { + printError("CSSM_UpdateContextAttributes", crtn); + return crtn; + } + } + #endif // RSA_WEAK_KEYS + break; + + case CSSM_ALGID_DSA: + /* + * extra step - generate params - this just adds some + * info to the context + */ + { + CSSM_DATA dummy = {0, NULL}; + crtn = CSSM_GenerateAlgorithmParams(ccHand, + keySize, &dummy); + if(crtn) { + printError("CSSM_GenerateAlgorithmParams", crtn); + return crtn; + } + appFreeCssmData(&dummy, CSSM_FALSE); + } + break; + default: + break; + } + + /* optional format specifiers */ + if(!pubIsRef && (pubFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE)) { + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT, + sizeof(uint32), + CAT_Uint32, + NULL, + pubFormat); + if(crtn) { + printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn); + return crtn; + } + } + if(!privIsRef && (privFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE)) { + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT, + sizeof(uint32), // currently sizeof CSSM_DATA + CAT_Uint32, + NULL, + privFormat); + if(crtn) { + printError("AddContextAttribute(CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT)", crtn); + return crtn; + } + } + crtn = CSSM_GenerateKeyPair(ccHand, + pubKeyUsage, + pubAttr, + &keyLabelData, + pubKey, + privKeyUsage, + privAttr, + &keyLabelData, // same labels + NULL, // CredAndAclEntry + privKey); + if(crtn) { + printError("CSSM_GenerateKeyPair", crtn); + ocrtn = crtn; + goto abort; + } + /* basic checks...*/ + if(privIsRef) { + if(privKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) { + printf("privKey blob type: exp %u got %u\n", + CSSM_KEYBLOB_REFERENCE, (unsigned)privKey->KeyHeader.BlobType); + ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; + goto abort; + } + } + else { + switch(privKey->KeyHeader.BlobType) { + case CSSM_KEYBLOB_RAW: + break; + default: + printf("privKey blob type: exp raw, got %u\n", + (unsigned)privKey->KeyHeader.BlobType); + ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; + goto abort; + } + } + if(pubIsRef) { + if(pubKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) { + printf("pubKey blob type: exp %u got %u\n", + CSSM_KEYBLOB_REFERENCE, (unsigned)pubKey->KeyHeader.BlobType); + ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; + goto abort; + } + } + else { + switch(pubKey->KeyHeader.BlobType) { + case CSSM_KEYBLOB_RAW: + break; + default: + printf("pubKey blob type: exp raw or raw_berder, got %u\n", + (unsigned)pubKey->KeyHeader.BlobType); + ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; + goto abort; + } + } +abort: + if(ccHand != 0) { + crtn = CSSM_DeleteContext(ccHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; + } + } + if(privData.Data != NULL) { + CSSM_FREE(privData.Data); + } + return ocrtn; +} + +/* + * Generate FEE key pair with optional primeType, curveType, and seed (password) data. + */ +CSSM_RETURN cspGenFEEKeyPair(CSSM_CSP_HANDLE cspHand, + const char *keyLabel, + unsigned keyLabelLen, + uint32 keySize, // in bits + uint32 primeType, // CSSM_FEE_PRIME_TYPE_MERSENNE, etc. + uint32 curveType, // CSSM_FEE_CURVE_TYPE_MONTGOMERY, etc. + CSSM_KEY_PTR pubKey, // mallocd by caller + CSSM_BOOL pubIsRef, // true - reference key, false - data + uint32 pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + CSSM_KEYBLOB_FORMAT pubFormat, // Optional. Specify 0 or CSSM_KEYBLOB_RAW_FORMAT_NONE + // to get the default format. + CSSM_KEY_PTR privKey, // mallocd by caller + CSSM_BOOL privIsRef, // true - reference key, false - data + uint32 privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc. + CSSM_KEYBLOB_FORMAT privFormat, // optional 0 ==> default + const CSSM_DATA *seedData) // Present: CSP will hash this for private data. + // NULL: CSP generates random seed. +{ + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + CSSM_CRYPTO_DATA privCData; + CSSM_CRYPTO_DATA_PTR privCDataPtr = NULL; + CSSM_DATA keyLabelData; + uint32 pubAttr; + uint32 privAttr; + CSSM_RETURN ocrtn = CSSM_OK; + + /* pre-context-create algorithm-specific stuff */ + if(seedData) { + privCData.Param = *((CSSM_DATA_PTR)seedData); + privCData.Callback = NULL; + privCDataPtr = &privCData; + } + /* else CSP generates random seed/key */ + + if(keySize == CSP_KEY_SIZE_DEFAULT) { + keySize = CSP_FEE_KEY_SIZE_DEFAULT; + } + + keyLabelData.Data = (uint8 *)keyLabel, + keyLabelData.Length = keyLabelLen; + memset(pubKey, 0, sizeof(CSSM_KEY)); + memset(privKey, 0, sizeof(CSSM_KEY)); + setBadKeyData(pubKey); + setBadKeyData(privKey); + + crtn = CSSM_CSP_CreateKeyGenContext(cspHand, + CSSM_ALGID_FEE, + keySize, + privCDataPtr, // Seed + NULL, // Salt + NULL, // StartDate + NULL, // EndDate + NULL, // Params + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateKeyGenContext", crtn); + ocrtn = crtn; + goto abort; + } + /* cook up attribute bits */ + if(pubIsRef) { + pubAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; + } + else { + pubAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + } + if(privIsRef) { + privAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; + } + else { + privAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + } + + /* optional post-context-create stuff */ + if(primeType != CSSM_FEE_PRIME_TYPE_DEFAULT) { + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_FEE_PRIME_TYPE, + sizeof(uint32), + CAT_Uint32, + NULL, + primeType); + if(crtn) { + printError("AddContextAttribute(CSSM_ATTRIBUTE_FEE_PRIME_TYPE)", crtn); + return crtn; + } + } + if(curveType != CSSM_FEE_CURVE_TYPE_DEFAULT) { + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_FEE_CURVE_TYPE, + sizeof(uint32), + CAT_Uint32, + NULL, + curveType); + if(crtn) { + printError("AddContextAttribute(CSSM_ATTRIBUTE_FEE_CURVE_TYPE)", crtn); + return crtn; + } + } + + if(pubFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE) { + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT, + sizeof(uint32), + CAT_Uint32, + NULL, + pubFormat); + if(crtn) { + printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn); + return crtn; + } + } + if(privFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE) { + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT, + sizeof(uint32), // currently sizeof CSSM_DATA + CAT_Uint32, + NULL, + pubFormat); + if(crtn) { + printError("AddContextAttribute(CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT)", crtn); + return crtn; + } + } + crtn = CSSM_GenerateKeyPair(ccHand, + pubKeyUsage, + pubAttr, + &keyLabelData, + pubKey, + privKeyUsage, + privAttr, + &keyLabelData, // same labels + NULL, // CredAndAclEntry + privKey); + if(crtn) { + printError("CSSM_GenerateKeyPair", crtn); + ocrtn = crtn; + goto abort; + } + /* basic checks...*/ + if(privIsRef) { + if(privKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) { + printf("privKey blob type: exp %u got %u\n", + CSSM_KEYBLOB_REFERENCE, (unsigned)privKey->KeyHeader.BlobType); + ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; + goto abort; + } + } + else { + switch(privKey->KeyHeader.BlobType) { + case CSSM_KEYBLOB_RAW: + break; + default: + printf("privKey blob type: exp raw, got %u\n", + (unsigned)privKey->KeyHeader.BlobType); + ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; + goto abort; + } + } + if(pubIsRef) { + if(pubKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) { + printf("pubKey blob type: exp %u got %u\n", + CSSM_KEYBLOB_REFERENCE, (unsigned)pubKey->KeyHeader.BlobType); + ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; + goto abort; + } + } + else { + switch(pubKey->KeyHeader.BlobType) { + case CSSM_KEYBLOB_RAW: + break; + default: + printf("pubKey blob type: exp raw or raw_berder, got %u\n", + (unsigned)pubKey->KeyHeader.BlobType); + ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; + goto abort; + } + } +abort: + if(ccHand != 0) { + crtn = CSSM_DeleteContext(ccHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; + } + } + return ocrtn; +} + +/* + * Generate DSA key pair with optional generateAlgParams and optional + * incoming parameters. + */ +CSSM_RETURN cspGenDSAKeyPair(CSSM_CSP_HANDLE cspHand, + const char *keyLabel, + unsigned keyLabelLen, + uint32 keySize, // in bits + CSSM_KEY_PTR pubKey, // mallocd by caller + CSSM_BOOL pubIsRef, // true - reference key, false - data + uint32 pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + CSSM_KEYBLOB_FORMAT pubFormat, // Optional. Specify 0 or CSSM_KEYBLOB_RAW_FORMAT_NONE + // to get the default format. + CSSM_KEY_PTR privKey, // mallocd by caller + CSSM_BOOL privIsRef, // true - reference key, false - data + uint32 privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc. + CSSM_KEYBLOB_FORMAT privFormat, // Optional. Specify 0 or CSSM_KEYBLOB_RAW_FORMAT_NONE + // to get the default format. + CSSM_BOOL genParams, + CSSM_DATA_PTR paramData) // optional +{ + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + CSSM_DATA keyLabelData; + uint32 pubAttr; + uint32 privAttr; + CSSM_RETURN ocrtn = CSSM_OK; + + if(keySize == CSP_KEY_SIZE_DEFAULT) { + keySize = CSP_DSA_KEY_SIZE_DEFAULT; + } + keyLabelData.Data = (uint8 *)keyLabel, + keyLabelData.Length = keyLabelLen; + memset(pubKey, 0, sizeof(CSSM_KEY)); + memset(privKey, 0, sizeof(CSSM_KEY)); + setBadKeyData(pubKey); + setBadKeyData(privKey); + + crtn = CSSM_CSP_CreateKeyGenContext(cspHand, + CSSM_ALGID_DSA, + keySize, + NULL, // Seed + NULL, // Salt + NULL, // StartDate + NULL, // EndDate + paramData, + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateKeyGenContext", crtn); + ocrtn = crtn; + goto abort; + } + + /* cook up attribute bits */ + if(pubIsRef) { + pubAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; + } + else { + pubAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + } + if(privIsRef) { + privAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; + } + else { + privAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + } + + if(genParams) { + /* + * extra step - generate params - this just adds some + * info to the context + */ + CSSM_DATA dummy = {0, NULL}; + crtn = CSSM_GenerateAlgorithmParams(ccHand, + keySize, &dummy); + if(crtn) { + printError("CSSM_GenerateAlgorithmParams", crtn); + return crtn; + } + appFreeCssmData(&dummy, CSSM_FALSE); + } + + /* optional format specifiers */ + if(!pubIsRef && (pubFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE)) { + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT, + sizeof(uint32), + CAT_Uint32, + NULL, + pubFormat); + if(crtn) { + printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn); + return crtn; + } + } + if(!privIsRef && (privFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE)) { + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT, + sizeof(uint32), // currently sizeof CSSM_DATA + CAT_Uint32, + NULL, + privFormat); + if(crtn) { + printError("AddContextAttribute(CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT)", crtn); + return crtn; + } + } + + crtn = CSSM_GenerateKeyPair(ccHand, + pubKeyUsage, + pubAttr, + &keyLabelData, + pubKey, + privKeyUsage, + privAttr, + &keyLabelData, // same labels + NULL, // CredAndAclEntry + privKey); + if(crtn) { + printError("CSSM_GenerateKeyPair", crtn); + ocrtn = crtn; + goto abort; + } + /* basic checks...*/ + if(privIsRef) { + if(privKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) { + printf("privKey blob type: exp %u got %u\n", + CSSM_KEYBLOB_REFERENCE, (unsigned)privKey->KeyHeader.BlobType); + ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; + goto abort; + } + } + else { + switch(privKey->KeyHeader.BlobType) { + case CSSM_KEYBLOB_RAW: + break; + default: + printf("privKey blob type: exp raw, got %u\n", + (unsigned)privKey->KeyHeader.BlobType); + ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; + goto abort; + } + } + if(pubIsRef) { + if(pubKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) { + printf("pubKey blob type: exp %u got %u\n", + CSSM_KEYBLOB_REFERENCE, (unsigned)pubKey->KeyHeader.BlobType); + ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; + goto abort; + } + } + else { + switch(pubKey->KeyHeader.BlobType) { + case CSSM_KEYBLOB_RAW: + break; + default: + printf("pubKey blob type: exp raw or raw_berder, got %u\n", + (unsigned)pubKey->KeyHeader.BlobType); + ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; + goto abort; + } + } +abort: + if(ccHand != 0) { + crtn = CSSM_DeleteContext(ccHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = CSSM_ERRCODE_INTERNAL_ERROR; + } + } + return ocrtn; +} + + +uint32 cspDefaultKeySize(uint32 alg) +{ + uint32 keySizeInBits; + switch(alg) { + case CSSM_ALGID_DES: + keySizeInBits = CSP_DES_KEY_SIZE_DEFAULT; + break; + case CSSM_ALGID_3DES_3KEY: + case CSSM_ALGID_DESX: + keySizeInBits = CSP_DES3_KEY_SIZE_DEFAULT; + break; + case CSSM_ALGID_RC2: + keySizeInBits = CSP_RC2_KEY_SIZE_DEFAULT; + break; + case CSSM_ALGID_RC4: + keySizeInBits = CSP_RC4_KEY_SIZE_DEFAULT; + break; + case CSSM_ALGID_RC5: + keySizeInBits = CSP_RC5_KEY_SIZE_DEFAULT; + break; + case CSSM_ALGID_ASC: + keySizeInBits = CSP_ASC_KEY_SIZE_DEFAULT; + break; + case CSSM_ALGID_BLOWFISH: + keySizeInBits = CSP_BFISH_KEY_SIZE_DEFAULT; + break; + case CSSM_ALGID_CAST: + keySizeInBits = CSP_CAST_KEY_SIZE_DEFAULT; + break; + case CSSM_ALGID_IDEA: + keySizeInBits = CSP_IDEA_KEY_SIZE_DEFAULT; + break; + case CSSM_ALGID_AES: + keySizeInBits = CSP_AES_KEY_SIZE_DEFAULT; + break; + case CSSM_ALGID_SHA1HMAC: + keySizeInBits = CSP_HMAC_SHA_KEY_SIZE_DEFAULT; + break; + case CSSM_ALGID_MD5HMAC: + keySizeInBits = CSP_HMAC_MD5_KEY_SIZE_DEFAULT; + break; + case CSSM_ALGID_FEE: + keySizeInBits = CSP_FEE_KEY_SIZE_DEFAULT; + break; + case CSSM_ALGID_RSA: + keySizeInBits = CSP_RSA_KEY_SIZE_DEFAULT; + break; + case CSSM_ALGID_DSA: + keySizeInBits = CSP_DSA_KEY_SIZE_DEFAULT; + break; + case CSSM_ALGID_ECDSA: + keySizeInBits = CSP_ECDSA_KEY_SIZE_DEFAULT; + break; + case CSSM_ALGID_NONE: + keySizeInBits = CSP_NULL_CRYPT_KEY_SIZE_DEF; + break; + default: + printf("***cspDefaultKeySize: Unknown symmetric algorithm\n"); + keySizeInBits = 0; + break; + } + return keySizeInBits; +} + +/* + * Create a random symmetric key. + */ +CSSM_KEY_PTR cspGenSymKey(CSSM_CSP_HANDLE cspHand, + uint32 alg, + const char *keyLabel, + unsigned keyLabelLen, + uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + uint32 keySizeInBits, + CSSM_BOOL refKey) +{ + CSSM_KEY_PTR symKey = (CSSM_KEY_PTR)CSSM_MALLOC(sizeof(CSSM_KEY)); + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + uint32 keyAttr; + CSSM_DATA dummyLabel; + + if(symKey == NULL) { + printf("Insufficient heap space\n"); + return NULL; + } + memset(symKey, 0, sizeof(CSSM_KEY)); + setBadKeyData(symKey); + if(keySizeInBits == CSP_KEY_SIZE_DEFAULT) { + keySizeInBits = cspDefaultKeySize(alg); + } + crtn = CSSM_CSP_CreateKeyGenContext(cspHand, + alg, + keySizeInBits, // keySizeInBits + NULL, // Seed + NULL, // Salt + NULL, // StartDate + NULL, // EndDate + NULL, // Params + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateKeyGenContext", crtn); + goto errorOut; + } + if(refKey) { + keyAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; + } + else { + keyAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + } + dummyLabel.Length = keyLabelLen; + dummyLabel.Data = (uint8 *)keyLabel; + + crtn = CSSM_GenerateKey(ccHand, + keyUsage, + keyAttr, + &dummyLabel, + NULL, // ACL + symKey); + if(crtn) { + printError("CSSM_GenerateKey", crtn); + goto errorOut; + } + crtn = CSSM_DeleteContext(ccHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + goto errorOut; + } + return symKey; +errorOut: + CSSM_FREE(symKey); + return NULL; +} + +/* + * Derive symmetric key. + * Note in the X CSP, we never return an IV. + */ +CSSM_KEY_PTR cspDeriveKey(CSSM_CSP_HANDLE cspHand, + uint32 deriveAlg, // CSSM_ALGID_PKCS5_PBKDF2, etc. + uint32 keyAlg, // CSSM_ALGID_RC5, etc. + const char *keyLabel, + unsigned keyLabelLen, + uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + uint32 keySizeInBits, + CSSM_BOOL isRefKey, + CSSM_DATA_PTR password, // in PKCS-5 lingo + CSSM_DATA_PTR salt, // ditto + uint32 iterationCnt, // ditto + CSSM_DATA_PTR initVector) // mallocd & RETURNED +{ + CSSM_KEY_PTR symKey = (CSSM_KEY_PTR) + CSSM_MALLOC(sizeof(CSSM_KEY)); + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + uint32 keyAttr; + CSSM_DATA dummyLabel; + CSSM_PKCS5_PBKDF2_PARAMS pbeParams; + CSSM_DATA pbeData; + CSSM_ACCESS_CREDENTIALS creds; + + if(symKey == NULL) { + printf("Insufficient heap space\n"); + return NULL; + } + memset(symKey, 0, sizeof(CSSM_KEY)); + setBadKeyData(symKey); + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + if(keySizeInBits == CSP_KEY_SIZE_DEFAULT) { + keySizeInBits = cspDefaultKeySize(keyAlg); + } + crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand, + deriveAlg, + keyAlg, + keySizeInBits, + &creds, + NULL, // BaseKey + iterationCnt, + salt, + NULL, // seed + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateDeriveKeyContext", crtn); + goto errorOut; + } + keyAttr = CSSM_KEYATTR_EXTRACTABLE; + if(isRefKey) { + keyAttr |= (CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE); + } + else { + keyAttr |= CSSM_KEYATTR_RETURN_DATA; + } + dummyLabel.Length = keyLabelLen; + dummyLabel.Data = (uint8 *)keyLabel; + + /* passing in password is pretty strange....*/ + pbeParams.Passphrase = *password; + pbeParams.PseudoRandomFunction = + CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1; + pbeData.Data = (uint8 *)&pbeParams; + pbeData.Length = sizeof(pbeParams); + crtn = CSSM_DeriveKey(ccHand, + &pbeData, + keyUsage, + keyAttr, + &dummyLabel, + NULL, // cred and acl + symKey); + if(crtn) { + printError("CSSM_DeriveKey", crtn); + goto errorOut; + } + /* copy IV back to caller */ + /* Nope, not supported */ + #if 0 + if(pbeParams.InitVector.Data != NULL) { + if(initVector->Data != NULL) { + if(initVector->Length < pbeParams.InitVector.Length) { + printf("***Insufficient InitVector\n"); + goto errorOut; + } + } + else { + initVector->Data = + (uint8 *)CSSM_MALLOC(pbeParams.InitVector.Length); + } + memmove(initVector->Data, pbeParams.InitVector.Data, + pbeParams.InitVector.Length); + initVector->Length = pbeParams.InitVector.Length; + CSSM_FREE(pbeParams.InitVector.Data); + } + else { + printf("***Warning: CSSM_DeriveKey, no InitVector\n"); + } + #endif + crtn = CSSM_DeleteContext(ccHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + goto errorOut; + } + return symKey; +errorOut: + CSSM_FREE(symKey); + return NULL; +} + +/* + * Cook up a symmetric key with specified key bits and other + * params. Currently the CSPDL can only deal with reference keys except when + * doing wrap/unwrap, so we manually cook up a raw key, then we null-unwrap it. + */ +CSSM_RETURN cspGenSymKeyWithBits( + CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS keyAlg, + CSSM_KEYUSE keyUsage, + const CSSM_DATA *keyBits, + unsigned keySizeInBytes, + CSSM_KEY_PTR refKey) // init'd and RETURNED +{ + CSSM_KEY rawKey; + CSSM_KEYHEADER_PTR hdr = &rawKey.KeyHeader; + CSSM_RETURN crtn; + + /* set up a raw key the CSP will accept */ + memset(&rawKey, 0, sizeof(CSSM_KEY)); + hdr->HeaderVersion = CSSM_KEYHEADER_VERSION; + hdr->BlobType = CSSM_KEYBLOB_RAW; + hdr->Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; + hdr->AlgorithmId = keyAlg; + hdr->KeyClass = CSSM_KEYCLASS_SESSION_KEY; + hdr->LogicalKeySizeInBits = keySizeInBytes * 8; + hdr->KeyAttr = CSSM_KEYATTR_EXTRACTABLE; + hdr->KeyUsage = keyUsage; + appSetupCssmData(&rawKey.KeyData, keySizeInBytes); + memmove(rawKey.KeyData.Data, keyBits->Data, keySizeInBytes); + + /* convert to a ref key */ + crtn = cspRawKeyToRef(cspHand, &rawKey, refKey); + appFreeCssmData(&rawKey.KeyData, CSSM_FALSE); + return crtn; +} + +/* + * Free a key. This frees a CSP's resources associated with the key if + * the key is a reference key. It also frees key->KeyData. The CSSM_KEY + * struct itself is not freed. + * Note this has no effect on the CSP or DL cached keys unless the incoming + * key is a reference key. + */ +CSSM_RETURN cspFreeKey(CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR key) +{ + CSSM_RETURN crtn; + crtn = CSSM_FreeKey(cspHand, + NULL, // access cred + key, + CSSM_FALSE); // delete - OK? maybe should parameterize? + if(crtn) { + printError("CSSM_FreeKey", crtn); + } + return crtn; +} + +/* generate a random and reasonable key size in bits for specified CSSM algorithm */ +uint32 randKeySizeBits(uint32 alg, + opType op) // OT_Encrypt, etc. +{ + uint32 minSize; + uint32 maxSize; + uint32 size; + + switch(alg) { + case CSSM_ALGID_DES: + return CSP_DES_KEY_SIZE_DEFAULT; + case CSSM_ALGID_3DES_3KEY: + case CSSM_ALGID_DESX: + return CSP_DES3_KEY_SIZE_DEFAULT; + case CSSM_ALGID_ASC: + case CSSM_ALGID_RC2: + case CSSM_ALGID_RC4: + case CSSM_ALGID_RC5: + minSize = 5 * 8; + maxSize = MAX_KEY_SIZE_RC245_BYTES * 8 ; // somewhat arbitrary + break; + case CSSM_ALGID_BLOWFISH: + minSize = 32; + maxSize = 448; + break; + case CSSM_ALGID_CAST: + minSize = 40; + maxSize = 128; + break; + case CSSM_ALGID_IDEA: + return CSP_IDEA_KEY_SIZE_DEFAULT; + case CSSM_ALGID_RSA: + minSize = CSP_RSA_KEY_SIZE_DEFAULT; + maxSize = 1024; + break; + case CSSM_ALGID_DSA: + /* signature only, no export restriction */ + minSize = 512; + maxSize = 1024; + break; + case CSSM_ALGID_SHA1HMAC: + minSize = 20 * 8; + maxSize = 256 * 8; + break; + case CSSM_ALGID_MD5HMAC: + minSize = 16 * 8; + maxSize = 256 * 8; + break; + case CSSM_ALGID_FEE: + /* FEE requires discrete sizes */ + size = genRand(1,4); + switch(size) { + case 1: + return 31; + case 2: + if(alg == CSSM_ALGID_FEE) { + return 127; + } + else { + return 128; + } + case 3: + return 161; + case 4: + return 192; + default: + printf("randKeySizeBits: internal error\n"); + return 0; + } + case CSSM_ALGID_ECDSA: + case CSSM_ALGID_SHA1WithECDSA: + /* ECDSA require discrete sizes */ + size = genRand(1,4); + switch(size) { + case 1: + return 192; + case 2: + return 256; + case 3: + return 384; + case 4: + default: + return 521; + } + case CSSM_ALGID_AES: + size = genRand(1, 3); + switch(size) { + case 1: + return 128; + case 2: + return 192; + case 3: + return 256; + } + case CSSM_ALGID_NONE: + return CSP_NULL_CRYPT_KEY_SIZE_DEF; + default: + printf("randKeySizeBits: unknown alg\n"); + return CSP_KEY_SIZE_DEFAULT; + } + size = genRand(minSize, maxSize); + + /* per-alg postprocessing.... */ + if(alg != CSSM_ALGID_RC2) { + size &= ~0x7; + } + switch(alg) { + case CSSM_ALGID_RSA: + // new for X - strong keys */ + size &= ~(16 - 1); + break; + case CSSM_ALGID_DSA: + /* size mod 64 == 0 */ + size &= ~(64 - 1); + break; + default: + break; + } + return size; +} + +#pragma mark --------- Encrypt/Decrypt --------- + +/* + * Encrypt/Decrypt + */ +/* + * Common routine for encrypt/decrypt - cook up an appropriate context handle + */ +/* + * When true, effectiveKeySizeInBits is passed down via the Params argument. + * Otherwise, we add a customized context attribute. + * Setting this true works with the stock Intel CSSM; this may well change. + * Note this overloading prevent us from specifying RC5 rounds.... + */ +#define EFFECTIVE_SIZE_VIA_PARAMS 0 +CSSM_CC_HANDLE genCryptHandle(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEED, etc. + uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for symmetric algs + CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc. + const CSSM_KEY *key0, + const CSSM_KEY *key1, // for CSSM_ALGID_FEED only - must be the + // public key + const CSSM_DATA *iv, // optional + uint32 effectiveKeySizeInBits, // 0 means skip this attribute + uint32 rounds) // ditto +{ + CSSM_CC_HANDLE cryptHand = 0; + uint32 params; + CSSM_RETURN crtn; + CSSM_ACCESS_CREDENTIALS creds; + + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + #if EFFECTIVE_SIZE_VIA_PARAMS + params = effectiveKeySizeInBits; + #else + params = 0; + #endif + switch(algorithm) { + case CSSM_ALGID_DES: + case CSSM_ALGID_3DES_3KEY_EDE: + case CSSM_ALGID_DESX: + case CSSM_ALGID_ASC: + case CSSM_ALGID_RC2: + case CSSM_ALGID_RC4: + case CSSM_ALGID_RC5: + case CSSM_ALGID_AES: + case CSSM_ALGID_BLOWFISH: + case CSSM_ALGID_CAST: + case CSSM_ALGID_IDEA: + case CSSM_ALGID_NONE: // used for wrapKey() + crtn = CSSM_CSP_CreateSymmetricContext(cspHand, + algorithm, + mode, + NULL, // access cred + key0, + iv, // InitVector + padding, + NULL, // Params + &cryptHand); + if(crtn) { + printError("CSSM_CSP_CreateSymmetricContext", crtn); + return 0; + } + break; + case CSSM_ALGID_FEED: + case CSSM_ALGID_FEEDEXP: + case CSSM_ALGID_FEECFILE: + case CSSM_ALGID_RSA: + crtn = CSSM_CSP_CreateAsymmetricContext(cspHand, + algorithm, + &creds, // access + key0, + padding, + &cryptHand); + if(crtn) { + printError("CSSM_CSP_CreateAsymmetricContext", crtn); + return 0; + } + if(key1 != NULL) { + /* + * FEED, some CFILE. Add (non-standard) second key attribute. + */ + crtn = AddContextAttribute(cryptHand, + CSSM_ATTRIBUTE_PUBLIC_KEY, + sizeof(CSSM_KEY), // currently sizeof CSSM_DATA + CAT_Ptr, + key1, + 0); + if(crtn) { + printError("AddContextAttribute", crtn); + return 0; + } + } + if(mode != CSSM_ALGMODE_NONE) { + /* special case, e.g., CSSM_ALGMODE_PUBLIC_KEY */ + crtn = AddContextAttribute(cryptHand, + CSSM_ATTRIBUTE_MODE, + sizeof(uint32), + CAT_Uint32, + NULL, + mode); + if(crtn) { + printError("AddContextAttribute", crtn); + return 0; + } + } + break; + default: + printf("genCryptHandle: bogus algorithm\n"); + return 0; + } + #if !EFFECTIVE_SIZE_VIA_PARAMS + /* add optional EffectiveKeySizeInBits and rounds attributes */ + if(effectiveKeySizeInBits != 0) { + CSSM_CONTEXT_ATTRIBUTE attr; + attr.AttributeType = CSSM_ATTRIBUTE_EFFECTIVE_BITS; + attr.AttributeLength = sizeof(uint32); + attr.Attribute.Uint32 = effectiveKeySizeInBits; + crtn = CSSM_UpdateContextAttributes( + cryptHand, + 1, + &attr); + if(crtn) { + printError("CSSM_UpdateContextAttributes", crtn); + return crtn; + } + } + #endif + + if(rounds != 0) { + CSSM_CONTEXT_ATTRIBUTE attr; + attr.AttributeType = CSSM_ATTRIBUTE_ROUNDS; + attr.AttributeLength = sizeof(uint32); + attr.Attribute.Uint32 = rounds; + crtn = CSSM_UpdateContextAttributes( + cryptHand, + 1, + &attr); + if(crtn) { + printError("CSSM_UpdateContextAttributes", crtn); + return crtn; + } + } + + return cryptHand; +} + +CSSM_RETURN cspEncrypt(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEED, etc. + uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for symmetric algs + CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc. + const CSSM_KEY *key, // public or session key + const CSSM_KEY *pubKey, // for CSSM_ALGID_FEED, CSSM_ALGID_FEECFILE only + uint32 effectiveKeySizeInBits, // 0 means skip this attribute + uint32 rounds, // ditto + const CSSM_DATA *iv, // init vector, optional + const CSSM_DATA *ptext, + CSSM_DATA_PTR ctext, // RETURNED + CSSM_BOOL mallocCtext) // if true, and ctext empty, malloc + // by getting size from CSP +{ + CSSM_CC_HANDLE cryptHand; + CSSM_RETURN crtn; + CSSM_SIZE bytesEncrypted; + CSSM_DATA remData = {0, NULL}; + CSSM_RETURN ocrtn = CSSM_OK; + unsigned origCtextLen; // the amount we malloc, if any + CSSM_RETURN savedErr = CSSM_OK; + CSSM_BOOL restoreErr = CSSM_FALSE; + + cryptHand = genCryptHandle(cspHand, + algorithm, + mode, + padding, + key, + pubKey, + iv, + effectiveKeySizeInBits, + rounds); + if(cryptHand == 0) { + return CSSMERR_CSSM_INTERNAL_ERROR; + } + if(mallocCtext && (ctext->Length == 0)) { + CSSM_QUERY_SIZE_DATA querySize; + querySize.SizeInputBlock = ptext->Length; + crtn = CSSM_QuerySize(cryptHand, + CSSM_TRUE, // encrypt + 1, + &querySize); + if(crtn) { + printError("CSSM_QuerySize", crtn); + ocrtn = crtn; + goto abort; + } + if(querySize.SizeOutputBlock == 0) { + /* CSP couldn't figure this out; skip our malloc */ + printf("***cspEncrypt: warning: cipherTextSize unknown; " + "skipping malloc\n"); + origCtextLen = 0; + } + else { + ctext->Data = (uint8 *) + appMalloc(querySize.SizeOutputBlock, NULL); + if(ctext->Data == NULL) { + printf("Insufficient heap space\n"); + ocrtn = CSSM_ERRCODE_MEMORY_ERROR; + goto abort; + } + ctext->Length = origCtextLen = querySize.SizeOutputBlock; + memset(ctext->Data, 0, ctext->Length); + } + } + else { + origCtextLen = ctext->Length; + } + crtn = CSSM_EncryptData(cryptHand, + ptext, + 1, + ctext, + 1, + &bytesEncrypted, + &remData); + if(crtn == CSSM_OK) { + /* + * Deal with remData - its contents are included in bytesEncrypted. + */ + if((remData.Length != 0) && mallocCtext) { + /* shouldn't happen - right? */ + if(bytesEncrypted > origCtextLen) { + /* malloc and copy a new one */ + uint8 *newCdata = (uint8 *)appMalloc(bytesEncrypted, NULL); + printf("**Warning: app malloced cipherBuf, but got nonzero " + "remData!\n"); + if(newCdata == NULL) { + printf("Insufficient heap space\n"); + ocrtn = CSSM_ERRCODE_MEMORY_ERROR; + goto abort; + } + memmove(newCdata, ctext->Data, ctext->Length); + memmove(newCdata+ctext->Length, remData.Data, remData.Length); + CSSM_FREE(ctext->Data); + ctext->Data = newCdata; + } + else { + /* there's room left over */ + memmove(ctext->Data+ctext->Length, remData.Data, remData.Length); + } + ctext->Length = bytesEncrypted; + } + // NOTE: We return the proper length in ctext.... + ctext->Length = bytesEncrypted; + } + else { + savedErr = crtn; + restoreErr = CSSM_TRUE; + printError("CSSM_EncryptData", crtn); + } +abort: + crtn = CSSM_DeleteContext(cryptHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = crtn; + } + if(restoreErr) { + ocrtn = savedErr; + } + return ocrtn; +} + +#define PAD_IMPLIES_RAND_PTEXTSIZE 1 +#define LOG_STAGED_OPS 0 +#if LOG_STAGED_OPS +#define soprintf(s) printf s +#else +#define soprintf(s) +#endif + +CSSM_RETURN cspStagedEncrypt(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEED, etc. + uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for symmetric algs + CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc. + const CSSM_KEY *key, // public or session key + const CSSM_KEY *pubKey, // for CSSM_ALGID_FEED, CSSM_ALGID_FEECFILE only + uint32 effectiveKeySizeInBits, // 0 means skip this attribute + uint32 cipherBlockSize, // ditto + uint32 rounds, // ditto + const CSSM_DATA *iv, // init vector, optional + const CSSM_DATA *ptext, + CSSM_DATA_PTR ctext, // RETURNED, we malloc + CSSM_BOOL multiUpdates) // false:single update, true:multi updates +{ + CSSM_CC_HANDLE cryptHand; + CSSM_RETURN crtn; + CSSM_SIZE bytesEncrypted; // per update + CSSM_SIZE bytesEncryptedTotal = 0; + CSSM_RETURN ocrtn = CSSM_OK; // 'our' crtn + unsigned toMove; // remaining + unsigned thisMove; // bytes to encrypt on this update + CSSM_DATA thisPtext; // running ptr into ptext + CSSM_DATA ctextWork; // per update, mallocd by CSP + CSSM_QUERY_SIZE_DATA querySize; + uint8 *origCtext; // initial ctext->Data + unsigned origCtextLen; // amount we mallocd + CSSM_BOOL restoreErr = CSSM_FALSE; + CSSM_RETURN savedErr = CSSM_OK; + + + cryptHand = genCryptHandle(cspHand, + algorithm, + mode, + padding, + key, + pubKey, + iv, + effectiveKeySizeInBits, + rounds); + if(cryptHand == 0) { + return CSSMERR_CSP_INTERNAL_ERROR; + } + if(cipherBlockSize) { + crtn = AddContextAttribute(cryptHand, + CSSM_ATTRIBUTE_BLOCK_SIZE, + sizeof(uint32), + CAT_Uint32, + NULL, + cipherBlockSize); + if(crtn) { + printError("CSSM_UpdateContextAttributes", crtn); + goto abort; + } + } + + /* obtain total required ciphertext size and block size */ + querySize.SizeInputBlock = ptext->Length; + crtn = CSSM_QuerySize(cryptHand, + CSSM_TRUE, // encrypt + 1, + &querySize); + if(crtn) { + printError("CSSM_QuerySize(1)", crtn); + ocrtn = CSSMERR_CSP_INTERNAL_ERROR; + goto abort; + } + if(querySize.SizeOutputBlock == 0) { + /* CSP couldn't figure this out; skip our malloc - caller is taking its + * chances */ + printf("***cspStagedEncrypt: warning: cipherTextSize unknown; aborting\n"); + ocrtn = CSSMERR_CSP_INTERNAL_ERROR; + goto abort; + } + else { + origCtextLen = querySize.SizeOutputBlock; + if(algorithm == CSSM_ALGID_ASC) { + /* ASC is weird - the more chunks we do, the bigger the + * resulting ctext...*/ + origCtextLen *= 2; + } + ctext->Length = origCtextLen; + ctext->Data = origCtext = (uint8 *)appMalloc(origCtextLen, NULL); + if(ctext->Data == NULL) { + printf("Insufficient heap space\n"); + ocrtn = CSSMERR_CSP_MEMORY_ERROR; + goto abort; + } + memset(ctext->Data, 0, ctext->Length); + } + + crtn = CSSM_EncryptDataInit(cryptHand); + if(crtn) { + printError("CSSM_EncryptDataInit", crtn); + ocrtn = crtn; + goto abort; + } + + toMove = ptext->Length; + thisPtext.Data = ptext->Data; + while(toMove) { + if(multiUpdates) { + thisMove = genRand(1, toMove); + } + else { + /* just do one pass thru this loop */ + thisMove = toMove; + } + thisPtext.Length = thisMove; + /* let CSP do the individual mallocs */ + ctextWork.Data = NULL; + ctextWork.Length = 0; + soprintf(("*** EncryptDataUpdate: ptextLen 0x%x\n", thisMove)); + crtn = CSSM_EncryptDataUpdate(cryptHand, + &thisPtext, + 1, + &ctextWork, + 1, + &bytesEncrypted); + if(crtn) { + printError("CSSM_EncryptDataUpdate", crtn); + ocrtn = crtn; + goto abort; + } + // NOTE: We return the proper length in ctext.... + ctextWork.Length = bytesEncrypted; + soprintf(("*** EncryptDataUpdate: ptextLen 0x%x bytesEncrypted 0x%x\n", + thisMove, bytesEncrypted)); + thisPtext.Data += thisMove; + toMove -= thisMove; + if(bytesEncrypted > ctext->Length) { + printf("cspStagedEncrypt: ctext overflow!\n"); + ocrtn = crtn; + goto abort; + } + if(bytesEncrypted != 0) { + memmove(ctext->Data, ctextWork.Data, bytesEncrypted); + bytesEncryptedTotal += bytesEncrypted; + ctext->Data += bytesEncrypted; + ctext->Length -= bytesEncrypted; + } + if(ctextWork.Data != NULL) { + CSSM_FREE(ctextWork.Data); + } + } + /* OK, one more */ + ctextWork.Data = NULL; + ctextWork.Length = 0; + crtn = CSSM_EncryptDataFinal(cryptHand, &ctextWork); + if(crtn) { + printError("CSSM_EncryptDataFinal", crtn); + savedErr = crtn; + restoreErr = CSSM_TRUE; + goto abort; + } + if(ctextWork.Length != 0) { + bytesEncryptedTotal += ctextWork.Length; + if(ctextWork.Length > ctext->Length) { + printf("cspStagedEncrypt: ctext overflow (2)!\n"); + ocrtn = CSSMERR_CSP_INTERNAL_ERROR; + goto abort; + } + memmove(ctext->Data, ctextWork.Data, ctextWork.Length); + } + if(ctextWork.Data) { + /* this could have gotten mallocd and Length still be zero */ + CSSM_FREE(ctextWork.Data); + } + + /* retweeze ctext */ + ctext->Data = origCtext; + ctext->Length = bytesEncryptedTotal; +abort: + crtn = CSSM_DeleteContext(cryptHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = crtn; + } + if(restoreErr) { + /* give caller the error from the encrypt */ + ocrtn = savedErr; + } + return ocrtn; +} + +CSSM_RETURN cspDecrypt(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEED, etc. + uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for symmetric algs + CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc. + const CSSM_KEY *key, // public or session key + const CSSM_KEY *pubKey, // for CSSM_ALGID_FEED, CSSM_ALGID_FEECFILE only + uint32 effectiveKeySizeInBits, // 0 means skip this attribute + uint32 rounds, // ditto + const CSSM_DATA *iv, // init vector, optional + const CSSM_DATA *ctext, + CSSM_DATA_PTR ptext, // RETURNED + CSSM_BOOL mallocPtext) // if true and ptext->Length = 0, + // we'll malloc +{ + CSSM_CC_HANDLE cryptHand; + CSSM_RETURN crtn; + CSSM_RETURN ocrtn = CSSM_OK; + CSSM_SIZE bytesDecrypted; + CSSM_DATA remData = {0, NULL}; + unsigned origPtextLen; // the amount we malloc, if any + + cryptHand = genCryptHandle(cspHand, + algorithm, + mode, + padding, + key, + pubKey, + iv, + effectiveKeySizeInBits, + rounds); + if(cryptHand == 0) { + return CSSMERR_CSP_INTERNAL_ERROR; + } + if(mallocPtext && (ptext->Length == 0)) { + CSSM_QUERY_SIZE_DATA querySize; + querySize.SizeInputBlock = ctext->Length; + crtn = CSSM_QuerySize(cryptHand, + CSSM_FALSE, // encrypt + 1, + &querySize); + if(crtn) { + printError("CSSM_QuerySize", crtn); + ocrtn = crtn; + goto abort; + } + if(querySize.SizeOutputBlock == 0) { + /* CSP couldn't figure this one out; skip our malloc */ + printf("***cspDecrypt: warning: plainTextSize unknown; " + "skipping malloc\n"); + origPtextLen = 0; + } + else { + ptext->Data = + (uint8 *)appMalloc(querySize.SizeOutputBlock, NULL); + if(ptext->Data == NULL) { + printf("Insufficient heap space\n"); + ocrtn = CSSMERR_CSP_MEMORY_ERROR; + goto abort; + } + ptext->Length = origPtextLen = querySize.SizeOutputBlock; + memset(ptext->Data, 0, ptext->Length); + } + } + else { + origPtextLen = ptext->Length; + } + crtn = CSSM_DecryptData(cryptHand, + ctext, + 1, + ptext, + 1, + &bytesDecrypted, + &remData); + if(crtn == CSSM_OK) { + /* + * Deal with remData - its contents are included in bytesDecrypted. + */ + if((remData.Length != 0) && mallocPtext) { + /* shouldn't happen - right? */ + if(bytesDecrypted > origPtextLen) { + /* malloc and copy a new one */ + uint8 *newPdata = (uint8 *)appMalloc(bytesDecrypted, NULL); + printf("**Warning: app malloced ClearBuf, but got nonzero " + "remData!\n"); + if(newPdata == NULL) { + printf("Insufficient heap space\n"); + ocrtn = CSSMERR_CSP_MEMORY_ERROR; + goto abort; + } + memmove(newPdata, ptext->Data, ptext->Length); + memmove(newPdata + ptext->Length, + remData.Data, remData.Length); + CSSM_FREE(ptext->Data); + ptext->Data = newPdata; + } + else { + /* there's room left over */ + memmove(ptext->Data + ptext->Length, + remData.Data, remData.Length); + } + ptext->Length = bytesDecrypted; + } + // NOTE: We return the proper length in ptext.... + ptext->Length = bytesDecrypted; + + // FIXME - sometimes get mallocd RemData here, but never any valid data + // there...side effect of CSPFullPluginSession's buffer handling logic; + // but will we ever actually see valid data in RemData? So far we never + // have.... + if(remData.Data != NULL) { + appFree(remData.Data, NULL); + } + } + else { + printError("CSSM_DecryptData", crtn); + ocrtn = crtn; + } +abort: + crtn = CSSM_DeleteContext(cryptHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = crtn; + } + return ocrtn; +} + +CSSM_RETURN cspStagedDecrypt(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEED, etc. + uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for symmetric algs + CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc. + const CSSM_KEY *key, // public or session key + const CSSM_KEY *pubKey, // for CSSM_ALGID_FEED, CSSM_ALGID_FEECFILE only + uint32 effectiveKeySizeInBits, // 0 means skip this attribute + uint32 cipherBlockSize, // ditto + uint32 rounds, // ditto + const CSSM_DATA *iv, // init vector, optional + const CSSM_DATA *ctext, + CSSM_DATA_PTR ptext, // RETURNED, we malloc + CSSM_BOOL multiUpdates) // false:single update, true:multi updates +{ + CSSM_CC_HANDLE cryptHand; + CSSM_RETURN crtn; + CSSM_SIZE bytesDecrypted; // per update + CSSM_SIZE bytesDecryptedTotal = 0; + CSSM_RETURN ocrtn = CSSM_OK; // 'our' crtn + unsigned toMove; // remaining + unsigned thisMove; // bytes to encrypt on this update + CSSM_DATA thisCtext; // running ptr into ptext + CSSM_DATA ptextWork; // per update, mallocd by CSP + CSSM_QUERY_SIZE_DATA querySize; + uint8 *origPtext; // initial ptext->Data + unsigned origPtextLen; // amount we mallocd + + cryptHand = genCryptHandle(cspHand, + algorithm, + mode, + padding, + key, + pubKey, + iv, + effectiveKeySizeInBits, + rounds); + if(cryptHand == 0) { + return CSSMERR_CSP_INTERNAL_ERROR; + } + if(cipherBlockSize) { + crtn = AddContextAttribute(cryptHand, + CSSM_ATTRIBUTE_BLOCK_SIZE, + sizeof(uint32), + CAT_Uint32, + NULL, + cipherBlockSize); + if(crtn) { + printError("CSSM_UpdateContextAttributes", crtn); + goto abort; + } + } + + /* obtain total required ciphertext size and block size */ + querySize.SizeInputBlock = ctext->Length; + crtn = CSSM_QuerySize(cryptHand, + CSSM_FALSE, // encrypt + 1, + &querySize); + if(crtn) { + printError("CSSM_QuerySize(1)", crtn); + ocrtn = crtn; + goto abort; + } + + /* required ptext size should be independent of number of chunks */ + if(querySize.SizeOutputBlock == 0) { + printf("***warning: cspStagedDecrypt: plainTextSize unknown; aborting\n"); + ocrtn = CSSMERR_CSP_INTERNAL_ERROR; + goto abort; + } + else { + // until exit, ptext->Length indicates remaining bytes of usable data in + // ptext->Data + ptext->Length = origPtextLen = querySize.SizeOutputBlock; + ptext->Data = origPtext = + (uint8 *)appMalloc(origPtextLen, NULL); + if(ptext->Data == NULL) { + printf("Insufficient heap space\n"); + ocrtn = CSSMERR_CSP_INTERNAL_ERROR; + goto abort; + } + memset(ptext->Data, 0, ptext->Length); + } + + crtn = CSSM_DecryptDataInit(cryptHand); + if(crtn) { + printError("CSSM_DecryptDataInit", crtn); + ocrtn = crtn; + goto abort; + } + toMove = ctext->Length; + thisCtext.Data = ctext->Data; + while(toMove) { + if(multiUpdates) { + thisMove = genRand(1, toMove); + } + else { + /* just do one pass thru this loop */ + thisMove = toMove; + } + thisCtext.Length = thisMove; + /* let CSP do the individual mallocs */ + ptextWork.Data = NULL; + ptextWork.Length = 0; + soprintf(("*** DecryptDataUpdate: ctextLen 0x%x\n", thisMove)); + crtn = CSSM_DecryptDataUpdate(cryptHand, + &thisCtext, + 1, + &ptextWork, + 1, + &bytesDecrypted); + if(crtn) { + printError("CSSM_DecryptDataUpdate", crtn); + ocrtn = crtn; + goto abort; + } + // + // NOTE: We return the proper length in ptext.... + ptextWork.Length = bytesDecrypted; + thisCtext.Data += thisMove; + toMove -= thisMove; + if(bytesDecrypted > ptext->Length) { + printf("cspStagedDecrypt: ptext overflow!\n"); + ocrtn = CSSMERR_CSP_INTERNAL_ERROR; + goto abort; + } + if(bytesDecrypted != 0) { + memmove(ptext->Data, ptextWork.Data, bytesDecrypted); + bytesDecryptedTotal += bytesDecrypted; + ptext->Data += bytesDecrypted; + ptext->Length -= bytesDecrypted; + } + if(ptextWork.Data != NULL) { + CSSM_FREE(ptextWork.Data); + } + } + /* OK, one more */ + ptextWork.Data = NULL; + ptextWork.Length = 0; + crtn = CSSM_DecryptDataFinal(cryptHand, &ptextWork); + if(crtn) { + printError("CSSM_DecryptDataFinal", crtn); + ocrtn = crtn; + goto abort; + } + if(ptextWork.Length != 0) { + bytesDecryptedTotal += ptextWork.Length; + if(ptextWork.Length > ptext->Length) { + printf("cspStagedDecrypt: ptext overflow (2)!\n"); + ocrtn = CSSMERR_CSP_INTERNAL_ERROR; + goto abort; + } + memmove(ptext->Data, ptextWork.Data, ptextWork.Length); + } + if(ptextWork.Data) { + /* this could have gotten mallocd and Length still be zero */ + CSSM_FREE(ptextWork.Data); + } + + /* retweeze ptext */ + ptext->Data = origPtext; + ptext->Length = bytesDecryptedTotal; +abort: + crtn = CSSM_DeleteContext(cryptHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = crtn; + } + return ocrtn; +} + +#pragma mark --------- sign/verify/MAC --------- + +/* + * Signature routines + * This all-in-one sign op has a special case for RSA keys. If the requested + * alg is MD5 or SHA1, we'll do a manual digest op followed by raw RSA sign. + * Likewise, if it's CSSM_ALGID_DSA, we'll do manual SHA1 digest followed by + * raw DSA sign. + */ + +CSSM_RETURN cspSign(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. + CSSM_KEY_PTR key, // private key + const CSSM_DATA *text, + CSSM_DATA_PTR sig) // RETURNED +{ + CSSM_CC_HANDLE sigHand; + CSSM_RETURN crtn; + CSSM_RETURN ocrtn = CSSM_OK; + const CSSM_DATA *ptext; + CSSM_DATA digest = {0, NULL}; + CSSM_ALGORITHMS digestAlg = CSSM_ALGID_NONE; + + /* handle special cases for raw sign */ + switch(algorithm) { + case CSSM_ALGID_SHA1: + digestAlg = CSSM_ALGID_SHA1; + algorithm = CSSM_ALGID_RSA; + break; + case CSSM_ALGID_MD5: + digestAlg = CSSM_ALGID_MD5; + algorithm = CSSM_ALGID_RSA; + break; + case CSSM_ALGID_DSA: + digestAlg = CSSM_ALGID_SHA1; + algorithm = CSSM_ALGID_DSA; + break; + default: + break; + } + if(digestAlg != CSSM_ALGID_NONE) { + crtn = cspDigest(cspHand, + digestAlg, + CSSM_FALSE, // mallocDigest + text, + &digest); + if(crtn) { + return crtn; + } + /* sign digest with raw RSA/DSA */ + ptext = &digest; + } + else { + ptext = text; + } + crtn = CSSM_CSP_CreateSignatureContext(cspHand, + algorithm, + NULL, // passPhrase + key, + &sigHand); + if(crtn) { + printError("CSSM_CSP_CreateSignatureContext (1)", crtn); + return crtn; + } + crtn = CSSM_SignData(sigHand, + ptext, + 1, + digestAlg, + sig); + if(crtn) { + printError("CSSM_SignData", crtn); + ocrtn = crtn; + } + crtn = CSSM_DeleteContext(sigHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = crtn; + } + if(digest.Data != NULL) { + CSSM_FREE(digest.Data); + } + return ocrtn; +} + +/* + * Staged sign. Each update does a random number of bytes 'till through. + */ +CSSM_RETURN cspStagedSign(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. + CSSM_KEY_PTR key, // private key + const CSSM_DATA *text, + CSSM_BOOL multiUpdates, // false:single update, true:multi updates + CSSM_DATA_PTR sig) // RETURNED +{ + CSSM_CC_HANDLE sigHand; + CSSM_RETURN crtn; + CSSM_RETURN ocrtn = CSSM_OK; + unsigned thisMove; // this update + unsigned toMove; // total to go + CSSM_DATA thisText; // actaully passed to update + crtn = CSSM_CSP_CreateSignatureContext(cspHand, + algorithm, + NULL, // passPhrase + key, + &sigHand); + if(crtn) { + printError("CSSM_CSP_CreateSignatureContext (1)", crtn); + return crtn; + } + crtn = CSSM_SignDataInit(sigHand); + if(crtn) { + printError("CSSM_SignDataInit", crtn); + ocrtn = crtn; + goto abort; + } + toMove = text->Length; + thisText.Data = text->Data; + while(toMove) { + if(multiUpdates) { + thisMove = genRand(1, toMove); + } + else { + thisMove = toMove; + } + thisText.Length = thisMove; + crtn = CSSM_SignDataUpdate(sigHand, + &thisText, + 1); + if(crtn) { + printError("CSSM_SignDataUpdate", crtn); + ocrtn = crtn; + goto abort; + } + thisText.Data += thisMove; + toMove -= thisMove; + } + crtn = CSSM_SignDataFinal(sigHand, sig); + if(crtn) { + printError("CSSM_SignDataFinal", crtn); + ocrtn = crtn; + goto abort; + } +abort: + crtn = CSSM_DeleteContext(sigHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = crtn; + } + return ocrtn; +} + +/* + * This all-in-one verify op has a special case for RSA keys. If the requested + * alg is MD5 or SHA1, we'll do a manual digest op followed by raw RSA verify. + * Likewise, if it's CSSM_ALGID_DSA, we'll do manual SHA1 digest followed by + * raw DSA sign. + */ + +CSSM_RETURN cspSigVerify(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. + CSSM_KEY_PTR key, // public key + const CSSM_DATA *text, + const CSSM_DATA *sig, + CSSM_RETURN expectResult) // expected result is verify failure + // CSSM_OK - expect success +{ + CSSM_CC_HANDLE sigHand; + CSSM_RETURN ocrtn = CSSM_OK; + CSSM_RETURN crtn; + const CSSM_DATA *ptext; + CSSM_DATA digest = {0, NULL}; + CSSM_ALGORITHMS digestAlg = CSSM_ALGID_NONE; + + /* handle special cases for raw sign */ + switch(algorithm) { + case CSSM_ALGID_SHA1: + digestAlg = CSSM_ALGID_SHA1; + algorithm = CSSM_ALGID_RSA; + break; + case CSSM_ALGID_MD5: + digestAlg = CSSM_ALGID_MD5; + algorithm = CSSM_ALGID_RSA; + break; + case CSSM_ALGID_DSA: + digestAlg = CSSM_ALGID_SHA1; + algorithm = CSSM_ALGID_DSA; + break; + default: + break; + } + if(digestAlg != CSSM_ALGID_NONE) { + crtn = cspDigest(cspHand, + digestAlg, + CSSM_FALSE, // mallocDigest + text, + &digest); + if(crtn) { + return crtn; + } + /* sign digest with raw RSA/DSA */ + ptext = &digest; + } + else { + ptext = text; + } + crtn = CSSM_CSP_CreateSignatureContext(cspHand, + algorithm, + NULL, // passPhrase + key, + &sigHand); + if(crtn) { + printError("CSSM_CSP_CreateSignatureContext (3)", crtn); + return crtn; + } + + crtn = CSSM_VerifyData(sigHand, + ptext, + 1, + digestAlg, + sig); + if(crtn != expectResult) { + if(!crtn) { + printf("Unexpected good Sig Verify\n"); + } + else { + printError("CSSM_VerifyData", crtn); + } + ocrtn = CSSMERR_CSSM_INTERNAL_ERROR; + } + crtn = CSSM_DeleteContext(sigHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = crtn; + } + if(digest.Data != NULL) { + CSSM_FREE(digest.Data); + } + return ocrtn; +} + +/* + * Staged verify. Each update does a random number of bytes 'till through. + */ +CSSM_RETURN cspStagedSigVerify(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. + CSSM_KEY_PTR key, // private key + const CSSM_DATA *text, + const CSSM_DATA *sig, + CSSM_BOOL multiUpdates, // false:single update, true:multi updates + CSSM_RETURN expectResult) // expected result is verify failure + // CSSM_TRUE - expect success +{ + CSSM_CC_HANDLE sigHand; + CSSM_RETURN crtn; + CSSM_RETURN ocrtn = CSSM_OK; + unsigned thisMove; // this update + unsigned toMove; // total to go + CSSM_DATA thisText; // actaully passed to update + crtn = CSSM_CSP_CreateSignatureContext(cspHand, + algorithm, + NULL, // passPhrase + key, + &sigHand); + if(crtn) { + printError("CSSM_CSP_CreateSignatureContext (4)", crtn); + return crtn; + } + crtn = CSSM_VerifyDataInit(sigHand); + if(crtn) { + printError("CSSM_VerifyDataInit", crtn); + ocrtn = crtn; + goto abort; + } + toMove = text->Length; + thisText.Data = text->Data; + while(toMove) { + if(multiUpdates) { + thisMove = genRand(1, toMove); + } + else { + thisMove = toMove; + } + thisText.Length = thisMove; + crtn = CSSM_VerifyDataUpdate(sigHand, + &thisText, + 1); + if(crtn) { + printError("CSSM_VerifyDataUpdate", crtn); + ocrtn = crtn; + goto abort; + } + thisText.Data += thisMove; + toMove -= thisMove; + } + crtn = CSSM_VerifyDataFinal(sigHand, sig); + if(crtn != expectResult) { + if(crtn) { + printError("CSSM_VerifyDataFinal", crtn); + } + else { + printf("Unexpected good Staged Sig Verify\n"); + } + ocrtn = CSSMERR_CSSM_INTERNAL_ERROR; + } +abort: + crtn = CSSM_DeleteContext(sigHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = crtn; + } + return ocrtn; +} + +/* + * MAC routines + */ +CSSM_RETURN cspGenMac(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. + CSSM_KEY_PTR key, // session key + const CSSM_DATA *text, + CSSM_DATA_PTR mac) // RETURNED +{ + CSSM_CC_HANDLE macHand; + CSSM_RETURN crtn; + CSSM_RETURN ocrtn = CSSM_OK; + crtn = CSSM_CSP_CreateMacContext(cspHand, + algorithm, + key, + &macHand); + if(crtn) { + printError("CSSM_CSP_CreateMacContext (1)", crtn); + return crtn; + } + crtn = CSSM_GenerateMac(macHand, + text, + 1, + mac); + if(crtn) { + printError("CSSM_GenerateMac", crtn); + ocrtn = crtn; + } + crtn = CSSM_DeleteContext(macHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = crtn; + } + return ocrtn; +} + +/* + * Staged generate mac. + */ +CSSM_RETURN cspStagedGenMac(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. + CSSM_KEY_PTR key, // private key + const CSSM_DATA *text, + CSSM_BOOL mallocMac, // if true and digest->Length = 0, we'll + // malloc + CSSM_BOOL multiUpdates, // false:single update, true:multi updates + CSSM_DATA_PTR mac) // RETURNED +{ + CSSM_CC_HANDLE macHand; + CSSM_RETURN crtn; + CSSM_RETURN ocrtn = CSSM_OK; + unsigned thisMove; // this update + unsigned toMove; // total to go + CSSM_DATA thisText; // actaully passed to update + + crtn = CSSM_CSP_CreateMacContext(cspHand, + algorithm, + key, + &macHand); + if(crtn) { + printError("CSSM_CSP_CreateMacContext (2)", crtn); + return crtn; + } + + if(mallocMac && (mac->Length == 0)) { + /* malloc mac - ask CSP for size */ + CSSM_QUERY_SIZE_DATA querySize = {0, 0}; + crtn = CSSM_QuerySize(macHand, + CSSM_TRUE, // encrypt + 1, + &querySize); + if(crtn) { + printError("CSSM_QuerySize(mac)", crtn); + ocrtn = crtn; + goto abort; + } + if(querySize.SizeOutputBlock == 0) { + printf("Unknown mac size\n"); + ocrtn = CSSMERR_CSSM_INTERNAL_ERROR; + goto abort; + } + mac->Data = (uint8 *)appMalloc(querySize.SizeOutputBlock, NULL); + if(mac->Data == NULL) { + printf("malloc failure\n"); + ocrtn = CSSMERR_CSSM_MEMORY_ERROR; + goto abort; + } + mac->Length = querySize.SizeOutputBlock; + } + + crtn = CSSM_GenerateMacInit(macHand); + if(crtn) { + printError("CSSM_GenerateMacInit", crtn); + ocrtn = crtn; + goto abort; + } + toMove = text->Length; + thisText.Data = text->Data; + + while(toMove) { + if(multiUpdates) { + thisMove = genRand(1, toMove); + } + else { + thisMove = toMove; + } + thisText.Length = thisMove; + crtn = CSSM_GenerateMacUpdate(macHand, + &thisText, + 1); + if(crtn) { + printError("CSSM_GenerateMacUpdate", crtn); + ocrtn = crtn; + goto abort; + } + thisText.Data += thisMove; + toMove -= thisMove; + } + crtn = CSSM_GenerateMacFinal(macHand, mac); + if(crtn) { + printError("CSSM_GenerateMacFinal", crtn); + ocrtn = crtn; + goto abort; + } +abort: + crtn = CSSM_DeleteContext(macHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = crtn; + } + return ocrtn; +} + +CSSM_RETURN cspMacVerify(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. + CSSM_KEY_PTR key, // public key + const CSSM_DATA *text, + const CSSM_DATA_PTR mac, + CSSM_RETURN expectResult) // expected result + // CSSM_OK - expect success +{ + CSSM_CC_HANDLE macHand; + CSSM_RETURN ocrtn = CSSM_OK; + CSSM_RETURN crtn; + crtn = CSSM_CSP_CreateMacContext(cspHand, + algorithm, + key, + &macHand); + if(crtn) { + printError("CSSM_CSP_CreateMacContext (3)", crtn); + return crtn; + } + crtn = CSSM_VerifyMac(macHand, + text, + 1, + mac); + if(crtn != expectResult) { + if(crtn) { + printError("CSSM_VerifyMac", crtn); + } + else { + printf("Unexpected good Mac Verify\n"); + } + ocrtn = CSSMERR_CSSM_INTERNAL_ERROR; + } + crtn = CSSM_DeleteContext(macHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = crtn; + } + return ocrtn; +} + +/* + * Staged mac verify. Each update does a random number of bytes 'till through. + */ +CSSM_RETURN cspStagedMacVerify(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. + CSSM_KEY_PTR key, // private key + const CSSM_DATA *text, + const CSSM_DATA_PTR mac, + CSSM_BOOL multiUpdates, // false:single update, true:multi updates + CSSM_RETURN expectResult) // expected result is verify failure + // CSSM_OK - expect success +{ + CSSM_CC_HANDLE macHand; + CSSM_RETURN crtn; + CSSM_RETURN ocrtn = CSSM_OK; + unsigned thisMove; // this update + unsigned toMove; // total to go + CSSM_DATA thisText; // actaully passed to update + + crtn = CSSM_CSP_CreateMacContext(cspHand, + algorithm, + key, + &macHand); + if(crtn) { + printError("CSSM_CSP_CreateMacContext (4)", crtn); + return crtn; + } + crtn = CSSM_VerifyMacInit(macHand); + if(crtn) { + printError("CSSM_VerifyMacInit", crtn); + ocrtn = crtn; + goto abort; + } + toMove = text->Length; + thisText.Data = text->Data; + + while(toMove) { + if(multiUpdates) { + thisMove = genRand(1, toMove); + } + else { + thisMove = toMove; + } + thisText.Length = thisMove; + crtn = CSSM_VerifyMacUpdate(macHand, + &thisText, + 1); + if(crtn) { + printError("CSSM_VerifyMacUpdate", crtn); + ocrtn = crtn; + goto abort; + } + thisText.Data += thisMove; + toMove -= thisMove; + } + crtn = CSSM_VerifyMacFinal(macHand, mac); + if(crtn != expectResult) { + if(crtn) { + printError("CSSM_VerifyMacFinal", crtn); + } + else { + printf("Unexpected good Staged Mac Verify\n"); + } + ocrtn = CSSMERR_CSSM_INTERNAL_ERROR; + } +abort: + crtn = CSSM_DeleteContext(macHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = crtn; + } + return ocrtn; +} + +#pragma mark --------- Digest --------- + +/* + * Digest functions + */ +CSSM_RETURN cspDigest(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_MD5, etc. + CSSM_BOOL mallocDigest, // if true and digest->Length = 0, we'll malloc + const CSSM_DATA *text, + CSSM_DATA_PTR digest) +{ + CSSM_CC_HANDLE digestHand; + CSSM_RETURN crtn; + CSSM_RETURN ocrtn = CSSM_OK; + + crtn = CSSM_CSP_CreateDigestContext(cspHand, + algorithm, + &digestHand); + if(crtn) { + printError("CSSM_CSP_CreateDIgestContext (1)", crtn); + return crtn; + } + if(mallocDigest && (digest->Length == 0)) { + /* malloc digest - ask CSP for size */ + CSSM_QUERY_SIZE_DATA querySize = {0, 0}; + crtn = CSSM_QuerySize(digestHand, + CSSM_FALSE, // encrypt + 1, + &querySize); + if(crtn) { + printError("CSSM_QuerySize(3)", crtn); + ocrtn = crtn; + goto abort; + } + if(querySize.SizeOutputBlock == 0) { + printf("Unknown digest size\n"); + ocrtn = CSSMERR_CSSM_INTERNAL_ERROR; + goto abort; + } + digest->Data = (uint8 *)appMalloc(querySize.SizeOutputBlock, NULL); + if(digest->Data == NULL) { + printf("malloc failure\n"); + ocrtn = CSSMERR_CSSM_MEMORY_ERROR; + goto abort; + } + digest->Length = querySize.SizeOutputBlock; + } + crtn = CSSM_DigestData(digestHand, + text, + 1, + digest); + if(crtn) { + printError("CSSM_DigestData", crtn); + ocrtn = crtn; + } +abort: + crtn = CSSM_DeleteContext(digestHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = crtn; + } + return ocrtn; +} + +CSSM_RETURN cspStagedDigest(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_MD5, etc. + CSSM_BOOL mallocDigest, // if true and digest->Length = 0, we'll + // malloc + CSSM_BOOL multiUpdates, // false:single update, true:multi updates + const CSSM_DATA *text, + CSSM_DATA_PTR digest) +{ + CSSM_CC_HANDLE digestHand; + CSSM_RETURN crtn; + CSSM_RETURN ocrtn = CSSM_OK; + unsigned thisMove; // this update + unsigned toMove; // total to go + CSSM_DATA thisText; // actually passed to update + + crtn = CSSM_CSP_CreateDigestContext(cspHand, + algorithm, + &digestHand); + if(crtn) { + printError("CSSM_CSP_CreateDigestContext (2)", crtn); + return crtn; + } + if(mallocDigest && (digest->Length == 0)) { + /* malloc digest - ask CSP for size */ + CSSM_QUERY_SIZE_DATA querySize = {0, 0}; + crtn = CSSM_QuerySize(digestHand, + CSSM_FALSE, // encrypt + 1, + &querySize); + if(crtn) { + printError("CSSM_QuerySize(4)", crtn); + ocrtn = crtn; + goto abort; + } + if(querySize.SizeOutputBlock == 0) { + printf("Unknown digest size\n"); + ocrtn = CSSMERR_CSSM_INTERNAL_ERROR; + goto abort; + } + digest->Data = (uint8 *)appMalloc(querySize.SizeOutputBlock, NULL); + if(digest->Data == NULL) { + printf("malloc failure\n"); + ocrtn = CSSMERR_CSSM_MEMORY_ERROR; + goto abort; + } + digest->Length = querySize.SizeOutputBlock; + } + crtn = CSSM_DigestDataInit(digestHand); + if(crtn) { + printError("CSSM_DigestDataInit", crtn); + ocrtn = crtn; + goto abort; + } + toMove = text->Length; + thisText.Data = text->Data; + while(toMove) { + if(multiUpdates) { + thisMove = genRand(1, toMove); + } + else { + thisMove = toMove; + } + thisText.Length = thisMove; + crtn = CSSM_DigestDataUpdate(digestHand, + &thisText, + 1); + if(crtn) { + printError("CSSM_DigestDataUpdate", crtn); + ocrtn = crtn; + goto abort; + } + thisText.Data += thisMove; + toMove -= thisMove; + } + crtn = CSSM_DigestDataFinal(digestHand, digest); + if(crtn) { + printError("CSSM_DigestDataFinal", crtn); + ocrtn = crtn; + goto abort; + } +abort: + crtn = CSSM_DeleteContext(digestHand); + if(crtn) { + printError("CSSM_DeleteContext", crtn); + ocrtn = crtn; + } + return ocrtn; +} + +#pragma mark --------- wrap/unwrap --------- + +/* wrap key function. */ +CSSM_RETURN cspWrapKey(CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *unwrappedKey, + const CSSM_KEY *wrappingKey, + CSSM_ALGORITHMS wrapAlg, + CSSM_ENCRYPT_MODE wrapMode, + CSSM_KEYBLOB_FORMAT wrapFormat, // NONE, PKCS7, PKCS8 + CSSM_PADDING wrapPad, + CSSM_DATA_PTR initVector, // for some wrapping algs + CSSM_DATA_PTR descrData, // optional + CSSM_KEY_PTR wrappedKey) // RETURNED +{ + CSSM_CC_HANDLE ccHand; + CSSM_RETURN crtn; + CSSM_ACCESS_CREDENTIALS creds; + + memset(wrappedKey, 0, sizeof(CSSM_KEY)); + setBadKeyData(wrappedKey); + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + /* special case for NULL wrap - no wrapping key */ + if((wrappingKey == NULL) || + (wrappingKey->KeyHeader.KeyClass == CSSM_KEYCLASS_SESSION_KEY)) { + crtn = CSSM_CSP_CreateSymmetricContext(cspHand, + wrapAlg, + wrapMode, + &creds, // passPhrase, + wrappingKey, + initVector, + wrapPad, // Padding + 0, // Params + &ccHand); + } + else { + crtn = CSSM_CSP_CreateAsymmetricContext(cspHand, + wrapAlg, + &creds, + wrappingKey, + wrapPad, // padding + &ccHand); + if(crtn) { + printError("cspWrapKey/CreateContext", crtn); + return crtn; + } + if(initVector) { + /* manually add IV for CMS. The actual low-level encrypt doesn't + * use it (and must ignore it). */ + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_INIT_VECTOR, + sizeof(CSSM_DATA), + CAT_Ptr, + initVector, + 0); + if(crtn) { + printError("CSSM_UpdateContextAttributes", crtn); + return crtn; + } + } + } + if(crtn) { + printError("cspWrapKey/CreateContext", crtn); + return crtn; + } + if(wrapFormat != CSSM_KEYBLOB_WRAPPED_FORMAT_NONE) { + /* only add this attribute if it's not the default */ + CSSM_CONTEXT_ATTRIBUTE attr; + attr.AttributeType = CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT; + attr.AttributeLength = sizeof(uint32); + attr.Attribute.Uint32 = wrapFormat; + crtn = CSSM_UpdateContextAttributes( + ccHand, + 1, + &attr); + if(crtn) { + printError("CSSM_UpdateContextAttributes", crtn); + return crtn; + } + } + crtn = CSSM_WrapKey(ccHand, + &creds, + unwrappedKey, + descrData, // DescriptiveData + wrappedKey); + if(crtn != CSSM_OK) { + printError("CSSM_WrapKey", crtn); + } + if(CSSM_DeleteContext(ccHand)) { + printf("CSSM_DeleteContext failure\n"); + } + return crtn; +} + +/* unwrap key function. */ +CSSM_RETURN cspUnwrapKey(CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *wrappedKey, + const CSSM_KEY *unwrappingKey, + CSSM_ALGORITHMS unwrapAlg, + CSSM_ENCRYPT_MODE unwrapMode, + CSSM_PADDING unwrapPad, + CSSM_DATA_PTR initVector, // for some wrapping algs + CSSM_KEY_PTR unwrappedKey, // RETURNED + CSSM_DATA_PTR descrData, // required + const char *keyLabel, + unsigned keyLabelLen) +{ + CSSM_CC_HANDLE ccHand; + CSSM_RETURN crtn; + CSSM_DATA labelData; + uint32 keyAttr; + CSSM_ACCESS_CREDENTIALS creds; + + memset(unwrappedKey, 0, sizeof(CSSM_KEY)); + setBadKeyData(unwrappedKey); + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + if((unwrappingKey == NULL) || + (unwrappingKey->KeyHeader.KeyClass == CSSM_KEYCLASS_SESSION_KEY)) { + crtn = CSSM_CSP_CreateSymmetricContext(cspHand, + unwrapAlg, + unwrapMode, + &creds, + unwrappingKey, + initVector, + unwrapPad, + 0, // Params + &ccHand); + } + else { + crtn = CSSM_CSP_CreateAsymmetricContext(cspHand, + unwrapAlg, + &creds, // passPhrase, + unwrappingKey, + unwrapPad, // Padding + &ccHand); + if(crtn) { + printError("cspUnwrapKey/CreateContext", crtn); + return crtn; + } + if(initVector) { + /* manually add IV for CMS. The actual low-level encrypt doesn't + * use it (and must ignore it). */ + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_INIT_VECTOR, + sizeof(CSSM_DATA), + CAT_Ptr, + initVector, + 0); + if(crtn) { + printError("CSSM_UpdateContextAttributes", crtn); + return crtn; + } + } + } + if(crtn) { + printError("cspUnwrapKey/CreateContext", crtn); + return crtn; + } + labelData.Data = (uint8 *)keyLabel; + labelData.Length = keyLabelLen; + + /* + * New keyAttr - clear some old bits, make sure we ask for ref key + */ + keyAttr = wrappedKey->KeyHeader.KeyAttr; + keyAttr &= ~(CSSM_KEYATTR_ALWAYS_SENSITIVE | CSSM_KEYATTR_NEVER_EXTRACTABLE); + keyAttr |= CSSM_KEYATTR_RETURN_REF; + crtn = CSSM_UnwrapKey(ccHand, + NULL, // PublicKey + wrappedKey, + wrappedKey->KeyHeader.KeyUsage, + keyAttr, + &labelData, + NULL, // CredAndAclEntry + unwrappedKey, + descrData); // required + if(crtn != CSSM_OK) { + printError("CSSM_UnwrapKey", crtn); + } + if(CSSM_DeleteContext(ccHand)) { + printf("CSSM_DeleteContext failure\n"); + } + return crtn; +} + +/* + * Simple NULL wrap to convert a reference key to a raw key. + */ +CSSM_RETURN cspRefKeyToRaw( + CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *refKey, + CSSM_KEY_PTR rawKey) // init'd and RETURNED +{ + CSSM_DATA descData = {0, 0}; + + memset(rawKey, 0, sizeof(CSSM_KEY)); + return cspWrapKey(cspHand, + refKey, + NULL, // unwrappingKey + CSSM_ALGID_NONE, + CSSM_ALGMODE_NONE, + CSSM_KEYBLOB_WRAPPED_FORMAT_NONE, + CSSM_PADDING_NONE, + NULL, // IV + &descData, + rawKey); +} + +/* + * Convert ref key to raw key with specified format. + */ +CSSM_RETURN cspRefKeyToRawWithFormat( + CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *refKey, + CSSM_KEYBLOB_FORMAT format, + CSSM_KEY_PTR rawKey) // init'd and RETURNED +{ + memset(rawKey, 0, sizeof(CSSM_KEY)); + CSSM_ATTRIBUTE_TYPE attrType; + + switch(refKey->KeyHeader.KeyClass) { + case CSSM_KEYCLASS_PUBLIC_KEY: + attrType = CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT; + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + attrType = CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT; + break; + case CSSM_KEYCLASS_SESSION_KEY: + attrType = CSSM_ATTRIBUTE_SYMMETRIC_KEY_FORMAT; + break; + default: + printf("***Unknown key class\n"); + return CSSMERR_CSP_INVALID_KEY; + } + + CSSM_DATA descData = {0, 0}; + CSSM_CC_HANDLE ccHand; + CSSM_RETURN crtn; +// uint32 keyAttr; + CSSM_ACCESS_CREDENTIALS creds; + + memset(rawKey, 0, sizeof(CSSM_KEY)); + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + crtn = CSSM_CSP_CreateSymmetricContext(cspHand, + CSSM_ALGID_NONE, + CSSM_ALGMODE_NONE, + &creds, + NULL, // unwrappingKey + NULL, // initVector + CSSM_PADDING_NONE, + NULL, // Reserved + &ccHand); + if(crtn) { + printError("cspRefKeyToRawWithFormat/CreateContext", crtn); + return crtn; + } + + /* Add the spec for the resulting format */ + crtn = AddContextAttribute(ccHand, + attrType, + sizeof(uint32), + CAT_Uint32, + NULL, + format); + + crtn = CSSM_WrapKey(ccHand, + &creds, + refKey, + &descData, // DescriptiveData + rawKey); + if(crtn != CSSM_OK) { + printError("CSSM_WrapKey", crtn); + } + if(rawKey->KeyHeader.Format != format) { + printf("***cspRefKeyToRawWithFormat format scewup\n"); + crtn = CSSMERR_CSP_INTERNAL_ERROR; + } + if(CSSM_DeleteContext(ccHand)) { + printf("CSSM_DeleteContext failure\n"); + } + return crtn; +} + +/* unwrap raw key --> ref */ +CSSM_RETURN cspRawKeyToRef( + CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *rawKey, + CSSM_KEY_PTR refKey) // init'd and RETURNED +{ + CSSM_DATA descData = {0, 0}; + + memset(refKey, 0, sizeof(CSSM_KEY)); + return cspUnwrapKey(cspHand, + rawKey, + NULL, // unwrappingKey + CSSM_ALGID_NONE, + CSSM_ALGMODE_NONE, + CSSM_PADDING_NONE, + NULL, // init vector + refKey, + &descData, + "noLabel", + 7); +} + + +#pragma mark --------- FEE key/curve support --------- + +/* + * Generate random key size, primeType, curveType for FEE key for specified op. + * + * First just enumerate the curves we know about, with ECDSA-INcapable first + */ + +typedef struct { + uint32 keySizeInBits; + uint32 primeType; // CSSM_FEE_PRIME_TYPE_xxx + uint32 curveType; // CSSM_FEE_CURVE_TYPE_xxx +} feeCurveParams; + +#define FEE_PROTOTYPE_CURVES 0 +#if FEE_PROTOTYPE_CURVES +/* obsolete as of 4/9/2001 */ +static feeCurveParams feeCurves[] = { + { 31, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_MONTGOMERY }, + { 127, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_MONTGOMERY }, + { 127, CSSM_FEE_PRIME_TYPE_GENERAL, CSSM_FEE_CURVE_TYPE_MONTGOMERY }, + #define NUM_NON_ECDSA_CURVES 3 + + /* start of Weierstrass, IEEE P1363-capable curves */ + { 31, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, + { 40, CSSM_FEE_PRIME_TYPE_FEE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, + { 127, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, + { 160, CSSM_FEE_PRIME_TYPE_FEE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, + { 160, CSSM_FEE_PRIME_TYPE_GENERAL, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, + { 192, CSSM_FEE_PRIME_TYPE_FEE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, +}; +#else /* FEE_PROTOTYPE_CURVES */ +static feeCurveParams feeCurves[] = { + { 31, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_MONTGOMERY }, + { 127, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_MONTGOMERY }, + #define NUM_NON_ECDSA_CURVES 2 + + /* start of Weierstrass, IEEE P1363-capable curves */ + { 31, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, + { 128, CSSM_FEE_PRIME_TYPE_FEE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, + { 161, CSSM_FEE_PRIME_TYPE_FEE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, + { 161, CSSM_FEE_PRIME_TYPE_GENERAL, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, + { 192, CSSM_FEE_PRIME_TYPE_GENERAL, CSSM_FEE_CURVE_TYPE_WEIERSTRASS }, +}; +#endif /* FEE_PROTOTYPE_CURVES */ +#define NUM_FEE_CURVES (sizeof(feeCurves) / sizeof(feeCurveParams)) + +void randFeeKeyParams( + CSSM_ALGORITHMS alg, // ALGID_FEED, CSSM_ALGID_FEE_MD5, etc. + uint32 *keySizeInBits, // RETURNED + uint32 *primeType, // CSSM_FEE_PRIME_TYPE_xxx, RETURNED + uint32 *curveType) // CSSM_FEE_CURVE_TYPE_xxx, RETURNED +{ + unsigned minParams; + unsigned die; + feeCurveParams *feeParams; + + switch(alg) { + case CSSM_ALGID_SHA1WithECDSA: + minParams = NUM_NON_ECDSA_CURVES; + break; + default: + minParams = 0; + break; + } + die = genRand(minParams, (NUM_FEE_CURVES - 1)); + feeParams = &feeCurves[die]; + *keySizeInBits = feeParams->keySizeInBits; + *primeType = feeParams->primeType; + *curveType = feeParams->curveType; +} + +/* + * Obtain strings for primeType and curveType. + */ +const char *primeTypeStr(uint32 primeType) +{ + const char *p; + switch(primeType) { + case CSSM_FEE_PRIME_TYPE_MERSENNE: + p = "Mersenne"; + break; + case CSSM_FEE_PRIME_TYPE_FEE: + p = "FEE"; + break; + case CSSM_FEE_PRIME_TYPE_GENERAL: + p = "General"; + break; + case CSSM_FEE_PRIME_TYPE_DEFAULT: + p = "Default"; + break; + default: + p = "***UNKNOWN***"; + break; + } + return p; +} + +const char *curveTypeStr(uint32 curveType) +{ + const char *c; + switch(curveType) { + case CSSM_FEE_CURVE_TYPE_DEFAULT: + c = "Default"; + break; + case CSSM_FEE_CURVE_TYPE_MONTGOMERY: + c = "Montgomery"; + break; + case CSSM_FEE_CURVE_TYPE_WEIERSTRASS: + c = "Weierstrass"; + break; + default: + c = "***UNKNOWN***"; + break; + } + return c; +} + +/* + * Perform FEE Key exchange via CSSM_DeriveKey. + */ +#if 0 +/* Not implemented in OS X */ +CSSM_RETURN cspFeeKeyExchange(CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR privKey, + CSSM_KEY_PTR pubKey, + CSSM_KEY_PTR derivedKey, // mallocd by caller + + /* remaining fields apply to derivedKey */ + uint32 keyAlg, + const char *keyLabel, + unsigned keyLabelLen, + uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + uint32 keySizeInBits) +{ + CSSM_CC_HANDLE dkHand; + CSSM_RETURN crtn; + CSSM_DATA labelData; + + if(derivedKey == NULL) { + printf("cspFeeKeyExchange: no derivedKey\n"); + return CSSMERR_CSSM_INTERNAL_ERROR; + } + if((pubKey == NULL) || + (pubKey->KeyHeader.KeyClass != CSSM_KEYCLASS_PUBLIC_KEY) || + (pubKey->KeyHeader.BlobType != CSSM_KEYBLOB_RAW)) { + printf("cspFeeKeyExchange: bad pubKey\n"); + return CSSMERR_CSSM_INTERNAL_ERROR; + } + if((privKey == NULL) || + (privKey->KeyHeader.KeyClass != CSSM_KEYCLASS_PRIVATE_KEY) || + (privKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE)) { + printf("cspFeeKeyExchange: bad privKey\n"); + return CSSMERR_CSSM_INTERNAL_ERROR; + } + memset(derivedKey, 0, sizeof(CSSM_KEY)); + + crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand, + CSSM_ALGID_FEE_KEYEXCH, // AlgorithmID + keyAlg, // alg of the derived key + keySizeInBits, + NULL, // access creds + // FIXME + 0, // IterationCount + NULL, // Salt + NULL, // Seed + NULL); // PassPhrase + if(dkHand == 0) { + printError("CSSM_CSP_CreateDeriveKeyContext"); + return CSSM_FAIL; + } + labelData.Length = keyLabelLen; + labelData.Data = (uint8 *)keyLabel; + crtn = CSSM_DeriveKey(dkHand, + privKey, + &pubKey->KeyData, // Param - pub key blob + keyUsage, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | + CSSM_KEYATTR_SENSITIVE, + &labelData, + derivedKey); + + /* FIXME - save/restore error */ + CSSM_DeleteContext(dkHand); + if(crtn) { + printError("CSSM_DeriveKey"); + } + return crtn; +} +#endif + +#pragma mark --------- Key/DL/DB support --------- + +/* + * Add a DL/DB handle to a crypto context. + */ +CSSM_RETURN cspAddDlDbToContext( + CSSM_CC_HANDLE ccHand, + CSSM_DL_HANDLE dlHand, + CSSM_DB_HANDLE dbHand) +{ + CSSM_DL_DB_HANDLE dlDb = { dlHand, dbHand }; + return AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_DL_DB_HANDLE, + sizeof(CSSM_ATTRIBUTE_DL_DB_HANDLE), + CAT_Ptr, + &dlDb, + 0); +} + +/* + * Common routine to do a basic DB lookup by label and key type. + * Query is aborted prior to exit. + */ +static CSSM_DB_UNIQUE_RECORD_PTR dlLookup( + CSSM_DL_DB_HANDLE dlDbHand, + const CSSM_DATA *keyLabel, + CT_KeyType keyType, + CSSM_HANDLE *resultHand, // RETURNED + CSSM_DATA_PTR theData, // RETURED + CSSM_DB_RECORDTYPE *recordType) // RETURNED +{ + CSSM_QUERY query; + CSSM_SELECTION_PREDICATE predicate; + CSSM_DB_UNIQUE_RECORD_PTR record = NULL; + CSSM_RETURN crtn; + + switch(keyType) { + case CKT_Public: + query.RecordType = *recordType = CSSM_DL_DB_RECORD_PUBLIC_KEY; + break; + case CKT_Private: + query.RecordType = *recordType = CSSM_DL_DB_RECORD_PRIVATE_KEY; + break; + case CKT_Session: + query.RecordType = *recordType = CSSM_DL_DB_RECORD_SYMMETRIC_KEY; + break; + default: + printf("Hey bozo! Give me a valid key type!\n"); + return NULL; + } + query.Conjunctive = CSSM_DB_NONE; + query.NumSelectionPredicates = 1; + predicate.DbOperator = CSSM_DB_EQUAL; + + predicate.Attribute.Info.AttributeNameFormat = + CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + predicate.Attribute.Info.Label.AttributeName = (char *) "Label"; + predicate.Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + /* hope this cast is OK */ + predicate.Attribute.Value = (CSSM_DATA_PTR)keyLabel; + query.SelectionPredicate = &predicate; + + query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? + query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? + query.QueryFlags = CSSM_QUERY_RETURN_DATA; // FIXME - used? + + crtn = CSSM_DL_DataGetFirst(dlDbHand, + &query, + resultHand, + NULL, + theData, + &record); + /* abort only on success */ + if(crtn == CSSM_OK) { + crtn = CSSM_DL_DataAbortQuery(dlDbHand, *resultHand); + if(crtn) { + printError("CSSM_DL_AbortQuery", crtn); + return NULL; + } + } + return record; +} + +/* + * Look up a key by label and type. + */ +CSSM_KEY_PTR cspLookUpKeyByLabel( + CSSM_DL_HANDLE dlHand, + CSSM_DB_HANDLE dbHand, + const CSSM_DATA *labelData, + CT_KeyType keyType) +{ + CSSM_DB_UNIQUE_RECORD_PTR record; + CSSM_HANDLE resultHand; + CSSM_DATA theData; + CSSM_KEY_PTR key; + CSSM_DB_RECORDTYPE recordType; + CSSM_DL_DB_HANDLE dlDbHand; + + dlDbHand.DLHandle = dlHand; + dlDbHand.DBHandle = dbHand; + + theData.Length = 0; + theData.Data = NULL; + + record = dlLookup(dlDbHand, + labelData, + keyType, + &resultHand, + &theData, + &recordType); + if(record == NULL) { + //printf("cspLookUpKeyByLabel: key not found\n"); + return NULL; + } + key = (CSSM_KEY_PTR)theData.Data; + CSSM_DL_FreeUniqueRecord(dlDbHand, record); + return key; +} + +/* + * Delete and free a key + */ +CSSM_RETURN cspDeleteKey( + CSSM_CSP_HANDLE cspHand, // for free + CSSM_DL_HANDLE dlHand, // for delete + CSSM_DB_HANDLE dbHand, // ditto + const CSSM_DATA *labelData, + CSSM_KEY_PTR key) +{ + CSSM_DB_UNIQUE_RECORD_PTR record; + CSSM_HANDLE resultHand; + CT_KeyType keyType; + CSSM_RETURN crtn = CSSM_OK; + CSSM_DB_RECORDTYPE recordType; + CSSM_DL_DB_HANDLE dlDbHand; + + if(key->KeyHeader.KeyAttr & CSSM_KEYATTR_PERMANENT) { + /* first do a lookup based in this key's fields */ + switch(key->KeyHeader.KeyClass) { + case CSSM_KEYCLASS_PUBLIC_KEY: + keyType = CKT_Public; + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + keyType = CKT_Private; + break; + case CSSM_KEYCLASS_SESSION_KEY: + keyType = CKT_Session; + break; + default: + printf("Hey bozo! Give me a valid key type!\n"); + return -1; + } + + dlDbHand.DLHandle = dlHand; + dlDbHand.DBHandle = dbHand; + + record = dlLookup(dlDbHand, + labelData, + keyType, + &resultHand, + NULL, // don't want actual data + &recordType); + if(record == NULL) { + printf("cspDeleteKey: key not found in DL\n"); + return CSSMERR_DL_RECORD_NOT_FOUND; + } + + /* OK, nuke it */ + crtn = CSSM_DL_DataDelete(dlDbHand, record); + if(crtn) { + printError("CSSM_DL_DataDelete", crtn); + } + CSSM_DL_FreeUniqueRecord(dlDbHand, record); + } + + /* CSSM_FreeKey() should fail due to the delete, but it will + * still free KeyData.... + * FIXME - we should be able to do this in this one single call - right? + */ + CSSM_FreeKey(cspHand, NULL, key, CSSM_FALSE); + + return crtn; +} + +/* + * Given any key in either blob or reference format, + * obtain the associated SHA-1 hash. + */ +CSSM_RETURN cspKeyHash( + CSSM_CSP_HANDLE cspHand, + const CSSM_KEY_PTR key, /* public key */ + CSSM_DATA_PTR *hashData) /* hash mallocd and RETURNED here */ +{ + CSSM_CC_HANDLE ccHand; + CSSM_RETURN crtn; + CSSM_DATA_PTR dp; + + *hashData = NULL; + + /* validate input params */ + if((key == NULL) || + (hashData == NULL)) { + printf("cspKeyHash: bogus args\n"); + return CSSMERR_CSSM_INTERNAL_ERROR; + } + + /* cook up a context for a passthrough op */ + crtn = CSSM_CSP_CreatePassThroughContext(cspHand, + key, + &ccHand); + if(ccHand == 0) { + printError("CSSM_CSP_CreatePassThroughContext", crtn); + return crtn; + } + + /* now it's up to the CSP */ + crtn = CSSM_CSP_PassThrough(ccHand, + CSSM_APPLECSP_KEYDIGEST, + NULL, + (void **)&dp); + if(crtn) { + printError("CSSM_CSP_PassThrough(PUBKEYHASH)", crtn); + } + else { + *hashData = dp; + crtn = CSSM_OK; + } + CSSM_DeleteContext(ccHand); + return crtn; +} + diff --git a/SecurityTests/cspxutils/utilLib/cspwrap.h b/SecurityTests/cspxutils/utilLib/cspwrap.h new file mode 100644 index 00000000..73bb61cf --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/cspwrap.h @@ -0,0 +1,454 @@ +/* Copyright (c) 1997,2003,2005-2006,2008 Apple Inc. + * + * cspwrap.h - wrappers to simplify access to CDSA + * + * Revision History + * ---------------- + * 3 May 2000 Doug Mitchell + * Ported to X/CDSA2. + * 12 Aug 1997 Doug Mitchell at Apple + * Created. + */ + +#ifndef _CSPWRAP_H_ +#define _CSPWRAP_H_ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Bug/feature workaround flags + */ + +/* + * Doing a WrapKey requires Access Creds, which should be + * optional. Looks like this is not a bug. + */ +#define WRAP_KEY_REQUIRES_CREDS 1 + +/* + * encrypt/decrypt - cook up a context handle + */ +CSSM_CC_HANDLE genCryptHandle(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEED, etc. + uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for symmetric algs + CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc. + const CSSM_KEY *key0, + const CSSM_KEY *key1, // for CSSM_ALGID_FEED only - must be the + // public key + const CSSM_DATA *iv, // optional + uint32 effectiveKeySizeInBits, // 0 means skip this attribute + uint32 rounds); // ditto +/* + * Key generation + */ +/* + * Specifying a keySize of CSP_KEY_SIZE_DEFAULT results in using the default + * key size for the specified algorithm. + */ +#define CSP_KEY_SIZE_DEFAULT 0 + +/* symmetric key sizes in bits */ +#define CSP_ASC_KEY_SIZE_DEFAULT (16 * 8) +#define CSP_DES_KEY_SIZE_DEFAULT (8 * 8) +#define CSP_DES3_KEY_SIZE_DEFAULT (24 * 8) +#define CSP_RC2_KEY_SIZE_DEFAULT (10 * 8) +#define CSP_RC4_KEY_SIZE_DEFAULT (10 * 8) +#define CSP_RC5_KEY_SIZE_DEFAULT (10 * 8) +#define CSP_AES_KEY_SIZE_DEFAULT 128 +#define CSP_BFISH_KEY_SIZE_DEFAULT 128 +#define CSP_CAST_KEY_SIZE_DEFAULT 128 +#define CSP_IDEA_KEY_SIZE_DEFAULT 128 /* fixed */ +#define CSP_HMAC_SHA_KEY_SIZE_DEFAULT (20 * 8) +#define CSP_HMAC_MD5_KEY_SIZE_DEFAULT (16 * 8) +#define CSP_NULL_CRYPT_KEY_SIZE_DEF (16 * 8) + +/* asymmetric key sizes in bits */ +/* note: we now use AI_RSAStrongKeyGen for RSA key pair + * generate; this requires at least 512 bits and also that + * the key size be a multiple of 16. */ +#define CSP_FEE_KEY_SIZE_DEFAULT 128 +#define CSP_ECDSA_KEY_SIZE_DEFAULT 256 +#define CSP_RSA_KEY_SIZE_DEFAULT 1024 /* min for SHA512/RSA */ +#define CSP_DSA_KEY_SIZE_DEFAULT 512 + +/* + * Generate key pair of arbitrary algorithm. + */ +extern CSSM_RETURN cspGenKeyPair(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, + const char *keyLabel, + unsigned keyLabelLen, + uint32 keySizeInBits, + CSSM_KEY_PTR pubKey, // mallocd by caller + CSSM_BOOL pubIsRef, // true - reference key, false - data + uint32 pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + CSSM_KEYBLOB_FORMAT pubFormat, // Optional. Specify 0 or CSSM_KEYBLOB_RAW_FORMAT_NONE + // to get the default format. + CSSM_KEY_PTR privKey, // mallocd by caller - always returned as ref + CSSM_BOOL privIsRef, // true - reference key, false - data + uint32 privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc. + CSSM_KEYBLOB_FORMAT privFormat, // optional 0 ==> default + CSSM_BOOL genSeed); // FEE only. True: we generate seed and CSP + // will hash it. False: CSP generates random + // seed. + +/* + * Generate FEE key pair with optional primeType, curveType, and seed (password) data. + */ +extern CSSM_RETURN cspGenFEEKeyPair(CSSM_CSP_HANDLE cspHand, + const char *keyLabel, + unsigned keyLabelLen, + uint32 keySize, // in bits + uint32 primeType, // CSSM_FEE_PRIME_TYPE_MERSENNE, etc. + uint32 curveType, // CSSM_FEE_CURVE_TYPE_MONTGOMERY, etc. + CSSM_KEY_PTR pubKey, // mallocd by caller + CSSM_BOOL pubIsRef, // true - reference key, false - data + uint32 pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + CSSM_KEYBLOB_FORMAT pubFormat, // Optional. Specify 0 or CSSM_KEYBLOB_RAW_FORMAT_NONE + // to get the default format. + CSSM_KEY_PTR privKey, // mallocd by caller + CSSM_BOOL privIsRef, // true - reference key, false - data + uint32 privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc. + CSSM_KEYBLOB_FORMAT privFormat, // optional 0 ==> default + const CSSM_DATA *seedData); // Present: CSP will hash this for private data. + // NULL: CSP generates random seed. + +/* + * Generate DSA key pair with optional generateAlgParams. + */ +extern CSSM_RETURN cspGenDSAKeyPair(CSSM_CSP_HANDLE cspHand, + const char *keyLabel, + unsigned keyLabelLen, + uint32 keySize, // in bits + CSSM_KEY_PTR pubKey, // mallocd by caller + CSSM_BOOL pubIsRef, // true - reference key, false - data + uint32 pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + CSSM_KEYBLOB_FORMAT pubFormat, // Optional. Specify 0 or CSSM_KEYBLOB_RAW_FORMAT_NONE + // to get the default format. + CSSM_KEY_PTR privKey, // mallocd by caller + CSSM_BOOL privIsRef, // true - reference key, false - data + uint32 privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc. + CSSM_KEYBLOB_FORMAT privFormat, // Optional. Specify 0 or CSSM_KEYBLOB_RAW_FORMAT_NONE + // to get the default format. + CSSM_BOOL genParams, + CSSM_DATA_PTR paramData); // optional + +/* + * Create a symmetric key. + */ +extern CSSM_KEY_PTR cspGenSymKey(CSSM_CSP_HANDLE cspHand, + uint32 alg, + const char *keyLabel, + unsigned keyLabelLen, + uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + uint32 keySizeInBits, + CSSM_BOOL refKey); // true - reference key, false - data + +/* + * Derive symmetric key using PBE. + */ +CSSM_KEY_PTR cspDeriveKey(CSSM_CSP_HANDLE cspHand, + uint32 deriveAlg, // CSSM_ALGID_MD5_PBE, etc. + uint32 keyAlg, // CSSM_ALGID_RC5, etc. + const char *keyLabel, + unsigned keyLabelLen, + uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + uint32 keySizeInBits, + CSSM_BOOL isRefKey, + CSSM_DATA_PTR password, // in PKCS-5 lingo + CSSM_DATA_PTR salt, // ditto + uint32 iterationCnt, // ditto + CSSM_DATA_PTR initVector); // mallocd & RETURNED + +/* + * Encrypt/Decrypt - these work for both symmetric and asymmetric algorithms. + */ +CSSM_RETURN cspEncrypt(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEED, etc. + uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for + // symmetric algs + CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc. + const CSSM_KEY *key, // public or session key + const CSSM_KEY *pubKey, // for CSSM_ALGID_{FEED,FEECFILE} only + uint32 effectiveKeySizeInBits, // 0 means skip this attribute + uint32 rounds, // ditto + const CSSM_DATA *iv, // init vector, optional + const CSSM_DATA *ptext, + CSSM_DATA_PTR ctext, // RETURNED + CSSM_BOOL mallocCtext); + +CSSM_RETURN cspStagedEncrypt(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEED, etc. + uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for + // symmetric algs + CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc. + const CSSM_KEY *key, // public or session key + const CSSM_KEY *pubKey, // for CSSM_ALGID_{FEED,FEECFILE} only + uint32 effectiveKeySizeInBits, // 0 means skip this attribute + uint32 cipherBlockSize, // ditto, block size in bytes + uint32 rounds, // ditto + const CSSM_DATA *iv, // init vector, optional + const CSSM_DATA *ptext, + CSSM_DATA_PTR ctext, // RETURNED, we malloc + CSSM_BOOL multiUpdates); // false:single update, true:multi updates + +CSSM_RETURN cspDecrypt(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEED, etc. + uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for + // symmetric algs + CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc. + const CSSM_KEY *key, // private or session key + const CSSM_KEY *pubKey, // for CSSM_ALGID_{FEED,FEECFILE} only + uint32 effectiveKeySizeInBits, // 0 means skip this attribute + uint32 rounds, // ditto + const CSSM_DATA *iv, // init vector, optional + const CSSM_DATA *ctext, + CSSM_DATA_PTR ptext, // RETURNED + CSSM_BOOL mallocPtext); + +CSSM_RETURN cspStagedDecrypt(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEED, etc. + uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for + // symmetric algs + CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc. + const CSSM_KEY *key, // private or session key + const CSSM_KEY *pubKey, // for CSSM_ALGID_{FEED,FEECFILE} only + uint32 effectiveKeySizeInBits, // 0 means skip this attribute + uint32 cipherBlockSize, // ditto, block size in bytes + uint32 rounds, // ditto + const CSSM_DATA *iv, // init vector, optional + const CSSM_DATA *ctext, + CSSM_DATA_PTR ptext, // RETURNED, we malloc + CSSM_BOOL multiUpdates); // false:single update, true:multi updates + +/* + * Signature routines + */ +CSSM_RETURN cspSign(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. + CSSM_KEY_PTR key, // private key + const CSSM_DATA *text, + CSSM_DATA_PTR sig); // RETURNED +CSSM_RETURN cspStagedSign(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. + CSSM_KEY_PTR key, // private key + const CSSM_DATA *text, + CSSM_BOOL multiUpdates, // false:single update, true:multi updates + CSSM_DATA_PTR sig); // RETURNED +CSSM_RETURN cspSigVerify(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. + CSSM_KEY_PTR key, // public key + const CSSM_DATA *text, + const CSSM_DATA *sig, + CSSM_RETURN expectResult); // expected result is verify failure + // CSSM_OK - expect success +CSSM_RETURN cspStagedSigVerify(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. + CSSM_KEY_PTR key, // private key + const CSSM_DATA *text, + const CSSM_DATA *sig, + CSSM_BOOL multiUpdates, // false:single update, true:multi updates + CSSM_RETURN expectResult); // expected result is verify failure + // CSSM_OK - expect success + +/* + * MAC routines + */ +CSSM_RETURN cspGenMac(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_DES, etc. + CSSM_KEY_PTR key, // session key + const CSSM_DATA *text, + CSSM_DATA_PTR mac); // RETURNED +CSSM_RETURN cspStagedGenMac(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. + CSSM_KEY_PTR key, // private key + const CSSM_DATA *text, + CSSM_BOOL mallocMac, // if true and digest->Length = 0, we'll + // malloc + CSSM_BOOL multiUpdates, // false:single update, true:multi updates + CSSM_DATA_PTR mac); // RETURNED +CSSM_RETURN cspMacVerify(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, + CSSM_KEY_PTR key, // public key + const CSSM_DATA *text, + const CSSM_DATA_PTR mac, + CSSM_RETURN expectResult); +CSSM_RETURN cspStagedMacVerify(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, + CSSM_KEY_PTR key, // private key + const CSSM_DATA *text, + const CSSM_DATA_PTR mac, + CSSM_BOOL multiUpdates, // false:single update, true:multi updates + CSSM_RETURN expectResult); + +/* + * Digest functions + */ +CSSM_RETURN cspDigest(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_MD5, etc. + CSSM_BOOL mallocDigest, // if true and digest->Length = 0, we'll malloc + const CSSM_DATA *text, + CSSM_DATA_PTR digest); +CSSM_RETURN cspStagedDigest(CSSM_CSP_HANDLE cspHand, + uint32 algorithm, // CSSM_ALGID_MD5, etc. + CSSM_BOOL mallocDigest, // if true and digest->Length = 0, we'll malloc + CSSM_BOOL multiUpdates, // false:single update, true:multi updates + const CSSM_DATA *text, + CSSM_DATA_PTR digest); +CSSM_RETURN cspFreeKey(CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR key); + +/* + * Perform FEE Key exchange via CSSM_DeriveKey. + */ +CSSM_RETURN cspFeeKeyExchange(CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR privKey, + CSSM_KEY_PTR pubKey, + CSSM_KEY_PTR derivedKey, // mallocd by caller + + /* remaining fields apply to derivedKey */ + uint32 keyAlg, + const char *keyLabel, + unsigned keyLabelLen, + uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + uint32 keySizeInBits); + +/* + * wrap/unwrap key functions. + */ +CSSM_RETURN cspWrapKey(CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *unwrappedKey, + const CSSM_KEY *wrappingKey, + CSSM_ALGORITHMS wrapAlg, + CSSM_ENCRYPT_MODE wrapMode, + CSSM_KEYBLOB_FORMAT wrapFormat, // NONE, PKCS7, PKCS8 + CSSM_PADDING wrapPad, + CSSM_DATA_PTR initVector, // for some wrapping algs + CSSM_DATA_PTR descrData, // optional + CSSM_KEY_PTR wrappedKey); // RETURNED +CSSM_RETURN cspUnwrapKey(CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *wrappedKey, + const CSSM_KEY *unwrappingKey, + CSSM_ALGORITHMS unwrapAlg, + CSSM_ENCRYPT_MODE unwrapMode, + CSSM_PADDING unwrapPad, + CSSM_DATA_PTR initVector, // for some wrapping algs + CSSM_KEY_PTR unwrappedKey, // RETURNED + CSSM_DATA_PTR descrData, // required + const char *keyLabel, + unsigned keyLabelLen); + +/* generate a random and reasonable key size in bits for specified CSSM algorithm */ +typedef enum { + OT_Sign, + OT_Encrypt, + OT_KeyExch +} opType; + +#define MAX_KEY_SIZE_RC245_BYTES 64 /* max bytes, RC2, RC4, RC5 */ + +uint32 randKeySizeBits(uint32 alg, opType op); +uint32 cspDefaultKeySize(uint32 alg); + +/* + * Generate random key size, primeType, curveType for FEE key for specified op. + */ +void randFeeKeyParams( + CSSM_ALGORITHMS alg, // ALGID_FEED, CSSM_ALGID_FEE_MD5, etc. + uint32 *keySizeInBits, // RETURNED + uint32 *primeType, // CSSM_FEE_PRIME_TYPE_xxx, RETURNED + uint32 *curveType); // CSSM_FEE_CURVE_TYPE_xxx, RETURNED + +/* + * Obtain strings for primeType and curveType. + */ +const char *primeTypeStr(uint32 primeType); +const char *curveTypeStr(uint32 curveType); + +/* + * Given any key in either blob or reference format, + * obtain the associated SHA-1 hash. + */ +CSSM_RETURN cspKeyHash( + CSSM_CSP_HANDLE cspHand, + const CSSM_KEY_PTR key, /* public key */ + CSSM_DATA_PTR *hashData); /* hash mallocd and RETURNED here */ + +/* wrap ref key --> raw key */ +CSSM_RETURN cspRefKeyToRaw( + CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *refKey, + CSSM_KEY_PTR rawKey); // init'd and RETURNED + +/* + * Convert ref key to raw key with specified format. + */ +CSSM_RETURN cspRefKeyToRawWithFormat( + CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *refKey, + CSSM_KEYBLOB_FORMAT format, + CSSM_KEY_PTR rawKey); // init'd and RETURNED + +/* unwrap raw key --> ref */ +CSSM_RETURN cspRawKeyToRef( + CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *rawKey, + CSSM_KEY_PTR refKey); // init'd and RETURNED + +/* + * Cook up a symmetric key with specified key bits and other + * params. Currently the CSPDL can only deal with reference keys except when + * doing wrap/unwrap, so we manually cook up a raw key, then we null-unwrap it. + */ +CSSM_RETURN cspGenSymKeyWithBits( + CSSM_CSP_HANDLE cspHand, + CSSM_ALGORITHMS keyAlg, + CSSM_KEYUSE keyUsage, + const CSSM_DATA *keyBits, + unsigned keySizeInBytes, + CSSM_KEY_PTR refKey); // init'd and RETURNED + +/* + * Add a DL/DB handle to a crypto context. + */ +CSSM_RETURN cspAddDlDbToContext( + CSSM_CC_HANDLE ccHand, + CSSM_DL_HANDLE dlHand, + CSSM_DB_HANDLE dbHand); + +/* + * Look up a key by label and type. + */ +typedef enum { + CKT_Public = 1, + CKT_Private = 2, + CKT_Session = 3 + /* any others? */ +} CT_KeyType; + +CSSM_KEY_PTR cspLookUpKeyByLabel( + CSSM_DL_HANDLE dlHand, + CSSM_DB_HANDLE dbHand, + const CSSM_DATA *labelData, + CT_KeyType keyType); + +/* + * Delete and free a key + */ +CSSM_RETURN cspDeleteKey( + CSSM_CSP_HANDLE cspHand, // for free + CSSM_DL_HANDLE dlHand, // for delete + CSSM_DB_HANDLE dbHand, // ditto + const CSSM_DATA *labelData, + CSSM_KEY_PTR key); + +// temp hack +#define CSSM_ALGID_FEECFILE (CSSM_ALGID_VENDOR_DEFINED + 102) + +#ifdef __cplusplus +} +#endif +#endif /* _CSPWRAP_H_ */ diff --git a/SecurityTests/cspxutils/utilLib/cssmErrorStrings.h b/SecurityTests/cspxutils/utilLib/cssmErrorStrings.h new file mode 100644 index 00000000..e5a82472 --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/cssmErrorStrings.h @@ -0,0 +1,532 @@ +/* + * This file autogenerated by genErrorStrings. Do not edit. + */ + +#include + +typedef struct { + CSSM_RETURN errCode; + const char *errStr; +} ErrString; + +static const ErrString errStrings[] = { + { CSSM_OK,"CSSM_OK"}, + /* Error codes from cssmerr.h */ + { CSSMERR_CSSM_INVALID_ADDIN_HANDLE,"CSSMERR_CSSM_INVALID_ADDIN_HANDLE"}, + { CSSMERR_CSSM_NOT_INITIALIZED,"CSSMERR_CSSM_NOT_INITIALIZED"}, + { CSSMERR_CSSM_INVALID_HANDLE_USAGE,"CSSMERR_CSSM_INVALID_HANDLE_USAGE"}, + { CSSMERR_CSSM_PVC_REFERENT_NOT_FOUND,"CSSMERR_CSSM_PVC_REFERENT_NOT_FOUND"}, + { CSSMERR_CSSM_FUNCTION_INTEGRITY_FAIL,"CSSMERR_CSSM_FUNCTION_INTEGRITY_FAIL"}, + { CSSMERR_CSSM_INTERNAL_ERROR,"CSSMERR_CSSM_INTERNAL_ERROR"}, + { CSSMERR_CSSM_MEMORY_ERROR,"CSSMERR_CSSM_MEMORY_ERROR"}, + { CSSMERR_CSSM_MDS_ERROR,"CSSMERR_CSSM_MDS_ERROR"}, + { CSSMERR_CSSM_INVALID_POINTER,"CSSMERR_CSSM_INVALID_POINTER"}, + { CSSMERR_CSSM_INVALID_INPUT_POINTER,"CSSMERR_CSSM_INVALID_INPUT_POINTER"}, + { CSSMERR_CSSM_INVALID_OUTPUT_POINTER,"CSSMERR_CSSM_INVALID_OUTPUT_POINTER"}, + { CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED,"CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED"}, + { CSSMERR_CSSM_SELF_CHECK_FAILED,"CSSMERR_CSSM_SELF_CHECK_FAILED"}, + { CSSMERR_CSSM_OS_ACCESS_DENIED,"CSSMERR_CSSM_OS_ACCESS_DENIED"}, + { CSSMERR_CSSM_FUNCTION_FAILED,"CSSMERR_CSSM_FUNCTION_FAILED"}, + { CSSMERR_CSSM_MODULE_MANIFEST_VERIFY_FAILED,"CSSMERR_CSSM_MODULE_MANIFEST_VERIFY_FAILED"}, + { CSSMERR_CSSM_INVALID_GUID,"CSSMERR_CSSM_INVALID_GUID"}, + { CSSMERR_CSSM_INVALID_CONTEXT_HANDLE,"CSSMERR_CSSM_INVALID_CONTEXT_HANDLE"}, + { CSSMERR_CSSM_INCOMPATIBLE_VERSION,"CSSMERR_CSSM_INCOMPATIBLE_VERSION"}, + { CSSMERR_CSSM_PRIVILEGE_NOT_GRANTED,"CSSMERR_CSSM_PRIVILEGE_NOT_GRANTED"}, + { CSSMERR_CSSM_SCOPE_NOT_SUPPORTED,"CSSMERR_CSSM_SCOPE_NOT_SUPPORTED"}, + { CSSMERR_CSSM_PVC_ALREADY_CONFIGURED,"CSSMERR_CSSM_PVC_ALREADY_CONFIGURED"}, + { CSSMERR_CSSM_INVALID_PVC,"CSSMERR_CSSM_INVALID_PVC"}, + { CSSMERR_CSSM_EMM_LOAD_FAILED,"CSSMERR_CSSM_EMM_LOAD_FAILED"}, + { CSSMERR_CSSM_EMM_UNLOAD_FAILED,"CSSMERR_CSSM_EMM_UNLOAD_FAILED"}, + { CSSMERR_CSSM_ADDIN_LOAD_FAILED,"CSSMERR_CSSM_ADDIN_LOAD_FAILED"}, + { CSSMERR_CSSM_INVALID_KEY_HIERARCHY,"CSSMERR_CSSM_INVALID_KEY_HIERARCHY"}, + { CSSMERR_CSSM_ADDIN_UNLOAD_FAILED,"CSSMERR_CSSM_ADDIN_UNLOAD_FAILED"}, + { CSSMERR_CSSM_LIB_REF_NOT_FOUND,"CSSMERR_CSSM_LIB_REF_NOT_FOUND"}, + { CSSMERR_CSSM_INVALID_ADDIN_FUNCTION_TABLE,"CSSMERR_CSSM_INVALID_ADDIN_FUNCTION_TABLE"}, + { CSSMERR_CSSM_EMM_AUTHENTICATE_FAILED,"CSSMERR_CSSM_EMM_AUTHENTICATE_FAILED"}, + { CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED,"CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED"}, + { CSSMERR_CSSM_INVALID_SERVICE_MASK,"CSSMERR_CSSM_INVALID_SERVICE_MASK"}, + { CSSMERR_CSSM_MODULE_NOT_LOADED,"CSSMERR_CSSM_MODULE_NOT_LOADED"}, + { CSSMERR_CSSM_INVALID_SUBSERVICEID,"CSSMERR_CSSM_INVALID_SUBSERVICEID"}, + { CSSMERR_CSSM_BUFFER_TOO_SMALL,"CSSMERR_CSSM_BUFFER_TOO_SMALL"}, + { CSSMERR_CSSM_INVALID_ATTRIBUTE,"CSSMERR_CSSM_INVALID_ATTRIBUTE"}, + { CSSMERR_CSSM_ATTRIBUTE_NOT_IN_CONTEXT,"CSSMERR_CSSM_ATTRIBUTE_NOT_IN_CONTEXT"}, + { CSSMERR_CSSM_MODULE_MANAGER_INITIALIZE_FAIL,"CSSMERR_CSSM_MODULE_MANAGER_INITIALIZE_FAIL"}, + { CSSMERR_CSSM_MODULE_MANAGER_NOT_FOUND,"CSSMERR_CSSM_MODULE_MANAGER_NOT_FOUND"}, + { CSSMERR_CSSM_EVENT_NOTIFICATION_CALLBACK_NOT_FOUND,"CSSMERR_CSSM_EVENT_NOTIFICATION_CALLBACK_NOT_FOUND"}, + { CSSMERR_CSP_INTERNAL_ERROR,"CSSMERR_CSP_INTERNAL_ERROR"}, + { CSSMERR_CSP_MEMORY_ERROR,"CSSMERR_CSP_MEMORY_ERROR"}, + { CSSMERR_CSP_MDS_ERROR,"CSSMERR_CSP_MDS_ERROR"}, + { CSSMERR_CSP_INVALID_POINTER,"CSSMERR_CSP_INVALID_POINTER"}, + { CSSMERR_CSP_INVALID_INPUT_POINTER,"CSSMERR_CSP_INVALID_INPUT_POINTER"}, + { CSSMERR_CSP_INVALID_OUTPUT_POINTER,"CSSMERR_CSP_INVALID_OUTPUT_POINTER"}, + { CSSMERR_CSP_FUNCTION_NOT_IMPLEMENTED,"CSSMERR_CSP_FUNCTION_NOT_IMPLEMENTED"}, + { CSSMERR_CSP_SELF_CHECK_FAILED,"CSSMERR_CSP_SELF_CHECK_FAILED"}, + { CSSMERR_CSP_OS_ACCESS_DENIED,"CSSMERR_CSP_OS_ACCESS_DENIED"}, + { CSSMERR_CSP_FUNCTION_FAILED,"CSSMERR_CSP_FUNCTION_FAILED"}, + { CSSMERR_CSP_OPERATION_AUTH_DENIED,"CSSMERR_CSP_OPERATION_AUTH_DENIED"}, + { CSSMERR_CSP_OBJECT_USE_AUTH_DENIED,"CSSMERR_CSP_OBJECT_USE_AUTH_DENIED"}, + { CSSMERR_CSP_OBJECT_MANIP_AUTH_DENIED,"CSSMERR_CSP_OBJECT_MANIP_AUTH_DENIED"}, + { CSSMERR_CSP_OBJECT_ACL_NOT_SUPPORTED,"CSSMERR_CSP_OBJECT_ACL_NOT_SUPPORTED"}, + { CSSMERR_CSP_OBJECT_ACL_REQUIRED,"CSSMERR_CSP_OBJECT_ACL_REQUIRED"}, + { CSSMERR_CSP_INVALID_ACCESS_CREDENTIALS,"CSSMERR_CSP_INVALID_ACCESS_CREDENTIALS"}, + { CSSMERR_CSP_INVALID_ACL_BASE_CERTS,"CSSMERR_CSP_INVALID_ACL_BASE_CERTS"}, + { CSSMERR_CSP_ACL_BASE_CERTS_NOT_SUPPORTED,"CSSMERR_CSP_ACL_BASE_CERTS_NOT_SUPPORTED"}, + { CSSMERR_CSP_INVALID_SAMPLE_VALUE,"CSSMERR_CSP_INVALID_SAMPLE_VALUE"}, + { CSSMERR_CSP_SAMPLE_VALUE_NOT_SUPPORTED,"CSSMERR_CSP_SAMPLE_VALUE_NOT_SUPPORTED"}, + { CSSMERR_CSP_INVALID_ACL_SUBJECT_VALUE,"CSSMERR_CSP_INVALID_ACL_SUBJECT_VALUE"}, + { CSSMERR_CSP_ACL_SUBJECT_TYPE_NOT_SUPPORTED,"CSSMERR_CSP_ACL_SUBJECT_TYPE_NOT_SUPPORTED"}, + { CSSMERR_CSP_INVALID_ACL_CHALLENGE_CALLBACK,"CSSMERR_CSP_INVALID_ACL_CHALLENGE_CALLBACK"}, + { CSSMERR_CSP_ACL_CHALLENGE_CALLBACK_FAILED,"CSSMERR_CSP_ACL_CHALLENGE_CALLBACK_FAILED"}, + { CSSMERR_CSP_INVALID_ACL_ENTRY_TAG,"CSSMERR_CSP_INVALID_ACL_ENTRY_TAG"}, + { CSSMERR_CSP_ACL_ENTRY_TAG_NOT_FOUND,"CSSMERR_CSP_ACL_ENTRY_TAG_NOT_FOUND"}, + { CSSMERR_CSP_INVALID_ACL_EDIT_MODE,"CSSMERR_CSP_INVALID_ACL_EDIT_MODE"}, + { CSSMERR_CSP_ACL_CHANGE_FAILED,"CSSMERR_CSP_ACL_CHANGE_FAILED"}, + { CSSMERR_CSP_INVALID_NEW_ACL_ENTRY,"CSSMERR_CSP_INVALID_NEW_ACL_ENTRY"}, + { CSSMERR_CSP_INVALID_NEW_ACL_OWNER,"CSSMERR_CSP_INVALID_NEW_ACL_OWNER"}, + { CSSMERR_CSP_ACL_DELETE_FAILED,"CSSMERR_CSP_ACL_DELETE_FAILED"}, + { CSSMERR_CSP_ACL_REPLACE_FAILED,"CSSMERR_CSP_ACL_REPLACE_FAILED"}, + { CSSMERR_CSP_ACL_ADD_FAILED,"CSSMERR_CSP_ACL_ADD_FAILED"}, + { CSSMERR_CSP_INVALID_CONTEXT_HANDLE,"CSSMERR_CSP_INVALID_CONTEXT_HANDLE"}, + { CSSMERR_CSP_PRIVILEGE_NOT_GRANTED,"CSSMERR_CSP_PRIVILEGE_NOT_GRANTED"}, + { CSSMERR_CSP_INVALID_DATA,"CSSMERR_CSP_INVALID_DATA"}, + { CSSMERR_CSP_INVALID_PASSTHROUGH_ID,"CSSMERR_CSP_INVALID_PASSTHROUGH_ID"}, + { CSSMERR_CSP_INVALID_CRYPTO_DATA,"CSSMERR_CSP_INVALID_CRYPTO_DATA"}, + { CSSMERR_CSP_INPUT_LENGTH_ERROR,"CSSMERR_CSP_INPUT_LENGTH_ERROR"}, + { CSSMERR_CSP_OUTPUT_LENGTH_ERROR,"CSSMERR_CSP_OUTPUT_LENGTH_ERROR"}, + { CSSMERR_CSP_PRIVILEGE_NOT_SUPPORTED,"CSSMERR_CSP_PRIVILEGE_NOT_SUPPORTED"}, + { CSSMERR_CSP_DEVICE_ERROR,"CSSMERR_CSP_DEVICE_ERROR"}, + { CSSMERR_CSP_DEVICE_MEMORY_ERROR,"CSSMERR_CSP_DEVICE_MEMORY_ERROR"}, + { CSSMERR_CSP_ATTACH_HANDLE_BUSY,"CSSMERR_CSP_ATTACH_HANDLE_BUSY"}, + { CSSMERR_CSP_NOT_LOGGED_IN,"CSSMERR_CSP_NOT_LOGGED_IN"}, + { CSSMERR_CSP_INVALID_KEY,"CSSMERR_CSP_INVALID_KEY"}, + { CSSMERR_CSP_INVALID_KEY_REFERENCE,"CSSMERR_CSP_INVALID_KEY_REFERENCE"}, + { CSSMERR_CSP_INVALID_KEY_CLASS,"CSSMERR_CSP_INVALID_KEY_CLASS"}, + { CSSMERR_CSP_ALGID_MISMATCH,"CSSMERR_CSP_ALGID_MISMATCH"}, + { CSSMERR_CSP_KEY_USAGE_INCORRECT,"CSSMERR_CSP_KEY_USAGE_INCORRECT"}, + { CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT,"CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT"}, + { CSSMERR_CSP_KEY_HEADER_INCONSISTENT,"CSSMERR_CSP_KEY_HEADER_INCONSISTENT"}, + { CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT,"CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT"}, + { CSSMERR_CSP_UNSUPPORTED_KEY_SIZE,"CSSMERR_CSP_UNSUPPORTED_KEY_SIZE"}, + { CSSMERR_CSP_INVALID_KEY_POINTER,"CSSMERR_CSP_INVALID_KEY_POINTER"}, + { CSSMERR_CSP_INVALID_KEYUSAGE_MASK,"CSSMERR_CSP_INVALID_KEYUSAGE_MASK"}, + { CSSMERR_CSP_UNSUPPORTED_KEYUSAGE_MASK,"CSSMERR_CSP_UNSUPPORTED_KEYUSAGE_MASK"}, + { CSSMERR_CSP_INVALID_KEYATTR_MASK,"CSSMERR_CSP_INVALID_KEYATTR_MASK"}, + { CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK,"CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK"}, + { CSSMERR_CSP_INVALID_KEY_LABEL,"CSSMERR_CSP_INVALID_KEY_LABEL"}, + { CSSMERR_CSP_UNSUPPORTED_KEY_LABEL,"CSSMERR_CSP_UNSUPPORTED_KEY_LABEL"}, + { CSSMERR_CSP_INVALID_KEY_FORMAT,"CSSMERR_CSP_INVALID_KEY_FORMAT"}, + { CSSMERR_CSP_INVALID_DATA_COUNT,"CSSMERR_CSP_INVALID_DATA_COUNT"}, + { CSSMERR_CSP_VECTOR_OF_BUFS_UNSUPPORTED,"CSSMERR_CSP_VECTOR_OF_BUFS_UNSUPPORTED"}, + { CSSMERR_CSP_INVALID_INPUT_VECTOR,"CSSMERR_CSP_INVALID_INPUT_VECTOR"}, + { CSSMERR_CSP_INVALID_OUTPUT_VECTOR,"CSSMERR_CSP_INVALID_OUTPUT_VECTOR"}, + { CSSMERR_CSP_INVALID_CONTEXT,"CSSMERR_CSP_INVALID_CONTEXT"}, + { CSSMERR_CSP_INVALID_ALGORITHM,"CSSMERR_CSP_INVALID_ALGORITHM"}, + { CSSMERR_CSP_INVALID_ATTR_KEY,"CSSMERR_CSP_INVALID_ATTR_KEY"}, + { CSSMERR_CSP_MISSING_ATTR_KEY,"CSSMERR_CSP_MISSING_ATTR_KEY"}, + { CSSMERR_CSP_INVALID_ATTR_INIT_VECTOR,"CSSMERR_CSP_INVALID_ATTR_INIT_VECTOR"}, + { CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR,"CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR"}, + { CSSMERR_CSP_INVALID_ATTR_SALT,"CSSMERR_CSP_INVALID_ATTR_SALT"}, + { CSSMERR_CSP_MISSING_ATTR_SALT,"CSSMERR_CSP_MISSING_ATTR_SALT"}, + { CSSMERR_CSP_INVALID_ATTR_PADDING,"CSSMERR_CSP_INVALID_ATTR_PADDING"}, + { CSSMERR_CSP_MISSING_ATTR_PADDING,"CSSMERR_CSP_MISSING_ATTR_PADDING"}, + { CSSMERR_CSP_INVALID_ATTR_RANDOM,"CSSMERR_CSP_INVALID_ATTR_RANDOM"}, + { CSSMERR_CSP_MISSING_ATTR_RANDOM,"CSSMERR_CSP_MISSING_ATTR_RANDOM"}, + { CSSMERR_CSP_INVALID_ATTR_SEED,"CSSMERR_CSP_INVALID_ATTR_SEED"}, + { CSSMERR_CSP_MISSING_ATTR_SEED,"CSSMERR_CSP_MISSING_ATTR_SEED"}, + { CSSMERR_CSP_INVALID_ATTR_PASSPHRASE,"CSSMERR_CSP_INVALID_ATTR_PASSPHRASE"}, + { CSSMERR_CSP_MISSING_ATTR_PASSPHRASE,"CSSMERR_CSP_MISSING_ATTR_PASSPHRASE"}, + { CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH,"CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH"}, + { CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH,"CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH"}, + { CSSMERR_CSP_INVALID_ATTR_BLOCK_SIZE,"CSSMERR_CSP_INVALID_ATTR_BLOCK_SIZE"}, + { CSSMERR_CSP_MISSING_ATTR_BLOCK_SIZE,"CSSMERR_CSP_MISSING_ATTR_BLOCK_SIZE"}, + { CSSMERR_CSP_INVALID_ATTR_OUTPUT_SIZE,"CSSMERR_CSP_INVALID_ATTR_OUTPUT_SIZE"}, + { CSSMERR_CSP_MISSING_ATTR_OUTPUT_SIZE,"CSSMERR_CSP_MISSING_ATTR_OUTPUT_SIZE"}, + { CSSMERR_CSP_INVALID_ATTR_ROUNDS,"CSSMERR_CSP_INVALID_ATTR_ROUNDS"}, + { CSSMERR_CSP_MISSING_ATTR_ROUNDS,"CSSMERR_CSP_MISSING_ATTR_ROUNDS"}, + { CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS,"CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS"}, + { CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS,"CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS"}, + { CSSMERR_CSP_INVALID_ATTR_LABEL,"CSSMERR_CSP_INVALID_ATTR_LABEL"}, + { CSSMERR_CSP_MISSING_ATTR_LABEL,"CSSMERR_CSP_MISSING_ATTR_LABEL"}, + { CSSMERR_CSP_INVALID_ATTR_KEY_TYPE,"CSSMERR_CSP_INVALID_ATTR_KEY_TYPE"}, + { CSSMERR_CSP_MISSING_ATTR_KEY_TYPE,"CSSMERR_CSP_MISSING_ATTR_KEY_TYPE"}, + { CSSMERR_CSP_INVALID_ATTR_MODE,"CSSMERR_CSP_INVALID_ATTR_MODE"}, + { CSSMERR_CSP_MISSING_ATTR_MODE,"CSSMERR_CSP_MISSING_ATTR_MODE"}, + { CSSMERR_CSP_INVALID_ATTR_EFFECTIVE_BITS,"CSSMERR_CSP_INVALID_ATTR_EFFECTIVE_BITS"}, + { CSSMERR_CSP_MISSING_ATTR_EFFECTIVE_BITS,"CSSMERR_CSP_MISSING_ATTR_EFFECTIVE_BITS"}, + { CSSMERR_CSP_INVALID_ATTR_START_DATE,"CSSMERR_CSP_INVALID_ATTR_START_DATE"}, + { CSSMERR_CSP_MISSING_ATTR_START_DATE,"CSSMERR_CSP_MISSING_ATTR_START_DATE"}, + { CSSMERR_CSP_INVALID_ATTR_END_DATE,"CSSMERR_CSP_INVALID_ATTR_END_DATE"}, + { CSSMERR_CSP_MISSING_ATTR_END_DATE,"CSSMERR_CSP_MISSING_ATTR_END_DATE"}, + { CSSMERR_CSP_INVALID_ATTR_VERSION,"CSSMERR_CSP_INVALID_ATTR_VERSION"}, + { CSSMERR_CSP_MISSING_ATTR_VERSION,"CSSMERR_CSP_MISSING_ATTR_VERSION"}, + { CSSMERR_CSP_INVALID_ATTR_PRIME,"CSSMERR_CSP_INVALID_ATTR_PRIME"}, + { CSSMERR_CSP_MISSING_ATTR_PRIME,"CSSMERR_CSP_MISSING_ATTR_PRIME"}, + { CSSMERR_CSP_INVALID_ATTR_BASE,"CSSMERR_CSP_INVALID_ATTR_BASE"}, + { CSSMERR_CSP_MISSING_ATTR_BASE,"CSSMERR_CSP_MISSING_ATTR_BASE"}, + { CSSMERR_CSP_INVALID_ATTR_SUBPRIME,"CSSMERR_CSP_INVALID_ATTR_SUBPRIME"}, + { CSSMERR_CSP_MISSING_ATTR_SUBPRIME,"CSSMERR_CSP_MISSING_ATTR_SUBPRIME"}, + { CSSMERR_CSP_INVALID_ATTR_ITERATION_COUNT,"CSSMERR_CSP_INVALID_ATTR_ITERATION_COUNT"}, + { CSSMERR_CSP_MISSING_ATTR_ITERATION_COUNT,"CSSMERR_CSP_MISSING_ATTR_ITERATION_COUNT"}, + { CSSMERR_CSP_INVALID_ATTR_DL_DB_HANDLE,"CSSMERR_CSP_INVALID_ATTR_DL_DB_HANDLE"}, + { CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE,"CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE"}, + { CSSMERR_CSP_INVALID_ATTR_ACCESS_CREDENTIALS,"CSSMERR_CSP_INVALID_ATTR_ACCESS_CREDENTIALS"}, + { CSSMERR_CSP_MISSING_ATTR_ACCESS_CREDENTIALS,"CSSMERR_CSP_MISSING_ATTR_ACCESS_CREDENTIALS"}, + { CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT,"CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT"}, + { CSSMERR_CSP_MISSING_ATTR_PUBLIC_KEY_FORMAT,"CSSMERR_CSP_MISSING_ATTR_PUBLIC_KEY_FORMAT"}, + { CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT,"CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT"}, + { CSSMERR_CSP_MISSING_ATTR_PRIVATE_KEY_FORMAT,"CSSMERR_CSP_MISSING_ATTR_PRIVATE_KEY_FORMAT"}, + { CSSMERR_CSP_INVALID_ATTR_SYMMETRIC_KEY_FORMAT,"CSSMERR_CSP_INVALID_ATTR_SYMMETRIC_KEY_FORMAT"}, + { CSSMERR_CSP_MISSING_ATTR_SYMMETRIC_KEY_FORMAT,"CSSMERR_CSP_MISSING_ATTR_SYMMETRIC_KEY_FORMAT"}, + { CSSMERR_CSP_INVALID_ATTR_WRAPPED_KEY_FORMAT,"CSSMERR_CSP_INVALID_ATTR_WRAPPED_KEY_FORMAT"}, + { CSSMERR_CSP_MISSING_ATTR_WRAPPED_KEY_FORMAT,"CSSMERR_CSP_MISSING_ATTR_WRAPPED_KEY_FORMAT"}, + { CSSMERR_CSP_STAGED_OPERATION_IN_PROGRESS,"CSSMERR_CSP_STAGED_OPERATION_IN_PROGRESS"}, + { CSSMERR_CSP_STAGED_OPERATION_NOT_STARTED,"CSSMERR_CSP_STAGED_OPERATION_NOT_STARTED"}, + { CSSMERR_CSP_VERIFY_FAILED,"CSSMERR_CSP_VERIFY_FAILED"}, + { CSSMERR_CSP_INVALID_SIGNATURE,"CSSMERR_CSP_INVALID_SIGNATURE"}, + { CSSMERR_CSP_QUERY_SIZE_UNKNOWN,"CSSMERR_CSP_QUERY_SIZE_UNKNOWN"}, + { CSSMERR_CSP_BLOCK_SIZE_MISMATCH,"CSSMERR_CSP_BLOCK_SIZE_MISMATCH"}, + { CSSMERR_CSP_PRIVATE_KEY_NOT_FOUND,"CSSMERR_CSP_PRIVATE_KEY_NOT_FOUND"}, + { CSSMERR_CSP_PUBLIC_KEY_INCONSISTENT,"CSSMERR_CSP_PUBLIC_KEY_INCONSISTENT"}, + { CSSMERR_CSP_DEVICE_VERIFY_FAILED,"CSSMERR_CSP_DEVICE_VERIFY_FAILED"}, + { CSSMERR_CSP_INVALID_LOGIN_NAME,"CSSMERR_CSP_INVALID_LOGIN_NAME"}, + { CSSMERR_CSP_ALREADY_LOGGED_IN,"CSSMERR_CSP_ALREADY_LOGGED_IN"}, + { CSSMERR_CSP_PRIVATE_KEY_ALREADY_EXISTS,"CSSMERR_CSP_PRIVATE_KEY_ALREADY_EXISTS"}, + { CSSMERR_CSP_KEY_LABEL_ALREADY_EXISTS,"CSSMERR_CSP_KEY_LABEL_ALREADY_EXISTS"}, + { CSSMERR_CSP_INVALID_DIGEST_ALGORITHM,"CSSMERR_CSP_INVALID_DIGEST_ALGORITHM"}, + { CSSMERR_CSP_CRYPTO_DATA_CALLBACK_FAILED,"CSSMERR_CSP_CRYPTO_DATA_CALLBACK_FAILED"}, + { CSSMERR_TP_INTERNAL_ERROR,"CSSMERR_TP_INTERNAL_ERROR"}, + { CSSMERR_TP_MEMORY_ERROR,"CSSMERR_TP_MEMORY_ERROR"}, + { CSSMERR_TP_MDS_ERROR,"CSSMERR_TP_MDS_ERROR"}, + { CSSMERR_TP_INVALID_POINTER,"CSSMERR_TP_INVALID_POINTER"}, + { CSSMERR_TP_INVALID_INPUT_POINTER,"CSSMERR_TP_INVALID_INPUT_POINTER"}, + { CSSMERR_TP_INVALID_OUTPUT_POINTER,"CSSMERR_TP_INVALID_OUTPUT_POINTER"}, + { CSSMERR_TP_FUNCTION_NOT_IMPLEMENTED,"CSSMERR_TP_FUNCTION_NOT_IMPLEMENTED"}, + { CSSMERR_TP_SELF_CHECK_FAILED,"CSSMERR_TP_SELF_CHECK_FAILED"}, + { CSSMERR_TP_OS_ACCESS_DENIED,"CSSMERR_TP_OS_ACCESS_DENIED"}, + { CSSMERR_TP_FUNCTION_FAILED,"CSSMERR_TP_FUNCTION_FAILED"}, + { CSSMERR_TP_INVALID_CONTEXT_HANDLE,"CSSMERR_TP_INVALID_CONTEXT_HANDLE"}, + { CSSMERR_TP_INVALID_DATA,"CSSMERR_TP_INVALID_DATA"}, + { CSSMERR_TP_INVALID_DB_LIST,"CSSMERR_TP_INVALID_DB_LIST"}, + { CSSMERR_TP_INVALID_CERTGROUP_POINTER,"CSSMERR_TP_INVALID_CERTGROUP_POINTER"}, + { CSSMERR_TP_INVALID_CERT_POINTER,"CSSMERR_TP_INVALID_CERT_POINTER"}, + { CSSMERR_TP_INVALID_CRL_POINTER,"CSSMERR_TP_INVALID_CRL_POINTER"}, + { CSSMERR_TP_INVALID_FIELD_POINTER,"CSSMERR_TP_INVALID_FIELD_POINTER"}, + { CSSMERR_TP_INVALID_NETWORK_ADDR,"CSSMERR_TP_INVALID_NETWORK_ADDR"}, + { CSSMERR_TP_CRL_ALREADY_SIGNED,"CSSMERR_TP_CRL_ALREADY_SIGNED"}, + { CSSMERR_TP_INVALID_NUMBER_OF_FIELDS,"CSSMERR_TP_INVALID_NUMBER_OF_FIELDS"}, + { CSSMERR_TP_VERIFICATION_FAILURE,"CSSMERR_TP_VERIFICATION_FAILURE"}, + { CSSMERR_TP_INVALID_DB_HANDLE,"CSSMERR_TP_INVALID_DB_HANDLE"}, + { CSSMERR_TP_UNKNOWN_FORMAT,"CSSMERR_TP_UNKNOWN_FORMAT"}, + { CSSMERR_TP_UNKNOWN_TAG,"CSSMERR_TP_UNKNOWN_TAG"}, + { CSSMERR_TP_INVALID_PASSTHROUGH_ID,"CSSMERR_TP_INVALID_PASSTHROUGH_ID"}, + { CSSMERR_TP_INVALID_CSP_HANDLE,"CSSMERR_TP_INVALID_CSP_HANDLE"}, + { CSSMERR_TP_INVALID_DL_HANDLE,"CSSMERR_TP_INVALID_DL_HANDLE"}, + { CSSMERR_TP_INVALID_CL_HANDLE,"CSSMERR_TP_INVALID_CL_HANDLE"}, + { CSSMERR_TP_INVALID_DB_LIST_POINTER,"CSSMERR_TP_INVALID_DB_LIST_POINTER"}, + { CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER,"CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER"}, + { CSSMERR_TP_INVALID_IDENTIFIER_POINTER,"CSSMERR_TP_INVALID_IDENTIFIER_POINTER"}, + { CSSMERR_TP_INVALID_KEYCACHE_HANDLE,"CSSMERR_TP_INVALID_KEYCACHE_HANDLE"}, + { CSSMERR_TP_INVALID_CERTGROUP,"CSSMERR_TP_INVALID_CERTGROUP"}, + { CSSMERR_TP_INVALID_CRLGROUP,"CSSMERR_TP_INVALID_CRLGROUP"}, + { CSSMERR_TP_INVALID_CRLGROUP_POINTER,"CSSMERR_TP_INVALID_CRLGROUP_POINTER"}, + { CSSMERR_TP_AUTHENTICATION_FAILED,"CSSMERR_TP_AUTHENTICATION_FAILED"}, + { CSSMERR_TP_CERTGROUP_INCOMPLETE,"CSSMERR_TP_CERTGROUP_INCOMPLETE"}, + { CSSMERR_TP_CERTIFICATE_CANT_OPERATE,"CSSMERR_TP_CERTIFICATE_CANT_OPERATE"}, + { CSSMERR_TP_CERT_EXPIRED,"CSSMERR_TP_CERT_EXPIRED"}, + { CSSMERR_TP_CERT_NOT_VALID_YET,"CSSMERR_TP_CERT_NOT_VALID_YET"}, + { CSSMERR_TP_CERT_REVOKED,"CSSMERR_TP_CERT_REVOKED"}, + { CSSMERR_TP_CERT_SUSPENDED,"CSSMERR_TP_CERT_SUSPENDED"}, + { CSSMERR_TP_INSUFFICIENT_CREDENTIALS,"CSSMERR_TP_INSUFFICIENT_CREDENTIALS"}, + { CSSMERR_TP_INVALID_ACTION,"CSSMERR_TP_INVALID_ACTION"}, + { CSSMERR_TP_INVALID_ACTION_DATA,"CSSMERR_TP_INVALID_ACTION_DATA"}, + { CSSMERR_TP_INVALID_ANCHOR_CERT,"CSSMERR_TP_INVALID_ANCHOR_CERT"}, + { CSSMERR_TP_INVALID_AUTHORITY,"CSSMERR_TP_INVALID_AUTHORITY"}, + { CSSMERR_TP_VERIFY_ACTION_FAILED,"CSSMERR_TP_VERIFY_ACTION_FAILED"}, + { CSSMERR_TP_INVALID_CERTIFICATE,"CSSMERR_TP_INVALID_CERTIFICATE"}, + { CSSMERR_TP_INVALID_CERT_AUTHORITY,"CSSMERR_TP_INVALID_CERT_AUTHORITY"}, + { CSSMERR_TP_INVALID_CRL_AUTHORITY,"CSSMERR_TP_INVALID_CRL_AUTHORITY"}, + { CSSMERR_TP_INVALID_CRL_ENCODING,"CSSMERR_TP_INVALID_CRL_ENCODING"}, + { CSSMERR_TP_INVALID_CRL_TYPE,"CSSMERR_TP_INVALID_CRL_TYPE"}, + { CSSMERR_TP_INVALID_CRL,"CSSMERR_TP_INVALID_CRL"}, + { CSSMERR_TP_INVALID_FORM_TYPE,"CSSMERR_TP_INVALID_FORM_TYPE"}, + { CSSMERR_TP_INVALID_ID,"CSSMERR_TP_INVALID_ID"}, + { CSSMERR_TP_INVALID_IDENTIFIER,"CSSMERR_TP_INVALID_IDENTIFIER"}, + { CSSMERR_TP_INVALID_INDEX,"CSSMERR_TP_INVALID_INDEX"}, + { CSSMERR_TP_INVALID_NAME,"CSSMERR_TP_INVALID_NAME"}, + { CSSMERR_TP_INVALID_POLICY_IDENTIFIERS,"CSSMERR_TP_INVALID_POLICY_IDENTIFIERS"}, + { CSSMERR_TP_INVALID_TIMESTRING,"CSSMERR_TP_INVALID_TIMESTRING"}, + { CSSMERR_TP_INVALID_REASON,"CSSMERR_TP_INVALID_REASON"}, + { CSSMERR_TP_INVALID_REQUEST_INPUTS,"CSSMERR_TP_INVALID_REQUEST_INPUTS"}, + { CSSMERR_TP_INVALID_RESPONSE_VECTOR,"CSSMERR_TP_INVALID_RESPONSE_VECTOR"}, + { CSSMERR_TP_INVALID_SIGNATURE,"CSSMERR_TP_INVALID_SIGNATURE"}, + { CSSMERR_TP_INVALID_STOP_ON_POLICY,"CSSMERR_TP_INVALID_STOP_ON_POLICY"}, + { CSSMERR_TP_INVALID_CALLBACK,"CSSMERR_TP_INVALID_CALLBACK"}, + { CSSMERR_TP_INVALID_TUPLE,"CSSMERR_TP_INVALID_TUPLE"}, + { CSSMERR_TP_NOT_SIGNER,"CSSMERR_TP_NOT_SIGNER"}, + { CSSMERR_TP_NOT_TRUSTED,"CSSMERR_TP_NOT_TRUSTED"}, + { CSSMERR_TP_NO_DEFAULT_AUTHORITY,"CSSMERR_TP_NO_DEFAULT_AUTHORITY"}, + { CSSMERR_TP_REJECTED_FORM,"CSSMERR_TP_REJECTED_FORM"}, + { CSSMERR_TP_REQUEST_LOST,"CSSMERR_TP_REQUEST_LOST"}, + { CSSMERR_TP_REQUEST_REJECTED,"CSSMERR_TP_REQUEST_REJECTED"}, + { CSSMERR_TP_UNSUPPORTED_ADDR_TYPE,"CSSMERR_TP_UNSUPPORTED_ADDR_TYPE"}, + { CSSMERR_TP_UNSUPPORTED_SERVICE,"CSSMERR_TP_UNSUPPORTED_SERVICE"}, + { CSSMERR_TP_INVALID_TUPLEGROUP_POINTER,"CSSMERR_TP_INVALID_TUPLEGROUP_POINTER"}, + { CSSMERR_TP_INVALID_TUPLEGROUP,"CSSMERR_TP_INVALID_TUPLEGROUP"}, + { CSSMERR_AC_INTERNAL_ERROR,"CSSMERR_AC_INTERNAL_ERROR"}, + { CSSMERR_AC_MEMORY_ERROR,"CSSMERR_AC_MEMORY_ERROR"}, + { CSSMERR_AC_MDS_ERROR,"CSSMERR_AC_MDS_ERROR"}, + { CSSMERR_AC_INVALID_POINTER,"CSSMERR_AC_INVALID_POINTER"}, + { CSSMERR_AC_INVALID_INPUT_POINTER,"CSSMERR_AC_INVALID_INPUT_POINTER"}, + { CSSMERR_AC_INVALID_OUTPUT_POINTER,"CSSMERR_AC_INVALID_OUTPUT_POINTER"}, + { CSSMERR_AC_FUNCTION_NOT_IMPLEMENTED,"CSSMERR_AC_FUNCTION_NOT_IMPLEMENTED"}, + { CSSMERR_AC_SELF_CHECK_FAILED,"CSSMERR_AC_SELF_CHECK_FAILED"}, + { CSSMERR_AC_OS_ACCESS_DENIED,"CSSMERR_AC_OS_ACCESS_DENIED"}, + { CSSMERR_AC_FUNCTION_FAILED,"CSSMERR_AC_FUNCTION_FAILED"}, + { CSSMERR_AC_INVALID_CONTEXT_HANDLE,"CSSMERR_AC_INVALID_CONTEXT_HANDLE"}, + { CSSMERR_AC_INVALID_DATA,"CSSMERR_AC_INVALID_DATA"}, + { CSSMERR_AC_INVALID_DB_LIST,"CSSMERR_AC_INVALID_DB_LIST"}, + { CSSMERR_AC_INVALID_PASSTHROUGH_ID,"CSSMERR_AC_INVALID_PASSTHROUGH_ID"}, + { CSSMERR_AC_INVALID_DL_HANDLE,"CSSMERR_AC_INVALID_DL_HANDLE"}, + { CSSMERR_AC_INVALID_CL_HANDLE,"CSSMERR_AC_INVALID_CL_HANDLE"}, + { CSSMERR_AC_INVALID_TP_HANDLE,"CSSMERR_AC_INVALID_TP_HANDLE"}, + { CSSMERR_AC_INVALID_DB_HANDLE,"CSSMERR_AC_INVALID_DB_HANDLE"}, + { CSSMERR_AC_INVALID_DB_LIST_POINTER,"CSSMERR_AC_INVALID_DB_LIST_POINTER"}, + { CSSMERR_AC_INVALID_BASE_ACLS,"CSSMERR_AC_INVALID_BASE_ACLS"}, + { CSSMERR_AC_INVALID_TUPLE_CREDENTIALS,"CSSMERR_AC_INVALID_TUPLE_CREDENTIALS"}, + { CSSMERR_AC_INVALID_ENCODING,"CSSMERR_AC_INVALID_ENCODING"}, + { CSSMERR_AC_INVALID_VALIDITY_PERIOD,"CSSMERR_AC_INVALID_VALIDITY_PERIOD"}, + { CSSMERR_AC_INVALID_REQUESTOR,"CSSMERR_AC_INVALID_REQUESTOR"}, + { CSSMERR_AC_INVALID_REQUEST_DESCRIPTOR,"CSSMERR_AC_INVALID_REQUEST_DESCRIPTOR"}, + { CSSMERR_CL_INTERNAL_ERROR,"CSSMERR_CL_INTERNAL_ERROR"}, + { CSSMERR_CL_MEMORY_ERROR,"CSSMERR_CL_MEMORY_ERROR"}, + { CSSMERR_CL_MDS_ERROR,"CSSMERR_CL_MDS_ERROR"}, + { CSSMERR_CL_INVALID_POINTER,"CSSMERR_CL_INVALID_POINTER"}, + { CSSMERR_CL_INVALID_INPUT_POINTER,"CSSMERR_CL_INVALID_INPUT_POINTER"}, + { CSSMERR_CL_INVALID_OUTPUT_POINTER,"CSSMERR_CL_INVALID_OUTPUT_POINTER"}, + { CSSMERR_CL_FUNCTION_NOT_IMPLEMENTED,"CSSMERR_CL_FUNCTION_NOT_IMPLEMENTED"}, + { CSSMERR_CL_SELF_CHECK_FAILED,"CSSMERR_CL_SELF_CHECK_FAILED"}, + { CSSMERR_CL_OS_ACCESS_DENIED,"CSSMERR_CL_OS_ACCESS_DENIED"}, + { CSSMERR_CL_FUNCTION_FAILED,"CSSMERR_CL_FUNCTION_FAILED"}, + { CSSMERR_CL_INVALID_CONTEXT_HANDLE,"CSSMERR_CL_INVALID_CONTEXT_HANDLE"}, + { CSSMERR_CL_INVALID_CERTGROUP_POINTER,"CSSMERR_CL_INVALID_CERTGROUP_POINTER"}, + { CSSMERR_CL_INVALID_CERT_POINTER,"CSSMERR_CL_INVALID_CERT_POINTER"}, + { CSSMERR_CL_INVALID_CRL_POINTER,"CSSMERR_CL_INVALID_CRL_POINTER"}, + { CSSMERR_CL_INVALID_FIELD_POINTER,"CSSMERR_CL_INVALID_FIELD_POINTER"}, + { CSSMERR_CL_INVALID_DATA,"CSSMERR_CL_INVALID_DATA"}, + { CSSMERR_CL_CRL_ALREADY_SIGNED,"CSSMERR_CL_CRL_ALREADY_SIGNED"}, + { CSSMERR_CL_INVALID_NUMBER_OF_FIELDS,"CSSMERR_CL_INVALID_NUMBER_OF_FIELDS"}, + { CSSMERR_CL_VERIFICATION_FAILURE,"CSSMERR_CL_VERIFICATION_FAILURE"}, + { CSSMERR_CL_UNKNOWN_FORMAT,"CSSMERR_CL_UNKNOWN_FORMAT"}, + { CSSMERR_CL_UNKNOWN_TAG,"CSSMERR_CL_UNKNOWN_TAG"}, + { CSSMERR_CL_INVALID_PASSTHROUGH_ID,"CSSMERR_CL_INVALID_PASSTHROUGH_ID"}, + { CSSMERR_CL_INVALID_BUNDLE_POINTER,"CSSMERR_CL_INVALID_BUNDLE_POINTER"}, + { CSSMERR_CL_INVALID_CACHE_HANDLE,"CSSMERR_CL_INVALID_CACHE_HANDLE"}, + { CSSMERR_CL_INVALID_RESULTS_HANDLE,"CSSMERR_CL_INVALID_RESULTS_HANDLE"}, + { CSSMERR_CL_INVALID_BUNDLE_INFO,"CSSMERR_CL_INVALID_BUNDLE_INFO"}, + { CSSMERR_CL_INVALID_CRL_INDEX,"CSSMERR_CL_INVALID_CRL_INDEX"}, + { CSSMERR_CL_INVALID_SCOPE,"CSSMERR_CL_INVALID_SCOPE"}, + { CSSMERR_CL_NO_FIELD_VALUES,"CSSMERR_CL_NO_FIELD_VALUES"}, + { CSSMERR_CL_SCOPE_NOT_SUPPORTED,"CSSMERR_CL_SCOPE_NOT_SUPPORTED"}, + { CSSMERR_DL_INTERNAL_ERROR,"CSSMERR_DL_INTERNAL_ERROR"}, + { CSSMERR_DL_MEMORY_ERROR,"CSSMERR_DL_MEMORY_ERROR"}, + { CSSMERR_DL_MDS_ERROR,"CSSMERR_DL_MDS_ERROR"}, + { CSSMERR_DL_INVALID_POINTER,"CSSMERR_DL_INVALID_POINTER"}, + { CSSMERR_DL_INVALID_INPUT_POINTER,"CSSMERR_DL_INVALID_INPUT_POINTER"}, + { CSSMERR_DL_INVALID_OUTPUT_POINTER,"CSSMERR_DL_INVALID_OUTPUT_POINTER"}, + { CSSMERR_DL_FUNCTION_NOT_IMPLEMENTED,"CSSMERR_DL_FUNCTION_NOT_IMPLEMENTED"}, + { CSSMERR_DL_SELF_CHECK_FAILED,"CSSMERR_DL_SELF_CHECK_FAILED"}, + { CSSMERR_DL_OS_ACCESS_DENIED,"CSSMERR_DL_OS_ACCESS_DENIED"}, + { CSSMERR_DL_FUNCTION_FAILED,"CSSMERR_DL_FUNCTION_FAILED"}, + { CSSMERR_DL_INVALID_CSP_HANDLE,"CSSMERR_DL_INVALID_CSP_HANDLE"}, + { CSSMERR_DL_INVALID_DL_HANDLE,"CSSMERR_DL_INVALID_DL_HANDLE"}, + { CSSMERR_DL_INVALID_CL_HANDLE,"CSSMERR_DL_INVALID_CL_HANDLE"}, + { CSSMERR_DL_INVALID_DB_LIST_POINTER,"CSSMERR_DL_INVALID_DB_LIST_POINTER"}, + { CSSMERR_DL_OPERATION_AUTH_DENIED,"CSSMERR_DL_OPERATION_AUTH_DENIED"}, + { CSSMERR_DL_OBJECT_USE_AUTH_DENIED,"CSSMERR_DL_OBJECT_USE_AUTH_DENIED"}, + { CSSMERR_DL_OBJECT_MANIP_AUTH_DENIED,"CSSMERR_DL_OBJECT_MANIP_AUTH_DENIED"}, + { CSSMERR_DL_OBJECT_ACL_NOT_SUPPORTED,"CSSMERR_DL_OBJECT_ACL_NOT_SUPPORTED"}, + { CSSMERR_DL_OBJECT_ACL_REQUIRED,"CSSMERR_DL_OBJECT_ACL_REQUIRED"}, + { CSSMERR_DL_INVALID_ACCESS_CREDENTIALS,"CSSMERR_DL_INVALID_ACCESS_CREDENTIALS"}, + { CSSMERR_DL_INVALID_ACL_BASE_CERTS,"CSSMERR_DL_INVALID_ACL_BASE_CERTS"}, + { CSSMERR_DL_ACL_BASE_CERTS_NOT_SUPPORTED,"CSSMERR_DL_ACL_BASE_CERTS_NOT_SUPPORTED"}, + { CSSMERR_DL_INVALID_SAMPLE_VALUE,"CSSMERR_DL_INVALID_SAMPLE_VALUE"}, + { CSSMERR_DL_SAMPLE_VALUE_NOT_SUPPORTED,"CSSMERR_DL_SAMPLE_VALUE_NOT_SUPPORTED"}, + { CSSMERR_DL_INVALID_ACL_SUBJECT_VALUE,"CSSMERR_DL_INVALID_ACL_SUBJECT_VALUE"}, + { CSSMERR_DL_ACL_SUBJECT_TYPE_NOT_SUPPORTED,"CSSMERR_DL_ACL_SUBJECT_TYPE_NOT_SUPPORTED"}, + { CSSMERR_DL_INVALID_ACL_CHALLENGE_CALLBACK,"CSSMERR_DL_INVALID_ACL_CHALLENGE_CALLBACK"}, + { CSSMERR_DL_ACL_CHALLENGE_CALLBACK_FAILED,"CSSMERR_DL_ACL_CHALLENGE_CALLBACK_FAILED"}, + { CSSMERR_DL_INVALID_ACL_ENTRY_TAG,"CSSMERR_DL_INVALID_ACL_ENTRY_TAG"}, + { CSSMERR_DL_ACL_ENTRY_TAG_NOT_FOUND,"CSSMERR_DL_ACL_ENTRY_TAG_NOT_FOUND"}, + { CSSMERR_DL_INVALID_ACL_EDIT_MODE,"CSSMERR_DL_INVALID_ACL_EDIT_MODE"}, + { CSSMERR_DL_ACL_CHANGE_FAILED,"CSSMERR_DL_ACL_CHANGE_FAILED"}, + { CSSMERR_DL_INVALID_NEW_ACL_ENTRY,"CSSMERR_DL_INVALID_NEW_ACL_ENTRY"}, + { CSSMERR_DL_INVALID_NEW_ACL_OWNER,"CSSMERR_DL_INVALID_NEW_ACL_OWNER"}, + { CSSMERR_DL_ACL_DELETE_FAILED,"CSSMERR_DL_ACL_DELETE_FAILED"}, + { CSSMERR_DL_ACL_REPLACE_FAILED,"CSSMERR_DL_ACL_REPLACE_FAILED"}, + { CSSMERR_DL_ACL_ADD_FAILED,"CSSMERR_DL_ACL_ADD_FAILED"}, + { CSSMERR_DL_INVALID_DB_HANDLE,"CSSMERR_DL_INVALID_DB_HANDLE"}, + { CSSMERR_DL_INVALID_PASSTHROUGH_ID,"CSSMERR_DL_INVALID_PASSTHROUGH_ID"}, + { CSSMERR_DL_INVALID_NETWORK_ADDR,"CSSMERR_DL_INVALID_NETWORK_ADDR"}, + { CSSMERR_DL_DATABASE_CORRUPT,"CSSMERR_DL_DATABASE_CORRUPT"}, + { CSSMERR_DL_INVALID_RECORD_INDEX,"CSSMERR_DL_INVALID_RECORD_INDEX"}, + { CSSMERR_DL_INVALID_RECORDTYPE,"CSSMERR_DL_INVALID_RECORDTYPE"}, + { CSSMERR_DL_INVALID_FIELD_NAME,"CSSMERR_DL_INVALID_FIELD_NAME"}, + { CSSMERR_DL_UNSUPPORTED_FIELD_FORMAT,"CSSMERR_DL_UNSUPPORTED_FIELD_FORMAT"}, + { CSSMERR_DL_UNSUPPORTED_INDEX_INFO,"CSSMERR_DL_UNSUPPORTED_INDEX_INFO"}, + { CSSMERR_DL_UNSUPPORTED_LOCALITY,"CSSMERR_DL_UNSUPPORTED_LOCALITY"}, + { CSSMERR_DL_UNSUPPORTED_NUM_ATTRIBUTES,"CSSMERR_DL_UNSUPPORTED_NUM_ATTRIBUTES"}, + { CSSMERR_DL_UNSUPPORTED_NUM_INDEXES,"CSSMERR_DL_UNSUPPORTED_NUM_INDEXES"}, + { CSSMERR_DL_UNSUPPORTED_NUM_RECORDTYPES,"CSSMERR_DL_UNSUPPORTED_NUM_RECORDTYPES"}, + { CSSMERR_DL_UNSUPPORTED_RECORDTYPE,"CSSMERR_DL_UNSUPPORTED_RECORDTYPE"}, + { CSSMERR_DL_FIELD_SPECIFIED_MULTIPLE,"CSSMERR_DL_FIELD_SPECIFIED_MULTIPLE"}, + { CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT,"CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT"}, + { CSSMERR_DL_INVALID_PARSING_MODULE,"CSSMERR_DL_INVALID_PARSING_MODULE"}, + { CSSMERR_DL_INVALID_DB_NAME,"CSSMERR_DL_INVALID_DB_NAME"}, + { CSSMERR_DL_DATASTORE_DOESNOT_EXIST,"CSSMERR_DL_DATASTORE_DOESNOT_EXIST"}, + { CSSMERR_DL_DATASTORE_ALREADY_EXISTS,"CSSMERR_DL_DATASTORE_ALREADY_EXISTS"}, + { CSSMERR_DL_DB_LOCKED,"CSSMERR_DL_DB_LOCKED"}, + { CSSMERR_DL_DATASTORE_IS_OPEN,"CSSMERR_DL_DATASTORE_IS_OPEN"}, + { CSSMERR_DL_RECORD_NOT_FOUND,"CSSMERR_DL_RECORD_NOT_FOUND"}, + { CSSMERR_DL_MISSING_VALUE,"CSSMERR_DL_MISSING_VALUE"}, + { CSSMERR_DL_UNSUPPORTED_QUERY,"CSSMERR_DL_UNSUPPORTED_QUERY"}, + { CSSMERR_DL_UNSUPPORTED_QUERY_LIMITS,"CSSMERR_DL_UNSUPPORTED_QUERY_LIMITS"}, + { CSSMERR_DL_UNSUPPORTED_NUM_SELECTION_PREDS,"CSSMERR_DL_UNSUPPORTED_NUM_SELECTION_PREDS"}, + { CSSMERR_DL_UNSUPPORTED_OPERATOR,"CSSMERR_DL_UNSUPPORTED_OPERATOR"}, + { CSSMERR_DL_INVALID_RESULTS_HANDLE,"CSSMERR_DL_INVALID_RESULTS_HANDLE"}, + { CSSMERR_DL_INVALID_DB_LOCATION,"CSSMERR_DL_INVALID_DB_LOCATION"}, + { CSSMERR_DL_INVALID_ACCESS_REQUEST,"CSSMERR_DL_INVALID_ACCESS_REQUEST"}, + { CSSMERR_DL_INVALID_INDEX_INFO,"CSSMERR_DL_INVALID_INDEX_INFO"}, + { CSSMERR_DL_INVALID_SELECTION_TAG,"CSSMERR_DL_INVALID_SELECTION_TAG"}, + { CSSMERR_DL_INVALID_NEW_OWNER,"CSSMERR_DL_INVALID_NEW_OWNER"}, + { CSSMERR_DL_INVALID_RECORD_UID,"CSSMERR_DL_INVALID_RECORD_UID"}, + { CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA,"CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA"}, + { CSSMERR_DL_INVALID_MODIFY_MODE,"CSSMERR_DL_INVALID_MODIFY_MODE"}, + { CSSMERR_DL_INVALID_OPEN_PARAMETERS,"CSSMERR_DL_INVALID_OPEN_PARAMETERS"}, + { CSSMERR_DL_RECORD_MODIFIED,"CSSMERR_DL_RECORD_MODIFIED"}, + { CSSMERR_DL_ENDOFDATA,"CSSMERR_DL_ENDOFDATA"}, + { CSSMERR_DL_INVALID_QUERY,"CSSMERR_DL_INVALID_QUERY"}, + { CSSMERR_DL_INVALID_VALUE,"CSSMERR_DL_INVALID_VALUE"}, + { CSSMERR_DL_MULTIPLE_VALUES_UNSUPPORTED,"CSSMERR_DL_MULTIPLE_VALUES_UNSUPPORTED"}, + { CSSMERR_DL_STALE_UNIQUE_RECORD,"CSSMERR_DL_STALE_UNIQUE_RECORD"}, + /* Error codes from cssmapple.h */ + { CSSMERR_CSSM_NO_USER_INTERACTION,"CSSMERR_CSSM_NO_USER_INTERACTION"}, + { CSSMERR_AC_NO_USER_INTERACTION,"CSSMERR_AC_NO_USER_INTERACTION"}, + { CSSMERR_CSP_NO_USER_INTERACTION,"CSSMERR_CSP_NO_USER_INTERACTION"}, + { CSSMERR_CL_NO_USER_INTERACTION,"CSSMERR_CL_NO_USER_INTERACTION"}, + { CSSMERR_DL_NO_USER_INTERACTION,"CSSMERR_DL_NO_USER_INTERACTION"}, + { CSSMERR_TP_NO_USER_INTERACTION,"CSSMERR_TP_NO_USER_INTERACTION"}, + { CSSMERR_CSSM_USER_CANCELED,"CSSMERR_CSSM_USER_CANCELED"}, + { CSSMERR_AC_USER_CANCELED,"CSSMERR_AC_USER_CANCELED"}, + { CSSMERR_CSP_USER_CANCELED,"CSSMERR_CSP_USER_CANCELED"}, + { CSSMERR_CL_USER_CANCELED,"CSSMERR_CL_USER_CANCELED"}, + { CSSMERR_DL_USER_CANCELED,"CSSMERR_DL_USER_CANCELED"}, + { CSSMERR_TP_USER_CANCELED,"CSSMERR_TP_USER_CANCELED"}, + { CSSMERR_CSSM_SERVICE_NOT_AVAILABLE,"CSSMERR_CSSM_SERVICE_NOT_AVAILABLE"}, + { CSSMERR_AC_SERVICE_NOT_AVAILABLE,"CSSMERR_AC_SERVICE_NOT_AVAILABLE"}, + { CSSMERR_CSP_SERVICE_NOT_AVAILABLE,"CSSMERR_CSP_SERVICE_NOT_AVAILABLE"}, + { CSSMERR_CL_SERVICE_NOT_AVAILABLE,"CSSMERR_CL_SERVICE_NOT_AVAILABLE"}, + { CSSMERR_DL_SERVICE_NOT_AVAILABLE,"CSSMERR_DL_SERVICE_NOT_AVAILABLE"}, + { CSSMERR_TP_SERVICE_NOT_AVAILABLE,"CSSMERR_TP_SERVICE_NOT_AVAILABLE"}, + { CSSMERR_CSSM_INSUFFICIENT_CLIENT_IDENTIFICATION,"CSSMERR_CSSM_INSUFFICIENT_CLIENT_IDENTIFICATION"}, + { CSSMERR_AC_INSUFFICIENT_CLIENT_IDENTIFICATION,"CSSMERR_AC_INSUFFICIENT_CLIENT_IDENTIFICATION"}, + { CSSMERR_CSP_INSUFFICIENT_CLIENT_IDENTIFICATION,"CSSMERR_CSP_INSUFFICIENT_CLIENT_IDENTIFICATION"}, + { CSSMERR_CL_INSUFFICIENT_CLIENT_IDENTIFICATION,"CSSMERR_CL_INSUFFICIENT_CLIENT_IDENTIFICATION"}, + { CSSMERR_DL_INSUFFICIENT_CLIENT_IDENTIFICATION,"CSSMERR_DL_INSUFFICIENT_CLIENT_IDENTIFICATION"}, + { CSSMERR_TP_INSUFFICIENT_CLIENT_IDENTIFICATION,"CSSMERR_TP_INSUFFICIENT_CLIENT_IDENTIFICATION"}, + { CSSMERR_CSSM_DEVICE_RESET,"CSSMERR_CSSM_DEVICE_RESET"}, + { CSSMERR_AC_DEVICE_RESET,"CSSMERR_AC_DEVICE_RESET"}, + { CSSMERR_CSP_DEVICE_RESET,"CSSMERR_CSP_DEVICE_RESET"}, + { CSSMERR_CL_DEVICE_RESET,"CSSMERR_CL_DEVICE_RESET"}, + { CSSMERR_DL_DEVICE_RESET,"CSSMERR_DL_DEVICE_RESET"}, + { CSSMERR_TP_DEVICE_RESET,"CSSMERR_TP_DEVICE_RESET"}, + { CSSMERR_CSSM_DEVICE_FAILED,"CSSMERR_CSSM_DEVICE_FAILED"}, + { CSSMERR_AC_DEVICE_FAILED,"CSSMERR_AC_DEVICE_FAILED"}, + { CSSMERR_CSP_DEVICE_FAILED,"CSSMERR_CSP_DEVICE_FAILED"}, + { CSSMERR_CL_DEVICE_FAILED,"CSSMERR_CL_DEVICE_FAILED"}, + { CSSMERR_DL_DEVICE_FAILED,"CSSMERR_DL_DEVICE_FAILED"}, + { CSSMERR_TP_DEVICE_FAILED,"CSSMERR_TP_DEVICE_FAILED"}, + { CSSMERR_CSP_APPLE_ADD_APPLICATION_ACL_SUBJECT,"CSSMERR_CSP_APPLE_ADD_APPLICATION_ACL_SUBJECT"}, + { CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE,"CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE"}, + { CSSMERR_CSP_APPLE_SIGNATURE_MISMATCH,"CSSMERR_CSP_APPLE_SIGNATURE_MISMATCH"}, + { CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE,"CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE"}, + { CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE,"CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE"}, + { CSSMERR_CSPDL_APPLE_DL_CONVERSION_ERROR,"CSSMERR_CSPDL_APPLE_DL_CONVERSION_ERROR"}, + { CSSMERR_CSP_APPLE_SSLv2_ROLLBACK,"CSSMERR_CSP_APPLE_SSLv2_ROLLBACK"}, + { CSSMERR_APPLEDL_INVALID_OPEN_PARAMETERS,"CSSMERR_APPLEDL_INVALID_OPEN_PARAMETERS"}, + { CSSMERR_APPLEDL_DISK_FULL,"CSSMERR_APPLEDL_DISK_FULL"}, + { CSSMERR_APPLEDL_QUOTA_EXCEEDED,"CSSMERR_APPLEDL_QUOTA_EXCEEDED"}, + { CSSMERR_APPLEDL_FILE_TOO_BIG,"CSSMERR_APPLEDL_FILE_TOO_BIG"}, + { CSSMERR_APPLEDL_INVALID_DATABASE_BLOB,"CSSMERR_APPLEDL_INVALID_DATABASE_BLOB"}, + { CSSMERR_APPLEDL_INVALID_KEY_BLOB,"CSSMERR_APPLEDL_INVALID_KEY_BLOB"}, + { CSSMERR_APPLEDL_INCOMPATIBLE_DATABASE_BLOB,"CSSMERR_APPLEDL_INCOMPATIBLE_DATABASE_BLOB"}, + { CSSMERR_APPLEDL_INCOMPATIBLE_KEY_BLOB,"CSSMERR_APPLEDL_INCOMPATIBLE_KEY_BLOB"}, + { CSSMERR_APPLETP_HOSTNAME_MISMATCH,"CSSMERR_APPLETP_HOSTNAME_MISMATCH"}, + { CSSMERR_APPLETP_UNKNOWN_CRITICAL_EXTEN,"CSSMERR_APPLETP_UNKNOWN_CRITICAL_EXTEN"}, + { CSSMERR_APPLETP_NO_BASIC_CONSTRAINTS,"CSSMERR_APPLETP_NO_BASIC_CONSTRAINTS"}, + { CSSMERR_APPLETP_INVALID_CA,"CSSMERR_APPLETP_INVALID_CA"}, + { CSSMERR_APPLETP_INVALID_AUTHORITY_ID,"CSSMERR_APPLETP_INVALID_AUTHORITY_ID"}, + { CSSMERR_APPLETP_INVALID_SUBJECT_ID,"CSSMERR_APPLETP_INVALID_SUBJECT_ID"}, + { CSSMERR_APPLETP_INVALID_KEY_USAGE,"CSSMERR_APPLETP_INVALID_KEY_USAGE"}, + { CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE,"CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE"}, + { CSSMERR_APPLETP_INVALID_ID_LINKAGE,"CSSMERR_APPLETP_INVALID_ID_LINKAGE"}, + { CSSMERR_APPLETP_PATH_LEN_CONSTRAINT,"CSSMERR_APPLETP_PATH_LEN_CONSTRAINT"}, + { CSSMERR_APPLETP_INVALID_ROOT,"CSSMERR_APPLETP_INVALID_ROOT"}, + { CSSMERR_APPLETP_CRL_EXPIRED,"CSSMERR_APPLETP_CRL_EXPIRED"}, + { CSSMERR_APPLETP_CRL_NOT_VALID_YET,"CSSMERR_APPLETP_CRL_NOT_VALID_YET"}, + { CSSMERR_APPLETP_CRL_NOT_FOUND,"CSSMERR_APPLETP_CRL_NOT_FOUND"}, + { CSSMERR_APPLETP_CRL_SERVER_DOWN,"CSSMERR_APPLETP_CRL_SERVER_DOWN"}, + { CSSMERR_APPLETP_CRL_BAD_URI,"CSSMERR_APPLETP_CRL_BAD_URI"}, + { CSSMERR_APPLETP_UNKNOWN_CERT_EXTEN,"CSSMERR_APPLETP_UNKNOWN_CERT_EXTEN"}, + { CSSMERR_APPLETP_UNKNOWN_CRL_EXTEN,"CSSMERR_APPLETP_UNKNOWN_CRL_EXTEN"}, + { CSSMERR_APPLETP_CRL_NOT_TRUSTED,"CSSMERR_APPLETP_CRL_NOT_TRUSTED"}, + { CSSMERR_APPLETP_CRL_INVALID_ANCHOR_CERT,"CSSMERR_APPLETP_CRL_INVALID_ANCHOR_CERT"}, + { CSSMERR_APPLETP_CRL_POLICY_FAIL,"CSSMERR_APPLETP_CRL_POLICY_FAIL"}, + { CSSMERR_APPLETP_IDP_FAIL,"CSSMERR_APPLETP_IDP_FAIL"}, + { CSSMERR_APPLETP_CERT_NOT_FOUND_FROM_ISSUER,"CSSMERR_APPLETP_CERT_NOT_FOUND_FROM_ISSUER"}, + { CSSMERR_APPLETP_BAD_CERT_FROM_ISSUER,"CSSMERR_APPLETP_BAD_CERT_FROM_ISSUER"}, + { CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND,"CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND"}, + { CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE,"CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE"}, + { CSSMERR_APPLETP_SMIME_BAD_KEY_USE,"CSSMERR_APPLETP_SMIME_BAD_KEY_USE"}, + { CSSMERR_APPLETP_SMIME_KEYUSAGE_NOT_CRITICAL,"CSSMERR_APPLETP_SMIME_KEYUSAGE_NOT_CRITICAL"}, + { CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS,"CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS"}, + { CSSMERR_APPLETP_SMIME_SUBJ_ALT_NAME_NOT_CRIT,"CSSMERR_APPLETP_SMIME_SUBJ_ALT_NAME_NOT_CRIT"}, + { CSSMERR_APPLETP_SSL_BAD_EXT_KEY_USE,"CSSMERR_APPLETP_SSL_BAD_EXT_KEY_USE"}, + { CSSMERR_APPLETP_OCSP_BAD_RESPONSE,"CSSMERR_APPLETP_OCSP_BAD_RESPONSE"}, + { CSSMERR_APPLETP_OCSP_BAD_REQUEST,"CSSMERR_APPLETP_OCSP_BAD_REQUEST"}, + { CSSMERR_APPLETP_OCSP_UNAVAILABLE,"CSSMERR_APPLETP_OCSP_UNAVAILABLE"}, + { CSSMERR_APPLETP_OCSP_STATUS_UNRECOGNIZED,"CSSMERR_APPLETP_OCSP_STATUS_UNRECOGNIZED"}, + { CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK,"CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK"}, + { CSSMERR_APPLETP_NETWORK_FAILURE,"CSSMERR_APPLETP_NETWORK_FAILURE"}, + { CSSMERR_APPLETP_OCSP_NOT_TRUSTED,"CSSMERR_APPLETP_OCSP_NOT_TRUSTED"}, + { CSSMERR_APPLETP_OCSP_INVALID_ANCHOR_CERT,"CSSMERR_APPLETP_OCSP_INVALID_ANCHOR_CERT"}, + { CSSMERR_APPLETP_OCSP_SIG_ERROR,"CSSMERR_APPLETP_OCSP_SIG_ERROR"}, + { CSSMERR_APPLETP_OCSP_NO_SIGNER,"CSSMERR_APPLETP_OCSP_NO_SIGNER"}, + { CSSMERR_APPLETP_OCSP_RESP_MALFORMED_REQ,"CSSMERR_APPLETP_OCSP_RESP_MALFORMED_REQ"}, + { CSSMERR_APPLETP_OCSP_RESP_INTERNAL_ERR,"CSSMERR_APPLETP_OCSP_RESP_INTERNAL_ERR"}, + { CSSMERR_APPLETP_OCSP_RESP_TRY_LATER,"CSSMERR_APPLETP_OCSP_RESP_TRY_LATER"}, + { CSSMERR_APPLETP_OCSP_RESP_SIG_REQUIRED,"CSSMERR_APPLETP_OCSP_RESP_SIG_REQUIRED"}, + { CSSMERR_APPLETP_OCSP_RESP_UNAUTHORIZED,"CSSMERR_APPLETP_OCSP_RESP_UNAUTHORIZED"}, + { CSSMERR_APPLETP_OCSP_NONCE_MISMATCH,"CSSMERR_APPLETP_OCSP_NONCE_MISMATCH"}, + { CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH,"CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH"}, + { CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS,"CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS"}, + { CSSMERR_APPLETP_CS_BAD_PATH_LENGTH,"CSSMERR_APPLETP_CS_BAD_PATH_LENGTH"}, + { CSSMERR_APPLETP_CS_NO_EXTENDED_KEY_USAGE,"CSSMERR_APPLETP_CS_NO_EXTENDED_KEY_USAGE"}, + { CSSMERR_APPLETP_CODE_SIGN_DEVELOPMENT,"CSSMERR_APPLETP_CODE_SIGN_DEVELOPMENT"}, + { CSSMERR_APPLETP_RS_BAD_CERT_CHAIN_LENGTH,"CSSMERR_APPLETP_RS_BAD_CERT_CHAIN_LENGTH"}, + { CSSMERR_APPLETP_RS_BAD_EXTENDED_KEY_USAGE,"CSSMERR_APPLETP_RS_BAD_EXTENDED_KEY_USAGE"}, + { CSSMERR_APPLETP_TRUST_SETTING_DENY,"CSSMERR_APPLETP_TRUST_SETTING_DENY"}, + { CSSMERR_APPLETP_INVALID_EMPTY_SUBJECT,"CSSMERR_APPLETP_INVALID_EMPTY_SUBJECT"}, + { CSSMERR_APPLETP_UNKNOWN_QUAL_CERT_STATEMENT,"CSSMERR_APPLETP_UNKNOWN_QUAL_CERT_STATEMENT"}, + { CSSMERR_APPLE_DOTMAC_REQ_QUEUED,"CSSMERR_APPLE_DOTMAC_REQ_QUEUED"}, + { CSSMERR_APPLE_DOTMAC_REQ_REDIRECT,"CSSMERR_APPLE_DOTMAC_REQ_REDIRECT"}, + { CSSMERR_APPLE_DOTMAC_REQ_SERVER_ERR,"CSSMERR_APPLE_DOTMAC_REQ_SERVER_ERR"}, + { CSSMERR_APPLE_DOTMAC_REQ_SERVER_PARAM,"CSSMERR_APPLE_DOTMAC_REQ_SERVER_PARAM"}, + { CSSMERR_APPLE_DOTMAC_REQ_SERVER_AUTH,"CSSMERR_APPLE_DOTMAC_REQ_SERVER_AUTH"}, + { CSSMERR_APPLE_DOTMAC_REQ_SERVER_UNIMPL,"CSSMERR_APPLE_DOTMAC_REQ_SERVER_UNIMPL"}, + { CSSMERR_APPLE_DOTMAC_REQ_SERVER_NOT_AVAIL,"CSSMERR_APPLE_DOTMAC_REQ_SERVER_NOT_AVAIL"}, + { CSSMERR_APPLE_DOTMAC_REQ_SERVER_ALREADY_EXIST,"CSSMERR_APPLE_DOTMAC_REQ_SERVER_ALREADY_EXIST"}, + { CSSMERR_APPLE_DOTMAC_REQ_SERVER_SERVICE_ERROR,"CSSMERR_APPLE_DOTMAC_REQ_SERVER_SERVICE_ERROR"}, + { CSSMERR_APPLE_DOTMAC_REQ_IS_PENDING,"CSSMERR_APPLE_DOTMAC_REQ_IS_PENDING"}, + { CSSMERR_APPLE_DOTMAC_NO_REQ_PENDING,"CSSMERR_APPLE_DOTMAC_NO_REQ_PENDING"}, + {0, NULL} +}; diff --git a/SecurityTests/cspxutils/utilLib/fileIo.c b/SecurityTests/cspxutils/utilLib/fileIo.c new file mode 100644 index 00000000..3ad1fae5 --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/fileIo.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include +#include +#include "fileIo.h" + +int cspWriteFile( + const char *fileName, + const unsigned char *bytes, + unsigned numBytes) +{ + int rtn; + int fd; + + fd = open(fileName, O_RDWR | O_CREAT | O_TRUNC, 0600); + if(fd <= 0) { + return errno; + } + rtn = lseek(fd, 0, SEEK_SET); + if(rtn < 0) { + return errno; + } + rtn = write(fd, bytes, (size_t)numBytes); + if(rtn != (int)numBytes) { + if(rtn >= 0) { + printf("writeFile: short write\n"); + } + rtn = EIO; + } + else { + rtn = 0; + } + close(fd); + return rtn; +} + +/* + * Read entire file. + */ +int cspReadFile( + const char *fileName, + unsigned char **bytes, // mallocd and returned + unsigned *numBytes) // returned +{ + int ourRtn = 0; + int fd; + char *buf; + char *thisBuf; + struct stat sb; + unsigned size; + size_t toMove; + ssize_t thisMoved; + int irtn; + off_t lrtn = 0; + + *numBytes = 0; + *bytes = NULL; + fd = open(fileName, O_RDONLY, 0); + if(fd <= 0) { + perror("open"); + return errno; + } + irtn = fstat(fd, &sb); + if(irtn) { + ourRtn = errno; + if(ourRtn == 0) { + fprintf(stderr, "***Bogus zero error on fstat\n"); + ourRtn = -1; + } + else { + perror("fstat"); + } + goto errOut; + } + size = sb.st_size; + buf = thisBuf = (char *)malloc(size); + if(buf == NULL) { + ourRtn = ENOMEM; + goto errOut; + } + lrtn = lseek(fd, 0, SEEK_SET); + if(lrtn < 0) { + ourRtn = errno; + if(ourRtn == 0) { + fprintf(stderr, "***Bogus zero error on lseek\n"); + ourRtn = -1; + } + else { + perror("lseek"); + } + goto errOut; + } + toMove = size; + + /* + * On ppc this read ALWAYS returns the entire file. On i386, not so. + */ + do { + thisMoved = read(fd, thisBuf, toMove); + if(thisMoved == 0) { + /* reading empty file: done */ + break; + } + else if(thisMoved < 0) { + ourRtn = errno; + perror("read"); + break; + } + size_t uThisMoved = (size_t)thisMoved; + if(uThisMoved != toMove) { + fprintf(stderr, "===Short read: asked for %ld, got %lu\n", + toMove, uThisMoved); + } + toMove -= thisMoved; + thisBuf += thisMoved; + } while(toMove); + + if(ourRtn == 0) { + *bytes = (unsigned char *)buf; + *numBytes = size; + } +errOut: + close(fd); + return ourRtn; +} diff --git a/SecurityTests/cspxutils/utilLib/fileIo.h b/SecurityTests/cspxutils/utilLib/fileIo.h new file mode 100644 index 00000000..b079359e --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/fileIo.h @@ -0,0 +1,20 @@ +/* + * Read entire file. + */ +#ifdef __cplusplus +extern "C" { +#endif + +int cspReadFile( + const char *fileName, + unsigned char **bytes, // mallocd and returned + unsigned *numBytes); // returned + +int cspWriteFile( + const char *fileName, + const unsigned char *bytes, + unsigned numBytes); + +#ifdef __cplusplus +} +#endif diff --git a/SecurityTests/cspxutils/utilLib/nssAppUtils.cpp b/SecurityTests/cspxutils/utilLib/nssAppUtils.cpp new file mode 100644 index 00000000..d1c7e216 --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/nssAppUtils.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please + * obtain a copy of the License at http://www.apple.com/publicsource and + * read it before using this file. + * + * This 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. + */ +/* + * nssAppUtils.cpp + */ + +#include "nssAppUtils.h" +#include "common.h" +#include "cspwrap.h" +#include +#include +#include +#include +#include + +/* + * Create pubKeyPartial as copy of pubKey without the DSA params. + * Returned partial key is RAW. Incoming key can be raw or ref. + */ +CSSM_RETURN extractDsaPartial( + CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *pubKey, + CSSM_KEY_PTR pubKeyPartial) +{ + const CSSM_KEY *thePubKey = pubKey; + CSSM_KEY rawPubKey; + CSSM_RETURN crtn; + + if(pubKey->KeyHeader.BlobType == CSSM_KEYBLOB_REFERENCE) { + /* first get this in raw form */ + crtn = cspRefKeyToRaw(cspHand, pubKey, &rawPubKey); + if(crtn) { + return crtn; + } + thePubKey = &rawPubKey; + } + + /* decode raw public key */ + NSS_DSAPublicKeyX509 nssPub; + SecAsn1CoderRef coder; + + OSStatus ortn = SecAsn1CoderCreate(&coder); + if(ortn) { + cssmPerror("SecAsn1CoderCreate", ortn); + return ortn; + } + memset(&nssPub, 0, sizeof(nssPub)); + if(SecAsn1DecodeData(coder, &thePubKey->KeyData, kSecAsn1DSAPublicKeyX509Template, + &nssPub)) { + printf("***Error decoding DSA public key. Aborting.\n"); + return 1; + } + + /* zero out the params and reencode */ + nssPub.dsaAlg.params = NULL; + CSSM_DATA newKey = {0, NULL}; + if(SecAsn1EncodeItem(coder, &nssPub, kSecAsn1DSAPublicKeyX509Template, + &newKey)) { + printf("***Error reencoding DSA pub key\n"); + return 1; + } + + /* copy - newKey is in coder space */ + *pubKeyPartial = *thePubKey; + appCopyCssmData(&newKey, &pubKeyPartial->KeyData); + + if(pubKey->KeyHeader.BlobType == CSSM_KEYBLOB_REFERENCE) { + /* free the KeyData mallocd by cspRefKeyToRaw */ + CSSM_FREE(thePubKey->KeyData.Data); + pubKeyPartial->KeyHeader.BlobType = CSSM_KEYBLOB_RAW; + } + pubKeyPartial->KeyHeader.KeyAttr |= CSSM_KEYATTR_PARTIAL; + SecAsn1CoderRelease(coder); + return CSSM_OK; +} diff --git a/SecurityTests/cspxutils/utilLib/nssAppUtils.h b/SecurityTests/cspxutils/utilLib/nssAppUtils.h new file mode 100644 index 00000000..b05676fb --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/nssAppUtils.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please + * obtain a copy of the License at http://www.apple.com/publicsource and + * read it before using this file. + * + * This 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. + */ +/* + * nssAppUtils.h + */ + +#ifndef _NSS_APP_UTILS_H_ +#define _NSS_APP_UTILS_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +CSSM_RETURN extractDsaPartial( + CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *pubKey, + CSSM_KEY_PTR pubKeyPartial); + +#ifdef __cplusplus +} +#endif + +#endif /* _NSS_APP_UTILS_H_ */ + diff --git a/SecurityTests/cspxutils/utilLib/rijndael-alg-ref.c b/SecurityTests/cspxutils/utilLib/rijndael-alg-ref.c new file mode 100644 index 00000000..aba67c46 --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/rijndael-alg-ref.c @@ -0,0 +1,373 @@ +/* rijndael-alg-ref.c v2.0 August '99 + * Reference ANSI C code + * authors: Paulo Barreto + * Vincent Rijmen + */ + +#include +#include + +#include "rijndael-alg-ref.h" + +#define SC ((BC - 4) >> 1) + +#include "boxes-ref.h" + +static const word8 shifts[3][4][2] = { + { { 0, 0 }, + { 1, 3 }, + { 2, 2 }, + { 3, 1 } + }, + { { 0, 0 }, + { 1, 5 }, + { 2, 4 }, + { 3, 3 } + }, + { { 0, 0 }, + { 1, 7 }, + { 3, 5 }, + { 4, 4 } + } +}; + + +static word8 mul(word8 a, word8 b) { + /* multiply two elements of GF(2^m) + * needed for MixColumn and InvMixColumn + */ + if (a && b) return Alogtable[(Logtable[a] + Logtable[b])%255]; + else return 0; +} + +static void KeyAddition(word8 a[4][MAXBC], word8 rk[4][MAXBC], word8 BC) { + /* Exor corresponding text input and round key input bytes + */ + int i, j; + + for(i = 0; i < 4; i++) + for(j = 0; j < BC; j++) a[i][j] ^= rk[i][j]; +} + +static void ShiftRow(word8 a[4][MAXBC], word8 d, word8 BC) { + /* Row 0 remains unchanged + * The other three rows are shifted a variable amount + */ + word8 tmp[MAXBC]; + int i, j; + + for(i = 1; i < 4; i++) { + for(j = 0; j < BC; j++) tmp[j] = a[i][(j + shifts[SC][i][d]) % BC]; + for(j = 0; j < BC; j++) a[i][j] = tmp[j]; + } +} + +static void Substitution(word8 a[4][MAXBC], const word8 box[256], word8 BC) { + /* Replace every byte of the input by the byte at that place + * in the nonlinear S-box + */ + int i, j; + + for(i = 0; i < 4; i++) + for(j = 0; j < BC; j++) a[i][j] = box[a[i][j]] ; +} + +static void MixColumn(word8 a[4][MAXBC], word8 BC) { + /* Mix the four bytes of every column in a linear way + */ + word8 b[4][MAXBC]; + int i, j; + + for(j = 0; j < BC; j++) + for(i = 0; i < 4; i++) + b[i][j] = mul(2,a[i][j]) + ^ mul(3,a[(i + 1) % 4][j]) + ^ a[(i + 2) % 4][j] + ^ a[(i + 3) % 4][j]; + for(i = 0; i < 4; i++) + for(j = 0; j < BC; j++) a[i][j] = b[i][j]; +} + +static void InvMixColumn(word8 a[4][MAXBC], word8 BC) { + /* Mix the four bytes of every column in a linear way + * This is the opposite operation of Mixcolumn + */ + word8 b[4][MAXBC]; + int i, j; + + for(j = 0; j < BC; j++) + for(i = 0; i < 4; i++) + b[i][j] = mul(0xe,a[i][j]) + ^ mul(0xb,a[(i + 1) % 4][j]) + ^ mul(0xd,a[(i + 2) % 4][j]) + ^ mul(0x9,a[(i + 3) % 4][j]); + for(i = 0; i < 4; i++) + for(j = 0; j < BC; j++) a[i][j] = b[i][j]; +} + +int _rijndaelKeySched (word8 k[4][MAXKC], int keyBits, int blockBits, word8 W[MAXROUNDS+1][4][MAXBC]) { + /* Calculate the necessary round keys + * The number of calculations depends on keyBits and blockBits + */ + int KC, BC, ROUNDS; + int i, j, t, rconpointer = 0; + word8 tk[4][MAXKC]; + + switch (keyBits) { + case 128: KC = 4; break; + case 192: KC = 6; break; + case 256: KC = 8; break; + default : return (-1); + } + + switch (blockBits) { + case 128: BC = 4; break; + case 192: BC = 6; break; + case 256: BC = 8; break; + default : return (-2); + } + + switch (keyBits >= blockBits ? keyBits : blockBits) { + case 128: ROUNDS = 10; break; + case 192: ROUNDS = 12; break; + case 256: ROUNDS = 14; break; + default : return (-3); /* this cannot happen */ + } + + + for(j = 0; j < KC; j++) + for(i = 0; i < 4; i++) + tk[i][j] = k[i][j]; + t = 0; + /* copy values into round key array */ + for(j = 0; (j < KC) && (t < (ROUNDS+1)*BC); j++, t++) + for(i = 0; i < 4; i++) W[t / BC][i][t % BC] = tk[i][j]; + + while (t < (ROUNDS+1)*BC) { /* while not enough round key material calculated */ + /* calculate new values */ + for(i = 0; i < 4; i++) + tk[i][0] ^= S[tk[(i+1)%4][KC-1]]; + tk[0][0] ^= rcon[rconpointer++]; + + if (KC != 8) + for(j = 1; j < KC; j++) + for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1]; + else { + for(j = 1; j < KC/2; j++) + for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1]; + for(i = 0; i < 4; i++) tk[i][KC/2] ^= S[tk[i][KC/2 - 1]]; + for(j = KC/2 + 1; j < KC; j++) + for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1]; + } + /* copy values into round key array */ + for(j = 0; (j < KC) && (t < (ROUNDS+1)*BC); j++, t++) + for(i = 0; i < 4; i++) W[t / BC][i][t % BC] = tk[i][j]; + } + + return 0; +} + +int _rijndaelEncrypt (word8 a[4][MAXBC], int keyBits, int blockBits, word8 rk[MAXROUNDS+1][4][MAXBC]) +{ + /* Encryption of one block. + */ + int r, BC, ROUNDS; + + switch (blockBits) { + case 128: BC = 4; break; + case 192: BC = 6; break; + case 256: BC = 8; break; + default : return (-2); + } + + switch (keyBits >= blockBits ? keyBits : blockBits) { + case 128: ROUNDS = 10; break; + case 192: ROUNDS = 12; break; + case 256: ROUNDS = 14; break; + default : return (-3); /* this cannot happen */ + } + + /* begin with a key addition + */ + KeyAddition(a,rk[0],BC); + + /* ROUNDS-1 ordinary rounds + */ + for(r = 1; r < ROUNDS; r++) { + Substitution(a,S,BC); + ShiftRow(a,0,BC); + MixColumn(a,BC); + KeyAddition(a,rk[r],BC); + } + + /* Last round is special: there is no MixColumn + */ + Substitution(a,S,BC); + ShiftRow(a,0,BC); + KeyAddition(a,rk[ROUNDS],BC); + + return 0; +} + + +#ifndef __APPLE__ + +int rijndaelEncryptRound (word8 a[4][MAXBC], int keyBits, int blockBits, + word8 rk[MAXROUNDS+1][4][MAXBC], int rounds) +/* Encrypt only a certain number of rounds. + * Only used in the Intermediate Value Known Answer Test. + */ +{ + int r, BC, ROUNDS; + + switch (blockBits) { + case 128: BC = 4; break; + case 192: BC = 6; break; + case 256: BC = 8; break; + default : return (-2); + } + + switch (keyBits >= blockBits ? keyBits : blockBits) { + case 128: ROUNDS = 10; break; + case 192: ROUNDS = 12; break; + case 256: ROUNDS = 14; break; + default : return (-3); /* this cannot happen */ + } + + /* make number of rounds sane */ + if (rounds > ROUNDS) rounds = ROUNDS; + + /* begin with a key addition + */ + KeyAddition(a,rk[0],BC); + + /* at most ROUNDS-1 ordinary rounds + */ + for(r = 1; (r <= rounds) && (r < ROUNDS); r++) { + Substitution(a,S,BC); + ShiftRow(a,0,BC); + MixColumn(a,BC); + KeyAddition(a,rk[r],BC); + } + + /* if necessary, do the last, special, round: + */ + if (rounds == ROUNDS) { + Substitution(a,S,BC); + ShiftRow(a,0,BC); + KeyAddition(a,rk[ROUNDS],BC); + } + + return 0; +} +#endif /* __APPLE__ */ + +int _rijndaelDecrypt (word8 a[4][MAXBC], int keyBits, int blockBits, word8 rk[MAXROUNDS+1][4][MAXBC]) +{ + int r, BC, ROUNDS; + + switch (blockBits) { + case 128: BC = 4; break; + case 192: BC = 6; break; + case 256: BC = 8; break; + default : return (-2); + } + + switch (keyBits >= blockBits ? keyBits : blockBits) { + case 128: ROUNDS = 10; break; + case 192: ROUNDS = 12; break; + case 256: ROUNDS = 14; break; + default : return (-3); /* this cannot happen */ + } + + /* To decrypt: apply the inverse operations of the encrypt routine, + * in opposite order + * + * (KeyAddition is an involution: it 's equal to its inverse) + * (the inverse of Substitution with table S is Substitution with the inverse table of S) + * (the inverse of Shiftrow is Shiftrow over a suitable distance) + */ + + /* First the special round: + * without InvMixColumn + * with extra KeyAddition + */ + KeyAddition(a,rk[ROUNDS],BC); + Substitution(a,Si,BC); + ShiftRow(a,1,BC); + + /* ROUNDS-1 ordinary rounds + */ + for(r = ROUNDS-1; r > 0; r--) { + KeyAddition(a,rk[r],BC); + InvMixColumn(a,BC); + Substitution(a,Si,BC); + ShiftRow(a,1,BC); + } + + /* End with the extra key addition + */ + + KeyAddition(a,rk[0],BC); + + return 0; +} + +#ifndef __APPLE__ + +int rijndaelDecryptRound (word8 a[4][MAXBC], int keyBits, int blockBits, + word8 rk[MAXROUNDS+1][4][MAXBC], int rounds) +/* Decrypt only a certain number of rounds. + * Only used in the Intermediate Value Known Answer Test. + * Operations rearranged such that the intermediate values + * of decryption correspond with the intermediate values + * of encryption. + */ +{ + int r, BC, ROUNDS; + + switch (blockBits) { + case 128: BC = 4; break; + case 192: BC = 6; break; + case 256: BC = 8; break; + default : return (-2); + } + + switch (keyBits >= blockBits ? keyBits : blockBits) { + case 128: ROUNDS = 10; break; + case 192: ROUNDS = 12; break; + case 256: ROUNDS = 14; break; + default : return (-3); /* this cannot happen */ + } + + + /* make number of rounds sane */ + if (rounds > ROUNDS) rounds = ROUNDS; + + /* First the special round: + * without InvMixColumn + * with extra KeyAddition + */ + KeyAddition(a,rk[ROUNDS],BC); + Substitution(a,Si,BC); + ShiftRow(a,1,BC); + + /* ROUNDS-1 ordinary rounds + */ + for(r = ROUNDS-1; r > rounds; r--) { + KeyAddition(a,rk[r],BC); + InvMixColumn(a,BC); + Substitution(a,Si,BC); + ShiftRow(a,1,BC); + } + + if (rounds == 0) { + /* End with the extra key addition + */ + KeyAddition(a,rk[0],BC); + } + + return 0; +} + +#endif /* __APPLE__ */ diff --git a/SecurityTests/cspxutils/utilLib/rijndael-alg-ref.h b/SecurityTests/cspxutils/utilLib/rijndael-alg-ref.h new file mode 100644 index 00000000..083378e0 --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/rijndael-alg-ref.h @@ -0,0 +1,53 @@ +/* rijndael-alg-ref.h v2.0 August '99 + * Reference ANSI C code + * authors: Paulo Barreto + * Vincent Rijmen + */ +#ifndef __RIJNDAEL_ALG_H +#define __RIJNDAEL_ALG_H + +#ifdef __APPLE__ +#define MIN_AES_KEY_BITS 128 +#define MID_AES_KEY_BITS 192 +#define MAX_AES_KEY_BITS 256 +#define MAX_AES_KEY_BYTES (MAX_AES_KEY_BITS / 8) + +#define MIN_AES_BLOCK_BITS 128 +#define MID_AES_BLOCK_BITS 192 +#define MAX_AES_BLOCK_BITS 256 +#define MIN_AES_BLOCK_BYTES (MIN_AES_BLOCK_BITS / 8) + +#endif +#define MAXBC (MAX_AES_BLOCK_BITS/32) +#define MAXKC (MAX_AES_KEY_BITS/32) +#define MAXROUNDS 14 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned char word8; +typedef unsigned short word16; +typedef unsigned long word32; + + +int _rijndaelKeySched (word8 k[4][MAXKC], int keyBits, int blockBits, + word8 rk[MAXROUNDS+1][4][MAXBC]); +int _rijndaelEncrypt (word8 a[4][MAXBC], int keyBits, int blockBits, + word8 rk[MAXROUNDS+1][4][MAXBC]); +#ifndef __APPLE__ +int rijndaelEncryptRound (word8 a[4][MAXBC], int keyBits, int blockBits, + word8 rk[MAXROUNDS+1][4][MAXBC], int rounds); +#endif +int _rijndaelDecrypt (word8 a[4][MAXBC], int keyBits, int blockBits, + word8 rk[MAXROUNDS+1][4][MAXBC]); +#ifndef __APPLE__ +int rijndaelDecryptRound (word8 a[4][MAXBC], int keyBits, int blockBits, + word8 rk[MAXROUNDS+1][4][MAXBC], int rounds); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __RIJNDAEL_ALG_H */ diff --git a/SecurityTests/cspxutils/utilLib/rijndaelApi.c b/SecurityTests/cspxutils/utilLib/rijndaelApi.c new file mode 100644 index 00000000..f7927d35 --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/rijndaelApi.c @@ -0,0 +1,357 @@ +/* + * rijndaelApi.c - AES API layer + * + * Based on rijndael-api-ref.h v2.0 written by Paulo Barreto + * and Vincent Rijmen + */ +#include +#include + +#include "rijndael-alg-ref.h" +#include "rijndaelApi.h" + +#define CBC_DEBUG 0 +#if CBC_DEBUG +static void dumpChainBuf(cipherInstance *cipher, char *op) +{ + int t,j; + int columns = cipher->blockLen / 32; + + printf("chainBuf %s: ", op); + for (j = 0; j < columns; j++) { + for(t = 0; t < 4; t++) { + printf("%02x ", cipher->chainBlock[t][j]); + } + } + printf("\n"); +} +#else +#define dumpChainBuf(c, o) +#endif + +int _makeKey( keyInstance *key, + BYTE direction, + int keyLen, // in BITS + int blockLen, // in BITS + BYTE *keyMaterial) +{ + word8 k[4][MAXKC]; + unsigned keyBytes; + unsigned i; + + if (key == NULL) { + return BAD_KEY_INSTANCE; + } + if(keyMaterial == NULL) { + return BAD_KEY_MAT; + } + if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) { + key->direction = direction; + } else { + return BAD_KEY_DIR; + } + + if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) { + key->keyLen = keyLen; + } else { + return BAD_KEY_MAT; + } + key->blockLen = blockLen; + + /* initialize key schedule: */ + keyBytes = keyLen / 8; + for(i = 0; i < keyBytes; i++) { + k[i % 4][i / 4] = keyMaterial[i]; + } + _rijndaelKeySched (k, key->keyLen, key->blockLen, key->keySched); + memset(k, 0, 4 * MAXKC); + return TRUE; +} + +int _cipherInit( cipherInstance *cipher, + BYTE mode, + int blockLen, // in BITS + BYTE *IV) +{ + int t, j; + int columns = blockLen / 32; + + /* MODE_CFB1 not supported */ + if ((mode == MODE_ECB) || (mode == MODE_CBC)) { + cipher->mode = mode; + } else { + return BAD_CIPHER_MODE; + } + cipher->blockLen = blockLen; + + if (IV != NULL) { + /* Save IV in rectangular block format */ + for (j = 0; j < columns; j++) { + for(t = 0; t < 4; t++) { + /* parse initial value into rectangular array */ + cipher->chainBlock[t][j] = IV[t+4*j]; + } + } + } + dumpChainBuf(cipher, "init "); + return TRUE; +} + + +int _blockEncrypt(cipherInstance *cipher, + keyInstance *key, BYTE *input, int inputLen, BYTE *outBuffer) +{ + int i, j, t, numBlocks; + unsigned blockSizeBytes; + int columns; + + /* check parameter consistency: */ + if (key == NULL || + key->direction != DIR_ENCRYPT || + (key->keyLen != 128 && key->keyLen != 192 && key->keyLen != 256)) { + return BAD_KEY_MAT; + } + if (cipher == NULL || + (cipher->mode != MODE_ECB && cipher->mode != MODE_CBC) || + (cipher->blockLen != 128 && cipher->blockLen != 192 && cipher->blockLen != 256)) { + return BAD_CIPHER_STATE; + } + + numBlocks = inputLen/cipher->blockLen; + blockSizeBytes = cipher->blockLen / 8; + columns = cipher->blockLen / 32; + + switch (cipher->mode) { + case MODE_ECB: + for (i = 0; i < numBlocks; i++) { + for (j = 0; j < columns; j++) { + for(t = 0; t < 4; t++) + /* parse input stream into rectangular array */ + cipher->chainBlock[t][j] = input[4*j+t]; + } + _rijndaelEncrypt (cipher->chainBlock, key->keyLen, cipher->blockLen, key->keySched); + for (j = 0; j < columns; j++) { + /* parse rectangular array into output ciphertext bytes */ + for(t = 0; t < 4; t++) + outBuffer[4*j+t] = (BYTE) cipher->chainBlock[t][j]; + } + input += blockSizeBytes; + outBuffer += blockSizeBytes; + dumpChainBuf(cipher, "encr ECB"); + } + break; + + case MODE_CBC: + for (i = 0; i < numBlocks; i++) { + for (j = 0; j < columns; j++) { + for(t = 0; t < 4; t++) + /* parse input stream into rectangular array and exor with + IV or the previous ciphertext */ + cipher->chainBlock[t][j] ^= input[4*j+t]; + } + _rijndaelEncrypt (cipher->chainBlock, key->keyLen, cipher->blockLen, key->keySched); + for (j = 0; j < columns; j++) { + /* parse rectangular array into output ciphertext bytes */ + for(t = 0; t < 4; t++) + outBuffer[4*j+t] = (BYTE) cipher->chainBlock[t][j]; + } + /* Hey! This code was broken for multi-block ops! */ + input += blockSizeBytes; + outBuffer += blockSizeBytes; + dumpChainBuf(cipher, "encr CBC"); + } + break; + + default: return BAD_CIPHER_STATE; + } + + return numBlocks*cipher->blockLen; +} + +int _blockDecrypt(cipherInstance *cipher, + keyInstance *key, BYTE *input, int inputLen, BYTE *outBuffer) +{ + int i, j, t, numBlocks; + word8 block[4][MAXBC]; // working memory: encrypt/decrypt in place here + unsigned blockSizeBytes; + word8 cblock[4][MAXBC]; // saved ciphertext + int columns; + + if (cipher == NULL || + key == NULL || + key->direction == DIR_ENCRYPT || + cipher->blockLen != key->blockLen) { + return BAD_CIPHER_STATE; + } + + /* check parameter consistency: */ + if (key == NULL || + key->direction != DIR_DECRYPT || + (key->keyLen != 128 && key->keyLen != 192 && key->keyLen != 256)) { + return BAD_KEY_MAT; + } + if (cipher == NULL || + (cipher->mode != MODE_ECB && cipher->mode != MODE_CBC) || + (cipher->blockLen != 128 && cipher->blockLen != 192 && cipher->blockLen != 256)) { + return BAD_CIPHER_STATE; + } + + numBlocks = inputLen/cipher->blockLen; + blockSizeBytes = cipher->blockLen / 8; + columns = cipher->blockLen / 32; + + switch (cipher->mode) { + case MODE_ECB: + for (i = 0; i < numBlocks; i++) { + for (j = 0; j < columns; j++) { + for(t = 0; t < 4; t++) + /* parse input stream into rectangular array */ + block[t][j] = input[4*j+t]; + } + _rijndaelDecrypt (block, key->keyLen, cipher->blockLen, key->keySched); + for (j = 0; j < columns; j++) { + /* parse rectangular array into output ciphertext bytes */ + for(t = 0; t < 4; t++) + outBuffer[4*j+t] = (BYTE) block[t][j]; + } + input += blockSizeBytes; + outBuffer += blockSizeBytes; + dumpChainBuf(cipher, "decr ECB"); + } + break; + + case MODE_CBC: + for (i = 0; i < numBlocks; i++) { + for (j = 0; j < columns; j++) { + for(t = 0; t < 4; t++) + /* parse input stream into rectangular array */ + block[t][j] = input[4*j+t]; + } + + /* save a copoy of incoming ciphertext for later chain; decrypt */ + memmove(cblock, block, 4*MAXBC); + _rijndaelDecrypt (block, key->keyLen, cipher->blockLen, key->keySched); + + /* + * exor with last ciphertext --> plaintext out + * save this ciphertext in lastBlock + * FIXME - we can optimize this by avoiding the copy into + * lastBlock on all but last time thru... + */ + for (j = 0; j < columns; j++) { + for(t = 0; t < 4; t++) { + outBuffer[4*j+t] = (block[t][j] ^ cipher->chainBlock[t][j]); + } + } + memmove(cipher->chainBlock, cblock, 4 * MAXBC); + input += blockSizeBytes; + outBuffer += blockSizeBytes; + dumpChainBuf(cipher, "decr CBC"); + } + break; + + default: return BAD_CIPHER_STATE; + } + memset(block, 0, 4 * MAXBC); + memset(cblock, 0, 4 * MAXBC); + return numBlocks*cipher->blockLen; +} + +/* + * Apple addenda 3/28/2001: simplified single-block encrypt/decrypt. + * Used when chaining and padding is done in elsewhere. + */ +#define AES_CONSISTENCY_CHECK 1 + +int _rijndaelBlockEncrypt( + cipherInstance *cipher, + keyInstance *key, + BYTE *input, + BYTE *outBuffer) +{ + int j, t; + unsigned blockSizeBytes; + int columns; + + #if AES_CONSISTENCY_CHECK + /* check parameter consistency: */ + if (key == NULL || + key->direction != DIR_ENCRYPT || + (key->keyLen != 128 && key->keyLen != 192 && key->keyLen != 256)) { + return BAD_KEY_MAT; + } + if (cipher == NULL || + (cipher->mode != MODE_ECB && cipher->mode != MODE_CBC) || + (cipher->blockLen != 128 && cipher->blockLen != 192 && cipher->blockLen != 256)) { + return BAD_CIPHER_STATE; + } + #endif /* AES_CONSISTENCY_CHECK */ + + blockSizeBytes = cipher->blockLen >> 3; /* was / 8; should just save in cipher */ + columns = cipher->blockLen >> 5; /* was / 32; ditto */ + + for (j = 0; j < columns; j++) { + for(t = 0; t < 4; t++) + /* parse input stream into rectangular array */ + cipher->chainBlock[t][j] = input[4*j+t]; + } + _rijndaelEncrypt (cipher->chainBlock, key->keyLen, cipher->blockLen, + key->keySched); + for (j = 0; j < columns; j++) { + /* parse rectangular array into output ciphertext bytes */ + for(t = 0; t < 4; t++) + outBuffer[4*j+t] = (BYTE) cipher->chainBlock[t][j]; + } + return cipher->blockLen; +} + +int _rijndaelBlockDecrypt( + cipherInstance *cipher, + keyInstance *key, + BYTE *input, + BYTE *outBuffer) +{ + int j, t; + word8 block[4][MAXBC]; // working memory: encrypt/decrypt in place here + unsigned blockSizeBytes; + int columns; + + #if AES_CONSISTENCY_CHECK + if (cipher == NULL || + key == NULL || + key->direction == DIR_ENCRYPT || + cipher->blockLen != key->blockLen) { + return BAD_CIPHER_STATE; + } + + /* check parameter consistency: */ + if (key == NULL || + key->direction != DIR_DECRYPT || + (key->keyLen != 128 && key->keyLen != 192 && key->keyLen != 256)) { + return BAD_KEY_MAT; + } + if (cipher == NULL || + (cipher->mode != MODE_ECB && cipher->mode != MODE_CBC) || + (cipher->blockLen != 128 && cipher->blockLen != 192 && cipher->blockLen != 256)) { + return BAD_CIPHER_STATE; + } + #endif /* AES_CONSISTENCY_CHECK */ + + blockSizeBytes = cipher->blockLen >> 3; /* was / 8; should just save in cipher */ + columns = cipher->blockLen >> 5; /* was / 32; ditto */ + + for (j = 0; j < columns; j++) { + for(t = 0; t < 4; t++) + /* parse input stream into rectangular array */ + block[t][j] = input[4*j+t]; + } + _rijndaelDecrypt (block, key->keyLen, cipher->blockLen, key->keySched); + for (j = 0; j < columns; j++) { + /* parse rectangular array into output ciphertext bytes */ + for(t = 0; t < 4; t++) + outBuffer[4*j+t] = (BYTE) block[t][j]; + } + + return cipher->blockLen; +} + diff --git a/SecurityTests/cspxutils/utilLib/rijndaelApi.h b/SecurityTests/cspxutils/utilLib/rijndaelApi.h new file mode 100644 index 00000000..d9c2734f --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/rijndaelApi.h @@ -0,0 +1,108 @@ +/* + * rijndaelApi.h - AES API layer + * + * Based on rijndael-api-ref.h v2.0 written by Paulo Barreto + * and Vincent Rijmen + */ + +#ifndef _RIJNDAEL_API_REF_H_ +#define _RIJNDAEL_API_REF_H_ + +#include +#include "rijndael-alg-ref.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define DIR_ENCRYPT 0 /* Are we encrpyting? */ +#define DIR_DECRYPT 1 /* Are we decrpyting? */ +#define MODE_ECB 1 /* Are we ciphering in ECB mode? */ +#define MODE_CBC 2 /* Are we ciphering in CBC mode? */ + +#define TRUE 1 +#define FALSE 0 + +/* Error Codes */ +#define BAD_KEY_DIR -1 /* Key direction is invalid, e.g., + unknown value */ +#define BAD_KEY_MAT -2 /* Key material not of correct + length */ +#define BAD_KEY_INSTANCE -3 /* Key passed is not valid */ +#define BAD_CIPHER_MODE -4 /* Params struct passed to + cipherInit invalid */ +#define BAD_CIPHER_STATE -5 /* Cipher in wrong state (e.g., not + initialized) */ +#define BAD_CIPHER_INSTANCE -7 + +#define MAX_AES_KEY_SIZE (MAX_AES_KEY_BITS / 8) +#define MAX_AES_BLOCK_SIZE (MAX_AES_BLOCK_BITS / 8) +#define MAX_AES_IV_SIZE MAX_AES_BLOCK_SIZE + +typedef unsigned char BYTE; + +/* The structure for key information */ +typedef struct { + BYTE direction; /* Key used for encrypting or decrypting? */ + int keyLen; /* Length of the key in bits */ + int blockLen; /* Length of block in bits */ + word8 keySched[MAXROUNDS+1][4][MAXBC]; /* key schedule */ + } keyInstance; + +/* The structure for cipher information */ +typedef struct { + BYTE mode; /* MODE_ECB, MODE_CBC, or MODE_CFB1 */ + word8 chainBlock[4][MAXBC]; + int blockLen; /* block length in bits */ + } cipherInstance; + + +int _makeKey( + keyInstance *key, + BYTE direction, + int keyLen, // in BITS + int blockLen, // in BITS + BYTE *keyMaterial); + +int _cipherInit( + cipherInstance *cipher, + BYTE mode, + int blockLen, // in BITS + BYTE *IV); + +int _blockEncrypt( + cipherInstance *cipher, + keyInstance *key, + BYTE *input, + int inputLen, // in BITS + BYTE *outBuffer); + +int _blockDecrypt( + cipherInstance *cipher, + keyInstance *key, + BYTE *input, + int inputLen, // in BITS + BYTE *outBuffer); + +/* + * Apple addenda 3/28/2001: simplified single-block encrypt/decrypt. + * Used when chaining and padding is done in elsewhere. + */ +int _rijndaelBlockEncrypt( + cipherInstance *cipher, + keyInstance *key, + BYTE *input, + BYTE *outBuffer); +int _rijndaelBlockDecrypt( + cipherInstance *cipher, + keyInstance *key, + BYTE *input, + BYTE *outBuffer); + +#ifdef __cplusplus +} +#endif // cplusplus + +#endif // RIJNDAEL_API_REF + + diff --git a/SecurityTests/cspxutils/utilLib/ssleayUtils.cpp b/SecurityTests/cspxutils/utilLib/ssleayUtils.cpp new file mode 100644 index 00000000..5b430b21 --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/ssleayUtils.cpp @@ -0,0 +1,266 @@ +/* + * ssleayUtils.c - common routines for CDSA/openssl compatibility testing + */ + +#include +#include +#include +#include +#include +#include +#include "ssleayUtils.h" +#include +#include "common.h" + +/* + * Caller sees EAY_KEY, we see a pointer to this. + */ +typedef struct { + CSSM_ALGORITHMS alg; + union { + BF_KEY bf; // blowfish + CAST_KEY cast; + } key; +} EayKeyPriv; + +/* + * Create a symmetric key. + */ +CSSM_RETURN eayGenSymKey( + CSSM_ALGORITHMS alg, + CSSM_BOOL forEncr, + const CSSM_DATA *keyData, + EAY_KEY *key) // RETURNED +{ + EayKeyPriv *ekp = (EayKeyPriv *)malloc(sizeof(EayKeyPriv)); + memset(ekp, 0, sizeof(*ekp)); + switch(alg) { + case CSSM_ALGID_BLOWFISH: + BF_set_key(&ekp->key.bf, keyData->Length, keyData->Data); + break; + case CSSM_ALGID_CAST: // cast128 only + CAST_set_key(&ekp->key.cast, keyData->Length, keyData->Data); + break; + default: + printf("***eayGenSymKey: bad alg\n"); + return -1; + } + ekp->alg = alg; + *key = (EAY_KEY)ekp; + return CSSM_OK; +} + +/* + * Free a key created in eayGenSymKey + */ +CSSM_RETURN eayFreeKey( + EAY_KEY key) +{ + memset(key, 0, sizeof(EayKeyPriv)); + free(key); + return CSSM_OK; +} + +/* + * encrypt/decrypt + */ +CSSM_RETURN eayEncryptDecrypt( + EAY_KEY key, + CSSM_BOOL forEncrypt, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE mode, // CSSM_ALGMODE_CBC ONLY! + const CSSM_DATA *iv, //Êoptional per mode + const CSSM_DATA *inData, + CSSM_DATA_PTR outData) // CSSM_MALLOCd and RETURNED +{ + EayKeyPriv *ekp = (EayKeyPriv *)key; + if((mode != CSSM_ALGMODE_CBC_IV8) && (mode != CSSM_ALGMODE_ECB)) { + printf("***eayEncryptDecrypt only does CBC_IV8, ECB\n"); + return -1; + } + + bool cbc = (mode == CSSM_ALGMODE_ECB) ? false : true; + + outData->Data = (uint8 *)CSSM_MALLOC(inData->Length); + outData->Length = inData->Length; + + /* BF_cbc_encrypt actually writes to IV */ + CSSM_DATA ivc = {0, NULL}; + if(cbc) { + ivc.Data = (uint8 *)malloc(iv->Length); + ivc.Length = iv->Length; + memmove(ivc.Data, iv->Data, ivc.Length); + } + switch(encrAlg) { + case CSSM_ALGID_BLOWFISH: + if(cbc) { + BF_cbc_encrypt(inData->Data, + outData->Data, + inData->Length, + &ekp->key.bf, + ivc.Data, + forEncrypt ? BF_ENCRYPT : BF_DECRYPT); + } + else { + CSSM_DATA intext = *inData; + CSSM_DATA outtext = *outData; + while(intext.Length) { + BF_ecb_encrypt(intext.Data, + outtext.Data, + &ekp->key.bf, + forEncrypt ? BF_ENCRYPT : BF_DECRYPT); + intext.Data += 8; + outtext.Data += 8; + intext.Length -= 8; + } + } + break; + case CSSM_ALGID_CAST: // cast128 only + CAST_cbc_encrypt(inData->Data, + outData->Data, + inData->Length, + &ekp->key.cast, + ivc.Data, + forEncrypt ? CAST_ENCRYPT : CAST_DECRYPT); + break; + default: + printf("***eayEncryptDecrypt: bad alg\n"); + return -1; + } + if(ivc.Data) { + free(ivc.Data); + } + return CSSM_OK; +} + +/*** EVP-based encrypt/decrypt ***/ + +int evpEncryptDecrypt( + CSSM_ALGORITHMS alg, // AES 128 only for now + CSSM_BOOL forEncr, + const CSSM_DATA *keyData, // may be larger than the key size we use + unsigned keyLengthInBits, + CSSM_ENCRYPT_MODE mode, // CSSM_ALGMODE_CBC_IV8, ECB, always padding + const CSSM_DATA *iv, // optional per mode + const CSSM_DATA *inData, + CSSM_DATA_PTR outData) // CSSM_MALLOCd and RETURNED +{ + EVP_CIPHER_CTX ctx; + const EVP_CIPHER *cipher; + unsigned blockSize; + unsigned outLen = inData->Length; + bool noPad = false; + + switch(alg) { + case CSSM_ALGID_AES: + switch(mode) { + case CSSM_ALGMODE_CBCPadIV8: + switch(keyLengthInBits) { + case 128: + cipher = EVP_aes_128_cbc(); + break; + case 192: + cipher = EVP_aes_192_cbc(); + break; + case 256: + cipher = EVP_aes_256_cbc(); + break; + default: + printf("***Bad AES key length (%u)\n", keyLengthInBits); + return -1; + } + break; + case CSSM_ALGMODE_ECB: + switch(keyLengthInBits) { + case 128: + cipher = EVP_aes_128_ecb(); + break; + case 192: + cipher = EVP_aes_192_ecb(); + break; + case 256: + cipher = EVP_aes_256_ecb(); + break; + default: + printf("***Bad AES key length (%u)\n", keyLengthInBits); + return -1; + } + noPad = true; + break; + default: + printf("***evpEncryptDecrypt only does CBC and ECB for now\n"); + return -1; + } + blockSize = 16; + break; + case CSSM_ALGID_DES: + switch(mode) { + case CSSM_ALGMODE_CBCPadIV8: + cipher = EVP_des_cbc(); + break; + case CSSM_ALGMODE_ECB: + cipher = EVP_des_ecb(); + noPad = true; + break; + default: + printf("***evpEncryptDecrypt only does CBC and ECB for now\n"); + return -1; + } + blockSize = 8; + break; + default: + printf("***evpEncryptDecrypt only does DES and AES 128 for now\n"); + return -1; + } + outLen += blockSize; + unsigned char *outp = (uint8 *)CSSM_MALLOC(outLen); + int outl = outLen; + outData->Data = outp; + + if(forEncr) { + int rtn = EVP_EncryptInit(&ctx, cipher, keyData->Data, iv ? iv->Data : NULL); + if(!rtn) { + printf("EVP_EncryptInit error\n"); + return -1; + } + if(noPad) { + EVP_CIPHER_CTX_set_padding(&ctx, 0); + } + if(!EVP_EncryptUpdate(&ctx, outp, &outl, inData->Data, inData->Length)) { + printf("EVP_EncryptUpdate error\n"); + return -1; + } + } + else { + int rtn = EVP_DecryptInit(&ctx, cipher, keyData->Data, iv ? iv->Data : NULL); + if(!rtn) { + printf("EVP_DecryptInit error\n"); + return -1; + } + if(noPad) { + EVP_CIPHER_CTX_set_padding(&ctx, 0); + } + + if(!EVP_DecryptUpdate(&ctx, outp, &outl, inData->Data, inData->Length)) { + printf("EVP_DecryptUpdate error\n"); + return -1; + } + } + outData->Length = outl; + outp += outl; + outl = outLen - outl; + if(forEncr) { + if(!EVP_EncryptFinal(&ctx, outp, &outl)) { + printf("EVP_EncryptFinal error\n"); + return -1; + } + } + else { + if(!EVP_DecryptFinal(&ctx, outp, &outl)) { + printf("EVP_DecryptFinal error\n"); + return -1; + } + } + outData->Length += outl; + return 0; +} diff --git a/SecurityTests/cspxutils/utilLib/ssleayUtils.h b/SecurityTests/cspxutils/utilLib/ssleayUtils.h new file mode 100644 index 00000000..9725a3d1 --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/ssleayUtils.h @@ -0,0 +1,54 @@ +/* + * ssleayUtils.h - common routines for CDSA/openssl compatibility testing + */ + +/* + * Clients of this module do not need to know about or see anything from the + * libcrypt headers. + */ +#ifndef _SSLEAY_UTILS_H_ +#define _SSLEAY_UTILS_H_ +#include + +typedef void *EAY_KEY; + +/* + * Create a symmetric key. + */ +CSSM_RETURN eayGenSymKey( + CSSM_ALGORITHMS alg, + CSSM_BOOL forEncr, + const CSSM_DATA *keyData, + EAY_KEY *key); // RETURNED + +/* + * Free a key created in eayGenSymKey + */ +CSSM_RETURN eayFreeKey( + EAY_KEY key); + +/* + * encrypt/decrypt + */ +CSSM_RETURN eayEncryptDecrypt( + EAY_KEY key, + CSSM_BOOL forEncrypt, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE mode, // CSSM_ALGMODE_CBC ONLY! + const CSSM_DATA *iv, //Êoptional per mode + const CSSM_DATA *inData, + CSSM_DATA_PTR outData); // mallocd and RETURNED + +/*** EVP-based encrypt/decrypt ***/ + +int evpEncryptDecrypt( + CSSM_ALGORITHMS alg, // AES 128 only for now + CSSM_BOOL forEncr, + const CSSM_DATA *keyData, // may be larger than the key size we use + unsigned keyLengthInBits, + CSSM_ENCRYPT_MODE mode, // CSSM_ALGMODE_CBC_IV8, ECB, always padding + const CSSM_DATA *iv, // optional per mode + const CSSM_DATA *inData, + CSSM_DATA_PTR outData); // CSSM_MALLOCd and RETURNED + +#endif /* _EAY_UTILS_H_ */ diff --git a/SecurityTests/cspxutils/utilLib/t_stdlib.c b/SecurityTests/cspxutils/utilLib/t_stdlib.c new file mode 100644 index 00000000..8fac2df9 --- /dev/null +++ b/SecurityTests/cspxutils/utilLib/t_stdlib.c @@ -0,0 +1,59 @@ +#include +#include +#include +//#include + +#define POINTER void * +#define NULL_PTR NULL + +void T_free(POINTER block) +{ + if (block != NULL_PTR) { + free(block); + } +} + +POINTER T_malloc(unsigned int len) +{ + return (POINTER) malloc(len ? len : 1); +} + +/* these are not needed - they are in system.c in security_bsafe */ +#if 0 +int T_memcmp(POINTER firstBlock, POINTER secondBlock, unsigned int len) +{ + if (len == 0) { + return 0; + } + return memcmp(firstBlock, secondBlock, len); +} + +void T_memcpy(POINTER output, POINTER input, unsigned int len) +{ + if (len != 0) { + memcpy(output, input, len); + } +} + +void T_memmove(POINTER output, POINTER input, unsigned int len) +{ + if (len != 0) { + memmove(output, input, len); + } +} + +void T_memset(POINTER output, int value, unsigned int len) +{ + if (len != 0) { + memset(output, value, len); + } +} +#endif + +POINTER T_realloc(POINTER block, unsigned int len) +{ + if (block == NULL_PTR) + return (POINTER) malloc(len ? len : 1); + + return (POINTER)realloc(block, len); +} diff --git a/SecurityTests/cspxutils/wrap/Makefile b/SecurityTests/cspxutils/wrap/Makefile new file mode 100644 index 00000000..92ec8d5d --- /dev/null +++ b/SecurityTests/cspxutils/wrap/Makefile @@ -0,0 +1,55 @@ +# name of executable to build +EXECUTABLE=wrap +# C++ source (with .cpp extension) +CPSOURCE= +# C source (.c extension) +CSOURCE= wrap.c + +# +# Note final load with cc, not ld +# +# project-specific libraries, e.g., -lstdc++ +# +PROJ_LIBS= +# +# Optional lib search paths +# +PROJ_LIBPATH= +# +# choose one for cc +# +VERBOSE= +#VERBOSE=-v + +# +# Other files to remove at 'make clean' time +# +OTHER_TO_CLEAN= + +# +# non-standard frameworks (e.g., -framework foo) +# +PROJ_FRAMEWORKS= + +# +# project-specific includes, with leading -I +# +PROJ_INCLUDES= + +# +# Optional C flags (warnings, optimizations, etc.) +# +PROJ_CFLAGS= + +# +# Optional link flags (using cc, not ld) +# +#PROJ_LDFLAGS= -lMallocDebug +PROJ_LDFLAGS= + +# +# Optional dependencies +# +PROJ_DEPENDS= + +include ../Makefile.cdsa diff --git a/SecurityTests/cspxutils/wrap/wrap.c b/SecurityTests/cspxutils/wrap/wrap.c new file mode 100644 index 00000000..7052a4c6 --- /dev/null +++ b/SecurityTests/cspxutils/wrap/wrap.c @@ -0,0 +1,249 @@ +/* + * encypt/decrypt using wrapped key + */ + +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include +#include + +static void usage(char **argv) +{ + printf("Usage: \n"); + printf(" %s w keyFile passPhrase1 passPhrase2 textToEncrypt textFile\n", argv[0]); + printf(" %s u keyFile passPhrase1 textFile\n", argv[0]); + exit(1); +} + +char *iv = (char *)"someInit"; +char *salt = (char *)"some20bytesOfGrainySalt"; + +char *wrapLabel = (char *)"wrapLabel"; +char *encrLabel = (char *)"encrLabel"; + +#define IV_LEN 8 +#define SALT_LEN 20 +#define ITER_COUNT 1000 +#define WRAPPING_KEY_ALG CSSM_ALGID_3DES_3KEY +#define WRAPPING_ALG CSSM_ALGID_3DES_3KEY_EDE +#define WRAPPING_KEY_SIZE 192 +#define ENCRYPTING_KEY_ALG CSSM_ALGID_3DES_3KEY +#define ENCRYPTING_ALG CSSM_ALGID_3DES_3KEY_EDE +#define ENCRYPTING_KEY_SIZE 192 + +int main(int argc, char **argv) +{ + int doWrap = 0; + CSSM_RETURN crtn; + CSSM_CSP_HANDLE cspHand; + CSSM_KEY_PTR wrappingKey; + CSSM_DATA saltData = {SALT_LEN, (uint8 *)salt}; + CSSM_DATA ivData = {IV_LEN, (uint8 *)iv}; + CSSM_DATA phraseData; + unsigned char *keyFileData; + unsigned keyFileLen; + unsigned char *textFileData; + unsigned textFileLen; + CSSM_DATA ptext; + CSSM_DATA ctext; + CSSM_KEY wrappedKey; + unsigned i; + + if(argc < 2) { + usage(argv); + } + switch(argv[1][0]) { + case 'w': + doWrap = 1; + if(argc != 7) { + usage(argv); + } + break; + case 'u': + doWrap = 0; + if(argc != 5) { + usage(argv); + } + break; + default: + usage(argv); + } + cspHand = cspDlDbStartup(CSSM_TRUE, NULL); + if(cspHand == 0) { + exit(1); + } + + /* passphrase1 ==> wrappingKey */ + phraseData.Data = (uint8 *)argv[3]; + phraseData.Length = strlen(argv[3]); + wrappingKey = cspDeriveKey(cspHand, + CSSM_ALGID_PKCS5_PBKDF2, + WRAPPING_KEY_ALG, + wrapLabel, + strlen(wrapLabel), + CSSM_KEYUSE_ANY, + WRAPPING_KEY_SIZE, + CSSM_TRUE, // ref key + &phraseData, + &saltData, + ITER_COUNT, + &ivData); + if(wrappingKey == NULL) { + printf("Error creating key from \'%s\'\n", argv[3]); + exit(1); + } + + if(doWrap) { + /* passphrase2 ==> encrKey */ + CSSM_KEY_PTR encrKey; + phraseData.Data = (uint8 *)argv[4]; + phraseData.Length = strlen(argv[4]); + encrKey = cspDeriveKey(cspHand, + CSSM_ALGID_PKCS5_PBKDF2, + ENCRYPTING_KEY_ALG, + encrLabel, + strlen(encrLabel), + CSSM_KEYUSE_ANY, + ENCRYPTING_KEY_SIZE, + CSSM_TRUE, // ref key + &phraseData, + &saltData, + ITER_COUNT, + &ivData); + if(encrKey == NULL) { + printf("Error creating key from \'%s\'\n", argv[4]); + exit(1); + } + + /* encrypt textToEncrypt, write it to textFile */ + ptext.Data = (uint8 *)argv[5]; + ptext.Length = strlen(argv[5]); + ctext.Data = NULL; + ctext.Length = 0; + crtn = cspEncrypt(cspHand, + CSSM_ALGID_3DES_3KEY_EDE, + CSSM_ALGMODE_CBCPadIV8, + CSSM_PADDING_PKCS5, + encrKey, + NULL, + 0, + 0, + &ivData, + &ptext, + &ctext, + CSSM_FALSE); + if(crtn) { + printf("Error encrypting.\n"); + exit(1); + } + if(writeFile(argv[6], ctext.Data, ctext.Length)) { + printf("Error writing to %s\n", argv[6]); + exit(1); + } + + /* now wrap encrKey with wrappingKey and write the wrapped blob */ + crtn = cspWrapKey(cspHand, + encrKey, + wrappingKey, + WRAPPING_ALG, + CSSM_ALGMODE_CBCPadIV8, + CSSM_KEYBLOB_WRAPPED_FORMAT_NONE, + CSSM_PADDING_PKCS5, + &ivData, + NULL, + &wrappedKey); + if(crtn) { + exit(1); + } + if(writeFile(argv[2], wrappedKey.KeyData.Data, wrappedKey.KeyData.Length)) { + printf("error writing to %s\n", argv[2]); + exit(1); + } + printf("...wrote %lu bytes of encrypted text to %s\n", + ctext.Length, argv[6]); + printf("...wrote %lu bytes of wrapped key data to %s\n", + wrappedKey.KeyData.Length, argv[2]); + } + else { + /* read in encrypted text and wrapped key blob */ + CSSM_KEY decrKey; + CSSM_DATA outDescData2 = {0, NULL}; + + if(readFile(argv[2], &keyFileData, &keyFileLen)) { + printf("Error reading %s\n", argv[2]); + } + if(readFile(argv[4], &textFileData, &textFileLen)) { + printf("Error reading %s\n", argv[2]); + } + + /* cook up a reasonable "wrapped key" */ + memset(&wrappedKey, 0, sizeof(CSSM_KEY)); + wrappedKey.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; + wrappedKey.KeyHeader.BlobType = CSSM_KEYBLOB_WRAPPED; + wrappedKey.KeyHeader.Format = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM; + wrappedKey.KeyHeader.AlgorithmId = CSSM_ALGID_3DES_3KEY; + wrappedKey.KeyHeader.KeyClass = CSSM_KEYCLASS_SESSION_KEY; + wrappedKey.KeyHeader.LogicalKeySizeInBits = ENCRYPTING_KEY_SIZE; + wrappedKey.KeyHeader.KeyAttr = CSSM_KEYATTR_EXTRACTABLE; + wrappedKey.KeyHeader.KeyUsage = CSSM_KEYUSE_ANY; + wrappedKey.KeyHeader.WrapAlgorithmId = WRAPPING_ALG; + wrappedKey.KeyHeader.WrapMode = CSSM_ALGMODE_CBCPadIV8; + wrappedKey.KeyData.Data = keyFileData; + wrappedKey.KeyData.Length = keyFileLen; + + /* unwrap the key to get decrypting key */ + crtn = cspUnwrapKey(cspHand, + &wrappedKey, + wrappingKey, + WRAPPING_ALG, + CSSM_ALGMODE_CBCPadIV8, + CSSM_PADDING_PKCS5, + &ivData, + &decrKey, + &outDescData2, + encrLabel, + strlen(encrLabel)); + if(crtn) { + printf("Error on unwrap.\n"); + exit(1); + } + + /* decrypt the text file and print its result */ + ctext.Data = textFileData; + ctext.Length = textFileLen; + ptext.Data = NULL; + ptext.Length = 0; + crtn = cspDecrypt(cspHand, + CSSM_ALGID_3DES_3KEY_EDE, + CSSM_ALGMODE_CBCPadIV8, + CSSM_PADDING_PKCS5, + &decrKey, + NULL, + 0, + 0, + &ivData, + &ctext, + &ptext, + CSSM_FALSE); + if(crtn) { + printf("Error on decrypt.\n"); + exit(1); + } + printf("...original text: "); + for(i=0; i +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "cspdlTesting.h" + +/* + * Currently the CSP can use wrapping keys flagged exclusively for wrapping + * (CSSM_KEYUSE_{WRAP,UNWRAP} for the actual wrap sinceÊthe wrp/unwrap op is + * done with an encrypt/decrypt op. The WrapKey op doesn't even see the + * wrapping key - it's in the context we pass it. Thus for now wrap/unwrap + * keys have to be marked with CSSM_KEYUSE_ANY. + */ +#define WRAP_USAGE_ANY 0 + +/* + * When false, the CMS wrap algorithm can't deal with RSA encryption - we + * have to encrypt something twice with the same key. An impossibility with + * BSAFE-based RSA encryption because the output of the first encrypt is + * the size of the key modulus, and you can't encrypt something that big + * with that key. + * This is not a limitation with openssl-based RSA. + */ +#define WRAP_WITH_RSA 1 + +/* + * When false, can't wrap with RC4 because the RC4 context is stateful + * but doesn't get reinit'd for the second CMS encrypt. + */ +#define WRAP_WITH_RC4 1 + +/* + * Temporary hack to use CSSM_KEYBLOB_WRAPPED_FORMAT_{PKCS7,PKCS8}, which + * are no longer supported as of 7/28/00 + */ +#define PKCS7_FORMAT_ENABLE 1 // for wrapping symmetric keys +#define PKCS8_FORMAT_ENABLE 1 // for wrapping private keys + + +#define ENCR_LABEL "encrKey" +#define ENCR_LABEL_LEN (strlen(ENCR_LABEL)) +#define WRAP_LABEL "wrapKey" +#define WRAP_LABEL_LEN (strlen(WRAP_LABEL)) +#define LOOPS_DEF 10 +#define MAX_PTEXT_SIZE 100 +#define LOOP_PAUSE 100 +#define MAX_DESC_DATA_SIZE 16 + +/* + * Enumerate algorithms our way to allow loop interations. + */ +typedef unsigned PrivAlg; +enum { + ALG_DES = 1, + ALG_3DES, + ALG_RC2, + ALG_RC4, + ALG_RSA, + ALG_NULL, + ALG_FEEDEXP, + ALG_ASC, + ALG_AES +}; + +#define ALG_MIN ALG_DES +#define ALG_MAX_WRAP ALG_AES +#define ALG_MAX_ENCR ALG_AES + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" w=wrapAlg (d=DES, 3=3DES, f=FEEDEXP, r=RSA, A=ASC, 4=RC4, " + "a=AES, n=null)\n"); + printf(" e=encrAlg (d=DES, 3=3DES, f=FEEDEXP, r=RSA, A=ASC, 4=RC4, " + "a=AES)\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" r (ref keys only)\n"); + printf(" p(ause every loop)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" v(erbose)\n"); + printf(" k (quick; small keys)\n"); + printf(" h(elp)\n"); + exit(1); +} + +/* wrapped format to string */ +static const char *formatString(CSSM_KEYBLOB_FORMAT format) +{ + static char noform[100]; + + switch(format) { + case CSSM_KEYBLOB_WRAPPED_FORMAT_NONE: + return "NONE (default)"; + case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7: + return "PKCS7"; + case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8: + return "PKCS8"; + case CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM: + return "APPLE_CUSTOM"; + default: + sprintf(noform, "***UNKNOWN (%u)***", (unsigned)format); + return noform; + } +} + +static int vfyWrapHeader( + const CSSM_KEYHEADER *srcHdr, + const CSSM_KEYHEADER *dstHdr, + CSSM_KEYBLOB_TYPE expectBlob, + const char *op, + CSSM_BOOL bareCsp, + int quiet) +{ + if(dstHdr->BlobType != expectBlob) { + printf("***%s.BlobType error: expect %u got %u\n", + op, (unsigned)expectBlob, (unsigned)dstHdr->BlobType); + if(testError(quiet)) { + return 1; + } + } + if(srcHdr->KeyClass != dstHdr->KeyClass) { + printf("***%s.KeyClass error: expect %u got %u\n", + op, (unsigned)srcHdr->KeyClass, (unsigned)dstHdr->KeyClass); + if(testError(quiet)) { + return 1; + } + } + if(srcHdr->AlgorithmId != dstHdr->AlgorithmId) { + printf("***%s.AlgorithmId error: expect %u got %u\n", + op, (unsigned)srcHdr->AlgorithmId, (unsigned)dstHdr->AlgorithmId); + if(testError(quiet)) { + return 1; + } + } + if(srcHdr->KeyUsage != dstHdr->KeyUsage) { + printf("***%s.KeyUsage error: expect 0x%x got 0x%x\n", + op, (unsigned)srcHdr->KeyUsage, (unsigned)dstHdr->KeyUsage); + if(testError(quiet)) { + return 1; + } + } + if(bareCsp) { + /* GUIDs must match */ + if(memcmp(&srcHdr->CspId, &dstHdr->CspId, sizeof(CSSM_GUID))) { + printf("***%s.CspId mismatch\n", op); + if(testError(quiet)) { + return 1; + } + } + } + else { + /* CSPDL - GUIDs do NOT match - ref keys are in the CSPDL's domain; + * wrapped keys are in the bare CSP's domain. */ + if(!memcmp(&srcHdr->CspId, &dstHdr->CspId, sizeof(CSSM_GUID))) { + printf("***Unexpected %s.CspId compare\n", op); + if(testError(quiet)) { + return 1; + } + } + } + return 0; +} + +#define UNWRAPPED_LABEL "unwrapped thing" +#define SHOW_WRAP_FORMAT 0 + +/* not all algs need this */ +CSSM_DATA initVector = {16, (uint8 *)"SomeReallyStrangeInitVect"}; + +static int doTest(CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR encrKey, + CSSM_BOOL wrapEncrKey, // wrap encrKey before using + CSSM_KEY_PTR decrKey, // we wrap this one + CSSM_KEY_PTR wrappingKey, // ...using this key + CSSM_KEY_PTR unwrappingKey, + CSSM_ALGORITHMS wrapAlg, + CSSM_ENCRYPT_MODE wrapMode, + CSSM_KEYBLOB_FORMAT wrapFormat, // NONE, PKCS7, PKCS8, APPLE_CUSTOM + CSSM_KEYBLOB_FORMAT expectFormat, // PKCS7, PKCS8, APPLE_CUSTOM + CSSM_PADDING wrapPad, + uint32 wrapIvSize, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE encrMode, + CSSM_PADDING encrPad, + uint32 encrIvSize, + uint32 effectiveKeySizeInBits, // for encr/decr - 0 means none specified + CSSM_DATA_PTR ptext, + CSSM_DATA_PTR descData, + CSSM_BOOL quiet, + CSSM_BOOL bareCsp) +{ + CSSM_DATA ctext; + CSSM_DATA rptext; + CSSM_KEY wrappedDecrKey; + CSSM_KEY unwrappedDecrKey; + CSSM_KEY wrappedEncrKey; + CSSM_RETURN crtn; + CSSM_KEY_PTR actualEncrKey; + uint32 maxPtextSize = MAX_PTEXT_SIZE; + CSSM_DATA outDescData1 = {0, NULL}; // for encr key + CSSM_DATA outDescData2 = {0, NULL}; // for decr key, must match descData + CSSM_DATA nullInitVect = {0, NULL}; // for custom unwrap + CSSM_DATA_PTR wrapIvp; + CSSM_DATA_PTR encrIvp; + + /* Hack to deal with RSA's max encrypt size */ + #if 0 + /* no more */ + if(encrAlg == CSSM_ALGID_RSA) { + uint32 keySizeBytes = encrKey->KeyHeader.LogicalKeySizeInBits / 8; + maxPtextSize = keySizeBytes - 11; + if(maxPtextSize > MAX_PTEXT_SIZE) { + maxPtextSize = MAX_PTEXT_SIZE; + } + } + else { + maxPtextSize = MAX_PTEXT_SIZE; + } + #endif + simpleGenData(ptext, 1, maxPtextSize); + + /* + * Optionaly wrap/unwrap encrKey. If encrKey is a ref key, do a + * NULL wrap. If encrKey is a raw key, do a NULL unwrap. + */ + if(wrapEncrKey) { + CSSM_KEYBLOB_TYPE expectBlob; + + if(encrKey->KeyHeader.BlobType == CSSM_KEYBLOB_REFERENCE) { + crtn = cspWrapKey(cspHand, + encrKey, + NULL, // wrappingKey + CSSM_ALGID_NONE, + CSSM_ALGMODE_NONE, + wrapFormat, + CSSM_PADDING_NONE, + NULL, // iv + descData, + &wrappedEncrKey); + expectBlob = CSSM_KEYBLOB_RAW; + } + else { + crtn = cspUnwrapKey(cspHand, + encrKey, + NULL, // unwrappingKey + CSSM_ALGID_NONE, + CSSM_ALGMODE_NONE, + CSSM_PADDING_NONE, + NULL, // iv + &wrappedEncrKey, + &outDescData1, + WRAP_LABEL, + WRAP_LABEL_LEN); + expectBlob = CSSM_KEYBLOB_REFERENCE; + } + if(crtn) { + return testError(quiet); + } + if(vfyWrapHeader(&encrKey->KeyHeader, + &wrappedEncrKey.KeyHeader, + expectBlob, + "wrappedEncrKey", + bareCsp, + quiet)) { + return 1; + } + actualEncrKey = &wrappedEncrKey; + } + else { + actualEncrKey = encrKey; + } + /* encrypt using actualEncrKey ==> ctext */ + ctext.Data = NULL; + ctext.Length = 0; + if(encrIvSize) { + initVector.Length = encrIvSize; + encrIvp = &initVector; + } + else { + encrIvp = NULL; + } + crtn = cspEncrypt(cspHand, + encrAlg, + encrMode, + encrPad, + actualEncrKey, + NULL, // no 2nd key + effectiveKeySizeInBits, + 0, // rounds + encrIvp, + ptext, + &ctext, + CSSM_TRUE); // mallocCtext + if(crtn) { + return testError(quiet); + } + /* wrap decrKey using wrappingKey ==> wrappedDecrKey */ + /* Note that APPLE_CUSTOM wrap alg REQUIRES an 8-byte IV */ + if(expectFormat == CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM) { + initVector.Length = 8; + } + else { + initVector.Length = wrapIvSize; + } + crtn = cspWrapKey(cspHand, + decrKey, + wrappingKey, + wrapAlg, + wrapMode, + wrapFormat, + wrapPad, + &initVector, + descData, + &wrappedDecrKey); + if(crtn) { + return testError(quiet); + } + if(wrapAlg != CSSM_ALGID_NONE) { + if(wrappedDecrKey.KeyHeader.Format != expectFormat) { + printf("***Wrap format mismatch expect %s got %s\n", + formatString(wrappedDecrKey.KeyHeader.Format), + formatString(expectFormat)); + if(testError(quiet)) { + return 1; + } + } + } + + if(vfyWrapHeader(&decrKey->KeyHeader, + &wrappedDecrKey.KeyHeader, + (wrapAlg == CSSM_ALGID_NONE) ? CSSM_KEYBLOB_RAW : CSSM_KEYBLOB_WRAPPED, + "wrappedDecrKey", + bareCsp, + quiet)) { + return 1; + } + + if(wrappedDecrKey.KeyHeader.Format == CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM) { + /* special case - no IV needed - test it */ + wrapIvp = &nullInitVect; + } + else { + wrapIvp = &initVector; + initVector.Length = wrapIvSize; + } + + /* unwrap wrappedDecrKey using unwrappingKey ==> unwrappedDecrKey; */ + crtn = cspUnwrapKey(cspHand, + &wrappedDecrKey, + unwrappingKey, + wrapAlg, + wrapMode, + wrapPad, + wrapIvp, + &unwrappedDecrKey, + &outDescData2, + "unwrapped thing", + 15); + if(crtn) { + return testError(quiet); + } + + if(vfyWrapHeader(&wrappedDecrKey.KeyHeader, + &unwrappedDecrKey.KeyHeader, + CSSM_KEYBLOB_REFERENCE, + "unwrappedDecrKey", + bareCsp, + quiet)) { + return 1; + } + + /* compare descData to outDescData2 */ + if(descData) { + if(descData->Length != outDescData2.Length) { + printf("descData length mismatch\n"); + if(testError(quiet)) { + return 1; + } + } + if(memcmp(descData->Data, outDescData2.Data, outDescData2.Length)) { + printf("***descDatadata miscompare\n"); + if(testError(quiet)) { + return 1; + } + } + } + + /* decrypt ctext with unwrappedDecrKey ==> rptext; */ + rptext.Data = NULL; + rptext.Length = 0; + if(encrIvSize) { + initVector.Length = encrIvSize; + } + crtn = cspDecrypt(cspHand, + encrAlg, + encrMode, + encrPad, + &unwrappedDecrKey, + NULL, // no 2nd key + effectiveKeySizeInBits, + 0, // rounds + &initVector, + &ctext, + &rptext, + CSSM_TRUE); + if(crtn) { + return testError(quiet); + } + /* compare ptext vs. rptext; */ + if(ptext->Length != rptext.Length) { + printf("ptext length mismatch\n"); + return testError(quiet); + } + if(memcmp(ptext->Data, rptext.Data, ptext->Length)) { + printf("***data miscompare\n"); + return testError(quiet); + } + /* free resources */ + cspFreeKey(cspHand, &wrappedDecrKey); + cspFreeKey(cspHand, &unwrappedDecrKey); + if(wrapEncrKey) { + cspFreeKey(cspHand, actualEncrKey); + } + CSSM_FREE(ctext.Data); + CSSM_FREE(rptext.Data); + if(outDescData2.Data != NULL) { + CSSM_FREE(outDescData2.Data); + } + if(outDescData1.Data != NULL) { + CSSM_FREE(outDescData1.Data); + } + return 0; +} + +/* + * values associated with a private algorithm (e.g., ALG_DES). + */ +typedef enum { + WT_Symmetric, + WT_Asymmetric, + WT_Null +} wrapType; + +typedef struct { + uint32 keyGenAlg; + wrapType wtype; + CSSM_ALGORITHMS encrAlg; + CSSM_ENCRYPT_MODE encrMode; + CSSM_PADDING encrPad; + uint32 ivSize; // in bytes; 0 means no IV + const char *algName; +} AlgInfo; + +/* + * Convert our private alg to CDSA keygen alg, encr alg, encr mode, pad + */ +static void getAlgInfo(PrivAlg privAlg, // e.g., ALG_DES + AlgInfo *algInfo) +{ + switch(privAlg) { + case ALG_DES: + algInfo->keyGenAlg = CSSM_ALGID_DES; + algInfo->wtype = WT_Symmetric; + algInfo->encrAlg = CSSM_ALGID_DES; + algInfo->encrMode = CSSM_ALGMODE_CBCPadIV8; + algInfo->encrPad = CSSM_PADDING_PKCS5; + algInfo->ivSize = 8; + algInfo->algName = "DES"; + break; + case ALG_3DES: + algInfo->keyGenAlg = CSSM_ALGID_3DES_3KEY; + algInfo->wtype = WT_Symmetric; + algInfo->encrAlg = CSSM_ALGID_3DES_3KEY_EDE; + algInfo->encrMode = CSSM_ALGMODE_CBCPadIV8; + algInfo->encrPad = CSSM_PADDING_PKCS5; + algInfo->ivSize = 8; + algInfo->algName = "3DES"; + break; + case ALG_FEEDEXP: + algInfo->keyGenAlg = CSSM_ALGID_FEE; + algInfo->wtype = WT_Asymmetric; + algInfo->encrAlg = CSSM_ALGID_FEEDEXP; + algInfo->encrMode = CSSM_ALGMODE_NONE; + algInfo->encrPad = CSSM_PADDING_NONE; + algInfo->ivSize = 0; + algInfo->algName = "FEEDEXP"; + break; + case ALG_RSA: + algInfo->keyGenAlg = CSSM_ALGID_RSA; + algInfo->wtype = WT_Asymmetric; + algInfo->encrAlg = CSSM_ALGID_RSA; + algInfo->encrMode = CSSM_ALGMODE_NONE; + algInfo->encrPad = CSSM_PADDING_PKCS1; + algInfo->ivSize = 0; + algInfo->algName = "RSA"; + break; + case ALG_ASC: + algInfo->keyGenAlg = CSSM_ALGID_ASC; + algInfo->wtype = WT_Symmetric; + algInfo->encrAlg = CSSM_ALGID_ASC; + algInfo->encrMode = CSSM_ALGMODE_NONE; + algInfo->encrPad = CSSM_PADDING_NONE; + algInfo->ivSize = 0; + algInfo->algName = "ASC"; + break; + case ALG_RC2: + algInfo->keyGenAlg = CSSM_ALGID_RC2; + algInfo->wtype = WT_Symmetric; + algInfo->encrAlg = CSSM_ALGID_RC2; + algInfo->encrMode = CSSM_ALGMODE_CBCPadIV8; + algInfo->encrPad = CSSM_PADDING_PKCS5; + algInfo->ivSize = 8; + algInfo->algName = "RC2"; + break; + case ALG_RC4: + algInfo->keyGenAlg = CSSM_ALGID_RC4; + algInfo->wtype = WT_Symmetric; + algInfo->encrAlg = CSSM_ALGID_RC4; + algInfo->encrMode = CSSM_ALGMODE_CBCPadIV8; + algInfo->encrPad = CSSM_PADDING_PKCS5; + algInfo->ivSize = 0; + algInfo->algName = "RC4"; + break; + case ALG_NULL: + algInfo->keyGenAlg = CSSM_ALGID_NONE; + algInfo->wtype = WT_Null; + algInfo->encrAlg = CSSM_ALGID_NONE; + algInfo->encrMode = CSSM_ALGMODE_NONE; + algInfo->encrPad = CSSM_PADDING_NONE; + algInfo->ivSize = 0; + algInfo->algName = "Null"; + break; + case ALG_AES: + algInfo->keyGenAlg = CSSM_ALGID_AES; + algInfo->wtype = WT_Symmetric; + algInfo->encrAlg = CSSM_ALGID_AES; + algInfo->encrMode = CSSM_ALGMODE_CBCPadIV8; + algInfo->encrPad = CSSM_PADDING_PKCS7; + algInfo->ivSize = 16; + algInfo->algName = "AES"; + break; + default: + printf("Bogus privAlg\n"); + exit(1); + } + return; +} + +/* argv letter to private alg */ +static PrivAlg letterToAlg(char **argv, char letter) +{ + switch(letter) { + case 'd': return ALG_DES; + case '3': return ALG_3DES; + case 'f': return ALG_FEEDEXP; + case 'r': return ALG_RSA; + case 'A': return ALG_ASC; + case '4': return ALG_RC4; + case 'a': return ALG_AES; + default: + usage(argv); + return 0; + } +} + +/* + * Null wrapping of symmetric keys now allowed + */ +#define SYMM_NULL_WRAP_ENABLE 1 + +/* indices into algInfo[] */ +#define AI_WRAP 0 +#define AI_ENCR 1 + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + CSSM_CSP_HANDLE cspHand; + CSSM_RETURN crtn; + CSSM_DATA ptext; + uint32 encrKeySizeBits; // well aligned + uint32 wrapKeySizeBits; + uint32 effectiveKeySizeInBits; // for encr, may be odd + int rtn = 0; + uint32 maxRsaKeySize = 1024; + uint32 maxFeeKeySize = 192; + CSSM_KEYBLOB_FORMAT wrapFormat; // NONE, PKCS7, PKCS8, APPLE_CUSTOM + CSSM_KEYBLOB_FORMAT expectFormat; // PKCS7, PKCS8, APPLE_CUSTOM + CSSM_DATA descData = {0, NULL}; + CSSM_DATA_PTR descDataP; + + /* + * key pointers passed to doTest() - for symmetric algs, the pairs + * might point to the same key + */ + CSSM_KEY_PTR encrKeyPtr; + CSSM_KEY_PTR decrKeyPtr; + CSSM_KEY_PTR wrapKeyPtr; + CSSM_KEY_PTR unwrapKeyPtr; + + /* persistent asymmetric keys - symm keys are dynamically allocated */ + CSSM_KEY pubEncrKey; + CSSM_KEY privEncrKey; + CSSM_KEY pubWrapKey; + CSSM_KEY privWrapKey; + + /* we iterate these values thru all possible algs */ + PrivAlg privEncrAlg; // ALG_xxx + PrivAlg privWrapAlg; + + /* two AlgInfo which contain everything we need to know per alg */ + AlgInfo algInfo[2]; + AlgInfo *encrInfo; + AlgInfo *wrapInfo; + CSSM_BOOL wrapEncrKey = CSSM_FALSE; // varies loop-to-loop + CSSM_BOOL encrKeyIsRef = CSSM_TRUE; // ditto + + CSSM_BOOL genSeed; // for FEE key gen + int i; + + /* user-specified vars */ + unsigned loops = LOOPS_DEF; + CSSM_BOOL pause = CSSM_FALSE; + CSSM_BOOL verbose = CSSM_FALSE; + PrivAlg minWrapAlg = ALG_MIN; + PrivAlg maxWrapAlg = ALG_MAX_WRAP; + PrivAlg minEncrAlg = ALG_MIN; + PrivAlg maxEncrAlg = ALG_MAX_ENCR; + CSSM_BOOL quick = CSSM_FALSE; + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL bareCsp = CSSM_TRUE; + CSSM_BOOL refKeysOnly = CSSM_FALSE; + + for(arg=1; argkeyGenAlg, OT_Encrypt); + if(!refKeysOnly) { + encrKeyIsRef = (loop & 2) ? CSSM_TRUE : CSSM_FALSE; + } + + switch(encrInfo->wtype) { + case WT_Symmetric: + /* round up to even byte */ + encrKeySizeBits = (effectiveKeySizeInBits + 7) & ~7; + if(encrKeySizeBits == effectiveKeySizeInBits) { + effectiveKeySizeInBits = 0; + } + encrKeyPtr = decrKeyPtr = cspGenSymKey(cspHand, + encrInfo->keyGenAlg, + ENCR_LABEL, + ENCR_LABEL_LEN, + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + encrKeySizeBits, + encrKeyIsRef); + if(encrKeyPtr == NULL) { + rtn = 1; + goto testDone; + } + #if SYMM_NULL_WRAP_ENABLE + /* wrapEncrKey every other loop */ + if(!refKeysOnly) { + wrapEncrKey = (loop & 1) ? CSSM_TRUE : CSSM_FALSE; + } + #else + wrapEncrKey = CSSM_FALSE; + #endif /* SYMM_NULL_WRAP_ENABLE */ + break; + case WT_Asymmetric: + /* handle alg-specific cases */ + genSeed = CSSM_FALSE; + switch(privEncrAlg) { + case ALG_RSA: + if(effectiveKeySizeInBits > maxRsaKeySize) { + effectiveKeySizeInBits = maxRsaKeySize; + } + break; + case ALG_FEEDEXP: + if(effectiveKeySizeInBits > maxFeeKeySize) { + effectiveKeySizeInBits = maxFeeKeySize; + } + if(loop & 4) { + genSeed = CSSM_TRUE; + } + break; + default: + break; + } + encrKeySizeBits = effectiveKeySizeInBits; + effectiveKeySizeInBits = 0; // i.e., not specified + crtn = cspGenKeyPair(cspHand, + encrInfo->keyGenAlg, + ENCR_LABEL, + ENCR_LABEL_LEN, + encrKeySizeBits, + &pubEncrKey, + encrKeyIsRef, // pubIsRef + CSSM_KEYUSE_ENCRYPT, + CSSM_KEYBLOB_RAW_FORMAT_NONE, + &privEncrKey, + CSSM_TRUE, // privIsRef + CSSM_KEYUSE_DECRYPT, + CSSM_KEYBLOB_RAW_FORMAT_NONE, + genSeed); + if(crtn) { + rtn = testError(quiet); + goto testDone; + } + encrKeyPtr = &pubEncrKey; + decrKeyPtr = &privEncrKey; + /* wrapEncrKey every other loop */ + if(!refKeysOnly) { + wrapEncrKey = (loop & 1) ? CSSM_TRUE : CSSM_FALSE; + } + break; + case WT_Null: + printf("***BRRZAP: can't do null encrypt\n"); + goto testDone; + } + if(verbose) { + printf(" ...encrAlg %s wrapEncrKey %d encrKeyIsRef %d size %u " + "bits effectSize %u\n", + encrInfo->algName, (int)wrapEncrKey, (int)encrKeyIsRef, + (unsigned)encrKeySizeBits, (unsigned)effectiveKeySizeInBits); + } + /* iterate thru all wrap algs */ + for(privWrapAlg=minWrapAlg; privWrapAlg<=maxWrapAlg; privWrapAlg++) { + /* handle disabled algs */ + if((privWrapAlg == ALG_AES) && (privEncrAlg == ALG_FEEDEXP)) { + /* + * Can't do it. FEED can't do PKCS8 because it doesn't + * support PKCS8 private key format, and AES can't + * do APPLE_CUSTOM because AES needs a 16-byte IV. + */ + continue; + } + /* any other restrictions/ */ + + /* generate wrapping key(s) */ + getAlgInfo(privWrapAlg, wrapInfo); + switch(wrapInfo->wtype) { + case WT_Symmetric: + /* note we can't do odd-size wrapping keys */ + wrapKeySizeBits = randKeySizeBits(wrapInfo->keyGenAlg, + OT_KeyExch); + wrapKeySizeBits &= ~7; + wrapKeyPtr = unwrapKeyPtr = cspGenSymKey(cspHand, + wrapInfo->keyGenAlg, + WRAP_LABEL, + WRAP_LABEL_LEN, + WRAP_USAGE_ANY ? CSSM_KEYUSE_ANY : + CSSM_KEYUSE_WRAP | CSSM_KEYUSE_UNWRAP, + wrapKeySizeBits, + CSSM_TRUE); + if(wrapKeyPtr == NULL) { + rtn = 1; + goto testDone; + } + break; + case WT_Asymmetric: + wrapKeySizeBits = randKeySizeBits(wrapInfo->keyGenAlg, + OT_KeyExch); + genSeed = CSSM_FALSE; + switch(privWrapAlg) { + case ALG_RSA: + if(wrapKeySizeBits > maxRsaKeySize) { + wrapKeySizeBits = maxRsaKeySize; + } + break; + case ALG_FEEDEXP: + if(wrapKeySizeBits > maxFeeKeySize) { + wrapKeySizeBits = maxFeeKeySize; + } + if(loop & 2) { + genSeed = CSSM_TRUE; + } + break; + default: + break; + } + crtn = cspGenKeyPair(cspHand, + wrapInfo->keyGenAlg, + WRAP_LABEL, + WRAP_LABEL_LEN, + wrapKeySizeBits, + &pubWrapKey, + CSSM_TRUE, // pubIsRef + WRAP_USAGE_ANY ? CSSM_KEYUSE_ANY : CSSM_KEYUSE_WRAP, + CSSM_KEYBLOB_RAW_FORMAT_NONE, + &privWrapKey, + CSSM_TRUE, // privIsRef + WRAP_USAGE_ANY ? CSSM_KEYUSE_ANY : CSSM_KEYUSE_UNWRAP, + CSSM_KEYBLOB_RAW_FORMAT_NONE, + genSeed); + if(crtn) { + rtn = testError(quiet); + goto testDone; + } + wrapKeyPtr = &pubWrapKey; + unwrapKeyPtr = &privWrapKey; + break; + case WT_Null: + #if !SYMM_NULL_WRAP_ENABLE + if(encrInfo->wtype == WT_Symmetric) { + /* can't do null wrap of symmetric key */ + continue; + } + #endif + wrapKeySizeBits = 0; + wrapKeyPtr = NULL; + unwrapKeyPtr = NULL; + break; + } + + /* special case for 3DES/3DES */ + #if 0 + if((wrapKeyPtr != NULL) && + (wrapKeyPtr->KeyHeader.AlgorithmId == CSSM_ALGID_3DES_3KEY) && + (decrKeyPtr->KeyHeader.AlgorithmId == CSSM_ALGID_3DES_3KEY)) { + isAppleCustom = CSSM_TRUE; + } + else { + isAppleCustom = CSSM_FALSE; + } + #endif + + /* cook up a wrapFormat - every other loop use default, others + * specify a reasonable one */ + if(wrapInfo->wtype == WT_Null) { + wrapFormat = expectFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_NONE; + } + else if((loop & 1)) { + /* + * FORMAT_NONE - default - figure out expected format; + * this has to track CSP behavior + */ + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_NONE; + switch(encrInfo->wtype) { + case WT_Symmetric: + expectFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7; + break; + case WT_Asymmetric: + if(privEncrAlg == ALG_FEEDEXP) { + expectFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM; + } + else { + expectFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8; + } + break; + default: + /* NULL encr not done */ + printf("**GAK! Internal error\n"); + } + } + else { + /* pick a good explicit one - this encapsulates the + * range of legal wrap formats per wrap/encrypt alg */ + int die = loop & 2; + switch(encrInfo->wtype) { + case WT_Symmetric: + if(privWrapAlg == ALG_AES) { + /* can't do APPLE_CUSTOM - 16 byte IV */ + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7; + } + else if(die) { + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7; + } + else { + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM; + } + break; + case WT_Asymmetric: + /* Can't wrap FEE key with AES no way, no how - + * this is detected at the top of the privWrapAlg + * loop + */ + if(privEncrAlg == ALG_FEEDEXP) { + /* FEE doesn't do PKCS8 private key format */ + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM; + } + else if(die) { + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8; + } + else if(privWrapAlg == ALG_AES) { + /* AES can't do APPLE_CUSTOM - 16 byte IV */ + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8; + } + else { + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM; + } + break; + default: + /* NULL encr not done */ + printf("***GAK! Internal error\n"); + exit(1); + } + expectFormat = wrapFormat; + } + + /* + * If wrapping with apple custom - either by default or + * explicitly - generate some descriptive data. + */ + if(expectFormat == CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM) { + simpleGenData(&descData, 1, MAX_DESC_DATA_SIZE); + descDataP = &descData; + } + else { + descDataP = NULL; + } + + if(verbose) { + printf(" ...wrapAlg = %s size %u bits format %s expect %s\n", + wrapInfo->algName, (unsigned)wrapKeySizeBits, formatString(wrapFormat), + formatString(expectFormat)); + } + /* OK, here we go! */ + if(doTest(cspHand, + encrKeyPtr, + wrapEncrKey, + decrKeyPtr, + wrapKeyPtr, + unwrapKeyPtr, + wrapInfo->encrAlg, + wrapInfo->encrMode, + wrapFormat, + expectFormat, + wrapInfo->encrPad, + wrapInfo->ivSize, + encrInfo->encrAlg, + encrInfo->encrMode, + encrInfo->encrPad, + encrInfo->ivSize, + effectiveKeySizeInBits, + &ptext, + descDataP, + quiet, + bareCsp)) { + rtn = 1; + goto testDone; + } + /* end of wrap alg loop - free/delete wrap key(s) */ + switch(wrapInfo->wtype) { + case WT_Symmetric: + cspFreeKey(cspHand, wrapKeyPtr); + /* mallocd by cspGenSymKey */ + CSSM_FREE(wrapKeyPtr); + break; + case WT_Asymmetric: + cspFreeKey(cspHand, wrapKeyPtr); + cspFreeKey(cspHand, unwrapKeyPtr); + break; + default: + break; + } + } /* for wrapAlg */ + /* end of encr alg loop - free encr key(s) */ + cspFreeKey(cspHand, encrKeyPtr); + if(encrInfo->wtype == WT_Symmetric) { + /* mallocd by cspGenSymKey */ + CSSM_FREE(decrKeyPtr); + } + else { + cspFreeKey(cspHand, decrKeyPtr); + } + } + } +testDone: + cspShutdown(cspHand, bareCsp); + if(pause) { + fpurge(stdin); + printf("ModuleDetach/Unload complete; hit CR to exit: "); + getchar(); + } + if((rtn == 0) && !quiet) { + printf("%s test complete\n", argv[0]); + } + return rtn; +} diff --git a/SecurityTests/mobileasset-certs/AppleRootCertificate.crt b/SecurityTests/mobileasset-certs/AppleRootCertificate.crt new file mode 100644 index 0000000000000000000000000000000000000000..8a9ff247419dd22a07c837ba7394aeabdd0f14e2 GIT binary patch literal 1215 zcmXqLV%crb#JqR`GZP~d5E<~YacZ@Bw0-AgWMpM!Fi0}wHsEAq4rO5zW(o~96gCh9 zakzxJ9199^QWZS&lJyML3{*gZ+`_UDLFd$>lFYQsBg2!4D>>yS-j;I@c+L7YuChh5U7`KHvAiEsOqE5wMI&W5Px=0B&b;#hyADPKr1x`dQTTp(jgCTo z!8UtFgP!fq=lSQ_e%AKXkUH`2+}53ZH{)ckownU-we|}?AHyW>jf!G=C0A{DZzqYZ zUR*fIJvj8>dVR;uKYl+hIQwj|k87R0Pjj_t->jT;Rj-bAq&^<-@B zm%W!-{69S|b&uzbviZg$sSC@eoYZAvW@KPo+{9P~43RPeK43h`@-s62XJG-R8#V)e z5MLO?XEk63QUIB4HrbfL%co zBPgB8DzG#$asX{)0b&Md!c0zKWi)8~WT3^yq0I(NqwGwKVsaTJB?ZM+`ugSN<$8&r zl&P1TpQ{gMB`4||G#-X4W-@5pCe^q(C^aWDF)uk)0hmHdGBS%5lHrLqRUxTTAu+E~ zp&+rS1js5bF3n9XR!B@vPAw>b=t%?WNd@6N1&|%Uq@D!K48=g%l*FPGg_6{wT%d-$ z6ouscyp&8(HYirePg5u@PSruNs30Gx7i1YwCER{crYR^&OfJa;IuB@ONosCtUP-YY za{2^jO7!e*{cX?eJDxY@8r; zW8atJ+3zl;@Sm>qH@UIM?q|jS>=W#7YAu_)gB31Y9ND;kmOoeaf9*e!%UL;V#2vx} zUUwk!R<>!CBEM2a=7;zgw~E zguTASugG_6SFxo3)|+Pa2irq$E}yy6$m#cutA+FG76xsX-aFYzMMzw9>OIdRD+ Xyc@&=R&`yy_2kb5PImJRrKO4hMS!&; literal 0 HcmV?d00001 diff --git a/SecurityTests/mobileasset-certs/Invalid-task_signing.crt b/SecurityTests/mobileasset-certs/Invalid-task_signing.crt new file mode 100644 index 0000000000000000000000000000000000000000..223fa7f1da40cc8f22cbb3b75492acabc30f1978 GIT binary patch literal 1000 zcmXqLVt!)K#B^o>GZP~d6Qhm+FB_*;n@8JsUPeY%RtAGgLv903Hs(+kHesgFU_)U8 zK@f*an9H%CASYG9GcQ@sP|ZLEB*-l+3lVfqEh@=O%S=uz$;{7Fa4ap!$S=w)sWj9z z&<3ev7FL0%%M8fK&r4Onq1-@DoY&CMz}(Qp$jI2p*f0vnwLsz;#1i2&IRhDp(?p?G z`Uflchd3&PBo=39=A|1-8i+%jBmfgt2+mB;14wk;=~i``UOMiesZe88p0+Sa$JI!$Ic`q(_Mk~Srk?54ZYs-ty83Ku+m!=ltu%Gj|Vi>^peV*8p0_m%}m2Nf|J2$^u zX|(rQk&w8$lwqN++5b4jO}m>C%u7dK8aXzVxO0|ufjKO^IR78YhE_6Bf@krifPGGH)}1xfL- zh_Q&=o__gJtl^=w|Es4eKWmOi(Yl!b(!c^FEze?Tpl_hNKzo5^n|ek`Nr9EVetCJh zULq)s=_Tjq>VsLyiTarZpd_Q0T$E!V3DT(mvXkF{*MJ+EY?D)1Igz6cn1+GT#>ik| zv!Lbi=T9H*y?vc4blKl)f9TV@NbK3PdvPV{QKw{8Cm3wnZ?w#J zld|)4?#Y`jZ$9{7*Y)RR_PgDMw1sZUUsx)&=l1*K-t04SI?gpMXgSyXzhIlS@1cVn z(?8rU=T2SG6Y<=2>h7I8C6_3j*SPpQ=4V!=%C!@%n-;IX95l)8>GZpY7S}$i;VYW5 zVX4|r+oXWj4HZo38`E7DoSB}NnU`+R#HfTEDvYcQ%uS5^3_x)% zrY1&4hOMU?euOso%j{8?^UbQ$b$xu%+$e7M6VHeQ#)P(24jqeERj%L;ooaJtb^qaY zB_;(-doD%yEJ!vwIyZ8mPyfF=Hw`M4oC>Jk^jr|6Ez@U`nXJq`(!otkN-T+QIvcfD(1`Oa( zmgQp+V-ZOXIP!1P6)p?89ZBU2Vhr}ktdTuvU;)x8&thnxZ=kzCdx2(~dPYe}ft9{~ zd3m{BA}F!xCFkergIURm`k4iww4;|?lw%+X(y0Klliz^XfE${AlT%nZkfRNln1Rv8 z$S{Aw;)fMaJ&$;_$MB0E@aDF^JAJ{LiCf;N)_i+(p?P+N%-+3zd(W?7ePODueY{(@ z>A@Wr2{WD0#`l4{=frKCyDM&q=IXx0gT~7`RGu&JaD917PW!-07G0BBp|e&Una0&T z?~;ACZQEwvZ$4W$@s<{R+PY}(iAdq6e)}UQKU{ZO?s%bL+7XMcC;Qw&ta>7+awOZR zo88JPN!H6gc>Le}PX;Q<3sqImg>5(7@kZ_7<819fslNJl?T z-{bHLyT$ikXL2}Dv-QN$X?yd2>b!_iJbYCtCAfX#-PH@{y_E3knAN;r_fW#c$$NKY Rc5XCjzmYWI%_WiD#sF=GeT4u3 literal 0 HcmV?d00001 diff --git a/SecurityTests/mobileasset-certs/iPhoneCACert.crt b/SecurityTests/mobileasset-certs/iPhoneCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..c6849621d8e5b36ead6142b5114848dafa03b52e GIT binary patch literal 1015 zcmXqLV*YH<#B_TBGZP~d6Qj5RFB_*;n@8JsUPeY%RtAG4Lv903Hs(+kHesgFU_)U8 zK@f*an9H%CASYG9GcQ@sP|ZLEB*-l+3lVfqEh@=O%S=uz$;{7Fa4ap!$S=w)sWcQb z5CN%U7UqSh3(C(gQE+xNkQ3)MFgGwUG%_?dF*dS@66ZBCLgE@!Qqc{%2HFres6gD1 z8IX~mm#Ton$p%e~O2{F?$jZRn#K_M86z5`UVq|1kEVu82`++U<1ft!R>`>g{-=TN^-~VKbh}-g#39Ky`9aEMgMTN@p>1ZSKbYrTiU-xZ~2>YcXQDL;mv== zZ|-@%;_acH#6wy?-<(?-cP;aE3U@C@|BeL#Zk%@{pFG_#C3pAtnKO>OnC<9y7c4RFPLxU$=(tOZCj!l;mPyL{ko`$@wWpDT)YbQ>1@?9Fz?Y5eSPss&UA~=u#KkL z5wBbptF^v6k>>T}eCG$-S4~q?K7D48$5lv@c}3PbuU4_a(bm&tchjci(!BI0G|~0(lmF17IXB&|IM2 zrkYVwQedU8UtV6Wmk3Iaddc~@`e0UaqJ9xDdFdq=jbqms=gzg*sn91{GbD=8J&d6~n@F()GI-fXLftl>|S&R^mO E07{s9>Hq)$ literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/AllCertificatesNoPoliciesTest2EE.crt b/SecurityTests/nist-certs/AllCertificatesNoPoliciesTest2EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..ae6be6c4c8f63f4853d671e0b30d3e09d0cd5113 GIT binary patch literal 898 zcmXqLVy-i2VoF=U%*4pV#K>sC%f_kI=F#?@mywa1mBGN>klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6gLnBDPR`n^UGHV$j`}4&IC$1I~vG| z^BNi$7y_Y%v4Md>lsK=kfuWHxjBAiZqD58)77&XJ9dmL}9fEALt1Ggc0?5@y22G4g z$o^zxWngY%6){F1jHDtM+5kAwW{-fc@l7RVI&QD4_O)Whd53>9$pDoB0ydrn6=#O`@ zihF%7Myx!0EBeA|gC9~p0xc7E`~98Fvtjkt$eqHqJC1y1m?6eJcN4dI&xD?>*A&;U z+YqaLZRZyKeRuj?i{F%JeiQj0!rZd(zusTdb+T5!xSEfsGQByuW!JyUe$S zKa1g-nIlfOs)L1r?Sh?wnrh4cb#vih1`|P;_cG=PJMYKoZRkpaQ4QM_zkJ2zO(vl z2zwK#@^k@L-(|PL^(pFnx9s|V?p^T2&hqs^848%YRn1%TR@^dniGlAj(hDHj`js|k# zyoLq_hCpaxY+zszCC+PXU}$6v;~M0WXp^mhHN++p$DABgmjox~rYgYgcXdUURRB30 z=#VBxC1k%cvNA9?G4eA2#krW87#SHZDE;Q^skl*epm}NLUXRIMH})8R{wKZcXH4nB zo!>(IR%=>W?BDWNyzF}8?uWX&W-rKYoV|I$w&O+tQe5V)yjz9(WNlsT0 zo+)A-J@bwt^F=v})L4ZqldYC3YFGU_-us|cA|-8+ZggkN*_H2ozuj4NxcOT8ljmoc zb29&T%;~kAIdPL+$AlQUWx1bR=RIgn7!W(&9&6dHJ>TwD-hMPdSnPr60&?OVk{zD)9$e(#JSEo>MmxywNcXI%RjE| z27Dm>{EUqMSy-5vSUwo2g7^w7at1O6JZxMEZ61uNz{F?3h{8iph``8UWYFF-NkQ|o z_u>M<_N*V*o94GK4VmD#q}XTE?0QF5F|}Ws&s{d!?JoNCc&C|9!Osl|l~;Ns?KRSi z=3g?Xy7tu2;(OckE_2x;&GH)wSJQ-JPucwPH9dUqf!oq=d>pr`_`~kAG?y$e=}@$Z z`5rTcSIW4u<#^)EBl49CIje(J5B;4}#%<2;yJVRW&`hcC97TK+P5Nf literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/AllCertificatesSamePoliciesTest13EE.crt b/SecurityTests/nist-certs/AllCertificatesSamePoliciesTest13EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..c296e5a4308848dcc1efa76852ff0515898982c4 GIT binary patch literal 958 zcmXqLV%}xY#I$GuGZP~d5E<~YacZ@Bw0-AgWaMULFz__wHsEAq4rO5zW(o~9lsAwC zakzxVLQ;!M6r59wN;14a7kTn1uxb@^dniGlAj(hDOE;&W;9h z;=G0i28KXrVQgSv5GBrQYygykaSd`ww93}N8e)}+V@?jLQ-Tw7Qx)J2aCJqNRRFo% z(Ac1fQ3=_zjI0dIO^o~uKyfanCPqevU7gQs?&m(d?w|f**6k&sGhE*2tWa#%Zfch} zZ*9KmBFp8V&(^CZ9!znQRigf0!QS zgt-3VPWXMl-^HQPLgdKfkLh==T&>cTUjO=rLe=)ax)C#`-_ErAsc`6{%J%g=VjV)f zkqr8Bj}wZ@1b&@(eP^n`TE`{NrUvsf#BR90CcNw5L#rU!Nm;^sLwPrG@VqrF$ayn3m=D74tejoEEkjU5J!tp@VIfRkJLlirRmfl=EMIrYr6-6YEe zZm!5O-~;LBXJq`(!otkN^1;9u#8+U^G0-yLVdF|@^I%K`rauEl6dn@_j~O|#fGHCg zS&R&oTNVDN{qsDtZ}y=V;#Q$jlTLpQ*5Rpd-TuC0=U%lt!q4<%b{W6&e$o5k(Jm#c z<>`5yGNu_*G`7}VTsZNf{d|4COZ%SK2sv}5{M`7L zdA+d0*SES$rgZHt6uwhg0 SJf}MKsGRZMK#4W)761VDRb+?& literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/AllCertificatesanyPolicyTest11EE.crt b/SecurityTests/nist-certs/AllCertificatesanyPolicyTest11EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..7439f85152a7850feb29f4d19081a61e9efd2993 GIT binary patch literal 914 zcmXqLV(v3&Vk%p}%*4pV#K>sC%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`nNzAJZ$j`}4u2gV#G>{YL zH8e0V1VRgA0|SF7ab9BsLnC7t*C3NbYb*`SA=Vf;=H#F{17WYLE3%9N$i;?+22G4g z$ev_mWngY%8NY1fA#TZ`?X%tcFN4I)eB>H-Ql@EZ%u`E z(8hKZKG$WIjW51L=x@JxEh+W4;zSOsS39n?Pw-Oebah+yVCOf35GC%;^?ft#HYhwS zGmd0Q*CT2zk#>J@y$p-SkAeL2TkuVTz5ZQh5 z-U*qh&z&AkSk$+UIcBv=LR~93Ey(h*h_Q(LHGH=s|C5D>eGjwCXZwPDM~gDak>sZKv4l`6_J`>y4O!{#Xq zXDRR9I3skG^UWWh_3oTaG(GvQUD@w#<*3|tMl4LI4DLs{5_nL>jNFo+W8H8wCbGKO&tB1p7G!$1vUjXc5{S65{BD1aPjXkyUBsD$h%Mpg#q zCPsb+pg0#(6C)$TsqmiKM4hBX+WnP$&l~UZlye3I6&Wn8KkWO|F3qMOuw;j^;l=r9 z-ksgp|Hk~%tH_OCg*8QdMZ({FTD<;I?DDooHI4;V{J&EFElw=DdfIEljKj0mnT2Xw zSUg&jkhx=G^yyY1^CRDr|GYVP|Jb@oN(pRp8nc(zpT3ges~*_7(e#uB$D8z-tApo# z*f-_D9CjbW9kOL{R}bEBdHi<0`>j2%`8Eo->{aKm$XkBqc1($e(TQ?F3j?1OeGhj_ zPbgy#;q%QX-n~+M;eVH+6H!GHwkE&N%6dM3*DZ99Px{6w_WbL{2cvyu`4Uf9HcenR zxPEQ18Mj_%k?AdaTc1CR&ij6~cVuE_WMEvJZIEdo4-8RRWflnou?CUdC-0q*nfl!6 z(S${P>zHF!t0dI5f}>uRk420{WaIh7lNAdWHr<>*&x6(A+E>f-yV4E#K>GO^8UM4e zFf*}yFc1gv6<7oe_zZa1xDwht7*m0X%zzO&I)F(G7#)lZ{%lkGbAN41kh^qRJWy0x zV!E5nhuNoHR?h27SgjVyUva%Y`mUQ=N>J3 zt|hjpFsp3OgY(yS7jL}r)9NB?Q<4sT-*;U!xx>!x?4j+q7P0Tr`|&Bz z{-J+}R(ja<8^&$c+;g}WzOWA2zQaT>!gy!e*KD25e;2D~mRH`FyO4KP*J4F(e7b|> z$2RU(+ms(2Gvn(DTW4@z6vD%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz@J2GpzdH67IR8WQE(3OQSdA-E=?^`@Jq~1Rd9AR zXkt`C_6j2_19KB2KLb#li>Zl`k>Ti@d~PZ8#6QPmx33J?w{=4Nwh1f`+eOtAD_5z1 z{I^ofeZnh8i;SjK%KZD@Jh4jr^Ca|Jpv%-lUv;v2uhg|^9XurcJ_w*nS7^%Udj`V+Mxd4K=zDqXW) zW<`3~{28HtR&(#reY^eDyBTL=weEW#tO{VY+%F8h4Z(ZyL| z-zOy=eJXlk#?H|AB^P(R47zfPZ`X5HL8q78JA4Zi-ZC*WGB7T#F{m<-2gaAIGK++P zScAxu+W3nxQ`?2K*oiVUR*r17;wF96!LM z28T-|W}$Gw))shggz{akAjx_ImDZ$+1P+obM(Ja2)Hg5m#v zE!wU}W-;t!owiTZmP5P&Hs7==L_DmohN2wt+O{`e^mVD UoVJ}0-@1JfO`jKL-uS)<0CARHv;Y7A literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/BadCRLSignatureCACert.crt b/SecurityTests/nist-certs/BadCRLSignatureCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..6dfa00d6b8ebf7170e60e14481856e20b0685a29 GIT binary patch literal 909 zcmXqLV(v6(Vk%s~%*4pV#K>X5%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz?Vd8WDTSt)`&PIrYJZE`6vWurspM=loq8bI6E3N zF)AT@gprkjxrvdV0VvMJ)WpchuxQ4i_3SAX0pA-|J8z8qqvLn4D^=U&7~gHN6HdQ0 z_U?PJMM|T>zm8F!kkw%?<}eO_}MQ)bI!`u(-mGb*}03@-deeNu7&vKRvY8zyAJI9 z(U~{-Wi#4pYNec~2$w0+#*v_Na~+LZ+-U7{qy)qH}d zEIh*cI4l3r&(80!-b%#FC-hXNoe|BqeHq&%FL@)@ip$Yz-|2ZJE1rIty>;1_*GDTi zOnV^P$FX!~>HE0NlEP^}eK|DM4hA~z-TQCe&ak_mj&9(b-z^ir#eQXygY6aRxfjkC zt9S`i!*O!eVsX_U4`g2U+-M3` zdf=zAMrDU%o@0xH)2Z|29lxgUm_1KwsgMKfEp90}7e)PfssE2x%m2U7=NIhhJ;P6G S;mT(&vfpNxhH^4G>H`2RKv;kP literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/BadSignedCACert.crt b/SecurityTests/nist-certs/BadSignedCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..0a598fcb8eb03f9d1169377e3e311ca826bf3569 GIT binary patch literal 902 zcmXqLVs0{MV#->;%*4pV#K>&G%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz>P#}#0*3r*6=zdrYHnwrst)mC^$PBG%+e6`+$*^ zfw_s1p8+V&#ni;e$Z-Gtp4Y3tm+!0E+kNVf-_Cz*Ij0{)s`!g+^}@;{ledcSIo`grp~ z{T61WgoBFvTz@BV&h$TP!&KmNK~cN1k%^g+fpKw-L6w0#F#KedStJa^8bqGd#$Sw? z+Qy;7x^7?Tw$$Y}V^^esBU+Y^MT|wH`mTVr*Mk#xU0VG*Y@)i)&QzMb-hdCJpP!NO zKMM;m>984ygZK(80tS2rJZxMEZ61uNKyd>`1AdT%Fi0V*0W*+7jvrtO1I7;{W6FO2 z|181ITej?Y?{_XS>Um`NbB))ZeU=KOGSZjf%j&sb z?|kj@ylktKqI%IT?%Hf$1;4bIuSYZ)zlF?SI_a`h1^=6XYqF^yL`~+Fl;3*Xd|2e+ zgO3kiow(WBrx~?J+KnMu%jZPbLgura#VdPs?Tpm7g&mm8utVc)rs!gWRR3w}`?J@4 Lax+M66)yt-48>Xm literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/BadnotAfterDateCACert.crt b/SecurityTests/nist-certs/BadnotAfterDateCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..7a7dcec665123a801a7cc3254a86e46da9c7c235 GIT binary patch literal 909 zcmXqLV(v6(Vk%s~%*4pV#K>yE%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{0a7sP>a4SY$oM%F+YVvUGXVv0gueu-mRNotXT3(z47&W;96j7rEJ zVPs`sZerwT0E%-lH8Cu;wR zBs^Xjrs}0-vQxM6_v(y$S3~av-w_bHwdCrhd&<3qADTJSf1bRMFWS!^qpaI+eM+l# zpND_Q$%{EV?%H(fM^D)MWyYNqI?eO*gD<6B+u0p5>zH(6y9eVQ23h~oXO{xh<2+YX z&oTYIC(dv8+?5=<#=G{L+x?21;pOTn}?aF&3YRf(O-$;nL2j0}v6YYeIk?-bJqDCn;)Goal2u_2hz{a z$oQXy1(<@^48%cv1r`AVJ_8;$u7oxZ##ErV0iyvwNJ1E-kkx=0NFm1$FrfkChmm1f z$I-~cO5UB8&kjtwFF7x{_QsAm*VVmq%>-AOsy?dzaW{R*-BTwxeod*CJAL@A+i%s5 z0$raM9Qp=arF}1JtF&^R7HG(-9xP#4^@!oJ>buY>sg*ZwdHq^(a(U5gg}a;IWr)2r zjgQz7%3ydVu79TWuGbeWBT}?aB>q__x9`XX#$PVxM>tvj*7|N_S$$}}wZy_khTN&K z)&~UxrZ4*97~zrSu&v9oWPieeO`iH~UlXr8UfrSawG`sYa6%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zF*h&-ssO4oFo*(jEs?keek58WXCMQyM${=WMIkT0#3?l`zbI9~1?Un5XGeo3MkQpQ zFtRc*H!<=v0L8hOniv@wmIqIdT6lbh8~=m#HYFneCR|ccP1jAIKJ(gBxu)vJ%l_x) z{+Dt+>goLSy2|(0npK>WiUVf#B^#!A_}((lK3ufpeaGYmr9$ERm;8=wc~ZQohF@Ui z`PlQbB6_u^s6Lx}Ke_1X^rLz+@_){pExSxaXn6*Q`5LQFMPA;E(=zW_E!zKcdej=G z>n%Nv8?*D8xL1chSJWz!G?lw8`$(wxy{OW=AB$Pe*Swp&sMO<7!p+>J(*%;fM@w`( zy|MGU!dCCo3DsUFrG9P}ofg9L@_zYkAj`)oMy0x{$1-J=dC3PZt2e^)Ob)mgv)5=W z{+ANkEYip)Yx>TvvNWLdwXRV2^{1RanV1-LpyOI?05c10RE!e#kb#8^a20po{}VVj4P z4%@jyujewYRQx~3^YH1_ZU@Y(BVJf74L@Dc|J38p;&t1b%`@2I*C;C-n|HnNlAK$w zoPhC{X?8I`PYY%Xi|=P#Wf)WS`|UT$IuAA$rQ6e`%n$BWGMlvd$)jcYU26|Guawu| zTdJ}seEPP76CStR%{nRj{#Hn(e)>lKmlo4g?*8|&*rAm%d+m~6M`zq$|M0)jqKMFi zb6Qs|DKkoVxG>q|jL;?DD7*Fxt}P2>Bg_s*CfeS=&8KV;wtKPoqZJ{0C!3z=eR=1{ zA>D6Jt$sBf?Y;B1H(+CSyy;AV?>}BlIDDmft68`(^MzS+mHRhT=4_m#vCjJK0gm|S NRY&|DpLnl(3jo+{UD5ym literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/BasicSelfIssuedCRLSigningKeyCACert.crt b/SecurityTests/nist-certs/BasicSelfIssuedCRLSigningKeyCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..4e1245299d42e8d9400af61a3106e82c8fedc856 GIT binary patch literal 925 zcmXqLVxDQx#MHQenTe5!iBZ&mmyJ`a&7Z=o)B4tWj}FEY3_;2u{sO)AcMaE=^5Qa1QcO z2+mB;%gjqx@J_8%aCS6kVpKx*7$YkKa}y&!15licsfm%1VfN|vi7%p0wz-?mQ(ZAd z@Ag4+_QjH_UM$jYCNVF)cg=r-)n)m|dm4E&Hb)CjVO%M=VP4EU1D0Ux-%rX|?edOo z;Q3?n(D2Bt3ErC(*1i0EulI+}q0?`crrp>2U%Ax8uK3Z@_OJhQ0=55l@VhOWGw<%I z36bnai`bjQo3Fo$Vl-0JtUb=?us1qVC1O&fq-e~ULrWuf?a8uQ=^f_!JxO()=H(yd zfq!q@Im4-Dm3vPs;d$@zDi_(O`~Oz{QjHI>UE90vKmtQdPK=_~9S@GlUyELAoxH|u zQM@7`<(B1)gU4I{u&Q6(J*Q9qMeZLZdBH0Z%l0rU$Bs8Au_=4=~{Y5$yp!P$aXZGDKbMItdG*G-_6u&}Qep|Oh zP?-3Veb*zim9P1wG@s%4a5-neizQ8Roi6%bUYqYv+Vy>DD7W9g{q}E|zV8h`c~bw< z$Bo;aPo0+z+^yTU>3gR1rgciY1+TfE**mdMUByED+;#t%%+8;$%B{*sY*JZ#>m$dz zl2)E8Sz80sbY{=)6F0v!gk@aL`M=W!d#xg1Ix)eeQz5CqsoEUtjS9+Zay6npfvGTZH?h;`8vNXE0atn+%SljmT5T4bTac{&2^7` zG57aHX~;0P_qnWEEdS)rc6m8%{w05MGW0gGpI+urWSjdw?o;fZqkc!kXKSC^&=*p? z>L%w*d7Xf;=qtOg--_xFf5{+l#KnK3=H50Pp{rfD{&5~>HfOB-!SZhZ>V}zfUdnDf zVzSw@>VUtgZ~DsafD5-+FO+BtCLHi>2j_y_pXMusR!)$-WuubF0WeU^Qa`snu(c_fpKw-L6w0#FgRtE zStJa^8bqGd#$Sw?+Qy;7x^7?Tw$$Y}V^^es<6V}IMT|vc!Jh*A8^WPUqNOyi@r)cZco$;#{l!>t?BkYwr$A-MWX9SB-!7^_9UD zwV~TyP2RQi*S&-kMa7HBTW(u_TB*NXHT$6ag8CDml!UuV1Ye$AoVPlp?L~{-34Pt7 zgeyn#bo=CcrmZiit$Y#Y;$E(+U?+Cid)~(BS2xD3QIItFsDC6!v+dYfDX$q7D?S-} zuD^Bq;WhIY;_k)o3Zl5Rj}#sMca%NJozZ*eEp<=v%p@hLBNe3cDQ4>ORc?B9 XeL}12w&kp9UyHBzUNK(2RQ?zM#jH|> literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt b/SecurityTests/nist-certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..8773e48464cb139645d7079868597feba315fc6a GIT binary patch literal 933 zcmXqLVqR#_#MHTfnTe5!iILHOmyJ`a&7VpKx*AR{XSa}y&! zgFzD`7gG}>Bg3g@a#3EZ7Kkh{n|q^_#X|boCY>->uKL+?TT{mzh%O=jPt zX&3$DPEB3Id47R=!|D}l-u2&OIJ{k^letN%yU|=FCU<{-RqArCN%ksR&ao|3K6Urq zv98uxlJ}klE!k_?z@aYnvYqkB%?Oj%xBdy`2=PvIn||-rk=ZO0SH=Dbe?7OcX@+{o z(HR?`y>$QlTp&kAQoWj+Gf(JGnc~cLyYFh8N zynOOtEvL;S{SBTS>;ArrlyXED{D{4I&Hv9ME|k`fd_i z&PutL@$rl1Cn-+_rvq6&7BLo)vYHzyEGC@(_X`zE_<6);o2_WNZomi9&(FyCpM?dO zve*p7L3{-k0Ruh*9yYFoHV?*Bptu2}0Y6AW7^INZfEh?3#}6<80^^5~f%gz2`|5{l z7Z;u`yPo9N8qh1hc<&*z1ftC4si?> zg_B**r_ka1U;5A&DdEfiQW47$bg(VRg%1n~$ z=PgaY5fpfr`-X)0dRZb!~g z_kY)XOFr93pg^t9>c!SA%B8g)4mwvjrNkKf)^Cnjuq1kQMy|ycg}{GW8?J;YF{_0yFm+*-k-N(LHR!X?+2^Tod8@fK{%#%z@=C7}+ GrvLyPpI3bV literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/BasicSelfIssuedOldKeyCACert.crt b/SecurityTests/nist-certs/BasicSelfIssuedOldKeyCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..b00748cc262b20871e9c0a460dc865bea275c649 GIT binary patch literal 917 zcmXqLVxDNw#8kO}nTe5!iBZIWmyJ`a&7+Fs6nudiy;GIQ_DWzS45eVMiTM*P1}vu}sK3+I%a`%_*c;dHevB2Mf2Ep6#J zx1$_{k`f+wGfwO(iiwbp{LRkT!L-;wNVn~G*R*{$4mygZ>plva-6>zJb6xnV%4OCs z7mtJBET((~jzWn>G1&*S+sN56m_mlC&w_Y?o(Is`}3{ajDv*95=PqjLQvb zB`)T_m>3rR@934xh4W5$a96ebzyEcy)Aeof0fu?H-*qCNy?nvX#LURRxVXlk%0M0% zoU+O+5(Z)oB2Q}LFUCx5hhbhE7HL6F3ZOv#v*c;x3o7nL+Hq9QHKK} zZ6aa@3-_%z-~;LBXJq`(!U9Z5YzE>Wz5kHdX-z{p5?-n}xT-;)w$L0+M z8=w9%N{h0cesf8+LYgkO&-@d;LB&f_UZmJdi>+hs7M@stUw;bY-}OoF9rD7(&->U0 zJfFkooPF;8FBZ89ek1n8gqiz4G<`k8zns;t;ekQ=Es@&2Cu}To7KM0=g`V=f=Axa< zcSrt!->Ua~x#=Y?&+X3n+Q@c2Grja(-Tla=#Mwut_{S<7d0HQFNsH0&CPR%&#Qxt0 YGPZA=nx%VHu35l2JVEnAN|nV40HqyRP5=M^ literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt b/SecurityTests/nist-certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..963f57a485d4a986c4078da47c3ea70c3a4979a7 GIT binary patch literal 1067 zcmXqLVo^6}V&-4K%*4pV#K>sC%f_kI=F#?@mywa1mBAp?klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kWR5efrDPR_saY`)COjZa^%}LYsEG{lh zO;PaANm1}ltyFM!G>{YLH8e0V1VRgA0|SF7ab9BsLnC7tmsZv`F)AT@kdc*vxrvdV z!Jvtei>Zl`k>OB*zrp9TtB-cLthebrwM9Lv&BD>}vs|)ia{g*~6s=R*5&@esR+wy4iPWE{&Y+njE`<#rDF1;~O-D+}t_kYjI!=XZN zYE@m0Sy)U}U+`i`*wOn_G0Up6X82#DQX z6){`d#gOg)uKO1YOpj~c`+a`{+mr{o`A7e3Jj1)Lw{Q!G)zb-*++R3@uFU>(UT`;S z>q0pnmB}X+y4F;BUK9N8IdQ|E$J;w4Z%tqGaO*6-H+fsDQ~p+FWHH+^6lNTjSDb#l zppG59+~qCp4bBic za$3~kfJmE&n8Ct*>%mDumXAe@MWiEspS`JN+N{^Uht#CiHfpJF<-Bq0n^$ZEh0qzoDxKqB%il?LSor3;D| z6fVg($R#l$+8S5`4FM)Z6XYZaO0Wtp0SamPMGANmC~7tUrV>VmY~4d4z5-ua?*A8; z(pa%?!bjyKR$lH!4?ChK_2eZxEdPGn?PYnxoVOFr5(TS$7x^u?Z2UYRRKRyq!X)$d z489Y4{>N#GzG6P#H0dDw)DN}MqBH-oe0+1qH=9e%@5q(@P0Vj9#V3n@ObJ(d!zI+B zHu=!6gjV(iR|42p?5aIt5Y(D(^o4B!yHyE)lwDfw-*BxPCEUt~A1r$MuYUQT)=viC z-_B6DB{uueU3Lk+$g;kY>FirWi?mz{m7>pXn5gM1Cg7&}_IOB(+$<$iUFhP{4o>q<~qN-90})MZww8Ku(<3(7?bD z2rY~a3=E>gd5sMWjf`PjgA@{NFflNK*r4qk5Udc8pP5&ZTBHzInwSH036SOLitH=} zkUNbG44N2~kiEvp%D~*j$j<;2=VEGNWMnudy0w^lnyJ#^qjy$Y>13*$Gl^%-+%&s& zN#LyaC65krTYixL-n}}$AZNh|2DOwjwuM29mDYLh`Sxhdk>{K(7EG5f9J1KL^n_O{ zVS@*Qa`MrB|Gm$=KCmqN>-6eJ*y_(W3a%Yr9ejM#ZRVe`cVo}L(fbh2SbS7)!@v0& zj!RnN*q_f&e||^DB;kH{;*Ippc5AJjH?MJdc=~spC*NuxpC7ZA9S-t1D4czu{yFQG z{>vYia;>YE)d~3(6nE>6_U`nHHxt`gcLf#Px8(d9&zLo{aepA+eNF#&3bj$8EC-l3 zF0V?fh;}`i&LvaucoFX^-&w)(2Hh5Fk||5wOLtl<=SkRX&&15gz__^ayg}m`19@Qh z$||!+7>G59L@>6fNbk`On&M@&C@auZ3li)NU%f}+dBJ$4Z0)JH5%CxYKgY7fc z9`W^!1aAi<0&7GK)*}((}vo(~I&;3ySrFL-do2Dho>T;}Z)CisLi$ z(uxv+D)Wo<3$iogi&E2p>WdOfGV}BFGD>oDlmomyK{1aU=fLC)jB`eYEPHw1Win6Z zKhQd`g=xF(7uAKr?V0>-i)QrdJr8C(ezxZSdGX0>w^-N8>$>`Lkqf^-7Dw8ax=(s+;^L3RO%DIsIHhCZ?LV9M&Hvw~F(c-VN0HLQcT+_x HDrDOLCmMok literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/DSACACert.crt b/SecurityTests/nist-certs/DSACACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..14787b05801bd1609875ca9bd1035f5301e776b2 GIT binary patch literal 1045 zcmXqLVi7cGV*0s&nTe5!iHZH90WTY;R+~rLcV0$DZdL{ZS3_6FF7N>$Ush< z*U-Sg5C|=d4GavT#CeSk42_IoTmyR&t>Fi{6KoBeOR%GYv!g*1<8~m{VPgk6{+tC1 zBakD{)Y!;y|EZwet(V*K1g^cB`)ID!2KT)#49CMxoXNXj+!E$)YWpqZ#N$J2cke3w ztZ&S-?5E+I^v6$U=Kj&lTNU0>Wb&wwVZwvOYf}0Se6x}5-*Ups!yvAH)toXl?%Tq} z#?8|Y9NqlP{Hxu6QQj*H^>!KlSlxbu`%L)^r@S?jXB^tAS8c-0B+77}jpfGw?$-=2 zzs0amEB-qz)k>cofvx_j}(Gd_Vo~neUNF{d4A=73hyy!arv_`Nt<+?&>ank_qHwai%Oyo_t~J=n2mzRZ;KE^&`?PI(B+?s~m$@$XarPjH#f zyu6*s;z*&GX7ahMoR%MA!anSCtJ5)9wlFoYztQ@HXYLodsZ;is` zFf}%m==+ymXbe}**G)^FaM4NOwDWwwM_;W(F5Ni(>h9-Fa*eYR1spgxRRw-d`)Q_J z5c1+>TGf=L8^1^!N`%Gk?~)XApO~=fXRm7vlXrdkW~OibxgtByrcAiY({cQWx6s8M z`-~RM-|5w2e0cRXCvR_~x0<%>KiKOQeZR3NEVxiBxO#DoL6w0#(DAa$ED{D{4I=#$ zj`fthsOC8ldA!ypIwUedm3t#Nd}aAq#8^a98|N2T^{oBoEPLX4e`wze@7wK<4ER9$ z`577iv#sC%f_kI=F#?@mywa1mBGN>klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6gLnBDPR`n3&_vOOwI&~2N)|jI~vG| z^BNi$7y_Y%v4Md>lsK=kfuWHxjBAicqD6)V`VfmWTr$(rQj1daN)+H$y1F7eO#$Rq zLnDJGMkQqLF|sl+H!<=v0L8hOniv@wK9~6KQFf4U3*xT4_lw16>W3v^>~FSgaKE=} zdB79i{x`mjEpO~U9+$~Jf6)Je@Rhv>)C)g&9gt*E_gEo#?phzu-+g7Bi(eP3OElf_ z`I;$uq`;Mzvu8Hb)S^eC4GR`ziOqfEIVpMV{OWcyl`er!A(wjx4m_CScX9X8$=idH zJy)e_&hyJMlWo0pY>!Ka)kHS~w*wC)Gq+8=7i3)H>lbyyw`NcI`4g`#x6V0yr#^CC zy4RwUzueBK7`&bKj+yUQ<@&`9@qATjaXdU{WDbY5>|2|6Mly!K;;?VH-NUbLs;nJ> zyy|jHhBdqvar@?+VQhc>_=V}T^un1TUl>hqUU{baB9Muhk%4h>wn3(WJTPcwm02VV z#2Q3yu&&lw(0zE)onvdW?Du~@Hsk4?zu;6L%f}+dB62vtF?5ZY-;sy~2?zEoO*;|$ zd-7ESK9GKXM#ldvEX+(S9}L7nd<7N(13m*DHm-y=55`nrdNW`_jt*dI14aiU!(z5a z%3(>njJE5`+*`K!{>HfxX^(gr6&3k5s;w!S)Ev1;@9;03l$<)gqqZ+4O?2CeucZN{cz5P7_vAdj>^uB^ zyqDIQCwz_jUvYeomhx{X*QJ(M@$zNUg5WvkmR>8{8U||$z5o>#A!<4*MrrMtF~}X LmYCk;5NibhwM$t; literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/DifferentPoliciesTest3EE.crt b/SecurityTests/nist-certs/DifferentPoliciesTest3EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..57f1df4334e9675b3a2c6ffe09b867899deeb0ac GIT binary patch literal 916 zcmXqLVxC~o#8k0>nTe5!iILHOmyJ`a&7{YLH8e0V1VRgA0|SF7ab9BsLnC7t*C2sJy9^BUAa<#{WTvI17NzEuD8OxXbwzfa z0?4_>22G4g$R1>5WngY%V}Dq@B~R_1oUz9#eIf;o}enb6u{r&wYM*>Be}Le|&Jr);wtE>m5vL zf8tqRncTCM_qd*4IK6Vi=Tdb~*IiHazE-qcldAuGHCo!MWdF5?ayQNLqNnFjK}kd;+t zkuVTz5Q(#CDV}FgP*gZ$U89-gZ6&^%^~~UOAj`)h#v&4-@NK>UUmA<;^5YjX-Yi(p z74q(z0Ut;|KO^IR78YhEmJbHvAie^NfB~NY4;xoPn+IbmFvS@#Ax8%=y#b?xks)QJ zqSVf~j+wj%cm4c#ILfA6yeE!v5-Pap_X55mTt{;#txx3A++WN{|?yOkhn!U$WxE>xk zk@-=sWYfdjulf`s96zL`20zc^w|?}A$j3s@x$cNM)~{)Fe9-bP7n;rcnM zd!HQt6&oFps(!DobZOLm$E$Jc7xRY}h--;|=Th&ol<(tQ@~^bsC%f_kI=F#?@mywa1mBGN-klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6gCh9DPR`na?j6CQ7A4=a&|P36X!KF zFfar{3u6NVgD7!cV*^7YV;I*UfkaCT4D=wDsJmpQrKJ|7=9MS}Wb_v z1&}*U44N2~kbTC;%D~*j$j<;2=VEGNWMtU5UEj3-&i&kzbxD`w+%~5!QE}&Zo2$NA z@`A^a-6wuM%#_}@=Z@_k_sRyN^Xz#soBQ0}9#viS^}zg@KJ%nbH}|gk^2n<4!@o-( zHG<4DS=K#NZJz$I^yQ{sh2NJZKd9S!w(~6)kHHo0Jr^gnmCdVtwbnbw*YQE)#~Dvn zJ+qy5M0Mu!t2K{5YF%>p;_-Zu^OWx|=g*UzYHc{}>&#bHqREPF4)By~%yUe%jfdcX5qI z4*OsHPw9E6YI^7U!)+T&ye_J{?tW?#=U(|IvHVE4O-OS6?deR+j0}v6vkfv0=HCBI(m&=$ z8{EBfy3BwNq@SOW@jnX-GZV`P191>vfknW8&wz)GE1}JUF%_89449Ck1DMc&(ZR@& z*ZCo5Rb$1D$6BsfDvVRCfBfxq_s8yTPPl??1Qe6al{hf3eRM^Rl2 zD>vNk)xNe{wDJry>-`(QAD-9Ak{8T=z`U-xucS}8&*|MGr_15*zE;FMWGWZQU^c0| zvuUA++WCWBR;u5dpWAla^!>LnuxG~-R(p=4>xy4%9Iq2j@%QSj5Lmt`y0`J-n$TW< zg%=_sT&vpWwA_6gk@zpCrSOZUjjP?VHdl?EvR(GiYi`GGuyC}0c{)=>TUD~AXZwzu zy{9KlZQv^u4v3QEX;aDIIH|wlZIJ}y`xq^|3F+0DEj-w*UYD literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/DifferentPoliciesTest5EE.crt b/SecurityTests/nist-certs/DifferentPoliciesTest5EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..b6d31236e2c5ebcb34005b52422d00e7c7997f32 GIT binary patch literal 917 zcmXqLVxDNw#8kO}nTe5!iILHOmyJ`a&7+&C~;n614AQY7}p?yM9T~e^dOe0yJV)Nr52^;l_GITXFD{JGE4-B#&e7rq`@ji7mXAe@MP$a5)0?cs)_!z564h;_ zZMao8i0`KXA4oqxBjbM-7G@@v4+i2Oz5_4}8ZC_1F+?`SuQE}S9|HGMiu`V)qq)(@JvkS$nd7bs?k!6s-NaNcFYo|#R z?d11s`MqXCs2`)=+tfY#l{e1OnR)fmCh?3Z$(b`J%39Qme>>3^^t*5dS6o<)&WQyr z8_$_0x2*2E^KFyDp1}=JZ?HJnu=GzbYWJ24#R@`}3;PzG^_{gNc#Yvgz zkDh;ep857TU%kj`@lOxJ-2G2f{ClB&?yX#PWX2tqmT!RuOw%t4O5`LmG|FAHe^Dkj z<@e>kzg9{=oKut_pqI7P=HC*xbG}QND&AjWf4*zOY8Q>uhvdz7#K($%U-4D3#Qgp* N^{~qp&m1p!0sy_vX!-yE literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/DifferentPoliciesTest7EE.crt b/SecurityTests/nist-certs/DifferentPoliciesTest7EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..4c9c82bbcdae6263292a16a09aef51954e971e21 GIT binary patch literal 943 zcmXqLVqR^~#58#UGZP~d6CB(+$<$iUFhP{lwAq<~piIv_tMGdU9|9$;u>tWaE< z1Vqk`Ku&<6ft)z6p@D%R5Ly@;7#Ku}^BNlfRl&Fh2_)KTV4w%FRox{sEiJVuHLpYg zZojK5vO5((4mUSwVpKx*DkCcca}y&!15licsfm%1Ve8KoEn4MY4c;6{xW%F@*K+TD zUA?hnadys3iG~F#-H&g^-P*}`OtR#`h6vNOX`O*ZJ`!0=Z`)cQowhq-*E>Z6yKAnd ztn;nU_DOYqbo-nAK%!=Rk`vQYq;-atlHPhYI-l-?#|KL$y z8C}umZ0@H~e@pquvUjT&73(ZIePoMT>)LScG59Jdw6@+y3mt${TMl8rQQv{1_{watNFvWcgUcSVU(2s5B6| zrm*z)>8nlI!P6|xp6a^rc4gvgP2SIeDi1vk12n8{#MVjdsK1$#($SLX)3I#o`59Io zH(lh`y??gn)tP;-?|%Onr={DqZOulLg3cz}o8P8K*m{3oy1csZ5{GVRd9T>#gfBay zxHmWnvwf}v}{jDQhn#CHLBow*QE5kL`XQ|URc1= eR8{j0)2A>ctx~br^5N~`t2YaoD!em~s{#Oo%V=}} literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/DifferentPoliciesTest8EE.crt b/SecurityTests/nist-certs/DifferentPoliciesTest8EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..6c01f377f46c86824d67ef2e6c5565499bcf6255 GIT binary patch literal 941 zcmXqLVqR&`#58dMGZP~d6CB(+$<$iUFhP{}|6q<~piG9W)EGdU9|9$;vsP+Xb> zM9z)@h5<$fa^k#(1_p*eXklz%U=StFYiwX>WDMgPB#>yQfq@>xPIZ^ew6xTs)VvY} zxb3d4$gWfXIoraZiBSpJql~N!%uS5^3_x)%rY1&4hJ!N?uuO{JPmImid9q#R<~4y< zi(@*zHM2UHS!?DkeeEoF>*AYbu}`eKY?>w{U$)4f{#5blnV>IaneslE*;caK{F=skt%Q`nH;*k+Q=6x7W$BF7T=N>{ z?mF~-kJ`*uF^S(_j^T@r;_cTFaXTb519%jR6lW3b!0d46-Q z{L9Nr7k+%Z>>JCPRhmtkjyZbI+HaA#;ji4Xy?@V~R!J=J{l8ApM{b_rr>VQe+yWo1 z6)+K7c&pJ!^~(FYWtVdjkFafRYI&5^vsFs5ys)QXRp;?dT&E28?o@4OVrFDuTwG&N zWgrg>Sy^Qk2?MbPk>g9vmtXj$^0emu?N70px8I%mHuD`gJ;?I0h_Q%>FU(&ho)g^2 zDW#eImub(x81RGi3o|nQXJIv922uv%AOQsy0Ruh*9yYFoHV?*BVA3;SGT;MA z@Pkyc00q7w#}6(e?+Ewk%=~_ci*`c5%YY8m6-`oHfsC zb~Hy;?fP?U=DsC&-nG6u>uYh!bElX4G`3nP_A1kfyRQ9;;8kWn=Xt;E_2-<5qV*Fj z-yZL_{glmZ?iO>ytL>8Z>b0NioLD*Zc}_8i6{}1)FMNCS;JddhpC6ok9n$b?YpBAH fUz2}z$L+}awQYIl(m6bj#Ztb8&6Zu7{YV!8vnXZL literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/DifferentPoliciesTest9EE.crt b/SecurityTests/nist-certs/DifferentPoliciesTest9EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..b2e30bd69217cc0f76f7c27140960f113b33ab44 GIT binary patch literal 931 zcmXqLVxDi%#MHiknTe5!iILHOmyJ`a&7tu`>wgIKNZl9`s4T9les zf^dYZE3#u1K(4nmXkt`C_AetV19KB2KLb#li>Zl`kzwEWHI)~=oBr!hd#iIq<>hqN z+IO|mW;M0T`jcAf93z@6%w9NNRowY{jor#ucKVVbJX*g!VxJ!3@z~ejpRt_ReoIG3 zpziONLZ>8c_)LGUSRC2&wb?Y`F#j@7R-*&cudz*akC;>xYasr3)`1BZgnzx#D!W{K zX)ep5T|#$V?!P%%a{fueZo?M`W;7k;R+23jNczqrJIB~Z<7UMw8JWbZHVq1l&l3e@ z=3f(;AMcSV8ui-dYDCAAuxWXLP4^2Gg7TGDg#KuY{?yFy!}))7Z>VSGhwHILRXer4 z*Y-XZ~=4E`d43Kx|04EDsJ{B<+k;iP|<)1@@_VJnO z%7o20cz)&5;1>pbApQJ|jQ?3!n3-5U7>I-T3M>K!dylfYHIo zV14vh@$-GnBKduZ9beZyJE2)VOX|{B?;Ae~Db=12A5Ank+286G zla-Uv5^TrI_w#yu73;yD*#aLWa~|GG4z|0f`&m*n`t`f7jRpdj(oFc1)LU4)KWn?a zaFn`S!LDfUx8LJstxEaPot^s=UafCxzpT1&tCymPj=Ix5uZ6)&E7$fGESUVhDZ%eF zFVoH&Kjd@n>V=D~h&7mg<<1X5rqxPuKlsF=BX6(Kob>%z`X{` z!`^jAc1-tOnHo3G_5ZAsa<7$D + + + + AllCertificatesanyPolicyTest11EE.crt + + valid + + reason + All Certificates AnyPolicy Test11 should validate successfully + + DifferentPoliciesTest12EE.crt + Check PDF + DifferentPoliciesTest4EE.crt + Check PDF + DifferentPoliciesTest5EE.crt + Check PDF + Validpre2000UTCnotBeforeDateTest3EE.crt + Can't parse 1950 UTCTime + DifferentPoliciesTest7EE.crt + Check PDF + DifferentPoliciesTest8EE.crt + Check PDF + DifferentPoliciesTest9EE.crt + Check PDF + InvalidBasicSelfIssuedNewWithOldTest5EE.crt + Check PDF + InvalidBasicSelfIssuedOldWithNewTest2EE.crt + Check PDF + InvalidLongSerialNumberTest18EE.crt + Check PDF + InvalidMappingFromanyPolicyTest7EE.crt + Check PDF + InvalidNegativeSerialNumberTest15EE.crt + Check PDF + InvalidPolicyMappingTest2EE.crt + Check PDF + InvalidcRLIssuerTest27EE.crt + Check PDF + InvalidcRLIssuerTest31EE.crt + Check PDF + InvalidcRLIssuerTest32EE.crt + Check PDF + InvalidcRLIssuerTest34EE.crt + Check PDF + InvalidcRLIssuerTest35EE.crt + Check PDF + InvalidinhibitAnyPolicyTest1EE.crt + Check PDF + InvalidinhibitAnyPolicyTest6EE.crt + Check PDF + InvalidinhibitPolicyMappingTest1EE.crt + Check PDF + InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt + Check PDF + InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt + Check PDF + InvalidonlyContainsAttributeCertsTest14EE.crt + Check PDF + InvalidonlyContainsCACertsTest12EE.crt + Check PDF + InvalidonlyContainsUserCertsTest11EE.crt + Check PDF + InvalidonlySomeReasonsTest15EE.crt + Check PDF + InvalidonlySomeReasonsTest16EE.crt + Check PDF + InvalidonlySomeReasonsTest17EE.crt + Check PDF + InvalidonlySomeReasonsTest20EE.crt + Check PDF + InvalidonlySomeReasonsTest21EE.crt + Check PDF + ValidDNSnameConstraintsTest30EE.crt + Check PDF + ValidDNSnameConstraintsTest32EE.crt + Check PDF + ValidDNandRFC822nameConstraintsTest27EE.crt + Check PDF + ValidDNnameConstraintsTest11EE.crt + Check PDF + ValidDNnameConstraintsTest14EE.crt + Check PDF + ValidDNnameConstraintsTest18EE.crt + Check PDF + ValidDNnameConstraintsTest19EE.crt + Check PDF + ValidDNnameConstraintsTest1EE.crt + Check PDF + ValidDNnameConstraintsTest4EE.crt + Check PDF + ValidDNnameConstraintsTest5EE.crt + Check PDF + ValidDNnameConstraintsTest6EE.crt + Check PDF + ValidDSAParameterInheritanceTest5EE.crt + Check PDF + ValidDSASignaturesTest4EE.crt + Check PDF + ValidPolicyMappingTest11EE.crt + Check PDF + ValidPolicyMappingTest12EE.crt + Check PDF + ValidPolicyMappingTest1EE.crt + Check PDF + ValidPolicyMappingTest3EE.crt + Check PDF + ValidPolicyMappingTest5EE.crt + Check PDF + ValidPolicyMappingTest6EE.crt + Check PDF + ValidRFC822nameConstraintsTest21EE.crt + Check PDF + ValidRFC822nameConstraintsTest23EE.crt + Check PDF + ValidRFC822nameConstraintsTest25EE.crt + Check PDF + ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt + Check PDF + ValidSelfIssuedinhibitAnyPolicyTest7EE.crt + Check PDF + ValidSelfIssuedinhibitAnyPolicyTest9EE.crt + Check PDF + ValidSelfIssuedinhibitPolicyMappingTest7EE.crt + Check PDF + ValidSelfIssuedpathLenConstraintTest15EE.crt + Check PDF + ValidSelfIssuedpathLenConstraintTest17EE.crt + Check PDF + ValidURInameConstraintsTest34EE.crt + Check PDF + ValidURInameConstraintsTest36EE.crt + Check PDF + ValidUTF8StringCaseInsensitiveMatchTest11EE.crt + Check PDF + ValidinhibitPolicyMappingTest2EE.crt + Check PDF + ValidinhibitPolicyMappingTest4EE.crt + Check PDF + + diff --git a/SecurityTests/nist-certs/GeneralizedTimeCRLnextUpdateCACert.crt b/SecurityTests/nist-certs/GeneralizedTimeCRLnextUpdateCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..f4acda66ec5cd99fcc67fd55d34554295ec21c21 GIT binary patch literal 920 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 Kzq1v%ivj?k>`=7; literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/GoodsubCAPanyPolicyMapping1to2CACert.crt b/SecurityTests/nist-certs/GoodsubCAPanyPolicyMapping1to2CACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..9f4d95f39533c50f3df78b40c031dc7c1f53809c GIT binary patch literal 968 zcmXqLVm@Nf#I$AsGZP~d6Qh^`FB_*;n@8JsUPeZ4Rt5tHLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP{4o>q<~qN-90})MZww8Ku(<3(7?bD z2rY~a3=E>gd5sMWjf`PjgJ=?M&^FM7*q{Wqp|~{3*-;@NF|RTpKPNM}Qo%Q|pdd3Z zUBR#<-^ieeQ3=^cjI0dIO^o~uKyfanCPqev6Geu49%qBMh~Ht;p6GP!px36$)!jwk zt_YNH%)9Tn{PTm@(0^P@fAiL$FP>SHF*9%RGoD`FUFOHHSGGjlH ziYE(XH$FKDj(AyqM#ldvEWpIXX21_JPZ-2!HDCr(20S1E6%en1k-SS+lcrR7loX0ig!bj`n|8~9Rv-R6l^|ElC(ps6{_Sd(?tCghKPq&@GIjhaI zRy%)kY|qhBgG;%BD;8DWx2@>U(UFnf_f|%P^wBGjnNm*O>Oh$vHvrY*iw07+mpB-F6Z{SEE4x>i?27Ew1`n= z#iQ3EN8c2?JMC}!ym)h|uVU@DL-q9v+lxK~cK$JVG*_v*G{Cd#K)%>DulaZTPh?~y z)(E?ppXtq*=)3+wa=+VCFYi^`?v?ioK91W~Yw|Tsc!9M7li|nJ|95W)DL(j{VIu&I Cj9|I| literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt b/SecurityTests/nist-certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..6cc192b8ba2195fc21f44401cd123ce34743fbf9 GIT binary patch literal 947 zcmXqLVqS01#58>YGZP~d6C;ZOFB_*;n@8JsUPeZ4RtAGmLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP}M*gq<~pi#woElGg%=xH78Biv$(i4 zHATTcCq=>+qnOByW zlbND`X}w=+xk7kmNe0**uCBImA{PLZTqLK`f+CQyG5xy0r}az z3+!z3Emv-6Y%j7lis+lUP+n=<<24f3_s{X$zxlMnlqrl2^SMr+-j+MJ?=s)fFN-V! zR&gHwazK>hUC>0PkNFEP))m~gYCmd}zs2l}g;4Yr<5vyhibaPeY@Ds&8)dgfIeXjZ zc}9Na+hms1J=_oZH(*gH0=1AwynBKO;j;m?S8K#h@FJ{@|PV3g5WquypnPQ4~U+qkIf8&k;A4oqxBjbM-7G@@v4+i2Oz5`*kEh{e6Hn|$zWRF=pVq8A zap}bFDP8tmJoAJy4Ec1VvpzCiU|f7vS?d2Liw$g+Q&jCwel7WKKHop-DP#5m&I>bR zCmpD~H7#qKLQmqR-=@BY4(l_C-rc-t;;bFPr;e7z?01q+z8lWDFDaHy_}`^nVlg(| zioYh5uutADZLE3WlJDx+TaPwL$zQ7cJM#ta?Ke6WzI^*8Exz06*4k9RL6T literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt b/SecurityTests/nist-certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..18033bc34b08de2db08663c7a201b74f547db21c GIT binary patch literal 947 zcmXqLVqS01#58>YGZP~d6C<+$FB_*;n@8JsUPeZ4RtAGmLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP}M*gq<~pi#woElGg%=xH78Biv$(i4 zHATTMwOqkFwNk;^(Lhd|*U-Sg5C|=d4GavT#CeSk42_IoT!Ru4t#vVQf>>+qnOByW zlbND`X}y0=ib8m1Ne0**uCB4Fs+(Csx0ZX^)0(HBe}vsXn83NzxF(YQ+I4$d_6Jd)C-49NQ}oSKDOh zl1j}#{xgorJjS-{=z{YTW|-|xogY`fVD9O?u@BSdzWHr`qPrOIm4>q-+hUAcL~I>o)A-81)-Q?_Dc`!Ur6>>Z0^D&7c7N?UDxd+xeas=TfC zca_DFOw5c7jEl1kG7aQ`p)IS-B4HrbAW~LyBZb9;)Bk>EP1nK6M3#?5 zj7212&fT(O3+nB^Z#I&h6ekki{Aqou0Ut;|KO^IR78YhEmJbHvAie^NfB~NY4;xoP zn+IbmFhLqHB1Z=>IRc}Dk->)Hmw83=>{AQn_i%@b&)F}>QMSms?Wo-GaknP!#Mh!E$ctT@ z&&pmXPc}E;zIFXSPdU%p3X@AbHivEYGu>L(*qihyY+myD7J2iU?f17Z|Y3AgvOPg1jO#iDi!Rn2phrY`3uRNlmh0FI`=Qi56 zX2GwtXTJi%=lC<<3xDTOmb6*E_=vLFsC%f_kI=F#?@mywa1mBGNxklTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6f+P3DPR`nbxKT82+mB;OHEO5b~KO^ z=QT7iFa$yiV*>+&C~;n614AQY7}p?}M0=DC6e0FVdFGWR=465_0b7??Qd*R%0CJs? zK@+1AvVRy^8JL?G`5A!XTue=jj104K7cZ^^^6|i8s8->G-FaaV2e! zPnGX7v27l^dfB7SM8#hI`XzYNTXu;h?rCig&t&XAGnwn3(WJTNe2m02VV z#2Q4Z?+RFZJvedKrPZ&)CaU}FOr^=|!OS2o>WM%gk3f&X_T& zkJW$=q@SOW@jnX-GZV`P191>vfknW8&wz)GE1}JUF%_7=4A7GoFgh3+Ce6t(J6sZ`{uur^&id5V z{K3Qrf-W+9O@-sEzQxT=dX^>n`q&mOs~HU9k+&wilwn;VZhdv_>EDa*-uV6Dw)?x- zu-U!0<1JQi=PYX9{P)}~ulZukTdJfu_Dz|nRGgAB=}KU##luU@JeSIopPrA%-q2R# IT;AXY00T&1bN~PV literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidCAnotAfterDateTest5EE.crt b/SecurityTests/nist-certs/InvalidCAnotAfterDateTest5EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..a9938aa80e9552c031ea4591a53172ea7abbaac8 GIT binary patch literal 925 zcmXqLVxDQx#MHQenTe5!iILHOmyJ`a&7PiL8@{^fGalN_T64%IiAFGLnhUwHlZdWroTL=+6ZPU`$O%iP?$ z+iSgx`-_|FJT6q7RNNeLO*DY}>0I|^0)gvZuU&GW{8~k!{bDBju%PQa(a~&yemBfc zG<&VA-QX%XS>Z!jY1&S{=q~~L4%ch>*K&(4WUPvv|2uxow3D3^H!1zKn38yTqv6H? z0THH~|5tm&ZC%-{BIYtl{S+7Pp-drPbK9o$wd?2Jefn1HkMlvV{W_dGXDl(YGEB-j zIs4)Dl@7&a@vqL5+7#tx&d=Sx{+fE6O~%%e+OI-Q)yLOfNbYB1W@KPooNbV4AP)>* zS!EUp1F;4X9lpQc-`RX#lJ@2~>->(*kIt94-2f*DSw0pq7Lj6qE8lIxT8l2vxaBD9 zwRB0usR@e>_(1yk85#exurM>Rd@v9P@fBDE4EPLq*tinfJQ!1fNzVX1;Q^zAk-_X3 zcjio;NpkB0!c5Nh&b(7K_3ay#=XI%nr)!S*MGs3s-gQS7`ae@wBCR2h0D(^%F(4 MRXewGke6TLl$w@bl&atY zRHESQXdoxfYiM9#2!s~K1_lOE;=INNhDOFPu0cA9_L&=)LhRG?%qvUG$xH!Sf^My= zE3!isKrS~lXkt`C_A4VR19KB2KLb#li>Zl`kztR(ZO226l3WL#ewexJXpn;N=8fBv z3$^UL)>f-_wXQg`sJK_COFOu%r?B3oQ0+{Z#-iZmCWky58eJ3B8!BciCTYEt%1=|C z6ZtLfTk5xsTlg+9pWGHCX#FvVQ~j0H=Y(b@trZrEYPZ+4ga_MLal4AWe{grte%q7k zhNY*=3wEDv{xs+Pkz<8d>Xh&MozhNFIbyf!|MCrQPGnqmXZOvCkL~z8d(k|`+gEO8 zm6bO(Pi1-X{L5XHYdza4HkRJZ4|}2`@gu_MK%ZdBF#(xN+heZBJy_ki&?h1G0$YI0 z=|8_W-`HjzdVd>}anL`>^6q_;G}dr^jk+D=`gFgeXw-L;ixW;VF*7nSF3vW{G>``d zu&gqRgn?LtNV44?sd>K_eu`YE?>+V3vwLAX+8n@1LY9w3j74PSj~&%v`Gs?T{#U$t z-d5E^_4~4313r*`en!UsEG*1SEFTQSL3{-k0Ruh*9yYFoHV?*BVB#}CPkO-UU}W&J zn3g;vt72p3LFaj<0jqh=2=9nLKSN^ifln7#a(_$K`M6(t&xh5QL^75y$zL?{E^oEw z(?7|~6VJX~?seFh$&vZjCa>%R3CH*MiHMqB+?VBhHRb}lt&PINw)IYu>)-VMS>MDc zuCr=;eL~%%hqD}P@ItEnQI>S@0@#F@xAW$54L?z?|RXnFtu literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidDNSnameConstraintsTest31EE.crt b/SecurityTests/nist-certs/InvalidDNSnameConstraintsTest31EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..5f7ad1535aa50a917f722f52058d22c7e60d76c0 GIT binary patch literal 981 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 FIRNT~dXoSE literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidDNnameConstraintsTest12EE.crt b/SecurityTests/nist-certs/InvalidDNnameConstraintsTest12EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..5f3a49f93e402b60be1e8060b555f961df1fa7a4 GIT binary patch literal 991 zcmXqLV!mzA#B_K8GZP~d6CB(+$<$iUFhP|838q<~vkupqT4H?yQ9H6^$-siY`1 z)zDDcKoKOzEG(6mn49XHpI2N`l$e=UQmo+OXQ)tIn&j+gXdoxfYiM9#2!s~K1_lOE z;=INNhDOFPu0dlf6VoqiX&?O4!j&pTI_NM~Kh&j1wXVrpV!WZ1aOJn37&CB8cbo_o0T4jM0?{Nlzry`Gc51ApHrxyW`pOPVo$ zA(z2Do3-EmxnxJpS$E*}*#&FElRSBRD*Lj_|9@85G3o5mqQK6x4e3TZ&q#(o`DJ*{ zNY+oG>=X0JFB60;-mT@1GZV9kPq+N~r@i9nLHUR2GNPZ795?#}zE9cF#8~6%T^p{^ z_>u8ylx5`3B7<*NqPgqx&qTaubiHv!({w*m^YYm~S^cLkPqJKf%XEs}j4gbj0hi5| ze_&iFahFTWa?Ad6O?DZE_LV!9z4hzan{zWbICA3F8P_V9FTe6mtxx^bRbgfnn%>g4 z(EDLoov-V4mX+aJp?7x&st(p77WZoy)*f)1F{7?Qkw*KiNDXx_-yG-r2*H=yWm}7mHW%+C0 zSR>v^_9xUNx6Yd;d*1W-mxqZqW$`MfN@rV1?cg)|G5zNZ&G54o?`phW7|q;2J(cQ*3yBhA9MdZKF(0#PRwt>y1aSOAz(u((4 vvkTm+1&%sCDhzRW&Tq8TBx_xJj5v?}<~a>%0kb_;@yt53G)8sRv1wBP^XhH3 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidDNnameConstraintsTest13EE.crt b/SecurityTests/nist-certs/InvalidDNnameConstraintsTest13EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..d64ddf53c7a101cd47bb9b2212613f8881004dfe GIT binary patch literal 991 zcmXqLV!mzA#B_K8GZP~d6CB(+$<$iUFhP|838q<~vkupqT4H?yQ9H6^$-siY`1 z)zDDcKoKOzEG(6mn49XHpI2N`l$e=UQmo+OXQ)tIn&j+gWFRNbYiM9#2!s~K1_lOE z;=INNhDOFPu0dlf6VoqiX&?O4!j&pTI_NM~Kh&j1wXVrpV!WY}SUUhG?ilg93y-JBC7%1=kx1Ss*fMZWm!6!rCMaG&hM0~(3@ zJ12(cZ$0^WQT`q;^L=|C6gQoUe|Nnsd&9=vYw~}K9#KzAlzm*kwQ0t3@i1G5Yx*xb z6aQ%*KaswpV@rP3W2bZFQ{*Sb@ZD6+d)CtGmLDRn_(im(!v5s)--)-@YV>X_o_3kz z?!|4{dB*w;ZaEhZme})8+MVboITw#XUQabFsLj$xnfUx_6nF85tNCXB%W1$OD5|R+&Y@K&(Mzk$yyTw9nM( z+uwa_-!h%=LH&d2qTnPY%f}+dB647Q$q8AbW%_Ljv(`0KJX?3yNk-m)52T-;k?}tZ z3o{eT2Lo{sUx7uyfX{%3jVqzegE1ADcn#2#E-*S68PxtiJm#Wn@g$~w+5Mzv2L<2e ztd%4{y``cYvr0aQE)Q&W6S!jEt(cE20 zB9{Mc!Bexu$BHkkUDTdlZ9TVU#$Q+F@B`lx7u@(_=rY;srP}d}J{neazxLVvXk+Ye ve)V8S!tw1h1B!o?aVRl2U3oljd%M%ZY6T^o{g-MsJ_`xCvSpfuDw8(=p(J%F literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidDNnameConstraintsTest15EE.crt b/SecurityTests/nist-certs/InvalidDNnameConstraintsTest15EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..fd864ced34c1763f00e5ec21c5cdda4dad0293a6 GIT binary patch literal 962 zcmXqLV%}%a#I$SyGZP~d6CB(+$<$iUFhP}x8cq<~piDlaiN)j2<}xTGjCGq0pr z!Nt#5p|~{3+0oEIPMp`!z`zg)EsPBe45Gw&jSUQqjA2}Z#ugH7l{63s*~%>}kXn(P zQ<{>R5?q>8Qk0r%XlQ9*4snoyXI@!iPG$f=Hx!sHD}oDX59MR6t;TCp*`o0Y`i%wwIXm|!|RpaQOlpL z*p~iq*}2^c7mn_0`f+d(*SRg%Z*eZRo+}70EfJ zDXA&JrAZ}4si{VWmIme!2N`(gl_ln6rT`tHfbKR|S7fg!fc$1?X3)f_gd7}KTh=T9wYWSxDFB`$JDLG?9 zeen#t+J<{s@1AzuwAvBeXus6uO=O5rvB($aw3Y(Dncel<3HYR-q_6E~Wi%E5ka|FZk|{)t%3KOW{$c zGsnC5^toOpT`ERdb+7hSo_u}%XiiAx+r=qDM^AqE-Ku-mC*fd=qRV>Sxw&G||BjxU z@@0d@{f$3)m?A_nUY9bgl~TIj&&15gz_>WuAk#n|7{s#5ED{D{4I&MDj_ZBzldAt{ zQT@gA_1%{d$7}+?sYaHMMT|uxVf&YtSL-evDAM`*Wq(h?r#1bm#|-#D`uQ0d|Ff_# zGqHRC$EK_Ti+};20S_BjLYoI;DlmN-Fd|0>Fm(c>gOS1S#?nI$Yg0D*=zsQ{QGYva zxB350OP)0hlj;tvURPQwXa4_Qw>k&su9RT?g(2~tTjvX&*0q*a6rcT}r}?Y2ZLN#Y zCl&e1PYivl563<{oc!s4&c)0P*AK2(nJa3;+@9zsdxG)wgazvA)*TWdl9o5;PMbda zYi~8vIY#Agta_<;xGS?dZ(I`Cx4C2Q>WMsmOD&J;yuRu5-r}Tg29xuh?Kd6v%!yPn zKj;7ExCQfF_JZV-JI^}L`7n8(n5F8~d$aGqnP(cablrL1-D^%xd)@B(rK_NLEq9e-UtIi3Ur?8ae>9bBexMzB?ugjF|wz)r)T9B(+$<$iUFhP}x8cq<~piDlaiN)j2<}xTGjCGq0pr z!Nt#5p|~{3+0n>APMp`!z`zg)EsPBe45Gw&jSUQqjA2}Z#ugH7l{63s*~%>}kXn(P zQ<{>R5?q>8Qk0r%XlQ9*4snoyXI@!iPG$%JwKB@)>U3ZhwK-iG{XfwN^i_Ani` ze1Eu4>#Zx9`Mh3>k*#?;g^1vXLRc4Ve5Ni-Q!}2yuL$>Z- z$}5Hrtv98D`UgW zF37|ybTccEYZiz9hG}Qc2vD%f_kI=F#?@mywa1mBGN@klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7lRDPR^B%S+5nb|A$y9Em4Ug5k)Oe!iIIz`iII`v zickK^{x;?>DaU62)jH2raBFRu=k?h$=34QGulpodex~T#Pa~!CN~s$X7Cf?5>0Q>k z>_m~|hc8U`eir6x?AsCGI_c(>;~%^h>Tzl)esE+z$(|-0)#(%e%HzGY{C@eCYn3)S z-_$k~T~~@uESQ!2L%Qwe6ydLzuDLRu^6dZqE-vD=%}?)GHOm2Pm~e(s;1rfKcOw3)0sW(54uzIU?peZOZ0 z<8~t+)<2fVp35>ZGcqtP&Nj$2kOxMstTKy)fmnlxV}+C3S-%xc&mUUe|GrY}0N0=Q zZQ!_<Rx%0p_AN?ZoIBq?CdZwEE>jSY8lZar3-^S&iVQ8G6@Xbsb+V5QfpZi`k%rvJ-N*uwjE&ZesWH-mPROMZIB z-aBE-Qx(1jtul$eO^bhCy6|%c|FtSTi>mj_GK!zRsy;c};;Ssj_2>Kl1idoiFyHvr z<4-h#O=en(e)uWM)G n3VBgqxAMiMdrMEvNtrcGrX?kg@okf`G5>^yQ(L=rkMaTl=n!C5 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidDNnameConstraintsTest2EE.crt b/SecurityTests/nist-certs/InvalidDNnameConstraintsTest2EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..3fd895c9242de0c4314cb2dd88e8b73f762d8f1e GIT binary patch literal 957 zcmXqLV%}-c#I$e$GZP~d5E<~YacZ@Bw0-AgWaMULFz`3zHsEAq4rO5zW(o~9lsAwC zakzxVLQ;!M6r59wN;1 z-}OtcdY;<_NH5%y%C6-nDSG)v&uaTnj#-^1w7wW|ff3fA{GPLZWY{-g$m|(p7`2N;$Jr*YhUt zcbfL8L{GA6)^GoLt@>8XGuxj`*zNhy;`OFaGSAu;d#^N8@v(WlHRhabo`L4vta{eu zqSRLxKTLf0roHS{H4`%<1LNXsgG>W?UMWE5#0Q z{dwO8PB5~3EMhDoe~SMvc@)+7UG4NHC+ly#GFzA5ylTJ)($CMx_@9M^nTh2CI5K4w zSOg6C40zbM652c%Q-Mj-fDt)5fC&>A9gGZNuOdF?#zbYWt8fZ*T(fo7-3@m{KWv>= z_DtAK>e`$q1#NHmpKVHaiqSmXZR>GudEK%%Qh7={Tb7ll6$fuAa4}l-z1{uxeGi-1 z`(LVhg9UQJZ(Vo1YGS!mYsZZfUHe2iqb{xfzN+@xEp^UF@tn)Gx!?15HSV9UBVL|x z^vD*+-#-H;n5$n+>)$J$lM!g+6{+>}mbKxAV;!ZUk5io_S^70odbc_r6Dqm<DY0sx--a2o&s literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidDNnameConstraintsTest3EE.crt b/SecurityTests/nist-certs/InvalidDNnameConstraintsTest3EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..decbf34aaceec2999b83492e201c5c6d755f3d6e GIT binary patch literal 1113 zcmXqLVhJ^9Vzynt%*4pV#K>&G%f_kI=F#?@mywa1mBGN@klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7lRDPR^B%S+5nbO92AVK49rc8{0u;G zE~X|%MuwyOjhq*cI&RLoB2^;cy~*m^4DSq?+cKI7c3+G5l{!Uk1L`ZaiUhs!l|3 z#eur1X40E1UX_b3J)!LEt?Qc1cH-E>S!EUp1F;4X#|kI6vwka@oCA_vaV-fr0OU@5{?wtMW{m0p&FVB!GMnR@qinhQ2$RKSP^)<%%r-+2{OPpzOADtJK9)MY#pTYkl&RbzIk8r4JM#7^Buuui`Or~c8~T>vQlHZH e9Kop{Z+fv?BysaiE6je{Cf5D`N@Yp^`dR?T^q67* literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidDNnameConstraintsTest7EE.crt b/SecurityTests/nist-certs/InvalidDNnameConstraintsTest7EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..6ac76654e5e7e347f48d2584258beb9bf9605205 GIT binary patch literal 957 zcmXqLV%}-c#I$e$GZP~d5E<~YacZ@Bw0-AgWaMULFz`3zHsEAq4rO5zW(o~9lsAwC zakzxVLQ;!M6r59wN;1{jqiTEZAQC*12J1Su1tuk1U5`x4z3O z4MCnq+Izn-E6kZ2k<4)7@HQsXEe1*M=RT&2{}jD@KKdJ%=**P$M|6(w`a8>Ct>51C zg3~n1l$%;ReantYtm~O`s7&?B+tbP?l^m`F9#^jXv%vpfo&IT~;=3&GS1(<3fBh$h zr$tjLrn2Xkw#3YRbVz@hQCs%>>lvNix0_0*Y*^Xv)nfBh=!Q1BOncb{~-McOqF zt&UNdHD}*}MKT38z;@ojw1)<&9QXol=BR`J3m> zCv$TgGfL{7CN#+3;ro&>hm9{4)VG4Zu4&q{u8%c?-t$v``aN|RbOmv-sKbb zUmoAM)PFS#XYKP%4xHy=avE>lE!DBDzPe=Fu9g(3`Fqn@zfKc9A{pDf;N}PC%f;3~ zo`Gq)b1X}o??gwNd}Ey38q4)#XF&SI+rbvUU&^0XFq@M5Suae<3OB>oQmS}@-_cbr33@g*FI7d3TX_j^8Wd+({t_jZU7zfZ!iD= literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidDNnameConstraintsTest8EE.crt b/SecurityTests/nist-certs/InvalidDNnameConstraintsTest8EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..48adc0a6d55c90ce0dd9c1a8f5ce152392a68367 GIT binary patch literal 957 zcmXqLV%}-c#I$e$GZP~d6CB(+$<$iUDLrhr*kEH5!P)j2<}xTGjCGq0pr!Nt!+ z!P(J3PMp`!z`zg)EsPBe45Gw&jSUQqjA2}Z#%2<2lr#_rIf+|XAhjYnr!*xsCAc)H zq$oAj(9pub3?#)YtnZmumY9>70(67|y1QImk-eb+@|T4{6QdGxNHDT8FgG#sGXTZ8 zn3@#VNC|GqipFPC;Ft<+g4{Mt6Yec85H^ZdslN4B12Rp-za^eH~` z^>5>zdeh*LOMx%L&KEA6`@i|5#RlE~TNNq;?`xFY*?G!%^E!uBM(N+nc>z)=;&b*$agQQY`ZwCA2S&X=B$TmCFKLZ;(naR~x$aWOcd4vh z-s<1nCy42<Jh0FpStwVy; zR2VLwDg`GPSw0pq77^LgYtB}dUw-xK`MT}}CrsDd7p2%3@PYL6Gcx{XVPR%s`2dbg zSp^mW13m*DHm-y=55`nr(lkI%n84^@WKi3)S!&YV(xbJ#?QV0eWDc!bP$sxOAwB58 zu2UaAZ;GDs=F*x{w)HIK1^Ykwuosz0uPa*=;QLN$;a0mhR@&1Zx`^lJxBbyoa6Hh? zKg})m|B`F9+r^d@w%nI*e)OmCmbc)RIl;dEP1pSPGH|@xddP|WLqufqqg@>})j!|n z?@50b5V1^K@z>Pcj_mo~T)jswCr=Uj_xkUB<45gg8|pqJ&W#rfZgr`-BmC>kjQ88O z_qz0R*hChrUSuAZG<9Q~f&GMicP+UjHaD8oet)#+HS3m>4BhjtmM;I#CbY)x)UQ2C odWCACMUCMrL$0@qd%0hGRe0ufPrlx4*Kq!aa~LF<{!hsP0JE}hwg3PC literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidDNnameConstraintsTest9EE.crt b/SecurityTests/nist-certs/InvalidDNnameConstraintsTest9EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..ed753d42e6664959fc6db584c1b4db1984164246 GIT binary patch literal 957 zcmXqLV%}-c#I$e$GZP~d5E<~YacZ@Bw0-AgWaMULFz`3zHsEAq4rO5zW(o~9lsAwC zakzxVLQ;!M6r59wN;1+@!Kye$~#2cRn1_e5xia9C&O`X~4S9`Qe8+>denA zc;1|^F!i&Og52p(omutUcuQi8-nmFTN@kF>*}me=zn1r3x`QvI*q9~S$=Q7Sxg zi<4Qt&wlyvU(}!exS79}T6akCUtLyvS7Xl0>9@-xPMMr!YdzbU9V8qf@yI7O?L~av zTiMsCGj9aEbF33S+Rwzy$iTQb+aS|G9vH&1$}AEFVhtiWo@Q(HB07c40v)YGg49$P zE}tp|Cm2~i7BLo)fF*`zY|?$#4_-LC@E~x;{LjL|%*65m9GS8T zECL3620UzB32h#XslcRZz=#|jz=R2m4n~F*v!^VxKefhD)A0;HyRqjvX`^Ec?5+yN z+fSDM6C(6E-h$)pj>R0Un?1!R2L!DA#86yvjCnE1kHXC-WdvDJ1 zOyq&t#_9~oW6z)L;cIbUS?@KsJI!*zn=D7E$KMaeO`W$b@91L-r@8JkY}McH3q5LX z@5sA`MQLNq?%Dijw!WSsu(kEqv?6Tx5@x{&G$;PhL=5fw~h1tN~kQ>Nl4rO5zW(o~9lsAwCakzxV zLQ;!M6r59wN;1 zMlki9`e%MN_IGv)hOchy7pa!trtv@3?djRMOErJ!ALM8#EhunQXE2MlT3GG9X<^vk zRUghdJvDo85>l=?YhCgx&+m5Y9v=Gnt<&iL%#7-v=S*Th)@Y_wo20B|5@nd4%)#q) zYQFdm-Z}=Wr>w?H^r8cq&4vI z!T@xJK;+IP2gQFG{A2v;drvL+`MjvHZ^{A<=lkDTMqnXjxW5+=6F8; z*O`SUH`Tc`K@w@)U(wI*Hb6Hz_FC2eUzxBa`b1^@rEzUN`G>`{IxU4dZgn?Lt zNdJUmJtZ%yc}_$gueFH|iA+%C-Uv>UvV1IJEFx_ge803jvpqk!#_dm98g#c+A;Hx^ z9Hd`?MZkd1fQOAMq0NIa6`0Zu7!CM968wye|5;d=nb-~>rF&*OMgv_Y5&I=i7+%lV uQ`{zUvUK;x+4jM&*1`Yk+iD593AG`dCsw>VSbS*yj71E{fC&Jnb3-}+ literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidEESignatureTest3EE.crt b/SecurityTests/nist-certs/InvalidEESignatureTest3EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..9238109b646e7d9fae59ea170a079560c45d80b7 GIT binary patch literal 893 zcmXqLVy-l3VoF@V%*4n9L*3>*x(4LI4DLs{5_nL>jNs{QMLJXGa4$ab80M14AIR zFg7qSh!W>DHZU|YhH(voNwh)PKoMetlxJR9Voqj?f~%`SaAta5Vo7OHsshMe#s*D{ zO2|H8WMyD(V&rE4igPhFF)}jjRn%rQXSFoi7-6|1?`ik$?D<9tcW(V`x^K1h>NS?r zSB~A1PHTCzwk!SU(;4MEZ%zIXv$3~+bMmo^kJ`0&mHhP=KB&>Bwc}QDv$SBr-+85T zH@wbu+?-ca{kSOL-#R<3BM~nHemI-FQ=Fn-ef)vBt&h~&zAH7~p2;e2JS2KILx0{u zK7V_smA&nuO6h?eru$z;v@SfhLP+oWtDdO$T>ENkIes`vh+n_|j72QY@b~MyLy~$v z`Ca}7UF&vS&?{Ilr7bTm=T_Z=#$^|m>@n>>yX>69`n1RIE@jPqF@;b6?3N?0R}6R7 zM`W8C%LIx#PkzY8=lM$KJ!{Rw|NiOyZQEEE7c((4GB7UAHpn!P2L`6BGK++PSc6Ce zV~dLP9_^qhUbagGibMjxuD3b~j&NB%7BLo)gU#nBIoi$t5cK2Wo4nw2DZ3x-aRNuT zEI%XTe-;*ICYBEd;vn-BSb*ukfQOAMq0NIa6_~UP7?Gm`n6QA+!N|b8`9tc#gKITD z*|h$BcCZD=(`5yq~8TB5nM3*~BkAxBkqMt~fd2lj_V1wJ+Q^Xov4U zopVN;=a+-QIeGuika^mnTemATsoBauI@a{?TlwMJTfDz<&Stq+@qMD|KHpvDh2iCF zDLyBqAFPuxpTD`Q3Gai`pli>|fHqTb9djpWlP;vuvhjPYHbV G)*1jikY9=b literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidEEnotAfterDateTest6EE.crt b/SecurityTests/nist-certs/InvalidEEnotAfterDateTest6EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..af6fdf8c5a91ced4ca4bddab927d445c35997464 GIT binary patch literal 912 zcmXqLV(u|$Vk%j{%*4pV#K>mA%f_kI=F#?@mywa1mBGNlklTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6foceDPR_6chApHQE+xNkQ3)MG%zp( zLJMO91A{0a7sP>a4bn)o!OXw}VuP+{URh#JW{QHVt3qCWiDOzxYLS8q&?z7RB$p|G zoN8v!#HfVqIYw3n<|amd2B0_>QxhX2!_^6`hYGDaxV@|vMJfN<{pUcK=!mAP&lEd7?ZENPn`WIadtGT(^03)+-}WVooF-Q;QP%zD&mU8<+T`pjb(2~Y z&b=3YxAg6bXHz<>rw1>pX}YoTG=sRUERWj}?bELW#LvHfZg`@B@0&J9W%m3tZ$p)) zE3df4I!F4#nmZd4-}c0WMsB`&V`=7XMb${B!oaJ4*Lt2y3=pnZ>Lu3^>JY~8nnCWb zqwqY3x#xqzR-IojUBc7PSARIPblQ#hpNi3HD&K8GYeICgZkL@s-NR};acYH8#O6wm z*}G0G_P_h)_vzM9CdbS*4vUTSS+*Zz$hLeWW_HxU=A1VZGb01z;%tLV19@Qh$||!+ z7>G59L@>6fNbk`On&M@&C@auZ3li)NU%f}+dBBJ`@both++tw?`3-X64?_yiO zcF96;3XtVzWc<&THuU2L+olR*r&~vq{T#AgqZ_Ti=Wq3@XjeFNl&9jxJJorK!2%p!`F6*- zB%Z$AE%5MTME)ken`YeR?;kIm_2%2UC;tkvcqdHwX%-bZbV=BBw6lPIy%SQ zH@W7C-^D`CZ5%qzf>u|OdCne@a(yE_93^e3?PthFyRZg#0DQAy^N z6hHmGlEYu?)wPC0H6G3jv!o>sHvYF*SQ_>@YL4Q6-h28p&t2xax%SNghZ|RP=6O~8 zjbQyT>28fv_x^;x3s(jeGEH_BJrKWI?NY#-?%gM6Cj~e#Haos|k!jbE5nQvLvA83) J{_L&-O90!nRGk0- literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidEEnotBeforeDateTest2EE.crt b/SecurityTests/nist-certs/InvalidEEnotBeforeDateTest2EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..3ddef09cabffac1e6772570205da804a79d05b72 GIT binary patch literal 913 zcmXqLV(v9)Vk%w0%*4pV#K>&G%f_kI=F#?@mywa1mBGNlklTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6foceDPR_6chApHQE+xNkQ3)MF*h&- zN&*!a7(@ZNmPlNKbP{baH!y|Rpy!!amY9>7qTuSPke6TLl$w@bl&atYbPGrX$!Q88 zw;CBVF)AVZj**ptxrvdV0VvMJ)Wpchu=VVgg!zweZRwqoRIh&P)n+lTgWQLI{$0xX zzbJg=ivy=QCBTMAFa1Re|~zsOp)eVy5&|#_lb(LfT3$nvp>v53qpS#Il;qn~FeSTQxGu+($hdC!gYM+v<01mF?OujS9TaVjX{GCw^<1ed_#*>x&L;k-l)o^5)gk z#EtTCkmJYR)CvV&NY-aR%#*6tXgB5epD!le=3KX~rPvru K)_W&kw+aB~7FwtP literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidLongSerialNumberTest18EE.crt b/SecurityTests/nist-certs/InvalidLongSerialNumberTest18EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..56b1ab45831fb547129ed606b10b8b9fd90321f3 GIT binary patch literal 948 zcmXqLV%}iT#57|8GZP~dlSn-y6Eh1d8#@Ol7dHd#AN85K^Mn-N{ z1_M7sZUas>=1>+kVW!YvLwN&P5Qj@xEF`tKM8P?=s3bEjGdZy&wOGN(z|hc8&OipF zfLU17CqFM;Avm=tGciZOuQWF)wMfC)(Lhd|*U-Sg5C|=d4GavT#CeSk42_IoT!Ty! z?Xxs6huCM}nOByWlbND`#a>reWS1&{oNj1g(8Q>O>{~`w2IeM4eg>d87gG}>Bf~M{ z1+G4q8dm8ku4}lr)kP{}yO4g2@x6toK5KXF5sCg-{=w4u*5@B79}-MuPIG$hwu_&A zcXj3DDd`KBY;=v%oZfPjKiP415|`~kxjjd+6#H8mpKqVRTQ%ot?Ty`wOXr<(kl$J; z=ia?#X>|Vy1$7(Kd8fo~{tqY*^pgAd=jUxxIjxDJ%Z@cC$emiNy|B!eg=Klnw*|_t z%N*ZcH}IXw=bjswulZnarQ!=EQ{{-cTirVCD>MV&&hcCqm+^bq$+))Scc0HOb~`nm z4GDF6@$&A@b+1BqewiTdmYnFfnf*l7<+9|avvSF0=Pb&v?|qeQ_H>ulJ>Lr-y1ly} z<|x^%{=7(%iJ6gsadEamrhz;#h-H;oBn-qFM7Wc;yRSRMZX{iw|JZ8BEAIc-QmfF1tE3c3%0iH$_*>E+4i3)qO+yMfDfdfpONuD3kx$7%LfB-5MO~sz<|$y zhm9+t&4V!&m?8}rk)s2c_<+&D$Pl@8_Wx&RyJqKdC6{?E4HHiMe)CVuiAC0{3OX;_ zugqEfI{5hmmDzc#ZNFbr-yt%|@YMR*FO8GeJ7Zo* z+l4(Iug-6%`OD@p^I5}JyR-;Y_K)&GR|DS63ffR4dK@j&sI*?!&E2 zm*#Q0o$&ta{%C){W89MG(Fvjx|ICYCAK7xjX8$|R4bnB0&P%thauo3_e7oQ3O5}!j ltDG$lYroy}enMrY!K#}-f6=(kkeQdR;8v8MtB{yi z8IYfonOv#h>}Vh-&TD93UZl`k>TjqcUg<0#I}Zd{CIxUF;|km z@lng_=>^Y<pc)w}2JvvhPevOjKKbl}XwiT%qs1@Ens<(_oQBYyhxnYyfd zZ3_}uT{|3Bi+t#FPv_nAsr$n+zg@RDlPn?8P*Po!#{d;GR;a{^E(l=f$kF{Cfy+r$# z=#xo?PEPk__W5)-+UCQ&lzr1x;>)E-KiJ6gsadEam zrhz;#lx3A!Bn-qFL^6s+9&nqSFLJmwW!g2-)m2OK^?JZ*Lza(4j77w-yJK=*`MEc{ zpSbI+p1M@$*QL#+27Dm>{EUqMSy-5vSUwntgZK(80tS2rJZxMEZ61uNz*J~}o(6%@ z!N_2J-=#Kzwcd8+n}B60r#pO~w6%$D)msHI5YAYq)kk;f0Lr#9zMQ zW+6MP5|bK?E_J3Da9@eaI#6-uf6xEO)eUK@kFx7zwukW>WwF literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidMappingToanyPolicyTest8EE.crt b/SecurityTests/nist-certs/InvalidMappingToanyPolicyTest8EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..ee6914c15aba209a9ba118c78fda02befd710bbe GIT binary patch literal 926 zcmXqLVxDEt#MHEanTe5!iILHOmyJ`a&7F(Js3QelybUc=GGT>E(UBm1)Rm(#guI=wH4qvv?E~~$i>-2_uN5kC>)H1zB-+w8fl%rAo0YaN;pu}(pL3h()wmv`h^zP^0* zaJp!jNZRq2NAonJ3WPSYi?&t2*Hmx#A6jd|S6WfjsPLsX`%t6Rf@h{r3a@`UX0_ZX{Zu}@yczxCUh zW6gzE^cJWs(0*3ct&@`%{y9Ei;WxMHD>oUgn$GpJfnWuW{3h!On^q+kU zfqMI*0@-&g+Zg%x1kW$VxQonjpAXM&+QB8Wx58qM*>%@0*){jCi*N~TTdn5rq5AOu Ne73B|>(92;0ssddXNdp+ literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidMissingbasicConstraintsTest1EE.crt b/SecurityTests/nist-certs/InvalidMissingbasicConstraintsTest1EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..80ba7a03dd1ad0fa897b651c2238e99929b50693 GIT binary patch literal 940 zcmXqLVqRg;#57?6GZP~d6CB(+$<$iUFhP{lwAq<~pi+BdVfI5RI@At|vqGub&m zuehWrF*C2ESi#xRKu(<3(7?bD2rY~a3=E>gd5sMWjf`PjgFF&#wKK4R*lOyTSC*KQ znWBKxc2`$qS1W+LVQA3AsD$isMpg#qCPsb+pg0#(6C)$Tc^B*6(C2>^f7S04n_sMM z=5$8xpNi?xw(ujHZ_b?>v|en=4%gjQuKSfAnwCqY-&YEiYF_naS$ zOYXU9aMURC*PJKDyMCNrKUcQ#c=5MOrW>6e+wUrxy!-GD5#P2`iP2B^->EXM_ibG! zcfvaJWYq`BYxDP9c&BRAbeb`Jsr7bCjWr7;*Y>WQ+_X|#=;u+MZ5|;~f=0YI3%Mg_ zas0~hUUPre)ma;z8s`Uk>!cn&!*qz_Y3E^?w>$Sfzv=3=JME}Y-K>Q5Nuo^5j0}v6 zvkfv01-nWaLyG|)NIyR#<9`+wW+s*o2I3&T0*inFp8*dWS3;WyV=6Eu8la~` zV017tgq0~2h)S)o5?G|&9JBc>+vQV?qJOUlOk$YQ@#w6P{eh_aes^yl`o-!Rc6OWG zeg-e?Sc@B9&fO8){50jxhyFVamqiwZdDW^tUTZM(N$nZkDEF(=lh5tD@o;nIlD)U2 zSw?)mL_xI8VFN zVaP46kbGj{x6&_L?0*R?PI^&to$KzceawPv%(E3)c#dAod|0HbmLbw>f4U1LW8 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidNameChainingOrderTest2EE.crt b/SecurityTests/nist-certs/InvalidNameChainingOrderTest2EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..6b7d7de29c65e338c3f0b3bca395cfb9bed538e7 GIT binary patch literal 999 zcmXqLVt#DU#B_QAGZP~d6COfOYv7rKA>R=A|n*I~vG|^BNi$7y_Y%v4Md> zlsK=kfuWHxjBAidqN6Ph%pq18c;=NQ=47To9O|5rn3)H%5^T4Et1Gg96+i)CWYEN@ zgdAp!tPIRejQk8haW1ANMn;BZ64fc<9cz8Pwli{mPFb-QBR>lu;v#=}_FUh7Fq{Bfj@lzb~7A zmo4;ytcLuV>6g#=h#ziuDec?YC&I{AF#SYAR(!v=tI`3mT4ottyG1U$eB6DWiJ6gsadEamrhz;#h-H;oBn-qFMD}}i zH_rC$5i#tEetG7u{)SU#_tBTwLz< zRjr(r&-Y(Le9^mmQ8pqMFTXRK{L{L=VX{y4wEM0PSqf&JGLkz`%{YV2;P%d=iRNX~ zXRq&Uy?n+0@~bF+&(!XtNl%$YI9JV>xbRF*-j%afli&RLu<&nwrtzyH z4rWP*{k^Q^`xhk4X*WDlaZ$fDsJX4a=0rt1>xC(fkrGu#>^3*d#Q5jU&^+q@>)}!N zoJVK5mwwskn&W>dp6mV-5$1CXGY?v+Upi;LDztKKWwiAFEB%id>+3rhXUup20H)(| ASpWb4 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidNameChainingTest1EE.crt b/SecurityTests/nist-certs/InvalidNameChainingTest1EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..ee18fa08fbb48d233ddb881f4bff98fe9cc8ae50 GIT binary patch literal 914 zcmXqLV(v3&Vk%p}%*4pV#K>vD%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`nanH|BQE+xt2+GedF_07I zH8e0V1VRgA0|SF7ab9BsLnC7t*C3fhYk;~T)@XU=l_ln6rYQI&=B6q*XC!9kW#*+T zxVj>{O#$RsLxUzpC1me0vNA9?G4eA2#krW87#SJ%FBi;9a7tM3-+bZW_9F-POUx+! zmM5Y-B_&wqz3rp3F`uf_KOJuCnmKcqRZ+x3^&Q(J;;KIWKVBuc#ImDw&P|nD&xN=B z36q*MUqXEU28pis42#Sfi=-4{j&d(>+&ZI~b${HZP3M`blXkD(DSowaL+U!_kPAJl zX8A?dc28YDx6DRt9cS*xb5-&|9Fvxx*d6h&Z^Ft?c@MgeDeGPeIm)+O_h+hHpX{9- zss$ci#q%CFJD2C3cewc^e`{*dZ%zGk-w(2^eA?s{Jv)EFXI+l;1wyAK6%u==+>bW3 zxfjDw$NEP%sjL5j$M4s-n_i#W9>h2=+S>c*yNGFjCcRO;Wt1Fys+)wn3(W zJTP!&m02VV#2Q2*7+X}N_h<)A@v>biP$Uxgb-mR|a4L}HV-aH!kvhOJ$%P;Z+AGtlgWw^aE(9YDd zd}C*#&cSbzvjsE{e-e}bb2U(L-IO_7PW|1Pd0*Y6j!ipNG2yJ=@A?%xugL@z^k}Z> ze{HgqtDnulM#L(1mXPkg^fb4l3)TAjx(>hpb(w9h!==w}zcQzPX2@)x@9wc?%ACq= z&zD(F`nOxFQuk?Y>DDzb?-a<~s%E(z%rs?%g?AIXW5fFFRpnZuN%B*dZ+pv-k=Hc6 zd}_{td%yO)yQO!_>+rwXL5kWxB(+$<$iUFhP{}|6q<~pi(l0eVu_UuBRUtUFC^Iof z!LKwoDYZz!+0j5woY&C6zz_&6j13G7qQrTP4GfKpVO)b;6794#u!h)a;+a>Ln3I{J zfWvNAS7a9}fV^O6YS6@}gzRfZRtDxKMt%mMI2ThBBO}A>r2c5BD=xL~7J3#vinlsv z`n7Gw4!$bK?+rK3@_TzEu9UWXDq>yduKmQ!#4)I|@8zuGU|vhzTgS~AxspG<{S>?1 zZj1Y?tpd@{SLSx@5#JM@pUN{WL)o3bBed_|#>mrJe$vr4O%_ir9Lr1%XTHdI1#Bm@^oy7l=+;SCU{3;&DC>j9NP9=^qneOTG{BG zr*iX_#5L7YZLOkXjJqQQ!!H~^J#9f(kN#ezS^Uf^XU(Zwa#uD)^;?NH6Eh zFcAWygOR~AYij81uSU9Ji}vOPXba7;;hi7V*lu{SL8;p9%cUp%?=;`+N?Pr<*!sim z1bLp%vmRIG9(u6O@@e>`ja%6!?0h@txWEj7B5$LOa*NV`&-nMbWQ(0l8{^AU`g=B- zZITo|xN4V!=?-E3?9Zl7uM4W|=T2hmbP(G-$^QO{X$G7Z_q|p*^ao%5*g&39p~ zQ~iP+vV@I=?wvSuDrbskWUlSUWjX~*7fK&Ha{54r+tEim;v0)LX00~4-8;c{ewzAA zeUs|;zxJ9L>zGhfz3$iRVNLT;= V@#bEon@msUO*dX1zxL_>JODztWLW?J literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidPolicyMappingTest10EE.crt b/SecurityTests/nist-certs/InvalidPolicyMappingTest10EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..053a608d7e63f75c05ad719553448a7962b78297 GIT binary patch literal 938 zcmXqLVqRv@#MHNdnTe5!iILHOmyJ`a&7 z)NW?%IsOJQWyAPsawe-JJ+v9V2fj{a=91cMQg!6Y9}_)}GNslTKhC{ekhtN%bt+_B%q@z;)bJ0~%zcApN~_wa*jAG?`Y{}k!E+e>wl)0SM_ z?(RRM=9a3R>-MYjg<@(YO!%jt_7T)e$nBlADSNh^-zu@hUDdjY##5d@@P4uAO@fRg zgVypDugpSiwu1gFmY2GEJlZU`lKESv)bw7zBY*b( zJVbqABz}^ z$jANvUfg}rzVMtyd6StUOMqOhtcn32NIyR#<9`+wW+s*o2I3&T0*inFp8*dWS3;Wy zV=6Em8la~_V017ttgo7``Y8Eaai-`0x9#&2_p81AEA*p7QA}gir)!V4YtPk^J~ORs z*9H9-o8OdKPgXpAPGf@X8P*dI+UD1r#ZC*VnQ`KMV~=|C7=5=^R)#t1Wc%*j z`+_XS{CAd_DI;U8Y4q^>6u~&xEB7rQW>eF{@ggXZ&L8BQ-9aYdr=H zJSvNoCB3&@(BhrrKI8mPZ?5ai_us#oa_V4Fv7P+7ZOnc1UhLoL{L6aAnF$WscX|$W ze0Nvnf0z5NZzc1uhx>hmmiGLYU}r1RZeX6+vtyE9n&G9BhdI1$pRWmvo)*3_|eV-S8PC6F=4cljd literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidPolicyMappingTest2EE.crt b/SecurityTests/nist-certs/InvalidPolicyMappingTest2EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..1ed661582c49fe14b9f6848751c0330ac74af35c GIT binary patch literal 918 zcmXqLVxDBs#8kC_nTe4JhzxkyIJMe5+P?ELGIFyr7i3J6jdFcv2#GK3&g@F8=%;ZW1n8mKH z$nH}BIoQaciBSpJi;S!c%uS5^3_x)%rY1&4hVvI^o;(=zH-!DJ<-KsNkWW0~S0{UL z7Ek&gd)ABTyW^wz1_m=fUOr{?w!V0I&dI>bHFFOC`JsPa|I(XHIot{#HXDBPoTad7 z-n8ZO3;O4^KAtKwBkkf*!>7CWPe{#Gy|=}W@7kx;oU&Y&p(aOsG@tx#QTwp1_=>i_ zT0p`I{Wlrk&(577a%0Df(@UqFn7zBuFY;^V+=I?3$7i4UvTsHE`zL)NVdit*vnelB zGkdz|>%R}D5BWUxk<_*`?5s%pwqSYJ)syS^4G%u^TViWf#9F2)p7X2o*W%zm++zI| zEi4U};$)0uJ2qXao76NVrF)u{R6^p8kZfKxyI$`2EKngzuZ0!P6@JnEMhDoGT*Bv&fhT8d|t_M zgVHtL*A(mbZZ+To>E~x;{LjL|%*67+KpezZU=c9jGvHz4N@(+7Oa-Pn14iWN0H!!# zbTBd;JGx-TMfO?e?%1e%$L75I+5J!>F8T3C_3Sg==e^r_=Vu5qEb?S%gMxTcu3 z=L;Wm>@a^_tP;p~E32aQkl(yrRmY4Et@Yk`DUbE`nxsghgYz#uxKdM4J-hV)tMQA5 z+vmgko~xD^oQmu9zF8=^R%^O;NyYN85QTQ>#D_UnVnr-pErUu=7B08o$@8|I`8-{i zA=l}T+xorp<#?A)@6ms~PU-!^s#eQucl*yQc&s|PwXIr{dt1R;%Z9`zL*JdjnNzvN Q@7>(@-O^z}(^b literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidPolicyMappingTest4EE.crt b/SecurityTests/nist-certs/InvalidPolicyMappingTest4EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..a194a040a70a07cede92b377a4890f494bee361d GIT binary patch literal 928 zcmXqLVxD8r#MH8YnTe4JhzxkyIJMe5+P?ELGIFyr7z7z|8*s8QhqAB{11g(@hMT7?qGc%gD;W+{DPw02Jq9YGPz$*ztTp)nAVF{2!-jYRdT^ zHEfuZd~cFcrn9$;Bkz)vlhpTA3GBFfcJBPfhR7!$7exLne(}P2c~)}pi+9%>o?p9R z-zp^6b+^`O;aiWx_ZRy+)!eT2V+-}1I_cP#`pI`0MAY3mXUIPgPhBwIyY8CXD~0O) z(^vZ3y4&<1xpvc)h}w|Pfv4En>b^ZZ+5N*i<=?8^>x=g?J!v{PMR4uU>s{Lxyqd>o z_r}a6<=(>ig@432=Y3${FPF1XxpKO@ZKdLUhb&%3_su-{o`=lt{CHii^!uY?f$j0c z84Gu{1^jY&DxUw@;q{WX^4V-t_3wsd@jX~CF_j_ZOE#}aM#;K>^aVjDKb4+mVrFDu zT%2u?X&?^_U0G!o2?MbP5r$YxJN~DuwBmHXt;^6_YdqU_b}=|j$nvp>v50({7kG*> zde`x7x6W*tl1mx7DewRp`w7Yo&GhsPWA6 zx0bDQd=xsrXZl3hll{VpCp_70inm3U%$jzn_{5K`H;0{I5J_+4C<)%o5Wb`S1&|+%j0~C>m5{y7$jZRn#K_M86z5`UVq|2v^lLW1aqUE}w_WNznJ$<8 zwHQ9iS{+{U!_lzng;qq$6|Vn>SML)F47ThsozHbdx8}S3ES)Jr-&LQ!Dz9nTptoc5 zy^u+cxfkY7DNdN4$vo8}OTt2ARZq{ASKIG@3t`l8Q~tj7wo#&>#FbnD|0{k=?pJc{ zThrmWZDrWD^&S08bLQsDM6A!5_~?1x+ zU8%>tM9N*7V{Xyrif=#6qogOAgeG#_`Mrw$KydbRj_F|={C~K2J#EWOd-wXqI*04G z-_Ka^nCqy%z?)b1^o`j|tQtg4C!ex+GJojeI3Z8FSJkD?Tr_e9y0?{rSDyQ&&F8 ztv@-OXGiVMYq|3H+2-FD9>hOYX1m&N+qh~DvyuE?@h@!8CjGlS`}zW{tA*7ib9!U_ zFIsH>Jn2?oR7aK9$DZ!6lvbN52NE`Jy?V{STxRhGnM-ab_A_6!d?Ef{;6{qWBfB5( z1V5c`d*Us5y8Gh>pKU*;UX;o|_x`-`%5A|ZCl5Z+?_b1l@N0_Tu_u}@LL(Qv0s!hL BeMSHP literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidRFC822nameConstraintsTest24EE.crt b/SecurityTests/nist-certs/InvalidRFC822nameConstraintsTest24EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..28ef8f7491e37dfd0ef06983210027426ba89f50 GIT binary patch literal 993 zcmXqLV!mt8#B_84GZP~d5E<~YacZ@Bw0-AgWaMULFbFo}HsEAq4rO5zW(o~9lsAwC zakzxVLQ;!M6r59wN;1Wb`S1&|+%ObnVBm5{y7$jZRn#K_M86z5`UVq|1^dtsfpwpf9n>FM=mO)EO( zV@(`3EYn$R+Qc(y|C`)n0rLuu>ze-4Vv)amS?!6D)yC3g?2M@?N)bGN&F5X1Zaq73 z?*8zbUo9&;bF{RN{9}HTb>MoEfzu?3&0BSj%|HC}a+}}jpYikR7}jgw+Vw%*{BM8H zhZU!eu6!n{=GE=QxhwCTUeAf`$>Fj&Q@%ZjetBY>w4_Aai~lQsR95Z2VBgQ|{&KFK zHP5!mw>i}IzL+lj&i0^zVy1D=Hn6`)8jlc)-AN zgYWh>H_r8k-k6_=5HDm{mZ&WH(p|Yn?9QveYDcg3l_i(970=9BeW-KKyvBTv3xKP2k{kH1Pu5Lc-XiS+B_Ijfho~| z(ZCoaA;_X*pw*}Wi6>WAhup->oZ{4?veY6yV2UeAMoNBq>G@^Iu?S4Oz*uBtF!*t= zx9Qr#r75)%oPJA9tyoM(xlTe#y|-x#w)1hDw6Smg|j0>gQH**_~V{ z^!U6Q{~Nu2;c73|O4TE>iHEvcUZ{KP=bB_C^KVQ)=VrvXeD)>o$i3etU$KnYC^Drr zyh|{Z@8=CJalzD+{kvvNTlDXqxNo_{@#DN9j!eSS4ob}U6f{esUT#CUiQK+tTMAFT z)l2IAboa00Cy%V_K0<3*E0Xi~SujiOOL&2%TWy>8kpufR z{r44xv3c)Xr6qN0;=kVK-NBwuHf@nq`L_SX>uJ9&)+wyY3BG9L_eEK5idFM=yVKux KZGUsrrUU@`j&WN6 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidRFC822nameConstraintsTest26EE.crt b/SecurityTests/nist-certs/InvalidRFC822nameConstraintsTest26EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..0e7f71937a505464f0ac067c9007c259f6f9639f GIT binary patch literal 982 zcmXqLV!mY1#I$PxGZP~d5E<~YacZ@Bw0-AgWaMULFbFo}HsEAq4rO5zW(o~9lsAwC zakzxVLQ;!M6r59wN;1Wb`S1&|+%%nX_sm5{y7$jZRn#K_M86z5`UVq|1^d`o85h1s80t^EJvzkv6~ zEBs%-F9~#xyD?*(0`K*5rU#k3cP(9Vv@|X`^hkYI)^f(AnrPV$w(w7{B6dw(r`=L@ z=i*XR|IB4wOYh{wY@By8U+eH?%hw0n-}l#U`grDl?}VQxf5Of)%DEI-}e4Mi^j*_ z`_e+B8M`V{dG40{-*R>~gK2AXz!ia{%{GyCPnRg~UCd?8xus7}dcvD8a;#^QxqDQ6 zyuUYD_kV~lon6WJS?KwPjgt-JfdMV6%pzeR)*v!#m!pF3-|X{%*hr($CMx_@9M^nTh3tfjEe-z#?G4XTZb8mC)wFmOkN^fx8;LAOAOhJu4mWvg@j-WQ4g+*V5>v7J)n3mX#PEvFq7rspKbd@s#TM zXG%Invoas^$_Q~u*@=BS@qWth>u!COr_$E)t0-$W3YOo?`R^8cHrZKX%NC;<%l=92 z;rV*zh35x-mg{Dxu8|JH*d9&aq@!sAz~Y+6i0uPLcaFYCXO^_%?EZ>!4tBXNqH_R`AM+)>eM%bmRpF6XX(xbLOEs!hY1<|bX8hPWj+ zlKvIg2V8!2N1Wx)Vdn|cHD5hfww)jFvY~WRcx0xU%~$vN-tiH?-&_>Ruy8&N0PL-J AO#lD@ literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt b/SecurityTests/nist-certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..2e85ce5c21c86011f2e868184a413e49ec630dc8 GIT binary patch literal 919 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt b/SecurityTests/nist-certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..103e0940fe5c2648487c6b00e493c7c6db0032d9 GIT binary patch literal 952 zcmXqLV%}oV#589CGZP~d6CB(+$<$iUFhP~AWkq<~piE;BD9GbytqAU`KFxzabW zpdd3Z-B2OGP@%Xq$=T6BPMp`!z`zg)EsPBe45Gw&jSUQqjA2}ZauO|eH*kemZ0DI* zmY9>7q7a;#lcwugTwI!(qJYgY3a+lm9#8=J$k5QBiBSnT5Exk*n41{+8GzzkOihf8 z3~$|D_eb{HKaOEJ({}6BZ~5htuXUgHzx^n^NS^EXIo}LbuS)3~8c$7n>dnmAl4>K& zo;~7Y-+pc5ZqCWE)@yyGt|^F1G)ynJu#LCf{k5ELhIRX~SigI-Ib-J(HBQd5b~>{< zUUiR4kN&Lod%Sx(?G(ycc5e!*zhL|D`CV_xWqdzjN&i^|xUM zukzkmAv!}ojdz1EXZs^JzwIvjuU|bhA#HEd%Eskw@_LOk=lzk;;0ns#V`H+m^WHM% zkIAa_F(${W1M4-^RRgrk;`gb4^Wl&@v*h!Qz03TBXYCV5j1^Y6jJDOEc&o{ z3ID$c(RY0pz8q0%o||m+J4MuVrczd)#vUQZ)+yql5h?p4-FC%PO`1L7(Et0=2M=C+ zEnV5XUg}8tmM1*7PrvMH=$fCuyC?6jr%ORh(z$Pb0$Z6{!nU0|$+d5iuHX8$5Cv(j zc}L`~w{)r|*Y8`vSNDtIrMCC0SZ=w-)z6RIEb&>TaD9&5T9Lz#raA2LU9|qcOI~?c zzW;0O#phl&>i%0gWfI3VomY#le|l$e)K*vO+@}!hN3XYBmSlH}|9$@SWsR?G+^?TM nU-q&!KjZ0-3HgSs+>=b3KH0?feO;>YeP>q6ru8Ro?$!nX&B(+$<$iUFhP|H9Aq<~piF*7eCGbytqAU`KFxzabW zpdd3Z-B2OGP@%Xq35c8>4dldm4GjzofzZO(z`!6%oY&aE(8w6ZH7Fy|ZZ`uLh~2iH zd1Z+?nJEgvsX1x7p2fwbsVNHB+@s*?itGmkkf$sRni!RkgMpEifw_s1p8+V&#ni;e z$gu4S>s3ki+42Y2S-Rv7%c!01-6&u1&R5SZK|evXV)62hdsgD!D#~U%c#a#KyU@9R zoo7pl^@q9VFMBzE&iuwbx4l2S>0-~>pE&4cPHr?!V&a#cNMnAD%5_dAvY3`O!W%-M-(~k0czeu`+$+>{-0=z--r^PiNK^ zvU&zDvXj-%ePb?gw(y(!Dz&8rg=&jfy~0yEA+`Mj35_Rl}D0|!Ve1(@SrzaUY*6^JA zEqmcd{y!frbN<&%%!~|-i?aKfziRpAaVElwJqEwXQPEWcb{O=eeB$Jd~4LMUM;)s ze}|?gnyq|&e}>hie^2=jSzL+PyhioKCXwc+{{m`GT-c-K@@0YhR$Hs@kC;AuHF>Ug z_onNG*;*^iB8Bz8_WEy-5c3t65U}5W(O<+_ynlUGk&OA;vPpUVuM!V^iMf&eUOiT% zHz?mlwcvTK|Bf2w6Y-pESvjgK{g&@f|FS$C@q8h(;JJ#vLx!u?l-|lx@!F+3FQevZ zwdz7oV=;m?Tzd nw<%l^^sJf{uwVVu!TV?X`ChcM++aN|zsO>eUhJ&@AI|{*=&)$x literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt b/SecurityTests/nist-certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..1a1da9fe7a00073b510775d7f09abd840bf333c5 GIT binary patch literal 954 zcmXqLV%}!Z#58XKGZP~d5E<~YacZ@Bw0-AgWaMULFo-hbHsEAq4rO5zW(o~9lsAwC zakzxVLQ;!M6r59wN;1}` zGV{_66#@(uic6D#$l1|APMp`!z`zg)EsPBe45Gw&jSUQqjA2}ZG7{}}GjM^}ZR?p= zmY9>7q7a;#lcwugTwI!(qJYgk3a+lmeoz2;%F>{TQ3*L17+D#Zn;7{SfZ|+CO^l2T z58s$|1aDE=HbeD5ib04(MYF|%W>MbM?jPnCT6eCGF}5w(vR|peU3)_9ZSReS+^vUK zJ#&BRqUrqWwb9p|hKFr<0)}MK|wyWRt<3!hAdP@~}JuBV|-V;+}ou|L>&V`jn@&Plj z%vkznioew9ogueQ6alKdMlvfknW8 z&wz)GE1}JUF%_6D4bW31Fgh3+Vjup>z7WXBsP{7d+49Ua%iWh2q*Z8!HE!{o%Noo) zd9Q=WXLpVdxdJNc%FY{Ky#BPTV$E~QeV=1yeCc2ItSnUD(&Pe%b*z)@k)vx3A9jD; z{73UnsE^ovmEx)8R~Q2L>})P{9qlRI={vD{+L4yK4__WxsrufFtMlgE+@m2m8!yg| zpY&0TA>h=7`H`HB(+$<$iUFhP{}|6q<~pivLLY}!zVS*IX|zsq$n{n zuf#y1xHQSx(a1nfoY&C6zz_&6j13G7qQrTP4GfKpVO)a}676&`aDv!r?U`4Wn3I{J z5S*Hmrt4W;T$-AqfZ+}WS65_*D}a1rXlBsFsD$i!Mpg#qCPsb+pg0#(6C)$TQ3ll| zjceF4QdX@pS(9==T;%t{PvQroc|E6E-2ClWkX^ORvgQA~jym0|5gdx_H+ER<(0b_h znSb%e$^vu6t$(&8E!lcNBKYz)@%PnjTF1PZjRJLh7V5wLD0}<&ws$INKKI0n!f#d2 z6)x0&YSVYRAj9Fl*q`p0i{UpO9#r03{WD}u-G{d&cfCF9Y^Q$ci7bA!h4oT}>TY?r zNGFauy~W>8dQH^KIMY%{Q|7IeJCEdji^(jTytMe<1IKBPnl3o^EO;sW zv%Vrg$dQSek%4h>wn3(WJTSCnm02VV#2Q47acW8b-tp2dBcbZ}^mCgd0;|jJfzyaA zABz}^$oJ#3`#vra@L~SFsAS{k>d+}KJHHz6f%Nk;GX7^_VP<0aU?2|SE3gO{@EP#1 zaV4~QFs1@iqXBwa1V#rVgWJ?s5$SV;*FDOSN_*^j(=&F(@$N0(V%mB27KU!A=Q#aE z=&EO2!zUlk`9i#QyJ9$=S-xm|T-#DpXd9E0;=tmyPsCc*BqC6^@=8=$|FVtKYG>Jt z?)CCsC@=LYba_U3&%!-*N18te&39eoTm0j;z>F<>RQ(@m9BbGm9OaH#D?`)_n+7lJ@Y4>dNOsmrj+8U`XDeWs_ zk{_KtKJ!ZUnu6d(&ko$M3gbM!yRDsT$DM^AoeSc_4)@!{X{+yI7G1nC@FPdV`IDB0 fS&LYAzpSZL*qd~&Y{t)5uaEy`Yrd0l__rSb4gYk1 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt b/SecurityTests/nist-certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..d4050e6f4f04742b459745405aa43aaec4be9acf GIT binary patch literal 925 zcmXqLVxDQx#MHQenTe5!iILHOmyJ`a&7$+jq3LKYu5E%zhe6LLBo=Be??0F+P_r1xGg>R+T%D? zt^>CPiZ3}x2dTbZziRij`&J*T?{M#4!F@x%O)-c2C8OAc6#E>-iYqnGOt&|Cy?PRB z@?^y+_m^R7q;6#7C@058^ z>RhPgH7)gf8}a>TA7@OSqew2-WhqYo=w#zIulX_GzCSrPq2Wb>eU@>WTgbtMJlmGt zemvdy`~UI<+baWmSkD>ge3LxRdF0q0iOU-&1W5iWV>aUrmUts@btU7Ty6uOvJ2}!{ z-#laQxLBKsnUR5UagafPfjlt4WtCYZ48$5l6w3ek81z2c94Onr;k!(|Z1W60cW_FP z6(!hK4rC~hpxK)VRp-Hp{txddwCac58kLF=PR$fV4wVT z&ClCQYjzj=KUCjyt16Lqq4UjWQ}_y}6$C7P?Wb8Mnfq%~Zcl7l6l=rjg%|9z=0AV& zkjH=01+G<7-l$HpGYD}_U3lSgz?^x(^Hki^rYIH*Z~okTkk3L-dDD=yVMJX0)yLvdDrg%KH_;5YqS?=+>&lmG7?fB+#UE^wvn)2D0^0qfE M^XylgIk0>R0F6CoApigX literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt b/SecurityTests/nist-certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..77b6a3c1472506bd34f9922e5a5bd84720dd3705 GIT binary patch literal 925 zcmXqLVxDQx#MHQenTe5!iILfWmyJ`a&7l5?D=P68$kMLT2uVm&!rL7Es9sGy9p6euTd4DV0 z+4iOxFNc`3>i)jNVGY-gY;EAKedHthD1Iv2%I*`>7w-KWFJE(mC+V=cgTR&FRe7gd zcKdm*S;)l9$iTQb$RNN#9vI-V$}AEFVhtjmT|E^GYBjXSaoL+IHkz) zv52vVoY0$^u;sxc_Jl=0%}&Wy>72>izuJHgq@SOW@jnX-GZV`Pc<+tdD>6@_42;M^zvDD57b*_;Iyxz-r~`tGXOM@&9_r$(U04xyCx@Sdzx| zvs=I4*8H%;;X>2a2`_b*EO$OMHTK}@!*Zzwf)^P**Zfu4_r%rl=DQdB(l5>W$Fc9P zOrzCe`LNv!j^28AK|8S~K{spOxg`uY3%AYL#`Nn?{9+@^}T>j`hO8t4$@UjqNAf#ebzNT6KCBd&TR__=P^J&RtHA-xdC9>UYMK z2{&!7XP^DRv&8Q|kM)YlR&DcJzg*&x*WWGD$h=~y^MP<{3;A~nZh_Cem=s>b{&#B) N)+zgR<#VA%69A=7Yk&X% literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidURInameConstraintsTest35EE.crt b/SecurityTests/nist-certs/InvalidURInameConstraintsTest35EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..65096685fe2b3782da76068cf8ae5657d106d142 GIT binary patch literal 987 zcmXqLV!m$B#I%0_GZP~d5E<~YacZ@Bw0-AgWaMULFbFW@HsEAq4rO5zW(o~9lsAwC zakzxVLQ;!M6r59wN;1 zZFhA=cB}%(^~RTp`&YBis`Kql&st!*W5cQE**|?xW*(es$yvfLd54LAVy(iYb8Z>R+<6n~ zgSj8E@)uRuJb8ER(E-2bK4B-CjXl)PlvF)7x0Mu`aBKP{zH`MgA!{dIzmvLp%W;wU z_1@Qm=Z9>0zx)OFRLkj-b=}&cDIY!mE)>>Td%2liH1Pi(BjHOq%dR;rJj&mjuxrH| z-jat?UaPH>>lgHY6IFF%;;KD{-Ch-IL~cAO44d=xZ)}yMgHryRjWRtl>nFUhDAU?; z-u0%8*E3_Dm_IjXgh{Sq>@QxO*qN-TFmtZG=4QuN%nMv|L?7;b&>F_f#LURRxVUkl zLE}6Fd0;5ZDziu!h&71((pc*#c26rq`~<&@vb`GfJth$*aLSP7V-aH!S>*I!s-)4| zr*GGDGL)sRzocG-Xrq@SOW@jnX-GZV`P191>vfknW8&wz)GE1}JUF%_5w4HylK zK@x&2ItE&88W|-e1y=g{z~ohujFi^&((}voGa=Efmr;_NgB**%WDAT%Muv!AucN*) zFVuQ<+31&Zz)pVs#w(9m+Zpcto3MYvw{N>VES4SE^49$EbL zyy*9lyhnF-=RaF)Qj_x0`qiX+;lA(Rm#Q+&{=W3jncY5f7jYll!oUAd@0_&%o;>#| z^_k7g1wRYTHjxlc=G9stKI4ep;#I0`u6O-B_jKRgF4uRau_14r#I<=!-O9>B!ZQQs zmWE#~f3x}Ndrq;VyQ;I7ZTn^Bv}^h`)eWarDkd6jmzUA15-`BJn K)^49G+W`PX*mcza literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidURInameConstraintsTest37EE.crt b/SecurityTests/nist-certs/InvalidURInameConstraintsTest37EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..e64db473af5f954231c13a9fbd8d72bf11a7ce2f GIT binary patch literal 987 zcmXqLV!m$B#I%0_GZP~d5E<~YacZ@Bw0-AgWaMULFbFW@HsEAq4rO5zW(o~9lsAwC zakzxVLQ;!M6r59wN;1 zZFhA=cB}%(^~UA~O^iy&9%f`^U~XdMX8?+GF*PwVGMwEwch}`@Y})C&-!~ae{I%ns zdk8J#Ib+D`M)73(j&DwX4?qPfN{nnY7#;rL^ zS$eY9E5BNP{w>#xAN!wiEi=w#Eqkl{>*1X%f>A4*E`R%U!f4&@XIT^8Fs6SEi+3^F zc#HkFt?8v5(FvXzOMk%4h> z<3fYRc?R;pP?l9@kuVTz5b=H8S$O{g3*)9=WmXXzcO~5IxqKL$GGzH!#8^bO%nvZD zxe*dw`JqpwZ0<_cPfK`B*k;?#DYS4q-8Zo%RpJf-U3bY7=< zOb2U(m?g|@H!Pc;*Sz9Q^uR`)3_>H!K)^|Tc*axzwVH3V}E9-alv)Z3Rf8p J7xAk{Y5~)zfZ6~6 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt b/SecurityTests/nist-certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..9200cccb39a7cbfafb3eb1d101cc859ed36263b4 GIT binary patch literal 954 zcmXqLV%}!Z#58XKGZP~d6JxvqFB_*;n@8JsUPeZ4Rt5uCLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`PjgHjT$aW!y;SYzXvSC*KQnW7Mymz|eio~Phklvx6F zP!6)&6kIDxQuB&4^Yav3UBMCxAmYLNot*vfJZ1b$@w#=L?*j(uwZ+K*u>ptuLZ%H1X6TKf_cTE&J?>yB(uJ4od zf_XFJ+?2%St(VR*xWe{(+g#ziEt~zD%dG2HBy~%6i0eW=aoyZ$;brUi^8~<441Wi~^_MN8Xp*bl$N3|BHXV zhn8&7R}=Qn6Ylf7<~O^#{>T2nGp`@{Z)?eYD7jhjyKK$I={jD=lAf~X`1bdui1oj0UTk<|CnU(NH zY<6X0W@KPo+}L1HXCMy@Z&_s)2?MbPktenB7h|TjapZ4|HMm^4bWj34t-!b0o zFObmts;TT%_^)49nyN-mX01Pbda<7V4bMq)6&Wi&^gP%PcR~_uZR! zs_$KgmPyd6!>3wHQ^K}f)=YWep;1-kQ+M>X!%>B^`p+)&`8_H=aI>d~UFhGE3Gxq% v|Jv9JE>5%&SZUgQ)^CUR9If56Vq|u|Z*Y;?9{E1y@?zJMUh^;eH+=;F6$Ea# literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidcAFalseTest2EE.crt b/SecurityTests/nist-certs/InvalidcAFalseTest2EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..3d5b82946bc87591dc321ae70a0c53584c6a79ed GIT binary patch literal 934 zcmXqLVqRp>#MHHbnTe5!iILHOmyJ`a&76^m3?T*{yR=n4L||hDx54 zNa;HAUue3JwjN*8JD#+pS--AkM)j_4`MfbVD_Cv{v%vBy&mbMv53h{wFN*qKFW;=1 zC|Li+nZK{#_<`o;d7niSb(i0dh?iuW@#w#urP+#J^>3a(x;E4v(ENS+VZqs55~4q* zyIXUJ-tSddbmR7wvV)KJr{0^^aFO@=&ANudDd{N{5AGDKR6T0s@;+y2I1@7?1LNXs zgG>W?V7$sIvq%_-HHZ}4chP5_DI;Di@yX0a#N-0!#ZPa+DMOZzMT|wHW=HjmH*88B zr}`%b+&XeduclEV$bb)|pP!NOKMM;p6Uzq!aS&gDMZkd1fQOAMq0NIa6_^GM&{H5V zIv5#}b_85_vG!u{?%QD*Rd4?86`7hp%jIP9lDN}3756k)1R4(B?|xnN*|c%8N6%58 z6V(-;x4!lXjd+yqWp;>9khx^zj?ZcwS2syMk$YD1tZn5lyGgSD7N*`dKG5<@MDN14 zOE>SAU$-jO;#iWk+wQrSdGqOep$mR~&57Us$*oF>Lp$(k`Mvi&SJF4>u6WNiFEQkT z?33U}o;sq&_miEs@v*n@MjtxReExdCTW?7PHZS!fQca#tTJxCZ@_enGW9y%DF)4Fv zf`Y6=#FmHFJ_j1#N%kpTI=jqj>KvwXOLuD~J?J~Gwx{6k&E968mhvP18jqX8HkNfV Ryvs{4_;c7}f^%9_GXQK~WM}{Y literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidcAFalseTest3EE.crt b/SecurityTests/nist-certs/InvalidcAFalseTest3EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..f791140cedab3a687f15ad38f9a2a3f8d71e8c90 GIT binary patch literal 938 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidcRLIssuerTest34EE.crt b/SecurityTests/nist-certs/InvalidcRLIssuerTest34EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..8b9041f5ba49f59d530a7507b5eef3d75679160f GIT binary patch literal 1044 zcmXqLVi7QCV*0UwnTe5!iILlYmyJ`a&7 zAScdiXkcIngcimI1_n{$yv7EGM#eC%K>~?385rn+Y+@Ex_slCx%*jkqNDlJxEG{lh zEmClGMRuA3$gRdE22G4g$lhaQWngY%_SuD3ob~!@kv`XBrC+#y&)jrHi9o*SatLed59!<YMXaB`~VxCy*(L3k1IZVB?A?XmaMV!dmjphqcDCrb0u7wEQ9k^kj*e-hl~%ks&u^ zPI&R0vh3@}ZwqWvw-?M$u-`KyYAc`T^^(^oKCBZx7@v80twCW!%A_C6ZpV*n^ytrd zm~nmj{M}D(rvw}~y7ez)jf#A%Tg$||^7S!F`|90p<%(^7awb`dZ+e!0_st0st7O`F zAKKZ+9$&pqASK%PGxx&ya<7-)YnC`KxFhW?6Y;>R>PC9i-g|oYU%rUHcT#?W121>f ziOv{3Uv{5eH?KOI7ks+3;oB7UD5jhByZ)TH^)qp5nd{-F+Q*hMerIF2v}mHmuIcZC zmORo7u&J-yyjbuhFLSoTRpkp@zow{Xp8qd7%f_kI=F#?@mywa1mBGNnklTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kWlrRtjDc~07&&*57EJ{r-aSrlPaCS5` zkQ3)MG%zp(LJMO91A{1WUSk78BV!oXAb~`i3=H%@HZcpUd*+oT=47TQBnSC;78jSM z7Ad&8B0Eh1e|UjE;{Ixc^nO@x$>amuz&Z%*rdxuN-?M12c8r}+Pg9_bNN|D`#x zwXK)F>MUui=sPPv^YHEno9o)y*?Wzge~U}LU^#c~(iR4RV^P{1UQYj|gmYi2t2&qd zt2Gc`W#DP8mcF>YG2n;CCh?1`C6UL9OC8)6-#F%X(b;fEW>Mk7>)&5TGchwVFfMLl zvv51&hF3FmC zxN&OlZ(+q&*_C43WOjcy-~;LBXJq`(!otkN^1(nH#8+SuFyJ%bVdF|@^I%K`ra1#f zgU0h98F`k*;|7gK3>ptEC|r=gB-bFD#PonOAF$l(3-$m1mi(~LRAd|xRf2Hg$qSr>Hp>`9|+shslk8(+@I z{OEAXFqvQWdCnd7^f^6h-#Fl*t&hMSYmKL$8=0-RSJ*LaS;%{` z|KIHA6Q5e@GknoH_)BzdySt zcJG$|-e+79V5=9uc;B3aDQ`E`9`J~GD?4}QX}@l_hc*d(_U$LC^}c_5ar}6tQqnZ> zq}-id+^aUv_z|Qr<@&>g1?_s8|Ml`spG-R)8z*GlqA g!ZqP`=QsBrG4&Ru;!E5N>0!ERTXrl^yc@O*03G6%HUIzs literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidinhibitAnyPolicyTest1EE.crt b/SecurityTests/nist-certs/InvalidinhibitAnyPolicyTest1EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..828203b11c7db73eacc6a2718d59b1d8cd40ca47 GIT binary patch literal 919 zcmXqLVxDZ!#8kb2nTe5!iILHOmyJ`a&7a|NH;q$-!?Wvptq< zxFPhY^VXTqvg(o-HU#$X+nToeq=D$GOQCw{hb^_97OmiIdiEkXd%p2Mu46lOAM~C0 z76uXFNzxY{uWMhbVsd}~=Tr6K^@96%&5TuD`+eC`mzdjIe{z11*Ge|Kb)bKd zbUeG!hQ1TqZVFhI&Rag!XMvT}$)-Qw`S*X9wt7A9{(PZ3^8$5N{XTi|zv=ZK)6R9@ zV7i$tY4m4e{;t61@4a{bn$TOKS~_jUuUoGLzpCkqs;w85|wRmAN#w^*}w@xmXAe@MTBL^=6Z(obq_T> z>}K?eX?zQ^_&eQz52T-;k?}tZ3o{eT2LnM6Ux9_ofWv@|jRnYLK#mAtk^@ErBZEuA z_ep|pC;Pp)948gJ^1Gkam*URp?=626aqb9XU-|pPxvh>e;eBe?>u;ntEe-dyboq&=M)hSJ9f*Lx6mEC2hN2r${ZFyELb6=G!NB^s=w9Ijrgr3?@7ad(b zPjsqt=iq9vTDDbody4t(}%ns+%oa=r+s;R8^0X>c>QU%)%0xc^R2WnI(>Sl>zxVnaP!g z3dN;K&W?r#a^k#(1_p*eXklz%U=StFYiwX>WDMgPq>*T)nSlw!N?p&qvc#Os6a{pv z6hs2_f~#!S|}8<#xZTOTJ#2ym;vn(;2DvP2FC;NIF{* zaQzbZW7(XIoa+{?iNCz`pTdJX-`eIKJicP`6T6u=8+3fWtPs7c;~&Ri8*Fe-j5+6e zZ*ShlI8KkZ!QEEr6&0MqA=3WLKC)I>>tddKU2Zbrg-q&`O-FzII^Nn<6v-X3V-f!c zmFKGKJ=iG#%xc9yU++-K?_sBE4t2GN&|ieGT$B+A8iW-u$if-?7N& zIoTT$*1l5ZNnf!~fKg+G)`ynMZ2wI{JZz?$SMK;0<`my}vi+)?yf70pBLm~&RD)!2 zl*%fzNEnDUh?Fe28gWxQ_>%U9v$2K87VdXmenJ$SC}jCq#8^axRE}@p_-fHy*W2sg zc$q8CBHd||0Ut1aWce8x|Ff_#GqHRy5CriRShx&04A|IMfJ_GDhyW%#U_>x7R74A? zg@%1AS8l${KS6TmwrI7GA6%Ql_boTM`RV8?#hw4^uW#_-U|~MkQDZkxulIkf!B@>v z&p9a;7kKpL_I#R|mOHa_)B1IhK`-9U{Ig(p+%>nIWqJ`?A9&y8FKiZhC*xxTG z{neGs7hkgPvYN#<$vXzmg#Cg_nWx>8-Y%{@Gb+lq?fWFHxyf9UY!eLd}}m^(8CY#&vtPoH=vr>R%f}j$P5pN*j&d8XWOWPrh|s Ks(p3Uxg`Km&R>%N literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidinhibitAnyPolicyTest5EE.crt b/SecurityTests/nist-certs/InvalidinhibitAnyPolicyTest5EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..2fc212d33ed9861b28f4d231358c99a4c5fe6897 GIT binary patch literal 925 zcmXqLVxDQx#MHQenTe5!iILHOmyJ`a&7A-4f18*?ZNn=n&ou%Wzx zEQrG;EEbYlT%zEdT2zvmmYJMbl3J`_WMF7$sBEAJQot-Mm6?~3nUq=Lm{%E)pOcwf zX{u0Mngm47js|k#yoLq_hCpaxY+zszCC+PXU}$6v;~J!qXsMZj3B*!e&%Cn4oXivj zbjuZ7U6CED0CK&lK@+1AvVR#_8JL?G`5A!XTue=jj11TBx%S-oCaIP6`g6QGH^;Ts zSvF?>eOjW7ezUZ-|KNM~e_r8DokA{-$~z~u4esg|tYDkpFkzLL^1475-r`MtZnZ1# zJW-y@H}UwhSE44atzMd8J63J!Qq+^J*!8*m5}VUuJLzJ+cZZWKclex-3`-VYp`Kh- zH#6{%t6bf>c@L)f3M(5=;aRV~?|o9B^TE%jE*^^9@jyo)-E) z@2OqR@EYB_O)|XKX7|uGpBO0fXO*Ov6WRvmX|tfs50|Ut#rzL;(v9O z<5_S1ovUvi(_>~zS@T;wq52AUh}qS%|JHG@uMvHCUE`GK=6%Oa76w>NZSaxz{2knV zj%9OdhNMoID74&m8LOCIbtX4YUkRIH-p)zY@U=cyd;Ce>2@e>J&H2d=JcKkCsH zyHh;9EB0>qj9Q8M-w&CzSSRfNcBt=_Y5Eac!JKxhM@8SC>=K=FFlgdC5mvpKcIg7= ze%?2_<@F$A`~Jp1c~@3yosLzyzqrvW;e5a0*%!yAE(w3aUSe>Aw1fs NZH`mB9`hC~1OQKuVaWgh literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidinhibitAnyPolicyTest6EE.crt b/SecurityTests/nist-certs/InvalidinhibitAnyPolicyTest6EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..9aafebfc25f67c64c9d4b2f12ae6144e23830302 GIT binary patch literal 926 zcmXqLVxDEt#MHEanTe5!iILHOmyJ`a&7arhK&4$Z>ujw%+_K_(tWKZpdW8G=jrBCz9D}MEsyy%F1)un^y%3P zPjdeWhgPp#`>CMl%ySphbUmAP~e|9oX*xF=uY=qj>u-&PVY65RpIA-Ww zt9eu6ROa4$&&k9!TfEKw@srq)l27aIzHxZE#QukfT;(p-4_33Y8MaL{|9$nC#it{C z1T@%kE9XAE>~TY8X3wFko7QU_zE|~fmS@`W%K|(mrF@rz@BgS>E#}F0nkQ(#`L(jP zr9w|1ah84WVNX1)f6HdcEyWG|Iy2g@Utsa#a%ago@>tK1f%TZzmi3#yo{^na`?8gb z;YIQx(cZm#yk@Qb@+anSOyrUmxi5V;7%OPlyQO~H${G3a+8*Y;@8s`%TePNVS^JAV Qe=fb2*KZEp*6zFv0AL$qZvX%Q literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidinhibitPolicyMappingTest1EE.crt b/SecurityTests/nist-certs/InvalidinhibitPolicyMappingTest1EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..65ca6340ea6e3a706e2f767597c7c92d362a734e GIT binary patch literal 950 zcmXqLV%}uX#58LGGZP~d6CB(+$<$iUFhP{lwAq<~piIx{aLGbytqAU`KFxzabW zpdd3Z-9VwZG|Ab~Ku(<3(7?bD2rY~a3=E>gd5sMWjf`PjgDetlwKA}P*lOsRSC*KQ znWBKrb_G{gWEU%dykKb1#HfVqX+~BC<|amd2B0_>QxhX2!`TaM6E{!YCiTe9m5ae= z=l#{$>$b05)3?EWY308E4o@0x_x!#7Lh2Z^K7&_H=J!=x42xGhdgT$ZMmzBTlP;xK zmp)s!|LDJy_+nyuY)2mdmF)8$HN_tO-+A}{Ss@mShA%qNN|o8|hP@Lew@ zqW*fyw}tORk4~Octs~mCCWCh-7sKt!EnEHueq^0w_50}&*Eol?&Aj)&HF9P@yMJfq z?$44YyK`T(_pM*B+k8cai|4gA)w0=7zKO}-=w|zIY^t)dcmLg=eO=yR4s1_nm!1v3 zQK_N!Q6@UOe$tKSOfxDSEY4nM^>GXg^8K34Wao7K@Pj8871$1+IqXRd@xW2@fBF)3}g&=*tinfJQ!1fsnCEC zg~x;(IlvSNj2uRWHsQQ=yt;SoblRWXo0U`IbME}4b0z^X&wETZ$^Ln*F3LTnv9Ts8 zx8c*J=Cb=I)6yE0_sdO=Vvq|t{M%QC|CF(|Wybo%G_CMpW+CM>`O8!*>doP+j{AcgcbyFkscc4>DPP{Ddky%0; ze;i(rXLn(X&(oI?vL8IA-gHmcqGWr>;(VLflL%d<^J#-X?8Oy2Z=+tn=>9U@L< z+?#yx$jb*$d?x10gnzK)H@|Ui(R>B(H4%-M0)8F-)qe0Lvv1YJs;K{Em-3~ZUdpYv ZFL8^@JQ1ZKsdlX?LuY{?L!@NXMF6(3YF_{V literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidinhibitPolicyMappingTest3EE.crt b/SecurityTests/nist-certs/InvalidinhibitPolicyMappingTest3EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..c8b06f07e40055a97af55ce08ae5c43faaa1f530 GIT binary patch literal 943 zcmXqLVqR^~#58#UGZP~d6CB(+$<$iUFhP}@Kgq<~piDKjr4GbytqAU`KFxzabW zpdd3Z-B2OG&`6=UGzo~D9S!8fc?}H=41v(X*ucObN}Si&z|hDT#x=+y(Q+#T3y9^0 zo_S@7IhiR6*c_qY>Wb`e1&~jS4VoC0kp0fc%D~*j$j<;2=VEGNWMtSscS0hsW2B?@ zrXAZKFMn6!v9NFnufp{y*O$)U5Pd08{`;cW-*+eJO<3yJQS@w?@ zV;6U&{1?+rxFxs!YwSI_dNs>+@!w@G=9Mx}-u+o_k>N)-z2!0Ii(XYU?X-9x^(0v- zL%7s}Q^wgrcIx4kzTvBM${*{Q>!gTIdTyn@Q}$$eQ0q16&X{Kfz0Z^jkGZW_uxRO= z7ZriBlI0Os+8>D8=R7%QV{Ua(@WUtW>E-Xg3D>VYBlg=Ni1B5c!-T6(u2=I+FD%rVzEO*3ExF<5|QO&5n~al zz0TF~ku%(WJ7>zSkb{h~A6xb)8SsJh^D{F3XJKJxV)2ZpZ(eP@cB`l4P>eEykVa!`uFr?Myowanzn?ap-03 zmOVbp{cUaM@7eoWCPseKkL0Yh9cMSx{yn%uHdfmud8Sfq^ZJGlwU;)AMdmGu*EyLZ zTyN}Wrz6c8I5EU(YSt8!&A%2K`EVtrCSUO1SQwSamT~OqKQ4WP@>+}TM8=md-#_GE z{)%7sM^lm4yic-9lP}#%=)9kCW#3toCJo2Hnzj29YiC%lJ>Kx8Y5xh?T&t7wrDM{f cPS+*=djIc!iqfauR>HGtkIs12=J)9g0HarIKL7v# literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidinhibitPolicyMappingTest5EE.crt b/SecurityTests/nist-certs/InvalidinhibitPolicyMappingTest5EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..f3526efb69fb232df87f46012b797102811817b5 GIT binary patch literal 942 zcmXqLVqRs?#58FEGZP~d6CB(+$<$iUFhP|H9Aq<~piF*7eCGbytqAU`KFxzabW zpdd3Z-Bh8tGzo&79S!8fc?}H=41v(X*ucObN}Si&z|hDT#x=+y(QYdP3y9r@o_S@7 zIhiR6*xaDt>Wb`c1&~Kf4VoC0kiE{x%D~*j$j<;2=VEGNWMtUVUH#Dl= z|17pkDipWe!uRdYlHdOdj)w?#)a`SzbKv-!yYbp%mqY6S7c_}^srM5hTiM2&?{Bxu&xX*b+-J$v$l*|o#{$2T~%+9URGgX1FG zEmxI&nd`Z1L-XD6lNHu^eDeyd1i6ZzEAijvy1CP}X@kupwx`C7Vl)5m^^OfZvyh3I zk%4h>wn3(WJTQ!9m02VV#2Q4_C7-_j=y2iVFX!_9n0}dk$=B|VI5>sK^0A1qi11AH z)BWtafN}Q0J?~ylnD9D!ZQy(ZK9GKXM#ldvEX+(S9}L7nd<7N(13m*DHm-y=55`nr zS~Ornjt*c-1V#rVgI><{pbdHp9u_z-K3nhnzCw2g%M&Z3Kc})|TiV|-PT_GlnXy%A z74xJ=nyr`E9rtJdu;t3(uW8V+Q))Qwao|1AduAbFHnV7jUfK1P8kw8-ZduBCOnJ$# z>6^Cst(|crBKD-G#t9b3(6bpr#_cn!c#Cv#t^c%HW0mq1wWBMa z$4E$CJj|_9YxG`ly7T5c!Rrs%F<&^4;>BUNU6kGH^Ou7^^3)t{3=*UTRvmio9De1> atXB)Kx@X?MC0iNmWSf53+o<>-(>4HDh-vWv literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidinhibitPolicyMappingTest6EE.crt b/SecurityTests/nist-certs/InvalidinhibitPolicyMappingTest6EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..733c152685dd340ff3020482e9fd611ee93edb13 GIT binary patch literal 947 zcmXqLVqS01#58>YGZP~d6CB(+$<$iUFhP~Sioq<~piEi*48GbytqAU`KFxzabW zpdd3Z-B2OG&`6=UGzo~D9X$hlO%3G4c?}H=41v(X*ucObN}Si&z|hDT#x=+y(E(Nl z77zy*dghfS=47TQU~`Cqt1GhO6+pf*GiYK|LiRr+D+6;ABR>OBoQtW6k&)rjml*$F zj+0JHCI5KBvP-PfOl0n>Z8o2NRdR|2RXBc6*ynUW{Ez(K1+zQrUp@|cyUS&^OVYK2 z!S@f`TNgPcKlQ{9k2i^m0t$PRc0}#r-NrTbK(fod=o*GcHFqwCFm2i=!t5-c_4e#G zn=U3l1;+^&YMt!W*o{4`tZzs&C|7kbq#S)E6tsa=fAzj1gQLwG-yOPp=z@jh*=Z^F zEf;-G+TpH#VJ=_#ql4}(6A$tIm~mf3Kl=3k2E7*#_QXYPJ{hT@e#jpuDNjgHZ~`sDThi;B9u^Q;cu*&W{SJFBlc_T7Z=EdPMY zs>3taH)!V+&SYBo*N$QDfq?y{lg@7l;&7aAFopHzU%k`+r+&Pl=(gPD-RFyex{D*~ j9(C8p8C;T%e5GD?nPL9E5V@Buli7AD-s|vLsL2cfx0r8V literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt b/SecurityTests/nist-certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..cfddd3a4359dc1a7353f3f26d3440b14355c9206 GIT binary patch literal 954 zcmXqLV%}!Z#58XKGZP~d6CB(+$<$iUFhP}@Kgq<~piDLb_?v^X(6Rl&I^vjnIl zMn#bf@_X`i>sRZcK+jI>+k&h@peIm z?O%_aR3n*u&udqUzX)G@yYu3gS66)%w!W(^cFI|k@6-0p@vyB5_l`3Y&wu588{)IN z_>)WbL93Y!OSslOX=h_Lb=clBz3+~D-u+I`&oOMfqWHueW$aa6vboIMCOv>+j z7b$%Cbv_|x?fZr$Um{j7J-@(v+9t6i?{(>`6RsSdz?&NSB0S0`vSR(mL$-A`9jO*E zOLG?WuaSKqa&P{sS;2nJ|813Cs2*T=?DqF+zVNj}`75O#9Iws&zjuw_tI9L39C8(^ zOw5c7jEl1kG7aQ`!7Z!IB4HrbAadwb=GQIjg>}Eo`6L*6TFYSbr6^BuYLVq*5n~at zyE5Zp$dVI@$KM>k9P}-qD{8}SB?CT?ett&A|12!bOe`M^#6f%o76Ai310FW6gf5^b|__uTMlvT#ZL@^q6fgB9O19w*Ealh~*iqmfnksfBOQMJ2QO8=n zdkKZ&7g}svUMups)bFx-5!mK4cd~QzjMv)*PkXe=2Wl!w+&wVq8kg>uHEI39HGdXn zX&O(T`oe1Kg>7%5R@}RO-r<={vDgBZ55_a6U96A09=K~!vis8usv)eC)MmPwa>r}z z_eq%RSUG$5ogXHAE#b>dU(W5W;mK*Peq(*>d!F}SS^p}(e%>V)lXff#zH{k^rmPVA Y!8gC_fBY1^9OH03e8X!m>7R^@0702@u>b%7 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt b/SecurityTests/nist-certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..16c103f7446fea365a2a9b11fd3cff873ff93a1e GIT binary patch literal 962 zcmXqLV%}%a#I$SyGZP~d6CB(+$<$iUFhP~Sioq<~piEjzU`v^X(6Rl&I^vjnIl zM*%1T(h!`Po~PiJm{Satax{<==QT7iFa$yiV*>+&C~;n614AQY7}ubZL0in%==azG&=q1cI;d`_a_<;)n6>~6zr^)zofKg!|R!TOcuLePyZOd zvEsbcjrHYsy`Ptr{5f;bj_d8ZBXZ4loI5T(JhbcoiK-;c`_q(eefq7I9e>B<%88jv z4l%Qx+#S34&7T`z&wqZEDZ6fW>Wx6Zo6HWr;ZN2--EvZK{qz;vmtEo(Zr86=i7a#o zSDoVe>S7+3%Wa{O_c*t+P2IOLTBW~HB{TZ&#)yg%R?|s^(P#7mDp#)G(k&HM zJVz={diC}qTXtUM0N=pxJfAwURv)+}7r*q_Bo+PCIa}{H{k2$sUio(k>(R-pQ+m@m z|7tQZGcqtP&Nj$2kOv02tTKy)fmnlxNho*vADNAJ4i#~Ud`NzIW%h^UpWsv@%f}+d zBGMwQBK)YHW7qZYPwTGE*{Y$HA}4FW2hz{a$oQXyg_()vgMm1RufQT;z-Pe2#+A_K z!I%n6p9biu6Br$g3^Nz6P2M6E!p8Az$zHB!t3-8VzN}h0X@POXHdC!SqoU0FMj5i} zQz(Cvs1rpV>oIS7~JWdY-_S@hmWX-O48L`rCpait&Yz>)S>vp_38n( z$q&>Sz8`%$g>m`AHP+KBAL$oPY%wlb-?r!CoEd!cYc==CjcTTb!q?r literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt b/SecurityTests/nist-certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..5583f19690c7c83a5403e68ed46b9ee7c0e23c71 GIT binary patch literal 962 zcmXqLV%}%a#I$SyGZP~d6CB(+$<$iUFhP~Sioq<~piEjzU`v^X(6RlzSGsIVxr z1gI=WAvwq=I5Ry@!7VYTI90*f(Lhd|*U-Sg5C|=d4GavT#CeSk42_IoT!Tsy9pGu; z4sn2kXI@!iPG*V%F%EHcMfQsV$aAI!O^iy&!NJJNz}&>h&j1wXVrpV!WZ1WaA(=tq z=D82rCvW^Xka%zXz3JS0ew^yxA>Q5D*YD$59QE?$|3AxR_6M$wveB8?k)?j{yUp5Z z|7TvQlUWt)Gvj8nhS=?8)4x|uTr)|3@BXWuZ;f`ZJ->F*36oZ?b9}6oMhr8ww>Qsc zZ4J-K*uY)FU%W?V35lyvq%_-HHiGI3tCW_#=_ykky^|tbWmdB8^QUXv58m9T`pl|kVVB$g zrQ3FH*x@?+rNqmyjP&-Nj3ni}^BEIfylHu}QP2Hm(jlg3fir8$yXUSh{U=&o%DXuA eo>IE?^^Ee1+Hsq{o==HidA*XwdFPrna+3ie9(4Ht literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt b/SecurityTests/nist-certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..f3062e9e4803a52b6171e860e177ba1ea89be7b5 GIT binary patch literal 963 zcmXqLV%~4i#I$??GZP~d6CB(+$<$iUFh(AdBbq<~piD?7C^v^X(6RlzSGsIVxr z1gI=W0VoR66r7o!r{I>DQ=F>c>}Vh-&TD93UI(Lg0?2np22G4g$l<}r%D~*j$j<;2=VEGNWMr80!8kY9 zKO%FFJ5%c_ca=g}tB)c3B@QauK0J1Zbu+`G+bX;6ei2$;-ybj|N9*vHMMm@23(LM) z8Di+Be|AH2{n=Y#KK6amA66f~)!k{fGMP8vVb=t`j~0)1)f)XS`dg-~y6pJt<7q)9 z#`_|-w=eW~vG=|N-{!Z{u2w!3YZ^KJZes2D)TCfHMX;}#BR|Z6`;(5rH&K&G|Fh#{ zr>$6f<2T!qo!49&*)Ff+VZ6T6qg1{zZr5@K!>)s3@^e!E{bS7AQ8sI_j&t0iGn*!D zo9qb?8L@-F*wcEC9zu{v2i>i5w zX@N~1&XL-aYddhHQ@(W+_l>8ALZ6|a8YIQZb4xW(V=@j8XiYGVs# e9Jx6$=5w^*-vv9g9%!>d3`*qR) literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidonlyContainsAttributeCertsTest14EE.crt b/SecurityTests/nist-certs/InvalidonlyContainsAttributeCertsTest14EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..279306ed188999946349868615fc5330f78a79e8 GIT binary patch literal 945 zcmXqLVqR;|#58pQGZP~d6CB(+$<$iUFhP|ZLEq<~piHa{gd5sMWjf`PjgF+JRbu_St*lXdLSC*KQ znWBJZe`Zl>63l*AS7etffV^U8V$j5>gzS4pRtDxKMt%mMI2ThBBO}AQCHXTQ!nXck zEZ?(;_mWybeIvuNJ$Xy()IW46i?U8v?wx6VT3{Vlvhl_#|4gJ?9~a7=p6T&PW%*@> zB)1iUYB{UVMs@pHb}b9k@MfCV^k;2yt;JNYgCa|0i|%QDo7mcA^I~Frzbx0p=jWyQ z*d8<)=H1Mj8ZPs19iQh~8I6mIYfQxWvwKR76J^WA7d^w;JK z8$|2PH2&_ZY*`t`A<32{dZI=-lEh6DRFqb(XUjgD36FPL`0kb^T! z>B0;5|E}T}Bm_$y>DRHB*-Cc5dbn7fz2ej&%Z&8XmWI{&Qjb@Z`&)_osun(--0IK7 z%*epFINKo8Kpq&>vdSzH24W2&zU=?L>F(JoDHY&*exd-X5BRkm@YCnix zu{qAt7wx_vxTEguO{KT<9N2W#16wB;#!44-{M^1i`(v|N@`uBv*WH@#_)R!hpdRxs zBT%2$?nd0^>-#hB+Uq9YoIb}nxc>9jOHZRqPv222{A%Q%Xu4m|jLE0%=i>(^d6NIa zonxNfSfV+9L(8=$t+ZJV3G&uqjo+Qz*8REgw^&m~-Y{n=ci7^#ER&}*x9xbl+Brny Xw6$E=lD*}##J(BwXNs6Re+&TtiM3q~ literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidonlyContainsCACertsTest12EE.crt b/SecurityTests/nist-certs/InvalidonlyContainsCACertsTest12EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..f206348963c0c5963b07796860d87586801ed035 GIT binary patch literal 931 zcmXqLVxDi%#MHiknTe5!iILHOmyJ`a&771Wel9-uS?Cc0qS*+mf zXdoxfYiM9#2!s~K1_lOE;=INNhDOFPu0a-w7FrotfLz2ZZ0MO+mY9>7qJYg}S65`W zDu5hsXk^gDsD$iaMpg#qCPsb+pg0#(6C)$T`F~uOjoC5;8PB>!zIyOv-9qd4MN6{| zwY=?I`TJ&piv7FWLHl0sUZav&Ifp&|qfy5FJ9nE+lHz8ZWL_OGqBM~ip=>h=jP+bhfc zWA^T4WiD-kXVzz|Ht?CM9PK9U_49&=YI^<0M{jp*S5ECbvaEA4*Vom@XV|UDo1d(C zA+%pV>mt*xSH08E6l+PmcaQgrpM2TZ|IwA3Ho=;21RUZ^`&%x}-w?Z7*l?@xW5<$r z*R32c_nnJfc<+w`|IfQ7o>7v|dSB%%`F=|E^hU< zS!EUp1F;4XRg1&xPU)6bMf+Ykz&xo#Sm}692sl~D^0A1qh`2xf`;jHE%9&x2v+DUr zmu84QcXT)41L@~yWc<&Y1XBphKEtlcRvw}zb{fA_bY%o zkD0C07kzMa$?h(bn@MlJ zUC8=m@0+$FJodTNTjA8059SSnTU6={1#3;unMgE|3Ll3 ztmZhaaI@Mwg1tv${?u2W`C%2y`_p~u>LW%j7Y^)a-rjz5`cxLRt-M>mdQF~xLZqg% z#QwZL_rbuJ^-Inky!NZBxk{OB#VP%(DpE{kA{_JXdf)i1cWJHiqOwPp&%)Ht%eDj` L@lt3|oF)eVTT5k~ literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidonlyContainsUserCertsTest11EE.crt b/SecurityTests/nist-certs/InvalidonlyContainsUserCertsTest11EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..ecf51285fa49fbb3a50db4bffc73271a5d0f4e43 GIT binary patch literal 952 zcmXqLV%}oV#589CGZP~d6CB(+$<$iUFhP|-jhq<~piB0n#u(m6k`Br!9uIJ7vm z2&A@H!P(J3PMp`!z`zg)EsPBe45Gw&jSUQqjA2}Z91^XxF|dMIY3!L-mY9>7qJZ6M zS65{BDu6s-XlT&HsD$iiMpg#qCPsb+pg0#(6C)$Tv&N0#KW8#W3JN9HuG{mxZ%u&l z**YCJ`Cpqg9x=dQkQo!him+tfAe;5ElH`}C(ApMTde%wbjbmwT;GxEm7W3|41X zpWYw5<&#Om$G_id?>KX8V7SGiW68vRot-n&bk_1sZ=UodWd@3E4`*U#WMEueV^9T- zSXpHj2?MbPk-2*qR^DMe`%iXSNA1>m{xk2XTw(<$4Ou=GF&2^bb(->wUco;m?7cC$ z%wm#=SJ8hS194z1$tti281NbJuyG}{c`&8|6P*F00Y6AWn33^63#$P$kTT!{3Gjmi zSb!?NA;%9eO#Vx0x|qG&=cKC#&nK+Mm`p0_@8b)X>j|6bYK1a`^DExuk2zwv^n7{ z|2Y=JlEs=Y70=wgW4-sP=#n4#4?L#sd=)Nl%k`PJ|9Pi%O?=}$Iksed8@*-g1=q#% z9{F4?V)1I}t|ZA#>0izsozs1+Q{nf6F4<24Vmtjb(pY{T^$ z;OuBxB3ACfKW($d?>vTv2&I0Ni(5B{ zc299`&OY|xgQ&s}zH6?P`g(7bW>qix!uXggH21~}{->YLWvJcqiB8r_erZ~|Ofd99 za_IWaw{O2=^?1F0g;wRml2z8f=Ea80xzx)1cUtjWp2N2bC)^9tFIkaX`~2a#pq3+! z9XTI0uCcMCH=KBJ?q7zBezS{x={8s#D=JT0&;r+y<*<1LTm>C%u7iSw}8ps2~ zS5}!t!a%G+Bp~A=r=xoNb1uK_6=A={``)pz7lPA+EFX&)i^#Ht1>zq&j>c?fjF0Ac z=@GlzlgrV752T-;k?}tZ3o{eT2Lo{sUx7uyfX{%3jVqzegE1AD@(j?^9WXi=8B`;g zWPZ-5`Ez3RhGyYOCp~BHc1!=-ofZ*T?_F|ify_7N{5tuyQVw#jjHa>e+^+lfgWeHU z);|n$`W`UP*IHqH?#&Xd%q2oMlia@@pV^c9J?c)u>AOwa->EE;D>iXG7S7qQB}K5s z?&#u;Uxa@MhE~3u^mni2=96sEZS8+<7^phL{%PX%INoDwv}Wspgo=6Q1|ESN3X;;B z*Sy(rE9%^nZ>b;q8yRkS#T$K@m358V?Xlst3B8%S7Vhe|QdzD2{=rTDB{yc=QEuFL z?)5~i4R;>D+Il#p(lUMf$=-Djp9@57?9yLd@AK{jdtr&nHp5kajD;6#U!T7Aw+4%F N@8nNcg?8J!0RSAdWxoIb literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidonlySomeReasonsTest16EE.crt b/SecurityTests/nist-certs/InvalidonlySomeReasonsTest16EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..af5aa4b0d4123d842b2bda5d0bfe627c159820a2 GIT binary patch literal 924 zcmXqLVxD2p#MH2WnTe4JhzxkyIJMe5+P?ELGIFyr82A`+8*s8QhqABZwq>W}jE#QNws%dO++|y@zadBF zwgu0%GjicE#mBxBg}>_5v)}Zmz1=nYL_ye$l2|Ub=!xu`URXRim$2k9?`@91?pr*1 zB>TdS?Y~}PkatE$`tz5(q&oW zaga&q!PKtJJJkNH@0|O|?8*FzTQ`Nwb3f}VG$Diii|3^&u2VRJ7wp`*ZtlVBH_s*U zmZAm#^Quac5G;Z2KIq zV{Scnjr1oh>N)hmASOP$a}GyCz4E!e3VVL7b1`ize}DZ;c{UR>BLm~&Y=cY#d0_a; zDziu!h&6}=WL)HQRBwOI<+r^e?6-K|I~MjraC(sCV-aH!SvgZV>C*Gxj0KL<4*2`F zGX=~`PBGvE>E~x;{LjL|%*67+KpezZU=c9jGvHz4N@(+7Oa-Pq14iWN0H!-&bTBd$ zD$Kv=WAjffka5Gx<=JLa8D}kQ(oR+Veo`uQ!N!dLLDM$;FPI~B`+l;gUytoSh49n` zi_@C2l=yz>OT-xdTxa`X^eM6FyQbu%h$gnckpJA1LmDhyTQ+ZSQ{|IT71&AHBVRsA+JbuQ`Hz*jNeO0B6ovi2wiq literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidonlySomeReasonsTest17EE.crt b/SecurityTests/nist-certs/InvalidonlySomeReasonsTest17EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..59722f96227983015b5b6e438c9b72a017fc689d GIT binary patch literal 924 zcmXqLVxD2p#MH2WnTe5!iILHOmyJ`a&7$ z;OuB*AScdiXkcIngcimI1_n{$yv7EGM#eC%K^lp+nHiWsY}573D@)ADOi@6$)zuZ* zkqRJJ8=4z5F)AT@l#!KzxrvdV0VvMJ)WpchF!y9m(U$AVcc0qXrrt_c?VIY_-<-F_ z`Q4FIOo|Gpy`$MSi|R(H1%6{}e%LqX+wR`K7QIPbM*AlB z+B999Pj7F6r`xS9SKq9uu)Lklkdid(bc)ow^yH8ok*l3c*?gxODVUwqNw^c!TeIN1 zsOyAHe`?j!_p#ly%)AzQubgw$?{Am>w|oA|*l#zte!-%^8SD0}=C=GlVba>^!Tu79 zU-pT=4^#Hx34T|3Xa8M^_nn&W_NTFES1q?9XLJ6^0A1qh!pp`zZH5d@!S2?6`?;X zOOLbN?n*Y`1L@~yWc<&zC7X_L6M(62`&7bke?MYRq{r7YQwz$b;fq_{C3vLRp+N~N}qUD z@ygbWz&q}X;w~TUeqA_0+KzeF1feO1b$2o>Ft>jqsFWHf@b8h2ObfsMeQ|5EtM?@K zzY_mcEy&q^We(e^8>aJ@PKosF%kus%zRUY%#Sf+Le=Q!hDmP}9K4U!h#K70A(M(c( Kx_$A%zX1U6i(R(> literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidonlySomeReasonsTest20EE.crt b/SecurityTests/nist-certs/InvalidonlySomeReasonsTest20EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..4a0f1916509cf731ab5ab50dbe3d559edf41e2c5 GIT binary patch literal 1153 zcmXqLVyQJ~VoqJa%*4n9L*415f^4LI4DLs{5_nL>jNDHZU|YhH(wjNVLt&zyxF)v#_pbURh#JW{Lv3t*)-f zj#L1-+Q`75iBSpJql~N!%uS5^3_x)%rY1&4hDR=^`CV@M?P4}6P>5XTTt9muzp*IS z?Z;=gKM^|KB4(?5ZmQD9vmS~3Yv%kmmNVAOlg!oj`x(^{-u8dZO|8ybYbx6hbIrNl z+aZ!NGx%z&zrRlUAN&5ZY%Z@h@_)*mA0#Lwx6S*|yokvP*KPb8riptuY*v2Ew%MUX z{n{j^3c;zzcFjpH%RZXn@K?W_Z;$EiqNj5E{ysV0+sl>pZ(7-cZQQFlLrvf5|4Z1bg3WkuFSYK=V;$kjx^Ej_wH2qoS7i> zV(n4=?C#>J)dhj7TuqsCOS7il-@Nju(*kLc0-Ji1$!%|!{AFThWMEv}#OMbM5ibLI zU>M6Pvq%_-HHhp>yCcWLX8rAQhsnfXwMO0y@w}7ZG$G5!BE}*j!7%Bv_@uw#cQ*P9 z1eEWeu`=hvL<2sMett&A|12!bOe`M^#6f%o76Ai310FW6gfHNzjnjfE#EDFv+ku2l*H_GO;EYWYFFsqef=-`3=Zv z4w$)sX^xR$TK}TR=1QsGr-PF7|2*#UpLF^mOS{)W9oO4hPbcLV&waVVH0|<-w^HS@ zU7j}{&tKeB0dG#L7O))On&-e=mhCvcZ$r$o$rAC0mgY^8 z-gO}B)f>60X+1~IDaJfBsFT_H?R=Bn{PRk4Zu^@rPYRM($ZkHiZ2{+kQVClbeo>JR zzd3f81zvKTp&+qP)1>f8|DNWS*$MkgBs>k@FABSH{F>&Yw}DGSzpQZDGO39@jPaO2 zjIY6V9?!$CXMQks_jz3?AZ)9>tNz4O|0@nZ=bo7JWkPeK<657$PlV37-K*fxa*uj{ W;)TKe1%j_P?AYWIeWAlSZ3O_a@s$Vw literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidonlySomeReasonsTest21EE.crt b/SecurityTests/nist-certs/InvalidonlySomeReasonsTest21EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..59a02de9d7807fddb20803b2880dad3e0f826ef3 GIT binary patch literal 1153 zcmXqLVyQJ~VoqJa%*4pV#K>&G%f_kI=F#?@mywa1mBGNrklTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kWlrfM3Dc}|s&dN9zVCJ?&iKfYVpf?PoLh@ z7O`m4=Z6pTs~;>Zwvw3ia^fQksTnJ!;-#Z@n(vvh;zHVc=NHcY0xQBgy_E~>pK6U3O2a7^R&l5h1_g^gs_bxkik#w9#`0Z)G8 zQqcyE-BuR!3QynAd-cFjU9vt-MzdC6_NQZ_XX-yXC!8rZmt?u@w6ZnxVp74JvnMa+ z&*ZI1_!9b1>LvUChD|G-&l^u&q*;<#D*H4qI%}fNMC;8d^R~EYGBGnUFfMLl^aF;7 zmw`MmjAfNsBn-qFME0fKk>g>r{&u;;WMZ&dBX5Ry-brwpkmX|$V-Zm|PksOL&bNsN zZC}q?S@nk{bC;@=0Ut;|KO^IR78YhEmJbHvAie^NfB~NY4;xoPn+IbmF!dQQ8Z_Pm z$;h)bUNdOCY>>VnaY6i&Sc7O169wKRXvk~84YUN9WLTVod<+|zSQ88~Xm62GBQyK_ z2IMpc%v``U$H<^NZ}a~a#?{a7^l+;@PPeH4x1USfHFBC=>E7hDH;dW z#)_@qcVx3G_G`KEmpXJ5>?z6r+jm?*x8&eSg`lNuHr`k3zW!`?^bGqxH|Fea&mAc> zFA8^l=N79u_jO&JT>Y9q3qIO0I6Kz3oqs)H@{7u{Z_7hVubSBi9B1NUwioiMd66G_ zxpT_Gb&_1=UX813X6*l8^KaG}p1PS2S|>l}{kU}D%URqZrl;dLtJf|t(A^xs(-qkq YzMWmy_k7>{&$bs2Xz+Z=d};I$0FWb`O1&|MbZfIguLiRKxD+6;ABR>OBoQtW6k&$8gs!#D3)!v>CQ<80~wyEKr zaPsMt3*x^ty^dIJzklP1|D1cx%*BUQuD5$WxjgI6feovKy;YCpEs9Kkc<<0|9{m2xo^)hc@MASvj% zSRKfg~zkt_e; zAF-k*Ta;&Lq|R!+rrgo2Cv9V7y!6EaMb7o&_b!*nCtXyTQ+n>nwJ`B0K_+HK2FArT z22}>~zz~*IW|1%uYY^GB^HIn5E0L;Qk2UZ6FJQB{TUgQrP8+g(EMhDoH^h%j77_gI z@a&6Pji|Eth4t&IE*pr0^eeCk81NbJuyG}{c`&8|Q=I{$0Y6AWn33^63#$P$kTT!{ z3GjmiSb!?NA;%9eQ3B(Kk>TrVuB79I?4C8P0ZUY@QdqkzwIlETYLs4)tRs`pJWuof zn{B7oz5MSL=w4%XTk#yLb5@we#FwcPGbcEnW%;<>Bl(VHbpM0))e13Jw;hb~d-m_r z=1%uJM=!ryd|{5X_trUE9w_*JvnW;YHhH!*dC#8-Cpc6rO7E@O#r|<+Qu>ssZmlev z)~c$!oz5hZd;C`8VS{f<`?EEL{w;VF_Iz=hc7p$(eeox9{0vwOl(+i6|6!`HeEVah z+wNuUY$x~5W%0Kbu>T>qa(+<8ufmz16 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidpathLenConstraintTest11EE.crt b/SecurityTests/nist-certs/InvalidpathLenConstraintTest11EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..c28c455abbec7238869de6fe616d60e0ee8fb4f7 GIT binary patch literal 940 zcmXqLVqRg;#57?6GZP~d6CB(+$<$iUFhP|H9Aq<~piu^_P|!zVS*IX|zsq$n{n zuf$BDxHJiZoE;4fBMjukc?}H=41v(X*ucObN}Si&z|hDT#x=+w(QXR^Gl<>#o_S@7 zIhiR67;aE-bwzfx0>~GJh6YWHO2{5(WMyD(V&rE4igPhFF)}h-Jz4Yr#>zkQ4{T3a z<5}OK;wXAbd}7@LVJ5Rur>+aV#ec$SZ@3JelyWDo{{L{CO zpB^~0_IBbc?~DDx+H#Y=9V{pfnPyy_S*u%V`Mpuv-D4N?Ohe6mi;o5bH3m*_+gzB? z7kGQ$mxb&x;&T|EZggw^u5ecHmF^wCS@(OiEl*bHa7F%D14CF=nMJ}ttU;vt){d>m=AP*0sOh$UD^;ZWXub3+aQcwtV-aH!u?+ty zklR1u_x8xf#a8+oODt~hTyDSz($CMx_@9M^nTh3tfjEe-z#?G4XTZb8mC)wFmmtwtRB=bev1Xb>_N+OY{5!9o{eev-laO(KCIa z`){9q$W9bnR20VXDvODGn%%x^`=^~2O?o@MCfD~^J~BT#{nc*whqWoEIZke5k~;QG z;*9$@hN7144QH?J-fj>X`R9z>dFI@fISx5XdJ6hBel1fC^3o|W+B+qr<2B34Zkg^G z`?D=lb@z7s<|@)uidnZ$TJ!Qt?%sNjZ~^(KKefIB(!0JtP>(D2{jlKt>lgm&qFx*u WG^3V1lUn5Rao?Il5rK;mm@)vW0c-&P literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidpathLenConstraintTest12EE.crt b/SecurityTests/nist-certs/InvalidpathLenConstraintTest12EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..dc6d0dda96abdd606821e34a0bb530edfe508d6d GIT binary patch literal 957 zcmXqLV%}-c#I$e$GZP~d5E<~YacZ@Bw0-AgWaMULFo-hbHsEAq4rO5zW(o~9lsAwC zakzxVLQ;!M6r59wN;1gd5sMWjf`PjgA5YwwlFY**sbrGSC*KQ znWBK<1_f7FWJfE2d|_y0(8Q>O>~Tg`2IeM4eg>d87gG}>Bg4$d+|9)mJBst)1@`$j zc4x$|-SGSFwbzea&#zLv`10K{UyG|HK3d&tt3Nx=p?Rx-_(UUxabZ zmk?$-yZMOA!m`EsRS^{rnYXS8J^0dD`IOaD{#G}eb;9CFEk`TGmT0U?5o>#`;rC@m zzwV~=b1ZzEDvKF)HS<1cKQPkZx}x$gPw?r^H8;8PYKo02_4!v!_tk$cBBI4Fr&gx- z`+;NKP1XsfwhpEHZzldKe9=(MbNWlG=ymQU$M#dTo~l82?yOW;VWHY9?524qt*5)W*}w2 z2NK{139tZFd_#^OV8R5(45UV#%42H3 zm}sow@LIIiz4xAVjOEPMSBGYJrA)S4w|Z|56Te7T&~d>tj0N*MVy3KUbyBM?+}5R8 z&C+TuCS-7r?e#A!=V`mNG_4K)U+_97>$BP2&Ynv^^5Yw>Lplj!U#;eybb6G%j6b=~$J<<9%_m@?NG^6>3u^DSC7-97u>77NqN3|Gw?X$23I)*aY!==7wg gv5G#=PNd4-y(0Cf>#9wdsMej|PaAk%`>tpK0GFIuEC2ui literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidpathLenConstraintTest5EE.crt b/SecurityTests/nist-certs/InvalidpathLenConstraintTest5EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..b8830a2405533a0bda0b7229832ca714cb379870 GIT binary patch literal 930 zcmXqLVxDKv#MHKcnTe5!iILHOmyJ`a&7@71^x{Ajg{;G%+e6dzX=wfw_s1p8+V&#ni;e$Z)<{s!nc(YQ0r$Y^~Qd&funq zOG|QnzFu6(6q@p8?O%zb1(PxlY*k2f42YFJ*lbqyebRy^^-brkHV5+_37qgw_`SHJ zen{4AKRc9o$fRaLaNi9m4^jHl#ADxr+DtGuRba>r}1OlcJ(*+zZ^*FPI`Zs zB{I@n~{!{u4p zcS@GzBpis*V`ER=*|$JjL0#7?n%mKAmeadkB8rzT$Rxe@R`})fFTUsH+2(0NbDck# zYkmIMqZJh_a@Bdo^bc=V6msUASyiW-_QO;lUAD7vnexuP3fnV;A4smfcj!cvEkn?T Nd-rc&V3E~O1OS=;RgeGx literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidpathLenConstraintTest6EE.crt b/SecurityTests/nist-certs/InvalidpathLenConstraintTest6EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..b96d3c626fdb7b9f6a6d2badd6d1c450dd4a7968 GIT binary patch literal 947 zcmXqLVqS01#58>YGZP~d5E<~YacZ@Bw0-AgWaMULFbFi{HsEAq4rO5zW(o~9lsAwC zakzxVLQ;!M6r59wN;11n>lbjt5Tb)!S$JZ;{oo=;q!Uck}M{!hnOZN45*jPf2;ZmRs)W zE#pYGw|cT~>^|AfarEn7@@~?#OA~EP*~PXL`UT*P`T8tUEq!PoF9D{`1L|H;Oq7F0DAFVC2?e+`-!XbZgAAlCn%y zh50dS{|N*hGv|tVEH7ZfqSDS&#{KGA^RxAHANc+;<~q8-FPA&~(_$uOMh3>kH3n7S zIF(gqkuVTz5D`gA7pT2tezb_~!oB*fVzQ?e7sr89g)AS77>mf?&X|fG& z#p&6a!+X>j4a9*FB&)z8V8CaOm7B^2K*oiVMfOPEUX61K+1p*B)|_6 zU;(Q5h8#b@UCTaqcv$k$qnY_gFaG6)`yN+GWWk|gG*Rf;afe+#zRw!&=$i3_9?gd7PlQQ@2 z4}4rSHKW72Vf*T&LpvhQ*7#b4hd#Yq>QfVTM&R=*G3SNtttNI4I)COdvFZvKCSS!*X}kk|Z_nUC{+Y`P-K`_z4&+N4L{ZcB`4+B<>R!t?#_Q@W!&FU%E-J#pW6fA&3fr<|i~w}#MHfjnTe5!iILHOmyJ`a&7*v##4-yehovUir!O zF$R364H5#?_Z{0GwfFKY$3rdOqPkY=aJp?c`n<_KdY!0#_>bM?oF;xTOH8B-*Y$b% z9yR{AWy|BUN`e8;HWn+_Fli-e?EP>+aM}IE`llx++9dSt-~PPy2OJt~R`!2hYPflq$*v3$wF`H>{E}LYwfMiy{H0-6qI2)VtLI1G z-uGUdJ+Jz7#FEA@%x6C+nXgW`mZe-NcV)`EuC%u z7iSw}8ps0!SXP-u!a%G+WY^9|9pA4+s&+lryzjq&&EjrhNfS6}$nvp>v4~VEA5-G_ z`oG1)V*anB&i>miNRd@v9P@fBDE4EPLq*tinfJQ!1fiO>K& z2?C>oks;v9+B3CG>(*vyZ=0kQ>c?s!$)BM9)8&BbE}efbf7m6tOv{;B6)w|bo;cxP zv*2{q!p{LQ_gME#(tH2Z@!RZqYsCw;CPhgo{eGmfYCn&?lvb|y1^M2xiP!Gsr^J7E ze{$#a_N!4RShgKmzSO?mMJzJ;luEk9&$-Es7fc`J-oCQ=)caqh6Tf^tx%Ypeb=ow= z-G|M^Ha=I=o>P2D>*jhLz4&EMvrx(NNSfFMiaCm1U{5###Dt<{v{!gtqc_Ffa_tNe@Y+%%bH?EL8ZF=P2HRr8b0=c{ye U6Zy8eU6pOH+7TkAo@iSG089^PDF6Tf literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt b/SecurityTests/nist-certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..4a7e31caf02fa84e04869fb54f73b5dfb8afbf50 GIT binary patch literal 926 zcmXqLVxDEt#MHEanTe5!iILramyJ`a&7d9><+t{ctCT!3Br3Pg}BQYPJa8f6LIOC}O?M;OHkgtBV#14^o|u<=DFP zH7d-$6{mA++wr$?0is`G>W_bSWp(a3wNSMBgktK>-P)$hntE22I_vX(Y_3_OpD8;1 z&pEfOj(cs-s)VF&<+=ovl=t@UQ|^7ORv5C;`m#yV8sUwn{bq9WFt{I@9r1H^?wk2* z49^w(oBE+bQ$klgZ|a&07o0Zqn5RYRF$(`Zq|-iOqCw*yl_!&qFDNO##UF228NWkk z#{u^A9Ht}#rjjJ(M=y4Lm?b`UWr+CP_~{C-h57w$!)x|jzpKf8PvVCjtL~1;Ow5c7 zjEl1kG7aQ`VJ)l7B4HrbAQHjYq9VOVJ7|iR?NWgvk-)F(txkedge)J67>meNrq+4E z25Rmd)9U<{CyS*_`7E&>oE~KP85#exurM>Rd@v9PnWw-4Oeh9CY+MO#9*n8Lv}eGG z938-v2aFCz28nKsS;v2=@lLQgGMicZOZ)8U9WuAx9J1WgJaOBEzwYafZdhOIx&3(b zjl4VCWiE0pe;uJBdO*OUOmgFutA{?f{9kKoCa`OT*cpGTltAp1u&>P4vE*-G}TuV+u+HQ#h{$>R3f4fdPzFS;gQ z)t;8582d(bs_g1Qhqtn}vhtHp)^A&F*Erd&z275rUh;z93c`7@zZbHXw)8(0IB&&Z z`Z6u+6L&bX%?EGe*_J-;A&%O6e*!s^!W2Z*;Yi94} Yzg-h_`h{k1uY}^7yK!qidtaRk0Ph-BApigX literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidrequireExplicitPolicyTest3EE.crt b/SecurityTests/nist-certs/InvalidrequireExplicitPolicyTest3EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..e9b7cf2510f60e8e77970b35924220ddb67fe9f1 GIT binary patch literal 919 zcmXqLVxDZ!#8kb2nTe5!iILHOmyJ`a&7B=D zBs#%7hG9gNKS94X#>^}sHlqn4b-Qhzp<>^fRMDWsc4%Jo4?+-ITwOX`PH z?p2<@eS5;mlYDwntzXYp@!#|83oUq?p!YkVZe~!h(wVn>9zQpHGd|k=UT3G^4BzJq zW@s*)cYMV$#((KA3V*e~cYd?BOmXTJ-3c0xHeHbxubwyia7%P%Y4~%otoxM@L;3#p zT)ukt(+Yua+YXg|+{~AG?MYyZj*Fo{;@8VdG&eF#+bI$4bt&_|d8H+X#?9MbnV1Ly?nvX4f_8c&0;L7GvEX1=VxU6&%(mY#PR_-)PYG380w4+;kLi_{Qe(!X4}Uaz}te1;-McN6EQMP8q{-R7pIexvc+GY4E0GB-->I`r`#4f^x!IGfW{n-_;SPOM4W^Cr9e`LBobC8w=6DerpMl&aO_oS5A9e1FW5t49-zTGdMx zTG_=5r!FcweAMYkw{FkhtUiW8M>$lLW11$CsU`Sv)P%`kUt@ E0QdNDWB>pF literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/InvalidrequireExplicitPolicyTest5EE.crt b/SecurityTests/nist-certs/InvalidrequireExplicitPolicyTest5EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..971d0a5de61b21859b64d4de8a9ca424eb48ee11 GIT binary patch literal 925 zcmXqLVxDQx#MHQenTe5!iILHOmyJ`a&7eodXrUn{y6&U<_9+!;Gr-WpE6-D!N&R=j;8 zJZZX#wDY`&zyCgEy(~WALh#*2hD|#(7%USd_?ki<8QML|d2hS%*PEKzXBeNig>EBsEYgveZ3CMB&J%>rhffBfTPBt_eR-YUxOd@$Cobz`ZF!39k3HoW z-Nlc3g*`OG8JDr|*}#4Mp!}o6`hv|z&+eF-B9JDKFo#>y_wAJn3`y0GPnRil?q=NS HEUn!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz>h?0*bJseo`IMbtv3Oe7ukH|`(08lSv$E97O=Y?!t35Hi#!?Y|>Tbq9P6?yR#|NjM zzm#&hJk9vh2GfIig7-M0_q;k+J%#PM_FYS2?MbP zktenB7h|Tjap$Bs8Au_=4=|+x z+}`8%~+u&SO0}{cd-A=q6{an3b2pU702})SkCYT)pL%l%Y?F^v<)( zZ#3*+S$9x&r7EBHjX-7YOKy)ZKWY6ddT5P`y2OMev$%C`moD?BaQnUA_x(vUPiMxi ztV<~iw<(JIdMK-D-2Zvyg%*p|ujk7q2%OsYelMf?mcEGPE^AIcI@I&6Cw>pdPx)=u zH+g4NUeZVuFO%u43Nfg4FP*1%khdY-ihavR)n%H+j%ULwOC{Bh9qF#$*eG&0pz@K$ RzphG&`+pDmng_<#0s!tzQ}X}- literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/Mapping1to2CACert.crt b/SecurityTests/nist-certs/Mapping1to2CACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..4b70c9a4fc00fdc74f469f344c92b933a13eecc4 GIT binary patch literal 960 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/NameOrderingCACert.crt b/SecurityTests/nist-certs/NameOrderingCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..f1c4a55fbf53a95eef94eaf74b8d5ee766f2dfdb GIT binary patch literal 980 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/NoissuingDistributionPointCACert.crt b/SecurityTests/nist-certs/NoissuingDistributionPointCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..c4f182ad7f9771eec58373f4320d23f4db7e3ef1 GIT binary patch literal 919 zcmXqLVxDZ!#8kb2nTe5!iP6V^myJ`a&72-Vi+xYiuWk{QW`Cs__HD&x_FJwKcJ_+@+VK7SC)=>v#R|NZvt(ahOFP@VC|b`t zVOK@Q``MW{&T{O1=eg_gE3K)fC*D^b(zKfvY1JOH^UH#@3s}B?-)J&xbC&AvuZ_Ex zWqvt(sCR4V&&Zy4Q8lv@Idv{(D?9WUY?xd5%t$DxtR-rh%d@kqDq^DKWV6VzkC;%nr_C-|Lpej=!f<{T2#W1Z#`XS8JKCpy{F*eGZC>BM;@6@TrJuyY;+>w z+0QxKmME{Z&uD+tKOsDpXU6{Hrt<4P8f5(}{j=-bnXNxBIX=Cwd+8TvWlv(HP|M%O zkH^o}UF|=&EB~k5hBXrHU)~GmF@@gsh;8MmU-Y+GHFdS=)P>#)a-613Kf$v4kb8g0 fQr3T$E-JNfOYUfy;?;jiX|7;ZB=ebFyXOD^C$VM| literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/OldCRLnextUpdateCACert.crt b/SecurityTests/nist-certs/OldCRLnextUpdateCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..2666670afb5e8eaf3032e9ede9a7768e2f17dfa5 GIT binary patch literal 910 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/P12Mapping1to3subsubCACert.crt b/SecurityTests/nist-certs/P12Mapping1to3subsubCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..91fc36a7273717ff4e09012fc0052f4d0e81351e GIT binary patch literal 980 zcmXqLV!mL|#I$1pGZP~d6CB(+$<$iUDLrhr*kEWpr6!8fs>ATuvr!LTIXSfRKy z$=T6BPMp`!z`zg)EsPBe45Gw&jSUQqjA2}ZAQCN9GEe}yh*?+?n}rZNn;4al{l&=2 zz}&>h&tTBR$i>ve$jGo&u{D@Osx!6q=~rceJ*@7JgdDdwGWBQ zGefWaZ7)zv*hf)TY^r9XDV`v`%79UIB4Z)9Vq*m_}JcQ#)6wA(eAVP zD>sJcC?9XSaOieWqZn@>`^_2qyl_nDcIer$OZB&} z_nq&x{+V^1b;Bv++^nztDpxTT}EH+V<$ zv|W9^BGngCP8}9b6)s=Hv@!H=bwrRh6EhlwW)vQaff`7eB1oT% zfs}y+l1dgNHV1ON0@EunUKttG7r)yuXU)2^TJKrKWGB`aiBx@OQ{46YqPNb>{hRV8 z9`fRRWIgTMiidCA^|%8vgmyPv`_z%Z?pEOx~&Y4+ou?HO(s8T4TYnMu$gN zW=**7ab4`*uiE?W(JRxnyrgz~kyu>e9G#He`K&1KWx4LrOIZ&zeAgX= zZ}t1VenoXAomuuhuy&)c(q;jq?gi}EKdMQyJ6!1 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/P1Mapping1to234CACert.crt b/SecurityTests/nist-certs/P1Mapping1to234CACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..3500737ab8e8ede4abbef3afc4fb43cefc3f9d93 GIT binary patch literal 1017 zcmXqLV*YB-#B_H7GZP~d6QhvB(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`Pj178xYku{KpSR)c(sNkDeP>`9Iu3%V_Z)9wu;OuD7 z#HfVq5k^)9<|amd2B0_>QxhX2!wcur)pf5d4Q2V)gg7{TdYdl%fA3Ba#*5qh&plqK zFkdBFw>Q+E|L5b|0WuD9Y}E%R{y2Q~+)kBZei4_dKU}=DT&1jY*lt!>_TCzphmkBpnNzXL~_P|Js@P#rCXz z8EXoci~GEhZL7@xTNw4zC3uB-^{Q`+I-kkijl1^Fw(wFXhl_JznruSHQWM5w2dczx zG^JkkKm6cN;Eu%-kq^H=o%w?!`=!;E^sib8_ogy2GcqtPZhUUg_{2aS7?85cED{D{ z4I)o!<1fZcZR5~kUAM1vTk7(gu`ANRF)qu;BE}*zm78&;XT_?rTlJj0YdS=Je*Nw~ z$$$@}pP!NOKMM;m4Y3)BgZK(80tS2rJZxMEZ61uNKyd>`1AdT%Fi0V*0W**SN&^K{ zK)eP<27@RNPZ1;?VBlvUfvgpY&4g2i8K(>ja#{c;YG7JmWN_s=<(XHw^ecl&NY(=50$^%eH%aY#-E= z-8tN6tY3DlVMf)AvytC#8eUm&)S0m&VX8NO$6MoLpVQ4B$v<~{`9Stqr4{3jB(+$<$iUFhP}V>iq<~piB*0L?H?g1~GcR4iuq5Be z*hInE(Lhd|*U-Sg5C|=d4GavT#CeSk42_IoT!R1-ty3_NgIFhyXo*g-J zHR#0mS`Nt|_U8ABTb?hfvDh{%JoOh-8JowGdL>J>W0g&94F^ppKB$*myr99+YwN6q zJ?{!Oue6hicC}(OUe6aECiG@@=ZR~+R$gJ80q5qJibySsRAKJ>vS`Z9t-JoE&YF2j zv2u5|BezfhQ&!fc#`1!r%}S}?Zi#-}xlPGMK?oyddM z0f{@R56rat_^qhLKE3u=#nrt^Nj>{QDnD-PuC%_J@JsB_RQ}~GmtUhVdF|@^I%K`Dl}k1;jtJvfRrhM z^qCo$7)T(iL}Ig|$gm*Eup!4dFckx19O%iMc=_~avrb&(*Ip#CnDH)OmXo>0bT3J_ z9mlTasWf&)FPK{;f^ z*T%d|Yx1ew*(X2SS3AFUn$K^&^~d&-ii9P{8^Zb-S6fI|dr#Ug{X3YkMC#|ak~x?E zMPz=z^rg7kuTu5Mq@oTr(<3J@9ph%Rypb={+BfZ!)$zox=Waiu=Sv=9w|_r1{Qv2Q z1vc9g9vJSE>j}^7k_Zbw@~39^`cs}$)dYSx9<4}!a@jY(+{vIJdlqkOM)9e|^B$dJ n(+l3+JI7S#AbXoU&s*M0N*mdD_`g;QuiN%xK>&-*arYJg&KqdS literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/P1anyPolicyMapping1to2CACert.crt b/SecurityTests/nist-certs/P1anyPolicyMapping1to2CACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..3818b6a7f5193ef14738d6989e2c355159b95d7d GIT binary patch literal 1329 zcmXqLV%0ThVi8@y%*4pV#As%~%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXAcRC~R1B0L)<_2!CgxQJ78GRWr7IYg zfKE9N{7DL z_wTWaKVQ#$e(AIWs_QRg9cwNg`(wD&d{_Ri#6C-&e#)#T&C zGT#qpmHzjSOPld**`l9UC%hGwJ5;F=zwF~x%LR_bldtbun)CeA4$d3KQBt|Jb)T0W zIlOh(H@&9(^Pm4lGQCs%iHBK+Iv{FzA$;d2L z0HTtNRE5&w)FOqv{F2P%RE4yn{9J{?(!?BKk_3ucDkK&c=OzK!$e9ON7yvU5BLnASYol+AzFv4#^fx5s$_2~AZ`BKIQ!ID=69uZ;IF2ON*%x>mK(zOGc&U)XX>;n^#X`KEF3 zb!E8inY(hnpJQo}V%W`ToEI}*zX~o^one&QvFFui!6mwL(!ZxZe>vsZJ+97$<{@Iw c4c_Y2oNFm%FOIG#ed3^Sx46Y$e`z-x04;>%ivR!s literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/PanyPolicyMapping1to2CACert.crt b/SecurityTests/nist-certs/PanyPolicyMapping1to2CACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..db220487cc05a1fb94077b7a3943f3693b342098 GIT binary patch literal 965 zcmXqLVm@fl#I$k&GZP~d6QijCFB_*;n@8JsUPeZ4Rt5uCLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`PjgJ2S^Q8rM7SR)mXm{%E)pOcwfso`9Iu3%V_ zZ=~StXwbx{gzOzgRtDxKMt%mMI2ThBBO}8*?Mf}KrB-=Qnq`0AQ_m^goENG5ZIfQ# ztDvq_jn9ANkGQ`%wQ-mExc0MXUcJgDF7*SJO}mzxDTb_i<;QSjtC2M~&ukqd?K7useP-@u zWn21LYe#A)=NEl%pUwpIm^V%$iTR`ajik)Dg$|7 zaLOvPNEnDUh&-u{zZf&MjYEfZ-M-RosmpK1u1EvNyDT4z7>kHIv%0>s?NR-klhz!+ zRCdAm*w6Ca27Dm>{EUqMSy+H6iOql?#1{tfSq+$hlmQP&Kn28WU}P{51o0GDxC}T9 z*w|QrOa=orkdPushm3)gfdm^@LYoI;D$p9a*P5KC@@AD8GN1z*VxClQrPlcYE*{GJ}X!eDrU^_D@@eYX2CKeYazms&RS z6vLsLvJukL-kKlee4x^{JndM#7mv#8GVz`2dqcAog5Bi1Z`3`#bnJ=ssh6`Re%WzT z&*G2Ep6G|^t)_e5DQR7=td5cs_xmB=QZe~)dtq*UUO?e*pIM!&e?98mSby2z$gXn$ DomXZP literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/PoliciesP1234CACert.crt b/SecurityTests/nist-certs/PoliciesP1234CACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..36cf4ce24ea9f01fb8f333080559a460cf69a341 GIT binary patch literal 964 zcmXqLVm@Hd#I#}oGZP~d6Qi;LFB_*;n@8JsUPeZ4Rt5uCLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`Pj11}P-kus2gSR)vapOcxK3A8={Xr76Jv!g*1qY|<& z7+D#Zn;7{SfZ|+CO^l2TPiGr+{z$%g<#(jN*=zgYhhbqS&*?N>)D#SQ6TU&(;4!Ov z#`5x(`dXDw>-p|&wo3Hd zuyp&wv-gP1i<1BAKFw4`W)!I_Ac~0Mqo==g6k0MQYa%wzGKJy*S7Uy)loDNA;@N`L_$ zNIyR#<9`+wU;<(@;0N)AL3~yNW*}w20}@aH@fsKz3>-l`1r{p<3!ns7LYoI;Do~pN zBMOfRg~yD-V?mBtVEP2cEF*)B&ZFL?`(GOFIy*DRGqKEN)f-pE-7AjXy0Y#_#Hl5m zA3yxR!dAVf$Fd5^m*-AO+$}R&yzS=QKPRo*>ez(3j&q*85PojW0-c1uZ|#g5Pan7zXPaSV zJfyPkaaJIyw$GOd8eRHkU^72ETP(mj4%&C}eJWkd32UpZVi iL$q!aW2*9dRvBB{G^TA?Z(L`xt4)nu+gWml%?bc&uWg+G literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/PoliciesP1234subCAP123Cert.crt b/SecurityTests/nist-certs/PoliciesP1234subCAP123Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..1ab7ab104f656479536dad0124973f23ede123e1 GIT binary patch literal 948 zcmXqLV%}iT#57|8GZP~d6CB(+$<$iUFhP|838q<~piFd#oCGdU9|9$;u>Y@*=o zXdoxfYiM9#2!s~K1_lOE;=INNKsgxKAdp166bd9`<{= zA|IXRZe6|F_{Mg*C7GA@?)*I2TH#Xp!Ou;0dow#;tv&r(JuuEB_tdPYXDi;M{#i1w z>p$bQ7s8s-`{i#xH)ISDx3;>wT%qj$r<}yYQ}V6gF4n+Wf>?`sxqZ!+#yt~~W;w(7d{Ugnv4J?E+EQE}!4jz2Z;7-=<@FozLx+nV1d%*Mv zj6FsMe);xyH(M3orz@;aJDRAHdscnLqLXiJ?p6K0E+p|K^`q(mwuE*64oQg4neSG# z$=8R==Gpn#o-&IZ)P+2GCa70js#W`DaYChS(oXG1X6?+I+4;)aFC1?_^`HNLXTE6F z$Hje8hjXqYzmMUfAb*r-p5Bf zRO%K@43hdJu_G$y1n(BZo6Ec1IlbO*`5+;AB%Appcfj?|H@{yp9o`e9D&H*kxoh&F S7d;n$Wz~1&Oty@++YJEsNn4u$ literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/PoliciesP1234subsubCAP123P12Cert.crt b/SecurityTests/nist-certs/PoliciesP1234subsubCAP123P12Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..df834464bbad670ff2ad805f1f60e742a0388525 GIT binary patch literal 947 zcmXqLVqS01#58>YGZP~d6CB(+$<$iUFhP|-jhq<~piA|O8}GdU9|9$;u>Y@$$H zn&j*VVj9Sa^BNi$7y_Y%v4Md>lsK=k0Z<&qH3%osN_7KOh?R1fR>Exs+HBCosD$i2 zMpg#qCPsb+pg0#(6C)$Tq8E4Fw#EI)-G6juiFxLv$wzJOUrEp2;`g`4R3_8*WV3RX zd*lPtf|?oneZP0C*V8oIVV#nkF-`Q+!aVtKcaD#t0jf^j3x2;*o^3UWF?!;oXia&U zb!y9g+}h(*yWQ)YWyL|ipBYM1{zoqTrM^Vw$61a$X36}ABhT8r4L@__YQXV>2g)8M z2u)z*NZ-FwdCkOipIrY6)g1}k%65PH%q>66PuJMxt1rFA((Ow&53ZeCd4QA4YKF@t9eFkn z_O}^E&op)(-shoyU*r39fzhxe z#mKN{&x&iu`JR8vnt4BXRmoD>_Oz=T_Fq_>d^mNMpk%et`v$op3#0trPA)Ue7;LV?XJ95Hw~6!kdzUk8{~XpiNhP&B=r;1*WgsK` zXQI02r)8Ycm*ySaczW@RQlUQQPO;myt$m$sWojET(@yXI#NM?1()C02TvLue&Ripy z(SGkS*Po-h<%cc^UuC-f^k&cd9~ze#oc_41??1F`NAD7@t*dl(RW5ElZ^xG>@ghuJ zX4AzDAMd|9+}p7?Fs<&xy*!B(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`Pj15XmIku(s8SR)XSpOcxK3A8={Xr6+zqd^m+60#>4 zSs9p{82K51;#^EkjEoHPYaSfylB$pw@2~E+TfgC5#+UsnH@g$lO#j!j7Cg#ddtdX~ zH4mW~`|~*7yqF#~Kjo*$_oKON6Fbg1FaCQ~ewNr#CdnN$wnlTBW;kbhx)q+R26i&W2^$G89hy>;LTh)riyWOw5c7jEftW8#FF4kOu~$tTKy)fmnmcliK); zF;m+(bXeEzE8Uj5{ATQmG;nOo^0A1qi1cW1-QwjGNqT2%J8ehdWTDPiFOm)TK>GO^ z8UM4e0Mief0Y8W@4C1pIFas$A9*}?vh}Xc#U|GR^@fD^FaZ|^M?;wzk4mHS@y;FPu@qnXgSx6`+dhH bx|N^ltoPt&d%{1l%Rs|Z>1)F6xcPmvYv_IUU`-!zvqQ+@bRI_C>-=2TJ z0_rZQ?ltGUpD!VBenINo>kbiYHmU2E?UyaOeCf!weQ6VaR{T7c_-?`^-Iw~6va1i@ zeEy~F#lAv?FO}cwox-1=TW)6b|IYoZ?DzPJ%5S>9JvP6Ued>h5gX<F9JM>?7F}pEMC++od8(;G_(@j&ieJon_GN9pK=+#ts8{V64e1vq%_-HHh?RaNXkN z6iIq#YddX6;bfuCS1*#m@h;29BE}+ej^WndRg)cl99U4f_F%<1+3V`x<{9vT^z$<^ z{%2tUrX)54eh^<6#Ah{N22uv9AOQsyIRhC39yYFoHV?*Bph5#i6dn_Dd;yamFuoWW z!o%mTnyj`wDPDT-8Oy^T?wj9V$j0XR_sY~w@vpW$+j^j&W6k5FkKfo<-{p7yd|1A} zebvRiHtSZzO`pIeYuIZ3xGdd!+ppW)smEO(E|_x6^TqN*hghAC=4oEJU&TOQxhX2!%dDS7WOOEQtzHS)t>&c;Y)zn`$ZT3S{hz|Zg{FVeBMOI9)sFL zt{lpj&G$4vu6Vd`yMKjf@fO~=smo6@aXIglViAuBW;=50oB00f!!~PGCdwYTwy(&B z$M5dyt)7jrDi=9P(U(ML|^h|tX-Ic6*-@#VtWuWYsj&HP7PLw=RmdgX*;*=&rYno@%Ex|J?q1du|g_`4ER9$`577i zv#6gOZr;0H+vgA}qFFas&%_yMLoVEiyLbQaZj z@x@<0acOg{!YlfeNwS<)4U$`%l9H13Uj}QD{a_vzw_NL zHj@w6Yi3;XD5|M!c(PzBTUBBr?}9Dm>{`O1$_!_A_qx^>|% z7n|+4SG!Srjve3Bd2_3utCX5K8gu?mZ09}fx-EhAPgChlNilCB!`Z98dWu%LZ?gJe zdi||^rG-)D@_p<*>Lp+EQdzrM*3SIz$oy;CvYhB?y#d^NPiU&d?|GuFmAmoU{q(K} zNjw2L0@-c3`70#OOnrGFVGa9{{j+|!bj>bSd&QdCaW%FvB>193mdD{sqKhj}C0`1; z`1#_m+z0F-8RsTm-S_aIumY>}y9xT%X_4XDwq?mSy5hgqo-`6Pw=OQ@T0U=uh|`$~ zb8kuWeqMF*+@)l7i^z_1QZX8?Ow5c7jEidwstn|Tp((4(B4HrbAaai3*56f=9ex~G zP`UPC#W~sQ>fh#p6M!rqix`W@%Rk%V!bJSoWG@>1?MTQL_`xcjX}|~4&(FyCpM?dO zq}UAjL408lpVfdFNEwKO1Qb{V4EPLq*tinfJQ!1f3JuUx9x#3w8GPq-cwSw)OH4uN zMhlyrwy}EihK%dI`(!hwdU5`HS9Bz{xOx9si3>0E!)6vv)9AZm|7MSZ`;M?bkFK^o zU8Hg8T0z&oyHY0?#f$3mh!%NlyI*%HGGcx2(o>F|e{(MQ`C2Y1@v}A9bwTy=?4X5{ z*gtUGTqByJr>c9Q{D#&!^)1|YRP+wz8lRD_|6`gtZO?Q0h@Ej8rfSS)K67||?WH_b zn+9Y(!d3-s$KziR3BVUnK z$uDpE|C%#X(e}rNJ5LWgzw+Btcgd5sN#s$g7$ND^(;G*E}ws({T_gv9}d22G4g z$bMvGWngY%#rDziu!h&713 z{Ie}COvH~(_M*|>j)ZK1AFR@u;G`hS$0Eie(y1Wc@_Ws0&g=K$;^t+1vkZ`T=rG^| z>E~x;{LjJyOk8XR;vl{Pi+};20S_BjLYoI;Dp1^j(SRQ$Aq-N;YQPMnkmCoK27&Rz z$WUy*;vHK{1jm~{;?_-z{(N|9v_IzNl&uM(2@k)|TJdVhUq%7#Nuj%EvMyy}Phra)Tp-)rpO7ZaeDSJErpM=*qGu3v@2LtY6Ub=3{Zw7t{Tm z?|hhjr(C*F)Euye&o99?+GOXmwCHh-5KyAR*>#g?D{HRI{zuhaOy-*P^2U3l#x z`8E2v_unbnH-BYMUcZUEdF`X;59DurJ9t5~&0RI?_w&d4MdfAx<`m9ev~)S^3;~O8 S=J(<*@3+3mz3tReJ3jzeB5(Zw literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/PoliciesP12CACert.crt b/SecurityTests/nist-certs/PoliciesP12CACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..dc1b60de0e85926c5f12a4279ca12d9841517ac7 GIT binary patch literal 934 zcmXqLVqRp>#MHHbnTe5!iBZ*nmyJ`a&7A1X>?pXr$omXwbx{gzN`K zRtDxKMt%mMI2ThBBO}9=+!J2=*2TBByzi9_@>99n*I{tYJU!#R+jTd#OD^XZp1OT= zmS`?FyYs&7R4vII|+h z0{=yk0gatZDR;uAU(exii`nH?ZZISK;_8W4msdP`enVG(%L3cw3V#3BYFwF@ao3ow z#_sP*|0}IC_XW*Wp4OeYBg+1eZmd$tC*P#g2U*VPRMy@|=rezD;a$$WZ3dg3JigTZ zO>P_W)~=te@~ixXH#SYR5cjOmV6{SoLr3vLte#X-I^@4H~Bz$OFSrR+$ADm<=LNYU3}) zOl{-PVO_VcbX)53o3Sg>z>zJ>$0EieawFdK(X4~!T59K-&lK|&h-z6qGBn@=>E~x; z{LjJyOg?M|{2;zCh|g-k45SQrKmsZtUIQb8fhvfnz#?ZL1C-!OX!Br91!^;3MBy%^Lx5EotuJ%qU+*0SxCKmbNh_Y?#?6+OUS0bz)h|2Bwz3jsx z_8+T^RKhszQY>C%Y2JIaVuQpt?@GzA590iX4+Nir#M?&s>y}mZe=H;)0!79_w zpPit;am$`pOJaOWC8HQ`&VT#lr=iR)^~R=u;r|j=Rk<#{qs#Jmy2)el2F4?1kDqUB z?bQ4^-R9fhr|ZpcY!TwyrzbG$aSmsHl783jg}+$+R*LVa*m2@yIPV=9nF9ec*a9<{ XO0G6LEZ2Qfv6)#})3ZIe^3N*(v2a;C literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/PoliciesP12subCAP1Cert.crt b/SecurityTests/nist-certs/PoliciesP12subCAP1Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..081f951b80d946602710464608e74347c20d5215 GIT binary patch literal 912 zcmXqLV(u|$Vk%j{%*4pV#K>sC%f_kI=F#?@mywa1mBGNnklTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kWlrRtjDPR`n56I8SOwI&~2N)VDI6E51 ziSrs77#ISfg|UHwL6kVJv4NqHF^p^AOQKD(2GS6lL{MxhE=_WF3@|ikVpKx*3nME7 za}y&!15licsfm%1;c%Z>?Umr>MfpEGofbrOZGEzP;ftG|ybC7Y{@8n3B$H`|EyYHHBgmPH#>1zgjApQJ|jQ?3! zfQg9BKpezZU=c9jGvHz4N@(+7Oa+P?FdFcKB!oclz_H6TFr9V%Yy?f7`nXF4U?#oMR^2*|>*#6SZZsEFfQ`VfGuXoZU J!z5*1EC3t^T8RJv literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/PoliciesP12subsubCAP1P2Cert.crt b/SecurityTests/nist-certs/PoliciesP12subsubCAP1P2Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..e8d0bb8ba8df7afcbc10f400388b5bf1418a2ba0 GIT binary patch literal 922 zcmXqLVxDHu#8kI{nTe5!iILHOmyJ`a&7wY+_{=5IfpU~gOrDqze`m)n*Jql^?|RixqPPUh*W-GbMiLp?2r36r(SIiWb1F5 z>Dm5~bx!5n1KWfv?y6p~JLo*qY^R@q_@R?b%!~|-i)#$34CH}fDXYvPVIbBZqBQS1 z-wuy+oP1WX`>y#$D2Mf)z6OqbSw0pq7Lnsi&6i*JrSi1q{_Rh(nYZ7a`Zn{O0Ut;| zKO^IR78YP~Vl&_e@r6NrRs&`rWgrd`P+$=-;4|Q1<4S1rU`z!nG+;uGA7H8j#t$Qd z_kQnL?97{^oEE!y&$|)v^2$?=w5{huu3ES_?)(=Tp{HiORMv1-X_k;&la&njq|WnN zz9;RLD5UhixZY@f>#%sVTC%Lq?asO3KE+OfY}djiUVdMz^sVWyf6})Cj+J6TTP`y^ zzajQu`0i&=hE2D1S zygW5{Rv9Db$K>O4zSl=<%YEGQ$mT%hwcabM(kr*;+~+_OxR{Q`2L}iKq literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/PoliciesP2subCA2Cert.crt b/SecurityTests/nist-certs/PoliciesP2subCA2Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..c734009d050a16df7d6c8242d37decabbe8cfeb6 GIT binary patch literal 918 zcmXqLVxDBs#8kC_nTe5!iBZUamyJ`a&7A1lk;6q)=R%O>;pzt z2IeM4eg>d87gG}>Bg28KHD3~AIPTV5wCt!!IHbzDMt}bXv!C{#?l5^ie$y_J&5@YA z+<4Pl!Hq_WToc~5gqYoGTcYb=jxX&jI-I#u;#3q)w7U) zlYNV~?lWQ*{i@^r^j3lRIlGeGt7Jpp&Tc&06xX*uX=C64sp9i$+|%7}9-AW(IH~c$ zT))W1t`^@2f>in6Q85tNCH+CB|b{NP5gHcwQMZ!R=K_r5)MMZj# zcF+_r+ob|UB7tAmTb%?)wJaZt7>kIw&MW2}?B$KNsY~}8%b%&bG~>@ca74@UGcx{X zVF4x{HUoZ;dBPw*s{u2RG7tv|D6jyNgaHp5S3;WyV=7Rg0TYl1lu!XFYhYwRjxS(} z1I8C4gH!jcCA*dt|BT)jG(Se zuj(9=tvmkaERoCEpfUBV=!18R_O(|U@)u8!xtSVTw^!QfRqWT)Ej*^uXMQr{W7Arb@8qJa?ZsLEXT=r}h%Z}hl z$G$R|${baj;w{2??03*+rS|o5&O7rJP0K|ke;j{QDYUNg7pGpN*^YH==hs;`EHr4} zZC&b6zwVXGGjU(mpBGDdmhQb+%n`Sq|IKrey*zp*E}j=wel;yvc~ZjHm~}h5X}ACK SiE6w4&h>q7x967?-(~=dM@wq} literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/PoliciesP2subCACert.crt b/SecurityTests/nist-certs/PoliciesP2subCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..0f3fbbb01a192281454dcfd134ec032ea8a04e88 GIT binary patch literal 901 zcmXqLVs12OV#-{=%*4pV#3*3E%f_kI=F#?@mywa1mBGNlklTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6foceDPR_6chApHQE+xNkQ3)MG%zp( zLJMO91A{1WUSk78BV!oXz>7p1qzoh=HV6jf=VT^l0&Na3QYbD>0@~HYsD$hRMpg#q zCPsb+pg0#(6C)$T0)wk2Rzy3B>aLrqi%li8A`t+jH-F8=w{SJ0K zd_3_&wpDhg)c(irSCp#X9sPEFdclIZidJ?{=Ttpgb;mt%+Jan_Rb96mJS>YGUFWgl8Kp-fpKw-L6w0#FbrjtStJa^8bl%(TU4a?Xa`O4 zvRx`rBog>_z12x@Jj?R2h_Q&o*|ZeTGbku3oUyLaO!Br8U(I@Ea4gI6Gcx{XVF9Kb zHUoZ;dBPw*s{u2RG7tv|D6jz2g8>g4S3;WyV=7Rg0TXik023H6ei#`_vVB>3H$LT^ zyNUPE-Wu|S*5P0ul-QaK{e&u z!?T+!E_<~IntR`nDq5j+-*Sz658uyOE$=K0+4|A~x8C`qI`wJM^ZQJ@x2blWO`Eqa z=U&5$Gso7wWQ$aaxVwF+i{-25YYOkIZ&VY?F_nAJkvjd)(PN7qNzGYXV<|ED*!nuX z;N|zqe$LXGTYojR-L6r^dO}0T$rYdOf2wTlzEU}LGWU@KMb%$gZ;I*bC@b&(P_V96 zubDqEwA1X>?ptl;cu(8Q>O>;*d87gG}>Bg2D|o43|nSlT-Ie45oC=C*$iUY$JmPVxNhX%`M(lHbx?Zk8O* zb@P+Vfc+#C?YqRY4e?B(j>7Bm@d?5Y& zjEw(TSb(XA&43@o7Y6ZJ4VZzH0S`z(1;lG$WH1m1@f27D4ETT&TnTL+jHy6v2F%Fu z1x#|l_+n&;E!g8c!T7))9d6CH*Q27|+^kTJb3Wr<^*TB%arMpqStb_sb2V@8nUE4C zKmBBPcjC3yx$0BvPH%3F(|&&B-~5zgMHiG3b!TL7<@&wXYus>--{4_jei=32 zd*5TJD*0GB?DX;Cnr2`eAF#ZOVcaD4Ln1~~wa`(W1q literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/RFC3280MandatoryAttributeTypesCACert.crt b/SecurityTests/nist-certs/RFC3280MandatoryAttributeTypesCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..9c648a30be041dfd3e995e0d272db04c3576a297 GIT binary patch literal 980 zcmXqLV!mL|#I$1pGZP~d6Jvq_FB_*;n@8JsUPeZ4Rt5uCLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`PjgT~1u+9PZr$i~GvNv(78C!G{VNipX1{4zrY1345y z0id%=l9AkKC}_YBavp~;hi_t0WlmyViXo2y7f6UznAzCG6y^#&VJ2rsgC<5L3cV`IY8H!3Z1iFUIB&u;fA_}9MZTk{#OEoGOV`TnSyr9Rt& z@9a^tBIQ{#1gAW{w#etz3Z+`9JL^6xb^kq>n5TLvaRIZm{k`(QtSZ%Ydq12yxyFA> z?(M|2oU3Q_>|7qt%KN&UvB+jy&%Jf4%^c3GiFS#SDt~CDadg>Q@xAjMRweFTIcM%) z0W*P>zKoOmrS587>^so^dDH7la+%wdj-P+_YBHbZymHN0Bgt1`otsRoH`cToyPw&{ zyKaB5LW`i^8S_m?7|SN|=RDLmtn*~zWnyMzU|d{dP-P$w3_@9D76}8f29YPV@fTyJ zwsGjNuG?3-Ep_?L*cEBuWFyPRBE}-}Ay6Xe{W-_u+c%__WHaqC;xeB3+JFzFpP!NO zKMM;mA+i~WgZK(80tS2rJZxMEZ61uNKyd>`aP-LvgA}qFFas&%_yML@VEiyLsHaA9 z*q23ZkmEjoD9=llQCd=?CC?|JT;ZQ9Q{=Z6073-_+BE)DBf@Tg|*JY3ZIq33tU z>!75xe@naza+K#Phpp99aFa<8zUn(k|9+j}yk*WO!uBVxiw(RHa+TLWL&nwQX6WK{ zPd-VPo&w#V=*v8*DV&xzo9(nVZBX0YG@UzVrI6n8`-OT(;_CSCFRk=`WGrvP;Qagl zp$)R8x*LjK?YD87Tv^t1Pb2xEUh@8h8tM7_T;uj{dK;f?^wfLWM83uAT9jocX->82 z3%qQZ`t7li*c2!8G!B(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`PjgU0#f*~2c(QxhX2!~U9+&gUmN|KH50mRaCG%Q950%iN?k z>*n99=bo(ny)*9W>wkSYNr}o|R(w1Xv1^*Wly<^`zps0L&3qEJej(rF`x092uOlaQ zcufw9AG^}+VUU&%8t$bFKILHr?OU80aGC}yS8x5yIHKv zGsJ#g=u4O+A!K^tWzFfc^H_zXH!tI~bnQKO*mUaV_i?+w9OXDFv*cMIlbz_Le-cNw zmg4ynOqvh`et>Bg7(a{*9KSjY4*e8b%IYmtI(^UoiCVi;jWZ*@*`GfD-;86k=%h7sSSMyw zY`0LB-+M3jZAarg&mX#z_wpv6{J`hFMQ=*Gl~?Ygv*G@FKc+r-#_)+t>FU+4dYKpB%f_kI=F#?@mywa1mBGNlklTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6foceDPR_6chApHQE+xNkQ3)MG%zp( zLJMO91A{1WUSk78BV!oXz>P#3#0*3rHt+_emgQ%srYIDbCIRhfVpKwQJR>Uua}y&! z15licsfm%1VX4H@MVvhHYmV&Y4f$GgQ!^iEwWn783i zKta)$vO^c1Jm2)_qE1Cc+=|K#OUes0o;dMO&B$7rKF#${om*VG*W(~XuicqvWzI6B z{Pa1^dG6ZcUvq^|+`076W4(Y&Ve#9Y3jFbt)*H6GJl3#qy6}8o$=gKUrlK2?MbPkqE{X73n?NK~ubJ zmkJb#1b$s_brKxMvV1IJEF#nLC(T^&vaDox{FNWSC2yXWWnJ(d9K*8wjEw(TSb(X9 z%|IMvo&pOn>J50j>tx z2NW!NzVbT9909w!ldg_|?~3VW4X=q?&;M-;w&^|1p7%B&Ec2`+2XjZ%lC39e E04AhSdjJ3c literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/RolloverfromPrintableStringtoUTF8StringCACert.crt b/SecurityTests/nist-certs/RolloverfromPrintableStringtoUTF8StringCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..32ddfe3e3152533d593e864cf9e96bc475a59f0c GIT binary patch literal 935 zcmXqLVqR>}#MHfjnTe5!i80xLmyJ`a&7ZZvtkDa~&&kOzOD$4JE6UGR2q?oO>?UZ4?!avQn-FJSH?l!@FlNh+4NZkq$J#1jGNitdU7aRYwJbiC=Mr$t~ zUHe};%{~uz2TW+IIyu|=u0$Tw#ea79{jc~MT=>G`Ge_Zt<1V)fF^^M`zW+2LF7zDR zJJ+#=t2z9XnYyNdM8DtljqoOQNlggvcD0Qd%MDp!?0o zWMEueV^C!v4-8;gWflnou?CSRwec5YrnYhDu&&!zx-E72&Da%b;FKWC$0EievNhLV z!~Xd0jWd?4TzX+ebevbo=H~`{ApQJ|jQ?3!fN6`(KpezZU=c9jGvHz4N@(+7Oa+P? zFdFcKB!ochj!giKnvjU#~TiKYPzYv2upw{v*HY4qdZ(dgRH|ppCD? z{x`{8;4OGuHtlfM-`TUn!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXAdW<9^bB+$)~E)j791l1802`|1fX%Jt_U}Vg{F-MqANUvozcSJGS)I?zBBneQicSk)V#wn^%{Z42+Aj4KfYnf#E8v z%pzeR)*$kvHvVGF)HV(s)^+8M`74oB(9`Sj1RFgj;M|`sG&DG?vF3-aVV} zdHVF58x6!k`W09N4EPLq*tinfJQ!1fNy~uIfDa_W&&c?ng$0z>kfQ^b(16jw$j~x7 zGxPMunFqg5TeYN=S)yr!Ku{-(^+Xj75wMg&+Xq-o*I8y_+^uEZ;v@g z!N0>w>6co(Bw9}|^XJItS)Arx^66^$litGoGs=6@OV7%zTjBP8Z=n zq&p02&ad%b`(oSAuP2XHo;`E@X~1>i$h0LBcCdaecb+@-lf(pd$wjR(`Kw|KlC2Gm``!E?xU6rqudHp@rJ9^)^U^4&! literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt b/SecurityTests/nist-certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..d747ea1fe5127cd7d6a7095cb11f985e532fc0cc GIT binary patch literal 926 zcmXqLVxDEt#MHEanTe5!i80-PmyJ`a&7(VtL4>>DV~A9@wAHz?;p-~YkwQB%qQim;Tmmpl|!n! zdYf(KHu(?!k3SWd@7=iXziClqL!GF(^%CaK6WS%BE^5oPclV?6b)lSP<>51r|3;b!4hl55(tgVOcD**>!o<_SK8N99ygr;qHG%;A!RQEGco(1DrWc XmOek#xC8&^x9%1#5y`9Z;T8k{J=an+ literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt b/SecurityTests/nist-certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..e75eb4cd707fb21af5418a9c50746af77d37cad0 GIT binary patch literal 926 zcmXqLVxDEt#MHEanTe5!i80lHmyJ`a&7`#y#3?cP+* zai=)0WAaB9{}W{oP1B5@oHo8VLF|l`u~2Bnr-|z~@;fuEE}ddl62kmBS@-E@&OBYm z?Qabde&^fY{L;QwO>p;&;)7`-U*|3rTlPgcN~ohuB|B`P(fZEd&vpuD1C(k`Hpmh&48%eD6<7oe_zZa1xDwht7*l~s%Ye~M4ngc W$npNbsaN)V@;3_6FXWmumlXi;D^IBa literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/TrustAnchorRootCertificate.crt b/SecurityTests/nist-certs/TrustAnchorRootCertificate.crt new file mode 100644 index 0000000000000000000000000000000000000000..04efaa0659ba5a46a9131e8283db71b06ccf8b25 GIT binary patch literal 843 zcmXqLVssC%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!nsTGli%Dj|D-k(GhDiIJbdpox)-sfm%1Vdu=iPC@qv zXI*!;s5c2SiJf(^T(#yl=iz&gbo_2F37#(;syo-e zXN3GyoGP=?{_y9fXa)|&EyuIPvn7tQy|Ls}U(xX{=hf0P{reRd7GK`(QE_tp>kZGo ztd^C!x2?2nSFQ9S>0_IMs~#M)59pXU=VL*62J`!6pZKkKu4x(R3M`%a!SmS>=ks^6 z1B#Ox4MfVqp60JvJ?FNsTBf$kGyO?&Yjj+$v|p5HchLTQPd+vDzGTGCw>s9xBR(-) zdCJ_&#LURRxY)_S0UV98d@N!tB2Q}LFUCx5hhbhE7A=3fRQN6&&c?n zg$0-}*bMkVd|?ou)qojDA%`+BnE*qXkzvNd^?B~|yi_eU4=X=v=@6G&_dor3;k{+4 z98(O0XH8(8dSc_hIPRlSe>tA}6gNG{t}y0GU$t@t-~%3 z&+fna<1XdobF*F^<&0U;7SS_h>eiF&R~oK~Y>eBHy3dOFyg&r+BZ(_d8$CAouD+&c z*DWcxtLx*jLtFWO+{ld)Ff4jCKPp-6wx7)$J?8TZ7l(f$NY9jV?I;vcU&zO otJ5y6(^M<1Jo9;L!CzBPwtyUSeJgLCX`9a%B~G3HcWKR00Js}O*Z=?k literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/TwoCRLsCACert.crt b/SecurityTests/nist-certs/TwoCRLsCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..28eb60a0713091407e817db77094bfc1ca4787fa GIT binary patch literal 900 zcmXqLVs0>KV#-*+%*4pV#K>*H%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz=cF>L=1!=)^LZE=PNh|`4lTSI~p`GDj~a{k(GhD ziIJZHD9**y#K_37H?-hh67QaT5AL%)nNdzXm(ITWa_Pd+@6X(J#L7E&>^M31bUB;J z`9*Oto{}O`_oVpuKRVfGC|@))gEv5F;rVqLQTK(i?kxCV@MuB&xq#)2oX-0b+==L-1jea%G3up&4fsJ4!XSmL2FySTIeviY3m89)3{ByyH?XR_ z_Yl2o)&Fr*Dwm4f(_Na`R*P-D=YC4vAjxy2oXbVHNlV^K*Fh|E){95|p3{Ea4ihS# z-a9c!DtvzMmLu0*?pS?nUVK;jT6M>jg=c=WJ@`ID@#*yoo9a|9o+#6v_m9hGldn$8 z21XN;38{7RrRtVB{D0-m04nAM_mo+|EBq%C;-JJCjc}uzHPCj>g`ec2}oJvupd3z=;P>lWgKeN>Tm;*Dt;JdAN+N&3z^j2E!f2~1rVUB9nVmB0J+ He8)5Z8#zn& literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/UIDCACert.crt b/SecurityTests/nist-certs/UIDCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..ec04d7445577067c6176d2b20e4eca2dd540e380 GIT binary patch literal 900 zcmXqLVs0>KV#-*+%*4pV#Kip4fR~L^tIebBJ1-+6H!FjIt0A`mCmVAp3!5-gXt1HY zfh>r_B`g+_T3n*woLW?pnU%o9>n3RK~kmz{QXnpj#_Z-Gn;!LxH@sWHt)9?|KGX4ZBx9otZc>9)vHPw z^O{qb{#xs;ii$pXEsguFa*@q1@s0kLTJ~iwx3BSRd353h^Af=w3ObW4Q=Go6+ox*r zK~3^d=*i}D&)ip6p0G5X^w-zZo%<5sc@zCl3dfR6);zI)5o+0PFR)%#?eDrzJ6FE% zaf;rS^(rE+kInV=uC$HT-Av4k42(@otO|>345|#|fq^Hh%pzeR)*$kvHvVGF)HV(s z)^+8M`749LutNEMhDo0`^B)3_jj)Hfybn>FMpB`%YhGr2!vEKR+Yme-;*C z!eKKI2k{kH1Pu5Lc-XiS+B_Ijf#L>?2K*oiVUR*r17;wF97n+91&kv`25zed^WN;y zIIrzdv-jG~!;vLhvs*t;U*i8}nRncEj_o14&L@P4|4o)!uz#P3@Heiz?+wKoW(eM6 zROkH>#vk*~x47X-hoy5&!|nw|Q7n;>tLJikJIYaGswAH_XXCB2t2wG1g?IkC9@YMm z*DYoF>X^FxA3|YX@3^(>+nDafy?(40P|H#NTlBy;Ka*b*13&m%M~1vn*PUlm z*E4qZHy+PBGfUF8>kD_q`KPHRb6Cui*DPC}(6y}Sd$vq!V2{j8Lq_|sbsrAy&*VF~ zWv<68+2bdjr9PXy^w`w>tM7s*$KR#9K2GRd|GSy_&-#VAH?8Vb; literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/UTF8StringCaseInsensitiveMatchCACert.crt b/SecurityTests/nist-certs/UTF8StringCaseInsensitiveMatchCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..2d653ef65b16141e574f4d3d97a9f41f935e581d GIT binary patch literal 925 zcmXqLVxDQx#MHQenTe5!i7~~1myJ`a&7%QY?wptG*&GYcR!tG< z`ZULP@%*3j4;VWi{b0H8f8T}+^*U30=FGFIb-yXPx}47L$87Te_I2+Gc02N6 ztH`4J|GZe$)h&1~JDt9EqE+~ULErRTwt2y+X>Dtg+)NXV!+$(-ySa#AmB_Qj+Lt#n zF*7nSF0L`CGLQ!btE@7Mgn?Lt$dlUmi!oE%ICNOo?JM1uy8LGBiZpQi%kr^^v4|wx zm$-OpWxymsaYdI)$Bs8Au_=4=~{YG6ruU{*va7Np` zW`9ikzQ5NmtLGkyEzD&`Ndl*Z4t}@@s&eGdfoWNkmaBNCcKsu|$&u4R=Ox-wd zMQp3u1?RJEO|QH2EH{L&yjGFjd$8_O&X%=rW9Qvnv8Xqps%hKm+$(X(?iTAaWU7=M zo^tumh)UOw`g$Sr$S;BUudjQnWMyvPxg#02VzN-f2eZV+6?SU>Doh?rYSgW`uK~1AA|C4PxB1Ay7JVjjmNW= m$S3A>)(9AsF(-Ghte^U4rJ&8{&%U{Nrss=dOr_7RSqcCJcVS=v literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/UTF8StringEncodedNamesCACert.crt b/SecurityTests/nist-certs/UTF8StringEncodedNamesCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..ae2ce8a7b49e84c1ecdb18c515713d8ee17ef09e GIT binary patch literal 902 zcmXqLVs0{MV#->;%*4pV#F%8j%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXzzw@KJh-e8GY|n=!^0aI;${(CQk0pOuHfuw(8Q>O z>;pzt2IeM4eg>d87gG}>Bg0FP;~51v#AMTs|5uZav%53P<;<)NkH2oc?9LRBa<=2| zcj3z4QQsX}1vbv+t({nQLA@`ebCu6rjuj8voTk?tVU3ya)OfLg?mz89E<=I;BFah2 z=I)diGJkU-p>VDuYvfyl)cM9wpRU$dVomL|IG$EiJU!~&nKxF|yY4M6edfUF`Y%h@ z#E3QQz4R*2HBY2?;yt`}FkIF69hkdv*RqO>->%>G`E)SHN1%QBUFNNFeHwG7e&{}1 zuXEz&9qntYF6v2E+3`=~loMt=p1kD!zIXTA7J454UcaI;L1Lrnzr8LB9qzsElk{(? zA2sOOD=}R@t<+Y$#?MUeq|mGXXEp>K3!1Q&iJ6gsadC}7m4Q4k{A86`Bn-qFM4r^f zUyPaB#-YQyZeQuP)a5s0SEPX>T9%JRj77vcJ=*0H?{bgYV$Gh(^RKEr7D`Yv-~;LB zXJq`(!U9Y>YzE>Wz5+-s};-TOPuzy9g3_$#Waxfho$I;41Tes-sc?xoW_Z6Xq@wd`dsv8sc?^=Zmmf8|}cR3hX$TW{`@+gsVL=Qy9y6Hj%& zvv~TPcwLUVh_8VP=VP5Ye_vmFVv5Gg(|(M9^JDBwtfpN0+Os^Kb4Q5QM3U%^nH>Fj!QI literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/UnknownCRLEntryExtensionCACert.crt b/SecurityTests/nist-certs/UnknownCRLEntryExtensionCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..69128811ba375190c43d5f707d12cc8fbf8186bf GIT binary patch literal 919 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/UserNoticeQualifierTest17EE.crt b/SecurityTests/nist-certs/UserNoticeQualifierTest17EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..5fefe19944457f517d6214bd7418958626564d1f GIT binary patch literal 1014 zcmXqLV*X^%#B^%`GZP~d6QhU$FB_*;n@8JsUPeZ4Rt5tHLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP{4o>q<~qN-90})MZww8Ku(<3(7?bD z2rY~a3=E>gd5sMWjf`PjgA@{NFflNK*q|L+oLZ#dmtT^ZoT?C5nwSH02~fb*71>z| zAa@#?8#FO0A$yIHm4Ug5k)Hu5&c)Qk$jGpbr(VLPzgd3%EtMzIW}7;C?l^?|%XP}d z&#|n&Z@K#N3>L--?uWjg53XEp#jCw(?x{!jed>RnO0^aLa-inK=g=2NcXeF8mF^4xjRpJ3U&9oy^WIHPKm{B5^j~ zu~5^gPqB$l*VOuS-g>`nyZo-c`d#Sg-^~}hKKl7u$2lc$nV1* zS!EUp1F;5?2*wr_={?#(Q@m`K3KWS1eqC>M5}XEP`B=nQME>bC8pd2Qp4*%->FSrw zWtu$cYP#SQAj{9l_@9M^nTh3tK`qEU1(q^{5`!W(79f+sAj=?wjYFG_k(HI5iOC>F zDyq=fNPD&eX9RHe6?9I;6l;JyK`#I=# zb9d>rIR{rH2#Q7>sJFS-vCP!@BEwte+e^C-x-bW9RDHs!apaEhd)YhxuTG1zf2n`w z%Isgiu3MeuiQ$W5%K2rrKiYDoUCdMFRDD&hoh`}>CrTe!QGMpq!v<-4y?55zV)x!( z=cvfW7sJG(o#pVC{npcECfd3sZ0-xDJ#u~h(&$HP^=4M9YYIzdxE$i_y3g#*d#u0N j^8K>~>*VYH%wHj{KWY8N7mnqZ?nM0l(K~zAT^3dVu$z9n literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/UserNoticeQualifierTest18EE.crt b/SecurityTests/nist-certs/UserNoticeQualifierTest18EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..1168b580e8c60c937fce1cf6bfd49fd6eb5cb7ea GIT binary patch literal 1240 zcmXqLV!2|_#Jpz#GZP~d6C<+$FB_*;n@8JsUPeZ4Rt5tPLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP{KeAq<~qNKOjFRGdU9|9$;vs;OuB1 zC(dhVU|^udKdkrlNni!Rky~xPQz}&>h&j1wXVrpV!WZ3h8!)cT7?h77jHFLQaOyJM( znNlDY!~>Q)GI2=;XJ+abozd!N|iJt->{{HMYC&oFC~O|p4r)| z^31FG-}8U^rz^PUJrc6znj*r}bo5wu_t~)N7A5^jYb=8u1Nzh2FBJ)8df1Y$z1d8Qf4H6N=VoGNWMEv}#JCz5 zBFhcrfgvob%mR$m29X=_rjKSFG}lr)*LX9KhHOTU@h_Q$~u;%zABQ<%& zvmQn*&a!N-eAbLY13r*`en!UsEG*1SEFXYo27^QtSeh8UfE+i2#<^@<32h#XsleoC zz-Z9eXVBQq#-Yu|$jZvj#AHw}RaPJP@qyWsh>d3`r+#jXe~cCDMf#`CMLn?Z({9NW*X2XmkH zxm90E3E9qVCw@uxQGVV%wKW!-w$eIwvY({01OekxBvhE literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/UserNoticeQualifierTest19EE.crt b/SecurityTests/nist-certs/UserNoticeQualifierTest19EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..3cb86cd1ce612a789334692feca12cc08da4ceac GIT binary patch literal 1263 zcmXqLVtH-Q#C&-HGZP~d6Qia9FB_*;n@8JsUPeZ4Rt5uCLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`PjgA@|2F)=WLSfd?UoLZ#dmtT^ZoT?C5nwSH04p6|= z71?bHAjcY78Zl`BidT7qT-*Z8cPXn->$9k-qEW z{cE15r?xLzQTN|zsyM6r*_qD$atmEA90<=5k}sIRyson%a~Jm)tBsHNTg!Ex-01ng zr?mcs6!YRP$BjjHg4%6=bYI$@>6jrqhvoX*C*M9#Yx&|*C@r;X$*FFChW2+qpYq(= z_j$SYyQLr8r54QFvPpC1-OCwfnIX}RY=^54&QSaLTl7)Lx>wup6)sL{)hk-Bo3&Cb zGf;mDyVaVDk7NEvi#lw7V_m=6&yV-qgG(PT?DG)Sa_8RDrTrn%lZly;fpKvY<56IU z95j#zhOn$Mi-dt#gUFNG_=_=9+c%fhc+7{D=Rw_6Od;m)x>C4XlA9L5S*G^l9`{UV4`QFXQ*eYke{XyI;12ilvOR+^JjsgRMFmy(l; z>b~;Kk_?61{GwElWAf143bqkwJ-Uzb%YX?U)msWV`FZKcNgbG#fk~Z_AzO!c-%j?F z-}Nc!sxH!hIm# zFF7JMUuIKw<&CMA$}3T5bg-D(}DK=l={T{a!T(QY1(k`d2?G3d(ciTr-_Q~nfthVf0ORud|37U6bLE`^9*26oF zD~gKWF~6|qi0ylitP-QT4|gv;=@!kMy!`A;3BA&};SaMN&RmL#bSpSpo57OIvT**( zPjNe@{N5BFGJQMaiCj;HEeqZSzG_~|wu@_b{EGkAYVLL1Dd_N({_tnr-VGV=<75w2 zUyx^FW@KPooNbV4AP)>{S!EUp1F;5?j`)4{rj}{5Ui%(WlUCcPrM{Iz3!F$~`B=nQ zMATj_O5c*SfB%&;e^YLET*_DPel2Ri2hz{a$oQXyg_()vgMm1RufQT;z-Pe2#+A_K z!I%n6js}d#(E&`1!02FPFn;trrtw(V`nOZgXrK9T-a9HNQt?!zufdtdP0U&X3K8Fp z-y7NbXRw8=+5K8^vXr*Cr}R|Y{8zztt2{sdusXDGlIGS>E)Z{p@ESbAPqmF0}+5N!Feh>?`&sYP?nw4_*GYg7w$z``5hB z-YVR==lG2m^ZswX-nnfKCzpBqB7>t>7yi%BpL9R-dT-CRYGVUYt+mE;eyim77DX@n fm%aX?TIk}$mbT^VSl#9F?zKD@NRyw=BNz$*kWp*P literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt b/SecurityTests/nist-certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..9a7919b00acb49d393bfbdfbfdb6ca353e2ad9ae GIT binary patch literal 945 zcmXqLVqR;|#58pQGZP~d6C<+$FB_*;n@8JsUPeZ4RtAGmLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP}M*gq<~pi#woElGg%=xH78Biv$(i4 zHATTcCq=7 zqJU|+UuwBRcxFik*cGm>$WB)P`NhPbiBSpJ_l&Fz%uS5^3_x)%rY1&4hOKR{Tvb}? zYJ@%>&;75pd+%%i`Ww%`t$i_d)mc4>*PCN}?y&w*_?qrFYvPe>H?*6I?=>Il?`4$j zE;JE2R{HMDtz!?0BNsS-&fk~nxX$X#V(GUb&t_H6E4y|2ZgN72m)~*axgt^3`ubj7 zhpQWZPm{bHWIn0Y^!fQPz7%Eo4~NdiZup&aFFCJ9Xz@kaJ+mL)G~b=to9y>xcW>e{ z(aDofE}!aJ`sBd<q|i^eR4$YpsIw zOB~rUnV1V|b(2>)k4hKZqM8pgh?pqH|B(i)g zVk{yhN9tVF#@B5k)hLTj-=`w?fg|sZ#f=zO3-tc{C+Vxhwe0E5qzGF=BJ=}sS|HDb3fDa345IbzcOS*M4&Imcy1N;YT2>sQCZ-%Bi8mVNcD z_ROhg*ZIV~t=&`Hw(ah}pGE8cEi}-Y{@x=s&{S+`%YVBA)g4_sZ{GBm{17Hz^X+oV h+N8LUE$5D&Ibhl^qWf~~p0~H3$CowPUSoEt0RRxGZhrs( literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt b/SecurityTests/nist-certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..038e4d7a80a7434a14deb1eda6bf448908e4c7ff GIT binary patch literal 945 zcmXqLVqR;|#58pQGZP~d5E<~YacZ@Bw0-AgWaMULFbFl|HsEAq4rO5zW(o~9lsAwC zakzxVLQ;!M6r59wN;1Z#lbeu})ePbFca$?6hCoXnzjtSn`Um4yNu&UT?e~>J3&YYv4YeL=4 z1+%p;91B#D7B^2mzVwzs?)9}svX;>WUs-P+sBC>I=JusqHcMiA=E0WzV(%vxt4`}; zy7cd{$qeV;lcv4)*cltcR6RRWKBbn)g}K@*i~SqRf1^bX78x(a1zeWTO|58>pSkT9 zKNB+}1LNXsgG>W?U|7p4vq%_-HHehe+(=>s93_!BR1P?MbmX~B9Y}|5n~Zy zzPsXy(s$dYDc*w4<$6cXt3UhiY`_Q7&(FyCpM`~)iRFWVIEb&nB4EI0z{AFs(B{FI z3QUd$jL6XeOpL(jU}R7z{8v_e--3JpyOvay^i{&viaDHf_B@Q)@#^&=PD%Z=f3n>T z3|C79&p5RSv($-i-ymGso45T<-5>qyVNUPnesXn0LtTHuK)l5 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidCertificatePathTest1EE.crt b/SecurityTests/nist-certs/ValidCertificatePathTest1EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..69ba3019d4b6bfd8b1fd4289b7b21bbd5efd3e8e GIT binary patch literal 893 zcmXqLVy-l3VoF@V%*4pV#K>sC%f_kI=F#?@mywa1mBGNlklTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6foceDPR_6chApHQE+xNkQ3)MG%zp( zLJMO91A{1WUSk78BV!oXAeclOlnoRiHb{jf=47TQxVj=cLjmM2LxUzpC1js4vNA9? zG4eA2#krW87#SIE-YJ(55Rgc4{QbN_fd5BJdBJ<#yijYwWix~9bHD6eIQ^HIT%L=Q z;ECXWrERn0%!N7@)!r=RxZ-JAc+Ty7^o7X2RQcCVwx{^+_)NGFl6gMPVv|C`-R3~O z`?s$~TTG17JwMBMOa8P8Ps>D-oHJVl&WAYuG<`MiO4RhZaRQNhA3Ql6*?Ilmr^*fO z*-Qr_7iuvyiRNbu3Ni$nl-PcGcqS}q(Ua5{${U+yBZ4_L8S75l_q5h{o@#x-|&g5*AQXRY4x{q6na zE$60W?2nsv!DZUVA784hxGF`1nV1mdX8_v1u-)^|?T6E!$L{V6WL+;e6;OLg+XJq`(!otkN z^1(nHWS#;GFdZ21uyG}{c`&8|la>K`!U9GIBZFMjP5$*sOLqqC+4F`cu|t?~6&F9R z`{H>kH;GICSbS6GQm@56>rLmc7zyoaU$EI%imi5bUp6(Ix&2OJp zNhV6<^;~?ycWZWTPA}VpcRCjuo$Yv8;?ci}$Kn~(MN+GUe(CRBvEQUm_q@1I zM6?0FUS^uBnwsK_%bzE#(`=9OJGS?QMjiixDbN1LY>n~1+m#r}$9n1i(aZyvJH0L* zdV1o^368^mwUqr^7-Do>bep>l*(x2kN%+)N@mSg|_14V(AIS%=R4pi2R<&GU_S`k~ s`$RstD7Qzf5fFXxdBJ`;)zfCHnKGl+{XdYm!Fe9XJV~4726?@Q0AB}AlmGw# literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidDNSnameConstraintsTest30EE.crt b/SecurityTests/nist-certs/ValidDNSnameConstraintsTest30EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..e5235c7ff251f29bc6d9ae78703ab5275a7140b1 GIT binary patch literal 976 zcmXqLVm@Qg#I$7rGZP~d6CB(+$<$iUFhP{BYBq<~piJTEaf)j2<}xTGjCGq0pr z!No7wP{G;JKu(<3(7?bD2rY~a3=E>gd5sMWjf`PjgA5XFv@kG(*r*?tn3I_TvPS{k zZdX@irz(Kl4z#<8Q3=_*jI0dIO^o~uKyfanCPqevBX^%45$5;vX)~<$JKyzY@^t|r z<#@Y1{{?n}8IPCkkhK2F+T?v+XlcY1mCC)FWNx@;Wvsb;%WOi$9&PD_JuaFa-EP)Z z+RIwb9{;xBOnU+`j` zrc?XIuvxp_N&e-!&-Y;GMH4q;;iSCJGA};Q!0D=TQ}@leXCc^&aW-sM(D{;%NVKKRXhQIz3$t$@iH+pGB7S~oMF&7 z)j%E?#%bMBm{?EI`{@4?oE@b&w#8^aJC!Nn1p1d{B ztm)`a=XfMv#67tV=eS)+ZwQ*Tq&{FF0BQ+8UXsGa`yl%eLGl;QGURcbY?u5J${n*mPQaHIeL literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidDNSnameConstraintsTest32EE.crt b/SecurityTests/nist-certs/ValidDNSnameConstraintsTest32EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..8bc3e87b9fc4a186c0856c941e317c78db671ceb GIT binary patch literal 976 zcmXqLVm@Qg#I$7rGZP~d6CB(+$<$iUFhP{BYBq<~piJTEaf)j2<}xTGjCGq0pr z!No7wNWt0BKu(<3(7?bD2rY~a3=E>gd5sMWjf`PjgA5XFv@kG(*r*?tn3I_TvPS{k zZdX@irz(KlZfs=G#HfVqT}D<0<|amd2B0_>QxhX2!(;2(fZY-5$|odth+JOz?%caI zr>=hS<*003FQvatP-c?+v)elVyjglUMa#FgF0gv1@b}*ysl9gh-^#Z$*`(Y|>HBe0 zdRbJ4(S<5&d2bfy5_!G?+0a*WTMTsqSu%d5s~of3we4!b6gAP7w@ZEm*qAiVcRM^; zr`-6jQLf}J!@7B%uZ`tAioAUf+p(>k-ydTr`+q}7T9=N{o$L3@zHIAISbXWc&yv*L z?v@g>x^ws4<+4xT;q}pXN!jr`Zlc#@y&e^|1)nl!Y_g5NSh~S3f6}vd@q-JL1CtIM zFTT>2EmXMM#xqk=?%k{2;)6EF6dCjD)*ZOl_~YNDtYxhRvS!QW!F85kEg&M;`4 zY9J2`V_9Vu2?MbP5jT%HPMm$Q!38(ORd@v9P@fBDE4EPLq*tinfJQ!1fDbRq?Kno-x z$f9hZ*dz~3RVBr#MP;c)dLU*pQfkvn&o4ucJYZS{Mjp_;KmRO=E^eM^GsXXF7X0{(fUNihtvjeadmkjr{#7N=a+W9W^GNms=WjRlB44lcmL*CA&)< zrf0qh`%*5tOHaT?+m)F|{DPDV^YLiM&99Dq=bhTubc>;62EWrw73b{Ipp#X+xA}5h zdQ8qQ75=<^rh0Y#$?2^W7nS^sP2isX>9 z?dNSwie;S@?!-4={%GH$#=Jl}&4WAJ!a#Cal;2;&iQ9|biuGSAxE?F=RBQ5$eKXT$ w9e%ZLHjoqNH8e0V1VRgA0|SF7 zab9BsLnC7t*PyYFiY{_8aDceTGAuDCGX>}lg~YrRg&;R)3nL>1bXU5%B70Z?6aq%( z22G4g$brVl%D~*j$j<;2=VEGNWMp{Q!^ygIUB|U^ai?y|%9V6BXZ%_G{UNK$YL%99 z)qq$r<;J7AI`48^)Z4GGYOLb)yS?BeQ}?86?RU@E*|Zsp>8v?>fO}a~)`d2Y+&~V0 z0p137(TX*p+iF(s>oZ+ub0<+ZT~5W}dyMCe%U$mE`sNM#5`4@Ts+Od`W0ZB=Hh&wd z@bf>L*)(=_UYV`Vy20$S;^OtcvKQRSm5z;z`O)r?@Zdpz@Us4(M=aTI^p;iL%sd-7 z{pqEY{)FuwM~viaBdn6H&$4owq#OOM|Cn0Uu1;CT+a^4YN|Pt$K*cw?fh{KYu1>Mh3>kjnfPoCmYBELt9pvMZ!R= zK}6m23Cm5_UpX_TBTv3xKP2k{kvDVWcIhm9+t&4V!&n2rq?4KzR!f-H&#@{O{Pcye`h z04CCsWTX_Um!4mS9Cg6-4vacRhDz<}PVwyXrTU)URH)f(BDcYdXVEbaFQ=W3LTbka zpV%BX+f@1MnyD+#(|rAt>n!#sdR#u(@$jHo>7j2qD;LMH3Vsn(o|vqc&l9G)vaHRr zu5QZ{gLL)@E9ZO29FRXV<@`kA# zh{x7HI79A4w=OS{*ypk0$m59~3<|o&zn(q*aMn?E@2ZmKCD;CL*{u0z{k63n_y2jw zNFDGBstu{ue%K+h&(O>G(2AP1GnIKb>)0n`Ivt+%RPANnhVHkwuG_x36|+C7)AL!) kHS>is($yPXv%)_-uueU(UYqyXqB;DPH#g7EIzEjH05r;e3IG5A literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidDNnameConstraintsTest11EE.crt b/SecurityTests/nist-certs/ValidDNnameConstraintsTest11EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..f8fe1223249f3321656ed8569cbdb0e13af4aec1 GIT binary patch literal 985 zcmXqLV!mq7#I$z-GZP~d5E<~YacZ@Bw0-AgWaMULFz`3zHsEAq4rO5zW(o~9lsAwC zakzxVLQ;!M6r59wN;1GCJO>b)2}}*GzbheBZkDac|qzEPuwC=uleNCO6)$}5JlJv9ZBhI4px6JG@YD)ce>yR=W z90uW+W^^(wWn)f}aOukA-?{Oa$%)LB`n~S1*BA2mOyvEuP|`B?qeb5YgD_=h3w~FH zlGQBRVt2jVkXXt0t%>XRcP3^=2FAtN2AKx(zyOw2W|1%uYY^ErpYzlN%Q=4KQLlds zOkHz%xmT<@I5Elcv52vV2%b)}O=wM_xmCm&{+wER}LiVny=}PDAMuC4!Fs7K&nk?Pt2E{db1@s=PkLeoUOk? z>d?<6j#Ix0-{D&H^Gfv5?d1y&uiO&W$mhK}eY&cB}5 z>SA1k&d>kz%{1E@S`TfH4L+lMJjLUFzL+ahVjjbf^y_sYto=p8zm`9&*^&3L`om}S s*U#$`FLkCGFZaFkY!a`H!G!xCne*gdg literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidDNnameConstraintsTest14EE.crt b/SecurityTests/nist-certs/ValidDNnameConstraintsTest14EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..4364e1bcbf58b2ef518d5e3b9233c05f64e173b9 GIT binary patch literal 926 zcmXqLVxDEt#MHEanTe4JhzxkyIJMe5+P?ELGIFyr7~~sr8*s8QhqAB;*z4o%)F9f1s6XFo+W8 zH8wCbGKO&t7z~;im5^P@$jZRn#K;d4=VEGNWMsJXjT(r=aMQ8VuXtihD?H&If zSuBZ~(6sxK`b*CoyX0*_cML9w)bCd)_xPTtzW2?-d)+ryCN9hMb@=OI+oY);)cMKc zeX8ZD+XDXDFsA(wft^kS&$ z7{~(yTvnMy!a%G+WRZSEbF|OY>D%9ZYu_@R??L^8>7wB1l;vX)V-bnhn<{Sb(MPYL z?z7aZwXv0pK3Hrw-~;LBXJq`(!otkN^1(nH#8+SuFyJ%bVdF|@^I%K`CL9As14odA zAV{IPfoY?0SYl3Qii;mwJcH7Vp^2-j12DOiBqOCAz4ZJt50nYYoD6# zFI7A6VvbW+g3J$nkLME4lDW%k0)Fqg^zV6)L+NQ_sg(B(muH>bE@0omw_^L|61M{{ zHr2N7?%MZ$!`*UO&!qV!u|HI!qr&?mWSjOd7;}B7h`-Mlz+-nV@z%n2?Tz9s^Kv|` zgf}?xhj4LsGn{&@7{igXuKV4S#eya$4;dRtOEdR1T_h5q3In%v7w`YIYYp_{6_vF%(-~0rOm3JI}+$}s?_Ik~;hvtvx J^X>?B1pwJ8Z`c3; literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidDNnameConstraintsTest18EE.crt b/SecurityTests/nist-certs/ValidDNnameConstraintsTest18EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..3b5ac8be530528ff89cf455c7bd7a2f5eba846a4 GIT binary patch literal 932 zcmXqLVqRd-#MH5XnTe4JhzxkyIJMe5+P?ELGIFyr7z7(~8*s8QhqAB=O7>wlWvz3eT%*zHb{Z1`)X|C`OX z|FEc?n;LVsd(Q%{zg^|M)2o;tT`+3nys+;S)3jr!qb}S|x|5a3Z`k_LQ8lZ-_Uy_u zq3dya3|}t&Gq~jHb||yesJ28+XzrnuZ(hIm@?D?t&U)Fyw#MH|dzB6B`W?U;xW1vq%_-HHe&Hd7GsnTX!$z6+?&Cn^M93OZC#h=|Yx|MT|vc3)7^9=cQJa zgnzEFaOZn&s?~bE!hjE?pP!NOKMM;p6Uzq!aS&gDMZkd1fQOAMq0NIa6_^4I7?Gm` znErs#!N?G#)|UG4HQODdXBLx=7$1y}>3;mkD&XJoofk@Pb!>X^jq7H2*$ltS_KVy3 z?=T*^(9y~%;5)_NQR8rognyBaWL#NqeE9x%{EIJ5Rp1T!m~X8Rl*%S4ZufKZO!XPs zj90bR|EP6+dAinU?;kh89Jf2ATylKRKHn>>IlH7|*>|_frppi0QrR{!>HUgaboA5P z>hc?ri@$R(xL)+26M|JWqI%h5Ma;eqsw!5@|OXA6$HK*m@Jb!d@i$|U7Pa|;?ZS_YB V6pT9l)_;FG$4xx<&!ro!F91rqZ2ABI literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidDNnameConstraintsTest19EE.crt b/SecurityTests/nist-certs/ValidDNnameConstraintsTest19EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..20fa140e19dd01b73b0fefe1439fe0cb65f48970 GIT binary patch literal 957 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidDSAParameterInheritanceTest5EE.crt b/SecurityTests/nist-certs/ValidDSAParameterInheritanceTest5EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..d8b6ce36d0de3b3e2936a752c5700c036674070e GIT binary patch literal 574 zcmXqLVzM%5V*Is$nTe5!iILHOlZ{=g&EuQ}3$sCpAvciA9LmBb%oG}IC~qJO;&2Iz zg`^gjC^)AUm1L%6CMTAp7AqJT7#bR?7$|`hFbhk&1Uo7OBo-y+rk11@6)Sk=Wuz8m zmZYXAI6E51iSrs77#ISfg|UHwL6kVJv4NqHF^p@FOQNl|2G$T;O~Mj$GE)>#?1ovL zn3tTY;OdI(Xa$fjObr?*A-v4U+}Ogv)Yy>TUmoCmvV5X*%xsGtbIyyexp=&4*4+GK zH*D;z^A3OYZI;`=dU@9M>Ef2<|CEE8`zNjR+bpF;efr~9N_UX@(AJ+yMlIt_=K zWFhsK8;i3IG7aQ`zLHgDkuVTz5J_#EUtra<_M5ZpiRb;HeJ{Lkw?6{MhAbb87>fv7 z{`!K;Z@E2I3(73M>K!d zlsK=kfuWHxjBAiYq6J0<1`rE0!xD2cQxrhf1ZSq_C6<&H0UhD$itH!_kSk3Lni#hM zu{O+Cj6jYYQ)45;lkW8nJ)+lbYu+(W6UsQK!1_Y`)Vz{Z?^z+!wJMBnEj?QF%4GAD z45zEof6G6taGIAgdBV0sOond4Rm_=ZX6S~^jZ==-*uS=(|3c=}q!=l7t+<|I&$_=t zN`0YE!(Of{(wx@Lp?5j;H^bxtD*Yrtn0+8%*o|Wv>qi zTct0zRqMn%C3n?|Y{k1G_UAqbG=85ZJI8T%oXezGy<>7a&SswIx3{*t;J@hHP3FcH z2B0%^M0U)5Bh_S*xIH;f%=WFmnyQTWi9^M9SAR$}eYh}Jza=t(JxIVUSk`n!aEiq> zsSmz}aZ@)Q_u+s1v?ez)Tyev}^I7|9cE%rxPZayYbaK7Ny%l$NJ)S>oPASHWdeFg&^CXvdmmwu-*-oJhI mKxLBtl}#x&Y}Z(rM7-O1O8q5vPig^ zOB~ZmQi~K^fbLRobwzfj0?6GK22G4g$UbFcWngY%SmGw)VToO;oDLi_#Qp%D`nUt6!ipn8jKxzocCuY}+&(?r))O?bUJ zCv4is>Lm|3*KgK8adz#>Wvl{A6F95XT6?pO_P&ku`a3_lL*RAwwZ6L7d;N@-R}@YP z6o}Vf=DyTfkj>!qZeH2CC23FAi@rM9pw?q(S!{mY;nDH6Nu5)x)%Vw(ZdCiyzFh1i z6Eh9 z`|Ko-`|AV2cN-2_>n>X)DeoE&8N85#exurM>Rd@v9PnWw-4OeY3BY+MO#9*n8L zq-Vg0938-f2aFCzh5|!Y(#2U`|zf4$`7t`h#T z`;YRhH!qjk{`_amVivYVCw?dF4Uc=v8aLB8={8rn%wNgl@ofDZQ$$KxD;yqw`MJjG z-^`|3C-)1I|7*^hH2iTluW2bef4%B_r|aLlXM$y;dcP{U{dvl?i-_d3B*PK{z?*8eHb-O*eE^lfJ zf8wU3{(VE0Slr(!Su#Ig_MMU1TmJ0)rH}7Tdic23e$hO)%J=flJ14wdCA=-~rcW-M zvGdGsCT2zk#>LqNnFjK}u$EP3kuVTz5Q$)HQIX!G9W=$ucBw#-NZ{A?RwuzJLY9w3 zj78+^>wASa&Ru=rw#qj9ywSmzQx4m`2d4*Fen!UsEG*1SEFTQSLFOs2027J<4;xoP zn+IbmFzp#IB1Z=>o2d9Yr_?aChvwwQD}FF$l|A3$=C6ONt4+84 z+S-n3jiuVWyP9Nzo*rN={G(#6qG0M(BsM=q)3#6e?J?u^pX-lIJ?(#6WZ%U4e?@EN z?!NQ<%Wut1H`MIAww(Fj`a5FF5|5nz^H%$q(xt|-L$DAV+2l^2~BY(7hG z3xq38H3)wFR*Z|C^Ufa2mFL%7&kW!Rtnt5VUiq)-{dRxLW|?CJ%{Mb0m5L`VTFus0 e&&&I7hGRFgh}u&t+sUt7V&@+d>Ed{{P8a|oPGrIW literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidLongSerialNumberTest16EE.crt b/SecurityTests/nist-certs/ValidLongSerialNumberTest16EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..44e890546d547296af0db9fd16559d77e2293632 GIT binary patch literal 946 zcmXqLVqRy^#58RIGZP~dlSn-y6Eh1d8#@Ol7dHd#AN85K^Mn-N{ z1_M7sZUas>=1>+kVW!YvLwN&P5Qj@xEF`tKM8P?=s3bEjGdZy&wOGN(z|hc8&OipF zfLU17CqFM;Avm=tGciZOuQWF)wMfC)(Lhd|*U-Sg5C|=d4GavT#CeSk42_IoT!VBH z?K3wph1jPTmY9>7qJYI#S65_rDu5hrXlBsFsD$iSMpg#qCPsb+pg0#(6C)$TYtOo1 zDSM&g0Gt z_glWXue~VtcIw{4CvqE?^hArZ6eTv5Ke6(fx?FL`^cHEU|EpC?Chp^Vn4&A{^K<9r zh>qhHGWV60CWd~P$vE*)sJ_^Xmc8G+?U!77+N}LJ@2UI}y9HB@UNT+%C$(BkH}{#= z)DN>CNA_P{o#}q$=!-_yC7~``*e&ANf0VP{5IC{+l}*XNA7RDW?Hk{25HxO?^8cVs zrHr$VYd8}#BLm~&Y=cY#d0+s`Dziu!h&70CCvSIOcZl6cx<3E0)s9!(|F5Sk0VfGr zJ{B<+k-FBcZM=~OJj?x5p48ox`?_hr&MpH!kbZtf#{VoV%uFmF48%cv1r`AVJ_8;$ zu7oxZ##CT>G+;!I4q(y)Mh7E<3AeAzSEK!Z6L-u$!XR+^0)VfGIwKZt*$rM_p#@wh|GNZ ijcKLluk-~G&(?XDPRa29lfcWxv&FgUq-2tU&Qbs)wq+s! literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidLongSerialNumberTest17EE.crt b/SecurityTests/nist-certs/ValidLongSerialNumberTest17EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..96186587225d25f35abd8be7b50210b726c18da2 GIT binary patch literal 946 zcmXqLVqRy^#58RIGZP~dlSmyS6Eh1d8#@Ol7dHd#AN85K^Mn-N{ z1_M7sZUas>=1>+kVW!YvLwN&P5Qj@xEF`tKM8P?=s3bEjGdZy&wOGN(z|hc8&OipF zfLU17CqFM;Avm=tGciZOuQWF)wMfC)(Lhd|*U-Sg5C|=d4GavT#CeSk42_IoT!VBH z?K3wph1jPTmY9>7qJYI#S65_rDu5hrXl~HNsD$iSMpg#qCPsb+pg0#(6C)$To~w-$ z65l+0v%Pzdx}eKO{j!_?*$ul)XY1axTjW~o`$&ygDcl@{k+A38@GD0Jt;ipTKKhc>2YPaVVkPxvxT~+R ztUuwX?yTEg_sb-}aDLb!gH82SPcQSYXUZ{-zp0Q@Agb1AecjYu-mdLf(CHmhvlG{7 z|FdgYd|P>*DsR-0lJ%c*CUnIg;OVpT_FFW2CR4OXJOAY@PI#l1%QiV!n4)VT#w_Nq|*{UCz zf2?id>gC^>_j?*|O$}){%xKMhs(fYboQEg(|77ByvD(om<5cNg=8Ck}Y#T1s>xCWr zv+ud%i$~259Fh%w8MJ5GtTHZKaxoz_vUl#6#10$JK;B1HUp38t2n(-Y!T7JFvf#>+2I2hPLY%mW?%*jkq@Jq~1RdCKo%*@NoOIL7CEXXVY zidQ9;Waj57xVj>{Q32#=Q-dZ(C1h_hvNA9?G4eA2#krW87#SJfJ#fs`)7jEnr8ZAL zBB}D)9sX^)Nh-VQX56{ZuN)=($LYu150C5RoqluKI5{4QPugkiVSQpTLyBjID#N^T z>mT1c-+JF*7c|{^LLs*5$h#>gH}l)x-Dss!v&&oX-+%4;lj0v1Khw&c{g(gTl!qJE z^#3;(<$f5|bhq8Tzt;Cy$6A94XUj9}SF+sMpK;7x;pJ{M<8}MnwzY22O-y{Tuq9%W z=>1a;tM6|uKhH4R?qu7^pb~@K1$yT%+|k;2E~;!tmz*d|MRnpoMfD5Kk6vDVq@|)> zCS28YcVGY;K%Ny;;Cr>b+G+xaj+N`CqznPqrOAARGMNhF4hQITJG@ z1LNXsgG>W?U`WdBTv3xKP2brh90!$MuxnV(VzHv4o|ryfB1Ul=fY!Wm>$QtHj9NF@4oBcv)1%^LrDPRTK3;x z;}0Ec`KR^t_4Pf%n{EZiEo6Oe@g_^^U8Zuc?op#F)7SPohy9&*`}MDi&BgJx9q|{9 zwN`ApwWV)6hmxB70nLxcn?!w|{ruB$(%eI!LT4`PulHu9vu3gOMP1%?Wk#&y+d65k zZ*r%(W<6nfqnu}ccYEgjSH&N%)LJeGS}l^5cZ-2t?)d81)rb6AL^sVk^~uC){eMH5 z&XeBzy0pvB_&4cv@U?VGy^=ItVrNm-dT&}r%>T0zd3yPNywaQR?%@5lUG~^|#V7d0g=^U#Q*>R literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidNameChainingWhitespaceTest3EE.crt b/SecurityTests/nist-certs/ValidNameChainingWhitespaceTest3EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..fc0f65d0796a9fd82dbcecc735aa9588a3f277ff GIT binary patch literal 923 zcmXqLVxDf$#8kh4nTe5!iILlYmyJ`a&7BVs^i{-nv$(LlfPui$rOfWc2{fhegE8Ux+eIxy?2&tz{4}If3z1b{F|KjDl*TkPIb$M)8*IP208 zAvVino=fwwQ>-dtjho~jaywjCJ<%JTf8$Mbhuyw?{k|P6YVA+9ZehHe!{kzTfTwlW z%U?n3zcMj1GB7UAHpn!P2Zpk&GK++PSc6CeV~dLP9_^qhUbagGibMjxuD3b~jwe|@ z7BLo)^ELpA?wp`x6eJvZD%Cmv6Kb(njx&GBC+ zEG}{U4`F)Wp7<+FN_t}4-821W1<5yCKAi1&|KY)jW4=EEdVZggjPCATb1+@l>EyS# z1dC5iNz5Kb&qUbsX4i>MKHU8;uv=qS`L)f~0%D4jX7Bj$!~gV&DKXp^e=UAmu>7|3 iOMCuPx6c@wZ>>LZ_+NLKsO5d>^1b)g?br5rdJO<0I$an5 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidNameChainingWhitespaceTest4EE.crt b/SecurityTests/nist-certs/ValidNameChainingWhitespaceTest4EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..a8ffc872cae3fcb86bf3917a93d68206152a7d09 GIT binary patch literal 924 zcmXqLVxD2p#MH2WnTe5!iIK;EmyJ`a&7h&j1wXVrpV!WZ0p* z{`2$18GD5Ld7=-@{jj)A`^J*WXv6G~cc<@sy5QozcCEncs7D3cFX`SbSn+_p;}p+X z)_?E&lHwvCD>~kHQc}zH^Rqi)`}g3fUoOW!zmzL2-e7pIm&YMd(c|3CJC@Uq&I~(q z`nvcVJF%84q7N=;Of>#=s$D(MCi$ec?^^bJvG1{)g4ALvU4w)Udu7{n<}wHFNzrPV z)t3;n)tNW{`O%NApE;IAui5&=^6icM3vc?mI14viv+L$KKK+N??#=Gc`U% zeYwf~@z-M}W=00a#n}d#2J*mAmQ`kvFc51HiC}C|k=~;nG{wtysX&oP;Met5C&BR~ z%f}+dA~IWhjo4pNj!NmZ{}{TTPWL!)Ze^MQA4oqxBjbM-7G@@v4+i2Oz5KXAG&=vldI&4Egl{EPR(Opl*_ zTx`Cz>;1aLQ&soxG%=B6nOatAEq3NtKwW}v?v=}u4+LBMZ{L`18nnKshkN@K<~fCa z-bw;I-#$IQUzhaK#Z@nb;YIT7UAal?ewOU6-*U@k=aU&{`ZEG~J}6|RoLm|@^=IFo zpvW>Q&o2jN_M5HFub6 k`)}mWWBTVZUHin|TZ}sdtTN5-KJr_(=g%2wW@$Yw070B#k^lez literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidNameUIDsTest6EE.crt b/SecurityTests/nist-certs/ValidNameUIDsTest6EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..7d0b70611374532bab250dea312061181daa4ef0 GIT binary patch literal 901 zcmXqLVs12OV#-{=%*4pV#K>sC%f_kI=F#?@mywa1mBGN?klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kWWb_X1(4g!44N2~kbT3* z%D~*j$j<;2=VEGNWMtUKVS3r`s^^5eoV&H9Bu?aNY<~ZB1NU=|^I2Nf4<>h(|C#)v zx+-#|@ix6Rl1X)`WubrfS}}Vi$M^Pj=kvB+5ese4sQ4UPJ#}(kkF0yjx%q+&5;IKB zU0BNC;M~AubyU;hty2jcYSH7DRTW3chgqlF0_4Lq@P z6VI!BTRtsmt`egT+o#8gR;CpvCv96*{4aHfe)q2Xn{Nb4MD4h0E;jRrlHlS8ivr%9 zJlg;L?MHLhxIorP%Fp)A{<+qyID zdqmEpb8IX>YqzJtZTq?F&(r_%NU!~Mi|y)8y-@bXRm(5Fj{U#O=wi33&s;fo=ltVZ zC(oMfTj88yo^W;AR*jWsSpNLq+rcZRUnP|)ysUoCD~ow^4?7%BsAx&4TX%1R?8}c^ z<2?jUoxa7>S!j4*ZTW(z2)1d*>fPM`dmhq%G|OV@A)cGhB~zy-t>cldT=wtS^eXc& zi`dwIaz0$SfQ4`A&NIa?B#*t#sx)J{=rnP;*X+zK4UgvX?7Mh2lbND` z!)8}kWcMn7JYZ;I(8Q>O>}N(+2IeM4eg>d87gG}>Bg0cg)8z-xNj(n`I9?xZtNs0C z<%($Tn(tNT7;Pt?bencz7WczAvu{<~G}g&^@4aDtfp>16!6YTt<;*(o7PhQuFF$_e zrG3+OvGWt`Bb}V?C?|xrslJrH$z;~s5oUYuL(;eCgu`}L^IkfwJbqug`}M8%Pg1El z$;%GBcV6g!$16!utGRw~UrHz9LE zh|@Q#&um+G_~sR!$%<{deC_Jwt*hRBbF(j$ek~E>uFTJJ*K%p~{j;t2bq-E$-?D70 z)k15N&u`Q&RtlO)Zn~H6m1*g@VEfAb(h83Qe=R>dhhuBnlZ{zE-!6KwGBGnUFfPtE z$TW}#2C}R&i-dt#gGka7J=0_SM_)|5z zFbM*qgOR~Xd2`{LLk_#FmlfGLPOp$>Nv~kop49d5&>`imTFrk&%_J&Jqg*O%{ET-c z#Hck01T;UJv@c_udFH;o8}*m?Ow(KGeKNx~(#>h|cB6pqq}$JLuieeyfxaOvt6w}MIlDo9?4 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidPolicyMappingTest11EE.crt b/SecurityTests/nist-certs/ValidPolicyMappingTest11EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..865c97542eecbae607874bf26cee1212e9e74a2b GIT binary patch literal 936 zcmXqLVqRj<#MHBZnTe4JhzxkyIJMe5+P?ELGIFyr7(^R#8*s8QhqAB5Mh0@?yoLq_hCpaxY+zszCC+PXU}$6v;~FHBXgN?f#B!~$ z#GK3&1vEQdU6CEE0P=yMp+OU)60)ZmSs9p{82K51;#^EkjEoHXuHK*9B64`WM~Xw{ zV)MGRD;}4;<}I0eV#Q^@+d+531q`!ig>$cTn|?^{;faHg^lM{Q zo3h0J6YtX9IX}64K4bept%Qh$TN~>|F zndR4a32GuizwIVY(3|pnO1kfg_N9G-{TUA%e_lT1@yw>RLg!pAo0fj#o(Fd(aNAe; zK98BaPB7@Zo;_dVYOR+>O9M6qtX4_0w|=`geWqAMD z>B~JEM0T!{U`y<@NEgbJk*415f^4LI4DLs{5_nL>jN#Dap%ymSS_l6+$Y zXGa4$ab80M14AIRFg7qSh!W>DHZU|YhH(v&Nwf{98)BPQSYl3Qib6nsPG)i?+*(&x zWEU!coNQ=h(8Q>O>`O*g2IeM4eg>d87gG}>Bf}c^*UN4lD@)|{S1~rU71vqsf9}@Z zA3Rg9@A=)Q&K}Dw{NnWadPW(8L`#M*U*CRN!L{tg{?k22H4aKMzh}>#bb;T-P+91$ z{%J$ORo8WY-{PvA$QNVZn5!{|BewSV$GV+MaNj_xJy@INfrUpS6CKl7>uc zc4?3C={IM(eqEZd)jN0UE3duAwk|@`GG5BeUu|<+sq{iZuKbHHTQ=LJ@_hWr=Iq%X z^i1j5$)|Sq(f0Fr7d{DW&F$~9$)A*;xpzsGuc+y+fd z><03{0G3r|kuVTz5c%_^H__Orp{CZf{a$>~@63;~2Zg{1LY9w3j73ELD)Y9F%RMr) zuV1xXk`I1dx^q6g5{!EH2JZ&IG2(6ovB4k_-hu&)^VUUtEbB?gTr z*jRvGWiV*mZ_v00*;DJK8rKwB5br4q3{NHIRYFobNq)fy3L_%Df?6y9GYlg`9jhAC zcN^W+jPPR|k+?4;ewP+RJ zw!JG1y~Q{ZTBKTAj#XDI<@KD~en;n`WM|X7^S=BK!e>o6_;vpN-#$^oAt(6%=3ZDe z{oJRPD<2oR+?|v$)4VO^V26oWUzwQpyx*D|4}Gk3U;O>$ha>i0iKi^8R{iTumX?iY KuYJRQ=^FrQB=G3~ literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidPolicyMappingTest13EE.crt b/SecurityTests/nist-certs/ValidPolicyMappingTest13EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..2d1b18c33f4194b5cf566fee2876161f2e986639 GIT binary patch literal 929 zcmXqLVxDWz#MHWgnTe5!iILHOmyJ`a&7lbKwp;G0-b zkeQdRU|5oGq~PpmAScdiXkcIngcimI1_n{$yv7EGM#eC%K{AQ90(C=d)e1|@$xKl| zv)0uW*`*2~ryCj@G%+e6`<9WFfw_s1p8+V&#ni;e$guO}=D%ro!}@k6g={un`Ga%X zToaE2)3=`#z3^XK-^}SvURG9HhKy71-7Wm| z{*Ql8PUXFsr%LTE&$)c4=Ir#F>+Yrgx)gqK!uCmlkENE^7P78buOs|PK-Qw%=9uHs zyDh?%wu|Bq-?uxmx*b2pR=-dU%5DQE3RylDF%}UU2O;P4FS*`K zT~sK!h`I3YvYgrg13r*`en!UsEG*1SEFTQSL3{-k0Ruh*9yYFoHV?*BVDd9yLXHk# z;sZtpBZJr5mD}IdM7o^j>-qL|X`QMw$K!;qP>_R5p zkOfhef>}pa)rCr!Pi!x4I4b8dq3m(az49m8CpjaP+PY`W_msH*`h4@(2ALBHHz%L| zRWM=I=7}!SXIhum|7Ez&uu}QbfnzLReT6C;HrA{Uc+Kc@@Iwy!zb~K7yw7*1y3XU@ z(ORDKI6|Yiu;N?Z(|L!Qzit*4Snz@Gg^axH)!HYQ9|bW<>^`A$>B;h$FN{Unx0P0z z|D3t6fL-?QJK@hyVk~Cwn5lMWw@gO9CA0g5Z3?A&dq>| UC+CI4ZXGV}$a&f~?avQx0H(}of&c&j literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidPolicyMappingTest14EE.crt b/SecurityTests/nist-certs/ValidPolicyMappingTest14EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..2487d626f7f9d9f3fdcf942ec67f36b7c743519e GIT binary patch literal 929 zcmXqLVxDWz#MHWgnTe4JhzxkyIJMe5+P?ELGIFyr7=##d8*s8QhqAB$iVkUgi}?(*rMFLIBk2j0B-+*PCG*Hx}J`?dEDA~cz?;O*wrDguiJ9T6g$s)`Q(i4!wdgEEaxsQyL^MiJ#M;s z_WnX{Med1rUhAvQN&l&KSiVrZfBqG{sA|sb>m`JO+fHBQnz3$vZsQe=+NB4UxXFE( z^3rE|qv7(*eRd@N!tBL8k@oH}HD&sM~U7jBcHm)<^1L@~yWc<&d{ZEkP;+5uK;!b_IxrzO5|1BefYQ`(`CNGSbdT37# z1lPDZx)yu2cPxtZv4gPe0434{UVzMA0~B#S#6%qeA=XL&*$lT|NVEZQTnv= z@;lK7p1xk*Gt~L+X}Rhz{`*9NmoajlnTe5!iILHOmyJ`a&7^cRIa}5oe7?qGc$jHjT+{DPw02Jq9YGPz$xVFY({)+_Zc}LjOmT2U=tMiInXNoz< zG(YNJS*2N*S!Yjkyl<8!ubTZM+rwWEUQ$kB5O&wR%yZXz(v-N4t51ZN#64vX7n{#~ z?(pi0x-T3C?tH;7_sf=KGc92B-C?HkZI4ge?CN{fsdbHO`okOKr@wq_C7%-U;2B3# z5wGB`={LT(yWh~2{m;wt@2~?~e&D^EBHPR(c9pzW^l>;bTdK!qqiMBS+Ul3Do}9im z)j;*&7MD3&AFz9Dm1c|5cZs<2O2Kirp`U=1#IIge(S575*zfR9S;gAY`ea>YmGKR> zoOuFo4tsdNPu4$^yNBgr;;QR$Zj-0oV~?FzRJZhH9_tOBzf8=G42+Aj4KfYnfnh7F z%mR$g29cRZD>6^p8kZfKxyI$`2EKngzuZ0!P6x7lEMhDoQy1CHKX|?`gLhZWDhGS^ z@Q8a|p$2>){rrrK|5;d=nOHs;h=ceFECL3620UzB32h#XslXIxz=Rwf!1M-;4n~I6 zdlzbdSQW_1WjDWEMP()<@W)XM*Q-}>~*+Zv|+87dkITEUNe1W$)n8hl-CX9b@WaU$o8S2q zM}A>a7tx$D^UQ-^UM-TEw&I-s--o&TDL7Xk-lI8YGcur;&jH#7@ny#GK3&g@F8= z%;ZYA<*u&C?o!h-QPv#^ft#x>fUMG>399Y;l%X|4*#uxHFr_C-r1v)H(edtJhncnpB^6ZtVuXZ z>7;98?p@&pMWzOvIee+_AM9o;d{n%CU2W!*iDtF8R%cImP$74Q{rR3x-9KI}7qyuc zV=r3pM`PJdp#`eR(p7!`7w?Im6Qo?qnHJx_-f3PYTc*y`;<@fJB`JO##UaVo^=6!g zEB@qd;w`G#nSb4A^7Io5^$|aJmc6|1=c*gP6%okm?WAs|mfE;w-rO36>#>Z7E(G-W z#&}9LKNo(rF6$8AW5@Hsrq@1{`zQuanRJ8o#N~gUKVQD@w|9SZguUnhBNHW?VA#qkvq%_-HHa|8TH5hHU8NPL`)yr@)>`A)wzG@DDMFTyMT|uxyl8*inq$2c z(i0BMpW?RUpIq>sC<8u_ett&A|12!bOe`M^#6f%o76Ai310FW6gf8U6kk6l|dP~dfojEdbd8B-_UN+Klt5B_wn8@E{cMG4lAZ4ZRFs&dG)%| zD#K;E`)Uebrt5`zjHlVZ?Ro1LxGkjkowR_iBi(PjFvS6fplxp2?&QGOrZ2 z@80ln)7x#Q;`iKRx%ai$v!Gs8EB4lg8(jZSYpq?`SLp6$bx$Bs;Ev3N;8jyuvd)SZ zc0T=LdFx_B!lOuc|D8{ty}W3uV7EF;F=687WL|y#?|hw#2AZL*W>f#So^lrt_!OF3 V-uCc|^2R;cJ&s;qmvWXp1^~x6TiO5s literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidPolicyMappingTest5EE.crt b/SecurityTests/nist-certs/ValidPolicyMappingTest5EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..d084fc7215863e33f2c18b8ba9da9b9ba8f96030 GIT binary patch literal 924 zcmXqLVxD2p#MH2WnTe5!iILHOmyJ`a&7ALlagybWA6NeTIcv!$rF!VE zxAW<}pPYm|Z3@%>x$TxW*d7$bcUJ7iz0wDtZ)+)S-fHpp*+7>>1XVdk%TRlkm3j^n_Ni3!7%huKE);n{&IMXR8mHdNSa{q^%&(E|iCVnV0 zdp7a2pndm&yc}j5zXBu0(qHZRwSF<1Vimq^Juf?5u0Vaore@93kM zFSizGeyW-C@fG*EY(DklscC;_@&A9OsKshHZ*SfA6O-PbVR+``SF&VtK>tbmj2Y~g zUz?{JDcqm@Q)21_G11kw|7LD|Ip4O@~ literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidPolicyMappingTest6EE.crt b/SecurityTests/nist-certs/ValidPolicyMappingTest6EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..97dd2e72c11b23225a0dd30e764770eeeb2d1b8a GIT binary patch literal 924 zcmXqLVxD2p#MH2WnTe4JhzxkyIJMe5+P?ELGIFyr7z7w{8*s8QhqAB zO1RywuE?%b06E*tpovil*`tiC49rc8{0u;GE~X|%Muzomk2Z!cUe79Vpl#pJPeRkW z^Ezt6%QBJ|lo-yv{5R<_*R}sYFWr?_3)7s_=D2#NOz9L^t`iOsGZ;Rvfu< z^_uIys$PyS=N`Se+fW}GR>D4^|8m66)&8emukO>Ct~@XI!@St(Q>ByM@}8cZ+3q>5 zk5}dMk?V6_$9yQ%@7%H^v|skgl>(pU1GAR~8K%X5_ULu2KCS&+FUp&z(AC?(A~)z< zyVr@EA)9V4H|;j&Jnq3fPqUg^Q*hxAl_T@hXPK+2pK{+~8soDhZQ1#`Ow5c7jEl1k zG7aQ`VJoZ5B4HrbAi^yEbSlGNEz64ar`^6e%t+;8db=B(9%T7g#8^Z&$KQ5jn#XxN zu{EUqMSy-5vSUwntgZK(80tS2rJZxMEZ61uNz?5geiX0ul zbO($MMuyCwN)49+mb3`BT?sD}REiI-vsRfkW1Hm3&SR^UBm?bcS}lK+a&$(iqVjyJ z+xNRKXzJXMw|<&^BX6QX{uLjp0DdM+qmNGt8Njl zYg&nllR1qh*65vI`L+L4da;GvR^5u#H#mELI~!TfUVE3Ot`U=h4P4~B~jP(-ydv9UGu65VUoOpuIFx++BpS~!X)pBEObD^3= U-nqx8WwtM`h*jCq|6++g0H&2+4*&oF literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidPolicyMappingTest9EE.crt b/SecurityTests/nist-certs/ValidPolicyMappingTest9EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..ef1ac897e08a3bb4831ce3972b28f6a785f8ae75 GIT binary patch literal 927 zcmXqLVxDc##MHcinTe5!iILHOmyJ`a&7A-4f18*?ZNn=n&ou%Wzx zEQrG;EEbYlT%zEdT2zvmmYJMbl3J`_WMF7$sBEAJQot-M6_A)$8IYfonOv#hn^;hg znU}6$Sdwp~;OuB1C(dhVU|ok?-MgJ9cPP%&c9!AtkwAMf4`_?wSdX-iaXZ`8h^9W z7X7D?vFBCY62EC3S0gT0FSaVlRNvCNuYax0GMP6H?^o~1lKF8hxVYFj|E`DpIgNMg z#0kxzFwOZ= zyhrctakWFXwO;16EvL(uw}qsOT)iiGP*(8xde5K_ob$RSKB%j^-^j$w$iTQb+aS|G z9vHT=$}AEFVhtkh%E~x;{LjL|%*67+KpezZU=c9jGvHz4N@(+7Oa&%B1N5W^j1EQy zAI~Lo8CLLg?mIqhmd0ZJ=G_}-R$o#{)~b#1NZQ5LCwIlT#MatYPbJXf@izN^ZU(X{ za^E~B6umV4VmM2z-LB=~%)jxB%Z?@=*qlDAZS&;6vBCP!T{74p52%DHBN zlw9S>kFQdf#Oz-Be)>+;?>{8h2_2{@?4P1?=sU0M%Ub0hPx=*&+xTCubGlPN2^UDks z4CGJ*1%S#+l9BWp3L5Z(%;gZ~@J%eL%t_2kG2}7e0tvASGaH+j!d#&z%;fB7AScdi zXkcIngcimI1_n{$yv7EGM#eC%K`Bf*k&bpXa0Xe$ENl~&n3I{J5ai};Y-C}e;0ts| zVo82crGjHgNl|7}X-TR=NM!-gudc4hepdhmhPgo#qY`rXF|sl+H!<=v0L8hOniv@w z?xq>EtUma6W{h#Px96nad^`M6&{oyXIre#^gXmrdBGGF z{trJYf8W%S(>&++JV!t0bMmzZWv8O=g(^Ldi%nqzu4ImP^4&W;DKRn5+PaoM8d z@A6~zcZw@jj-JxL?~y(^Giz4Xcaf_%6z1*cZ{NzqxFF49i8)iN+=`~B`@ZB(-Q~Dd zxR&qywo_|3_paTr`|#SQm!^o7knR~ycBGGDsnt+h4_nZZv zs*4ZFZPt2Iu>9j$CT2zk#>LqNnFjK};FeWpkuVTz5cv=&k@WtYsIbby^w(Cp;RiHC0;l@s{2>}u5qlZ-9LMZHetKleOY=dPg3b2vCbsHbNZSL1d` zt5s*B4$aB+deO0NX#w}KAQe8tXZ!p%#;Dy9dG}a}jrF<0S?0?NzI>jrtLRt8rfKT3 zuT3?!`IP?sX)B-GyGXBTrTMH&;qzu%LAtwNL{RXkMn-cQ{6plkGp5aaQGVm0MW5_sQ>@~ literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt b/SecurityTests/nist-certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..60a20316813bbcb0fbcad39e79b5c5538e0dad23 GIT binary patch literal 1022 zcmXqLV*X{&#PnzZGZP~d6CiMYb`dW8OZte{W~0=p^|>$^IX@p z7HfQ%b5C_}=xuuJYBFEpXtAR)>w)&L)j3?XzXbXemsQN}PY67@;l$$P-2CL@uWcD~ zS>oqOS? zHK)|R4|Dh$goA$1YQH7E@!hpvr|EN}j`ke$WnyMzU|gJSkZB+f3~gCu76}8f29eo$ z`SxAQzdYaCV;FsIruRgdnwq`f1SiYKBE}*TWxAz1HUDGZ+Tes$y~^{Jriy4d8}Nbj z^D{F3XJKJxV)ha~XNMBUH~*X Bbx{BS literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidRFC822nameConstraintsTest21EE.crt b/SecurityTests/nist-certs/ValidRFC822nameConstraintsTest21EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..576a1b81716124a048d3486659d8348acdb18fb9 GIT binary patch literal 991 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 K>MCU}y8{5^S9oUt literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt b/SecurityTests/nist-certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..0a4e150700fa7c754cca75eaf6a32664a1be50f2 GIT binary patch literal 965 zcmXqLVm@fl#I$k&GZP~d6CB(+$<$iUFh(A>Zjq=1=6FDO4JC%-JUNFl8#KUX23 zC^N4lF)1fCxCF>bS18F>2n}(wfbyIj4dldm4GjzofzZO(z`!6%oY&aE(8w6ZH7Fs` zAua|^5QkWYCFW$ND8QYA-zBcDU{5K4ya#ko6QdGxh%mA;FgG#sGXTZ8n3@ zwJ)DdVf(#C*LSDN)^B|so{=l0mD@N=SDCzW5!-H)a$$4k4-bYx2yZ*fnDF# zj@AlF%w9f=J0)4Z?4^bv@0EWQ4^vH3R!doz-Ha{0_5At5_~(aNy)HkF;k8<+hfgl_@TW4A4oqxBjbM-7G@@v4+i2Oz5uD>YI({J5d$%QW_NNnx9RH=6O z;XK6|o41yA#jIQr{=}_j6N8A4o_FmVsjTA*_cr$wcr>u>c0ZN3Pk(jej3nom_UQY&=I#zQaSt-^X+IpXEc3l~9=B@?kAv>zOt)L- fSLpCx=S?`6BqDn2{sb95tN*Dh@5>((EYt-61aE3G literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt b/SecurityTests/nist-certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..16968ab59b17dcdfcefe4c9fc7bb1f7546f092bc GIT binary patch literal 939 zcmXqLVqR|0#MHllnTe5!iILHOmyJ`a&7eGujZa` z+8lC;Q(gV&wekqdCHsz@J1ir}2P{fSq0{-r-xy4O}bxi+z{XNN{$_@=im6Lqz|DEyoFd!Y&2ElVHaTPK9C7z%{U zlU&xvXE|TMNVX?vv;C>BKN6NU2G%T}nE6BW#r5LPRgxNW>aBJ7!rOPh`S5l6g$3uH zn{J-GDJt#j)_oS2_OJNs9SDtBN>^ir(*1b~^ala5>uv!|CGZCscSD zUeju2VrFDuT%2u?365M@Wflnou?CSI);ss>Qf?>hyX_sA(vy{TBWCepaPpAlV-aH! zxw&+~(U;pVp8Mu3blp#2a?Iz507e5oU`)yKGcx{XVPR%s`CuRp;w!KS81NbJuyG}{ zc`&8|6QTinG6Y5kBZKnv^Aqf+X1ouwb!E8S#ZwsrDfMt+p1oC zC$hTw_@vWc*aH5^Jqt^j`>ELM{G};N)}Am6>k8k=>GAr_WZuJ%5A{y4+kN*_ype0y z+B45*T@}?h`9x~LDH-AWl4{q@Q;&2fywUBo(p~oAT7pZMhOW*TSBd$2EX{gC*S(A) zf)y24%r4D&nQ_nZbn9W;o%{YWL@>FQ{r$Qj^l-6gzV`3;TCPP*K__>~${**edAa&U z;BE)esXLlZ7k6&h{5x&No-6^cc@kN-A0=?zkZm0NDI+1poj5 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt b/SecurityTests/nist-certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..1516f1ee703deb808b4090602849b568994e0187 GIT binary patch literal 939 zcmXqLVqR|0#MHllnTe5!iIK&CmyJ`a&7TRNw#~7Jv+^IyUER|& zFF2-Z@!@;xo)^BnxhqX>>eI>#3dN7DKEFP7*FXM|>)k_JH3iNVnm!3Ad>QK6m44&l zezwi>pVuf)*tYN8ZW&drh^r}`_fE#1J9g9N_eH(LVwEHf+oe-_LXMiwJI?lR6@PzS z=HKsm8{c=iP3*aG_ekZYWCJ}hjlS>KGUev&}HR?ZZ@`eoI$-*+u4|6iz9%{AZy#*{2SBjbM-7G@@v4+i2Oz5r1}?-p3b0 z5`Xq~GS<&ZUGevW>CHaJ0}o=DxvfhKO5}U@?2^t(5Nta3qL|M~{B-G$bD#a5{0lGJ zykX(X(%5Q6t6ng$v?MkYn{19<5&utlS<3ALpI#KOe?Nmba2ss6mVJK z{%nrTjY{^%PXF_BFJKFeap-z{dBOS>wp0BJl5ZOvpQ=~RZ-3*puIoE}U&ey(7jCUy g^6$alP>v;MCRWWa-YIzR`=*b&#h*`BNxbs`0KN8hng9R* literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt b/SecurityTests/nist-certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..a4385c1d959fb0db9d56ebcdaf99f6e63bdee257 GIT binary patch literal 949 zcmXqLV%})b#58jOGZP~d6CB(+$<$iUFhP~AWkq<~piE;BD9GbytqAU`KFxzabW zpdd3Z-B2OGP@%Xq$=T6BPMp`!z`zg)EsPBe45Gw&jSUQqjA2}Z5)v(TF>r!dY#o-E zlbNCroSKuS>see}nwp}3%_$15uE@?;0QtwO z794$2J9AnY@9(D@Zu3n2b;>Z z`*JJQgNl)UPycRWFrBk>QNiu|9+&F(z5A!{v?=#a>6)ht4m?u-b9kzb)AwsO`#N$v zf}Wjna^c?QyIz<_mC$>#q%$o-z447SXsF3 zzPI{DldDVPnYEdi85tNCXB%W1$OA)LR+&Y@K&(OJ^I3NLW`oPenUZcjJC(z@bmO*$ z)8K?6%f}+dBBI;U@;@g=n!m}#F1XG8a)8m3zgrCWK>GO^8UM4eFf*}yFc1gv6<7oe z_zZa1xDwht7*l~s(trs$I)Dih7#)lZE=v#ZcgpGEvD@_RsA$m1sM@1h_2G{+^KTYE zF3tfOaQvyY|=wEO-&?YcKM`e4-#ZZog# zH%lKnF>k-VASuwg=SP9+CYQ$(l9P{nZRRrJC_9;$^?cRR{*K<6xBtBUZ1mx9{JC(Y z)e|)J4nOp1OLFIK=-@m&@o7k3uilmKO6s=+0;ik#J=7}np4)e`^tH*6!}9~2{PS-I mUe9Z0^llN!}Vh-&TD93U6<%}LYs zEG{lhO;Nybfr6_mvXd1+elRpOXkt`C_BJCc19KB2KLb#li>Zl`kzvbuwkt2&J@prT znSDPhFzJ3=v+}<3japx%Q#~SPKJ}R)B^Sb-=vH9-W4k5avlF|*>WtEVeOS@Vd(tm@ z;`XOIZ{3Oy`yY5V#d3?E9vou|JFNd+4v+=X*|f?NR=j zOw5c7jEl1kG7aQ`VJ)l7B4HrbAky%Fcku$gOQ~!@fg&@0;c~o)1_nS-+k0 z(K&5*DtZb>wZ-l(o8GO7kER>V)AsIZpXI~k9J*lRzu(78Z9CX5H%c6x>7HsnS5o7f zlSN~3+DYdh!H!zuy_K%oZtKF5`4$OnOwya#n5`?3aCc$<{%gzk>`lm;U%t~+>D{8` z<@yzeU-4%5o~`t7o2&XgzHCAyzqG?8vXV|;1qL)xiS-j*+Y~b c&6SEanw*h;s_^Hh9X_iWCRE%M^Z2m=0B|{EL;wH) literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidSelfIssuedpathLenConstraintTest17EE.crt b/SecurityTests/nist-certs/ValidSelfIssuedpathLenConstraintTest17EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..ed346760878c83be35ac86cafdb712f0b6890a87 GIT binary patch literal 941 zcmXqLVqR&`#58dMGZP~d5E<~YacZ@Bw0-AgWaMULFbFi{HsEAq4rO5zW(o~9lsAwC zakzxVLQ;!M6r59wN;1At?lbjt5-bIbwzfy0>~SN<_1lSO2|HEWMyD(V&rE4igPhFF)}hNtG^yA?A*Mv zVMop9SldIt>)$2?Tx~qFi$(PN%^!AepOo~5I=qvav^i_`ql1kN3F&QBLT4C#RZA+UprT=2|JM|!r@Y6hI-m1%YF*Do?*>;Zi$IKH^yh)}O zSEeTfynZ)h_Q&s zJ-;u&^Wj42O3qvRbT4l+n{@E!WCK26T*>k?GX7^_VP<0aU?2|SE3gO{@EP#1aV4~Q zFs1^Nq5&gvbN~|~Fgh3+#KO81pQeA?$L^WHHf!Zt_5Y7}TT-4d+a>nR>D(72?tFJe z(fRhNnU7P~ztj=(i4)DAD)Z#cLe>_wT+@gX+V}F9Ro`D#tC?wE|4A!Q@<(g(lcwg@ zKRH>KH$*WCGt|8gi%QnBVt;PyuXgmB#{bTvYyGdxWp)U#e%CD^dvx}zeAhrrErBEJ zUxZ0EnsWPoED>lrWdAdEBlo+P&EgfazPN8;aXw>e`R?&9<5f5Om&iXl@b2DiW=Yrc z*I1A16nvc+yiZ`myA>C^ETm*LCjX7=e)QaQdEw6T)vntY82{Rl!~OT^$?h2rhPC=k dipux?dTrmZusk|`(|JRta2FoO_2q4P^#JtKZJ+=E literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt b/SecurityTests/nist-certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..22179d72995126384641c4f1fd651520528862be GIT binary patch literal 945 zcmXqLVqR;|#58pQGZP~d5E<~YacZ@Bw0-AgWaMULFbFc_HsEAq4rO5zW(o~9lsAwC zakzxVLQ;!M6r59wN;1-U6Gxx0P>5OK@+1AvhNvL8JL?G`5A!XTue=jj10HUR1eN})AjN{ z)_Rx!d#h#aA(>-OHMU(e`S|A3cBSwIRc9sK16J)9Epd5pDlzd>&eg!joD)yX{gfwW z*4pI8bn^FpXP3_NM|PcD@6r2*ze~iAbJnHRMJIw2D_vdZE-<~pyv@b_tX^cEx6ZCa zd-paQSC)`Um3KG8(_M}=G67NntyIJpS*H=!r^m@*&)@; zyWjFIa=Rcu^PJdxbFX(71j2%y&&{6p!fs#P=8w-V>u|_PIS6cc;c)(8!=5QQ&o1-* zFZh-l`yfeB@Y@uF)m3|#otBH72~_fUe8}m?oZc&5vrqiI6Du^WEq>|y)nz<4KNO}` exj%oj?pnA{^xcTZ4>%_8Rdd+8qaZb2*aiS2{co87 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidURInameConstraintsTest34EE.crt b/SecurityTests/nist-certs/ValidURInameConstraintsTest34EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..be8ef42f19a6dee9e656112ba1eb9aacce842772 GIT binary patch literal 994 zcmXqLV!mh4#B^){GZP~d6CB(+$<$iUFhP{BYBq<~piJTEaf)j2<}xTGjCGq0pr zAvDO-P{G;JKu(<3(7?bD2rY~a3=E>gd5sMWjf`PjgA5XFv@kG(*r*?tn3I_TvPS{k zZdX@irz(KlZfs)E#HfVqT}D<0<|amd2B0_>QxhX2!?`E%-w!4fAAQa6wEyxSp&!e_ zXRYa&6r=I&&%9}j-EpgG)z6a~O#(_es7HQeW%=x5rD@lIk%JaTP5~}9! z=gP@5wrMu{&;DfCG$S@E_~Y(I>GiE2L|^YeyV_EJmP)GG+Eo#E4ZUA|d-zLNf!nc7 z{>fy^iPM<&u9+_9V)~_Vb>LP{$paUfnU8?5!+&YxkxvurS}x_Ub}Okhj)+!^w7hi|o0M9}UiDVrFDuT->b=yQh^Qeu7^{*vfknW8&wz)GE1}JUF%_5s4Hyk< zKoWv1rUu4sh8ZO#1y=g{z{FKjoLW?tTBHYJCL<*}z4ZJt{mi_S)C#?flH45R=me%- zV01Dv1h5~_5w3bLRXXqB=7|%Eo+@zg*t4r>#T*M(P+uzYP*U*u6{Cin533$L@0_CF zVpNy5=D`HPh=2Z9M9VX6Cj81>;$j{6@1V_ppC7qLPJek;7g4zL#kUoyO8Yp)>=Jx^ znG4J%CcZmx?n>WrmGAufZ(KYTVx<+Ft;;xbg6-T3wI?!9C@@_)%a_S_+bivqrEi^Z z{c-c;qm^MRlFYyRIh8)&xbhRLwqRS`;*2jZ4(aE38HX$L9&1uvQJ&Xbetn|O$>a$) z7_P}KSLW1G{IYh>WaG#{*?*U>^v_=^Ui3|9(Vq|g#T_Sh$E1C2o3Q#@gYWMvw|E&V SKZUqB(+$<$iUFhP{BYBq<~piJTEaf)j2<}xTGjCGq0pr zAvDO-NWt0BKu(<3(7?bD2rY~a3=E>gd5sMWjf`PjgA5XFv@kG(*r*?tn3I_TvPS{k zZdX@irz(KlZfs`I#HfVqT}D<0<|amd2B0_>QxhX2!crS1=ueogOXl&Ze@iLdILr=y3velx06OBG>xtVg8{r-pi zF3uktQWw_uB^k&iD27yjKDx?c&A)vm$NMebS0CGcI>GHy+uIz)=F64l*)i|#IR1)X z7Vc17$yk_hkb`eB>->vr?#jCTR(U7y5zKx|*rnl7;VrE?xu-MhO^p@T&)R%vP5b7i zo@quNTvh!t@7FTuxE>X-y(_Nw$SdId+sFdrx)nxlet{dmtLrHg{GBJy9%|fjFVG{W z@z@%r&P`9Bo3}U%9PvxtJu%?y#aNY=uJCsW-|Kd+m;F;Z-)vHFlPnW6BLm~&#wP@e8#NSjuick-2aTOeLv{`G*>eJ%|E-+AYDccErm}7eH$Bu9FtEu zGzZ>)amG$nsej6mHR24O?aynBVs<{?H8YQ^_(s;2Gg_?kodS~oKHep9Q9$p-gUb`S z-p0g>RekOGdL%QzBlCVo)Y7jxq?eA^doF?MK|e&(>(UL$?O z1eLW`hVB_c7c}Kt^wtZnd&II^%Xj(#Us3k|vg$t#6dk6yUNK#M|5yHdp`W|@S5`!Y T>m`>{YLH8e0V1VRgA0|SF7ab9BsLnC7t*Psm5 z4e|!E5I2a0fL!2=?gB$M0~d(>wqc1mnJEgPA#N7I5LY;ZT;Yl22w$)xTwRfkQ2?21 zXlT&HsDvCGjI0dIO^o~uKyfanCPqevyL-<}+SL-|_N+kfRFk;JX6sm$Fzbm<-JDxH z?@fK;baU>C3FedECT}aYykhCDx#G1e)4Y=}Z+0eJd8YU|asHl#yBnu$IV!{OzpQfa zqnjH$@>b=4>K5KU_1iN?v9H+z59*$W9`yWB%9$T$dcM9(j1VohF^% zL+czX`c-$bemhl}QXI0@M}3M>=?(w9={Hh$U&~dTKPAU2hCN%$Otv&cr@L~IP20lN zPJ$}8%{|p@i#i=`ME|U8ala}x{aW+`q4njuTzTg&DJ2)r;Jp>na`JDp&IwRt8KG6jyY)RQ@$TcLlwUxnhUIwy#k~$ahRN15^`iBYo!IYlo*%p;Iul0BIt#NVO zw#Z8Pez)q{BF?o*pPRZDbHp9~(f;uV>x!N47Oj}@QuTfEpIN)y4FV)zh}&kHk&=??L5Cq zq4w%wxAO;YJWzWUG`aqpZ^drc`(8#SAI~p}W!}TWcYBuLwjFww8nM%!+5K`|#akI_ z_}b(29M8u;zb{YS9{yzKD;tAF{=05()!=Q_^6p;hbYtUv&zLCPzMoz*8Y0g|%qhrz IxcJ;$0Gw=jI{*Lx literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidUTF8StringEncodedNamesTest9EE.crt b/SecurityTests/nist-certs/ValidUTF8StringEncodedNamesTest9EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..b14d789b5dc1666a530f10a0b886505bf1b452b4 GIT binary patch literal 924 zcmXqLVxD2p#MH2WnTe5!iILHOmyJ`a&7}Vh- z&TD93UQxhX2!y{+Kdp|h~4sUW3pVy~XdNq6f z`2(gq=bTy4YMRXcKPYr_>&?S`TSE3P$+30ZZgHD!vFGeAdv6!E86{qBsi&lh!{-5G~^7#4#7bU0HEYdZtV)(tNt;t50MdpkC495?~ zZfpKkUz?lK5Ov~2PTK^|ZEUqmF9+JGif{kye7NIMPE}nEL(Y9!r6po{j0}v6vkfv0 ze)i>cQx;(d_zPl8W=z9M%_#yI;-^NgLm$kuxy%6sRD^E}so_f+(f&+B(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`PjgK`qBaW`;D$B{41PpTwu)Ggu#c z5^#8*ZK~b6mK*!E7KSCQPX4E)mGQCW#*DdIE^1Z3X8OC%-O_&W$LR>3)&{m5!@nCc zT6fDQGBGnUFfOh&s5X!X2Dq#;i-dt#gUFNG_=_=9+cTlQ|Y9RlX;aAQs zA6?10QzT1GdG4%VSY2-)cQm&DWRmwA-#xo*3JT5E#U=1+x!AU>(B^u&E?jQKyH#0Q z)Bndu#!kOl5VFH|!`r{VlPa8Ff82C1d76hp;J42&H(Gx%`e4xYj-&g*(cMjJPHlR4 x?B%wFug?8We4=rY#lwxAv455Ity$9;Za>SYwOMt&?98fp0WTM9=K68*6#xnEZ^-}v literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidbasicConstraintsNotCriticalTest4EE.crt b/SecurityTests/nist-certs/ValidbasicConstraintsNotCriticalTest4EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..4059c017a744057b8083a7834941abc563b98b98 GIT binary patch literal 948 zcmXqLV%}iT#57|8GZP~d6CB(+$<$iUFhP}4viq<~piAt|vqGub&muehWrF*C2E zSivtJsG%sc1gJbm!P(J3PMp`!z`zg)EsPBe45Gw&jSUQqjA2}ZLK3ZZG_Z$QZ4s83 zlbJ%m0j{pdu2%qg$HbtCQ3*K!7+D#Zn;7{SfZ|+CO^l2T`=)$7|6~cvjvb|uFJc%C$Dn_r<2bj!2B?c~lJt8EP5Hy=5Yc4rIc+N-&L zCOU63=vKMCcUeudi^{LNk_))iEZ7oHrIkF|;>XN1Gq5Yy%Xh*bx0Me>PG;Xv-C@Of zz1+c|=qq1Td8nc3{T4o#JGcI@-_V_UYPF7K`t$E4*|%S+I`y*NS=cn~i1Irz4|6vbI-oG(UlmB+bwc^F|6TD2!j0}v6 zvkfv0J@9lVpf%Nk;GX7^_VP<0aU?2|SE3gO{@EP#1aV4~QFs1@iqyc(* z1V#rVgOF@=aYYG3s`{k0lQ=Dv-E-eA>`0Y!ufA5*UYc3;=EIk?l|8+se7{p$=C}KZ z>Nx&ox^ORIYPVR*lDX@#ovxTI&kv3@rQ|R&g$Ie%WtLy z&r5Edbuq!bzD7-JIhTzR>w@lJfOni)TQ zP|Fh7eoZeX$c16jo1*ZD*HMoQnJTY;=(e52_B!Kwc=V&&78`l{1Rnifb@OvcR)}c6 zT*7|^r41{#`MUO3-*5kN*JAe3PpcbUe!Lb=oGsF6f2K2w*3_J|E4LI4DLs{5_nL>jNSZejk+yp+tM)Z`N9ARh&1M`Hsy zab80M14AIRFg7qSh!W>DHZU|YhH(wzNVG}MKnG+Kv#@GdVoqj?LUNFgXK`_9YLSAg zE3(5BKrS`1Flb^_LiQXZD+6;ABR>OBoQtW6k&)p*5$nzAGGF(dn!SE{biMxl#@0Tr z&wgpS+w`sq$*WIyk3O+%kzMrtV@vICbWO59VU%}7Q`NX|!z`w3r^wwp>#BoZOiRwY zx1eaMNupHV#rRVe=d@Xze{1c#xFPhb$dt%sh4Jx7EH=@-3S;7Y3wq z>K1AKUf8sH(RZ%N0>yh69nx8KrmYrZX`!GB7S~VvGfb zNTh*0Fl=R&S%A^mAmTAOr1nUz!GGOw*Fu&1KCJV-7<9quK$ee1j76lmdS-B1%Eq0U zr{2tBoO?sTqCoPr0Ut;|KO^IR78YhEmJbHvAie^NfB~NY4;xoPn+IbmFvS@#8Z^EI z$;h)bJ~e23WYBnjL1W8;#>OS}2DK!n2PFdqph>`#CyAEw5Glh@(?A`hhFMqvrbYpj zJk#=v-~!O(x+rW(h(Qqboq(JKf%yxV1Q{7}S8QnzE?DzrqgP-xPy zFQp3>_fCs+{h{BKALnt}k&E|}TT#=4rh*44eDUv#!v4I-|HQO^+rhNA2iGo5<-IDW zC;siUee-njz|!9p7CB}rYW$0O6dKZh*}L(5d{w$igI6o&d)t4Z-LwTmb1Y+I$YuIbr{WfvXhq)*x1 z+06B)I8u@Gz}mYVi?;BsWoDnPWHwc?yJ*73Wh$ydvsU@!&yLzI|MKU>XUtnn-tKT+ pq39^n**xieRjJj>HBT>HN!icZDL(7VgBuU+cQ!9QbYI0F4giw4m#hE) literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidcRLIssuerTest29EE.crt b/SecurityTests/nist-certs/ValidcRLIssuerTest29EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..b10632b2093202d3c7f20951127be77e600a6f50 GIT binary patch literal 1065 zcmXqLVo^0{V&+}I%*4pV#K>&G%f_kI=F#?@mywa1mBGNnklTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kWlrRtjDc~07&&*57EJ{r-aSrlPaCS5{ zkQ3)MG%zp(LJMO91A{1WUSk78BV!oXAdWBFBpdKINFaU^wc1`JkufMR^gu`zKyZ<`ggeDE~J6M#G|MUp8#)-+S=z z#0Tfi_I0q#+P-e)4J!frj%9y;+X$P?+Q^h3Ror{rhvCqdfLX~4EagT0{=AWodsBNe z;laXtor6K^;4Ys z@mp2PYp0&QvdFum>PW0w{UgQ3fE@dnMV(CVlIQrW=KIo}ercI~Ia}_A{}M~Jl>RNe zeTb(yvZM3GM8n>*|8}g#9vHN;$}GUxY!LC798!BE*WkZyxND)xeIM5OUJSb6WFX7OBE}-}f6ts$rJSb*uf{@b*FcSdN2_u8FQHQm-y9&$6bAC#~hrK;s_0HV!g?+D8zrx+$M_Gy& zXFlO!T4P^UlG{}~ebSkB?(6J7A0)*8pT%~6=j=0Y0~gNv+z_)SP*wT=GIk!tGBy4+ zhGu1VKR*eINfy0#%zU+^!oHanmg!3-R^7BR%HQ;nwM#5BbJ4ynzP3Mjje1Nv4xRs# zeQCm{o8E5W53Q;b7rLKHdXtbERq+1A*MmF0w?vk$c8i`I(ZQy#AQSi~OzfqA->r8q zwiX}f<#bCk`2Fl($B~K8kGdSvzq9m@iF1A*OX{i~p7U8ej$B8!oHjVUOWrwa&0;V1 h$8oRQIQ^2Z3D{X4(r}%d$i3m6ZRV$v*L#-j0|0N#gY5tS literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidcRLIssuerTest30EE.crt b/SecurityTests/nist-certs/ValidcRLIssuerTest30EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..593ef98e3508a0ead415308724ce1d0e45e4f010 GIT binary patch literal 1156 zcmXqLVrejFV$N8=%*4n9L*3_J|E4LI4DLs{5_nL>jNSZejk+yp+tM)Z`N9ARh&1M-u}% zab80M14AIRFg7qSh!W>DHZU|YhH(wzNVG}MKnG+Kv#@GdVoqj?LUNFgXK`_9YLSAg zE3(5BKrRK^*u^VkO2IeM4eg>d87gG}>Bg3V0U7YXoRCm3O-F=1A!BRTeN%d2e zh#%Xj$y2=cC_Q3%wDNHBv{o0UmxBEE0#j^$=DxVTX5GHyY8!ZzmsYRSYs|cO-TLpz zsp6ZmCnPYfF6*+RZ z^!{7D@X5PZzR9XdyQVB%V#>7N((J3{jl$v_dVgJyn)T+T{m+1&V26oXjzP{5?8VNm zTA3S{e?L~k#m~ix`W@l8vt0I9EOFc8d#r zdRew+g-43cX#+lxett&A|12!bOe`M^#6f%o76Ai310FW6gfJ4g1Ob<#13P6*9DNhnDN^2B2?FyMFbOg;*m=)m5&63OlGB9m=brZD7?=IZTYTZ=r5!CI zt4izkO=D20)>V;o{5ff^!HM+?-X!mlsCx1{xy1YCVvj(sd~u)M5*d%9C71g*Tu*a2 zyq^Ei3WbZ+S;@(K9;f-O=5TtgYu*3h(7#8aqGHXrvZS)UF4)Duy*@o!eaDH7GyG@p z?YZuo9;?3Kd{<+oeM6dF+9Qj}?OuZ79#)I{Cl<`@`qw zB_+ni>C4!4x9#=L)&JNoVJ@0&z^$|1ZK;6a|NI4IH}!RI?Nohx{HVBxYTzF~m7B%~ m*~^0J?;dz+?$vA5VQX_Q>-ssv?#$QX*2_h2I6f-Aun+(!=982F literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidcRLIssuerTest33EE.crt b/SecurityTests/nist-certs/ValidcRLIssuerTest33EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..2ae810abf9d9921c4f6b0766a07288a82dd30912 GIT binary patch literal 1134 zcmXqLV#zXSVh&os%*4pV#K>;I%f_kI=F#?@mywa1mBGNnklTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kWlrRtjDPR`n&&*57EJ{r-aSrlPaCS5^ zkQ3)MG%zp(LJMO91A{1WUSk78BV!oXAdWC=~IAmmP zU|*co7c=RY*X+`C}CaD~P9f2*w*8=N>J!Rj&d=Hcy^C2GztzN+=F6#P{&bo~(I~PF75LHa#na_t~D$O^$^#Qa)Bb)n;O5WMEv}#OMwT z5oZH=VA#qkvjC&BK}7zfLNE8?9Nlt%;d@SBxVPQYDl-J916e*6F&2?&FN#lJtYrMx z*{`@z=cvRCj?>NR27Dm>{EUqMSy-5vSUwntgZK(80tS2rJZxMEZ61uNz!Yb|XwY~a zBqPt#c;2A#j6vhc1(gfRmy{Y5lb9Ny>5dyc-I*F{8mI$p0H#OBDerF zi7xV4;ze$P$FvwZu>o@uFtIT*)O}meG1;w5^PBrdhNGq1ob?|{1`BJS@%Z`m+|q`0!inYA){fEjtSS%S{#5PiXNIY3FCX zzhbS{g5_V=Gxy14_j^6c;@Nwc|AI?s<)y9f!d>3AsXDsHANYQ5Z@KJ?d5dRuE=}#X z&@S_DI(FyYx9vtoJ7-D#kY2De(sBJQZ{;W7cr7?bApP1__Lj;Uo}4*< zBEES4a+SZhA?y jQOzI`!DPAcaNA$?JN_QO#}Rerr|nP16}Ic;ABY10wd0vL literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidinhibitAnyPolicyTest2EE.crt b/SecurityTests/nist-certs/ValidinhibitAnyPolicyTest2EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..df4ba444504e657ec4e81273b54f88c18e8b3332 GIT binary patch literal 931 zcmXqLVxDi%#MHiknTe4JhzxkyIJMe5+P?ELGIFyr82B1;8*s8QhqABc^R2WnI(>Sl>zxVnaPy~ z3eJuOa^k#(1_p*eXklz%U=StFYiwX>WDMgPq>yNxiGdNsI_?Lech;@Tf*D3rud+ZDL0QGOQM?2mOX3x4?g?0 zI#vIV@yn`^ztT44To3h*ebu+@J7UqwsO^IRMZNuum)ZAPm#bZS&)2g`Us`u76793q9cV+21lcl#mWDB@Ba#@Ssby>Uh z(9YeyT03@075Q$weIw)H76z{T?~kmmU+Ysl(!!h&dq3rv$qePrmwDQ1Yvn)9ETm>C%u7Z)288ps1fS5}!t z!a%G+L}I~$s;vK6b6cBK&K_24{jtBxoDG~DWcgUcSVYbpRO6X{qN{xMYROLZ65*$@ z6Ln4*@PYL6Gcx{XVPR%s`2aCb0c4&58yicgtOA1p4;xoPn+IbmFaa7cB1a1_`2nMa zkzxM1BT-V%Y%a69Z49~@aw*pB|DDIrkB4`&->nJj?@FHjp}?^3WA?%$(K_d>x3Fr& zr&WFE-+z4V`733~we2Vw>A%BU#XlX5vD(od zv0ilha+k>ty)UK9m^?*<-<@9bWbZ8r@8HQR&uh=SJ9U@Jr~A8n^#o-XYTbQp^K$RY z$)ZOtesSQO8OXHdPS<9s{ZqP_9ysv*(LDFcvTJhac~7Y~dKcp7-JVgRfA-o@F|i*K z$09}L^|zVq=2_~!?^|lpSyr(*x3ZphPKq??`Mmya=uhRjF&S8cC literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidinhibitPolicyMappingTest2EE.crt b/SecurityTests/nist-certs/ValidinhibitPolicyMappingTest2EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..f13524a0dce9bcce2e6535b5b88b107abf5cc16e GIT binary patch literal 938 zcmXqLVqRv@#MHNdnTe5!iILHOmyJ`a&7`9IZm1AoXrxeFn&j+gAScdiXkcIngcimI1_n{$yv7EGM#eC%K?aF7TNs!@Y}OA; z%*jkqz-GUKt1Ggb6+oUaGH7B{LiRQzD+6;ABR>OBoQtW6k&)rUMYDEgqgkEaN3RRj zc2)LYdZ&8&)8(jZNA|==FJoB{wCMV&ofjgfGKPD;W)acVXb#J{bf(4UrU-NBqTlX1 zzt%Qhyd2yH?V3}-e9-GAjZ$`4#VQT zNmn-T=a@eJ`Yp&VMQKfc`j%(&{avzCOal(dDtO7w;#5%lBa!<-LO65k4uku*yT5Dg zpZzDVFfZJ}uR+n=+WocI8>P95Tg%r+S`?mI8CG8_e#$H+eyXZT?6J2ew~02LX;>)q zH)@^QU7OfksGeg93y;CYlU(u@ zop*K}|MuB>OId2A_tSuOo0-LY6P60R{*#hEd)MUhAB@&_bZ#A6lYPv#u;XcJ^NeLv zT6NzwDXXcy)G-Z`-&SUO%r;^De&*G);v-e3ckygddbS{5BPTTT?aJf}H7|EYh1Pg& zS9TB7Njk~(c)?|c6(@Elhd*Om{(5@6m>BDHbIv_3*N%E#;%B}xjk|yPs@)pj&9YJ# zFZo)$V#{qiZoZo}*Iq7gR&T#D`BBftFW(!t-qQ1a?jpDE)`VB;&qOND-|lQr|MrD- Ybpr3Il4ku*%dYeNUYbv;o(FFL0C6c{v;Y7A literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidinhibitPolicyMappingTest4EE.crt b/SecurityTests/nist-certs/ValidinhibitPolicyMappingTest4EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..75daa870284699a2fe11cf97455de1633fdfd3e2 GIT binary patch literal 941 zcmXqLVqR&`#58dMGZP~d5E<~YacZ@Bw0-AgWaMULFo-tfHsEAq4rO5zW(o~9lsAwC zakzxVLQ;!M6r59wN;1}` zGV{_66#@*66pBlefXLa=Ku(<3(7?bD2rY~a3=E>gd5sMWjf`PjgA5Waw=gh+Sgs$I zn3I{JfXxXCuCB<=Rsi|K#Gr{$3EAh2tPIRejQk8haW1ANMn;BZ+^=)iy?=fw*>drv z+7GWDF7CJfb)!Y}kJ4WjhpBy?$|83{eqDcd=cG07zLUoa&j>83>Fwj%E4e1)%9QHA zPqjnc9x(czJu%~OdvnX@X6{S1bt-TJ2mBcvJFfT75(+7}d;WJ_(uaiju3E0gJDHdn z85kF58)O>D14CF=nMJ}ttU=^@LyT~DpJUlBuC2v|FBUsAl<-{yClFaa7BLo)a{Vfv z;x;Cuz`|FV#j7n2U0lw&$bb)|pP!NOKMM;p6Uzq!aS&gDMZkd1fQOAMq0NIa6_^wa zSdgOwm=J-{!N{;v_T}P^C!1UIdvX%~&GneRmFN1S3RkP9jN^SX!nj=e#q%IP=xXV9q>8e*Zd21Y3SNJ^tZycChE_Hdq`gT|Kvxm!f7nEo=3+Z#LTeeB+ z&bN+}7Z(K{`{vSdHtg}25A%=IT{|9jWKEps_u`A1B|U-%L;DY{Oq%nwqN04K_i-j& Z^|dM|!``erIL~F`+vJE(hWx?5Lji*2ZH52< literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidkeyUsageNotCriticalTest3EE.crt b/SecurityTests/nist-certs/ValidkeyUsageNotCriticalTest3EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..6da79065ea1d448cfce6652d78426a593899969b GIT binary patch literal 932 zcmXqLVqRd-#MH5XnTe5!iILHOmyJ`a&7?gZ-BbL<&)3b?4+`%c%*oP0E}02YsxoKl9T4QEsEe%9*Dh*eAW35*EBvrdK4auJz9u zpUI^f{(3SVLEZ0#S=P?Hd%~0Zfy$yIIZQD>9Qm0e?Q@Tw6#RQNOmgETkF$PDr>p#* z{$u*FN4gHPH40qJu9q`A--0$-!o-1xbhiJ6gsadEamCOB4Q zm02VV#2Q2nP7w6ExkdYELEX6?>!gUMyQgaxgVTj9ABz}^$ULjcBZK+P zCEYA@&m|g9DmYoR=uUZnfeyPX_p!{&ysPBDGcTE>m{brve^2Bq?E|)vUYbV255&2@ z^VKSar#nPy&XI#v9BUGEasRg5-M&*)s)S+sR=)kZOE#)}$`9s%p0Ngd!mo5uFU zRiH-iM_6Fe{@06Z*15W>hAmW4mlw#nP;w#rU$kXj4? literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidonlyContainsCACertsTest13EE.crt b/SecurityTests/nist-certs/ValidonlyContainsCACertsTest13EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..3eec5cc6fe8aefb9fa4b857c5b709979c0152ad4 GIT binary patch literal 946 zcmXqLVqRy^#58RIGZP~d5E<~YacZ@Bw0-AgWaMULFz`3zHsEAq4rO5zW(o~9lsAwC zakzxVLQ;!M6r59wN;1*|W^QU#FH z4UG+&7?qHH%gD;W+{DPw02Jq9YGPz$xcc=;_H>J^iC1`j{x3AjewXqu+c+d8SAdW4 z*eQKkuD1`G_^+IJ;kKb_!``-IRymLU9C*NE>%Hh>z?7)NK|jAO2~$0u?Q`{r?kl)W>hx=9{@4W(Ct>9WYn6?!o<3mUzyAG!&W;(W2MfPES*zn0 zwb{Pjzq5Mf^pfq%mO9v!dMz_EZPU5WAR@4f{mf)<<5hW)E8X6@wdDBpWk!o{z3Fh( z{P>(HrJNx@AKcE>4P>+3yYSv7Bh8|X3d=V&9!q+Y!=An{+Fa!to2`+>A?^bfoUTW@ zf{V{S{b;-Ofxyqh>oOcK+z36Aaex2zyd^~u+})?EW>nTQF*7nSF0L`CGLQ#`u&gqR zgn?Lth^ocmb*FSotD=3c9AKW*A*^&fCj^`*WcgUcSVXLy{kID*bAPg^O!Zu!itgnW zKjnM_agcrm76Ai310FW6gf{dSkN^u%#W&>m z0j5S^{4g@qC5tSOK6!fP&8Lr;roPni->MWaKjD=AyCZDsS1wm9Uh8UPt9o*EZcV|j zW<}SK(p_vDS#Nzi9J6}C7twVp{o9Xh?l|hr?EHxTzsI{{@BO+sq+k9oZVu9#St}u+ zYx%pGUr0SrW4C1c;~CQ?tnE=&{@!{{G`;5&<4Gln!0Wq=-v;jbbZMH=FO84pFCJCT zm}FuxCx)TmP)E_FUyq{=!;M*HSm=M3TcLLT(ORu8k1aEo1Z5|PDOvj4OB#1S+UdvQ z#{G!(+JjFyS4!`1-?ue-L*~KzK_L^Y>N$ z;OuB@AScdiXkcIngcimI1_n{$yv7EGM#eC%K?;esnHU&>Y-1MI4ol3*Oi@6$)72H( zi3%V$8(J7NF)AT@laZByxrvdV0VvMJ)Wpch@L1mX*yLkP1zA&C+c$mNnZ)Pu_O5Ed z(p0s7nm#9<3zoIzHOBZn$oo0TUO+wkn$TtD_ntZ)>(@@T{k~*cW5RD0jaN^d&YiKn z_45ZaS7&7M*{@$+l%fzO?vN+$Yv@4daor(1j53Lo$HlM`;w{@ z>3cP5WCN;J<(zX+h<@lNG;iW9wb`>T8S9RI*%4vc?B1|NQ<`#(Ew9(g~@ ze9MXDd&Op->e@VmrFII-nFW6QQrXLIbj(=xMCDupZH|&j*J<1SMTQvY210mVZjgE>wdKc zjA~blRpxN-?Jq0h-uZ7$!KCf;lpPDE#8l)JGrr(r3O{jHDv%-M$ZP#JF3G^wMD?(3 z;Tk$~R-jH?`&pA@>cJ(GGaXCHT6gy+LpHn~=Fwp-JVE;+NZ(k|op%_1lJwj=;Q CxOrXx literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidonlySomeReasonsTest19EE.crt b/SecurityTests/nist-certs/ValidonlySomeReasonsTest19EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..912968e9502997f5bede84fb17247000e69e2257 GIT binary patch literal 1151 zcmXqLVyQN0VoqMb%*4pV#K>sC%f_kI=F#?@mywa1mBGNrklTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kWlrfM3Dc}|s&d>FSE? zL=IghiHRn9L7K9{=?amWcpY*j^ z*6$w6I~#!|4t@ctVcYKgGB2_6zLk4v$)WOzNqKfo49x8-@|9E+yJm77>HDs?S@VaJ z$iw}o%3}j}sLnjGpvdOHqh~b-u3T@7UDFb#dqiF2f649jhlHKK-HyM1&zOJDp4%R& zm#vJ{r+@$cA$#f)hgl0Pd-_%8`_?{6JE-}%d}-6OOond)Q5U7U?|0VBl4x)_pJRQh zde`4Met8cyO-%2XB+gC!d6?~yi|q01r`-N@8vIU-o9?~M?vcgHvU~e-9_#-%-}wLC z+}Sn1AIo*CiY6+>|BW+pdlL4~(ZS-Qp~{@5h0Eg1<|cWh?On>m%*epFxQWpZ7$RN< z^1u+5Rc4Ve5Nivht2xi)-|YgJ;yg7oi^ zZ%-#>-EkGDGJo;;=ld6eIfDI@o;@hua_FLK>uvjGKejh+Rbh0fXEYYf}8#;wYOV}@66L*i2X;u%j;xhrnY@B6#LL1^{E`^jH^W-jgA(-E0>B=))E X%&N@^FDwFTZv4ra{hVFyH>VN+DgC4E literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidpathLenConstraintTest13EE.crt b/SecurityTests/nist-certs/ValidpathLenConstraintTest13EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..1ad52efdb6ce887c43c590d03c7af0c13dd2e750 GIT binary patch literal 938 zcmXqLVqRv@#MHNdnTe5!iILHOmyJ`a&7Z!@woFgG#sGXTZ8n3@sW z`}dx7D|Z!Hzy5%Q3NKTj_rICtx6AjppV3-%%2vr$>t06mqS(b24varvRo!o{&2mWl z>Y!V(ZKC)TshXt1g*U!L=Uxh^KNNlB@Y2?VTITc3lRXSPqo$;Lp67|#X0gS*z(u&p z@={p{3sm0b+n9Db25w&nIr%!~|- zi?aRVIbBZvheMq&!!=A24?Q2l=2t3iFM zzcVJ3Cms37pVA~LxRKX!@5Sj~A{J+SIFnwRVmH-P@TJ?XJ1M=sTW8yCoLY4I(aIVJ zfo|UUy|)qtKI@<2>8XV+PYwC73+ZrSX3^W&3qUix7>f|@q&UwN8MsdVz5*uc4QCLRB-7Ikyw_$;?S zRjJF&(Rc6e!~gvY55{=37Bn7>PrYOK<;cD{9N)fnzWert#U${=ah9~dCEr_nj&0_7 UJ$*`|yw2hV?#IVjW*z+s0E`Z3SpWb4 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidpathLenConstraintTest14EE.crt b/SecurityTests/nist-certs/ValidpathLenConstraintTest14EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..76800f5159cec3c9101a09521d7de3507684935e GIT binary patch literal 955 zcmXqLV%~1h#58{aGZP~d5E<~YacZ@Bw0-AgWaMULFo-hbHsEAq4rO5zW(o~9lsAwC zakzxVLQ;!M6r59wN;1gd5sMWjf`PjgESKDHZw4R*sU9un3I{J zfZ+lKS65^wD}el9XkyUBsD$ioMpg#qCPsb+pg0#(6C)$T9{v2868Xp6Dt?H5N=^To z6n2VNET3=fZ03VoHay%NY-#EFf6Et_4`!|hpB#Ch zrv2i9abdm7JcEzi`bRE^CdR5=;q2OamLqrW$49O4|Fny|PiXW7FI7txvfc3iz=vAy z>zX|pl2@OuyW1bb74chRuA70tp_?mRKm40J)oWAH#y2bWb2~pfaD7_Wx1;t<%!~|- zi)#$34CH~~E33>RVIbBZvheMq&!!4H3jnn%B--Q|jagcrm76Ai310FW6gf{dSkN^u%#W&>m0VYde{4g?vNwQ}@J7V&=?!J(eNJ8c}b%T4{35R8Wv}bBfJ1cb7 zCiU^LgA!59?$_API(|w2=2ExwjLpJo=Py3N4(frwi|;N_syn&Her3nIX_|Z`vrl(E zc~==F)Df?LYQ?!}uRl(lesA(K_jmtacFwi`5u-bMO=iyX`O-_4Wcf&y#-?0bVaD@x zLe3TY{4F=yniGTSMEANKd$Xc$TV!zE?GK?3X1mQ2_{@1G@vwtd%w+THEdJ zl$@D)`0Vl(3qzi&3)|)NES_|9TkW;hx><%&PN5T(9gnHr(5g=V@7QRW_)6pKkMByl iKbD%+Ips;mC(l^!f9(b{!)%dBr6~iJ5sN z1`5uO26E!Oh6V&TDL7Xk-lI8l;kFpQ(W{#6F#{#GK3&1q@piTwRf! zsQ_}fxj_@760%PjSs9p{82K51;#^EkjEoEqV*b6aJneHu_ zoscQTm^10KiRR;ndMm1}nXY|_TNXQKW$c+}I|AFJW!m%KCrOqoeG82;_gHmac5>PW zl{;47L~1sioTT3RVb=C@(X%zu4;*VvcyTA^WvR|p(?e&|V#`)Ynd#~LxS)B|(Mj;- zItqG!=?^)$#w4Pc{$dZ`Cl-4RL}?ZSEbE*~Dbp8uq28tK{Zk&Am%< zEzCD$n@q7gxX;va^=t7MX=N7)-qqVwmu#E5dy>n(>dBstfr@T9$v?Q9_HQiJec||m zUGMqg*M9w`yTZ#V7-daF-yGAkTK;pVV|VubXQ3BPZmhAG&&15gz_>WuAk#n|7`(E| zED{D{4I;C(H+k7iIGPv0cv5L^@;T0rJ+{BV2||{SMT|wHGCE$}jD7h!cfMB(?`l1t zWTfqCYQP85&(FyCpM`~)iRFWVIEb&nB4EI0z{AFs(B{FI3QT$ijL6XeOnAWPU}VVK zon68rvg@5umaF#TEViu8Q$7`yt?^+EeCh5PdS%Apx^-vx^P5-CkWyav@@U%meMdOe z^{0j|NO*AS`TVTajbdMKu-`4^x8G|0?o7ef2QC`lZhmraa5yv9(JM>##M6y=DV674 z>z7|o)%<_UkfBB(+$<$iUFhP|iRGq<~piv>>r0!zVS*IX|zsq$n{n zuf#yX+0j5woY&C6zz_&6j13G7qQrTP4GfKpVO)b$674fJFoxKt6PB2hnWBJUtAeX5 zvNIJx?zS*!VpKx*DI+Tba}y&!15licsfm%1Vedoxu+=w=MP_tNQ(9s=b=#SJx>^#m zO}AX=sIXh{rHz+#{GjKV}i}6 zWMNIQ-GX{Px~I35l}2{Yg_RiuQhJ+jS|1^^#VXqBgs_>e8EniJ2ca ztU3A1N-wJFQx@N&sUNF#|Grq$c1q=Vsc*xaijNYMc}(-7a90(R{*Fw_H{`#{X670EdHY=D(#i}cb*;}Rko?5)y6(7AVZ^cVy3&rKu8Yp+)yii{F zZ9>_{ypn&9_FD#I1eUpXHhsVCd+coMF1Nk{+eo)#KUC-1GchwVFfOh!s4|cT2Cu9# zi-dt#gUD>{ObbKe2(*DkL@pTf{^875n~bgz4{8HcF(7fwm`Et9D&P@ zW~dhX7>I-PE3gO{@EP#1aV4~QFs1^NngOE$KS)BDk?}tZs{u2RGT;LV@PhIF!+N*dCB=XFrfm?kXZrq}chkkSdYlheb&F=)Nvz^i`z&;>cI!#$ zYgW@Yty?Bz<7?2@7$?20U(VsY?#U^uUj^NKqkF`CQ9(aH+qBKT(-i$r{Mn?CeA)lA z+voFg))%->WHO1|nbRJ^wWfn9)8t8y=Hc`P`Jm)(7CC1d{)?xicZckWKH&dZVbN>X z{j1!14!z2dH2$Ubcz%xK=?9K3nmt;NQyaeDo%BL7B4+cE=!>Sde+2B8?rQ!1S8HQl z(gCgATReAZ+r8f!$vJ0N-}XIE+vC`iukb&-9`6u#^BAwjWX(4r46io4{Ob~vk~-bh XvuJ%{Nc!B%Yt?4D{7ndI?pq1~Q5jvm literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/Validpre2000UTCnotBeforeDateTest3EE.crt b/SecurityTests/nist-certs/Validpre2000UTCnotBeforeDateTest3EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..15b2928401a98eb97ca5c5df99017b45acabc797 GIT binary patch literal 920 zcmXqLVxD5q#8k6@nTe5!iIK&CmyJ`a&7b^4qJNk-AJ4MHD zesYXl{Pc3xlzAfVmV#!VLRzb3ijO?+IUj#v-s_#5%I-U^$|Y_r;S{vnHFbVs~C-S}WeA@nC*}wblEu+ue#zj>)ONH!rzwn3(WJTRPPm02VV#2Q2*7+X}N_h<)A@v>biP$Uxgb-mR|a9WV%V-aH!amb&r zg1L9ig;#$9ZpQu&D^*Q6G8>!{Wce8x|Ff_#GqHRy5C@s3zyeGn20UzB32h#XslZfc zz=#|jz%&Pp4n_un=UYzQ;*PmA$y8wGwTH?tOZyM$yy5cg-E01*LhI9v!$xIKe&?Ynu8d7BN`Wv;$8SuWCj@t&J<{!Hs6fgVNHCn_^|ZgSuJl*{<^e1uBh zs!10#Z=Lb4H+sj$cYk*CJhmlP^~tF-c4_mi2$wDqQcJz&T5PyYPdnO9P4)M*-NtuQ zTwK0xD!qPUahY!Cd!MTn_*JDboC*=Fze@@x@90^W)~5Z9OwtA-Brk zOnpN@`3vVYBW&UUWk@41ShvS;VD>E*f YW<7FjqGr>sYGJ|jHf^0Zj9#Tz0EtUgk^lez literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidrequireExplicitPolicyTest1EE.crt b/SecurityTests/nist-certs/ValidrequireExplicitPolicyTest1EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..7cf888e16ad1989713b2325eea52e7ca3794da5f GIT binary patch literal 918 zcmXqLVxDBs#8kC_nTe5!iILHOmyJ`a&7Yg8LJG>*DrdO8-g{*0xaP%`@(4|S?J!*;@_nh2)Rd_WF$V2T5VIwONSgGAsh!OfRyuiyC> z&70CY<5c`Z`TB>F-#^{RtyHg@@p_5WU!KF?#S0I9-L$$fw(TI_N_V@q+pVI@3;%?6 z9{>8{_SGm`{UZ+YEv7Hir`$jMdVYXP&JTyhODC90waff_Q~ccbk-wp9tfCKx->tV? zd-fRE8I^iAURydhd_h_EuHEecaW{Jl>)uG|A6>QWm}KONY1u1YtUJwRSRuw~qr_4z z{bMdt>opsHw*vq^ CerZ1d literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidrequireExplicitPolicyTest2EE.crt b/SecurityTests/nist-certs/ValidrequireExplicitPolicyTest2EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..23889360cc222fee606b87b3972c8d6b0d1f05c5 GIT binary patch literal 917 zcmXqLVxDNw#8kO}nTe5!iILHOmyJ`a&77 zqJY&23a+lm?p6SK#K@qDQ3=`WjI0dIO^o~uKyfanCPqeva|L-)ho3HFbb7v`fL9{Z`Tb9b$#+#k2l0@aXExq!A((|Dk>N|==0n|9 zqJmbQE4MJPUiV^jZz{Ow!fO({sYfnV+oBxsYS#aR*jeI6%Mh3>k zK?VT^^1vXLRc4Ve5NiP zZkf@GS2}L4^UmGh{FB2<@otN(*iZiNcWWKA)YnZHUfQPV{#n_o#3232w5FrsDtSxJ z7;c|-W~#|$BjZOcy~j(}Cvt6CwfX89tM0owzW!o|6isewgx`*n0|4XU BYk&X% literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/ValidrequireExplicitPolicyTest4EE.crt b/SecurityTests/nist-certs/ValidrequireExplicitPolicyTest4EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..e93a0e1fe91fed010b8098517ebb537f53a59cc0 GIT binary patch literal 942 zcmXqLVqRs?#58FEGZP~d6CB(+$<$iUFhP}@Kgq<~pisVKFuG_xqxwW1&=GdZ&) zARkCo8YmQ(CP9$1qk)__uc3i~ArM*^8yFZwiSrs87#bPFxCWUdT5f4z4zb)IEHNiD zMFFc56kJ`A-K_xfh>1ZHqY|>$8Ce;an;7{SfZ|+CO^l2T_xMHcIP2K#ob&kGQ9kFt zI;n!({^c80vg7f{K~m2&(Bo2|Ld5oNdDUBF6Ho&=f@awWPimzE0?bj zu6;E5ZSko;H9F}_?8sc~<=U(;Vpt2!_H84nDMj>YqorHD1mDxTG6RAKc( zTEQYnZ@JG2(So(>ZLE{t^?vG|8n@0ttA2h!{o*Uzj*3rzzH$wVRpZy1xAX1qtd;#& zcVTXamF5ACU;*_*?RqM&>iialM(4ME;kx!|dFFi|C68O_f+}5=SC)GMh3>k z*#?;g^1vXLRc4Ve5Nig`v}9)!;4m5=H@lv1L@~yWc<&-MYctiC>P-&L+n2K{=|&;K!-|GW2;vEYe4TcsDgWBjmm?*BYXhK?0d zOk4Ktby%=hX3v{VNuSnv?%3b|**4P!!wIjV=D(i)z9UaNH!dPZPOoC+-0p_=2`4XDFD)+pvUz2|i!C$$8i<%5 zUhpc(j9%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!ns0&BvH^7GOaoP&H6oE;6C7?qGcz{twL+{DPw02Jq9 zYGPz$*nX*Osa@^2dx}o&pLHv)R5u;ETCybcwqt_L^zNlBi*x_RZ@K@uZ&G8pNPFdW z?Y(~AvKKwk-X+nuHg)UAt$kfnJLg6H_wM|nx=B{CJ+I|J^FO_lO3e$l=6}z*C;a34 zd;QoZ_TBj>QXV~&tUkTy1csJXW%E=gOEKWvl7#3|=K8C*M67X31PqFvXL z2$pH9bQyp4hFp95``Q6!CT2zk#>F)TRR;3FSdvv{kuVTz5P4D?e=%li8;1_-x_zbF zQkUP1U6BTkXIVZLF%}UXRksJ7Re|hY>rL06op7XxZ~F>113r*`en!UsEG)p3!)723 z;w!KS81NbJuyG}{c`&8|#SIt@_(2lFAcd?3%s>h`et-!K7(a{*<{mwh?%Pbzz4rIf z%MC|zd9E4Ex-62?H+f62^MdW+(>eTlCC*ybYJK8cUr~~jY8@NXZ*Jc-A#v}Gr0sV4 z{RfvR_J$uib7#S^hrj%SmOuV%wWnXqH}n1KyclsKZqtHZ=H-I2s@1OhyLLZldLMOv z+VY9tyzV_$`6XTP@~fxe%!TjRC0eX*mb=${m{qWiW95sNDHFasHu%eO25U@ey`_GJ zAyy!(b#340788+x^{3@$SWTOz5u3PQING*+#wJN10wpZxa5;91PS z4t`Sj!*wQOd+r&BvriUjJTG~eaK^Bw)hPaei|vc6r+>`K-PO*2*l3!y(W8oE5{Ci$ C>RY7% literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/anyPolicyCACert.crt b/SecurityTests/nist-certs/anyPolicyCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..df54668adbd2773cf297e6cf6709611da8b9c9c2 GIT binary patch literal 911 zcmXqLV(vC*Vk%z1%*4pV#HeP#%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!ns0&5cUDg*L!GLtJ6oE;6C7?qGcz{twL+{DPw02Jq9 zYGPz$*!M#HuD{9I1A9Kk*=cUp;e5XTLEu4_)hm}Doc;4*W$Ed#%WG?{tngb9wx};p zyzAJ>#-oOU=PiXJd#5-q7JRt)%QWMp>h(MPEcSP*8A}|T;bi9%-otX;r1iw2usQMq zf|>SFapuo$xYL-rJ$~PfG+g+|?N!Zt4R*QP&3CvntDSxGs%AS|u4K-ieQ5O`D=WR< zy-HUuUiD*jo}Af!r$pM`qKvz$jHBzJ-G2_gIgy1oSthXc1gxKPwz}NHS$(znYE9*t zA6*N}%yiY7=kf9OulDL)xkv0?=;_yw&&vO~^1A%>om-oqZl5o&a_Mod-xMdV578l0 zT+GAsPqH%dmPIc(Sk1)D$iTR`vDKil$v_?$PqNA^5(Z)oB2Q}LFUCx5hhbhE7HI*Ez8Fu#v-!&IzQ=dCMny{#E9dpcTm4v!h13r*`en!UsEG)pZ!)Cw_ z;tPZLtOm?L%76zXpaSAGFftejf_MrnTm~ElY-}t*CIfOz0h1aqrWhG)OBFu&HI^;y zIb+H6vmr+4n9iSybE5x)QhvU<8Fsh-agNz9V+qx?{Wmt&Oj&$5@6J!zm7Dj@X8&A! zvU^>1``Rmucivq*RW?*`&cAnW&hz{^|M~X5Lk1>+onBdj?;AocR$i5S65;!@@6m~W z(J#7oNbYOM6Y^d?KlY;N#f`xW8(13``vhChwy56y@XW$P4jZ5NZur{#@pQD?ytfPE zIc>k#P4o{EaIfcNes(?V|EW1uW^XS3ifddkb<3L%!s{;{@?Q9u;l*at3u=9ztPU1Q z-TeKl>#lL}rO)1a;l5d~H>5=;TZyk?2rgTY-=TNrz=r?j)#8sge7$#J^@PQl+os(= IIQ!270JslhApigX literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/basicConstraintsCriticalcAFalseCACert.crt b/SecurityTests/nist-certs/basicConstraintsCriticalcAFalseCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..4b678fee0c56878812687ebca4ca5681126a2901 GIT binary patch literal 923 zcmXqLVxDf$#8kh4nTe5!iBa5umyJ`a&7*-^nQF{e0H!P(KEiBSpJXN;^2%uS5^3_x)%rY1&4hEo@P zSL~mYyjt#apYBb=y{UdT|FNz7>(C|j{^qo(?HA5e&U^apBvZ8fE$-#VW*uqtT;rR1 zbI*roO}>ie-`gjAN%75jWPfLmi7DeF_2&yOZS-#ynLjQ4cIuLcJGqa}&J^Wjv9S6O zD71}h*B$HF_ZIga*(}lLcNJbfXVO8*&s**-cp81|u+=B4FZcg2o}AP?Nr&gb#sxBk zMYSvmvT1iGoC@ZXSv}dIcmKxniM-vG-)`EMzP+*JdQ$Vmgai90s{dR2X%@qibS7p- z2FAse2IU6wz;KmSW|1%uYY=%-8-FooY8!_R>$-iV+ftX`j9rliP5`oeEMhDo1@~R_ znPup& zfjppuFi0Vj0RwX60Fxasau^xBpXYJr6$S)+`}S`Ci7UZ2`A39avF`p*cg)Hu%`J@C z%i)mAzUM@tuV#xbl|^X;Bl#SA}tH8#$Bbj)t$+^?K}GEC>2zEk;FA$suTs$cc1|6OB?&FB9faDDPONsf>m z$4^8be=E92oi8@6jA?4y#Cm0o!p&{5kHuC5SnBM0$(h`nn-wnnc*5TA(^GCqZJrSK i|Hj0Bt8c8G%`McncSR6Gt-}_+@{LRFmd>wG+X?_jZ(@}I literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/basicConstraintsNotCriticalCACert.crt b/SecurityTests/nist-certs/basicConstraintsNotCriticalCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..d6c7fb805fa6a7d9d7a4f057a863df9d2aaaca01 GIT binary patch literal 918 zcmXqLVxDBs#8kC_nTe5!iBZykmyJ`a&7C>@^&XNr+?|Y*v*-P2_|!7tdXPlc!@CzZcZ8Tm|Gwz&md|SN zJ-MaxZM{m&+V(=L=mgI4XG>(}?)q|wHQiV4&5`S+;<@o5nu40ImI(b$dVP7~jPQgl z>HB#0HO@|(`qE`)1&@E~hEL&LQHh=FT~k^c|7}R~PFZ0%BlL&pWAV_V4VQf1$+X^c zv{n4X6cTpo?iqot%%}2mEpnA?XV&sDaYZ(#PTjF@W-#|HPPOp3d2z|g(Pq3ocj9(_ zt7!aPc`>h>aaE;P*#1v_rixeh8-Ci(f2db~yZ+VX_kB10=~yhy#LURRxVX}w+&~@} zq_WB^5(Z)oB2Q}LFUCx5hhbhE7HJmFU!Xw#v;PCWT%1i8s`%xOv2~i zhrZZfFyC#x0Ut;|KO^IR78YP?Vlxm2@fBDE4EPLq*tinfJQ!1f;s%UB9#BGUq!GZ!^+!Q zwf_GbJ+$=K?>#pyZJ}fK>aDupZ!+$TVZISQPfu+cf3nE@Mcwmnc8S*Wv#Sc2ulyph zsIx1QWxi>M?&PeL=|Xa6uDUKWysh~BKjY*!*H(v$UjodsmsVY{tX=ptq1@=>ht-!} Zsvi2H(sgA=_6fz}rLPuu*ms5X0swRhRR910 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/basicConstraintsNotCriticalcAFalseCACert.crt b/SecurityTests/nist-certs/basicConstraintsNotCriticalcAFalseCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..27e670ec162ba97bd78c99b01fe34566db49cd76 GIT binary patch literal 924 zcmXqLVxD2p#MH2WnTe5!iBZCUmyJ`a&7*E(N=|!x7T@WSp5Ua|b)D~4!QyFWBkYd~?t8QQ&!Q8@*zYfU zaay9WfXOnt?q2u60oOF zYyXjcRhJIkZS!1Daxz4dE5W%#fDX}tQTL@y}7$JQb_Hy-ks~b*P4E{ zE|B88vd^$V>Acc&-^~%M`e&oxEmX?s)$M*3+pzG_)~pL(E(^?l_I2MShnn^iQ7_EP z_U@OGzy0jO>P0WRas^mc>{uh>Truf&w1t|j7kufedmk-63w7u|ou|vg@E1!v( zk%4h>nL&wxJTPo!m02VV#2Q4N)W%9*A6H)B_%ffIo&ABz}^h~GO^8UM4e0FxD)fjEe-z#?G4XTZb8mC)wFmzykPUsbSuVPae>xN`E;XWc@Rk0}2X7hJsY zUaaw#6_@viTz<57^IgO9%o`R3B|V5#YImRK_ICNUHB5VUa|k@?G^l&$@knT=#ElgP z)XxR~5DC3evANA*cZgWz|7pjYG(UV<*Atn(b&qCfw}K8EL)3?78`9I>tT1V3QuTKK z_NZbP$J`5&GuAXr(}`gTE}I{{u`?|tzKTor|CE!bfaPl7G6_1{@M;BC2CMa`=J_G<2PF-#Q literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/deltaCRLCA1Cert.crt b/SecurityTests/nist-certs/deltaCRLCA1Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..6815e4f888f14686ac1ae266de7da251a1c53d43 GIT binary patch literal 901 zcmXqLVs12OV#-{=%*4pV#29VB%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!ns0&7xIb4n7OgM1X69Ssed7?qGcz{twL+{DPw02Jq9 zYGPz$IP0wKE-=wKmq$QQIXbscSuA(evWGHtP326gUBSj__Vywz}icjpqhSuRapBK2@+UjPGrx^e&@!l^<^(%aM7ae(45>W6m85zGX5q z?w@&R+qVBw-{FN)9E@F>8J| zeX(Z7EcMr0doC$uDtuYT(J7s25}(|m>JqbJLg{p8)~l~epEO)$ILdKann6oGVy41_ zqPp0(@8dQp9#}q4b53T|$=&PS*u}IbJ`GO^8UM4e082XTQ}xPgVffJdu)@R8u|nr zO_w>*yi(p?`JaKn!H{;LS}w83%<7zlYH#K5Da8cN4lCMM&|LiPLc$qY`MGKz76*x6 z<=ZiNf=rUaidhbgl3TZL;x*dGXYWy18EJfY-}y%(3lHgs^%w7`F!*;_)PKK>94~vu z;x3JQdrEh1ZRGmoAol;nd9Rt7@!MP`yYf$&*Zk+d^c`K6ueYp@-P(1+UGT++Z@UG! ze*Bg=z4^>i_mvsp-1m%2-H%z@{i}M+-Bc7Z^P|M6FA`sFNIu`c+biYK_WK4x0PWFD AjsO4v literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/deltaCRLCA2Cert.crt b/SecurityTests/nist-certs/deltaCRLCA2Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..2f64a74e135563594b0d369d826403970bbcd314 GIT binary patch literal 901 zcmXqLVs12OV#-{=%*4pV#2911%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!ns0&7xIb4n7OgM1X69gPf{7?qGcz{twL+{DPw02Jq9 zYGPz$_}Nyi)irkxr)aSyA4?gl?aNiG?f8TWoHnOjFFVYaWtk|Jd&v3A1Hn3`?zHLXXLo&Fxa*4U`hXcV{pVh-IDNX%)jX$2p50$9q}onVz;tU#Ra^MhhQ-1A z_O00>KK0c0?I+SW&%Liaa8_2}vTEQj)qe~nZD&N*?zzvI^do2cpBMd4Ufysolyb-_ zx^H&=vlUB4nq@-d*DBpuQNf1ZGhfWhBR)5<>dM^q5ni-H_VJgZI+jHZPsQdK^a^x# z8K=#i{>fl(V`}AM%{TLYeGX606mm&xu$+AC+J$FjrbRE_$Q(PcWPcW4JX>`%i-XLI z?o$jFg*D4Q6r5|=&&15gz__@^pvpiV7)!FsED{D{4I)o!<1fZcZR5~kUAM1vTk7(g zu`ANR@hr>7BE}+8bK~1SW}kECx7#n2+--FB>M-2Et`uQ0d|Ff_FQx2PfIEb&n zB4EI0z{AFs(B{FI3KTbBG~fqG2!j-|8ZZMXtW3bRuOg-jOz{Qt~4d>aM8TOC`Rc{xaT&(xlmiw@i0`Lt#2rFJP(o0O$* zKeEaD=&DGsn5fjqa`5s|!HFl@T@rHENLtBtI`kY@Xxp|e{nPUGx&@pEjh#Hztz{l~ zKjIPIzEJ!Ie_SRj_lcL6r@2{vi#xGM{n&~1l|O8qzPnj)?^GUn!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!ns0&7xIb4n7OgM1X69gPi|7?qGcz{twL+{DPw02Jq9 zYGPz$xVj{~`^&s5i@plZS5!RTcx!UTB)_)crhi#~5BGmo_PuuGfFS>JSB@8*JpY@o zyfYW^JQmcx;%Jb;Tr*YksP`&9i(|{2$~K*J$eQ{f)Yti==CtV9Qto$dW#5~*?B%31 z4#B)`vB0v6Ru4O>3~axj>VNm?@6rPXCt7Ojmn;ieqI~k~ZH8ktFK3<;e7U8mX^Kxe z@1^p~wS{wc}1@f96 z-oG1RO@u>RE-w%uEqm>C%u7uOh68OQ@;NmiLf!a%G+h`et-!K7(a{*=|xXpP7d19WRkzu zV`q+!MCVkyg|)`BcdriJT{>%-!I=wOFH@iFTu?RZq6+V0uMdsf^-pGAe8c>xw|&;y zX>~8H+~W>Of4=3@y!vDN$6baV7dg83tg=b`?YcJ38=F!)mfo-uE-U%J z<4rGvwp`3KiHsVXulv65J@oLw#JSaVKTFrghsMTOu1`JhvG0{BkGp{4W|^y}&dj{T zxQzF4SJBrH6O|nd&0?M@V(~L`!_Owm?>hE}U2t~2-ZXLfUEhz^O8=R)xo*n-YX?*T DZ$w~Z literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/deltaCRLIndicatorNoBaseCACert.crt b/SecurityTests/nist-certs/deltaCRLIndicatorNoBaseCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..7cd82a4363c5af9eab44debf5723fdd9f6cb0487 GIT binary patch literal 917 zcmXqLVxDNw#8kO}nTe5!i80E6myJ`a&7QEtA}sfU7}vpV=_hMEIXCuQD2Uz_pDh~wtt2egHJQCU?zlkD`k$4v-v2dt zv)8FAz0;9*@vJG2g&gnIf84kHnQ4ch`mJATovh_icP1`;>l*gBqun6J6m{UB4^ng1Qi@pfCC_fFVwPW00cxvUbNJzx4hyvF)TRR;3F;FMKn zkuVTz5P4D?e=%li8;1_-x_zbFQkUP1U6BTkcUe9bF&2?87G8 zxK_V}@&1O_zUr*@Ps;4}${h(8ey+&PKBu$)$Hw|~`#5fjIqh$={a~;^d*!9tiCQ|h z)Q^}5PLa&{Wwgd{OCZ1WvV>23Z)5#l-d+6az^Ul2<5_X4)8+3}TgJ92?SHACB{2VA zk(IH-B_%dR^nf3BUfed_FM8(5QLWwDrq=OTOA7_Off&rrwoL zGq{55yGo?Z4L+^l*EDxgXqDCDK3a72NgsRC-P6G-)3bJbds&t7e_>+F?#+^mO4qMA WyVG#$OHr1Tl37M^vRNe`8uI~7wOQ!^ literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/distributionPoint1CACert.crt b/SecurityTests/nist-certs/distributionPoint1CACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..23250812d93bea78c4fb47d628c1e0fb35f43120 GIT binary patch literal 910 zcmXqLV(v0%Vk%m|%*4pV#OP(f%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz>h?0|Sul^7~G zI~p`GDk1xXk(GhDiIJZHD9**y#K_2SkT+TL!s~^0YHX%Q-muKe%#42`>v5A?Q9HZi z^6l@>w><3lwV;WE=M&$*s<*Q@rNn>YmHoLSL5IP&>Do@^i_@&vZo87jx#HIAggeD7 zp|><5CkTf=`JK0Y@dm+j;#Hk0-}hPwXR)4~^ZTu!Tbga-mo|%YOo@C49fO*^qo;p= z^3gS|#@a$muep2wNe9-J3IF_GUVrNJmcwZd&-JBCoVD^}KfJ%1^;#}-nUCI|slgTE zJ}YjX5Esth9{+cn&fFLOZgNVu@~jg3wJP+U)jl(!pt)Z*>OPzGg*9vA0EXq{kN^jB8z{we%j^l@{M1%M{FNg%dJ;c_tr8oGcqtPt}&=GkOzjNtTKy) zfmnmcliK);F;m+(bXeEzE8Uj5{ATQmG;oB=^0A1qhzJ@K@9iznXu6bt{*w9Iv#*sW z-hOYu2hz{a$oQXy1(<}`48%cv1r`AVJ_8;$u7oxZ##ErV0iyvwNJ1E-kkx=0NFm1$ zFr@+Ghmm2`N3(Wrf#WaSR#&PU&0u=F?%m`<`Q25o+AS{MJlb4yZGlLR(DHmofu*UI zYgYbHiwz9RS#`FlOZ)Htx3^4}@$8L~nyC8giBrYTe??1ppY*r}IGJSrPnU}P#jxp3 z-?c}!{?lHyZC@Z0mAdNljh3wzFQ-0Xi=Vb`*OHp4f2I|7-Q9Hddhy Xg@b=H*PSx{82Tb@YrUn!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz>h?0|Sul^7{F zI~p`GDk1xXk(GhDiIJZHD9**y#K_37#Y{);g@V22bGDyv?#R~6{ra@=xm$=BhvEXg zq;?InkLGb{fB$l8cJNNPJ@wx9*y)T<+}TX(4sH0-fzS`RXM(?MgSJ?5QhNJ`!G&dEZt%ZF+OL_3^19+m_#xR?c3ju}I;~ zqh0E`hdv+a;Fq+zB(ZJ#R~G#vu0j>gWvegB20Z(=?97Fx>djn>&%aM}J^W;)XGh{S zxAV)lSqT`vOl$aYDcLLOpym5I4*s@3rygB@IMajqVl@*pBLm~&8iOhWd0;roDziu! zh&6~jsg1uFGqsIFhjrb)(ru~BZ^o`j14pR&slDcH>Qdyu^U+Ftph5c$`J zy%94jGI`m$dIZGoS1ezBezMY(lGNIyvef#^n|OaEZD^mhF(x=6!>i@w_pYr!OrJ{B zUunzE=Ks8zYs&s<7bYo1RZg19tzlDYRABRc{)F$P*MjGsWU;YM+k8zRb-kY8`8cWH zqOM;Wo&;F$Uyw8NSykZ8vT6Tb-z;l+wS7iT{qtGf^ObT=?kxDud&RkW7K^yVKet-V UML7+peA#VyXVe`2(wE=`06ZI9wg3PC literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/indirectCRLCA1Cert.crt b/SecurityTests/nist-certs/indirectCRLCA1Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..046deefaec87e8b260943886eaf9a534281e0e1f GIT binary patch literal 904 zcmXqLVs0^LV#-;-%*4pV#28}0%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz=K30Wz>0dO1&`_k+08?O&+nXYssCoE z;3cD=l7`fMf!C%PpO~TbIqGP-;$lakO@3mb#_jo0jt)i^g=|+|%%5n`d8H>LWE00k zxo^+YVrpJ~5ENPeEx7AW;68=yYoDhG-(_NEWMEueV^C!v4-7$BWfoviHi$f_jlUQ( zwT(lEb=|(wZK=y|#;!;MN3|>;ix`WD>W}q*)^A%WC0*%#`*eyu8>Px7MYNl$Klz7!+d@Fsq3*X+4% z6W=a=>ix4!dQ))YnLN(-oL$d46mm;TYJNC>@>$}sY|q34GSzk8dju4HCw${O`nd07 z@JjRDwjM%ZUn_m46eV!6Hf?t>($w^e{kSpZY0M858{WNJey>}(?)QR-KfdkX6nP_^ zRy!-LxEER(SX)|W<#)q#z5lcFj783QuY;bq96jV$`XO{mt=%>Gc}8;nJgWloWIQeQ KyT0qWPy_%haa5lG literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/indirectCRLCA2Cert.crt b/SecurityTests/nist-certs/indirectCRLCA2Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..de9a0be510efb643e22d5d712171375f8abc485d GIT binary patch literal 904 zcmXqLVs0^LV#-;-%*4pV#29M8%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz=K3>4BR(?B9Rlf9CNuOkZWzeK-EqI|I(FyLoj+hp5qxh4ueGFWAex_ph?7%M!nW z(~C>rn)81DZxQzA!h?A6#;*-)YEq7`Xgj#5p_=1WZt82LAP4ggEE=t`k^-j^=8N@6 zOZP4Aims4d`Sg$}gZBB9jL`h!HY~OQ((SW99(Xl-4ws0+1@G)unc)W%9*A6H)B_%fumZMk420{q(k}P=FOjS{u!>^*PXb^dQv;bXm>3_Npw*e1B)hJC?>{A%x{Z&en;73_A2Xe}JO21Y7k% z2Dj-7$}A;i-27*^pXy#~Z|ur3r8Q;+x0Z;e;i4pN&zehe?8@u)Li(F_)-3H;?Md#4 zcAT((7TY_n*MIWP1Wz~XRKDY2Tlyl*YU`zUyEYb`pY7wKK8ttngsMZW+m~<&@lCPK zzjYckSmZR%)*b8g8y}-}P+nX_xpXY0Mtq4(x0x zR%SW%($aK+bC}BJ8GP%sdE&1{z4>aA^>yQcKkLrsdy6Ownpi*g*;u2jW0uUZVa|!! NN1kgM-0M`(0|5VmR4xDj literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/indirectCRLCA3Cert.crt b/SecurityTests/nist-certs/indirectCRLCA3Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..03bb3eb2da91023c0267415b2c20535445090165 GIT binary patch literal 904 zcmXqLVs0^LV#-;-%*4pV#29A4%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz=K3_fw_s1p8+V&#ni;e$Z(@qyV6hNv~_i%`Wx$c&%#bG_g~h=)w}(}YH{|A;(W*S z;yvc7=PQkCn^Yq8-*{YH{$F%zQ1*54x64#`+OJ&~a1ywn6(zPh=cyH!kV|M}^hu%g zwNh^aKXO@lKX|s`z~_G-zr3;i*L0pOVGWz+GCKK@ z?;w-s-7os)+?bxejL&5H%M0Q%6Pfrrm%O~n#LURRxVXlk%0M0%g0jjiz@Tgpc~TpH zF=lEThYstyeWlw{m*0$Ckp_-xSw0pq77>rhA+<+x4gTwfyB4b4_hFsy#h`1z2hz{a z$oQXy1(>e+Or%UohE?RpLap|{T%XsyiHmNLINHQ~zGlr+ zt&g`Ze=TsB(+$<$iUFhP{KeAq<~wPKQk{SvnVyW#5u@E!P(K+ zKu(<3(7?bD2rY~a3=E>gd5sMWjf`PjgCG)ZQZi70*d&Q&lR|Qkk7sdlX=;%{6QdHc zhZtEIn41{+8GzzkOihf83`d0cpItw^Wa-AV#skl8S-mW&b5LOWaw~G8*Cpx1X?gFQ zsv|zR2^>3CZKnO*!r}tc`J3z6lr>m*Zg050C+*b-?MvE+67Q{G z?wmJ#Yb*=D{bsdUerew)AtlkviRzkPBqFRc+bK!=kfy+5A^D?Txv0 z?h$WZhRk`HQ?u4s*fV5*x^47(r}wW}l1(Avj_-L_U+`J9z-#Tp=4~GelD>BIik~YM z%Q^G=X|YL)+_5Va|1QKCF&wBgJ6Le9{E}(Qlg(GJ+=}JI^{3>vQ*$OA)DR+$ADfej)a zlS68cBgiyC8Z=q(L}| zagQ^V8S)x%1C3{47G?paJ458i2c~9VN$&;+iZLCyV;dxjx>1Hbe?q7nx-bFfAT}~goP@V)tNUv ztXL%HM3t>yl`ik-*y+o0Nb*0ggsuPd{$q-Z?I*IY+;ly1XMxJIqRqmsLOQEY?loCH zagkeko5gFJkcOu-Gg>=m;5%e&@z0RRwDZomKl literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/indirectCRLCA4Cert.crt b/SecurityTests/nist-certs/indirectCRLCA4Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..f1cb26b375bc0be054f41653d15200436ccfbee7 GIT binary patch literal 904 zcmXqLVs0^LV#-;-%*4pV#29YC%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz=K3_fw_s1p8+V&#ni;e$Z$xeAas9l#Pph3-gBSTuhiFk=PsCXkdGq6D#rF-GH?R7xT@TqadK!qJn?>>QrxA6w9ZK$@7>MW%rBjAIj7_7 zG->Xl@ZDd-EZUe>S!j1mV~cRPb>*IRhm7kjwF~_djgHFI+fL5r$(d@@=)W&H*Vb6~ zTvx&BS%;P=1)9uLkMby=oWgdzT)AWF`;|=0j0}v6YYeIksC%f_kI=F#?@mywa1mBGNnklTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kWlrRtjDc~07&&*57EJ{r-aSrlPaCS5? zkQ3)MG%zp(LJMO91A{1WUSk78BV!oXAc#bplnfLgHc6t{q>vos<5^r>np$Mg#HfVq zAx2gP<|amd2B0_>QxhX2!``Eh*KL_O@Ao-Ri<~R^jDav#oclJ!o-iU z=F$~^4lIn`*FD=)%5{F6{j!xd;i^;I%vbeis(U_@{hQ?R@L$TClo#I`{+>GA!O#1y zNkQU9*91n70)ORSK~e#&#s2dWUwY478jvLS=Gv-fXG3C_-1*l2;NPN&9wp~Q=k*-d?347-zNGPN3S`)%x}^e%H$zH5j!y^kRM%mN%uGyz7x9ccDgV!?Q!n zRL!2hx4vyNFJ|6M&b>AhW@$az{c-s$hO`8~u!izl9X};c^P@X-Bm_MI4bHn#8k(NXM=lwb-l_{n4ieF@z>6-pEH?F(AyEbL+WrG_F-Ii^6 zv6w|S(%RzY-|r?Gdu$_DE-jiMyFtn(vfM|gq|P_?;?3pDma)mqTHvbo_TLJVr5tB KS(;LP@ihQdE|tCj literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/indirectCRLCA5Cert.crt b/SecurityTests/nist-certs/indirectCRLCA5Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..c4f9f17874606dc83d1c86f797e561aa76519dd8 GIT binary patch literal 904 zcmXqLVs0^LV#-;-%*4pV#28_~%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz=K3_fw_s1p8+V&#ni;e$Z%n~$ef985BELqiaMvaPxxQ*oBPL%AASlyc+caau6Sp7 z$(w>q-%E3rG0m9lW4u{-8voo$no&D{Z}*KAU%6kovGn|pw96qyPhRf1yx79IP2S?> z!OA(|r_+9AzOHHE35?3&TpGU1^T@ii{qHY16v?!nZeV+vSHhkJY~O0`tmtFQx7|@iJi2~XA#3$KXv8v z2kc5Wp3#vqTv70T-GR-%Dd$6;l$?GbzWZO$#P9a24is-Kpo{+cBsHLetB=7h7dyN-b3ZAqtWnyMzU|d{dP-P$w3_)3C7GO{|h&-u{ zzZf&MjYEfZ-M-RosmpK1u1Et%wJaZt7>h{b_f>m6N+TOKoWHLuG55w~w z{EUqMSy+IHhs{77#8+SuFyJ%bVdF|@^I%K`iW@K*@Pj0TK?+$7n1K{>`~cG!Fn$;r zI?rvF{`T+Wm*Z^LXSW{PRY( zf7iD^F;&=jW7-X)y5PQt7HcNN?E9Rm@S`Cq$Ez{(i3$hMT%TEp49nQ0Gi=o06P5-?jTU{O=HsW?UaL=kvXGi=UgFO#V z?b-F!^~3&&)~CDT9{)J$=EIusE6m_kli#_;%6Il({I=rzj1Aq60ijV0=iUcDT74jk zeO}kzM0j8+~hSkLSz2s+U6ZTaN6y$oezc@$!|n!?qUP PX5I%?Zu%L$`MMqeEe>Kj literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/indirectCRLCA6Cert.crt b/SecurityTests/nist-certs/indirectCRLCA6Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..46443aab941682033e3bf50d0b6c603aa967d238 GIT binary patch literal 904 zcmXqLVs0^LV#-;-%*4pV#29J7%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz=K3xbus_*q{wsyBvz`=Auexn3zpv}b+er~Br=H}p!a+b)>i zUC8sc>1}_oSIzk{i|r!X?Gh|G>^4!K({;nnyK}9nZxrA6LMKd~@11F}zP_X1&ZQDx z3MN1Ic(O5-bI!?d^AtvRuAh8Qde-sPxv{YIO%84N*krl&!L{qApSuUB+=n;i0T?%w7_n+#4GysbKHEMaGQ{Yc@7m5m3Bm^#lnXCGYnE37?UV)N_O zFT(yjtGv5mSIYCo-rfCQ6Bbm;Je(~0RIfnvWBStRs|+-D-}v?Ukj<($3zo14-RPNk zr_R;UVZ+@UJ8rM~bN+=wt-ZU^*{N@93YnN085kGW7*rX^14B?&nFSb>4I)o!<1fZc zZR5~kUAM1vTk7(gu`ANRQ7y~IBE}*je^Q~BdvT6#xxer|r!U;w?rD`78t{Si^D{F3 zXJG**9ySAU5MO~sz<|$yhm9+t&4V!&C~m-Lzz>oT1}S7UUWA3Ymg3D&iKkxc{)wFiQJWGica;KShzIHXN=Y5sRz9z;bq>G)Wz4cVwoi*B@ zxFdEE3+IL$%)imO#AflXPnG+;UH>1;xU1)y_hI$z!)I=Nei-nki)n*!YE>L> z=->0_csDG4m!`vQ)d}wa>#=X^B?! L@83-BI{OU)@%>mP literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/inhibitAnyPolicy0CACert.crt b/SecurityTests/nist-certs/inhibitAnyPolicy0CACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..cf3611025edc9692e7b233366569673d91e347c1 GIT binary patch literal 940 zcmXqLVqRg;#57?6GZP~d6Qi{OFB_*;n@8JsUPeZ4Rt5uCLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`Pj178xYku{KpSR;~|mywy2S>l*i8IYfonOte0;OuD7 z#HfVq5k^)9<|amd2B0_>QxhX2!=b#3GZtr^x$1cBRUZG>!xOGZR@Z(Bd*rl-xpvi6 z=^1YrIe9x~>mIwE?YG#&WaC}dDb{O>oUh#6el>c2MD~;kap4zMm*~B{x%#2b^LV8X zJ&q}=Z^{!Q_Ft6fF7r9`Kh5itrodL;&bq>w3!`a`1&^!Gb01z;>KA9jnfU}fdMJ2%pzeR z)*$kvHvVGF)HV(s)^+8M`749OJTlEMhDo5(^eoW&O{Z+uEdZ_OM#(kNsWd zYzBNF{rrrK|5;doX^7209K=^(5isC0;9=uRX!Br91&SLm8t{W8gh2{f4VZxxP#P$p z0^&6=G63TX$TI^;1C@ig$mtLmeT)nV44a&Dl5YQqTGo~O_K@9ykHu;?zg6m-wSSp% zQd09{*jv%OCHE)sGkU)Bes+ibZqt0H4+m9GoHRgyc;|8^AQ-CVI$L_gtTuei>^riCjz8hIO&I1ipPlQn#qk+(hh zcW7}f&z+3&|KBoZnWjeZmf7r*sQg-f?C)g%-(8Q*zAu};d9LD`#iyB)B(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`Pj178xYku{KpSR;~|mywy2S>l*i8IYfonOte8;OuD7 z#HfVq5k^)9<|amd2B0_>QxhX2!)t?l$>}j64)XtJr$~e!og*4F>xJ46eVbze>%Ue1 za?-i)5@@@tP{D{{OS~yxWkdYNfWyDe>-TKkH9bnA{J$*w$;a=NPyd`%v(11v-}%{7 zJ`efbzCYK$_#BkDaqnz3pS`^rT}K!Cwj|!X^k|J_TlzK4ow1gym`;R7#Fl-%b*J0x z_y3PUz7NzVS@}C%`x3N7wO8fd&LUY}&ud;!^;L>DPg%b~MZj^oh(PcK)_CPhRYr$( z3XMWM3@UjS{P}fcvOp$RyalWJ^us&+PQKdoF`t=J(pSFwc6Td_$GP;AH`w!LY>k*< z9lK`YrhnW?S7trV)2rw`e&gZ(so(5g+;min^{-}PW@KPo+&Igiak_y#Fd$`>StJa^ z8bqGd#$Sw?+Qy;7x^7?Tw$$Y}V^^esV_cSxMT|w{#^>`as(275g{WslOv#7g8V)a*{ z%_SFC1w@9Xao=L<6ESFuian!u)78CG!7W*{prmkzUp!B7tcOVb;wwq-|GOx>xWYVD ztVd1d?QxC;CFXl0xi(D;23xi`vOfjB3~CTlwCI=|w8gcwaqstU6;F4Z2m=7b9#(V! literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/inhibitAnyPolicy1SelfIssuedCACert.crt b/SecurityTests/nist-certs/inhibitAnyPolicy1SelfIssuedCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..6512e9d2e9c981f0473f264cd2240a2ebe5d41bf GIT binary patch literal 917 zcmXqLVxDNw#8kO}nTe5!iILfWmyJ`a&7 zBf}xFxAN*DFZZ=A{dRv@^w;lJhm2nbO-sG3HzCI;J*#cb(@eEHHy88BEl;Z7^Q`Cu z%k~PTlRpeC*WEf45czas+u@5#e4f1iuFL)FKWiMLQrXgnrjxGnmsYdkqc3vS}vfrzB@{-W2Y-^{**zP&5cIHd# z;VHV}uay#3KfKr{`_5|n4QeJ$ z4{j>o{pVsorKaBMXMV##np#IM(fOB-eiSxsPj#bjZSto}Y^T0@NOl|@(BH;ByM;a_0Y=PaX^<{@{C z>9{(_v4VbE$1%IWM>G98MIdpN}6t}Lb`OVdboAf(p2GuSPuy@|aX%--N|L}#9 zBq_!^J{9{%DbpJM6|hAl223^lgG(iUtzz~`nU>lg$h*AeL90>G8AAZE237R{ literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt b/SecurityTests/nist-certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..42e00344afc25505e87ba1d008b04711c0356ab3 GIT binary patch literal 919 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 HDN^?U2A61= literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/inhibitAnyPolicy5CACert.crt b/SecurityTests/nist-certs/inhibitAnyPolicy5CACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..fc9b42329920c2e51f653146aee2994c1527470a GIT binary patch literal 940 zcmXqLVqRg;#57?6GZP~d6QivGFB_*;n@8JsUPeZ4Rt5uCLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`Pj178xYku{KpSR;~|mywy2S>l*i8IYfonOteA;OuD7 z#HfVq5k^)9<|amd2B0_>QxhX2!(9(v^<~o9?`A|S5Y>C`%iVwA`@B-Nx26iO6awFG z5x;a||F#SEaxeB+%#`6ve!F@5UfHC-fkzw8WbfLLb~5#*!n*iGC#}?bX-_B2o+&Gj()wI<^&H;u)dn_Q>a6g)aA)2yJZ`qb*$ys0tk*KuxsdcDg-c)#Dg`c3Ee zJapB~XMF!s=u4l3)b4vT7&RihxepsC9G+)wETj0vEq+z zn{$@H$F!c92Kg^1oyDa?ALs<___FbDb-Yn_+047zwH{@ACwcCkzUI}boQa>-v9K}i p?42lnI&=Rvsr&pUQuDv;-_rH!%)}Raj+FmleWIM3#Az}?69CYcVkQ6p literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/inhibitAnyPolicy5subCACert.crt b/SecurityTests/nist-certs/inhibitAnyPolicy5subCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..11ceeb78cc9c157ba47f1850ea675598dcb13ca1 GIT binary patch literal 937 zcmXqLVqR*{#MHZhnTe5!iILHOmyJ`a&78 z7+D#Zn;7{SfZ|+CO^l2TJD;x&yQAxLGvnFLzP8P!(f5;nbf^D$!y{iW`TNWUwNL(* zwW7y0Z5OyFoI0p%KjU`A>c87oo;aYv-O~2&SbB!)jMr7Od*Twk_Py+{a?-mHw(ju( znc&|_dW#+Ba-F;sGC%U5o~BsPnTox}hEvo#N+O!`nwG#c%`|#c*)P*QnQ|h@p;c#wNuzFQE7AOs@Uo;YTSyi zJ8C_Y>@M!OcgQke+3e+-Kfdgm=45K-w(x3K{jA;{?wo}o{Hj;J{rmo8_QzSiKU0$T zv`suab-lNPYNe9*8kK8N$21O|ILmV>H|91IGb01z;>I3>#!dryU|7m3vq%_-HHaKg zYkZ!0ZEnqny;tY13g%1wIp;JNIPzurSj1RFa%QgF#`=0+fv1^I#4M#3A|0*zw+;9} z`uQ0d|Ff_FlM|bPIEb&nB4EI0z{AFs(B{FI3KTbBG~fqG2!j-|8ZZMXUJ_ z1?Y(o7-5VIMZ`t-902fDX}{0&#TsbvMcY4TR%gY z{<@>jueouZ3T+XUViV}y;xqTx1?9;Jagz^()U_RdQqabILw&JiO$1HX@v3jRB WB+p-U-t@@aEyo_QItk4Af{Y)935ktceh; z+8?sSb-Ieyi@QBa#}BVsaa8S{#S*9c&+Hf1-kl&{zP|xfsHh<*nWUqAD0AGC)?@oob<%M!T(Q@ zo=7w6vp4rzkFsrUxDv~2aFl(``nL=r>deMdN;&0&?xwY=y7=tSRC3-rt@4Ndzrz=u&_klCPfhjp!d;&-F*7nSF0L`CGLQ!brmQlHgn?LtNY2ca z+gM-kEATY)iI}DILZqWr|28-Q$nvp>v4|KxwEvTo*N}R4Wu*Xvc3x-H3)aI1d?5Y& zjEw(TSb#~2%|IN)S6~q^;4|Q1<4S1rU`z#y8!#I1gCvAO3Rw-9ffRE508<_?ei#{I z{5PiUy7n)@Mtf#&9FzUD74Fx~-8ru}vwdyS(5PG~9pS5}t=C>UBfDru?yo5;DvH-` zT&Awzxoyh1GZuRK=YEG8ns47{f8L*`;;~}aot_}qZu70_Yl>7HRIi_0(@+>RgKzJ$ z%chsi{_jxwuv{fl=+LrWsZOa!!AH0F*zoY*bP+h>dDC%0PPdw{w9zNIO;dAx-v}5P zX7L?AC{VpI@$3G@&+Z=hSXN^B?sTc$Szi4qH9@Vbn!jE9xA2|n=Uu1RnM?H(IgTiE z&wP8$n5XrK@4m-px$kc5U8WFZAa|?(A-P literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/inhibitAnyPolicyTest3EE.crt b/SecurityTests/nist-certs/inhibitAnyPolicyTest3EE.crt new file mode 100644 index 0000000000000000000000000000000000000000..2c8fd4f6d125298052ef3a02be336a70f2f4deb0 GIT binary patch literal 921 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/inhibitPolicyMapping1P12CACert.crt b/SecurityTests/nist-certs/inhibitPolicyMapping1P12CACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..5baaf35e0f1f8c36b2d683ea1310e8f67751c60d GIT binary patch literal 953 zcmXqLV%}=d#58vSGZP~d6QhLzFB_*;n@8JsUPeZ4Rt5uCLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`PjgHRH!Q8iG8SR<2}mywy2SrU++lbKxUn^;hgnU`*; z5MXGe;OuD7#HfVqAx2gP<|amd2B0_>QxhX2!&l`w9}6E#F50-MkGDXnZBOpUdHzxJ zWxI}qeq&x!qt`ss!aLmHT%etI{?_b{%?ulkt-fI3#<_fV`MwRd%s*_E&C|Uc?iX?i z{@eYDL3y%nKHtN#vzui7ONth|<~gc7nX{htV)veD6|CX*VUMDYUO3TS6T)Ema&nG% z&&N)$&I&K{n5FxkJ^m)e7c0wne)YY5Ay;#LvfS#pzH9IOb*fSj1RFeADZC?^;T(f1!4d zkI|%JW2wNcB?f#T{rrrK|5;doX^G8%AH)|1@mUR+fs}y|NI(T7z+u4Fz{t?Z$Y`Jn z5>sH2GmtUhVdF|@^I%K`YBpd*;V~h{Auv$_5|Phi7rK%xlOLD3{K1XYEJk(Qn=>RU-6=rHR$#>n|HB6HTU1nxN@L)g~_uu zi3#Fs`(0R1O{lAIR{3&S_>1q(9_I~56b0lTm@WI2@@MOtgE=#_zgt}LWly{*%X##X zt$O1EmeUQM#;k8H9Nrf9E%QpocbSvBFS_nL(iL>%Ns{HZSx<$wesjO*baH{A+J%#z z9ByH|Jbrwcym{W&gs7`ha{o&HwK(3;Q2pNQQFK0)>9{WQcY{Z|E1ksWR^Jl}GW1%y uF0zt!!l$jZMpKUp&d+iaU!wk8rEbZ3+fB(+$<$iUFhP}M*gq<~piCNnQ1GbytqAU`KFxzabW zpdd3Z-B2OG&`81A(Lhd|*U-Sg5C|=d4GavT#CeSk42_IoT!RP_t<^A4gIFt%+uGvN zB%sYrj7rFUWMpMvZerwT0E%-lH8COR$}PG5_R({*4;3{OxiLC-RavVVe*U&= zV+HrJ`iPK+l^+bNX0QLY>`$}j+KrR+mbPZIwcczinD=4!<3CHPk~Ss&JLI{<=4rMb z!x@p_R9VlcHPM+r7_DYFW}9j{_ay|2h7?5Z?*8$RkDImArbcY*vzQ%v9i3GxPA$8g z`>CgQ(uJ0G;rjk}#WE{6LYrosy{meD^_H$9*`43#~4o*S}D^$H!<=v9VO())H`HkmX|$V-Z=UHbpjtzm9cJY(g)4_@9EQ zX*tgg_(1yk85#exumF=6n*l$FFAUym zI>S2i7oRUnFwTFkT+whvolW-20*^jn+54Zk=aqyVy02-@dQ|p7&YMIHu~)6L)kVvn z_5Tj)dsU^hoz-m7dBy9B#d|F{6Yif0Tyi65iC{My$LZpwsU?aD1@o`Jd)50n#kpox z@-?RRs*5})lftea;Bu{b+_Bi_&6Jq`7vp|KOz1fi?Qwfew8!FEp05weFPU1w!?%g~ z)-4vEbw^Dc%}P{6&F3xTK?W@-M$&Yb^0$COi`M-vXN{1C7yZP_SYZUr^t{301HTTX8-^I literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt b/SecurityTests/nist-certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..4ad9f1e174dd639b81beacd13ca3ab855cbdc92a GIT binary patch literal 973 zcmXqLVm@im#I$h%GZP~d5E<~YacZ@Bw0-AgWaMULFbFl|HsEAq4rO5zW(o~9lsAwC zakzxVLQ;!M6r59wN;1}` zGV{_66#@*66r3Fm+GyLj zg{d1p`?M4)+soVteB1N$#M7s1W(j0E&%Z39-|<$c?p9HBqki(@pz<&Cx~KbzIfhOY z-BGmwG^s6Yi88CeZfK`Injn3@UBwn%<13|cZEZ6P>;BV=4l3JjsFho;`)GDmmdKX{e%nNy zOx1%9P8Qq3`C-M5Jul3^XL|@e-EcZP>A~xc%+(K)SRWj7Snlw^Blxf5!FP%o@s7fr zM=qq9+CLZF;rZ%~XU8syl`B=V-Y&hlyhU-{_VVCMheG2{eB&!IOxh#&=)GUuz2wus z#8$sZ4mdVx>cUs5J+r@i%s6nK_i~N-W}5}vvktzUysP=e+wJT77k^s+r;uwt``P~) hdw1Px>3#6}&z{>)Wn&#Lh(6G9*H-xJ^}` zGV{_66#@*66pBleoE;71#CZ)33=DzL!q~vTAWEFq*uc=p7{)b-CedbX15Jp{N_cIC zSl+~_gzQsBRtDxKMt%l^CPpr%CPqev$03esM}yMtSmwtbpK>DqP>$@2h5Pqd-maYa zQRMLY0Ds~46F&bB{^Fssq+2%lN3Lt>%5%Hs)S3OA{%e)Vk<$9DH|Jf9br9TB?z+38 zCdlW*v$*nanhPb`*TsKYWWL6A_LnwaHtSA5HXipyj}~A0dfTVDwg2x6{-`})QbU%x zEcA62bT<0+;L^fX%I9xM3Ml;LyC**J^UYUH%%=aNjJPlA-POo1^o}*z@YOKf|40kx zeQl@ja*LibdWI{y{;9jMQ;>__eERm5+ZS9`>#h5{#4y-O)#~BuZ67oXHE!^w9C`lh zQ`e5=g_gIL zh7!Ju27Dm>{EUqMSy+IHjLm=_#1{tfSq+$hlz}QpK!HWhK*oTFjVqzegE1AT(100* z#{y1RvWg&mG6qrx638l%*sRF$3QWPkcx7Y=Ry%*F@#(1_7c7=J`&vzYwb-EcNw4sR zkmJWVLaa(eqz>GS$fQ0-`Mv*j=pczL~o;nt7oAx7es)+j%iF>ymxY$aq ziU0p5AyDmtc=Jp7g}eI}^xMoxORal!MW*Gr|55(;+Z@=dG9C(BWGgP8WnHcpB&&Uh zHAgLf>E(jIbqzBV_J#+DO$jQyxAgb^?MdG!SxLkne)CW7)3rlZ4Q&r%_kHgDwrbAK zlqdaLO%I)U`jl(7&2;HKCf-6$GDQW?Lkt3EpStlZxYGOJwmA>3Iu`DGe*VjRZSU6_ qEw|Uiv}LvmrWPx+&gXPHxaF}$Zns;LZQthNJ+1=9X0vVzT?7DYL~(ck literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt b/SecurityTests/nist-certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..b1e9ff8d06883a9c034880c4da3054cbb0fd4d2e GIT binary patch literal 1006 zcmXqLVt!@N#B^x^GZP~d6CB(+$<$iUFhP{%+Eq<~piIWsRKGbytqAU`KFxzabW zpdd3Z-B2OG&`6=UG|Ab~Gr-r>Ku(<3(7?bD2rY~a3=E>gd5sMWjf`PjgLo2c*Ei6G z*sg}xc7y|(7?qHH%*e{X+{DPwV9>shGov-x-EwelnXm!E~NR2pV1RyuyA+V)#f zyAKPpQKW%PdAmM z>bI-Axv$zHA%3#F)|7uP+fk3(&C+=q%sVtLmOb3Me`A50K;ZuM%2U&b(OV|0P20g_;ks+-t(LNu zDL?1TUgNiTTOIrKMn~O!d((`#73DR<(Lk@Z}F*7nSE^gdx(73@s z9vHN;$}AEFVhtj)Ea%JA+545O4}EFUd-v?Fa6@%4IBCf8v52vV2(?R_rhnM8aDmw_ z(G{AKZ>45O7Z~t?^z$<^{%2tUCN?$$eh^<6#Ah{N22uv9AOQsyIRhC39yYFoHV?*B zph5#i6dsd-8c3NUNS};>lz{}YN+dQja=ZdlGB92l8C1OU6@2Ekm@d+o{i4Ti=gVtH z??$TZiCD3>)0W*m@6oPT*PkC>KWW;t7hcvA_g&(=z?AlFbHW9~gcl3+KYVrGymN)Y z1iKkGvJE8ietcza5qKrRdV0zO4mDPem!HgP@~3W|%Xo?}(j@IduJziGb?KE7bKjZ$ z+k07j!*BB$D@($*%AM)kzuwZ-_Ik*JTEnt)t{TZp*$(%<;)-(}EcKPz+5Zl8~BA3S}QE@V2AS!JcOa@7M~ue6*uk3Y>Z+j_|9!Fn~e wKff%ZOnkgn@XL8y&Sd28-XoB4DY!!B#_L_KPCuSkbe%X{sbDMZ+L-FO)MzL%u6>^ z2ryJ|b~I>WR6_O-BP#=Q6C*zZP@IdYiII`va&eKw)R^e)Hut8=R+hin{`7_F+<-C&X?`t4jQxl8N_9+&(7XXO z+9rqhTX1eYl4Yyz&y0`A=q<9XFhowYvV#?1OIUn(EoN&G!b% z_4fsI%`577iv#6gOZr;0H+vgA}qF zFas$AA&`IyNPxqDt$~rDk&zKO)_|!H7;B6SBAwA`wJ`^}7RWVfE9eV*r>u#tiMe?~ zZmJ~DN`TH{@Na1&3dES=! z^#U`D(_X!tF820dT|?>WNvByiOq;Ad`DfLIhTi)s_Z`*NO|yKx(VVOL%B!T=MN%vq zk8R|St-kP&r)I_qkL2PbF4{BmQ)isrCh+l0XZ03y*`}jATo?Ga4!2g~d~=l+c^pj&i*g$xm*dwe5K}Kg6$&E#J25EJIPUV>wgC0pC~c(RvPC pNr|⋙hA6FR<#jv>V*tk&}F5Vzm6sB_ZiA7i^!tSNF%n&j7&ax literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt b/SecurityTests/nist-certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..65155c7b5a037643975bf327eb5af00cff66486d GIT binary patch literal 931 zcmXqLVxDi%#MHiknTe5!iILHOmyJ`a&7`9IZm1AosNn2qAScdiXkcIngcimI1_n{$yv7EGM#eBMjcjdVR6_P1BP#=Q6C*!^ zK@%evQxhX2!#+h3rd>z7j?M8`Td`+H?`k9dCD&K_aOmEtH5N$|t1t_RVsML>lQW#Q zyV-QV!>Up8aG3AhtudcD%w+S;hnsm)RbD6Q+B*wm{ zUv|-TkKg5tZ3z|CZT}4$c{Q3gyb(`RbleoH@#$TG@2kyAm04`pMQ(QIefaP9ylI*R zuNf9s{fvBb`qlpD$6qPG5Nr6i$lmy_z>%B-7bV%g&3mWnac`DSY4f%Tna=u~N)Mkb zp1a&YXDUO{^}BIC%u7uOh68OQ_UP*#~m!a%G+WZ$;Ado}B&7T)ZB zxTGPYS!1o&2S#uzkmX|$V-cBt#wqUl4^fxy&C>%X-OXXNR+PA5zz5RL&&c?ng$0$Bs8Au_=4>0)wLm5{Gs)wk0Uz;~^yIAg-3xO|mCx$sq zJF4NTap;|E^27xaKcDZsYJ5cb8}qvr@d5{0LQ~F8b;#0m-C}j#-yvx7<*onzIdi37 z-N5OZ%yZq{Jk~AaQOAx--+c{*ch{+LY|S%aN>Ywamvd=6!Q4|l)w0K2b_7mG1e~ksQw|Y*^wfULpl6cmj F2mp+0T(AHD literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt b/SecurityTests/nist-certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..ae1891624b9422d3bad407133bba7072186abd67 GIT binary patch literal 979 zcmXqLVm@!s#I$_@GZP~d6C<+$FB_*;n@8JsUPeZ4RtAG`Lv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP~AWkq<~piE;BD9GbytqAU`KFxzabW zpdd3Z-B2OGP@%Xq$=T6BPMp`!z`zg)EsPBe45Gw&jSUQqjA2~bS=_{^gzQO1RtDxK zMt%l^CPpr%CPqev)mzW~fBa39@5^c?qf2}*f6nz++_*30#WjU=-cCLv@8yYBtDebt zzhnu>Vb5$dc256OetTde$n}G@22+#1OL^_S4syP2ERXTdA<6v-QQBfXJ!k!^o)1aWGN&qSu{WK z`-7(r3^Ku9<{6QValdkUFA6-^@J|2qQOW%0O2%RRhg(dRIiI+8Aw@MrRrG3f=o)P+ zpG&$PYn-m%R(W>R(1t4`WSeT&7s<4PY=U1E^<=~3^e0^s(7DXC%u-nI7i-9SFZrup zbLU)p=ykB@*X-y$uO}>jee=POC9+J+j0}v68i-dt#gUIKz?DowD zmya_g-FkK^hjHn~Z4IZvsX>;HMT|uxa%WD;tIzAEz1kKSquOtM{_WSvd5I*PAH)|1@mUR+fs}zbNI-!_z<|$yhm9+t&4V!&sL+7PKn*0J2vR9yAY~wd zEQiEKPp-h2WMuG}Qqxiu;{8$W%cSaO=J6KIOJ@iu^j%S2apL%;ZE64HuV3Z}`d_FT ztDoil_l?yHSIuV(nQHrPRiE0o@aoKm7d@C8G$($3!dAUUWzi)0F89Pjqj_P*>00YK zey@J6RlfXqrqrd}>E|7c_5N*0du6*JVcU1NKks%N%oK82kh^P=NvOljS*L5H`EUDd z`f%y9Yz@b}H6o9K>@TM;*{x$d`&nSwhx3lv)$USi+=r&g%2#aBX5AJYx#8UE-??HM z_7(4+p0r>7^273OQBLNmO6CG?jZ&tb2NJW_%snRWpu(QLx0}~aI>}` zGV{_66#@(uoE;71#CZ)33=DzL!q~vTAWEFq*uc=p7{)aSC(%}Q167EvayV@*E=>Yj z+{CDa>_bLY2IeM4eg>d87gG}>Bg5N`-+%ZVk~_v>ZkR4_bjkjQ-r0b~yuVJf_1I=6 zIiFhksC>%I=}P`n=P&GCcYEiv2?3UJ3eHmZc@5l4OD0GO6sAvm@Osfn|EW9bu3l7} zzR$up>qSPwbV0LLnc#?f#-A6LUJd?Ym!z|;?$VZYlc^as->p{vymeeJE-$em@Y1@w ze^)hyOL#p^zq0T6?y{Q5`;3owt=_&qi78-1+$Ys*XC2hvBo)M;&px`Z_=93$%gp~$ zW}A1fV&`uTs%8qB`TFh41g9T4yEg=77Z%Q$??01ETkNnjhkZwt{+IPX|beDUEQ#8R;cbrCT2zk#>I_G4H_32$OD5^R+&Y@ zK&(Mz`WdIV>pw(Yx;IY`oOCyb(OOaB1~@6m^0A1qhK!d>Sw&n(z}p<1}%qN?qrUEQ@(^IyvbzrT1=-TCh&9vO)(1(P&mZ?m^gSU&Sm z$EmOk*6CTP!e*-?zAfZa>1^P-VV!g7|MtFl5>FR)%X~fP%xsXj#QW8Wv;U{4Ej-7< zDm%gB{HN|I5h72`j%XiXctA4IusRQ*c}k`q_o!xK|g8JTChDm`i@ jdxu8n#xvatvP)C7V!J9rf4R8MQZHHm)9;je_^j0cNWg31 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/inhibitPolicyMapping1P1subsubCACert.crt b/SecurityTests/nist-certs/inhibitPolicyMapping1P1subsubCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..3a72ec12fb8bebaece28b7d617ddb9f715e1744d GIT binary patch literal 982 zcmXqLV!mY1#I$PxGZP~d5E<~YacZ@Bw0-AgWaMULFbFr~HsEAq4rO5zW(o~9lsAwC zakzxVLQ;!M6r59wN;1}` zGV{_66#@(uic6E69S!8fc?}H=41v(X*ucObN}Si&z|hDT#x;l{(PAwF4T!~x_$-Fl z-NdMb>`z8k2IeM4eg=akMlPl%Mn;B7+0Jvmjrm(M4S6-D z*Y?N<`5i8Pa^+O0sL=YQt-m<`$jp*oH(Q`|s^3cHB`*>f9|Udv@AAnkXM<$v62Z-; z5!2`OY98Nl^=pGj@)RxY1CRQjoWJ}m<*VjY{^N~_lh5vo`P6eH`_N;d-nto2XE7d= z-}G{$+Ufo8M193f@r6NrRs&`rWgrd`P+$=-;4|Q1<4S1rU`z!nG+;7N z14$@?RLU4g8Au?@A+ec}V-lERficO*Q2JxN*p9hAzSk8eL{xS5-zZF++K$L zk3Wm$U79+*>>cZK!NRnp^S9-*j22Fvb6ruVZ~4W=ksp6qcKe^2@%6~*S4wug9^U(0 zb7t+Cb0?%NH#B1kONz`{*~iCN-n`JcX1Mie^>_C*Hg{Qfdrw|g^?1XI>lYSW-eh6% zcWWa<^}Np6$D;oWl-*`sadqPT20Ol96N9NgW(WnBUU!;utW&2%eeu8h7qeZyUsgRH pqR@URs3*_IwCJJF}#MHfjnTe5!iP6%4myJ`a&7qE^tdYpf%g9X1ED6ZZ$xN>FO)MzL%u6>_ zaCS6kVpKx*3?nN8a}y&!15licsfm%1;aa+i;rWEj=4q0Tb8DxSpJ=u`!+%f6<5ijF zqNASzujs@TnDO%8X*K%U)0;Ev@PpVZTjgI{-s#vmfAWjWWz*fOCobce|I^-Vfzdb9 zqf3LN&mZ_c@6WSavtI5FeR`wI*JInf6#bu>-NA|LMCqF z!+X~+xj$n$&2!iM!E8;b`BNma7glaaW!aK&)NV@rs@(6QbJy}OxbbKce|M<;JF8!B zCOl2b{kHq@svmOQGw$&};}G=>-Ea4>OS;-DlPKTXlbrlc?#Cj=sVPY- z>wj(8JJ;~&QEgqJ=Jo(Q8ELww9ZM@ zO`FpDb(U{k6Q26&c9|@{+a&!5#@}XePU0~9yHakAdha8-*+;G8m>jNZ)Na3Y)r{lt z>3yb*oA3HC)g@~?aLxF4z3Y>(tl+)FS6K~Q76f&ln6u%F664KK_DxP_6@;=DssB4r zI!8zD-!Ude_oC9DeGEs~PQ)zpTzz5n(e|&Lr|0+AUshVaW==xro2;Abs$vWtIo0@Y ojGmsfUvJ07e)$>y;$qY{=FZ<>C7I3gIBuUar?%s4S>3rz00@p>u>b%7 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/inhibitPolicyMapping5subCACert.crt b/SecurityTests/nist-certs/inhibitPolicyMapping5subCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..93857ab656577dab046109c44f79b411adbcfd19 GIT binary patch literal 947 zcmXqLVqS01#58>YGZP~d6CB(+$<$iUFhP|-jhq<~piA~P=|GbytqAU`KFxzabW zpdd3Z-BiKZ(Lhd|*U-Sg5C|=d4GavT#CeSk42_IoT!Ro2tyD2kf>3U`2`$ZSA`V zIOp$_vV;|#f=l;bw$0>z(ZL@2>1lOc*>96K1$vXhyqUhte{sL>Q-q&Y<)5O&mbR51 zHkDN?O2lhjA7&*w^`zwgO516gxMfDfOW9VVBYD5m8tz7Jl)kByBq_jni#h$2!-|5) zXHm!ZWm!I&INxGR%7m^5f*}+8a`!36Ojj<%NvuSPLkLN6py`0pJHZrW^{Bccx zU$mEUQ|lmy-UPiJ6gsadBgxL1Q;K3T2g9Bn-qFL~b{* z?@ZD;did{W=SOLQs=IH0kvR)a1hRZAVk{yz-sJAvo_|U>`IP#ZInj$U&9;5YFyI5m zhb%uM<9`+wV6tK}5C`!USOg6C40zbM652c%Q-R_Jj0XH531N^zRs&`r1rbnz3N&IQ zM_`mOGB{3~DY0x@*Qd3~XJjHz-|{~3?+;I5Ou)Rpkh6&s#Htpol;B#%99MBE?X2~J z)ZlA1Ykw7dUl`bYAZ5neLWi<5Vl6_A32nb48=0@Uf42O)vfrce^Y)k1?j60WI{#^t zd&8^ZsJZ!n8Dnopg)!A;@Rd}wpUQi2t|RtDkIEo&Ixkh*9L-C-D;lnGW#DCKWeDUpTdVLVWp&ZKo5jo_nO$aVJdX53|p@ Tn1*@RJRdgkee>~J{J#VMAOc{< literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/inhibitPolicyMapping5subsubCACert.crt b/SecurityTests/nist-certs/inhibitPolicyMapping5subsubCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..134b7f8cb186c381c2bc376d7f5b845b75f83e4f GIT binary patch literal 934 zcmXqLVqRp>#MHHbnTe5!iILHOmyJ`a&7`9IZmLjRn&j+gAScdiXkcIngcimI1_n{$yv7EGM#eC%K{$!FsvD?6Y?Z@lE5za^ zMkQn)GO{u-H!<=v7&I|*F*PwVGCXnMik-})yWS-^^0MttnSxiZ3%B(1h*(JZ1V_82 zoIS$4(28@eU-@Z=jp_HIZ;SLF+BW-j<=m5NT5Jt_-Mgn>3gvRDjyuM2|D1#-^Ih|M z)7qc+PTe|DO8;8^;w4NvE7uM;@GU2ZHs86x;=X2<=h z{2v%b{c6wD!c^SG){E`Oj>9^(G+VyWqVe zf)P?58@6Rntx%5{nCY98}b)5Fjih~|8Q}2%7L)&J(7zJcQq_|X#8~2u3K`7 zNn2)!&x!8XU|XBWn{={vPw~?2OFt$TuB|s@P+4Ub2?MbP zksEJv_ifKVC7gUp{mh)`MVV&XK4pLtf-E147>kJM@+%L$OZ-At6mD^V=Y}3NuY)i(Kz!r-{6K zw#Rgm$z#{-cbfP1-DmD&D5x#e4GNxZpxF1|nQnma^j7|&=t&bNJjh5msbj07+uE3P z`0j#}nZ3BX$Lgk)BZK}U&FxcGUApU1;M(-+PvHTtaP$002M;f{ UaQv;h-f?olDkHW9%YIn{04-!`Q2+n{ literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/inhibitPolicyMapping5subsubsubCACert.crt b/SecurityTests/nist-certs/inhibitPolicyMapping5subsubsubCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..dfb268d1d33d1692801e094b18a4cddbfb4c1c41 GIT binary patch literal 982 zcmXqLV!mY1#I$PxGZP~d6CB(+$<$iUFhP~AWkq<~piE;BD9GbytqAU`KFxzabW zpdd3Z-Bh8tGzo~D9S!8fc?}H=41v(X*ucObN}Si&z|hDT#x;l{(PAwF4T!~x_$-Fl z-NdMb>`z8k2IeM4eg=akMlPl%Mn;CiQ>y0%@EBI;wEQW#WF5TW?;kDOH$1Cvm^R(p z8?I}TC-TMh^to$|m$_3G8#n|O1qB*bR;S5Vnzt#$ALU6ge1CCSva#9;v#oLtexKiG zUH*3BgXXt%AFh=@v{jcFoO}CDXkA{u`rX*p@aHo_l&zfKFs+yPtT(5gt$^Fe)Be}x zgi8sn&qXx+bhj`piws>=VE*HZ@v$TGn-1Gwd(iv)W$NMo>Yv2iz6iM(_`ZL)P1VkM zQ^m>5;^v!cZ#MM*-XxyE@yOFd$aKZ5OLp#3%3Q`=7IC{H=E&{e{`hxyoEz(o2AxYe zTNLJ0pYFZ5Hre6Al#_pxBiLW$&764tzWc;H?&*vhnV1xS!EUp z1F;4X)8$tldYAZxt|;8%RB!Z;Md~Eu4se2ysT(!j4eB#E_V&^wo zUu8aDzb0mTO~Jk!4?kDzkn)Oubm5RlyZj=qu2SwN>-XI)Uc--ry84%s zWurU)^i4dj(!O-Zx5w)@sr_5>=k>JSr~}g^ns<795GlSIR(*VORBB<-`}Z5w+lBrl o?p#U9wfe?8*Vvjw{^h=oh&<(Z`c07j>C^Z)<= literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/keyUsageCriticalcRLSignFalseCACert.crt b/SecurityTests/nist-certs/keyUsageCriticalcRLSignFalseCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..2467c945add087449d1d45dd05e8440fb01b121a GIT binary patch literal 923 zcmXqLVxDf$#8kh4nTe5!iBZ9TmyJ`a&7QxhX2!_}B5&$M0lg-a6Wb*N{!?)<_2 z&!O=q|5Wx37f(KaS5|hCfp_k1%K%|<&%&CCPMdx$_$^q%&8lvbz_3qUc;(KYo0rCS z{Z`r{v_S2e{<{?RSq1i47h^V^E>Jipb-^=o(&g9p9%O`ze^mK>?|Sf)b9EIek9T(_ z^Q`)IXs)x_n*B|@@>^zxtex1fQFkkILWBE0gS_mdZS8CB*ZEK3{Tsuk+}R`4UCLbE zFyYibhGP4UIbnM*S*+R3`7CE+e-_{OH&=tibHd$uZZ$Z}>fqZsHz91A^Tq7uD>F*w zsdL=vefvb`{fW)oCysvcxcKG*hm3vdkMEo3om5mm5ij$^zM*4I;pf*(%!~|-i)#$3 z4CH}s0po{}!E(M!v>UJA^{Y=d?l%_Ho4MGq@AcM=B72oNW8_r)?$fd=NQTndU_dQO9>yin<@MXlsCCh3T$S8W}sjl*gZmVo7}-a{txViPNUt zlCGB6>7QEn{`OVleJNkJhDX3q@7l_ssejC3cU^Mjx%?{9Iqb`7QCqHiOlKKozqeoYz0^Nv z`|JIh7EkvtOrId2{k?6r>yh@BPYjdJA6GHn=b%+U8C$L}`jJIXZMUNv_we6st~ gvlEwJcy6|ch^!ZWGO>H+{+*&4j;~{!^l!TW0K&>*D*ylh literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/keyUsageCriticalkeyCertSignFalseCACert.crt b/SecurityTests/nist-certs/keyUsageCriticalkeyCertSignFalseCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..aa19cec73d2a0d7d5023b1cd681dc0df7835f855 GIT binary patch literal 927 zcmXqLVxDc##MHcinTe5!iBZ;omyJ`a&70fQlkGS>J z9t+>BWXJk$6xo!sKwjVytiYaTi+zkFiGjEegy!T)VOJ>J+RezDiY z_|`iGNxr06r3L~w1&h8%tq;uRIcgs8oTYlUnV>VrXO;Z#4x(I{nw34S|AO}zE9XjE zFrFz>l;2?N6&HP5F*D=n$*D5CuFkhH9I0eY^v52vVn1pht|B=~v=TH%s z$cN;YS7v`m{%If%(yzcGV8CaOj`zw2K*oiVMfOPEUX61K+1p*B)|_6 zU;(8*dhwSsC*$3er!_GGi`P#6ZLsBW+hYE| z>GFX!C+<|`OujuwU9;udyV|^`=6?^q-Ia8{kt@qcWsjs~%75vXE0^%Rlb7T^(zwm7 z<(8R0!+ACNMc=nB=ZR!$cqqJn;pE1zkAH|CU{RX8YgOul`a1!+#@kys9xChX^nT?V c#qR5F7js!`;-Xv2o=P|zIP~YQxIXg}04s)8ApigX literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/keyUsageNotCriticalCACert.crt b/SecurityTests/nist-certs/keyUsageNotCriticalCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..bab8307e33090b6af0528075dc045f51b760290c GIT binary patch literal 910 zcmXqLV(v0%Vk%m|%*4pV#3*mT%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXAdp0B6bCa#4d=qUE;Q88@ zCuc4-FK**g->bV5dDCD2Il%f#BvSRiN{{s^@y3@$f?|b<8`$Z;ZMh3>kl?LVDpp;c+kuVTz z5P4D?e=%li8;1_-x_zbFQkUP1U6BTkb6GwXF&2@769m0(ZqYtkP z=Q$l)H!fSbtI@#VYU{($yAKS`8Gc@P?c%wEd*;uWJwbfe)3+Cwv@(}eFJM>o=IvrK z@9tr*4_seY6~5k7*nGui|!jsO4v literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/keyUsageNotCriticalcRLSignFalseCACert.crt b/SecurityTests/nist-certs/keyUsageNotCriticalcRLSignFalseCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..a6d878c8dff5008c174150662c1ac9d2d647716a GIT binary patch literal 924 zcmXqLVxD2p#MH2WnTe5!iBZvjmyJ`a&7uQ9SRFgG#sGXTZ8n3@@b5bBS_d z>}Th`8GmowV_kE;T;^l8!S)Sl<*%;Z{T%h%-+ZZr$(o6a4RcPN`<9fXbD%8xb9KYC ztG=3(qZV`&erq^gzaX#F-zQn~YEbc-NndBHZhLf7Yq4qGU73Hk7b!e?>a$Pr&LXX! zMn09dq*e;>-JS5v`Qr@(agcrm76Ai310FW6gfpsV_ zUiFL48pgKLKMU&SGL-L2D63p3>3ZUML;CDw{?dzA6I)dj*&}(c&M2O`rRYWRG~PzH znE7}7-YmM-v0KnCulMA=1A=C;{}TlQ58f*jsoGX@DrM5Wbo1CVnYX`Mgzde?_c3h7 zJ1yVk-%tN)k34>#|Fg!1dHV59r{ba?Hg}(Ke(77avT%mZykDmyR6M&a6en!F@@x5@ zL&2Nn%nHh1yKGxAGv=JswprWE7p;na9PsRyV(Onq*Jd}qD_mZAhCe2rBdpDL(HT3{ iwL%iCD<>LTT>j&}z3%!9?X8(xeY>-lRByL=5di??4PXTT literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt b/SecurityTests/nist-certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..ef1056f1c39c7f1e1a3f6067c4d270ccc07cc69d GIT binary patch literal 928 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/nameConstraintsDN1subCA1Cert.crt b/SecurityTests/nist-certs/nameConstraintsDN1subCA1Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..645f0ae7c4b41d1a613f823715fc47b3b3294b6a GIT binary patch literal 1079 zcmXqLVlg&oVwPUO%*4pV#K>yE%f_kI=F#?@mywa1mBGN@klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7lRDPR^B%S+5nbG*mWF1j#WAOJQ?NacPpXqoF|)qY|>G8Ce;an;7{SfZ|+CO^l2T%O@|mqv#k= z&mP#>e$8EvCGEWQwp-Jj{&qc>UHD5}lu_z(wfgtgg5|CgVx~oh9^Yx^J4MENrQ9TD zog;3ZU9OF{bNU~~H{0F+^Jto9_8mKocD;F1KVLh|P{TNDe`-w}llysz*tgE7yGstV zg#^BG+O`p4Wa@EGkcN@OCpS#hu`*xp&Q741` zyPa!({atnScg6lKB1aSqCIzPad{Xu9UD&%wm!P(!2j>}FgRtEStJa^8bll`oZQa(t!R4w(DMHGm0}0D{=9Dkrw&;@ z7BLo)hZcMy5+cqq=bn2f9hW*d>04UUD+4}|ett&A|12!P^u}f&4&p1Y2pI4g@UU?u zw0SV50>up&4fsJ4!XSmL2FyUppb8`)2NEbS$Xk$OkhLVkAdQMi1$QzsLQWmPECEa% zj0^&4wr?drR2{delzK36=bD5!w^!ZQvR$gU@5kg~&P{LDmbA*P+!)KX@pp;G2d48= z_DV4G3Wi2aT`80MZJM8A=3#DG)6%mis~V5zSUtNM`$MC|=vG?EnXU2VrtxzmW+^V_ zN}0J)P;Sck-(#Df z^d7I%%E@wTkkVd0%l}*tGbih0Ro_>+i>eQrsTC%%e0#+_b5WM>lKmc<{B<(M7Js_T P?wy*mNd50}UYR!lnL&gr literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/nameConstraintsDN1subCA2Cert.crt b/SecurityTests/nist-certs/nameConstraintsDN1subCA2Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..6cfc5926a505818cb241274bb2cd45db5b422524 GIT binary patch literal 1051 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 Y7^}Ve#)_K2n=&fzq^8)HuaLC>0GiZ;Y5)KL literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/nameConstraintsDN3CACert.crt b/SecurityTests/nist-certs/nameConstraintsDN3CACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..87ba14d13a64bbe1fa889a798e69d9de51ab6732 GIT binary patch literal 1008 zcmXqLVt!-L#B^l=GZP~d6QhFxFB_*;n@8JsUPeZ4Rt5uCLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`Pj1Ah{&fx3fPSS&9wH`O^muehWrF*C2ESi!~5Si#xR zpovil*(;2!49rc8{0u;GE~X|%Muua>(wh`Mn<>ezxe#{h!`lSDyT%dSEk};*n(24x z^n-)|g}pPj%omtG>Z4QMS1=-G(aliA;YRA|7pP~nMOKU`bEM;?G zTN8eAdGQ0~mNlwfD{N%=rp!JweW`R8+uuyDUpvz|k6dbG59JgJSp7&EnvLx*+UzS3=}%WuZ6NCU^YEFX&)iwN7D=zYh9%p;d{Ih53J&ULl% zT6o)l52T-;k?}tZ3osS28Hj`U3M>K!d_i&x=~TuuI3m_H##ZTKKG6ViO5B)w5mi+2bItmnnSPdR{;N?Xh~@ zhJB%Tzcswqblx1n&Xv|6HL-C+SIfuW!9fan5#P2mN-nnK;db!**mVDFwXt%KVNPX!$OrwY O!mhdEf+@$MmIDA~)pcM1 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/nameConstraintsDN3subCA1Cert.crt b/SecurityTests/nist-certs/nameConstraintsDN3subCA1Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..7eed575fb4806c8efb91446898073a4ab52fd240 GIT binary patch literal 1022 zcmXqLV*X{&#PnzZGZP~d6C<+$FB_*;n@8JsUPeZ4Rt5uqLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUDLrhr*kEH5!P)j2<}xTGjCGq0pr!Nt#5 z!P(J3PMp`!z`zg)EsPBe45Gw&jSUQqjA2}ZU=l4V#+L#TjZ#yi`57Z-4ZvqbECUn|C~kX1}fSL1)Xm;*R^f&Rs8G`hRYECiDE)e=of$ zlVE+>{c4ivsp>toH`30|Pko{I>HWD=Jcrl(Wb!a;+qyFE=R+RG1DiO^ZqGg+!?TXt zo;R!Tfs9b+g@5{C$E;FriEa6HFYxy5$vFqOnV1qS!EUp1F;4X zwmZ@LjtiMbF6nY8so|XKYU8!=HaG>y^0A1qh&1duuJ^r9s{W%z^%v9EcV9*vvk5TZ z1L@~yWc<&<0!&kE2I3&T0*inFp8*dWS3;WyV=7SGfYE>-Bq0n^$ZEh0qzqy~0&*aM zV1vMg{sz8FybU}_Ob(J@`&hVz1yU=Lb4pWEQ-VvAN{UibjgS)nFl7T103$;|hXUv0 zKcXha|2!qNnAd6=cK6x2WFFA?|MioH$Tz{Bro3Zpi)z;HjXJw!&-B&1By;bs__JuU z>ihL+j`~GkK4qxLI3>8rn`-iDN;Ld($xvkfa3k_p(b3mFJ2EcJbNEqF6yUa_LuYZw zl}RFk7wdPjtSf9-?ta_#rqX&hk)FLAD@~TXl>K72>&AljOcHw{)rzmAKk`|@Eb*d$ zkwMvtR<_F;6(4uH-$}VwBDu-r{L{psA8&e#|3v5P0%H8z!^dDKwiu!J^^U)k^8Be&35sI{Q9o9nJr= JD(3IoZ2*)LdBFex literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/nameConstraintsDN3subCA2Cert.crt b/SecurityTests/nist-certs/nameConstraintsDN3subCA2Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..08f2245ef6cde76df2b473062101201986e19d39 GIT binary patch literal 995 zcmXqLV!m(C#B_WCGZP~d6C;ZOFB_*;n@8JsUPeZ4Rt5uqLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUDLrhr*kEH5!P)j2<}xTGjCGq0pr!Nt#5 z!P(J3PMp`!z`zg)EsPBe45Gw&jSUQqjA2}ZU=l4N_snRW}$&%MO`de8k!Ws6>V_~u;_d6M;6UhtlUUF6xY%*)Tbd9Q3YKEW@bBi;5& z+E9>Z!RDEJrUX5xyDTdz%5nK~mt|CmVGI-dqgPQ&x!g{F?_>PQ!_J?sV#)OUSCixK zM{fc&tc85KH(&UYR&n8S#zjN_4cAW{n^pJsde(jWvJZk&Pc2nYj}F?fK>fJP60fC& z*O%5aYHd6B=vr&Dm2K;-<+`_z2`$Um_webm%)?B~j0}v68xI;Z?lX`F2B)kti-dt# zg9zK5=zYh9%p;d{Ih53J&ULl%T6i0r0%ZAE#8^bmu)NLEkgdCy@`|BD>rJWP{-t{9 z27Dm>{EUqMSy+H+ip@YA#8+SuFyJ%bVdF|@^I%K`iW@K*@Pj0TK?+$7n1Pgm6G%V~ zBw%4+w!p-|Xo-P=9%;z|IhKLR7Z}To43myNvdwu_)VMw3)GLNhK`DA`{`7Cv$>6 zLru4hOW1N1WB#NSUmrCp79^M`S1z9J-83WZ%7oL|XUr}iN;z=utdp>F+LDtDdB@}a zFHO;(_DClAi(KT*1M_!(>#Uq+<)pLnqM)hzI{CLRbJQk_t$wgBy2jA$`HZ6<6J4bJ ziY5nCeKS7Y71N&i%02OJ_TlHNgzuEjeB0u2sN&-8Z!_y6j=Ly$F7Mj3H!$zjB6E%$ zU0(LJoC061MQVe7G&e0{yx*RwT0ZSnSp4a~(?mHZu6P^H{=dj1%|W>-|MV3(DfSnu nuPJryHqzNt8u)2~R>hkAylyf~VvWa2l6Xo*6!%v8Y?T85ndWgj literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/nameConstraintsDN4CACert.crt b/SecurityTests/nist-certs/nameConstraintsDN4CACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..3b11463186944707a91f6c695581e17986b2eb74 GIT binary patch literal 1093 zcmXqLVsSKRV%A*1%*4pV#OP?i%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz@J2GpzdH67RyV_O?A%CD=sNY%*-n(R&en%QE&!& ziBSpJD~zlR%uS5^3_x)%rY1&4h9m0&|83If-Kib-yL^JwxjX(z2YY|s&9VOPskA=Z z@UTQ>c_06?4-YF}&s7lRf8X7B)%=inO+$~_)b6)MllRRr5?9Z$({t`zc6;rmpHsQk zH7xiTc2DC1Q;Fh1<37C)m(Da~%wmd5{nJ%!VH(4%^+x4)@eL7~1r|TQbFVMi8hCZ} zGMmcRS{uGCE3ZACax3fhqHZB4);%fwGVfm9GCtPy_4v!$<$dBCv~9L_b)9Uemrvlm z{jxfC#Wq)~(@vA^RsSgmvo8DB%hLF8d%?~HCU@DIGQFxo>G2yQR&<%*epFxQWpK7$Q0b^1wKgRc4Ve z5Ni;5QX79UW@;OU4(qyorQ1@M-;7<6299-EJ{B<+ksMF6wR#bqLS})E)*(S^Dh!uT zl^XDY^z$<^{%2tUrXw~3aS&gDMZkd1fQOAMq0NIa6)0}NXuuDW5C$n^HDCr(294`M zB61*+#w7-g3l}!dGw@yFZQw~_f{+B;$-*rxkXn(PQ<{>R5?q>8Qk0r%NL}NMkW&>f zg8)+%BSY?{mi1iSr!wDc60EJw;(W{dLsBbz;_v4xcJnMyI?0fUXhr&tqWi0o(@-Jn~ShKV~(dWNc?fXBW zwS6l>f?xNneBAP?*IcxI*TL$U4?>$?{fO3)O1P1@JA^%*4pV#OP$e%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz@J2GpzdH67RyV_O?A%CD=sNY%*-n(R&en%Rd9AR zXkt`C_6j2_19KB2KLb#li>Zl`k>MTF?-)5hx0COM_Fh+6uw;G89^syAf1fFwv(yU7 z(ztqjatznAcZ&{*&tG`w=s8y9H{bVJ@i^@jD%EK4`#T{Z`Uao(ftb}ZrM9+w_F{Z} z_rt4*6W3I8{4aP}A9XBMaoy_H{`6Z|;B6bhdu<;LWlru{`6pug<)~w9*M;tA?AV;X zV$tqt+XJOjJwC?C#N`$?zZP$6Qop)2`lheXB$LTL`jU?_hZuzgZUStJtJM)*ThuaWnyMzU|ih9=m!iDF9UgCoXIM) zNEnDUh&-u{zZf&MjYEfZ-M-RosmpK1u1EvNx-1`y7>mfR`JAUFSkCb)k9z%EVCtI7 z%e`XN4fsI%`577iv#6gOZr;0H+vgA}qFFas%r z#A%n*K3jz%MmiQQWk(eH&3?zW&uy6|t7Ni#CW|owsrUaKJl@z6>8ZOK> z$Xt?ckV-uh4JE-I1llH$T9KSnnu4$lIn4pH4=~L!GBA9c_m;m!VVzpkWqICBsfCx$ z?qNRoDf$+_vZe2SnRy2e=&~O^%^H79Fv0Zj-xDA0O+IS8Qs?t)@)Dk-|N6&)yAO4) zD4)7g9#vM%8^UNG`a-IuiXz+dsQT=$t z=3iy(z1i1)|BfnLad6Gj#yz`aLM^X)q;9-wxQ6{w%1-XIo7S%%&)+T1bG7UBo^?%( zTcUi8TDv_=?L6`v*&jq{eEFKg-~0ZyionOE<@dIpo2m8qU3uD3sSN#TVXc>3m(7pU w&e+|~y2wyr+K#N~$tp7!A6}Lan*LJm@O~@H*~gsAdbPheXo^_Z#TmT@0GS4qrT_o{ literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/nameConstraintsDNS1CACert.crt b/SecurityTests/nist-certs/nameConstraintsDNS1CACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..a7ec3bd1ebb5da702bd6b791dcd4673787bcc93d GIT binary patch literal 954 zcmXqLV%}!Z#58XKGZP~d6Qi2}FB_*;n@8JsUPeZ4Rt5uCLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`Pjg8&k(Q818$SR}b%$sD$hnMpg#qCPsb+pg0#(6C)$TaWxOCI|tHl{(BKs6~MJTXj;T-?L(T{m$$oa zjpkicy5XegnF~cr|4wE2^zVP~f=o@v9j{Vv9q`LioA=_8euF^R%#y3I;VPd#c|P@9 zX{FV==TTkHJ{K{qjpZA5I2>HA+bVIa^?Z?s_Q~1Wzb04+`bi)EeC~gON#mCrESe?y zoiEJ4`^f5T*XXh{JT4Kss8-uRY(cw3-h;~WmLFbqU5nHn9O~LC#P-Czy=(P?f{H~y zs-j{7gu80nFA;%;zRRUv@k-@B(Y0|zkyDdeFpK#VxwliJr zHx<3c(A98k-u{ih*Pr+`TV;h{#_@LnGWYKk-v4O%Fj+e~fNR|~--Sw|ne!f4&f50S z!RR`(PVV)2{F`drr*GyKzOjGa`&;&0ylz+Qt-_x%tQ85CkUp{8IPX%AX7m9?_3AZW z{(h}q7Fe+N$)PtJ{}uJ|MhWkl>hiOx;LNVI2CH4)IL}{x=YsZ&OSPub>$0|-&d{p+ z7y6tvS-Eua|IMZT)46KCJa<>n@SGAfbIR3Fv4rz`SW?xN8tlyGSp7F>%lXT$({I(E wykFVB(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`Pjg8&k(Q818$SR}b%$sD$hnMpg#qCPsb+pg0#(6C)$T-XD8RYyIp!?%v#c+pEdQNGJ4#|Ne>nSF&Y8 zU8Hkfx^9~;+mz%Nml0q8&7^#~?2bI`a+hNF$(!zE)`d;l8zDT!Z@G@kAwfRL%u{dD zd9Ivv-8XqJo89vJceL*=s5N+a$x=6|^_%UtH0yxoqKI4K=Ukcp|5#sNxbD#N-&4ci z_tt1^W7oN+VR@TnvbHy?#Wh*3Yd%H0RmB+m+VZo~j~|=zWGYjS*XoIh%VjlY)gDgh zyl!TAUY;rDklo?m2OX35y2=>tUbuWy>r(rP9TR*G7%p_LjC=)Xy1LNYx6$Xt<4dj7gDXYvP zVIbBZ@}xHYV$9Sw4jtBY`%1T^F25POA`KkrvV1IJEFx|mbDTK)VuK5Ah{-)Tcv3>t zl#9)P52T-;k?}tZ3ose68Hj`U3M>K!dMFB_*;n@8JsUPeZ4Rt5uCLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`PjgJ2S^Q8rM7SR<8}n49XHpI2N`l$e=UQmhc<=4@eP zq~PpmXwbx{gzOzgRtDxKMt%mMI2ThBBO}A=+qc)>>{*igKaY31L*~Y*Q(9I&%CssG z+2JMh@WdQ(DW{CZTvi*qr_B*wlM(pmV!MUU73*Ey(JHr?b97tZYP3$$Ic9xKW9=uS zpUXvVJu;B4n|WW!hNa}x!9=!XBc(aAYG-|K8Khe<`$s#qTHQL@RL(xfc~)P)>Ln{T z) z^o#rH_fba=7)-34l_@F8rMH;Zuftul$)YQg`Cs$zr)yobnV1q zS!EUp1F;5?C$;exW2Uxo=&-KaSGp~A`OVlBY2bL5!aZkom;7W4?*`(+lAWmvfFD z+;`l9<;Ktc)S46XjVuk6f*w|dzuac~SXFpaR0fl(=W!;X^v2n>_kG@%uity7Xr`(! z!$&^G`d<}q7foIBVxmedf6axE=R2nhziI1w8vk{v_@(z8uP$A5XKAToUi*RP#fpqx z=UVNVRbqdA*TA^qMg>%1-WI;l0CIHV` BWS0N{ literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/nameConstraintsRFC822CA2Cert.crt b/SecurityTests/nist-certs/nameConstraintsRFC822CA2Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..58308f8939d67eabfe05f5b8da73d1802b750587 GIT binary patch literal 957 zcmXqLV%}-c#I$e$GZP~d6Qhd(FB_*;n@8JsUPeZ4Rt5uCLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`PjgJ2S^Q8rM7SR<8}n49XHpI2N`l$e=UQmhc<=4@eP zq~PpmWYEN@gzOzgRtDxKMt%mMI2ThBBO}Apv^&8MeMNhp|9up5&CfDm#haTa6H^%ub&ECT{j5vG)m^#OysyRBm1Da z)l<5GjhMF#S~ z;FMKnkuVTz5P4D?e=%li8;1_-x_zbFQkUP1U6BTkcUe9bF&2@)hO@ssi#%-J^7(O} zJ16guDpat*fDfdfpONuD3kxtMu^EVi_zEln27CrQY+MO#9*n6#aRWvJevpJPNFl2M zGmtV+0}0511Y``P762X4C<07PCCNxhOD{dY3^^u&2@@ETj0`GYlIQ+>!6mO}%2#qO z@8qhDXFq6aKfbD(etqNJ>mZi(~`oEr5}TD#04l%cHiV3^3K69 zWcy8yx$3jGuTJ<~BEfDxxoH13oq$Jnj7N($Y!;sCy{jYh1E;p^mVHrbS5|#u;7ajt zSDmBUDffM%^0DVbl*wcoQruiIA`8cUAtM`Jmbpqn=;dzmpBHs znU|kl_WO*>`*5xji?atWWpDVy+Pdq}a-+HmzuS@V`cL1vT)kY*Y!q@ohVA<6=K!Ou BZj1l` literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/nameConstraintsRFC822CA3Cert.crt b/SecurityTests/nist-certs/nameConstraintsRFC822CA3Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..ff6ba166ba488ac41f7fb2bd281cc74dbe228ea4 GIT binary patch literal 957 zcmXqLV%}-c#I$e$GZP~d6QipEFB_*;n@8JsUPeZ4Rt5uCLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`PjgJ2S^Q8rM7SR<8}n49XHpI2N`l$e=UQmhc<=4@eP zq~PpmY|zB0gzOzgRtDxKMt%mMI2ThBBO}9_l70VbxF0m~A7;Jx@cG*c*REx2^Ykm4 z_k`&uuy=Q31peenPJW$|MjM@vtv@n~SUH{~FU z#h+rw)^pDp&aN=H(tP&Lg~tnuVv@rrHa|PHoa>@xO_8V73#h-rs3)L?&XVJ=HHUZV7a&WQqlYjFf%Nk;GX7^_0j4B2191>vfknW8&wz)GE1}JUF%>9oz-Yh^k`M+dWHn$0 zQU+=u0XdL>jDgfbpaU93fT^h@87XP$rRSF+$0RUe0%MYqA+h{u|0~V|M$7I>-jw>v zbm80Gjq&ou%U9o($*fo~HI1Kl#nN96@f?B0l@o59mUy$^{tV^(!&RSNIJ(TeIJc|j ze#AxdhpQfIyk8d*F_Xj2@6pMrlcHZL_qYa5?mMCxqY}1%+lo0Qn_XXBuv`21$IBb% z>z*=3UpI>}@a>wK9N%MJAF)Gc$?;#B3unY~-;-jm`(tFBH!=Fh&&!4H1B#!;FP8I= zI4`&OKCg$tv1?tq2ltEUooLX!rO7!bo8v^2>(p?&-&xQ12IiX1n7!=k)qU@N&%DNH z?Oh|afHTC^)b>q>*s0WCV%OB=w*EI#QLL7hS`zp%UfSeU{JZ7+ A+5i9m literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/nameConstraintsURI1CACert.crt b/SecurityTests/nist-certs/nameConstraintsURI1CACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..5f638c093c03d1ccd3e5692b760e894f969df9b4 GIT binary patch literal 955 zcmXqLV%~1h#58{aGZP~d6QhR#FB_*;n@8JsUPeZ4Rt5uCLv903Hs(+kHesgFU_*HW zSrCUySS%#9xJ1D@wWuUBEi*Z>B(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`Pjg8&k(Q818$SR}b%$sD$hnMpg#qCPsb+pg0#(6C)$T^5;5tS6f-`yv@YtA>=uIgZ*`#Bqpi2RiOvD z*q8S(J8?4|oNG{$b#jNq?TJ&IUs<{SzASs;$Ax=Mt1K<|y{~(_K(udD$Xi;umWv}!?k$L`s4vuZZ~`ms>)rqUE18NT%MkEb?CR;;-ix6({< zPR-BAX;J0O=Rf@3pSNvNZbxUAr19HOMvskBQc5p6`zs7wuDyG;So%GS!zq<{I{p9Z zx_cU$_IH}Ja_`&EoM~I_md+jkS(q_p~y^Pw>kq+p96( zV-jI9-~;LBXJq`(!U9Z2YzE>Wz5~6h0a*j-1(F8hZK8U>v{aIel(6*D^UIK<5|}K3QOU><{c_iq`pWay8dZH_7k|&` z6}cP6-T2PTk9IN{pOas+&U=X-QE&E_w28#>GLN}I<=L%m1TkT(N)v*LISdXoLM+`cgrHn z{HWC#OX@oQW@~&et(wIBs7A|)LH4z6wA$91;?$budY2>o{^zgJOAV>WSnX;wcfP`1 zxy46Kwd*3nZmtXGy{vZRsaXBto$~}AT2@J|lnwNLs#%B(+$<$iUFhP}D#eq<~qNC#0wpsKPNXIU~QwKu(<3 z(7?bD2rY~a3=E>gd5sMWjf`Pjg8&k(Q818$SR}b%$sD$hnMpg#qCPsb+pg0#(6C)$TzW4@p(KT0-`F>?w-1hJ9Tow*3g&(P}E-}|1 z(OvkbC8G7c#Tn-rExMc26gFOypZzMMG_AuV`q(SEr{Be_CzK?}I{dvD@%bd1pFzE^ zhVBmqx01Niv-SIa%;A3GxJdEU;kxVFe!R*FFnxCD%dBUUe|>Y=^GUNh>RC+Aw1fht zvXZ(t56@~iw?r;kmb7)vr>fmErmg4j=G8S;ozlwF!FKayrsNNil*}|4+4;rBOQd;X z9O4D7nloDdtDQe9)1P@kGFC72W3Rc=6XWeF_B$(ljQdjWEol_|FVwr!P(eE_GhmyI zx>BL^LCvWzKY0Ybx}NX+H|%i8jF(S7C|_st(%ILi&&15gz__?^g+b#|19@Or$||!+ z7>G59JgJSp7&EnvLx*+UzS3=}%WuZ6NCQW@EFX&)i-_;*&cgd2SQt0`Dzl2%xGUjq z&*j4gd?5Y&jEw(TSb)ih%|IN)S6~q^;4|Q1<4S1rU`z#y8!#I1gCvAO3Rw-9fs}zJ zNI(uG08Cj6r41z8#542C5_2+Bl97^@UV45Ra%2J%CNMG?8Pe8rr0(9-5vn_XC ze=XP}_x0!edn~2l6ZE`HPIheMebd^&_eivW`8E@W`NQ`C`FSsEgO{f#rP)*(b_T0T zU9h;q7Jk6s_a(NFdukmHOZ{gYJAFdTegARuxXUW(PB~kCXkSgL4~xIPJN=mxlV9;{ zr}NX#+j7SVPnFvIugTiHLH}zY)ACOn-Y2(j`F-@a)y-|Mj-(589p9C+Crhg;_Q}#| zthKQ`$FkWD8h6Smzh*Z+?*6dG`S``)M^hg&n@8D)U*r2Km~pkw?qaLb2fcm(Y|&|` literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/onlyContainsAttributeCertsCACert.crt b/SecurityTests/nist-certs/onlyContainsAttributeCertsCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..e8d2b7224a82bb589492df7708e3daa4ffebcdb7 GIT binary patch literal 918 zcmXqLVxDBs#8kC_nTe5!iP7JHmyJ`a&7zLe(bdjAgB z=5m!Qm)W9%`0n44?~Ug9b@q3^eQ3~c-kVBu&N$rfsylKa&}qH)edRqRfdOpMhnj6% ztwhBH z{9UrTtm?>oQNwtToA+*A@4WHGPUgk8Z5+1mpQc~D;%rn<$i&RZz__@^pvpiV7@o4q zED{D{4I)o!<1fZcZR5~kUAM1vTk7(gu`ANR5iiTfBE}-(%l_}1?w+lZQUSjAXR=h~ z8W&9PGvEX1=VxU6&%y#sN^Az=Aie^NfB~NY4;xoPn+IbmP~3pgfFC3w3{uEyzzn32 z;|G}Hfbqk~Ain2#-_D6n0=G(9?=0h)bS`3@E0cNB6jPh_LwkhYE#c*Vt&u3HdG~Mk z3Fq0i_PeehZG3lCR!8x{*4z+g(=D^^GBUiox}cn z=kLGjNOvutpSB=LE35yG{T{9ZyJ~sV92wVsD%o?RdT&hpyLZ>4Z=d_rEBfQpgD=)$ z9!I`Z?>*eStvp_hzd>J{QDZy1^|WTEHGZ8!CRbcfuHG{v&x(;_!=9^W4(c6TI&YN{ ze?=Sn^j}+jPHc4jDHE7*D}N7nUn!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz@J2GpzdH67R%4esdUcID@n}ED|U7SIjC5{+0meh zQ3=^AjI0dIO^o~uKyfanCPqev6KkgbSDeIdq{zE>hyAfGuipv1jJ>IkQ@62qPdxjn zcyg`Nry~+G19!TFbiVh=edTwd>QU9b0KR8mW4ExSq)*)v`SpUV^IPvHk0ZMhmkQ0^ zr5GZ`yM~YJnUcL^PQwpYUHwJuysswq%-x~(nPpDm;oHlb`8Q8zjz~>r2tU2OH2uEo z{2niPIgg`PZ#VeZKcBX{!TRz_k(m$H@Rt7VT+LK8_j}gjhXsql_2b)KlKb-DhHEWMEueV^C!v4~#EaWflnou?CSR zwec5YrnYhDu&&!zx-E72&Da%b;24+XV-aH!QMEX{?v!q6RkZJw1I&{;gq4oxgc$IF z^z$<^{%2tUrXe;1aS&gDMZkd1fQOAMq0NIa6)0}NXuuDW5C$n^HDCr($ngVAYQXqm zWN=bCeZAq7WX0Dg2TumM_>LXFm(-|&K>c`X z_wkfxhWj2dXm+PO3@@>&41e16>sv3+??A8jJ@MJOdz_BOF(pFC3{tT<98S1!8a z-4*uZ`xLL|vsz3E*Z;A9agDRkUZ$+6S65}d$TobpeADtt=6T9H9%=FzeXu)b^P?k1 zY0`|;1n-qIS2uskIBI(?TRY*c^2`5I`faax$whD9v^vV~+Rt|1IVsjMMn8PFz3llR PB5(7+MRVi6IrTRIeKA>E literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/onlyContainsUserCertsCACert.crt b/SecurityTests/nist-certs/onlyContainsUserCertsCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..0d0b95030b17b3cbf7e8e987f766118d0b5ce2ed GIT binary patch literal 913 zcmXqLV(v9)Vk%w0%*4pV#OQ0l%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXAdp0B6b%CfsnnKkeAk_p29v(zx}r zS0LxmuZQ6pp7;6xhMZ3~xyg4~>)GC9=ASR(Zhv!bNGPa&us*OhE%I^TT~T50wf*b7 zE0)Psa>*_BWxRLw?E?{ZzlCO8&dcsP7%RxDfBCcf)>pTxEv9{Hrv%SM1l22XR%PlO z=Vdn&Jb&9va${U;w=dA!&E_d4+4 z-kkc6RntB0zhZWGowdc|k&gOpZ-u*?8XPx!IqhO^ddkGi$iTR`#-Iuul(Nb!5(Z)o zB2Q}LFUCx5hhbhE7HJmF3ZOv#v(Fz55vkkjA#GJPV1=MI?sRRJ(WwW z27JJ%kmYA&{LjJyOhs%4;vl{Pi+};20S_BjLYoI;Dp1^j(SRQ$Aq-N;YQPMnkmCoK z*nsiF$S~oP32o@8*lay7kthG0U+B!-;p To!gfAnq2DneCEZ3S<2D?A#_}c literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/onlySomeReasonsCA1Cert.crt b/SecurityTests/nist-certs/onlySomeReasonsCA1Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..ca247b06b402a65037fa98a127ed5dc40b2ece86 GIT binary patch literal 908 zcmXqLV(u_#Vk%g`%*4pV#28?}%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz=uR@WDKMr)(Ge4w0aP)51MZB{-8$l(S3AFWGO_1W*u@@+=j zg9lE}^*h`j{oM2Z$qMxi?!^=BURAs8c(ca&-KwCd?;2a>=Q*|;U36RgzUcI_4L!$8 zi>ugKerLNk$t~!4x^`K+bMOnLmRzng2Hwsc%RRQbG20#DFIv4(Y4gurjb*zY3M!YH zE}tqcTxD?dIn$&s#y>B!o!=tBpfvgB;fU55>r$g5YP}BZy<#uC=v-T9d8O1`+iupB zQp+xz-%oeOgf@$?1ixH0FXP+w*n;Gvo2Log>Y2{O%*epFxW=H$Kpq&1vdSzH24W2& zPio^Y#!PMF&|zJ-uXJ1L@|&?M(!kLz%f}+dA`*~sk<(GV{W+K4_KL9I;(hN}*b5E# zK>GO^8UM4e022_KfjEe-z#?G4XTZb8mC)wFm%Zg%B*m|srC1(w*atduqy-fV=9w|J`CvJyG|IW8PS*TIG;e;eIsfZ`aDj_cLzA z*#&ps(-WF_H1~r+hckC!-pBmv=zUexccg{l4-uNy|~q`^&7ukE?xLGm*bdQ z)1Okis{hH;-yVPYD)?XG>y_r*^%Yg+8(rTlVQp`iy6Nq=UX^b~CbJ%yJ!4)m@A$#B R&;0X?W(e(^^SN=x6#&E+UH$+7 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/onlySomeReasonsCA2Cert.crt b/SecurityTests/nist-certs/onlySomeReasonsCA2Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..c1cce6e0cecefd5a5b3bff0ae2332efca4c6066c GIT binary patch literal 908 zcmXqLV(u_#Vk%g`%*4pV#29G6%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz=uR@WDKMr)(Ge4|!sn-}l88ZWqL z{46b7cOhD0F0^eQ^)R9AZP!!VAi6$)miv)ukq3_kw0-M07gnWq0YcPD)b z6k}NDDiP1gzAW2#<|+N68IlQ}I_GwpuI6IBbLyL*QHC#9QDv)h_>AQLljfKQ{5(I~ z_tJz}Ia9Wo)QbH~c=65dUf7Lv{*{v})68obS(%s_85kGW7*rX^14B_(nMJ}ttU=^S zZT!WUscjrOtn2obZcAN$Gj>H9IJ#x|Sj1RF5|ZyE~x;{LjJyOh9Y~;vl{Pi+};20S_BjLYoI;Dp1^j(SRQ$Aq-N;YQPMnkmCoK&Vcd5 z$WYk4ahm$w2^{H(zmLA3Ggo6xk(^6U^or?^vTW_0qQ490=pWZS%4j~RW%Uk@y_Wme z@1Iz_lk4{-({h>kuaiD{NXYNF{^6*{*G;vFw?CflR1IGtXl zoM*76P3uxf+@eh{HqNP8wkR-AvN@Rjhxyf|D&Ir|H!bLYU-D=2_B$dBG9nW`e!FCM zzy9^sx3LG^OFnR&&1G`4`SRH>fnDZ#_!%CDr~hxOEv{!?q_Fg_(zK&(&2bOj`(C)i zcVg{^N2?bF{rh@Jc!BtuXK@Gj#jjatD}MNqz;CHsM)x}{YjSoZedTlQ+Z5eas&H3I SUn!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz=uR@WDKN0)^H08=jY{A2IuFd2Bjtz=jRnGI6E2} zG%+e6`-72{fw_s1p8+V&#ni;e$Z+k=;+oeF3`_KTzMG1+%YI(db0a@a^XV2py;_Zs zUDt1D9XNBAQJrV6u=*P&+^uqM_QC;H}fIk&%Cw~+7Kiwh=BtehhbhE7HKxEz8Fu#v-DtvVD5H&bwPO`|eF|kzT(*RBT_i z0Ut;|KO^IR78YOvVlxm2@fBDE4EPLq*tinfJQ!1f;s%Tc{2&QokU~}iW*~(eKfrVb zj2}jZu#&6GE_TdJk$85KqXy}Q18NIMp&{#6;g>CM;{^iE*$Bs7k_-&XpvwEdM z>-8$LbKiC1tu6f=7TdBexxQMf{;K}=S1i;2@hw&oxaYFt?ee*iXP@bxt4vz3`KjLh TgQA;SmP}UARTEL0cJcuL2&!Cc literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/onlySomeReasonsCA4Cert.crt b/SecurityTests/nist-certs/onlySomeReasonsCA4Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..f205db0a3bef4d2628d7c0e2ac48e6ace3610ff1 GIT binary patch literal 908 zcmXqLV(u_#Vk%g`%*4pV#29SA%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz=uR@WDKN0)^H08=jY{A2IuFd2Bjtz=jRnGI6Imc zG%+e6`-72{fw_s1p8+V&#ni;e$S@~}H(1{O-M6jwpcCh@O1#BJZQzTk4L zakK2Ak_Fpm+)xZ+auYI$KeOS|BRi{#pzvE$9&{C~UAJRV<67N)j}EVyxaH^dd5m`R zSlm7eHoI&*JIBWN?{!s0|0U)V>z|1CoAhcIO%yiNid^$p_tJC)uZdgidBcp7?_bte zxbrABV5y5;eQvk=^9c1T6P=p(9|_zW_EK|kn(7PN@-ltT#!GX}Y`tyIZIbr+F!%9- zaLy#}xs`@4_AHAx%&VyQ?n-1tgrL}4*MbhUPnBNd;(sEnIeC}(W3?N850l<9op%?u`D*cM z&ZINJLb>54c}yz}G|4f6Ym}JyY9Kdoaf6k)~{TpvMtw- zp84UG|Hp>({)befo+&1=~ zVp_D=f7xC8hTD(MGpcR>SG4Km^i|v&i@xZ4=6&Zn`+Tk8?ti}~I@=~_oMAkWezX0A z;K$?pZm}ioX3#(7XeQkDpJDH@XI1x&yLo0sepC#(y<7X-gX3{^AAJ7u6);L~n5g>T Tb^Em1=ePHXC>(b====@Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz>h?02QONY2S;4Nd#gX4OvB-h0j}<4L8x$>%sf_SpV1 z-~;LBXJq`(!U9Y}YzE>Wz5%#1xeXW@mt z@3{W$eYV;Agrfcw|Clu$6NH}kN=vOh!+hdCm*bYD8@==Q-+XasY4NffYuZ$<%T7tx zING!RZo|6(zzr5dEY7|la@W+i`G5J%IJPyRV W7HwM=8=rMX)S`MdV~_lw&piOXmtKAV literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/pathLenConstraint0SelfIssuedCACert.crt b/SecurityTests/nist-certs/pathLenConstraint0SelfIssuedCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..6e8f97c2035ca23229aee64f24964c3fb9476954 GIT binary patch literal 919 zcmXqLVxDZ!#8kb2nTe5!iIK&CmyJ`a&7}Vh-&TD93U zBO}AQ{RW5sG5pf|dLvI{@0=sAtH1lQH2Iy9tJZ(E@DZO%>}jEt`!`zeyq%=Iz37UD zSL^Il<=s5zN{;d`&Ymk@e}Fyt)3MoN;nR(`_{1di<}CQT+WqjV+Liu7)eAJOS$5nh z`%+)jx{NU`<5$Bj@$a%}4-f3QWGU11)FS>!4v%TzIh36k8P}!+>U+wEhMehiqF2L zo_+1^g*`bZrmu|VJ6U+rSuxN=cx!!&Tv?bB>z;i^bAtPRJa?TLcl}0O(T}jZa~!o! z1uS@OX7;^{@luP;O(teW2FArT22}>~z<85YW|1%uYY>^Oy~)dF!qL0{#*<2Wlh1K} z?6Lg?j(J%=7BLo)hS$aWd}q#^vRB+Y>ihZd@{+^xgWp+9YhgT`AV=DGuenw+{#z+5}FI!ibij{9Z7PP5( z`Ppnmopb9`UztvvWmt80ll$Rw9Ko@7`0FO-9!unJe!d|qyW_LDpzr6!n?)J_E`PpK zA!LpE_t2_U-sOQ{l}ZxIrqO*WIyzu6X?RGHkD^<#6F`bfh}>a zPdIHG{~wiJy_bJ>)S+qCr%&FS@Nu@h12XfA)3G}Vh-&TD93UP)#=$fzY6lO%X( zUg-`askO%okBA%YzFGQn3wL*$b*7VzL|e~S=ikRmXML8Q|9b20#N4N=LpMe(+u!RQ z(79r2k7)ZLMT5SHnLpSXj2qXzu5i#XNGrBFZtPx?xb>u5BFlX-+pY4i;?AgZUN96& zn-KPqfq$>$-nuntyNraY!BG!e&4yb&W*^C4{%N1Cv2ksrBWxkcu)1}8?VgM%M9*+s`|+6wd#i4&HMzT z*pJQ?>-}@|KI|-9U3GZN0lkpLX5Z>Vv|oMHUpP7c{_|%yWQDJaI?0^Mxc%Nes@NxU z)!esNj}$At-Tpm8|EpxQ$@73SD}L<#b}@wW-LGr=7wl&dYCUi@R`Ar8wbGq;s#%rh zcH}<4y1ykSZo}n2X?Bw|?I(SW339BfikWij=X)znmK$%@&smp#(C7N5-~F1GrhPlP z*fL14Sj1A=J8gg5;~O29zJz>!n04TwrqRJz*?xJyf)wkR`pd!Fk536?eI|cr`jS~) RyH`7{3B3KWZ+gAvLjbcPXQKcB literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/pathLenConstraint0subCACert.crt b/SecurityTests/nist-certs/pathLenConstraint0subCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..b156179e3a730a4f5072fe175202723f9b19566b GIT binary patch literal 922 zcmXqLVxDHu#8kI{nTe5!iILHOmyJ`a&7}Vh-&TD93U zUoo;WFgG#sGXTZ8n3@ZZd-XCX)-l~1}uZ$#kZysSZe(}O*$ETU| z=JH9s`#+)iYHOx^j@w@K9f|_rYq881XfG z+?X2YKJdOP(Q1@F=SoFOWMZ1~6n)P7>CTMYx25IlKiQ{RCUcGhM!KP&&l;hUN z9^UgxC%u7uOh6frC<3nMJ}ttU+Y9_9icz z2}kn+7*8tgO+Lr@vB&loIPzurSj1RFM3T}4YA=}|En>THuYRkT?5V}YaRz+AsF3An zWc<&<0!&V92I3&T0*inFp8*dWS3;WyV=7SGfYE>-Bq0n^$ZEh0q>$qWnCgJ>!^ogF zQtx;rOFESKGs6 zz~l02vft~aRZe>9(X20JWYlvXh%S%)t@miRFn+XRJK=d zy0Iy;IqeFcy^KN9jN{)|Pyciz<;l-iK{6>4Ci|z&o-R-mx8cCGnsNu@-j(-OvDsV^ z3Ds(tm3Ko&DP>#r+mQIahc%yXuKcL@{E%L*9cO4tfajz8yKiiN9LH>abKPrht|Qjb Mt^7-rBup5b0gjtf!vFvP literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/pathLenConstraint1CACert.crt b/SecurityTests/nist-certs/pathLenConstraint1CACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..a424261672868de229f240d691ce44485a41faf3 GIT binary patch literal 913 zcmXqLV(v9)Vk%w0%*4pV#3*CH%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz>h?0u)I(I#gZTb8c!$dAfOX z+OdCaCkq)Bg!ZO7&QUuf%_VTMHIL)bqbQeKsWJ&a%YUbBj|^J9)j-(8Q*YxkBN4zZQyNNzqH6^QuoC3n*{Dm zxcHn=yf8hWcD7&i?9OJT6?51Hy;s|Q51jq?%oSVVt^8f?J7nBFAAMI^JblV`Suxw| z-LWzDXUmVRVz}!zWsTtE*B*M;CT1+i3+(>=FaK^;@=m9pH=m0?e8H&MTQg<G59 zJgJSp7&EnvLx*+UzS3=}%WuZ6NCQW>EFX&)i^%6Eg$e(~Meg;gwHnvS{5j~J{_CIt zA4oqxBjbM-7GM%$GY|*y6<7oe_zZa1xDwht7*m1b28;$mAPHfRLJk8qAjQPUh#W=0 z#0HEaMg}uKtqvs(2d^gU>i;jo`n;~65R6cov0`0F!A8$3v3vc0-g}vv;5u5 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/pathLenConstraint1SelfIssuedCACert.crt b/SecurityTests/nist-certs/pathLenConstraint1SelfIssuedCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..87590c3d2620218727dccd8680c9f1c23c3a486b GIT binary patch literal 919 zcmXqLVxDZ!#8kb2nTe5!iILHOmyJ`a&7}Vh-&TD93U zBO}A^`rk)#*e*ZoTK;)or%vhzvu!okqn34iP2aNT|7MO0>dh6a-b=?6PAENi=CRlL z5_`YP5*IWsc^K~%-NCij{q^!a)23H1vlCXkDRwRLmL>x$PxjHfKitIF4+s1Rt|&jU zbb05E=7S&8-|>EH+Uu$2S;@UPUf_bt=jes)>le(qKcoF##VyHGnI|+1UHX`h)pOiE zv0mdwa=4TI@d@^t1&KfB{HidC%w%9pTX@T!%O-h6n^O!L{>6g68HPI~X3JgqT+ zam$_?VJ=%;oxgCsE-%~m^T_l%fd#B_e>Xh+vek?$+H%P^m#|KOzrGWLswQzw=hmFo zv*gx>f8qTSCwVtC2Qo1;GB7T#F{m<-2gaMMGK++PScAytCxr?B#YOJ*sGU`-8>UE z*O+|!p5$N4Xtu%nt$DxNqomc^>vQbZr*)PJ9=drYgK?tfM3$J!B^_6Gg*UiN`EHkD zHZ_7n|B2hJWf7l`mGA$Y_~)YZY(>dv|49oTpAxrLcRpEaHBEE*;YCNY*1Ygl%L-io zd-tIY{}(cTls)k(ZaPBf~PcdsEKOf6{4l;*hSfu5|j1bI$)t48%iNJ*Jm`c+M?Sp~Ks+#+U6aW|394 zdWkk0{Q$l#W7bmXxcZm z(~p`w=I!}@QY&Id;e&-cC*9forusR1_mm2Su5)4?nI@;cNBwsXIwUoH%8PxI**EVv zq(4ddb;@idt<#G|Eb=}Gco=6NV3K(9tH9M&@=#Iy_Tt43o?qrqD^$8CGcx{XVF9KnHUn`G zUx7uyfX{%3jVqzegE18-Zop{350VfDDP%QZ22#lJ159|p_+ez=oWG>!gVWsJ{H=D| zX4lHg?K#I5q$s|jP$I-zC~9A^ZA|8x7xtkBdwQq*xwN_OdU8UG$dg5;()ZnGi?Cez zdpfI^O?yjE_vY8NGv$6dUE^F^Z}wwmlWjpt`yB08w)cHfV_&W~vQ7AzPqQG)EzP1M zvstI6@JXc3nO(HuwPerZ!p?=EAs*$i#tc;}Hb0iV;m;?#Hez+emT6P=-?4ZiC%Vky z_1~}O7&lM(Ff*^i<;IP~o9CD8+Z(Umkr@#eoHSiov~cZ>%$A)$I0Y`eRG&G$=l0#4 z*DQ;!6>Lg-FxlSHaALmGoA4#l*)D6N=GuOr>DK)^>!kLSO(A!<%F{a3B{T2r+7AGx C#9p-k literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/pathLenConstraint1subCACert.crt b/SecurityTests/nist-certs/pathLenConstraint1subCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..05a2bac1da8277d987f78747196c54d7b74e3766 GIT binary patch literal 922 zcmXqLVxDHu#8kI{nTe4JhzxkyIJMe5+P?ELGIFyr82A}-8*s8QhqAB)%dBr6~iJ5sN zh6>J(26E!Oh6V&TDL7Xk-lI8U&JPpQ3?0#6Afu_7#^V0j+FeR6_O@ zBP#=Q6C*zZP@IdYiII_EpYR*2`~~kn%{sm4?Yl{;i`E{wDE#x1T2(Ns_67}m!?w(d zW|?K@ZR5=hSzQ#==JC#NihOUkMa50%c4~c%>#~@0%{x?$J=Tg%oYwl@#_Fm;e}}j9 zl7p+>hTXgra!0?-5c3& zxol6C*l3*l`nT4NuX--gryMt42wx$kDBb`4+LfE-E)yqxUB1Yv__SD0vI&dr9^)SN zH!f#3iY88A-&>l$wQ(au&4xAKBy+f5&&r*@UH6U7U4{R@JNIs$dBg4WYu|v~!3@jy zw6++gzHQfW7U6Sq|9Fpi|Gf5fFU!Xw#v<}`=CrNHYeSvZHufD?{U&jC&D;r<27JJ%kmYA& z{LjJyOipYD;vl{Pi+};20S_BjLYoI;Dp1^j(SRQ$Aq-N;YQPMnkmCoK>VWaX$l&c@ zbE{VAfnxE8zh3e>{Tc5Bv`_!J-?D|NmiKt#{xj|Z#wk-1EUs$q%z2mWduL5<#>w?p zzigTK-T!QZ{_bsS1WGPuoZa)hx#PEihvgiT>38iP9@tp=cV2*2;w+|l?fOpX1@1yi zT{=Gb+<$+aSu*5ic3b35-;Ux|nU$4mD^nyDa*E#Zg->?R*8917=Al1ZqYQ5^h*Xd} z^0>WY=hYvzH-GJ^eY$MtzsKrVjsBTGk@)?b>E8?c{gUw(?yW7Vb3R7otv2l45*d~r z7 LnYj8~^{Gz)n8sfJ literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/pathLenConstraint6CACert.crt b/SecurityTests/nist-certs/pathLenConstraint6CACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..c254a2376d3db5e7a1fb83ca4251b57b9604c625 GIT binary patch literal 913 zcmXqLV(v9)Vk%w0%*4pV#3*gR%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXz>h?0MlMXBe}S7kc`zGFK~ zW?qulPT;s=pV`>T+dkvE=&JMA4+p=V{$!JTy~*cGIqv-hK94TWILEf~RzS$UEqrEA zIi^ioo?8BE-}=V?S0~ojFWCG->%mS{W|J>pv)$G9M^~2xJ;^}FBh zac%XyIU&ok<9$n-^y^o5zm;!d`*Uc1+`aVtyyR1pnV1-LpyOI?05c10RE!e#kb#8^bu?`d84&u87k-s#F6CzftZ;NInT z!+;N@pP!NOKMM;m39%W7gZK(80tS2rJZxMEZ61uNKyd>`10j%vFi0VX0UMA4DMn3f zz$jv5Fqp9Vy)$E#rtJ=|mWO|Lm&*42bB=^HzY?!7Lyx%?1f-T8D<$Ci`hW4D+VjIJI9({-T7uK48TbusvyM9qcSoxJtjIm~G z3pQlUzb4~e^gUCz=yI^r^;`C9+dFRj>tNsCX?$1l^1GK`C*28{oRXLyy~9=^+IgkN zx8@&e}Vh-&TD93U;OkF|^MY>OHxTq}q!Qhkcvb_iMxFxJq6J8vAuX(F6|G&3*z2Ve? znTM9G_Pxmz$g#P7!~f?8ZM%9F%L$3}9f;<+&cw{fz__^Hpw>Vh7?!fiED{D{4I=CJ zw66Q-v+iNJH_b$#&uX!DG;L4S^9tM0M z{rrrK|5;do>50ui9K=^(5isC0;9=uRX!Br91&SLm8VG?Tgh2{94A_7a6C(q16aiBn zFp3x%9O|PEa_wb2;5I$h^6ryIJ)f7c)qGA>Gh_SrrRlZ7j_^5C)n81V?`6B#Q*$9- zM(?V(x2NS?4Kc_M0wtkPRnKiK;F zfX&yu>lZf9oOMHYWs&!TGvbTI*pJTl+L62RLYMr`y9aJHw&q#SX5M2_pth`VKIiEJ zd7qVnt**W4;xlb`G!-cH5%g% zEzS4IJIDLokR?I*vCFK>sSPY|U)h_B&M|()_U4*wv30s{XUt3EwB^e3*KRCJNjx8Y UB`s^S(!*x&{U`N4byoQR03iNmM*si- literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/pathLenConstraint6subCA1Cert.crt b/SecurityTests/nist-certs/pathLenConstraint6subCA1Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..bd686290efec31105e4734066354faa98f27aa87 GIT binary patch literal 926 zcmXqLVxDEt#MHEanTe4JhzxkyIJMe5+P?ELGIFyr82A}-8*s8QhqAB)%dBr6~iJ5sN zW(v-Z26E!Oh6V&TDL7Xk-lI8U&GOpOS$B#6C$Z_7#^VIXfB}G%+e6 zdyA2kfw_s1p8+V&#ni;e$Z&i5|Bq451<$X{<}2m5@8a&s4!jh6^V=?y~Y*Qa)8{F-uYU&I0=oi}KFp1{ZVx z-*kU884R*9%SN#V)*{-pItv$iTR`-k{b%9vGIg$}AEFVhtke_q4A2 z=dGO^ z8UM4e0MiqjfjEe-z#?G4XTZb8mC)wFm`T-c`yQEpyRk4_ zs#Q?<{F=3qdPchU)<-J7Sa><>S>*Nos}?*^Na19(tX~Sn@2oD}Tm8U4T*Z6xg=)_&Odl^gT{hUi&FPmwXM2qDk3Dsc7i6cMI`BKmZ2gNx zosCJi-o;k_ofC8H>DM=YZYjA}r(Zvj`d6!VN!8p5JTafWEm}Vh-&TD93U!k^U#Usj~<7SGHo+!=f^?EFdN!{P~#?Cv$5NHe%G z-@_*_O$pX-EyoYL03@@?JiRr*toR@H01X!O2WQa_bvUGv=s z7Jt_GNlRRBFjJXwmZ4>dN_4!C;sKVQIYxIb`A=SwZP3}#$(GLdZ%KPypKH&8=ce49 zSA88hRrgE@Z8-I&0=%kKs__GS54#8^Z;TW@>+7EHc5lSyL>chx*$@hH)913r*` zen!UsEG)qE#AYB4;w!KS81NbJuyG}{c`&8|#SIt@gg_F)AcY(TY(R>Mkp(%5fGH0c zMT`s+(mYvP(>SJYYP@>X|8V!w;y)9&Z8SW+e!kMFxqli@)xB%B_u7(Gb}{bGDk;~! z-YgYf+T1$F-{noZDq>=*ymczNd`^}-eN&%E7l;=$B+!Z|c| zk(-!H+0m>CT2F4X%>P!;EO4y-Cg)Bi!_PlAKN6SiSbaa2^ S=lH~VHWE3L<)=u89|HhTAzvH- literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/pathLenConstraint6subsubCA00Cert.crt b/SecurityTests/nist-certs/pathLenConstraint6subsubCA00Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..e2fd7ae3cd6556128bde8234d193165328f07dd7 GIT binary patch literal 934 zcmXqLVqRp>#MHHbnTe5!iILHOmyJ`a&7anD z^Z(mW`)-=_vkwyz9)7QjRjt^+RLCXq$ls}#zJDm+S8KU$N!Z%M+v->CV)MFYaz`R3 z=eA`_@{`Zqxkl{&WZiiqoch=7oOrfZedY)5do8(j#t}c`d7ntcuoQ_eQi;n{ReF7L z$@WeA|HPcIIJQ%~JLlAkMM8l-iO-INPc~hW&cw{fz__^Hpw>Vh7@o4qED{D{4I<~u z%9@KOs2uNIoSRB->*cfc0Ja-@4tY};%;F{lK~${ zKR+Yme-;*Cx?(dB2k{kH1Pu5Lc-XiS+B_Ijf#L>?20|bSVUR)&12!PV#K?dgMZgpY zj3Pz`r!MQRG`&KjaIu#&t}fP+z9`@o#sA;vyzix7F%et0IyzNuvR`t;S)sUZ(^qG& z^5q;(-{V>FzvwW>bjKvJ2uH%AXaLmI)9XW|X?w?^eA}M$RslzvJn@rCxg5L|p`&i^2_4jt4)feh~S# SOX}jI0EX#P4BCrpmjM9HXJj(~ literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/pathLenConstraint6subsubCA11Cert.crt b/SecurityTests/nist-certs/pathLenConstraint6subsubCA11Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..44c0162e945b26d1fbb1158b27d624f228c5d7f7 GIT binary patch literal 934 zcmXqLVqRp>#MHHbnTe5!iILHOmyJ`a&72QsKfe5ARf*YO z71bv@RBa!wyMr2%Zzut%nEZno-)bg+8T}Z`8>URrb$WS)Lb|Peb48%cv1r`AVJ_8;$u7oxZ##ErV0i%HsNJ1E-ki&otNMWWxU=%Sj z__sa3vR(VDv&EBF{sNkR-Mc0VJ!5>7AiMapyV=j{j#+a5cyBG9v(?>s=Jsg~ho>an zAJ(7V&GgNGzA5WQ4 z&*?Q~&U!W3Shnc*%^QyU{5vE6sato}x@XT89^SA;$Rlim{ulG9@=E(T9_}{x_)vXc QbnesCKdW_1TVC@508toayZ`_I literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/pathLenConstraint6subsubCA41Cert.crt b/SecurityTests/nist-certs/pathLenConstraint6subsubCA41Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..284f4a9e4830501c6734e7c24756b38343e6a54c GIT binary patch literal 934 zcmXqLVqRp>#MHHbnTe5!iILHOmyJ`a&7m1eILmxuZ`o-t3`hQ17db_s7Zq|SEuPHMzGcqtPt~aPPkOzjRtTKy)fmnlx zXX|b6--5|EXEJGQ;jWq|EFL9V4o(HKd@N!tA}&$O*w26aeB!v<`;>)WqYv6Q?Fl#F z1L@~yWc<&<0!&wI2I3&T0*inFp8*dWS3;WyV=7SGfYCq*Bq0n^$YH<+q%cz;Fp3x% zw%f0sXzaY~=b0Xb&$GU!Zd1B1>k@po{#e(<6%)75O+N2nc4cd+WUsiwCFOvJ*LVMs zJGxC$&O}6s|3T;MW1n9Kuy8OcPYslNq_ak-|9;?s^>)7BYYQC;pB{IZTe(jotMhU< zqn4(N@k+K9{`E(v+E~ncSmgU!G{(21`Mt9z!p!>cnM(*y!ffB4_!! N#xG#~$!(Ui7XUL7RVV-e literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/pathLenConstraint6subsubsubCA11XCert.crt b/SecurityTests/nist-certs/pathLenConstraint6subsubsubCA11XCert.crt new file mode 100644 index 0000000000000000000000000000000000000000..9766cf01596982582ec6f65d0047d97e1bfead66 GIT binary patch literal 939 zcmXqLVqR|0#MHllnTe5!iILHOmyJ`a&7&TDL7Xk-lI8bpz3uaOBoQtW6k&)qCugHRnZvJ&;rbwnVEUEecptR+G(ny(&jor`Te4%_U-(xE2c3Et0`{!KGm3E*1h=s z>-q1V-nK&Y-4c2BNi2)Eh*UfM%30t%FIG+K+4}>bJ#5B|`#k=H)%URc^3Thz)XoVg zxa_zh{rtsPsB%{|f0QPXYzR;oz#(R%4u z27Dm>{EUqMSy+JSi_JhB#8+SuFyJ%bVdF|@^I%K`iW@K*@Pj0TK?+$7n1K{>`~Z_7 zFn$;re7n~^*?M!8l~K)0iFTFM6|bB>-^*LgxB2MZqap1tBr5Y}CmPMV@$F#l<)hyn zc@<~r1f4K1vGshT-|l{kYgOUaqzc8FHHwBW{+|DQ{P)NCRg?C)Fg(g%yz<4|x-+_- z9Di5nZ00YpKc%%Qcj~(k*L!-GuJ-)8w4yX(v6p+->IL)VE*@DUF1|~a`y)TUd&#t@ z>>De8HLrI%b}rWWlZfUE=PQ})g$XgeO*%5x_L|QoR$qQ-IOj88I^Xjtf@j}ytyO%X zRH0rl{liHI?fCtoH$t+_IP;|HZFwY literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/pathLenConstraint6subsubsubCA41XCert.crt b/SecurityTests/nist-certs/pathLenConstraint6subsubsubCA41XCert.crt new file mode 100644 index 0000000000000000000000000000000000000000..e14753174b412891f3217bb38d462dded15b81ac GIT binary patch literal 939 zcmXqLVqR|0#MHllnTe5!iILHOmyJ`a&7&TDL7Xk-lI8bpz3uaOBoQtW6k&)q*u=xsI8(&+kE`?IY(m)A$?(CR5HUUCQ+DiPR z0%z{N5V~g1zjy`4qea{Pb%j`H_EubvIq_KKbVDlVuC9=O6}s2fY}w43D!^|b?!!_n zDC%e?%3-Aca-+6sOVI-%XQ(Y4)kU%>SRDgvT= z>z^O-*?i;FyBPPX+f%nk%&SbSui4_Co+4fUYnjpXl^HD8UH|d!d{^DWd-SA(^gh;v zo0Sh;#T|sIdA_>|rW7~-EIasMNAZoHRxKCK9Q|2+Y2!-XBEI&kYKm=ac|C!xh#Q9%!~|-i)#$34CH}fDyz&QVIbBZ z;u5ut{rtDjCyu+lPg(di`k;N&o^Wt#kmX|$V-Z>ScF||kkfrnYBtLV{3RcPS;wjQG z-~;LBXJq`(!U9ZRYzE>Wz5aWVqM#gEykpVd0$}9aUL;nOZT9_YXD6&#ZZyzcIf#Z?}fizhlPsi{CiyGw)Mf zdv@c*Mt&i2=K5czKMXlf3a{Iex!1OhbGu%WN`%_>+rG>5xi7BS%b_4=Jr}@@v8aU)(NT~R!LoJKYFOjcw@tY>934B{x0=%_gTiD zd5?41%9Ql|Ueose_;9Ss{qbIH(H!q<@6x4%dH(jc>FH(sn#KJuY}$jx!6`3T=4pJK R_QA7b`@{U7n`SPS1OWRgSCjw% literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/pre2000CRLnextUpdateCACert.crt b/SecurityTests/nist-certs/pre2000CRLnextUpdateCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..30aff16129db1b6ad06f689ffdb132782a2f0cf6 GIT binary patch literal 914 zcmXqLV(v3&Vk%p}%*4pV#K>>J%f_kI=F#?@mywa1mBGN(klTQhjX9KsO_(V(*iha; z7R2Ea77Ix&E>Un!Eh@=O%S=uzNi9||GB7kW6g3bADPR`n2`MTCs&LFp&d4t^kQ3)M zG%zp(LJMO91A{1WUSk78BV!oXAc#b3lnfLg)<_lrRv-49l~zlN=zjCfOC>^9KjgaC_I*p#J_}nMi?Ip(vba4y zsn0WTL7b<*#Eo}G{>GD#zjRT={!4kcx#l)JO?vsVaZzpR z`_ePX1$RW}mgV>_iBK)bE}BPL~=M`Si@s25&BZ zG);MT;@Hg8XR{B_>df(8$eH@^@m#F~-U^dGRHlc%VJj(`*ksRn-EF;Ed*`gY11!_s z89z^RJ9+Ip|Es;{{+G!#KGK=Fe`cWc{DlJH%m2mZoz(2OtTImu7OCT`*U6~H}dE#nI2L)pmyJ`a&7ba~tdT5AEiBC}N_DL$$jMC3ED6X5Qk4b@ z&W;96j7rG9VPs`sZerwT0E%-lH8CAyDImu1;F9R+PwQeWiYIo?501Pa`r<~<<-^>k zuD;%^%l9eVxoJrb%kru9#b=l3sc!kh_*9PPC%u7dQ49GH9IND|TSj1RFcD}j4D@bX_j(u6*7YSWe zSGbnWVrsw#($CMx_@9LZn2^{E#6f%o76Ai310FW6gf~Vl>Ot~zb8!M&FM8)eOJHB)S2vF z`seJ7S2vDC{z?A2%Yh@eb8QGeL&jbzzs)i%Zct@Zr7bJ4UV_U|>;e)oLV^WESEM{evqy{$C?QXGetsGva8rw^>Rs2=7%SjMdR~+zqH?7wM>#J3jn6`Y*PRL literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/requireExplicitPolicy0subCACert.crt b/SecurityTests/nist-certs/requireExplicitPolicy0subCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..b7a1518eb86a3f7b9cafebdf5ba73a4d16541b68 GIT binary patch literal 930 zcmXqLVxDKv#MHKcnTe5!iILHOmyJ`a&7npu?UT2YXbnVeY? zkPoCP4HTRm4dldm4GjzofzZO(z`!6%oY&aE(8w6ZH3%iqPE`YCh@CPx>?|%#0$SU| zsD$i0Mpg#qCPsb+pg0#(6C)$THK**CzP9II{mGQy>h{BfslWLGV_8|>1CBEd?Iz#P zKe{Nx?!NNzhGj>ke8dF>L(7Z~tcc(=YdW}Vmh0zrlcq)PVl{qi7@qhn%HUFdAG>Lz zK~c$sPfxd1wAHhxg$Uk!VquW4XvHtM`~J@DG8{7h&c3?1Q^WU!{Igg2$D8GL{+-#a z7jf%#@?87#myh|c`f+>iJP(zK#;8RLtL%k8rI`O*tG7X1?GbyT`4N|^ts)I!k5;Kx zOje5D=u~d?`Qt5dU%vjOs<-}LpRKQ{d%^Df10R-+3Y+?E9;h&J^E+!M8dfH^`8=Gn zv9R@qy5Zu7kCi68-L2o-t<<I23P zBg0nDzCTJo3lIKY{_>sR?q%_*yLMcep8hrAjK|x?rLXex#in~$w(a+H+x6wJ29wu{ zOIOk-&X<_{tE=SWE9H$Iztz8YU-d6jpUUibFSjxJEDyszwyXWy6f)-iuzAEF@pRXV zg&NEEHmbdQx-#+pm5ga0`v3f%GPCsOU8Vf_tL_*lsm=LsBEI)&;i2@!uhjpW{_*Gb-g8gO8N@zeNov^CsN8p}NTSdtQIx>Q22Cw_nx# ToUYIw{BrS*b5maT%rF7~kLznx literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/requireExplicitPolicy0subsubCACert.crt b/SecurityTests/nist-certs/requireExplicitPolicy0subsubCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..db57e9b337f313eda09e3d954c93feca961de871 GIT binary patch literal 936 zcmXqLVqRj<#MHBZnTe5!iILHOmyJ`a&7lM%Cb9Y)F zMEx?%m~HE8RKoYxD7dw8#g)Lb}8l{jMQ%%#Z$k zvo&oK|B@YLvWX@E3GxYFzr8wEmi~hG0l$~JVo;j=8Nz4n`7@BGQj7k6p!H=h)l&*j2&Vy5ezBZawp_OS^aXpt#By2f#7b-a|5 zf@XeLYglZEmtU>IrZ<1OTTB0X{+shQhu>YoTk5dS>M3{U$E?3;JEMsIL(bEjJv-_x zJ8w6+aZb$sdc8`Rd-LXS8-KDkTII;``DteqI4Q{Tv52vVyuLBLs=i9uRPxFB=_=|;z=~ z302t|-Hkt^)?F$dFY=c63P;AAbz7c0?e_o1zxw9&i|d~CR`taAFH>vrKDhS6h6S9C zViO|QJ04K(U*vP3!s)KbTXWlp{Lk{`vJ)2mOgc4DqU-xx=~X=W&+cWsl74$_qV(b` QJ`oqTsT`N+DNzjs0C107IRF3v literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/requireExplicitPolicy0subsubsubCACert.crt b/SecurityTests/nist-certs/requireExplicitPolicy0subsubsubCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..4952094eef3e7f9ccccd5ee22c85c7695880aa8e GIT binary patch literal 942 zcmXqLVqRs?#58FEGZP~d6CB(+$<$iUFhP{TkCq<~piz9_Y@G_xqxwW1&=GdZ&) zARkCo8YmQ(CIOMNqk)__uc3i~ArM*^8yFZwiSrs87#bPFxCYTA+N^D$39(rTugwt4 zn;4aleagtnz}&>h&tTBR$i>ve$jI>UzQ~@t7iLI1YBB|hXu4jn6I=Jccf+?!A8(5v zecEBOVl)4HBc6Zd?(7BYPg<{jVpd;qv$S-@zWFy@noj@bV*jcV?QtdZgz?+F-Akrd z_-8ur4baZ4(CQa7`}yDe2@`h ztKi?Ur?x8cZc}8}w(tiUS(CF^PiH1YFLv!&Ch~{nLG}zO#g?w$+OJDKoN0QWeMooe z;fGhAg#Vu}_QJhnasS)GvsFgt%Jl_8H|(DDWU}3Z#md`u3R!1*#%RXmf(+bq{kC~)XUIUcWA?9zGboL=@W z13r*`en!UsEG)nz#%3T6;w!KS81NbJuyG}{c`&8|#SIt@_(2lFAcd?3%s>h`et;7*$#uK%y8pDK3T(*9QAw?Ish$2{4`W{cC_d-xeS3Fg?W3Y}!{I=KcoFr|GNh58YooX^GIaqat#_9y8|O54yZr z?B~XIGo}m47DDT*65P(-T-)>7%HT@)Uh$;=JY4sgDwF^0+V*VYl-a3475c|Fo_3au SwE8p2Y1f`dk7nM9I|Kk^i(_;E literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/requireExplicitPolicy10CACert.crt b/SecurityTests/nist-certs/requireExplicitPolicy10CACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..3a54e7f2b82d31a19135360321e675935ff682f4 GIT binary patch literal 934 zcmXqLVqRp>#MHHbnTe5!iBZddmyJ`a&7tn3tdS~8EiBC}N_DL$$jMC3ED6X5Qk8}V z3eJuOO^iy&-eF{AU~XdMX8?+GF*PwVGJL+}+gkar*T-$?qtbu!iO3bLjjrlfD0K4$Vr>-+x=`-{qU4&9igeW_%2I>(r^^usZDd=9$e3 zoW5I?uYIiw`EW3JUZKd-S<1iSHYsoYwKn{`wB^i6Q&(t&I~+1R<0fq$rCI;ZX4`MB zhll(1TXP5f2QW2jn9U;N7{Z%Z}%+Nb&DbGLdUQD zz15#TZ1Q=LF*`>*cvHh-E|q;>3O~;3xS6t-X~*i@`{m^g)|8pav1oqEnbYF^GFEe5 z?jC0E_G8PqPi6#3XRziU-^1E^=1oh}bFmdC+b>=f>M*)@m5G^=fpKwTpFv}{fjlrc zWtCYZ48$5lp47%)jG5ZTp~JdvU+K2g33E+J&;uuHJL|v98>FyM>A;t6gsC#inj@ zJbcc&=YMIiLgYiXhDSCh+rJw>4mFXK{#x?=i%0z5$kSq)GhgjWyP5vk?d|NX4zrG4 ze>mm(u5%HgMqK5N(c(f3=$Sp@2&;b^U3Em0OP&OH`ySdttfc@Uag8-!{GOSsk;3-}l{fH!-v9 ie}x7s>eud>p|&IRi=RhrL%l=ln))+OXLf!1G8X`5YHU9M literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/requireExplicitPolicy10subCACert.crt b/SecurityTests/nist-certs/requireExplicitPolicy10subCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..650a53f4c2e4d892d736fce3c4ca82ff0f87fd55 GIT binary patch literal 932 zcmXqLVqRd-#MH5XnTe5!iILHOmyJ`a&7A-4f18*?ZNn=n&ou%Wzx zEQrG;EEbYlT%zEdT2zvmmYJMbl3J`_WMF7$sBEAJQot-MRg_v-npu?UT2YXbnVeY? zkPoCP4Gk2W9S!8fc?}H=41v(X*ucObN}Si&z|hDT#x)2d(NZ-76^Ny>xGXI$O#<56 z#HfVqKSovt<|amd2B0_>QxhX2!_|0)u4#2f=kECT#C{P~`l?y9N&2lCx8nN5MZ(*j zSsmyJ66~vQmP?(kl^k_CMP$;hFUAwHVC!VB3Ag$EpX?IZY`ob$UMK9q z?a=m~`92xBOL}UHb}TZ{Nr(Zep%+lZp(_~_1WMEueV^C!v4-8LPWflnou?7*z z&ps>{jBiQ(4#`)~|;A9}n$0Eiek|(h&QH4L_wjP_{G&S?}Co43=*bMkU z`uQ0d|Ff_F6Be6+IEb&nB4EI0z{AFs(B{FI3KTbBG~fqG2!j-|8ZZMX3?<@H(eM3}pli!ayU-tE~X|%MuzRqif4YLG;X1k{L9e?YY`Tg0kgD3mF_PqYMHGD6} zqS;O-U;h_R|M);U+P3PlZqeB<545-!++VhVY1Tisz3+7vXg_`xcp{3G`PVrMlLuTM z7!L0gTd8HbySMP(t#8}*B*strw2?*c;RLmv9$Xhf_e%zb=8{m&Z(&Z|!O zsyo%<%Re-ydFRxwf9SFBV8qw;%*$MTe$LtxYP>|B%bjt?{{=@&)>=(nng7N!Z$nM* zy6J-RU9P3&&)@T9Yk0lEsj~i$`8M1q;-`0AGPGYCv5|?Hk%4h>jX{-xJTORQm02VV z#2Q5MB$g$r@MqlCV-uXFX1@Mpg=QEVI5Eibv52vVLrpA^z$<^{%2tUCNDMvaS&gDMZkd1fQOAMq0NIa6)0}NXuuDW5C$n^HDCr($ngVA zg~0e>WH=Whe@3vSY4SovC^c2lZtMeF(%GcWEvbSGJyVkg5lJmRQwQ<)!p5Uku zJ&|+tn9Ql*9Oh|GZ=)72c^{T_WI}!GTsH3uQDVMJo^08#dj9pbA1?xgwuU)x397YP VrFuWx$$4X8c9gR2$y1Huh5)AJZ|DF3 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/requireExplicitPolicy10subsubsubCACert.crt b/SecurityTests/nist-certs/requireExplicitPolicy10subsubsubCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..a7c216c1640d0889a8c3ce4a6c733ce3447a472b GIT binary patch literal 944 zcmXqLVqRm=#583AGZP~d6CB(+$<$iUFhP}4viq<~pip(wSmG_xqxwW1&=GdZ&) zARkCo8X71RmnH#`v!j8WIIp3BfguoD7#kQEM2Yhn8yFfH!?*@9BwDRwparp78NbyK z+nX4bkp0TY%D~*j$j@NV#K^_e#K_37jpw~gYN8pRrft({^0y~#zmEo zmksVq<1#!Z|IaFxOZsJ|;}CpKG5N*c*s#oF4iD#EQ@s51-5IkhYQeU(p0%rt8aQLJ zp0DUm<(E%-y07rql85utX028Jx9Q6AH}AK^ zOse?AS$U@|ev~u&;Dl}3Q<~SSDL-9V`uOzBgd+zwRVx1e!c^=0Rn~A*Ecd~)Gb_Z7 zR(JjSq&|0X=OoJsqWwN0r?x*clJ#8X{QAPrmZ$4j-U>1?GcqtPt}&=GkOzjUtTKy) zfmnk`M1Vivr+-B%OD>e#FPNrNzE$OgA~;FN^0A1qh)nA#{3E);`rOSUKMr4r&n&EY z!QgGc2hz{a$oQXy1(?X#48%cv1r`AVJ_8;$u7oxZ##ErV0iyvwNJ1E-kkx=0NFm1$ zFf9V(hmk?EJ~jWvboa^16T(sV zUUe-0`Qg%5?}n^`C;CZc{CC?Y%@9;tb3(Uaiit={wYy`&!j2-|-nWq}Z68(l{JOoa zFl(*To5t6MeeFlq7Vn-h=~VQs3r#0k?3SLtdQ)#fgRa01Mw8#_?^GO@a%%~GE)ZH@ z)-kJbPU^L)tE;-+?)mb=W1XJHOK3@3GCp%N1Fcb}J5~C$Cri6;khAGBMYA+w)IbD(hZP{_=X! W6%X}8O$}QNIhKa7?NQX#dkO$Rr*NGB literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/requireExplicitPolicy2CACert.crt b/SecurityTests/nist-certs/requireExplicitPolicy2CACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..f7ca7ae7e2a271af99274c581a8fd476b092d2bf GIT binary patch literal 933 zcmXqLVqR#_#MHTfnTe5!iBaExmyJ`a&7ba~tdT5AEiBC}N_DL$$jMC3ED6X5Qk6yu z&W;96j7rG9VPs`sZerwT0E%-lH8C!`B0M z7G-aIvG*4D&D)pqH_W!?-6i$UMPu`+8j*t%=l-gCo)O7=5?OSGNpSX}105GPy-9he zaeUX7cHJ{3hnF1t|Kr4~b&vQ|n>%A?{z-l=GW8*shN#wOCT2zk#>I_&294bY^1#rP zRc4Ve5Ni;5QX79UW@;OU4(qyorQ1@M-;7<6299=FJ{B<+5wn#yf3LF8U+~?>`ey6g zS)z+|R~|Ru1L@~yWc<&<0!&D32I3&T0*inFp8*dWS3;WyV=7SGfYE>-Bq0n^$ZEh0 zq#yz+P=N+UCgdmsCO}}6F*3+q_-oLenWyIZ$wDJUyX&2FUkv{uj;i@>2U2frtJb>t zL0mC?Yw^)Tjy8*~T3ujS-_UXXfQ!5P&8b1mPb(f h8$E}7Uh1gJW*t*kyFIh>t#xnP6)x5%=Aut80{|eMXubdd literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/requireExplicitPolicy2SelfIssuedCACert.crt b/SecurityTests/nist-certs/requireExplicitPolicy2SelfIssuedCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..9d1626909055a69fe657c6b1fa487487c954d4f2 GIT binary patch literal 927 zcmXqLVxDc##MHcinTe5!iILHOmyJ`a&7npu?UT2YXbnVeY? zkPoCPjTD?64dldm4GjzofzZO(z`!6%oY&aE(8w6ZrHP$Qj7rE}V`ODuZerwTFlb`r zVrpV!WOyPop-*}75&sow6-(0+_pMyPw>aNcZ2oljTerBYzC?YV`p2R{;q9^?pH)`x zO^Yol?>+xOVZXqNo=fkiZi%&$DOUBH+qce9(>Lp*%hV5P?ZWB_7xqs){J&`Cy+;a+ z0-Mc?PItKae0fzE?ssH~qvEY^$M4*;SpI&x=&nV1Oj{o7_(c3k~={`uQ0d|Ff_F(-fP5 zIEb&nB4EI0z{AFs(B{FI3KTbBG~fqG2!j-|8ZZMX zchBGE$iMl$Z3)lW=(>e#)}HlgVy=Db*~9HkDv!pU9KD_9~09L-q!yZU0aE-P5$(7CQa-t}itKGyMOEuZlkYHoZCI z#@}>l?#r$Vd8K|Ve7pFgYMR5Tl`&2mO;q11iJTX`cPXCx!tw7S&VdHZ>$s&NjxEk{ zpY`*gL+deX;WoXL^A$V`^U;@t2(ay7iD%)9aJx zqb8oK;|yCc@4^|K%okm469dh+M2RX)+WhhEkDLV=r{n{Vd=HRwd~>(xQ|TI4?vwHW Dyjfrb literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/requireExplicitPolicy2SelfIssuedsubCACert.crt b/SecurityTests/nist-certs/requireExplicitPolicy2SelfIssuedsubCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..b53bec1560d18fef7ff01047f704ef91cbcefb98 GIT binary patch literal 933 zcmXqLVqR#_#MHTfnTe4JhzxkyIJMe5+P?ELGIFyr7=#*f8*s8QhqAB%)&B7sfDGPMX9b81v#0?nI!@F zK&sM6p|~{3+0j5woY&C6zz_&6j13G7qQrTP4GfKpVO&~S+r+4Z>_J9W2IeM4eg=ak zMlPl%Mn;B1HJ5^B1pk%iHJjeF=G@QNY4^_UIl5l&XyMdpvWh7t%luCpb#~M=JbF6u z)+OTyWh+c&zh>@Pv@L46_NiNuM>6un?DvPsWZf2Hi?`q{pVDPrt=G@Gi7}#Kc6ceX zu<%VPQ;Mw<`VwnaY^#6dWYUF*JpmtWF0oHrvCU$|p1fDrE7IEe z53B6t{U7(OiL253eBVx8CT2zk#>F)TRR;3FSd>*}kuVTz5K$=q=VQ?OXmg-!|Ay}} z^|H+~_}sziK$ee1j77wgD?KsHz4ub&^z}+<27%=PtL`i^-~;LBXJq`(!U9ZLYzE>W zz5+%E z&1UxUY*W_t;H|HU_WtP2zVTBl#`WSO=be5Rd%A++uT8zIbTc&L-x(X<)T7INXKZ-t z*%BxsHak?`^qu-2vn>0^Prth+%BAS_O*rdrEq!KXTdob;mbt;-8aX!n-&ZKQuW0U> z*#7O;*c95iSsI%DzVA-oQ8G#YbFguw%kHJF%>OL?+`Rh3QXRfY&d7CGXzN+QCB87> z$f9MMG1oF27=G4$Z`tV))pN4WB0e6p?0{~TZ BUHt$6 literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/requireExplicitPolicy2subCACert.crt b/SecurityTests/nist-certs/requireExplicitPolicy2subCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..36fc0d8df48dfedacc6a41638c29145a468b87fa GIT binary patch literal 930 zcmXqLVxDKv#MHKcnTe5!iILfWmyJ`a&7npu?UT2YXbnVeY? zkPoCPjTD?64dldm4GjzofzZO(z`!6%oY&aE(8w6ZH3%iqPE`YCh@CPx>?|%#0$SU| zsD$i0Mpg#qCPsb+pg0#(6C)$TCjB*H_g{u^v+Ky});zzU!ZexpYR05Jfeii;lVr?h z%vrXCBkjK;89^YS+my57_AJ>WQ+^? z#1MS(yz4BDRMkCK6)Pl_93Hs@oL(9eC%WyhYg!aj@$}0Yo4a18a+DRHiTJ1!?0@-X zR>^&pA2SwK%#6Ep^gtj#8(-_b?+0}Fza6xHVyzh5JuBY(b=to(TKk;!y!QDEG_QHM z=ut`RvKUjJR|=08cNA}ZC!Bfr&-2ZXZb%FF=`yIq@4Z&MkmbeEx@Cv`W1qXHD(hWp zei!o5*XOR?kFETrIv@W=x|py0Qhz~kYRut=SSDsh2FArT22}>~z~GcsW|1%uYY=(A z`qqty4Tj5|#oiq$<6ZwI_fx_`a3YZ9V-aH!Q7HfCW6=9(bD(VhhVL@Rab*`*q7WD?Q*_{vRHJ6^yH%PiT!luxY`Xl}an5CT;pM zH!|_4yi0w>HFqDz|HW?WA8&iew0EuK#GS6IYo8r2+xPt6dDGW?!PgX~aJ%Sxdd{rQ zJiB=Nmd`tym76_%=SAK)*tm0fiS>fzKlg8+8&rCvrcPqw#6>3rB|qg>S9pJPf1_T! zX2uJh%&F-X3mn(RR{!f!)?UU~<5@5KY}%TPnfmMa4L5Cm&}JAE|4%4AWuBTtZLrK# z-kOO;$5ZpomT2`adphOa->pYCF!U&$`Ss(~;@xREf{f8-av}ba~tdT5AEiBC}N_DL$$jMC3ED6X5Qk5nO z&W;96j7rG9VPs`sZerwT0E%-lH8CCuI%W(EOkS(`5$k|sY|wXs4(2r z@vvWG;(LDm|ECJ92M*?itgCTp75w&a)|zXIHX+A5SM1vT^i#<-ukRwPWgdR~|Go-M zF?A5#Z_pyx*PY}W&5@*T%@}u;#o^WZXvyF6%~x*7`@@iM=&SOAm0vvT&rJ@qo>(4h z*0E&X!f4eOf5J+>96BQ>bs%NM&N3zSoVt~>58tr6cHjuF+bY8}QBKW&>Ymr5jV~*G zw`O~L=ZaG>_l?*)Z1X0h?5u7M@TpQtocwwL$2XP*VN0J~e-ZQkG|RM|uI`(HO_$Bv z706J~buM^6`GhNi4C zi-dt#gUFNG_=_=9+coT1}S7UU75~ zebbejOMEgobdIy#HCDf`+E*lyzW?~6BNq1m`orR%1g|=<^xPfxHBQU5EyMplYA`Im zwZy3G%2V4L-Up6)?!L0}@bdx{ldqn0^CJh3>WkLFoI|s=#_Tq0zO`JkLEs|Gr@Pw% z7fd`B;JR#ek!rv?);^Z|h8al(Yv#|sc)WP#Qsabsj2j4zkn}sui5lsi7^c fUNAvF=fUBOj!SAynnpu?UT2YXbnVeY? zkPoCPO%$9R4dldm4GjzofzZO(z`!6%oY&aE(8w6ZH3%iqPE`YCh@CPx>?|%#0$SU| zsD$i0Mpg#qCPsb+pg0#(6C)$TCL4#Dft}i4?q6AYr}cnq&BOIR*P3j)E^hh7v-8S@ z(4|uYwq2cI88GFxb+F@!7P*XmwfDj7T}d-n8TbSlhA(>jsq>H;-=yE(dO_XyCmp@~ zGGTx1tGvv_7QbVBeA6Y*#+9Dlr~C8y^TM*fyHZP4HthE^S=adcbF%MqsU@F;zjZ4t z+_*nZBPe5PmFc3H_3C@e?u&~EF;BQ+$n5*pMN@EPF^8U!e}QGr&-n5u>D%vKOqW?@ zwlV(uu365BewB~qG^@@3eiv0iDDYqe^X(6TKQNL}ZYYI=>UP@f@9P3>q!H4`%<1LNWvgDL}gU~tMRvq%_-HHe(O zc<0O&!(?`yShJ1%z4J=a^>W&9L!-GEmHo) zFZEd0WcSUPR$kXrTo*NM0$1n61HqAEHf!@6FBYkqIWg?*JZGo>$4B~JrX{CY3VZR= zb(h2^$A4T>^46j}eTBT&W*zgQiMzH08)g~zY-@{CUcF`^7o%wWAGS~1irPFQ4qjfq z_nDr`;~#S00=pzWehpo5d%0Tes~4Zcd=Ieya7bRY_gal-Zs*%fP@zT`#9 QoUpnw@8yf#d;2Z`02ggz6#xJL literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/requireExplicitPolicy4subsubCACert.crt b/SecurityTests/nist-certs/requireExplicitPolicy4subsubCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..1a37158581b428fd827767b79c3a13775d87c636 GIT binary patch literal 936 zcmXqLVqRj<#MHBZnTe5!iILHOmyJ`a&7IXYI*kIYZQecZOT{{fR4H%_s^yGs`(UJ*(;JGo=^YQ;ru^Y~1JfcUk4fjdQego0Kv{ zrX*b2uCY+NW@8$&)t_0SW)Xj!6d$r({yk%R9^W5zCT2zk#>F)TRR;3F5S3MCkuVTz z5UG97H${B+x8>8H-B9vy_E@v|-L776Qjq0i5n~Zq`Rdu_c^f#VuYdkePEWvSp+LG% zn*kq4KR+Yme-;*C;$kxp2k{kH1Pu5Lc-XiS+B_Ijf#L>?2K*oiVUR*r17;wF96!J` z2#g;_hE>z{zfD~}%y+ny>HX^p7h;R;nywQ|Pkot4~SHTHra2A;V1H z^L*~FMYopKJB(+$<$iUFhP{TkCq<~piz9_Y@G_xqxwW1&=GdZ&) zARkConkW>PCIOMNqk)__uc3i~ArM*^8yFZwiSrs87#bPFxCYTA+N^D$39(rTugwt4 zn;4aleagtnz}&>h&tTBR$i>ve$jES$_41MZD-JlVvhls1u)SC3--0~zfA4$Ub~SW- zWBdNi<4e#??xhu5r){ckdgapU`dj$=iZ=yK>Zc5ky>ZC?vS6d{VS_z8mUx-UH^18@ zq-(F$cxFyofA;FN4;CAxnnv^<@8CG0m|L*Uw$`q%q|Eg5%g?MW&k`3&B|LFH^|JVn z)`}w&mI(daE^gdk{AYKte3~S^NZ(pO>7A9?h811c*^n+ zbF28;=CYH#&rAJNY*%8$ zMvqOMyDG(IoZSC(Q{3sfY8%ejPoIDBcK?>0-!{gWWHT`{GB7T#F{m<-2L`IFGK++P zScAyQSI;ib+rT+}{quivdIClZ1=4-mzzIT@k420{L}d3xwJ-A;ZMyk{&flyS-K2A8 zv7!MVNIyR#<9`+wU=m|95C`!USOg6C40zbM652c%Q-R_Jj0XH531N^zRs&`rg&aS? zln9I;MurMsne&VPu}7bYDoS0oVVP;$u`MV1YnNZhFesS2DD{|e!2DOCb_YaPy6zFW z85z6IuW3b9P#~|;;i&yT6Dms2zFKPZ<3-KKwrLB~SC>EhIz>co!R7YTx7sEaALi}% zpPP{H8rOUMYeb{X1pX`h88^$`?GbDcGvZL#H#u0U>NWeR{pIHTf>nwZQ5Le|-QU|y za=7NJG3>p?xnK6r%^p6L|6BGjd|n^6ZQ_B>vK5teY0@W_ie=Bcba~tdT5AEiBC}N_DL$$jMC3ED6X5QkA9( z&W;96j7rG9VPs`sZerwT0E%-lH8C`oO(pe?%>aNwZA82!}MfkCOy zpr%2^{y?zwJ%*LO`C=c}PJf)dD870N?}MYuR-e`>IB(do^Ux)(iC>q@(GJyK-+r<1 z=!Zogf;n&ebtz=Lxv=E=&M8di((HFEZq6|-+hOx!;>N8N9c$Sh7+${n>#)$~^UIXW z7fFSc)IMMeY*zZ`U}@%1f(u{5>)A zRM!!~izjxc3%t#ldsMLe9bbQbm3Ug!hfhq2`&TAa-8sq1#LURRxVW*;pt0LP9vGUk z$}AEFVhtisYU3})Ol{-PVO_VcbX)53o3Sg>z|k(t$0EievU_6l>UHbx#oT!CX@X76 zulafpEi(-GK>GO^8UM4e0230MfjEe-z#?G4XTZb8mC)wFmB`P(6CoOP>6mwa$q1oO82UUZY zW~+I9pS$Cke`e~8SU0I#Y1jI^WB2)2+NlO?T#s4EqaCI&O_@eeKk^t@7wx84s<6FPawbVJi6l!TjG| z(@C#hCx-iHmc+dXP))s7*O)$S;m=9eoPNJ|d0!!D{^-*tk-jEn+vVIRq=hopn58c@ gne+SomuLHHPkmx4blju<+auTVRtJZZys_O&07ph^Qvd(} literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/requireExplicitPolicy5subCACert.crt b/SecurityTests/nist-certs/requireExplicitPolicy5subCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..16958532f00d75e104be1dd1f6992219ddff5f7a GIT binary patch literal 930 zcmXqLVxDKv#MHKcnTe5!iILHOmyJ`a&7npu?UT2YXbnVeY? zkPoCPO%?|%#0$SU| zsD$i0Mpg#qCPsb+pg0#(6C)$TWfj+sKQX-PM2ieLjEp}XPl-y*{3c^OeML_Ai+y!V z?D=(<9@Ftj%rq~ExU=uS!mU8ZNBv!~V)2)pPHxyXQNKpu>)whrH;#F1Xx#L`bjGTR zJ?aa;8Sj!`xct;fJMkz8u~$=3uM2W(|TvpBe``x$(w9S;!WQ^%zOBBk#7Fw4R`Yj_+($Xvo5e> zuvK#vaDP~t!WOminTtpI?ps^VckTP}p?Q_dvK1+xAKvM5SDbXay&{&$^M%A!h5NTn zg$>wVs8o4(ofGZqRFGUbZ~MdxOlof{H+Q_zd&|Vk$iTR`#-PeT9vGam$}AEFVhtj@ zCpNEMx9(odjR&75*u?yrulLY01DptC`B=nQM9eSmzjr6#`1%uFFD7j`;*t2liiOdD z52T-;k?}tZ3ou!+8Hj`U3M>K!dM=u|LxWIR9{s*0)wMbn$7PiMH$*%$UIU*|>ZqrQ{s|GR29efVR;_RW_qeD=uuZQYFe zxP|xbW;EB=$o}1OVqc~qx58F^^Ha~PZJn%)>!zz_rl>vh(6TvH&Rb~9XyTqwdRb+T POXOFTsJ_VM`6}-LwtQnh literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/requireExplicitPolicy5subsubCACert.crt b/SecurityTests/nist-certs/requireExplicitPolicy5subsubCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..093963aeca5a65ea853aa93e8a6292afb6f2a55a GIT binary patch literal 936 zcmXqLVqRj<#MHBZnTe5!iILHOmyJ`a&7PQz_1(2F-^p=}%1y^}S;<`Q1Vt*?wizsQg)dJGa>;^L)pr$)-K))@{<*CHI9r zVAl@yfM?ePI{e+ex3=tipJsPs$I8$-O0OQ)EPS)KL2tF0-9zW>dHn(BZz`|vj#&RB z{7AX<>6FuP(MPl`*xp}#w(Y~U_ulcH94QWh?B2W<{m;{bBK%#Xi;}j!U~)L(vyAJ9 zlFs7uU+fj0rrcWh@l#U%;;(^`PV>)WW~t`~EVs$85j;&)^afF>L!? z+jMZsmdjR(&TqZsdGb`k8%m$0g#W)*(bE}vEtH9wk%4h>jX{-xJTOFMm02VV#2Q4* zFYmv1C*b({6J0MRZ8+kQ_`!;W5u6lc`B=nQM1C~sSN`8p$H8GO^8UM4e023FRfjEe-z#?G4XTZb8mC)wFm^g8+X#{JpB^;v6YXjQ6AzHfUif-iBZft#w!tmzM0g;uvp{q1q~$-Zm9 zPp;&l+A)qD1qL@>_NHEn;P;<3^TGUgane(nUZ&o4exBOC&!;i|XCOn$DyBP==YQb0 zYY4Ra@0hcAd-tBcLw7s9KL`o*X3B?a#>XE2byu@ZxSJL$EL*LzuBc_* R^i^k_e=Xt@Uia;}JOFRcXNUj* literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/requireExplicitPolicy5subsubsubCACert.crt b/SecurityTests/nist-certs/requireExplicitPolicy5subsubsubCACert.crt new file mode 100644 index 0000000000000000000000000000000000000000..58da176c46551762236de081b98466d220136e2e GIT binary patch literal 942 zcmXqLVqRs?#58FEGZP~d6CB(+$<$iUFhP{TkCq<~piz9_Y@G_xqxwW1&=GdZ&) zARkConkp2RCIOMNqk)__uc3i~ArM*^8yFZwiSrs87#bPFxCYTA+N^D$39(rTugwt4 zn;4aleagtnz}&>h&tTBR$i>ve$jC6&{A)D}XPS`WgP)y01HSvSGi^`bG2>T|eCPLw zgB~rLpFBKtVg0(N4=p~YXe2!AG+ih5$8GcU-hbUWd$$^#shu|~_)G?cwF?&YyeXQuwt`6IL9v=C-gkcz;0HtE8R((85C7Yp=E>PYSu? zXUu)!LXooKOYUPjhoARnq?LT}th*7vZC)0`Y@R7*!H4;CJ#%%{i*|pX-}*bUz~BFn z;NG3P-(8KeQNPJK*|?Nl^x7M@y%xJ~OusPi`n=DE&6gWrhujX{-xJTOpYm02VV z#2Q3?H0f9V-%`iHbUS*z(cCAdiCc4|!3jc^k420{)T%_vLr7?~|`IZ@TkG zSi^u1q@SOW@jnX-Fp04lh=ceFECL3620UzB32h#XsX%c9MgxA3gfK`Us{u2RLXIC` zN(9CaBSZh8k{Uq?uF8osLIh+(70h=Zx|}Ug>TB32a!c4a$ynr&<#EZji6xD5S^4!8 zdl{b0*roHsZ_TCDPJuno1VXe7xS~=mmOpxD7Ox;J^25n5vu@qO?>cKF=O$OAFc)jI zMT+?|MZB2r_uyrQ(*m!97oB}FZ&zsARi5V!n-F-Te6Lx3b*%06bqViXrb@^+COu0w zdsD=*xc7(YiD$PrEfLn&eX!cjv!q8xc&&Fsf|mB(Mgba~tdT5AEiBC}N_DL$$jMC3ED6X5QkCWk z&W;96j7rG9VPs`sZerwT0E%-lH8Cg*`lViViN2g1C za?SA9dGtef;i*dpL-sVz?+9RLSh)Rcuc7CPoeDoJRzG>)yw-De`TAz1JthK^{#(zx z&3#YVr`MD#Zi98S=-mGF?m4Zz6DM@|CmD!!I+rr8Nfz2&75ped^g_&$s(W8n6`J{< zSk0I*_xJv3Uk~kfT^*?rcl0mEgWBe;O=>w8b*07bFMedSJC*r%;?C3VcORx(Y`S=3 z$EvEo!P#%B+*J27$80kCEg!OKid9LeCh?t#nUR5UaburBW4D1kFf?VA zStJa^8bqGd#$Sw?+Qy;7x^7?Tw$$Y}V^^esqg|GdMT|ux$8b8MslvV6rcb#tBO*Ie z&M2PqGT;O0=VxU6&%y#sNNfh;Aie^NfB~NY4;xoPn+IbmP~3pgfFC3w3{uEyzzn1y z0xD2}21a(|C<7)yV3aX3l!$0{PmT#)X?KL9BmKws6R{=c*ORAd3av_eb&%`4yy1G| z)$5Lh2qxVq)c9#5o^e<2PF~jC*UXdOZdp{F`}Rzfzntldop-P4@A`SI>z;Z?-f!{S ziuUzuKF*X;P;aOVG)()h^-!ho`G+Z+OcuLV*WMQ?ofB}DXQ%i@lXZUYu5D;u_*7xn z|JKd#t)1S8ZabN-V9ZgFrSDTKsrT|ku;11!=T`JCHFyUElV_WPcqrQayN2cf!ZZM5v0st^ literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/requireExplicitPolicy7subCARE2Cert.crt b/SecurityTests/nist-certs/requireExplicitPolicy7subCARE2Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..c57e9e4a5bdd40e5fc9aab879d69e001a40f52b5 GIT binary patch literal 952 zcmXqLV%}oV#589CGZP~d6CB(+$<$iUFhP{}|6q<~pivM9B%G_xqxwW1&=GdZ&) zARkConkzUv8pw(B8X6cF0-=Smfq_AkIIppRp^-6+YY;)Aof-ye5If~@*jZef&Dr?uz4I7+h zb^J2xe0?yp@n%48T#WFd>#pTmk^3U&J&_cezP>D(Tfp<;1L?rkf7`B}FXhUfWO(WI z9$|Xz4)H-9z6TW zyr}=kyL%@d-Y#M1)_$rnRe5q^fxhJ|z8~oy772Zue3hMvnUR5UaburBW4D1kFid5Y zStJa^8bopor!$%=+`Dc1lq)kLvLoe;;yEvHN|5Da5n~Z~9;4b_48r5-#2t zBJ%%eeSo;^g)IVH>(`X9EQw?mF-X#r=A5zA)8Y0G|7+sk-`|e3s12-ePu;ugm(7wj zN@t~h{yltT_2=rX+4)yHlBOQ`Dro=YrWA{!cfy8O_crgCaK-3_b#(de^~p`TA{;); z-1fZwGx^%LqDvF5>92omKCdx;V^5sve$(m6QlD@8mClpx7LM6=jH!|Du>B$y-U};( z#cVq~o~M+tMW0hv`q=CIKxn#r;N9drr+fiFndmYH&K9F%c2W{^CR(367A_`zK}w!0 eTKJIp#FEFFRWlseg#G=3ufM;yc-5Jm2~GedqGoyk literal 0 HcmV?d00001 diff --git a/SecurityTests/nist-certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt b/SecurityTests/nist-certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..343efa5ec2d0aa5aa4d9410cd6c1f5467b54a0b6 GIT binary patch literal 964 zcmXqLVm@Hd#I#}oGZP~d6CB(+$<$iUFhP{TkCq<~piz9_Y@G_xqxwW1&=GdZ&) zARkConky8SCOJC>xf&VBiSrs77#ISfg|UHwL6kVJv4NqHF^p>vN21Mo209R%RdL%4 zvpmSv#Gr{$3E8uZtPIRejQk8haW1ANMn;AWi$1Sx#FS1lczVHoFnz)3yb9B#?%Jg;~H}o zrQJ?QslLoqYG#v@9mTHs?t@5rRpMpF>taWHZf!gqz3fDv@t%~LsObkT9Te#bV*Pi_ zsle;1pWl6+8~ZhF59;eQ&*ayUi3nIN^tbz>!UkQKi;A_XjHq-%Zz#Td$FJ=y7h^o`bT!rr&2CSFc>b(~_|K z*Y|(rdsZBtdf-szly$}r^zZF0e7=6_vL`R@Z&(+v8B(bKzM6@dk%4h>W1m4|w}Ct` zWM!3EBn-qFM4rc}_SLQODQ~Vm{3`R>@kJ&NO(MamLY9w3j722xe=kRO+P~RLtAD2$ zr@msI>M>=80Ut;|KO^IR78YPSV>1v3@fBDE4EPLq*tinfJQ!1f;s%Tc{2&QokU~}i zW*`L-P=N|GFtQ*=88CeUql}S(P3VjBU$6T=a>^IaeQCHP>*b8c8zR``tz4=LnHsxd zpX)5T#&^x#GiHm9!%LPWyXu>#JieIpEote`Z7f^YAAeH#f&2PnwRgXE1vtcB)c>G6 z^RB`C>wSM-X2rjFrM-AXqe|qosP`Tbu7~TKKTpWE@ZVt6FuTd(v)Dw9SK6FWTWmNE z9+a5%;q)BKQ%18gCPbhA;Fz+#=1B52j&dFsm*jtwbzjVWHmCi{GI8OpyG!_fXB(+$<$iUFhP|rXIq<~piwJ5c)G_xqxwW1&=GdZ&) zARkConky8SCIOMNW00#+kgJJ-oH(zcfq@|qS{NG`7(|Kl8XFiI8N;{+i6q)@XrK?V zUjwiG$WCZtR6_POBP#=Q6C*!^K@%evQxhX2!|oMP6He$(xzO-yLuUljpFK&nQ{P!f zc-X!Dz_+BphjI34$&PikhTY$7ZEn;pjXB1d7N5WUuZ0|kzu?BW$dC2j#}=MnU_EK} zB=#RWwr&4BSz*R1{hbL`#{9hh)J=o9Z&bgVS6lUv@4?o>DRT^UADoDjT~xYF&FI`h zwlzz(Udey7EP55U!^zb$o5b!+OU_N_<(rpyQ_Eq7$9e5zi>FNU;9R1#^-Hak(ZVy#_tc*Mc*^^1s&m@R z;spNlHv3doJ2;BnXZk1}>p4m1YO`HiMNo;nn(J@-r1+0flMLFKm>C%u7uOh68OQ^J zR#urs!a%G+B=3JOM|ax4*-NW`rx>TcVxHv4~Xb1ST4au3e*(y>g$m zwS?59RrM|gd?5Y&jEw(TSb)im%|IN)S6~q^;4|Q1<4S1rU`z#y8!#I1gCvAO3Rw-9 zffRE508=F}ei#|%%;d>0&i%Y`Uf9NkySlC$hGh%#K5C7!l=ERZbm-ZfH&2chDRJJq zZMNaSbN@N(mNFKa)tZM1#P!P0$>5zhrD;icZLWj$zWbf}(gMF~wktFK&#iU)-22fe z#rZ(p&Y;dxXWigi7X%CbC2wys=rs#^^Z84Ln6zY8u;|>Ms>`;!O(f= 0 the test passes otherwise print a + diagnostic with the name and number of the errno. + +is_unix(EXPR, VALUE, NAME) + Evaluate EXPR, if the errno set by it equals VALUE the test + passes, otherwise print a diagnostic with the expected and + actual errno. + +Finally if you somehow can't express the success or failure of a +test using the macros above you can use pass(NAME) or fail(NAME) +explicitly. These are equivalent to ok(1, NAME) and ok(0, NAME) +respectively. + + +LEAKS +===== + +If you want to check for leaks in your test you can #include +"testleaks.h" in your program and call: + +ok_leaks(NAME) + Passes if there are no leaks in your program. + +is_leaks(VALUE, NAME) + Passes if there are exactly VALUE leaks in your program. Useful + if you are calling code that is known to leak and you can't fix + it. But you still want to make sure there are no new leaks in + your code. + + +C++ +=== + +For C++ programs you can #include "testcpp.h" which defines these +additional macros: +no_throw(EXPR, NAME) + Success if EXPR doesn't throw. + +does_throw(EXPR, NAME) + Success if EXPR does throw. + +is_throw(EXPR, CLASS, FUNC, VALUE, NAME) + Success if EXPR throws an exception of type CLASS and CLASS.FUNC == VALUE. + Example usage: + is_throw(CssmError::throwMe(42), CssmError, osStatus(), 42, "throwMe(42)"); + + +TODO and SKIP +============= + +Sometimes you write a test case that is known to fail (because you +found a bug). Rather than commenting out that test case you should +put it inside a TODO block. This will cause the test to run but +the failure will not be reported as an error. When the test starts +passing (presumably because someone fixed the bug) you can comment +out the todo block and leave the test in place. + +The syntax for doing this looks like so: + + TODO: { + todo(" ER: AAPL target: $4,000,000/share"); + + cmp_ok(apple_stock_price(), >=, 4000000, "stock over 4M"); + } + +Sometimes you don't want to run a particular test case or set of +test cases because something in the environment is missing or you +are running on a different version of the OS than the test was +designed for. To achieve this you can use a skip block. + +The syntax for a skip block looks like so: + + SKIP: { + skip("only runs on Tiger and later", 4, os_version() >= os_tiger); + + ok(tiger_test1(), "test1"); + ok(tiger_test2(), "test2"); + ok(tiger_test3(), "test3"); + ok(tiger_test4(), "test4"); + } + +How it works is like so: If the third argument to skip evaluates +to false it breaks out of the skip block and reports N tests as +being skipped (where N is the second argument to skip) The reason +for the test being skipped is given as the first argument to skip. + + +Utility Functions +================= + +Anyone writing tests can add new utility functions. Currently there +is a pair called tests_begin and tests_end. To get them +#include "testenv.h". Calling them doesn't count as running a test +case, unless you wrap them in an ok() macro. tests_begin creates +a unique dir in /tmp and sets HOME in the environment to that dir. +tests_end cleans up the mess that tests_begin made. + +When writing your own utility functions you will probably want to use +the setup("task") macro so that any uses of ok() and other macros +don't count as actual test cases run, but do report errors when they +fail. Here is an example of how tests_end() does this: + +int +tests_end(int result) +{ + setup("tests_end"); + /* Restore previous cwd and remove scratch dir. */ + return (ok_unix(fchdir(current_dir), "fchdir") && + ok_unix(close(current_dir), "close") && + ok_unix(rmdir_recursive(scratch_dir), "rmdir_recursive")); +} + +Setup cases all tests unil the end of the current funtion to not count +againt your test cases test count and they output nothing if they +succeed. + +There is also a simple utility header called "testcssm.h" which +currently defines cssm_attach and cssm_detach functions for loading +and initializing cssm and loading a module. + + +EXCLUDING TESTS +=============== + +Some tests cannot be automated, notably those that require user +interaction. Such tests should be built, to ensure that API/SPI changes +are caught, but they should not be run via 'make test' since that is how +our automated testing is invoked. To keep your test from being run via +'make test,' add the string NO_AUTOMATED_TESTING as a comment to your main +test file. + +Excluded tests can and should still be run by hand, of course. diff --git a/SecurityTests/regressions/auth/auth-01-immediate-agent.c b/SecurityTests/regressions/auth/auth-01-immediate-agent.c new file mode 100644 index 00000000..df7102ab --- /dev/null +++ b/SecurityTests/regressions/auth/auth-01-immediate-agent.c @@ -0,0 +1,41 @@ +/* NO_AUTOMATED_TESTING */ +#include +#include +#include +#include +#include "testmore.h" + +/* + * XXX/gh These should be in AuthorizationTagsPriv.h + */ +#ifdef AUTHHOST_TYPE_AGENT +#warning AUTHHOST_TYPE_AGENT defined, clean up immediate-agent test +#else +#define AUTHHOST_TYPE_AGENT 1 // SecurityAgent +#endif + +#ifdef AUTHHOST_TYPE_PRIVILEGED +#warning AUTHHOST_TYPE_PRIVILEGED defined, clean up immediate-agent test +#else +#define AUTHHOST_TYPE_PRIVILEGED 2 // authorizationhost +#endif + +int main(__unused int ac, const char *av[]) +{ + uint32_t hostType = AUTHHOST_TYPE_AGENT; + AuthorizationItem item = { AGENT_HINT_IMMEDIATE_LAUNCH, sizeof(hostType), &hostType, 0 }; + AuthorizationEnvironment hints = { 1, &item }; + const char *hostTypeStr; + + plan_tests(1); + + switch(hostType) + { + case AUTHHOST_TYPE_AGENT: hostTypeStr = "SecurityAgent"; break; + case AUTHHOST_TYPE_PRIVILEGED: hostTypeStr = "authorizationhost"; break; + default: hostTypeStr = "unknown host type"; break; + } + ok_status(AuthorizationCreate(NULL, &hints, kAuthorizationFlagDefaults, NULL), "force immediate agent launch"); + + return 0; +} diff --git a/SecurityTests/regressions/auth/auth-02-aewp-basic.c b/SecurityTests/regressions/auth/auth-02-aewp-basic.c new file mode 100644 index 00000000..c3c38b9e --- /dev/null +++ b/SecurityTests/regressions/auth/auth-02-aewp-basic.c @@ -0,0 +1,40 @@ +/* NO_AUTOMATED_TESTING */ +#include +#include +#include +#include +#include "testmore.h" + +#define EXECUTABLE "/bin/ls" +#define LSTARGET "/private/var/db/shadow" + +/* XXX/gh interactive, so inappropriate for auto-regressions */ +int main(__unused int ac, const char *av[]) +{ + AuthorizationRef authRef = NULL; + char *lsargs[2] = { "-l", LSTARGET }; + FILE *commPipe = NULL; + DIR *dir = NULL; + char lsbuf[6]; /* "total" */ + /* uint32_t total; */ + + plan_tests(5); + + /* make sure LSTARGET isn't readable by mere mortals */ + dir = opendir(LSTARGET); + is(errno, EACCES, "AEWP-basic: opendir()"); + ok_status(AuthorizationCreate(NULL, NULL, kAuthorizationFlagDefaults, &authRef), + "AEWP-basic: AuthCreate()"); + ok(authRef != NULL, "AEWP-basic: NULL authRef"); + ok_status(AuthorizationExecuteWithPrivileges(authRef, + EXECUTABLE, + kAuthorizationFlagDefaults, + lsargs, + &commPipe), + "AEWP-basic: AEWP()"); + + /* stops at first white space */ + is_status(fscanf(commPipe, "%s", lsbuf), 1, "AEWP-basic: fscanf()"); + printf("ls output: %s\n", lsbuf); + return 0; +} diff --git a/SecurityTests/regressions/auth/auth-SessionCreate-01-basic.c b/SecurityTests/regressions/auth/auth-SessionCreate-01-basic.c new file mode 100644 index 00000000..5cede143 --- /dev/null +++ b/SecurityTests/regressions/auth/auth-SessionCreate-01-basic.c @@ -0,0 +1,34 @@ +/* NO_AUTOMATED_TESTING */ + +#include +#include /* getenv(3) */ +#include +#include "testmore.h" + +#define SSID_ENV_STR "SECURITYSESSIONID" /* hard-coded in Authorization.cpp */ + +/* + * Not automated because SessionCreate() implicitly invokes task_for_pid(), + * which in turn can trigger an Authorization call (and thus UI) via + * taskgated. + */ +int main(__unused int ac, __unused const char *av[]) +{ + char *ssid = NULL; + + plan_tests(1); + + if ((ssid = getenv(SSID_ENV_STR)) != NULL) + printf("Current SecuritySessionID: %s\n", ssid); + /* + * @@@ SessionCreate() is documented to return "noErr" on success, but + * errSessionSuccess is part of the SessionStatus enum + */ + is(SessionCreate(0/*SessionCreationFlags*/, + sessionHasGraphicAccess|sessionHasTTY/*SessionAttributeFlags*/), + errSessionSuccess, "SessionCreate()"); + if ((ssid = getenv(SSID_ENV_STR)) == NULL) + fprintf(stderr, "Missing %s in environment!\n", SSID_ENV_STR); + printf("New SecuritySessionID: %s\n", ssid); + return 0; +} diff --git a/SecurityTests/regressions/dl/dl-10-create-delete.c b/SecurityTests/regressions/dl/dl-10-create-delete.c new file mode 100644 index 00000000..bdae3acf --- /dev/null +++ b/SecurityTests/regressions/dl/dl-10-create-delete.c @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2005-2006 Apple Computer, 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@ + * + * 00DL_Create-Delete.c + */ + +#include +#include +#include +#include + +#include "testmore.h" +#include "testenv.h" +#include "testcssm.h" +#include "testleaks.h" + +#define DBNAME "testdl.db" + +static CSSM_APPLEDL_OPEN_PARAMETERS openParameters = +{ + sizeof(CSSM_APPLEDL_OPEN_PARAMETERS), + CSSM_APPLEDL_OPEN_PARAMETERS_VERSION, + CSSM_FALSE, + kCSSM_APPLEDL_MASK_MODE, + 0600 +}; +static CSSM_DBINFO dbInfo = +{ + 0 /* NumberOfRecordTypes */, + NULL, + NULL, + NULL, + CSSM_TRUE /* IsLocal */, + NULL, /* AccessPath - URL, dir path, etc. */ + NULL /* reserved */ +}; + +int +static test1(CSSM_DL_HANDLE dl) +{ + int pass = 1; + CSSM_DL_DB_HANDLE dldb = { dl }; + + /* Case 1 regular create close delete. */ + pass &= ok_status(CSSM_DL_DbCreate(dldb.DLHandle, DBNAME, + NULL /* DbLocation */, + &dbInfo, + CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, + NULL /* CredAndAclEntry */, + NULL /* &openParameters */, + &dldb.DBHandle), + "CSSM_DL_DbCreate"); + + pass &= ok_status(CSSM_DL_DbClose(dldb), "CSSM_DL_DbClose"); + pass &= ok_status(CSSM_DL_DbDelete(dldb.DLHandle, DBNAME, + NULL /* DbLocation */, + NULL /* AccessCred */), "CSSM_DL_DbDelete"); + pass &= is_unix(unlink(DBNAME), ENOENT, "unlink"); + + return pass; +} + +int +static test2(CSSM_DL_HANDLE dl) +{ + int pass = 1; + CSSM_DL_DB_HANDLE dldb = { dl }; + + /* Case 2 regular create delete then close. */ + pass &= ok_status(CSSM_DL_DbCreate(dldb.DLHandle, DBNAME, + NULL /* DbLocation */, + &dbInfo, + CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, + NULL /* CredAndAclEntry */, + NULL /* &openParameters */, + &dldb.DBHandle), + "CSSM_DL_DbCreate"); + + pass &= ok_status(CSSM_DL_DbDelete(dldb.DLHandle, DBNAME, + NULL /* DbLocation */, + NULL /* AccessCred */), "CSSM_DL_DbDelete"); + pass &= ok_status(CSSM_DL_DbClose(dldb), "CSSM_DL_DbClose"); + pass &= is_unix(unlink(DBNAME), ENOENT, "unlink"); + + return pass; +} + +int +static test3(CSSM_DL_HANDLE dl) +{ + int pass = 1; + CSSM_DL_DB_HANDLE dldb = { dl }; + + /* Case 3 non autocommit create close delete. */ + pass &= ok_status(CSSM_DL_DbCreate(dldb.DLHandle, DBNAME, + NULL /* DbLocation */, + &dbInfo, + CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, + NULL /* CredAndAclEntry */, + &openParameters, + &dldb.DBHandle), + "CSSM_DL_DbCreate"); + + pass &= ok_status(CSSM_DL_DbClose(dldb), "CSSM_DL_DbClose"); + pass &= ok_status(CSSM_DL_DbDelete(dldb.DLHandle, DBNAME, + NULL /* DbLocation */, + NULL /* AccessCred */), "CSSM_DL_DbDelete"); + pass &= is_unix(unlink(DBNAME), ENOENT, "unlink"); + + return pass; +} + +int +static test4(CSSM_DL_HANDLE dl) +{ + int pass = 1; + CSSM_DL_DB_HANDLE dldb = { dl }; + + /* Case 4 non autocommit create delete then close. */ + pass &= ok_status(CSSM_DL_DbCreate(dldb.DLHandle, DBNAME, + NULL /* DbLocation */, + &dbInfo, + CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, + NULL /* CredAndAclEntry */, + &openParameters, + &dldb.DBHandle), + "CSSM_DL_DbCreate"); + + pass &= ok_status(CSSM_DL_DbDelete(dldb.DLHandle, DBNAME, + NULL /* DbLocation */, + NULL /* AccessCred */), "CSSM_DL_DbDelete"); + pass &= ok_status(CSSM_DL_DbClose(dldb), "CSSM_DL_DbClose"); + pass &= is_unix(unlink(DBNAME), ENOENT, "unlink"); + + return pass; +} + +int +static test5(CSSM_DL_HANDLE dl) +{ + int pass = 1; + CSSM_DL_DB_HANDLE dldb = { dl }; + + /* Case 5 non autocommit create rollback close delete. */ + pass &= ok_status(CSSM_DL_DbCreate(dldb.DLHandle, DBNAME, + NULL /* DbLocation */, + &dbInfo, + CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, + NULL /* CredAndAclEntry */, + &openParameters, + &dldb.DBHandle), + "CSSM_DL_DbCreate"); + pass &= ok_status(CSSM_DL_PassThrough(dldb, CSSM_APPLEFILEDL_ROLLBACK, + NULL, NULL), "CSSM_APPLEFILEDL_ROLLBACK"); + pass &= ok_status(CSSM_DL_DbClose(dldb), "CSSM_DL_DbClose"); + pass &= is_status(CSSM_DL_DbDelete(dldb.DLHandle, DBNAME, + NULL /* DbLocation */, NULL /* AccessCred */), + CSSMERR_DL_DATASTORE_DOESNOT_EXIST, "CSSM_DL_DbDelete"); + pass &= is_unix(unlink(DBNAME), ENOENT, "unlink"); + + return pass; +} + +int +static test6(CSSM_DL_HANDLE dl) +{ + int pass = 1; + CSSM_DL_DB_HANDLE dldb = { dl }; + + /* Case 6 non autocommit create rollback delete then close. */ + pass &= ok_status(CSSM_DL_DbCreate(dldb.DLHandle, DBNAME, + NULL /* DbLocation */, + &dbInfo, + CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, + NULL /* CredAndAclEntry */, + &openParameters, + &dldb.DBHandle), + "CSSM_DL_DbCreate"); + + pass &= ok_status(CSSM_DL_PassThrough(dldb, CSSM_APPLEFILEDL_ROLLBACK, + NULL, NULL), "CSSM_APPLEFILEDL_ROLLBACK"); + pass &= is_status(CSSM_DL_DbDelete(dldb.DLHandle, DBNAME, + NULL /* DbLocation */, NULL /* AccessCred */), + CSSMERR_DL_DATASTORE_DOESNOT_EXIST, "CSSM_DL_DbDelete"); + pass &= ok_status(CSSM_DL_DbClose(dldb), "CSSM_DL_DbClose"); + pass &= is_unix(unlink(DBNAME), ENOENT, "unlink"); + + return pass; +} + +int +static test7(CSSM_DL_HANDLE dl) +{ + int pass = 1; + CSSM_DL_DB_HANDLE dldb = { dl }; + + /* Case 7 non autocommit create delete rollback then close. */ + pass &= ok_status(CSSM_DL_DbCreate(dldb.DLHandle, DBNAME, + NULL /* DbLocation */, + &dbInfo, + CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, + NULL /* CredAndAclEntry */, + &openParameters, + &dldb.DBHandle), + "CSSM_DL_DbCreate"); + + pass &= ok_status(CSSM_DL_DbDelete(dldb.DLHandle, DBNAME, + NULL /* DbLocation */, NULL /* AccessCred */), "CSSM_DL_DbDelete"); + pass &= ok_status(CSSM_DL_PassThrough(dldb, CSSM_APPLEFILEDL_ROLLBACK, + NULL, NULL), "CSSM_APPLEFILEDL_ROLLBACK"); + pass &= ok_status(CSSM_DL_DbClose(dldb), "CSSM_DL_DbClose"); + pass &= is_unix(unlink(DBNAME), ENOENT, "unlink"); + + return pass; +} + +int +static test8(CSSM_DL_HANDLE dl) +{ + int pass = 1; + CSSM_DL_DB_HANDLE dldb = { dl }; + + /* Case 8 delete non existant db. */ + pass &= is_status(CSSM_DL_DbDelete(dldb.DLHandle, DBNAME, + NULL /* DbLocation */, NULL /* AccessCred */), + CSSMERR_DL_DATASTORE_DOESNOT_EXIST, "CSSM_DL_DbDelete"); + + + return pass; +} + +int +main(int argc, char * const *argv) +{ + int guid_alt = argc > 1 && !strcmp(argv[1], "-g"); + /* {2cb56191-ee6f-432d-a377-853d3c6b949e} */ + CSSM_GUID s3dl_guid = + { + 0x2cb56191, 0xee6f, 0x432d, + { 0xa3, 0x77, 0x85, 0x3d, 0x3c, 0x6b, 0x94, 0x9e } + }; + const CSSM_GUID *guid = guid_alt ? & s3dl_guid : &gGuidAppleFileDL; + CSSM_DL_HANDLE dl; + + /* Total number of test cases in this file. */ + plan_tests(45); + + ok(cssm_attach(guid, &dl), "cssm_attach"); + ok(tests_begin(argc, argv), "setup"); + + /* Run tests. */ + ok(test1(dl), "create close delete"); + ok(test2(dl), "create delete close"); + ok(test3(dl), "autocommit off create close delete"); + ok(test4(dl), "autocommit off create delete close"); + ok(test5(dl), "autocommit off create rollback close delete"); + ok(test6(dl), "autocommit off create rollback delete close"); + ok(test7(dl), "autocommit off create delete rollback close"); + ok(test8(dl), "delete non existant db"); + + ok(cssm_detach(guid, dl), "cssm_detach"); + ok(tests_end(1), "cleanup"); + TODO: {ok_leaks("leaks");} + + return 0; +} diff --git a/SecurityTests/regressions/dl/dl-11-create-relation.c b/SecurityTests/regressions/dl/dl-11-create-relation.c new file mode 100644 index 00000000..bc01119c --- /dev/null +++ b/SecurityTests/regressions/dl/dl-11-create-relation.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2005 Apple Computer, 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@ + * + * 01DL_CreateReleation.c + */ + +#include +#include +#include +#include + +#include "testmore.h" +#include "testenv.h" +#include "testcssm.h" + +#define DBNAME "testdl" + +CSSM_APPLEDL_OPEN_PARAMETERS openParameters = +{ + sizeof(CSSM_APPLEDL_OPEN_PARAMETERS), + CSSM_APPLEDL_OPEN_PARAMETERS_VERSION, + CSSM_FALSE, + kCSSM_APPLEDL_MASK_MODE, + 0600 +}; +CSSM_DBINFO dbInfo = +{ + 0 /* NumberOfRecordTypes */, + NULL, + NULL, + NULL, + CSSM_TRUE /* IsLocal */, + NULL, /* AccessPath - URL, dir path, etc. */ + NULL /* reserved */ +}; +CSSM_DB_SCHEMA_ATTRIBUTE_INFO attributeInfo[] = +{ + { + 1, + "One", + {}, + CSSM_DB_ATTRIBUTE_FORMAT_STRING + }, + { + 2, + "Two", + {}, + CSSM_DB_ATTRIBUTE_FORMAT_STRING + } +}; +CSSM_DB_SCHEMA_INDEX_INFO indexInfo[] = +{ + { + 1, + 0, + CSSM_DB_INDEX_UNIQUE, + CSSM_DB_INDEX_ON_ATTRIBUTE + }, + { + 1, + 1, + CSSM_DB_INDEX_NONUNIQUE, + CSSM_DB_INDEX_ON_ATTRIBUTE + }, + { + 2, + 2, + CSSM_DB_INDEX_NONUNIQUE, + CSSM_DB_INDEX_ON_ATTRIBUTE + } +}; +CSSM_DATA values[] = +{ + { 5, (uint8 *)"value" } +}; +CSSM_DB_ATTRIBUTE_DATA attributeData[] = +{ + { + { + CSSM_DB_ATTRIBUTE_NAME_AS_STRING, + { "One" }, + CSSM_DB_ATTRIBUTE_FORMAT_STRING + }, + sizeof(values) / sizeof(CSSM_DATA), + values + }, + { + { + CSSM_DB_ATTRIBUTE_NAME_AS_STRING, + { "Two" }, + CSSM_DB_ATTRIBUTE_FORMAT_STRING + }, + sizeof(values) / sizeof(CSSM_DATA), + values + } +}; +CSSM_DB_RECORD_ATTRIBUTE_DATA attributes = +{ + 42, + 0, + sizeof(attributeData) / sizeof(CSSM_DB_ATTRIBUTE_DATA), + attributeData +}; + +int +static test1(CSSM_DL_HANDLE dl) +{ + int pass = 1; + CSSM_DL_DB_HANDLE dldb = { dl }; + CSSM_DB_UNIQUE_RECORD_PTR uniqueId; + + pass &= ok_status(CSSM_DL_DbCreate(dl, DBNAME, NULL /* DbLocation */, + &dbInfo, + CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, + NULL /* CredAndAclEntry */, + &openParameters, + &dldb.DBHandle), + "CSSM_DL_DbCreate"); + + pass &= is_status(CSSM_DL_DataInsert(dldb, + attributes.DataRecordType, + &attributes, + NULL, + &uniqueId), + CSSMERR_DL_INVALID_RECORDTYPE, "CSSM_DL_DataInsert no table"); + + pass &= ok_status(CSSM_DL_CreateRelation(dldb, + 42, + "Fourty Two", + sizeof(attributeInfo) / sizeof(CSSM_DB_SCHEMA_ATTRIBUTE_INFO), + attributeInfo, + sizeof(indexInfo) / sizeof(CSSM_DB_SCHEMA_INDEX_INFO), + indexInfo), "CSSM_DL_CreateRelation"); + + pass &= ok_status(CSSM_DL_DataInsert(dldb, + attributes.DataRecordType, + &attributes, + NULL, + &uniqueId), "CSSM_DL_DataInsert"); + + pass &= is_status(CSSM_DL_DataInsert(dldb, + attributes.DataRecordType, + &attributes, + NULL, + &uniqueId), + CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA, "CSSM_DL_DataInsert dupe"); + + pass &= ok_status(CSSM_DL_FreeUniqueRecord(dldb, uniqueId), + "CSSM_DL_FreeUniqueRecord"); + + pass &= ok_status(CSSM_DL_DbClose(dldb), + "CSSM_DL_DbClose"); + + return pass; +} + +int +static test2(CSSM_DL_HANDLE dl) +{ + int pass = 1; + CSSM_DL_DB_HANDLE dldb = { dl }; + CSSM_DB_UNIQUE_RECORD_PTR uniqueId; + + pass &= ok_status(CSSM_DL_DbCreate(dl, DBNAME, NULL /* DbLocation */, + &dbInfo, + CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, + NULL /* CredAndAclEntry */, + NULL, + &dldb.DBHandle), + "CSSM_DL_DbCreate"); + + pass &= ok_status(CSSM_DL_DbClose(dldb), + "CSSM_DL_DbClose"); + + pass &= ok_status(CSSM_DL_DbOpen(dl, DBNAME, NULL /* DbLocation */, + CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, + NULL /* CredAndAclEntry */, + &openParameters, + &dldb.DBHandle), + "CSSM_DL_DbOpen"); + + pass &= is_status(CSSM_DL_DataInsert(dldb, + attributes.DataRecordType, + &attributes, + NULL, + &uniqueId), + CSSMERR_DL_INVALID_RECORDTYPE, "CSSM_DL_DataInsert no table"); + + pass &= ok_status(CSSM_DL_CreateRelation(dldb, + 42, + "Fourty Two", + sizeof(attributeInfo) / sizeof(CSSM_DB_SCHEMA_ATTRIBUTE_INFO), + attributeInfo, + sizeof(indexInfo) / sizeof(CSSM_DB_SCHEMA_INDEX_INFO), + indexInfo), "CSSM_DL_CreateRelation"); + + pass &= ok_status(CSSM_DL_DataInsert(dldb, + attributes.DataRecordType, + &attributes, + NULL, + &uniqueId), "CSSM_DL_DataInsert fails unless 4039735 is fixed"); + + pass &= is_status(CSSM_DL_DataInsert(dldb, + attributes.DataRecordType, + &attributes, + NULL, + &uniqueId), + CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA, + "CSSM_DL_DataInsert dupe"); + + pass &= ok_status(CSSM_DL_FreeUniqueRecord(dldb, uniqueId), + "CSSM_DL_FreeUniqueRecord"); + + pass &= ok_status(CSSM_DL_DbClose(dldb), + "CSSM_DL_DbDelete"); + + return pass; +} + +int +main(int argc, char * const *argv) +{ + int guid_alt = argc > 1 && !strcmp(argv[1], "-g"); + /* {2cb56191-ee6f-432d-a377-853d3c6b949e} */ + CSSM_GUID s3dl_guid = + { + 0x2cb56191, 0xee6f, 0x432d, + { 0xa3, 0x77, 0x85, 0x3d, 0x3c, 0x6b, 0x94, 0x9e } + }; + const CSSM_GUID *guid = guid_alt ? & s3dl_guid : &gGuidAppleFileDL; + + int pass = 1; + + plan_tests(23); + + CSSM_DL_HANDLE dl; + pass &= ok(cssm_attach(guid, &dl), "cssm_attach"); + pass &= ok(tests_begin(argc, argv), "tests_begin"); + + pass &= ok(test1(dl), "insert record in new table with ac off"); + pass &= ok_status(CSSM_DL_DbDelete(dl, DBNAME, NULL /* DbLocation */, + NULL /* AccessCred */), "CSSM_DL_DbDelete"); + pass &= ok(test2(dl), + "insert record in existing db in new table with ac off"); + pass &= ok_status(CSSM_DL_DbDelete(dl, DBNAME, NULL /* DbLocation */, + NULL /* AccessCred */), "CSSM_DL_DbDelete"); + pass &= ok(cssm_detach(guid, dl), "cssm_detach"); + + return !tests_end(pass); +} diff --git a/SecurityTests/regressions/dl/dl-12-modify.c b/SecurityTests/regressions/dl/dl-12-modify.c new file mode 100644 index 00000000..9d591480 --- /dev/null +++ b/SecurityTests/regressions/dl/dl-12-modify.c @@ -0,0 +1,687 @@ +/* + * Copyright (c) 2005-2006,2010 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@ + * + * 01DL_CreateReleation.c + */ + +#include +#include +#include +#include + +#include "testmore.h" +#include "testenv.h" +#include "testcssm.h" +#include "testleaks.h" + +#define DBNAME "testdl" + +CSSM_APPLEDL_OPEN_PARAMETERS openParameters = +{ + sizeof(CSSM_APPLEDL_OPEN_PARAMETERS), + CSSM_APPLEDL_OPEN_PARAMETERS_VERSION, + CSSM_FALSE, + kCSSM_APPLEDL_MASK_MODE, + 0600 +}; +CSSM_DBINFO dbInfo = +{ + 0 /* NumberOfRecordTypes */, + NULL, + NULL, + NULL, + CSSM_TRUE /* IsLocal */, + NULL, /* AccessPath - URL, dir path, etc. */ + NULL /* reserved */ +}; +CSSM_DB_SCHEMA_ATTRIBUTE_INFO attributeInfo[] = +{ + { + 1, + "string-1", + {}, + CSSM_DB_ATTRIBUTE_FORMAT_STRING + }, + { + 2, + "sint32-2", + {}, + CSSM_DB_ATTRIBUTE_FORMAT_SINT32 + }, + { + 3, + "uint32-3", + {}, + CSSM_DB_ATTRIBUTE_FORMAT_UINT32 + }, + { + 4, + "big_num-4", + {}, + CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM + }, + { + 5, + "real-5", + {}, + CSSM_DB_ATTRIBUTE_FORMAT_REAL + }, + { + 6, + "time-date-6", + {}, + CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE + }, + { + 7, + "blob-7", + {}, + CSSM_DB_ATTRIBUTE_FORMAT_BLOB + }, + { + 8, + "multi-uint32-8", + {}, + CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32 + }, +#if 0 + /* @@@ DL bug if you create a relation with a + CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX type attribute it succeeds but + subsequent inserts in that table fail. */ + { + 9, + "complex-9", + {}, + CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX + } +#endif +}; +CSSM_DB_SCHEMA_INDEX_INFO indexInfo[] = +{ + { + 1, + 0, + CSSM_DB_INDEX_UNIQUE, + CSSM_DB_INDEX_ON_ATTRIBUTE + }, + { + 1, + 1, + CSSM_DB_INDEX_NONUNIQUE, + CSSM_DB_INDEX_ON_ATTRIBUTE + }, + { + 2, + 2, + CSSM_DB_INDEX_NONUNIQUE, + CSSM_DB_INDEX_ON_ATTRIBUTE + } +}; +CSSM_DATA values_str_1[] = +{ + { 7, (uint8 *)"value-1" } +}; +CSSM_DATA values_str_2[] = +{ + { 7, (uint8 *)"value-2" } +}; +CSSM_DATA values_sint32_1[] = +{ + { sizeof(sint32), (uint8 *)"1111" } +}; +CSSM_DATA values_sint32_2[] = +{ + { sizeof(sint32), (uint8 *)"2222" } +}; + +CSSM_DB_ATTRIBUTE_DATA attributeData[] = +{ + { + { + CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, + { (char *)((uint64_t)1<<32|1) }, + CSSM_DB_ATTRIBUTE_FORMAT_STRING + }, + sizeof(values_str_1) / sizeof(CSSM_DATA), + values_str_1 + }, + { + { + CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, + { (char *)((uint64_t)2<<32|2) }, + CSSM_DB_ATTRIBUTE_FORMAT_SINT32 + }, + sizeof(values_sint32_1) / sizeof(CSSM_DATA), + values_sint32_1 + } +}; +CSSM_DB_RECORD_ATTRIBUTE_DATA attributes = +{ + 42, + 0x00008000, + sizeof(attributeData) / sizeof(CSSM_DB_ATTRIBUTE_DATA), + attributeData +}; + +CSSM_DB_ATTRIBUTE_DATA newAttributeData[] = +{ + { + { + CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, + { (char *)((uint64_t)1<<32|1) }, + CSSM_DB_ATTRIBUTE_FORMAT_STRING + }, + sizeof(values_str_2) / sizeof(CSSM_DATA), + values_str_2 + }, + { + { + CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, + { (char *)((uint64_t)2<<32|2) }, + CSSM_DB_ATTRIBUTE_FORMAT_SINT32 + }, + sizeof(values_sint32_2) / sizeof(CSSM_DATA), + values_sint32_2 + } +}; +CSSM_DB_RECORD_ATTRIBUTE_DATA newAttributes = +{ + 42, + 0x80000001, /* Semantic Information. */ + sizeof(newAttributeData) / sizeof(CSSM_DB_ATTRIBUTE_DATA), + newAttributeData +}; + +static void free_attributes_data(const CSSM_API_MEMORY_FUNCS *memfuncs, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR attributes, CSSM_DATA_PTR data) +{ + if (data && data->Data) + { + memfuncs->free_func(data->Data, memfuncs->AllocRef); + data->Data = NULL; + } + + if (attributes && attributes->AttributeData) + { + uint32 aix; + for (aix = 0; aix < attributes->NumberOfAttributes; ++aix) + { + if (attributes->AttributeData[aix].Value) + { + uint32 vix; + for (vix = 0; + vix < attributes->AttributeData[aix].NumberOfValues; ++vix) + { + if (attributes->AttributeData[aix].Value[vix].Data) + { + memfuncs->free_func( + attributes->AttributeData[aix].Value[vix].Data, + memfuncs->AllocRef); + } + } + + memfuncs->free_func(attributes->AttributeData[aix].Value, + memfuncs->AllocRef); + attributes->AttributeData[aix].NumberOfValues = 0; + attributes->AttributeData[aix].Value = NULL; + } + } + } +} + +static int test_is_attributes_data( + const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes1, const CSSM_DATA *data1, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes2, const CSSM_DATA *data2, + const char *description, const char *directive, + const char *reason, const char *file, unsigned line) +{ + if (attributes1 || attributes2) + { + if (!attributes1 || !attributes2) + return test_ok(0, description, directive, reason, file, line, + "# got CSSM_DB_RECORD_ATTRIBUTE_DATA %p\n" + "# expected CSSM_DB_RECORD_ATTRIBUTE_DATA %p\n", + attributes1, attributes2); + + if (attributes1->DataRecordType != attributes2->DataRecordType || + attributes1->SemanticInformation != + attributes2->SemanticInformation || + attributes1->NumberOfAttributes != attributes2->NumberOfAttributes) + return test_ok(0, description, directive, reason, file, line, + "# got CSSM_DB_RECORD_ATTRIBUTE_DATA:\n" + "# DataRecordType: %08x\n" + "# SemanticInformation: %08x\n" + "# NumberOfAttributes: %lu\n" + "# expected CSSM_DB_RECORD_ATTRIBUTE_DATA:\n" + "# DataRecordType: %08x\n" + "# SemanticInformation: %08x\n" + "# NumberOfAttributes: %lu\n", + attributes1->DataRecordType, + attributes1->SemanticInformation, + attributes1->NumberOfAttributes, + attributes2->DataRecordType, + attributes2->SemanticInformation, + attributes2->NumberOfAttributes); + uint32 ai; + for (ai = 0; ai < attributes1->NumberOfAttributes; ++ai) + { + const CSSM_DB_ATTRIBUTE_DATA *a1 = &attributes1->AttributeData[ai]; + const CSSM_DB_ATTRIBUTE_DATA *a2 = &attributes2->AttributeData[ai]; + if (a1->Info.AttributeFormat != a2->Info.AttributeFormat || + a1->NumberOfValues != a2->NumberOfValues) + return test_ok(0, description, directive, reason, file, line, + "# got AttributeData[%lu]:\n" + "# AttributeFormat: %08x\n" + "# NumberOfValues: %lu\n" + "# expected AttributeData[%lu]:\n" + "# AttributeFormat: %08x\n" + "# NumberOfValues: %lu\n", + ai, a1->Info.AttributeFormat, a1->NumberOfValues, + ai, a2->Info.AttributeFormat, a2->NumberOfValues); + uint32 vi; + for (vi = 0; vi < a1->NumberOfValues; ++vi) + { + const CSSM_DATA *d1 = &a1->Value[vi]; + const CSSM_DATA *d2 = &a2->Value[vi]; + if (d1->Length != d2->Length || !d1->Data || !d2->Data || + memcmp(d1->Data, d2->Data, d1->Length)) + return test_ok(d1->Data == d2->Data, description, + directive, reason, file, line, + "# got AttributeData[%lu].Value[%lu]:\n" + "# length: %lu\n" + "# data: '%.*s'\n" + "# expected AttributeData[%lu].Value[%lu]:\n" + "# length: %lu\n" + "# data: '%.*s'\n", + ai, vi, d1->Length, (int)d1->Length, d1->Data, + ai, vi, d2->Length, (int)d2->Length, d2->Data); + } + } + } + if (data1 || data2) + { + if (!data1 || !data2) + return test_ok(0, description, directive, reason, file, line, + "# got CSSM_DATA %p\n" + "# expected CSSM_DATA %p\n", data1, data2); + if (data1->Length != data2->Length || !data1->Data || !data2->Data || + memcmp(data1->Data, data2->Data, data1->Length)) + return test_ok(data1->Data == data2->Data, description, directive, + reason, file, line, + "# got CSSM_DATA:\n" + "# length: %lu\n" + "# data: '%.*s'\n" + "# expected CSSM_DATA:\n" + "# length: %lu\n" + "# data: '%.*s'\n", + data1->Length, (int)data1->Length, data1->Data, + data2->Length, (int)data2->Length, data2->Data); + } + + return test_ok(1, description, directive, reason, file, line, NULL); +} + +#define is_attributes_data(A1, D1, A2, D2, TESTNAME) \ +( \ + test_is_attributes_data((A1), (D1), (A2), (D2), \ + TESTNAME, test_directive, test_reason, __FILE__, __LINE__) \ +) + +static void test1(CSSM_DL_HANDLE dl) +{ + CSSM_DL_DB_HANDLE dldb = { dl }; + CSSM_DB_UNIQUE_RECORD_PTR uniqueId; + + CSSM_DATA data = { 4, (uint8 *)"test" }; + ok_status(CSSM_DL_DbCreate(dl, DBNAME, NULL /* DbLocation */, + &dbInfo, + CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, + NULL /* CredAndAclEntry */, + NULL /* &openParameters */, + &dldb.DBHandle), + "CSSM_DL_DbCreate"); + + is_status(CSSM_DL_DataInsert(dldb, + attributes.DataRecordType, + &attributes, + &data, + &uniqueId), + CSSMERR_DL_INVALID_RECORDTYPE, "CSSM_DL_DataInsert no table"); + + ok_status(CSSM_DL_CreateRelation(dldb, + 42, + "Fourty Two", + sizeof(attributeInfo) / sizeof(CSSM_DB_SCHEMA_ATTRIBUTE_INFO), + attributeInfo, + sizeof(indexInfo) / sizeof(CSSM_DB_SCHEMA_INDEX_INFO), + indexInfo), "CSSM_DL_CreateRelation"); + + ok_status(CSSM_DL_DataInsert(dldb, + attributes.DataRecordType, + &attributes, + &data, + &uniqueId), "CSSM_DL_DataInsert"); + + is_status(CSSM_DL_DataInsert(dldb, + attributes.DataRecordType, + &attributes, + &data, + &uniqueId), + CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA, "CSSM_DL_DataInsert dupe"); + + ok_status(CSSM_DL_DataModify(dldb, + attributes.DataRecordType, + uniqueId, + &newAttributes, + &data, + CSSM_DB_MODIFY_ATTRIBUTE_REPLACE), "CSSM_DL_DataModify"); + + ok_status(CSSM_DL_FreeUniqueRecord(dldb, uniqueId), + "CSSM_DL_FreeUniqueRecord"); + + ok_status(CSSM_DL_DataInsert(dldb, + attributes.DataRecordType, + &attributes, + &data, + &uniqueId), "CSSM_DL_DataInsert old one again"); + + CSSM_API_MEMORY_FUNCS memfuncs = {}; + ok_status(CSSM_GetAPIMemoryFunctions(dldb.DLHandle, &memfuncs), + "CSSM_GetAPIMemoryFunctions"); + + ok_status(CSSM_DL_DataGetFromUniqueRecordId(dldb, uniqueId, NULL, NULL), + "CSSM_DL_DataGetFromUniqueRecordId get nothing"); + + CSSM_DATA resultData = {}; + ok_status(CSSM_DL_DataGetFromUniqueRecordId(dldb, uniqueId, + NULL, &resultData), + "CSSM_DL_DataGetFromUniqueRecordId get data"); + is_attributes_data(NULL, &resultData, NULL, &data, "Does data match?"); + free_attributes_data(&memfuncs, NULL, &resultData); + + CSSM_DB_RECORD_ATTRIBUTE_DATA baseNoAttrs = attributes; + baseNoAttrs.NumberOfAttributes = 0; + baseNoAttrs.AttributeData = NULL; + CSSM_DB_RECORD_ATTRIBUTE_DATA resultNoAttrs = {}; + ok_status(CSSM_DL_DataGetFromUniqueRecordId(dldb, uniqueId, + &resultNoAttrs, NULL), + "CSSM_DL_DataGetFromUniqueRecordId get 0 attributes"); + is_attributes_data(&resultNoAttrs, NULL, &baseNoAttrs, NULL, + "Do attrs match?"); + free_attributes_data(&memfuncs, &resultNoAttrs, NULL); + + ok_status(CSSM_DL_DataGetFromUniqueRecordId(dldb, uniqueId, + &resultNoAttrs, &resultData), + "CSSM_DL_DataGetFromUniqueRecordId get data and 0 attributes"); + is_attributes_data(&resultNoAttrs, &resultData, &baseNoAttrs, &data, + "Do attrs and data match?"); + free_attributes_data(&memfuncs, &resultNoAttrs, &resultData); + + CSSM_DB_ATTRIBUTE_DATA resultAttributeData[] = + { + {{ CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, { (char *)((uint64_t)1<<32|1) } }}, + {{ CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, { (char *)((uint64_t)2<<32|2) } }} + }; + CSSM_DB_RECORD_ATTRIBUTE_DATA resultAttrs = + { + 0, 0, + sizeof(resultAttributeData) / sizeof(*resultAttributeData), + resultAttributeData + }; + ok_status(CSSM_DL_DataGetFromUniqueRecordId(dldb, uniqueId, + &resultAttrs, &resultData), + "CSSM_DL_DataGetFromUniqueRecordId get data and 2 attributes"); + is_attributes_data(&resultAttrs, &resultData, &attributes, &data, + "Do attrs and data match?"); + free_attributes_data(&memfuncs, &resultAttrs, &resultData); + + ok_status(CSSM_DL_FreeUniqueRecord(dldb, uniqueId), + "CSSM_DL_FreeUniqueRecord"); + + CSSM_SELECTION_PREDICATE predicates[] = + { + { + CSSM_DB_EQUAL, + { + { CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER, { (char *)((uint64_t)1<<32|1) } }, + 1, values_str_1 + } + } + }; + CSSM_QUERY query = + { + attributes.DataRecordType, + CSSM_DB_AND, + sizeof(predicates) / sizeof(*predicates), + predicates, + { CSSM_QUERY_TIMELIMIT_NONE, CSSM_QUERY_SIZELIMIT_NONE }, + 0 /* CSSM_QUERY_RETURN_DATA -- for keys only to return raw key bits */ + }; + CSSM_HANDLE search = CSSM_INVALID_HANDLE; + is_status(CSSM_DL_DataGetFirst(dldb, &query, NULL, + NULL, NULL, NULL), CSSM_ERRCODE_INVALID_POINTER, + "CSSM_DL_DataGetFirst no search handle, no unique_record"); + is_status(CSSM_DL_DataGetFirst(dldb, &query, &search, + NULL, NULL, NULL), CSSM_ERRCODE_INVALID_POINTER, + "CSSM_DL_DataGetFirst no unique_record"); + is_status(CSSM_DL_DataGetFirst(dldb, &query, NULL, + NULL, NULL, &uniqueId), CSSM_ERRCODE_INVALID_POINTER, + "CSSM_DL_DataGetFirst no search handle"); + + ok_status(CSSM_DL_DataGetFirst(dldb, &query, &search, + NULL, NULL, &uniqueId), + "CSSM_DL_DataGetFirst no data no attrs"); + ok_status(CSSM_DL_FreeUniqueRecord(dldb, uniqueId), + "CSSM_DL_FreeUniqueRecord"); + ok_status(CSSM_DL_DataAbortQuery(dldb, search), + "CSSM_DL_DataAbortQuery"); + + ok_status(CSSM_DL_DataGetFirst(dldb, &query, &search, + &resultNoAttrs, NULL, &uniqueId), + "CSSM_DL_DataGetFirst 0 attrs"); + is_attributes_data(&resultNoAttrs, NULL, &baseNoAttrs, NULL, + "Do attrs match?"); + free_attributes_data(&memfuncs, &resultNoAttrs, NULL); + ok_status(CSSM_DL_FreeUniqueRecord(dldb, uniqueId), + "CSSM_DL_FreeUniqueRecord"); + ok_status(CSSM_DL_DataAbortQuery(dldb, search), + "CSSM_DL_DataAbortQuery"); + + ok_status(CSSM_DL_DataGetFirst(dldb, &query, &search, + NULL, &resultData, &uniqueId), + "CSSM_DL_DataGetFirst data"); + is_attributes_data(NULL, &resultData, NULL, &data, "Does data match?"); + free_attributes_data(&memfuncs, NULL, &resultData); + ok_status(CSSM_DL_FreeUniqueRecord(dldb, uniqueId), + "CSSM_DL_FreeUniqueRecord"); + ok_status(CSSM_DL_DataAbortQuery(dldb, search), + "CSSM_DL_DataAbortQuery"); + + ok_status(CSSM_DL_DataGetFirst(dldb, &query, &search, + &resultNoAttrs, &resultData, &uniqueId), + "CSSM_DL_DataGetFirst 0 attrs and data"); + is_attributes_data(&resultNoAttrs, &resultData, &baseNoAttrs, &data, + "Do attrs and data match?"); + free_attributes_data(&memfuncs, &resultNoAttrs, &resultData); + ok_status(CSSM_DL_FreeUniqueRecord(dldb, uniqueId), + "CSSM_DL_FreeUniqueRecord"); + ok_status(CSSM_DL_DataAbortQuery(dldb, search), + "CSSM_DL_DataAbortQuery"); + + ok_status(CSSM_DL_DataGetFirst(dldb, &query, &search, + &resultAttrs, &resultData, &uniqueId), + "CSSM_DL_DataGetFirst 2 attrs and data"); + is_attributes_data(&resultAttrs, &resultData, &attributes, &data, + "Do attrs and data match?"); + free_attributes_data(&memfuncs, &resultAttrs, &resultData); + ok_status(CSSM_DL_FreeUniqueRecord(dldb, uniqueId), + "CSSM_DL_FreeUniqueRecord"); + ok_status(CSSM_DL_DataAbortQuery(dldb, search), + "CSSM_DL_DataAbortQuery"); + + SKIP: { + skip("nothing to free", 2, + ok_status(CSSM_DL_DataGetFirst(dldb, &query, &search, + &resultAttrs, &resultData, &uniqueId), + "CSSM_DL_DataGetFirst 2 attrs and data")); + is_attributes_data(&resultAttrs, &resultData, &attributes, &data, + "Do attrs and data match?"); + free_attributes_data(&memfuncs, &resultAttrs, &resultData); + ok_status(CSSM_DL_FreeUniqueRecord(dldb, uniqueId), + "CSSM_DL_FreeUniqueRecord"); + } + + is_status(CSSM_DL_DataGetNext(dldb, search, + &resultAttrs, &resultData, &uniqueId), + CSSMERR_DL_ENDOFDATA, "CSSM_DL_DataGetNext returns eod"); + + CSSM_QUERY query2 = + { + attributes.DataRecordType, + CSSM_DB_NONE, + 0, + NULL, + { CSSM_QUERY_TIMELIMIT_NONE, CSSM_QUERY_SIZELIMIT_NONE }, + 0 /* CSSM_QUERY_RETURN_DATA -- for keys only to return raw key bits */ + }; + ok_status(CSSM_DL_DataGetFirst(dldb, &query2, &search, + &resultAttrs, &resultData, &uniqueId), + "CSSM_DL_DataGetFirst 2 attrs and data"); + free_attributes_data(&memfuncs, &resultAttrs, &resultData); + ok_status(CSSM_DL_FreeUniqueRecord(dldb, uniqueId), + "CSSM_DL_FreeUniqueRecord"); + ok_status(CSSM_DL_DataGetNext(dldb, search, + &resultAttrs, &resultData, &uniqueId), + "CSSM_DL_DataGetNext 2 attrs and data"); + free_attributes_data(&memfuncs, &resultAttrs, &resultData); + ok_status(CSSM_DL_FreeUniqueRecord(dldb, uniqueId), + "CSSM_DL_FreeUniqueRecord"); + ok_status(CSSM_DL_DataAbortQuery(dldb, search), + "CSSM_DL_DataAbortQuery"); + + ok_status(CSSM_DL_DbClose(dldb), + "CSSM_DL_DbClose"); +} + +static void test2(CSSM_DL_HANDLE dl) +{ + CSSM_DL_DB_HANDLE dldb = { dl }; + CSSM_DB_UNIQUE_RECORD_PTR uniqueId; + + ok_status(CSSM_DL_DbCreate(dl, DBNAME, NULL /* DbLocation */, + &dbInfo, + CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, + NULL /* CredAndAclEntry */, + NULL, + &dldb.DBHandle), + "CSSM_DL_DbCreate"); + + ok_status(CSSM_DL_DbClose(dldb), + "CSSM_DL_DbClose"); + + ok_status(CSSM_DL_DbOpen(dl, DBNAME, NULL /* DbLocation */, + CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, + NULL /* CredAndAclEntry */, + &openParameters, + &dldb.DBHandle), + "CSSM_DL_DbOpen"); + + is_status(CSSM_DL_DataInsert(dldb, + attributes.DataRecordType, + &attributes, + NULL, + &uniqueId), + CSSMERR_DL_INVALID_RECORDTYPE, "CSSM_DL_DataInsert no table"); + + ok_status(CSSM_DL_CreateRelation(dldb, + 42, + "Fourty Two", + sizeof(attributeInfo) / sizeof(CSSM_DB_SCHEMA_ATTRIBUTE_INFO), + attributeInfo, + sizeof(indexInfo) / sizeof(CSSM_DB_SCHEMA_INDEX_INFO), + indexInfo), "CSSM_DL_CreateRelation"); + + ok_status(CSSM_DL_DataInsert(dldb, + attributes.DataRecordType, + &attributes, + NULL, + &uniqueId), "CSSM_DL_DataInsert fails unless 4039735 is fixed"); + + is_status(CSSM_DL_DataInsert(dldb, + attributes.DataRecordType, + &attributes, + NULL, + &uniqueId), + CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA, + "CSSM_DL_DataInsert dupe"); + + ok_status(CSSM_DL_DataDelete(dldb, uniqueId), + "CSSM_DL_Delete"); + + is_status(CSSM_DL_DataDelete(dldb, uniqueId), + CSSMERR_DL_RECORD_NOT_FOUND, "delete again should fail"); + + ok_status(CSSM_DL_FreeUniqueRecord(dldb, uniqueId), + "CSSM_DL_FreeUniqueRecord"); + + ok_status(CSSM_DL_DataInsert(dldb, + attributes.DataRecordType, + &attributes, + NULL, + &uniqueId), "Insert again after delete"); + + ok_status(CSSM_DL_FreeUniqueRecord(dldb, uniqueId), + "CSSM_DL_FreeUniqueRecord"); + + ok_status(CSSM_DL_DbClose(dldb), + "CSSM_DL_DbDelete"); +} + +int +main(int argc, char * const *argv) +{ + int guid_alt = argc > 1 && !strcmp(argv[1], "-g"); + /* {2cb56191-ee6f-432d-a377-853d3c6b949e} */ + CSSM_GUID s3dl_guid = + { + 0x2cb56191, 0xee6f, 0x432d, + { 0xa3, 0x77, 0x85, 0x3d, 0x3c, 0x6b, 0x94, 0x9e } + }; + const CSSM_GUID *guid = guid_alt ? & s3dl_guid : &gGuidAppleFileDL; + + plan_tests(70); + + CSSM_DL_HANDLE dl; + ok(cssm_attach(guid, &dl), "cssm_attach"); + ok(tests_begin(argc, argv), "tests_begin"); + + test1(dl); + ok_status(CSSM_DL_DbDelete(dl, DBNAME, NULL /* DbLocation */, + NULL /* AccessCred */), "CSSM_DL_DbDelete"); + test2(dl); + ok_status(CSSM_DL_DbDelete(dl, DBNAME, NULL /* DbLocation */, + NULL /* AccessCred */), "CSSM_DL_DbDelete"); + ok(cssm_detach(guid, dl), "cssm_detach"); + ok_leaks("no leaks"); + + return !tests_end(1); +} diff --git a/SecurityTests/regressions/inc/MyHarness.pm b/SecurityTests/regressions/inc/MyHarness.pm new file mode 100644 index 00000000..781b828c --- /dev/null +++ b/SecurityTests/regressions/inc/MyHarness.pm @@ -0,0 +1,29 @@ +use warnings; +use strict; + +package MyStraps; +use base qw( Test::Harness::Straps ); + +sub _command_line { + my $self = shift; + my $file = shift; + + $file = qq["$file"] if ($file =~ /\s/) && ($file !~ /^".*"$/); + my $line = "$file"; + + return $line; +} + +sub _default_inc { + return @INC; +} + +package MyHarness; +use base qw( Test::Harness ); + +#my $Strap = MyStraps->new(); +$Test::Harness::Strap = MyStraps->new(); + +sub strap { return $Test::Harness::Strap } + +1; diff --git a/SecurityTests/regressions/inc/Test.pm b/SecurityTests/regressions/inc/Test.pm new file mode 100644 index 00000000..f2cddc09 --- /dev/null +++ b/SecurityTests/regressions/inc/Test.pm @@ -0,0 +1,955 @@ + +require 5.004; +package Test; +# Time-stamp: "2004-04-28 21:46:51 ADT" + +use strict; + +use Carp; +use vars (qw($VERSION @ISA @EXPORT @EXPORT_OK $ntest $TestLevel), #public-ish + qw($TESTOUT $TESTERR %Program_Lines $told_about_diff + $ONFAIL %todo %history $planned @FAILDETAIL) #private-ish + ); + +# In case a test is run in a persistent environment. +sub _reset_globals { + %todo = (); + %history = (); + @FAILDETAIL = (); + $ntest = 1; + $TestLevel = 0; # how many extra stack frames to skip + $planned = 0; +} + +$VERSION = '1.25'; +require Exporter; +@ISA=('Exporter'); + +@EXPORT = qw(&plan &ok &skip); +@EXPORT_OK = qw($ntest $TESTOUT $TESTERR); + +$|=1; +$TESTOUT = *STDOUT{IO}; +$TESTERR = *STDERR{IO}; + +# Use of this variable is strongly discouraged. It is set mainly to +# help test coverage analyzers know which test is running. +$ENV{REGRESSION_TEST} = $0; + + +=head1 NAME + +Test - provides a simple framework for writing test scripts + +=head1 SYNOPSIS + + use strict; + use Test; + + # use a BEGIN block so we print our plan before MyModule is loaded + BEGIN { plan tests => 14, todo => [3,4] } + + # load your module... + use MyModule; + + # Helpful notes. All note-lines must start with a "#". + print "# I'm testing MyModule version $MyModule::VERSION\n"; + + ok(0); # failure + ok(1); # success + + ok(0); # ok, expected failure (see todo list, above) + ok(1); # surprise success! + + ok(0,1); # failure: '0' ne '1' + ok('broke','fixed'); # failure: 'broke' ne 'fixed' + ok('fixed','fixed'); # success: 'fixed' eq 'fixed' + ok('fixed',qr/x/); # success: 'fixed' =~ qr/x/ + + ok(sub { 1+1 }, 2); # success: '2' eq '2' + ok(sub { 1+1 }, 3); # failure: '2' ne '3' + + my @list = (0,0); + ok @list, 3, "\@list=".join(',',@list); #extra notes + ok 'segmentation fault', '/(?i)success/'; #regex match + + skip( + $^O =~ m/MSWin/ ? "Skip if MSWin" : 0, # whether to skip + $foo, $bar # arguments just like for ok(...) + ); + skip( + $^O =~ m/MSWin/ ? 0 : "Skip unless MSWin", # whether to skip + $foo, $bar # arguments just like for ok(...) + ); + +=head1 DESCRIPTION + +This module simplifies the task of writing test files for Perl modules, +such that their output is in the format that +L expects to see. + +=head1 QUICK START GUIDE + +To write a test for your new (and probably not even done) module, create +a new file called F (in a new F directory). If you have +multiple test files, to test the "foo", "bar", and "baz" feature sets, +then feel free to call your files F, F, and +F + +=head2 Functions + +This module defines three public functions, C, C, +and C. By default, all three are exported by +the C statement. + +=over 4 + +=item C + + BEGIN { plan %theplan; } + +This should be the first thing you call in your test script. It +declares your testing plan, how many there will be, if any of them +should be allowed to fail, and so on. + +Typical usage is just: + + use Test; + BEGIN { plan tests => 23 } + +These are the things that you can put in the parameters to plan: + +=over + +=item C I> + +The number of tests in your script. +This means all ok() and skip() calls. + +=item C [I<1,5,14>]> + +A reference to a list of tests which are allowed to fail. +See L. + +=item C sub { ... }> + +=item C \&some_sub> + +A subroutine reference to be run at the end of the test script, if +any of the tests fail. See L. + +=back + +You must call C once and only once. You should call it +in a C block, like so: + + BEGIN { plan tests => 23 } + +=cut + +sub plan { + croak "Test::plan(%args): odd number of arguments" if @_ & 1; + croak "Test::plan(): should not be called more than once" if $planned; + + local($\, $,); # guard against -l and other things that screw with + # print + + _reset_globals(); + + _read_program( (caller)[1] ); + + my $max=0; + while (@_) { + my ($k,$v) = splice(@_, 0, 2); + if ($k =~ /^test(s)?$/) { $max = $v; } + elsif ($k eq 'todo' or + $k eq 'failok') { for (@$v) { $todo{$_}=1; }; } + elsif ($k eq 'onfail') { + ref $v eq 'CODE' or croak "Test::plan(onfail => $v): must be CODE"; + $ONFAIL = $v; + } + else { carp "Test::plan(): skipping unrecognized directive '$k'" } + } + my @todo = sort { $a <=> $b } keys %todo; + if (@todo) { + print $TESTOUT "1..$max todo ".join(' ', @todo).";\n"; + } else { + print $TESTOUT "1..$max\n"; + } + ++$planned; + print $TESTOUT "# Running under perl version $] for $^O", + (chr(65) eq 'A') ? "\n" : " in a non-ASCII world\n"; + + print $TESTOUT "# Win32::BuildNumber ", &Win32::BuildNumber(), "\n" + if defined(&Win32::BuildNumber) and defined &Win32::BuildNumber(); + + print $TESTOUT "# MacPerl version $MacPerl::Version\n" + if defined $MacPerl::Version; + + printf $TESTOUT + "# Current time local: %s\n# Current time GMT: %s\n", + scalar(localtime($^T)), scalar(gmtime($^T)); + + print $TESTOUT "# Using Test.pm version $VERSION\n"; + + # Retval never used: + return undef; +} + +sub _read_program { + my($file) = shift; + return unless defined $file and length $file + and -e $file and -f _ and -r _; + open(SOURCEFILE, "<$file") || return; + $Program_Lines{$file} = []; + close(SOURCEFILE); + + foreach my $x (@{$Program_Lines{$file}}) + { $x =~ tr/\cm\cj\n\r//d } + + unshift @{$Program_Lines{$file}}, ''; + return 1; +} + +=begin _private + +=item B<_to_value> + + my $value = _to_value($input); + +Converts an C parameter to its value. Typically this just means +running it, if it's a code reference. You should run all inputted +values through this. + +=cut + +sub _to_value { + my ($v) = @_; + return ref $v eq 'CODE' ? $v->() : $v; +} + +sub _quote { + my $str = $_[0]; + return "" unless defined $str; + $str =~ s/\\/\\\\/g; + $str =~ s/"/\\"/g; + $str =~ s/\a/\\a/g; + $str =~ s/[\b]/\\b/g; + $str =~ s/\e/\\e/g; + $str =~ s/\f/\\f/g; + $str =~ s/\n/\\n/g; + $str =~ s/\r/\\r/g; + $str =~ s/\t/\\t/g; + $str =~ s/([\0-\037])(?!\d)/sprintf('\\%o',ord($1))/eg; + $str =~ s/([\0-\037\177-\377])/sprintf('\\x%02X',ord($1))/eg; + $str =~ s/([^\0-\176])/sprintf('\\x{%X}',ord($1))/eg; + #if( $_[1] ) { + # substr( $str , 218-3 ) = "..." + # if length($str) >= 218 and !$ENV{PERL_TEST_NO_TRUNC}; + #} + return qq("$str"); +} + + +=end _private + +=item C + + ok(1 + 1 == 2); + ok($have, $expect); + ok($have, $expect, $diagnostics); + +This function is the reason for C's existence. It's +the basic function that +handles printing "C" or "C", along with the +current test number. (That's what C wants to see.) + +In its most basic usage, C simply takes a single scalar +expression. If its value is true, the test passes; if false, +the test fails. Examples: + + # Examples of ok(scalar) + + ok( 1 + 1 == 2 ); # ok if 1 + 1 == 2 + ok( $foo =~ /bar/ ); # ok if $foo contains 'bar' + ok( baz($x + $y) eq 'Armondo' ); # ok if baz($x + $y) returns + # 'Armondo' + ok( @a == @b ); # ok if @a and @b are the same length + +The expression is evaluated in scalar context. So the following will +work: + + ok( @stuff ); # ok if @stuff has any elements + ok( !grep !defined $_, @stuff ); # ok if everything in @stuff is + # defined. + +A special case is if the expression is a subroutine reference (in either +C syntax or C<\&foo> syntax). In +that case, it is executed and its value (true or false) determines if +the test passes or fails. For example, + + ok( sub { # See whether sleep works at least passably + my $start_time = time; + sleep 5; + time() - $start_time >= 4 + }); + +In its two-argument form, C, I)> compares the two +scalar values to see if they match. They match if both are undefined, +or if I is a regex that matches I, or if they compare equal +with C. + + # Example of ok(scalar, scalar) + + ok( "this", "that" ); # not ok, 'this' ne 'that' + ok( "", undef ); # not ok, "" is defined + +The second argument is considered a regex if it is either a regex +object or a string that looks like a regex. Regex objects are +constructed with the qr// operator in recent versions of perl. A +string is considered to look like a regex if its first and last +characters are "/", or if the first character is "m" +and its second and last characters are both the +same non-alphanumeric non-whitespace character. These regexp + +Regex examples: + + ok( 'JaffO', '/Jaff/' ); # ok, 'JaffO' =~ /Jaff/ + ok( 'JaffO', 'm|Jaff|' ); # ok, 'JaffO' =~ m|Jaff| + ok( 'JaffO', qr/Jaff/ ); # ok, 'JaffO' =~ qr/Jaff/; + ok( 'JaffO', '/(?i)jaff/ ); # ok, 'JaffO' =~ /jaff/i; + +If either (or both!) is a subroutine reference, it is run and used +as the value for comparing. For example: + + ok sub { + open(OUT, ">x.dat") || die $!; + print OUT "\x{e000}"; + close OUT; + my $bytecount = -s 'x.dat'; + unlink 'x.dat' or warn "Can't unlink : $!"; + return $bytecount; + }, + 4 + ; + +The above test passes two values to C -- the first +a coderef, and the second is the number 4. Before C compares them, +it calls the coderef, and uses its return value as the real value of +this parameter. Assuming that C<$bytecount> returns 4, C ends up +testing C<4 eq 4>. Since that's true, this test passes. + +Finally, you can append an optional third argument, in +C,I, I)>, where I is a string value that +will be printed if the test fails. This should be some useful +information about the test, pertaining to why it failed, and/or +a description of the test. For example: + + ok( grep($_ eq 'something unique', @stuff), 1, + "Something that should be unique isn't!\n". + '@stuff = '.join ', ', @stuff + ); + +Unfortunately, a note cannot be used with the single argument +style of C. That is, if you try C, I)>, then +C will interpret this as C, I)>, and probably +end up testing C eq I> -- and that's not what you want! + +All of the above special cases can occasionally cause some +problems. See L. + +=cut + +# A past maintainer of this module said: +# <> +# + +sub ok ($;$$) { + croak "ok: plan before you test!" if !$planned; + + local($\,$,); # guard against -l and other things that screw with + # print + + my ($pkg,$file,$line) = caller($TestLevel); + my $repetition = ++$history{"$file:$line"}; + my $context = ("$file at line $line". + ($repetition > 1 ? " fail \#$repetition" : '')); + + # Are we comparing two values? + my $compare = 0; + + my $ok=0; + my $result = _to_value(shift); + my ($expected, $isregex, $regex); + if (@_ == 0) { + $ok = $result; + } else { + $compare = 1; + $expected = _to_value(shift); + if (!defined $expected) { + $ok = !defined $result; + } elsif (!defined $result) { + $ok = 0; + } elsif (ref($expected) eq 'Regexp') { + $ok = $result =~ /$expected/; + $regex = $expected; + } elsif (($regex) = ($expected =~ m,^ / (.+) / $,sx) or + (undef, $regex) = ($expected =~ m,^ m([^\w\s]) (.+) \1 $,sx)) { + $ok = $result =~ /$regex/; + } else { + $ok = $result eq $expected; + } + } + my $todo = $todo{$ntest}; + if ($todo and $ok) { + $context .= ' TODO?!' if $todo; + print $TESTOUT "ok $ntest # ($context)\n"; + } else { + # Issuing two seperate prints() causes problems on VMS. + if (!$ok) { + print $TESTOUT "not ok $ntest\n"; + } + else { + print $TESTOUT "ok $ntest\n"; + } + + $ok or _complain($result, $expected, + { + 'repetition' => $repetition, 'package' => $pkg, + 'result' => $result, 'todo' => $todo, + 'file' => $file, 'line' => $line, + 'context' => $context, 'compare' => $compare, + @_ ? ('diagnostic' => _to_value(shift)) : (), + }); + + } + ++ $ntest; + $ok; +} + + +sub _complain { + my($result, $expected, $detail) = @_; + $$detail{expected} = $expected if defined $expected; + + # Get the user's diagnostic, protecting against multi-line + # diagnostics. + my $diag = $$detail{diagnostic}; + $diag =~ s/\n/\n#/g if defined $diag; + + $$detail{context} .= ' *TODO*' if $$detail{todo}; + if (!$$detail{compare}) { + if (!$diag) { + print $TESTERR "# Failed test $ntest in $$detail{context}\n"; + } else { + print $TESTERR "# Failed test $ntest in $$detail{context}: $diag\n"; + } + } else { + my $prefix = "Test $ntest"; + + print $TESTERR "# $prefix got: " . _quote($result) . + " ($$detail{context})\n"; + $prefix = ' ' x (length($prefix) - 5); + my $expected_quoted = (defined $$detail{regex}) + ? 'qr{'.($$detail{regex}).'}' : _quote($expected); + + print $TESTERR "# $prefix Expected: $expected_quoted", + $diag ? " ($diag)" : (), "\n"; + + _diff_complain( $result, $expected, $detail, $prefix ) + if defined($expected) and 2 < ($expected =~ tr/\n//); + } + + if(defined $Program_Lines{ $$detail{file} }[ $$detail{line} ]) { + print $TESTERR + "# $$detail{file} line $$detail{line} is: $Program_Lines{ $$detail{file} }[ $$detail{line} ]\n" + if $Program_Lines{ $$detail{file} }[ $$detail{line} ] + =~ m/[^\s\#\(\)\{\}\[\]\;]/; # Otherwise it's uninformative + + undef $Program_Lines{ $$detail{file} }[ $$detail{line} ]; + # So we won't repeat it. + } + + push @FAILDETAIL, $detail; + return; +} + + + +sub _diff_complain { + my($result, $expected, $detail, $prefix) = @_; + return _diff_complain_external(@_) if $ENV{PERL_TEST_DIFF}; + return _diff_complain_algdiff(@_) + if eval { require Algorithm::Diff; Algorithm::Diff->VERSION(1.15); 1; }; + + $told_about_diff++ or print $TESTERR <<"EOT"; +# $prefix (Install the Algorithm::Diff module to have differences in multiline +# $prefix output explained. You might also set the PERL_TEST_DIFF environment +# $prefix variable to run a diff program on the output.) +EOT + ; + return; +} + + + +sub _diff_complain_external { + my($result, $expected, $detail, $prefix) = @_; + my $diff = $ENV{PERL_TEST_DIFF} || die "WHAAAA?"; + + require File::Temp; + my($got_fh, $got_filename) = File::Temp::tempfile("test-got-XXXXX"); + my($exp_fh, $exp_filename) = File::Temp::tempfile("test-exp-XXXXX"); + unless ($got_fh && $exp_fh) { + warn "Can't get tempfiles"; + return; + } + + print $got_fh $result; + print $exp_fh $expected; + if (close($got_fh) && close($exp_fh)) { + my $diff_cmd = "$diff $exp_filename $got_filename"; + print $TESTERR "#\n# $prefix $diff_cmd\n"; + if (open(DIFF, "$diff_cmd |")) { + local $_; + while () { + print $TESTERR "# $prefix $_"; + } + close(DIFF); + } + else { + warn "Can't run diff: $!"; + } + } else { + warn "Can't write to tempfiles: $!"; + } + unlink($got_filename); + unlink($exp_filename); + return; +} + + + +sub _diff_complain_algdiff { + my($result, $expected, $detail, $prefix) = @_; + + my @got = split(/^/, $result); + my @exp = split(/^/, $expected); + + my $diff_kind; + my @diff_lines; + + my $diff_flush = sub { + return unless $diff_kind; + + my $count_lines = @diff_lines; + my $s = $count_lines == 1 ? "" : "s"; + my $first_line = $diff_lines[0][0] + 1; + + print $TESTERR "# $prefix "; + if ($diff_kind eq "GOT") { + print $TESTERR "Got $count_lines extra line$s at line $first_line:\n"; + for my $i (@diff_lines) { + print $TESTERR "# $prefix + " . _quote($got[$i->[0]]) . "\n"; + } + } elsif ($diff_kind eq "EXP") { + if ($count_lines > 1) { + my $last_line = $diff_lines[-1][0] + 1; + print $TESTERR "Lines $first_line-$last_line are"; + } + else { + print $TESTERR "Line $first_line is"; + } + print $TESTERR " missing:\n"; + for my $i (@diff_lines) { + print $TESTERR "# $prefix - " . _quote($exp[$i->[1]]) . "\n"; + } + } elsif ($diff_kind eq "CH") { + if ($count_lines > 1) { + my $last_line = $diff_lines[-1][0] + 1; + print $TESTERR "Lines $first_line-$last_line are"; + } + else { + print $TESTERR "Line $first_line is"; + } + print $TESTERR " changed:\n"; + for my $i (@diff_lines) { + print $TESTERR "# $prefix - " . _quote($exp[$i->[1]]) . "\n"; + print $TESTERR "# $prefix + " . _quote($got[$i->[0]]) . "\n"; + } + } + + # reset + $diff_kind = undef; + @diff_lines = (); + }; + + my $diff_collect = sub { + my $kind = shift; + &$diff_flush() if $diff_kind && $diff_kind ne $kind; + $diff_kind = $kind; + push(@diff_lines, [@_]); + }; + + + Algorithm::Diff::traverse_balanced( + \@got, \@exp, + { + DISCARD_A => sub { &$diff_collect("GOT", @_) }, + DISCARD_B => sub { &$diff_collect("EXP", @_) }, + CHANGE => sub { &$diff_collect("CH", @_) }, + MATCH => sub { &$diff_flush() }, + }, + ); + &$diff_flush(); + + return; +} + + + + +#~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~ + + +=item C, I)> + +This is used for tests that under some conditions can be skipped. It's +basically equivalent to: + + if( $skip_if_true ) { + ok(1); + } else { + ok( args... ); + } + +...except that the C emits not just "C>" but +actually "C # I>". + +The arguments after the I are what is fed to C if +this test isn't skipped. + +Example usage: + + my $if_MSWin = + $^O =~ m/MSWin/ ? 'Skip if under MSWin' : ''; + + # A test to be skipped if under MSWin (i.e., run except under MSWin) + skip($if_MSWin, thing($foo), thing($bar) ); + +Or, going the other way: + + my $unless_MSWin = + $^O =~ m/MSWin/ ? '' : 'Skip unless under MSWin'; + + # A test to be skipped unless under MSWin (i.e., run only under MSWin) + skip($unless_MSWin, thing($foo), thing($bar) ); + +The tricky thing to remember is that the first parameter is true if +you want to I the test, not I it; and it also doubles as a +note about why it's being skipped. So in the first codeblock above, read +the code as "skip if MSWin -- (otherwise) test whether C is +C" or for the second case, "skip unless MSWin...". + +Also, when your I string is true, it really should (for +backwards compatibility with older Test.pm versions) start with the +string "Skip", as shown in the above examples. + +Note that in the above cases, C and C +I evaluated -- but as long as the C is true, +then we C just tosses out their value (i.e., not +bothering to treat them like values to C. But if +you need to I eval the arguments when skipping the +test, use +this format: + + skip( $unless_MSWin, + sub { + # This code returns true if the test passes. + # (But it doesn't even get called if the test is skipped.) + thing($foo) eq thing($bar) + } + ); + +or even this, which is basically equivalent: + + skip( $unless_MSWin, + sub { thing($foo) }, sub { thing($bar) } + ); + +That is, both are like this: + + if( $unless_MSWin ) { + ok(1); # but it actually appends "# $unless_MSWin" + # so that Test::Harness can tell it's a skip + } else { + # Not skipping, so actually call and evaluate... + ok( sub { thing($foo) }, sub { thing($bar) } ); + } + +=cut + +sub skip ($;$$$) { + local($\, $,); # guard against -l and other things that screw with + # print + + my $whyskip = _to_value(shift); + if (!@_ or $whyskip) { + $whyskip = '' if $whyskip =~ m/^\d+$/; + $whyskip =~ s/^[Ss]kip(?:\s+|$)//; # backwards compatibility, old + # versions required the reason + # to start with 'skip' + # We print in one shot for VMSy reasons. + my $ok = "ok $ntest # skip"; + $ok .= " $whyskip" if length $whyskip; + $ok .= "\n"; + print $TESTOUT $ok; + ++ $ntest; + return 1; + } else { + # backwards compatiblity (I think). skip() used to be + # called like ok(), which is weird. I haven't decided what to do with + # this yet. +# warn <(\@FAILDETAIL) if @FAILDETAIL && $ONFAIL; +} + +1; +__END__ + +=head1 TEST TYPES + +=over 4 + +=item * NORMAL TESTS + +These tests are expected to succeed. Usually, most or all of your tests +are in this category. If a normal test doesn't succeed, then that +means that something is I. + +=item * SKIPPED TESTS + +The C function is for tests that might or might not be +possible to run, depending +on the availability of platform-specific features. The first argument +should evaluate to true (think "yes, please skip") if the required +feature is I available. After the first argument, C works +exactly the same way as C does. + +=item * TODO TESTS + +TODO tests are designed for maintaining an B. +These tests are I If a TODO test does succeed, +then the feature in question shouldn't be on the TODO list, now +should it? + +Packages should NOT be released with succeeding TODO tests. As soon +as a TODO test starts working, it should be promoted to a normal test, +and the newly working feature should be documented in the release +notes or in the change log. + +=back + +=head1 ONFAIL + + BEGIN { plan test => 4, onfail => sub { warn "CALL 911!" } } + +Although test failures should be enough, extra diagnostics can be +triggered at the end of a test run. C is passed an array ref +of hash refs that describe each test failure. Each hash will contain +at least the following fields: C, C, and +C. (You shouldn't rely on any other fields being present.) If the test +had an expected value or a diagnostic (or "note") string, these will also be +included. + +The I C hook might be used simply to print out the +version of your package and/or how to report problems. It might also +be used to generate extremely sophisticated diagnostics for a +particularly bizarre test failure. However it's not a panacea. Core +dumps or other unrecoverable errors prevent the C hook from +running. (It is run inside an C block.) Besides, C is +probably over-kill in most cases. (Your test code should be simpler +than the code it is testing, yes?) + + +=head1 BUGS and CAVEATS + +=over + +=item * + +C's special handing of strings which look like they might be +regexes can also cause unexpected behavior. An innocent: + + ok( $fileglob, '/path/to/some/*stuff/' ); + +will fail, since Test.pm considers the second argument to be a regex! +The best bet is to use the one-argument form: + + ok( $fileglob eq '/path/to/some/*stuff/' ); + +=item * + +C's use of string C can sometimes cause odd problems +when comparing +numbers, especially if you're casting a string to a number: + + $foo = "1.0"; + ok( $foo, 1 ); # not ok, "1.0" ne 1 + +Your best bet is to use the single argument form: + + ok( $foo == 1 ); # ok "1.0" == 1 + +=item * + +As you may have inferred from the above documentation and examples, +C's prototype is C<($;$$)> (and, incidentally, C's is +C<($;$$$)>). This means, for example, that you can do C +to compare the I of the two arrays. But don't be fooled into +thinking that C means a comparison of the contents of two +arrays -- you're comparing I the number of elements of each. It's +so easy to make that mistake in reading C that you might +want to be very explicit about it, and instead write C. + +=item * + +This almost definitely doesn't do what you expect: + + ok $thingy->can('some_method'); + +Why? Because C returns a coderef to mean "yes it can (and the +method is this...)", and then C sees a coderef and thinks you're +passing a function that you want it to call and consider the truth of +the result of! I.e., just like: + + ok $thingy->can('some_method')->(); + +What you probably want instead is this: + + ok $thingy->can('some_method') && 1; + +If the C returns false, then that is passed to C. If it +returns true, then the larger expression S<< C<< +$thingy->can('some_method') && 1 >> >> returns 1, which C sees as +a simple signal of success, as you would expect. + + +=item * + +The syntax for C is about the only way it can be, but it's still +quite confusing. Just start with the above examples and you'll +be okay. + +Moreover, users may expect this: + + skip $unless_mswin, foo($bar), baz($quux); + +to not evaluate C and C when the test is being +skipped. But in reality, they I evaluated, but C just won't +bother comparing them if C<$unless_mswin> is true. + +You could do this: + + skip $unless_mswin, sub{foo($bar)}, sub{baz($quux)}; + +But that's not terribly pretty. You may find it simpler or clearer in +the long run to just do things like this: + + if( $^O =~ m/MSWin/ ) { + print "# Yay, we're under $^O\n"; + ok foo($bar), baz($quux); + ok thing($whatever), baz($stuff); + ok blorp($quux, $whatever); + ok foo($barzbarz), thang($quux); + } else { + print "# Feh, we're under $^O. Watch me skip some tests...\n"; + for(1 .. 4) { skip "Skip unless under MSWin" } + } + +But be quite sure that C is called exactly as many times in the +first block as C is called in the second block. + +=back + + +=head1 ENVIRONMENT + +If C environment variable is set, it will be used as a +command for comparing unexpected multiline results. If you have GNU +diff installed, you might want to set C to C. +If you don't have a suitable program, you might install the +C module and then set C to be C. If C isn't set +but the C module is available, then it will be used +to show the differences in multiline results. + +=for comment +If C is set, then the initial "Got 'something' but +expected 'something_else'" readings for long multiline output values aren't +truncated at about the 230th column, as they normally could be in some +cases. Normally you won't need to use this, unless you were carefully +parsing the output of your test programs. + + +=head1 NOTE + +A past developer of this module once said that it was no longer being +actively developed. However, rumors of its demise were greatly +exaggerated. Feedback and suggestions are quite welcome. + +Be aware that the main value of this module is its simplicity. Note +that there are already more ambitious modules out there, such as +L and L. + +Some earlier versions of this module had docs with some confusing +typoes in the description of C. + + +=head1 SEE ALSO + +L + +L, L, L + +L for building your own testing library. + +L is an interesting XUnit-style testing library. + +L and L let you embed tests in code. + + +=head1 AUTHOR + +Copyright (c) 1998-2000 Joshua Nathaniel Pritikin. All rights reserved. + +Copyright (c) 2001-2002 Michael G. Schwern. + +Copyright (c) 2002-2004 and counting Sean M. Burke. + +Current maintainer: Sean M. Burke. Esburke@cpan.orgE + +This package is free software and is provided "as is" without express +or implied warranty. It may be used, redistributed and/or modified +under the same terms as Perl itself. + +=cut + +# "Your mistake was a hidden intention." +# -- /Oblique Strategies/, Brian Eno and Peter Schmidt diff --git a/SecurityTests/regressions/inc/Test/Builder.pm b/SecurityTests/regressions/inc/Test/Builder.pm new file mode 100644 index 00000000..1a2cdb03 --- /dev/null +++ b/SecurityTests/regressions/inc/Test/Builder.pm @@ -0,0 +1,1873 @@ +package Test::Builder; + +use 5.006; +use strict; + +our $VERSION = '0.80'; +$VERSION = eval { $VERSION }; # make the alpha version come out as a number + +# Make Test::Builder thread-safe for ithreads. +BEGIN { + use Config; + # Load threads::shared when threads are turned on. + # 5.8.0's threads are so busted we no longer support them. + if( $] >= 5.008001 && $Config{useithreads} && $INC{'threads.pm'}) { + require threads::shared; + + # Hack around YET ANOTHER threads::shared bug. It would + # occassionally forget the contents of the variable when sharing it. + # So we first copy the data, then share, then put our copy back. + *share = sub (\[$@%]) { + my $type = ref $_[0]; + my $data; + + if( $type eq 'HASH' ) { + %$data = %{$_[0]}; + } + elsif( $type eq 'ARRAY' ) { + @$data = @{$_[0]}; + } + elsif( $type eq 'SCALAR' ) { + $$data = ${$_[0]}; + } + else { + die("Unknown type: ".$type); + } + + $_[0] = &threads::shared::share($_[0]); + + if( $type eq 'HASH' ) { + %{$_[0]} = %$data; + } + elsif( $type eq 'ARRAY' ) { + @{$_[0]} = @$data; + } + elsif( $type eq 'SCALAR' ) { + ${$_[0]} = $$data; + } + else { + die("Unknown type: ".$type); + } + + return $_[0]; + }; + } + # 5.8.0's threads::shared is busted when threads are off + # and earlier Perls just don't have that module at all. + else { + *share = sub { return $_[0] }; + *lock = sub { 0 }; + } +} + + +=head1 NAME + +Test::Builder - Backend for building test libraries + +=head1 SYNOPSIS + + package My::Test::Module; + use base 'Test::Builder::Module'; + + my $CLASS = __PACKAGE__; + + sub ok { + my($test, $name) = @_; + my $tb = $CLASS->builder; + + $tb->ok($test, $name); + } + + +=head1 DESCRIPTION + +Test::Simple and Test::More have proven to be popular testing modules, +but they're not always flexible enough. Test::Builder provides the a +building block upon which to write your own test libraries I. + +=head2 Construction + +=over 4 + +=item B + + my $Test = Test::Builder->new; + +Returns a Test::Builder object representing the current state of the +test. + +Since you only run one test per program C always returns the same +Test::Builder object. No matter how many times you call new(), you're +getting the same object. This is called a singleton. This is done so that +multiple modules share such global information as the test counter and +where test output is going. + +If you want a completely new Test::Builder object different from the +singleton, use C. + +=cut + +my $Test = Test::Builder->new; +sub new { + my($class) = shift; + $Test ||= $class->create; + return $Test; +} + + +=item B + + my $Test = Test::Builder->create; + +Ok, so there can be more than one Test::Builder object and this is how +you get it. You might use this instead of C if you're testing +a Test::Builder based module, but otherwise you probably want C. + +B: the implementation is not complete. C, for example, is +still shared amongst B Test::Builder objects, even ones created using +this method. Also, the method name may change in the future. + +=cut + +sub create { + my $class = shift; + + my $self = bless {}, $class; + $self->reset; + + return $self; +} + +=item B + + $Test->reset; + +Reinitializes the Test::Builder singleton to its original state. +Mostly useful for tests run in persistent environments where the same +test might be run multiple times in the same process. + +=cut + +use vars qw($Level); + +sub reset { + my ($self) = @_; + + # We leave this a global because it has to be localized and localizing + # hash keys is just asking for pain. Also, it was documented. + $Level = 1; + + $self->{Have_Plan} = 0; + $self->{No_Plan} = 0; + $self->{Original_Pid} = $$; + + share($self->{Curr_Test}); + $self->{Curr_Test} = 0; + $self->{Test_Results} = &share([]); + + $self->{Exported_To} = undef; + $self->{Expected_Tests} = 0; + + $self->{Skip_All} = 0; + + $self->{Use_Nums} = 1; + + $self->{No_Header} = 0; + $self->{No_Ending} = 0; + + $self->{TODO} = undef; + + $self->_dup_stdhandles unless $^C; + + return; +} + +=back + +=head2 Setting up tests + +These methods are for setting up tests and declaring how many there +are. You usually only want to call one of these methods. + +=over 4 + +=item B + + $Test->plan('no_plan'); + $Test->plan( skip_all => $reason ); + $Test->plan( tests => $num_tests ); + +A convenient way to set up your tests. Call this and Test::Builder +will print the appropriate headers and take the appropriate actions. + +If you call plan(), don't call any of the other methods below. + +=cut + +sub plan { + my($self, $cmd, $arg) = @_; + + return unless $cmd; + + local $Level = $Level + 1; + + if( $self->{Have_Plan} ) { + $self->croak("You tried to plan twice"); + } + + if( $cmd eq 'no_plan' ) { + $self->no_plan; + } + elsif( $cmd eq 'skip_all' ) { + return $self->skip_all($arg); + } + elsif( $cmd eq 'tests' ) { + if( $arg ) { + local $Level = $Level + 1; + return $self->expected_tests($arg); + } + elsif( !defined $arg ) { + $self->croak("Got an undefined number of tests"); + } + elsif( !$arg ) { + $self->croak("You said to run 0 tests"); + } + } + else { + my @args = grep { defined } ($cmd, $arg); + $self->croak("plan() doesn't understand @args"); + } + + return 1; +} + +=item B + + my $max = $Test->expected_tests; + $Test->expected_tests($max); + +Gets/sets the # of tests we expect this test to run and prints out +the appropriate headers. + +=cut + +sub expected_tests { + my $self = shift; + my($max) = @_; + + if( @_ ) { + $self->croak("Number of tests must be a positive integer. You gave it '$max'") + unless $max =~ /^\+?\d+$/ and $max > 0; + + $self->{Expected_Tests} = $max; + $self->{Have_Plan} = 1; + + $self->_print("1..$max\n") unless $self->no_header; + } + return $self->{Expected_Tests}; +} + + +=item B + + $Test->no_plan; + +Declares that this test will run an indeterminate # of tests. + +=cut + +sub no_plan { + my $self = shift; + + $self->{No_Plan} = 1; + $self->{Have_Plan} = 1; +} + +=item B + + $plan = $Test->has_plan + +Find out whether a plan has been defined. $plan is either C (no plan has been set), C (indeterminate # of tests) or an integer (the number of expected tests). + +=cut + +sub has_plan { + my $self = shift; + + return($self->{Expected_Tests}) if $self->{Expected_Tests}; + return('no_plan') if $self->{No_Plan}; + return(undef); +}; + + +=item B + + $Test->skip_all; + $Test->skip_all($reason); + +Skips all the tests, using the given $reason. Exits immediately with 0. + +=cut + +sub skip_all { + my($self, $reason) = @_; + + my $out = "1..0"; + $out .= " # Skip $reason" if $reason; + $out .= "\n"; + + $self->{Skip_All} = 1; + + $self->_print($out) unless $self->no_header; + exit(0); +} + + +=item B + + my $pack = $Test->exported_to; + $Test->exported_to($pack); + +Tells Test::Builder what package you exported your functions to. + +This method isn't terribly useful since modules which share the same +Test::Builder object might get exported to different packages and only +the last one will be honored. + +=cut + +sub exported_to { + my($self, $pack) = @_; + + if( defined $pack ) { + $self->{Exported_To} = $pack; + } + return $self->{Exported_To}; +} + +=back + +=head2 Running tests + +These actually run the tests, analogous to the functions in Test::More. + +They all return true if the test passed, false if the test failed. + +$name is always optional. + +=over 4 + +=item B + + $Test->ok($test, $name); + +Your basic test. Pass if $test is true, fail if $test is false. Just +like Test::Simple's ok(). + +=cut + +sub ok { + my($self, $test, $name) = @_; + + # $test might contain an object which we don't want to accidentally + # store, so we turn it into a boolean. + $test = $test ? 1 : 0; + + $self->_plan_check; + + lock $self->{Curr_Test}; + $self->{Curr_Test}++; + + # In case $name is a string overloaded object, force it to stringify. + $self->_unoverload_str(\$name); + + $self->diag(<todo(); + + # Capture the value of $TODO for the rest of this ok() call + # so it can more easily be found by other routines. + local $self->{TODO} = $todo; + + $self->_unoverload_str(\$todo); + + my $out; + my $result = &share({}); + + unless( $test ) { + $out .= "not "; + @$result{ 'ok', 'actual_ok' } = ( ( $todo ? 1 : 0 ), 0 ); + } + else { + @$result{ 'ok', 'actual_ok' } = ( 1, $test ); + } + + $out .= "ok"; + $out .= " $self->{Curr_Test}" if $self->use_numbers; + + if( defined $name ) { + $name =~ s|#|\\#|g; # # in a name can confuse Test::Harness. + $out .= " - $name"; + $result->{name} = $name; + } + else { + $result->{name} = ''; + } + + if( $todo ) { + $out .= " # TODO $todo"; + $result->{reason} = $todo; + $result->{type} = 'todo'; + } + else { + $result->{reason} = ''; + $result->{type} = ''; + } + + $self->{Test_Results}[$self->{Curr_Test}-1] = $result; + $out .= "\n"; + + $self->_print($out); + + unless( $test ) { + my $msg = $todo ? "Failed (TODO)" : "Failed"; + $self->_print_diag("\n") if $ENV{HARNESS_ACTIVE}; + + my(undef, $file, $line) = $self->caller; + if( defined $name ) { + $self->diag(qq[ $msg test '$name'\n]); + $self->diag(qq[ at $file line $line.\n]); + } + else { + $self->diag(qq[ $msg test at $file line $line.\n]); + } + } + + return $test ? 1 : 0; +} + + +sub _unoverload { + my $self = shift; + my $type = shift; + + $self->_try(sub { require overload } ) || return; + + foreach my $thing (@_) { + if( $self->_is_object($$thing) ) { + if( my $string_meth = overload::Method($$thing, $type) ) { + $$thing = $$thing->$string_meth(); + } + } + } +} + + +sub _is_object { + my($self, $thing) = @_; + + return $self->_try(sub { ref $thing && $thing->isa('UNIVERSAL') }) ? 1 : 0; +} + + +sub _unoverload_str { + my $self = shift; + + $self->_unoverload(q[""], @_); +} + +sub _unoverload_num { + my $self = shift; + + $self->_unoverload('0+', @_); + + for my $val (@_) { + next unless $self->_is_dualvar($$val); + $$val = $$val+0; + } +} + + +# This is a hack to detect a dualvar such as $! +sub _is_dualvar { + my($self, $val) = @_; + + local $^W = 0; + my $numval = $val+0; + return 1 if $numval != 0 and $numval ne $val; +} + + + +=item B + + $Test->is_eq($got, $expected, $name); + +Like Test::More's is(). Checks if $got eq $expected. This is the +string version. + +=item B + + $Test->is_num($got, $expected, $name); + +Like Test::More's is(). Checks if $got == $expected. This is the +numeric version. + +=cut + +sub is_eq { + my($self, $got, $expect, $name) = @_; + local $Level = $Level + 1; + + $self->_unoverload_str(\$got, \$expect); + + if( !defined $got || !defined $expect ) { + # undef only matches undef and nothing else + my $test = !defined $got && !defined $expect; + + $self->ok($test, $name); + $self->_is_diag($got, 'eq', $expect) unless $test; + return $test; + } + + return $self->cmp_ok($got, 'eq', $expect, $name); +} + +sub is_num { + my($self, $got, $expect, $name) = @_; + local $Level = $Level + 1; + + $self->_unoverload_num(\$got, \$expect); + + if( !defined $got || !defined $expect ) { + # undef only matches undef and nothing else + my $test = !defined $got && !defined $expect; + + $self->ok($test, $name); + $self->_is_diag($got, '==', $expect) unless $test; + return $test; + } + + return $self->cmp_ok($got, '==', $expect, $name); +} + +sub _is_diag { + my($self, $got, $type, $expect) = @_; + + foreach my $val (\$got, \$expect) { + if( defined $$val ) { + if( $type eq 'eq' ) { + # quote and force string context + $$val = "'$$val'" + } + else { + # force numeric context + $self->_unoverload_num($val); + } + } + else { + $$val = 'undef'; + } + } + + local $Level = $Level + 1; + return $self->diag(sprintf < + + $Test->isnt_eq($got, $dont_expect, $name); + +Like Test::More's isnt(). Checks if $got ne $dont_expect. This is +the string version. + +=item B + + $Test->isnt_num($got, $dont_expect, $name); + +Like Test::More's isnt(). Checks if $got ne $dont_expect. This is +the numeric version. + +=cut + +sub isnt_eq { + my($self, $got, $dont_expect, $name) = @_; + local $Level = $Level + 1; + + if( !defined $got || !defined $dont_expect ) { + # undef only matches undef and nothing else + my $test = defined $got || defined $dont_expect; + + $self->ok($test, $name); + $self->_cmp_diag($got, 'ne', $dont_expect) unless $test; + return $test; + } + + return $self->cmp_ok($got, 'ne', $dont_expect, $name); +} + +sub isnt_num { + my($self, $got, $dont_expect, $name) = @_; + local $Level = $Level + 1; + + if( !defined $got || !defined $dont_expect ) { + # undef only matches undef and nothing else + my $test = defined $got || defined $dont_expect; + + $self->ok($test, $name); + $self->_cmp_diag($got, '!=', $dont_expect) unless $test; + return $test; + } + + return $self->cmp_ok($got, '!=', $dont_expect, $name); +} + + +=item B + + $Test->like($this, qr/$regex/, $name); + $Test->like($this, '/$regex/', $name); + +Like Test::More's like(). Checks if $this matches the given $regex. + +You'll want to avoid qr// if you want your tests to work before 5.005. + +=item B + + $Test->unlike($this, qr/$regex/, $name); + $Test->unlike($this, '/$regex/', $name); + +Like Test::More's unlike(). Checks if $this B the +given $regex. + +=cut + +sub like { + my($self, $this, $regex, $name) = @_; + + local $Level = $Level + 1; + $self->_regex_ok($this, $regex, '=~', $name); +} + +sub unlike { + my($self, $this, $regex, $name) = @_; + + local $Level = $Level + 1; + $self->_regex_ok($this, $regex, '!~', $name); +} + + +=item B + + $Test->cmp_ok($this, $type, $that, $name); + +Works just like Test::More's cmp_ok(). + + $Test->cmp_ok($big_num, '!=', $other_big_num); + +=cut + + +my %numeric_cmps = map { ($_, 1) } + ("<", "<=", ">", ">=", "==", "!=", "<=>"); + +sub cmp_ok { + my($self, $got, $type, $expect, $name) = @_; + + # Treat overloaded objects as numbers if we're asked to do a + # numeric comparison. + my $unoverload = $numeric_cmps{$type} ? '_unoverload_num' + : '_unoverload_str'; + + $self->$unoverload(\$got, \$expect); + + + my $test; + { + local($@,$!,$SIG{__DIE__}); # isolate eval + + my $code = $self->_caller_context; + + # Yes, it has to look like this or 5.4.5 won't see the #line + # directive. + # Don't ask me, man, I just work here. + $test = eval " +$code" . "\$got $type \$expect;"; + + } + local $Level = $Level + 1; + my $ok = $self->ok($test, $name); + + unless( $ok ) { + if( $type =~ /^(eq|==)$/ ) { + $self->_is_diag($got, $type, $expect); + } + else { + $self->_cmp_diag($got, $type, $expect); + } + } + return $ok; +} + +sub _cmp_diag { + my($self, $got, $type, $expect) = @_; + + $got = defined $got ? "'$got'" : 'undef'; + $expect = defined $expect ? "'$expect'" : 'undef'; + + local $Level = $Level + 1; + return $self->diag(sprintf <caller(1); + + my $code = ''; + $code .= "#line $line $file\n" if defined $file and defined $line; + + return $code; +} + +=back + + +=head2 Other Testing Methods + +These are methods which are used in the course of writing a test but are not themselves tests. + +=over 4 + +=item B + + $Test->BAIL_OUT($reason); + +Indicates to the Test::Harness that things are going so badly all +testing should terminate. This includes running any additional test +scripts. + +It will exit with 255. + +=cut + +sub BAIL_OUT { + my($self, $reason) = @_; + + $self->{Bailed_Out} = 1; + $self->_print("Bail out! $reason"); + exit 255; +} + +=for deprecated +BAIL_OUT() used to be BAILOUT() + +=cut + +*BAILOUT = \&BAIL_OUT; + + +=item B + + $Test->skip; + $Test->skip($why); + +Skips the current test, reporting $why. + +=cut + +sub skip { + my($self, $why) = @_; + $why ||= ''; + $self->_unoverload_str(\$why); + + $self->_plan_check; + + lock($self->{Curr_Test}); + $self->{Curr_Test}++; + + $self->{Test_Results}[$self->{Curr_Test}-1] = &share({ + 'ok' => 1, + actual_ok => 1, + name => '', + type => 'skip', + reason => $why, + }); + + my $out = "ok"; + $out .= " $self->{Curr_Test}" if $self->use_numbers; + $out .= " # skip"; + $out .= " $why" if length $why; + $out .= "\n"; + + $self->_print($out); + + return 1; +} + + +=item B + + $Test->todo_skip; + $Test->todo_skip($why); + +Like skip(), only it will declare the test as failing and TODO. Similar +to + + print "not ok $tnum # TODO $why\n"; + +=cut + +sub todo_skip { + my($self, $why) = @_; + $why ||= ''; + + $self->_plan_check; + + lock($self->{Curr_Test}); + $self->{Curr_Test}++; + + $self->{Test_Results}[$self->{Curr_Test}-1] = &share({ + 'ok' => 1, + actual_ok => 0, + name => '', + type => 'todo_skip', + reason => $why, + }); + + my $out = "not ok"; + $out .= " $self->{Curr_Test}" if $self->use_numbers; + $out .= " # TODO & SKIP $why\n"; + + $self->_print($out); + + return 1; +} + + +=begin _unimplemented + +=item B + + $Test->skip_rest; + $Test->skip_rest($reason); + +Like skip(), only it skips all the rest of the tests you plan to run +and terminates the test. + +If you're running under no_plan, it skips once and terminates the +test. + +=end _unimplemented + +=back + + +=head2 Test building utility methods + +These methods are useful when writing your own test methods. + +=over 4 + +=item B + + $Test->maybe_regex(qr/$regex/); + $Test->maybe_regex('/$regex/'); + +Convenience method for building testing functions that take regular +expressions as arguments, but need to work before perl 5.005. + +Takes a quoted regular expression produced by qr//, or a string +representing a regular expression. + +Returns a Perl value which may be used instead of the corresponding +regular expression, or undef if it's argument is not recognised. + +For example, a version of like(), sans the useful diagnostic messages, +could be written as: + + sub laconic_like { + my ($self, $this, $regex, $name) = @_; + my $usable_regex = $self->maybe_regex($regex); + die "expecting regex, found '$regex'\n" + unless $usable_regex; + $self->ok($this =~ m/$usable_regex/, $name); + } + +=cut + + +sub maybe_regex { + my ($self, $regex) = @_; + my $usable_regex = undef; + + return $usable_regex unless defined $regex; + + my($re, $opts); + + # Check for qr/foo/ + if( _is_qr($regex) ) { + $usable_regex = $regex; + } + # Check for '/foo/' or 'm,foo,' + elsif( ($re, $opts) = $regex =~ m{^ /(.*)/ (\w*) $ }sx or + (undef, $re, $opts) = $regex =~ m,^ m([^\w\s]) (.+) \1 (\w*) $,sx + ) + { + $usable_regex = length $opts ? "(?$opts)$re" : $re; + } + + return $usable_regex; +} + + +sub _is_qr { + my $regex = shift; + + # is_regexp() checks for regexes in a robust manner, say if they're + # blessed. + return re::is_regexp($regex) if defined &re::is_regexp; + return ref $regex eq 'Regexp'; +} + + +sub _regex_ok { + my($self, $this, $regex, $cmp, $name) = @_; + + my $ok = 0; + my $usable_regex = $self->maybe_regex($regex); + unless (defined $usable_regex) { + $ok = $self->ok( 0, $name ); + $self->diag(" '$regex' doesn't look much like a regex to me."); + return $ok; + } + + { + my $test; + my $code = $self->_caller_context; + + local($@, $!, $SIG{__DIE__}); # isolate eval + + # Yes, it has to look like this or 5.4.5 won't see the #line + # directive. + # Don't ask me, man, I just work here. + $test = eval " +$code" . q{$test = $this =~ /$usable_regex/ ? 1 : 0}; + + $test = !$test if $cmp eq '!~'; + + local $Level = $Level + 1; + $ok = $self->ok( $test, $name ); + } + + unless( $ok ) { + $this = defined $this ? "'$this'" : 'undef'; + my $match = $cmp eq '=~' ? "doesn't match" : "matches"; + + local $Level = $Level + 1; + $self->diag(sprintf < + + my $return_from_code = $Test->try(sub { code }); + my($return_from_code, $error) = $Test->try(sub { code }); + +Works like eval BLOCK except it ensures it has no effect on the rest of the test (ie. $@ is not set) nor is effected by outside interference (ie. $SIG{__DIE__}) and works around some quirks in older Perls. + +$error is what would normally be in $@. + +It is suggested you use this in place of eval BLOCK. + +=cut + +sub _try { + my($self, $code) = @_; + + local $!; # eval can mess up $! + local $@; # don't set $@ in the test + local $SIG{__DIE__}; # don't trip an outside DIE handler. + my $return = eval { $code->() }; + + return wantarray ? ($return, $@) : $return; +} + +=end private + + +=item B + + my $is_fh = $Test->is_fh($thing); + +Determines if the given $thing can be used as a filehandle. + +=cut + +sub is_fh { + my $self = shift; + my $maybe_fh = shift; + return 0 unless defined $maybe_fh; + + return 1 if ref $maybe_fh eq 'GLOB'; # its a glob ref + return 1 if ref \$maybe_fh eq 'GLOB'; # its a glob + + return eval { $maybe_fh->isa("IO::Handle") } || + # 5.5.4's tied() and can() doesn't like getting undef + eval { (tied($maybe_fh) || '')->can('TIEHANDLE') }; +} + + +=back + + +=head2 Test style + + +=over 4 + +=item B + + $Test->level($how_high); + +How far up the call stack should $Test look when reporting where the +test failed. + +Defaults to 1. + +Setting L<$Test::Builder::Level> overrides. This is typically useful +localized: + + sub my_ok { + my $test = shift; + + local $Test::Builder::Level = $Test::Builder::Level + 1; + $TB->ok($test); + } + +To be polite to other functions wrapping your own you usually want to increment C<$Level> rather than set it to a constant. + +=cut + +sub level { + my($self, $level) = @_; + + if( defined $level ) { + $Level = $level; + } + return $Level; +} + + +=item B + + $Test->use_numbers($on_or_off); + +Whether or not the test should output numbers. That is, this if true: + + ok 1 + ok 2 + ok 3 + +or this if false + + ok + ok + ok + +Most useful when you can't depend on the test output order, such as +when threads or forking is involved. + +Defaults to on. + +=cut + +sub use_numbers { + my($self, $use_nums) = @_; + + if( defined $use_nums ) { + $self->{Use_Nums} = $use_nums; + } + return $self->{Use_Nums}; +} + + +=item B + + $Test->no_diag($no_diag); + +If set true no diagnostics will be printed. This includes calls to +diag(). + +=item B + + $Test->no_ending($no_ending); + +Normally, Test::Builder does some extra diagnostics when the test +ends. It also changes the exit code as described below. + +If this is true, none of that will be done. + +=item B + + $Test->no_header($no_header); + +If set to true, no "1..N" header will be printed. + +=cut + +foreach my $attribute (qw(No_Header No_Ending No_Diag)) { + my $method = lc $attribute; + + my $code = sub { + my($self, $no) = @_; + + if( defined $no ) { + $self->{$attribute} = $no; + } + return $self->{$attribute}; + }; + + no strict 'refs'; ## no critic + *{__PACKAGE__.'::'.$method} = $code; +} + + +=back + +=head2 Output + +Controlling where the test output goes. + +It's ok for your test to change where STDOUT and STDERR point to, +Test::Builder's default output settings will not be affected. + +=over 4 + +=item B + + $Test->diag(@msgs); + +Prints out the given @msgs. Like C, arguments are simply +appended together. + +Normally, it uses the failure_output() handle, but if this is for a +TODO test, the todo_output() handle is used. + +Output will be indented and marked with a # so as not to interfere +with test output. A newline will be put on the end if there isn't one +already. + +We encourage using this rather than calling print directly. + +Returns false. Why? Because diag() is often used in conjunction with +a failing test (C) it "passes through" the failure. + + return ok(...) || diag(...); + +=for blame transfer +Mark Fowler + +=cut + +sub diag { + my($self, @msgs) = @_; + + return if $self->no_diag; + return unless @msgs; + + # Prevent printing headers when compiling (i.e. -c) + return if $^C; + + # Smash args together like print does. + # Convert undef to 'undef' so its readable. + my $msg = join '', map { defined($_) ? $_ : 'undef' } @msgs; + + # Escape each line with a #. + $msg =~ s/^/# /gm; + + # Stick a newline on the end if it needs it. + $msg .= "\n" unless $msg =~ /\n\Z/; + + local $Level = $Level + 1; + $self->_print_diag($msg); + + return 0; +} + +=begin _private + +=item B<_print> + + $Test->_print(@msgs); + +Prints to the output() filehandle. + +=end _private + +=cut + +sub _print { + my($self, @msgs) = @_; + + # Prevent printing headers when only compiling. Mostly for when + # tests are deparsed with B::Deparse + return if $^C; + + my $msg = join '', @msgs; + + local($\, $", $,) = (undef, ' ', ''); + my $fh = $self->output; + + # Escape each line after the first with a # so we don't + # confuse Test::Harness. + $msg =~ s/\n(.)/\n# $1/sg; + + # Stick a newline on the end if it needs it. + $msg .= "\n" unless $msg =~ /\n\Z/; + + print $fh $msg; +} + +=begin private + +=item B<_print_diag> + + $Test->_print_diag(@msg); + +Like _print, but prints to the current diagnostic filehandle. + +=end private + +=cut + +sub _print_diag { + my $self = shift; + + local($\, $", $,) = (undef, ' ', ''); + my $fh = $self->todo ? $self->todo_output : $self->failure_output; + print $fh @_; +} + +=item B + + $Test->output($fh); + $Test->output($file); + +Where normal "ok/not ok" test output should go. + +Defaults to STDOUT. + +=item B + + $Test->failure_output($fh); + $Test->failure_output($file); + +Where diagnostic output on test failures and diag() should go. + +Defaults to STDERR. + +=item B + + $Test->todo_output($fh); + $Test->todo_output($file); + +Where diagnostics about todo test failures and diag() should go. + +Defaults to STDOUT. + +=cut + +sub output { + my($self, $fh) = @_; + + if( defined $fh ) { + $self->{Out_FH} = $self->_new_fh($fh); + } + return $self->{Out_FH}; +} + +sub failure_output { + my($self, $fh) = @_; + + if( defined $fh ) { + $self->{Fail_FH} = $self->_new_fh($fh); + } + return $self->{Fail_FH}; +} + +sub todo_output { + my($self, $fh) = @_; + + if( defined $fh ) { + $self->{Todo_FH} = $self->_new_fh($fh); + } + return $self->{Todo_FH}; +} + + +sub _new_fh { + my $self = shift; + my($file_or_fh) = shift; + + my $fh; + if( $self->is_fh($file_or_fh) ) { + $fh = $file_or_fh; + } + else { + open $fh, ">", $file_or_fh or + $self->croak("Can't open test output log $file_or_fh: $!"); + _autoflush($fh); + } + + return $fh; +} + + +sub _autoflush { + my($fh) = shift; + my $old_fh = select $fh; + $| = 1; + select $old_fh; +} + + +my($Testout, $Testerr); +sub _dup_stdhandles { + my $self = shift; + + $self->_open_testhandles; + + # Set everything to unbuffered else plain prints to STDOUT will + # come out in the wrong order from our own prints. + _autoflush($Testout); + _autoflush(\*STDOUT); + _autoflush($Testerr); + _autoflush(\*STDERR); + + $self->output ($Testout); + $self->failure_output($Testerr); + $self->todo_output ($Testout); +} + + +my $Opened_Testhandles = 0; +sub _open_testhandles { + my $self = shift; + + return if $Opened_Testhandles; + + # We dup STDOUT and STDERR so people can change them in their + # test suites while still getting normal test output. + open( $Testout, ">&STDOUT") or die "Can't dup STDOUT: $!"; + open( $Testerr, ">&STDERR") or die "Can't dup STDERR: $!"; + +# $self->_copy_io_layers( \*STDOUT, $Testout ); +# $self->_copy_io_layers( \*STDERR, $Testerr ); + + $Opened_Testhandles = 1; +} + + +sub _copy_io_layers { + my($self, $src, $dst) = @_; + + $self->_try(sub { + require PerlIO; + my @src_layers = PerlIO::get_layers($src); + + binmode $dst, join " ", map ":$_", @src_layers if @src_layers; + }); +} + +=item carp + + $tb->carp(@message); + +Warns with C<@message> but the message will appear to come from the +point where the original test function was called (C<$tb->caller>). + +=item croak + + $tb->croak(@message); + +Dies with C<@message> but the message will appear to come from the +point where the original test function was called (C<$tb->caller>). + +=cut + +sub _message_at_caller { + my $self = shift; + + local $Level = $Level + 1; + my($pack, $file, $line) = $self->caller; + return join("", @_) . " at $file line $line.\n"; +} + +sub carp { + my $self = shift; + warn $self->_message_at_caller(@_); +} + +sub croak { + my $self = shift; + die $self->_message_at_caller(@_); +} + +sub _plan_check { + my $self = shift; + + unless( $self->{Have_Plan} ) { + local $Level = $Level + 2; + $self->croak("You tried to run a test without a plan"); + } +} + +=back + + +=head2 Test Status and Info + +=over 4 + +=item B + + my $curr_test = $Test->current_test; + $Test->current_test($num); + +Gets/sets the current test number we're on. You usually shouldn't +have to set this. + +If set forward, the details of the missing tests are filled in as 'unknown'. +if set backward, the details of the intervening tests are deleted. You +can erase history if you really want to. + +=cut + +sub current_test { + my($self, $num) = @_; + + lock($self->{Curr_Test}); + if( defined $num ) { + unless( $self->{Have_Plan} ) { + $self->croak("Can't change the current test number without a plan!"); + } + + $self->{Curr_Test} = $num; + + # If the test counter is being pushed forward fill in the details. + my $test_results = $self->{Test_Results}; + if( $num > @$test_results ) { + my $start = @$test_results ? @$test_results : 0; + for ($start..$num-1) { + $test_results->[$_] = &share({ + 'ok' => 1, + actual_ok => undef, + reason => 'incrementing test number', + type => 'unknown', + name => undef + }); + } + } + # If backward, wipe history. Its their funeral. + elsif( $num < @$test_results ) { + $#{$test_results} = $num - 1; + } + } + return $self->{Curr_Test}; +} + + +=item B

    + + my @tests = $Test->summary; + +A simple summary of the tests so far. True for pass, false for fail. +This is a logical pass/fail, so todos are passes. + +Of course, test #1 is $tests[0], etc... + +=cut + +sub summary { + my($self) = shift; + + return map { $_->{'ok'} } @{ $self->{Test_Results} }; +} + +=item B
    + + my @tests = $Test->details; + +Like summary(), but with a lot more detail. + + $tests[$test_num - 1] = + { 'ok' => is the test considered a pass? + actual_ok => did it literally say 'ok'? + name => name of the test (if any) + type => type of test (if any, see below). + reason => reason for the above (if any) + }; + +'ok' is true if Test::Harness will consider the test to be a pass. + +'actual_ok' is a reflection of whether or not the test literally +printed 'ok' or 'not ok'. This is for examining the result of 'todo' +tests. + +'name' is the name of the test. + +'type' indicates if it was a special test. Normal tests have a type +of ''. Type can be one of the following: + + skip see skip() + todo see todo() + todo_skip see todo_skip() + unknown see below + +Sometimes the Test::Builder test counter is incremented without it +printing any test output, for example, when current_test() is changed. +In these cases, Test::Builder doesn't know the result of the test, so +it's type is 'unkown'. These details for these tests are filled in. +They are considered ok, but the name and actual_ok is left undef. + +For example "not ok 23 - hole count # TODO insufficient donuts" would +result in this structure: + + $tests[22] = # 23 - 1, since arrays start from 0. + { ok => 1, # logically, the test passed since it's todo + actual_ok => 0, # in absolute terms, it failed + name => 'hole count', + type => 'todo', + reason => 'insufficient donuts' + }; + +=cut + +sub details { + my $self = shift; + return @{ $self->{Test_Results} }; +} + +=item B + + my $todo_reason = $Test->todo; + my $todo_reason = $Test->todo($pack); + +todo() looks for a $TODO variable in your tests. If set, all tests +will be considered 'todo' (see Test::More and Test::Harness for +details). Returns the reason (ie. the value of $TODO) if running as +todo tests, false otherwise. + +todo() is about finding the right package to look for $TODO in. It's +pretty good at guessing the right package to look at. It first looks for +the caller based on C<$Level + 1>, since C is usually called inside +a test function. As a last resort it will use C. + +Sometimes there is some confusion about where todo() should be looking +for the $TODO variable. If you want to be sure, tell it explicitly +what $pack to use. + +=cut + +sub todo { + my($self, $pack) = @_; + + return $self->{TODO} if defined $self->{TODO}; + + $pack = $pack || $self->caller(1) || $self->exported_to; + return 0 unless $pack; + + no strict 'refs'; ## no critic + return defined ${$pack.'::TODO'} ? ${$pack.'::TODO'} + : 0; +} + +=item B + + my $package = $Test->caller; + my($pack, $file, $line) = $Test->caller; + my($pack, $file, $line) = $Test->caller($height); + +Like the normal caller(), except it reports according to your level(). + +C<$height> will be added to the level(). + +=cut + +sub caller { + my($self, $height) = @_; + $height ||= 0; + + my @caller = CORE::caller($self->level + $height + 1); + return wantarray ? @caller : $caller[0]; +} + +=back + +=cut + +=begin _private + +=over 4 + +=item B<_sanity_check> + + $self->_sanity_check(); + +Runs a bunch of end of test sanity checks to make sure reality came +through ok. If anything is wrong it will die with a fairly friendly +error message. + +=cut + +#'# +sub _sanity_check { + my $self = shift; + + $self->_whoa($self->{Curr_Test} < 0, 'Says here you ran a negative number of tests!'); + $self->_whoa(!$self->{Have_Plan} and $self->{Curr_Test}, + 'Somehow your tests ran without a plan!'); + $self->_whoa($self->{Curr_Test} != @{ $self->{Test_Results} }, + 'Somehow you got a different number of results than tests ran!'); +} + +=item B<_whoa> + + $self->_whoa($check, $description); + +A sanity check, similar to assert(). If the $check is true, something +has gone horribly wrong. It will die with the given $description and +a note to contact the author. + +=cut + +sub _whoa { + my($self, $check, $desc) = @_; + if( $check ) { + local $Level = $Level + 1; + $self->croak(<<"WHOA"); +WHOA! $desc +This should never happen! Please contact the author immediately! +WHOA + } +} + +=item B<_my_exit> + + _my_exit($exit_num); + +Perl seems to have some trouble with exiting inside an END block. 5.005_03 +and 5.6.1 both seem to do odd things. Instead, this function edits $? +directly. It should ONLY be called from inside an END block. It +doesn't actually exit, that's your job. + +=cut + +sub _my_exit { + $? = $_[0]; + + return 1; +} + + +=back + +=end _private + +=cut + +sub _ending { + my $self = shift; + + my $real_exit_code = $?; + $self->_sanity_check(); + + # Don't bother with an ending if this is a forked copy. Only the parent + # should do the ending. + if( $self->{Original_Pid} != $$ ) { + return; + } + + # Exit if plan() was never called. This is so "require Test::Simple" + # doesn't puke. + if( !$self->{Have_Plan} ) { + return; + } + + # Don't do an ending if we bailed out. + if( $self->{Bailed_Out} ) { + return; + } + + # Figure out if we passed or failed and print helpful messages. + my $test_results = $self->{Test_Results}; + if( @$test_results ) { + # The plan? We have no plan. + if( $self->{No_Plan} ) { + $self->_print("1..$self->{Curr_Test}\n") unless $self->no_header; + $self->{Expected_Tests} = $self->{Curr_Test}; + } + + # Auto-extended arrays and elements which aren't explicitly + # filled in with a shared reference will puke under 5.8.0 + # ithreads. So we have to fill them in by hand. :( + my $empty_result = &share({}); + for my $idx ( 0..$self->{Expected_Tests}-1 ) { + $test_results->[$idx] = $empty_result + unless defined $test_results->[$idx]; + } + + my $num_failed = grep !$_->{'ok'}, + @{$test_results}[0..$self->{Curr_Test}-1]; + + my $num_extra = $self->{Curr_Test} - $self->{Expected_Tests}; + + if( $num_extra < 0 ) { + my $s = $self->{Expected_Tests} == 1 ? '' : 's'; + $self->diag(<<"FAIL"); +Looks like you planned $self->{Expected_Tests} test$s but only ran $self->{Curr_Test}. +FAIL + } + elsif( $num_extra > 0 ) { + my $s = $self->{Expected_Tests} == 1 ? '' : 's'; + $self->diag(<<"FAIL"); +Looks like you planned $self->{Expected_Tests} test$s but ran $num_extra extra. +FAIL + } + + if ( $num_failed ) { + my $num_tests = $self->{Curr_Test}; + my $s = $num_failed == 1 ? '' : 's'; + + my $qualifier = $num_extra == 0 ? '' : ' run'; + + $self->diag(<<"FAIL"); +Looks like you failed $num_failed test$s of $num_tests$qualifier. +FAIL + } + + if( $real_exit_code ) { + $self->diag(<<"FAIL"); +Looks like your test died just after $self->{Curr_Test}. +FAIL + + _my_exit( 255 ) && return; + } + + my $exit_code; + if( $num_failed ) { + $exit_code = $num_failed <= 254 ? $num_failed : 254; + } + elsif( $num_extra != 0 ) { + $exit_code = 255; + } + else { + $exit_code = 0; + } + + _my_exit( $exit_code ) && return; + } + elsif ( $self->{Skip_All} ) { + _my_exit( 0 ) && return; + } + elsif ( $real_exit_code ) { + $self->diag(<<'FAIL'); +Looks like your test died before it could output anything. +FAIL + _my_exit( 255 ) && return; + } + else { + $self->diag("No tests run!\n"); + _my_exit( 255 ) && return; + } +} + +END { + $Test->_ending if defined $Test and !$Test->no_ending; +} + +=head1 EXIT CODES + +If all your tests passed, Test::Builder will exit with zero (which is +normal). If anything failed it will exit with how many failed. If +you run less (or more) tests than you planned, the missing (or extras) +will be considered failures. If no tests were ever run Test::Builder +will throw a warning and exit with 255. If the test died, even after +having successfully completed all its tests, it will still be +considered a failure and will exit with 255. + +So the exit codes are... + + 0 all tests successful + 255 test died or all passed but wrong # of tests run + any other number how many failed (including missing or extras) + +If you fail more than 254 tests, it will be reported as 254. + + +=head1 THREADS + +In perl 5.8.1 and later, Test::Builder is thread-safe. The test +number is shared amongst all threads. This means if one thread sets +the test number using current_test() they will all be effected. + +While versions earlier than 5.8.1 had threads they contain too many +bugs to support. + +Test::Builder is only thread-aware if threads.pm is loaded I +Test::Builder. + +=head1 EXAMPLES + +CPAN can provide the best examples. Test::Simple, Test::More, +Test::Exception and Test::Differences all use Test::Builder. + +=head1 SEE ALSO + +Test::Simple, Test::More, Test::Harness + +=head1 AUTHORS + +Original code by chromatic, maintained by Michael G Schwern +Eschwern@pobox.comE + +=head1 COPYRIGHT + +Copyright 2002, 2004 by chromatic Echromatic@wgz.orgE and + Michael G Schwern Eschwern@pobox.comE. + +This program is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + +See F + +=cut + +1; diff --git a/SecurityTests/regressions/inc/Test/Builder/Module.pm b/SecurityTests/regressions/inc/Test/Builder/Module.pm new file mode 100644 index 00000000..ea2f2d96 --- /dev/null +++ b/SecurityTests/regressions/inc/Test/Builder/Module.pm @@ -0,0 +1,185 @@ +package Test::Builder::Module; + +use strict; + +use Test::Builder; + +require Exporter; +our @ISA = qw(Exporter); + +our $VERSION = '0.80'; + +# 5.004's Exporter doesn't have export_to_level. +my $_export_to_level = sub { + my $pkg = shift; + my $level = shift; + (undef) = shift; # redundant arg + my $callpkg = caller($level); + $pkg->export($callpkg, @_); +}; + + +=head1 NAME + +Test::Builder::Module - Base class for test modules + +=head1 SYNOPSIS + + # Emulates Test::Simple + package Your::Module; + + my $CLASS = __PACKAGE__; + + use base 'Test::Builder::Module'; + @EXPORT = qw(ok); + + sub ok ($;$) { + my $tb = $CLASS->builder; + return $tb->ok(@_); + } + + 1; + + +=head1 DESCRIPTION + +This is a superclass for Test::Builder-based modules. It provides a +handful of common functionality and a method of getting at the underlying +Test::Builder object. + + +=head2 Importing + +Test::Builder::Module is a subclass of Exporter which means your +module is also a subclass of Exporter. @EXPORT, @EXPORT_OK, etc... +all act normally. + +A few methods are provided to do the C 23> part +for you. + +=head3 import + +Test::Builder::Module provides an import() method which acts in the +same basic way as Test::More's, setting the plan and controling +exporting of functions and variables. This allows your module to set +the plan independent of Test::More. + +All arguments passed to import() are passed onto +C<< Your::Module->builder->plan() >> with the exception of +C[qw(things to import)]>. + + use Your::Module import => [qw(this that)], tests => 23; + +says to import the functions this() and that() as well as set the plan +to be 23 tests. + +import() also sets the exported_to() attribute of your builder to be +the caller of the import() function. + +Additional behaviors can be added to your import() method by overriding +import_extra(). + +=cut + +sub import { + my($class) = shift; + + # Don't run all this when loading ourself. + return 1 if $class eq 'Test::Builder::Module'; + + my $test = $class->builder; + + my $caller = caller; + + $test->exported_to($caller); + + $class->import_extra(\@_); + my(@imports) = $class->_strip_imports(\@_); + + $test->plan(@_); + + $class->$_export_to_level(1, $class, @imports); +} + + +sub _strip_imports { + my $class = shift; + my $list = shift; + + my @imports = (); + my @other = (); + my $idx = 0; + while( $idx <= $#{$list} ) { + my $item = $list->[$idx]; + + if( defined $item and $item eq 'import' ) { + push @imports, @{$list->[$idx+1]}; + $idx++; + } + else { + push @other, $item; + } + + $idx++; + } + + @$list = @other; + + return @imports; +} + + +=head3 import_extra + + Your::Module->import_extra(\@import_args); + +import_extra() is called by import(). It provides an opportunity for you +to add behaviors to your module based on its import list. + +Any extra arguments which shouldn't be passed on to plan() should be +stripped off by this method. + +See Test::More for an example of its use. + +B This mechanism is I as it +feels like a bit of an ugly hack in its current form. + +=cut + +sub import_extra {} + + +=head2 Builder + +Test::Builder::Module provides some methods of getting at the underlying +Test::Builder object. + +=head3 builder + + my $builder = Your::Class->builder; + +This method returns the Test::Builder object associated with Your::Class. +It is not a constructor so you can call it as often as you like. + +This is the preferred way to get the Test::Builder object. You should +I get it via C<< Test::Builder->new >> as was previously +recommended. + +The object returned by builder() may change at runtime so you should +call builder() inside each function rather than store it in a global. + + sub ok { + my $builder = Your::Class->builder; + + return $builder->ok(@_); + } + + +=cut + +sub builder { + return Test::Builder->new; +} + + +1; diff --git a/SecurityTests/regressions/inc/Test/Builder/Tester.pm b/SecurityTests/regressions/inc/Test/Builder/Tester.pm new file mode 100644 index 00000000..fdb3fb1f --- /dev/null +++ b/SecurityTests/regressions/inc/Test/Builder/Tester.pm @@ -0,0 +1,646 @@ +package Test::Builder::Tester; + +use strict; +our $VERSION = "1.13"; + +use Test::Builder; +use Symbol; +use Carp; + +=head1 NAME + +Test::Builder::Tester - test testsuites that have been built with +Test::Builder + +=head1 SYNOPSIS + + use Test::Builder::Tester tests => 1; + use Test::More; + + test_out("not ok 1 - foo"); + test_fail(+1); + fail("foo"); + test_test("fail works"); + +=head1 DESCRIPTION + +A module that helps you test testing modules that are built with +B. + +The testing system is designed to be used by performing a three step +process for each test you wish to test. This process starts with using +C and C in advance to declare what the testsuite you +are testing will output with B to stdout and stderr. + +You then can run the test(s) from your test suite that call +B. At this point the output of B is +safely captured by B rather than being +interpreted as real test output. + +The final stage is to call C that will simply compare what you +predeclared to what B actually outputted, and report the +results back with a "ok" or "not ok" (with debugging) to the normal +output. + +=cut + +#### +# set up testing +#### + +my $t = Test::Builder->new; + +### +# make us an exporter +### + +use Exporter; +our @ISA = qw(Exporter); + +our @EXPORT = qw(test_out test_err test_fail test_diag test_test line_num); + +# _export_to_level and import stolen directly from Test::More. I am +# the king of cargo cult programming ;-) + +# 5.004's Exporter doesn't have export_to_level. +sub _export_to_level +{ + my $pkg = shift; + my $level = shift; + (undef) = shift; # XXX redundant arg + my $callpkg = caller($level); + $pkg->export($callpkg, @_); +} + +sub import { + my $class = shift; + my(@plan) = @_; + + my $caller = caller; + + $t->exported_to($caller); + $t->plan(@plan); + + my @imports = (); + foreach my $idx (0..$#plan) { + if( $plan[$idx] eq 'import' ) { + @imports = @{$plan[$idx+1]}; + last; + } + } + + __PACKAGE__->_export_to_level(1, __PACKAGE__, @imports); +} + +### +# set up file handles +### + +# create some private file handles +my $output_handle = gensym; +my $error_handle = gensym; + +# and tie them to this package +my $out = tie *$output_handle, "Test::Builder::Tester::Tie", "STDOUT"; +my $err = tie *$error_handle, "Test::Builder::Tester::Tie", "STDERR"; + +#### +# exported functions +#### + +# for remembering that we're testing and where we're testing at +my $testing = 0; +my $testing_num; + +# remembering where the file handles were originally connected +my $original_output_handle; +my $original_failure_handle; +my $original_todo_handle; + +my $original_test_number; +my $original_harness_state; + +my $original_harness_env; + +# function that starts testing and redirects the filehandles for now +sub _start_testing +{ + # even if we're running under Test::Harness pretend we're not + # for now. This needed so Test::Builder doesn't add extra spaces + $original_harness_env = $ENV{HARNESS_ACTIVE} || 0; + $ENV{HARNESS_ACTIVE} = 0; + + # remember what the handles were set to + $original_output_handle = $t->output(); + $original_failure_handle = $t->failure_output(); + $original_todo_handle = $t->todo_output(); + + # switch out to our own handles + $t->output($output_handle); + $t->failure_output($error_handle); + $t->todo_output($error_handle); + + # clear the expected list + $out->reset(); + $err->reset(); + + # remeber that we're testing + $testing = 1; + $testing_num = $t->current_test; + $t->current_test(0); + + # look, we shouldn't do the ending stuff + $t->no_ending(1); +} + +=head2 Functions + +These are the six methods that are exported as default. + +=over 4 + +=item test_out + +=item test_err + +Procedures for predeclaring the output that your test suite is +expected to produce until C is called. These procedures +automatically assume that each line terminates with "\n". So + + test_out("ok 1","ok 2"); + +is the same as + + test_out("ok 1\nok 2"); + +which is even the same as + + test_out("ok 1"); + test_out("ok 2"); + +Once C or C (or C or C) have +been called once all further output from B will be +captured by B. This means that your will not +be able perform further tests to the normal output in the normal way +until you call C (well, unless you manually meddle with the +output filehandles) + +=cut + +sub test_out +{ + # do we need to do any setup? + _start_testing() unless $testing; + + $out->expect(@_) +} + +sub test_err +{ + # do we need to do any setup? + _start_testing() unless $testing; + + $err->expect(@_) +} + +=item test_fail + +Because the standard failure message that B produces +whenever a test fails will be a common occurrence in your test error +output, and because has changed between Test::Builder versions, rather +than forcing you to call C with the string all the time like +so + + test_err("# Failed test ($0 at line ".line_num(+1).")"); + +C exists as a convenience function that can be called +instead. It takes one argument, the offset from the current line that +the line that causes the fail is on. + + test_fail(+1); + +This means that the example in the synopsis could be rewritten +more simply as: + + test_out("not ok 1 - foo"); + test_fail(+1); + fail("foo"); + test_test("fail works"); + +=cut + +sub test_fail +{ + # do we need to do any setup? + _start_testing() unless $testing; + + # work out what line we should be on + my ($package, $filename, $line) = caller; + $line = $line + (shift() || 0); # prevent warnings + + # expect that on stderr + $err->expect("# Failed test ($0 at line $line)"); +} + +=item test_diag + +As most of the remaining expected output to the error stream will be +created by Test::Builder's C function, B +provides a convience function C that you can use instead of +C. + +The C function prepends comment hashes and spacing to the +start and newlines to the end of the expected output passed to it and +adds it to the list of expected error output. So, instead of writing + + test_err("# Couldn't open file"); + +you can write + + test_diag("Couldn't open file"); + +Remember that B's diag function will not add newlines to +the end of output and test_diag will. So to check + + Test::Builder->new->diag("foo\n","bar\n"); + +You would do + + test_diag("foo","bar") + +without the newlines. + +=cut + +sub test_diag +{ + # do we need to do any setup? + _start_testing() unless $testing; + + # expect the same thing, but prepended with "# " + local $_; + $err->expect(map {"# $_"} @_) +} + +=item test_test + +Actually performs the output check testing the tests, comparing the +data (with C) that we have captured from B against +that that was declared with C and C. + +This takes name/value pairs that effect how the test is run. + +=over + +=item title (synonym 'name', 'label') + +The name of the test that will be displayed after the C or C. + +=item skip_out + +Setting this to a true value will cause the test to ignore if the +output sent by the test to the output stream does not match that +declared with C. + +=item skip_err + +Setting this to a true value will cause the test to ignore if the +output sent by the test to the error stream does not match that +declared with C. + +=back + +As a convience, if only one argument is passed then this argument +is assumed to be the name of the test (as in the above examples.) + +Once C has been run test output will be redirected back to +the original filehandles that B was connected to +(probably STDOUT and STDERR,) meaning any further tests you run +will function normally and cause success/errors for B. + +=cut + +sub test_test +{ + # decode the arguements as described in the pod + my $mess; + my %args; + if (@_ == 1) + { $mess = shift } + else + { + %args = @_; + $mess = $args{name} if exists($args{name}); + $mess = $args{title} if exists($args{title}); + $mess = $args{label} if exists($args{label}); + } + + # er, are we testing? + croak "Not testing. You must declare output with a test function first." + unless $testing; + + # okay, reconnect the test suite back to the saved handles + $t->output($original_output_handle); + $t->failure_output($original_failure_handle); + $t->todo_output($original_todo_handle); + + # restore the test no, etc, back to the original point + $t->current_test($testing_num); + $testing = 0; + + # re-enable the original setting of the harness + $ENV{HARNESS_ACTIVE} = $original_harness_env; + + # check the output we've stashed + unless ($t->ok( ($args{skip_out} || $out->check) + && ($args{skip_err} || $err->check), + $mess)) + { + # print out the diagnostic information about why this + # test failed + + local $_; + + $t->diag(map {"$_\n"} $out->complaint) + unless $args{skip_out} || $out->check; + + $t->diag(map {"$_\n"} $err->complaint) + unless $args{skip_err} || $err->check; + } +} + +=item line_num + +A utility function that returns the line number that the function was +called on. You can pass it an offset which will be added to the +result. This is very useful for working out the correct text of +diagnostic functions that contain line numbers. + +Essentially this is the same as the C<__LINE__> macro, but the +C idiom is arguably nicer. + +=cut + +sub line_num +{ + my ($package, $filename, $line) = caller; + return $line + (shift() || 0); # prevent warnings +} + +=back + +In addition to the six exported functions there there exists one +function that can only be accessed with a fully qualified function +call. + +=over 4 + +=item color + +When C is called and the output that your tests generate +does not match that which you declared, C will print out +debug information showing the two conflicting versions. As this +output itself is debug information it can be confusing which part of +the output is from C and which was the original output from +your original tests. Also, it may be hard to spot things like +extraneous whitespace at the end of lines that may cause your test to +fail even though the output looks similar. + +To assist you, if you have the B module installed +(which you should do by default from perl 5.005 onwards), C +can colour the background of the debug information to disambiguate the +different types of output. The debug output will have it's background +coloured green and red. The green part represents the text which is +the same between the executed and actual output, the red shows which +part differs. + +The C function determines if colouring should occur or not. +Passing it a true or false value will enable or disable colouring +respectively, and the function called with no argument will return the +current setting. + +To enable colouring from the command line, you can use the +B module like so: + + perl -Mlib=Text::Builder::Tester::Color test.t + +Or by including the B module directly in +the PERL5LIB. + +=cut + +my $color; +sub color +{ + $color = shift if @_; + $color; +} + +=back + +=head1 BUGS + +Calls C<no_ending>> turning off the ending tests. +This is needed as otherwise it will trip out because we've run more +tests than we strictly should have and it'll register any failures we +had that we were testing for as real failures. + +The color function doesn't work unless B is installed +and is compatible with your terminal. + +Bugs (and requests for new features) can be reported to the author +though the CPAN RT system: +L + +=head1 AUTHOR + +Copyright Mark Fowler Emark@twoshortplanks.comE 2002, 2004. + +Some code taken from B and B, written by by +Michael G Schwern Eschwern@pobox.comE. Hence, those parts +Copyright Micheal G Schwern 2001. Used and distributed with +permission. + +This program is free software; you can redistribute it +and/or modify it under the same terms as Perl itself. + +=head1 NOTES + +This code has been tested explicitly on the following versions +of perl: 5.7.3, 5.6.1, 5.6.0, 5.005_03, 5.004_05 and 5.004. + +Thanks to Richard Clamp Erichardc@unixbeard.netE for letting +me use his testing system to try this module out on. + +=head1 SEE ALSO + +L, L, L. + +=cut + +1; + +#################################################################### +# Helper class that is used to remember expected and received data + +package Test::Builder::Tester::Tie; + +## +# add line(s) to be expected + +sub expect +{ + my $self = shift; + + my @checks = @_; + foreach my $check (@checks) { + $check = $self->_translate_Failed_check($check); + push @{$self->{wanted}}, ref $check ? $check : "$check\n"; + } +} + + +sub _translate_Failed_check +{ + my($self, $check) = @_; + + if( $check =~ /\A(.*)# (Failed .*test) \((.*?) at line (\d+)\)\Z(?!\n)/ ) { + $check = "/\Q$1\E#\\s+\Q$2\E.*?\\n?.*?\Qat $3\E line \Q$4\E.*\\n?/"; + } + + return $check; +} + + +## +# return true iff the expected data matches the got data + +sub check +{ + my $self = shift; + + # turn off warnings as these might be undef + local $^W = 0; + + my @checks = @{$self->{wanted}}; + my $got = $self->{got}; + foreach my $check (@checks) { + $check = "\Q$check\E" unless ($check =~ s,^/(.*)/$,$1, or ref $check); + return 0 unless $got =~ s/^$check//; + } + + return length $got == 0; +} + +## +# a complaint message about the inputs not matching (to be +# used for debugging messages) + +sub complaint +{ + my $self = shift; + my $type = $self->type; + my $got = $self->got; + my $wanted = join "\n", @{$self->wanted}; + + # are we running in colour mode? + if (Test::Builder::Tester::color) + { + # get color + eval { require Term::ANSIColor }; + unless ($@) + { + # colours + + my $green = Term::ANSIColor::color("black"). + Term::ANSIColor::color("on_green"); + my $red = Term::ANSIColor::color("black"). + Term::ANSIColor::color("on_red"); + my $reset = Term::ANSIColor::color("reset"); + + # work out where the two strings start to differ + my $char = 0; + $char++ while substr($got, $char, 1) eq substr($wanted, $char, 1); + + # get the start string and the two end strings + my $start = $green . substr($wanted, 0, $char); + my $gotend = $red . substr($got , $char) . $reset; + my $wantedend = $red . substr($wanted, $char) . $reset; + + # make the start turn green on and off + $start =~ s/\n/$reset\n$green/g; + + # make the ends turn red on and off + $gotend =~ s/\n/$reset\n$red/g; + $wantedend =~ s/\n/$reset\n$red/g; + + # rebuild the strings + $got = $start . $gotend; + $wanted = $start . $wantedend; + } + } + + return "$type is:\n" . + "$got\nnot:\n$wanted\nas expected" +} + +## +# forget all expected and got data + +sub reset +{ + my $self = shift; + %$self = ( + type => $self->{type}, + got => '', + wanted => [], + ); +} + + +sub got +{ + my $self = shift; + return $self->{got}; +} + +sub wanted +{ + my $self = shift; + return $self->{wanted}; +} + +sub type +{ + my $self = shift; + return $self->{type}; +} + +### +# tie interface +### + +sub PRINT { + my $self = shift; + $self->{got} .= join '', @_; +} + +sub TIEHANDLE { + my($class, $type) = @_; + + my $self = bless { + type => $type + }, $class; + + $self->reset; + + return $self; +} + +sub READ {} +sub READLINE {} +sub GETC {} +sub FILENO {} + +1; diff --git a/SecurityTests/regressions/inc/Test/Builder/Tester/Color.pm b/SecurityTests/regressions/inc/Test/Builder/Tester/Color.pm new file mode 100644 index 00000000..b479e71a --- /dev/null +++ b/SecurityTests/regressions/inc/Test/Builder/Tester/Color.pm @@ -0,0 +1,50 @@ +package Test::Builder::Tester::Color; + +use strict; + +require Test::Builder::Tester; + +=head1 NAME + +Test::Builder::Tester::Color - turn on colour in Test::Builder::Tester + +=head1 SYNOPSIS + + When running a test script + + perl -MTest::Builder::Tester::Color test.t + +=head1 DESCRIPTION + +Importing this module causes the subroutine color in Test::Builder::Tester +to be called with a true value causing colour highlighting to be turned +on in debug output. + +The sole purpose of this module is to enable colour highlighting +from the command line. + +=cut + +sub import +{ + Test::Builder::Tester::color(1); +} + +=head1 AUTHOR + +Copyright Mark Fowler Emark@twoshortplanks.comE 2002. + +This program is free software; you can redistribute it +and/or modify it under the same terms as Perl itself. + +=head1 BUGS + +This module will have no effect unless Term::ANSIColor is installed. + +=head1 SEE ALSO + +L, L + +=cut + +1; diff --git a/SecurityTests/regressions/inc/Test/Harness.pm b/SecurityTests/regressions/inc/Test/Harness.pm new file mode 100644 index 00000000..1991a60f --- /dev/null +++ b/SecurityTests/regressions/inc/Test/Harness.pm @@ -0,0 +1,1169 @@ +# -*- Mode: cperl; cperl-indent-level: 4 -*- + +package Test::Harness; + +require 5.00405; +use Test::Harness::Straps; +use Test::Harness::Assert; +use Exporter; +use Benchmark; +use Config; +use strict; + + +use vars qw( + $VERSION + @ISA @EXPORT @EXPORT_OK + $Verbose $Switches $Debug + $verbose $switches $debug + $Columns + $Timer + $ML $Last_ML_Print + $Strap + $has_time_hires +); + +BEGIN { + eval q{use Time::HiRes 'time'}; + $has_time_hires = !$@; +} + +=head1 NAME + +Test::Harness - Run Perl standard test scripts with statistics + +=head1 VERSION + +Version 2.64 + +=cut + +$VERSION = '2.64'; + +# Backwards compatibility for exportable variable names. +*verbose = *Verbose; +*switches = *Switches; +*debug = *Debug; + +$ENV{HARNESS_ACTIVE} = 1; +$ENV{HARNESS_VERSION} = $VERSION; + +END { + # For VMS. + delete $ENV{HARNESS_ACTIVE}; + delete $ENV{HARNESS_VERSION}; +} + +my $Files_In_Dir = $ENV{HARNESS_FILELEAK_IN_DIR}; + +# Stolen from Params::Util +sub _CLASS { + (defined $_[0] and ! ref $_[0] and $_[0] =~ m/^[^\W\d]\w*(?:::\w+)*$/s) ? $_[0] : undef; +} + +# Strap Overloading +if ( $ENV{HARNESS_STRAPS_CLASS} ) { + die 'Set HARNESS_STRAP_CLASS, singular, not HARNESS_STRAPS_CLASS'; +} +my $HARNESS_STRAP_CLASS = $ENV{HARNESS_STRAP_CLASS} || 'Test::Harness::Straps'; +if ( $HARNESS_STRAP_CLASS =~ /\.pm$/ ) { + # "Class" is actually a filename, that should return the + # class name as its true return value. + $HARNESS_STRAP_CLASS = require $HARNESS_STRAP_CLASS; + if ( !_CLASS($HARNESS_STRAP_CLASS) ) { + die "HARNESS_STRAP_CLASS '$HARNESS_STRAP_CLASS' is not a valid class name"; + } +} +else { + # It is a class name within the current @INC + if ( !_CLASS($HARNESS_STRAP_CLASS) ) { + die "HARNESS_STRAP_CLASS '$HARNESS_STRAP_CLASS' is not a valid class name"; + } + eval "require $HARNESS_STRAP_CLASS"; + die $@ if $@; +} +if ( !$HARNESS_STRAP_CLASS->isa('Test::Harness::Straps') ) { + die "HARNESS_STRAP_CLASS '$HARNESS_STRAP_CLASS' must be a Test::Harness::Straps subclass"; +} + +$Strap = $HARNESS_STRAP_CLASS->new; + +sub strap { return $Strap }; + +@ISA = ('Exporter'); +@EXPORT = qw(&runtests); +@EXPORT_OK = qw(&execute_tests $verbose $switches); + +$Verbose = $ENV{HARNESS_VERBOSE} || 0; +$Debug = $ENV{HARNESS_DEBUG} || 0; +$Switches = '-w'; +$Columns = $ENV{HARNESS_COLUMNS} || $ENV{COLUMNS} || 80; +$Columns--; # Some shells have trouble with a full line of text. +$Timer = $ENV{HARNESS_TIMER} || 0; + +=head1 SYNOPSIS + + use Test::Harness; + + runtests(@test_files); + +=head1 DESCRIPTION + +B If all you want to do is write a test script, consider +using Test::Simple. Test::Harness is the module that reads the +output from Test::Simple, Test::More and other modules based on +Test::Builder. You don't need to know about Test::Harness to use +those modules. + +Test::Harness runs tests and expects output from the test in a +certain format. That format is called TAP, the Test Anything +Protocol. It is defined in L. + +C runs all the testscripts named +as arguments and checks standard output for the expected strings +in TAP format. + +The F utility is a thin wrapper around Test::Harness. + +=head2 Taint mode + +Test::Harness will honor the C<-T> or C<-t> in the #! line on your +test files. So if you begin a test with: + + #!perl -T + +the test will be run with taint mode on. + +=head2 Configuration variables. + +These variables can be used to configure the behavior of +Test::Harness. They are exported on request. + +=over 4 + +=item C<$Test::Harness::Verbose> + +The package variable C<$Test::Harness::Verbose> is exportable and can be +used to let C display the standard output of the script +without altering the behavior otherwise. The F utility's C<-v> +flag will set this. + +=item C<$Test::Harness::switches> + +The package variable C<$Test::Harness::switches> is exportable and can be +used to set perl command line options used for running the test +script(s). The default value is C<-w>. It overrides C. + +=item C<$Test::Harness::Timer> + +If set to true, and C is available, print elapsed seconds +after each test file. + +=back + + +=head2 Failure + +When tests fail, analyze the summary report: + + t/base..............ok + t/nonumbers.........ok + t/ok................ok + t/test-harness......ok + t/waterloo..........dubious + Test returned status 3 (wstat 768, 0x300) + DIED. FAILED tests 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 + Failed 10/20 tests, 50.00% okay + Failed Test Stat Wstat Total Fail List of Failed + --------------------------------------------------------------- + t/waterloo.t 3 768 20 10 1 3 5 7 9 11 13 15 17 19 + Failed 1/5 test scripts, 80.00% okay. 10/44 subtests failed, 77.27% okay. + +Everything passed but F. It failed 10 of 20 tests and +exited with non-zero status indicating something dubious happened. + +The columns in the summary report mean: + +=over 4 + +=item B + +The test file which failed. + +=item B + +If the test exited with non-zero, this is its exit status. + +=item B + +The wait status of the test. + +=item B + +Total number of tests expected to run. + +=item B + +Number which failed, either from "not ok" or because they never ran. + +=item B + +A list of the tests which failed. Successive failures may be +abbreviated (ie. 15-20 to indicate that tests 15, 16, 17, 18, 19 and +20 failed). + +=back + + +=head1 FUNCTIONS + +The following functions are available. + +=head2 runtests( @test_files ) + +This runs all the given I<@test_files> and divines whether they passed +or failed based on their output to STDOUT (details above). It prints +out each individual test which failed along with a summary report and +a how long it all took. + +It returns true if everything was ok. Otherwise it will C with +one of the messages in the DIAGNOSTICS section. + +=cut + +sub runtests { + my(@tests) = @_; + + local ($\, $,); + + my ($tot, $failedtests,$todo_passed) = execute_tests(tests => \@tests); + print get_results($tot, $failedtests,$todo_passed); + + my $ok = _all_ok($tot); + + assert(($ok xor keys %$failedtests), + q{ok status jives with $failedtests}); + + if (! $ok) { + die("Failed $tot->{bad}/$tot->{tests} test programs. " . + "@{[$tot->{max} - $tot->{ok}]}/$tot->{max} subtests failed.\n"); + } + + return $ok; +} + +# my $ok = _all_ok(\%tot); +# Tells you if this test run is overall successful or not. + +sub _all_ok { + my($tot) = shift; + + return $tot->{bad} == 0 && ($tot->{max} || $tot->{skipped}) ? 1 : 0; +} + +# Returns all the files in a directory. This is shorthand for backwards +# compatibility on systems where C doesn't work right. + +sub _globdir { + local *DIRH; + + opendir DIRH, shift; + my @f = readdir DIRH; + closedir DIRH; + + return @f; +} + +=head2 execute_tests( tests => \@test_files, out => \*FH ) + +Runs all the given C<@test_files> (just like C) but +doesn't generate the final report. During testing, progress +information will be written to the currently selected output +filehandle (usually C), or to the filehandle given by the +C parameter. The I is optional. + +Returns a list of two values, C<$total> and C<$failed>, describing the +results. C<$total> is a hash ref summary of all the tests run. Its +keys and values are this: + + bonus Number of individual todo tests unexpectedly passed + max Number of individual tests ran + ok Number of individual tests passed + sub_skipped Number of individual tests skipped + todo Number of individual todo tests + + files Number of test files ran + good Number of test files passed + bad Number of test files failed + tests Number of test files originally given + skipped Number of test files skipped + +If C<< $total->{bad} == 0 >> and C<< $total->{max} > 0 >>, you've +got a successful test. + +C<$failed> is a hash ref of all the test scripts that failed. Each key +is the name of a test script, each value is another hash representing +how that script failed. Its keys are these: + + name Name of the test which failed + estat Script's exit value + wstat Script's wait status + max Number of individual tests + failed Number which failed + canon List of tests which failed (as string). + +C<$failed> should be empty if everything passed. + +=cut + +sub execute_tests { + my %args = @_; + my @tests = @{$args{tests}}; + my $out = $args{out} || select(); + + # We allow filehandles that are symbolic refs + no strict 'refs'; + _autoflush($out); + _autoflush(\*STDERR); + + my %failedtests; + my %todo_passed; + + # Test-wide totals. + my(%tot) = ( + bonus => 0, + max => 0, + ok => 0, + files => 0, + bad => 0, + good => 0, + tests => scalar @tests, + sub_skipped => 0, + todo => 0, + skipped => 0, + bench => 0, + ); + + my @dir_files; + @dir_files = _globdir $Files_In_Dir if defined $Files_In_Dir; + my $run_start_time = new Benchmark; + + my $width = _leader_width(@tests); + foreach my $tfile (@tests) { + $Last_ML_Print = 0; # so each test prints at least once + my($leader, $ml) = _mk_leader($tfile, $width); + local $ML = $ml; + + print $out $leader; + + $tot{files}++; + + $Strap->{_seen_header} = 0; + if ( $Test::Harness::Debug ) { + print $out "# Running: ", $Strap->_command_line($tfile), "\n"; + } + my $test_start_time = $Timer ? time : 0; + my $results = $Strap->analyze_file($tfile) or + do { warn $Strap->{error}, "\n"; next }; + my $elapsed; + if ( $Timer ) { + $elapsed = time - $test_start_time; + if ( $has_time_hires ) { + $elapsed = sprintf( " %8d ms", $elapsed*1000 ); + } + else { + $elapsed = sprintf( " %8s s", $elapsed ? $elapsed : "<1" ); + } + } + else { + $elapsed = ""; + } + + # state of the current test. + my @failed = grep { !$results->details->[$_-1]{ok} } + 1..@{$results->details}; + my @todo_pass = grep { $results->details->[$_-1]{actual_ok} && + $results->details->[$_-1]{type} eq 'todo' } + 1..@{$results->details}; + + my %test = ( + ok => $results->ok, + 'next' => $Strap->{'next'}, + max => $results->max, + failed => \@failed, + todo_pass => \@todo_pass, + todo => $results->todo, + bonus => $results->bonus, + skipped => $results->skip, + skip_reason => $results->skip_reason, + skip_all => $Strap->{skip_all}, + ml => $ml, + ); + + $tot{bonus} += $results->bonus; + $tot{max} += $results->max; + $tot{ok} += $results->ok; + $tot{todo} += $results->todo; + $tot{sub_skipped} += $results->skip; + + my $estatus = $results->exit; + my $wstatus = $results->wait; + + if ( $results->passing ) { + # XXX Combine these first two + if ($test{max} and $test{skipped} + $test{bonus}) { + my @msg; + push(@msg, "$test{skipped}/$test{max} skipped: $test{skip_reason}") + if $test{skipped}; + if ($test{bonus}) { + my ($txt, $canon) = _canondetail($test{todo},0,'TODO passed', + @{$test{todo_pass}}); + $todo_passed{$tfile} = { + canon => $canon, + max => $test{todo}, + failed => $test{bonus}, + name => $tfile, + estat => '', + wstat => '', + }; + + push(@msg, "$test{bonus}/$test{max} unexpectedly succeeded\n$txt"); + } + print $out "$test{ml}ok$elapsed\n ".join(', ', @msg)."\n"; + } + elsif ( $test{max} ) { + print $out "$test{ml}ok$elapsed\n"; + } + elsif ( defined $test{skip_all} and length $test{skip_all} ) { + print $out "skipped\n all skipped: $test{skip_all}\n"; + $tot{skipped}++; + } + else { + print $out "skipped\n all skipped: no reason given\n"; + $tot{skipped}++; + } + $tot{good}++; + } + else { + # List unrun tests as failures. + if ($test{'next'} <= $test{max}) { + push @{$test{failed}}, $test{'next'}..$test{max}; + } + # List overruns as failures. + else { + my $details = $results->details; + foreach my $overrun ($test{max}+1..@$details) { + next unless ref $details->[$overrun-1]; + push @{$test{failed}}, $overrun + } + } + + if ($wstatus) { + $failedtests{$tfile} = _dubious_return(\%test, \%tot, + $estatus, $wstatus); + $failedtests{$tfile}{name} = $tfile; + } + elsif ( $results->seen ) { + if (@{$test{failed}} and $test{max}) { + my ($txt, $canon) = _canondetail($test{max},$test{skipped},'Failed', + @{$test{failed}}); + print $out "$test{ml}$txt"; + $failedtests{$tfile} = { canon => $canon, + max => $test{max}, + failed => scalar @{$test{failed}}, + name => $tfile, + estat => '', + wstat => '', + }; + } + else { + print $out "Don't know which tests failed: got $test{ok} ok, ". + "expected $test{max}\n"; + $failedtests{$tfile} = { canon => '??', + max => $test{max}, + failed => '??', + name => $tfile, + estat => '', + wstat => '', + }; + } + $tot{bad}++; + } + else { + print $out "FAILED before any test output arrived\n"; + $tot{bad}++; + $failedtests{$tfile} = { canon => '??', + max => '??', + failed => '??', + name => $tfile, + estat => '', + wstat => '', + }; + } + } + + if (defined $Files_In_Dir) { + my @new_dir_files = _globdir $Files_In_Dir; + if (@new_dir_files != @dir_files) { + my %f; + @f{@new_dir_files} = (1) x @new_dir_files; + delete @f{@dir_files}; + my @f = sort keys %f; + print $out "LEAKED FILES: @f\n"; + @dir_files = @new_dir_files; + } + } + } # foreach test + $tot{bench} = timediff(new Benchmark, $run_start_time); + + $Strap->_restore_PERL5LIB; + + return(\%tot, \%failedtests, \%todo_passed); +} + +# Turns on autoflush for the handle passed +sub _autoflush { + my $flushy_fh = shift; + my $old_fh = select $flushy_fh; + $| = 1; + select $old_fh; +} + +=for private _mk_leader + + my($leader, $ml) = _mk_leader($test_file, $width); + +Generates the 't/foo........' leader for the given C<$test_file> as well +as a similar version which will overwrite the current line (by use of +\r and such). C<$ml> may be empty if Test::Harness doesn't think you're +on TTY. + +The C<$width> is the width of the "yada/blah.." string. + +=cut + +sub _mk_leader { + my($te, $width) = @_; + chomp($te); + $te =~ s/\.\w+$/./; + + if ($^O eq 'VMS') { + $te =~ s/^.*\.t\./\[.t./s; + } + my $leader = "$te" . '.' x ($width - length($te)); + my $ml = ""; + + if ( -t STDOUT and not $ENV{HARNESS_NOTTY} and not $Verbose ) { + $ml = "\r" . (' ' x 77) . "\r$leader" + } + + return($leader, $ml); +} + +=for private _leader_width + + my($width) = _leader_width(@test_files); + +Calculates how wide the leader should be based on the length of the +longest test name. + +=cut + +sub _leader_width { + my $maxlen = 0; + my $maxsuflen = 0; + foreach (@_) { + my $suf = /\.(\w+)$/ ? $1 : ''; + my $len = length; + my $suflen = length $suf; + $maxlen = $len if $len > $maxlen; + $maxsuflen = $suflen if $suflen > $maxsuflen; + } + # + 3 : we want three dots between the test name and the "ok" + return $maxlen + 3 - $maxsuflen; +} + +sub get_results { + my $tot = shift; + my $failedtests = shift; + my $todo_passed = shift; + + my $out = ''; + + my $bonusmsg = _bonusmsg($tot); + + if (_all_ok($tot)) { + $out .= "All tests successful$bonusmsg.\n"; + if ($tot->{bonus}) { + my($fmt_top, $fmt) = _create_fmts("Passed TODO",$todo_passed); + # Now write to formats + $out .= swrite( $fmt_top ); + for my $script (sort keys %{$todo_passed||{}}) { + my $Curtest = $todo_passed->{$script}; + $out .= swrite( $fmt, @{ $Curtest }{qw(name estat wstat max failed canon)} ); + } + } + } + elsif (!$tot->{tests}){ + die "FAILED--no tests were run for some reason.\n"; + } + elsif (!$tot->{max}) { + my $blurb = $tot->{tests}==1 ? "script" : "scripts"; + die "FAILED--$tot->{tests} test $blurb could be run, ". + "alas--no output ever seen\n"; + } + else { + my $subresults = sprintf( " %d/%d subtests failed.", + $tot->{max} - $tot->{ok}, $tot->{max} ); + + my($fmt_top, $fmt1, $fmt2) = _create_fmts("Failed Test",$failedtests); + + # Now write to formats + $out .= swrite( $fmt_top ); + for my $script (sort keys %$failedtests) { + my $Curtest = $failedtests->{$script}; + $out .= swrite( $fmt1, @{ $Curtest }{qw(name estat wstat max failed canon)} ); + $out .= swrite( $fmt2, $Curtest->{canon} ); + } + if ($tot->{bad}) { + $bonusmsg =~ s/^,\s*//; + $out .= "$bonusmsg.\n" if $bonusmsg; + $out .= "Failed $tot->{bad}/$tot->{tests} test scripts.$subresults\n"; + } + } + + $out .= sprintf("Files=%d, Tests=%d, %s\n", + $tot->{files}, $tot->{max}, timestr($tot->{bench}, 'nop')); + return $out; +} + +sub swrite { + my $format = shift; + $^A = ''; + formline($format,@_); + my $out = $^A; + $^A = ''; + return $out; +} + + +my %Handlers = ( + header => \&header_handler, + test => \&test_handler, + bailout => \&bailout_handler, +); + +$Strap->set_callback(\&strap_callback); +sub strap_callback { + my($self, $line, $type, $totals) = @_; + print $line if $Verbose; + + my $meth = $Handlers{$type}; + $meth->($self, $line, $type, $totals) if $meth; +}; + + +sub header_handler { + my($self, $line, $type, $totals) = @_; + + warn "Test header seen more than once!\n" if $self->{_seen_header}; + + $self->{_seen_header}++; + + warn "1..M can only appear at the beginning or end of tests\n" + if $totals->seen && ($totals->max < $totals->seen); +}; + +sub test_handler { + my($self, $line, $type, $totals) = @_; + + my $curr = $totals->seen; + my $next = $self->{'next'}; + my $max = $totals->max; + my $detail = $totals->details->[-1]; + + if( $detail->{ok} ) { + _print_ml_less("ok $curr/$max"); + + if( $detail->{type} eq 'skip' ) { + $totals->set_skip_reason( $detail->{reason} ) + unless defined $totals->skip_reason; + $totals->set_skip_reason( 'various reasons' ) + if $totals->skip_reason ne $detail->{reason}; + } + } + else { + _print_ml("NOK $curr/$max"); + } + + if( $curr > $next ) { + print "Test output counter mismatch [test $curr]\n"; + } + elsif( $curr < $next ) { + print "Confused test output: test $curr answered after ". + "test ", $next - 1, "\n"; + } + +}; + +sub bailout_handler { + my($self, $line, $type, $totals) = @_; + + die "FAILED--Further testing stopped" . + ($self->{bailout_reason} ? ": $self->{bailout_reason}\n" : ".\n"); +}; + + +sub _print_ml { + print join '', $ML, @_ if $ML; +} + + +# Print updates only once per second. +sub _print_ml_less { + my $now = CORE::time; + if ( $Last_ML_Print != $now ) { + _print_ml(@_); + $Last_ML_Print = $now; + } +} + +sub _bonusmsg { + my($tot) = @_; + + my $bonusmsg = ''; + $bonusmsg = (" ($tot->{bonus} subtest".($tot->{bonus} > 1 ? 's' : ''). + " UNEXPECTEDLY SUCCEEDED)") + if $tot->{bonus}; + + if ($tot->{skipped}) { + $bonusmsg .= ", $tot->{skipped} test" + . ($tot->{skipped} != 1 ? 's' : ''); + if ($tot->{sub_skipped}) { + $bonusmsg .= " and $tot->{sub_skipped} subtest" + . ($tot->{sub_skipped} != 1 ? 's' : ''); + } + $bonusmsg .= ' skipped'; + } + elsif ($tot->{sub_skipped}) { + $bonusmsg .= ", $tot->{sub_skipped} subtest" + . ($tot->{sub_skipped} != 1 ? 's' : '') + . " skipped"; + } + return $bonusmsg; +} + +# Test program go boom. +sub _dubious_return { + my($test, $tot, $estatus, $wstatus) = @_; + + my $failed = '??'; + my $canon = '??'; + + printf "$test->{ml}dubious\n\tTest returned status $estatus ". + "(wstat %d, 0x%x)\n", + $wstatus,$wstatus; + print "\t\t(VMS status is $estatus)\n" if $^O eq 'VMS'; + + $tot->{bad}++; + + if ($test->{max}) { + if ($test->{'next'} == $test->{max} + 1 and not @{$test->{failed}}) { + print "\tafter all the subtests completed successfully\n"; + $failed = 0; # But we do not set $canon! + } + else { + push @{$test->{failed}}, $test->{'next'}..$test->{max}; + $failed = @{$test->{failed}}; + (my $txt, $canon) = _canondetail($test->{max},$test->{skipped},'Failed',@{$test->{failed}}); + print "DIED. ",$txt; + } + } + + return { canon => $canon, max => $test->{max} || '??', + failed => $failed, + estat => $estatus, wstat => $wstatus, + }; +} + + +sub _create_fmts { + my $failed_str = shift; + my $failedtests = shift; + + my ($type) = split /\s/,$failed_str; + my $short = substr($type,0,4); + my $total = $short eq 'Pass' ? 'TODOs' : 'Total'; + my $middle_str = " Stat Wstat $total $short "; + my $list_str = "List of $type"; + + # Figure out our longest name string for formatting purposes. + my $max_namelen = length($failed_str); + foreach my $script (keys %$failedtests) { + my $namelen = length $failedtests->{$script}->{name}; + $max_namelen = $namelen if $namelen > $max_namelen; + } + + my $list_len = $Columns - length($middle_str) - $max_namelen; + if ($list_len < length($list_str)) { + $list_len = length($list_str); + $max_namelen = $Columns - length($middle_str) - $list_len; + if ($max_namelen < length($failed_str)) { + $max_namelen = length($failed_str); + $Columns = $max_namelen + length($middle_str) + $list_len; + } + } + + my $fmt_top = sprintf("%-${max_namelen}s", $failed_str) + . $middle_str + . $list_str . "\n" + . "-" x $Columns + . "\n"; + + my $fmt1 = "@" . "<" x ($max_namelen - 1) + . " @>> @>>>> @>>>> @>>> " + . "^" . "<" x ($list_len - 1) . "\n"; + my $fmt2 = "~~" . " " x ($Columns - $list_len - 2) . "^" + . "<" x ($list_len - 1) . "\n"; + + return($fmt_top, $fmt1, $fmt2); +} + +sub _canondetail { + my $max = shift; + my $skipped = shift; + my $type = shift; + my @detail = @_; + my %seen; + @detail = sort {$a <=> $b} grep !$seen{$_}++, @detail; + my $detail = @detail; + my @result = (); + my @canon = (); + my $min; + my $last = $min = shift @detail; + my $canon; + my $uc_type = uc($type); + if (@detail) { + for (@detail, $detail[-1]) { # don't forget the last one + if ($_ > $last+1 || $_ == $last) { + push @canon, ($min == $last) ? $last : "$min-$last"; + $min = $_; + } + $last = $_; + } + local $" = ", "; + push @result, "$uc_type tests @canon\n"; + $canon = join ' ', @canon; + } + else { + push @result, "$uc_type test $last\n"; + $canon = $last; + } + + return (join("", @result), $canon) + if $type=~/todo/i; + push @result, "\t$type $detail/$max tests, "; + if ($max) { + push @result, sprintf("%.2f",100*(1-$detail/$max)), "% okay"; + } + else { + push @result, "?% okay"; + } + my $ender = 's' x ($skipped > 1); + if ($skipped) { + my $good = $max - $detail - $skipped; + my $skipmsg = " (less $skipped skipped test$ender: $good okay, "; + if ($max) { + my $goodper = sprintf("%.2f",100*($good/$max)); + $skipmsg .= "$goodper%)"; + } + else { + $skipmsg .= "?%)"; + } + push @result, $skipmsg; + } + push @result, "\n"; + my $txt = join "", @result; + return ($txt, $canon); +} + +1; +__END__ + + +=head1 EXPORT + +C<&runtests> is exported by Test::Harness by default. + +C<&execute_tests>, C<$verbose>, C<$switches> and C<$debug> are +exported upon request. + +=head1 DIAGNOSTICS + +=over 4 + +=item C + +If all tests are successful some statistics about the performance are +printed. + +=item C + +For any single script that has failing subtests statistics like the +above are printed. + +=item C + +Scripts that return a non-zero exit status, both C<$? EE 8> +and C<$?> are printed in a message similar to the above. + +=item C + +=item C + +If not all tests were successful, the script dies with one of the +above messages. + +=item C + +If a single subtest decides that further testing will not make sense, +the script dies with this message. + +=back + +=head1 ENVIRONMENT VARIABLES THAT TEST::HARNESS SETS + +Test::Harness sets these before executing the individual tests. + +=over 4 + +=item C + +This is set to a true value. It allows the tests to determine if they +are being executed through the harness or by any other means. + +=item C + +This is the version of Test::Harness. + +=back + +=head1 ENVIRONMENT VARIABLES THAT AFFECT TEST::HARNESS + +=over 4 + +=item C + +This value will be used for the width of the terminal. If it is not +set then it will default to C. If this is not set, it will +default to 80. Note that users of Bourne-sh based shells will need to +C for this module to use that variable. + +=item C + +When true it will make harness attempt to compile the test using +C before running it. + +B This currently only works when sitting in the perl source +directory! + +=item C + +If true, Test::Harness will print debugging information about itself as +it runs the tests. This is different from C, which prints +the output from the test being run. Setting C<$Test::Harness::Debug> will +override this, or you can use the C<-d> switch in the F utility. + +=item C + +When set to the name of a directory, harness will check after each +test whether new files appeared in that directory, and report them as + + LEAKED FILES: scr.tmp 0 my.db + +If relative, directory name is with respect to the current directory at +the moment runtests() was called. Putting absolute path into +C may give more predictable results. + +=item C + +When set to a true value, forces it to behave as though STDOUT were +not a console. You may need to set this if you don't want harness to +output more frequent progress messages using carriage returns. Some +consoles may not handle carriage returns properly (which results in a +somewhat messy output). + +=item C + +Usually your tests will be run by C<$^X>, the currently-executing Perl. +However, you may want to have it run by a different executable, such as +a threading perl, or a different version. + +If you're using the F utility, you can use the C<--perl> switch. + +=item C + +Its value will be prepended to the switches used to invoke perl on +each test. For example, setting C to C<-W> will +run all tests with all warnings enabled. + +=item C + +Setting this to true will make the harness display the number of +milliseconds each test took. You can also use F's C<--timer> +switch. + +=item C + +If true, Test::Harness will output the verbose results of running +its tests. Setting C<$Test::Harness::verbose> will override this, +or you can use the C<-v> switch in the F utility. + +If true, Test::Harness will output the verbose results of running +its tests. Setting C<$Test::Harness::verbose> will override this, +or you can use the C<-v> switch in the F utility. + +=item C + +Defines the Test::Harness::Straps subclass to use. The value may either +be a filename or a class name. + +If HARNESS_STRAP_CLASS is a class name, the class must be in C<@INC> +like any other class. + +If HARNESS_STRAP_CLASS is a filename, the .pm file must return the name +of the class, instead of the canonical "1". + +=back + +=head1 EXAMPLE + +Here's how Test::Harness tests itself + + $ cd ~/src/devel/Test-Harness + $ perl -Mblib -e 'use Test::Harness qw(&runtests $verbose); + $verbose=0; runtests @ARGV;' t/*.t + Using /home/schwern/src/devel/Test-Harness/blib + t/base..............ok + t/nonumbers.........ok + t/ok................ok + t/test-harness......ok + All tests successful. + Files=4, Tests=24, 2 wallclock secs ( 0.61 cusr + 0.41 csys = 1.02 CPU) + +=head1 SEE ALSO + +The included F utility for running test scripts from the command line, +L and L for writing test scripts, L for +the underlying timing routines, and L for test coverage +analysis. + +=head1 TODO + +Provide a way of running tests quietly (ie. no printing) for automated +validation of tests. This will probably take the form of a version +of runtests() which rather than printing its output returns raw data +on the state of the tests. (Partially done in Test::Harness::Straps) + +Document the format. + +Fix HARNESS_COMPILE_TEST without breaking its core usage. + +Figure a way to report test names in the failure summary. + +Rework the test summary so long test names are not truncated as badly. +(Partially done with new skip test styles) + +Add option for coverage analysis. + +Trap STDERR. + +Implement Straps total_results() + +Remember exit code + +Completely redo the print summary code. + +Straps->analyze_file() not taint clean, don't know if it can be + +Fix that damned VMS nit. + +Add a test for verbose. + +Change internal list of test results to a hash. + +Fix stats display when there's an overrun. + +Fix so perls with spaces in the filename work. + +Keeping whittling away at _run_all_tests() + +Clean up how the summary is printed. Get rid of those damned formats. + +=head1 BUGS + +Please report any bugs or feature requests to +C, or through the web interface at +L. +I will be notified, and then you'll automatically be notified of progress on +your bug as I make changes. + +=head1 SUPPORT + +You can find documentation for this module with the F command. + + perldoc Test::Harness + +You can get docs for F with + + prove --man + +You can also look for information at: + +=over 4 + +=item * AnnoCPAN: Annotated CPAN documentation + +L + +=item * CPAN Ratings + +L + +=item * RT: CPAN's request tracker + +L + +=item * Search CPAN + +L + +=back + +=head1 SOURCE CODE + +The source code repository for Test::Harness is at +L. + +=head1 AUTHORS + +Either Tim Bunce or Andreas Koenig, we don't know. What we know for +sure is, that it was inspired by Larry Wall's F script that came +with perl distributions for ages. Numerous anonymous contributors +exist. Andreas Koenig held the torch for many years, and then +Michael G Schwern. + +Current maintainer is Andy Lester C<< >>. + +=head1 COPYRIGHT + +Copyright 2002-2006 +by Michael G Schwern C<< >>, +Andy Lester C<< >>. + +This program is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + +See L. + +=cut diff --git a/SecurityTests/regressions/inc/Test/Harness/Assert.pm b/SecurityTests/regressions/inc/Test/Harness/Assert.pm new file mode 100644 index 00000000..29f6c7ad --- /dev/null +++ b/SecurityTests/regressions/inc/Test/Harness/Assert.pm @@ -0,0 +1,64 @@ +package Test::Harness::Assert; + +use strict; +require Exporter; +use vars qw($VERSION @EXPORT @ISA); + +$VERSION = '0.02'; + +@ISA = qw(Exporter); +@EXPORT = qw(assert); + + +=head1 NAME + +Test::Harness::Assert - simple assert + +=head1 SYNOPSIS + + ### FOR INTERNAL USE ONLY ### + + use Test::Harness::Assert; + + assert( EXPR, $name ); + +=head1 DESCRIPTION + +A simple assert routine since we don't have Carp::Assert handy. + +B + +=head1 FUNCTIONS + +=head2 C + + assert( EXPR, $name ); + +If the expression is false the program aborts. + +=cut + +sub assert ($;$) { + my($assert, $name) = @_; + + unless( $assert ) { + require Carp; + my $msg = 'Assert failed'; + $msg .= " - '$name'" if defined $name; + $msg .= '!'; + Carp::croak($msg); + } + +} + +=head1 AUTHOR + +Michael G Schwern C<< >> + +=head1 SEE ALSO + +L + +=cut + +1; diff --git a/SecurityTests/regressions/inc/Test/Harness/Iterator.pm b/SecurityTests/regressions/inc/Test/Harness/Iterator.pm new file mode 100644 index 00000000..2648cea7 --- /dev/null +++ b/SecurityTests/regressions/inc/Test/Harness/Iterator.pm @@ -0,0 +1,70 @@ +package Test::Harness::Iterator; + +use strict; +use vars qw($VERSION); +$VERSION = 0.02; + +=head1 NAME + +Test::Harness::Iterator - Internal Test::Harness Iterator + +=head1 SYNOPSIS + + use Test::Harness::Iterator; + my $it = Test::Harness::Iterator->new(\*TEST); + my $it = Test::Harness::Iterator->new(\@array); + + my $line = $it->next; + +=head1 DESCRIPTION + +B + +This is a simple iterator wrapper for arrays and filehandles. + +=head2 new() + +Create an iterator. + +=head2 next() + +Iterate through it, of course. + +=cut + +sub new { + my($proto, $thing) = @_; + + my $self = {}; + if( ref $thing eq 'GLOB' ) { + bless $self, 'Test::Harness::Iterator::FH'; + $self->{fh} = $thing; + } + elsif( ref $thing eq 'ARRAY' ) { + bless $self, 'Test::Harness::Iterator::ARRAY'; + $self->{idx} = 0; + $self->{array} = $thing; + } + else { + warn "Can't iterate with a ", ref $thing; + } + + return $self; +} + +package Test::Harness::Iterator::FH; +sub next { + my $fh = $_[0]->{fh}; + + # readline() doesn't work so good on 5.5.4. + return scalar <$fh>; +} + + +package Test::Harness::Iterator::ARRAY; +sub next { + my $self = shift; + return $self->{array}->[$self->{idx}++]; +} + +"Steve Peters, Master Of True Value Finding, was here."; diff --git a/SecurityTests/regressions/inc/Test/Harness/Point.pm b/SecurityTests/regressions/inc/Test/Harness/Point.pm new file mode 100644 index 00000000..df0706ac --- /dev/null +++ b/SecurityTests/regressions/inc/Test/Harness/Point.pm @@ -0,0 +1,143 @@ +# -*- Mode: cperl; cperl-indent-level: 4 -*- +package Test::Harness::Point; + +use strict; +use vars qw($VERSION); +$VERSION = '0.01'; + +=head1 NAME + +Test::Harness::Point - object for tracking a single test point + +=head1 SYNOPSIS + +One Test::Harness::Point object represents a single test point. + +=head1 CONSTRUCTION + +=head2 new() + + my $point = new Test::Harness::Point; + +Create a test point object. + +=cut + +sub new { + my $class = shift; + my $self = bless {}, $class; + + return $self; +} + +=head1 from_test_line( $line ) + +Constructor from a TAP test line, or empty return if the test line +is not a test line. + +=cut + +sub from_test_line { + my $class = shift; + my $line = shift or return; + + # We pulverize the line down into pieces in three parts. + my ($not, $number, $extra) = ($line =~ /^(not )?ok\b(?:\s+(\d+))?\s*(.*)/) or return; + + my $point = $class->new; + $point->set_number( $number ); + $point->set_ok( !$not ); + + if ( $extra ) { + my ($description,$directive) = split( /(?:[^\\]|^)#/, $extra, 2 ); + $description =~ s/^- //; # Test::More puts it in there + $point->set_description( $description ); + if ( $directive ) { + $point->set_directive( $directive ); + } + } # if $extra + + return $point; +} # from_test_line() + +=head1 ACCESSORS + +Each of the following fields has a getter and setter method. + +=over 4 + +=item * ok + +=item * number + +=cut + +sub ok { my $self = shift; $self->{ok} } +sub set_ok { + my $self = shift; + my $ok = shift; + $self->{ok} = $ok ? 1 : 0; +} +sub pass { + my $self = shift; + + return ($self->ok || $self->is_todo || $self->is_skip) ? 1 : 0; +} + +sub number { my $self = shift; $self->{number} } +sub set_number { my $self = shift; $self->{number} = shift } + +sub description { my $self = shift; $self->{description} } +sub set_description { + my $self = shift; + $self->{description} = shift; + $self->{name} = $self->{description}; # history +} + +sub directive { my $self = shift; $self->{directive} } +sub set_directive { + my $self = shift; + my $directive = shift; + + $directive =~ s/^\s+//; + $directive =~ s/\s+$//; + $self->{directive} = $directive; + + my ($type,$reason) = ($directive =~ /^\s*(\S+)(?:\s+(.*))?$/); + $self->set_directive_type( $type ); + $reason = "" unless defined $reason; + $self->{directive_reason} = $reason; +} +sub set_directive_type { + my $self = shift; + $self->{directive_type} = lc shift; + $self->{type} = $self->{directive_type}; # History +} +sub set_directive_reason { + my $self = shift; + $self->{directive_reason} = shift; +} +sub directive_type { my $self = shift; $self->{directive_type} } +sub type { my $self = shift; $self->{directive_type} } +sub directive_reason{ my $self = shift; $self->{directive_reason} } +sub reason { my $self = shift; $self->{directive_reason} } +sub is_todo { + my $self = shift; + my $type = $self->directive_type; + return $type && ( $type eq 'todo' ); +} +sub is_skip { + my $self = shift; + my $type = $self->directive_type; + return $type && ( $type eq 'skip' ); +} + +sub diagnostics { + my $self = shift; + return @{$self->{diagnostics}} if wantarray; + return join( "\n", @{$self->{diagnostics}} ); +} +sub add_diagnostic { my $self = shift; push @{$self->{diagnostics}}, @_ } + + +1; diff --git a/SecurityTests/regressions/inc/Test/Harness/Results.pm b/SecurityTests/regressions/inc/Test/Harness/Results.pm new file mode 100644 index 00000000..4b86bd7a --- /dev/null +++ b/SecurityTests/regressions/inc/Test/Harness/Results.pm @@ -0,0 +1,182 @@ +# -*- Mode: cperl; cperl-indent-level: 4 -*- +package Test::Harness::Results; + +use strict; +use vars qw($VERSION); +$VERSION = '0.01_01'; + +=head1 NAME + +Test::Harness::Results - object for tracking results from a single test file + +=head1 SYNOPSIS + +One Test::Harness::Results object represents the results from one +test file getting analyzed. + +=head1 CONSTRUCTION + +=head2 new() + + my $results = new Test::Harness::Results; + +Create a test point object. Typically, however, you'll not create +one yourself, but access a Results object returned to you by +Test::Harness::Results. + +=cut + +sub new { + my $class = shift; + my $self = bless {}, $class; + + return $self; +} + +=head1 ACCESSORS + +The following data points are defined: + + passing true if the whole test is considered a pass + (or skipped), false if its a failure + + exit the exit code of the test run, if from a file + wait the wait code of the test run, if from a file + + max total tests which should have been run + seen total tests actually seen + skip_all if the whole test was skipped, this will + contain the reason. + + ok number of tests which passed + (including todo and skips) + + todo number of todo tests seen + bonus number of todo tests which + unexpectedly passed + + skip number of tests skipped + +So a successful test should have max == seen == ok. + + +There is one final item, the details. + + details an array ref reporting the result of + each test looks like this: + + $results{details}[$test_num - 1] = + { ok => is the test considered ok? + actual_ok => did it literally say 'ok'? + name => name of the test (if any) + diagnostics => test diagnostics (if any) + type => 'skip' or 'todo' (if any) + reason => reason for the above (if any) + }; + +Element 0 of the details is test #1. I tried it with element 1 being +#1 and 0 being empty, this is less awkward. + + +Each of the following fields has a getter and setter method. + +=over 4 + +=item * wait + +=item * exit + +=cut + +sub set_wait { my $self = shift; $self->{wait} = shift } +sub wait { + my $self = shift; + return $self->{wait} || 0; +} + +sub set_skip_all { my $self = shift; $self->{skip_all} = shift } +sub skip_all { + my $self = shift; + return $self->{skip_all}; +} + +sub inc_max { my $self = shift; $self->{max} += (@_ ? shift : 1) } +sub max { + my $self = shift; + return $self->{max} || 0; +} + +sub set_passing { my $self = shift; $self->{passing} = shift } +sub passing { + my $self = shift; + return $self->{passing} || 0; +} + +sub inc_ok { my $self = shift; $self->{ok} += (@_ ? shift : 1) } +sub ok { + my $self = shift; + return $self->{ok} || 0; +} + +sub set_exit { + my $self = shift; + if ($^O eq 'VMS') { + eval { + use vmsish q(status); + $self->{exit} = shift; # must be in same scope as pragma + } + } + else { + $self->{exit} = shift; + } +} +sub exit { + my $self = shift; + return $self->{exit} || 0; +} + +sub inc_bonus { my $self = shift; $self->{bonus}++ } +sub bonus { + my $self = shift; + return $self->{bonus} || 0; +} + +sub set_skip_reason { my $self = shift; $self->{skip_reason} = shift } +sub skip_reason { + my $self = shift; + return $self->{skip_reason} || 0; +} + +sub inc_skip { my $self = shift; $self->{skip}++ } +sub skip { + my $self = shift; + return $self->{skip} || 0; +} + +sub inc_todo { my $self = shift; $self->{todo}++ } +sub todo { + my $self = shift; + return $self->{todo} || 0; +} + +sub inc_seen { my $self = shift; $self->{seen}++ } +sub seen { + my $self = shift; + return $self->{seen} || 0; +} + +sub set_details { + my $self = shift; + my $index = shift; + my $details = shift; + + my $array = ($self->{details} ||= []); + $array->[$index-1] = $details; +} + +sub details { + my $self = shift; + return $self->{details} || []; +} + +1; diff --git a/SecurityTests/regressions/inc/Test/Harness/Straps.pm b/SecurityTests/regressions/inc/Test/Harness/Straps.pm new file mode 100644 index 00000000..3ee529c2 --- /dev/null +++ b/SecurityTests/regressions/inc/Test/Harness/Straps.pm @@ -0,0 +1,648 @@ +# -*- Mode: cperl; cperl-indent-level: 4 -*- +package Test::Harness::Straps; + +use strict; +use vars qw($VERSION); +$VERSION = '0.26_01'; + +use Config; +use Test::Harness::Assert; +use Test::Harness::Iterator; +use Test::Harness::Point; +use Test::Harness::Results; + +# Flags used as return values from our methods. Just for internal +# clarification. +my $YES = (1==1); +my $NO = !$YES; + +=head1 NAME + +Test::Harness::Straps - detailed analysis of test results + +=head1 SYNOPSIS + + use Test::Harness::Straps; + + my $strap = Test::Harness::Straps->new; + + # Various ways to interpret a test + my $results = $strap->analyze($name, \@test_output); + my $results = $strap->analyze_fh($name, $test_filehandle); + my $results = $strap->analyze_file($test_file); + + # UNIMPLEMENTED + my %total = $strap->total_results; + + # Altering the behavior of the strap UNIMPLEMENTED + my $verbose_output = $strap->dump_verbose(); + $strap->dump_verbose_fh($output_filehandle); + + +=head1 DESCRIPTION + +B in that the interface is subject to change +in incompatible ways. It is otherwise stable. + +Test::Harness is limited to printing out its results. This makes +analysis of the test results difficult for anything but a human. To +make it easier for programs to work with test results, we provide +Test::Harness::Straps. Instead of printing the results, straps +provide them as raw data. You can also configure how the tests are to +be run. + +The interface is currently incomplete. I contact the author +if you'd like a feature added or something change or just have +comments. + +=head1 CONSTRUCTION + +=head2 new() + + my $strap = Test::Harness::Straps->new; + +Initialize a new strap. + +=cut + +sub new { + my $class = shift; + my $self = bless {}, $class; + + $self->_init; + + return $self; +} + +=for private $strap->_init + + $strap->_init; + +Initialize the internal state of a strap to make it ready for parsing. + +=cut + +sub _init { + my($self) = shift; + + $self->{_is_vms} = ( $^O eq 'VMS' ); + $self->{_is_win32} = ( $^O =~ /^(MS)?Win32$/ ); + $self->{_is_macos} = ( $^O eq 'MacOS' ); +} + +=head1 ANALYSIS + +=head2 $strap->analyze( $name, \@output_lines ) + + my $results = $strap->analyze($name, \@test_output); + +Analyzes the output of a single test, assigning it the given C<$name> +for use in the total report. Returns the C<$results> of the test. +See L. + +C<@test_output> should be the raw output from the test, including +newlines. + +=cut + +sub analyze { + my($self, $name, $test_output) = @_; + + my $it = Test::Harness::Iterator->new($test_output); + return $self->_analyze_iterator($name, $it); +} + + +sub _analyze_iterator { + my($self, $name, $it) = @_; + + $self->_reset_file_state; + $self->{file} = $name; + + my $results = Test::Harness::Results->new; + + # Set them up here so callbacks can have them. + $self->{totals}{$name} = $results; + while( defined(my $line = $it->next) ) { + $self->_analyze_line($line, $results); + last if $self->{saw_bailout}; + } + + $results->set_skip_all( $self->{skip_all} ) if defined $self->{skip_all}; + + my $passed = + (($results->max == 0) && defined $results->skip_all) || + ($results->max && + $results->seen && + $results->max == $results->seen && + $results->max == $results->ok); + + $results->set_passing( $passed ? 1 : 0 ); + + return $results; +} + + +sub _analyze_line { + my $self = shift; + my $line = shift; + my $results = shift; + + $self->{line}++; + + my $linetype; + my $point = Test::Harness::Point->from_test_line( $line ); + if ( $point ) { + $linetype = 'test'; + + $results->inc_seen; + $point->set_number( $self->{'next'} ) unless $point->number; + + # sometimes the 'not ' and the 'ok' are on different lines, + # happens often on VMS if you do: + # print "not " unless $test; + # print "ok $num\n"; + if ( $self->{lone_not_line} && ($self->{lone_not_line} == $self->{line} - 1) ) { + $point->set_ok( 0 ); + } + + if ( $self->{todo}{$point->number} ) { + $point->set_directive_type( 'todo' ); + } + + if ( $point->is_todo ) { + $results->inc_todo; + $results->inc_bonus if $point->ok; + } + elsif ( $point->is_skip ) { + $results->inc_skip; + } + + $results->inc_ok if $point->pass; + + if ( ($point->number > 100_000) && ($point->number > ($self->{max}||100_000)) ) { + if ( !$self->{too_many_tests}++ ) { + warn "Enormous test number seen [test ", $point->number, "]\n"; + warn "Can't detailize, too big.\n"; + } + } + else { + my $details = { + ok => $point->pass, + actual_ok => $point->ok, + name => _def_or_blank( $point->description ), + type => _def_or_blank( $point->directive_type ), + reason => _def_or_blank( $point->directive_reason ), + }; + + assert( defined( $details->{ok} ) && defined( $details->{actual_ok} ) ); + $results->set_details( $point->number, $details ); + } + } # test point + elsif ( $line =~ /^not\s+$/ ) { + $linetype = 'other'; + # Sometimes the "not " and "ok" will be on separate lines on VMS. + # We catch this and remember we saw it. + $self->{lone_not_line} = $self->{line}; + } + elsif ( $self->_is_header($line) ) { + $linetype = 'header'; + + $self->{saw_header}++; + + $results->inc_max( $self->{max} ); + } + elsif ( $self->_is_bail_out($line, \$self->{bailout_reason}) ) { + $linetype = 'bailout'; + $self->{saw_bailout} = 1; + } + elsif (my $diagnostics = $self->_is_diagnostic_line( $line )) { + $linetype = 'other'; + # XXX We can throw this away, really. + my $test = $results->details->[-1]; + $test->{diagnostics} ||= ''; + $test->{diagnostics} .= $diagnostics; + } + else { + $linetype = 'other'; + } + + $self->callback->($self, $line, $linetype, $results) if $self->callback; + + $self->{'next'} = $point->number + 1 if $point; +} # _analyze_line + + +sub _is_diagnostic_line { + my ($self, $line) = @_; + return if index( $line, '# Looks like you failed' ) == 0; + $line =~ s/^#\s//; + return $line; +} + +=for private $strap->analyze_fh( $name, $test_filehandle ) + + my $results = $strap->analyze_fh($name, $test_filehandle); + +Like C, but it reads from the given filehandle. + +=cut + +sub analyze_fh { + my($self, $name, $fh) = @_; + + my $it = Test::Harness::Iterator->new($fh); + return $self->_analyze_iterator($name, $it); +} + +=head2 $strap->analyze_file( $test_file ) + + my $results = $strap->analyze_file($test_file); + +Like C, but it runs the given C<$test_file> and parses its +results. It will also use that name for the total report. + +=cut + +sub analyze_file { + my($self, $file) = @_; + + unless( -e $file ) { + $self->{error} = "$file does not exist"; + return; + } + + unless( -r $file ) { + $self->{error} = "$file is not readable"; + return; + } + + local $ENV{PERL5LIB} = $self->_INC2PERL5LIB; + if ( $Test::Harness::Debug ) { + local $^W=0; # ignore undef warnings + print "# PERL5LIB=$ENV{PERL5LIB}\n"; + } + + # *sigh* this breaks under taint, but open -| is unportable. + my $line = $self->_command_line($file); + + unless ( open(FILE, "$line|" )) { + print "can't run $file. $!\n"; + return; + } + + my $results = $self->analyze_fh($file, \*FILE); + my $exit = close FILE; + + $results->set_wait($?); + if ( $? && $self->{_is_vms} ) { + $results->set_exit($?); + } + else { + $results->set_exit( _wait2exit($?) ); + } + $results->set_passing(0) unless $? == 0; + + $self->_restore_PERL5LIB(); + + return $results; +} + + +eval { require POSIX; &POSIX::WEXITSTATUS(0) }; +if( $@ ) { + *_wait2exit = sub { $_[0] >> 8 }; +} +else { + *_wait2exit = sub { POSIX::WEXITSTATUS($_[0]) } +} + +=for private $strap->_command_line( $file ) + +Returns the full command line that will be run to test I<$file>. + +=cut + +sub _command_line { + my $self = shift; + my $file = shift; + + my $command = $self->_command(); + my $switches = $self->_switches($file); + + $file = qq["$file"] if ($file =~ /\s/) && ($file !~ /^".*"$/); + my $line = "$command $switches $file"; + + return $line; +} + + +=for private $strap->_command() + +Returns the command that runs the test. Combine this with C<_switches()> +to build a command line. + +Typically this is C<$^X>, but you can set C<$ENV{HARNESS_PERL}> +to use a different Perl than what you're running the harness under. +This might be to run a threaded Perl, for example. + +You can also overload this method if you've built your own strap subclass, +such as a PHP interpreter for a PHP-based strap. + +=cut + +sub _command { + my $self = shift; + + return $ENV{HARNESS_PERL} if defined $ENV{HARNESS_PERL}; + #return qq["$^X"] if $self->{_is_win32} && ($^X =~ /[^\w\.\/\\]/); + return qq["$^X"] if $^X =~ /\s/ and $^X !~ /^["']/; + return $^X; +} + + +=for private $strap->_switches( $file ) + +Formats and returns the switches necessary to run the test. + +=cut + +sub _switches { + my($self, $file) = @_; + + my @existing_switches = $self->_cleaned_switches( $Test::Harness::Switches, $ENV{HARNESS_PERL_SWITCHES} ); + my @derived_switches; + + local *TEST; + open(TEST, $file) or print "can't open $file. $!\n"; + my $shebang = ; + close(TEST) or print "can't close $file. $!\n"; + + my $taint = ( $shebang =~ /^#!.*\bperl.*\s-\w*([Tt]+)/ ); + push( @derived_switches, "-$1" ) if $taint; + + # When taint mode is on, PERL5LIB is ignored. So we need to put + # all that on the command line as -Is. + # MacPerl's putenv is broken, so it will not see PERL5LIB, tainted or not. + if ( $taint || $self->{_is_macos} ) { + my @inc = $self->_filtered_INC; + push @derived_switches, map { "-I$_" } @inc; + } + + # Quote the argument if there's any whitespace in it, or if + # we're VMS, since VMS requires all parms quoted. Also, don't quote + # it if it's already quoted. + for ( @derived_switches ) { + $_ = qq["$_"] if ((/\s/ || $self->{_is_vms}) && !/^".*"$/ ); + } + return join( " ", @existing_switches, @derived_switches ); +} + +=for private $strap->_cleaned_switches( @switches_from_user ) + +Returns only defined, non-blank, trimmed switches from the parms passed. + +=cut + +sub _cleaned_switches { + my $self = shift; + + local $_; + + my @switches; + for ( @_ ) { + my $switch = $_; + next unless defined $switch; + $switch =~ s/^\s+//; + $switch =~ s/\s+$//; + push( @switches, $switch ) if $switch ne ""; + } + + return @switches; +} + +=for private $strap->_INC2PERL5LIB + + local $ENV{PERL5LIB} = $self->_INC2PERL5LIB; + +Takes the current value of C<@INC> and turns it into something suitable +for putting onto C. + +=cut + +sub _INC2PERL5LIB { + my($self) = shift; + + $self->{_old5lib} = $ENV{PERL5LIB}; + + return join $Config{path_sep}, $self->_filtered_INC; +} + +=for private $strap->_filtered_INC() + + my @filtered_inc = $self->_filtered_INC; + +Shortens C<@INC> by removing redundant and unnecessary entries. +Necessary for OSes with limited command line lengths, like VMS. + +=cut + +sub _filtered_INC { + my($self, @inc) = @_; + @inc = @INC unless @inc; + + if( $self->{_is_vms} ) { + # VMS has a 255-byte limit on the length of %ENV entries, so + # toss the ones that involve perl_root, the install location + @inc = grep !/perl_root/i, @inc; + + } + elsif ( $self->{_is_win32} ) { + # Lose any trailing backslashes in the Win32 paths + s/[\\\/+]$// foreach @inc; + } + + my %seen; + $seen{$_}++ foreach $self->_default_inc(); + @inc = grep !$seen{$_}++, @inc; + + return @inc; +} + + +{ # Without caching, _default_inc() takes a huge amount of time + my %cache; + sub _default_inc { + my $self = shift; + my $perl = $self->_command; + $cache{$perl} ||= [do { + local $ENV{PERL5LIB}; + my @inc =`$perl -le "print join qq[\\n], \@INC"`; + chomp @inc; + }]; + return @{$cache{$perl}}; + } +} + + +=for private $strap->_restore_PERL5LIB() + + $self->_restore_PERL5LIB; + +This restores the original value of the C environment variable. +Necessary on VMS, otherwise a no-op. + +=cut + +sub _restore_PERL5LIB { + my($self) = shift; + + return unless $self->{_is_vms}; + + if (defined $self->{_old5lib}) { + $ENV{PERL5LIB} = $self->{_old5lib}; + } +} + +=head1 Parsing + +Methods for identifying what sort of line you're looking at. + +=for private _is_diagnostic + + my $is_diagnostic = $strap->_is_diagnostic($line, \$comment); + +Checks if the given line is a comment. If so, it will place it into +C<$comment> (sans #). + +=cut + +sub _is_diagnostic { + my($self, $line, $comment) = @_; + + if( $line =~ /^\s*\#(.*)/ ) { + $$comment = $1; + return $YES; + } + else { + return $NO; + } +} + +=for private _is_header + + my $is_header = $strap->_is_header($line); + +Checks if the given line is a header (1..M) line. If so, it places how +many tests there will be in C<< $strap->{max} >>, a list of which tests +are todo in C<< $strap->{todo} >> and if the whole test was skipped +C<< $strap->{skip_all} >> contains the reason. + +=cut + +# Regex for parsing a header. Will be run with /x +my $Extra_Header_Re = <<'REGEX'; + ^ + (?: \s+ todo \s+ ([\d \t]+) )? # optional todo set + (?: \s* \# \s* ([\w:]+\s?) (.*) )? # optional skip with optional reason +REGEX + +sub _is_header { + my($self, $line) = @_; + + if( my($max, $extra) = $line =~ /^1\.\.(\d+)(.*)/ ) { + $self->{max} = $max; + assert( $self->{max} >= 0, 'Max # of tests looks right' ); + + if( defined $extra ) { + my($todo, $skip, $reason) = $extra =~ /$Extra_Header_Re/xo; + + $self->{todo} = { map { $_ => 1 } split /\s+/, $todo } if $todo; + + if( $self->{max} == 0 ) { + $reason = '' unless defined $skip and $skip =~ /^Skip/i; + } + + $self->{skip_all} = $reason; + } + + return $YES; + } + else { + return $NO; + } +} + +=for private _is_bail_out + + my $is_bail_out = $strap->_is_bail_out($line, \$reason); + +Checks if the line is a "Bail out!". Places the reason for bailing +(if any) in $reason. + +=cut + +sub _is_bail_out { + my($self, $line, $reason) = @_; + + if( $line =~ /^Bail out!\s*(.*)/i ) { + $$reason = $1 if $1; + return $YES; + } + else { + return $NO; + } +} + +=for private _reset_file_state + + $strap->_reset_file_state; + +Resets things like C<< $strap->{max} >> , C<< $strap->{skip_all} >>, +etc. so it's ready to parse the next file. + +=cut + +sub _reset_file_state { + my($self) = shift; + + delete @{$self}{qw(max skip_all todo too_many_tests)}; + $self->{line} = 0; + $self->{saw_header} = 0; + $self->{saw_bailout}= 0; + $self->{lone_not_line} = 0; + $self->{bailout_reason} = ''; + $self->{'next'} = 1; +} + +=head1 EXAMPLES + +See F for an example of use. + +=head1 AUTHOR + +Michael G Schwern C<< >>, currently maintained by +Andy Lester C<< >>. + +=head1 SEE ALSO + +L + +=cut + +sub _def_or_blank { + return $_[0] if defined $_[0]; + return ""; +} + +sub set_callback { + my $self = shift; + $self->{callback} = shift; +} + +sub callback { + my $self = shift; + return $self->{callback}; +} + +1; diff --git a/SecurityTests/regressions/inc/Test/Harness/TAP.pod b/SecurityTests/regressions/inc/Test/Harness/TAP.pod new file mode 100644 index 00000000..deb506db --- /dev/null +++ b/SecurityTests/regressions/inc/Test/Harness/TAP.pod @@ -0,0 +1,492 @@ +=head1 NAME + +Test::Harness::TAP - Documentation for the TAP format + +=head1 SYNOPSIS + +TAP, the Test Anything Protocol, is Perl's simple text-based interface +between testing modules such as Test::More and the test harness +Test::Harness. + +=head1 TODO + +Exit code of the process. + +=head1 THE TAP FORMAT + +TAP's general format is: + + 1..N + ok 1 Description # Directive + # Diagnostic + .... + ok 47 Description + ok 48 Description + more tests.... + +For example, a test file's output might look like: + + 1..4 + ok 1 - Input file opened + not ok 2 - First line of the input valid + ok 3 - Read the rest of the file + not ok 4 - Summarized correctly # TODO Not written yet + +=head1 HARNESS BEHAVIOR + +In this document, the "harness" is any program analyzing TAP output. +Typically this will be Perl's I program, or the underlying +C subroutine. + +A harness must only read TAP output from standard output and not +from standard error. Lines written to standard output matching +C must be interpreted as test lines. All other +lines must not be considered test output. + +=head1 TESTS LINES AND THE PLAN + +=head2 The plan + +The plan tells how many tests will be run, or how many tests have +run. It's a check that the test file hasn't stopped prematurely. +It must appear once, whether at the beginning or end of the output. + +The plan is usually the first line of TAP output and it specifies how +many test points are to follow. For example, + + 1..10 + +means you plan on running 10 tests. This is a safeguard in case your test +file dies silently in the middle of its run. The plan is optional but if +there is a plan before the test points it must be the first non-diagnostic +line output by the test file. + +In certain instances a test file may not know how many test points +it will ultimately be running. In this case the plan can be the last +non-diagnostic line in the output. + +The plan cannot appear in the middle of the output, nor can it appear more +than once. + +=head2 The test line + +The core of TAP is the test line. A test file prints one test line test +point executed. There must be at least one test line in TAP output. Each +test line comprises the following elements: + +=over 4 + +=item * C or C + +This tells whether the test point passed or failed. It must be +at the beginning of the line. C indicates a failed test +point. C is a successful test point. This is the only mandatory +part of the line. + +Note that unlike the Directives below, C and C are +case-sensitive. + +=item * Test number + +TAP expects the C or C to be followed by a test point +number. If there is no number the harness must maintain +its own counter until the script supplies test numbers again. So +the following test output + + 1..6 + not ok + ok + not ok + ok + ok + +has five tests. The sixth is missing. Test::Harness will generate + + FAILED tests 1, 3, 6 + Failed 3/6 tests, 50.00% okay + +=item * Description + +Any text after the test number but before a C<#> is the description of +the test point. + + ok 42 this is the description of the test + +Descriptions should not begin with a digit so that they are not confused +with the test point number. + +The harness may do whatever it wants with the description. + +=item * Directive + +The test point may include a directive, following a hash on the +test line. There are currently two directives allowed: C and +C. These are discussed below. + +=back + +To summarize: + +=over 4 + +=item * ok/not ok (required) + +=item * Test number (recommended) + +=item * Description (recommended) + +=item * Directive (only when necessary) + +=back + +=head1 DIRECTIVES + +Directives are special notes that follow a C<#> on the test line. +Only two are currently defined: C and C. Note that +these two keywords are not case-sensitive. + +=head2 TODO tests + +If the directive starts with C<# TODO>, the test is counted as a +todo test, and the text after C is the explanation. + + not ok 13 # TODO bend space and time + +Note that if the TODO has an explanation it must be separated from +C by a space. + +These tests represent a feature to be implemented or a bug to be fixed +and act as something of an executable "things to do" list. They are +B expected to succeed. Should a todo test point begin succeeding, +the harness should report it as a bonus. This indicates that whatever +you were supposed to do has been done and you should promote this to a +normal test point. + +=head2 Skipping tests + +If the directive starts with C<# SKIP>, the test is counted as having +been skipped. If the whole test file succeeds, the count of skipped +tests is included in the generated output. The harness should report +the text after C< # SKIP\S*\s+> as a reason for skipping. + + ok 23 # skip Insufficient flogiston pressure. + +Similarly, one can include an explanation in a plan line, +emitted if the test file is skipped completely: + + 1..0 # Skipped: WWW::Mechanize not installed + +=head1 OTHER LINES + +=head2 Bail out! + +As an emergency measure a test script can decide that further tests +are useless (e.g. missing dependencies) and testing should stop +immediately. In that case the test script prints the magic words + + Bail out! + +to standard output. Any message after these words must be displayed +by the interpreter as the reason why testing must be stopped, as +in + + Bail out! MySQL is not running. + +=head2 Diagnostics + +Additional information may be put into the testing output on separate +lines. Diagnostic lines should begin with a C<#>, which the harness must +ignore, at least as far as analyzing the test results. The harness is +free, however, to display the diagnostics. Typically diagnostics are +used to provide information about the environment in which test file is +running, or to delineate a group of tests. + + ... + ok 18 - Closed database connection + # End of database section. + # This starts the network part of the test. + # Daemon started on port 2112 + ok 19 - Opened socket + ... + ok 47 - Closed socket + # End of network tests + +=head2 Anything else + +Any output line that is not a plan, a test line or a diagnostic is +incorrect. How a harness handles the incorrect line is undefined. +Test::Harness silently ignores incorrect lines, but will become more +stringent in the future. + +=head1 EXAMPLES + +All names, places, and events depicted in any example are wholly +fictitious and bear no resemblance to, connection with, or relation to any +real entity. Any such similarity is purely coincidental, unintentional, +and unintended. + +=head2 Common with explanation + +The following TAP listing declares that six tests follow as well as +provides handy feedback as to what the test is about to do. All six +tests pass. + + 1..6 + # + # Create a new Board and Tile, then place + # the Tile onto the board. + # + ok 1 - The object isa Board + ok 2 - Board size is zero + ok 3 - The object isa Tile + ok 4 - Get possible places to put the Tile + ok 5 - Placing the tile produces no error + ok 6 - Board size is 1 + +=head2 Unknown amount and failures + +This hypothetical test program ensures that a handful of servers are +online and network-accessible. Because it retrieves the hypothetical +servers from a database, it doesn't know exactly how many servers it +will need to ping. Thus, the test count is declared at the bottom after +all the test points have run. Also, two of the tests fail. + + ok 1 - retrieving servers from the database + # need to ping 6 servers + ok 2 - pinged diamond + ok 3 - pinged ruby + not ok 4 - pinged saphire + ok 5 - pinged onyx + not ok 6 - pinged quartz + ok 7 - pinged gold + 1..7 + +=head2 Giving up + +This listing reports that a pile of tests are going to be run. However, +the first test fails, reportedly because a connection to the database +could not be established. The program decided that continuing was +pointless and exited. + + 1..573 + not ok 1 - database handle + Bail out! Couldn't connect to database. + +=head2 Skipping a few + +The following listing plans on running 5 tests. However, our program +decided to not run tests 2 thru 5 at all. To properly report this, +the tests are marked as being skipped. + + 1..5 + ok 1 - approved operating system + # $^0 is solaris + ok 2 - # SKIP no /sys directory + ok 3 - # SKIP no /sys directory + ok 4 - # SKIP no /sys directory + ok 5 - # SKIP no /sys directory + +=head2 Skipping everything + +This listing shows that the entire listing is a skip. No tests were run. + + 1..0 # skip because English-to-French translator isn't installed + +=head2 Got spare tuits? + +The following example reports that four tests are run and the last two +tests failed. However, because the failing tests are marked as things +to do later, they are considered successes. Thus, a harness should report +this entire listing as a success. + + 1..4 + ok 1 - Creating test program + ok 2 - Test program runs, no error + not ok 3 - infinite loop # TODO halting problem unsolved + not ok 4 - infinite loop 2 # TODO halting problem unsolved + +=head2 Creative liberties + +This listing shows an alternate output where the test numbers aren't +provided. The test also reports the state of a ficticious board game in +diagnostic form. Finally, the test count is reported at the end. + + ok - created Board + ok + ok + ok + ok + ok + ok + ok + # +------+------+------+------+ + # | |16G | |05C | + # | |G N C | |C C G | + # | | G | | C +| + # +------+------+------+------+ + # |10C |01G | |03C | + # |R N G |G A G | |C C C | + # | R | G | | C +| + # +------+------+------+------+ + # | |01G |17C |00C | + # | |G A G |G N R |R N R | + # | | G | R | G | + # +------+------+------+------+ + ok - board has 7 tiles + starter tile + 1..9 + +=head1 Non-Perl TAP + +In Perl, we use Test::Simple and Test::More to generate TAP output. +Other languages have solutions that generate TAP, so that they can take +advantage of Test::Harness. + +The following sections are provided by their maintainers, and may not +be up-to-date. + +=head2 C/C++ + +libtap makes it easy to write test programs in C that produce +TAP-compatible output. Modeled on the Test::More API, libtap contains +all the functions you need to: + +=over 4 + +=item * Specify a test plan + +=item * Run tests + +=item * Skip tests in certain situations + +=item * Have TODO tests + +=item * Produce TAP compatible diagnostics + +=back + +More information about libtap, including download links, checksums, +anonymous access to the Subersion repository, and a bug tracking +system, can be found at: + + http://jc.ngo.org.uk/trac-bin/trac.cgi/wiki/LibTap + +(Nik Clayton, April 17, 2006) + +=head2 Python + +PyTap will, when it's done, provide a simple, assertive (Test::More-like) +interface for writing tests in Python. It will output TAP and will +include the functionality found in Test::Builder and Test::More. It will +try to make it easy to add more test code (so you can write your own +C, for example. + +Right now, it's got a fair bit of the basics needed to emulate Test::More, +and I think it's easy to add more stuff -- just like Test::Builder, +there's a singleton that you can get at easily. + +I need to better identify and finish implementing the most basic tests. +I am not a Python guru, I just use it from time to time, so my aim may +not be true. I need to write tests for it, which means either relying +on Perl for the tester tester, or writing one in Python. + +Here's a sample test, as found in my Subversion: + + from TAP.Simple import * + + plan(15) + + ok(1) + ok(1, "everything is OK!") + ok(0, "always fails") + + is_ok(10, 10, "is ten ten?") + is_ok(ok, ok, "even ok is ok!") + ok(id(ok), "ok is not the null pointer") + ok(True, "the Truth will set you ok") + ok(not False, "and nothing but the truth") + ok(False, "and we'll know if you lie to us") + + isa_ok(10, int, "10") + isa_ok('ok', str, "some string") + + ok(0, "zero is true", todo="be more like Ruby!") + ok(None, "none is true", skip="not possible in this universe") + + eq_ok("not", "equal", "two strings are not equal"); + +(Ricardo Signes, April 17, 2006) + +=head2 JavaScript + +Test.Simple looks and acts just like TAP, although in reality it's +tracking test results in an object rather than scraping them from a +print buffer. + + http://openjsan.org/doc/t/th/theory/Test/Simple/ + +(David Wheeler, April 17, 2006) + +=head2 PHP + +All the big PHP players now produce TAP + +=over + +=item * phpt + +Outputs TAP by default as of the yet-to-be-released PEAR 1.5.0 + + http://pear.php.net/PEAR + +=item * PHPUnit + +Has a TAP logger (since 2.3.4) + + http://www.phpunit.de/wiki/Main_Page + +=item * SimpleTest + +There's a third-party TAP reporting extension for SimpleTest + + http://www.digitalsandwich.com/archives/51-Updated-Simpletest+Apache-Test.html + +=item * Apache-Test + +Apache-Test's PHP writes TAP by default and includes the standalone +test-more.php + + http://search.cpan.org/dist/Apache-Test/ + +=back + +(Geoffrey Young, April 17, 2006) + +=head1 AUTHORS + +Andy Lester, based on the original Test::Harness documentation by Michael Schwern. + +=head1 ACKNOWLEDGEMENTS + +Thanks to +Pete Krawczyk, +Paul Johnson, +Ian Langworth +and Nik Clayton +for help and contributions on this document. + +The basis for the TAP format was created by Larry Wall in the +original test script for Perl 1. Tim Bunce and Andreas Koenig +developed it further with their modifications to Test::Harness. + +=head1 COPYRIGHT + +Copyright 2003-2005 by +Michael G Schwern C<< >>, +Andy Lester C<< >>. + +This program is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + +See L. + +=cut diff --git a/SecurityTests/regressions/inc/Test/Harness/Util.pm b/SecurityTests/regressions/inc/Test/Harness/Util.pm new file mode 100644 index 00000000..0cda2fee --- /dev/null +++ b/SecurityTests/regressions/inc/Test/Harness/Util.pm @@ -0,0 +1,133 @@ +package Test::Harness::Util; + +use strict; +use vars qw($VERSION); +$VERSION = '0.01'; + +use File::Spec; +use Exporter; +use vars qw( @ISA @EXPORT @EXPORT_OK ); + +@ISA = qw( Exporter ); +@EXPORT = (); +@EXPORT_OK = qw( all_in shuffle blibdirs ); + +=head1 NAME + +Test::Harness::Util - Utility functions for Test::Harness::* + +=head1 SYNOPSIS + +Utility functions for Test::Harness::* + +=head1 PUBLIC FUNCTIONS + +The following are all available to be imported to your module. No symbols +are exported by default. + +=head2 all_in( {parm => value, parm => value} ) + +Finds all the F<*.t> in a directory. Knows to skip F<.svn> and F +directories. + +Valid parms are: + +=over + +=item start + +Starting point for the search. Defaults to ".". + +=item recurse + +Flag to say whether it should recurse. Default to true. + +=back + +=cut + +sub all_in { + my $parms = shift; + my %parms = ( + start => ".", + recurse => 1, + %$parms, + ); + + my @hits = (); + my $start = $parms{start}; + + local *DH; + if ( opendir( DH, $start ) ) { + my @files = sort readdir DH; + closedir DH; + for my $file ( @files ) { + next if $file eq File::Spec->updir || $file eq File::Spec->curdir; + next if $file eq ".svn"; + next if $file eq "CVS"; + + my $currfile = File::Spec->catfile( $start, $file ); + if ( -d $currfile ) { + push( @hits, all_in( { %parms, start => $currfile } ) ) if $parms{recurse}; + } + else { + push( @hits, $currfile ) if $currfile =~ /\.t$/; + } + } + } + else { + warn "$start: $!\n"; + } + + return @hits; +} + +=head1 shuffle( @list ) + +Returns a shuffled copy of I<@list>. + +=cut + +sub shuffle { + # Fisher-Yates shuffle + my $i = @_; + while ($i) { + my $j = rand $i--; + @_[$i, $j] = @_[$j, $i]; + } +} + + +=head2 blibdir() + +Finds all the blib directories. Stolen directly from blib.pm + +=cut + +sub blibdirs { + my $dir = File::Spec->curdir; + if ($^O eq 'VMS') { + ($dir = VMS::Filespec::unixify($dir)) =~ s-/\z--; + } + my $archdir = "arch"; + if ( $^O eq "MacOS" ) { + # Double up the MP::A so that it's not used only once. + $archdir = $MacPerl::Architecture = $MacPerl::Architecture; + } + + my $i = 5; + while ($i--) { + my $blib = File::Spec->catdir( $dir, "blib" ); + my $blib_lib = File::Spec->catdir( $blib, "lib" ); + my $blib_arch = File::Spec->catdir( $blib, $archdir ); + + if ( -d $blib && -d $blib_arch && -d $blib_lib ) { + return ($blib_arch,$blib_lib); + } + $dir = File::Spec->catdir($dir, File::Spec->updir); + } + warn "$0: Cannot find blib\n"; + return; +} + +1; diff --git a/SecurityTests/regressions/inc/Test/More.pm b/SecurityTests/regressions/inc/Test/More.pm new file mode 100644 index 00000000..5842e052 --- /dev/null +++ b/SecurityTests/regressions/inc/Test/More.pm @@ -0,0 +1,1569 @@ +package Test::More; + +use 5.006; +use strict; + + +# Can't use Carp because it might cause use_ok() to accidentally succeed +# even though the module being used forgot to use Carp. Yes, this +# actually happened. +sub _carp { + my($file, $line) = (caller(1))[1,2]; + warn @_, " at $file line $line\n"; +} + + + +use vars qw($VERSION @ISA @EXPORT %EXPORT_TAGS $TODO); +$VERSION = '0.80'; +$VERSION = eval $VERSION; # make the alpha version come out as a number + +use Test::Builder::Module; +@ISA = qw(Test::Builder::Module); +@EXPORT = qw(ok use_ok require_ok + is isnt like unlike is_deeply + cmp_ok + skip todo todo_skip + pass fail + eq_array eq_hash eq_set + $TODO + plan + can_ok isa_ok + diag + BAIL_OUT + ); + + +=head1 NAME + +Test::More - yet another framework for writing test scripts + +=head1 SYNOPSIS + + use Test::More tests => 23; + # or + use Test::More qw(no_plan); + # or + use Test::More skip_all => $reason; + + BEGIN { use_ok( 'Some::Module' ); } + require_ok( 'Some::Module' ); + + # Various ways to say "ok" + ok($got eq $expected, $test_name); + + is ($got, $expected, $test_name); + isnt($got, $expected, $test_name); + + # Rather than print STDERR "# here's what went wrong\n" + diag("here's what went wrong"); + + like ($got, qr/expected/, $test_name); + unlike($got, qr/expected/, $test_name); + + cmp_ok($got, '==', $expected, $test_name); + + is_deeply($got_complex_structure, $expected_complex_structure, $test_name); + + SKIP: { + skip $why, $how_many unless $have_some_feature; + + ok( foo(), $test_name ); + is( foo(42), 23, $test_name ); + }; + + TODO: { + local $TODO = $why; + + ok( foo(), $test_name ); + is( foo(42), 23, $test_name ); + }; + + can_ok($module, @methods); + isa_ok($object, $class); + + pass($test_name); + fail($test_name); + + BAIL_OUT($why); + + # UNIMPLEMENTED!!! + my @status = Test::More::status; + + +=head1 DESCRIPTION + +B If you're just getting started writing tests, have a look at +Test::Simple first. This is a drop in replacement for Test::Simple +which you can switch to once you get the hang of basic testing. + +The purpose of this module is to provide a wide range of testing +utilities. Various ways to say "ok" with better diagnostics, +facilities to skip tests, test future features and compare complicated +data structures. While you can do almost anything with a simple +C function, it doesn't provide good diagnostic output. + + +=head2 I love it when a plan comes together + +Before anything else, you need a testing plan. This basically declares +how many tests your script is going to run to protect against premature +failure. + +The preferred way to do this is to declare a plan when you C. + + use Test::More tests => 23; + +There are rare cases when you will not know beforehand how many tests +your script is going to run. In this case, you can declare that you +have no plan. (Try to avoid using this as it weakens your test.) + + use Test::More qw(no_plan); + +B: using no_plan requires a Test::Harness upgrade else it will +think everything has failed. See L). + +In some cases, you'll want to completely skip an entire testing script. + + use Test::More skip_all => $skip_reason; + +Your script will declare a skip with the reason why you skipped and +exit immediately with a zero (success). See L for +details. + +If you want to control what functions Test::More will export, you +have to use the 'import' option. For example, to import everything +but 'fail', you'd do: + + use Test::More tests => 23, import => ['!fail']; + +Alternatively, you can use the plan() function. Useful for when you +have to calculate the number of tests. + + use Test::More; + plan tests => keys %Stuff * 3; + +or for deciding between running the tests at all: + + use Test::More; + if( $^O eq 'MacOS' ) { + plan skip_all => 'Test irrelevant on MacOS'; + } + else { + plan tests => 42; + } + +=cut + +sub plan { + my $tb = Test::More->builder; + + $tb->plan(@_); +} + + +# This implements "use Test::More 'no_diag'" but the behavior is +# deprecated. +sub import_extra { + my $class = shift; + my $list = shift; + + my @other = (); + my $idx = 0; + while( $idx <= $#{$list} ) { + my $item = $list->[$idx]; + + if( defined $item and $item eq 'no_diag' ) { + $class->builder->no_diag(1); + } + else { + push @other, $item; + } + + $idx++; + } + + @$list = @other; +} + + +=head2 Test names + +By convention, each test is assigned a number in order. This is +largely done automatically for you. However, it's often very useful to +assign a name to each test. Which would you rather see: + + ok 4 + not ok 5 + ok 6 + +or + + ok 4 - basic multi-variable + not ok 5 - simple exponential + ok 6 - force == mass * acceleration + +The later gives you some idea of what failed. It also makes it easier +to find the test in your script, simply search for "simple +exponential". + +All test functions take a name argument. It's optional, but highly +suggested that you use it. + + +=head2 I'm ok, you're not ok. + +The basic purpose of this module is to print out either "ok #" or "not +ok #" depending on if a given test succeeded or failed. Everything +else is just gravy. + +All of the following print "ok" or "not ok" depending on if the test +succeeded or failed. They all also return true or false, +respectively. + +=over 4 + +=item B + + ok($got eq $expected, $test_name); + +This simply evaluates any expression (C<$got eq $expected> is just a +simple example) and uses that to determine if the test succeeded or +failed. A true expression passes, a false one fails. Very simple. + +For example: + + ok( $exp{9} == 81, 'simple exponential' ); + ok( Film->can('db_Main'), 'set_db()' ); + ok( $p->tests == 4, 'saw tests' ); + ok( !grep !defined $_, @items, 'items populated' ); + +(Mnemonic: "This is ok.") + +$test_name is a very short description of the test that will be printed +out. It makes it very easy to find a test in your script when it fails +and gives others an idea of your intentions. $test_name is optional, +but we B strongly encourage its use. + +Should an ok() fail, it will produce some diagnostics: + + not ok 18 - sufficient mucus + # Failed test 'sufficient mucus' + # in foo.t at line 42. + +This is the same as Test::Simple's ok() routine. + +=cut + +sub ok ($;$) { + my($test, $name) = @_; + my $tb = Test::More->builder; + + $tb->ok($test, $name); +} + +=item B + +=item B + + is ( $got, $expected, $test_name ); + isnt( $got, $expected, $test_name ); + +Similar to ok(), is() and isnt() compare their two arguments +with C and C respectively and use the result of that to +determine if the test succeeded or failed. So these: + + # Is the ultimate answer 42? + is( ultimate_answer(), 42, "Meaning of Life" ); + + # $foo isn't empty + isnt( $foo, '', "Got some foo" ); + +are similar to these: + + ok( ultimate_answer() eq 42, "Meaning of Life" ); + ok( $foo ne '', "Got some foo" ); + +(Mnemonic: "This is that." "This isn't that.") + +So why use these? They produce better diagnostics on failure. ok() +cannot know what you are testing for (beyond the name), but is() and +isnt() know what the test was and why it failed. For example this +test: + + my $foo = 'waffle'; my $bar = 'yarblokos'; + is( $foo, $bar, 'Is foo the same as bar?' ); + +Will produce something like this: + + not ok 17 - Is foo the same as bar? + # Failed test 'Is foo the same as bar?' + # in foo.t at line 139. + # got: 'waffle' + # expected: 'yarblokos' + +So you can figure out what went wrong without rerunning the test. + +You are encouraged to use is() and isnt() over ok() where possible, +however do not be tempted to use them to find out if something is +true or false! + + # XXX BAD! + is( exists $brooklyn{tree}, 1, 'A tree grows in Brooklyn' ); + +This does not check if C is true, it checks if +it returns 1. Very different. Similar caveats exist for false and 0. +In these cases, use ok(). + + ok( exists $brooklyn{tree}, 'A tree grows in Brooklyn' ); + +For those grammatical pedants out there, there's an C +function which is an alias of isnt(). + +=cut + +sub is ($$;$) { + my $tb = Test::More->builder; + + $tb->is_eq(@_); +} + +sub isnt ($$;$) { + my $tb = Test::More->builder; + + $tb->isnt_eq(@_); +} + +*isn't = \&isnt; + + +=item B + + like( $got, qr/expected/, $test_name ); + +Similar to ok(), like() matches $got against the regex C. + +So this: + + like($got, qr/expected/, 'this is like that'); + +is similar to: + + ok( $got =~ /expected/, 'this is like that'); + +(Mnemonic "This is like that".) + +The second argument is a regular expression. It may be given as a +regex reference (i.e. C) or (for better compatibility with older +perls) as a string that looks like a regex (alternative delimiters are +currently not supported): + + like( $got, '/expected/', 'this is like that' ); + +Regex options may be placed on the end (C<'/expected/i'>). + +Its advantages over ok() are similar to that of is() and isnt(). Better +diagnostics on failure. + +=cut + +sub like ($$;$) { + my $tb = Test::More->builder; + + $tb->like(@_); +} + + +=item B + + unlike( $got, qr/expected/, $test_name ); + +Works exactly as like(), only it checks if $got B match the +given pattern. + +=cut + +sub unlike ($$;$) { + my $tb = Test::More->builder; + + $tb->unlike(@_); +} + + +=item B + + cmp_ok( $got, $op, $expected, $test_name ); + +Halfway between ok() and is() lies cmp_ok(). This allows you to +compare two arguments using any binary perl operator. + + # ok( $got eq $expected ); + cmp_ok( $got, 'eq', $expected, 'this eq that' ); + + # ok( $got == $expected ); + cmp_ok( $got, '==', $expected, 'this == that' ); + + # ok( $got && $expected ); + cmp_ok( $got, '&&', $expected, 'this && that' ); + ...etc... + +Its advantage over ok() is when the test fails you'll know what $got +and $expected were: + + not ok 1 + # Failed test in foo.t at line 12. + # '23' + # && + # undef + +It's also useful in those cases where you are comparing numbers and +is()'s use of C will interfere: + + cmp_ok( $big_hairy_number, '==', $another_big_hairy_number ); + +=cut + +sub cmp_ok($$$;$) { + my $tb = Test::More->builder; + + $tb->cmp_ok(@_); +} + + +=item B + + can_ok($module, @methods); + can_ok($object, @methods); + +Checks to make sure the $module or $object can do these @methods +(works with functions, too). + + can_ok('Foo', qw(this that whatever)); + +is almost exactly like saying: + + ok( Foo->can('this') && + Foo->can('that') && + Foo->can('whatever') + ); + +only without all the typing and with a better interface. Handy for +quickly testing an interface. + +No matter how many @methods you check, a single can_ok() call counts +as one test. If you desire otherwise, use: + + foreach my $meth (@methods) { + can_ok('Foo', $meth); + } + +=cut + +sub can_ok ($@) { + my($proto, @methods) = @_; + my $class = ref $proto || $proto; + my $tb = Test::More->builder; + + unless( $class ) { + my $ok = $tb->ok( 0, "->can(...)" ); + $tb->diag(' can_ok() called with empty class or reference'); + return $ok; + } + + unless( @methods ) { + my $ok = $tb->ok( 0, "$class->can(...)" ); + $tb->diag(' can_ok() called with no methods'); + return $ok; + } + + my @nok = (); + foreach my $method (@methods) { + $tb->_try(sub { $proto->can($method) }) or push @nok, $method; + } + + my $name; + $name = @methods == 1 ? "$class->can('$methods[0]')" + : "$class->can(...)"; + + my $ok = $tb->ok( !@nok, $name ); + + $tb->diag(map " $class->can('$_') failed\n", @nok); + + return $ok; +} + +=item B + + isa_ok($object, $class, $object_name); + isa_ok($ref, $type, $ref_name); + +Checks to see if the given C<< $object->isa($class) >>. Also checks to make +sure the object was defined in the first place. Handy for this sort +of thing: + + my $obj = Some::Module->new; + isa_ok( $obj, 'Some::Module' ); + +where you'd otherwise have to write + + my $obj = Some::Module->new; + ok( defined $obj && $obj->isa('Some::Module') ); + +to safeguard against your test script blowing up. + +It works on references, too: + + isa_ok( $array_ref, 'ARRAY' ); + +The diagnostics of this test normally just refer to 'the object'. If +you'd like them to be more specific, you can supply an $object_name +(for example 'Test customer'). + +=cut + +sub isa_ok ($$;$) { + my($object, $class, $obj_name) = @_; + my $tb = Test::More->builder; + + my $diag; + $obj_name = 'The object' unless defined $obj_name; + my $name = "$obj_name isa $class"; + if( !defined $object ) { + $diag = "$obj_name isn't defined"; + } + elsif( !ref $object ) { + $diag = "$obj_name isn't a reference"; + } + else { + # We can't use UNIVERSAL::isa because we want to honor isa() overrides + my($rslt, $error) = $tb->_try(sub { $object->isa($class) }); + if( $error ) { + if( $error =~ /^Can't call method "isa" on unblessed reference/ ) { + # Its an unblessed reference + if( !UNIVERSAL::isa($object, $class) ) { + my $ref = ref $object; + $diag = "$obj_name isn't a '$class' it's a '$ref'"; + } + } else { + die <isa on your object and got some weird error. +Here's the error. +$error +WHOA + } + } + elsif( !$rslt ) { + my $ref = ref $object; + $diag = "$obj_name isn't a '$class' it's a '$ref'"; + } + } + + + + my $ok; + if( $diag ) { + $ok = $tb->ok( 0, $name ); + $tb->diag(" $diag\n"); + } + else { + $ok = $tb->ok( 1, $name ); + } + + return $ok; +} + + +=item B + +=item B + + pass($test_name); + fail($test_name); + +Sometimes you just want to say that the tests have passed. Usually +the case is you've got some complicated condition that is difficult to +wedge into an ok(). In this case, you can simply use pass() (to +declare the test ok) or fail (for not ok). They are synonyms for +ok(1) and ok(0). + +Use these very, very, very sparingly. + +=cut + +sub pass (;$) { + my $tb = Test::More->builder; + $tb->ok(1, @_); +} + +sub fail (;$) { + my $tb = Test::More->builder; + $tb->ok(0, @_); +} + +=back + + +=head2 Module tests + +You usually want to test if the module you're testing loads ok, rather +than just vomiting if its load fails. For such purposes we have +C and C. + +=over 4 + +=item B + + BEGIN { use_ok($module); } + BEGIN { use_ok($module, @imports); } + +These simply use the given $module and test to make sure the load +happened ok. It's recommended that you run use_ok() inside a BEGIN +block so its functions are exported at compile-time and prototypes are +properly honored. + +If @imports are given, they are passed through to the use. So this: + + BEGIN { use_ok('Some::Module', qw(foo bar)) } + +is like doing this: + + use Some::Module qw(foo bar); + +Version numbers can be checked like so: + + # Just like "use Some::Module 1.02" + BEGIN { use_ok('Some::Module', 1.02) } + +Don't try to do this: + + BEGIN { + use_ok('Some::Module'); + + ...some code that depends on the use... + ...happening at compile time... + } + +because the notion of "compile-time" is relative. Instead, you want: + + BEGIN { use_ok('Some::Module') } + BEGIN { ...some code that depends on the use... } + + +=cut + +sub use_ok ($;@) { + my($module, @imports) = @_; + @imports = () unless @imports; + my $tb = Test::More->builder; + + my($pack,$filename,$line) = caller; + + my $code; + if( @imports == 1 and $imports[0] =~ /^\d+(?:\.\d+)?$/ ) { + # probably a version check. Perl needs to see the bare number + # for it to work with non-Exporter based modules. + $code = <ok( $eval_result, "use $module;" ); + + unless( $ok ) { + chomp $eval_error; + $@ =~ s{^BEGIN failed--compilation aborted at .*$} + {BEGIN failed--compilation aborted at $filename line $line.}m; + $tb->diag(< + + require_ok($module); + require_ok($file); + +Like use_ok(), except it requires the $module or $file. + +=cut + +sub require_ok ($) { + my($module) = shift; + my $tb = Test::More->builder; + + my $pack = caller; + + # Try to deterine if we've been given a module name or file. + # Module names must be barewords, files not. + $module = qq['$module'] unless _is_module_name($module); + + my $code = <ok( $eval_result, "require $module;" ); + + unless( $ok ) { + chomp $eval_error; + $tb->diag(< I'm not quite sure what will happen with filehandles. + +=over 4 + +=item B + + is_deeply( $got, $expected, $test_name ); + +Similar to is(), except that if $got and $expected are references, it +does a deep comparison walking each data structure to see if they are +equivalent. If the two structures are different, it will display the +place where they start differing. + +is_deeply() compares the dereferenced values of references, the +references themselves (except for their type) are ignored. This means +aspects such as blessing and ties are not considered "different". + +is_deeply() current has very limited handling of function reference +and globs. It merely checks if they have the same referent. This may +improve in the future. + +Test::Differences and Test::Deep provide more in-depth functionality +along these lines. + +=cut + +use vars qw(@Data_Stack %Refs_Seen); +my $DNE = bless [], 'Does::Not::Exist'; + +sub _dne { + ref $_[0] eq ref $DNE; +} + + +sub is_deeply { + my $tb = Test::More->builder; + + unless( @_ == 2 or @_ == 3 ) { + my $msg = <ok(0); + } + + my($got, $expected, $name) = @_; + + $tb->_unoverload_str(\$expected, \$got); + + my $ok; + if( !ref $got and !ref $expected ) { # neither is a reference + $ok = $tb->is_eq($got, $expected, $name); + } + elsif( !ref $got xor !ref $expected ) { # one's a reference, one isn't + $ok = $tb->ok(0, $name); + $tb->diag( _format_stack({ vals => [ $got, $expected ] }) ); + } + else { # both references + local @Data_Stack = (); + if( _deep_check($got, $expected) ) { + $ok = $tb->ok(1, $name); + } + else { + $ok = $tb->ok(0, $name); + $tb->diag(_format_stack(@Data_Stack)); + } + } + + return $ok; +} + +sub _format_stack { + my(@Stack) = @_; + + my $var = '$FOO'; + my $did_arrow = 0; + foreach my $entry (@Stack) { + my $type = $entry->{type} || ''; + my $idx = $entry->{'idx'}; + if( $type eq 'HASH' ) { + $var .= "->" unless $did_arrow++; + $var .= "{$idx}"; + } + elsif( $type eq 'ARRAY' ) { + $var .= "->" unless $did_arrow++; + $var .= "[$idx]"; + } + elsif( $type eq 'REF' ) { + $var = "\${$var}"; + } + } + + my @vals = @{$Stack[-1]{vals}}[0,1]; + my @vars = (); + ($vars[0] = $var) =~ s/\$FOO/ \$got/; + ($vars[1] = $var) =~ s/\$FOO/\$expected/; + + my $out = "Structures begin differing at:\n"; + foreach my $idx (0..$#vals) { + my $val = $vals[$idx]; + $vals[$idx] = !defined $val ? 'undef' : + _dne($val) ? "Does not exist" : + ref $val ? "$val" : + "'$val'"; + } + + $out .= "$vars[0] = $vals[0]\n"; + $out .= "$vars[1] = $vals[1]\n"; + + $out =~ s/^/ /msg; + return $out; +} + + +sub _type { + my $thing = shift; + + return '' if !ref $thing; + + for my $type (qw(ARRAY HASH REF SCALAR GLOB CODE Regexp)) { + return $type if UNIVERSAL::isa($thing, $type); + } + + return ''; +} + +=back + + +=head2 Diagnostics + +If you pick the right test function, you'll usually get a good idea of +what went wrong when it failed. But sometimes it doesn't work out +that way. So here we have ways for you to write your own diagnostic +messages which are safer than just C. + +=over 4 + +=item B + + diag(@diagnostic_message); + +Prints a diagnostic message which is guaranteed not to interfere with +test output. Like C @diagnostic_message is simply concatenated +together. + +Handy for this sort of thing: + + ok( grep(/foo/, @users), "There's a foo user" ) or + diag("Since there's no foo, check that /etc/bar is set up right"); + +which would produce: + + not ok 42 - There's a foo user + # Failed test 'There's a foo user' + # in foo.t at line 52. + # Since there's no foo, check that /etc/bar is set up right. + +You might remember C with the mnemonic C. + +B The exact formatting of the diagnostic output is still +changing, but it is guaranteed that whatever you throw at it it won't +interfere with the test. + +=cut + +sub diag { + my $tb = Test::More->builder; + + $tb->diag(@_); +} + + +=back + + +=head2 Conditional tests + +Sometimes running a test under certain conditions will cause the +test script to die. A certain function or method isn't implemented +(such as fork() on MacOS), some resource isn't available (like a +net connection) or a module isn't available. In these cases it's +necessary to skip tests, or declare that they are supposed to fail +but will work in the future (a todo test). + +For more details on the mechanics of skip and todo tests see +L. + +The way Test::More handles this is with a named block. Basically, a +block of tests which can be skipped over or made todo. It's best if I +just show you... + +=over 4 + +=item B + + SKIP: { + skip $why, $how_many if $condition; + + ...normal testing code goes here... + } + +This declares a block of tests that might be skipped, $how_many tests +there are, $why and under what $condition to skip them. An example is +the easiest way to illustrate: + + SKIP: { + eval { require HTML::Lint }; + + skip "HTML::Lint not installed", 2 if $@; + + my $lint = new HTML::Lint; + isa_ok( $lint, "HTML::Lint" ); + + $lint->parse( $html ); + is( $lint->errors, 0, "No errors found in HTML" ); + } + +If the user does not have HTML::Lint installed, the whole block of +code I. Test::More will output special ok's +which Test::Harness interprets as skipped, but passing, tests. + +It's important that $how_many accurately reflects the number of tests +in the SKIP block so the # of tests run will match up with your plan. +If your plan is C $how_many is optional and will default to 1. + +It's perfectly safe to nest SKIP blocks. Each SKIP block must have +the label C, or Test::More can't work its magic. + +You don't skip tests which are failing because there's a bug in your +program, or for which you don't yet have code written. For that you +use TODO. Read on. + +=cut + +#'# +sub skip { + my($why, $how_many) = @_; + my $tb = Test::More->builder; + + unless( defined $how_many ) { + # $how_many can only be avoided when no_plan is in use. + _carp "skip() needs to know \$how_many tests are in the block" + unless $tb->has_plan eq 'no_plan'; + $how_many = 1; + } + + if( defined $how_many and $how_many =~ /\D/ ) { + _carp "skip() was passed a non-numeric number of tests. Did you get the arguments backwards?"; + $how_many = 1; + } + + for( 1..$how_many ) { + $tb->skip($why); + } + + local $^W = 0; + last SKIP; +} + + +=item B + + TODO: { + local $TODO = $why if $condition; + + ...normal testing code goes here... + } + +Declares a block of tests you expect to fail and $why. Perhaps it's +because you haven't fixed a bug or haven't finished a new feature: + + TODO: { + local $TODO = "URI::Geller not finished"; + + my $card = "Eight of clubs"; + is( URI::Geller->your_card, $card, 'Is THIS your card?' ); + + my $spoon; + URI::Geller->bend_spoon; + is( $spoon, 'bent', "Spoon bending, that's original" ); + } + +With a todo block, the tests inside are expected to fail. Test::More +will run the tests normally, but print out special flags indicating +they are "todo". Test::Harness will interpret failures as being ok. +Should anything succeed, it will report it as an unexpected success. +You then know the thing you had todo is done and can remove the +TODO flag. + +The nice part about todo tests, as opposed to simply commenting out a +block of tests, is it's like having a programmatic todo list. You know +how much work is left to be done, you're aware of what bugs there are, +and you'll know immediately when they're fixed. + +Once a todo test starts succeeding, simply move it outside the block. +When the block is empty, delete it. + +B: TODO tests require a Test::Harness upgrade else it will +treat it as a normal failure. See L). + + +=item B + + TODO: { + todo_skip $why, $how_many if $condition; + + ...normal testing code... + } + +With todo tests, it's best to have the tests actually run. That way +you'll know when they start passing. Sometimes this isn't possible. +Often a failing test will cause the whole program to die or hang, even +inside an C with and using C. In these extreme +cases you have no choice but to skip over the broken tests entirely. + +The syntax and behavior is similar to a C except the +tests will be marked as failing but todo. Test::Harness will +interpret them as passing. + +=cut + +sub todo_skip { + my($why, $how_many) = @_; + my $tb = Test::More->builder; + + unless( defined $how_many ) { + # $how_many can only be avoided when no_plan is in use. + _carp "todo_skip() needs to know \$how_many tests are in the block" + unless $tb->has_plan eq 'no_plan'; + $how_many = 1; + } + + for( 1..$how_many ) { + $tb->todo_skip($why); + } + + local $^W = 0; + last TODO; +} + +=item When do I use SKIP vs. TODO? + +B, use SKIP. +This includes optional modules that aren't installed, running under +an OS that doesn't have some feature (like fork() or symlinks), or maybe +you need an Internet connection and one isn't available. + +B, use TODO. This +is for any code you haven't written yet, or bugs you have yet to fix, +but want to put tests in your testing script (always a good idea). + + +=back + + +=head2 Test control + +=over 4 + +=item B + + BAIL_OUT($reason); + +Indicates to the harness that things are going so badly all testing +should terminate. This includes the running any additional test scripts. + +This is typically used when testing cannot continue such as a critical +module failing to compile or a necessary external utility not being +available such as a database connection failing. + +The test will exit with 255. + +=cut + +sub BAIL_OUT { + my $reason = shift; + my $tb = Test::More->builder; + + $tb->BAIL_OUT($reason); +} + +=back + + +=head2 Discouraged comparison functions + +The use of the following functions is discouraged as they are not +actually testing functions and produce no diagnostics to help figure +out what went wrong. They were written before is_deeply() existed +because I couldn't figure out how to display a useful diff of two +arbitrary data structures. + +These functions are usually used inside an ok(). + + ok( eq_array(\@got, \@expected) ); + +C can do that better and with diagnostics. + + is_deeply( \@got, \@expected ); + +They may be deprecated in future versions. + +=over 4 + +=item B + + my $is_eq = eq_array(\@got, \@expected); + +Checks if two arrays are equivalent. This is a deep check, so +multi-level structures are handled correctly. + +=cut + +#'# +sub eq_array { + local @Data_Stack; + _deep_check(@_); +} + +sub _eq_array { + my($a1, $a2) = @_; + + if( grep !_type($_) eq 'ARRAY', $a1, $a2 ) { + warn "eq_array passed a non-array ref"; + return 0; + } + + return 1 if $a1 eq $a2; + + my $ok = 1; + my $max = $#$a1 > $#$a2 ? $#$a1 : $#$a2; + for (0..$max) { + my $e1 = $_ > $#$a1 ? $DNE : $a1->[$_]; + my $e2 = $_ > $#$a2 ? $DNE : $a2->[$_]; + + push @Data_Stack, { type => 'ARRAY', idx => $_, vals => [$e1, $e2] }; + $ok = _deep_check($e1,$e2); + pop @Data_Stack if $ok; + + last unless $ok; + } + + return $ok; +} + +sub _deep_check { + my($e1, $e2) = @_; + my $tb = Test::More->builder; + + my $ok = 0; + + # Effectively turn %Refs_Seen into a stack. This avoids picking up + # the same referenced used twice (such as [\$a, \$a]) to be considered + # circular. + local %Refs_Seen = %Refs_Seen; + + { + # Quiet uninitialized value warnings when comparing undefs. + local $^W = 0; + + $tb->_unoverload_str(\$e1, \$e2); + + # Either they're both references or both not. + my $same_ref = !(!ref $e1 xor !ref $e2); + my $not_ref = (!ref $e1 and !ref $e2); + + if( defined $e1 xor defined $e2 ) { + $ok = 0; + } + elsif ( _dne($e1) xor _dne($e2) ) { + $ok = 0; + } + elsif ( $same_ref and ($e1 eq $e2) ) { + $ok = 1; + } + elsif ( $not_ref ) { + push @Data_Stack, { type => '', vals => [$e1, $e2] }; + $ok = 0; + } + else { + if( $Refs_Seen{$e1} ) { + return $Refs_Seen{$e1} eq $e2; + } + else { + $Refs_Seen{$e1} = "$e2"; + } + + my $type = _type($e1); + $type = 'DIFFERENT' unless _type($e2) eq $type; + + if( $type eq 'DIFFERENT' ) { + push @Data_Stack, { type => $type, vals => [$e1, $e2] }; + $ok = 0; + } + elsif( $type eq 'ARRAY' ) { + $ok = _eq_array($e1, $e2); + } + elsif( $type eq 'HASH' ) { + $ok = _eq_hash($e1, $e2); + } + elsif( $type eq 'REF' ) { + push @Data_Stack, { type => $type, vals => [$e1, $e2] }; + $ok = _deep_check($$e1, $$e2); + pop @Data_Stack if $ok; + } + elsif( $type eq 'SCALAR' ) { + push @Data_Stack, { type => 'REF', vals => [$e1, $e2] }; + $ok = _deep_check($$e1, $$e2); + pop @Data_Stack if $ok; + } + elsif( $type ) { + push @Data_Stack, { type => $type, vals => [$e1, $e2] }; + $ok = 0; + } + else { + _whoa(1, "No type in _deep_check"); + } + } + } + + return $ok; +} + + +sub _whoa { + my($check, $desc) = @_; + if( $check ) { + die < + + my $is_eq = eq_hash(\%got, \%expected); + +Determines if the two hashes contain the same keys and values. This +is a deep check. + +=cut + +sub eq_hash { + local @Data_Stack; + return _deep_check(@_); +} + +sub _eq_hash { + my($a1, $a2) = @_; + + if( grep !_type($_) eq 'HASH', $a1, $a2 ) { + warn "eq_hash passed a non-hash ref"; + return 0; + } + + return 1 if $a1 eq $a2; + + my $ok = 1; + my $bigger = keys %$a1 > keys %$a2 ? $a1 : $a2; + foreach my $k (keys %$bigger) { + my $e1 = exists $a1->{$k} ? $a1->{$k} : $DNE; + my $e2 = exists $a2->{$k} ? $a2->{$k} : $DNE; + + push @Data_Stack, { type => 'HASH', idx => $k, vals => [$e1, $e2] }; + $ok = _deep_check($e1, $e2); + pop @Data_Stack if $ok; + + last unless $ok; + } + + return $ok; +} + +=item B + + my $is_eq = eq_set(\@got, \@expected); + +Similar to eq_array(), except the order of the elements is B +important. This is a deep check, but the irrelevancy of order only +applies to the top level. + + ok( eq_set(\@got, \@expected) ); + +Is better written: + + is_deeply( [sort @got], [sort @expected] ); + +B By historical accident, this is not a true set comparison. +While the order of elements does not matter, duplicate elements do. + +B eq_set() does not know how to deal with references at the top +level. The following is an example of a comparison which might not work: + + eq_set([\1, \2], [\2, \1]); + +Test::Deep contains much better set comparison functions. + +=cut + +sub eq_set { + my($a1, $a2) = @_; + return 0 unless @$a1 == @$a2; + + # There's faster ways to do this, but this is easiest. + local $^W = 0; + + # It really doesn't matter how we sort them, as long as both arrays are + # sorted with the same algorithm. + # + # Ensure that references are not accidentally treated the same as a + # string containing the reference. + # + # Have to inline the sort routine due to a threading/sort bug. + # See [rt.cpan.org 6782] + # + # I don't know how references would be sorted so we just don't sort + # them. This means eq_set doesn't really work with refs. + return eq_array( + [grep(ref, @$a1), sort( grep(!ref, @$a1) )], + [grep(ref, @$a2), sort( grep(!ref, @$a2) )], + ); +} + +=back + + +=head2 Extending and Embedding Test::More + +Sometimes the Test::More interface isn't quite enough. Fortunately, +Test::More is built on top of Test::Builder which provides a single, +unified backend for any test library to use. This means two test +libraries which both use Test::Builder B. + +If you simply want to do a little tweaking of how the tests behave, +you can access the underlying Test::Builder object like so: + +=over 4 + +=item B + + my $test_builder = Test::More->builder; + +Returns the Test::Builder object underlying Test::More for you to play +with. + + +=back + + +=head1 EXIT CODES + +If all your tests passed, Test::Builder will exit with zero (which is +normal). If anything failed it will exit with how many failed. If +you run less (or more) tests than you planned, the missing (or extras) +will be considered failures. If no tests were ever run Test::Builder +will throw a warning and exit with 255. If the test died, even after +having successfully completed all its tests, it will still be +considered a failure and will exit with 255. + +So the exit codes are... + + 0 all tests successful + 255 test died or all passed but wrong # of tests run + any other number how many failed (including missing or extras) + +If you fail more than 254 tests, it will be reported as 254. + +B This behavior may go away in future versions. + + +=head1 CAVEATS and NOTES + +=over 4 + +=item Backwards compatibility + +Test::More works with Perls as old as 5.6.0. + + +=item Overloaded objects + +String overloaded objects are compared B (or in cmp_ok()'s +case, strings or numbers as appropriate to the comparison op). This +prevents Test::More from piercing an object's interface allowing +better blackbox testing. So if a function starts returning overloaded +objects instead of bare strings your tests won't notice the +difference. This is good. + +However, it does mean that functions like is_deeply() cannot be used to +test the internals of string overloaded objects. In this case I would +suggest Test::Deep which contains more flexible testing functions for +complex data structures. + + +=item Threads + +Test::More will only be aware of threads if "use threads" has been done +I Test::More is loaded. This is ok: + + use threads; + use Test::More; + +This may cause problems: + + use Test::More + use threads; + +5.8.1 and above are supported. Anything below that has too many bugs. + + +=item Test::Harness upgrade + +no_plan and todo depend on new Test::Harness features and fixes. If +you're going to distribute tests that use no_plan or todo your +end-users will have to upgrade Test::Harness to the latest one on +CPAN. If you avoid no_plan and TODO tests, the stock Test::Harness +will work fine. + +Installing Test::More should also upgrade Test::Harness. + +=back + + +=head1 HISTORY + +This is a case of convergent evolution with Joshua Pritikin's Test +module. I was largely unaware of its existence when I'd first +written my own ok() routines. This module exists because I can't +figure out how to easily wedge test names into Test's interface (along +with a few other problems). + +The goal here is to have a testing utility that's simple to learn, +quick to use and difficult to trip yourself up with while still +providing more flexibility than the existing Test.pm. As such, the +names of the most common routines are kept tiny, special cases and +magic side-effects are kept to a minimum. WYSIWYG. + + +=head1 SEE ALSO + +L if all this confuses you and you just want to write +some tests. You can upgrade to Test::More later (it's forward +compatible). + +L is the old testing module. Its main benefit is that it has +been distributed with Perl since 5.004_05. + +L for details on how your test results are interpreted +by Perl. + +L for more ways to test complex data structures. +And it plays well with Test::More. + +L is like XUnit but more perlish. + +L gives you more powerful complex data structure testing. + +L is XUnit style testing. + +L shows the idea of embedded testing. + +L installs a whole bunch of useful test modules. + + +=head1 AUTHORS + +Michael G Schwern Eschwern@pobox.comE with much inspiration +from Joshua Pritikin's Test module and lots of help from Barrie +Slaymaker, Tony Bowden, blackstar.co.uk, chromatic, Fergal Daly and +the perl-qa gang. + + +=head1 BUGS + +See F to report and view bugs. + + +=head1 COPYRIGHT + +Copyright 2001-2002, 2004-2006 by Michael G Schwern Eschwern@pobox.comE. + +This program is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + +See F + +=cut + +1; diff --git a/SecurityTests/regressions/inc/Test/Simple.pm b/SecurityTests/regressions/inc/Test/Simple.pm new file mode 100644 index 00000000..e4799ca5 --- /dev/null +++ b/SecurityTests/regressions/inc/Test/Simple.pm @@ -0,0 +1,230 @@ +package Test::Simple; + +use 5.004; + +use strict 'vars'; +use vars qw($VERSION @ISA @EXPORT); +$VERSION = '0.80'; +$VERSION = eval $VERSION; # make the alpha version come out as a number + +use Test::Builder::Module; +@ISA = qw(Test::Builder::Module); +@EXPORT = qw(ok); + +my $CLASS = __PACKAGE__; + + +=head1 NAME + +Test::Simple - Basic utilities for writing tests. + +=head1 SYNOPSIS + + use Test::Simple tests => 1; + + ok( $foo eq $bar, 'foo is bar' ); + + +=head1 DESCRIPTION + +** If you are unfamiliar with testing B first! ** + +This is an extremely simple, extremely basic module for writing tests +suitable for CPAN modules and other pursuits. If you wish to do more +complicated testing, use the Test::More module (a drop-in replacement +for this one). + +The basic unit of Perl testing is the ok. For each thing you want to +test your program will print out an "ok" or "not ok" to indicate pass +or fail. You do this with the ok() function (see below). + +The only other constraint is you must pre-declare how many tests you +plan to run. This is in case something goes horribly wrong during the +test and your test program aborts, or skips a test or whatever. You +do this like so: + + use Test::Simple tests => 23; + +You must have a plan. + + +=over 4 + +=item B + + ok( $foo eq $bar, $name ); + ok( $foo eq $bar ); + +ok() is given an expression (in this case C<$foo eq $bar>). If it's +true, the test passed. If it's false, it didn't. That's about it. + +ok() prints out either "ok" or "not ok" along with a test number (it +keeps track of that for you). + + # This produces "ok 1 - Hell not yet frozen over" (or not ok) + ok( get_temperature($hell) > 0, 'Hell not yet frozen over' ); + +If you provide a $name, that will be printed along with the "ok/not +ok" to make it easier to find your test when if fails (just search for +the name). It also makes it easier for the next guy to understand +what your test is for. It's highly recommended you use test names. + +All tests are run in scalar context. So this: + + ok( @stuff, 'I have some stuff' ); + +will do what you mean (fail if stuff is empty) + +=cut + +sub ok ($;$) { + $CLASS->builder->ok(@_); +} + + +=back + +Test::Simple will start by printing number of tests run in the form +"1..M" (so "1..5" means you're going to run 5 tests). This strange +format lets Test::Harness know how many tests you plan on running in +case something goes horribly wrong. + +If all your tests passed, Test::Simple will exit with zero (which is +normal). If anything failed it will exit with how many failed. If +you run less (or more) tests than you planned, the missing (or extras) +will be considered failures. If no tests were ever run Test::Simple +will throw a warning and exit with 255. If the test died, even after +having successfully completed all its tests, it will still be +considered a failure and will exit with 255. + +So the exit codes are... + + 0 all tests successful + 255 test died or all passed but wrong # of tests run + any other number how many failed (including missing or extras) + +If you fail more than 254 tests, it will be reported as 254. + +This module is by no means trying to be a complete testing system. +It's just to get you started. Once you're off the ground its +recommended you look at L. + + +=head1 EXAMPLE + +Here's an example of a simple .t file for the fictional Film module. + + use Test::Simple tests => 5; + + use Film; # What you're testing. + + my $btaste = Film->new({ Title => 'Bad Taste', + Director => 'Peter Jackson', + Rating => 'R', + NumExplodingSheep => 1 + }); + ok( defined($btaste) && ref $btaste eq 'Film, 'new() works' ); + + ok( $btaste->Title eq 'Bad Taste', 'Title() get' ); + ok( $btaste->Director eq 'Peter Jackson', 'Director() get' ); + ok( $btaste->Rating eq 'R', 'Rating() get' ); + ok( $btaste->NumExplodingSheep == 1, 'NumExplodingSheep() get' ); + +It will produce output like this: + + 1..5 + ok 1 - new() works + ok 2 - Title() get + ok 3 - Director() get + not ok 4 - Rating() get + # Failed test 'Rating() get' + # in t/film.t at line 14. + ok 5 - NumExplodingSheep() get + # Looks like you failed 1 tests of 5 + +Indicating the Film::Rating() method is broken. + + +=head1 CAVEATS + +Test::Simple will only report a maximum of 254 failures in its exit +code. If this is a problem, you probably have a huge test script. +Split it into multiple files. (Otherwise blame the Unix folks for +using an unsigned short integer as the exit status). + +Because VMS's exit codes are much, much different than the rest of the +universe, and perl does horrible mangling to them that gets in my way, +it works like this on VMS. + + 0 SS$_NORMAL all tests successful + 4 SS$_ABORT something went wrong + +Unfortunately, I can't differentiate any further. + + +=head1 NOTES + +Test::Simple is B tested all the way back to perl 5.004. + +Test::Simple is thread-safe in perl 5.8.0 and up. + +=head1 HISTORY + +This module was conceived while talking with Tony Bowden in his +kitchen one night about the problems I was having writing some really +complicated feature into the new Testing module. He observed that the +main problem is not dealing with these edge cases but that people hate +to write tests B. What was needed was a dead simple module +that took all the hard work out of testing and was really, really easy +to learn. Paul Johnson simultaneously had this idea (unfortunately, +he wasn't in Tony's kitchen). This is it. + + +=head1 SEE ALSO + +=over 4 + +=item L + +More testing functions! Once you outgrow Test::Simple, look at +Test::More. Test::Simple is 100% forward compatible with Test::More +(i.e. you can just use Test::More instead of Test::Simple in your +programs and things will still work). + +=item L + +The original Perl testing module. + +=item L + +Elaborate unit testing. + +=item L, L + +Embed tests in your code! + +=item L + +Interprets the output of your test program. + +=back + + +=head1 AUTHORS + +Idea by Tony Bowden and Paul Johnson, code by Michael G Schwern +Eschwern@pobox.comE, wardrobe by Calvin Klein. + + +=head1 COPYRIGHT + +Copyright 2001, 2002, 2004 by Michael G Schwern Eschwern@pobox.comE. + +This program is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + +See F + +=cut + +1; diff --git a/SecurityTests/regressions/inc/Test/Tutorial.pod b/SecurityTests/regressions/inc/Test/Tutorial.pod new file mode 100644 index 00000000..b730918c --- /dev/null +++ b/SecurityTests/regressions/inc/Test/Tutorial.pod @@ -0,0 +1,603 @@ +=head1 NAME + +Test::Tutorial - A tutorial about writing really basic tests + +=head1 DESCRIPTION + + +I + +I<*sob*> + +I + + +Is this you? Is writing tests right up there with writing +documentation and having your fingernails pulled out? Did you open up +a test and read + + ######## We start with some black magic + +and decide that's quite enough for you? + +It's ok. That's all gone now. We've done all the black magic for +you. And here are the tricks... + + +=head2 Nuts and bolts of testing. + +Here's the most basic test program. + + #!/usr/bin/perl -w + + print "1..1\n"; + + print 1 + 1 == 2 ? "ok 1\n" : "not ok 1\n"; + +since 1 + 1 is 2, it prints: + + 1..1 + ok 1 + +What this says is: C<1..1> "I'm going to run one test." [1] C +"The first test passed". And that's about all magic there is to +testing. Your basic unit of testing is the I. For each thing you +test, an C is printed. Simple. B interprets your test +results to determine if you succeeded or failed (more on that later). + +Writing all these print statements rapidly gets tedious. Fortunately, +there's B. It has one function, C. + + #!/usr/bin/perl -w + + use Test::Simple tests => 1; + + ok( 1 + 1 == 2 ); + +and that does the same thing as the code above. C is the backbone +of Perl testing, and we'll be using it instead of roll-your-own from +here on. If C gets a true value, the test passes. False, it +fails. + + #!/usr/bin/perl -w + + use Test::Simple tests => 2; + ok( 1 + 1 == 2 ); + ok( 2 + 2 == 5 ); + +from that comes + + 1..2 + ok 1 + not ok 2 + # Failed test (test.pl at line 5) + # Looks like you failed 1 tests of 2. + +C<1..2> "I'm going to run two tests." This number is used to ensure +your test program ran all the way through and didn't die or skip some +tests. C "The first test passed." C "The second test +failed". Test::Simple helpfully prints out some extra commentary about +your tests. + +It's not scary. Come, hold my hand. We're going to give an example +of testing a module. For our example, we'll be testing a date +library, B. It's on CPAN, so download a copy and follow +along. [2] + + +=head2 Where to start? + +This is the hardest part of testing, where do you start? People often +get overwhelmed at the apparent enormity of the task of testing a +whole module. Best place to start is at the beginning. Date::ICal is +an object-oriented module, and that means you start by making an +object. So we test C. + + #!/usr/bin/perl -w + + use Test::Simple tests => 2; + + use Date::ICal; + + my $ical = Date::ICal->new; # create an object + ok( defined $ical ); # check that we got something + ok( $ical->isa('Date::ICal') ); # and it's the right class + +run that and you should get: + + 1..2 + ok 1 + ok 2 + +congratulations, you've written your first useful test. + + +=head2 Names + +That output isn't terribly descriptive, is it? When you have two +tests you can figure out which one is #2, but what if you have 102? + +Each test can be given a little descriptive name as the second +argument to C. + + use Test::Simple tests => 2; + + ok( defined $ical, 'new() returned something' ); + ok( $ical->isa('Date::ICal'), " and it's the right class" ); + +So now you'd see... + + 1..2 + ok 1 - new() returned something + ok 2 - and it's the right class + + +=head2 Test the manual + +Simplest way to build up a decent testing suite is to just test what +the manual says it does. [3] Let's pull something out of the +L and test that all its bits work. + + #!/usr/bin/perl -w + + use Test::Simple tests => 8; + + use Date::ICal; + + $ical = Date::ICal->new( year => 1964, month => 10, day => 16, + hour => 16, min => 12, sec => 47, + tz => '0530' ); + + ok( defined $ical, 'new() returned something' ); + ok( $ical->isa('Date::ICal'), " and it's the right class" ); + ok( $ical->sec == 47, ' sec()' ); + ok( $ical->min == 12, ' min()' ); + ok( $ical->hour == 16, ' hour()' ); + ok( $ical->day == 17, ' day()' ); + ok( $ical->month == 10, ' month()' ); + ok( $ical->year == 1964, ' year()' ); + +run that and you get: + + 1..8 + ok 1 - new() returned something + ok 2 - and it's the right class + ok 3 - sec() + ok 4 - min() + ok 5 - hour() + not ok 6 - day() + # Failed test (- at line 16) + ok 7 - month() + ok 8 - year() + # Looks like you failed 1 tests of 8. + +Whoops, a failure! [4] Test::Simple helpfully lets us know on what line +the failure occurred, but not much else. We were supposed to get 17, +but we didn't. What did we get?? Dunno. We'll have to re-run the +test in the debugger or throw in some print statements to find out. + +Instead, we'll switch from B to B. B +does everything B does, and more! In fact, Test::More does +things I the way Test::Simple does. You can literally swap +Test::Simple out and put Test::More in its place. That's just what +we're going to do. + +Test::More does more than Test::Simple. The most important difference +at this point is it provides more informative ways to say "ok". +Although you can write almost any test with a generic C, it +can't tell you what went wrong. Instead, we'll use the C +function, which lets us declare that something is supposed to be the +same as something else: + + #!/usr/bin/perl -w + + use Test::More tests => 8; + + use Date::ICal; + + $ical = Date::ICal->new( year => 1964, month => 10, day => 16, + hour => 16, min => 12, sec => 47, + tz => '0530' ); + + ok( defined $ical, 'new() returned something' ); + ok( $ical->isa('Date::ICal'), " and it's the right class" ); + is( $ical->sec, 47, ' sec()' ); + is( $ical->min, 12, ' min()' ); + is( $ical->hour, 16, ' hour()' ); + is( $ical->day, 17, ' day()' ); + is( $ical->month, 10, ' month()' ); + is( $ical->year, 1964, ' year()' ); + +"Is C<$ical-Esec> 47?" "Is C<$ical-Emin> 12?" With C in place, +you get some more information + + 1..8 + ok 1 - new() returned something + ok 2 - and it's the right class + ok 3 - sec() + ok 4 - min() + ok 5 - hour() + not ok 6 - day() + # Failed test (- at line 16) + # got: '16' + # expected: '17' + ok 7 - month() + ok 8 - year() + # Looks like you failed 1 tests of 8. + +letting us know that C<$ical-Eday> returned 16, but we expected 17. A +quick check shows that the code is working fine, we made a mistake +when writing up the tests. Just change it to: + + is( $ical->day, 16, ' day()' ); + +and everything works. + +So any time you're doing a "this equals that" sort of test, use C. +It even works on arrays. The test is always in scalar context, so you +can test how many elements are in a list this way. [5] + + is( @foo, 5, 'foo has 5 elements' ); + + +=head2 Sometimes the tests are wrong + +Which brings us to a very important lesson. Code has bugs. Tests are +code. Ergo, tests have bugs. A failing test could mean a bug in the +code, but don't discount the possibility that the test is wrong. + +On the flip side, don't be tempted to prematurely declare a test +incorrect just because you're having trouble finding the bug. +Invalidating a test isn't something to be taken lightly, and don't use +it as a cop out to avoid work. + + +=head2 Testing lots of values + +We're going to be wanting to test a lot of dates here, trying to trick +the code with lots of different edge cases. Does it work before 1970? +After 2038? Before 1904? Do years after 10,000 give it trouble? +Does it get leap years right? We could keep repeating the code above, +or we could set up a little try/expect loop. + + use Test::More tests => 32; + use Date::ICal; + + my %ICal_Dates = ( + # An ICal string And the year, month, date + # hour, minute and second we expect. + '19971024T120000' => # from the docs. + [ 1997, 10, 24, 12, 0, 0 ], + '20390123T232832' => # after the Unix epoch + [ 2039, 1, 23, 23, 28, 32 ], + '19671225T000000' => # before the Unix epoch + [ 1967, 12, 25, 0, 0, 0 ], + '18990505T232323' => # before the MacOS epoch + [ 1899, 5, 5, 23, 23, 23 ], + ); + + + while( my($ical_str, $expect) = each %ICal_Dates ) { + my $ical = Date::ICal->new( ical => $ical_str ); + + ok( defined $ical, "new(ical => '$ical_str')" ); + ok( $ical->isa('Date::ICal'), " and it's the right class" ); + + is( $ical->year, $expect->[0], ' year()' ); + is( $ical->month, $expect->[1], ' month()' ); + is( $ical->day, $expect->[2], ' day()' ); + is( $ical->hour, $expect->[3], ' hour()' ); + is( $ical->min, $expect->[4], ' min()' ); + is( $ical->sec, $expect->[5], ' sec()' ); + } + +So now we can test bunches of dates by just adding them to +C<%ICal_Dates>. Now that it's less work to test with more dates, you'll +be inclined to just throw more in as you think of them. +Only problem is, every time we add to that we have to keep adjusting +the C ##> line. That can rapidly get +annoying. There's two ways to make this work better. + +First, we can calculate the plan dynamically using the C +function. + + use Test::More; + use Date::ICal; + + my %ICal_Dates = ( + ...same as before... + ); + + # For each key in the hash we're running 8 tests. + plan tests => keys %ICal_Dates * 8; + +Or to be even more flexible, we use C. This means we're just +running some tests, don't know how many. [6] + + use Test::More 'no_plan'; # instead of tests => 32 + +now we can just add tests and not have to do all sorts of math to +figure out how many we're running. + + +=head2 Informative names + +Take a look at this line here + + ok( defined $ical, "new(ical => '$ical_str')" ); + +we've added more detail about what we're testing and the ICal string +itself we're trying out to the name. So you get results like: + + ok 25 - new(ical => '19971024T120000') + ok 26 - and it's the right class + ok 27 - year() + ok 28 - month() + ok 29 - day() + ok 30 - hour() + ok 31 - min() + ok 32 - sec() + +if something in there fails, you'll know which one it was and that +will make tracking down the problem easier. So try to put a bit of +debugging information into the test names. + +Describe what the tests test, to make debugging a failed test easier +for you or for the next person who runs your test. + + +=head2 Skipping tests + +Poking around in the existing Date::ICal tests, I found this in +F [7] + + #!/usr/bin/perl -w + + use Test::More tests => 7; + use Date::ICal; + + # Make sure epoch time is being handled sanely. + my $t1 = Date::ICal->new( epoch => 0 ); + is( $t1->epoch, 0, "Epoch time of 0" ); + + # XXX This will only work on unix systems. + is( $t1->ical, '19700101Z', " epoch to ical" ); + + is( $t1->year, 1970, " year()" ); + is( $t1->month, 1, " month()" ); + is( $t1->day, 1, " day()" ); + + # like the tests above, but starting with ical instead of epoch + my $t2 = Date::ICal->new( ical => '19700101Z' ); + is( $t2->ical, '19700101Z', "Start of epoch in ICal notation" ); + + is( $t2->epoch, 0, " and back to ICal" ); + +The beginning of the epoch is different on most non-Unix operating +systems [8]. Even though Perl smooths out the differences for the most +part, certain ports do it differently. MacPerl is one off the top of +my head. [9] We I this will never work on MacOS. So rather than +just putting a comment in the test, we can explicitly say it's never +going to work and skip the test. + + use Test::More tests => 7; + use Date::ICal; + + # Make sure epoch time is being handled sanely. + my $t1 = Date::ICal->new( epoch => 0 ); + is( $t1->epoch, 0, "Epoch time of 0" ); + + SKIP: { + skip('epoch to ICal not working on MacOS', 6) + if $^O eq 'MacOS'; + + is( $t1->ical, '19700101Z', " epoch to ical" ); + + is( $t1->year, 1970, " year()" ); + is( $t1->month, 1, " month()" ); + is( $t1->day, 1, " day()" ); + + # like the tests above, but starting with ical instead of epoch + my $t2 = Date::ICal->new( ical => '19700101Z' ); + is( $t2->ical, '19700101Z', "Start of epoch in ICal notation" ); + + is( $t2->epoch, 0, " and back to ICal" ); + } + +A little bit of magic happens here. When running on anything but +MacOS, all the tests run normally. But when on MacOS, C causes +the entire contents of the SKIP block to be jumped over. It's never +run. Instead, it prints special output that tells Test::Harness that +the tests have been skipped. + + 1..7 + ok 1 - Epoch time of 0 + ok 2 # skip epoch to ICal not working on MacOS + ok 3 # skip epoch to ICal not working on MacOS + ok 4 # skip epoch to ICal not working on MacOS + ok 5 # skip epoch to ICal not working on MacOS + ok 6 # skip epoch to ICal not working on MacOS + ok 7 # skip epoch to ICal not working on MacOS + +This means your tests won't fail on MacOS. This means less emails +from MacPerl users telling you about failing tests that you know will +never work. You've got to be careful with skip tests. These are for +tests which don't work and I. It is not for skipping +genuine bugs (we'll get to that in a moment). + +The tests are wholly and completely skipped. [10] This will work. + + SKIP: { + skip("I don't wanna die!"); + + die, die, die, die, die; + } + + +=head2 Todo tests + +Thumbing through the Date::ICal man page, I came across this: + + ical + + $ical_string = $ical->ical; + + Retrieves, or sets, the date on the object, using any + valid ICal date/time string. + +"Retrieves or sets". Hmmm, didn't see a test for using C to set +the date in the Date::ICal test suite. So I'll write one. + + use Test::More tests => 1; + use Date::ICal; + + my $ical = Date::ICal->new; + $ical->ical('20201231Z'); + is( $ical->ical, '20201231Z', 'Setting via ical()' ); + +run that and I get + + 1..1 + not ok 1 - Setting via ical() + # Failed test (- at line 6) + # got: '20010814T233649Z' + # expected: '20201231Z' + # Looks like you failed 1 tests of 1. + +Whoops! Looks like it's unimplemented. Let's assume we don't have +the time to fix this. [11] Normally, you'd just comment out the test +and put a note in a todo list somewhere. Instead, we're going to +explicitly state "this test will fail" by wrapping it in a C block. + + use Test::More tests => 1; + + TODO: { + local $TODO = 'ical($ical) not yet implemented'; + + my $ical = Date::ICal->new; + $ical->ical('20201231Z'); + + is( $ical->ical, '20201231Z', 'Setting via ical()' ); + } + +Now when you run, it's a little different: + + 1..1 + not ok 1 - Setting via ical() # TODO ical($ical) not yet implemented + # got: '20010822T201551Z' + # expected: '20201231Z' + +Test::More doesn't say "Looks like you failed 1 tests of 1". That '# +TODO' tells Test::Harness "this is supposed to fail" and it treats a +failure as a successful test. So you can write tests even before +you've fixed the underlying code. + +If a TODO test passes, Test::Harness will report it "UNEXPECTEDLY +SUCCEEDED". When that happens, you simply remove the TODO block with +C and turn it into a real test. + + +=head2 Testing with taint mode. + +Taint mode is a funny thing. It's the globalest of all global +features. Once you turn it on, it affects I code in your program +and I modules used (and all the modules they use). If a single +piece of code isn't taint clean, the whole thing explodes. With that +in mind, it's very important to ensure your module works under taint +mode. + +It's very simple to have your tests run under taint mode. Just throw +a C<-T> into the C<#!> line. Test::Harness will read the switches +in C<#!> and use them to run your tests. + + #!/usr/bin/perl -Tw + + ...test normally here... + +So when you say C it will be run with taint mode and +warnings on. + + +=head1 FOOTNOTES + +=over 4 + +=item 1 + +The first number doesn't really mean anything, but it has to be 1. +It's the second number that's important. + +=item 2 + +For those following along at home, I'm using version 1.31. It has +some bugs, which is good -- we'll uncover them with our tests. + +=item 3 + +You can actually take this one step further and test the manual +itself. Have a look at B (formerly B). + +=item 4 + +Yes, there's a mistake in the test suite. What! Me, contrived? + +=item 5 + +We'll get to testing the contents of lists later. + +=item 6 + +But what happens if your test program dies halfway through?! Since we +didn't say how many tests we're going to run, how can we know it +failed? No problem, Test::More employs some magic to catch that death +and turn the test into a failure, even if every test passed up to that +point. + +=item 7 + +I cleaned it up a little. + +=item 8 + +Most Operating Systems record time as the number of seconds since a +certain date. This date is the beginning of the epoch. Unix's starts +at midnight January 1st, 1970 GMT. + +=item 9 + +MacOS's epoch is midnight January 1st, 1904. VMS's is midnight, +November 17th, 1858, but vmsperl emulates the Unix epoch so it's not a +problem. + +=item 10 + +As long as the code inside the SKIP block at least compiles. Please +don't ask how. No, it's not a filter. + +=item 11 + +Do NOT be tempted to use TODO tests as a way to avoid fixing simple +bugs! + +=back + +=head1 AUTHORS + +Michael G Schwern Eschwern@pobox.comE and the perl-qa dancers! + +=head1 COPYRIGHT + +Copyright 2001 by Michael G Schwern Eschwern@pobox.comE. + +This documentation is free; you can redistribute it and/or modify it +under the same terms as Perl itself. + +Irrespective of its distribution, all code examples in these files +are hereby placed into the public domain. You are permitted and +encouraged to use this code in your own programs for fun +or for profit as you see fit. A simple comment in the code giving +credit would be courteous but is not required. + +=cut diff --git a/SecurityTests/regressions/kc/kc-05-retain-release.c b/SecurityTests/regressions/kc/kc-05-retain-release.c new file mode 100755 index 00000000..2d9a8b86 --- /dev/null +++ b/SecurityTests/regressions/kc/kc-05-retain-release.c @@ -0,0 +1,36 @@ +#include +#include + +#include "testmore.h" +#include "testenv.h" + +int main(int argc, char *const *argv) +{ + plan_tests(8); + + if (!tests_begin(argc, argv)) + BAIL_OUT("tests_begin failed"); + + ok_status(SecKeychainSetUserInteractionAllowed(FALSE), "disable ui"); + SecKeychainRef keychain = NULL; + ok_status(SecKeychainCreate("test", 4, "test", FALSE, NULL, &keychain), + "SecKeychainCreate"); + SKIP: { + skip("can't continue without keychain", 2, ok(keychain, "keychain not NULL")); + ok_status(SecKeychainDelete(keychain), "SecKeychainDelete"); + + is_status(CFGetRetainCount(keychain), 1, "retaincount is 1"); + CFRelease(keychain); + } + + keychain = NULL; + ok_status(SecKeychainOpen("test", &keychain), "SecKeychainOpen"); + SKIP: { + skip("can't continue without keychain", 2, ok(keychain, "keychain not NULL")); + CFIndex retCount = CFGetRetainCount(keychain); + is_status(retCount, 1, "retaincount is 1"); + CFRelease(keychain); + } + + return !tests_end(1); +} diff --git a/SecurityTests/regressions/kc/kc-10-unlock-noui.c b/SecurityTests/regressions/kc/kc-10-unlock-noui.c new file mode 100755 index 00000000..939fc5af --- /dev/null +++ b/SecurityTests/regressions/kc/kc-10-unlock-noui.c @@ -0,0 +1,37 @@ +#include + +#include "testmore.h" +#include "testenv.h" + +int main(int argc, char *const *argv) +{ + int dont_skip = argc > 1 && !strcmp(argv[1], "-s"); + + plan_tests(7); + + ok_status(SecKeychainSetUserInteractionAllowed(FALSE), "SecKeychainSetUserInteractionAllowed(FALSE)"); + if (!tests_begin(argc, argv)) + BAIL_OUT("tests_begin failed"); + + SecKeychainRef keychain; + ok_status(SecKeychainCreate("test", 4, "test", FALSE, NULL, &keychain), + "SecKeychainCreate"); + ok_status(SecKeychainLock(keychain), "SecKeychainLock"); + SKIP: { + skip(" 8A325 SecKeychainSetUserInteractionAllowed() doesn't affect kc unlock dialogs", 1, dont_skip); + + is_status(SecKeychainUnlock(keychain, 0, NULL, FALSE), + errSecInteractionNotAllowed, "SecKeychainUnlock"); + } + ok_status(SecKeychainLock(keychain), "SecKeychainLock"); + CFRelease(keychain); + + ok_status(SecKeychainOpen("test", &keychain), "SecKeychainOpen locked kc"); + SKIP: { + skip(" 8A325 SecKeychainSetUserInteractionAllowed() doesn't affect kc unlock dialogs", 1, dont_skip); + + is_status(SecKeychainUnlock(keychain, 0, NULL, FALSE), + errSecInteractionNotAllowed, "SecKeychainUnlock"); + } + return !tests_end(1); +} diff --git a/SecurityTests/regressions/kc/kc-11-unlock-referral.c b/SecurityTests/regressions/kc/kc-11-unlock-referral.c new file mode 100755 index 00000000..c3fe6104 --- /dev/null +++ b/SecurityTests/regressions/kc/kc-11-unlock-referral.c @@ -0,0 +1,64 @@ +#include +#include + +#include "testmore.h" +#include "testenv.h" + +int main(int argc, char *const *argv) +{ + int dont_skip = argc > 1 && !strcmp(argv[1], "-s"); + + plan_tests(10); + + ok_status(SecKeychainSetUserInteractionAllowed(FALSE), "disable ui"); + if (!tests_begin(argc, argv)) + BAIL_OUT("tests_begin failed"); + + char *home = getenv("HOME"); + char source[256], dest[256]; + if (!home || strlen(home) > 200) + plan_skip_all("home too big"); + + sprintf(source, "%s/source", home); + sprintf(dest, "%s/dest", home); + SecKeychainRef sourcekc = NULL, destkc = NULL; + ok_status(SecKeychainCreate(source, 4, "test", FALSE, NULL, &sourcekc), + "SecKeychainCreate source"); + ok_status(SecKeychainCreate(dest, 4, "test", FALSE, NULL, &destkc), + "SecKeychainCreate dest"); + char cmdbuf[1024]; + ok_unix(sprintf(cmdbuf, "systemkeychain -k '%s' -s '%s'", dest, source), + "sprintf"); + SKIP: { + skip("systemkeychain brings up UI", 1, dont_skip); + + ok_unix(system(cmdbuf), "systemkeychain"); + } + ok_status(SecKeychainLock(sourcekc), "SecKeychainLock source"); + SKIP: { + skip("unlocking a source keychain w/ referal before reopen brings " + "up ui", 1, dont_skip); + TODO: { + todo(" Unlocking a source " + "keychain w/ referal before reopen fails"); + + ok_status(SecKeychainUnlock(sourcekc, 0, NULL, FALSE), + "SecKeychainUnlock source"); + } + } + CFRelease(sourcekc); + sourcekc = NULL; + char source2[256]; + sprintf(source2, "%s/source2", home); + ok_unix(rename(source, source2), "rename source -> source2"); + ok_status(SecKeychainOpen(source2, &sourcekc), "SecKeychainOpen source2"); + SKIP: { + skip("systemkeychain brings up UI", 1, dont_skip); + + ok_status(SecKeychainUnlock(sourcekc, 0, NULL, FALSE), + "SecKeychainUnlock source2"); + } + CFRelease(sourcekc); + + return !tests_end(1); +} diff --git a/SecurityTests/regressions/kc/kc-12-status.c b/SecurityTests/regressions/kc/kc-12-status.c new file mode 100755 index 00000000..68fb14af --- /dev/null +++ b/SecurityTests/regressions/kc/kc-12-status.c @@ -0,0 +1,138 @@ +#include +#include +#include +#include + +#include "testmore.h" +#include "testenv.h" +#include "testleaks.h" + +static void tests(void) +{ + char *home = getenv("HOME"); + char kcname1[256], kcname2[256]; + SecKeychainStatus status1, status2; + + if (!home || strlen(home) > 200) + plan_skip_all("home too big"); + + sprintf(kcname1, "%s/kc1/kc1", home); + SecKeychainRef kc1 = NULL, kc2 = NULL; + ok_status(SecKeychainCreate(kcname1, 4, "test", FALSE, NULL, &kc1), + "SecKeychainCreate kc1"); + + ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); + is(status1, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus, + "status unlocked readable writable"); + ok_status(SecKeychainLock(kc1), "SecKeychainLock kc1"); + ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); + TODO: { + todo(" KeychainImpl::status() returns " + "incorrect status (always writable?)"); + + is(status1, kSecReadPermStatus|kSecWritePermStatus, + "status (locked) readable writable"); + } + + /* Make keychain non writable. */ + char kcdir1[256]; + sprintf(kcdir1, "%s/kc1", home); + ok_unix(chmod(kcdir1, 0555), "chmod kcdir1 0555"); + + ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); + is(status1, kSecReadPermStatus, "status (locked) readable"); + ok_status(SecKeychainUnlock(kc1, 4, "test", TRUE), "SecKeychainLock kc1"); + ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); + TODO: { + todo(" KeychainImpl::status() returns " + "incorrect status (always writable?)"); + + is(status1, kSecUnlockStateStatus|kSecReadPermStatus, + "status unlocked readable"); + } + + /* Reopen the keychain. */ + CFRelease(kc1); + ok_status(SecKeychainOpen(kcname1, &kc1), "SecKeychainOpen kc1"); + + ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); + TODO: { + todo(" KeychainImpl::status() returns " + "incorrect status (always writable?)"); + + is(status1, kSecUnlockStateStatus|kSecReadPermStatus, + "status unlocked readable"); + } + + sprintf(kcname2, "%s/kc2/kc2", home); + ok_status(SecKeychainOpen(kcname2, &kc2), "SecKeychainOpen kc2"); + is_status(SecKeychainGetStatus(kc2, &status2), errSecNoSuchKeychain, + "get kc2 status"); + ok_status(SecKeychainCreate(kcname2, 4, "test", FALSE, NULL, &kc2), + "SecKeychainCreate kc2"); + ok_unix(chmod(kcname2, 0444), "chmod kc2 0444"); + ok_status(SecKeychainGetStatus(kc2, &status2), "get kc2 status"); + is(status2, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus, + "status unlocked readable writable"); + + /* Reopen the keychain. */ + CFRelease(kc2); + ok_status(SecKeychainOpen(kcname2, &kc2), "SecKeychainOpen kc2"); + + ok_status(SecKeychainGetStatus(kc2, &status2), "get kc2 status"); + is(status2, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus, + "status unlocked readable writable"); + + /* Restore dir to writable so cleanup code will work ok. */ + ok_unix(chmod(kcdir1, 0755), "chmod kcdir1 0755"); + CFRelease(kc1); + CFRelease(kc2); + + bool testWithFreshlyCreatedKeychain = true; + SecKeychainRef keychain; + ok_status(SecKeychainCreate("test", 4, "test", FALSE, NULL, &keychain), + "SecKeychainCreate"); + ok_status(SecKeychainLock(keychain), "SecKeychainLock"); + + do { + SecKeychainStatus keychainStatus = 0; + is_status(SecKeychainUnlock(keychain, 0, NULL, true), -25293, "SecKeychainUnlock with NULL password (incorrect)"); + ok_status(SecKeychainGetStatus(keychain, &keychainStatus), "SecKeychainGetStatus"); + is( (keychainStatus & kSecUnlockStateStatus), 0, "Check it's not unlocked"); + + keychainStatus = 0; + ok_status(SecKeychainUnlock(keychain, strlen("test"), "test", true), "SecKeychainUnlock with correct password"); + ok_status(SecKeychainGetStatus(keychain, &keychainStatus), "SecKeychainGetStatus"); + is( (keychainStatus & kSecUnlockStateStatus), kSecUnlockStateStatus, "Check it's unlocked"); + + ok_status(SecKeychainLock(keychain), "SecKeychainLock"); + CFRelease(keychain); + + if (testWithFreshlyCreatedKeychain) + { + testWithFreshlyCreatedKeychain = false; + ok_status(SecKeychainOpen("test", &keychain), "SecKeychainOpen"); + } + else + testWithFreshlyCreatedKeychain = true; + + } + while(!testWithFreshlyCreatedKeychain); + + tests_end(1); +} + + + +int main(int argc, char *const *argv) +{ + plan_tests(43); + if (!tests_begin(argc, argv)) + BAIL_OUT("tests_begin failed"); + + tests(); + + ok_leaks("leaks"); + + return 0; +} diff --git a/SecurityTests/regressions/kc/kc-15-item-add-generic.c b/SecurityTests/regressions/kc/kc-15-item-add-generic.c new file mode 100755 index 00000000..c9f778cc --- /dev/null +++ b/SecurityTests/regressions/kc/kc-15-item-add-generic.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include + +#include "testmore.h" +#include "testenv.h" +#include "testleaks.h" + +void tests(void) +{ + SecKeychainRef keychain; + ok_status(SecKeychainCreate("test", 4, "test", FALSE, NULL, &keychain), + "create keychain"); + SecKeychainItemRef item = NULL; + ok_status(SecKeychainAddGenericPassword(keychain, 7, "service", 7, + "account", 4, "test", &item), "add generic password"); + ok(item, "is item non NULL"); + SecKeychainItemRef oldItem = item; + is_status(SecKeychainAddGenericPassword(keychain, 7, "service", 7, + "account", 4, "test", &oldItem), + errSecDuplicateItem, "add generic password again"); + is((intptr_t)item, (intptr_t)oldItem, "item is unchanged"); + + SecItemClass itemClass = 0; + SecKeychainAttribute attrs[] = + { + { kSecAccountItemAttr }, + { kSecServiceItemAttr } + }; + SecKeychainAttributeList attrList = { sizeof(attrs) / sizeof(*attrs), attrs }; + UInt32 length = 0; + void *data = NULL; + ok_status(SecKeychainItemCopyContent(item, &itemClass, &attrList, &length, &data), "SecKeychainItemCopyContent"); + ok_status(SecKeychainItemFreeContent(&attrList, data), "SecKeychainItemCopyContent"); + + is(CFGetRetainCount(item), 1, "item retaincount is 1"); + is(CFGetRetainCount(keychain), 2, "keychain retaincount is 2"); + CFRelease(item); + is(CFGetRetainCount(keychain), 1, "keychain retaincount is 1"); + ok_status(SecKeychainDelete(keychain), "delete keychain"); + CFRelease(keychain); +} + +int main(int argc, char *const *argv) +{ + plan_tests(13); + + if (!tests_begin(argc, argv)) + BAIL_OUT("tests_begin failed"); + + tests(); + ok(tests_end(1), "cleanup"); + ok_leaks("no leaks"); + + return 0; +} diff --git a/SecurityTests/regressions/kc/kc-16-item-add-certificate.c b/SecurityTests/regressions/kc/kc-16-item-add-certificate.c new file mode 100644 index 00000000..f3d44c4e --- /dev/null +++ b/SecurityTests/regressions/kc/kc-16-item-add-certificate.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2005-2007,2009,2011 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@ + * + * 01DL_CreateReleation.c + */ + +#include +#include +#include +#include + +#include "testmore.h" +#include "testenv.h" + +/* Cert File Name: keybank_v3.101.cer */ +static const uint8 keybank_der_bytes[] = +{ + 0x30, 0x82, 0x03, 0x86, 0x30, 0x82, 0x02, 0xef, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x78, + 0xee, 0x48, 0xde, 0x18, 0x5b, 0x20, 0x71, 0xc9, + 0xc9, 0xc3, 0xb5, 0x1d, 0x7b, 0xdd, 0xc1, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x5f, + 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, 0x37, + 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, + 0x2e, 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, 0x30, + 0x1e, 0x17, 0x0d, 0x39, 0x37, 0x30, 0x34, 0x31, + 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, + 0x17, 0x0d, 0x31, 0x31, 0x31, 0x30, 0x32, 0x34, + 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, + 0x81, 0xba, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x04, 0x0a, 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, 0x17, 0x30, 0x15, 0x06, + 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0e, 0x56, 0x65, + 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, + 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x33, 0x30, 0x31, + 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, + 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x20, 0x43, 0x41, 0x20, + 0x2d, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, + 0x33, 0x31, 0x49, 0x30, 0x47, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x13, 0x40, 0x77, 0x77, 0x77, 0x2e, + 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, + 0x20, 0x49, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x62, 0x79, 0x20, 0x52, 0x65, 0x66, 0x2e, 0x20, + 0x4c, 0x49, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, + 0x59, 0x20, 0x4c, 0x54, 0x44, 0x2e, 0x28, 0x63, + 0x29, 0x39, 0x37, 0x20, 0x56, 0x65, 0x72, 0x69, + 0x53, 0x69, 0x67, 0x6e, 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, 0xd8, 0x82, 0x80, 0xe8, 0xd6, 0x19, 0x02, + 0x7d, 0x1f, 0x85, 0x18, 0x39, 0x25, 0xa2, 0x65, + 0x2b, 0xe1, 0xbf, 0xd4, 0x05, 0xd3, 0xbc, 0xe6, + 0x36, 0x3b, 0xaa, 0xf0, 0x4c, 0x6c, 0x5b, 0xb6, + 0xe7, 0xaa, 0x3c, 0x73, 0x45, 0x55, 0xb2, 0xf1, + 0xbd, 0xea, 0x97, 0x42, 0xed, 0x9a, 0x34, 0x0a, + 0x15, 0xd4, 0xa9, 0x5c, 0xf5, 0x40, 0x25, 0xdd, + 0xd9, 0x07, 0xc1, 0x32, 0xb2, 0x75, 0x6c, 0xc4, + 0xca, 0xbb, 0xa3, 0xfe, 0x56, 0x27, 0x71, 0x43, + 0xaa, 0x63, 0xf5, 0x30, 0x3e, 0x93, 0x28, 0xe5, + 0xfa, 0xf1, 0x09, 0x3b, 0xf3, 0xb7, 0x4d, 0x4e, + 0x39, 0xf7, 0x5c, 0x49, 0x5a, 0xb8, 0xc1, 0x1d, + 0xd3, 0xb2, 0x8a, 0xfe, 0x70, 0x30, 0x95, 0x42, + 0xcb, 0xfe, 0x2b, 0x51, 0x8b, 0x5a, 0x3c, 0x3a, + 0xf9, 0x22, 0x4f, 0x90, 0xb2, 0x02, 0xa7, 0x53, + 0x9c, 0x4f, 0x34, 0xe7, 0xab, 0x04, 0xb2, 0x7b, + 0x6f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, + 0xe6, 0x30, 0x81, 0xe3, 0x30, 0x0f, 0x06, 0x03, + 0x55, 0x1d, 0x13, 0x04, 0x08, 0x30, 0x06, 0x01, + 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x44, 0x06, + 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3d, 0x30, 0x3b, + 0x30, 0x39, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, + 0x86, 0xf8, 0x45, 0x01, 0x07, 0x01, 0x01, 0x30, + 0x2a, 0x30, 0x28, 0x06, 0x08, 0x2b, 0x06, 0x01, + 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1c, 0x68, + 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, + 0x77, 0x77, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, + 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x43, 0x50, 0x53, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x1d, 0x1f, 0x04, 0x2d, 0x30, 0x2b, 0x30, 0x29, + 0xa0, 0x27, 0xa0, 0x25, 0x86, 0x23, 0x68, 0x74, + 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, + 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, + 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x63, + 0x61, 0x33, 0x2d, 0x67, 0x32, 0x2e, 0x63, 0x72, + 0x6c, 0x30, 0x34, 0x06, 0x03, 0x55, 0x1d, 0x25, + 0x04, 0x2d, 0x30, 0x2b, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, + 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, + 0x42, 0x04, 0x01, 0x06, 0x0a, 0x60, 0x86, 0x48, + 0x01, 0x86, 0xf8, 0x45, 0x01, 0x08, 0x01, 0x30, + 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, + 0x03, 0x02, 0x01, 0x06, 0x30, 0x11, 0x06, 0x09, + 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, + 0x01, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, + 0x81, 0x00, 0x23, 0x5d, 0xee, 0xa6, 0x24, 0x05, + 0xfd, 0x76, 0xd3, 0x6a, 0x1a, 0xd6, 0xba, 0x46, + 0x06, 0xaa, 0x6a, 0x0f, 0x03, 0x90, 0x66, 0xb2, + 0xb0, 0xa6, 0xc2, 0x9e, 0xc9, 0x1e, 0xa3, 0x55, + 0x53, 0xaf, 0x3e, 0x45, 0xfd, 0xdc, 0x8c, 0x27, + 0xdd, 0x53, 0x38, 0x09, 0xbb, 0x7c, 0x4b, 0x2b, + 0xba, 0x95, 0x4a, 0xfe, 0x70, 0x4e, 0x1b, 0x69, + 0xd6, 0x3c, 0xf7, 0x4f, 0x07, 0xc5, 0xf2, 0x17, + 0x5a, 0x4c, 0xa2, 0x8f, 0xac, 0x0b, 0x8a, 0x06, + 0xdb, 0xb9, 0xd4, 0x6b, 0xc5, 0x1d, 0x58, 0xda, + 0x17, 0x52, 0xe3, 0x21, 0xf1, 0xd2, 0xd7, 0x5a, + 0xd5, 0xe5, 0xab, 0x59, 0x7b, 0x21, 0x7a, 0x86, + 0x6a, 0xd4, 0xfe, 0x17, 0x11, 0x3a, 0x53, 0x0d, + 0x9c, 0x60, 0xa0, 0x4a, 0xd9, 0x5e, 0xe4, 0x1d, + 0x0c, 0x29, 0xaa, 0x13, 0x07, 0x65, 0x86, 0x1f, + 0xbf, 0xb4, 0xc9, 0x82, 0x53, 0x9c, 0x2c, 0x02, + 0x8f, 0x23 +}; +static const CSSM_DATA keybank_der = +{ + sizeof(keybank_der_bytes), + (uint8 *)keybank_der_bytes +}; + +static void +certTests(SecKeychainRef keychain) +{ + SecCertificateRef certificate = NULL; + ok_status(SecCertificateCreateFromData(&keybank_der, + CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &certificate), + "SecCertificateCreateFromData"); + ok(certificate, "certificate non NULL"); + ok_status(SecCertificateAddToKeychain(certificate, keychain), + "SecCertificateAddToKeychain fails unless 4039735 is fixed"); + + is_status(SecCertificateAddToKeychain(certificate, keychain), + errSecDuplicateItem, "SecCertificateAddToKeychain twice"); + + SecCertificateRef certificate2 = NULL; + ok_status(SecCertificateCreateFromData(&keybank_der, + CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &certificate2), + "SecCertificateCreateFromData"); + is_status(SecCertificateAddToKeychain(certificate2, keychain), + errSecDuplicateItem, "SecCertificateAddToKeychain twice"); + is(CFGetRetainCount(certificate2), 1, "certificate2 retain count is 1"); + CFRelease(certificate2); + + SecKeychainRef certKeychain = NULL; + ok_status(SecKeychainItemCopyKeychain((SecKeychainItemRef)certificate, + &certKeychain), "SecKeychainItemCopyKeychain"); + is((intptr_t)keychain, (intptr_t)certKeychain, "cert's keychain is keychain"); + CFRelease(certKeychain); + + is(CFGetRetainCount(certificate), 1, "certificate retain count is 1"); + CFRelease(certificate); + + ok_status(SecKeychainDelete(keychain), "SecKeychainDelete"); + is(CFGetRetainCount(keychain), 1, "keychain retain count is 1"); + CFRelease(keychain); +} + +int +main(int argc, char * const *argv) +{ + plan_tests(33); + if (!tests_begin(argc, argv)) + return 255; + + /* Test with autocommit on. */ + SecKeychainRef keychain = NULL; + ok_status(SecKeychainCreate("test.keychain", 4, "test", FALSE, NULL, + &keychain), "SecKeychainCreate"); + ok(keychain, "keychain non NULL"); + certTests(keychain); + + /* Test with autocommit off. */ + keychain = NULL; + ok_status(SecKeychainCreate("test2.keychain", 4, "test", FALSE, NULL, + &keychain), "SecKeychainCreate"); + ok(keychain, "keychain non NULL"); + CSSM_DL_DB_HANDLE cspdl_dldb = {}; + ok_status(SecKeychainGetDLDBHandle(keychain, &cspdl_dldb), + "SecKeychainGetDLDBHandle"); + CSSM_DL_DB_HANDLE dldb = {}; + ok_status(CSSM_DL_PassThrough(cspdl_dldb, CSSM_APPLECSPDL_DB_GET_HANDLE, + NULL, (void **)&dldb), "get dl handle"); + ok(dldb.DLHandle, "dldb.DLHandle non 0"); + ok(dldb.DBHandle, "dldb.DBHandle non 0"); + ok_status(CSSM_DL_PassThrough(dldb, CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, + (const void *)FALSE, NULL), "autocommit off"); + certTests(keychain); + + return !tests_end(1); +} diff --git a/SecurityTests/regressions/kc/kc-17-item-find-key.c b/SecurityTests/regressions/kc/kc-17-item-find-key.c new file mode 100755 index 00000000..eb4024d8 --- /dev/null +++ b/SecurityTests/regressions/kc/kc-17-item-find-key.c @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include + +#include "testmore.h" +#include "testenv.h" +#include "testleaks.h" + +void tests(void) +{ + SecKeychainRef keychain; + ok_status(SecKeychainCreate("test", 4, "test", FALSE, NULL, &keychain), + "create keychain"); + SecKeyRef pub_crypt = NULL, prv_crypt = NULL; + ok_status(SecKeyCreatePair(keychain, CSSM_ALGID_RSA, 256, + 0 /* contextHandle */, + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_WRAP, + CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE, + CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_UNWRAP, + CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE | + CSSM_KEYATTR_SENSITIVE, + NULL /* initialAccess */, &pub_crypt, &prv_crypt), + "generate encryption keypair"); + + SecKeyRef pub_sign = NULL, prv_sign = NULL; + ok_status(SecKeyCreatePair(keychain, CSSM_ALGID_RSA, 256, + 0 /* contextHandle */, + CSSM_KEYUSE_VERIFY, + CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE, + CSSM_KEYUSE_SIGN, + CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE | + CSSM_KEYATTR_SENSITIVE, + NULL /* initialAccess */, &pub_sign, &prv_sign), + "generate signing keypair"); + + uint32 btrue = 1; + uint32 bfalse = 0; + /* uint32 prv_class = CSSM_KEYCLASS_PRIVATE_KEY; */ + SecKeychainAttribute attrs[] = + { + { kSecKeyDecrypt, sizeof(uint32), &btrue }, + { kSecKeyEncrypt, sizeof(uint32), &bfalse }, + /* { kSecKeyKeyClass, sizeof(uint32), &prv_class } */ + }; + SecKeychainAttributeList attrList = { sizeof(attrs) / sizeof(*attrs), attrs }; + SecKeychainSearchRef search; + OSStatus result; + SecKeychainItemRef item; + + ok_status((result = SecKeychainSearchCreateFromAttributes(keychain, + CSSM_DL_DB_RECORD_PRIVATE_KEY, &attrList, &search)), "create key search"); + if (result == noErr) + { + ok_status(SecKeychainSearchCopyNext(search, &item), "get first key"); + cmp_ok((intptr_t)prv_crypt, ==, (intptr_t)item, "is key found the right one?"); + CFRelease(item); + item = NULL; + is_status(SecKeychainSearchCopyNext(search, &item), + errSecItemNotFound, "get next key"); + is((intptr_t)item, 0, "no item returned"); + CFRelease(search); + } + + SecKeychainAttribute attrs2[] = { { kSecKeySign, sizeof(btrue), &btrue } }; + SecKeychainAttributeList attrList2 = { sizeof(attrs2) / sizeof(*attrs2), attrs2 }; + ok_status((result = SecKeychainSearchCreateFromAttributes(keychain, + CSSM_DL_DB_RECORD_PRIVATE_KEY, &attrList2, &search)), "create private signing key search"); + + if (result == noErr) + { + ok_status(SecKeychainSearchCopyNext(search, &item), "get first key"); + cmp_ok((intptr_t)prv_sign, ==, (intptr_t)item, "is key found the right one?"); + CFRelease(item); + is_status(SecKeychainSearchCopyNext(search, &item), + errSecItemNotFound, "get next key"); + CFRelease(search); + } + + CFRelease(pub_crypt); + CFRelease(prv_crypt); + CFRelease(pub_sign); + CFRelease(prv_sign); + CFRelease(keychain); + + ok(tests_end(1), "cleanup"); +} + +int main(int argc, char *const *argv) +{ + plan_tests(14); + + if (!tests_begin(argc, argv)) + BAIL_OUT("tests_begin failed"); + + tests(); + ok_leaks("no leaks"); + + return 0; +} diff --git a/SecurityTests/regressions/kc/kc-18-item-find-internet.c b/SecurityTests/regressions/kc/kc-18-item-find-internet.c new file mode 100755 index 00000000..49899b66 --- /dev/null +++ b/SecurityTests/regressions/kc/kc-18-item-find-internet.c @@ -0,0 +1,114 @@ +#include +#include +#include +#include + +#include "testmore.h" +#include "testenv.h" +#include "testleaks.h" + +void tests(int dont_skip) +{ + SecKeychainRef keychain; + ok_status(SecKeychainCreate("test", 4, "test", FALSE, NULL, &keychain), + "create keychain"); + SecKeychainItemRef item = NULL; + ok_status(SecKeychainAddInternetPassword(keychain, + 19, "members.spamcop.net", + 0, NULL, + 5, "smith", + 0, NULL, + 80, kSecProtocolTypeHTTP, + kSecAuthenticationTypeDefault, + 4, "test", &item), "add internet password"); + ok(item, "is item non NULL"); + SecKeychainItemRef oldItem = item; + is_status(SecKeychainAddInternetPassword(keychain, + 19, "members.spamcop.net", + 0, NULL, + 5, "smith", + 0, NULL, + 80, kSecProtocolTypeHTTP, + kSecAuthenticationTypeDefault, + 4, "test", &item), errSecDuplicateItem, "add internet password again"); + is((intptr_t)item, (intptr_t)oldItem, "item is unchanged"); + + CFRelease(item); + item = NULL; + ok_status(SecKeychainFindInternetPassword(NULL, + 19, "members.spamcop.net", + 0, NULL, + 0, NULL, + 0, NULL, + 80, + kSecProtocolTypeHTTP, + kSecAuthenticationTypeDefault, + NULL, NULL, + &item), "find internet password"); + + SecItemClass itemClass = 0; + SecKeychainAttribute attrs[] = + { + { kSecAccountItemAttr }, + { kSecSecurityDomainItemAttr }, + { kSecServerItemAttr } + }; + SecKeychainAttributeList attrList = + { + sizeof(attrs) / sizeof(*attrs), + attrs + }; + ok_status(SecKeychainItemCopyContent(item, &itemClass, &attrList, + NULL, NULL), "SecKeychainItemCopyContent"); + is(itemClass, kSecInternetPasswordItemClass, "is internet password?"); + is(attrs[0].length, 5, "account len"); + ok(!strncmp(attrs[0].data, "smith", 5), "account eq smith"); + is(attrs[1].length, 0, "security domain len"); + is(attrs[2].length, 19, "server len"); + ok(!strncmp(attrs[2].data, "members.spamcop.net", 19), + "servername eq members.spamcop.net"); + ok_status(SecKeychainItemFreeContent(&attrList, NULL), + "SecKeychainItemCopyContent"); + + SecKeychainAttribute attrs2[] = + { + { kSecAccountItemAttr }, + { kSecServiceItemAttr }, + { kSecSecurityDomainItemAttr }, + { kSecServerItemAttr } + }; + SecKeychainAttributeList attrList2 = + { + (sizeof(attrs2) / sizeof(*attrs2)), + attrs2 + }; + SKIP: { + skip(" 6L60 Malloc/free misuse in " + "SecKeychainItemCopyContent()", 1, dont_skip); + is_status(SecKeychainItemCopyContent(item, &itemClass, &attrList2, + NULL, NULL), errSecNoSuchAttr, "SecKeychainItemCopyContent fails"); + } + + is(CFGetRetainCount(item), 1, "item retaincount is 1"); + is(CFGetRetainCount(keychain), 2, "keychain retaincount is 2"); + CFRelease(item); + is(CFGetRetainCount(keychain), 1, "keychain retaincount is 1"); + ok_status(SecKeychainDelete(keychain), "delete keychain"); + CFRelease(keychain); +} + +int main(int argc, char *const *argv) +{ + int dont_skip = argc > 1 && !strcmp(argv[1], "-s"); + + plan_tests(21); + + if (!tests_begin(argc, argv)) + BAIL_OUT("tests_begin failed"); + + tests(dont_skip); + ok(tests_end(1), "cleanup"); + ok_leaks("no leaks"); + + return 0; +} diff --git a/SecurityTests/regressions/kc/kc-19-item-copy-internet.c b/SecurityTests/regressions/kc/kc-19-item-copy-internet.c new file mode 100755 index 00000000..f3a2e20c --- /dev/null +++ b/SecurityTests/regressions/kc/kc-19-item-copy-internet.c @@ -0,0 +1,112 @@ +#include +#include +#include +#include + +#include "testmore.h" +#include "testenv.h" +#include "testleaks.h" + +void tests(int dont_skip) +{ + SecKeychainRef source, dest; + ok_status(SecKeychainCreate("source", 4, "test", FALSE, NULL, &source), + "create source keychain"); + ok_status(SecKeychainCreate("dest", 4, "test", FALSE, NULL, &dest), + "create dest keychain"); + SecKeychainItemRef original = NULL; + ok_status(SecKeychainAddInternetPassword(source, + 19, "members.spamcop.net", + 0, NULL, + 5, "smith", + 0, NULL, + 80, kSecProtocolTypeHTTP, + kSecAuthenticationTypeDefault, + 4, "test", &original), "add internet password"); + SecKeychainAttribute origAttrs[] = + { + { kSecCreationDateItemAttr }, + { kSecModDateItemAttr } + }; + SecKeychainAttributeList origAttrList = + { + sizeof(origAttrs) / sizeof(*origAttrs), + origAttrs + }; + ok_status(SecKeychainItemCopyContent(original, NULL, &origAttrList, + NULL, NULL), "SecKeychainItemCopyContent"); + + /* Must sleep 1 second to trigger mod date bug. */ + sleep(1); + SecKeychainItemRef copy; + ok_status(SecKeychainItemCreateCopy(original, dest, NULL, ©), + "copy item"); + + SecKeychainAttribute copyAttrs[] = + { + { kSecCreationDateItemAttr }, + { kSecModDateItemAttr } + }; + SecKeychainAttributeList copyAttrList = + { + sizeof(copyAttrs) / sizeof(*copyAttrs), + copyAttrs + }; + ok_status(SecKeychainItemCopyContent(copy, NULL, ©AttrList, + NULL, NULL), "SecKeychainItemCopyContent"); + + is(origAttrs[0].length, 16, "creation date length 16"); + is(origAttrs[1].length, 16, "mod date length 16"); + is(origAttrs[0].length, copyAttrs[0].length, "creation date length same"); + is(origAttrs[1].length, copyAttrs[1].length, "mod date length same"); + + TODO: { + todo(" Moving/copying a keychain item " + "between keychains erroneously updates dates"); + + diag("original creation: %.*s copy creation: %.*s", + (int)origAttrs[0].length, (const char *)origAttrs[0].data, + (int)copyAttrs[0].length, (const char *)copyAttrs[0].data); + ok(!memcmp(origAttrs[0].data, copyAttrs[0].data, origAttrs[0].length), + "creation date same"); + + diag("original mod: %.*s copy mod: %.*s", + (int)origAttrs[1].length, (const char *)origAttrs[1].data, + (int)copyAttrs[1].length, (const char *)copyAttrs[1].data); + ok(!memcmp(origAttrs[1].data, copyAttrs[1].data, origAttrs[1].length), + "mod date same"); + } + + ok_status(SecKeychainItemFreeContent(&origAttrList, NULL), + "SecKeychainItemCopyContent"); + ok_status(SecKeychainItemFreeContent(©AttrList, NULL), + "SecKeychainItemCopyContent"); + + is(CFGetRetainCount(original), 1, "original retaincount is 1"); + CFRelease(original); + is(CFGetRetainCount(copy), 1, "copy retaincount is 1"); + CFRelease(copy); + is(CFGetRetainCount(source), 1, "source retaincount is 1"); + ok_status(SecKeychainDelete(source), "delete keychain source"); + CFRelease(source); + ok_status(SecKeychainDelete(dest), "delete keychain dest"); + is(CFGetRetainCount(dest), 1, "dest retaincount is 1"); + CFRelease(dest); + + ok(tests_end(1), "cleanup"); +} + +int main(int argc, char *const *argv) +{ + int dont_skip = argc > 1 && !strcmp(argv[1], "-s"); + + plan_tests(22); + + if (!tests_begin(argc, argv)) + BAIL_OUT("tests_begin failed"); + + tests(dont_skip); + ok_leaks("no leaks"); + + return 0; +} diff --git a/SecurityTests/regressions/kc/kc-20-item-change-label.m b/SecurityTests/regressions/kc/kc-20-item-change-label.m new file mode 100755 index 00000000..2bd4c404 --- /dev/null +++ b/SecurityTests/regressions/kc/kc-20-item-change-label.m @@ -0,0 +1,327 @@ +// +// keychain_test.m +// Keychain item access control example +// +// Created by Perry Kiehtreiber on Wed Jun 19 2002 +// Modified by Ken McLeod, Mon Apr 21 2003 -- added "always allow" ACL support +// Wed Jul 28 2004 -- add test code for persistent ref SPI +// Mon Aug 02 2004 -- add test code to change label attributes +// +// To build and run this example: +// cc -framework Security -framework Foundation keychain_test.m ; ./a.out +// +// Copyright (c) 2003-2005 Apple Computer, Inc. All Rights Reserved. +// + +#define TEST_PERSISTENT_REFS 0 +#define USE_SYSTEM_KEYCHAIN 0 + + +#import + +#include +#include +#include +#include +#include +#include +#include +#include + +#import "testmore.h" +#import "testenv.h" +#import "testleaks.h" + +SecAccessRef createAccess(NSString *accessLabel, BOOL allowAny) +{ + SecAccessRef access=nil; + NSArray *trustedApplications=nil; + + if (!allowAny) // use default access ("confirm access") + { + // make an exception list of applications you want to trust, which + // are allowed to access the item without requiring user confirmation + SecTrustedApplicationRef myself, someOther; + ok_status(SecTrustedApplicationCreateFromPath(NULL, &myself), + "create trusted app for self"); + ok_status(SecTrustedApplicationCreateFromPath("/Applications/Mail.app", + &someOther), "create trusted app for Mail.app"); + trustedApplications = [NSArray arrayWithObjects:(id)myself, + (id)someOther, nil]; + CFRelease(myself); + CFRelease(someOther); + } + + ok_status(SecAccessCreate((CFStringRef)accessLabel, + (CFArrayRef)trustedApplications, &access), "SecAccessCreate"); + + if (allowAny) + { + // change access to be wide-open for decryption ("always allow access") + // get the access control list for decryption operations + CFArrayRef aclList=nil; + ok_status(SecAccessCopySelectedACLList(access, + CSSM_ACL_AUTHORIZATION_DECRYPT, &aclList), + "SecAccessCopySelectedACLList"); + + // get the first entry in the access control list + SecACLRef aclRef=(SecACLRef)CFArrayGetValueAtIndex(aclList, 0); + CFArrayRef appList=nil; + CFStringRef promptDescription=nil; + CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector; + ok_status(SecACLCopySimpleContents(aclRef, &appList, + &promptDescription, &promptSelector), "SecACLCopySimpleContents"); + + // modify the default ACL to not require the passphrase, and have a + // nil application list + promptSelector.flags &= ~CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE; + ok_status(SecACLSetSimpleContents(aclRef, NULL, promptDescription, + &promptSelector), "SecACLSetSimpleContents"); + + if (appList) CFRelease(appList); + if (promptDescription) CFRelease(promptDescription); + if (aclList) CFRelease(aclList); + } + + return access; +} + + +void addApplicationPassword(SecKeychainRef keychain, NSString *password, + NSString *account, NSString *service, BOOL allowAny) +{ + SecKeychainItemRef item = nil; + const char *serviceUTF8 = [service UTF8String]; + const char *accountUTF8 = [account UTF8String]; + const char *passwordUTF8 = [password UTF8String]; + // use the service string as the name of this item for display purposes + NSString *itemLabel = service; + const char *itemLabelUTF8 = [itemLabel UTF8String]; + +#if USE_SYSTEM_KEYCHAIN + const char *sysKeychainPath = "/Library/Keychains/System.keychain"; + status = SecKeychainOpen(sysKeychainPath, &keychain); + if (status) { NSLog(@"SecKeychainOpen returned %d", status); return; } + status = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem); + if (status) { NSLog(@"SecKeychainSetPreferenceDomain returned %d", status); return; } +#endif + + // create initial access control settings for the item + SecAccessRef access = createAccess(itemLabel, allowAny); + + // Below is the lower-layer equivalent to the + // SecKeychainAddGenericPassword() function; it does the same thing + // (except specify the access controls) set up attribute vector + // (each attribute consists of {tag, length, pointer}) + SecKeychainAttribute attrs[] = { + { kSecLabelItemAttr, strlen(itemLabelUTF8), (char *)itemLabelUTF8 }, + { kSecAccountItemAttr, strlen(accountUTF8), (char *)accountUTF8 }, + { kSecServiceItemAttr, strlen(serviceUTF8), (char *)serviceUTF8 } + }; + SecKeychainAttributeList attributes = + { sizeof(attrs) / sizeof(attrs[0]), attrs }; + + ok_status(SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass, + &attributes, strlen(passwordUTF8), passwordUTF8, keychain, access, + &item), "SecKeychainItemCreateFromContent"); + + if (access) CFRelease(access); + if (item) CFRelease(item); +} + + +void addInternetPassword(SecKeychainRef keychain, NSString *password, + NSString *account, NSString *server, NSString *path, + SecProtocolType protocol, int port, BOOL allowAny) +{ + SecKeychainItemRef item = nil; + const char *pathUTF8 = [path UTF8String]; + const char *serverUTF8 = [server UTF8String]; + const char *accountUTF8 = [account UTF8String]; + const char *passwordUTF8 = [password UTF8String]; + // use the server string as the name of this item for display purposes + NSString *itemLabel = server; + const char *itemLabelUTF8 = [itemLabel UTF8String]; + +#if USE_SYSTEM_KEYCHAIN + const char *sysKeychainPath = "/Library/Keychains/System.keychain"; + status = SecKeychainOpen(sysKeychainPath, &keychain); + if (status) { NSLog(@"SecKeychainOpen returned %d", status); return 1; } + status = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem); + if (status) { NSLog(@"SecKeychainSetPreferenceDomain returned %d", status); return 1; } +#endif + + // create initial access control settings for the item + SecAccessRef access = createAccess(itemLabel, allowAny); + + // below is the lower-layer equivalent to the + // SecKeychainAddInternetPassword() function; it does the same + // thing (except specify the access controls) set up attribute + // vector (each attribute consists of {tag, length, pointer}) + SecKeychainAttribute attrs[] = { + { kSecLabelItemAttr, strlen(itemLabelUTF8), (char *)itemLabelUTF8 }, + { kSecAccountItemAttr, strlen(accountUTF8), (char *)accountUTF8 }, + { kSecServerItemAttr, strlen(serverUTF8), (char *)serverUTF8 }, + { kSecPortItemAttr, sizeof(int), (int *)&port }, + { kSecProtocolItemAttr, sizeof(SecProtocolType), + (SecProtocolType *)&protocol }, + { kSecPathItemAttr, strlen(pathUTF8), (char *)pathUTF8 } + }; + SecKeychainAttributeList attributes = + { sizeof(attrs) / sizeof(attrs[0]), attrs }; + + ok_status(SecKeychainItemCreateFromContent(kSecInternetPasswordItemClass, + &attributes, strlen(passwordUTF8), passwordUTF8, keychain, access, + &item), "SecKeychainItemCreateFromContent"); + +//*** code to test persistent reference SPI +#if TEST_PERSISTENT_REFS + CFDataRef persistentRef = NULL; + SecKeychainItemRef item2 = NULL; + status = SecKeychainItemCopyPersistentReference(item, &persistentRef); + if (!status) + { + NSLog(@"Created persistent reference for item %@:\n%@", item, + persistentRef); + status = SecKeychainItemFromPersistentReference(persistentRef, &item2); + if (!status) + NSLog(@"SUCCESS: Got item from persistent reference (%@)", item2); + else + NSLog(@"ERROR: unable to reconsitute item (%d)", status); + } + else + { + NSLog(@"ERROR: unable to create persistent reference (%d)", status); + } + //[(NSData*)pref writeToFile:@"/tmp/persistentData" atomically:YES]; + if (item2) CFRelease(item2); + if (persistentRef) CFRelease(persistentRef); +#endif +//*** end persistent reference test code + + if (access) CFRelease(access); + if (item) CFRelease(item); +} + +void testLabelChange(SecKeychainRef keychain) +{ + // Find each generic password item in any keychain whose label + // is "sample service", and modify the existing label attribute + // by adding a " [label]" suffix. (Note that if the Keychain + // Access app is running, you may need to quit and relaunch it to + // see the changes, due to notification bugs.) + + const char *searchString = "sample service"; + const char *labelSuffix = " [label]"; + +#if USE_SYSTEM_KEYCHAIN + const char *sysKeychainPath = "/Library/Keychains/System.keychain"; + status = SecKeychainOpen(sysKeychainPath, &keychain); + if (status) { NSLog(@"SecKeychainOpen returned %d", status); return 0; } + status = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem); + if (status) { NSLog(@"SecKeychainSetPreferenceDomain returned %d", status); return 0; } +#endif + + SecKeychainSearchRef searchRef = nil; + SecKeychainAttribute sAttrs[] = + { { kSecServiceItemAttr, strlen(searchString), (char*)searchString } }; + SecKeychainAttributeList sAttrList = + { sizeof(sAttrs) / sizeof(sAttrs[0]), sAttrs }; + ok_status(SecKeychainSearchCreateFromAttributes(keychain, + kSecGenericPasswordItemClass, &sAttrList, &searchRef), + "SecKeychainSearchCreateFromAttributes"); + + SecKeychainItemRef foundItemRef = NULL; + int count; + for (count = 0; count < 2; ++count) + { + ok_status(SecKeychainSearchCopyNext(searchRef, &foundItemRef), + "SecKeychainSearchCopyNext"); + + // get the item's label attribute (allocated for us by + // SecKeychainItemCopyContent, must free later...) + SecKeychainAttribute itemAttrs[] = { { kSecLabelItemAttr, 0, NULL } }; + SecKeychainAttributeList itemAttrList = + { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs }; + + ok_status(SecKeychainItemCopyContent(foundItemRef, NULL, &itemAttrList, + NULL, NULL), "get label"); + + // malloc enough space to hold our new label string + // (length = old label string + suffix string + terminating NULL) + CFIndex newLen = itemAttrs[0].length + strlen(labelSuffix); + char *p = (char*) malloc(newLen); + memcpy(p, itemAttrs[0].data, itemAttrs[0].length); + memcpy(p + itemAttrs[0].length, labelSuffix, strlen(labelSuffix)); + + // set up the attribute we want to change with its new value + SecKeychainAttribute newAttrs[] = { { kSecLabelItemAttr, newLen, p } }; + SecKeychainAttributeList newAttrList = + { sizeof(newAttrs) / sizeof(newAttrs[0]), newAttrs }; + + // modify the attribute + ok_status(SecKeychainItemModifyContent(foundItemRef, &newAttrList, + 0, NULL), "modify label PR-3751523"); + + // free the memory we allocated for the new label string + free(p); + + // free the memory in the itemAttrList structure which was + // allocated by SecKeychainItemCopyContent + ok_status(SecKeychainItemFreeContent(&itemAttrList, NULL), + "SecKeychainItemFreeContent"); + + if (foundItemRef) + CFRelease(foundItemRef); + } + + is_status(SecKeychainSearchCopyNext(searchRef, &foundItemRef), + errSecItemNotFound, "SecKeychainSearchCopyNext at end"); + + if (searchRef) CFRelease(searchRef); +} + +void tests(void) +{ + SecKeychainRef keychain = NULL; + ok_status(SecKeychainCreate("login.keychain", 4, "test", NO, NULL, + &keychain), "SecKeychainCreate"); + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + // add some example passwords to the keychain + addApplicationPassword(keychain, @"sample password", + @"sample account", @"sample service", NO); + addApplicationPassword(keychain, @"sample password", + @"different account", @"sample service", NO); + addApplicationPassword(keychain, @"sample password", + @"sample account", @"sample unprotected service", YES); + addInternetPassword(keychain, @"sample password", + @"sample account", @"samplehost.apple.com", + @"cgi-bin/bogus/testpath", kSecProtocolTypeHTTP, 8080, NO); + + // test searching and changing item label attributes + testLabelChange(keychain); + + [pool release]; + + SKIP: { + skip("no keychain", 1, keychain); + ok_status(SecKeychainDelete(keychain), "SecKeychainDelete"); + CFRelease(keychain); + } + + tests_end(1); +} + +int main(int argc, char * const *argv) +{ + plan_tests(30); + tests_begin(argc, argv); + + tests(); + + ok_leaks("leaks"); + + return 0; +} diff --git a/SecurityTests/regressions/kc/kc-21-item-use-callback.c b/SecurityTests/regressions/kc/kc-21-item-use-callback.c new file mode 100644 index 00000000..3d522600 --- /dev/null +++ b/SecurityTests/regressions/kc/kc-21-item-use-callback.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include + +#include "testmore.h" +#include "testenv.h" +#include "testleaks.h" + +static char account[] = "account"; +static char service[] = "service"; +static char password[] = "password"; + +static void checkContent(SecKeychainItemRef itemRef) +{ + SecItemClass itemClass; + + SecKeychainAttribute attrs[] = + { + { kSecLabelItemAttr, 0, NULL }, + { kSecAccountItemAttr, 0, NULL }, + { kSecServiceItemAttr, 0, NULL } + }; + + SecKeychainAttributeList attrList = + { sizeof(attrs) / sizeof(*attrs), attrs }; + UInt32 length; + void *data; + +#if 1 + ok_status(SecKeychainItemCopyContent(itemRef, &itemClass, &attrList, + &length, &data), "get item data in callback"); + SKIP: { + skip("length mismatch", 1, + is(length, sizeof(password), " " + "SecKeychainItemCopyContent() returns bad data on items " + "from notifications")); + + ok(!memcmp(password, data, length), "password data matches."); + } +#else + if (length != sizeof(password) || memcmp(password, data, length)) + { + fprintf(stderr, "password '%.*s' not same as '%.*s'\n", + (int)sizeof(password), password, + (int)length, (char *)data); + } +#endif + + ok_status(SecKeychainItemFreeContent(&attrList, data), + "free item data in callback"); +} + +static OSStatus callbackFunction(SecKeychainEvent keychainEvent, + SecKeychainCallbackInfo *info, void *context) +{ + assert(keychainEvent == kSecAddEvent && context != NULL); + assert(info != NULL); + assert(info->item != NULL); + + checkContent(info->item); + *((UInt32 *)context) = 1; + + ok_status(SecKeychainItemDelete(info->item), "delete item"); + return 0; +} + +int +main(int argc, char *const *argv) +{ + plan_tests(6); + + ok(tests_begin(argc, argv), "setup"); + + UInt32 didGetNotification = 0; + ok_status(SecKeychainAddCallback(callbackFunction, kSecAddEventMask, + &didGetNotification), "add callback"); + + SecKeychainRef keychain; + ok_status(SecKeychainCreate("test", 4, "test", FALSE, NULL, &keychain), + "create keychain"); + SecKeychainItemRef itemRef; + ok_status(SecKeychainAddGenericPassword(keychain, + sizeof(account), account, + sizeof(service), service, + sizeof(password), password, + &itemRef), + "add generic password, release and wait for callback"); + //checkContent(itemRef); + CFRelease(itemRef); + CFRelease(keychain); + + if (argc > 1 && !strcmp(argv[1], "-l")) { + printf("pid: %d\n", getpid()); + sleep(100); + } + ok(tests_end(1), "cleanup"); + ok_leaks("leaks"); + + return 0; +} diff --git a/SecurityTests/regressions/kc/kc-22-key-symmetric.c b/SecurityTests/regressions/kc/kc-22-key-symmetric.c new file mode 100755 index 00000000..51b472ef --- /dev/null +++ b/SecurityTests/regressions/kc/kc-22-key-symmetric.c @@ -0,0 +1,133 @@ +/* Included due to SecKeyPriv.h should + include */ +#include + +#include +#include +#include +#include + +#include "testenv.h" +#include "testleaks.h" +#include "testmore.h" +#include "testsecevent.h" + +void tests(int dont_skip) +{ + SecKeychainRef keychain; + ok_status(SecKeychainCreate("test", 4, "test", FALSE, NULL, &keychain), + "create keychain"); + + /* Symmetric key tests. */ + +#ifdef DEBUG + ok_status(test_sec_event_register(kSecAddEventMask | kSecDeleteEventMask), + "register for add events"); + SecKeychainItemRef aes_key = NULL; +#endif + + ok_status(SecKeyGenerate(keychain, CSSM_ALGID_AES, 128, + 0 /* contextHandle */, + CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_ENCRYPT, + CSSM_KEYATTR_EXTRACTABLE, + NULL, NULL), "SecKeyGenerate"); + +#ifdef DEBUG + /* Wait for the add notification to get the generated aes_key to work + around SecKeyGenerate CFReleases the + returned key before returning it. */ + is_sec_event(kSecAddEvent, NULL, &aes_key, NULL, + "got add event for key"); +#endif + + uint32 btrue = 1; + SecKeychainAttribute sym_attrs[] = + { + { kSecKeyEncrypt, sizeof(btrue), &btrue } + }; + SecKeychainAttributeList sym_attr_list = + { sizeof(sym_attrs) / sizeof(*sym_attrs), sym_attrs }; + SecKeychainSearchRef search = NULL; + ok_status(SecKeychainSearchCreateFromAttributes(keychain, + CSSM_DL_DB_RECORD_SYMMETRIC_KEY, &sym_attr_list, &search), + "create symmetric encryption key search"); + SecKeychainItemRef item = NULL; + ok_status(SecKeychainSearchCopyNext(search, &item), "get first key"); + +#ifdef DEBUG + cmp_ok((intptr_t)aes_key, ==, (intptr_t)item, "is key found the right one?"); +#endif + + if (item) CFRelease(item); + is_status(SecKeychainSearchCopyNext(search, &item), + errSecItemNotFound, "copy next returns no more keys"); + CFRelease(search); + + ok_status(SecKeychainSearchCreateFromAttributes(keychain, + CSSM_DL_DB_RECORD_ANY, NULL, &search), + "create any item search"); + item = NULL; + TODO: { + todo(" Searching for CSSM_DL_DB_RECORD_ANY does not return " + "user-added symmetric keys"); + + ok_status(SecKeychainSearchCopyNext(search, &item), "get first key"); + +#ifdef DEBUG + cmp_ok((intptr_t)aes_key, ==, (intptr_t)item, "is key found the right one?"); +#endif + + } + if (item) CFRelease(item); + + is_status(SecKeychainSearchCopyNext(search, &item), + errSecItemNotFound, "copy next returns no more keys"); + CFRelease(search); + +#ifdef DEBUG + ok_status(SecKeychainItemDelete(aes_key), "delete key"); + is(CFGetRetainCount(aes_key), 2, "key retain count is 2"); +#endif + +#ifdef DEBUG + SecKeychainItemRef deleted_item = NULL; + is_sec_event(kSecDeleteEvent, NULL, &deleted_item, NULL, "got delete event for key"); + is((intptr_t)aes_key, (intptr_t)deleted_item, "key was the deleted item"); +#endif + + +#ifdef DEBUG + ok_status(test_sec_event_deregister(), "deregister for events"); +#endif + + SecKeyRef aes_key2 = NULL; + ok_status(SecKeyGenerate(keychain, CSSM_ALGID_AES, 128, + 0 /* contextHandle */, + CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_ENCRYPT, + CSSM_KEYATTR_EXTRACTABLE, + NULL, &aes_key2), "SecKeyGenerate and get key"); + + is(CFGetRetainCount(aes_key2), 1, "retain count is 1"); + CFRelease(aes_key2); + + + CFRelease(keychain); + + ok(tests_end(1), "cleanup"); +} + +int main(int argc, char *const *argv) +{ + int dont_skip = argc > 1 && !strcmp(argv[1], "-s"); + // plan_tests(21); + plan_tests(12); + + if (!tests_begin(argc, argv)) + BAIL_OUT("tests_begin failed"); + + tests(dont_skip); + + ok_leaks("no leaks"); + + return 0; +} diff --git a/SecurityTests/regressions/kc/kc-23-item-notify.c b/SecurityTests/regressions/kc/kc-23-item-notify.c new file mode 100755 index 00000000..34f54299 --- /dev/null +++ b/SecurityTests/regressions/kc/kc-23-item-notify.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include + +#include "testenv.h" +#include "testleaks.h" +#include "testmore.h" +#include "testsecevent.h" + +static char account[] = "account"; +static char service[] = "service"; +static char password[] = "password"; + +void tests(int dont_skip) +{ + SecKeychainRef keychain = NULL; + ok_status(SecKeychainCreate("test", 4, "test", FALSE, NULL, &keychain), + "create keychain"); + ok_status(test_sec_event_register(kSecEveryEventMask), + "register for all events"); + SecKeychainItemRef itemRef; + ok_status(SecKeychainAddGenericPassword(keychain, + sizeof(account), account, + sizeof(service), service, + sizeof(password), password, + &itemRef), + "add generic password, wait for callback"); + SecKeychainRef eventKeychain = NULL; + SecKeychainItemRef eventItem = NULL; + is_sec_event(kSecAddEvent, &eventKeychain, &eventItem, NULL, + "add event"); + is(eventItem, itemRef, "add event item matches"); + is(eventKeychain, keychain, "add event keychain matches"); + CFRelease(eventKeychain); + eventKeychain = NULL; + CFRelease(eventItem); + eventItem = NULL; + + ok_status(SecKeychainItemDelete(itemRef), "delete item"); + is_sec_event(kSecDeleteEvent, &eventKeychain, &eventItem, NULL, + "delete event"); + is(eventItem, itemRef, "delete event item matches"); + is(eventKeychain, keychain, "delete event keychain matches"); + if (eventKeychain != NULL) // eventKeychain can be null if the test times out + { + CFRelease(eventKeychain); + eventKeychain = NULL; + } + + if (eventItem != NULL) + { + CFRelease(eventItem); + eventItem = NULL; + } + + no_sec_event("no event"); + ok_status(test_sec_event_deregister(), "deregister events."); + + CFRelease(itemRef); + CFRelease(keychain); + + + ok(tests_end(1), "cleanup"); +} + +int main(int argc, char *const *argv) +{ +#ifdef DEBUG + int dont_skip = argc > 1 && !strcmp(argv[1], "-s"); + plan_tests(14); + + if (!tests_begin(argc, argv)) + BAIL_OUT("tests_begin failed"); + + tests(dont_skip); + ok_leaks("no leaks"); +#endif + plan_tests(1); + ok_leaks("no leaks"); + + return 0; +} diff --git a/SecurityTests/regressions/kc/kc-23-notify.c b/SecurityTests/regressions/kc/kc-23-notify.c new file mode 100755 index 00000000..06393663 --- /dev/null +++ b/SecurityTests/regressions/kc/kc-23-notify.c @@ -0,0 +1,99 @@ +#include +#include +#include +#include + +#include "testenv.h" +#include "testleaks.h" +#include "testmore.h" +#include "testsecevent.h" + +void tests(int dont_skip) +{ + SecKeychainRef keychain = NULL, default_keychain = NULL; + is_status(SecKeychainCopyDefault(&default_keychain), + errSecNoDefaultKeychain, "no default keychain"); + + ok_status(test_sec_event_register(kSecEveryEventMask), + "register for all events"); + ok_status(SecKeychainCreate("test", 4, "test", FALSE, NULL, &keychain), + "create keychain"); + is_sec_event(kSecKeychainListChangedEvent, NULL, NULL, NULL, + "list changed event"); + SecKeychainRef notKc = NULL; + + is_sec_event(kSecDefaultChangedEvent, ¬Kc, NULL, NULL, + "default changed event"); + + is((intptr_t)keychain, (intptr_t)notKc, + "keychain in notification is keychain"); + + no_sec_event("no event"); + + ok_status(SecKeychainCopyDefault(&default_keychain), + "get default keychain"); + is((intptr_t)default_keychain, (intptr_t)keychain, + "default kc is just created kc"); + if (default_keychain) + { + CFRelease(default_keychain); + default_keychain = NULL; + } + + SecKeychainRef keychain2; + ok_status(SecKeychainCreate("test2", 4, "test", FALSE, NULL, &keychain2), + "create keychain2"); + is_sec_event(kSecKeychainListChangedEvent, NULL, NULL, NULL, + "list changed event"); + no_sec_event("no event"); + + ok_status(SecKeychainCopyDefault(&default_keychain), + "get default keychain"); + + is((intptr_t)default_keychain, (intptr_t)keychain, + "default kc is first created kc"); + + if (default_keychain) + { + CFRelease(default_keychain); + default_keychain = NULL; + } + + ok_status(SecKeychainDelete(keychain), "delete default keychain"); + is_sec_event(kSecKeychainListChangedEvent, NULL, NULL, NULL, + "list changed event"); + + is_sec_event(kSecDefaultChangedEvent, NULL, NULL, NULL, + "default changed event"); + + no_sec_event("no event"); + CFRelease(keychain); + + ok_status(SecKeychainDelete(keychain2), "delete keychain2"); + CFRelease(keychain2); + is_sec_event(kSecKeychainListChangedEvent, NULL, NULL, NULL, + "list changed event"); + no_sec_event("no event"); + + ok_status(test_sec_event_deregister(), "deregister events."); + + + ok(tests_end(1), "cleanup"); +} + +int main(int argc, char *const *argv) +{ +#ifdef DEBUG + int dont_skip = argc > 1 && !strcmp(argv[1], "-s"); + plan_tests(24); + + if (!tests_begin(argc, argv)) + BAIL_OUT("tests_begin failed"); + + tests(dont_skip); +#endif + plan_tests(1); + ok_leaks("no leaks"); + + return 0; +} diff --git a/SecurityTests/regressions/kc/kc-24-login.c b/SecurityTests/regressions/kc/kc-24-login.c new file mode 100755 index 00000000..e30a067b --- /dev/null +++ b/SecurityTests/regressions/kc/kc-24-login.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include + +#include "testenv.h" +#include "testleaks.h" +#include "testmore.h" +#include "testsecevent.h" + +void tests(int dont_skip) +{ + const char *user = getenv("USER"); + ok((user != NULL && strlen(user) != 0), "USER must be non-nil and non-zero length"); + fprintf(stdout, "Testing login for user \"%s\"\n", user); + + ok_status(test_sec_event_register(kSecEveryEventMask), + "register for all events"); + + // test SecKeychainLogin for $USER with password "test" + ok_status(SecKeychainLogin(strlen(user), user, 4, "test"), "login user"); + + // wait for a list changed event + is_sec_event(kSecKeychainListChangedEvent, NULL, NULL, NULL, + "list changed event"); + no_sec_event("no event"); + + // get the default keychain (should be login.keychain if none is explicitly set) + SecKeychainRef default_keychain = NULL; + ok_status(SecKeychainCopyDefault(&default_keychain), "get default"); + + // test status of default keychain (should be read/write and unlocked) + SecKeychainStatus status = 0; + ok_status(SecKeychainGetStatus(default_keychain, &status), "get status"); + is(status, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus, + "default should be read/write/unlocked"); + + // get the path for the default keychain + char path[1024]; + UInt32 path_len = sizeof(path) - 1; + ok_status(SecKeychainGetPath(default_keychain, &path_len, path), + "get path"); + fprintf(stdout, "Default keychain path is %s\n", path); + path[path_len] = 0; + const char *login_path = "Library/Keychains/login.keychain"; + cmp_ok(path_len, >, strlen(login_path), "path len is enough"); + eq_string(path + path_len - strlen(login_path), login_path, "check path"); + + // check retain count on default keychain (why??) + is(CFGetRetainCount(default_keychain), 1, "default retain count is 1"); + CFRelease(default_keychain); + default_keychain = NULL; + + // lock and unlock events have been removed because they can't be made reliable + + ok_status(test_sec_event_deregister(), "deregister events."); + + // rename login.keychain to $USER to simulate a Panther-style keychain + char testuser_path[1024]; + sprintf(testuser_path, "Library/Keychains/%s", user); + ok_unix(rename(login_path, testuser_path), + "rename login.keychain to $USER"); + + // login and verify that SecKeychainLogin cleans up the $USER keychain + // (either by renaming to $USER.keychain, or renaming to login.keychain) + ok_status(SecKeychainLogin(strlen(user), user, 4, "test"), "login again"); + + // get the default keychain (should be login.keychain if none is explicitly set) + ok_status(SecKeychainCopyDefault(&default_keychain), "get default"); + path_len = sizeof(path) - 1; + ok_status(SecKeychainGetPath(default_keychain, &path_len, path), + "get path"); + path[path_len] = 0; + cmp_ok(path_len, >, strlen(testuser_path), "path len is enough"); + + // lock the default keychain + ok_status(SecKeychainLock(default_keychain), "lock default"); + CFRelease(default_keychain); + + ok(tests_end(1), "cleanup"); +} + +int main(int argc, char *const *argv) +{ + int dont_skip = argc > 1 && !strcmp(argv[1], "-s"); + plan_tests(21); + + if (!tests_begin(argc, argv)) + BAIL_OUT("tests_begin failed"); + + tests(dont_skip); + ok_leaks("no leaks"); + + return 0; +} diff --git a/SecurityTests/regressions/kc/kc-25-bulk-notify.c b/SecurityTests/regressions/kc/kc-25-bulk-notify.c new file mode 100755 index 00000000..e7562428 --- /dev/null +++ b/SecurityTests/regressions/kc/kc-25-bulk-notify.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include + +#include "testenv.h" +#include "testleaks.h" +#include "testmore.h" +#include "testsecevent.h" + +void tests(void) +{ + SecKeychainRef keychain = NULL; + ok_status(SecKeychainCreate("test", 4, "test", FALSE, NULL, &keychain), + "create keychain"); + ok_status(test_sec_event_register(kSecEveryEventMask), + "register for all events"); + int item_num; + int item_count = 9; + for (item_num = 0; item_num < item_count; ++item_num) + { + char account[64]; + sprintf(account, "account-%d", item_num); + ok_status(SecKeychainAddGenericPassword(keychain, 7, "service", + strlen(account), account, 4, "test", NULL), + "add generic password"); + } + SecKeychainAttribute attrs[] = + { { kSecAccountItemAttr } }; + SecKeychainAttributeList attrList = + { sizeof(attrs) / sizeof(*attrs), attrs }; + + for (item_num = 0; item_num < item_count - 2; ++item_num) + { + char account[64]; + sprintf(account, "account-%d", item_num); + SecKeychainItemRef item = NULL; + is_sec_event(kSecAddEvent, NULL, &item, NULL, "got add event"); + + SKIP: { + skip("no item", 3, item != NULL); + + ok_status(SecKeychainItemCopyContent(item, NULL, &attrList, NULL, + NULL), "get content"); + + eq_stringn(account, strlen(account), attrs[0].data, attrs[0].length, + "account name in notification matches"); + ok_status(SecKeychainItemFreeContent(&attrList, NULL), + "free content"); + } + } + + for (; item_num < item_count; ++item_num) + { + char account[64]; + sprintf(account, "account-%d", item_num); + SecKeychainItemRef item = NULL; + is_sec_event(kSecAddEvent, NULL, &item, NULL, "got add event"); + + SKIP: { + skip("no item", 3, item != NULL); + + ok_status(SecKeychainItemCopyContent(item, NULL, &attrList, NULL, + NULL), "get content"); + eq_stringn(account, strlen(account), attrs[0].data, attrs[0].length, + "account name in notification matches"); + ok_status(SecKeychainItemFreeContent(&attrList, NULL), + "free content"); + } + } + + ok(tests_end(1), "cleanup"); +} + +int main(int argc, char *const *argv) +{ +#ifdef DEBUG + plan_tests(49); + + if (!tests_begin(argc, argv)) + BAIL_OUT("tests_begin failed"); + + tests(); + ok_leaks("no leaks"); +#endif + plan_tests(1); + ok_leaks("no leaks"); + + return 0; +} diff --git a/SecurityTests/regressions/kc/kc-26-is-valid.c b/SecurityTests/regressions/kc/kc-26-is-valid.c new file mode 100755 index 00000000..d17b05a2 --- /dev/null +++ b/SecurityTests/regressions/kc/kc-26-is-valid.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "testmore.h" +#include "testenv.h" +#include "testleaks.h" + +static void tests(void) +{ + char *home = getenv("HOME"); + char kcname1[256], kcname2[256]; + + if (!home || strlen(home) > 200) + plan_skip_all("home too big"); + + sprintf(kcname1, "%s/kc1", home); + SecKeychainRef kc1 = NULL, kc2 = NULL; + Boolean kc1valid, kc2valid; + ok_status(SecKeychainCreate(kcname1, 4, "test", FALSE, NULL, &kc1), + "SecKeychainCreate kc1"); + ok_status(SecKeychainIsValid(kc1, &kc1valid), "SecKeychainIsValid kc1"); + is(kc1valid, TRUE, "is kc1 valid"); + CFRelease(kc1); + + int fd; + sprintf(kcname2, "%s/kc2", home); + ok_unix(fd = open(kcname2, O_CREAT|O_WRONLY|O_TRUNC, 0600), + "create invalid kc2 file"); + ok_unix(close(fd), "close the kc2 file"); + ok_status(SecKeychainOpen(kcname2, &kc2), "SecKeychainOpen kc2"); + + ok_status(SecKeychainIsValid(kc2, &kc2valid), "SecKeychainIsValid kc2"); + TODO: { + todo(" SecKeychainIsValid always returns " + "TRUE"); + is(kc2valid, FALSE, "is kc2 not valid"); + } + CFRelease(kc2); + + tests_end(1); +} + +int main(int argc, char *const *argv) +{ + plan_tests(9); + if (!tests_begin(argc, argv)) + BAIL_OUT("tests_begin failed"); + + tests(); + + ok_leaks("leaks"); + + return 0; +} diff --git a/SecurityTests/regressions/kc/kc-30-trust.c b/SecurityTests/regressions/kc/kc-30-trust.c new file mode 100755 index 00000000..7582c009 --- /dev/null +++ b/SecurityTests/regressions/kc/kc-30-trust.c @@ -0,0 +1,25 @@ +#include + +#include "testmore.h" +#include "testleaks.h" + +static void tests(void) +{ + SecTrustRef trust = NULL; + + ok_status(SecTrustCreateWithCertificates(NULL, NULL, &trust), + "create empty trust"); + ok(trust, "trust not NULL"); + CFRelease(trust); +} + +int main(int argc, char *const *argv) +{ + plan_tests(3); + + tests(); + + ok_leaks("leaks"); + + return 0; +} diff --git a/SecurityTests/regressions/kc/kc-40-item-change-label2.m b/SecurityTests/regressions/kc/kc-40-item-change-label2.m new file mode 100755 index 00000000..67cb9229 --- /dev/null +++ b/SecurityTests/regressions/kc/kc-40-item-change-label2.m @@ -0,0 +1,351 @@ +// +// keychain_test.m +// Keychain item access control example +// +// Created by Perry Kiehtreiber on Wed Jun 19 2002 +// Modified by Ken McLeod, Mon Apr 21 2003 -- added "always allow" ACL support +// Wed Jul 28 2004 -- add test code for persistent ref SPI +// Mon Aug 02 2004 -- add test code to change label attributes +// +// To build and run this example: +// cc -framework Security -framework Foundation keychain_test.m ; ./a.out +// +// Copyright (c) 2003-2005,2007 Apple Inc. All Rights Reserved. +// + +#define TEST_PERSISTENT_REFS 0 +#define USE_SYSTEM_KEYCHAIN 0 + + +#import + +#include +#include +#include +#include +#include +#include +#include +#include + +#import "testmore.h" +#import "testenv.h" +#import "testleaks.h" + +void renameItemViaModifyAttributesAndData(SecKeychainItemRef item) +{ + const char *labelSuffix = " [MAD]"; + + // get the item's label attribute (allocated for us by + // SecKeychainItemCopyAttributesAndData, must free later...) + UInt32 itemTags[] = { kSecLabelItemAttr }; + UInt32 itemFmts[] = { CSSM_DB_ATTRIBUTE_FORMAT_STRING }; + SecKeychainAttributeInfo attrInfo = { 1, itemTags, itemFmts }; + SecKeychainAttributeList *attrList = NULL; + SecItemClass itemClass; + + ok_status(SecKeychainItemCopyAttributesAndData(item, &attrInfo, &itemClass, &attrList, NULL, NULL), + "get label attribute"); + + ok(attrList && attrList->count == 1, "check that exactly one attribute was returned"); + + // malloc enough space to hold our new label string + // (length = old label string + suffix string + terminating NULL) + CFIndex newLen = attrList->attr[0].length + strlen(labelSuffix); + char *p = (char*) malloc(newLen); + memcpy(p, attrList->attr[0].data, attrList->attr[0].length); + memcpy(p + attrList->attr[0].length, labelSuffix, strlen(labelSuffix)); + + // set up the attribute we want to change with its new value + SecKeychainAttribute newAttrs[] = { { kSecLabelItemAttr, newLen, p } }; + SecKeychainAttributeList newAttrList = + { sizeof(newAttrs) / sizeof(newAttrs[0]), newAttrs }; + + // modify the attribute + ok_status(SecKeychainItemModifyAttributesAndData(item, &newAttrList, 0, NULL), + "SecKeychainItemModifyAttributesAndData"); + + // free the memory we allocated for the new label string + free(p); + + // free the attrList which was allocated by SecKeychainItemCopyAttributesAndData + ok_status(SecKeychainItemFreeAttributesAndData(attrList, NULL), + "SecKeychainItemFreeAttributesAndData"); +} + +void renameItemViaModifyContent(SecKeychainItemRef item) +{ + const char *labelSuffix = " [MC]"; + + // get the item's label attribute (allocated for us by + // SecKeychainItemCopyContent, must free later...) + SecKeychainAttribute itemAttrs[] = { { kSecLabelItemAttr, 0, NULL } }; + SecKeychainAttributeList itemAttrList = + { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs }; + + ok_status(SecKeychainItemCopyContent(item, NULL, &itemAttrList, + NULL, NULL), "get label"); + + ok(itemAttrs[0].data != NULL, "check that attribute data was returned"); + + // malloc enough space to hold our new label string + // (length = old label string + suffix string + terminating NULL) + CFIndex newLen = itemAttrs[0].length + strlen(labelSuffix); + char *p = (char*) malloc(newLen); + memcpy(p, itemAttrs[0].data, itemAttrs[0].length); + memcpy(p + itemAttrs[0].length, labelSuffix, strlen(labelSuffix)); + + // set up the attribute we want to change with its new value + SecKeychainAttribute newAttrs[] = { { kSecLabelItemAttr, newLen, p } }; + SecKeychainAttributeList newAttrList = + { sizeof(newAttrs) / sizeof(newAttrs[0]), newAttrs }; + + // modify the attribute + ok_status(SecKeychainItemModifyContent(item, &newAttrList, + 0, NULL), "modify label"); + + // free the memory we allocated for the new label string + free(p); + + // free the memory in the itemAttrList structure which was + // allocated by SecKeychainItemCopyContent + ok_status(SecKeychainItemFreeContent(&itemAttrList, NULL), + "SecKeychainItemFreeContent"); +} + +void testRenameItemLabels(SecKeychainRef keychain) +{ + // Find each generic password item in the given keychain whose label + // is "sample service", and modify the existing label attribute + // by adding a " [label]" suffix. + + const char *searchString = "sample service"; + + SecKeychainSearchRef searchRef = nil; + SecKeychainAttribute sAttrs[] = + { { kSecServiceItemAttr, strlen(searchString), (char*)searchString } }; + SecKeychainAttributeList sAttrList = + { sizeof(sAttrs) / sizeof(sAttrs[0]), sAttrs }; + ok_status(SecKeychainSearchCreateFromAttributes(keychain, + kSecGenericPasswordItemClass, &sAttrList, &searchRef), + "SecKeychainSearchCreateFromAttributes"); + + SecKeychainItemRef foundItemRef = NULL; + int count; + for (count = 0; count < 2; ++count) + { + ok_status(SecKeychainSearchCopyNext(searchRef, &foundItemRef), + "SecKeychainSearchCopyNext"); + + renameItemViaModifyAttributesAndData(foundItemRef); // 4 + renameItemViaModifyContent(foundItemRef); // 4 + + if (foundItemRef) + CFRelease(foundItemRef); + } + + is_status(SecKeychainSearchCopyNext(searchRef, &foundItemRef), + errSecItemNotFound, "SecKeychainSearchCopyNext at end"); + + if (searchRef) CFRelease(searchRef); +} + +SecAccessRef createAccess(NSString *accessLabel, BOOL allowAny) +{ + SecAccessRef access=nil; + NSArray *trustedApplications=nil; + + if (!allowAny) // use default access ("confirm access") + { + // make an exception list of applications you want to trust, which + // are allowed to access the item without requiring user confirmation + SecTrustedApplicationRef myself, someOther; + ok_status(SecTrustedApplicationCreateFromPath(NULL, &myself), + "create trusted app for self"); + ok_status(SecTrustedApplicationCreateFromPath("/Applications/Mail.app", + &someOther), "create trusted app for Mail.app"); + trustedApplications = [NSArray arrayWithObjects:(id)myself, + (id)someOther, nil]; + CFRelease(myself); + CFRelease(someOther); + } + + ok_status(SecAccessCreate((CFStringRef)accessLabel, + (CFArrayRef)trustedApplications, &access), "SecAccessCreate"); + + if (allowAny) + { + // change access to be wide-open for decryption ("always allow access") + // get the access control list for decryption operations + CFArrayRef aclList=nil; + ok_status(SecAccessCopySelectedACLList(access, + CSSM_ACL_AUTHORIZATION_DECRYPT, &aclList), + "SecAccessCopySelectedACLList"); + + // get the first entry in the access control list + SecACLRef aclRef=(SecACLRef)CFArrayGetValueAtIndex(aclList, 0); + CFArrayRef appList=nil; + CFStringRef promptDescription=nil; + CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector; + ok_status(SecACLCopySimpleContents(aclRef, &appList, + &promptDescription, &promptSelector), "SecACLCopySimpleContents"); + + // modify the default ACL to not require the passphrase, and have a + // nil application list + promptSelector.flags &= ~CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE; + ok_status(SecACLSetSimpleContents(aclRef, NULL, promptDescription, + &promptSelector), "SecACLSetSimpleContents"); + + if (appList) CFRelease(appList); + if (promptDescription) CFRelease(promptDescription); + if (aclList) CFRelease(aclList); + } + + return access; +} + +void addApplicationPassword(SecKeychainRef keychain, NSString *password, + NSString *account, NSString *service, BOOL allowAny, SecKeychainItemRef *outItem) +{ + SecKeychainItemRef item = nil; + const char *serviceUTF8 = [service UTF8String]; + const char *accountUTF8 = [account UTF8String]; + const char *passwordUTF8 = [password UTF8String]; + // use the service string as the name of this item for display purposes + NSString *itemLabel = service; + const char *itemLabelUTF8 = [itemLabel UTF8String]; + +#if USE_SYSTEM_KEYCHAIN + const char *sysKeychainPath = "/Library/Keychains/System.keychain"; + status = SecKeychainOpen(sysKeychainPath, &keychain); + if (status) { NSLog(@"SecKeychainOpen returned %d", status); return; } + status = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem); + if (status) { NSLog(@"SecKeychainSetPreferenceDomain returned %d", status); return; } +#endif + + // create initial access control settings for the item + SecAccessRef access = createAccess(itemLabel, allowAny); + + // Below is the lower-layer equivalent to the + // SecKeychainAddGenericPassword() function; it does the same thing + // (except specify the access controls) set up attribute vector + // (each attribute consists of {tag, length, pointer}) + SecKeychainAttribute attrs[] = { + { kSecLabelItemAttr, strlen(itemLabelUTF8), (char *)itemLabelUTF8 }, + { kSecAccountItemAttr, strlen(accountUTF8), (char *)accountUTF8 }, + { kSecServiceItemAttr, strlen(serviceUTF8), (char *)serviceUTF8 } + }; + SecKeychainAttributeList attributes = + { sizeof(attrs) / sizeof(attrs[0]), attrs }; + + ok_status(SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass, + &attributes, strlen(passwordUTF8), passwordUTF8, keychain, access, + &item), "SecKeychainItemCreateFromContent"); + + if (access) CFRelease(access); + + if (outItem) { + *outItem = item; + } else if (item) { + CFRelease(item); + } +} + +// 1 +void addInternetPassword(SecKeychainRef keychain, NSString *password, + NSString *account, NSString *server, NSString *path, + SecProtocolType protocol, int port, BOOL allowAny, SecKeychainItemRef *outItem) +{ + SecKeychainItemRef item = nil; + const char *pathUTF8 = [path UTF8String]; + const char *serverUTF8 = [server UTF8String]; + const char *accountUTF8 = [account UTF8String]; + const char *passwordUTF8 = [password UTF8String]; + // use the server string as the name of this item for display purposes + NSString *itemLabel = server; + const char *itemLabelUTF8 = [itemLabel UTF8String]; + +#if USE_SYSTEM_KEYCHAIN + const char *sysKeychainPath = "/Library/Keychains/System.keychain"; + status = SecKeychainOpen(sysKeychainPath, &keychain); + if (status) { NSLog(@"SecKeychainOpen returned %d", status); return 1; } + status = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem); + if (status) { NSLog(@"SecKeychainSetPreferenceDomain returned %d", status); return 1; } +#endif + + // create initial access control settings for the item + SecAccessRef access = createAccess(itemLabel, allowAny); + + // below is the lower-layer equivalent to the + // SecKeychainAddInternetPassword() function; it does the same + // thing (except specify the access controls) set up attribute + // vector (each attribute consists of {tag, length, pointer}) + SecKeychainAttribute attrs[] = { + { kSecLabelItemAttr, strlen(itemLabelUTF8), (char *)itemLabelUTF8 }, + { kSecAccountItemAttr, strlen(accountUTF8), (char *)accountUTF8 }, + { kSecServerItemAttr, strlen(serverUTF8), (char *)serverUTF8 }, + { kSecPortItemAttr, sizeof(int), (int *)&port }, + { kSecProtocolItemAttr, sizeof(SecProtocolType), + (SecProtocolType *)&protocol }, + { kSecPathItemAttr, strlen(pathUTF8), (char *)pathUTF8 } + }; + SecKeychainAttributeList attributes = + { sizeof(attrs) / sizeof(attrs[0]), attrs }; + + ok_status(SecKeychainItemCreateFromContent(kSecInternetPasswordItemClass, + &attributes, strlen(passwordUTF8), passwordUTF8, keychain, access, + &item), "SecKeychainItemCreateFromContent"); + + if (access) CFRelease(access); + + if (outItem) { + *outItem = item; + } else if (item) { + CFRelease(item); + } +} + +void tests(void) +{ + SecKeychainRef keychain = NULL; + ok_status(SecKeychainCreate("login.keychain", 4, "test", NO, NULL, + &keychain), "SecKeychainCreate"); + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + // add some example passwords to the keychain + addApplicationPassword(keychain, @"sample password", + @"sample account", @"sample service", NO, NULL); + addApplicationPassword(keychain, @"sample password", + @"different account", @"sample service", NO, NULL); + addApplicationPassword(keychain, @"sample password", + @"sample account", @"sample unprotected service", YES, NULL); + addInternetPassword(keychain, @"sample password", + @"sample account", @"samplehost.apple.com", + @"cgi-bin/bogus/testpath", kSecProtocolTypeHTTP, 8080, NO, NULL); + + // test searching and changing item label attributes + testRenameItemLabels(keychain); + + [pool release]; + + SKIP: { + skip("no keychain", 1, keychain); + ok_status(SecKeychainDelete(keychain), "SecKeychainDelete"); + CFRelease(keychain); + } + + tests_end(1); +} + +int main(int argc, char * const *argv) +{ + plan_tests(40); + tests_begin(argc, argv); + + tests(); + + ok_leaks("leaks"); + + return 0; +} diff --git a/SecurityTests/regressions/kc/kc-46-dl-add-certificate.c b/SecurityTests/regressions/kc/kc-46-dl-add-certificate.c new file mode 100644 index 00000000..82008581 --- /dev/null +++ b/SecurityTests/regressions/kc/kc-46-dl-add-certificate.c @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2005-2007,2009,2011 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@ + * + * 01DL_CreateReleation.c + */ + +#include +#include +#include +#include +#include + +#include "testmore.h" +#include "testenv.h" +#include "testcssm.h" + +/* Cert File Name: keybank_v3.101.cer */ +static const uint8 keybank_der_bytes[] = +{ + 0x30, 0x82, 0x03, 0x86, 0x30, 0x82, 0x02, 0xef, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x78, + 0xee, 0x48, 0xde, 0x18, 0x5b, 0x20, 0x71, 0xc9, + 0xc9, 0xc3, 0xb5, 0x1d, 0x7b, 0xdd, 0xc1, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x5f, + 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, 0x37, + 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, + 0x2e, 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, 0x30, + 0x1e, 0x17, 0x0d, 0x39, 0x37, 0x30, 0x34, 0x31, + 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, + 0x17, 0x0d, 0x31, 0x31, 0x31, 0x30, 0x32, 0x34, + 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, + 0x81, 0xba, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x04, 0x0a, 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, 0x17, 0x30, 0x15, 0x06, + 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0e, 0x56, 0x65, + 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, + 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x33, 0x30, 0x31, + 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, + 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x20, 0x43, 0x41, 0x20, + 0x2d, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, + 0x33, 0x31, 0x49, 0x30, 0x47, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x13, 0x40, 0x77, 0x77, 0x77, 0x2e, + 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, + 0x20, 0x49, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x62, 0x79, 0x20, 0x52, 0x65, 0x66, 0x2e, 0x20, + 0x4c, 0x49, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, + 0x59, 0x20, 0x4c, 0x54, 0x44, 0x2e, 0x28, 0x63, + 0x29, 0x39, 0x37, 0x20, 0x56, 0x65, 0x72, 0x69, + 0x53, 0x69, 0x67, 0x6e, 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, 0xd8, 0x82, 0x80, 0xe8, 0xd6, 0x19, 0x02, + 0x7d, 0x1f, 0x85, 0x18, 0x39, 0x25, 0xa2, 0x65, + 0x2b, 0xe1, 0xbf, 0xd4, 0x05, 0xd3, 0xbc, 0xe6, + 0x36, 0x3b, 0xaa, 0xf0, 0x4c, 0x6c, 0x5b, 0xb6, + 0xe7, 0xaa, 0x3c, 0x73, 0x45, 0x55, 0xb2, 0xf1, + 0xbd, 0xea, 0x97, 0x42, 0xed, 0x9a, 0x34, 0x0a, + 0x15, 0xd4, 0xa9, 0x5c, 0xf5, 0x40, 0x25, 0xdd, + 0xd9, 0x07, 0xc1, 0x32, 0xb2, 0x75, 0x6c, 0xc4, + 0xca, 0xbb, 0xa3, 0xfe, 0x56, 0x27, 0x71, 0x43, + 0xaa, 0x63, 0xf5, 0x30, 0x3e, 0x93, 0x28, 0xe5, + 0xfa, 0xf1, 0x09, 0x3b, 0xf3, 0xb7, 0x4d, 0x4e, + 0x39, 0xf7, 0x5c, 0x49, 0x5a, 0xb8, 0xc1, 0x1d, + 0xd3, 0xb2, 0x8a, 0xfe, 0x70, 0x30, 0x95, 0x42, + 0xcb, 0xfe, 0x2b, 0x51, 0x8b, 0x5a, 0x3c, 0x3a, + 0xf9, 0x22, 0x4f, 0x90, 0xb2, 0x02, 0xa7, 0x53, + 0x9c, 0x4f, 0x34, 0xe7, 0xab, 0x04, 0xb2, 0x7b, + 0x6f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, + 0xe6, 0x30, 0x81, 0xe3, 0x30, 0x0f, 0x06, 0x03, + 0x55, 0x1d, 0x13, 0x04, 0x08, 0x30, 0x06, 0x01, + 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x44, 0x06, + 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3d, 0x30, 0x3b, + 0x30, 0x39, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, + 0x86, 0xf8, 0x45, 0x01, 0x07, 0x01, 0x01, 0x30, + 0x2a, 0x30, 0x28, 0x06, 0x08, 0x2b, 0x06, 0x01, + 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1c, 0x68, + 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, + 0x77, 0x77, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, + 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x43, 0x50, 0x53, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x1d, 0x1f, 0x04, 0x2d, 0x30, 0x2b, 0x30, 0x29, + 0xa0, 0x27, 0xa0, 0x25, 0x86, 0x23, 0x68, 0x74, + 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, + 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, + 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x63, + 0x61, 0x33, 0x2d, 0x67, 0x32, 0x2e, 0x63, 0x72, + 0x6c, 0x30, 0x34, 0x06, 0x03, 0x55, 0x1d, 0x25, + 0x04, 0x2d, 0x30, 0x2b, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, + 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, + 0x42, 0x04, 0x01, 0x06, 0x0a, 0x60, 0x86, 0x48, + 0x01, 0x86, 0xf8, 0x45, 0x01, 0x08, 0x01, 0x30, + 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, + 0x03, 0x02, 0x01, 0x06, 0x30, 0x11, 0x06, 0x09, + 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, + 0x01, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, + 0x81, 0x00, 0x23, 0x5d, 0xee, 0xa6, 0x24, 0x05, + 0xfd, 0x76, 0xd3, 0x6a, 0x1a, 0xd6, 0xba, 0x46, + 0x06, 0xaa, 0x6a, 0x0f, 0x03, 0x90, 0x66, 0xb2, + 0xb0, 0xa6, 0xc2, 0x9e, 0xc9, 0x1e, 0xa3, 0x55, + 0x53, 0xaf, 0x3e, 0x45, 0xfd, 0xdc, 0x8c, 0x27, + 0xdd, 0x53, 0x38, 0x09, 0xbb, 0x7c, 0x4b, 0x2b, + 0xba, 0x95, 0x4a, 0xfe, 0x70, 0x4e, 0x1b, 0x69, + 0xd6, 0x3c, 0xf7, 0x4f, 0x07, 0xc5, 0xf2, 0x17, + 0x5a, 0x4c, 0xa2, 0x8f, 0xac, 0x0b, 0x8a, 0x06, + 0xdb, 0xb9, 0xd4, 0x6b, 0xc5, 0x1d, 0x58, 0xda, + 0x17, 0x52, 0xe3, 0x21, 0xf1, 0xd2, 0xd7, 0x5a, + 0xd5, 0xe5, 0xab, 0x59, 0x7b, 0x21, 0x7a, 0x86, + 0x6a, 0xd4, 0xfe, 0x17, 0x11, 0x3a, 0x53, 0x0d, + 0x9c, 0x60, 0xa0, 0x4a, 0xd9, 0x5e, 0xe4, 0x1d, + 0x0c, 0x29, 0xaa, 0x13, 0x07, 0x65, 0x86, 0x1f, + 0xbf, 0xb4, 0xc9, 0x82, 0x53, 0x9c, 0x2c, 0x02, + 0x8f, 0x23 +}; +static const CSSM_DATA keybank_der = +{ + sizeof(keybank_der_bytes), + (uint8 *)keybank_der_bytes +}; + +static void +certTests(SecKeychainRef keychain) +{ + SecCertificateRef certificate = NULL; + ok_status(SecCertificateCreateFromData(&keybank_der, + CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &certificate), + "SecCertificateCreateFromData"); + ok(certificate, "certificate non NULL"); + ok_status(SecCertificateAddToKeychain(certificate, keychain), + "SecCertificateAddToKeychain fails unless 4039735 is fixed"); + + is_status(SecCertificateAddToKeychain(certificate, keychain), + errSecDuplicateItem, "SecCertificateAddToKeychain twice"); + + SecCertificateRef certificate2 = NULL; + ok_status(SecCertificateCreateFromData(&keybank_der, + CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &certificate2), + "SecCertificateCreateFromData"); + is_status(SecCertificateAddToKeychain(certificate2, keychain), + errSecDuplicateItem, "SecCertificateAddToKeychain twice"); + is(CFGetRetainCount(certificate2), 1, "certificate2 retain count is 1"); // 1 because the above test fails, therefore it's not owned by a keychain + CFRelease(certificate2); + + SecKeychainRef certKeychain = NULL; + ok_status(SecKeychainItemCopyKeychain((SecKeychainItemRef)certificate, + &certKeychain), "SecKeychainItemCopyKeychain"); + is((intptr_t)keychain, (intptr_t)certKeychain, "cert's keychain is keychain"); + CFRelease(certKeychain); + + is(CFGetRetainCount(certificate), 1, "certificate retain count is 1"); + CFRelease(certificate); + + ok_status(SecKeychainDelete(keychain), "SecKeychainDelete"); + is(CFGetRetainCount(keychain), 1, "keychain retain count is 1"); + CFRelease(keychain); +} + +CSSM_DBINFO dbInfo = +{ + 0 /* NumberOfRecordTypes */, + NULL, + NULL, + NULL, + CSSM_TRUE /* IsLocal */, + NULL, /* AccessPath - URL, dir path, etc. */ + NULL /* reserved */ +}; + +int +main(int argc, char * const *argv) +{ + int guid_alt = argc > 1 && !strcmp(argv[1], "-g"); + /* {2cb56191-ee6f-432d-a377-853d3c6b949e} */ + CSSM_GUID s3dl_guid = + { + 0x2cb56191, 0xee6f, 0x432d, + { 0xa3, 0x77, 0x85, 0x3d, 0x3c, 0x6b, 0x94, 0x9e } + }; + const CSSM_GUID *guid = guid_alt ? & s3dl_guid : &gGuidAppleFileDL; + + plan_tests(18); + + CSSM_DL_DB_HANDLE dldb = {}; + ok(cssm_attach(guid, &dldb.DLHandle), "cssm_attach"); + + if (!tests_begin(argc, argv)) + return 255; + + const char *dbname = "test.keychain"; + ok_status(CSSM_DL_DbCreate(dldb.DLHandle, dbname, NULL /* DbLocation */, + &dbInfo, + CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, + NULL /* CredAndAclEntry */, + NULL /* &openParameters */, + &dldb.DBHandle), + "CSSM_DL_DbCreate pure dl"); + ok_status(CSSM_DL_DbClose(dldb), "close db"); + ok(cssm_detach(guid, dldb.DLHandle), "cssm_detach"); + + SecKeychainRef keychain = NULL; + ok_status(SecKeychainOpenWithGuid(guid, 0, CSSM_SERVICE_DL, dbname, + NULL, &keychain), "Open pure dl keychain"); + ok(keychain, "keychain non NULL"); + + certTests(keychain); + + return !tests_end(1); +} diff --git a/SecurityTests/regressions/kc/kc-50-iPhone-emulation.c b/SecurityTests/regressions/kc/kc-50-iPhone-emulation.c new file mode 100644 index 00000000..f553148d --- /dev/null +++ b/SecurityTests/regressions/kc/kc-50-iPhone-emulation.c @@ -0,0 +1,325 @@ +#include +#include +#include +#include +#include +#include + +#include "testmore.h" +#include "testenv.h" +#include "testcssm.h" +#include "testleaks.h" + + +void AddKeyCFTypePairToDictionary(CFMutableDictionaryRef mdr, CFTypeRef key, CFTypeRef value) +{ + CFDictionaryAddValue(mdr, key, value); +} + + + +void AddKeyNumberPairToDictionary(CFMutableDictionaryRef mdr, CFTypeRef key, uint32 value) +{ + // make a CFNumber out of the value + CFNumberRef number = CFNumberCreate(NULL, kCFNumberSInt32Type, &value); + CFDictionaryAddValue(mdr, key, number); + CFRelease(number); +} + + + +void AddKeyStringPairToDictionary(CFMutableDictionaryRef mdr, CFTypeRef key, const char* string) +{ + // We add the string as a CFData + CFDataRef data = CFDataCreate(NULL, (const UInt8*) string, strlen(string)); + CFDictionaryAddValue(mdr, key, data); + CFRelease(data); +} + + + +int SignVerifyTest() +{ + CFMutableDictionaryRef parameters; + SecKeyRef publicKey, privateKey; + + // start out with an empty dictionary and see if it returns an error + parameters = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + OSStatus result = SecKeyGeneratePair(parameters, &publicKey, &privateKey); + + ok(result != noErr, "result is noErr"); + + // add the algorithm type + AddKeyCFTypePairToDictionary(parameters, kSecAttrKeyType, kSecAttrKeyTypeRSA); + + // see if we can get a 2048 bit keypair + AddKeyNumberPairToDictionary(parameters, kSecAttrKeySizeInBits, 2048); + + // put an application tag on the key + AddKeyStringPairToDictionary(parameters, kSecAttrApplicationTag, "This is a test."); + + // try again + result = SecKeyGeneratePair(parameters, &publicKey, &privateKey); + ok_status(result, "SecKeyGeneratePair"); + if (result != noErr) + { + return 1; + } + + // Make a chunk of data + char data[] = "This is a test of some data. Ain't it grand?"; + + SecPadding paddings[] = {kSecPaddingNone, kSecPaddingPKCS1, kSecPaddingPKCS1MD2, kSecPaddingPKCS1MD5, kSecPaddingPKCS1SHA1}; + const int numberOfPaddings = sizeof(paddings) / sizeof (SecPadding); + + // test each padding mode + int n; + for (n = 0; n < numberOfPaddings; ++n) + { + // sign that data with the private key + uint8 signature[512]; + size_t signatureLength = sizeof(signature); + + result = SecKeyRawSign(privateKey, paddings[n], (uint8_t*) data, strlen(data), signature, &signatureLength); + ok_status(result, "SecKeyRawSign"); + + // verify with the signature + result = SecKeyRawVerify(publicKey, paddings[n], (uint8_t*) data, strlen(data), signature, signatureLength); + ok_status(result, "SecKeyRawVerify"); + } + + // clean up + SecKeychainItemDelete((SecKeychainItemRef) publicKey); + SecKeychainItemDelete((SecKeychainItemRef) privateKey); + + CFRelease(publicKey); + CFRelease(privateKey); + CFRelease(parameters); + + return 0; +} + +int SignVerifyWithAsyncTest() +{ + CFMutableDictionaryRef parameters; + __block SecKeyRef publicKey, privateKey; + + // start out with an empty dictionary and see if it returns an error + parameters = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + OSStatus result = SecKeyGeneratePair(parameters, &publicKey, &privateKey); + dispatch_group_t everyone_called = dispatch_group_create(); + + dispatch_group_enter(everyone_called); + SecKeyGeneratePairAsync(parameters, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(SecKeyRef publicKey, SecKeyRef privateKey, CFErrorRef error){ + ok(publicKey == NULL && privateKey == NULL, "keys are NULL"); + ok(error != NULL, "error set"); + dispatch_group_leave(everyone_called); + }); + + // add the algorithm type + AddKeyCFTypePairToDictionary(parameters, kSecAttrKeyType, kSecAttrKeyTypeRSA); + + // see if we can get a 2048 bit keypair + AddKeyNumberPairToDictionary(parameters, kSecAttrKeySizeInBits, 2048); + + // put an application tag on the key + AddKeyStringPairToDictionary(parameters, kSecAttrApplicationTag, "This is a test."); + + // throw some sort of access thingie on it too + SecAccessRef access = NULL; + SecTrustedApplicationRef myself = NULL; + ok_status(SecTrustedApplicationCreateFromPath(NULL, &myself), "create trusted app for self"); + CFArrayRef trustedApplications = CFArrayCreate(NULL, (const void **)&myself, 1, &kCFTypeArrayCallBacks); + ok_status(SecAccessCreate(CFSTR("Trust self (test)"), trustedApplications, &access), "SecAccessCreate"); + CFRelease(trustedApplications); + CFRelease(myself); + AddKeyCFTypePairToDictionary(parameters, kSecAttrAccess, access); + + // try again + dispatch_group_enter(everyone_called); + SecKeyGeneratePairAsync(parameters, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(SecKeyRef pubKey, SecKeyRef privKey, CFErrorRef error){ + ok(pubKey != NULL && privKey != NULL, "keys set"); + ok(error == NULL, "no error"); + publicKey = (SecKeyRef)CFRetain(pubKey); + privateKey = (SecKeyRef)CFRetain(privKey); + dispatch_group_leave(everyone_called); + }); + + dispatch_group_wait(everyone_called, DISPATCH_TIME_FOREVER); + if (NULL == publicKey || NULL == privateKey) + { + return 1; + } + + // Make a chunk of data + char data[] = "This is a test of some data. Ain't it grand?"; + + SecPadding paddings[] = {kSecPaddingNone, kSecPaddingPKCS1, kSecPaddingPKCS1MD2, kSecPaddingPKCS1MD5, kSecPaddingPKCS1SHA1}; + const int numberOfPaddings = sizeof(paddings) / sizeof (SecPadding); + + // test each padding mode + int n; + for (n = 0; n < numberOfPaddings; ++n) + { + // sign that data with the private key + uint8 signature[512]; + size_t signatureLength = sizeof(signature); + + result = SecKeyRawSign(privateKey, paddings[n], (uint8_t*) data, strlen(data), signature, &signatureLength); + ok_status(result, "SecKeyRawSign"); + + // verify with the signature + result = SecKeyRawVerify(publicKey, paddings[n], (uint8_t*) data, strlen(data), signature, signatureLength); + ok_status(result, "SecKeyRawVerify"); + } + + // clean up + SecKeychainItemDelete((SecKeychainItemRef) publicKey); + SecKeychainItemDelete((SecKeychainItemRef) privateKey); + + CFRelease(publicKey); + CFRelease(privateKey); + CFRelease(parameters); + + return 0; +} + + + +int EncryptDecryptTest() +{ + CFMutableDictionaryRef parameters; + SecKeyRef encryptionKey, decryptionKey; + + // start out with an empty dictionary and see if it returns an error + parameters = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + // add the algorithm type + AddKeyCFTypePairToDictionary(parameters, kSecAttrKeyType, kSecAttrKeyTypeRSA); + + // see if we can get a 2048 bit keypair + AddKeyNumberPairToDictionary(parameters, kSecAttrKeySizeInBits, 2048); + + // put an application tag on the key + AddKeyStringPairToDictionary(parameters, kSecAttrApplicationTag, "This is a test."); + + OSStatus result = SecKeyGeneratePair(parameters, &encryptionKey, &decryptionKey); + ok_status(result, "EncryptDecryptTest"); + + // Make a chunk of data + char data[] = "I want to keep this data secure."; + + SecPadding paddings[] = {kSecPaddingPKCS1}; + const int numberOfPaddings = sizeof(paddings) / sizeof (SecPadding); + + // test each padding mode + int n; + for (n = 0; n < numberOfPaddings; ++n) + { + // encrypt that data with the public key + uint8 encryptedData[2048]; + size_t encryptedDataLength = sizeof(encryptedData); + memset(encryptedData, 0xFF, encryptedDataLength); + + result = SecKeyEncrypt(encryptionKey, paddings[n], (uint8_t*) data, sizeof(data), encryptedData, &encryptedDataLength); + if (result != noErr) + { + fprintf(stderr, "Error in encryption.\n"); + cssmPerror(NULL, result); + return 1; + } + + uint8 decryptedData[2048]; + size_t decryptedDataLength = sizeof(decryptedData); + + // decrypt with the private key + result = SecKeyDecrypt(decryptionKey, paddings[n], encryptedData, encryptedDataLength, decryptedData, &decryptedDataLength); + ok_status(result, "SecKeyDecrypt"); + + // what we got back had better equal what we put in + if (memcmp(data, decryptedData, sizeof(data)) != 0) + { + fprintf(stderr, "Decrypted text != original plain text.\n"); + return 1; + } + } + + // clean up + SecKeychainItemDelete((SecKeychainItemRef) encryptionKey); + SecKeychainItemDelete((SecKeychainItemRef) decryptionKey); + + CFRelease(encryptionKey); + CFRelease(decryptionKey); + CFRelease(parameters); + + return 0; +} + + + +#define TEST_ITEM_ACCOUNT CFSTR("SecItemTest_Account") +#define TEST_ITEM_SERVICE CFSTR("SecItemTest_Service") + +int SecItemTest() +{ + // create a dictionary to hold the item + CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + // create our item -- we are only testing generic passwords, since that is the scope of the bug + CFDictionaryAddValue(dict, kSecClass, kSecClassGenericPassword); + CFDictionaryAddValue(dict, kSecAttrAccount, TEST_ITEM_ACCOUNT); + CFDictionaryAddValue(dict, kSecAttrService, TEST_ITEM_SERVICE); + + const char* data = "Shh! It's a secret!!!"; + CFDataRef dataRef = CFDataCreateWithBytesNoCopy(NULL, (const UInt8*) data, strlen(data), NULL); + CFDictionaryAddValue(dict, kSecValueData, dataRef); + + CFTypeRef itemRef; + OSStatus result = SecItemAdd(dict, &itemRef); + ok_status(result, "SecItemAdd"); + + // cleanup + CFRelease(dict); + + // search for the item + dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + // create our item -- we are only testing generic passwords, since that is the scope of the bug + CFDictionaryAddValue(dict, kSecClass, kSecClassGenericPassword); + CFDictionaryAddValue(dict, kSecAttrAccount, TEST_ITEM_ACCOUNT); + CFDictionaryAddValue(dict, kSecAttrService, TEST_ITEM_SERVICE); + CFDictionaryAddValue(dict, kSecReturnAttributes, kCFBooleanTrue); + + result = SecItemCopyMatching(dict, &itemRef); + ok_status(result, "SecItemCopyMatching"); + + return 0; +} + + + +void tests() +{ + SecKeychainRef keychain = NULL; + ok_status(SecKeychainSetUserInteractionAllowed(FALSE), "SecKeychainSetUserInteractionAllowed(FALSE)"); + ok_status(SecKeychainCreate("test", 4, "test", FALSE, NULL, &keychain), "SecKeychainCreate"); + + SignVerifyWithAsyncTest(); + SignVerifyTest(); + SecItemTest(); + + if (keychain) CFRelease(keychain); +} + + + +int main(int argc, char * const *argv) +{ + plan_tests(34); + if (!tests_begin(argc, argv)) + BAIL_OUT("tests_begin failed"); + tests(); + ok(tests_end(1), "cleanup"); + ok_leaks("no leaks"); + return 0; +} diff --git a/SecurityTests/regressions/kc/kc-50-thread.c b/SecurityTests/regressions/kc/kc-50-thread.c new file mode 100644 index 00000000..933e5d5f --- /dev/null +++ b/SecurityTests/regressions/kc/kc-50-thread.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include "testmore.h" +#include "testenv.h" +#include "testleaks.h" +#include + +const double kTestLength = 10.0; // length of a test + +#define MAXIMUM_NUMBER_OF_THREADS 100 + +double GetTimeOfDay() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0; +} + + + +void* CopyDefaultAndReleaseInSingleThread(void* arg) +{ + OSStatus result; + + double endTime = GetTimeOfDay() + kTestLength; + do + { + SecKeychainRef kc; + result = SecKeychainCopyDefault(&kc); + CFRelease(kc); + + if (result != noErr) + { + return NULL; + } + + } while (GetTimeOfDay() < endTime); + + return NULL; +} + + + +int CopyDefaultAndDeleteInMultipleThreadsTest() +{ + const int gMax = MAXIMUM_NUMBER_OF_THREADS; + pthread_t threads[gMax]; + + // make the threads + int i; + for (i = 0; i < gMax; ++i) + { + pthread_create(&threads[i], NULL, CopyDefaultAndReleaseInSingleThread, NULL); + } + + // wait for them to complete + for (i = 0; i < gMax; ++i) + { + pthread_join(threads[i], NULL); + } + + return 1; +} + + + +int main(int argc, char* const argv[]) +{ + plan_tests(2); + ok(CopyDefaultAndDeleteInMultipleThreadsTest(), "CopyDefaultAndDeleteInMultipleThreadsTest"); + ok_leaks("kc-50-thread"); + return 0; +} + diff --git a/SecurityTests/regressions/kc/kc-51-testSecItemFind.c b/SecurityTests/regressions/kc/kc-51-testSecItemFind.c new file mode 100644 index 00000000..26e40ec3 --- /dev/null +++ b/SecurityTests/regressions/kc/kc-51-testSecItemFind.c @@ -0,0 +1,3359 @@ +// +// testSecItemFind.c +// +// Tests the ability of SecItemCopyMatching to replace the following +// deprecated keychain search functions: +// +// - SecKeychainSearchCreateFromAttributes + +// SecKeychainSearchCopyNext [for keys, certificates, passwords] +// +// - SecIdentitySearchCreate (or SecIdentitySearchCreateWithPolicy) + +// SecIdentitySearchCopyNext [for identities] +// +// +// This tool incidentally tests other Security API functions, including: +// - SecItemAdd +// - SecItemImport +// - SecItemDelete +// - SecKeyGenerateSymmetric +// +// +// To build and run this tool (from Terminal): +// cc -framework Security -framework CoreFoundation -o testSecItemFind testSecItemFind.c +// ./testSecItemFind +// +// IMPORTANT: when building this code yourself, make sure that the AUTO_TEST +// symbol is undefined (or defined to 0) below. If the AUTO_TEST symbol is +// defined and non-zero, it is assumed that this tool is being built as part of +// an automated regression test suite by internal Security test harness code. +// +// +// Last modified: Tue Nov 16 2010 (kcm) + + +#define AUTO_TEST 1 + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#if AUTO_TEST +#import "testmore.h" +#import "testenv.h" +#import "testleaks.h" +#else +#define tests_begin(ARGC, ARGV) /* no-op */ +#define tests_end(RESULT) /* no-op */ +#define plan_tests(COUNT) /* no-op */ +#define ok(RESULT, REASON) /* no-op */ +#endif + +/* Following is a 3-element certificate chain + * (ROOT_CERT, INTERMEDIATE_CERT, LEAF_CERT) + */ +unsigned char ROOT_CERT[985]={ + 0x30,0x82,0x03,0xD5,0x30,0x82,0x02,0xBD,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x01, + 0x30,0x0B,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x30,0x81,0x9D, + 0x31,0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x03,0x0C,0x11,0x54,0x65,0x73,0x74,0x2D, + 0x35,0x36,0x38,0x35,0x33,0x31,0x36,0x2D,0x52,0x4F,0x4F,0x54,0x31,0x0E,0x30,0x0C, + 0x06,0x03,0x55,0x04,0x0A,0x0C,0x05,0x41,0x70,0x70,0x6C,0x65,0x31,0x14,0x30,0x12, + 0x06,0x03,0x55,0x04,0x0B,0x0C,0x0B,0x43,0x6F,0x72,0x65,0x20,0x43,0x72,0x79,0x70, + 0x74,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x12,0x30,0x10, + 0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F, + 0x31,0x2B,0x30,0x29,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x01,0x16, + 0x1C,0x73,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x2D,0x64,0x65,0x76,0x40,0x67,0x72, + 0x6F,0x75,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x1E,0x17, + 0x0D,0x30,0x39,0x31,0x32,0x31,0x38,0x31,0x37,0x32,0x39,0x32,0x33,0x5A,0x17,0x0D, + 0x31,0x30,0x31,0x32,0x31,0x38,0x31,0x37,0x32,0x39,0x32,0x33,0x5A,0x30,0x81,0x9D, + 0x31,0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x03,0x0C,0x11,0x54,0x65,0x73,0x74,0x2D, + 0x35,0x36,0x38,0x35,0x33,0x31,0x36,0x2D,0x52,0x4F,0x4F,0x54,0x31,0x0E,0x30,0x0C, + 0x06,0x03,0x55,0x04,0x0A,0x0C,0x05,0x41,0x70,0x70,0x6C,0x65,0x31,0x14,0x30,0x12, + 0x06,0x03,0x55,0x04,0x0B,0x0C,0x0B,0x43,0x6F,0x72,0x65,0x20,0x43,0x72,0x79,0x70, + 0x74,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x12,0x30,0x10, + 0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F, + 0x31,0x2B,0x30,0x29,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x01,0x16, + 0x1C,0x73,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x2D,0x64,0x65,0x76,0x40,0x67,0x72, + 0x6F,0x75,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x82,0x01, + 0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00, + 0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xB0,0x4C, + 0x94,0xF7,0x56,0x26,0x91,0xB8,0xD1,0x5B,0x7C,0xEE,0x74,0xCB,0x1F,0x43,0xFE,0x88, + 0x24,0xAD,0xB0,0x1E,0x85,0x86,0xE9,0x3F,0xE7,0x74,0x40,0x6C,0x4A,0x8E,0x6B,0x50, + 0x7A,0x1B,0x43,0x9A,0x9E,0xF4,0x81,0xB3,0xF1,0xDB,0x6E,0xD4,0xFA,0xAE,0x06,0xCB, + 0x7F,0xE6,0xCA,0x06,0x06,0xC4,0x1E,0x2D,0xF3,0xFA,0x67,0xD6,0x95,0x0E,0xAC,0xCA, + 0x2B,0x25,0x14,0x4C,0x20,0x04,0xB4,0x26,0xAC,0x15,0x62,0x15,0xA6,0x21,0x14,0x51, + 0xCC,0x77,0x82,0x11,0xD0,0xF8,0xB0,0x06,0xC1,0x0F,0xFB,0x08,0x60,0x53,0x11,0x1F, + 0x00,0xA8,0x27,0x0E,0x2C,0x2C,0x63,0x34,0x6A,0xC5,0x4B,0x2D,0xCC,0x07,0xF6,0x39, + 0xDC,0x00,0xCF,0x6E,0x29,0x15,0x3E,0x3F,0x6C,0x89,0xB9,0x48,0x97,0x19,0xA2,0xB8, + 0x44,0x8D,0x98,0x85,0xF4,0x0B,0x70,0x06,0xD6,0x9A,0x39,0x4F,0x44,0x92,0x73,0x74, + 0xDF,0x46,0x10,0x9C,0xB5,0xBB,0x69,0xF4,0xE1,0xB5,0x61,0x2E,0xFF,0x92,0xDB,0x47, + 0x93,0x48,0x45,0xEB,0x7E,0xFA,0xCC,0xDB,0xCE,0x50,0x0A,0xCA,0xAF,0xAB,0x7D,0x09, + 0x9A,0x1E,0xC4,0x08,0xA1,0xD4,0xB9,0x2A,0x42,0x49,0x10,0x75,0x63,0x4E,0x51,0x3B, + 0xF7,0xF4,0xCA,0xCB,0x05,0xC9,0xE0,0xC9,0xD3,0x04,0x14,0x81,0xF6,0x9A,0xEE,0x0C, + 0x2B,0x56,0x87,0x20,0x50,0x27,0x14,0x71,0x1C,0x30,0x18,0x8C,0xDD,0xF4,0xA9,0x41, + 0x13,0x6D,0xE4,0x41,0xB1,0xE0,0x7E,0x09,0xD7,0x99,0xCE,0xE4,0x7A,0x91,0x65,0xBB, + 0x3F,0xE1,0xD4,0x07,0x8D,0xA9,0x23,0x0A,0xA4,0x80,0x47,0x58,0xD5,0x25,0x02,0x03, + 0x01,0x00,0x01,0xA3,0x20,0x30,0x1E,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01, + 0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x0B,0x06,0x03,0x55,0x1D,0x0F,0x04, + 0x04,0x03,0x02,0x02,0x84,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, + 0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x38,0x44,0x10,0xF4,0x24,0x4A,0xAA, + 0x9F,0x0D,0x37,0x5E,0x75,0xB7,0xF5,0xC5,0x27,0x19,0x57,0xE5,0x25,0x4A,0x44,0x03, + 0x5F,0x2E,0xD4,0x70,0x69,0xDD,0x55,0xDB,0x47,0x07,0x06,0x3E,0x5D,0xA4,0xBB,0x64, + 0xE2,0xA6,0x09,0x8B,0x6D,0x0B,0x50,0x33,0x5A,0x92,0x5A,0x5B,0xDF,0x6A,0x9F,0x81, + 0x5F,0x17,0x95,0xB0,0xC6,0xC3,0xCD,0x6D,0x17,0xDD,0x83,0xC1,0xA5,0xB7,0xCD,0xFF, + 0xE8,0x13,0x10,0x35,0x85,0x3E,0xCA,0xE4,0xF5,0x22,0x58,0x1E,0x68,0x14,0x62,0x35, + 0xE4,0x65,0xB4,0xD3,0x42,0x5A,0x03,0x5C,0x2D,0x76,0xD5,0x9B,0xAA,0xCB,0x3A,0xAC, + 0x55,0x58,0xAD,0x67,0x30,0xDC,0xC3,0xA7,0xA9,0x37,0xBB,0x61,0xA2,0xEA,0x6E,0x0C, + 0xB0,0x4B,0x0D,0x64,0x3D,0x59,0x3C,0xA3,0xA1,0x73,0x4F,0x33,0xDB,0x6F,0xBF,0x2D, + 0xB2,0x9D,0xCE,0x05,0x1C,0xF0,0xAB,0x4A,0xB0,0x70,0x5D,0x32,0x20,0x22,0xD7,0x12, + 0xC0,0x1C,0x0B,0x0D,0xC0,0x72,0x6B,0x6F,0xA4,0xF8,0xAA,0xD2,0x34,0x36,0x63,0x84, + 0x80,0xF0,0x70,0x5E,0x09,0xEA,0xFF,0x48,0x49,0x85,0x83,0x8E,0x8E,0x6E,0x4C,0x2E, + 0x2F,0xBB,0xBF,0xDF,0x3B,0x73,0x65,0xA2,0x0D,0x09,0x84,0x8F,0x08,0x86,0x61,0x27, + 0x58,0xB6,0x7E,0x2D,0xEC,0x08,0xBA,0x40,0x5D,0x20,0x54,0x37,0xDD,0xCC,0xE5,0xDB, + 0x38,0x68,0xEE,0x56,0x9F,0x92,0xDD,0x03,0x04,0xD2,0x94,0x51,0xD3,0xA9,0x08,0x2E, + 0x6E,0x25,0x8E,0xBF,0x8A,0xA9,0x2B,0xAD,0x50,0x00,0xA7,0x39,0x11,0x6A,0x9A,0x28, + 0x99,0x9A,0xB9,0x3B,0xB9,0xB5,0x9C,0x19,0x3A, +}; + +unsigned char INTERMEDIATE_CERT[1037]={ + 0x30,0x82,0x04,0x09,0x30,0x82,0x02,0xF1,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x02, + 0x30,0x0B,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x30,0x81,0x9D, + 0x31,0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x03,0x0C,0x11,0x54,0x65,0x73,0x74,0x2D, + 0x35,0x36,0x38,0x35,0x33,0x31,0x36,0x2D,0x52,0x4F,0x4F,0x54,0x31,0x0E,0x30,0x0C, + 0x06,0x03,0x55,0x04,0x0A,0x0C,0x05,0x41,0x70,0x70,0x6C,0x65,0x31,0x14,0x30,0x12, + 0x06,0x03,0x55,0x04,0x0B,0x0C,0x0B,0x43,0x6F,0x72,0x65,0x20,0x43,0x72,0x79,0x70, + 0x74,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31, + 0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x12,0x30,0x10, + 0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F, + 0x31,0x2B,0x30,0x29,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x01,0x16, + 0x1C,0x73,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x2D,0x64,0x65,0x76,0x40,0x67,0x72, + 0x6F,0x75,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x1E,0x17, + 0x0D,0x30,0x39,0x31,0x32,0x31,0x38,0x31,0x37,0x33,0x30,0x35,0x34,0x5A,0x17,0x0D, + 0x31,0x30,0x31,0x32,0x31,0x38,0x31,0x37,0x33,0x30,0x35,0x34,0x5A,0x30,0x81,0xA5, + 0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x03,0x0C,0x19,0x54,0x65,0x73,0x74,0x2D, + 0x35,0x36,0x38,0x35,0x33,0x31,0x36,0x2D,0x49,0x4E,0x54,0x45,0x52,0x4D,0x45,0x44, + 0x49,0x41,0x54,0x45,0x31,0x0E,0x30,0x0C,0x06,0x03,0x55,0x04,0x0A,0x0C,0x05,0x41, + 0x70,0x70,0x6C,0x65,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0B,0x0C,0x0B,0x43, + 0x6F,0x72,0x65,0x20,0x43,0x72,0x79,0x70,0x74,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06, + 0x13,0x02,0x55,0x53,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43, + 0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x2B,0x30,0x29,0x06,0x09,0x2A,0x86, + 0x48,0x86,0xF7,0x0D,0x01,0x09,0x01,0x16,0x1C,0x73,0x65,0x63,0x75,0x72,0x69,0x74, + 0x79,0x2D,0x64,0x65,0x76,0x40,0x67,0x72,0x6F,0x75,0x70,0x2E,0x61,0x70,0x70,0x6C, + 0x65,0x2E,0x63,0x6F,0x6D,0x30,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,0xBD,0x46,0x0E,0x0F,0x5C,0x1C,0xA2,0x23,0xD2, + 0x3B,0x8C,0xC4,0x02,0x52,0x8C,0xD8,0xB1,0xC2,0x58,0x2E,0x84,0xAA,0x6C,0xCB,0x4B, + 0xE4,0xF1,0xE7,0x48,0x98,0x46,0x6B,0xD0,0x50,0xB0,0xA3,0x1F,0x23,0xC6,0x3C,0x81, + 0x73,0xE7,0xEA,0xAA,0x55,0xF7,0x37,0x58,0x85,0xF6,0x96,0x0D,0xC0,0x81,0x8D,0x3D, + 0xD9,0xAD,0xFA,0x32,0x46,0x56,0x4A,0x53,0xF5,0x53,0x34,0x5B,0xFC,0xFC,0x51,0x2A, + 0x45,0xD4,0xCB,0x53,0xF9,0x58,0xBF,0x7D,0x48,0xB3,0x23,0x41,0xD7,0x93,0x1C,0xC2, + 0x32,0xE8,0x1C,0x82,0xDC,0xDC,0xCB,0xED,0x0B,0xDA,0x8A,0x1C,0xC0,0x0E,0x83,0x24, + 0xE6,0x2E,0x68,0xA6,0xB6,0x60,0xEE,0xAF,0xB1,0x07,0xF1,0xC0,0xDB,0x29,0x83,0x9E, + 0x0C,0xF4,0xCF,0x67,0x5B,0x49,0x3A,0x17,0x7E,0xC1,0xEB,0x75,0x3E,0xDD,0x0F,0x9A, + 0xC7,0x06,0x60,0x2B,0x18,0xBD,0xAA,0x96,0xD1,0xE1,0x9C,0xF0,0x34,0xFF,0x3E,0x8C, + 0x4A,0x96,0x5D,0x68,0x7C,0xCF,0xA1,0x14,0xED,0xB1,0x8E,0x10,0x8D,0x1F,0x15,0x22, + 0x4E,0x8E,0x1A,0xC7,0xAD,0xB9,0x16,0xCB,0x3C,0xCB,0x5D,0xB9,0xAC,0xD9,0xFE,0xAE, + 0xDE,0x06,0x3B,0xB6,0xA1,0xAA,0x7C,0x91,0x76,0xC6,0xA4,0x81,0xBD,0x29,0x86,0x33, + 0xA6,0xB5,0x4D,0x28,0x94,0x51,0x81,0x3F,0x68,0x95,0xEB,0x41,0x7A,0xE9,0x87,0xD7, + 0xDC,0xC8,0xA0,0x5F,0xAB,0x29,0xD9,0xC4,0x08,0xC8,0xA0,0x0B,0x77,0xAC,0x6C,0x21, + 0x10,0xA4,0xED,0x86,0x78,0x99,0x1F,0xA7,0x23,0x33,0x34,0x89,0x80,0x02,0xBC,0xAF, + 0xC6,0x3E,0x38,0xFB,0x7C,0x47,0x02,0x03,0x01,0x00,0x01,0xA3,0x4C,0x30,0x4A,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,0x84, + 0x30,0x27,0x06,0x03,0x55,0x1D,0x11,0x04,0x20,0x30,0x1E,0x81,0x1C,0x73,0x65,0x63, + 0x75,0x72,0x69,0x74,0x79,0x2D,0x64,0x65,0x76,0x40,0x67,0x72,0x6F,0x75,0x70,0x2E, + 0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x3C,0x66,0x3B, + 0x9D,0x6E,0xA9,0x0E,0xC9,0xC2,0x6C,0xF4,0x79,0xFB,0xD5,0x6E,0x1F,0x01,0x4E,0x0D, + 0x2C,0x64,0x7B,0x6E,0xD7,0xC7,0xA7,0x64,0x8B,0xF0,0xCD,0x93,0xCD,0x12,0x29,0x71, + 0x87,0x3E,0xA3,0x1E,0x7F,0x57,0xC7,0xD9,0xBF,0xD2,0xF2,0x03,0x27,0xD5,0x5E,0xEF, + 0x59,0xBC,0x91,0x37,0xB4,0x4A,0xEE,0xD2,0x2F,0xEA,0x92,0x07,0xBC,0xEC,0xAC,0x6A, + 0xF1,0x34,0xA4,0x40,0x61,0x8B,0xB9,0x3D,0xAF,0x5B,0x86,0x6E,0xEE,0x4C,0xCB,0x7F, + 0x1F,0xD0,0x0F,0x9E,0x5A,0xF0,0x39,0xFD,0x89,0xF3,0x03,0x61,0x5A,0xDF,0x6B,0x5F, + 0xE3,0x33,0x51,0x80,0x1B,0x61,0xFE,0x7A,0xC7,0x27,0xBF,0x12,0xB5,0x69,0x79,0x1E, + 0xAD,0x75,0xA8,0xFA,0x94,0xCC,0x22,0x4C,0xF9,0xB4,0xD3,0xD0,0xDC,0x57,0xD3,0x66, + 0x96,0xDD,0x8A,0xC0,0xE4,0x11,0x5A,0xD9,0xB3,0x76,0x17,0x04,0xDA,0x62,0x71,0x58, + 0xEA,0x99,0xC3,0x06,0xA7,0xE8,0xDB,0xA9,0x05,0xEC,0xA3,0xCA,0xDA,0x2E,0x77,0x66, + 0xF4,0xC4,0xD2,0xC6,0xF0,0x5F,0xE6,0x88,0xDF,0x7F,0x23,0xDE,0x7B,0x04,0xA4,0x22, + 0x45,0xEF,0x0A,0x13,0x79,0x8E,0xE1,0x14,0x22,0x79,0x22,0x86,0x1A,0x4C,0xA7,0xBA, + 0x06,0x55,0xD9,0x5E,0xF3,0x9C,0xE0,0x1F,0xE3,0xA4,0x1C,0x8E,0x01,0x9F,0x7E,0xEF, + 0xD2,0xA7,0x8D,0xD6,0x4D,0x1A,0x3D,0xA7,0xB2,0xDB,0x44,0x25,0xB5,0xA6,0x8A,0xD5, + 0x49,0x87,0x04,0x6C,0x41,0x13,0x88,0x7A,0xFB,0x5E,0x16,0xA2,0x8F,0x37,0x81,0x47, + 0xD8,0x27,0x3D,0xBD,0xB1,0x3E,0xCE,0x2A,0x07,0x75,0x45,0x5F,0x44, +}; + +unsigned char LEAF_CERT[1037]={ + 0x30,0x82,0x04,0x09,0x30,0x82,0x02,0xF1,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x03, + 0x30,0x0B,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x30,0x81,0xA5, + 0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x03,0x0C,0x19,0x54,0x65,0x73,0x74,0x2D, + 0x35,0x36,0x38,0x35,0x33,0x31,0x36,0x2D,0x49,0x4E,0x54,0x45,0x52,0x4D,0x45,0x44, + 0x49,0x41,0x54,0x45,0x31,0x0E,0x30,0x0C,0x06,0x03,0x55,0x04,0x0A,0x0C,0x05,0x41, + 0x70,0x70,0x6C,0x65,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0B,0x0C,0x0B,0x43, + 0x6F,0x72,0x65,0x20,0x43,0x72,0x79,0x70,0x74,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06, + 0x13,0x02,0x55,0x53,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43, + 0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x2B,0x30,0x29,0x06,0x09,0x2A,0x86, + 0x48,0x86,0xF7,0x0D,0x01,0x09,0x01,0x16,0x1C,0x73,0x65,0x63,0x75,0x72,0x69,0x74, + 0x79,0x2D,0x64,0x65,0x76,0x40,0x67,0x72,0x6F,0x75,0x70,0x2E,0x61,0x70,0x70,0x6C, + 0x65,0x2E,0x63,0x6F,0x6D,0x30,0x1E,0x17,0x0D,0x30,0x39,0x31,0x32,0x31,0x38,0x31, + 0x37,0x33,0x32,0x31,0x36,0x5A,0x17,0x0D,0x31,0x30,0x31,0x32,0x31,0x38,0x31,0x37, + 0x33,0x32,0x31,0x36,0x5A,0x30,0x81,0x9D,0x31,0x1A,0x30,0x18,0x06,0x03,0x55,0x04, + 0x03,0x0C,0x11,0x54,0x65,0x73,0x74,0x2D,0x35,0x36,0x38,0x35,0x33,0x31,0x36,0x2D, + 0x4C,0x45,0x41,0x46,0x31,0x0E,0x30,0x0C,0x06,0x03,0x55,0x04,0x0A,0x0C,0x05,0x41, + 0x70,0x70,0x6C,0x65,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0B,0x0C,0x0B,0x43, + 0x6F,0x72,0x65,0x20,0x43,0x72,0x79,0x70,0x74,0x6F,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06, + 0x13,0x02,0x55,0x53,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43, + 0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x2B,0x30,0x29,0x06,0x09,0x2A,0x86, + 0x48,0x86,0xF7,0x0D,0x01,0x09,0x01,0x16,0x1C,0x73,0x65,0x63,0x75,0x72,0x69,0x74, + 0x79,0x2D,0x64,0x65,0x76,0x40,0x67,0x72,0x6F,0x75,0x70,0x2E,0x61,0x70,0x70,0x6C, + 0x65,0x2E,0x63,0x6F,0x6D,0x30,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,0xBF,0x1B,0x87,0x6B,0x10,0xF8,0xF6,0x24,0x07,0x40, + 0xC3,0xE3,0x81,0x26,0xD6,0xF4,0xFF,0xAA,0x6C,0x26,0xD4,0xBF,0xF7,0x9A,0xF5,0xB8, + 0x63,0xBD,0x8B,0xFD,0x4B,0xFE,0xFF,0x4B,0xA2,0x15,0x13,0x52,0x84,0x87,0x9E,0x2B, + 0x32,0x5B,0xF8,0x01,0x28,0x5E,0xF1,0x9C,0xE7,0x52,0xB0,0x89,0xB8,0x4A,0xD0,0x87, + 0x40,0x0C,0xCD,0xAC,0x11,0x22,0x89,0x44,0x26,0x3B,0x40,0xF3,0x34,0x61,0x14,0x3A, + 0x94,0xF3,0x1F,0x27,0x62,0xF8,0x8C,0xB4,0xF5,0x1E,0xA6,0x37,0x53,0xB2,0xB3,0x1E, + 0x35,0xF6,0x00,0x34,0x4B,0x28,0x72,0x5B,0x9D,0xD8,0xEA,0x06,0x91,0x77,0x57,0x38, + 0x9C,0xA5,0x66,0x5F,0x1A,0x9A,0x0B,0xCC,0x2F,0x2E,0x58,0xA2,0x70,0x66,0xA6,0xEF, + 0x1B,0x3A,0x0E,0xF0,0x4B,0xA6,0x9D,0x6D,0x63,0xE0,0x1C,0x9C,0x8E,0xFF,0x6F,0x50, + 0x5F,0x03,0x1A,0x80,0x12,0x4A,0xB6,0x89,0x83,0x5C,0x51,0x9F,0x2F,0xEA,0xE4,0x7F, + 0x12,0xFB,0xE4,0x92,0xF0,0x8B,0x17,0x35,0x02,0x73,0xA0,0x7D,0xA2,0xB9,0x89,0xE2, + 0x78,0x52,0xA1,0x08,0x42,0x78,0xD5,0xD3,0x8C,0x3C,0xF2,0x88,0x5E,0x7A,0xCC,0x94, + 0x80,0x42,0xEA,0xED,0x6E,0x64,0x19,0x5E,0x53,0x05,0xB6,0x60,0xDB,0x81,0x92,0x2C, + 0x3D,0xD4,0xAF,0xF8,0xED,0xD9,0x28,0xCE,0x0B,0xD9,0xDC,0x20,0x0C,0xA9,0x8D,0xA4, + 0x54,0xD1,0xDA,0xDE,0x30,0x4A,0x67,0xC6,0xAC,0x4E,0xE3,0xB4,0xD7,0x16,0xF5,0xDC, + 0xE3,0x52,0xAC,0x01,0x1C,0xB6,0xC1,0x5B,0xB4,0xEA,0x67,0x25,0xFE,0xF6,0x58,0x5C, + 0xFE,0x88,0x4E,0xCF,0xF1,0x11,0x02,0x03,0x01,0x00,0x01,0xA3,0x4C,0x30,0x4A,0x30, + 0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07,0x80,0x30, + 0x0F,0x06,0x03,0x55,0x1D,0x25,0x04,0x08,0x30,0x06,0x06,0x04,0x55,0x1D,0x25,0x00, + 0x30,0x27,0x06,0x03,0x55,0x1D,0x11,0x04,0x20,0x30,0x1E,0x81,0x1C,0x73,0x65,0x63, + 0x75,0x72,0x69,0x74,0x79,0x2D,0x64,0x65,0x76,0x40,0x67,0x72,0x6F,0x75,0x70,0x2E, + 0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x1A,0xE5,0xD1, + 0x13,0x66,0x83,0xC7,0x1A,0xB0,0x50,0xF0,0x1B,0x6E,0x70,0x6E,0x36,0x1A,0x0F,0x12, + 0x9E,0x0B,0xFD,0x4B,0x79,0xEC,0xAA,0x5E,0x2A,0x37,0x79,0x50,0x97,0x13,0x9E,0xB6, + 0x43,0xF0,0xD2,0xC6,0xF3,0x43,0x73,0x33,0x6C,0xCB,0x73,0xE5,0xBE,0x4C,0x42,0x6F, + 0x33,0x76,0x96,0xA2,0x6B,0xA0,0x8D,0xAD,0x46,0xA5,0xD4,0xAC,0x0E,0x55,0x80,0x1A, + 0x6E,0xAF,0xC2,0x2E,0xB3,0xD4,0x64,0xC3,0x65,0xFA,0x1C,0x42,0x47,0x12,0x9F,0x44, + 0xD2,0x1F,0xCF,0xA1,0x53,0x49,0x66,0x66,0x14,0x21,0xD4,0x17,0xD1,0x26,0x75,0xAD, + 0x08,0x93,0x9C,0x3B,0xB7,0x7C,0x03,0x2F,0x76,0x5D,0xB7,0x25,0x83,0x68,0xE3,0x01, + 0x5C,0xCD,0x87,0x7A,0x71,0x8B,0x8D,0x5D,0x27,0x27,0xF2,0x24,0x56,0x7C,0x7E,0x33, + 0x8F,0xE6,0x02,0x46,0xAD,0x63,0x28,0x85,0xA2,0x9E,0xEA,0x5A,0xC4,0x92,0xCE,0x76, + 0xE8,0xD4,0xD4,0x7D,0x48,0x44,0xA4,0x21,0x8C,0xB7,0xC2,0x15,0x80,0x87,0x19,0xB1, + 0x10,0x6A,0xC7,0x51,0xB7,0x25,0x40,0x26,0x8A,0xCC,0xB6,0x0C,0xE2,0x0D,0xA1,0x40, + 0x20,0x85,0x0F,0xE5,0xB9,0xB5,0x32,0x10,0xA9,0x5F,0x25,0xCA,0xD2,0x95,0x11,0x54, + 0x41,0xEA,0xC3,0xBA,0x0C,0x24,0x10,0x28,0xC9,0x09,0xAF,0x7E,0xDF,0x6A,0x2F,0x30, + 0x49,0x7C,0xB0,0x23,0x46,0xA8,0xDC,0xE3,0x6A,0x17,0x87,0xF7,0xCC,0x3A,0xBD,0x11, + 0x95,0xC3,0x0A,0x37,0xD1,0x1F,0x20,0xB6,0x1B,0xB2,0xA2,0x45,0xFF,0xC1,0x0D,0x9A, + 0x56,0xCD,0x5A,0xF6,0x08,0xAA,0xBD,0xAB,0x13,0xC6,0xFD,0xAA,0xEC, +}; + +/* Test certificate for Code Signing policy + */ +unsigned char Test_codesign[1017]={ + 0x30,0x82,0x03,0xF5,0x30,0x82,0x02,0xDD,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x77, + 0xCE,0xF5,0x3D,0x30,0x0B,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05, + 0x30,0x81,0xA5,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x03,0x0C,0x19,0x54,0x65, + 0x73,0x74,0x2D,0x35,0x36,0x38,0x35,0x33,0x31,0x36,0x2D,0x49,0x4E,0x54,0x45,0x52, + 0x4D,0x45,0x44,0x49,0x41,0x54,0x45,0x31,0x0E,0x30,0x0C,0x06,0x03,0x55,0x04,0x0A, + 0x0C,0x05,0x41,0x70,0x70,0x6C,0x65,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0B, + 0x0C,0x0B,0x43,0x6F,0x72,0x65,0x20,0x43,0x72,0x79,0x70,0x74,0x6F,0x31,0x0B,0x30, + 0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07, + 0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x2B,0x30,0x29,0x06, + 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x01,0x16,0x1C,0x73,0x65,0x63,0x75, + 0x72,0x69,0x74,0x79,0x2D,0x64,0x65,0x76,0x40,0x67,0x72,0x6F,0x75,0x70,0x2E,0x61, + 0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x1E,0x17,0x0D,0x31,0x30,0x30,0x35, + 0x32,0x30,0x30,0x31,0x32,0x35,0x33,0x32,0x5A,0x17,0x0D,0x31,0x31,0x30,0x35,0x32, + 0x30,0x30,0x31,0x32,0x35,0x33,0x32,0x5A,0x30,0x81,0xA8,0x31,0x24,0x30,0x22,0x06, + 0x03,0x55,0x04,0x03,0x0C,0x1B,0x54,0x65,0x73,0x74,0x2D,0x37,0x38,0x37,0x35,0x38, + 0x30,0x31,0x20,0x28,0x43,0x6F,0x64,0x65,0x20,0x53,0x69,0x67,0x6E,0x69,0x6E,0x67, + 0x29,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C, + 0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x0B,0x0C, + 0x07,0x43,0x6F,0x72,0x65,0x20,0x4F,0x53,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x08,0x0C,0x02,0x43,0x41,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70, + 0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x2B,0x30,0x29,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x09,0x01,0x16,0x1C,0x73,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x2D, + 0x64,0x65,0x76,0x40,0x67,0x72,0x6F,0x75,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E, + 0x63,0x6F,0x6D,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02, + 0x82,0x01,0x01,0x00,0xC0,0x5E,0x52,0x53,0xB0,0x05,0x8D,0x9E,0xF2,0xBF,0x2E,0xA1, + 0x95,0xD5,0x10,0x97,0xFC,0x8E,0x77,0x6E,0x63,0x7A,0x7D,0xD2,0x56,0x05,0xE9,0xEE, + 0x3D,0xEE,0xCA,0xA4,0xBB,0x99,0x42,0xA2,0x55,0x67,0x97,0x15,0xFB,0x94,0x6D,0x22, + 0x39,0x7F,0xE9,0xC0,0x72,0x41,0x8F,0xF5,0x76,0x55,0x65,0x3B,0x39,0x5F,0x31,0x15, + 0x72,0x2A,0xB4,0x2F,0xED,0xB7,0x6A,0x3E,0xE9,0x3A,0x1C,0x50,0xD4,0x31,0x6D,0x7A, + 0x71,0x28,0x98,0x8D,0x8A,0xBF,0x90,0x01,0x8A,0xFF,0x42,0x62,0xEB,0xE5,0xC8,0x5A, + 0xB2,0x5A,0xB8,0x46,0x27,0xDA,0xD5,0x70,0xAF,0xD4,0xF6,0xF2,0xEC,0xD6,0x43,0x7E, + 0x25,0x31,0xED,0xA2,0x1E,0xFA,0x77,0xF4,0x59,0xBF,0x3F,0x11,0xAE,0xF1,0x0E,0xC9, + 0xFD,0x56,0xCA,0xA0,0x3E,0x8B,0xA5,0xE9,0xF6,0x91,0x82,0xE0,0xC6,0x5E,0x35,0x92, + 0x3F,0x0E,0x77,0x23,0x88,0x6F,0x33,0x91,0xAC,0x98,0xC5,0xF5,0x52,0x12,0xB2,0x3A, + 0x08,0x66,0xEB,0xC8,0x14,0x8E,0xED,0x0F,0xE5,0x76,0xCE,0x36,0xE8,0xED,0xB6,0x41, + 0xD6,0xF3,0x1C,0x24,0xBA,0xCC,0xEE,0x28,0xF8,0xC8,0xAE,0x87,0x15,0x1D,0x33,0x47, + 0xEA,0x5B,0x7D,0xE2,0x80,0xA9,0x6B,0xE3,0x8B,0x36,0xD0,0x25,0x2C,0x32,0xDA,0xFF, + 0x7C,0x85,0x28,0x48,0xDB,0x35,0x2A,0x1A,0xBE,0x7F,0xCD,0xE1,0xA6,0x79,0x35,0xB3, + 0x79,0xA3,0xB9,0x15,0xC6,0x31,0xA1,0xB4,0x63,0xD8,0x05,0x1D,0xDD,0x11,0x74,0xCD, + 0xCF,0xBD,0x27,0x02,0xB7,0xD8,0xA9,0xA1,0x1D,0xFB,0xA1,0xEC,0x44,0x8D,0x21,0x64, + 0x84,0x2E,0x6B,0x3B,0x02,0x03,0x01,0x00,0x01,0xA3,0x2A,0x30,0x28,0x30,0x0E,0x06, + 0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x16,0x06, + 0x03,0x55,0x1D,0x25,0x01,0x01,0xFF,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01, + 0x05,0x05,0x07,0x03,0x03,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, + 0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x80,0xC4,0xB6,0x9D,0xBE,0x72,0x30, + 0x72,0xFD,0x49,0x43,0x8F,0x3B,0xFE,0xC6,0xF1,0x4D,0xAA,0xB3,0xD1,0xD6,0x0C,0x54, + 0x9D,0x24,0xDF,0x86,0x9B,0x0A,0x68,0x55,0x4B,0x5A,0x20,0x53,0xC0,0xBF,0x82,0xAF, + 0xC7,0x19,0x19,0x43,0xA1,0xA4,0x53,0xF4,0xE5,0x33,0xE6,0xF7,0xAD,0x8E,0x6D,0xD8, + 0x94,0x23,0xEB,0x3E,0x6A,0xCF,0xDA,0x4B,0x09,0x6E,0x26,0x2B,0x62,0x70,0x98,0x0A, + 0xCE,0x58,0x70,0xA6,0xAD,0x08,0x45,0xAB,0x9E,0x89,0xBB,0xF8,0x84,0x6F,0x0D,0x9B, + 0x77,0xBA,0x60,0x9E,0xB8,0xA6,0xB6,0x7D,0x20,0xE9,0x83,0x72,0xE1,0xE9,0xB0,0x0E, + 0x0D,0x27,0xFB,0xD0,0x4C,0x81,0x88,0xAF,0x82,0x8F,0xB9,0x82,0xAD,0x1D,0x1B,0x54, + 0x11,0x84,0x16,0xFC,0x0B,0x53,0xB8,0xED,0x71,0xA2,0x6A,0xD9,0xC7,0x88,0xEE,0xD6, + 0x0C,0x5E,0xAD,0x2E,0x50,0xBA,0x56,0x12,0x95,0x5C,0x7F,0xF1,0x3B,0x48,0xB5,0x17, + 0x53,0xA9,0xC5,0x4C,0xD6,0x8C,0x39,0xCB,0x1A,0x5B,0xB6,0x4B,0x73,0x67,0x1E,0xB5, + 0x7D,0x13,0xAE,0x6B,0xD5,0xF4,0x59,0xE3,0xA1,0x4C,0x6A,0xEC,0xA5,0x27,0x07,0x9D, + 0x93,0x8F,0xF5,0xBB,0x50,0x28,0x00,0x05,0x25,0xCD,0xED,0xF7,0xA9,0x11,0x22,0x7E, + 0x92,0x4D,0xF5,0x7C,0x55,0xF4,0x1C,0x7A,0xA3,0xBC,0x24,0xC7,0xFB,0xED,0x6A,0x0A, + 0x1E,0xD5,0x9D,0x63,0xE0,0x2B,0x91,0x59,0x48,0xF2,0xF6,0xEB,0xF9,0xEB,0x9E,0x4D, + 0x3E,0xAE,0x44,0x9D,0xF9,0x93,0xB5,0x44,0xA1,0x36,0x3E,0x4E,0xC7,0xD9,0x47,0x83, + 0xCE,0xDD,0xA0,0x7C,0xA1,0xB4,0x75,0x1F,0xC8, +}; + +/* Test certificate for S/MIME policy (encrypt only, no sign) + */ +unsigned char Test_smime_encryptonly[1060]={ + 0x30,0x82,0x04,0x20,0x30,0x82,0x03,0x08,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x77, + 0xCF,0x46,0x7D,0x30,0x0B,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05, + 0x30,0x81,0xA5,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x03,0x0C,0x19,0x54,0x65, + 0x73,0x74,0x2D,0x35,0x36,0x38,0x35,0x33,0x31,0x36,0x2D,0x49,0x4E,0x54,0x45,0x52, + 0x4D,0x45,0x44,0x49,0x41,0x54,0x45,0x31,0x0E,0x30,0x0C,0x06,0x03,0x55,0x04,0x0A, + 0x0C,0x05,0x41,0x70,0x70,0x6C,0x65,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0B, + 0x0C,0x0B,0x43,0x6F,0x72,0x65,0x20,0x43,0x72,0x79,0x70,0x74,0x6F,0x31,0x0B,0x30, + 0x09,0x06,0x03,0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07, + 0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x2B,0x30,0x29,0x06, + 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x01,0x16,0x1C,0x73,0x65,0x63,0x75, + 0x72,0x69,0x74,0x79,0x2D,0x64,0x65,0x76,0x40,0x67,0x72,0x6F,0x75,0x70,0x2E,0x61, + 0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x1E,0x17,0x0D,0x31,0x30,0x30,0x37, + 0x32,0x37,0x32,0x30,0x35,0x39,0x35,0x38,0x5A,0x17,0x0D,0x31,0x32,0x30,0x37,0x32, + 0x37,0x32,0x30,0x35,0x39,0x35,0x38,0x5A,0x30,0x81,0xB2,0x31,0x21,0x30,0x1F,0x06, + 0x03,0x55,0x04,0x03,0x0C,0x18,0x54,0x65,0x73,0x74,0x2D,0x45,0x6E,0x63,0x72,0x79, + 0x70,0x74,0x69,0x6F,0x6E,0x20,0x28,0x53,0x2F,0x4D,0x49,0x4D,0x45,0x29,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x0B,0x0C,0x1C,0x43,0x6F, + 0x72,0x65,0x20,0x4F,0x53,0x20,0x49,0x6E,0x66,0x6F,0x72,0x6D,0x61,0x74,0x69,0x6F, + 0x6E,0x20,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x08,0x0C,0x02,0x43,0x41,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06, + 0x13,0x02,0x55,0x53,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43, + 0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x23,0x30,0x21,0x06,0x09,0x2A,0x86, + 0x48,0x86,0xF7,0x0D,0x01,0x09,0x01,0x16,0x14,0x73,0x6D,0x69,0x6D,0x65,0x2D,0x74, + 0x65,0x73,0x74,0x40,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x82,0x01, + 0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00, + 0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xBB,0x8F, + 0xC3,0x01,0xD7,0x8A,0x62,0xE2,0xDD,0x26,0xE3,0x13,0x3E,0x61,0xC7,0x90,0xDE,0x98, + 0xCB,0x4A,0xC6,0x80,0xB3,0x36,0x99,0x8A,0xDE,0x6D,0xCF,0x60,0x7B,0x38,0x2E,0x86, + 0x0F,0x9E,0x9F,0xB0,0xCB,0x23,0xB1,0x52,0x0E,0x6E,0x70,0xD5,0x8D,0x56,0x32,0x36, + 0x35,0x7D,0x59,0x32,0xE6,0x3F,0x67,0x2F,0xC0,0x0F,0x2B,0x85,0x47,0x20,0x70,0x22, + 0xE5,0xB0,0x3C,0xF7,0xE3,0x4A,0x40,0xA5,0xB2,0x28,0xE5,0xB1,0x85,0x47,0x54,0x03, + 0xD1,0xB6,0x96,0x3E,0xDB,0x8D,0xD0,0x0E,0x5E,0x7A,0x65,0x2A,0x8A,0xBE,0xF7,0xB0, + 0x28,0x70,0x42,0x55,0x5A,0xAE,0xE6,0x58,0x91,0x20,0x5D,0x5B,0xFF,0x9B,0xF0,0x0C, + 0x49,0x94,0x55,0x68,0x46,0x34,0x2A,0xE4,0xA1,0x69,0x89,0xC8,0xB1,0xE7,0x07,0xB7, + 0xEC,0x2C,0x8A,0x65,0xF0,0xC6,0x51,0x3F,0x7C,0xC9,0x6F,0x42,0x71,0x15,0x30,0x9F, + 0xB5,0xA7,0xA5,0xD1,0xFE,0x2B,0x46,0x4F,0x3D,0xFD,0xCD,0xA8,0x1B,0x82,0x7B,0xA0, + 0x7B,0x9F,0x34,0x00,0xB7,0xC5,0x9F,0xCC,0x74,0xB4,0x35,0xC6,0x31,0x38,0x8D,0x91, + 0x79,0xE8,0xAF,0xCB,0xE4,0x17,0x78,0x11,0x7A,0x41,0xB1,0xF8,0x4D,0x2C,0xEE,0x7E, + 0x8D,0xEB,0x09,0x89,0xDC,0x74,0x2B,0xC1,0x25,0x57,0x3E,0x55,0x79,0x98,0x8B,0x5C, + 0xCF,0x05,0x38,0x69,0xF9,0x99,0x07,0x42,0x6D,0x99,0x1B,0x5E,0x89,0xBD,0xB6,0x4B, + 0x52,0x0F,0xDD,0xF9,0x67,0x53,0xDF,0xE2,0x25,0xBC,0x6C,0x72,0x19,0x6A,0x28,0xCE, + 0x6A,0xB4,0x22,0x93,0x20,0xDE,0xB6,0xF5,0x83,0x6A,0xC6,0x82,0x36,0x2B,0x02,0x03, + 0x01,0x00,0x01,0xA3,0x4B,0x30,0x49,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01, + 0xFF,0x04,0x04,0x03,0x02,0x05,0x20,0x30,0x16,0x06,0x03,0x55,0x1D,0x25,0x01,0x01, + 0xFF,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x04,0x30, + 0x1F,0x06,0x03,0x55,0x1D,0x11,0x04,0x18,0x30,0x16,0x81,0x14,0x73,0x6D,0x69,0x6D, + 0x65,0x2D,0x74,0x65,0x73,0x74,0x40,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03, + 0x82,0x01,0x01,0x00,0x7D,0xB4,0x4B,0x4B,0xE1,0xB3,0x29,0x22,0x72,0x7E,0x66,0xEA, + 0x78,0x51,0xBB,0x38,0xA0,0x44,0x6E,0xAE,0xB7,0xFE,0x43,0x24,0x78,0xAE,0x93,0x3B, + 0xF0,0x2B,0xAB,0x31,0x61,0x9F,0x6E,0x1F,0x89,0x0F,0x2C,0xD0,0xC4,0x29,0xE0,0x1C, + 0x4C,0x7B,0x96,0x82,0x0D,0x29,0x08,0x1F,0xDE,0x35,0xA2,0x12,0x0D,0xB4,0xA0,0x5D, + 0xE4,0xE8,0x38,0xC3,0x5C,0x99,0xFD,0x2E,0xE9,0x3B,0xC7,0xFC,0x67,0x3D,0xBD,0x1E, + 0x46,0x3A,0xDD,0xFB,0x24,0xF0,0x83,0x77,0x4F,0xA0,0x63,0x40,0x58,0x28,0x3C,0x32, + 0x3B,0xEB,0x8B,0x20,0x29,0xFD,0x22,0x4A,0xEC,0x3C,0x78,0xE2,0xD5,0xD3,0x54,0x35, + 0x8F,0x4D,0x48,0x61,0x2E,0xB6,0xC1,0xE5,0x3A,0x95,0xCD,0xBF,0x73,0xA2,0x1A,0x15, + 0xC3,0x24,0x0F,0xDB,0x86,0x08,0x55,0x01,0xBC,0x8C,0x4F,0x83,0x4E,0x90,0x55,0x84, + 0xF8,0x82,0xB1,0x1E,0x9F,0x70,0xD3,0xE8,0xE8,0xD3,0xDB,0x97,0xE0,0x66,0xAA,0x54, + 0x58,0x32,0x16,0x56,0xA3,0xF3,0x9B,0xCE,0xC4,0xA3,0x65,0x66,0x71,0xFD,0x20,0x87, + 0x3A,0x34,0x74,0xAB,0x6B,0x26,0xB8,0x18,0x8A,0x77,0xFF,0x77,0x21,0x6A,0xF0,0x38, + 0x12,0x74,0x45,0x1F,0x67,0x3D,0xBD,0xDF,0xBF,0x32,0x82,0x8E,0x4D,0xC5,0x3D,0x59, + 0x07,0xCD,0x1A,0x05,0xB6,0x96,0xD7,0x95,0xDB,0x44,0x81,0x59,0xD7,0x2A,0x88,0x0D, + 0x3C,0xD8,0xD5,0x2B,0x92,0xA8,0xC1,0x8D,0xDE,0x60,0x6F,0x98,0xE4,0x3C,0xB8,0xEC, + 0x52,0x2A,0x56,0x6E,0xF1,0x76,0x56,0x64,0x3D,0xD9,0x09,0xB9,0x4B,0x73,0xEF,0x11, + 0x78,0xFB,0xA6,0x9A, +}; + +/* Test identity for S/MIME policy (sign only, no encrypt) + */ +unsigned char Test_smime_signonly_p12[2761] = { + 0x30,0x82,0x0a,0xc5,0x02,0x01,0x03,0x30,0x82,0x0a,0x8c,0x06,0x09,0x2a,0x86,0x48, + 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x82,0x0a,0x7d,0x04,0x82,0x0a,0x79,0x30,0x82, + 0x0a,0x75,0x30,0x82,0x04,0xef,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07, + 0x06,0xa0,0x82,0x04,0xe0,0x30,0x82,0x04,0xdc,0x02,0x01,0x00,0x30,0x82,0x04,0xd5, + 0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x30,0x1c,0x06,0x0a,0x2a, + 0x86,0x48,0x86,0xf7,0x0d,0x01,0x0c,0x01,0x06,0x30,0x0e,0x04,0x08,0x03,0x00,0x56, + 0xda,0x33,0x28,0xb6,0xbc,0x02,0x02,0x08,0x00,0x80,0x82,0x04,0xa8,0x36,0xa9,0x2d, + 0xab,0xcc,0x17,0x76,0x6e,0x1c,0xf2,0x82,0xb1,0xc1,0xac,0x19,0xbe,0xb3,0x71,0x4f, + 0x1a,0xe6,0x0f,0x2d,0x7e,0xd4,0x66,0x0a,0x70,0x85,0x41,0xa5,0x92,0x06,0x02,0x71, + 0x0f,0x7a,0xed,0xef,0x52,0x96,0xd2,0x67,0xf4,0xa8,0x5b,0xde,0x6e,0xc6,0xdc,0xc6, + 0xe8,0x6e,0x86,0x11,0x94,0x60,0x0d,0xa1,0x24,0x57,0x1f,0x51,0xd8,0x7d,0x28,0xf9, + 0x10,0xcb,0x68,0x1b,0x32,0xe4,0xa3,0x60,0x7c,0xb2,0x2b,0x33,0x4e,0x23,0xec,0x60, + 0x4c,0xe0,0x1a,0x39,0x03,0x60,0xb7,0x09,0x4d,0xb7,0x8c,0x94,0x91,0x44,0xa7,0xc7, + 0x3b,0xd7,0xc5,0xc5,0x0f,0x4a,0x54,0xe5,0xee,0x41,0xd5,0x32,0xf2,0xfc,0x7a,0x4d, + 0x68,0x5d,0xfc,0xe9,0xab,0xa0,0x74,0xb9,0x6f,0x68,0xc4,0x68,0xa1,0x91,0x5d,0x74, + 0x2b,0x06,0xfc,0xa7,0x93,0x2c,0xc3,0x8e,0xaf,0x12,0x84,0x09,0x1f,0xa8,0xd7,0xb3, + 0xf2,0x13,0x33,0xdf,0xd2,0xa5,0x34,0xa5,0x08,0x73,0xea,0x8f,0xc3,0x88,0xd4,0xa1, + 0xce,0xa9,0x56,0xc4,0x4f,0xc9,0x48,0xfb,0x84,0x26,0x16,0xc8,0x1a,0x15,0x6d,0x10, + 0x8e,0x4e,0x85,0xfc,0x8b,0xb7,0xfc,0x69,0x6a,0x79,0xc0,0xff,0xed,0xfd,0x7b,0x0b, + 0x7f,0x5b,0x8d,0x89,0x4e,0xb6,0x25,0x0e,0x04,0x42,0xdb,0x15,0x7b,0xbc,0x7b,0x75, + 0x91,0x12,0x7c,0x0f,0x22,0xfd,0xd4,0x4d,0x3c,0x9c,0x6c,0x10,0x40,0x9e,0x3e,0x0b, + 0xfd,0x2e,0x2d,0x23,0x27,0x96,0x86,0x85,0x44,0xdd,0xc4,0x44,0xbf,0x74,0x09,0x2f, + 0x90,0x48,0x3d,0x8a,0x05,0xbe,0x44,0xe5,0x75,0x1f,0x4e,0xbc,0x91,0xfd,0xf5,0x1a, + 0xde,0xd4,0x99,0xf4,0xbe,0x2f,0x28,0xbf,0x47,0x49,0x90,0xb5,0xea,0xd6,0x48,0xcb, + 0x7b,0xde,0xea,0x3d,0x07,0x8d,0xf4,0x7c,0xd7,0x4d,0xcb,0xc1,0xcb,0xa3,0x30,0x2f, + 0x7c,0x59,0x09,0xad,0xb3,0x27,0x66,0x2a,0x87,0x51,0xd7,0x7b,0xbb,0xb1,0x6d,0x4e, + 0x0e,0x1a,0x6a,0x7a,0xf8,0x31,0x99,0xa8,0x1c,0x06,0x1a,0x4e,0x83,0xa8,0xac,0xaf, + 0x72,0xdb,0x89,0x1b,0xe1,0x9d,0x52,0x22,0x94,0xaf,0x6a,0xe0,0x5c,0x60,0xd5,0xf2, + 0x6a,0xde,0x1f,0x51,0xb0,0x19,0x13,0xff,0xb9,0xfe,0x15,0xeb,0x4a,0x5c,0x44,0xe6, + 0xbd,0x3d,0xbd,0xdc,0xb2,0xa8,0x96,0xa2,0x05,0x7e,0xdc,0x39,0x15,0x7a,0xc9,0xdc, + 0xb3,0x2b,0xa2,0x1c,0xe1,0x78,0xfb,0x5b,0x12,0x35,0xc2,0x05,0xed,0x59,0xa2,0xf1, + 0x8d,0x5b,0xe2,0xf8,0x95,0xc7,0xdd,0x20,0xf9,0xcc,0xfd,0x43,0xbe,0x03,0x0f,0xdb, + 0xa1,0x21,0x7b,0x86,0x0e,0x0b,0x26,0xbd,0x38,0x10,0x62,0xbc,0x5c,0x43,0x48,0x6f, + 0xbc,0x6c,0x68,0x83,0xd4,0x54,0x5b,0x80,0x25,0x13,0x69,0x18,0xce,0x8e,0xe9,0x3f, + 0xfb,0x81,0x51,0x92,0x19,0x3f,0x4b,0x41,0x53,0x39,0x3e,0xa2,0xef,0x90,0x59,0x5c, + 0x30,0x22,0x36,0xed,0x78,0x78,0xc5,0x70,0x9c,0x8b,0x96,0x8d,0xe8,0x7a,0x9b,0x27, + 0xdc,0x9b,0x4f,0x2b,0x30,0x86,0x27,0x95,0x70,0x8f,0xc0,0xd5,0xd4,0x79,0x9f,0x0f, + 0x38,0x49,0x1d,0xe9,0x76,0xcf,0x6c,0x34,0x06,0xc0,0xfa,0xa0,0xab,0x41,0x1c,0x26, + 0x04,0x18,0x0f,0xa8,0x45,0xf5,0xdc,0x82,0x5d,0x8a,0xe6,0x2b,0x84,0xe9,0xaa,0xa2, + 0xbd,0xf4,0xc6,0x94,0xa6,0xbb,0x6f,0x35,0x3c,0x5f,0x9a,0x45,0xd3,0x3e,0x6b,0x75, + 0x54,0x10,0x5a,0x6f,0x0c,0x26,0xe7,0xb1,0x92,0x6c,0x93,0xf1,0xce,0x02,0x97,0xbe, + 0xf8,0x76,0xbc,0x9b,0xff,0x09,0xe2,0x8a,0x62,0xdc,0x19,0xfa,0x33,0x94,0x07,0x4b, + 0x7d,0x62,0xe3,0xca,0xc6,0x1e,0xc4,0x18,0xd7,0xa8,0xbb,0x79,0xd1,0x4e,0x2e,0x37, + 0xa4,0x02,0x06,0x80,0xa4,0xed,0xbf,0x3e,0x8b,0xc7,0xcd,0xf2,0xa5,0x8f,0x68,0x1e, + 0xb2,0x72,0xc2,0xa2,0xa7,0x8d,0x03,0x51,0x0f,0xe2,0x7a,0x04,0x03,0x83,0x2f,0x71, + 0x16,0x85,0x7e,0xf3,0x29,0xc7,0x31,0x27,0x24,0xae,0x8b,0x08,0xe7,0x6b,0x7d,0x5f, + 0x27,0xdd,0xdb,0x28,0x63,0x65,0xbb,0x2a,0x6e,0x63,0xc4,0xa4,0x90,0x36,0x8e,0xc4, + 0x8b,0x55,0x6f,0x99,0x4f,0xf3,0x63,0xef,0xc7,0x3a,0xd5,0x55,0xf3,0x98,0xaa,0x9c, + 0x20,0x9d,0x9b,0x07,0x44,0x92,0x27,0x2c,0xc5,0x22,0x78,0x85,0x66,0x71,0xd5,0x0f, + 0xea,0xa7,0xdc,0x0c,0xad,0x07,0x2a,0xa5,0x34,0xca,0xbc,0x8e,0xff,0xfd,0x0b,0xb0, + 0x9d,0x21,0x16,0x9d,0xfa,0x21,0xaf,0xec,0x25,0x6a,0xd7,0x7d,0xff,0xe6,0x73,0xe3, + 0x6c,0x4e,0x9c,0xe0,0xeb,0x0c,0x56,0x32,0xa9,0xbb,0x48,0xe5,0xa7,0x4b,0x59,0x1d, + 0x70,0x31,0xf2,0x79,0x88,0x50,0xc4,0x59,0x01,0x3c,0xc2,0x61,0xbe,0xe7,0xbc,0xc0, + 0x6f,0xb4,0x27,0x90,0xcd,0x4f,0x44,0x60,0x9f,0x02,0x5a,0x68,0x81,0xb6,0x6f,0x78, + 0x10,0xd3,0x3e,0xb3,0xb4,0xc5,0x6f,0xa6,0x3e,0x77,0x30,0x29,0xd7,0xa7,0xda,0x5f, + 0xb4,0x3e,0x3f,0xf9,0xb3,0x04,0xd8,0xe5,0x75,0xc5,0x1e,0xcf,0xa6,0x85,0x4c,0x57, + 0xf6,0xbb,0x8f,0xda,0x80,0x02,0x4b,0x79,0x0f,0x94,0xed,0x98,0xdb,0x64,0x8d,0x8f, + 0x8e,0x90,0x5b,0x31,0x80,0x1b,0x50,0x8b,0x99,0x7b,0x23,0x94,0xf2,0x1e,0x8e,0xe6, + 0xce,0x7f,0x2f,0x16,0x64,0x7f,0xdb,0x16,0x08,0x97,0x78,0x5c,0x4d,0xef,0x9c,0x63, + 0x0f,0x37,0x14,0x58,0x68,0x57,0x29,0x42,0xd3,0x4d,0x97,0x62,0xe8,0x08,0xe4,0x60, + 0x87,0x07,0x73,0x11,0x21,0x5e,0x8c,0x97,0x78,0xdb,0x2f,0x81,0xb3,0xa0,0xfd,0x17, + 0x0b,0xf0,0x29,0x88,0x1a,0x39,0xec,0x0c,0xfb,0x30,0x0d,0x0a,0x9a,0x60,0xe2,0xaf, + 0xf9,0xb3,0x9c,0xdd,0xa6,0x2e,0x7c,0x90,0xf7,0x31,0x3c,0x35,0xe8,0x2f,0xdd,0x54, + 0xdf,0x45,0x54,0xcf,0xdd,0xfc,0xf6,0x36,0x3f,0x36,0x8a,0x23,0x60,0xd0,0x4b,0xe2, + 0x0b,0xb5,0x90,0xc4,0xbe,0xaf,0xa1,0xd6,0xc2,0x69,0x0a,0x5b,0x74,0xae,0xa5,0xb3, + 0x12,0xaf,0x06,0x98,0xfe,0xc3,0x52,0xbb,0xf0,0xde,0x67,0xd4,0x8d,0x2a,0xf4,0x35, + 0x71,0xaf,0x5e,0x24,0xc4,0x2a,0x48,0xa6,0x42,0x32,0x10,0xb0,0x09,0x74,0x83,0x9e, + 0x3c,0x50,0x15,0x74,0xeb,0x2e,0x29,0x64,0x3e,0xe5,0x6e,0x13,0xc0,0x5b,0x9b,0x5b, + 0x1f,0x8f,0xe5,0x49,0x25,0x36,0x57,0x90,0x81,0xce,0x27,0xf4,0x8d,0x42,0x5d,0x04, + 0x2c,0x44,0x7a,0xeb,0xe0,0x10,0x4e,0xba,0x21,0xf3,0x1d,0xdf,0xb0,0xe4,0x56,0xf9, + 0x5a,0xbe,0xfe,0x1a,0x6d,0xeb,0x2d,0xe2,0x93,0x5f,0xa1,0x74,0x86,0x0c,0x64,0x68, + 0xf4,0x67,0xf3,0xe0,0xfa,0xe6,0x9d,0x6a,0xfe,0xb6,0x5f,0x58,0x2d,0xa7,0x77,0x07, + 0x58,0xc8,0x79,0x51,0xa5,0x8e,0xbd,0x4c,0x61,0x80,0x9d,0x91,0xda,0x32,0xee,0x09, + 0x02,0xca,0x14,0xf8,0xfa,0x08,0xf3,0x4a,0xf5,0x6a,0x50,0xcd,0x98,0x21,0xbd,0xb4, + 0x5e,0x4c,0x20,0x8f,0x0a,0x94,0xd0,0x6c,0x96,0xf1,0xa2,0xff,0xf6,0x1f,0x15,0xd5, + 0x1d,0x64,0x92,0x82,0xaf,0x01,0xca,0xa0,0x38,0xe9,0x80,0xea,0xe9,0xb3,0xdf,0xed, + 0xa8,0x03,0x31,0x5e,0x05,0x12,0xcd,0x29,0x33,0x59,0xf9,0xf2,0xbc,0x7f,0x05,0x86, + 0x9e,0x96,0xc4,0x52,0x2d,0x1f,0x1e,0x29,0x05,0x68,0xde,0xf1,0x3c,0x2d,0x65,0x97, + 0x7c,0xde,0x28,0x88,0xab,0xd3,0x12,0x5e,0x3d,0x15,0x45,0xc3,0x05,0x47,0x13,0x03, + 0x65,0xad,0x49,0x5f,0x8a,0x15,0xf5,0x27,0xc1,0x13,0xa5,0x16,0x85,0x13,0x11,0xf6, + 0x71,0x03,0x2c,0xaf,0xce,0xc4,0x36,0x17,0x0b,0xfd,0x4a,0x4c,0xce,0x9e,0x0d,0xcc, + 0xa5,0xa3,0x30,0xce,0x61,0x30,0x82,0x05,0x7e,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7, + 0x0d,0x01,0x07,0x01,0xa0,0x82,0x05,0x6f,0x04,0x82,0x05,0x6b,0x30,0x82,0x05,0x67, + 0x30,0x82,0x05,0x63,0x06,0x0b,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x0c,0x0a,0x01, + 0x02,0xa0,0x82,0x04,0xee,0x30,0x82,0x04,0xea,0x30,0x1c,0x06,0x0a,0x2a,0x86,0x48, + 0x86,0xf7,0x0d,0x01,0x0c,0x01,0x03,0x30,0x0e,0x04,0x08,0xb1,0xca,0xab,0x81,0x75, + 0x32,0xf4,0x2c,0x02,0x02,0x08,0x00,0x04,0x82,0x04,0xc8,0xc8,0xe4,0x07,0x32,0x15, + 0x32,0xb1,0xce,0xca,0xa4,0x03,0x84,0x91,0xbc,0x74,0x45,0x63,0x46,0xa8,0x20,0xcf, + 0xa2,0x2d,0x0e,0xfb,0xf7,0xfa,0x3d,0xad,0x72,0xa4,0x97,0xc9,0x14,0xb9,0x55,0x00, + 0x5e,0xb6,0x17,0xf9,0xba,0xe4,0xf4,0x4b,0x36,0x31,0xbb,0xfc,0x4a,0xb3,0xfe,0xd7, + 0xf5,0xd0,0xe8,0x63,0x43,0x6b,0x7e,0xfe,0xcc,0xa8,0x2f,0x8a,0x8a,0xf3,0xfb,0x23, + 0x0c,0xed,0x03,0x20,0x66,0xe2,0x90,0x9b,0x68,0x71,0xfb,0x44,0x68,0xe5,0x87,0x97, + 0x0a,0x97,0x63,0x53,0x3c,0x07,0x86,0x63,0xb2,0x0f,0x8e,0xe8,0xb5,0x0a,0x0c,0xe2, + 0x12,0x6d,0x33,0xa1,0xa5,0xc5,0xc4,0xab,0xf7,0x23,0x35,0x53,0x69,0xc1,0x37,0x28, + 0x86,0x42,0xa1,0x9c,0xe4,0xf5,0x2e,0x8c,0x92,0x1a,0xeb,0x67,0x10,0xcb,0x24,0xb5, + 0xd6,0x75,0x33,0x7a,0x5f,0x20,0x8f,0x1e,0x13,0x4c,0x4c,0xa1,0x53,0x87,0x8c,0xad, + 0x04,0x28,0xe0,0x21,0x65,0xf0,0x1b,0x62,0x15,0x95,0x36,0xd1,0x21,0xe1,0x50,0x0d, + 0xe4,0xed,0x07,0x8d,0x37,0xd3,0x06,0x2d,0x88,0x46,0x0f,0x54,0x16,0x19,0xac,0xc7, + 0x0b,0xcf,0x83,0xe9,0x49,0xbc,0x9e,0x7f,0x38,0xed,0xe4,0xf1,0x84,0x6a,0x0e,0xd1, + 0x92,0x39,0x61,0x36,0xa3,0x12,0xfc,0x31,0x4c,0xde,0x9d,0xcf,0xa0,0x90,0xd0,0x17, + 0x29,0x51,0x93,0x04,0xb1,0xe9,0xab,0x5e,0x5d,0x9e,0x2f,0x99,0xe9,0x53,0x95,0x27, + 0x39,0x5a,0x48,0x64,0x56,0x7b,0x97,0x9e,0x5d,0xf0,0xc9,0xd5,0x6b,0x57,0x0e,0xdc, + 0x69,0x7f,0x2d,0x6e,0xd7,0x3a,0xd8,0x31,0xcb,0x14,0xf4,0x3b,0x33,0xaf,0x62,0x95, + 0xbe,0x6b,0xe9,0xd7,0x2a,0x17,0x6c,0x9d,0x65,0x6c,0x2a,0xf5,0x38,0x39,0x95,0x8c, + 0xc6,0x97,0xc9,0xa1,0xe8,0x07,0x09,0x62,0x71,0x92,0xc2,0x4f,0xb1,0x25,0x83,0x90, + 0x44,0x54,0xcd,0x5c,0x3d,0x7b,0x0f,0xf1,0xdf,0x00,0xe2,0x4a,0x0e,0xd4,0xfe,0xa8, + 0x3e,0x81,0x4e,0x6c,0x92,0x49,0xa0,0x49,0xc4,0x3a,0x80,0x78,0x1d,0xb2,0x43,0xbd, + 0x21,0x5a,0xe0,0xbd,0x99,0xe0,0x77,0xd1,0xe6,0x2d,0x73,0xd4,0x4b,0xa9,0x07,0xcc, + 0xbd,0x12,0xa2,0x06,0x08,0x60,0xbd,0x99,0xfd,0x9f,0xcc,0x23,0x6f,0xd2,0xd0,0xdf, + 0xbe,0x63,0xef,0xe9,0x15,0x24,0x54,0x55,0x73,0x85,0x9e,0x26,0x62,0xd8,0xc1,0x14, + 0xce,0xcc,0x3b,0xf6,0x87,0x68,0xfa,0x3d,0x6e,0xb1,0x1c,0x5e,0x4e,0x05,0xe4,0xbc, + 0x95,0x1b,0xb4,0xd5,0xa1,0xfb,0xe2,0x25,0x48,0xe9,0x63,0x36,0xdf,0x33,0x8e,0xed, + 0x1d,0xdf,0x63,0x1a,0xfd,0xb6,0xc9,0x09,0x3a,0xc2,0x9f,0x1d,0xd4,0x45,0x00,0x2a, + 0x86,0x09,0x9c,0x30,0x4e,0xc0,0x81,0x9c,0x30,0x14,0x6b,0x4c,0x52,0xfd,0xca,0x36, + 0xef,0x99,0x2e,0xd1,0x86,0xc0,0xdf,0x9d,0x6a,0xb5,0xfa,0xa3,0x12,0xe0,0x5f,0x73, + 0xb4,0xfd,0xd7,0x59,0x23,0x6d,0xa8,0x77,0x8f,0x65,0x4a,0x65,0x46,0x5e,0x56,0xe0, + 0x23,0xbb,0xc5,0x38,0xff,0xf0,0x4a,0x2e,0xab,0x20,0x75,0x02,0xc5,0x85,0x7e,0x6b, + 0x3f,0xa4,0x00,0xf5,0x39,0x88,0xd1,0x9c,0xc9,0xe9,0x77,0xeb,0x8d,0xce,0x2e,0x74, + 0x5c,0xb9,0x6c,0xb0,0x6d,0x9e,0x5f,0x7b,0x93,0x7b,0x22,0x0e,0xb3,0x55,0x65,0xca, + 0x64,0xec,0xc0,0xa5,0xff,0x19,0x0a,0x2d,0x1c,0xc9,0xd3,0xe3,0xb6,0x18,0xe3,0x8c, + 0x83,0xd8,0x43,0x01,0xf8,0x6e,0x64,0x07,0xb9,0xac,0x20,0x29,0xeb,0x36,0xf5,0x04, + 0xd8,0x41,0xeb,0x8d,0x23,0x39,0x21,0x83,0xb6,0x82,0xbd,0x18,0xac,0xc6,0xb7,0x5b, + 0xf7,0x4d,0x80,0x7a,0xf6,0xdc,0x40,0x04,0x9c,0xec,0xb2,0xea,0xd6,0xf1,0x5d,0xa4, + 0x62,0x43,0x05,0x0b,0xba,0x29,0x36,0xeb,0xbd,0x23,0xb6,0x02,0xf6,0x62,0x4e,0xf3, + 0xff,0xee,0x3d,0x92,0xbe,0x65,0xc0,0x4a,0xb1,0x60,0x60,0x46,0x23,0x85,0x67,0x71, + 0xe4,0x25,0x6b,0x58,0xdc,0x91,0x4c,0x05,0x54,0xfa,0x4b,0xa5,0x60,0x82,0x3e,0xa2, + 0x4f,0x3e,0xc7,0xe5,0xf0,0x2b,0xa6,0x9d,0x55,0xdc,0x98,0x46,0xd7,0xec,0x3e,0x47, + 0x5b,0x4c,0x02,0x46,0x9c,0x2d,0x25,0x6d,0x55,0x25,0xfc,0x67,0xc2,0xe9,0xbf,0xa1, + 0xb0,0x5b,0x97,0xf8,0x4f,0xae,0xdf,0xab,0x50,0xa0,0x0b,0x5b,0xc8,0x78,0xcc,0xcd, + 0x50,0x55,0xc6,0x46,0x21,0x01,0x7e,0xac,0x38,0xe2,0x10,0x34,0x0b,0x22,0x64,0xa7, + 0xa5,0xe4,0x7f,0x60,0x51,0x75,0xdf,0x32,0x87,0xd4,0xa6,0x06,0x4f,0x8c,0x60,0x15, + 0xd0,0x1f,0xc1,0xbb,0xa4,0xca,0x4a,0xac,0x80,0xf1,0x7f,0x3a,0xfc,0x4a,0xe7,0x4e, + 0xb8,0xc2,0xdb,0x84,0xd8,0x5c,0xeb,0x44,0x23,0xec,0x9e,0x92,0x72,0xb7,0x45,0x02, + 0xee,0x52,0x08,0x47,0xb6,0x09,0x5d,0xdc,0xe5,0x26,0xae,0x61,0x42,0x77,0x13,0x85, + 0xa2,0x4f,0xf0,0xb0,0x46,0x88,0x2a,0x3c,0x09,0x98,0x89,0xe3,0xf1,0x69,0x89,0x0a, + 0x76,0xd9,0x8e,0x7e,0x0c,0xd7,0xcc,0x16,0xda,0xfd,0xfb,0x96,0x2b,0xd7,0xe2,0x8d, + 0x54,0x3f,0x75,0x2f,0x66,0x6b,0x72,0x8f,0xbd,0x5c,0x3c,0x05,0xa7,0xe4,0x11,0x06, + 0xcf,0x4a,0xd6,0x32,0x95,0x42,0x71,0xc6,0x2b,0xf9,0x8b,0xe6,0xda,0x0c,0x37,0xa8, + 0xed,0x7b,0x71,0x9a,0xea,0x8e,0xa1,0xbd,0x27,0x8f,0x45,0x00,0x48,0x40,0xba,0xf4, + 0x41,0x0e,0xb6,0x98,0x88,0xed,0xc7,0x3d,0xbd,0x59,0x52,0xc4,0xeb,0xbc,0xb8,0x0b, + 0x22,0x5e,0x68,0x79,0xc9,0x71,0x3d,0xd7,0x31,0x4c,0x55,0x40,0xcd,0x1f,0x41,0x0c, + 0xd7,0xb0,0x02,0x47,0xb0,0x9f,0xfa,0xb2,0x60,0xd4,0x3c,0x64,0xe8,0xc5,0xae,0xe8, + 0x12,0xad,0x84,0xc3,0xe1,0xfd,0x1e,0x20,0x6f,0x20,0x2e,0xbe,0xa9,0xd4,0x30,0xb6, + 0x6c,0xa5,0xf0,0x03,0x75,0xae,0x1b,0xb1,0x15,0x36,0x8d,0xba,0x0f,0x1e,0xb7,0x74, + 0x8b,0xa4,0x41,0xfd,0x13,0x7a,0xa9,0x16,0x22,0x54,0xe4,0x60,0x38,0x52,0xb6,0x60, + 0x8b,0x7f,0x7a,0xb9,0x2a,0xb0,0x28,0x63,0x71,0xeb,0x29,0x52,0xab,0x66,0x70,0x66, + 0x72,0x12,0xe9,0x4d,0xf4,0x01,0xba,0x88,0xb6,0x15,0xe1,0xb9,0x67,0x10,0x0a,0x59, + 0xc8,0x12,0x1b,0x81,0x6a,0x4c,0x79,0x0f,0x94,0xd7,0xa7,0xa8,0x4c,0x25,0xf2,0xd3, + 0x4d,0x23,0x6c,0x9d,0x65,0x81,0x75,0x72,0xd9,0xca,0xa5,0x32,0xa5,0x9a,0xcc,0xef, + 0xfe,0xb2,0x30,0x2f,0x6c,0x17,0x53,0xac,0x9d,0xc6,0xd5,0x6a,0x85,0x35,0xfa,0x17, + 0xe4,0xfa,0xb8,0x93,0x18,0xc6,0x82,0x42,0xa4,0xaf,0x72,0x7d,0xd4,0xbd,0xf2,0xe3, + 0x7b,0x6e,0x56,0x2d,0x25,0xeb,0xeb,0x53,0x4e,0x34,0xaa,0x86,0x5d,0xcb,0xe1,0xd6, + 0x22,0x4d,0x74,0xee,0x37,0xbd,0x8d,0x43,0xf8,0x3b,0xdb,0xf6,0x9a,0xef,0xe9,0x7f, + 0x3d,0x7f,0x74,0xe6,0x25,0xbb,0xf9,0x4a,0xf8,0x20,0x07,0x94,0x30,0x43,0x48,0xab, + 0x0e,0x1d,0x97,0xd6,0x01,0xa1,0x5b,0x9e,0x92,0xa2,0xeb,0xbe,0x22,0xe8,0x2f,0xb0, + 0x31,0x24,0xb4,0xb5,0x2b,0x73,0xf2,0xdd,0x29,0x5b,0xfd,0x1b,0x18,0x3e,0x3a,0xe6, + 0xa3,0x4b,0x0b,0x19,0xe3,0x4c,0x83,0x8b,0xe3,0x5f,0x94,0xd7,0x5a,0x33,0xb3,0x3d, + 0x3c,0x3f,0xf2,0x16,0x39,0x84,0x48,0x6b,0xc4,0x21,0x87,0x68,0xa7,0xe7,0x94,0xb4, + 0x4f,0x36,0x97,0x28,0x9a,0xbd,0xd4,0x5c,0xf5,0x89,0x5a,0x46,0xf4,0x4b,0x1f,0xe9, + 0x5c,0x48,0xae,0x51,0xe5,0x6f,0xb3,0xea,0xe2,0x6e,0x4e,0x72,0x2d,0x87,0x8c,0x5d, + 0x07,0x3e,0xfb,0x1c,0x95,0x88,0x9e,0xde,0xec,0xc2,0xd1,0x7c,0xef,0x6d,0x4e,0x19, + 0x0c,0xbc,0x6f,0x9f,0xd1,0xa0,0x8e,0x71,0xc8,0x13,0xe6,0xc9,0x21,0xcb,0x31,0x77, + 0x13,0x38,0x14,0xe9,0x25,0xea,0x5c,0x35,0x48,0x06,0x2c,0x4d,0xbe,0x53,0x76,0x51, + 0x1d,0x7a,0x88,0x31,0x62,0x30,0x3b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01, + 0x09,0x14,0x31,0x2e,0x1e,0x2c,0x00,0x54,0x00,0x65,0x00,0x73,0x00,0x74,0x00,0x2d, + 0x00,0x53,0x00,0x69,0x00,0x67,0x00,0x6e,0x00,0x4f,0x00,0x6e,0x00,0x6c,0x00,0x79, + 0x00,0x20,0x00,0x28,0x00,0x53,0x00,0x2f,0x00,0x4d,0x00,0x49,0x00,0x4d,0x00,0x45, + 0x00,0x29,0x30,0x23,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x15,0x31, + 0x16,0x04,0x14,0x6f,0x7c,0x20,0x36,0xbe,0x29,0x2b,0xca,0x1a,0xbf,0x51,0xb7,0x15, + 0x8a,0xf9,0x7c,0x2b,0x4e,0x04,0xe8,0x30,0x30,0x30,0x21,0x30,0x09,0x06,0x05,0x2b, + 0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14,0x0e,0xb5,0xcf,0xf5,0x4e,0x2b,0x2c,0x5d, + 0x2e,0x43,0xc9,0x60,0xf2,0x16,0x0f,0xd2,0xe6,0x50,0x93,0x0b,0x04,0x08,0xf0,0x18, + 0xb1,0xdb,0x61,0x97,0x53,0xcb,0x02,0x01,0x01 +}; + +/* Test identity (PKCS12 data) + */ +unsigned char Test_p12[2721] = { + 0x30,0x82,0x0a,0x9d,0x02,0x01,0x03,0x30,0x82,0x0a,0x64,0x06,0x09,0x2a,0x86,0x48, + 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x82,0x0a,0x55,0x04,0x82,0x0a,0x51,0x30,0x82, + 0x0a,0x4d,0x30,0x82,0x04,0xd7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07, + 0x06,0xa0,0x82,0x04,0xc8,0x30,0x82,0x04,0xc4,0x02,0x01,0x00,0x30,0x82,0x04,0xbd, + 0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x30,0x1c,0x06,0x0a,0x2a, + 0x86,0x48,0x86,0xf7,0x0d,0x01,0x0c,0x01,0x06,0x30,0x0e,0x04,0x08,0xba,0x25,0x0b, + 0x36,0xab,0xc2,0xe7,0x34,0x02,0x02,0x08,0x00,0x80,0x82,0x04,0x90,0xe2,0x74,0x80, + 0xf1,0xf9,0xff,0xb5,0x9a,0xa4,0xe2,0x43,0x70,0x41,0xa1,0x90,0x19,0xb2,0xd5,0x8e, + 0x00,0x4b,0xfc,0x07,0xd6,0x72,0x99,0x9c,0x89,0xa8,0x0c,0x97,0x4a,0x9c,0x10,0x30, + 0x11,0x80,0xc1,0x42,0xda,0x56,0xdd,0x1b,0xfa,0x9e,0x5f,0x85,0x72,0x1d,0xde,0xdf, + 0x78,0x8f,0xd4,0x69,0xf0,0x39,0xfb,0xf1,0xf4,0x96,0xc1,0x2d,0x97,0x20,0x98,0xe2, + 0x38,0xd0,0xe1,0xda,0x01,0x59,0x64,0x71,0xd6,0xd9,0xa2,0x46,0x38,0x87,0x54,0x4c, + 0x4d,0x3f,0x8a,0x9b,0x75,0xf4,0x98,0xec,0xf1,0xe4,0x01,0x60,0x8d,0x04,0x54,0x28, + 0x4c,0xbb,0x90,0x08,0x98,0xb1,0x6b,0x61,0xe3,0x03,0xcd,0x00,0x19,0x87,0xa2,0xc2, + 0xb5,0x7b,0x57,0xd4,0x22,0x77,0xd1,0x68,0x9a,0xfe,0xe3,0x43,0xef,0x2b,0xb6,0x11, + 0x7c,0x63,0x9c,0x28,0xab,0x86,0xdf,0x1b,0x95,0x58,0x54,0xa5,0x3d,0x18,0xb0,0xad, + 0x20,0x76,0x92,0xf5,0xef,0x20,0x8a,0x0c,0x21,0xdb,0x83,0x15,0x1e,0xa5,0x6f,0xeb, + 0xd3,0xc8,0x40,0x14,0x7f,0x69,0x46,0x73,0x20,0x60,0x2b,0x3e,0x27,0xd7,0xb9,0x33, + 0x8c,0xe6,0x43,0xc8,0xf6,0xa5,0x53,0xa7,0x36,0x03,0x3d,0xa9,0xdd,0x85,0x59,0xde, + 0x70,0xc2,0x65,0x38,0x06,0x04,0x00,0x01,0xcc,0xed,0xdf,0x1f,0xab,0x83,0xed,0xeb, + 0xc0,0x3d,0x33,0x4e,0x99,0x22,0xcc,0x63,0xc7,0x14,0x9c,0x50,0x60,0x38,0xc3,0xa5, + 0xe2,0xfe,0x78,0x04,0x01,0x0f,0x1d,0xde,0xe0,0x3e,0x86,0x05,0x02,0xfc,0x3c,0x7f, + 0x38,0xf7,0xb0,0xd0,0xbb,0x0c,0xe1,0x1b,0xdc,0x6e,0xb0,0x12,0x7a,0xae,0x13,0x5d, + 0x80,0xd7,0x0e,0xb2,0xe8,0x5d,0x2a,0xbf,0x2e,0x67,0xc3,0xd8,0x8d,0xa1,0x9f,0x2c, + 0xbb,0xc4,0x33,0xca,0xf4,0x43,0x89,0xbd,0x4e,0x19,0xa5,0x71,0x1c,0x5f,0x6b,0x4d, + 0xd4,0xf7,0xdd,0xd3,0xfd,0x13,0xdc,0xde,0x76,0x2c,0x38,0x8e,0xef,0xb2,0x00,0x9c, + 0xfd,0xa5,0x52,0xa0,0xec,0xa3,0xfe,0xcc,0x80,0xee,0x8d,0xed,0x25,0xf9,0xa8,0x30, + 0x99,0x04,0x6f,0x61,0x4e,0x2f,0x08,0x6c,0xa5,0xe2,0x5b,0x15,0xae,0x58,0xbd,0xbd, + 0xa1,0x36,0xa9,0xa1,0xb5,0xed,0x1e,0x95,0xf5,0x90,0x35,0xa2,0x5c,0xc3,0x9b,0x1f, + 0x98,0x5d,0xdd,0xcf,0xd4,0x08,0xd4,0xb7,0x90,0x58,0xb8,0xc7,0x9d,0x60,0x25,0x57, + 0xa1,0x39,0xc3,0x2c,0x75,0x07,0xd9,0x4c,0xdd,0x2f,0xc8,0xf5,0x7a,0xee,0x06,0xcf, + 0xdc,0xc3,0x22,0x89,0x37,0xa0,0x9f,0x9f,0x45,0x46,0x2d,0x98,0xac,0xdb,0x33,0x80, + 0xb3,0x29,0x76,0x6f,0x1b,0x9e,0x71,0xc7,0x41,0x9f,0x12,0x00,0x4e,0x09,0x0c,0xab, + 0xc7,0xda,0x58,0x60,0x6c,0x0a,0x6e,0x09,0xbe,0x2e,0x2f,0x4f,0x0a,0x63,0x38,0x60, + 0xca,0xc9,0xe9,0x67,0x70,0xcb,0x4e,0xed,0xa9,0xd3,0xd4,0xbc,0xa2,0x69,0x32,0xcb, + 0x62,0x69,0xa0,0x32,0x36,0x09,0x96,0x1f,0xdc,0xea,0x73,0xe6,0x84,0x3d,0x84,0xbf, + 0x62,0x82,0x4d,0x23,0xb1,0xc5,0x64,0xa8,0x57,0x07,0x37,0x3c,0x54,0x63,0x61,0xe1, + 0x24,0xeb,0xd9,0xdd,0x2e,0xb8,0x8f,0xbd,0xa9,0x3e,0x55,0xd7,0xea,0xfb,0x5a,0xc9, + 0x68,0xd9,0x9d,0x0e,0x75,0xb1,0x86,0xf0,0xa4,0xb2,0x3f,0xd7,0x77,0x7d,0x5f,0x5f, + 0x87,0x00,0x07,0x24,0x16,0x20,0x0a,0x5b,0x4b,0x52,0xb6,0x1a,0x39,0xd6,0x32,0x43, + 0x7a,0xb4,0xf8,0x81,0x59,0xec,0xbd,0x97,0xb6,0xe7,0x41,0x2b,0x68,0x19,0xb4,0x06, + 0xec,0xbf,0x34,0x36,0xa2,0x9a,0x7f,0xa0,0xa9,0x16,0x9e,0x98,0x40,0x37,0x22,0x21, + 0x3e,0x43,0xe3,0xaf,0x30,0x6e,0x50,0xf5,0xba,0xe4,0x00,0x14,0x25,0x08,0xbf,0xa8, + 0xdf,0x71,0x4b,0x3d,0x27,0x8b,0x44,0xbb,0xed,0x2c,0xcb,0x75,0x6a,0x1d,0xb8,0x8b, + 0xe9,0xe2,0x99,0x0b,0xe5,0xcd,0x0e,0x24,0xa8,0x68,0x91,0xca,0xc9,0x48,0x5c,0xdb, + 0x60,0xa0,0x43,0x52,0x82,0x74,0x17,0xd7,0x47,0x91,0xd7,0x92,0x04,0xba,0x3f,0xe4, + 0x54,0xc9,0x41,0xb9,0xa4,0xcf,0x2f,0x0f,0x7e,0xce,0xa2,0x82,0xe7,0xed,0x3a,0x48, + 0x83,0xdb,0xdb,0x9f,0x1d,0xa2,0x44,0x56,0xf0,0x76,0x7a,0x20,0x6b,0xd7,0x8e,0xc1, + 0x34,0x67,0x28,0xc3,0x1e,0x8d,0x03,0xf0,0x91,0x87,0x83,0xeb,0x26,0xa3,0x38,0xe0, + 0xc6,0xd9,0x1d,0x3a,0xa6,0xe4,0xf0,0x31,0xe9,0x23,0xce,0x6c,0x0a,0xe4,0xab,0x3c, + 0x3c,0xf2,0x68,0x8a,0x41,0xda,0x19,0x5b,0x40,0x9c,0xde,0xc7,0x84,0x0b,0x2b,0xa7, + 0xfd,0x95,0x37,0xf7,0x42,0x17,0xac,0x90,0x6e,0x11,0x53,0xfb,0x75,0x4b,0x37,0x88, + 0xd2,0x1f,0xaa,0x73,0x98,0x0d,0x74,0xb3,0x69,0x54,0x2b,0x9e,0x5f,0xaf,0x93,0x21, + 0x07,0x05,0x60,0xc6,0x61,0x4e,0x5d,0xaf,0x36,0x79,0xca,0x85,0x4a,0x6c,0x58,0xeb, + 0xcf,0xaf,0x99,0xd9,0xb5,0x82,0x46,0xb4,0x73,0x95,0x1a,0xbc,0x78,0xdd,0xb7,0x47, + 0x10,0xeb,0x03,0x50,0x63,0x06,0x73,0xdc,0xc4,0xa1,0xa8,0xa3,0x44,0xc1,0x4d,0xc9, + 0x2c,0x73,0x75,0x0f,0xb0,0xe0,0xa5,0x43,0xd1,0x8a,0x29,0xa9,0x60,0x71,0x4d,0x82, + 0xae,0x5c,0xa5,0x87,0x93,0x4c,0xa2,0xfd,0xb5,0xb3,0xda,0xf4,0x90,0x61,0x87,0x6e, + 0xe8,0x8d,0xfc,0x52,0x17,0x06,0x87,0x32,0x37,0x6a,0xff,0xe7,0x58,0xa2,0x46,0x25, + 0xd0,0x3a,0xd8,0xf7,0xc4,0x1b,0xda,0x58,0x5d,0xb8,0xa2,0x5d,0x4d,0x8b,0x1a,0x90, + 0x20,0x12,0x00,0xf3,0x7f,0xb0,0x53,0x97,0x6d,0xfb,0xa0,0x5c,0x4a,0x6c,0xb5,0xb5, + 0xc3,0xb0,0x3a,0x32,0x71,0xbc,0x61,0xe5,0x37,0x60,0xea,0x4a,0xf5,0xd8,0x05,0xc2, + 0xd4,0x62,0xb2,0x94,0xb0,0x73,0xd6,0x82,0x08,0x60,0x71,0xee,0x7e,0xd5,0xf7,0x30, + 0x89,0xe8,0xb5,0x1a,0x08,0xb8,0xea,0x11,0x57,0x9d,0x99,0x2d,0xef,0xd0,0x5a,0xb7, + 0x24,0xc8,0x1d,0x87,0x81,0x70,0xbb,0xb9,0x88,0xed,0x04,0x32,0xab,0x55,0x7e,0xea, + 0x1a,0x77,0x80,0x7a,0x88,0x08,0xc7,0xa1,0x53,0x05,0xb1,0x85,0x43,0x5a,0x11,0x4f, + 0x2a,0x7e,0xda,0xfe,0x83,0x12,0x47,0xc4,0xd7,0x6b,0xfb,0x8a,0x0c,0x90,0x77,0x84, + 0xc0,0xb3,0xa6,0x60,0x96,0xd3,0x2f,0x5f,0x3f,0x62,0xe4,0xda,0x13,0xf4,0x35,0x50, + 0x20,0x5b,0x1a,0xd0,0xc7,0x39,0x06,0x08,0x6a,0x0d,0x5e,0xb7,0x8b,0x37,0x56,0x1c, + 0x52,0x7c,0x9b,0x6a,0xd6,0x7e,0x8e,0xb0,0x36,0xb7,0x44,0x36,0x30,0xb9,0x0f,0x39, + 0x51,0x48,0xc3,0xa3,0xa1,0x98,0x57,0x6b,0xba,0xf6,0x62,0xaf,0xf4,0x2b,0x6c,0x50, + 0xa1,0x55,0xf4,0x58,0x37,0xc4,0x4a,0xd2,0xcb,0xb6,0x59,0x19,0x82,0x3d,0x5e,0x3d, + 0x38,0xc3,0x74,0xab,0x0c,0xd0,0xb2,0xc5,0xb0,0x87,0x30,0xa2,0xef,0x0a,0x85,0xb0, + 0xe5,0x6c,0x39,0x13,0x8f,0x54,0xfe,0xf4,0x3c,0x16,0x4b,0xfd,0xfa,0x2a,0xef,0x66, + 0xa8,0x2a,0x8d,0xc0,0x7b,0x53,0x55,0x4b,0xba,0x19,0xa3,0xa3,0x5f,0x16,0xb4,0x06, + 0xb2,0x56,0xa7,0xca,0xfa,0x6a,0x1f,0xf2,0x0f,0xe5,0x58,0x8a,0x6d,0x45,0x43,0xb3, + 0xd5,0xd2,0x35,0x4f,0x52,0x75,0x47,0x74,0x6f,0x7c,0x25,0x98,0xb2,0xa9,0xef,0x37, + 0x8e,0xa9,0x89,0xff,0x18,0xb6,0x56,0x75,0x32,0x8e,0x98,0xed,0x35,0x8b,0xca,0xad, + 0x91,0xaf,0xdd,0xd4,0xdf,0xff,0x23,0x99,0x45,0x30,0xad,0x9d,0xec,0xce,0x94,0x4a, + 0x6d,0xaa,0xd7,0x6b,0x73,0xa3,0x33,0x0d,0x8b,0x1d,0xd0,0xde,0xc6,0x30,0x82,0x05, + 0x6e,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x82,0x05,0x5f, + 0x04,0x82,0x05,0x5b,0x30,0x82,0x05,0x57,0x30,0x82,0x05,0x53,0x06,0x0b,0x2a,0x86, + 0x48,0x86,0xf7,0x0d,0x01,0x0c,0x0a,0x01,0x02,0xa0,0x82,0x04,0xee,0x30,0x82,0x04, + 0xea,0x30,0x1c,0x06,0x0a,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x0c,0x01,0x03,0x30, + 0x0e,0x04,0x08,0xe9,0x3c,0x06,0x49,0x97,0xcf,0x08,0xfe,0x02,0x02,0x08,0x00,0x04, + 0x82,0x04,0xc8,0x95,0xff,0x56,0xf1,0x44,0xdd,0xe9,0x3d,0x50,0x22,0xbd,0xda,0x8c, + 0x1d,0x0f,0x6f,0xde,0x2d,0x96,0x46,0x21,0x32,0xc9,0xde,0x6d,0x96,0x45,0xfd,0x05, + 0x67,0xde,0x46,0x22,0x87,0xc3,0xbe,0xb9,0xb1,0x30,0x9d,0x8b,0xb0,0x6b,0x35,0xd9, + 0xa0,0x09,0x49,0x43,0x77,0x93,0x3b,0x6f,0xdd,0xc9,0xba,0xdd,0xa4,0xf9,0x81,0xb0, + 0xc8,0x61,0x2e,0xd8,0xe9,0xd0,0xb4,0xa4,0xe8,0x49,0x5a,0x48,0xe7,0x88,0x21,0xdc, + 0x1d,0x84,0x12,0x08,0x08,0x74,0x52,0x36,0x4a,0x30,0x6b,0xb0,0x57,0x91,0x71,0x0c, + 0x56,0x64,0xc8,0x6d,0x4e,0xfa,0xc6,0xdf,0xec,0xc6,0xc6,0x97,0x76,0xe0,0x5d,0x14, + 0xb7,0x67,0xdc,0xec,0xc9,0x83,0xec,0x8e,0xae,0x3d,0x3d,0x85,0xd2,0x26,0xc9,0x8c, + 0x2a,0xb1,0xf1,0xd7,0xc6,0xe3,0x64,0xf8,0x31,0x59,0xf5,0x6d,0x29,0xd3,0xce,0x29, + 0x8c,0xaa,0x0e,0x3d,0x5d,0x8f,0x9e,0x00,0xb6,0xfd,0xfb,0x7a,0x3a,0x2f,0xaa,0x1e, + 0x01,0x0a,0xd6,0xb5,0xdf,0x34,0x60,0x60,0xe0,0x5a,0x94,0x68,0x6d,0x87,0x26,0x3e, + 0x85,0x83,0x1a,0xb9,0x82,0x71,0xc5,0xb1,0x28,0x67,0x9e,0x2c,0xbe,0x07,0x4a,0x8b, + 0xd2,0xa1,0x2e,0x5c,0xb1,0xff,0x26,0xae,0x2e,0xc9,0xc2,0x3a,0x78,0x12,0x50,0x0b, + 0xbd,0x01,0x48,0x41,0x89,0x1f,0xa1,0x74,0xe8,0xe0,0xc7,0x70,0x88,0xac,0xa2,0x04, + 0x21,0x82,0x4b,0x8f,0x2a,0x81,0x13,0x4a,0xbb,0x80,0x59,0x7c,0xef,0xc4,0x26,0xb8, + 0x9d,0x43,0x76,0xef,0x2e,0x53,0xc3,0x10,0xd8,0xd8,0x76,0x2b,0xf0,0x00,0xca,0xf3, + 0xf7,0xa5,0xff,0x2a,0x7d,0x2b,0x9e,0xec,0x2d,0xf4,0x0c,0x1c,0x0e,0xa5,0xef,0x92, + 0xd5,0x26,0x2d,0x22,0xf8,0x67,0xcf,0x9d,0xc3,0x06,0xd7,0xdf,0x9a,0x91,0x94,0xaa, + 0x73,0x70,0x6b,0xf9,0xa6,0x32,0x21,0xb2,0x8a,0x2a,0xe2,0x6c,0x9b,0x6e,0x8d,0xc7, + 0xa5,0x18,0xa3,0xf4,0x8f,0xaf,0x6e,0xe3,0x4c,0x76,0xe9,0xe6,0x81,0x7f,0xa1,0x3b, + 0x53,0x3f,0xb1,0x0f,0x94,0x5b,0x57,0x23,0xfe,0x19,0x51,0xf8,0xc5,0xd6,0x6d,0xa9, + 0x55,0x53,0xb6,0xf8,0x93,0x29,0xe8,0x4b,0xca,0x1f,0x9c,0xe5,0xdb,0x30,0xa2,0x13, + 0x26,0xed,0x90,0xea,0x5e,0xa5,0xc8,0xf6,0x04,0xf3,0xc0,0xd0,0x0d,0x7c,0x33,0x66, + 0x8d,0xfd,0x69,0x70,0x91,0x96,0xe4,0x9f,0x70,0xfa,0x4b,0xbc,0x07,0xbf,0xf7,0x0e, + 0x9f,0xcc,0x3a,0xef,0x5a,0xc8,0x5f,0xd7,0x17,0x5a,0xaa,0x35,0x68,0x09,0xb7,0x5a, + 0xc9,0xab,0x33,0x40,0x17,0xb7,0xd2,0x66,0xe6,0xea,0x74,0xca,0xd5,0x71,0x89,0x8b, + 0x95,0x07,0x2c,0xbd,0x43,0xc9,0x7a,0xa3,0xb5,0x8b,0x11,0x61,0x95,0x4e,0x39,0xeb, + 0x66,0xfb,0x06,0xfb,0xf2,0xd4,0x56,0xb5,0x2b,0xca,0x93,0xde,0x22,0xbe,0xc2,0x62, + 0xbd,0xbc,0x58,0x0d,0x49,0x4d,0x08,0x82,0x8a,0x63,0x74,0x7c,0x64,0x0d,0xf5,0x36, + 0x82,0xc2,0x14,0x6a,0xa1,0x34,0x34,0x94,0x55,0x74,0xc6,0x69,0xe6,0xd4,0x3c,0x6c, + 0x03,0x0f,0xa5,0xa5,0x23,0x58,0xbb,0x97,0x75,0x97,0x70,0x4e,0x6a,0x94,0x57,0xba, + 0x5a,0xbb,0xab,0x3f,0xfe,0x8f,0x1d,0x5a,0x1f,0x7a,0x6d,0x79,0xaa,0x67,0xd8,0xdc, + 0x03,0x88,0x2f,0x2c,0xa7,0x79,0xc0,0xd7,0x85,0x42,0xf9,0xc3,0x23,0x67,0x09,0x22, + 0x3a,0xb8,0x04,0x5c,0xa9,0x75,0x18,0x35,0x16,0x39,0x7a,0xf2,0x01,0xb7,0x5e,0xe6, + 0xa1,0xc8,0x2b,0x29,0x9c,0x38,0xb1,0x8b,0x50,0xd8,0xe9,0x8b,0x6a,0x38,0x5b,0xe0, + 0xfe,0x88,0x21,0xb6,0xc9,0xf6,0x6a,0x66,0x17,0xe7,0x37,0x42,0xe9,0x62,0x63,0x41, + 0xca,0xa1,0xc7,0x0c,0x5c,0xf6,0xdc,0xf5,0xf4,0x5f,0xc1,0x84,0xc5,0x8f,0xe8,0x87, + 0x5e,0xb2,0xf5,0x0a,0x9f,0x8f,0x8d,0x71,0x25,0x3b,0x54,0xb8,0xd2,0x15,0x3f,0x69, + 0x27,0x9b,0xea,0xf7,0x83,0xf5,0xf2,0x24,0xd9,0xd8,0xd6,0x62,0x13,0x43,0xe5,0x64, + 0xb3,0xf2,0x49,0x70,0x02,0xf4,0x76,0x42,0xae,0xed,0x00,0xbf,0x18,0x5b,0xe0,0x1c, + 0x41,0x37,0x0e,0xbd,0x13,0x2d,0xa1,0x31,0x0c,0x8c,0xd6,0xc4,0x27,0xe4,0x2a,0x74, + 0xa3,0x90,0x63,0x56,0x05,0x59,0x6a,0xdc,0x45,0x9e,0x04,0x14,0xd3,0x32,0x77,0xff, + 0xb2,0x50,0x73,0xba,0x2a,0xd3,0x70,0x69,0xbe,0xec,0xf6,0xee,0xed,0xf9,0x88,0x65, + 0x4e,0x61,0x32,0x09,0x73,0xdc,0x16,0x16,0x8a,0xec,0x09,0x44,0xcb,0x2c,0x03,0x44, + 0xaf,0xd7,0xcd,0x0d,0x91,0x52,0xf1,0xba,0xed,0x64,0x7b,0xd9,0xa1,0x1a,0x40,0xdb, + 0xf8,0x46,0x86,0x74,0x30,0x2d,0x72,0x62,0x2a,0x8c,0xd0,0xa2,0x6f,0xcd,0x21,0x02, + 0xc9,0xc4,0xd0,0x81,0x23,0x1c,0x81,0xd9,0x71,0xc1,0xee,0x70,0x37,0x8e,0x23,0x9d, + 0x2c,0xd6,0x4b,0x2b,0x08,0x92,0x95,0xbb,0xf4,0xae,0x78,0x14,0xa6,0x16,0xdc,0xf7, + 0xba,0xc1,0x18,0x96,0x13,0x5a,0xa4,0x12,0xcd,0x96,0x2b,0xb3,0x21,0x0a,0xd6,0x7e, + 0x25,0xd8,0xe9,0x59,0xd5,0x18,0x91,0x85,0xc1,0xe3,0xee,0xf8,0x9b,0x4f,0x42,0x04, + 0x03,0x7d,0xe8,0xcc,0x2a,0xa3,0x8e,0x95,0x9b,0x47,0xb0,0x89,0x7f,0xd5,0x53,0xbd, + 0x54,0x7b,0x73,0xa2,0x0a,0x62,0x51,0x34,0x3b,0xc5,0x41,0x5d,0xa5,0x5c,0x94,0x69, + 0xd5,0xfd,0x5e,0x71,0xc1,0x6e,0x18,0x80,0x1f,0xab,0x94,0xcd,0x0d,0x44,0x47,0xd4, + 0xa9,0xf3,0x3a,0xfd,0xf8,0x47,0xe4,0x9c,0xd7,0x5d,0x54,0x6f,0x4b,0xea,0xf1,0x8f, + 0x9f,0xca,0x3c,0x24,0xe6,0x8b,0xa5,0x29,0x5b,0x07,0x05,0x60,0x41,0xce,0x77,0x2b, + 0xfe,0xe0,0x4e,0x47,0x92,0x2d,0xca,0x5b,0x6e,0x08,0xcc,0x25,0x8e,0xc8,0x93,0x96, + 0x49,0x6d,0x3f,0x25,0xbf,0x8e,0x37,0xe3,0xdf,0xb9,0xea,0xf0,0x2b,0x56,0xc8,0x30, + 0x7d,0xff,0x32,0xfa,0x9c,0xf1,0x35,0x6b,0x68,0xf2,0xfd,0x1e,0x23,0xf2,0x95,0x81, + 0x68,0xd8,0xec,0x95,0x5b,0x85,0xa8,0x42,0xa6,0xcc,0xf5,0x03,0x95,0xf1,0x3f,0xd2, + 0x86,0x3a,0x1f,0x11,0xd2,0xcf,0x4b,0x32,0xf2,0xb9,0x46,0x3e,0xf5,0xbb,0x0d,0xa0, + 0x5b,0x85,0xea,0xe0,0xbd,0x7c,0x3b,0x75,0x80,0x1c,0x8a,0x6d,0x92,0x39,0x27,0xbf, + 0xc5,0x8e,0xb4,0x5a,0xaf,0xd5,0x8b,0x34,0x53,0x85,0x76,0x60,0xe6,0xd4,0xb8,0xe2, + 0x2f,0x9e,0x66,0x24,0x28,0x66,0x06,0x25,0x62,0x77,0x35,0xce,0x36,0x68,0x2a,0xdc, + 0x82,0x94,0xd8,0x21,0x96,0x7b,0x05,0x10,0x3b,0xcc,0xfb,0x43,0x11,0xd0,0x25,0xfc, + 0x1c,0x5a,0x1c,0xee,0x3d,0x1c,0x75,0xf8,0x41,0xa7,0x10,0x48,0xd7,0xee,0x9e,0xa4, + 0x62,0xb0,0x64,0xaa,0x55,0xd9,0xd7,0xb6,0x4b,0xe9,0x84,0xa8,0x64,0xcc,0xb3,0x3a, + 0xe7,0x83,0xf0,0x8a,0xd3,0xe3,0x86,0xda,0xb5,0xc7,0x8e,0x9c,0x84,0xde,0x06,0x5d, + 0x8f,0x4d,0x68,0x35,0x69,0x88,0xc2,0xd1,0xea,0xab,0x1b,0xa7,0xf0,0x8e,0x05,0x3d, + 0xdb,0x8b,0x27,0x20,0xd2,0xb1,0x20,0xab,0x9a,0xda,0x4d,0x03,0xbd,0xa4,0x17,0xf6, + 0x01,0xb5,0x25,0x62,0x02,0xe5,0x17,0xdd,0x71,0x8a,0xe8,0x2b,0x01,0x56,0x35,0x31, + 0x79,0x6f,0x7f,0x98,0x3f,0x5c,0x3d,0x0d,0x11,0x43,0x44,0x31,0xe0,0x94,0xa0,0x6a, + 0xaa,0x8e,0x24,0x0d,0x8f,0xe2,0x81,0x75,0x0d,0x9f,0x54,0xf8,0x0e,0x23,0x19,0xb9, + 0xa9,0x6e,0x11,0xfc,0x08,0xb4,0x73,0x77,0xda,0x3b,0x00,0x63,0xc4,0xb8,0x79,0xb4, + 0xf9,0xb2,0x41,0x55,0xd5,0xb6,0xd3,0x91,0x4d,0x77,0xeb,0xc9,0xb9,0x42,0xba,0xef, + 0x05,0xae,0x2f,0xc3,0x1a,0x7d,0x9b,0x01,0xef,0xee,0x8f,0x0b,0x2c,0x68,0xab,0xc6, + 0x43,0xb3,0x87,0x1f,0xca,0xba,0xe7,0x30,0xe9,0x7a,0xda,0x55,0xec,0x77,0xd1,0xb6, + 0x44,0xcb,0x91,0x43,0xa9,0x2b,0xc1,0x26,0xed,0x14,0x85,0x31,0x52,0x30,0x2b,0x06, + 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x14,0x31,0x1e,0x1e,0x1c,0x00,0x54, + 0x00,0x65,0x00,0x73,0x00,0x74,0x00,0x20,0x00,0x53,0x00,0x53,0x00,0x4c,0x00,0x20, + 0x00,0x55,0x00,0x73,0x00,0x65,0x00,0x72,0x00,0x00,0x30,0x23,0x06,0x09,0x2a,0x86, + 0x48,0x86,0xf7,0x0d,0x01,0x09,0x15,0x31,0x16,0x04,0x14,0xf1,0x1b,0x6e,0xf2,0x3a, + 0xc4,0x3a,0xe1,0xd6,0x4b,0x7d,0x31,0xf3,0x2c,0xd4,0x63,0x06,0x66,0x37,0xe0,0x30, + 0x30,0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14, + 0x85,0xed,0x34,0x3d,0xde,0xa1,0x8a,0x94,0xcd,0x12,0x95,0xf7,0x2d,0xb2,0x60,0xfd, + 0xbd,0x67,0xe9,0x2d,0x04,0x08,0x71,0xfc,0x54,0xf2,0x12,0x3c,0x22,0xf1,0x02,0x01, + 0x01 +}; + +/* Test identity (PKCS12 data), SMIME cert, expired in 2008 + */ +unsigned char TestIDSMIME2007_p12[2805] = { + 0x30,0x82,0x0a,0xf1,0x02,0x01,0x03,0x30,0x82,0x0a,0xb8,0x06,0x09,0x2a,0x86,0x48, + 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x82,0x0a,0xa9,0x04,0x82,0x0a,0xa5,0x30,0x82, + 0x0a,0xa1,0x30,0x82,0x05,0x17,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07, + 0x06,0xa0,0x82,0x05,0x08,0x30,0x82,0x05,0x04,0x02,0x01,0x00,0x30,0x82,0x04,0xfd, + 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,0x3f,0x0b,0xd9, + 0x3c,0x80,0x6d,0x5e,0x7b,0x02,0x02,0x08,0x00,0x80,0x82,0x04,0xd0,0x08,0x25,0x32, + 0xdc,0x7b,0xed,0x8a,0x29,0xf8,0x56,0x84,0x51,0x5c,0x6d,0xe6,0xe6,0x34,0xf8,0x03, + 0xb3,0x80,0xe2,0xf4,0x0e,0x3f,0x1f,0xad,0x12,0x11,0x27,0x56,0xe8,0x89,0x59,0x90, + 0x03,0xf0,0xa7,0xc2,0xde,0xd0,0x70,0xbf,0x2c,0xea,0x01,0xe7,0xbd,0xba,0xaf,0xfc, + 0x07,0x84,0x2f,0xdb,0x65,0xa0,0x7b,0x4b,0x6a,0xab,0xe4,0xbd,0xd0,0xbb,0x31,0xaf, + 0x90,0x8c,0xa8,0x71,0x10,0x23,0x96,0x67,0x44,0xdd,0x02,0x72,0xd2,0x0f,0xca,0xcb, + 0x4f,0xc2,0x14,0x04,0xfa,0xde,0x31,0xa5,0x2f,0x97,0xc0,0x2a,0xdd,0xdd,0x91,0x62, + 0xa7,0xf7,0x9b,0x43,0x57,0x7d,0x4d,0x1c,0xb1,0x92,0xba,0xae,0xa1,0x24,0x6c,0x99, + 0x81,0x49,0x56,0x46,0x8b,0xea,0x7c,0x16,0x19,0x76,0xf7,0x40,0x06,0x82,0xe2,0x5b, + 0x3f,0xd8,0x2c,0x87,0x60,0xf7,0xae,0xaa,0xa5,0xba,0x96,0xbf,0x5c,0x86,0x57,0x81, + 0x8d,0xbf,0x6c,0xe1,0xd1,0xb9,0x20,0x93,0x27,0xfc,0xe6,0x35,0x80,0xaa,0xfb,0xe6, + 0x4b,0xfd,0x4f,0xa4,0x06,0x05,0x46,0x85,0x66,0x15,0xfb,0x83,0x2b,0x42,0x26,0x98, + 0xc8,0x69,0x24,0xa1,0x71,0xb4,0x56,0x38,0x3d,0x5e,0xc2,0x13,0x34,0xab,0x2f,0xb1, + 0x33,0x6e,0xf0,0x07,0x80,0xdd,0x0e,0x6f,0x19,0x01,0xaf,0xff,0x5f,0xc3,0xea,0x24, + 0x5a,0x6d,0xad,0xb3,0x10,0xbb,0x63,0x02,0x14,0x38,0xa9,0x21,0x83,0xb9,0xc3,0x23, + 0xba,0xfc,0x56,0x76,0x4d,0x46,0x43,0xd1,0x09,0x37,0x1f,0x79,0xe5,0x70,0x93,0xb5, + 0x0f,0x21,0xe3,0xef,0x0b,0x4d,0x87,0x0c,0x68,0xf5,0x16,0xc0,0x13,0xee,0x28,0xe8, + 0x49,0xaa,0x60,0x61,0xe5,0x76,0xe6,0x8e,0xd6,0xae,0x52,0x70,0xb2,0x70,0xbf,0xeb, + 0xd2,0xd8,0xb8,0x92,0x71,0x6e,0xb8,0x59,0xdf,0xee,0xad,0xc1,0x55,0x14,0x4b,0x52, + 0x0c,0x20,0x4c,0x79,0x93,0x71,0xe6,0xc5,0xbc,0xf3,0xf3,0x14,0x13,0xd0,0xcd,0x1c, + 0x62,0x21,0xc0,0xcf,0x4e,0xf5,0xda,0x52,0xbf,0x2c,0x86,0x8f,0xb5,0x67,0xf5,0x72, + 0xbb,0xe9,0xb8,0x86,0x17,0xd9,0x35,0x49,0xae,0x0a,0x99,0x94,0xa5,0xaa,0x96,0xf4, + 0x95,0xfe,0x4a,0xe2,0x13,0x46,0xcb,0xd9,0x8b,0x48,0x50,0xff,0x34,0x88,0x12,0xe7, + 0x9b,0x00,0x8d,0x57,0x94,0x44,0xa5,0xe6,0xd1,0x7f,0x34,0xbb,0x33,0x9f,0xc3,0x12, + 0x3b,0xb2,0xba,0xb6,0xb3,0x15,0x9e,0xaf,0x90,0x5e,0x2e,0x61,0x0d,0xe6,0x02,0x25, + 0x41,0x55,0x18,0xc9,0x4a,0x5a,0x0a,0xb2,0xf5,0x99,0x8a,0x27,0xc7,0xd7,0x01,0x96, + 0x9e,0x4c,0x05,0x7f,0x54,0x90,0x08,0x92,0x9c,0xf2,0xbd,0x0d,0x7d,0x37,0x5a,0x57, + 0x1d,0x5b,0xcb,0xce,0xc1,0x58,0x5e,0x50,0x73,0x4d,0x61,0x28,0x18,0x90,0x2d,0xac, + 0x91,0x4b,0x5e,0x5f,0x57,0x29,0x58,0x65,0xba,0xa4,0x11,0x92,0xa8,0xf4,0xac,0xa8, + 0x39,0x1c,0x52,0x14,0x09,0x13,0xdd,0x4e,0xfa,0xef,0xba,0x4f,0x48,0xc3,0x46,0x4e, + 0xb9,0x8d,0xff,0x5e,0x28,0xb8,0xcc,0x99,0x7f,0x3a,0xdc,0xf4,0x90,0x5c,0x41,0x14, + 0x4b,0xbc,0x6b,0xa3,0x01,0x78,0x87,0xc1,0x86,0xd7,0xad,0x98,0xa0,0xc6,0x82,0x35, + 0x76,0x41,0x6f,0xf1,0xee,0x54,0xbd,0xef,0xef,0xfc,0x2b,0x88,0x56,0x61,0xb1,0x93, + 0xa0,0xe5,0x8e,0x1e,0xb4,0xb1,0x39,0xb3,0xd3,0x85,0xe0,0xa2,0x61,0x4b,0xe8,0x24, + 0xc3,0xdd,0x48,0x2a,0xfd,0x5a,0x98,0x7a,0x98,0x2a,0xc7,0x81,0x4c,0x3d,0x3b,0x0c, + 0x42,0x69,0x42,0x87,0xf1,0x5f,0x13,0x47,0xf6,0x89,0xc5,0x5e,0x47,0x84,0x59,0x81, + 0x97,0xef,0x22,0x79,0x16,0x37,0xdc,0x74,0x66,0x30,0x81,0xbc,0x45,0x21,0xe4,0x75, + 0x69,0xe4,0x64,0x2b,0x98,0x97,0x61,0xe1,0x34,0xdf,0x4a,0x37,0x65,0x74,0xdc,0xe1, + 0x71,0x37,0xd6,0x2c,0x54,0x83,0x7a,0x91,0xc4,0xa6,0xfe,0x09,0x12,0xf3,0xf5,0x2b, + 0xec,0xe9,0x63,0xa3,0x25,0x0f,0x6f,0xd1,0xb0,0x95,0x3f,0x7f,0xab,0xa7,0x25,0x9b, + 0x85,0xdb,0xcf,0x6e,0x0e,0xc0,0x8d,0xd3,0xca,0x0e,0xd2,0x98,0xeb,0x77,0x39,0xf4, + 0x1a,0x30,0xe6,0x76,0x6d,0xba,0xc0,0x61,0x55,0x4e,0xbe,0x88,0x32,0xb2,0xae,0x16, + 0x27,0xbd,0x61,0xc5,0x48,0x26,0x0f,0x05,0x1a,0x42,0xa6,0xd9,0x29,0xf8,0x58,0x96, + 0x16,0x1d,0xad,0xf4,0x58,0xc6,0x79,0x46,0xdf,0x1f,0x25,0x43,0xaa,0xf5,0xc3,0x1f, + 0x75,0x36,0x1c,0x17,0xd2,0x4d,0x88,0xf6,0x37,0x35,0x21,0x1f,0x0f,0x45,0x85,0x13, + 0x50,0x85,0x0a,0xa2,0xb4,0x96,0x7a,0xe4,0x0a,0x27,0x74,0x87,0x1b,0x11,0xaa,0x7c, + 0x35,0xf6,0xb6,0x49,0x8d,0x58,0x30,0x16,0xb7,0x36,0xd6,0xd8,0x82,0xe6,0x3d,0xa4, + 0xdf,0xa7,0xc4,0xc7,0xfe,0x81,0x01,0xa6,0xda,0x63,0x10,0x9f,0x2b,0x84,0x14,0x62, + 0xb8,0x37,0x9b,0xb4,0x3f,0x62,0x6b,0x76,0x36,0x39,0xb7,0x41,0xaf,0xb9,0xc9,0xf8, + 0xa5,0x20,0x1f,0x0c,0xfc,0x71,0xca,0x6f,0x56,0x4d,0x6b,0x23,0x5b,0xb2,0x77,0x6f, + 0x83,0xcc,0x8e,0x8c,0x78,0xda,0x4a,0xbf,0x92,0xd4,0x20,0xfe,0x43,0x6a,0xd4,0x7e, + 0xd5,0x6c,0x56,0xdb,0xf8,0x94,0x01,0xc8,0x6f,0xdb,0x00,0x9c,0x0b,0x4c,0x97,0xa5, + 0x2b,0xc1,0x46,0x19,0x91,0x34,0x05,0x9b,0x33,0x20,0xb2,0x79,0xe5,0x00,0x3d,0xb2, + 0x54,0x4f,0xfa,0x23,0xaa,0xfa,0x3d,0x0c,0x83,0xcf,0x81,0xd1,0xd0,0x12,0x03,0x34, + 0xda,0x6b,0xbb,0x63,0xbe,0x1b,0x3c,0x53,0x91,0x2b,0x7e,0xd7,0x76,0x62,0x6e,0xc9, + 0xb1,0x3d,0x74,0x9f,0x96,0xfb,0x66,0xad,0x35,0xba,0x23,0x10,0x9b,0xab,0xc3,0x8a, + 0x87,0xd1,0x0b,0xa2,0x99,0x34,0x8a,0x43,0x90,0xe9,0x65,0xe7,0x69,0x09,0x61,0x5f, + 0xce,0x42,0x58,0x69,0xdf,0x8b,0x0c,0x5a,0xa0,0x6a,0x25,0x33,0x29,0x9e,0x23,0xbb, + 0x77,0xf9,0xa4,0x2f,0x66,0x86,0xc5,0x38,0xf6,0x3d,0xcb,0x03,0xbf,0x94,0x9d,0x56, + 0x73,0x53,0x9d,0xf4,0xc6,0xad,0x22,0x6d,0xff,0x92,0x90,0x63,0x80,0x5b,0xd2,0x4b, + 0x18,0xcd,0xc5,0xe1,0xdb,0x4d,0x96,0xc4,0x29,0x0b,0x0e,0xb8,0x18,0x53,0x66,0x49, + 0x20,0x8e,0xef,0x25,0x93,0x48,0x12,0xe6,0x36,0xd4,0x33,0xcc,0x4d,0x99,0xbd,0x94, + 0x96,0x61,0xb2,0x7a,0x76,0x7f,0xa1,0xd9,0x1b,0x77,0xfc,0xb7,0x54,0xaf,0x6c,0xeb, + 0xec,0x90,0x15,0x21,0x2f,0xe2,0x40,0x05,0x23,0x0c,0x2a,0xe2,0xda,0xa0,0x9b,0x0c, + 0xc7,0x8b,0x31,0xd7,0x8e,0x91,0x95,0x39,0x79,0xd7,0x6d,0xbf,0x86,0x24,0x4d,0xcd, + 0x72,0x43,0x05,0x56,0xc0,0xe1,0x0c,0xed,0x51,0xa3,0xa9,0x85,0x74,0x41,0x20,0xe2, + 0x37,0x66,0x80,0x40,0x02,0xf2,0x4b,0x60,0x36,0x4f,0xcf,0x12,0x5a,0x22,0xbc,0x6c, + 0x21,0xb1,0x2f,0x0c,0x4a,0x26,0xc2,0x14,0x23,0xb3,0x91,0x17,0x48,0x9e,0x27,0x6d, + 0x6a,0x2f,0xaf,0x58,0xe4,0xf7,0x4d,0x40,0x4b,0xd9,0x52,0xa0,0xf6,0x5e,0xc3,0x36, + 0xda,0xa6,0x27,0x81,0x1e,0x7c,0x61,0x45,0x93,0x1a,0xa6,0x9d,0x16,0x61,0x95,0xed, + 0x20,0x2c,0x49,0x6d,0x8f,0x8d,0x1a,0x44,0x89,0x0a,0xce,0x3c,0x00,0x9c,0x76,0x76, + 0xa5,0x0b,0x40,0x52,0xf2,0xb9,0x30,0xae,0xab,0x04,0x41,0xa1,0x30,0x2f,0x43,0x1b, + 0x68,0xdb,0x7c,0x4d,0x6c,0xe6,0x05,0xfc,0xa4,0xab,0xd2,0x0a,0x75,0x0c,0xd9,0x40, + 0x09,0xf1,0xcb,0x5e,0x0a,0x09,0x2c,0x75,0xbc,0x79,0xa5,0xd5,0xb5,0xde,0x07,0xfd, + 0x27,0x31,0x96,0xad,0x66,0xc6,0xa6,0x5e,0x0a,0x57,0x06,0x39,0x03,0xe4,0x84,0x61, + 0xcf,0x25,0x6c,0xcd,0x56,0xf4,0xe7,0xd1,0xff,0x93,0x6c,0x2d,0xd6,0xcf,0x0d,0xe6, + 0x1e,0xe5,0x57,0x37,0xa6,0x6d,0xec,0xa1,0xde,0xe8,0x1f,0x64,0x90,0x5e,0x70,0xe2, + 0xe8,0x05,0x24,0xac,0x36,0xe1,0xea,0x75,0xdf,0x60,0xe2,0xbf,0xc2,0x30,0x82,0x05, + 0x82,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x82,0x05,0x73, + 0x04,0x82,0x05,0x6f,0x30,0x82,0x05,0x6b,0x30,0x82,0x05,0x67,0x06,0x0b,0x2a,0x86, + 0x48,0x86,0xf7,0x0d,0x01,0x0c,0x0a,0x01,0x02,0xa0,0x82,0x04,0xee,0x30,0x82,0x04, + 0xea,0x30,0x1c,0x06,0x0a,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x0c,0x01,0x03,0x30, + 0x0e,0x04,0x08,0xf4,0xa6,0x0f,0xb4,0x2e,0x8e,0x48,0xa6,0x02,0x02,0x08,0x00,0x04, + 0x82,0x04,0xc8,0x0a,0x64,0x3b,0x68,0x4a,0x9a,0xf0,0xf6,0x80,0x65,0x2d,0xca,0xa6, + 0x74,0x33,0x32,0xf3,0x71,0x97,0x27,0x24,0x3c,0xd1,0xaf,0x8b,0xfb,0xee,0x69,0x40, + 0xfc,0xff,0x45,0x32,0x3a,0x1a,0xd1,0x35,0x2d,0xae,0xce,0xd6,0x84,0x5b,0x2b,0x20, + 0x91,0xf8,0x26,0xa6,0x13,0x19,0x21,0x3e,0x8d,0xbb,0x30,0xef,0xdd,0x99,0x58,0x00, + 0x61,0x57,0xe5,0x1b,0xc6,0x96,0xbe,0x7f,0x9e,0x95,0x47,0x7c,0xdf,0xf1,0x09,0x8f, + 0xb9,0xa8,0x99,0x0d,0xf1,0x2a,0xe0,0xfd,0x08,0x92,0xf7,0x56,0x45,0x2e,0xb0,0xf4, + 0x2b,0xf9,0x36,0x43,0xb2,0xbf,0x63,0x82,0x59,0x41,0x25,0x70,0xd6,0x49,0xe8,0x15, + 0x7f,0x77,0x7c,0x7c,0xb3,0xab,0x7e,0xb6,0x16,0xd9,0xf7,0x22,0xa6,0x23,0x00,0x6a, + 0x0e,0x62,0xfa,0xd6,0xe2,0x51,0x13,0x0e,0x99,0x9e,0x12,0x48,0xfa,0x71,0xea,0x47, + 0xeb,0xf7,0xd9,0x9d,0x6f,0xa1,0x77,0x55,0xff,0x30,0xf7,0x68,0x33,0xee,0x26,0x16, + 0xf6,0x43,0x63,0x4e,0xb7,0x16,0x97,0xd3,0x49,0x1c,0xf1,0x9e,0xe0,0xe5,0x77,0x52, + 0xca,0x13,0x48,0x8f,0x11,0x23,0x0d,0x87,0x38,0xa7,0xf3,0x81,0x65,0x96,0xff,0xc7, + 0xb4,0x0f,0x39,0x59,0xff,0x39,0x5a,0x55,0x2b,0x7b,0xab,0x34,0x11,0x42,0x47,0x42, + 0x0c,0xb0,0x71,0x64,0x73,0xa5,0x1d,0x88,0x6e,0xa4,0x61,0x3c,0x67,0x18,0x67,0x2b, + 0x42,0xa1,0x2e,0x60,0xae,0x82,0x3e,0x37,0xc8,0x2e,0x8a,0x80,0x2e,0x9c,0x5d,0xe4, + 0x37,0x58,0xcb,0x6e,0x38,0x75,0x76,0x9a,0xaf,0x25,0xd3,0xb2,0xbe,0xf5,0x36,0x4f, + 0x09,0x05,0xe2,0xe3,0x20,0x03,0x64,0x6f,0x94,0x3b,0xec,0x40,0x8c,0xe1,0x7e,0xed, + 0x94,0xfa,0xed,0x9c,0x4d,0x1d,0xd7,0x31,0x1b,0x9d,0xf3,0xf5,0x1b,0xa0,0xf9,0xc8, + 0xd6,0xf0,0x5e,0xe5,0x26,0x17,0x42,0x18,0xd8,0xe3,0x04,0x65,0xdf,0xa3,0xe6,0x16, + 0x16,0xd5,0xfb,0xbe,0x08,0x1e,0xbf,0xd2,0x0e,0xd5,0x2b,0x4b,0x78,0xb2,0x80,0xf3, + 0x8c,0xe6,0x74,0x89,0xe8,0xce,0xa6,0x2b,0xa5,0x38,0x1f,0x2f,0x87,0x93,0x51,0x35, + 0xe8,0xad,0x6c,0x8d,0x95,0xbd,0xc0,0x24,0xa5,0x14,0x25,0x2d,0xdf,0x4e,0x77,0x32, + 0x68,0xc0,0x91,0xad,0x51,0x95,0x25,0x44,0x7a,0xd7,0x4c,0x75,0xdf,0x73,0xe5,0x2b, + 0xeb,0x1c,0xd3,0xe9,0x42,0xa7,0x5a,0x58,0x85,0x06,0xf0,0xcb,0x38,0x51,0x6d,0x09, + 0x57,0x14,0x6f,0xd8,0x55,0x0c,0x7a,0x77,0x7f,0xb5,0x20,0xe8,0xd0,0xbd,0x88,0x5a, + 0xad,0xe6,0xf5,0x02,0x2c,0x7d,0x0b,0xfb,0xe4,0x07,0xad,0xa2,0xd5,0x0c,0xc5,0xbc, + 0x66,0xc4,0x19,0x48,0xe8,0xa2,0x60,0xdd,0xd2,0xf8,0x03,0x9a,0xd9,0x68,0x4d,0xa9, + 0xd8,0xfa,0xda,0xa3,0x6f,0xcc,0x53,0xea,0x11,0x7e,0xa0,0xa8,0x8f,0xec,0xdb,0xc0, + 0x2a,0x40,0xc6,0x84,0x58,0x4f,0x2a,0x23,0x4c,0xbc,0xfe,0xaa,0x78,0x58,0x9c,0xdd, + 0x6c,0xd5,0x63,0xe9,0xe6,0x78,0xc2,0x73,0x14,0xd5,0x11,0xc3,0x2a,0xf5,0x8a,0x46, + 0x78,0xfc,0x5a,0x59,0xc9,0x9a,0x7f,0xba,0x94,0x44,0xb3,0x45,0x83,0x08,0x94,0x4d, + 0x72,0x0b,0x0f,0xd6,0x89,0x9a,0x75,0x6b,0x31,0xcb,0xeb,0x55,0x85,0x38,0x2c,0x3e, + 0x9b,0x86,0xf0,0x58,0x0f,0x4c,0x93,0x24,0xec,0xd5,0xa3,0x61,0x3a,0x79,0x76,0xab, + 0x37,0x63,0x2d,0x79,0xde,0x6d,0xa3,0x7f,0xf2,0xf0,0x8c,0x45,0xe6,0xce,0x97,0xc6, + 0x88,0xfd,0x93,0xe0,0xf9,0xd0,0x93,0x6a,0x77,0xa4,0x28,0xc3,0x02,0x77,0x87,0xf6, + 0x22,0xfa,0x2b,0x0b,0x31,0xcf,0xe2,0xce,0xaa,0xd9,0x65,0xa6,0x96,0x53,0x8d,0xc7, + 0x67,0xaf,0x0c,0x0f,0xbc,0x51,0xdf,0x0b,0xc4,0xf8,0x06,0x46,0x07,0x12,0x95,0xce, + 0x38,0x8e,0xe7,0x8f,0x8d,0x46,0x68,0xbe,0xa5,0x40,0xdc,0xed,0xab,0x76,0x5c,0x87, + 0xac,0xb3,0x5f,0xb9,0xfd,0x9d,0x79,0x54,0x28,0xc2,0x19,0x2e,0x46,0x3f,0x1f,0x67, + 0xe2,0x58,0x30,0x4e,0x89,0xdd,0x2f,0x44,0x59,0xde,0xe4,0xf4,0x0d,0x4c,0x33,0xe4, + 0x98,0x6d,0xb4,0x1f,0x03,0x6b,0x0f,0x8e,0xde,0x86,0x1b,0x33,0x37,0x74,0x14,0xbe, + 0xa9,0x4a,0xac,0xf4,0x9b,0xa7,0x37,0xe8,0xdd,0x94,0x67,0x25,0x5c,0xb4,0x5b,0x79, + 0xfd,0xd3,0x24,0x21,0x11,0xbe,0x76,0x1f,0x98,0x8b,0x73,0x87,0x0c,0x96,0x82,0x59, + 0x04,0x22,0x8c,0x9b,0x57,0x0c,0xca,0x16,0xb3,0x02,0xc6,0xdc,0x6f,0xd2,0x9c,0xcd, + 0x0f,0x31,0xea,0x97,0x94,0xf7,0x43,0xfe,0xe2,0x8f,0xc7,0x07,0x98,0x57,0x30,0x72, + 0x55,0x43,0xca,0xfa,0xde,0x92,0xf9,0x06,0x9e,0x56,0x73,0x80,0x84,0xbb,0x44,0xe5, + 0x7d,0x04,0xfc,0x49,0x8d,0x28,0xfa,0x91,0xe3,0x50,0x76,0xc2,0xf8,0x87,0x29,0x04, + 0xa4,0xfd,0xfb,0x28,0x20,0xe3,0x07,0xb6,0xf4,0xbf,0xe7,0xc4,0x6a,0x93,0x8c,0x12, + 0xda,0x9d,0x9a,0x5d,0x8c,0x0a,0xd7,0xf5,0x9f,0xbd,0x71,0x00,0xfc,0x22,0xea,0xa4, + 0x45,0x6f,0xd4,0xc6,0x7d,0x7a,0x47,0x38,0x15,0x17,0xc6,0xde,0xb3,0xeb,0x1b,0x9a, + 0xea,0x94,0xc1,0x74,0xd1,0x65,0x25,0xc1,0x11,0x82,0x5d,0xb3,0x66,0x7f,0x05,0xd3, + 0xe1,0x0a,0xfe,0x29,0xcf,0xdd,0x18,0x30,0xff,0x00,0x7f,0xef,0xc1,0x50,0x54,0x7c, + 0x8b,0x89,0x3c,0x6a,0x12,0x9d,0xd4,0x5a,0xcc,0x48,0x76,0xab,0x64,0xd3,0x54,0x36, + 0x70,0x9e,0x04,0x69,0x3d,0x20,0x9d,0x62,0x5d,0xe6,0x55,0x8e,0xd0,0x53,0x5c,0xb4, + 0x54,0x79,0x73,0x69,0x6f,0x56,0xfa,0x60,0x1d,0x61,0xeb,0xeb,0x76,0xb4,0xd5,0x7a, + 0xc9,0x51,0xfc,0xa9,0xed,0x4a,0xfa,0x5c,0x5c,0xb5,0x20,0x6a,0x44,0xf7,0xaa,0xf0, + 0x27,0x90,0x55,0xda,0x2d,0xb4,0x11,0x59,0x21,0x65,0x0e,0x87,0xd2,0x53,0x21,0xd2, + 0x81,0x93,0xf7,0xfe,0x3b,0xec,0x49,0x7e,0x1c,0xdc,0xc2,0x8f,0xdb,0xef,0x3c,0x0a, + 0x40,0x89,0x94,0xf3,0x2d,0x77,0x84,0x15,0x03,0x00,0x29,0xfa,0x1b,0xea,0x55,0x7d, + 0xdc,0xdb,0x69,0x95,0xe5,0x72,0xa5,0x17,0x8f,0xfb,0xfc,0x86,0xfc,0x72,0x91,0x09, + 0x9b,0x32,0x1a,0x06,0x5c,0xa5,0x26,0x4b,0x61,0x40,0x97,0x40,0xce,0x17,0xca,0xe7, + 0x79,0xe6,0xcc,0x6c,0xa3,0x81,0x9c,0x9f,0x36,0x74,0x36,0x9f,0xd9,0x5d,0x3e,0x29, + 0xa0,0xce,0xa1,0x84,0xf6,0xaf,0x33,0x2b,0x8b,0x32,0xb4,0x45,0xb1,0x3d,0x72,0x87, + 0x20,0x8c,0x88,0x02,0x0d,0x93,0x50,0xcc,0x31,0xce,0x03,0xf8,0x85,0x4a,0xdc,0xed, + 0xc0,0xcc,0xb3,0xda,0x06,0xbd,0x12,0xd5,0xfc,0xd2,0xbb,0x75,0x4b,0xca,0xb2,0x77, + 0x18,0xe1,0x5e,0xf5,0x9f,0x0c,0x8c,0xe2,0x17,0x73,0xe5,0xa3,0x80,0x40,0xd8,0x42, + 0xb1,0xf7,0xd0,0x04,0x9f,0x2e,0xc2,0x2b,0x9b,0x5e,0xcb,0xae,0xb4,0x5f,0x95,0x53, + 0xf5,0xc1,0x72,0xf1,0xff,0xa2,0x5a,0xcf,0x1b,0x78,0x5c,0x99,0xdf,0x09,0x24,0xbf, + 0xbf,0x86,0xc3,0x0e,0x65,0x9a,0xe6,0xdc,0xde,0x88,0x28,0x94,0xd7,0xc0,0x6d,0xf6, + 0x93,0x52,0xa6,0x7f,0x74,0x92,0x9b,0x0b,0x62,0xd5,0x2c,0xb4,0xad,0x7c,0xc0,0xc6, + 0x3b,0x1b,0xd2,0xbd,0x89,0xa8,0x64,0x02,0x9c,0x81,0x9a,0xd8,0x51,0x04,0x22,0x10, + 0x62,0x46,0x38,0xaa,0xaa,0x3b,0x00,0x5c,0xe8,0x58,0x09,0x25,0xf7,0x53,0x1d,0x72, + 0xab,0x44,0x80,0xb4,0x33,0x91,0xf8,0x8e,0xe1,0x00,0x5c,0x07,0xdb,0x81,0x71,0x25, + 0x86,0x3b,0xa7,0x8e,0x31,0x02,0x89,0x43,0x8f,0x0a,0xa8,0xac,0x6b,0x2a,0xe3,0xba, + 0x4d,0xdf,0x8c,0x20,0x46,0xea,0xd4,0x98,0x2f,0x47,0x98,0xfb,0x03,0x5e,0xdd,0x92, + 0xc5,0x73,0xa2,0x54,0xf7,0x9f,0x5f,0xda,0xb5,0x1d,0xb5,0xab,0x78,0x2b,0x72,0x43, + 0x07,0x0a,0x34,0x22,0xb6,0x23,0xde,0x90,0x0f,0x85,0x7b,0x31,0x66,0x30,0x3f,0x06, + 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x14,0x31,0x32,0x1e,0x30,0x00,0x54, + 0x00,0x65,0x00,0x73,0x00,0x74,0x00,0x20,0x00,0x49,0x00,0x64,0x00,0x65,0x00,0x6e, + 0x00,0x74,0x00,0x69,0x00,0x74,0x00,0x79,0x00,0x20,0x00,0x53,0x00,0x4d,0x00,0x49, + 0x00,0x4d,0x00,0x45,0x00,0x20,0x00,0x32,0x00,0x30,0x00,0x30,0x00,0x37,0x30,0x23, + 0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x15,0x31,0x16,0x04,0x14,0x69, + 0x6e,0x3e,0x79,0x39,0x9b,0x28,0xf4,0x29,0xd4,0x38,0x78,0xcd,0xbd,0x11,0x46,0xb5, + 0x73,0xec,0x96,0x30,0x30,0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a, + 0x05,0x00,0x04,0x14,0x5b,0xc7,0xc7,0x83,0x6c,0xc1,0x23,0xf1,0xeb,0xe8,0xd7,0xc8, + 0x3f,0x4c,0x59,0x18,0x49,0x61,0xdb,0x72,0x04,0x08,0xde,0xab,0x8d,0x3a,0xff,0xf8, + 0x2d,0x69,0x02,0x01,0x01 +}; + +/* Test identity (PKCS12 data), SSL cert, expired in 2008 + */ +unsigned char TestIDSSL2007_p12[2753] = { + 0x30,0x82,0x0a,0xbd,0x02,0x01,0x03,0x30,0x82,0x0a,0x84,0x06,0x09,0x2a,0x86,0x48, + 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x82,0x0a,0x75,0x04,0x82,0x0a,0x71,0x30,0x82, + 0x0a,0x6d,0x30,0x82,0x04,0xe7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07, + 0x06,0xa0,0x82,0x04,0xd8,0x30,0x82,0x04,0xd4,0x02,0x01,0x00,0x30,0x82,0x04,0xcd, + 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,0x7a,0xe7,0xca, + 0x1b,0x57,0x26,0xac,0x5e,0x02,0x02,0x08,0x00,0x80,0x82,0x04,0xa0,0x1a,0x44,0x31, + 0x1c,0x4d,0xa9,0x00,0x7f,0x14,0x71,0x83,0x3b,0x68,0xf8,0xf0,0x6e,0x42,0xd0,0x6a, + 0x8c,0x02,0xbf,0x6e,0x0c,0xcd,0xee,0x7e,0x48,0xab,0x8b,0x7e,0xc7,0xe4,0x66,0x3f, + 0x4d,0x3f,0x05,0xcd,0xa5,0x41,0x5c,0xa2,0x2e,0x59,0x4c,0x62,0x4c,0xa7,0xca,0x31, + 0x10,0xd8,0xc7,0x8c,0xa1,0x6c,0x1d,0x9b,0x27,0x7a,0xa8,0x00,0x7a,0xb9,0xd3,0x4b, + 0x09,0xf0,0xf7,0x75,0xb6,0x53,0xdf,0x54,0xba,0x2e,0x26,0xf5,0x1c,0x49,0x94,0x72, + 0xcb,0x06,0xf3,0xa3,0x28,0xcb,0x48,0xb4,0x70,0x4a,0x0a,0xf8,0xfb,0x82,0xad,0x7f, + 0x50,0x78,0xb7,0x11,0x41,0xd5,0x2b,0x11,0x5c,0x95,0x90,0x0f,0xcb,0xd8,0x95,0xe6, + 0x77,0x74,0x84,0xe5,0x4c,0x24,0xa0,0xd4,0x7a,0x0a,0xd6,0xc8,0x10,0xa4,0x7a,0xcb, + 0x5d,0x81,0x61,0x33,0xb7,0x75,0x6a,0x98,0xbe,0xd4,0xaf,0x3c,0x8c,0x61,0x66,0x43, + 0x6f,0x12,0x4b,0x1e,0x72,0x10,0x76,0xbb,0xc6,0x57,0xbd,0xdb,0x2c,0x99,0xa7,0x53, + 0x1e,0xe5,0x6a,0x42,0x80,0xb9,0x24,0x4f,0x1a,0x2c,0x96,0x0b,0x64,0xd3,0x63,0x36, + 0x6f,0x75,0x74,0x8e,0xd0,0x50,0x5d,0xab,0x4b,0xec,0x59,0x04,0xdb,0x23,0xfb,0x9a, + 0xbf,0xe0,0x88,0x24,0xc6,0x00,0x7e,0xd9,0x12,0x11,0xf0,0xe5,0xe2,0x96,0xb7,0x85, + 0x6b,0x90,0x03,0xab,0x18,0xa4,0x07,0xcc,0xda,0x19,0x76,0x49,0xde,0x41,0x32,0xda, + 0x0f,0x9c,0x8d,0xca,0x96,0xbb,0x39,0xbe,0xeb,0x3d,0xb8,0xe6,0xc1,0xea,0xc5,0xa6, + 0xc3,0x69,0x72,0x96,0x53,0xde,0x36,0x8b,0xee,0x2c,0x6b,0x2e,0x3d,0xad,0xdd,0x9b, + 0x8a,0xd9,0x1c,0xdd,0x92,0xf3,0x38,0xa7,0xec,0x5d,0xa6,0x46,0x54,0x70,0x71,0x0b, + 0xa9,0x1a,0x2a,0x54,0x67,0x6e,0x82,0x8e,0xcb,0x5c,0x2d,0x23,0x2f,0x9b,0x0a,0xc8, + 0xb1,0xf8,0xea,0x9b,0x16,0x72,0xc5,0xf5,0x2c,0x94,0x10,0xdf,0x3f,0xde,0x84,0xa0, + 0x97,0x96,0xfc,0xd7,0x49,0x4e,0xa6,0x37,0x0c,0x2a,0x39,0x08,0x5e,0xbe,0x58,0x9c, + 0x94,0x59,0x98,0x71,0x5b,0x30,0x16,0xcc,0x6f,0x64,0xb5,0xe1,0x1e,0x31,0x34,0x6d, + 0x4a,0xe6,0xb0,0x20,0x31,0x81,0xe4,0x0e,0x48,0x7e,0x4c,0xc4,0xfa,0x9c,0x57,0xf9, + 0xee,0x58,0xfb,0xc2,0x1b,0xd7,0x96,0xdd,0x91,0x0f,0x86,0x40,0xc9,0x45,0x29,0x07, + 0x65,0x48,0xd1,0x1d,0xf8,0x1c,0x6d,0x1d,0x5d,0xce,0x76,0xce,0x70,0x33,0x4f,0x1d, + 0xcc,0x4a,0x87,0xd0,0x9a,0xf3,0xb5,0x40,0xf3,0x35,0xcc,0x89,0x26,0x72,0x94,0x53, + 0x79,0x59,0xbb,0xe6,0xc4,0x24,0x63,0x46,0x83,0x27,0xb7,0xf8,0xff,0x80,0x4c,0x0a, + 0x98,0xee,0xe7,0x4a,0x73,0x11,0x90,0xbf,0x94,0x1c,0x03,0x91,0x78,0xe8,0x01,0x3a, + 0xa1,0xf3,0x53,0xea,0x78,0xb1,0x09,0x4e,0xea,0x2d,0xaa,0xb4,0xce,0xce,0xb1,0xc6, + 0x51,0xb6,0x59,0x52,0x89,0x7e,0xab,0x4c,0xe3,0xd3,0x9b,0x6b,0xa7,0xf2,0xca,0x70, + 0x53,0x95,0x8a,0x13,0xfc,0xc0,0xa2,0x24,0xd2,0x94,0xb5,0xe5,0x95,0x38,0x01,0x39, + 0x0a,0x28,0x1d,0x83,0xd1,0x2a,0x03,0xfa,0xf6,0x6e,0x63,0x80,0x17,0x05,0x18,0x33, + 0x11,0x56,0xe1,0x7e,0x66,0x94,0xbf,0x1b,0x8b,0x11,0xcf,0x41,0xbf,0x71,0xd9,0xa3, + 0x6f,0xbb,0xf5,0xae,0x43,0x1d,0x2f,0xf1,0x88,0x00,0x72,0xca,0x49,0x83,0x3e,0xe3, + 0x87,0x5e,0x0f,0x58,0x97,0xaa,0x2b,0x92,0x40,0xdd,0x8b,0x17,0xce,0xd8,0x11,0x05, + 0xa4,0x03,0x51,0x0b,0xfa,0x35,0x4c,0xde,0x5b,0xda,0x88,0xdd,0x3a,0xe7,0x93,0x60, + 0xca,0xe2,0x8e,0x84,0xcd,0x5b,0x6d,0xb6,0x5c,0x53,0xbc,0x85,0x75,0x96,0xaa,0x00, + 0x06,0x19,0x84,0x66,0x4d,0x41,0x89,0xdd,0x84,0x81,0xbe,0xb6,0xa3,0x69,0x71,0xf4, + 0x3e,0x31,0x89,0xae,0x9e,0x77,0x68,0xff,0x21,0x78,0xa2,0x43,0xc9,0x0e,0x36,0xe0, + 0xa0,0xb6,0xae,0x40,0xf1,0xf4,0xe3,0xc8,0xa9,0x89,0x80,0x32,0x45,0x07,0x37,0xf1, + 0x1d,0xc3,0x1e,0x79,0x0b,0x8b,0x1d,0x7d,0xc9,0xd6,0xa2,0x91,0xc8,0xd8,0x05,0xc0, + 0xc0,0x25,0x27,0x97,0x5f,0x60,0x3f,0xc7,0xc9,0x3e,0xf2,0xac,0x7e,0x4c,0x4b,0x42, + 0x15,0x85,0x1a,0xe0,0xe1,0xfa,0xf9,0x27,0xaf,0x8d,0x6f,0x90,0x52,0x33,0x6c,0x55, + 0xa7,0x9d,0x9c,0x0b,0xc1,0xf8,0xe5,0xa9,0xd7,0x9c,0x81,0xce,0x08,0x49,0x9c,0xb1, + 0x91,0x00,0xdd,0x6f,0xaf,0x17,0xf8,0x01,0xb5,0x9e,0x53,0x2a,0xa0,0xdd,0x47,0x6e, + 0xb3,0x1b,0xd3,0x9d,0xc1,0x8c,0x07,0x9b,0x78,0x8c,0x2e,0xad,0xbb,0x7d,0xe1,0x0a, + 0x11,0x35,0xf7,0xfa,0xf4,0x00,0xf3,0xc2,0xa6,0xf1,0x3f,0xa1,0xdc,0xe1,0xc2,0x2a, + 0x4b,0x22,0x31,0x20,0x45,0x93,0xbb,0x5e,0xfc,0xe5,0xd7,0xcb,0x69,0x1b,0xad,0x3a, + 0x48,0x59,0x9c,0xc7,0x74,0xbb,0x79,0x56,0xb7,0x73,0x92,0x54,0x49,0xc9,0xbc,0x5d, + 0xf2,0x74,0xc8,0x63,0xa8,0x9c,0x99,0x67,0x4d,0x75,0x64,0x10,0x46,0xe7,0x0f,0xf1, + 0xb0,0x4e,0x8b,0x9d,0x4f,0xa7,0x67,0xe9,0xec,0xbf,0x1b,0x0a,0xfd,0xde,0xe4,0xf6, + 0xcd,0xba,0x12,0xce,0x4e,0xb5,0x29,0xbf,0x59,0x0b,0xf7,0xea,0xc7,0x7c,0xfb,0xe4, + 0xe6,0x36,0x86,0x52,0x18,0xf6,0xe5,0x14,0xe1,0x92,0x02,0x98,0x08,0x0f,0xbc,0xd0, + 0x40,0xf3,0xb1,0x87,0xcc,0x6b,0xee,0xee,0x1a,0x8c,0x40,0x13,0x53,0x9e,0x61,0xb3, + 0x17,0x02,0x7e,0x97,0x22,0x90,0x6f,0xf0,0x64,0x75,0x42,0xf4,0xf9,0x8f,0x38,0x46, + 0x27,0x5c,0x14,0x82,0x80,0x71,0xe9,0x7d,0xe9,0xc8,0x32,0xb2,0xae,0xbd,0x90,0x28, + 0xda,0xc0,0xc1,0x6d,0x06,0x03,0x6c,0x83,0x68,0x3b,0xdf,0xb4,0xb4,0x48,0x04,0x0e, + 0xbb,0x6e,0xa8,0xa5,0xa5,0x1b,0x36,0xbe,0xfc,0x40,0xd3,0x97,0xc3,0x62,0xb9,0x34, + 0x94,0xbf,0x01,0xfb,0x21,0xae,0xbb,0xd9,0xdd,0x0d,0xe0,0xf4,0xce,0x25,0x9a,0x7c, + 0xc4,0x10,0xfc,0xac,0x53,0x1d,0x11,0xdc,0x5c,0x4c,0x6e,0x65,0xb3,0x9c,0xca,0x76, + 0x3d,0x5d,0x2d,0x21,0x64,0xa6,0x3c,0xc1,0xa1,0x35,0xe7,0x38,0x8b,0x39,0x9f,0x7f, + 0x93,0x68,0x6f,0xeb,0x96,0x4f,0x7c,0xd3,0x49,0xbe,0x65,0xdb,0x82,0x91,0x2a,0xb4, + 0x62,0x38,0xdd,0x73,0xa7,0x7f,0x66,0x54,0xfa,0x92,0x65,0xbf,0x71,0xc6,0x62,0x38, + 0x96,0xe2,0xf4,0x16,0xc6,0xf7,0x7e,0x9d,0x7a,0x4f,0x35,0x5f,0x0e,0x29,0xe6,0x38, + 0x7b,0x05,0x02,0x61,0xfb,0x16,0xb4,0x43,0xe9,0xb1,0x74,0x3d,0x50,0xe3,0x51,0x5c, + 0x54,0x5e,0x3e,0xe0,0xb1,0xfe,0x20,0x2d,0xe0,0x05,0x25,0x2f,0x1f,0x9a,0x25,0xe9, + 0xec,0xb6,0xb8,0x9a,0xe9,0xff,0x3a,0x7a,0xc8,0x53,0xfd,0xc4,0x61,0xb1,0xa1,0x22, + 0xc6,0x85,0x7a,0x11,0x07,0x84,0xe9,0x58,0x15,0x74,0x33,0x08,0x1f,0x59,0xe9,0x0d, + 0x7f,0x7e,0x38,0xd9,0x77,0x22,0x46,0xb5,0xfc,0xd5,0x3b,0x1d,0x47,0x7a,0x4a,0x16, + 0x35,0xa8,0x67,0x99,0x6d,0x72,0x66,0x0d,0xd4,0xb3,0x3b,0xdf,0xb8,0x9f,0x7f,0x59, + 0x37,0x97,0x65,0xdf,0x79,0x0c,0x15,0xe3,0x14,0x99,0xc0,0x1a,0xcc,0x9a,0x98,0x6a, + 0xb7,0x59,0x35,0x21,0x31,0x3e,0xf4,0xa2,0xce,0xc4,0xca,0x60,0xf8,0xa0,0x43,0xb6, + 0xbe,0x8a,0x0a,0x95,0xea,0xe7,0xa0,0xdb,0x4f,0x36,0x22,0xf8,0xb6,0x60,0xff,0x15, + 0x69,0x45,0x84,0x53,0xad,0x48,0x00,0x0e,0x20,0xb3,0x62,0x07,0xbd,0x02,0x46,0x19, + 0xf6,0x3d,0xb8,0x55,0x4b,0x5f,0xac,0x3a,0x6a,0x86,0xcf,0x07,0x79,0x30,0x82,0x05, + 0x7e,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x82,0x05,0x6f, + 0x04,0x82,0x05,0x6b,0x30,0x82,0x05,0x67,0x30,0x82,0x05,0x63,0x06,0x0b,0x2a,0x86, + 0x48,0x86,0xf7,0x0d,0x01,0x0c,0x0a,0x01,0x02,0xa0,0x82,0x04,0xee,0x30,0x82,0x04, + 0xea,0x30,0x1c,0x06,0x0a,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x0c,0x01,0x03,0x30, + 0x0e,0x04,0x08,0xd3,0x22,0x2a,0xd2,0xd9,0xd0,0xd6,0xd3,0x02,0x02,0x08,0x00,0x04, + 0x82,0x04,0xc8,0x7b,0x88,0x0e,0x83,0x90,0x25,0x3f,0x51,0xab,0x13,0xf1,0x35,0x1f, + 0xec,0x56,0xcb,0xfc,0x31,0x6b,0xd1,0x1a,0x6c,0x35,0x51,0x31,0xb7,0x27,0x2e,0xe6, + 0x8c,0x75,0x7d,0xa6,0x58,0xfd,0x08,0x0b,0xe4,0x39,0x63,0xc6,0x3e,0x2d,0xee,0x2b, + 0xe5,0x58,0x90,0x48,0xb5,0x57,0x38,0x97,0x48,0xf3,0x2c,0xac,0xf1,0xf8,0x10,0x9c, + 0x56,0x02,0xc7,0x9d,0x7f,0x9e,0xe0,0x9c,0x96,0xe7,0x0c,0x9f,0x54,0xab,0x9f,0x26, + 0x17,0xac,0x86,0x88,0x5e,0x4a,0x9c,0xce,0xea,0xc8,0x48,0x83,0x0c,0x2e,0xf0,0xa0, + 0x6c,0x96,0x07,0x26,0x47,0x63,0xc1,0xac,0x27,0xd1,0x1a,0x25,0x88,0x43,0x8e,0x9d, + 0xe0,0x5f,0x80,0xd9,0xd1,0x1a,0x86,0x92,0x12,0x80,0xe1,0x99,0x13,0xc3,0xab,0x53, + 0x97,0xbe,0x51,0x17,0xc4,0x5a,0x9d,0xc0,0xcd,0xe4,0xc5,0xd6,0x44,0x56,0xaa,0x8d, + 0x5b,0x3d,0xc8,0x66,0xaf,0x6c,0xd2,0x96,0xc6,0x83,0x57,0x7a,0x0e,0x66,0x68,0xd6, + 0x30,0xf0,0xaa,0xde,0x13,0x92,0x5e,0x21,0x2c,0x36,0x96,0x77,0x1f,0xd0,0xaa,0x4b, + 0x14,0x9f,0x9f,0xe5,0xa4,0x3f,0xbf,0x7a,0x9b,0x38,0xff,0x91,0x1d,0x0d,0xd4,0x32, + 0x34,0x2b,0x3f,0xd8,0xfb,0x09,0x71,0xdf,0x1b,0x61,0xa3,0x36,0x81,0xaa,0x49,0xa3, + 0xe4,0x5c,0xc4,0x8d,0xc5,0xab,0xc0,0x43,0xbe,0xc1,0x41,0xa2,0xcc,0x28,0x36,0x65, + 0xa6,0xb6,0x73,0x96,0x6a,0x5f,0x1a,0xd9,0xb8,0x48,0x49,0x7b,0x12,0xda,0x2a,0xdb, + 0xaa,0xaf,0x46,0x8b,0x39,0x7e,0xa7,0x78,0x88,0x15,0x95,0x32,0x13,0x76,0xbb,0x2d, + 0xf5,0xd5,0x41,0x6a,0x9b,0xb8,0xe6,0x6d,0x43,0xa6,0xc3,0x53,0xb7,0xc5,0x68,0x9d, + 0xa9,0x84,0x30,0x42,0x59,0x33,0x81,0x79,0x22,0x91,0x1e,0x34,0x31,0x9b,0xd4,0xf3, + 0x2a,0xda,0xe2,0xa3,0x95,0x7a,0x2a,0x9c,0x67,0x57,0xee,0x2b,0x89,0xfc,0x64,0x67, + 0x00,0x98,0x21,0x63,0xc7,0x19,0x95,0x69,0x9b,0x42,0x73,0x5c,0x68,0x59,0xfc,0x64, + 0xe5,0x22,0x57,0x54,0x58,0x06,0xff,0xa3,0x87,0x7d,0x05,0xc8,0xc4,0xfd,0xc7,0x29, + 0x1b,0x1d,0x88,0x0b,0x08,0x96,0x94,0x9b,0xd8,0xee,0x47,0x99,0x06,0xfa,0x64,0x67, + 0xfd,0xb0,0xb1,0xa1,0xf5,0x26,0x7e,0xb1,0x46,0xb1,0x0c,0x82,0x52,0x5f,0xc5,0x94, + 0x23,0x75,0xff,0xb3,0x42,0x18,0xa2,0x9f,0x65,0xfb,0x06,0xb0,0x8a,0x29,0xc1,0x6e, + 0x84,0xd9,0xd4,0x39,0x77,0x02,0x47,0xe3,0x5f,0xf2,0xb4,0x84,0xc0,0x75,0x48,0x4b, + 0x3a,0xef,0x48,0x2e,0x8d,0xa1,0xe5,0xc6,0x86,0x44,0x00,0xd9,0x4d,0x73,0xed,0x68, + 0x8c,0x91,0x56,0x3e,0x2c,0x18,0xd0,0x58,0xd8,0x04,0x15,0xe0,0xd8,0xa8,0xe6,0x46, + 0x36,0x54,0xc5,0x8c,0x2b,0x98,0xa5,0x01,0x73,0xf0,0x67,0x95,0x41,0x4e,0xa3,0xd6, + 0x8d,0x24,0xc4,0xc3,0x8f,0x28,0x7c,0x76,0x76,0x84,0x6c,0x95,0x94,0x22,0xde,0xe2, + 0x9d,0xcb,0x37,0xb6,0x97,0x6b,0xf3,0x58,0x1d,0x5a,0x98,0x88,0xac,0xd9,0xb1,0x59, + 0x16,0x11,0xd8,0x0b,0x68,0xce,0xdf,0x4b,0x1a,0x28,0x3c,0xeb,0x14,0xb2,0x28,0xa7, + 0xad,0x54,0x55,0xa1,0x6b,0x50,0x86,0x55,0x00,0xae,0xf6,0xdf,0x6b,0xb3,0x42,0xb3, + 0x7b,0xbb,0x0d,0x91,0x14,0xdb,0x82,0xea,0xe9,0x08,0x9f,0xf6,0x6f,0xd0,0x10,0xd7, + 0x83,0x1e,0xfc,0x5e,0x58,0xca,0x01,0xdd,0xb4,0xc8,0xbe,0x80,0xe3,0x07,0x71,0x0a, + 0x74,0x01,0xd4,0xf1,0x50,0xe1,0x51,0x22,0xb1,0x43,0x98,0xf1,0x5e,0xdd,0xb4,0x65, + 0x5a,0x18,0x0c,0x8b,0x1b,0x4e,0xe1,0xce,0xb1,0x0e,0x81,0xda,0x6b,0x98,0xc4,0xcb, + 0xd9,0xd2,0xb2,0x1e,0xea,0xac,0x0c,0x08,0x86,0xa4,0x60,0xab,0x84,0x50,0x13,0xf8, + 0x48,0xfb,0x64,0xf3,0x33,0x88,0x83,0x72,0x22,0xe8,0x6a,0x43,0xd3,0xb4,0xc7,0xd2, + 0x04,0xed,0x07,0x75,0x26,0x96,0x2d,0x84,0xb9,0x10,0x02,0xd2,0xda,0xc8,0xc8,0x0b, + 0x95,0xe3,0x69,0x1e,0x57,0x16,0x7a,0xb5,0x1c,0xe7,0x46,0x89,0xfc,0xed,0x49,0x69, + 0x47,0xb8,0x07,0xe4,0xcb,0xd1,0x52,0xd6,0x8c,0x32,0xaa,0x91,0x8d,0x45,0x19,0xf1, + 0x54,0x23,0x3c,0x5f,0xcc,0xc7,0x60,0xfc,0x89,0x00,0x9a,0xa3,0xc2,0xf0,0x48,0xda, + 0xbf,0xe4,0xfd,0x78,0x3b,0x6c,0x2d,0x34,0x91,0x6b,0x0d,0x21,0xb4,0xba,0xe8,0x6d, + 0x80,0xbc,0xfb,0x91,0xcb,0xce,0x77,0x01,0x4e,0xfe,0x7b,0xf2,0x08,0x78,0x2e,0x3f, + 0x16,0xd4,0xfd,0xf0,0x76,0x68,0xce,0x43,0xdc,0xb2,0xe2,0x82,0x64,0x8f,0xc8,0x71, + 0x0f,0x6e,0xc6,0x3b,0x4a,0x6b,0x6a,0xd7,0xf6,0x21,0x46,0xcd,0x05,0xce,0x19,0xab, + 0x28,0x28,0x55,0x19,0x1d,0x07,0xaf,0x38,0xd9,0x9c,0xdf,0xe8,0x91,0x68,0x16,0xdd, + 0x36,0x19,0x71,0x46,0x86,0x08,0x0a,0x08,0x34,0xc5,0x3b,0x53,0xaa,0x35,0x27,0x6e, + 0xe4,0xf3,0xa1,0xd6,0x04,0x78,0xf9,0x63,0xec,0x1e,0xfe,0x30,0x38,0xb3,0xe7,0xd8, + 0x27,0x9f,0x98,0xd5,0xb9,0x4d,0xb9,0x80,0x4f,0xb0,0x81,0xc6,0xaa,0xc2,0xe6,0xbf, + 0x98,0x63,0x05,0xc6,0xab,0x4e,0xc8,0x7e,0xf4,0x37,0x68,0xad,0x63,0x08,0x6e,0x8f, + 0xe5,0xd9,0x62,0x43,0xa3,0x0d,0x61,0x84,0x41,0x02,0xd0,0xc6,0x33,0x19,0x76,0xb8, + 0x31,0xb1,0x27,0x2f,0x81,0x40,0x71,0x35,0x3c,0xf6,0xf2,0xc7,0x9b,0x85,0x9c,0x2e, + 0xa0,0xf6,0xd2,0x3a,0xd9,0x7e,0xdd,0x82,0x56,0xf4,0x61,0x97,0x79,0xdb,0x27,0x5d, + 0xa7,0x5b,0x8d,0x01,0x9d,0x68,0x9b,0x3a,0x4e,0xe1,0x3c,0xaf,0x61,0x0f,0xbf,0xfa, + 0x61,0x12,0x2f,0xde,0x7a,0x71,0x0a,0xdd,0x6e,0x29,0x11,0x8e,0xa4,0x93,0x31,0x85, + 0x2a,0x31,0xa8,0xd7,0x3f,0xfb,0xf4,0xd2,0xd4,0x7f,0x0c,0xb2,0x8d,0x63,0x25,0x47, + 0x18,0x04,0x00,0x28,0x90,0xd3,0xc0,0x7e,0xca,0xfa,0x0d,0xc4,0xab,0xd4,0x7a,0x17, + 0xb7,0xdc,0xce,0x7d,0xc2,0xe8,0x5b,0x68,0x7c,0xa9,0x3c,0xac,0x4e,0x2c,0xde,0x0c, + 0x4a,0x09,0x09,0x03,0x77,0x12,0xb9,0x31,0xc9,0x0d,0x6e,0x2b,0xac,0x96,0x7b,0xb0, + 0x3d,0x37,0x03,0x32,0xc6,0xe1,0x64,0x16,0xc1,0x1b,0xfa,0xa3,0x32,0xe9,0xea,0x25, + 0x0c,0xa1,0xbf,0xae,0xaa,0xba,0xbd,0x24,0xba,0x9d,0x5f,0x15,0x20,0x59,0x2d,0xe5, + 0x09,0xe6,0x71,0x70,0xcd,0xf5,0x44,0x12,0xcf,0x17,0x8b,0x33,0x4b,0x67,0x86,0x53, + 0xd3,0x66,0x80,0x2e,0xfb,0x6b,0x95,0x38,0x35,0x2d,0x39,0xb8,0x19,0xb7,0x01,0xe0, + 0xe2,0x7d,0x29,0xd3,0x89,0xc7,0xc9,0x4f,0xb4,0xf9,0x48,0x20,0x6a,0x40,0xd3,0x71, + 0x28,0xf4,0xdf,0x3a,0xff,0xf0,0xd1,0x7a,0x78,0xbd,0x92,0xe4,0xa2,0x05,0x47,0xf5, + 0xfa,0x25,0x4f,0x22,0x3f,0x8f,0x85,0x72,0xaa,0x0f,0xfa,0x21,0x84,0x63,0xbc,0xb6, + 0xe0,0x49,0x1e,0xdf,0x0a,0xee,0x4b,0xa8,0x96,0xbf,0x2f,0xa7,0x31,0x64,0xc3,0xa1, + 0x19,0xe1,0x2b,0x69,0xbf,0x0f,0xcc,0x76,0x49,0x9f,0xdd,0x4e,0xf0,0x77,0xf0,0xae, + 0x83,0x20,0xe2,0xd6,0x21,0x1a,0x3a,0x1a,0xb4,0xbf,0x57,0x02,0x9c,0xf6,0xb1,0x47, + 0x83,0x59,0x0c,0x43,0xce,0x9a,0x3d,0xb3,0x9b,0x9c,0xd2,0x30,0xcd,0x40,0x58,0xfe, + 0xec,0xa9,0x59,0xa8,0xf6,0x28,0x31,0xbf,0xc3,0xfb,0xad,0x37,0x07,0xd4,0x34,0xe7, + 0x58,0xfa,0xca,0xe7,0xe3,0xbb,0x3d,0xd8,0xf6,0xd7,0x9c,0xf5,0x6f,0xc0,0xbd,0x9e, + 0x3a,0x91,0x30,0x7c,0xe4,0xff,0x8d,0xbe,0x85,0x91,0x27,0x92,0x51,0xdc,0xd6,0x66, + 0x7e,0x5a,0xfb,0xf7,0xbe,0x34,0xce,0x5e,0xa4,0x50,0xf1,0x6d,0xc0,0x32,0x3b,0xaa, + 0x8c,0x52,0x25,0xcc,0x75,0x26,0x2b,0xa8,0x2f,0x6f,0x02,0x81,0x18,0x07,0x5f,0xbe, + 0xc3,0xed,0xa3,0x93,0x73,0xc9,0xd4,0x79,0xec,0x34,0x78,0x31,0x62,0x30,0x3b,0x06, + 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x14,0x31,0x2e,0x1e,0x2c,0x00,0x54, + 0x00,0x65,0x00,0x73,0x00,0x74,0x00,0x20,0x00,0x49,0x00,0x64,0x00,0x65,0x00,0x6e, + 0x00,0x74,0x00,0x69,0x00,0x74,0x00,0x79,0x00,0x20,0x00,0x53,0x00,0x53,0x00,0x4c, + 0x00,0x20,0x00,0x32,0x00,0x30,0x00,0x30,0x00,0x37,0x30,0x23,0x06,0x09,0x2a,0x86, + 0x48,0x86,0xf7,0x0d,0x01,0x09,0x15,0x31,0x16,0x04,0x14,0xd0,0xcb,0xd6,0x5c,0xe1, + 0x73,0x7a,0xb8,0xa8,0x2a,0xf8,0xc9,0xe6,0xdc,0xbb,0xc2,0xec,0x00,0x2e,0x6a,0x30, + 0x30,0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14, + 0x47,0x2e,0x9e,0xca,0x71,0x3b,0x36,0xcf,0x34,0x59,0x7e,0x0a,0x6e,0xe0,0xeb,0x79, + 0xcb,0x82,0x47,0x76,0x04,0x08,0xff,0xe9,0xf7,0xee,0x2f,0x48,0xcc,0x24,0x02,0x01, + 0x01 +}; + + +static int quiet = 0; +static int debug = 0; +static int verbose = 0; + +#define MAXNAMELEN MAXPATHLEN +#define MAXITEMS INT32_MAX + +#pragma mark -- Utility Functions -- + + +void PrintTestResult(char *testStr, OSStatus status, OSStatus expected) +{ + if (verbose) { + fprintf(stdout, "%s: %s (result=%d, expected=%d)\n", testStr, + (status==expected) ? "OK" : "FAILED", + (int)status, (int)expected); + } + if (debug) { + fprintf(stdout, "\n"); + } + fflush(stdout); +} + + +void PrintStringToMatch(CFStringRef nameStr) +{ + char *buf = (char*)malloc(MAXNAMELEN); + if (buf) { + if (CFStringGetCString(nameStr, buf, (CFIndex)MAXNAMELEN, kCFStringEncodingUTF8)) { + fprintf(stdout, "### String to match is \"%s\"\n", buf); + fflush(stdout); + } + free(buf); + } +} + + +void PrintSecCertificate(SecCertificateRef certificate) +{ + CFStringRef nameStr; + OSStatus status = SecCertificateCopyCommonName(certificate, &nameStr); + if (status) { + fprintf(stderr, "### SecCertificateCopyCommonName error %d\n", (int)status); + } + else { + char *buf = (char*)malloc(MAXNAMELEN); + if (buf) { + if (CFStringGetCString(nameStr, buf, (CFIndex)MAXNAMELEN, kCFStringEncodingUTF8)) { + fprintf(stdout, "### Found certificate name: \"%s\"\n", buf); + } + free(buf); + } + CFRelease(nameStr); + } +} + + +void PrintSecIdentity(SecIdentityRef identity) +{ + SecCertificateRef certRef; + OSStatus status = SecIdentityCopyCertificate(identity, &certRef); + if (status) { + fprintf(stderr, "### SecIdentityCopyCertificate error %d\n", (int)status); + } + else { + PrintSecCertificate(certRef); + CFRelease(certRef); + } +} + + +void PrintCFStringWithFormat(const char *formatStr, CFStringRef inStr) +{ + char *buf = (char*)malloc(MAXNAMELEN); + if (buf) { + if (CFStringGetCString(inStr, buf, (CFIndex)MAXNAMELEN, kCFStringEncodingUTF8)) { + fprintf(stdout, formatStr, buf); + fflush(stdout); + } + free(buf); + } +} + + +void PrintCFThing(CFTypeRef thing) +{ + fprintf(stderr, "### Results: %p\n", (void*)thing); + + CFTypeID thingID = (thing) ? CFGetTypeID(thing) : 0; + if (thingID == SecCertificateGetTypeID()) { + // print a SecCertificateRef + PrintSecCertificate((SecCertificateRef)thing); + } + else if (thingID == SecIdentityGetTypeID()) { + // print a SecIdentityRef + PrintSecIdentity((SecIdentityRef)thing); + } + else if (thingID == SecKeychainItemGetTypeID() || + thingID == SecIdentityGetTypeID() || + thingID == CFDictionaryGetTypeID() || + thingID == CFArrayGetTypeID() || + thingID == CFStringGetTypeID() || + thingID == CFDataGetTypeID()) { + CFShow(thing); + } + else { + fprintf(stderr, "### ERROR: result is not a supported CFType! (%ld)\n", + thingID); + } +} + +//%%% FIXME need to break this up into separate functions +int TestAddItems() +{ + SecCertificateRef certs[5]; + SecKeychainRef keychain; + CFDataRef tmpData; + OSStatus status; + +#if AUTO_TEST + /* the regression suite environment does not have a keychain; must create one */ + status = SecKeychainCreate("SecItemTest.keychain", 4, "test", FALSE, NULL, &keychain); +#else + status = SecKeychainCopyDefault(&keychain); +#endif + if (status) { + fprintf(stderr, "Unable to get default keychain: error %d\n", (int)status); + goto error_exit; + } + + /* add test leaf */ + tmpData = CFDataCreateWithBytesNoCopy(NULL, LEAF_CERT, sizeof(LEAF_CERT), kCFAllocatorNull); + certs[0] = SecCertificateCreateWithData(NULL, tmpData); + CFRelease(tmpData); +// will add this below using SecItemAdd instead of SecCertificateAddToKeychain +#if 0 + status = SecCertificateAddToKeychain(certs[0], keychain); + if (status && status != errSecDuplicateItem) { // ignore error if duplicate + fprintf(stderr, "Unable to add test leaf certificate: error %d\n", (int)status); + goto error_exit; + } +#endif + /* add test intermediate */ + tmpData = CFDataCreateWithBytesNoCopy(NULL, INTERMEDIATE_CERT, sizeof(INTERMEDIATE_CERT), kCFAllocatorNull); + certs[1] = SecCertificateCreateWithData(NULL, tmpData); + CFRelease(tmpData); +// will add this below using SecItemAdd instead of SecCertificateAddToKeychain +#if 0 + status = SecCertificateAddToKeychain(certs[1], keychain); + if (status && status != errSecDuplicateItem) { // ignore error if duplicate + fprintf(stderr, "Unable to add test intermediate certificate: error %d\n", (int)status); + goto error_exit; + } +#endif + /* add test root */ + tmpData = CFDataCreateWithBytesNoCopy(NULL, ROOT_CERT, sizeof(ROOT_CERT), kCFAllocatorNull); + certs[2] = SecCertificateCreateWithData(NULL, tmpData); + CFRelease(tmpData); +// will add this below using SecItemAdd instead of SecCertificateAddToKeychain +#if 0 + status = SecCertificateAddToKeychain(certs[2], keychain); + if (status && status != errSecDuplicateItem) { // ignore error if duplicate + fprintf(stderr, "Unable to add test root certificate: error %d\n", (int)status); + goto error_exit; + } +#endif + + /* use SecItemAdd to add an array containing certs 1-3 */ + CFArrayRef certArray = CFArrayCreate(NULL, (const void**) certs, 3, &kCFTypeArrayCallBacks); + CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue(attrs, kSecClass, kSecClassCertificate); // we are adding certificates + CFDictionaryAddValue(attrs, kSecUseItemList, certArray); // add these items (to default keychain, since we aren't specifying one) + status = SecItemAdd(attrs, NULL); + CFRelease(attrs); + CFRelease(certArray); + if (status && status != errSecDuplicateItem) { // ignore error if duplicate + fprintf(stderr, "Unable to add 3 test certificates: error %d\n", (int)status); + goto error_exit; + } + + + /* add test cert for S/MIME policy (encrypt only, no sign) */ + tmpData = CFDataCreateWithBytesNoCopy(NULL, Test_smime_encryptonly, sizeof(Test_smime_encryptonly), kCFAllocatorNull); + certs[3] = SecCertificateCreateWithData(NULL, tmpData); + CFRelease(tmpData); + status = SecCertificateAddToKeychain(certs[3], keychain); + if (status && status != errSecDuplicateItem) { // ignore error if duplicate + fprintf(stderr, "Unable to add test S/MIME certificate: error %d\n", (int)status); + goto error_exit; + } + + /* add test cert for Code Signing policy */ + tmpData = CFDataCreateWithBytesNoCopy(NULL, Test_codesign, sizeof(Test_codesign), kCFAllocatorNull); + certs[4] = SecCertificateCreateWithData(NULL, tmpData); + CFRelease(tmpData); + status = SecCertificateAddToKeychain(certs[4], keychain); + if (status && status != errSecDuplicateItem) { // ignore error if duplicate + fprintf(stderr, "Unable to add test Code Signing certificate: error %d\n", (int)status); + goto error_exit; + } + + /* import test SSL identity */ + { + CFDataRef p12DataRef = CFDataCreateWithBytesNoCopy(NULL, Test_p12, (CFIndex)sizeof(Test_p12), kCFAllocatorNull); + SecExternalFormat format = kSecFormatPKCS12; + SecExternalItemType itemType = kSecItemTypeAggregate; + SecItemImportExportFlags flags = 0; + #if 0 + /* deprecated method, using CDSA constants */ + SecKeyImportExportParameters keyParams = { + SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION, // uint32_t version + 0, // SecKeyImportExportFlags flags + CFSTR("test"), // CFTypeRef passphrase + CFSTR("title"), // CFStringRef alertTitle + CFSTR("pw:"), // CFStringRef alertPrompt + NULL, // SecAccessRef accessRef (unspecified, use default) + CSSM_KEYUSE_SIGN, // CSSM_KEYUSE keyUsage (0=unspecified) + CSSM_KEYATTR_PERMANENT // CSSM_KEYATTR_FLAGS keyAttributes + }; + status = SecKeychainItemImport(p12DataRef, + NULL, &format, &itemType, flags, &keyParams, keychain, NULL); + #else + CFTypeRef keyUsages[1] = { kSecAttrCanSign }; + CFArrayRef keyUsagesArray = CFArrayCreate(NULL, keyUsages, 1, &kCFTypeArrayCallBacks); + CFTypeRef keyAttrs[1] = { kSecAttrIsPermanent }; + CFArrayRef keyAttrsArray = CFArrayCreate(NULL, keyAttrs, 1, &kCFTypeArrayCallBacks); + SecItemImportExportKeyParameters keyParams = { + SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION, // uint32_t version + 0, // SecKeyImportExportFlags flags + CFSTR("test"), // CFTypeRef passphrase + CFSTR("title"), // CFStringRef alertTitle + CFSTR("pw:"), // CFStringRef alertPrompt + NULL, // SecAccessRef accessRef (unspecified, use default) + keyUsagesArray, // CFArrayRef keyUsages + keyAttrsArray // CFArrayRef keyAttributes + }; + status = SecItemImport(p12DataRef, + NULL, &format, &itemType, flags, &keyParams, keychain, NULL); + CFRelease(keyUsagesArray); + CFRelease(keyAttrsArray); + #endif + if (status && status != errSecDuplicateItem) { // ignore error if duplicate + fprintf(stderr, "Unable to import test SSL identity: error %d\n", (int)status); + goto error_exit; + } + } + + /* import test S/MIME signing identity */ + { + CFDataRef p12DataRef = CFDataCreateWithBytesNoCopy(NULL, Test_smime_signonly_p12, (CFIndex)sizeof(Test_smime_signonly_p12), kCFAllocatorNull); + SecExternalFormat format = kSecFormatPKCS12; + SecExternalItemType itemType = kSecItemTypeAggregate; + SecItemImportExportFlags flags = 0; + #if 0 + /* deprecated method, using CDSA constants */ + SecKeyImportExportParameters keyParams = { + SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION, // uint32_t version + 0, // SecKeyImportExportFlags flags + CFSTR("test"), // CFTypeRef passphrase + CFSTR("title"), // CFStringRef alertTitle + CFSTR("pw:"), // CFStringRef alertPrompt + NULL, // SecAccessRef accessRef (unspecified, use default) + CSSM_KEYUSE_SIGN, // CSSM_KEYUSE keyUsage (0=unspecified) + CSSM_KEYATTR_PERMANENT // CSSM_KEYATTR_FLAGS keyAttributes + }; + status = SecKeychainItemImport(p12DataRef, + NULL, &format, &itemType, flags, &keyParams, keychain, NULL); + #else + CFTypeRef keyUsages[1] = { kSecAttrCanSign }; + CFArrayRef keyUsagesArray = CFArrayCreate(NULL, keyUsages, 1, &kCFTypeArrayCallBacks); + CFTypeRef keyAttrs[1] = { kSecAttrIsPermanent }; + CFArrayRef keyAttrsArray = CFArrayCreate(NULL, keyAttrs, 1, &kCFTypeArrayCallBacks); + SecItemImportExportKeyParameters keyParams = { + SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION, // uint32_t version + 0, // SecKeyImportExportFlags flags + CFSTR("test"), // CFTypeRef passphrase + CFSTR("title"), // CFStringRef alertTitle + CFSTR("pw:"), // CFStringRef alertPrompt + NULL, // SecAccessRef accessRef (unspecified, use default) + keyUsagesArray, // CFArrayRef keyUsages + keyAttrsArray // CFArrayRef keyAttributes + }; + status = SecItemImport(p12DataRef, + NULL, &format, &itemType, flags, &keyParams, keychain, NULL); + CFRelease(keyUsagesArray); + CFRelease(keyAttrsArray); + #endif + if (status && status != errSecDuplicateItem) { // ignore error if duplicate + fprintf(stderr, "Unable to import test S/MIME identity: error %d\n", (int)status); + goto error_exit; + } + } + + /* import expired SSL identity */ + { + CFDataRef p12DataRef = CFDataCreateWithBytesNoCopy(NULL, TestIDSSL2007_p12, (CFIndex)sizeof(TestIDSSL2007_p12), kCFAllocatorNull); + SecExternalFormat format = kSecFormatPKCS12; + SecExternalItemType itemType = kSecItemTypeAggregate; + SecItemImportExportFlags flags = 0; + CFTypeRef keyUsages[1] = { kSecAttrCanSign }; + CFArrayRef keyUsagesArray = CFArrayCreate(NULL, keyUsages, 1, &kCFTypeArrayCallBacks); + CFTypeRef keyAttrs[1] = { kSecAttrIsPermanent }; + CFArrayRef keyAttrsArray = CFArrayCreate(NULL, keyAttrs, 1, &kCFTypeArrayCallBacks); + SecItemImportExportKeyParameters keyParams = { + SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION, // uint32_t version + 0, // SecKeyImportExportFlags flags + CFSTR("test"), // CFTypeRef passphrase + CFSTR("title"), // CFStringRef alertTitle + CFSTR("pw:"), // CFStringRef alertPrompt + NULL, // SecAccessRef accessRef (unspecified, use default) + keyUsagesArray, // CFArrayRef keyUsages + keyAttrsArray // CFArrayRef keyAttributes + }; + status = SecItemImport(p12DataRef, + NULL, &format, &itemType, flags, &keyParams, keychain, NULL); + CFRelease(keyUsagesArray); + CFRelease(keyAttrsArray); + if (status && status != errSecDuplicateItem) { // ignore error if duplicate + fprintf(stderr, "Unable to import TestIDSSL2007_p12 identity: error %d\n", (int)status); + goto error_exit; + } + } + + /* import expired S/MIME identity */ + { + CFDataRef p12DataRef = CFDataCreateWithBytesNoCopy(NULL, TestIDSMIME2007_p12, (CFIndex)sizeof(TestIDSMIME2007_p12), kCFAllocatorNull); + SecExternalFormat format = kSecFormatPKCS12; + SecExternalItemType itemType = kSecItemTypeAggregate; + SecItemImportExportFlags flags = 0; + CFTypeRef keyUsages[1] = { kSecAttrCanSign }; + CFArrayRef keyUsagesArray = CFArrayCreate(NULL, keyUsages, 1, &kCFTypeArrayCallBacks); + CFTypeRef keyAttrs[1] = { kSecAttrIsPermanent }; + CFArrayRef keyAttrsArray = CFArrayCreate(NULL, keyAttrs, 1, &kCFTypeArrayCallBacks); + SecItemImportExportKeyParameters keyParams = { + SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION, // uint32_t version + 0, // SecKeyImportExportFlags flags + CFSTR("test"), // CFTypeRef passphrase + CFSTR("title"), // CFStringRef alertTitle + CFSTR("pw:"), // CFStringRef alertPrompt + NULL, // SecAccessRef accessRef (unspecified, use default) + keyUsagesArray, // CFArrayRef keyUsages + keyAttrsArray // CFArrayRef keyAttributes + }; + status = SecItemImport(p12DataRef, + NULL, &format, &itemType, flags, &keyParams, keychain, NULL); + CFRelease(keyUsagesArray); + CFRelease(keyAttrsArray); + if (status && status != errSecDuplicateItem) { // ignore error if duplicate + fprintf(stderr, "Unable to import TestIDSMIME2007_p12 identity: error %d\n", (int)status); + goto error_exit; + } + } + + /* add generic password items */ + status = SecKeychainAddGenericPassword(keychain, + strlen("Test Service 42"), "Test Service 42", + strlen("nobody"), "nobody", + strlen("weakpass"), "weakpass", + NULL); + if (status && status != errSecDuplicateItem) { // ignore error if duplicate + fprintf(stderr, "Unable to add \"Test Service 42\" generic password: error %d\n", (int)status); + goto error_exit; + } + status = SecKeychainAddGenericPassword(keychain, + strlen("Test Service 69"), "Test Service 69", + strlen("nobody"), "nobody", + strlen("weakpass"), "weakpass", + NULL); + if (status && status != errSecDuplicateItem) { // ignore error if duplicate + fprintf(stderr, "Unable to add \"Test Service 69\" generic password: error %d\n", (int)status); + goto error_exit; + } + + /* add internet password items */ + status = SecKeychainAddInternetPassword(keychain, + strlen("test1.subdomain.apple.com"), "test1.subdomain.apple.com", + 0, NULL, + strlen("nobody"), "nobody", + 0, NULL, + 80, kSecProtocolTypeHTTP, kSecAuthenticationTypeDefault, + strlen("weakpass"), "weakpass", + NULL); + if (status && status != errSecDuplicateItem) { // ignore error if duplicate + fprintf(stderr, "Unable to add \"test1.subdomain.apple.com\" internet password: error %d\n", (int)status); + goto error_exit; + } + status = SecKeychainAddInternetPassword(keychain, + strlen("test2.subdomain.apple.com"), "test2.subdomain.apple.com", + 0, NULL, + strlen("nobody"), "nobody", + 0, NULL, + 443, kSecProtocolTypeHTTPS, kSecAuthenticationTypeDefault, + strlen("weakpass"), "weakpass", + NULL); + if (status && status != errSecDuplicateItem) { // ignore error if duplicate + fprintf(stderr, "Unable to add \"test2.subdomain.apple.com\" internet password: error %d\n", (int)status); + goto error_exit; + } + + /* add a Mail password */ + status = SecKeychainAddInternetPassword(keychain, + strlen("mail.apple.com"), "mail.apple.com", + 0, NULL, + strlen("testacct"), "testacct", + 0, NULL, + 143, kSecProtocolTypeIMAP, kSecAuthenticationTypeDefault, + strlen("testpass"), "testpass", + NULL); + if (status && status != errSecDuplicateItem) { // ignore error if duplicate + fprintf(stderr, "Unable to add \"mail.apple.com\" internet password: error %d\n", (int)status); + goto error_exit; + } + + /* if an item was already in the keychain from a previous run, we can ignore the error */ + if (status == errSecDuplicateItem) + status = noErr; + +error_exit: + + if (keychain) CFRelease(keychain); + PrintTestResult("TestAddItems", status, noErr); + + return (int)status; +} + + +int CheckResults(CFTypeRef results, CFIndex minMatchesExpected, CFIndex maxMatchesExpected) +{ + OSStatus status = noErr; + if (debug) { + PrintCFThing(results); + } + if (minMatchesExpected > 0) { + CFIndex matchesFound; + if (CFGetTypeID(results) == CFArrayGetTypeID()) { + // multiple items returned as an array + matchesFound = CFArrayGetCount(results); + } + else { + // single item returned as either a dictionary or an item reference + matchesFound = (results) ? 1 : 0; + } + if (debug) { + fprintf(stdout, "### Items matched: %d (minimum expected: %d", + (int)matchesFound, (int)minMatchesExpected); + if (maxMatchesExpected < MAXITEMS) + fprintf(stdout, ", maximum expected: %d", (int)minMatchesExpected); + fprintf(stdout, ")\n"); + fflush(stdout); + } + if (matchesFound < minMatchesExpected || + matchesFound > maxMatchesExpected) { + /* should not happen, unless SecItemCopyMatching has a bug */ + status = errSecInternalError; + } + } + return (int)status; +} + + +#pragma mark -- Individual Test Cases -- + + +int FindCertificateByEmail(CFStringRef emailStr, + CFTypeRef returnType, + CFTypeRef matchLimit, + CFIndex minMatchesExpected, + OSStatus expected) +{ + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + /* set up the query */ + CFDictionaryAddValue( query, kSecClass, kSecClassCertificate ); + CFDictionaryAddValue( query, kSecMatchEmailAddressIfPresent, emailStr ); + CFDictionaryAddValue( query, kSecMatchLimit, matchLimit ); + CFDictionaryAddValue( query, returnType, kCFBooleanTrue ); + + CFTypeRef results = NULL; + if (debug) { + PrintStringToMatch(emailStr); + } + + OSStatus status = SecItemCopyMatching(query, &results); + + if (!status && results) { + status = CheckResults(results, minMatchesExpected, MAXITEMS); + CFRelease(results); + } + if (query) + CFRelease(query); + + PrintTestResult("FindCertificateByEmail", status, expected); + + return (status==expected) ? (int)noErr : (int)status; +} + + +int FindCertificateByLabel(CFStringRef labelStr, + CFTypeRef returnType, + CFTypeRef matchLimit, + CFIndex minMatchesExpected, + CFIndex maxMatchesExpected, + OSStatus expected) +{ + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + /* set up the query */ + CFDictionaryAddValue( query, kSecClass, kSecClassCertificate ); + CFDictionaryAddValue( query, kSecAttrLabel, labelStr ); + CFDictionaryAddValue( query, kSecMatchLimit, matchLimit ); + CFDictionaryAddValue( query, returnType, kCFBooleanTrue ); + + CFTypeRef results = NULL; + if (debug) { + PrintStringToMatch(labelStr); + } + + OSStatus status = SecItemCopyMatching(query, &results); + + if (!status && results) { + status = CheckResults(results, minMatchesExpected, maxMatchesExpected); + CFRelease(results); + } + if (query) + CFRelease(query); + + PrintTestResult("FindCertificateByLabel", status, expected); + + return (status==expected) ? (int)noErr : (int)status; +} + + +int FindCertificateByNameInSubject(CFStringRef nameStr, + CFTypeRef matchType, + CFTypeRef returnType, + CFTypeRef matchLimit, + CFIndex minMatchesExpected, + OSStatus expected) +{ + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + /* set up the query */ + CFDictionaryAddValue( query, kSecClass, kSecClassCertificate ); + CFDictionaryAddValue( query, matchType, nameStr ); + CFDictionaryAddValue( query, kSecMatchLimit, matchLimit ); + CFDictionaryAddValue( query, returnType, kCFBooleanTrue ); + + CFTypeRef results = NULL; + if (debug) { + PrintStringToMatch(nameStr); + } + + OSStatus status = SecItemCopyMatching(query, &results); + + if (!status && results) { + status = CheckResults(results, minMatchesExpected, MAXITEMS); + CFRelease(results); + } + if (query) + CFRelease(query); + + PrintTestResult("FindCertificateByNameInSubject", status, expected); + + return (status==expected) ? (int)noErr : (int)status; +} + + +int FindCertificateByNameAndPolicy(CFStringRef nameStr, + CFTypeRef policyIdentifier, + Boolean isClientPolicy, + CFTypeRef returnType, + CFTypeRef matchLimit, + CFIndex minMatchesExpected, + OSStatus expected) +{ + /* given the policy OID, create a SecPolicyRef */ + SecPolicyRef policy = SecPolicyCreateWithOID(policyIdentifier); + if (policy == NULL) + return errSecPolicyNotFound; + if (isClientPolicy == TRUE) { + /* specify the kSecPolicyClient property key for this policy */ + const void *keys[] = { kSecPolicyClient }; + const void *values[] = { kCFBooleanTrue }; + CFDictionaryRef properties = CFDictionaryCreate(NULL, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + SecPolicySetProperties(policy, properties); + } + + const void *keys[] = { + kSecClass, + kSecMatchSubjectContains, + kSecMatchPolicy, + kSecMatchLimit, + returnType + }; + const void *values[] = { + kSecClassCertificate, + nameStr, + policy, + matchLimit, + kCFBooleanTrue + }; + + OSStatus status = noErr; + CFTypeRef results = NULL; + CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + if (debug) { + PrintStringToMatch(nameStr); + PrintStringToMatch(CFCopyDescription(policyIdentifier)); + } + + status = SecItemCopyMatching(query, &results); + + if (!status && results) { + status = CheckResults(results, minMatchesExpected, MAXITEMS); + CFRelease(results); + } + if (query) + CFRelease(query); + if (policy) + CFRelease(policy); + + PrintTestResult("FindCertificateByNameAndPolicy", status, expected); + + return (status==expected) ? (int)noErr : (int)status; +} + + +int FindCertificateByNameAndValidDate(CFStringRef nameStr, + CFTypeRef validOnDate, + CFTypeRef returnType, + CFTypeRef matchLimit, + CFIndex minMatchesExpected, + OSStatus expected) +{ + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + /* set up the query */ + CFDictionaryAddValue( query, kSecClass, kSecClassCertificate ); + CFDictionaryAddValue( query, kSecMatchSubjectContains, nameStr ); + CFDictionaryAddValue( query, kSecMatchValidOnDate, validOnDate ); // value may be a CFDateRef or a CFNullRef + CFDictionaryAddValue( query, kSecMatchLimit, matchLimit ); + CFDictionaryAddValue( query, returnType, kCFBooleanTrue ); + + CFTypeRef results = NULL; + if (debug) { + PrintStringToMatch(nameStr); + PrintStringToMatch(CFCopyDescription(validOnDate)); + } + + OSStatus status = SecItemCopyMatching(query, &results); + + if (!status && results) { + status = CheckResults(results, minMatchesExpected, MAXITEMS); + CFRelease(results); + } + if (query) + CFRelease(query); + + PrintTestResult("FindCertificateByNameAndValidDate", status, expected); + + return (status==expected) ? (int)noErr : (int)status; +} + + +int FindCertificateForSMIMEEncryption(CFStringRef emailAddr, + CFTypeRef validOnDate, + CFTypeRef returnType, + CFTypeRef matchLimit, + CFIndex minMatchesExpected, + OSStatus expected) +{ + /* create a SecPolicyRef for S/MIME */ + SecPolicyRef policy = SecPolicyCreateWithOID(kSecPolicyAppleSMIME); + if (policy == NULL) + return errSecPolicyNotFound; + + CFMutableDictionaryRef properties = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + /* property 1: must match email address */ + CFDictionaryAddValue( properties, kSecPolicyName, emailAddr ); + /* property 2: must have "key encipherment" key usage to be used for encryption */ + CFDictionaryAddValue( properties, kSecPolicyKU_KeyEncipherment, kCFBooleanTrue ); + + SecPolicySetProperties(policy, properties); + + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + /* set up the query */ + CFDictionaryAddValue( query, kSecClass, kSecClassCertificate ); + CFDictionaryAddValue( query, kSecMatchPolicy, policy ); + CFDictionaryAddValue( query, kSecMatchValidOnDate, validOnDate ); + CFDictionaryAddValue( query, kSecMatchLimit, matchLimit ); + CFDictionaryAddValue( query, returnType, kCFBooleanTrue ); + + CFTypeRef results = NULL; + if (debug) { + PrintStringToMatch(emailAddr); + PrintStringToMatch(CFCopyDescription(kSecPolicyAppleSMIME)); + PrintStringToMatch(CFCopyDescription(validOnDate)); + } + + OSStatus status = SecItemCopyMatching(query, &results); + + if (!status && results) { + status = CheckResults(results, minMatchesExpected, MAXITEMS); + CFRelease(results); + } + if (query) + CFRelease(query); + if (policy) + CFRelease(policy); + if (properties) + CFRelease(properties); + + PrintTestResult("FindCertificateForSMIMEEncryption", status, expected); + + return (status==expected) ? (int)noErr : (int)status; +} + + +int FindPreferredCertificateForSMIMEEncryption(CFStringRef emailAddr, + CFTypeRef validOnDate) +{ + // Note: this function assumes that a preferred certificate has been set up + // previously for the given email address. This is handled in the calling + // function. + + OSStatus status = noErr; + SecCertificateRef preferredCertificate = NULL; + SecCertificateRef validatedCertificate = NULL; + + // Pass an explicit key usage value to SecCertificateCopyPreferred to test + CFArrayRef keyUsage = CFArrayCreate(kCFAllocatorDefault, (const void **)&kSecAttrCanEncrypt, 1, &kCFTypeArrayCallBacks); + + preferredCertificate = SecCertificateCopyPreferred(emailAddr, keyUsage); + if (!preferredCertificate) + status = errSecItemNotFound; // our test expects a preferred certificate to exist, so we return an error + if (keyUsage) + CFRelease(keyUsage); + + if (!status && preferredCertificate) { + // We found a preferred certificate, but it may have expired. + // Verify the preferred certificate by looking up all certificates which + // are valid for SMIME encryption, and using the kSecMatchItemList query + // parameter to filter out everything but our preferred certificate. If + // we end up with 0 results, the preferred certificate wasn't valid. + + // set up the S/MIME policy first to check for the Key Encipherment key usage (needed for encryption) + SecPolicyRef policy = SecPolicyCreateWithOID(kSecPolicyAppleSMIME); + CFDictionaryRef properties = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&kSecPolicyKU_KeyEncipherment, (const void **)&kCFBooleanTrue, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + status = SecPolicySetProperties(policy, properties); + CFRelease(properties); + + // set up an item list consisting of just our preferred certificate + CFArrayRef itemList = CFArrayCreate(kCFAllocatorDefault, (const void **)&preferredCertificate, 1, &kCFTypeArrayCallBacks); + + // set up the query + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue( query, kSecClass, kSecClassCertificate ); + CFDictionaryAddValue( query, kSecMatchPolicy, policy ); + CFDictionaryAddValue( query, kSecMatchValidOnDate, validOnDate ); + CFDictionaryAddValue( query, kSecMatchItemList, itemList ); + CFDictionaryAddValue( query, kSecMatchLimit, kSecMatchLimitOne ); // only need to match one item! + CFDictionaryAddValue( query, kSecReturnRef, kCFBooleanTrue ); + + if (debug) { + PrintStringToMatch(emailAddr); + PrintStringToMatch(CFCopyDescription(validOnDate)); + } + + status = SecItemCopyMatching(query, (CFTypeRef*)&validatedCertificate); + + if (!status && validatedCertificate) { + status = CheckResults(validatedCertificate, 1, 1); // expect exactly 1 result + CFRelease(validatedCertificate); + } + if (query) + CFRelease(query); + if (policy) + CFRelease(policy); + if (itemList) + CFRelease(itemList); + } + else if (!quiet) + fprintf(stderr, "FindPreferredCertificateForSMIMEEncryption: unexpected error %d\n", (int)status); + + if (preferredCertificate) + CFRelease(preferredCertificate); + + PrintTestResult("FindPreferredCertificateForSMIMEEncryption", status, noErr); + + return (status==noErr) ? (int)noErr : (int)status; +} + + +int SetPreferredCertificateForSMIMEEncryption(CFStringRef nameStr, + CFStringRef emailAddr) +{ + // find the certificate exactly matching the given common name + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + CFDictionaryAddValue( query, kSecClass, kSecClassCertificate ); + CFDictionaryAddValue( query, kSecMatchSubjectWholeString, nameStr ); + CFDictionaryAddValue( query, kSecMatchLimit, kSecMatchLimitOne ); + CFDictionaryAddValue( query, kSecReturnRef, kCFBooleanTrue ); + + CFTypeRef results = NULL; + OSStatus status = SecItemCopyMatching(query, &results); + + if (!quiet && status) + fprintf(stderr, "SetPreferredCertificateForSMIMEEncryption: SecItemCopyMatching error %d\n", (int)status); + + if (!status && results) { + // since we asked for kSecMatchLimitOne, the result is a single item + SecCertificateRef certificate = (SecCertificateRef) results; + if (SecCertificateGetTypeID() != CFGetTypeID(certificate)) { + fprintf(stderr, "SetPreferredCertificateForSMIMEEncryption: unexpected result type!\n"); + } + else { + // Pass an explicit key usage value to SecCertificateSetPreferred to test + CFArrayRef keyUsage = CFArrayCreate(kCFAllocatorDefault, (const void **)&kSecAttrCanEncrypt, 1, &kCFTypeArrayCallBacks); + status = SecCertificateSetPreferred(certificate, emailAddr, keyUsage); + if (!quiet && status) + fprintf(stderr, "SetPreferredCertificateForSMIMEEncryption: SecCertificateSetPreferred error %d\n", (int)status); + if (keyUsage) + CFRelease(keyUsage); + } + CFRelease(results); + } + if (query) + CFRelease(query); + + return (status==noErr) ? (int)noErr : (int)status; +} + + +int FindIdentityByName(CFStringRef nameStr, + CFTypeRef returnType, + CFTypeRef matchLimit, + CFIndex minMatchesExpected, + OSStatus expected) +{ + const void *keys[] = { + kSecClass, + kSecMatchSubjectContains, + kSecMatchLimit, + returnType + }; + const void *values[] = { + kSecClassIdentity, + nameStr, + matchLimit, + kCFBooleanTrue + }; + + OSStatus status = noErr; + CFTypeRef results = NULL; + CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + if (debug) PrintStringToMatch(nameStr); + + status = SecItemCopyMatching(query, &results); + + if (!status && results) { + status = CheckResults(results, minMatchesExpected, MAXITEMS); + CFRelease(results); + } + if (query) + CFRelease(query); + + PrintTestResult("FindIdentityByName", status, expected); + + return (status==expected) ? (int)noErr : (int)status; +} + + +int FindIdentityByPolicy(CFTypeRef policyIdentifier, + Boolean isClientPolicy, + CFTypeRef returnType, + CFTypeRef matchLimit, + CFIndex minMatchesExpected, + OSStatus expected) +{ + /* given the policy OID, create a SecPolicyRef */ + SecPolicyRef policy = SecPolicyCreateWithOID(policyIdentifier); + if (policy == NULL) + return errSecPolicyNotFound; + if (isClientPolicy == TRUE) { + /* specify the kSecPolicyClient property key for this policy */ + const void *keys[] = { kSecPolicyClient }; + const void *values[] = { kCFBooleanTrue }; + CFDictionaryRef properties = CFDictionaryCreate(NULL, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + SecPolicySetProperties(policy, properties); + } + + const void *keys[] = { + kSecClass, + kSecMatchPolicy, + kSecMatchLimit, + returnType + }; + const void *values[] = { + kSecClassIdentity, + policy, + matchLimit, + kCFBooleanTrue + }; + + OSStatus status = noErr; + CFTypeRef results = NULL; + CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + if (debug) PrintStringToMatch(CFCopyDescription(policyIdentifier)); + + status = SecItemCopyMatching(query, &results); + + if (!status && results) { + status = CheckResults(results, minMatchesExpected, MAXITEMS); + CFRelease(results); + } + if (query) + CFRelease(query); + if (policy) + CFRelease(policy); + + PrintTestResult("FindIdentityByPolicy", status, expected); + + return (status==expected) ? (int)noErr : (int)status; +} + + +int FindIdentityByPolicyAndValidDate(CFTypeRef policyIdentifier, + Boolean isClientPolicy, + CFTypeRef validOnDate, + CFStringRef forbidStr, + CFTypeRef returnType, + CFTypeRef matchLimit, + CFIndex minMatchesExpected, + OSStatus expected) +{ + /* given the policy OID, create a SecPolicyRef */ + SecPolicyRef policy = SecPolicyCreateWithOID(policyIdentifier); + if (policy == NULL) + return errSecPolicyNotFound; + if (isClientPolicy == TRUE) { + /* specify the kSecPolicyClient property key for this policy */ + const void *keys[] = { kSecPolicyClient }; + const void *values[] = { kCFBooleanTrue }; + CFDictionaryRef properties = CFDictionaryCreate(NULL, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + SecPolicySetProperties(policy, properties); + } + + const void *keys[] = { + kSecClass, + kSecMatchPolicy, + kSecMatchValidOnDate, + kSecMatchLimit, + returnType + }; + const void *values[] = { + kSecClassIdentity, + policy, + validOnDate, + matchLimit, + kCFBooleanTrue + }; + + OSStatus status = noErr; + CFTypeRef results = NULL; + CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + if (debug) PrintStringToMatch(CFCopyDescription(policyIdentifier)); + + status = SecItemCopyMatching(query, &results); + + // check returned items for forbidStr as a substring in the label attribute; + // return errSecInternalError if found + if (!status && results && forbidStr) { + if (CFArrayGetTypeID() == CFGetTypeID(results)) { + CFArrayRef items = (CFArrayRef) results; + CFIndex ix, count = CFArrayGetCount(results); + for (ix=0; ix + CFArrayRef keyUsage = CFArrayCreate(kCFAllocatorDefault, (const void **)&kSecAttrCanSign, 1, &kCFTypeArrayCallBacks); + + preferredIdentity = SecIdentityCopyPreferred(emailAddr, keyUsage, NULL); + if (!preferredIdentity) + status = errSecItemNotFound; // our test expects a preferred identity to exist, so we return an error + if (keyUsage) + CFRelease(keyUsage); + + if (!status && preferredIdentity) { + // We found a preferred identity, but it may have expired. + // Verify the preferred identity by looking up all identities which + // are valid for SMIME signing, and using the kSecMatchItemList query + // parameter to filter out everything but our preferred identity. If + // we end up with 0 results, the preferred identity wasn't valid. + + // set up the S/MIME policy first to check for Digital Signature key usage + SecPolicyRef policy = SecPolicyCreateWithOID(kSecPolicyAppleSMIME); + CFDictionaryRef properties = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&kSecPolicyKU_DigitalSignature, (const void **)&kCFBooleanTrue, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + status = SecPolicySetProperties(policy, properties); + CFRelease(properties); + + // set up an item list consisting of just our preferred identity + CFArrayRef itemList = CFArrayCreate(kCFAllocatorDefault, (const void **)&preferredIdentity, 1, &kCFTypeArrayCallBacks); + + // set up the query + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue( query, kSecClass, kSecClassIdentity ); + CFDictionaryAddValue( query, kSecMatchPolicy, policy ); + CFDictionaryAddValue( query, kSecMatchValidOnDate, validOnDate ); + CFDictionaryAddValue( query, kSecMatchItemList, itemList ); + CFDictionaryAddValue( query, kSecMatchLimit, kSecMatchLimitOne ); // only need to match one item! + CFDictionaryAddValue( query, kSecReturnRef, kCFBooleanTrue ); + + if (debug) { + PrintStringToMatch(emailAddr); + PrintStringToMatch(CFCopyDescription(validOnDate)); + } + + status = SecItemCopyMatching(query, (CFTypeRef*)&validatedIdentity); + + if (!status && validatedIdentity) { + status = CheckResults(validatedIdentity, 1, 1); // expect exactly 1 result + CFRelease(validatedIdentity); + } + if (query) + CFRelease(query); + if (policy) + CFRelease(policy); + if (itemList) + CFRelease(itemList); + } + else if (!quiet) + fprintf(stderr, "FindPreferredIdentityForSMIMESigning: unexpected error %d\n", (int)status); + + if (preferredIdentity) + CFRelease(preferredIdentity); + + PrintTestResult("FindPreferredIdentityForSMIMESigning", status, noErr); + + return (status==noErr) ? (int)noErr : (int)status; +} + + +int SetPreferredIdentityForSMIMESigning(CFStringRef nameStr, + CFStringRef emailAddr) +{ + // find the identity exactly matching the given common name + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + CFDictionaryAddValue( query, kSecClass, kSecClassIdentity ); + CFDictionaryAddValue( query, kSecMatchSubjectWholeString, nameStr ); + CFDictionaryAddValue( query, kSecMatchLimit, kSecMatchLimitOne ); + CFDictionaryAddValue( query, kSecReturnRef, kCFBooleanTrue ); + + CFTypeRef results = NULL; + OSStatus status = SecItemCopyMatching(query, &results); + + if (!quiet && status) + fprintf(stderr, "SetPreferredIdentityForSMIMESigning: SecItemCopyMatching error %d\n", (int)status); + + if (!status && results) { + // since we asked for kSecMatchLimitOne, the result is a single SecIdentityRef + SecIdentityRef identity = (SecIdentityRef) results; + if (SecIdentityGetTypeID() != CFGetTypeID(identity)) { + fprintf(stderr, "SetPreferredCertificateForSMIMEEncryption: unexpected result type!\n"); + } + else { + // Pass an explicit key usage value to SecIdentitySetPreferred to test + CFArrayRef keyUsage = CFArrayCreate(kCFAllocatorDefault, (const void **)&kSecAttrCanSign, 1, &kCFTypeArrayCallBacks); + status = SecIdentitySetPreferred(identity, emailAddr, keyUsage); + if (!quiet && status) + fprintf(stderr, "SetPreferredIdentityForSMIMESigning: SecIdentitySetPreferred error %d\n", (int)status); + if (keyUsage) + CFRelease(keyUsage); + } + CFRelease(results); + } + if (query) + CFRelease(query); + + return (status==noErr) ? (int)noErr : (int)status; +} + + +int FindGenericPasswordByAccount(CFStringRef accountStr, + CFTypeRef returnType, + CFTypeRef matchLimit, + CFIndex minMatchesExpected, + OSStatus expected) +{ + const void *keys[] = { + kSecClass, + kSecAttrAccount, + kSecMatchLimit, + returnType + }; + const void *values[] = { + kSecClassGenericPassword, + accountStr, + matchLimit, + kCFBooleanTrue + }; + + OSStatus status = noErr; + CFTypeRef results = NULL; + CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + if (debug) PrintStringToMatch(accountStr); + + status = SecItemCopyMatching(query, &results); + + if (!status && results) { + status = CheckResults(results, minMatchesExpected, MAXITEMS); + CFRelease(results); + } + if (query) + CFRelease(query); + + PrintTestResult("FindGenericPasswordByAccount", status, expected); + + return (status==expected) ? (int)noErr : (int)status; +} + + +int FindGenericPasswordByAccountAndService(CFStringRef accountStr, + CFStringRef serviceStr, + CFTypeRef returnType, + CFTypeRef matchLimit, + CFIndex minMatchesExpected, + OSStatus expected) +{ + const void *keys[] = { + kSecClass, + kSecAttrAccount, + kSecAttrService, + kSecMatchLimit, + returnType + }; + const void *values[] = { + kSecClassGenericPassword, + accountStr, + serviceStr, + matchLimit, + kCFBooleanTrue + }; + + OSStatus status = noErr; + CFTypeRef results = NULL; + CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + if (debug) { + PrintStringToMatch(accountStr); + PrintStringToMatch(serviceStr); + } + status = SecItemCopyMatching(query, &results); + + if (!status && results) { + status = CheckResults(results, minMatchesExpected, MAXITEMS); + CFRelease(results); + } + if (query) + CFRelease(query); + + PrintTestResult("FindGenericPasswordByAccountAndService", status, expected); + + return (status==expected) ? (int)noErr : (int)status; +} + + +int FindInternetPasswordByAccount(CFStringRef accountStr, + CFTypeRef returnType, + CFTypeRef matchLimit, + CFIndex minMatchesExpected, + OSStatus expected) +{ + const void *keys[] = { + kSecClass, + kSecAttrAccount, + kSecMatchLimit, + returnType + }; + const void *values[] = { + kSecClassInternetPassword, + accountStr, + matchLimit, + kCFBooleanTrue + }; + + OSStatus status = noErr; + CFTypeRef results = NULL; + CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + if (debug) PrintStringToMatch(accountStr); + + status = SecItemCopyMatching(query, &results); + + if (!status && results) { + status = CheckResults(results, minMatchesExpected, MAXITEMS); + CFRelease(results); + } + if (query) + CFRelease(query); + + PrintTestResult("FindInternetPasswordByAccount", status, expected); + + return (status==expected) ? (int)noErr : (int)status; +} + + +int FindInternetPasswordByAccountAndServer(CFStringRef accountStr, + CFStringRef serverStr, + CFTypeRef returnType, + CFTypeRef matchLimit, + CFIndex minMatchesExpected, + OSStatus expected) +{ + const void *keys[] = { + kSecClass, + kSecAttrAccount, + kSecAttrServer, + kSecMatchLimit, + returnType + }; + const void *values[] = { + kSecClassInternetPassword, + accountStr, + serverStr, + matchLimit, + kCFBooleanTrue + }; + + OSStatus status = noErr; + CFTypeRef results = NULL; + CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + if (debug) { + PrintStringToMatch(accountStr); + PrintStringToMatch(serverStr); + } + status = SecItemCopyMatching(query, &results); + + if (!status && results) { + status = CheckResults(results, minMatchesExpected, MAXITEMS); + CFRelease(results); + } + if (query) + CFRelease(query); + + PrintTestResult("FindInternetPasswordByAccountAndServer", status, expected); + + return (status==expected) ? (int)noErr : (int)status; +} + + +int FindMailPassword( + CFStringRef account, + CFStringRef server) +{ + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + SInt16 port = 143; + CFNumberRef portNumber = CFNumberCreate(NULL, kCFNumberSInt16Type, &port); + + // set up query for a Mail password (IMAP, port 143) for given account and server + CFDictionaryAddValue( query, kSecClass, kSecClassInternetPassword ); + CFDictionaryAddValue( query, kSecAttrAccount, account ); + CFDictionaryAddValue( query, kSecAttrServer, server ); + CFDictionaryAddValue( query, kSecAttrProtocol, kSecAttrProtocolIMAP ); + CFDictionaryAddValue( query, kSecAttrPort, portNumber ); + CFDictionaryAddValue( query, kSecMatchLimit, kSecMatchLimitOne ); + CFDictionaryAddValue( query, kSecReturnData, kCFBooleanTrue ); + + CFTypeRef results = NULL; + OSStatus status = SecItemCopyMatching(query, &results); + + if (!quiet && status) + fprintf(stderr, "FindMailPassword: SecItemCopyMatching error %d\n", (int)status); + + if (!status && results) { + // since we asked for kSecMatchLimitOne w/kSecReturnData, the result is the found password + CFDataRef password = (CFDataRef) results; + if (CFDataGetTypeID() != CFGetTypeID(password)) { + fprintf(stderr, "FindMailPassword: unexpected result type!\n"); + } + else { + if (debug) CFShow(password); + } + CFRelease(results); + } + if (query) + CFRelease(query); + if (portNumber) + CFRelease(portNumber); + + return (status==noErr) ? (int)noErr : (int)status; +} + + + +const CFStringRef gPrefix = CFSTR("Test Key"); +const CFStringRef gLabel = CFSTR("Test AES Encryption Key"); +const CFStringRef gUUID = CFSTR("550e8400-e29b-41d4-a716-446655441234"); + +// CreateSymmetricKey will create a new AES-128 symmetric encryption key +// with the provided label, application label, and application tag. +// Each of those attributes is optional, but only the latter two +// (application label and application tag) are considered part of the +// key's "unique" attribute set. Previously, if you attempted to create a +// key which differs only in the label attribute (but not in the other two) +// then the attempt would fail and leave a "turd" key with no label in your +// keychain: , fixed in 11A268a. + +int CreateSymmetricKey( + CFStringRef keyLabel, + CFStringRef keyAppLabel, + CFStringRef keyAppTag, + OSStatus expected) +{ + OSStatus status; + int keySizeValue = 128; + CFNumberRef keySize = CFNumberCreate(NULL, kCFNumberIntType, &keySizeValue); + + // get a SecKeychainRef for the keychain in which we want the key to be created + // (this step is optional, but if omitted, the key is NOT saved in any keychain!) + SecKeychainRef keychain = NULL; + status = SecKeychainCopyDefault(&keychain); + + // create a SecAccessRef to set up the initial access control settings for this key + // (this step is optional; if omitted, the creating application has access to the key) + // note: the access descriptor should be the same string as will be used for the item's label, + // since it's the string that is displayed by the access confirmation dialog to describe the item. + SecAccessRef access = NULL; + status = SecAccessCreate(gLabel, NULL, &access); + + // create a dictionary of parameters describing the key we want to create + CFMutableDictionaryRef params = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + CFDictionaryAddValue( params, kSecClass, kSecClassKey ); + CFDictionaryAddValue( params, kSecUseKeychain, keychain ); + CFDictionaryAddValue( params, kSecAttrAccess, access ); + CFDictionaryAddValue( params, kSecAttrKeyClass, kSecAttrKeyClassSymmetric ); + CFDictionaryAddValue( params, kSecAttrKeyType, kSecAttrKeyTypeAES ); + CFDictionaryAddValue( params, kSecAttrKeySizeInBits, keySize ); + CFDictionaryAddValue( params, kSecAttrIsPermanent, kCFBooleanTrue ); + CFDictionaryAddValue( params, kSecAttrCanEncrypt, kCFBooleanTrue ); + CFDictionaryAddValue( params, kSecAttrCanDecrypt, kCFBooleanTrue ); + CFDictionaryAddValue( params, kSecAttrCanWrap, kCFBooleanFalse ); + CFDictionaryAddValue( params, kSecAttrCanUnwrap, kCFBooleanFalse ); + if (keyLabel) + CFDictionaryAddValue( params, kSecAttrLabel, keyLabel ); + if (keyAppLabel) + CFDictionaryAddValue( params, kSecAttrApplicationLabel, keyAppLabel ); + if (keyAppTag) + CFDictionaryAddValue( params, kSecAttrApplicationTag, keyAppTag ); + + // generate the key + CFErrorRef error = NULL; + SecKeyRef key = SecKeyGenerateSymmetric(params, &error); + + // print result and clean up + if (debug) { + if (key == NULL) { + CFStringRef desc = (error) ? CFErrorCopyDescription(error) : CFRetain(CFSTR("(no result!")); + PrintCFStringWithFormat("SecKeyGenerateSymmetric failed: %s\n", desc); + CFRelease(desc); + } + else { + CFStringRef desc = CFCopyDescription(key); + PrintCFStringWithFormat("SecKeyGenerateSymmetric succeeded: %s\n", desc); + CFRelease(desc); + } + } + status = (error) ? (OSStatus) CFErrorGetCode(error) : noErr; +// if (status == errSecDuplicateItem) +// status = noErr; // it's OK if the key already exists + + if (key) CFRelease(key); + if (error) CFRelease(error); + if (params) CFRelease(params); + if (keychain) CFRelease(keychain); + if (access) CFRelease(access); + + PrintTestResult("CreateSymmetricKey", status, expected); + + return status; +} + + +int FindSymmetricKey( + CFStringRef keyLabel, + CFStringRef keyAppLabel, + CFStringRef keyAppTag, + OSStatus expected) +{ + // create a dictionary of parameters describing the key we want to find, + // and how we want the result to be returned + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + CFDictionaryAddValue( query, kSecClass, kSecClassKey ); + CFDictionaryAddValue( query, kSecAttrKeyClass, kSecAttrKeyClassSymmetric ); + CFDictionaryAddValue( query, kSecMatchLimit, kSecMatchLimitOne ); // we only want the first match + CFDictionaryAddValue( query, kSecReturnRef, kCFBooleanTrue ); // we want the result as a SecKeyRef + CFDictionaryAddValue( query, kSecReturnAttributes, kCFBooleanTrue ); // we also want the found item's attributes + if (keyLabel) + CFDictionaryAddValue( query, kSecAttrLabel, keyLabel ); + if (keyAppLabel) + CFDictionaryAddValue( query, kSecAttrApplicationLabel, keyAppLabel ); + if (keyAppTag) + CFDictionaryAddValue( query, kSecAttrApplicationLabel, keyAppTag ); + + CFTypeRef result = NULL; + OSStatus status = SecItemCopyMatching(query, &result); + + // print result and clean up + if (debug) { + if (status == noErr) { + fprintf(stdout, "SecItemCopyMatching succeeded; found key\n"); + PrintCFThing(result); + } + else if (status == errSecItemNotFound) { + fprintf(stdout, "SecItemCopyMatching: item not found\n"); + } + else { + fprintf(stdout, "SecItemCopyMatching: failed! (error %d)\n", (int)status); + } + } + + SecKeyRef key = NULL; + if (result) { + // since we asked for both the item reference and the item attributes, + // we expect a dictionary to be returned... + if (CFDictionaryGetTypeID() == CFGetTypeID(result)) { + if (CFDictionaryGetValueIfPresent(result, kSecValueRef, (CFTypeRef*)&key)) + CFRetain(key); + } + CFRelease(result); // all done with result dictionary + } + + if (key) CFRelease(key); + if (query) CFRelease(query); + + PrintTestResult("FindSymmetricKey", status, expected); + + return status; +} + + +int FindAndDeleteItemsByName( + CFStringRef nameStr, + CFStringRef accountStr, + CFTypeRef itemClass, + CFTypeRef matchLimit, + CFIndex minMatchesExpected, + OSStatus expected) +{ + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + CFTypeRef nameMatchKey; + if (CFEqual(itemClass, kSecClassCertificate) || + CFEqual(itemClass, kSecClassIdentity)) { + nameMatchKey = kSecMatchSubjectStartsWith; /* must start with nameStr */ + } + else { + nameMatchKey = kSecAttrLabel; /* nameStr must exactly match label */ + } + + /* set up the query */ + CFDictionaryAddValue( query, kSecClass, itemClass ); + CFDictionaryAddValue( query, nameMatchKey, nameStr); + CFDictionaryAddValue( query, kSecMatchLimit, matchLimit); + if (accountStr) { + CFDictionaryAddValue( query, kSecAttrAccount, accountStr); + } + + CFTypeRef results = NULL; + if (debug) { + PrintStringToMatch(nameStr); + } + + OSStatus status = SecItemCopyMatching(query, &results); + + if (!status) { + /* Make sure that we found the items we expected to find */ + status = CheckResults(results, minMatchesExpected, MAXITEMS); + CFRelease(results); + } + + if (!status) { + /* OK, now the real reason we're here... the same query must work for SecItemDelete */ + status = SecItemDelete(query); + + PrintTestResult("FindAndDeleteItemsByName: deleting items", status, expected); + } + + if (!status) { + /* re-run the same query... should find no matching items this time */ + status = SecItemCopyMatching(query, &results); + if (!status) { + /* oops... we still found matches using this query */ + int count = (int)CFArrayGetCount(results); + fprintf(stderr, "### still found %d items, expected 0\n", count); + CFRelease(results); + } + PrintTestResult("FindAndDeleteItemsByName: find after delete", status, errSecItemNotFound); + + status = (status == errSecItemNotFound) ? expected : errSecInternalError; + } + + if (query) + CFRelease(query); + + return (status==expected) ? (int)noErr : (int)status; +} + + +#pragma mark -- Test Functions -- + + +int TestIdentityLookup() +{ + int result = 0; + + // look up identity by name, want first result as a SecIdentityRef + result += FindIdentityByName(CFSTR("Test SSL User"), kSecReturnRef, kSecMatchLimitOne, 1, noErr); + + // look up existing non-identity certificate by name, expect errSecItemNotFound error + result += FindIdentityByName(CFSTR("Test-5685316-LEAF"), kSecReturnRef, kSecMatchLimitOne, 0, errSecItemNotFound); + + // look up non-existent identity by name, expect errSecItemNotFound error + result += FindIdentityByName(CFSTR("myxlpytk"), kSecReturnRef, kSecMatchLimitOne, 0, errSecItemNotFound); + + // look up identity by policy, want first result as a SecIdentityRef (should find "Test SSL User" identity) + result += FindIdentityByPolicy(kSecPolicyAppleSSL, TRUE, kSecReturnRef, kSecMatchLimitOne, 1, noErr); + + // look up identity by policy, want first result as a CFDictionary of attributes (should find "Test SSL User" identity) + result += FindIdentityByPolicy(kSecPolicyAppleSSL, TRUE, kSecReturnAttributes, kSecMatchLimitOne, 1, noErr); + + // look up identity by policy, expect errSecItemNotFound error (this assumes no code signing identity is present!) + result += FindIdentityByPolicy(kSecPolicyAppleCodeSigning, FALSE, kSecReturnRef, kSecMatchLimitOne, 0, errSecItemNotFound); + + // ------------------------- + // test kSecMatchValidOnDate + // ------------------------- + + // make a valid date which will match at least some identities we used to populate the keychain + CFGregorianDate aCurrentGDate = { 2010, 7, 20, 12, 0, 0 }; // Jul 20 2010 12:00 PM + CFDateRef aCurrentDate = CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(aCurrentGDate, NULL)); + if (FindIdentityByNameAndValidDate(CFSTR("Test SSL User"), aCurrentDate, kSecReturnRef, kSecMatchLimitAll, 1, noErr)) + ++result; + if(aCurrentDate) CFRelease(aCurrentDate); + + // make a date in the past which should NOT match any identities (expect errSecItemNotFound) + CFGregorianDate aPastGDate = { 1984, 7, 20, 12, 0, 0 }; // Jul 20 1984 12:00 PM + CFDateRef aPastDate = CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(aPastGDate, NULL)); + if (FindIdentityByNameAndValidDate(CFSTR("Test SSL User"), aPastDate, kSecReturnRef, kSecMatchLimitAll, 0, errSecItemNotFound)) + ++result; + if(aPastDate) CFRelease(aPastDate); + + // make a date in the future which should NOT match any identities yet (expect errSecItemNotFound) + CFGregorianDate aFutureGDate = { 2034, 7, 20, 12, 0, 0 }; // Jul 20 2034 12:00 PM + CFDateRef aFutureDate = CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(aFutureGDate, NULL)); + if (FindIdentityByNameAndValidDate(CFSTR("Test SSL User"), aFutureDate, kSecReturnRef, kSecMatchLimitAll, 0, errSecItemNotFound)) + ++result; + if(aFutureDate) CFRelease(aFutureDate); + + // make a date in the past which SHOULD match 2 identities we used to populate the keychain + CFGregorianDate aPastValidGDate = { 2007, 12, 20, 12, 0, 0 }; // Dec 20 2007 12:00 PM + CFDateRef aPastValidDate = CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(aPastValidGDate, NULL)); + if (FindIdentityByNameAndValidDate(CFSTR(" 2007"), aPastValidDate, kSecReturnRef, kSecMatchLimitAll, 0, noErr)) + ++result; + + // test the ability of kCFNull to denote "currently valid" (should not find anything, since the " 2007" certs are expired) + if (FindIdentityByNameAndValidDate(CFSTR(" 2007"), kCFNull, kSecReturnRef, kSecMatchLimitAll, 0, errSecItemNotFound)) + ++result; + + // test Ian's bug: ; the 4th argument is a string which should NOT be present in any found items + if (FindIdentityByPolicyAndValidDate(kSecPolicyAppleSMIME, FALSE, kCFNull, CFSTR(" 2007"), kSecReturnAttributes, kSecMatchLimitAll, 0, noErr)) + ++result; + + return result; +} + + +int TestCertificateLookup() +{ + int result = 0; + + //====================================================================== + // item attribute tests (kSecItemAttr* keys) + //====================================================================== + + // %%%TBA: need to flesh out this section with all certificate attributes + + // ------------------------------------------ + // test kSecAttrIssuer & kSecAttrSerialNumber + // ------------------------------------------ + + // look up cert by issuer & serial + // %%%TBA -- underlying support was added in ; need to implement these keys + //CFDictionarySetValue(query, (const void *)kSecAttrIssuer, (const void *)nameStr); + //CFDictionarySetValue(query, (const void *)kSecAttrSerialNumber, (const void *)nameStr); + + // ------------------------- + // test kSecAttrSubjectKeyID + // ------------------------- + + // look up cert by subject key ID + // %%%TBA -- can we get the subject key ID from SecCertificateCopyValues?? + //CFDictionarySetValue(query, (const void *)kSecAttrSubjectKeyID, (const void *)nameStr); + + // ------------------ + // test kSecAttrLabel + // ------------------ + + // look up cert by label, want array of all results (expect only 1) as SecCertificateRef + result += FindCertificateByLabel(CFSTR("com.apple.kerberos.kdc"), + kSecReturnRef, kSecMatchLimitAll, 1, 1, noErr); + + + //====================================================================== + // search attribute tests (kSecMatch* keys) + //====================================================================== + + // ----------------------------------- + // test kSecMatchEmailAddressIfPresent + // ----------------------------------- + + // look up cert by email, want first result as a SecCertificateRef + result += FindCertificateByEmail(CFSTR("security-dev@group.apple.com"), + kSecReturnRef, kSecMatchLimitOne, 0, noErr); + + // look up cert by email, want first result as a CFDictionaryRef of attributes + result += FindCertificateByEmail(CFSTR("security-dev@group.apple.com"), + kSecReturnAttributes, kSecMatchLimitOne, 0, noErr); + + // ----------------------------- + // test kSecMatchSubjectContains + // ----------------------------- + + // look up cert containing name, want array of all results (expect at least 3) as SecCertificateRef + result += FindCertificateByNameInSubject(CFSTR("Test-5685316"), + kSecMatchSubjectContains, kSecReturnRef, kSecMatchLimitAll, 3, noErr); + + // look up non-existent cert by name, expect errSecItemNotFound error + result += FindCertificateByNameInSubject(CFSTR("myxlpytk"), + kSecMatchSubjectContains, kSecReturnRef, kSecMatchLimitOne, 0, errSecItemNotFound); + + // look up cert by name, want array of all results (expect at least 2) as CFDataRef + result += FindCertificateByNameInSubject(CFSTR("Test-5685316"), + kSecMatchSubjectContains, kSecReturnData, kSecMatchLimitAll, 2, noErr); + + // look up cert by name, want array of all results (expect at least 2) as CFDictionaryRef of attributes + result += FindCertificateByNameInSubject(CFSTR("Test-5685316"), + kSecMatchSubjectContains, kSecReturnAttributes, kSecMatchLimitAll, 2, noErr); + + // ------------------------------- + // test kSecMatchSubjectStartsWith + // ------------------------------- + + // look up cert starting with name, want array of all results (expect at least 3) as SecCertificateRef + result += FindCertificateByNameInSubject(CFSTR("Test-568"), + kSecMatchSubjectStartsWith, kSecReturnRef, kSecMatchLimitAll, 3, noErr); + + // look up cert starting with a name which isn't at start, expect errSecItemNotFound error + result += FindCertificateByNameInSubject(CFSTR("5685316"), + kSecMatchSubjectStartsWith, kSecReturnRef, kSecMatchLimitOne, 0, errSecItemNotFound); + + // ----------------------------- + // test kSecMatchSubjectEndsWith + // ----------------------------- + + // look up cert ending with name, want array of all results (expect at least 1) as SecCertificateRef + result += FindCertificateByNameInSubject(CFSTR("LEAF"), + kSecMatchSubjectEndsWith, kSecReturnRef, kSecMatchLimitAll, 1, noErr); + + // look up cert ending with a name which isn't at end, expect errSecItemNotFound error + result += FindCertificateByNameInSubject(CFSTR("Test-"), + kSecMatchSubjectEndsWith, kSecReturnRef, kSecMatchLimitOne, 0, errSecItemNotFound); + + // -------------------------------- + // test kSecMatchSubjectWholeString + // -------------------------------- + + // look up cert by whole name, want first result (expecting 1) as a SecCertificateRef + result += FindCertificateByNameInSubject(CFSTR("Test-5685316-LEAF"), + kSecMatchSubjectWholeString, kSecReturnRef, kSecMatchLimitOne, 1, noErr); + + // look up cert by whole name (which is a substring in other certs), expect errSecItemNotFound error + result += FindCertificateByNameInSubject(CFSTR("Test-568"), + kSecMatchSubjectWholeString, kSecReturnRef, kSecMatchLimitOne, 0, errSecItemNotFound); + + // -------------------- + // test kSecMatchPolicy + // -------------------- + + // look up cert by name and policy (Code Signing), want first result as a SecCertificateRef + result += FindCertificateByNameAndPolicy(CFSTR("Test-7875801"), + kSecPolicyAppleCodeSigning, FALSE, + kSecReturnRef, kSecMatchLimitOne, 0, noErr); + + // look up cert by name and policy (S/MIME), want first result as a SecCertificateRef + result += FindCertificateByNameAndPolicy(CFSTR("Test-"), + kSecPolicyAppleSMIME, FALSE, + kSecReturnRef, kSecMatchLimitOne, 0, noErr); + + // look up cert by name and policy, want array of all results as SecCertificateRef + // (note that we expect an error here, since if all went well, there will be only 1 cert + // matching both name and policy parameters, but we asked for a minimum of 2 matches.) + result += FindCertificateByNameAndPolicy(CFSTR("Test-7875801"), + kSecPolicyAppleCodeSigning, FALSE, + kSecReturnAttributes, kSecMatchLimitAll, 2, errSecInternalError); + + // look up cert by email address for SMIME encryption, date valid today, want array of all results as SecCertificateRef + // (note that a date value of kCFNull is interpreted as the current date) + result += FindCertificateForSMIMEEncryption(CFSTR("smime-test@apple.com"), kCFNull, + kSecReturnRef, kSecMatchLimitAll, 1, noErr); + + // ------------------------- + // test kSecMatchValidOnDate + // ------------------------- + + // make a valid date which will match at least 2 certificates we used to populate the keychain + CFGregorianDate aCurrentGDate = { 2010, 7, 20, 12, 0, 0 }; // Jul 20 2010 12:00 PM + CFDateRef aCurrentDate = CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(aCurrentGDate, NULL)); + if (FindCertificateByNameAndValidDate(CFSTR("Test-"), aCurrentDate, kSecReturnRef, kSecMatchLimitAll, 2, noErr)) + ++result; + if(aCurrentDate) CFRelease(aCurrentDate); + + // make a date in the past which should NOT match any certificates (expect errSecItemNotFound) + CFGregorianDate aPastGDate = { 1984, 7, 20, 12, 0, 0 }; // Jul 20 1984 12:00 PM + CFDateRef aPastDate = CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(aPastGDate, NULL)); + if (FindCertificateByNameAndValidDate(CFSTR("Test-"), aPastDate, kSecReturnRef, kSecMatchLimitAll, 2, errSecItemNotFound)) + ++result; + if(aPastDate) CFRelease(aPastDate); + + // make a date in the future which should NOT match any certificates yet (expect errSecItemNotFound) + CFGregorianDate aFutureGDate = { 2034, 7, 20, 12, 0, 0 }; // Jul 20 2034 12:00 PM + CFDateRef aFutureDate = CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(aFutureGDate, NULL)); + if (FindCertificateByNameAndValidDate(CFSTR("Test-"), aFutureDate, kSecReturnRef, kSecMatchLimitAll, 2, errSecItemNotFound)) + ++result; + if(aFutureDate) CFRelease(aFutureDate); + + return result; +} + + +int TestPreferredIdentityLookup() +{ + int result = 0; + + // set a preferred identity first + if (SetPreferredIdentityForSMIMESigning(CFSTR("Test-SignOnly (S/MIME)"), CFSTR("smime-test@apple.com"))) + ++result; + + // define a valid date for this preferred identity (typically this would just be kCFNull in a real program, meaning "now") + CFGregorianDate aCurrentGDate = { 2010, 7, 27, 21, 0, 0 }; // Jul 27 2010 9:00 PM + CFDateRef aCurrentDate = CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(aCurrentGDate, NULL)); + if (FindPreferredIdentityForSMIMESigning(CFSTR("smime-test@apple.com"), aCurrentDate)) + ++result; + if(aCurrentDate) CFRelease(aCurrentDate); + + // delete identity preference(s) for this email address by setting a NULL identity + if (SecIdentitySetPreferred(NULL, CFSTR("smime-test@apple.com"), 0) != noErr) + ++result; + + return result; +} + + +int TestPreferredCertificateLookup() +{ + int result = 0; + + // set a preferred certificate first + if (SetPreferredCertificateForSMIMEEncryption(CFSTR("Test-Encryption (S/MIME)"), CFSTR("smime-test@apple.com"))) + ++result; + + // define a valid date for this preferred certificate (typically this would just be kCFNull in a real program, meaning "now") + CFGregorianDate aCurrentGDate = { 2010, 7, 27, 21, 0, 0 }; // Jul 27 2010 9:00 PM + CFDateRef aCurrentDate = CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(aCurrentGDate, NULL)); + if (FindPreferredCertificateForSMIMEEncryption(CFSTR("smime-test@apple.com"), aCurrentDate)) + ++result; + if(aCurrentDate) CFRelease(aCurrentDate); + + // delete certificate preference(s) for this email address by setting a NULL identity + if (SecCertificateSetPreferred(NULL, CFSTR("smime-test@apple.com"), 0) != noErr) + ++result; + + return result; +} + + +int TestSymmetricKeyLookup() +{ + int result = 0; + + // look up our symmetric key by label and UUID (it might not exist yet) + if (FindSymmetricKey(gLabel, gUUID, NULL, errSecItemNotFound) != errSecSuccess) { + // create test key (unique by UUID only) + if (CreateSymmetricKey(gLabel, gUUID, NULL, errSecSuccess) != errSecSuccess) + ++result; + // look it up again (it should exist now!) + if (FindSymmetricKey(gLabel, gUUID, NULL, errSecSuccess) != errSecSuccess) + ++result; + } + + // now look up a key whose name is derived from today's date + // (so we can make sure on a daily basis that SecKeyGenerateSymmetric is still working) + CFGregorianDate curGDate = CFAbsoluteTimeGetGregorianDate(CFAbsoluteTimeGetCurrent(), NULL); + CFStringRef curDateLabel = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ (%4d-%02d-%02d)"), + gPrefix, curGDate.year, curGDate.month, curGDate.day); + // + //%%% FIXME Creating a symmetric key with attributes that would duplicate an existing + // key item currently results in a broken key which can't be found: + // + //CFStringRef curAppTag = curDateLabel; // i.e. make sure it will be unique, for now + CFStringRef curAppTag = CFSTR("SecItemFind"); + + // look up our date-based symmetric key by label, UUID, and tag (it might not exist yet) + if (FindSymmetricKey(curDateLabel, gUUID, curAppTag, errSecItemNotFound) != errSecSuccess) { + // create test key (unique by combination of UUID and application tag) + if (CreateSymmetricKey(curDateLabel, gUUID, curAppTag, errSecSuccess) != errSecSuccess) + ++result; + // look it up again (it should exist now!) + if (FindSymmetricKey(curDateLabel, gUUID, curAppTag, errSecSuccess) != errSecSuccess) + ++result; + } + + // test handling of duplicate symmetric key items () + if (CreateSymmetricKey(curDateLabel, gUUID, curAppTag, errSecDuplicateItem) != errSecDuplicateItem) + ++result; + + CFRelease(curDateLabel); + + return result; +} + + +int TestInternetPasswordLookup() +{ + int result = 0; + + // look up internet password by account and server, want first result as data + if (FindInternetPasswordByAccountAndServer(CFSTR("nobody"), + CFSTR("test2.subdomain.apple.com"), kSecReturnData, kSecMatchLimitOne, 1, noErr)) + ++result; + + // look up internet password by account and server, want dictionary of the item's attributes + if (FindInternetPasswordByAccountAndServer(CFSTR("nobody"), + CFSTR("test2.subdomain.apple.com"), kSecReturnAttributes, kSecMatchLimitOne, 1, noErr)) + ++result; + + // look up internet passwords by account, want array of SecKeychainItemRef results + if (FindInternetPasswordByAccount(CFSTR("nobody"), + kSecReturnRef, kSecMatchLimitAll, 1, noErr)) + ++result; + + // look up a Mail password for an IMAP account, replacing SecKeychainFindInternetPassword + // (see ) + if (FindMailPassword(CFSTR("testacct"), CFSTR("mail.apple.com"))) + ++result; + + return result; +} + + +int TestGenericPasswordLookup() +{ + int result = 0; + + // look up generic password by account and service, want first result as data + if (FindGenericPasswordByAccountAndService(CFSTR("nobody"), + CFSTR("Test Service 42"), kSecReturnData, kSecMatchLimitOne, 1, noErr)) + ++result; + + // look up generic password by account and service, dictionary of the item's attributes + if (FindGenericPasswordByAccountAndService(CFSTR("nobody"), + CFSTR("Test Service 42"), kSecReturnAttributes, kSecMatchLimitOne, 1, noErr)) + ++result; + + // look up generic passwords by account, want array of SecKeychainItemRef results + if (FindGenericPasswordByAccount(CFSTR("nobody"), + kSecReturnRef, kSecMatchLimitAll, 1, noErr)) + ++result; + + return result; +} + + +int TestUpdateItems() +{ + int result = 0; + + // test for + // create a new 1024-bit RSA key pair + SecKeyRef publicKey = NULL; + SecKeyRef privateKey = NULL; + CFMutableDictionaryRef params = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + int keySizeValue = 1024; + CFNumberRef keySize = CFNumberCreate(NULL, kCFNumberIntType, &keySizeValue); + CFStringRef keyLabel = CFSTR("AppleID 8658820 test key"); + CFDictionaryAddValue( params, kSecAttrKeyType, kSecAttrKeyTypeRSA ); + CFDictionaryAddValue( params, kSecAttrKeySizeInBits, keySize ); + CFDictionaryAddValue( params, kSecAttrLabel, keyLabel ); +// CFDictionaryAddValue( params, kSecUseKeychain, keychain ); +// CFDictionaryAddValue( params, kSecAttrAccess, access ); +// %%% note that SecKeyGeneratePair will create the key pair in the default keychain +// if a keychain is not given via the kSecUseKeychain parameter. + OSStatus status = SecKeyGeneratePair(params, &publicKey, &privateKey); + if (status != noErr) { + ++result; + } + PrintTestResult("TestUpdateItems: generating key pair", status, noErr); + + // create a query which will match just the private key item (based on its known reference) + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFArrayRef itemList = CFArrayCreate(NULL, (const void**) &privateKey, 1, &kCFTypeArrayCallBacks); +// %%% note that kSecClass seems to be a required query parameter even though +// kSecMatchItemList is provided; that looks like it could be a bug... + CFDictionaryAddValue( query, kSecClass, kSecClassKey ); +// CFDictionaryAddValue( query, kSecAttrKeyClass, kSecAttrKeyClassPrivate ); + CFDictionaryAddValue( query, kSecMatchItemList, itemList ); + + // create dictionary of changed attributes for the private key + CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + SecAccessRef access = NULL; + CFStringRef newLabel = CFSTR("AppleID 8658820 test PRIVATE key"); + status = SecAccessCreate(newLabel, NULL, &access); + if (status != noErr) { + ++result; + } + PrintTestResult("TestUpdateItems: creating access", status, noErr); +//%%% note that changing the access for this key causes a dialog, +// so leave this out for the moment (uncomment to test that access change works). +// Normally the desired access should be passed into the SecKeyGeneratePair function. +// so there is no need for a dialog later. +// CFDictionaryAddValue( attrs, kSecAttrAccess, access ); + CFDictionaryAddValue( attrs, kSecAttrLabel, newLabel ); + + // update the private key with the new attributes + status = SecItemUpdate( query, attrs ); + if (status != noErr) { + ++result; + } + PrintTestResult("TestUpdateItems: updating item", status, noErr); + + if (publicKey) + CFRelease(publicKey); + if (privateKey) + CFRelease(privateKey); + if (access) + CFRelease(access); + + if (params) + CFRelease(params); + if (query) + CFRelease(query); + if (attrs) + CFRelease(attrs); + + return result; +} + + +int TestDeleteItems() +{ + int result = 0; + + // delete our 3 test certificates that start with "Test-5685316-" + if (FindAndDeleteItemsByName(CFSTR("Test-5685316-"), NULL, kSecClassCertificate, kSecMatchLimitAll, 3, noErr)) + ++result; + + // delete our 2 test identities that start with "Test Identity S" (fixed by ) + if (FindAndDeleteItemsByName(CFSTR("Test Identity S"), NULL, kSecClassIdentity, kSecMatchLimitAll, 2, noErr)) + ++result; + + // delete the "Test-SignOnly (S/MIME)" identity + if (FindAndDeleteItemsByName(CFSTR("Test-SignOnly (S/MIME)"), NULL, kSecClassIdentity, kSecMatchLimitAll, 1, noErr)) + ++result; + + // delete the "Test-Encryption (S/MIME)" certificate + if (FindAndDeleteItemsByName(CFSTR("Test-Encryption (S/MIME)"), NULL, kSecClassCertificate, kSecMatchLimitAll, 1, noErr)) + ++result; + + // delete the "Test-7875801 (Code Signing)" certificate + if (FindAndDeleteItemsByName(CFSTR("Test-7875801 (Code Signing)"), NULL, kSecClassCertificate, kSecMatchLimitAll, 1, noErr)) + ++result; + + // delete our test passwords (no partial string matching for password items! need an ER Radar...) + if (FindAndDeleteItemsByName(CFSTR("Test Service 42"), NULL, kSecClassGenericPassword, kSecMatchLimitAll, 1, noErr)) + ++result; + if (FindAndDeleteItemsByName(CFSTR("Test Service 69"), NULL, kSecClassGenericPassword, kSecMatchLimitAll, 1, noErr)) + ++result; + if (FindAndDeleteItemsByName(CFSTR("test1.subdomain.apple.com"), NULL, kSecClassInternetPassword, kSecMatchLimitAll, 1, noErr)) + ++result; + if (FindAndDeleteItemsByName(CFSTR("test2.subdomain.apple.com"), NULL, kSecClassInternetPassword, kSecMatchLimitAll, 1, noErr)) + ++result; + if (FindAndDeleteItemsByName(CFSTR("mail.apple.com"), CFSTR("testacct"), kSecClassInternetPassword, kSecMatchLimitAll, 1, noErr)) + ++result; + + // delete our test symmetric keys (no partial string matching for key items! need an ER Radar...) + if (FindAndDeleteItemsByName(gLabel, NULL, kSecClassKey, kSecMatchLimitAll, 1, noErr)) + ++result; + CFGregorianDate curGDate = CFAbsoluteTimeGetGregorianDate(CFAbsoluteTimeGetCurrent(), NULL); + CFStringRef curDateLabel = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ (%4d-%02d-%02d)"), + gPrefix, curGDate.year, curGDate.month, curGDate.day); + if (FindAndDeleteItemsByName(curDateLabel, NULL, kSecClassKey, kSecMatchLimitAll, 1, noErr)) + ++result; + CFRelease(curDateLabel); + + // delete our test asymmetric key pair (remember we renamed the private key...) + if (FindAndDeleteItemsByName(CFSTR("AppleID 8658820 test key"), NULL, kSecClassKey, kSecMatchLimitAll, 1, noErr)) + ++result; + if (FindAndDeleteItemsByName(CFSTR("AppleID 8658820 test PRIVATE key"), NULL, kSecClassKey, kSecMatchLimitAll, 1, noErr)) + ++result; + + return result; +} + + +void usage(const char *arg0) +{ + fprintf(stdout, "Usage: %s [-q] [-d]\n", arg0); + fprintf(stdout, "Options:\n"); + fprintf(stdout, " -q : (quiet) suppress output of pass/fail lines\n"); + fprintf(stdout, " -d : (debug) show debug output\n"); +} + + +int main (int argc, const char * argv[]) +{ + int n, i, c, e; + + /* validate arguments */ + if (argc > 3) + { + usage(argv[0]); + exit(1); + } + + for (i=1; i +#include +#include + +#include "testmore.h" +#include "testenv.h" + +/* ========================================================================== + This test is to ensure we do not regress the fix for radar + Security CF runtime objects do not implement CF's Hash function + ========================================================================== */ + +static void tests(void) +{ + CFDictionaryRef query = CFDictionaryCreate(NULL, (const void **)&kSecClass, (const void **)&kSecClassCertificate, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + ok_status(NULL != query, "Dictionary Creation"); // 1 + + CFTypeRef result = NULL; + OSStatus err = SecItemCopyMatching(query, &result); + ok_status(noErr == err && NULL != result, "SecItemCopyMatching"); // 2 + + CFRelease(query); + + + SecCertificateRef cert = (SecCertificateRef)result; + + + CFDataRef cert_data = SecCertificateCopyData(cert); + ok_status(NULL != cert_data, "SecCertificateCopyData"); // 3 + + SecCertificateRef certs[5]; + certs[0] = cert; + + for (int iCnt = 1; iCnt < 5; iCnt++) + { + cert = NULL; + cert = SecCertificateCreateWithData(NULL, cert_data); + ok_status(NULL != cert_data, "SecCertificateCreateWithData"); // 4 5 6 7 + certs[iCnt] = cert; + } + + CFSetRef aSet = CFSetCreate(NULL, (const void **)certs, 4, &kCFTypeSetCallBacks); + ok_status(NULL != aSet, "CFSetCreate"); // 8 + + + CFIndex count = CFSetGetCount(aSet); + ok_status(count == 1, "CFSetGetCount"); // 9 + + + for (int iCnt = 0; iCnt < 5; iCnt++) + { + cert = certs[iCnt]; + if (NULL != cert) + { + CFRelease(cert); + certs[iCnt] = NULL; + } + } + +} + +int main(int argc, char *const *argv) +{ + plan_tests(9); + if (!tests_begin(argc, argv)) + BAIL_OUT("tests_begin failed"); + + tests(); + + //ok_leaks("leaks"); + + return 0; +} \ No newline at end of file diff --git a/SecurityTests/regressions/t/40kc-list.t b/SecurityTests/regressions/t/40kc-list.t new file mode 100755 index 00000000..c494fa4f --- /dev/null +++ b/SecurityTests/regressions/t/40kc-list.t @@ -0,0 +1,13 @@ +#!/usr/bin/perl -w +use strict; +BEGIN { require 't/security.pl' }; +plan_security tests => 1; + +my($xd, $security) = build_test('test'); + +is_output('security', 'list', ['-d', 'common'], + [' "/Library/Keychains/System.keychain"'], 'list -d common'); +#is_output('security', 'list', ['-d', 'system'], +# [' "/Library/Keychains/System.keychain"'], 'list -d system'); + +1; diff --git a/SecurityTests/regressions/t/40kc-unlock.t b/SecurityTests/regressions/t/40kc-unlock.t new file mode 100755 index 00000000..5b740794 --- /dev/null +++ b/SecurityTests/regressions/t/40kc-unlock.t @@ -0,0 +1,27 @@ +#!/usr/bin/perl -w + +use strict; +use warnings; +BEGIN { require 't/security.pl' }; +plan_security tests => 6; + +$ENV{HOME}="/tmp/test$$"; +ok(mkdir($ENV{HOME}), 'setup home'); +is_output('security', 'create-keychain', [qw(-p test test-unlock)], + [], + 'create kc'); +TODO: { + local $TODO = " Unlocking an unlocked keychain with the wrong password succeeds"; + is_output('security', 'unlock-keychain', ['-p', 'wrong', 'test-unlock'], + ['security: SecKeychainUnlock test-unlock: The user name or passphrase you entered is not correct.'], + 'unlock unlocked kc w/ wrong pw'); +}; +is_output('security', 'lock-keychain', ['test-unlock'], + [], + 'lock'); +is_output('security', 'unlock-keychain', ['-p', 'wrong', 'test-unlock'], + ['security: SecKeychainUnlock test-unlock: The user name or passphrase you entered is not correct.'], + 'unlock locked kc w/ wrong pw'); +ok(system("rm -rf '$ENV{HOME}'") eq 0, 'cleanup home'); + +1; diff --git a/SecurityTests/regressions/t/41kc-unlock-referral.t b/SecurityTests/regressions/t/41kc-unlock-referral.t new file mode 100755 index 00000000..441dd3af --- /dev/null +++ b/SecurityTests/regressions/t/41kc-unlock-referral.t @@ -0,0 +1,37 @@ +#!/usr/bin/perl -w + +use strict; +use warnings; +BEGIN { require 't/security.pl' }; +plan_security tests => 7; + +$ENV{HOME}="/tmp/test$$"; +ok(mkdir($ENV{HOME}), 'setup home'); +my $source = "$ENV{HOME}/source"; +my $dest = "$ENV{HOME}/dest"; +is_output('security', 'create-keychain', ['-p', 'test', $source], + [], + 'create source'); +is_output('security', 'create-keychain', ['-p', 'test', $dest], + [], + 'create dest'); +SKIP: { + skip "systemkeychain brings up UI", 1; + + is_output('systemkeychain', '-k', [$dest, '-s', $source], + [], + 'systemkeychain'); +} +is_output('security', 'lock-keychain', [$source], + [], + 'lock source'); +SKIP: { + skip "systemkeychain bring up UI", 1; + + is_output('security', 'unlock-keychain', ['-u', $source], + [], + 'unlock source w/ referal'); +} +ok(system("rm -rf '$ENV{HOME}'") eq 0, 'cleanup home'); + +1; diff --git a/SecurityTests/regressions/t/IPC/Run3.pm b/SecurityTests/regressions/t/IPC/Run3.pm new file mode 100644 index 00000000..c011d972 --- /dev/null +++ b/SecurityTests/regressions/t/IPC/Run3.pm @@ -0,0 +1,666 @@ +package IPC::Run3; + +$VERSION = 0.010; + +=head1 NAME + +IPC::Run3 - Run a subprocess in batch mode (a la system) on Unix, Win32, etc. + +=head1 SYNOPSIS + + use IPC::Run3; ## Exports run3() by default + use IPC::Run3 (); ## Don't pollute + + run3 \@cmd, \$in, \$out, \$err; + run3 \@cmd, \@in, \&out, \$err; + +=head1 DESCRIPTION + +This module allows you to run a subprocess and redirect stdin, stdout, +and/or stderr to files and perl data structures. It aims to satisfy 99% +of the need for using system()/qx``/open3() with a simple, extremely +Perlish API and none of the bloat and rarely used features of IPC::Run. + +Speed (of Perl code; which is often much slower than the kind of +buffered I/O that this module uses to spool input to and output from the +child command), simplicity, and portability are paramount. Disk space +is not. + +Note that passing in \undef explicitly redirects the associated file +descriptor for STDIN, STDOUT, or STDERR from or to the local equivalent +of /dev/null (this does I pass a closed filehandle). Passing in +"undef" (or not passing a redirection) allows the child to inherit the +corresponding STDIN, STDOUT, or STDERR from the parent. + +Because the redirects come last, this allows STDOUT and STDERR to +default to the parent's by just not specifying them; a common use +case. + +B: This means that: + + run3 \@cmd, undef, \$out; ## Pass on parent's STDIN + +B, it passes on the parent's. Use + + run3 \@cmd, \undef, \$out; ## Close child's STDIN + +for that. It's not ideal, but it does work. + +If the exact same value is passed for $stdout and $stderr, then +the child will write both to the same filehandle. In general, this +means that + + run3 \@cmd, \undef, "foo.txt", "foo.txt"; + run3 \@cmd, \undef, \$both, \$both; + +will DWYM and pass a single file handle to the child for both +STDOUT and STDERR, collecting all into $both. + +=head1 DEBUGGING + +To enable debugging use the IPCRUN3DEBUG environment variable to +a non-zero integer value: + + $ IPCRUN3DEBUG=1 myapp + +. + +=head1 PROFILING + +To enable profiling, set IPCRUN3PROFILE to a number to enable +emitting profile information to STDERR (1 to get timestamps, +2 to get a summary report at the END of the program, +3 to get mini reports after each run) or to a filename to +emit raw data to a file for later analysis. + +=head1 COMPARISON + +Here's how it stacks up to existing APIs: + +=over + +=item compared to system(), qx'', open "...|", open "|...": + +=over + +=item + redirects more than one file descriptor + +=item + returns TRUE on success, FALSE on failure + +=item + throws an error if problems occur in the parent process (or the +pre-exec child) + +=item + allows a very perlish interface to perl data structures and +subroutines + +=item + allows 1 word invocations to avoid the shell easily: + + run3 ["foo"]; ## does not invoke shell + +=item - does not return the exit code, leaves it in $? + +=back + +=item compared to open2(), open3(): + +=over + +=item + No lengthy, error prone polling / select loop needed + +=item + Hides OS dependancies + +=item + Allows SCALAR, ARRAY, and CODE references to source and sink I/O + +=item + I/O parameter order is like open3() (not like open2()). + +=item - Does not allow interaction with the subprocess + +=back + +=item compared to IPC::Run::run(): + +=over + +=item + Smaller, lower overhead, simpler, more portable + +=item + No select() loop portability issues + +=item + Does not fall prey to Perl closure leaks + +=item - Does not allow interaction with the subprocess (which +IPC::Run::run() allows by redirecting subroutines). + +=item - Lacks many features of IPC::Run::run() (filters, pipes, +redirects, pty support). + +=back + +=back + +=cut + +@EXPORT = qw( run3 ); +%EXPORT_TAGS = ( all => \@EXPORT ); +@ISA = qw( Exporter ); +use Exporter; + +use strict; +use constant debugging => $ENV{IPCRUN3DEBUG} || $ENV{IPCRUNDEBUG} || 0; +use constant profiling => $ENV{IPCRUN3PROFILE} || $ENV{IPCRUNPROFILE} || 0; +use constant is_win32 => 0 <= index $^O, "Win32"; + +BEGIN { + if ( is_win32 ) { + eval "use Win32 qw( GetOSName ); 1" or die $@; + } +} + +#use constant is_win2k => is_win32 && GetOSName() =~ /Win2000/i; +#use constant is_winXP => is_win32 && GetOSName() =~ /WinXP/i; + +use Carp qw( croak ); +use File::Temp qw( tempfile ); +use UNIVERSAL qw( isa ); +use POSIX qw( dup dup2 ); + +## We cache the handles of our temp files in order to +## keep from having to incur the (largish) overhead of File::Temp +my %fh_cache; + +my $profiler; + +sub _profiler { $profiler } ## test suite access + +BEGIN { + if ( profiling ) { + eval "use Time::HiRes qw( gettimeofday ); 1" or die $@; + if ( $ENV{IPCRUN3PROFILE} =~ /\A\d+\z/ ) { + require IPC::Run3::ProfPP; + $profiler = IPC::Run3::ProfPP->new( + Level => $ENV{IPCRUN3PROFILE}, + ); + } + else { + my ( $dest, undef, $class ) = + reverse split /(=)/, $ENV{IPCRUN3PROFILE}, 2; + $class = "IPC::Run3::ProfLogger" + unless defined $class && length $class; + unless ( eval "require $class" ) { + my $x = $@; + $class = "IPC::Run3::$class"; + eval "require IPC::Run3::$class" or die $x; + } + $profiler = $class->new( + Destination => $dest, + ); + } + $profiler->app_call( [ $0, @ARGV ], scalar gettimeofday() ); + } +} + + +END { + $profiler->app_exit( scalar gettimeofday() ) if profiling; +} + + +sub _spool_data_to_child { + my ( $type, $source, $binmode_it ) = @_; + + ## If undef (not \undef) passed, they want the child to inherit + ## the parent's STDIN. + return undef unless defined $source; + warn "binmode()ing STDIN\n" if is_win32 && debugging && $binmode_it; + + my $fh; + if ( ! $type ) { + local *FH; ## Do this the backcompat way + open FH, "<$source" or croak "$!: $source"; + $fh = *FH{IO}; + if ( is_win32 ) { + binmode ":raw"; ## Remove all layers + binmode ":crlf" unless $binmode_it; + } + warn "run3(): feeding file '$source' to child STDIN\n" + if debugging >= 2; + } + elsif ( $type eq "FH" ) { + $fh = $source; + warn "run3(): feeding filehandle '$source' to child STDIN\n" + if debugging >= 2; + } + else { + $fh = $fh_cache{in} ||= tempfile; + truncate $fh, 0; + seek $fh, 0, 0; + if ( is_win32 ) { + binmode $fh, ":raw"; ## Remove any previous layers + binmode $fh, ":crlf" unless $binmode_it; + } + my $seekit; + if ( $type eq "SCALAR" ) { + + ## When the run3()'s caller asks to feed an empty file + ## to the child's stdin, we want to pass a live file + ## descriptor to an empty file (like /dev/null) so that + ## they don't get surprised by invalid fd errors and get + ## normal EOF behaviors. + return $fh unless defined $$source; ## \undef passed + + warn "run3(): feeding SCALAR to child STDIN", + debugging >= 3 + ? ( ": '", $$source, "' (", length $$source, " chars)" ) + : (), + "\n" + if debugging >= 2; + + $seekit = length $$source; + print $fh $$source or die "$! writing to temp file"; + + } + elsif ( $type eq "ARRAY" ) { + warn "run3(): feeding ARRAY to child STDIN", + debugging >= 3 ? ( ": '", @$source, "'" ) : (), + "\n" + if debugging >= 2; + + print $fh @$source or die "$! writing to temp file"; + $seekit = grep length, @$source; + } + elsif ( $type eq "CODE" ) { + warn "run3(): feeding output of CODE ref '$source' to child STDIN\n" + if debugging >= 2; + my $parms = []; ## TODO: get these from $options + while (1) { + my $data = $source->( @$parms ); + last unless defined $data; + print $fh $data or die "$! writing to temp file"; + $seekit = length $data; + } + } + + seek $fh, 0, 0 or croak "$! seeking on temp file for child's stdin" + if $seekit; + } + + croak "run3() can't redirect $type to child stdin" + unless defined $fh; + + return $fh; +} + + +sub _fh_for_child_output { + my ( $what, $type, $dest, $binmode_it ) = @_; + + my $fh; + if ( $type eq "SCALAR" && $dest == \undef ) { + warn "run3(): redirecting child $what to oblivion\n" + if debugging >= 2; + + $fh = $fh_cache{nul} ||= do { + local *FH; + open FH, ">" . File::Spec->devnull; + *FH{IO}; + }; + } + elsif ( !$type ) { + warn "run3(): feeding child $what to file '$dest'\n" + if debugging >= 2; + + local *FH; + open FH, ">$dest" or croak "$!: $dest"; + $fh = *FH{IO}; + } + else { + warn "run3(): capturing child $what\n" + if debugging >= 2; + + $fh = $fh_cache{$what} ||= tempfile; + seek $fh, 0, 0; + truncate $fh, 0; + } + + if ( is_win32 ) { + warn "binmode()ing $what\n" if debugging && $binmode_it; + binmode $fh, ":raw"; + binmode $fh, ":crlf" unless $binmode_it; + } + return $fh; +} + + +sub _read_child_output_fh { + my ( $what, $type, $dest, $fh, $options ) = @_; + + return if $type eq "SCALAR" && $dest == \undef; + + seek $fh, 0, 0 or croak "$! seeking on temp file for child $what"; + + if ( $type eq "SCALAR" ) { + warn "run3(): reading child $what to SCALAR\n" + if debugging >= 3; + + ## two read()s are used instead of 1 so that the first will be + ## logged even it reads 0 bytes; the second won't. + my $count = read $fh, $$dest, 10_000; + while (1) { + croak "$! reading child $what from temp file" + unless defined $count; + + last unless $count; + + warn "run3(): read $count bytes from child $what", + debugging >= 3 ? ( ": '", substr( $$dest, -$count ), "'" ) : (), + "\n" + if debugging >= 2; + + $count = read $fh, $$dest, 10_000, length $$dest; + } + } + elsif ( $type eq "ARRAY" ) { + @$dest = <$fh>; + if ( debugging >= 2 ) { + my $count = 0; + $count += length for @$dest; + warn + "run3(): read ", + scalar @$dest, + " records, $count bytes from child $what", + debugging >= 3 ? ( ": '", @$dest, "'" ) : (), + "\n"; + } + } + elsif ( $type eq "CODE" ) { + warn "run3(): capturing child $what to CODE ref\n" + if debugging >= 3; + + local $_; + while ( <$fh> ) { + warn + "run3(): read ", + length, + " bytes from child $what", + debugging >= 3 ? ( ": '", $_, "'" ) : (), + "\n" + if debugging >= 2; + + $dest->( $_ ); + } + } + else { + croak "run3() can't redirect child $what to a $type"; + } + +# close $fh; +} + + +sub _type { + my ( $redir ) = @_; + return "FH" if isa $redir, "IO::Handle"; + my $type = ref $redir; + return $type eq "GLOB" ? "FH" : $type; +} + + +sub _max_fd { + my $fd = dup(0); + POSIX::close $fd; + return $fd; +} + +my $run_call_time; +my $sys_call_time; +my $sys_exit_time; + +sub run3 { + $run_call_time = gettimeofday() if profiling; + + my $options = @_ && ref $_[-1] eq "HASH" ? pop : {}; + + my ( $cmd, $stdin, $stdout, $stderr ) = @_; + + print STDERR "run3(): running ", + join( " ", map "'$_'", ref $cmd ? @$cmd : $cmd ), + "\n" + if debugging; + + if ( ref $cmd ) { + croak "run3(): empty command" unless @$cmd; + croak "run3(): undefined command" unless defined $cmd->[0]; + croak "run3(): command name ('')" unless length $cmd->[0]; + } + else { + croak "run3(): missing command" unless @_; + croak "run3(): undefined command" unless defined $cmd; + croak "run3(): command ('')" unless length $cmd; + } + + my $in_type = _type $stdin; + my $out_type = _type $stdout; + my $err_type = _type $stderr; + + ## This routine procedes in stages so that a failure in an early + ## stage prevents later stages from running, and thus from needing + ## cleanup. + + my $in_fh = _spool_data_to_child $in_type, $stdin, + $options->{binmode_stdin} if defined $stdin; + + my $out_fh = _fh_for_child_output "stdout", $out_type, $stdout, + $options->{binmode_stdout} if defined $stdout; + + my $tie_err_to_out = + defined $stderr && defined $stdout && $stderr eq $stdout; + + my $err_fh = $tie_err_to_out + ? $out_fh + : _fh_for_child_output "stderr", $err_type, $stderr, + $options->{binmode_stderr} if defined $stderr; + + ## this should make perl close these on exceptions + local *STDIN_SAVE; + local *STDOUT_SAVE; + local *STDERR_SAVE; + + my $saved_fd0 = dup( 0 ) if defined $in_fh; + +# open STDIN_SAVE, "<&STDIN"# or croak "run3(): $! saving STDIN" +# if defined $in_fh; + open STDOUT_SAVE, ">&STDOUT" or croak "run3(): $! saving STDOUT" + if defined $out_fh; + open STDERR_SAVE, ">&STDERR" or croak "run3(): $! saving STDERR" + if defined $err_fh; + + my $ok = eval { + ## The open() call here seems to not force fd 0 in some cases; + ## I ran in to trouble when using this in VCP, not sure why. + ## the dup2() seems to work. + dup2( fileno $in_fh, 0 ) +# open STDIN, "<&=" . fileno $in_fh + or croak "run3(): $! redirecting STDIN" + if defined $in_fh; + +# close $in_fh or croak "$! closing STDIN temp file" +# if ref $stdin; + + open STDOUT, ">&" . fileno $out_fh + or croak "run3(): $! redirecting STDOUT" + if defined $out_fh; + + open STDERR, ">&" . fileno $err_fh + or croak "run3(): $! redirecting STDERR" + if defined $err_fh; + + $sys_call_time = gettimeofday() if profiling; + + my $r = ref $cmd + ? system {$cmd->[0]} + is_win32 + ? map { + ## Probably need to offer a win32 escaping + ## option, every command may be different. + ( my $s = $_ ) =~ s/"/"""/g; + $s = qq{"$s"}; + $s; + } @$cmd + : @$cmd + : system $cmd; + + $sys_exit_time = gettimeofday() if profiling; + + unless ( defined $r ) { + if ( debugging ) { + my $err_fh = defined $err_fh ? \*STDERR_SAVE : \*STDERR; + print $err_fh "run3(): system() error $!\n" + } + die $!; + } + + if ( debugging ) { + my $err_fh = defined $err_fh ? \*STDERR_SAVE : \*STDERR; + print $err_fh "run3(): \$? is $?\n" + } + 1; + }; + my $x = $@; + + my @errs; + + if ( defined $saved_fd0 ) { + dup2( $saved_fd0, 0 ); + POSIX::close( $saved_fd0 ); + } + +# open STDIN, "<&STDIN_SAVE"# or push @errs, "run3(): $! restoring STDIN" +# if defined $in_fh; + open STDOUT, ">&STDOUT_SAVE" or push @errs, "run3(): $! restoring STDOUT" + if defined $out_fh; + open STDERR, ">&STDERR_SAVE" or push @errs, "run3(): $! restoring STDERR" + if defined $err_fh; + + croak join ", ", @errs if @errs; + + die $x unless $ok; + + _read_child_output_fh "stdout", $out_type, $stdout, $out_fh, $options + if defined $out_fh && $out_type && $out_type ne "FH"; + _read_child_output_fh "stderr", $err_type, $stderr, $err_fh, $options + if defined $err_fh && $err_type && $err_type ne "FH" && !$tie_err_to_out; + $profiler->run_exit( + $cmd, + $run_call_time, + $sys_call_time, + $sys_exit_time, + scalar gettimeofday + ) if profiling; + + return 1; +} + +my $in_fh; +my $in_fd; +my $out_fh; +my $out_fd; +my $err_fh; +my $err_fd; + $in_fh = tempfile; + $in_fd = fileno $in_fh; + $out_fh = tempfile; + $out_fd = fileno $out_fh; + $err_fh = tempfile; + $err_fd = fileno $err_fh; + my $saved_fd0 = dup 0; + my $saved_fd1 = dup 1; + my $saved_fd2 = dup 2; + my $r; + my ( $cmd, $stdin, $stdout, $stderr ); + +sub _run3 { + ( $cmd, $stdin, $stdout, $stderr ) = @_; + + truncate $in_fh, 0; + seek $in_fh, 0, 0; + + print $in_fh $$stdin or die "$! writing to temp file"; + seek $in_fh, 0, 0; + + seek $out_fh, 0, 0; + truncate $out_fh, 0; + + seek $err_fh, 0, 0; + truncate $err_fh, 0; + + dup2 $in_fd, 0 or croak "run3(): $! redirecting STDIN"; + dup2 $out_fd, 1 or croak "run3(): $! redirecting STDOUT"; + dup2 $err_fd, 2 or croak "run3(): $! redirecting STDERR"; + + $r = + system {$cmd->[0]} + is_win32 + ? map { + ## Probably need to offer a win32 escaping + ## option, every command is different. + ( my $s = $_ ) =~ s/"/"""/g; + $s = q{"$s"} if /[^\w.:\/\\'-]/; + $s; + } @$cmd + : @$cmd; + + die $! unless defined $r; + + dup2 $saved_fd0, 0; + dup2 $saved_fd1, 1; + dup2 $saved_fd2, 2; + + seek $out_fh, 0, 0 or croak "$! seeking on temp file for child output"; + + my $count = read $out_fh, $$stdout, 10_000; + while ( $count == 10_000 ) { + $count = read $out_fh, $$stdout, 10_000, length $$stdout; + } + croak "$! reading child output from temp file" + unless defined $count; + + seek $err_fh, 0, 0 or croak "$! seeking on temp file for child errput"; + + $count = read $err_fh, $$stderr, 10_000; + while ( $count == 10_000 ) { + $count = read $err_fh, $$stderr, 10_000, length $$stdout; + } + croak "$! reading child stderr from temp file" + unless defined $count; + + return 1; +} + +=cut + + +=head1 TODO + +pty support + +=head1 LIMITATIONS + +Often uses intermediate files (determined by File::Temp, and thus by the +File::Spec defaults and the TMPDIR env. variable) for speed, portability and +simplicity. + +=head1 COPYRIGHT + + Copyright 2003, R. Barrie Slaymaker, Jr., All Rights Reserved + +=head1 LICENSE + +You may use this module under the terms of the BSD, Artistic, or GPL licenses, +any version. + +=head1 AUTHOR + +Barrie Slaymaker + +=cut + +1; diff --git a/SecurityTests/regressions/t/security.pl b/SecurityTests/regressions/t/security.pl new file mode 100755 index 00000000..1cee4e2d --- /dev/null +++ b/SecurityTests/regressions/t/security.pl @@ -0,0 +1,66 @@ +#!/usr/bin/perl -w + +my $pid = $$; + +END { + return unless $$ == $pid; + rm_test($_) for @TOCLEAN; +} + +use strict; +use Test::More; +use lib 't'; +use IPC::Run3; + +sub plan_security { + + unless (1) { + plan skip_all => "security not installed"; + exit; + }; + plan @_; +} + +use Carp; +our @TOCLEAN; +END { + return unless $$ == $pid; + $SIG{__WARN__} = sub { 1 }; + cleanup_test($_) for @TOCLEAN; +} + +our $output = ''; + +sub build_test { + my $xd = "/tmp/test-$pid"; + my $security = 'security'; + $ENV{HOME} = $xd; + push @TOCLEAN, [$xd, $security]; + return ($xd, $security); +} + +sub rm_test { + my ($xd, $security) = @{+shift}; + #rmtree [$xd]; +} + +sub cleanup_test { + return unless $ENV{TEST_VERBOSE}; + my ($xd, $security) = @{+shift}; +} + +sub is_output { + my ($security, $cmd, $arg, $expected, $test) = @_; + $output = ''; + run3([$security, $cmd, @$arg], \undef, \$output, \$output); +# open(STDOUT, ">&STDERR") || die "couldn't dup strerr: $!"; +# open(my $out, '-|', $security, $cmd, @$arg); +# while (<$out>) { $output .= $_; } + + my $cmp = (grep {ref ($_) eq 'Regexp'} @$expected) + ? \&is_deeply_like : \&is_deeply; + @_ = ([sort split (/\r?\n/, $output)], [sort @$expected], $test || join(' ', $cmd, @$arg)); + goto &$cmp; +} + +1; diff --git a/SecurityTests/regressions/test/00testtest.c b/SecurityTests/regressions/test/00testtest.c new file mode 100644 index 00000000..e8062618 --- /dev/null +++ b/SecurityTests/regressions/test/00testtest.c @@ -0,0 +1,45 @@ +#include + +#include "testmore.h" + +int main(int argc, char *const *argv) +{ + int rv = 1; + plan_tests(6); + + TODO: { + todo("ok 0 is supposed to fail"); + + rv = ok(0, "ok bad"); + if (!rv) + diag("ok bad not good today"); + } + rv &= ok(1, "ok ok"); +#if 0 + SKIP: { + skip("is bad will fail", 1, 0); + + if (!is(0, 4, "is bad")) + diag("is bad not good today"); + } + SKIP: { + skip("is ok should not be skipped", 1, 1); + + is(3, 3, "is ok"); + } +#endif + isnt(0, 4, "isnt ok"); + TODO: { + todo("isnt bad is supposed to fail"); + + isnt(3, 3, "isnt bad"); + } + TODO: { + todo("cmp_ok bad is supposed to fail"); + + cmp_ok(3, &&, 0, "cmp_ok bad"); + } + cmp_ok(3, &&, 3, "cmp_ok ok"); + + return 0; +} diff --git a/SecurityTests/regressions/test/testcpp.h b/SecurityTests/regressions/test/testcpp.h new file mode 100644 index 00000000..1f9e92ae --- /dev/null +++ b/SecurityTests/regressions/test/testcpp.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2005 Apple Computer, 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@ + * + * testcpp.h + */ + +#ifndef _TESTCPP_H_ +#define _TESTCPP_H_ 1 + +#include "testmore.h" + +#ifdef __cplusplus + +#define no_throw(THIS, TESTNAME) \ +({ \ + bool _this; \ + try { THIS; _this = true; } catch (...) { _this = false; } \ + test_ok(_this, TESTNAME, test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# got: \n" \ + "# expected: \n"); \ +}) +#define does_throw(THIS, TESTNAME) \ +({ \ + bool _this; \ + try { THIS; _this = false; } catch (...) { _this = true; } \ + test_ok(_this, TESTNAME, test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# got: \n" \ + "# expected: \n"); \ +}) +#define is_throw(THIS, CLASS, METHOD, VALUE, TESTNAME) \ +({ \ + bool _this; \ + try \ + { \ + THIS; \ + _this = test_ok(false, TESTNAME, test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# got: \n" \ + "# expected: %s.%s == %s\n", \ + #CLASS, #METHOD, #VALUE); \ + } \ + catch (const CLASS &_exception) \ + { \ + _this = test_ok(_exception.METHOD == (VALUE), TESTNAME, \ + test_directive, test_reason, __FILE__, __LINE__, \ + "# got: %d\n" \ + "# expected: %s.%s == %s\n", \ + _exception.METHOD, #CLASS, #METHOD, #VALUE); \ + } \ + catch (...) \ + { \ + _this = test_ok(false, TESTNAME, test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# got: \n" \ + "# expected: %s.%s == %s\n", \ + #CLASS, #METHOD, #VALUE); \ + } \ + _this; \ +}) +#endif /* __cplusplus */ + +#endif /* !_TESTCPP_H_ */ diff --git a/SecurityTests/regressions/test/testcssm.c b/SecurityTests/regressions/test/testcssm.c new file mode 100644 index 00000000..1cae1e91 --- /dev/null +++ b/SecurityTests/regressions/test/testcssm.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2005 Apple Computer, 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@ + * + * cssmlib.c + */ + +#include +#include +#include + +#include "testcssm.h" +#include "testmore.h" + +const CSSM_API_MEMORY_FUNCS gMemFuncs = +{ + (CSSM_MALLOC)malloc, + (CSSM_FREE)free, + (CSSM_REALLOC)realloc, + (CSSM_CALLOC)calloc, + NULL /* context */ +}; + +int +cssm_attach(const CSSM_GUID *guid, CSSM_HANDLE *handle) +{ + setup("cssm_attach"); + + CSSM_VERSION version = {2, 0}; + CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE; + return (ok_status(CSSM_Init(&version, CSSM_PRIVILEGE_SCOPE_NONE, + &gGuidCssm, CSSM_KEY_HIERARCHY_NONE, &pvcPolicy, + NULL /* reserved */), "CSSM_Init") && + ok_status(CSSM_ModuleLoad(guid, CSSM_KEY_HIERARCHY_NONE, NULL, NULL), + "CSSM_ModuleLoad") && + ok_status(CSSM_ModuleAttach(guid, &version, &gMemFuncs, + 0 /* SubserviceID */, CSSM_SERVICE_DL, 0 /* CSSM_ATTACH_FLAGS */, + CSSM_KEY_HIERARCHY_NONE, NULL, 0, NULL, handle), + "CSSM_ModuleAttach")); +} + +int +cssm_detach(const CSSM_GUID *guid, CSSM_HANDLE handle) +{ + setup("cssm_detach"); + + return ok_status(CSSM_ModuleDetach(handle), "CSSM_ModuleDetach") && + ok_status(CSSM_ModuleUnload(guid, NULL, NULL), "CSSM_ModuleUnload") && + ok_status(CSSM_Terminate(), "CSSM_Terminate"); +} diff --git a/SecurityTests/regressions/test/testcssm.h b/SecurityTests/regressions/test/testcssm.h new file mode 100644 index 00000000..2e4c2914 --- /dev/null +++ b/SecurityTests/regressions/test/testcssm.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2005 Apple Computer, 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@ + * + * cssmlib.h + */ + +#include + +extern const CSSM_API_MEMORY_FUNCS gMemFuncs; +extern int cssm_attach(const CSSM_GUID *guid, CSSM_HANDLE *handle); +extern int cssm_detach(const CSSM_GUID *guid, CSSM_HANDLE handle); diff --git a/SecurityTests/regressions/test/testenv.c b/SecurityTests/regressions/test/testenv.c new file mode 100644 index 00000000..65696ddf --- /dev/null +++ b/SecurityTests/regressions/test/testenv.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2005-2006 Apple Computer, 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 +#include +#include +#include +#include +#include +#include + +#include "testmore.h" +#include "testenv.h" + +static int current_dir = -1; +static char scratch_dir[50]; +static char *home_var; + +int +rmdir_recursive(const char *path) +{ + char command_buf[256]; + if (strlen(path) + 10 > sizeof(command_buf) || strchr(path, '\'')) + { + fprintf(stderr, "# rmdir_recursive: invalid path: %s", path); + return -1; + } + + sprintf(command_buf, "rm -rf '%s'", path); + return system(command_buf); +} + +int +tests_begin(int argc, char * const *argv) +{ + char library_dir[70]; + char preferences_dir[80]; + + setup("tests_begin"); + + /* Create scratch dir for tests to run in. */ + sprintf(scratch_dir, "/tmp/tst-%d", getpid()); + sprintf(library_dir, "%s/Library", scratch_dir); + sprintf(preferences_dir, "%s/Preferences", library_dir); + return (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_unix(home_var = getenv("HOME"), "getenv")); +} + +int +tests_end(int result) +{ + setup("tests_end"); + /* Restore previous cwd and remove scratch dir. */ + return (ok_unix(fchdir(current_dir), "fchdir") && + ok_unix(close(current_dir), "close") && + ok_unix(rmdir_recursive(scratch_dir), "rmdir_recursive")); +} diff --git a/SecurityTests/regressions/test/testenv.h b/SecurityTests/regressions/test/testenv.h new file mode 100644 index 00000000..411a8ed9 --- /dev/null +++ b/SecurityTests/regressions/test/testenv.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2005 Apple Computer, 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.h + */ + +#ifndef _TESTENV_H_ +#define _TESTENV_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +int tests_begin(int argc, char * const *argv); +int tests_end(int result); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* !_TESTENV_H_ */ diff --git a/SecurityTests/regressions/test/testeventqueue.c b/SecurityTests/regressions/test/testeventqueue.c new file mode 100644 index 00000000..0aa6dd3c --- /dev/null +++ b/SecurityTests/regressions/test/testeventqueue.c @@ -0,0 +1,95 @@ +#include +#include + +#include "testeventqueue.h" + + + +struct CallbackDataQueueElement; +typedef struct CallbackDataQueueElement CallbackDataQueueElement; + +struct CallbackDataQueueElement +{ + CallbackData callbackData; + CallbackDataQueueElement *forward; + CallbackDataQueueElement *back; +}; + +// allocate static storage for the queue header, which is a circularly linked list +static CallbackDataQueueElement gCallbackQueue = {{0, 0, NULL, NULL, 0}, &gCallbackQueue, &gCallbackQueue}; +static int gNumItemsInQueue = 0; + + +void TEQ_Enqueue (CallbackData *cd) +{ + // allocate storage for the queue element and copy it. + CallbackDataQueueElement* element = (CallbackDataQueueElement*) malloc (sizeof (CallbackDataQueueElement)); + memcpy (&element->callbackData, cd, sizeof (CallbackData)); + + // enqueue the new element -- always at the end + CallbackDataQueueElement* tail = gCallbackQueue.back; + element->forward = tail->forward; + element->forward->back = element; + element->back = tail; + tail->forward = element; + + gNumItemsInQueue += 1; +} + + + +bool TEQ_Dequeue (CallbackData *cd) +{ + if (TEQ_ItemsInQueue () == 0) + { + return false; + } + + // pull the element out of the queue and copy the data + CallbackDataQueueElement* element = gCallbackQueue.forward; + element->forward->back = element->back; + element->back->forward = element->forward; + memcpy (cd, &element->callbackData, sizeof (CallbackData)); + + free (element); + + gNumItemsInQueue -= 1; + return true; +} + + + +int TEQ_ItemsInQueue () +{ + return gNumItemsInQueue; +} + + + +void TEQ_FlushQueue () +{ + CallbackDataQueueElement* element = gCallbackQueue.forward; + while (element != &gCallbackQueue) + { + CallbackDataQueueElement* forward = element->forward; + free (element); + element = forward; + } + + gNumItemsInQueue = 0; +} + + + +void TEQ_Release (CallbackData *cd) +{ + if (cd->itemRef != NULL) + { + CFRelease (cd->itemRef); + } + + if (cd->keychain != NULL) + { + CFRelease (cd->keychain); + } +} diff --git a/SecurityTests/regressions/test/testeventqueue.h b/SecurityTests/regressions/test/testeventqueue.h new file mode 100644 index 00000000..dfe70513 --- /dev/null +++ b/SecurityTests/regressions/test/testeventqueue.h @@ -0,0 +1,25 @@ +#ifndef __TEST_EVENT_QUEUE +#define __TEST_EVENT_QUEUE + + + +#include + +typedef struct CallbackData +{ + UInt32 version; + SecKeychainEvent event; + SecKeychainItemRef itemRef; + SecKeychainRef keychain; + pid_t pid; +} CallbackData; + + + +void TEQ_Enqueue(CallbackData* cd); +bool TEQ_Dequeue(CallbackData* cd); +void TEQ_FlushQueue(); +int TEQ_ItemsInQueue(); +void TEQ_Release(CallbackData* cd); + +#endif diff --git a/SecurityTests/regressions/test/testleaks.c b/SecurityTests/regressions/test/testleaks.c new file mode 100644 index 00000000..a58e7744 --- /dev/null +++ b/SecurityTests/regressions/test/testleaks.c @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2003-2006 Apple Computer, 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@ + * + * testleaks.c + */ + +#include +#include +#include +#include +#include +#include + +#include "testleaks.h" +#include "testmore.h" + +#if 0 +static char *cf_user_text_encoding_var; +#endif + +int +test_leaks(void) +{ + return 0; +#if 0 + int leaks = 0; + pid_t child; + pid_t parent; + + setup("leaks"); + + /* Work around the fact that CF calls setenv, which leaks. */ + cf_user_text_encoding_var = getenv("__CF_USER_TEXT_ENCODING"); + + ok_unix(parent = getpid(), "getpid"); + int cld_stdout[2] = {}; + ok_unix(child = pipe(cld_stdout), "pipe"); + ok_unix(child = fork(), "fork"); + switch (child) + { + case -1: + break; + case 0: + { + /* child. */ + + /* Set childs stdout and stderr to pipe. */ + ok_unix(close(cld_stdout[0]), "close parent end of pipe"); + ok_unix(dup2(cld_stdout[1], 1), "reopen stdout on pipe"); +#if 0 + ok_unix(dup2(cld_stdout[1], 2), "reopen stderr on pipe"); +#endif + + int argc = 0; + char *const *argv = NULL; + char **argvec = (char **)malloc((argc + 2) * sizeof(char *)); + char pidstr[8]; + int ix; + + sprintf(pidstr, "%d", parent); + argvec[0] = "/usr/bin/leaks"; + for (ix = 1; ix < argc; ++ix) + argvec[ix] = argv[ix]; + argvec[ix] = pidstr; + argvec[ix + 1] = NULL; + + ok_unix(execv(argvec[0], argvec), "execv"); + _exit(1); + break; + } + default: + { + /* Parent. */ + ok_unix(close(cld_stdout[1]), "close child end of pipe"); + + /* Set statemachine initial state to 0. */ + int state = 0; + /* True iff the last char read was a newline. */ + int newline = 1; + char buf[4098]; + for (;;) + { + char *p = buf + 2; + ssize_t bytes_read; + bytes_read = read(cld_stdout[0], p, 4096); + if (bytes_read <= 0) + break; + + int start = newline ? -2 : 0; + int ix = 0; + for (ix = 0; ix < bytes_read; ++ix) + { + /* Simple state machine for parsing leaks output. + * Looks for + * '[^\n]*\n[^:]*: ([0-9]*)' + * and sets leaks to atoi of the ([0-9]*) bit. */ + switch (state) + { + case 0: if (p[ix] == '\n') state = 1; break; + case 1: if (p[ix] == ':') state = 2; break; + case 2: if (p[ix] == ' ') state = 3; break; + case 3: + if (p[ix] <= '0' || p[ix] >='9') + state = 4; + else + leaks = leaks * 10 + p[ix] - '0'; + break; + case 4: break; + } + + /* If there is a newline in the input or we are looking + at the last char of the buffer it's time to write the + output. */ + if (p[ix] == '\n' || ix + 1 >= bytes_read) + { + /* If the previous char was a newline we prefix the + output with "# ". */ + if (newline) + { + p[start] = '#'; + p[start + 1] = ' '; + } + fwrite(p + start, ix + 1 - start, 1, stdout); + if (p[ix] == '\n') + { + start = ix - 1; + newline = 1; + } + else + newline = 0; + } + } + } + + int status = 0; + for (;;) + { + /* Wait for the child to exit. */ + pid_t waited_pid = waitpid(child, &status, 0); + if (waited_pid == -1) + { + int error = errno; + /* Keep going if we get interupted but bail out on any + other error. */ + if (error == EINTR) + continue; + + ok_unix(waited_pid, "waitpid"); + break; + } + + if (WIFEXITED(status)) + { + is(WEXITSTATUS(status), 0, "leaks exit status"); + break; + } + else if (WIFSIGNALED(status)) + { + is(WTERMSIG(status), 0, "leaks terminated by"); + break; + } + } + break; + } + } + + return leaks; +#endif +} diff --git a/SecurityTests/regressions/test/testleaks.h b/SecurityTests/regressions/test/testleaks.h new file mode 100644 index 00000000..aff02524 --- /dev/null +++ b/SecurityTests/regressions/test/testleaks.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2003-2006,2011 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@ + * + * testleaks.h + */ + +#ifndef _TESTLEAKS_H_ +#define _TESTLEAKS_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + + +#define ok_leaks(TESTNAME) \ +({ \ + int _this = test_leaks(); \ + test_ok(!_this, TESTNAME, test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# found: %d leaks\n", \ + _this); \ +}) +#define is_leaks(THAT, TESTNAME) \ +({ \ + int _this = test_leaks(); \ + int _that = (THAT); \ + test_ok(_this == _that, TESTNAME, test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# found: %d leaks\n" \ + "# expected: %d leaks\n", \ + _this, _that); \ +}) + +int test_leaks(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _TESTLEAKS_H_ */ diff --git a/SecurityTests/regressions/test/testmore.c b/SecurityTests/regressions/test/testmore.c new file mode 100644 index 00000000..29db3012 --- /dev/null +++ b/SecurityTests/regressions/test/testmore.c @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2005 Apple Computer, 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@ + * + * testmore.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "testmore.h" + +static int test_num = 0; +static int test_fails = 0; +static int test_cases = 0; + +const char *test_directive = NULL; +const char *test_reason = NULL; + +void test_skip(const char *reason, int how_many, int unless) +{ + if (unless) + return; + + int done; + for (done = 0; done < how_many; ++done) + test_ok(1, NULL, "skip", reason, __FILE__, __LINE__, NULL); +} + +void test_bail_out(const char *reason, const char *file, unsigned line) +{ + printf("BAIL OUT! (%s at line %u) %s\n", file, line, reason); + fflush(stdout); + exit(255); +} + +void test_plan_skip_all(const char *reason) +{ + if (test_num > test_cases) + { + test_skip(reason, test_cases - test_num, 0); + exit(test_fails > 255 ? 255 : test_fails); + } +} + +static void test_plan_exit(void) +{ + int status = 0; + fflush(stdout); + + if (!test_num) + { + if (test_cases) + { + fprintf(stderr, "# No tests run!\n"); + status = 255; + } + else + { + fprintf(stderr, "# Looks like your test died before it could " + "output anything.\n"); + status = 255; + } + } + else if (test_num < test_cases) + { + fprintf(stderr, "# Looks like you planned %d tests but only ran %d.\n", + test_cases, test_num); + status = test_fails + test_cases - test_num; + } + else if (test_num > test_cases) + { + fprintf(stderr, "# Looks like you planned %d tests but ran %d extra.\n", + test_cases, test_num - test_cases); + status = test_fails; + } + else if (test_fails) + { + fprintf(stderr, "# Looks like you failed %d tests of %d.\n", + test_fails, test_cases); + status = test_fails; + } + + fflush(stderr); + if (status) + _exit(status > 255 ? 255 : status); +} + +void test_plan_tests(int count, const char *file, unsigned line) +{ + if (atexit(test_plan_exit) < 0) + { + fprintf(stderr, "failed to setup atexit handler: %s\n", + strerror(errno)); + fflush(stderr); + exit(255); + } + + if (test_cases) + { + fprintf(stderr, + "You tried to plan twice! Second plan at %s line %u\n", + file, line); + fflush(stderr); + exit(255); + } + else + { + if (!count) + { + fprintf(stderr, "You said to run 0 tests! You've got to run " + "something.\n"); + fflush(stderr); + exit(255); + } + + test_cases = count; + printf("1..%d\n", test_cases); + fflush(stdout); + } +} + +int +test_diag(const char *directive, const char *reason, + const char *file, unsigned line, const char *fmt, ...) +{ + int is_todo = directive && !strcmp(directive, "TODO"); + va_list args; + + va_start(args, fmt); + + if (is_todo) + { + fputs("# ", stdout); + if (fmt) + vprintf(fmt, args); + fputs("\n", stdout); + fflush(stdout); + } + else + { + fflush(stdout); + fputs("# ", stderr); + if (fmt) + vfprintf(stderr, fmt, args); + fputs("\n", stderr); + fflush(stderr); + } + + va_end(args); + + return 1; +} + +int +test_ok(int passed, const char *description, const char *directive, + const char *reason, const char *file, unsigned line, + const char *fmt, ...) +{ + int is_todo = !passed && directive && !strcmp(directive, "TODO"); + int is_setup = directive && !is_todo && !strcmp(directive, "SETUP"); + + if (is_setup) + { + if (!passed) + { + fflush(stdout); + fprintf(stderr, "# SETUP not ok%s%s%s%s\n", + description ? " - " : "", + description ? description : "", + reason ? " - " : "", + reason ? reason : ""); + } + } + else + { + if (!test_cases) + { + atexit(test_plan_exit); + fprintf(stderr, "You tried to run a test without a plan! " + "Gotta have a plan. at %s line %u\n", file, line); + fflush(stderr); + exit(255); + } + + ++test_num; + if (test_num > test_cases || (!passed && !is_todo)) + ++test_fails; + + printf("%sok %d%s%s%s%s%s%s\n", passed ? "" : "not ", test_num, + description ? " - " : "", + description ? description : "", + directive ? " # " : "", + directive ? directive : "", + reason ? " " : "", + reason ? reason : ""); + } + + if (passed) + fflush(stdout); + else + { + va_list args; + + va_start(args, fmt); + + if (is_todo) + { + printf("# Failed (TODO) test (%s at line %u)\n", file, line); + if (fmt) + vprintf(fmt, args); + fflush(stdout); + } + else + { + fflush(stdout); + fprintf(stderr, "# Failed test (%s at line %u)\n", file, line); + if (fmt) + vfprintf(stderr, fmt, args); + fflush(stderr); + } + + va_end(args); + } + + return passed; +} + + +const char * +sec_errstr(int err) +{ + if (err >= errSecErrnoBase && err <= errSecErrnoLimit) + return strerror(err - 100000); + +#ifdef MAC_OS_X_VERSION_10_4 + /* AvailabilityMacros.h would only define this if we are on a + Tiger or later machine. */ + extern const char *cssmErrorString(long); + return cssmErrorString(err); +#else +#if 0 + extern const char *_ZN8Security15cssmErrorStringEl(long); + return _ZN8Security15cssmErrorStringEl(err); +#else + return ""; +#endif +#endif +} diff --git a/SecurityTests/regressions/test/testmore.h b/SecurityTests/regressions/test/testmore.h new file mode 100644 index 00000000..d1f2c8b6 --- /dev/null +++ b/SecurityTests/regressions/test/testmore.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2005-2006 Apple Computer, 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@ + * + * testmore.h + */ + +#ifndef _TESTMORE_H_ +#define _TESTMORE_H_ 1 + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define ok(THIS, TESTNAME) \ + test_ok(!!(THIS), TESTNAME, test_directive, test_reason, \ + __FILE__, __LINE__, NULL) +#define is(THIS, THAT, TESTNAME) \ +({ \ + __typeof__(THIS) _this = (THIS); \ + __typeof__(THAT) _that = (THAT); \ + test_ok((_this == _that), TESTNAME, test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# got: '%d'\n" \ + "# expected: '%d'\n", \ + _this, _that); \ +}) +#define isnt(THIS, THAT, TESTNAME) \ + cmp_ok((THIS), !=, (THAT), (TESTNAME)) +#define diag(MSG, ARGS...) \ + test_diag(test_directive, test_reason, __FILE__, __LINE__, MSG, ## ARGS) +#define cmp_ok(THIS, OP, THAT, TESTNAME) \ +({ \ + __typeof__(THIS) _this = (THIS); \ + __typeof__(THAT) _that = (THAT); \ + test_ok((_this OP _that), TESTNAME, test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# '%d'\n" \ + "# " #OP "\n" \ + "# '%d'\n", \ + _this, _that); \ +}) +#define eq_string(THIS, THAT, TESTNAME) \ +({ \ + const char *_this = (THIS); \ + const char *_that = (THAT); \ + test_ok(!strcmp(_this, _that), TESTNAME, test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# '%s'\n" \ + "# eq\n" \ + "# '%s'\n", \ + _this, _that); \ +}) +#define eq_stringn(THIS, THISLEN, THAT, THATLEN, TESTNAME) \ +({ \ + __typeof__(THISLEN) _thislen = (THISLEN); \ + __typeof__(THATLEN) _thatlen = (THATLEN); \ + const char *_this = (THIS); \ + const char *_that = (THAT); \ + test_ok(_thislen == _thatlen && !strncmp(_this, _that, _thislen), \ + TESTNAME, test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# '%.*s'\n" \ + "# eq\n" \ + "# '%.*s'\n", \ + (int)_thislen, _this, (int)_thatlen, _that); \ +}) +#define like(THIS, REGEXP, TESTNAME) like_not_yet_implemented() +#define unlike(THIS, REGEXP, TESTNAME) unlike_not_yet_implemented() +#define is_deeply(STRUCT1, STRUCT2, TESTNAME) is_deeply_not_yet_implemented() +#define TODO switch(0) default +#define SKIP switch(0) default +#define SETUP switch(0) default +#define todo(REASON) const char *test_directive __attribute__((unused)) = "TODO", \ + *test_reason __attribute__((unused)) = (REASON) +#define skip(WHY, HOW_MANY, UNLESS) if (!(UNLESS)) \ + { test_skip((WHY), (HOW_MANY), 0); break; } +#define setup(REASON) const char *test_directive = "SETUP", \ + *test_reason = (REASON) +#define pass(TESTNAME) ok(1, (TESTNAME)) +#define fail(TESTNAME) ok(0, (TESTNAME)) +#define BAIL_OUT(WHY) test_bail_out(WHY, __FILE__, __LINE__) +#define plan_skip_all(REASON) test_plan_skip_all(REASON) +#define plan_tests(COUNT) test_plan_tests(COUNT, __FILE__, __LINE__) + +#define ok_status(THIS, TESTNAME) \ +({ \ + OSStatus _this = (THIS); \ + test_ok(!_this, TESTNAME, test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# status: %s(%ld)\n", \ + sec_errstr(_this), _this); \ +}) +#define is_status(THIS, THAT, TESTNAME) \ +({ \ + OSStatus _this = (THIS); \ + OSStatus _that = (THAT); \ + test_ok(_this == _that, TESTNAME, test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# got: %s(%ld)\n" \ + "# expected: %s(%ld)\n", \ + sec_errstr(_this), _this, sec_errstr(_that), _that); \ +}) +#define ok_unix(THIS, TESTNAME) \ +({ \ + int _this = (THIS) < 0 ? errno : 0; \ + test_ok(!_this, TESTNAME, test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# got: %s(%d)\n", \ + strerror(_this), _this); \ +}) +#define is_unix(THIS, THAT, TESTNAME) \ +({ \ + int _result = (THIS); \ + int _this = _result < 0 ? errno : 0; \ + int _that = (THAT); \ + _that && _result < 0 \ + ? test_ok(_this == _that, TESTNAME, test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# got: %s(%d)\n" \ + "# expected: %s(%d)\n", \ + strerror(_this), _this, strerror(_that), _that) \ + : test_ok(_this == _that, TESTNAME, test_directive, test_reason, \ + __FILE__, __LINE__, \ + "# got: %d\n" \ + "# expected errno: %s(%d)\n", \ + _result, strerror(_that), _that); \ +}) + + +extern const char *test_directive; +extern const char *test_reason; + +void test_bail_out(const char *reason, const char *file, unsigned line); +int test_diag(const char *directive, const char *reason, + const char *file, unsigned line, const char *fmt, ...); +int test_ok(int passed, const char *description, const char *directive, + const char *reason, const char *file, unsigned line, const char *fmt, ...); +void test_plan_skip_all(const char *reason); +void test_plan_tests(int count, const char *file, unsigned line); +void test_skip(const char *reason, int how_many, int unless); + +const char *sec_errstr(int err); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* !_TESTMORE_H_ */ diff --git a/SecurityTests/regressions/test/testsecevent.c b/SecurityTests/regressions/test/testsecevent.c new file mode 100644 index 00000000..0fec9888 --- /dev/null +++ b/SecurityTests/regressions/test/testsecevent.c @@ -0,0 +1,171 @@ +#include "testsecevent.h" + +#include +#include +#include + +#include "testmore.h" +#include "testeventqueue.h" + +static OSStatus test_sec_event_callback(SecKeychainEvent keychainEvent, + SecKeychainCallbackInfo *info, void *inContext) +{ + if (keychainEvent == kSecLockEvent || keychainEvent == kSecUnlockEvent) + { + return 0; + } + + CallbackData cd; + cd.event = keychainEvent; + cd.version = info->version; + cd.itemRef = info->item; + cd.keychain = info->keychain; + cd.pid = info->pid; + + if (cd.itemRef) + { + CFRetain (cd.itemRef); + } + + if (cd.keychain) + { + CFRetain (cd.keychain); + } + + + TEQ_Enqueue (&cd); + + return 0; +} + +OSStatus test_sec_event_register(SecKeychainEventMask mask) +{ + return SecKeychainAddCallback(test_sec_event_callback, mask, NULL); +} + +OSStatus test_sec_event_deregister() +{ + return SecKeychainRemoveCallback(test_sec_event_callback); +} + +double GetCurrentTime() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + double d = tv.tv_sec + tv.tv_usec / 1000000.0; + return d; +} + + + +/* Get the next keychain event, and optionally return the events + keychain, item and pid. */ +int test_is_sec_event(SecKeychainEvent event, SecKeychainRef *keychain, + SecKeychainItemRef *item, pid_t *pid, const char *description, + const char *directive, const char *reason, const char *file, unsigned line) +{ + int expected = event == 0 ? 0 : 1; + + if (event == 0) // looking for no event? + { + if (TEQ_ItemsInQueue() == 0) + { + return test_ok(TRUE, + description, directive, reason, file, line, + "", 0, 0); + } + } + + + double startTime = GetCurrentTime(); + double nextTime = startTime + 2.0; + double currentTime; + + while ((currentTime = GetCurrentTime()) < nextTime) + { + /* Run the runloop until we get an event. Don't hang for + more than 0.15 seconds though. */ + SInt32 result = kCFRunLoopRunHandledSource; + + if (TEQ_ItemsInQueue () == 0) // are there events left over? + result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, TRUE); + + switch (result) + { + case kCFRunLoopRunFinished: + return test_ok(0, description, directive, reason, file, line, + "# no sources registered in runloop\n"); + case kCFRunLoopRunStopped: + return test_ok(0, description, directive, reason, file, line, + "# runloop was stopped\n"); + case kCFRunLoopRunTimedOut: + continue; + + case kCFRunLoopRunHandledSource: + { + CallbackData cd; + bool dataInQueue; + + if (expected) + { + dataInQueue = TEQ_Dequeue (&cd); + if (dataInQueue) + { + if (keychain != NULL) + *keychain = cd.keychain; + else if (cd.keychain) + CFRelease(cd.keychain); + + if (item != NULL) + *item = cd.itemRef; + else if (cd.itemRef) + CFRelease(cd.itemRef); + + return test_ok(cd.event == event, + description, directive, reason, file, line, + "# got: '%d'\n" + "# expected: '%d'\n", + cd.event, event); + } + else + { + + // oops, we didn't get an event, even though we were looking for one. + return test_ok(0, description, directive, reason, file, line, + "# event expected but not received\n"); + } + } + + /* We didn't expect anything and we got one event or more. Report them */ + dataInQueue = TEQ_Dequeue (&cd); + int unexpected_events = 0; + while (dataInQueue) + { + test_diag(directive, reason, file, line, + " got unexpected event: '%d'", cd.event); + unexpected_events++; + TEQ_Release (&cd); + dataInQueue = TEQ_Dequeue (&cd); + } + return test_ok(unexpected_events == 0, description, directive, reason, file, line, + "# got %d unexpected events\n", unexpected_events); + } + + default: + return test_ok(0, description, directive, reason, file, line, + "# runloop returned: '%d'\n" + "# expected: 'kCFRunLoopRunHandledSource'\n", + result); + } + } + + if (expected) + return test_ok(0, description, directive, reason, + file, line, "# runloop timed out waiting for event : %d\n", + event); + else + return test_ok(TRUE, description, directive, reason, file, line, + "# got %d unexpected events\n", 0); + +} diff --git a/SecurityTests/regressions/test/testsecevent.h b/SecurityTests/regressions/test/testsecevent.h new file mode 100644 index 00000000..140bc37b --- /dev/null +++ b/SecurityTests/regressions/test/testsecevent.h @@ -0,0 +1,38 @@ +/* + * testsecevent.h + */ + +#ifndef _TESTSECEVENT_H_ +#define _TESTSECEVENT_H_ 1 +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define is_sec_event(EVENT, KEYCHAIN, ITEM, PID, TESTNAME) \ +( \ + test_is_sec_event((EVENT), (KEYCHAIN), (ITEM), (PID), (TESTNAME), \ + test_directive, test_reason, __FILE__, __LINE__) \ +) + +#define no_sec_event(TESTNAME) \ +( \ + test_is_sec_event(0, NULL, NULL, NULL, (TESTNAME), \ + test_directive, test_reason, __FILE__, __LINE__) \ +) + +OSStatus test_sec_event_register(SecKeychainEventMask mask); + +OSStatus test_sec_event_deregister(); + +int test_is_sec_event(SecKeychainEvent event, SecKeychainRef *keychain, + SecKeychainItemRef *item, pid_t *pid, const char *description, + const char *directive, const char *reason, const char *file, + unsigned line); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* !_TESTSECEVENT_H_ */ diff --git a/SecurityTests/regressions/ut/ut-00-errors.cpp b/SecurityTests/regressions/ut/ut-00-errors.cpp new file mode 100755 index 00000000..a06e85f3 --- /dev/null +++ b/SecurityTests/regressions/ut/ut-00-errors.cpp @@ -0,0 +1,18 @@ +#include + +#include "testcpp.h" + +using namespace Security; + +int main(int argc, char *const *argv) +{ + plan_tests(5); + + no_throw(, "doesn't throw"); + does_throw(throw 1, "does throw"); + does_throw(UnixError::throwMe(1), "throws something."); + is_throw(UnixError::throwMe(1), CommonError, unixError(), 1, + "throws UnixError 1"); + is_throw(UnixError::throwMe(1), CommonError, osStatus(), 100001, + "throws osStatus 100001"); +} diff --git a/SecurityTests/regressions/ut/ut-01-devrandom.cpp b/SecurityTests/regressions/ut/ut-01-devrandom.cpp new file mode 100755 index 00000000..55927d24 --- /dev/null +++ b/SecurityTests/regressions/ut/ut-01-devrandom.cpp @@ -0,0 +1,23 @@ +#include + +#include "testcpp.h" + +int main(int argc, char *const *argv) +{ + plan_tests(4); + + DevRandomGenerator rnd; + char buf[8] = {}; + no_throw(rnd.random(buf, sizeof(buf)), "read data from rnd."); + TODO: { + todo("writing to read only rnd succeeeds unexpectedly."); + + does_throw(rnd.addEntropy(buf, sizeof(buf)), + "writing to rnd throws"); + } + + + DevRandomGenerator rndw(true); + no_throw(rndw.random(buf, sizeof(buf)), "read data from rndw."); + no_throw(rndw.addEntropy(buf, sizeof(buf)), "write data to rndw."); +} diff --git a/SecurityTests/shoebox-certs/Apple TEST RootCertificate.crt b/SecurityTests/shoebox-certs/Apple TEST RootCertificate.crt new file mode 100644 index 0000000000000000000000000000000000000000..b85d838c298a143a8637e2ec4650209434d47624 GIT binary patch literal 1244 zcmXqLV!2_^#C%`@GZP~d5E<~YacZ@Bw0-AgWMpM!Fi1D#HsEAq4rO5zW(o~96gCh9 zakzxJ9199^QWZS&lJyML3{*gZ+`_UDLFd$>lFYQsCb2&XtlLz4nkPPIof91Ey{vk*XT4zDJii3RDgWJc zwxu|)%<0kWkKhaa$ZtA#w!zQFCw_u2OxJPQ%v$a7d^%t66W{HtS3Nt&zwD#ybsihj zFXAeDezx4!<`mI*RVaI)^BZsOgv~N)JCaVOY-`9}InkD1^^k+4uwwd=EdkovJulC^ z+-1bg;^Dn*25aeK$4N{Y$NIh2@Q1DJd{|W>y5sVV4|aAj8sB*T9(}a;d-B~RU#>Ed z%bI(IEahs1B=3Y~KfTBra@lj<*K7Xu(`FQ1IXms~stEOD#)%iU`#($QY?v6}z4gYb z>&H!a{ER=GnN)N0$@8MM5)$9G{ql}n^0+YJDHAgz1LNW*#$I5EbQ+|I^EfTIxoO+L4F~&e1B(2OM zVIbCkT|pBgC~?Uuurx7B18o!sVqs_!O-^BD1aesnwAeVb*?`HForzIQE~BKRpx8=Z zzr4I$FAoo?37AugfwC!yMJWm;sYSU!4S6XF$@zIHnV>vUtdO6kP+FX-gJMxZK2R^nGN4Mh z{h%CGP?VTlk_mJk(9Dw5+|<01Vm;&}3(U8`B+JN9+wmfgaf|Hb%0a%rNjD7+wps8q z@avr1x%`N+MSBblv?XRBtnw%aIlUh$Qe-mY_E>Z82LB2Vg$7%OaRnX%a*$8~ap z;lD2#my}lRYPk8Z<7lJinVQcF^yh3)4hdL1t0Q<%?fmUY%$m=IpWLb0#CZ+Pkhlho)37^&2iXxi23lZ8 z@F+tJ56>^kNh!}vNmX!3ElbVGFGwv?2ujTXyQ$dF#lQ*d6dr3LR4d@{kUIV9Jtx~*mOc3N^qkf?1> z*PH#>5>p>AuVJj6&YFIXuXU<<)?3bP>(b8#rp!MUb8%02Ub<;Rnc0%|#ypGu8``3N z)v7n5_WLy-?7cMks#M|DggJAK{X%~VMewxk5aT`gwA{5fz+;!T?vp944__Radn{w= zhQ)u<>k4);MS7PzO|;zk_3T5R_Xn&!dX_y^jQyLHwR^dkX~LyvYd^bbo_uk*`(@>U zti*KDO&|U~&DfI^pLc%d-S^VT|0bobW@2V!U|ig|&Y*F%0Ut2DW%(Hy|Ff_FlUkbr zKZq|3;h`Ux;W>`Z4wFHZ(i^E<{o)8C}i<=19_0NGK++PSc8c6 zg-rJ;Wt{)MWcTVhEc@>6Th9?^UVJ@=m5ZPQlM_jVT^MR;3$ zd0QGKA5$P3W-0XaA+O+*PF1$OSGS1v#a)P;KH;Tzf$>s?CZBo|n@pP49Y^;$XV z-%{P_->Y|DYj<;MeH~=0wkdhVmW`+Sznpor`Gos}{j(yQf8Cl9tkv|jCRK0hP2Acw*r@b6HQk_fhp0-j|J~}V_hu*nMD<{Pj>*=eOiUI)R Cp^hm4 literal 0 HcmV?d00001 diff --git a/SecurityTests/shoebox-certs/Apple Worldwide Developer Relations Certification Authority TEST Cert.crt b/SecurityTests/shoebox-certs/Apple Worldwide Developer Relations Certification Authority TEST Cert.crt new file mode 100644 index 0000000000000000000000000000000000000000..0166fd9fe18a1ef515a48ea25a023fe7d13223fe GIT binary patch literal 1068 zcmXqLV$m>YVis7y%*4pV#3*UN%f_kI=F#?@mywZ`mBAq0klTQhjX9KsO_(V(*ihI& z5X9jU=5j13$VpZ3%uCiYR5MTk333a|LIj;ti%K%nGLsWaGV}8k97{_w@{2M{Dh;I# zBthz!g@qvMLR^DG6oT^eOB9?P4dldm4J-_d49ty;42?_;qQrR(%?wNoVO)d8Y1m!D zgX|I=11+#ic$6VFgy$FKq?Bi-q$;?imZj$87o-*`1f}MH9ae1UV&DXJ505nwsughf z%Ako+2|3UhSs9p{82K51;#^EkjEoEqRF55NxE{`uqG)Tn_}lxqva_e|q+ad%u(&|( z-;FsDdD;!;=W2Q7%&cbhzh_@zxk1urAw#)o25FUn#jGK@@ohrF_1{yrdej}*%f!scz__?^ok8Pj13qAQ%knca z{%2tUrnfc&eh^<6#Ah{N22uvHAOSuWF&2?2snZJ8Dz(zi%$Qzwu~pkBzEW(hfjmfB znMJ}ttU=_0XRX3C-g8@@FP~|VaBbq$d+dra24)}y@+|rWx(3<{G#9A1sb-Xv6jr#`qoHtAVrQVACTYux|T({(7;@32KjjtT} zryicEa94v*Kwp`&zcBvGMeB7oea9ZJGSL3O;#WDX`~K3Ft-{l1b1W|w+{~i)D&_T3 zJ?$NP%J&!vTu570qtbl;y!<?*EUS^>dQ%O$*}Sqp%(7Mp*DQb7 z&lWbTUYA8ymc{fl%XEW#Q%YGT9*OHsf8g=mQ>lFYQsBg2!4D>>yS-j;I@c+L7YuChh5U7`KHvAiEsOqE5wMI&W5Px=0B&b;#hyADPKr1x`dQTTp(jgCTo z!8UtFgP!fq=lSQ_e%AKXkUH`2+}53ZH{)ckownU-we|}?AHyW>jf!G=C0A{DZzqYZ zUR*fIJvj8>dVR;uKYl+hIQwj|k87R0Pjj_t->jT;Rj-bAq&^<-@B zm%W!-{69S|b&uzbviZg$sSC@eoYZAvW@KPo+{9P~43RPeK43h`@-s62XJG-R8#V)e z5MLO?XEk63QUIB4HrbfL%co zBPgB8DzG#$asX{)0b&Md!c0zKWi)8~WT3^yq0I(NqwGwKVsaTJB?ZM+`ugSN<$8&r zl&P1TpQ{gMB`4||G#-X4W-@5pCe^q(C^aWDF)uk)0hmHdGBS%5lHrLqRUxTTAu+E~ zp&+rS1js5bF3n9XR!B@vPAw>b=t%?WNd@6N1&|%Uq@D!K48=g%l*FPGg_6{wT%d-$ z6ouscyp&8(HYirePg5u@PSruNs30Gx7i1YwCER{crYR^&OfJa;IuB@ONosCtUP-YY za{2^jO7!e*{cX?eJDxY@8r; zW8atJ+3zl;@Sm>qH@UIM?q|jS>=W#7YAu_)gB31Y9ND;kmOoeaf9*e!%UL;V#2vx} zUUwk!R<>!CBEM2a=7;zgw~E zguTASugG_6SFxo3)|+Pa2irq$E}yy6$m#cutA+FG76xsX-aFYzMMzw9>OIdRD+ Xyc@&=R&`yy_2kb5PImJRrKO4hMS!&; literal 0 HcmV?d00001 diff --git a/SecurityTests/shoebox-certs/Invalid.com.apple.testcard.crt b/SecurityTests/shoebox-certs/Invalid.com.apple.testcard.crt new file mode 100644 index 0000000000000000000000000000000000000000..df27ac6754c33b0f8a121f96b7e7e82160315592 GIT binary patch literal 1524 zcma)6eNYr-7{A@yTi`xCkQ2EO*g!tyj=T2&MFcFB&k-Ue!vPDIy**gH+r94gI2d*0 zuDBW0phy8F48=%O6Va?hGh|FH%hF8450tblO~Yb9C!_ZO5oi3PKXzuHulIT0-}C#u zz$y9@II#=OLKHz!Pu0iK_e=OST|kC=MY%Fu12O~=i3Gq=r;`9LT(}6sebGg^I$z-9 zHpEi#9JAR-6PYZf(Wya{+bNNTjyUr;i&1Z9^fZw|m(oVgOk0SBw2|Z)j zP@4EZvWa=Lg=Y*5HC#;0vGFCGh2hIV&}5k|222O>y7<_*nCbb@j2&kJ$68$oAaJo) zZFto?_tbg>kxryIlZJGUt>I}aPmvbAE&wP;hIv|W^s*9oS>4>2d9f*Rsnd1gVCo10 zfsYX&q9G7GZDC0x@e(|mVT+%D4LFgI@yH?~fzXM_1<)@>od_bh9P(3S-@Hke4yT8{ z7ZD~)vlX0_=5+?IZ&@1ZEvUJOp1x3~ENoujeP4X7XxVkg>jzvlZQIc$f2f&F9yuEP z+llhQ`Lz|=pX>bRw|7?;(~UXVF@l7fWuJBsyTuwDq1X65O5J z-$*UVTYRXU9%3(^R0qg!@~*qL@|D@ElwIGoHf_S!^=CM;W~z2&r03xt0}Z{N5A|=Y z_}dUf=6A3At*W!SX{vqg>M8rBp^Bc{hpxS?Jh#(PR{hoS!K6-9hzO7tCz=VIXe!9W zJykfQp9g|q$siFVJhB1eiZ0=K^DM2Fqpap=8_8=Z&SDygbTq zs-eF0`$|F2Trir3*f@I4HGil-BpVewJ(N=<_DB8@A)EHn5?fzK8O|k797Wr1w~xbkSVI)41@Ue`f-wLzK;0bG9O()l&8IBJr!B{B*IP6&1|;r6Ife;Q zj|vdvHo~yUVA7+`LUasSYy$Ac#lue$rN@N`hQe1Vjs^6;1x#kFR?NGn^x79e||^1XYa@=TsN>$X^H-9 zS!I??xbooV&l#N&=lxU8&iLzL*0!j$W1aDSwU_qaQFa)F-l9H9m^N#{^5Qtv;s-V9 zcPe*AATFjq4Ew?75Y>>Jc;dt4zTQew-pCfAOl8 zp543aa82Lf)lNlP{egYO8&XBBd4>-*r+u`!;zDgiaHHgn^S27Jzj*P%C)=kr1<0BQFLJ3$?(nx0u#3@5K1eZKS6q{bdRP5vxB=Q46-Wpz{i Gng0Ok3=sbS literal 0 HcmV?d00001 diff --git a/SecurityTests/test-certs/CACert.ecc.pem b/SecurityTests/test-certs/CACert.ecc.pem new file mode 100644 index 00000000..f96e7df1 --- /dev/null +++ b/SecurityTests/test-certs/CACert.ecc.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBjTCCATOgAwIBAgIJAMQsXubbJnDAMAkGByqGSM49BAEwJTEjMCEGA1UEAwwa +U2VjdXJpdHlUZXN0IENBIENlcnQgKEVDQykwHhcNMTExMTE0MTkzMTM4WhcNMTIx +MTEzMTkzMTM4WjAlMSMwIQYDVQQDDBpTZWN1cml0eVRlc3QgQ0EgQ2VydCAoRUND +KTBWMBAGByqGSM49AgEGBSuBBAAKA0IABK5O3qLKvKB5vMRqWEKv4Nye+fhkJj/B +8gs36QR0z8CXUVH22c0EXaIZwIOZ4XrZGD1/FUHh3JWqser7B45znOqjUDBOMB0G +A1UdDgQWBBQxswVVmWBV4cMaTe8uIpaa2+11LzAfBgNVHSMEGDAWgBQxswVVmWBV +4cMaTe8uIpaa2+11LzAMBgNVHRMEBTADAQH/MAkGByqGSM49BAEDSQAwRgIhAKZW +WRe6AVtqmdCUjZSpMKnn1N8ErlrRhbPCbXrYWImfAiEAhGdbOPreQ1cGkozAumNt +akSeluukYrPN1dks78s6++c= +-----END CERTIFICATE----- diff --git a/SecurityTests/test-certs/CACert.rsa.pem b/SecurityTests/test-certs/CACert.rsa.pem new file mode 100644 index 00000000..0fe2aa1a --- /dev/null +++ b/SecurityTests/test-certs/CACert.rsa.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICGDCCAYGgAwIBAgIJAJ9QpULLeIQbMA0GCSqGSIb3DQEBBQUAMCUxIzAhBgNV +BAMMGlNlY3VyaXR5VGVzdCBDQSBDZXJ0IChSU0EpMB4XDTExMTExNDE5MzEzOFoX +DTEyMTExMzE5MzEzOFowJTEjMCEGA1UEAwwaU2VjdXJpdHlUZXN0IENBIENlcnQg +KFJTQSkwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALqAEyGep4elcmCv1ELx +JrkSGQi4GF/2/fCgR1u6n6T9HeukKOZbmaCCirum7EWb1SbgGohLMqNMhYDyHska +S2KXDB1YhiAkHFuHOJf0oJDxbCFvfAgz/xwBfG6FKrloQk2vGi3DdTUg7hrP3/2m +AfDcvj7kd+YS5tqfV375ljlnAgMBAAGjUDBOMB0GA1UdDgQWBBTj+S/2zKrckMmA +NTFrL1Os0ICojTAfBgNVHSMEGDAWgBTj+S/2zKrckMmANTFrL1Os0ICojTAMBgNV +HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAIS3eqZ/6ziu+f2xA+mACWakZNYW +ERLQ9i74mp52noNy3gY10EQdNBjjSfAr73HUDecSZ6EyuP+Q1Oo9JUSleZEne0pb +3MYy5p2OQRwT30XuzwcILjVeibi2BOgupmfuTwbTMRdiLErj/R2R7aHGQMjiEBh9 +DmYhaZn0u/Z/0eMP +-----END CERTIFICATE----- diff --git a/SecurityTests/test-certs/CAKey.ecc.pem b/SecurityTests/test-certs/CAKey.ecc.pem new file mode 100644 index 00000000..f9582d6b --- /dev/null +++ b/SecurityTests/test-certs/CAKey.ecc.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQggCn1xg7vmn4iguMpbpiW +NYtOx14IS0MfpbOCJx0YdSShRANCAASuTt6iyrygebzEalhCr+Dcnvn4ZCY/wfIL +N+kEdM/Al1FR9tnNBF2iGcCDmeF62Rg9fxVB4dyVqrHq+weOc5zq +-----END PRIVATE KEY----- diff --git a/SecurityTests/test-certs/CAKey.rsa.pem b/SecurityTests/test-certs/CAKey.rsa.pem new file mode 100644 index 00000000..487b65b3 --- /dev/null +++ b/SecurityTests/test-certs/CAKey.rsa.pem @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALqAEyGep4elcmCv +1ELxJrkSGQi4GF/2/fCgR1u6n6T9HeukKOZbmaCCirum7EWb1SbgGohLMqNMhYDy +HskaS2KXDB1YhiAkHFuHOJf0oJDxbCFvfAgz/xwBfG6FKrloQk2vGi3DdTUg7hrP +3/2mAfDcvj7kd+YS5tqfV375ljlnAgMBAAECgYEAkm63FsGcZowH51SHA9yWe99y +2n65XLfwoPsnrCU27fNzh65IEr6/O+Djjv08LFdzn+d7zaHFa6RMencgpuPHZZV0 +17vH8Km4aBr5zL52UbvqkFPsO/1vH0CQu0fhQJMYtCTzkIIn6GbFHDq0iK2LO+ET +09S1l+O+0jf0Ox3+xvkCQQDbEO2VDYAf3XWJhWqMMtziS5XUUgC+H/EsmStkll4l +HGyRmWYFOXTAh6dTNEkMUPYElf1iRi2IbRPF1SOzPZVTAkEA2fGUL7Wi9+1byvSB +f+AiC7uQ5GOJMiVpSiYztORzwfHy5dBksRKH1P4OHeM+qXZtOULkhIU6i/Hb8ynG +nCGVHQJAXvv4B6jS5P4g+H/gsula3MPpMyZbLBStfajsJ7ELIQwyBu98TMec1935 +rxn8klqIUXS3aOUE2SJycFT6Jb2OAQJAGYbOEHh5yggnBDJ3KH8b/bvOULHH0/PF +zUWEMN/BHyozhO9Pm93LwwqupJmFMVwJlvdaxJrGLLX7SRPPi2HzkQJAf9K8Ff3Q +sB9jGsygiP9Z8kAewGyCp2EViJ+zwuNidD64P16zt+IlkMCNuY3EZRrMI+0q0hOh +/xRHfj1n+6rY0g== +-----END PRIVATE KEY----- diff --git a/SecurityTests/test-certs/ClientCert.ecc.ecc.pem b/SecurityTests/test-certs/ClientCert.ecc.ecc.pem new file mode 100644 index 00000000..222a2cf8 --- /dev/null +++ b/SecurityTests/test-certs/ClientCert.ecc.ecc.pem @@ -0,0 +1,9 @@ +-----BEGIN CERTIFICATE----- +MIIBNDCB3QICA+wwCQYHKoZIzj0EATAlMSMwIQYDVQQDDBpTZWN1cml0eVRlc3Qg +Q0EgQ2VydCAoRUNDKTAeFw0xMTExMTQxOTMxMzlaFw0xMTEyMTQxOTMxMzlaMCox +KDAmBgNVBAMMH1NlY3VyaXR5VGVzdHMgQ2xpZW50IENlcnQgKEVDQykwWTATBgcq +hkjOPQIBBggqhkjOPQMBBwNCAAQRHXiQO5Xw20eXWvh2ScjSx7XSMt7n5thN5y+d +sG+ezyETQOZg4T5PBF5/qb8rI8iF4pv/KBhA9h585d6Lptx0MAkGByqGSM49BAED +RwAwRAIgBTKxt5A/4UU0X6NePPqT0DqEkjC+NFMpRpAd+Wlv5agCIFIe0yAPgGPO +I1h28CfZamWahpCGDPZGjG1eRNNY7EJP +-----END CERTIFICATE----- diff --git a/SecurityTests/test-certs/ClientCert.ecc.rsa.pem b/SecurityTests/test-certs/ClientCert.ecc.rsa.pem new file mode 100644 index 00000000..f56215b4 --- /dev/null +++ b/SecurityTests/test-certs/ClientCert.ecc.rsa.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBdzCB4QICA+swDQYJKoZIhvcNAQEFBQAwJTEjMCEGA1UEAwwaU2VjdXJpdHlU +ZXN0IENBIENlcnQgKFJTQSkwHhcNMTExMTE0MTkzMTM5WhcNMTExMjE0MTkzMTM5 +WjAqMSgwJgYDVQQDDB9TZWN1cml0eVRlc3RzIENsaWVudCBDZXJ0IChFQ0MpMFkw +EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEER14kDuV8NtHl1r4dknI0se10jLe5+bY +TecvnbBvns8hE0DmYOE+TwRef6m/KyPIheKb/ygYQPYefOXei6bcdDANBgkqhkiG +9w0BAQUFAAOBgQAq2AQPq3Z+KC9T/irBIWMMymrB7X0zqOHwQlVdBzTx2Hv8y+by +8kuFKrEfulTV8IwTQbGxuqsZpq39EKUkRUYCWI97zODH0vR+XBSaTKnyzHNaijqw +nJJltefGjhT9c2GBokhAJfet9zIxFenFvtfhUeb94hKmPbxrsruf/ryNvw== +-----END CERTIFICATE----- diff --git a/SecurityTests/test-certs/ClientCert.rsa.ecc.pem b/SecurityTests/test-certs/ClientCert.rsa.ecc.pem new file mode 100644 index 00000000..2ca565cf --- /dev/null +++ b/SecurityTests/test-certs/ClientCert.rsa.ecc.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBfjCCASQCAgPqMAkGByqGSM49BAEwJTEjMCEGA1UEAwwaU2VjdXJpdHlUZXN0 +IENBIENlcnQgKEVDQykwHhcNMTExMTE0MTkzMTM5WhcNMTExMjE0MTkzMTM5WjAq +MSgwJgYDVQQDDB9TZWN1cml0eVRlc3RzIENsaWVudCBDZXJ0IChSU0EpMIGfMA0G +CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUKqDI37OiBOScaSNZRZ69ttex5U3g//G7 +dRSWJKVXrumlSW/RISvSUHYDpp6cMrOUOB3g3aFnlFEmLfqrj4lZoIDg0fftZ0yv +r7RmE+57t3yH9gNX8ilWiGIB7ZoVEkiugfTzBRbEiGPeohwatx7Y8gF2c+LbHdY5 +hO6yA+fwwwIDAQABMAkGByqGSM49BAEDSQAwRgIhAOpCpGjJs4/izL1iThvR6h61 +WzpopufKdv6LIyVkoFskAiEA+/fTImPTmAj/PiHZrGK2fxCmfGofdf4DnF3qbiUF +GGg= +-----END CERTIFICATE----- diff --git a/SecurityTests/test-certs/ClientCert.rsa.rsa.pem b/SecurityTests/test-certs/ClientCert.rsa.rsa.pem new file mode 100644 index 00000000..5f8cc8dd --- /dev/null +++ b/SecurityTests/test-certs/ClientCert.rsa.rsa.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBvzCCASgCAgPpMA0GCSqGSIb3DQEBBQUAMCUxIzAhBgNVBAMMGlNlY3VyaXR5 +VGVzdCBDQSBDZXJ0IChSU0EpMB4XDTExMTExNDE5MzEzOVoXDTExMTIxNDE5MzEz +OVowKjEoMCYGA1UEAwwfU2VjdXJpdHlUZXN0cyBDbGllbnQgQ2VydCAoUlNBKTCB +nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1CqgyN+zogTknGkjWUWevbbXseVN +4P/xu3UUliSlV67ppUlv0SEr0lB2A6aenDKzlDgd4N2hZ5RRJi36q4+JWaCA4NH3 +7WdMr6+0ZhPue7d8h/YDV/IpVohiAe2aFRJIroH08wUWxIhj3qIcGrce2PIBdnPi +2x3WOYTusgPn8MMCAwEAATANBgkqhkiG9w0BAQUFAAOBgQCeUHfriInHwURsxBya +vw6PY41TW+o1ega9CeI/GZokPCvxehRNJMXzbgSjNINzbjrJ1lEwWhRbqmkjT7WQ +2xs30KuZ4hcIjR77LRg9xAjcD9Rujvu2b2Vxl5NjOlmt1CXkMKjnz4JqEcPOBQQa +W+oz386aSITi+UJPoUh104asxA== +-----END CERTIFICATE----- diff --git a/SecurityTests/test-certs/ClientKey.ecc.pem b/SecurityTests/test-certs/ClientKey.ecc.pem new file mode 100644 index 00000000..b999dd9d --- /dev/null +++ b/SecurityTests/test-certs/ClientKey.ecc.pem @@ -0,0 +1,25 @@ +Public Key Info: + Public Key Algorithm: ECC + Key Security Level: High + +curve: SECP256R1 +private key: + 77:dd:c7:4d:4c:54:9a:cc:9a:f3:38:1b:68:77:d8: + 20:96:cf:83:6c:37:33:13:b9:f8:5a:c5:a9:6b:cd: + 14:07: +x: + 11:1d:78:90:3b:95:f0:db:47:97:5a:f8:76:49:c8: + d2:c7:b5:d2:32:de:e7:e6:d8:4d:e7:2f:9d:b0:6f: + 9e:cf: +y: + 21:13:40:e6:60:e1:3e:4f:04:5e:7f:a9:bf:2b:23: + c8:85:e2:9b:ff:28:18:40:f6:1e:7c:e5:de:8b:a6: + dc:74: + +Public Key ID: F0:E8:3C:CF:A0:45:1D:ED:B2:D8:1B:7A:08:3F:4A:79:02:A9:50:22 + +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIHfdx01MVJrMmvM4G2h32CCWz4NsNzMTufhaxalrzRQHoAoGCCqGSM49 +AwEHoUQDQgAEER14kDuV8NtHl1r4dknI0se10jLe5+bYTecvnbBvns8hE0DmYOE+ +TwRef6m/KyPIheKb/ygYQPYefOXei6bcdA== +-----END EC PRIVATE KEY----- diff --git a/SecurityTests/test-certs/ClientKey.rsa.pem b/SecurityTests/test-certs/ClientKey.rsa.pem new file mode 100644 index 00000000..400b7304 --- /dev/null +++ b/SecurityTests/test-certs/ClientKey.rsa.pem @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANQqoMjfs6IE5Jxp +I1lFnr2217HlTeD/8bt1FJYkpVeu6aVJb9EhK9JQdgOmnpwys5Q4HeDdoWeUUSYt ++quPiVmggODR9+1nTK+vtGYT7nu3fIf2A1fyKVaIYgHtmhUSSK6B9PMFFsSIY96i +HBq3HtjyAXZz4tsd1jmE7rID5/DDAgMBAAECgYA45lXIiXX7daR57hh00J8J8gdW +xlBkjz+dLoEe4yUUpuwyT8eVJnhCJyH/SKgw68gNcB9TNx0aUkSRILOhXxVOXyPN +StX3ptkNBaHMWxMfjuuHE750lh0K12jlHtaXvJ9ST6IwUDYniQlCWgdDJ4qZ6bh7 +5oH6+/UU55KBAKFyAQJBAOlbbWILMGF7bKdaBZYIkYcFfueX6K+yd+HvoTRdE19y +nzU/RN0EQ0a7m/j30YqalxxPwjco8xmbWTARQg4MPKECQQDowNPSOOhqXbtNlahu +hlP2RnmC3JK7gezq6Fli9SILhgY54k8n3I8Eln/nV10d3hMprAdy8KZxwpzME37U +YW7jAkEAv40RCL3uhNZvph+7HiECdDcKqMiFdFOnHIs7ZGRSlrLcBTVeLZ5mKxWt +Pn0OQBwNlmvSHL08b/SZDV/dPPLGgQJAG3s5B2dEudpbVSvIeVRO8ZMcocDdalpK +2OmaND7xSB8I+SipY/F8yXPjojMEgZRI+vCe6IlVfbUWwlnC7dybNQJBALK5VCDA +Hf9unwk0TaB1C73y+8wCzAdo8F+TuSlJCbrlkk/fWqjr2eBknz3F8hDhAeRijdSG +Vi82fdDpcIDXVm8= +-----END PRIVATE KEY----- diff --git a/SecurityTests/test-certs/ClientReq.ecc.pem b/SecurityTests/test-certs/ClientReq.ecc.pem new file mode 100644 index 00000000..ad10779c --- /dev/null +++ b/SecurityTests/test-certs/ClientReq.ecc.pem @@ -0,0 +1,7 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIHjMIGMAgEAMCoxKDAmBgNVBAMMH1NlY3VyaXR5VGVzdHMgQ2xpZW50IENlcnQg +KEVDQykwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQRHXiQO5Xw20eXWvh2ScjS +x7XSMt7n5thN5y+dsG+ezyETQOZg4T5PBF5/qb8rI8iF4pv/KBhA9h585d6Lptx0 +oAAwCQYHKoZIzj0EAQNHADBEAiBcP+jUoxoKnIiRaucK5NhHK/miFF9Bp3yHqjL5 +oTw/VwIgMjBXnU9XM7BBzf8ghuIP+f7vvZlpUhT2Z93cV08Yhjg= +-----END CERTIFICATE REQUEST----- diff --git a/SecurityTests/test-certs/ClientReq.rsa.pem b/SecurityTests/test-certs/ClientReq.rsa.pem new file mode 100644 index 00000000..dc6d737d --- /dev/null +++ b/SecurityTests/test-certs/ClientReq.rsa.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBaTCB0wIBADAqMSgwJgYDVQQDDB9TZWN1cml0eVRlc3RzIENsaWVudCBDZXJ0 +IChSU0EpMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUKqDI37OiBOScaSNZ +RZ69ttex5U3g//G7dRSWJKVXrumlSW/RISvSUHYDpp6cMrOUOB3g3aFnlFEmLfqr +j4lZoIDg0fftZ0yvr7RmE+57t3yH9gNX8ilWiGIB7ZoVEkiugfTzBRbEiGPeohwa +tx7Y8gF2c+LbHdY5hO6yA+fwwwIDAQABoAAwDQYJKoZIhvcNAQEFBQADgYEAwNwk +3mDMney97Xc5Wlt9PGjk5KDeJppz6x8oi4voLTqEqDC84j52Z6T7dMAz5Xr4XEwj +W04UFTX/rbtHYV3IWZb7/3Zaf3RZMyLtAhhzc2uRcQZ9QGN8XideheU3uUFkxIVt +6ZFHQFZUGjW6Va06wp3aIsbDKQvrlqzGOOufhXs= +-----END CERTIFICATE REQUEST----- diff --git a/SecurityTests/test-certs/SECG_ecc-secp256r1-client.pem b/SecurityTests/test-certs/SECG_ecc-secp256r1-client.pem new file mode 100644 index 00000000..c56218b8 --- /dev/null +++ b/SecurityTests/test-certs/SECG_ecc-secp256r1-client.pem @@ -0,0 +1,27 @@ +BAG #0 + Elements: 1 + Key ID: 3A:8B:1B:18:22:29:59:28:BC:B2:8B:A4:79:DB:08:DD:9C:75:20:01 +-----BEGIN ENCRYPTED PRIVATE KEY----- +MGgwHAYKKoZIhvcNAQwBAzAOBAhoqNgi8tCmswICCAAESPoHMAKQbVR1jzkhHUCK +SH1mEke4QFTVZOf8pDi5nwPlCDQi8Aaqg8AnSDdzHzLcw1p6OdrgrQs5wAMkKkQS +dxwWK23GyVzMcA== +-----END ENCRYPTED PRIVATE KEY----- + +BAG #1 + Elements: 1 + Key ID: 3A:8B:1B:18:22:29:59:28:BC:B2:8B:A4:79:DB:08:DD:9C:75:20:01 +-----BEGIN CERTIFICATE----- +MIICQDCCAeegAwIBAgICBBkwCQYHKoZIzj0EATCBmzEUMBIGA1UECxMLU0FNUExF +IE9OTFkxFzAVBgNVBAoTDkNlcnRpY29tIENvcnAuMRAwDgYDVQQHEwdUb3JvbnRv +MRAwDgYDVQQEEwdPbnRhcmlvMTkwNwYDVQQDEzB0bHMuc2VjZy5vcmcgRUNDIHNl +Y3AyNTZyMSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxCzAJBgNVBAYTAkNBMB4XDTA2 +MDUwMTAwMDAwMFoXDTE1MDUwMTAwMDAwMFowgYsxFDASBgNVBAsTC1NBTVBMRSBP +TkxZMRcwFQYDVQQKEw5DZXJ0aWNvbSBDb3JwLjEQMA4GA1UEBxMHVG9yb250bzEQ +MA4GA1UEBBMHT250YXJpbzE2MDQGA1UEAxMtdGxzLnNlY2cub3JnIEVDQyBzZWNw +MjU2cjEgQ2xpZW50IENlcnRpZmljYXRlMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD +QgAENkiY+LPQxC7KmT0UuxQk9YmCNuM0svU1B9Co3hSE13ikYgF36r2po5+LSF88 +eqGWQNEstt3qIfjtKXBEgEkud6MqMCgwDgYDVR0PAQH/BAQDAgOIMBYGA1UdJQEB +/wQMMAoGCCsGAQUFBwMCMAkGByqGSM49BAEDSAAwRQIgRaKZLOAIsu4JzR1RQmA/ +Vk0toX2r0PVt9/DiIzO8vbMCIQDN+1ccOjLRvGe7Dx0S62MSH1A3Z3dmK+E31I/d +4KrkIg== +-----END CERTIFICATE----- diff --git a/SecurityTests/test-certs/SECG_ecc_rsa-secp256r1-client.pem b/SecurityTests/test-certs/SECG_ecc_rsa-secp256r1-client.pem new file mode 100644 index 00000000..f1555b05 --- /dev/null +++ b/SecurityTests/test-certs/SECG_ecc_rsa-secp256r1-client.pem @@ -0,0 +1,28 @@ +BAG #0 + Elements: 1 + Key ID: 43:85:09:0E:1A:D4:D1:EC:1D:9A:F9:8D:01:8A:38:DC:EC:B3:5E:AC +-----BEGIN ENCRYPTED PRIVATE KEY----- +MGgwHAYKKoZIhvcNAQwBAzAOBAhOSQT+jnrhJgICCAAESLYbifvjFHKHe5MGUWMP +amHOJ6674UnDtjmj0Ywh43m4LjZev/YSG4KyhUJEJukStkpHPamx3DtJCj4/XajG +E8u1tw83iMmMIA== +-----END ENCRYPTED PRIVATE KEY----- + +BAG #1 + Elements: 1 + Key ID: 43:85:09:0E:1A:D4:D1:EC:1D:9A:F9:8D:01:8A:38:DC:EC:B3:5E:AC +-----BEGIN CERTIFICATE----- +MIICgTCCAeqgAwIBAgICBBkwDQYJKoZIhvcNAQEEBQAwgZYxFDASBgNVBAsTC1NB +TVBMRSBPTkxZMRcwFQYDVQQKEw5DZXJ0aWNvbSBDb3JwLjEQMA4GA1UEBxMHVG9y +b250bzEQMA4GA1UEBBMHT250YXJpbzE0MDIGA1UEAxMrdGxzLnNlY2cub3JnIFJT +QSAxMDI0IENlcnRpZmljYXRlIEF1dGhvcml0eTELMAkGA1UEBhMCQ0EwHhcNMDYw +NTAxMDAwMDAwWhcNMTUwNTAxMDAwMDAwWjCBjzEUMBIGA1UECxMLU0FNUExFIE9O +TFkxFzAVBgNVBAoTDkNlcnRpY29tIENvcnAuMRAwDgYDVQQHEwdUb3JvbnRvMRAw +DgYDVQQEEwdPbnRhcmlvMTowOAYDVQQDEzF0bHMuc2VjZy5vcmcgRUNDLVJTQSBz +ZWNwMjU2cjEgQ2xpZW50IENlcnRpZmljYXRlMFkwEwYHKoZIzj0CAQYIKoZIzj0D +AQcDQgAENkiY+LPQxC7KmT0UuxQk9YmCNuM0svU1B9Co3hSE13ikYgF36r2po5+L +SF88eqGWQNEstt3qIfjtKXBEgEkud6MqMCgwDgYDVR0PAQH/BAQDAgOIMBYGA1Ud +JQEB/wQMMAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBBAUAA4GBAGIzvgvULZtfoBMF +xJyixSRNBsr3VN1IMCf2v5NM45d8p+NjD+YXocWuexA1EF4lpOWjSy2mhjwktOPt +UjnkRsOZoTr/QbOwWb18U9BGmZgkrIojUV4GDcufsJV1c0lgJFzNARr8rcoURMIK +ARC9GeHXLMAvxxe9n9sIW/4RUSus +-----END CERTIFICATE----- diff --git a/SecurityTests/test-certs/ServerCert.ecc.ecc.pem b/SecurityTests/test-certs/ServerCert.ecc.ecc.pem new file mode 100644 index 00000000..07ee989c --- /dev/null +++ b/SecurityTests/test-certs/ServerCert.ecc.ecc.pem @@ -0,0 +1,9 @@ +-----BEGIN CERTIFICATE----- +MIIBNDCB3AIBBDAJBgcqhkjOPQQBMCUxIzAhBgNVBAMMGlNlY3VyaXR5VGVzdCBD +QSBDZXJ0IChFQ0MpMB4XDTExMTExNDE5MzEzOVoXDTExMTIxNDE5MzEzOVowKjEo +MCYGA1UEAwwfU2VjdXJpdHlUZXN0cyBTZXJ2ZXIgQ2VydCAoRUNDKTBZMBMGByqG +SM49AgEGCCqGSM49AwEHA0IABIXbOlTTvCN5E7usCk6YcBOv/pnyh4OQpFXEWnIT +QSLUNmAGZV/KaxHyC+uE+PjiRdjcxKAqJFYxPc5RvL/+mgYwCQYHKoZIzj0EAQNI +ADBFAiEAn0keI44d02aA+FaBXPJ/+ja/zLk60H++8mdPGI+3qvkCIAIjSCL6kn6H +C1WY1/1+d7DHY0JTeUJJf8k7Hb1BWfNG +-----END CERTIFICATE----- diff --git a/SecurityTests/test-certs/ServerCert.ecc.rsa.pem b/SecurityTests/test-certs/ServerCert.ecc.rsa.pem new file mode 100644 index 00000000..0cad0d47 --- /dev/null +++ b/SecurityTests/test-certs/ServerCert.ecc.rsa.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBdjCB4AIBAzANBgkqhkiG9w0BAQUFADAlMSMwIQYDVQQDDBpTZWN1cml0eVRl +c3QgQ0EgQ2VydCAoUlNBKTAeFw0xMTExMTQxOTMxMzlaFw0xMTEyMTQxOTMxMzla +MCoxKDAmBgNVBAMMH1NlY3VyaXR5VGVzdHMgU2VydmVyIENlcnQgKEVDQykwWTAT +BgcqhkjOPQIBBggqhkjOPQMBBwNCAASF2zpU07wjeRO7rApOmHATr/6Z8oeDkKRV +xFpyE0Ei1DZgBmVfymsR8gvrhPj44kXY3MSgKiRWMT3OUby//poGMA0GCSqGSIb3 +DQEBBQUAA4GBAJCrP/smtSSBTrtU0SDYRPZ+mLJXUh75BRNpbWUbx4Yqahr+bdi6 +Zr0ZB3hh0Cfsl3mzOwIZwJMfIIIkCB9FjwGyF4PJE7mXFgy5NeiTMcQ/Y8n+c4yi +papKnqVHT39ZFgdrgiPvML9qEprTHmzGag9a5o+5fQ9ZAQbwdvXeGtc6 +-----END CERTIFICATE----- diff --git a/SecurityTests/test-certs/ServerCert.rsa.ecc.pem b/SecurityTests/test-certs/ServerCert.rsa.ecc.pem new file mode 100644 index 00000000..2bd3fc9a --- /dev/null +++ b/SecurityTests/test-certs/ServerCert.rsa.ecc.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBezCCASMCAQIwCQYHKoZIzj0EATAlMSMwIQYDVQQDDBpTZWN1cml0eVRlc3Qg +Q0EgQ2VydCAoRUNDKTAeFw0xMTExMTQxOTMxMzlaFw0xMTEyMTQxOTMxMzlaMCox +KDAmBgNVBAMMH1NlY3VyaXR5VGVzdHMgU2VydmVyIENlcnQgKFJTQSkwgZ8wDQYJ +KoZIhvcNAQEBBQADgY0AMIGJAoGBAMItnQMZpB3gi1CZ8Fh4+3JpT+kIkA3/Moqu +P6P2/adVva/4Uxfd0CV8AE5bZqgrimUVBzswmLVcQgyJ93WI3E2vqAIM90OiP/sn +MJSnIgj2ZaANEFKBDt3hYBDZkzs08g7hBK5vUykaSESQiFCRjRGT7I8IAE6Bvia3 +eGPe4mnlAgMBAAEwCQYHKoZIzj0EAQNHADBEAiBOKPczPb0PkaJw8YHUywnEpAhs +wRaE2PNHWjJwUbmZHgIgXVUy2/K30DEs9SHlUiL991KENDpuldfKVN2obeM0smE= +-----END CERTIFICATE----- diff --git a/SecurityTests/test-certs/ServerCert.rsa.rsa.pem b/SecurityTests/test-certs/ServerCert.rsa.rsa.pem new file mode 100644 index 00000000..65a3b3f1 --- /dev/null +++ b/SecurityTests/test-certs/ServerCert.rsa.rsa.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBvjCCAScCAQEwDQYJKoZIhvcNAQEFBQAwJTEjMCEGA1UEAwwaU2VjdXJpdHlU +ZXN0IENBIENlcnQgKFJTQSkwHhcNMTExMTE0MTkzMTM5WhcNMTExMjE0MTkzMTM5 +WjAqMSgwJgYDVQQDDB9TZWN1cml0eVRlc3RzIFNlcnZlciBDZXJ0IChSU0EpMIGf +MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCLZ0DGaQd4ItQmfBYePtyaU/pCJAN +/zKKrj+j9v2nVb2v+FMX3dAlfABOW2aoK4plFQc7MJi1XEIMifd1iNxNr6gCDPdD +oj/7JzCUpyII9mWgDRBSgQ7d4WAQ2ZM7NPIO4QSub1MpGkhEkIhQkY0Rk+yPCABO +gb4mt3hj3uJp5QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAKhBF706RaV39ohZqdOT +QwK0RZ/ES8xtrE+humkhbOctC5x7p9HO0pZbiWQYPwUn/k+5XHwe021Tj6h7v3Tg +I/U2SAW30+3F/6N9fWihmVHmU/92EO2bYmBA+HYSfBERm94s4w97kM2InP/EHyhI +089Tc0wnQdTcDBVFyfEy2L9F +-----END CERTIFICATE----- diff --git a/SecurityTests/test-certs/ServerKey.ecc.pem b/SecurityTests/test-certs/ServerKey.ecc.pem new file mode 100644 index 00000000..7b988b0f --- /dev/null +++ b/SecurityTests/test-certs/ServerKey.ecc.pem @@ -0,0 +1,25 @@ +Public Key Info: + Public Key Algorithm: ECC + Key Security Level: High + +curve: SECP256R1 +private key: + 7c:0c:c5:1a:1e:7d:fc:c0:ef:b7:e8:cf:60:b4:da: + c9:e9:0f:d2:bc:21:79:eb:cb:7d:b2:1b:71:cd:f4: + c5:32: +x: + 00:85:db:3a:54:d3:bc:23:79:13:bb:ac:0a:4e:98: + 70:13:af:fe:99:f2:87:83:90:a4:55:c4:5a:72:13: + 41:22:d4: +y: + 36:60:06:65:5f:ca:6b:11:f2:0b:eb:84:f8:f8:e2: + 45:d8:dc:c4:a0:2a:24:56:31:3d:ce:51:bc:bf:fe: + 9a:06: + +Public Key ID: 0E:EC:35:0C:A2:B7:81:2F:2B:D0:44:B3:21:94:5A:C0:AB:1D:C5:F3 + +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIHwMxRoeffzA77foz2C02snpD9K8IXnry32yG3HN9MUyoAoGCCqGSM49 +AwEHoUQDQgAEhds6VNO8I3kTu6wKTphwE6/+mfKHg5CkVcRachNBItQ2YAZlX8pr +EfIL64T4+OJF2NzEoCokVjE9zlG8v/6aBg== +-----END EC PRIVATE KEY----- diff --git a/SecurityTests/test-certs/ServerKey.rsa.pem b/SecurityTests/test-certs/ServerKey.rsa.pem new file mode 100644 index 00000000..3a181fd1 --- /dev/null +++ b/SecurityTests/test-certs/ServerKey.rsa.pem @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMItnQMZpB3gi1CZ +8Fh4+3JpT+kIkA3/MoquP6P2/adVva/4Uxfd0CV8AE5bZqgrimUVBzswmLVcQgyJ +93WI3E2vqAIM90OiP/snMJSnIgj2ZaANEFKBDt3hYBDZkzs08g7hBK5vUykaSESQ +iFCRjRGT7I8IAE6Bvia3eGPe4mnlAgMBAAECgYEAqH72QWttmzNvEJkUE2GgJ+60 +le2FO3AYRnjf5oL8JsljGaCtUgd7iBtrFJOBqCpoJEC0Dqujx7Rv5/uMjSQerZPV +azpOYBn/mUqFHSLv2SMMCjHu3YBgQchnMc3iP7xremXhFhdsrkDkghnLHM12RTYL +Lyq6b+w3l0+Y/hgtecECQQDkHhrcgn8WvileMSrzWUihhUuCdgupl7bTF8nETQky +wa9xLCkKttKZKErMB9dL5CH0AQ/+KnyZH3mrHQ7Hm5ZxAkEA2emHnPRwhqD1xlJr +QU4C1Erj8ZSTZhp4DLT2daXtclJ7Z1Ao1p5bJuV8mr6J6pVvysXqiVEsdHMsxUQ8 +d2/MtQJAJ85JCamL28AbH+CcihJOZkEISB+pMVLUCEniX2rB7CV4I9t83e3BGhC5 +3JiRrSCF/DojPErVqzKe3IkZhyNTQQJBALn6iohVQthT9Y7udqWEq/t9cy+SS36f +5oeJxrLAC3g/lxykmEYbXtZCk+cJ6XExWvjnk3Tgt50nUzWFOEoDO+UCQQCzesQy +yk375W0h4KSiHU+rzdqjkLTm5s6RbJ0sUp9gFqiknoAeLeakAfQKyqIz/iFVBGXL +z0AjPVrxWuKkTCFt +-----END PRIVATE KEY----- diff --git a/SecurityTests/test-certs/ServerReq.ecc.pem b/SecurityTests/test-certs/ServerReq.ecc.pem new file mode 100644 index 00000000..e26c2087 --- /dev/null +++ b/SecurityTests/test-certs/ServerReq.ecc.pem @@ -0,0 +1,7 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIHjMIGMAgEAMCoxKDAmBgNVBAMMH1NlY3VyaXR5VGVzdHMgU2VydmVyIENlcnQg +KEVDQykwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASF2zpU07wjeRO7rApOmHAT +r/6Z8oeDkKRVxFpyE0Ei1DZgBmVfymsR8gvrhPj44kXY3MSgKiRWMT3OUby//poG +oAAwCQYHKoZIzj0EAQNHADBEAiAHUnRoQlOGKfl2OB71WkUi7q5F9Dw1PJDjVeGf +yqZVugIgfDG8F0/dzrgrN1ZiVvrqDdHEZkdxJ3nHFHRBGDoZJFo= +-----END CERTIFICATE REQUEST----- diff --git a/SecurityTests/test-certs/ServerReq.rsa.pem b/SecurityTests/test-certs/ServerReq.rsa.pem new file mode 100644 index 00000000..1404b801 --- /dev/null +++ b/SecurityTests/test-certs/ServerReq.rsa.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBaTCB0wIBADAqMSgwJgYDVQQDDB9TZWN1cml0eVRlc3RzIFNlcnZlciBDZXJ0 +IChSU0EpMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCLZ0DGaQd4ItQmfBY +ePtyaU/pCJAN/zKKrj+j9v2nVb2v+FMX3dAlfABOW2aoK4plFQc7MJi1XEIMifd1 +iNxNr6gCDPdDoj/7JzCUpyII9mWgDRBSgQ7d4WAQ2ZM7NPIO4QSub1MpGkhEkIhQ +kY0Rk+yPCABOgb4mt3hj3uJp5QIDAQABoAAwDQYJKoZIhvcNAQEFBQADgYEAUQxm +ZZU7G1eUyizNJ+x5F6nR8SAiGMPKjPoDMedO4NWU5mmN12+vxe4VwFby1fQJUJG+ +1F0HuP05WJXrCqDy85Xnj80+mS1u6NRapXtWTBWk4XHsjVkE9+2yMdbZ3BNp4Hcy +XqBiwBfTx8mia7rgIEZVjfb3cAk4bxFqMtAULfE= +-----END CERTIFICATE REQUEST----- diff --git a/SecurityTests/test-certs/ecparam.pem b/SecurityTests/test-certs/ecparam.pem new file mode 100644 index 00000000..32d952ea --- /dev/null +++ b/SecurityTests/test-certs/ecparam.pem @@ -0,0 +1,3 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQACg== +-----END EC PARAMETERS----- diff --git a/SecurityTests/testKeychainAPI/English.lproj/InfoPlist.strings b/SecurityTests/testKeychainAPI/English.lproj/InfoPlist.strings new file mode 100644 index 00000000..7658fc22 --- /dev/null +++ b/SecurityTests/testKeychainAPI/English.lproj/InfoPlist.strings @@ -0,0 +1,5 @@ +/* Localized versions of Info.plist keys */ + +CFBundleName = "CarbonApp"; +CFBundleShortVersionString = "CarbonApp version 0.0.1d1"; +CFBundleGetInfoString = "CarbonApp version 0.0.1d1, Copyright 2000, MyGreatSoftware."; diff --git a/SecurityTests/testKeychainAPI/run.sh b/SecurityTests/testKeychainAPI/run.sh new file mode 100755 index 00000000..80709209 --- /dev/null +++ b/SecurityTests/testKeychainAPI/run.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +HOME=/tmp/kc$$ +export HOME +mkdir -p $HOME/Library/Preferences + +echo Running with HOME=$HOME + +${LOCAL_BUILD_DIR}/testKeychainAPI.app/Contents/MacOS/testKeychainAPI -vnall +${LOCAL_BUILD_DIR}/testKeychainAPI.app/Contents/MacOS/testKeychainAPI -vsall + +rm -rf /tmp/kc$$ diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI.cwp/testKeychainAPI/testKeychainAPI b/SecurityTests/testKeychainAPI/testKeychainAPI.cwp/testKeychainAPI/testKeychainAPI new file mode 100644 index 0000000000000000000000000000000000000000..4ca84d6bddd7322f21ef2d571168e947127c6c32 GIT binary patch literal 71104 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 literal 0 HcmV?d00001 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI.pbproj/project.pbxproj b/SecurityTests/testKeychainAPI/testKeychainAPI.pbproj/project.pbxproj new file mode 100644 index 00000000..6c5952d5 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI.pbproj/project.pbxproj @@ -0,0 +1,1871 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 39; + objects = { + 00C85A54FEA53F3711CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + path = Radar.cpp; + refType = 4; + sourceTree = ""; + }; + 00C85A55FEA53F3711CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = Radar.h; + refType = 4; + sourceTree = ""; + }; + 00C85A58FEA5469711CD2A60 = { + children = ( + 00C85A59FEA5469711CD2A60, + 00C85A5AFEA5469711CD2A60, + 439B82D7FEB134D611CD2A60, + 1B0D0ABCFEAD2FFE11CD2A60, + 15A5F76FFEC0FEAB11CD2A60, + 2AE1C682FEAEB9E511CD2A60, + 15A5F771FEC1024711CD2A60, + 2AE1C686FEAF848911CD2A60, + 15A5F773FEC104FB11CD2A60, + 3C5F1DF5FEAFCCDC11CD2A60, + 15A5F775FEC1058011CD2A60, + 3C5F1DF7FEAFCE0911CD2A60, + 15A5F777FEC1093311CD2A60, + 3C5F1DF9FEAFCEAF11CD2A60, + 15A5F779FEC109BD11CD2A60, + 3C5F1DFBFEAFCF4611CD2A60, + 15A5F77BFEC10AE211CD2A60, + 3C5F1DFDFEAFE1B711CD2A60, + 00E41F6EFEB4C28611CD2A60, + 15A5F77DFEC1116B11CD2A60, + 40894A8BFEB0E0F911CD2A60, + 00E41F70FEB4C54E11CD2A60, + 00E41F71FEB4C54E11CD2A60, + 00E41F72FEB4C54E11CD2A60, + 439B82D3FEB12E9C11CD2A60, + 15A5F77FFEC1185511CD2A60, + 00E41F73FEB4C54E11CD2A60, + 15A5F781FEC1194511CD2A60, + 00E41F74FEB4C54E11CD2A60, + 15A5F783FEC119F911CD2A60, + 00E41F75FEB4C54E11CD2A60, + 15A5F785FEC11AFA11CD2A60, + 00E41F76FEB4C54E11CD2A60, + 1FA1A592FEC38E1611CD2A60, + 00F69664FEB4F50D11CD2A60, + 00F69666FEB4F6DC11CD2A60, + 00F69668FEB4F87D11CD2A60, + 00F6966AFEB4F92A11CD2A60, + 00EFF7F5FEB920BF11CD2A60, + 00EFF7F6FEB920BF11CD2A60, + 00EFF7F7FEB920BF11CD2A60, + 00EFF7F8FEB920BF11CD2A60, + 00EFF7F9FEB920BF11CD2A60, + 098DBF7CFEBA2C3511CD2A60, + 1FA1A58CFEC389EA11CD2A60, + 1FA1A58EFEC38BB411CD2A60, + 1FA1A596FEC3903011CD2A60, + 098DBF7EFEBA2D9E11CD2A60, + 1FA1A590FEC38C3011CD2A60, + 1FA1A598FEC3916E11CD2A60, + 1FA1A59AFEC3920D11CD2A60, + 098DBF80FEBA2E5311CD2A60, + 1FA1A594FEC38F4B11CD2A60, + 1FA1A59CFEC3930C11CD2A60, + 1FA1A59EFEC3937211CD2A60, + 098DBF82FEBA2F3811CD2A60, + 1FA1A5A0FEC3946E11CD2A60, + 098DBF84FEBA2FD711CD2A60, + 1FA1A5A2FEC394EE11CD2A60, + 098DBF86FEBA305A11CD2A60, + 1FA1A5A4FEC395F311CD2A60, + 09A72047FF0ADC1311CD287F, + 033D0E58FF0AD25311CD287F, + 2AE1C684FEAF841411CD2A60, + F51787050086346001CD2B7F, + 03FB9BD10066BA857F000001, + 03FB9BD30066CF0B7F000001, + ); + isa = PBXGroup; + name = scripts; + path = testKeychainAPI/scripts; + refType = 4; + sourceTree = ""; + }; + 00C85A59FEA5469711CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0000; + refType = 4; + sourceTree = ""; + }; + 00C85A5AFEA5469711CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0001; + refType = 4; + sourceTree = ""; + }; + 00C85A5BFEA5469711CD2A60 = { + fileRef = 00C85A59FEA5469711CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 00C85A5CFEA5469711CD2A60 = { + fileRef = 00C85A5AFEA5469711CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 00C8F077FE9ED53D11CD2A60 = { + children = ( + 00C8F08AFE9ED53D11CD2A60, + 1B0D0AB8FEAD1D8211CD2A60, + 00C85A54FEA53F3711CD2A60, + 00C85A55FEA53F3711CD2A60, + 00C8F078FE9ED53D11CD2A60, + 00C8F079FE9ED53D11CD2A60, + 00C8F07AFE9ED53D11CD2A60, + 00C8F07BFE9ED53D11CD2A60, + 00C8F07CFE9ED53D11CD2A60, + 00C8F07DFE9ED53D11CD2A60, + 00C8F07EFE9ED53D11CD2A60, + 00C8F07FFE9ED53D11CD2A60, + 00C8F080FE9ED53D11CD2A60, + 00C8F081FE9ED53D11CD2A60, + 00C8F082FE9ED53D11CD2A60, + 00C8F083FE9ED53D11CD2A60, + 00C8F084FE9ED53D11CD2A60, + 00C8F085FE9ED53D11CD2A60, + 00C8F086FE9ED53D11CD2A60, + 00C8F087FE9ED53D11CD2A60, + 00C8F088FE9ED53D11CD2A60, + 00C8F089FE9ED53D11CD2A60, + ); + isa = PBXGroup; + path = testKeychainAPI; + refType = 4; + sourceTree = ""; + }; + 00C8F078FE9ED53D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + path = KCAPI_Cert.cpp; + refType = 4; + sourceTree = ""; + }; + 00C8F079FE9ED53D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = KCAPI_Cert.h; + refType = 4; + sourceTree = ""; + }; + 00C8F07AFE9ED53D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + path = KCAPI_CString.cpp; + refType = 4; + sourceTree = ""; + }; + 00C8F07BFE9ED53D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = KCAPI_CString.h; + refType = 4; + sourceTree = ""; + }; + 00C8F07CFE9ED53D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + path = KCAPI_Item.cpp; + refType = 4; + sourceTree = ""; + }; + 00C8F07DFE9ED53D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = KCAPI_Item.h; + refType = 4; + sourceTree = ""; + }; + 00C8F07EFE9ED53D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + path = KCAPI_Keychain.cpp; + refType = 4; + sourceTree = ""; + }; + 00C8F07FFE9ED53D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = KCAPI_Keychain.h; + refType = 4; + sourceTree = ""; + }; + 00C8F080FE9ED53D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + path = KCAPI_Manager.cpp; + refType = 4; + sourceTree = ""; + }; + 00C8F081FE9ED53D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = KCAPI_Manager.h; + refType = 4; + sourceTree = ""; + }; + 00C8F082FE9ED53D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + path = KCAPI_Password.cpp; + refType = 4; + sourceTree = ""; + }; + 00C8F083FE9ED53D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = KCAPI_Password.h; + refType = 4; + sourceTree = ""; + }; + 00C8F084FE9ED53D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + path = KCOperation.cpp; + refType = 4; + sourceTree = ""; + }; + 00C8F085FE9ED53D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = KCOperation.h; + refType = 4; + sourceTree = ""; + }; + 00C8F086FE9ED53D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + path = KCOperationID.cpp; + refType = 4; + sourceTree = ""; + }; + 00C8F087FE9ED53D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = KCOperationID.h; + refType = 4; + sourceTree = ""; + }; + 00C8F088FE9ED53D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + path = KCParamUtility.cpp; + refType = 4; + sourceTree = ""; + }; + 00C8F089FE9ED53D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = KCParamUtility.h; + refType = 4; + sourceTree = ""; + }; + 00C8F08AFE9ED53D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + path = testKeychainAPI.cpp; + refType = 4; + sourceTree = ""; + }; + 00C8F08BFE9ED53D11CD2A60 = { + children = ( + 21E9F1C7FF1D12F211CD283A, + ); + isa = PBXGroup; + name = Products; + refType = 4; + sourceTree = ""; + }; + 00E41F6EFEB4C28611CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0010; + refType = 4; + sourceTree = ""; + }; + 00E41F6FFEB4C28611CD2A60 = { + fileRef = 00E41F6EFEB4C28611CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 00E41F70FEB4C54E11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0011.001; + refType = 4; + sourceTree = ""; + }; + 00E41F71FEB4C54E11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0011.002; + refType = 4; + sourceTree = ""; + }; + 00E41F72FEB4C54E11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0011.003; + refType = 4; + sourceTree = ""; + }; + 00E41F73FEB4C54E11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0013; + refType = 4; + sourceTree = ""; + }; + 00E41F74FEB4C54E11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0014; + refType = 4; + sourceTree = ""; + }; + 00E41F75FEB4C54E11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0015; + refType = 4; + sourceTree = ""; + }; + 00E41F76FEB4C54E11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0016; + refType = 4; + sourceTree = ""; + }; + 00E41F77FEB4C54E11CD2A60 = { + fileRef = 00E41F70FEB4C54E11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 00E41F78FEB4C54E11CD2A60 = { + fileRef = 00E41F71FEB4C54E11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 00E41F79FEB4C54E11CD2A60 = { + fileRef = 00E41F72FEB4C54E11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 00E41F7AFEB4C54E11CD2A60 = { + fileRef = 00E41F73FEB4C54E11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 00E41F7BFEB4C54E11CD2A60 = { + fileRef = 00E41F74FEB4C54E11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 00E41F7CFEB4C54E11CD2A60 = { + fileRef = 00E41F75FEB4C54E11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 00E41F7DFEB4C54E11CD2A60 = { + fileRef = 00E41F76FEB4C54E11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 00EFF7F5FEB920BF11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0021; + refType = 4; + sourceTree = ""; + }; + 00EFF7F6FEB920BF11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0022; + refType = 4; + sourceTree = ""; + }; + 00EFF7F7FEB920BF11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0023; + refType = 4; + sourceTree = ""; + }; + 00EFF7F8FEB920BF11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0024; + refType = 4; + sourceTree = ""; + }; + 00EFF7F9FEB920BF11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0025; + refType = 4; + sourceTree = ""; + }; + 00EFF7FAFEB920BF11CD2A60 = { + fileRef = 00EFF7F5FEB920BF11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 00EFF7FBFEB920BF11CD2A60 = { + fileRef = 00EFF7F6FEB920BF11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 00EFF7FCFEB920BF11CD2A60 = { + fileRef = 00EFF7F7FEB920BF11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 00EFF7FDFEB920BF11CD2A60 = { + fileRef = 00EFF7F8FEB920BF11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 00EFF7FEFEB920BF11CD2A60 = { + fileRef = 00EFF7F9FEB920BF11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 00F69664FEB4F50D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0017; + refType = 4; + sourceTree = ""; + }; + 00F69665FEB4F50D11CD2A60 = { + fileRef = 00F69664FEB4F50D11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 00F69666FEB4F6DC11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0018; + refType = 4; + sourceTree = ""; + }; + 00F69667FEB4F6DC11CD2A60 = { + fileRef = 00F69666FEB4F6DC11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 00F69668FEB4F87D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0019; + refType = 4; + sourceTree = ""; + }; + 00F69669FEB4F87D11CD2A60 = { + fileRef = 00F69668FEB4F87D11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 00F6966AFEB4F92A11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0020; + refType = 4; + sourceTree = ""; + }; + 00F6966BFEB4F92A11CD2A60 = { + fileRef = 00F6966AFEB4F92A11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; +//000 +//001 +//002 +//003 +//004 +//010 +//011 +//012 +//013 +//014 + 01349571FFB0B4D211CD287F = { + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + OPTIMIZATION_CFLAGS = "-O0 -fno-inline"; + ZERO_LINK = YES; + }; + isa = PBXBuildStyle; + name = Development; + }; + 01349572FFB0B4D211CD287F = { + buildSettings = { + COPY_PHASE_STRIP = YES; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + ZERO_LINK = NO; + }; + isa = PBXBuildStyle; + name = Deployment; + }; +//010 +//011 +//012 +//013 +//014 +//030 +//031 +//032 +//033 +//034 + 033D0E57FF0ACE4D11CD287F = { + fileRef = 2AE1C684FEAF841411CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 033D0E58FF0AD25311CD287F = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0033; + refType = 4; + sourceTree = ""; + }; + 033D0E59FF0AD25311CD287F = { + fileRef = 033D0E58FF0AD25311CD287F; + isa = PBXBuildFile; + settings = { + }; + }; + 03FB9BD10066BA857F000001 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = error_scripts; + refType = 4; + sourceTree = ""; + }; + 03FB9BD20066BA857F000001 = { + fileRef = 03FB9BD10066BA857F000001; + isa = PBXBuildFile; + settings = { + }; + }; + 03FB9BD30066CF0B7F000001 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = error_sub_cases_scripts; + refType = 4; + sourceTree = ""; + }; + 03FB9BD40066CF0B7F000001 = { + fileRef = 03FB9BD30066CF0B7F000001; + isa = PBXBuildFile; + settings = { + }; + }; +//030 +//031 +//032 +//033 +//034 +//040 +//041 +//042 +//043 +//044 + 04313892FE3035C9C02AAC07 = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXRezBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; +//040 +//041 +//042 +//043 +//044 +//080 +//081 +//082 +//083 +//084 + 0867D6AAFE840B52C02AAC07 = { + children = ( + 0867D6ABFE840B52C02AAC07, + ); + isa = PBXVariantGroup; + name = InfoPlist.strings; + refType = 4; + sourceTree = ""; + }; + 0867D6ABFE840B52C02AAC07 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text.plist.strings; + name = English; + path = English.lproj/InfoPlist.strings; + refType = 4; + sourceTree = ""; + }; + 0867D6ACFE840B52C02AAC07 = { + fileRef = 0867D6AAFE840B52C02AAC07; + isa = PBXBuildFile; + settings = { + }; + }; +//080 +//081 +//082 +//083 +//084 +//090 +//091 +//092 +//093 +//094 + 098DBF7CFEBA2C3511CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0026; + refType = 4; + sourceTree = ""; + }; + 098DBF7DFEBA2C3511CD2A60 = { + fileRef = 098DBF7CFEBA2C3511CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 098DBF7EFEBA2D9E11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0027; + refType = 4; + sourceTree = ""; + }; + 098DBF7FFEBA2D9E11CD2A60 = { + fileRef = 098DBF7EFEBA2D9E11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 098DBF80FEBA2E5311CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0028; + refType = 4; + sourceTree = ""; + }; + 098DBF81FEBA2E5311CD2A60 = { + fileRef = 098DBF80FEBA2E5311CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 098DBF82FEBA2F3811CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0029; + refType = 4; + sourceTree = ""; + }; + 098DBF83FEBA2F3811CD2A60 = { + fileRef = 098DBF82FEBA2F3811CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 098DBF84FEBA2FD711CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0030; + refType = 4; + sourceTree = ""; + }; + 098DBF85FEBA2FD711CD2A60 = { + fileRef = 098DBF84FEBA2FD711CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 098DBF86FEBA305A11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0031; + refType = 4; + sourceTree = ""; + }; + 098DBF87FEBA305A11CD2A60 = { + fileRef = 098DBF86FEBA305A11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 09A72047FF0ADC1311CD287F = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0032; + refType = 4; + sourceTree = ""; + }; + 09A72048FF0ADC1311CD287F = { + fileRef = 09A72047FF0ADC1311CD287F; + isa = PBXBuildFile; + settings = { + }; + }; +//090 +//091 +//092 +//093 +//094 +//150 +//151 +//152 +//153 +//154 + 15A5F76FFEC0FEAB11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0002.000; + refType = 4; + sourceTree = ""; + }; + 15A5F770FEC0FEAB11CD2A60 = { + fileRef = 15A5F76FFEC0FEAB11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 15A5F771FEC1024711CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0003.000; + refType = 4; + sourceTree = ""; + }; + 15A5F772FEC1024711CD2A60 = { + fileRef = 15A5F771FEC1024711CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 15A5F773FEC104FB11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0004.000; + refType = 4; + sourceTree = ""; + }; + 15A5F774FEC104FB11CD2A60 = { + fileRef = 15A5F773FEC104FB11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 15A5F775FEC1058011CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0005.000; + refType = 4; + sourceTree = ""; + }; + 15A5F776FEC1058011CD2A60 = { + fileRef = 15A5F775FEC1058011CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 15A5F777FEC1093311CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0006.000; + refType = 4; + sourceTree = ""; + }; + 15A5F778FEC1093311CD2A60 = { + fileRef = 15A5F777FEC1093311CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 15A5F779FEC109BD11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0007.000; + refType = 4; + sourceTree = ""; + }; + 15A5F77AFEC109BD11CD2A60 = { + fileRef = 15A5F779FEC109BD11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 15A5F77BFEC10AE211CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0008.000; + refType = 4; + sourceTree = ""; + }; + 15A5F77CFEC10AE211CD2A60 = { + fileRef = 15A5F77BFEC10AE211CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 15A5F77DFEC1116B11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0010.000; + refType = 4; + sourceTree = ""; + }; + 15A5F77EFEC1116B11CD2A60 = { + fileRef = 15A5F77DFEC1116B11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 15A5F77FFEC1185511CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0012.000; + refType = 4; + sourceTree = ""; + }; + 15A5F780FEC1185511CD2A60 = { + fileRef = 15A5F77FFEC1185511CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 15A5F781FEC1194511CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0013.000; + refType = 4; + sourceTree = ""; + }; + 15A5F782FEC1194511CD2A60 = { + fileRef = 15A5F781FEC1194511CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 15A5F783FEC119F911CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0014.000; + refType = 4; + sourceTree = ""; + }; + 15A5F784FEC119F911CD2A60 = { + fileRef = 15A5F783FEC119F911CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 15A5F785FEC11AFA11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0015.000; + refType = 4; + sourceTree = ""; + }; + 15A5F786FEC11AFA11CD2A60 = { + fileRef = 15A5F785FEC11AFA11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; +//150 +//151 +//152 +//153 +//154 +//1B0 +//1B1 +//1B2 +//1B3 +//1B4 + 1B0D0AB8FEAD1D8211CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = testKeychainAPI.h; + refType = 4; + sourceTree = ""; + }; + 1B0D0ABCFEAD2FFE11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0002; + refType = 4; + sourceTree = ""; + }; + 1B0D0ABDFEAD2FFE11CD2A60 = { + fileRef = 1B0D0ABCFEAD2FFE11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; +//1B0 +//1B1 +//1B2 +//1B3 +//1B4 +//1F0 +//1F1 +//1F2 +//1F3 +//1F4 + 1FA1A58CFEC389EA11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0026.000; + refType = 4; + sourceTree = ""; + }; + 1FA1A58DFEC389EA11CD2A60 = { + fileRef = 1FA1A58CFEC389EA11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 1FA1A58EFEC38BB411CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0026.001; + refType = 4; + sourceTree = ""; + }; + 1FA1A58FFEC38BB411CD2A60 = { + fileRef = 1FA1A58EFEC38BB411CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 1FA1A590FEC38C3011CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0027.000; + refType = 4; + sourceTree = ""; + }; + 1FA1A591FEC38C3011CD2A60 = { + fileRef = 1FA1A590FEC38C3011CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 1FA1A592FEC38E1611CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0016.000; + refType = 4; + sourceTree = ""; + }; + 1FA1A593FEC38E1611CD2A60 = { + fileRef = 1FA1A592FEC38E1611CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 1FA1A594FEC38F4B11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0028.000; + refType = 4; + sourceTree = ""; + }; + 1FA1A595FEC38F4B11CD2A60 = { + fileRef = 1FA1A594FEC38F4B11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 1FA1A596FEC3903011CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0026.002; + refType = 4; + sourceTree = ""; + }; + 1FA1A597FEC3903011CD2A60 = { + fileRef = 1FA1A596FEC3903011CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 1FA1A598FEC3916E11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0027.001; + refType = 4; + sourceTree = ""; + }; + 1FA1A599FEC3916E11CD2A60 = { + fileRef = 1FA1A598FEC3916E11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 1FA1A59AFEC3920D11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0027.002; + refType = 4; + sourceTree = ""; + }; + 1FA1A59BFEC3920D11CD2A60 = { + fileRef = 1FA1A59AFEC3920D11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 1FA1A59CFEC3930C11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0028.001; + refType = 4; + sourceTree = ""; + }; + 1FA1A59DFEC3930C11CD2A60 = { + fileRef = 1FA1A59CFEC3930C11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 1FA1A59EFEC3937211CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0028.002; + refType = 4; + sourceTree = ""; + }; + 1FA1A59FFEC3937211CD2A60 = { + fileRef = 1FA1A59EFEC3937211CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 1FA1A5A0FEC3946E11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0029.000; + refType = 4; + sourceTree = ""; + }; + 1FA1A5A1FEC3946E11CD2A60 = { + fileRef = 1FA1A5A0FEC3946E11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 1FA1A5A2FEC394EE11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0030.000; + refType = 4; + sourceTree = ""; + }; + 1FA1A5A3FEC394EE11CD2A60 = { + fileRef = 1FA1A5A2FEC394EE11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 1FA1A5A4FEC395F311CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0031.000; + refType = 4; + sourceTree = ""; + }; + 1FA1A5A5FEC395F311CD2A60 = { + fileRef = 1FA1A5A4FEC395F311CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; +//1F0 +//1F1 +//1F2 +//1F3 +//1F4 +//200 +//201 +//202 +//203 +//204 + 20286C28FDCF999611CA2CEA = { + buildSettings = { + }; + buildStyles = ( + 01349571FFB0B4D211CD287F, + 01349572FFB0B4D211CD287F, + 30197C39FFFD721711CD283A, + ); + hasScannedForEncodings = 1; + isa = PBXProject; + mainGroup = 20286C29FDCF999611CA2CEA; + projectDirPath = ""; + targets = ( + 20286C34FDCF999611CA2CEA, + ); + }; + 20286C29FDCF999611CA2CEA = { + children = ( + 00C8F077FE9ED53D11CD2A60, + 20286C2CFDCF999611CA2CEA, + 20286C32FDCF999611CA2CEA, + 00C8F08BFE9ED53D11CD2A60, + ); + isa = PBXGroup; + name = testKeychainAPI; + path = ""; + refType = 4; + sourceTree = ""; + }; + 20286C2CFDCF999611CA2CEA = { + children = ( + 0867D6AAFE840B52C02AAC07, + 00C85A58FEA5469711CD2A60, + ); + isa = PBXGroup; + name = Resources; + path = ""; + refType = 4; + sourceTree = ""; + }; + 20286C32FDCF999611CA2CEA = { + children = ( + 20286C33FDCF999611CA2CEA, + F556AF770107963D01CD283A, + ); + isa = PBXGroup; + name = "External Frameworks and Libraries"; + path = ""; + refType = 4; + sourceTree = ""; + }; + 20286C33FDCF999611CA2CEA = { + isa = PBXFileReference; + lastKnownFileType = wrapper.framework; + name = Carbon.framework; + path = /System/Library/Frameworks/Carbon.framework; + refType = 0; + sourceTree = ""; + }; + 20286C34FDCF999611CA2CEA = { + buildPhases = ( + 20286C35FDCF999611CA2CEA, + 20286C36FDCF999611CA2CEA, + 20286C38FDCF999611CA2CEA, + 20286C3BFDCF999611CA2CEA, + 04313892FE3035C9C02AAC07, + ); + buildSettings = { + FRAMEWORK_SEARCH_PATHS = "\"$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks\" \"$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/OSServices.framework\" \"$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Frameworks\" /usr/local/SecurityPieces/Frameworks"; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)\""; + INSTALL_PATH = /AppleInternal/Applications; + LIBRARY_SEARCH_PATHS = ""; + OTHER_CFLAGS = "-DCALL_IN_KEYCHAIN_BUT_NOT_IN_CARBON=1"; + OTHER_LDFLAGS = "-lstdc++"; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = testKeychainAPI; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; + WRAPPER_EXTENSION = app; + }; + dependencies = ( + ); + isa = PBXApplicationTarget; + name = testKeychainAPI; + productInstallPath = /AppleInternal/Applications; + productName = testKeychainAPI; + productReference = 21E9F1C7FF1D12F211CD283A; + productSettingsXML = " + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + testKeychainAPI + CFBundleIconFile + + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 0.0.1d1 + + +"; + }; + 20286C35FDCF999611CA2CEA = { + buildActionMask = 2147483647; + files = ( + 3CB71739FFAE65EC11CD287F, + 3CB7173BFFAE660711CD287F, + 3CB7173FFFAE662911CD287F, + 3CB71741FFAE663611CD287F, + 3CB71743FFAE666411CD287F, + 3CB71744FFAE666411CD287F, + 3CB71745FFAE666411CD287F, + 3CB71746FFAE666411CD287F, + 3CB71747FFAE666411CD287F, + 3CB71748FFAE666411CD287F, + 3CB7174FFFAE66CD11CD287F, + ); + isa = PBXHeadersBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + 20286C36FDCF999611CA2CEA = { + buildActionMask = 2147483647; + files = ( + 0867D6ACFE840B52C02AAC07, + 00C85A5BFEA5469711CD2A60, + 00C85A5CFEA5469711CD2A60, + 1B0D0ABDFEAD2FFE11CD2A60, + 2AE1C683FEAEB9E511CD2A60, + 2AE1C687FEAF848911CD2A60, + 3C5F1DF6FEAFCCDC11CD2A60, + 3C5F1DF8FEAFCE0911CD2A60, + 3C5F1DFAFEAFCEAF11CD2A60, + 3C5F1DFCFEAFCF4611CD2A60, + 3C5F1DFEFEAFE1B711CD2A60, + 40894A8CFEB0E0F911CD2A60, + 439B82D4FEB12E9C11CD2A60, + 439B82D8FEB134D611CD2A60, + 00E41F6FFEB4C28611CD2A60, + 00E41F77FEB4C54E11CD2A60, + 00E41F78FEB4C54E11CD2A60, + 00E41F79FEB4C54E11CD2A60, + 00E41F7AFEB4C54E11CD2A60, + 00E41F7BFEB4C54E11CD2A60, + 00E41F7CFEB4C54E11CD2A60, + 00E41F7DFEB4C54E11CD2A60, + 00F69665FEB4F50D11CD2A60, + 00F69667FEB4F6DC11CD2A60, + 00F69669FEB4F87D11CD2A60, + 00F6966BFEB4F92A11CD2A60, + 00EFF7FAFEB920BF11CD2A60, + 00EFF7FBFEB920BF11CD2A60, + 00EFF7FCFEB920BF11CD2A60, + 00EFF7FDFEB920BF11CD2A60, + 00EFF7FEFEB920BF11CD2A60, + 098DBF7DFEBA2C3511CD2A60, + 098DBF7FFEBA2D9E11CD2A60, + 098DBF81FEBA2E5311CD2A60, + 098DBF83FEBA2F3811CD2A60, + 098DBF85FEBA2FD711CD2A60, + 098DBF87FEBA305A11CD2A60, + 15A5F770FEC0FEAB11CD2A60, + 15A5F772FEC1024711CD2A60, + 15A5F774FEC104FB11CD2A60, + 15A5F776FEC1058011CD2A60, + 15A5F778FEC1093311CD2A60, + 15A5F77AFEC109BD11CD2A60, + 15A5F77CFEC10AE211CD2A60, + 15A5F77EFEC1116B11CD2A60, + 15A5F780FEC1185511CD2A60, + 15A5F782FEC1194511CD2A60, + 15A5F784FEC119F911CD2A60, + 15A5F786FEC11AFA11CD2A60, + 1FA1A58DFEC389EA11CD2A60, + 1FA1A58FFEC38BB411CD2A60, + 1FA1A591FEC38C3011CD2A60, + 1FA1A593FEC38E1611CD2A60, + 1FA1A595FEC38F4B11CD2A60, + 1FA1A597FEC3903011CD2A60, + 1FA1A599FEC3916E11CD2A60, + 1FA1A59BFEC3920D11CD2A60, + 1FA1A59DFEC3930C11CD2A60, + 1FA1A59FFEC3937211CD2A60, + 1FA1A5A1FEC3946E11CD2A60, + 1FA1A5A3FEC394EE11CD2A60, + 1FA1A5A5FEC395F311CD2A60, + 033D0E57FF0ACE4D11CD287F, + 033D0E59FF0AD25311CD287F, + 09A72048FF0ADC1311CD287F, + 03FB9BD20066BA857F000001, + 03FB9BD40066CF0B7F000001, + F51787060086346001CD2B7F, + ); + isa = PBXResourcesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + 20286C38FDCF999611CA2CEA = { + buildActionMask = 2147483647; + files = ( + 3CB7173AFFAE65EC11CD287F, + 3CB7173CFFAE660711CD287F, + 3CB71740FFAE662911CD287F, + 3CB71742FFAE663611CD287F, + 3CB71749FFAE666411CD287F, + 3CB7174AFFAE666411CD287F, + 3CB7174BFFAE666411CD287F, + 3CB7174CFFAE666411CD287F, + 3CB7174DFFAE666411CD287F, + 3CB7174EFFAE666411CD287F, + 3CB71751FFAE6A8B11CD287F, + ); + isa = PBXSourcesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + 20286C3BFDCF999611CA2CEA = { + buildActionMask = 2147483647; + files = ( + 20286C3CFDCF999611CA2CEA, + F556AF780107963D01CD283A, + ); + isa = PBXFrameworksBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + 20286C3CFDCF999611CA2CEA = { + fileRef = 20286C33FDCF999611CA2CEA; + isa = PBXBuildFile; + settings = { + }; + }; +//200 +//201 +//202 +//203 +//204 +//210 +//211 +//212 +//213 +//214 + 21E9F1C7FF1D12F211CD283A = { + explicitFileType = wrapper.application; + isa = PBXFileReference; + path = testKeychainAPI.app; + refType = 3; + sourceTree = BUILT_PRODUCTS_DIR; + }; +//210 +//211 +//212 +//213 +//214 +//2A0 +//2A1 +//2A2 +//2A3 +//2A4 + 2AE1C682FEAEB9E511CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0003; + refType = 4; + sourceTree = ""; + }; + 2AE1C683FEAEB9E511CD2A60 = { + fileRef = 2AE1C682FEAEB9E511CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 2AE1C684FEAF841411CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0034; + refType = 4; + sourceTree = ""; + }; + 2AE1C686FEAF848911CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0004; + refType = 4; + sourceTree = ""; + }; + 2AE1C687FEAF848911CD2A60 = { + fileRef = 2AE1C686FEAF848911CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; +//2A0 +//2A1 +//2A2 +//2A3 +//2A4 +//300 +//301 +//302 +//303 +//304 + 30197C39FFFD721711CD283A = { + buildSettings = { + COPY_PHASE_STRIP = NO; + OPTIMIZATION_CFLAGS = "-O0 -fno-inline"; + OTHER_LDFLAGS = "\U0001-dylib_file \"$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/A/Security:$(SYMROOT)/Security.framework/Versions/A/Security\" -dylib_file \"$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Versions/A/Frameworks/OSServices.framework/Versions/A/OSServices:$(SYMROOT)/OSServices.framework/Versions/A/OSServices\" -dylib_file \"$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Versions/A/Frameworks/SecurityHI.framework/Versions/A/SecurityHI:$(SYMROOT)/SecurityHI.framework/Versions/A/SecurityHI\""; + }; + isa = PBXBuildStyle; + name = "Build Folder"; + }; +//300 +//301 +//302 +//303 +//304 +//3C0 +//3C1 +//3C2 +//3C3 +//3C4 + 3C5F1DF5FEAFCCDC11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0005; + refType = 4; + sourceTree = ""; + }; + 3C5F1DF6FEAFCCDC11CD2A60 = { + fileRef = 3C5F1DF5FEAFCCDC11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 3C5F1DF7FEAFCE0911CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0006; + refType = 4; + sourceTree = ""; + }; + 3C5F1DF8FEAFCE0911CD2A60 = { + fileRef = 3C5F1DF7FEAFCE0911CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 3C5F1DF9FEAFCEAF11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0007; + refType = 4; + sourceTree = ""; + }; + 3C5F1DFAFEAFCEAF11CD2A60 = { + fileRef = 3C5F1DF9FEAFCEAF11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 3C5F1DFBFEAFCF4611CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0008; + refType = 4; + sourceTree = ""; + }; + 3C5F1DFCFEAFCF4611CD2A60 = { + fileRef = 3C5F1DFBFEAFCF4611CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 3C5F1DFDFEAFE1B711CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0009; + refType = 4; + sourceTree = ""; + }; + 3C5F1DFEFEAFE1B711CD2A60 = { + fileRef = 3C5F1DFDFEAFE1B711CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 3CB71739FFAE65EC11CD287F = { + fileRef = 1B0D0AB8FEAD1D8211CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 3CB7173AFFAE65EC11CD287F = { + fileRef = 00C8F08AFE9ED53D11CD2A60; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + ); + }; + }; + 3CB7173BFFAE660711CD287F = { + fileRef = 00C85A55FEA53F3711CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 3CB7173CFFAE660711CD287F = { + fileRef = 00C85A54FEA53F3711CD2A60; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + ); + }; + }; + 3CB7173FFFAE662911CD287F = { + fileRef = 00C8F07BFE9ED53D11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 3CB71740FFAE662911CD287F = { + fileRef = 00C8F07AFE9ED53D11CD2A60; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + ); + }; + }; + 3CB71741FFAE663611CD287F = { + fileRef = 00C8F07DFE9ED53D11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 3CB71742FFAE663611CD287F = { + fileRef = 00C8F07CFE9ED53D11CD2A60; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + ); + }; + }; + 3CB71743FFAE666411CD287F = { + fileRef = 00C8F07FFE9ED53D11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 3CB71744FFAE666411CD287F = { + fileRef = 00C8F081FE9ED53D11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 3CB71745FFAE666411CD287F = { + fileRef = 00C8F083FE9ED53D11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 3CB71746FFAE666411CD287F = { + fileRef = 00C8F085FE9ED53D11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 3CB71747FFAE666411CD287F = { + fileRef = 00C8F087FE9ED53D11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 3CB71748FFAE666411CD287F = { + fileRef = 00C8F089FE9ED53D11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 3CB71749FFAE666411CD287F = { + fileRef = 00C8F07EFE9ED53D11CD2A60; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + ); + }; + }; + 3CB7174AFFAE666411CD287F = { + fileRef = 00C8F080FE9ED53D11CD2A60; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + ); + }; + }; + 3CB7174BFFAE666411CD287F = { + fileRef = 00C8F082FE9ED53D11CD2A60; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + ); + }; + }; + 3CB7174CFFAE666411CD287F = { + fileRef = 00C8F084FE9ED53D11CD2A60; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + ); + }; + }; + 3CB7174DFFAE666411CD287F = { + fileRef = 00C8F086FE9ED53D11CD2A60; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + ); + }; + }; + 3CB7174EFFAE666411CD287F = { + fileRef = 00C8F088FE9ED53D11CD2A60; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + ); + }; + }; + 3CB7174FFFAE66CD11CD287F = { + fileRef = 00C8F079FE9ED53D11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 3CB71751FFAE6A8B11CD287F = { + fileRef = 00C8F078FE9ED53D11CD2A60; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + ); + }; + }; +//3C0 +//3C1 +//3C2 +//3C3 +//3C4 +//400 +//401 +//402 +//403 +//404 + 40894A8BFEB0E0F911CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0011; + refType = 4; + sourceTree = ""; + }; + 40894A8CFEB0E0F911CD2A60 = { + fileRef = 40894A8BFEB0E0F911CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; +//400 +//401 +//402 +//403 +//404 +//430 +//431 +//432 +//433 +//434 + 439B82D3FEB12E9C11CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0012; + refType = 4; + sourceTree = ""; + }; + 439B82D4FEB12E9C11CD2A60 = { + fileRef = 439B82D3FEB12E9C11CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; + 439B82D7FEB134D611CD2A60 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0001.001; + refType = 4; + sourceTree = ""; + }; + 439B82D8FEB134D611CD2A60 = { + fileRef = 439B82D7FEB134D611CD2A60; + isa = PBXBuildFile; + settings = { + }; + }; +//430 +//431 +//432 +//433 +//434 +//F50 +//F51 +//F52 +//F53 +//F54 + F51787050086346001CD2B7F = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text; + path = script0035; + refType = 4; + sourceTree = ""; + }; + F51787060086346001CD2B7F = { + fileRef = F51787050086346001CD2B7F; + isa = PBXBuildFile; + settings = { + }; + }; + F556AF770107963D01CD283A = { + isa = PBXFileReference; + lastKnownFileType = wrapper.framework; + name = Security.framework; + path = /System/Library/Frameworks/Security.framework; + refType = 0; + sourceTree = ""; + }; + F556AF780107963D01CD283A = { + fileRef = F556AF770107963D01CD283A; + isa = PBXBuildFile; + settings = { + }; + }; + }; + rootObject = 20286C28FDCF999611CA2CEA; +} diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_CString.cpp b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_CString.cpp new file mode 100644 index 00000000..3786f79f --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_CString.cpp @@ -0,0 +1,445 @@ +// ====================================================================== +// File: KCAPI_CString.cpp +// +// Operation classes for KC Manager APIs that use "C" strings +// - kcunlock +// - kccreatekeychain +// - kcgetkeychainname +// - kcaddapplesharepassword +// - kcfindapplesharepassword +// - kcaddinternetpassword +// - kcaddinternetpasswordwithpath +// - kcfindinternetpassword +// - kcfindinternetpasswordwithpath +// - kcaddgenericpassword +// - kcfindgenericpassword +// +// +// Copyright: Copyright (c) 2000,2003,2006 Apple Computer, Inc. All Rights Reserved. +// +// Change History (most recent first): +// +// <1> 3/1/00 em Created. +// ====================================================================== +#include "KCAPI_CString.h" +#include "KCParamUtility.h" + +#if TARGET_RT_MAC_MACHO + #include + #include + #include +#else + #include +#endif +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kcunlock +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_kcunlock::COp_kcunlock() + :mPassword("Password") +{ + AddParam(mKeychainIndex); + AddParam(mPassword); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_kcunlock::Operate() +{ + mStatus = ::kcunlock( + GetKeychain(), + (const char *)((StringPtr)mPassword+1)); + return(mStatus); +} + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kccreatekeychain +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_kccreatekeychain::COp_kccreatekeychain() + :mPassword("Password") +{ + AddParam(mPassword); + AddResult(mKeychainIndex); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_kccreatekeychain::Operate() +{ + KCRef aKeychain = NULL; + mStatus = ::kccreatekeychain( + (const char *)((StringPtr)mPassword+1), + (KCRef*)&aKeychain); + AddKeychain(aKeychain); + return(mStatus); +} + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kcgetkeychainname +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_kcgetkeychainname::COp_kcgetkeychainname() + :mKeychainName("KeychainName") +{ + AddParam(mKeychainIndex); + AddResult(mKeychainName); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_kcgetkeychainname::Operate() +{ + mStatus = ::kcgetkeychainname( + GetKeychain(), + (char*)((StringPtr)mKeychainName+1)); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kcaddapplesharepassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_kcaddapplesharepassword::COp_kcaddapplesharepassword() + :mServerSignature("ServerSignature"), + mServerAddress("ServerAddress"), + mServerName("ServerName"), + mVolumeName("VolumeName"), + mAccountName("AccountName"), + mPassword("Password") +{ + AddParam(mServerSignature); + AddParam(mServerAddress); + AddParam(mServerName); + AddParam(mVolumeName); + AddParam(mAccountName); + AddParam(mPassword); + + AddResult(mItemIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_kcaddapplesharepassword::Operate() +{ + KCItemRef aItem = NULL; + mStatus = ::kcaddapplesharepassword( + &static_cast(mServerSignature).data, + (const char *)((StringPtr)mServerAddress+1), + (const char *)((StringPtr)mServerName+1), + (const char *)((StringPtr)mVolumeName+1), + (const char *)((StringPtr)mAccountName+1), + (UInt32)((kcBlob*)mPassword)->length, + (const void *)((kcBlob*)mPassword)->data, + (KCItemRef*)&aItem); + AddItem(aItem); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kcfindapplesharepassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_kcfindapplesharepassword::COp_kcfindapplesharepassword() + :mServerSignature("ServerSignature"), + mServerAddress("ServerAddress"), + mServerName("ServerName"), + mVolumeName("VolumeName"), + mAccountName("AccountName"), + mPassword("Password"), + mActualLength("ActualLength") +{ + AddParam(mServerSignature); + AddParam(mServerAddress); + AddParam(mServerName); + AddParam(mVolumeName); + AddParam(mAccountName); + AddParam(mPassword); + + AddResult(mPassword); + AddResult(mActualLength); + AddResult(mItemIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_kcfindapplesharepassword::Operate() +{ + KCItemRef aItem = NULL; + mStatus = ::kcfindapplesharepassword( + &static_cast(mServerSignature).data, + (const char *)((StringPtr)mServerAddress+1), + (const char *)((StringPtr)mServerName+1), + (const char *)((StringPtr)mVolumeName+1), + (const char *)((StringPtr)mAccountName+1), + (UInt32)((kcBlob*)mPassword)->length, + (void *)((kcBlob*)mPassword)->data, + (UInt32*)mActualLength, + (KCItemRef *)&aItem); + AddItem(aItem); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kcaddinternetpassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_kcaddinternetpassword::COp_kcaddinternetpassword() + :mServerName("ServerName"), + mSecurityDomain("SecurityDomain"), + mAccountName("AccountName"), + mPort("Port"), + mProtocol("Protocol"), + mAuthType("AuthType"), + mPassword("Password") +{ + AddParam(mServerName); + AddParam(mSecurityDomain); + AddParam(mAccountName); + AddParam(mPort); + AddParam(mProtocol); + AddParam(mAuthType); + AddParam(mPassword); + + AddResult(mItemIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_kcaddinternetpassword::Operate() +{ + KCItemRef aItem = NULL; + mStatus = ::kcaddinternetpassword( + (const char *)((StringPtr)mServerName+1), + (const char *)((StringPtr)mSecurityDomain+1), + (const char *)((StringPtr)mAccountName+1), + (UInt16)mPort, + (OSType)mProtocol, + (OSType)mAuthType, + (UInt32)((kcBlob*)mPassword)->length, + (const void *)((kcBlob*)mPassword)->data, + (KCItemRef *)&aItem); + + AddItem(aItem); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kcaddinternetpasswordwithpath +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_kcaddinternetpasswordwithpath::COp_kcaddinternetpasswordwithpath() + :mServerName("ServerName"), + mSecurityDomain("SecurityDomain"), + mAccountName("AccountName"), + mPath("Path"), + mPort("Port"), + mProtocol("Protocol"), + mAuthType("AuthType"), + mPassword("Password") +{ + AddParam(mServerName); + AddParam(mSecurityDomain); + AddParam(mAccountName); + AddParam(mPath); + AddParam(mPort); + AddParam(mProtocol); + AddParam(mAuthType); + AddParam(mPassword); + + AddResult(mItemIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_kcaddinternetpasswordwithpath::Operate() +{ + KCItemRef aItem = NULL; + mStatus = ::kcaddinternetpasswordwithpath( + (const char *)((StringPtr)mServerName+1), + (const char *)((StringPtr)mSecurityDomain+1), + (const char *)((StringPtr)mAccountName+1), + (const char *)((StringPtr)mPath+1), + (UInt16)mPort, + (OSType)mProtocol, + (OSType)mAuthType, + (UInt32)((kcBlob*)mPassword)->length, + (const void *)((kcBlob*)mPassword)->data, + (KCItemRef *)&aItem); + + AddItem(aItem); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kcfindinternetpassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_kcfindinternetpassword::COp_kcfindinternetpassword() + :mServerName("ServerName"), + mSecurityDomain("SecurityDomain"), + mAccountName("AccountName"), + mPort("Port"), + mProtocol("Protocol"), + mAuthType("AuthType"), + mPassword("Password"), + mActualLength("ActualLength") +{ + AddParam(mServerName); + AddParam(mSecurityDomain); + AddParam(mAccountName); + AddParam(mPort); + AddParam(mProtocol); + AddParam(mAuthType); + AddParam(mPassword); + + AddResult(mPassword); + AddResult(mActualLength); + AddResult(mItemIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_kcfindinternetpassword::Operate() +{ + KCItemRef aItem = NULL; + mStatus = ::kcfindinternetpassword( + (const char *)((StringPtr)mServerName+1), + (const char *)((StringPtr)mSecurityDomain+1), + (const char *)((StringPtr)mAccountName+1), + (UInt16)mPort, + (OSType)mProtocol, + (OSType)mAuthType, + (UInt32)((kcBlob*)mPassword)->length, + (void *)((kcBlob*)mPassword)->data, + (UInt32*)mActualLength, + (KCItemRef*)&aItem); + AddItem(aItem); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kcfindinternetpasswordwithpath +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_kcfindinternetpasswordwithpath::COp_kcfindinternetpasswordwithpath() + :mServerName("ServerName"), + mSecurityDomain("SecurityDomain"), + mAccountName("AccountName"), + mPath("Path"), + mPort("Port"), + mProtocol("Protocol"), + mAuthType("AuthType"), + mPassword("Password"), + mActualLength("ActualLength") +{ + AddParam(mServerName); + AddParam(mSecurityDomain); + AddParam(mAccountName); + AddParam(mPath); + AddParam(mPort); + AddParam(mProtocol); + AddParam(mAuthType); + AddParam(mPassword); + + AddResult(mPassword); + AddResult(mActualLength); + AddResult(mItemIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_kcfindinternetpasswordwithpath::Operate() +{ + KCItemRef aItem = NULL; + mStatus = ::kcfindinternetpasswordwithpath( + (const char *)((StringPtr)mServerName+1), + (const char *)((StringPtr)mSecurityDomain+1), + (const char *)((StringPtr)mAccountName+1), + (const char *)((StringPtr)mPath+1), + (UInt16)mPort, + (OSType)mProtocol, + (OSType)mAuthType, + (UInt32)((kcBlob*)mPassword)->length, + (void *)((kcBlob*)mPassword)->data, + (UInt32*)mActualLength, + (KCItemRef*)&aItem); + AddItem(aItem); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kcaddgenericpassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_kcaddgenericpassword::COp_kcaddgenericpassword() + :mServiceName("ServiceName"), + mAccountName("AccountName"), + mPassword("Password") +{ + AddParam(mServiceName); + AddParam(mAccountName); + AddParam(mPassword); + + AddResult(mItemIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_kcaddgenericpassword::Operate() +{ + KCItemRef aItem = NULL; + mStatus = ::kcaddgenericpassword( + (const char *)((StringPtr)mServiceName+1), + (const char *)((StringPtr)mAccountName+1), + (UInt32)((kcBlob*)mPassword)->length, + (const void *)((kcBlob*)mPassword)->data, + (KCItemRef*)&aItem); + AddItem(aItem); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kcfindgenericpassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_kcfindgenericpassword::COp_kcfindgenericpassword() + :mServiceName("ServiceName"), + mAccountName("AccountName"), + mPassword("Password"), + mActualLength("ActualLength") +{ + AddParam(mServiceName); + AddParam(mAccountName); + AddParam(mPassword); + + AddResult(mPassword); + AddResult(mActualLength); + AddResult(mItemIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_kcfindgenericpassword::Operate() +{ + KCItemRef aItem = NULL; + mStatus = ::kcfindgenericpassword( + (const char *)((StringPtr)mServiceName+1), + (const char *)((StringPtr)mAccountName+1), + (UInt32)((kcBlob*)mPassword)->length, + (void *)((kcBlob*)mPassword)->data, + (UInt32*)mActualLength, + (KCItemRef*)&aItem); + AddItem(aItem); + return(mStatus); +} diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_CString.h b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_CString.h new file mode 100644 index 00000000..47342f5a --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_CString.h @@ -0,0 +1,213 @@ +// ====================================================================== +// File: KCAPI_CString.h +// +// Operation classes for KC Manager APIs that use "C" strings +// - kcunlock +// - kccreatekeychain +// - kcgetkeychainname +// - kcaddapplesharepassword +// - kcfindapplesharepassword +// - kcaddinternetpassword +// - kcaddinternetpasswordwithpath +// - kcfindinternetpassword +// - kcfindinternetpasswordwithpath +// - kcaddgenericpassword +// - kcfindgenericpassword +// +// +// Copyright: Copyright (c) 2000,2003 Apple Computer, Inc. All Rights Reserved. +// +// Change History (most recent first): +// +// <1> 3/1/00 em Created. +// ====================================================================== +#ifndef __KCAPI_CSTRING__ +#define __KCAPI_CSTRING__ +#include "KCOperation.h" +#include "KCOperationID.h" +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kcunlock +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_kcunlock : public KCOperation +{ +public: +OPERATION_ID(kcunlock) + COp_kcunlock(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mPassword; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kccreatekeychain +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_kccreatekeychain : public KCOperation +{ +public: +OPERATION_ID(kccreatekeychain) + COp_kccreatekeychain(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mPassword; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kcgetkeychainname +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_kcgetkeychainname : public KCOperation +{ +public: +OPERATION_ID(kcgetkeychainname) + COp_kcgetkeychainname(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mKeychainName; +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kcaddapplesharepassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_kcaddapplesharepassword : public KCItemOperation +{ +public: +OPERATION_ID(kcaddapplesharepassword) + COp_kcaddapplesharepassword(); + virtual OSStatus Operate(); +protected: + CParamAFPServerSignature mServerSignature; + CParamStringPtr mServerAddress; + CParamStringPtr mServerName; + CParamStringPtr mVolumeName; + CParamStringPtr mAccountName; + CParamkcBlob mPassword; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kcfindapplesharepassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_kcfindapplesharepassword : public KCItemOperation +{ +public: +OPERATION_ID(kcfindapplesharepassword) + COp_kcfindapplesharepassword(); + virtual OSStatus Operate(); +protected: + CParamAFPServerSignature mServerSignature; + CParamStringPtr mServerAddress; + CParamStringPtr mServerName; + CParamStringPtr mVolumeName; + CParamStringPtr mAccountName; + CParamkcBlob mPassword; + CParamUInt32 mActualLength; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kcaddinternetpassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_kcaddinternetpassword : public KCItemOperation +{ +public: +OPERATION_ID(kcaddinternetpassword) + COp_kcaddinternetpassword(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mServerName; + CParamStringPtr mSecurityDomain; + CParamStringPtr mAccountName; + CParamUInt16 mPort; + CParamOSType mProtocol; + CParamOSType mAuthType; + CParamkcBlob mPassword; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kcaddinternetpasswordwithpath +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_kcaddinternetpasswordwithpath : public KCItemOperation +{ +public: +OPERATION_ID(kcaddinternetpasswordwithpath) + COp_kcaddinternetpasswordwithpath(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mServerName; + CParamStringPtr mSecurityDomain; + CParamStringPtr mAccountName; + CParamStringPtr mPath; + CParamUInt16 mPort; + CParamOSType mProtocol; + CParamOSType mAuthType; + CParamkcBlob mPassword; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kcfindinternetpassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_kcfindinternetpassword : public KCItemOperation +{ +public: +OPERATION_ID(kcfindinternetpassword) + COp_kcfindinternetpassword(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mServerName; + CParamStringPtr mSecurityDomain; + CParamStringPtr mAccountName; + CParamUInt16 mPort; + CParamOSType mProtocol; + CParamOSType mAuthType; + CParamkcBlob mPassword; + CParamUInt32 mActualLength; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kcfindinternetpasswordwithpath +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_kcfindinternetpasswordwithpath : public KCItemOperation +{ +public: +OPERATION_ID(kcfindinternetpasswordwithpath) + COp_kcfindinternetpasswordwithpath(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mServerName; + CParamStringPtr mSecurityDomain; + CParamStringPtr mAccountName; + CParamStringPtr mPath; + CParamUInt16 mPort; + CParamOSType mProtocol; + CParamOSType mAuthType; + CParamkcBlob mPassword; + CParamUInt32 mActualLength; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kcaddgenericpassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_kcaddgenericpassword : public KCItemOperation +{ +public: +OPERATION_ID(kcaddgenericpassword) + COp_kcaddgenericpassword(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mServiceName; + CParamStringPtr mAccountName; + CParamkcBlob mPassword; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_kcfindgenericpassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_kcfindgenericpassword : public KCItemOperation +{ +public: +OPERATION_ID(kcfindgenericpassword) + COp_kcfindgenericpassword(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mServiceName; + CParamStringPtr mAccountName; + CParamkcBlob mPassword; + CParamUInt32 mActualLength; +}; +#endif // __KCAPI_CSTRING__ diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Cert.cpp b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Cert.cpp new file mode 100644 index 00000000..b3734566 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Cert.cpp @@ -0,0 +1,88 @@ +// ====================================================================== +// File: KCAPI_Cert.cpp +// +// Operation classes for APIs for working with Certificates +// - KCFindX509Certificates +// - KCChooseCertificate +// +// +// Copyright: Copyright (c) 2000,2003,2008 Apple Inc. All Rights Reserved. +// +// Change History (most recent first): +// +// <1> 3/1/00 em Created. +// ====================================================================== + +#include "KCAPI_Cert.h" +#include "KCParamUtility.h" + +#if TARGET_RT_MAC_MACHO + #include + #include + #include +#else + #include +#endif + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCFindX509Certificates +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCFindX509Certificates::COp_KCFindX509Certificates() +{ +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCFindX509Certificates::Operate() +{ +#if TARGET_RT_MAC_MACHO + throw("KCGetDataNoUI is not implemented"); +#else + KCRef mKeychain = NULL; + CFStringRef mName = NULL; + CFStringRef mEmailAddress = NULL; + KCCertSearchOptions mOptions; + CFMutableArrayRef mCertificateItems; + + mStatus = ::KCFindX509Certificates( + (KCRef)mKeychain, + (CFStringRef)mName, + (CFStringRef)mEmailAddress, + (KCCertSearchOptions)mOptions, + (CFMutableArrayRef *)&mCertificateItems); +#endif + return(mStatus); +} + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCChooseCertificate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCChooseCertificate::COp_KCChooseCertificate() +{ +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCChooseCertificate::Operate() +{ +/* + CFArrayRef mItems = NULL; + KCItemRef mCertificate = NULL; + CFArrayRef mPolicyOIDs = NULL; + KCVerifyStopOn mStopOn; + + mStatus = ::KCChooseCertificate( + (CFArrayRef)mItems, + (KCItemRef *)&mCertificate, + (CFArrayRef)mPolicyOIDs, + (KCVerifyStopOn)mStopOn); +*/ +printf("WARNING : ChooseCertificate cannot be linked\n"); + return(mStatus); +} diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Cert.h b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Cert.h new file mode 100644 index 00000000..12937f5e --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Cert.h @@ -0,0 +1,51 @@ +// ====================================================================== +// File: KCAPI_Cert.h +// +// Operation classes for APIs for working with Certificates +// - KCFindX509Certificates +// - KCChooseCertificate +// +// +// Copyright: Copyright (c) 2000,2003 Apple Computer, Inc. All Rights Reserved. +// +// Change History (most recent first): +// +// <1> 3/1/00 em Created. +// ====================================================================== + +#ifndef __KCAPI_CERT__ +#define __KCAPI_CERT__ + +#include "KCOperation.h" +#include "KCOperationID.h" + + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCFindX509Certificates +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCFindX509Certificates : public KCOperation +{ +public: +OPERATION_ID(KCFindX509Certificates) + + COp_KCFindX509Certificates(); + virtual OSStatus Operate(); + +protected: +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCChooseCertificate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCChooseCertificate : public KCOperation +{ +public: +OPERATION_ID(KCChooseCertificate) + + COp_KCChooseCertificate(); + virtual OSStatus Operate(); + +protected: +}; + +#endif // __KCAPI_CERT__ diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Item.cpp b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Item.cpp new file mode 100644 index 00000000..1c94dc3a --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Item.cpp @@ -0,0 +1,512 @@ +// ====================================================================== +// File: KCAPI_Item.cpp +// +// Operation classes for APIs to manage KC items +// - KCNewItem +// - KCSetAttribute +// - KCGetAttribute +// - KCSetData +// - KCGetData +// - KCGetDataNoUI +// - KCAddItem +// - KCAddItemNoUI +// - KCDeleteItem +// - KCDeleteItemNoUI +// - KCUpdateItem +// - KCReleaseItem +// - KCCopyItem +// +// Operation classes for APIs for searching and enumertating KC items +// - KCFindFirstItem +// - KCFindNextItem +// - KCReleaseSearch +// +// +// Copyright: Copyright (c) 2000,2003 Apple Computer, Inc. All Rights Reserved. +// +// Change History (most recent first): +// +// <1> 3/1/00 em Created. +// ====================================================================== + + +#include "KCAPI_Item.h" +#include "KCParamUtility.h" + +#if TARGET_RT_MAC_MACHO + #include + #include + #include +#else + #include +#endif + + + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCNewItem +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCNewItem::COp_KCNewItem() + :mItemClass("Class"), + mItemCreator("Creator"), + mData("Data") +{ + AddParam(mItemClass); + AddParam(mItemCreator); + AddParam(mData); + + AddResult(mItemIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCNewItem::Operate() +{ + KCItemRef aKCItemRef = NULL; + mStatus = ::KCNewItem( + (KCItemClass)mItemClass, + (OSType)mItemCreator, + (UInt32)((kcBlob*)mData)->length, + (const void *)((kcBlob*)mData)->data, + (KCItemRef *)&aKCItemRef); + + AddItem(aKCItemRef); + return(mStatus); +} + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCSetAttribute +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCSetAttribute::COp_KCSetAttribute() + :mAttribute("Attribute") +{ + AddParam(mItemIndex); + AddParam(mAttribute); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCSetAttribute::Operate() +{ + mStatus = ::KCSetAttribute( + (KCItemRef)GetItem(), + (KCAttribute *)mAttribute); + return(mStatus); +} + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCGetAttribute +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCGetAttribute::COp_KCGetAttribute() + :mAttribute("Attribute"), + mActualLength("ActualLength") +{ + AddParam(mItemIndex); + AddParam(mAttribute); + + AddResult(mAttribute); + AddResult(mActualLength); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCGetAttribute::Operate() +{ + mStatus = ::KCGetAttribute( + (KCItemRef)GetItem(), + (KCAttribute *)mAttribute, + (UInt32 *)mActualLength); + return(mStatus); +} + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCSetData +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCSetData::COp_KCSetData() + :mData("Data") +{ + AddParam(mItemIndex); + AddParam(mData); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCSetData::Operate() +{ + mStatus = ::KCSetData( + (KCItemRef)GetItem(), + (UInt32)((kcBlob*)mData)->length, + (const void *)((kcBlob*)mData)->data); + return(mStatus); +} + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCGetData +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCGetData::COp_KCGetData() + :mData("Data"), + mActualLength("ActualLength") +{ + AddParam(mItemIndex); + AddParam(mData); + + AddResult(mData); + AddResult(mActualLength); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCGetData::Operate() +{ + mStatus = ::KCGetData( + (KCItemRef)GetItem(), + (UInt32)((kcBlob*)mData)->length, + (void *)((kcBlob*)mData)->data, + (UInt32 *)mActualLength); + + return(mStatus); +} + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCGetDataNoUI +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +/* +COp_KCGetDataNoUI::COp_KCGetDataNoUI() + :mData("Data"), + mActualLength("ActualLength") +{ + AddParam(mItemIndex); + AddParam(mData); + + AddResult(mData); + AddResult(mActualLength); +} +*/ +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +/* +OSStatus +COp_KCGetDataNoUI::Operate() +{ +//#if TARGET_RT_MAC_MACHO + mStatus = ::KCGetDataNoUI((KCItemRef)GetItem(), + (UInt32)((kcBlob*)mData)->length, + (void *)((kcBlob*)mData)->data, + (UInt32 *)mActualLength); +//#else +// throw("KCGetDataNoUI is not implemented"); +//#endif + return(mStatus); +} +*/ +/* +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Callback1 +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCGetDataNoUI::Callback1( + KCItemRef *outItemRef, + UInt32 *outMaxLength, + void **outData, + UInt32 **outActualLength, + void *inContext) +{ + COp_KCGetDataNoUI *thisObject = static_cast(inContext); + if(thisObject == NULL) return -1; + + *outItemRef = thisObject->GetItem(); + *outMaxLength = thisObject->GetMaxLength(); + *outData = thisObject->GetDataPtr(); + *outActualLength = thisObject->GetActualLengthPtr(); + return(noErr); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ CallBack2 +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCGetDataNoUI::Callback2( + void *inContext) +{ + return noErr; +} +*/ + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCAddItem +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCAddItem::COp_KCAddItem() +{ + AddParam(mItemIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCAddItem::Operate() +{ + mStatus = ::KCAddItem((KCItemRef)GetItem()); + return(mStatus); +} + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCAddItemNoUI +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCAddItemNoUI::COp_KCAddItemNoUI() +{ + AddParam(mItemIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCAddItemNoUI::Operate() +{ +#if TARGET_RT_MAC_MACHO + KCRef keychainRef=NULL; //%%% add test for non-default keychain + mStatus = ::KCAddItemNoUI(keychainRef,GetItem()); +#else + throw("COp_KCAddItemNoUI is not implemented"); +#endif + return(mStatus); +} + +/* +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCAddItemNoUI +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCAddItemNoUI::Callback( + KCItemRef *outItem, + void *inContext) +{ + COp_KCAddItemNoUI *thisObject = static_cast(inContext); + if(thisObject == NULL) return -1; + + *outItem = thisObject->GetItem(); + return noErr; +} +*/ + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCDeleteItem +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCDeleteItem::COp_KCDeleteItem() +{ + AddParam(mItemIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCDeleteItem::Operate() +{ + mStatus = ::KCDeleteItem(GetItem()); + return(mStatus); +} + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCDeleteItemNoUI +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCDeleteItemNoUI::COp_KCDeleteItemNoUI() +{ + AddParam(mItemIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCDeleteItemNoUI::Operate() +{ +#if TARGET_RT_MAC_MACHO +//%%%couldn't link? +// mStatus = ::KCDeleteItemNoUI( +// (KCDeleteItemNoUIProcPtr)COp_KCDeleteItemNoUI::CallBack, +// (void*)this); + throw("KCDeleteItemNoUI is not implemented"); +#else + throw("KCDeleteItemNoUI is not implemented"); +#endif + return(mStatus); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ CallBack +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCDeleteItemNoUI::CallBack( + KCItemRef *outItem, + void *inContext) +{ + COp_KCAddItemNoUI *thisObject = static_cast(inContext); + if(thisObject == NULL) return -1; + + *outItem = thisObject->GetItem(); + return noErr; +} + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCUpdateItem +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCUpdateItem::COp_KCUpdateItem() +{ + AddParam(mItemIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCUpdateItem::Operate() +{ + mStatus = ::KCUpdateItem((KCItemRef)GetItem()); + return(mStatus); +} + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCReleaseItem +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCReleaseItem::COp_KCReleaseItem() +{ + AddParam(mItemIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCReleaseItem::Operate() +{ + KCItemRef aItem = GetItem(); + mStatus = ::KCReleaseItem(&aItem); + return(mStatus); +} + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCCopyItem +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCCopyItem::COp_KCCopyItem() +{ + AddParam(mKeychainIndex); + AddParam(mItemIndex); + AddResult(mItemIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCCopyItem::Operate() +{ + KCItemRef aItem = NULL; + mStatus = ::KCCopyItem( + GetItem(), + GetKeychain(), + &aItem); + AddItem(aItem); + return(mStatus); +} + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCFindFirstItem +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCFindFirstItem::COp_KCFindFirstItem() + :mAttrList("AttributeList") +{ + AddParam(mKeychainIndex); + AddParam(mAttrList); + AddResult(mSearchIndex); + AddResult(mItemIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCFindFirstItem::Operate() +{ + KCSearchRef aSearch = NULL; + KCItemRef aItem = NULL; + mStatus = ::KCFindFirstItem( + GetKeychain(), + (const KCAttributeList *)mAttrList, + &aSearch, + &aItem); + + AddSearch(aSearch); + AddItem(aItem); + return(mStatus); +} + + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCFindNextItem +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCFindNextItem::COp_KCFindNextItem() +{ + AddParam(mSearchIndex); + AddResult(mItemIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCFindNextItem::Operate() +{ + KCItemRef aItem = NULL; + mStatus = ::KCFindNextItem( + GetSearch(), + &aItem); + AddItem(aItem); + return(mStatus); +} + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCReleaseSearch +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCReleaseSearch::COp_KCReleaseSearch() +{ + AddParam(mSearchIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCReleaseSearch::Operate() +{ + KCSearchRef aSearch = GetSearch(); + mStatus = ::KCReleaseSearch(&aSearch); + return(mStatus); +} diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Item.h b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Item.h new file mode 100644 index 00000000..946f2b39 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Item.h @@ -0,0 +1,298 @@ +// ====================================================================== +// File: KCAPI_Item.h +// +// Operation classes for APIs to manage KC items +// - KCNewItem +// - KCSetAttribute +// - KCGetAttribute +// - KCSetData +// - KCGetData +// - KCGetDataNoUI +// - KCAddItem +// - KCAddItemNoUI +// - KCDeleteItem +// - KCDeleteItemNoUI +// - KCUpdateItem +// - KCReleaseItem +// - KCCopyItem +// +// Operation classes for APIs for searching and enumertating KC items +// - KCFindFirstItem +// - KCFindNextItem +// - KCReleaseSearch +// +// Copyright: Copyright (c) 2000,2003 Apple Computer, Inc. All Rights Reserved. +// +// Change History (most recent first): +// +// <1> 3/1/00 em Created. +// ====================================================================== + +#ifndef __KCAPI_ITEM__ +#define __KCAPI_ITEM__ + +#include "KCOperation.h" +#include "KCOperationID.h" + + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCNewItem +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCNewItem : public KCItemOperation +{ +public: +OPERATION_ID(KCNewItem) + + COp_KCNewItem(); + virtual OSStatus Operate(); + +protected: + CParamKCItemClass mItemClass; + CParamOSType mItemCreator; + CParamkcBlob mData; + +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCSetAttribute +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCSetAttribute : public KCItemOperation +{ +public: +OPERATION_ID(KCSetAttribute) + + COp_KCSetAttribute(); + virtual OSStatus Operate(); + +protected: + CParamKCAttribute mAttribute; +}; + + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCGetAttribute +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCGetAttribute : public KCItemOperation +{ +public: +OPERATION_ID(KCGetAttribute) + + COp_KCGetAttribute(); + virtual OSStatus Operate(); + +protected: + CParamKCAttribute mAttribute; + CParamUInt32 mActualLength; +}; + + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCSetData +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCSetData : public KCItemOperation +{ +public: +OPERATION_ID(KCSetData) + + COp_KCSetData(); + virtual OSStatus Operate(); + +protected: + CParamkcBlob mData; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCGetData +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCGetData : public KCItemOperation +{ +public: +OPERATION_ID(KCGetData) + + COp_KCGetData(); + virtual OSStatus Operate(); + +protected: + CParamkcBlob mData; + CParamUInt32 mActualLength; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCGetDataNoUI +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +/* +class COp_KCGetDataNoUI : public KCItemOperation +{ +public: +OPERATION_ID(KCGetDataNoUI) + + COp_KCGetDataNoUI(); + virtual OSStatus Operate(); + +protected: + CParamkcBlob mData; + CParamUInt32 mActualLength; + +*/ +/* static OSStatus Callback1( + KCItemRef *outItemRef, + UInt32 *outMaxLength, + void **outData, + UInt32 **outActualLength, + void *inContext); + + static OSStatus Callback2( + void *inContext); +*/ +//}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCAddItem +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCAddItem : public KCItemOperation +{ +public: +OPERATION_ID(KCAddItem) + + COp_KCAddItem(); + virtual OSStatus Operate(); + +protected: +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCAddItemNoUI +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCAddItemNoUI : public KCItemOperation +{ +public: +OPERATION_ID(KCAddItemNoUI) + + COp_KCAddItemNoUI(); + virtual OSStatus Operate(); + +protected: + static OSStatus Callback( + KCItemRef *outItem, + void *inContext); +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCDeleteItem +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCDeleteItem : public KCItemOperation +{ +public: +OPERATION_ID(KCDeleteItem) + + COp_KCDeleteItem(); + virtual OSStatus Operate(); + +protected: +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCDeleteItemNoUI +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCDeleteItemNoUI : public KCItemOperation +{ +public: +OPERATION_ID(KCDeleteItemNoUI) + + COp_KCDeleteItemNoUI(); + virtual OSStatus Operate(); + +protected: + static OSStatus CallBack( + KCItemRef *outItem, + void *inContext); +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCUpdateItem +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCUpdateItem : public KCItemOperation +{ +public: +OPERATION_ID(KCUpdateItem) + + COp_KCUpdateItem(); + virtual OSStatus Operate(); + +protected: +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCReleaseItem +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCReleaseItem : public KCItemOperation +{ +public: +OPERATION_ID(KCReleaseItem) + + COp_KCReleaseItem(); + virtual OSStatus Operate(); + +protected: +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCCopyItem +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCCopyItem : public KCItemOperation +{ +public: +OPERATION_ID(KCCopyItem) + + COp_KCCopyItem(); + virtual OSStatus Operate(); + +protected: +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCFindFirstItem +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCFindFirstItem : public KCSearchOperation +{ +public: +OPERATION_ID(KCFindFirstItem) + + COp_KCFindFirstItem(); + virtual OSStatus Operate(); + +protected: + CParamKCAttributeList mAttrList; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCFindNextItem +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCFindNextItem : public KCSearchOperation +{ +public: +OPERATION_ID(KCFindNextItem) + + COp_KCFindNextItem(); + virtual OSStatus Operate(); + +protected: +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCReleaseSearch +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCReleaseSearch : public KCSearchOperation +{ +public: +OPERATION_ID(KCReleaseSearch) + + COp_KCReleaseSearch(); + virtual OSStatus Operate(); + +protected: +}; + +#endif // __KCAPI_ITEM__ + + diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Keychain.cpp b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Keychain.cpp new file mode 100644 index 00000000..725d62bf --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Keychain.cpp @@ -0,0 +1,784 @@ +// ====================================================================== +// File: KCAPI_Keychain.cpp +// +// Operation classes for core KC APIs: +// - KCMakeKCRefFromFSRef +// - KCMakeKCRefFromFSSpec +// - KCMakeKCRefFromAlias +// - KCMakeAliasFromKCRef +// - KCReleaseKeychain +// - KCUnlockNoUI +// - KCUnlock +// - KCUnlockWithInfo +// - KCLock +// - KCLockNoUI +// - KCGetDefaultKeychain +// - KCSetDefaultKeychain +// - KCCreateKeychain +// - KCCreateKeychainNoUI +// - KCGetStatus +// - KCChangeSettingsNoUI +// - KCGetKeychain +// - KCGetKeychainName +// - KCChangeSettings +// - KCCountKeychains +// - KCGetIndKeychain +// - KCAddCallback +// - KCRemoveCallback +// - KCSetInteractionAllowed +// - KCIsInteractionAllowed +// +// Copyright: Copyright (c) 2000,2003 Apple Computer, Inc. All Rights Reserved. +// +// Change History (most recent first): +// +// <1> 2/25/00 em Created. +// ====================================================================== +#include "KCAPI_Keychain.h" + +#if TARGET_RT_MAC_MACHO + #include +#endif + +#include +#undef check +UInt32 COp_KCAddCallback::sCounter[] = {0,0,0,0,0,0,0,0,0,0,0}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCMakeKCRefFromFSRef +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCMakeKCRefFromFSRef::COp_KCMakeKCRefFromFSRef() + :mFSRef("FSRef") +{ + AddParam(mFSRef); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCMakeKCRefFromFSRef::Operate() +{ + throw("KCMakeKCRefFromFSRef is not implemented"); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCMakeKCRefFromFSSpec +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCMakeKCRefFromFSSpec::COp_KCMakeKCRefFromFSSpec() + :mKeychainFile("KeychainFile") +{ + AddParam(mKeychainFile); + AddResult(mKeychainIndex); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCMakeKCRefFromFSSpec::Operate() +{ + KCRef aKeychain = NULL; + + mStatus = ::KCMakeKCRefFromFSSpec( + (FSSpec*)mKeychainFile, + &aKeychain); + + AddKeychain(aKeychain); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCMakeKCRefFromAlias +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCMakeKCRefFromAlias::COp_KCMakeKCRefFromAlias() +{ + AddParam(mAliasIndex); + AddResult(mKeychainIndex); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCMakeKCRefFromAlias::Operate() +{ + KCRef aKeychain = NULL; + AliasHandle alias = GetAlias(); + + mStatus = ::KCMakeKCRefFromAlias(alias, &aKeychain); + AddKeychain(aKeychain); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCMakeAliasFromKCRef +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCMakeAliasFromKCRef::COp_KCMakeAliasFromKCRef() +{ + AddParam(mKeychainIndex); + AddResult(mAliasIndex); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCMakeAliasFromKCRef::Operate() +{ + AliasHandle alias = GetAlias(); + mStatus = ::KCMakeAliasFromKCRef(GetKeychain(), (AliasHandle*)&alias); + AddAlias(alias); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCReleaseKeychain +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCReleaseKeychain::COp_KCReleaseKeychain() +{ + AddParam(mKeychainIndex); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCReleaseKeychain::Operate() +{ + KCRef aKeychain = GetKeychain(); + mStatus = ::KCReleaseKeychain(&aKeychain); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCLogout +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCLogout::COp_KCLogout() +{ +} + +OSStatus +COp_KCLogout::Operate() +{ + mStatus = ::KCLogout(); + + return(mStatus); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCLogin +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCLogin::COp_KCLogin() + :mName("Name"), + mPassword("Password") +{ + AddParam(mName); + AddParam(mPassword); +} + +OSStatus +COp_KCLogin::Operate() +{ + mStatus = ::KCLogin( (StringPtr)mName, (StringPtr)mPassword ); + + return(mStatus); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCChangeLoginPassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCChangeLoginPassword::COp_KCChangeLoginPassword() + :mOldPassword("OldPassword"), + mNewPassword("NewPassword") +{ + AddParam(mOldPassword); + AddParam(mNewPassword); +} + +OSStatus +COp_KCChangeLoginPassword::Operate() +{ + mStatus = ::KCChangeLoginPassword( (StringPtr)mOldPassword, (StringPtr)mNewPassword ); + + return(mStatus); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCUnlockNoUI +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCUnlockNoUI::COp_KCUnlockNoUI() + :mPassword("Password") +{ + AddParam(mKeychainIndex); + AddParam(mPassword); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCUnlockNoUI::Operate() +{ +//#if TARGET_RT_MAC_MACHO +//%%%¥¥¥¥¥¥¥ + KCRef aKeychain = GetKeychain(); + mStatus = ::KCUnlockNoUI( aKeychain, (StringPtr)mPassword); +// throw("KCUnlockNoUI not implemented"); +//#else +// throw("KCUnlockNoUI not implemented"); +//#endif + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCUnlock +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCUnlock::COp_KCUnlock() + :mPassword("Password") +{ + AddParam(mKeychainIndex); + AddParam(mPassword); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCUnlock::Operate() +{ + mStatus = ::KCUnlock(GetKeychain(), (StringPtr)mPassword); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCUnlockWithInfo +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCUnlockWithInfo::COp_KCUnlockWithInfo() + :mPassword("Password"), mMessage("Mesage") +{ + AddParam(mKeychainIndex); + AddParam(mPassword); + AddParam(mMessage); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCUnlockWithInfo::Operate() +{ +#if 0 //TARGET_RT_MAC_MACHO + mStatus = ::KCUnlockWithInfo(GetKeychain(), (StringPtr)mPassword, (StringPtr)mMessage); +#else + return unimpErr; + //throw("KCUnlockWithInfo is not implemented"); +#endif + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCLock +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCLock::COp_KCLock() +{ + AddParam(mKeychainIndex); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCLock::Operate() +{ + mStatus = ::KCLock(GetKeychain()); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCLockNoUI +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +/* +COp_KCLockNoUI::COp_KCLockNoUI() +{ + AddParam(mKeychainIndex); +} +*/ +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +/* +OSStatus +COp_KCLockNoUI::Operate() +{ +#if TARGET_RT_MAC_MACHO + mStatus = ::KCLockNoUI(GetKeychain()); +#else + throw("KCLockNoUI not implemented"); +#endif + return(mStatus); +} +#pragma mark - +*/ +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCGetDefaultKeychain +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCGetDefaultKeychain::COp_KCGetDefaultKeychain() +{ + AddResult(mKeychainIndex); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCGetDefaultKeychain::Operate() +{ + KCRef aKeychain = NULL; + mStatus = ::KCGetDefaultKeychain(&aKeychain); + AddKeychain(aKeychain); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCSetDefaultKeychain +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCSetDefaultKeychain::COp_KCSetDefaultKeychain() +{ + AddParam(mKeychainIndex); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCSetDefaultKeychain::Operate() +{ + mStatus = ::KCSetDefaultKeychain(GetKeychain()); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCCreateKeychain +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCCreateKeychain::COp_KCCreateKeychain() + :mPassword("Password") +{ + AddParam(mKeychainIndex); + AddParam(mPassword); + AddResult(mKeychainIndex); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCCreateKeychain::Operate() +{ + KCRef aKeychain = GetKeychain(); + mStatus = ::KCCreateKeychain((StringPtr)mPassword, &aKeychain); + AddKeychain(aKeychain); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCCreateKeychainNoUI +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCCreateKeychainNoUI::COp_KCCreateKeychainNoUI() + : mPassword("Password") +{ + AddParam(mKeychainIndex); + AddParam(mPassword); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCCreateKeychainNoUI::Operate() +{ +//#if TARGET_RT_MAC_MACHO + + KCRef aKeychain = GetKeychain(); + + mStatus = ::KCCreateKeychainNoUI(aKeychain, (StringPtr)mPassword); +//#else +// throw("KCCreateKeychainNoUI not implemented"); +//#endif + return(mStatus); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Callback +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCCreateKeychainNoUI::Callback( + KCRef *outKeychain, + StringPtr *outPassword, + void *inContext) +{ +/* COp_KCCreateKeychainNoUI *thisObject = static_cast(inContext); + if(thisObject == NULL) return -1; + +// FSSpec *aFileSpec = thisObject->GetKeychainFile(); + KCRef *aKeychain = thisObject->GetKeychainInCallback(); + StringPtr aPassword = thisObject->GetPassword(); + // OSStatus aStatus = ::KCMakeKCRefFromFSSpec(aFileSpec, aKeychain); + if(aStatus == noErr){ + *outKeychain = *aKeychain; + *outPassword = aPassword; + } + else{ + *outKeychain = NULL; + *outPassword = NULL; + } + + return aStatus; +*/ +return noErr; +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCGetStatus +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCGetStatus::COp_KCGetStatus() + :mKeychainStatus("KeychainStatus") +{ + AddParam(mKeychainIndex); + AddResult(mKeychainStatus); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCGetStatus::Operate() +{ + mStatus = ::KCGetStatus( + GetKeychain(), + (UInt32*)mKeychainStatus); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCChangeSettingsNoUI +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCChangeSettingsNoUI::COp_KCChangeSettingsNoUI() + :mLockOnSleep("LockOnSleep"), + mUseKCGetDataSound("UseKCGetDataSound"), + mUseKCGetDataAlert("UseKCGetDataAlert"), + mUseLockInterval("UseLockInterval"), + mLockInterval("LockInterval"), + mNewPassword("NewPassword"), + mOldPassword("OldPassword") +{ + AddParam(mLockOnSleep); + AddParam(mUseKCGetDataSound); + AddParam(mUseKCGetDataAlert); + AddParam(mUseLockInterval); + AddParam(mLockInterval); + AddParam(mNewPassword); + AddParam(mOldPassword); + AddParam(mKeychainIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCChangeSettingsNoUI::Operate() +{ +#if TARGET_RT_MAC_MACHO + + mChangeSettingsInfo.lockOnSleep = (Boolean)mLockOnSleep; +// mChangeSettingsInfo.useKCGetDataSound = (Boolean)mUseKCGetDataSound; +// mChangeSettingsInfo.useKCGetDataAlert = (Boolean)mUseKCGetDataAlert; + mChangeSettingsInfo.useLockInterval = (Boolean)mUseLockInterval; + mChangeSettingsInfo.lockInterval = (UInt32)mLockInterval; +// mChangeSettingsInfo.newPassword = (StringPtr)mNewPassword; +// mChangeSettingsInfo.oldPassword = (StringPtr)mOldPassword; + mChangeSettingsInfo.keychain = GetKeychain(); + +// mStatus = ::KCChangeSettingsNoUI( +// COp_KCChangeSettingsNoUI::Callback, +// this); + throw("KCChangeSettingsNoUI not implemented"); +#else + throw("KCChangeSettingsNoUI not implemented"); +#endif + return(mStatus); +} + +#if TARGET_RT_MAC_MACHO +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Callback +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCChangeSettingsNoUI::Callback( + KCChangeSettingsInfo * outSettings, + void * inContext) +{ + COp_KCChangeSettingsNoUI *thisObject = static_cast(inContext); + if(thisObject == NULL) return -1; + + // #2462430 - this should be : + // *outSettings = thisObject->GetSettingsInfoPtr(); + // where KCChangeSettingsInfo **outSettings + // + outSettings = thisObject->GetChangeSettingsInfoPtr(); + return noErr; +} +#endif + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCGetKeychain +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCGetKeychain::COp_KCGetKeychain() +{ + AddParam(mItemIndex); + AddResult(mKeychainIndex); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCGetKeychain::Operate() +{ + KCRef aKeychain; + mStatus = ::KCGetKeychain( + GetItem(), + &aKeychain); + AddKeychain(aKeychain); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCGetKeychainName +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCGetKeychainName::COp_KCGetKeychainName() + :mKeychainName("KeychainName") +{ + AddParam(mKeychainIndex); + AddResult(mKeychainName); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCGetKeychainName::Operate() +{ + mStatus = ::KCGetKeychainName( + GetKeychain(), + (StringPtr)mKeychainName); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCChangeSettings +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCChangeSettings::COp_KCChangeSettings() +{ + AddParam(mKeychainIndex); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCChangeSettings::Operate() +{ + mStatus = ::KCChangeSettings(GetKeychain()); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCCountKeychains +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCCountKeychains::COp_KCCountKeychains() + :mCount("Count") +{ + AddResult(mCount); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCCountKeychains::Operate() +{ + mStatus = noErr; + mCount = ::KCCountKeychains(); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCGetIndKeychain +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCGetIndKeychain::COp_KCGetIndKeychain() + :mIndex("Index") +{ + AddParam(mIndex); + AddResult(mKeychainIndex); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCGetIndKeychain::Operate() +{ + KCRef aKeychain = NULL; + mStatus = ::KCGetIndKeychain(mIndex, &aKeychain); + AddKeychain(aKeychain); + return(mStatus); +} +#pragma mark - +KCCallbackUPP COp_KCAddCallback::sCallbacks[] = + { NewKCCallbackUPP(COp_KCAddCallback::Callback0), + NewKCCallbackUPP(COp_KCAddCallback::Callback1), + NewKCCallbackUPP(COp_KCAddCallback::Callback2), + NewKCCallbackUPP(COp_KCAddCallback::Callback3), + NewKCCallbackUPP(COp_KCAddCallback::Callback4), + NewKCCallbackUPP(COp_KCAddCallback::Callback5), + NewKCCallbackUPP(COp_KCAddCallback::Callback6), + NewKCCallbackUPP(COp_KCAddCallback::Callback7), + NewKCCallbackUPP(COp_KCAddCallback::Callback8), + NewKCCallbackUPP(COp_KCAddCallback::Callback9), + NewKCCallbackUPP(COp_KCAddCallback::Callback10) }; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCAddCallback +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCAddCallback::COp_KCAddCallback() + :mEvent("KCEvent") +{ + AddParam(mEvent); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCAddCallback::Operate() +{ + mStatus = ::KCAddCallback( + COp_KCAddCallback::sCallbacks[mEvent], + (KCEventMask)(1 << (KCEvent)mEvent), + (void *)this); + return(mStatus); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +#define KCADDCALLBACK(N) \ +OSStatus \ +COp_KCAddCallback::Callback ## N( \ + KCEvent inKeychainEvent, \ + KCCallbackInfo *inInfo, \ + void *inContext) \ +{ \ + COp_KCAddCallback::sCounter[inKeychainEvent]++; \ + return noErr; \ +} + +KCADDCALLBACK(0) +KCADDCALLBACK(1) +KCADDCALLBACK(2) +KCADDCALLBACK(3) +KCADDCALLBACK(4) +KCADDCALLBACK(5) +KCADDCALLBACK(6) +KCADDCALLBACK(7) +KCADDCALLBACK(8) +KCADDCALLBACK(9) +KCADDCALLBACK(10) + +#undef KCADDCALLBACK + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCRemoveCallback +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCRemoveCallback::COp_KCRemoveCallback() + :mEvent("KCEvent"), + mIdleCount("IdleCount"), + mLockCount("LockCount"), + mUnlockCount("UnlockCount"), + mAddCount("AddCount"), + mDeleteCount("DeleteCount"), + mUpdateCount("UpdateCount"), + mChangeIdentityCount("ChangeIdentityCount"), + mFindCount("FindCount"), + mSystemCount("SystemCount"), + mDefaultChangedCount("DefaultChangedCount"), + mDataAccessCount("DataAccessCount") +{ + AddParam(mEvent); + + AddResult(mIdleCount); + AddResult(mLockCount); + AddResult(mUnlockCount); + AddResult(mAddCount); + AddResult(mDeleteCount); + AddResult(mUpdateCount); + AddResult(mChangeIdentityCount); + AddResult(mFindCount); + AddResult(mSystemCount); + AddResult(mDefaultChangedCount); + AddResult(mDataAccessCount); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCRemoveCallback::Operate() +{ + // Receive a few events so we make sure we get all pending notifications (callbacks) + EventRecord er; + for (int ix = 0; ix < 142; ix++) + GetNextEvent(0, &er); + + mStatus = ::KCRemoveCallback( + COp_KCAddCallback::sCallbacks[mEvent]); + + // Copy the current results + UInt16 i = 0; + tParamList::iterator aIterator = mResultList.begin(); + CParamUInt32 * aParam = static_cast(*aIterator); + while(aIterator != mResultList.end()){ + if(aParam){ + *aParam = COp_KCAddCallback::sCounter[i]; + i++; + } + aParam = static_cast(*(++aIterator)); + } + + // reset the counter + COp_KCAddCallback::sCounter[mEvent] = 0; + + return(mStatus); +} + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCSetInteractionAllowed +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCSetInteractionAllowed::COp_KCSetInteractionAllowed() + :mAllow("AllowInteraction") +{ + AddParam(mAllow); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCSetInteractionAllowed::Operate() +{ + mStatus = ::KCSetInteractionAllowed(mAllow); + return(mStatus); +} + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCIsInteractionAllowed +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCIsInteractionAllowed::COp_KCIsInteractionAllowed() + :mAllow("AllowInteraction") +{ + AddResult(mAllow); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCIsInteractionAllowed::Operate() +{ + mStatus = noErr; + mAllow = ::KCIsInteractionAllowed(); + return(mStatus); +} diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Keychain.h b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Keychain.h new file mode 100644 index 00000000..d9b99570 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Keychain.h @@ -0,0 +1,463 @@ +// ====================================================================== +// File: KCAPI_Keychain.h +// +// Operation classes for core KC APIs: +// - KCMakeKCRefFromFSRef +// - KCMakeKCRefFromFSSpec +// - KCMakeKCRefFromAlias +// - KCMakeAliasFromKCRef +// - KCReleaseKeychain +// - KCUnlockNoUI +// - KCUnlock +// - KCLogin +// - KCChangeLoginPassword +// - KCLogout +// - KCUnlockWithInfo +// - KCLock +// - KCLockNoUI +// - KCGetDefaultKeychain +// - KCSetDefaultKeychain +// - KCCreateKeychain +// - KCCreateKeychainNoUI +// - KCGetStatus +// - KCChangeSettingsNoUI +// - KCGetKeychain +// - KCGetKeychainName +// - KCChangeSettings +// - KCCountKeychains +// - KCGetIndKeychain +// - KCAddCallback +// - KCRemoveCallback +// - KCSetInteractionAllowed +// - KCIsInteractionAllowed +// +// Copyright: Copyright (c) 2000,2003 Apple Computer, Inc. All Rights Reserved. +// +// Change History (most recent first): +// +// <1> 2/25/00 em Created. +// ====================================================================== +#ifndef __KCAPI_KEYCHAIN__ +#define __KCAPI_KEYCHAIN__ +#include "KCOperation.h" +#include "KCOperationID.h" +#include "KCParamUtility.h" + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCMakeKCRefFromFSRef +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCMakeKCRefFromFSRef : public KCOperation +{ +public: +OPERATION_ID(KCMakeKCRefFromFSRef) + COp_KCMakeKCRefFromFSRef(); + virtual OSStatus Operate(); + +protected: + CParamFSRef mFSRef; +private: + OSStatus KCMakeKCRefFromFSRef( + FSRef *inKeychainFSRef, + KCRef *outKeychain) + { + *outKeychain = (KCRef)NULL; + return noErr; + } +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCMakeKCRefFromFSSpec +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCMakeKCRefFromFSSpec : public KCOperation +{ +public: +OPERATION_ID(KCMakeKCRefFromFSSpec) + COp_KCMakeKCRefFromFSSpec(); + virtual OSStatus Operate(); +protected: + CParamFSSpec mKeychainFile; +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCMakeKCRefFromAlias +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCMakeKCRefFromAlias : public KCOperation +{ +public: +OPERATION_ID(KCMakeKCRefFromAlias) + COp_KCMakeKCRefFromAlias(); + virtual OSStatus Operate(); +protected: +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCMakeAliasFromKCRef +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCMakeAliasFromKCRef : public KCOperation +{ +public: +OPERATION_ID(KCMakeAliasFromKCRef) + + COp_KCMakeAliasFromKCRef(); + virtual OSStatus Operate(); +protected: +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCReleaseKeychain +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCReleaseKeychain : public KCOperation +{ +public: +OPERATION_ID(KCReleaseKeychain) + + COp_KCReleaseKeychain(); + virtual OSStatus Operate(); +protected: +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCUnlockNoUI +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCUnlockNoUI : public KCOperation +{ +public: +OPERATION_ID(KCUnlockNoUI) + + COp_KCUnlockNoUI(); + virtual OSStatus Operate(); + virtual StringPtr GetPassword(){ return (StringPtr)mPassword; } +protected: + CParamStringPtr mPassword; +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCUnlock +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCUnlock : public KCOperation +{ +public: +OPERATION_ID(KCUnlock) + + COp_KCUnlock(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mPassword; +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCChangeLoginPassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCChangeLoginPassword : public KCOperation +{ +public: +OPERATION_ID(KCChangeLoginPassword) + + COp_KCChangeLoginPassword(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mOldPassword; + CParamStringPtr mNewPassword; +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCLogin +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCLogin : public KCOperation +{ +public: +OPERATION_ID(KCLogin) + + COp_KCLogin(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mName; + CParamStringPtr mPassword; +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCLogout +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCLogout : public KCOperation +{ +public: +OPERATION_ID(KCLogout) + + COp_KCLogout(); + virtual OSStatus Operate(); +protected: +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCUnlockWithInfo +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCUnlockWithInfo : public KCOperation +{ +public: +OPERATION_ID(KCUnlockWithInfo) + COp_KCUnlockWithInfo(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mPassword; + CParamStringPtr mMessage; +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCLock +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCLock : public KCOperation +{ +public: +OPERATION_ID(KCLock) + COp_KCLock(); + virtual OSStatus Operate(); +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCLockNoUI +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +/* +class COp_KCLockNoUI : public KCOperation +{ +public: +OPERATION_ID(KCLockNoUI) + COp_KCLockNoUI(); + virtual OSStatus Operate(); +protected: +}; +*/ +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCGetDefaultKeychain +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCGetDefaultKeychain : public KCOperation +{ +public: +OPERATION_ID(KCGetDefaultKeychain) + COp_KCGetDefaultKeychain(); + virtual OSStatus Operate(); +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCSetDefaultKeychain +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCSetDefaultKeychain : public KCOperation +{ +public: +OPERATION_ID(KCSetDefaultKeychain) + COp_KCSetDefaultKeychain(); + virtual OSStatus Operate(); +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCCreateKeychain +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCCreateKeychain : public KCOperation +{ +public: +OPERATION_ID(KCCreateKeychain) + COp_KCCreateKeychain(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mPassword; +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCCreateKeychainNoUI +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCCreateKeychainNoUI : public KCOperation +{ +public: +OPERATION_ID(KCCreateKeychainNoUI) + COp_KCCreateKeychainNoUI(); + virtual OSStatus Operate(); + + virtual StringPtr GetPassword(){ return (StringPtr)mPassword; } + virtual KCRef * GetKeychainInCallback(){ return &mKeychainInCallback; } +protected: + CParamStringPtr mPassword; + KCRef mKeychainInCallback; + static OSStatus Callback( + KCRef *outKeychain, + StringPtr *outPassword, + void *inContext); +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCGetStatus +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCGetStatus : public KCOperation +{ +public: +OPERATION_ID(KCGetStatus) + COp_KCGetStatus(); + virtual OSStatus Operate(); +protected: + CParamUInt32 mKeychainStatus; +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCChangeSettingsNoUI +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCChangeSettingsNoUI : public KCOperation +{ +public: +OPERATION_ID(KCChangeSettingsNoUI) + COp_KCChangeSettingsNoUI(); + virtual OSStatus Operate(); + +#if TARGET_RT_MAC_MACHO + virtual KCChangeSettingsInfo + *GetChangeSettingsInfoPtr(){ return &mChangeSettingsInfo; } +#endif + +protected: +#if TARGET_RT_MAC_MACHO + static OSStatus Callback( + KCChangeSettingsInfo *outSettings, + void *inContext); +#endif + + CParamBoolean mLockOnSleep; + CParamBoolean mUseKCGetDataSound; + CParamBoolean mUseKCGetDataAlert; + CParamBoolean mUseLockInterval; + CParamUInt32 mLockInterval; + CParamStringPtr mNewPassword; + CParamStringPtr mOldPassword; + +#if TARGET_RT_MAC_MACHO + KCChangeSettingsInfo mChangeSettingsInfo; +#endif +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCGetKeychain +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCGetKeychain : public KCItemOperation +{ +public: +OPERATION_ID(KCGetKeychain) + COp_KCGetKeychain(); + virtual OSStatus Operate(); +protected: +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCGetKeychainName +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCGetKeychainName : public KCOperation +{ +public: +OPERATION_ID(KCGetKeychainName) + COp_KCGetKeychainName(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mKeychainName; +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCChangeSettings +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCChangeSettings : public KCOperation +{ +public: +OPERATION_ID(KCChangeSettings) + COp_KCChangeSettings(); + virtual OSStatus Operate(); +protected: +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCCountKeychains +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCCountKeychains : public KCOperation +{ +public: +OPERATION_ID(KCCountKeychains) + COp_KCCountKeychains(); + virtual OSStatus Operate(); + +protected: + CParamUInt16 mCount; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCGetIndKeychain +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCGetIndKeychain : public KCOperation +{ +public: +OPERATION_ID(KCGetIndKeychain) + COp_KCGetIndKeychain(); + virtual OSStatus Operate(); + +protected: + CParamUInt16 mIndex; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCAddCallback +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCAddCallback : public KCOperation +{ +public: +OPERATION_ID(KCAddCallback) + COp_KCAddCallback(); + virtual OSStatus Operate(); + +protected: + CParamUInt16 mEvent; + static UInt32 sCounter[11]; + static KCCallbackUPP sCallbacks[11]; + +#define KCADDCALLBACK_DEF(N) \ + static OSStatus Callback ## N( \ + KCEvent inKeychainEvent, \ + KCCallbackInfo *inInfo, \ + void *inContext) + + KCADDCALLBACK_DEF(0); + KCADDCALLBACK_DEF(1); + KCADDCALLBACK_DEF(2); + KCADDCALLBACK_DEF(3); + KCADDCALLBACK_DEF(4); + KCADDCALLBACK_DEF(5); + KCADDCALLBACK_DEF(6); + KCADDCALLBACK_DEF(7); + KCADDCALLBACK_DEF(8); + KCADDCALLBACK_DEF(9); + KCADDCALLBACK_DEF(10); +#undef KCADDCALLBACK_DEF + + + friend class COp_KCRemoveCallback; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCRemoveCallback +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCRemoveCallback : public KCOperation +{ +public: +OPERATION_ID(KCRemoveCallback) + COp_KCRemoveCallback(); + virtual OSStatus Operate(); +protected: + CParamUInt16 mEvent; + CParamUInt32 mIdleCount; + CParamUInt32 mLockCount; + CParamUInt32 mUnlockCount; + CParamUInt32 mAddCount; + CParamUInt32 mDeleteCount; + CParamUInt32 mUpdateCount; + CParamUInt32 mChangeIdentityCount; + CParamUInt32 mFindCount; + CParamUInt32 mSystemCount; + CParamUInt32 mDefaultChangedCount; + CParamUInt32 mDataAccessCount; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCSetInteractionAllowed +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCSetInteractionAllowed : public KCOperation +{ +public: +OPERATION_ID(KCSetInteractionAllowed) + COp_KCSetInteractionAllowed(); + virtual OSStatus Operate(); +protected: + CParamBoolean mAllow; +}; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCIsInteractionAllowed +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCIsInteractionAllowed : public KCOperation +{ +public: +OPERATION_ID(KCIsInteractionAllowed) + COp_KCIsInteractionAllowed(); + virtual OSStatus Operate(); +protected: + CParamBoolean mAllow; +}; +#endif // __KCAPI_KEYCHAIN__ diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Manager.cpp b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Manager.cpp new file mode 100644 index 00000000..01764630 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Manager.cpp @@ -0,0 +1,64 @@ +// ====================================================================== +// File: KCAPI_Manager.cpp +// +// Operation classes for KC manager APIs: +// - KCGetKeychainManagerVersion +// - KeychainManagerAvailable +// +// +// Copyright: Copyright (c) 2000,2003 Apple Computer, Inc. All Rights Reserved. +// +// Change History (most recent first): +// +// <1> 2/22/00 em Created. +// ====================================================================== + +#include "KCAPI_Manager.h" +#include "KCParamUtility.h" + +#if TARGET_RT_MAC_MACHO + #include + #include + #include +#else + #include +#endif + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCGetKeychainManagerVersion +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCGetKeychainManagerVersion::COp_KCGetKeychainManagerVersion() + :mVersion("Version") +{ + AddResult(mVersion); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCGetKeychainManagerVersion::Operate() +{ + mStatus = ::KCGetKeychainManagerVersion((UInt32*)mVersion); + return(mStatus); +} + +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KeychainManagerAvailable +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KeychainManagerAvailable::COp_KeychainManagerAvailable() + :mAvailable("Available") +{ + AddResult(mAvailable); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KeychainManagerAvailable::Operate() +{ + mAvailable = ::KeychainManagerAvailable(); + return(noErr); +} diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Manager.h b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Manager.h new file mode 100644 index 00000000..277c72e0 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Manager.h @@ -0,0 +1,52 @@ +// ====================================================================== +// File: KCAPI_Manager.h +// +// Operation classes for KC manager APIs: +// - KCGetKeychainManagerVersion +// - KeychainManagerAvailable +// +// +// Copyright: Copyright (c) 2000,2003 Apple Computer, Inc. All Rights Reserved. +// +// Change History (most recent first): +// +// <1> 2/22/00 em Created. +// ====================================================================== + +#ifndef __KCAPI_MANAGER__ +#define __KCAPI_MANAGER__ + +#include "KCOperation.h" +#include "KCOperationID.h" + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCGetKeychainManagerVersion +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCGetKeychainManagerVersion : public KCOperation +{ +public: +OPERATION_ID(KCGetKeychainManagerVersion) + + COp_KCGetKeychainManagerVersion(); + virtual OSStatus Operate(); + +protected: + CParamUInt32 mVersion; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KeychainManagerAvailable +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KeychainManagerAvailable : public KCOperation +{ +public: +OPERATION_ID(KeychainManagerAvailable) + + COp_KeychainManagerAvailable(); + virtual OSStatus Operate(); + +protected: + CParamBoolean mAvailable; +}; + +#endif // __KCAPI_MANAGER__ diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Password.cpp b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Password.cpp new file mode 100644 index 00000000..e38935f6 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Password.cpp @@ -0,0 +1,372 @@ +// ====================================================================== +// File: KCAPI_Password.cpp +// +// Operation classes for APIs to store and retriev passwords +// - KCAddAppleSharePassword +// - KCFindAppleSharePassword +// - KCAddInternetPassword +// - KCAddInternetPasswordWithPath +// - KCFindInternetPassword +// - KCFindInternetPasswordWithPath +// - KCAddGenericPassword +// - KCFindGenericPassword +// +// +// Copyright: Copyright (c) 2000,2003,2006 Apple Computer, Inc. All Rights Reserved. +// +// Change History (most recent first): +// +// <1> 3/1/00 em Created. +// ====================================================================== +#include "KCAPI_Password.h" +#include "KCParamUtility.h" + +#if TARGET_RT_MAC_MACHO + #include + #include + #include +#else + #include +#endif + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCAddAppleSharePassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCAddAppleSharePassword::COp_KCAddAppleSharePassword() + :mServerSignature("ServerSignature"), + mServerAddress("ServerAddress"), + mServerName("ServerName"), + mVolumeName("VolumeName"), + mAccountName("AccountName"), + mPassword("Password") +{ + AddParam(mServerSignature); + AddParam(mServerAddress); + AddParam(mServerName); + AddParam(mVolumeName); + AddParam(mAccountName); + AddParam(mPassword); + + AddResult(mItemIndex); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCAddAppleSharePassword::Operate() +{ + // ¥¥¥ store fully-specified AFPXVolMountInfo + // record as the password data + + KCItemRef aItem = NULL; + mStatus = ::KCAddAppleSharePassword( + &static_cast(mServerSignature).data, + (StringPtr)mServerAddress, + (StringPtr)mServerName, + (StringPtr)mVolumeName, + (StringPtr)mAccountName, + (UInt32)((kcBlob*)mPassword)->length, + (const void *)((kcBlob*)mPassword)->data, + (KCItemRef*)&aItem); + AddItem(aItem); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCFindAppleSharePassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCFindAppleSharePassword::COp_KCFindAppleSharePassword() + :mServerSignature("ServerSignature"), + mServerAddress("ServerAddress"), + mServerName("ServerName"), + mVolumeName("VolumeName"), + mAccountName("AccountName"), + mPassword("Password"), + mActualLength("ActualLength") +{ + AddParam(mServerSignature); + AddParam(mServerAddress); + AddParam(mServerName); + AddParam(mVolumeName); + AddParam(mAccountName); + AddParam(mPassword); + + AddResult(mPassword); + AddResult(mActualLength); + AddResult(mItemIndex); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCFindAppleSharePassword::Operate() +{ + KCItemRef aItem = NULL; + mStatus = ::KCFindAppleSharePassword( + &static_cast(mServerSignature).data, + (StringPtr)mServerAddress, + (StringPtr)mServerName, + (StringPtr)mVolumeName, + (StringPtr)mAccountName, + (UInt32)((kcBlob*)mPassword)->length, + (void *)((kcBlob*)mPassword)->data, + (UInt32*)mActualLength, + (KCItemRef *)&aItem); + AddItem(aItem); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCAddInternetPassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCAddInternetPassword::COp_KCAddInternetPassword() + :mServerName("ServerName"), + mSecurityDomain("SecurityDomain"), + mAccountName("AccountName"), + mPort("Port"), + mProtocol("Protocol"), + mAuthType("AuthType"), + mPassword("Password") +{ + AddParam(mServerName); + AddParam(mSecurityDomain); + AddParam(mAccountName); + AddParam(mPort); + AddParam(mProtocol); + AddParam(mAuthType); + AddParam(mPassword); + + AddResult(mItemIndex); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCAddInternetPassword::Operate() +{ + KCItemRef aItem = NULL; + mStatus = ::KCAddInternetPassword( + (StringPtr)mServerName, + (StringPtr)mSecurityDomain, + (StringPtr)mAccountName, + (UInt16)mPort, + (OSType)mProtocol, + (OSType)mAuthType, + (UInt32)((kcBlob*)mPassword)->length, + (const void *)((kcBlob*)mPassword)->data, + (KCItemRef *)&aItem); + AddItem(aItem); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCAddInternetPasswordWithPath +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCAddInternetPasswordWithPath::COp_KCAddInternetPasswordWithPath() + :mServerName("ServerName"), + mSecurityDomain("SecurityDomain"), + mAccountName("AccountName"), + mPath("Path"), + mPort("Port"), + mProtocol("Protocol"), + mAuthType("AuthType"), + mPassword("Password") +{ + AddParam(mServerName); + AddParam(mSecurityDomain); + AddParam(mAccountName); + AddParam(mPath); + AddParam(mPort); + AddParam(mProtocol); + AddParam(mAuthType); + AddParam(mPassword); + + AddResult(mItemIndex); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCAddInternetPasswordWithPath::Operate() +{ + KCItemRef aItem = NULL; + mStatus = ::KCAddInternetPasswordWithPath( + (StringPtr)mServerName, + (StringPtr)mSecurityDomain, + (StringPtr)mAccountName, + (StringPtr)mPath, + (UInt16)mPort, + (OSType)mProtocol, + (OSType)mAuthType, + (UInt32)((kcBlob*)mPassword)->length, + (const void *)((kcBlob*)mPassword)->data, + (KCItemRef *)&aItem); + AddItem(aItem); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCFindInternetPassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCFindInternetPassword::COp_KCFindInternetPassword() + :mServerName("ServerName"), + mSecurityDomain("SecurityDomain"), + mAccountName("AccountName"), + mPort("Port"), + mProtocol("Protocol"), + mAuthType("AuthType"), + mPassword("Password"), + mActualLength("ActualLength") +{ + AddParam(mServerName); + AddParam(mSecurityDomain); + AddParam(mAccountName); + AddParam(mPort); + AddParam(mProtocol); + AddParam(mAuthType); + AddParam(mPassword); + + AddResult(mPassword); + AddResult(mActualLength); + AddResult(mItemIndex); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCFindInternetPassword::Operate() +{ + KCItemRef aItem = NULL; + mStatus = ::KCFindInternetPassword( + (StringPtr)mServerName, + (StringPtr)mSecurityDomain, + (StringPtr)mAccountName, + (UInt16)mPort, + (OSType)mProtocol, + (OSType)mAuthType, + (UInt32)((kcBlob*)mPassword)->length, + (void *)((kcBlob*)mPassword)->data, + (UInt32*)mActualLength, + (KCItemRef*)&aItem); + AddItem(aItem); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCFindInternetPasswordWithPath +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCFindInternetPasswordWithPath::COp_KCFindInternetPasswordWithPath() + :mServerName("ServerName"), + mSecurityDomain("SecurityDomain"), + mAccountName("AccountName"), + mPath("Path"), + mPort("Port"), + mProtocol("Protocol"), + mAuthType("AuthType"), + mPassword("Password"), + mActualLength("ActualLength") +{ + AddParam(mServerName); + AddParam(mSecurityDomain); + AddParam(mAccountName); + AddParam(mPath); + AddParam(mPort); + AddParam(mProtocol); + AddParam(mAuthType); + AddParam(mPassword); + + AddResult(mPassword); + AddResult(mActualLength); + AddResult(mItemIndex); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCFindInternetPasswordWithPath::Operate() +{ + KCItemRef aItem = NULL; + mStatus = ::KCFindInternetPasswordWithPath( + (StringPtr)mServerName, + (StringPtr)mSecurityDomain, + (StringPtr)mAccountName, + (StringPtr)mPath, + (UInt16)mPort, + (OSType)mProtocol, + (OSType)mAuthType, + (UInt32)((kcBlob*)mPassword)->length, + (void *)((kcBlob*)mPassword)->data, + (UInt32*)mActualLength, + (KCItemRef*)&aItem); + AddItem(aItem); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCAddGenericPassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCAddGenericPassword::COp_KCAddGenericPassword() + :mServiceName("ServiceName"), + mAccountName("AccountName"), + mPassword("Password") +{ + AddParam(mServiceName); + AddParam(mAccountName); + AddParam(mPassword); + + AddResult(mItemIndex); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCAddGenericPassword::Operate() +{ + KCItemRef aItem = NULL; + mStatus = ::KCAddGenericPassword( + (StringPtr)mServiceName, + (StringPtr)mAccountName, + (UInt32)((kcBlob*)mPassword)->length, + (const void *)((kcBlob*)mPassword)->data, + (KCItemRef*)&aItem); + + AddItem(aItem); + return(mStatus); +} +#pragma mark - +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCFindGenericPassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +COp_KCFindGenericPassword::COp_KCFindGenericPassword() + :mServiceName("ServiceName"), + mAccountName("AccountName"), + mPassword("Password"), + mActualLength("ActualLength") +{ + AddParam(mServiceName); + AddParam(mAccountName); + AddParam(mPassword); + + AddResult(mPassword); + AddResult(mActualLength); + AddResult(mItemIndex); +} +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operate +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +OSStatus +COp_KCFindGenericPassword::Operate() +{ + KCItemRef aItem = NULL; + mStatus = ::KCFindGenericPassword( + (StringPtr)mServiceName, + (StringPtr)mAccountName, + (UInt32)((kcBlob*)mPassword)->length, + (void *)((kcBlob*)mPassword)->data, + (UInt32*)mActualLength, + (KCItemRef*)&aItem); + + AddItem(aItem); + return(mStatus); +} diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Password.h b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Password.h new file mode 100644 index 00000000..59955af6 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/KCAPI_Password.h @@ -0,0 +1,176 @@ +// ====================================================================== +// File: KCAPI_Password.h +// +// Operation classes for APIs to store and retriev passwords +// - KCAddAppleSharePassword +// - KCFindAppleSharePassword +// - KCAddInternetPassword +// - KCAddInternetPasswordWithPath +// - KCFindInternetPassword +// - KCFindInternetPasswordWithPath +// - KCAddGenericPassword +// - KCFindGenericPassword +// +// +// Copyright: Copyright (c) 2000,2003 Apple Computer, Inc. All Rights Reserved. +// +// Change History (most recent first): +// +// <1> 3/1/00 em Created. +// ====================================================================== + +#ifndef __KCAPI_PASSWORD__ +#define __KCAPI_PASSWORD__ +#include "KCOperation.h" +#include "KCOperationID.h" + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCAddAppleSharePassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCAddAppleSharePassword : public KCItemOperation +{ +public: +OPERATION_ID(KCAddAppleSharePassword) + COp_KCAddAppleSharePassword(); + virtual OSStatus Operate(); +protected: + CParamAFPServerSignature mServerSignature; + CParamStringPtr mServerAddress; + CParamStringPtr mServerName; + CParamStringPtr mVolumeName; + CParamStringPtr mAccountName; + CParamkcBlob mPassword; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCFindAppleSharePassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCFindAppleSharePassword : public KCItemOperation +{ +public: +OPERATION_ID(KCFindAppleSharePassword) + COp_KCFindAppleSharePassword(); + virtual OSStatus Operate(); + +protected: + CParamAFPServerSignature mServerSignature; + CParamStringPtr mServerAddress; + CParamStringPtr mServerName; + CParamStringPtr mVolumeName; + CParamStringPtr mAccountName; + CParamkcBlob mPassword; + CParamUInt32 mActualLength; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCAddInternetPassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCAddInternetPassword : public KCItemOperation +{ +public: +OPERATION_ID(KCAddInternetPassword) + COp_KCAddInternetPassword(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mServerName; + CParamStringPtr mSecurityDomain; + CParamStringPtr mAccountName; + CParamUInt16 mPort; + CParamOSType mProtocol; + CParamOSType mAuthType; + CParamkcBlob mPassword; + +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCAddInternetPasswordWithPath +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCAddInternetPasswordWithPath : public KCItemOperation +{ +public: +OPERATION_ID(KCAddInternetPasswordWithPath) + COp_KCAddInternetPasswordWithPath(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mServerName; + CParamStringPtr mSecurityDomain; + CParamStringPtr mAccountName; + CParamStringPtr mPath; + CParamUInt16 mPort; + CParamOSType mProtocol; + CParamOSType mAuthType; + CParamkcBlob mPassword; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCFindInternetPassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCFindInternetPassword : public KCItemOperation +{ +public: +OPERATION_ID(KCFindInternetPassword) + COp_KCFindInternetPassword(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mServerName; + CParamStringPtr mSecurityDomain; + CParamStringPtr mAccountName; + CParamUInt16 mPort; + CParamOSType mProtocol; + CParamOSType mAuthType; + CParamkcBlob mPassword; + CParamUInt32 mActualLength; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCFindInternetPasswordWithPath +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCFindInternetPasswordWithPath : public KCItemOperation +{ +public: +OPERATION_ID(KCFindInternetPasswordWithPath) + COp_KCFindInternetPasswordWithPath(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mServerName; + CParamStringPtr mSecurityDomain; + CParamStringPtr mAccountName; + CParamStringPtr mPath; + CParamUInt16 mPort; + CParamOSType mProtocol; + CParamOSType mAuthType; + CParamkcBlob mPassword; + CParamUInt32 mActualLength; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCAddGenericPassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCAddGenericPassword : public KCItemOperation +{ +public: +OPERATION_ID(KCAddGenericPassword) + COp_KCAddGenericPassword(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mServiceName; + CParamStringPtr mAccountName; + CParamkcBlob mPassword; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COp_KCFindGenericPassword +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COp_KCFindGenericPassword : public KCItemOperation +{ +public: +OPERATION_ID(KCFindGenericPassword) + COp_KCFindGenericPassword(); + virtual OSStatus Operate(); +protected: + CParamStringPtr mServiceName; + CParamStringPtr mAccountName; + CParamkcBlob mPassword; + CParamUInt32 mActualLength; +}; +#endif // __KCAPI_PASSWORD__ diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/KCOperation.cpp b/SecurityTests/testKeychainAPI/testKeychainAPI/KCOperation.cpp new file mode 100644 index 00000000..0f2299e3 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/KCOperation.cpp @@ -0,0 +1,211 @@ +// ====================================================================== +// File: KCOperation.cpp +// +// pure virtual base class for performing operations in KeychainLib +// (based on Dave Akhond's Operation for CDSA +// +// Copyright: Copyright (c) 2000,2003 Apple Computer, Inc. All Rights Reserved. +// +// Change History (most recent first): +// +// <1> 3/28/00 em Created. +// ====================================================================== + +#include "KCOperation.h" + +#include + +vector KCOperation::sKCRefList; +vector KCItemOperation::sKCItemRefList; +vector KCSearchOperation::sKCSearchRefList; +vector KCOperation::sAliasList; + +//vector SecOperation::sSecRefList; +//vector SecOperation::sAliasList; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ SetClient +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +void +Operation::SetClient(void *inClient) +{ + if(inClient == NULL) return; + CTestApp *aTestApp = static_cast(inClient); + if(aTestApp == NULL) return; + mClient = aTestApp; +} + + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ ReadArguments +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +void +Operation::ReadArguments( + FILE *inFile) +{ + + tParamList::iterator aIterator = mParamList.begin(); + CParam * aParam = *aIterator; + + while(aIterator != mParamList.end()){ + + aParam->Read(inFile); + aParam = *(++aIterator); + } +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ WriteArguments +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +void +Operation::WriteArguments( + FILE *inFile) +{ + tParamList::iterator aIterator = mParamList.begin(); + CParam * aParam = *aIterator; + while(aIterator != mParamList.end()){ + aParam->Write(inFile); + aParam = *(++aIterator); + } +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ WriteResults +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +void +Operation::WriteResults( + FILE *inFile) +{ + if (CSSM_BASE_ERROR <= mStatus && mStatus < CSSM_AC_BASE_ERROR + CSSM_ERRORCODE_MODULE_EXTENT) + //fprintf(inFile, " OSStatus CSSMERR_%s (0x%08lx)\n", cssmErrorString(mStatus).c_str(), mStatus); + printf("Error"); + else + fprintf(inFile, " OSStatus %ld\n", mStatus); + + + tParamList::iterator aIterator = mResultList.begin(); + CParam * aParam = *aIterator; + while(aIterator != mResultList.end()){ + aParam->Write(inFile); + aParam = *(++aIterator); + } +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ ReadScript +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +int +Operation::ReadScript( + FILE *inFile, + eKCOperationID &outID) +{ + UInt32 aID; + char aBuffer[1024]; + char aName[256]; + int aResult; + + while(UNIX_fgets(aBuffer, sizeof(aBuffer)-1, inFile)){ + // Read off comment lines + if(aBuffer[0] == '/' && aBuffer[1] == '/') continue; + // instructional comments + if(aBuffer[0] == '#' && aBuffer[0] == '#'){ + for(UInt16 i=0; iIsRelaxErrorChecking()) aResult = false; + if(mClient->IsRelaxErrorChecking() && ((aStatus == noErr) || (mStatus == noErr))) aResult = false; + } + + tParamList::iterator aIterator = mResultList.begin(); + CParam * aParam = *aIterator; + while(aIterator != mResultList.end()){ + if(aParam->Compare(inFile) == false) + aResult = false; + aParam = *(++aIterator); + } + return aResult; +} + diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/KCOperation.h b/SecurityTests/testKeychainAPI/testKeychainAPI/KCOperation.h new file mode 100644 index 00000000..57e7e6d7 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/KCOperation.h @@ -0,0 +1,259 @@ +// ====================================================================== +// File: KCOperation.h +// +// pure virtual base class for performing operations in KeychainLib +// (based on Dave Akhond's Operation for CDSA +// +// Copyright: Copyright (c) 2000,2003,2008 Apple Inc. All Rights Reserved. +// +// Change History (most recent first): +// +// <1> 2/22/00 em Created. +// ====================================================================== + +#ifndef __KC_OPERATION__ +#define __KC_OPERATION__ + +#ifdef _CPP_UTILITIES +#pragma export on +#endif + +#include +#include +#include +#undef check +#if TARGET_RT_MAC_MACHO + #include + #include + #include +#else + #include +#endif + +#include "testKeychainAPI.h" +#include "KCParamUtility.h" +#include "KCOperationID.h" + + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Operation +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class Operation { +public: + // Birth & Death + Operation():mStatus(noErr){} + virtual ~Operation(){} + + virtual void SetClient(void *inClient); + virtual OSStatus Operate() = 0; + virtual eKCOperationID GetID() = 0; + + virtual void ReadArguments( + FILE *inFile); + + virtual void WriteArguments( + FILE *inFile); + + virtual void WriteResults( + FILE *inFile); + + static int ReadScript( + FILE *inFile, + eKCOperationID &outID); + + virtual void ReadScript( + FILE *inFile); + + virtual void WriteScript( + FILE *inFile); + + virtual void GenerateScript( + FILE *inFile); + + virtual bool RunScript( + FILE *inFile); + + virtual bool CompareResults( + FILE *inFile); +protected: + CTestApp *mClient; + OSStatus mStatus; + tParamList mParamList; + tParamList mResultList; + + virtual void AddParam(CParam &inParam){ mParamList.push_back(&inParam);} + virtual void AddResult(CParam &inParam){ mResultList.push_back(&inParam);} + + +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ KCOperation +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class KCOperation : public Operation { +public: + KCOperation():mKeychainIndex("KeychainIndex"), mAliasIndex("AliasIndex") {} + virtual ~KCOperation(){} + + virtual void AddAlias(AliasHandle alias) + { + sAliasList.push_back(alias); + mAliasIndex = (UInt32)(sAliasList.size()-1); + } + + virtual void AddKeychain(KCRef &inKeychain) + { + sKCRefList.push_back(inKeychain); + mKeychainIndex = (UInt32)(sKCRefList.size()-1); + } + + virtual AliasHandle GetAlias() + { + if((UInt32)mAliasIndex < sAliasList.size()) + return sAliasList[(UInt32)mAliasIndex]; + else + return NULL; + } + + virtual KCRef GetKeychain() + { + if((UInt32)mKeychainIndex < sKCRefList.size()) + return sKCRefList[(UInt32)mKeychainIndex]; + else + return NULL; + } + + static void Cleanup() + { + // ¥¥¥ need to release each keychain first + sAliasList.clear(); + sKCRefList.clear(); + } +protected: + class CKeychainIndex : public CUInt32 + { + public: + CKeychainIndex & operator = (const UInt32 &inData){ data = inData; return *this; } + bool operator == (const UInt32 inData) const + { + return (CKCRef(KCOperation::sKCRefList[data]) == KCOperation::sKCRefList[inData]); + } + }; + typedef TParam CParamKeychainIndex; + + class CAliasIndex : public CUInt32 + { + public: + CAliasIndex & operator = (const UInt32 &inData){ data = inData; return *this; } + bool operator == (const UInt32 inData) const + { + return (CAliasHandle(KCOperation::sAliasList[data]) == KCOperation::sAliasList[inData]); + } + }; + typedef TParam CParamAliasIndex; + + CParamKeychainIndex mKeychainIndex; + CParamAliasIndex mAliasIndex; + static vector sKCRefList; + static vector sAliasList; + + friend class CKeychainIndex; + friend class CAliasIndex; +}; + + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ KCItemOperation +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class KCItemOperation : public KCOperation { +public: + KCItemOperation():mItemIndex("ItemIndex"){} + virtual ~KCItemOperation(){} + + virtual void AddItem(KCItemRef &inItem) + { + sKCItemRefList.push_back(inItem); + mItemIndex = (UInt32)(sKCItemRefList.size()-1); + } + + virtual KCItemRef GetItem() + { + if((UInt32)mItemIndex < sKCItemRefList.size()) + return sKCItemRefList[(UInt32)mItemIndex]; + else + return NULL; + } + + static void Cleanup() + { + // ¥¥¥ need to release each item first + sKCItemRefList.clear(); + } +protected: + class CItemIndex : public CUInt32 + { + public: + CItemIndex & operator = (const UInt32 &inData){ data = inData; return *this; } + bool operator == (const UInt32 inData) const + { + return(CKCItemRef(KCItemOperation::sKCItemRefList[data]) == KCItemOperation::sKCItemRefList[inData]); + } + }; + typedef TParam CParamItemIndex; + CParamItemIndex mItemIndex; + + static vector sKCItemRefList; + + friend class CItemIndex; +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ KCSearchOperation +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class KCSearchOperation : public KCItemOperation { +public: + KCSearchOperation():mSearchIndex("SearchIndex"){} + virtual ~KCSearchOperation(){} + + virtual void AddSearch(KCSearchRef &inSearch) + { + sKCSearchRefList.push_back(inSearch); mSearchIndex = (UInt32)(sKCSearchRefList.size()-1); + } + + virtual KCSearchRef GetSearch() + { + if((UInt32)mSearchIndex < sKCSearchRefList.size()) + return sKCSearchRefList[(UInt32)mSearchIndex]; + else + return NULL; + } + + static void Cleanup() + { + // ¥¥¥ need to release each ref first + sKCSearchRefList.clear(); + } +protected: + class CSearchIndex : public CUInt32 + { + public: + CSearchIndex & operator = (const UInt32 &inData){ data = inData; return *this; } + bool operator == (const UInt32 inData) const + { + return (data == inData) || + (KCSearchOperation::sKCSearchRefList[data] == KCSearchOperation::sKCSearchRefList[inData]); + } + }; + typedef TParam CParamSearchIndex; + CParamSearchIndex mSearchIndex; + + static vector sKCSearchRefList; + + friend class CSearchIndex; +}; + +#ifdef _CPP_UTILITIES +#pragma export off +#endif + +#endif // __KC_OPERATION__ diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/KCOperationID.cpp b/SecurityTests/testKeychainAPI/testKeychainAPI/KCOperationID.cpp new file mode 100644 index 00000000..31eee573 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/KCOperationID.cpp @@ -0,0 +1,124 @@ +// ====================================================================== +// File: KCOperationID.cpp +// +// OperationID must be registered so that a test script knows how to +// construct an appropriate KCOperation class +// +// Copyright: Copyright (c) 2000,2003,2008 Apple Inc. All Rights Reserved. +// +// Change History (most recent first): +// +// <1> 2/22/00 em Created. +// ====================================================================== + +//#include "SecAPI_Keychain.h" +#include "KCOperationID.h" +#include "KCAPI_Manager.h" +#include "KCAPI_Keychain.h" +#include "KCAPI_Password.h" +#include "KCAPI_Item.h" +#include "KCAPI_Cert.h" +#include "KCAPI_CString.h" + + + + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Static initialization +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +bool COpRegister::sRegistered = false; +tOperationInfo COpRegister::sOperationInfoTbl[OpID_NumOperations]; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ RegisterAll +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +void +COpRegister::RegisterAll() +{ + if(sRegistered) return; + + // Getting KC manager info + // (KCAPI_Manager) + Register(KCGetKeychainManagerVersion); + Register(KeychainManagerAvailable); + + // High level KC APIs + // (KCAPI_Keychain) +// Register(KCMakeKCRefFromFSRef); + Register(KCMakeKCRefFromFSSpec); + Register(KCMakeKCRefFromAlias); + Register(KCMakeAliasFromKCRef); + Register(KCReleaseKeychain); + Register(KCUnlockNoUI); + Register(KCUnlock); + Register(KCLogin); + Register(KCChangeLoginPassword); + Register(KCLogout); + Register(KCUnlockWithInfo); + Register(KCLock); + //Register(KCLockNoUI); + Register(KCGetDefaultKeychain); + Register(KCSetDefaultKeychain); + Register(KCCreateKeychain); + Register(KCCreateKeychainNoUI); + Register(KCGetStatus); + Register(KCChangeSettingsNoUI); + Register(KCGetKeychain); + Register(KCGetKeychainName); + Register(KCChangeSettings); + Register(KCCountKeychains); + Register(KCGetIndKeychain); + Register(KCAddCallback); + Register(KCRemoveCallback); + Register(KCSetInteractionAllowed); + Register(KCIsInteractionAllowed); + + // Storing and retrieveng passwords + // (KCAPI_Password) + Register(KCAddAppleSharePassword); + Register(KCFindAppleSharePassword); + Register(KCAddInternetPassword); + Register(KCAddInternetPasswordWithPath); + Register(KCFindInternetPassword); + Register(KCFindInternetPasswordWithPath); + Register(KCAddGenericPassword); + Register(KCFindGenericPassword); + + // Managing KC items + // (KCAPI_Item) + Register(KCNewItem); + Register(KCSetAttribute); + Register(KCGetAttribute); + Register(KCSetData); + Register(KCGetData); + //Register(KCGetDataNoUI); + Register(KCAddItem); + Register(KCAddItemNoUI); + Register(KCDeleteItem); + Register(KCDeleteItemNoUI); + Register(KCUpdateItem); + Register(KCReleaseItem); + Register(KCCopyItem); + Register(KCFindFirstItem); + Register(KCFindNextItem); + Register(KCReleaseSearch); + + // Working with Certificates + // (KCAPI_Cert) + Register(KCFindX509Certificates); + Register(KCChooseCertificate); + + // KC Manager calls that use "C" strings + // (KCAPI_CString) + Register(kcunlock); + Register(kccreatekeychain); + Register(kcgetkeychainname); + Register(kcaddapplesharepassword); + Register(kcfindapplesharepassword); + Register(kcaddinternetpassword); + Register(kcaddinternetpasswordwithpath); + Register(kcfindinternetpassword); + Register(kcfindinternetpasswordwithpath); + Register(kcaddgenericpassword); + Register(kcfindgenericpassword); + } diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/KCOperationID.h b/SecurityTests/testKeychainAPI/testKeychainAPI/KCOperationID.h new file mode 100644 index 00000000..4df03951 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/KCOperationID.h @@ -0,0 +1,159 @@ +// ====================================================================== +// File: KCOperationID.h +// +// OperationID must be registered so that a test script knows how to +// construct an appropriate KCOperation class +// +// Copyright: Copyright (c) 2000,2003 Apple Computer, Inc. All Rights Reserved. +// +// Change History (most recent first): +// +// <1> 2/22/00 em Created. +// ====================================================================== +#ifndef __KC_OPERATION_ID__ +#define __KC_OPERATION_ID__ +#include +enum eKCOperationID { + OpID_Unknown = -1, + OpID_COp_KCGetKeychainManagerVersion = 0, + OpID_COp_KeychainManagerAvailable,//1 + OpID_COp_KCMakeKCRefFromFSRef,//2 + OpID_COp_KCMakeKCRefFromFSSpec,//3 + OpID_COp_KCMakeKCRefFromAlias,//4 + OpID_COp_KCMakeAliasFromKCRef,//5 + OpID_COp_KCReleaseKeychain,//6 + OpID_COp_KCUnlockNoUI,//7 + OpID_COp_KCUnlock,//8 + OpID_COp_KCUnlockWithInfo,//9 + OpID_COp_KCLock,//10 + OpID_COp_KCLockNoUI,//11 + OpID_COp_KCGetDefaultKeychain,//12 + OpID_COp_KCSetDefaultKeychain,//13 + OpID_COp_KCCreateKeychain,//14 + OpID_COp_KCCreateKeychainNoUI,//15 + OpID_COp_KCGetStatus,//16 + OpID_COp_KCChangeSettingsNoUI,//17 + OpID_COp_KCGetKeychain,//18 + OpID_COp_KCGetKeychainName,//19 + OpID_COp_KCChangeSettings,//20 + OpID_COp_KCCountKeychains,//21 + OpID_COp_KCGetIndKeychain,//22 + OpID_COp_KCAddCallback,//23 + OpID_COp_KCRemoveCallback,//24 + OpID_COp_KCSetInteractionAllowed,//25 + OpID_COp_KCIsInteractionAllowed,//26 + OpID_COp_KCAddAppleSharePassword,//27 + OpID_COp_KCFindAppleSharePassword,//28 + OpID_COp_KCAddInternetPassword,//29 + OpID_COp_KCAddInternetPasswordWithPath,//30 + OpID_COp_KCFindInternetPassword,//31 + OpID_COp_KCFindInternetPasswordWithPath,//32 + OpID_COp_KCAddGenericPassword,//33 + OpID_COp_KCFindGenericPassword,//34 + OpID_COp_KCNewItem,//35 + OpID_COp_KCSetAttribute,//36 + OpID_COp_KCGetAttribute,//37 + OpID_COp_KCSetData,//38 + OpID_COp_KCGetData,//39 + OpID_COp_KCGetDataNoUI,//40 + OpID_COp_KCAddItem,//41 + OpID_COp_KCAddItemNoUI,//42 + OpID_COp_KCDeleteItem,//43 + OpID_COp_KCDeleteItemNoUI,//44 + OpID_COp_KCUpdateItem,//45 + OpID_COp_KCReleaseItem,//46 + OpID_COp_KCCopyItem,//47 + OpID_COp_KCFindFirstItem,//48 + OpID_COp_KCFindNextItem,//49 + OpID_COp_KCReleaseSearch,//50 + OpID_COp_KCFindX509Certificates,//51 + OpID_COp_KCChooseCertificate,//52 + OpID_COp_kcunlock,//53 + OpID_COp_kccreatekeychain,//54 + OpID_COp_kcgetkeychainname,//55 + OpID_COp_kcaddapplesharepassword,//56 + OpID_COp_kcfindapplesharepassword,//57 + OpID_COp_kcaddinternetpassword,//58 + OpID_COp_kcaddinternetpasswordwithpath,//59 + OpID_COp_kcfindinternetpassword,//60 + OpID_COp_kcfindinternetpasswordwithpath,//61 + OpID_COp_kcaddgenericpassword,//62 + OpID_COp_kcfindgenericpassword,//63 + OpID_COp_KCLogin,//64 + OpID_COp_KCLogout,//65 + OpID_COp_KCChangeLoginPassword,//66 + OpID_NumOperations +}; +#define IS_VALID_OPERATIONID(aID) (aID >= 0 && aID < OpID_NumOperations) + +typedef void * (*tClassCreatorFunc)(void *inClient); +typedef struct tOperationInfo{ + const char * name; + tClassCreatorFunc func; +} tOperationInfo; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ COpRegister +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class COpRegister { +public: + static void * CreateOperation( + eKCOperationID inID, + void *inClient) + { + RegisterAll(); + if(IS_VALID_OPERATIONID(inID)){ + if(sOperationInfoTbl[inID].func) + return (sOperationInfoTbl[inID].func)(inClient); + } + return NULL; + } + + static const char * GetOperationName( + eKCOperationID inID) + { + RegisterAll(); + if(IS_VALID_OPERATIONID(inID)) + return sOperationInfoTbl[inID].name; + else + return "INVALID OPERATION ID"; + } + + static void RegisterAll(); + static void RegisterOne( + eKCOperationID inID, + const char * inName, + tClassCreatorFunc inFunc = NULL) + { + sOperationInfoTbl[inID].name = inName; + sOperationInfoTbl[inID].func = inFunc; + } +protected: + static bool sRegistered; + static tOperationInfo sOperationInfoTbl[OpID_NumOperations]; +}; +template +class TOpRegister{ +public: + static T * Create( + void *inClient) + { + T *aOperation = new T; + if(aOperation) aOperation->SetClient(inClient); + return aOperation; + } + static void RegisterOne( + eKCOperationID inID, + const char * inName) + { + COpRegister::RegisterOne(inID, inName, (tClassCreatorFunc)Create); + } +}; + + // Relax notations so one can avoid typing long names +#define KC_CLASS(funcname) COp_## funcname +#define KC_OP_ID(funcname) OpID_COp_## funcname +#define Register(funcname) TOpRegister::RegisterOne(KC_OP_ID(funcname), (const char*)#funcname "") +#define OPERATION_ID(funcname) enum{ operation_ID = KC_OP_ID(funcname) };\ + eKCOperationID GetID(){ return (eKCOperationID)operation_ID; }; + +#endif // __KC_OPERATION_ID__ diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/KCParamUtility.cpp b/SecurityTests/testKeychainAPI/testKeychainAPI/KCParamUtility.cpp new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/KCParamUtility.cpp @@ -0,0 +1 @@ + diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/KCParamUtility.h b/SecurityTests/testKeychainAPI/testKeychainAPI/KCParamUtility.h new file mode 100644 index 00000000..f842641f --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/KCParamUtility.h @@ -0,0 +1,649 @@ +// ====================================================================== +// File: KCParamUtility.h +// +// Wrapper classes for function parameters +// (using Parry's PodWrapper) +// +// +// Copyright: Copyright (c) 2000,2003,2006 Apple Computer, Inc. All Rights Reserved. +// +// Change History (most recent first): +// +// <1> 2/22/00 em Created. +// ====================================================================== +#ifndef __KC_PARAM_UTILITY_ +#define __KC_PARAM_UTILITY_ + +#if TARGET_RT_MAC_MACHO + #include + #include + #include + //#include +#else + #include +#endif +#include + +#include +#include +#include +#include + +#undef check +//typedef const char* SecStringPtr; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ CParam - base class for TParam template +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class CParam +{ +public: + virtual void Write(FILE *inFile)=0; + virtual void Read(FILE *inFile)=0; + virtual bool Compare(FILE *inFile)=0; +}; +typedef std::list tParamList; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ TParam +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +template +class TParam : public CParam +{ +public: + TParam(const char *inName) + :mName(inName), mResult(true) + { + } + + TParam(const char *inName, T&inData) + :mPod(inData), mName(inName), mResult(true) + { + } + + virtual ~TParam(){} + + bool operator == (const T inData) const { return (mPod == inData); } + Wrapper& operator = (const T inData){ return mPod = inData; } + Wrapper& operator = (const T* inData){ return mPod = inData; } + operator T*(){ return (T*)mPod; } + operator T(){ return (T)mPod; } + + virtual void Write(FILE *inFile) + { + WriteTitle(inFile); + mPod.WriteData(inFile); + } + + virtual void Read(FILE *inFile) + { + ReadTitle(inFile); + mPod.ReadData(inFile); + } + + virtual bool Compare(FILE *inFile) + { + ReadTitle(inFile); + Wrapper aWrapper; + aWrapper.ReadData(inFile); + return (mResult = (mPod == aWrapper)); + } + +protected: + Wrapper mPod; + const char *mName; + bool mResult; + + virtual void WriteTitle(FILE *inFile) + { + if(mResult) + fprintf(inFile, " %s : ", mName); + else + fprintf(inFile, "*** %s : ", mName); + } + + virtual void ReadTitle(FILE *inFile) + { + char aTitle[256]; + fscanf(inFile, "%s : ", aTitle); + if(::strcmp(mName, aTitle) != 0){ + throw(mName); + } + } + +}; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Non-struct POD wrapping macros +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +#define POD_STRUCT(type) type##Struct +#define POD_CLASS(type) CParam##type +#define TYPEDEF_POD_STRUCT(type) typedef struct type##Struct { type data; } type##Struct; +#define TYPEDEF_POD_CLASS(type) typedef TParam CParam##type; +#define TYPEDEF_STRUCTPOD_CLASS(type) typedef TParam CParam##type; +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ UInt32 wrapper +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +TYPEDEF_POD_STRUCT(UInt32) +class CUInt32 : public PodWrapper{ +public: + CUInt32(){ data = 0; }; + CUInt32(const UInt32 &inData){ data = inData; } + + CUInt32 & operator = (const UInt32 &inData){ data = inData; return *this; } + bool operator == (const UInt32 inData) const { return data == inData; } + operator UInt32*(){ return &data; } + operator UInt32(){ return data; } + + virtual void WriteData(FILE *inFile) + { + fprintf(inFile, "%ld\n", data); + } + + virtual void ReadData(FILE *inFile) + { + fscanf(inFile, "%ld\n", &data); + } +}; +TYPEDEF_POD_CLASS(UInt32) + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ UInt16 wrapper +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +TYPEDEF_POD_STRUCT(UInt16) +class CUInt16 : public PodWrapper{ +public: + CUInt16(){ data = 0; }; + CUInt16(const UInt16 &inData){ data = inData; } + + CUInt16 & operator = (const UInt16 &inData){ data = inData; return *this; } + bool operator == (const UInt16 inData) const { return data == inData; } + operator UInt16*(){ return &data; } + operator UInt16(){ return data; } + + virtual void WriteData(FILE *inFile) + { + fprintf(inFile, "%ld\n", (UInt32)data); + } + + virtual void ReadData(FILE *inFile) + { + UInt32 aData; + fscanf(inFile, "%ld\n", &aData); + data = aData; + } +}; +TYPEDEF_POD_CLASS(UInt16) + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Boolean wrapper +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +TYPEDEF_POD_STRUCT(Boolean) +class CBoolean : public PodWrapper{ +public: + CBoolean(){ data = false; } + CBoolean(const Boolean &inData){ data = inData; } + operator Boolean*(){ return &data; } + operator Boolean(){ return data; } + + CBoolean & operator = (const Boolean &inData){ data = inData; return *this; } + bool operator == (const Boolean inData) const { return data == inData; } + + virtual void WriteData(FILE *inFile) + { + fprintf(inFile, "%d\n", data); + } + + virtual void ReadData(FILE *inFile) + { + int aValue; + fscanf(inFile, "%d\n", &aValue); + data = ((aValue == 0) ? false : true); + } + +}; +TYPEDEF_POD_CLASS(Boolean) + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ FourCharCode wrapper +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +TYPEDEF_POD_STRUCT(FourCharCode) +class CFourCharCode : public PodWrapper{ +public: + CFourCharCode(){ data = '????'; } + CFourCharCode(const FourCharCode &inData){ data = inData; } + + CFourCharCode & operator = (const FourCharCode &inData){ data = inData; return *this; } + bool operator == (const FourCharCode inData) const { return data == inData; } + operator FourCharCode*(){ return &data; } + operator FourCharCode(){ return data; } + + virtual void WriteData(FILE *inFile) + { + for(UInt16 i=0; i> ((sizeof(FourCharCode)-i-1) * 8))); + } + fprintf(inFile, "\n"); + } + + virtual void ReadData(FILE *inFile) + { + FourCharCode aValue = 0; + for(UInt16 i=0; i{ +public: + CAliasHandle(){ data = NULL; } + CAliasHandle(const AliasHandle &inData){ data = inData; } + + CAliasHandle & operator = (const AliasHandle &inData){ data = inData; return *this; } + bool operator == (const AliasHandle inData) const { return data == inData; } + operator AliasHandle*(){ return &data; } + operator AliasHandle(){ return data; } + + virtual void WriteData(FILE *inFile) + { + fprintf(inFile, "%s\n", mFullPathName); + } + + virtual void ReadData(FILE *inFile) + { + memset(mFullPathName, 0, sizeof(mFullPathName)); + if(UNIX_fgets(mFullPathName, sizeof(mFullPathName), inFile)){ + // fgets grabs the newline code too + mFullPathName[strlen(mFullPathName)-1] = 0; + } + else throw("Syntax error in CAliasHandle"); + + if(strchr(mFullPathName, ':')){ + // Create a alias from the full-path name + //%%%cpm - this WONT work, Keychain mgr does not fill in the FSSpec + ::NewAliasMinimalFromFullPath( + strlen(mFullPathName), + mFullPathName, + NULL, + NULL, + &data); + } + else{ + // Ask KeychainLib to fill in the FSSpec for us + FSSpec tmpSpec = {0,0}; + tmpSpec.name[0] = ::strlen(mFullPathName); + memcpy(tmpSpec.name+1, mFullPathName, tmpSpec.name[0]); + + KCRef aKeychain; + ::KCMakeKCRefFromFSSpec(&tmpSpec, &aKeychain); + ::KCReleaseKeychain(&aKeychain); + //%%%cpm - this WONT work, Keychain mgr does not fill in the FSSpec + ::NewAliasMinimal( + &tmpSpec, + &data); + } + } +protected: + char mFullPathName[1024]; +}; +TYPEDEF_POD_CLASS(AliasHandle) +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ StringPtr wrapper +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +TYPEDEF_POD_STRUCT(StringPtr) +class CStringPtr : public PodWrapper{ +public: + CStringPtr(){ data = new unsigned char[256]; memset(data, 0, 256); } + CStringPtr(const StringPtr &inData){ memset(data, 0, 256); memcpy(data, inData, inData[0]); } + virtual ~CStringPtr(){ delete data; } + + CStringPtr & operator = (const StringPtr inData){ memset(data, 0, 256); memcpy(data, inData, inData[0]); return *this; } + bool operator == (const StringPtr inData) const { return ((data[0] == inData[0]) && (memcmp(data, inData, data[0]+1) == 0)); } + operator StringPtr*(){ return &data; } + operator StringPtr(){ return data; } + + virtual void WriteData(FILE *inFile) + { + fprintf(inFile, "%s\n", data+1); + } + + virtual void ReadData(FILE *inFile) + { + memset(data, 0, 256); + + char cString[256]; + if(UNIX_fgets(cString, 256, inFile)){ + data[0] = strlen(cString)-1; + memcpy(data+1, cString, data[0]); + } + else + throw("Syntax error in CStringPtr"); + } +}; +TYPEDEF_POD_CLASS(StringPtr) + + +TYPEDEF_POD_STRUCT(AFPServerSignature) +class CAFPServerSignature : public PodWrapper{ +public: + CAFPServerSignature(){ memset(data, 0, sizeof(data)); } + CAFPServerSignature(const AFPServerSignature &inData){ memcpy(data, inData, sizeof(data)); } + + CAFPServerSignature &operator = (const AFPServerSignature inData){ memcpy(data, inData, sizeof(data)); return *this; } + bool operator == (const AFPServerSignature inData) const { return (memcmp(data, inData, sizeof(data)) == 0); } + operator AFPServerSignature*(){ return &data; } + + virtual void WriteData(FILE *inFile) + { + for(UInt16 i=0; i CParamAFPServerSignature; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Blob wrapper +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +typedef struct kcBlob{UInt32 length; void* data; } kcBlob; +class CkcBlob : public PodWrapper{ +public: + CkcBlob(){ length = 0; data = NULL; } + CkcBlob(const kcBlob &inData){ length = 0; data = NULL; DeepCopy(inData.length, inData.data); } + CkcBlob & operator = (const kcBlob &inData){ DeepCopy(inData.length, inData.data); return *this; } + bool operator == (const kcBlob inData) const { return ((inData.length == length) && (memcmp(data, inData.data, length) == 0)); } + operator kcBlob*(){ return this; } + +#if defined(__MWERKS__) + operator kcBlob(){ return *this; } +#endif + + virtual void WriteData(FILE *inFile) + { + fprintf(inFile, "/%ld/", length); + if(length > 0){ + for(UInt32 i=0; i 0) data = (UInt8*)new char[aLength+2]; + length = aLength; + } + if(length > 0){ + UNIX_fgets((char*)data, aLength+3, inFile); + ((UInt8*)data)[length] = 0; + } + else + fscanf(inFile, "\n"); + } +protected: + virtual void DeepCopy(UInt32 inLength, const void *inData) + { + if(data != NULL) delete (UInt8*)data; + data = NULL; + + length = inLength; + if(length == 0) return; + data = (UInt8*)new char[length]; + memcpy(data, inData, length); + } +}; +TYPEDEF_STRUCTPOD_CLASS(kcBlob) + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ FSSpec wrapper +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class CFSSpec : public PodWrapper{ +public: + CFSSpec(){ vRefNum = 0; parID = 0; memset(name, 0, sizeof(name)); mFullPathName[0] = 0;} + CFSSpec(const FSSpec &inData){ memcpy(this, &inData, sizeof(*this)); } + CFSSpec & operator = (const FSSpec &inData){ memcpy(this, &inData, sizeof(*this)); return *this; } + bool operator == (const FSSpec inData) const { return (this == &inData) || !memcmp(this, &inData, sizeof(FSSpec)); } + operator FSSpec*(){ return this ; } + + virtual void WriteData(FILE *inFile) + { + fprintf(inFile, "%s\n", mFullPathName); + } + + virtual void ReadData(FILE *inFile) + { + memset(mFullPathName, 0, sizeof(mFullPathName)); + if(UNIX_fgets(mFullPathName, sizeof(mFullPathName), inFile)){ + // fgets grabs the newline code too + name[0] = strlen(mFullPathName)-1; + mFullPathName[name[0]] = 0; + memcpy(name+1, mFullPathName, name[0]); + } + else throw("Syntax error in CFSSpec"); + } +protected: + char mFullPathName[1024]; +}; +TYPEDEF_STRUCTPOD_CLASS(FSSpec) + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ FSRef wrapper +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class CFSRef : public PodWrapper{ +public: + CFSRef(){ memset(hidden, 0, sizeof(hidden)); } + CFSRef(const FSRef &inData){ memcpy(this, &inData, sizeof(*this)); } + + CFSRef & operator = (const FSRef &inData){ memcpy(this, &inData, sizeof(*this)); return *this; } + bool operator == (const FSRef inData) const { return (this == &inData) || !memcmp(this, &inData, sizeof(FSRef)); } + operator FSRef*(){ return this; } + + virtual void WriteData(FILE *inFile) + { + // ¥¥¥ need work + fprintf(inFile, "\n"); + } + + virtual void ReadData(FILE *inFile) + { + // ¥¥¥ need work + fscanf(inFile, "\n"); + } +}; +TYPEDEF_STRUCTPOD_CLASS(FSRef) + + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ KCAttribute wrapper +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class CKCAttribute : public PodWrapper{ +public: + CKCAttribute(){ tag = '0000'; length = 0; data = NULL; } + CKCAttribute(const KCAttribute &inData){ memcpy(this, &inData, sizeof(*this)); } + + CKCAttribute & operator = (const KCAttribute &inData){ memcpy(this, &inData, sizeof(*this)); return *this; } + bool operator == (const KCAttribute inData) const + { + if(inData.tag != tag) return false; + return(memcmp(inData.data, data, ((inData.length < length) ? inData.length : length)) == 0); + } + + operator KCAttribute*(){ return this; } +#if defined(__MWERKS__) + operator KCAttribute(){ return *this; } +#endif + virtual void WriteData(FILE *inFile) + { + fprintf(inFile, "\n"); + + CParamKCAttrType aTag(".tag", tag); + aTag.Write(inFile); + + kcBlob theBlob = {length, data}; + CParamkcBlob aData(".data", theBlob); + aData.Write(inFile); + } + + virtual void ReadData(FILE *inFile) + { + fscanf(inFile, "\n"); + + CParamKCAttrType aTag(".tag"); + aTag.Read(inFile); + tag = aTag; + + CParamkcBlob aData(".data"); + aData.Read(inFile); + + kcBlob aBlob; + aBlob = aData; + length = aBlob.length; + data = aBlob.data; + } +}; +TYPEDEF_STRUCTPOD_CLASS(KCAttribute) + + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ KCAttributeList wrapper +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +class CKCAttributeList : public PodWrapper{ +public: + CKCAttributeList(){ count = 0; attr = NULL; } + CKCAttributeList(const CKCAttributeList &inData){ memcpy(this, &inData, sizeof(*this)); } + + CKCAttributeList & operator = (const CKCAttributeList &inData){ memcpy(this, &inData, sizeof(*this)); return *this; } + bool operator == (const CKCAttributeList inData) const { return (this == &inData) || !memcmp(this, &inData, sizeof(CKCAttributeList)); } + operator CKCAttributeList*(){ return this; } + + virtual void WriteData(FILE *inFile) + { + fprintf(inFile, "\n"); + + CParamUInt32 aCount(".count", count); + aCount.Write(inFile); + + for(UInt32 i=0; i{ +public: + CKCRef(){ data = NULL; } + CKCRef(const KCRef &inData){ data = inData; } + bool operator == (const KCRef inKC) + { + if(inKC == data) return true; + + char thisName[256] = ""; + char aInName[256] = ""; + ::kcgetkeychainname(data, thisName); + ::kcgetkeychainname(inKC, aInName); + return(::strcmp(thisName, aInName)); + } +}; + + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ KCItemRef wrapper +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +TYPEDEF_POD_STRUCT(KCItemRef) +class CKCItemRef : public PodWrapper{ +public: + CKCItemRef(){ data = NULL; } + CKCItemRef(const KCItemRef &inData){ data = inData; } + bool operator == (const KCItemRef inKCItem) + { + if(inKCItem == data) return true; + + KCRef thisKeychain = 0; + KCRef aInKeychain = 0; + ::KCGetKeychain(data, &thisKeychain); + ::KCGetKeychain(inKCItem, &aInKeychain); + if((CKCRef(thisKeychain) == aInKeychain) == false) return false; + +// Bug #2458217 - (KCGetData() causes bus error) +#if TARGET_RT_MAC_MACHO + return true; +#else + UInt32 thisLength; + UInt32 aInLength; + ::KCGetData(data, 0, NULL, &thisLength); + ::KCGetData(inKCItem, 0, NULL, &aInLength); + if(thisLength != aInLength) return false; + + char *thisData = new char[thisLength]; + char *aInData = new char[aInLength]; + ::KCGetData(data, thisLength, thisData, &thisLength); + ::KCGetData(inKCItem, aInLength, aInData, &aInLength); + + int aResult = ::memcmp(thisData, aInData, thisLength); + + delete thisData; + delete aInData; + return(aResult == 0); +#endif + } +}; + + +#endif // __KC_PARAM_UTILITY_ diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/Radar.cpp b/SecurityTests/testKeychainAPI/testKeychainAPI/Radar.cpp new file mode 100644 index 00000000..10ad3269 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/Radar.cpp @@ -0,0 +1,116 @@ +// ====================================================================== +// File: Radar.cpp +// +// Repository of test cases which are entered into Radar. Use them to +// reproduce and regress Radar bugs. +// +// Copyright: Copyright (c) 2000,2003 Apple Computer, Inc. All Rights Reserved. +// +// Change History (most recent first): +// +// <1> 4/12/00 em Created. +// ====================================================================== + +#include "testKeychainAPI.h" +#include "Radar.h" + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Radar_2456779 +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// +// Wrong error number when creating duplicate keychain +// +void Radar_2456779(CTestApp *inClient) +{ + inClient->DoRunTestScript("0001"); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Radar_2458217 +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// +// GetData() causes bus error +// +void Radar_2458217(CTestApp *inClient) +{ + inClient->DoRunTestScript("0002"); + inClient->DoRunTestScript("0003"); + inClient->DoRunTestScript("0004"); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Radar_2458257 +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// +// GetKeychainManagerVersion() returns a wrong version +// +void Radar_2458257(CTestApp *inClient) +{ + inClient->DoRunTestScript("0000"); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Radar_2458503 +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// +// KCAddItem() fails to detect duplicate items +// +void Radar_2458503(CTestApp *inClient) +{ + inClient->DoRunTestScript("0008"); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Radar_2458613 +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// +// FindFirstItem returns an item from an empty keychain +// +void Radar_2458613(CTestApp *inClient) +{ + inClient->DoRunTestScript("0009"); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Radar_2459096 +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// +// InvalidItemRef error when deleting an item not previously added to keychain +// +void Radar_2459096(CTestApp *inClient) +{ + inClient->DoRunTestScript("0012"); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Radar_2462081 +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// +// AddAppleSharePassword returns DL_INVALID_FIELD_NAME +// +void Radar_2462081(CTestApp *inClient) +{ + inClient->DoRunTestScript("0013"); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Radar_2462265 +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// +// GetDataUI does not set ActualLength +// +void Radar_2462265(CTestApp *inClient) +{ + inClient->DoRunTestScript("0027"); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ Radar_2462300 +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// +// No dialog for KCChangeSettings +// +void Radar_2462300(CTestApp *inClient) +{ + inClient->DoRunTestScript("0025"); +} diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/Radar.h b/SecurityTests/testKeychainAPI/testKeychainAPI/Radar.h new file mode 100644 index 00000000..df14cd44 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/Radar.h @@ -0,0 +1,48 @@ +// ====================================================================== +// File: Radar.h +// +// Repository of test cases which are entered into Radar. Use them to +// reproduce and regress Radar bugs. +// +// Copyright: Copyright (c) 2000,2003,2008 Apple Inc. All Rights Reserved. +// +// Change History (most recent first): +// +// <1> 4/12/00 em Created. +// ====================================================================== + +#ifndef __RADAR__ +#define __RADAR__ + +void Radar_2456779(CTestApp *inClient); +void Radar_2458217(CTestApp *inClient); +void Radar_2458257(CTestApp *inClient); +void Radar_2458503(CTestApp *inClient); +void Radar_2458613(CTestApp *inClient); +void Radar_2459096(CTestApp *inClient); +void Radar_2462081(CTestApp *inClient); +void Radar_2462265(CTestApp *inClient); +void Radar_2462300(CTestApp *inClient); + +typedef void (*tRadarTestCaseFunc)(CTestApp *inClient); +typedef struct tRadarBug{ + tRadarTestCaseFunc testCaseFunc; + char * ID; + char * desc; +} tRadarBug; + + +static tRadarBug gRadarBugs[] ={ + {Radar_2456779, "2456779", "Wrong error number when creating duplicate keychain"}, + {Radar_2458217, "2458217", "GetData() causes bus error"}, + {Radar_2458257, "2458257", "GetKeychainManagerVersion() returns a wrong version"}, + {Radar_2458503, "2458503", "KCAddItem() fails to detect duplicate items"}, + {Radar_2458613, "2458613", "FindFirstItem returns an item from an empty keychain"}, + {Radar_2459096, "2459096", "InvalidItemRef error when deleting an item not previously added to keychain"}, + {Radar_2462081, "2462081", "AddAppleSharePassword returns DL_INVALID_FIELD_NAME"}, + {Radar_2462265, "2462265", "GetDataUI does not set ActualLength"}, + {Radar_2462300, "2462300", "No dialog for KCChangeSettings"}, + + {0}}; + +#endif // __RADAR__ diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/cleanup b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/cleanup new file mode 100644 index 00000000..f81f9ee7 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/cleanup @@ -0,0 +1,7 @@ +# +# Until this gets installed automatically, do the following line +# from your build dir: +# cp ../Tests/testKeychainAPI/testKeychainAPI/scripts/cleanup . +rm ~/Library/Preferences/test00* +rm ~/Library/Preferences/com.apple.securitycore.plist +rm ./*.db diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/error_scripts b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/error_scripts new file mode 100644 index 00000000..68c8dab5 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/error_scripts @@ -0,0 +1,166 @@ +// +// script0025 +// +// KCChangeSettings +// KCSetInteractionAllowed +// KCGetInteractionAllowed +// +// Change keychain settings w/ and w/o interaction allowed enabled +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0025.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +25 KCSetInteractionAllowed + Input Arguments : 1 + AllowInteraction : 0 + Results : 1 + OSStatus 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +20 KCChangeSettings + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus -25308 +25 KCSetInteractionAllowed + Input Arguments : 1 + AllowInteraction : 1 + Results : 1 + OSStatus 0 +26 KCIsInteractionAllowed + Input Arguments : 0 + Results : 2 + OSStatus 0 + AllowInteraction : 1 + +// +## Click the Cancel button ## +20 KCChangeSettings + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus -128 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 + + + 24 KCRemoveCallback + Input Arguments : 1 + KCEvent : 5 + Results : 12 + OSStatus 0 + IdleCount : 0 + LockCount : 0 + UnlockCount : 0 + AddCount : 0 + DeleteCount : 0 + UpdateCount : 1 + ChangeIdentityCount : 0 + FindCount : 0 + SystemCount : 0 + DefaultChangedCount : 1 + DataAccessCount : 1 +24 KCRemoveCallback + Input Arguments : 1 + KCEvent : 6 + Results : 12 + OSStatus 0 + IdleCount : 0 + LockCount : 0 + UnlockCount : 0 + AddCount : 0 + DeleteCount : 0 + UpdateCount : 0 + ChangeIdentityCount : 0 + FindCount : 0 + SystemCount : 0 + DefaultChangedCount : 1 + DataAccessCount : 1 +24 KCRemoveCallback + Input Arguments : 1 + KCEvent : 7 + Results : 12 + OSStatus 0 + IdleCount : 0 + LockCount : 0 + UnlockCount : 0 + AddCount : 0 + DeleteCount : 0 + UpdateCount : 0 + ChangeIdentityCount : 0 + FindCount : 0 + SystemCount : 0 + DefaultChangedCount : 1 + DataAccessCount : 1 +24 KCRemoveCallback + Input Arguments : 1 + KCEvent : 9 + Results : 12 + OSStatus 0 + IdleCount : 0 + LockCount : 0 + UnlockCount : 0 + AddCount : 0 + DeleteCount : 0 + UpdateCount : 0 + ChangeIdentityCount : 0 + FindCount : 0 + SystemCount : 0 + DefaultChangedCount : 1 + DataAccessCount : 1 +24 KCRemoveCallback + Input Arguments : 1 + KCEvent : 10 + Results : 12 + OSStatus 0 + IdleCount : 0 + LockCount : 0 + UnlockCount : 0 + AddCount : 0 + DeleteCount : 0 + UpdateCount : 0 + ChangeIdentityCount : 0 + FindCount : 0 + SystemCount : 0 + DefaultChangedCount : 0 + DataAccessCount : 1 +// remove twice +24 KCRemoveCallback + Input Arguments : 1 + KCEvent : 1 + Results : 12 + OSStatus -25298 + IdleCount : 0 + LockCount : 0 + UnlockCount : 0 + AddCount : 0 + DeleteCount : 0 + UpdateCount : 0 + ChangeIdentityCount : 0 + FindCount : 0 + SystemCount : 0 + DefaultChangedCount : 0 + DataAccessCount : 0 + diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/error_sub_cases_scripts b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/error_sub_cases_scripts new file mode 100644 index 00000000..9babebde --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/error_sub_cases_scripts @@ -0,0 +1,494 @@ +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Orange + Results : 1 + OSStatus -25293 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus -25315 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus -25315 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /5/00000 + Results : 3 + OSStatus 0 + Data : /5/Dog00 + ActualLength : 3 +41 KCAddItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +49 KCFindNextItem + Input Arguments : 1 + SearchIndex : 0 + Results : 2 + OSStatus 0 + ItemIndex : 1 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /50/00000000000000000000000000000000000000000000000000 + Results : 3 + OSStatus 0 + Data : /50/This item is not identical.00000000000000000000000 + ActualLength : 27 +49 KCFindNextItem + Input Arguments : 1 + SearchIndex : 0 + Results : 2 + OSStatus -25300 + ItemIndex : 3 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 1 + Results : 1 + OSStatus 0 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : type + .data : /2/00 + Results : 3 + OSStatus -25301 + Attribute : + .tag : type + .data : /2/00 + ActualLength : 4 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 5 + .0 : + .tag : desc + .data : /21/Description Attribute + .1 : + .tag : icmt + .data : /17/Comment Attribute + .2 : + .tag : labl + .data : /15/Label Attribute + .3 : + .tag : crtr + .data : /4/meme + .4 : + .tag : type + .data : /4/yuyu + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : desc + .data : /25/0000000000000000000000000 + Results : 3 + OSStatus 0 + Attribute : + .tag : desc + .data : /25/Description Attribute0000 + ActualLength : 21 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : icmt + .data : /17/00000000000000000 + Results : 3 + OSStatus 0 + Attribute : + .tag : icmt + .data : /17/Comment Attribute + ActualLength : 17 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : labl + .data : /15/000000000000000 + Results : 3 + OSStatus 0 + Attribute : + .tag : labl + .data : /15/Label Attribute + ActualLength : 15 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : crtr + .data : /5/00000 + Results : 3 + OSStatus 0 + Attribute : + .tag : crtr + .data : /4/meme + ActualLength : 4 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : type + .data : /4/0000 + Results : 3 + OSStatus 0 + Attribute : + .tag : type + .data : /4/yuyu + ActualLength : 4 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : type + .data : /2/00 + Results : 3 + OSStatus -25301 + Attribute : + .tag : type + .data : /2/00 + ActualLength : 4 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : clas + .data : /4/0000 + Results : 3 + OSStatus 0 + Attribute : + .tag : clas + .data : /4/inet + ActualLength : 4 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +49 KCFindNextItem + Input Arguments : 1 + SearchIndex : 0 + Results : 2 + OSStatus -25300 + ItemIndex : 1 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 037 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : type + .data : /2/00 + Results : 3 + OSStatus -25301 + Attribute : + .tag : type + .data : /2/00 + ActualLength : 4 +49 KCFindNextItem + Input Arguments : 1 + SearchIndex : 0 + Results : 2 + OSStatus -25300 + ItemIndex : 1 +49 KCFindNextItem + Input Arguments : 1 + SearchIndex : 0 + Results : 2 + OSStatus -25300 + ItemIndex : 1 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 0 +28 KCFindAppleSharePassword + Input Arguments : 6 + ServerSignature : My Signature.... + ServerAddress : This is my Server Address + ServerName : This is my Server Name + VolumeName : This is my Volume Name + AccountName : This is my Account Name + Password : /8/00000000 + Results : 4 + OSStatus 0 + Password : /8/Apple000 + ActualLength : 5 + ItemIndex : 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +34 KCFindGenericPassword + Input Arguments : 3 + ServiceName : This is my Service Name + AccountName : This is my Account Name + Password : /10/0000000000 + Results : 4 + OSStatus 0 + Password : /10/Apple00000 + ActualLength : 0 + ItemIndex : 1 +7 KCUnlockNoUI + Input Arguments : 2 + KeychainIndex : 0 Password : Apple + OSStatus 0 + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +40 KCGetDataNoUI + Input Arguments : 2 + ItemIndex : 0 + Data : /8/00000000 + Results : 3 + OSStatus -25308 + Data : /8/00000000 + ActualLength : 0 +42 KCAddItemNoUI + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus -25308 +40 KCGetDataNoUI + Input Arguments : 2 + ItemIndex : 0 + Data : /50/00000000000000000000000000000000000000000000000000 + Results : 3 + OSStatus -25308 + Data : /50/00000000000000000000000000000000000000000000000000 + ActualLength : 0 +42 KCAddItemNoUI + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 040 KCGetDataNoUI + Input Arguments : 2 + ItemIndex : 0 + Data : /50/00000000000000000000000000000000000000000000000000 + Results : 3 + OSStatus -25308 + Data : /50/00000000000000000000000000000000000000000000000000 + ActualLength : 0 +42 KCAddItemNoUI + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus -25308 +40 KCGetDataNoUI + Input Arguments : 2 + ItemIndex : 0 + Data : /8/00000000 + Results : 3 + OSStatus -25308 + Data : /8/00000000 + ActualLength : 0 +26 KCIsInteractionAllowed + Input Arguments : 0 + Results : 2 + OSStatus 0 + AllowInteraction : 1 +// +// script0025 +// +// KCChangeSettings +// KCSetInteractionAllowed +// KCGetInteractionAllowed +// +// Change keychain settings w/ and w/o interaction allowed enabled +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0025.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +25 KCSetInteractionAllowed + Input Arguments : 1 + AllowInteraction : 0 + Results : 1 + OSStatus 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +20 KCChangeSettings + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus -25308 +25 KCSetInteractionAllowed + Input Arguments : 1 + AllowInteraction : 1 + Results : 1 + OSStatus 0 +26 KCIsInteractionAllowed + Input Arguments : 0 + Results : 2 + OSStatus 0 + AllowInteraction : 1 + +// +## Click the Cancel button ## +20 KCChangeSettings + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus -128 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 + + + 24 KCRemoveCallback + Input Arguments : 1 + KCEvent : 5 + Results : 12 + OSStatus 0 + IdleCount : 0 + LockCount : 0 + UnlockCount : 0 + AddCount : 0 + DeleteCount : 0 + UpdateCount : 1 + ChangeIdentityCount : 0 + FindCount : 0 + SystemCount : 0 + DefaultChangedCount : 1 + DataAccessCount : 1 +24 KCRemoveCallback + Input Arguments : 1 + KCEvent : 6 + Results : 12 + OSStatus 0 + IdleCount : 0 + LockCount : 0 + UnlockCount : 0 + AddCount : 0 + DeleteCount : 0 + UpdateCount : 0 + ChangeIdentityCount : 0 + FindCount : 0 + SystemCount : 0 + DefaultChangedCount : 1 + DataAccessCount : 1 +24 KCRemoveCallback + Input Arguments : 1 + KCEvent : 7 + Results : 12 + OSStatus 0 + IdleCount : 0 + LockCount : 0 + UnlockCount : 0 + AddCount : 0 + DeleteCount : 0 + UpdateCount : 0 + ChangeIdentityCount : 0 + FindCount : 0 + SystemCount : 0 + DefaultChangedCount : 1 + DataAccessCount : 1 +24 KCRemoveCallback + Input Arguments : 1 + KCEvent : 9 + Results : 12 + OSStatus 0 + IdleCount : 0 + LockCount : 0 + UnlockCount : 0 + AddCount : 0 + DeleteCount : 0 + UpdateCount : 0 + ChangeIdentityCount : 0 + FindCount : 0 + SystemCount : 0 + DefaultChangedCount : 1 + DataAccessCount : 1 +24 KCRemoveCallback + Input Arguments : 1 + KCEvent : 10 + Results : 12 + OSStatus 0 + IdleCount : 0 + LockCount : 0 + UnlockCount : 0 + AddCount : 0 + DeleteCount : 0 + UpdateCount : 0 + ChangeIdentityCount : 0 + FindCount : 0 + SystemCount : 0 + DefaultChangedCount : 0 + DataAccessCount : 1 +// remove twice +24 KCRemoveCallback + Input Arguments : 1 + KCEvent : 1 + Results : 12 + OSStatus -25298 + IdleCount : 0 + LockCount : 0 + UnlockCount : 0 + AddCount : 0 + DeleteCount : 0 + UpdateCount : 0 + ChangeIdentityCount : 0 + FindCount : 0 + SystemCount : 0 + DefaultChangedCount : 0 + DataAccessCount : 0 +25 KCSetInteractionAllowed + Input Arguments : 1 + AllowInteraction : 0 + Results : 1 + OSStatus 0 +25 KCSetInteractionAllowed + Input Arguments : 1 + AllowInteraction : 1 + Results : 1 + OSStatus 0 +25 KCSetInteractionAllowed + Input Arguments : 1 + AllowInteraction : 1 + Results : 1 + OSStatus 0 +26 KCIsInteractionAllowed + Input Arguments : 0 + Results : 2 + OSStatus 0 + AllowInteraction : 1 + + diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0000 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0000 new file mode 100644 index 00000000..cb0fd99a --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0000 @@ -0,0 +1,19 @@ +// +// script0000 +// +// KCGetKeychainManagerVersion +// KeychainManagerAvailable +// +// ** note ** update the expected version number for different +// version of SecurityLib +// +0 KCGetKeychainManagerVersion + Input Arguments : 0 + Results : 1 + OSStatus 0 + Version : 33718272 +1 KeychainManagerAvailable + Input Arguments : 0 + Results : 1 + OSStatus 0 + Available 1 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0001 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0001 new file mode 100644 index 00000000..ceb8551e --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0001 @@ -0,0 +1,69 @@ +// +// script0001 +// +// KCCreateKeychain +// KCGetDefaultKeychain +// +// Create a keychain & release KCRef twice +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0001.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 1 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0001.002 + Results : 2 + OSStatus 0 + KeychainIndex : 2 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 2 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 3 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0001.001 + Results : 2 + OSStatus 0 + KeychainIndex : 4 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 4 + Password : Apple + Results : 2 + OSStatus -25296 + KeychainIndex : 5 +// First keychain is the default keychain +12 KCGetDefaultKeychain + Input Arguments : 0 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +19 KCGetKeychainName + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 + KeychainName : test0001.001 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 2 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0001.001 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0001.001 new file mode 100644 index 00000000..4f52f7fd --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0001.001 @@ -0,0 +1,15 @@ +// +// script0001.001 +// +// KCUnlock +// +// ** note ** +// Once this script is executed, the Keychain "test0001.001" should not +// be unlocked until the system rebooted. (run this script with discretion) +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0001.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0002 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0002 new file mode 100644 index 00000000..86593016 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0002 @@ -0,0 +1,69 @@ +// +// script0002 +// +// KCNewItem +// KCAddItem +// KCGetData +// +// Create an Apple Share Password item & add it to a default Keychain +// +35 KCNewItem + Input Arguments : 4 + Class : ashp + Creator : meme + Data : /5/apple + Results : 2 + OSStatus 0 + ItemIndex : 0 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0002.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +41 KCAddItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /8/00000000 + Results : 3 + OSStatus 0 + Data : /8/apple000 + ActualLength : 5 +45 KCUpdateItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0002.000 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0002.000 new file mode 100644 index 00000000..e0eeacf7 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0002.000 @@ -0,0 +1,65 @@ +// +// script0002.000 +// +// KCNewItem +// KCAddItem +// KCGetData +// +// Check the item created in script0002 still exists +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0002.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 2 + .0 : + .tag : clas + .data : /4/ashp + .1 : + .tag : crtr + .data : /4/meme + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +49 KCFindNextItem + Input Arguments : 1 + SearchIndex : 0 + Results : 2 + OSStatus -25300 + ItemIndex : 1 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /8/00000000 + Results : 3 + OSStatus 0 + Data : /8/apple000 + ActualLength : 5 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0003 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0003 new file mode 100644 index 00000000..28958fe2 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0003 @@ -0,0 +1,69 @@ +// +// script0003 +// +// KCNewItem +// KCAddItem +// KCGetData +// +// Create a Generic Password item & add it to a default Keychain +// +35 KCNewItem + Input Arguments : 4 + Class : genp + Creator : meme + Data : /50/First Generic password:abcdefghijklmnopqrstuvwxyz# + Results : 2 + OSStatus 0 + ItemIndex : 0 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0003.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +41 KCAddItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /50/00000000000000000000000000000000000000000000000000 + Results : 3 + OSStatus 0 + Data : /50/First Generic password:abcdefghijklmnopqrstuvwxyz# + ActualLength : 50 +45 KCUpdateItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0003.000 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0003.000 new file mode 100644 index 00000000..3c6c525b --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0003.000 @@ -0,0 +1,70 @@ +// +// script0003.000 +// +// KCNewItem +// KCAddItem +// KCGetData +// +// Check the item created in script0003 still exists +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0003.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 2 + .0 : + .tag : clas + .data : /4/genp + .1 : + .tag : crtr + .data : /4/meme + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /50/00000000000000000000000000000000000000000000000000 + Results : 3 + OSStatus 0 + Data : /50/First Generic password:abcdefghijklmnopqrstuvwxyz# + ActualLength : 50 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +49 KCFindNextItem + Input Arguments : 1 + SearchIndex : 0 + Results : 2 + OSStatus -25300 + ItemIndex : 1 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0004 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0004 new file mode 100644 index 00000000..2e6c0862 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0004 @@ -0,0 +1,69 @@ +// +// script0004 +// +// KCNewItem +// KCAddItem +// KCGetData +// +// Create a Internet Password item & add it to a default Keychain +// +35 KCNewItem + Input Arguments : 4 + Class : inet + Creator : meme + Data : /48/First Internet password:abcdefghijklmnopqrstuvwx + Results : 2 + OSStatus 0 + ItemIndex : 0 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0004.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +41 KCAddItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /50/00000000000000000000000000000000000000000000000000 + Results : 3 + OSStatus 0 + Data : /50/First Internet password:abcdefghijklmnopqrstuvwx00 + ActualLength : 48 +45 KCUpdateItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0004.000 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0004.000 new file mode 100644 index 00000000..5eb070ea --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0004.000 @@ -0,0 +1,70 @@ +// +// script0004.000 +// +// KCNewItem +// KCAddItem +// KCGetData +// +// Check the item created in script0003 still exists +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0004.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 2 + .0 : + .tag : clas + .data : /4/inet + .1 : + .tag : crtr + .data : /4/meme + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /50/00000000000000000000000000000000000000000000000000 + Results : 3 + OSStatus 0 + Data : /50/First Internet password:abcdefghijklmnopqrstuvwx00 + ActualLength : 48 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +49 KCFindNextItem + Input Arguments : 1 + SearchIndex : 0 + Results : 2 + OSStatus -25300 + ItemIndex : 1 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0005 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0005 new file mode 100644 index 00000000..8da3b332 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0005 @@ -0,0 +1,77 @@ +// +// script0005 +// +// KCSetData +// KCGetData +// +// Create & Add an Apple Share Password item a default Keychain, then modify the data +// +35 KCNewItem + Input Arguments : 4 + Class : ashp + Creator : hehe + Data : /5/Apple + Results : 2 + OSStatus 0 + ItemIndex : 0 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0005.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +41 KCAddItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +38 KCSetData + Input Arguments : 2 + ItemIndex : 0 + Data : /3/Dog + Results : 1 + OSStatus 0 +// +// THIS IS WRONG NOW: - the rogueapp alert does come up and allow access (returns 0) +// +// NOTE! We return errKCInvalid (soon to change to access denied) +// We want to prohibit processes from accessing data that is cached in +// memory that hasn't been written out. We want to stop the process +// from bypassing our rogue-app/access control UI +// +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /5/00000 + Results : 3 + OSStatus 0 + Data : /5/Apple + ActualLength : 5 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0005.000 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0005.000 new file mode 100644 index 00000000..a1a5dd7d --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0005.000 @@ -0,0 +1,61 @@ +// +// script0005.000 +// +// KCSetData +// KCGetData +// +// Check the item created in script0005 still exists +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0005.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 2 + .0 : + .tag : clas + .data : /4/ashp + .1 : + .tag : crtr + .data : /4/hehe + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +49 KCFindNextItem + Input Arguments : 1 + SearchIndex : 0 + Results : 2 + OSStatus -25300 + ItemIndex : 1 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0006 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0006 new file mode 100644 index 00000000..82800acd --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0006 @@ -0,0 +1,80 @@ +// +// script0006 +// +// KCSetData +// KCGetData +// +// Create & Add an Generic Password item a default Keychain, then modify the data +// +35 KCNewItem + Input Arguments : 4 + Class : genp + Creator : meme + Data : /50/First Generic password:abcdefghijklmnopqrstuvwxyz# + Results : 2 + OSStatus 0 + ItemIndex : 0 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0006.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +41 KCAddItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +38 KCSetData + Input Arguments : 2 + ItemIndex : 0 + Data : /3/Cat + Results : 1 + OSStatus 0 +45 KCUpdateItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +// +// NOTE! We return errKCInvalid (soon to change to access denied) +// We want to prohibit processes from accessing data that is cached in +// memory that hasn't been written out. We want to stop the process +// from bypassing our rogue-app/access control UI +// +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /3/000 + Results : 3 + OSStatus 0 + Data : /3/Cat + ActualLength : 3 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0006.000 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0006.000 new file mode 100644 index 00000000..afa4e344 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0006.000 @@ -0,0 +1,69 @@ +// +// script0006.000 +// +// KCSetData +// KCGetData +// +// Check the item created in script0006 still exists +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0006.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 2 + .0 : + .tag : clas + .data : /4/genp + .1 : + .tag : crtr + .data : /4/meme + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /3/000 + Results : 3 + OSStatus 0 + Data : /3/Cat + ActualLength : 3 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +49 KCFindNextItem + Input Arguments : 1 + SearchIndex : 0 + Results : 2 + OSStatus -25300 + ItemIndex : 1 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0007 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0007 new file mode 100644 index 00000000..b37034e9 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0007 @@ -0,0 +1,82 @@ +// +// script0007 +// +// KCSetData +// KCGetData +// +// Create & Add an Internet Password item a default Keychain, then modify the data +// +35 KCNewItem + Input Arguments : 4 + Class : inet + Creator : meme + Data : /48/First Internet password:abcdefghijklmnopqrstuvwx + Results : 2 + OSStatus 0 + ItemIndex : 0 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0007.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +41 KCAddItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +38 KCSetData + Input Arguments : 2 + ItemIndex : 0 + Data : /6/Monkey + Results : 1 + OSStatus 0 +45 KCUpdateItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +// +// THIS IS WRONG NOW - the rogueapp does come up and +// +// NOTE! We return errKCInvalid (soon to change to access denied) +// We want to prohibit processes from accessing data that is cached in +// memory that hasn't been written out. We want to stop the process +// from bypassing our rogue-app/access control UI +// +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /6/000000 + Results : 3 + OSStatus 0 + Data : /6/Monkey + ActualLength : 6 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0007.000 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0007.000 new file mode 100644 index 00000000..264c9261 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0007.000 @@ -0,0 +1,69 @@ +// +// script0007.000 +// +// KCSetData +// KCGetData +// +// Check the item created in script0007 still exists +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0007.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 2 + .0 : + .tag : clas + .data : /4/inet + .1 : + .tag : crtr + .data : /4/meme + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /6/000000 + Results : 3 + OSStatus 0 + Data : /6/Monkey + ActualLength : 6 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +49 KCFindNextItem + Input Arguments : 1 + SearchIndex : 0 + Results : 2 + OSStatus -25300 + ItemIndex : 1 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0008 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0008 new file mode 100644 index 00000000..616a85e5 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0008 @@ -0,0 +1,94 @@ +// +// script0008 +// +// KCSetData +// +// Try adding an identical Internet Password password twice +// +// +35 KCNewItem + Input Arguments : 4 + Class : inet + Creator : meme + Data : /48/First Internet password:abcdefghijklmnopqrstuvwx + Results : 2 + OSStatus 0 + ItemIndex : 0 +35 KCNewItem + Input Arguments : 4 + Class : inet + Creator : usus + Data : /27/This item is not identical. + Results : 2 + OSStatus 0 + ItemIndex : 1 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0008.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +41 KCAddItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +41 KCAddItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus -25299 +45 KCUpdateItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /50/00000000000000000000000000000000000000000000000000 + Results : 3 + OSStatus 0 + Data : /50/First Internet password:abcdefghijklmnopqrstuvwx00 + ActualLength : 48 +39 KCGetData + Input Arguments : 2 + ItemIndex : 1 + Data : /50/00000000000000000000000000000000000000000000000000 + Results : 3 + OSStatus 0 + Data : /50/This item is not identical.00000000000000000000000 + ActualLength : 27 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 1 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0008.000 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0008.000 new file mode 100644 index 00000000..d9fe5bd1 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0008.000 @@ -0,0 +1,57 @@ +// +// script0008.000 +// +// KCSetData +// +// Check the items created in script0008 still exist +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0008.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 2 + .0 : + .tag : clas + .data : /4/inet + .1 : + .tag : crtr + .data : /4/meme + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /50/00000000000000000000000000000000000000000000000000 + Results : 3 + OSStatus 0 + Data : /50/First Internet password:abcdefghijklmnopqrstuvwx00 + ActualLength : 48 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0009 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0009 new file mode 100644 index 00000000..82b16015 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0009 @@ -0,0 +1,50 @@ +// +// script0009 +// +// KCFindFirstItem +// +// Find the first item of an empty keychain +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0009.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 0 + Results : 3 + OSStatus -25300 + SearchIndex : 0 + ItemIndex : 0 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus -25305 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0010 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0010 new file mode 100644 index 00000000..e0227887 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0010 @@ -0,0 +1,87 @@ +// +// script0010 +// +// Adding an Internet Password to an empty Keychain and +// retrieve it via KCFindFirstItem() +// +35 KCNewItem + Input Arguments : 4 + Class : inet + Creator : meme + Data : /19/Internet Password 1 + Results : 2 + OSStatus 0 + ItemIndex : 0 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0010.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +41 KCAddItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 2 + .0 : + .tag : clas + .data : /4/inet + .1 : + .tag : crtr + .data : /4/meme + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +49 KCFindNextItem + Input Arguments : 1 + SearchIndex : 0 + Results : 2 + OSStatus -25300 + ItemIndex : 2 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /50/00000000000000000000000000000000000000000000000000 + Results : 3 + OSStatus 0 + Data : /50/Internet Password 10000000000000000000000000000000 + ActualLength : 19 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0010.000 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0010.000 new file mode 100644 index 00000000..c5163a20 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0010.000 @@ -0,0 +1,66 @@ +// +// script0010.000 +// +// Check the items created in script0010 still exist +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0010.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 2 + .0 : + .tag : clas + .data : /4/inet + .1 : + .tag : crtr + .data : /4/meme + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +49 KCFindNextItem + Input Arguments : 1 + SearchIndex : 0 + Results : 2 + OSStatus -25300 + ItemIndex : 1 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /50/00000000000000000000000000000000000000000000000000 + Results : 3 + OSStatus 0 + Data : /50/Internet Password 10000000000000000000000000000000 + ActualLength : 19 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0011 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0011 new file mode 100644 index 00000000..93585317 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0011 @@ -0,0 +1,189 @@ +// +// script0011 +// +// KCSetAttribute +// +// Adding an Internet Password to an empty Keychain and +// set 5 attributes & retrieve them +// Description (desc) +// Comment (icmt) +// Label (labl) +// Creator Type (crtr) +// File Type (type) +// +35 KCNewItem + Input Arguments : 4 + Class : inet + Creator : meme + Data : /19/Internet Password 1 + Results : 2 + OSStatus 0 + ItemIndex : 0 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0011.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +41 KCAddItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +36 KCSetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : desc + .data : /21/Description Attribute + Results : 1 + OSStatus 0 +36 KCSetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : icmt + .data : /17/Comment Attribute + Results : 1 + OSStatus 0 +36 KCSetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : labl + .data : /15/Label Attribute + Results : 1 + OSStatus 0 +36 KCSetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : crtr + .data : /4/meme + Results : 1 + OSStatus 0 +36 KCSetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : type + .data : /4/yuyu + Results : 1 + OSStatus 0 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : desc + .data : /25/0000000000000000000000000 + Results : 3 + OSStatus 0 + Attribute : + .tag : desc + .data : /25/Description Attribute0000 + ActualLength : 21 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : icmt + .data : /17/00000000000000000 + Results : 3 + OSStatus 0 + Attribute : + .tag : icmt + .data : /17/Comment Attribute + ActualLength : 17 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : labl + .data : /15/000000000000000 + Results : 3 + OSStatus 0 + Attribute : + .tag : labl + .data : /15/Label Attribute + ActualLength : 15 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : crtr + .data : /5/00000 + Results : 3 + OSStatus 0 + Attribute : + .tag : crtr + .data : /4/meme + ActualLength : 4 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : type + .data : /4/0000 + Results : 3 + OSStatus 0 + Attribute : + .tag : type + .data : /4/yuyu + ActualLength : 4 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : type + .data : /2/00 + Results : 3 + OSStatus 0 + Attribute : + .tag : type + .data : /2/yu + ActualLength : 2 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : clas + .data : /4/0000 + Results : 3 + OSStatus 0 + Attribute : + .tag : clas + .data : /4/inet + ActualLength : 4 +45 KCUpdateItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0011.001 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0011.001 new file mode 100755 index 00000000..d37ae156 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0011.001 @@ -0,0 +1,130 @@ +// +// script0011.001 +// +// Test all 5 attributes added in script0011 can be retrieved +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0011.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 2 + .0 : + .tag : clas + .data : /4/inet + .1 : + .tag : crtr + .data : /4/meme + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : desc + .data : /25/0000000000000000000000000 + Results : 3 + OSStatus 0 + Attribute : + .tag : desc + .data : /25/Description Attribute0000 + ActualLength : 21 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : icmt + .data : /17/00000000000000000 + Results : 3 + OSStatus 0 + Attribute : + .tag : icmt + .data : /17/Comment Attribute + ActualLength : 17 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : labl + .data : /15/000000000000000 + Results : 3 + OSStatus 0 + Attribute : + .tag : labl + .data : /15/Label Attribute + ActualLength : 15 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : crtr + .data : /5/00000 + Results : 3 + OSStatus 0 + Attribute : + .tag : crtr + .data : /4/meme + ActualLength : 4 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : type + .data : /4/0000 + Results : 3 + OSStatus 0 + Attribute : + .tag : type + .data : /4/yuyu + ActualLength : 4 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : clas + .data : /4/0000 + Results : 3 + OSStatus 0 + Attribute : + .tag : clas + .data : /4/inet + ActualLength : 4 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +49 KCFindNextItem + Input Arguments : 1 + SearchIndex : 0 + Results : 2 + OSStatus -25300 + ItemIndex : 1 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0011.002 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0011.002 new file mode 100755 index 00000000..3c32f10e --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0011.002 @@ -0,0 +1,27 @@ +// +// script0011.002 +// +// Test all 5 attributes added in script0011 can be retrieved +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0011.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0011.003 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0011.003 new file mode 100755 index 00000000..d9a4632b --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0011.003 @@ -0,0 +1,122 @@ +// +// script0011.003 [alpha blocker] +// +// Test all 5 attributes added in script0011 can be retrieved +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0011.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 1 + .0 : + .tag : labl + .data : /15/Label Attribute + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : desc + .data : /25/0000000000000000000000000 + Results : 3 + OSStatus 0 + Attribute : + .tag : desc + .data : /25/Description Attribute0000 + ActualLength : 21 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : icmt + .data : /17/00000000000000000 + Results : 3 + OSStatus 0 + Attribute : + .tag : icmt + .data : /17/Comment Attribute + ActualLength : 17 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : labl + .data : /15/000000000000000 + Results : 3 + OSStatus 0 + Attribute : + .tag : labl + .data : /15/Label Attribute + ActualLength : 15 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : crtr + .data : /5/00000 + Results : 3 + OSStatus 0 + Attribute : + .tag : crtr + .data : /4/meme + ActualLength : 4 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : type + .data : /4/0000 + Results : 3 + OSStatus 0 + Attribute : + .tag : type + .data : /4/yuyu + ActualLength : 4 +37 KCGetAttribute + Input Arguments : 2 + ItemIndex : 0 + Attribute : + .tag : clas + .data : /4/0000 + Results : 3 + OSStatus 0 + Attribute : + .tag : clas + .data : /4/inet + ActualLength : 4 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 + diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0012 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0012 new file mode 100644 index 00000000..02c88caf --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0012 @@ -0,0 +1,60 @@ +// +// script0012 +// +// KCDeleteItem +// +// Delete an item not previously added (it shouldn't do anything) +// Delete the same item twice (error) +// +35 KCNewItem + Input Arguments : 4 + Class : genp + Creator : meme + Data : /16/Generic Password + Results : 2 + OSStatus 0 + ItemIndex : 0 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0012.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +41 KCAddItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +43 KCDeleteItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +43 KCDeleteItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus -25300 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0012.000 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0012.000 new file mode 100644 index 00000000..b5384aa5 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0012.000 @@ -0,0 +1,45 @@ +// +// script0012.000 +// +// KCDeleteItem +// +// Test if keychain created in script0012 remains empty +// (all items added were deleted in script0012) +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0012.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 2 + .0 : + .tag : clas + .data : /4/genp + .1 : + .tag : crtr + .data : /4/meme + Results : 3 + OSStatus -25300 + SearchIndex : 0 + ItemIndex : 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0012.001 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0012.001 new file mode 100644 index 00000000..81e8620f --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0012.001 @@ -0,0 +1,17 @@ +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFSSpec : test0012.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +7 KCUnlockNoUI + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0013 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0013 new file mode 100755 index 00000000..27aa509d --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0013 @@ -0,0 +1,79 @@ +// +// script0013 +// +// KCAddAppleSharePassword +// KCFindAppleSharePassword +// +// Add an Apple Share password and retrieve it +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0013.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +27 KCAddAppleSharePassword + Input Arguments : 7 + ServerSignature : My Signature.... + ServerAddress : This is my Server Address + ServerName : This is my Server Name + VolumeName : This is my Volume Name + AccountName : This is my Account Name + Password : /5/Apple + Results : 2 + OSStatus 0 + ItemIndex : 0 +// %%%cpm - +// The following stuff won't run correctly because +// Only AppleShare and KeychainAccess can interpret the contents of +// a AppleSharePassword item. It's contains a AppleShare private structure +// with a max of 8 characters inside for the pwd. +// +//## Click the Allow button (to acquire data on the find)## +// +//28 KCFindAppleSharePassword +// Input Arguments : 6 +// ServerSignature : My Signature.... +// ServerAddress : This is my Server Address +// ServerName : This is my Server Name +// VolumeName : This is my Volume Name +// AccountName : This is my Account Name +// Password : /8/00000000 +// Results : 4 +// OSStatus 0 +// Password : /8/Apple000 +// ActualLength : 5 +// ItemIndex : 0 +//45 KCUpdateItem +// Input Arguments : 1 +// ItemIndex : 0 +// Results : 1 +// OSStatus 0 +//46 KCReleaseItem +// Input Arguments : 1 +// ItemIndex : 0 +// Results : 1 +// OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0013.000 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0013.000 new file mode 100644 index 00000000..b50f8ced --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0013.000 @@ -0,0 +1,30 @@ +// +// script0013.000 +// +// KCAddAppleSharePassword +// KCFindAppleSharePassword +// +// Find the AppleShare password added in script0013 +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0013.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0014 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0014 new file mode 100755 index 00000000..5048f073 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0014 @@ -0,0 +1,80 @@ +// +// script0014 +// +// KCAddInternetPassword +// KCFindInternetPassword +// +// Add an Internet password and retrieve it +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0014.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +29 KCAddInternetPassword + Input Arguments : 7 + ServerName : This is my Server name + SecurityDomain : This is my Security Domain + AccountName : This is my Accout name + Port : 18 + Protocol : http + AuthType : httd + Password : /5/Apple + Results : 2 + OSStatus 0 + ItemIndex : 0 +29 KCAddInternetPassword + Input Arguments : 7 + ServerName : This is my Server name + SecurityDomain : This is my Security Domain + AccountName : This is my Accout name + Port : 18 + Protocol : http + AuthType : httd + Password : /5/Apple + Results : 2 + OSStatus -25299 + ItemIndex : 1 +31 KCFindInternetPassword + Input Arguments : 7 + ServerName : This is my Server name + SecurityDomain : This is my Security Domain + AccountName : This is my Accout name + Port : 18 + Protocol : http + AuthType : httd + Password : /10/0000000000 + Results : 4 + OSStatus 0 + Password : /10/Apple00000 + ActualLength : 5 + ItemIndex : 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0014.000 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0014.000 new file mode 100644 index 00000000..24254fbb --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0014.000 @@ -0,0 +1,49 @@ +// +// script0014.000 +// +// KCAddInternetPassword +// KCFindInternetPassword +// +// Find the Internet password added in script0014 +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0014.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +31 KCFindInternetPassword + Input Arguments : 7 + ServerName : This is my Server name + SecurityDomain : This is my Security Domain + AccountName : This is my Accout name + Port : 18 + Protocol : http + AuthType : httd + Password : /10/0000000000 + Results : 4 + OSStatus 0 + Password : /10/Apple00000 + ActualLength : 5 + ItemIndex : 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0015 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0015 new file mode 100644 index 00000000..bb67e21d --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0015 @@ -0,0 +1,92 @@ +// +// script0015 +// +// +// KCAddInternetPasswordWithPath +// KCFindInternetPasswordWithPath +// +// Add an Internet password and retrieve it +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0015.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +30 KCAddInternetPasswordWithPath + Input Arguments : 8 + ServerName : This is my Server name + SecurityDomain : This is my Security Domain + AccountName : This is my Accout name + Path : This is my Path + Port : 18 + Protocol : http + AuthType : httd + Password : /5/Apple + Results : 2 + OSStatus 0 + ItemIndex : 0 +30 KCAddInternetPasswordWithPath + Input Arguments : 8 + ServerName : This is my Server name + SecurityDomain : This is my Security Domain + AccountName : This is my Accout name + Path : This is my Path + Port : 18 + Protocol : http + AuthType : httd + Password : /5/Apple + Results : 2 + OSStatus -25299 + ItemIndex : 1 +32 KCFindInternetPasswordWithPath + Input Arguments : 8 + ServerName : This is my Server name + SecurityDomain : This is my Security Domain + AccountName : This is my Accout name + Path : This is my Path + Port : 18 + Protocol : http + AuthType : httd + Password : /10/0000000000 + Results : 4 + OSStatus 0 + Password : /10/Apple00000 + ActualLength : 5 + ItemIndex : 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 + + + + + + + + diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0015.000 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0015.000 new file mode 100644 index 00000000..00adf6fc --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0015.000 @@ -0,0 +1,59 @@ +// +// script0015.000 +// +// +// KCAddInternetPasswordWithPath +// KCFindInternetPasswordWithPath +// +// Find the Internet password added in script0015 +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0015.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +32 KCFindInternetPasswordWithPath + Input Arguments : 8 + ServerName : This is my Server name + SecurityDomain : This is my Security Domain + AccountName : This is my Accout name + Path : This is my Path + Port : 18 + Protocol : http + AuthType : httd + Password : /10/0000000000 + Results : 4 + OSStatus 0 + Password : /10/Apple00000 + ActualLength : 5 + ItemIndex : 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 + + + + + + + + diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0016 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0016 new file mode 100644 index 00000000..f6f60d90 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0016 @@ -0,0 +1,86 @@ +// +// script0016 +// +// KCAddGenericPassword +// KCFindGenericPassword +// +// Add a Generic password and retrieve it +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0016.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +33 KCAddGenericPassword + Input Arguments : 3 + ServiceName : This is my Service Name + AccountName : This is my Account Name + Password : /5/Apple + Results : 2 + OSStatus 0 + ItemIndex : 0 +33 KCAddGenericPassword + Input Arguments : 3 + ServiceName : This is my Service Name + AccountName : This is my Account Name + Password : /5/Apple + Results : 2 + OSStatus -25299 + ItemIndex : 1 +34 KCFindGenericPassword + Input Arguments : 3 + ServiceName : This is my Service Name + AccountName : This is my Account Name + Password : /10/0000000000 + Results : 4 + OSStatus 0 + Password : /10/Apple00000 + ActualLength : 5 + ItemIndex : 0 +34 KCFindGenericPassword + Input Arguments : 3 + ServiceName : This is my Service Name + AccountName : This is my Account Name + Password : /10/0000000000 + Results : 4 + OSStatus 0 + Password : /10/Apple00000 + ActualLength : 5 + ItemIndex : 3 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 + + + + + + + + diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0016.000 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0016.000 new file mode 100644 index 00000000..8b4c5141 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0016.000 @@ -0,0 +1,53 @@ +// +// script0016.000 +// +// KCAddGenericPassword +// KCFindGenericPassword +// +// Find the Internet password added in script0016 +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0016.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +34 KCFindGenericPassword + Input Arguments : 3 + ServiceName : This is my Service Name + AccountName : This is my Account Name + Password : /10/0000000000 + Results : 4 + OSStatus 0 + Password : /10/Apple00000 + ActualLength : 5 + ItemIndex : 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 + + + + + + + + diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0017 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0017 new file mode 100644 index 00000000..4d08628d --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0017 @@ -0,0 +1,82 @@ +// +// script0017 +// +// KCSetDefaultKeychain +// KCGetDefaultKeychain +// +// Switch default keychain +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0017.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 1 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0017.002 + Results : 2 + OSStatus 0 + KeychainIndex : 2 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 2 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 3 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0017.003 + Results : 2 + OSStatus 0 + KeychainIndex : 4 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 4 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 5 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 1 + Results : 1 + OSStatus 0 +12 KCGetDefaultKeychain + Input Arguments : 0 + Results : 2 + OSStatus 0 + KeychainIndex : 1 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 3 + Results : 1 + OSStatus 0 +12 KCGetDefaultKeychain + Input Arguments : 0 + Results : 2 + OSStatus 0 + KeychainIndex : 3 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 2 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 4 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0018 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0018 new file mode 100644 index 00000000..996eefbe --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0018 @@ -0,0 +1,32 @@ +// +// script0018 +// +// KCNewItem +// +// Create an Apple Share Password item with its data length > 8 +// +// This length is enforced by AppleShare client, but we can't enforce this +// limit in case it is lifted later. +// +35 KCNewItem + Input Arguments : 4 + Class : ashp + Creator : meme + Data : /14/apple computer + Results : 2 + OSStatus 0 + ItemIndex : 0 +35 KCNewItem + Input Arguments : 4 + Class : ashp + Creator : meme + Data : /5/apple + Results : 2 + OSStatus 0 + ItemIndex : 1 +38 KCSetData + Input Arguments : 2 + ItemIndex : 1 + Data : /14/apple computer + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0019 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0019 new file mode 100644 index 00000000..1316f692 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0019 @@ -0,0 +1,60 @@ +// +// script0019 +// +// KCAddAppleSharePassword +// +// Create an Apple Share Password item with its data length > 8 +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0019.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +//%%%why does it expect -25302? (dataTooLarge) - we CANT impose the 8 char limit on our hi level call +27 KCAddAppleSharePassword + Input Arguments : 7 + ServerSignature : My Signature.... + ServerAddress : This is my Server Address + ServerName : This is my Server Name + VolumeName : This is my Volume Name + AccountName : This is my Account Name + Password : /14/apple computer + Results : 2 + OSStatus -25302 + ItemIndex : 0 +27 KCAddAppleSharePassword + Input Arguments : 7 + ServerSignature : My Signature.... + ServerAddress : This is my Server Address + ServerName : This is my Server Name + VolumeName : This is my Volume Name + AccountName : This is my Account Name + Password : /5/apple + Results : 2 + OSStatus 0 + ItemIndex : 1 +38 KCSetData + Input Arguments : 2 + ItemIndex : 1 + Data : /14/apple computer + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0020 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0020 new file mode 100644 index 00000000..b6f01288 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0020 @@ -0,0 +1,44 @@ +// +// script0020 @@@needs work +// +// Copy Item +// +35 KCNewItem + Input Arguments : 4 + Class : inet + Creator : meme + Data : /48/First Internet password:abcdefghijklmnopqrstuvwx + Results : 2 + OSStatus 0 + ItemIndex : 0 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0020.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +47 KCCopyItem + Input Arguments : 2 + KeychainIndex : 0 + ItemIndex : 0 + Results : 2 + OSStatus 0 + ItemIndex : 1 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0021 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0021 new file mode 100755 index 00000000..2cb6e65b --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0021 @@ -0,0 +1,41 @@ +// +// script0021 +// +// KCMakeKCRefFromAlias +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0021.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 + KeychainIndex : 1 +5 KCMakeAliasFromKCRef + Input Arguments : 1 + KeychainIndex : 1 + Results : 2 + OSStatus 0 + AliasIndex : 0 +4 KCMakeKCRefFromAlias + Input Arguments : 1 + AliasIndex : 0 + Results : 2 + OSStatus 0 + KeychainIndex : 2 +19 KCGetKeychainName + Input Arguments : 1 + KeychainIndex : 2 + Results : 2 + OSStatus 0 + KeychainName : test0021.001 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 1 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0022 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0022 new file mode 100755 index 00000000..fe6c6c04 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0022 @@ -0,0 +1,170 @@ +// +// script0022 +// +// KCAddCallback +// KCRemoveCallback +// +// Add/remove callback for each event type +// +// kLockKCEvent +23 KCAddCallback + Input Arguments : 1 + KCEvent : 1 + Results : 1 + OSStatus 0 +// kUnlockEvent +23 KCAddCallback + Input Arguments : 1 + KCEvent : 2 + Results : 1 + OSStatus 0 +// kAddKCEvent +23 KCAddCallback + Input Arguments : 1 + KCEvent : 3 + Results : 1 + OSStatus 0 +// kDeleteKCEvent +23 KCAddCallback + Input Arguments : 1 + KCEvent : 4 + Results : 1 + OSStatus 0 +// kUpdateKCEvent +23 KCAddCallback + Input Arguments : 1 + KCEvent : 5 + Results : 1 + OSStatus 0 +// kChangeIdentityKCEvent +23 KCAddCallback + Input Arguments : 1 + KCEvent : 6 + Results : 1 + OSStatus 0 +// kFindKCEvent +23 KCAddCallback + Input Arguments : 1 + KCEvent : 7 + Results : 1 + OSStatus 0 +// kDefaultChangedKCEvent +23 KCAddCallback + Input Arguments : 1 + KCEvent : 9 + Results : 1 + OSStatus 0 +// kDataAccessKCEvent +23 KCAddCallback + Input Arguments : 1 + KCEvent : 10 + Results : 1 + OSStatus 0 +// kLockKCEvent (duplicate) +23 KCAddCallback + Input Arguments : 1 + KCEvent : 1 + Results : 1 + OSStatus -25297 +// +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0022.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 1 +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0022.002 + Results : 2 + OSStatus 0 + KeychainIndex : 2 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 2 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 3 +// +35 KCNewItem + Input Arguments : 4 + Class : inet + Creator : meme + Data : /17/Internet password + Results : 2 + OSStatus 0 + ItemIndex : 0 +// generate kLockKCEvent +10 KCLock + Input Arguments : 1 + KeychainIndex : 1 + Results : 1 + OSStatus 0 +// generate kUnlockKCEvent +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 1 + Password : Apple + Results : 1 + OSStatus 0 +// generate kDefaultChangedKCEvent +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 1 + Results : 1 + OSStatus 0 +// generate kAddKCEvent +41 KCAddItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +// generate kDataAccessKCEvent +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /50/00000000000000000000000000000000000000000000000000 + Results : 3 + OSStatus 0 + Data : /50/Internet password000000000000000000000000000000000 + ActualLength : 17 +// generate kUpdateKCEvent +38 KCSetData + Input Arguments : 2 + ItemIndex : 0 + Data : /3/Cat + Results : 1 + OSStatus 0 +45 KCUpdateItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +// generate kDeleteKCEvent +43 KCDeleteItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +// generate kLockKCEvent +10 KCLock + Input Arguments : 1 + KeychainIndex : 1 + Results : 1 + OSStatus 0 +// +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0023 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0023 new file mode 100755 index 00000000..f1c402f1 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0023 @@ -0,0 +1,43 @@ +// +// script0023 +// +// KCStatus +// +// Check lock state +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0023.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +// keychain is locked by default +// keychain is now unlocked +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +// status bitmask +// kcUnlockState 1 : unlocked +// kcRdPerm 2 : unlocked with read permission +// kcWrPerm 4 : unlocked with write permission +16 KCGetStatus + Input Arguments : 1 + KeychainIndex : 0 + Results : 2 + OSStatus 0 + KeychainStatus : 7 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0024 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0024 new file mode 100755 index 00000000..68b419a0 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0024 @@ -0,0 +1,33 @@ +// +// script0024 +// +// KCCreateKeychain +// KCSetInteractionAllowed +// KCGetInteractionAllowed +// +// Create a new keychain w/ and w/o interaction allowed enabled +// +25 KCSetInteractionAllowed + Input Arguments : 1 + AllowInteraction : 0 + Results : 1 + OSStatus 0 +26 KCIsInteractionAllowed + Input Arguments : 0 + Results : 2 + OSStatus 0 + AllowInteraction : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : -1 + Password : Apple + Results : 2 + OSStatus -25308 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : -1 + Password : Apple + Results : 2 + OSStatus -25308 + KeychainIndex : 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0025 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0025 new file mode 100755 index 00000000..263f8115 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0025 @@ -0,0 +1,59 @@ +// +// script0025 +// +// KCChangeSettings +// KCSetInteractionAllowed +// KCGetInteractionAllowed +// +// Change keychain settings w/ and w/o interaction allowed enabled +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0025.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +25 KCSetInteractionAllowed + Input Arguments : 1 + AllowInteraction : 0 + Results : 1 + OSStatus 0 +20 KCChangeSettings + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus -25308 +// taken out to avoid any UI for automation purposes +//25 KCSetInteractionAllowed +// Input Arguments : 1 +// AllowInteraction : 1 +// Results : 1 +// OSStatus 0 +//20 KCChangeSettings +// Input Arguments : 1 +// KeychainIndex : 0 +// Results : 1 +// OSStatus -128 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0026 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0026 new file mode 100644 index 00000000..6999d201 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0026 @@ -0,0 +1,68 @@ +// +// script0026 +// +// KCNewItem +// KCAddItemNoUI +// KCGetDataNoUI +// +// Create an Apple Share Password item & add it to a default Keychain +// +35 KCNewItem + Input Arguments : 4 + Class : ashp + Creator : meme + Data : /5/apple + Results : 2 + OSStatus 0 + ItemIndex : 0 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0026.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +15 KCCreateKeychainNoUI + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 +7 KCUnlockNoUI + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +42 KCAddItemNoUI + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /8/00000000 + Results : 3 + OSStatus 0 + Data : /8/apple000 + ActualLength : 5 +45 KCUpdateItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0026.000 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0026.000 new file mode 100644 index 00000000..e7f75d47 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0026.000 @@ -0,0 +1,44 @@ +// +// script0026.000 +// +// KCAddItemNoUI +// KCGetDataNoUI +// +// Check the item added in script0026 still exists +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0026.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 2 + .0 : + .tag : clas + .data : /4/ashp + .1 : + .tag : crtr + .data : /4/meme + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0026.001 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0026.001 new file mode 100644 index 00000000..6fdef795 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0026.001 @@ -0,0 +1,54 @@ +// +// script0026.001 +// +// KCAddItemNoUI +// KCGetDataNoUI +// +// Call KCGetDataNoUI (Apple Share Password) to a locked keychain +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0026.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +10 KCLock + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 2 + .0 : + .tag : clas + .data : /4/ashp + .1 : + .tag : crtr + .data : /4/meme + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0026.002 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0026.002 new file mode 100644 index 00000000..80160c5e --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0026.002 @@ -0,0 +1,42 @@ +// +// script0026.001 +// +// KCAddItemNoUI +// KCGetDataNoUI +// +// Call KCAddItemNoUI (Apple Share Password) to a locked keychain +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0026.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +10 KCLock + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +35 KCNewItem + Input Arguments : 4 + Class : ashp + Creator : meme + Data : /6/apple2 + Results : 2 + OSStatus 0 + ItemIndex : 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0027 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0027 new file mode 100644 index 00000000..bd9d843e --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0027 @@ -0,0 +1,68 @@ +// +// script0027 +// +// KCNewItem +// KCAddItemNoUI +// KCGetDataNoUI +// +// Create a Generic Password item & add it to a default Keychain +// +35 KCNewItem + Input Arguments : 4 + Class : genp + Creator : meme + Data : /50/First Generic password:abcdefghijklmnopqrstuvwxyz# + Results : 2 + OSStatus 0 + ItemIndex : 0 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0027.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +15 KCCreateKeychainNoUI + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 +7 KCUnlockNoUI + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +42 KCAddItemNoUI + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /50/00000000000000000000000000000000000000000000000000 + Results : 3 + OSStatus 0 + Data : /50/First Generic password:abcdefghijklmnopqrstuvwxyz# + ActualLength : 50 +45 KCUpdateItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0027.000 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0027.000 new file mode 100644 index 00000000..a218934f --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0027.000 @@ -0,0 +1,64 @@ +// +// script0027.000 +// +// KCNewItem +// KCAddItemNoUI +// KCGetDataNoUI +// +// Check the item added in script0027 still exists +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0027.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +7 KCUnlockNoUI + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 2 + .0 : + .tag : clas + .data : /4/genp + .1 : + .tag : crtr + .data : /4/meme + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /50/00000000000000000000000000000000000000000000000000 + Results : 3 + OSStatus 0 + Data : /50/First Generic password:abcdefghijklmnopqrstuvwxyz# + ActualLength : 50 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0027.001 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0027.001 new file mode 100644 index 00000000..550713bb --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0027.001 @@ -0,0 +1,55 @@ +// +// script0027.001 +// +// KCNewItem +// KCAddItemNoUI +// KCGetDataNoUI +// +// Call KCGetDataNoUI (Generic Password) to a locked keychain +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0027.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +10 KCLock + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 2 + .0 : + .tag : clas + .data : /4/genp + .1 : + .tag : crtr + .data : /4/meme + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0027.002 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0027.002 new file mode 100644 index 00000000..e2ec25b6 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0027.002 @@ -0,0 +1,43 @@ +// +// script0027.002 +// +// KCNewItem +// KCAddItemNoUI +// KCGetDataNoUI +// +// Call KCAddItemNoUI (Generic Password) to a locked keychain +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0027.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +10 KCLock + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +35 KCNewItem + Input Arguments : 4 + Class : genp + Creator : meme + Data : /23/Second Generic password + Results : 2 + OSStatus 0 + ItemIndex : 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0028 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0028 new file mode 100644 index 00000000..f5cc406b --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0028 @@ -0,0 +1,68 @@ +// +// script0028 +// +// KCNewItem +// KCAddItemNoUI +// KCGetDataNoUI +// +// Create a Internet Password item & add it to a default Keychain +// +35 KCNewItem + Input Arguments : 4 + Class : inet + Creator : meme + Data : /48/First Internet password:abcdefghijklmnopqrstuvwx + Results : 2 + OSStatus 0 + ItemIndex : 0 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0028.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +15 KCCreateKeychainNoUI + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 +7 KCUnlockNoUI + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +42 KCAddItemNoUI + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /50/00000000000000000000000000000000000000000000000000 + Results : 3 + OSStatus 0 + Data : /50/First Internet password:abcdefghijklmnopqrstuvwx00 + ActualLength : 48 +45 KCUpdateItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0028.000 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0028.000 new file mode 100644 index 00000000..142570fb --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0028.000 @@ -0,0 +1,63 @@ +// +// script0028.000 +// +// KCAddItemNoUI +// KCGetDataNoUI +// +// Check the item added in script0028 still exists +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0028.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 2 + .0 : + .tag : clas + .data : /4/inet + .1 : + .tag : crtr + .data : /4/meme + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /50/00000000000000000000000000000000000000000000000000 + Results : 3 + OSStatus 0 + Data : /50/First Internet password:abcdefghijklmnopqrstuvwx00 + ActualLength : 48 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0028.001 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0028.001 new file mode 100644 index 00000000..df61848f --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0028.001 @@ -0,0 +1,54 @@ +// +// script0028.001 +// +// KCAddItemNoUI +// KCGetDataNoUI +// +// Call KCGetDataNoUI (Internet Password) to a locked keychain +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0028.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +10 KCLock + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 2 + .0 : + .tag : clas + .data : /4/inet + .1 : + .tag : crtr + .data : /4/meme + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0028.002 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0028.002 new file mode 100644 index 00000000..575fdac8 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0028.002 @@ -0,0 +1,42 @@ +// +// script0028.002 +// +// KCAddItemNoUI +// KCGetDataNoUI +// +// Call KCAddItemNoUI (Internet Password) to a locked keychain +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0028.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +10 KCLock + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +35 KCNewItem + Input Arguments : 4 + Class : inet + Creator : meme + Data : /24/Second Internet password + Results : 2 + OSStatus 0 + ItemIndex : 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0029 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0029 new file mode 100644 index 00000000..09b3dce1 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0029 @@ -0,0 +1,73 @@ +// +// script0029 +// +// KCSetDataNo +// KCGetDataNoUI +// +// Create & Add an Apple Share Password item a default Keychain, then modify the data +// +35 KCNewItem + Input Arguments : 4 + Class : ashp + Creator : meme + Data : /5/Apple + Results : 2 + OSStatus 0 + ItemIndex : 0 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0029.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +15 KCCreateKeychainNoUI + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 +7 KCUnlockNoUI + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +42 KCAddItemNoUI + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +38 KCSetData + Input Arguments : 2 + ItemIndex : 0 + Data : /3/Dog + Results : 1 + OSStatus 0 +45 KCUpdateItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /5/00000 + Results : 3 + OSStatus 0 + Data : /5/Dog00 + ActualLength : 3 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0029.000 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0029.000 new file mode 100644 index 00000000..ca076280 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0029.000 @@ -0,0 +1,63 @@ +// +// script0029.000 +// +// KCSetDataNo +// KCGetDataNoUI +// +// Check the item added in script0029 still exists +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0029.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 2 + .0 : + .tag : clas + .data : /4/ashp + .1 : + .tag : crtr + .data : /4/meme + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /5/00000 + Results : 3 + OSStatus 0 + Data : /5/Dog00 + ActualLength : 3 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0030 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0030 new file mode 100644 index 00000000..d485bc9e --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0030 @@ -0,0 +1,73 @@ +// +// script0030 +// +// KCSetData +// KCGetDataNoUI +// +// Create & Add an Generic Password item a default Keychain, then modify the data +// +35 KCNewItem + Input Arguments : 4 + Class : genp + Creator : meme + Data : /50/First Generic password:abcdefghijklmnopqrstuvwxyz# + Results : 2 + OSStatus 0 + ItemIndex : 0 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0030.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +15 KCCreateKeychainNoUI + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 +7 KCUnlockNoUI + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +42 KCAddItemNoUI + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +38 KCSetData + Input Arguments : 2 + ItemIndex : 0 + Data : /3/Cat + Results : 1 + OSStatus 0 +45 KCUpdateItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /3/000 + Results : 3 + OSStatus 0 + Data : /3/Cat + ActualLength : 3 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0030.000 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0030.000 new file mode 100644 index 00000000..98f08c06 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0030.000 @@ -0,0 +1,63 @@ +// +// script0030.000 +// +// KCSetData +// KCGetDataNoUI +// +// Check the item added in script0030 still exists +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0030.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 2 + .0 : + .tag : clas + .data : /4/genp + .1 : + .tag : crtr + .data : /4/meme + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /3/000 + Results : 3 + OSStatus 0 + Data : /3/Cat + ActualLength : 3 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0031 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0031 new file mode 100644 index 00000000..035cafe6 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0031 @@ -0,0 +1,73 @@ +// +// script0031 +// +// KCSetData +// KCGetDataNoUI +// +// Create & Add an Internet Password item a default Keychain, then modify the data +// +35 KCNewItem + Input Arguments : 4 + Class : inet + Creator : meme + Data : /48/First Internet password:abcdefghijklmnopqrstuvwx + Results : 2 + OSStatus 0 + ItemIndex : 0 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0031.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +15 KCCreateKeychainNoUI + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 +7 KCUnlockNoUI + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +42 KCAddItemNoUI + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +38 KCSetData + Input Arguments : 2 + ItemIndex : 0 + Data : /6/Monkey + Results : 1 + OSStatus 0 +45 KCUpdateItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /6/000000 + Results : 3 + OSStatus 0 + Data : /6/Monkey + ActualLength : 6 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0031.000 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0031.000 new file mode 100644 index 00000000..c9a1a0dc --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0031.000 @@ -0,0 +1,63 @@ +// +// script0031.000 +// +// KCSetData +// KCGetDataNoUI +// +// Check the item added in script0031 still exists +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0031.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +48 KCFindFirstItem + Input Arguments : 2 + KeychainIndex : 0 + AttributeList : + .count : 2 + .0 : + .tag : clas + .data : /4/inet + .1 : + .tag : crtr + .data : /4/meme + Results : 3 + OSStatus 0 + SearchIndex : 0 + ItemIndex : 0 +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /6/000000 + Results : 3 + OSStatus 0 + Data : /6/Monkey + ActualLength : 6 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +50 KCReleaseSearch + Input Arguments : 1 + SearchIndex : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0032 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0032 new file mode 100644 index 00000000..c7e6ac94 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0032 @@ -0,0 +1,23 @@ +// +// script00032 +// +// KCLogin +// KCChangeLoginPassword +// KCLogout +// +64 KCLogin + Input Arguments : 2 + Name : LoginKC + Password : Craig + Results : 1 + OSStatus 0 +66 KCChangeLoginPassword + Input Arguments : 2 + OldPassword : Craig + NewPassword : Craig2 + Results : 1 + OSStatus 0 +65 KCLogout + Input Arguments : 0 + Results : 1 + OSStatus 0 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0033 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0033 new file mode 100644 index 00000000..c49f2836 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0033 @@ -0,0 +1,64 @@ +// +// script0033 +// +// KCNewItem +// KCAddItem +// KCGetData +// +// Create a Generic Password item & add it to a default Keychain twice +// Also create new item that is identical and see if it can be added. +35 KCNewItem + Input Arguments : 4 + Class : genp + Creator : meme + Data : /50/First Generic password:abcdefghijklmnopqrstuvwxyz# + Results : 2 + OSStatus 0 + ItemIndex : 0 +35 KCNewItem + Input Arguments : 4 + Class : genp + Creator : meme + Data : /50/First Generic password:abcdefghijklmnopqrstuvwxyz# + Results : 2 + OSStatus 0 + ItemIndex : 1 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0033.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +41 KCAddItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +41 KCAddItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus -25299 +41 KCAddItem + Input Arguments : 1 + ItemIndex : 1 + Results : 1 + OSStatus -25299 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0034 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0034 new file mode 100644 index 00000000..4ea97534 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0034 @@ -0,0 +1,65 @@ +// +// script0025 +// +// KCChangeSettings +// KCSetInteractionAllowed +// KCGetInteractionAllowed +// +// Change keychain settings w/ and w/o interaction allowed enabled +// +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0034.000 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +25 KCSetInteractionAllowed + Input Arguments : 1 + AllowInteraction : 0 + Results : 1 + OSStatus 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +20 KCChangeSettings + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus -25308 +25 KCSetInteractionAllowed + Input Arguments : 1 + AllowInteraction : 0 + Results : 1 + OSStatus 0 +26 KCIsInteractionAllowed + Input Arguments : 0 + Results : 2 + OSStatus 0 + AllowInteraction : 0 +20 KCChangeSettings + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus -25308 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 + + diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0035 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0035 new file mode 100644 index 00000000..817f11c4 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0035 @@ -0,0 +1,98 @@ +35 KCNewItem + Input Arguments : 4 + Class : ashp + Creator : meme + Data : /5/apple + Results : 2 + OSStatus 0 + ItemIndex : 0 +35 KCNewItem + Input Arguments : 4 + Class : ashp + Creator : meme + Data : /5/apple + Results : 2 + OSStatus 0 + ItemIndex : 1 +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0035.001 + Results : 2 + OSStatus 0 + KeychainIndex : 0 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 0 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 0 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +41 KCAddItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 + + +3 KCMakeKCRefFromFSSpec + Input Arguments : 1 + KeychainFile : test0035.002 + Results : 2 + OSStatus 0 + KeychainIndex : 1 +14 KCCreateKeychain + Input Arguments : 2 + KeychainIndex : 2 + Password : Apple + Results : 2 + OSStatus 0 + KeychainIndex : 2 +8 KCUnlock + Input Arguments : 2 + KeychainIndex : 1 + Password : Apple + Results : 1 + OSStatus 0 +13 KCSetDefaultKeychain + Input Arguments : 1 + KeychainIndex : 2 + Results : 1 + OSStatus 0 +41 KCAddItem + Input Arguments : 1 + ItemIndex : 1 + Results : 1 + OSStatus 0 + +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +46 KCReleaseItem + Input Arguments : 1 + ItemIndex : 1 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 0 + Results : 1 + OSStatus 0 +6 KCReleaseKeychain + Input Arguments : 2 + KeychainIndex : 2 + Results : 1 + OSStatus 0 + diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0036 b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0036 new file mode 100644 index 00000000..e1b79ce0 --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/scripts/script0036 @@ -0,0 +1,35 @@ +// +// script0036 - designed to run after the default keychain DELETED from disk +// +// KCNewItem +// KCAddItem +// KCGetData +// +// Attempt to add an AppleShare password to the default keychain +// - If there aren't any keychains available, a panel will ask you to create one. +// - If default is deleted, a panel appears asking to select a different +// keychain or create a new one for the item (here you can change the default too). +// +35 KCNewItem + Input Arguments : 4 + Class : ashp + Creator : cind + Data : /8/CindyLou + Results : 2 + OSStatus 0 + ItemIndex : 0 +41 KCAddItem + Input Arguments : 1 + ItemIndex : 0 + Results : 1 + OSStatus 0 +// +## Chose a keychain or create one, then hit 'Select' ## +39 KCGetData + Input Arguments : 2 + ItemIndex : 0 + Data : /8/00000000 + Results : 3 + OSStatus 0 + Data : /8/CindyLou + ActualLength : 5 diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI/testKeychainAPI.cpp b/SecurityTests/testKeychainAPI/testKeychainAPI/testKeychainAPI.cpp new file mode 100644 index 00000000..dbdead3d --- /dev/null +++ b/SecurityTests/testKeychainAPI/testKeychainAPI/testKeychainAPI.cpp @@ -0,0 +1,476 @@ +#include "KCAPI_Keychain.h" +#include "KCAPI_Manager.h" +#include "testKeychainAPI.h" +#include "Radar.h" +#include + +#if TARGET_RT_MAC_MACHO + #include + #include + #include +#else + #include + #include + #include + static void GetArg(int &outArgc, char** &outArgv); +#endif + +static char* gResourcePath = NULL; +static char* GetResourcePath(char**argv); +static int gSleep=0; + +#ifndef TEST_SCRIPT_PATH + #define TEST_SCRIPT_PATH (getenv("TESTKEYCHAINAPI_TEST_SCRIPT_PATH") ? getenv("TESTKEYCHAINAPI_TEST_SCRIPT_PATH") : gResourcePath) +#endif + + +int main(int argc, char** argv) +{ + +#if defined(__MWERKS__) + // Set SIOUX window position to top left corner + // so that Security Dialogs will not cover the + // window + SIOUXSettings.toppixel = 40; + SIOUXSettings.leftpixel = 5; + + // emulate argc, argv + GetArg(argc, argv); +#endif + + gResourcePath = GetResourcePath(argv); + + try{ + CTestApp aTestApp(argc, argv); + aTestApp.Run(); + } + catch(const char *inErrorMsg){ + fprintf(stderr, "ERROR : %s\n", inErrorMsg); + } + + if(gSleep) + { + fprintf(stderr, "\n-----> sleeping...\n"); + sleep(60000); + } + +} + +CTestApp::CTestApp( + int inArgc, + char ** inArgv) + :mArgc(inArgc), mArgv(inArgv), + mVerbose(false), mRelaxErrorChecking(false) +{ +} + +void +CTestApp::Run() +{ + int ch; + bool didWork = false; + const char *options = "hH?vlew:f:r:R:n:s:S"; + +#if TARGET_RT_MAC_MACHO + extern char * optarg; + while ((ch = getopt(mArgc, mArgv, options)) != -1){ +#else + char * optarg = NULL; + for(int i=1; i -> -> Running script%04ld ...\n", i); + DoRunScript(aInput, aPass, aFail); + aPassCount += aPass; + aFailCount += aFail; + fclose(aInput); + } + } + } + else{ + +#if TARGET_RT_MAC_MACHO + sprintf(aFullPath, "%s//script%04d", TEST_SCRIPT_PATH, atoi(inScriptNo)); +#else + sprintf(aFullPath, "%s:script%04d", TEST_SCRIPT_PATH, atoi(inScriptNo)); +#endif + + if((aInput = fopen(aFullPath, "r")) != NULL){ + DoRunScript(aInput, aPassCount, aFailCount); + fclose(aInput); + } + else{ + fprintf(stderr, "No script file for [%s]\n", inScriptNo); + return; + } + } + + printf("Total number of test cases executed %ld : (passed = %ld, failed = %ld)\n", aPassCount+aFailCount, aPassCount, aFailCount); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ DoRunSubTestScript +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +void +CTestApp::DoRunSubTestScript( + const char * inScriptNo) +{ + FILE *aInput; + char aFullPath[256]; + UInt32 aPassCount = 0; + UInt32 aFailCount = 0; + UInt32 aStartScript = 0; + UInt32 aEndScript = 50; /* 9999 */ + + // not "all" - run the specified test case's sub-test cases + if(strcmp(inScriptNo, "all")){ + aStartScript = aEndScript = atoi(inScriptNo); + } + + for(UInt32 j=aStartScript; j<=aEndScript; j++){ + for(UInt32 i=0; i<5 /*999*/; i++){ +#if TARGET_RT_MAC_MACHO + sprintf(aFullPath, "%s//script%04ld.%03ld", TEST_SCRIPT_PATH, j, i); +#else + sprintf(aFullPath, "%s:script%04ld.%03ld", TEST_SCRIPT_PATH, j, i); +#endif + + if((aInput = fopen(aFullPath, "r")) != NULL){ + UInt32 aPass, aFail; + if(mVerbose) printf("\n\n-> -> -> Running script%04ld.%03ld ...\n", j, i); + DoRunScript(aInput, aPass, aFail); + aPassCount += aPass; + aFailCount += aFail; + fclose(aInput); + } + } + } + + printf("Total number of test cases executed %ld : (passed = %ld, failed = %ld)\n", aPassCount+aFailCount, aPassCount, aFailCount); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ DoRunScript +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +void +CTestApp::DoRunScript( + const char *inPath, + UInt32 &outPass, + UInt32 &outFail) +{ + Cleanup(); + + FILE *aInput = fopen(inPath, "r"); + if(aInput == NULL){ + fprintf(stderr, "ERROR Cannot open the file %s\n", inPath); + return; + } + DoRunScript(aInput, outPass, outFail); + fclose(aInput); +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ DoRunScript +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +void +CTestApp::DoRunScript( + FILE *inFile, + UInt32 &outPass, + UInt32 &outFail) +{ + Cleanup(); + + eKCOperationID aID; + UInt32 aPassCount = 0; + UInt32 aFailCount = 0; + + try{ + while(KCOperation::ReadScript(inFile, aID) != EOF){ + KCOperation *aOperation = (KCOperation*)COpRegister::CreateOperation(aID, this); + if(aOperation == NULL){ + fprintf(stderr, "ERROR COpRegister::CreateOperation(%d) failed\n", aID); + break; + } + + bool aResult = aOperation->RunScript(inFile); + aPassCount += (aResult) ? 1 : 0; + aFailCount += (!aResult) ? 1 : 0; + if(mVerbose){ + printf("TestCase No.%04ld (%s): %s\n", aPassCount+aFailCount, COpRegister::GetOperationName(aID), (aResult) ? "PASSED" : "FAILED"); + if(!aResult){ + fprintf(stdout, "%d %s\n", aID, COpRegister::GetOperationName(aID)); + aOperation->WriteResults(stdout); + } + } + delete aOperation; + } + } + catch(const char *inErrorMsg){ + fprintf(stderr, "ERROR : %s\n", inErrorMsg); + fprintf(stderr, " Terminating this script\n"); + } + + outPass = aPassCount; + outFail = aFailCount; + +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ DoDumpScript +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +void +CTestApp::DoDumpScript( + const char *inOperationNo) +{ + FILE *aOutput = stdout; + bool aDoAll = (strcmp(inOperationNo, "all") == 0); + + for(long i=0; iOperate(); + aOperation->WriteScript(aOutput); + delete aOperation; + } + } +} + + + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ DoRadar +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +void +CTestApp::DoRadar( + const char *inArg) +{ + UInt32 i=0; + + // -l (list all Radar bug descriptions) + if(inArg == NULL){ + while(gRadarBugs[i].testCaseFunc){ + printf("%s %s\n", gRadarBugs[i].ID, gRadarBugs[i].desc); + i++; + } + } + // -r all (run all Radar bugs) + else if(!strcmp(inArg, "all")){ + while(gRadarBugs[i].testCaseFunc){ + printf(">>>>>>>>>> Radar %s >>>>>>>>>>\n", gRadarBugs[i].ID); + printf("%s\n", gRadarBugs[i].desc); + (gRadarBugs[i].testCaseFunc)(this); + printf("<<<<<<<<<< Radar %s done <<<<<<<<<<\n\n", gRadarBugs[i].ID); + + i++; + } + } + // -r nnnnn (run a specific Radar bug) + else{ + while(gRadarBugs[i].testCaseFunc){ + if(!strcmp(inArg, gRadarBugs[i].ID)){ + (gRadarBugs[i].testCaseFunc)(this); + return; + } + i++; + } + fprintf(stderr, "No such Radar ID\n"); + DoRadar(NULL); + } +} + +void +CTestApp::Cleanup() +{ + KCOperation::Cleanup(); + KCItemOperation::Cleanup(); + KCSearchOperation::Cleanup(); +} + +#if TARGET_RT_MAC_MACHO +char* +GetResourcePath(char **inArgv) +{ + // Can I do better than this ? + const char *aResourcesDir = "../Resources/"; + const char *progname; + char *aResourcePath = NULL; + int len; + + progname = strrchr(inArgv[0], '/'); + len = (progname) ? (strlen(inArgv[0]) - strlen(progname)+1) : 0; + aResourcePath = new char[len + strlen(aResourcesDir)+1]; + if(len) memcpy(aResourcePath, inArgv[0], len); + memcpy(aResourcePath+len, aResourcesDir, strlen(aResourcesDir)); + aResourcePath[len+strlen(aResourcesDir)] = '\0'; + return(aResourcePath); +} +#else +char* +GetResourcePath(char **inArgv) +{ + // ¥¥¥ temp solution + return("Work:CVS Project:Security:Tests:testKeychainAPI:testKeychainAPI:scripts"); +} + +void GetArg( + int &outArgc, + char** &outArgv) +{ + // emulate the command line arg + const char *kProgname = "testKeychainAPI"; + char *aBuffer = new char[1024]; + + memset(aBuffer, 0, 1024); + strcpy(aBuffer, kProgname); + int i = strlen(kProgname)+1; + + cout << kProgname << " "; + cin.getline(aBuffer+i, 1024-i); + for(; i<1028; i++) if(aBuffer[i] == ' ') aBuffer[i] = '\0'; + + int j = 0; + char *p = aBuffer; + char **argv = new char*[128]; + do{ + if(strlen(p) > 0) argv[j++] = p; + p += strlen(p)+1; + } while(p < aBuffer+1024); + + outArgc = j; + outArgv = argv; +} + +char* +UNIX_fgets( + char *inBuffer, + int inSize, + FILE *inFile) +{ + // Scripts are in UNIX format + // so fgets() does not work on ClassicMac + // as is + for(int i=0; i 4/18/00 em Created. +// ====================================================================== + +#ifndef __TESTKEYCHAINAPI__ +#define __TESTKEYCHAINAPI__ + +#include +#include +#undef check + +class CTestApp{ +public: + CTestApp( + int inArgc, + char ** inArgv); + + virtual void Run(); + + virtual void DoRunScript( + const char *inPath, + UInt32 &outPass, + UInt32 &outFail); + + virtual void DoRunScript( + FILE *inFile, + UInt32 &outPass, + UInt32 &outFail); + + virtual void DoRunTestScript( + const char *inScriptNo); + + virtual void DoRunSubTestScript( + const char * inScriptNo); + + virtual void DoDumpScript( + const char *inOperationNo); + + virtual void DoRadar( + const char *inBugNo); + + virtual void Cleanup(); + + bool IsVerbose(){ return mVerbose; } + bool IsRelaxErrorChecking(){ return mRelaxErrorChecking; } +protected: + int mArgc; + char ** mArgv; + bool mVerbose; + bool mRelaxErrorChecking; + +}; + +#if TARGET_RT_MAC_MACHO + #define UNIX_fgets(a, b, c) fgets(a, b, c) +#else + #define UNIX_fgets(a, b, c) UNIXfgets(a, b, c) + char* UNIX_fgets(char *inBuffer, int inSize, FILE *inFile); +#endif + +#endif diff --git a/SecurityTests/testKeychainAPI/testKeychainAPI_user_manual.cwk b/SecurityTests/testKeychainAPI/testKeychainAPI_user_manual.cwk new file mode 100644 index 0000000000000000000000000000000000000000..163480e8efa8912e5e83edfb8e5c028654a08dfc GIT binary patch literal 115775 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 Zng4wC^bfxO|GjeR#sBzD_R>e&|9{i0NnQW| literal 0 HcmV?d00001 diff --git a/SecurityTests/testclient/attributes.cpp b/SecurityTests/testclient/attributes.cpp new file mode 100644 index 00000000..6fa036dc --- /dev/null +++ b/SecurityTests/testclient/attributes.cpp @@ -0,0 +1,78 @@ +#include "attributes.h" + +//#include +//#include + +#include +// -------------------------------------------------------------------- +// Attribute initializations +//-------------------------------------------------------------------- + +// Meta Attributes +CSSM_DB_NAME_ATTR(Attributes::RelationID, 0, "RelationID", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::RelationName, 1, "RelationName", 0, NULL, STRING); +CSSM_DB_NAME_ATTR(Attributes::AttributeID, 1, "AttributeID", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::AttributeNameFormat, 2, "AttributeNameFormat", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::AttributeName, 3, "AttributeName", 0, NULL, STRING); +CSSM_DB_NAME_ATTR(Attributes::AttributeNameID, 4, "AttributeNameID", 0, NULL, BLOB); +CSSM_DB_NAME_ATTR(Attributes::AttributeFormat, 5, "AttributeFormat", 0, NULL, UINT32); + +// Keychain Attributes. +//CSSM_DB_INTEGER_ATTR(Attributes::Protected, kProtectedDataKCItemAttr, "Protected", 0, NULL, BLOB); +CSSM_DB_INTEGER_ATTR(Attributes::Class, kClassKCItemAttr, "Class", 0, NULL, BLOB); +CSSM_DB_INTEGER_ATTR(Attributes::CreationDate, kCreationDateKCItemAttr, "CreationDate", 0, NULL, BLOB); +CSSM_DB_INTEGER_ATTR(Attributes::ModDate, kModDateKCItemAttr, "ModDate", 0, NULL, BLOB); +CSSM_DB_INTEGER_ATTR(Attributes::Description, kDescriptionKCItemAttr, "Description", 0, NULL, BLOB); +CSSM_DB_INTEGER_ATTR(Attributes::Comment, kCommentKCItemAttr, "Comment", 0, NULL, BLOB); +CSSM_DB_INTEGER_ATTR(Attributes::Creator, kCreatorKCItemAttr, "Creator", 0, NULL, BLOB); +CSSM_DB_INTEGER_ATTR(Attributes::Type, kTypeKCItemAttr, "Type", 0, NULL, BLOB); +CSSM_DB_INTEGER_ATTR(Attributes::ScrCode, kScriptCodeKCItemAttr, "ScriptCode", 0, NULL, BLOB); +CSSM_DB_INTEGER_ATTR(Attributes::Label, kLabelKCItemAttr, "Label", 0, NULL, BLOB); +CSSM_DB_INTEGER_ATTR(Attributes::Invisible, kInvisibleKCItemAttr, "Invisible", 0, NULL, BLOB); +CSSM_DB_INTEGER_ATTR(Attributes::Negative, kNegativeKCItemAttr, "Negative", 0, NULL, BLOB); +CSSM_DB_INTEGER_ATTR(Attributes::Custom, kCustomIconKCItemAttr, "CustomIcon", 0, NULL, BLOB); +// for Generic Password items: +CSSM_DB_INTEGER_ATTR(Attributes::Account, kAccountKCItemAttr, "Account", 0, NULL, BLOB); +CSSM_DB_INTEGER_ATTR(Attributes::Service, kServiceKCItemAttr, "Service", 0, NULL, BLOB); +CSSM_DB_INTEGER_ATTR(Attributes::Generic, kGenericKCItemAttr, "Generic", 0, NULL, BLOB); +// for Internet Password items: +CSSM_DB_INTEGER_ATTR(Attributes::SecDomain, kSecurityDomainKCItemAttr, "SecurityDomain", 0, NULL, BLOB); +CSSM_DB_INTEGER_ATTR(Attributes::Server, kServerKCItemAttr, "Server", 0, NULL, BLOB); +CSSM_DB_INTEGER_ATTR(Attributes::AuthType, kAuthTypeKCItemAttr, "AuthType", 0, NULL, BLOB); +CSSM_DB_INTEGER_ATTR(Attributes::Port, kPortKCItemAttr, "Port", 0, NULL, BLOB); +CSSM_DB_INTEGER_ATTR(Attributes::Path, kPathKCItemAttr, "Path", 0, NULL, BLOB); +// for AppleShare Password items: +CSSM_DB_INTEGER_ATTR(Attributes::Volume, kVolumeKCItemAttr, "Volume", 0, NULL, BLOB); +CSSM_DB_INTEGER_ATTR(Attributes::Addr, kAddressKCItemAttr, "Address", 0, NULL, BLOB); +CSSM_DB_INTEGER_ATTR(Attributes::Signature, kSignatureKCItemAttr, "Signature", 0, NULL, BLOB); +// for AppleShare and Interent Password items: +CSSM_DB_INTEGER_ATTR(Attributes::ProtocolType, kProtocolKCItemAttr, "Protocol", 0, NULL, BLOB); + +// Key Attributes +CSSM_DB_NAME_ATTR(Attributes::KeyClass, 0, "KeyClass", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::PrintName, 1, "PrintName", 0, NULL, BLOB); +CSSM_DB_NAME_ATTR(Attributes::Alias, 2, "Alias", 0, NULL, BLOB); +CSSM_DB_NAME_ATTR(Attributes::Permanent, 3, "Permanent", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::Private, 4, "Private", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::Modifiable, 5, "Modifiable", 0, NULL, UINT32); +//CSSM_DB_NAME_ATTR(Attributes::Label, 6, "Label", 0, NULL, BLOB); +CSSM_DB_NAME_ATTR(Attributes::ApplicationTag, 7, "ApplicationTag", 0, NULL, BLOB); +CSSM_DB_NAME_ATTR(Attributes::KeyCreator, 8, "KeyCreator", 0, NULL, BLOB); +CSSM_DB_NAME_ATTR(Attributes::KeyType, 9, "KeyType", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::KeySizeInBits, 10, "KeySizeInBits", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::EffectiveKeySize, 11, "EffectiveKeySize", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::StartDate, 12, "StartDate", 0, NULL, TIME_DATE); +CSSM_DB_NAME_ATTR(Attributes::EndDate, 13, "EndDate", 0, NULL, TIME_DATE); +CSSM_DB_NAME_ATTR(Attributes::Sensitive, 14, "Sensitive", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::AlwaysSensitive, 15, "AlwaysSensitive", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::Extractable, 16, "Extractable", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::NeverExtractable, 17, "NeverExtractable", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::Encrypt, 18, "Encrypt", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::Decrypt, 19, "Decrypt", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::Derive, 20, "Derive", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::Sign, 21, "Sign", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::Verify, 22, "Verify", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::SignRecover, 23, "SignRecover", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::VerifyRecover, 24, "VerifyRecover", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::Wrap, 25, "Wrap", 0, NULL, UINT32); +CSSM_DB_NAME_ATTR(Attributes::UnWrap, 26, "UnWrap", 0, NULL, UINT32); diff --git a/SecurityTests/testclient/attributes.h b/SecurityTests/testclient/attributes.h new file mode 100644 index 00000000..2ff76737 --- /dev/null +++ b/SecurityTests/testclient/attributes.h @@ -0,0 +1,76 @@ +#include + +class Attributes +{ +public: + // Meta Attributes. + CSSM_DB_ATTR_DECL(RelationID); + CSSM_DB_ATTR_DECL(RelationName); + CSSM_DB_ATTR_DECL(AttributeID); + CSSM_DB_ATTR_DECL(AttributeNameFormat); + CSSM_DB_ATTR_DECL(AttributeName); + CSSM_DB_ATTR_DECL(AttributeNameID); + CSSM_DB_ATTR_DECL(AttributeFormat); + + // Keychain Attributes + CSSM_DB_ATTR_DECL(Protected); + CSSM_DB_ATTR_DECL(Class); + CSSM_DB_ATTR_DECL(CreationDate); + CSSM_DB_ATTR_DECL(ModDate); + CSSM_DB_ATTR_DECL(Description); + CSSM_DB_ATTR_DECL(Comment); + CSSM_DB_ATTR_DECL(Creator); + CSSM_DB_ATTR_DECL(Type); + CSSM_DB_ATTR_DECL(ScrCode); + CSSM_DB_ATTR_DECL(Label); + CSSM_DB_ATTR_DECL(Invisible); + CSSM_DB_ATTR_DECL(Negative); + CSSM_DB_ATTR_DECL(Custom); + // for Generic Password items: + CSSM_DB_ATTR_DECL(Account); + CSSM_DB_ATTR_DECL(Service); + CSSM_DB_ATTR_DECL(Generic); + // for Internet Password items: + CSSM_DB_ATTR_DECL(SecDomain); + CSSM_DB_ATTR_DECL(Server); + CSSM_DB_ATTR_DECL(AuthType); + CSSM_DB_ATTR_DECL(Port); + CSSM_DB_ATTR_DECL(Path); + // for AppleShare Password items: + CSSM_DB_ATTR_DECL(Volume); + CSSM_DB_ATTR_DECL(Addr); + CSSM_DB_ATTR_DECL(Signature); + // for AppleShare and Interent Password items: + CSSM_DB_ATTR_DECL(ProtocolType); + + // For keys + CSSM_DB_ATTR_DECL(KeyClass); + CSSM_DB_ATTR_DECL(PrintName); + CSSM_DB_ATTR_DECL(Alias); + CSSM_DB_ATTR_DECL(Permanent); + CSSM_DB_ATTR_DECL(Private); + CSSM_DB_ATTR_DECL(Modifiable); + //CSSM_DB_ATTR_DECL(Label); + CSSM_DB_ATTR_DECL(ApplicationTag); + CSSM_DB_ATTR_DECL(KeyCreator); + CSSM_DB_ATTR_DECL(KeyType); + CSSM_DB_ATTR_DECL(KeySizeInBits); + CSSM_DB_ATTR_DECL(EffectiveKeySize); + CSSM_DB_ATTR_DECL(StartDate); + CSSM_DB_ATTR_DECL(EndDate); + CSSM_DB_ATTR_DECL(Sensitive); + CSSM_DB_ATTR_DECL(AlwaysSensitive); + CSSM_DB_ATTR_DECL(Extractable); + CSSM_DB_ATTR_DECL(NeverExtractable); + CSSM_DB_ATTR_DECL(Encrypt); + CSSM_DB_ATTR_DECL(Decrypt); + CSSM_DB_ATTR_DECL(Derive); + CSSM_DB_ATTR_DECL(Sign); + CSSM_DB_ATTR_DECL(Verify); + CSSM_DB_ATTR_DECL(SignRecover); + CSSM_DB_ATTR_DECL(VerifyRecover); + CSSM_DB_ATTR_DECL(Wrap); + CSSM_DB_ATTR_DECL(UnWrap); +private: + static const CSSM_OID noOID; +}; diff --git a/SecurityTests/testclient/csptests.cpp b/SecurityTests/testclient/csptests.cpp new file mode 100644 index 00000000..ac1b575c --- /dev/null +++ b/SecurityTests/testclient/csptests.cpp @@ -0,0 +1,210 @@ +#include "csptests.h" + +#include +#include +#include +#include +#include + +using namespace CssmClient; + +static void testCrypt(const Guid &cspGuid); +static void testDigests(const Guid &cspGuid); +static void testRandom(const Guid &cspGuid); +static void testMac(const Guid &cspGuid); +static void testWrap(const Guid &cspGuid); + + +void csptests() +{ + testCrypt(gGuidAppleCSP); + testCrypt(gGuidAppleCSPDL); + testDigests(gGuidAppleCSP); + testRandom(gGuidAppleCSP); + testRandom(gGuidAppleCSPDL); + testMac(gGuidAppleCSP); + testMac(gGuidAppleCSPDL); +} + +void testmac() +{ + testMac(gGuidAppleCSP); +} + +void testwrap() +{ + testWrap(gGuidAppleCSP); +} + +static void testCrypt(const Guid &cspGuid) +{ + printf("\n* performing encrypt/decrypt test...\n"); + + CSP csp(cspGuid); + + printf("Generating key\n"); + GenerateKey genKey(csp, CSSM_ALGID_DES, 64); + Key key = genKey(KeySpec(CSSM_KEYUSE_ANY, CSSM_KEYATTR_RETURN_DEFAULT)); + printf("done\n"); + + // Gnerate IV + printf("Generating iv\n"); + //CssmData iv = Random(csp, CSSM_ALGID_SHARandom)(8); + CssmPolyData iv("12345678"); + + CssmPolyData in("Om mani padme hum"); + printf("input="); + dump(in); + + // Encrypt + printf("Encrypting\n"); + + Encrypt encrypt(csp, CSSM_ALGID_DES); + encrypt.mode(CSSM_ALGMODE_CBCPadIV8); + encrypt.padding(CSSM_PADDING_PKCS1); + encrypt.initVector(iv); + encrypt.key(key); + CssmData cipher; + CssmData remcipher; + encrypt.encrypt(&in, 1, &cipher, 1); + encrypt.final(remcipher); + printf("ciphertext="); + dump(cipher); + printf("remainder="); + dump(remcipher); + + // Decrypt + printf("Decrypting\n"); + + Decrypt decrypt(csp, CSSM_ALGID_DES); + decrypt.key(key); + decrypt.mode(CSSM_ALGMODE_CBCPadIV8); + decrypt.padding(CSSM_PADDING_PKCS1); + decrypt.initVector(iv); + CssmData plain; + CssmData remplain; + CssmData inp[] = { cipher, remcipher }; + decrypt.decrypt(inp, 2, &plain, 1); + decrypt.final(remplain); + printf("plaintext="); + dump(plain); + printf("remainder="); + dump(remplain); + + printf("end encrypt/decrypt test\n"); +} + +static void testDigests(const Guid &cspGuid) +{ + printf("\n* performing digest test...\n"); + CSP csp(cspGuid); + Digest md5(csp, CSSM_ALGID_MD5); + StringData data("Once in a blue moon"); + DataBuffer<20> digest; + md5.digest(data, digest); + printf("digest="); + dump(digest); +} + + +static void testRandom(const Guid &cspGuid) +{ + printf("\n* performing random test...\n"); + CSP csp(cspGuid); + CssmData result = Random(csp, CSSM_ALGID_APPLE_YARROW)(16); + assert(result.length() == 16); + printf("result="); + dump(result); + free(result.data()); +} + + +void dump(const CssmData &data) +{ + unsigned char *p = data; + for (uint32 n = 0; n < data.length(); n++) + printf("%2.2x", p[n]); + printf("\n"); +} + +static void testMac(const Guid &cspGuid) +{ + printf("\n* performing mac test...\n"); + + CssmData keyData; + keyData.Length = 8; + keyData.Data = (uint8 *)"1234567"; + + CSP csp(cspGuid); + + Key key(csp, keyData); + + printf("Generating key\n"); + GenerateKey genKey(csp, CSSM_ALGID_DES, 64); + key = genKey(KeySpec(CSSM_KEYUSE_ANY, CSSM_KEYATTR_RETURN_DEFAULT)); + printf("done\n"); + + GenerateMac mac(csp, CSSM_ALGID_SHA1HMAC); + mac.key(key); + StringData data("Om mani padme hum"); + DataBuffer<20> signature; + mac.sign(data, signature); + printf("signature="); + dump(signature); + + VerifyMac vmac(csp, CSSM_ALGID_SHA1HMAC); + vmac.key(key); + vmac.verify(data, signature); + printf("testing mac verify\n"); + + bool failed = false; + try + { + printf("testing mac verify with bad data\n"); + StringData baddata("not even close to the original"); + vmac.verify(baddata, signature); + } + catch(const CssmError &e) + { + printf("caught verify error\n"); + failed = true; + if (e.osStatus() != CSSMERR_CSP_VERIFY_FAILED) + throw; + } + if (!failed) throw Error(CSSMERR_CSP_VERIFY_FAILED); + + printf("end mac test\n"); +} + +static void testWrap(const Guid &cspGuid) +{ + printf("\n* performing wrap test...\n"); + + CssmData keyData; + keyData.Length = 8; + keyData.Data = (uint8 *)"1234567"; + + CSP csp(cspGuid); + + Key key(csp, keyData); + + Key wrappedKey; + GenerateKey genKey(csp, CSSM_ALGID_RC4, 128); + key = genKey(KeySpec(CSSM_KEYUSE_ANY, CSSM_KEYATTR_RETURN_DEFAULT)); + + WrapKey wrapKey(csp, CSSM_ALGID_RC2); + wrapKey.key(key); + + AccessCredentials(cred); + wrapKey.cred(&cred); + wrapKey.mode(CSSM_ALGMODE_CBC_IV8); + CssmData initVec; + initVec.Length = 8; + initVec.Data = (uint8 *)"12345678"; + wrapKey.initVector(initVec); + + wrappedKey=wrapKey(key); + + + printf("end wrap test\n"); +} diff --git a/SecurityTests/testclient/csptests.h b/SecurityTests/testclient/csptests.h new file mode 100644 index 00000000..51f1b561 --- /dev/null +++ b/SecurityTests/testclient/csptests.h @@ -0,0 +1,9 @@ +#include + +#define CSPGUID "{0000fade-000b-0001-0102030405060708}" + +extern void csptests(); +extern void testmac(); +extern void testwrap(); + +extern void dump(const CssmData &data); diff --git a/SecurityTests/testclient/dltests.cpp b/SecurityTests/testclient/dltests.cpp new file mode 100644 index 00000000..6d70ee7f --- /dev/null +++ b/SecurityTests/testclient/dltests.cpp @@ -0,0 +1,804 @@ +#include "dltests.h" +#include "csptests.h" +#include "attributes.h" +#include +#include +#include // For CSPDL. +#include +#include + +using namespace CssmClient; + +// Configuration. +#define HEX_DIGITS_PER_LINE 20 +#define INDENT_SIZE 2 + + +const CSSM_GUID* gSelectedFileGuid = &gGuidAppleFileDL; + + + +static void testDLCreate(const Guid &dlGuid); +static void testDLDelete(const Guid &dlGuid, bool throwOnError); +static void testGen(const Guid &cspDlGuid); +static void testDLCrypt(const Guid &cspDlGuid); +static void testMultiDLDb(const Guid &dlGuid); +static void dumpRelation(uint32 indent, Db &db, uint32 relationID, const char *relationName, bool printSchema); +static void dumpRecord(uint32 indent, const DbAttributes &record, const CssmData &data, const DbUniqueRecord &uniqueId); + +#define CSSM_DB_RELATION(RELATIONID) RecordAttrInfo ## RELATIONID + +#define CSSM_DB_DEFINE_RELATION_BEGIN(RELATIONID) \ +static const CSSM_DB_ATTRIBUTE_INFO AttrInfo ## RELATIONID[] = + +#define CSSM_DB_DEFINE_RELATION_END(RELATIONID) \ +; \ +static const CSSM_DB_RECORD_ATTRIBUTE_INFO CSSM_DB_RELATION(RELATIONID) = \ +{ \ + RELATIONID, \ + sizeof(AttrInfo ## RELATIONID) / sizeof(CSSM_DB_ATTRIBUTE_INFO), \ + const_cast(AttrInfo ## RELATIONID) \ +} + +// GENERIC PASSWORDS +CSSM_DB_DEFINE_RELATION_BEGIN(CSSM_DL_DB_RECORD_GENERIC_PASSWORD) +{ + CSSM_DB_ATTR(Attributes::Class), + CSSM_DB_ATTR(Attributes::CreationDate), + CSSM_DB_ATTR(Attributes::ModDate), + CSSM_DB_ATTR(Attributes::Description), + CSSM_DB_ATTR(Attributes::Comment), + CSSM_DB_ATTR(Attributes::Creator), + CSSM_DB_ATTR(Attributes::Type), + CSSM_DB_ATTR(Attributes::ScrCode), + CSSM_DB_ATTR(Attributes::Label), + CSSM_DB_ATTR(Attributes::Invisible), + CSSM_DB_ATTR(Attributes::Negative), + CSSM_DB_ATTR(Attributes::Custom), + //CSSM_DB_ATTR(Attributes::Protected), + CSSM_DB_ATTR(Attributes::Account), + CSSM_DB_ATTR(Attributes::Service), + CSSM_DB_ATTR(Attributes::Generic) +} +CSSM_DB_DEFINE_RELATION_END(CSSM_DL_DB_RECORD_GENERIC_PASSWORD); + + +// APPLESHARE PASSWORDS +CSSM_DB_DEFINE_RELATION_BEGIN(CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD) +{ + CSSM_DB_ATTR(Attributes::Class), + CSSM_DB_ATTR(Attributes::CreationDate), + CSSM_DB_ATTR(Attributes::ModDate), + CSSM_DB_ATTR(Attributes::Description), + CSSM_DB_ATTR(Attributes::Comment), + CSSM_DB_ATTR(Attributes::Creator), + CSSM_DB_ATTR(Attributes::Type), + CSSM_DB_ATTR(Attributes::ScrCode), + CSSM_DB_ATTR(Attributes::Label), + CSSM_DB_ATTR(Attributes::Invisible), + CSSM_DB_ATTR(Attributes::Negative), + CSSM_DB_ATTR(Attributes::Custom), + //CSSM_DB_ATTR(Attributes::Protected), + CSSM_DB_ATTR(Attributes::Volume), + CSSM_DB_ATTR(Attributes::Addr), + CSSM_DB_ATTR(Attributes::Signature), + CSSM_DB_ATTR(Attributes::ProtocolType) +} +CSSM_DB_DEFINE_RELATION_END(CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD); + +// INTERNET PASSWORDS +CSSM_DB_DEFINE_RELATION_BEGIN(CSSM_DL_DB_RECORD_INTERNET_PASSWORD) +{ + CSSM_DB_ATTR(Attributes::Class), + CSSM_DB_ATTR(Attributes::CreationDate), + CSSM_DB_ATTR(Attributes::ModDate), + CSSM_DB_ATTR(Attributes::Description), + CSSM_DB_ATTR(Attributes::Comment), + CSSM_DB_ATTR(Attributes::Creator), + CSSM_DB_ATTR(Attributes::Type), + CSSM_DB_ATTR(Attributes::ScrCode), + CSSM_DB_ATTR(Attributes::Label), + CSSM_DB_ATTR(Attributes::Invisible), + CSSM_DB_ATTR(Attributes::Negative), + CSSM_DB_ATTR(Attributes::Custom), + //CSSM_DB_ATTR(Attributes::Protected), + CSSM_DB_ATTR(Attributes::Account), + CSSM_DB_ATTR(Attributes::SecDomain), + CSSM_DB_ATTR(Attributes::Server), + CSSM_DB_ATTR(Attributes::AuthType), + CSSM_DB_ATTR(Attributes::Port), + CSSM_DB_ATTR(Attributes::Path), + CSSM_DB_ATTR(Attributes::ProtocolType) +} +CSSM_DB_DEFINE_RELATION_END(CSSM_DL_DB_RECORD_INTERNET_PASSWORD); + +// INTERNET PASSWORDS +CSSM_DB_DEFINE_RELATION_BEGIN(CSSM_DL_DB_RECORD_SYMMETRIC_KEY) +{ + CSSM_DB_ATTR(Attributes::KeyClass), + CSSM_DB_ATTR(Attributes::PrintName), + CSSM_DB_ATTR(Attributes::Alias), + CSSM_DB_ATTR(Attributes::Permanent), + CSSM_DB_ATTR(Attributes::Private), + CSSM_DB_ATTR(Attributes::Modifiable), + CSSM_DB_ATTR(Attributes::Label), + CSSM_DB_ATTR(Attributes::ApplicationTag), + CSSM_DB_ATTR(Attributes::KeyCreator), + CSSM_DB_ATTR(Attributes::KeyType), + CSSM_DB_ATTR(Attributes::KeySizeInBits), + CSSM_DB_ATTR(Attributes::EffectiveKeySize), + CSSM_DB_ATTR(Attributes::StartDate), + CSSM_DB_ATTR(Attributes::EndDate), + CSSM_DB_ATTR(Attributes::Sensitive), + CSSM_DB_ATTR(Attributes::AlwaysSensitive), + CSSM_DB_ATTR(Attributes::Extractable), + CSSM_DB_ATTR(Attributes::NeverExtractable), + CSSM_DB_ATTR(Attributes::Encrypt), + CSSM_DB_ATTR(Attributes::Decrypt), + CSSM_DB_ATTR(Attributes::Derive), + CSSM_DB_ATTR(Attributes::Sign), + CSSM_DB_ATTR(Attributes::Verify), + CSSM_DB_ATTR(Attributes::SignRecover), + CSSM_DB_ATTR(Attributes::VerifyRecover), + CSSM_DB_ATTR(Attributes::Wrap), + CSSM_DB_ATTR(Attributes::UnWrap) +} +CSSM_DB_DEFINE_RELATION_END(CSSM_DL_DB_RECORD_SYMMETRIC_KEY); + + +static const CSSM_DB_RECORD_ATTRIBUTE_INFO KCAttrs[] = +{ + CSSM_DB_RELATION(CSSM_DL_DB_RECORD_GENERIC_PASSWORD), + CSSM_DB_RELATION(CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD), + CSSM_DB_RELATION(CSSM_DL_DB_RECORD_INTERNET_PASSWORD) + //CSSM_DB_RELATION(CSSM_DL_DB_RECORD_SYMMETRIC_KEY) +}; + +static const CSSM_DB_RECORD_INDEX_INFO recordIndex = +{ + CSSM_DB_RECORDTYPE_APP_DEFINED_START, // CSSM_DB_RECORDTYPE + 0, //%%% for now + NULL //%%% for now +}; +static const CSSM_DB_RECORD_INDEX_INFO recordIndexes[] = {recordIndex, recordIndex, recordIndex}; + +// parse info (to improve later) +static const CSSM_DB_PARSING_MODULE_INFO parseInfo = +{ + CSSM_DB_RECORDTYPE_APP_DEFINED_START, + { + {0,0,0,{0}}, + {0,0}, + 0, + 0 + } +}; +static const CSSM_DB_PARSING_MODULE_INFO parseInfos[] = {parseInfo, parseInfo, parseInfo}; + +static const CSSM_DBINFO KCDBInfo = +{ + sizeof(KCAttrs) / sizeof(CSSM_DB_RECORD_ATTRIBUTE_INFO), + const_cast(parseInfos), + const_cast(KCAttrs), + const_cast(recordIndexes), + CSSM_TRUE, + NULL, + NULL +}; + + + +void dltests(bool autoCommit) +{ + testDLDelete(gGuidAppleFileDL, false); + testDLCreate(gGuidAppleFileDL); + testMultiDLDb(gGuidAppleFileDL); + + testDLDelete(gGuidAppleCSPDL, false); + testDLCreate(gGuidAppleCSPDL); + testGen(gGuidAppleCSPDL); + testDLCrypt(gGuidAppleCSPDL); + testMultiDLDb(gGuidAppleCSPDL); + //testDLDelete(gGuidAppleCSPDL, true); +} + +static void testDLCreate(const Guid &dlGuid) +{ + DL appledl(dlGuid); + Db testDb(appledl, DBNAME1); + testDb->dbInfo(&KCDBInfo); + testDb->create(); +} + +static void testDLDelete(const Guid &dlGuid, bool throwOnError) +{ + DL appledl(dlGuid); + Db testDb(appledl, DBNAME1); + try + { + testDb->deleteDb(); + } + catch(CssmError e) + { + if (throwOnError || e.osStatus() != CSSMERR_DL_DATASTORE_DOESNOT_EXIST) + throw; + } +} + +static void testGen(const Guid &cspDlGuid) +{ + printf("\n* performing CSP/DL keygen test...\n"); + CSPDL cspdl(cspDlGuid); + Db db(cspdl, DBNAME1); + + printf("Generating permanent key\n"); + GenerateKey genKey(cspdl, CSSM_ALGID_DES, 64); + genKey.database(db); + CssmPolyData label("First Key!"); + Key key = genKey(KeySpec(CSSM_KEYUSE_ANY, + CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_SENSITIVE, + label)); + printf("done\n"); +} + +static void testDLCrypt(const Guid &cspDlGuid) +{ + printf("\n* performing encrypt/decrypt test...\n"); + CSPDL cspdl(cspDlGuid); + Db db(cspdl, DBNAME1); + + printf("Finding key\n"); + DbCursor cursor(db); + cursor->recordType(CSSM_DL_DB_RECORD_SYMMETRIC_KEY); + DbUniqueRecord keyId; + CssmDataContainer keyData; + if (!cursor->next(NULL, &keyData, keyId)) + CssmError::throwMe(CSSMERR_DL_ENDOFDATA); + + Key key(cspdl, *reinterpret_cast(keyData.Data)); + + printf("done\n"); + + // Gnerate IV + printf("Generating iv\n"); + //CssmData iv = Random(csp, CSSM_ALGID_SHARandom)(8); + CssmPolyData iv("12345678"); + + CssmPolyData in("Om mani padme hum"); + printf("input="); + dump(in); + + // Encrypt + printf("Encrypting\n"); + + Encrypt encrypt(cspdl, CSSM_ALGID_DES); + encrypt.mode(CSSM_ALGMODE_CBCPadIV8); + encrypt.padding(CSSM_PADDING_PKCS1); + encrypt.initVector(iv); + encrypt.key(key); + CssmData cipher; + CssmData remcipher; + encrypt.encrypt(&in, 1, &cipher, 1); + encrypt.final(remcipher); + printf("ciphertext="); + dump(cipher); + printf("remainder="); + dump(remcipher); + + // Decrypt + printf("Decrypting\n"); + + Decrypt decrypt(cspdl, CSSM_ALGID_DES); + decrypt.key(key); + decrypt.mode(CSSM_ALGMODE_CBCPadIV8); + decrypt.padding(CSSM_PADDING_PKCS1); + decrypt.initVector(iv); + CssmData plain; + CssmData remplain; + CssmData inp[] = { cipher, remcipher }; + decrypt.decrypt(inp, 2, &plain, 1); + decrypt.final(remplain); + printf("plaintext="); + dump(plain); + printf("remainder="); + dump(remplain); + + printf("end encrypt/decrypt test\n"); +} + +static void print(sint32 value) +{ + printf("%ld", value); +} + +static void print(double value) +{ + printf("%g", value); +} + +static void print(uint32 value) +{ + uint8 *bytes = reinterpret_cast(&value); + bool ascii = true; + for (uint32 ix = 0; ix < sizeof(uint32); ++ix) + if (bytes[ix] < 0x20 || bytes[ix] > 0x7f) + { + ascii = false; + break; + } + + if (ascii) + { + putchar('\''); + for (uint32 ix = 0; ix < sizeof(uint32); ++ix) + putchar(bytes[ix]); + + printf("' (0x%08lx)", value); + } + else + printf("0x%08lx", value); +} + +static void printAsString(uint32 indent, const CSSM_DATA &value) +{ + printf("%.*s", static_cast(value.Length), value.Data); +} + +static void print(uint32 indent, const char *value) +{ + printf("%s", value); +} + +static void printIndent(uint32 indent) +{ + //if (indent == 0) + // return; + + putchar('\n'); + for (uint32 ix = 0; ix < indent; ++ix) + putchar(' '); +} + +static void printRange(uint32 length, const uint8 *data) +{ + for (uint32 ix = 0; ix < HEX_DIGITS_PER_LINE; ++ix) + { + if (ix && ix % 4 == 0) + putchar(' '); + + if (ix < length) + printf("%02x", static_cast(data[ix])); + else + printf(" "); + } + + printf(" "); + for (uint32 ix = 0; ix < length; ++ix) + { + if (data[ix] < 0x20 || data[ix] > 0x7f) + putchar('.'); + else + putchar(data[ix]); + } +} + +static void print(uint32 indent, const CSSM_DATA &value) +{ + if (value.Length == 0) + return; + + if (value.Length > HEX_DIGITS_PER_LINE) + { + uint32 ix; + for (ix = 0; ix < value.Length - HEX_DIGITS_PER_LINE; ix += HEX_DIGITS_PER_LINE) + { + printIndent(indent); + printRange(HEX_DIGITS_PER_LINE, &value.Data[ix]); + } + printIndent(indent); + printRange(value.Length - ix, &value.Data[ix]); + printIndent(indent - INDENT_SIZE); + } + else + printRange(value.Length, value.Data); +} + +static void printOID(uint32 indent, const CSSM_OID &value) +{ + print(indent, value); +} + +static const char *format(CSSM_DB_ATTRIBUTE_FORMAT format) +{ + switch(format) + { + case CSSM_DB_ATTRIBUTE_FORMAT_STRING: return "string"; + case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: return "sint32"; + case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: return "uint32"; + case CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM: return "big_num"; + case CSSM_DB_ATTRIBUTE_FORMAT_REAL: return "real"; + case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE: return "time_date"; + case CSSM_DB_ATTRIBUTE_FORMAT_BLOB: return "blob"; + case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32: return "multi_uint32"; + case CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX: return "complex"; + default: abort(); + } +} + +static void print(uint32 indent, const CssmDbAttributeData &attr) +{ + bool multiValues = false; + if (attr.size() == 0) + { + printf(""); + return; + } + + if (attr.size() != 1) + { + printIndent(indent); + printf(""); + indent += INDENT_SIZE; + multiValues = true; + } + + for (uint32 ix = 0; ix < attr.size(); ++ix) + { + if (multiValues) + printIndent(indent); + + printf("<%s>", format(attr.format())); + switch (attr.format()) + { + case CSSM_DB_ATTRIBUTE_FORMAT_STRING: + printAsString(indent + INDENT_SIZE, attr.at(ix)); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: + print(attr.at(ix)); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: + print(attr.at(ix)); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_REAL: + print(attr.at(ix)); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE: + printf("%*s", 15, attr.at(ix)); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32: + case CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM: + case CSSM_DB_ATTRIBUTE_FORMAT_BLOB: + case CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX: + default: + print(indent + INDENT_SIZE, attr.at(ix)); + break; + } + printf("", format(attr.format())); + } + + if (multiValues) + { + indent -= INDENT_SIZE; + printIndent(indent); + printf(""); + } +} + +static void print(uint32 indent, const CssmDbAttributeInfo &info) +{ + switch (info.nameFormat()) + { + case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: + { + printf(""); + print(indent + INDENT_SIZE, info.Label.AttributeName); + printf(""); + break; + } + case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: + { + printf(""); + print(info.Label.AttributeID); + printf(""); + break; + } + case CSSM_DB_ATTRIBUTE_NAME_AS_OID: + { + printf(""); + printOID(indent + INDENT_SIZE, info.Label.AttributeOID); + printf(""); + break; + } + default: + throw Error(CSSMERR_DL_DATABASE_CORRUPT); + } +} + +void dumpDb(char *dbName, bool printSchema) +{ + DL appledl(*gSelectedFileGuid); + Db db(appledl, dbName); + DbCursor relations(db); + relations->recordType(CSSM_DL_DB_SCHEMA_INFO); + DbAttributes schemaRecord(db, 2); + schemaRecord.add(Attributes::RelationID); + schemaRecord.add(Attributes::RelationName); + CssmDataContainer data; + DbUniqueRecord uniqueId(db); + + uint32 indent = 0; + printf(""); + indent += INDENT_SIZE; + printIndent(indent); + printf("%s", dbName); + while (relations->next(&schemaRecord, &data, uniqueId)) + { + uint32 relationID = schemaRecord.at(0); + if (!printSchema && CSSM_DB_RECORDTYPE_SCHEMA_START <= relationID + && relationID < CSSM_DB_RECORDTYPE_SCHEMA_END) + continue; + + printIndent(indent); + printf(""); + string relationName = schemaRecord.at(1); + dumpRelation(indent + INDENT_SIZE, db, relationID, relationName.c_str(), printSchema); + printIndent(indent); + printf(""); + } + + indent -= INDENT_SIZE; + printIndent(indent); + printf("\n"); +} + +static void dumpRelation(uint32 indent, Db &db, uint32 relationID, const char *relationName, bool printSchema) +{ + TrackingAllocator anAllocator(Allocator::standard()); + + printIndent(indent); + printf(""); + print(indent + INDENT_SIZE, relationName); + printf(""); + printIndent(indent); + printf(""); + print(relationID); + printf(""); + + // Create a cursor on the SCHEMA_ATTRIBUTES table for records with RelationID == relationID + DbCursor attributes(db); + attributes->recordType(CSSM_DL_DB_SCHEMA_ATTRIBUTES); + attributes->add(CSSM_DB_EQUAL, Attributes::RelationID, relationID); + + // Set up a record for retriving the SCHEMA_ATTRIBUTES + DbAttributes schemaRecord(db, 5); + schemaRecord.add(Attributes::AttributeNameFormat); + schemaRecord.add(Attributes::AttributeFormat); + schemaRecord.add(Attributes::AttributeName); + schemaRecord.add(Attributes::AttributeID); + schemaRecord.add(Attributes::AttributeNameID); + + DbAttributes record(db); + CssmDataContainer data; + DbUniqueRecord uniqueId(db); + + if (printSchema) + { + printIndent(indent); + printf(""); + indent += INDENT_SIZE; + } + + while (attributes->next(&schemaRecord, &data, uniqueId)) + { + CssmDbAttributeInfo &anInfo = record.add().info(); + anInfo.AttributeNameFormat = schemaRecord.at(0); + anInfo.AttributeFormat = schemaRecord.at(1); + switch (anInfo.AttributeNameFormat) + { + case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: + { + CssmDbAttributeData &anAttributeName = schemaRecord.at(2); + + string name = static_cast(anAttributeName); + anInfo.Label.AttributeName = reinterpret_cast(anAllocator.malloc(name.size() + 1)); + strcpy(anInfo.Label.AttributeName, name.c_str()); + + // XXX Need to copy the memory. For now avoid it being freed. + anAttributeName.Value[0].Data = NULL; + anAttributeName.Value[0].Length = 0; + break; + } + case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: + { + CssmDbAttributeData &anAttributeID = schemaRecord.at(3); + anInfo.Label.AttributeID = anAttributeID; + break; + } + case CSSM_DB_ATTRIBUTE_NAME_AS_OID: + { + CssmDbAttributeData &anAttributeOID = schemaRecord.at(4); + anInfo.Label.AttributeOID = anAttributeOID; + + // XXX Need to copy the memory. For now avoid it being freed. + anAttributeOID.Value[0].Data = NULL; + anAttributeOID.Value[0].Length = 0; + break; + } + default: + throw Error(CSSMERR_DL_DATABASE_CORRUPT); + } + + if (printSchema) + { + printIndent(indent); + print(indent, anInfo); + printf("%s", format(anInfo.format())); + } + } + + if (printSchema) + { + indent -= INDENT_SIZE; + printIndent(indent); + printf(""); + } + + DbCursor records(db); + records->recordType(relationID); + printIndent(indent); + printf(""); + indent += INDENT_SIZE; + while (records->next(&record, &data, uniqueId)) + dumpRecord(indent, record, data, uniqueId); + + indent -= INDENT_SIZE; + printIndent(indent); + printf(""); +} + +static void +dumpRecord(uint32 indent, const DbAttributes &record, const CssmData &data, const DbUniqueRecord &uniqueId) +{ + const CSSM_DB_UNIQUE_RECORD *recId = static_cast(uniqueId); + uint32 recCount = recId->RecordIdentifier.Length; + const uint32 *recArray = reinterpret_cast(recId->RecordIdentifier.Data); + printIndent(indent); + printf(""); + for (uint32 ix = 0; ix < recCount / 4; ++ix) + { + if (ix != 0) + putchar(' '); + printf("0x%08lx", recArray[ix]); + } + printf(""); + + // Print the attributes + printIndent(indent); + if (record.size() == 0) + { + printf(""); + } + else + { + printf(""); + indent += INDENT_SIZE; + for (uint32 ix = 0; ix < record.size(); ix++) + { + const CssmDbAttributeData &anAttr = record.at(ix); + if (anAttr.size()) // Skip zero valued attributes. + { + printIndent(indent); + print(indent + INDENT_SIZE, anAttr.info()); + print(indent + INDENT_SIZE, anAttr); + } + } + + indent -= INDENT_SIZE; + printIndent(indent); + printf(""); + } + + // Print the data + printIndent(indent); + if (data.length()) + { + printf(""); + print(indent + INDENT_SIZE, data); + printf(""); + } + else + printf(""); +} + +static void testMultiDLDb(const Guid &dlGuid) +{ + // Setup a list of DLDbIdentifier object to hand off the MultiDLDb. + vector list; + list.push_back(DLDbIdentifier(CssmSubserviceUid(dlGuid), "multidb1.db", NULL)); + list.push_back(DLDbIdentifier(CssmSubserviceUid(dlGuid), "multidb2.db", NULL)); + + // Create MultiDLDb instance. + MultiDLDb multiDLDb(list, false); + + // Get a handle for the first and second Db. + Db db1(multiDLDb->database(list[0])); + Db db2(multiDLDb->database(list[1])); + + // Until this point no CSSM API's have been called! + + // Delete both databases if they exist. + try + { db1->deleteDb(); } + catch(CssmError e) + { if (e.osStatus() != CSSMERR_DL_DATASTORE_DOESNOT_EXIST) throw; } + + try + { db2->deleteDb(); } + catch(CssmError e) + { if (e.osStatus() != CSSMERR_DL_DATASTORE_DOESNOT_EXIST) throw; } + + // XXX Note to self if you set the schema but do not call create() + // explicitly maybe the db should only be created if it did not yet exist... + + // Set the schema of both databases so they get created on activate. + db1->dbInfo(&KCDBInfo); + db2->dbInfo(&KCDBInfo); + + // Insert a record into each database. + DbAttributes attrs(db1); + attrs.add(Attributes::Comment, "This is the first comment").add("This is the second comment", attrs); + attrs.add(Attributes::Label, "Item1"); + CssmPolyData testdata1("testdata1"); + db1->insert(CSSM_DL_DB_RECORD_GENERIC_PASSWORD, &attrs, &testdata1); + + attrs.clear(); + attrs.add(Attributes::Comment, "This is the second comment"); + attrs.add(Attributes::Label, "Item (in database2)."); + CssmPolyData testdata2("testdata2"); + db2->insert(CSSM_DL_DB_RECORD_GENERIC_PASSWORD, &attrs, &testdata2); + + // Create a cursor on the multiDLDb. + DbCursor cursor(multiDLDb); + // Set the type of records we wish to query. + cursor->recordType(CSSM_DL_DB_RECORD_GENERIC_PASSWORD); + cursor->add(CSSM_DB_EQUAL, Attributes::Comment, "This is the second comment"); + + DbUniqueRecord uniqueId; // Empty uniqueId calling cursor.next will initialize. + CssmDataContainer data; // XXX Think about data's allocator. + + // Iterate over the records in all the db's in the multiDLDb. + while (cursor->next(&attrs, &data, uniqueId)) + { + // Print the record data. + dumpRecord(0, attrs, data, uniqueId); + } +} + +#if 0 + CssmDb::Impl *CssmDL::Impl::newDb(args) { new CssmDbImpl(args); } + + SecureStorage ss(Guid); + CssmDb db(ss, DBNAME); + CssmUniqueId unique; + db.insert(attr, data, unique); + + Cursor cursor(db); + CssmKey key; + cursor.next(key); + + Cssm cssm; + Module module(cssm); + CSPDL cspdl(module); + + + SecureStorage ss(Guid); + CssmDb db = ss->db(DBNAME); + CssmUniqueId unique; + db->insert(attr, data, unique); + + Cursor cursor(db); + CssmKey key; + cursor->next(key); + + +#endif diff --git a/SecurityTests/testclient/dltests.h b/SecurityTests/testclient/dltests.h new file mode 100644 index 00000000..87ffbe0a --- /dev/null +++ b/SecurityTests/testclient/dltests.h @@ -0,0 +1,11 @@ +#include + +//#define DLGUID "{0000fade-0002-0003-0102030405060708}" +#define DLGUID gGuidAppleFileDL + +#define DBNAME1 "dbname1.db" + +extern void dltests(bool autoCommit); +void dumpDb(char *dbName, bool printSchema); + +extern const CSSM_GUID* gSelectedFileGuid; diff --git a/SecurityTests/testclient/testclient.cpp b/SecurityTests/testclient/testclient.cpp new file mode 100644 index 00000000..affb5116 --- /dev/null +++ b/SecurityTests/testclient/testclient.cpp @@ -0,0 +1,132 @@ +// +// Test driver program for cdsa_client library +// +#include "csptests.h" +#include "dltests.h" + +#include +#include +#include +#include +#include + +using namespace CssmClient; +extern "C" void malloc_debug(int); + +static void usage(); + +static const char *progname; + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ main +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +int main(int argc, char *argv[]) +{ + extern char *optarg; + extern int optind; + bool didWork = false; + bool autoCommit = true; + bool printSchema = false; + int ch; + + progname = strrchr(argv[0], '/'); + progname = progname ? progname + 1 : argv[0]; + + try + { + while ((ch = getopt(argc, argv, "?haAbcdM:D:smwg:")) != -1) + { + switch(ch) + { + case 'a': + autoCommit=true; + break; + case 'A': + autoCommit=false; + break; + case 'b': + setbuf(stdout, NULL); + break; + case 'c': + csptests(); + didWork = true; + break; + case 'm': + testmac(); + didWork = true; + break; + case 'w': + testwrap(); + didWork = true; + break; + case 'd': + dltests(autoCommit); + didWork = true; + break; + case 's': + printSchema = true; + break; + case 'g': + if (strcmp (optarg, "AppleFileDL") == 0) + { + gSelectedFileGuid = &gGuidAppleFileDL; + } + else if (strcmp (optarg, "LDAPDL") == 0) + { + gSelectedFileGuid = &gGuidAppleLDAPDL; + } + else + { + didWork = false; + } + break; + case 'D': + dumpDb(optarg, printSchema); + didWork = true; + break; + case 'M': + malloc_debug(atoi(optarg)); + break; + case '?': + case 'h': + default: + usage(); + } + } + + if (argc != optind) + usage(); + + if (!didWork) + usage(); + + Cssm::standard()->terminate(); + } + catch (CommonError &error) + { + cssmPerror("Tester abort", error.osStatus()); + } + + return 0; +} + +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +// ¥ usage +// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ +static void +usage() +{ + printf("usage: %s [-M] [-b] [-c] [[-a|-A] -d] [[-s ] [-g AppleFileDL | LDAPDL] -D ]\n", progname); + printf(" -M debug_level Call malloc_debug(debug_level) to enable malloc debugging.\n"); + printf(" -b turn off stdout buffering.\n"); + printf(" -c run csp (rotty) tests.\n"); + printf(" -m Test Mac\n"); + printf(" -w Test Wrap\n"); + printf(" -d run dl tests.\n"); + printf(" -a Enable AutoCommit for dl modifications (default).\n"); + printf(" -A Disable AutoCommit for dl modifications.\n"); + printf(" -D dbname Dump a db into a human readable format.\n"); + printf(" -s Dump out schema info (use with -D).\n"); + exit(1); +} + diff --git a/SecurityTests/testclient/testclient.pbproj/project.pbxproj b/SecurityTests/testclient/testclient.pbproj/project.pbxproj new file mode 100644 index 00000000..dc9ffeea --- /dev/null +++ b/SecurityTests/testclient/testclient.pbproj/project.pbxproj @@ -0,0 +1,372 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 39; + objects = { + 0A161878000410B011CD287F = { + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + OPTIMIZATION_CFLAGS = "-O0"; + ZERO_LINK = YES; + }; + isa = PBXBuildStyle; + name = Development; + }; + 0A161879000410B011CD287F = { + buildSettings = { + COPY_PHASE_STRIP = YES; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + ZERO_LINK = NO; + }; + isa = PBXBuildStyle; + name = Deployment; + }; + 0A16187B000411F911CD287F = { + isa = PBXFileReference; + lastKnownFileType = wrapper.framework; + path = Security.framework; + refType = 3; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 0A16187C000411F911CD287F = { + fileRef = 0A16187B000411F911CD287F; + isa = PBXBuildFile; + settings = { + }; + }; +//0A0 +//0A1 +//0A2 +//0A3 +//0A4 +//180 +//181 +//182 +//183 +//184 + 1871086CFF15495111CD283A = { + children = ( + 0A16187B000411F911CD287F, + 4C5285110624AB2C00FCEF5B, + 4C5285130624AB2C00FCEF5B, + 4C5285120624AB2C00FCEF5B, + ); + isa = PBXGroup; + name = Frameworks; + refType = 4; + sourceTree = ""; + }; + 1871086DFF15495111CD283A = { + explicitFileType = "compiled.mach-o.executable"; + isa = PBXFileReference; + path = testclient; + refType = 3; + sourceTree = BUILT_PRODUCTS_DIR; + }; +//180 +//181 +//182 +//183 +//184 +//1F0 +//1F1 +//1F2 +//1F3 +//1F4 + 1FF0DAFBFE99550B11CD296C = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + path = testclient.cpp; + refType = 4; + sourceTree = ""; + }; +//1F0 +//1F1 +//1F2 +//1F3 +//1F4 +//240 +//241 +//242 +//243 +//244 + 2416F430FE8A493011CD283A = { + buildSettings = { + }; + buildStyles = ( + 0A161878000410B011CD287F, + 0A161879000410B011CD287F, + ); + hasScannedForEncodings = 1; + isa = PBXProject; + mainGroup = 2416F431FE8A493011CD283A; + projectDirPath = ""; + targets = ( + 2416F446FE8A495F11CD283A, + ); + }; + 2416F431FE8A493011CD283A = { + children = ( + 2416F432FE8A495F11CD283A, + 1871086CFF15495111CD283A, + 25099329FE8A4BB411CD283A, + ); + isa = PBXGroup; + refType = 4; + sourceTree = ""; + }; + 2416F432FE8A495F11CD283A = { + children = ( + 2C3534BEFE9C2E9A11CD283A, + 2C3534BDFE9C2E9A11CD283A, + 2C3534B0FE9C275611CD283A, + 2C3534B1FE9C275611CD283A, + 2C3534ACFE9C268311CD283A, + 2C3534ABFE9C268311CD283A, + 1FF0DAFBFE99550B11CD296C, + ); + isa = PBXGroup; + name = Sources; + path = ""; + refType = 4; + sourceTree = ""; + }; + 2416F446FE8A495F11CD283A = { + buildPhases = ( + 2416F447FE8A495F11CD283A, + 2416F450FE8A495F11CD283A, + 2416F459FE8A495F11CD283A, + ); + buildSettings = { + FRAMEWORK_SEARCH_PATHS = "/usr/local/SecurityPieces/Frameworks \"$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks\""; + INSTALL_PATH = /usr/local/bin; + PRODUCT_NAME = testclient; + WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; + }; + dependencies = ( + ); + isa = PBXToolTarget; + name = testclient; + productInstallPath = /usr/local/bin; + productName = testclient; + productReference = 1871086DFF15495111CD283A; + }; + 2416F447FE8A495F11CD283A = { + buildActionMask = 2147483647; + files = ( + 2C3534BFFE9C2E9A11CD283A, + 2C3534B4FE9C286211CD283A, + 2C3534B5FE9C286211CD283A, + ); + isa = PBXHeadersBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + 2416F450FE8A495F11CD283A = { + buildActionMask = 2147483647; + files = ( + 2C3534C0FE9C2E9A11CD283A, + 2C3534B6FE9C286211CD283A, + 2C3534B7FE9C286211CD283A, + 2C3534B8FE9C286211CD283A, + ); + isa = PBXSourcesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + 2416F459FE8A495F11CD283A = { + buildActionMask = 2147483647; + files = ( + 0A16187C000411F911CD287F, + 4C5285140624AB2C00FCEF5B, + 4C5285150624AB2C00FCEF5B, + 4C5285160624AB2C00FCEF5B, + ); + isa = PBXFrameworksBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; +//240 +//241 +//242 +//243 +//244 +//250 +//251 +//252 +//253 +//254 + 25099329FE8A4BB411CD283A = { + children = ( + 1871086DFF15495111CD283A, + ); + isa = PBXGroup; + name = Products; + path = ""; + refType = 3; + sourceTree = BUILT_PRODUCTS_DIR; + }; +//250 +//251 +//252 +//253 +//254 +//2C0 +//2C1 +//2C2 +//2C3 +//2C4 + 2C3534ABFE9C268311CD283A = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + path = dltests.cpp; + refType = 4; + sourceTree = ""; + }; + 2C3534ACFE9C268311CD283A = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = dltests.h; + refType = 4; + sourceTree = ""; + }; + 2C3534B0FE9C275611CD283A = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = csptests.h; + refType = 4; + sourceTree = ""; + }; + 2C3534B1FE9C275611CD283A = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + path = csptests.cpp; + refType = 4; + sourceTree = ""; + }; + 2C3534B4FE9C286211CD283A = { + fileRef = 2C3534B0FE9C275611CD283A; + isa = PBXBuildFile; + settings = { + }; + }; + 2C3534B5FE9C286211CD283A = { + fileRef = 2C3534ACFE9C268311CD283A; + isa = PBXBuildFile; + settings = { + }; + }; + 2C3534B6FE9C286211CD283A = { + fileRef = 2C3534B1FE9C275611CD283A; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + ); + }; + }; + 2C3534B7FE9C286211CD283A = { + fileRef = 2C3534ABFE9C268311CD283A; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + ); + }; + }; + 2C3534B8FE9C286211CD283A = { + fileRef = 1FF0DAFBFE99550B11CD296C; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + ); + }; + }; + 2C3534BDFE9C2E9A11CD283A = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.cpp; + path = attributes.cpp; + refType = 4; + sourceTree = ""; + }; + 2C3534BEFE9C2E9A11CD283A = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = attributes.h; + refType = 4; + sourceTree = ""; + }; + 2C3534BFFE9C2E9A11CD283A = { + fileRef = 2C3534BEFE9C2E9A11CD283A; + isa = PBXBuildFile; + settings = { + }; + }; + 2C3534C0FE9C2E9A11CD283A = { + fileRef = 2C3534BDFE9C2E9A11CD283A; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + ); + }; + }; +//2C0 +//2C1 +//2C2 +//2C3 +//2C4 +//4C0 +//4C1 +//4C2 +//4C3 +//4C4 + 4C5285110624AB2C00FCEF5B = { + isa = PBXFileReference; + lastKnownFileType = wrapper.framework; + path = security_cdsa_client.framework; + refType = 3; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4C5285120624AB2C00FCEF5B = { + isa = PBXFileReference; + lastKnownFileType = wrapper.framework; + path = security_cdsa_utilities.framework; + refType = 3; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4C5285130624AB2C00FCEF5B = { + isa = PBXFileReference; + lastKnownFileType = wrapper.framework; + path = security_utilities.framework; + refType = 3; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4C5285140624AB2C00FCEF5B = { + fileRef = 4C5285110624AB2C00FCEF5B; + isa = PBXBuildFile; + settings = { + }; + }; + 4C5285150624AB2C00FCEF5B = { + fileRef = 4C5285120624AB2C00FCEF5B; + isa = PBXBuildFile; + settings = { + }; + }; + 4C5285160624AB2C00FCEF5B = { + fileRef = 4C5285130624AB2C00FCEF5B; + isa = PBXBuildFile; + settings = { + }; + }; + }; + rootObject = 2416F430FE8A493011CD283A; +} diff --git a/SecurityTests/testlist.h b/SecurityTests/testlist.h new file mode 100644 index 00000000..ee85893a --- /dev/null +++ b/SecurityTests/testlist.h @@ -0,0 +1,8 @@ +/* Don't prevent multiple inclusion of this file. */ +#include +#include +#include +#include +#include +#include +#include diff --git a/SecurityTests/testmain.c b/SecurityTests/testmain.c new file mode 100644 index 00000000..2b6256b8 --- /dev/null +++ b/SecurityTests/testmain.c @@ -0,0 +1,47 @@ +/* + * testmain.c + * Security + * + * Created by Fabrice Gautier on 8/26/10. + * Copyright (c) 2010,2012-2014 Apple Inc. All Rights Reserved. + * + */ +#include +#include + +#include + +#include + +#include "testlist.h" +#include +#include "testlist.h" +#include + +#include +#include + +int main(int argc, char *argv[]) +{ + //printf("Build date : %s %s\n", __DATE__, __TIME__); + //printf("WARNING: If running those tests on a device with a passcode, DONT FORGET TO UNLOCK!!!\n"); + +#if 0 && NO_SERVER + SOSCloudKeychainServerInit(); +#endif + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + int result = tests_begin(argc, argv); + + fflush(stderr); + fflush(stdout); + + sleep(1); + + exit(result); + }); + + CFRunLoopRun(); + + return 0; +} diff --git a/SecurityTests/xdr_rpc/Makefile.xdr_test b/SecurityTests/xdr_rpc/Makefile.xdr_test new file mode 100644 index 00000000..f26a6e8c --- /dev/null +++ b/SecurityTests/xdr_rpc/Makefile.xdr_test @@ -0,0 +1,36 @@ +# Makefile for XDR RPC test program + +xdr_test: xdr_test.cpp securityd_data_saver.h +### XXX ld64 is broken in Leopard, ca. 9A110 - ? +# g++ -F/usr/local/SecurityPieces/Frameworks \ + -g -Wall -arch ppc -arch i386 -arch ppc64 \ + -o $@ $< \ + -framework securityd_client \ + -framework security_cdsa_utilities \ + -framework security_utilities + + g++ -F/usr/local/SecurityPieces/Frameworks \ + -g -Wall -arch ppc -arch i386 \ + -o $@ $< \ + -framework securityd_client \ + -framework security_cdsa_utilities \ + -framework security_utilities + +# only needed when building a "save data" version of securityd +securityd_data_saver.o: securityd_data_saver.cpp securityd_data_saver.h + g++ -F/usr/local/SecurityPieces/Frameworks \ + -g -Wall -arch ppc -arch i386 -c $< + +# run all tests with minimally verbose output +.PHONY: test +test: xdr_test + @for F in TestData/* ; do ./xdr_test -v $${F} ; done + +# run all tests silently (except for errors) +.PHONY: qtest +qtest: xdr_test + @for F in TestData/* ; do ./xdr_test $${F} ; done + +.PHONY: clean +clean: + /bin/rm -f xdr_test *.o diff --git a/SecurityTests/xdr_rpc/Reference/AclOwnerPrototype_getOwner.decoded b/SecurityTests/xdr_rpc/Reference/AclOwnerPrototype_getOwner.decoded new file mode 100644 index 00000000..0ddf228d --- /dev/null +++ b/SecurityTests/xdr_rpc/Reference/AclOwnerPrototype_getOwner.decoded @@ -0,0 +1,63 @@ +preamble: +0000000 00001234 00000001 000003fe 00000004 + byte order version data type ptr size +0000020 03935c50 000000cf + base ptr # of bytes + +CSSM_ACL_OWNER_PROTOTYPE: + 00000000 03935c60 + TypedSubject. TypedSubject. + ListType Head +0000040 03935ca8 00000000 + TypedSubject. Delegate + Tail + +TypedSubject.Head: + 03935c78 0000007b + NextElement WordID +0000060 00000002 00060000 00000023 00000000 + ElementType +TypedSubject.Head->NextElement: +0000100 03935c90 00000001 00000002 000a0000 + NextElement WordID ElementType +0000120 00000023 00000000 + +TypedSubject.Head->NextElement->NextElement: + 03935ca8 00000001 + NextElement WordID +0000140 00000002 00080000 00000023 00000000 + ElementType +TypedSubject.Head->NextElement->NextElement->NextElement: +0000160 00000000 00000000 00000001 00000000 + NextElement WordID ElementType Sublist. + ListType +0000200 03935cc0 03935cf4 + Sublist.Head Sublist.Tail +TypedSubject.Head->NextElement->NextElement->NextElement->Sublist.Head: + 03935cd8 00010000 + NextElement WordID +0000220 00000002 00225c10 00000026 00000000 + ElementType +TypedSubject.Head->NextElement->NextElement->NextElement->Sublist.Head->NextElement: +0000240 03935cf4 00000000 00000000 00000004 + NextElement WordID ElementType Element.Word. + Length +0000260 03935cf0 00000000 + Element.Word. + Data +TypedSubject.Head->NextElement->NextElement->NextElement->Sublist.Head->NextElement->Element.Word.Data: + 01010000 + Data +TypedSubject.Head->NextElement->NextElement->NextElement->Sublist.Head->NextElement->NextElement: + 00000000 + NextElement +0000300 00000000 00000000 00000013 03935d0c + WordID ElementType Element.Word. Element.Word. + Length Data +0000320 00000000 + +TypedSubject.Head->NextElement->NextElement->NextElement->Sublist.Head->NextElement->NextElement->Element.Word.Data: + 49505365 63205368 61726564 + I P S e c S h a r e d +0000340 20536563 72657400 + S e c r e t diff --git a/SecurityTests/xdr_rpc/Reference/transition.cpp b/SecurityTests/xdr_rpc/Reference/transition.cpp new file mode 100644 index 00000000..77450b2d --- /dev/null +++ b/SecurityTests/xdr_rpc/Reference/transition.cpp @@ -0,0 +1,1244 @@ +/* + * Copyright (c) 2000-2004,2006 Apple Computer, 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@ + */ + + +// +// transition - securityd IPC-to-class-methods transition layer +// +#include +#include "server.h" +#include "session.h" +#include "database.h" +#include "kcdatabase.h" +#include "tokendatabase.h" +#include "kckey.h" +#include "transwalkers.h" +#include "child.h" +#include +#include "securityd_data_saver.h" // for SecuritydDataSave + +#include +#include + + +// +// Bracket Macros +// +#define UCSP_ARGS mach_port_t servicePort, mach_port_t replyPort, audit_token_t auditToken, \ + CSSM_RETURN *rcode +#define CONTEXT_ARGS Context context, Pointer contextBase, Context::Attr *attributes, mach_msg_type_number_t attrSize + +#define BEGIN_IPCN *rcode = CSSM_OK; try { +#define BEGIN_IPC BEGIN_IPCN RefPointer connRef(&Server::connection(replyPort)); \ +Connection &connection __attribute__((unused)) = *connRef; +#define END_IPC(base) END_IPCN(base) Server::requestComplete(); return KERN_SUCCESS; +#define END_IPCN(base) } \ + catch (const CommonError &err) { *rcode = CssmError::cssmError(err, CSSM_ ## base ## _BASE_ERROR); } \ + catch (const std::bad_alloc &) { *rcode = CssmError::merge(CSSM_ERRCODE_MEMORY_ERROR, CSSM_ ## base ## _BASE_ERROR); } \ + catch (Connection *conn) { *rcode = 0; } \ + catch (...) { *rcode = CssmError::merge(CSSM_ERRCODE_INTERNAL_ERROR, CSSM_ ## base ## _BASE_ERROR); } + +#define BEGIN_IPCS try { +#define END_IPCS(more) } catch (...) { } \ + mach_port_deallocate(mach_task_self(), serverPort); more; return KERN_SUCCESS; + +#define DATA_IN(base) void *base, mach_msg_type_number_t base##Length +#define DATA_OUT(base) void **base, mach_msg_type_number_t *base##Length +#define DATA(base) CssmData(base, base##Length) +#define OPTDATA(base) (base ? &CssmData(base, base##Length) : NULL) + +#define SSBLOB(Type, name) makeBlob(DATA(name)) + +#define COPY_IN(type,name) type *name, mach_msg_type_number_t name##Length, type *name##Base +#define COPY_OUT(type,name) \ + type **name, mach_msg_type_number_t *name##Length, type **name##Base + + +using LowLevelMemoryUtilities::increment; +using LowLevelMemoryUtilities::difference; + + +// +// Setup/Teardown functions. +// +kern_return_t ucsp_server_setup(UCSP_ARGS, mach_port_t taskPort, ClientSetupInfo info, const char *identity) +{ + BEGIN_IPCN + Server::active().setupConnection(Server::connectNewProcess, servicePort, replyPort, + taskPort, auditToken, &info, identity); + END_IPCN(CSSM) + return KERN_SUCCESS; +} + +kern_return_t ucsp_server_setupNew(UCSP_ARGS, mach_port_t taskPort, + ClientSetupInfo info, const char *identity, + mach_port_t *newServicePort) +{ + BEGIN_IPCN + try { + RefPointer session = new DynamicSession(taskPort); + Server::active().setupConnection(Server::connectNewSession, session->servicePort(), replyPort, + taskPort, auditToken, &info, identity); + *newServicePort = session->servicePort(); + } catch (const MachPlusPlus::Error &err) { + switch (err.error) { + case BOOTSTRAP_SERVICE_ACTIVE: + MacOSError::throwMe(errSessionAuthorizationDenied); // translate + default: + throw; + } + } + END_IPCN(CSSM) + return KERN_SUCCESS; +} + +kern_return_t ucsp_server_setupThread(UCSP_ARGS, mach_port_t taskPort) +{ + BEGIN_IPCN + Server::active().setupConnection(Server::connectNewThread, servicePort, replyPort, + taskPort, auditToken); + END_IPCN(CSSM) + return KERN_SUCCESS; +} + + +kern_return_t ucsp_server_teardown(UCSP_ARGS) +{ + BEGIN_IPCN + Server::active().endConnection(replyPort); + END_IPCN(CSSM) + return KERN_SUCCESS; +} + + +// +// Common database operations +// +kern_return_t ucsp_server_authenticateDb(UCSP_ARGS, DbHandle db, + CSSM_DB_ACCESS_TYPE accessType, COPY_IN(AccessCredentials, cred)) +{ + BEGIN_IPC + secdebug("dl", "authenticateDb"); + relocate(cred, credBase, credLength); + // ignoring accessType + Server::database(db)->authenticate(accessType, cred); + END_IPC(DL) +} + +kern_return_t ucsp_server_releaseDb(UCSP_ARGS, DbHandle db) +{ + BEGIN_IPC + connection.process().kill(*Server::database(db)); + END_IPC(DL) +} + + +kern_return_t ucsp_server_getDbName(UCSP_ARGS, DbHandle db, char name[PATH_MAX]) +{ + BEGIN_IPC + string result = Server::database(db)->dbName(); + assert(result.length() < PATH_MAX); + memcpy(name, result.c_str(), result.length() + 1); + END_IPC(DL) +} + +kern_return_t ucsp_server_setDbName(UCSP_ARGS, DbHandle db, const char *name) +{ + BEGIN_IPC + Server::database(db)->dbName(name); + END_IPC(DL) +} + + +// +// External database interface +// +kern_return_t ucsp_server_openToken(UCSP_ARGS, uint32 ssid, FilePath name, + COPY_IN(AccessCredentials, accessCredentials), DbHandle *db) +{ + BEGIN_IPC + relocate(accessCredentials, accessCredentialsBase, accessCredentialsLength); + *db = (new TokenDatabase(ssid, connection.process(), name, accessCredentials))->handle(); + END_IPC(DL) +} + +kern_return_t ucsp_server_findFirst(UCSP_ARGS, DbHandle db, + COPY_IN(CssmQuery, query), + COPY_IN(CssmDbRecordAttributeData, inAttributes), + COPY_OUT(CssmDbRecordAttributeData, outAttributes), + boolean_t getData, + DATA_OUT(data), KeyHandle *hKey, SearchHandle *hSearch, RecordHandle *hRecord) +{ + BEGIN_IPC + relocate(query, queryBase, queryLength); + SecuritydDataSave sds("/var/tmp/Query_findFirst"); + sds.writeQuery(query, queryLength); + relocate(inAttributes, inAttributesBase, inAttributesLength); + + RefPointer search; + RefPointer record; + RefPointer key; + CssmData outData; //OutputData outData(data, dataLength); + CssmDbRecordAttributeData *outAttrs; mach_msg_type_number_t outAttrsLength; + Server::database(db)->findFirst(*query, inAttributes, inAttributesLength, + getData ? &outData : NULL, key, search, record, outAttrs, outAttrsLength); + + // handle nothing-found case without exceptions + if (!record) { + *hRecord = noRecord; + *hSearch = noSearch; + *hKey = noKey; + } else { + // return handles + *hRecord = record->handle(); + *hSearch = search->handle(); + *hKey = key ? key->handle() : noKey; + + // return attributes (assumes relocated flat blob) + flips(outAttrs, outAttributes, outAttributesBase); + *outAttributesLength = outAttrsLength; + + // return data (temporary fix) + if (getData) { + *data = outData.data(); + *dataLength = outData.length(); + } + } + END_IPC(DL) +} + +kern_return_t ucsp_server_findNext(UCSP_ARGS, SearchHandle hSearch, + COPY_IN(CssmDbRecordAttributeData, inAttributes), + COPY_OUT(CssmDbRecordAttributeData, outAttributes), + boolean_t getData, DATA_OUT(data), KeyHandle *hKey, + RecordHandle *hRecord) +{ + BEGIN_IPC + relocate(inAttributes, inAttributesBase, inAttributesLength); + RefPointer search = + Server::find(hSearch, CSSMERR_DL_INVALID_RESULTS_HANDLE); + RefPointer record; + RefPointer key; + CssmData outData; //OutputData outData(data, dataLength); + CssmDbRecordAttributeData *outAttrs; mach_msg_type_number_t outAttrsLength; + search->database().findNext(search, inAttributes, inAttributesLength, + getData ? &outData : NULL, key, record, outAttrs, outAttrsLength); + + // handle nothing-found case without exceptions + if (!record) { + *hRecord = noRecord; + *hKey = noKey; + } else { + // return handles + *hRecord = record->handle(); + *hKey = key ? key->handle() : noKey; + + // return attributes (assumes relocated flat blob) + flips(outAttrs, outAttributes, outAttributesBase); + *outAttributesLength = outAttrsLength; + + // return data (temporary fix) + if (getData) { + *data = outData.data(); + *dataLength = outData.length(); + } + } + END_IPC(DL) +} + +kern_return_t ucsp_server_findRecordHandle(UCSP_ARGS, RecordHandle hRecord, + COPY_IN(CssmDbRecordAttributeData, inAttributes), + COPY_OUT(CssmDbRecordAttributeData, outAttributes), + boolean_t getData, DATA_OUT(data), KeyHandle *hKey) +{ + BEGIN_IPC + relocate(inAttributes, inAttributesBase, inAttributesLength); + RefPointer record = + Server::find(hRecord, CSSMERR_DL_INVALID_RECORD_UID); + RefPointer key; + CssmData outData; //OutputData outData(data, dataLength); + CssmDbRecordAttributeData *outAttrs; mach_msg_type_number_t outAttrsLength; + record->database().findRecordHandle(record, inAttributes, inAttributesLength, + getData ? &outData : NULL, key, outAttrs, outAttrsLength); + + // return handles + *hKey = key ? key->handle() : noKey; + + // return attributes (assumes relocated flat blob) + flips(outAttrs, outAttributes, outAttributesBase); + *outAttributesLength = outAttrsLength; + + // return data (temporary fix) + if (getData) { + *data = outData.data(); + *dataLength = outData.length(); + } + END_IPC(DL) +} + +kern_return_t ucsp_server_insertRecord(UCSP_ARGS, DbHandle db, CSSM_DB_RECORDTYPE recordType, + COPY_IN(CssmDbRecordAttributeData, attributes), DATA_IN(data), RecordHandle *record) +{ + BEGIN_IPC + relocate(attributes, attributesBase, attributesLength); + Server::database(db)->insertRecord(recordType, attributes, attributesLength, + DATA(data), *record); + END_IPC(DL) +} + +kern_return_t ucsp_server_modifyRecord(UCSP_ARGS, DbHandle db, RecordHandle *hRecord, + CSSM_DB_RECORDTYPE recordType, COPY_IN(CssmDbRecordAttributeData, attributes), + boolean_t setData, DATA_IN(data), CSSM_DB_MODIFY_MODE modifyMode) +{ + BEGIN_IPC + relocate(attributes, attributesBase, attributesLength); + CssmData newData(DATA(data)); + RefPointer record = + Server::find(*hRecord, CSSMERR_DL_INVALID_RECORD_UID); + Server::database(db)->modifyRecord(recordType, record, attributes, attributesLength, + setData ? &newData : NULL, modifyMode); + // note that the record handle presented to the client never changes here + // (we could, but have no reason to - our record handles are just always up to date) + END_IPC(DL) +} + +kern_return_t ucsp_server_deleteRecord(UCSP_ARGS, DbHandle db, RecordHandle hRecord) +{ + BEGIN_IPC + Server::database(db)->deleteRecord( + Server::find(hRecord, CSSMERR_DL_INVALID_RECORD_UID)); + END_IPC(DL) +} + +kern_return_t ucsp_server_releaseSearch(UCSP_ARGS, SearchHandle hSearch) +{ + BEGIN_IPC + RefPointer search = Server::find(hSearch, 0); + search->database().releaseSearch(*search); + END_IPC(DL) +} + +kern_return_t ucsp_server_releaseRecord(UCSP_ARGS, RecordHandle hRecord) +{ + BEGIN_IPC + RefPointer record = Server::find(hRecord, 0); + record->database().releaseRecord(*record); + END_IPC(DL) +} + +kern_return_t ucsp_server_getRecordFromHandle(UCSP_ARGS, RecordHandle record, + COPY_IN(CssmDbRecordAttributeData, inAttributes), + COPY_OUT(CssmDbRecordAttributeData, outAttributes), + boolean_t getData, + DATA_OUT(data)) +{ + BEGIN_IPC + secdebug("dl", "getRecordFromHandle"); + relocate(inAttributes, inAttributesBase, inAttributesLength); + // @@@ + END_IPC(DL) +} + + +// +// Internal database management +// +kern_return_t ucsp_server_createDb(UCSP_ARGS, DbHandle *db, + COPY_IN(DLDbFlatIdentifier, ident), + COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner), + DBParameters params) +{ + BEGIN_IPC + relocate(cred, credBase, credLength); + relocate(owner, ownerBase, ownerLength); + relocate(ident, identBase, identLength); + *db = (new KeychainDatabase(*ident, params, connection.process(), cred, owner))->handle(); + END_IPC(DL) +} + +// keychain synchronization +// @@@ caller should be required to call decodeDb() to get a DbHandle +// instead of passing the blob itself +kern_return_t ucsp_server_cloneDbForSync(UCSP_ARGS, DATA_IN(blob), + DbHandle srcDb, DATA_IN(agentData), DbHandle *newDb) +{ + BEGIN_IPC + RefPointer srcKC = Server::keychain(srcDb); + *newDb = (new KeychainDatabase(*srcKC, connection.process(), + SSBLOB(DbBlob, blob), DATA(agentData)))->handle(); + END_IPC(DL) +} + +kern_return_t ucsp_server_commitDbForSync(UCSP_ARGS, DbHandle srcDb, + DbHandle cloneDb, DATA_OUT(blob)) +{ + BEGIN_IPC + RefPointer srcKC = Server::keychain(srcDb); + RefPointer cloneKC = Server::keychain(cloneDb); + srcKC->commitSecretsForSync(*cloneKC); + + // re-encode blob for convenience + if (blob && blobLength) { + DbBlob *dbBlob = srcKC->blob(); + *blob = dbBlob; + *blobLength = dbBlob->length(); + } else { + secdebug("kcrecode", "No blob can be returned to client"); + } + END_IPC(DL) +} + +kern_return_t ucsp_server_decodeDb(UCSP_ARGS, DbHandle *db, + COPY_IN(DLDbFlatIdentifier, ident), COPY_IN(AccessCredentials, cred), DATA_IN(blob)) +{ + BEGIN_IPC + relocate(cred, credBase, credLength); + relocate(ident, identBase, identLength); + *db = (new KeychainDatabase(*ident, SSBLOB(DbBlob, blob), + connection.process(), cred))->handle(); + END_IPC(DL) +} + +kern_return_t ucsp_server_encodeDb(UCSP_ARGS, DbHandle db, DATA_OUT(blob)) +{ + BEGIN_IPC + DbBlob *dbBlob = Server::keychain(db)->blob(); // memory owned by database + *blob = dbBlob; + *blobLength = dbBlob->length(); + END_IPC(DL) +} + +kern_return_t ucsp_server_setDbParameters(UCSP_ARGS, DbHandle db, DBParameters params) +{ + BEGIN_IPC + Server::keychain(db)->setParameters(params); + END_IPC(DL) +} + +kern_return_t ucsp_server_getDbParameters(UCSP_ARGS, DbHandle db, DBParameters *params) +{ + BEGIN_IPC + Server::keychain(db)->getParameters(*params); + END_IPC(DL) +} + +kern_return_t ucsp_server_changePassphrase(UCSP_ARGS, DbHandle db, + COPY_IN(AccessCredentials, cred)) +{ + BEGIN_IPC + relocate(cred, credBase, credLength); + Server::keychain(db)->changePassphrase(cred); + END_IPC(DL) +} + +kern_return_t ucsp_server_lockAll (UCSP_ARGS, boolean_t) +{ + BEGIN_IPC + connection.session().processLockAll(); + END_IPC(DL) +} + +kern_return_t ucsp_server_unlockDb(UCSP_ARGS, DbHandle db) +{ + BEGIN_IPC + Server::keychain(db)->unlockDb(); + END_IPC(DL) +} + +kern_return_t ucsp_server_unlockDbWithPassphrase(UCSP_ARGS, DbHandle db, DATA_IN(passphrase)) +{ + BEGIN_IPC + Server::keychain(db)->unlockDb(DATA(passphrase)); + END_IPC(DL) +} + +kern_return_t ucsp_server_isLocked(UCSP_ARGS, DbHandle db, boolean_t *locked) +{ + BEGIN_IPC + *locked = Server::database(db)->isLocked(); + END_IPC(DL) +} + + +// +// Key management +// +kern_return_t ucsp_server_encodeKey(UCSP_ARGS, KeyHandle keyh, DATA_OUT(blob), + boolean_t wantUid, DATA_OUT(uid)) +{ + BEGIN_IPC + RefPointer gKey = Server::key(keyh); + if (KeychainKey *key = dynamic_cast(gKey.get())) { + KeyBlob *keyBlob = key->blob(); // still owned by key + *blob = keyBlob; + *blobLength = keyBlob->length(); + if (wantUid) { // uid generation is not implemented + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + } else { + *uidLength = 0; // do not return this + } + } else { // not a KeychainKey + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); + } + END_IPC(CSP) +} + +kern_return_t ucsp_server_decodeKey(UCSP_ARGS, KeyHandle *keyh, CssmKey::Header *header, + DbHandle db, DATA_IN(blob)) +{ + BEGIN_IPC + RefPointer key = new KeychainKey(*Server::keychain(db), SSBLOB(KeyBlob, blob)); + key->returnKey(*keyh, *header); + flip(*header); + END_IPC(CSP) +} + +// keychain synchronization +kern_return_t ucsp_server_recodeKey(UCSP_ARGS, DbHandle oldDb, KeyHandle keyh, + DbHandle newDb, DATA_OUT(newBlob)) +{ + BEGIN_IPC + // If the old key is passed in as DATA_IN(oldBlob): + // RefPointer key = new KeychainKey(*Server::keychain(oldDb), SSBLOB(KeyBlob, oldBlob)); + RefPointer key = Server::key(keyh); + if (KeychainKey *kckey = dynamic_cast(key.get())) { + KeyBlob *blob = Server::keychain(newDb)->recodeKey(*kckey); + *newBlob = blob; + *newBlobLength = blob->length(); + Server::releaseWhenDone(*newBlob); + // @@@ stop leaking blob + } else { // not a KeychainKey + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); + } + END_IPC(CSP) +} + +kern_return_t ucsp_server_releaseKey(UCSP_ARGS, KeyHandle keyh) +{ + BEGIN_IPC + RefPointer key = Server::key(keyh); + key->database().releaseKey(*key); + END_IPC(CSP) +} + +kern_return_t ucsp_server_queryKeySizeInBits(UCSP_ARGS, KeyHandle keyh, CSSM_KEY_SIZE *length) +{ + BEGIN_IPC + RefPointer key = Server::key(keyh); + key->database().queryKeySizeInBits(*key, CssmKeySize::overlay(*length)); + END_IPC(CSP) +} + +kern_return_t ucsp_server_getOutputSize(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh, + uint32 inputSize, boolean_t encrypt, uint32 *outputSize) +{ + BEGIN_IPC + relocate(context, contextBase, attributes, attrSize); + RefPointer key = Server::key(keyh); + key->database().getOutputSize(context, *key, inputSize, encrypt, *outputSize); + END_IPC(CSP) +} + +kern_return_t ucsp_server_getKeyDigest(UCSP_ARGS, KeyHandle key, DATA_OUT(digest)) +{ + BEGIN_IPC + CssmData digestData = Server::key(key)->canonicalDigest(); + *digest = digestData.data(); + *digestLength = digestData.length(); + END_IPC(CSP) +} + + +// +// Signatures and MACs +// +kern_return_t ucsp_server_generateSignature(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh, + CSSM_ALGORITHMS signOnlyAlgorithm, DATA_IN(data), DATA_OUT(signature)) +{ + BEGIN_IPC + relocate(context, contextBase, attributes, attrSize); + RefPointer key = Server::key(keyh); + OutputData sigData(signature, signatureLength); + key->database().generateSignature(context, *key, signOnlyAlgorithm, + DATA(data), sigData); + END_IPC(CSP) +} + +kern_return_t ucsp_server_verifySignature(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh, + CSSM_ALGORITHMS verifyOnlyAlgorithm, DATA_IN(data), DATA_IN(signature)) +{ + BEGIN_IPC + relocate(context, contextBase, attributes, attrSize); + RefPointer key = Server::key(keyh); + key->database().verifySignature(context, *key, verifyOnlyAlgorithm, + DATA(data), DATA(signature)); + END_IPC(CSP) +} + +kern_return_t ucsp_server_generateMac(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh, + DATA_IN(data), DATA_OUT(mac)) +{ + BEGIN_IPC + relocate(context, contextBase, attributes, attrSize); + RefPointer key = Server::key(keyh); + OutputData macData(mac, macLength); + key->database().generateMac(context, *key, DATA(data), macData); + END_IPC(CSP) +} + +kern_return_t ucsp_server_verifyMac(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh, + DATA_IN(data), DATA_IN(mac)) +{ + BEGIN_IPC + relocate(context, contextBase, attributes, attrSize); + RefPointer key = Server::key(keyh); + key->database().verifyMac(context, *key, DATA(data), DATA(mac)); + END_IPC(CSP) +} + + +// +// Encryption/Decryption +// +kern_return_t ucsp_server_encrypt(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh, + DATA_IN(clear), DATA_OUT(cipher)) +{ + BEGIN_IPC + relocate(context, contextBase, attributes, attrSize); + RefPointer key = Server::key(keyh); + OutputData cipherOut(cipher, cipherLength); + key->database().encrypt(context, *key, DATA(clear), cipherOut); + END_IPC(CSP) +} + +kern_return_t ucsp_server_decrypt(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh, + DATA_IN(cipher), DATA_OUT(clear)) +{ + BEGIN_IPC + SecuritydDataSave sds("/var/tmp/securityd_Context_decrypt"); // XXX/gh get sample Context for XDR testing + relocate(context, contextBase, attributes, attrSize); + // save attributes base addr for backwards compatibility + intptr_t attraddr = reinterpret_cast(&context->ContextAttributes); + sds.writeContext(&context, attraddr, attrSize); + RefPointer key = Server::key(keyh); + OutputData clearOut(clear, clearLength); + key->database().decrypt(context, *key, DATA(cipher), clearOut); + END_IPC(CSP) +} + + +// +// Key generation +// +kern_return_t ucsp_server_generateKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, + COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner), + uint32 usage, uint32 attrs, KeyHandle *newKey, CssmKey::Header *newHeader) +{ + BEGIN_IPC + relocate(context, contextBase, attributes, attrSize); + relocate(cred, credBase, credLength); + relocate(owner, ownerBase, ownerLength); + //@@@ preliminary interpretation - will get "type handle" + RefPointer database = + Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT); + RefPointer key; + database->generateKey(context, cred, owner, usage, attrs, key); + key->returnKey(*newKey, *newHeader); + flip(*newHeader); + END_IPC(CSP) +} + +kern_return_t ucsp_server_generateKeyPair(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, + COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner), + uint32 pubUsage, uint32 pubAttrs, uint32 privUsage, uint32 privAttrs, + KeyHandle *pubKey, CssmKey::Header *pubHeader, KeyHandle *privKey, CssmKey::Header *privHeader) +{ + BEGIN_IPC + relocate(context, contextBase, attributes, attrSize); + relocate(cred, credBase, credLength); + relocate(owner, ownerBase, ownerLength); + RefPointer database = + Server::optionalDatabase(db, (privAttrs | pubAttrs) & CSSM_KEYATTR_PERMANENT); + RefPointer pub, priv; + database->generateKey(context, cred, owner, + pubUsage, pubAttrs, privUsage, privAttrs, pub, priv); + pub->returnKey(*pubKey, *pubHeader); + flip(*pubHeader); + priv->returnKey(*privKey, *privHeader); + flip(*privHeader); + END_IPC(CSP) +} + + +// +// Key wrapping and unwrapping +// +kern_return_t ucsp_server_wrapKey(UCSP_ARGS, CONTEXT_ARGS, KeyHandle hWrappingKey, + COPY_IN(AccessCredentials, cred), KeyHandle hKeyToBeWrapped, + DATA_IN(descriptiveData), CssmKey *wrappedKey, DATA_OUT(keyData)) +{ + BEGIN_IPC + relocate(context, contextBase, attributes, attrSize); + relocate(cred, credBase, credLength); + RefPointer subjectKey = Server::key(hKeyToBeWrapped); + RefPointer wrappingKey = Server::optionalKey(hWrappingKey); + if ((context.algorithm() == CSSM_ALGID_NONE && subjectKey->attribute(CSSM_KEYATTR_SENSITIVE)) + || !subjectKey->attribute(CSSM_KEYATTR_EXTRACTABLE)) + CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); + pickDb(subjectKey, wrappingKey)->wrapKey(context, cred, wrappingKey, *subjectKey, DATA(descriptiveData), *wrappedKey); + + // transmit key data back as a separate blob + OutputData keyDatas(keyData, keyDataLength); + keyDatas = wrappedKey->keyData(); + flip(*wrappedKey); + END_IPC(CSP) +} + +kern_return_t ucsp_server_unwrapKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, + KeyHandle hWrappingKey, COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner), + KeyHandle hPublicKey, CssmKey wrappedKey, DATA_IN(wrappedKeyData), + CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, DATA_OUT(descriptiveData), + KeyHandle *newKey, CssmKey::Header *newHeader) +{ + BEGIN_IPC + relocate(context, contextBase, attributes, attrSize); + flip(wrappedKey); + wrappedKey.keyData() = DATA(wrappedKeyData); + relocate(cred, credBase, credLength); + relocate(owner, ownerBase, ownerLength); + OutputData descriptiveDatas(descriptiveData, descriptiveDataLength); + RefPointer wrappingKey = Server::optionalKey(hWrappingKey); + RefPointer unwrappedKey; + pickDb(Server::optionalDatabase(db), wrappingKey)->unwrapKey(context, cred, owner, + wrappingKey, Server::optionalKey(hPublicKey), + usage, attrs, wrappedKey, unwrappedKey, descriptiveDatas); + unwrappedKey->returnKey(*newKey, *newHeader); + flip(*newHeader); + END_IPC(CSP) +} + + +// +// Key derivation. +// +// Note that the "param" argument can have structure. The walker for the +// (artificial) POD CssmDeriveData handles those that are known; if you add +// an algorithm with structured param, you need to add a case there. +// +kern_return_t ucsp_server_deriveKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, KeyHandle hKey, + COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner), + COPY_IN(CssmDeriveData, paramInput), DATA_OUT(paramOutput), + uint32 usage, uint32 attrs, KeyHandle *newKey, CssmKey::Header *newHeader) +{ + BEGIN_IPC + relocate(context, contextBase, attributes, attrSize); + relocate(cred, credBase, credLength); + relocate(owner, ownerBase, ownerLength); + relocate(paramInput, paramInputBase, paramInputLength); + if (!paramInput || paramInput->algorithm != context.algorithm()) + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); // client layer fault + + RefPointer database = + Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT); + RefPointer key = Server::optionalKey(hKey); + CssmData *param = paramInput ? ¶mInput->baseData : NULL; + RefPointer derivedKey; + pickDb(Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT), + key)->deriveKey(context, key, cred, owner, param, usage, attrs, derivedKey); + derivedKey->returnKey(*newKey, *newHeader); + flip(*newHeader); + if (param && param->length()) { + if (!param->data()) // CSP screwed up + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); + if (paramInputLength) // using incoming buffer; make a copy + *param = CssmAutoData(Server::csp().allocator(), *param).release(); + OutputData(paramOutput, paramOutputLength) = *param; // return the data + } + END_IPC(CSP) +} + + +// +// Random generation +// +kern_return_t ucsp_server_generateRandom(UCSP_ARGS, uint32 ssid, CONTEXT_ARGS, DATA_OUT(data)) +{ + BEGIN_IPC + relocate(context, contextBase, attributes, attrSize); + if (ssid) + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + + // default version (use /dev/random) + Allocator &allocator = Allocator::standard(Allocator::sensitive); + if (size_t bytes = context.getInt(CSSM_ATTRIBUTE_OUTPUT_SIZE)) { + void *buffer = allocator.malloc(bytes); + Server::active().random(buffer, bytes); + *data = buffer; + *dataLength = bytes; + Server::releaseWhenDone(allocator, buffer); + } + END_IPC(CSP) +} + + +// +// ACL management. +// Watch out for the memory-management tap-dance. +// +kern_return_t ucsp_server_getOwner(UCSP_ARGS, AclKind kind, KeyHandle key, + COPY_OUT(AclOwnerPrototype, ownerOut)) +{ + BEGIN_IPC + AclOwnerPrototype owner; + Server::aclBearer(kind, key).getOwner(owner); // allocates memory in owner + Copier owners(&owner, Allocator::standard()); // make flat copy + { ChunkFreeWalker free; walk(free, owner); } // release chunked original + *ownerOutLength = owners.length(); + flips(owners.value(), ownerOut, ownerOutBase); + Server::releaseWhenDone(owners.keep()); // throw flat copy out when done + END_IPC(CSP) +} + +kern_return_t ucsp_server_setOwner(UCSP_ARGS, AclKind kind, KeyHandle key, + COPY_IN(AccessCredentials, cred), COPY_IN(AclOwnerPrototype, owner)) +{ + BEGIN_IPC + relocate(cred, credBase, credLength); + relocate(owner, ownerBase, ownerLength); + Server::aclBearer(kind, key).changeOwner(*owner, cred); + END_IPC(CSP) +} + +kern_return_t ucsp_server_getAcl(UCSP_ARGS, AclKind kind, KeyHandle key, + boolean_t haveTag, const char *tag, + uint32 *countp, COPY_OUT(AclEntryInfo, acls)) +{ + BEGIN_IPC + uint32 count; + AclEntryInfo *aclList; + Server::aclBearer(kind, key).getAcl(haveTag ? tag : NULL, count, aclList); + *countp = count; + Copier aclsOut(aclList, count); // make flat copy + + { // release the chunked memory originals + ChunkFreeWalker free; + for (uint32 n = 0; n < count; n++) + walk(free, aclList[n]); + + // release the memory allocated for the list itself when we are done + Allocator::standard().free (aclList); + } + + // set result (note: this is *almost* flips(), but on an array) + *aclsLength = aclsOut.length(); + *acls = *aclsBase = aclsOut; + if (flipClient()) { + FlipWalker w; + for (uint32 n = 0; n < count; n++) + walk(w, (*acls)[n]); + w.doFlips(); + Flippers::flip(*aclsBase); + } + SecuritydDataSave sds("/var/tmp/AclEntryInfo_getAcl"); + sds.writeAclEntryInfo(*acls, *aclsLength); + Server::releaseWhenDone(aclsOut.keep()); + END_IPC(CSP) +} + +kern_return_t ucsp_server_changeAcl(UCSP_ARGS, AclKind kind, KeyHandle key, + COPY_IN(AccessCredentials, cred), CSSM_ACL_EDIT_MODE mode, CSSM_ACL_HANDLE handle, + COPY_IN(AclEntryInput, acl)) +{ + BEGIN_IPC + relocate(cred, credBase, credLength); + relocate(acl, aclBase, aclLength); + SecuritydDataSave sds("/var/tmp/AclEntryInput_changeAcl"); + sds.writeAclEntryInput(acl, aclLength); + Server::aclBearer(kind, key).changeAcl(AclEdit(mode, handle, acl), cred); + END_IPC(CSP) +} + + +// +// Login/Logout +// +kern_return_t ucsp_server_login(UCSP_ARGS, COPY_IN(AccessCredentials, cred), DATA_IN(name)) +{ + BEGIN_IPC + relocate(cred, credBase, credLength); + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + END_IPC(CSP) +} + +kern_return_t ucsp_server_logout(UCSP_ARGS) +{ + BEGIN_IPC + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + END_IPC(CSP) +} + + +// +// Miscellaneous CSP-related calls +// +kern_return_t ucsp_server_getStatistics(UCSP_ARGS, uint32 ssid, CSPOperationalStatistics *statistics) +{ + BEGIN_IPC + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + END_IPC(CSP) +} + +kern_return_t ucsp_server_getTime(UCSP_ARGS, uint32 ssid, CSSM_ALGORITHMS algorithm, DATA_OUT(data)) +{ + BEGIN_IPC + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + END_IPC(CSP) +} + +kern_return_t ucsp_server_getCounter(UCSP_ARGS, uint32 ssid, DATA_OUT(data)) +{ + BEGIN_IPC + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + END_IPC(CSP) +} + +kern_return_t ucsp_server_selfVerify(UCSP_ARGS, uint32 ssid) +{ + BEGIN_IPC + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + END_IPC(CSP) +} + + +// +// Passthrough calls (separate for CSP and DL passthroughs) +// +kern_return_t ucsp_server_cspPassThrough(UCSP_ARGS, uint32 ssid, uint32 id, CONTEXT_ARGS, + KeyHandle hKey, DATA_IN(inData), DATA_OUT(outData)) +{ + BEGIN_IPC + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + END_IPC(CSP) +} + +kern_return_t ucsp_server_dlPassThrough(UCSP_ARGS, uint32 ssid, uint32 id, + DATA_IN(inData), DATA_OUT(outData)) +{ + BEGIN_IPC + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + END_IPC(DL) +} + + +// +// Database key management. +// ExtractMasterKey looks vaguely like a key derivation operation, and is in fact +// presented by the CSPDL's CSSM layer as such. +// +kern_return_t ucsp_server_extractMasterKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, DbHandle sourceDb, + COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner), + uint32 usage, uint32 attrs, KeyHandle *newKey, CssmKey::Header *newHeader) +{ + BEGIN_IPC + context.postIPC(contextBase, attributes); + relocate(cred, credBase, credLength); + relocate(owner, ownerBase, ownerLength); + RefPointer keychain = Server::keychain(sourceDb); + RefPointer masterKey = keychain->extractMasterKey( + *Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT), + cred, owner, usage, attrs); + masterKey->returnKey(*newKey, *newHeader); + flip(*newHeader); + END_IPC(CSP) +} + + +// +// Authorization subsystem support +// +kern_return_t ucsp_server_authorizationCreate(UCSP_ARGS, + COPY_IN(AuthorizationItemSet, inRights), + uint32 flags, + COPY_IN(AuthorizationItemSet, inEnvironment), + AuthorizationBlob *authorization) +{ + BEGIN_IPC + relocate(inRights, inRightsBase, inRightsLength); + relocate(inEnvironment, inEnvironmentBase, inEnvironmentLength); + Authorization::AuthItemSet rights(inRights), environment(inEnvironment); + + *rcode = connection.process().session().authCreate(rights, environment, + flags, *authorization, auditToken); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_authorizationRelease(UCSP_ARGS, + AuthorizationBlob authorization, uint32 flags) +{ + BEGIN_IPC + connection.process().session().authFree(authorization, flags); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_authorizationCopyRights(UCSP_ARGS, + AuthorizationBlob authorization, + COPY_IN(AuthorizationItemSet, inRights), + uint32 flags, + COPY_IN(AuthorizationItemSet, inEnvironment), + COPY_OUT(AuthorizationItemSet, result)) +{ + BEGIN_IPC + relocate(inRights, inRightsBase, inRightsLength); + relocate(inEnvironment, inEnvironmentBase, inEnvironmentLength); + Authorization::AuthItemSet rights(inRights), environment(inEnvironment), grantedRights; + *rcode = connection.process().session().authGetRights(authorization, + rights, environment, flags, grantedRights); + if (result && resultLength) + { + size_t resultSize; + grantedRights.copy(*result, resultSize); + *resultLength = resultSize; + *resultBase = *result; + flips(*result, result, resultBase); + Server::releaseWhenDone(*result); + } + END_IPC(CSSM) +} + +kern_return_t ucsp_server_authorizationCopyInfo(UCSP_ARGS, + AuthorizationBlob authorization, + AuthorizationString tag, + COPY_OUT(AuthorizationItemSet, info)) +{ + BEGIN_IPC + Authorization::AuthItemSet infoSet; + *info = *infoBase = NULL; + *infoLength = 0; + *rcode = connection.process().session().authGetInfo(authorization, + tag[0] ? tag : NULL, infoSet); + if (*rcode == noErr) { + size_t infoSize; + infoSet.copy(*info, infoSize); + *infoLength = infoSize; + *infoBase = *info; + flips(*info, info, infoBase); + Server::releaseWhenDone(*info); + } + END_IPC(CSSM) +} + +kern_return_t ucsp_server_authorizationExternalize(UCSP_ARGS, + AuthorizationBlob authorization, AuthorizationExternalForm *extForm) +{ + BEGIN_IPC + *rcode = connection.process().session().authExternalize(authorization, *extForm); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_authorizationInternalize(UCSP_ARGS, + AuthorizationExternalForm extForm, AuthorizationBlob *authorization) +{ + BEGIN_IPC + *rcode = connection.process().session().authInternalize(extForm, *authorization); + END_IPC(CSSM) +} + + +// +// Session management subsystem +// +kern_return_t ucsp_server_getSessionInfo(UCSP_ARGS, + SecuritySessionId *sessionId, SessionAttributeBits *attrs) +{ + BEGIN_IPC + Session &session = Session::find(*sessionId); + *sessionId = session.handle(); + *attrs = session.attributes(); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_setupSession(UCSP_ARGS, + SessionCreationFlags flags, SessionAttributeBits attrs) +{ + BEGIN_IPC + Server::process().session().setupAttributes(flags, attrs); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_setSessionDistinguishedUid(UCSP_ARGS, + SecuritySessionId sessionId, uid_t user) +{ + BEGIN_IPC + Session::find(sessionId).originatorUid(user); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_getSessionDistinguishedUid(UCSP_ARGS, + SecuritySessionId sessionId, uid_t *user) +{ + BEGIN_IPC + *user = Session::find(sessionId).originatorUid(); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_setSessionUserPrefs(UCSP_ARGS, SecuritySessionId sessionId, DATA_IN(userPrefs)) +{ + BEGIN_IPC + CFRef data(CFDataCreate(NULL, (UInt8 *)userPrefs, userPrefsLength)); + + if (!data) + { + *rcode = errSessionValueNotSet; + return 0; + } + + Session::find(sessionId).setUserPrefs(data); + *rcode = 0; + + END_IPC(CSSM) +} + + + +// +// Notification core subsystem +// +kern_return_t ucsp_server_requestNotification(UCSP_ARGS, mach_port_t receiver, uint32 domain, uint32 events) +{ + BEGIN_IPC + connection.process().requestNotifications(receiver, domain, events); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_stopNotification(UCSP_ARGS, mach_port_t receiver) +{ + BEGIN_IPC + connection.process().stopNotifications(receiver); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_postNotification(mach_port_t serverPort, uint32 domain, uint32 event, DATA_IN(data)) +{ + BEGIN_IPCS + Listener::notify(domain, event, DATA(data)); + END_IPCS() +} + + +// +// AuthorizationDB modification +// +kern_return_t ucsp_server_authorizationdbGet(UCSP_ARGS, const char *rightname, DATA_OUT(rightDefinition)) +{ + BEGIN_IPC + CFDictionaryRef rightDict; + + *rcode = connection.process().session().authorizationdbGet(rightname, &rightDict); + + if (!*rcode && rightDict) + { + CFRef data(CFPropertyListCreateXMLData (NULL, rightDict)); + CFRelease(rightDict); + if (!data) + return errAuthorizationInternal; + + // @@@ copy data to avoid having to do a delayed cfrelease + mach_msg_type_number_t length = CFDataGetLength(data); + void *xmlData = Allocator::standard().malloc(length); + memcpy(xmlData, CFDataGetBytePtr(data), length); + Server::releaseWhenDone(xmlData); + + *rightDefinition = xmlData; + *rightDefinitionLength = length; + } + END_IPC(CSSM) +} + +kern_return_t ucsp_server_authorizationdbSet(UCSP_ARGS, AuthorizationBlob authorization, const char *rightname, DATA_IN(rightDefinition)) +{ + BEGIN_IPC + CFRef data(CFDataCreate(NULL, (UInt8 *)rightDefinition, rightDefinitionLength)); + + if (!data) + return errAuthorizationInternal; + + CFRef rightDefinition(static_cast(CFPropertyListCreateFromXMLData(NULL, data, kCFPropertyListImmutable, NULL))); + + if (!rightDefinition || (CFGetTypeID(rightDefinition) != CFDictionaryGetTypeID())) + return errAuthorizationInternal; + + *rcode = connection.process().session().authorizationdbSet(authorization, rightname, rightDefinition); + + END_IPC(CSSM) +} + +kern_return_t ucsp_server_authorizationdbRemove(UCSP_ARGS, AuthorizationBlob authorization, const char *rightname) +{ + BEGIN_IPC + *rcode = connection.process().session().authorizationdbRemove(authorization, rightname); + END_IPC(CSSM) +} + + +// +// Miscellaneous administrative functions +// +kern_return_t ucsp_server_addCodeEquivalence(UCSP_ARGS, DATA_IN(oldHash), DATA_IN(newHash), + const char *name, boolean_t forSystem) +{ + BEGIN_IPC + Server::codeSignatures().addLink(DATA(oldHash), DATA(newHash), name, forSystem); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_removeCodeEquivalence(UCSP_ARGS, DATA_IN(hash), + const char *name, boolean_t forSystem) +{ + BEGIN_IPC + Server::codeSignatures().removeLink(DATA(hash), name, forSystem); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_setAlternateSystemRoot(UCSP_ARGS, const char *root) +{ + BEGIN_IPC +#if defined(NDEBUG) + if (connection.process().uid() != 0) + CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED); +#endif //NDEBUG + Server::codeSignatures().open((string(root) + EQUIVALENCEDBPATH).c_str()); + END_IPC(CSSM) +} + + +// +// Child check-in service. +// Note that this isn't using the standard argument pattern. +// +kern_return_t ucsp_server_childCheckIn(mach_port_t serverPort, + mach_port_t servicePort, mach_port_t taskPort) +{ + BEGIN_IPCS + ServerChild::checkIn(servicePort, TaskPort(taskPort).pid()); + END_IPCS(mach_port_deallocate(mach_task_self(), taskPort)) +} diff --git a/SecurityTests/xdr_rpc/TestData/AclEntryInfo_getAcl b/SecurityTests/xdr_rpc/TestData/AclEntryInfo_getAcl new file mode 100644 index 0000000000000000000000000000000000000000..5921d523f2f4ec7004c1ff71a28cbd0b53c0045d GIT binary patch literal 1072 zcmZuwL2J}d5S~qfRrFAFk)l!qwIYa{9ux(8sPq(FYhhJ-O}7ubl1)OAip3rkM0zNV zAV~2SsCekzqJozm3iaT@Lkm6hVAJiPvIlAX=DoKPN(a8o%=hNao0<1Qbn+?@m53~W zEQ@}#>cNL#uUVA8W*c(EqU{sV94Ez`Tb}LMtj)}uVHCN8_R)ic@?}oszW^-gkdj5M zGTX@cgCY6-{XM-d75ElIaiv|9w`*o+m*9Uda?C48-av0{tUm(`x{^%NRFI0e;#suS z4UX$EFaRlLHa-ac5*$dykKIeLObOJU{pFdV6DUz1LoKJ3(6aA$E~%=T;Q?jk=dM!XR;6 zZYU6`JsbvssHYV#iYO}FXQ$p4xGKO`qv}1)Gq-hrxeZ>`dkz-F%+CDfJ<5|`)SKU+ zo}HDQcb{jTewh!;mD#U%UcLG7cE0ydA&$)f#7?l`)TWbEG@WW=oLhB3Gun8>xpTiJa*SI#$x7pdiF8mFi`r&hE Ok&6)?GKW>{?fVDEX}@0p literal 0 HcmV?d00001 diff --git a/SecurityTests/xdr_rpc/TestData/AclEntryInput_changeAcl b/SecurityTests/xdr_rpc/TestData/AclEntryInput_changeAcl new file mode 100644 index 0000000000000000000000000000000000000000..4434bb4cbe68eb90123281bd89782ae2b884d9af GIT binary patch literal 404 zcmZQz5Hew4U|?imVEzxJS(uJ(0C8)81Ot#=0>p1XY#?A`I<_$d!lVrew5tbbay1Y$ zF);gf+20V}Z8roM7=)pcY(Np9 zenu0ZoQ(s-oCu~PjRguo!+~l9fb0`M^=v>k2yj6tnv={x_iRA61;~E@!Z0x)`v=f% zK&L?fknI4(5imX|bbx>f2;l&#z8WI_{{UFRqQwBN034=3O-C9vKo~3zHwUU7Cz5kw6TJ eOMCzrkBvuIA`CVF6>$LB7sA@R+h#wi&;G^b5b8lJ zoO+mmk|f$A05T9_k3Aol0}_A$?DoK9L9|FfCNdYu#;OP8XOP=KfDsrjG7u&z2^6=0 zih%tAeIjgawb-LT7VKDzko0k9(zK7@*n`SCjra@3Cw56 zfwEz86-aKl0F(o{Ap_(F&%Bh>ijc~JR0f3tsCWZJFIKlvBMc0n_V@s4fq@PKkQ)Xd z3=)vSfNy}p0O$lrIsnpqh%f*NgT))bEbM6%l=k_77?S7gj!b~4g^^g(4oD9$zM*<- Kq#wXkgJ=LBiel#g literal 0 HcmV?d00001 diff --git a/SecurityTests/xdr_rpc/securityd_data_saver.cpp b/SecurityTests/xdr_rpc/securityd_data_saver.cpp new file mode 100644 index 00000000..8c2b466e --- /dev/null +++ b/SecurityTests/xdr_rpc/securityd_data_saver.cpp @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2006 Apple Computer, 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 "securityd_data_saver.h" + +/* + * Please don't use this as an exemplar for new write...() calls. This was + * the first, is messy, and probably should be rewritten. At the very + * least, its correctness should be revisited. + */ +void +SecuritydDataSave::writeContext(Context *context, intptr_t attraddr, + mach_msg_type_number_t attrSize) +{ + // finish the preamble + uint32_t dtype = CONTEXT; + writeAll(&dtype, sizeof(dtype)); + + // save size of a CSSM_CONTEXT (not strictly necessary) + uint32_t csize = sizeof(CSSM_CONTEXT); + writeAll(&csize, sizeof(csize)); // write the length first! + writeAll(context, csize); + + // save the original base address for relocation + csize = sizeof(attraddr); + writeAll(&csize, sizeof(csize)); + writeAll(&attraddr, csize); + + // finally, save off the attributes + csize = attrSize; + writeAll(&csize, sizeof(csize)); + writeAll(context->ContextAttributes, csize); +} + +void +SecuritydDataSave::writeAclEntryInfo(AclEntryInfo *acls, + mach_msg_type_number_t aclsLength) +{ + // finish the preamble + uint32_t dtype = ACL_ENTRY_INFO; + writeAll(&dtype, sizeof(dtype)); + + // write the base pointer, then the ACL itself + uint32_t ptrsize = sizeof(acls); + writeAll(&ptrsize, sizeof(ptrsize)); + writeAll(&acls, ptrsize); + writeAll(&aclsLength, sizeof(aclsLength)); + writeAll(acls, aclsLength); +} + +void +SecuritydDataSave::writeAclEntryInput(AclEntryInput *acl, + mach_msg_type_number_t aclLength) +{ + // finish the preamble + uint32_t dtype = ACL_ENTRY_INPUT; + writeAll(&dtype, sizeof(dtype)); + + // write the pointer, then the ACL itself + uint32_t ptrsize = sizeof(acl); + writeAll(&ptrsize, sizeof(ptrsize)); + writeAll(&acl, ptrsize); + writeAll(&aclLength, sizeof(aclLength)); + writeAll(acl, aclLength); +} + + +// +// Excerpts from securityd's transition.cpp showing where SecuritydDataSave +// is (to be) used +// + +#if 0 +kern_return_t ucsp_server_findFirst(UCSP_ARGS, DbHandle db, + COPY_IN(CssmQuery, query), + COPY_IN(CssmDbRecordAttributeData, inAttributes), + COPY_OUT(CssmDbRecordAttributeData, outAttributes), + boolean_t getData, + DATA_OUT(data), KeyHandle *hKey, SearchHandle *hSearch, RecordHandle *hRecord) +{ + BEGIN_IPC + relocate(query, queryBase, queryLength); + SecuritydDataSave sds("/var/tmp/Query_findFirst"); + sds.writeQuery(query, queryLength); + relocate(inAttributes, inAttributesBase, inAttributesLength); + + RefPointer search; + RefPointer record; + RefPointer key; + CssmData outData; //OutputData outData(data, dataLength); + CssmDbRecordAttributeData *outAttrs; mach_msg_type_number_t outAttrsLength; + Server::database(db)->findFirst(*query, inAttributes, inAttributesLength, + getData ? &outData : NULL, key, search, record, outAttrs, outAttrsLength); + + // handle nothing-found case without exceptions + if (!record) { + *hRecord = noRecord; + *hSearch = noSearch; + *hKey = noKey; + } else { + // return handles + *hRecord = record->handle(); + *hSearch = search->handle(); + *hKey = key ? key->handle() : noKey; + + // return attributes (assumes relocated flat blob) + flips(outAttrs, outAttributes, outAttributesBase); + *outAttributesLength = outAttrsLength; + + // return data (temporary fix) + if (getData) { + *data = outData.data(); + *dataLength = outData.length(); + } + } + END_IPC(DL) +} + +kern_return_t ucsp_server_decrypt(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh, + DATA_IN(cipher), DATA_OUT(clear)) +{ + BEGIN_IPC + SecuritydDataSave td("/var/tmp/securityd_Context_decrypt"); // XXX/gh get sample Context for XDR testing + relocate(context, contextBase, attributes, attrSize); + // save attributes base addr for backwards compatibility + intptr_t attraddr = reinterpret_cast(&context->ContextAttributes); + td.writeContext(&context, attraddr, attrSize); + RefPointer key = Server::key(keyh); + OutputData clearOut(clear, clearLength); + key->database().decrypt(context, *key, DATA(cipher), clearOut); + END_IPC(CSP) +} + +// ... + +kern_return_t ucsp_server_getAcl(UCSP_ARGS, AclKind kind, KeyHandle key, + boolean_t haveTag, const char *tag, + uint32 *countp, COPY_OUT(AclEntryInfo, acls)) +{ + BEGIN_IPC + uint32 count; + AclEntryInfo *aclList; + Server::aclBearer(kind, key).getAcl(haveTag ? tag : NULL, count, aclList); + *countp = count; + Copier aclsOut(aclList, count); // make flat copy + + { // release the chunked memory originals + ChunkFreeWalker free; + for (uint32 n = 0; n < count; n++) + walk(free, aclList[n]); + + // release the memory allocated for the list itself when we are done + Allocator::standard().free (aclList); + } + + // set result (note: this is *almost* flips(), but on an array) + *aclsLength = aclsOut.length(); + *acls = *aclsBase = aclsOut; + if (flipClient()) { + FlipWalker w; + for (uint32 n = 0; n < count; n++) + walk(w, (*acls)[n]); + w.doFlips(); + Flippers::flip(*aclsBase); + } + SecuritydDataSave sds("/var/tmp/AclEntryInfo_getAcl"); + sds.writeAclEntryInfo(*acls, *aclsLength); + Server::releaseWhenDone(aclsOut.keep()); + END_IPC(CSP) +} + +kern_return_t ucsp_server_changeAcl(UCSP_ARGS, AclKind kind, KeyHandle key, + COPY_IN(AccessCredentials, cred), CSSM_ACL_EDIT_MODE mode, CSSM_ACL_HANDLE handle, + COPY_IN(AclEntryInput, acl)) +{ + BEGIN_IPC + relocate(cred, credBase, credLength); + relocate(acl, aclBase, aclLength); + SecuritydDataSave sds("/var/tmp/AclEntryInput_changeAcl"); + sds.writeAclEntryInput(acl, aclLength); + Server::aclBearer(kind, key).changeAcl(AclEdit(mode, handle, acl), cred); + END_IPC(CSP) +} + +#endif /* 0 -- example code */ diff --git a/SecurityTests/xdr_rpc/securityd_data_saver.h b/SecurityTests/xdr_rpc/securityd_data_saver.h new file mode 100644 index 00000000..0464ba6c --- /dev/null +++ b/SecurityTests/xdr_rpc/securityd_data_saver.h @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2006 Apple Computer, 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 _SECURITYD_DATA_SAVER_H_ +#define _SECURITYD_DATA_SAVER_H_ + +#include +#include +#include +#include + +// +// Possible enhancement: have class silently do nothing on write if the +// file already exists. This would keep us from writing > 1 of the given +// object. +// +// XXX/gh this should handle readPreamble() as well +// +class SecuritydDataSave: public Security::UnixPlusPlus::AutoFileDesc +{ +public: + // For x-platform consistency, sentry and version must be fixed-size + static const uint32_t sentry = 0x1234; // byte order sentry value + static const uint32_t version = 1; + // define type of data saved; naming convention is to strip CSSM_ + // most of these will probably never be used + enum + { + s32 = 32, // signed 32-bit + u32 = 33, // unsigned 32-bit + s64 = 64, + u64 = 65, + // leave some space: we might need to discriminate among the + // various integer types (although I can't see why we'd care to + // save them by themselves) + DATA = 1000, + GUID = 1001, + VERSION = 1002, + SUBSERVICE_UID = 1003, + NET_ADDRESS = 1004, + CRYPTO_DATA = 1005, + LIST = 1006, + LIST_ELEMENT = 1007, + TUPLE = 1008, + TUPLEGROUP = 1009, + SAMPLE = 1010, + SAMPLEGROUP = 1011, + MEMORY_FUNCS = 1012, + ENCODED_CERT = 1013, + PARSED_CERT = 1014, + CERT_PAIR = 1015, + CERTGROUP = 1016, + BASE_CERTS = 1017, + ACCESS_CREDENTIALS = 1018, + AUTHORIZATIONGROUP = 1019, + ACL_VALIDITY_PERIOD = 1020, + ACL_ENTRY_PROTOTYPE = 1021, + ACL_OWNER_PROTOTYPE = 1022, + ACL_ENTRY_INPUT = 1023, + RESOURCE_CONTROL_CONTEXT = 1024, + ACL_ENTRY_INFO = 1025, + ACL_EDIT = 1026, + FUNC_NAME_ADDR = 1027, + DATE = 1028, + RANGE = 1029, + QUERY_SIZE_DATA = 1030, + KEY_SIZE = 1031, + KEYHEADER = 1032, + KEY = 1033, + DL_DB_HANDLE = 1034, + CONTEXT_ATTRIBUTE = 1035, + CONTEXT = 1036, + PKCS1_OAEP_PARAMS = 1037, + CSP_OPERATIONAL_STATISTICS = 1038, + PKCS5_PBKDF1_PARAMS = 1039, + PKCS5_PBKDF2_PARAMS = 1040, + KEA_DERIVE_PARAMS = 1041, + TP_AUTHORITY_ID = 1042, + FIELD = 1043, + TP_POLICYINFO = 1044, + DL_DB_LIST = 1045, + TP_CALLERAUTH_CONTEXT = 1046, + ENCODED_CRL = 1047, + PARSED_CRL = 1048, + CRL_PAIR = 1049, + CRLGROUP = 1050, + FIELDGROUP = 1051, + EVIDENCE = 1052, + TP_VERIFY_CONTEXT = 1053, + TP_VERIFY_CONTEXT_RESULT = 1054, + TP_REQUEST_SET = 1055, + TP_RESULT_SET = 1056, + TP_CONFIRM_RESPONSE = 1057, + TP_CERTISSUE_INPUT = 1058, + TP_CERTISSUE_OUTPUT = 1059, + TP_CERTCHANGE_INPUT = 1060, + TP_CERTCHANGE_OUTPUT = 1061, + TP_CERTVERIFY_INPUT = 1062, + TP_CERTVERIFY_OUTPUT = 1063, + TP_CERTNOTARIZE_INPUT = 1064, + TP_CERTNOTARIZE_OUTPUT = 1065, + TP_CERTRECLAIM_INPUT = 1066, + TP_CERTRECLAIM_OUTPUT = 1067, + TP_CRLISSUE_INPUT = 1068, + TP_CRLISSUE_OUTPUT = 1069, + CERT_BUNDLE_HEADER = 1070, + CERT_BUNDLE = 1071, + DB_ATTRIBUTE_INFO = 1072, + DB_ATTRIBUTE_DATA = 1073, + DB_RECORD_ATTRIBUTE_INFO = 1074, + DB_RECORD_ATTRIBUTE_DATA = 1075, + DB_PARSING_MODULE_INFO = 1076, + DB_INDEX_INFO = 1077, + DB_UNIQUE_RECORD = 1078, + DB_RECORD_INDEX_INFO = 1079, + DBINFO = 1080, + SELECTION_PREDICATE = 1081, + QUERY_LIMITS = 1082, + QUERY = 1083, + DL_PKCS11_ATTRIBUTE = 1084, // a pointer + NAME_LIST = 1085, + DB_SCHEMA_ATTRIBUTE_INFO = 1086, + DB_SCHEMA_INDEX_INFO = 1087 + }; + static const int sdsFlags = O_RDWR|O_CREAT|O_APPEND; + +public: + SecuritydDataSave(const char *file) : AutoFileDesc(file, sdsFlags, 0644), mFile(file) + { + writePreamble(); + } + SecuritydDataSave(const SecuritydDataSave &sds) : AutoFileDesc(sds.fd()), mFile(sds.file()) { } + + ~SecuritydDataSave() { } + + const char *file() const { return mFile; } + + void writeContext(Security::Context *context, intptr_t attraddr, + mach_msg_type_number_t attrSize); + void writeAclEntryInfo(AclEntryInfo *acls, + mach_msg_type_number_t aclsLength); + void writeAclEntryInput(AclEntryInput *acl, + mach_msg_type_number_t aclLength); + void writeQuery(Security::CssmQuery *query, + mach_msg_type_number_t queryLength) + { + // finish the preamble + uint32_t dtype = QUERY; + writeAll(&dtype, sizeof(dtype)); + + writeDataWithBase(query, queryLength); + } + +private: + // slightly misleading, in that the saved data type is also part of the + // preamble but must be written by the appropriate write...() routine + void writePreamble() + { + uint32_t value = sentry; + writeAll(&value, sizeof(value)); + value = version; + writeAll(&value, sizeof(value)); + } + + // The usual pattern for data structures that include pointers is + // (1) let securityd relocate() the RPC-delivered raw data, thus + // transforming the raw data into walked (flattened) data + // (2) write the size of the data pointer + // (3) write the data pointer (for xdr_test reconstitution) + // (4) write the length (in bytes) of the flattened data, and finally + // (5) write the flattened data + // + // writeDataWithBase() does (2) - (5) + void writeDataWithBase(void *data, mach_msg_type_number_t datalen) + { + uint32_t ptrsize = sizeof(data); + writeAll(&ptrsize, sizeof(ptrsize)); + writeAll(&data, ptrsize); + writeAll(&datalen, sizeof(datalen)); + writeAll(data, datalen); + } + +private: + const char *mFile; +}; + + +#endif /* _SECURITYD_DATA_SAVER_H_ */ diff --git a/SecurityTests/xdr_rpc/xdr_test.cpp b/SecurityTests/xdr_rpc/xdr_test.cpp new file mode 100644 index 00000000..a4c6684a --- /dev/null +++ b/SecurityTests/xdr_rpc/xdr_test.cpp @@ -0,0 +1,2676 @@ +/* + * g++ -F/usr/local/SecurityPieces/Frameworks -g -Wall path/to/xdr_test.cpp + * -framework [securityd_client, security_cdsa_utilities, security_utilities] + * + * -W triggers a lot of warnings in Security code.... + */ +#include +#include /* bool_t */ +#include /* exit(3), malloc(3) */ +#include /* memcmp(3), memset(3), strdup(3) */ +#include /* open(2) */ +#include /* errno */ +#include /* read() */ +#include /* read() */ +#include /* read(), getopt(3) */ +#include +#include +#include +#include +#include +#include "securityd_data_saver.h" + +using Security::DataWalkers::Copier; + +const char *testString = "FOOBAR"; + +/* + * securityd is extremely sloppy about zeroing out data fields it doesn't + * use. It's unlikely that sloppiness will be cleaned up in one fell + * swoop, so we'll never be able to set this to 0; instead, search on the + * symbol name and selectively unbracket code as securityd is fixed. + */ +#define SECURITYD_SENDS_GARBAGE 1 + + +/* + * The securityd RPC protocol can't handle 64-bit quantities until both + * securityd itself and our XDR implementation do. Ergo, don't be tempted + * to make ALIGNMENT depend on __LP64__. + * + * ALIGNMENT and ALIGNUP borrowed from libsecurityd, sec_xdr.c. They + * really should be defined once in a more central location, like + * libsecurity_utilities. + */ +#define LP64_FULLY_SUPPORTED 0 + +#if LP64_FULLY_SUPPORTED +#define ALIGNMENT 8 +#else +#define ALIGNMENT 4 +#endif // LP64_FULLY_SUPPORTED + +#define ALIGNUP(LEN) (((LEN - 1) & ~(ALIGNMENT - 1)) + ALIGNMENT) +#define ALIGNSIZE(TYPE) ALIGNUP(sizeof(TYPE)) + +#define NULLCHECK(a, b, func) \ + if (!(a) && !(b))\ + return OK;\ + else if (!(a) && (b) || (a) && !(b))\ + {\ + fprintf(stderr, "%s (NULL and non-NULL parameter)\n", (func));\ + return MISMATCH;\ + } + +#define N_ITERS 3 /* # of encode/decode cycles */ + +#define OK 0 +#define XDR_ENCODE_ERROR -1 +#define XDR_DECODE_ERROR -2 +#define MISMATCH -3 +#define UNKNOWN_TYPE -4 /* invalid union discriminator */ +#define MEM_ERROR -10 +#define BAD_PARAM -11 +#define BAD_FILE -12 +#define BAD_READ -13 +#define READ_EOF -14 /* not an error per se */ +#define INCOMPATIBLE -98 /* input data format not recognized */ +#define NOT_IMPLEMENTED -99 + +/* This isn't publicly exposed */ +#ifdef __cplusplus +extern "C" { +extern unsigned long xdr_sizeof(xdrproc_t, void *); +} +#endif + +/* + * CSSM data structures of interest. Chosen either for their complexity + * (e.g., CSSM_CONTEXT) or their ubiquity (CSSM_DATA). + * + * CSSM_DATA + * CSSM_GUID + * CSSM_CRYPTO_DATA (possible callback) + * CSSM_LIST_ELEMENT (union) + * CSSM_LIST (pointers) + * CSSM_SAMPLEGROUP (array of CSSM_SAMPLEs) + * CSSM_DATE (fixed-size arrays handled via xdr_vector()) + * CSSM_KEY (heavily used) + * CSSM_DB_RECORD_ATTRIBUTE_DATA (exercises a lot of the above) + * CSSM_CONTEXT (exercises a lot of the above) + * AccessCredentials + * CSSM_AUTHORIZATIONGROUP + * CSSM_ACL_VALIDITY_PERIOD + * CSSM_ACL_ENTRY_PROTOTYPE + * CSSM_ACL_OWNER_PROTOTYPE + * CSSM_ACL_ENTRY_INPUT + * CSSM_ACL_ENTRY_INFO + * CSSM_QUERY + */ + +/* utility routines */ +bool_t xdr_stdio(void *data, xdrproc_t proc, enum xdr_op op); /* XXX/gh needed? */ +bool_t xdr_mem_encode(void *input, void **output, u_int *outlen, + xdrproc_t proc); +bool_t xdr_mem_decode(void *input, void *output, u_int bytesNeeded, + xdrproc_t proc); +void flip(uint8_t *addr, size_t size); +int readPreamble(int fd, uint32_t *doflip, uint32_t *vers, uint32_t *type); +int fill_CSSM_CONTEXT_ATTRIBUTE(CSSM_CONTEXT_ATTRIBUTE *attr, + CSSM_ATTRIBUTE_TYPE type, + uint32_t attrlen, + void *attrval); + +/* byte reordering routines */ +void hostorder_CSSM_DATA(CSSM_DATA *data, off_t offset); +void hostorder_CSSM_GUID(CSSM_GUID *guid); +void hostorder_CSSM_VERSION(CSSM_VERSION *version); +void hostorder_CSSM_SUBSERVICE_UID(CSSM_SUBSERVICE_UID *ssuid); +void hostorder_CSSM_CRYPTO_DATA(CSSM_CRYPTO_DATA *crypto, off_t offset); +void hostorder_CSSM_LIST(CSSM_LIST *list, off_t offset); +void hostorder_CSSM_LIST_ELEMENT(CSSM_LIST_ELEMENT *element, off_t offset); +void hostorder_CSSM_SAMPLE(CSSM_SAMPLE *sample, off_t offset); +void hostorder_CSSM_SAMPLEGROUP(CSSM_SAMPLEGROUP *sgrp, off_t offset); +void hostorder_CSSM_ENCODED_CERT(CSSM_ENCODED_CERT *cert, off_t offset); +void hostorder_CSSM_CERTGROUP(CSSM_CERTGROUP *grp, off_t offset); +void hostorder_CSSM_BASE_CERTS(CSSM_BASE_CERTS *certs, off_t offset); +void hostorder_CSSM_ACCESS_CREDENTIALS(CSSM_ACCESS_CREDENTIALS *creds, + off_t offset); +void hostorder_CSSM_AUTHORIZATIONGROUP(CSSM_AUTHORIZATIONGROUP *grp, + off_t offset); +void hostorder_CSSM_ACL_VALIDITY_PERIOD(CSSM_ACL_VALIDITY_PERIOD *period, + off_t offset); +void hostorder_CSSM_ACL_ENTRY_PROTOTYPE(CSSM_ACL_ENTRY_PROTOTYPE *proto, + off_t offset); +void hostorder_CSSM_ACL_OWNER_PROTOTYPE(CSSM_ACL_OWNER_PROTOTYPE *proto, + off_t offset); +void hostorder_CSSM_ACL_ENTRY_INPUT(CSSM_ACL_ENTRY_INPUT *input, off_t offset); +void hostorder_CSSM_ACL_ENTRY_INFO(CSSM_ACL_ENTRY_INFO *info, off_t offset); +void hostorder_CSSM_KEYHEADER(CSSM_KEYHEADER *key); +void hostorder_CSSM_KEY(CSSM_KEY *key, off_t offset); +void hostorder_CSSM_DL_DB_HANDLE(CSSM_DL_DB_HANDLE *handle); +void hostorder_CSSM_RANGE(CSSM_RANGE *range); +void hostorder_CSSM_CONTEXT_ATTRIBUTE(CSSM_CONTEXT_ATTRIBUTE *attr, + off_t offset); +void hostorder_CSSM_CONTEXT(CSSM_CONTEXT *ctx, CSSM_CONTEXT_ATTRIBUTE *attrs); +void hostorder_CSSM_OID(CSSM_OID *oid, off_t offset); +void hostorder_CSSM_DB_ATTRIBUTE_INFO(CSSM_DB_ATTRIBUTE_INFO *attrinfo, + off_t offset); +void hostorder_CSSM_DB_ATTRIBUTE_DATA(CSSM_DB_ATTRIBUTE_DATA *attrdata, + off_t offset); +void hostorder_CSSM_SELECTION_PREDICATE(CSSM_SELECTION_PREDICATE *pred, + off_t offset); +void hostorder_CSSM_QUERY_LIMITS(CSSM_QUERY_LIMITS *limits); +void hostorder_CSSM_QUERY(CSSM_QUERY *range, off_t offset); + +/* comparators */ +int compare_CSSM_DATA(CSSM_DATA *data1, CSSM_DATA *data2); +int compare_CSSM_SUBSERVICE_UID(const CSSM_SUBSERVICE_UID *ssuid1, + const CSSM_SUBSERVICE_UID *ssuid2); +int compare_CSSM_CRYPTO_DATA(CSSM_CRYPTO_DATA *data1, CSSM_CRYPTO_DATA *data2); +int compare_CSSM_LIST(const CSSM_LIST *list1, const CSSM_LIST *list2); +int compare_CSSM_SAMPLE(const CSSM_SAMPLE *sample1, const CSSM_SAMPLE *sample2); +int compare_CSSM_SAMPLEGROUP(CSSM_SAMPLEGROUP *sgrp1, CSSM_SAMPLEGROUP *sgrp2); +int compare_CSSM_ENCODED_CERT(CSSM_ENCODED_CERT *cert1, + CSSM_ENCODED_CERT *cert2); +int compare_CSSM_CERTGROUP(CSSM_CERTGROUP *grp1, CSSM_CERTGROUP *grp2); +int compare_CSSM_BASE_CERTS(CSSM_BASE_CERTS *bases1, CSSM_BASE_CERTS *bases2); +int compare_CSSM_ACCESS_CREDENTIALS(CSSM_ACCESS_CREDENTIALS *creds1, + CSSM_ACCESS_CREDENTIALS *creds2); +int compare_CSSM_AUTHORIZATIONGROUP(CSSM_AUTHORIZATIONGROUP *grp1, + CSSM_AUTHORIZATIONGROUP *grp2); +int compare_CSSM_ACL_VALIDITY_PERIOD(CSSM_ACL_VALIDITY_PERIOD *period1, + CSSM_ACL_VALIDITY_PERIOD *period2); +int compare_CSSM_ACL_ENTRY_PROTOTYPE(CSSM_ACL_ENTRY_PROTOTYPE *proto1, + CSSM_ACL_ENTRY_PROTOTYPE *proto2, + int skipGarbage); +int compare_CSSM_ACL_OWNER_PROTOTYPE(CSSM_ACL_OWNER_PROTOTYPE *proto1, + CSSM_ACL_OWNER_PROTOTYPE *proto2); +int compare_CSSM_ACL_ENTRY_INPUT(CSSM_ACL_ENTRY_INPUT *input1, + CSSM_ACL_ENTRY_INPUT *input2); +int compare_CSSM_ACL_ENTRY_INFO(CSSM_ACL_ENTRY_INFO *info1, + CSSM_ACL_ENTRY_INFO *info2); +int compare_CSSM_DATE(CSSM_DATE *date1, CSSM_DATE *date2); +int compare_CSSM_KEYHEADER(CSSM_KEYHEADER *hdr1, CSSM_KEYHEADER *hdr2); +int compare_CSSM_KEY(CSSM_KEY *key1, CSSM_KEY *key2); +int compare_CSSM_RANGE(CSSM_RANGE *range1, CSSM_RANGE *range2); +int compare_CSSM_CONTEXT_ATTRIBUTE(CSSM_CONTEXT_ATTRIBUTE *attr1, + CSSM_CONTEXT_ATTRIBUTE *attr2); +int compare_CSSM_OID(CSSM_OID *oid1, CSSM_OID *oid2); +int compare_CSSM_CONTEXT(CSSM_CONTEXT *ctx1, CSSM_CONTEXT *ctx2); +int compare_CSSM_DB_ATTRIBUTE_INFO(CSSM_DB_ATTRIBUTE_INFO *attrinfo1, + CSSM_DB_ATTRIBUTE_INFO *attrinfo2); +int compare_CSSM_DB_ATTRIBUTE_DATA(CSSM_DB_ATTRIBUTE_DATA *attrdata1, + CSSM_DB_ATTRIBUTE_DATA *attrdata2); +int compare_CSSM_SELECTION_PREDICATE(CSSM_SELECTION_PREDICATE *pred1, + CSSM_SELECTION_PREDICATE *pred2); +int compare_CSSM_QUERY_LIMITS(CSSM_QUERY_LIMITS *limits1, + CSSM_QUERY_LIMITS *limits2); +int compare_CSSM_QUERY(CSSM_QUERY *query1, CSSM_QUERY *query2); + +CSSM_RETURN dummyCSSMCallback(CSSM_DATA *data, void *context); +CSSM_RETURN dummyACLSubjectCallback(const CSSM_LIST *subjectRequest, + void *callerContext, + const CSSM_MEMORY_FUNCS *MemFuncs); + +/* the actual test functions */ +int test_CSSM_DB_RECORD_ATTRIBUTE_DATA(const char *srcfile); /* TODO/gh */ +int test_xdrwalk_CSSM_CONTEXT(CSSM_CONTEXT *ctx, int dbglvl); +int test_CSSM_CONTEXT(int fd, int doflip, int dbglvl); +int test_xdrwalk_CSSM_ACL_OWNER_PROTOTYPE(CSSM_ACL_OWNER_PROTOTYPE *aclOwnerPrototype, int dbglvl); +int test_CSSM_ACL_OWNER_PROTOTYPE(int fd, int doflip, int dbglvl); +int test_xdrwalk_CSSM_ACL_ENTRY_INPUT(CSSM_ACL_ENTRY_INPUT *aclEntryInput, + int dbglvl); +int test_CSSM_ACL_ENTRY_INPUT(int fd, int doflip, int dbglvl); +int test_xdrwalk_CSSM_ACL_ENTRY_INFO(CSSM_ACL_ENTRY_INFO *aclEntryInfo, + int dbglvl); +int test_CSSM_ACL_ENTRY_INFO(int fd, int doflip, int dbglvl); +int test_xdrwalk_CSSM_QUERY(CSSM_QUERY *query, int dbglvl); +int test_CSSM_QUERY(int fd, int doflip, int dbglvl); + + +/************************************************************************** + * misc utility functions + **************************************************************************/ + +/* XXX/gh needed? */ +/* XXX/gh should "data" be a uint8_t *? */ +bool_t xdr_stdio(void *data, xdrproc_t proc, enum xdr_op op) +{ + XDR xdr; + /* should we call xdrstdio_create(...,..., XDR_FREE) when done? */ + xdrstdio_create(&xdr, stdout, op); + if (proc(&xdr, data)) + return (FALSE); + return (TRUE); +} + +/* note no error-checking of parameters */ +bool_t xdr_mem_encode(void *input, void **output, u_int *outlen, + xdrproc_t proc) +{ + XDR xdr; + char *data; + u_int length; + + length = xdr_sizeof(proc, input); + if ((data = (char *)malloc(length)) == NULL) + { + fprintf(stderr, "xdr_mem_encode(): malloc() error\n"); + return (FALSE); + } + xdrmem_create(&xdr, data, length, XDR_ENCODE); + if (!proc(&xdr, input)) + { + fprintf(stderr, "xdr_mem_encode(): XDR error\n"); + free(data); + return (FALSE); + } + *output = data; + if (outlen) + *outlen = length; + return (TRUE); +} + +/* note no error-checking of parameters */ +bool_t xdr_mem_decode(void *input, void *output, u_int bytesNeeded, + xdrproc_t proc) +{ + XDR xdr; + + xdrmem_create(&xdr, (char *)input, bytesNeeded, XDR_DECODE); + if (!proc(&xdr, output)) + return (FALSE); + return (TRUE); +} + +/* + * Because sometimes ntoh*() isn't enough. Stolen from securityd and + * slightly modified to avoid type dependencies. + */ +void flip(void *inaddr, size_t size) +{ + uint8 *addr = reinterpret_cast(inaddr); + size_t n; + + assert(size > 1 && (size % 2 == 0)); + uint8_t *word = addr; + for (n = 0; n < size/2; n++) + { + uint8_t b = word[n]; + word[n] = word[size-1-n]; + word[size-1-n] = b; + } +} + +/* + * note that if this returns prematurely, you can make no assumption about + * the value of "doflip," "vers," or "type" + */ +int readPreamble(int fd, uint32_t *doflip, uint32_t *vers, uint32_t *type) +{ + const char *func = "readPreamble()"; + uint32_t value; + ssize_t bytesRead; + + /* byte order sentry value */ + if ((bytesRead = read(fd, &value, sizeof(value))) != sizeof(value)) + { + if (bytesRead == 0) + return READ_EOF; + fprintf(stderr, "%s: error reading byte order sentry\n", func); + return BAD_READ; + } + if (value == SecuritydDataSave::sentry) + *doflip = 0; + else if (value == 0x34120000) + *doflip = 1; + else + { + fprintf(stderr, "%s: unrecognized sentry value %d\n", func, value); + return INCOMPATIBLE; + } + + /* version info (for this disk-saving protocol) */ + if (read(fd, &value, sizeof(value)) != sizeof(value)) + { + fprintf(stderr, "%s: error reading data format version\n", func); + return BAD_READ; + } + if (*doflip) + flip(&value, sizeof(value)); + *vers = value; + + switch(*vers) + { + case 1: + /* type of record */ + if (read(fd, &value, sizeof(value)) != sizeof(value)) + { + fprintf(stderr, "%s: error reading data type\n", func); + return BAD_READ; + } + if (*doflip) + flip(&value, sizeof(value)); + *type = value; + break; + default: + fprintf(stderr, "%s: incompatible version (expected <= %d, got %d)\n", + func, SecuritydDataSave::version, *vers); + return INCOMPATIBLE; + break; + } + return OK; +} + +int fill_CSSM_CONTEXT_ATTRIBUTE(CSSM_CONTEXT_ATTRIBUTE *attr, + CSSM_ATTRIBUTE_TYPE type, + uint32_t attrlen, + void *attrval) +{ + if (!attr || !attrval) + return BAD_PARAM; + attr->AttributeType = type; + attr->AttributeLength = attrlen; + /* XXX copy instead of assigning */ + switch (type & CSSM_ATTRIBUTE_TYPE_MASK) + { + case CSSM_ATTRIBUTE_DATA_UINT32: + attr->Attribute.Uint32 = *(reinterpret_cast(attrval)); + break; + case CSSM_ATTRIBUTE_DATA_CSSM_DATA: + attr->Attribute.Data = (CSSM_DATA_PTR)attrval; + break; + case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA: + attr->Attribute.CryptoData = (CSSM_CRYPTO_DATA_PTR)attrval; + break; + case CSSM_ATTRIBUTE_DATA_KEY: + attr->Attribute.Key = (CSSM_KEY_PTR)attrval; + break; + case CSSM_ATTRIBUTE_DATA_STRING: + attr->Attribute.String = (char *)attrval; + break; + case CSSM_ATTRIBUTE_DATA_DATE: + attr->Attribute.Date = (CSSM_DATE_PTR)attrval; + break; + case CSSM_ATTRIBUTE_DATA_RANGE: + attr->Attribute.Range = (CSSM_RANGE_PTR)attrval; + break; + case CSSM_ATTRIBUTE_DATA_ACCESS_CREDENTIALS: + attr->Attribute.AccessCredentials = (CSSM_ACCESS_CREDENTIALS_PTR)attrval; + break; + case CSSM_ATTRIBUTE_DATA_VERSION: + attr->Attribute.Version = (CSSM_VERSION_PTR)attrval; + break; + case CSSM_ATTRIBUTE_DATA_DL_DB_HANDLE: + attr->Attribute.DLDBHandle = (CSSM_DL_DB_HANDLE_PTR)attrval; + break; + /* _KR_PROFILE not supported? */ + default: + return BAD_PARAM; + } + return OK; +} + + +/************************************************************************** + * These do their best to handle byte-ordering issues. + * + * Note that pointers are generally (maybe always) byte-order swapped in + * these routines, since you generally need to do some kind of arithmetic + * with them (relocation). + **************************************************************************/ + +void hostorder_CSSM_DATA(CSSM_DATA *data, off_t offset) +{ + intptr_t newaddr; /* for readability */ + + if (!data) return; + flip(&data->Length, sizeof(data->Length)); + if (data->Data) + { + flip(&data->Data, sizeof(data->Data)); + newaddr = reinterpret_cast(data->Data) + offset; + data->Data = reinterpret_cast(newaddr); + } +} + +void hostorder_CSSM_GUID(CSSM_GUID *guid) +{ + if (!guid) return; + flip(&guid->Data1, sizeof(guid->Data1)); + flip(&guid->Data2, sizeof(guid->Data2)); + flip(&guid->Data3, sizeof(guid->Data3)); +} + +void hostorder_CSSM_VERSION(CSSM_VERSION *version) +{ + if (!version) return; + flip(&version->Major, sizeof(version->Major)); + flip(&version->Minor, sizeof(version->Minor)); +} + +void hostorder_CSSM_SUBSERVICE_UID(CSSM_SUBSERVICE_UID *ssuid) +{ + if (!ssuid) return; + hostorder_CSSM_GUID(&ssuid->Guid); + hostorder_CSSM_VERSION(&ssuid->Version); + flip(&ssuid->SubserviceId, sizeof(ssuid->SubserviceId)); + flip(&ssuid->SubserviceType, sizeof(ssuid->SubserviceType)); +} + +void hostorder_CSSM_CRYPTO_DATA(CSSM_CRYPTO_DATA *crypto, off_t offset) +{ + if (!crypto) return; + hostorder_CSSM_DATA(&crypto->Param, offset); + flip(&crypto->Callback, sizeof(crypto->Callback)); + flip(&crypto->CallerCtx, sizeof(crypto->CallerCtx)); +} + +void hostorder_CSSM_LIST(CSSM_LIST *list, off_t offset) +{ + CSSM_LIST_ELEMENT_PTR ptr; + intptr_t newaddr; /* for readability */ + + if (!list) return; + + flip(&list->ListType, sizeof(list->ListType)); + + if (list->Head) + { + flip(&list->Head, sizeof(list->Head)); + newaddr = reinterpret_cast(list->Head) + offset; + list->Head = reinterpret_cast(newaddr); + } + + if (list->Tail) + { + flip(&list->Tail, sizeof(list->Tail)); + newaddr = reinterpret_cast(list->Tail) + offset; + list->Tail = reinterpret_cast(newaddr); + } + + for (ptr = list->Head; ptr != NULL; ptr = ptr->NextElement) + { + hostorder_CSSM_LIST_ELEMENT(ptr, offset); + } +} + +void hostorder_CSSM_LIST_ELEMENT(CSSM_LIST_ELEMENT *element, off_t offset) +{ + intptr_t newaddr; /* for readability */ + + if (!element) return; + + if (element->NextElement) + { + flip(&element->NextElement, sizeof(element->NextElement)); + newaddr = reinterpret_cast(element->NextElement) + offset; + element->NextElement = reinterpret_cast(newaddr); + } + + flip(&element->WordID, sizeof(element->WordID)); + flip(&element->ElementType, sizeof(element->ElementType)); + switch (element->ElementType) + { + case CSSM_LIST_ELEMENT_DATUM: + hostorder_CSSM_DATA(&element->Element.Word, offset); + break; + case CSSM_LIST_ELEMENT_SUBLIST: + hostorder_CSSM_LIST(&element->Element.Sublist, offset); + break; + case CSSM_LIST_ELEMENT_WORDID: + break; + default: + fprintf(stderr, "hostorder_CSSM_LIST_ELEMENT() (unknown ListElement type)\n"); + } +} + +void hostorder_CSSM_SAMPLE(CSSM_SAMPLE *sample, off_t offset) +{ + CSSM_SUBSERVICE_UID *ptr; + + if (!sample) return; + hostorder_CSSM_LIST(&sample->TypedSample, offset); + if (sample->Verifier) + { + ptr = const_cast(sample->Verifier); + flip(&ptr, sizeof(CSSM_SUBSERVICE_UID *)); + sample->Verifier = reinterpret_cast(reinterpret_cast(ptr) + offset); + /* Verifier had better not be really and truly immutable... */ + hostorder_CSSM_SUBSERVICE_UID(const_cast(sample->Verifier)); + } +} + +void hostorder_CSSM_SAMPLEGROUP(CSSM_SAMPLEGROUP *sgrp, off_t offset) +{ + u_int i; + CSSM_SAMPLE *ptr; + + if (!sgrp) return; + flip(&sgrp->NumberOfSamples, sizeof(sgrp->NumberOfSamples)); + if (sgrp->Samples) + { + ptr = const_cast(sgrp->Samples); + flip(&ptr, sizeof(ptr)); + sgrp->Samples = reinterpret_cast(reinterpret_cast(ptr) + offset); + for (i = 0; i < sgrp->NumberOfSamples; ++i) + { + hostorder_CSSM_SAMPLE(const_cast(&sgrp->Samples[i]), offset); + } + } +} + +void hostorder_CSSM_ENCODED_CERT(CSSM_ENCODED_CERT *cert, off_t offset) +{ + if (!cert) return; + flip(&cert->CertType, sizeof(cert->CertType)); + flip(&cert->CertEncoding, sizeof(cert->CertEncoding)); + hostorder_CSSM_DATA(&cert->CertBlob, offset); +} + +void hostorder_CSSM_CERTGROUP(CSSM_CERTGROUP *grp, off_t offset) +{ + const char *func = "hostorder_CSSM_CERTGROUP()"; + intptr_t newaddr; /* for readability */ + u_int i; + + if (!grp) return; + flip(&grp->CertType, sizeof(grp->CertType)); + flip(&grp->CertEncoding, sizeof(grp->CertEncoding)); + flip(&grp->NumCerts, sizeof(grp->NumCerts)); + /* Any field in the union will do; CertList is the shortest to type */ + if (grp->GroupList.CertList) + { + flip(&grp->GroupList.CertList, sizeof(CSSM_DATA *)); + newaddr = reinterpret_cast(grp->GroupList.CertList) + offset; + grp->GroupList.CertList = reinterpret_cast(newaddr); + } + /* handled out of order of definition since for() loop depends on it */ + flip(&grp->CertGroupType, sizeof(grp->CertGroupType)); + + /* Note: we will crash if GroupList contains NULL and NumCerts > 0 */ + for (i = 0; i < grp->NumCerts; ++i) + { + char *err = NULL; + + switch (grp->CertGroupType) + { + case CSSM_CERTGROUP_DATA: + hostorder_CSSM_DATA(&grp->GroupList.CertList[i], offset); + break; + /* damned if I can find an example of the others */ + case CSSM_CERTGROUP_ENCODED_CERT: + /* See the cautionary note in compare_CSSM_CERTGROUP() */ + hostorder_CSSM_ENCODED_CERT(&grp->GroupList.EncodedCertList[i], + offset); + break; + case CSSM_CERTGROUP_PARSED_CERT: + err = "CSSM_CERTGROUP_PARSED_CERT unimplemented"; + break; + case CSSM_CERTGROUP_CERT_PAIR: + err = "CSSM_CERTGROUP_CERT_PAIR unimplemented"; + break; + default: + err = "unknown type"; + break; + } + if (err) + { + fprintf(stderr, "%s (%s)\n", func, err); + return; + } + } + flip(&grp->Reserved, sizeof(grp->Reserved)); + /* Depending on how Reserved is used, this code might be required + newaddr = reinterpret_cast(grp->Reserved) + offset; + grp->Reserved = reinterpret_cast(newaddr); + */ +} + +void hostorder_CSSM_BASE_CERTS(CSSM_BASE_CERTS *certs, off_t offset) +{ + if (!certs) return; + flip(&certs->TPHandle, sizeof(certs->TPHandle)); + flip(&certs->CLHandle, sizeof(certs->CLHandle)); + hostorder_CSSM_CERTGROUP(&certs->Certs, offset); +} + +void hostorder_CSSM_AUTHORIZATIONGROUP(CSSM_AUTHORIZATIONGROUP *grp, + off_t offset) +{ + intptr_t newaddr; /* for readability */ + uint32_t i; + + flip(&grp->NumberOfAuthTags, sizeof(grp->NumberOfAuthTags)); + if (grp->AuthTags) + { + flip(&grp->AuthTags, sizeof(grp->AuthTags)); + newaddr = reinterpret_cast(grp->AuthTags) + offset; + grp->AuthTags = reinterpret_cast(newaddr); + } + for (i = 0; i < grp->NumberOfAuthTags; ++i) + { + flip(&grp->AuthTags[i], sizeof(CSSM_ACL_AUTHORIZATION_TAG)); + } +} + +void hostorder_CSSM_ACL_VALIDITY_PERIOD(CSSM_ACL_VALIDITY_PERIOD *period, + off_t offset) +{ + hostorder_CSSM_DATA(&period->StartDate, offset); + hostorder_CSSM_DATA(&period->EndDate, offset); +} + +void hostorder_CSSM_ACL_OWNER_PROTOTYPE(CSSM_ACL_OWNER_PROTOTYPE *proto, + off_t offset) +{ + hostorder_CSSM_LIST(&proto->TypedSubject, offset); + flip(&proto->Delegate, sizeof(proto->Delegate)); +} + +void hostorder_CSSM_ACL_ENTRY_PROTOTYPE(CSSM_ACL_ENTRY_PROTOTYPE *proto, + off_t offset) +{ + hostorder_CSSM_LIST(&proto->TypedSubject, offset); + flip(&proto->Delegate, sizeof(proto->Delegate)); + hostorder_CSSM_AUTHORIZATIONGROUP(&proto->Authorization, offset); + hostorder_CSSM_ACL_VALIDITY_PERIOD(&proto->TimeRange, offset); +} + +void hostorder_CSSM_ACL_ENTRY_INPUT(CSSM_ACL_ENTRY_INPUT *input, off_t offset) +{ + hostorder_CSSM_ACL_ENTRY_PROTOTYPE(&input->Prototype, offset); + flip(&input->Callback, sizeof(input->Callback)); + flip(&input->CallerContext, sizeof(input->CallerContext)); +} + +void hostorder_CSSM_ACL_ENTRY_INFO(CSSM_ACL_ENTRY_INFO *info, off_t offset) +{ + hostorder_CSSM_ACL_ENTRY_PROTOTYPE(&info->EntryPublicInfo, offset); + flip(&info->EntryHandle, sizeof(info->EntryHandle)); +} + +void hostorder_CSSM_ACCESS_CREDENTIALS(CSSM_ACCESS_CREDENTIALS *creds, + off_t offset) +{ + if (!creds) return; + hostorder_CSSM_BASE_CERTS(&creds->BaseCerts, offset); + hostorder_CSSM_SAMPLEGROUP(&creds->Samples, offset); + flip(&creds->Callback, sizeof(creds->Callback)); + flip(&creds->CallerCtx, sizeof(creds->CallerCtx)); +} + +void hostorder_CSSM_KEYHEADER(CSSM_KEYHEADER *hdr) +{ + if (!hdr) return; + flip(&hdr->HeaderVersion, sizeof(hdr->HeaderVersion)); + flip(&hdr->BlobType, sizeof(hdr->BlobType)); + flip(&hdr->Format, sizeof(hdr->Format)); + flip(&hdr->AlgorithmId, sizeof(hdr->AlgorithmId)); + flip(&hdr->KeyClass, sizeof(hdr->KeyClass)); + flip(&hdr->LogicalKeySizeInBits, sizeof(hdr->LogicalKeySizeInBits)); + flip(&hdr->KeyAttr, sizeof(hdr->KeyAttr)); + flip(&hdr->KeyUsage, sizeof(hdr->KeyUsage)); + flip(&hdr->WrapAlgorithmId, sizeof(hdr->WrapAlgorithmId)); + flip(&hdr->WrapMode, sizeof(hdr->WrapMode)); + flip(&hdr->Reserved, sizeof(hdr->Reserved)); +} + +void hostorder_CSSM_KEY(CSSM_KEY *key, off_t offset) +{ + if (!key) return; + hostorder_CSSM_KEYHEADER(&key->KeyHeader); + hostorder_CSSM_DATA(&key->KeyData, offset); +} + +void hostorder_CSSM_DL_DB_HANDLE(CSSM_DL_DB_HANDLE *handle) +{ + if (!handle) return; + /* + * XXX/gh offset is needed if these values are being treated as + * as pointers! + */ + flip(&handle->DLHandle, sizeof(handle->DLHandle)); + flip(&handle->DBHandle, sizeof(handle->DBHandle)); +} + +void hostorder_CSSM_RANGE(CSSM_RANGE *range) +{ + if (!range) return; + flip(&range->Min, sizeof(range->Min)); + flip(&range->Max, sizeof(range->Max)); +} + +void hostorder_CSSM_CONTEXT_ATTRIBUTE(CSSM_CONTEXT_ATTRIBUTE *attr, + off_t offset) +{ + if (!attr) return; + flip(&attr->AttributeType, sizeof(attr->AttributeType)); + flip(&attr->AttributeLength, sizeof(attr->AttributeLength)); + if ((attr->AttributeType & CSSM_ATTRIBUTE_TYPE_MASK) == CSSM_ATTRIBUTE_DATA_UINT32) + { + flip(&attr->Attribute.Uint32, sizeof(attr->Attribute.Uint32)); + } + else + { + intptr_t newaddr; /* for readability */ + + /* any pointer accessor of the union will do */ + if (attr->Attribute.String) + { + flip(&attr->Attribute.String, sizeof(attr->Attribute.String)); + newaddr = reinterpret_cast(attr->Attribute.String) + offset; + attr->Attribute.String = reinterpret_cast(newaddr); + } + switch (attr->AttributeType & CSSM_ATTRIBUTE_TYPE_MASK) + { + case CSSM_ATTRIBUTE_DATA_CSSM_DATA: + hostorder_CSSM_DATA(attr->Attribute.Data, offset); + break; + case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA: + hostorder_CSSM_CRYPTO_DATA(attr->Attribute.CryptoData, offset); + break; + case CSSM_ATTRIBUTE_DATA_KEY: + hostorder_CSSM_KEY(attr->Attribute.Key, offset); + break; + case CSSM_ATTRIBUTE_DATA_STRING: + case CSSM_ATTRIBUTE_DATA_DATE: + break; + case CSSM_ATTRIBUTE_DATA_RANGE: + hostorder_CSSM_RANGE(attr->Attribute.Range); + break; + case CSSM_ATTRIBUTE_DATA_ACCESS_CREDENTIALS: + hostorder_CSSM_ACCESS_CREDENTIALS(attr->Attribute.AccessCredentials, offset); + break; + case CSSM_ATTRIBUTE_DATA_VERSION: + hostorder_CSSM_VERSION(attr->Attribute.Version); + break; + case CSSM_ATTRIBUTE_DATA_DL_DB_HANDLE: + hostorder_CSSM_DL_DB_HANDLE(attr->Attribute.DLDBHandle); + break; + /* _KR_PROFILE not supported? */ + default: + fprintf(stderr, "hostorder_CSSM_CONTEXT_ATTRIBUTE(): unrecognized attribute type\n"); + } + } /* end if (CSSM_ATTRIBUTE_DATA_UINT32 */ +} + +void hostorder_CSSM_CONTEXT(CSSM_CONTEXT *ctx, CSSM_CONTEXT_ATTRIBUTE *attrs) +{ + off_t offset; + uint32_t i; + + if (!ctx) return; + flip(&ctx->ContextType, sizeof(ctx->ContextType)); + flip(&ctx->AlgorithmType, sizeof(ctx->AlgorithmType)); + flip(&ctx->NumberOfAttributes, sizeof(ctx->NumberOfAttributes)); + if (ctx->ContextAttributes) + { + flip(&ctx->ContextAttributes, sizeof(ctx->ContextAttributes)); + offset = reinterpret_cast(attrs) - reinterpret_cast(ctx->ContextAttributes); + ctx->ContextAttributes = reinterpret_cast(attrs); + } + for (i = 0; i < ctx->NumberOfAttributes; ++i) + { + hostorder_CSSM_CONTEXT_ATTRIBUTE(&ctx->ContextAttributes[i], offset); + } + flip(&ctx->CSPHandle, sizeof(ctx->CSPHandle)); + flip(&ctx->Privileged, sizeof(ctx->Privileged)); + flip(&ctx->EncryptionProhibited, sizeof(ctx->EncryptionProhibited)); + flip(&ctx->WorkFactor, sizeof(ctx->WorkFactor)); + flip(&ctx->Reserved, sizeof(ctx->Reserved)); +} + +void hostorder_CSSM_OID(CSSM_OID *oid, off_t offset) +{ + hostorder_CSSM_DATA(reinterpret_cast(oid), offset); +} + +void hostorder_CSSM_DB_ATTRIBUTE_INFO(CSSM_DB_ATTRIBUTE_INFO *attrinfo, + off_t offset) +{ + if (!attrinfo) return; + flip(&attrinfo->AttributeNameFormat, sizeof(attrinfo->AttributeNameFormat)); + switch(attrinfo->AttributeNameFormat) + { + case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: + { + intptr_t newaddr; /* for readability */ + flip(&attrinfo->Label.AttributeName, sizeof(attrinfo->Label.AttributeName)); + newaddr = reinterpret_cast(attrinfo->Label.AttributeName) + offset; + attrinfo->Label.AttributeName = reinterpret_cast(newaddr); + break; + } + case CSSM_DB_ATTRIBUTE_NAME_AS_OID: + hostorder_CSSM_OID(&attrinfo->Label.AttributeOID, offset); + break; + case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: + flip(&attrinfo->Label.AttributeID, sizeof(attrinfo->Label.AttributeID)); + break; + default: + break; /* error, but no way to tell caller */ + } + flip(&attrinfo->AttributeFormat, sizeof(attrinfo->AttributeFormat)); +} + +void hostorder_CSSM_DB_ATTRIBUTE_DATA(CSSM_DB_ATTRIBUTE_DATA *attrdata, + off_t offset) +{ + uint32_t i; + + if (!attrdata) return; + hostorder_CSSM_DB_ATTRIBUTE_INFO(&attrdata->Info, offset); + flip(&attrdata->NumberOfValues, sizeof(attrdata->NumberOfValues)); + for (i = 0; i < attrdata->NumberOfValues; ++i) + { + hostorder_CSSM_DATA(&attrdata->Value[i], offset); + } +} + +void hostorder_CSSM_SELECTION_PREDICATE(CSSM_SELECTION_PREDICATE *pred, + off_t offset) +{ + if (!pred) return; + flip(&pred->DbOperator, sizeof(pred->DbOperator)); + hostorder_CSSM_DB_ATTRIBUTE_DATA(&pred->Attribute, offset); +} + +void hostorder_CSSM_QUERY_LIMITS(CSSM_QUERY_LIMITS *limits) +{ + if (!limits) return; + flip(&limits->TimeLimit, sizeof(limits->TimeLimit)); + flip(&limits->SizeLimit, sizeof(limits->SizeLimit)); +} + +void hostorder_CSSM_QUERY(CSSM_QUERY *query, off_t offset) +{ + uint32_t i; + + if (!query) return; + flip(&query->RecordType, sizeof(query->RecordType)); + flip(&query->Conjunctive, sizeof(query->Conjunctive)); + flip(&query->NumSelectionPredicates, sizeof(query->NumSelectionPredicates)); + if (query->SelectionPredicate) + { + intptr_t newaddr; /* for readability */ + + flip(&query->SelectionPredicate, sizeof(query->SelectionPredicate)); + newaddr = reinterpret_cast(query->SelectionPredicate) + offset; + query->SelectionPredicate = reinterpret_cast(newaddr); + } + for (i = 0; i < query->NumSelectionPredicates; ++i) + { + hostorder_CSSM_SELECTION_PREDICATE(&query->SelectionPredicate[i], offset); + } + hostorder_CSSM_QUERY_LIMITS(&query->QueryLimits); + flip(&query->QueryFlags, sizeof(query->QueryFlags)); +} + + +/************************************************************************** + * Comparators--data integrity checking routines. + * + * Each comparator compares two of the same high-level data structure, one + * of which is presumed to have been through at least one + * encoding/decoding cycle; these comparators check for errors introduced + * during that cycle. + * + * TODO/gh A hand-crafted function per type seems sloppy, not well thought + * out. I bet I could leverage part of the walker machinery to create a + * more elegant solution (a "comparison walker," anyone?). Whether the + * result would be maintainable is, of course, a different question.... + **************************************************************************/ + +int compare_CSSM_DATA(CSSM_DATA *data1, CSSM_DATA *data2) +{ + const char *func = "compare_CSSM_DATA()"; + + NULLCHECK(data1, data2, func); + if (data1->Length != data2->Length || + memcmp(data1->Data, data2->Data, data1->Length)) + { + fprintf(stderr, "%s (mismatch)\n", func); + return MISMATCH; + } + return OK; +} + +int compare_CSSM_SUBSERVICE_UID(const CSSM_SUBSERVICE_UID *ssuid1, + const CSSM_SUBSERVICE_UID *ssuid2) +{ + const char *func = "compare_CSSM_SUBSERVICE_UID()"; + + NULLCHECK(ssuid1, ssuid2, func); + if (memcmp(&ssuid1->Guid, &ssuid2->Guid, sizeof(CSSM_GUID)) || + memcmp(&ssuid1->Version, &ssuid2->Version, sizeof(CSSM_VERSION)) || + ssuid1->SubserviceId != ssuid2->SubserviceId || + ssuid1->SubserviceType != ssuid2->SubserviceType) + { + fprintf(stderr, "%s (mismatch)\n", func); + return MISMATCH; + } + return OK; +} + +int compare_CSSM_CRYPTO_DATA(CSSM_CRYPTO_DATA *data1, CSSM_CRYPTO_DATA *data2) +{ + const char *func = "compare_CSSM_CRYPTO_DATA()"; + int ret; + + NULLCHECK(data1, data2, func); + if ((ret = compare_CSSM_DATA(&data1->Param, &data2->Param)) != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + if (data1->Callback != data2->Callback || + data1->CallerCtx != data2->CallerCtx) + { + fprintf(stderr, "%s (mismatch)\n", func); + return MISMATCH; + } + return OK; +} + +int compare_CSSM_LIST(const CSSM_LIST *list1, const CSSM_LIST *list2) +{ + const char *func = "compare_CSSM_LIST()"; + CSSM_LIST_ELEMENT_PTR p1, p2; + int ret; + + NULLCHECK(list1, list2, func); + if (list1->ListType != list2->ListType) + { + fprintf(stderr, "%s (ListType)\n", func); + return MISMATCH; + } + for (p1 = list1->Head, p2 = list2->Head; + p1 != NULL && p2 != NULL; + p1 = p1->NextElement, p2 = p2->NextElement) + { + if (p1->ElementType != p2->ElementType) + { + fprintf(stderr, "%s (ListElements' ElementType)\n", func); + return MISMATCH; + } + switch (p1->ElementType) + { + case CSSM_LIST_ELEMENT_DATUM: + ret = compare_CSSM_DATA(&p1->Element.Word, &p2->Element.Word); + if (ret != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + break; + case CSSM_LIST_ELEMENT_SUBLIST: + ret = compare_CSSM_LIST(&p1->Element.Sublist, &p2->Element.Sublist); + if (ret != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + break; + case CSSM_LIST_ELEMENT_WORDID: + if (p1->WordID != p2->WordID) + { + fprintf(stderr, "%s (ListElements' WordID)\n", func); + return MISMATCH; + } + break; + default: + fprintf(stderr, "%s (unknown ListElement type)\n", func); + return UNKNOWN_TYPE; + } + if ((p1->NextElement == NULL && p1 != list1->Tail) || + (p2->NextElement == NULL && p2 != list2->Tail)) + { + fprintf(stderr, "%s (tail mismatch)\n", func); + return MISMATCH; + } + } + if (p1 != NULL || p2 != NULL) /* lists didn't both terminate */ + { + fprintf(stderr, "%s (unequal lists)\n", func); + return MISMATCH; + } + return OK; +} + +int compare_CSSM_SAMPLE(const CSSM_SAMPLE *sample1, const CSSM_SAMPLE *sample2) +{ + const char *func = "compare_CSSM_SAMPLE()"; + int ret; + + NULLCHECK(sample1, sample2, func); + ret = compare_CSSM_LIST(&sample1->TypedSample, &sample2->TypedSample); + if (ret != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + if (sample1->Verifier && sample2->Verifier) + { + ret = compare_CSSM_SUBSERVICE_UID(sample1->Verifier, sample2->Verifier); + if (ret != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + } + else if (sample1->Verifier && !sample2->Verifier || + !sample1->Verifier && sample2->Verifier) + { + fprintf(stderr, "%s (Verifier mismatch)\n", func); + return MISMATCH; + } + return OK; +} + +int compare_CSSM_SAMPLEGROUP(CSSM_SAMPLEGROUP *sgrp1, CSSM_SAMPLEGROUP *sgrp2) +{ + const char *func = "compare_CSSM_SAMPLEGROUP()"; + int ret; + u_int i; + + NULLCHECK(sgrp1, sgrp2, func); + if (sgrp1->NumberOfSamples != sgrp2->NumberOfSamples) + { + fprintf(stderr, "%s (NumberOfSamples mismatch)\n", func); + return MISMATCH; + } + for (i = 0; i < sgrp1->NumberOfSamples; ++i) + { + ret = compare_CSSM_SAMPLE(&sgrp1->Samples[i], &sgrp2->Samples[i]); + if (ret != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + } + return OK; +} + +int compare_CSSM_ENCODED_CERT(CSSM_ENCODED_CERT *cert1, + CSSM_ENCODED_CERT *cert2) +{ + const char *func = "compare_CSSM_ENCODED_CERT()"; + int ret; + + NULLCHECK(cert1, cert2, func); + if (cert1->CertType != cert2->CertType || + cert1->CertEncoding != cert2->CertEncoding) + { + fprintf(stderr, "%s (mismatch)\n", func); + return MISMATCH; + } + if ((ret = compare_CSSM_DATA(&cert1->CertBlob, &cert2->CertBlob)) != OK) + fprintf(stderr, "%s\n", func); + return ret; +} + +int compare_CSSM_CERTGROUP(CSSM_CERTGROUP *grp1, CSSM_CERTGROUP *grp2) +{ + const char *func = "compare_CSSM_CERTGROUP()"; + int ret; + u_int i; + + NULLCHECK(grp1, grp2, func); + if (grp1->CertType != grp2->CertType || + grp1->CertEncoding != grp2->CertEncoding || + grp1->NumCerts != grp2->NumCerts || + grp1->CertGroupType != grp2->CertGroupType || + grp1->Reserved != grp2->Reserved) + { + fprintf(stderr, "%s (mismatch)\n", func); + return MISMATCH; + } + for (i = 0; i < grp1->NumCerts; ++i) + { + char *err = NULL; + + switch (grp1->CertGroupType) + { + case CSSM_CERTGROUP_DATA: + ret = compare_CSSM_DATA(&grp1->GroupList.CertList[i], + &grp2->GroupList.CertList[i]); + break; + /* damned if I can find an example of the others */ + case CSSM_CERTGROUP_ENCODED_CERT: + /* + * This is apparently in use (see CertGroup in + * cdsa_utilities, cssmcert.{cpp,h}), but it's just a + * guess that it's implemented in the same way as + * CSSM_CERTGROUP_DATA... + */ + ret = compare_CSSM_ENCODED_CERT(&grp1->GroupList.EncodedCertList[i], + &grp2->GroupList.EncodedCertList[i]); + break; + case CSSM_CERTGROUP_PARSED_CERT: + err = "CSSM_CERTGROUP_PARSED_CERT unimplemented"; + ret = NOT_IMPLEMENTED; + break; + case CSSM_CERTGROUP_CERT_PAIR: + err = "CSSM_CERTGROUP_CERT_PAIR unimplemented"; + ret = NOT_IMPLEMENTED; + break; + default: + err = "unknown type"; + ret = UNKNOWN_TYPE; + break; + } + if (ret != OK) + { + if (err) + fprintf(stderr, "%s (%s)\n", func, err); + else + fprintf(stderr, "%s\n", func); + return ret; + } + } + return OK; +} + +int compare_CSSM_BASE_CERTS(CSSM_BASE_CERTS *bases1, CSSM_BASE_CERTS *bases2) +{ + const char *func = "compare_CSSM_BASE_CERTS()"; + int ret; + + NULLCHECK(bases1, bases2, func); + if (bases1->TPHandle != bases2->TPHandle || + bases1->CLHandle != bases2->CLHandle) + { + fprintf(stderr, "%s (mismatch)\n", func); + return MISMATCH; + } + ret = compare_CSSM_CERTGROUP(&bases1->Certs, &bases2->Certs); + if (ret != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + return OK; +} + +int compare_CSSM_ACCESS_CREDENTIALS(CSSM_ACCESS_CREDENTIALS *creds1, + CSSM_ACCESS_CREDENTIALS *creds2) +{ + const char *func = "compare_CSSM_ACCESS_CREDENTIALS()"; + int ret; + + NULLCHECK(creds1, creds2, func); + if (memcmp(creds1->EntryTag, creds2->EntryTag, sizeof(CSSM_STRING)) || + creds1->Callback != creds2->Callback || + creds1->CallerCtx != creds2->CallerCtx) + { + fprintf(stderr, "%s (mismatch)\n", func); + return MISMATCH; + } + ret = compare_CSSM_BASE_CERTS(&creds1->BaseCerts, &creds2->BaseCerts); + if (ret != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + ret = compare_CSSM_SAMPLEGROUP(&creds1->Samples, &creds2->Samples); + if (ret != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + return OK; +} + +int compare_CSSM_AUTHORIZATIONGROUP(CSSM_AUTHORIZATIONGROUP *grp1, + CSSM_AUTHORIZATIONGROUP *grp2) +{ + const char *func = "compare_CSSM_AUTHORIZATIONGROUP()"; + + NULLCHECK(grp1, grp2, func); + if (grp1->NumberOfAuthTags != grp2->NumberOfAuthTags || + memcmp(grp1->AuthTags, grp2->AuthTags, grp1->NumberOfAuthTags*ALIGNSIZE(CSSM_ACL_AUTHORIZATION_TAG))) + { + fprintf(stderr, "%s (mismatch)\n", func); + return MISMATCH; + } + return OK; +} + +int compare_CSSM_ACL_VALIDITY_PERIOD(CSSM_ACL_VALIDITY_PERIOD *period1, + CSSM_ACL_VALIDITY_PERIOD *period2) +{ + const char *func = "compare_CSSM_ACL_VALIDITY_PERIOD()"; + int ret; + + NULLCHECK(period1, period2, func); + ret = compare_CSSM_DATA(&period1->StartDate, &period1->StartDate); + if (ret != OK) + { + fprintf(stderr, "%s (StartDate)\n", func); + return ret; + } + ret = compare_CSSM_DATA(&period1->EndDate, &period1->EndDate); + if (ret != OK) + fprintf(stderr, "%s (EndDate)\n", func); + return ret; +} + +int compare_CSSM_ACL_ENTRY_PROTOTYPE(CSSM_ACL_ENTRY_PROTOTYPE *proto1, + CSSM_ACL_ENTRY_PROTOTYPE *proto2, + int skipGarbage) +{ + const char *func = "compare_CSSM_ACL_ENTRY_PROTOTYPE()"; + int ret; + + NULLCHECK(proto1, proto2, func); + ret = compare_CSSM_LIST(&proto1->TypedSubject, &proto2->TypedSubject); + if (ret != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + if (!skipGarbage) + { + if (proto1->Delegate != proto2->Delegate) + { + fprintf(stderr, "%s (Delegate mismatch)\n", func); + return MISMATCH; + } + } + ret = compare_CSSM_AUTHORIZATIONGROUP(&proto1->Authorization, &proto2->Authorization); + if (ret != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + if (!skipGarbage) + { + ret = compare_CSSM_ACL_VALIDITY_PERIOD(&proto1->TimeRange, &proto2->TimeRange); + if (ret != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + } + if (memcmp(proto1->EntryTag, proto2->EntryTag, sizeof(CSSM_STRING))) + { + fprintf(stderr, "%s (EntryTag mismatch)\n", func); + return MISMATCH; + } + return OK; +} + +int compare_CSSM_ACL_OWNER_PROTOTYPE(CSSM_ACL_OWNER_PROTOTYPE *proto1, + CSSM_ACL_OWNER_PROTOTYPE *proto2) +{ + const char *func = "compare_CSSM_ACL_OWNER_PROTOTYPE()"; + + NULLCHECK(proto1, proto2, func); + int ret = compare_CSSM_LIST(&proto1->TypedSubject, &proto2->TypedSubject); + if (ret != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + if (proto1->Delegate != proto2->Delegate) + { + fprintf(stderr, "%s (Delegate mismatch)\n", func); + return MISMATCH; + } + return OK; +} + +int compare_CSSM_ACL_ENTRY_INPUT(CSSM_ACL_ENTRY_INPUT *input1, + CSSM_ACL_ENTRY_INPUT *input2) +{ + const char *func = "compare_CSSM_ACL_ENTRY_INPUT()"; + int ret, skipGarbage = 0; + + NULLCHECK(input1, input2, func); + ret = compare_CSSM_ACL_ENTRY_PROTOTYPE(&input1->Prototype, + &input2->Prototype, + skipGarbage); + if (ret != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + if (input1->Callback != input2->Callback || + input1->CallerContext != input2->CallerContext) + { + fprintf(stderr, "%s (mismatch)\n", func); + return MISMATCH; + } + return OK; +} + +int compare_CSSM_ACL_ENTRY_INFO(CSSM_ACL_ENTRY_INFO *info1, + CSSM_ACL_ENTRY_INFO *info2) +{ + const char *func = "compare_CSSM_ACL_ENTRY_INFO()"; + int ret, skipGarbage = 0; + + NULLCHECK(info1, info2, func); +#if SECURITYD_SENDS_GARBAGE + skipGarbage = 1; + /* fprintf(stderr, "%s: skipping garbage\n", func); */ +#endif + ret = compare_CSSM_ACL_ENTRY_PROTOTYPE(&info1->EntryPublicInfo, + &info2->EntryPublicInfo, + skipGarbage); + if (ret != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + if (info1->EntryHandle != info2->EntryHandle) + { + fprintf(stderr, "%s (EntryHandle mismatch)\n", func); + return MISMATCH; + } + return OK; +} + +int compare_CSSM_DATE(CSSM_DATE *date1, CSSM_DATE *date2) +{ + const char *func = "compare_CSSM_DATE()"; + + NULLCHECK(date1, date2, func); + if (memcmp(date1, date2, sizeof(CSSM_DATE))) + { + fprintf(stderr, "%s (mismatch)\n", func); + return MISMATCH; + } + return OK; +} + +int compare_CSSM_KEYHEADER(CSSM_KEYHEADER *hdr1, CSSM_KEYHEADER *hdr2) +{ + const char *func = "compare_CSSM_KEYHEADER()"; + int ret; + + NULLCHECK(hdr1, hdr2, func); + if (hdr1->HeaderVersion != hdr2->HeaderVersion || + memcmp(&hdr1->CspId, &hdr2->CspId, sizeof(CSSM_GUID)) || + hdr1->BlobType != hdr2->BlobType || + hdr1->Format != hdr2->Format || + hdr1->AlgorithmId != hdr2->AlgorithmId || + hdr1->KeyClass != hdr2->KeyClass || + hdr1->LogicalKeySizeInBits != hdr2->LogicalKeySizeInBits || + hdr1->KeyUsage != hdr2->KeyUsage || + hdr1->WrapAlgorithmId != hdr2->WrapAlgorithmId || + hdr1->WrapMode != hdr2->WrapMode || + hdr1->Reserved != hdr2->Reserved) + { + fprintf(stderr, "%s (mismatch)\n", func); + return MISMATCH; + } + if ((ret = compare_CSSM_DATE(&hdr1->StartDate, &hdr2->StartDate)) != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + if ((ret = compare_CSSM_DATE(&hdr1->EndDate, &hdr2->EndDate)) != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + return OK; +} + +int compare_CSSM_KEY(CSSM_KEY *key1, CSSM_KEY *key2) +{ + const char *func = "compare_CSSM_KEY()"; + int ret; + + NULLCHECK(key1, key2, func); + if ((ret = compare_CSSM_KEYHEADER(&key1->KeyHeader, &key1->KeyHeader)) != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + if ((ret = compare_CSSM_DATA(&key1->KeyData, &key2->KeyData)) != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + return OK; +} + +int compare_CSSM_RANGE(CSSM_RANGE *range1, CSSM_RANGE *range2) +{ + const char *func = "compare_CSSM_RANGE()"; + + NULLCHECK(range1, range2, func); + if (memcmp(range1, range2, sizeof(CSSM_RANGE))) + { + fprintf(stderr, "%s (mismatch)\n", func); + return MISMATCH; + } + return OK; +} + +int compare_CSSM_CONTEXT_ATTRIBUTE(CSSM_CONTEXT_ATTRIBUTE *attr1, + CSSM_CONTEXT_ATTRIBUTE *attr2) +{ + const char *func = "compare_CSSM_CONTEXT_ATTRIBUTE()"; + char *err = NULL; + int ret = OK; + + NULLCHECK(attr1, attr2, func); + if (attr1->AttributeType != attr2->AttributeType || + attr1->AttributeLength != attr2->AttributeLength) + { + fprintf(stderr, "%s (mismatch)\n", func); + return MISMATCH; + } + switch (attr1->AttributeType & CSSM_ATTRIBUTE_TYPE_MASK) + { + case CSSM_ATTRIBUTE_DATA_UINT32: + if (attr1->Attribute.Uint32 != attr2->Attribute.Uint32) + { + err = "Uint32 mismatch"; + ret = MISMATCH; + } + break; + case CSSM_ATTRIBUTE_DATA_CSSM_DATA: + ret = compare_CSSM_DATA(attr1->Attribute.Data, attr2->Attribute.Data); + break; + case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA: + ret = compare_CSSM_CRYPTO_DATA(attr1->Attribute.CryptoData, attr2->Attribute.CryptoData); + break; + case CSSM_ATTRIBUTE_DATA_KEY: + ret = compare_CSSM_KEY(attr1->Attribute.Key, attr2->Attribute.Key); + break; + case CSSM_ATTRIBUTE_DATA_STRING: + if (memcmp(attr1->Attribute.String, attr2->Attribute.String, attr1->AttributeLength)) + { + err = "String mismatch"; + ret = MISMATCH; + } + break; + case CSSM_ATTRIBUTE_DATA_DATE: + ret = compare_CSSM_DATE(attr1->Attribute.Date, attr2->Attribute.Date); + break; + case CSSM_ATTRIBUTE_DATA_RANGE: + ret = compare_CSSM_RANGE(attr1->Attribute.Range, attr2->Attribute.Range); + break; + case CSSM_ATTRIBUTE_DATA_ACCESS_CREDENTIALS: + ret = compare_CSSM_ACCESS_CREDENTIALS(attr1->Attribute.AccessCredentials, + attr2->Attribute.AccessCredentials); + break; + case CSSM_ATTRIBUTE_DATA_VERSION: + if (memcmp(&attr1->Attribute.Version, &attr2->Attribute.Version, sizeof(CSSM_VERSION))) + { + err = "Version mismatch"; + ret = MISMATCH; + } + break; + case CSSM_ATTRIBUTE_DATA_DL_DB_HANDLE: + if (memcmp(&attr1->Attribute.DLDBHandle, &attr2->Attribute.DLDBHandle, sizeof(CSSM_DL_DB_HANDLE))) + { + err = "DLDBHandle mismatch"; + ret = MISMATCH; + } + break; + /* _PADDING and _KR_PROFILE not supported? */ + default: + err = "unknown type"; + ret = UNKNOWN_TYPE; + break; + } + if (ret != OK) + { + if (err) + fprintf(stderr, "%s (%s)\n", func, err); + else + fprintf(stderr, "%s\n", func); + return ret; + } + return OK; +} + +int compare_CSSM_CONTEXT(CSSM_CONTEXT *ctx1, CSSM_CONTEXT *ctx2) +{ + const char *func = "compare_CSSM_CONTEXT()"; + u_int i, ret; + + NULLCHECK(ctx1, ctx2, func); + if (ctx1->ContextType != ctx2->ContextType || + ctx1->AlgorithmType != ctx2->AlgorithmType || + ctx1->NumberOfAttributes != ctx2->NumberOfAttributes || + ctx1->CSPHandle != ctx2->CSPHandle || + ctx1->Privileged != ctx2->Privileged || + ctx1->EncryptionProhibited != ctx2->EncryptionProhibited || + ctx1->WorkFactor != ctx2->WorkFactor || + ctx1->Reserved != ctx2->Reserved) + { + fprintf(stderr, "%s (mismatch)\n", func); + return MISMATCH; + } + for (i = 0; i < ctx1->NumberOfAttributes; ++i) + { + ret = compare_CSSM_CONTEXT_ATTRIBUTE(&ctx1->ContextAttributes[i], + &ctx2->ContextAttributes[i]); + if (ret != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + } + return OK; +} + +int compare_CSSM_OID(CSSM_OID *oid1, CSSM_OID *oid2) +{ + return compare_CSSM_DATA(reinterpret_cast(oid1), + reinterpret_cast(oid2)); +} + +/* oy -- see cdsa_utilities, cssmdb.cpp: CompareAttributeInfos() */ +int compare_CSSM_DB_ATTRIBUTE_INFO(CSSM_DB_ATTRIBUTE_INFO *attrinfo1, + CSSM_DB_ATTRIBUTE_INFO *attrinfo2) +{ + const char *func = "compare_CSSM_DB_ATTRIBUTE_INFO()"; + + NULLCHECK(attrinfo1, attrinfo2, func); + if (attrinfo1->AttributeNameFormat != attrinfo2->AttributeNameFormat || + attrinfo1->AttributeFormat != attrinfo2->AttributeFormat) + { + fprintf(stderr, "%s (mismatch)\n", func); + return MISMATCH; + } + switch(attrinfo1->AttributeNameFormat) + { + case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: + if (strcmp(attrinfo1->Label.AttributeName, attrinfo2->Label.AttributeName)) + { + fprintf(stderr, "%s (string mismatch)\n", func); + return MISMATCH; + } + break; + case CSSM_DB_ATTRIBUTE_NAME_AS_OID: + return compare_CSSM_OID(&attrinfo1->Label.AttributeOID, + &attrinfo2->Label.AttributeOID); + break; + case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: + if (attrinfo1->Label.AttributeID != attrinfo2->Label.AttributeID) + { + fprintf(stderr, "%s (integer mismatch)\n", func); + return MISMATCH; + } + break; + default: + fprintf(stderr, "%s (unknown type)\n", func); + return UNKNOWN_TYPE; + } + return OK; +} + +int compare_CSSM_DB_ATTRIBUTE_DATA(CSSM_DB_ATTRIBUTE_DATA *attrdata1, + CSSM_DB_ATTRIBUTE_DATA *attrdata2) +{ + const char *func = "compare_CSSM_DB_ATTRIBUTE_DATA()"; + int ret; + uint32_t i; + + NULLCHECK(attrdata1, attrdata2, func); + ret = compare_CSSM_DB_ATTRIBUTE_INFO(&attrdata1->Info, &attrdata2->Info); + if (ret != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + if (attrdata1->NumberOfValues != attrdata2->NumberOfValues) + { + fprintf(stderr, "%s (mismatch)\n", func); + return MISMATCH; + } + for (i = 0; i < attrdata1->NumberOfValues; ++i) + { + ret = compare_CSSM_DATA(&attrdata1->Value[i], &attrdata2->Value[i]); + if (ret != OK) + { + fprintf(stderr, "%s (Value %d)\n", func, i+1); + return ret; + } + } + return OK; +} + +int compare_CSSM_SELECTION_PREDICATE(CSSM_SELECTION_PREDICATE *pred1, + CSSM_SELECTION_PREDICATE *pred2) +{ + const char *func = "compare_CSSM_SELECTION_PREDICATE()"; + int ret; + + NULLCHECK(pred1, pred2, func); + if (pred1->DbOperator != pred2->DbOperator) + { + fprintf(stderr, "%s (mismatch)\n", func); + return MISMATCH; + } + ret = compare_CSSM_DB_ATTRIBUTE_DATA(&pred1->Attribute, &pred2->Attribute); + if (ret != OK) + fprintf(stderr, "%s\n", func); + return ret; +} + +int compare_CSSM_QUERY_LIMITS(CSSM_QUERY_LIMITS *limits1, + CSSM_QUERY_LIMITS *limits2) +{ + const char *func = "compare_CSSM_QUERY_LIMITS()"; + + NULLCHECK(limits1, limits2, func); + if (limits1->TimeLimit != limits2->TimeLimit || + limits1->SizeLimit != limits2->SizeLimit) + { + fprintf(stderr, "%s (mismatch)\n", func); + return MISMATCH; + } + return OK; +} + +int compare_CSSM_QUERY(CSSM_QUERY *query1, CSSM_QUERY *query2) +{ + const char *func = "compare_CSSM_QUERY()"; + int ret; + uint32_t i; + + NULLCHECK(query1, query2, func); + if (query1->RecordType != query2->RecordType || + query1->Conjunctive != query2->Conjunctive || + query1->NumSelectionPredicates != query2->NumSelectionPredicates || + query1->QueryFlags != query2->QueryFlags) + { + fprintf(stderr, "%s (mismatch)\n", func); + return MISMATCH; + } + for (i = 0; i < query1->NumSelectionPredicates; ++i) + { + ret = compare_CSSM_SELECTION_PREDICATE(&query1->SelectionPredicate[i], + &query2->SelectionPredicate[i]); + } + ret = compare_CSSM_QUERY_LIMITS(&query1->QueryLimits, &query2->QueryLimits); + if (ret != OK) + fprintf(stderr, "%s\n", func); + return ret; +} + +/************************************************************************** + * Support routines for test_...() functions. + **************************************************************************/ + +CSSM_RETURN dummyACLSubjectCallback(const CSSM_LIST *subjectRequest, + void *callerContext, + const CSSM_MEMORY_FUNCS *MemFuncs) +{ + return CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED; /* XXX/gh */ +} + +/* + * Dummy func to make sure CSSM_CRYPTO_DATA isn't being corrupted. Kindly + * note the requirement that "context" be a CSSM_CRYPTO_DATA. + */ +CSSM_RETURN dummyCSSMCallback(CSSM_DATA *data, void *context) +{ + CSSM_CRYPTO_DATA_PTR crypto = (CSSM_CRYPTO_DATA *)context; + data->Length = crypto->Param.Length; + data->Data = (uint8 *)malloc(data->Length); /* XXX/gh leaked */ + /* XXX/gh yeah, should check if the malloc() failed */ + memcpy(data->Data, crypto->Param.Data, data->Length); + return CSSM_OK; +} + +/************************************************************************** + * test_CSSM_...() routines read sample data from disk (obtained from + * securityd via the SecuritydDataSave class), set up the named + * top-level structure by byte-reordering (if needed) and pointer + * relocating (using libsecurity_utilities walkers), and let the + * corresponding test_xdrwalk_...() routine test the XDR encoding/decoding + * routines against themselves and against the equivalent walker-generated + * output. + * + * General test methodology: + * + * encode/decode x 3, then compare (1) the encoded original vs. the decoded + * copy, and (2) the flattened encoded version with the equivalent walker's + * flattened output. + **************************************************************************/ + +/* TODO/gh don't worry about this until we get smart cards working */ +int test_CSSM_DB_RECORD_ATTRIBUTE_DATA(const char *srcfile) +{ + CSSM_DB_RECORD_ATTRIBUTE_DATA *data = NULL; + + if (srcfile) + { + /* read binary data from disk */ + } + else + { + /* dummy something up */ + data = (CSSM_DB_RECORD_ATTRIBUTE_DATA *)malloc(sizeof(CSSM_DB_RECORD_ATTRIBUTE_DATA)); + if (!data) + return MEM_ERROR; + data->DataRecordType = CSSM_DL_DB_RECORD_CERT; + /* TODO/gh pick up from here */ + } + if (data) + free(data); + return NOT_IMPLEMENTED; /* TODO/gh */ +} + +int test_xdrwalk_CSSM_CONTEXT(CSSM_CONTEXT *ctx, int dbglvl) +{ + const char *func = "test_xdrwalk_CSSM_CONTEXT()"; + CSSM_CONTEXT *walkcopy, *xdrctxcopy = NULL; + CSSM_CONTEXT_ATTRIBUTE *attrs; + void *flattenedCtxPtr = NULL; + u_int flattenedCtxLen = 0, i; + int ret, iter; + size_t attrsSize, walkedAttrsSize; + + /* + * Reimplement Context::Builder so we control where the memory is + * allocated, thus what pointer values are. + */ + SizeWalker sizer; + for (i = 0; i < ctx->NumberOfAttributes; ++i) + { + walk(sizer, ctx->ContextAttributes[i]); + } + attrsSize = ALIGNUP(ctx->NumberOfAttributes * sizeof(CSSM_CONTEXT_ATTRIBUTE)); + walkedAttrsSize = attrsSize + ALIGNUP(sizer); + + /* create a *flat* copy of ctx for direct memcmp() w/ XDR copy */ + walkcopy = reinterpret_cast(calloc(1, sizeof(CSSM_CONTEXT) + walkedAttrsSize)); + if (walkcopy == NULL) + { + fprintf(stderr, "%s: error allocating walked context\n", func); + return MEM_ERROR; + } + memcpy(walkcopy, ctx, sizeof(CSSM_CONTEXT)); + attrs = reinterpret_cast(reinterpret_cast(walkcopy) + sizeof(CSSM_CONTEXT)); + CopyWalker copier = LowLevelMemoryUtilities::increment(attrs, attrsSize); + for (i = 0; i < ctx->NumberOfAttributes; ++i) + { + attrs[i] = ctx->ContextAttributes[i]; /* shallow copy */ + walk(copier, attrs[i]); /* deep copy */ + } + walkcopy->ContextAttributes = attrs; + + for (iter = 0; iter < N_ITERS; ++iter) + { + if (!xdr_mem_encode(ctx, &flattenedCtxPtr, &flattenedCtxLen, + (xdrproc_t)xdr_CSSM_CONTEXT)) + { + fprintf(stderr, "%s, round %d (encode error)\n", func, iter+1); + return XDR_ENCODE_ERROR; + } + /* always zero out memory before attempting a decode */ + if ((xdrctxcopy = (CSSM_CONTEXT *)calloc(1, sizeof(CSSM_CONTEXT))) == NULL) + { + fprintf(stderr, "%s, round %d (allocation error)\n", func, iter+1); + return MEM_ERROR; + } + if (!xdr_mem_decode(flattenedCtxPtr, xdrctxcopy, flattenedCtxLen, + (xdrproc_t)xdr_CSSM_CONTEXT)) + { + fprintf(stderr, "%s, round %d (decode error)\n", func, iter+1); + return XDR_DECODE_ERROR; + } + if (dbglvl >= 3) + printf("comparing XDR-generated structs...\n"); + if ((ret = compare_CSSM_CONTEXT(ctx, xdrctxcopy)) != OK) + { + fprintf(stderr, "%s: CSSM_CONTEXT old/new XDR comparison, round %d, failed\n", + func, iter+1); + return ret; + } + if (dbglvl >= 3) + printf("comparing walked- and XDR-generated structs...\n"); + if ((ret = compare_CSSM_CONTEXT(xdrctxcopy, walkcopy)) != OK) + { + fprintf(stderr, "%s: CSSM_CONTEXT XDR/walker comparison, round %d, failed\n", + func, iter+1); + return ret; + } + if (dbglvl >= 2) + printf("CSSM_CONTEXT compared OK, round %d\n", iter+1); +#if 0 + if (dbglvl >= 3) + printf("Starting XDR/walker comparison...\n"); + /* + * XXX/gh xdrctxcopy and walkcopy should be identical except for + * pointer offsets. However, xdrctxcopy has extra bytes following + * CSSM_CONTEXT's Reserved field; still investigating why. + */ + /* XXX/gh relocate somebody's pointers */ + if (memcmp(walkcopy, xdrctxcopy, walkedAttrsSize+sizeof(CSSM_CONTEXT))) + { + fprintf(stderr, "%s, round %d (comparison failed)\n", func, iter+1); + return MISMATCH; + } +#endif + if (iter > 0) + free(ctx); + ctx = xdrctxcopy; + free(flattenedCtxPtr); + flattenedCtxPtr = NULL; + flattenedCtxLen = 0; + } + if (dbglvl >= 1) + printf("Successfully finished CSSM_CONTEXT check\n"); + return OK; +} + +int test_CSSM_CONTEXT(int fd, int doflip, int dbglvl) +{ + const char *func = "test_CSSM_CONTEXT()"; + CSSM_CONTEXT ctx; + CSSM_CONTEXT_ATTRIBUTE *attrs; + int ret; + CSSM_CRYPTO_DATA crypto; + + if (fd > -1) /* cheesy hack, but what ya gonna do? */ + { + int csize, attrSize; + u_int i; + intptr_t attraddr; + off_t offset; + /* + * Saved format: + * - size (of CSSM_CONTEXT) + * - CSSM_CONTEXT + * - size (of starting address for attributes) + * - starting address for CSSM_CONTEXT_ATTRIBUTEs + * - total size of CSSM_CONTEXT_ATTRIBUTEs + * - CSSM_CONTEXT_ATTRIBUTEs (contiguous) + */ + + /* context size; not really needed */ + if (read(fd, &csize, sizeof(csize)) != static_cast(sizeof(csize))) + { + fprintf(stderr, "%s: Error reading context size\n", func); + return BAD_READ; + } + if (doflip) flip(&csize, sizeof(csize)); + if (read(fd, &ctx, csize) != static_cast(csize)) + { + fprintf(stderr, "Error reading context\n"); + return BAD_READ; + } + /* Defer reorder of CSSM_CONTEXT until attributes have been read */ + /* attribute array starting address */ + if (read(fd, &csize, sizeof(csize)) != static_cast(sizeof(csize))) + { + fprintf(stderr, "Error reading attribute address size\n"); + return BAD_READ; + } + if (doflip) flip(&csize, sizeof(csize)); + if (read(fd, &attraddr, csize) != csize) + { + fprintf(stderr, "Error reading attribute address\n"); + return BAD_READ; + } + /* + * byte reorder of old attribute address, if needed, handled in + * hostorder_CSSM_CONTEXT() + */ + /* size of attributes */ + if (read(fd, &attrSize, sizeof(attrSize)) != static_cast(sizeof(attrSize))) + { + fprintf(stderr, "Error reading attribute size\n"); + return BAD_READ; + } + if (doflip) flip(&attrSize, sizeof(attrSize)); + if ((attrs = (CSSM_CONTEXT_ATTRIBUTE *)malloc(attrSize)) == NULL) + return MEM_ERROR; + /* attributes */ + if (read(fd, attrs, attrSize) != attrSize) + { + fprintf(stderr, "Error reading attributes\n"); + return BAD_READ; + } + if (doflip) + { + ctx.ContextAttributes = reinterpret_cast(attraddr); + hostorder_CSSM_CONTEXT(&ctx, attrs); + } + else + { + /* NB: this was the working code before byte-reordering */ + offset = reinterpret_cast(attrs) - attraddr; + ReconstituteWalker relocator(offset); + for (i = 0; i < ctx.NumberOfAttributes; ++i) + { + walk(relocator, attrs[i]); + } + ctx.ContextAttributes = attrs; + } + (void)close(fd); + } + else + { + int err; + uint32_t intattr; + + /* + * dummy something up; this is from FakeContext usages in + * securityd/tests/ + */ + ctx.ContextType = CSSM_ALGCLASS_KEYGEN; + ctx.AlgorithmType = CSSM_ALGID_DES; +#define N_TEST_ATTRS 2 + ctx.NumberOfAttributes = N_TEST_ATTRS; + attrs = (CSSM_CONTEXT_ATTRIBUTE *)malloc(N_TEST_ATTRS*sizeof(CSSM_CONTEXT_ATTRIBUTE)); + if (!attrs) + return MEM_ERROR; + ctx.ContextAttributes = attrs; + intattr = 64; + err = fill_CSSM_CONTEXT_ATTRIBUTE(&ctx.ContextAttributes[0], + CSSM_ATTRIBUTE_KEY_LENGTH, + sizeof(uint32_t), + &intattr); + if (err != OK) + return err; + crypto.Param.Length = strlen(testString); + crypto.Param.Data = (uint8 *)testString; +#if 0 + crypto.Callback = dummyCSSMCallback; + crypto.CallerCtx = &crypto; /* dummy cb needs crypto.Param */ +#endif + crypto.Callback = NULL; + crypto.CallerCtx = NULL; /* dummy cb needs crypto.Param */ + err = fill_CSSM_CONTEXT_ATTRIBUTE(&ctx.ContextAttributes[1], + CSSM_ATTRIBUTE_SEED, + sizeof(CSSM_CRYPTO_DATA), + (void *)&crypto); + if (err != OK) + return err; + ctx.CSPHandle = 13; + ctx.Privileged = CSSM_TRUE; /* ! 0 */ + ctx.EncryptionProhibited = CSSM_TRUE; + ctx.WorkFactor = 41; + ctx.Reserved = 0xfeefee; /* sentry value */ + } + + if ((ret = test_xdrwalk_CSSM_CONTEXT(&ctx, dbglvl)) != OK) + { + fprintf(stderr, "%s\n", func); + return ret; + } + return OK; +} + +int test_xdrwalk_CSSM_ACL_OWNER_PROTOTYPE(CSSM_ACL_OWNER_PROTOTYPE *aclOwnerPrototype, + int dbglvl) +{ + const char *func = "test_xdrwalk_CSSM_ACL_OWNER_PROTOTYPE()"; + CSSM_ACL_OWNER_PROTOTYPE *walkcopy, *xdrcopy; + void *flattenedAclOwnerPtr = NULL; + u_int flattenedAclOwnerLen = 0; + int ret, iter; + + /* save off aclOwnerPrototype because we're going to reuse the pointer */ + walkcopy = reinterpret_cast(calloc(1, sizeof(CSSM_ACL_OWNER_PROTOTYPE))); + if (walkcopy == NULL) + { + fprintf(stderr, "%s: error allocating walked CSSM_ACL_OWNER_PROTOTYPE\n", func); + return MEM_ERROR; + } + memcpy(walkcopy, aclOwnerPrototype, sizeof(CSSM_ACL_OWNER_PROTOTYPE)); + /* aclOwnerPrototype *is* a walked copy, so no need to re-walk it */ + + for (iter = 0; iter < N_ITERS; ++iter) + { + if (!xdr_mem_encode(aclOwnerPrototype, &flattenedAclOwnerPtr, + &flattenedAclOwnerLen, + reinterpret_cast(xdr_CSSM_ACL_OWNER_PROTOTYPE))) + { + fprintf(stderr, "%s, round %d (encode error)\n", func, iter+1); + return XDR_ENCODE_ERROR; + } + /* always zero out memory before attempting a decode */ + if ((xdrcopy = (CSSM_ACL_OWNER_PROTOTYPE *)calloc(1, sizeof(CSSM_ACL_OWNER_PROTOTYPE))) == NULL) + { + fprintf(stderr, "%s, round %d (allocation error)\n", func, iter+1); + return MEM_ERROR; + } + if (!xdr_mem_decode(flattenedAclOwnerPtr, xdrcopy, flattenedAclOwnerLen, + (xdrproc_t)xdr_CSSM_ACL_OWNER_PROTOTYPE)) + { + fprintf(stderr, "%s, round %d (decode error)\n", func, iter+1); + return XDR_DECODE_ERROR; + } + if (dbglvl >= 3) + printf("comparing XDR-generated structs...\n"); + if ((ret = compare_CSSM_ACL_OWNER_PROTOTYPE(aclOwnerPrototype, xdrcopy)) != OK) + { + fprintf(stderr, "%s: CSSM_ACL_OWNER_PROTOTYPE old/new XDR comparison, round %d, failed\n", + func, iter+1); + return ret; + } + if (dbglvl >= 3) + printf("comparing walked- and XDR-generated structs...\n"); + if ((ret = compare_CSSM_ACL_OWNER_PROTOTYPE(xdrcopy, walkcopy)) != OK) + { + fprintf(stderr, "%s: CSSM_ACL_OWNER_PROTOTYPE XDR/walker comparison, round %d, failed\n", + func, iter+1); + return ret; + } + if (dbglvl >= 2) + printf("CSSM_ACL_OWNER_PROTOTYPE compared OK, round %d\n", iter+1); + if (iter > 0) + free(aclOwnerPrototype); + aclOwnerPrototype = xdrcopy; + free(flattenedAclOwnerPtr); + flattenedAclOwnerPtr = NULL; + flattenedAclOwnerLen = 0; + } + + if (dbglvl >= 1) + printf("Successfully finished CSSM_ACL_OWNER_PROTOTYPE check\n"); + return OK; +} + +int test_CSSM_ACL_OWNER_PROTOTYPE(int fd, int doflip, int dbglvl) +{ + const char *func = "test_CSSM_ACL_OWNER_PROTOTYPE()"; + CSSM_ACL_OWNER_PROTOTYPE *aclOwnerPrototype; + int ret; + + if (fd > -1) /* cheesy hack, but what ya gonna do? */ + { + int aclsize; + uint32_t ptrsize; /* AKA mach_msg_type_number_t, AKA natural_t */ + intptr_t baseptr; + off_t offset; + /* + * Saved format: + * - sizeof(base pointer) + * - base pointer + * - length + * - CSSM_ACL_OWNER_PROTOTYPE + */ + if (read(fd, &ptrsize, sizeof(ptrsize)) < static_cast(sizeof(ptrsize))) + { + fprintf(stderr, "%s: Error reading base pointer size\n", func); + return BAD_READ; + } + if (doflip) flip(&ptrsize, sizeof(ptrsize)); + if (read(fd, &baseptr, ptrsize) < static_cast(ptrsize)) + { + fprintf(stderr, "%s: Error reading base pointer\n", func); + return BAD_READ; + } + if (doflip) flip(&baseptr, sizeof(baseptr)); + if (read(fd, &aclsize, sizeof(aclsize)) < static_cast(sizeof(aclsize))) + { + fprintf(stderr, "%s: Error reading AclOwnerPrototype size\n", func); + return BAD_READ; + } + if (doflip) flip(&aclsize, sizeof(aclsize)); + aclOwnerPrototype = (CSSM_ACL_OWNER_PROTOTYPE *)malloc(aclsize); + if (aclOwnerPrototype == NULL) + return MEM_ERROR; + if (read(fd, aclOwnerPrototype, aclsize) < aclsize) + { + fprintf(stderr, "Error reading CSSM_ACL_OWNER_PROTOTYPE\n"); + return BAD_READ; + } + offset = reinterpret_cast(aclOwnerPrototype) - baseptr; + if (doflip) + { + hostorder_CSSM_ACL_OWNER_PROTOTYPE(aclOwnerPrototype, offset); + } + else + { + ReconstituteWalker relocator(offset); + walk(relocator, reinterpret_cast(baseptr)); + } + (void)close(fd); + } + else + { + /* TODO/gh cobble something up */ + return NOT_IMPLEMENTED; + } + + ret = test_xdrwalk_CSSM_ACL_OWNER_PROTOTYPE(aclOwnerPrototype, dbglvl); + if (ret != OK) + fprintf(stderr, "%s\n", func); + free(aclOwnerPrototype); + return ret; +} + +int test_xdrwalk_CSSM_ACL_ENTRY_INPUT(CSSM_ACL_ENTRY_INPUT *aclEntryInput, + int dbglvl) +{ + const char *func = "test_xdrwalk_CSSM_ACL_ENTRY_INPUT()"; + CSSM_ACL_ENTRY_INPUT *walkcopy, *xdrcopy; + void *flattenedAclEIPtr = NULL; + u_int flattenedAclEILen = 0; + int ret, iter; + + /* save off aclEntryInput because we're going to reuse the pointer */ + walkcopy = reinterpret_cast(calloc(1, sizeof(CSSM_ACL_ENTRY_INPUT))); + if (walkcopy == NULL) + { + fprintf(stderr, "%s: error allocating walked CSSM_ACL_ENTRY_INPUT\n", func); + return MEM_ERROR; + } + memcpy(walkcopy, aclEntryInput, sizeof(CSSM_ACL_ENTRY_INPUT)); + /* aclEntryInput *is* a walked copy, so no need to re-walk it */ + + for (iter = 0; iter < N_ITERS; ++iter) + { + if (!xdr_mem_encode(aclEntryInput, &flattenedAclEIPtr, &flattenedAclEILen, + (xdrproc_t)xdr_CSSM_ACL_ENTRY_INPUT)) + { + fprintf(stderr, "%s, round %d\n", func, iter+1); + return XDR_ENCODE_ERROR; + } + /* always zero out memory before attempting a decode */ + if ((xdrcopy = (CSSM_ACL_ENTRY_INPUT *)calloc(1, sizeof(CSSM_ACL_ENTRY_INPUT))) == NULL) + { + fprintf(stderr, "%s, round %d (allocation error)\n", func, iter+1); + return MEM_ERROR; + } + if (!xdr_mem_decode(flattenedAclEIPtr, xdrcopy, flattenedAclEILen, + (xdrproc_t)xdr_CSSM_ACL_ENTRY_INPUT)) + { + fprintf(stderr, "%s, round %d\n", func, iter+1); + return XDR_DECODE_ERROR; + } + if (dbglvl >= 3) + printf("comparing XDR-generated structs...\n"); + if ((ret = compare_CSSM_ACL_ENTRY_INPUT(aclEntryInput, xdrcopy)) != OK) + { + fprintf(stderr, "%s: CSSM_ACL_ENTRY_INPUT old/new XDR comparison, round %d, failed\n", + func, iter+1); + return ret; + } + if (dbglvl >= 3) + printf("comparing walked- and XDR-generated structs...\n"); + if ((ret = compare_CSSM_ACL_ENTRY_INPUT(xdrcopy, walkcopy)) != OK) + { + fprintf(stderr, "%s: CSSM_ACL_ENTRY_INPUT XDR/walker comparison, round %d, failed\n", + func, iter+1); + return ret; + } + if (dbglvl >= 2) + printf("CSSM_ACL_ENTRY_INPUT compared OK, round %d\n", iter+1); + if (iter > 0) + free(aclEntryInput); + aclEntryInput = xdrcopy; + free(flattenedAclEIPtr); + flattenedAclEIPtr = NULL; + flattenedAclEILen = 0; + } + + if (dbglvl >= 1) + printf("Successfully finished CSSM_ACL_ENTRY_INPUT check\n"); + return OK; +} + +int test_CSSM_ACL_ENTRY_INPUT(int fd, int doflip, int dbglvl) +{ + const char *func = "test_CSSM_ACL_ENTRY_INPUT()"; + CSSM_ACL_ENTRY_INPUT *aclEntryInput; + int ret; + + if (fd > -1) /* cheesy hack, but what ya gonna do? */ + { + int aclsize; + uint32_t ptrsize; /* AKA mach_msg_type_number_t, AKA natural_t */ + intptr_t baseptr; + off_t offset; + /* + * Saved format: + * - sizeof(base pointer) + * - base pointer + * - length + * - CSSM_ACL_ENTRY_INPUT + */ + if (read(fd, &ptrsize, sizeof(ptrsize)) < static_cast(sizeof(ptrsize))) + { + fprintf(stderr, "%s: Error reading base pointer size\n", func); + return BAD_READ; + } + if (doflip) flip(&ptrsize, sizeof(ptrsize)); + if (read(fd, &baseptr, ptrsize) < static_cast(ptrsize)) + { + fprintf(stderr, "%s: Error reading base pointer\n", func); + return BAD_READ; + } + if (doflip) flip(&baseptr, sizeof(baseptr)); + if (read(fd, &aclsize, sizeof(aclsize)) < static_cast(sizeof(aclsize))) + { + fprintf(stderr, "%s: Error reading AclEntryInput size\n", func); + return BAD_READ; + } + if (doflip) flip(&aclsize, sizeof(aclsize)); + aclEntryInput = (CSSM_ACL_ENTRY_INPUT *)malloc(aclsize); + if (aclEntryInput == NULL) + return MEM_ERROR; + if (read(fd, aclEntryInput, aclsize) < aclsize) + { + fprintf(stderr, "Error reading CSSM_ACL_ENTRY_INPUT\n"); + return BAD_READ; + } + offset = reinterpret_cast(aclEntryInput) - baseptr; + if (doflip) + { + hostorder_CSSM_ACL_ENTRY_INPUT(aclEntryInput, offset); + } + else + { + ReconstituteWalker relocator(offset); + walk(relocator, reinterpret_cast(baseptr)); + } + (void)close(fd); + } + else + { + /* TODO/gh cobble something up */ + fprintf(stderr, "%s: hard-coded test not implemented yet\n", func); + return NOT_IMPLEMENTED; + } + + if ((ret = test_xdrwalk_CSSM_ACL_ENTRY_INPUT(aclEntryInput, dbglvl)) != OK) + fprintf(stderr, "%s\n", func); + free(aclEntryInput); + return ret; +} + +int test_xdrwalk_CSSM_ACL_ENTRY_INFO(CSSM_ACL_ENTRY_INFO *aclEntryInfo, + int dbglvl) +{ + const char *func = "test_xdrwalk_CSSM_ACL_ENTRY_INFO()"; + + CSSM_ACL_ENTRY_INFO *walkcopy, *xdrcopy; + void *flattenedAclEIPtr = NULL; + u_int flattenedAclEILen = 0; + int ret, iter; + + /* save off aclEntryInfo because we're going to reuse the pointer */ + walkcopy = reinterpret_cast(calloc(1, sizeof(CSSM_ACL_ENTRY_INFO))); + if (walkcopy == NULL) + { + fprintf(stderr, "%s: error allocating walked CSSM_ACL_ENTRY_INFO\n", func); + return MEM_ERROR; + } + memcpy(walkcopy, aclEntryInfo, sizeof(CSSM_ACL_ENTRY_INFO)); + /* right now aclEntryInfo *is* a walked copy, so no need to re-walk it */ + for (iter = 0; iter < N_ITERS; ++iter) + { + if (!xdr_mem_encode(aclEntryInfo, &flattenedAclEIPtr, &flattenedAclEILen, + (xdrproc_t)xdr_CSSM_ACL_ENTRY_INFO)) + { + fprintf(stderr, "%s, round %d\n", func, iter+1); + return XDR_ENCODE_ERROR; + } + /* always zero out memory before attempting a decode */ + if ((xdrcopy = (CSSM_ACL_ENTRY_INFO *)calloc(1, sizeof(CSSM_ACL_ENTRY_INFO))) == NULL) + { + fprintf(stderr, "%s, round %d (allocation error)\n", func, iter+1); + return MEM_ERROR; + } + if (!xdr_mem_decode(flattenedAclEIPtr, xdrcopy, flattenedAclEILen, + (xdrproc_t)xdr_CSSM_ACL_ENTRY_INFO)) + { + fprintf(stderr, "%s, round %d\n", func, iter+1); + return XDR_DECODE_ERROR; + } + if (dbglvl >= 3) + printf("comparing XDR-generated structs...\n"); + if ((ret = compare_CSSM_ACL_ENTRY_INFO(aclEntryInfo, xdrcopy)) != OK) + { + fprintf(stderr, "%s: CSSM_ACL_ENTRY_INFO old/new XDR comparison, round %d, failed\n", + func, iter+1); + return ret; + } + if (dbglvl >= 3) + printf("comparing walked- and XDR-generated structs...\n"); + if ((ret = compare_CSSM_ACL_ENTRY_INFO(xdrcopy, walkcopy)) != OK) + { + fprintf(stderr, "%s: CSSM_ACL_ENTRY_INFO XDR/walker comparison, round %d, failed\n", + func, iter+1); + return ret; + } + if (dbglvl >= 2) + printf("CSSM_ACL_ENTRY_INFO compared OK, round %d\n", iter+1); + if (iter > 0) + free(aclEntryInfo); + aclEntryInfo = xdrcopy; + free(flattenedAclEIPtr); + flattenedAclEIPtr = NULL; + flattenedAclEILen = 0; + } + if (dbglvl >= 1) + printf("Successfully finished CSSM_ACL_ENTRY_INFO check\n"); + return OK; +} + +int test_CSSM_ACL_ENTRY_INFO(int fd, int doflip, int dbglvl) +{ + const char *func = "test_CSSM_ACL_ENTRY_INFO()"; + CSSM_ACL_ENTRY_INFO *aclEntryInfo; + int ret, aclsize; + + if (fd > -1) /* cheesy hack, but what ya gonna do? */ + { + uint32_t ptrsize; /* AKA mach_msg_type_number_t, AKA natural_t */ + intptr_t baseptr; + off_t offset; + /* + * Saved format (v. 1 of saved-data protocol): + * - preamble + * - sizeof(base pointer) + * - base pointer + * - length + * - CSSM_ACL_ENTRY_INFO + */ + + if (read(fd, &ptrsize, sizeof(ptrsize)) < static_cast(sizeof(ptrsize))) + { + fprintf(stderr, "%s: Error reading base pointer size\n", func); + return BAD_READ; + } + if (doflip) flip(&ptrsize, sizeof(ptrsize)); + if (read(fd, &baseptr, ptrsize) < static_cast(ptrsize)) + { + fprintf(stderr, "%s: Error reading base pointer\n", func); + return BAD_READ; + } + if (doflip) flip(&baseptr, sizeof(baseptr)); + if (read(fd, &aclsize, sizeof(aclsize)) < static_cast(sizeof(aclsize))) + { + fprintf(stderr, "%s: Error reading AclEntryInput size\n", func); + return BAD_READ; + } + if (doflip) flip(&aclsize, sizeof(aclsize)); + aclEntryInfo = (CSSM_ACL_ENTRY_INFO *)malloc(aclsize); + if (aclEntryInfo == NULL) + return MEM_ERROR; + if (read(fd, aclEntryInfo, aclsize) < aclsize) + { + fprintf(stderr, "Error reading CSSM_ACL_ENTRY_INFO\n"); + return BAD_READ; + } + offset = reinterpret_cast(aclEntryInfo) - baseptr; + if (doflip) + { + hostorder_CSSM_ACL_ENTRY_INFO(aclEntryInfo, offset); + } + else + { + ReconstituteWalker relocator(offset); + walk(relocator, reinterpret_cast(baseptr)); + } + (void)close(fd); + } + else + { + /* TODO/gh cobble something up */ + fprintf(stderr, "%s: hard-coded test not implemented yet\n", func); + return NOT_IMPLEMENTED; + } + if ((ret = test_xdrwalk_CSSM_ACL_ENTRY_INFO(aclEntryInfo, dbglvl)) != OK) + fprintf(stderr, "%s\n", func); + free(aclEntryInfo); + return ret; +} + +int test_xdrwalk_CSSM_QUERY(CSSM_QUERY *query, int dbglvl) +{ + const char *func = "test_xdrwalk_CSSM_QUERY()"; + + CSSM_QUERY *walkcopy, *xdrcopy; + void *flattenedQueryPtr = NULL; + u_int flattenedQueryLen = 0; + int ret, iter; + + /* save off query because we're going to reuse the pointer */ + walkcopy = reinterpret_cast(calloc(1, sizeof(CSSM_QUERY))); + if (walkcopy == NULL) + { + fprintf(stderr, "%s: error allocating walked CSSM_QUERY\n", func); + return MEM_ERROR; + } + memcpy(walkcopy, query, sizeof(CSSM_QUERY)); + /* right now query *is* a walked copy, so no need to re-walk it */ + for (iter = 0; iter < N_ITERS; ++iter) + { + if (!xdr_mem_encode(query, &flattenedQueryPtr, &flattenedQueryLen, + (xdrproc_t)xdr_CSSM_QUERY)) + { + fprintf(stderr, "%s, round %d\n", func, iter+1); + return XDR_ENCODE_ERROR; + } + /* always zero out memory before attempting a decode */ + if ((xdrcopy = (CSSM_QUERY *)calloc(1, sizeof(CSSM_QUERY))) == NULL) + { + fprintf(stderr, "%s, round %d (allocation error)\n", func, iter+1); + return MEM_ERROR; + } + if (!xdr_mem_decode(flattenedQueryPtr, xdrcopy, flattenedQueryLen, + (xdrproc_t)xdr_CSSM_QUERY)) + { + fprintf(stderr, "%s, round %d\n", func, iter+1); + return XDR_DECODE_ERROR; + } + if (dbglvl >= 3) + printf("comparing XDR-generated structs...\n"); + if ((ret = compare_CSSM_QUERY(query, xdrcopy)) != OK) + { + fprintf(stderr, "%s: CSSM_QUERY old/new XDR comparison, round %d, failed\n", + func, iter+1); + return ret; + } + if (dbglvl >= 3) + printf("comparing walked- and XDR-generated structs...\n"); + if ((ret = compare_CSSM_QUERY(xdrcopy, walkcopy)) != OK) + { + fprintf(stderr, "%s: CSSM_QUERY XDR/walker comparison, round %d, failed\n", + func, iter+1); + return ret; + } + if (dbglvl >= 2) + printf("CSSM_QUERY compared OK, round %d\n", iter+1); + if (iter > 0) + free(query); + query = xdrcopy; + free(flattenedQueryPtr); + flattenedQueryPtr = NULL; + flattenedQueryLen = 0; + } + if (dbglvl >= 1) + printf("Successfully finished CSSM_QUERY check\n"); + return OK; +} + +int test_CSSM_QUERY(int fd, int doflip, int dbglvl) +{ + const char *func = "test_CSSM_QUERY()"; + CSSM_QUERY *query; + int ret, querysize; + + if (fd > -1) /* cheesy hack, but what ya gonna do? */ + { + uint32_t ptrsize; /* AKA mach_msg_type_number_t, AKA natural_t */ + intptr_t baseptr; + off_t offset; + ssize_t readPtr; + int nq = 0; /* # of queries */ + /* + * Saved format (v. 1 of saved-data protocol): + * - preamble + * - sizeof(base pointer) + * - base pointer + * - length + * - CSSM_QUERY + */ + do + { + if (nq) /* first readPreamble() was in main() */ + { + /* dummy vars -- let the func params govern */ + uint32_t d1, d2, d3 = 0; + if ((ret = readPreamble(fd, &d1, &d2, &d3)) != OK) + { + if (ret == READ_EOF) + { + readPtr = -1; + continue; + } + return ret; + } + } + readPtr = read(fd, &ptrsize, sizeof(ptrsize)); + if (readPtr == 0) break; /* we're done */ + if (readPtr < static_cast(sizeof(ptrsize))) + { + fprintf(stderr, "%s: Error reading base pointer size\n", func); + return BAD_READ; + } + if (doflip) flip(&ptrsize, sizeof(ptrsize)); + if (read(fd, &baseptr, ptrsize) < static_cast(ptrsize)) + { + fprintf(stderr, "%s: Error reading base pointer\n", func); + return BAD_READ; + } + if (doflip) flip(&baseptr, sizeof(baseptr)); + if (read(fd, &querysize, sizeof(querysize)) < static_cast(sizeof(querysize))) + { + fprintf(stderr, "%s: Error reading CSSM_QUERY size\n", func); + return BAD_READ; + } + if (doflip) flip(&querysize, sizeof(querysize)); + query = (CSSM_QUERY *)malloc(querysize); + if (query == NULL) + return MEM_ERROR; + if (read(fd, query, querysize) < querysize) + { + fprintf(stderr, "Error reading CSSM_QUERY\n"); + return BAD_READ; + } + offset = reinterpret_cast(query) - baseptr; + if (doflip) + { + hostorder_CSSM_QUERY(query, offset); + } + else + { + ReconstituteWalker relocator(offset); + walk(relocator, reinterpret_cast(baseptr)); + } + ++nq; + if (dbglvl >= 2) + printf("%s: read a new CSSM_QUERY (%d)\n", func, nq); + if ((ret = test_xdrwalk_CSSM_QUERY(query, dbglvl)) != OK) + fprintf(stderr, "%s\n", func); + free(query); + } + while (readPtr != -1); + (void)close(fd); + } + else + { + /* TODO/gh cobble something up */ + fprintf(stderr, "%s: hard-coded test not implemented yet\n", func); + return NOT_IMPLEMENTED; + } + return OK; +} + +void usage(const char *progname) +{ + fprintf(stderr, "Usage: %s [-c|-I|-i] \n", progname); + fprintf(stderr, " FILE is binary data saved from securityd\n"); + fprintf(stderr, " -c\trun hard-coded CSSM_CONTEXT test\n"); + fprintf(stderr, " -i\trun hard-coded CSSM_ACL_ENTRY_INFO test\n"); + fprintf(stderr, " -I\trun hard-coded CSSM_ACL_ENTRY_INPUT test\n"); + fprintf(stderr, " -v\tverbose (more -v options mean more output\n"); + fprintf(stderr, " If FILE is not provided, %s will try to run any requested hard-coded test\n", progname); +} + +int main(int ac, char **av) +{ + const char *optstring = "chIiv"; + char *infile = NULL; + int c, fd, ret = OK, debuglevel = 0; + uint32_t doflip, version, type = 0; + + while ((c = getopt(ac, av, optstring)) != EOF) + { + switch(c) + { + case 'c': + type = SecuritydDataSave::CONTEXT; + break; + case 'I': + type = SecuritydDataSave::ACL_ENTRY_INPUT; + break; + case 'i': + type = SecuritydDataSave::ACL_ENTRY_INFO; + break; + case 'h': + usage(av[0]); + exit(0); + break; + case 'v': + debuglevel++; + break; + default: + break; + } + } + ac -= optind; + av += optind; + if (ac >= 1) + { + infile = av[0]; /* XXX/gh need to validate av[0]? */ + if ((fd = open(infile, O_RDONLY, 0)) < 0) + { + fprintf(stderr, "Couldn't open %s (%s)\n", infile, strerror(errno)); + return 2; + } + if ((ret = readPreamble(fd, &doflip, &version, &type)) != OK) + return ret; + } + else + { + fd = -1; /* use a hard-coded test */ + if (!type) + { + type = SecuritydDataSave::CONTEXT; /* the only test that has hard-coded data...*/ + fprintf(stderr, "*** running hard-coded CSSM_CONTEXT test\n"); + } + } + switch (type) + { + case SecuritydDataSave::CONTEXT: + ret = test_CSSM_CONTEXT(fd, doflip, debuglevel); + break; + case SecuritydDataSave::ACL_OWNER_PROTOTYPE: + ret = test_CSSM_ACL_OWNER_PROTOTYPE(fd, doflip, debuglevel); + break; + case SecuritydDataSave::ACL_ENTRY_INPUT: + ret = test_CSSM_ACL_ENTRY_INPUT(fd, doflip, debuglevel); + break; + case SecuritydDataSave::ACL_ENTRY_INFO: + ret = test_CSSM_ACL_ENTRY_INFO(fd, doflip, debuglevel); + break; + case SecuritydDataSave::QUERY: + ret = test_CSSM_QUERY(fd, doflip, debuglevel); + break; + default: + fprintf(stderr, "Unrecognized test\n"); + ret = NOT_IMPLEMENTED; + } + return ret; +} diff --git a/SecurityTool/APPLE_LICENSE b/SecurityTool/APPLE_LICENSE new file mode 100644 index 00000000..71fe6fd7 --- /dev/null +++ b/SecurityTool/APPLE_LICENSE @@ -0,0 +1,335 @@ +APPLE PUBLIC SOURCE LICENSE +Version 2.0 - August 6, 2003 + +Please read this License carefully before downloading this software. By +downloading or using this software, you are agreeing to be bound by the terms +of this License. If you do not or cannot agree to the terms of this License, +please do not download or use the software. + +Apple Note: In January 2007, Apple changed its corporate name from "Apple +Computer, Inc." to "Apple Inc." This change has been reflected below and +copyright years updated, but no other changes have been made to the APSL 2.0. + +1. General; Definitions. This License applies to any program or other +work which Apple Inc. ("Apple") makes publicly available and which contains a +notice placed by Apple identifying such program or work as "Original Code" and +stating that it is subject to the terms of this Apple Public Source License +version 2.0 ("License"). As used in this License: + +1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is the +grantor of rights, (i) claims of patents that are now or hereafter acquired, +owned by or assigned to Apple and (ii) that cover subject matter contained in +the Original Code, but only to the extent necessary to use, reproduce and/or +distribute the Original Code without infringement; and (b) in the case where +You are the grantor of rights, (i) claims of patents that are now or hereafter +acquired, owned by or assigned to You and (ii) that cover subject matter in +Your Modifications, taken alone or in combination with Original Code. + +1.2 "Contributor" means any person or entity that creates or contributes to +the creation of Modifications. + +1.3 "Covered Code" means the Original Code, Modifications, the combination +of Original Code and any Modifications, and/or any respective portions thereof. + +1.4 "Externally Deploy" means: (a) to sublicense, distribute or otherwise +make Covered Code available, directly or indirectly, to anyone other than You; +and/or (b) to use Covered Code, alone or as part of a Larger Work, in any way +to provide a service, including but not limited to delivery of content, through +electronic communication with a client other than You. + +1.5 "Larger Work" means a work which combines Covered Code or portions +thereof with code not governed by the terms of this License. + +1.6 "Modifications" mean any addition to, deletion from, and/or change to, +the substance and/or structure of the Original Code, any previous +Modifications, the combination of Original Code and any previous Modifications, +and/or any respective portions thereof. When code is released as a series of +files, a Modification is: (a) any addition to or deletion from the contents of +a file containing Covered Code; and/or (b) any new file or other representation +of computer program statements that contains any part of Covered Code. + +1.7 "Original Code" means (a) the Source Code of a program or other work as +originally made available by Apple under this License, including the Source +Code of any updates or upgrades to such programs or works made available by +Apple under this License, and that has been expressly identified by Apple as +such in the header file(s) of such work; and (b) the object code compiled from +such Source Code and originally made available by Apple under this License + +1.8 "Source Code" means the human readable form of a program or other work +that is suitable for making modifications to it, including all modules it +contains, plus any associated interface definition files, scripts used to +control compilation and installation of an executable (object code). + +1.9 "You" or "Your" means an individual or a legal entity exercising rights +under this License. For legal entities, "You" or "Your" includes any entity +which controls, is controlled by, or is under common control with, You, where +"control" means (a) the power, direct or indirect, to cause the direction or +management of such entity, whether by contract or otherwise, or (b) ownership +of fifty percent (50%) or more of the outstanding shares or beneficial +ownership of such entity. + +2. Permitted Uses; Conditions & Restrictions. Subject to the terms and +conditions of this License, Apple hereby grants You, effective on the date You +accept this License and download the Original Code, a world-wide, royalty-free, +non-exclusive license, to the extent of Apple's Applicable Patent Rights and +copyrights covering the Original Code, to do the following: + +2.1 Unmodified Code. You may use, reproduce, display, perform, internally +distribute within Your organization, and Externally Deploy verbatim, unmodified +copies of the Original Code, for commercial or non-commercial purposes, +provided that in each instance: + +(a) You must retain and reproduce in all copies of Original Code the +copyright and other proprietary notices and disclaimers of Apple as they appear +in the Original Code, and keep intact all notices in the Original Code that +refer to this License; and + +(b) You must include a copy of this License with every copy of Source Code +of Covered Code and documentation You distribute or Externally Deploy, and You +may not offer or impose any terms on such Source Code that alter or restrict +this License or the recipients' rights hereunder, except as permitted under +Section 6. + +2.2 Modified Code. You may modify Covered Code and use, reproduce, +display, perform, internally distribute within Your organization, and +Externally Deploy Your Modifications and Covered Code, for commercial or +non-commercial purposes, provided that in each instance You also meet all of +these conditions: + +(a) You must satisfy all the conditions of Section 2.1 with respect to the +Source Code of the Covered Code; + +(b) You must duplicate, to the extent it does not already exist, the notice +in Exhibit A in each file of the Source Code of all Your Modifications, and +cause the modified files to carry prominent notices stating that You changed +the files and the date of any change; and + +(c) If You Externally Deploy Your Modifications, You must make Source Code +of all Your Externally Deployed Modifications either available to those to whom +You have Externally Deployed Your Modifications, or publicly available. Source +Code of Your Externally Deployed Modifications must be released under the terms +set forth in this License, including the license grants set forth in Section 3 +below, for as long as you Externally Deploy the Covered Code or twelve (12) +months from the date of initial External Deployment, whichever is longer. You +should preferably distribute the Source Code of Your Externally Deployed +Modifications electronically (e.g. download from a web site). + +2.3 Distribution of Executable Versions. In addition, if You Externally +Deploy Covered Code (Original Code and/or Modifications) in object code, +executable form only, You must include a prominent notice, in the code itself +as well as in related documentation, stating that Source Code of the Covered +Code is available under the terms of this License with information on how and +where to obtain such Source Code. + +2.4 Third Party Rights. You expressly acknowledge and agree that although +Apple and each Contributor grants the licenses to their respective portions of +the Covered Code set forth herein, no assurances are provided by Apple or any +Contributor that the Covered Code does not infringe the patent or other +intellectual property rights of any other entity. Apple and each Contributor +disclaim any liability to You for claims brought by any other entity based on +infringement of intellectual property rights or otherwise. As a condition to +exercising the rights and licenses granted hereunder, You hereby assume sole +responsibility to secure any other intellectual property rights needed, if any. +For example, if a third party patent license is required to allow You to +distribute the Covered Code, it is Your responsibility to acquire that license +before distributing the Covered Code. + +3. Your Grants. In consideration of, and as a condition to, the licenses +granted to You under this License, You hereby grant to any person or entity +receiving or distributing Covered Code under this License a non-exclusive, +royalty-free, perpetual, irrevocable license, under Your Applicable Patent +Rights and other intellectual property rights (other than patent) owned or +controlled by You, to use, reproduce, display, perform, modify, sublicense, +distribute and Externally Deploy Your Modifications of the same scope and +extent as Apple's licenses under Sections 2.1 and 2.2 above. + +4. Larger Works. You may create a Larger Work by combining Covered Code +with other code not governed by the terms of this License and distribute the +Larger Work as a single product. In each such instance, You must make sure the +requirements of this License are fulfilled for the Covered Code or any portion +thereof. + +5. Limitations on Patent License. Except as expressly stated in Section +2, no other patent rights, express or implied, are granted by Apple herein. +Modifications and/or Larger Works may require additional patent licenses from +Apple which Apple may grant in its sole discretion. + +6. Additional Terms. You may choose to offer, and to charge a fee for, +warranty, support, indemnity or liability obligations and/or other rights +consistent with the scope of the license granted herein ("Additional Terms") to +one or more recipients of Covered Code. However, You may do so only on Your own +behalf and as Your sole responsibility, and not on behalf of Apple or any +Contributor. You must obtain the recipient's agreement that any such Additional +Terms are offered by You alone, and You hereby agree to indemnify, defend and +hold Apple and every Contributor harmless for any liability incurred by or +claims asserted against Apple or such Contributor by reason of any such +Additional Terms. + +7. Versions of the License. Apple may publish revised and/or new versions +of this License from time to time. Each version will be given a distinguishing +version number. Once Original Code has been published under a particular +version of this License, You may continue to use it under the terms of that +version. You may also choose to use such Original Code under the terms of any +subsequent version of this License published by Apple. No one other than Apple +has the right to modify the terms applicable to Covered Code created under this +License. + +8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in +part pre-release, untested, or not fully tested works. The Covered Code may +contain errors that could cause failures or loss of data, and may be incomplete +or contain inaccuracies. You expressly acknowledge and agree that use of the +Covered Code, or any portion thereof, is at Your sole and entire risk. THE +COVERED CODE IS PROVIDED "AS IS" AND WITHOUT WARRANTY, UPGRADES OR SUPPORT OF +ANY KIND AND APPLE AND APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" +FOR THE PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM +ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF MERCHANTABILITY, OF +SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY, OF +QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. APPLE AND EACH +CONTRIBUTOR DOES NOT WARRANT AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE +COVERED CODE, THAT THE FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR +REQUIREMENTS, THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR +ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO ORAL OR +WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE AUTHORIZED +REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. You acknowledge +that the Covered Code is not intended for use in the operation of nuclear +facilities, aircraft navigation, communication systems, or air traffic control +machines in which case the failure of the Covered Code could lead to death, +personal injury, or severe physical or environmental damage. + +9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO +EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO THIS LICENSE OR +YOUR USE OR INABILITY TO USE THE COVERED CODE, OR ANY PORTION THEREOF, WHETHER +UNDER A THEORY OF CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE), PRODUCTS +LIABILITY OR OTHERWISE, EVEN IF APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF +THE POSSIBILITY OF SUCH DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL +PURPOSE OF ANY REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF +LIABILITY OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT +APPLY TO YOU. In no event shall Apple's total liability to You for all damages +(other than as may be required by applicable law) under this License exceed the +amount of fifty dollars ($50.00). + +10. Trademarks. This License does not grant any rights to use the +trademarks or trade names "Apple", "Mac", "Mac OS", "QuickTime", "QuickTime +Streaming Server" or any other trademarks, service marks, logos or trade names +belonging to Apple (collectively "Apple Marks") or to any trademark, service +mark, logo or trade name belonging to any Contributor. You agree not to use +any Apple Marks in or as part of the name of products derived from the Original +Code or to endorse or promote products derived from the Original Code other +than as expressly permitted by and in strict compliance at all times with +Apple's third party trademark usage guidelines which are posted at +http://www.apple.com/legal/guidelinesfor3rdparties.html. + +11. Ownership. Subject to the licenses granted under this License, each +Contributor retains all rights, title and interest in and to any Modifications +made by such Contributor. Apple retains all rights, title and interest in and +to the Original Code and any Modifications made by or on behalf of Apple +("Apple Modifications"), and such Apple Modifications will not be automatically +subject to this License. Apple may, at its sole discretion, choose to license +such Apple Modifications under this License, or on different terms from those +contained in this License or may choose not to license them at all. + +12. Termination. + +12.1 Termination. This License and the rights granted hereunder will +terminate: + +(a) automatically without notice from Apple if You fail to comply with any +term(s) of this License and fail to cure such breach within 30 days of becoming +aware of such breach; +(b) immediately in the event of the circumstances described in Section +13.5(b); or +(c) automatically without notice from Apple if You, at any time during the +term of this License, commence an action for patent infringement against Apple; +provided that Apple did not first commence an action for patent infringement +against You in that instance. + +12.2 Effect of Termination. Upon termination, You agree to immediately stop +any further use, reproduction, modification, sublicensing and distribution of +the Covered Code. All sublicenses to the Covered Code which have been properly +granted prior to termination shall survive any termination of this License. +Provisions which, by their nature, should remain in effect beyond the +termination of this License shall survive, including but not limited to +Sections 3, 5, 8, 9, 10, 11, 12.2 and 13. No party will be liable to any other +for compensation, indemnity or damages of any sort solely as a result of +terminating this License in accordance with its terms, and termination of this +License will be without prejudice to any other right or remedy of any party. + +13. Miscellaneous. + +13.1 Government End Users. The Covered Code is a "commercial item" as +defined in FAR 2.101. Government software and technical data rights in the +Covered Code include only those rights customarily provided to the public as +defined in this License. This customary commercial license in technical data +and software is provided in accordance with FAR 12.211 (Technical Data) and +12.212 (Computer Software) and, for Department of Defense purchases, DFAR +252.227-7015 (Technical Data -- Commercial Items) and 227.7202-3 (Rights in +Commercial Computer Software or Computer Software Documentation). Accordingly, +all U.S. Government End Users acquire Covered Code with only those rights set +forth herein. + +13.2 Relationship of Parties. This License will not be construed as +creating an agency, partnership, joint venture or any other form of legal +association between or among You, Apple or any Contributor, and You will not +represent to the contrary, whether expressly, by implication, appearance or +otherwise. + +13.3 Independent Development. Nothing in this License will impair Apple's +right to acquire, license, develop, have others develop for it, market and/or +distribute technology or products that perform the same or similar functions +as, or otherwise compete with, Modifications, Larger Works, technology or +products that You may develop, produce, market or distribute. + +13.4 Waiver; Construction. Failure by Apple or any Contributor to enforce +any provision of this License will not be deemed a waiver of future enforcement +of that or any other provision. Any law or regulation which provides that the +language of a contract shall be construed against the drafter will not apply to +this License. + +13.5 Severability. (a) If for any reason a court of competent jurisdiction +finds any provision of this License, or portion thereof, to be unenforceable, +that provision of the License will be enforced to the maximum extent +permissible so as to effect the economic benefits and intent of the parties, +and the remainder of this License will continue in full force and effect. (b) +Notwithstanding the foregoing, if applicable law prohibits or restricts You +from fully and/or specifically complying with Sections 2 and/or 3 or prevents +the enforceability of either of those Sections, this License will immediately +terminate and You must immediately discontinue any use of the Covered Code and +destroy all copies of it that are in your possession or control. + +13.6 Dispute Resolution. Any litigation or other dispute resolution between +You and Apple relating to this License shall take place in the Northern +District of California, and You and Apple hereby consent to the personal +jurisdiction of, and venue in, the state and federal courts within that +District with respect to this License. The application of the United Nations +Convention on Contracts for the International Sale of Goods is expressly +excluded. + +13.7 Entire Agreement; Governing Law. This License constitutes the entire +agreement between the parties with respect to the subject matter hereof. This +License shall be governed by the laws of the United States and the State of +California, except that body of California law concerning conflicts of law. + +Where You are located in the province of Quebec, Canada, the following clause +applies: The parties hereby confirm that they have requested that this License +and all related documents be drafted in English. Les parties ont exigé que le +présent contrat et tous les documents connexes soient rédigés en anglais. + +EXHIBIT A. + +"Portions Copyright (c) 1999-2007 Apple Inc. All Rights Reserved. + +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." + diff --git a/SecurityTool/SecurityTool.xcodeproj/project.pbxproj b/SecurityTool/SecurityTool.xcodeproj/project.pbxproj new file mode 100644 index 00000000..544cdf0b --- /dev/null +++ b/SecurityTool/SecurityTool.xcodeproj/project.pbxproj @@ -0,0 +1,513 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXBuildFile section */ + 1865FCA814725B4D00FD79DF /* libsecurity_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1865FCA714725B4C00FD79DF /* libsecurity_utilities.a */; }; + 1865FCAA14725B6F00FD79DF /* libsecurity_cdsa_utils.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1865FCA914725B6F00FD79DF /* libsecurity_cdsa_utils.a */; }; + 1865FCAF14725BC600FD79DF /* libsecurity_cdsa_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1865FCAB14725B8B00FD79DF /* libsecurity_cdsa_client.a */; }; + 1865FCB014725BD100FD79DF /* libsecurity_cdsa_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1865FCAD14725BBA00FD79DF /* libsecurity_cdsa_utilities.a */; }; + 18A25BEE14752A48004F59F8 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C67F36D0468956400CA2E66 /* Security.framework */; }; + 18A25BEF14752A50004F59F8 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C67F36F0468957300CA2E66 /* CoreFoundation.framework */; }; + 18B6B2A614DB72BC00EDDE5F /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18B6B2A514DB72BC00EDDE5F /* libASN1.a */; }; + 5287946E13CCCC32007AFF54 /* createFVMaster.c in Sources */ = {isa = PBXBuildFile; fileRef = 5287946C13CCCC32007AFF54 /* createFVMaster.c */; }; + 5287946F13CCCC32007AFF54 /* createFVMaster.h in Headers */ = {isa = PBXBuildFile; fileRef = 5287946D13CCCC32007AFF54 /* createFVMaster.h */; }; + 5287947713CCD56A007AFF54 /* srCdsaUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5287947513CCD56A007AFF54 /* srCdsaUtils.cpp */; }; + 5287947813CCD56A007AFF54 /* srCdsaUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 5287947613CCD56A007AFF54 /* srCdsaUtils.h */; }; + AACD2C7D0E12D81D00D485EA /* db_commands.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CFE73F3048809CA00CA2E66 /* db_commands.h */; }; + AACD2C7E0E12D81D00D485EA /* key_create.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C2597F4047EFB4900CA2E66 /* key_create.h */; }; + AACD2C7F0E12D81D00D485EA /* keychain_add.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C583DC0484475600933075 /* keychain_add.h */; }; + AACD2C800E12D81D00D485EA /* keychain_create.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C67F35D046885F400CA2E66 /* keychain_create.h */; }; + AACD2C810E12D81D00D485EA /* keychain_delete.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C67F3610468866E00CA2E66 /* keychain_delete.h */; }; + AACD2C820E12D81D00D485EA /* keychain_export.h in Headers */ = {isa = PBXBuildFile; fileRef = 051E64E9060F7A5F00FB8A46 /* keychain_export.h */; }; + AACD2C830E12D81D00D485EA /* keychain_find.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A749330488FE6D0042026C /* keychain_find.h */; }; + AACD2C840E12D81D00D485EA /* keychain_import.h in Headers */ = {isa = PBXBuildFile; fileRef = 051E6450060F668F00FB8A46 /* keychain_import.h */; }; + AACD2C850E12D81D00D485EA /* keychain_list.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CAF1F4A046C88D300CA2E66 /* keychain_list.h */; }; + AACD2C860E12D81D00D485EA /* keychain_lock.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C76BE704704CED00E9A8A8 /* keychain_lock.h */; }; + AACD2C870E12D81D00D485EA /* keychain_set_settings.h in Headers */ = {isa = PBXBuildFile; fileRef = 83CCF86704732AA300C6B016 /* keychain_set_settings.h */; }; + AACD2C880E12D81D00D485EA /* keychain_show_info.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C737568047AE5AD00CA2E66 /* keychain_show_info.h */; }; + AACD2C890E12D81D00D485EA /* keychain_unlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 831FF8BD046F4CCE00CC0098 /* keychain_unlock.h */; }; + AACD2C8A0E12D81D00D485EA /* keychain_utilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7A49B70469F0CB00CA2E66 /* keychain_utilities.h */; }; + AACD2C8B0E12D81D00D485EA /* leaks.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CAEBD830469D90400CA2E66 /* leaks.h */; }; + AACD2C8C0E12D81D00D485EA /* readline.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C67F3690468892B00CA2E66 /* readline.h */; }; + AACD2C8D0E12D81D00D485EA /* security.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C67F3560468831300CA2E66 /* security.h */; }; + AACD2C8E0E12D81D00D485EA /* cmsutil.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CA9BF2C0637403D0013F16F /* cmsutil.h */; }; + AACD2C8F0E12D81D00D485EA /* mds_install.h in Headers */ = {isa = PBXBuildFile; fileRef = 0599C5F006F77CED00C2A9E0 /* mds_install.h */; }; + AACD2C900E12D81D00D485EA /* keychain_recode.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CEFD16E07BD8E10002A0D93 /* keychain_recode.h */; }; + AACD2C910E12D81D00D485EA /* trusted_cert_dump.h in Headers */ = {isa = PBXBuildFile; fileRef = 058C7A8409F6AC1C00DB7E98 /* trusted_cert_dump.h */; }; + AACD2C920E12D81D00D485EA /* trusted_cert_add.h in Headers */ = {isa = PBXBuildFile; fileRef = 058C7A8809F6AC2D00DB7E98 /* trusted_cert_add.h */; }; + AACD2C930E12D81D00D485EA /* trusted_cert_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 058C7A8A09F6AC2D00DB7E98 /* trusted_cert_utils.h */; }; + AACD2C940E12D81D00D485EA /* user_trust_enable.h in Headers */ = {isa = PBXBuildFile; fileRef = 057E14A00A1508B600886CB8 /* user_trust_enable.h */; }; + AACD2C950E12D81D00D485EA /* trust_settings_impexp.h in Headers */ = {isa = PBXBuildFile; fileRef = 05DD14A40A1A498300C46534 /* trust_settings_impexp.h */; }; + AACD2C960E12D81D00D485EA /* authz.h in Headers */ = {isa = PBXBuildFile; fileRef = 40F1827A0A4C625B00A6E783 /* authz.h */; }; + AACD2C970E12D81D00D485EA /* verify_cert.h in Headers */ = {isa = PBXBuildFile; fileRef = 056A9CEC0AD57D7C00847C65 /* verify_cert.h */; }; + AACD2C980E12D81D00D485EA /* display_error_code.h in Headers */ = {isa = PBXBuildFile; fileRef = 524654BC0D57D0F10045335E /* display_error_code.h */; }; + AACD2C9A0E12D81D00D485EA /* cmsutil.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CA9BF2606373C200013F16F /* cmsutil.c */; }; + AACD2C9B0E12D81D00D485EA /* db_commands.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFE73F4048809CA00CA2E66 /* db_commands.cpp */; }; + AACD2C9C0E12D81D00D485EA /* key_create.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2597F5047EFB4900CA2E66 /* key_create.c */; }; + AACD2C9D0E12D81D00D485EA /* keychain_add.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C583DD0484475600933075 /* keychain_add.c */; }; + AACD2C9E0E12D81D00D485EA /* keychain_create.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C67F35E046885F400CA2E66 /* keychain_create.c */; }; + AACD2C9F0E12D81D00D485EA /* keychain_delete.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C67F3620468866E00CA2E66 /* keychain_delete.c */; }; + AACD2CA00E12D81D00D485EA /* keychain_export.c in Sources */ = {isa = PBXBuildFile; fileRef = 051E64E8060F7A5F00FB8A46 /* keychain_export.c */; }; + AACD2CA10E12D81D00D485EA /* keychain_find.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A749340488FE6D0042026C /* keychain_find.c */; }; + AACD2CA20E12D81D00D485EA /* keychain_import.c in Sources */ = {isa = PBXBuildFile; fileRef = 051E6439060F607800FB8A46 /* keychain_import.c */; }; + AACD2CA30E12D81D00D485EA /* keychain_list.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAF1F4B046C88D300CA2E66 /* keychain_list.c */; }; + AACD2CA40E12D81D00D485EA /* keychain_lock.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C76BE804704CEE00E9A8A8 /* keychain_lock.c */; }; + AACD2CA50E12D81D00D485EA /* keychain_set_settings.c in Sources */ = {isa = PBXBuildFile; fileRef = 83CCF86804732AA300C6B016 /* keychain_set_settings.c */; }; + AACD2CA60E12D81D00D485EA /* keychain_show_info.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C737567047AE5AD00CA2E66 /* keychain_show_info.c */; }; + AACD2CA70E12D81D00D485EA /* keychain_unlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 831FF8BF046F4CE000CC0098 /* keychain_unlock.c */; }; + AACD2CA80E12D81D00D485EA /* keychain_utilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C7A49B80469F0CB00CA2E66 /* keychain_utilities.c */; }; + AACD2CA90E12D81D00D485EA /* leaks.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAEBD840469D90400CA2E66 /* leaks.c */; }; + AACD2CAA0E12D81D00D485EA /* readline.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C67F36A0468892B00CA2E66 /* readline.c */; }; + AACD2CAB0E12D81D00D485EA /* security.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C67F3550468831300CA2E66 /* security.c */; }; + AACD2CAC0E12D81D00D485EA /* mds_install.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0599C5EE06F77CE300C2A9E0 /* mds_install.cpp */; }; + AACD2CAD0E12D81D00D485EA /* keychain_recode.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CEFD16D07BD8E10002A0D93 /* keychain_recode.c */; }; + AACD2CAE0E12D81D00D485EA /* trusted_cert_dump.c in Sources */ = {isa = PBXBuildFile; fileRef = 058C7A8309F6AC1C00DB7E98 /* trusted_cert_dump.c */; }; + AACD2CAF0E12D81D00D485EA /* trusted_cert_add.c in Sources */ = {isa = PBXBuildFile; fileRef = 058C7A8709F6AC2D00DB7E98 /* trusted_cert_add.c */; }; + AACD2CB00E12D81D00D485EA /* trusted_cert_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 058C7A8909F6AC2D00DB7E98 /* trusted_cert_utils.c */; }; + AACD2CB10E12D81D00D485EA /* user_trust_enable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 057E14A10A1508B600886CB8 /* user_trust_enable.cpp */; }; + AACD2CB20E12D81D00D485EA /* trust_settings_impexp.c in Sources */ = {isa = PBXBuildFile; fileRef = 05DD14A50A1A498300C46534 /* trust_settings_impexp.c */; }; + AACD2CB30E12D81D00D485EA /* authz.c in Sources */ = {isa = PBXBuildFile; fileRef = 40F182790A4C625B00A6E783 /* authz.c */; }; + AACD2CB40E12D81D00D485EA /* verify_cert.c in Sources */ = {isa = PBXBuildFile; fileRef = 056A9CEB0AD57D7C00847C65 /* verify_cert.c */; }; + AACD2CB50E12D81D00D485EA /* display_error_code.c in Sources */ = {isa = PBXBuildFile; fileRef = 524654BB0D57D0F10045335E /* display_error_code.c */; }; + AACD2CB80E12D81D00D485EA /* security.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6A0FF2C0290799A04C91782 /* security.1 */; }; + BE2D8DFA0F2D3A7C0047A0F9 /* identity_find.h in Headers */ = {isa = PBXBuildFile; fileRef = BE2D8DF80F2D3A7C0047A0F9 /* identity_find.h */; }; + BE2D8DFB0F2D3A7C0047A0F9 /* identity_find.c in Sources */ = {isa = PBXBuildFile; fileRef = BE2D8DF90F2D3A7C0047A0F9 /* identity_find.c */; }; + BE851CE60E270695008295B3 /* access_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = BE851CE40E270695008295B3 /* access_utils.c */; }; + BE851CE70E270695008295B3 /* access_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = BE851CE50E270695008295B3 /* access_utils.h */; }; + BE926A540F253EBB00371998 /* identity_prefs.h in Headers */ = {isa = PBXBuildFile; fileRef = BE926A520F253EBB00371998 /* identity_prefs.h */; }; + BE926A550F253EBB00371998 /* identity_prefs.c in Sources */ = {isa = PBXBuildFile; fileRef = BE926A530F253EBB00371998 /* identity_prefs.c */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + AACD2CB70E12D81D00D485EA /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + AACD2CB80E12D81D00D485EA /* security.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 051E6439060F607800FB8A46 /* keychain_import.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keychain_import.c; sourceTree = ""; }; + 051E6450060F668F00FB8A46 /* keychain_import.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = keychain_import.h; sourceTree = ""; }; + 051E64E8060F7A5F00FB8A46 /* keychain_export.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = keychain_export.c; sourceTree = ""; }; + 051E64E9060F7A5F00FB8A46 /* keychain_export.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = keychain_export.h; sourceTree = ""; }; + 056A9CEB0AD57D7C00847C65 /* verify_cert.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = verify_cert.c; sourceTree = ""; }; + 056A9CEC0AD57D7C00847C65 /* verify_cert.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = verify_cert.h; sourceTree = ""; }; + 057E14A00A1508B600886CB8 /* user_trust_enable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = user_trust_enable.h; sourceTree = ""; }; + 057E14A10A1508B600886CB8 /* user_trust_enable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = user_trust_enable.cpp; sourceTree = ""; }; + 058C7A8309F6AC1C00DB7E98 /* trusted_cert_dump.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = trusted_cert_dump.c; sourceTree = ""; }; + 058C7A8409F6AC1C00DB7E98 /* trusted_cert_dump.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = trusted_cert_dump.h; sourceTree = ""; }; + 058C7A8709F6AC2D00DB7E98 /* trusted_cert_add.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = trusted_cert_add.c; sourceTree = ""; }; + 058C7A8809F6AC2D00DB7E98 /* trusted_cert_add.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = trusted_cert_add.h; sourceTree = ""; }; + 058C7A8909F6AC2D00DB7E98 /* trusted_cert_utils.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = trusted_cert_utils.c; sourceTree = ""; }; + 058C7A8A09F6AC2D00DB7E98 /* trusted_cert_utils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = trusted_cert_utils.h; sourceTree = ""; }; + 0599C5EE06F77CE300C2A9E0 /* mds_install.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mds_install.cpp; sourceTree = ""; }; + 0599C5F006F77CED00C2A9E0 /* mds_install.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mds_install.h; sourceTree = ""; }; + 05DD14A40A1A498300C46534 /* trust_settings_impexp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = trust_settings_impexp.h; sourceTree = ""; }; + 05DD14A50A1A498300C46534 /* trust_settings_impexp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = trust_settings_impexp.c; sourceTree = ""; }; + 1865FCA714725B4C00FD79DF /* libsecurity_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_utilities.a; path = /usr/local/lib/libsecurity_utilities.a; sourceTree = ""; }; + 1865FCA914725B6F00FD79DF /* libsecurity_cdsa_utils.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_cdsa_utils.a; path = /usr/local/lib/libsecurity_cdsa_utils.a; sourceTree = ""; }; + 1865FCAB14725B8B00FD79DF /* libsecurity_cdsa_client.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_cdsa_client.a; path = /usr/local/lib/libsecurity_cdsa_client.a; sourceTree = ""; }; + 1865FCAD14725BBA00FD79DF /* libsecurity_cdsa_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_cdsa_utilities.a; path = /usr/local/lib/libsecurity_cdsa_utilities.a; sourceTree = ""; }; + 18A25BEA14752959004F59F8 /* debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 18A25BEB14752959004F59F8 /* project.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = project.xcconfig; sourceTree = ""; }; + 18A25BEC14752959004F59F8 /* release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 18B6B2A514DB72BC00EDDE5F /* libASN1.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libASN1.a; path = /usr/local/lib/libASN1.a; sourceTree = ""; }; + 40F182790A4C625B00A6E783 /* authz.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = authz.c; sourceTree = ""; }; + 40F1827A0A4C625B00A6E783 /* authz.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = authz.h; sourceTree = ""; }; + 4C2597F4047EFB4900CA2E66 /* key_create.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = key_create.h; sourceTree = ""; }; + 4C2597F5047EFB4900CA2E66 /* key_create.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = key_create.c; sourceTree = ""; }; + 4C67F3550468831300CA2E66 /* security.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = security.c; sourceTree = ""; }; + 4C67F3560468831300CA2E66 /* security.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = security.h; sourceTree = ""; }; + 4C67F35D046885F400CA2E66 /* keychain_create.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keychain_create.h; sourceTree = ""; }; + 4C67F35E046885F400CA2E66 /* keychain_create.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keychain_create.c; sourceTree = ""; }; + 4C67F3610468866E00CA2E66 /* keychain_delete.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keychain_delete.h; sourceTree = ""; }; + 4C67F3620468866E00CA2E66 /* keychain_delete.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keychain_delete.c; sourceTree = ""; }; + 4C67F3690468892B00CA2E66 /* readline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = readline.h; sourceTree = ""; }; + 4C67F36A0468892B00CA2E66 /* readline.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readline.c; sourceTree = ""; }; + 4C67F36D0468956400CA2E66 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = ""; }; + 4C67F36F0468957300CA2E66 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; + 4C737567047AE5AD00CA2E66 /* keychain_show_info.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = keychain_show_info.c; sourceTree = ""; }; + 4C737568047AE5AD00CA2E66 /* keychain_show_info.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = keychain_show_info.h; sourceTree = ""; }; + 4C7A49B70469F0CB00CA2E66 /* keychain_utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keychain_utilities.h; sourceTree = ""; }; + 4C7A49B80469F0CB00CA2E66 /* keychain_utilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keychain_utilities.c; sourceTree = ""; }; + 4CA9BF2606373C200013F16F /* cmsutil.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmsutil.c; sourceTree = ""; }; + 4CA9BF2C0637403D0013F16F /* cmsutil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cmsutil.h; sourceTree = ""; }; + 4CAEBD830469D90400CA2E66 /* leaks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = leaks.h; sourceTree = ""; }; + 4CAEBD840469D90400CA2E66 /* leaks.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = leaks.c; sourceTree = ""; }; + 4CAF1F4A046C88D300CA2E66 /* keychain_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keychain_list.h; sourceTree = ""; }; + 4CAF1F4B046C88D300CA2E66 /* keychain_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keychain_list.c; sourceTree = ""; }; + 4CEFD16D07BD8E10002A0D93 /* keychain_recode.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = keychain_recode.c; sourceTree = ""; }; + 4CEFD16E07BD8E10002A0D93 /* keychain_recode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = keychain_recode.h; sourceTree = ""; }; + 4CFE73F3048809CA00CA2E66 /* db_commands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = db_commands.h; sourceTree = ""; }; + 4CFE73F4048809CA00CA2E66 /* db_commands.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = db_commands.cpp; sourceTree = ""; }; + 524654BB0D57D0F10045335E /* display_error_code.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = display_error_code.c; sourceTree = ""; }; + 524654BC0D57D0F10045335E /* display_error_code.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = display_error_code.h; sourceTree = ""; }; + 5287946C13CCCC32007AFF54 /* createFVMaster.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = createFVMaster.c; sourceTree = ""; }; + 5287946D13CCCC32007AFF54 /* createFVMaster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = createFVMaster.h; sourceTree = ""; }; + 5287947513CCD56A007AFF54 /* srCdsaUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = srCdsaUtils.cpp; sourceTree = ""; }; + 5287947613CCD56A007AFF54 /* srCdsaUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = srCdsaUtils.h; sourceTree = ""; }; + 831FF8BD046F4CCE00CC0098 /* keychain_unlock.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = keychain_unlock.h; sourceTree = ""; }; + 831FF8BF046F4CE000CC0098 /* keychain_unlock.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = keychain_unlock.c; sourceTree = ""; }; + 83A749330488FE6D0042026C /* keychain_find.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keychain_find.h; sourceTree = ""; }; + 83A749340488FE6D0042026C /* keychain_find.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keychain_find.c; sourceTree = ""; }; + 83C583DC0484475600933075 /* keychain_add.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keychain_add.h; sourceTree = ""; }; + 83C583DD0484475600933075 /* keychain_add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keychain_add.c; sourceTree = ""; }; + 83C76BE704704CED00E9A8A8 /* keychain_lock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keychain_lock.h; sourceTree = ""; }; + 83C76BE804704CEE00E9A8A8 /* keychain_lock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keychain_lock.c; sourceTree = ""; }; + 83CCF86704732AA300C6B016 /* keychain_set_settings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keychain_set_settings.h; sourceTree = ""; }; + 83CCF86804732AA300C6B016 /* keychain_set_settings.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keychain_set_settings.c; sourceTree = ""; }; + AACD2CBE0E12D81D00D485EA /* security */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = security; sourceTree = BUILT_PRODUCTS_DIR; }; + BE2D8DF80F2D3A7C0047A0F9 /* identity_find.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = identity_find.h; sourceTree = ""; }; + BE2D8DF90F2D3A7C0047A0F9 /* identity_find.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = identity_find.c; sourceTree = ""; }; + BE851CE40E270695008295B3 /* access_utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = access_utils.c; sourceTree = ""; }; + BE851CE50E270695008295B3 /* access_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = access_utils.h; sourceTree = ""; }; + BE926A520F253EBB00371998 /* identity_prefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = identity_prefs.h; sourceTree = ""; }; + BE926A530F253EBB00371998 /* identity_prefs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = identity_prefs.c; sourceTree = ""; }; + C6A0FF2C0290799A04C91782 /* security.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = security.1; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + AACD2CB60E12D81D00D485EA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 18B6B2A614DB72BC00EDDE5F /* libASN1.a in Frameworks */, + 18A25BEF14752A50004F59F8 /* CoreFoundation.framework in Frameworks */, + 18A25BEE14752A48004F59F8 /* Security.framework in Frameworks */, + 1865FCAF14725BC600FD79DF /* libsecurity_cdsa_client.a in Frameworks */, + 1865FCB014725BD100FD79DF /* libsecurity_cdsa_utilities.a in Frameworks */, + 1865FCAA14725B6F00FD79DF /* libsecurity_cdsa_utils.a in Frameworks */, + 1865FCA814725B4D00FD79DF /* libsecurity_utilities.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* SecurityTool */ = { + isa = PBXGroup; + children = ( + 18A25BE914752959004F59F8 /* config */, + 08FB7795FE84155DC02AAC07 /* Source */, + C6A0FF2B0290797F04C91782 /* Documentation */, + 4C67F3710468957A00CA2E66 /* Frameworks */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + ); + name = SecurityTool; + sourceTree = ""; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + 5287947513CCD56A007AFF54 /* srCdsaUtils.cpp */, + 5287947613CCD56A007AFF54 /* srCdsaUtils.h */, + 5287946C13CCCC32007AFF54 /* createFVMaster.c */, + 5287946D13CCCC32007AFF54 /* createFVMaster.h */, + 0599C5F006F77CED00C2A9E0 /* mds_install.h */, + 0599C5EE06F77CE300C2A9E0 /* mds_install.cpp */, + 4CA9BF2606373C200013F16F /* cmsutil.c */, + 4CA9BF2C0637403D0013F16F /* cmsutil.h */, + 4CFE73F4048809CA00CA2E66 /* db_commands.cpp */, + 4CFE73F3048809CA00CA2E66 /* db_commands.h */, + 524654BB0D57D0F10045335E /* display_error_code.c */, + 524654BC0D57D0F10045335E /* display_error_code.h */, + 058C7A8309F6AC1C00DB7E98 /* trusted_cert_dump.c */, + 058C7A8409F6AC1C00DB7E98 /* trusted_cert_dump.h */, + BE2D8DF90F2D3A7C0047A0F9 /* identity_find.c */, + BE2D8DF80F2D3A7C0047A0F9 /* identity_find.h */, + BE926A530F253EBB00371998 /* identity_prefs.c */, + BE926A520F253EBB00371998 /* identity_prefs.h */, + 4C2597F5047EFB4900CA2E66 /* key_create.c */, + 4C2597F4047EFB4900CA2E66 /* key_create.h */, + 83C583DD0484475600933075 /* keychain_add.c */, + 83C583DC0484475600933075 /* keychain_add.h */, + 4C67F35E046885F400CA2E66 /* keychain_create.c */, + 4C67F35D046885F400CA2E66 /* keychain_create.h */, + 4C67F3620468866E00CA2E66 /* keychain_delete.c */, + 4C67F3610468866E00CA2E66 /* keychain_delete.h */, + 051E64E8060F7A5F00FB8A46 /* keychain_export.c */, + 051E64E9060F7A5F00FB8A46 /* keychain_export.h */, + 83A749340488FE6D0042026C /* keychain_find.c */, + 83A749330488FE6D0042026C /* keychain_find.h */, + 051E6439060F607800FB8A46 /* keychain_import.c */, + 051E6450060F668F00FB8A46 /* keychain_import.h */, + 4CAF1F4B046C88D300CA2E66 /* keychain_list.c */, + 4CAF1F4A046C88D300CA2E66 /* keychain_list.h */, + 83C76BE804704CEE00E9A8A8 /* keychain_lock.c */, + 83C76BE704704CED00E9A8A8 /* keychain_lock.h */, + 4CEFD16D07BD8E10002A0D93 /* keychain_recode.c */, + 4CEFD16E07BD8E10002A0D93 /* keychain_recode.h */, + 83CCF86804732AA300C6B016 /* keychain_set_settings.c */, + 83CCF86704732AA300C6B016 /* keychain_set_settings.h */, + 4C737567047AE5AD00CA2E66 /* keychain_show_info.c */, + 4C737568047AE5AD00CA2E66 /* keychain_show_info.h */, + 831FF8BF046F4CE000CC0098 /* keychain_unlock.c */, + 831FF8BD046F4CCE00CC0098 /* keychain_unlock.h */, + 4C7A49B80469F0CB00CA2E66 /* keychain_utilities.c */, + 4C7A49B70469F0CB00CA2E66 /* keychain_utilities.h */, + 4CAEBD840469D90400CA2E66 /* leaks.c */, + 4CAEBD830469D90400CA2E66 /* leaks.h */, + 4C67F36A0468892B00CA2E66 /* readline.c */, + 4C67F3690468892B00CA2E66 /* readline.h */, + 4C67F3550468831300CA2E66 /* security.c */, + 4C67F3560468831300CA2E66 /* security.h */, + 058C7A8709F6AC2D00DB7E98 /* trusted_cert_add.c */, + 058C7A8809F6AC2D00DB7E98 /* trusted_cert_add.h */, + 058C7A8909F6AC2D00DB7E98 /* trusted_cert_utils.c */, + 058C7A8A09F6AC2D00DB7E98 /* trusted_cert_utils.h */, + 05DD14A40A1A498300C46534 /* trust_settings_impexp.h */, + 05DD14A50A1A498300C46534 /* trust_settings_impexp.c */, + 057E14A00A1508B600886CB8 /* user_trust_enable.h */, + 057E14A10A1508B600886CB8 /* user_trust_enable.cpp */, + 40F1827A0A4C625B00A6E783 /* authz.h */, + 40F182790A4C625B00A6E783 /* authz.c */, + 056A9CEB0AD57D7C00847C65 /* verify_cert.c */, + 056A9CEC0AD57D7C00847C65 /* verify_cert.h */, + BE851CE40E270695008295B3 /* access_utils.c */, + BE851CE50E270695008295B3 /* access_utils.h */, + ); + name = Source; + sourceTree = ""; + }; + 18A25BE914752959004F59F8 /* config */ = { + isa = PBXGroup; + children = ( + 18A25BEA14752959004F59F8 /* debug.xcconfig */, + 18A25BEB14752959004F59F8 /* project.xcconfig */, + 18A25BEC14752959004F59F8 /* release.xcconfig */, + ); + path = config; + sourceTree = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + AACD2CBE0E12D81D00D485EA /* security */, + ); + name = Products; + sourceTree = ""; + }; + 4C67F3710468957A00CA2E66 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 18B6B2A514DB72BC00EDDE5F /* libASN1.a */, + 1865FCAD14725BBA00FD79DF /* libsecurity_cdsa_utilities.a */, + 1865FCAB14725B8B00FD79DF /* libsecurity_cdsa_client.a */, + 1865FCA914725B6F00FD79DF /* libsecurity_cdsa_utils.a */, + 1865FCA714725B4C00FD79DF /* libsecurity_utilities.a */, + 4C67F36F0468957300CA2E66 /* CoreFoundation.framework */, + 4C67F36D0468956400CA2E66 /* Security.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + C6A0FF2B0290797F04C91782 /* Documentation */ = { + isa = PBXGroup; + children = ( + C6A0FF2C0290799A04C91782 /* security.1 */, + ); + name = Documentation; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + AACD2C7C0E12D81D00D485EA /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + AACD2C7D0E12D81D00D485EA /* db_commands.h in Headers */, + AACD2C7E0E12D81D00D485EA /* key_create.h in Headers */, + AACD2C7F0E12D81D00D485EA /* keychain_add.h in Headers */, + AACD2C800E12D81D00D485EA /* keychain_create.h in Headers */, + AACD2C810E12D81D00D485EA /* keychain_delete.h in Headers */, + AACD2C820E12D81D00D485EA /* keychain_export.h in Headers */, + AACD2C830E12D81D00D485EA /* keychain_find.h in Headers */, + AACD2C840E12D81D00D485EA /* keychain_import.h in Headers */, + AACD2C850E12D81D00D485EA /* keychain_list.h in Headers */, + AACD2C860E12D81D00D485EA /* keychain_lock.h in Headers */, + AACD2C870E12D81D00D485EA /* keychain_set_settings.h in Headers */, + AACD2C880E12D81D00D485EA /* keychain_show_info.h in Headers */, + AACD2C890E12D81D00D485EA /* keychain_unlock.h in Headers */, + AACD2C8A0E12D81D00D485EA /* keychain_utilities.h in Headers */, + AACD2C8B0E12D81D00D485EA /* leaks.h in Headers */, + AACD2C8C0E12D81D00D485EA /* readline.h in Headers */, + AACD2C8D0E12D81D00D485EA /* security.h in Headers */, + AACD2C8E0E12D81D00D485EA /* cmsutil.h in Headers */, + AACD2C8F0E12D81D00D485EA /* mds_install.h in Headers */, + AACD2C900E12D81D00D485EA /* keychain_recode.h in Headers */, + AACD2C910E12D81D00D485EA /* trusted_cert_dump.h in Headers */, + AACD2C920E12D81D00D485EA /* trusted_cert_add.h in Headers */, + AACD2C930E12D81D00D485EA /* trusted_cert_utils.h in Headers */, + AACD2C940E12D81D00D485EA /* user_trust_enable.h in Headers */, + AACD2C950E12D81D00D485EA /* trust_settings_impexp.h in Headers */, + AACD2C960E12D81D00D485EA /* authz.h in Headers */, + AACD2C970E12D81D00D485EA /* verify_cert.h in Headers */, + AACD2C980E12D81D00D485EA /* display_error_code.h in Headers */, + BE851CE70E270695008295B3 /* access_utils.h in Headers */, + BE926A540F253EBB00371998 /* identity_prefs.h in Headers */, + BE2D8DFA0F2D3A7C0047A0F9 /* identity_find.h in Headers */, + 5287946F13CCCC32007AFF54 /* createFVMaster.h in Headers */, + 5287947813CCD56A007AFF54 /* srCdsaUtils.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + AACD2C7B0E12D81D00D485EA /* security */ = { + isa = PBXNativeTarget; + buildConfigurationList = AACD2CB90E12D81D00D485EA /* Build configuration list for PBXNativeTarget "security" */; + buildPhases = ( + AACD2C7C0E12D81D00D485EA /* Headers */, + AACD2C990E12D81D00D485EA /* Sources */, + AACD2CB60E12D81D00D485EA /* Frameworks */, + AACD2CB70E12D81D00D485EA /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = security; + productInstallPath = /usr/bin; + productName = SecurityTool; + productReference = AACD2CBE0E12D81D00D485EA /* security */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0410; + }; + buildConfigurationList = C27AD1BA0987FCDB001272E0 /* Build configuration list for PBXProject "SecurityTool" */; + compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 08FB7794FE84155DC02AAC07 /* SecurityTool */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + AACD2C7B0E12D81D00D485EA /* security */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + AACD2C990E12D81D00D485EA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AACD2C9A0E12D81D00D485EA /* cmsutil.c in Sources */, + AACD2C9B0E12D81D00D485EA /* db_commands.cpp in Sources */, + AACD2C9C0E12D81D00D485EA /* key_create.c in Sources */, + AACD2C9D0E12D81D00D485EA /* keychain_add.c in Sources */, + AACD2C9E0E12D81D00D485EA /* keychain_create.c in Sources */, + AACD2C9F0E12D81D00D485EA /* keychain_delete.c in Sources */, + AACD2CA00E12D81D00D485EA /* keychain_export.c in Sources */, + AACD2CA10E12D81D00D485EA /* keychain_find.c in Sources */, + AACD2CA20E12D81D00D485EA /* keychain_import.c in Sources */, + AACD2CA30E12D81D00D485EA /* keychain_list.c in Sources */, + AACD2CA40E12D81D00D485EA /* keychain_lock.c in Sources */, + AACD2CA50E12D81D00D485EA /* keychain_set_settings.c in Sources */, + AACD2CA60E12D81D00D485EA /* keychain_show_info.c in Sources */, + AACD2CA70E12D81D00D485EA /* keychain_unlock.c in Sources */, + AACD2CA80E12D81D00D485EA /* keychain_utilities.c in Sources */, + AACD2CA90E12D81D00D485EA /* leaks.c in Sources */, + AACD2CAA0E12D81D00D485EA /* readline.c in Sources */, + AACD2CAB0E12D81D00D485EA /* security.c in Sources */, + AACD2CAC0E12D81D00D485EA /* mds_install.cpp in Sources */, + AACD2CAD0E12D81D00D485EA /* keychain_recode.c in Sources */, + AACD2CAE0E12D81D00D485EA /* trusted_cert_dump.c in Sources */, + AACD2CAF0E12D81D00D485EA /* trusted_cert_add.c in Sources */, + AACD2CB00E12D81D00D485EA /* trusted_cert_utils.c in Sources */, + AACD2CB10E12D81D00D485EA /* user_trust_enable.cpp in Sources */, + AACD2CB20E12D81D00D485EA /* trust_settings_impexp.c in Sources */, + AACD2CB30E12D81D00D485EA /* authz.c in Sources */, + AACD2CB40E12D81D00D485EA /* verify_cert.c in Sources */, + AACD2CB50E12D81D00D485EA /* display_error_code.c in Sources */, + BE851CE60E270695008295B3 /* access_utils.c in Sources */, + BE926A550F253EBB00371998 /* identity_prefs.c in Sources */, + BE2D8DFB0F2D3A7C0047A0F9 /* identity_find.c in Sources */, + 5287946E13CCCC32007AFF54 /* createFVMaster.c in Sources */, + 5287947713CCD56A007AFF54 /* srCdsaUtils.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + AACD2CBA0E12D81D00D485EA /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18A25BEA14752959004F59F8 /* debug.xcconfig */; + buildSettings = { + INSTALL_PATH = /usr/bin; + }; + name = Debug; + }; + AACD2CBD0E12D81D00D485EA /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18A25BEC14752959004F59F8 /* release.xcconfig */; + buildSettings = { + INSTALL_PATH = /usr/bin; + }; + name = Release; + }; + C27AD1BB0987FCDB001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18A25BEB14752959004F59F8 /* project.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD1BE0987FCDB001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18A25BEB14752959004F59F8 /* project.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + AACD2CB90E12D81D00D485EA /* Build configuration list for PBXNativeTarget "security" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AACD2CBA0E12D81D00D485EA /* Debug */, + AACD2CBD0E12D81D00D485EA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD1BA0987FCDB001272E0 /* Build configuration list for PBXProject "SecurityTool" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD1BB0987FCDB001272E0 /* Debug */, + C27AD1BE0987FCDB001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/SecurityTool/access_utils.c b/SecurityTool/access_utils.c new file mode 100644 index 00000000..6a3afa70 --- /dev/null +++ b/SecurityTool/access_utils.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2008-2009,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@ + * + * access_utils.c + */ + +#include "access_utils.h" +#include "security.h" +#include +#include +#include +#include + +// create_access +// +// This function creates a SecAccessRef with an array of trusted applications. +// +int +create_access(const char *accessName, Boolean allowAny, CFArrayRef trustedApps, SecAccessRef *access) +{ + int result = 0; + CFArrayRef appList = NULL; + CFArrayRef aclList = NULL; + CFStringRef description = NULL; + const char *descriptionLabel = (accessName) ? accessName : ""; + CFStringRef promptDescription = NULL; + CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector; + SecACLRef aclRef; + OSStatus status; + + if (accessName) { + description = CFStringCreateWithCString(NULL, descriptionLabel, kCFStringEncodingUTF8); + } + + status = SecAccessCreate(description, trustedApps, access); + if (status) + { + sec_perror("SecAccessCreate", status); + result = 1; + goto cleanup; + } + + // get the access control list for decryption operations (this controls access to an item's data) + status = SecAccessCopySelectedACLList(*access, CSSM_ACL_AUTHORIZATION_DECRYPT, &aclList); + if (status) + { + sec_perror("SecAccessCopySelectedACLList", status); + result = 1; + goto cleanup; + } + + // get the first entry in the access control list + aclRef = (SecACLRef)CFArrayGetValueAtIndex(aclList, 0); + status = SecACLCopySimpleContents(aclRef, &appList, &promptDescription, &promptSelector); + if (status) + { + sec_perror("SecACLCopySimpleContents", status); + result = 1; + goto cleanup; + } + + if (allowAny) // "allow all applications to access this item" + { + // change the decryption ACL to not require the passphrase, and have a nil application list. + promptSelector.flags &= ~CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE; + status = SecACLSetSimpleContents(aclRef, NULL, promptDescription, &promptSelector); + } + else // "allow access by these applications" + { + // modify the application list + status = SecACLSetSimpleContents(aclRef, trustedApps, promptDescription, &promptSelector); + } + if (status) + { + sec_perror("SecACLSetSimpleContents", status); + result = 1; + goto cleanup; + } + +cleanup: + if (description) + CFRelease(description); + if (promptDescription) + CFRelease(promptDescription); + if (appList) + CFRelease(appList); + if (aclList) + CFRelease(aclList); + + return result; +} + +// merge_access +// +// This function merges the contents of otherAccess into access. +// Simple ACL contents are assumed, and only the standard ACL +// for decryption operations is currently processed. +// +int +merge_access(SecAccessRef access, SecAccessRef otherAccess) +{ + OSStatus status; + CFArrayRef aclList, newAclList; + + // get existing access control list for decryption operations (this controls access to an item's data) + status = SecAccessCopySelectedACLList(access, CSSM_ACL_AUTHORIZATION_DECRYPT, &aclList); + if (status) { + return status; + } + // get desired access control list for decryption operations + status = SecAccessCopySelectedACLList(otherAccess, CSSM_ACL_AUTHORIZATION_DECRYPT, &newAclList); + if (status) { + newAclList = nil; + } else { + SecACLRef aclRef=(SecACLRef)CFArrayGetValueAtIndex(aclList, 0); + SecACLRef newAclRef=(SecACLRef)CFArrayGetValueAtIndex(newAclList, 0); + CFArrayRef appList=nil; + CFArrayRef newAppList=nil; + CFMutableArrayRef mergedAppList = nil; + CFStringRef promptDescription=nil; + CFStringRef newPromptDescription=nil; + CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector; + CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR newPromptSelector; + + status = SecACLCopySimpleContents(aclRef, &appList, &promptDescription, &promptSelector); + if (!status) { + status = SecACLCopySimpleContents(newAclRef, &newAppList, &newPromptDescription, &newPromptSelector); + } + if (!status) { + if (appList) { + mergedAppList = CFArrayCreateMutableCopy(NULL, 0, appList); + } + if (newAppList) { + if (mergedAppList) { + CFArrayAppendArray(mergedAppList, newAppList, CFRangeMake(0, CFArrayGetCount(newAppList))); + } else { + mergedAppList = CFArrayCreateMutableCopy(NULL, 0, newAppList); + } + } + promptSelector.flags = newPromptSelector.flags; + status = SecACLSetSimpleContents(aclRef, mergedAppList, newPromptDescription, &newPromptSelector); + } + + if (appList) CFRelease(appList); + if (newAppList) CFRelease(newAppList); + if (mergedAppList) CFRelease(mergedAppList); + if (promptDescription) CFRelease(promptDescription); + if (newPromptDescription) CFRelease(newPromptDescription); + } + if (aclList) CFRelease(aclList); + if (newAclList) CFRelease(newAclList); + + return status; +} + +// modify_access +// +// This function updates the access for an existing item. +// The provided access is merged with the item's existing access. +// +int +modify_access(SecKeychainItemRef itemRef, SecAccessRef access) +{ + OSStatus status; + SecAccessRef curAccess = NULL; + // for historical reasons, we have to modify the item's existing access reference + // (setting the item's access to a freshly created SecAccessRef instance doesn't behave as expected) + status = SecKeychainItemCopyAccess(itemRef, &curAccess); + if (status) { + sec_error("SecKeychainItemCopyAccess: %s", sec_errstr(status)); + } else { + status = merge_access(curAccess, access); // make changes to the existing access reference + if (!status) { + status = SecKeychainItemSetAccess(itemRef, curAccess); // will prompt! + if (status) { + sec_error("SecKeychainItemSetAccess: %s", sec_errstr(status)); + } + } + } + if (curAccess) { + CFRelease(curAccess); + } + return status; +} diff --git a/SecurityTool/access_utils.h b/SecurityTool/access_utils.h new file mode 100644 index 00000000..78ea171c --- /dev/null +++ b/SecurityTool/access_utils.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2008-2009 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@ + * + * access_utils.h + */ + +#ifndef _ACCESS_UTILS_H_ +#define _ACCESS_UTILS_H_ 1 + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int create_access(const char *accessName, Boolean allowAny, CFArrayRef trustedApps, SecAccessRef *access); + +extern int merge_access(SecAccessRef access, SecAccessRef otherAccess); + +extern int modify_access(SecKeychainItemRef itemRef, SecAccessRef access); + +#ifdef __cplusplus +} +#endif + +#endif /* _ACCESS_UTILS_H_ */ diff --git a/SecurityTool/authz.c b/SecurityTool/authz.c new file mode 100644 index 00000000..b7bd1ec8 --- /dev/null +++ b/SecurityTool/authz.c @@ -0,0 +1,723 @@ +/* + * Copyright (c) 2003-2004,2006-2007,2009-2010,2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * authz.c + */ + +#include +#include +#include + +#include "authz.h" +#include "security.h" + +// AEWP? + +AuthorizationRef +read_auth_ref_from_stdin() +{ + AuthorizationRef auth_ref = NULL; + AuthorizationExternalForm extform; + size_t bytes_read; + + while (kAuthorizationExternalFormLength != (bytes_read = read(STDIN_FILENO, &extform, kAuthorizationExternalFormLength))) + { + if ((bytes_read == -1) && ((errno != EAGAIN) || (errno != EINTR))) + break; + } + if (bytes_read != kAuthorizationExternalFormLength) + fprintf(stderr, "ERR: Failed to read authref\n"); + else + if (AuthorizationCreateFromExternalForm(&extform, &auth_ref)) + fprintf(stderr, "ERR: Failed to internalize authref\n"); + + close(0); + + return auth_ref; +} + +int +write_auth_ref_to_stdout(AuthorizationRef auth_ref) +{ + AuthorizationExternalForm extform; + size_t bytes_written; + + if (AuthorizationMakeExternalForm(auth_ref, &extform)) + return -1; + + while (kAuthorizationExternalFormLength != (bytes_written = write(STDOUT_FILENO, &extform, kAuthorizationExternalFormLength))) + { + if ((bytes_written == -1) && ((errno != EAGAIN) || (errno != EINTR))) + break; + } + + if (bytes_written == kAuthorizationExternalFormLength) + return 0; + + return -1; +} + +void +write_dict_to_stdout(CFDictionaryRef dict) +{ + if (!dict) + return; + + CFDataRef right_definition_xml = CFPropertyListCreateXMLData(NULL, dict); + + if (!right_definition_xml) + return; + + write(STDOUT_FILENO, CFDataGetBytePtr(right_definition_xml), CFDataGetLength(right_definition_xml)); + CFRelease(right_definition_xml); +} + +CFDictionaryRef +read_dict_from_stdin() +{ + int bytes_read = 0; + uint8_t buffer[4096]; + CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0); + CFErrorRef err = NULL; + + if (!data) + return NULL; + + while ((bytes_read = read(STDIN_FILENO, (void *)buffer, sizeof(buffer)))) + { + if (bytes_read == -1) + break; + else + CFDataAppendBytes(data, buffer, bytes_read); + } + + CFDictionaryRef right_dict = (CFDictionaryRef)CFPropertyListCreateWithData(kCFAllocatorDefault, data, kCFPropertyListImmutable, NULL, &err); + CFRelease(data); + + if (NULL == right_dict) { + CFShow(err); + return NULL; + } + + if (CFGetTypeID(right_dict) != CFDictionaryGetTypeID()) + { + fprintf(stderr, "This is not a dictionary.\n"); + CFRelease(right_dict); + return NULL; + } + return right_dict; +} + +CFPropertyListRef +read_plist_from_file(CFStringRef filePath) +{ + CFTypeRef property = NULL; + CFPropertyListRef propertyList = NULL; + CFURLRef fileURL = NULL; + CFErrorRef errorString = NULL; + CFDataRef resourceData = NULL; + Boolean status = FALSE; + SInt32 errorCode = -1; + + // Convert the path to a URL. + fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, filePath, kCFURLPOSIXPathStyle, false); + if (NULL == fileURL) { + goto bail; + } + property = CFURLCreatePropertyFromResource(kCFAllocatorDefault, fileURL, kCFURLFileExists, NULL); + if (NULL == property) { + goto bail; + } + status = CFBooleanGetValue(property); + if (!status) { + fprintf(stderr, "The file does not exist.\n"); + goto bail; + } + + // Read the XML file. + status = CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, fileURL, &resourceData, NULL, NULL, &errorCode); + if (!status) { + fprintf(stderr, "Error (%d) reading the file.\n", (int)errorCode); + goto bail; + } + + // Reconstitute the dictionary using the XML data. + propertyList = CFPropertyListCreateWithData(kCFAllocatorDefault, resourceData, kCFPropertyListImmutable, NULL, &errorString); + if (NULL == propertyList) { + CFShow(errorString); + goto bail; + } + + // Some error checking. + if (!CFPropertyListIsValid(propertyList, kCFPropertyListXMLFormat_v1_0) || CFGetTypeID(propertyList) != CFDictionaryGetTypeID()) { + fprintf(stderr, "The file is invalid.\n"); + CFRelease(propertyList); + propertyList = NULL; + goto bail; + } + +bail: + if (NULL != fileURL) + CFRelease(fileURL); + if (NULL != property) + CFRelease(property); + if (NULL != resourceData) + CFRelease(resourceData); + + return propertyList; +} + +Boolean +write_plist_to_file(CFPropertyListRef propertyList, CFStringRef filePath) +{ + CFTypeRef property = NULL; + CFURLRef fileURL = NULL; + CFDataRef xmlData = NULL; + Boolean status = FALSE; + SInt32 errorCode = -1; + CFErrorRef errorRef = NULL; + + // Convert the path to a URL. + fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, filePath, kCFURLPOSIXPathStyle, false); + if (NULL == fileURL) { + goto bail; + } + property = CFURLCreatePropertyFromResource(kCFAllocatorDefault, fileURL, kCFURLFileExists, NULL); + if (NULL == property) { + goto bail; + } + if (!CFBooleanGetValue(property)) { + fprintf(stderr, "The file does not exist.\n"); + goto bail; + } + + // Convert the property list into XML data. + xmlData = CFPropertyListCreateData(kCFAllocatorDefault, propertyList, kCFPropertyListXMLFormat_v1_0, 0, &errorRef); + if (errorRef) { + fprintf(stderr, "The file could not be written.\n"); + goto bail; + } + + // Write the XML data to the file. + if (!CFURLWriteDataAndPropertiesToResource(fileURL, xmlData, NULL, &errorCode)) { + fprintf(stderr, "The file could not be written.\n"); + goto bail; + } + + status = TRUE; +bail: + if (NULL != xmlData) + CFRelease(xmlData); + if (NULL != fileURL) + CFRelease(fileURL); + + return status; +} + +static void merge_dictionaries(const void *key, const void *value, void *mergeDict) +{ + CFDictionarySetValue(mergeDict, key, value); +} + +int +authorizationdb(int argc, char * const * argv) +{ + AuthorizationRef auth_ref = NULL; + int ch; + while ((ch = getopt(argc, argv, "i")) != -1) + { + switch (ch) + { + case 'i': + auth_ref = read_auth_ref_from_stdin(); + break; + case '?': + default: + return 2; + } + } + + argc -= optind; + argv += optind; + + if (argc == 0) + return 2; // required right parameter(s) + + OSStatus status; + + if (argc > 1) + { + if (!auth_ref && AuthorizationCreate(NULL, NULL, 0, &auth_ref)) + return -1; + + if (!strcmp("read", argv[0])) + { + CFDictionaryRef right_definition; + status = AuthorizationRightGet(argv[1], &right_definition); + if (!status) + { + write_dict_to_stdout(right_definition); + CFRelease(right_definition); + } + } + else if (!strcmp("write", argv[0])) + { + if (argc == 2) + { + CFDictionaryRef right_definition = read_dict_from_stdin(); + if (!right_definition) + return -1; + status = AuthorizationRightSet(auth_ref, argv[1], right_definition, NULL, NULL, NULL); + CFRelease(right_definition); + } + else if (argc == 3) + { + // argv[2] is shortcut string + CFStringRef shortcut_definition = CFStringCreateWithCStringNoCopy(NULL, argv[2], kCFStringEncodingUTF8, kCFAllocatorNull); + if (!shortcut_definition) + return -1; + status = AuthorizationRightSet(auth_ref, argv[1], shortcut_definition, NULL, NULL, NULL); + CFRelease(shortcut_definition); + } + else + return 2; // take one optional argument - no more + + } + else if (!strcmp("remove", argv[0])) + { + status = AuthorizationRightRemove(auth_ref, argv[1]); + } + else if (!strcmp("smartcard", argv[0])) + { + if (argc == 2) + { + if(!strcmp("status", argv[1])) + { + const CFStringRef SMARTCARD_LINE = CFSTR("builtin:smartcard-sniffer,privileged"); + const CFStringRef MECHANISMS = CFSTR("mechanisms"); + const CFStringRef BUILTIN_LINE = CFSTR("builtin:policy-banner"); + const char* SYSTEM_LOGIN_CONSOLE = "system.login.console"; + const char* AUTHENTICATE = "authenticate"; + + CFIndex requiredLine1 = -1; + CFIndex requiredLine2 = -1; + + CFDictionaryRef right_definition; + status = AuthorizationRightGet(SYSTEM_LOGIN_CONSOLE, &right_definition); + if(!status) + { + CFArrayRef mechanisms; + + Boolean res = CFDictionaryGetValueIfPresent(right_definition, MECHANISMS, (void*)&mechanisms); + if(res) + { + // now parse all array elements until "builtin:policy-banner" is found + CFIndex c = CFArrayGetCount(mechanisms); + CFStringRef mechanismName; + + for (CFIndex i = 0; i < c; ++i) + { + mechanismName = CFArrayGetValueAtIndex(mechanisms, i); + if(CFStringCompare(mechanismName, BUILTIN_LINE, 0) == kCFCompareEqualTo) + { + if(i + 1 < c) + { + mechanismName = CFArrayGetValueAtIndex(mechanisms, i + 1); + if(CFStringCompare(mechanismName, SMARTCARD_LINE, 0) == kCFCompareEqualTo) + { + requiredLine1 = i + 1; + } + break; + } + } + } + } + CFRelease(right_definition); + } + status = AuthorizationRightGet(AUTHENTICATE, &right_definition); + if(!status) + { + CFArrayRef mechanisms; + + Boolean res = CFDictionaryGetValueIfPresent(right_definition, MECHANISMS, (void*)&mechanisms); + if(res) + { + // now parse all array elements until "builtin:policy-banner" is found + CFIndex c = CFArrayGetCount(mechanisms); + CFStringRef mechanismName; + + if(c > 0) + { + mechanismName = CFArrayGetValueAtIndex(mechanisms, 0); + if(CFStringCompare(mechanismName, SMARTCARD_LINE, 0) == kCFCompareEqualTo) + { + requiredLine2 = 0; + } + } + } + CFRelease(right_definition); + } + printf("Current smartcard login state: %s (system.login.console %s, authentication rule %s)\n", requiredLine1 != -1 && requiredLine2 != -1 ?"enabled":"disabled", requiredLine1 != -1 ? "enabled":"disabled", requiredLine2 != -1 ? "enabled":"disabled"); + + } + else if(!strcmp("disable", argv[1])) + status = AuthorizationEnableSmartCard(auth_ref, FALSE); + else if(!strcmp("enable", argv[1])) + status = AuthorizationEnableSmartCard(auth_ref, TRUE); + else + return 2; // unrecognized parameter + } + else + return 2; // required parameter missing + } + else if (!strcmp("merge", argv[0])) { + status = 1; + CFStringRef sourcePath = NULL; + CFStringRef destPath = NULL; + CFPropertyListRef sourcePlist = NULL; + CFPropertyListRef destPlist = NULL; + CFDictionaryRef sourceRights = NULL; + CFDictionaryRef sourceRules = NULL; + CFDictionaryRef destRights = NULL; + CFDictionaryRef destRules = NULL; + CFIndex rightsCount = 0; + CFIndex rulesCount = 0; + CFMutableDictionaryRef mergeRights = NULL; + CFMutableDictionaryRef mergeRules = NULL; + CFMutableDictionaryRef outDict = NULL; + + if (argc < 2 || argc > 3) + return 2; + + if (!strcmp("-", argv[1])) { + // Merging from . + sourcePlist = read_dict_from_stdin(); + } else { + sourcePath = CFStringCreateWithCString(kCFAllocatorDefault, argv[1], kCFStringEncodingUTF8); + if (NULL == sourcePath) { + goto bail; + } + sourcePlist = read_plist_from_file(sourcePath); + } + if (NULL == sourcePlist) + goto bail; + if (argc == 2) { + // Merging to /etc/authorization. + destPath = CFStringCreateWithCString(kCFAllocatorDefault, "/etc/authorization", kCFStringEncodingUTF8); + } else { + destPath = CFStringCreateWithCString(kCFAllocatorDefault, argv[2], kCFStringEncodingUTF8); + } + if (NULL == destPath) { + goto bail; + } + destPlist = read_plist_from_file(destPath); + if (NULL == destPlist) + goto bail; + + sourceRights = CFDictionaryGetValue(sourcePlist, CFSTR("rights")); + sourceRules = CFDictionaryGetValue(sourcePlist, CFSTR("rules")); + destRights = CFDictionaryGetValue(destPlist, CFSTR("rights")); + destRules = CFDictionaryGetValue(destPlist, CFSTR("rules")); + if (sourceRights) + rightsCount += CFDictionaryGetCount(sourceRights); + if (destRights) + rightsCount += CFDictionaryGetCount(destRights); + mergeRights = CFDictionaryCreateMutable(NULL, rightsCount, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (NULL == mergeRights) { + goto bail; + } + if (sourceRules) + rulesCount += CFDictionaryGetCount(sourceRules); + if (destRules) + rulesCount += CFDictionaryGetCount(destRules); + mergeRules = CFDictionaryCreateMutable(NULL, rulesCount, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (NULL == mergeRules) { + goto bail; + } + + if (destRights) + CFDictionaryApplyFunction(destRights, merge_dictionaries, mergeRights); + if (destRules) + CFDictionaryApplyFunction(destRules, merge_dictionaries, mergeRules); + if (sourceRights) + CFDictionaryApplyFunction(sourceRights, merge_dictionaries, mergeRights); + if (sourceRules) + CFDictionaryApplyFunction(sourceRules, merge_dictionaries, mergeRules); + + outDict = CFDictionaryCreateMutable(NULL, 3, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (NULL == outDict) { + goto bail; + } + if (CFDictionaryContainsKey(sourcePlist, CFSTR("comment"))) + CFDictionaryAddValue(outDict, CFSTR("comment"), CFDictionaryGetValue(sourcePlist, CFSTR("comment"))); + else if (CFDictionaryContainsKey(destPlist, CFSTR("comment"))) + CFDictionaryAddValue(outDict, CFSTR("comment"), CFDictionaryGetValue(destPlist, CFSTR("comment"))); + CFDictionaryAddValue(outDict, CFSTR("rights"), mergeRights); + CFDictionaryAddValue(outDict, CFSTR("rules"), mergeRules); + if (!write_plist_to_file(outDict, destPath)) + goto bail; + + status = noErr; +bail: + if (sourcePath) + CFRelease(sourcePath); + if (destPath) + CFRelease(destPath); + if (sourcePlist) + CFRelease(sourcePlist); + if (destPlist) + CFRelease(destPlist); + if (outDict) + CFRelease(outDict); + } + else + return 2; + } + else + return 2; + + if (auth_ref) + AuthorizationFree(auth_ref, 0); + + if (!do_quiet) + fprintf(stderr, "%s (%d)\n", status ? "NO" : "YES", (int)status); + + return (status ? -1 : 0); +} + +int +authorize(int argc, char * const *argv) +{ + int ch; + OSStatus status; + + Boolean user_interaction_allowed = FALSE, extend_rights = TRUE; + Boolean partial_rights = FALSE, destroy_rights = FALSE; + Boolean pre_authorize = FALSE, internalize = FALSE, externalize = FALSE; + Boolean wait = FALSE, explicit_credentials = FALSE; + Boolean isolate_explicit_credentials = FALSE, least_privileged = FALSE; + char *login = NULL; + + while ((ch = getopt(argc, argv, "ucC:EpdPieqwxl")) != -1) + { + switch (ch) + { + case 'u': + user_interaction_allowed = TRUE; + break; + case 'c': + explicit_credentials = TRUE; + break; + case 'C': + explicit_credentials = TRUE; + login = optarg; + break; + case 'e': + externalize = TRUE; + break; + case 'E': + extend_rights = FALSE; + break; + case 'p': + partial_rights = TRUE; + break; + case 'd': + destroy_rights = TRUE; + break; + case 'P': + pre_authorize = TRUE; + break; + case 'i': + internalize = TRUE; + break; + case 'w': + wait = TRUE; + externalize = TRUE; + break; + case 'x': + isolate_explicit_credentials = TRUE; + break; + case 'l': + least_privileged = TRUE; + break; + case '?': + default: + return 2; /* @@@ Return 2 triggers usage message. */ + } + } + + argc -= optind; + argv += optind; + + if (argc == 0) + return 2; // required right parameter(s) + +// set up AuthorizationFlags + AuthorizationFlags flags = kAuthorizationFlagDefaults | + (user_interaction_allowed ? kAuthorizationFlagInteractionAllowed : 0) | + (extend_rights ? kAuthorizationFlagExtendRights : 0) | + (partial_rights ? kAuthorizationFlagPartialRights : 0) | + (pre_authorize ? kAuthorizationFlagPreAuthorize : 0) | + (least_privileged ? kAuthorizationFlagLeastPrivileged : 0); + +// set up AuthorizationRightSet + AuthorizationItem rights[argc]; + memset(rights, '\0', argc * sizeof(AuthorizationItem)); + AuthorizationItemSet rightset = { argc, rights }; + while (argc > 0) + rights[--argc].name = *argv++; + + AuthorizationRef auth_ref = NULL; + +// internalize AuthorizationRef + if (internalize) + { + auth_ref = read_auth_ref_from_stdin(); + if (!auth_ref) + return 1; + } + + if (!auth_ref && AuthorizationCreate(NULL, NULL, + (least_privileged ? kAuthorizationFlagLeastPrivileged : 0), + &auth_ref)) + return -1; + +// prepare environment if needed + AuthorizationEnvironment *envp = NULL; + if (explicit_credentials) { + if (!login) + login = getlogin(); + char *pass = getpass("Password:"); + if (!(login && pass)) + return 1; + static AuthorizationItem authenv[] = { + { kAuthorizationEnvironmentUsername }, + { kAuthorizationEnvironmentPassword }, + { kAuthorizationEnvironmentShared } // optional (see below) + }; + static AuthorizationEnvironment env = { 0, authenv }; + authenv[0].valueLength = strlen(login); + authenv[0].value = login; + authenv[1].valueLength = strlen(pass); + authenv[1].value = pass; + if (isolate_explicit_credentials) + env.count = 2; // do not send kAuthorizationEnvironmentShared + else + env.count = 3; // do send kAuthorizationEnvironmentShared + envp = &env; + } + +// perform Authorization + AuthorizationRights *granted_rights = NULL; + status = AuthorizationCopyRights(auth_ref, &rightset, envp, flags, &granted_rights); + +// externalize AuthorizationRef + if (externalize) + write_auth_ref_to_stdout(auth_ref); + + if (!do_quiet) + fprintf(stderr, "%s (%d) ", status ? "NO" : "YES", (int)status); + + if (!do_quiet && !status && granted_rights) + { + uint32_t index; + fprintf(stderr, "{ %d: ", (int)granted_rights->count); + for (index = 0; index < granted_rights->count; index++) + { + fprintf(stderr, "\"%s\"%s %c ", granted_rights->items[index].name, + (kAuthorizationFlagCanNotPreAuthorize & granted_rights->items[index].flags) ? " (cannot-preauthorize)" : "", + (index+1 != granted_rights->count) ? ',' : '}'); + } + AuthorizationFreeItemSet(granted_rights); + } + + if (!do_quiet) + fprintf(stderr, "\n"); + +// wait for client to pick up AuthorizationRef + if (externalize && wait) + while (-1 != write(STDOUT_FILENO, NULL, 0)) + usleep(100); + +// drop AuthorizationRef + if (auth_ref) + AuthorizationFree(auth_ref, destroy_rights ? kAuthorizationFlagDestroyRights : 0); + + return (status ? -1 : 0); +} + + +int +execute_with_privileges(int argc, char * const *argv) +{ + AuthorizationRef auth_ref = NULL; + int ch; + while ((ch = getopt(argc, argv, "i")) != -1) + { + switch (ch) + { + case 'i': + auth_ref = read_auth_ref_from_stdin(); + break; + case '?': + default: + return 2; + } + } + + argc -= optind; + argv += optind; + + if (argc == 0) + return 2; // required tool parameter(s) + + OSStatus status; + + if (!auth_ref && AuthorizationCreate(NULL, NULL, 0, &auth_ref)) + return -1; + + FILE *communications_pipe = NULL; + + status = AuthorizationExecuteWithPrivileges(auth_ref,argv[0], 0, (argc > 1) ? &argv[1] : NULL, &communications_pipe); + + if (!do_quiet) + fprintf(stderr, "%s (%d) ", status ? "NO" : "YES", (int)status); + + if (!status) + { + int bytes_read = 0; + uint8_t buffer[4096]; + + while ((bytes_read = read(STDIN_FILENO, &buffer, sizeof(buffer)))) + { + if ((bytes_read == -1) && ((errno != EAGAIN) || (errno != EINTR))) + break; + else + while ((-1 == write(fileno(communications_pipe), buffer, bytes_read)) && + ((errno == EAGAIN) || (errno == EINTR))) + usleep(100); + } + } + + return (status ? -1 : 0); +} + diff --git a/SecurityTool/authz.h b/SecurityTool/authz.h new file mode 100644 index 00000000..5a3d5ca0 --- /dev/null +++ b/SecurityTool/authz.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2003-2004,2006,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + * + * authz.h + */ + +#include +#include +#include + +int authorize(int argc, char * const *argv); +int authorizationdb(int argc, char * const *argv); +int execute_with_privileges(int argc, char * const *argv); diff --git a/SecurityTool/cmsutil.c b/SecurityTool/cmsutil.c new file mode 100644 index 00000000..584fba1c --- /dev/null +++ b/SecurityTool/cmsutil.c @@ -0,0 +1,1595 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * Modifications Copyright (c) 2003-2009,2012,2014 Apple Inc. All Rights Reserved. + * + * cmsutil -- A command to work with CMS data + */ + +#include "security.h" +#include "keychain_utilities.h" +#include "identity_find.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +// SecPolicyCopy +#include +// SecKeychainSearchCreateForCertificateByEmail, SecCertificateFindBySubjectKeyID, SecCertificateFindByEmail +#include +// SecIdentitySearchCreateWithPolicy +#include + +#define SEC_CHECK0(CALL, ERROR) do { if (!(CALL)) { sec_error(ERROR); goto loser; } } while(0) +#define SEC_CHECK(CALL, ERROR) do { rv = (CALL); if (rv) { sec_perror(ERROR, rv); goto loser; } } while(0) +#define SEC_CHECK2(CALL, ERROR, ARG) do { rv = CALL; if (rv) \ + { sec_error(ERROR ": %s", ARG, sec_errstr(rv)); goto loser; } } while(0) + +// @@@ Remove this +#if 1 + +static CSSM_KEYUSE CERT_KeyUsageForCertUsage(SECCertUsage certUsage) +{ + switch (certUsage) + { + case certUsageSSLClient: return CSSM_KEYUSE_SIGN; + case certUsageSSLServer: return CSSM_KEYUSE_SIGN; + case certUsageSSLServerWithStepUp: return CSSM_KEYUSE_SIGN; + case certUsageSSLCA: return CSSM_KEYUSE_SIGN; + case certUsageEmailSigner: return CSSM_KEYUSE_SIGN; + case certUsageEmailRecipient: return CSSM_KEYUSE_UNWRAP; + case certUsageObjectSigner: return CSSM_KEYUSE_SIGN; + case certUsageUserCertImport: return CSSM_KEYUSE_SIGN; + case certUsageVerifyCA: return CSSM_KEYUSE_SIGN; + case certUsageProtectedObjectSigner: return CSSM_KEYUSE_SIGN; + case certUsageStatusResponder: return CSSM_KEYUSE_SIGN; + case certUsageAnyCA: return CSSM_KEYUSE_SIGN; + default: + sec_error("CERT_PolicyForCertUsage %ld: unknown certUsage", certUsage); + return CSSM_KEYUSE_SIGN; + } +} + +static SecPolicyRef CERT_PolicyForCertUsage(SECCertUsage certUsage, const char *emailAddress) +{ + SecPolicyRef policy = NULL; + const CSSM_OID *policyOID; + OSStatus rv; + + switch (certUsage) + { + case certUsageSSLClient: policyOID = &CSSMOID_APPLE_TP_SSL; break; + case certUsageSSLServer: policyOID = &CSSMOID_APPLE_TP_SSL; break; + case certUsageSSLServerWithStepUp: policyOID = &CSSMOID_APPLE_TP_SSL; break; + case certUsageSSLCA: policyOID = &CSSMOID_APPLE_TP_SSL; break; + case certUsageEmailSigner: policyOID = &CSSMOID_APPLE_TP_SMIME; break; + case certUsageEmailRecipient: policyOID = &CSSMOID_APPLE_TP_SMIME; break; + case certUsageObjectSigner: policyOID = &CSSMOID_APPLE_TP_CODE_SIGN; break; + case certUsageUserCertImport: policyOID = &CSSMOID_APPLE_X509_BASIC; break; + case certUsageVerifyCA: policyOID = &CSSMOID_APPLE_X509_BASIC; break; + case certUsageProtectedObjectSigner: policyOID = &CSSMOID_APPLE_ISIGN; break; + case certUsageStatusResponder: policyOID = &CSSMOID_APPLE_TP_REVOCATION_OCSP; break; + case certUsageAnyCA: policyOID = &CSSMOID_APPLE_X509_BASIC; break; + default: + sec_error("CERT_PolicyForCertUsage %ld: unknown certUsage", certUsage); + goto loser; + } + + SEC_CHECK(SecPolicyCopy(CSSM_CERT_X_509v3, policyOID, &policy), "SecPolicyCopy"); + if (certUsage == certUsageEmailSigner || certUsage == certUsageEmailRecipient) + { + CSSM_APPLE_TP_SMIME_OPTIONS options = + { + CSSM_APPLE_TP_SMIME_OPTS_VERSION, + certUsage == certUsageEmailSigner + ? CE_KU_DigitalSignature | CE_KU_NonRepudiation + : CE_KU_KeyEncipherment, + emailAddress ? sizeof(emailAddress) : 0, + emailAddress + }; + CSSM_DATA value = { sizeof(options), (uint8 *)&options }; + SEC_CHECK(SecPolicySetValue(policy, &value), "SecPolicySetValue"); + } + + // @@@ Need to set values for SSL and other policies. + return policy; + +loser: + if (policy) CFRelease(policy); + return NULL; +} + +static SecCertificateRef CERT_FindUserCertByUsage(CFTypeRef keychainOrArray, const char *emailAddress, + SECCertUsage certUsage, Boolean validOnly) +{ + SecKeychainSearchRef search = NULL; + SecCertificateRef cert = NULL; + SecPolicyRef policy; + OSStatus rv; + + policy = CERT_PolicyForCertUsage(certUsage, emailAddress); + if (!policy) + goto loser; + + SEC_CHECK2(SecKeychainSearchCreateForCertificateByEmail(keychainOrArray, emailAddress, &search), + "create search for certificate with email: \"%s\"", emailAddress); + for (;;) + { + SecKeychainItemRef item; + rv = SecKeychainSearchCopyNext(search, &item); + if (rv) + { + if (rv == errSecItemNotFound) + break; + + sec_perror("error finding next matching certificate", rv); + goto loser; + } + + cert = (SecCertificateRef)item; + // @@@ Check cert against policy. + } + +loser: + if (policy) CFRelease(policy); + if (search) CFRelease(search); + + return cert; +} + +static SecIdentityRef CERT_FindIdentityByUsage(CFTypeRef keychainOrArray, + const char *emailAddress, + SECCertUsage certUsage, + Boolean validOnly) +{ + SecIdentitySearchRef search = NULL; + SecIdentityRef identity = NULL; + CFStringRef idString = CFStringCreateWithCString(NULL, emailAddress, kCFStringEncodingUTF8); + SecPolicyRef policy; + OSStatus rv; + + policy = CERT_PolicyForCertUsage(certUsage, emailAddress); + if (!policy) + goto loser; + + + SEC_CHECK2(SecIdentitySearchCreateWithPolicy(policy, idString, + CERT_KeyUsageForCertUsage(certUsage), keychainOrArray, validOnly, &search), + "create search for identity with email: \"%s\"", emailAddress); + for (;;) + { + rv = SecIdentitySearchCopyNext(search, &identity); + if (rv) + { + if (rv == errSecItemNotFound) + break; + + sec_perror("error finding next matching identity", rv); + goto loser; + } + } + +loser: + if (policy) CFRelease(policy); + if (search) CFRelease(search); + if (idString) CFRelease(idString); + + return identity; + + +#if 0 + SecIdentityRef identity = NULL; + SecCertificateRef cert; + OSStatus rv; + + cert = CERT_FindUserCertByUsage(keychainOrArray, emailAddress, certUsage, validOnly); + if (!cert) + goto loser; + + SEC_CHECK2(SecIdentityCreateWithCertificate(keychainOrArray, cert, &identity), + "failed to find private key for certificate with email: \"%s\"", emailAddress); +loser: + if (cert) CFRelease(cert); + + return identity; +#endif +} + +static SecCertificateRef CERT_FindCertByNicknameOrEmailAddr(CFTypeRef keychainOrArray, const char *emailAddress) +{ + SecCertificateRef certificate = NULL; + OSStatus rv; + + SEC_CHECK2(SecCertificateFindByEmail(keychainOrArray, emailAddress, &certificate), + "failed to find certificate with email: \"%s\"", emailAddress); + +loser: + return certificate; +} + +static SecIdentityRef CERT_FindIdentityBySubjectKeyID(CFTypeRef keychainOrArray, + const char *subjectKeyIDString) +{ + // ss will be something like "B2ACD31AC8D0DA62E7679432ADDD3398EF66948B" + + SecCertificateRef certificate = NULL; + SecIdentityRef identityRef = NULL; + OSStatus rv; + + CSSM_SIZE len = strlen(subjectKeyIDString)/2; + CSSM_DATA subjectKeyID = {0,}; + subjectKeyID.Length = len; + subjectKeyID.Data = (uint8 *)malloc(subjectKeyID.Length); + fromHex(subjectKeyIDString, &subjectKeyID); + + SEC_CHECK2(SecCertificateFindBySubjectKeyID(keychainOrArray, &subjectKeyID, &certificate), + "failed to find identity with subject key ID: \"%s\"", subjectKeyIDString); + + SEC_CHECK2(SecIdentityCreateWithCertificate(keychainOrArray, certificate, &identityRef), + "failed to find certificate with subject key ID: \"%s\"", subjectKeyIDString); +loser: + return identityRef; +} + + +static OSStatus CERT_CheckCertUsage (SecCertificateRef cert,unsigned char usage) +{ + return 0; +} + +#endif + +// @@@ Eleminate usage of this header. +//#include "cert.h" +//#include +//#include "plgetopt.h" +//#include "secitem.h" + +#ifdef HAVE_DODUMPSTATES +extern int doDumpStates; +#endif /* HAVE_DODUMPSTATES */ + +OSStatus SECU_FileToItem(CSSM_DATA *dst, FILE *src); + + +extern void SEC_Init(void); /* XXX */ +static int cms_verbose = 0; +static int cms_update_single_byte = 0; + +/* XXX stolen from cmsarray.c + * nss_CMSArray_Count - count number of elements in array + */ +static int nss_CMSArray_Count(void **array) +{ + int n = 0; + if (array == NULL) + return 0; + while (*array++ != NULL) + n++; + return n; +} + +typedef OSStatus(update_func)(void *cx, const char *data, unsigned int len); + +static OSStatus do_update(update_func *update, + void *cx, const unsigned char *data, int len) +{ + OSStatus rv = noErr; + if (cms_update_single_byte) + { + for (;len; --len, ++data) + { + rv = update(cx, (const char *)data, 1); + if (rv) + break; + } + } + else + rv = update(cx, (const char *)data, len); + + return rv; +} + + +static OSStatus DigestFile(SecArenaPoolRef poolp, CSSM_DATA ***digests, CSSM_DATA *input, SECAlgorithmID **algids) +{ + SecCmsDigestContextRef digcx = SecCmsDigestContextStartMultiple(algids); + if (digcx == NULL) + return paramErr; + + do_update((update_func *)SecCmsDigestContextUpdate, digcx, input->Data, input->Length); + + return SecCmsDigestContextFinishMultiple(digcx, poolp, digests); +} + +static char * +ownpw(void *info, Boolean retry, void *arg) +{ + char * passwd = NULL; + + if ( (!retry) && arg ) { + passwd = strdup((char *)arg); + } + + return passwd; +} + +struct optionsStr { + PK11PasswordFunc password; + SECCertUsage certUsage; + SecKeychainRef certDBHandle; +}; + +struct decodeOptionsStr { + struct optionsStr *options; + FILE *contentFile; + int headerLevel; + Boolean suppressContent; + SecCmsGetDecryptKeyCallback dkcb; + SecSymmetricKeyRef bulkkey; +}; + +struct signOptionsStr { + struct optionsStr *options; + char *nickname; + char *encryptionKeyPreferenceNick; + char *subjectKeyID; + Boolean signingTime; + Boolean smimeProfile; + Boolean detached; + SECOidTag hashAlgTag; + Boolean wantTimestamping; + char *timestampingURL; +}; + +struct envelopeOptionsStr { + struct optionsStr *options; + char **recipients; +}; + +struct certsonlyOptionsStr { + struct optionsStr *options; + char **recipients; +}; + +struct encryptOptionsStr { + struct optionsStr *options; + char **recipients; + SecCmsMessageRef envmsg; + CSSM_DATA *input; + FILE *outfile; + FILE *envFile; + SecSymmetricKeyRef bulkkey; + SECOidTag bulkalgtag; + int keysize; +}; + +static SecCmsMessageRef decode(FILE *out, CSSM_DATA *output, CSSM_DATA *input, + const struct decodeOptionsStr *decodeOptions) +{ + SecCmsDecoderRef dcx; + SecCmsMessageRef cmsg=NULL; + SecCmsContentInfoRef cinfo; + SecCmsSignedDataRef sigd = NULL; + SecCmsEnvelopedDataRef envd; + SecCmsEncryptedDataRef encd; + SECAlgorithmID **digestalgs; + int nlevels, i, nsigners, j; + CFStringRef signercn; + SecCmsSignerInfoRef si; + SECOidTag typetag; + CSSM_DATA **digests; + SecArenaPoolRef poolp = NULL; + PK11PasswordFunc pwcb; + void *pwcb_arg; + CSSM_DATA *item, sitem = { 0, }; + CFTypeRef policy = NULL; + OSStatus rv; + + pwcb = (PK11PasswordFunc)((decodeOptions->options->password != NULL) ? ownpw : NULL); + pwcb_arg = (decodeOptions->options->password != NULL) ? + (void *)decodeOptions->options->password : NULL; + + if (decodeOptions->contentFile) // detached content: grab content file + SECU_FileToItem(&sitem, decodeOptions->contentFile); + + SEC_CHECK(SecCmsDecoderCreate(NULL, + NULL, NULL, /* content callback */ + pwcb, pwcb_arg, /* password callback */ + decodeOptions->dkcb, /* decrypt key callback */ + decodeOptions->bulkkey, + &dcx), + "failed to create to decoder"); + SEC_CHECK(do_update((update_func *)SecCmsDecoderUpdate, dcx, input->Data, input->Length), + "failed to add data to decoder"); + SEC_CHECK(SecCmsDecoderFinish(dcx, &cmsg), + "failed to decode message"); + + if (decodeOptions->headerLevel >= 0) + { + /*fprintf(out, "SMIME: ", decodeOptions->headerLevel, i);*/ + fprintf(out, "SMIME: "); + } + + nlevels = SecCmsMessageContentLevelCount(cmsg); + for (i = 0; i < nlevels; i++) + { + cinfo = SecCmsMessageContentLevel(cmsg, i); + typetag = SecCmsContentInfoGetContentTypeTag(cinfo); + + if (decodeOptions->headerLevel >= 0) + fprintf(out, "\tlevel=%d.%d; ", decodeOptions->headerLevel, nlevels - i); + + switch (typetag) + { + case SEC_OID_PKCS7_SIGNED_DATA: + if (decodeOptions->headerLevel >= 0) + fprintf(out, "type=signedData; "); + + SEC_CHECK0(sigd = (SecCmsSignedDataRef )SecCmsContentInfoGetContent(cinfo), + "problem finding signedData component"); + /* if we have a content file, but no digests for this signedData */ + if (decodeOptions->contentFile != NULL && !SecCmsSignedDataHasDigests(sigd)) + { + SEC_CHECK(SecArenaPoolCreate(1024, &poolp), "failed to create arenapool"); + digestalgs = SecCmsSignedDataGetDigestAlgs(sigd); + SEC_CHECK(DigestFile(poolp, &digests, &sitem, digestalgs), + "problem computing message digest"); + SEC_CHECK(SecCmsSignedDataSetDigests(sigd, digestalgs, digests), + "problem setting message digests"); + SecArenaPoolFree(poolp, false); + } + + policy = CERT_PolicyForCertUsage(decodeOptions->options->certUsage, NULL); + // import the certificates + SEC_CHECK(SecCmsSignedDataImportCerts(sigd,decodeOptions->options->certDBHandle, + decodeOptions->options->certUsage, true /* false */), + "cert import failed"); + + /* find out about signers */ + nsigners = SecCmsSignedDataSignerInfoCount(sigd); + if (decodeOptions->headerLevel >= 0) + fprintf(out, "nsigners=%d; ", nsigners); + if (nsigners == 0) + { + /* must be a cert transport message */ + OSStatus rv; + /* XXX workaround for bug #54014 */ + SecCmsSignedDataImportCerts(sigd,decodeOptions->options->certDBHandle, + decodeOptions->options->certUsage,true); + SEC_CHECK(SecCmsSignedDataVerifyCertsOnly(sigd,decodeOptions->options->certDBHandle, policy), + "verify certs-only failed"); + return cmsg; + } + + SEC_CHECK0(SecCmsSignedDataHasDigests(sigd), "message has no digests"); + for (j = 0; j < nsigners; j++) + { + si = SecCmsSignedDataGetSignerInfo(sigd, j); + signercn = SecCmsSignerInfoGetSignerCommonName(si); + if (decodeOptions->headerLevel >= 0) + { + const char *px = signercn ? CFStringGetCStringPtr(signercn,kCFStringEncodingMacRoman) : ""; + fprintf(out, "\n\t\tsigner%d.id=\"%s\"; ", j, px); + } + SecCmsSignedDataVerifySignerInfo(sigd, j, decodeOptions->options->certDBHandle, + policy, NULL); + if (decodeOptions->headerLevel >= 0) + fprintf(out, "signer%d.status=%s; ", j, + SecCmsUtilVerificationStatusToString(SecCmsSignerInfoGetVerificationStatus(si))); + /* XXX what do we do if we don't print headers? */ + } + break; + case SEC_OID_PKCS7_ENVELOPED_DATA: + if (decodeOptions->headerLevel >= 0) + fprintf(out, "type=envelopedData; "); + envd = (SecCmsEnvelopedDataRef )SecCmsContentInfoGetContent(cinfo); + break; + case SEC_OID_PKCS7_ENCRYPTED_DATA: + if (decodeOptions->headerLevel >= 0) + fprintf(out, "type=encryptedData; "); + encd = (SecCmsEncryptedDataRef )SecCmsContentInfoGetContent(cinfo); + break; + case SEC_OID_PKCS7_DATA: + if (decodeOptions->headerLevel >= 0) + fprintf(out, "type=data; "); + break; + default: + break; + } + if (decodeOptions->headerLevel >= 0) + fprintf(out, "\n"); + } + + if (!decodeOptions->suppressContent) + { + item = decodeOptions->contentFile ? &sitem : + SecCmsMessageGetContent(cmsg); + /* Copy the data. */ + output->Length = item->Length; + output->Data = malloc(output->Length); + memcpy(output->Data, item->Data, output->Length); + } + + if (policy) CFRelease(policy); + + return cmsg; +loser: + if (policy) CFRelease(policy); + if (cmsg) SecCmsMessageDestroy(cmsg); + return NULL; +} + +/* example of a callback function to use with encoder */ +/* +static void +writeout(void *arg, const char *buf, unsigned long len) +{ + FILE *f = (FILE *)arg; + + if (f != NULL && buf != NULL) + (void)fwrite(buf, len, 1, f); +} +*/ + +static SecCmsMessageRef signed_data(struct signOptionsStr *signOptions) +{ + SecCmsMessageRef cmsg = NULL; + SecCmsContentInfoRef cinfo; + SecCmsSignedDataRef sigd; + SecCmsSignerInfoRef signerinfo; + SecIdentityRef identity = NULL; + SecCertificateRef cert = NULL, ekpcert = NULL; + OSStatus rv; + + if (cms_verbose) + { + fprintf(stderr, "Input to signed_data:\n"); + if (signOptions->options->password) + fprintf(stderr, "password [%s]\n", "***" /*signOptions->options->password*/); + else + fprintf(stderr, "password [NULL]\n"); + fprintf(stderr, "certUsage [%d]\n", signOptions->options->certUsage); + if (signOptions->options->certDBHandle) + fprintf(stderr, "certdb [%p]\n", signOptions->options->certDBHandle); + else + fprintf(stderr, "certdb [NULL]\n"); + if (signOptions->nickname) + fprintf(stderr, "nickname [%s]\n", signOptions->nickname); + else + fprintf(stderr, "nickname [NULL]\n"); + if (signOptions->subjectKeyID) + fprintf(stderr, "subject Key ID [%s]\n", signOptions->subjectKeyID); + } + + if (signOptions->subjectKeyID) + { + if ((identity = CERT_FindIdentityBySubjectKeyID(signOptions->options->certDBHandle, + signOptions->subjectKeyID)) == NULL) + { + sec_error("could not find signing identity for subject key ID: \"%s\"", signOptions->subjectKeyID); + return NULL; + } + + if (cms_verbose) + fprintf(stderr, "Found identity for subject key ID %s\n", signOptions->subjectKeyID); + } + else if (signOptions->nickname) + { + if ((identity = CERT_FindIdentityByUsage(signOptions->options->certDBHandle, + signOptions->nickname, + signOptions->options->certUsage, + false)) == NULL) + { + // look for identity by common name rather than email address + if ((identity = find_identity(signOptions->options->certDBHandle, + signOptions->nickname, + NULL, + signOptions->options->certUsage)) == NULL) + { + sec_error("could not find signing identity for name: \"%s\"", signOptions->nickname); + return NULL; + } + } + + if (cms_verbose) + fprintf(stderr, "Found identity for %s\n", signOptions->nickname); + } + else + { + // no identity was specified + sec_error("no signing identity was specified"); + return NULL; + } + + // Get the cert from the identity + SEC_CHECK(SecIdentityCopyCertificate(identity, &cert), + "SecIdentityCopyCertificate"); + // create the message object on its own pool + SEC_CHECK0(cmsg = SecCmsMessageCreate(NULL), "cannot create CMS message"); + // build chain of objects: message->signedData->data + SEC_CHECK0(sigd = SecCmsSignedDataCreate(cmsg), + "cannot create CMS signedData object"); + SEC_CHECK0(cinfo = SecCmsMessageGetContentInfo(cmsg), + "message has no content info"); + SEC_CHECK(SecCmsContentInfoSetContentSignedData(cmsg, cinfo, sigd), + "cannot attach CMS signedData object"); + SEC_CHECK0(cinfo = SecCmsSignedDataGetContentInfo(sigd), + "signed data has no content info"); + /* we're always passing data in and detaching optionally */ + SEC_CHECK(SecCmsContentInfoSetContentData(cmsg, cinfo, NULL, signOptions->detached), + "cannot attach CMS data object"); + // create & attach signer information + SEC_CHECK0(signerinfo = SecCmsSignerInfoCreate(cmsg, identity, signOptions->hashAlgTag), + "cannot create CMS signerInfo object"); + if (cms_verbose) + fprintf(stderr,"Created CMS message, added signed data w/ signerinfo\n"); + + // we want the cert chain included for this one + SEC_CHECK(SecCmsSignerInfoIncludeCerts(signerinfo, SecCmsCMCertChain, signOptions->options->certUsage), + "cannot add cert chain"); + + if (cms_verbose) + fprintf(stderr, "imported certificate\n"); + + if (signOptions->signingTime) + SEC_CHECK(SecCmsSignerInfoAddSigningTime(signerinfo, CFAbsoluteTimeGetCurrent()), + "cannot add signingTime attribute"); + + if (signOptions->smimeProfile) + SEC_CHECK(SecCmsSignerInfoAddSMIMECaps(signerinfo), + "cannot add SMIMECaps attribute"); + + if (signOptions->wantTimestamping) + { + CFErrorRef error = NULL; + SecCmsMessageSetTSAContext(cmsg, SecCmsTSAGetDefaultContext(&error)); + } + + if (!signOptions->encryptionKeyPreferenceNick) + { + /* check signing cert for fitness as encryption cert */ + OSStatus FitForEncrypt = CERT_CheckCertUsage(cert, certUsageEmailRecipient); + + if (noErr == FitForEncrypt) + { + /* if yes, add signing cert as EncryptionKeyPreference */ + SEC_CHECK(SecCmsSignerInfoAddSMIMEEncKeyPrefs(signerinfo, cert, signOptions->options->certDBHandle), + "cannot add default SMIMEEncKeyPrefs attribute"); + SEC_CHECK(SecCmsSignerInfoAddMSSMIMEEncKeyPrefs(signerinfo, cert, signOptions->options->certDBHandle), + "cannot add default MS SMIMEEncKeyPrefs attribute"); + } + else + { + /* this is a dual-key cert case, we need to look for the encryption + certificate under the same nickname as the signing cert */ + /* get the cert, add it to the message */ + if ((ekpcert = CERT_FindUserCertByUsage( + signOptions->options->certDBHandle, + signOptions->nickname, + certUsageEmailRecipient, + false)) == NULL) + { + sec_error("can find encryption cert for \"%s\"", signOptions->nickname); + goto loser; + } + + SEC_CHECK(SecCmsSignerInfoAddSMIMEEncKeyPrefs(signerinfo, ekpcert,signOptions->options->certDBHandle), + "cannot add SMIMEEncKeyPrefs attribute"); + SEC_CHECK(SecCmsSignerInfoAddMSSMIMEEncKeyPrefs(signerinfo, ekpcert,signOptions->options->certDBHandle), + "cannot add MS SMIMEEncKeyPrefs attribute"); + SEC_CHECK(SecCmsSignedDataAddCertificate(sigd, ekpcert), + "cannot add encryption certificate"); + } + } + else if (strcmp(signOptions->encryptionKeyPreferenceNick, "NONE") == 0) + { + /* No action */ + } + else + { + /* specific email address for encryption preferred encryption cert specified. + get the cert, add it to the message */ + if ((ekpcert = CERT_FindUserCertByUsage( + signOptions->options->certDBHandle, + signOptions->encryptionKeyPreferenceNick, + certUsageEmailRecipient, false)) == NULL) + { + sec_error("can find encryption cert for \"%s\"", signOptions->encryptionKeyPreferenceNick); + goto loser; + } + + SEC_CHECK(SecCmsSignerInfoAddSMIMEEncKeyPrefs(signerinfo, ekpcert,signOptions->options->certDBHandle), + "cannot add SMIMEEncKeyPrefs attribute"); + SEC_CHECK(SecCmsSignerInfoAddMSSMIMEEncKeyPrefs(signerinfo, ekpcert,signOptions->options->certDBHandle), + "cannot add MS SMIMEEncKeyPrefs attribute"); + SEC_CHECK(SecCmsSignedDataAddCertificate(sigd, ekpcert), + "cannot add encryption certificate"); + } + + SEC_CHECK(SecCmsSignedDataAddSignerInfo(sigd, signerinfo), + "cannot add CMS signerInfo object"); + + if (cms_verbose) + fprintf(stderr, "created signed-data message\n"); + + if (ekpcert) CFRelease(ekpcert); + if (cert) CFRelease(cert); + if (identity) CFRelease(identity); + return cmsg; + +loser: + if (ekpcert) CFRelease(ekpcert); + if (cert) CFRelease(cert); + if (identity) CFRelease(identity); + SecCmsMessageDestroy(cmsg); + return NULL; +} + +static SecCmsMessageRef enveloped_data(struct envelopeOptionsStr *envelopeOptions) +{ + SecCmsMessageRef cmsg = NULL; + SecCmsContentInfoRef cinfo; + SecCmsEnvelopedDataRef envd; + SecCmsRecipientInfoRef recipientinfo; + SecCertificateRef *recipientcerts = NULL; + SecKeychainRef dbhandle; + SECOidTag bulkalgtag; + OSStatus rv; + int keysize, i = 0; + int cnt; + + dbhandle = envelopeOptions->options->certDBHandle; + /* count the recipients */ + SEC_CHECK0(cnt = nss_CMSArray_Count((void **)envelopeOptions->recipients), + "please name at least one recipient"); + + // @@@ find the recipient's certs by email address or nickname + if ((recipientcerts = (SecCertificateRef *)calloc((cnt+1), sizeof(SecCertificateRef))) == NULL) + { + sec_error("failed to alloc certs array: %s", strerror(errno)); + goto loser; + } + + for (i = 0; envelopeOptions->recipients[i] != NULL; ++i) + { + if ((recipientcerts[i] = + CERT_FindCertByNicknameOrEmailAddr(dbhandle, envelopeOptions->recipients[i])) == NULL) + { + i = 0; + goto loser; + } + } + + recipientcerts[i] = NULL; + i = 0; + + // find a nice bulk algorithm + SEC_CHECK(SecSMIMEFindBulkAlgForRecipients(recipientcerts, &bulkalgtag, &keysize), + "cannot find common bulk algorithm"); + // create the message object on its own pool + SEC_CHECK0(cmsg = SecCmsMessageCreate(NULL), "cannot create CMS message"); + // build chain of objects: message->envelopedData->data + SEC_CHECK0(envd = SecCmsEnvelopedDataCreate(cmsg, bulkalgtag, keysize), + "cannot create CMS envelopedData object"); + SEC_CHECK0(cinfo = SecCmsMessageGetContentInfo(cmsg), + "message has no content info"); + SEC_CHECK(SecCmsContentInfoSetContentEnvelopedData(cmsg, cinfo, envd), + "cannot attach CMS envelopedData object"); + SEC_CHECK0(cinfo = SecCmsEnvelopedDataGetContentInfo(envd), + "enveloped data has no content info"); + // We're always passing data in, so the content is NULL + SEC_CHECK(SecCmsContentInfoSetContentData(cmsg, cinfo, NULL, false), + "cannot attach CMS data object"); + + // create & attach recipient information + for (i = 0; recipientcerts[i] != NULL; i++) + { + SEC_CHECK0(recipientinfo = SecCmsRecipientInfoCreate(cmsg, recipientcerts[i]), + "cannot create CMS recipientInfo object"); + SEC_CHECK(SecCmsEnvelopedDataAddRecipient(envd, recipientinfo), + "cannot add CMS recipientInfo object"); + CFRelease(recipientcerts[i]); + } + + if (recipientcerts) + free(recipientcerts); + + return cmsg; +loser: + if (recipientcerts) + { + for (; recipientcerts[i] != NULL; i++) + CFRelease(recipientcerts[i]); + } + + if (cmsg) + SecCmsMessageDestroy(cmsg); + + if (recipientcerts) + free(recipientcerts); + + return NULL; +} + +static SecSymmetricKeyRef dkcb(void *arg, SECAlgorithmID *algid) +{ + return (SecSymmetricKeyRef)arg; +} + +static OSStatus get_enc_params(struct encryptOptionsStr *encryptOptions) +{ + struct envelopeOptionsStr envelopeOptions; + OSStatus rv = paramErr; + SecCmsMessageRef env_cmsg = NULL; + SecCmsContentInfoRef cinfo; + int i, nlevels; + + // construct an enveloped data message to obtain bulk keys + if (encryptOptions->envmsg) + env_cmsg = encryptOptions->envmsg; // get it from an old message + else + { + CSSM_DATA dummyOut = { 0, }; + CSSM_DATA dummyIn = { 0, }; + char str[] = "Hello!"; + SecArenaPoolRef tmparena = NULL; + + SEC_CHECK(SecArenaPoolCreate(1024, &tmparena), "failed to create arenapool"); + + dummyIn.Data = (unsigned char *)str; + dummyIn.Length = strlen(str); + envelopeOptions.options = encryptOptions->options; + envelopeOptions.recipients = encryptOptions->recipients; + env_cmsg = enveloped_data(&envelopeOptions); + SecCmsMessageEncode(env_cmsg, &dummyIn, tmparena, &dummyOut); + fwrite(dummyOut.Data, 1, dummyOut.Length,encryptOptions->envFile); + + SecArenaPoolFree(tmparena, false); + } + + // get the content info for the enveloped data + nlevels = SecCmsMessageContentLevelCount(env_cmsg); + for (i = 0; i < nlevels; i++) + { + SECOidTag typetag; + cinfo = SecCmsMessageContentLevel(env_cmsg, i); + typetag = SecCmsContentInfoGetContentTypeTag(cinfo); + if (typetag == SEC_OID_PKCS7_DATA) + { + // get the symmetric key + encryptOptions->bulkalgtag = SecCmsContentInfoGetContentEncAlgTag(cinfo); + encryptOptions->keysize = SecCmsContentInfoGetBulkKeySize(cinfo); + encryptOptions->bulkkey = SecCmsContentInfoGetBulkKey(cinfo); + rv = noErr; + break; + } + } + if (i == nlevels) + sec_error("could not retrieve enveloped data: messsage has: %ld levels", nlevels); + +loser: + if (env_cmsg) + SecCmsMessageDestroy(env_cmsg); + + return rv; +} + +static SecCmsMessageRef encrypted_data(struct encryptOptionsStr *encryptOptions) +{ + OSStatus rv = paramErr; + SecCmsMessageRef cmsg = NULL; + SecCmsContentInfoRef cinfo; + SecCmsEncryptedDataRef encd; + SecCmsEncoderRef ecx = NULL; + SecArenaPoolRef tmppoolp = NULL; + CSSM_DATA derOut = { 0, }; + + /* arena for output */ + SEC_CHECK(SecArenaPoolCreate(1024, &tmppoolp), "failed to create arenapool"); + // create the message object on its own pool + SEC_CHECK0(cmsg = SecCmsMessageCreate(NULL), "cannot create CMS message"); + // build chain of objects: message->encryptedData->data + SEC_CHECK0(encd = SecCmsEncryptedDataCreate(cmsg, encryptOptions->bulkalgtag, + encryptOptions->keysize), + "cannot create CMS encryptedData object"); + SEC_CHECK0(cinfo = SecCmsMessageGetContentInfo(cmsg), + "message has no content info"); + SEC_CHECK(SecCmsContentInfoSetContentEncryptedData(cmsg, cinfo, encd), + "cannot attach CMS encryptedData object"); + SEC_CHECK0(cinfo = SecCmsEncryptedDataGetContentInfo(encd), + "encrypted data has no content info"); + /* we're always passing data in, so the content is NULL */ + SEC_CHECK(SecCmsContentInfoSetContentData(cmsg, cinfo, NULL, false), + "cannot attach CMS data object"); + SEC_CHECK(SecCmsEncoderCreate(cmsg, NULL, NULL, &derOut, tmppoolp, NULL, NULL, + dkcb, encryptOptions->bulkkey, NULL, NULL, &ecx), + "cannot create encoder context"); + SEC_CHECK(do_update((update_func *)SecCmsEncoderUpdate, ecx, encryptOptions->input->Data, + encryptOptions->input->Length), + "failed to add data to encoder"); + SEC_CHECK(SecCmsEncoderFinish(ecx), "failed to encrypt data"); + fwrite(derOut.Data, derOut.Length, 1, encryptOptions->outfile); + /* @@@ Check and report write errors. */ + /* + if (bulkkey) + CFRelease(bulkkey); + */ + + if (tmppoolp) + SecArenaPoolFree(tmppoolp, false); + return cmsg; +loser: + /* + if (bulkkey) + CFRelease(bulkkey); + */ + if (tmppoolp) + SecArenaPoolFree(tmppoolp, false); + if (cmsg) + SecCmsMessageDestroy(cmsg); + + return NULL; +} + +static SecCmsMessageRef signed_data_certsonly(struct certsonlyOptionsStr *certsonlyOptions) +{ + SecCmsMessageRef cmsg = NULL; + SecCmsContentInfoRef cinfo; + SecCmsSignedDataRef sigd; + SecCertificateRef *certs = NULL; + SecKeychainRef dbhandle; + OSStatus rv; + + int i = 0, cnt; + dbhandle = certsonlyOptions->options->certDBHandle; + SEC_CHECK0(cnt = nss_CMSArray_Count((void**)certsonlyOptions->recipients), + "please indicate the nickname of a certificate to sign with"); + if ((certs = (SecCertificateRef *)calloc((cnt+1), sizeof(SecCertificateRef))) == NULL) + { + sec_error("failed to alloc certs array: %s", strerror(errno)); + goto loser; + } + for (i=0; certsonlyOptions->recipients && certsonlyOptions->recipients[i] != NULL; i++) + { + if ((certs[i] = CERT_FindCertByNicknameOrEmailAddr(dbhandle,certsonlyOptions->recipients[i])) == NULL) + { + i=0; + goto loser; + } + } + certs[i] = NULL; + i = 0; + // create the message object on its own pool + SEC_CHECK0(cmsg = SecCmsMessageCreate(NULL), "cannot create CMS message"); + // build chain of objects: message->signedData->data + SEC_CHECK0(sigd = SecCmsSignedDataCreateCertsOnly(cmsg, certs[0], true), + "cannot create certs only CMS signedData object"); + CFRelease(certs[0]); + for (i = 1; i < cnt; ++i) + { + SEC_CHECK2(SecCmsSignedDataAddCertChain(sigd, certs[i]), + "cannot add cert chain for \"%s\"", certsonlyOptions->recipients[i]); + CFRelease(certs[i]); + } + + SEC_CHECK0(cinfo = SecCmsMessageGetContentInfo(cmsg), + "message has no content info"); + SEC_CHECK(SecCmsContentInfoSetContentSignedData(cmsg, cinfo, sigd), + "cannot attach CMS signedData object"); + SEC_CHECK0(cinfo = SecCmsSignedDataGetContentInfo(sigd), + "signed data has no content info"); + SEC_CHECK(SecCmsContentInfoSetContentData(cmsg, cinfo, NULL, false), + "cannot attach CMS data object"); + + if (certs) + free(certs); + + return cmsg; +loser: + if (certs) + { + for (; i < cnt; ++i) + CFRelease(certs[i]); + + free(certs); + } + if (cmsg) SecCmsMessageDestroy(cmsg); + + return NULL; +} + +typedef enum { UNKNOWN, DECODE, SIGN, ENCRYPT, ENVELOPE, CERTSONLY } Mode; + +int cms_util(int argc, char **argv) +{ + FILE *outFile; + SecCmsMessageRef cmsg = NULL; + FILE *inFile; + int ch; + Mode mode = UNKNOWN; + PK11PasswordFunc pwcb; + void *pwcb_arg; + struct decodeOptionsStr decodeOptions = { 0 }; + struct signOptionsStr signOptions = { 0 }; + struct envelopeOptionsStr envelopeOptions = { 0 }; + struct certsonlyOptionsStr certsonlyOptions = { 0 }; + struct encryptOptionsStr encryptOptions = { 0 }; + struct optionsStr options = { 0 }; + int result = 1; + static char *ptrarray[128] = { 0 }; + int nrecipients = 0; + char *str, *tok; + char *envFileName; + const char *keychainName = NULL; + CSSM_DATA input = { 0,}; + CSSM_DATA output = { 0,}; + CSSM_DATA dummy = { 0, }; + CSSM_DATA envmsg = { 0, }; + OSStatus rv; + + inFile = stdin; + outFile = stdout; + envFileName = NULL; + mode = UNKNOWN; + decodeOptions.contentFile = NULL; + decodeOptions.suppressContent = false; + decodeOptions.headerLevel = -1; + options.certUsage = certUsageEmailSigner; + options.password = NULL; + signOptions.nickname = NULL; + signOptions.subjectKeyID = NULL; + signOptions.detached = false; + signOptions.signingTime = false; + signOptions.smimeProfile = false; + signOptions.encryptionKeyPreferenceNick = NULL; + signOptions.hashAlgTag = SEC_OID_SHA1; + envelopeOptions.recipients = NULL; + encryptOptions.recipients = NULL; + encryptOptions.envmsg = NULL; + encryptOptions.envFile = NULL; + encryptOptions.bulkalgtag = SEC_OID_UNKNOWN; + encryptOptions.bulkkey = NULL; + encryptOptions.keysize = -1; + + // Parse command line arguments + while ((ch = getopt(argc, argv, "CDEGH:N:OPSTY:Z:c:de:h:i:k:no:p:r:su:vt:")) != -1) + { + switch (ch) + { + case 'C': + mode = ENCRYPT; + break; + case 'D': + mode = DECODE; + break; + case 'E': + mode = ENVELOPE; + break; + case 'G': + if (mode != SIGN) { + sec_error("option -G only supported with option -S"); + result = 2; /* Trigger usage message. */ + goto loser; + } + signOptions.signingTime = true; + break; + case 'H': + if (mode != SIGN) { + sec_error("option -n only supported with option -D"); + result = 2; /* Trigger usage message. */ + goto loser; + } + decodeOptions.suppressContent = true; + if (!strcmp(optarg, "MD2")) + signOptions.hashAlgTag = SEC_OID_MD2; + else if (!strcmp(optarg, "MD4")) + signOptions.hashAlgTag = SEC_OID_MD4; + else if (!strcmp(optarg, "MD5")) + signOptions.hashAlgTag = SEC_OID_MD5; + else if (!strcmp(optarg, "SHA1")) + signOptions.hashAlgTag = SEC_OID_SHA1; + else if (!strcmp(optarg, "SHA256")) + signOptions.hashAlgTag = SEC_OID_SHA256; + else if (!strcmp(optarg, "SHA384")) + signOptions.hashAlgTag = SEC_OID_SHA384; + else if (!strcmp(optarg, "SHA512")) + signOptions.hashAlgTag = SEC_OID_SHA512; + else { + sec_error("option -H requires one of MD2,MD4,MD5,SHA1,SHA256,SHA384,SHA512"); + goto loser; + } + break; + case 'N': + if (mode != SIGN) { + sec_error("option -N only supported with option -S"); + result = 2; /* Trigger usage message. */ + goto loser; + } + signOptions.nickname = strdup(optarg); + break; + case 'O': + mode = CERTSONLY; + break; + case 'P': + if (mode != SIGN) { + sec_error("option -P only supported with option -S"); + result = 2; /* Trigger usage message. */ + goto loser; + } + signOptions.smimeProfile = true; + break; + case 'S': + mode = SIGN; + break; + case 'T': + if (mode != SIGN) { + sec_error("option -T only supported with option -S"); + result = 2; /* Trigger usage message. */ + goto loser; + } + signOptions.detached = true; + break; + case 'Y': + if (mode != SIGN) { + sec_error("option -Y only supported with option -S"); + result = 2; /* Trigger usage message. */ + goto loser; + } + signOptions.encryptionKeyPreferenceNick = strdup(optarg); + break; + + case 'c': + if (mode != DECODE) + { + sec_error("option -c only supported with option -D"); + result = 2; /* Trigger usage message. */ + goto loser; + } + if ((decodeOptions.contentFile = fopen(optarg, "rb")) == NULL) + { + sec_error("unable to open \"%s\" for reading: %s", optarg, strerror(errno)); + result = 1; + goto loser; + } + break; + +#ifdef HAVE_DODUMPSTATES + case 'd': + doDumpStates++; + break; +#endif /* HAVE_DODUMPSTATES */ + + case 'e': + envFileName = strdup(optarg); + encryptOptions.envFile = fopen(envFileName, "rb"); // PR_RDONLY, 00660); + break; + + case 'h': + if (mode != DECODE) { + sec_error("option -h only supported with option -D"); + result = 2; /* Trigger usage message. */ + goto loser; + } + decodeOptions.headerLevel = atoi(optarg); + if (decodeOptions.headerLevel < 0) { + sec_error("option -h cannot have a negative value"); + goto loser; + } + break; + case 'i': + inFile = fopen(optarg,"rb"); // PR_RDONLY, 00660); + if (inFile == NULL) + { + sec_error("unable to open \"%s\" for reading: %s", optarg, strerror(errno)); + goto loser; + } + break; + + case 'k': + keychainName = optarg; + break; + + case 'n': + if (mode != DECODE) + { + sec_error("option -n only supported with option -D"); + result = 2; /* Trigger usage message. */ + goto loser; + } + decodeOptions.suppressContent = true; + break; + case 'o': + outFile = fopen(optarg, "wb"); + if (outFile == NULL) + { + sec_error("unable to open \"%s\" for writing: %s", optarg, strerror(errno)); + goto loser; + } + break; + case 'p': + if (!optarg) + { + sec_error("option -p must have a value"); + result = 2; /* Trigger usage message. */ + goto loser; + } + + options.password = (PK11PasswordFunc)ownpw;//strdup(optarg); + break; + + case 'r': + if (!optarg) + { + sec_error("option -r must have a value"); + result = 2; /* Trigger usage message. */ + goto loser; + } + + envelopeOptions.recipients = ptrarray; + str = (char *)optarg; + do { + tok = strchr(str, ','); + if (tok) *tok = '\0'; + envelopeOptions.recipients[nrecipients++] = strdup(str); + if (tok) str = tok + 1; + } while (tok); + envelopeOptions.recipients[nrecipients] = NULL; + encryptOptions.recipients = envelopeOptions.recipients; + certsonlyOptions.recipients = envelopeOptions.recipients; + break; + + case 's': + cms_update_single_byte = 1; + break; + + case 'Z': + if (!optarg) + { + sec_error("option -Z must have a value"); + result = 2; /* Trigger usage message. */ + goto loser; + } + signOptions.subjectKeyID = strdup(optarg); + + break; + + case 'u': + { + int usageType = atoi (strdup(optarg)); + if (usageType < certUsageSSLClient || usageType > certUsageAnyCA) + { + result = 1; + goto loser; + } + options.certUsage = (SECCertUsage)usageType; + break; + } + case 'v': + cms_verbose = 1; + break; + case 't': + if (optarg) + signOptions.timestampingURL = strdup(optarg); + signOptions.wantTimestamping = true; + break; + default: + result = 2; /* Trigger usage message. */ + goto loser; + } + } + + argc -= optind; + argv += optind; + + if (argc != 0 || mode == UNKNOWN) + { + result = 2; /* Trigger usage message. */ + goto loser; + } + + result = 0; + + if (mode != CERTSONLY) + SECU_FileToItem(&input, inFile); + if (inFile != stdin) + fclose(inFile); + if (cms_verbose) + fprintf(stderr, "received commands\n"); + + /* Call the libsec initialization routines */ + if (keychainName) + { + check_obsolete_keychain(keychainName); + options.certDBHandle = keychain_open(keychainName); + if (!options.certDBHandle) + { + sec_perror("SecKeychainOpen", errSecInvalidKeychain); + result = 1; + goto loser; + } + } + + if (cms_verbose) + fprintf(stderr, "Got default certdb\n"); + + switch (mode) + { + case DECODE: + decodeOptions.options = &options; + if (encryptOptions.envFile) + { + /* Decoding encrypted-data, so get the bulkkey from an + * enveloped-data message. + */ + SECU_FileToItem(&envmsg, encryptOptions.envFile); + decodeOptions.options = &options; + encryptOptions.envmsg = decode(NULL, &dummy, &envmsg, &decodeOptions); + if (!encryptOptions.envmsg) + { + sec_error("problem decoding env msg"); + result = 1; + break; + } + rv = get_enc_params(&encryptOptions); + decodeOptions.dkcb = dkcb; + decodeOptions.bulkkey = encryptOptions.bulkkey; + } + cmsg = decode(outFile, &output, &input, &decodeOptions); + if (!cmsg) + { + sec_error("problem decoding"); + result = 1; + } + fwrite(output.Data, output.Length, 1, outFile); + break; + case SIGN: + signOptions.options = &options; + cmsg = signed_data(&signOptions); + if (!cmsg) + { + sec_error("problem signing"); + result = 1; + } + break; + case ENCRYPT: + if (!envFileName) + { + sec_error("you must specify an envelope file with -e"); + result = 1; + goto loser; + } + encryptOptions.options = &options; + encryptOptions.input = &input; + encryptOptions.outfile = outFile; + if (!encryptOptions.envFile) { + encryptOptions.envFile = fopen(envFileName,"wb"); //PR_WRONLY|PR_CREATE_FILE, 00660); + if (!encryptOptions.envFile) + { + sec_error("failed to create file %s: %s", envFileName, strerror(errno)); + result = 1; + goto loser; + } + } + else + { + SECU_FileToItem(&envmsg, encryptOptions.envFile); + decodeOptions.options = &options; + encryptOptions.envmsg = decode(NULL, &dummy, &envmsg, + &decodeOptions); + if (encryptOptions.envmsg == NULL) + { + sec_error("problem decrypting env msg"); + result = 1; + break; + } + } + + /* decode an enveloped-data message to get the bulkkey (create + * a new one if neccessary) + */ + rv = get_enc_params(&encryptOptions); + /* create the encrypted-data message */ + cmsg = encrypted_data(&encryptOptions); + if (!cmsg) + { + sec_error("problem encrypting"); + result = 1; + } + + if (encryptOptions.bulkkey) + { + CFRelease(encryptOptions.bulkkey); + encryptOptions.bulkkey = NULL; + } + break; + case ENVELOPE: + envelopeOptions.options = &options; + cmsg = enveloped_data(&envelopeOptions); + if (!cmsg) + { + sec_error("problem enveloping"); + result = 1; + } + break; + case CERTSONLY: + certsonlyOptions.options = &options; + cmsg = signed_data_certsonly(&certsonlyOptions); + if (!cmsg) + { + sec_error("problem with certs-only"); + result = 1; + } + break; + case UNKNOWN: + /* Already handled above. */ + break; + } + + if ( (mode == SIGN || mode == ENVELOPE || mode == CERTSONLY) + && (!result) ) + { + SecArenaPoolRef arena = NULL; + SecCmsEncoderRef ecx; + CSSM_DATA output = {}; + + SEC_CHECK(SecArenaPoolCreate(1024, &arena), "failed to create arenapool"); + pwcb = (PK11PasswordFunc)((options.password != NULL) ? ownpw : NULL); + pwcb_arg = (options.password != NULL) ? (void *)options.password : NULL; + if (cms_verbose) { + fprintf(stderr, "cmsg [%p]\n", cmsg); + fprintf(stderr, "arena [%p]\n", arena); + if (pwcb_arg) + fprintf(stderr, "password [%s]\n", (char *)pwcb_arg); + else + fprintf(stderr, "password [NULL]\n"); + } + + SEC_CHECK(SecCmsEncoderCreate(cmsg, + NULL, NULL, /* DER output callback */ + &output, arena, /* destination storage */ + pwcb, pwcb_arg, /* password callback */ + NULL, NULL, /* decrypt key callback */ + NULL, NULL, /* detached digests */ + &ecx), + "cannot create encoder context"); + if (cms_verbose) + { + fprintf(stderr, "input len [%ld]\n", input.Length); + { + unsigned int j; + for (j = 0; j < input.Length; ++j) + fprintf(stderr, "%2x%c", input.Data[j], (j>0&&j%35==0)?'\n':' '); + } + } + + if (input.Length > 0) { /* skip if certs-only (or other zero content) */ + SEC_CHECK(SecCmsEncoderUpdate(ecx, (char *)input.Data, input.Length), + "failed to add data to encoder"); + } + + SEC_CHECK(SecCmsEncoderFinish(ecx), "failed to encode data"); + + if (cms_verbose) { + fprintf(stderr, "encoding passed\n"); + } + + /*PR_Write(output.data, output.len);*/ + fwrite(output.Data, output.Length, 1, outFile); + if (cms_verbose) { + fprintf(stderr, "wrote to file\n"); + } + SecArenaPoolFree(arena, false); + } + +loser: + if (cmsg) + SecCmsMessageDestroy(cmsg); + if (outFile != stdout) + fclose(outFile); + + if (decodeOptions.contentFile) + fclose(decodeOptions.contentFile); + + return result; +} + + +#pragma mark ================ Misc from NSS =================== +// from /security/nss/cmd/lib/secutil.c + +OSStatus +SECU_FileToItem(CSSM_DATA *dst, FILE *src) +{ + const int kReadSize = 4096; + size_t bytesRead, totalRead = 0; + + do + { + /* Make room in dst for the new data. */ + dst->Length += kReadSize; + dst->Data = realloc(dst->Data, dst->Length); + if (!dst->Data) + return 1 /* @@@ memFullErr */; + + bytesRead = fread (&dst->Data[totalRead], 1, kReadSize, src); + totalRead += bytesRead; + } while (bytesRead == kReadSize); + + if (!feof (src)) + { + /* We are here, but there's no EOF. This is bad */ + if (dst->Data) { + free(dst->Data); + dst->Data = NULL; + dst->Length = 0; + } + return 1 /* @@@ ioErr */; + } + + /* Trim down the buffer. */ + dst->Length = totalRead; + dst->Data = realloc(dst->Data, totalRead); + if (!dst->Data) + return 1 /* @@@ memFullErr */; + + return noErr; +} diff --git a/SecurityTool/cmsutil.h b/SecurityTool/cmsutil.h new file mode 100644 index 00000000..6b79b1ee --- /dev/null +++ b/SecurityTool/cmsutil.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2004,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@ + * + * cmsutil.h + */ + +#ifndef _CMSUTIL_H_ +#define _CMSUTIL_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int cms_util(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _CMSUTIL_H_ */ diff --git a/SecurityTool/config/debug.xcconfig b/SecurityTool/config/debug.xcconfig new file mode 100644 index 00000000..937d1775 --- /dev/null +++ b/SecurityTool/config/debug.xcconfig @@ -0,0 +1,3 @@ +GCC_OPTIMIZATION_LEVEL = 0 +GCC_PREPROCESSOR_DEFINITIONS = DEBUG=1 $(inherited) +COPY_PHASE_STRIP = NO diff --git a/SecurityTool/config/project.xcconfig b/SecurityTool/config/project.xcconfig new file mode 100644 index 00000000..39c7976a --- /dev/null +++ b/SecurityTool/config/project.xcconfig @@ -0,0 +1,25 @@ +ARCHS = $(ARCHS_STANDARD_32_64_BIT) +CODE_SIGN_IDENTITY = -; +GCC_VERSION = com.apple.compilers.llvm.clang.1_0 +DEBUG_INFORMATION_FORMAT = dwarf-with-dsym +SDKROOT = +CURRENT_PROJECT_VERSION = $(RC_ProjectSourceVersion) +VERSIONING_SYSTEM = apple-generic; +DEAD_CODE_STRIPPING = YES; + +FRAMEWORK_SEARCH_PATHS = $(SYSTEM_LIBRARY_DIR)/PrivateFrameworks + +PRODUCT_NAME = $(TARGET_NAME) + +ALWAYS_SEARCH_USER_PATHS = NO + +GCC_C_LANGUAGE_STANDARD = gnu99 + +WARNING_CFLAGS = -Wmost -Wno-four-char-constants -Wno-unknown-pragmas $(inherited) + +GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO + +GCC_WARN_64_TO_32_BIT_CONVERSION = YES +GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES +GCC_WARN_ABOUT_RETURN_TYPE = YES +GCC_WARN_UNUSED_VARIABLE = YES \ No newline at end of file diff --git a/SecurityTool/config/release.xcconfig b/SecurityTool/config/release.xcconfig new file mode 100644 index 00000000..dc5f8761 --- /dev/null +++ b/SecurityTool/config/release.xcconfig @@ -0,0 +1,3 @@ +GCC_PREPROCESSOR_DEFINITIONS = NDEBUG=1 $(inherited) +COPY_PHASE_STRIP = YES + diff --git a/SecurityTool/createFVMaster.c b/SecurityTool/createFVMaster.c new file mode 100644 index 00000000..e563c2fc --- /dev/null +++ b/SecurityTool/createFVMaster.c @@ -0,0 +1,790 @@ +/* + * Copyright (c) 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@ + * + * createFVMaster.c + */ + +#include "createFVMaster.h" + +#include "readline.h" +#include "security.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "srCdsaUtils.h" + +#include + +const char * const _masterKeychainName = "FileVaultMaster.keychain"; +const char * const _masterKeychainPath = "./FileVaultMaster"; + +/* + * Parameters used to create key pairs and certificates in + * SR_CertificateAndKeyCreate(). + */ +#define SR_KEY_ALGORITHM CSSM_ALGID_RSA +#define SR_KEY_SIZE_IN_BITS 1024 + +#define SR2_KEY_SIZE_IN_BITS 2048 // Recommended size for FileVault2 (FDE) + +/* + * The CSSM_ALGORITHMS and OID values defining the signature + * algorithm in the generated certificate. + */ +#define SR_CERT_SIGNATURE_ALGORITHM CSSM_ALGID_SHA1WithRSA +#define SR_CERT_SIGNATURE_ALG_OID CSSMOID_SHA1WithRSA + +OSStatus makeMasterPassword(const char *fvmkcName, const char *masterPasswordPassword, uint32 keySizeInBits, SecKeychainRef *keychainRef); + +OSStatus createPair(CFStringRef hostName,CFStringRef userName,SecKeychainRef keychainRef, uint32 keySizeInBits, CFDataRef *cert); +OSStatus generateKeyPair(CSSM_CSP_HANDLE cspHand, CSSM_DL_DB_HANDLE dlDbHand, CSSM_ALGORITHMS keyAlg, + uint32 keySizeInBits, const char *keyLabel, CSSM_KEY_PTR *pubKeyPtr, CSSM_KEY_PTR *privKeyPtr); +OSStatus createRootCert(CSSM_TP_HANDLE tpHand, CSSM_CL_HANDLE clHand, CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR subjPubKey, CSSM_KEY_PTR signerPrivKey, const char *hostName, const char *userName, + CSSM_ALGORITHMS sigAlg, const CSSM_OID *sigOid, CSSM_DATA_PTR certData); +void randUint32(uint32 *u); + +static char *secCopyCString(CFStringRef theString); + +OSStatus makeMasterPassword(const char *fvmkcName, const char *masterPasswordPassword, uint32 keySizeInBits, SecKeychainRef *keychainRef) +{ + /* + OSStatus SecFileVaultMakeMasterPassword(CFStringRef masterPasswordPassword); + + *** In the real code, this will be done directly rather than exec'ing a tool, since there are too many parameters to specify + *** this needs to be done as root, since the keychain will be a system keychain + /usr/bin/certtool y c k=/Library/Keychains/FileVaultMaster.keychain p= + /usr/bin/certtool c k=/Library/Keychains/FileVaultMaster.keychain o=/Library/Keychains/FileVaultMaster.cer + Two steps: create the keychain, then create the keypair + */ + + SecAccessRef initialAccess = NULL; + + if (!masterPasswordPassword) + { + sec_error("You must supply a non-empty password"); + return -2; + } + + // We return an error if the keychain already exists + OSStatus status = SecKeychainCreate(fvmkcName, strlen(masterPasswordPassword), masterPasswordPassword, false, initialAccess, keychainRef); + if (status!=noErr) + { + if (status==errSecDuplicateKeychain || status==CSSMERR_DL_DATASTORE_ALREADY_EXISTS) + sec_error("The keychain file %s already exists", fvmkcName); + return status; + } + + // Create the key pair + char host[PATH_MAX]; + int rx = gethostname(host, sizeof(host)); + if (rx) + strcpy(host, "localhost"); + + CFStringRef hostName = CFSTR("FileVault Recovery Key"); // This is what shows up in Keychain Access display + CFStringRef userName = CFStringCreateWithCString(kCFAllocatorDefault, host, kCFStringEncodingUTF8); + CFDataRef certData = NULL; + printf("Generating a %d bit key pair; this may take several minutes\n", keySizeInBits); + status = createPair(hostName,userName,*keychainRef,keySizeInBits, &certData); + if (status) + sec_error("Error in createPair: %s", sec_errstr(status)); + if (certData) + CFRelease(certData); + + return status; +} + +OSStatus createPair(CFStringRef hostName,CFStringRef userName,SecKeychainRef keychainRef, uint32 keySizeInBits, CFDataRef *cert) +{ + SecCertificateRef certRef = NULL; + CSSM_DL_DB_HANDLE dlDbHand = {0, 0}; + CSSM_CSP_HANDLE cspHand = 0; + CSSM_TP_HANDLE tpHand = 0; + CSSM_CL_HANDLE clHand = 0; + CSSM_KEY_PTR pubKey = NULL; + CSSM_KEY_PTR privKey = NULL; + CSSM_DATA certData = {0, NULL}; + char *hostStr = NULL; + char *userStr = NULL; + OSStatus ortn; + CSSM_OID algOid = SR_CERT_SIGNATURE_ALG_OID; + + hostStr = secCopyCString(hostName); + userStr = secCopyCString(userName); + if (!hostStr || !userStr) // could not convert to UTF-8 + { + ortn = paramErr; + goto xit; + } + + // open keychain, connect to all the CDSA modules we'll need + + ortn = SecKeychainGetCSPHandle(keychainRef, &cspHand); + if (ortn) + goto xit; + + ortn = SecKeychainGetDLDBHandle(keychainRef, &dlDbHand); + if (ortn) + goto xit; + + tpHand = srTpStartup(); + if (tpHand == 0) + { + ortn = ioErr; + goto xit; + } + + clHand = srClStartup(); + if (clHand == 0) + { + ortn = ioErr; + goto xit; + } + + // generate key pair, private key stored in keychain + ortn = generateKeyPair(cspHand, dlDbHand, SR_KEY_ALGORITHM, keySizeInBits, + "FileVault Master Password Key", &pubKey, &privKey); + if (ortn) + goto xit; + + // generate the cert + ortn = createRootCert(tpHand,clHand,cspHand,pubKey,privKey,hostStr,userStr, + SR_CERT_SIGNATURE_ALGORITHM,&algOid,&certData); + if (ortn) + goto xit; + + // store the cert in the same DL/DB as the key pair [see SecCertificateCreateFromData] + ortn = SecCertificateCreateFromData(&certData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &certRef); + if (ortn) + goto xit; + + ortn = SecCertificateAddToKeychain(certRef, keychainRef); + if (ortn) + goto xit; + + // return the cert to caller + *cert = CFDataCreate(NULL, certData.Data, certData.Length); + + // cleanup +xit: + if (certRef) + CFRelease(certRef); + if (certData.Data) + free(certData.Data); + if (hostStr) + free(hostStr); + if (userStr) + free(userStr); + if (tpHand) + CSSM_ModuleDetach(tpHand); + if (clHand) + CSSM_ModuleDetach(clHand); + if (pubKey) + { + CSSM_FreeKey(cspHand, + NULL, // access cred + pubKey, + CSSM_FALSE); // delete + APP_FREE(pubKey); + } + if (privKey) + { + CSSM_FreeKey(cspHand, + NULL, // access cred + privKey, + CSSM_FALSE); // delete + APP_FREE(privKey); + } + + return ortn; +} + +/* +* Given a CFStringRef, this function allocates and returns a pointer +* to a null-terminated 'C' string copy. If conversion of the string +* to UTF8 fails for some reason, the function will return NULL. +* +* The caller must free this pointer +*/ + +char *secCopyCString(CFStringRef theString) +{ + CFIndex maxLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(theString), kCFStringEncodingUTF8) + 1; + char* buffer = (char*) malloc(maxLength); + Boolean converted = CFStringGetCString(theString, buffer, maxLength, kCFStringEncodingUTF8); + if (!converted) { + free(buffer); + buffer = NULL; + } + return buffer; +} + + +#pragma mark -------------------- SecFileVaultCert private implementation -------------------- + +OSStatus createRootCert( + CSSM_TP_HANDLE tpHand, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR subjPubKey, + CSSM_KEY_PTR signerPrivKey, + const char *hostName, // CSSMOID_CommonName + const char *userName, // CSSMOID_Description + CSSM_ALGORITHMS sigAlg, + const CSSM_OID *sigOid, + CSSM_DATA_PTR certData) // mallocd and RETURNED +{ + CE_DataAndType exts[2]; + CE_DataAndType *extp = exts; + unsigned numExts; + CSSM_DATA refId; // mallocd by + // CSSM_TP_SubmitCredRequest + CSSM_APPLE_TP_CERT_REQUEST certReq; + CSSM_TP_REQUEST_SET reqSet; + sint32 estTime; + CSSM_BOOL confirmRequired; + CSSM_TP_RESULT_SET_PTR resultSet=NULL; + CSSM_ENCODED_CERT *encCert=NULL; + CSSM_APPLE_TP_NAME_OID subjectNames[2]; + CSSM_TP_CALLERAUTH_CONTEXT CallerAuthContext; + CSSM_FIELD policyId; + + numExts = 0; + + certReq.challengeString = NULL; + + /* KeyUsage extension */ + extp->type = DT_KeyUsage; + extp->critical = CSSM_FALSE; + extp->extension.keyUsage = CE_KU_DigitalSignature | + CE_KU_KeyCertSign | + CE_KU_KeyEncipherment | + CE_KU_DataEncipherment; + extp++; + numExts++; + + /* BasicConstraints */ + extp->type = DT_BasicConstraints; + extp->critical = CSSM_TRUE; + extp->extension.basicConstraints.cA = CSSM_FALSE; + extp->extension.basicConstraints.pathLenConstraintPresent = CSSM_FALSE; + extp++; + numExts++; + + /* name array */ + subjectNames[0].string = hostName; + subjectNames[0].oid = &CSSMOID_CommonName; + subjectNames[1].string = userName; + subjectNames[1].oid = &CSSMOID_Description; + + /* certReq */ + certReq.cspHand = cspHand; + certReq.clHand = clHand; + randUint32(&certReq.serialNumber); // random serial number + certReq.numSubjectNames = 2; + certReq.subjectNames = subjectNames; + + certReq.numIssuerNames = 0; // root for now + certReq.issuerNames = NULL; + certReq.issuerNameX509 = NULL; + certReq.certPublicKey = subjPubKey; + certReq.issuerPrivateKey = signerPrivKey; + certReq.signatureAlg = sigAlg; + certReq.signatureOid = *sigOid; + certReq.notBefore = 0; + certReq.notAfter = 60 * 60 * 24 * 365; // seconds from now, one year + certReq.numExtensions = numExts; + certReq.extensions = exts; + + reqSet.NumberOfRequests = 1; + reqSet.Requests = &certReq; + + /* a CSSM_TP_CALLERAUTH_CONTEXT to specify an OID */ + memset(&CallerAuthContext, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT)); + memset(&policyId, 0, sizeof(CSSM_FIELD)); + policyId.FieldOid = CSSMOID_APPLE_TP_LOCAL_CERT_GEN; + + CallerAuthContext.Policy.NumberOfPolicyIds = 1; + CallerAuthContext.Policy.PolicyIds = &policyId; + + CSSM_RETURN crtn = CSSM_TP_SubmitCredRequest(tpHand, + NULL, // PreferredAuthority + CSSM_TP_AUTHORITY_REQUEST_CERTISSUE, + &reqSet, + &CallerAuthContext, + &estTime, + &refId); + + if(crtn) { + sec_error("CSSM_TP_SubmitCredRequest: %s", sec_errstr(crtn)); + goto xit; + } + crtn = CSSM_TP_RetrieveCredResult(tpHand, + &refId, + NULL, // CallerAuthCredentials + &estTime, + &confirmRequired, + &resultSet); + if(crtn) { + sec_error("CSSM_TP_RetrieveCredResult: %s", sec_errstr(crtn)); + goto xit; + } + if(resultSet == NULL) { + sec_error("CSSM_TP_RetrieveCredResult: returned NULL result set"); + crtn = ioErr; + goto xit; + } + encCert = (CSSM_ENCODED_CERT *)resultSet->Results; + certData->Length = encCert->CertBlob.Length; + certData->Data = malloc(encCert->CertBlob.Length); + if (certData->Data) + memcpy(certData->Data, encCert->CertBlob.Data, encCert->CertBlob.Length); + crtn = noErr; + +xit: + /* free resources allocated by TP */ + APP_FREE(refId.Data); + if (encCert) + { + if (encCert->CertBlob.Data) + { + APP_FREE(encCert->CertBlob.Data); + } + APP_FREE(encCert); + } + APP_FREE(resultSet); + return crtn; +} + +/* Convert a reference key to a raw key. */ +static CSSM_RETURN refKeyToRaw( + CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *refKey, + CSSM_KEY_PTR rawKey) // RETURNED +{ + CSSM_CC_HANDLE ccHand; + CSSM_RETURN crtn; + CSSM_ACCESS_CREDENTIALS creds; + + memset(rawKey, 0, sizeof(CSSM_KEY)); + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + crtn = CSSM_CSP_CreateSymmetricContext(cspHand, + CSSM_ALGID_NONE, + CSSM_ALGMODE_NONE, + &creds, // passPhrase + NULL, // wrapping key + NULL, // init vector + CSSM_PADDING_NONE, // Padding + 0, // Params + &ccHand); + if(crtn) { + sec_error("CSSM_CSP_CreateSymmetricContext: refKeyToRaw context err: %s", sec_errstr(crtn)); + return crtn; + } + + crtn = CSSM_WrapKey(ccHand, + &creds, + refKey, + NULL, // DescriptiveData + rawKey); + if(crtn != CSSM_OK) { + sec_error("CSSM_WrapKey: refKeyToRaw wrap err: %s", sec_errstr(crtn)); + return crtn; + } + CSSM_DeleteContext(ccHand); + return CSSM_OK; +} + +/* + * Find private key by label, modify its Label attr to be the + * hash of the associated public key. + */ +CSSM_RETURN setPubKeyHash( + CSSM_CSP_HANDLE cspHand, + CSSM_DL_DB_HANDLE dlDbHand, + const CSSM_KEY *pubOrPrivKey, // to get hash; raw or ref/CSPDL + const char *keyLabel) // look up by this +{ + CSSM_QUERY query; + CSSM_SELECTION_PREDICATE predicate; + CSSM_DB_UNIQUE_RECORD_PTR record = NULL; + CSSM_RETURN crtn; + CSSM_DATA labelData; + CSSM_HANDLE resultHand; + + labelData.Data = (uint8 *)keyLabel; + labelData.Length = strlen(keyLabel) + 1; // incl. NULL + query.RecordType = CSSM_DL_DB_RECORD_PRIVATE_KEY; + query.Conjunctive = CSSM_DB_NONE; + query.NumSelectionPredicates = 1; + predicate.DbOperator = CSSM_DB_EQUAL; + + predicate.Attribute.Info.AttributeNameFormat = + CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + predicate.Attribute.Info.Label.AttributeName = "Label"; + predicate.Attribute.Info.AttributeFormat = + CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + predicate.Attribute.Value = &labelData; + query.SelectionPredicate = &predicate; + + query.QueryLimits.TimeLimit = 0; + query.QueryLimits.SizeLimit = 1; + query.QueryFlags = 0; + + /* build Record attribute with one attr */ + CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; + CSSM_DB_ATTRIBUTE_DATA attr; + attr.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr.Info.Label.AttributeName = "Label"; + attr.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + + recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_PRIVATE_KEY; + recordAttrs.NumberOfAttributes = 1; + recordAttrs.AttributeData = &attr; + + crtn = CSSM_DL_DataGetFirst(dlDbHand, + &query, + &resultHand, + &recordAttrs, + NULL, // hopefully optional ...theData, + &record); + /* abort only on success */ + if(crtn != CSSM_OK) { + sec_error("CSSM_DL_DataGetFirst: setPubKeyHash: can't find private key: %s", sec_errstr(crtn)); + return crtn; + } + + /* + * If specified key is a ref key, do NULL unwrap for use with raw CSP. + * If the CSPDL and SecurityServer support the key digest passthrough + * this is unnecessary. + */ + CSSM_KEY rawKeyToDigest; + if(pubOrPrivKey->KeyHeader.BlobType == CSSM_KEYBLOB_REFERENCE) { + crtn = refKeyToRaw(cspHand, pubOrPrivKey, &rawKeyToDigest); + if(crtn) { + sec_error("setPubKeyHash: Error converting public key to raw format: %s", sec_errstr(crtn)); + return crtn; + } + } + else { + /* use as is */ + rawKeyToDigest = *pubOrPrivKey; + } + + /* connect to raw CSP */ + CSSM_CSP_HANDLE rawCspHand = srCspStartup(CSSM_TRUE); + if(rawCspHand == 0) { + printf("***Error connecting to raw CSP; aborting.\n"); + return -1; + } + + /* calculate hash of pub key from private or public part */ + CSSM_DATA_PTR keyDigest = NULL; + CSSM_CC_HANDLE ccHand; + crtn = CSSM_CSP_CreatePassThroughContext(rawCspHand, + &rawKeyToDigest, + &ccHand); + if(ccHand == 0) { + sec_error("CSSM_CSP_CreatePassThroughContext: Error calculating public key hash. Aborting: %s", sec_errstr(crtn)); + return -1; + } + crtn = CSSM_CSP_PassThrough(ccHand, + CSSM_APPLECSP_KEYDIGEST, + NULL, + (void **)&keyDigest); + if(crtn) { + sec_error("CSSM_CSP_PassThrough(PUBKEYHASH): Error calculating public key hash. Aborting: %s", sec_errstr(crtn)); + return crtn; + } + if(pubOrPrivKey->KeyHeader.BlobType == CSSM_KEYBLOB_REFERENCE) { + /* created in refKeyToRaw().... */ + CSSM_FreeKey(cspHand, NULL, &rawKeyToDigest, CSSM_FALSE); + } + CSSM_DeleteContext(ccHand); + CSSM_ModuleDetach(rawCspHand); + + /* + * Replace Label attr data with hash. + * NOTE: the module which allocated this attribute data - a DL - + * was loaded and attached by the Sec layer, not by us. Thus + * we can't use the memory allocator functions *we* used when + * attaching to the CSPDL - we have to use the ones + * which the Sec layer registered with the DL. + */ + CSSM_API_MEMORY_FUNCS memFuncs; + crtn = CSSM_GetAPIMemoryFunctions(dlDbHand.DLHandle, &memFuncs); + if(crtn) { + sec_error("CSSM_GetAPIMemoryFunctions(DLHandle): Error: %s", sec_errstr(crtn)); + /* oh well, leak and continue */ + } + else { + memFuncs.free_func(attr.Value->Data, memFuncs.AllocRef); + memFuncs.free_func(attr.Value, memFuncs.AllocRef); + } + attr.Value = keyDigest; + + /* modify key attributes */ + crtn = CSSM_DL_DataModify(dlDbHand, + CSSM_DL_DB_RECORD_PRIVATE_KEY, + record, + &recordAttrs, + NULL, // DataToBeModified + CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + if(crtn) { + sec_error("CSSM_DL_DataModify(PUBKEYHASH): Error setting public key hash. Aborting: %s", sec_errstr(crtn)); + return crtn; + } + crtn = CSSM_DL_DataAbortQuery(dlDbHand, resultHand); + if(crtn) { + sec_error("CSSM_DL_DataAbortQuery: Error while stopping query: %s", sec_errstr(crtn)); + /* let's keep going in this case */ + } + crtn = CSSM_DL_FreeUniqueRecord(dlDbHand, record); + if(crtn) { + sec_error("CSSM_DL_FreeUniqueRecord: Error while freeing record: %s", sec_errstr(crtn)); + /* let's keep going in this case */ + crtn = CSSM_OK; + } + + /* free resources */ + if (keyDigest) + { + srAppFree(keyDigest->Data, NULL); + srAppFree(keyDigest, NULL); + } + return CSSM_OK; +} + +/* + * Generate a key pair using the CSPDL. + */ +OSStatus generateKeyPair( + CSSM_CSP_HANDLE cspHand, + CSSM_DL_DB_HANDLE dlDbHand, + CSSM_ALGORITHMS keyAlg, // e.g., CSSM_ALGID_RSA + uint32 keySizeInBits, + const char *keyLabel, // C string + CSSM_KEY_PTR *pubKeyPtr, // mallocd, created, RETURNED + CSSM_KEY_PTR *privKeyPtr) // mallocd, created, RETURNED +{ + CSSM_KEY_PTR pubKey = (CSSM_KEY_PTR)(APP_MALLOC(sizeof(CSSM_KEY))); + CSSM_KEY_PTR privKey = (CSSM_KEY_PTR)(APP_MALLOC(sizeof(CSSM_KEY))); + if((pubKey == NULL) || (privKey == NULL)) { + return memFullErr; + } + + CSSM_RETURN crtn; + CSSM_KEYUSE pubKeyUse; + CSSM_KEYUSE privKeyUse; + + pubKeyUse = CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_ENCRYPT | + CSSM_KEYUSE_WRAP; + privKeyUse = CSSM_KEYUSE_SIGN | CSSM_KEYUSE_DECRYPT | + CSSM_KEYUSE_UNWRAP; + + crtn = srCspGenKeyPair(cspHand, + &dlDbHand, + keyAlg, + keyLabel, + strlen(keyLabel) + 1, + keySizeInBits, + pubKey, + pubKeyUse, + CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_REF, + privKey, + privKeyUse, + CSSM_KEYATTR_SENSITIVE | CSSM_KEYATTR_RETURN_REF | + CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE); + + if(crtn) { + APP_FREE(pubKey); + APP_FREE(privKey); + return paramErr; + } + + /* bind private key to cert by public key hash */ + crtn = setPubKeyHash(cspHand, + dlDbHand, + pubKey, + keyLabel); + if(crtn) { + sec_error("setPubKeyHash: Error setting public key hash. Continuing at peril: %s", sec_errstr(crtn)); + } + + *pubKeyPtr = pubKey; + *privKeyPtr = privKey; + return noErr; +} + +// Fill a uint32 with random data +void randUint32(uint32 *u) +{ + int dev = open("/dev/random", O_RDONLY); + if(dev < 0) { + return; + } + read(dev, u, sizeof(*u)); + close(dev); +} + + +//========================================================================== + +int +keychain_createMFV(int argc, char * const *argv) +{ + int zero_password = 0; + char *password = NULL; + const char *keychainName = NULL; + int result = 0, ch = 0; + Boolean do_prompt = FALSE; + SecKeychainRef keychainRef = NULL; + uint32 keySizeInBits = SR2_KEY_SIZE_IN_BITS; // default + +/* AG: getopts optstring name [args] + AG: while loop calling getopt is used to extract password from cl from user + password is the only option to keychain_create + optstring is a string containing the legitimate option + characters. If such a character is followed by a colon, + the option requires an argument, so getopt places a + pointer to the following text in the same argv-element, or + the text of the following argv-element, in optarg. +*/ + while ((ch = getopt(argc, argv, "hp:s:P")) != -1) + { + switch (ch) + { + case 'p': + password = optarg; + break; + case 'P': + do_prompt = TRUE; + break; + case 's': + // Specify the keysize in bits (default 1024) + keySizeInBits = atoi(optarg); + if (!(keySizeInBits == SR_KEY_SIZE_IN_BITS || keySizeInBits == SR2_KEY_SIZE_IN_BITS || keySizeInBits == 4096)) + return 2; + break; + case '?': + default: + return 2; /* @@@ Return 2 triggers usage message. */ + } + } +/* + AG: The external variable optind is the index of the next + array element of argv[] to be processed; it communicates + from one call of getopt() to the next which element to + process. + The variable optind is the index of the next element of the argv[] vector to be processed. It shall be initialized to 1 by the system, and getopt() shall update it when it finishes with each element of argv[]. When an element of argv[] contains multiple option characters, it is unspecified how getopt() determines which options have already been processed. + +*/ + argc -= optind; + argv += optind; + + if (argc > 1) + return 2; /* @@@ Return 2 triggers usage message. */ + + keychainName = (argc == 1)?*argv:_masterKeychainName; + if (!keychainName || *keychainName == '\0') + return -1; + + if (!password && !do_prompt) + { + int compare = 1; + int tries; + + for (tries = 3; tries-- > 0;) + { + char *firstpass; + + password = getpass("password for new keychain: "); + if (!password) + { + result = -1; + goto loser; + } + + firstpass = malloc(strlen(password) + 1); + strcpy(firstpass, password); + password = getpass("retype password for new keychain: "); + compare = password ? strcmp(password, firstpass) : 1; + memset(firstpass, 0, strlen(firstpass)); + free(firstpass); + if (!password) + { + result = -1; + goto loser; + } + + if (compare) + { + fprintf(stderr, "passwords don't match\n"); + memset(password, 0, strlen(password)); + } + else + { + zero_password = 1; + break; + } + } + + if (compare) + { + result = 1; + goto loser; + } + } + + do + { + // result = do_create(keychain, password, do_prompt); + result = makeMasterPassword(keychainName, password, keySizeInBits, &keychainRef); + if (keychainRef) + CFRelease(keychainRef); + if (zero_password) + memset(password, 0, strlen(password)); + if (result) + goto loser; + + argc--; + argv++; + keychainName = *argv; + } while (argc > 0); + +loser: + + return result; +} diff --git a/SecurityTool/createFVMaster.h b/SecurityTool/createFVMaster.h new file mode 100644 index 00000000..c5d9bdb9 --- /dev/null +++ b/SecurityTool/createFVMaster.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2011 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@ + * + * createFVMaster.h + */ + +#ifndef _KEYCHAIN_CREATE_MFV_H_ +#define _KEYCHAIN_CREATE_MFV_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int keychain_createMFV(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _KEYCHAIN_CREATE_MFV_H_ */ diff --git a/SecurityTool/db_commands.cpp b/SecurityTool/db_commands.cpp new file mode 100644 index 00000000..fb17ae42 --- /dev/null +++ b/SecurityTool/db_commands.cpp @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2003-2005,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@ + * + * db_commands.cpp -- commands to directly manipulate Db's using the DL API. + */ + +#include "db_commands.h" + +#include "readline.h" +#include "security.h" + +#include +#include +#include +#include + +using namespace CssmClient; + +static int +do_db_create(const CSSM_GUID guid, const char *dbname, Boolean do_openparams, Boolean do_autocommit, Boolean do_mode, mode_t mode, Boolean do_version_0_params) +{ + int result = 0; + + try + { + CSSM_APPLEDL_OPEN_PARAMETERS openParameters = { sizeof(CSSM_APPLEDL_OPEN_PARAMETERS), + (do_version_0_params ? 0 : CSSM_APPLEDL_OPEN_PARAMETERS_VERSION) }; + Cssm cssm; + Module module(guid, cssm); + DL dl(module); + Db db(dl, dbname); + + if (do_openparams) + { + openParameters.autoCommit = do_autocommit; + if (!do_version_0_params && do_mode) + { + openParameters.mask |= kCSSM_APPLEDL_MASK_MODE; + openParameters.mode = mode; + } + + db->openParameters(&openParameters); + } + + db->create(); + } + catch (const CommonError &e) + { + OSStatus status = e.osStatus(); + sec_error("CSSM_DbCreate %s: %s", dbname, sec_errstr(status)); + } + catch (...) + { + result = 1; + } + + return result; +} + +static int +parse_guid(const char *name, CSSM_GUID *guid) +{ + size_t len = strlen(name); + + if (!strncmp("dl", name, len)) + *guid = gGuidAppleFileDL; + else if (!strncmp("cspdl", name, len)) + *guid = gGuidAppleCSPDL; + else + { + sec_error("Invalid guid: %s", name); + return 2; + } + + return 0; +} + + +static int +parse_mode(const char *name, mode_t *pmode) +{ + int result = 0; + mode_t mode = 0; + const char *p; + + if (!name || !pmode || *name != '0') + { + result = 2; + goto loser; + } + + for (p = name + 1; *p; ++p) + { + if (*p < '0' || *p > '7') + { + result = 2; + goto loser; + } + + mode = (mode << 3) + *p - '0'; + } + + *pmode = mode; + return 0; + +loser: + sec_error("Invalid mode: %s", name); + return result; +} + +int +db_create(int argc, char * const *argv) +{ + int free_dbname = 0; + char *dbname = NULL; + int ch, result = 0; + bool do_autocommit = true, do_mode = false; + bool do_openparams = false, do_version_0_params = false; + mode_t mode = 0666; + CSSM_GUID guid = gGuidAppleFileDL; + + while ((ch = getopt(argc, argv, "0ahg:m:o")) != -1) + { + switch (ch) + { + case '0': + do_version_0_params = true; + do_openparams = true; + break; + case 'a': + do_autocommit = false; + do_openparams = true; + break; + case 'g': + result = parse_guid(optarg, &guid); + if (result) + goto loser; + break; + case 'm': + result = parse_mode(optarg, &mode); + if (result) + goto loser; + do_mode = true; + do_openparams = true; + break; + case 'o': + do_openparams = true; + break; + case '?': + default: + return 2; /* @@@ Return 2 triggers usage message. */ + } + } + + argc -= optind; + argv += optind; + + if (argc > 0) + dbname = *argv; + else + { + fprintf(stderr, "db to create: "); + dbname = readline(NULL, 0); + if (!dbname) + { + result = -1; + goto loser; + } + + free_dbname = 1; + if (*dbname == '\0') + goto loser; + } + + do + { + result = do_db_create(guid, dbname, do_openparams, do_autocommit, do_mode, mode, do_version_0_params); + if (result) + goto loser; + + argc--; + argv++; + dbname = *argv; + } while (argc > 0); + +loser: + if (free_dbname) + free(dbname); + + return result; +} diff --git a/SecurityTool/db_commands.h b/SecurityTool/db_commands.h new file mode 100644 index 00000000..c036b2fd --- /dev/null +++ b/SecurityTool/db_commands.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2003-2004,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@ + * + * db_commands.h + */ + +#ifndef _DB_COMMANDS_H_ +#define _DB_COMMANDS_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int db_create(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _DB_COMMANDS_H_ */ diff --git a/SecurityTool/display_error_code.c b/SecurityTool/display_error_code.c new file mode 100644 index 00000000..939c5a9b --- /dev/null +++ b/SecurityTool/display_error_code.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2003-2009,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@ + * + * leaks.c + */ + +#include "display_error_code.h" +#include "security.h" +#include +#include +#include +#include +#include +#include + +// cssmErrorString +#include + + +int display_error_code(int argc, char *const *argv) +{ + CSSM_RETURN error; + int ix = 0; + + for (ix = 0; ix < argc; ix++) + { + if (strcmp("error", argv[ix])==0) + continue; + // set base to 0 to have it interpret radix automatically + error = strtoul(argv[ix], NULL, 0); + printf("Error: 0x%08X %d %s\n", error, error, cssmErrorString(error)); + } + + return 1; +} diff --git a/SecurityTool/display_error_code.h b/SecurityTool/display_error_code.h new file mode 100644 index 00000000..099155e9 --- /dev/null +++ b/SecurityTool/display_error_code.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2003-2004,2008,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * leaks.h + */ + +#ifndef _DISPLAY_ERROR_CODE_H_ +#define _DISPLAY_ERROR_CODE_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int display_error_code(int argc, char *const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _DISPLAY_ERROR_CODE_H_ */ diff --git a/SecurityTool/entitlements.plist b/SecurityTool/entitlements.plist new file mode 100644 index 00000000..4d4bad7a --- /dev/null +++ b/SecurityTool/entitlements.plist @@ -0,0 +1,19 @@ + + + + + keychain-cloud-circle + + keychain-access-groups + + test + * + + modify-anchor-certificates + + restore-keychain + + application-identifier + com.apple.security + + diff --git a/SecurityTool/identity_find.c b/SecurityTool/identity_find.c new file mode 100644 index 00000000..675a0b05 --- /dev/null +++ b/SecurityTool/identity_find.c @@ -0,0 +1,531 @@ +/* + * Copyright (c) 2003-2010,2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * identity_find.c + */ + +#include "identity_find.h" +#include "keychain_utilities.h" +#include "trusted_cert_utils.h" +#include "security.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// cssmErrorString +#include +// SecCertificateInferLabel, SecDigestGetData +#include +// SecIdentitySearchCreateWithPolicy +#include + + +SecIdentityRef +find_identity(CFTypeRef keychainOrArray, + const char *identity, + const char *hash, + CSSM_KEYUSE keyUsage) +{ + SecIdentityRef identityRef = NULL; + SecIdentitySearchRef searchRef = NULL; + OSStatus status = SecIdentitySearchCreate(keychainOrArray, keyUsage, &searchRef); + if (status) { + return identityRef; + } + + // check input hash string and convert to data + CSSM_DATA hashData = { 0, NULL }; + if (hash) { + CSSM_SIZE len = strlen(hash)/2; + hashData.Length = len; + hashData.Data = (uint8 *)malloc(hashData.Length); + fromHex(hash, &hashData); + } + + // filter candidates against the hash (or the name, if no hash provided) + CFStringRef matchRef = (identity) ? CFStringCreateWithCString(NULL, identity, kCFStringEncodingUTF8) : NULL; + Boolean exactMatch = FALSE; + + CSSM_DATA certData = { 0, NULL }; + SecIdentityRef candidate = NULL; + + while (SecIdentitySearchCopyNext(searchRef, &candidate) == noErr) { + SecCertificateRef cert = NULL; + if (SecIdentityCopyCertificate(candidate, &cert) != noErr) { + safe_CFRelease(&candidate); + continue; + } + if (SecCertificateGetData(cert, &certData) != noErr) { + safe_CFRelease(&cert); + safe_CFRelease(&candidate); + continue; + } + if (hash) { + uint8 candidate_sha1_hash[20]; + CSSM_DATA digest; + digest.Length = sizeof(candidate_sha1_hash); + digest.Data = candidate_sha1_hash; + if ((SecDigestGetData(CSSM_ALGID_SHA1, &digest, &certData) == CSSM_OK) && + (hashData.Length == digest.Length) && + (!memcmp(hashData.Data, digest.Data, digest.Length))) { + identityRef = candidate; // currently retained + safe_CFRelease(&cert); + break; // we're done - can't get more exact than this + } + } else { + // copy certificate name + CFStringRef nameRef = NULL; + if ((SecCertificateCopyCommonName(cert, &nameRef) != noErr) || nameRef == NULL) { + safe_CFRelease(&cert); + safe_CFRelease(&candidate); + continue; // no name, so no match is possible + } + CFIndex nameLen = CFStringGetLength(nameRef); + CFIndex bufLen = 1 + CFStringGetMaximumSizeForEncoding(nameLen, kCFStringEncodingUTF8); + char *nameBuf = (char *)malloc(bufLen); + if (!CFStringGetCString(nameRef, nameBuf, bufLen-1, kCFStringEncodingUTF8)) + nameBuf[0]=0; + + if (!strcmp(identity, "*")) { // special case: means "just take the first one" + sec_error("Using identity \"%s\"", nameBuf); + identityRef = candidate; // currently retained + free(nameBuf); + safe_CFRelease(&nameRef); + safe_CFRelease(&cert); + break; + } + CFRange find = { kCFNotFound, 0 }; + if (nameRef && matchRef) + find = CFStringFind(nameRef, matchRef, kCFCompareCaseInsensitive | kCFCompareNonliteral); + Boolean isExact = (find.location == 0 && find.length == nameLen); + if (find.location == kCFNotFound) { + free(nameBuf); + safe_CFRelease(&nameRef); + safe_CFRelease(&cert); + safe_CFRelease(&candidate); + continue; // no match + } + if (identityRef) { // got two matches + if (exactMatch && !isExact) { // prior is better; ignore this one + free(nameBuf); + safe_CFRelease(&nameRef); + safe_CFRelease(&cert); + safe_CFRelease(&candidate); + continue; + } + if (exactMatch == isExact) { // same class of match + if (CFEqual(identityRef, candidate)) { // identities have same cert + free(nameBuf); + safe_CFRelease(&nameRef); + safe_CFRelease(&cert); + safe_CFRelease(&candidate); + continue; + } + // ambiguity - must fail + sec_error("\"%s\" is ambiguous, matches more than one certificate", identity); + free(nameBuf); + safe_CFRelease(&nameRef); + safe_CFRelease(&cert); + safe_CFRelease(&candidate); + safe_CFRelease(&identityRef); + break; + } + safe_CFRelease(&identityRef); // about to replace with this one + } + identityRef = candidate; // currently retained + exactMatch = isExact; + free(nameBuf); + safe_CFRelease(&nameRef); + } + safe_CFRelease(&cert); + } + + safe_CFRelease(&searchRef); + safe_CFRelease(&matchRef); + if (hashData.Data) { + free(hashData.Data); + } + + return identityRef; +} + +static void printIdentity(SecIdentityRef identity, SecPolicyRef policy, int ordinalValue) +{ + OSStatus status; + Boolean printHash = TRUE, printName = TRUE; + SecCertificateRef cert = NULL; + + status = SecIdentityCopyCertificate(identity, &cert); + if (!status) + { + CSSM_DATA certData = { 0, nil }; + (void) SecCertificateGetData(cert, &certData); + fprintf(stdout, "%3d) ", ordinalValue); + if (printHash) { + uint8 sha1_hash[20]; + CSSM_DATA digest; + digest.Length = sizeof(sha1_hash); + digest.Data = sha1_hash; + if (SecDigestGetData(CSSM_ALGID_SHA1, &digest, &certData) == CSSM_OK) { + unsigned int i; + uint32 len = digest.Length; + uint8 *cp = digest.Data; + for(i=0; i 0) { + CFIndex bufLen = 1 + CFStringGetMaximumSizeForEncoding(nameLen, kCFStringEncodingUTF8); + nameBuf = (char *)malloc(bufLen); + if (!CFStringGetCString(nameRef, nameBuf, bufLen-1, kCFStringEncodingUTF8)) + nameBuf[0]=0; + } + fprintf(stdout, " \"%s\"", (nameBuf && nameBuf[0] != 0) ? nameBuf : ""); + if (nameBuf) + free(nameBuf); + safe_CFRelease(&nameRef); + } + + // Default to X.509 Basic if no policy was specified + if (!policy) { + SecPolicySearchRef policySearch = NULL; + if (SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_X509_BASIC, NULL, &policySearch)==noErr) { + SecPolicySearchCopyNext(policySearch, &policy); + } + safe_CFRelease(&policySearch); + } else { + CFRetain(policy); + } + + // Create the trust reference, given policy and certificates + SecTrustRef trust = nil; + SecTrustResultType trustResult = kSecTrustResultInvalid; + OSStatus trustResultCode = noErr; + CFMutableArrayRef certificates = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + if (certificates) { + CFArrayAppendValue(certificates, cert); + } + status = SecTrustCreateWithCertificates((CFArrayRef)certificates, policy, &trust); + if (!status) { + status = SecTrustEvaluate(trust, &trustResult); + } + if (trustResult != kSecTrustResultInvalid) { + status = SecTrustGetCssmResultCode(trust, &trustResultCode); + } + if (trustResultCode != noErr) { + fprintf(stdout, " (%s)\n", cssmErrorString(trustResultCode)); + } else { + fprintf(stdout, "\n"); + } + safe_CFRelease(&trust); + safe_CFRelease(&policy); + safe_CFRelease(&certificates); + } + safe_CFRelease(&cert); + (void) status; +} + +static void +do_identity_search_with_policy(CFTypeRef keychainOrArray, + const char *name, + const CSSM_OID* oidPtr, + CSSM_KEYUSE keyUsage, + Boolean client, + Boolean validOnly) +{ + // set up SMIME options with provided data + CE_KeyUsage ceKeyUsage = 0; + if (keyUsage & CSSM_KEYUSE_SIGN) ceKeyUsage |= CE_KU_DigitalSignature; + if (keyUsage & CSSM_KEYUSE_ENCRYPT) ceKeyUsage |= CE_KU_KeyEncipherment; + CSSM_APPLE_TP_SMIME_OPTIONS smimeOpts = { + CSSM_APPLE_TP_SMIME_OPTS_VERSION, // Version + ceKeyUsage, // IntendedUsage + name ? strlen(name) : 0, // SenderEmailLen + name // SenderEmail + }; + CSSM_DATA smimeValue = { sizeof(smimeOpts), (uint8*)&smimeOpts }; + + // set up SSL options with provided data + CSSM_APPLE_TP_SSL_OPTIONS sslOpts = { + CSSM_APPLE_TP_SSL_OPTS_VERSION, // Version + (name && !client) ? strlen(name) : 0, // ServerNameLen + (client) ? NULL : name, // ServerName + (client) ? CSSM_APPLE_TP_SSL_CLIENT : 0 // Flags + }; + CSSM_DATA sslValue = { sizeof(sslOpts), (uint8*)&sslOpts }; + + // get a policy ref for the specified policy OID + OSStatus status = noErr; + SecPolicyRef policy = NULL; + SecPolicySearchRef policySearch = NULL; + status = SecPolicySearchCreate(CSSM_CERT_X_509v3, oidPtr, NULL, &policySearch); + if (!status) + status = SecPolicySearchCopyNext(policySearch, &policy); + + CSSM_DATA *policyValue = NULL; + const char *policyName = ""; + + if (compareOids(oidPtr, &CSSMOID_APPLE_TP_SMIME)) { + policyName = "S/MIME"; + policyValue = &smimeValue; + } + else if (compareOids(oidPtr, &CSSMOID_APPLE_TP_SSL)) { + if (client) + policyName = "SSL (client)"; + else + policyName = "SSL (server)"; + policyValue = &sslValue; + } + else if (compareOids(oidPtr, &CSSMOID_APPLE_TP_EAP)) { + policyName = "EAP"; + } + else if (compareOids(oidPtr, &CSSMOID_APPLE_TP_IP_SEC)) { + policyName = "IPsec"; + } + else if (compareOids(oidPtr, &CSSMOID_APPLE_TP_ICHAT)) { + policyName = "iChat"; + } + else if (compareOids(oidPtr, &CSSMOID_APPLE_TP_CODE_SIGNING)) { + policyName = "Code Signing"; + } + else if (compareOids(oidPtr, &CSSMOID_APPLE_X509_BASIC)) { + policyName = "X.509 Basic"; + } + else if (compareOids(oidPtr, &CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT)) { + policyName = "Mac App Store Receipt"; + } + else if (compareOids(oidPtr, &CSSMOID_APPLE_TP_APPLEID_SHARING)) { + policyName = "AppleID Sharing"; + } + + // set the policy's value, if there is one (this is specific to certain policies) + if (policy && policyValue) + status = SecPolicySetValue(policy, policyValue); + + CFStringRef idStr = (name) ? CFStringCreateWithCStringNoCopy(NULL, name, kCFStringEncodingUTF8, kCFAllocatorNull) : NULL; + SecIdentitySearchRef searchRef = NULL; + int identityCount = 0; + + if (!validOnly) { + // create an identity search, specifying all identities (i.e. returnOnlyValidIdentities=FALSE) + // this should return all identities which match the policy and key usage, regardless of validity + fprintf(stdout, "\nPolicy: %s\n", policyName); + fprintf(stdout, " Matching identities\n"); + status = SecIdentitySearchCreateWithPolicy(policy, idStr, keyUsage, keychainOrArray, FALSE, &searchRef); + if (!status) + { + SecIdentityRef identityRef = NULL; + while (SecIdentitySearchCopyNext(searchRef, &identityRef) == noErr) + { + identityCount++; + printIdentity(identityRef, policy, identityCount); + safe_CFRelease(&identityRef); + } + safe_CFRelease(&searchRef); + } + fprintf(stdout, " %d identities found\n\n", identityCount); + } + + // create a second identity search, specifying only valid identities (i.e. returnOnlyValidIdentities=TRUE) + // this should return only valid identities for the policy. + identityCount = 0; + if (!validOnly) { + fprintf(stdout, " Valid identities only\n"); + } + status = SecIdentitySearchCreateWithPolicy(policy, idStr, keyUsage, keychainOrArray, TRUE, &searchRef); + if (!status) + { + SecIdentityRef identityRef = NULL; + while (SecIdentitySearchCopyNext(searchRef, &identityRef) == noErr) + { + identityCount++; + printIdentity(identityRef, policy, identityCount); + safe_CFRelease(&identityRef); + } + safe_CFRelease(&searchRef); + } + fprintf(stdout, " %d valid identities found\n", identityCount); + + safe_CFRelease(&idStr); + safe_CFRelease(&policy); + safe_CFRelease(policySearch); +} + +static void +do_system_identity_search(CFStringRef domain) +{ + SecIdentityRef identity = NULL; + OSStatus status = SecIdentityCopySystemIdentity(domain, &identity, NULL); + if (CFEqual(domain, kSecIdentityDomainDefault)) { + fprintf(stdout, "\n System default identity\n"); + } else if (CFEqual(domain, kSecIdentityDomainKerberosKDC)) { + fprintf(stdout, "\n System Kerberos KDC identity\n"); + } + if (!status && identity) { + SecPolicyRef policy = NULL; + SecPolicySearchRef policySearch = NULL; + if (SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_X509_BASIC, NULL, &policySearch) == noErr) { + if (SecPolicySearchCopyNext(policySearch, &policy) == noErr) { + printIdentity(identity, policy, 1); + CFRelease(policy); + } + safe_CFRelease(&policySearch); + } + safe_CFRelease(&identity); + } +} + +static int +do_find_identities(CFTypeRef keychainOrArray, const char *name, unsigned int policyFlags, Boolean validOnly) +{ + int result = 0; + + if (name) { + fprintf(stdout, "Looking for identities matching \"%s\"\n", name); + } + if (policyFlags & (1 << 0)) + do_identity_search_with_policy(keychainOrArray, name, &CSSMOID_APPLE_TP_SSL, CSSM_KEYUSE_SIGN, TRUE, validOnly); + if (policyFlags & (1 << 1)) + do_identity_search_with_policy(keychainOrArray, name, &CSSMOID_APPLE_TP_SSL, CSSM_KEYUSE_SIGN, FALSE, validOnly); + if (policyFlags & (1 << 2)) + do_identity_search_with_policy(keychainOrArray, name, &CSSMOID_APPLE_TP_SMIME, CSSM_KEYUSE_SIGN, TRUE, validOnly); + if (policyFlags & (1 << 3)) + do_identity_search_with_policy(keychainOrArray, name, &CSSMOID_APPLE_TP_EAP, CSSM_KEYUSE_SIGN, TRUE, validOnly); + if (policyFlags & (1 << 4)) + do_identity_search_with_policy(keychainOrArray, name, &CSSMOID_APPLE_TP_IP_SEC, CSSM_KEYUSE_SIGN, TRUE, validOnly); + if (policyFlags & (1 << 5)) + do_identity_search_with_policy(keychainOrArray, name, &CSSMOID_APPLE_TP_ICHAT, CSSM_KEYUSE_SIGN, TRUE, validOnly); + if (policyFlags & (1 << 6)) + do_identity_search_with_policy(keychainOrArray, name, &CSSMOID_APPLE_TP_CODE_SIGNING, CSSM_KEYUSE_SIGN, TRUE, validOnly); + if (policyFlags & (1 << 7)) + do_identity_search_with_policy(keychainOrArray, name, &CSSMOID_APPLE_X509_BASIC, CSSM_KEYUSE_SIGN, TRUE, validOnly); + + if (policyFlags & (1 << 8)) + do_system_identity_search(kSecIdentityDomainDefault); + if (policyFlags & (1 << 9)) + do_system_identity_search(kSecIdentityDomainKerberosKDC); + if (policyFlags & (1 << 10)) + do_identity_search_with_policy(keychainOrArray, name, &CSSMOID_APPLE_TP_APPLEID_SHARING, CSSM_KEYUSE_SIGN, FALSE, validOnly); + if (policyFlags & (1 << 11)) + do_identity_search_with_policy(keychainOrArray, name, &CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT, CSSM_KEYUSE_SIGN, TRUE, validOnly); + + return result; +} + +int +keychain_find_identity(int argc, char * const *argv) +{ + int ch, result = 0; + unsigned int policyFlags = 0; + const char *name = NULL; + Boolean validOnly = FALSE; + CFTypeRef keychainOrArray = NULL; + + /* + * " -p Specify policy to evaluate (multiple -p options are allowed)\n" + * " -s Specify optional policy-specific string (e.g. a DNS hostname for SSL,\n" + * " or RFC822 email address for S/MIME)\n" + * " -v Show valid identities only (default is to show all identities)\n" + */ + + while ((ch = getopt(argc, argv, "hp:s:v")) != -1) + { + switch (ch) + { + case 'p': + if (optarg != NULL) { + if (!strcmp(optarg, "ssl-client")) + policyFlags |= 1 << 0; + else if (!strcmp(optarg, "ssl-server")) + policyFlags |= 1 << 1; + else if (!strcmp(optarg, "smime")) + policyFlags |= 1 << 2; + else if (!strcmp(optarg, "eap")) + policyFlags |= 1 << 3; + else if (!strcmp(optarg, "ipsec")) + policyFlags |= 1 << 4; + else if (!strcmp(optarg, "ichat")) + policyFlags |= 1 << 5; + else if (!strcmp(optarg, "codesigning")) + policyFlags |= 1 << 6; + else if (!strcmp(optarg, "basic")) + policyFlags |= 1 << 7; + else if (!strcmp(optarg, "sys-default")) + policyFlags |= 1 << 8; + else if (!strcmp(optarg, "sys-kerberos-kdc")) + policyFlags |= 1 << 9; + else if (!strcmp(optarg, "appleID")) + policyFlags |= 1 << 10; + else if (!strcmp(optarg, "macappstore")) + policyFlags |= 1 << 11; + else { + result = 2; /* @@@ Return 2 triggers usage message. */ + goto cleanup; + } + } + break; + case 's': + name = optarg; + break; + case 'v': + validOnly = TRUE; + break; + case '?': + default: + result = 2; /* @@@ Return 2 triggers usage message. */ + goto cleanup; + } + } + + if (!policyFlags) + policyFlags |= 1 << 7; /* default to basic policy if none specified */ + + argc -= optind; + argv += optind; + + keychainOrArray = keychain_create_array(argc, argv); + + result = do_find_identities(keychainOrArray, name, policyFlags, validOnly); + +cleanup: + safe_CFRelease(&keychainOrArray); + + return result; +} + diff --git a/SecurityTool/identity_find.h b/SecurityTool/identity_find.h new file mode 100644 index 00000000..96dca380 --- /dev/null +++ b/SecurityTool/identity_find.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2003-2009 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@ + * + * identity_find.h + */ + +#ifndef _IDENTITY_FIND_H_ +#define _IDENTITY_FIND_H_ 1 + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern SecIdentityRef find_identity(CFTypeRef keychainOrArray, + const char *identity, + const char *hash, + CSSM_KEYUSE keyUsage); + +extern int keychain_find_identity(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _IDENTITY_FIND_H_ */ diff --git a/SecurityTool/identity_prefs.c b/SecurityTool/identity_prefs.c new file mode 100644 index 00000000..8fc4826c --- /dev/null +++ b/SecurityTool/identity_prefs.c @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2003-2010,2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * identity_prefs.c + */ + +#include "identity_prefs.h" +#include "identity_find.h" +#include "keychain_utilities.h" +#include "security.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +// SecCertificateInferLabel, SecDigestGetData +#include + + +static int +do_set_identity_preference(CFTypeRef keychainOrArray, + const char *identity, + const char *service, + CSSM_KEYUSE keyUsage, + const char *hash) +{ + int result = 0; + CFStringRef serviceRef = NULL; + SecIdentityRef identityRef = NULL; + + // must have a service name + if (!service) { + return 2; + } + + // find identity (if specified by name or hash) + if (identity || hash) { + identityRef = find_identity(keychainOrArray, identity, hash, keyUsage); + if (!identityRef) { + sec_error("No matching identity found for \"%s\"", (hash) ? hash : identity); + result = 1; + goto cleanup; + } + } + + // set the identity preference + serviceRef = CFStringCreateWithCString(NULL, service, kCFStringEncodingUTF8); + result = SecIdentitySetPreference(identityRef, serviceRef, keyUsage); + +cleanup: + if (identityRef) + CFRelease(identityRef); + if (serviceRef) + CFRelease(serviceRef); + + return result; +} + +int +do_get_identity_preference(const char *service, + CSSM_KEYUSE keyUsage, + Boolean printName, + Boolean printHash, + Boolean pemFormat) +{ + int result = 0; + if (!service) { + return 2; + } + CFStringRef serviceRef = CFStringCreateWithCString(NULL, service, kCFStringEncodingUTF8); + SecCertificateRef certRef = NULL; + SecIdentityRef identityRef = NULL; + CSSM_DATA certData = { 0, NULL }; + + result = SecIdentityCopyPreference(serviceRef, keyUsage, NULL, &identityRef); + if (result) { + sec_perror("SecIdentityCopyPreference", result); + goto cleanup; + } + result = SecIdentityCopyCertificate(identityRef, &certRef); + if (result) { + sec_perror("SecIdentityCopyCertificate", result); + goto cleanup; + } + result = SecCertificateGetData(certRef, &certData); + if (result) { + sec_perror("SecCertificateGetData", result); + goto cleanup; + } + + if (printName) { + char *nameBuf = NULL; + CFStringRef nameRef = NULL; + (void)SecCertificateCopyCommonName(certRef, &nameRef); + CFIndex nameLen = (nameRef) ? CFStringGetLength(nameRef) : 0; + if (nameLen > 0) { + CFIndex bufLen = 1 + CFStringGetMaximumSizeForEncoding(nameLen, kCFStringEncodingUTF8); + nameBuf = (char *)malloc(bufLen); + if (!CFStringGetCString(nameRef, nameBuf, bufLen-1, kCFStringEncodingUTF8)) + nameBuf[0]=0; + } + fprintf(stdout, "common name: \"%s\"\n", (nameBuf && nameBuf[0] != 0) ? nameBuf : ""); + if (nameBuf) + free(nameBuf); + safe_CFRelease(&nameRef); + } + + if (printHash) { + uint8 sha1_hash[20]; + CSSM_DATA digest; + digest.Length = sizeof(sha1_hash); + digest.Data = sha1_hash; + if (SecDigestGetData(CSSM_ALGID_SHA1, &digest, &certData) == CSSM_OK) { + unsigned int i; + uint32 len = digest.Length; + uint8 *cp = digest.Data; + fprintf(stdout, "SHA-1 hash: "); + for(i=0; i +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int set_identity_preference(int argc, char * const *argv); + +extern int get_identity_preference(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _IDENTITY_PREFS_H_ */ diff --git a/SecurityTool/key_create.c b/SecurityTool/key_create.c new file mode 100644 index 00000000..db76d601 --- /dev/null +++ b/SecurityTool/key_create.c @@ -0,0 +1,619 @@ +/* + * Copyright (c) 2003-2004,2006,2008,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@ + * + * key_create.c + */ + +#include "key_create.h" + +#include "keychain_utilities.h" +#include "security.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static int +do_key_create_pair(const char *keychainName, SecAccessRef access, CSSM_ALGORITHMS algorithm, uint32 keySizeInBits, CFAbsoluteTime from_time, CFAbsoluteTime to_time, Boolean print_hash) +{ + SecKeychainRef keychain = NULL; + OSStatus status; + int result = 0; + CSSM_CC_HANDLE contextHandle = 0; + CSSM_KEYUSE publicKeyUsage = CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_WRAP | CSSM_KEYUSE_DERIVE; + uint32 publicKeyAttr = CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE; + CSSM_KEYUSE privateKeyUsage = CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_SIGN | CSSM_KEYUSE_UNWRAP | CSSM_KEYUSE_DERIVE; + uint32 privateKeyAttr = CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_SENSITIVE | CSSM_KEYATTR_EXTRACTABLE; + SecKeyRef publicKey = NULL; + SecKeyRef privateKey = NULL; + SecKeychainAttributeList *attrList = NULL; + + if (keychainName) + { + keychain = keychain_open(keychainName); + if (!keychain) + { + result = 1; + goto loser; + } + } + + status = SecKeyCreatePair(keychain, algorithm, keySizeInBits, contextHandle, + publicKeyUsage, + publicKeyAttr, + privateKeyUsage, + privateKeyAttr, + access, + &publicKey, + &privateKey); + if (status) + { + sec_error("SecKeyCreatePair %s: %s", keychainName ? keychainName : "", sec_errstr(status)); + result = 1; + goto loser; + } + + if (print_hash) + { + SecItemClass itemClass = 0; + UInt32 tag = 0x00000006; + UInt32 format = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + SecKeychainAttributeInfo info = { 1, &tag, &format }; + + status = SecKeychainItemCopyAttributesAndData((SecKeychainItemRef)privateKey, &info, &itemClass, &attrList, NULL, NULL); + if (status) + { + sec_perror("SecKeychainItemCopyAttributesAndData", status); + result = 1; + goto loser; + } + + if (info.count != attrList->count) + { + sec_error("info count: %ld != attribute count: %ld", info.count, attrList->count); + result = 1; + goto loser; + } + + if (tag != attrList->attr[0].tag) + { + sec_error("attribute info tag: %ld != attribute tag: %ld", tag, attrList->attr[0].tag); + result = 1; + goto loser; + } + + print_buffer_pem(stdout, "PUBLIC KEY HASH", attrList->attr[0].length, attrList->attr[0].data); + } + +loser: + if (attrList) + { + status = SecKeychainItemFreeAttributesAndData(attrList, NULL); + if (status) + sec_perror("SecKeychainItemFreeAttributesAndData", status); + } + + if (keychain) + CFRelease(keychain); + if (publicKey) + CFRelease(publicKey); + if (privateKey) + CFRelease(privateKey); + + return result; +} + +static int +parse_algorithm(const char *name, CSSM_ALGORITHMS *algorithm) +{ + size_t len = strlen(name); + + if (!strncmp("rsa", name, len)) + *algorithm = CSSM_ALGID_RSA; + else if (!strncmp("dsa", name, len)) + *algorithm = CSSM_ALGID_DSA; + else if (!strncmp("dh", name, len)) + *algorithm = CSSM_ALGID_DH; + else if (!strncmp("fee", name, len)) + *algorithm = CSSM_ALGID_FEE; + else + { + sec_error("Invalid algorithm: %s", name); + return 2; + } + + return 0; +} + +static int +parse_time(const char *time, CFAbsoluteTime *ptime) +{ + CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, NULL, kCFDateFormatterShortStyle, kCFDateFormatterShortStyle); + CFStringRef time_string = CFStringCreateWithCString(NULL, time, kCFStringEncodingUTF8); + int result = 0; + if (!CFDateFormatterGetAbsoluteTimeFromString(formatter, time_string, NULL, ptime)) + { + sec_error("%s is not a valid date", time); + result = 1; + } + if (formatter) + CFRelease(formatter); + if (time_string) + CFRelease(time_string); + return result; +} + +int +key_create_pair(int argc, char * const *argv) +{ + const char *keychainName = NULL; + CSSM_ALGORITHMS algorithm = CSSM_ALGID_RSA; + uint32 keySizeInBits = 512; + int ch, result = 0; + OSStatus status; + Boolean always_allow = FALSE; + Boolean print_hash = FALSE; + CFAbsoluteTime from_time = 0.0, to_time = 0.0; + double days = 0.0; + SecAccessRef access = NULL; + CFMutableArrayRef trusted_list = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFStringRef description = NULL; + +/* + { "create-keypair", key_create_pair, + "[-a alg] [-s size] [-f date] [-t date] [-d days] [-k keychain] [-A|-T appPath] description\n" + " -a Use alg as the algorithm, can be rsa, dh, dsa or fee (default rsa)\n" + " -s Specify the keysize in bits (default 512)\n" + " -f Make a key valid from the specified date\n" + " -t Make a key valid to the specified date\n" + " -d Make a key valid for the number of days specified from now\n" + " -k Use the specified keychain rather than the default\n" + " -H Print the public key hash attribute\n" + " -A Allow any application to access without warning\n" + " -T Allow the application specified to access without warning (multiple -T options are allowed)\n" + "If no options are provided, ask the user interactively.", +*/ + + while ((ch = getopt(argc, argv, "a:s:f:t:d:k:AHT:h")) != -1) + { + switch (ch) + { + case 'a': + result = parse_algorithm(optarg, &algorithm); + if (result) + goto loser; + break; + case 's': + keySizeInBits = atoi(optarg); + break; + case 'k': + keychainName = optarg; + break; + case 'A': + always_allow = TRUE; + break; + case 'H': + print_hash = TRUE; + break; + case 'T': + { + if (optarg[0]) + { + SecTrustedApplicationRef app = NULL; + status = SecTrustedApplicationCreateFromPath(optarg, &app); + if (status) + { + sec_error("SecTrustedApplicationCreateFromPath %s: %s", optarg, sec_errstr(status)); + result = 1; + goto loser; + } + + CFArrayAppendValue(trusted_list, app); + CFRelease(app); + } + break; + } + case 'f': + result = parse_time(optarg, &from_time); + if (result) + goto loser; + break; + case 't': + result = parse_time(optarg, &to_time); + if (result) + goto loser; + break; + case 'd': + days = atof(optarg); + if (days < 1) + { + result = 2; + goto loser; + } + from_time = CFAbsoluteTimeGetCurrent(); + to_time = from_time + days * 86400.0; + break; + case '?': + default: + return 2; /* @@@ Return 2 triggers usage message. */ + } + } + + argc -= optind; + argv += optind; + + if (argc == 1) + { + if (*argv[0] == '\0') + { + result = 2; + goto loser; + } + description = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); + } + else if (argc != 0) + return 2; + else + description = CFStringCreateWithCString(NULL, "", kCFStringEncodingUTF8); + + if (always_allow) + { + status = SecAccessCreate(description, NULL, &access); + if (status) + { + sec_perror("SecAccessCreate", status); + result = 1; + } + } + else + { + status = SecAccessCreate(description, trusted_list, &access); + if (status) + { + sec_perror("SecAccessCreate", status); + result = 1; + } + } + + if (result) + goto loser; + + result = do_key_create_pair(keychainName, access, algorithm, keySizeInBits, from_time, to_time, print_hash); + +loser: + if (description) + CFRelease(description); + if (trusted_list) + CFRelease(trusted_list); + if (access) + CFRelease(access); + + return result; +} + +#if 0 +static OSStatus +createCertCsr( + CSSM_TP_HANDLE tpHand, // eventually, a SecKeychainRef + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + SecKeyRef subjPubKey, + SecKeyRef signerPrivKey, + CSSM_ALGORITHMS sigAlg, + const CSSM_OID *sigOid, + /* + * Issuer's RDN is obtained from the issuer cert, if present, or is + * assumed to be the same as the subject name (i.e., we're creating + * a self-signed root cert). + */ + CSSM_BOOL useAllDefaults, + CSSM_DATA_PTR csrData) // CSR: mallocd and RETURNED +{ + CE_DataAndType exts[2]; + CE_DataAndType *extp = exts; + unsigned numExts; + + CSSM_DATA refId; // mallocd by CSSM_TP_SubmitCredRequest + CSSM_APPLE_TP_CERT_REQUEST certReq; + CSSM_TP_REQUEST_SET reqSet; + sint32 estTime; + CSSM_BOOL confirmRequired; + CSSM_TP_RESULT_SET_PTR resultSet; + CSSM_ENCODED_CERT *encCert; + CSSM_APPLE_TP_NAME_OID subjectNames[MAX_NAMES]; + uint32 numNames; + CSSM_TP_CALLERAUTH_CONTEXT CallerAuthContext; + CSSM_FIELD policyId; + + /* Note a lot of the CSSM_APPLE_TP_CERT_REQUEST fields are not + * used for the createCsr option, but we'll fill in as much as is practical + * for either case. + */ + numExts = 0; + + char challengeBuf[400]; + if(useAllDefaults) { + strcpy(challengeBuf, ZDEF_CHALLENGE); + } + else { + while(1) { + getStringWithPrompt("Enter challenge string: ", + challengeBuf, sizeof(challengeBuf)); + if(challengeBuf[0] != '\0') { + break; + } + } + } + certReq.challengeString = challengeBuf; + + /* name array, get from user. */ + if(useAllDefaults) { + subjectNames[0].string = ZDEF_COMMON_NAME; + subjectNames[0].oid = &CSSMOID_CommonName; + subjectNames[1].string = ZDEF_ORG_NAME; + subjectNames[1].oid = &CSSMOID_OrganizationName; + subjectNames[2].string = ZDEF_COUNTRY; + subjectNames[2].oid = &CSSMOID_CountryName; + subjectNames[3].string = ZDEF_STATE; + subjectNames[3].oid = &CSSMOID_StateProvinceName; + numNames = 4; + } + else { + getNameOids(subjectNames, &numNames); + } + + /* certReq */ + certReq.cspHand = cspHand; + certReq.clHand = clHand; + certReq.serialNumber = 0x12345678; // TBD - random? From user? + certReq.numSubjectNames = numNames; + certReq.subjectNames = subjectNames; + + /* TBD - if we're passed in a signing cert, certReq.issuerNameX509 will + * be obtained from that cert. For now we specify "self-signed" cert + * by not providing an issuer name at all. */ + certReq.numIssuerNames = 0; // root for now + certReq.issuerNames = NULL; + certReq.issuerNameX509 = NULL; + certReq.certPublicKey = subjPubKey; + certReq.issuerPrivateKey = signerPrivKey; + certReq.signatureAlg = sigAlg; + certReq.signatureOid = *sigOid; + certReq.notBefore = 0; // TBD - from user + certReq.notAfter = 60 * 60 * 24 * 30; // seconds from now + certReq.numExtensions = numExts; + certReq.extensions = exts; + + reqSet.NumberOfRequests = 1; + reqSet.Requests = &certReq; + + /* a CSSM_TP_CALLERAUTH_CONTEXT to specify an OID */ + memset(&CallerAuthContext, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT)); + memset(&policyId, 0, sizeof(CSSM_FIELD)); + policyId.FieldOid = CSSMOID_APPLE_TP_CSR_GEN; + CallerAuthContext.Policy.NumberOfPolicyIds = 1; + CallerAuthContext.Policy.PolicyIds = &policyId; + + CSSM_RETURN crtn = CSSM_TP_SubmitCredRequest(tpHand, + NULL, // PreferredAuthority + CSSM_TP_AUTHORITY_REQUEST_CERTISSUE, + &reqSet, + &CallerAuthContext, + &estTime, + &refId); + + /* before proceeding, free resources allocated thus far */ + if(!useAllDefaults) { + freeNameOids(subjectNames, numNames); + } + + if(crtn) { + printError("***Error submitting credential request","CSSM_TP_SubmitCredRequest",crtn); + return crtn; + } + crtn = CSSM_TP_RetrieveCredResult(tpHand, + &refId, + NULL, // CallerAuthCredentials + &estTime, + &confirmRequired, + &resultSet); + if(crtn) { + printError("***Error retreiving credential request","CSSM_TP_RetrieveCredResult",crtn); + return crtn; + } + if(resultSet == NULL) { + printf("***CSSM_TP_RetrieveCredResult returned NULL result set.\n"); + return ioErr; + } + encCert = (CSSM_ENCODED_CERT *)resultSet->Results; + *csrData = encCert->CertBlob; + + /* free resources allocated by TP */ + APP_FREE(refId.Data); + APP_FREE(encCert); + APP_FREE(resultSet); + return noErr; +} +#endif + +#if 0 +/* this was added in Michael's integration of PR-3420772, but this is an unimplemented command */ + +int +csr_create(int argc, char * const *argv) +{ + int result = 0; + int ch; + const char *keychainName = NULL; + CSSM_ALGORITHMS algorithm = CSSM_ALGID_RSA; + uint32 keySizeInBits = 512; + OSStatus status; + Boolean always_allow = FALSE; + CFAbsoluteTime from_time = 0.0, to_time = 0.0; + double days = 0.0; + SecAccessRef access = NULL; + CFMutableArrayRef trusted_list = NULL; + CFStringRef description = NULL; + +/* + { "create-keypair", key_create_pair, + "[-a alg] [-s size] [-f date] [-t date] [-d days] [-k keychain] [-u sdux] [-c challenge] description\n" + " [-k keychain] [-u sewx] description\n" + " -a Look for key with alg as the algorithm, can be rsa, dh, dsa or fee (default rsa)\n" + " -s Look for key with keysize in bits\n" + " -c Add challenge to the key as a challange string\n" + " -f Look for a key at least valid from the specified date\n" + " -t Look for a key at least valid to the specified date\n" + " -d Look for a key at least valid for the number of days specified from now\n" + " -u Look for a key with the specified usage flags (s)igning (d)ecryption (u)nwrapping e(x)change\n" + " -k Look in specified keychain rather than the default search list\n" + "If no options are provided ask the user interactively", +*/ + + while ((ch = getopt(argc, argv, "a:s:f:t:d:k:AT:h")) != -1) + { + switch (ch) + { + case 'a': + result = parse_algorithm(optarg, &algorithm); + if (result) + goto loser; + break; + case 's': + keySizeInBits = atoi(optarg); + break; + case 'k': + keychainName = optarg; + break; + case 'A': + always_allow = TRUE; + break; + case 'T': + { + if (!trusted_list) + { + trusted_list = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + } + + if (optarg[0]) + { + SecTrustedApplicationRef app = NULL; + status = SecTrustedApplicationCreateFromPath(optarg, &app); + if (status) + { + sec_error("SecTrustedApplicationCreateFromPath %s: %s", optarg, sec_errstr(status)); + result = 1; + goto loser; + } + + CFArrayAppendValue(trusted_list, app); + CFRelease(app); + break; + } + } + case 'f': + result = parse_time(optarg, &from_time); + if (result) + goto loser; + break; + case 't': + result = parse_time(optarg, &to_time); + if (result) + goto loser; + break; + case 'd': + days = atof(optarg); + if (days < 1) + { + result = 2; + goto loser; + } + from_time = CFAbsoluteTimeGetCurrent(); + to_time = from_time + days * 86400.0; + break; + case '?': + default: + return 2; /* @@@ Return 2 triggers usage message. */ + } + } + + argc -= optind; + argv += optind; + + if (argc == 1) + { + if (*argv[0] == '\0') + { + result = 2; + goto loser; + } + description = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); + } + else if (argc != 0) + return 2; + else + description = CFStringCreateWithCString(NULL, "", kCFStringEncodingUTF8); + + if (always_allow) + { + status = SecAccessCreate(description, NULL, &access); + if (status) + { + sec_perror("SecAccessCreate", status); + result = 1; + } + // @@@ Make the acl always allow now. + } + else + { + status = SecAccessCreate(description, trusted_list, &access); + if (status) + { + sec_perror("SecAccessCreate", status); + result = 1; + } + } + + if (result) + goto loser; + + result = do_csr_create(keychainName, access, algorithm, keySizeInBits, from_time, to_time); + +loser: + if (description) + CFRelease(description); + if (trusted_list) + CFRelease(trusted_list); + if (access) + CFRelease(access); + + return result; +} +#endif diff --git a/SecurityTool/key_create.h b/SecurityTool/key_create.h new file mode 100644 index 00000000..ddb109cc --- /dev/null +++ b/SecurityTool/key_create.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2003-2004,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@ + * + * key_create.h + */ + +#ifndef _KEY_CREATE_H_ +#define _KEY_CREATE_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int key_create_pair(int argc, char * const *argv); + +extern int csr_create(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _KEY_CREATE_H_ */ diff --git a/SecurityTool/keychain_add.c b/SecurityTool/keychain_add.c new file mode 100644 index 00000000..c09f7791 --- /dev/null +++ b/SecurityTool/keychain_add.c @@ -0,0 +1,898 @@ +/* + * Copyright (c) 2003-2009,2011-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * keychain_add.c + */ + +#include "keychain_add.h" +#include "keychain_find.h" +#include "readline.h" +#include "security.h" +#include "access_utils.h" +#include "keychain_utilities.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// SecTrustedApplicationCreateApplicationGroup +#include + + +static int +do_update_generic_password(const char *keychainName, + FourCharCode itemCreator, + FourCharCode itemType, + const char *kind, + const char *value, + const char *comment, + const char *label, + const char *serviceName, + const char *accountName, + const void *passwordData, + SecAccessRef access) +{ + OSStatus status; + SecKeychainRef keychainRef = NULL; + SecKeychainItemRef itemRef = NULL; + + if (keychainName) { + keychainRef = keychain_open(keychainName); + } + itemRef = find_first_generic_password(keychainRef,itemCreator,itemType,kind,value,comment,label,serviceName,accountName); + if (keychainRef) { + CFRelease(keychainRef); + } + if (!itemRef) { + return errSecItemNotFound; + } + + // build list of attributes + SecKeychainAttribute attrs[8]; // maximum number of attributes + SecKeychainAttributeList attrList = { 0, attrs }; + + if ((UInt32)itemCreator != 0) { + attrs[attrList.count].tag = kSecCreatorItemAttr; + attrs[attrList.count].length = sizeof(FourCharCode); + attrs[attrList.count].data = (FourCharCode *)&itemCreator; + attrList.count++; + } + if ((UInt32)itemType != 0) { + attrs[attrList.count].tag = kSecTypeItemAttr; + attrs[attrList.count].length = sizeof(FourCharCode); + attrs[attrList.count].data = (FourCharCode *)&itemType; + attrList.count++; + } + if (kind != NULL) { + attrs[attrList.count].tag = kSecDescriptionItemAttr; + attrs[attrList.count].length = strlen(kind); + attrs[attrList.count].data = (void *)kind; + attrList.count++; + } + if (value != NULL) { + attrs[attrList.count].tag = kSecGenericItemAttr; + attrs[attrList.count].length = strlen(value); + attrs[attrList.count].data = (void *)value; + attrList.count++; + } + if (comment != NULL) { + attrs[attrList.count].tag = kSecCommentItemAttr; + attrs[attrList.count].length = strlen(comment); + attrs[attrList.count].data = (void *)comment; + attrList.count++; + } + if (label != NULL) { + attrs[attrList.count].tag = kSecLabelItemAttr; + attrs[attrList.count].length = strlen(label); + attrs[attrList.count].data = (void *)label; + attrList.count++; + } + if (serviceName != NULL) { + attrs[attrList.count].tag = kSecServiceItemAttr; + attrs[attrList.count].length = strlen(serviceName); + attrs[attrList.count].data = (void *)serviceName; + attrList.count++; + } + if (accountName != NULL) { + attrs[attrList.count].tag = kSecAccountItemAttr; + attrs[attrList.count].length = strlen(accountName); + attrs[attrList.count].data = (void *)accountName; + attrList.count++; + } + + // modify attributes and password data, if provided + status = SecKeychainItemModifyContent(itemRef, &attrList, (passwordData) ? strlen(passwordData) : 0, passwordData); + if (status) { + sec_error("SecKeychainItemModifyContent: %s", sec_errstr(status)); + } + + // modify access, if provided + if (!status && access) { + SecAccessRef curAccess = NULL; + // for historical reasons, we have to modify the item's existing access reference + // (setting the item's access to a freshly created SecAccessRef instance doesn't behave as expected) + status = SecKeychainItemCopyAccess(itemRef, &curAccess); + if (status) { + sec_error("SecKeychainItemCopyAccess: %s", sec_errstr(status)); + } else { + int result = merge_access(curAccess, access); // make changes to the existing access reference + if (result == noErr) { + status = SecKeychainItemSetAccess(itemRef, curAccess); // will prompt + if (status) { + sec_error("SecKeychainItemSetAccess: %s", sec_errstr(status)); + } + } + } + if (curAccess) { + CFRelease(curAccess); + } + } + + CFRelease(itemRef); + + return status; +} + +static int +do_add_generic_password(const char *keychainName, + FourCharCode itemCreator, + FourCharCode itemType, + const char *kind, + const char *value, + const char *comment, + const char *label, + const char *serviceName, + const char *accountName, + const void *passwordData, + SecAccessRef access, + Boolean update) +{ + SecKeychainRef keychain = NULL; + OSStatus result = 0; + SecKeychainItemRef itemRef = NULL; + + // if update flag is specified, try to find and update an existing item + if (update) { + result = do_update_generic_password(keychainName,itemCreator,itemType,kind,value,comment,label,serviceName,accountName,passwordData,access); + if (result == noErr) + return result; + } + + if (keychainName) + { + keychain = keychain_open(keychainName); + if (!keychain) + { + result = 1; + goto cleanup; + } + } + + // set up attribute vector for new item (each attribute consists of {tag, length, pointer}) + SecKeychainAttribute attrs[] = { + { kSecLabelItemAttr, label ? strlen(label) : 0, (char *)label }, + { kSecDescriptionItemAttr, kind ? strlen(kind) : 0, (char *)kind }, + { kSecGenericItemAttr, value ? strlen(value) : 0, (char *)value }, + { kSecCommentItemAttr, comment ? strlen(comment) : 0, (char *)comment }, + { kSecServiceItemAttr, serviceName ? strlen(serviceName) : 0, (char *)serviceName }, + { kSecAccountItemAttr, accountName ? strlen(accountName) : 0, (char *)accountName }, + { (SecKeychainAttrType)0, sizeof(FourCharCode), NULL }, /* placeholder */ + { (SecKeychainAttrType)0, sizeof(FourCharCode), NULL } /* placeholder */ + }; + SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs }; + attributes.count -= 2; + + if (itemCreator != 0) + { + attrs[attributes.count].tag = kSecCreatorItemAttr; + attrs[attributes.count].data = (FourCharCode *)&itemCreator; + attributes.count++; + } + if (itemType != 0) + { + attrs[attributes.count].tag = kSecTypeItemAttr; + attrs[attributes.count].data = (FourCharCode *)&itemType; + attributes.count++; + } + + result = SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass, + &attributes, + passwordData ? strlen(passwordData) : 0, + passwordData, + keychain, + access, + &itemRef); + + if (result) + { + sec_error("SecKeychainItemCreateFromContent (%s): %s", keychainName ? keychainName : "", sec_errstr(result)); + } + +cleanup: + if (itemRef) + CFRelease(itemRef); + if (keychain) + CFRelease(keychain); + + return result; +} + +static int +do_update_internet_password(const char *keychainName, + FourCharCode itemCreator, + FourCharCode itemType, + const char *kind, + const char *comment, + const char *label, + const char *serverName, + const char *securityDomain, + const char *accountName, + const char *path, + UInt16 port, + SecProtocolType protocol, + SecAuthenticationType authenticationType, + const void *passwordData, + SecAccessRef access) +{ + OSStatus status; + SecKeychainRef keychainRef = NULL; + SecKeychainItemRef itemRef = NULL; + + if (keychainName) { + keychainRef = keychain_open(keychainName); + } + itemRef = find_first_internet_password(keychainRef,itemCreator,itemType,kind,comment,label,serverName, + securityDomain,accountName,path,port,protocol,authenticationType); + if (keychainRef) { + CFRelease(keychainRef); + } + if (!itemRef) { + return errSecItemNotFound; + } + + // build list of attributes + SecKeychainAttribute attrs[12]; // maximum number of attributes + SecKeychainAttributeList attrList = { 0, attrs }; + + if ((UInt32)itemCreator != 0) { + attrs[attrList.count].tag = kSecCreatorItemAttr; + attrs[attrList.count].length = sizeof(FourCharCode); + attrs[attrList.count].data = (FourCharCode *)&itemCreator; + attrList.count++; + } + if ((UInt32)itemType != 0) { + attrs[attrList.count].tag = kSecTypeItemAttr; + attrs[attrList.count].length = sizeof(FourCharCode); + attrs[attrList.count].data = (FourCharCode *)&itemType; + attrList.count++; + } + if (kind != NULL) { + attrs[attrList.count].tag = kSecDescriptionItemAttr; + attrs[attrList.count].length = strlen(kind); + attrs[attrList.count].data = (void *)kind; + attrList.count++; + } + if (comment != NULL) { + attrs[attrList.count].tag = kSecCommentItemAttr; + attrs[attrList.count].length = strlen(comment); + attrs[attrList.count].data = (void *)comment; + attrList.count++; + } + if (label != NULL) { + attrs[attrList.count].tag = kSecLabelItemAttr; + attrs[attrList.count].length = strlen(label); + attrs[attrList.count].data = (void *)label; + attrList.count++; + } + if (serverName != NULL) { + attrs[attrList.count].tag = kSecServerItemAttr; + attrs[attrList.count].length = strlen(serverName); + attrs[attrList.count].data = (void *)serverName; + attrList.count++; + } + if (securityDomain != NULL) { + attrs[attrList.count].tag = kSecSecurityDomainItemAttr; + attrs[attrList.count].length = strlen(securityDomain); + attrs[attrList.count].data = (void *)securityDomain; + attrList.count++; + } + if (accountName != NULL) { + attrs[attrList.count].tag = kSecAccountItemAttr; + attrs[attrList.count].length = strlen(accountName); + attrs[attrList.count].data = (void *)accountName; + attrList.count++; + } + if (path != NULL) { + attrs[attrList.count].tag = kSecPathItemAttr; + attrs[attrList.count].length = strlen(path); + attrs[attrList.count].data = (void *)path; + attrList.count++; + } + if (port != 0) { + attrs[attrList.count].tag = kSecPortItemAttr; + attrs[attrList.count].length = sizeof(UInt16); + attrs[attrList.count].data = (UInt16 *)&port; + attrList.count++; + } + if ((UInt32)protocol != 0) { + attrs[attrList.count].tag = kSecProtocolItemAttr; + attrs[attrList.count].length = sizeof(SecProtocolType); + attrs[attrList.count].data = (SecProtocolType *)&protocol; + attrList.count++; + } + if ((UInt32)authenticationType != 0) { + attrs[attrList.count].tag = kSecAuthenticationTypeItemAttr; + attrs[attrList.count].length = sizeof(SecAuthenticationType); + attrs[attrList.count].data = (SecAuthenticationType *)&authenticationType; + attrList.count++; + } + + // modify attributes and password data, if provided + status = SecKeychainItemModifyContent(itemRef, &attrList, (passwordData) ? strlen(passwordData) : 0, passwordData); + if (status) { + sec_error("SecKeychainItemModifyContent: %s", sec_errstr(status)); + } + + // modify access, if provided + if (!status && access) { + status = modify_access(itemRef, access); + } + + CFRelease(itemRef); + + return status; +} + +static int +do_add_internet_password(const char *keychainName, + FourCharCode itemCreator, + FourCharCode itemType, + const char *kind, + const char *comment, + const char *label, + const char *serverName, + const char *securityDomain, + const char *accountName, + const char *path, + UInt16 port, + SecProtocolType protocol, + SecAuthenticationType authenticationType, + const void *passwordData, + SecAccessRef access, + Boolean update) +{ + SecKeychainRef keychain = NULL; + SecKeychainItemRef itemRef = NULL; + OSStatus result = 0; + + // if update flag is specified, try to find and update an existing item + if (update) { + result = do_update_internet_password(keychainName,itemCreator,itemType,kind,comment,label,serverName, + securityDomain,accountName,path,port,protocol,authenticationType, + passwordData,access); + if (result == noErr) + return result; + } + + if (keychainName) + { + keychain = keychain_open(keychainName); + if (!keychain) + { + result = 1; + goto cleanup; + } + } + + // set up attribute vector for new item (each attribute consists of {tag, length, pointer}) + SecKeychainAttribute attrs[] = { + { kSecLabelItemAttr, label ? strlen(label) : 0, (char *)label }, + { kSecDescriptionItemAttr, kind ? strlen(kind) : 0, (char *)kind }, + { kSecCommentItemAttr, comment ? strlen(comment) : 0, (char *)comment }, + { kSecServerItemAttr, serverName ? strlen(serverName) : 0, (char *)serverName }, + { kSecSecurityDomainItemAttr, securityDomain ? strlen(securityDomain) : 0, (char *)securityDomain }, + { kSecAccountItemAttr, accountName ? strlen(accountName) : 0, (char *)accountName }, + { kSecPathItemAttr, path ? strlen(path) : 0, (char *)path }, + { kSecPortItemAttr, sizeof(UInt16), (UInt16 *)&port }, + { kSecProtocolItemAttr, sizeof(SecProtocolType), (SecProtocolType *)&protocol }, + { kSecAuthenticationTypeItemAttr, sizeof(SecAuthenticationType), (SecAuthenticationType *)&authenticationType }, + { (SecKeychainAttrType)0, sizeof(FourCharCode), NULL }, /* placeholder */ + { (SecKeychainAttrType)0, sizeof(FourCharCode), NULL } /* placeholder */ + }; + SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs }; + attributes.count -= 2; + + if (itemCreator != 0) + { + attrs[attributes.count].tag = kSecCreatorItemAttr; + attrs[attributes.count].data = (FourCharCode *)&itemCreator; + attributes.count++; + } + if (itemType != 0) + { + attrs[attributes.count].tag = kSecTypeItemAttr; + attrs[attributes.count].data = (FourCharCode *)&itemType; + attributes.count++; + } + + result = SecKeychainItemCreateFromContent(kSecInternetPasswordItemClass, + &attributes, + passwordData ? strlen(passwordData) : 0, + passwordData, + keychain, + access, + &itemRef); + + if (result) + { + sec_error("SecKeychainAddInternetPassword %s: %s", keychainName ? keychainName : "", sec_errstr(result)); + } + +cleanup: + if (itemRef) + CFRelease(itemRef); + if (keychain) + CFRelease(keychain); + + return result; +} + +static int +do_add_certificates(const char *keychainName, int argc, char * const *argv) +{ + SecKeychainRef keychain = NULL; + int ix, result = 0; + + if (keychainName) + { + keychain = keychain_open(keychainName); + if (!keychain) + { + result = 1; + goto cleanup; + } + } + + for (ix = 0; ix < argc; ++ix) + { + CSSM_DATA certData = {}; + OSStatus status; + SecCertificateRef certificate = NULL; + + if (read_file(argv[ix], &certData)) + { + result = 1; + continue; + } + + status = SecCertificateCreateFromData(&certData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_UNKNOWN, &certificate); + if (status) + { + sec_perror("SecCertificateCreateFromData", status); + result = 1; + } + else + { + status = SecCertificateAddToKeychain(certificate, keychain); + if (status) + { + if (status == errSecDuplicateItem) + { + if (keychainName) + sec_error("%s: already in %s", argv[ix], keychainName); + else + sec_error("%s: already in default keychain", argv[ix]); + } + else + { + sec_perror("SecCertificateAddToKeychain", status); + } + result = 1; + } + } + + if (certData.Data) + free(certData.Data); + if (certificate) + CFRelease(certificate); + } + +cleanup: + if (keychain) + CFRelease(keychain); + + return result; +} + +int +keychain_add_generic_password(int argc, char * const *argv) +{ + char *serviceName = NULL, *passwordData = NULL, *accountName = NULL; + char *kind = NULL, *label = NULL, *value = NULL, *comment = NULL; + FourCharCode itemCreator = 0, itemType = 0; + int ch, result = 0; + const char *keychainName = NULL; + Boolean access_specified = FALSE; + Boolean always_allow = FALSE; + Boolean update_item = FALSE; + SecAccessRef access = NULL; + CFMutableArrayRef trusted_list = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + OSStatus status; + + /* + * " -a Specify account name (required)\n" + * " -c Specify item creator (optional four-character code)\n" + * " -C Specify item type (optional four-character code)\n" + * " -D Specify kind (default is \"application password\")\n" + * " -G Specify generic attribute (optional)\n" + * " -j Specify comment string (optional)\n" + * " -l Specify label (if omitted, service name is used as default label)\n" + * " -s Specify service name (required)\n" + * " -p Specify password to be added (legacy option, equivalent to -w)\n" + * " -w Specify password to be added\n" + * " -A Allow any application to access this item without warning (insecure, not recommended!)\n" + * " -T Specify an application which may access this item (multiple -T options are allowed)\n" + * " -U Update item if it already exists (if omitted, the item cannot already exist)\n" + */ + + while ((ch = getopt(argc, argv, "a:c:C:D:G:j:l:s:p:w:UAT:")) != -1) + { + switch (ch) + { + case 'a': + accountName = optarg; + break; + case 'c': + result = parse_fourcharcode(optarg, &itemCreator); + if (result) goto cleanup; + break; + case 'C': + result = parse_fourcharcode(optarg, &itemType); + if (result) goto cleanup; + break; + case 'D': + kind = optarg; + break; + case 'G': + value = optarg; + break; + case 'j': + comment = optarg; + break; + case 'l': + label = optarg; + break; + case 's': + serviceName = optarg; + break; + case 'p': + case 'w': + passwordData = optarg; + break; + case 'U': + update_item = TRUE; + break; + case 'A': + always_allow = TRUE; + access_specified = TRUE; + break; + case 'T': + { + if (optarg[0]) + { + SecTrustedApplicationRef app = NULL; + /* check whether the argument specifies an application group */ + const char *groupPrefix = "group://"; + size_t prefixLen = strlen(groupPrefix); + if (strlen(optarg) > prefixLen && !memcmp(optarg, groupPrefix, prefixLen)) { + const char *groupName = &optarg[prefixLen]; + if ((status = SecTrustedApplicationCreateApplicationGroup(groupName, NULL, &app)) != noErr) { + sec_error("SecTrustedApplicationCreateApplicationGroup %s: %s", optarg, sec_errstr(status)); + } + } else { + if ((status = SecTrustedApplicationCreateFromPath(optarg, &app)) != noErr) { + sec_error("SecTrustedApplicationCreateFromPath %s: %s", optarg, sec_errstr(status)); + } + } + + if (status) { + result = 1; + goto cleanup; + } + + CFArrayAppendValue(trusted_list, app); + CFRelease(app); + } + access_specified = TRUE; + break; + } + case '?': + default: + result = 2; + goto cleanup; /* @@@ Return 2 triggers usage message. */ + } + } + + argc -= optind; + argv += optind; + + if (!accountName || !serviceName) + { + result = 2; + goto cleanup; + } + else if (argc > 0) + { + keychainName = argv[0]; + if (argc > 1 || *keychainName == '\0') + { + result = 2; + goto cleanup; + } + } + + if (access_specified) + { + const char *accessName = (label) ? label : (serviceName) ? serviceName : (accountName) ? accountName : ""; + if ((result = create_access(accessName, always_allow, trusted_list, &access)) != 0) + goto cleanup; + } + + result = do_add_generic_password(keychainName, + itemCreator, + itemType, + kind, + value, + comment, + (label) ? label : serviceName, + serviceName, + accountName, + passwordData, + access, + update_item); + +cleanup: + if (trusted_list) + CFRelease(trusted_list); + if (access) + CFRelease(access); + + return result; +} + +int +keychain_add_internet_password(int argc, char * const *argv) +{ + char *serverName = NULL, *securityDomain = NULL, *accountName = NULL, *path = NULL, *passwordData = NULL; + char *kind = NULL, *comment = NULL, *label = NULL; + FourCharCode itemCreator = 0, itemType = 0; + UInt16 port = 0; + SecProtocolType protocol = 0; + SecAuthenticationType authenticationType = OSSwapHostToBigInt32('dflt'); + int ch, result = 0; + const char *keychainName = NULL; + Boolean access_specified = FALSE; + Boolean always_allow = FALSE; + Boolean update_item = FALSE; + SecAccessRef access = NULL; + CFMutableArrayRef trusted_list = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + OSStatus status; + + /* + * " -a Specify account name (required)\n" + * " -c Specify item creator (optional four-character code)\n" + * " -C Specify item type (optional four-character code)\n" + * " -d Specify security domain string (optional)\n" + * " -D Specify kind (default is \"Internet password\")\n" + * " -j Specify comment string (optional)\n" + * " -l Specify label (if omitted, server name is used as default label)\n" + * " -p Specify path string (optional)\n" + * " -P Specify port number (optional)\n" + * " -r Specify protocol (optional four-character SecProtocolType, e.g. \"http\", \"ftp \")\n" + * " -s Specify server name (required)\n" + * " -t Specify authentication type (as a four-character SecAuthenticationType, default is \"dflt\")\n" + * " -w Specify password to be added\n" + * " -A Allow any application to access this item without warning (insecure, not recommended!)\n" + * " -T Specify an application which may access this item (multiple -T options are allowed)\n" + * " -U Update item if it already exists (if omitted, the item cannot already exist)\n" + */ + + while ((ch = getopt(argc, argv, "a:c:C:d:D:j:l:p:P:r:s:t:w:UAT:h")) != -1) + { + switch (ch) + { + case 'a': + accountName = optarg; + break; + case 'c': + result = parse_fourcharcode(optarg, &itemCreator); + if (result) goto cleanup; + break; + case 'C': + result = parse_fourcharcode(optarg, &itemType); + if (result) goto cleanup; + break; + case 'd': + securityDomain = optarg; + break; + case 'D': + kind = optarg; + break; + case 'j': + comment = optarg; + break; + case 'l': + label = optarg; + break; + case 'p': + path = optarg; + break; + case 'P': + port = atoi(optarg); + break; + case 'r': + result = parse_fourcharcode(optarg, &protocol); + if (result) goto cleanup; + break; + case 's': + serverName = optarg; + break; + case 't': + result = parse_fourcharcode(optarg, &authenticationType); + if (result) goto cleanup; + /* auth type attribute is special */ + authenticationType = OSSwapHostToBigInt32(authenticationType); + break; + case 'w': + passwordData = optarg; + break; + case 'U': + update_item = TRUE; + break; + case 'A': + always_allow = TRUE; + access_specified = TRUE; + break; + case 'T': + { + if (optarg[0]) + { + SecTrustedApplicationRef app = NULL; + /* check whether the argument specifies an application group */ + const char *groupPrefix = "group://"; + size_t prefixLen = strlen(groupPrefix); + if (strlen(optarg) > prefixLen && !memcmp(optarg, groupPrefix, prefixLen)) { + const char *groupName = &optarg[prefixLen]; + if ((status = SecTrustedApplicationCreateApplicationGroup(groupName, NULL, &app)) != noErr) { + sec_error("SecTrustedApplicationCreateApplicationGroup %s: %s", optarg, sec_errstr(status)); + } + } else { + if ((status = SecTrustedApplicationCreateFromPath(optarg, &app)) != noErr) { + sec_error("SecTrustedApplicationCreateFromPath %s: %s", optarg, sec_errstr(status)); + } + } + + if (status) { + result = 1; + goto cleanup; + } + + CFArrayAppendValue(trusted_list, app); + CFRelease(app); + } + access_specified = TRUE; + break; + } + case '?': + default: + result = 2; + goto cleanup; /* @@@ Return 2 triggers usage message. */ + } + } + + argc -= optind; + argv += optind; + + if (!accountName || !serverName) + { + result = 2; + goto cleanup; + } + else if (argc > 0) + { + keychainName = argv[0]; + if (argc > 1 || *keychainName == '\0') + { + result = 2; + goto cleanup; + } + } + + if (access_specified) + { + const char *accessName = (label) ? label : (serverName) ? serverName : (accountName) ? accountName : ""; + if ((result = create_access(accessName, always_allow, trusted_list, &access)) != 0) + goto cleanup; + } + + result = do_add_internet_password(keychainName, + itemCreator, + itemType, + kind, + comment, + (label) ? label : serverName, + serverName, + securityDomain, + accountName, + path, + port, + protocol, + authenticationType, + passwordData, + access, + update_item); + +cleanup: + if (trusted_list) + CFRelease(trusted_list); + if (access) + CFRelease(access); + + return result; +} + +int +keychain_add_certificates(int argc, char * const *argv) +{ + int ch, result = 0; + const char *keychainName = NULL; + while ((ch = getopt(argc, argv, "hk:")) != -1) + { + switch (ch) + { + case 'k': + keychainName = optarg; + if (*keychainName == '\0') + return 2; + break; + case '?': + default: + return 2; /* @@@ Return 2 triggers usage message. */ + } + } + + argc -= optind; + argv += optind; + + if (argc == 0) + return 2; + + result = do_add_certificates(keychainName, argc, argv); + + return result; +} diff --git a/SecurityTool/keychain_add.h b/SecurityTool/keychain_add.h new file mode 100644 index 00000000..4d16e314 --- /dev/null +++ b/SecurityTool/keychain_add.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2003-2004,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.h + */ + +#ifndef _KEYCHAIN_ADD_H_ +#define _KEYCHAIN_ADD_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int keychain_add_internet_password(int argc, char * const *argv); + +extern int keychain_add_certificates(int argc, char * const *argv); + +extern int keychain_add_generic_password(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _KEYCHAIN_ADD_H_ */ diff --git a/SecurityTool/keychain_create.c b/SecurityTool/keychain_create.c new file mode 100644 index 00000000..edb0e554 --- /dev/null +++ b/SecurityTool/keychain_create.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2003-2004,2008,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@ + * + * keychain_create.c + */ + +#include "keychain_create.h" + +#include "readline.h" +#include "security.h" + +#include +#include +#include +#include +#include +#include + +static int +do_create(const char *keychain, const char *password, Boolean do_prompt) +{ + SecKeychainRef keychainRef = NULL; + OSStatus result; + + result = SecKeychainCreate(keychain, password ? strlen(password) : 0, password, do_prompt, NULL, &keychainRef); + if (keychainRef) + CFRelease(keychainRef); + + if (result) + sec_error("SecKeychainCreate %s: %s", keychain, sec_errstr(result)); + + return result; +} + +int +keychain_create(int argc, char * const *argv) +{ + int free_keychain = 0, zero_password = 0; + char *password = NULL, *keychain = NULL; + int ch, result = 0; + Boolean do_prompt = FALSE; + +/* AG: getopts optstring name [args] + AG: while loop calling getopt is used to extract password from cl from user + password is the only option to keychain_create + optstring is a string containing the legitimate option + characters. If such a character is followed by a colon, + the option requires an argument, so getopt places a + pointer to the following text in the same argv-element, or + the text of the following argv-element, in optarg. +*/ + while ((ch = getopt(argc, argv, "hp:P")) != -1) + { + switch (ch) + { + case 'p': + password = optarg; + break; + case 'P': + do_prompt = TRUE; + break; + case '?': + default: + return 2; /* @@@ Return 2 triggers usage message. */ + } + } +/* + AG: The external variable optind is the index of the next + array element of argv[] to be processed; it communicates + from one call of getopt() to the next which element to + process. + The variable optind is the index of the next element of the argv[] vector to be processed. It shall be initialized to 1 by the system, and getopt() shall update it when it finishes with each element of argv[]. When an element of argv[] contains multiple option characters, it is unspecified how getopt() determines which options have already been processed. + +*/ + argc -= optind; + argv += optind; + + if (argc > 0) + keychain = *argv; + else + { + fprintf(stderr, "keychain to create: "); + keychain = readline(NULL, 0); + if (!keychain) + { + result = -1; + goto loser; + } + + free_keychain = 1; + if (*keychain == '\0') + goto loser; + } + + if (!password && !do_prompt) + { + int compare = 1; + int tries; + + for (tries = 3; tries-- > 0;) + { + char *firstpass; + + password = getpass("password for new keychain: "); + if (!password) + { + result = -1; + goto loser; + } + + firstpass = malloc(strlen(password) + 1); + strcpy(firstpass, password); + password = getpass("retype password for new keychain: "); + compare = password ? strcmp(password, firstpass) : 1; + memset(firstpass, 0, strlen(firstpass)); + free(firstpass); + if (!password) + { + result = -1; + goto loser; + } + + if (compare) + { + fprintf(stderr, "passwords don't match\n"); + memset(password, 0, strlen(password)); + } + else + { + zero_password = 1; + break; + } + } + + if (compare) + { + result = 1; + goto loser; + } + } + + do + { + result = do_create(keychain, password, do_prompt); + if (zero_password) + memset(password, 0, strlen(password)); + if (result) + goto loser; + + argc--; + argv++; + if (!free_keychain) + keychain = *argv; + } while (argc > 0); + +loser: + if (free_keychain) + free(keychain); + + return result; +} diff --git a/SecurityTool/keychain_create.h b/SecurityTool/keychain_create.h new file mode 100644 index 00000000..04056614 --- /dev/null +++ b/SecurityTool/keychain_create.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2003-2004,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_create.h + */ + +#ifndef _KEYCHAIN_CREATE_H_ +#define _KEYCHAIN_CREATE_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int keychain_create(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _KEYCHAIN_CREATE_H_ */ diff --git a/SecurityTool/keychain_delete.c b/SecurityTool/keychain_delete.c new file mode 100644 index 00000000..ba6e972b --- /dev/null +++ b/SecurityTool/keychain_delete.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2003-2010,2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * keychain_delete.c + */ + +#include "keychain_delete.h" +#include "keychain_find.h" + +#include "keychain_utilities.h" +#include "security.h" +#include +#include +#include +#include + +static int +do_delete(CFTypeRef keychainOrArray) +{ + /* @@@ SecKeychainDelete should really take a CFTypeRef argument. */ + OSStatus result = SecKeychainDelete((SecKeychainRef)keychainOrArray); + if (result) + { + /* @@@ Add printing of keychainOrArray. */ + sec_perror("SecKeychainDelete", result); + } + + return result; +} + +static int +do_delete_certificate(CFTypeRef keychainOrArray, const char *name, const char *hash, Boolean deleteTrust) +{ + OSStatus result = noErr; + SecKeychainItemRef itemToDelete = NULL; + if (!name && !hash) { + return 2; + } + + itemToDelete = find_unique_certificate(keychainOrArray, name, hash); + if (itemToDelete) { + if (deleteTrust) { + result = SecTrustSettingsRemoveTrustSettings((SecCertificateRef)itemToDelete, + kSecTrustSettingsDomainUser); + if (result && result != errSecItemNotFound) { + sec_perror("SecTrustSettingsRemoveTrustSettings (user)", result); + } + if (geteuid() == 0) { + result = SecTrustSettingsRemoveTrustSettings((SecCertificateRef)itemToDelete, + kSecTrustSettingsDomainAdmin); + if (result && result != errSecItemNotFound) { + sec_perror("SecTrustSettingsRemoveTrustSettings (admin)", result); + } + } + } + result = SecKeychainItemDelete(itemToDelete); + if (result) { + sec_perror("SecKeychainItemDelete", result); + goto cleanup; + } + } else { + result = 1; + fprintf(stderr, "Unable to delete certificate matching \"%s\"", + (name) ? name : (hash) ? hash : ""); + } + +cleanup: + safe_CFRelease(&itemToDelete); + + return result; +} + +int +keychain_delete_certificate(int argc, char * const *argv) +{ + CFTypeRef keychainOrArray = NULL; + char *name = NULL; + char *hash = NULL; + Boolean delete_trust = FALSE; + int ch, result = 0; + + while ((ch = getopt(argc, argv, "hc:Z:t")) != -1) + { + switch (ch) + { + case 'c': + name = optarg; + break; + case 'Z': + hash = optarg; + break; + case 't': + delete_trust = TRUE; + break; + case '?': + default: + result = 2; /* @@@ Return 2 triggers usage message. */ + goto cleanup; + } + } + + argc -= optind; + argv += optind; + + keychainOrArray = keychain_create_array(argc, argv); + + result = do_delete_certificate(keychainOrArray, name, hash, delete_trust); + +cleanup: + safe_CFRelease(&keychainOrArray); + + return result; +} + +int +keychain_delete(int argc, char * const *argv) +{ + CFTypeRef keychainOrArray = NULL; + int ch, result = 0; + + while ((ch = getopt(argc, argv, "h")) != -1) + { + switch (ch) + { + case '?': + default: + return 2; /* @@@ Return 2 triggers usage message. */ + } + } + + argc -= optind; + argv += optind; + + keychainOrArray = keychain_create_array(argc, argv); + + result = do_delete(keychainOrArray); + if (keychainOrArray) + CFRelease(keychainOrArray); + + return result; +} diff --git a/SecurityTool/keychain_delete.h b/SecurityTool/keychain_delete.h new file mode 100644 index 00000000..03e00878 --- /dev/null +++ b/SecurityTool/keychain_delete.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2003-2009 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_delete.h + */ + +#ifndef _KEYCHAIN_DELETE_H_ +#define _KEYCHAIN_DELETE_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int keychain_delete_certificate(int argc, char * const *argv); + +extern int keychain_delete(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _KEYCHAIN_DELETE_H_ */ diff --git a/SecurityTool/keychain_export.c b/SecurityTool/keychain_export.c new file mode 100644 index 00000000..50de121c --- /dev/null +++ b/SecurityTool/keychain_export.c @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2003-2004,2006,2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * keychain_export.c + */ + +#include "keychain_export.h" +#include "keychain_utilities.h" +#include "security.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef enum { + IS_Certs, + IS_AllKeys, + IS_PubKeys, + IS_PrivKeys, + IS_Identities, + IS_All +} ItemSpec; + +/* + * Add all itmes of specified class from a keychain to an array. + * Item class are things like kSecCertificateItemClass, and + * CSSM_DL_DB_RECORD_PRIVATE_KEY. Identities are searched separately. + */ +static OSStatus addKcItems( + SecKeychainRef kcRef, + SecItemClass itemClass, // kSecCertificateItemClass + CFMutableArrayRef outArray, + unsigned *numItems) // UPDATED on return +{ + OSStatus ortn; + SecKeychainSearchRef srchRef; + + ortn = SecKeychainSearchCreateFromAttributes(kcRef, + itemClass, + NULL, // no attrs + &srchRef); + if(ortn) { + sec_perror("SecKeychainSearchCreateFromAttributes", ortn); + return ortn; + } + for(;;) { + SecKeychainItemRef itemRef; + ortn = SecKeychainSearchCopyNext(srchRef, &itemRef); + if(ortn) { + if(ortn == errSecItemNotFound) { + /* normal search end */ + ortn = noErr; + } + else { + sec_perror("SecIdentitySearchCopyNext", ortn); + } + break; + } + CFArrayAppendValue(outArray, itemRef); + CFRelease(itemRef); // array owns the item + (*numItems)++; + } + CFRelease(srchRef); + return ortn; +} + +/* + * Add all SecIdentityRefs from a keychain into an array. + */ +static OSStatus addIdentities( + SecKeychainRef kcRef, + CFMutableArrayRef outArray, + unsigned *numItems) // UPDATED on return +{ + /* Search for all identities */ + SecIdentitySearchRef srchRef; + OSStatus ortn = SecIdentitySearchCreate(kcRef, + 0, // keyUsage - any + &srchRef); + if(ortn) { + sec_perror("SecIdentitySearchCreate", ortn); + return ortn; + } + + do { + SecIdentityRef identity; + ortn = SecIdentitySearchCopyNext(srchRef, &identity); + if(ortn) { + if(ortn == errSecItemNotFound) { + /* normal search end */ + ortn = noErr; + } + else { + sec_perror("SecIdentitySearchCopyNext", ortn); + } + break; + } + CFArrayAppendValue(outArray, identity); + + /* the array has the retain count we need */ + CFRelease(identity); + (*numItems)++; + } while(ortn == noErr); + CFRelease(srchRef); + return ortn; +} + +static int do_keychain_export( + SecKeychainRef kcRef, + SecExternalFormat externFormat, + ItemSpec itemSpec, + const char *passphrase, + int doPem, + const char *fileName) +{ + int result = 0; + CFIndex numItems; + unsigned numPrivKeys = 0; + unsigned numPubKeys = 0; + unsigned numCerts = 0; + unsigned numIdents = 0; + OSStatus ortn; + uint32 expFlags = 0; // SecItemImportExportFlags + SecKeyImportExportParameters keyParams; + CFStringRef passStr = NULL; + CFDataRef outData = NULL; + unsigned len; + + /* gather items */ + CFMutableArrayRef exportItems = CFArrayCreateMutable(NULL, 0, + &kCFTypeArrayCallBacks); + switch(itemSpec) { + case IS_Certs: + ortn = addKcItems(kcRef, kSecCertificateItemClass, exportItems, &numCerts); + if(ortn) { + result = 1; + goto loser; + } + break; + + case IS_PrivKeys: + ortn = addKcItems(kcRef, CSSM_DL_DB_RECORD_PRIVATE_KEY, exportItems, + &numPrivKeys); + if(ortn) { + result = 1; + goto loser; + } + break; + + case IS_PubKeys: + ortn = addKcItems(kcRef, CSSM_DL_DB_RECORD_PUBLIC_KEY, exportItems, + &numPubKeys); + if(ortn) { + result = 1; + goto loser; + } + break; + + case IS_AllKeys: + ortn = addKcItems(kcRef, CSSM_DL_DB_RECORD_PRIVATE_KEY, exportItems, + &numPrivKeys); + if(ortn) { + result = 1; + goto loser; + } + ortn = addKcItems(kcRef, CSSM_DL_DB_RECORD_PUBLIC_KEY, exportItems, + &numPubKeys); + if(ortn) { + result = 1; + goto loser; + } + break; + + case IS_All: + /* No public keys here - PKCS12 doesn't support them */ + ortn = addKcItems(kcRef, kSecCertificateItemClass, exportItems, &numCerts); + if(ortn) { + result = 1; + goto loser; + } + ortn = addKcItems(kcRef, CSSM_DL_DB_RECORD_PRIVATE_KEY, exportItems, + &numPrivKeys); + if(ortn) { + result = 1; + goto loser; + } + break; + + case IS_Identities: + ortn = addIdentities(kcRef, exportItems, &numIdents); + if(ortn) { + result = 1; + goto loser; + } + if(numIdents) { + numPrivKeys += numIdents; + numCerts += numIdents; + } + break; + default: + sec_error("Internal error parsing item_spec"); + result = 1; + goto loser; + } + + numItems = CFArrayGetCount(exportItems); + if(externFormat == kSecFormatUnknown) { + /* Use default export format per set of items */ + if(numItems > 1) { + externFormat = kSecFormatPEMSequence; + } + else if(numCerts) { + externFormat = kSecFormatX509Cert; + } + else { + externFormat = kSecFormatOpenSSL; + } + } + if(doPem) { + expFlags |= kSecItemPemArmour; + } + + /* + * Key related arguments, ignored if we're not exporting keys. + * Always specify some kind of passphrase - default is secure passkey. + */ + memset(&keyParams, 0, sizeof(keyParams)); + keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; + if(passphrase != NULL) { + passStr = CFStringCreateWithCString(NULL, passphrase, kCFStringEncodingASCII); + keyParams.passphrase = passStr; + } + else { + keyParams.flags = kSecKeySecurePassphrase; + } + + /* Go */ + ortn = SecKeychainItemExport(exportItems, externFormat, expFlags, &keyParams, + &outData); + if(ortn) { + sec_perror("SecKeychainItemExport", ortn); + result = 1; + goto loser; + } + + len = CFDataGetLength(outData); + if(fileName) { + int rtn = writeFile(fileName, CFDataGetBytePtr(outData), len); + if(rtn == 0) { + if(!do_quiet) { + fprintf(stderr, "...%u bytes written to %s\n", len, fileName); + } + } + else { + sec_error("Error writing to %s: %s", fileName, strerror(errno)); + result = 1; + } + } + else { + int irtn = write(STDOUT_FILENO, CFDataGetBytePtr(outData), len); + if(irtn != (int)len) { + perror("write"); + } + } +loser: + if(exportItems) { + CFRelease(exportItems); + } + if(passStr) { + CFRelease(passStr); + } + if(outData) { + CFRelease(outData); + } + return result; +} + +int +keychain_export(int argc, char * const *argv) +{ + int ch, result = 0; + + char *outFile = NULL; + char *kcName = NULL; + SecKeychainRef kcRef = NULL; + SecExternalFormat externFormat = kSecFormatUnknown; + ItemSpec itemSpec = IS_All; + int wrapped = 0; + int doPem = 0; + const char *passphrase = NULL; + + while ((ch = getopt(argc, argv, "k:o:t:f:P:wph")) != -1) + { + switch (ch) + { + case 'k': + kcName = optarg; + break; + case 'o': + outFile = optarg; + break; + case 't': + if(!strcmp("certs", optarg)) { + itemSpec = IS_Certs; + } + else if(!strcmp("allKeys", optarg)) { + itemSpec = IS_AllKeys; + } + else if(!strcmp("pubKeys", optarg)) { + itemSpec = IS_PubKeys; + } + else if(!strcmp("privKeys", optarg)) { + itemSpec = IS_PrivKeys; + } + else if(!strcmp("identities", optarg)) { + itemSpec = IS_Identities; + } + else if(!strcmp("all", optarg)) { + itemSpec = IS_All; + } + else { + return 2; /* @@@ Return 2 triggers usage message. */ + } + break; + case 'f': + if(!strcmp("openssl", optarg)) { + externFormat = kSecFormatOpenSSL; + } + else if(!strcmp("openssh1", optarg)) { + externFormat = kSecFormatSSH; + } + else if(!strcmp("openssh2", optarg)) { + externFormat = kSecFormatSSHv2; + } + else if(!strcmp("bsafe", optarg)) { + externFormat = kSecFormatBSAFE; + } + else if(!strcmp("raw", optarg)) { + externFormat = kSecFormatRawKey; + } + else if(!strcmp("pkcs7", optarg)) { + externFormat = kSecFormatPKCS7; + } + else if(!strcmp("pkcs8", optarg)) { + externFormat = kSecFormatWrappedPKCS8; + } + else if(!strcmp("pkcs12", optarg)) { + externFormat = kSecFormatPKCS12; + } + else if(!strcmp("netscape", optarg)) { + externFormat = kSecFormatNetscapeCertSequence; + } + else if(!strcmp("x509", optarg)) { + externFormat = kSecFormatX509Cert; + } + else if(!strcmp("pemseq", optarg)) { + externFormat = kSecFormatPEMSequence; + } + else { + return 2; /* @@@ Return 2 triggers usage message. */ + } + break; + case 'w': + wrapped = 1; + break; + case 'p': + doPem = 1; + break; + case 'P': + passphrase = optarg; + break; + case '?': + default: + return 2; /* @@@ Return 2 triggers usage message. */ + } + } + + if(wrapped) { + switch(externFormat) { + case kSecFormatOpenSSL: + case kSecFormatUnknown: // i.e., use default + externFormat = kSecFormatWrappedOpenSSL; + break; + case kSecFormatSSH: + externFormat = kSecFormatWrappedSSH; + break; + case kSecFormatSSHv2: + /* there is no wrappedSSHv2 */ + externFormat = kSecFormatWrappedOpenSSL; + break; + case kSecFormatWrappedPKCS8: + /* proceed */ + break; + default: + sec_error("Don't know how to wrap in specified format/type"); + return 2; /* @@@ Return 2 triggers usage message. */ + } + } + + if(kcName) { + kcRef = keychain_open(kcName); + if(kcRef == NULL) { + return 1; + } + } + result = do_keychain_export(kcRef, externFormat, itemSpec, + passphrase, doPem, outFile); + + if(kcRef) { + CFRelease(kcRef); + } + return result; +} diff --git a/SecurityTool/keychain_export.h b/SecurityTool/keychain_export.h new file mode 100644 index 00000000..fde99da6 --- /dev/null +++ b/SecurityTool/keychain_export.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2003-2004,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_export.h + */ + +#ifndef _KEYCHAIN_EXPORT_H_ +#define _KEYCHAIN_EXPORT_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int keychain_export(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _KEYCHAIN_EXPORT_H_ */ diff --git a/SecurityTool/keychain_find.c b/SecurityTool/keychain_find.c new file mode 100644 index 00000000..23f56859 --- /dev/null +++ b/SecurityTool/keychain_find.c @@ -0,0 +1,1341 @@ +/* + * Copyright (c) 2003-2010,2012-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * keychain_find.c + */ + +#include "keychain_find.h" + +#include "keychain_utilities.h" +#include "readline.h" +#include "security.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// SecDigestGetData, SecKeychainSearchCreateForCertificateByEmail, SecCertificateFindByEmail +#include + +Boolean gDeleteIt = 0; + +// find_first_generic_password +// +// Returns a SecKeychainItemRef for the first item +// which matches the specified attributes. Caller is +// responsible for releasing the item (with CFRelease). +// +SecKeychainItemRef +find_first_generic_password(CFTypeRef keychainOrArray, + FourCharCode itemCreator, + FourCharCode itemType, + const char *kind, + const char *value, + const char *comment, + const char *label, + const char *serviceName, + const char *accountName) +{ + OSStatus status = noErr; + SecKeychainSearchRef searchRef = NULL; + SecKeychainItemRef itemRef = NULL; + + SecKeychainAttribute attrs[8]; // maximum number of searchable attributes + SecKeychainAttributeList attrList = { 0, attrs }; + + // the primary key for a generic password item (i.e. the combination of + // attributes which determine whether the item is unique) consists of: + // { kSecAccountItemAttr, kSecServiceItemAttr } + // + // if we have a primary key, we don't need to search on other attributes + // (and we don't want to, if non-primary attributes are being updated) + Boolean primaryKey = (accountName && serviceName); + + // build the attribute list for searching + if ((UInt32)itemCreator != 0 && !primaryKey) { + attrs[attrList.count].tag = kSecCreatorItemAttr; + attrs[attrList.count].length = sizeof(FourCharCode); + attrs[attrList.count].data = (FourCharCode *)&itemCreator; + attrList.count++; + } + if ((UInt32)itemType != 0 && !primaryKey) { + attrs[attrList.count].tag = kSecTypeItemAttr; + attrs[attrList.count].length = sizeof(FourCharCode); + attrs[attrList.count].data = (FourCharCode *)&itemType; + attrList.count++; + } + if (kind != NULL && !primaryKey) { + attrs[attrList.count].tag = kSecDescriptionItemAttr; + attrs[attrList.count].length = strlen(kind); + attrs[attrList.count].data = (void*)kind; + attrList.count++; + } + if (value != NULL && !primaryKey) { + attrs[attrList.count].tag = kSecGenericItemAttr; + attrs[attrList.count].length = strlen(value); + attrs[attrList.count].data = (void*)value; + attrList.count++; + } + if (comment != NULL && !primaryKey) { + attrs[attrList.count].tag = kSecCommentItemAttr; + attrs[attrList.count].length = strlen(comment); + attrs[attrList.count].data = (void*)comment; + attrList.count++; + } + if (label != NULL && !primaryKey) { + attrs[attrList.count].tag = kSecLabelItemAttr; + attrs[attrList.count].length = strlen(label); + attrs[attrList.count].data = (void*)label; + attrList.count++; + } + if (serviceName != NULL) { + attrs[attrList.count].tag = kSecServiceItemAttr; + attrs[attrList.count].length = strlen(serviceName); + attrs[attrList.count].data = (void*)serviceName; + attrList.count++; + } + if (accountName != NULL) { + attrs[attrList.count].tag = kSecAccountItemAttr; + attrs[attrList.count].length = strlen(accountName); + attrs[attrList.count].data = (void*)accountName; + attrList.count++; + } + + status = SecKeychainSearchCreateFromAttributes(keychainOrArray, kSecGenericPasswordItemClass, &attrList, &searchRef); + if (status) { + sec_perror("SecKeychainSearchCreateFromAttributes", status); + goto cleanup; + } + // we're only interested in the first match, if there is a match at all + status = SecKeychainSearchCopyNext(searchRef, &itemRef); + if (status) { + itemRef = NULL; + } + +cleanup: + if (searchRef) + CFRelease(searchRef); + + return itemRef; +} + +// find_first_internet_password +// +// Returns a SecKeychainItemRef for the first item +// which matches the specified attributes. Caller is +// responsible for releasing the item (with CFRelease). +// +SecKeychainItemRef +find_first_internet_password(CFTypeRef keychainOrArray, + FourCharCode itemCreator, + FourCharCode itemType, + const char *kind, + const char *comment, + const char *label, + const char *serverName, + const char *securityDomain, + const char *accountName, + const char *path, + UInt16 port, + SecProtocolType protocol, + SecAuthenticationType authenticationType) +{ + OSStatus status = noErr; + SecKeychainSearchRef searchRef = NULL; + SecKeychainItemRef itemRef = NULL; + + SecKeychainAttribute attrs[12]; // maximum number of searchable attributes + SecKeychainAttributeList attrList = { 0, attrs }; + + // the primary key for an internet password item (i.e. the combination of + // attributes which determine whether the item is unique) consists of: + // { kSecAccountItemAttr, kSecSecurityDomainItemAttr, kSecServerItemAttr, + // kSecProtocolItemAttr, kSecAuthenticationTypeItemAttr, + // kSecPortItemAttr, kSecPathItemAttr } + // + // if we have a primary key, we don't need to search on other attributes. + // (and we don't want to, if non-primary attributes are being updated) + Boolean primaryKey = (accountName && securityDomain && serverName && + protocol && authenticationType && port && path); + + // build the attribute list for searching + if ((UInt32)itemCreator != 0 && !primaryKey) { + attrs[attrList.count].tag = kSecCreatorItemAttr; + attrs[attrList.count].length = sizeof(FourCharCode); + attrs[attrList.count].data = (FourCharCode *)&itemCreator; + attrList.count++; + } + if ((UInt32)itemType != 0 && !primaryKey) { + attrs[attrList.count].tag = kSecTypeItemAttr; + attrs[attrList.count].length = sizeof(FourCharCode); + attrs[attrList.count].data = (FourCharCode *)&itemType; + attrList.count++; + } + if (kind != NULL && !primaryKey) { + attrs[attrList.count].tag = kSecDescriptionItemAttr; + attrs[attrList.count].length = strlen(kind); + attrs[attrList.count].data = (void*)kind; + attrList.count++; + } + if (comment != NULL && !primaryKey) { + attrs[attrList.count].tag = kSecCommentItemAttr; + attrs[attrList.count].length = strlen(comment); + attrs[attrList.count].data = (void*)comment; + attrList.count++; + } + if (label != NULL && !primaryKey) { + attrs[attrList.count].tag = kSecLabelItemAttr; + attrs[attrList.count].length = strlen(label); + attrs[attrList.count].data = (void*)label; + attrList.count++; + } + if (serverName != NULL) { + attrs[attrList.count].tag = kSecServerItemAttr; + attrs[attrList.count].length = strlen(serverName); + attrs[attrList.count].data = (void*)serverName; + attrList.count++; + } + if (securityDomain != NULL) { + attrs[attrList.count].tag = kSecSecurityDomainItemAttr; + attrs[attrList.count].length = strlen(securityDomain); + attrs[attrList.count].data = (void *)securityDomain; + attrList.count++; + } + if (accountName != NULL) { + attrs[attrList.count].tag = kSecAccountItemAttr; + attrs[attrList.count].length = strlen(accountName); + attrs[attrList.count].data = (void *)accountName; + attrList.count++; + } + if (path != NULL) { + attrs[attrList.count].tag = kSecPathItemAttr; + attrs[attrList.count].length = strlen(path); + attrs[attrList.count].data = (void *)path; + attrList.count++; + } + if (port != 0) { + attrs[attrList.count].tag = kSecPortItemAttr; + attrs[attrList.count].length = sizeof(UInt16); + attrs[attrList.count].data = (UInt16 *)&port; + attrList.count++; + } + if ((UInt32)protocol != 0) { + attrs[attrList.count].tag = kSecProtocolItemAttr; + attrs[attrList.count].length = sizeof(SecProtocolType); + attrs[attrList.count].data = (SecProtocolType *)&protocol; + attrList.count++; + } + if ((UInt32)authenticationType != 0) { + attrs[attrList.count].tag = kSecAuthenticationTypeItemAttr; + attrs[attrList.count].length = sizeof(SecAuthenticationType); + attrs[attrList.count].data = (SecAuthenticationType *)&authenticationType; + attrList.count++; + } + + status = SecKeychainSearchCreateFromAttributes(keychainOrArray, kSecInternetPasswordItemClass, &attrList, &searchRef); + if (status) { + sec_perror("SecKeychainSearchCreateFromAttributes", status); + goto cleanup; + } + // we're only interested in the first match, if there is a match at all + status = SecKeychainSearchCopyNext(searchRef, &itemRef); + if (status) { + itemRef = NULL; + } + +cleanup: + if (searchRef) + CFRelease(searchRef); + + return itemRef; +} + +// find_unique_certificate +// +// Returns a SecKeychainItemRef for the certificate +// in the specified keychain (or keychain list) +// which is a unique match for either the specified name +// or SHA-1 hash. If more than one match exists, the +// certificate is not unique and none are returned. Caller is +// responsible for releasing the item (with CFRelease). +// +SecKeychainItemRef +find_unique_certificate(CFTypeRef keychainOrArray, + const char *name, + const char *hash) +{ + OSStatus status = noErr; + SecKeychainSearchRef searchRef = NULL; + SecKeychainItemRef uniqueItemRef = NULL; + + status = SecKeychainSearchCreateFromAttributes(keychainOrArray, kSecCertificateItemClass, NULL, &searchRef); + if (status) { + return uniqueItemRef; + } + + // check input hash string and convert to data + CSSM_DATA hashData = { 0, NULL }; + if (hash) { + CSSM_SIZE len = strlen(hash)/2; + hashData.Length = len; + hashData.Data = (uint8 *)malloc(hashData.Length); + fromHex(hash, &hashData); + } + + // filter candidates against the hash (or the name, if no hash provided) + CFStringRef matchRef = (name) ? CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8) : NULL; + Boolean exactMatch = FALSE; + + CSSM_DATA certData = { 0, NULL }; + SecKeychainItemRef candidate = NULL; + + while (SecKeychainSearchCopyNext(searchRef, &candidate) == noErr) { + SecCertificateRef cert = (SecCertificateRef)candidate; + if (SecCertificateGetData(cert, &certData) != noErr) { + safe_CFRelease(&candidate); + continue; + } + if (hash) { + uint8 candidate_sha1_hash[20]; + CSSM_DATA digest; + digest.Length = sizeof(candidate_sha1_hash); + digest.Data = candidate_sha1_hash; + if ((SecDigestGetData(CSSM_ALGID_SHA1, &digest, &certData) == CSSM_OK) && + (hashData.Length == digest.Length) && + (!memcmp(hashData.Data, digest.Data, digest.Length))) { + exactMatch = TRUE; + uniqueItemRef = candidate; // currently retained + break; // we're done - can't get more exact than this + } + } else { + // copy certificate name + CFStringRef nameRef = NULL; + if ((SecCertificateCopyCommonName(cert, &nameRef) != noErr) || nameRef == NULL) { + safe_CFRelease(&candidate); + continue; // no name, so no match is possible + } + CFIndex nameLen = CFStringGetLength(nameRef); + CFIndex bufLen = 1 + CFStringGetMaximumSizeForEncoding(nameLen, kCFStringEncodingUTF8); + char *nameBuf = (char *)malloc(bufLen); + if (!CFStringGetCString(nameRef, nameBuf, bufLen-1, kCFStringEncodingUTF8)) + nameBuf[0]=0; + + CFRange find = { kCFNotFound, 0 }; + if (nameRef && matchRef) + find = CFStringFind(nameRef, matchRef, kCFCompareCaseInsensitive | kCFCompareNonliteral); + Boolean isExact = (find.location == 0 && find.length == nameLen); + if (find.location == kCFNotFound) { + free(nameBuf); + safe_CFRelease(&nameRef); + safe_CFRelease(&candidate); + continue; // no match + } + if (uniqueItemRef) { // got two matches + if (exactMatch && !isExact) { // prior is better; ignore this one + free(nameBuf); + safe_CFRelease(&nameRef); + safe_CFRelease(&candidate); + continue; + } + if (exactMatch == isExact) { // same class of match + if (CFEqual(uniqueItemRef, candidate)) { // same certificate + free(nameBuf); + safe_CFRelease(&nameRef); + safe_CFRelease(&candidate); + continue; + } + // ambiguity - must fail + sec_error("\"%s\" is ambiguous, matches more than one certificate", name); + free(nameBuf); + safe_CFRelease(&nameRef); + safe_CFRelease(&candidate); + safe_CFRelease(&uniqueItemRef); + break; + } + safe_CFRelease(&uniqueItemRef); // about to replace with this one + } + uniqueItemRef = candidate; // currently retained + exactMatch = isExact; + free(nameBuf); + safe_CFRelease(&nameRef); + } + } + + safe_CFRelease(&searchRef); + safe_CFRelease(&matchRef); + if (hashData.Data) { + free(hashData.Data); + } + + return uniqueItemRef; +} + +static OSStatus +do_password_item_printing( SecKeychainItemRef itemRef, + Boolean get_password, + Boolean password_stdout) +{ + OSStatus result = noErr; + void *passwordData = NULL; + UInt32 passwordLength = 0; + + if(get_password) { + result = SecKeychainItemCopyContent(itemRef, NULL, NULL, &passwordLength, &passwordData); + if(result != noErr) return result; + } + if(!password_stdout) { + print_keychain_item_attributes(stdout, itemRef, FALSE, FALSE, FALSE, FALSE); + if(get_password) { + fputs("password: ", stderr); + print_buffer(stderr, passwordLength, passwordData); + fputc('\n', stderr); + } + } else { + char *password = (char *) passwordData; + int doHex = 0; + for(int i=0; i +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern SecKeychainItemRef find_first_generic_password( + CFTypeRef keychainOrArray, + FourCharCode itemCreator, + FourCharCode itemType, + const char *kind, + const char *value, + const char *comment, + const char *label, + const char *serviceName, + const char *accountName); + +extern SecKeychainItemRef find_first_internet_password( + CFTypeRef keychainOrArray, + FourCharCode itemCreator, + FourCharCode itemType, + const char *kind, + const char *comment, + const char *label, + const char *serverName, + const char *securityDomain, + const char *accountName, + const char *path, + UInt16 port, + SecProtocolType protocol, + SecAuthenticationType authenticationType); + +extern SecKeychainItemRef find_unique_certificate( + CFTypeRef keychainOrArray, + const char *name, + const char *hash); + +extern int keychain_find_internet_password(int argc, char * const *argv); + +extern int keychain_delete_internet_password(int argc, char * const *argv); + +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_find_certificate(int argc, char * const *argv); + +extern int keychain_dump(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _KEYCHAIN_FINDINTERNETPASSWORD_H_ */ diff --git a/SecurityTool/keychain_import.c b/SecurityTool/keychain_import.c new file mode 100644 index 00000000..e68c1d4c --- /dev/null +++ b/SecurityTool/keychain_import.c @@ -0,0 +1,484 @@ +/* + * Copyright (c) 2003-2009,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@ + * + * keychain_import.c + */ + +#include "keychain_import.h" +#include "keychain_utilities.h" +#include "access_utils.h" +#include "security.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// SecTrustedApplicationCreateApplicationGroup +#include + +#define KC_IMPORT_KEY_PASSWORD_MESSAGE CFSTR("Enter the password for \"%1$@\":") +#define KC_IMPORT_KEY_PASSWORD_RETRYMESSAGE CFSTR("Sorry, you entered an invalid password.\n\nEnter the password for \"%1$@\":") + +static int do_keychain_import( + SecKeychainRef kcRef, + CFDataRef inData, + SecExternalFormat externFormat, + SecExternalItemType itemType, + SecAccessRef access, + Boolean nonExtractable, + const char *passphrase, + const char *fileName, + char **attrNames, + char **attrValues, + unsigned numExtendedAttributes) +{ + SecKeyImportExportParameters keyParams; + OSStatus ortn; + CFStringRef fileStr; + CFArrayRef outArray = NULL; + int result = 0; + int numCerts = 0; + int numKeys = 0; + int numIdentities = 0; + int tryCount = 0; + CFIndex dex; + CFIndex numItems = 0; + CFStringRef passStr = NULL; + CFStringRef promptStr = NULL; + CFStringRef retryStr = NULL; + + /* + * Specify some kind of passphrase in case caller doesn't know this + * is a wrapped object + */ + memset(&keyParams, 0, sizeof(SecKeyImportExportParameters)); + keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; + if(passphrase != NULL) { + passStr = CFStringCreateWithCString(NULL, passphrase, kCFStringEncodingASCII); + keyParams.passphrase = passStr; + } + else { + keyParams.flags = kSecKeySecurePassphrase; + } + if(nonExtractable) { + // explicitly set the key attributes, omitting the CSSM_KEYATTR_EXTRACTABLE bit + keyParams.keyAttributes = CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_SENSITIVE; + } + keyParams.accessRef = access; + + fileStr = CFStringCreateWithCString(NULL, fileName, kCFStringEncodingUTF8); + if (fileStr) { + CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, fileStr, kCFURLPOSIXPathStyle, FALSE); + if (fileURL) { + CFStringRef nameStr = CFURLCopyLastPathComponent(fileURL); + if (nameStr) { + safe_CFRelease(&fileStr); + fileStr = nameStr; + } + safe_CFRelease(&fileURL); + } + } + promptStr = CFStringCreateWithFormat(NULL, NULL, KC_IMPORT_KEY_PASSWORD_MESSAGE, fileStr); + retryStr = CFStringCreateWithFormat(NULL, NULL, KC_IMPORT_KEY_PASSWORD_RETRYMESSAGE, fileStr); + + while (TRUE) + { + keyParams.alertPrompt = (tryCount == 0) ? promptStr : retryStr; + + ortn = SecKeychainItemImport(inData, + fileStr, + &externFormat, + &itemType, + 0, /* flags not used (yet) */ + &keyParams, + kcRef, + &outArray); + + if(ortn) { + if (ortn == errSecPkcs12VerifyFailure && ++tryCount < 3) { + continue; + } + sec_perror("SecKeychainItemImport", ortn); + result = 1; + goto cleanup; + } + break; + } + + /* + * Parse returned items & report to user + */ + if(outArray == NULL) { + sec_error("No keychain items found"); + result = 1; + goto cleanup; + } + numItems = CFArrayGetCount(outArray); + for(dex=0; dex 1) { + str = "identities"; + } + else { + str = "identity"; + } + fprintf(stdout, "%d %s imported.\n", numIdentities, str); + } + if(numKeys) { + char *str; + if(numKeys > 1) { + str = "keys"; + } + else { + str = "key"; + } + fprintf(stdout, "%d %s imported.\n", numKeys, str); + } + if(numCerts) { + char *str; + if(numCerts > 1) { + str = "certificates"; + } + else { + str = "certificate"; + } + fprintf(stdout, "%d %s imported.\n", numCerts, str); + } + + /* optionally apply extended attributes */ + if(numExtendedAttributes) { + unsigned attrDex; + for(attrDex=0; attrDex (argc - 1)) { + result = 2; /* @@@ Return 2 triggers usage message. */ + goto cleanup; + } + attrNames = (char **)realloc(attrNames, numExtendedAttributes * sizeof(char *)); + attrValues = (char **)realloc(attrValues, numExtendedAttributes * sizeof(char *)); + attrNames[numExtendedAttributes] = optarg; + attrValues[numExtendedAttributes] = argv[optind]; + numExtendedAttributes++; + optind++; + break; + case 'A': + always_allow = TRUE; + access_specified = TRUE; + break; + case 'T': + if (optarg[0]) + { + SecTrustedApplicationRef app = NULL; + OSStatus status = noErr; + /* check whether the argument specifies an application group */ + const char *groupPrefix = "group://"; + size_t prefixLen = strlen(groupPrefix); + if (strlen(optarg) > prefixLen && !memcmp(optarg, groupPrefix, prefixLen)) { + const char *groupName = &optarg[prefixLen]; + if ((status = SecTrustedApplicationCreateApplicationGroup(groupName, NULL, &app)) != noErr) { + sec_error("SecTrustedApplicationCreateApplicationGroup %s: %s", optarg, sec_errstr(status)); + } + } else { + if ((status = SecTrustedApplicationCreateFromPath(optarg, &app)) != noErr) { + sec_error("SecTrustedApplicationCreateFromPath %s: %s", optarg, sec_errstr(status)); + } + } + + if (status) { + result = 1; + goto cleanup; + } + + CFArrayAppendValue(trusted_list, app); + CFRelease(app); + } + access_specified = TRUE; + break; + case '?': + default: + result = 2; /* @@@ Return 2 triggers usage message. */ + goto cleanup; + } + } + + if(wrapped) { + switch(externFormat) { + case kSecFormatOpenSSL: + case kSecFormatUnknown: // i.e., use default + externFormat = kSecFormatWrappedOpenSSL; + break; + case kSecFormatSSH: + externFormat = kSecFormatWrappedSSH; + break; + case kSecFormatSSHv2: + /* there is no wrappedSSHv2 */ + externFormat = kSecFormatWrappedOpenSSL; + break; + case kSecFormatWrappedPKCS8: + /* proceed */ + break; + default: + fprintf(stderr, "Don't know how to wrap in specified format/type\n"); + result = 2; /* @@@ Return 2 triggers usage message. */ + goto cleanup; + } + } + + if(kcName) { + kcRef = keychain_open(kcName); + if(kcRef == NULL) { + return 1; + } + } + if(readFile(inFile, &inFileData, &inFileLen)) { + sec_error("Error reading infile %s: %s", inFile, strerror(errno)); + result = 1; + goto cleanup; + } + inData = CFDataCreate(NULL, inFileData, inFileLen); + if(inData == NULL) { + result = 1; + goto cleanup; + } + free(inFileData); + + if(access_specified) + { + char *accessName = NULL; + CFStringRef fileStr = CFStringCreateWithCString(NULL, inFile, kCFStringEncodingUTF8); + if (fileStr) { + CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, fileStr, kCFURLPOSIXPathStyle, FALSE); + if (fileURL) { + CFStringRef nameStr = CFURLCopyLastPathComponent(fileURL); + if (nameStr) { + CFIndex nameLen = CFStringGetLength(nameStr); + CFIndex bufLen = 1 + CFStringGetMaximumSizeForEncoding(nameLen, kCFStringEncodingUTF8); + accessName = (char *)malloc(bufLen); + if (!CFStringGetCString(nameStr, accessName, bufLen-1, kCFStringEncodingUTF8)) + accessName[0]=0; + nameLen = strlen(accessName); + char *p = &accessName[nameLen]; // initially points to terminating null + while (--nameLen > 0) { + if (*p == '.') { // strip extension, if any + *p = '\0'; + break; + } + p--; + } + safe_CFRelease(&nameStr); + } + safe_CFRelease(&fileURL); + } + safe_CFRelease(&fileStr); + } + + result = create_access(accessName, always_allow, trusted_list, &access); + + if (accessName) { + free(accessName); + } + if (result != 0) { + goto cleanup; + } + } + + result = do_keychain_import(kcRef, inData, externFormat, itemType, access, + nonExtractable, passphrase, inFile, attrNames, + attrValues, numExtendedAttributes); + +cleanup: + safe_CFRelease(&trusted_list); + safe_CFRelease(&access); + safe_CFRelease(&kcRef); + safe_CFRelease(&inData); + + return result; +} diff --git a/SecurityTool/keychain_import.h b/SecurityTool/keychain_import.h new file mode 100644 index 00000000..6fd3d675 --- /dev/null +++ b/SecurityTool/keychain_import.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2003-2004,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_import.h + */ + +#ifndef _KEYCHAIN_IMPORT_H_ +#define _KEYCHAIN_IMPORT_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int keychain_import(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _KEYCHAIN_IMPORT_H_ */ diff --git a/SecurityTool/keychain_list.c b/SecurityTool/keychain_list.c new file mode 100644 index 00000000..a0d42f8b --- /dev/null +++ b/SecurityTool/keychain_list.c @@ -0,0 +1,459 @@ +/* + * Copyright (c) 2003-2010,2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * keychain_list.c + */ + +#include "keychain_list.h" + +#include "keychain_utilities.h" +#include "security.h" + +#include +#include +#include +#include +#include +#include + +// SecKeychainCopyLogin +#include + + +typedef enum +{ + kList, + kAdd, + kRemove, + kSet, +} list_operation; + +static void +display_name(const void *value, void *context) +{ + SecKeychainRef keychain = (SecKeychainRef)value; + UInt32 pathLength = MAXPATHLEN; + char pathName[MAXPATHLEN + 1]; + OSStatus result = SecKeychainGetPath(keychain, &pathLength, pathName); + if (result) + sec_error("SecKeychainGetPath %p: %s", keychain, sec_errstr(result)); + else + fprintf(stdout, " \"%*s\"\n", (int)pathLength, pathName); +} + + +static void +display_list(const char *desc, CFTypeRef keychainOrArray) +{ + if (desc && strlen(desc)) + fprintf(stdout, "%s\n", desc); + + if (!keychainOrArray) + { + fprintf(stdout, " \n"); + } + else if (CFGetTypeID(keychainOrArray) == SecKeychainGetTypeID()) + { + display_name(keychainOrArray, NULL); + } + else + { + CFArrayRef array = (CFArrayRef)keychainOrArray; + CFRange range = { 0, CFArrayGetCount(array) }; + CFArrayApplyFunction(array, range, display_name, NULL); + } +} + +static int +parse_domain(const char *name, SecPreferencesDomain *domain) +{ + size_t len = strlen(name); + + if (!strncmp("user", name, len)) + *domain = kSecPreferencesDomainUser; + else if (!strncmp("system", name, len)) + *domain = kSecPreferencesDomainSystem; + else if (!strncmp("common", name, len)) + *domain = kSecPreferencesDomainCommon; + else if (!strncmp("dynamic", name, len)) + *domain = kSecPreferencesDomainDynamic; + else + { + sec_error("Invalid domain: %s", name); + return 2; + } + + return 0; +} + +const char * +domain2str(SecPreferencesDomain domain) +{ + switch (domain) + { + case kSecPreferencesDomainUser: + return "user"; + case kSecPreferencesDomainSystem: + return "system"; + case kSecPreferencesDomainCommon: + return "common"; + case kSecPreferencesDomainDynamic: + return "dynamic"; + default: + return "unknown"; + } +} + +int +keychain_list(int argc, char * const *argv) +{ + CFTypeRef keychainOrArray = NULL; + CFArrayRef searchList = NULL; + list_operation operation = kList; + SecPreferencesDomain domain = kSecPreferencesDomainUser; + Boolean use_domain = false; + int ch, result = 0; + OSStatus status; + + while ((ch = getopt(argc, argv, "d:hs")) != -1) + { + switch (ch) + { + case 'd': + result = parse_domain(optarg, &domain); + if (result) + return result; + use_domain = true; + break; + case 's': + operation = kSet; + break; + case '?': + default: + return 2; /* @@@ Return 2 triggers usage message. */ + } + } + + argc -= optind; + argv += optind; + + switch (operation) + { + case kAdd: + result = 1; + break; + case kRemove: + result = 1; + break; + case kList: + if (argc > 0) + result = 2; // Show usage + else + { + if (use_domain) + { + status = SecKeychainCopyDomainSearchList(domain, &searchList); + if (status) + { + sec_error("SecKeychainCopyDomainSearchList %s: %s", domain2str(domain), sec_errstr(status)); + result = 1; + } + else + { +#if 0 + fprintf(stdout, "%s search list: ", domain2str(domain)); +#endif + display_list("", searchList); + } + } + else + { + status = SecKeychainCopySearchList(&searchList); + if (status) + { + sec_perror("SecKeychainCopySearchList", status); + result = 1; + } + else + { +#if 0 + display_list("search list:", searchList); +#else + display_list("", searchList); +#endif + } + } + } + break; + case kSet: + keychainOrArray = keychain_create_array(argc, argv); + if (argc == 0) + searchList = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); + else if (argc == 1) + searchList = CFArrayCreate(NULL, &keychainOrArray, 1, &kCFTypeArrayCallBacks); + else + searchList = (CFArrayRef)CFRetain(keychainOrArray); + + if (use_domain) + { + status = SecKeychainSetDomainSearchList(domain, searchList); + if (status) + { + sec_error("SecKeychainSetDomainSearchList %s: %s", domain2str(domain), sec_errstr(status)); + result = 1; + } + } + else + { + status = SecKeychainSetSearchList(searchList); + if (status) + { + sec_perror("SecKeychainSetSearchList", status); + result = 1; + } + } + break; + } + + if (keychainOrArray) + CFRelease(keychainOrArray); + if (searchList) + CFRelease(searchList); + + return result; +} + +int +keychain_default(int argc, char * const *argv) +{ + SecPreferencesDomain domain = kSecPreferencesDomainUser; + SecKeychainRef keychain = NULL; + Boolean use_domain = false; + Boolean do_set = false; + int ch, result = 0; + OSStatus status; + + while ((ch = getopt(argc, argv, "d:hs")) != -1) + { + switch (ch) + { + case 'd': + result = parse_domain(optarg, &domain); + if (result) + return result; + use_domain = true; + break; + case 's': + do_set = true; + break; + case '?': + default: + return 2; /* @@@ Return 2 triggers usage message. */ + } + } + + argc -= optind; + argv += optind; + + if (do_set) + { + if (argc == 1) + keychain = (SecKeychainRef)keychain_create_array(argc, argv); + else if (argc > 0) + return 2; + + if (use_domain) + { + status = SecKeychainSetDomainDefault(domain, keychain); + if (status) + { + sec_error("SecKeychainSetDomainDefault %s: %s", domain2str(domain), sec_errstr(status)); + result = 1; + } + } + else + { + status = SecKeychainSetDefault(keychain); + if (status) + { + sec_perror("SecKeychainSetDefault", status); + result = 1; + } + } + } + else + { + if (argc > 0) + return 2; + + if (use_domain) + { + status = SecKeychainCopyDomainDefault(domain, &keychain); + if (status) + { + sec_error("SecKeychainCopyDomainDefault %s: %s", domain2str(domain), sec_errstr(status)); + result = 1; + } + else + { +#if 0 + fprintf(stdout, "default %s keychain: ", domain2str(domain)); +#endif + display_list("", keychain); + } + } + else + { + status = SecKeychainCopyDefault(&keychain); + if (status) + { + sec_perror("SecKeychainCopyDefault", status); + result = 1; + } + else + { +#if 0 + display_list("default keychain: ", keychain); +#else + display_list("", keychain); +#endif + } + } + } + + if (keychain) + CFRelease(keychain); + + return result; +} + +int +keychain_login(int argc, char * const *argv) +{ + SecPreferencesDomain domain = kSecPreferencesDomainUser; + SecKeychainRef keychain = NULL; + Boolean use_domain = false; + Boolean do_set = false; + int ch, result = 0; + OSStatus status; + + while ((ch = getopt(argc, argv, "d:hs")) != -1) + { + switch (ch) + { + case 'd': + result = parse_domain(optarg, &domain); + if (result) + return result; + use_domain = true; + break; + case 's': + do_set = true; + break; + case '?': + default: + return 2; /* @@@ Return 2 triggers usage message. */ + } + } + + argc -= optind; + argv += optind; + + if (do_set) + { + if (argc == 1) + keychain = (SecKeychainRef)keychain_create_array(argc, argv); + else if (argc > 0) + return 2; + +#if 0 + if (use_domain) + { + status = SecKeychainSetDomainLogin(domain, keychain); + if (status) + { + sec_error("SecKeychainSetDomainLogin %s: %s", domain2str(domain), sec_errstr(status)); + result = 1; + } + } + else + { + status = SecKeychainSetLogin(keychain); + if (status) + { + sec_perror("SecKeychainSetLogin", status); + result = 1; + } + } +#else + result = 1; +#endif + } + else + { + if (argc > 0) + return 2; + + if (use_domain) + { +#if 0 + status = SecKeychainCopyDomainLogin(domain, &keychain); + if (status) + { + sec_error("SecKeychainCopyDomainLogin %s: %s", domain2str(domain), sec_errstr(status)); + result = 1; + } + else + { +#if 0 + fprintf(stdout, "login %s keychain: ", domain2str(domain)); +#endif + display_list("", keychain); + } +#else + result = 1; +#endif + } + else + { + status = SecKeychainCopyLogin(&keychain); + if (status) + { + sec_perror("SecKeychainCopyLogin", status); + result = 1; + } + else + { +#if 0 + display_list("login keychain: ", keychain); +#else + display_list("", keychain); +#endif + } + } + } + + if (keychain) + CFRelease(keychain); + + return result; +} diff --git a/SecurityTool/keychain_list.h b/SecurityTool/keychain_list.h new file mode 100644 index 00000000..54813e13 --- /dev/null +++ b/SecurityTool/keychain_list.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2003-2004,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_list.h + */ + +#ifndef _KEYCHAIN_LIST_H_ +#define _KEYCHAIN_LIST_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int keychain_list(int argc, char * const *argv); + +extern int keychain_default(int argc, char * const *argv); + +extern int keychain_login(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _KEYCHAIN_LIST_H_ */ diff --git a/SecurityTool/keychain_lock.c b/SecurityTool/keychain_lock.c new file mode 100644 index 00000000..806f20f3 --- /dev/null +++ b/SecurityTool/keychain_lock.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2003-2004,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@ + * + * keychain_lock.c + */ + +#include "keychain_lock.h" + +#include "keychain_utilities.h" +#include "readline.h" +#include "security.h" + +#include +#include +#include +#include +#include + +static int +do_lock_all(void) +{ + OSStatus result = SecKeychainLockAll(); + if (result) + sec_perror("SecKeychainLockAll", result); + + return result; +} + +static int +do_lock(const char *keychainName) +{ + SecKeychainRef keychain = NULL; + OSStatus result; + + if (keychainName) + { + keychain = keychain_open(keychainName); + if (!keychain) + { + result = 1; + goto loser; + } + } + + result = SecKeychainLock(keychain); + if (result) + { + sec_error("SecKeychainLock %s: %s", keychainName ? keychainName : "", sec_errstr(result)); + } + +loser: + if (keychain) + CFRelease(keychain); + + return result; +} + +int +keychain_lock(int argc, char * const *argv) +{ + char *keychainName = NULL; + int ch, result = 0; + Boolean lockAll = FALSE; + while ((ch = getopt(argc, argv, "ah")) != -1) + { + switch (ch) + { + case 'a': + lockAll = TRUE; + break; + case '?': + default: + return 2; /* @@@ Return 2 triggers usage message. */ + } + } + argc -= optind; + argv += optind; + + if (argc == 1 && !lockAll) + { + keychainName = argv[0]; + if (*keychainName == '\0') + { + result = 2; + goto loser; + } + } + else if (argc != 0) + return 2; + + if (lockAll) + result = do_lock_all(); + else + result = do_lock(keychainName); + +loser: + + return result; +} diff --git a/SecurityTool/keychain_lock.h b/SecurityTool/keychain_lock.h new file mode 100644 index 00000000..304062a0 --- /dev/null +++ b/SecurityTool/keychain_lock.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2003-2004,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_lock.h + */ + +#ifndef _KEYCHAIN_LOCK_H_ +#define _KEYCHAIN_LOCK_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int keychain_lock(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _KEYCHAIN_LOCK_H_ */ diff --git a/SecurityTool/keychain_recode.c b/SecurityTool/keychain_recode.c new file mode 100644 index 00000000..8aa8a8a4 --- /dev/null +++ b/SecurityTool/keychain_recode.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2003-2005,2009,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@ + * + * keychain_recode.c + */ + +#include "keychain_recode.h" + +#include "keychain_utilities.h" +#include "readline.h" +#include "security.h" + +#include +#include +#include +#include +#include +#include +#include + +// SecKeychainCopyBlob, SecKeychainRecodeKeychain +#include + + +static int +do_recode(const char *keychainName1, const char *keychainName2) +{ + SecKeychainRef keychain1 = NULL, keychain2 = NULL; + CFMutableArrayRef dbBlobArray = NULL; + CFDataRef dbBlob = NULL, extraData = NULL; + OSStatus result; + + if (keychainName1) + { + keychain1 = keychain_open(keychainName1); + if (!keychain1) + { + result = 1; + goto loser; + } + } + + keychain2 = keychain_open(keychainName2); + if (!keychain2) + { + result = 1; + goto loser; + } + + result = SecKeychainCopyBlob(keychain2, &dbBlob); + if (result) + { + sec_error("SecKeychainCopyBlob %s: %s", keychainName2, + sec_errstr(result)); + goto loser; + } + + extraData = CFDataCreate(NULL, NULL, 0); + + dbBlobArray = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks); + if (dbBlobArray) { + CFArrayAppendValue(dbBlobArray, dbBlob); + } + +#if !defined MAC_OS_X_VERSION_10_6 || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 + result = SecKeychainRecodeKeychain(keychain1, dbBlob, extraData); +#else + result = SecKeychainRecodeKeychain(keychain1, dbBlobArray, extraData); +#endif + if (result) + sec_error("SecKeychainRecodeKeychain %s, %s: %s", keychainName1, + keychainName2, sec_errstr(result)); + +loser: + if (dbBlobArray) + CFRelease(dbBlobArray); + if (dbBlob) + CFRelease(dbBlob); + if (extraData) + CFRelease(extraData); + if (keychain1) + CFRelease(keychain1); + if (keychain2) + CFRelease(keychain2); + + return result; +} + +int +keychain_recode(int argc, char * const *argv) +{ + char *keychainName1 = NULL, *keychainName2 = NULL; + int ch, result = 0; + + while ((ch = getopt(argc, argv, "h")) != -1) + { + switch (ch) + { + case '?': + default: + return 2; /* @@@ Return 2 triggers usage message. */ + } + } + argc -= optind; + argv += optind; + + if (argc == 2) + { + keychainName1 = argv[0]; + if (*keychainName1 == '\0') + { + result = 2; + goto loser; + } + + keychainName2 = argv[1]; + if (*keychainName2 == '\0') + { + result = 2; + goto loser; + } + + } + else + return 2; + + result = do_recode(keychainName1, keychainName2); + +loser: + + return result; +} diff --git a/SecurityTool/keychain_recode.h b/SecurityTool/keychain_recode.h new file mode 100644 index 00000000..b4a77255 --- /dev/null +++ b/SecurityTool/keychain_recode.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2003-2005,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_recode.h + */ + +#ifndef _KEYCHAIN_RECODE_H_ +#define _KEYCHAIN_RECODE_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int keychain_recode(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _KEYCHAIN_RECODE_H_ */ diff --git a/SecurityTool/keychain_set_settings.c b/SecurityTool/keychain_set_settings.c new file mode 100644 index 00000000..480e39d9 --- /dev/null +++ b/SecurityTool/keychain_set_settings.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2003-2009,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@ + * + * keychain_set_settings.c + */ + +#include "keychain_set_settings.h" +#include "keychain_utilities.h" +#include "readline.h" +#include "security.h" + +#include +#include +#include +#include +#include +#include +#include + +#define PW_BUF_SIZE 512 /* size of buffer to alloc for password */ + + +static int +do_keychain_set_settings(const char *keychainName, SecKeychainSettings newKeychainSettings) +{ + SecKeychainRef keychain = NULL; + OSStatus result; + + if (keychainName) + { + keychain = keychain_open(keychainName); + if (!keychain) + { + result = 1; + goto cleanup; + } + } + result = SecKeychainSetSettings(keychain, &newKeychainSettings); + if (result) + { + sec_error("SecKeychainSetSettings %s: %s", keychainName ? keychainName : "", sec_errstr(result)); + } + +cleanup: + if (keychain) + CFRelease(keychain); + + return result; +} + + +static int +do_keychain_set_password(const char *keychainName, const char* oldPassword, const char* newPassword) +{ + SecKeychainRef keychain = NULL; + OSStatus result = 1; + UInt32 oldLen = (oldPassword) ? strlen(oldPassword) : 0; + UInt32 newLen = (newPassword) ? strlen(newPassword) : 0; + char *oldPass = (oldPassword) ? (char*)oldPassword : NULL; + char *newPass = (newPassword) ? (char*)newPassword : NULL; + char *oldBuf = NULL; + char *newBuf = NULL; + + if (keychainName) + { + keychain = keychain_open(keychainName); + if (!keychain) + { + result = 1; + goto cleanup; + } + } + + if (!oldPass) { + /* prompt for old password */ + char *pBuf = getpass("Old Password: "); + if (pBuf) { + oldBuf = (char*) calloc(PW_BUF_SIZE, 1); + oldLen = strlen(pBuf); + memcpy(oldBuf, pBuf, oldLen); + bzero(pBuf, oldLen); + oldPass = oldBuf; + } + } + + if (!newPass) { + /* prompt for new password */ + char *pBuf = getpass("New Password: "); + if (pBuf) { + newBuf = (char*) calloc(PW_BUF_SIZE, 1); + newLen = strlen(pBuf); + memcpy(newBuf, pBuf, newLen); + bzero(pBuf, newLen); + } + /* confirm new password */ + pBuf = getpass("Retype New Password: "); + if (pBuf) { + UInt32 confirmLen = strlen(pBuf); + if (confirmLen == newLen && newBuf && + !memcmp(pBuf, newBuf, newLen)) { + newPass = newBuf; + } + bzero(pBuf, confirmLen); + } + } + + if (!oldPass || !newPass) { + sec_error("try again"); + goto cleanup; + } + + /* lock keychain first to remove existing credentials */ + (void)SecKeychainLock(keychain); + + /* change the password */ + result = SecKeychainChangePassword(keychain, oldLen, oldPass, newLen, newPass); + if (result) + { + sec_error("error changing password for \"%s\": %s", + keychainName ? keychainName : "", sec_errstr(result)); + } + +cleanup: + /* if we allocated password buffers, zero and free them */ + if (oldBuf) { + bzero(oldBuf, PW_BUF_SIZE); + free(oldBuf); + } + if (newBuf) { + bzero(newBuf, PW_BUF_SIZE); + free(newBuf); + } + if (keychain) { + CFRelease(keychain); + } + return result; +} + + +int +keychain_set_settings(int argc, char * const *argv) +{ + char *keychainName = NULL; + int ch, result = 0; + SecKeychainSettings newKeychainSettings = + { SEC_KEYCHAIN_SETTINGS_VERS1, FALSE, FALSE, INT_MAX }; + + while ((ch = getopt(argc, argv, "hlt:u")) != -1) + { + switch (ch) + { + case 'l': + newKeychainSettings.lockOnSleep = TRUE; + break; + case 't': + newKeychainSettings.lockInterval = atoi(optarg); + break; + case 'u': + newKeychainSettings.useLockInterval = TRUE; + break; + case '?': + default: + result = 2; /* @@@ Return 2 triggers usage message. */ + goto cleanup; + } + } + + if (newKeychainSettings.lockInterval != INT_MAX) { + // -t was specified, which implies -u + newKeychainSettings.useLockInterval = TRUE; + } else { + // -t was unspecified, so revert to no timeout + newKeychainSettings.useLockInterval = FALSE; + } + + argc -= optind; + argv += optind; + + if (argc == 1) + { + keychainName = argv[0]; + if (*keychainName == '\0') + { + result = 2; + goto cleanup; + } + } + else if (argc != 0) + { + result = 2; + goto cleanup; + } + + result = do_keychain_set_settings(keychainName, newKeychainSettings); + +cleanup: + + return result; +} + +int +keychain_set_password(int argc, char * const *argv) +{ + char *keychainName = NULL; + char *oldPassword = NULL; + char *newPassword = NULL; + int ch, result = 0; + + while ((ch = getopt(argc, argv, "ho:p:")) != -1) + { + switch (ch) + { + case 'o': + oldPassword = optarg; + break; + case 'p': + newPassword = optarg; + break; + case '?': + default: + result = 2; /* @@@ Return 2 triggers usage message. */ + goto cleanup; + } + } + + argc -= optind; + argv += optind; + + if (argc == 1) + { + keychainName = argv[0]; + if (*keychainName == '\0') + { + result = 2; + goto cleanup; + } + } + else if (argc != 0) + { + result = 2; + goto cleanup; + } + + result = do_keychain_set_password(keychainName, oldPassword, newPassword); + +cleanup: + + return result; +} + diff --git a/SecurityTool/keychain_set_settings.h b/SecurityTool/keychain_set_settings.h new file mode 100644 index 00000000..0007fb51 --- /dev/null +++ b/SecurityTool/keychain_set_settings.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2003-2004,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@ + * + * keychain_set_settings.h + */ + +#ifndef _KEYCHAIN_SET_SETTINGS_H_ +#define _KEYCHAIN_SET_SETTINGS_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int keychain_set_settings(int argc, char * const *argv); +extern int keychain_set_password(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _KEYCHAIN_SET_SETTINGS_H_ */ diff --git a/SecurityTool/keychain_show_info.c b/SecurityTool/keychain_show_info.c new file mode 100644 index 00000000..69c065ea --- /dev/null +++ b/SecurityTool/keychain_show_info.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2003-2004,2008-2009,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@ + * + * keychain_show_info.c + */ + +#include "keychain_show_info.h" +#include "keychain_utilities.h" +#include "readline.h" +#include "security.h" + +#include +#include +#include +#include +#include +#include + +static int +do_keychain_show_info(const char *keychainName) +{ + SecKeychainRef keychain = NULL; + SecKeychainSettings keychainSettings = { SEC_KEYCHAIN_SETTINGS_VERS1 }; + OSStatus result; + + if (keychainName) + { + keychain = keychain_open(keychainName); + if (!keychain) + { + result = 1; + goto loser; + } + } + + result = SecKeychainCopySettings(keychain, &keychainSettings); + if (result) + { + sec_error("SecKeychainCopySettings %s: %s", keychainName ? keychainName : "", sec_errstr(result)); + goto loser; + } + + fprintf(stderr,"Keychain \"%s\"%s%s", + keychainName ? keychainName : "", + keychainSettings.lockOnSleep ? " lock-on-sleep" : "", + keychainSettings.useLockInterval ? " use-lock-interval" : ""); + if (keychainSettings.lockInterval == INT_MAX) + fprintf(stderr," no-timeout\n"); + else + fprintf(stderr," timeout=%ds\n", (int)keychainSettings.lockInterval); + +loser: + if (keychain) + CFRelease(keychain); + return result; +} + +int +keychain_show_info(int argc, char * const *argv) +{ + char *keychainName = NULL; + int result = 0; + + if (argc == 2) + { + keychainName = argv[1]; + if (*keychainName == '\0') + { + result = 2; + goto loser; + } + } + else if (argc != 1) + return 2; + + result = do_keychain_show_info(keychainName); + +loser: + return result; +} diff --git a/SecurityTool/keychain_show_info.h b/SecurityTool/keychain_show_info.h new file mode 100644 index 00000000..c371118a --- /dev/null +++ b/SecurityTool/keychain_show_info.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2003-2004,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_show_info.h + */ + +#ifndef _KEYCHAIN_SHOW_INFO_H_ +#define _KEYCHAIN_SHOW_INFO_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int keychain_show_info(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _KEYCHAIN_SHOW_INFO_H_ */ diff --git a/SecurityTool/keychain_unlock.c b/SecurityTool/keychain_unlock.c new file mode 100644 index 00000000..eda34585 --- /dev/null +++ b/SecurityTool/keychain_unlock.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2003-2004,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@ + * + * keychain_unlock.c + */ + +#include "keychain_unlock.h" +#include "readline.h" +#include "keychain_utilities.h" +#include "security.h" + +#include +#include +#include +#include +#include + +static int +do_unlock(const char *keychainName, char *password, Boolean use_password) +{ + SecKeychainRef keychain = NULL; + OSStatus result; + + if (keychainName) + { + keychain = keychain_open(keychainName); + if (!keychain) + { + result = 1; + goto loser; + } + } + + result = SecKeychainUnlock(keychain, password ? strlen(password) : 0, password, use_password); + if (result) + { + sec_error("SecKeychainUnlock %s: %s", keychainName ? keychainName : "", sec_errstr(result)); + } + +loser: + if (keychain) + CFRelease(keychain); + + return result; +} + +int +keychain_unlock(int argc, char * const *argv) +{ + int zero_password = 0; + char *password = NULL; + int ch, result = 0; + Boolean use_password = TRUE; + const char *keychainName = NULL; + + while ((ch = getopt(argc, argv, "hp:u")) != -1) + { + switch (ch) + { + case 'p': + password = optarg; + break; + case 'u': + use_password = FALSE; + break; + case '?': + default: + return 2; /* @@@ Return 2 triggers usage message. */ + } + } + + argc -= optind; + argv += optind; + + if (argc == 1) + { + keychainName = argv[0]; + if (*keychainName == '\0') + { + result = 2; + goto loser; + } + } + else if (argc != 0) + return 2; + + 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); + if (!password) + { + result = -1; + goto loser; + } + zero_password = 1; + } + + result = do_unlock(keychainName, password, use_password); + if (result) + goto loser; + +loser: + if (zero_password) + memset(password, 0, strlen(password)); + + return result; +} diff --git a/SecurityTool/keychain_unlock.h b/SecurityTool/keychain_unlock.h new file mode 100644 index 00000000..a3be1b74 --- /dev/null +++ b/SecurityTool/keychain_unlock.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2003-2004,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_unlock.h + */ + +#ifndef _KEYCHAIN_UNLOCK_H_ +#define _KEYCHAIN_UNLOCK_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int keychain_unlock(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _KEYCHAIN_UNLOCK_H_ */ diff --git a/SecurityTool/keychain_utilities.c b/SecurityTool/keychain_utilities.c new file mode 100644 index 00000000..ae9fcc20 --- /dev/null +++ b/SecurityTool/keychain_utilities.c @@ -0,0 +1,961 @@ +/* + * Copyright (c) 2003-2009,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@ + * + * keychain_utilities.c + */ + +#include "keychain_utilities.h" +#include "security.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "readline.h" + +// SecTrustedApplicationValidateWithPath +#include + + +void check_obsolete_keychain(const char *kcName) +{ + if(kcName == NULL) { + return; + } + if(!strcmp(kcName, "/System/Library/Keychains/X509Anchors")) { + fprintf(stderr, "***************************************************************\n"); + fprintf(stderr, " WARNING\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The keychain you are accessing, X509Anchors, is no longer\n"); + fprintf(stderr, "used by Mac OS X as the system root certificate store.\n"); + fprintf(stderr, "Please read the security man page for information on the \n"); + fprintf(stderr, "add-trusted-cert command. New system root certificates should\n"); + fprintf(stderr, "be added to the Admin Trust Settings domain and to the \n"); + fprintf(stderr, "System keychain in /Library/Keychains.\n"); + fprintf(stderr, "***************************************************************\n"); + } + else if(!strcmp(kcName, "/System/Library/Keychains/X509Certificates")) { + fprintf(stderr, "***************************************************************\n"); + fprintf(stderr, " WARNING\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "The keychain you are accessing, X509Certificates, is no longer\n"); + fprintf(stderr, "used by Mac OS X as the system intermediate certificate\n"); + fprintf(stderr, "store. New system intermediate certificates should be added\n"); + fprintf(stderr, "to the System keychain in /Library/Keychains.\n"); + fprintf(stderr, "***************************************************************\n"); + } +} + +SecKeychainRef +keychain_open(const char *name) +{ + SecKeychainRef keychain = NULL; + OSStatus result; + + check_obsolete_keychain(name); + if (name && name[0] != '/') + { + CFArrayRef dynamic = NULL; + result = SecKeychainCopyDomainSearchList( + kSecPreferencesDomainDynamic, &dynamic); + if (result) + { + sec_error("SecKeychainCopyDomainSearchList %s: %s", + name, sec_errstr(result)); + return NULL; + } + else + { + uint32_t i; + uint32_t count = dynamic ? CFArrayGetCount(dynamic) : 0; + + for (i = 0; i < count; ++i) + { + char pathName[MAXPATHLEN]; + UInt32 ioPathLength = sizeof(pathName); + bzero(pathName, ioPathLength); + keychain = (SecKeychainRef)CFArrayGetValueAtIndex(dynamic, i); + result = SecKeychainGetPath(keychain, &ioPathLength, pathName); + if (result) + { + sec_error("SecKeychainGetPath %s: %s", + name, sec_errstr(result)); + return NULL; + } + if (!strncmp(pathName, name, ioPathLength)) + { + CFRetain(keychain); + CFRelease(dynamic); + return keychain; + } + } + CFRelease(dynamic); + } + } + + result = SecKeychainOpen(name, &keychain); + if (result) + { + sec_error("SecKeychainOpen %s: %s", name, sec_errstr(result)); + } + + return keychain; +} + +CFTypeRef +keychain_create_array(int argc, char * const *argv) +{ + if (argc == 0) + return NULL; + else if (argc == 1) + return keychain_open(argv[0]); + else + { + CFMutableArrayRef keychains = CFArrayCreateMutable(NULL, argc, &kCFTypeArrayCallBacks); + int ix; + for (ix = 0; ix < argc; ++ix) + { + SecKeychainRef keychain = keychain_open(argv[ix]); + if (keychain) + { + CFArrayAppendValue(keychains, keychain); + CFRelease(keychain); + } + } + + return keychains; + } +} + +int +parse_fourcharcode(const char *name, UInt32 *code) +{ + UInt32 cc = 0; + int len = (name) ? strlen(name) : 0; + + // error check the name + if (len != 4) + { + fprintf(stderr, "Error: four-character types must be exactly 4 characters long.\n"); + if (len == 3) { + fprintf(stderr, "(Try \"%s \" instead of \"%s\")\n", name, name); + } + return 1; + } + + int i; + for (i = 0; i < 4; ++i) + { + cc = (cc << 8) | name[i]; + } + + *code = cc; // note: this is in host byte order, suitable for passing to APIs + + return 0; +} + +int +print_keychain_name(FILE *stream, SecKeychainRef keychain) +{ + int result = 0; + char pathName[MAXPATHLEN]; + UInt32 ioPathLength = sizeof(pathName); + OSStatus status = SecKeychainGetPath(keychain, &ioPathLength, pathName); + if (status) + { + sec_perror("SecKeychainGetPath", status); + result = 1; + goto loser; + } + + print_buffer(stream, ioPathLength, pathName); + +loser: + return result; +} + +static void +print_cfdata(FILE *stream, CFDataRef data) +{ + if (data) + return print_buffer(stream, CFDataGetLength(data), CFDataGetBytePtr(data)); + else + fprintf(stream, ""); +} + +static void +print_cfstring(FILE *stream, CFStringRef string) +{ + if (!string) + fprintf(stream, ""); + else + { + const char *utf8 = CFStringGetCStringPtr(string, kCFStringEncodingUTF8); + if (utf8) + fprintf(stream, "%s", utf8); + else + { + CFRange rangeToProcess = CFRangeMake(0, CFStringGetLength(string)); + while (rangeToProcess.length > 0) + { + UInt8 localBuffer[256]; + CFIndex usedBufferLength; + CFIndex numChars = CFStringGetBytes(string, rangeToProcess, + kCFStringEncodingUTF8, '?', FALSE, localBuffer, + sizeof(localBuffer), &usedBufferLength); + if (numChars == 0) + break; // Failed to convert anything... + + fprintf(stream, "%.*s", (int)usedBufferLength, localBuffer); + rangeToProcess.location += numChars; + rangeToProcess.length -= numChars; + } + } + } +} + +static int +print_access(FILE *stream, SecAccessRef access, Boolean interactive) +{ + CFArrayRef aclList = NULL; + CFIndex aclix, aclCount; + int result = 0; + OSStatus status; + + status = SecAccessCopyACLList(access, &aclList); + if (status) + { + sec_perror("SecAccessCopyACLList", status); + result = 1; + goto loser; + } + + aclCount = CFArrayGetCount(aclList); + fprintf(stream, "access: %lu entries\n", aclCount); + for (aclix = 0; aclix < aclCount; ++aclix) + { + CFArrayRef applicationList = NULL; + CFStringRef description = NULL; + CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector = {}; + CFIndex appix, appCount; + + SecACLRef acl = (SecACLRef)CFArrayGetValueAtIndex(aclList, aclix); + 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 loser; + } + + fprintf(stream, " entry %lu:\n authorizations (%lu):", aclix, + (unsigned long)tagCount); + for (tagix = 0; tagix < tagCount; ++tagix) + { + CSSM_ACL_AUTHORIZATION_TAG tag = tags[tagix]; + switch (tag) + { + case CSSM_ACL_AUTHORIZATION_ANY: + fputs(" any", stream); + break; + case CSSM_ACL_AUTHORIZATION_LOGIN: + fputs(" login", stream); + break; + case CSSM_ACL_AUTHORIZATION_GENKEY: + fputs(" genkey", stream); + break; + case CSSM_ACL_AUTHORIZATION_DELETE: + fputs(" delete", stream); + break; + case CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED: + fputs(" export_wrapped", stream); + break; + case CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR: + fputs(" export_clear", stream); + break; + case CSSM_ACL_AUTHORIZATION_IMPORT_WRAPPED: + fputs(" import_wrapped", stream); + break; + case CSSM_ACL_AUTHORIZATION_IMPORT_CLEAR: + fputs(" import_clear", stream); + break; + case CSSM_ACL_AUTHORIZATION_SIGN: + fputs(" sign", stream); + break; + case CSSM_ACL_AUTHORIZATION_ENCRYPT: + fputs(" encrypt", stream); + break; + case CSSM_ACL_AUTHORIZATION_DECRYPT: + fputs(" decrypt", stream); + break; + case CSSM_ACL_AUTHORIZATION_MAC: + fputs(" mac", stream); + break; + case CSSM_ACL_AUTHORIZATION_DERIVE: + fputs(" derive", stream); + break; + case CSSM_ACL_AUTHORIZATION_DBS_CREATE: + fputs(" dbs_create", stream); + break; + case CSSM_ACL_AUTHORIZATION_DBS_DELETE: + fputs(" dbs_delete", stream); + break; + case CSSM_ACL_AUTHORIZATION_DB_READ: + fputs(" db_read", stream); + break; + case CSSM_ACL_AUTHORIZATION_DB_INSERT: + fputs(" db_insert", stream); + break; + case CSSM_ACL_AUTHORIZATION_DB_MODIFY: + fputs(" db_modify", stream); + break; + case CSSM_ACL_AUTHORIZATION_DB_DELETE: + fputs(" db_delete", stream); + break; + case CSSM_ACL_AUTHORIZATION_CHANGE_ACL: + fputs(" change_acl", stream); + break; + case CSSM_ACL_AUTHORIZATION_CHANGE_OWNER: + fputs(" change_owner", stream); + break; + default: + fprintf(stream, " tag=%lu", (unsigned long)tag); + break; + } + } + fputc('\n', stream); + + status = SecACLCopySimpleContents(acl, &applicationList, &description, &promptSelector); + if (status) + { + sec_perror("SecACLCopySimpleContents", status); + continue; + } + + if (promptSelector.flags & CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE) + fputs(" require-password\n", stream); + else + fputs(" don't-require-password\n", stream); + + fputs(" description: ", stream); + print_cfstring(stream, description); + fputc('\n', stream); + + if (applicationList) + { + appCount = CFArrayGetCount(applicationList); + fprintf(stream, " applications (%lu):\n", appCount); + } + else + { + appCount = 0; + fprintf(stream, " applications: \n"); + } + + for (appix = 0; appix < appCount; ++appix) + { + const UInt8* bytes; + SecTrustedApplicationRef app = (SecTrustedApplicationRef)CFArrayGetValueAtIndex(applicationList, appix); + CFDataRef data = NULL; + fprintf(stream, " %lu: ", appix); + status = SecTrustedApplicationCopyData(app, &data); + if (status) + { + sec_perror("SecTrustedApplicationCopyData", status); + continue; + } + + bytes = CFDataGetBytePtr(data); + if (bytes && bytes[0] == 0x2f) { + fprintf(stream, "%s", (const char *)bytes); + if ((status = SecTrustedApplicationValidateWithPath(app, (const char *)bytes)) == noErr) { + fprintf(stream, " (OK)"); + } else { + fprintf(stream, " (status %d)", (int)status); + } + fprintf(stream, "\n"); + } else { + print_cfdata(stream, data); + fputc('\n', stream); + } + if (data) + CFRelease(data); + } + + if (applicationList) + CFRelease(applicationList); + + if (description) + CFRelease(description); + + if (interactive) + { + char buffer[10] = {}; + fprintf(stderr, "Remove this acl? "); + if (readline(buffer, sizeof(buffer)) && buffer[0] == 'y') + { + fprintf(stderr, "removing acl\n"); + status = SecACLRemove(acl); + if (status) + { + sec_perror("SecACLRemove", status); + continue; + } + } + } + } + +loser: + if (aclList) + CFRelease(aclList); + + return result; +} + +int +print_keychain_item_attributes(FILE *stream, SecKeychainItemRef item, Boolean show_data, Boolean show_raw_data, Boolean show_acl, Boolean interactive) +{ + int result = 0; + unsigned int ix; + OSStatus status; + SecKeychainRef keychain = NULL; + SecAccessRef access = NULL; + SecItemClass itemClass = 0; + UInt32 itemID; + SecKeychainAttributeList *attrList = NULL; + SecKeychainAttributeInfo *info = NULL; + UInt32 length = 0; + void *data = NULL; + + status = SecKeychainItemCopyKeychain(item, &keychain); + if (status) + { + sec_perror("SecKeychainItemCopyKeychain", status); + result = 1; + goto loser; + } + + fputs("keychain: ", stream); + result = print_keychain_name(stream, keychain); + fputc('\n', stream); + if (result) + goto loser; + + /* First find out the item class. */ + status = SecKeychainItemCopyAttributesAndData(item, NULL, &itemClass, NULL, NULL, NULL); + if (status) + { + sec_perror("SecKeychainItemCopyAttributesAndData", status); + result = 1; + goto loser; + } + + fputs("class: ", stream); + char buffer[4]; + buffer[3] = itemClass & 0xFF; + buffer[2] = (itemClass >> 8) & 0xFF; + buffer[1] = (itemClass >> 16) & 0xFF; + buffer[0] = (itemClass >> 24) & 0xFF; + + print_buffer(stream, 4, buffer); + fputs("\nattributes:\n", stream); + + switch (itemClass) + { + case kSecInternetPasswordItemClass: + itemID = CSSM_DL_DB_RECORD_INTERNET_PASSWORD; + break; + case kSecGenericPasswordItemClass: + itemID = CSSM_DL_DB_RECORD_GENERIC_PASSWORD; + break; + case 'ashp': /* kSecAppleSharePasswordItemClass */ + itemID = CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD; + break; + default: + itemID = itemClass; + break; + } + + /* Now get the AttributeInfo for it. */ + status = SecKeychainAttributeInfoForItemID(keychain, itemID, &info); + if (status) + { + sec_perror("SecKeychainAttributeInfoForItemID", status); + result = 1; + goto loser; + } + + status = SecKeychainItemCopyAttributesAndData(item, info, &itemClass, &attrList, + show_data ? &length : NULL, + show_data ? &data : NULL); + if (status) + { + sec_perror("SecKeychainItemCopyAttributesAndData", status); + result = 1; + goto loser; + } + + if (info->count != attrList->count) + { + sec_error("info count: %ld != attribute count: %ld", info->count, attrList->count); + result = 1; + goto loser; + } + + for (ix = 0; ix < info->count; ++ix) + { + UInt32 tag = info->tag[ix]; + UInt32 format = info->format[ix]; + SecKeychainAttribute *attribute = &attrList->attr[ix]; + if (tag != attribute->tag) + { + sec_error("attribute %d of %ld info tag: %ld != attribute tag: %ld", ix, info->count, tag, attribute->tag); + result = 1; + goto loser; + } + + fputs(" ", stream); + print_uint32(stream, tag); + switch (format) + { + case CSSM_DB_ATTRIBUTE_FORMAT_STRING: + fputs("", stream); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: + fputs("", stream); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: + fputs("", stream); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM: + fputs("", stream); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_REAL: + fputs("", stream); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE: + fputs("", stream); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_BLOB: + fputs("", stream); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32: + fputs("", stream); + break; + case CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX: + fputs("", stream); + break; + default: + fprintf(stream, "", (int)format); + break; + } + fputs("=", stream); + if (!attribute->length && !attribute->data) + fputs("", stream); + else + { switch (format) + { + case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: + case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: + { + print_uint32(stream, *(UInt32*) attribute->data); + break; + } + + case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32: + { + int n = attribute->length / sizeof(UInt32); + UInt32* ptr = (UInt32*) attribute->data; + + while (n--) + { + print_uint32(stream, *ptr++); + } + } + break; + + default: + { + print_buffer(stream, attribute->length, attribute->data); + } + break; + } + } + fputc('\n', stream); + } + + if (show_data) + { + fputs("data:\n", stream); + print_buffer(stream, length, data); + fputc('\n', stream); + } + + if (show_raw_data) + { + CSSM_DL_DB_HANDLE dldbHandle = {}; + const CSSM_DB_UNIQUE_RECORD *uniqueRecordID = NULL; + CSSM_DATA data = {}; + status = SecKeychainItemGetDLDBHandle(item, &dldbHandle); + if (status) + { + sec_perror("SecKeychainItemGetDLDBHandle", status); + result = 1; + goto loser; + } + + status = SecKeychainItemGetUniqueRecordID(item, &uniqueRecordID); + if (status) + { + sec_perror("SecKeychainItemGetUniqueRecordID", status); + result = 1; + goto loser; + } + + status = CSSM_DL_DataGetFromUniqueRecordId(dldbHandle, uniqueRecordID, NULL, &data); + if (status) + { + sec_perror("CSSM_DL_DataGetFromUniqueRecordId", status); + result = 1; + goto loser; + } + + fputs("raw data:\n", stream); + print_buffer(stream, data.Length, data.Data); + fputc('\n', stream); + + /* @@@ Hmm which allocators should we use here? */ + free(data.Data); + } + + if (show_acl) + { + status = SecKeychainItemCopyAccess(item, &access); + if (status == errSecNoAccessForItem) + fprintf(stream, "no access control for this item\n"); + else + { + if (status) + { + sec_perror("SecKeychainItemCopyAccess", status); + result = 1; + goto loser; + } + + result = print_access(stream, access, interactive); + if (result) + goto loser; + + if (interactive) + { + char buffer[10] = {}; + fprintf(stderr, "Update access? "); + if (readline(buffer, sizeof(buffer)) && buffer[0] == 'y') + { + fprintf(stderr, "Updating access\n"); + status = SecKeychainItemSetAccess(item, access); + if (status) + { + sec_perror("SecKeychainItemSetAccess", status); + result = 1; + goto loser; + } + } + } + } + } + +loser: + if (access) + CFRelease(access); + + if (attrList) + { + status = SecKeychainItemFreeAttributesAndData(attrList, data); + if (status) + sec_perror("SecKeychainItemFreeAttributesAndData", status); + } + + if (info) + { + status = SecKeychainFreeAttributeInfo(info); + if (status) + sec_perror("SecKeychainFreeAttributeInfo", status); + } + + if (keychain) + CFRelease(keychain); + + return result; +} + +static void +print_buffer_hex(FILE *stream, UInt32 length, const void *data) +{ + uint8 *p = (uint8 *) data; + while (length--) + { + int ch = *p++; + fprintf(stream, "%02X", ch); + } +} + +static void +print_buffer_ascii(FILE *stream, UInt32 length, const void *data) +{ + uint8 *p = (uint8 *) data; + while (length--) + { + int ch = *p++; + if (ch >= ' ' && ch <= '~' && ch != '\\') + { + fputc(ch, stream); + } + else + { + fputc('\\', stream); + fputc('0' + ((ch >> 6) & 7), stream); + fputc('0' + ((ch >> 3) & 7), stream); + fputc('0' + ((ch >> 0) & 7), stream); + } + } +} + +void +print_buffer(FILE *stream, UInt32 length, const void *data) +{ + uint8 *p = (uint8 *) data; + Boolean hex = FALSE; + Boolean ascii = FALSE; + UInt32 ix; + for (ix = 0; ix < length; ++ix) + { + int ch = *p++; + if (ch >= ' ' && ch <= '~' && ch != '\\') + ascii = TRUE; + else + hex = TRUE; + } + + if (hex) + { + fputc('0', stream); + fputc('x', stream); + print_buffer_hex(stream, length, data); + if (ascii) + fputc(' ', stream); + fputc(' ', stream); + } + if (ascii) + { + fputc('"', stream); + print_buffer_ascii(stream, length, data); + fputc('"', stream); + } +} + +void +print_uint32(FILE *stream, uint32 n) +{ + n = OSSwapHostToBigInt32 (n); + print_buffer(stream, sizeof(UInt32), &n); +} + +unsigned char +hexValue(char c) +{ + static const char digits[] = "0123456789abcdef"; + char *p; + if ((p = strchr(digits, tolower(c)))) + return p - digits; + else + return 0; +} + +void +fromHex(const char *hexDigits, CSSM_DATA *data) +{ + size_t bytes = strlen(hexDigits) / 2; // (discards malformed odd end) + if (bytes > data->Length) + return; + // length(bytes); // (will assert if we try to grow it) + size_t n; + for (n = 0; n < bytes; n++) { + data->Data[n] = (uint8)(hexValue(hexDigits[2*n]) << 4 | hexValue(hexDigits[2*n+1])); + } +} + +void +safe_CFRelease(void *cfTypeRefPtr) +{ + CFTypeRef *obj = (CFTypeRef *)cfTypeRefPtr; + if (obj && *obj) { + CFRelease(*obj); + *obj = NULL; + } +} + +/* + * map a 6-bit binary value to a printable character. + */ +static const +unsigned char bintoasc[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* + * map 6 bits to a printing char + */ +#define ENC(c) (bintoasc[((c) & 0x3f)]) + +#define PAD '=' + +/* + * map one group of up to 3 bytes at inp to 4 bytes at outp. + * Count is number of valid bytes in *inp; if less than 3, the + * 1 or two extras must be zeros. + */ +static void +encChunk(const unsigned char *inp, + unsigned char *outp, + int count) +{ + unsigned char c1, c2, c3, c4; + + c1 = *inp >> 2; + c2 = ((inp[0] << 4) & 0x30) | ((inp[1] >> 4) & 0xf); + c3 = ((inp[1] << 2) & 0x3c) | ((inp[2] >> 6) & 0x3); + c4 = inp[2] & 0x3f; + *outp++ = ENC(c1); + *outp++ = ENC(c2); + if (count == 1) { + *outp++ = PAD; + *outp = PAD; + } else { + *outp++ = ENC(c3); + if (count == 2) { + *outp = PAD; + } + else { + *outp = ENC(c4); + } + } +} + +static unsigned char * +malloc_enc64_with_lines(const unsigned char *inbuf, + unsigned inlen, + unsigned linelen, + unsigned *outlen) +{ + unsigned outTextLen; + unsigned len; // to malloc, liberal + unsigned olen = 0; // actual output size + unsigned char *outbuf; + unsigned char endbuf[3]; + unsigned i; + unsigned char *outp; + unsigned numLines; + unsigned thisLine; + + outTextLen = ((inlen + 2) / 3) * 4; + if(linelen) { + /* + * linelen must be 0 mod 4 for this to work; round up... + */ + if((linelen & 0x03) != 0) { + linelen = (linelen + 3) & 0xfffffffc; + } + numLines = (outTextLen + linelen - 1)/ linelen; + } + else { + numLines = 1; + } + + /* + * Total output size = encoded text size plus one newline per + * line of output, plus trailing NULL. We always generate newlines + * as \n; when decoding, we tolerate \r\n (Microsoft) or \n. + */ + len = outTextLen + (2 * numLines) + 1; + outbuf = (unsigned char*)malloc(len); + outp = outbuf; + thisLine = 0; + + while(inlen) { + if(inlen < 3) { + for(i=0; i<3; i++) { + if(i < inlen) { + endbuf[i] = inbuf[i]; + } + else { + endbuf[i] = 0; + } + } + encChunk(endbuf, outp, inlen); + inlen = 0; + } + else { + encChunk(inbuf, outp, 3); + inlen -= 3; + inbuf += 3; + } + outp += 4; + thisLine += 4; + olen += 4; + if((linelen != 0) && (thisLine >= linelen) && inlen) { + /* + * last trailing newline added below + * Note we don't split 4-byte output chunks over newlines + */ + *outp++ = '\n'; + olen++; + thisLine = 0; + } + } + *outp++ = '\n'; + olen += 1; + *outlen = olen; + return outbuf; +} + +void +print_buffer_pem(FILE *stream, const char *headerString, UInt32 length, const void *data) +{ + unsigned char *buf; + unsigned bufLen; + + if (headerString) + fprintf(stream, "-----BEGIN %s-----\n", headerString); + buf = malloc_enc64_with_lines(data, length, 64, &bufLen); + fwrite(buf, bufLen, 1, stream); + free(buf); + if (headerString) + fprintf(stream, "-----END %s-----\n", headerString); +} diff --git a/SecurityTool/keychain_utilities.h b/SecurityTool/keychain_utilities.h new file mode 100644 index 00000000..f291bb4f --- /dev/null +++ b/SecurityTool/keychain_utilities.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2003-2009 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_utilities.h + */ + +#ifndef _KEYCHAIN_UTILITIES_H_ +#define _KEYCHAIN_UTILITIES_H_ 1 + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Open a given named keychain. */ +extern SecKeychainRef keychain_open(const char *name); + +/* Return either NULL if argc is 0, or a SecKeychainRef if argc is 1 or a CFArrayRef of SecKeychainRefs if argc is greater than 1. */ +extern CFTypeRef keychain_create_array(int argc, char * const *argv); + +extern int parse_fourcharcode(const char *name, UInt32 *code); + +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_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 void safe_CFRelease(void *cfTypeRefPtr); + +extern void check_obsolete_keychain(const char *kcName); + +#ifdef __cplusplus +} +#endif + +#endif /* _KEYCHAIN_UTILITIES_H_ */ diff --git a/SecurityTool/leaks.c b/SecurityTool/leaks.c new file mode 100644 index 00000000..7508e5e9 --- /dev/null +++ b/SecurityTool/leaks.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2003-2004,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@ + * + * leaks.c + */ + +#include "leaks.h" +#include "security.h" + +#include +#include +#include +#include +#include +#include + +int +leaks(int argc, char *const *argv) +{ + int result = 1; + pid_t child; + pid_t parent = getpid(); + + child = fork(); + switch (child) + { + case -1: + /* Fork failed we're hosed. */ + sec_error("fork: %s", strerror(errno)); + break; + case 0: + { + /* child. */ + char **argvec = (char **)malloc((argc + 2) * sizeof(char *)); + char pidstr[8]; + int ix; + + sprintf(pidstr, "%d", parent); + argvec[0] = "/usr/bin/leaks"; + for (ix = 1; ix < argc; ++ix) + argvec[ix] = argv[ix]; + argvec[ix] = pidstr; + argvec[ix + 1] = NULL; + + execv(argvec[0], argvec); + sec_error("exec: %s", strerror(errno)); + _exit(1); + break; + } + default: + { + /* Parent. */ + int status = 0; + for (;;) + { + /* Wait for the child to exit. */ + pid_t waited_pid = waitpid(child, &status, 0); + if (waited_pid == -1) + { + int error = errno; + /* Keep going if we get interupted but bail out on any + other error. */ + if (error == EINTR) + continue; + + sec_error("waitpid %d: %s", status, strerror(errno)); + break; + } + + if (WIFEXITED(status)) + { + if (WEXITSTATUS(status)) + { + /* Force usage message. */ + result = 2; + sec_error("leaks exited: %d", result); + } + break; + } + else if (WIFSIGNALED(status)) + { + sec_error("leaks terminated by signal: %d", WTERMSIG(status)); + break; + } + } + break; + } + } + + return result; +} diff --git a/SecurityTool/leaks.h b/SecurityTool/leaks.h new file mode 100644 index 00000000..67727f38 --- /dev/null +++ b/SecurityTool/leaks.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2003-2004,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@ + * + * leaks.h + */ + +#ifndef _LEAKS_H_ +#define _LEAKS_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int leaks(int argc, char *const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _LEAKS_H_ */ diff --git a/SecurityTool/mds_install.cpp b/SecurityTool/mds_install.cpp new file mode 100644 index 00000000..de4baf11 --- /dev/null +++ b/SecurityTool/mds_install.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2003-2004,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@ + * + * mds_install.cpp + */ + +#include "mds_install.h" +#include + +int +mds_install(int argc, char * const *argv) +{ + if(argc != 1) { + /* crufty "show usage" return code */ + return 2; + } + + try { + MDSClient::mds().install(); + } + catch(const CssmError &err) { + cssmPerror("MDS_Install", err.error); + return -1; + } + catch(...) { + /* should never happen */ + fprintf(stderr, "Unexpected error on MDS_Install\n"); + return -1; + } + return 0; +} diff --git a/SecurityTool/mds_install.h b/SecurityTool/mds_install.h new file mode 100644 index 00000000..1a80b351 --- /dev/null +++ b/SecurityTool/mds_install.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2003-2004,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@ + * + * mds_install.h + */ + +#ifndef _MDS_INSTALL_H_ +#define _MDS_INSTALL_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int mds_install(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _MDS_INSTALL_H_ */ diff --git a/SecurityTool/readline.c b/SecurityTool/readline.c new file mode 100644 index 00000000..6134c721 --- /dev/null +++ b/SecurityTool/readline.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2003-2004,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@ + * + * readline.c + */ + +#include "readline.h" +#include "security.h" + +#include +#include +#include +#include +#include +#include + +/* Read a line from stdin into buffer as a null terminated string. If buffer is + non NULL use at most buffer_size bytes and return a pointer to buffer. Otherwise + return a newly malloced buffer. + if EOF is read this function returns NULL. */ +char * +readline(char *buffer, int buffer_size) +{ + int ix = 0, bytes_malloced = 0; + + if (!buffer) + { + bytes_malloced = 64; + buffer = (char *)malloc(bytes_malloced); + buffer_size = bytes_malloced; + } + + for (;;++ix) + { + int ch; + + if (ix == buffer_size - 1) + { + if (!bytes_malloced) + break; + bytes_malloced += bytes_malloced; + buffer = (char *)realloc(buffer, bytes_malloced); + buffer_size = bytes_malloced; + } + + ch = getchar(); + if (ch == EOF) + { + if (bytes_malloced) + free(buffer); + return NULL; + } + if (ch == '\n') + break; + buffer[ix] = ch; + } + + /* 0 terminate buffer. */ + buffer[ix] = '\0'; + + return buffer; +} + +/* Read the file name into buffer. On return buffer contains a newly + malloced buffer or length buffer_size. Return 0 on success and -1 on failure. */ +int +read_file(const char *name, CSSM_DATA *outData) +{ + int fd, result; + char *buffer = NULL; + off_t length; + ssize_t bytes_read; + + do { + fd = open(name, O_RDONLY, 0); + } while (fd == -1 && errno == EINTR); + + if (fd == -1) + { + sec_error("open %s: %s", name, strerror(errno)); + result = -1; + goto loser; + } + + length = lseek(fd, 0, SEEK_END); + if (length == -1) + { + sec_error("lseek %s, SEEK_END: %s", name, strerror(errno)); + result = -1; + goto loser; + } + + buffer = malloc(length); + + do { + bytes_read = pread(fd, buffer, length, 0); + } while (bytes_read == -1 && errno == EINTR); + + if (bytes_read == -1) + { + sec_error("pread %s: %s", name, strerror(errno)); + result = -1; + goto loser; + } + if (bytes_read != (ssize_t)length) + { + sec_error("read %s: only read %d of %qu bytes", name, bytes_read, length); + result = -1; + goto loser; + } + + do { + result = close(fd); + } while (result == -1 && errno == EINTR); + if (result == -1) + { + sec_error("close %s: %s", name, strerror(errno)); + goto loser; + } + + outData->Data = (uint8 *)buffer; + outData->Length = (uint32)length; + + return result; + +loser: + if (buffer) + free(buffer); + + return result; +} diff --git a/SecurityTool/readline.h b/SecurityTool/readline.h new file mode 100644 index 00000000..570d7b56 --- /dev/null +++ b/SecurityTool/readline.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2003-2004,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@ + * + * readline.h + */ + +#ifndef _READLINE_H_ +#define _READLINE_H_ 1 + +#include // For CSSM_DATA + +#ifdef __cplusplus +extern "C" { +#endif + +/* Read a line from stdin into buffer as a null terminated string. If buffer is + non NULL use at most buffer_size bytes and return a pointer to buffer. Otherwise + return a newly malloced buffer. + if EOF is read this function returns NULL. */ +extern char *readline(char *buffer, int buffer_size); + +/* Read the file name into buffer. On return outData.Data contains a newly + malloced buffer of outData.Length bytes. Return 0 on success and -1 on failure. */ +extern int read_file(const char *name, CSSM_DATA *outData); + +#ifdef __cplusplus +} +#endif + +#endif /* _READLINE_H_ */ diff --git a/SecurityTool/security.1 b/SecurityTool/security.1 new file mode 100644 index 00000000..4ef08a2e --- /dev/null +++ b/SecurityTool/security.1 @@ -0,0 +1,1418 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. +.\"See Also: +.\"man mdoc.samples for a complete listing of options +.\"man mdoc for the short list of editing options +.Dd March 1, 2012 \" DATE +.Dt security 1 \" Program name and manual section number +.Os Darwin +.Sh NAME \" Section Header - required - don't modify +.Nm security +.\" The following lines are read in generating the apropos(man -k) database. Use only key +.\" words here as the database is built based on the words here and in the .ND line. +.\" Use .Nm macro to designate other names for the documented program. +.Nd Command line interface to keychains and Security framework +.Sh SYNOPSIS \" Section Header - required - don't modify +.Nm +.Op Fl hilqv \" [-hilqv] +.Op Fl p Ar prompt \" [-p prompt] +.Op Ar command \" [command] +.Op Ar command_options \" [command_options] +.Op Ar command_args \" [command_args] +.Sh DESCRIPTION \" Section Header - required - don't modify +A simple command line interface which lets you administer keychains, +manipulate keys and certificates, and do just about anything the +Security framework is capable of from the command line. +.Pp +By default +.Nm +will execute the +.Ar command +supplied and report if anything went wrong. +.Pp +If the +.Fl i +or +.Fl p +options are provided, +.Nm +will enter interactive mode and allow the user to enter multiple commands on stdin. When EOF is read from stdin +.Nm +will exit. +.Pp +Here is a complete list of the options available: +.Bl -tag -width -indent +.It Fl h +If no arguments are specified, show a list of all commands. If arguments are provided, show usage for each the specified commands. This option is essentially the same as the +.Nm help +command. +.It Fl i +Run +.Nm +in interactive mode. A prompt +.Po +.Li security> +by default +.Pc +will be displayed and the user will be able to type commands on stdin until an EOF is encountered. +.It Fl l +Before +.Nm +exits, run +.Dl "/usr/bin/leaks -nocontext" +on itself to see if the command(s) you executed had any leaks. +.It Fl p Ar prompt +This option implies the +.Fl i +option but changes the default prompt to the argument specified instead. +.It Fl q +Will make +.Nm +less verbose. +.It Fl v +Will make +.Nm +more verbose. +.El \" Ends the list +.Pp +.Sh "SECURITY COMMAND SUMMARY" +.Nm +provides a rich variety of commands +.Po Ar command +in the +.Sx SYNOPSIS Pc Ns +, each of which often has a wealth of options, to allow access to +the broad functionality provided by the Security framework. However, +you don't have to master every detail for +.Nm +to be useful to you. +.Pp +Here are brief descriptions of all the +.Nm +commands: +.Pp +.Bl -tag -width user-trust-settings-enable -compact +.It Nm help +Show all commands, or show usage for a command. +.It Nm list-keychains +Display or manipulate the keychain search list. +.It Nm default-keychain +Display or set the default keychain. +.It Nm login-keychain +Display or set the login keychain. +.It Nm create-keychain +Create keychains. +.It Nm delete-keychain +Delete keychains and remove them from the search list. +.It Nm lock-keychain +Lock the specified keychain. +.It Nm unlock-keychain +Unlock the specified keychain. +.It Nm set-keychain-settings +Set settings for a keychain. +.It Nm set-keychain-password +Set password for a keychain. +.It Nm show-keychain-info +Show the settings for keychain. +.It Nm dump-keychain +Dump the contents of one or more keychains. +.It Nm create-keypair +Create an asymmetric key pair. +.It Nm add-generic-password +Add a generic password item. +.It Nm add-internet-password +Add an internet password item. +.It Nm add-certificates +Add certificates to a keychain. +.It Nm find-generic-password +Find a generic password item. +.It Nm delete-generic-password +Delete a generic password item. +.It Nm find-internet-password +Find an internet password item. +.It Nm delete-internet-password +Delete an internet password item. +.It Nm find-certificate +Find a certificate item. +.It Nm find-identity +Find an identity (certificate + private key). +.It Nm delete-certificate +Delete a certificate from a keychain. +.It Nm set-identity-preference +Set the preferred identity to use for a service. +.It Nm get-identity-preference +Get the preferred identity to use for a service. +.It Nm create-db +Create a db using the DL. +.It Nm export +Export items from a keychain. +.It Nm import +Import items into a keychain. +.It Nm cms +Encode or decode CMS messages. +.It Nm install-mds +Install (or re-install) the MDS database. +.It Nm add-trusted-cert +Add trusted certificate(s). +.It Nm remove-trusted-cert +Remove trusted certificate(s). +.It Nm dump-trust-settings +Display contents of trust settings. +.It Nm user-trust-settings-enable +Display or manipulate user-level trust settings. +.It Nm trust-settings-export +Export trust settings. +.It Nm trust-settings-import +Import trust settings. +.It Nm verify-cert +Verify certificate(s). +.It Nm authorize +Perform authorization operations. +.It Nm authorizationdb +Make changes to the authorization policy database. +.It Nm execute-with-privileges +Execute tool with privileges. +.It Nm leaks +Run +.Pa /usr/bin/leaks +on this process. +.It Nm error +Display a descriptive message for the given error code(s). +.El +.Sh "COMMON COMMAND OPTIONS" +This section describes the +.Ar command_options +that are available across all +.Nm +commands. +.Bl -tag -width -indent +.It Fl h +Show a usage message for the specified command. This option is +essentially the same as the +.Ar help +command. +.El +.Sh "SECURITY COMMANDS" +Here (finally) are details on all the +.Nm +commands and the options each accepts. +.Bl -item +.It +.Nm help +.Op Fl h +.Bl -item -offset -indent +Show all commands, or show usage for a command. +.El +.It +.Nm list-keychains +.Op Fl h +.Op Fl d Ar user Ns | Ns Ar system Ns | Ns Ar common Ns | Ns Ar dynamic +.Op Fl s Op Ar keychain... +.Bl -item -offset -indent +Display or manipulate the keychain search list. +.It +.Bl -tag -compact -width -indent +.It Fl d Ar user Ns | Ns Ar system Ns | Ns Ar common Ns | Ns Ar dynamic +Use the specified preference domain. +.It Fl s +Set the search list to the specified keychains. +.El +.El +.It +.Nm default-keychain +.Op Fl h +.Op Fl d Ar user Ns | Ns Ar system Ns | Ns Ar common Ns | Ns Ar dynamic +.Op Fl s Op Ar keychain +.Bl -item -offset -indent +Display or set the default keychain. +.It +.Bl -tag -compact -width -indent +.It Fl d Ar user Ns | Ns Ar system Ns | Ns Ar common Ns | Ns Ar dynamic +Use the specified preference domain. +.It Fl s +Set the default keychain to the specified +.Ar keychain Ns . +Unset it if no keychain is specified. +.El +.El +.It +.Nm login-keychain +.Op Fl h +.Op Fl d Ar user Ns | Ns Ar system Ns | Ns Ar common Ns | Ns Ar dynamic +.Op Fl s Op Ar keychain +.Bl -item -offset -indent +Display or set the login keychain. +.It +.Bl -tag -compact -width -indent +.It Fl d Ar user Ns | Ns Ar system Ns | Ns Ar common Ns | Ns Ar dynamic +Use the specified preference domain. +.It Fl s +Set the login keychain to the specified +.Ar keychain Ns . +Unset it if no keychain is specified. +.El +.El +.It +.Nm create-keychain +.Op Fl hP +.Op Fl p Ar password +.Op Ar keychain... +.Bl -item -offset -indent +Create keychains. +.It +.Bl -tag -compact -width -indent-indent +.It Fl P +Prompt the user for a password using the SecurityAgent. +.It Fl p Ar password +Use +.Ar password +as the password for the keychains being created. +.El +.It +If neither +.Fl P +or +.Fl p Ar password +are specified, the user is prompted for a password on the command line. +.El +.It +.Nm delete-keychain +.Op Fl h +.Op Ar keychain... +.Bl -item -offset -indent +Delete keychains and remove them from the search list. +.El +.It +.Nm lock-keychain +.Op Fl h +.Op Fl a Ns | Ns Ar keychain +.Bl -item -offset -indent +Lock +.Ar keychain Ns +\&, or the default keychain if none is specified. If the +.Fl a +option is specified, all keychains are locked. +.El +.It +.Nm unlock-keychain +.Op Fl hu +.Op Fl p Ar password +.Op Ar keychain +.Bl -item -offset -indent +Unlock +.Ar keychain Ns +\&, or the default keychain if none is specified. +.El +.It +.Nm set-keychain-settings +.Op Fl hlu +.Op Fl t Ar timeout +.Op Ar keychain +.Bl -item -offset -indent +Set settings for +.Ar keychain Ns +\&, or the default keychain if none is specified. +.It +.Bl -tag -compact -width -indent-indent +.It Fl l +Lock keychain when the system sleeps. +.It Fl u +Lock keychain after timeout interval. +.It Fl t Ar timeout +Specify +.Ar timeout +interval in seconds (omitting this option specifies "no timeout"). +.El +.El +.It +.Nm set-keychain-password +.Op Fl h +.Op Fl o Ar oldPassword +.Op Fl p Ar newPassword +.Op Ar keychain +.Bl -item -offset -indent +Set password for +.Ar keychain Ns +\&, or the default keychain if none is specified. +.It +.Bl -tag -compact -width -indent-indent +.It Fl o Ar oldPassword +Old keychain password (if not provided, will prompt) +.It Fl p Ar newPassword +New keychain password (if not provided, will prompt) +.El +.El +.It +.Nm show-keychain-info +.Op Fl h +.Op Ar keychain +.Bl -item -offset -indent +Show the settings for +.Ar keychain Ns +\&. +.El +.It +.Nm dump-keychain +.Op Fl adhir +.Bl -item -offset -indent +Dump the contents of one or more keychains. +.It +.Bl -tag -compact -width -indent-indent +.It Fl a +Dump access control list of items +.It Fl d +Dump (decrypted) data of items +.It Fl i +Interactive access control list editing mode +.It Fl r +Dump raw (encrypted) data of items +.El +.El +.It +.Nm create-keypair +.Op Fl h +.Op Fl a Ar alg +.Op Fl s Ar size +.Op Fl f Ar date +.Op Fl t Ar date +.Op Fl d Ar days +.Op Fl k Ar keychain +.Op Fl A Ns | Ns Fl T Ar appPath +.Op Ar name +.Bl -item -offset -indent +Create an asymmetric key pair. +.It +.Bl -tag -compact -width -indent-indent +.It Fl a Ar alg +Use +.Ar alg +as the algorithm, can be rsa, dh, dsa or fee (default rsa) +.It Fl s Ar size +Specify the keysize in bits (default 512) +.It Fl f Ar date +Make a key valid from the specified date (ex: "13/11/10 3:30pm") +.It Fl t Ar date +Make a key valid to the specified date +.It Fl d Ar days +Make a key valid for the number of days specified from today +.It Fl k Ar keychain +Use the specified keychain rather than the default +.It Fl A +Allow any application to access this key without warning (insecure, not recommended!) +.It Fl T Ar appPath +Specify an application which may access this key (multiple +.Fl T Ns +\& options are allowed) +.El +.El +.It +.Nm add-generic-password +.Op Fl h +.Op Fl a Ar account +.Op Fl s Ar service +.Op Fl w Ar password +.Op Ar options... +.Op Ar keychain +.Bl -item -offset -indent +Add a generic password item. +.It +.Bl -tag -compact -width -indent-indent +.It Fl a Ar account +Specify account name (required) +.It Fl c Ar creator +Specify item creator (optional four-character code) +.It Fl C Ar type +Specify item type (optional four-character code) +.It Fl D Ar kind +Specify kind (default is "application password") +.It Fl G Ar value +Specify generic attribute value (optional) +.It Fl j Ar comment +Specify comment string (optional) +.It Fl l Ar label +Specify label (if omitted, service name is used as default label) +.It Fl s Ar service +Specify service name (required) +.It Fl p Ar password +Specify password to be added (legacy option, equivalent to +.Fl w Ns +\&) +.It Fl w Ar password +Specify password to be added +.It Fl A +Allow any application to access this item without warning (insecure, not recommended!) +.It Fl T Ar appPath +Specify an application which may access this item (multiple +.Fl T Ns +\& options are allowed) +.It Fl U +Update item if it already exists (if omitted, the item cannot already exist) +.El +.It +.Bl -item +By default, the application which creates an item is trusted to access its data without warning. You can remove this default access by explicitly specifying an empty app pathname: +.Fl T Ns +\& "". If no keychain is specified, the password is added to the default keychain. +.El +.El +.It +.Nm add-internet-password +.Op Fl h +.Op Fl a Ar account +.Op Fl s Ar server +.Op Fl w Ar password +.Op Ar options... +.Op Ar keychain +.Bl -item -offset -indent +Add an internet password item. +.It +.Bl -tag -compact -width -indent-indent +.It Fl a Ar account +Specify account name (required) +.It Fl c Ar creator +Specify item creator (optional four-character code) +.It Fl C Ar type +Specify item type (optional four-character code) +.It Fl d Ar domain +Specify security domain string (optional) +.It Fl D Ar kind +Specify kind (default is "application password") +.It Fl j Ar comment +Specify comment string (optional) +.It Fl l Ar label +Specify label (if omitted, service name is used as default label) +.It Fl p Ar path +Specify path string (optional) +.It Fl P Ar port +Specify port number (optional) +.It Fl r Ar protocol +Specify protocol (optional four-character SecProtocolType, e.g. "http", "ftp ") +.It Fl s Ar server +Specify server name (required) +.It Fl t Ar authenticationType +Specify authentication type (as a four-character SecAuthenticationType, default is "dflt") +.It Fl w Ar password +Specify password to be added +.It Fl A +Allow any application to access this item without warning (insecure, not recommended!) +.It Fl T Ar appPath +Specify an application which may access this item (multiple +.Fl T Ns +\& options are allowed) +.It Fl U +Update item if it already exists (if omitted, the item cannot already exist) +.El +.It +.Bl -item +By default, the application which creates an item is trusted to access its data without warning. You can remove this default access by explicitly specifying an empty app pathname: +.Fl T Ns +\& "". If no keychain is specified, the password is added to the default keychain. +.El +.El +.It +.Nm add-certificates +.Op Fl h +.Op Fl k Ar keychain +.Ar file... +.Bl -item -offset -indent +Add certficates contained in the specified +.Ar files +to the default keychain. The files must contain one DER encoded X509 certificate each. +.Bl -tag -compact -width -indent-indent +.It Fl k Ar keychain +Use +.Ar keychain +rather than the default keychain. +.El +.El +.It +.Nm find-generic-password +.Op Fl h +.Op Fl a Ar account +.Op Fl s Ar service +.Op Fl Ar options... +.Op Fl g +.Op Fl Ar keychain... +.Bl -item -offset -indent +Find a generic password item. +.It +.Bl -tag -compact -width -indent-indent +.It Fl a Ar account +Match account string +.It Fl c Ar creator +Match creator (four-character code) +.It Fl C Ar type +Match type (four-character code) +.It Fl D Ar kind +Match kind string +.It Fl G Ar value +Match value string (generic attribute) +.It Fl j Ar comment +Match comment string +.It Fl l Ar label +Match label string +.It Fl s Ar service +Match service string +.It Fl g +Display the password for the item found +.It Fl w +Display the password(only) for the item found +.El +.El +.It +.Nm delete-generic-password +.Op Fl h +.Op Fl a Ar account +.Op Fl s Ar service +.Op Fl Ar options... +.Op Fl Ar keychain... +.Bl -item -offset -indent +Delete a generic password item. +.It +.Bl -tag -compact -width -indent-indent +.It Fl a Ar account +Match account string +.It Fl c Ar creator +Match creator (four-character code) +.It Fl C Ar type +Match type (four-character code) +.It Fl D Ar kind +Match kind string +.It Fl G Ar value +Match value string (generic attribute) +.It Fl j Ar comment +Match comment string +.It Fl l Ar label +Match label string +.It Fl s Ar service +Match service string +.El +.El +.It +.Nm delete-internet-password +.Op Fl h +.Op Fl a Ar account +.Op Fl s Ar server +.Op Ar options... +.Op Ar keychain... +.Bl -item -offset -indent +Delete an internet password item. +.It +.Bl -tag -compact -width -indent-indent +.It Fl a Ar account +Match account string +.It Fl c Ar creator +Match creator (four-character code) +.It Fl C Ar type +Match type (four-character code) +.It Fl d Ar securityDomain +Match securityDomain string +.It Fl D Ar kind +Match kind string +.It Fl j Ar comment +Match comment string +.It Fl l Ar label +Match label string +.It Fl p Ar path +Match path string +.It Fl P Ar port +Match port number +.It Fl r Ar protocol +Match protocol (four-character code) +.It Fl s Ar server +Match server string +.It Fl t Ar authenticationType +Match authenticationType (four-character code) +.El +.El +.It +.Nm find-internet-password +.Op Fl h +.Op Fl a Ar account +.Op Fl s Ar server +.Op Ar options... +.Op Fl g +.Op Ar keychain... +.Bl -item -offset -indent +Find an internet password item. +.It +.Bl -tag -compact -width -indent-indent +.It Fl a Ar account +Match account string +.It Fl c Ar creator +Match creator (four-character code) +.It Fl C Ar type +Match type (four-character code) +.It Fl d Ar securityDomain +Match securityDomain string +.It Fl D Ar kind +Match kind string +.It Fl j Ar comment +Match comment string +.It Fl l Ar label +Match label string +.It Fl p Ar path +Match path string +.It Fl P Ar port +Match port number +.It Fl r Ar protocol +Match protocol (four-character code) +.It Fl s Ar server +Match server string +.It Fl t Ar authenticationType +Match authenticationType (four-character code) +.It Fl g +Display the password for the item found +.It Fl w +Display the password(only) for the item found +.El +.El +.It +.Nm find-certificate +.Op Fl h +.Op Fl a +.Op Fl c Ar name +.Op Fl e Ar emailAddress +.Op Fl m +.Op Fl p +.Op Fl Z +.Op Ar keychain... +.Bl -item -offset -indent +Find a certificate item. If no +.Ar keychain Ns +\& arguments are provided, the default search list is used. +.It +Options: +.Bl -tag -compact -width -indent-indent +.It Fl a +Find all matching certificates, not just the first one +.It Fl c Ar name +Match on +.Ar name Ns +\& when searching (optional) +.It Fl e Ar emailAddress +Match on +.Ar emailAddress Ns +\& when searching (optional) +.It Fl m +Show the email addresses in the certificate +.It Fl p +Output certificate in pem format. Default is to dump the attributes and keychain the cert is in. +.It Fl Z +Print SHA-1 hash of the certificate +.El +.It +.Sy Examples +.Bl -tag -width -indent +.It security> find-certificate -a -p > allcerts.pem +Exports all certificates from all keychains into a pem file called allcerts.pem. +.It security> find-certificate -a -e me@foo.com -p > certs.pem +Exports all certificates from all keychains with the email address +me@foo.com into a pem file called certs.pem. +.It security> find-certificate -a -c MyName -Z login.keychain | grep ^SHA-1 +Print the SHA-1 hash of every certificate in 'login.keychain' whose common name includes 'MyName' +.El +.El +.It +.Nm find-identity +.Op Fl h +.Op Fl p Ar policy +.Op Fl s Ar string +.Op Fl v +.Op Ar keychain... +.Bl -item -offset -indent +Find an identity (certificate + private key) satisfying a given policy. If no +.Ar policy Ns +\& arguments are provided, the X.509 basic policy is assumed. If no +.Ar keychain Ns +\& arguments are provided, the default search list is used. +.It +Options: +.Bl -tag -compact -width -indent-indent +.It Fl p Ar policy +Specify +.Ar policy Ns +\& to evaluate (multiple -p options are allowed). Supported policies: +basic, ssl-client, ssl-server, smime, eap, ipsec, ichat, codesigning, +sys-default, sys-kerberos-kdc +.It Fl s Ar string +Specify optional policy-specific +.Ar string Ns +\& (e.g. a DNS hostname for SSL, or RFC822 email address for S/MIME) +.It Fl v +Show valid identities only (default is to show all identities) +.El +.It +.Sy Examples +.Bl -tag -width -indent +.It security> find-identity -v -p ssl-client +Display valid identities that can be used for SSL client authentication +.It security> find-identity -p ssl-server -s www.domain.com +Display identities for a SSL server running on the host 'www.domain.com' +.It security> find-identity -p smime -s user@domain.com +Display identities that can be used to sign a message from 'user@domain.com' +.El +.El +.It +.Nm delete-certificate +.Op Fl h +.Op Fl c Ar name +.Op Fl Z Ar hash +.Op Fl t +.Op Ar keychain... +.Bl -item -offset -indent +Delete a certificate from a keychain. If no +.Ar keychain Ns +\& arguments are provided, the default search list is used. +.It +.Bl -tag -compact -width -indent-indent +.It Fl c Ar name +Specify certificate to delete by its common name +.It Fl Z Ar hash +Specify certificate to delete by its SHA-1 hash +.It Fl t +Also delete user trust settings for this certificate +.El +.It +The certificate to be deleted must be uniquely specified either by a +string found in its common name, or by its SHA-1 hash. +.El +.It +.Nm set-identity-preference +.Op Fl h +.Op Fl n +.Op Fl c Ar identity +.Op Fl s Ar service +.Op Fl u Ar keyUsage +.Op Fl Z Ar hash +.Op Ar keychain... +.Bl -item -offset -indent +Set the preferred identity to use for a service. +.It +.Bl -tag -compact -width -indent-indent +.It Fl n +Specify no identity (clears existing preference for the given service) +.It Fl c Ar identity +Specify identity by common name of the certificate +.It Fl s Ar service +Specify service (may be a URL, RFC822 email address, DNS host, or other name) for which this identity is to be preferred +.It Fl u Ar keyUsage +Specify key usage (optional) +.It Fl Z Ar hash +Specify identity by SHA-1 hash of certificate (optional) +.El +.It +The identity is located by searching the specified keychain(s) for a certificate whose common name contains +the given identity string. If no keychains are specified to search, the default search list is used. Different +identity preferences can be set for individual key usages. You can differentiate between two identities which contain +the same string by providing a SHA-1 hash of the certificate (in addition to, or instead of, the name.) +.It +.Sy PARTIAL PATHS AND WILDCARDS +.It +Prior to 10.5.4, identity preferences for SSL/TLS client authentication could only be set on a per-URL basis. The +URL being visited had to match the service name exactly for the preference to be in effect. +.It +In 10.5.4, it became possible to specify identity preferences on a per-server basis, by using +a service name with a partial path URL to match more specific paths on the same server. For +example, if an identity preference for "https://www.apache-ssl.org/" exists, it will be in effect for +"https://www.apache-ssl.org/cgi/cert-export", and so on. Note that partial path URLs must end with a trailing +slash character. +.It +Starting with 10.6, it is possible to specify identity preferences on a per-domain +basis, by using the wildcard character '*' as the leftmost component of the service name. Unlike SSL wildcards, +an identity preference wildcard can match more than one subdomain. For example, an identity preference for +the name "*.army.mil" will match "server1.subdomain1.army.mil" or "server2.subdomain2.army.mil". Likewise, +a preference for "*.mil" will match both "server.army.mil" and "server.navy.mil". +.It +.Sy KEY USAGE CODES +.It +.Bl -tag -width -indent + 0 - preference is in effect for all possible key usages (default) + 1 - encryption only + 2 - decryption only + 4 - signing only + 8 - signature verification only + 16 - signing with message recovery only + 32 - signature verification with message recovery only + 64 - key wrapping only + 128 - key unwrapping only + 256 - key derivation only +.It To specify more than one usage, add values together. +.El +.El +.It +.Nm get-identity-preference +.Op Fl h +.Op Fl s Ar service +.Op Fl u Ar keyUsage +.Op Fl p +.Op Fl c +.Op Fl Z +.Bl -item -offset -indent +Get the preferred identity to use for a service. +.It +.Bl -tag -compact -width -indent-indent +.It Fl s Ar service +Specify service (may be a URL, RFC822 email address, DNS host, or other name) +.It Fl u Ar keyUsage +Specify key usage (optional) +.It Fl p +Output identity certificate in pem format +.It Fl c +Print common name of the preferred identity certificate +.It Fl Z +Print SHA-1 hash of the preferred identity certificate +.El +.El +.It +.Nm create-db +.Op Fl aho0 +.Op Fl g Ar dl Ns | Ns Ar cspdl +.Op Fl m Ar mode +.Op Ar name +.Bl -item -offset -indent +Create a db using the DL. If +.Ar name +isn't provided +.Nm +will prompt the user to type a name. +.It +Options: +.Bl -tag -compact -width -indent-indent +.It Fl a +Turn off autocommit +.It Fl g Ar dl Ns | Ns Ar cspdl +Use the AppleDL (default) or AppleCspDL +.It Fl m Ar mode +Set the file permissions to +.Ar mode Ns +\&. +.It Fl o +Force using openparams argument +.It Fl 0 +Force using version 0 openparams +.El +.It +.Sy Examples +.Bl -tag -width -indent +.It security> create-db -m 0644 test.db +.It security> create-db -g cspdl -a test2.db +.El +.\"new import/export commands. +.El +.It +.Nm export +.Op Fl k Ar keychain +.Op Fl t Ar type +.Op Fl f Ar format +.Op Fl w +.Op Fl p Ar format +.Op Fl P Ar passphrase +.Op Fl o Ar outfile +.Bl -item -offset -indent +Export one or more items from a keychain to one of a number of external representations. If +.Ar keychain +isn't provided, items will be exported from the user's default keychain. +.It +Options: +.Bl -tag -compact -width -indent-indent +.It Fl k Ar keychain +Specify keychain from which item(s) will be exported. +.It Fl t Ar type +Specify the type of items to export. Possible types are certs, allKeys, pubKeys, privKeys, identities, and all. The default is all. An identity consists of both a certificate and the corresponding provate key. +.It Fl f Ar format +Specify the format of the exported data. Possible formats are openssl, bsafe, pkcs7, pkcs8, pkcs12, x509, openssh1, openssh2, and pemseq. The default is pemseq if more than one item is being exported. The default is openssl if one key is being exported. The default is x509 if one certificate is being exported. +.It Fl w +Specifies that private keys are to be wrapped on export. +.It Fl p +Specifies that PEM armour is to be applied to the output data. +.It Fl P Ar passphrase +Specify the wrapping passphrase immediately. The default is to obtain a secure passphrase via GUI. +.It Fl o Ar outfile +Write the output data to +.Ar outfile Ns +\&. Default is to write data to stdout. +.El +.It +.Sy Examples +.Bl -tag -width -indent +.It security> export -k login.keychain -t certs -o /tmp/certs.pem +.It security> export -k newcert.keychain -t identities -f pkcs12 -o /tmp/mycerts.p12 +.El +.\"marker. +.El +.It +.Nm import +inputfile +.Op Fl k Ar keychain +.Op Fl t Ar type +.Op Fl f Ar format +.Op Fl w +.Op Fl P Ar passphrase +.Op Ar options... +.Bl -item -offset -indent +Import one or more items from +.Ar inputfile Ns +\& into a keychain. If +.Ar keychain +isn't provided, items will be imported into the user's default keychain. +.It +Options: +.Bl -tag -compact -width -indent-indent +.It Fl k Ar keychain +Specify keychain into which item(s) will be imported. +.It Fl t Ar type +Specify the type of items to import. Possible types are cert, pub, priv, session, cert, and agg. Pub, priv, and session refer to keys; agg is one of the aggregate types (pkcs12 and PEM sequence). The command can often figure out what item_type an item contains based in the filename and/or item_format. +.It Fl f Ar format +Specify the format of the exported data. Possible formats are openssl, bsafe, raw, pkcs7, pkcs8, pkcs12, x509, openssh1, openssh2, and pemseq. The command can often figure out what format an item is in based in the filename and/or item_type. +.It Fl w +Specify that private keys are wrapped and must be unwrapped on import. +.It Fl x +Specify that private keys are non-extractable after being imported. +.It Fl P Ar passphrase +Specify the unwrapping passphrase immediately. The default is to obtain a secure passphrase via GUI. +.It Fl a Ar attrName Ar attrValue +Specify optional extended attribute name and value. Can be used multiple times. This is only valid when importing keys. +.It Fl A +Allow any application to access the imported key without warning (insecure, not recommended!) +.It Fl T Ar appPath +Specify an application which may access the imported key (multiple +.Fl T Ns +\& options are allowed) +.El +.It +.Sy Examples +.Bl -tag -width -indent +.It security> import /tmp/certs.pem -k +.It security> import /tmp/mycerts.p12 -t agg -k newcert.keychain +.It security> import /tmp/mycerts.p12 -f pkcs12 -k newcert.keychain +.El +.\"end of new import/export commands. +.El +.It +.Nm cms +.Op Fl C Ns | Ns Fl D Ns | Ns Fl E Ns | Ns Fl S +.Op Ar options... +.Bl -item -offset -indent +Encode or decode CMS messages. +.Bl -tag -compact -width -indent-indent +.It Fl C +create a CMS encrypted message +.It Fl D +decode a CMS message +.It Fl E +create a CMS enveloped message +.It Fl S +create a CMS signed message +.El +.It +Decoding options: +.Bl -tag -compact -width -indent-indent +.It Fl c Ar content +use this detached content file +.It Fl h Ar level +generate email headers with info about CMS message (output +.Ar level Ns +\& >= 0) +.It Fl n +suppress output of content +.El +.It +Encoding options: +.Bl -tag -compact -width -indent-indent +.It Fl r Ar id,... +create envelope for comma-delimited list of recipients, where id can be a certificate nickname or email address +.It Fl G +include a signing time attribute +.It Fl H Ar hash +hash = MD2|MD4|MD5|SHA1|SHA256|SHA384|SHA512 (default: SHA1) +.It Fl N Ar nick +use certificate named "nick" for signing +.It Fl P +include a SMIMECapabilities attribute +.It Fl T +do not include content in CMS message +.It Fl Y Ar nick +include an EncryptionKeyPreference attribute with certificate (use "NONE" to omit) +.It Fl Z Ar hash +find a certificate by subject key ID +.El +.It +Common options: +.Bl -tag -compact -width -indent-indent +.It Fl e Ar envelope +specify envelope file (valid with +.Fl D Ns +\& or +.Fl E Ns +\&) +.It Fl k Ar keychain +specify keychain to use +.It Fl i Ar infile +use infile as source of data (default: stdin) +.It Fl o Ar outfile +use outfile as destination of data (default: stdout) +.It Fl p Ar password +use password as key db password (default: prompt) +.It Fl s +pass data a single byte at a time to CMS +.It Fl u Ar certusage +set type of certificate usage (default: certUsageEmailSigner) +.It Fl v +print debugging information +.El +.It +Cert usage codes: + 0 - certUsageSSLClient + 1 - certUsageSSLServer + 2 - certUsageSSLServerWithStepUp + 3 - certUsageSSLCA + 4 - certUsageEmailSigner + 5 - certUsageEmailRecipient + 6 - certUsageObjectSigner + 7 - certUsageUserCertImport + 8 - certUsageVerifyCA + 9 - certUsageProtectedObjectSigner + 10 - certUsageStatusResponder + 11 - certUsageAnyCA +.It +.El +.It +.Nm install-mds +.Bl -item -offset -indent +Install (or re-install) the Module Directory Services (MDS) database. This is a system tool which is not normally used by users. There are no options. +.El +.It +.Nm add-trusted-cert +.Op Fl d +.Op Fl r Ar resultType +.Op Fl p Ar policy +.Op Fl a Ar appPath +.Op Fl s Ar policyString +.Op Fl e Ar allowedError +.Op Fl u Ar keyUsage +.Op Fl k Ar keychain +.Op Fl i Ar settingsFileIn +.Op Fl o Ar settingsFileOut +.Op Fl D +certFile +.Bl -item -offset -indent +Add certificate (in DER or PEM format) from +.Ar certFile Ns +\& to per-user or local Admin Trust Settings. When modifying per-user Trust Settings, user authentication is required via an authentication dialog. When modifying admin Trust Settings, the process must be running as root, or admin authentication is required. +.It +Options: +.Bl -tag -compact -width -indent-indent +.It Fl d +Add to admin cert store; default is user. +.It Fl r Ar resultType +resultType = trustRoot|trustAsRoot|deny|unspecified; default is trustRoot. +.It Fl p Ar policy +Specify policy constraint (ssl, smime, codeSign, IPSec, iChat, basic, swUpdate, pkgSign, pkinitClient, pkinitServer, eap). +.It Fl r Ar resultType +resultType = trustRoot|trustAsRoot|deny|unspecified; default is trustRoot. +.It Fl a Ar appPath +Specify application constraint. +.It Fl s Ar policyString +Specify policy-specific string. +.It Fl e Ar allowedError +Specify allowed error (an integer value, or one of: certExpired, hostnameMismatch) +.It Fl u Ar keyUsage +Specify key usage, an integer. +.It Fl k Ar keychain +Specify keychain to which cert is added. +.It Fl i Ar settingsFileIn +Input trust settings file; default is user domain. +.It Fl o Ar settingsFileOut +Output trust settings file; default is user domain. +.It Fl D +Add default setting instead of per-cert setting. No certFile is specified when using this option +.El +.It +.Sy Key usage codes: + -1 - Any + 1 - Sign + 2 - Encrypt/Decrypt Data + 4 - Encrypt/Decrypt Key + 8 - Sign certificate + 16 - Sign revocation + 32 - Key exchange + To specify more than one usage, add values together (except -1 - Any). +.It +.Sy Examples +.Bl -tag -width -indent +.Dl security> add-trusted-cert /tmp/cert.der +.Dl security> add-trusted-cert -d .tmp/cert.der +.El +.\"marker. +.It +.Nm remove-trusted-cert +.Op Fl d +.Op Fl D +certFile +.Bl -item -offset -indent +Remove certificate (in DER or PEM format) in +.Ar certFile Ns +\& from per-user or local Admin Trust Settings. When modifying per-user Trust Settings, user authentication is required via an authentication dialog. When modifying admin Trust Settings, the process must be running as root, or admin authentication is required. +.It +Options: +.Bl -tag -compact -width -indent-indent +.It Fl d +Remove from admin cert store; default is user. +.It Fl D +Remove Default Root Cert setting instead of an actual cert setting. No certFile is specified when using this option. +.El +.\"marker. +.El +.It +.Nm dump-trust-settings +.Op Fl s +.Op Fl d +.Bl -item -offset -indent +Display Trust Settings. +.It +Options: +.Bl -tag -compact -width -indent-indent +.It Fl s +Display trusted system certs; default is user. +.It Fl d +Display trusted admin certs; default is user. +.El +.\"marker. +.El +.It +.Nm user-trust-settings-enable +.Op Fl d +.Op Fl e +.Bl -item -offset -indent +Display or manipulate user-level Trust Settings. With no arguments, shows the current state of the user-level Trust Settings enable. Otherwise enables or disables user-level Trust Settings. +.It +Options: +.Bl -tag -compact -width -indent-indent +.It Fl d +Disable user-level Trust Settings. +.It Fl e +Enable user-level Trust Settings. +.El +.\"marker. +.El +.It +.Nm trust-settings-export +.Op Fl s +.Op Fl d +settings_file +.Bl -item -offset -indent +Export Trust Settings to the specified file. +.It +Options: +.Bl -tag -compact -width -indent-indent +.It Fl s +Export system Trust Settings; default is user. +.It Fl d +Export admin Trust Settings; default is user. +.El +.\"marker. +.El +.It +.Nm trust-settings-import +.Op Fl d +settings_file +.Bl -item -offset -indent +Import Trust Settings from the specified file. When modifying per-user Trust Settings, user authentication is required via an authentication dialog. When modifying admin Trust Settings, the process must be running as root, or admin authentication is required. +.It +Options: +.Bl -tag -compact -width -indent-indent +.It Fl d +Import admin Trust Settings; default is user. +.El +.\"marker. +.El +.It +.Nm verify-cert +.Op Fl c Ar certFile +.Op Fl r Ar rootCertFile +.Op Fl p Ar policy +.Op Fl k Ar keychain +.Op Fl n +.Op Fl L +.Op Fl l +.Op Fl e Ar emailAddress +.Op Fl s Ar sslHost +.Op Fl q +.Bl -item -offset -indent +Verify one or more certificates. +.It +Options: +.Bl -tag -compact -width -indent-indent +.It Fl c Ar certFile +Certificate to verify, in DER or PEM format. Can be specified more than once; leaf certificate has to be specified first. +.It Fl r Ar rootCertFile +Root certificate, in DER or PEM format. Can be specified more than once. If not specified, the system anchor certificates are used. If one root certificate is specified, and zero (non-root) certificates are specified, the root certificate is verified against itself. +.It Fl p Ar policy +Specify verification policy (ssl, smime, codeSign, IPSec, iChat, basic, swUpdate, pkgSign, pkinitClient, pkinitServer, eap, appleID, macappstore, timestamping). Default is basic. +.It Fl k Ar keychain +Keychain to search for intermediate certs. Can be specified multiple times. Default is the current user's keychain search list. +.It Fl n +Avoid searching any keychains. +.It Fl L +Use local certificates only. If an issuing CA certificate is missing, this option will avoid accessing the network to fetch it. +.It Fl l +Specifies that the leaf certificate is a CA cert. By default, a leaf certificate with a Basic Constraints extension with the CA bit set fails verification. +.It Fl e Ar emailAddress +Specify email address for the smime policy. +.It Fl s Ar sslHost +Specify SSL host name for the ssl policy. +.It Fl q +Quiet, no stdout or stderr. +.El +.It +.Sy Examples +.Bl -tag -width -indent +.It security> verify-cert -c applestore0.cer -c applestore1.cer -p ssl -s store.apple.com +.It security> verify-cert -r serverbasic.crt +.El +.\"marker. +.El +.It +.Nm authorize +.Op Fl updPiew +.Op Ar right... +.Bl -item -offset -indent +Authorize requested right(s). The extend-rights flag will be passed by default. +.It +Options: +.Bl -tag -compact -width -indent-indent +.It Fl u +Allow user interaction. +.It Fl p +Allow returning partial rights. +.It Fl d +Destroy acquired rights. +.It Fl P +Pre-authorize rights only. +.It Fl l +Operate authorization in least privileged mode. +.It Fl i +Internalize authref passed on stdin. +.It Fl e +Externalize authref to stdout +.It Fl w +Wait while holding AuthorizationRef until stdout is closed. This will allow client to read externalized AuthorizationRef from pipe. +.El +.It +.Sy Examples +.Bl -tag -width -indent +.It security> security authorize -ud my-right +Basic authorization of my-right. +.It security> security -q authorize -uew my-right | security -q authorize -i my-right +Authorizing a right and passing it to another command as a way to add authorization to shell scripts. +.El +.El +.It +.Nm authorizationdb +.Ar read +.It +.Nm authorizationdb +.Ar write [allow|deny|] +.It +.Nm authorizationdb +.Ar remove +.Bl -item -offset -indent +Read/Modify authorization policy database. Without a rulename write will read a dictionary as a plist from stdin. +.It +.Sy Examples +.Bl -tag -width -indent +.It security> security authorizationdb read system.privilege.admin > /tmp/aewp-def +Read definition of system.privilege.admin right. +.It security> security authorizationdb write system.preferences < /tmp/aewp-def +Set system.preferences to definition of system.privilege.admin right. +.It security> security authorizationdb write system.preferences authenticate-admin +Every change to preferences requires an Admin user to authenticate. +.El +.El +.It +.Nm execute-with-privileges +.Ar +.Op Ar args... +.Bl -item -offset -indent +Execute tool with privileges. +On success stdin will be read and forwarded to the tool. +.El +.It +.Nm leaks +.Op Fl h +.Op Fl cycles +.Op Fl nocontext +.Op Fl nostacks +.Op Fl exclude Ar symbol +.Bl -item -offset -indent +Run +.Li /usr/bin/leaks +on this process. This can help find memory leaks after running +certain commands. +.It +Options: +.Bl -tag -compact -width -indent-indent +.It Fl cycles +Use a stricter algorithm (See +.Xr leaks 1 +for details). +.It Fl nocontext +Withhold the hex dumps of the leaked memory. +.It Fl nostacks +Don't show stack traces of leaked memory. +.It Fl exclude Ar symbol +Ignore leaks called from +.Ar symbol Ns . +.El +.El +.It +.Nm error +.Op Fl h +.Op Ar +.Bl -item -offset -indent +Display an error string for the given security-related error code. +The error can be in decimal or hex, e.g. 1234 or 0x1234. Multiple +errors can be separated by spaces. +.El +.El +.El +.Sh ENVIRONMENT \" May not be needed +.Bl -tag -width -indent +.It Ev MallocStackLogging +When using the +.Nm leaks +command or the +.Fl l +option it's probably a good idea to set this environment variable before +.Nm +is started. Doing so will allow leaks to display symbolic backtraces. +.El +.Sh FILES +.Bl -tag -width -indent +.It Pa ~/Library/Preferences/com.apple.security.plist +.Pp +Property list file containing the current user's default keychain and keychain search list. +.It Pa /Library/Preferences/com.apple.security.plist +.Pp +Property list file containing the system default keychain and keychain search list. This is used by processes started at boot time, or those requesting to use the system search domain, such as system daemons. +.It Pa /Library/Preferences/com.apple.security-common.plist +.Pp +Property list file containing the common keychain search list, which is appended to every user's search list and to the system search list. +.El +.Sh SEE ALSO +.\" List links in ascending order by section, alphabetically within a section. +.\" Please do not reference files that do not exist without filing a bug report +.Xr certtool 1 , +.Xr leaks 1 +.\" .Xr systemkeychain 8 +.Sh HISTORY +.Nm +was first introduced in Mac OS X version 10.3. +.Sh BUGS +.Nm +still needs more commands before it can be considered complete. +In particular, it should someday supersede both the +.Li certtool +and +.Li systemkeychain +commands. diff --git a/SecurityTool/security.c b/SecurityTool/security.c new file mode 100644 index 00000000..c66740fd --- /dev/null +++ b/SecurityTool/security.c @@ -0,0 +1,967 @@ +/* + * Copyright (c) 2003-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@ + * + * security.c + */ + +#include "security.h" + +#include "leaks.h" +#include "readline.h" + +#include "cmsutil.h" +#include "db_commands.h" +#include "keychain_add.h" +#include "keychain_create.h" +#include "keychain_delete.h" +#include "keychain_list.h" +#include "keychain_lock.h" +#include "keychain_set_settings.h" +#include "keychain_show_info.h" +#include "keychain_unlock.h" +#include "keychain_recode.h" +#include "key_create.h" +#include "keychain_find.h" +#include "keychain_import.h" +#include "keychain_export.h" +#include "identity_find.h" +#include "identity_prefs.h" +#include "mds_install.h" +#include "trusted_cert_add.h" +#include "trusted_cert_dump.h" +#include "user_trust_enable.h" +#include "trust_settings_impexp.h" +#include "verify_cert.h" +#include "authz.h" +#include "display_error_code.h" +#include "createFVMaster.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* Maximum length of an input line in interactive mode. */ +#define MAX_LINE_LEN 4096 +/* Maximum number of arguments on an input line in interactive mode. */ +#define MAX_ARGS 32 + +/* Entry in commands array for a command. */ +typedef struct command +{ + const char *c_name; /* name of the command. */ + command_func c_func; /* function to execute the command. */ + const char *c_usage; /* usage sting for command. */ + const char *c_help; /* help string for (or description of) command. */ +} command; + +/* The default prompt. */ +const char *prompt_string = "security> "; + +/* The name of this program. */ +const char *prog_name; + + +/* Forward declarations of static functions. */ +static int help(int argc, char * const *argv); + +/* + * The command array itself. + * Add commands here at will. + * Matching is done on a prefix basis. The first command in the array + * gets matched first. + */ +const command commands[] = +{ + { "help", help, + "[command ...]", + "Show all commands, or show usage for a command." }, + + { "list-keychains", keychain_list, + "[-d user|system|common|dynamic] [-s [keychain...]]\n" + " -d Use the specified preference domain\n" + " -s Set the search list to the specified keychains\n" + "With no parameters, display the search list.", + "Display or manipulate the keychain search list." }, + + { "default-keychain", keychain_default, + "[-d user|system|common|dynamic] [-s [keychain]]\n" + " -d Use the specified preference domain\n" + " -s Set the default keychain to the specified keychain\n" + "With no parameters, display the default keychain.", + "Display or set the default keychain." }, + + { "login-keychain", keychain_login, + "[-d user|system|common|dynamic] [-s [keychain]]\n" + " -d Use the specified preference domain\n" + " -s Set the login keychain to the specified keychain\n" + "With no parameters, display the login keychain.", + "Display or set the login keychain." }, + + { "create-keychain", keychain_create, + "[-P] [-p password] [keychains...]\n" + " -p Use \"password\" as the password for the keychains being created\n" + " -P Prompt the user for a password using the SecurityAgent", + "Create keychains and add them to the search list." }, + + { "delete-keychain", keychain_delete, + "[keychains...]", + "Delete keychains and remove them from the search list." }, + + { "lock-keychain", keychain_lock, + "[-a | keychain]\n" + " -a Lock all keychains", + "Lock the specified keychain."}, + + { "unlock-keychain", keychain_unlock, + "[-u] [-p password] [keychain]\n" + " -p Use \"password\" as the password to unlock the keychain\n" + " -u Do not use the password", + "Unlock the specified keychain."}, + + { "set-keychain-settings", keychain_set_settings, + "[-lu] [-t timeout] [keychain]\n" + " -l Lock keychain when the system sleeps\n" + " -u Lock keychain after timeout interval\n" + " -t Timeout in seconds (omitting this option specifies \"no timeout\")\n", + "Set settings for a keychain."}, + + { "set-keychain-password", keychain_set_password, + "[-o oldPassword] [-p newPassword] [keychain]\n" + " -o Old keychain password (if not provided, will prompt)\n" + " -p New keychain password (if not provided, will prompt)\n", + "Set password for a keychain."}, + + { "show-keychain-info", keychain_show_info, + "[keychain]", + "Show the settings for keychain." }, + + { "dump-keychain", keychain_dump, + "[-adir] [keychain...]\n" + " -a Dump access control list of items\n" + " -d Dump (decrypted) data of items\n" + " -i Interactive access control list editing mode\n" + " -r Dump the raw (encrypted) data of items", + "Dump the contents of one or more keychains." }, + +#ifndef NDEBUG + { "recode-keychain", keychain_recode, + "keychain_to_recode keychain_to_get_secrets_from", + "Recode a keychain to use the secrets from another one."}, +#endif + + { "create-keypair", key_create_pair, + "[-a alg] [-s size] [-f date] [-t date] [-d days] [-k keychain] [-A|-T appPath] description\n" + " -a Use alg as the algorithm, can be rsa, dh, dsa or fee (default rsa)\n" + " -s Specify the keysize in bits (default 512)\n" + " -f Make a key valid from the specified date\n" + " -t Make a key valid to the specified date\n" + " -d Make a key valid for the number of days specified from today\n" + " -k Use the specified keychain rather than the default\n" + " -A Allow any application to access this key without warning (insecure, not recommended!)\n" + " -T Specify an application which may access this key (multiple -T options are allowed)\n" + "If no options are provided, ask the user interactively.", + "Create an asymmetric key pair." }, + + #if 0 + /* this was added in mb's integration of PR-3420772, but this is an unimplemented command */ + { "create-csr", csr_create, + "[-a alg] [-s size] [-f date] [-t date] [-d days] [-k keychain] [-A|-T appPath] description\n" + " -a Use alg as the algorithm, can be rsa, dh, dsa or fee (default rsa)\n" + " -s Specify the keysize in bits (default 512)\n" + " -f Make a key valid from the specified date\n" + " -t Make a key valid to the specified date\n" + " -d Make a key valid for the number of days specified from today\n" + " -k Use the specified keychain rather than the default\n" + " -A Allow any application to access this key without warning (insecure, not recommended!)\n" + " -T Specify an application which may access this key (multiple -T options are allowed)\n" + "If no options are provided, ask the user interactively.", + "Create a certificate signing request." }, + #endif + + { "add-generic-password", keychain_add_generic_password, + "[-a account] [-s service] [-w password] [options...] [-A|-T appPath] [keychain]\n" + " -a Specify account name (required)\n" + " -c Specify item creator (optional four-character code)\n" + " -C Specify item type (optional four-character code)\n" + " -D Specify kind (default is \"application password\")\n" + " -G Specify generic attribute (optional)\n" + " -j Specify comment string (optional)\n" + " -l Specify label (if omitted, service name is used as default label)\n" + " -s Specify service name (required)\n" + " -p Specify password to be added (legacy option, equivalent to -w)\n" + " -w Specify password to be added\n" + " -A Allow any application to access this item without warning (insecure, not recommended!)\n" + " -T Specify an application which may access this item (multiple -T options are allowed)\n" + " -U Update item if it already exists (if omitted, the item cannot already exist)\n" + "\n" + "By default, the application which creates an item is trusted to access its data without warning.\n" + "You can remove this default access by explicitly specifying an empty app pathname: -T \"\"\n" + "If no keychain is specified, the password is added to the default keychain.", + "Add a generic password item."}, + + { "add-internet-password", keychain_add_internet_password, + "[-a account] [-s server] [-w password] [options...] [-A|-T appPath] [keychain]\n" + " -a Specify account name (required)\n" + " -c Specify item creator (optional four-character code)\n" + " -C Specify item type (optional four-character code)\n" + " -d Specify security domain string (optional)\n" + " -D Specify kind (default is \"Internet password\")\n" + " -j Specify comment string (optional)\n" + " -l Specify label (if omitted, server name is used as default label)\n" + " -p Specify path string (optional)\n" + " -P Specify port number (optional)\n" + " -r Specify protocol (optional four-character SecProtocolType, e.g. \"http\", \"ftp \")\n" + " -s Specify server name (required)\n" + " -t Specify authentication type (as a four-character SecAuthenticationType, default is \"dflt\")\n" + " -w Specify password to be added\n" + " -A Allow any application to access this item without warning (insecure, not recommended!)\n" + " -T Specify an application which may access this item (multiple -T options are allowed)\n" + " -U Update item if it already exists (if omitted, the item cannot already exist)\n" + "\n" + "By default, the application which creates an item is trusted to access its data without warning.\n" + "You can remove this default access by explicitly specifying an empty app pathname: -T \"\"\n" + "If no keychain is specified, the password is added to the default keychain.", + "Add an internet password item."}, + + { "add-certificates", keychain_add_certificates, + "[-k keychain] file...\n" + "If no keychain is specified, the certificates are added to the default keychain.", + "Add certificates to a keychain."}, + + { "find-generic-password", keychain_find_generic_password, + "[-a account] [-s service] [options...] [-g] [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" + " -g Display the password for the item found\n" + " -w Display only the password on stdout\n" + "If no keychains are specified to search, the default search list is used.", + "Find a generic password item."}, + + { "delete-generic-password", keychain_delete_generic_password, + "[-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" + " -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" + "If no keychains are specified to search, the default search list is used.", + "Delete a generic password item."}, + + { "find-internet-password", keychain_find_internet_password, + "[-a account] [-s server] [options...] [-g] [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" + " -g Display the password for the item found\n" + " -w Display only the password on stdout\n" + "If no keychains are specified to search, the default search list is used.", + "Find an internet password item."}, + + { "delete-internet-password", keychain_delete_internet_password, + "[-a account] [-s server] [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" + "If no keychains are specified to search, the default search list is used.", + "Delete an 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" + " -c Match on \"name\" when searching (optional)\n" + " -e Match on \"emailAddress\" when searching (optional)\n" + " -m Show the email addresses in the certificate\n" + " -p Output certificate in pem format\n" + " -Z Print SHA-1 hash of the certificate\n" + "If no keychains are specified to search, the default search list is used.", + "Find a certificate item."}, + + { "find-identity", keychain_find_identity, + "[-p policy] [-s string] [-v] [keychain...]\n" + " -p Specify policy to evaluate (multiple -p options are allowed)\n" + " Supported policies: basic, ssl-client, ssl-server, smime, eap,\n" + " ipsec, ichat, codesigning, sys-default, sys-kerberos-kdc, macappstore, appleID\n" + " -s Specify optional policy-specific string (e.g. DNS hostname for SSL,\n" + " or RFC822 email address for S/MIME)\n" + " -v Show valid identities only (default is to show all identities)\n" + "If no keychains are specified to search, the default search list is used.", + "Find an identity (certificate + private key)."}, + + { "delete-certificate", keychain_delete_certificate, + "[-c name] [-Z hash] [-t] [keychain...]\n" + " -c Specify certificate to delete by its common name\n" + " -Z Specify certificate to delete by its SHA-1 hash value\n" + " -t Also delete user trust settings for this certificate\n" + "The certificate to be deleted must be uniquely specified either by a\n" + "string found in its common name, or by its SHA-1 hash.\n" + "If no keychains are specified to search, the default search list is used.", + "Delete a certificate from a keychain."}, + + { "set-identity-preference", set_identity_preference, + "[-n] [-c identity] [-s service] [-u keyUsage] [-Z hash] [keychain...]\n" + " -n Specify no identity (clears existing preference for service)\n" + " -c Specify identity by common name of the certificate\n" + " -s Specify service (may be a URL, RFC822 email address, DNS host, or\n" + " other name) for which this identity is to be preferred\n" + " -u Specify key usage (optional) - see man page for values\n" + " -Z Specify identity by SHA-1 hash of certificate (optional)\n", + "Set the preferred identity to use for a service."}, + + { "get-identity-preference", get_identity_preference, + "[-s service] [-u keyUsage] [-p] [-c] [-Z] [keychain...]\n" + " -s Specify service (may be a URL, RFC822 email address, DNS host, or\n" + " other name)\n" + " -u Specify key usage (optional) - see man page for values\n" + " -p Output identity certificate in pem format\n" + " -c Print common name of the preferred identity certificate\n" + " -Z Print SHA-1 hash of the preferred identity certificate\n", + "Get the preferred identity to use for a service."}, + + { "create-db", db_create, + "[-ao0] [-g dl|cspdl] [-m mode] [name]\n" + " -a Turn off autocommit\n" + " -g Attach to \"guid\" rather than the AppleFileDL\n" + " -m Set the inital mode of the created db to \"mode\"\n" + " -o Force using openparams argument\n" + " -0 Force using version 0 openparams\n" + "If no name is provided, ask the user interactively.", + "Create a db using the DL." }, + + { "export" , keychain_export, + "[-k keychain] [-t type] [-f format] [-w] [-p] [-P passphrase] [-o outfile]\n" + " -k keychain to export items from\n" + " -t Type = certs|allKeys|pubKeys|privKeys|identities|all (Default: all)\n" + " -f Format = openssl|openssh1|openssh2|bsafe|pkcs7|pkcs8|pkcs12|pemseq|x509\n" + " ...default format is pemseq for aggregate, openssl for single\n" + " -w Private keys are wrapped\n" + " -p PEM encode the output\n" + " -P Specify wrapping passphrase immediately (default is secure passphrase via GUI)\n" + " -o Specify output file (default is stdout)", + "Export items from a keychain." }, + + { "import", keychain_import, + "inputfile [-k keychain] [-t type] [-f format] [-w] [-P passphrase] [options...]\n" + " -k Target keychain to import into\n" + " -t Type = pub|priv|session|cert|agg\n" + " -f Format = openssl|openssh1|openssh2|bsafe|raw|pkcs7|pkcs8|pkcs12|netscape|pemseq\n" + " -w Specify that private keys are wrapped and must be unwrapped on import\n" + " -x Specify that private keys are non-extractable after being imported\n" + " -P Specify wrapping passphrase immediately (default is secure passphrase via GUI)\n" + " -a Specify name and value of extended attribute (can be used multiple times)\n" + " -A Allow any application to access the imported key without warning (insecure, not recommended!)\n" + " -T Specify an application which may access the imported key (multiple -T options are allowed)\n", + "Import items into a keychain." }, + + { "cms", cms_util, + "[-C|-D|-E|-S] []\n" + " -C create a CMS encrypted message\n" + " -D decode a CMS message\n" + " -E create a CMS enveloped message\n" + " -S create a CMS signed message\n" + "\n" + "Decoding options:\n" + " -c content use this detached content file\n" + " -h level generate email headers with info about CMS message\n" + " (output level >= 0)\n" + " -n suppress output of content\n" + "\n" + "Encoding options:\n" + " -r id,... create envelope for these recipients,\n" + " where id can be a certificate nickname or email address\n" + " -G include a signing time attribute\n" + " -H hash hash = MD2|MD4|MD5|SHA1|SHA256|SHA384|SHA512 (default: SHA1)\n" + " -N nick use certificate named \"nick\" for signing\n" + " -P include a SMIMECapabilities attribute\n" + " -T do not include content in CMS message\n" + " -Y nick include an EncryptionKeyPreference attribute with certificate\n" + " (use \"NONE\" to omit)\n" + " -Z hash find a certificate by subject key ID\n" + "\n" + "Common options:\n" + " -e envelope specify envelope file (valid with -D or -E)\n" + " -k keychain specify keychain to use\n" + " -i infile use infile as source of data (default: stdin)\n" + " -o outfile use outfile as destination of data (default: stdout)\n" + " -p password use password as key db password (default: prompt)\n" + " -s pass data a single byte at a time to CMS\n" + " -u certusage set type of certificate usage (default: certUsageEmailSigner)\n" + " -v print debugging information\n" + "\n" + "Cert usage codes:\n" + " 0 - certUsageSSLClient\n" + " 1 - certUsageSSLServer\n" + " 2 - certUsageSSLServerWithStepUp\n" + " 3 - certUsageSSLCA\n" + " 4 - certUsageEmailSigner\n" + " 5 - certUsageEmailRecipient\n" + " 6 - certUsageObjectSigner\n" + " 7 - certUsageUserCertImport\n" + " 8 - certUsageVerifyCA\n" + " 9 - certUsageProtectedObjectSigner\n" + " 10 - certUsageStatusResponder\n" + " 11 - certUsageAnyCA", + "Encode or decode CMS messages." }, + + { "install-mds" , mds_install, + "", /* no options */ + "Install (or re-install) the MDS database." }, + + { "add-trusted-cert" , trusted_cert_add, + " [] [certFile]\n" + " -d Add to admin cert store; default is user\n" + " -r resultType resultType = trustRoot|trustAsRoot|deny|unspecified;\n" + " default is trustRoot\n" + " -p policy Specify policy constraint (ssl, smime, codeSign, IPSec, iChat,\n" + " basic, swUpdate, pkgSign, pkinitClient, pkinitServer, eap)\n" + " -a appPath Specify application constraint\n" + " -s policyString Specify policy-specific string\n" + " -e allowedError Specify allowed error (certExpired, hostnameMismatch) or integer\n" + " -u keyUsage Specify key usage, an integer\n" + " -k keychain Specify keychain to which cert is added\n" + " -i settingsFileIn Input trust settings file; default is user domain\n" + " -o settingsFileOut Output trust settings file; default is user domain\n" + " -D Add default setting instead of per-cert setting\n" + " certFile Certificate(s)", + "Add trusted certificate(s)." }, + + { "remove-trusted-cert" , trusted_cert_remove, + " [-d] [-D] [certFile]\n" + " -d Remove from admin cert store (default is user)\n" + " -D Remove default setting instead of per-cert setting\n" + " certFile Certificate(s)", + "Remove trusted certificate(s)." }, + + { "dump-trust-settings" , trusted_cert_dump, + " [-s] [-d]\n" + " -s Display trusted system certs (default is user)\n" + " -d Display trusted admin certs (default is user)\n", + "Display contents of trust settings." }, + + { "user-trust-settings-enable", user_trust_enable, + "[-d] [-e]\n" + " -d Disable user-level trust Settings\n" + " -e Enable user-level trust Settings\n" + "With no parameters, show current enable state of user-level trust settings.", + "Display or manipulate user-level trust settings." }, + + { "trust-settings-export", trust_settings_export, + " [-s] [-d] settings_file\n" + " -s Export system trust settings (default is user)\n" + " -d Export admin trust settings (default is user)\n", + "Export trust settings." }, + + { "trust-settings-import", trust_settings_import, + " [-d] settings_file\n" + " -d Import admin trust settings (default is user)\n", + "Import trust settings." }, + + { "verify-cert" , verify_cert, + " []\n" + " -c certFile Certificate to verify. Can be specified multiple times, leaf first.\n" + " -r rootCertFile Root Certificate. Can be specified multiple times.\n" + " -p policy Verify Policy (basic, ssl, smime, codeSign, IPSec, iChat, swUpdate,\n" + " pkgSign, pkinitClient, pkinitServer, eap, appleID,\n" + " macappstore, timestamping); default is basic.\n" + " -k keychain Keychain. Can be called multiple times. Default is default search list.\n" + " -n No keychain search list.\n" + " -L Local certificates only (do not try to fetch missing CA certs from net).\n" + " -l Leaf cert is a CA (normally an error, unless this option is given).\n" + " -e emailAddress Email address for smime policy.\n" + " -s sslHost SSL host name for ssl policy.\n" + " -q Quiet.\n", + "Verify certificate(s)." }, + + { "authorize" , authorize, + "[] \n" + " -u Allow user interaction.\n" + " -c Use login name and prompt for password.\n" + " -C login Use given login name and prompt for password.\n" + " -x Do NOT share -c/-C explicit credentials\n" +#ifndef NDEBUG + " -E Don't extend rights.\n" +#endif + " -p Allow returning partial rights.\n" + " -d Destroy acquired rights.\n" + " -P Pre-authorize rights only.\n" + " -l Operate authorizations in least privileged mode.\n" + " -i Internalize authref passed on stdin.\n" + " -e Externalize authref to stdout.\n" + " -w Wait until stdout is closed (to allow reading authref from pipe).\n" + "Extend rights flag is passed per default.", + "Perform authorization operations." }, + + { "authorizationdb" , authorizationdb, + "read \n" + " authorizationdb remove \n" + " authorizationdb write [allow|deny|]\n" + "If no rulename is specified, write will read a plist from stdin.\n" + " authorizationdb merge source [destination]\n" + "If no destination path is specified, merge will merge to /etc/authorization.\n" + " authorizationdb smartcard \n" + "Enables/disables smartcard login support or report current status.", + "Make changes to the authorization policy database.\n" }, + + { "execute-with-privileges" , execute_with_privileges, + " [args...]\n" + "On success, stdin will be read and forwarded to the tool.", + "Execute tool with privileges." }, + + { "leaks", leaks, + "[-cycles] [-nocontext] [-nostacks] [-exclude symbol]\n" + " -cycles Use a stricter algorithm (\"man leaks\" for details)\n" + " -nocontext Withhold hex dumps of the leaked memory\n" + " -nostacks Don't show stack traces of leaked memory\n" + " -exclude Ignore leaks called from \"symbol\"\n" + "(Set the environment variable MallocStackLogging to get symbolic traces.)", + "Run /usr/bin/leaks on this process." }, + + { "error", display_error_code, + "\n" + "Display an error string for the given security-related error code.\n" + "The error can be in decimal or hex, e.g. 1234 or 0x1234. Multiple " + "errors can be separated by spaces.", + "Display a descriptive message for the given error code(s)." }, + + { "create-filevaultmaster-keychain", keychain_createMFV, + "[-p password] [keychain name]\n" + " -p Use \"password\" as the password for the keychain being created\n" + " -s Specify the keysize in bits (default 2048; 1024 & 4096 are allowed)\n" + "By default the keychain will be created in ~/Library/Keychains/\n", + "Create a keychain containing a key pair for FileVault recovery use." + }, + + {} +}; + +/* Global variables. */ +int do_quiet = 0; +int do_verbose = 0; + +/* Return 1 if name matches command. */ +static int +match_command(const char *command, const char *name) +{ + return !strncmp(command, name, strlen(name)); +} + +/* The help command. */ +static int +help(int argc, char * const *argv) +{ + const command *c; + + if (argc > 1) + { + char * const *arg; + for (arg = argv + 1; *arg; ++arg) + { + int found = 0; + + for (c = commands; c->c_name; ++c) + { + if (match_command(c->c_name, *arg)) + { + found = 1; + break; + } + } + + if (found) + printf("Usage: %s %s\n", c->c_name, c->c_usage); + else + { + sec_error("%s: no such command: %s", argv[0], *arg); + return 1; + } + } + } + else + { + for (c = commands; c->c_name; ++c) + printf(" %-17s %s\n", c->c_name, c->c_help); + } + + return 0; +} + +/* States for split_line parser. */ +typedef enum +{ + SKIP_WS, + READ_ARG, + READ_ARG_ESCAPED, + QUOTED_ARG, + QUOTED_ARG_ESCAPED +} parse_state; + +/* Split a line into multiple arguments and return them in *pargc and *pargv. */ +static void +split_line(char *line, int *pargc, char * const **pargv) +{ + static char *argvec[MAX_ARGS + 1]; + int argc = 0; + char *ptr = line; + char *dst = line; + parse_state state = SKIP_WS; + int quote_ch = 0; + + for (ptr = line; *ptr; ++ptr) + { + if (state == SKIP_WS) + { + if (isspace(*ptr)) + continue; + + if (*ptr == '"' || *ptr == '\'') + { + quote_ch = *ptr; + state = QUOTED_ARG; + argvec[argc] = dst; + continue; /* Skip the quote. */ + } + else + { + state = READ_ARG; + argvec[argc] = dst; + } + } + + if (state == READ_ARG) + { + if (*ptr == '\\') + { + state = READ_ARG_ESCAPED; + continue; + } + else if (isspace(*ptr)) + { + /* 0 terminate each arg. */ + *dst++ = '\0'; + argc++; + state = SKIP_WS; + if (argc >= MAX_ARGS) + break; + } + else + *dst++ = *ptr; + } + + if (state == QUOTED_ARG) + { + if (*ptr == '\\') + { + state = QUOTED_ARG_ESCAPED; + continue; + } + if (*ptr == quote_ch) + { + /* 0 terminate each arg. */ + *dst++ = '\0'; + argc++; + state = SKIP_WS; + if (argc >= MAX_ARGS) + break; + } + else + *dst++ = *ptr; + } + + if (state == READ_ARG_ESCAPED) + { + *dst++ = *ptr; + state = READ_ARG; + } + + if (state == QUOTED_ARG_ESCAPED) + { + *dst++ = *ptr; + state = QUOTED_ARG; + } + } + + if (state != SKIP_WS) + { + /* Terminate last arg. */ + *dst++ = '\0'; + argc++; + } + + /* Teminate arg vector. */ + argvec[argc] = NULL; + + *pargv = argvec; + *pargc = argc; +} + +/* Print a (hopefully) useful usage message. */ +static int +usage(void) +{ + printf( + "Usage: %s [-h] [-i] [-l] [-p prompt] [-q] [-v] [command] [opt ...]\n" + " -i Run in interactive mode.\n" + " -l Run /usr/bin/leaks -nocontext before exiting.\n" + " -p Set the prompt to \"prompt\" (implies -i).\n" + " -q Be less verbose.\n" + " -v Be more verbose about what's going on.\n" + "%s commands are:\n", prog_name, prog_name); + help(0, NULL); + return 2; +} + +/* Execute a single command. */ +static int +execute_command(int argc, char * const *argv) +{ + const command *c; + int found = 0; + + /* Nothing to do. */ + if (argc == 0) + return 0; + + for (c = commands; c->c_name; ++c) + { + if (match_command(c->c_name, argv[0])) + { + found = 1; + break; + } + } + + if (found) + { + int result; + + /* Reset getopt for command proc. */ + optind = 1; + optreset = 1; + + if (do_verbose) + { + int ix; + + fprintf(stderr, "%s", c->c_name); + for (ix = 1; ix < argc; ++ix) + fprintf(stderr, " \"%s\"", argv[ix]); + fprintf(stderr, "\n"); + } + + result = c->c_func(argc, argv); + if (result == 2) + fprintf(stderr, "Usage: %s %s\n %s\n", c->c_name, c->c_usage, c->c_help); + + return result; + } + else + { + sec_error("unknown command \"%s\"", argv[0]); + return 1; + } +} + +static void +receive_notifications(void) +{ + /* Run the CFRunloop to get any pending notifications. */ + while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, TRUE) == kCFRunLoopRunHandledSource); +} + + +const char * +sec_errstr(int err) +{ + const char *errString; + if (IS_SEC_ERROR(err)) + errString = SECErrorString(err); + else + errString = cssmErrorString(err); + return errString; +} + +void +sec_error(const char *msg, ...) +{ + va_list args; + + fprintf(stderr, "%s: ", prog_name); + + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); + + fprintf(stderr, "\n"); +} + +void +sec_perror(const char *msg, int err) +{ + sec_error("%s: %s", msg, sec_errstr(err)); +} + +int +main(int argc, char * const *argv) +{ + int result = 0; + int do_help = 0; + int do_interactive = 0; + int do_leaks = 0; + int ch; + + + /* Remember my name. */ + prog_name = strrchr(argv[0], '/'); + prog_name = prog_name ? prog_name + 1 : argv[0]; + + /* Do getopt stuff for global options. */ + optind = 1; + optreset = 1; + while ((ch = getopt(argc, argv, "hilp:qvR")) != -1) + { + switch (ch) + { + case 'h': + do_help = 1; + break; + case 'i': + do_interactive = 1; + break; + case 'l': + do_leaks = 1; + break; + case 'p': + do_interactive = 1; + prompt_string = optarg; + break; + case 'q': + do_quiet = 1; + break; + case 'v': + do_verbose = 1; + break; + case 'R': + // "Recovery mode", do NOT ask security-checksystem to run when using keychain APIs + // NOTE: this is a hidden option (not in the usage message) + SecKeychainSystemKeychainCheckWouldDeadlock(); + break; + case '?': + default: + return usage(); + } + } + + argc -= optind; + argv += optind; + + if (do_help) + { + /* Munge argc/argv so that argv[0] is something. */ + return help(argc + 1, argv - 1); + } + else if (argc > 0) + { + receive_notifications(); + result = execute_command(argc, argv); + receive_notifications(); + } + else if (do_interactive) + { + /* In interactive mode we just read commands and run them until readline returns NULL. */ + + /* Only show prompt string if stdin is a tty. */ + int show_prompt = isatty(0); + + for (;;) + { + static char buffer[MAX_LINE_LEN]; + char * const *av, *input; + int ac; + + if (show_prompt) + fprintf(stderr, "%s", prompt_string); + + input = readline(buffer, MAX_LINE_LEN); + if (!input) + break; + + split_line(input, &ac, &av); + receive_notifications(); + result = execute_command(ac, av); + receive_notifications(); + if (result == -1) + { + result = 0; + break; + } + + if (result && ! do_quiet) + { + fprintf(stderr, "%s: returned %d\n", av[0], result); + } + } + } + else + result = usage(); + + if (do_leaks) + { + char *const argvec[3] = { "leaks", "-nocontext", NULL }; + leaks(2, argvec); + } + + return result; +} diff --git a/SecurityTool/security.h b/SecurityTool/security.h new file mode 100644 index 00000000..2244bf76 --- /dev/null +++ b/SecurityTool/security.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2003-2004,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@ + * + * security.h + */ + +#ifndef _SECURITY_H_ +#define _SECURITY_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int(*command_func)(int argc, char * const *argv); + +/* If 1 attempt to be as quiet as possible. */ +extern int do_quiet; + +/* If 1 attempt to be as verbose as possible. */ +extern int do_verbose; + +const char *sec_errstr(int err); +void sec_error(const char *msg, ...); +void sec_perror(const char *msg, int err); + +#ifdef __cplusplus +} +#endif + +#endif /* _SECURITY_H_ */ diff --git a/SecurityTool/security_tool_commands.c b/SecurityTool/security_tool_commands.c new file mode 100644 index 00000000..b2dde6c9 --- /dev/null +++ b/SecurityTool/security_tool_commands.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +#include + +#include "SecurityTool/SecurityTool.h" + +#include "SecurityTool/security_tool_commands.h" + +#include "SecurityTool/builtin_commands.h" +#include "SecurityTool/sub_commands.h" + +#include "SecurityTool/security_tool_commands_table.h" + +const command commands[] = +{ +#include "SecurityTool/builtin_commands.h" + +#include "SecurityTool/sub_commands.h" + + {} +}; diff --git a/SecurityTool/srCdsaUtils.cpp b/SecurityTool/srCdsaUtils.cpp new file mode 100644 index 00000000..c44761a0 --- /dev/null +++ b/SecurityTool/srCdsaUtils.cpp @@ -0,0 +1,525 @@ +/* + * Copyright (c) 2001,2003-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@ + * + * srCdsaUtils.cpp -- common CDSA access utilities + */ + +#include "srCdsaUtils.h" +#include +#include +#include +#include /* for cssmPerror() */ +#include /* for cssmPerror() */ +#include + +static CSSM_VERSION vers = {2, 0}; +static const CSSM_GUID testGuid = { 0xFADE, 0, 0, { 1,2,3,4,5,6,7,0 }}; + +/* + * Standard app-level memory functions required by CDSA. + */ +void * srAppMalloc (CSSM_SIZE size, void *allocRef) { + return( malloc(size) ); +} + +void srAppFree (void *mem_ptr, void *allocRef) { + free(mem_ptr); + return; +} + +void * srAppRealloc (void *ptr, CSSM_SIZE size, void *allocRef) { + return( realloc( ptr, size ) ); +} + +void * srAppCalloc (uint32 num, CSSM_SIZE size, void *allocRef) { + return( calloc( num, size ) ); +} + +static CSSM_API_MEMORY_FUNCS memFuncs = { + srAppMalloc, + srAppFree, + srAppRealloc, + srAppCalloc, + NULL + }; + +CSSM_BOOL srCompareCssmData(const CSSM_DATA *d1, + const CSSM_DATA *d2) +{ + if(d1->Length != d2->Length) { + return CSSM_FALSE; + } + if(memcmp(d1->Data, d2->Data, d1->Length)) { + return CSSM_FALSE; + } + return CSSM_TRUE; +} + +/* + * Init CSSM; returns CSSM_FALSE on error. Reusable. + */ +static CSSM_BOOL cssmInitd = CSSM_FALSE; + +CSSM_BOOL srCssmStartup() +{ + CSSM_RETURN crtn; + CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE; + + if(cssmInitd) { + return CSSM_TRUE; + } + crtn = CSSM_Init (&vers, + CSSM_PRIVILEGE_SCOPE_NONE, + &testGuid, + CSSM_KEY_HIERARCHY_NONE, + &pvcPolicy, + NULL /* reserved */); + if(crtn != CSSM_OK) + { + srPrintError("CSSM_Init", crtn); + return CSSM_FALSE; + } + else { + cssmInitd = CSSM_TRUE; + return CSSM_TRUE; + } +} + +/* + * Attach to CSP. Returns zero on error. + */ +CSSM_CSP_HANDLE srCspStartup( + CSSM_BOOL bareCsp) // true ==> CSP, false ==> CSP/DL +{ + CSSM_CSP_HANDLE cspHand; + CSSM_RETURN crtn; + const CSSM_GUID *guid; + + /* common CSSM init */ + if(srCssmStartup() == CSSM_FALSE) { + return 0; + } + if(bareCsp) { + guid = &gGuidAppleCSP; + } + else { + guid = &gGuidAppleCSPDL; + } + crtn = CSSM_ModuleLoad(guid, + CSSM_KEY_HIERARCHY_NONE, + NULL, // eventHandler + NULL); // AppNotifyCallbackCtx + if(crtn) { + srPrintError("CSSM_ModuleLoad()", crtn); + return 0; + } + crtn = CSSM_ModuleAttach (guid, + &vers, + &memFuncs, // memFuncs + 0, // SubserviceID + CSSM_SERVICE_CSP, + 0, // AttachFlags + CSSM_KEY_HIERARCHY_NONE, + NULL, // FunctionTable + 0, // NumFuncTable + NULL, // reserved + &cspHand); + if(crtn) { + srPrintError("CSSM_ModuleAttach()", crtn); + return 0; + } + return cspHand; +} + +/* Attach to DL side of CSPDL */ +CSSM_DL_HANDLE srDlStartup() +{ + CSSM_DL_HANDLE dlHand = 0; + CSSM_RETURN crtn; + + if(srCssmStartup() == CSSM_FALSE) { + return 0; + } + crtn = CSSM_ModuleLoad(&gGuidAppleCSPDL, + CSSM_KEY_HIERARCHY_NONE, + NULL, // eventHandler + NULL); // AppNotifyCallbackCtx + if(crtn) { + srPrintError("CSSM_ModuleLoad(Apple CSPDL)", crtn); + return 0; + } + crtn = CSSM_ModuleAttach (&gGuidAppleCSPDL, + &vers, + &memFuncs, // memFuncs + 0, // SubserviceID + CSSM_SERVICE_DL, + 0, // AttachFlags + CSSM_KEY_HIERARCHY_NONE, + NULL, // FunctionTable + 0, // NumFuncTable + NULL, // reserved + &dlHand); + if(crtn) { + srPrintError("CSSM_ModuleAttach(Apple CSPDL)", crtn); + return 0; + } + return dlHand; +} + +CSSM_CL_HANDLE srClStartup() +{ + CSSM_CL_HANDLE clHand; + CSSM_RETURN crtn; + + if(srCssmStartup() == CSSM_FALSE) { + return 0; + } + crtn = CSSM_ModuleLoad(&gGuidAppleX509CL, + CSSM_KEY_HIERARCHY_NONE, + NULL, // eventHandler + NULL); // AppNotifyCallbackCtx + if(crtn) { + srPrintError("CSSM_ModuleLoad(AppleCL)", crtn); + return 0; + } + crtn = CSSM_ModuleAttach (&gGuidAppleX509CL, + &vers, + &memFuncs, // memFuncs + 0, // SubserviceID + CSSM_SERVICE_CL, // SubserviceFlags - Where is this used? + 0, // AttachFlags + CSSM_KEY_HIERARCHY_NONE, + NULL, // FunctionTable + 0, // NumFuncTable + NULL, // reserved + &clHand); + if(crtn) { + srPrintError("CSSM_ModuleAttach(AppleCL)", crtn); + return 0; + } + else { + return clHand; + } +} + +CSSM_TP_HANDLE srTpStartup() +{ + CSSM_TP_HANDLE tpHand; + CSSM_RETURN crtn; + + if(srCssmStartup() == CSSM_FALSE) { + return 0; + } + crtn = CSSM_ModuleLoad(&gGuidAppleX509TP, + CSSM_KEY_HIERARCHY_NONE, + NULL, // eventHandler + NULL); // AppNotifyCallbackCtx + if(crtn) { + srPrintError("CSSM_ModuleLoad(AppleTP)", crtn); + return 0; + } + crtn = CSSM_ModuleAttach (&gGuidAppleX509TP, + &vers, + &memFuncs, // memFuncs + 0, // SubserviceID + CSSM_SERVICE_TP, // SubserviceFlags + 0, // AttachFlags + CSSM_KEY_HIERARCHY_NONE, + NULL, // FunctionTable + 0, // NumFuncTable + NULL, // reserved + &tpHand); + if(crtn) { + srPrintError("CSSM_ModuleAttach(AppleTP)", crtn); + return 0; + } + else { + return tpHand; + } +} + +/* + * Given a context specified via a CSSM_CC_HANDLE, add a new + * CSSM_CONTEXT_ATTRIBUTE to the context as specified by AttributeType, + * AttributeLength, and an untyped pointer. + */ +CSSM_RETURN srAddContextAttribute(CSSM_CC_HANDLE CCHandle, + uint32 AttributeType, + uint32 AttributeLength, + const void *AttributePtr) +{ + CSSM_CONTEXT_ATTRIBUTE newAttr; + CSSM_RETURN crtn; + + newAttr.AttributeType = AttributeType; + newAttr.AttributeLength = AttributeLength; + newAttr.Attribute.Data = (CSSM_DATA_PTR)AttributePtr; + crtn = CSSM_UpdateContextAttributes(CCHandle, 1, &newAttr); + if(crtn) { + srPrintError("CSSM_UpdateContextAttributes", crtn); + } + return crtn; +} + + +/* + * Derive symmetric key. + * Note in the X CSP, we never return an IV. + */ +CSSM_RETURN srCspDeriveKey(CSSM_CSP_HANDLE cspHand, + uint32 keyAlg, // CSSM_ALGID_RC5, etc. + const char *keyLabel, + unsigned keyLabelLen, + uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + uint32 keySizeInBits, + CSSM_DATA_PTR password, // in PKCS-5 lingo + CSSM_DATA_PTR salt, // ditto + uint32 iterationCnt, // ditto + CSSM_KEY_PTR key) +{ + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + uint32 keyAttr; + CSSM_DATA dummyLabel; + CSSM_PKCS5_PBKDF2_PARAMS pbeParams; + CSSM_DATA pbeData; + CSSM_ACCESS_CREDENTIALS creds; + + memset(key, 0, sizeof(CSSM_KEY)); + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand, + CSSM_ALGID_PKCS5_PBKDF2, + keyAlg, + keySizeInBits, + &creds, + NULL, // BaseKey + iterationCnt, + salt, + NULL, // seed + &ccHand); + if(crtn) { + srPrintError("CSSM_CSP_CreateDeriveKeyContext", crtn); + return crtn; + } + keyAttr = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_REF | + CSSM_KEYATTR_SENSITIVE; + dummyLabel.Length = keyLabelLen; + dummyLabel.Data = (uint8 *)keyLabel; + + /* passing in password is pretty strange....*/ + pbeParams.Passphrase = *password; + pbeParams.PseudoRandomFunction = CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1; + pbeData.Data = (uint8 *)&pbeParams; + pbeData.Length = sizeof(pbeParams); + crtn = CSSM_DeriveKey(ccHand, + &pbeData, + keyUsage, + keyAttr, + &dummyLabel, + NULL, // cred and acl + key); + if(crtn) { + srPrintError("CSSM_DeriveKey", crtn); + return crtn; + } + crtn = CSSM_DeleteContext(ccHand); + if(crtn) { + srPrintError("CSSM_DeleteContext", crtn); + } + return crtn; +} + +/* + * Generate key pair of arbitrary algorithm. + */ + +/* CSP DL currently does not perform DSA generate params; let CSP do it implicitly */ +#define DO_DSA_GEN_PARAMS 0 + +CSSM_RETURN srCspGenKeyPair(CSSM_CSP_HANDLE cspHand, + CSSM_DL_DB_HANDLE *dlDbHand, // optional + uint32 algorithm, + const char *keyLabel, + unsigned keyLabelLen, + uint32 keySize, // in bits + CSSM_KEY_PTR pubKey, // mallocd by caller + CSSM_KEYUSE pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + CSSM_KEYATTR_FLAGS pubAttrs, // CSSM_KEYATTR_EXTRACTABLE, etc. + CSSM_KEY_PTR privKey, // mallocd by caller + CSSM_KEYUSE privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc. + CSSM_KEYATTR_FLAGS privAttrs) // CSSM_KEYATTR_EXTRACTABLE, etc. +{ + CSSM_RETURN crtn; + CSSM_RETURN ocrtn; + CSSM_CC_HANDLE ccHand; + CSSM_DATA keyLabelData; + + keyLabelData.Data = (uint8 *)keyLabel, + keyLabelData.Length = keyLabelLen; + memset(pubKey, 0, sizeof(CSSM_KEY)); + memset(privKey, 0, sizeof(CSSM_KEY)); + + crtn = CSSM_CSP_CreateKeyGenContext(cspHand, + algorithm, + keySize, + NULL, // Seed + NULL, // Salt + NULL, // StartDate + NULL, // EndDate + NULL, // Params + &ccHand); + if(crtn) { + srPrintError("CSSM_CSP_CreateKeyGenContext", crtn); + return crtn; + } + + /* post-context-create algorithm-specific stuff */ + switch(algorithm) { + #if DO_DSA_GEN_PARAMS + case CSSM_ALGID_DSA: + /* + * extra step - generate params - this just adds some + * info to the context + */ + { + CSSM_DATA dummy = {0, NULL}; + crtn = CSSM_GenerateAlgorithmParams(ccHand, + keySize, &dummy); + if(crtn) { + srPrintError("CSSM_GenerateAlgorithmParams", crtn); + CSSM_DeleteContext(ccHand); + return crtn; + } + srAppFree(dummy.Data, NULL); + } + break; + #endif /* DO_DSA_GEN_PARAMS */ + default: + break; + } + + /* optionally specify DL/DB storage location */ + if(dlDbHand) { + crtn = srAddContextAttribute(ccHand, + CSSM_ATTRIBUTE_DL_DB_HANDLE, + sizeof(CSSM_ATTRIBUTE_DL_DB_HANDLE), + dlDbHand); + if(crtn) { + CSSM_DeleteContext(ccHand); + return crtn; + } + } + ocrtn = CSSM_GenerateKeyPair(ccHand, + pubKeyUsage, + pubAttrs, + &keyLabelData, + pubKey, + privKeyUsage, + privAttrs, + &keyLabelData, // same labels + NULL, // CredAndAclEntry + privKey); + if(ocrtn) { + srPrintError("CSSM_GenerateKeyPair", ocrtn); + } + crtn = CSSM_DeleteContext(ccHand); + if(crtn) { + srPrintError("CSSM_DeleteContext", crtn); + if(ocrtn == CSSM_OK) { + /* error on CSSM_GenerateKeyPair takes precedence */ + ocrtn = crtn; + } + } + return ocrtn; +} + + +/* + * Add a certificate to an open Keychain. + */ +CSSM_RETURN srAddCertToKC( + SecKeychainRef keychain, + const CSSM_DATA *cert, + CSSM_CERT_TYPE certType, + CSSM_CERT_ENCODING certEncoding, + const char *printName, // C string + const CSSM_DATA *keyLabel) // ?? +{ + SecCertificateRef certificate; + + OSStatus rslt = SecCertificateCreateFromData(cert, certType, certEncoding, &certificate); + if (!rslt) + { + rslt = SecCertificateAddToKeychain(certificate, keychain); + CFRelease(certificate); + } + + return rslt; +} + +/* + * Convert a CSSM_DATA_PTR, referring to a DER-encoded int, to an + * unsigned. + */ +unsigned srDER_ToInt(const CSSM_DATA *DER_Data) +{ + uint32 rtn = 0; + unsigned i = 0; + + while(i < DER_Data->Length) { + rtn |= DER_Data->Data[i]; + if(++i == DER_Data->Length) { + break; + } + rtn <<= 8; + } + return rtn; +} + +/* + * Log CSSM error. + */ +void srPrintError(const char *op, CSSM_RETURN err) +{ + cssmPerror(op, err); +} + +/* + * Convert a CFString into a C string as safely as we can. Caller must + * free the result. + */ +char *srCfStrToCString( + CFStringRef cfStr) +{ + CFIndex len = CFStringGetLength(cfStr) + 1; + char *cstr = (char *)malloc(len); + if(cstr == NULL) { + return NULL; + } + if(!CFStringGetCString(cfStr, cstr, len, kCFStringEncodingASCII)) { + printf("***CFStringGetCString error\n"); + free(cstr); + return NULL; + } + return cstr; +} + diff --git a/SecurityTool/srCdsaUtils.h b/SecurityTool/srCdsaUtils.h new file mode 100644 index 00000000..770c9c8c --- /dev/null +++ b/SecurityTool/srCdsaUtils.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2001,2003-2011 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@ + * + * srCdsaUtils.h -- common CDSA access utilities + */ + +#ifndef _COMMON_CDSA_UTILS_H_ +#define _COMMON_CDSA_UTILS_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* common memory allocators shared by app and CSSM */ +extern void * srAppMalloc (CSSM_SIZE size, void *allocRef); +extern void srAppFree (void *mem_ptr, void *allocRef); +extern void * srAppRealloc (void *ptr, CSSM_SIZE size, void *allocRef); +extern void * srAppCalloc (uint32 num, CSSM_SIZE size, void *allocRef); + +#define APP_MALLOC(s) srAppMalloc(s, NULL) +#define APP_FREE(p) srAppFree(p, NULL) +#define APP_REALLOC(p, s) srAppRealloc(p, s, NULL) +#define APP_CALLOC(n, s) srAppRealloc(n, s, NULL) + +extern CSSM_BOOL srCompareCssmData( + const CSSM_DATA *d1, + const CSSM_DATA *d2); + +/* OID flavor of same, which will break when an OID is not a CSSM_DATA */ +#define srCompareOid(o1, o2) srCompareCssmData(o1, o2) + +void srPrintError(const char *op, CSSM_RETURN err); + +/* Init CSSM; returns CSSM_FALSE on error. Reusable. */ +extern CSSM_BOOL srCssmStartup(); + +/* Attach to CSP. Returns zero on error. */ +extern CSSM_CSP_HANDLE srCspStartup( + CSSM_BOOL bareCsp); // true ==> CSP, false ==> CSP/DL + +/* Attach to DL side of CSPDL. */ +extern CSSM_DL_HANDLE srDlStartup(); + +/* Attach to CL, TP */ +extern CSSM_CL_HANDLE srClStartup(); +extern CSSM_TP_HANDLE srTpStartup(); + +/* + * Derive symmetric key using PBE. + */ +extern CSSM_RETURN srCspDeriveKey(CSSM_CSP_HANDLE cspHand, + uint32 keyAlg, // CSSM_ALGID_RC5, etc. + const char *keyLabel, + unsigned keyLabelLen, + uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + uint32 keySizeInBits, + CSSM_DATA_PTR password, // in PKCS-5 lingo + CSSM_DATA_PTR salt, // ditto + uint32 iterationCnt, // ditto + CSSM_KEY_PTR key); + +/* + * Generate key pair of arbitrary algorithm. + */ +extern CSSM_RETURN srCspGenKeyPair(CSSM_CSP_HANDLE cspHand, + CSSM_DL_DB_HANDLE *dlDbHand, // optional + uint32 algorithm, + const char *keyLabel, + unsigned keyLabelLen, + uint32 keySize, // in bits + CSSM_KEY_PTR pubKey, // mallocd by caller + CSSM_KEYUSE pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + CSSM_KEYATTR_FLAGS pubAttrs, // CSSM_KEYATTR_EXTRACTABLE, etc. + CSSM_KEY_PTR privKey, // mallocd by caller + CSSM_KEYUSE privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc. + CSSM_KEYATTR_FLAGS privAttrs); // CSSM_KEYATTR_EXTRACTABLE, etc. + +/* Convert a reference key to a raw key. */ +CSSM_RETURN srRefKeyToRaw(CSSM_CSP_HANDLE cspHand, + const CSSM_KEY *refKey, + CSSM_KEY_PTR rawKey); // RETURNED + +/* + * Add a certificate to a keychain. + */ +CSSM_RETURN srAddCertToKC( + SecKeychainRef keychain, + const CSSM_DATA *cert, + CSSM_CERT_TYPE certType, + CSSM_CERT_ENCODING certEncoding, + const char *printName, // C string + const CSSM_DATA *keyLabel); // ?? + +/* + * Convert a CSSM_DATA_PTR, referring to a DER-encoded int, to an + * unsigned. + */ +unsigned srDER_ToInt( + const CSSM_DATA *DER_Data); + +char *srCfStrToCString( + CFStringRef cfStr); + +#ifdef __cplusplus +} +#endif + +#endif /* _COMMON_CDSA_UTILS_H_ */ diff --git a/SecurityTool/sub_commands.h b/SecurityTool/sub_commands.h new file mode 100644 index 00000000..39fd218c --- /dev/null +++ b/SecurityTool/sub_commands.h @@ -0,0 +1,29 @@ +/* + * 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 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" diff --git a/SecurityTool/trust_settings_impexp.c b/SecurityTool/trust_settings_impexp.c new file mode 100644 index 00000000..9bc255a8 --- /dev/null +++ b/SecurityTool/trust_settings_impexp.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2006,2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * trust_cert_add.c + */ + +#include "trust_settings_impexp.h" +#include "security.h" +#include +#include +#include +#include +#include +#include +#include + +extern int trust_settings_export(int argc, char * const *argv) +{ + extern char *optarg; + extern int optind; + OSStatus ortn; + int arg; + CFDataRef settings = NULL; + SecTrustSettingsDomain domain = kSecTrustSettingsDomainUser; + int rtn; + char *settingsFile = NULL; + unsigned len; + + if(argc < 2) { + return 2; /* @@@ Return 2 triggers usage message. */ + } + + optind = 1; + while ((arg = getopt(argc, argv, "dsh")) != -1) { + switch (arg) { + case 'd': + domain = kSecTrustSettingsDomainAdmin; + break; + case 's': + domain = kSecTrustSettingsDomainSystem; + break; + default: + return 2; + } + } + if(optind != (argc - 1)) { + /* no args left for settings file */ + return 2; + } + settingsFile = argv[optind]; + + ortn = SecTrustSettingsCreateExternalRepresentation(domain, &settings); + if(ortn) { + cssmPerror("SecTrustSettingsCreateExternalRepresentation", ortn); + return 1; + } + len = CFDataGetLength(settings); + rtn = writeFile(settingsFile, CFDataGetBytePtr(settings), len); + if(rtn) { + fprintf(stderr, "Error (%d) writing %s.\n", rtn, settingsFile); + } + else if(!do_quiet) { + fprintf(stdout, "...Trust Settings exported successfully.\n"); + } + CFRelease(settings); + return rtn; +} + +extern int trust_settings_import(int argc, char * const *argv) +{ + extern char *optarg; + extern int optind; + OSStatus ortn; + int arg; + char *settingsFile = NULL; + unsigned char *settingsData = NULL; + unsigned settingsLen = 0; + CFDataRef settings = NULL; + SecTrustSettingsDomain domain = kSecTrustSettingsDomainUser; + int rtn; + + if(argc < 2) { + return 2; /* @@@ Return 2 triggers usage message. */ + } + + optind = 1; + while ((arg = getopt(argc, argv, "dh")) != -1) { + switch (arg) { + case 'd': + domain = kSecTrustSettingsDomainAdmin; + break; + default: + return 2; + } + } + if(optind != (argc - 1)) { + /* no args left for settings file */ + return 2; + } + settingsFile = argv[optind]; + rtn = readFile(settingsFile, &settingsData, &settingsLen); + if(rtn) { + fprintf(stderr, "Error (%d) reading %s.\n", rtn, settingsFile); + return 1; + } + settings = CFDataCreate(NULL, (const UInt8 *)settingsData, settingsLen); + free(settingsData); + ortn = SecTrustSettingsImportExternalRepresentation(domain, settings); + CFRelease(settings); + if(ortn) { + cssmPerror("SecTrustSettingsImportExternalRepresentation", ortn); + rtn = 1; + } + else if(!do_quiet) { + fprintf(stdout, "...Trust Settings imported successfully.\n"); + rtn = 0; + } + return rtn; +} + diff --git a/SecurityTool/trust_settings_impexp.h b/SecurityTool/trust_settings_impexp.h new file mode 100644 index 00000000..07c662fd --- /dev/null +++ b/SecurityTool/trust_settings_impexp.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2006,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + * + * trust_settings_impexp.h + */ + +#ifndef _TRUST_SETTINGS_IMP_EXP_H_ +#define _TRUST_SETTINGS_IMP_EXP_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int trust_settings_export(int argc, char * const *argv); +extern int trust_settings_import(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _TRUST_SETTINGS_IMP_EXP_H_ */ diff --git a/SecurityTool/trusted_cert_add.c b/SecurityTool/trusted_cert_add.c new file mode 100644 index 00000000..7c0b9cdc --- /dev/null +++ b/SecurityTool/trusted_cert_add.c @@ -0,0 +1,626 @@ +/* + * Copyright (c) 2006-2010,2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * trust_cert_add.c + */ + +/* + * This command is fairly versatile and hence the usage might be a bit confusing. + * The standard usage of this command is to add one or more certs to a Trust + * Settings domain, along with optional usage constraints. Often, but not + * necessarily, you'd also add the cert to a keychain while you're adding + * it to Trust Settings. + * + * -- To add someRoot.cer to your login keychain and to your Trust Settings as + * an unrestricted root cert: + * + * % security add-trusted-cert -k login.keychain someRoot.cer + * + * -- To add anotherRoot.cer to the local admin trust settings, only for policy + * ssl, without adding it to a keychain (presumably because it's already in + * a keychain somewhere else): + * + * % security add-trusted-cert -p ssl -d anotherRoot.cer + * + * The more obscure uses involve default settings and trust settings files. + * + * Specifying a default trust setting precludes specifying a cert. Other + * options apply as usual; note that if the domain for which you are + * specifying a default setting already has a default setting, the old default + * will be replaced by the new one you specify. + * + * -- To specify a default of "deny" for policy SMIME for the admin domain: + * + * % security add-trusted-cert -p smime -r deny -D + * + * This command can also operate on trust settings as files instead of + * modifying an actual on-disk Trust Settings record. One standard use for + * this function is in the creation of the system Trust Settings, which + * are immutable at runtime via the SecTrustSettings API. You provide a + * file name for this option via -f settingsFile. If the file does not + * exist, a new empty Trust Settings will be created, and certs and/or + * a default will be added to that record, and the record will be written + * out to the filename you provide (infile = outfile, always). + * + * -- To create Trust Settings record with one cert in it, restricted to + * policy SSL: + * + * % security add-trusted-cert -p ssl -f someTrustSettingsFile.plist -r someRoot.cer + * + * You can also use the -f option and specify no certs, in which case an empty + * Trust Settings record will be created. This can be useful if you want to + * quickly reset the Trust Settings in a given domain to "empty"; the + * empty Trust Settings record can be imported via the trust-settings-import + * command. + * + * -- To reset the admin trust settings to "empty": + * + * % security add-trusted-cert -f emptySettingsFile.plist + * % security trust-settings-import -d emptySettingsFile.plist + */ + +#include "trusted_cert_add.h" +#include "trusted_cert_utils.h" +#include "security.h" +#include "keychain_utilities.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* r/w files as CFData */ +static CFDataRef readFileData( + const char *fileName) +{ + unsigned char *d; + unsigned dLen; + + if(readFile(fileName, &d, &dLen)) { + return NULL; + } + CFDataRef cfd = CFDataCreate(NULL, (const UInt8 *)d, dLen); + free(d); + return cfd; +} + +static int writeFileData( + const char *fileName, + CFDataRef cfd) +{ + unsigned long l = (unsigned long)CFDataGetLength(cfd); + int rtn = writeFile(fileName, CFDataGetBytePtr(cfd), l); + if(rtn) { + fprintf(stderr, "Error %d writing to %s\n", rtn, fileName); + } + else if(!do_quiet) { + fprintf(stdout, "...wrote %ld bytes to %s\n", l, fileName); + } + return rtn; +} + +static int appendConstraintsToDict( + const char *appPath, /* optional */ + const char *policy, /* optional - smime, ssl, etc. */ + const char *policyStr, /* optional policy string */ + SecTrustSettingsResult resultType, + CSSM_RETURN allowErr, /* optional allowed error */ + SecTrustSettingsKeyUsage keyUse,/* optional key use */ + CFMutableDictionaryRef *dict) /* result RETURNED here, created if necessary */ +{ + if(*dict == NULL) { + *dict = CFDictionaryCreateMutable(NULL, + 0, // capacity + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + } + + /* OID string to an OID pointer */ + const CSSM_OID *oid = NULL; + if(policy != NULL) { + oid = policyStringToOid(policy); + if(oid == NULL) { + return 2; + } + + /* OID to SecPolicyRef */ + SecPolicyRef policyRef = oidToPolicy(oid); + if(policyRef == NULL) { + return 2; + } + CFDictionaryAddValue(*dict, kSecTrustSettingsPolicy, policyRef); + CFRelease(policyRef); + } + + /* app string to SecTrustedApplicationRef */ + if(appPath != NULL) { + SecTrustedApplicationRef appRef; + OSStatus ortn = SecTrustedApplicationCreateFromPath(appPath, &appRef); + if(ortn) { + cssmPerror("SecTrustedApplicationCreateFromPath", ortn); + return -1; + } + CFDictionaryAddValue(*dict, kSecTrustSettingsApplication, appRef); + CFRelease(appRef); + } + + if(policyStr != NULL) { + CFStringRef pstr = CFStringCreateWithCString(NULL, policyStr, kCFStringEncodingUTF8); + CFDictionaryAddValue(*dict, kSecTrustSettingsPolicyString, pstr); + CFRelease(pstr); + } + + if(allowErr) { + SInt32 ae = (SInt32)allowErr; + CFNumberRef cfNum = CFNumberCreate(NULL, kCFNumberSInt32Type, &ae); + CFDictionaryAddValue(*dict, kSecTrustSettingsAllowedError, cfNum); + CFRelease(cfNum); + } + + if(keyUse != 0) { + SInt32 ku = (SInt32)keyUse; + CFNumberRef cfNum = CFNumberCreate(NULL, kCFNumberSInt32Type, &ku); + CFDictionaryAddValue(*dict, kSecTrustSettingsKeyUsage, cfNum); + CFRelease(cfNum); + } + + if(resultType != kSecTrustSettingsResultTrustRoot) { + SInt32 rt = (SInt32)resultType; + CFNumberRef cfNum = CFNumberCreate(NULL, kCFNumberSInt32Type, &rt); + CFDictionaryAddValue(*dict, kSecTrustSettingsResult, cfNum); + CFRelease(cfNum); + } + + return 0; +} + + +int +trusted_cert_add(int argc, char * const *argv) +{ + extern char *optarg; + extern int optind; + OSStatus ortn; + int arg; + SecTrustSettingsDomain domain = kSecTrustSettingsDomainUser; + int ourRtn = 0; + SecKeychainRef kcRef = NULL; + int defaultSetting = 0; + char *certFile = NULL; + SecCertificateRef certRef = NULL; + + /* for operating in file-based settings */ + char *settingsFileIn = NULL; + char *settingsFileOut = NULL; + CFDataRef settingsIn = NULL; + CFDataRef settingsOut = NULL; + + /* optional usage constraints */ +// char *policy = NULL; + char *appPath = NULL; +// char *policyString = NULL; + SecTrustSettingsResult resultType = kSecTrustSettingsResultTrustRoot; + CSSM_RETURN allowErr = CSSM_OK; + SecTrustSettingsKeyUsage keyUse = 0; + CFMutableArrayRef trustSettings = NULL; + int haveConstraints = 0; + + const int maxPolicies = 16; // upper limit on policies that can be set in one invocation + char *policyNames[maxPolicies]; + char *policyStrings[maxPolicies]; + int allowedErrors[maxPolicies]; + int policyNameCount = 0, policyStringCount = 0, allowedErrorCount = 0; + + if(argc < 2) { + return 2; /* @@@ Return 2 triggers usage message. */ + } + + optind = 1; + while ((arg = getopt(argc, argv, "dr:a:p:s:e:u:k:i:o:Dh")) != -1) { + switch (arg) { + case 'd': + domain = kSecTrustSettingsDomainAdmin; + break; + case 'r': + if(!strcmp(optarg, "trustRoot")) { + resultType = kSecTrustSettingsResultTrustRoot; + } + else if(!strcmp(optarg, "trustAsRoot")) { + resultType = kSecTrustSettingsResultTrustAsRoot; + } + else if(!strcmp(optarg, "deny")) { + resultType = kSecTrustSettingsResultDeny; + } + else if(!strcmp(optarg, "unspecified")) { + resultType = kSecTrustSettingsResultUnspecified; + } + else { + return 2; + } + haveConstraints = 1; + break; + case 'p': + if (policyNameCount < maxPolicies) { + policyNames[policyNameCount++] = optarg; + } else { + fprintf(stderr, "Too many policy arguments.\n"); + return 2; + } + haveConstraints = 1; + break; + case 'a': + appPath = optarg; + haveConstraints = 1; + break; + case 's': + if (policyStringCount < maxPolicies) { + policyStrings[policyStringCount++] = optarg; + } else { + fprintf(stderr, "Too many policy string arguments.\n"); + return 2; + } + haveConstraints = 1; + break; + case 'e': + if (allowedErrorCount < maxPolicies) { + if (!strcmp("certExpired", optarg)) + allowErr = -2147409654; // 0x8001210A = CSSMERR_TP_CERT_EXPIRED + else if (!strcmp("hostnameMismatch", optarg)) + allowErr = -2147408896; // 0x80012400 = CSSMERR_APPLETP_HOSTNAME_MISMATCH + else + allowErr = (CSSM_RETURN)atoi(optarg); + if (!allowErr) { + fprintf(stderr, "Invalid value for allowed error.\n"); + return 2; + } + allowedErrors[allowedErrorCount++] = allowErr; + } else { + fprintf(stderr, "Too many \"allowed error\" arguments.\n"); + return 2; + } + haveConstraints = 1; + break; + case 'u': + keyUse = (SecTrustSettingsKeyUsage)atoi(optarg); + haveConstraints = 1; + break; + case 'k': + kcRef = keychain_open(optarg); + if(kcRef == NULL) { + return 1; + } + break; + case 'i': + settingsFileIn = optarg; + break; + case 'o': + settingsFileOut = optarg; + break; + case 'D': + defaultSetting = 1; + break; + default: + case 'h': + return 2; /* @@@ Return 2 triggers usage message. */ + } + } + if(ourRtn) { + goto errOut; + } + + switch(argc - optind) { + case 0: + /* no certs */ + break; + case 1: + certFile = argv[optind]; + break; + default: + ourRtn = 2; + goto errOut; + } + + /* validate inputs */ + if(defaultSetting && (certFile != NULL)) { + fprintf(stderr, "Can't specify cert when manipulating default setting.\n"); + ourRtn = 2; /* @@@ Return 2 triggers usage message. */ + goto errOut; + } + if((certFile == NULL) && (settingsFileOut == NULL) && !defaultSetting) { + /* no cert file - only legal for r/w file or for default settings */ + fprintf(stderr, "No cert file specified.\n"); + ourRtn = 2; + goto errOut; + } + if((settingsFileOut != NULL) && (domain != kSecTrustSettingsDomainUser)) { + fprintf(stderr, "Can't specify both domain and a settingsFile\n"); + ourRtn = 2; + goto errOut; + } + if((settingsFileIn != NULL) && (settingsFileOut == NULL)) { + /* on the other hand, fileOut with no fileIn is OK */ + fprintf(stderr, "Can't specify settingsFileIn and no settingsFileOut\n"); + ourRtn = 2; + goto errOut; + } + + /* build per-policy constraints dictionaries */ + if(haveConstraints) { + int i, j, k; + for (i=0; i +#include +#include +#include +#include +#include +#include +#include + +// SecCertificateInferLabel +#include + + +/* print cert's label (the one SecCertificate infers) */ +static OSStatus printCertLabel( + SecCertificateRef certRef) +{ + OSStatus ortn; + CFStringRef label; + + ortn = SecCertificateInferLabel(certRef, &label); + if(ortn) { + cssmPerror("SecCertificateInferLabel", ortn); + return ortn; + } + printCfStr(label); + CFRelease(label); + return noErr; +} + +/* + * Display a Trust Settings array as obtained from + * SecTrustSettingsCopyTrustSettings(). + */ +static int displayTrustSettings( + CFArrayRef trustSettings) +{ + /* must always be there though it may be empty */ + if(trustSettings == NULL) { + fprintf(stderr, "***displayTrustSettings: missing trust settings array"); + return -1; + } + if(CFGetTypeID(trustSettings) != CFArrayGetTypeID()) { + fprintf(stderr, "***displayTrustSettings: malformed trust settings array"); + return -1; + } + + int ourRtn = 0; + CFIndex numUseConstraints = CFArrayGetCount(trustSettings); + indentIncr(); + indent(); printf("Number of trust settings : %ld\n", (long)numUseConstraints); + OSStatus ortn; + SecPolicyRef certPolicy; + SecTrustedApplicationRef certApp; + CFDictionaryRef ucDict; + CFStringRef policyStr; + CFNumberRef cfNum; + CFIndex ucDex; + + /* grind thru the trust settings dictionaries */ + for(ucDex=0; ucDex +#include +#include +#include +#include +#include +#include +#include + +static int indentSize = 0; +void indentIncr(void) { indentSize += 3; } +void indentDecr(void) { indentSize -= 3; } + +void indent(void) +{ + int dex; + if(indentSize < 0) { + /* bug */ + indentSize = 0; + } + for (dex=0; dex maxLen) { + len = maxLen; + doEllipsis = true; + } + for(dex=0; dex maxLen) { + len = maxLen; + doEllipsis = true; + } + for(dex=0; dex>"); + return; + } + const char *cp = (const char *)CFDataGetBytePtr(strData); + CFIndex len = CFDataGetLength(strData); + for(dex=0; dex>\n"); + return; + } + CFGregorianDate gregDate = CFAbsoluteTimeGetGregorianDate(absTime, NULL); + const char *month = "Unknown"; + if((gregDate.month > 12) || (gregDate.month <= 0)) { + printf("Huh? GregDate.month > 11. These amps only GO to 11.\n"); + } + else { + month = months[gregDate.month - 1]; + } + printf("%s %d, %d %02d:%02d", + month, gregDate.day, (int)gregDate.year, gregDate.hour, gregDate.minute); +} + +/* print a CFNumber */ +void printCfNumber( + CFNumberRef cfNum) +{ + SInt32 s; + if(!CFNumberGetValue(cfNum, kCFNumberSInt32Type, &s)) { + printf("***CFNumber overflow***"); + return; + } + printf("%d", (int)s); +} + +/* print a CFNumber as a SecTrustSettingsResult */ +void printResultType( + CFNumberRef cfNum) +{ + SInt32 n; + if(!CFNumberGetValue(cfNum, kCFNumberSInt32Type, &n)) { + printf("***CFNumber overflow***"); + return; + } + const char *s; + char bogus[100]; + switch(n) { + case kSecTrustSettingsResultInvalid: s = "kSecTrustSettingsResultInvalid"; break; + case kSecTrustSettingsResultTrustRoot: s = "kSecTrustSettingsResultTrustRoot"; break; + case kSecTrustSettingsResultTrustAsRoot: s = "kSecTrustSettingsResultTrustAsRoot"; break; + case kSecTrustSettingsResultDeny: s = "kSecTrustSettingsResultDeny"; break; + case kSecTrustSettingsResultUnspecified: s = "kSecTrustSettingsResultUnspecified"; break; + default: + sprintf(bogus, "Unknown SecTrustSettingsResult (%d)", (int)n); + s = bogus; + break; + } + printf("%s", s); +} + +/* print a CFNumber as SecTrustSettingsKeyUsage */ +void printKeyUsage( + CFNumberRef cfNum) +{ + SInt32 s; + if(!CFNumberGetValue(cfNum, kCFNumberSInt32Type, &s)) { + printf("***CFNumber overflow***"); + return; + } + uint32 n = (uint32)s; + if(n == kSecTrustSettingsKeyUseAny) { + printf(""); + return; + } + else if(n == 0) { + printf(""); + return; + } + printf("< "); + if(n & kSecTrustSettingsKeyUseSignature) { + printf("Signature "); + } + if(n & kSecTrustSettingsKeyUseEnDecryptData) { + printf("EnDecryptData "); + } + if(n & kSecTrustSettingsKeyUseEnDecryptKey) { + printf("EnDecryptKey "); + } + if(n & kSecTrustSettingsKeyUseSignCert) { + printf("SignCert "); + } + if(n & kSecTrustSettingsKeyUseSignRevocation) { + printf("SignRevocation "); + } + if(n & kSecTrustSettingsKeyUseKeyExchange) { + printf("KeyExchange "); + } + printf(" >"); +} + +/* print a CFNumber as CSSM_RETURN string */ +void printCssmErr( + CFNumberRef cfNum) +{ + SInt32 s; + if(!CFNumberGetValue(cfNum, kCFNumberSInt32Type, &s)) { + printf("***CFNumber overflow***"); + return; + } + printf("%s", cssmErrorString((CSSM_RETURN)s)); +} + +/* convert an OID to a SecPolicyRef */ +SecPolicyRef oidToPolicy( + const CSSM_OID *oid) +{ + OSStatus ortn; + SecPolicyRef policyRef = NULL; + + ortn = SecPolicyCopy(CSSM_CERT_X_509v3, oid, &policyRef); + if(ortn) { + cssmPerror("SecPolicyCopy", ortn); + return NULL; + } + return policyRef; +} + +typedef struct { + const CSSM_OID *oid; + const char *oidStr; +} OidString; + +static OidString oidStrings[] = +{ + { &CSSMOID_APPLE_ISIGN, "iSign" }, + { &CSSMOID_APPLE_X509_BASIC, "Apple X509 Basic" }, + { &CSSMOID_APPLE_TP_SSL, "SSL" }, + { &CSSMOID_APPLE_TP_SMIME, "SMIME" }, + { &CSSMOID_APPLE_TP_EAP, "EAP" }, + { &CSSMOID_APPLE_TP_SW_UPDATE_SIGNING, "SW Update Signing" }, + { &CSSMOID_APPLE_TP_IP_SEC, "IPSec" }, + { &CSSMOID_APPLE_TP_ICHAT, "iChat" }, + { &CSSMOID_APPLE_TP_RESOURCE_SIGN, "Resource Signing" }, + { &CSSMOID_APPLE_TP_PKINIT_CLIENT, "PKINIT Client" }, + { &CSSMOID_APPLE_TP_PKINIT_SERVER, "PKINIT Server" }, + { &CSSMOID_APPLE_TP_CODE_SIGNING, "Code Signing" }, + { &CSSMOID_APPLE_TP_PACKAGE_SIGNING, "Package Signing" }, + { &CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT, "Mac App Store" }, + { &CSSMOID_APPLE_TP_APPLEID_SHARING, "AppleID Sharing" } +}; +#define NUM_OID_STRINGS (sizeof(oidStrings) / sizeof(oidStrings[0])) + +/* convert a policy string to a SecPolicyRef */ +SecPolicyRef oidStringToPolicy( + const char *oidStr) +{ + /* OID string to an OID pointer */ + const CSSM_OID *oid = NULL; + unsigned dex; + + for(dex=0; dexoidStr)) { + oid = os->oid; + break; + } + } + if(oid == NULL) { + return NULL; + } + + /* OID to SecPolicyRef */ + return oidToPolicy(oid); +} + +/* CSSM_OID --> OID string */ +const char *oidToOidString( + const CSSM_OID *oid) +{ + unsigned dex; + static char unknownOidString[200]; + + for(dex=0; dexoid)) { + return os->oidStr; + } + } + sprintf(unknownOidString, "Unknown OID length %ld, value { ", oid->Length); + for(dex=0; dexLength; dex++) { + char tmp[6]; + sprintf(tmp, "%02X ", oid->Data[dex]); + strcat(unknownOidString, tmp); + } + strcat(unknownOidString, " }"); + return unknownOidString; +} + +/* compare OIDs; returns 1 if identical, else returns 0 */ +int compareOids( + const CSSM_OID *oid1, + const CSSM_OID *oid2) +{ + if((oid1 == NULL) || (oid2 == NULL)) { + return 0; + } + if(oid1->Length != oid2->Length) { + return 0; + } + if(memcmp(oid1->Data, oid2->Data, oid1->Length)) { + return 0; + } + return 1; +} + +/* app path string to SecTrustedApplicationRef */ +SecTrustedApplicationRef appPathToAppRef( + const char *appPath) +{ + SecTrustedApplicationRef appRef = NULL; + OSStatus ortn; + + if(appPath == NULL) { + return NULL; + } + ortn = SecTrustedApplicationCreateFromPath(appPath, &appRef); + if(ortn) { + cssmPerror("SecTrustedApplicationCreateFromPath", ortn); + return NULL; + } + return appRef; +} + +int readCertFile( + const char *fileName, + SecCertificateRef *certRef) +{ + unsigned char *cp = NULL; + unsigned len = 0; + CSSM_DATA certData; + OSStatus ortn; + unsigned char *decoded = NULL; + unsigned decodedLen = 0; + + if(readFile(fileName, &cp, &len)) { + printf("***Error reading file %s\n", fileName); + return -1; + } + if(isPem(cp, len)) { + if(pemDecode(cp, len, &decoded, &decodedLen)) { + fprintf(stderr, "Error decoding cert file %s\n", fileName); + return -1; + } + certData.Length = decodedLen; + certData.Data = decoded; + } + else { + certData.Length = len; + certData.Data = cp; + } + ortn = SecCertificateCreateFromData(&certData, + CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, certRef); + free(cp); + if(decoded) { + free(decoded); + } + if(ortn) { + cssmPerror("SecCertificateCreateFromData", ortn); + return -1; + } + return 0; +} + +/* policy string --> CSSM_OID */ +const CSSM_OID *policyStringToOid( + const char *policy) +{ + if(policy == NULL) { + return NULL; + } + if(!strcmp(policy, "ssl")) { + return &CSSMOID_APPLE_TP_SSL; + } + else if(!strcmp(policy, "smime")) { + return &CSSMOID_APPLE_TP_SMIME; + } + else if(!strcmp(policy, "codeSign")) { + return &CSSMOID_APPLE_TP_CODE_SIGNING; + } + else if(!strcmp(policy, "IPSec")) { + return &CSSMOID_APPLE_TP_IP_SEC; + } + else if(!strcmp(policy, "iChat")) { + return &CSSMOID_APPLE_TP_ICHAT; + } + else if(!strcmp(policy, "basic")) { + return &CSSMOID_APPLE_X509_BASIC; + } + else if(!strcmp(policy, "swUpdate")) { + return &CSSMOID_APPLE_TP_SW_UPDATE_SIGNING; + } + else if(!strcmp(policy, "pkgSign")) { + return &CSSMOID_APPLE_TP_PACKAGE_SIGNING; + } + else if(!strcmp(policy, "pkinitClient")) { + return &CSSMOID_APPLE_TP_PKINIT_CLIENT; + } + else if(!strcmp(policy, "pkinitServer")) { + return &CSSMOID_APPLE_TP_PKINIT_SERVER; + } + else if(!strcmp(policy, "eap")) { + return &CSSMOID_APPLE_TP_EAP; + } + else if(!strcmp(policy, "macappstore")) { + return &CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT; + } + else if(!strcmp(policy, "appleID")) { + return &CSSMOID_APPLE_TP_APPLEID_SHARING; + } + else if(!strcmp(policy, "timestamping")) { + return &CSSMOID_APPLE_TP_TIMESTAMPING; + } + else { + fprintf(stderr, "***unknown policy spec (%s)\n", policy); + return NULL; + } +} diff --git a/SecurityTool/trusted_cert_utils.h b/SecurityTool/trusted_cert_utils.h new file mode 100644 index 00000000..fb2e10fb --- /dev/null +++ b/SecurityTool/trusted_cert_utils.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2003-2004,2006,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + * + * trusted_cert_utils.h + */ +#ifndef _TRUSTED_CERT_UTILS_H_ +#define _TRUSTED_CERT_UTILS_H_ 1 + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define CFRELEASE(cf) if(cf != NULL) { CFRelease(cf); } + +extern void indentIncr(void); +extern void indentDecr(void); +extern void indent(void); +void printAscii(const char *buf, unsigned len, unsigned maxLen); +void printHex(const unsigned char *buf, unsigned len, unsigned maxLen); +void printCfStr(CFStringRef cfstr); +void printCFDate(CFDateRef dateRef); +void printCfNumber(CFNumberRef cfNum); +void printResultType(CFNumberRef cfNum); +void printKeyUsage(CFNumberRef cfNum); +void printCssmErr(CFNumberRef cfNum); + +/* convert an OID to a SecPolicyRef */ +extern SecPolicyRef oidToPolicy(const CSSM_OID *oid); + +/* convert a policy string to a SecPolicyRef */ +extern SecPolicyRef oidStringToPolicy(const char *oidStr); + +/* CSSM_OID --> OID string */ +extern const char *oidToOidString(const CSSM_OID *oid); + +/* compare OIDs; returns 1 if identical, else returns 0 */ +extern int compareOids(const CSSM_OID *oid1, const CSSM_OID *oid2); + +/* app path string to SecTrustedApplicationRef */ +extern SecTrustedApplicationRef appPathToAppRef(const char *appPath); + +/* read a file --> SecCertificateRef */ +int readCertFile(const char *fileName, SecCertificateRef *certRef); + +/* policy string --> CSSM_OID */ +const CSSM_OID *policyStringToOid(const char *policy); + +#ifdef __cplusplus +} +#endif + +#endif /* _TRUSTED_CERT_UTILS_H_ */ diff --git a/SecurityTool/user_trust_enable.cpp b/SecurityTool/user_trust_enable.cpp new file mode 100644 index 00000000..338d7752 --- /dev/null +++ b/SecurityTool/user_trust_enable.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2003-2004,2006,2008-2009,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@ + * + * user_trust_enable.cpp + */ + +#include "user_trust_enable.h" +#include +#include +#include +#include /* private SPI */ +#include + +typedef enum { + utoSet = 0, + utoShow +} UserTrustOp; + +int +user_trust_enable(int argc, char * const *argv) +{ + extern int optind; + int arg; + UserTrustOp op = utoShow; + CFBooleanRef disabledBool = kCFBooleanFalse; /* what we write to prefs */ + optind = 1; + int ourRtn = 0; + + while ((arg = getopt(argc, argv, "deh")) != -1) { + switch (arg) { + case 'd': + op = utoSet; + disabledBool = kCFBooleanTrue; + break; + case 'e': + op = utoSet; + disabledBool = kCFBooleanFalse; + break; + default: + case 'h': + return 2; /* @@@ Return 2 triggers usage message. */ + } + } + if(optind != argc) { + return 2; /* @@@ Return 2 triggers usage message. */ + } + + if(op == utoShow) { + bool utDisable = false; + +#if !defined MAC_OS_X_VERSION_10_6 || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 + Dictionary* prefsDict = new Dictionary(kSecTrustSettingsPrefsDomain, Dictionary::US_System); +#else + Dictionary* prefsDict = Dictionary::CreateDictionary(kSecTrustSettingsPrefsDomain, Dictionary::US_System); +#endif + if (prefsDict != NULL) + { + utDisable = prefsDict->getBoolValue(kSecTrustSettingsDisableUserTrustSettings); + delete prefsDict; + } + + fprintf(stdout, "User-level Trust Settings are %s\n", + utDisable ? "Disabled" : "Enabled"); + return 0; + } + + /* set the pref... */ + if(geteuid() != 0) { + fprintf(stderr, "You must be root to set this preference.\n"); + return 1; + } + + /* get a mutable copy of the existing prefs, or a fresh empty one */ +#if !defined MAC_OS_X_VERSION_10_6 || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 + MutableDictionary *prefsDict = new MutableDictionary(kSecTrustSettingsPrefsDomain, Dictionary::US_System); +#else + MutableDictionary *prefsDict = MutableDictionary::CreateMutableDictionary(kSecTrustSettingsPrefsDomain, Dictionary::US_System); +#endif + if (prefsDict == NULL) + { + prefsDict = new MutableDictionary(); + } + + prefsDict->setValue(kSecTrustSettingsDisableUserTrustSettings, disabledBool); + if(prefsDict->writePlistToPrefs(kSecTrustSettingsPrefsDomain, Dictionary::US_System)) { + fprintf(stdout, "...User-level Trust Settings are %s\n", + (disabledBool == kCFBooleanTrue) ? "Disabled" : "Enabled"); + } + else { + fprintf(stderr, "Could not write system preferences.\n"); + ourRtn = 1; + } + delete prefsDict; + return ourRtn; +} diff --git a/SecurityTool/user_trust_enable.h b/SecurityTool/user_trust_enable.h new file mode 100644 index 00000000..c27af38a --- /dev/null +++ b/SecurityTool/user_trust_enable.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2003-2004,2006,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + * + * user_trust_enable.h + */ + +#ifndef _USER_TRUST_ENABLE_H_ +#define _USER_TRUST_ENABLE_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int user_trust_enable(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _USER_TRUST_ENABLE_H_ */ diff --git a/SecurityTool/verify_cert.c b/SecurityTool/verify_cert.c new file mode 100644 index 00000000..59b74d6a --- /dev/null +++ b/SecurityTool/verify_cert.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2006,2010,2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * verify_cert.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "trusted_cert_utils.h" + +/* + * Read file as a cert, add to a CFArray, creating the array if necessary + */ +static int addCertFile( + const char *fileName, + CFMutableArrayRef *array) +{ + SecCertificateRef certRef; + + if(readCertFile(fileName, &certRef)) { + return -1; + } + if(*array == NULL) { + *array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + } + CFArrayAppendValue(*array, certRef); + CFRelease(certRef); + return 0; +} + +int +verify_cert(int argc, char * const *argv) +{ + extern char *optarg; + extern int optind; + OSStatus ortn; + int arg; + CFMutableArrayRef certs = NULL; + CFMutableArrayRef roots = NULL; + CFMutableArrayRef keychains = NULL; + const CSSM_OID *policy = &CSSMOID_APPLE_X509_BASIC; + SecKeychainRef kcRef = NULL; + int ourRtn = 0; + bool quiet = false; + SecPolicyRef policyRef = NULL; + SecTrustRef trustRef = NULL; + SecPolicySearchRef searchRef = NULL; + const char *emailAddrs = NULL; + const char *sslHost = NULL; + CSSM_APPLE_TP_SSL_OPTIONS sslOpts; + CSSM_APPLE_TP_SMIME_OPTIONS smimeOpts; + CSSM_APPLE_TP_ACTION_FLAGS actionFlags = 0; + bool forceActionFlags = false; + CSSM_APPLE_TP_ACTION_DATA actionData; + CSSM_DATA optionData; + CFDataRef cfActionData = NULL; + SecTrustResultType resultType; + OSStatus ocrtn; + + if(argc < 2) { + return 2; /* @@@ Return 2 triggers usage message. */ + } + /* permit network cert fetch unless explicitly turned off with '-L' */ + actionFlags |= CSSM_TP_ACTION_FETCH_CERT_FROM_NET; + optind = 1; + while ((arg = getopt(argc, argv, "c:r:p:k:e:s:Llnq")) != -1) { + switch (arg) { + case 'c': + /* this can be specified multiple times */ + if(addCertFile(optarg, &certs)) { + ourRtn = 1; + goto errOut; + } + break; + case 'r': + /* this can be specified multiple times */ + if(addCertFile(optarg, &roots)) { + ourRtn = 1; + goto errOut; + } + break; + case 'p': + policy = policyStringToOid(optarg); + if(policy == NULL) { + ourRtn = 2; + goto errOut; + } + break; + case 'k': + ortn = SecKeychainOpen(optarg, &kcRef); + if(ortn) { + cssmPerror("SecKeychainOpen", ortn); + ourRtn = 1; + goto errOut; + } + /* this can be specified multiple times */ + if(keychains == NULL) { + keychains = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + } + CFArrayAppendValue(keychains, kcRef); + CFRelease(kcRef); + break; + case 'L': + actionFlags &= ~CSSM_TP_ACTION_FETCH_CERT_FROM_NET; + forceActionFlags = true; + break; + case 'l': + actionFlags |= CSSM_TP_ACTION_LEAF_IS_CA; + break; + case 'n': + /* No keychains, signalled by empty keychain array */ + if(keychains != NULL) { + fprintf(stderr, "-k and -n are mutually exclusive\n"); + ourRtn = 2; + goto errOut; + } + keychains = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + break; + case 'e': + emailAddrs = optarg; + break; + case 's': + sslHost = optarg; + break; + case 'q': + quiet = true; + break; + default: + ourRtn = 2; + goto errOut; + } + } + if(optind != argc) { + ourRtn = 2; + goto errOut; + } + + if(certs == NULL) { + if(roots == NULL) { + fprintf(stderr, "***No certs specified.\n"); + ourRtn = 2; + goto errOut; + } + if(CFArrayGetCount(roots) != 1) { + fprintf(stderr, "***Multiple roots and no certs not allowed.\n"); + ourRtn = 2; + goto errOut; + } + + /* no certs and one root: verify the root */ + certs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(certs, CFArrayGetValueAtIndex(roots, 0)); + actionFlags |= CSSM_TP_ACTION_LEAF_IS_CA; + } + + /* cook up a SecPolicyRef */ + ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3, + policy, + NULL, // policy opts + &searchRef); + if(ortn) { + cssmPerror("SecPolicySearchCreate", ortn); + ourRtn = 1; + goto errOut; + } + ortn = SecPolicySearchCopyNext(searchRef, &policyRef); + if(ortn) { + cssmPerror("SecPolicySearchCopyNext", ortn); + ourRtn = 1; + goto errOut; + } + + /* per-policy options */ + if(compareOids(policy, &CSSMOID_APPLE_TP_SSL) || compareOids(policy, &CSSMOID_APPLE_TP_APPLEID_SHARING)) { + if(sslHost != NULL) { + memset(&sslOpts, 0, sizeof(sslOpts)); + sslOpts.Version = CSSM_APPLE_TP_SSL_OPTS_VERSION; + sslOpts.ServerName = sslHost; + sslOpts.ServerNameLen = strlen(sslHost); + optionData.Data = (uint8 *)&sslOpts; + optionData.Length = sizeof(sslOpts); + ortn = SecPolicySetValue(policyRef, &optionData); + if(ortn) { + cssmPerror("SecPolicySetValue", ortn); + ourRtn = 1; + goto errOut; + } + } + } + if(compareOids(policy, &CSSMOID_APPLE_TP_SMIME)) { + if(emailAddrs != NULL) { + memset(&smimeOpts, 0, sizeof(smimeOpts)); + smimeOpts.Version = CSSM_APPLE_TP_SMIME_OPTS_VERSION; + smimeOpts.SenderEmail = emailAddrs; + smimeOpts.SenderEmailLen = strlen(emailAddrs); + optionData.Data = (uint8 *)&smimeOpts; + optionData.Length = sizeof(smimeOpts); + ortn = SecPolicySetValue(policyRef, &optionData); + if(ortn) { + cssmPerror("SecPolicySetValue", ortn); + ourRtn = 1; + goto errOut; + } + } + } + + /* Now create a SecTrustRef and set its options */ + ortn = SecTrustCreateWithCertificates(certs, policyRef, &trustRef); + if(ortn) { + cssmPerror("SecTrustCreateWithCertificates", ortn); + ourRtn = 1; + goto errOut; + } + + /* roots (anchors) are optional */ + if(roots != NULL) { + ortn = SecTrustSetAnchorCertificates(trustRef, roots); + if(ortn) { + cssmPerror("SecTrustSetAnchorCertificates", ortn); + ourRtn = 1; + goto errOut; + } + } + if(actionFlags || forceActionFlags) { + memset(&actionData, 0, sizeof(actionData)); + actionData.Version = CSSM_APPLE_TP_ACTION_VERSION; + actionData.ActionFlags = actionFlags; + cfActionData = CFDataCreate(NULL, (UInt8 *)&actionData, sizeof(actionData)); + ortn = SecTrustSetParameters(trustRef, CSSM_TP_ACTION_DEFAULT, cfActionData); + if(ortn) { + cssmPerror("SecTrustSetParameters", ortn); + ourRtn = 1; + goto errOut; + } + } + if(keychains) { + ortn = SecTrustSetKeychains(trustRef, keychains); + if(ortn) { + cssmPerror("SecTrustSetKeychains", ortn); + ourRtn = 1; + goto errOut; + } + } + + /* GO */ + ortn = SecTrustEvaluate(trustRef, &resultType); + if(ortn) { + /* should never fail - error on this doesn't mean the cert verified badly */ + cssmPerror("SecTrustEvaluate", ortn); + ourRtn = 1; + goto errOut; + } + switch(resultType) { + case kSecTrustResultUnspecified: + /* cert chain valid, no special UserTrust assignments */ + case kSecTrustResultProceed: + /* cert chain valid AND user explicitly trusts this */ + break; + case kSecTrustResultDeny: + if(!quiet) { + fprintf(stderr, "SecTrustEvaluate result: kSecTrustResultDeny\n"); + } + ourRtn = 1; + break; + case kSecTrustResultConfirm: + /* + * Cert chain may well have verified OK, but user has flagged + * one of these certs as untrustable. + */ + if(!quiet) { + fprintf(stderr, "SecTrustEvaluate result: kSecTrustResultConfirm\n"); + } + ourRtn = 1; + break; + default: + ourRtn = 1; + if(!quiet) { + /* See what the TP had to say about this */ + ortn = SecTrustGetCssmResultCode(trustRef, &ocrtn); + if(ortn) { + cssmPerror("SecTrustGetCssmResultCode", ortn); + } + else { + cssmPerror("Cert Verify Result", ocrtn); + } + } + break; + } + + if((ourRtn == 0) & !quiet) { + printf("...certificate verification successful.\n"); + } +errOut: + /* cleanup */ + CFRELEASE(certs); + CFRELEASE(roots); + CFRELEASE(keychains); + CFRELEASE(policyRef); + CFRELEASE(trustRef); + CFRELEASE(searchRef); + CFRELEASE(cfActionData); + return ourRtn; +} diff --git a/SecurityTool/verify_cert.h b/SecurityTool/verify_cert.h new file mode 100644 index 00000000..89940831 --- /dev/null +++ b/SecurityTool/verify_cert.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2006,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + * + * verify_cert.h + */ + +#ifndef _VERIFY_CERT_H_ +#define _VERIFY_CERT_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +extern int verify_cert(int argc, char * const *argv); + +#ifdef __cplusplus +} +#endif + +#endif /* _VERIFY_CERT_H_ */ diff --git a/SharedWebCredentialViewService/Base.lproj/Main_iPad.storyboard b/SharedWebCredentialViewService/Base.lproj/Main_iPad.storyboard new file mode 100755 index 00000000..4edef30d --- /dev/null +++ b/SharedWebCredentialViewService/Base.lproj/Main_iPad.storyboard @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SharedWebCredentialViewService/Base.lproj/Main_iPhone.storyboard b/SharedWebCredentialViewService/Base.lproj/Main_iPhone.storyboard new file mode 100755 index 00000000..ce2c6585 --- /dev/null +++ b/SharedWebCredentialViewService/Base.lproj/Main_iPhone.storyboard @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SharedWebCredentialViewService/RemoteCFUserNotificationTest-Info.plist b/SharedWebCredentialViewService/RemoteCFUserNotificationTest-Info.plist new file mode 100755 index 00000000..066e41d1 --- /dev/null +++ b/SharedWebCredentialViewService/RemoteCFUserNotificationTest-Info.plist @@ -0,0 +1,56 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.apple.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + UIMainStoryboardFile + Main_iPhone + UIMainStoryboardFile~ipad + Main_iPad + UIRequiredDeviceCapabilities + + armv7 + + UIViewServiceUsesNSXPCConnection + + CanInheritApplicationStateFromOtherProcesses + + CAProcessCanAccessGPU + + SBMachServices + + com.apple.uikit.viewservice.com.apple.RemoteCFUserNotificationT + + SBMatchingApplicationGenres + + Games + Entertainment + Lifestyle + + SBAppTags + + hidden + + + diff --git a/SharedWebCredentialViewService/RemoteCFUserNotificationTest-Prefix.pch b/SharedWebCredentialViewService/RemoteCFUserNotificationTest-Prefix.pch new file mode 100755 index 00000000..3fdee9d3 --- /dev/null +++ b/SharedWebCredentialViewService/RemoteCFUserNotificationTest-Prefix.pch @@ -0,0 +1,10 @@ +// +// Prefix header +// +// The contents of this file are implicitly included at the beginning of every source file. +// + +#ifdef __OBJC__ + #import + #import +#endif diff --git a/SharedWebCredentialViewService/SWCAppDelegate.h b/SharedWebCredentialViewService/SWCAppDelegate.h new file mode 100755 index 00000000..3085c422 --- /dev/null +++ b/SharedWebCredentialViewService/SWCAppDelegate.h @@ -0,0 +1,14 @@ +// +// SWCAppDelegate.h +// SharedWebCredentialViewService +// +// Copyright (c) 2014 Apple Inc. All Rights Reserved. +// + +#import + +@interface SWCAppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + +@end diff --git a/SharedWebCredentialViewService/SWCAppDelegate.m b/SharedWebCredentialViewService/SWCAppDelegate.m new file mode 100755 index 00000000..d8108038 --- /dev/null +++ b/SharedWebCredentialViewService/SWCAppDelegate.m @@ -0,0 +1,48 @@ +// +// SWCAppDelegate.m +// SharedWebCredentialViewService +// +// Copyright (c) 2014 Apple Inc. All Rights Reserved. +// + +#import "SWCAppDelegate.h" + +@implementation SWCAppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ +// self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + // Override point for customization after application launch. +// self.window.backgroundColor = [UIColor whiteColor]; +// [self.window makeKeyAndVisible]; + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application +{ + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application +{ + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application +{ + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/SharedWebCredentialViewService/SWCViewController.h b/SharedWebCredentialViewService/SWCViewController.h new file mode 100755 index 00000000..3ac3843e --- /dev/null +++ b/SharedWebCredentialViewService/SWCViewController.h @@ -0,0 +1,13 @@ +// +// SWCViewController.h +// SharedWebCredentialViewService +// +// Copyright (c) 2014 Apple Inc. All Rights Reserved. +// + +#import +#import + +@interface SWCViewController : SBSUIRemoteAlertItemContentViewController + +@end diff --git a/SharedWebCredentialViewService/SWCViewController.m b/SharedWebCredentialViewService/SWCViewController.m new file mode 100755 index 00000000..87c85b42 --- /dev/null +++ b/SharedWebCredentialViewService/SWCViewController.m @@ -0,0 +1,428 @@ +// +// SWCViewController.m +// SharedWebCredentialViewService +// +// Copyright (c) 2014 Apple Inc. All Rights Reserved. +// + +#import "SWCViewController.h" +#import +#import + +#import +#import + +#include +#include +#include "SharedWebCredential/swcagent_client.h" + +const NSString* SWC_PASSWORD_KEY = @"spwd"; +const NSString* SWC_ACCOUNT_KEY = @"acct"; +const NSString* SWC_SERVER_KEY = @"srvr"; + +// +// SWCDictionaryAdditions +// + +@interface NSDictionary (SWCDictionaryAdditions) +- (NSComparisonResult) compareCredentialDictionaryAscending:(NSDictionary *)other; +@end + +@implementation NSDictionary (SWCDictionaryAdditions) +- (NSComparisonResult)compareCredentialDictionaryAscending:(NSDictionary *)other +{ + NSComparisonResult result; + NSString *str1 = [self objectForKey:SWC_ACCOUNT_KEY], *str2 = [other objectForKey:SWC_ACCOUNT_KEY]; + if (!str1) str1 = @""; + if (!str2) str2 = @""; + + // primary sort by account name + result = [str1 localizedCaseInsensitiveCompare:str2]; + if (result == NSOrderedSame) { + // secondary sort by domain name + NSString *str3 = [self objectForKey:SWC_SERVER_KEY], *str4 = [other objectForKey:SWC_SERVER_KEY]; + if (!str3) str3 = @""; + if (!str4) str4 = @""; + + result = [str3 localizedCaseInsensitiveCompare:str4]; + } + + return result; +} +@end + + +// +// SWCItemCell +// +@interface SWCItemCell : UITableViewCell +{ + NSDictionary *_dict; + BOOL _isTicked; + UIView *_bottomLine; + UIView *_bottomLineSelected; + UIView *_topLine; + UIView *_topLineSelected; + BOOL _showSeparator; + BOOL _showTopSeparator; +} + +- (id)initWithDictionary:(NSDictionary *)dict; +@property (nonatomic, readonly) id userInfo; +@property (nonatomic, assign) BOOL showSeparator; +@end + +@implementation SWCItemCell + +@synthesize showSeparator = _showSeparator; + +- (id)initWithDictionary:(NSDictionary *)dict +{ + if ((self = [super initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:nil])) + { + _dict = dict; + + self.selectionStyle = UITableViewCellSelectionStyleNone; + + self.backgroundColor = [UIColor colorWithWhite:0.1 alpha:0.005]; + + self.textLabel.textColor = [UIColor blackColor]; + self.textLabel.textAlignment = NSTextAlignmentLeft; + self.textLabel.AdjustsFontSizeToFitWidth = YES; + self.textLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; + + NSString *title = [dict objectForKey:SWC_ACCOUNT_KEY]; + self.textLabel.text = title ? title : @"--"; + + self.detailTextLabel.textColor = [UIColor darkGrayColor]; + self.detailTextLabel.textAlignment = NSTextAlignmentLeft; + self.detailTextLabel.AdjustsFontSizeToFitWidth = YES; + self.detailTextLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; + + NSString *subtitle = [dict objectForKey:SWC_SERVER_KEY]; + self.detailTextLabel.text = subtitle ? subtitle : @"--"; + + self.backgroundView = [[UIView alloc] init]; + self.backgroundView.backgroundColor = self.backgroundColor; + + self.imageView.image = [self _checkmarkImage: NO]; + self.imageView.hidden = YES; + + } + + return self; +} + +- (void)setTicked: (BOOL) selected +{ + _isTicked = selected; +} + +- (void)layoutSubviews +{ + + if (_bottomLine) { + CGFloat scale = [[UIScreen mainScreen] scale]; + [_bottomLine setFrame:CGRectMake(0, self.frame.size.height - (1 / scale), self.frame.size.width, 1 / scale)]; + } + + if (_bottomLineSelected) { + CGFloat scale = [[UIScreen mainScreen] scale]; + [_bottomLineSelected setFrame:CGRectMake(0, self.frame.size.height - (1 / scale), self.frame.size.width, 1 / scale)]; + } + + if (_topLine) { + CGFloat scale = [[UIScreen mainScreen] scale]; + [_topLine setFrame:CGRectMake(0, 0, self.frame.size.width, 1 / scale)]; + } + + if (_topLineSelected) { + CGFloat scale = [[UIScreen mainScreen] scale]; + [_topLineSelected setFrame:CGRectMake(0, 0, self.frame.size.width, 1 / scale)]; + } + + if (_isTicked) + { + self.imageView.hidden = NO; + } else { + self.imageView.hidden = YES; + } + + [super layoutSubviews]; + +} + +- (void)setShowSeparator:(BOOL)showSeparator { + if (_showSeparator != showSeparator) { + _showSeparator = showSeparator; + + if (_showSeparator) { + if (!_bottomLine) { + CGRect rectZero = CGRectMake(0, 0, 0, 0); + _bottomLine = [[UIView alloc] initWithFrame:rectZero]; + _bottomLine.backgroundColor = [UIColor colorWithWhite:.5 alpha:.5]; + [self.backgroundView addSubview:_bottomLine]; + } + if (!_bottomLineSelected) { + CGRect rectZero = CGRectMake(0, 0, 0, 0); + _bottomLineSelected = [[UIView alloc] initWithFrame:rectZero]; + _bottomLineSelected.backgroundColor = [UIColor colorWithWhite:.5 alpha:.5]; + [self.selectedBackgroundView addSubview: _bottomLineSelected]; + } + + } else { + if (_bottomLine) { + [_bottomLine removeFromSuperview]; + _bottomLine = nil; + } + if (_bottomLineSelected) { + [_bottomLineSelected removeFromSuperview]; + _bottomLineSelected = nil; + } + } + } +} + +- (void)setShowTopSeparator:(BOOL)showTopSeparator { + if (_showTopSeparator != showTopSeparator) { + _showTopSeparator = showTopSeparator; + + if (_showTopSeparator) { + if (!_topLine) { + CGRect rectZero = CGRectMake(0, 0, 0, 0); + _topLine = [[UIView alloc] initWithFrame:rectZero]; + _topLine.backgroundColor = [UIColor colorWithWhite:.5 alpha:.5]; + [self.backgroundView addSubview:_topLine]; + } + if (!_topLineSelected) { + CGRect rectZero = CGRectMake(0, 0, 0, 0); + _topLineSelected = [[UIView alloc] initWithFrame:rectZero]; + _topLineSelected.backgroundColor = [UIColor colorWithWhite:.5 alpha:.5]; + [self.selectedBackgroundView addSubview: _topLineSelected]; + } + + } else { + if (_topLine) { + [_topLine removeFromSuperview]; + _topLine = nil; + } + if (_topLineSelected) { + [_topLineSelected removeFromSuperview]; + _topLineSelected = nil; + } + } + } +} + +@end + + +// +// SWCViewController +// + +@interface SWCViewController () +{ + NSMutableArray *_credentials; // array of NSDictionary + UILabel *_topLabel; + UILabel *_middleLabel; + UITableView *_table; + NSDictionary *_selectedDict; + NSIndexPath *_selectedCell; +} + +@end + +@implementation SWCViewController + +- (NSDictionary *)selectedItem +{ + return _selectedDict; +} + +- (void)setCredentials:(NSArray *)inArray +{ + NSMutableArray *credentials = [[NSMutableArray alloc] initWithArray:inArray]; + [credentials sortUsingSelector:@selector(compareCredentialDictionaryAscending:)]; + _credentials = credentials; + if (_table) + [_table reloadData]; +} + +- (void)_enableTable +{ + [_table setUserInteractionEnabled:YES]; +} + +- (UITableView *)tableView +{ + if (_table == nil) { + _table = [[UITableView alloc] init]; + [_table setTranslatesAutoresizingMaskIntoConstraints:NO]; + [_table setAutoresizingMask:UIViewAutoresizingNone]; + [_table setBackgroundColor:[UIColor clearColor]]; + [_table setSeparatorStyle:UITableViewCellSeparatorStyleNone]; + } + [_table sizeToFit]; + + return (UITableView *)_table; +} + +-(void)loadView +{ + + UIView* view = [[UIView alloc] init]; + + UITableView* table = [self tableView]; + [table setDelegate: self]; + [table setDataSource: self]; + + [view addSubview: table]; + + CFErrorRef error = NULL; + audit_token_t auditToken = {}; + memset(&auditToken, 0, sizeof(auditToken)); + CFArrayRef credentialList = swca_copy_pairs(swca_copy_pairs_request_id, &auditToken, &error); + if (error) { + NSLog(@"Unable to get accounts: %@", [(__bridge NSError*)error localizedDescription]); + } + + [self setCredentials:(__bridge NSArray*)credentialList]; + if (credentialList) { + CFRelease(credentialList); + } + + + NSDictionary* views = NSDictionaryOfVariableBindings(table); + + if ([_credentials count] > 2) + { + + NSDictionary *metrics = @{@"height":@120.0}; + [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[table]-|" options:0 metrics:metrics views:views]]; + [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[table(height)]-|" options:0 metrics:metrics views:views]]; + + CGFloat scale = [[UIScreen mainScreen] scale]; + table.layer.borderWidth = 1.0 / scale; + table.layer.borderColor = [UIColor colorWithWhite:.5 alpha:.5].CGColor; + + [self setPreferredContentSize:CGSizeMake(0,140)]; + + } else if ([_credentials count] == 2) { + + NSDictionary *metrics = @{@"height":@90.0}; + [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[table]|" options:0 metrics:metrics views:views]]; + [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[table(height)]-|" options:0 metrics:metrics views:views]]; + + [self setPreferredContentSize:CGSizeMake(0,90)]; + [table setScrollEnabled: NO]; + + } else { // [_credentials count] == 1 + + NSDictionary *metrics = @{@"height":@45.0}; + [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[table]|" options:0 metrics:metrics views:views]]; + [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[table(height)]|" options:0 metrics:metrics views:views]]; + + [self setPreferredContentSize:CGSizeMake(0,45)]; + [table setScrollEnabled: NO]; + + } + + [self setView:view]; +} + +-(void)viewWillAppear:(BOOL)animated +{ + + // Select the first cell by default + + NSDictionary *dict = [_credentials objectAtIndex: 0]; + _selectedDict = dict; + _selectedCell = [NSIndexPath indexPathForItem:0 inSection: 0]; + SWCItemCell *cell = (SWCItemCell *)[_table cellForRowAtIndexPath: _selectedCell]; + [cell setTicked: YES]; + [_table selectRowAtIndexPath: _selectedCell animated: NO scrollPosition: UITableViewScrollPositionTop]; + + CFErrorRef error = NULL; + audit_token_t auditToken = {}; + memset(&auditToken, 0, sizeof(auditToken)); + bool result = swca_set_selection(swca_set_selection_request_id, + &auditToken, (__bridge CFDictionaryRef)dict, &error); + if (!result) { + NSLog(@"Unable to select item: %@", [(__bridge NSError*)error localizedDescription]); + } + + [super viewWillAppear:animated]; +} + + +// +// UITableView delegate methods +// + +- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section +{ + return [_credentials count]; +} + +- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + NSUInteger row = indexPath.row; + + NSDictionary *dict = [_credentials objectAtIndex:row]; + _selectedDict = dict; + + CFErrorRef error = NULL; + audit_token_t auditToken = {}; + memset(&auditToken, 0, sizeof(auditToken)); + bool result = swca_set_selection(swca_set_selection_request_id, + &auditToken, (__bridge CFDictionaryRef)dict, &error); + if (!result) { + NSLog(@"Unable to select item: %@", [(__bridge NSError*)error localizedDescription]); + } + + _selectedCell = indexPath; + SWCItemCell *cell = (SWCItemCell *)[tableView cellForRowAtIndexPath: indexPath]; + [cell setTicked: YES]; + [cell layoutSubviews]; +} + +- (void) tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath +{ + SWCItemCell *cell = (SWCItemCell *)[tableView cellForRowAtIndexPath: indexPath]; + [cell setTicked: NO]; + [cell layoutSubviews]; + +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + + NSDictionary *dict = [_credentials objectAtIndex:[indexPath row]]; + SWCItemCell *cell = [[SWCItemCell alloc] initWithDictionary:dict]; + + // show separator on top cell if there's only or or two items + if ([_credentials count] <= 2) { + cell.showTopSeparator = YES; + } else { + cell.showSeparator = YES; + + if (indexPath.row == 0) + { + cell.showTopSeparator = YES; + } + + } + + if (_selectedCell == indexPath) + { + [cell setTicked: YES]; + } else { + [cell setTicked: NO]; + } + + return cell; +} + + +@end diff --git a/SharedWebCredentialViewService/SharedWebCredentialViewService-Info.plist b/SharedWebCredentialViewService/SharedWebCredentialViewService-Info.plist new file mode 100644 index 00000000..ab683e75 --- /dev/null +++ b/SharedWebCredentialViewService/SharedWebCredentialViewService-Info.plist @@ -0,0 +1,55 @@ + + + + + CAProcessCanAccessGPU + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.apple.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + CanInheritApplicationStateFromOtherProcesses + + LSRequiresIPhoneOS + + SBAppTags + + hidden + + SBMachServices + + com.apple.uikit.viewservice.com.apple.SharedWebCredentialViewSe + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewServiceUsesNSXPCConnection + + + diff --git a/SharedWebCredentialViewService/SharedWebCredentialViewService-Prefix.pch b/SharedWebCredentialViewService/SharedWebCredentialViewService-Prefix.pch new file mode 100644 index 00000000..3fdee9d3 --- /dev/null +++ b/SharedWebCredentialViewService/SharedWebCredentialViewService-Prefix.pch @@ -0,0 +1,10 @@ +// +// Prefix header +// +// The contents of this file are implicitly included at the beginning of every source file. +// + +#ifdef __OBJC__ + #import + #import +#endif diff --git a/SharedWebCredentialViewService/en.lproj/InfoPlist.strings b/SharedWebCredentialViewService/en.lproj/InfoPlist.strings new file mode 100755 index 00000000..477b28ff --- /dev/null +++ b/SharedWebCredentialViewService/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/SharedWebCredentialViewService/entitlements.plist b/SharedWebCredentialViewService/entitlements.plist new file mode 100755 index 00000000..ef81b9b7 --- /dev/null +++ b/SharedWebCredentialViewService/entitlements.plist @@ -0,0 +1,10 @@ + + + + + com.apple.UIKit.vends-view-services + + com.apple.private.associated-domains + + + diff --git a/SharedWebCredentialViewService/main.m b/SharedWebCredentialViewService/main.m new file mode 100755 index 00000000..da9e97d3 --- /dev/null +++ b/SharedWebCredentialViewService/main.m @@ -0,0 +1,17 @@ +// +// main.m +// SharedWebCredentialViewService +// +// Copyright (c) 2014 Apple Inc. All Rights Reserved. +// + +#import + +#import "SWCAppDelegate.h" + +int main(int argc, char * argv[]) +{ + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([SWCAppDelegate class])); + } +} diff --git a/SyncTest/KCATableViewController.xib b/SyncTest/KCATableViewController.xib new file mode 100644 index 00000000..d6764755 --- /dev/null +++ b/SyncTest/KCATableViewController.xib @@ -0,0 +1,160 @@ + + + + 1536 + 12A269 + 2835 + 1187 + 624.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 1919 + + + IBProxyObject + IBUITableView + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + PluginDependencyRecalculationVersion + + + + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 274 + {{0, 20}, {320, 548}} + + + + + 3 + MQA + + NO + YES + NO + + + IBUIScreenMetrics + + YES + + + + + + {320, 568} + {568, 320} + + + IBCocoaTouchFramework + Retina 4 Full Screen + 2 + + IBCocoaTouchFramework + NO + 1 + 0 + YES + 44 + 22 + 22 + + + + + + + view + + + + 5 + + + + dataSource + + + + 6 + + + + delegate + + + + 7 + + + + + + 0 + + + + + + -1 + + + File's Owner + + + -2 + + + + + 4 + + + + + + + KCATableViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + + + 7 + + + + + KCATableViewController + UITableViewController + + IBProjectSource + ./Classes/KCATableViewController.h + + + + + 0 + IBCocoaTouchFramework + YES + 3 + YES + 1919 + + diff --git a/SyncTest/spiralsink114.png b/SyncTest/spiralsink114.png new file mode 100644 index 0000000000000000000000000000000000000000..d69b283a1396dcfb3ea4e04cfe543013db7c12a2 GIT binary patch literal 24752 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 z z%59s{qc$tR@nt4QRv)#4qm_1emYsD@O5k2K7Ps3VhzL;nGKq6wLBdgu2Z& z!hH{;PWQtuFgY%6S&c!dv<%^!mT{ogry!vrmaBWEO^U%(+NDmE9t)gUVVld^6QWRl z^BD`Yi%?)ulHi1wLK`-~OD4O6Q7*>{p*4NKGWb4%RKpZS7$Q-F`;=c27?DybS6de8 zxF$&@$RU5L4A>|P5pt;FMkyKO9O`2x$9=7}Q(nFy*%voh&c0d~s}(B@k3J9SJgFaX zj5SbJ_%cc*)ctOPdlQI#(qq6CnbtyHDE_uT^%Puj@i(y@PmQ>Oy__{wAL(EO0lIBYP*=cf=d4 zt-qeJqR}dr3QzK5a#YlgRg&o_9q~l8BIpI~*zbP-`}`_yh2{1kHkE!af-P+)g~DZR zu|BUUnrj7H@J#4e)~I~aBvkh)^W1HAh8dn0h4_SN`-RBq0k)` z_>&cJncSDxC<}B6EDT1W6s8ffv{_a~D4URO5Z3~E!^sr0G4qowolW5}NcW{;;wYco zi)7gerVmxLHSRSqWjzhAkYUmkqQZ_hAwXLK#v zx+Prl{mbEX?o%<>l~Hia>qoAJy6H>QXc>|ASqmg!as1^ppD%Q<4XxEaG<_!kWM8>0 zCKnL4TRgNDhb6ip!~0H;ZA-Aza?19K>t+!q(c#`eZSThM|?F zB^J)sry&HO3${%y5O*k_aHFUy89dOl{IE?Uz`X=9yM3h@c(@jVpGbY-%a`43@Mwg=h3h z6cI+J4}<7_=$;+#s+=;)epjJ&SE=B?{83>2)APP~Z@xk^j4^o^osB`~fTU748kM!O zEx8F#bp;Thgi?Tp(Wc)2!If=gpjMY;VCNpDO8gM&M$p}8a${3fT7q)DBRvYjy=q0P zA{ZfU#HCrhm~6QSQ9%gD{zSOSnY0>&bBiz(TnUZyAh-xM0u*L3Q%KcM)_uUzPAM&x zxkf+DvebSC^7GRUgNQ0|jE@7eJlGT#8;*iX7O;Um-jz%=gEvDQI!V#R& zPvu*_Dp)J5ty6#$B&%23Lka8bIJ)+m)UQ47yw>st(M7<$deVjGKV=eJaNpAd$GQp) z#_MegF1Q5`h2Jf(Xw(Wl99oQ)AGKM=f%}-qo}Klv1SY>(qa06HQ0t@Pz@7kx#$xA` zz=pG<0rh%4$_8$DRwoxmxY}hH@{o1Nd%VDSfgo>eoISP9<$|BDPxH`oZYW&v&O6N& z28IaUVpzUk?#IQZii|F|spbGnu8^issS_z!qppP#6ByDd%zdRM>+ktWE?-+rw2X{Q z+K|qD7gj7Na7Y3FvUaX1^M&gOsmcg1f0m(6glHNcty4S;OWHMmXiYEVTA;Lt`nAP2 z#$4#0&6P}M&(cR3y+6gZZotTyT})nBC+=~8AEt#vf#HP73hl0~FkwLlDQvx)fy_gK zn7a!^<@AA|L0rJpCKn0(5b}t=xQ`UHH_$|o`g{NS4^5C5&xw%Mxv&9`VsLk*TAOv` zGuK0zlqF5Ta-;-X_a^=44lN~hg(G8Aknj2zRMOIy4~bm}WnubFt5Ww%0_y#oxON(P z-8$1ZLZ|%DavZP=jN)8rG0f=(0r-TqZ88_St1Y$zlT5NRF}0yUbcdNCqK`A^!L%Ib z6;6sC#w#d3dIEsJ=s>Ix zWPS&b@&kr)z~fTrnUIZPaBgaKu#F zp0TC2j{s&Grmi9UCvu+$X&tD$J;miNXIyl>*a6I@4d^z2%a6A~*I1%kqHxlk0B5DF z-Nsek<;QCtvxQ`A6Bj+fER}K-j)sEZjkZhK#jOlVI>bBf*htHU)a*!@22w$K_^6+r zBauNE!ID&}kR09Px`f$H-pufXs-8Uxj*P62IbLs-NP5pqY4R;#xt*V?Q*d_Vf2o|n zx7=(&8Q@sINGjxD4A^xGOe9JqNEq72aijBC;2eYaS%y2~r2A~Y3r`yvHk75wY~AY! z2?l5G?dx1}@_A2Ev-hZkp+PkIK;8n)KA{K8EKb8{tuPZT;AU5+#fq1_??GD0M&2l| z!O|V}+-Fwb$!+IDgMgK+D}dpMfUVjsMS%|4Wsx#d(6sJ2upde0Yfu2)Ug{xq3CsT= zAgh>W8MT@JO34N3Tj!MeQeD%A`W;?X2u%fxeB0;fidr|MqyFp+jq4jz^I6OtF%LR7 z!JZhR&{?=DRZDEpQf=K9GD*xZ4L{Zq-iAsHXjzi8{i(i=_T0N8@-A^{=}v$z(D&U( zfOi?sI_#e&3Z0?>->I$)++?QRA)f+DDcy1!Ajz|alQen8-)M!YsmG5ucynUCn;hdW zb)cf`4$G<3kH|zp&|m~C<{Wh|ncHQf7|E@#t$X27Ehqqoe-6+6db@nVt@f&X_37L7 zd)+VA8Sb`V>!SQbsUTv&I@n5wuFL*!nxB@K8)rKO7C7ll45%&`v{1ov#G&*@3eLRB zH&D_#Cb^eu%gprXqOETqDAS!!eY{{0v&euR7wXHK7z+w`ZQW-?*J+zYLXcO(9Kgy4$oV9tF!2j8v* zI<+=|``nEMx&pC#hNu&!YQ3w=v_|=H#)TvLHZ3F*A=H&eIvLi&$gJMSE}lP`$QTdN0l}Ocy7y{3#GsKp4)kjBn8Yu_tuImcl)3Dcoxi z!xW(WaQ!jv68eo6#}QHlNISM?&?O(>Yh0}exGO;Cl%+BRZ;=NG@Fo`ci1FaMvp95L zc{4KRTIBN0zcGr3aOHI!%0;D1qkP*Q_)wrc0OCnuy$Q;5Xnt3_dFLL>W$x?5XOrn_ zyCM{@QumO6vbfyl%Qk7I@=PH?rh0_Ib&)cbth_4VwPm&{h!pohJoQq;t16Pb%IJMv z-TCby{K7HbBw8#L1;?fgV#al2Sl~3XFuQr5oGx@48WsLBeV}MmNG~~JLw6y{e#i`8 zECjIH1m#P0-SEtODT<>@buRRlE|j5!xQr&<`bi#E?y$kYHI!1e<1C(9oA;KDXN-GQ zA-i=#AMNS^l!Y`EmI$)3#b6g}C5vuh085vS6tO>sqF~nTc;$c^;mO2M<#i!aSKHq< zAVO(Jl!yB&v6VW2srxFdb`AGmhAoT~%EfTK-M$RdmC1naMnkA(!ZGgnYt4ylEs&K6 zx+f>H1?jNCo>$)~t&tOz>n9s10?DQ+*eD6`T#2yC4CQ6Cs}c{H(Yf_d7s{?V+_Nq; zu=sK)5?@STjJSel@zhPvz!jK6z6n(luHV2YitOTtp*|k5l_I) znTe2m=C_+XrYZ(zKB*m=|th)U>IFl#XFXX3! zr6AV4w5;H;23;UDXfqp(#VU_}1i?+LFSDKEX`5xJG{bfZ`#XtR!a6MHAl^X3wz6J| zB+6u!F> zB-0ff64DlwrR&%ncibpVK_l1V7YbDz6q8Dkhk^$cvX}>Szlcu-FAWppuJze=-*TZa zgO^`4=@DLYZvz>x^;9y<^II5OcU#xiF*#zl00#;6zjfV{bFNg{sXOCCU64~z9+5D1B2|JVaFLG4jSFXc zWQgg)j+li(ne@fXy$+y)Z@p)Sq6V{bhT9B+7bS}Dc**rH^VFOH8Q=s#fq2+}4Vmu& zj(+FgD~}}ATe38HjV*L z9JF4KSaYrsI)H`Ud1RzqEs@GzGgh$?DXZj*>)0xdX!g($_vNccL_mN$kA5p)p_eeK zT=J4(4eJ#GoWdl~-cIXzW_qMdwdF!mvCElLbC#q-W`dqMJ8g7w=)0p*44*vgn)q zWP(@Bhx2F*>szxU25FfxiDt~PE#DuIb~QRr7&8|*>E@Av{4O{N^+UBVUEp4Nl%{ZJ zq~LvWdT!lYW~*FE4PRFCkGcjQ5}kME*$@noL?Ml{18s~6jcMGcyV3Tsono5M-}y}( zD*}XQ7HnsHnS%^L2`U-{hBG+8$QY2T6@<~ntUC{%M?}CDEiG;khY<60Xp~? z6DThaC)WLp(t%S#*P!p+#LXBC%%i!FnE=dUrmRDIB-*1in8t<0N2b;{a0-4>bPGdi z$_PBk`SNn8zLgv~nGO*9J_D>CWEn8nZoN4J*Fq38Vk&K}@w;76F=L<;W=eEonJtEH zGSH_6fe-00#dd|SZac}XEoDCpc?vvT2{=4rIq43Q*|!)6I`iXP=q&ZJ&67I*ieD!8 zWCZ`}Y!n6fu`tpTH1RXVdbuphgF~Wf+r@QSkN@yZfz+I8@l6;$H!9;W{NkVO49ZXu zHar2&Xu}c$^b_tvFm7rF6CT479wN-;4Wlc#1L6wPwK>|Lb(kk$EC1y2ijakFs5Wds&H?9rGm!GMH}#LqigtzzZfiIJeu6 z7030_27kV5Jy20tXHQoVk`L0(u&$^ZTVNpXWcD3gs4MgaBnBViq3}Z|c$p9x^5t?C z_9&MMPls(<2D3dDHByzu;aN(R(6<#|xW+2|aNv)MQAeC=TT2;Am9nILC|wG^f8^q4 zVMuEnB3U?=o88UBBkM$G&K0h~X{U@b0SuFCeQ;YEfe^;;6tInx zAnMM>v^+Al_M{;Q96dV31}j|XJkMgfjO6aJ416IH&xi032F#LR^P+IT(Go~vj?}?A z&rs0zD$DFzrn4+l&^yPNc?@M(a5)JVdJiG4z(F@jrC*js5dz4{ACU)WjaR`V(lF9Q zp~8IXDp*{Do=(f@3Py62S!t_QG9k(VP`6mR562wSRW94nk^@i8*K^uF2dNaR@}nno z-ZO^aGO=<4Ct6L|J_B+(qsI`r&KvV}CQf0={6ti8$(lAs<0Yctk?VpfgDFO)?n2a) z4s#WrJK`j&cBEl30>M>AzY*RfpE*Q3Pd746yQoQY+AW7Zry)$c1Kpxb%S;FgXTL&n z?(Gq?x}X5bOJs?~`u_1J3_I>KjJV4S7FO5AsREqzX$ppRJRmQ)%gho^I;KqR`H)cc zyHKa~TUa7FYaA*w&2cO9O%q1(JpLj0x)sxYR%TIMp;6a`WV@Ce7!~h`9hFyiJm5G3I*G=de>=zvTK4NI%PO!Kp5VI(BX4|5cP)(^P!@)(;Ktl25 z;3R?yPlO{t($c4dU=XG3CbKZ31Tj3J%dWFIBtmvuC2%n~3t>>8Kt_y#qfge;wSuJt zP9Y@AxuMC}RONK?(Nzbv{0SCtTLH4$-9B=PsWj`z8Rt&*0&%18RqTT!82dh21-VLF z$RbLYE+Fn(`T`;fR1{X4!IZN_Wy#W03{v6T8(WVwz<2IrX((prnZmc8!<5K~w!~^3 z!H#%d#)lzb3|sdZGw$IDri@3FzV1)cCU26Eenh0U36YN=Q0=B#1Yr=6hzbU22@>HE zjgs!>Hg+ah={~N&T=9MvYQBRdi`nRy&0^=FqfAUXtWrjffjeFn*= zqJ|!lHW(w@Whh^jIee3cAToCL@C-N<6WxNhhv)lUS3|91MR5ZXLIqz$uz(^wTII$N zJQ`C$hDgW4bh#D|@gmAWnlGg_Tqld=M?;eX~qc|*k%i0Fxb_OXg>9#?RX!9 z2N^gvECh$y5kT=kazI1&53mhlNZ^oug`17k;JKnz^OvAUD+7)t#Y>IPi}$(bF1(2x zxD%Xh7$9jdx;+)iu50U%$9zng}~Tuz$maPHhmxFp=$3Nij0Y z6j9=2>H|9AAdvmLmpmDPKCoXB>u! znlG@|ZR$$xW7T}o5Nr)S5F&I6MR!S~8nU`VaO>?J z2$i@;xRmrq0CGTUpQ456K1c3^#-G{ATbmZZ1SsCKjc}7k&SnteUY<(Y+uFgkxB(eM`f|4`S3l@R9*qg8iZbF0p_D3g$3o32*U;f&2rW*m??0>u|)ermW-{ zLeVK0&^7^qGC7t;8!}I{ZCfF05i%jOK3;2yFdzX*v|Pc$P;mur`ayXLoT{U>QVqaS zJY1|^!hg$CAs?e|yPnVkODgJ?XJ6$L>%4smP;caB#2Mh_d}PwD$K(E`s} z*hl%Z2mR6P;4P&(3eq literal 0 HcmV?d00001 diff --git a/SyncTest/spiralsink57.png b/SyncTest/spiralsink57.png new file mode 100644 index 0000000000000000000000000000000000000000..ada42f210c65f4279fe750643c09d06dc9ee8f51 GIT binary patch literal 7978 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 literal 0 HcmV?d00001 diff --git a/TODO b/TODO new file mode 100644 index 00000000..419357de --- /dev/null +++ b/TODO @@ -0,0 +1,265 @@ +=== Advanced CFErrorRef usage === + +Make SecError a macro with an extra argument (formatOptions) and make the arguments proper CFStringRef +CFCopyDescription takes formatOptions as well, which it passes down to us. +Make sure we plumb though formatOptions everywhere +Have every cftype implement a proper copyDescriotion function that looks at a kSecDebugFormatOption key and use it to do debug printing. +Have the CFGiblis macros automatically implement copyDebugDescription function that calls + + +== Content Protection == + +* Notice that the system keystore is unavailible during upgrade and + fail without removing old keychain since it won't work after an + upgrade either. + +* cert table should be AlwaysAvailable + migratable... + +==== + +* security export - dump all classes and caches in unencrypted plist + genp, inet, cert, keys, ocsp, cair, crls. + security export genp, inet, cert, keys, ocsp, cair + +* security dh command should support decodePEM. + +== TESTCASES == + +SSL EKU: +Test ssl server and ssl client against certs with proper and wrong EKU. Also +test this for EV certs. +IPSEC EKU: +Add some ipsec certs with proper ipsec eku extensions and without them and +ensure that the ipsec policy rejects (done in si-20-sectrust) and accepts +each kind as it should. + +== AUDIT of securityd_server_request == + +in_args are a valid plist. + +sec_item_add_id + _SecItemAdd() argument 1 is a dictionary, but its contents have not been checked. +sec_item_copy_matching_id + _SecItemCopyMatching() argument 1 is a dictionary, but its contents have not been checked. +sec_item_delete_id + _SecItemDelete() argument 1 is a dictionary, but its contents have not been checked. +sec_item_update_id + _SecItemUpdate() argument 1 and 2 are dictionaries, but their contents have not been checked. +sec_trust_store_contains_id (ok) + SecTrustStoreForDomainName() argument 1 is a string of any length (might be 0). + SecTrustStoreContainsCertificateWithDigest() argument 1 might be NULL, argument 2 is a data of any length (might be 0). +sec_trust_store_set_trust_settings_id (ok) + SecCertificateCreateWithData() argument 2 is a data of any length (might be 0) (done) + _SecTrustStoreSetTrustSettings() argument 1 might be NULL, argument 3 is either NULL, a dictionary or an array, but its contents have not been checked. +sec_trust_store_remove_certificate_id (ok) + SecTrustStoreRemoveCertificateWithDigest() argument 2 is a data of any length (might be 0) an its bound to a statement in sqlite. +sec_delete_all_id (ok) + Audit done (args_in not used and its value is ignored). +sec_trust_evaluate_id + SecTrustServerEvaluateAsync() argument 1 is a dictionary, but its contents have not been checked. + The options field of each policy provided ends up in policy->_options unchecked, so every access + of policy->_options in SecPolicyServer.c needs to be sanitized. +sec_restore_keychain (ok) + Audit done (args_in not used and its value is ignored). + +== GENERAL == + +Function naming conventions: + - Use Sec@@@Finalaize only if the function does not free the thing it's finalizing. + - use Sec@@@Destroy otherwise. + +Move EVRoots.plist and system TrustStore.sqlite3 into perfect hashtable inside securityd. + +Stop using framework relative resources in securityd since it uses a few kb of ram just to get to them. + +Change the interfaces to securityd to use real argument lists and do all the encoding/decoding inside client.c and server.c. + +Remove SecCertificateCreate() now that iap submits a binary is fixed. + +SecKeyRawSign/SecKeyRawVerify should get better error codes. + +== OCSP == + +Consider calling int sqlite3_release_memory(int); (after committing outstanding transactions); when we are low on ram. + +change api to asynchttp.h to take 2 arguments, a boolean flag to use http GET is the URL size is less than 256 bytes, two dictionary arguments of header name,values pairs to add to the GET and POST requests. If only GET is present GET will always be used, if only POST is present only POST will be used. If both are present, we use GET only if the URL size is less than 256 bytes and POST otherwise. The callback should have a CFHTTPMessage() argument, which will go away when the callback returns. + +When receiving a stale response refetch by adding a Cache-Control: no-cache header. +Implement a timeout and retry count (perhaps after timeout go to next responder, but possibly retry responders again if they all timeout). +If id-pkix-ocsp-nocheck is not present in the responder cert, check revocation status of the responder cert itself (probably via crls, otherwise watch out for infinite recursion). + +Verify responder cert chain. (done) +Verify singleResponse validity at usage time. (done) +Verify signature of response. (done) +Verify responder id. (done) + +== SSL Policy == + +Check extended keyUsage and keyUsage of leaf. + +== Snowbird == + +Priority 2 + + Implement DSA using libGiants + Add support for DSA ciphersuites in SecureTransport + Implement DSS (DSA) Support for SecKeys + Add support for DSS (DSA) signed certificates + + Support CRL Fetching and caching + Support URL based certificate issuer fetching + + Suite B support for Blackberry feature parody + +== == + +* Trust settings dialog (P2 for P3) +* Trust settings ui (P2 for P3) + +=== Later === + +* SecItemDelete for identities should be server-side so it's done in an exclusive transaction + +* SecKeyRef for DH public/private keys (P3) +* AES support + - SecKey AES support? + + +Notes on TrustStore trustsettings db. + + // Version table has one record + CREATE TABLE version(version INTEGER); + CREATE TABLE cert{sha1 BLOB(20) UNIQUE PRIMARY KEY,subj BLOB,cert BLOB,mdat REAL); + CREATE INDEX isubj ON cert(subj); + CREATE TABLE trust(sha1 BLOB(20) UNIQUE PRIMARY KEY, + domain INTEGER, + policy BLOB, + application BLOB, + keyUsage INTEGER(4), + policyString TEXT, + allowedError INTEGER, + result INTEGER(1) + ) + + SELECT domain,policyString,allowedError,result FROM trust WHERE + (sha1=? OR sha1=defaut) AND + domain=? AND + (policy=? OR policy ISNULL) AND + (application=? OR application ISNULL) AND + (keyUsage&?) + ORDER BY COLLATE domain DESC; + + BEGIN EXCLUSIVE; + INSERT OR REPLACE INTO cert(sha1,subj,cert,mdat)VALUES(?,?,?,?); + DELETE FROM trust WHERE sha1=? AND domain=? + INSERT INTO trust(sha1,domain, + policy,application,keyUsage,policyString,allowedError,result) + VALUES(?,?,?,?,?,?,?,?); + +To adopt libdispatch in SecTrustServer.c, we should make a queue per builder. +That builders queue can then have +The chain builder will look something like + dispatch_async(queue, builder, SecPathBuilderNext); + inside SecPathBuilderNext we dispatch_async(queue, builder, state); + where state is whatever the new state to be run is. + where today we invoke the client callback and free the builder in + SecPathBuilderStep(), that will be replaced by doing it in the level + that today sets builder->state to NULL, which of course just doesn't + dispatch any new blocks since invoking the callback completes the API. + If we want to allow the caller to use dispatch himself (for sending + the reply on a reply queue of some kind that can reschedule jobs when + a port_notify_send_ok (or whatever it's called) is received. + If async io is done it uses a dispatch_source to run (or it can use a + plain cfrunloop callback if the callback are low latency). when the + async io operation has completed succesfully a callback is invoked, + this callback then pushes the new state onto the queue using + dispatch_async(queue, builder, builder->state); + so the new state runs after we return from the callback. + + IO can be on the global hi priority queue if it's truely async. + Since only one runnable job is ever posted on a queue at a time for a + given request, all of the job can be run on the high (dispatching new + requests) normal (request handeling) and low (signature + verification). + priority global queues as we see fit. + If multiple requests where received, they would end up being + executed round robin on a single core, or in parallel on multi core + machines, since each request would get queued by the dispatcher as they + arrived, and then jobs for the queues would add their next job to the end + of the queue behind the other one again. + + During parts of the code where we write to a databsse or read from a + database both of which could potentially block, we need to see if + sqlite3 has async APIs otherwise we might end up having to serialize all + db accesses to a single serial queue, which stops us from taking advantage + of the multiple reader / single writer paradigm. We just might have to + create a sqlite3 io thread or threads. + +#if 0 +/* Idea sketch for state_engine to replace SecPathBuilderStep() one. */ + +/* State engine api */ +typedef struct state_engine_s state_engine_t; +typedef void(*state_engine_function_t)(void *); +#ifdef __BLOCKS__ +typedef void(^state_engine_block_t)(void); +void state_engine_init(state_engine_t *engine, state_engine_block_t completed); +void state_engine_next(state_engine_t *engine, state_engine_block_t state); +#endif +void state_engine_init_f(state_engine_t *engine, + void *context, state_engine_function_t completed); + +void state_engine_next_f(state_engine_t *engine, + void *context, state_engine_function_t state); +bool state_engine_step(state_engine_t **engine); +void state_engine_push(state_engine_t **engine, state_engine_t *child); + +/* Complete engine, return parent, . */ +state_engine_t *state_engine_pop(state_engine_t *engine); + +/* State engine spi */ +struct state_engine_s { + state_engine_t *parent; + void *completed; + state_engine_function_t completed_f; + void *state; + state_engine_function_t state_f; +}; + +//static state_engine_t *current_engine; + +void state_engine_next_f(state_engine_t *engine, + void *state, state_engine_function_t state_f) { + engine->state_f = state_f; + engine->state = state; +} + +bool state_engine_step(state_engine_t **engine) { + if (!engine) + return false; + for (;;) { + if (!*engine) + return false; + if (!(*engine)->state_f) { + *engine = state_engine_pop(*engine); + } else { + (*engine)->state_f((*engine)->state); + } + } +} + +void state_engine_push(state_engine_t **engine, + state_engine_t *child) { + child->parent = *engine; + *engine = child; +} + +state_engine_t *state_engine_pop(state_engine_t *engine) { + state_engine_t *parent = engine->parent; + if (engine->completed_f) + engine->completed_f(engine->completed); + + return parent; +} + +#endif diff --git a/WHITEPAPER b/WHITEPAPER new file mode 100644 index 00000000..15a3cef2 --- /dev/null +++ b/WHITEPAPER @@ -0,0 +1,146 @@ +Security White Paper For Purple v1 +================================== + +Author +====== + +Michael Brouwer + + +Goals +==== + +* SSL support with Client Side authentication working. +* SecKeychain API for password storage. + +Footprint +======= + +To get an idea of how small an SSL implementation can be I compiled +MatrixSSL on ppc and arm. PPC binary is about 75k and arm is about +100k. MatrixSSL uses a GPL license so we can't use it directly. +However we could purchase a more liberal license from them and get +additional features available in the commercial version only. I +didn't investigate yet what those features are or what the pricing is. + +We've exceeded the matrixssl size by arriving at less than 100k ppc +binary for sslv2 sslv3 tlsv1 support with aes rc4 3des md5 sha1 rsa +support including the 40 bit export strength suites. + +I'm using the above numbers as a target to beat. Note that MatrixSSL +only does SSLv3 and TLS. In addition it only supports a cipher suites +using: MD2, MD5, SHA1, 3DES, and RSA. Also it doesn't support the +weaker "export strength" algorithms, which use smaller (40 bit) key +sizes, so you can't talk to an "export strength" only SSL server. + +Currently SecureTransport on Mac OS X supports, in addition to the +above: SSLv2 and cipher suites using RC2, RC4, AES, and Diffie-Hellman +key exchange (both anon and not). As well as export and non-export +versions of everything. + +We can decide later on if we need the algorithms that we support above +the MatrixSSL baseline, using a compile time flag. Of course each +addition algorithm adds to the code footprint. Diffie-Hellman in +particular adds extra code to SSL itself as well. Something else to +consider is whether or not we want to support ECCDSA and SHA2 (256 384 +and 512) something that the Federal government is requiring. + +SSLv2 support is something else we need to decide whether or not we +need, since supporting it requires a reasonable amount of code as +well. It's generally considered insecure today, however I don't know +how many websites are out there that only support SSLv2 and not any of +the more modern protocols. If we decide it's worth dropping SSLv2 to +save space, we should research this. + +SSL Milestones +============ + +* Converted our existing SecureTransport SSL code to C from C++ (done) +* Switch from using CDSA to embedded crypto (done) +* Move to a standalone certificate verification layer (mostly done) + Once the above are completed we will have a functional standalone + SSL library without client side auth support. (done) +* Optionally switch from using a generic ASN.1 encoding/decoding library to some + hand written C code instead which will be much smaller, saving and + estimated 100k code. (done) + +Progress +======== + +I've started evaluating and collecting crypto algorithms for use with +this SSL library. So far a number of them are smaller and faster than +the ones provided with MatrixSSL. However this comparison was done on +PPC as I don't have any ARM hardware to test on yet. Once selected +these algorithms should probably also go into the IP-Sec stack in xnu +or potentially even be shared between kernel and user space. + +Open Questions +============== + +Do we need to support: + +* CRLs (could potentially be synced connected to a host computer) +* OCSP certificate checking (requires a live connection). +* Suite B algorithms: AES 128/192/256, SHA2 256/384/512 and + ECCDSA 256/384/512. + +MatrixSSL has no support for either. The federal government requires +that we support at least one of the above and possibly even both. + +Keychain Support +============== + +To add client side certificate support we will need a way to securely +store private keys. For this I propose using a subset interface +similar, or identical to, the current SecKeychain API, but with a +completely new back-end implementation. This will get us both key and +password storage at the same time. + +For the back-end we can either use sqlite3 as the data store layer or +a custom lightweight DB or something based on CFPropertyLists. +Tradeoffs are that sqlite3 will scale better to large numbers of items +and large items (such as certificates and CRLs), but have a larger +code footprint. Safari is probably the only client that doesn't +already use sqlite3 though so in the other cases using sqlite3 will +probably make the footprint smaller than having custom code. + +An alternative is to keep each type of item in a separate lightweight +DB or property list to help scaling, but if a user stores a lot of web +form passwords for a lot of websites we will still end up reading all +of them into ram rather than just those we need when using sqlite3. + +In either case there need to be searchable attributes, and a single +non searchable attribute per item which will be encrypted with a +system wide key know only to a privileged agent. + +This agent will need to support 2 simple operations: encrypt blob and +decrypt blob. The agent can live either in the kernel or in a +lightweight server process that is launched on demand and can exit +when it is no longer needed. In either case the agent guards the key +bits but freely allows access to it by any client. This means we have +no keychain ACLs and any application running on the system can decrypt +all keychain secrets. Mac OS X currently has a much better +architecture which allows unwrapping keys inside the agent and +operating on them by reference without exposing the key bits to the +client. For private keys and multi use sessions keys this might be +desirable, but adds complexity and code size. + +Keychain Synching will require an agent running on the system that +decrypts each item and re-encrypts it the way a Tiger system expects +to see it. This can be done when the device is connect to a computer, +by requiring the user to enter the synched keychain password on the +device once to obtain the secrets. + +Other Security Issues +===================== + +* I have not yet looked at SPNEGO and NTLM at all yet. +* We might want to consolidate the Keychain secret mechanism above + with whatever the device will be using for music DRM services. + +Conclusion +========== + +If desired I can turn this into a more formal whitepaper and +start trying to set some milestones and timelines. However for now +I'd like to get some feedback on the current plan. diff --git a/asl/com.apple.securityd b/asl/com.apple.securityd index 9a003307..2d983200 100644 --- a/asl/com.apple.securityd +++ b/asl/com.apple.securityd @@ -1,6 +1,6 @@ -> security.log format='$Time $(Sender)[$(PID)] <$((Level)(str))> [$(Facility){$(SecAPITrace)} $(CALLER)]: $Message' rotate=utc-basic crashlog compress file_max=5M all_max=20M +> /var/mobile/Library/Logs/CrashReporter/DiagnosticLogs/security.log format='$Time $(Sender)[$(PID)] <$((Level)(str))> [$(Facility){$(SecAPITrace)} $(CALLER)]: $Message' uid=501 mode=0644 rotate=utc-basic crashlog compress file_max=5M all_max=20M -# Note: this file is for OSX only. +# Note: this file is for iOS only. # Note: # securityd is the iOS securityd @@ -8,21 +8,21 @@ # com.apple.secd is the iOS version of securityd running on OSX ? [T SecAPITrace] file security.log +? [= Sender com.apple.kb-service] file security.log ? [= Sender com.apple.securityd] file security.log ? [= Sender com.apple.secd] file security.log ? [= Sender CloudKeychainProxy] file security.log ? [= Sender securityd] file security.log ? [= Sender secd] file security.log -? [= Sender securityd_service] file security.log # Claim prevents the built-in ASL configuration from # processing our messages. We claim anything short # of errors, and let ASL do what it wants with the rest ? [T SecAPITrace] [> Level error] claim +? [= Sender com.apple.kb-service] [> Level error] claim ? [= Sender com.apple.securityd] [> Level error] claim ? [= Sender com.apple.secd] [> Level error] claim ? [= Sender CloudKeychainProxy] [> Level error] claim ? [= Sender securityd] [> Level error] claim ? [= Sender secd] [> Level error] claim -? [= Sender securityd_service] [> Level error] claim diff --git a/authd/Info.plist b/authd/Info.plist deleted file mode 100644 index 45709370..00000000 --- a/authd/Info.plist +++ /dev/null @@ -1,31 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIdentifier - com.apple.${PRODUCT_NAME:rfc1034identifier} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - XPC! - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 55471.14.18 - NSHumanReadableCopyright - Copyright © 2012 Apple. All rights reserved. - XPCService - - ServiceType - System - - - diff --git a/authd/ccaudit.h b/authd/ccaudit.h deleted file mode 100644 index 1485790a..00000000 --- a/authd/ccaudit.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ - -#ifndef _SECURITY_AUTH_CCAUDIT_H_ -#define _SECURITY_AUTH_CCAUDIT_H_ - -#include - -AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED -ccaudit_t ccaudit_create(process_t, auth_token_t, int32_t event); - -AUTH_NONNULL_ALL -void ccaudit_log_authorization(ccaudit_t, const char * right, OSStatus err); - -AUTH_NONNULL_ALL -void ccaudit_log_success(ccaudit_t, credential_t cred, const char * right); - -AUTH_NONNULL_ALL -void ccaudit_log_failure(ccaudit_t, const char * credName, const char * right); - -AUTH_NONNULL1 -void ccaudit_log_mechanism(ccaudit_t, const char * right, const char * mech, uint32_t status, const char * interrupted); - -AUTH_NONNULL1 -void ccaudit_log(ccaudit_t, const char * right, const char * msg, OSStatus err); - -#endif /* !_SECURITY_AUTH_CCAUDIT_H_ */ diff --git a/authd/connection.h b/authd/connection.h deleted file mode 100644 index f23cc8ff..00000000 --- a/authd/connection.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ - -#ifndef _SECURITY_AUTH_CONNECTION_H_ -#define _SECURITY_AUTH_CONNECTION_H_ - -#if defined(__cplusplus) -extern "C" { -#endif - -AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED -connection_t connection_create(process_t); - -AUTH_NONNULL_ALL -pid_t connection_get_pid(connection_t); - -AUTH_NONNULL_ALL -process_t connection_get_process(connection_t); - -AUTH_NONNULL_ALL -dispatch_queue_t connection_get_dispatch_queue(connection_t); - -AUTH_NONNULL1 -void connection_set_engine(connection_t, engine_t); - -AUTH_NONNULL_ALL -void connection_destory_agents(connection_t); - -AUTH_NONNULL_ALL -bool connection_get_syslog_warn(connection_t); - -AUTH_NONNULL_ALL -void connection_set_syslog_warn(connection_t); - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_AUTH_CONNECTION_H_ */ diff --git a/authd/credential.h b/authd/credential.h deleted file mode 100644 index eb25b450..00000000 --- a/authd/credential.h +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ - -#ifndef _SECURITY_AUTH_CREDENTIAL_H_ -#define _SECURITY_AUTH_CREDENTIAL_H_ - -#if defined(__cplusplus) -extern "C" { -#endif - -#ifdef __BLOCKS__ - typedef bool (^credential_iterator_t)(credential_t); -#endif /* __BLOCKS__ */ - -AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED -credential_t credential_create(uid_t); - -AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED -credential_t credential_create_with_credential(credential_t,bool); - -AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED -credential_t credential_create_with_right(const char *); - -AUTH_NONNULL_ALL -uid_t credential_get_uid(credential_t); - -AUTH_NONNULL_ALL -const char * credential_get_name(credential_t); - -AUTH_NONNULL_ALL -const char * credential_get_realname(credential_t); - -AUTH_NONNULL_ALL -CFAbsoluteTime credential_get_creation_time(credential_t); - -AUTH_NONNULL_ALL -bool credential_get_valid(credential_t); - -AUTH_NONNULL_ALL -bool credential_get_shared(credential_t); - -AUTH_NONNULL_ALL -bool credential_is_right(credential_t); - -AUTH_NONNULL_ALL -bool credential_check_membership(credential_t,const char*); - -AUTH_NONNULL_ALL -void credential_invalidate(credential_t); - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_AUTH_CREDENTIAL_H_ */ diff --git a/authd/debugging.c b/authd/debugging.c deleted file mode 100644 index beb0803a..00000000 --- a/authd/debugging.c +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ - -#include "debugging.h" -#include "authd_private.h" -#include "authutilities.h" -#include -#include -#include -#include - -// sudo defaults write /Library/Preferences/com.apple.security.coderequirements Entitlements -string always - -static bool -security_auth_verbose(void) -{ - static dispatch_once_t onceToken; - static bool verbose_enabled = false; - - //sudo defaults write /Library/Preferences/com.apple.authd verbose -bool true - dispatch_once(&onceToken, ^{ - CFTypeRef verbose = (CFNumberRef)CFPreferencesCopyValue(CFSTR("verbose"), CFSTR(SECURITY_AUTH_NAME), kCFPreferencesAnyUser, kCFPreferencesCurrentHost); - - if (verbose && CFGetTypeID(verbose) == CFBooleanGetTypeID()) { - verbose_enabled = CFBooleanGetValue((CFBooleanRef)verbose); - } -#if DEBUG - syslog(LOG_NOTICE, "verbose: %s", verbose_enabled ? "enabled" : "disabled"); -#endif - CFReleaseSafe(verbose); - }); - - return verbose_enabled; -} - -void -security_auth_log(int type,const char * format,...) -{ - va_list ap; - va_start(ap, format); - switch (type) { - case AUTH_LOG_NORMAL: - vsyslog(LOG_NOTICE, format, ap); - break; - case AUTH_LOG_VERBOSE: - if (security_auth_verbose()) { - vsyslog(LOG_NOTICE, format, ap); - } - break; - case AUTH_LOG_ERROR: - vsyslog(LOG_ERR, format, ap); - break; - default: - break; - } - va_end(ap); -} - -void _show_cf(CFTypeRef value) -{ - CFStringRef string = NULL; - char * tmp = NULL; - require(value != NULL, done); - - if (security_auth_verbose()) { - string = CFCopyDescription(value); - tmp = _copy_cf_string(string, NULL); - - syslog(LOG_NOTICE, "%s", tmp); - } - -done: - CFReleaseSafe(string); - free_safe(tmp); - return; -} diff --git a/authd/debugging.h b/authd/debugging.h deleted file mode 100644 index 07a3e1c7..00000000 --- a/authd/debugging.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ - -#ifndef _SECURITY_AUTH_DEBUGGING_H_ -#define _SECURITY_AUTH_DEBUGGING_H_ - -#if defined(__cplusplus) -extern "C" { -#endif - -enum { - AUTH_LOG_NORMAL, - AUTH_LOG_VERBOSE, - AUTH_LOG_ERROR -}; - -#define LOG(...) security_auth_log(AUTH_LOG_NORMAL, ##__VA_ARGS__) -#define LOGV(...) security_auth_log(AUTH_LOG_VERBOSE, ##__VA_ARGS__) -#define LOGE(...) security_auth_log(AUTH_LOG_ERROR, ##__VA_ARGS__) -#if DEBUG -#define LOGD(...) security_auth_log(AUTH_LOG_VERBOSE, ##__VA_ARGS__) -#else -#define LOGD(...) -#endif - -void security_auth_log(int,const char *,...) __printflike(2, 3); - -#define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) CFRelease(_cf); } -#define CFReleaseNull(CF) { CFTypeRef _cf = (CF); \ - if (_cf) { (CF) = NULL; CFRelease(_cf); } } -#define CFRetainSafe(CF) { CFTypeRef _cf = (CF); if (_cf) CFRetain(_cf); } - -#define xpc_release_safe(obj) if (obj) { xpc_release(obj); obj = NULL; } -#define free_safe(obj) if (obj) { free(obj); obj = NULL; } - -void _show_cf(CFTypeRef); - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_AUTH_DEBUGGING_H_ */ diff --git a/authd/main.c b/authd/main.c deleted file mode 100644 index 9309d5cd..00000000 --- a/authd/main.c +++ /dev/null @@ -1,208 +0,0 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ - -#include "debugging.h" -#include "server.h" -#include "process.h" -#include "session.h" -#include "authtoken.h" -#include "engine.h" -#include "authd_private.h" -#include "connection.h" - -#include - -#include -#include -#include -#include -#include - -#if DEBUG -#include -#endif - -static void -security_auth_peer_event_handler(xpc_connection_t connection, xpc_object_t event) -{ - __block OSStatus status = errAuthorizationDenied; - - connection_t conn = (connection_t)xpc_connection_get_context(connection); - require_action(conn != NULL, done, LOGE("xpc[%i]: process context not found", xpc_connection_get_pid(connection))); - - CFRetainSafe(conn); - - xpc_type_t type = xpc_get_type(event); - - if (type == XPC_TYPE_ERROR) { - if (event == XPC_ERROR_CONNECTION_INVALID) { - // The client process on the other end of the connection has either - // crashed or cancelled the connection. After receiving this error, - // the connection is in an invalid state, and you do not need to - // call xpc_connection_cancel(). Just tear down any associated state - // here. - LOGV("xpc[%i]: client disconnected", xpc_connection_get_pid(connection)); - connection_destory_agents(conn); - } else if (event == XPC_ERROR_TERMINATION_IMMINENT) { - // Handle per-connection termination cleanup. - LOGD("xpc[%i]: per-connection termination", xpc_connection_get_pid(connection)); - } - } else { - assert(type == XPC_TYPE_DICTIONARY); - - xpc_object_t reply = xpc_dictionary_create_reply(event); - require(reply != NULL, done); - - uint64_t auth_type = xpc_dictionary_get_uint64(event, AUTH_XPC_TYPE); - LOGV("xpc[%i]: received message type=%llu", connection_get_pid(conn), auth_type); - - switch (auth_type) { - case AUTHORIZATION_CREATE: - status = authorization_create(conn,event,reply); - break; - case AUTHORIZATION_CREATE_WITH_AUDIT_TOKEN: - status = authorization_create_with_audit_token(conn,event,reply); - break; - case AUTHORIZATION_FREE: - status = authorization_free(conn,event,reply); - break; - case AUTHORIZATION_COPY_RIGHTS: - status = authorization_copy_rights(conn,event,reply); - break; - case AUTHORIZATION_COPY_INFO: - status = authorization_copy_info(conn,event,reply); - break; - case AUTHORIZATION_MAKE_EXTERNAL_FORM: - status = authorization_make_external_form(conn,event,reply); - break; - case AUTHORIZATION_CREATE_FROM_EXTERNAL_FORM: - status = authorization_create_from_external_form(conn,event,reply); - break; - case AUTHORIZATION_RIGHT_GET: - status = authorization_right_get(conn,event,reply); - break; - case AUTHORIZATION_RIGHT_SET: - status = authorization_right_set(conn,event,reply); - break; - case AUTHORIZATION_RIGHT_REMOVE: - status = authorization_right_remove(conn,event,reply); - break; - case SESSION_SET_USER_PREFERENCES: - status = session_set_user_preferences(conn,event,reply); - break; - case AUTHORIZATION_DISMISS: - connection_destory_agents(conn); - status = errAuthorizationSuccess; - break; - case AUTHORIZATION_ENABLE_SMARTCARD: - status = authorization_enable_smartcard(conn,event,reply); - break; - case AUTHORIZATION_SETUP: - { - mach_port_t bootstrap = xpc_dictionary_copy_mach_send(event, AUTH_XPC_BOOTSTRAP); - if (!process_set_bootstrap(connection_get_process(conn), bootstrap)) { - if (bootstrap != MACH_PORT_NULL) { - mach_port_deallocate(mach_task_self(), bootstrap); - } - } - } - status = errAuthorizationSuccess; - break; -#if DEBUG - case AUTHORIZATION_DEV: - server_dev(); - break; -#endif - default: - break; - } - - xpc_dictionary_set_int64(reply, AUTH_XPC_STATUS, status); - xpc_connection_send_message(connection, reply); - xpc_release(reply); - } - -done: - CFReleaseSafe(conn); -} - -static void -connection_finalizer(void * conn) -{ - LOGD("xpc[%i]: connection_finalizer", connection_get_pid(conn)); - server_unregister_connection(conn); - -//#if DEBUG -// malloc_printf("-=-=-=- connection_finalizer() -=-=-=-\n"); -// malloc_zone_print(malloc_default_zone(), false); -//#endif -} - -static void -security_auth_event_handler(xpc_connection_t xpc_conn) -{ - connection_t conn = server_register_connection(xpc_conn); - - if (conn) { - xpc_connection_set_context(xpc_conn, conn); - xpc_connection_set_finalizer_f(xpc_conn, connection_finalizer); - - xpc_connection_set_event_handler(xpc_conn, ^(xpc_object_t event) { - xpc_retain(xpc_conn); - xpc_retain(event); - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - security_auth_peer_event_handler(xpc_conn, event); - xpc_release(event); - xpc_release(xpc_conn); - }); - }); - xpc_connection_resume(xpc_conn); - - } else { - LOGE("xpc[%i]: failed to register connection", xpc_connection_get_pid(xpc_conn)); - xpc_connection_cancel(xpc_conn); - } -} - -static void sandbox() -{ - char * errorbuf; - int32_t rc; - - rc = sandbox_init(SECURITY_AUTH_NAME, SANDBOX_NAMED, &errorbuf); - - if (rc) { - LOGE("server: sandbox_init failed %s (%i)", errorbuf, rc); - sandbox_free_error(errorbuf); -#ifndef DEBUG - abort(); -#endif - } -} - -int main(int argc AUTH_UNUSED, const char *argv[] AUTH_UNUSED) -{ -//#if DEBUG -// malloc_printf("-=-=-=- main() -=-=-=-\n"); -// malloc_zone_print(malloc_default_zone(), false); -//#endif - - LOGV("starting"); - - sandbox(); - - if (server_init() != errAuthorizationSuccess) { - LOGE("auth: server_init() failed"); - return errAuthorizationInternal; - } - -//#if DEBUG -// malloc_printf("-=-=-=- server_init() -=-=-=-\n"); -// malloc_zone_print(malloc_default_zone(), false); -//#endif - - xpc_main(security_auth_event_handler); - - server_cleanup(); - - return 0; -} diff --git a/authd/object.c b/authd/object.c deleted file mode 100644 index 7e507696..00000000 --- a/authd/object.c +++ /dev/null @@ -1,5 +0,0 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ - -#include "object.h" -#include "crc.h" -#include "authutilities.h" diff --git a/authd/process.h b/authd/process.h deleted file mode 100644 index 94e5d29b..00000000 --- a/authd/process.h +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ - -#ifndef _SECURITY_AUTH_PROCESS_H_ -#define _SECURITY_AUTH_PROCESS_H_ - -#include -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED -process_t process_create(const audit_info_s*,session_t); - -AUTH_NONNULL_ALL -const void * process_get_key(process_t); - -AUTH_NONNULL_ALL -uid_t process_get_uid(process_t); - -AUTH_NONNULL_ALL -pid_t process_get_pid(process_t); - -AUTH_NONNULL_ALL -int32_t process_get_generation(process_t); - -AUTH_NONNULL_ALL -session_id_t process_get_session_id(process_t); - -AUTH_NONNULL_ALL -session_t process_get_session(process_t); - -AUTH_NONNULL_ALL -uint32_t process_get_count(process_t); - -AUTH_NONNULL_ALL -const audit_info_s * process_get_audit_info(process_t); - -AUTH_NONNULL_ALL -SecCodeRef process_get_code(process_t); - -AUTH_NONNULL_ALL -const char * process_get_code_url(process_t); - -AUTH_NONNULL_ALL -CFIndex process_add_connection(process_t, connection_t); - -AUTH_NONNULL_ALL -CFIndex process_remove_connection(process_t, connection_t); - -AUTH_NONNULL_ALL -CFIndex process_get_connection_count(process_t); - -AUTH_NONNULL_ALL -void process_add_auth_token(process_t,auth_token_t); - -AUTH_NONNULL_ALL -void process_remove_auth_token(process_t,auth_token_t, uint32_t flags); - -AUTH_NONNULL_ALL -auth_token_t process_find_copy_auth_token(process_t,const AuthorizationBlob*); - -AUTH_NONNULL_ALL -CFIndex process_get_auth_token_count(process_t); - -AUTH_NONNULL_ALL -CFTypeRef process_copy_entitlement_value(process_t, const char * entitlement); - -AUTH_NONNULL_ALL -bool process_has_entitlement(process_t, const char * entitlement); - -AUTH_NONNULL_ALL -bool process_has_entitlement_for_right(process_t, const char * right); - -AUTH_NONNULL_ALL -const char * process_get_identifier(process_t); - -AUTH_NONNULL_ALL -CFDataRef process_get_requirement_data(process_t); - -AUTH_NONNULL_ALL -SecRequirementRef process_get_requirement(process_t); - -AUTH_NONNULL_ALL -bool process_verify_requirment(process_t,SecRequirementRef); - -AUTH_NONNULL_ALL -bool process_apple_signed(process_t proc); - -AUTH_NONNULL_ALL -mach_port_t process_get_bootstrap(process_t); - -AUTH_NONNULL_ALL -bool process_set_bootstrap(process_t, mach_port_t); - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_AUTH_PROCESS_H_ */ diff --git a/authd/server.c b/authd/server.c deleted file mode 100644 index 8f4e0d88..00000000 --- a/authd/server.c +++ /dev/null @@ -1,1169 +0,0 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ - -#include "server.h" -#include "session.h" -#include "process.h" -#include "authtoken.h" -#include "authdb.h" -#include "rule.h" -#include "authutilities.h" -#include "crc.h" -#include "mechanism.h" -#include "agent.h" -#include "authitems.h" -#include "debugging.h" -#include "engine.h" -#include "connection.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAX_PROCESS_RIGHTS 30 - -static CFMutableDictionaryRef gProcessMap = NULL; -static CFMutableDictionaryRef gSessionMap = NULL; -static CFMutableDictionaryRef gAuthTokenMap = NULL; -static authdb_t gDatabase = NULL; - -static dispatch_queue_t power_queue; -static bool gInDarkWake = false; -static IOPMConnection gIOPMconn = NULL; -static bool gXPCTransaction = false; - -static dispatch_queue_t -get_server_dispatch_queue() -{ - static dispatch_once_t onceToken; - static dispatch_queue_t server_queue = NULL; - - dispatch_once(&onceToken, ^{ - server_queue = dispatch_queue_create("com.apple.security.auth.server", DISPATCH_QUEUE_SERIAL); - check(server_queue != NULL); - }); - - return server_queue; -} - -static Boolean _processEqualCallBack(const void *value1, const void *value2) -{ - audit_info_s * info1 = (audit_info_s*)value1; - audit_info_s * info2 = (audit_info_s*)value2; - if (info1->pid == info2->pid) { - if (info1->tid == info2->tid) { - return true; - } - } - return false; -} - -static CFHashCode _processHashCallBack(const void *value) -{ - audit_info_s * info = (audit_info_s*)value; - uint64_t crc = crc64_init(); - crc = crc64_update(crc, &info->pid, sizeof(info->pid)); - crc = crc64_update(crc, &info->tid, sizeof(info->tid)); - crc = crc64_final(crc); - return crc; -} - -static const CFDictionaryKeyCallBacks kProcessMapKeyCallBacks = { - .version = 0, - .retain = NULL, - .release = NULL, - .copyDescription = NULL, - .equal = &_processEqualCallBack, - .hash = &_processHashCallBack -}; - -static Boolean _sessionEqualCallBack(const void *value1, const void *value2) -{ - return (*(session_id_t*)value1) == (*(session_id_t*)value2); -} - -static CFHashCode _sessionHashCallBack(const void *value) -{ - return (CFHashCode)(*(session_id_t*)(value)); -} - -static const CFDictionaryKeyCallBacks kSessionMapKeyCallBacks = { - .version = 0, - .retain = NULL, - .release = NULL, - .copyDescription = NULL, - .equal = &_sessionEqualCallBack, - .hash = &_sessionHashCallBack -}; - -void server_cleanup() -{ - CFRelease(gProcessMap); - CFRelease(gSessionMap); - CFRelease(gAuthTokenMap); - - IOPMConnectionSetDispatchQueue(gIOPMconn, NULL); - IOPMConnectionRelease(gIOPMconn); - - dispatch_queue_t queue = get_server_dispatch_queue(); - if (queue) { - dispatch_release(queue); - } - dispatch_release(power_queue); -} - -static void _IOMPCallBack(void * param AUTH_UNUSED, IOPMConnection connection, IOPMConnectionMessageToken token, IOPMSystemPowerStateCapabilities capabilities) -{ - LOGV("server: IOMP powerstates %i", capabilities); - if (capabilities & kIOPMSystemPowerStateCapabilityDisk) - LOGV("server: disk"); - if (capabilities & kIOPMSystemPowerStateCapabilityNetwork) - LOGV("server: net"); - if (capabilities & kIOPMSystemPowerStateCapabilityAudio) - LOGV("server: audio"); - if (capabilities & kIOPMSystemPowerStateCapabilityVideo) - LOGV("server: video"); - - /* if cpu and no display -> in DarkWake */ - LOGD("server: DarkWake check current=%i==%i", (capabilities & (kIOPMSystemPowerStateCapabilityCPU|kIOPMSystemPowerStateCapabilityVideo)), kIOPMSystemPowerStateCapabilityCPU); - if ((capabilities & (kIOPMSystemPowerStateCapabilityCPU|kIOPMSystemPowerStateCapabilityVideo)) == kIOPMSystemPowerStateCapabilityCPU) { - LOGV("server: enter DarkWake"); - gInDarkWake = true; - } else if (gInDarkWake) { - LOGV("server: exit DarkWake"); - gInDarkWake = false; - } - - (void)IOPMConnectionAcknowledgeEvent(connection, token); - - return; -} - -static void -_setupDarkWake(void *ctx) -{ - IOReturn ret; - - IOPMConnectionCreate(CFSTR("IOPowerWatcher"), - kIOPMSystemPowerStateCapabilityDisk - | kIOPMSystemPowerStateCapabilityNetwork - | kIOPMSystemPowerStateCapabilityAudio - | kIOPMSystemPowerStateCapabilityVideo, - &gIOPMconn); - - ret = IOPMConnectionSetNotification(gIOPMconn, NULL, _IOMPCallBack); - if (ret != kIOReturnSuccess) - return; - - IOPMConnectionSetDispatchQueue(gIOPMconn, power_queue); - - IOPMScheduleUserActiveChangedNotification(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(bool active) { - if (active) { - gInDarkWake = false; - } - }); -} - -bool server_in_dark_wake() -{ - return gInDarkWake; -} - -authdb_t server_get_database() -{ - return gDatabase; -} - -static void _setupAuditSessionMonitor() -{ - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - au_sdev_handle_t *dev = au_sdev_open(AU_SDEVF_ALLSESSIONS); - int event; - auditinfo_addr_t aia; - - if (NULL == dev) { - LOGE("server: could not open %s %d", AUDIT_SDEV_PATH, errno); - return; - } - - for (;;) { - if (0 != au_sdev_read_aia(dev, &event, &aia)) { - LOGE("server: au_sdev_read_aia failed: %d", errno); - continue; - } - LOGD("server: au_sdev_handle_t event=%i, session=%i", event, aia.ai_asid); - if (event == AUE_SESSION_CLOSE) { - dispatch_async(get_server_dispatch_queue(), ^{ - LOGV("server: session %i destroyed", aia.ai_asid); - CFDictionaryRemoveValue(gSessionMap, &aia.ai_asid); - }); - } - } - - }); -} - -static void _setupSignalHandlers() -{ - signal(SIGTERM, SIG_IGN); - static dispatch_source_t sigtermHandler; - sigtermHandler = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGTERM, 0, get_server_dispatch_queue()); - if (sigtermHandler) { - dispatch_source_set_event_handler(sigtermHandler, ^{ - - // should we clean up any state? - exit(EXIT_SUCCESS); - }); - dispatch_resume(sigtermHandler); - } -} - -OSStatus server_init(void) -{ - OSStatus status = errAuthorizationSuccess; - - auditinfo_addr_t info; - memset(&info, 0, sizeof(info)); - getaudit_addr(&info, sizeof(info)); - LOGV("server: uid=%i, sid=%i", info.ai_auid, info.ai_asid); - - require_action(get_server_dispatch_queue() != NULL, done, status = errAuthorizationInternal); - - gProcessMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kProcessMapKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - require_action(gProcessMap != NULL, done, status = errAuthorizationInternal); - - gSessionMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kSessionMapKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - require_action(gSessionMap != NULL, done, status = errAuthorizationInternal); - - gAuthTokenMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kAuthTokenKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - require_action(gAuthTokenMap != NULL, done, status = errAuthorizationInternal); - - gDatabase = authdb_create(); - require_action(gDatabase != NULL, done, status = errAuthorizationInternal); - - // check to see if we have an updates - authdb_connection_t dbconn = authdb_connection_acquire(gDatabase); - authdb_maintenance(dbconn); - authdb_connection_release(&dbconn); - - power_queue = dispatch_queue_create("com.apple.security.auth.power", DISPATCH_QUEUE_SERIAL); - check(power_queue != NULL); - dispatch_async_f(power_queue, NULL, _setupDarkWake); - - _setupAuditSessionMonitor(); - _setupSignalHandlers(); - -done: - return status; -} - -static void _server_parse_audit_token(audit_token_t * token, audit_info_s * info) -{ - if (token && info) { - memset(info, 0, sizeof(*info)); - au_tid_t tid; - memset(&tid, 0, sizeof(tid)); - audit_token_to_au32(*token, &info->auid, &info->euid, - &info->egid, &info->ruid, &info->rgid, - &info->pid, &info->asid, &tid); - info->tid = tid.port; - info->opaqueToken = *token; - } -} - -connection_t -server_register_connection(xpc_connection_t connection) -{ - __block connection_t conn = NULL; - __block session_t session = NULL; - __block process_t proc = NULL; - __block CFIndex conn_count = 0; - - require(connection != NULL, done); - - audit_token_t auditToken; - audit_info_s info; - xpc_connection_get_audit_token(connection, &auditToken); - _server_parse_audit_token(&auditToken, &info); - - - dispatch_sync(get_server_dispatch_queue(), ^{ - session = (session_t)CFDictionaryGetValue(gSessionMap, &info.asid); - if (session) { - CFRetain(session); - } else { - session = session_create(info.asid); - CFDictionarySetValue(gSessionMap, session_get_key(session), session); - } - - proc = (process_t)CFDictionaryGetValue(gProcessMap, &info); - if (proc) { - CFRetain(proc); - } - - if (proc) { - conn = connection_create(proc); - conn_count = process_add_connection(proc, conn); - } else { - proc = process_create(&info, session); - if (proc) { - conn = connection_create(proc); - conn_count = process_add_connection(proc, conn); - session_add_process(session, proc); - CFDictionarySetValue(gProcessMap, process_get_key(proc), proc); - } - } - - if (!gXPCTransaction) { - xpc_transaction_begin(); - gXPCTransaction = true; - } - }); - - LOGV("server[%i]: registered connection (total=%li)", info.pid, conn_count); - -done: - CFReleaseSafe(session); - CFReleaseSafe(proc); - return conn; -} - -void -server_unregister_connection(connection_t conn) -{ - if (conn != NULL) { - process_t proc = connection_get_process(conn); - - dispatch_sync(get_server_dispatch_queue(), ^{ - CFIndex connectionCount = process_get_connection_count(proc); - LOGV("server[%i]: unregistered connection (total=%li)", process_get_pid(proc), connectionCount); - - if (connectionCount == 1) { - CFDictionaryRemoveValue(gProcessMap, process_get_key(proc)); - } - - if (CFDictionaryGetCount(gProcessMap) == 0) { - xpc_transaction_end(); - gXPCTransaction = false; - } - }); - // move the destruction of the connection/process off the server queue - CFRelease(conn); - } -} - -void -server_register_auth_token(auth_token_t auth) -{ - if (auth != NULL) { - dispatch_sync(get_server_dispatch_queue(), ^{ - LOGV("server: registering auth %p", auth); - CFDictionarySetValue(gAuthTokenMap, auth_token_get_key(auth), auth); - auth_token_set_state(auth, auth_token_state_registered); - }); - } -} - -void -server_unregister_auth_token(auth_token_t auth) -{ - if (auth != NULL) { - AuthorizationBlob blob = *(AuthorizationBlob*)auth_token_get_key(auth); - dispatch_async(get_server_dispatch_queue(), ^{ - LOGV("server: unregistering auth %p", auth); - CFDictionaryRemoveValue(gAuthTokenMap, &blob); - }); - } -} - -auth_token_t -server_find_copy_auth_token(AuthorizationBlob * blob) -{ - __block auth_token_t auth = NULL; - if (blob != NULL) { - dispatch_sync(get_server_dispatch_queue(), ^{ - auth = (auth_token_t)CFDictionaryGetValue(gAuthTokenMap, blob); - if (auth) { - CFRetain(auth); - } - }); - } - return auth; -} - -session_t -server_find_copy_session(session_id_t sid, bool create) -{ - __block session_t session = NULL; - - dispatch_sync(get_server_dispatch_queue(), ^{ - session = (session_t)CFDictionaryGetValue(gSessionMap, &sid); - if (session) { - CFRetain(session); - } else if (create) { - session = session_create(sid); - if (session) { - CFDictionarySetValue(gSessionMap, session_get_key(session), session); - } - } - }); - - return session; -} - -#pragma mark - -#pragma mark API - -static OSStatus -_process_find_copy_auth_token_from_xpc(process_t proc, xpc_object_t message, auth_token_t * auth_out) -{ - OSStatus status = errAuthorizationSuccess; - require_action(auth_out != NULL, done, status = errAuthorizationInternal); - - size_t len; - AuthorizationBlob * blob = (AuthorizationBlob *)xpc_dictionary_get_data(message, AUTH_XPC_BLOB, &len); - require_action(blob != NULL, done, status = errAuthorizationInvalidRef); - require_action(len == sizeof(AuthorizationBlob), done, status = errAuthorizationInvalidRef); - - auth_token_t auth = process_find_copy_auth_token(proc, blob); - require_action(auth != NULL, done, status = errAuthorizationInvalidRef); - -#if DEBUG - LOGV("server[%i]: authtoken lookup %#x%x %p", process_get_pid(proc), blob->data[1],blob->data[0], auth); -#else - LOGV("server[%i]: authtoken lookup %p", process_get_pid(proc), auth); -#endif - - *auth_out = auth; - -done: - return status; -} - -static OSStatus _server_authorize(connection_t conn, auth_token_t auth, AuthorizationFlags flags, auth_rights_t rights, auth_items_t enviroment, engine_t * engine_out) -{ - __block OSStatus status = errAuthorizationDenied; - engine_t engine = NULL; - - require_action(conn, done, status = errAuthorizationInternal); - - engine = engine_create(conn, auth); - require_action(engine, done, status = errAuthorizationInternal); - - if (flags & kAuthorizationFlagInteractionAllowed) { - dispatch_sync(connection_get_dispatch_queue(conn), ^{ - connection_set_engine(conn, engine); - status = engine_authorize(engine, rights, enviroment, flags); - connection_set_engine(conn, NULL); - }); - } else { - status = engine_authorize(engine, rights, enviroment, flags); - } - -done: - if (engine) { - if (engine_out) { - *engine_out = engine; - } else { - CFRelease(engine); - } - } - return status; -} - -// IN: AUTH_XPC_RIGHTS, AUTH_XPC_ENVIROMENT, AUTH_XPC_FLAGS -// OUT: AUTH_XPC_BLOB -OSStatus -authorization_create(connection_t conn, xpc_object_t message, xpc_object_t reply) -{ - OSStatus status = errAuthorizationDenied; - - process_t proc = connection_get_process(conn); - - // Passed in args - auth_rights_t rights = auth_rights_create_with_xpc(xpc_dictionary_get_value(message, AUTH_XPC_RIGHTS)); - auth_items_t enviroment = auth_items_create_with_xpc(xpc_dictionary_get_value(message, AUTH_XPC_ENVIROMENT)); - AuthorizationFlags flags = (AuthorizationFlags)xpc_dictionary_get_uint64(message, AUTH_XPC_FLAGS); - - // Create Authorization Token - auth_token_t auth = auth_token_create(proc, flags & kAuthorizationFlagLeastPrivileged); - require_action(auth != NULL, done, status = errAuthorizationInternal); - - if (!(flags & kAuthorizationFlagNoData)) { - process_add_auth_token(proc,auth); - } - - status = _server_authorize(conn, auth, flags, rights, enviroment, NULL); - require_noerr(status, done); - - //reply - xpc_dictionary_set_data(reply, AUTH_XPC_BLOB, auth_token_get_blob(auth), sizeof(AuthorizationBlob)); - -done: - CFReleaseSafe(rights); - CFReleaseSafe(enviroment); - CFReleaseSafe(auth); - return status; -} - -// IN: AUTH_XPC_DATA, AUTH_XPC_ENVIROMENT, AUTH_XPC_FLAGS -// OUT: AUTH_XPC_BLOB -OSStatus authorization_create_with_audit_token(connection_t conn, xpc_object_t message, xpc_object_t reply) -{ - OSStatus status = errAuthorizationDenied; - auth_token_t auth = NULL; - - process_t proc = connection_get_process(conn); - require(process_get_uid(proc) == 0, done); //only root can use this call - - // Passed in args - size_t len = 0; - const char * data = xpc_dictionary_get_data(message, AUTH_XPC_DATA, &len); - require(data != NULL, done); - require(len == sizeof(audit_token_t), done); - -// auth_items_t enviroment = auth_items_create_with_xpc(xpc_dictionary_get_value(message, AUTH_XPC_ENVIROMENT)); - AuthorizationFlags flags = (AuthorizationFlags)xpc_dictionary_get_uint64(message, AUTH_XPC_FLAGS); - - audit_info_s auditInfo; - _server_parse_audit_token((audit_token_t*)data, &auditInfo); - - // Create Authorization Token - auth = auth_token_create(proc, flags & kAuthorizationFlagLeastPrivileged); - require_action(auth != NULL, done, status = errAuthorizationInternal); - - process_add_auth_token(proc,auth); - - //reply - xpc_dictionary_set_data(reply, AUTH_XPC_BLOB, auth_token_get_blob(auth), sizeof(AuthorizationBlob)); - -done: -// CFReleaseSafe(enviroment); - CFReleaseSafe(auth); - return status; -} - -// IN: AUTH_XPC_BLOB, AUTH_XPC_FLAGS -// OUT: -OSStatus -authorization_free(connection_t conn, xpc_object_t message, xpc_object_t reply AUTH_UNUSED) -{ - OSStatus status = errAuthorizationSuccess; - AuthorizationFlags flags = 0; - process_t proc = connection_get_process(conn); - - auth_token_t auth = NULL; - status = _process_find_copy_auth_token_from_xpc(proc, message, &auth); - require_noerr(status, done); - - flags = (AuthorizationFlags)xpc_dictionary_get_uint64(message, AUTH_XPC_FLAGS); - - if (flags & kAuthorizationFlagDestroyRights) { - auth_token_credentials_iterate(auth, ^bool(credential_t cred) { - credential_invalidate(cred); - LOGV("engine[%i]: invalidating %scredential %s (%i) from authorization (%p)", connection_get_pid(conn), credential_get_shared(cred) ? "shared " : "", credential_get_name(cred), credential_get_uid(cred), auth); - return true; - }); - - session_credentials_purge(auth_token_get_session(auth)); - } - - process_remove_auth_token(proc, auth, flags); - -done: - CFReleaseSafe(auth); - LOGV("server[%i]: AuthorizationFree %i (flags:%x)", connection_get_pid(conn), status, flags); - return status; -} - -// IN: AUTH_XPC_BLOB, AUTH_XPC_RIGHTS, AUTH_XPC_ENVIROMENT, AUTH_XPC_FLAGS -// OUT: AUTH_XPC_OUT_ITEMS -OSStatus -authorization_copy_rights(connection_t conn, xpc_object_t message, xpc_object_t reply) -{ - OSStatus status = errAuthorizationDenied; - engine_t engine = NULL; - - process_t proc = connection_get_process(conn); - - // Passed in args - auth_rights_t rights = auth_rights_create_with_xpc(xpc_dictionary_get_value(message, AUTH_XPC_RIGHTS)); - auth_items_t enviroment = auth_items_create_with_xpc(xpc_dictionary_get_value(message, AUTH_XPC_ENVIROMENT)); - AuthorizationFlags flags = (AuthorizationFlags)xpc_dictionary_get_uint64(message, AUTH_XPC_FLAGS); - - auth_token_t auth = NULL; - status = _process_find_copy_auth_token_from_xpc(proc, message, &auth); - require_noerr(status, done); - - status = _server_authorize(conn, auth, flags, rights, enviroment, &engine); - require_noerr(status, done); - - //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); - -done: - CFReleaseSafe(rights); - CFReleaseSafe(enviroment); - CFReleaseSafe(auth); - CFReleaseSafe(engine); - - return status; -} - -// IN: AUTH_XPC_BLOB, AUTH_XPC_TAG -// OUT: AUTH_XPC_OUT_ITEMS -OSStatus -authorization_copy_info(connection_t conn, xpc_object_t message, xpc_object_t reply) -{ - - OSStatus status = errAuthorizationSuccess; - auth_items_t items = NULL; - const char * tag = NULL; - - process_t proc = connection_get_process(conn); - - auth_token_t auth = NULL; - status = _process_find_copy_auth_token_from_xpc(proc, message, &auth); - require_noerr(status, done); - - items = auth_items_create(); - - tag = xpc_dictionary_get_string(message, AUTH_XPC_TAG); - LOGV("server[%i]: requested tag: %s", connection_get_pid(conn), tag ? tag : "(all)"); - if (tag) { - size_t len; - const void * data = auth_items_get_data(auth_token_get_context(auth), tag, &len); - if (data) { - auth_items_set_data(items, tag, data, len); - } - } else { - auth_items_copy(items, auth_token_get_context(auth)); - } - -#if DEBUG - LOGV("server[%i]: Dumping requested AuthRef items", connection_get_pid(conn)); - _show_cf(items); -#endif - - //reply - xpc_object_t outItems = auth_items_export_xpc(items); - xpc_dictionary_set_value(reply, AUTH_XPC_OUT_ITEMS, outItems); - xpc_release_safe(outItems); - -done: - CFReleaseSafe(items); - CFReleaseSafe(auth); - LOGV("server[%i]: AuthorizationCopyInfo %i", connection_get_pid(conn), status); - return status; -} - -// IN: AUTH_XPC_BLOB -// OUT: AUTH_XPC_EXTERNAL -OSStatus -authorization_make_external_form(connection_t conn, xpc_object_t message, xpc_object_t reply) -{ - OSStatus status = errAuthorizationSuccess; - - process_t proc = connection_get_process(conn); - - auth_token_t auth = NULL; - status = _process_find_copy_auth_token_from_xpc(proc, message, &auth); - require_noerr(status, done); - - AuthorizationExternalForm exForm; - AuthorizationExternalBlob * exBlob = (AuthorizationExternalBlob *)&exForm; - memset(&exForm, 0, sizeof(exForm)); - - exBlob->blob = *auth_token_get_blob(auth); - exBlob->session = process_get_session_id(proc); - - xpc_dictionary_set_data(reply, AUTH_XPC_EXTERNAL, &exForm, sizeof(exForm)); - server_register_auth_token(auth); - -done: - CFReleaseSafe(auth); - LOGV("server[%i]: AuthorizationMakeExternalForm %i", connection_get_pid(conn), status); - return status; -} - -// IN: AUTH_XPC_EXTERNAL -// OUT: AUTH_XPC_BLOB -OSStatus -authorization_create_from_external_form(connection_t conn, xpc_object_t message, xpc_object_t reply) -{ - OSStatus status = errAuthorizationSuccess; - auth_token_t auth = NULL; - - process_t proc = connection_get_process(conn); - - size_t len; - AuthorizationExternalForm * exForm = (AuthorizationExternalForm *)xpc_dictionary_get_data(message, AUTH_XPC_EXTERNAL, &len); - require_action(exForm != NULL, done, status = errAuthorizationInternal); - require_action(len == sizeof(AuthorizationExternalForm), done, status = errAuthorizationInvalidRef); - - AuthorizationExternalBlob * exBlob = (AuthorizationExternalBlob *)exForm; - auth = server_find_copy_auth_token(&exBlob->blob); - require_action(auth != NULL, done, status = errAuthorizationDenied); - - process_add_auth_token(proc, auth); - xpc_dictionary_set_data(reply, AUTH_XPC_BLOB, auth_token_get_blob(auth), sizeof(AuthorizationBlob)); - -done: - CFReleaseSafe(auth); - LOGV("server[%i]: AuthorizationCreateFromExternalForm %i", connection_get_pid(conn), status); - return status; -} - -// IN: AUTH_XPC_RIGHT_NAME -// OUT: AUTH_XPC_DATA -OSStatus -authorization_right_get(connection_t conn AUTH_UNUSED, xpc_object_t message, xpc_object_t reply) -{ - OSStatus status = errAuthorizationDenied; - rule_t rule = NULL; - CFTypeRef cfdict = NULL; - xpc_object_t xpcdict = NULL; - - authdb_connection_t dbconn = authdb_connection_acquire(server_get_database()); - rule = rule_create_with_string(xpc_dictionary_get_string(message, AUTH_XPC_RIGHT_NAME), dbconn); - require(rule != NULL, done); - require(rule_get_id(rule) != 0, done); - - cfdict = rule_copy_to_cfobject(rule, dbconn); - require(cfdict != NULL, done); - - xpcdict = _CFXPCCreateXPCObjectFromCFObject(cfdict); - require(xpcdict != NULL, done); - - // reply - xpc_dictionary_set_value(reply, AUTH_XPC_DATA, xpcdict); - - status = errAuthorizationSuccess; - -done: - authdb_connection_release(&dbconn); - CFReleaseSafe(cfdict); - xpc_release_safe(xpcdict); - CFReleaseSafe(rule); - LOGV("server[%i]: AuthorizationRightGet %i", connection_get_pid(conn), status); - return status; -} - -static bool _prompt_for_modifications(process_t proc, rule_t rule) -{ -// will put back it back at some later date -// SecRequirementRef ruleReq = rule_get_requirment(rule); -// -// if (ruleReq && process_verify_requirment(proc, ruleReq)) { -// return false; -// } - - return true; -} - -static CFIndex _get_mechanism_index(CFArrayRef mechanisms, CFStringRef m_name) -{ - CFIndex index = -1; - require(mechanisms, done); - - CFIndex c = CFArrayGetCount(mechanisms); - CFStringRef i_name = NULL; - for (CFIndex i = 0; i < c; ++i) - { - i_name = CFArrayGetValueAtIndex(mechanisms, i); - if (i_name && (CFGetTypeID(m_name) == CFStringGetTypeID())) { - if (CFStringCompare(i_name, m_name, kCFCompareCaseInsensitive) == kCFCompareEqualTo) { - index = i; - break; - } - } - } - -done: - return index; -} - -static bool _update_rule_mechanism(authdb_connection_t dbconn, const char * rule_name, CFStringRef mechanism_name, CFStringRef insert_after_name, bool remove) -{ - bool updated = false; - rule_t rule = NULL; - rule_t update_rule = NULL; - CFMutableDictionaryRef cfdict = NULL; - CFStringRef update_name = NULL; - - require(mechanism_name, done); - - rule = rule_create_with_string(rule_name, dbconn); - require(rule_get_id(rule) != 0, done); // rule doesn't exist in the database - - cfdict = rule_copy_to_cfobject(rule, dbconn); - require(cfdict != NULL, done); - - CFMutableArrayRef mechanisms = NULL; - bool res = CFDictionaryGetValueIfPresent(cfdict, CFSTR(kAuthorizationRuleParameterMechanisms), (void*)&mechanisms); - require(res == true, done); - - CFIndex index = -1; - - if (remove) { - index = _get_mechanism_index(mechanisms, mechanism_name); - } else { - if (insert_after_name) { - if ((index = _get_mechanism_index(mechanisms, insert_after_name)) != -1) { - index++; - } else { - index = 0; // if we couldn't find the index add it to the begining - } - } else { - index = 0; - } - } - - if (index != -1) { - if(remove) { - CFArrayRemoveValueAtIndex(mechanisms, index); - } else { - if (index < CFArrayGetCount(mechanisms)) { - require_action(CFStringCompare(CFArrayGetValueAtIndex(mechanisms, index), mechanism_name, kCFCompareCaseInsensitive) != kCFCompareEqualTo, done, updated = true); - } - CFArrayInsertValueAtIndex(mechanisms, index, mechanism_name); - } - - CFDictionarySetValue(cfdict, CFSTR(kAuthorizationRuleParameterMechanisms), mechanisms); - - // and write it back - update_name = CFStringCreateWithCString(kCFAllocatorDefault, rule_name, kCFStringEncodingUTF8); - require(update_name, done); - update_rule = rule_create_with_plist(rule_get_type(rule), update_name, cfdict, dbconn); - require(update_rule, done); - - require(rule_sql_commit(update_rule, dbconn, CFAbsoluteTimeGetCurrent(), NULL), done); - } - - updated = true; - -done: - CFReleaseSafe(rule); - CFReleaseSafe(update_rule); - CFReleaseSafe(cfdict); - CFReleaseSafe(update_name); - return updated; -} - -/// IN: AUTH_XPC_BLOB, AUTH_XPC_INT64 -// OUT: -OSStatus -authorization_enable_smartcard(connection_t conn, xpc_object_t message, xpc_object_t reply AUTH_UNUSED) -{ - const CFStringRef SMARTCARD_LINE = CFSTR("builtin:smartcard-sniffer,privileged"); - const CFStringRef BUILTIN_LINE = CFSTR("builtin:policy-banner"); - const char* SYSTEM_LOGIN_CONSOLE = "system.login.console"; - const char* AUTHENTICATE = "authenticate"; - - __block OSStatus status = errAuthorizationSuccess; - bool enable_smartcard = false; - authdb_connection_t dbconn = NULL; - auth_token_t auth = NULL; - auth_rights_t checkRight = NULL; - - process_t proc = connection_get_process(conn); - - status = _process_find_copy_auth_token_from_xpc(proc, message, &auth); - require_noerr(status, done); - - checkRight = auth_rights_create(); - auth_rights_add(checkRight, "config.modify.smartcard"); - status = _server_authorize(conn, auth, kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights, checkRight, NULL, NULL); - require_noerr(status, done); - - enable_smartcard = xpc_dictionary_get_bool(message, AUTH_XPC_DATA); - - dbconn = authdb_connection_acquire(server_get_database()); - - if (!_update_rule_mechanism(dbconn, SYSTEM_LOGIN_CONSOLE, SMARTCARD_LINE, BUILTIN_LINE, enable_smartcard ? false : true)) { - status = errAuthorizationInternal; - LOGE("server[%i]: smartcard: enable(%i) failed to update %s", connection_get_pid(conn), enable_smartcard, SYSTEM_LOGIN_CONSOLE); - } - if (!_update_rule_mechanism(dbconn, AUTHENTICATE, SMARTCARD_LINE, NULL, enable_smartcard ? false : true)) { - status = errAuthorizationInternal; - LOGE("server[%i]: smartcard: enable(%i) failed to update %s", connection_get_pid(conn), enable_smartcard, AUTHENTICATE); - } - - authdb_checkpoint(dbconn); - -done: - authdb_connection_release(&dbconn); - CFReleaseSafe(checkRight); - CFReleaseSafe(auth); - return status; -} - -static int64_t _process_get_identifier_count(process_t proc, authdb_connection_t conn) -{ - __block int64_t result = 0; - - authdb_step(conn, "SELECT COUNT(*) AS cnt FROM rules WHERE identifier = ? ", ^(sqlite3_stmt *stmt) { - sqlite3_bind_text(stmt, 1, process_get_identifier(proc), -1, NULL); - }, ^bool(auth_items_t data) { - result = auth_items_get_int64(data, "cnt"); - return true; - }); - - return result; -} - -static int64_t _get_max_process_rights() -{ - static dispatch_once_t onceToken; - static int64_t max_rights = MAX_PROCESS_RIGHTS; - - //sudo defaults write /Library/Preferences/com.apple.authd max_process_rights -bool true - dispatch_once(&onceToken, ^{ - CFTypeRef max = (CFNumberRef)CFPreferencesCopyValue(CFSTR("max_process_rights"), CFSTR(SECURITY_AUTH_NAME), kCFPreferencesAnyUser, kCFPreferencesCurrentHost); - - if (max && CFGetTypeID(max) == CFNumberGetTypeID()) { - CFNumberGetValue(max, kCFNumberSInt64Type, &max_rights); - } - CFReleaseSafe(max); - }); - - return max_rights; -} - -// IN: AUTH_XPC_BLOB, AUTH_XPC_RIGHT_NAME, AUTH_XPC_DATA -// OUT: -OSStatus -authorization_right_set(connection_t conn, xpc_object_t message, xpc_object_t reply AUTH_UNUSED) -{ - __block OSStatus status = errAuthorizationDenied; - __block engine_t engine = NULL; - CFStringRef cf_rule_name = NULL; - CFDictionaryRef cf_rule_dict = NULL; - rule_t rule = NULL; - rule_t existingRule = NULL; - authdb_connection_t dbconn = NULL; - auth_token_t auth = NULL; - bool force_modify = false; - RuleType rule_type = RT_RIGHT; - const char * rule_name = NULL; - bool auth_rule = false; - - process_t proc = connection_get_process(conn); - - status = _process_find_copy_auth_token_from_xpc(proc, message, &auth); - require_noerr(status, done); - - require_action(xpc_dictionary_get_string(message, AUTH_XPC_RIGHT_NAME) != NULL, done, status = errAuthorizationInternal); - require_action(xpc_dictionary_get_value(message, AUTH_XPC_DATA) != NULL, done, status = errAuthorizationInternal); - - rule_name = xpc_dictionary_get_string(message, AUTH_XPC_RIGHT_NAME); - require(rule_name != NULL, done); - - if (_compare_string(rule_name, "authenticate")) { - rule_type = RT_RULE; - auth_rule = true; - } - - cf_rule_name = CFStringCreateWithCString(kCFAllocatorDefault, rule_name, kCFStringEncodingUTF8); - require(cf_rule_name != NULL, done); - - cf_rule_dict = _CFXPCCreateCFObjectFromXPCObject(xpc_dictionary_get_value(message, AUTH_XPC_DATA)); - require(cf_rule_dict != NULL, done); - - dbconn = authdb_connection_acquire(server_get_database()); - - rule = rule_create_with_plist(rule_type, cf_rule_name, cf_rule_dict, dbconn); - if (process_get_uid(proc) != 0) { - require_action(rule_get_extract_password(rule) == false, done, status = errAuthorizationDenied; LOGE("server[%i]: AuthorizationRightSet not allowed to set extract-password. (denied)", connection_get_pid(conn))); - } - - // if rule doesn't currently exist then we have to check to see if they are over the Max. - if (rule_get_id(rule) == 0) { - if (process_get_identifier(proc) == NULL) { - LOGE("server[%i]: AuthorizationRightSet required for process %s (missing code signature). To add rights to the Authorization database, your process must have a code signature.", connection_get_pid(conn), process_get_code_url(proc)); - force_modify = true; - } else { - int64_t process_rule_count = _process_get_identifier_count(proc, dbconn); - if ((process_rule_count >= _get_max_process_rights())) { - if (!connection_get_syslog_warn(conn)) { - LOGE("server[%i]: AuthorizationRightSet Denied API abuse process %s already contains %lli rights.", connection_get_pid(conn), process_get_code_url(proc), _get_max_process_rights()); - connection_set_syslog_warn(conn); - } - status = errAuthorizationDenied; - goto done; - } - } - } else { - if (auth_rule) { - if (process_get_uid(proc) != 0) { - LOGE("server[%i]: AuthorizationRightSet denied, root required to update the 'authenticate' rule", connection_get_pid(conn)); - status = errAuthorizationDenied; - goto done; - } - } else { - // verify they are updating a right and not a rule - existingRule = rule_create_with_string(rule_get_name(rule), dbconn); - if (rule_get_type(existingRule) == RT_RULE) { - LOGE("server[%i]: AuthorizationRightSet Denied updating '%s' rule is prohibited", connection_get_pid(conn), rule_get_name(existingRule)); - status = errAuthorizationDenied; - goto done; - } - } - } - - if (_prompt_for_modifications(proc,rule)) { - authdb_connection_release(&dbconn); - - dispatch_sync(connection_get_dispatch_queue(conn), ^{ - engine = engine_create(conn, auth); - connection_set_engine(conn, engine); - status = engine_verify_modification(engine, rule, false, force_modify); - connection_set_engine(conn, NULL); - }); - require_noerr(status, done); - - dbconn = authdb_connection_acquire(server_get_database()); - } - - if (rule_sql_commit(rule, dbconn, engine ? engine_get_time(engine) : CFAbsoluteTimeGetCurrent(), proc)) { - LOGV("server[%i]: Successfully updated rule %s", connection_get_pid(conn), rule_get_name(rule)); - authdb_checkpoint(dbconn); - status = errAuthorizationSuccess; - } else { - LOGE("server[%i]: Failed to update rule %s", connection_get_pid(conn), rule_get_name(rule)); - status = errAuthorizationDenied; - } - -done: - authdb_connection_release(&dbconn); - CFReleaseSafe(existingRule); - CFReleaseSafe(cf_rule_name); - CFReleaseSafe(cf_rule_dict); - CFReleaseSafe(auth); - CFReleaseSafe(rule); - CFReleaseSafe(engine); - return status; -} - -// IN: AUTH_XPC_BLOB, AUTH_XPC_RIGHT_NAME -// OUT: -OSStatus -authorization_right_remove(connection_t conn, xpc_object_t message, xpc_object_t reply AUTH_UNUSED) -{ - __block OSStatus status = errAuthorizationDenied; - __block engine_t engine = NULL; - rule_t rule = NULL; - authdb_connection_t dbconn = NULL; - - process_t proc = connection_get_process(conn); - - auth_token_t auth = NULL; - status = _process_find_copy_auth_token_from_xpc(proc, message, &auth); - require_noerr(status, done); - - dbconn = authdb_connection_acquire(server_get_database()); - - rule = rule_create_with_string(xpc_dictionary_get_string(message, AUTH_XPC_RIGHT_NAME), dbconn); - require(rule != NULL, done); - - if (_prompt_for_modifications(proc,rule)) { - authdb_connection_release(&dbconn); - - dispatch_sync(connection_get_dispatch_queue(conn), ^{ - engine = engine_create(conn, auth); - connection_set_engine(conn, engine); - status = engine_verify_modification(engine, rule, true, false); - connection_set_engine(conn, NULL); - }); - require_noerr(status, done); - - dbconn = authdb_connection_acquire(server_get_database()); - } - - if (rule_get_id(rule) != 0) { - rule_sql_remove(rule, dbconn); - } - -done: - authdb_connection_release(&dbconn); - CFReleaseSafe(auth); - CFReleaseSafe(rule); - CFReleaseSafe(engine); - LOGV("server[%i]: AuthorizationRightRemove %i", connection_get_pid(conn), status); - return status; -} - -#pragma mark - -#pragma mark test code - -OSStatus -session_set_user_preferences(connection_t conn, xpc_object_t message, xpc_object_t reply) -{ - (void)conn; - (void)message; - (void)reply; - return errAuthorizationSuccess; -} - -void -server_dev() { -// rule_t rule = rule_create_with_string("system.preferences.accounts"); -// CFDictionaryRef dict = rule_copy_to_cfobject(rule); -// _show_cf(dict); -// CFReleaseSafe(rule); -// CFReleaseSafe(dict); - -// auth_items_t config = NULL; -// double d2 = 0, d1 = 5; -// authdb_get_key_value(server_get_authdb_reader(), "config", &config); -// auth_items_set_double(config, "test", d1); -// d2 = auth_items_get_double(config, "test"); -// LOGV("d1=%f d2=%f", d1, d2); -// CFReleaseSafe(config); - - -// auth_items_t items = auth_items_create(); -// auth_items_set_string(items, "test", "testing 1"); -// auth_items_set_string(items, "test2", "testing 2"); -// auth_items_set_string(items, "test3", "testing 3"); -// auth_items_set_flags(items, "test3", 4); -// auth_items_set_string(items, "apple", "apple"); -// auth_items_set_flags(items, "apple", 1); -// auth_items_set_int(items, "int", 45); -// auth_items_set_flags(items, "int", 2); -// auth_items_set_bool(items, "true", true); -// auth_items_set_bool(items, "false", false); -// auth_items_set(items, "com.apple."); -// auth_show(items); -// LOGD("Yeah it works: %s", auth_items_get_string(items, "test3")); -// LOGD("Yeah it works: %i", auth_items_get_bool(items, "true")); -// LOGD("Yeah it works: %i", auth_items_get_bool(items, "false")); -// LOGD("Yeah it works: %i", auth_items_get_int(items, "int")); -// (void)auth_items_get_bool(items, "test3"); -// AuthorizationItemSet * itemSet = auth_items_get_item_set(items); -// for (uint32_t i = 0; i < itemSet->count; i++) { -// LOGD("item: %s", itemSet->items[i].name); -// } -// -// xpc_object_t xpcdata = SerializeItemSet(auth_items_get_item_set(items)); -// auth_items_t items2 = auth_items_create_with_xpc(xpcdata); -// xpc_release(xpcdata); -// auth_items_remove_with_flags(items2, 7); -//// auth_items_set_string(items2, "test3", "testing 3 very good"); -// auth_items_copy_with_flags(items2, items, 7); -// LOGD("Yeah it works: %s", auth_items_get_string(items2, "test3")); -// auth_show(items2); -// CFReleaseSafe(items2); -// -// CFReleaseSafe(items); -} - diff --git a/authd/server.h b/authd/server.h deleted file mode 100644 index 9b4a7389..00000000 --- a/authd/server.h +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ - -#ifndef _SECURITY_AUTH_SERVER_H_ -#define _SECURITY_AUTH_SERVER_H_ - -#include "authd_private.h" -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -OSStatus server_init(void); -void server_cleanup(void); -bool server_in_dark_wake(void); -authdb_t server_get_database(void); - -AUTH_NONNULL_ALL -connection_t server_register_connection(xpc_connection_t); - -AUTH_NONNULL_ALL -void server_unregister_connection(connection_t); - -AUTH_NONNULL_ALL -void server_register_auth_token(auth_token_t); - -AUTH_NONNULL_ALL -void server_unregister_auth_token(auth_token_t); - -AUTH_NONNULL_ALL -auth_token_t server_find_copy_auth_token(AuthorizationBlob * blob); - -AUTH_NONNULL_ALL -session_t server_find_copy_session(session_id_t,bool create); - -void server_dev(void); - -/* API */ - -AUTH_NONNULL_ALL -OSStatus authorization_create(connection_t,xpc_object_t,xpc_object_t); - -AUTH_NONNULL_ALL -OSStatus authorization_create_with_audit_token(connection_t,xpc_object_t,xpc_object_t); - -AUTH_NONNULL_ALL -OSStatus authorization_free(connection_t,xpc_object_t,xpc_object_t); - -AUTH_NONNULL_ALL -OSStatus authorization_copy_rights(connection_t,xpc_object_t,xpc_object_t); - -AUTH_NONNULL_ALL -OSStatus authorization_copy_info(connection_t,xpc_object_t,xpc_object_t); - -AUTH_NONNULL_ALL -OSStatus authorization_make_external_form(connection_t,xpc_object_t,xpc_object_t); - -AUTH_NONNULL_ALL -OSStatus authorization_create_from_external_form(connection_t,xpc_object_t,xpc_object_t); - -AUTH_NONNULL_ALL -OSStatus authorization_right_get(connection_t,xpc_object_t,xpc_object_t); - -AUTH_NONNULL_ALL -OSStatus authorization_right_set(connection_t,xpc_object_t,xpc_object_t); - -AUTH_NONNULL_ALL -OSStatus authorization_enable_smartcard(connection_t,xpc_object_t,xpc_object_t); - -AUTH_NONNULL_ALL -OSStatus authorization_right_remove(connection_t,xpc_object_t,xpc_object_t); - -AUTH_NONNULL_ALL -OSStatus session_set_user_preferences(connection_t,xpc_object_t,xpc_object_t); - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_AUTH_SERVER_H_ */ diff --git a/authd/session.h b/authd/session.h deleted file mode 100644 index 460e2a39..00000000 --- a/authd/session.h +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright (c) 2012 Apple Inc. All rights reserved. */ - -#ifndef _SECURITY_AUTH_SESSION_H_ -#define _SECURITY_AUTH_SESSION_H_ - -#include "credential.h" -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED -session_t session_create(session_id_t); - -AUTH_NONNULL_ALL -bool session_update(session_t); - -AUTH_NONNULL_ALL -uint64_t session_get_attributes(session_t); - -AUTH_NONNULL_ALL -void session_set_attributes(session_t,uint64_t flags); - -AUTH_NONNULL_ALL -void session_clear_attributes(session_t,uint64_t flags); - -AUTH_NONNULL_ALL -const void * session_get_key(session_t); - -AUTH_NONNULL_ALL -session_id_t session_get_id(session_t); - -AUTH_NONNULL_ALL -uid_t session_get_uid(session_t); - -AUTH_NONNULL_ALL -CFIndex session_add_process(session_t, process_t); - -AUTH_NONNULL_ALL -CFIndex session_remove_process(session_t, process_t); - -AUTH_NONNULL_ALL -CFIndex session_get_process_count(session_t); - -AUTH_NONNULL_ALL -void session_set_credential(session_t,credential_t); - -AUTH_NONNULL_ALL -void session_credentials_purge(session_t); - -AUTH_NONNULL_ALL -bool session_credentials_iterate(session_t, credential_iterator_t iter); - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_AUTH_SESSION_H_ */ diff --git a/certificates/CertificateTool/Asset/SecurityCertificatesAssets/AssetData/PKITrustData/AppleESCertificates.plist b/certificates/CertificateTool/Asset/SecurityCertificatesAssets/AssetData/PKITrustData/AppleESCertificates.plist new file mode 100644 index 0000000000000000000000000000000000000000..e1634ec07cfef8fb8198a8f5688123fe3f08e729 GIT binary patch literal 2086 zcmYc)$jK}&F)+Bq$i&PVFCZ3Bl%GA(VJCPpSE#uNiyHcqWJkGAi;jEvl@3XFjHu-p|F7+LJlxSRtDxKMt%l^CPpr%CPqev1EFV1&U?OmGpkJ8K**u? zVCIbJI?E4S`!Y-RkXz}twT+MTQ$Mc%wrlS}7xT$GCTTUFd7S@u>Z-PNzDYCoJe%MU z9i^Ab^PhcZL*MGe;=iR{#6AGqZd+y02 zDEad4D+`02vR|(M-~A`s^H1gr*1l;X?Mc^~^cPLv>eb-p{PmOcl>Pray6b(f+1jP- z5U)sgwWPf{0ulHiuo z-I8J(93}EiZIZBZv+=$MOPv2yE|~aRM*Ktj)1Hh^=hs;uy?QC4@3&^~zj^oknV1)UNR-JIA&M}gf;y8@$~k|gFIQT?oPM)uNw_e~=6vJ4k5-^f!J zdhW=)Wn65t0~}a{7aaFBzu9_z(@il8@5M{)?y&Jb*eG1nT`8Y_W7n35IV}=T-YSVZ zuC(sB8X6LB?E7f%zBISU0|`erRed{kcBk&%fX&w=uFC&%GVl@jEwpkLpXIOeZB4!-iB((v=5FA=>vi}1 z0}g4KWw&>2I=Dn2-qgRlyK3=mn{Odgoz`ku|6}WUIO$`;^a$yj{ri5q`Dn(-d{Ee? zy;O*EwuYn0^!cAVyfcelS*dRbknPaq-Tjtjk>Gir=+s2hy`OmhJld&nc{_7~<<$pm zH7sXNE^OU0drybo^|dkob$A>40xcD~*UPz0{lzPNX@A3m`MF+S4bvqAmnN%oyt~P+ zdEtuL#OU8%-0T;5E5-7}n3NliiL&P|VB6+8VZ*v5Yxzo9w6!ZfhPNoUtGtOg@{z2Z z{kLLTaKp84ca|NFWV3i%Y1bbh9e|Rvu`0llvkOH}wO`QPDsk1c>g@d_jSt+(zJ5%* zY+jlDxh`5( zEJ44ttF0C9@)X$qc0E>^k@To@hw8iJGNw&RFN0e%>`J$Br@oZg)iQZQ*ZZwfLQneF zU5#1D>czMx|7S$pcb3F=Uym)2cF~Knid?vP!g~mk67pK>tTLvV^6$V{8lw~?$+&Q<|60gLYLZnma7cd-D2Y)9w + + + + VersionNumber + 2014081900 + + diff --git a/certificates/CertificateTool/Asset/SecurityCertificatesAssets/AssetData/PKITrustData/Blocked.plist b/certificates/CertificateTool/Asset/SecurityCertificatesAssets/AssetData/PKITrustData/Blocked.plist new file mode 100644 index 0000000000000000000000000000000000000000..a3eaf9755ae9c0383e1b7de4852a8b2c8b67dd72 GIT binary patch literal 435 zcmYc)$jK}&F)&y!z|Y9U%)-jX&cVsW&BM#b?=K*d@>{yic8Av|m!_X#wy)FYo|+&wH6)uXgQ;FS_U8ayWJOA(DkVGWI{{Gd*H$ zk)8Bi!@8yM1kZI}pdmPf|J|A5$&>#+rvBJRp_%?-o@;+Mr2cP1t>WV!$)kR_*KCel@!O zV@L+6&Yl?V>=!**^wc2{hj}{Ab?+r4fWnhFQa0|Mzhq)`-1^|Rk0yP-ownAHfrCMc u!H~g&A)cX(p_gF^!)}I43@;fO7{wX&7+o1-7{Gvu5kfNvKxrt&SPTGNw5)Xi literal 0 HcmV?d00001 diff --git a/certificates/CertificateTool/Asset/SecurityCertificatesAssets/AssetData/PKITrustData/EVRoots.plist b/certificates/CertificateTool/Asset/SecurityCertificatesAssets/AssetData/PKITrustData/EVRoots.plist new file mode 100644 index 0000000000000000000000000000000000000000..d3a23da378c252688ac0f70afb2d223d40b5ee68 GIT binary patch literal 3448 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 E02pqQJOBUy literal 0 HcmV?d00001 diff --git a/certificates/CertificateTool/Asset/SecurityCertificatesAssets/AssetData/PKITrustData/certsIndex.data b/certificates/CertificateTool/Asset/SecurityCertificatesAssets/AssetData/PKITrustData/certsIndex.data new file mode 100644 index 0000000000000000000000000000000000000000..39729370f19169ca28c0c0a37217f2af7aaed0ab GIT binary patch literal 5352 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 literal 0 HcmV?d00001 diff --git a/certificates/CertificateTool/Asset/SecurityCertificatesAssets/AssetData/PKITrustData/certsTable.data b/certificates/CertificateTool/Asset/SecurityCertificatesAssets/AssetData/PKITrustData/certsTable.data new file mode 100644 index 0000000000000000000000000000000000000000..d78d59330c78469ada227bb3b10635240ae1bbfe GIT binary patch literal 242192 zcmeFa1z1#VyEY6A-Q6*C3Ntha(v5%uA|X9=cS*M(tsq?@h?GcoD4o&@BB7v2DWj{L?k3U z)c5kNJam|GqoD>%)}JRJIH(vL;fmp3a1aquP!J%(P%H=rDo7g{l?X{r6G{vrgby&W zv6S@W)HLM4n%q*{P$CEcd@BeWQ^^PB-~{6~bF_!hlHovvpuA8%C?72#4)$|CUQ%o5k%ayc+!h38c3NM>GF{r5xKBE2 zU*mWziB5f~wra`SUkY+)mv_7s`{wF%E$t{uJ}73TPJMoKYUjtx{M{*1*8c7tV&HC* zhHDBr;P|B6c$Hl>zc4wi2csw~QWejx((tu(fqIzz+MVVu?_pfhVpS~VS?nsk($k-) zswpDG_;DQZ@C}CS)vM-hi#U1_3{6j{^1rh@BiSuF4y9Q8m>XFwYaJT08#U^NT0DR? z*)h)=roqxjR@dtjaf6Ezk=Cw-=m~!5Gp2pvgxpD$+3m)$d4*@&O+lY^ZHFl|*J4Tf zmHUewWml-Ah8M$&`bKQBn^a>_`SkL_R^kP6ObtlYwwCgaK$O*7&QEW0&HG}_QR01= zr>8^pL{PHOd^5N8nc~iduhSIL<>M3L6@*;6eii0o#(l%u z&C$i$u{k%-q@y=Hg=F z0CNP(0dq~Q&0!{BC_iv~2o(4M|8YbJ9{h@l5D`z1Q6M1T4+Iy!0S~?b8PHi&2n~FU zi%g14OhXOBeYC^uTb(exTv@r=tnFrpa#1w^4F*&L5#dFUydyoidJf9wyNQPT8hOSW zg^9$J*V7NTBb9SrdAW~H(50w#zpJ%gW!O7lf5Z{hGCb@Nw*+;~WErQXQXpkVvkHwK z`&voGbY(1+oQvsh`DfpCSyC#FuA`j$YwLD53pU*!Bbbh6ZV(C1F<{kfjqW-4%13l$ zHZ`|MU#@i>dB7o7txrgbP);Ed`y@nzx+h4z83|83OW@w8&E*b|A3HUYe=|R;VY%jH zCRwYF-P%Y9etGMytDEt@w>V2buHQyrAsaw4Fq@(vFZ#&&BKpcr+~|nakZiRoe%ewk z40ReLED`@8bdvfUYoZ=r&ZQ@IM3W(zjF+nH^CH9jAK@UfU`Wnvu&Ko)G2zW^(_Z!Q z(R*8XbNf}CQCcuI_i)wg)Pclgi9?L1h4+~Ch4u-v~y9vv1&X*s)ntqd+{Yt#A&`h>9F;87Jkh+nw^MNw5_SL>m zELha7NZsb+S^i_=3Dhci`_wCB)HvAJ^AqSYw&*vIk{ye4l=|Mw#B}ZP&-yXsKexD2 zM}-o3tD)&j)5X9lMwJ!GW-K1Tfbjnqfd4T7|6>6D%?1F_;8O$O^$?p>Ia@VSw5=bv zko0zTy`m9$9FD2r=RpeF(#I2@6KRQ>W16cbaWBJ(Y~XfnYrYw=BE9p$@DnYBA+29% zw2R&@=wpjL%PRGpX~1V7SnO(Bs>wU%MTWGyQhq9e; zbvp#O<2j%+%W^(a1>8jG{J0jrN{`L&kH~j=XS!&ZJxtX{ZC13O771~BFR+C&TGF&M z*Mqd~_bqs~L;t!!S*qxh27x5TB09y_0`jR<_*Tn>&<@O-+!R6hy&CSv>w2U^1XG_j zH6kyWoJdH!q9n^q+!a$p6s0JnlUMT`xwR6+Kp*iv`F7}Z(vwLm8O5r(53Wq_5(2ae zY67oh=8LJibm(;Dyc`f_9hyMR%2S+K%N`1L5=?qbY=Y3%H(kA_X+73< zGAxJ!X2#l4AW`?}2IU#8lTY)3)0aktCk!uPrQW_`H+Reu`2xWI3J?N90q_f8e-1#E zBhT<35qc5u;f!DA0^?WKfKo#!;gklGh)CJQ2_P}9FtCE72h7F69_HW%C4~^fKgA-# zk#cgfvoxV>XxDeX8%9#74I~e~^J%9e!$q(8QYMTZUY&KYf?d6` zfsT@ycQ@y2{4>KGvN{biv!hXdJ|DQTo6~sTRWMClK#KEU5;&FOO3KURnb`e{70dx4&1h#jWN( zdQWNmQVSOG`Gm*cNVXg|?2Paac1b^jqT`AP39$RWNqDzsd^7!&Kdgm4%4tM)W$8+5 z8|M{_^zV@m{i_qnjv14KnjMO|V>&(%$ju!{_1^PXcQW!Ov|Y|e(?i*0RT`$xj#kBR zvM6S0=Oj?$8^b-Gv>U_aHMcr>g5qTaqIt9wU&{0bPqIj*><(LPa349^YOTK88ki!W ziYiJA&ewVXU2Q$n*G52J^Uw4Zge=?kr^fnU_GwlKq3r;;I&O|&Etr{= zgQK0Jr8Ug;%wuPTFrR)?M6@z67dLl%F#M0T#km55rQF@D058YQ`^UjRL=@*cYPq-r zj*mH54d&+Q=wb^#S9W12gcs0nh!7v#)8`d|^728?hmil%*Y{62vGnzJzDq;LRxfeH zzAd8KqJtz_gFWl5fG_%&p6b20X7sp#_n}EdjRRiz7zFA5!IZU5F1g4p8*}gHh`Oa> zP-S7iG2}57w)bG8%V>E6S6%0J%hX@on9wV_7j?Az*y<%?xGw8325VEPgG&fC#AV@4 z-rCrrn>$4_N0u*%7Bbb8jK~vhw(hr-jeBj&Wx`5)10G@7B64E|Sv!O=*AD!aF9qzE z8hs$muDmqbFpwbasmk0NFYGwCHSqN=?S0)V6UJ(*C~O-_-b5-5igP@NF5@D7-|43L zUG}RbhoOj_ALj`!k=>%J(-<|RD6*bM<74a7NI5Lh>emX_kSjh^I>QNRh~!^&^OviM z?lIVpcEa?zdvK#MzUghKki7eszre=dsPe-{PZ)*}#UJLMn2soB-Z6Bk@RD76MO}{Z zjZyKanWL*-8~GW2ek|)eR%eF3E*PuSjD|xgqgT%DG~DaW8v4LmKEi1a)h z)!wTG;Y#R(7;*?(EN&7g_k+5sIXEueBYPvF)ucG?!J7Ht66(X=k0N7_=dvGQu_6hu zS4yV5JA9v^9Z4ZSS=^D?o>J&-7Ru&|~p4Jw{gILqPmfk$EpD zvWyxO7lM7J$S5*uYDzLc!)!#Dr(^JSb#<*XOAFzL3POY+B2a#~@(EoSLjKJA>7U3%akv>3tl zsvcXfAyRwcTge<9bRBVfK?Jd#=$qno`Y!E-+3BZR9u01lwYR6*-hbBZzS`6LgpPQ2 z;ifDzF9pX7fB(B>!W9r-1s4qH7G$oI%7eYp+Cxp}kjgwS=|-(%n!_9>at6UtAYH#% zGCpSUqIod%Fot#GVH(0`rzG-&T>kL<*FGKO-k*J70>kkin)#BlH6OcPUQOo*^U!P- z)0k1_1kQnY4p}I}$6_0cTds>nSSsSQR_9E!v@jaE3I(vNCL-qt41+AP0Um&&PZa$p2 zOz>AF!-CJiI}Pr9zhJ2UcJkk7n2Nxsf#tH+PKPJiDVJ3w^l2A#*z{+zw38cSy-pnj>@=wJ0Nu*A?njo zXq&;kXWjDa@^8YlYp8k&C))=H19y=S#d@s!dcVts?d^Bfht1ePt7g1gtnc#tBD<0&JJel=Hlo8 zOa%_4;$rROc6y}W4kYK`>SpcM+2q>U1RPCUPDM)Y0>x4>0ZyWMX0~ljT)iC~fLNo8 zEzHLnsti$tpALjA_45+Wrh`>FYixf_0xMek*u&hwnkHS@b|&6km1bR)u3eSD$uxoc z?QF6K^PS_1FfTt8$|nSY8+WJ>5WjAn)y9}x+Iq^-3Y6OqJ);^2%31N$2k)Kvek&H0O?#{9g ziqNr(zFcjwJ|KC#RAN`vk2uHMI`$!KI2T8|Q(suesm}em_b4%BgX*Tf?WVv^F1=d! zkYAdSU40!xl19;>s*_EN4N3q}1}E+McZDJ3LdVi1Za>cKEN`NO_v=}G!tQrXD^ij; zRum5vj6!{6MJObx8?-sULaKr`LziBCOcfRZg`pQ~fl%1DdgJb_V}-*g2*%ei z80W2$K)r(0^bSKY7Tal%>8YokGzUT4kD7zAEWQW#FTSA+?vxDr#YKKmkLJjT-nh>N zm{=try1yqdW|6S&SVo#+ZnrdG)xAxFuO1&`QjFdJ6@r|{!G}J--3je zm>+Ejs-^?#;QPF`!;E*^n2n2y$Kum2-C<%lJjxU%**s|7^)^NuFtmI$@rGSu~q8t&vr>7^k zIq;Dg@DV&22xWpWoFWnt)z2AHuCDGbfFq$K3%>5?=mu6e#Tt0B5CZoc&Y}i<@PWYj z@ZWVA9uRy~w9|VBvMnf_LC6RUAX5Znig!(=vapT8I*FTKV=HxvWiO$S>}+D4;Jal% zGrewP;ZL{nib~EKYv8#iW@hXyq?uyfc_h8hDIB=5!phM~&zqiugwc$&XZ6J@6-Un6@s>3+~vli{$?;1OGkw6Mlgo^p7+bFQ%eg%e^X;7ven>OT)1odhuHW zSt3Bpks!OG80PCM={^L|lV!wD`XS%&zDx;N@WUf{nIUc1R6cza@* zKU@R};wPxN1z9mQ6HR+tlYcp#|A=-LKhfDRfvD(pfkWZ|@8mwc#S5PGduBE;xx^I2 z>Qk{g!3Sgt=~S)|zXNg=b|zQoZugm^Ur6|9UA!`g-0$-AE2}JJVPWlJf9hjG!4TRr zD@JxzqiU<5dxXT$%h)BFp0z=0T2kz|5K za=is=Ma2?*`bek;O?NX`4A8_^w2ty82ME{qh>hOgrFhK4t+-lBF5^`?BGlPjHORH9 z@RoAbtWKPp$E!$s%HibrwTsp;TKu9d%Z90sT{Zt-)q2PmZcAqu^0Rfh4 z5QI*f?~)T`lVX46lD~@!>cyviE)QfFyAhEZdgVQB(ya%kl#=tKm7})^eW3uOdkFZ(2#h;WcsQPDN0TGs* zgBv`=!0iBYgGxfKoFWRb5FAl}fa8x(cw{s*jd&sa!eDC$Ge;LEZm_90*ac?64Q2!Q znYEiM*v{I-l$#yO3}HOOBx*J@b}&>#LC>23WJMR{^nrI;|hYCRu}MnY=N!KpIZiluz@ z?naq{jl|lI@XXX6T<-LrvN3-gMjW1^f1g*wQM{+Y0(K zmC$;iFrJwr-Hv;8!I5RSlbqhvLdI!wq77~FjH0+fT>i=X(_Ri5B?xSpj;cq`haToK zVUX54UBK^u@$qT-&F9-_QV7WS5L_zs8v@)AQGRX+2njj<55+l+mFg;#(uYQq^=3qA z(l!K!Q9c(_yHc4^Ac23Yo-p!R(_tSXmf($E?jln5Ffv-ay21~7*E3}-k1oFV*) zGxG<3Jg)z)3i(%@;T3@h0kFdlr$+ySGyhlP44f4HY1IGX>-=H~e+w#q6EwP<9(N-h z@=i0&&&Rvy>isE-l=!cxbbWk&@@8@OESQcYspwhzR$W|o)W1X1zV%?MT4_EH3?@oF zs(CVdOMH9C;WG(AaxnHMiIj4J$9Pjb^K_s%9WL75#s`$LDIdtyAJPrp*1_jVN5;?# zedaJtBf2=5HEQQ==uJ)By)>elbQvbLu^`^^a3zJZ^BF~Fv!Q}ML%H@s{!be zBV>fOhO%^C@5^Y(Bi4uCy@R^E)A)262rG);NZTd#-I)JwABu&3$3J#`DwY2E?mIDW z9>a`LRg&1nj|@Ts4`i_JzY2_xeQKHRsEAH-W4Lvj)6ejM$C_?@w_k_=0qokz2|9oo zM`v-_&wwv9f9?mF2WK4%(YoC_zJGGRr}9MVB8I^0VS=dLsmDmZh%BqG-Iwl{Hb zgPDP407ByEa+(T-(wzc6kRT=f`SB^c{gFR`%0Xn#n1|TU9c1iGTwTGuU=4RuAf*a0 zUTb?37w>z9x;BWor<5?DpH)Pbe47pV6d#NqLe9n3x=GA*g2)v)xcAXUu~DJJnL+ZfAh+lm)r zCucEuk0VxNrzFw-=GBZ!4KW4Q!|{8IlNd`BEYyc|FqK0}8ES-($&nJJyq9yUros&x z#4`4W(1RPKGr~v-!yoKkH;SmGEkZ2iwqI_=b}oG15k{lGjbL~~_UW>5a{_0^V|`>7 zyehUCm&YhzY35>mkPR4r0J_CFE5J4K^}&6$tzZ?-X(PdWtV`u)I5f-wxef-Vxv^|l za*wIO2Z%fk+7AdSD8_m;ylru9P^LXt6_YPbHjCpL9x zVC&>Ud8~K;DnejnWN>t+GtS-asC2H4SgbJ@t^M0C4P=YtH-g`B6-9~8>bSg&+_FQ5(T7gbmkywGl&#m(6Xq;v| zVvau*_6|Rx8BSx?(KD6nC$()>8Z69@vG!&zt5dbRBWa;RDlv>i`FhdL7R|)QgM>XT zfa-N*V0-JcIM?on_ZUMTvV}A8*&uT3xH8umw#Kc}m^_kXx1@sTiKF0ys7VJA32u#%kgZ3MSX$v%8=6A zXdYU>F(}##wdxS_Om6mxJoB!w=CEr5-UVt_@xIhP1&NQyc2Y@pk_LJUcvBj&)gjHP zIaqgA9H{c-kGz`l93Sf%7V-@D&Dxjnd??L*YEx3nZ7Fcady&>U^6jepU{2wB3)YZ_ zs1I)X`tdBQzPKwL!>XdmbJbnz%17K(H7}uHuBPDVy9Ky~Q&BRx}ZkYalN*Py{K`VbXtdAlo<#R);BT0_xqUc3z1;Wp$ZAa68u z$k!n1kgGW=IZELQ=fY{`V)wgn^8B4h!ix!hNhBbUr}D@ROg?jln33UCMChETK*IqV z2RA;4DfrbybL+kbYy0F-na163}JBl4ADk@;>arR3!g zVAbl?EDdg#nb`f3{HMyZH>i#82fhlL-=!09klGL`s! zx%|T(3k@kpfE^@7h=-4`G~o4%QG%FjsZ}HS2_sKFXJ>^Z(b7oQ$(P$&Y^4XRFM*I& zkgm0tObBGUNP?mopfuh1R@bu@^1`|e&>woOYN}VhuN^1ON_yC7zEtY(JlK@I2BI4H zx>gEpFZUyHLrUwcQh3+3fUFrqv_2thxB`;Jn5B0$iC{ zLC?~V0Bu3n^t5($g#*j4PzgLn>jq@0e#Jjv@T8Fk5YKgmQb8!r@Q3in%(M8dj1-vn zjD|o2dHEs2e8Q*MXg(+~6aeZ%;KP5@Rs2(fNQ$&tXy&!mag6sadW_a{UQTyOw>jf* zKto9b+z9BtkNINu)+ATSR3B&6DG>8|^1f!no+no^^2k0AxqPe^HSO1Jx%qgkp5Mq; zbk|&PsH0+-$f~cW|HHGl;@tEL>s&A296H@oJ+Zl&T1&P}b$!Jj4S~jJcJ)dMa;1LjMRSJ5y9=oI70l5LqV_cVdl5w<SHBCAQ4#^tt6 z#7`Ph=mLyRoW-QoF%DsCH3Y-Z*P1L;3zzhiktC11+G^IIl;~_L#+`Is@pth}jb(8@ zVzy|LJ98E8RW*^Ao=`8f(9F{6JQedF45mp~Qu)AjoxdXb8=>00iVsc!St4I7q$?kn zUZ3@l)bZtLe(wOP!U_zF%*1}t;aTzEfzDpt5s`salBi|D{Sm6P+HhVKu6-DffD{H(ma;YG7r|qvMH+@i1BvO)| zZ807D(C!||((2B^c8IB6qxPCfQoi_prOq97#)|ZnWE-A^n1z&U?8doR?8^q)H)|gq zr+s3+s*3w`Ts1EAJv-hvd@ZD~p2L;SJHzkr&XF-35)|@>Z*?ADr-wrl(CUO{9Oj0o z31k6&yg6-uI&02AhoAy28Aym|7eYE$S-=cYD&rFcn7NMgZwZ6Cx5c=BD+u`89WJqOPt1nlm$a}(UIqqyQ-`{Mk&!{+*Z@AjD;-UTunt> zDW5)Y5gApD*GI{OUFj$Iod%mH#<~H6VflB&6{(q##4K;`^RDqgR&E#i2#@Sqa9GgB z@`Xe@`Z+w(bAM1bHG5N0R^gHAk*X4=atEQ%BT4Mep2ZOzocp{fFGRENkLw&@&9AuZ z=Fgoxo7SyzeSMX~xvD{Fzn^+y-@7O6>2bTN+fsEiyATO78|}QDywk_>1~1%bjv)l^ zS8YZVmRzGE1fHrWl(KU&Bmt%0smk6RuM~XHMW4X=h+G(JhxF2%|w{;*T4C zdP3#`Ch7<*q33cI!5xV+XdfTF%itofN^`GF-MMlRh5erHUSpQK_%MzTj_Djrj9D?` zf+eb$pXe;V^rA(zJo5bWd#QLTiat!d?g`nYU#!+R>a}4*w@k)aou-ApXV;hKaNnrS zhh5va{Ft~^^&05CQ8Y^Wr)Y{CV>E01C;*475H|0sJ^x7=X%z0wBPaaC5 zgrOMpp-~uM5wWS>4CpA_l$$jkFN2w6YKFLVlLW(BC_RogI;e%+Bpfc9%fN>uj0-? zX8>x74{%brj|#-kkpcho;~CDQllv4u>bOUb{U^SgUch%CMR(qkhe?D9FU*C(^K;x# z76=m@y0M68&NlwScc5zbLebxORWInQsu%VH-%rsUNVEW6awLe%uZA#k={{n5eA@B%J=^THq)TbyWQaQlAPL zIg#>>rd%c31S;-?VoIPg1r()7d{DAA9EPyUqdeUw7$6bAb8$&FNYl6T3O z^#b{rgVk+|Z;ki*KC*ksSz8<18bv1_XECmdb}&4Js#7=Y)bQ&{f2t@(0+A;m*F5#& z=A#Rg!;y1r#MRRe5Pdg|K81zLYyUM|aM|v07eTaBC`(DU?C5sgbKhjLbj2@NH%S{9 zyR%6|{QGWo@*3g2xgH?7-cpKgo}%ANnXwYsM`t5TZFi-sf`yLeqi?xkj*YlN@l8Ug z1lWVko`$-jLyf?i7AtWgO0$%Bm zZR8EV@=MLde{CfrR24W9W|r# zC8N>qq?S+V(N3`7OwuJve6pxZj|RVCd)-vRW((l^gy2I}?NM6utWka85mjan#eHS0 z8+PigeGhX}jpb+F}yjQ4Lgxb-l_m+-MUe15{{yr;yEttW@(Pj3z zhI_X-bKI?bgtctJ7)6n|rzEoA9QU<9XrDy} zlP$qWe&aF~M<-oMmJfD;!X5pWq(XfCU3gcAh^dAibXQEH`@Nf|lu`20Fx!oqjaOO-&ALlzKDrjoAm-9$HJ@~rhG`O0tD(6q9 zYO8TiDyqxP6bnB@DuORMs1kDXqaHGEjMdXPnt7P(iKQW|Nom?6n~xZl>zUkp=}hB; z5q$t`^!S73p#D|KfBAratK$EN0l|py9&j2kaxfw~a7MsnAtIc&lAD>MAVPw6ARIqj zJ0wI>S~xlJEF$1D5r^j@I z!JA`Tx&KhjQwP>SFirK6SM5ej`m0^f^c{~ePl$RuU06sMRhqbh&`xo>_DoS)J+JiF=?Uj7|J>`fRLx1!OoSXS@MvnTW*D0Fs05N}ltfR= zE+3Czpb1sDyVIWp0x@^bv$(q}z-#o+cnu&h7cd`=V;3D(mFrNP(-;P@@&K}mlBN`t z8^U!;Ww4o599@8Z>VLs7fbBrhfQj9YMkNq74t)A4qX8UND4fzj1b})*z+r_5@WYV| za8`c}|4mmBj0nDX`==`!AmYF~nb1!=nVOK7kBCIJ`0s&j?W`J)<~&bWzm$IDdG~EA zz}_*2V~`m`pJ^}G>X_|gFZ0{djrktF(EW-+4AG)W1;y?G^%(DrLsXsHuRjTY9wx5J zSRZe@!+$xv%9Wy(hzzDCNE`zc|ejtO*BHM{YjC-LZ@Ow-*G6u8y zV3LBE&^nT3;`d_)CWF#3t~UmVe9`R`b4ZAwe0WLNFOX`jVVwr)dB9Xn5T$NFSMKX0JEnuURf;{DRUrl?6F0&_{YXd=@gqP1HF@6GxK}J zRwMz;hS3KFuI+)*VVJnr-}AncJ5YlKCZxH^tjJ|5acm{0yk1*`j1f8Xs#SWfAP+y$ zqfN%pn-W8(F7sI<=53dIGRC6lQu;`0c8fkj#Bkx*{KUkKBV#80j!}nD(saHM&*dcB zDk`+101S=IanTlf+vxbqtjgEaY_l>VG7r4sp&JCO&mZZw9Ft>xz3a~{y}0oXgTA?* zsQZTH9?L^%nRr>PYUgy1WlF+QN;ZUr^!AB^IfMLz#LDLCmxmfN2uSL4AtMCp1=2T6 zME!|)$3y9Q8&3W{Uyg5#c)wP@XuZ1n!K4b$m-w$2m5HYt0F$RK z1{;LsR4<9>e%Ht!;UloDwTHDU0GL3gO7Lt?9(ZLA@a+l%@cipYKw3-Q(FJUB)`{c; z6bb@Z3}C;V_l07@vk5;lWT$n6fLa3?v9rQuVF*7!OHN;Kj`Dj(?7!O${S)D-YGvj6 zIybHV+RK+J%hMvL|4Nfz+3rKu2mJX~P-kI2)8$=f3-8KeSbpK1i8$j+64C=Dw!CeO z{ajM7mluvrGTypYF{BX4kQ;T?(COG=qTFQY5mXiRD;ymTFOMveMIv%@cEyy|MLM7& zwv}FRG-|L7&dbz)r`$}7=rX6`_Wp7}z->C@YL@gj)q150;@Wjn6)e};5TTM5(=$xX zpE;&K(kmIHfA(1m&=&B&XB(T8#M+IDBhQ@70i7_`@r9Sekv!i9-~q zF00rE!qzX4C!6es^gn;G%6P?0q8ORGR(z0}@n&}d%4R}fXL&DHB(1+gj!EQ<@cbu= zC@-#{@x-nq**Ifk`Q+#drW>aj=u3@m>mQs+Q^oXloKfY@V) z_bU(f@}X`nb7aFvK?mqdNlH_GK?woGvQo30vwpI{H;MCUyv!Ph5Oy^gC}&186A6 zXS`HiL63p?*J6+IHf_Gr?_4)o$Occ*y{(-2PHsL%sBd(5lU$%lVK7(l&^F*@h47Vj zs?Hd`nQ0#K?`(Kai$W$l9c0@~1n!Z3*Uh-&VL!E?qy-O8OkIO<-X@wB<>{zggBR&Dnqi4@Y2liYhB(2dAF)z5U)3}W(!LlXX1+x^Sd z%YDcz-%IQdhF-dMr>KZNbJxBH@3*Mx-|p}?wm%QIY2oe0){={>k9l(I7Z;0Z-eqZb z)3S&UI}3=y-{nkAXL4%JT4xhBzN<^fHmbKh4mZHy&n@!TLy(L1Yn3I zuhy|}ft$sjvPFF{I$?NwKa_3_wi)qeq1{sH>8%e{7#ts1HoRJHOK|SivIy84MIqKG z>1QLNq(2sCZXc)#=-74)e|}_c^&#j|@(1bKqZr!PrrRwVmbG@xyW4cO*n()J0YZMo z`u0BCg!0BAQ>@4>Dns{MIxRV@2o?h0Ve?tE65$X#>;}-8;nN<)QZd`x#TC|?AXbj$ zv*hACXFhq`dDxkDt(FrFeTaKiqpIi#Q;sKZYv(lK{rCJEAFeneK=-Zykf{-b4}O1s z5bX=`MfvL&;)|ztUd_?o+V#g;0a!#tQZnG{CT7+S@NTMetNddM2xwn~drqfQPWd-b z;t$})=?l}|IxAg$)x=V+&xm0iahpGJu?@3(YmT_K>x0gd zyn#m~DMV6L^o|-vOfAlGPQ(`PG@{f5vyTIFnK^}mRIcrg2x?}%MDUwT1RM1T=7~XZ zh29i%3a}W<)m23;rKfNy6iE`TO48@^ct6k?ij+6^w4Fe`ht-F46$fS7??E-M^cUjf z3Pnl$hxePGL1uldK**BWV0CjeP6s-C&0(jHVcgP&Tvub%%*_Q#19-Rbd_MItqgbMg_rbNUOnLGYTw-^AukkXPJJ^*`?J8=nQ51i6C_rf~{ss5`OQHO^djA#+ z`MG=ma3DFEQz!d$@eg6B0I$GVxDdV?2rv|Y5C1Q?!++5t5=zuN(qJ#;`_^vcgSL?c z5+&1~ew4MsQeDUG?H#1f4L01j(bINcZK~sDfxu`FVSjO{D#= z&lU#0tDSr=UM)g`=%-DE386moMgR7J^^S7#;o?!zT^98Beu-B0uG5YzrSwR3X|*g; z`pm{k7qZZ#k1>ycy{hNpOmERGN*q^L=VDkTqdOKrn!hAr+#Sj@7i!) zYK2LJdjsZTt!ZuPaIOx&DldP00RFx5QWPS5rUlTS4(N|Pf2zU1azW3XR}c};k11ea zu?-KH3%t4a%;5dKMw}YF|IjV{Z+?IOWLaOB2pLu)^3R!0k))s8)Qe$coHV|hFcqH~ z;J(pYyUsyY*(20mu$)aVv$342L+(o~@ZW71K zU=rLNLFW+TXG99VCOhh+uCu;Gy)@wc>E<+U$5XkaHm-LM$T)owgnXpH+uDkZ#&fZP@k2c`j~X5@rF$xbL^RA4XT0!mH(CV{;A6LKZ4+h*vKXjqug6L z`Vd`+4n&(21E>kMgz;EfTR?!CK?oYqr-%zeqC_T+TN$SeFO9ux+c_L)^HPzV%a?*1 z!c59|o{<9y}kQjx`%VxU|4n25N5-L5L zN*}aTE<@>`2c_K5!>#OiS@}@6bla@IPL)PCUU@T~l#NcW4F7A8hA_6>z_xhjzS+{# zCHh__k+p9m7V>*k1S3~n^KZ)^if=qJGJUx%aqz}Xhm$-rsJe@7Hu-*`(}z-;7Bqsb ziMiJ+Fq}DInbo8ciX_y*-%1 zKQk8Rw z8PFGd22~d;$<}98KXxT4$?m0nRV5+^z^eFE4zh#q$MtL=1CT^AJEJFjKKf~7~4+GvcoM#;ERK71~0Pt5P` zC_*>JF-FF}=bc5$zgk>##4IP$Lkl}h+ArC@{wgh1yfB;+TY&FKr4SjFgc=&SSwe2x z;X5@ubjSyu*l)JsyA*`{wZhOT^iS zuUK$eA1b(^PDhT4vO_|L#zX>5sUE%1QEIZ$zGg|H+#-OsJmH=y z&VzgzFbL@AOr^F}BMtoE;{}t;L!d0j#?dzCSFB5{->%kR-%)3zo3$&YlU;nx=ygs1 z1!*Lp!*Jgi;39s29-E)*F?s1Tn{U=NB%)?^<+Dd!xqs^M&ENI-7dcmeIi4x;X#SKk0Z&9f|MBOTXKePeROn zd!#ilEqo3|2b)YH>e^(;5|nRxd`s~kGJ!Pugcu<;BUTdsTy-u4Hh4jJR8^g-THuEq8lB>5rt8EYpc5Iroq`!M)dY1#n|^9Ja0aIIkn~X z;#$y?8pq=)+}St$6*!ch@0QS0H*X$ggw_g{cPx~S?ct+3ISZWW`2S+0nQKBr>ORSx ztvEpwedVvVGikkiiGK*wsUGS%1#rEtwED|4FloJ?2FAb(=^YT6b8fSoX2~0Ua5V; z6luLKSzd!GrR5Yku7sD4JER(d5@t#DptXn9&VhuAX)dmMx|;1~*ZDSzddEbNoQ~d9 zN?Wj(q+i>BXfY5Q%{-=QUrydS*ysGR-sdGhS(otbAr2=cG2)fLE$N&TG(-Er0hI!| z*vEwLpU&&8Ooo0|b$EIiXgbakqiJX(!BDt|mOh{6T^lTo~| zG{tFkGTa{kODRCl`zk<0v?GDHwq#STdS^6{Q#g842E|Lacl zPu0m?+YtfdUeGVXy$79XGEFbOGzq;^b8b+HD|DqXa7Zl!>68fz$?%Yg)AbBl;kSF0 zQGht{kGQ-;KEJQGs@L8@mMs!FJVw4lyPbEH_0Yt(p>`#YsOE#ol@Ytq)vrf}8#L8f zIRg5*iTztjiQmI8QLe1cV7*mue3c?}oUq0#z%WWDs>T|YSwWJ_J8OcYaMf74EK%Wo zh@QsHwdgzbw{l;-PE)26v}{yd4yh6PpeS07XBkI^_8z%!(*_#xvaRMY+1c09ysjoe zS=txI4Y9%AkN=dix-%I3aVA&!46a@4h13;~HCZUk#0GiXR@aN^Pf; zyX@?Tx+(Wsc4?Iup zG|rl)3y@2&p7C$=a%o4!;~0tyb22H-8N{j+VZRZ|s}|lU-o-I9Md$MA`?XvKsY+)g zGs@r!)5nH7gmer2uibOnZh6PYP`%Muoriu;^>s2TjGumTfK=l+Zv0wOg`r#giKtID zC8a`wH(x{WD_(2RJqJ3KE$8n`mM%G!tp<0NkJ1=kgw|8VGTxWiV16?UYuq%D%jeK9t+SBdfS8*zww*j7!}6y9BQ{`XN@yVsbm8NQrQ(cG9})Dr~3 z^4mdAq#(QURAKSuuxAsM%cS~V?lkv(>~)Jd;(X^jBckxrlw7@f#G9`PxN%Hu`&(0S zG+u6Iu6v*-?qU*e5%CFo^6Exahf4KFA7(sa%Rg=A|B)v!0c2pu%jC4#_QXXq9I4I zD-Uc*5Y;S8W=(Hg2}QRU>k_s}+7~swdogF|jG6G=D5$=H?0m99bao zU<-4#b$5lH*B*ed>Ez`8CKe(vb@&6oUrsm=x}ScMmIQ~%rG zqt)DFr>47!u5{y$#ncaf4E55jY7B4Wjom77}B>4pIHSc&+G@)i{ zZ`4-W7+_G8s-CT_uN%!i6+n5+Enly<`Qd&n|aNHA-xXtzyUy|OYtGwd6C;8&N z=^M9}UJDx16lrMXbaO11#3Vwl0lygCHf{EE=Rsy1TojL%JoTr39oA zl#ni^JEcTQK#*>vL=o;>pued9-kyEWKIfi$pNkLbTyw5D=bGyq;~U=?<9*+BjtjRu zIIOsw93KcVLA9|!K7w(b26b67rn{mKDTEjgFza|72=bEZ2}(nS39N6Tz$tVK*wxd@ zp-6>egtF?a$iVb0>8`jqC+Oim#!5W@GE*+Le8-`f%VwpL&55SBQX}ga3O5W6sU}~B zl;+JGe?$ovtcuII-9UpVo}>P0=K#TTqn#5sD!uv12(+B`GbJIYYqXZ zg8UovzMQ1$Kc$X=c<>+PeSe_!zrTg_3a!ufFQD}~zAx>7p2NRi+WkNEVgKZ}N-1vK zp!MX)Fhnj~mEo0t=iR_3PWX!c{W&evsm6_5(+4=zNBbo`Ea7@&YjlPAB9$?p>eXt? zYh^0WV|?K?wsu8l%#Cr3h73{iCg(oAZ#TZduZp!P)u*NUfNGgO=2qtBQFdG#o7AMJ ziM6uKXv~^}lH5qRl~=dJapgNqml-cT8TGNGW}N%kWrsPGA4>@zS=?McgoD|QtzUvz zn!Qtve*yLKkZk}3Z02BP}ARxh_+Zbf55)syDXULT*rnuq$kK8n)Gl-WsMT&|Bj5X z-JrKfyD9>l8Qn0Sq&piT{{wBrk$(F=8TUKd<{z94$zo=ge<&4ATf7(>itOjh7~Ewlz^=rABx@N3S6Af z&H7KR+w(KRh3}I{dk0N%xC43C@C?JQ&m2ed;4F*g^fefu`ZoDqQlGpCB*HCnCEe#?y(;04YoYh znwx@_x*tWPA8@M%8H}tkd@ROz`)u39`T_*xkSMP5NTfi#bK}atK~ntkumIrw4*=6$ zDHb$f|0RzIoQl1jnUm3XHbrp0_wt1+N5k?x-^&8DHUjHYb{-ZsaK88Y=6~kYe=^qU za1we23q+5LPU25~eA^?w(`AFU%$&vST{BarcsEQyY-A5*ccNdRp@^vUrZYX=Jt>H6 zFRD-OkKPr;v3M5fWTJv59O;9eNRh4m6z=mQjr7k?AwRmVlQgJPDa*U#n`x>+Yqns& zi1b!7aL~C=4#$~%KvA7~H*skm1qoJsdE_He;HxgI_veM4U#&n12czN-&OWm0u+FXB z(0Lm>Qg4$+)hJ z6&xJ?M#6K6e?Wyngt;NHh#YaO5~h4T*9-T{_kU?D5d;;zdPY?X_4M^BBNY$Q??>bA zVDQhhnM~;>w zHF*UVw=9jSGP>?IHf#k9e+Vk_liH}`9p4;6X#)V!x8_oy?5h^gYr9%B(1h9$caG%JqbNE zN4z0^g859D#{vx1kCFuD8R8#a1Vo~tY2C)xXjDrDFA+2WTamxA7iqv=Sii*sVx?vN zZ*!?%hJ$!Qm_7;F{POrfg5TSK5wAE!!FY9Ww#Uc?sGfYQ^orUueUB5Mu~5YTo{jGv z!kSn8!9dFs8^Dkb1ou2wMg(jEh$et?RQo@Ffj^njeCc|!;*B7UssUrOw?VOF>Ml&0wn_`WLTt2y9hUrzE z*b<)m{N=VYlP5A9Yfz5wLu}9>M%DrycfAK9%U8ulf3x{oC6l0@#W14{8KZzLWt;k( zMHvE`Ov&5~_VuQ&(0=mfcxqY{(aUMd`mV|ORvf51 zMbmcs0!&A`H=gjl4YFE7Ps69Hq1E`X%%7II2X&3x<~LLNwGR3tTJI<*&+}q%{5-QD z6YF}>fn)d}9Q~J}acNn(1Pp0-5W3HacWBJH?lcE=3(B-3WF?a7eVEb`8x=qiXnZJ> z-xg4up7nMzWzrMUHhGoPn3*30KBU*F5m)A^LJVy5q9fwM&@8;wRB!D7T`Kd^wSTdlyON8 zeNdM<8bU*MVh!!u6MLoNWGi|^C7G&hQL9;WZsF$WK7*2@j*Z1b!SW#I8I(3iVqsPh zz5xm$7Gl%X#4ruFA*>g3Wz;7w;*_5?%B*VLyIjLL|pLb09Yv@AqfHkzJWb}w*eV-b0@I$r5(`x3FOvYO~G<802BWEx$;0FZxjhQH(D z3u#1<9#FFRmxuayKek?9-u|}<-uLO z1Tfry;qXN0FaZCxKafWP5=meixiXmmaAN5vqqz>UG^~EGrEcnriBD}oq=+Nq{DSus z^IC((KiK^nc_`;UCl5t@Nkw&c%=sC@fejKUeoQZZv-Lq z^35JdS;78fSiQ%N`H$^uyc@avnik?IZSD6EOYm+kKsUhC_LNYqeKOkndKP*+LasC!gRW(%LOmSpRz+PGk%MmH*voIq>_{@Z};fY%VOn3({)NU4=szG1#VtwKG zVRA(or_Yd#H<%5KRe<=z0f;@!uHp|Pz_O&i#UF@(p#X%|-atntBJleg%=*sv038tv zT^T?WUN&U_6knH2=-)^Ik+86T+I2}-tbP@Gfc27CfdRn7dKtfSUfTryXU_d6FIpR; z<~Zs<>t*Fpuy<3DmCxAX7%>rkcIDPV#?+{=s!d6zcN6~Lm%By6mc%zV)OwiX+{0a8{JTjm9$uQ#{&a#3`qJA^ zTgl1l>TYRcg=z$i?2)dnDUgelK|J*dUtc$JPI&A{)xc=|{zPtXzlM&RB>;tX0isn2 zO;-66jCP@q(^y?7-76DxXu8U51r%-lyS4nNM=o0_nWy{|0b%*GhN^3cocvt~@u|6( z{t#*@_!5o7Prch;ejzzILi^7hv>l`+9@#(((v=ql zBM|-=bzC<`_;w{wUg5g<3l56U7ZeO^!{zCb*Ua&6cmK`m*gzn}&907vPo9&I*yC~Y z*Kte?4`tLHmhgsIztfQ}oZD*;AyrZCd{M1`Yx1VNFi9>)MDC3WNd)?wpIMV37PVto zp7V!blaV~N1;zN4Tc{qx77cfMng#Jt5?8unt>#v%nCB9GhA{>C1^na$u`Q1<6vtZ+ zW1rq2Vllihj3ie@EIrS*>m2cHZlc^iThimutsx$y^#Vsv^RlYP#_#OkpDZo zvbP&5Tf948DkKeljZKuUIcz|H9Pr@a*aRAx2WT<|B+5*UOo6%P$NXUe#$p46c(z6k zPWI+zV5A|qM+z+D%*o2h2CSL6FSBnvAfPqslB9|Q9J_#tGQoZsXi3%v{TE#FPc`4Z zB%A1sPha+PINtloPQPzgp75zb?}5^<6s7A>u&(GM)T2pt#~`rM(kQJa65&ceQc6t1wJAv5Cg;Bv$>)<5rt7azKlHJr&0T$1H;wTMk1-`3 zi{kD{=i+2$v|o3Oi>-FWn$uD74h4D%GxqcaW9nT;i6)WxSCBJ@eq%H-ELu8ay-@j8 z%6)dpUqm}^P}x5`eDyVxrVwRZ`~d3?(PWEzjIaeCaf0a!FQm@3DabG$g5(fW;c?zj zWV_F3U5%31%{+2%GK6bll88)_;-?bf+*vF$xZrsG!^Mqw$h&We<>D+8etHCY^(_au z3kul!8;U8&-|E0W7DQ%)n?)SN5CXpAE-i#r&Jw5urT}|F{2bNv9ZZemxp(YN_Al++WpCYk5gd&6ygfoO0ggpc)gemYZDa1YC6;cQh;1xUI ze|EsXZkMmHLvUTbZUo^3VFDa^@7oc;jX-b%zbp`3zZm;v*%;3!>$GaNvvadVhN3zf zs%Z9Um~;i2nhd>0B=0iI?0E<4{;G~?5-01;t*5N_Cq9VPv|!Nr*YjK3d8dt)oVCBr zT`{Hg9$DZf4y3=JHY@#ti_^j67`$A4@i|YT(UkSoF=cQLwa5`^SsNBQ#vnS*OOaT* zQL%+2s!bM2%&&CQy>LS=#Ls2MLupPu*dGZniLD*SD8z6GQdaW3Gog#MAvNew#*|NH zpes&Ko|F8TYd+I98kCrCUXVeFwvNOWXNIWVKBbB|TiPyEt9=V>#N1f@J#ZH_J?EdUF&m$hS z)ZuM!xv3mcKt@)Qt;u++b)|pK#eQY>z|Kwq(-)C1J&^{e4FRo^!2AG10L%|iP#6#q zIBeD# z$vJD@013mHt7bW#!--H_bel>Qu0*g8`+ad=2^>-4;-~ce_l6g3ey;Sg1JmcBDYrLX zo(rf>jB2^h@YxMzVL=eoQD-kTStRvkbyhx^?RCxA1f?3}4oqb4d}cBj^?s13vJXR<_T7fu!4r9yMuep;fUZVV|wC$@er z=z@fmR(~jWt762UqGmKqw=#3E|4qS^VPf!|Ppw=;Mt!Sgoy&34s`zn`mH}oeXt34rLTlok9!^rbqUT2%6;U3yx^=I;$*K=tYY{_}FvOe*djnWPA+t36b zVgO{gqW0Tl+5~O?GAYj)ro^vxea&3ljKl(Q!X*ys-FpgxYpfYAeLbs;u8X6;%+S>y;;qeh&@h4o!6J$ zbv>1Fc5Ui!!Ph%bz|^%RT}k6(PxdORlg}Mgs=LsQ?i(MXZAjPtIu; zQ#N`3Rk83r3Bw?zvQt+6)w5$NtZskYr_I`Dp+oK-;kQ#4W#JJ+I2u0ADRqn{)xPtU z-*Na#$g_zIrG(8G-H7|Xb^fmFDn-fGp-9z(cn5Tgm+5dE(l^KGJqMITvOP^kR$gUy z(zkIoVWF%vn)rHn6(FDp65JZwKcjwBF)ReB?Slv!YW+Y*OVlrLq~yOCn@c^sZ| zn4tPC7Veu>j%cZaJ*XMcOt%&y9|!f5u_@w_#czkVVx_^*|#< zWE#&fp(0j$lrR~Hr|mV|&>bTm0s|~YfuC3aiyLx<#|;Dsm%jC<{me%N0|0hZuK5w5 z|AY`k0A7e9Vqu9px>}hVxnE^~erDQ)#v=MM;^=$;P1;o|{`9tzxbP;fCMT=?qN1_s=~tyEg%neV=|Oa%h_}Zux!LbULD*?$ zO^NIf+)g}ImQ~a4MB`St``Pvr6USR3@6E-%GFShe=UBx}VY_$iiVWzujiG>2)_F`m z^p!1|gG~P}q5GS`UC+=+yR#}|%xK|q>d&`ga|&5Yc*|yAGv~kEeQl}$zG7(L^SkOi zOM}K(Syz`GJbf%sC-Cdl>vRPL5Or?J8eb*R!wfD>p8q>p{n@BP+ z>J0CkE{VR{I6t4i(eIJgpf+7#1s9;5CJBs1p{w!82aLz3Q0R=e&ZP08a^p5vFODL_ zn~<)5dtkCmgP%v{KkSU+0&#$cED{#ezosw(p3!(XffUIPk_J|8uuS9khRFZ&8~A4< zwnjT57sZ-9$lqp&C-m?(78{%_WzM!5W^!kNfBom6R?@7`%s43C*@ia09t@x1(C)lA zzGYuNdcjPiY!Kul)8SeB$(+Pr^{lonT1y&Rxg&Q%JyMxHk9XLtM3M|MHc9N7BPv^q+ZJT_*G=@lA6yr5U;2 zvq_*8Z=V#-5HCf*=^9e^i7UUx-4%p0T}`m`He|!WuqsVAj>?5rwaIT<-hsVo2-7U$ z|8@A;Gh#^IlU&`>+;=Nf{^WdhVlF3$FQg)j+y^L{!yXo(ZaCu$f0cvY3maK>k9ta{ zaGZ>ScfW7)_i=>yk{H66b*+k%N{_^QF#I1?K(2{Fc!a&Di5VF&?>H4pf#IFy)$WOp-{{mx+6-}L{`0u!K-&jn z@rZt@pvSEaR>K+kfsq^%(F(V!NK7D0mXh9kXOJIJ`&u$11uLFCV z8(8qdPF9{k8umK@3_KR1iiy38i?gZGJu?;p(9NrP6hp#Z%*fQ#1DtvK2I0R3nzJXp z-1#fE-s}f!^$!#e55OjKZS@RLO|bptssjE;+~uDl@@7Zl8~dNN*iUZt-poDmm(pA( z3&P6pBo&3^4c=dQAeBkIaU6V0KC5cR;c+)BWI3z=y!_7LX9Z?05ZP)GzPin#Km6GN zuB$(flGpMnM~#d8^Qb_qr5eHK&_SPbnjYd<`^_P>*WhEr_HDF3gGu1M>&=RC0AWtn z6J=$~8HsVTcC3QXu!{RLROIWi*}L#_hyt5>-aX!5%IH<{9vNFHQNkJ#hy_G4JQqzO zpD(@>kcvv%N%(wSkGLiy1BA%)dOytni;Ug?>(&EfQA&0wb!y1CDqaUVLA&y`Ct;92 znQu;KRBR2?n;BL$i|P#Sp1tn419v;>ws!8m(X!T6L2Dq+xQM zd3Z*9XUHYexr$q48rJI*lxyABr{xnbjwj}@`c=?xR4B%3^ux*6ZWw2wZ70gC=b2j>MV6Q;8eK7% zcM$R##lFJfaJ8l_vF2`buT7dBF!*AhL2YCXUcg)8&5*@%GkQjisP0>RFktKRBw*&sZ+3VSak0h{K#vTJU@uK(iSfUQu;BDgE6h!7BiiSD*_ z{Rx6`>j6X8%v@XeJK*jH7P5vJQ0aHFBNa7rFk`_4NWB5;hsQzyZ<4Co-?zJF>Z+GS zkAP5`owMsb7b`o9@7N8bKl4VCgKmS*42?zb?JSA_>&9i3=esnps4xp1h~^vlFbX69 z@VEu=&|e`~Ki_Ai|Mx!eKMSXN&8I%Wiw)IBGVNvW zVu{~_ou8w|RpJ!JxOb0t`yAZ|Gh;bTB=y{orQN*N`HtiZ`C(SBgs^IqnyG`2VpHQ` zn6qwj9|_Lv$%#GpCm)N;!=vxwiVTao+DgwY7WT4SkU%(in-8H=-gxkd_;5^4rs? z6!@WM+T>51iIOI?>p7d{wl|&>ua!C$HJLOc-H>dXo3KY1I8~OUtKM<_p zfK4e2=&?$=>a%(TT_L%>!a% z`PNVXjfH*LX>)lrFyVb`X9N#n7NC9!j9Wm?iv^r=V!OWiUwZ97l{ViDARsabK05Zp z&OmySYE2{rGW}XOk4g-uld1S%V=$^n)MBpev#)L z^##zUeQwW(y6vmK6)1)Ouun_$&Ke49 z>!Bk8}pLy@8j^Yq9)&?(|xLwarc$Q_0Dr$y|r2=h1lT!%vdo89jp%HNdahot--Kr8( zSFqu3jk6OqOldVBNcwvmsERdReITaXVeVi8zIK;l#l-u%(@#V zd-Sv&w8ng6W6Y5(?~$du%hXR`*1tXAnuEBU>;a|=Uw+kTGCcxK0bW(=moEo;J`h-M z2%KVWsvGbtzJ9+UNkui}q3#<;m?Aiw9Y@H3rtmmXOQms`Y%)ym3D?;d(^mJ$h*U#_ zjq%U74TfFJRuwy&nd*^{N~+87@-ZXd7`tz%TW=wb3bpgWf&}CeYBQyw$9$+|YR<)8 zf5vAcu+0-0nH}iqnZQ*JQs79a#8mTHUKH6}dJ>P&BC7*m)NPBArHGe6{;V4D5n6?3 zt04pT071Ua#Yf~1g(QUU>ayag=S)8M-OjwTobmZRmbL3_iCpE;6~v z0nezPn^M7HPxd~t8yWdsWm?9?Tw!>1tH-0T2n|-<+D3yh0fsno{G=X0F#K`RsVDXZ1w96w>Dql&;@;YQIy&ecR+5XBd8)I5kH`Bq0O1|kyPfFz zju@2%i&t!QVK{e(wyiiWTv6^GymnmZvv$sbmgC40yV{)zw^(RflbIY z2Mr|neh9k?Un=N`+S@v~0s+pqwaGW78zd}>pLhRgMFC_9{vyI-p#@Q2MJ=RPhyTJ6 zcJ0v1`T?M(0baoX6nX66oZ$6MP{99`8~xKN=Km{jKte#~20}3d;WhnlEgZikGk>gP z{&y8PXn`SislWjMk01$w-<#JJI07LNK*E1@b3o#9{JjLnw+>*itcKAQ`MQe-GcfLL zotZ3MZ14R)qRb%%epDnd0P6vWCyOhKBZTc=cp6UMg^bj`KTb$U7%7kh02}_+RSkj) z;rSO%Xkr9rQUKN{SC9DGJO&PQf$|MR`ZObrCbN$lOg+q)!0TFb6ZshCH|H`XPK~)d zUCMH>kCl(Yl^`iRnh01=mc=4u#Nc@X-)i?&k?K#qz|kX$Bw}smW-*r3>t2X0|3o45 z$v`trNlzoab@_sC!0EPK$NGBq{RsvK6)HNjNm+O_%PMd59IwdQ{EY@qK%;TlR z8g4OuT#QUmy0a#|A06wcgywOgT*U-E8dr!?7DO2YO6;5J^UhH@@Rdx;+vlnu2`ITk zIzP-K@5>9@C)Onq#%1(PL@Znn7k+#TKwFSDOXwq0b*gd5b%7#MEU>!~NM1^GPeUSv zQivorVj1Ei?r!*@+6}gfiQbVO|8Q~P4)hFKU-b=|1Abio%8#SL`zptKy~p{Wv1b+8 zzx9(W8rZ9QU32Q93M}BS2v|HKA`7V4n^>8Fy9Y&$Yyr64yqD_a4mIi9c-wT;3lA1`im5exrZc(;K!#rvG$n@AuWa@3|hhcmcF z4Jc30S_svb81jdzp-attJDcsUk_N;)_5sHCIvG3gRPk%MqMmTY^&BIOZ!IrB?8!a=#pLDYWY4Np&h4eLk_5$hfLfoEsHCan;HU`BrdOi#O8SJO zooz!OeW5gUMa9EMiGjei@bDBmW7LA5iv65g!vD_y;fgLtj)g3SP5CE(QwT>-N zfJfi^5yJs|#19+_$u~^JUpN#KBe20;wj!E3m@tF1|2h~7Bu^kK3vhq904(DGJk}X( zz81j2b}rjSmmA<@)DMX!Q+rZCJ;VV(kpKcvW_Ezc6QBy@1pJTmo)M{-qUi5ZO~Beg zH=(*tJWej!hyP(w|#Y5h6@%S~O92uk}yzj%7aZ-^4vEAnTIpG$P zw}hZ!v%|NBj6d*Gx|ugq)xIKYvcKTbaCzz33z^uOsI*qZ@Tok6bX~BYLuV9ko$fpc z3r}b#%-Bq4oY!#Oi?6PC+>aBAve2@P1*aBdw&_PC=}|t!vnb+^J9ZRLekPmTtIc)K zn`}~ga5S1Th$k)j^ zn60@kk@3F5bN3^*LZ(L11Q|yLgmS{oC5cHZpO9-gKNoXupzw%Q=c??Y_02`wr{&r8 z)umx|;3%H1>v1(dOOxf1h`wc?CI_WT# zzd2+8S7b*Hu^?i-@=q7jd_yfcLjKXZSp%RnXiO&{J6 z$dPJX?<@Lz zn2AXEn89&jqP-V&vDNMU@1L%Z5L2ilvO1n48W9gc-Djti|0!+Qm3J|J@`twt&G^cO^(yDU!AH|xwX;l zM04E9mqg6%6+}1@Zn_f3u3Ve?uFd;MUX=BJQjPfG_XML-wIa^Eyq@Hia+mRJ$2$7I z?fEU{|C_)Lhrk!>Vf`9>t_(G6g;3nb+asnAnoO)mhXUGg#yx$JX^Xjt3BBEv6Q`^F z$g^qhoAt7$KVwoaGIV>5TNUN!-ZGw|6y&Er)r9;^aht5W1XkAV%k~bjgz51KwT~_h zns}$Kv3`DPTwJXR9@D!L!}KImo<~+cNzo@k zUMmu#pmh@B=Tt6@)Qoj*-7;eE$leOA7Mzxwx(xxEi=9RtBanP9@Bj%rBC2CU7&IaE*}>=Ph=8vKv!%jBAU{mc2&Z$h)s$V5NoPp>c}F73}ruhc3o zBQ|bu5*5&Zaq3=c9F+}6i9e;$~MMeX28rNP# z?QD(8BzM3>L*g*6#w@?x?P!nS#I!xmnmoL(d4I&PL0*3*HTYPUoBzJ_qIJssbsF`$+|yItzpI=dE=3a)w)xKoSi%Rm5ymWXmxmvHepPOm3gVHpiW9mlsQ% zIijxP`w(f1OA`Yk&@%3x%RaB_UNDiyk1ZL^J1)3cBn#HeTRUr;k}ZqO3WK#HH^gowULC)LKckFG4jYadCAmatU+La#d<6eFk)kcBVl9`vO%M94 zeQepg*Oh$Y@Tg&KX@1bZIWEkn0IQ1UCBw_c5u1U7r!?DQ89vIn_DM|mzJvz=TWs_z zL!bNR5~_g^7>4&)Tc2^?+O&I&^>&B*XfG3W_nal5b(A8JS;f;TXAdnzJX$l5UY6{Q ze%7iF6}99%<=rT08t;&d(=-CDdb4KO*%}c&{uKzxKz-5^jKI0R$;=fl2_RT?KQU?- zHr0d@KAnC)^67N#t1@@ZQTY6oKLRs>|CU4e$8i}-WR20ZSltM=PkWP(zU1EPKI<|N z-c?uzljTu zWciDGIbSap;d*#7_qCtTl4;^RdpK6U!io?GeQ!eWM)#-smk_q~Z_kuj_454kSQ1{< z$a4G9fH*EP$yI7=cCZ~Fgy^Rwir9Vi3)DeI^bw-PUu(i>j%;cK45a~l2D?Sn#-@R| zDlcAf#8Q_T+RkvKo;lBJ)`Cg&M{{T{ZHdLbAC>*d=JB4H#f^6;@*e369vF##2rz1q^dM0ZWE1cMip(VGpj>OWw zOx*V-fpjp=CMC$}B%nFG4ZXuO)#|@dKNa{^$E~fOw|W#}FBf&8#7^jBCaY@r?hBj= zu{Jr5(@~_4c*n)&;}jJNBZMg}c1J#&E--bca`zD?s)pb}2>W#q>Qi{QxQO&2^D&V4 z1k0}iO)i>{+;H`|xK<`zl5?)Bp@yYuuv~++DirL+d|E2q3qAN4>2?~w z-7oZ?J@&gx_Rv)*Vk69ZpM@2bY6F7MO)u~6=s0^Z-~|Tg8#81>nN>D+(nI)moI$f` zplmOGeyu0|mV1z+rlNKDNq}_WQU#JR*wf%9BkgM6==EkIKNrlO7pihfByz z6^Oq0!7Kq0rbYimPv;Z*;_ypPnJ;r(5D)}9G#^HvI18|bKF;n{VxE{QW~=jhTAq^e?SX) zv0o(6orN%vD>?Fh#&q>j^-!sks6)hQdoUkXq3@$K4VC!M4sCI$ET?G}dh1Et`UaKG z@?kg@a~W>v#-vSZR*9kzJaWf7W!mymVyc=3B0=DKaT$=q%D&2Dr2~1a2Um6k1>5z@ z0|SX)vmp_=?*;?F&6Qm3)s0L61?0;Gu$d{#Ef799s|AgP`PZ)RL^oGpb8r%horMSZ z8w@rFE8~GTL7eRD+W)T0{3&P|&=A2@eX{a+Y)o$Fe7ieSltj zT0@R2XtZt@I3TSyuT)VfLKg6Ivb1Kr*SXB+_={?YyW|-EC zw&TkcnEn#DJo{0%0+!AGA?NF1EcuIOX=HZU{Px?8iZE)M<*(Aeh!dOQ%&9>}Lb+A< zXA6p0H83|?isGt=({ULAJk~GdTl%rh61Zd@!R^8f_dE%kLGlVHE$64}FuUVkv-8fs zd~_`3$()oEC)ji(p;B(zQ7^5LzVbsj4znc>B^vQs9{t z^2DnU$6n_;LEdyqndu9m&8wg#5Hb-cOT_&ixCAVG%MeY00^WiG#=a>QG-*OWg9181 z0rA&TKLH^G0YSom-1ns-ELhnau!YOG-W<^N2B&?1z9JVZ7ob}AcOu}w+sIFER=iU9 zX1?|!7*nqJUEf>91-JxQ-gC)(vK}z?*l~zzU(ktuqJWn&eZio4TJ2!$CATXfXw`{|L%ZnsXQQ;{crIQfxr8n zOCYX7Nfv|b=a!H5C+2EJWn|q?UIOJ?cFQ@^oYvjHSnk@yhjOV=q_@urM!I>pt5ky6} zQ99;$Q@Do_{-d*>D%{%7xUmY6=R~aN?GE@h{i$b;^2Jaxwbitc#!-|dJ6~jeWcKge zU{&P6OlE3bxY#ETQ{vA2Xs+(Iil&tOR2f-LN(tbFXwH#AMkfkMku5xM!iZnmI8K{> zrdJ?Wn*sI08KP&J9D40^1K-6MBB7s*v?-xLt2)rSDaFI{`A2CAxs}@dl|XdA@BSCw7^6BX8e9<=eFr+i+mkU1jpRCvE<%r{Oz=^h zXRR8HB^utl&{u5wGzs6TZn@i;P1bK9-%9gn?&iyJI+|A)5qR;BQw$Sy$%nM5ll75c z;o`Z7d964%pJx~m#js9CBfoVK@Is)NhP*G)!8^zvnR3*(KxxEQp>=D~Zh}jr2IV>C zGX6vmI)>MtpbpQUVA0d9tC zfSBu>pnu0T{uBaE58N~XeLch@Cjj{5=lSk&FFDq_$GvIDo|OIcOtc1iUG6sgjj(A= zW^*3eMp*ZVbnZ3ST5Dg&yp;~a{IXsDrEnUw49d6LK?f!Iaovx5MQ(Cnr}oqH}Jh5hB>s zV>tnPG& zbZF2*zvgJObb95gRX|F=yXhbKt`^V7mQmqfieOEVF?imA~&q($|Rv55H4j-)@67_s{NMVFUNq z4_(<;KVV;#-|P!wQSw*&3W&I7V8W^_k{~d9KTymR6lT0avPu9%RHWui01={zrJ0kZ znU#yPvj7orzJ& z6;O)=now?naKYDr{%z0YDvg~5sAIAMMa@g-8q4)f(EqHv{gcfn#T89Nmub~OHdYar zq!vzX~?oW#FB8}bFjpByD0X|cF3fl3lqXoYJ#vQ zYuhB%=R*w5tl{b83T_eA$S`x`Dhk59-J7jtZk0n*q?g(Q{?*)CTmD*R!7SDWYH_j@ z%M__W!JbY2`#T1t@P+sB?jbFz6(+ggfXYbTqko}!6^Gy(B9l8leM(;I87XTmB{lh^LpjPV)3`(oY^$PPyl%y!2= z395o!PixRQY-mWr(;@0p3I!zyIk{G$=iraNPsJ|Z=J*hTTR^ia8YpoON%j28hVjc4 zq+QeY0NEO;#=FGIt{kt68i+{>u!A5LHV6{w4y%iuy~N`@;|fi2YKoM0>(^-lgdc|9 znPzWoVM8-;7o}i#MInE;hCh`=71eGG??#S3YG`S+WPvl?q(ItN!4uBCgvQL*f8Lea zp6z{NkOjxuiLU(ujlyeA5si}Z)e+IV3T9kwd3+?2NtN zyyTyZ3my8*cmdXv^18C?`+!{=T-h}Yfb6UP)v&L(21|*5@0~})LJ%M-^vCYY?%+!^1>omkxm9*R*BMy;0o`Q4Cb+vD*!-zA z_}_i)KN(#v%qy~@$NU;=R8FbY9&czD7uFK}%ga9KMAOrzn$BnIZI>ay+Ro50y*AD< zKCcR!#@yuIyq(@6Ob@B-6?T7&FsA!ueOR?M!m9HchET!CK%a3G<8lmAzT)UJ#deyF zqaw=Chp9<~&n@Z%k;hL?m9d!HZjC!Q?8UTT_QCb1E=={YdES5fX{&zUQcOe=YqX^; z?}fhMc}+g-S=B7O7StQ9n~zP7o|?RmMfTCFfb%?fu(A0D`h|Y5fWZaMwpGI^52uss z(0ygOgWgz%dj92Jauq=mipRHg;ZtZEyY6hQ+J)S)Np>+|YqY${vgaP<)_j%`tw$G9 zAQ$_Nnt|aJI2Q%uR}*X)y#Wi{q`g zGmKoc7O1LE%3M4!T01f#>Fg!v6J&WbV0YR*FoZ2Rx3|tyA!D++Y0gg2 z@0v5o5fhXX$ajsjB!-psUa&;4LC@3%c?pmP>u*=6(-eGqUoYgy)!8qBnoMWeLY8QZ zGb1r|G)#XHDAQXaFef_`3(SiM4}&4LK#2S|2fuu!(@G^z#A6W8Ah8qmutnB=d@fng zNiLzQ|J81lxa!zad?X}DC+A^Q`3GA6b4tgslBR~3V&x>6LZzrBEEfDVdAZD);!5lB z1|C(%K2J}-*jXPU|EYjiT2yTq=PU7xC;m%jU)Z@&Y5g7KO1VRrGW;}3Gw@z)686*F zHmD(-T+M+YI~|*z?7#9F0cD_olHZ)bZKSgynAEn}A~^72*u zyF<+L_D^I)zXUhhUUO6bVE1qQqg+fZci5Q#npl|FU##siAsqh(R5k%kN;iCJvKEI7 zOZwaZzt77_{!RJJaMBl5ZF~mg8z&VF51ys_+43q^(#@>C2?nTi(E6z$;}q{58elKR zyR=|sfbJ-Ms50y%+#?ft%=Rf(hQ)vG$)oSs-}lRBBP zzP}_IwTK~hr@6E-NW@t=qVQD#?a+}aA)?$!Lt$|y-SCB<-?Yz0`8J5MHF%nRRL4C? zed`HlJJlk_v4s@TqoT+!n-`ut52One{r3uVr4yJ8U{m;%h2IZWnG8XSzI+n&F2<1e zK)b5S>%}xuEVt`!0Fn9ViG~AbW%C(LsUzhB9jtR=KkX_$V0~Q&Le+*PGG$9 zPw289)u}X3+*nMH!o`N;pysa2bb|sCes)yfn@zB=RXl8g9w;*t09$wEfB<)K&FTEL z`)a))Z{~8}-pPjL2X)n72mI@@ChTBm1jHFY*E)DXa2ac`0pQzfNV@--x9tXC72)YZ zBwzCbi8)yM02l}|Xk!Q%jiHT79y!76+wbj|xt+Q~lMfysNdTFqo{__pv_37f3)#~R zq*}`H(c>)^Mpk3Y3Ad1f&)mIcZ_b?;gLyv5N*QC#z8nwBGT`q~C=-myR>W9}zgyC7 z(7&H&ov6On@~?`wQ=~VHI-U@q99p%z&N}69j@}c*=>vHf@fG$U>CSb2+pLk z0Lr(QD^e`7zuqBfWnoDw43I^m^WFSuX6qVQ zc3%1N=G8JIBWwQra)4m(Af;4|BVGG=0=q>HB4L?AP*Eg+2`of6VWm*o8i=$g#fYwmUSUi;j8?okJh@9#1A z-uT{lp7xrG$ialHd|@r#;hEU6N7F9cSu%a{Q~@V4*(#Xa+XvFNj?q5G)rC3wZCOF5 z3PwszryX0<+%ZeA%ka_2?X<#b=e^otI6jVR9L@4h2>eaF+=@@!SqNWNc2bHbtEZ0^2{#wgQ@E|Cg@PeMNdEN+&C^B_A6mQIG_ zu(r3_w4TWV*K?3M%reG%IzP-k51!CWC=72JvzpMFr~5sKdEAAFCLf#4bl(KEW>Aql z*CkLyBE{?zuD3%{;;xnbY1#hVDi-qRMd@#WsB(ceOX$;PNyw1|Y65tu9b=P+ZNCdd z{pA6F5r`rpfQ_FSPf2?eY6c6hK{gHWR@0joG~=_n388DWh97uNVwk?-ID2~`UiEfT zjzzXMdQFt!Rprxx=_M5p$FXIySjZ{0=Sh?%$Khsub17W?dFS}QPv|CThKLXyWB9N)%K+F;HjqFCv{flNMSz^@A!Xy2uN)+X$R z7_Pp5(YMbe$&kVAv8v$a7M%Cg-(057GA9bEswpqiaqRsyWcGI}706BB{f2n_H!jt2 z@#U|hulqo%x(nz%Co2y(sh}z26p9er1KV2F^Q{&%k6=T7C>kP^7{m6e%a-x@!?ibt z=dSnOpW~?AvBX_lkpGr_7RCr+OArJ z;5;iL14TjZ`Bn+OFGR$FJ%~~J3XRp;_I>Tv(T|r3U1XSdxCk|*zwQr5kRL2I1cCgT zxzpx3;@iJu&$_+--v2{NVDz5a$+&B|+SpvYiKg^9grpF?bjF8fSl$;}LXS2!Y*1=; zQub9wB+oN$3eZW{ zPS?y*2dUn%kN@j3^+(czyPo~A?PaSbczKqv+ zH6^npfX0PZvq#3tpXdADZ}m-#f9+?Mx|jMg(;4eu$j7URG1QlNkDqK5M1THL&0r9f z>(pnohWB94gCmt%0w^5X@c&*$UBoc8p@~Vk5X8j4v$OJ;vP5^T(L)XNkUk-IByj5e zcTPi3Ia)HY&$FB#AIEPnv~x%}BYoEl7RNitjoa3*SCQ16dWmtd?2=j*RS(XiJ}hyfe1V!xW&y-D z^={*v+Q7O++9GBq*TnYyshfT+NZ9TFCa zim9=y6PQZ@=()9ZwF4*h!BG!zO$&hSaTD`k12Z>)fHo@jnDnb>#LaijT3Z4D;C_vw%&& zj(h&akh8&-M*XeEc1w%;CF|#`$yXmK#$V;SEW3?nndA)DUwAY{^|Z_buoS^T(ih=CaE*zCnhhx8qVRw zD&wR-Q|^|{BkTTD{=K*DjlmGwZlS~J*Is#_t+BJh$wpt*{p@v*v&k_xN?PYz)d?n% z{>?8-ca~1HmdtM82zBv%QE!(}2Wf{+zSj?Ldy*c-drw1P$Pe0I`AC+xS2fV3~gWl(XOA z+=B5b?I0Ud%@};o7P}4%4k2QJ2~6|~BxymS{QMQZ@7mSW;O@48aM+QR0J@ciZOJL2&ZtrD~dsZ`Lpp+8kO zXo?0J6PQB5mbQz2O@qy{(|*Dze!A7!oGFY#@jm9qeF*bL$kP6K#|!PxChhZa34`y1 z79qoTXyEotA;ZNOVNG3?TSCxD$@Fck(QHZ(h)VY}@!8v5vz&?cUe4?k|EP3(AJaVZ z2A!m-w~J3Z$l$(uY`z+J$#4qvZfxH6Z>$3G_0PBS6JD;=S%m17%bzNP{r!OO5a-Pb z9+_EOM3PkeCM#`kXKDS5*W22VRLauR*3^Ym#jrii#?Yg^+_=5mxxE}{%eX?5!+q03KgbH`AY|-;9KrI^HtfF+r-zw=r{IZNdd$>;Q;4 zKu~~%6Bq&rtU#SH4-hl|-~Whzw^rFs4>BC&wK79zonYbi&COlD%vd;&cdvDfTf>Tz z2vn%v*LPC4!!pQ*j9z@w(Xa8q-B{_GnSZ)Yuppmf)no8zkg}R=W0NBGimv%QEE?G) z>7LBPKIH8^{^S75EVjJ@gox#} z%QtxO4skqeBhKfgR4|E&{d zp3>R8s5_1y%3>;LLc0G^eBA-yPJ~FEeD|MXG5XCSuMT`txWF}!JCk__*9w!{Yc)3| z`MXHTUmkEr>)aS+pcN!JAxXFCfR@7Tlg)|miqP8@&Y3qT#KkxroD-uwJNqQ$dX)k1 zb?fB_dSXz%N>Y+kQcgvOt_M2Iz8+uyQ27;CTVQU!>wNgqhVB$cBHe77OGN%}_6fLw)tHE2LfVM>eG$}>y6EP&cS#O>$^9in!-5@Ai@ITTz8r4B$* zgb3;j7fN@AX+004JWe9gsdrLuGa(t>{eX{5_stx{Hm4Jm)-dF2SgrPoKl zg4Z^531oToxCi-|`Yu(^6ZYRwe`VhZSBVbQC5U||=uLh)9{M3CA})_#ncXN2f<#qK z#Qc-IL}Wd-I6q<>?kn_+_{7m+P;lSed#9R)@JIM`7MC-QaNCqTR%hR{i@2G8kf5W& zIufAEUAg*PlW6dW^o%dyWT>lY5e~g8#h7^9mi=%is<~w=0PD%iF(-!Ck0Y(H;G@&s<4;aJr(u01$p5GmPRjO+nLQ_Lg;ELZv zx>|-d9)_A@PHub{DEtsswqA2|XuPHl-FPBQ=6%5|uJMswlR?Jm_qDMo1%gi<>2$-n zWO+y0k4`$JGs%)<-YApCIVG9(o_q-r^(JqM`_TxQCpo*!C-lShVe&%>laQArhmq%S z?t>fBnM5y@v2ze#-$aTOft;%FZC;fh(EC(><(Gi{fB$9{z%jg4_?)V3Dax`pk)VG` z@BcoDH#qKR@lxOX!&N*14wGXF=S-5JC_HHgSjPXdzp=?%dL?B%)&nmhGbiV zo2i|RWqX?CpKJvwI58^>AVRd4TayC)CtNr70tiU4a(2RdwO7W`;Y$|=;Ef0&=UhHecXeiA}5lSGdLd;D(qaK00J zM9KH_`)S)!$vC`ZcgKlb$5cw><5jWYxxb*rm3tUg|?Gc7ca#d;B z&ll$T44$Pod4z>@r7`|MlxQ##W-{)ihs7(QA7j%@VQ{FAwA?!B+<(Ldg zp2Ad|a%o$F4}wxnRdw=kp@h!t2)KfFoKiy&)l$`Ii_91XdDUOD!%-E(mqm7=A!zla zCJ-&Fp4N%`TE*LkTFA@5Qgekup;mtyb4nbrcAqk0$x?q%qW{u;O7}SQf?)D(mH#el z?NaDq%7ImST{5;72dBd4gI9XGc*QtxCT1%}aqJ)-SIT}ii~Tm=Uv+QFSmVWVWx;d{ z6H%1dG=VOD)^-!jlf+R+eKk`PqtVP{7_E>lBllJB0C6jRyymS`SLBj+_S(bD37m(! zNB0Xcbh~nv=ryfG5ZW4JsLfbWbm7%pt|Jl#5p#m9hIpR+j5|93y2RvGpBMo8MCw+b zKtY237-wEr#B!&(N#FYWecWB3&|c6qdZ zVn8Cn_}@@@2>#jvx_682#LLVKZqi^fbFj8#GPieQHZyiGHe@z71g9OHrEf@PMLcdc zGC6P=15hP*uHYYPV`At4Tmt;xZ?_-hHS!7hg-RDoXmfgn- z=2geV4}%4^-V@Jxhxs&g zsLv3oos~91dg1cAE{(N0lE0KTE3inl0t11G-<(cZIBz!$JdXqWWOEVB)z(8<7feI=#6afr&!A)M2znwUUVz6k;n*(;B-?A|ZW!gqcgc!9z1SmsE;g{l} z;L#+&!PK&PyECd)L9EP>=-A&$_mz;|(93aX?x1BEg;%D4F?S+_ewGP+7m&r}TX|dn z@(JCy@`!3o1px^Gh5eEZ2kM*6;az10UR>OTcM}u8L&~EndOHV20Y?C!9lz;v07$rR zry=1V_Nv)g0^gJ~*dq}Bg+vaG_28czMJg>VeX}kAa}DqS!J}JmftBYj*TDbQhxVGDN6pu33`o4|t*_4at$Q9VraXT2?Z>lW znl!>u^QX@leUT(9JJ-6Uyi1w;5GRFq(yo#gDoTE+R4uPdq!}!IeL3uV9_Le8<#Z}r z4DZoz874$?MBiF0x|OBUWmtXk#e?1)-%ZN)2^HiJbw`bcB?ZnC!|>u=LdMBbojvL( z%luJfp(8dw(a4l{ZuH{sOPhTKo(sBl^wZCgcHnCE{vbR;>qWs(HmUvMX5=2Yrra3qD0g$C>Z=P+s6_qdk0TZw8(uB@F}F)C{=M}6CQg5O{$Kd~ft{rrzVe8Vc*-rB zyllgm)+-TK@ikrsC*d8qi6~;Bbw=5<6?aG*JhYM4yg#zoRMT82-4NSV*hFiCYcbyy zFF~4aVQvu0L#i}k0f{k?dyD~hytP$C@SwuXPTkzV(?zevHlDMj3Psn(6#47%3x#VFe|0pw$Gv)jI6ZE#QwS}+r_fu1Ac6sI9VX20a0)B z{wz)nJ`|y~FZw=R87bp+FL##E0$!7cq2DzebcozzFW5AUke6ZGH0{%i4fkImwY6b& zGC~{k4X=I6r2iNIAB(HHyYql1imDa`m6lM_U9yoVk7_UWy%}JC{Qy~ay_I)IK;E@( zwqb1HvL=p7Q;7Qo;v2%J0R7{wVf$bBc;`zeE-h`GKsHp_RS6A*r;dks**T z^t7=w_B6G#1aG>5ZTxA&ppj8kw1p+4mG5FsfV<*vi^Vu@Jpa4H-{lnld+zvm0$L== z9I3^^lf8kmn;r465h|;(AJMr0VWm$$z{)j0ez_iY=b%M5qxDOehvx3grdq_dCV>~t zwTxmVM1~a>1zXe_vkIpjz73kt7?;L4EDCcJWsk^Q`Udv`57{LmLBHvVN|U6JoXQos=|``63N=q+@9(q`P_TR~&yG9i*ouP4ZF}Kv1@u1w zL~*y5S|#S)v+Dr2UAB?U7;{NOHbM(N`aevb8wZ$2Q7!eG$aNOsB58M3AAcC5P=2m- z7-5A;8&4M>XIYSCFiw%gJ9IK34AS6tS6Cv^n*|W9iXS?@9}9~s6CV|5yF1&=A22*% zjjZyMl!Rt`rS%rZ{}Ev@mTL)qg~l<8%b?g-GT&MQY~T42-w%hYIquIq$LqE4yO8m@d$l_}URg9uaenYA z@hmT;!>x;VFnVcpeJsWfonSwHL>+dda(lRwCxJBLb<}pSUAi5tD4N7viiRFc+jt5h zCH99#D>dOOb9hFr|MrnU=%*f3u7#GRXsW3>!wx|H!2Fp)x9jakfd5N*D}R5&{sH+n z{k!9Lx}Ybw@jKQ3w)mZ_A&@Sz1&8lAZp<_X;OBAyMP^(#qRj$8>Vfg}ZifHg|A2p| zN%A>;+M-3}+U_U7cXeudDd0wA4@g5ka7Hb1#mYH*%Ro9e5rv94Wch{Wyudw;Mwx1{ zS9f9}P!aE0cvXNP%&YgKyVAKPH6%>>q$!H73Z)BG!q|riF`=Ey%O;YBk{*{WN_(w| zt1|;u=cQGUpcx6Go$#$UJ2Tg%=tP^T6J-Tf!T2b6-2%;f$%6=CBA4kR?^DB+)aX7F zIy3~S7Pn$ONH}D2GkBpZm{i<@+?=caB+|Wh^sR?*L=Xrdf_?K1a-7>Z{hgpGHkq-mdksLfEyX*m58R0)C(KT3|N=ji3noGRFYz zR+ET=gzxyhlU$XL?_ExQPQ%14sSab_q~Z-Fx;6A@kdW6f_n@KSU?Ki&`TxR{I~l~) zbk9uC=}`phS5z{(orjL&U3uAx*B%Gkq>*3HqmyqH)Par*HOF|+SrX|W8pF(l&t2xC zTk(<7stkKmd7F;%V&9Rg+2KiFf1%ssrq z+zfUbL%4EsT!gY2e+cdi$yz0Zh>d6cp-z{i`mB3&aWhWd+=Da4!_w-681T{{(+0i4DG68p)LNS1BJvJn}=s&-~_(;OIm* zULmq`z9c%!t>Srl9q)R={H?$mCP=I&XVK!-rJAAGmq~1@G{WERNTK$7TH-zztBU#tn_7|q6R+v9Ln;$s9YNl_^#E->$npCg z>bF{atUh&4-Jv8BC2Jl#1Gi9iq=U+#veX{KMHAvy3AkG0SrRtW%2x<#%KTN0*KnJ~ zhHCf>`IZSX1wtKc*rqNJKceSKp`|*6RA)Obc z?j(Iw*ZIVuE@B1J|5$ju$S+vgjSO@Q|Coy zp~3@e7vH8yLUX>;C=x<}C?!0uV4gd~3po$9v})W>vdpGQEKD^DI#z0B=%&D#psgvS z!m5&32!Xn$j%W{!Ay&V-Z@#bg&F`IcN}>CLk|PQ!kanJKbn}37PoynQ(wiz*5M$tY zl^xf48Mv$Y$zv?RJMZOHhyWaJ%!1b{@fMq#j|h`Y@Q>&)iy&zK?Bt}TC9V$DLUlfT zM&T^vQ<3S!^m!-ydff$F1r%SVI zy6N5c4G|4XjUONL(rYZIM}<# zrulBM_Oo|?Kyu^1+E2vKdcd2H92N8EiC19YH9GR6ZTqsqimlKM@Zo93MgD`l)<-q$~M3=cP{4IgIkcswB|wv^ig|M zM?VeXpkBO)bsBjEp{erOr(70gSuteut@YPyx||8g$@Dn<>3#7^@VvDEYKU}i>xh63 zXlUV|cI0;jMBt`_$9L?=-{UNkf=Iw-1{xXf7Yy^S#UYZnY3eRmz_$CcW$7iD+6H!KT zqHFGPchbCSt#K+bsn%i|CX+cq%*GpM-MvcZ|8ESmB)`>X&zO+bYyf8 zSpC!dj1-oHdIK-L|sgUY0)!{jPE~E zn=mA)pI{{v>f(l%aS>^xieHDuaW>cYz-QQ84hs{$T9`axgM+UBKoAyZNsV}KpZh%)4BM*ffspNp?M zBE&h?J9VU=P8!p5-(2Rdgi%iPMX=i}QZP?q5|GuYMcX4qd)!AZ779gjSoHjYI$r!GV zJtCi3=ZjmQJsjMdBI>oQ?U6RJ?HV*Tnl(VvEQri#xR-5~`I*qIBFLm%jz_r#^kFwb z7OJee<~JMpC!_b9(Uh$1zh1WAKCRedevJBqs_fMx>$X1`%{$KOucCbjQVL-Xn5d6J zMg}{J9CG7=MT_iFwHfwqXSldoQd|t{Q6Kjoog$`9_%GK#nWAFI%2jiuWIgUe+HbHr zeO*)m_fbD>y00s|pvlU9K^nb}W!$g6zH1^A)kI?>^XOwf3(gl(tE~%iNZQXKwSFY| zeHht~_HipEQ!l>wk+t^@N;(K<^aS3AXRzJZbx#S$#v0)yirHO;<(kP^iAv^<)UhU% z2oV+07l4FQQPnklb`tKKk)*2qfKC*f=3_8gRj3yMUu+GrL2gybDxIZ8OvUCffI14L|#oxEafM3YorseoEpO5waXI7KwVH!eFq5Ye!$dX%Q%u$+p%F6J3G9jv=ryD0=?^^y?_(YbAb-Lt(px-t?x;ZsUI2 zzHg_T1s18_8+GFy#89eHIc64+b?eiWVtajXH!+ys#fW#wIZifoCn{@5Fe`p;x;;9-05Pm#VXKM!e0ohZIOT|wT4=>YM+)CXuHf&`GFF?gT(B~9EhedRZz!rXw6GHBVw73Y&Mpl3Sq2i?sVrP7OM<@t~A01v5$H~c@jqT98W&nal#dLsj zPupablX;&B>SO#@r!^>&^b`K7a|;9LGq(H{Ok3E6{5;*qkFF+HAxw*^@5_4y`m#%I zEa2Ogzaa7`T>V+?01kfsF;nbR6 zq4EY&1KLaE1LodAx&1_!>&Va%oTZ4*QLRceN+1V0>-R6~oLlv)@=D|~&!l_dByc$! zm%22#eYn3hQ?VI*n&C<@uGdQ-A*cx0Ey;1m@Dr2FpzGMJ82kaepl;>smR@XU8WqyVq4x#TEW0lo#E?fxGUBgU_gF_l3T~@`@Md_AcpnNewJ& zbUkcX6fZZpkDnNE4@+`w&>BL~6d0hY-;I;6Bua8jyv$bc$K=I$R@sN-dO+gvju3j| zENN|piIb-P!6 zlsVkm*^l(#Sc_-8sfV6K7JpkQAaqUJ)P29!l8@v4SO(7Nt3>xmbd0Nd*}^s#rzvd* zPS-=XK3n_yfrpn$q4e(VZf#Z!Je#5TA`U7?y%dg5X=s)eb z2??_U&BXv_4!HOM@c9Aky5EMsC%OJV;uHT}WGW{F&XKG^1z+^}GsjFXC@yv_T}Y!~ zt^GCcojM9N!Uk0Brn#(~ok|7VR%+e-&V9 zPjiA;$B)*yOscBb0xg3N3kNfj-WQA8|3y0T*6aQo{5#o45yZjk_J4-mx#MXA0&|mL zB9kpjNa>@(kJVXnZ z*Z6p{d_dR_F`!dxiqp6J%dwJ@lAK4TOFaN8hYOEwNEHObhzL+9DXO0=K%ii?mSY-a z9h`YceX}}8h;Q)CXivg4LmWjfAAzddOMip^RAEz!fI`B_`whC=vpJJDp3&B$ikyd( zLjvO^1fWM_Tz;RY^o+>FMyPh$OLeFp9^Pv~!mi4J0Og4_bcrVjowa}rrOVi~H&iKF z=7ba*{2Etgq8etZU2JhGmp%wWO>y{c)zOK)LE+W6bk%?+Fl=Hr$*|&*7zn~?SHH#w zV#4URabaYjX7BLU&xD4AApN6$5xBFW2Xd=F@nI3MFoC)ZPg56rQWXa#QcqHQCVQq| z7z5A%uRKt+=W6?lFW_h9mYtLBrXLiD`+_4!H$%{W_4DtcL=Xp*`P37>Z&bb`28Vu7pvxAC(5t=(CWR=lK*}HphD>RfFb)W< zCNJN`GKhPgKR!BG%$49JnD?9%g%Ju-D+`0DUz|Jc6 zhtJz(Vlg)Fc?2?p?22p2+`o*t2RvUP753j=JjJLn9>U{ly6;9w1VbRV$zNb@&p6V5 zWy<2vL6`%D_`$%-R`X+$^p!CylJydAOHm@E}(21K$Ctn@npqq@=UC@Dv}9gRN#&@*OhJ9iYp|4 z9&Q-5>_*y(0sE|w!7k?rL-^GhV==vV`|izqpLd2Mo9YGEsD zDmp|Psk=tFNV(nmKyc!t+d%1w)&7}qP9__6_p+z)@LMCU(O}cJs4FUzE`)l-m?}>? z8CCQTrVx_I?#8JxJBY*F zQS6KJfXm2PU}RN)01tYaiGHMAJre(hHWmr8fqhj=6$LpH98zz-ORr=- zaqD=tbszH=kxS{>+_29oAEqF*X`2JSo_@e0RtyQadRP|72@;mUTbFp zh=7k1clw>(#$|EE$Eh7CNv!aey-Jp11)>Folu|V0)RU(u6Nen?ep5BJc#)|j{w51o z9pWE~t?LjyA1lZPZOiUGo5i@k&O?BJNCRG=0EA>v09@eDc=+%7zQKW+07w!R0nnqH zC^r_zEu$Hj*A^he{73ybm?IOQIJ5Kww%U-2JG&SHgqZ54cBY>8HimZgckHjaI19iA z1-=*@7Mv*1T?J4R|Dqm&$3hpgbanxd8SDYpTnB)A(*|gqWxrVoU@@uyyG(5jNgv-Z za{h@>7kB`m)7RL=3F!1SHe>;^@!<22uy|Em9e^rTpi0vY;N~>8Gz34mim8*ECGgNU zOrF306n8HI&LQ6*4xXSuB0%Ee8X7wRpHax!)!7(u4ora>e-VqgE!NK}+`NC;F!J71i(0^E_FqPI_ zrpacwpfHFtz+}Bf8L>>&6#V47oFJtCtCd82WooTt%mh=SH%+dIxX31A3n%*?@b4ES zHOggXBt?=PWO=9hhAg9D1qUq7e}u?G&jeaIpLuPkThHZ-V) zAkMtQgenp0V8g}LCnp96YX|~oGeqam>wc*38WRSk9=ElBYJ-E`35ydwGqHZx0Og}+ zPTUF2l8w1+Q0HjhQa8*DDCB=A5I)!KZ?4_K^DfwY%o&Czh>)8;>)DI?8k00Cdnn>M z_@VdQoDYg(kVKG)ZO-$1IX z*pDbP(>5`rn#Qwg@p)R!1Q~_mpX^T2zWbiYQ3>NjnVv+;XXqB|WSuIl%FIZ9WsDY+ zU&QM5=zc9sa&C?9m-=GSG~EN8Wt(1ing;*Xl1&98dI}oF{dD!$t1J54WcoWDVPg!> zkHgP7y`C^NL}hIE$#JOX6Vya~s$Bkw{}BM7R0cpz{RLVv6o?Cuc4ABz5Qr%N?GN&q zP6&I?AVd!eDjgFUU0GU!QIZj;+X9ft**F&b~f&3}Q+yL3}je*Hb6RlZ~x zkX=Ral__8VTy|g}>WBSThh+pnQfGl}@&8qpe&t|Lb%pNL-RTBtCz9K7fJx zuA}lRm|8;Ld$D3Z)7pAe)3w6L*rLM6#L$-#`MG&0Xz0Y|NOH@qP0q?_E$*qIy9Nj^ z3@gbWFQo27Bt5d-^z9SdAGmAWs;DYz(0PTgT?iqrkF9&t_>X?%?t@fgP-&hk7za5{ zGpWZ)cRKGpzW>=iRvmS*^6Z3hjm7Hi`-eQKB_=IcqcTg8j%6Oz~h9S?jNK{ zmDeM0p#+|{SMaXVC-J2kNI@3I<+;id_)D%{&$D4qePU)#ir+RjU6|fY{ODaiCM(Ks zPHT{{)a?8y_vC9G;q0j9^lASIH$8PJfOZ?>d+#`bz5C<+=SyY$fzP_877GNsh4cOPo)sXitd80f7PGEE&FHSHx_2VfRTAY-iD507#Ej%M)t{A0 z!hQ@O=+F#?qqq6|n5R?;^I71sH(OEzzSb3d^ra_J^5FBRL(K_vI#9a{ickf<*u04T zi#f?zxuR`U4!Q|8e%zuW5wnN`b!fBIv8XOnlatOCrXHIqrhtIWj1twv4F69tA3$;wf~^x>?jG5OK~lrb-K{gQA@#i5M9iSTu8sqSH~uad|Tedmy_Q{2=Z zSyW(y@uR~Sc=t40tyyP7k-VMDUZahKEnXrdu%27L_0upQA`KmJK6q&2MLfgcEgG9HxjT8lbqwOa`lg_`*TJFZV0oS&210@XX95>*JH_NG;AqN;d@h9Z? zf9*DZ=K)mE(mB%;Zzks-y**7&)E`w*JPl^Re`2*ZtDQgadTsF3eWsSFfMa%rFR*2f zIv0B#?W^v0uR8tAkjE-GRR=z{oGpv9ds`grX8DIOk2Px77-oz*m(wSJ|B5cmy97m7VDLh@ub3r$9tM$)?m=8Q9LGA8GeZ4LxQEzd?E}FBr=4_l z0S9#d97x6L@=H|PU^M|QFBt9u&kv`sT?FI#@)|cFFjV{xJFz+_niL)$6O)uL`LL5T zdOW4^>7Y93lX4*R+chL&E=arNm}e_r%5A^zPTXc7{xkr-we}d_=TL)OJ!xIAy%LJZ zQ~Jv3-T_M8JtPx>L=Xn~ndhfid&LU4V1r1Sqs>bi2~s~=G9=VkfZuBiS36l$dJ4I^Gh*A-GbE^4+a?oJ|oD=WdYK>0A z!7GC8zO~EDw2u*sB)YH0Q4@8AY6eU5t6a5tsp^lTL>((8kK&(jPbhCm)P(xLQO;0S zmq|0;#(?}cLH=uhuA21^x-|sPKwh9n>AdOOA)G%It(mEbr4zV2?Pr%7lcf!_u@msR z-EvEy<^klYBK`=T{$y9C8 zS@!B4v#}u!&wlaBLXxhhx+8K+A$c$;Y|J+vyGHTdfte=Sk20>|K|M`Dj#P8H5|>Zo z;S)LS%(;s}FpFk`3yJmPA3=eh3dhjMjx>D2{nAmXO9eOT^?|p3 zjh6P|&R5^g9r-`t($hJg&gR!tqr5|gaXkwVA2+pa`Ae5^!a z$o*S7I-hMyoVKck=dHqDNhpg-;^!MDj8qyAxY!=+kZ4NoB4eK55_Iw!oSuJ|pV6XZ z3vLosKh|74Ug#EO70jISm1>jL8Pk$vp=?gk&>4Z zAJ-YVsXNSQ1p%pw3yZr1qbSDMT_Nx^WHmQQkI&Q(vQClW`Rm@(KJ^HamGM3dPi74- zwj+`G1hW&=P9#BPAg`7O)Ly3C)?X$7?l9!fbvx=^{SVHn$=+FY|5F$PWS}VTW~mG< z4pcc~-?-NRiUATZ`W?Jc7w0K*@6+>=lk+!;NLb0j=bd*k$jjV%dI{CUY zsD~^_kU0ebnkp7oz~i8p9)4PAaB@!Z+4xkYVhUuuf!wEV)ln}5Q8eX;x>Wq{sTT?f zb`?lg*+*jBgtZ-i>LGB3@^=D!Tnj^ks*XEZXFPeCp=v6e4ll)gM*;lh?my~_Kc(Km zc$I)dNdh7Q(`OrmNI{wc+>XeQzZ?CofDxP>^7n@zA%+otnPP6sZ-M)xP!4xQ%*Ay8 zm5>jqC$IBa7Pp*4M4}uLM69j#2{)bEix;p1sJ-*l3IUduG0gJw;`TFP>eqQ3UIh;n zx@UEG)pJcjGy@}zpYgKpuCRzImT|q7_&|mT|MKX*YWI2Q^g+o!Z&>sr&y_-00_)F3jB9!blwu!@ zl6=PA<@wC3x{}^2QmjcaCa?j`Og*??K29=sIX>ST8^~3%^+5FTtQW(VMy71$Z~3*w zyd#NO)l}=r)({3U2G%Md@E&IMm4K6?OP33!vdO2J1-Q)at zF%tpmQ~o3rf0UZviWVP}tCHfsSy{4MK|4FE!~7157s>O7>2(wPH87`*wMUgQ-ej5G zFvlMad-kZ~g^cfd)AU2UuVwnq?)0o!JpSe)K@|Jq<{Vq0&8LxNhREz$C8TmepQcYa z7ThMk=7`jHiou8Ya=K7zPuZXV5I2qc(zDeMx+_s6>G>0x>vig@Mo1SD^;INrrY(|p z4?v>=EQ>FL-Y$htO~natU}fv?{%}xqkQBzyxc|5%vIMsM4Hh0VAyt~|e)+4!4126{ zVaKab`Yr`@Qnm2|Z1LrJvBQn$Z&+WWUa3f&F{ECQ2f08+AW>?9T@)j#!S5l*O7naa@<2Kvt^WaEdMq(tE~;66uBcHJHkk z)`eGu!I&oPjhF0>&;94bAsg>z>jvUX2tH!li4}RTM6SuBIX)2L&VhLM{OR$J*bu$q zjTSw(%}MNcx^|x4$l0=LzOeV{eBUNfk6P7pQ^H#%be2!OONhSom|oUyC#t&@_rJ^V z{sblM+=}see0mg@ZEi%LwJVQdFlhhMK+~{@x?Y(>2mUkYJWnPr{DF}OMFbw&;Rllx zydp`uuc--oUu+BAA`&42N@lfjp}eWc}@QXuv(w|5kjir2yFh%Mh?82l`u~vVYn)O#a=~ zDSC3rEbg%R@a=B%y9(&0*y;Zt;slnh|0_=auNJ3YzG8yG$nw6bK^Z@Rzlr3@lXsK$ zZFESvU-JE>kK1g6v1!G{AP*gN-Y{XK5j-5qw{F!p=f~Z1A}wvg?Lh_UclTz$W@s~4 zC2=ATr*N~0C00_lNo}8(gc|Q_-u3gsx1*XdG91gfY9;oath{`wBaW{9$(j zVNA;CoJkX?6<4^e7ncQOiS1U7Fd(XBL*W)Fw!3sNi*rz6GxqNa64+4`yknMBH2_V{ zbYp9fX@0}M`nh}oa&?wB%<`e^BCDc#$9vSgn%P?>TX`n-#DaKJ=DXv8Dz8TW+2pTn4 zL8cE7z}Kk-Q4@^mePXPDQ9|AMifk;o*^UXX^f1v;Z`9IjLATqTm~>11)v}=hKZ*uGUxr!)EWLHI3pr8JSeY8SF9V801_8#Y^KvI}C4uaz($bKo-+DM8K6*~K{w*eU z12%?^=IKiDIR82#lHTF`SV$_PQ|}8C^_9btr`hQ|Y?_Z|@*-cpw_>~ubzXm?=nV4} zBUC_S49ex4q20d0W^CTiekdfHRRelV{_rtkBDtH7j8MR7_qWHrDvX`w)r-R)U1{v< zP#r7SFPe!SfBb)_`wFnE*5zNiJ5{Vx>Me82UrnRn(lGr!^g!SNMoP$MP#UXc9aLP@Q|Q)`{{ zx;F@wm0A~hP&QXhsIMnWr>!#|C`1c=Cy`LI%8Ka<8EUM)BCH+AO+#9`94cvn{05MU zMb9c=zsLii@C)gwClC1ww2t&R+dl|+$(uf;VBu-AUMA;x|7z3;He)5eRCZ8O9bU_ zkfN8oD{oXpfF7mH@{#<}8FGmGAF7pC70OVU$zJbnBoF$ZH_$GB3xG#Mmrs0cV=57a zri2^+gNK(y*AETF4y`3xp@Nl>Lim8%0{F0}u1Ab-(4%1!OUygXGg|^O5FXOZ&b+`6 zTBz;U-r_2zvksV(usEl=ub7YJ9`31sKC?F1k||vY*F;0J7jlfpe{Z#Q?l2rHI&%po z;u0R`fo2)EAHgoy{RM-iO3Q`|4f_E8Bwvk_29 z5Mcg@7KUoc!5QrZ(!y|Nt=*-WS4csUz1jTmxqJl<)^X8W)|5OaeV{S;B41BxPtSn) zpuVt`3RL2@5Gf^G|D*(_$D0mp(~d)ZHluHvA04G!CeP~OL=v2&ar1eLhN!HsyeVxX zFQ?&3b)jv{H83djT`M*d-;8usAA}9)IV*1fc^JTEGK5ol%Y?<8a}j4|3c`t{>$}_ zEO()zpY@J_Tg`f>-tlJmAF6l!<9`37Wv6>|jyvHeT+T$v4h{~@mbY0TKjj9IEI&nU zUUTwS-rOJr<4V0Ig6|KnsQR3czR{%@6XZwhkfsiIC1dy<H!;DhBllQynF^-|jgb8KOe7@EnFu%xEI`8qywuw}6nMmwZV~r8G$K*6o z9wa>wU#SXb`2h|);@Q;#_5G(El+C_&ZZE|YO)2Aan`$w4>4d?#!UGf>lbyRPiWu_V z2SKsl0^Ucq$h2!g%ER-2#tDr>%G+=_LsnYHhQD`;w)<#I71xt*;kfR;h>50mkdy?&08RSLYIq`FUlHv&bap!(!3G13EtN$jEjJ4 z73oPb|2Elr?jZ`^Y}hxp$h3!q5V-gervBr$nfDNeFij`>ER=`dN<@9G-~aH$f%t12 zH%$BcIj*@nm2YN*IbLt0mI-Xj_i|3oj`0kQ%`&Bxau#v#nZP~vp0uo&t7ZKH-qddU znuN|WO(es|s0pbYjkq_z5%B>|$e;vs`Lc^M14mi#U~zB{96NSlVlk~;(QaBQB%1Yv zUB&gg$`7yzyy3fPn^ajYRD&}8N{+A`2PD)(vR20uxea@0=}$enMEV9j7qijdSho+Y z>a0PgbG=j4RZcq3>)=U~vYlC)!+;Z;!9WAS( zOLo{?#iPtkA5&!s(YG^9x&ybDknuIo(c2yGyz#K%43|K#w4lRY8>8B8yG3ECybRik z(T=h5?NWJeD+*>|-PPlo=NK3yg-?WQIw}t6pH4|)1n-k6(SiE)f+{6SiMDv2RmIJT zEeRv!bbce6x=?7Ck{rcB?qBV%f9~QXOrqo8(-6*`P$ih)D{Q0pa&i6SjNI;{XDz=( zdtE@~OG5N0Ec42pZDRKdsK=rBkDM>dR6{7~6$Be<3gyF#q7%>P-aXf1cr{?$&{*^g zODV7((M#Xe_OjSquYm~74dtSLgVM*oD^YOIrBsw0sb{kRCBTo~$3i$1p<^@OVm=vb zAaqj42POIoH3ElJ_bC@9`xTWx!=8Kl%thp7{(v|=$=hI+3Kz7GDbC%I^hCMMliye> zI!elp$K2&MC*T*Qj>#jd@-oebBWr5(4syvyDK_IY-OXmv+l8K#Sv*zzn47#{eHj7i zMni!+7nA-RQBHGBMhc{PZxzXEHR{Xw>(zM=Ycju1Q*ODsBn@Nz!N)Ikx=v|es@-rM zlLy<%N$05b2shQ03UW7=a|H{pz@K+DC+G zY!GfV#Zxu;VITK{`;{^eMfVM~H8mEQmWY;%r$&)RGuo$p5qJA~s8P$3@YJ&aU(gk> zU9E2IS2MtVRl2ob5h1#uQ??afTGQUOTdy5J+sk}B0xK5GY3nsGx+C5 zBy1!gAN1E`P=O`fn4RAjzxee3vh=6T!9?y9M?Mc?(l!)p8uqG zOS)W-KPTlDYU;S$tC@u{L^rrdO+fUSTrbIAOrwtDSxi&K3D7b;aZLV8o`A!vf{dY9YgY#t&1W7C4&-`bZx>*Fwm3QF!Qz zB2chkecnPT@9;#=cNh7nY5TFga2k^ED77@Q@o|uA7O^^W#f~46kMJ=;UqvYk^#r}e zmZ!z?q7FHd_&@-&T-oKPG0El=y+rP6qn^35Pg`(>%u zT{r1sTq_XUz!WEBH)0?b2U8OGG3KYUY8(9!K4Bb)6C}w+VWt$@>d`4zY=b6%jt)(u#oyilZUWQEnN)t18W|!w0O{lD$>AROyv&+U({k&39S#|3>fr z8N$8GuNHz-#})fvwRAf*`rgSQp8)&l`#)6*U;C`r^{XslN9m9I+Hh9F%eeY^5GM$R zgKB3tCz@&7uqwpqVI0e_mAWg^ zXvp56gyoESo+1W(sPl$IKH{_YsdvClq z-TJWAY{H74eVsT*L2nwK?z|>9FWnk9M*Y4lQq@u_DDmJaIxNc@o6TWpczB)(8M%m2{kDJEZ_cyfDQ? zz59L;9Tsv9O=H;b0vip?3g1OitQIjHSK`Vd0^<3|D!XSSd*`|J^#`6QB2W7Y!KS5d zH8+G2!`LK{a&P5%(tVN|_WL{m6+r~Utl1;;-4d)kU8nTM*K%m#tT1~##(AU~ol_%k zPub2y5GB~vC#18to+QSgtkGJ&vz#q{2rxw*5Us7DMgx>f@K=urVw?=s$yDhoPLd$(TyLiDxOFx?uri$>% zu3YyIK! zvkI^Ga%17fO6?`EFlrvo#ObQ&{qh>$#IbOf9G+C;H|R>6i4`2_xSN!X&pAn#UQ(&` z@brn{Vpz8`TMT@JkM$-DG=NxQ!TK^daK>#JwWzYlC&cJ+G{SA9w)6b>N&(;Q z_$7%8SIu?X9zyGW?!h?gm#fw>Rc<=;TOj^l*m3{<<0dkKFU0?5~{Mw-AU^f!YjKI7e@~95UG7*r|E>o|Q@{e(Cg(c3mxX z)8L!A@*vFokO<`}U?B|iRk*bcnqK^f$#9}nJ6Dq5F!ifx%DX`V!REG_Fg7U0B(?kJ z;Wj0@GqS^S&}6wE#@S-k69!~aAn^Ef9}M;OSQeDOXD)16Us*7o8b5=s6E^C@s6c}? zc;{no2D%vEez}86GoKmnaIio%V~IB>%*D15c0RTag9By|_A2XfksnY}J=2M~M*yQ~ z`mXQoX(M)4QX}T0#;GTR9vS#!15}qm@|29~D6VoDkXQwe3L%ZGJ@knJ0_Hb5Eb8+g z#`|}vV4^q>A=gN}924Og7P5{nzj_x}Zk-qq>1mS@>Vqn6<*@iXhPZ3LbAOW&*5)I@ z2&XelZ=L2ce&N8ZGs)aFQQ?W#SmCKXI>!~O;prypl&vEHKVMg zW^6_n&nAydg$N(P#Dvn(Sy}K9t~q%^*`e)sthEl@pH0`Rd1I{CPz|%)w;J>+#aO6l z4Rgy^96IdCzJYvQ&%PguM z%a&=iX#Ds&HEdW@UNuG1ugBbJh1zoPNamM0NiZGGULqNZ=Ae4~fP++H^{hf|IykJz z7kT2rff@c>=Ph)4xZ53yhrg(rUv<$Rs;55rM`cyq;S%W-Qu(mFdLE;-$kty}4`6>$ z!|B+r8L{^IS$|B!=OJ)6u7NyqfSNU0i-_KTNk~{u{t_+Fz{}%c0(Xc56yfKs#5Ub^+$HKYRv9p=vsB&R{^o) zI$oVeSju4=^d>Er9I}T^BV)DFF}&~T(2@xfj=@d5ZyzyQ?`JtZr4u)3P+Xo__{ht}44b-2P;et*X2kOfL2<37jNyS03Yk&6`FBR4)c# zf5F_=nO^hCtp8p9z_q_?aL3;T^3ZDyQ zy{@1`fV!?so=czJcydoV``PBSu2j%Q+w9fyjtSv`k!kG{yDS}-*ITL5Uu}K()$bV~ z*v#w=jtY81sgkQ=e5moA=y2kf@$PZy5^ybj09{XN!DRlZx;xnG?Q7zy&JW@=HYJ=I z$1kX-KQJ5><2RDnbI2Fq3mPTGe0pfDopTxd1$oYUB?5P0bAV@Z5i19q;X`DlE*5_l z0xUv%-ibX&640mBZ5D=C(HOz>;&SZ%aaC{j zGAh7vBaxsI3KBZkw*%zcdM7b%{B6~E^n@&?T`hQkKl^gF$b4c6s>Z{c%(}f zD;$p2OX7RS2nGB|_fKBwk(9cc^a{@1v}r^n)s=a5IZ&YLFWqk?m)tSSJiFNe>gY#_J9whTkGAU^|X zGG0FgbtKrYn+0Y0QKtARY9?)3^{a=PPs%ybD~Y^6wPs#hV!ePb)^_WUH3Rw}=T;xU zKqMuE{_@B`YIjtEyeu=2-*^+c#l}@}1cM!c0!@3MwF~esP&*3LY%)`WD6jWJV-x-D z{=1QfYi3?R1#q*l-t_Ih&glb6NVx$kj7#%>>bC#n10{{uD`C3(7T_e=S+xzWVG~Tz zpt;wY-y>`QYfgd@+vi?l_n2(Y?$30iU}dnY3DDC73t1e0o+Sq#zUe_bJeqV?k&6m% zx#!Fon7-aG-7~I`gpHUZKpvdtJ++5nRJW~rZxVm$NB6~Idd`jtTA)h~`T|ID8)A*s zQ_SQ65HSeL%1}%)Wm6_$w1V8z6W?RrEM_*Pd+jcq@$SBNT%8g(w0F&1AxmnVWTZ{q zd#dK;Fe_jx#f^XcWUh!R_SNTX=sO`u~08CLbbOJ`ZSBhaCtqiuoq? zs4DW+XIo^6nerBcVD8gT=9d(wEz42|CXdW9G01)+<@JpQ`9}UCNeb6;MG7MYk^qUp z!2th-0P%r%?$k>$-l>-YnrdCQUNbc^Gi0>3WU{?(s%B>7z;vCx&u}wx`wL?KhhbCX zx!Gcn=ZNhH@h#!Yd$vyccFP~Xyp}gU6>Pu@HAfC`=j*YFceq8^b(wjWueWjQnBY+8 z_KITiz^Lb?S_sdSupi02c?jR@}I1D~~#E!fi8$kNI24mPf?EOXtXkMS>Bfs2_HaLukw10cr(=&cD1nL&V7`2XWm z{F9QY3dEi1h2|X1mEg1_AWi_i(G0{gq1bz!xfbfHNAm-_n6KqHsHEgzpNg*T(y4;j zHz*XghRCRfYrSreHsuVTV>fovZMf4vj7*^mwOn}KHC<|nL`3YI&x(xHqMST{QX~pr z?u{ae;Sd8ixq9$LjX}EVjEGrBufp`bMS)(kfH;17pLZU^tSud(Ne=MCkpelQd$OP*pj!@Y*D$p_LXDVcOs6A0fduy5)O_FB#hK>dD>qPHN zlW!6&~&13{pv_9BjTy}SB>`D)kW-xfg;5cH0&SD%g z&r7yVXTxpq5x3L&Xx>La(e-}lEOahTK4)P)y+;G)i#6E2mWH{Bt3+SgfXhoui9ihD zOgX1;_=#i_8>dj4WyP4I;9ene~q_j-%%3(`@H-#pzGoXfWLwGU-0r@hrUFG zZ=e?-=*7+g`~dycZ^)VM4*#cb|4(u`ip#BBtz6sO{nYQRwsHlJsF9CM&t5{yCyvCa z0>khko$pIXgvaxV{4y0s+TY0Pg-eHCc{yjcod|HSW$|_%F=L85#_~V$={^Zb?q4Z2 zpQxV^eu>dJH6;@Aru~2mD_&L=_LyT?-2XX_(bQ)Yxv@Dflv3WexNSV@1)4U_X3E9x zuX;DlQ?!*w8IUa4@enZrM$P+q;2=09m%W}S2!?H%GzFJ*x2dSrM8EZXRTX$2&Xw^K z_`zx5;p6D+HN45l9PatJCR-9(!LV~79Rq(p|A!BfEk@>^n)9C9;7yZUJjU3R_rv2U zqd`&GEuW;UvVd0XWZ=V_6=S1$;B@u}0Q$#Tj1*YxVg#GyA>{i5J&~Sk7wH?{$S)!Z z_g69gHOC1syJdND#mZiZSNFtv^&%sQ%o}bHZa=j|Xb#ae?|&Sh;T{FwJtJ=KXNSf! zK4?=|mre2dh%$2k|1!K__|5pI!H9Fab7;CwOKnzN!v-VX5Sx3>u7{sRiK>Qi*H#z(hkIS_mZgNKsRm6YRc_CpV3mY1$+B-Qo zk_wA36M+bB#SZ89t*WYuzc*T>0FhnqhQ@yI`)(yCuqBXPX=Dg2<~M8Zb#gsWM+2<2 z06!WV`^|!Tclh6%$Un*EGI7e~XGF~xd6|-Jn7Wk#Y@hV`+*}*Kg6hAa5I%g1clG6) z-Dc<^ruCKrYVKTlEU2DlY-E$KL4VA9l(SFjMG~7fQs$ zQ?PUd(yf%w*RuFcnZC=|dSG*vx8PFkP7RmlbTCgbWq!HBd3qiY`|*W`tSa_q<`@I! zk9#~kb5tLX-wSQ!!C}4SU5M^fXaA1#*@y$tx-<{Ihkfh~G%Lq5Cu%E^T`UVx8yUN} zQ#PV4Z0mj>?<6M6S4JPc-pZ!$1W@8}X9eVr57Q6R>YMOs)<91b#6=JtOezE+17AB4 z`t|Aw`8T5J8-2YS@Yh2?zCk`Xe|Lp!i#)Uc+BXk?Eq}LW-!FCA_z`9Vj>m2`gV_n{ z$Ij|0Q7|MBymwT@K(7`B+X&haF(>MvQer4@{7+4TeTELLfv81l_nt#j593!@iC7}d4t`HZ^@zHR4`&VSRjC==GU&$n|zstT+7gu^fu8PWSzKR0K52ooi zePMd{iQUxwq~1{&QfkbYH!2yRZ9))n0$LOU<~;Lni!>58vAmI^tc`&MsTA1K#vSaa zZ|3d@l=^^8%t&R79T|TX0wDv1KwxVp2Qx=!u(g|o8Nd={!OR9?xz#C;eqKb})z;p~ z!NHxB_7?UNr6c|Iw3`YZZV(F#J8(W1^L6qzko>{|RPo#nLB9V_&;H-l;%t7avIK`x zP*v)YE`7{Ak465Z9Z{8CE5zeBeBt!Pl?6ITGblcKOXW0O=zMj3_Tw{m=vM80UX(5+ zx72dAtgoZc7?nuPI3gdFsWHiW#z_bL@=}T~n|z(q%^Sx#oCKh_VhdGd{02E>-U|{G7 zb}%EAFtT(sax}6uGSdex0Q|CdBsH=$2YAFBY%EBDQ*6z_)}(-U=?;{c0hb{)HM>3< zc;kSIGGiM{H?S3OA;({D2e_nGMi$1vk(NMPY$Fqfn->^33+wKq*g{Ix5oh& zy*}_}_BWs9`fk^If$LkEf&mt^U!IEeb+1`#BS%tG8^FK5`KVyhYly_*H_jVipCurM zjKFUuLx7`()W8hzlS!SyCT_q(0kD(nYhK^;=d6V8oIz^Da8pcoa}Fb^w49=XvZ}DW zDjDfDQf~&dF9%y27?A>gJ*gwG!O6jh)W#V2FYrLF>CkRVEUphEb#T%*2dLOcfxBHF zDgWCyE2^kM3S_sLS%UQ~f$IPtPJ&nTR zgY+S2*Da~Od}64U<86Xer`Ax)M_9(pHpR^YY8(uP31j>p8J#p2yIaf8WwI>mOH-cM z7HnnZZ808RoVQ-eaU!6!EG77pA4(H=%RH)6?ey_TmM0nw-ySVni8*yrzckFkj%sSc zO9#W6`1Fo`$cKkwOM;1Dg_*cfuvvg^O}N#sF@Qbheyd**Aiu2C`H~}^22x3upV%id3eoM(KNm~>9sv10V-N-D_PCos3Ni@sTD8Jq zL#e6UR6VnS*Z{K(pmMn>;b-N(GyLyO!0BJn>evkR5&nQl(j`o!X*W1vS8O>fn%LcCVKZjGxtvBgS*(?L3qY*A}odhUPlM zI}8k7){H@cVcF{yI#UMti#m3fn#HpeC$YlzX6K@VD83&y*fT=TARjSuBk11GHV{T8 zER5?6daJ_Ze1tTOGUhM%K;{1alSvxybL^%cF%jqQX+`W12Fp1;3PeskX^{F&oB`u7+r)I>N6Zzp_>`Cgc?(%>L`t#b)rQ;rJxVVZ>B z-u1c!JC;OSm8q!5;|vw24VRyiZ7=1sldv&)9pn^p<;x6|4gDXfPx%lQ6WEpw=2|!> zHc^71MUfRNv)E=8<#5k5DLD@(6tz z9#N18du)_q{?62LdN7$lvdX^8CF<=lIL(n{_`)LlOyMqd6|c|cZiR$x z-{Tq!#z1Mks7Ov3o-y%W_tL%I*qM3YY>fD$E#rt}IHF+;l|E?31pB&v*sT{AaxE?D z7(Vkf;50p2JF9%xCG(AhgBn{kD9*lS18OVGY8j>AWycezk#G@DtyN~v{l1zQGYPcd zA4?1(HC#mn_ak;Qhqld)S{_tUwHDG{90=q%Nw;Tw>N_qZHb`F3lDLY24L>C&Jqe0a zr&_6d!j--mY=}c9O~&1>Z(LlR({Ce4rq>-ZArSF{coc05QNvrKSEvM9>cIwk> zlmt>@0vYF-eS;6aiSj|Vu(|e{9ll#t{|1N1@p2RAF@a8BFvScsC>ptmL*Qhsp4O&K z@Ec#05z$Hq@r%5Y=A?_5B};0TS-3hwxEBZVQ_YV{@QMy#O^g$o7uDRl=(VMze54aLxB+5Y-J}_>VU}8ccScrIN$tr6|bL>QMTs&=M@;$nh7=^ zmiiWS{DrHl4gj-i0)7D9TnCsqX@7@X{TjCha4SO4gKJ%igpK_eYzwwF0#?623Jsaj zZXz21Tm>tqD5a?SyV}Mkx*7i~Z2QJnW&yDRRx2kv&?4;GjJ+NL8*Xb5?*`BR$0qSl zesaV+C9}r|Hsb0w&_OX3tFvdhc+aAWpV~fqYZSq&-#{B-(7g6KbtEGJySbe&>h!Vo z;&uVdiKfSRTX{h0e2Uk&jI9_)oq0%!vb(Ekw$I@V3-KJa;zz2Dp86~U6yN(3p!)^b zp?sgjH1!-rT5^M05BF$^2`^|mkcyqloZdqf?7Nolco&c{y+F7a zMaOS3->CY<65Q9DNTSchL#~g(Q~8*pDXiuEC3`m8$8rXgK810HF>M;o23{?iVs>P0 zl+?krW3#y;7xpRs1P z0}qtBW}wMy?TK>gv*F z3h_gkFUSrdxxYL5(eu}Di#2Uo;H~R?2d^Gl$PQP>-qRA77fL}EX7Zv$QPU_66CGq5=syGPc1$jkGS%J|#vEHAr3wR%m znKyHhxdiUuQrAg1b+^I@c1CYf<|_3EbclvKSHK~|NVVR#ck8qiLO-NkuJeA+ zZsqqFkl*=R`9)@CVQ1xJ;ky2N_o-bY&>D9f*?$xw)Ele=kYpH1MH%UzVh@dteQj3( z%)-}+CjjpJJJbbq^|%fv-L#Md#FzE%@PF{m|0J^oCFN8`QxKR_>+a4a2di~5`-5G| zbrEF+3iUB|HWKxdp1R#Da#ZXMW@v!iYr!m?EEMJ+3t&1}l9rXX z+O_rS@-BcKbWQ#0`>Ck6M=RqzCWfIPagVFs+94jLLvXkt4pe^%+c=j&T5^tU*caMt zxU*=m{2{5rqF$gtt%+5D-u{dp6XNU{9#g76{M*l(%|-6wm`9w|W4EeePi7t^&AT%I~)H1X9p`i&G&KISYySZ2a2_)1869?j$hus zYhXfSm~P|zc&>gJ>J@%{;Ml9BFY$v^%%~6rG1lGhz&8O&02D zp@Y_j?QR^Ik(lo3`3{|Fan1|39k(5YGI$rRYk}#2f`F(2egIji0DjnSJfMrMkcn;Xf(bUEs=(%Hfiym29y8R^hhsI|3{R~BWGb^yY+rKiJZ-9{-%b62M z75$gJoB!XP`oHMkj9a~a0gWrVQnvYm6H|X@+@C|)Q~U|?~ygb&rxKJI61tU~U zp8ZlyJ&Fc|56KWbQaC;!Uyf0CYcPXosrI$CbDJ9S>tePn=`%NHMMHA$?6s}cG~m=;%;{fUy=8C6X=wAndi?r9sQ+T`801KI=vWC#T^On6$b zjyMb&6aw+LQW`Uc*a@%+3C%`eMZb%QYxZ)cbn40yZN)b%Kl8M|MBh4KmkV45) zWXKkU;};2&V{H=Y(qE7ZvdHDRMmzaHEw)kgPJ^S};Yz&xaR`RgV9!@wMo~CvWTPb) z`1a6It*POwIw~2j(s%q`FSIP$3qK=^doRuzH#U#Rt-VH3l0wvPRfH5280yz10zb9K z<>xT-;@Jw{`wW3X-i!n2+LK*RY)7c8*V!wl5N?D8#=^l`dQS=%5#Kgnq>L1j2z9+4 z)I?H~;pK8xYBC55h{Ib|-~R(O`#%uz%TkD!Ng0&q#e)w*&uE(3LDogQzX;P!x$TGx zy|sFqd~HJjL|mz4AL_VsPf#Wi{QHKw*9fkaX5+}xbFAHEY+TX6n z%}u;7#-`G|w9cvUg#GNfZ~5J;AY%LD^som0dNEyvgVc+))P8HaY(w4q*vA!c7*|T~ zQsvaB6k?MxAXS`pv4?vKgoVf3gY&(`&&!(f>se9!-k!l9nXga<=)(1P261D4(in2# zrGF!fu9LF#y;J~9ph)?q<6!sxcTBp5{CiNT(+0A(;gY$~qFS%CC9+U$uAWA=&1Twn zJ$p1C{%m*!MZz+s1}RroRpcHn*1gu5^JYiutImcj!wb&e>`3Em!Lyl64P3UZ!mkAf@70d;X7iwlbq64zqa80;}lyGPj=7>L1-<^ z)ke`zOi|DnF0@oMK>aZ~DMJw2;rOR<_fVOk{B`+V9cn7brxaOU<40a(Po`;FaG%KL zNpybkCq|K#BT<06zj#t~z~h%)<0k4hRc_->^Ab95gYt#o$JUQu_jDDd3AevZGhS=p zD!|sxy|uTmLxV4F^)Dp#-S_3%*tWZ4GKh))bf5v;Ow7p1(ZK+S2dM&aHVYdoQenxT z-0{fRc&ZH7n*p<%^wzErHM$OVG5?Wq@|V+p#z}5+z__owE^q^mI1t;o4F=z2fwOZ1 z!~Yvo`X~Rq6gijuOBfwaHBMk9AI37b4ZHT^irEctM7;EYjbZKsJ>$G$A@YEa6ZtEy zv1q1{<*($lc!u9M6^RJVkK{J{JvEOZC?ianL3l((b7Dpzx%*|4-aYjY8*0>x&Eri5 zAH>tr!x@xA7QRPiiZfGPbN+GtMJUNEXb4j3&&%^8&0KJn~mIVsJ2+Gjr5wo77ptBNaza+0dHRX%?YAuBg1RC-$lHtN3YbNCjs;Ir|z?;NPC$=V3k3#lMr`WBr=0F3G)` zS9OycU()MAB=R{4^HXM+nqmBX`W}4_wMFs|A!>C=QYD6`Q-mBJ#9TEsDR`bF9=d}R zDl*MwWgbOlK`#k>DV`XAK3-e2XwO%kapm)LIaR#wh_`Bp`+gG3$_5$u$tH6*uf2;=94qBw=i-y`$-K8jY9JCxPKA# zyfMcBzzuXw-OSC#1qeRSaQ6m*yBYrf`Jw*F(px+fjD=Mq4%AoGaYsJ92k&3uRq1g& z5o(cdAjyV%CVC~iAr(X^$ySy;*-hx?IH3*qoNU9TU1 z-yp#)+NK)JllVbEzEg`P+DuQ`)J?B7LHI-4u(c~zhqh3VW;c@f{X<3AT(yq_YuqXw zNg3g)`eD>n$DR=$%kMIbMb!Kx*J?B(jE~_x7&%rI2?aliQg*ioNxId#5guzEV1Kjx zA-MRIBz{{&;8l4MOQ3Y3#H9>#l;%LWqa?}K=*D?k81k$MbnQhqg$>KVpw^;-;pNk= zh1!ZaKBeseY!68905ol-xD0HR2F85Z6K-1$n}mKw6fw2#{!?wJ-1#ZPaLrmsq~dxc zN&KswXrYIZ*%Ca=Nh_G=gRiC4L(gB0f>UgaELXb*1e~NVqY4*8x=p6jC9vh0op~v1 zGcb*UO1*c8CVsT6m1$}Y(l5wvc zrL0w@M`|&+_$mX9#%RW}KTe!vU#?-<_K4rAP6H754r0N$^r=RAG)>h_>y+l<<)Hld zy1eRN=CH^h2`WqkZTlQ6nCPGYH(3rC;WgBYqY=j6fRGInC_eQ z*l4N87o?X`u3Pd+(8-sydeKB6q9y~6qE+_#)AwNK)hT$HezTOC0C$&IaeUlN%F!fj ztgF{qj2H5NXa%{3&R8|=3>SaN(j$eo+;;Cz;SX3 zfukNLG`-~fVcg^T5(1YotXzp*1-{6_wBkgb51x7m0oHbqThO^R|Gfz{WKe<1xE`;E zsJB{ZOZ_1*#5 zEx%xl+^t+ZNIJzLA^p%%h!WWS@_?5ifx4Q$O}2EidOWo6lPfklF=Dz^6htP}Oy?32FX;~A=iD_vsK7s!CtB=e6lh#BRUYkwnzJR!|LGS zPN#+Q%$e8gK)!L6H*#%u3*uuJ6eg(HPG=)VCgkZARfuDVS43>>mlTPd|*tX!bC~xZgUftS(^?)6ierpFJz+t>`D|O-j6HV*2Ip}<6SrL`` zNfVBQji}-Rq!e9uB?5Fe=z3*=#-{sy+jTNAt+I+Rsk98K9N3MNgY>4oDl-=k2*ktA zMR#L3-l6-(FaQhve)3O>Z=eS(GYio7m4%b-hTRqL*?%AYUz^uI8HQ!tUfio3E@2{S zP(n5oLM_G zjrp~(SVMeu_5n||j`h|z6qy&wSWKH0QjFvi6o+&z$1uD+!~{+c;xrIzydOz?KJrt} zH&}&wq9F{7v&0oHAQuH6vEjY_cp4vQ-EQY1qKUr)s60 z4&947F-{--X73%C<}djOrQrz=pu*F$##lZwmZ_xdQhp0-gR3w@cdOkbLE?YTIsP;H z`iIS!Fl{%){cz$uxH_~{#no&lO41AOChG}+dZ9oNcdeYC)?qHoR~z`&MCHlvW|*=o z>#x7BNqoUp`%EM!-5=*m@G;w|`(y4)Dn4R*q;pR+lkYDc&ers5jj2A@~ zHW!D8t*=<@*2OMqdywZC^k$aLG&aI zWB=SE0p$Pv=Cs|ww?N$VrW6mT)W5de*Z^P+5K&eRpv%~Q>Nfu*ZQY8`GkDoY=ii18 zMW$}$c5oygh-?%J`1qq26h3{?_flNc3t}V4?ICn4KWB1?apOv;dQfbdsf;O1cx)_` z0BD?(ha4P27%1-^7ymnOK-jQ^363qE;@6jm1tzOt8X?M zlMH=xvc`5%DAO=A@TC8bzrs+nIqxy@sZ_I{c~_Qv z9~S%A@5I3krEOYK)x^{dS zDq%MqrJn5z$iw$ob=Ss@kh5zw2s+W|A|?!FUA74U&3n{-#QOEqebo_Ee-g&UaV-8o zmUbvZxM@pWHXu)^x2Y=sk(n)wdDo8#ES3|ruIkS$0b=wv0}|*P#=__dyBhfgsHo`R zx%>=mPor!;{Iw!A`JJqut#@MHs)xB>qP}~mkw?)r_~tHH$~yD?EUglfGY-?rL@Wp?lYj8QM#lNke@-+}9DA3vpzsj5R z9eD%R&p-O%{Jz{><0yZ?B!6sHv;>kBtevc`*V5};(i@rM02(;4gSdc}=r<%8cZZ<= z;I012hv}csfm)pTaSo4HJ*QVPm!M@x(!=C6Vsa`bGUaR#U$I$fPZ}yN8KmzTG)2ly zeNd5mL9v#fR!>fLzmYSRyhAa~@ACd!k;TQJm7KkIxXuIahO8C<|``6 zqCIU?W|=9erwwmWATy#ja?iTa*CkgpL=#XLo8OuCm%(&jEB$Q*Vi&xw`#Ud*WnsgJH{7G$yQWvpKrNO87#c~(4|GTASfH^bhSkQ!_(USt=SvezqobdO`~`@s($>BuhnJGz{*OSuQi zMWm>_opa)6*)XdR%X}$HRmGpw+XEy3>k^fKu5@@kiZ`hBZ&SE*T79SI*>Uko2b8a4zyzWMKW)I zafHBvLp+pou?L+7Ury8{5YBB0MQ9Tu8@oG&o#YYi+*Yg-`epKi^+rLCP5lU;>p&So z@OTzR@h*@Rd5!GIzB6{X#g6z~&o%l_n9e$koFkq=zVe*&<2P(-!*R?-QhiS!e-EGi zP{~3tDklNV?P?*jQjqmSWnKv*R)5WhX>sgJOC*Pc3+uP0v&azv z8}YN>Mp$ipkj};7j5c$@7v_ezRWWJDZoHLa5@;}OckcjJmWa%WMKD4{9m~Car_8tB zKjruN5-e=l{&RCgu;b_=nGm)BhKHZvj@- z)~*fHARyA+A|Scw?pC^`ySt?%q+3cl1PMXu?nXe65Tpeukq!Zge=cHgw(j@c=Uo3e z=R5y*{d%d4Ime8(9M3(Tx}S$lShSQ7)6sX329hnAX^cL~`uUuXjM}0==X2-DkSK}i0v|5K`*OQW@*~j!Tr(p2$d%aL( zD|!)^J%Zcj+5PRE3oQ1GDOH;{Av`(Ro**ItE4(O1+jEP^IXsQ#XX``@_?#cL-buW$ z^r-~p_C`#+Ve%!JYct^(i7f~Sd}=%l=u$lZmN#GFc|CyVudeZ24G}F-xMQ*Z_NoE< z*(`72xs>uv;wU^atPH@5u(<(pL}Yv+!z;3h5`!Is5CbEKg$3wR0l2x?Ic|7Y(8$C$ zlfbztfW!PcKkc@b1vtdHfJ7BQ)dDdCS{6_N;m_g!?92Sqo{-nok^3-*Zfgm*vqb)t ztpZO5qDF6bx(HSw<6nvz zNZU&1{S`vZWgrqXY#CcbyO0?ku=gg@=Z=Y74JMDh?v*-@D(nFe<13LGJig|3x%97S?A(CsH508 z3DWxWQIrw0+L;db=YESy%1>veQipfpQy8im_%{Nqw;rJFCgKb0|9F(R8di!5e`4%g zmd!QzgZBdWXV;EK*pmgQB99kCvY2vD#14^lsC7$L1;hpi-=*08d_Ll;5pP=*_dI>G zq2*E3qu3)+vIQnFeR)~biA6R~X}pSA*ydMo89kK)UrEMs;O@G|JE`0?!#_nOFfdB9 zo{!ILkAqjci@Dqg`?Drvc`j_BYsEX^P^r_0Ri0XX8(rQW2UNH0X4tS_R-8gxcK(Gc zT&E6+G;Y?zzvg05HKH1AjVFA!v{gGT2T7Xta~bYIWya&b^J^(i1atRfxS4E(?0In7 z#q~l#u@C)wRrPPL_z(ECkUSiMTJ&B^Ne8Ph69xakG?IKhp^k_mhru?-Ml`ws$JFD? zZ!tE*gU`Gf&4)J3upilO$Z+4J#I(t_ss)2fuP~eSL9DalY+hP1N>GTRy#+Qe9+Cf1 z@eP+rL+#hW<{BevKo`P&6Y2H zht86lbg(1`(6DM-9%@yr2LIq^e_L&EMr<%^=Y~ossX5t@!&zs#p~A1DHa7|_DD9gw zEN7T^NB9orDMUe=kE0wzi{NK856N%tP%R_t)R2_wPOUADeCRi*$*) zvLrEaC+BppCS34qWXd?@Qcj2@^`25L?41=1C9m2=Nx6SoYD7etqTh>XUSG`d>g$fT zU!8pA+1YmF^a6$;uqcOINwBKuT-s&uXB=}2TZW5(%~G^Y=4;CA8oH*Bv;k*%W<7O~ zw53)~L^Y1_E1T8b54ItsAqk6#MCaqvmve&P! zjk#kXiFMHiUsW1$FH%chyqvEY@}*qa6J-g0Ru4C8)mR3{Zzj}k14Nk3nNf@kH4Krv zn4$e^m7YJX(vWk%BwVNiwy^w_JuD5_!>rdh?kNYuML3#7e;dcael5{kI1Xe+UAIj| zL`D)aF)??rzO;F7!kf^@*td?}u<3y=cvtx(fZfXl=B+YccGm_*Ko6p;;eXLn{>cii zc;3%~!(bU_WvQ>2x&CVKX`J*@oKI4pijk;sl&R4I+@cnT)FETa^XJ6$yLxFL+5YDN z3v`3T>F4ZkSX|jeC)g73`Pf(8Q6|PDvMkKQKA+ZezkRAPw*Se#J~{fnWpZ_}QxGz- zZf!dK$r~lw>3SFbSZM@=aN_LygrgS4WMA`KR7hJ`AybkwY__Ci(vF2pd7Yg=js zGp0;l&fNE=yrv_OsThtA70e9sD)?-&E+Y1%Td}UPSau9S?X5)C(|wgxqjaht6_vO} zhaG!52w;sh3|^#e3PmtYt+0N3LN*5JK5kTF#5K^n@owWWv}9gp5~RW z{2uoh@2C+iJz+o;u$uUIuym)wN*Mxi9!n<3*}7UiL1V^x7$S2&MY5@#Bd3mi-ZLm5 z5g#jimLXfS@g44QwETeGlOrlqiN5Ykcy6zcblO&U+$NP?XEC;ZrA-L2QAc;p?~L+e=MK&N{q%OFgjqKQgiV`q6ctJfN!H zUmXOXXSW1OOyx$$0l4KtB0z^pYhwqnSOFnJAyN@3aZ({pz^lu`%*k=1F(F~#-zpYn zXr^y%0Ca!^+{+BM4yH`xAkr%rGoHxx88CNM#MTiQXnpXAj!_e!U}F& z!vf?GTn_=4)c^4p^n)b5{iXd@U$UBAWhqx17c@T^q8xMD)2(>KDF1n@6d>wKcoAsU zId`6B1yh_bZoEf$#HHM!;9fbY_l=X+x2$ic{&UQI0ZB+Z=K@%oViNnkUS&QaI154k za^!$bErO?Q1|2o*k!;$K$oF9+*a}nhWHU|p`X~`o1+(_GUpCvn$%QbZ+3db`y^Dlo(|ej^Q{$3(4Nz-Q3As zy$3X3AvDqz|OM zUNJzQcZOe94CBq%0azNBt>OQKhQ+vpQkk`>tcRLvVKOdoE?+)ohyG^8{zm43zbteH z5DS0?#lD2MZ!dT=xL&PS6Vd+z6V|!5gHQ24}4k#-~cQv zJQO50=;njkIsX1Z?HvF5Va=SZt!}Tg8z4g#N^HXqY$5l|_!+&2{}H-$3*(qf7bbPG zH#dUHDj_JQNhli9A$En>OZPCOOFK{S4quU!nAkK!1jwxHPTkLT#{N2_IRRG>aW8Ik zipYd0URXri;W%m{YvdM&VDhnvK_ZOqZOQR**u24RiF6)b)*c_ZQOx?&yYfFy%D)Ti z7R*@p>^l#7v^r3hLK14xow>_aKz72a)voXs!hQ~3gBKV2uqEXCR(;Mt`|bO2SCSP7 z-Zb0DugrIdWZYQYSb5`8C^zKnyYSo_Ny#NO&L4Y0SFflybur625u45An`xHwZyI=g z_E|-AcCX&7Fis|mo-Z7F*}z%p$QyPveeE|F1h9<#3eT7UJj1`z6Mm~W0`j$WOyZgpr(L>(M`n+L}WAoq->3B!A`sz z&-!%yxHv zX>gGJwuAL{UpW~avE99lMQ>p;L}ia$eQ$PpaLYe1J3LMQ-Q{FrW&%5^sbXw~gde2i~QuZS~~&NvSbshHJm;SVfpeqz$T zt1j&SWT@*HJ_(zY&zawc5Dr4`pbL^K&xtVB) z_xTfc;J+`td${G7`)ml5Q}G+>{N_9JxWYUqkOPP_lRc9)kog7*z?gTrv<&sZKQIDo z>DE%ZSxJ}B2V9rQ9QX%_{Bh-For!;Q-CuY3OX?DW>M7KA%IZbV$tRC4QJ)WT9i4{| z>iw^)8Zf2IU|d$0H?_Y*-P8LNA&)CZDGRx{T#~!l+~A}v)O>b|Uehh7u^*xb`%JGI z_R-$qPFr(Fty5qXy_aSG@SgY#W7oVzdpj#Momaw)MjJ{VVp1z?*c)WVJuU7*D-M-A zL9S-chuU(`a_GQsZuc*?hK5+qhNft9$9q>t-veyKi?FX*s#?_*Pm5 zj5pD52;f(j87>?c(D{v8KnTh2aQSD%udye*w7II+MRtWBL;!xkUf~C-tS^12pYc2r z)FwY0l=u?gF9;0s_5FK1!T5K0g7F)kV4#V}$;gSy-NuvaGCt54#5d>ufRx`lrh?dk zaQ!V*0a7miM3w&y@AyyPG9(xl=CBw;@I#@MKpE!cNI`S!a;P>>(9ind4|f+C1>h34 zvmeSQy`AF8QY&#%upihEj*$^MFX)-D2y_*#e`1m-uTwEfXD2#1$q_GX&I{_WFIU_q zlgXN>yQ1i5ZhBE1xvH~Eo;pAr~xIec(TBH>+w#s+Io@u-LNSKkcG+E zy!b1-X|vB4Fp?pzvz2Qpl;-oM4I*gG(gHH|&x>`LDp`YGM6}FTlF`gHCq|F@FOU{4di}4hh!AxvJgX5;@>XjRbua@mm+@ zEj-At+*0u*Q#3vvyZgmzpFcd-F@^!ELl)lNwk3*FA0eOE7qNwrlu;-wW?E9LVW(@h z&c%|Y2ZEkSTzX?AZ7?|Qf~7@ul_HR`W`dJ*j>d8Zy}w&P0!KQ#4KCr%r>S!RUU8v0 z^##>?ygaRhv233?6^k}|zB7Pi&eq{aKs45WDr z9{`8M4O124o(h8!!|hrH$N-7wlI#dAYAee0=Lk%9z9x7yVx%-MHY!!G0=y}&pF`0wD|^o*Z3PNgR1t$rlE76bzKbWY5LwiJz{r*o68FpCuo$C#FIr>+QvQIX=#CIH@T6BJ)Wo1V5i0l=qkU z`jwtBx7IWX1 zzxy)&x}Gj~>z6SR0wF#12QB7~4|&*%>dFyZ`0VbySbHu?2I+LGQt2 zzMm{w^G>{<_2hmZG!@>kKbbS_$~-|5<@9sG_|^R3{zG*wlP!TqiKu==b%@zBnsBsf zc}BA943KO&6#^K=DqqJO^UYJxc3$o>5!(um9=T;i#sJk4VWLe6;b=d6aeqsICc{zQ%v_ z{qVg87pC`d6GXA$s!$D|ZSidt*=?Lv5miR!M1siBj6=Pn8p&oYnFR=*v&O@w39+re zSWlQKd?Em;WSu0pv9v&=5#3tb@fvHeM{NDIc4R95wh@I(E>JtjwravdLEq-}v!I@Z z>Lu1`q2O#QwfDNK5U1v`V(-pCH*~v%R?f(^r(ihOK(;LRYFg&jgiIIZ z%s6bwX8n+BfE)SNW8~z~7B7@)?5MsIoy==d`m(nps9{jdT5Q3FT;ROn9+TGUE+7$^ zfGi|j$pcW|4C=bR85%@Dz z&W<-GGBgJIO}m#rn7~4p3lhxn;Q-n@0GkeA(ENA9(Mp#+J#` zgGJXUw6|6;8%e8^c_GfNGp3@a$M+3Bh1qGZEWtvZ=dQV6aaM&zf` zo~2ii9lGgbk$_M=MXHC2x6wA@DTJPZuK-Z@}z^co32|0z^!5xZy zjN<86ox6Xid%hv~I_ zJYgt1f^UKob+FKO@Hq(=XOb+4U#4??qf=yNyjE7q2DExC;*W9RE0WLpV*uoS)qJ!ArIJ=!dLbsKVV-{UfGv0kCejy(u(+! z^V4)oCjUb37qf8!mxR9Fr>H@cS33=flCd!<_A%H)#z^|{kRzLsV7X34$?HUxA*?_cBaDD@zmI4^T1|9;% zU;aP-0sje>>Yi6QOr;}RE+nmiAoEZFba$L(HX`DAyek zlO=TcB+I<(5PI*2Ki-gqj}L?xaY^?|ax=Ob72zv0M#P{-3riFo<2^#xvC)7CJF<#$ z=9RGQu|O`U(wbq34_|wwI(YJCe=2*aHEpljv^_23Mp9Xje~HbEp~dK?+S(RZzN_(- zDmjBX(Ngms&Q8YZ^A5rkl2THoB{QEd`%jQM0 z%+dy~-vG0zp0xol>}{&TO0{>TQYj1hlJ%e+FaF6wifNVqenjp&18JFg^&%rybm*h1 zh&V%v9Q!L+0vn*eM&f?+g#D=-TR2d<4-s#9t?-yDj9NuxM5CL$xxHImQeA-Z@=r5} z61u9M3Xn$xjRZl%=vi1MGdu}#L@N^ccz|&c!A0A$+bCxjUcmSbrvphjeUu>KB@1tU zu|YP3%bO?WHgH7V9krqnFW;e$>Q5o!iA(IQ|1fM7gcZykuHLUqW^XPCb_s@2fuT(e zdWO%z>rJ1FKQS7j^S-f&&uYT@-PoSXy#bzJPVzLX*yIkrW=TIWU#q8G1kCuv*la@@jx1E9na+_+M4iY(UFid{m*+$sg9dW^fu8y!= z#rNHvPWGpN!Utqt^B`r%9LKiU3kB37EM>@vQ`pjwtY=RC$x`FfvL2z5wqat2R|cpL zfF*8Mc;W=$iPp8hO0)?%Odf)w0&Rqy=G++Z?DiK3j*t5${#Ep@v&IpCTBOQM*BUWA z1`6Qsb|RJ5w**S#o<(M#$(7`f^@82_P3aDfYTVv6sX95Hpu0tU^---F?^xEw~|5o{cebIQY~i^_K$h8r;=^;`cCKxM7$ObW4x%Q z+*}*97y~Bj@po8qtP)FCyS}$NKTQ?aiFh+)aaK#Cf`h7Dj<=nBxKpZKm1q5P-X6y? zJNPHW+&MmzD{?ZVdnxlGEhIdrO?$4+{RXiV5Bb(!P}I~Ct^0`PPZmMq%(0g^4Pim; zAtTzEk!6L2hmq#NaGfV1WP1o{<_vdOQXbwFzZc#w#ad#n(0B|tU{-7*-N0X@--sBD z(lf`m=?Np9hNxp1^J%ktgF51kOi+m9kWJ1IF?JZ{7Z*|JXNE;z2c%LvU+lkO&XUx; zR#Iv~zE!t%lCIxv-9Nz~%R!ftfcm9KJdoEl7Lbtkc(`2*=tgy^kpTIkAg)Y~OtwIl zTaK;2EH}o#Uu2i+2^07(4`66O)Hk6xXvjZ)g8kzsxIcb^|3!!{ZEy*^d$UemNr~@H zi>Y;-BiHFoH)TC&$B{1%XZuvL5x+<)8^`KdW}v4Q>-f{HYrJjwO1}?bNL15ewL2(P zFB5AE_ZpGBOv(U3_M)c;vn&`}dj;|RRotcNekY~l-EFqy=i6gJbxajZGo~&dPqNKJs8;WV$z?#B+#C0T z<`p^eMF^#r?tNN`aV(+&i*$v%Gz#gy$D=$tcIeMgnNx}D(~eB?!F2~-U)dYkfV~lV zjXxNHY%)XwaJ#L?#;{}2ga*HSb$>~11XP>rs!@m-Fsf2YLQISx`YSz!Qq>$Nx_wnx z`?9v5zST{`DN-RvM_WVl%cD1J7N8E`RVB8`n$#Vi38g9vRS^ms7aCmDnXYMw!Fjg{}H9gLeXdxo46VFV+uFl+P?e;9nO%`1M?r}mb`IIGLMDAWfvTW z7Nf}>MF#e^zBzsn3oUsqbs_DQW*^+)LKLk@w0YM5WAjWex6~cm{v-B~Cpxc{dE(St zU9Mz1Mp#}vahN1h_8~nReYkpT;c&Yjpr7+oCa)kM8<*)OV{|jc!(=Q{`S@mF#m`-u zGZA^eLM&5NUp%Luts|#OK(${d-Vg<`9P$le_vsZkw ze_vPnoknGYNCFsN{xY-kVvP`oN_eY?$n`Grl@Q9RB*W6Vew>^ zfY$2B^_SdNQ?>DBr^1!{o4&?m zBk*>LpH}+{G{X5&(W9!vR=UB~GEN~|Mn`*NKH;p7qrh1Dn1(qw;wK}%?Zc(Wd~fl2 znY+lY&aAEg(ad5QL1q@seP|m7NUR{O*Urw}iTX{mfzzXsQ;jsuk5ndCz2tvZ_~6vU zHAC`!o2>JkS2x9}Ri6(I6gRa>LzPfx9%A!+N)w%}fr@sYt(dX@>m$v)9;#jcS)F=8^gA{+WJG`!&Vw(DDSCXeV|#3@0J`)uqAr&pr@;=wG|n*h_YkYdH4&BX$zlb zZu0t|2Y!AUrr6TG%w*$PM(V~7ws9u@k`E`o8Hc}%{cMz>qDI+l+sDC_^h&RuusDR3 z*`P**49)>LOUqik^W@$ z(3(&xWMzr%g7Oxh@Jy<8BD_WTNLRb}wEJEz^KPbBfCMJ={{~2Z0+5VYs~Km#V}W@V z>B`0ddDeZ*@$|n?U;cK&UjZ%fH^c%6{ic?1wYp+FG>=)zmkBJN$ddQhR_8qE&Fk1! zPCzo+D^-`%Q8+D2^q?|sTYA587x{sQ!Qx3qMNqYv_&fjHM9J{n#vN?h6c;*oHa#me zpTz!x7mCZY%jO#eN9^=;uFd+A9}SUeH5E5-OGJdpUzfVRoi*4~=7SIOej| zoO*YP3c|IoACdcLNqm4>M9UDpI7?>k_cBsISy!WU;a(&r=WTnERz{-Ns9(f+n0X}9Aezz#Kyjjeh1MUPe8Ap~piZBar|=GhD0T4K zJP4j%RNN(!W+|Cx95?$kl@qnUi)XkJhuik-?SsYxhbKm*PBfglxYBcj_Anakqs@#- zsjHvsO5>NI9+PEhjMG=%~-%mb5?^3QE`51W!DIsKCMn|U5F;T<qyHDY-*r@Vd7BIsqEV3UO+y7>hoElyZ5xzRbmi7p?7 zD7Ff>I-D+l@TZo2?d13KRqv>;j6`Mm&OsB^SxY>FNsq*b{PDb6vd{_Rtsm`Abmz*j zFa&T3I(uV!`k=p*?-nwx$@I}zer+X7GM|P5zt&sFvU1*{LQMzdlZSVZKCPkzo#+8C zd6D#!Bb1`!NxwX*VPs(ee#vwEz+>I|QhA%4kBI$a_TD6U1fB;%?XS2^Yv9q-p|5!e@#=*YW5c({M!lOwst`7C6K1?i~8GY zx)u4n@%{9EMA2aw>o51@?>ptYxJw-$3)9m)Iq}A8~s5ac;rto)= zRc2wq`<-{8Cjv;07X05B1ieY#D(gR8XF%W>zrPor(L_}GCC7Oxb3qxiw2ts$4(=g( zT{b4>A`@GW;6?R3tczMJ;gj8?=C2zM478qadwY|VHyu}#q4h&Us@mnDz91%G^(8J& z#czk<-GI{nL=3m5%N?{!yCW8~#8>pOTkUzH<=g3r<0=9JJ0w2#Ug2Hlad-XY;VHhs zo`T+#=_z&5aa+!J&)h~{72`YC5w@~>MiE;RwmXZzWrKZvsKrONsk+_kM^5jq{Kl@` zi`>}HF5&k+z))xq-!t>VY@9712Rl6b8RK-uZ$rbS&*%LusRMMne;N4vr|{$Nu}!Z3 zcx+P)Byy!I^8OLqyox8W{wKn#ELUzKAk*p3WG8?$&B63Xz{&UjrVsm1P*vQQi)P;S zElO@i=qJ<+^n=Ui5*QDaVS{f3m;hCI39?cW{V0Tz47z!E5ZFiXi=P^he z{;QAm>xl%0Rk|aza?ZOZuT#GD-q)OpT-d{i#D79x2(|q^C&*;FRp4NvcK^Fy*Dzl^ z(4|D~dGF^}qSSB}<6=eImKIyGx<_b!#GHn#Ci0{Fv5qI8c9Y_ZSo*{*=u4>jWw~G4 zdr>D3Eaf!6=Ezd1ydlSW!u!4warDvDo0%+KrOr$>uC@;nv`ySSs?BYmsZhB~VR>6z znd-SmU_Gpp2|?jLeX+4L{%>Fv{GcGvOfC0<^(AznW5+b_&hLz7F|!4faZi=_z4_RO z*dQ0K+4&fPhlIxOwKsdfv^TFQMCDf=#rgboZLH%i>+ND9lz{4jWJgR5%_t%2ma$cO znH-&g!p|EYrYFXDg^6%l(Y3`m+d2160~q|pCCkQ1bziVYtvtQ=QYUG3dnl*=K&g@D z!;_MCHqWf;hlwFd$Tp6I4E$;*$~x-B<@cC6qagF0)(_mMCRcu#i0q~N^OF{~v+2cr zxVWf+hkz&s{($`83qXFbG1vYXL%6`aP7dQ-k?4F2_5M-jU%ot$Z`3WUkX8i}iCDl= zi-gq>W>Er1ql^7@WWjzF+S)!f*I!NJ&+LDqo*aI1i8zA2>#~YN=j1HiXuV}FLerbK>1*~WXN9TII&(2IoLP= zzwrOMH~uHXGNtDDOkagjE+-eWk|DB|BC6`yj7wtRVpIK|8< ze}3mlEW4sRgPVR*#q3hG74~5j5Lv=-?-39U6RQwTH!G%Jy5aft9z8SSFYG-pjaV-+ zI%wGI;OCD1CL1Y0fY)H*-yXwjrScO|v1Rp(wrc=Or_|hci{@r4j`K*VY%JUlVUd=^ zoUcH(!M@%Os-pNE?p*f{JE9Us%hn-ewPx#Ac&e8vU}G(1mSaSlH(wHT2N0kMd62W` zHSw>yb4=sTMyEv$l#M3~EZ{uTMEmPz?1n zUl6pJpnHp`O5RP6^g^UWdvO7aQ!TE;O+H+F)0KS1lQ$nM&NH22u9$29)lkK z@y$VE6Wt1i0Zkl@8LV7xm9h8*c`xf$kWfEjizYKPLu7P&_lnq$GVzrFkhJ&sm9RS; zhOuTVOy9bf=T_YAPRK#^oFWvN`S7;{)}_qB#F|tU6x4uMm^yT@N0rsn~|1$0B8j8k?F)vfrox@wH7w;53S#p&NI zVQkqm?j`+b>+O-IuB9F&8&6jrYx%Gr`Bf#(BZ{Jn^Yo2-j;bqPzSx%0i=3fH-t~@Q z`*#%`0pGEXh|frYovXn`H#MOnvB)wNg{D;PGJ8(sStmWCd+t+o_i?ha2i86JvfK3^ zFG((_)n)94lFdvRZBOFOeP~JX;c9brHN;YKcz%)-1quInf00n(Wf1niY*>JMOWBms5aej&4z8SYRB#v%QBjB!&j_hZ;Bt-OI+ad zyH`cTyR>h<9)P}MwJB!$axh8KrS(IoQ?i*NBrAE(#sVhN^F|xg@KT4Ard5P-wXtX4 zDj@k}zb>qru7rE9tq7xS#f$gEd}^Y?@xfz#xzaU9d`hO99>~|=y`9?VkiIYBr)h7x zcQUOkov$_Vq}x8#P2?PucE&y2xH<_3sTP|ulI{>L~|KYRY9Q92~ncl*DkL1rM zoU@{8SW8FYJ)b2P?qX9B5%>59JgBZKR1xZjCVxyH6A`u?^3J4t?SgiVw`g*>y#0$= zYRHj0gzD_RO1#z2I-?nbusI}G=5>R9%H)*#LIZ#43OILA&%@>oIGMy+!VV_dG2I3w zbez;AwTC9I`eaP-3=gEzaCbNNXzjx*>$u>hTu-+cUPQx2&@;MvY>70p)hACJJLb{t z4ykQY%Tnq_MVsAWtT~#7TVqJ(SIGNF-hr6MDQQ)HeBt#bP;Ig9Q-GUmoya%IXNMC_ z_pOPWKeAh?Ywc|2;3?xDKo7ete+h5oEgzA5ywG#>>_xtdc&e~5e-3dgJhX;5eNEzC z^;nq-*;d`OG(_T0%y=r6=2a01@nM7{Y&{;J8Qk&)=eO^W#JrNKQg^zgIUv%5QCb|o z*qW?4NPzfJmyn=)lZ7FyI^(?cJ3{B4`Qaly>3G8ITHc^%uF7>*0p~&Y$%y@PqvXbO z67O8{D4H6eH&OMdQnZ^aJ^q=mt>`!pq*H?MJj4Qn<+sjFhobuC^KXUuN7IL8PeZG& zU9G}@VS1;vn7&3P|4exx_U5&*A{y0%SdroHTi~w_iCaE{o8FS;YBHz>vfN*bzSR)E zW4_;0E~TN6>Ovjyv`|ePXY4@nuv&B#L9`k7`7n~tKqvYcgbJ*FkkE7`MLKWCM9)vV zbVj!Xe^T~Y&wJ(=!MV=tFA-jM%@uuERR2`XKU=rA&MG*O?R(%Rz&MtB`Z;@42L=VF z_*`gvsm$R-)Q?4Ym0taaYPf+wop4DivX(c4F{PH097LI$ch=n``iL5$$n1`iGoTVt zPGk>^K|#j`8=!@3pm6HEV2riPEl9P^^THtV?n00()iGUHKzOjW{J>K2VNB{Umm`AO zY!Y0BW*REomo|v}8p20Vh?qmILhpZuvyplEaqbo<$KbKW##vi%ca{y+hXls1ru5$9 z&U3HH+IAB^Ipttn3VpsecMkJ8%PffOheFbK%)$7A)eEib}f%-Hsj zEFOdWY+6;|5c`eZq_V8$D<5y!mUQ^Hb@=8tY{@Et4Y;o>^K~lxtt`z2M>3{&+RZI% zzgXYd-zk)LL3H& z3k5d73|S`h(D<;PHE+Sano;iz;Ny=vPk%UHRddG-j}TYnDqn^a@TFp0`BU!!{?s4; zD*pB87N9CUW&#=*fo&9c3`AiEAmr?51$0WjIf#gXC~6LH*-7;o92sshXQ6@2Ss~KP z%>~>- z6oGYxFUkcoa7p9Iyvku*&;s{5KXk48J3!?FGD7}D$14^jRhDdibqi70 zFT7xpt;C_VTQ%^kTZC!I-Ssi4 zh}BK?@nBW4KzQgl%+jKp^g&?ZLDUJKmHjLF_onM+9yTlm$bQuM(iUWbSft35n*MDC z*jOzTe%iFy#qSLdoghl)L^@FQR80-9%QO34fP7DXN0C3{IT2-2W@!!x4{BSe4&-B1 zCB^NJqkdD-*}+OQ8Vr!F;EQ3XZ);}^EDc)+K_l>DU~sey#J;8Y-5g{z)CZY>uOop0 zns0&VGifs)22%a~L`H!54$RlRx)vDxl7I_PLvP*o_u1f=j)`4H zgn)nmS690QkT(o+ZB{3J>32L67a7*-?1X$szIV}S#Zi6ER(Pp~+cR1?ol74&{w4Q{ zRqz9Z)2C*4gS-rmDs+E#PDnSZHwcJmjuJ!4@ESJV-wGelkgqXQK1NJpL4){`-X`wq zckl!*oJ>0C&cIUsB|z8#xh(ou`7GK1K8Ri612n{f@GoB(NaYqn2q`oD*|tuI{;IqT z9ta1F8AuqY*GK4W6r6!vTp$c`eG2;bQ>_6eg#Q~uY zT6#LMnR@@Q>s0rCq^Y93dL4R>1rPR*a7Q`m&_{cEG3)%sNe@2@jxiu?p9g*#F#a(! z!5j}S8^J^AJjHS7n`;Vh@kM`)iJsaZn_ z4(J4$q^tDe4U?+SQGSRiC=3P>!uUTVT60TeqIo1CQW^Vl>G*4r%#T?@_f1cWDb0y( z>5T175tYn!-Y*`r_1hb$K;?g6)Yd@3P_l&nIVIbzDjo(BDx9++K4Up*Y zJ8FP;1|k#~L>L6wCm*_@n1evSA;sTF+xjq{gu3#+$09B2u!}?7>AD-a-U0M$t)o5Jq;B{YlKSYXWN>7Ja}7nK`WO(=vS#t+LS#0975Paf%U zm92it%lX2F>Rfr=u84`mIs5tvbqs3P)pmR#2*?`imArufc}u$XPu`8hLjO`!?;63m zNHG@<`mJucZ{IEH(-68Tyo!KvIvlUQ`)%2#f1ri3yU&ydGIcJW*hVBBOyRFSlsw*@G?)6>dfqFK!Hb8!w zu)d?YAwb~1yxFZVDITytT+X030M8I~x_mmAI02SxQr~P-t zu7-wKCF>S>IX|pr$vC#x8cnvsC-)>aU7a0fBBW9h)H2;h-wP;|nLKr~pB%k-edZKR6CK%Pf%a_4)ZnonmBf6hkQs6x6SYLjs+7 z4?n+FB7RIPpnTHuoXzoDOu@8vtQssFGJNejBvGzlvdm3C#{zLibE^kV1p{+=<7WXN zm^ijac?2vJbfVZBh#hl2g~s^J_LSRT5d!y(thnkMSpvup-nIOg_Iz1gY$9wtjp2!W zeLqO*m$wJ#<^Li1x%MN#V<3q-I~eHOxR_g68Q(OYLBxQ&TKh~yAaDQ|*y%8DMCx|R z*R7oI>(k2S)_|1iTiXFL2T020`ses}>;He%+y1-t`-xWFO-X_mA&xKX&!>n?8J$A=s>*NH+LjU{anECVk@+c&db6adjPe>GV^!>J zaOAkA38tmkP`U13yie&FG!dAV#vk>C6ILYoLRpH9Q@3pAz$CgV8=?7iVXl{ z3e6F2Fgw0t=UpK-0`qFh1DyU=Je|j$S_}R@F(-^aldG}8>z5j^#qh4|F)U#Hp8YF( z%;?s7RTBHd!G(b&WMp)yZjlNJ-&%)%99349|AU?Yly(9yQ)mpFKTgX#8vt#?!R0po zC^7~Du>n~s0H2=iGRSm$2>PFSi+|F^*6=}5{=t~7q!YX;Q3T%5PW6-KBjUM7k!{Fm z(F(bYCdz^;-=;_&scvT6x7p|F%c`~A^*+`PqSQ|(JX-kv+V_a8lcFCDSzwCN!Mz(Y z5gzAw9G4E{h2lQLaZXn8f~XD$-GF@+b7&=nBoi+h-|n;)m| z47#$4%aV5e+CSH_~xMpZoym2gCIb_vi zJh{y?fcsr@^Nj?nZuen)13|w2KA3-Zhb*%klmD6jcE7*3%AkK>JvyS8yswHK>oUVm zUHg`xrhUh#juh7|{vnkbY=bAweyxJaWDwNsJ!~ANqr#^QcQESTm6771FU1}|KK5S~ z9V-)h&>ZY+dx3iTNO?$i`(%sV(Tjjxtc%RL0;@)LFjXs;PXi(nZjslL*<&|jyXtIi zn;KVgyQ^WSnbjwu?NO<9WOuaKETd_W7|bj8X_Xhf5+)P);oTdlvdQ!4^_3RV&%b;j zzZ(Q$bRO`bgzto#4YXa5r>jIJn}@z6ePSh1Yhss+6$e!8|^ zl4V|-9tE>2l`KQW(`_UOb7H~9CH?S|d({-PL0t^m{8xv)z8;<3XS=*74_7SOt;=b( zq>&psqad2PX6BQi@NBhvj=mnI?m2pfiM&PYHrfDYzwea#aL#nhS|1A2u)ssvhNF z891LiyrT9jH{qy{YNUCLeGbc%$_~?QsS2T3M@mf+mxHsB)I?Oiv=lAu>~c!|f+7Wh zJpnWGT#p}ea)6)-l+xaBW26fAd^+Yr?^t`!x%|4yh94wAa)D&~&Hnl=WNHl-d=eNy zv_S@$dYL*oTA=^V|2*L-7_>QYxy!)#wLO`m#pp>G;%!LvjlNeNmTe}%Xpgi!i+ z(kO)p1HMlNO4YnFKF5eLW`}E$TWCGjyc0sO+Jk+DR@8%un4Y3!2+>XSNevf3y=={x z#Od=fS9@OJJh^6#tW!KAwSfcqzR%j5#mEW6+;S$T1R+w#-_*%32p;WDsT2kPx7$5dt*o4gtMRXVpQ_u&&-F0zDBVztZW4Au459Vy^5R9Q9Z4l9TlAW z8uSV2D9c)&G9Z?~p%(i|AKF@G6v4)8HP4ZInV26IqAYZAFD`-s+w|#`ed-M8C)!uI zg9IQE;77xHtkE9#%l8ISyM;i)VmGcHL=033D_aA7D{z4kQX3a~NBtX@5fTRc6;DFw zR*i*Qldn%+YRQ}+Agc!4lIxN!0T3scz?B0phyQ&K{wM62L|IOX`0#2`F4X(yPMH4# z%Wsk-J2WM=@n|rO+lC((Oicy}X9fu*X*VN6B9q@e^f7+3)=iJz_l8i~4nB(y5j21m zA$K%08ZM7TxFx^Y!SLgBO>sBIYu$?;f za*oQe7y;Y_4aBUKVX)z~u3@E9B&0EK?kL$rfAHXNs(b4<7AD z@j}T@Ml|F8tQT}NtyXvC23W-zn#B&s;QAA=s_kD(3nkQp@>jnK6`-XDd@)^|%Z1jB}s^ z$xb0I@g>Y$yKdYVRxhSdYKOM75!T%c70~ybhU=!hlQte4d!PI=#oas^YPoS zw;o18mSR;R6Xl+p)0tDa5tru?+8b=X?@27e(GG1pk_fb+=}={gA2JOIpgp#Ftu3C0 zTZ?0raSK7Y0S|0_8JEMMT)C%5Xjzf|0U0Yc*cgK`Me1ONZ! z@PDlwLfpYMt1*>pzhlz${Cd4)U9)ndp%tl~e1%$wJC>b9M8hSURx3;v| z{-XXQ1M+^-6z>{;j9Z%k8F57|TOZ>ggH_3WYt{S|^^3C6fT<)`Lk>U{2hu+OOCIu1 z8(c??U_;E9A<1}BW*D*{u~W5Vns_)=**t~rHXcSEhrgwEcjWPN&Uiibu zAB!IMeQKi=iT2q|9SuO9j^;nbFtQ(6V@~CXT&}3aiq(` zCm@wHJ zEftmSM;|*6td_yD+o|Q`b75}gDq`jbU2()50r+=a=MPzE65P(*5%|(aHAR~)HsJWT zu(yZQH7}yqH;N|rxM3xQ%i}wlkcBB~YL;@YHaI`%yMS{|{uhlPC`7Qyl{>8q2HfaW z^;FeNW$>f_hEM-Ge1pY?1GI%$!3>bg+=c@P!%r~)r|0In@CBau^U6Shych!x!gxgZ zQwNHbF?9P`fOSE~_{M+x;DEv((JfU@W-uQI zGZ+>IF7h`!xI_;*(VkD!B)5qWd@3@JhbClCC{rkvwU$Cy;Alh2XslnPZ6ugaEr(G* zgLik@_)wJ*-^2-ZhC9jY%NNTUITODcn49Q|x~Q4ze}RQpU{e|P(KEWafO){1cB6b> zpU2$x-Z-4fy*E87gVpCXl5k_l6L`oRbO-9#Bl7(bsxqadTSE!%leb7wZ7YA^(QG%{ z3La+2+(Tcmw))I3jP<$>O_I__08k}se0R7_REFEK{;UN_&naXA^Q2j|Sm1|U7e|=r zeeBS)L|A3_Hs-a!v_rmOq}p$_ragk{18UO9TX*M$x3G_1^Kg8EI(V`iLvm^kYgm~G z4=-rxhE@08*5qOb8VYI=_yShY9Psu03O6w6c`}LPkl|)TN@%lCRyY!10QJjT^np@+ zg23knR=DPdqhJ%=aEQf4MX&Jz;GRF?xIx7D^{VS9VX={aJqdx6t1*@km-(vW81SJ1 zg%NgO4+r4nzyFFFU~B}$%ijoChgZKEEHoml2ozjpoBL3N)m`)yW?n*K*vz6=i@b

    VPU_h^1v30cZvMGprJ%s#Fyv5E(P^pJ+5NEZms-f+c z0L-_qyxu3u6+(Wqk3UUr5RttRFey6Qsu}#Q&@GhK|L1S;pZ2E)gR)qqYPHkjy~ikgcV;o48pnS4 zRNL#(e@GX{Or?CEis$>CfGPEd-I+8Z@dGK(f^SvD_tOK#R(jg_8sT*E|K z9hC6ot=^NA)lu1vXHI$TR^wZA4+7{BaE_Fhh9*rALyWkw#s)S%dV++-GB&$Y@#pMK z`bbP!zq>#ac6h_8m&ZzzWMfgUw4u6u`D)s|rjt#*wb-Lq_c#Zd20gt?xwY6Mmc*X) z0bMZcl!bUxCZVn^SMSI4_Z8>bJoArge~5`LMb`Y>pI{yV5xN{$@S1xK4GqT%hG>cW z9JK(34kU*#Z5)9)g0@DEcFgw9wl0tbW@~EdXlCnRa#@W1i!u+1h}B;cuY-XeF9}4BbHnHtrxh z0|zJIk)xwCP#Xgo7#W$^IbEH=^zsCd334C68)t}&_2v*=6$0S~FK^yXyuU^F_AJ=92(k?WDfVozZ^l!c zzk5xZuYabm@Bg@!`N8o)!0Go8{zfQpO_T~A#wk1h_9{Aua5(dc13|=unb#w#>BqLb z9xeI0g7fO{W$hCD4OWQ0niHV+ok%LA%3bVGk=2#-9nhR^uqfp_dcq1i*(~9`SWqjz@xU{i^_Eq%b5kQ>Cq08nOhWBNhL>-z3D0ys zeqdevG#p8_D(Q~?xlYrV#}ua9z^G1B#YiDrA}n8UkMdn!R$otS3dL#(tF)Ro$8c8C z)J_qDj_W<(^rbZoiswJ#575undZIJ&S{@Osk@pqvF8TW|R_6uM?ulyZU?mrjPUJ2k zTjcnpKBw#7dm%f#(K^56F~CI`{J@Fp2oeem06DSttGw7p!0O&!;rpLU7=P(U7ZYb? z09qpeY(_?=Okf4uQ!W zKQ{zeRAOZ&WfLnCC7_r6YPY`ve25t3Pkn4aO$^xRfk=Y&QizcKlIwmgmwU4x{eS8v z{|V&t^(Kk*Rve=iC$+z&FG()$o2lr-lfYz_zSh_$4SvT_c#76MAw{@l9?=OpCC^7B z+sUwaY zv;+k+R(-A!!)2l|%*%J*!S0Ri`JM0yJK$)_h5AiL&VZY z+J9x){({iI+w89_TZ0CO3(7q;mBKP~WY1u*lCj(G!A<|;x}lsEHr)V)%xT4etIhgI z_RTRx?wqe`e{W67+S@2Xo_G0PxU&1@8DUx9!Vksra#qM=3-3W0;sx!%RG%79F0sD` zdsuQAdKSV_`m3AFe`W|?zN^G-sH9gr32jK1o=s!F#7FU@$(AJ64)g$#V|MKV_vvEw zn8&!5vlqMvo#d1Ixvbc(z4!S)C`x)TV}6yyoJlqv2pLf}J$|OL=G9F1f@syYv~M2X zzmw&jTY#ZWr(Tnrk&}9(6ai`??|Np>oicaLFx;eZ9JE6ZM74H`XYfn{ukTU|5|rkN zdUbTXHI6{fXhax&VNGK0a6ONr`(|jQX_-X=I{u&Pu*Molg z=TNcrc&Xo+C3Zb|{Tz-%dgE^X@gPm*+<%nfQBeR3G&fMPwE=jr*QN{1*1PfSA6~l) z>!s7h4RD+;)7O`!c6JEq>H6@$e&T;>GHI?~r`aLT*f*zEd6L|!f)}NIwoTrk^wfiC zFe=oDb!UTW=VR8OgV$~AZ`>7&OJ444p=Ev{MN;JjP*Wz(8}zbzP0tTNCJes0lJ{Ov z#)9!8eOA;ErIrbc8pIzLa}y!ZpU)f>ct1PQtzL+Te_SsU9%hWF#-n1+!6k?-wJkqC zWJ;RZf2Ts1i+%V5LLCA0nXA77l=wlY&I)DilXK3wO$E<9a2VkbQn=Y;od$t;0;L){ z!`3ccho<(p;m=H|AIQvMH`eAAc2Na(3ig$lc8Cu)t$2AIpW<~qdQaK=<=)h^fMjY7 zXYhQ2SxEh2gTvO~an>f*=4k>!9<|F9t;}r@@sJOmE7PX!)9=zXO7Jy0X6?fr&UivE zG(*1QOAbHW9em+_PgXD?*IJ51D;N?tEQ z*_v%O1j(UzJJZbO6`nD_=VRFCN-bbnur+8_MB=>{qEuD$cydaq%0+`KS#%NfMUYKD zfI_jNoxNrnmnG9J8`0BOf(tHi+MTmKmXZH`20rJaBiRRSjqS;`+a{hK13oFGALzOH z?LuB_RWVd-lqh1wE755V?_k}Yl833mie@n!7BUz0LK{6*cZLp1R>zZ>sgAsm1Ueio z4)sbRElOdsVS*Y;C7;kwj2xS}amrrd2t<$nFF5k2l)*0$*@@8Lfhs+Scol~_vVQED zkH3PA^_v}Bw(Zp~XdB8=eM7x^V zfWE-!0B3q_$1rQpyHQ}12sfJ#Sa*4)f+DG$ zmGKJuzWp%AG3GtVsI0cT-%dl^(4wkzY-BR9PmGRtU>T?`OEA2E7M_)?6*c8Tr6ANs ze=<>#R5rRaFtI`yf@?2TSg|&)5i}gxfLA)PTA*Q|+(BI3)zmdt1$r34_wq$nYEQ$^ zp>w8loV6;%F9HL(QL3x_C51u7_@#PT?RDp z;R0C$h?|6sdPNici`4TkcO5bW=z1R1FMcW@sRlU#3N{O5`~Z+F;{u`x2;KGSOhDd5 z;y+M&{;B=}i;Z{n27oGIZf)S;ehuE2$PFm_07~zF3cljr$s~~mfW>=q{+f1<>#7pb4NIArVm7VciFcmL` zsq_#Ud&FX5!e9(-*EOdx!)RY=`$yjPK&x{yWwGE%ogYyaTPHzGL9DjjT0N6Pp*y(e zp9;O3^!5kwlNXsQY2)@LXc>y0TeX7}`e;>J$+Oj`idrb|5=vH?SK(F+pU*IKjL9`U zG$x(yf39BrK)%Zik%Tz;LE8vRRF9Xv195BP<8`*P&S>qJ$$-Y!4NBe&NZ&$}qsZbd z9(B(kab>!Wdp=hX8@XpgXMVyfO-+iF_0;n|)A|ZcKMftwOx|)>2Zwvl1De8{dC{r3$e!8>zco@w_yk2GHuHCR*W4`GxK&ULq@YvJn%@%ZA=iF(h%V)DD-D z_DbSc!z?ItB^qR$E!OgpOWN&IrLO!;qT0`lKr)3?E8l(22Y+uG5AV0 z(}1^fZtHMIX!9~G!0mX3sfLQcO?f)&`ZASMlq%BB1< z>5iKUZ+t&O=Q1Oy($p}9ZW>p0%UqxoJKM{iybmKZA=2nl*K`rmCOq|SHQ_QVFE+!!0xvR&L zA8TDq06oZ-6!V|gwgN;VLBh8g_!{>u}?~&-a$3P6CBtjbA=RjFA(|qybLW=bY7{P0tjToY zAk2tVmn7~pDF@v~Sev_ZPw+7rAVKHlw}Pqjps5OHO?krfwbu)8xL1aqtB(ZUByA5K zP%kVk5_pB!%v$xhX~{d3bZZNR!iRl&7+M(JKIi6RVkM2B!1#u(dF(-(bFhY-v#q3V z(-n9C^%3x&%O`)6Qo%h?x!{g_szIK4nuhxjbU3Ux2}^a_A9?2+Ir6J5zG92*?H~G| z9&(wAlkA(qIKg>FgL7w)T`;y|ZR$F?m+qhyypYoBdB)XzAfc_{r}|;!obtoCGO^g( zmYhYLJ^^6^FVUsm7GIwGm(-bbGmr?j3NTccw%At5HI>BugH}=+Qy-%wnEzH z_sz;KHgX1scnFe)yv=oX+OkNgh%zKk%@NI(7hZkX#7KMo9H#I2pp@KP?M3&lL$sJN z?A^5)Et{0iJ-LGE_KQdW10Y-@z-RCWaKP#(4j}!8n?Rl7r&K!vHjJno>#sR2DmLa< zZD&890vb?NZqk~6n>Ttn8Sv)@{$D%kKdt^!9mK9cYH!Q=6CNb=9=~RbJ5cGkdZVku z&=sn%&>9g3Jmyp`&AJS&hYStxPK3`eG*91-J+qSqCwzKS;!+bmTC;ka)|{40Y-N{m zOx=rW)CY!d$Jf$8U+5eAjP>Fg?IZcqJQ5=>lP zXx$Yd&@aN;lyD|q9M6l>te?>wb$cAA_0m;g&xU9wPVqtZsEnvHxoMc|28_Rpw%F}* z5(BG+43Kw4ST#nJb9>lqEsTCHU2dJA=+)}?O$P)00)GlD{%j0J0O$fT)skoQWB}#6@L1Nt!ej{Tc<0W8;0Ip zjgw7o?-nI&PhR*@MjVbQnX07D+{NOz=fYFLayb$Fp{&JP4TbQ-TV*lF~R;c$BCbQys)4{`!`E6Us3PfL0aY6SHGL5Z}3g~lwt+I?{ZVcMpTnlGLbQH zzoz)10ArMF?c5#AADcOWt~cE4LFg#hg!0l#%Hn{J?hGXPAt`+zNos8C;Amoe-J=GJ zO?LH~pC|sA_q_7bC4s@imu)q`zRL!<>Oi|W$7R}+`{yAqCo3SC_5ae%{u7*Z%a=mE z7UY^f`Xp^(d0U!nW1OL+?FXALooMXCSA>-0xZ*QkJBSrkw2EG?a9=Q3t`4u&(@*Cr zGK`siG|<+E={V?f@Z_)DlQX&XsyEYuunD@xF?;Or<8*IrW=L70K_zs0#<1)#ykJz} zj}N!(jo;br5?ekw{OFoY<>Q=R8@!uF^LgTeQ6(rU^@}{>ds@{{0-|`a@E6lx@NJgqw$5kD5e_rS@qX zNtip4gpXsOh%+c6;(g?J5}F@>SKDFY7U^3#fv>)-DX`fmjpuYhDwF;r3b5t#{u$X^`Ivmr za|AM@VrHd+M@mlqr4msRaZnXc8O!Is-k$%QzDyed9cPGl59%v%7MCwU`ol*qjhGoW zOC;4_HS4*QTJJeW1e(*SE0rbH*rsT=5^PMf%q4W5*3TlN0e-m@z%0Cf)mJ9~6#TMa zZrfEakldc2<0$9p@`UZFZn$asFhC|$?}p|7D|JnvdjJ9nDA>$bx|i(#m%5h_M;g*4 z%EtRg+zs%5Zw&qWx8K0OYJBU|)_Ai=6by~?;r1-t{m)<3-dTv>kMKuD`NTdkf!V(W zqfU1BJAJMgeEtS3nVZj>msPKz@+rMX3j)%O#M>QcdcHkubG9Gk-If>Gah^qvYzqh3 zCSd$1pwzRYQ>4MSQf1JesxYI&OYUWyNQu*Z~V}N+1E_`ilX$}M*`{5 zta*sV(9cK>C69wWoqckOjOib`PfPqbn#HTU^>}t?CAO9%!iq6hvBz;dvr%bBZj`#w z1zOEFT95<|O7iw;23huDMqVM+o zSm{&@T{28rN@?`2a7gOp;0=k zWBd=+5!>~wzJL1-{I6O^5Qhj@N4Fgw<-y|+vfUEiX|+V|d4fSs*t_s}N-vLSscXeC znPNP_#u3&as@3bg_7Bp-7rjnES=mcXsduKJZ|4B$P6jv-C1)z&N$*3yOrybxgSO zM`8ef#OtR&qK*P@r9}0)L_v)}?`Sdm_cRNb<_0JM%?Llo4#Q$&h?oHJytDP6l6pYf zBO4%~3xO9%lnx;^UmyP8pXi_V@s2e6RbmMdcQ@FHXr8YoE!xXbFn+=!$Or4DlUGgDTpT*BvqCTPKT*es!jpA* zkqa$fNMUMsEJG681Xf?GoiG`H^&x0oTH?{{pc1Z2H;xXWbg`|)(9l_JGt-8+5R#C3 z{ps*FRH!efL&JB1wKzj>23j9nE2F`#E^qjP4r@efwtBNl`1?i5399!@cfl*$EpK1y zBF?ZyU^(S$aZoBZu37b+b4BMO;jg7J^;>=QCz*N9%#I@9G*7O;6U(gqWwDL*==1$! zi?qz(m#=fk5uTIK47H?nK74QcGc2e9`&RyiYw(wXga{-!0Koxsj)2L1@cKLuLqM!apzl z9h;L3a#cz=V6i;K`P=vWjmywsO`#ZU@B<^xW&~8?`=f0t0}pDl*J9a{{#ZjQ=b<$B zm}8m+w23ZT-E#cU0JDJOP^jm#?NN~?q1-$j4DM=|!TWVROhQ9q!qQ1+T6EuFC@Hk; zi5k==Xyus1zfCTe8HtNwqS5=X`*2Br=(EX#VJ*@=>v+*1;yJdfzc=>$P>tE+i3Rpk zlBur)Mx=uFti}4nZ*FzH-HBSVsyA{--qu$=c+JT|tWBbrL#Dim6@Rg3^W0ma(`j^jUC?_;!v-M+ zZXsReIS;J`h3jT7=jQyZjIJ z`mQtasCYN^`hLzfGB>b-cm$U;2FSn^E-+-U5yXVq0m;70!~dqM{F6l=63IVCWJtq3 zK%nR*gD&~%D2^Z|%~&IS7iYBZW5ruW`8Hv;7`0=p94++u2r|+@!kqjvrYb$O;O2J$ zobGH)HN=M8d&OE01iO0e^;SjdV^%t5jwqyz+ZNxpF<2ME?;MYy^uJo%QOFG8m&~Hn z^6>byXl82=U2G)nuTKjx%LeDmvle9U2|9Te7i25O7f57mkaK=-P}J>d82UYp|< zdCP%}S~y+!5MesG&)OxoR(4%T9C7#JGs`+W+$Tix8GN+Q`>5qJOno`uiB&6;5`)=H zl9vQt>MF>2eB~Rq>A7=qG{{{d+S#XqcG9^a{Oc6DJL{E2|E5~^vP~&O zx9goy3Ms~7Vr(tdVNAqd>y5wj7H-(pH8DZG;2RuzZzI|T^4V}To*rGDr&*%9^xy{) zZdo51ZwUk)(Y8S5dyXa4-tsT=%3J7Py(N#wDV_-(diw%*+>&Z|7q4hMQ+wD)F?^E% zy7;A0UF{Epr?1`=_lele=XoRC^`=QXx7{curJDRIqjCp|pYsF%#F!5F%oqE`UNZv2 z=Hr&|PSFx=OWYSQwT7p1du8nTCALGz=?Y&D`B#|5nm?QJ2oI! zby+{*c!HMV;1WWV;&AqeQ&=1(j)l17m7_Fyv9zSP>M2sbNye(G7d14-15AKG(8Q115&x(VFmz$=n z&qCYmIiAbmue}S23L{n(E~4Pp<=!Ki_{4<9Vy>7|Z<-yW?h+@A2byZl7aqePrqW{p_t%@hS>Ck%suZMg1x!MUJ*|{{>ygj zI}O?B$l!cOz`lcE-{+~m{;9scfj(Bo26g~N)Y#ks=n#kOsK!iAf6UVrl@t8Aa_+K$ zA!`Ttb{WV4-`OFLg@OOrfG=@X$OB*U0XYHi1Y{91iVBK}3;m*InmCxa*cx4? zd92JGoxl>QVyPm5_iu{A-M9gWDBRB*(sKZ=uXj0eS&v;0P>N&IGjY*_T=Vw<%-3+j zvFWKPkQo!SeFxJSk)`xp;FwgAdj0t!-3%aV-$sSB+SIQ?^Z`84cjp{IF&j6NX}d(G z0YrOO`cpQSE60lQ?4x4Lc1Mq1-Z#yKq4wl^nwIZo1>{uTmH3Rrf041&#>;d zm5O1LuwAwfP0jWv4(hU7FUD>e8S&6Kld`Yb6uezV<+4j1 z0gEd z#d(<%fQ(p%P}hMzV2IoP^N<6g;S2WtfAqfp3F!LreT6bI4BYZrp;Tfq-_T%?5zq3y z_A>)FJ}@BJWkEl#cmJM6xvioY=imGJYn9DC)^TLe<3OY(_Ng$L8Px=#e7s+TA1IFA>WBR{^*cs(R=fR*T4T!Hk(Y>BvXKgKA?!r~mo zrL+DU#lqvNw|8`1n*tE0(X1M_5ZYZWgx};~jGb)7;8&am)MvhJA!eN(EB~~xvptI! zQS#{JSlaN5G(_fxIcO{q(mQkGu^gX`-DxkXnK7FeSG1y~P9#y9ttJcEo(b<~EehM6 znM7J2A1k&T)x|Lo!Z8k6=S=PR*gi9vw|M(J(D`SS@DA)-a5LZcFK4ArZW=q`B;g3W zoleZF)1s9P5$GHTUq%pQR}n-iXDWLj>rYq#V1)T!%}TvmV3#-oVeA4W3JNgjI`Dw~ zRgSoYfc#Tk9vK$yH?z5{^4}tRRLm{r_W7)@YBDx1Az#J#X_@BzY4WVrrhPrehaHld z=4&fEoSfeV?(TPFXFh*WM^x;1t8VyXS2<^mMxZNeZ_ZPkBJAzcVyPp`yLXus%Nec3 zn-V&LRdw!diOSuxqzND3lLxClgfK>S}e%HApxWXM6*p=V@WMIi_Yyk>- zTLNDIJKxcX^_P~>pPs*t=RsElOJEKMP;7_P-XYn4Ahd@Za&WS-@oN6}UFe@|x!{7Q zeAN_2`fK`!xyYmY5$;Fxb?)adbz4-?Bov2}0S@NpV?s#7(@|wGNdsY;b1EMd0;}k# zo4-z^?wZ5Wf}V;~FsbJ7E61u*Xpqs)l7R%R)4A#?Q;TiNifM#+m5|onTC6ygG@EFL zH+X$?^Y49wcY44q52C-7;=12T+Vbj=DXEn1*V_mY6bW-C;Y2!=ru>yzY>FL$`DuA? zd|YChv#lzGcSbr8c$S7y=lA&^S}TOMJfmsC_SX=6Cq^{<*;EPJGI>c zHH%H4rbq48F^cT&+VK5dg-cZyia);2?KRuEx3QRd)&d#Yvd^^kN(qCXhM+vZvSn&8 z6&MR*NSB&&x4;O1rW_13>~Bs<+i%O^(t^+>Mg)rHpHJxehQK5U-wJ(LJNbEwhRAQ( zLVN=+L_Q#Ozr?OiGp@SJ#(GO41gJ1D$CVPYuYX9%E#clu$c-;&E`LljoGpDu{L;kb zjR?yWh1DzhJxyHRV*4=$#T9GfgvJT_Z)tv>Bb~zOl+aE*Dj^tE%#YJSaNLtgC`0(< zUn1h&Ic)uiUZ|(+yf-;Vc-072J+|` zhl?xmv6t+b7Lzd6rov-kY(et3F~RwAUQNX(IiqDXEb(t`zL3m+B4#8Ln?J3ON=rH! zrBiYYOi>yaMb{ZM^0Oy->eO{O4`Vr@39%nY{ww+_z77ZCYnPw#HT^|>O8U;~^WXk# zVA>m2^h<;T&|Cd2?{zhU6yPBPdS91mb%>b&0vmvt@LcA>{u5{VCp&0!6d{eiaK;E} za0<*3+AJYpVv0Y?J4tvzIXe>eCA5u=7>@~2WR$7gh9&3Vv@O6-Cw8Wc0;(rh>3+&P zWX^Pt_PMU_`nMmW=O{ShE5)Wzq@e29mJ8R0u1}Ik)aAr9?BD4gJ_$o7W$%a^+Xz*f zc}dDa8mwSXt^Pr$Iq1ct{@@F8p_wsg0xp|5MmtzIlkEfq1|3qvDHY3eQ)6oeLxQue=1yLFf8ug^`4o?Jl6Q0_=Nk%TM@`=hLK645G>pktimia>Z|CIR( z2wwlzT2qg%0UI+j`V<=X>+K}of69FQ?R#!S=+~8U#qogY8a3OVRI9QKP?8eT{sU-K zrv`@7SFfrG_E3Tfh)dbu^(|sU(?t8Lzq(!Zy$2`S(g`m(Zbfms;rPMboEPOr3_3CD zpZYN!%1Ntuh4EzRYB`lqCTGIYd-Gyl?{>v#u9lb=jW=S~C!EG5`TM9~F9|&VS_{g| z5>*{&a2%FD1PfJyoA;&Vy^U@H~AqM6#6|x zG-oxjT%`|OF2;#dHtT{CHaI%El1gE2vR`Ow!UJ3&)_HL;4)hN6UG)!i0e*GKm3_iN zCB%i^v`t8$ep6^k?%}m+5i%;Sl9Pdf6Uf-a0Z{A%{zsd2CaJ8l;0?;c(L~o< zorp5t+kRv36uk|48ROz$0&35K9oiM0ezQntKJz3$b;RQmSyCV<_VY#$HQ>wPiX zoS84~WYlnr&Yxw_H`-g&t@_$^?4uBPFP(z`70HYilXzjSO8cH4FLp>8{0 z?zyk6DCUdoHuIoQrGaE*qC$0h$K?XWz3g4xNuGI>M7-Hk94?YlpBlOZt}M{8pS~e` z=Ei6>VvbE~KTh`YXf(&T@4+dFPQEtjVTLS!<#*nnK7BmcH|DRYi$@UG00bukmIg~A zzyS}Tz!1LYuSEZ~-|p(_%4}z8ZtG&=UVq7BX=gi7=BML z{z{KTnXx^`C3!Jlwp+kO%Mpg+Wf-*no0(pAG~^0DcuXJd>!)BdH#T0%%fAnUi=?2q z%~VI_85GEW^r1EyDX!|U@hzo3f_o^YoZ_JSQ}&Z&srn6JQD3qrlJ|)hJ#Ka7hd3AF zv^1}n3iu)BEYbLB5iDWYOeow779pT(`=ENNdOH;!zYdks=iAH8q&tfB)8fJnQB)tu zLRa_*$8?qGrAiZoaja5XNs;E8MZ?ee zIcmP1Le#ot?VUUpMm}+h1Ilj}pA}k$Dp6c${sCX*ekYV;|BcoHx0dCDSw^+s`!BExsA9eCnhqThBt0 zNe3Tg_K?`VPq2<*E&E}QJXLk-&8EM!{w^3A=w|>p5ENHD2vQ*FmU)HinED#hU#OXD zRF05cgYAzVj9c9h5`YB~qd#Z*{Y%{j&TEMVV1ULiiH7SZ{~fvw|CuYg092VjbQ|Cq zeBq!dU=5+*B*oF=PP}y*R(U^>|42b8AMqrO=9AJO-Z5llYV@Ezzmua~THX`CEIzD$ z{K?f?G`;b;2?sKn$Mm`Yds=IL9p8C-r&_v5Q>n0riZ{%;2+u6pfpo1*{nq*aU_ZYSA34)8=yOud zvsd%pSe=_*#zWokcSBSsQkQjg=JKH;v@J@&nX?S(CC?^CqQ%d6TSH>jep_ zvv+89#GA73CdynU)(UQT>f$P_qF`YF34uW?e6j|{fbb@W*3rZSWaRAN0CfC<42+E( zOn{bNz)gVQppk*KiG!)RgS7#qbD!nsPwB2@-{G;5gn8JwIoR2FxUYG4$k$@xvFhNQJJeMVbOVSOb%*Fx9x3Tkpxq*t? z)gh3s`Cs+x{FBSlIIB9e!1vlk`~&vqi>7kI5N=_D*hiA<_{nrZ;ha_oY|N5|`_ga? z-eO$E_C0l)NRA^D0b&^b&YN7ZeqiWMSvoA;WcXEAeNQK>;hnmizRNg;VUZIKPBzeeQ7=IeioZ#QU z*qPDrDFG8_)96Q6LXbLs;-)xk{1bsd(xA}#y(s?(6OM7Hhu#&e_?mPc$OKg24DK?I zJZNv~(IfP5jomXM_A)wte173_^6BA5!K{=NGEs%jnp!K5_=K(AP_mOG#i9_qI+_&w zM#}>4NYj-u9X_=8Bh6tW9m&Z})&m0#iVI(VeB|LO8qINDdgm{y^D-LM0&#|)B!ObI zpo#NyM(W)QhcXwE8S7O>Q^rUB1LDzr#EXmUBvXh=${G27{I9rKrlwPkSC^*iicXCK zNCa{^5oY`^ELSY=2(+e`ikyTX-P61EsNJw-7~a02#dzUI+Ow5=Sg&(Qhq+`~><`0e z51-{>4;nN@)krmRLT1Lh4E){XAsFXIZqVysPyRfs^leXYXJF& z39#?zQ=GqhO`2~>rY|JX`M=3>{B9uH?{1dhl`99C6~gw@m4j3rf4OqRKU1(*p4x9H z_8UN6x?xX)eC%eTX(!-gBrYP=@^)Ef@1R*8d!Z9cQ@PWOOXS$D!&;jbJb107 zY&)l)o{Lnqv996O#<@F1u)6zr@m;m}7o?dkF^pz>bk`_x4|YAhI7YLOCdr6|*Mf~3 z-3KFn(f*vD>bZDS9ayy_ney>7jTG0Bp$mOBoZob(k?s0m6;~}7`#c_{r2kgQtCO%o zo-F1 z3DUB_SUWq!B85pAwY5>IMZeVLYzjL<{?3?eNPJl6HJ!~$T3+1#B!K!j)1qwB2>faL zC3lG_i#PoDgq6 z+!FUZ?e7WfCgijdU8G!gP$D@q(12lr#6$>VnV*XBqu{Qy(Cj!Ve6TOWpQ^7-gvx_w)HT{NQH==Agx zibzTmu(j?0vGv!h_<9zIuiLNoRdhmjC}=1c+B>h{YWGyce_K0Xj~gZhl*E6|e?-Q{ zRu%BoN9plfNh2m|GTx= zny;iryc#zw@3gKT#V~v2F*QLzq~l_W(_c8IOW`+kiCwbY7{WUn`?MZ?_sf5UU%z3%7k^ zfh%lM8(Yw15M9U4X{sT@!=i~9W2j9RgF(Zp$H3~m(LiouNnWBvbDj{#&i@ApY7;sq z{>jHWEbVAY{M0NGaeQ3LSJAi1D1ySK7^v326yuu>y)&qr2yiE+CuD zl0>TNxXY?6p@^x1_Ch;sa*%+@aj$ZO=0J*q`;*~!PqYr6khBNyPX~6_D*}y{zo0w% zoH;0#t$NR^z#F?g_PN^jjKBte(hck#i%hf0X!r~son*TkiMqr~`qbpFf&8C$gTNab zSC0*S03uJD>I;vrlH{fj6>hO=Dh`}x>*6@iJmlZl-RyaS ziTJ=^Yppb#FO$7(Gg!n_epkS=GYeigv3P?~YilZQFi1(pjibtDsRpCfBijp|VAdAH z>EWlm-L%zlW#b;*IJb1wJ57!yxNU0ivyAyb&Y(Zt7wom*?*ngJineiEn_ujCmh(#| z80^bAL~(~oN3V8l(5HTvw(&xvYO}Q3<6-HtgJ1NSZDU|~`gCN{w)=j~IMEJO=j{$L zm?z9b3Hj-0y9@)9$Kk{m$}4jZY^HNZ-O9ML3XDf^DBIDq*5{CT#u~l!vvd+7LSaUx zRCD)b)$>q>y^Nip+4g2J9t7vXq^FbkyEgCk#Mf~UI_bo)14X1vG48D8;7(%Y zqja%eCWBDi2;UK%^x;UsP@DS(A2oEwC*}^FBq`jTyeGRdY`Jl{b{Oy23t+m;>fE`f zY~*HX@`UU%kXiw-e)@T0)yvZP8LN`ubVX;@#2m? zmO-|b@9uxUAYvb?V+M%Czel@KI#`gJk;~INb#jNPCKMJsCmJd%yz*Ow~ z+MQ;@ddnEKc~IbhYh`Qz-Hj3y)k#HfLZ?OXoxJavZsz`s%#c}xgtPWDBpW)*7Q4`c zL0CSO{o*zc%q@uh5+2uyUw@V#KYln`zyzwOGb4CU- zf{|~<8LHZFe4c=*0y}?&8(fZPevf${xnRT|#xR7ne!7iPomE7X$?2%=O?EKG>UqPn zB~dl1>TL;*{4p$Op3R^6R>*9Z-%_DJQJEYLsICK14WfR46SNW(^dArYCelIt(^dd` zmu1G*51LP#af%_$yzKFC=+M~>r2pF={|(Y}-tOMWhC@Tc=xzM`Hg_*59(DF5i>%ju zRaTGnObq>AkNx_OG~uxKGN-Y&pO88s2nez65qn0ll7HA4u!_L?@m#wf_=v6WjRNDc8~gxkv1UTBvs|RM1rGg}N0NT}OQe&&#V0r@n!723vDNnm zh(>WqGU@|IK4UaW8`m%^5XuZv{g@_2R2|?+1(d2>LdT{_XHx82D7T+sYiCg5%F^8z zuxQB}ugDh5Li_e5*_HIZ9rfwt1lNN5LYYwQYm@pK%((u~ZM3|6xB4Wtlr&ot&vo*q zw;v9-Wfj6Kg(6~++QNRaP0iS+tHWwnNPq7Wl$YrGs<<(Wms#7(e4g?B8n;E}oaWqt z!s4^-tQz{D<6br&Uy~ zrMP}i>Wg9-){7e_ze4My=$aS!s~XhXTtA%)Wq_{!=%k|aT>mwcu<=el{YJTnXx|G{-;R(J zUS-(3LwKCw{sVf);5!GetiGWu9r0;>A_kCN0l;|iE1VYwaGvf8=V4I))D{G(nknA! z<(1X0Q(VZ{NXo*}YQl0%fN%b@+4ROdiR+2)fXA-}P+NZ{w=NS}SN)-v0L~4dHlTb8 zNoHNq$2qTD^nb%8{|U3-!+-8r4{fmtCf^R1O|nNOdt|q1?UxkaI`&XbT)O+dNEsG~ z6=AbeCaYcmO#Fr@JF?PXQfPQZrTb@w5sSTW)0Qm;XvFB@(gB!Rg+rBhrs&;YB=uPs z*myY~@zFl};fdEqP-!?Sc{i$WhY(A)(CA=D$XSnWCk;$YpPG=3Teo#a$h9*cB^q(u zHF}#y`r-C;({6y>>#nt2P0>^9KwHOEZt=VwuJ)cFXVMxggp1df_wY9i^6kCaNYcMc zui};ojHVeJV19?UB{{>a9{?jZ)4fNMqn`Sjo*QLB)*K}sq`jC>X`h8l*y-hr*<(w&s(1(j&bNvy)z z7>%K*jSRTtG9)U5yi1u1tRvH7)BE}-{gx3q2;){O$@A%+Wb@RA(>)+JbtfzRScdd? zW^@=)VxN9;iGo|d+qWDe6=Ss{)~7)w3f`k%5Vz5G1}O&m*%${=&;6{O%GZxa5~BEX z{M}-yGc|AhU~u{X1t&0Di4(pun-^yFIGUZLv0`u|x}zScfsqd07RK_;c5MTFtyZH# zgs`3c^Agz#xIF(1ws%EamiQqh#phOYk)c7k@lt&qvfcX#{dyM2BE_Vnt}NlHOVQ{E zr|=Ym)N`zg-fUAp6Hb(1^4}2qZ-#f>z|%{1E8scnarnAy$B~RImQBDI`QtSerP?Xx ze19m(*?}@fEBL~GBA;D&4Ts2z9IDYugz!mnF{=;^pg_7rI50crx>{Ydh-y%nzG&gs2K&$6Cj|nOKNXj{u{%m`Zr#&lx z>}@~Ch7j#J>aJR#T&K!+;^FZuZv+q9k=fg`zH;Oy#pQGO?y=$seR@4p5-*I*#KK;F zGqy_=Os0kZ$ZJ<==m|Po_`G^6t@4c^QoH;KDPeN15S4nleCXchuk%zxKjzdeAwuA#;^zHG#93n_s%|-Z__VQ@J3(x_6iyUH zS=r-Q<`4BVV73@GhK-_8bn97MEHlcfYa?LCk@p@NOVsfiF2=2M7-7=(#O@YuZ%;i{ zms*vnTr(+HJ$+hM)**gW(3CP!wPqL;-m)w646AS{#DDZn^ZGM_6pI=nDt&glo{jHp z``Q!k-rH|7&pRnUQf=Wz7YjzoQwP?WI#OY;WfmDV6?*%_3fy)JBy#`SvcCrx3o4@Y zYboV}GHh7lqMB2yZYPa&9?=tuHDGAs?_Df4GZ>Jd&Le+h&a}?lzV6zW%~uA?F7NVb zSz8%er`zpYCu&1KRyaNrrCH4K+w;5<2802)UI0(+0B*106~9*(z*C8ze)AQ-m;3|f z5WN{fUZMH#ezWh(8}R!7C%=~nObDrW0Dd;W?*&x3#DtZFMQt7IKuVILKiR!pY#gjS zoZM`z06+umUdSQvKRe)O|G#p3JNohneBee*qo?};J#tj-lm)(uYz}>A;gd${h0KjK8Da} zFB=niT}djbevghHZ{<$v!|cv)1R7?Ic6&-tjk*ecS*o^NM-RS;1*Xc%jY`@`Kj?lu zmfZqh6;Ar?^rCl}>q`>6RS7!-I($JokBEdFY zXiw|Dx>s9ND;aE2WZy+rOkb%d0*|sG0siEG(zU8;eXu?2R&P*Ul2ruvur{~A95=ph zd;LRb1Lu$7kDqAKwfR!)2-rccE$Q!m`lWBdzPbO`++HQNPo@1n$6t0+bpqs~2j7U3 ze2~ACg96$YE)&hE;8f;7#(&A}ymx{&rkE4QD)5a0qQ(8#|bk?sWe9NW$>_8vU+@xA=@mTs{iN!c#?Ye8`mdUTAb? zAZ`+I7oK|6D@tq5@F6ST!V_;!EPmb_YWBq(cC|$=p@csauM|BMH9_I^%RD=z4#td# zS(t?{_I$e^C>>Jsp=W0k?%^n;vQpR4u4;m*osT^AiNp4L6{xM@XkN{ZpovS;Su!rU zOytpdvrTt$3DgyF?qa?nsfiTAl9US{dxBx;Nb-o9hnPV64D9r(Ws!nqyfJJu%Htta z#Q$OME5NGS*0pH_K~hS(n?-lGv>+%Y9n#$$5|Yv=ozfkmbP7@mNF%9$APAxe{Bx}Z zdt>ag@A;qe-*fJLet8h)nq$s6)?$pWzxQ?Y)0>{V5h-o8K4+O+)UBzAfp(bb8OM8= z9Jn~=V0q>$YM>-E{3Z2kkJjh@+x+g$%pUy(VN9Q|K-~1RJAmz`0=3^10G#_;sJwyw zLBN37hyqeC2^hKC7oIsX&J_t4pxp$Z!@UTtqT-M$n>s7n8C#Ld8Cu(U8af+UdO8E3 z-i81Gmx7ry>ji`LRe-_T(AEX$`g8>V#H}n1P3)||TwqXn!fM(+JFQD z`Og=fiy0s=3oy-tI5?nU2Jq$25C5a*{*QXet3DuXk!MkL#PAsm_sZ0~xp8{jl$wDs zOYHaXW1~!%Cj7bE@wq2Dy3RyxvI7E^u4&Ehr0~Bh=Ds;? zOb)9EgAXUm+d~lPL%zE9wT8{p2p2^LcfjNz(!b8AXv%8B;SozsD~iUQZKTa2uUW~e zY|HcP8C)h%u$ulGpAz9mBM0Cq!un&+0oe5b0|r2?5(sDT=ZokFfpBVgfpAJP^0IfO z6{VFZ$fZ32TzCKr{$d@F8-n?6AquS*_KAY4S*kx&g7=n_YEBlo$Rd0flKV~8`_dvnL2p_+~~k<$So|vqk+{1z|))A zS$i1T05<|s@;^Qfj7D#2Wd@A2wsUeaHD`e=Uf?Q2Cqn=;&cqUYD-&qs31D^ro?{6- z5qPqhow=b2Fv!->iX6BcIyZ7dPvDdtbZ*wBwswx5zziz(n<~H1^|~90OzcMEeQU}W&)4}kQ)P> z)wblWhUOl?hXRydf$s@^=EbbUE?q%x%3@<^X$`%Gm0Vs)Rppk3xUvQXxduQ500iP( zAjtk;%ziKiKhTB&2JCmX06vgQU17jLawiu^pAR|kH1J5}^S`X5syex$EAR*i6#(#8 z01N)VoH_vX36Kn&&j}c8Z0~e=wyc+pAu!z)0C#{eQ~nUY;^@9MbfQC@~`O%wRKvMS3Ye4CkXyb_D(Gp^qp9UWnUNzQr~&%16Uuu&v*U`l) zodC}rX6~%DyzsEG&^1QzOHtPhgYmUE3!aGN=m-Z36y%kS*Vj~zCYTiS@V@Ryro_}_ z+*+`SbvQv29aJ_z zxn?Sh$p+hoC>nEABfg_8;d^&yEE&!8TxP>^0TmCRU$Z;>V4H~y0noA_)-2{M#!&i8 zCKpha$?67Pb!Om22PsK%bFz0d2C9=Bt$&pDusxT;g|vx;m~S_-ljF{23E$Qsh>SU* z-UkI#gC7M{PCNw#01Z&T8u!e1)3PMa!w8SghqSi<3UdPUirQK-|MB%Ic{AIu5UQvDQ!gVY#F2G~N; za(ppam|o*0UPXS&iW@KAz+g9J!|rqNJsT7G!7H}Avm$q9pl0G(BTz$G3az6o0(3gd zxnD|Q%bEXjJS@+S0lAh=sB7wS=^jug{G)6;?*&E0!BzLLF$6RiKwJ;Figu2W*5M1t z{i`^5f1HLS`N3Ml&Cbz^T^b|_wGD;-7yva2*)Ig#1=RDODIqZQ+#ga7@K0sAz@iSQ zt_J~a@sNMe8aSZb{sKSfKXlrEQP4SQR(E5jyvE?8%!e>z7eU4ZoBey(hszil^{BY& za<}?s1!`W(k<(%;e+v(Oy%4v;;6o4lc7{OGGMlV!JQQ!X*Uy}4VS$}J2%g)%N}-_- z|C!p$*#!KV4=94J*z-^8{@H>~)3zv@1GMI3w^-2()Tn$ zY0D0tP7OlL5V+|lvOD7I*0fJhgumFtjv`92Rkj2@ve-kDmgjFxMIau>%mOdnU7+V` z3HSzd@EoviyP@m$8c7bg?qsXMz~4Qp9_goj5AwLQZvRDfCqVlgbnTM-!@3iQ9=<3$ z;o{%}7AN4=0L7UXWhei}sr{Ym&2ytllB$UP%wCB3nfAfseZIFC`t!r$8|-C0&T-U9 z?xZML>1l~KZyp$V!xasb9&01G^3UJ<^tGmSAO6nmv8N5o2$Z8o3DcBUV4}voY4rx( zJl2`r`HN_suI1>_Sca(FzLvJr(hULAh#Y`jj(RVE>ipi`&WNQP>!`obOca zJLMnXw5ZKbreJID2n2D)Be_Jzdt+O8+26;gORsm+k-Ph3WkS;8=4%fBtzw#Xp-$(;#0IX^7<1I9=gZNy2Hu=vxLv$VtuyOk`YKB4N}TaCWqGJ zpbAM+x%uwSt_@L>2?nKe2?TL1Lsjq3RTuGjF3fouF9M`CJ-$bDC+2Trx;Xu+m;buz z;|TfOxWm-McGI`q{4(2D2nvB_XLwE1B1CfWBGdPTOQ(O8lqdmL|c?-#EW@3!n+&%!vSqx+j?Yn z-6K~gQ_l5NAF$V(q5Hia*zXzV`yH_jyx+w~kWiIgxnTah-(CNi{SIy;2O^#T#_3Nx z8LEr8z*S}!yiPd8e>vuIjTumi4FoPA#C<<(_J7yB{%)t&4Jke@D_48wE!U0C5bB9r z_EuFG#gQBxx8Att^iIYih5mjFCE=`c9Qlx47(-4?dnu!1bEHP2*uA}{N0Ol(Al<=2 zJ-?nS@+;T)*`f(1;^wIEJp5;@8hO0T@_}pP z3iRr2DUv=C&-WbXBrFUCN3Iv6qO7sRu_-pFJho{7-h zKzg1(XN2h6qp01wfg$qHZXi>5Hs!A=;w503~@2v4KSBgD?4O(2YzE>|uQ9KE?s|@i|`Lk0v@KF4=Wy?`n%*z$RV6 zLDK?al0b|E=#{WHy+}7BF(^L?gtQTg zX$gR#{$Y~>;Y+aEzhHR#-|;s8QM7YBPt~^XOw(#@Sg-yAnuUvO&eM+RV4CkmpJmmi zL+Z$#6GBNbT>9T%F+4!B0oh(BgnNIh&1gm`HRIiVG%3EJ(-+GoDE8f_RaOl3Z1R1A zujvqIFq7HVV{O{#B~m99CFeU2C~Pz`^*RCOww1R!m5sBtUJE<|9d%}u*b@)Xp_>{9 z1jV0+!W55+O0ss2GBsJ7Fe`(yN-SlDkGXF2bYMN*D2h-{vn(F3tqVrV>;0PqE2p!?-VeFEMf zrkB)-y7V99fH+shO-!KC2yuxE&2be6_m5XKG*thHQ&2!^?SPy(!5^nD;uMz|Er19F zP_G2y1dy-5ZrLtl3gHL8Y8m8$v zY@}wdGS-XtGv1}?S7#+_Rf6gSFu30ErFdszRqbv<{qx@GQ7jaS7wr}DCzxKBGvU7} z_6djqECg^g^Z_U!*dOigo^Y-4|I3Vn)Ub&cI-yYQK!r-{Rn z%MOF2H^`-~w0YKxoph~mFOlF8kF+pFPdK~m$x-${Ua%Z!}8PFpAs@Z1}mX;>Kq_$04ARYY!`wfmApXc zlAi;_1)yAOgZ^74@pm$!h;1X!5(!?m^F3qA8DWlnT90bAZ~lUX(hYBn`eX|qmV(IS z_a>qJxjR{*tp=u#6*R&+)cn1$ghi+|1J@65xe|uWDcjr9pZx5 z*BhoXCubc>eA8Ofqd74sPsmu;k$HBE_`By`Hq+oz&7<`Q3%v@wvSubSttN;kkc;S- zHT&Sr98@nJCvy`X1r@)GIl=ghXY za_X$U?6(*bUbKOh9KulK{#7Ft(+EpHY&ajwPMxP$KBGG62_ zkh<+MDC3m{)UG5z>sMj{z3zT)2P3B6(8`FW;CRQ6{JhZ3Mfb8Dj0UKAqaU~L1=ubQ z8n~$h?C*g$F8jG-cNGT{oKgp8{lShK*kNP;Q^)^t1;jisHG%e-oaY%h!2}oJq88}x z1s?zr9?0Q;%N+i$Ub%HG*2!Z2*^1sxArK|Vl5?x0kcPFNLU=D?>TbspL!t1U64$h$ za<3b~=v^SP{Tq3Fc$=C%$u=Y<)gF5TSYs>qCJ=>gVca6?$+({H`y#Vg3-9i2#|n!_ z_8ryDE~)pOI1)xNr7&3+0{4-F*PI1y9Nw{@-S|lUrk|X|n1SWhmcDY|qazB#bgoUr z9{nvHqL$76;h|D4v3pgXW*^=9(pxU;SJ7YPUT1$f z{YZZ{I>vvxJ}yNp)}zzCx4x>Y?mht@JZ99?Yu-FoM4zyOKoQJ1`;yy%;vADR2u_T) zaj@PLimzMBZ@|0gxtqNeV3$hc6l=XQsV$$^u~wXAK9@(=lC8pDhjj=43$?CHjLDaF z%P`jzSK+&Q60Q%zlPx{vb{BK7ZmzXNF@@v8u=djR~~Pe z6mX7)BQHH~Sd+{nXe@ApUBXB}qadl)V4w-NUcGipP1gAZZE3x@%e-gly(rQCmT_?` zY@Jn1)lK&90Y^Malm%}^7g6IaihEt;YF2htC83cj9TU>`o{)dfChcyE$*J;1rA<9p zv1CgjVL5nPTuriiwKcgMIOd>dqPW0nF1p^FQcjGa^3w)`w0%D_eCtze{Q|!$ z?nY;J4ouXti3Nt{uv@wP*ORoHsZIUvx@c(kR@QJCG_Uf=>q!|emOV})FuOs8F6{B% z#%e<2XiTVGQmmXr_2Aa`Sixs0sg_o~?S(}ad33W+zS5P0LYfZEl>|g$?($QrOKtY) z!4GV!dioeqp!)YYnT=*48r<8+uPv-7`eMWV*jqbdB8M+^-#zlP(ir*Gd4!J-(`5r3 z(c5r2c0hMo%NHH?G*|8?+r_KeBt=1%y0Y2 z)G3PE(rbIrj^z~@C6AH5+rAmua^pnyCi;T8nQyg@_=w=jXTi@1#_xAJG+@-SA{hH$ zxevbi@Bo3J=2eA!SjB#PYJJU`A;wq;%(^Pk%8kS)gxO7xtJ14rNOwjsR3xnXQCmJr zeiLxW?^B}9=ROJ7YY8zT;TX$e(%4SZYM=RrIZW6PdGkgLY&~6~`bK@YjZTZjYpRV% zwH(c_y9NGP6QngQ7#Qj<3{OAcxUI}T44^1O#+1b>dmxNF>e4d2Z{`cOr@;K6$54Cf z3t&$zK;<)nTqexV+4i64yp%6W0a4KyBrPm$4FQRKUh{OG4+dT^vjebGAoOC;PH=Wv zkTfI|hbHo0z6K1J{%3>_C=LS~WsoE>0GI-Rt^pPo2RGRCx_tPbHQB#2(b9dLK0X(8 ze`+ErexSOLu*X^*bu(H3z_f%v;;5=J0|V?GIB^2j910oT0xB#;R@{ zeW^1``qhHnWGVfd^QJ`;dE%EIj40VsZKOHFl6PBEnfNS^2ZXqjZ#xW0hE&Po9Wbl= zyAF@Tm^>Ftog18*>B^kIxhEbJ`4#;^ye5}55$09=H`>I>cY=k2iCA^xxNHgU`Qcl3 zo9BWpE4NQDyNZriuo|=cr ziu_A7{}21yRAw$d-QyJI9-~g(b?^;$O3^gfdNgq`*r$=!O$ABpcxL)YzMl9a4de=& z;T1hm#PexOl&Mo&c}F(+0ZGX?D(T_QI;WO|z~;ktk3J<=pZUY8hJeMaui5T0_(Ym1 zyUM~P#M@i^v&eE^j8BouJMwhz>u`j1_i~1mnn}oZ+@VfgS`}G!VUCuZ&=YbeElLbz zP#qn`Yu;&p;rX_9YLHY>X34FJz2rG#->VqgY&}1C7p|4EaA^(w7v=Q%&qUolHl1ov z(NA9Vf6**GY}jT?r(o#it557g*z06D!DWn1Z9*Q*1dD;QKEOtM2DQ@~06Q%cDhJ>Y ze<28!zGRt6C|#Ifs5qEvE_RxRCO}Q0qNNQ`#A$M=#rKa>=bd2y))5dP1OXt5;MM~U zfan{%e*w=4a>xm^ih=$`kNG?MDve-3ApsqRr2?KIVizNzuUwHZgyc$Q34>I~K3hN; z2WhNKYi=kl5$UNfF@b>YV*`9f0p}o2kdL7T*30dZ#kH{<-vcW(&Zlw0_w$cYgO3o$*~sH>IB_w=o> zO3=QBY)ZX9LU7u9f2y1E@W83Us@8YtwJsc!BL7l#Vj_#ggUL5Fv62neIG^U{4!e%R zMMqr@;ydHsM1+mRZq3@vhj*AdBt@dbpFD2W0f44wKAd`Zmu*&j!FxF~M8mX7cAS>^ zPHj*?9ZhcS+VlQeSEO5OSU4e$#_$M>2s}*Wgm4?qg=F>pnr6E$G_&UI*9;B9YD7kh zzUNMpRE}0rX)H*&+H8wYwO3Qts}nD9lgwtjF|x0)9IUR+^evvP`cGap&N}1F#%N}~ ze*Hso%~(#|i@k?Qq(m_!)_I1!O`%SllgUXLR6c=uiUIGkN1M&>B_ik2VSU8I^lFj5 zsaTCLRisM1U*o3HVoY@5I|U-iMQx+Zg#{)~eRRV5^^XS)XCpb?#-%v8 zQH&7c@i3<{=wy!tDVC2mNp#KwNR^;~vR_5ZB_hPja)l_^s6|eZlLq1S$B{$$E<%~n z1S^m&G=2m`i2QMXHy~R+572%8lD!l7>#l^Db0VmCN|{JHMdc29Y=~^;YdF$DT|9^T zZM10Ub+RUUN41XqGWqZXbU*=*kL!mdE`NOT+4Z2KsPD*))Ay8E&8ve?-b#IUQw>=2 zuI)#^>ZpF?ii|8Sn}l|}7)bl*_QO+3G6PfZd+W3{UpQh@RA2Kt+&+w_aQ~9%@$HC( z_JNru$gP0ao%0svopMpb=)L<@I|RNr?-~z8QU^NRt}+BK1;IrG_p#u>U3;Wg3OZ0Zo&yB4Bvs^hS*ZAttJuqpxvFQ zZC2@+iT960*Q=Np1STjS&IUiDv>Q2E>EVBm5GK^wym{Nx#y^$%z#8`WD7i90XY*vt z?vtAZI=2Z`Y2)o|_)#SZ!r3F2yPCOQi{w3yDy}tQWqCK;-{u;rr#0dudVqGcal$$t z>xUf2NHXE88xoXS$#+Hcz5Z8jsrQAm(gAugaD10NYCei)zYTfe%9w|gYha&J1t??ElfnyH-VTRI@pI;A#(f(u;)HN5(f;AQuhfrMof(70gfX#CR1iceb!Efc_#D3lz z43C3+)5XP+MO^_R;n@KT4QTTKfZ-v{Wjr80067PLav$FqIx27xP}$rYypA=Nt^H8V|U6XoT-|PYIQEWH^%QqY9kz zv(0M*&k2k-{E4HMh@*rT&vfp6Fj-CB5KZ+%Lq*|)AyO}-SmINd2)a>LVbbxH*z=*8 zoRS$C0qQ%EXJp8xk3yP=Dx12F(XkE>CcfV2WoBw1P&-}pIxLc_uohHd+c_GQC8gEc zRU_d{I@`G`Jgqc(ovZhQD4v{G9I?M7hHxXI$Y@RC(9{4%hot#T!=pvYK-L!r7W6?) z?ShtGtz&GM~^VTaeFil**At+$vqOl7O4iwNy8qfx#4r2;@k;6Cv|2x7s z!&t(Y0pC_IhQOCI@VXt0E%3i9%nFP(%zfZBC*W1^85bB6;B|4}dKO^36Yx9uPJiCP z8FEMPE0!=ekP%kEc_-k`E|AfN!2Jw?Gc3S$3c%IBf4(K~6!7eLjd5cK;&7ZS;V14zl^&NYymbfkIp4) z6yd3-Z0<^U1<^37SRsL^-OhWT7e7Q8e>>nu>vrv@Eexqg@oFbXP|rcxKczKKQ(fsq zWMkrXk5lw6!ou=Ul)qcr_a($sSLT@@W)@tShqsrUI~UiXyw#-9;O)%hKe)pHo>^}i3+Q30u7X~Ue{ zxr3H}fWfSUEQ{kZot&I($F950^u&u?aH>h;t$u2rfEp@0q&E4_Ap5h*`RqHKVQG00 zsq-(MZ&pmdq%QeY^8C2ukuLw`F2H7k-nVz*=@aR35xm{r`D}d+Mn<7=p;`v38{=fn z^I>*@)vFHp*N+b#^*A@)UwBG&9S&q;7J)hN8vV7(P?V%dZG>??r|q)MG=75#S)V%X z*Dxbz{;T*pFV%|BHVEL?bE@gjFoBo|5;QIX2gF6J;4ppOo+1wykv3p@m>(C0bN$Su z0SaipWZeNNCw$O#aHsYbkNn5`1H)v1jx0lH>yRf9@P_n%*;;#Cs^Gu41Par4kr@XsSbjc$#0A1l z0rARyq=5e4@E-qB(Z-#A*CFJ=OExt}dE028 z@G%6x7Jj9fY#$Cb-t#sd&XL{g(cz3X5ks(O_ir*GmUio%vOP#-5K`UXnsg^CYPOM# zON^1$()aB?9>_!3{E*D60kV4rE6c$-G^>?vVrh7kPC^{6qH7LO%0CNvpgu!QY3POS z%M`-L*Q;Uq-C30|%BbYRJY=(4}=^IY^S=SH$GOSYz>roT1qb`Vcb4k+jjY2y1}9ONG809 zCc+fyqgAU1^2n!#ifv}4_-AcJ_X^E@5caNLu`i9E@Ie^kJXWl~di9v7zbgv9*jIN? zwFEmqdst32e`lfmtKRsYYS%^>&t5nT=4~7YC?kcabFQM=;D^Pw@)qn z4E0vUO;tEP5g;bqC!Qy>pAqrmfa9t|v(Aq2&i@>9_Ij!e{|yVmsOTO4cL8_9UbHRC zJfc30eNLMLV%bQh)#46!P9iwG{;qrV$9OUE2J}*rj%nt>sPh@5$@H%8ZtrV*s#EiyYAHOHk10yeBd#8GIln$My zkK>3OYsiO#Q!YV6acY^K`iD2O z+*VPTq@`p_8_fM+BM`M8y~u7qJ6gYHo+m5ss^=0*bU+)k3pE?h!~mJb3zch}fLyx) zm1_Y1>;B~r4GfT_bV;)PHUH}cek~g5U-Q2L`Q;zTUpWB;TR>8AoRhyo4*%7U`#X1d zy!z&_r|gbPI@LD;wh2|~aBhJftC`ao7>lAscq|fL)hn4wH!TvlYt%;*j0?#%E9TYQ zw-|-@<>XXFP#0uwN7C7JVk)7>-IAPou&AfZQ%5myk6#Soo{sNeZVywj80lM{;0d|? zcv3DIa_aUxwdk8fJF23VdW3$`oxQLzYW-9jj^(v2nkatQFNv!v7-CWTZx3RO*Ai{Z za%)60$}V*8Rc_^IIi} zWQ#H)Q+b^O+THB_8**ux36`gXb5l;<0Ru_%(c3i~h^E0@YilQ3n05DDTiGfx(Yr6) zVIn~G;QeZp{wX(3rg6J6LGu*PNhSEdml#vYFMbOCMQ#L)Lj_g9OHe=`D8N6g?Iyzq9P!x1S-u9y)@)`=S)qCHR$Zrc!Hz zf#Bo)0g`w67E`%Tl2^qH#&{@BM`|1Kr=4^CUN2Opz?IrrSuxX4J7$}Hq|sho<5=HY zD3SlRA8Sc9gYb4;_s)0I*U2vizq6ta(lBx(92vx2cM%ppqaq{hv)&9;M<`fPq*RJ} z*!)VzY0E@I)n@eZ?PJSMp3a9YLLmiKsI=&dk5UZEeS4^rBMk4wMVrN=Jm49MOlJ`} zRC}%Z`Y!$RpuItQFZEEHDcUgm$q#WuB25Erv9{Vh`p%}4x~IACe&Z)_ghi)~9c<#r z9{F{V^U@q$mLuS>+yAu<&Gk=o(f&{M6aItV<3I8fns--*zjl>}Xfz>feU0h%v%os) z!mpH?T?RS5VKicF92q3urq}U(et)(mj(R}cNa#BpY%4Jydjevzt8Gr%b3=SI<&kC9K5rUA`m(r z%C`^0K=xODLdZkx_QEFB>z*$~N*g63W}nXCHirlJ!U|D2P=v7s&KiG%lP;CMJIQ!Q zN~a++Krr4y_#H3xftPiRD|Zq~(cLFauc%6#CxT8moam-3MI@aM%e%wV*44e=dmSq5 zx0?pdM@2jq3X9^u`~9gXWmI;%nQDNe;x?s;ipqe0Ts;GjM+AK47O3Cc2>8ueP<@Jt zwi~T`1uwr$!f$tzj^OUd&znN-l5)L-vVnsS1=WC7c3*BrKliTTajyL^LLA}&0EtDQ zEPx-#D4y$8pi_sPp9{pztquCuJ?ZaMYDr$eYU0qrA#QYs%E0S)?umCEi!Y(4ic#b9 z$8nmyf3Xx)VWb;A`kh+Gux1epOPrX*cDM1_(R^V*bAen>Cdu;`(Z%8-jS1TfM6aXA z;7Q%5{eDszOZyVs`=n`(0sHW*seZpSWR zeM`jRfW+fc|xw4 z6< z)N)}aQ$G)v7j=!hVj_MX5-n-H$t|9H2Ig-ccOyDqT{ov1yYfBkeR-tc66iCp?@15G zG)smQ2xR>cd47!R``DS-p~7b~86=H@Jq}c3T98%x=xn5H^HS3rqmi7f&*q5k48}xu z2opy=in(c3ytPrQ^a>;y%pHvuE!%J(*}RV+QsaET}=2_{{9aH;Ig;ar67#Z zK-5c64uV}|X-qC|Y-nO?1N;KUBf4ekWNPSWYypJAoSZG4UBJabPLTQ@0AuL_?S@?p zBmx*vK!*nJKXVswbpa5>1v>K}rP<(m0-(l#lZ&4lj5!8~0Pq>;;g7`S|3UNqJE2mn z4ztW!a2Wl~V2UMC zwMn@*7dn^YNB@)%a9a1f|Iiqilrh=9LMiU6#%EFlnLAUvzNBjksv z3kWF?fz{Lm`V;KNBL+av0zbfK1J2I^Kfz}&S;ZH=HQA1b_>z~cX!XNTUWuE^#Jr?Y zX3f+A{VLcP6m9Uyp)@vnmO>cPMAgyn>%g<0ACs6r;Brndq z0`o(EKiIVnD7>WpFM$`L{Rv)pQ2~yIc7ag_fhyz$af1cLRWw!rb+EJ9sk6-4wKE%v zR@hl%1)viCfu;pc-dywsGXVU{oDd0v#(Z%jUT=CIHkRtUGN{;hiOzU^+e9dfo|&Z_PTfiY=!>TVbrIyGLuvCv`O8~(*m+9Cb^NWx64Qc=?z#P&}=-dAnP%a zA#bqv6PlNsNm6g%cUvKP*NYeInykb2jPQEMk!8q1YGLsnS7C8|0sMEnP+<*kSA=w{ zuVQ*IT)nKRE>Bj&;GZfT!H-F}wgHvbFh!BM0Ho1x0+BxfE5cr`4jTMs{%E(paU{Qu zbYK1Cq54A5WYT3Bap5_a_bp^37b%_i`OjmEy3g0|gJjqD+FXK-w% zc1-i|=R(u`&6Lq&#A+Fr>s0scLX1KFyKgec7>GNpD^>66#p(zap@W87ef(a1dJ^=! zU&fZa;H#lpGX5He9CCr58oFKX>6Q%QP;%qb($9uMm_;PSZcjhl6}}E zl4kUCfyqJqVF}`<@caC$JVw)lNcVUm>-E_i8ISc39Tuc$GrHE$<7!!568+WgD}V|r zjj|toN}qbwW$Yq)SGMXr{-z4Z2uY}%5C!ZEx^p|@m*QjJOA;v#{21r1x)(bN#A zJ0@2GAP+4dkOCLAD9C8Y>V^RBqoc_MqA4mGmZY7HorxXL`u|6n;yEuBJlYMYCvmyh z_z!^r+4x-G7G`j7$a!Y$G62B8dwzeno!cBZ10zQ4H=P~?ioGFOdD(wWBKGS%S5tN~ z)@PcK{Xs{YJ+EY|8stxI)N%J{Vh){!SNuDUgwXd}#XfxLyEW=)x6@Z5-e}8;&zNY5 zHZ(?>;KhhtlhpFDq4SeUjV#rZxg`un!p z<|7B?GT3#g=n|HfMW?Xxa=UGFy%tmPr^4rULoXrzpM(A1-_j`{zWehKFN(l!TD`j0RDjn(l0)`p72R|nsx-H>BAW_>>*;jY~w52DLl>nyfz(WN^#umze!6ULUhXia9#%ip;qH-u6c&| zHjVfs0RI+&8sL$#s~-5dTX;Mpf}r-5Wqr=Ltq+)i5=-u(h+cGY8nPe_(dKibD$i zBfHpKk{&-+i(H5qoEzr@FWS*Ax+Nf<3y^>ZYzq*O-{Rxs=LT1daPeF^{7;zT-<4E9 z|LT6U_QoI0EH=04uL{NwdMXV z4i9DJ5@k@l70FoG_AZV-ys1s+E6Lk+y0Wu0xa9U8)%bKc=I6ytTz64hgKwTKoYrJ+ zzRg%nq1r02a>HYs87vbd&U-K`<(hrIeoJ$;X4S=OQalcER?l)d5nZzBdr%U8qL;P5whE48&!i87r&RN; zJjOTTGAQJylv(vUps1E`v^SIXM-OhDOz)Jcu_D(fpN^nR+wY`&(_FKesnb%JU1g@Z z-j~7Zu6#88I3tvKKx?09wJ$!BC@{&hvqcr#a_XA4Or*dj?Ki6a`pSS85-@p36Q>~7 z-Z7cO)o7QKy}_oD2RegDm+xEu7%=ViB2-A(XKV1ob!Lf1N3?uYAyP*}dzS=U6PwIc<&g_zAF& zvgp;N9+cegiccbA%pq=mGDmlOOQ|wOdt*DQ(_%S3ix%xcY$g1M`=<0)x@6oJb(*j3 za?aA#`-TZWkIzf;6)*C?;x)m8-GX^Now}u@%m*u+jeYxQY*;;dvsS%u9btg2fU*l~ zb~B})QcwK;Eb1);ofg(CpWgcTXVh8yyrWE#MT4I#+=+bcjAOkro%^ibUcG(j0WTcX zD=rp)?0S`#24AQ`(AGOekkumaVs@SQ__t(j4R zdzfsG(d}R{j@Gsk)_h`zi56S0qNmNaW7osvq@Uz`4;mS4dbmhyVSm$ofdW6{vms*t z^}b=eX>P;t1j(Y{BK8#b^d@CHW_4`qA(ApC>Syd-OlLt-cJ;#4ZYUpG8H>p7YaWtg zU}+==xD?X7x_dv+bf@9N`nxEXNZY+Rl>&XE$HSPYCL_u=ub2jP4h-_?WTPxU`@Onh zKW~47e8P690Jca7d#qSA%S!)QG;22bN_)PX%AYO>yW<^{8mw~8(RQ}5WV!Hjl>!h}6 za42|XOj+Ru_oltro`U{Mq24D?f`fC#i@n{@8q^1rrBsb}G`z=M@QF7Td*l@APZb3S z12ii&KN2PxJ=M-NX+Kof;Oucb?Ivzs)uS0W*nN~1gvGk{^2k~GbRDs=WPRbK!V+)r zbW>!qJ?ZYd$jQp7Yfq{yCm7?rise;&*P;`rg6M?aSjb;{{p65!v+%_xD6f=E>U&}d zC(^Nx0qQ(ZnOOO_crUL>9rnQp&`0Z6a`ygPzZhSbc`biWu$@-F`b=~5$2Q68Ba|T9 zGqYil9sHU*1T-jI`pYjTaO=1B;_aMQ*a8^e#K$czCJS*`AciQ6e$je&i{ufJMkb zS9CUEWe0-ska!FZ<+(Ej?!Nzp1QMu)1VG%_89;Q97z_^iA2<2aQvShuf@XC<{J)$ZFzq5(j!)8!gtYy62GZVe)IAix5jV9W8$SJAyU%hwRlSIuy zGRYf^<~ib9quRB#sS=uV%nc#V9v80VWEy9yIQ>v5e%HLd3&{sH!#QNaL(!ktbAcc6 z*4;0kZ^%gIjfI4abvo?37;!Z-NBEJ(d<2?VuzHh*ZV5MYPRuFIUlqKmkl8`Y_N@+& z*pb_9KuB+GV2L)8h{shIcE%Z(=5)I*D-2`KeSn1wIT-}Y;^^^BW&($?sHvbNNSTkmd~YF=Yu2~+*#`8hP9Ht4uk3Axu<%A z6|n4EXq#hE8y_Bft=WE|GeaYio3xc!7M-UM@mfN+KQ?|^WKE<|t4rhApVJ?SSMZG4 z7hfMy>5eTn3G7E~O!OWOKZ3LGpT7;+#%=J(zaWycjO<8KBEqh=#BWE9o%rTKDc9QU zWqD-Z`^}SgY6^YKRYmJ8wqZGLY;LE+put>V?)2&7-Pe(Rj+C!@GL!3%Dk8Eli{2g+ z^wihs-VzG0CuDSjMa6)x!8X|QWDA(dwLPN+B_Bl2g=^K93D;CGbvL-e?dDG~rG?@$ zIvy@_KGZ`|z*%_q&>82J0@V8qgu4Z(EM*WH*nPx7I0vu06tphC1fUhJ&&;#j!0C4y$`cT>n#}kZu;RN1_fCmW%$o_h8AgmtvIpE$84WJwbQjT{~l2*qHZvF^_6$G(eDoXn!_x8&) z&N=AqP0WBu?VnX_3>P!`1G_te?XcU;qfoKtw6vN5X7}A)|sAvk1mO!IHkXCgk zMkrYZKvsJp+WtZ+k*nHSTN-=(%9H_cd>H@o#x8vlzoB8_yG+8ugvap5vt=Ajftjc) z{*_~SIkpJNKLANhJnPiYW@uaoBO&@es9V#R%6!E73k5WY3UM6m8-kyN=cG_{kmVy7 zUYfx*RHc2PNkI{czOgjN^MFa=nZ-E2nQ#_u?;d{~iCRgZm+zZb+AHtiwd^gEuYA?N zQ-Heg5GhR>504L3U+d7Q*AotLt%bC1FXMADL(ow*?y@cY1F6nfqItezp;AdD6X{oT z^u@Y+PF@H{_!}iv`>eVqwodE<*o`eUSSvm;0cvT2QQ@DJ9+`Ow!EcYJk)-XLsvcyG zxMZ?b?0yK8OgXZA9PZI2870gTsO*%E3>zG-vu1=21^=|53Fk{n0`35Zl``koekizoTX8gr~8P0GF3w@0NtB|S@d zu4f@Vj9_)<9kMDy#&VE~wb0fY+(_L}5&+3}38I=7pf2+V{?SME2RC5K3i-hCK)UN}`_T zN0ILFH$#rxF@jFn%9sI+@@Fg~>*xZFBCihJ56fk#2XeW2UiJ1oNSWR`eqa5HEPHE^Vffb`)%zMn#`={gXMSIH!Bt`8SkOUVJn(vi zUXnfhU@0F#dP4|1AEmo;v_XB}0Jk~B@;-$(nTsJlIlh;*pg4o>QmOXn(8Kgi0}{fm zFRPW)Up)x&rA6f>wZ`VC-!SK%#6{87t#0BXr73z*JQFAbArZ7qwOcX!-PP5LtFoum z+KjN0yZHu#VXH^1jV(;k0v6xxGc}>g^KVPl ztJfHD**im69;Q@&>5AMU;a zF3N4)o9=GOp+jQm?oMeCq`Mm_=>`D-Q5pmUDM3PzmXZ<>P$}sW6cD79?;T=`Zui;e zeBV9iyZ3H4znL}j#+sS+JnR3||Jfc2yqVs|{yrTu_O?omb@UheJsJ!ad*@EK;SYF2 zF7dS^zA$?Wb)(3Rc3B>w{L2Bf1z+T#TJxbNL?Pjczvy@Ja~|4RN<{pXSOky}c~M`F zgo`NdYUAVNXmVM8iinG%VdmuS?q+UcZ*ke!00oy60w67IEbPsH3R+y0AOb1ffFc3% ztIlxd`C;ddF95dMSOWZ*?iN4NvCaw)&rEQBpm5g%>7<`6H=gM||L8fai8fKYZ0);VVQ$ta$^BfL^bgU*-*7=0)$+GF7`4CEZ^TYh z9l1`?n>_furx&{6c&$E)c`8(Y%>CHTs57bnOFc?PYq!pWbU9#Avt02&%T)*F+5w@< z&2@4HMEA~2xn}$7-TaCjb6)Sn)(siMfH?;ZCDW$^6sTqm0-47r-cS!s+z07`#msh| zx!PVsPwgGW@aX3~j)`i!xosL?RApoVJ}7*y?5RiYX~@+Icz#o(tF{922b!ih*!}Je z&KhAK*cHp)8ct0fezahwkL+2aZ91puPL?uCH;M#zbLb%k#`1@g_6>@J?Q^U2x1RdH z-nsnHI4BCo!2un2tn*BZa$lDq>eK%MD$kNAv2PyH-hg#VP8Cd}2oB>P^@LA0oMT9G zFf~AanNu`c;la1fWt+K}9UV@mw#+=-#o~A$q>u=`Q5S9H%RX<#8ham>j#V;Kfqf67 z2Cd=wJZ}Ki3#dE{U-e_V2EmRIZ#9*Hgk3AdYp;Z4e9)oqbn31+EQf&!(`Y)dX5sc{ zzXXgHqnt{R@qS8PGQWufy3IGjA;K5rk>Yk_9beh^nxb>#D8qlyzj7OqrS_zyH@{`* z0lY%vM0{zbAR<901}>`<8WALd-AJa z+F4z|-769=uE{P3mVwA93Yw@m%X$8@tc4pZ$dVPLVFP4304*YIfZhDeiw*RAbO2gK zTG+X}vVx=l*>&`^aJ93rb_K~gn95ypG@+tlU0jL9QO(1|o(0T#`4;S--#U|bAjyfH z7wFV_p78)la{6Nk4*G94-@lXgGGP-(*qsEyR&mtOz<~{>yiB_W$CnbJ`)YV|IYlgL zd1_xiP;YTbohGmM!&BcEt4H)Ipxr}hk`7-TZ)$~$3zIV03@Ge5YNPEBV>T0oH+GYU zpEdTnkEJ+uh<)?5OMqBJ-HcB8_Z0<`q!k|NU~BXn3WgCD6ocpy3woy{Tf~?`@^ttBv#eAv_qOX|0$sX8-gk^;85U@q-^h7X?bJ+ISJxQEbcPP zQEOCl_@>;gs-&>u7BjZRz}H-PT&5y>?>}2bvcthTp^hRRt9W3Ju#U76c6TvsAfRK@ zU|vnTeT{*RV$ES+FV23gq!Q6r`QgZ|is7w7iJY2_xToK@MRzxE$Uu3n z!yF%Gz7b35jufcN#`fL`v?yw#81V|qQB&frer!PNJZ#xxeaMQ9XT7cY5UG?d5%WV- z*62}{_w_e<-lH2ar4bs|5=v@n?&Ku&tP5W$7~PdWJ>8#6ObuFX7U(8a-Fx13l3o#Q z_cjvtUOd8WfiRfqhhvgnqFrG8(sa8%o##<%F#@YSp=gtpsvs0%g%`HOO&cVyIz!VS z-QZ78!9cD7)p@=FInbXO;atAqpn%Mds{($ur9ZzS;F5ZmmHe=1?DDK<+!GL?1U6rw zV*f83PRt-MKO3YRiycUNKUWSks;-`n?PZsJUF}Rd?m~t@^*^L6eT^K9~ zIUE&@>*7}8W@fH{j}4${1F5zHk_u93K{@I;&VBvf{^6yJsItPI^7p24X|cHTm? z&(#+Y)N#iT^2XhEDHvCGFt@OD|=Eid$ghqp1`+ut+XkX!7ef$qC- zTtl-0rY6&$700hIA!r4nNkDKxGvJ^paL_mc954bBYlgr<16R$(R^p&0O$$dLqXyz9 z1=hSB&^FlC0_5p!4m5?fHL-I7*?FD`gPjwk`8eo&pL6o`zIuYQlR3cM;sYEFu#cLt zf;c#MA<_W`X_&HtJVDO(Chm?F4j>;#3r8C^O-T1+;D47tgzWs9mlr&Pye4L5K)N8L z!4NPtNgp8F2dG|f2dOw+xwxd0y*=v{N4-*TJA|LIba3l$zgdRY9cQb1YtTxVW9g@j44%dfcG&IBPP!TPXhNq~as$ zRY68)7oviLg@|%WT-#k6rkfb-RSX&erfH=}Nq$cvYK`FO2}5{aNUh+|40PBT%ffJBT;#9G)i-r zIM|j~KZT(PiYnyw5L12CT@77Ui(6w~CS###-RvL4oESrIh$XdsQmZTOGks4Bek6Pj zi1+|3bp0F;(F1rW;dk-Iv%XQUuPDp^Pkp0)aEM>@jZ$?5>R5mrFNk71?;phgrn}ld z>YDTU5iD+JNBm12r2e;k;D1y<`G$wbHs;++{j7-~anpFd&+>3uZ-+KXN$wNKZW76H z3#jj2w?&8-Wc#SS@HG5x7U6zYwS@yUtCt81e3|gz}15CMoZ^TEqS4 zdP&jAF%!JhJz6DjM=LHi(iHvjuE)#R(9n_BjOsRz|1-i4uKKS?VJAJ%e5cCIUkD^5 zR~qzWj@!DhDYg|V7-V|dJ0$Kj9+lj59DA-7iM@~?cFitWDIX1|Y%RZBbh};NA}zM_ zl?d(gKxPEa<%S24n+twcEFK)Hl+Fdd z0#NQ7Bc*r9npYLinNjh-ZB_kkXQ}^fANYU17(wg>fWyclp)?XxdwdzpHA>e#q`IB> z!ETg45}B&&u~`W0e(LS_&z6Yl49s?bj3E1rRIhDCuRGUh+ONZe9yC&oM^nAaIdR#z z7XjL?+o)X93M>^?f5ngSa;p{o#@k?z*e0VlQ=Vz?I6Y5Y+ox##^OfTW3uYq%=F;@$ zjHk@0g(O&&&-b5JK!&Q$<>)COM-R^TA1oxnS?vS~naW%b+n$^Ex)pwvBa{5>qJ*M?SoBFj*svxbFQNS@{rR>5;VJ(a z`2MC8@kgi!_Jb<7_OMceTCwD+8GBqjop7VSO zCTVlhlT)*?MMUF~yp~LTM$!g0PQ_Hu*j^cN}u+)6Kt&p9mJAeIV zs~Ghs7KUJH5pT^zx`(rYaz(tGTW`IM2|kprVhlKzN)ht0$xqBli!jymXbcLdBJ8uS zcIe34n@|#s!IgOlF$)CR6|O(U$6I?J)mG1EKY!0Y`qaGsHmwf0m4qg5Zfb2t)~}|T z1_>U#!P11XF3h~)C~0L=~gA%3#ou;%^SC-9HS4td%pEU9uXdsZLn@2)@33J*lN zhjGM5`&1?}c*(6OC!NLsouc2u5v^iKJCrCQ4Iv#X*KMX+m*38@Z4ZB}s7SOJ2jMPz zX+Q z7fVbCx7~c^X=eN4p>WK=j%xbSWg8o zSfV!MK^a?V3OjD6^>U9Er?1W(0;&G(zvf>oCyvYJng8|){Eu2r7wAG4pOIhacHYD- zT3A2hqtD2xLiAY9uh5W}t0D$b=800cP5WEY>AjdI0Nvz!fh+KEQ$p~xVn6ztEuC;h+?M)vF>zgn z@nCULfP6LxODIsA$bJ#+L%~J7c=3t~lUF)}3S3}Lpj!evC&vZH3E<4<2ORW}A^899 zs(-ipZ!K!tTp#IDriQXpR<71;>&p;SuF8qMXR8E|;kY(GFE!6G! z=rG3IUZ5;YOHH$YPphsZ1n!HdInRFUT}eq>%i(=Orm;<)BQTc4JB@+EBThG^s>a|6KlK;>X-20*8ij^;Imf~*MExXw`j~0!B)1FOMB<^jUslWv*u&*A}bAb z3ByIMti|TMjbc-S>2{^Z!QzXYsHHuenC8JcOyAJTc;?W`6+1TtQ^%>R^bM+YHr$=j zm~Nc!{y{llfYRjW6i#7?*NXxU;#&tu33FJ(nJ>~VECC;@E2OB;4ftV!M^+pAGhXP6 zU-g2Nlr-Vzjkgh0;7_G!!P{wu?)+>x+uN!>GIu$~#NGIHJ+j44m(OleLgm%1h zO%L_sQ!z)NXPPUl*+5FIMnNA9b9;p|$Ngy=o}J7s6>UAGcY0(wtavN>*rV+WvXF&^ z`Hs^2vc5>0oyCynXibEADTKZHr)3SKYb>FG?uthbD1Tz$SU)sTSnS{- zzc%F*icN9otob-)|F_{73q8D2`b=ox2>%84_o;O_iiDvxWUAx^_ z_&*vimtjBBj__@_PWyfk>s&Nr!Lge!7MuH03Kk<7$|}bNDp>B+8K^O~KCd%22kHWq zF62|H87)Q?il!QSga@qH%6a=&`3%atB6$Gtzo2(U0_dGJFByIj0S+P)dv}nMiJb*V z638-TCkK;4z&;8tzNWPWNJ~RnT~l34L-Uem_p&)1DlXBL^c;Yt*Yyv^n#)9bSX?SC zO%)c%C1h+|-P~C&s|6vH(~vMdgg)gAfbfF>qEmK0E}(7@$f5)M^JhbDUM_w;@c)cY z@pt;C>iAynB9B&BDFT;%PMYqsgBncu+acu~m7a;#8`KIto}vpGwY=W2^(8iU5ov3$ zSuIwO5V@Hstojd(u$eDB_Cq@&49r89jk=-c!uI(@^stT~Fd{067L+C#Y(wM8aFaWi ztTiA6!JGiZJR+YTR^4h6poVl{jejq&uVC!6pulb@oT2f}!dNcX&vjm%!-6;pPW~43 z_4!(z^-hxcon*|Zt?Kz+O88Y`50UI7yPzw4e81X}Qi=9$o)!%WD0<>&y&3LeU6|A% z;doT%v>N_c)VXBIIk7~FTuk*iBhPfv-ZAIZhxtH>qcyhG*Bo&1es`af=5Y(*PiM84 zKPb4+Kli{vaaSv2y8i5z|6zO_h4)O(zF716s#x?Ee`afB&K6GyeB)eQ0Rd*PRE|WB zSh&b#Ha3tK{?jsK`|aYpy7qo0283+K!2mH}{tj*b@aVk|s-b?4lJpc6u6vpwS}qeK zCK&v=nBvnr=4yi|r;T^sQ`&mLsmKa4?(tU&vH%957 z)E1l&47jn2)>+UGj%pBZl{#kMfJcK3Dhy@p&}%Z+aV--ZAt<5&|dD&<5doAJR+=rw40cB170I$tSL{AQe{gTc%e zBw`8!*7dF%E}k2jaTH-_(6&d9`AR7|LahNTV0exP^Z+~{ajtLR1bchbf7LOTms$lN zjh9knM*|qo&y)wOqOue_CU7()a)*lmj936@a8btwi;I5#!i6*Xj2jsRIgu_Z=?k+t zG%OyL4bXkf%tXx2!JGvsMmM)R(-M3Dg8>f!6!_1$O8{DWz-+k~g8x(V_&YgIM=hw% zA;c4;!Zr?g@LhV#C9@*GJE5V6Zw5Ji?F4s^8Ec=fXqJVP4Vno?!?Kd2 zFJ{H6Kg_|qM4nCPn;awGeTjNp;oih=BqE4DdshOVU5fu1=Aj3=BNhlbnZ{u$Y2-Id9S^fzFX{{={Q3TdQGB4_K>i|YA#eP zLmo$Ae$80f*cPdz26~yUy-Ue;q zbKLs!9+2k_*lw}s_FE(%XXqFEI`;|Pt?|$sJ;HRtI_c%_w6As%06KhMk+`3{dG6LG zx7{r+lH>rE>2uLzgD~v_fkj@>)%X7a&;E~E|ML_6@E}|kmqM8Q&rm$jyb#QN<~2BT z_(A&5@?F|_|4pX(7ri4Mjb#M;-p|}t_lo!)P0#|rJd+1=10AsoO6>(2j5-Tdz65{A z_xO)JZOx;~r`bMP^Ob&SWrg9$ZV|&PX$w9D#g4}>s+?P`A|G*&0wi?b%3f}=9~IT_ z93yqz8$M>df7UzVPnjw|L*=WyJ8AEsz)&l80bxX+V`^VVqa9$+HC+AGVQrwmmN4v4 z(+9IUvigO~DD6#O1EU{sqmx7lX@=is=*`{r{!p{bSFvT`92)?m`LgBoeXhv(AaF{@ z-Q<%gjW<)7UIY~QoYWfX3wrDZnZ4yrxQtTh^!i0B))_eax}vPEFgkhhxp-%dm>_+R zQ_k~35&^vFbG|O2k$zSF0#}xzqzXIs*=7zPM4`(M&`wO0{_2U`|m0mC#seZR7LmP_B%LQWD00aIU_2pzZcF#!kXQIN%^)O(ers8 zsUfqWVNpE38ytn{K+_6mkCz;zoP+Lexw94a^uYYuhx)akq#=f|R9OiHW+6U$h5pk+ z`)luNb~e+?^|=t<#XrJD$cPS=7^})luyzPa_^cedq2#Q>@_~l`^))ETB(FoHa5Bl^ zUDrnVR;!~{wKqLsh&1K=fK3*@`0%@fRIk1qjvU;SvcYQF6)@$ST+2cAs z@@$+#!vyZBOwlS7S}7tMS^bOp;hg={EcaX2;4Rq)MVQpTJ7w?GHyySGedV2CRSKdt z*c(qy8{v)tG4L9xt=}>2ev&kNIKAt6yv%j`KJhNfG|Q@;&?5@*g*%3~_J zs_;_kC+`9r`j9|ho{D`vm6COtrk}=T$o=Tae~6Wnqb!zB|Li9Ib$b??=QL(s`;tUH zn9A4-tECYVcUN>>@=F{awLb7`Sin{6ooui}I<%>Va~*4!slWa4^u_VomH-;}UOZ+w zLMXv>vexKkFa2{^p-xgdrmsRp1^3g#x1*!14!Y4SD?f?11V4td7NFw#OuoM46y<)y zw%E2v$4Y$^WYYFpqwgC{fDzqHE|N`3PS$sM$@!6w6CK-;?39kAa|1gb7$7Nv{yT2& z+|tZ~L8G9JTI5&}xo7ehVDu3fa28#uU_|(3&oYBRO3*UvOZIb-9F9K9CRG3mw{e@!Tc( zmABpFPN`LiM`g4uI&8~t*%^3X^f_LASbhULHm{W7*DaTB@Vol~eXxgBsSx9)=*>L(% z-+IM(1g?qKM^^Ric1tTAnss`wXyID> zYgx8dFB2lYZi|yl8GW58Ka7Ty5G+3}B4oJo;r$pUk(_1Kw_u)kD=~Z;8}d@KgZVSt z8on`lwR_kJif=u3zQgP=KHZ{ry@U7ZiNTCdP*!>()d~3lw6yqxZaZj`W=`ubIToRo zjk8So)*~)JYpM@L8+ckV_3;p$0a8F(=eLlo;>|^!E zeVT~(eTUx7m+!>Qp}szH&oLJD>&YoHMiq;pug5|n&HVD5u81N7tcM*@x-8o1sWIRS zP&@Yr0A)0=+!y-!PrPFeSM{?T`#B~9^fSDPxr2@4rM^bRMY>FuyJQVQ#l7}(Hr-{s z0H6-K^c(=}#p005NQ$#a0__3-MGp9W0q!55p)orrCxFu-mi+mU<7^224^QXsp!ypw zTK3c@%zRo0W@=x-407X!ba2oMScEhZLjl=eU5c3d37E#(Lbfod( z1InD9v=E7Oo5@%+I#IT{$a+7Q^pp0lkiJhZ)Y)tgDjL@d)ClWz^u9F#-D~rtx^486 zJ>EMU#oefR!~m>pLi~>k9VP1$G=$$;I$yK~84Y1(L?k^T-`)?@vZq>7)FUWyoUIGP zAxq$7wijgn%HP-fT9PN^_5O2)(9c5sK}p~B(LY7i^AOHttvz^z=s&`|cE9$3F|Cn# z?jW*MLkBxF1zvAdx&CBKMX<;Ib=LpAyi}k@ak$0%YcVOdU2Txm{Xau#V2J!-J~wF^jKF{sLys4F7C@ zABTq0*f`^4i(yIC;T8v5@ozZu16>q!mY;ev1;j19Uhl$GXdFq#FOD~qYX%b18so?Z zxvvUVO<^FgP@`K5Igsw?C^EDlWD(*?EHN)X3M5cD#mp2UJ-~md?(uN+ zfFNo}d4&O~`#yupa!inX>IA*;+L1SS+`ee0M1TYz=Mub-3?y5m!n; zfPxAF{=mTqcYyj^i*x+~5Sv{6&dw6uo?g)~0Qc#SLLWH~M=K!gc&TF$aeuI({%EUo z$zCdFV(;W*;%;i=;|_QPO{{D{XZ)zdV4`yy1{fem-kNQ3*lD)lT*Mb>nS7X_#nrLnYfvNJb}0l^4AJF>oIn;EuqZEuE}P z%z=X(P3%Cx>F09;nfL&2Ii1hV-onwz)d!ftVfwqRG-j{O% zelnmR>($w^{-RsY_9HnOnf({qPDig8V8v9H*!k_~>@)%gy~xGFuJUKsf*Cu zrlA|UdL4QBwZ^(*wLusRC>U>;@+;)kyZ8{lH=`iO4nG|1oxo$yz43cIo zId}`k6g9A3ucb(f(>D)?#!$&gP&`T{L^!+ZJ{{NNew^L@%m_naG;~6?Fgg(?x|?pf zMU8^%OEPskH+?~shGNhTFRZHU);Bxn54oq&Y!PbH7}A`p#27tWU1YHBB%dy6iytqO z@`ort-+NSP*;9o6Z0mM2PaBAyqrU&0Uhf{EIFIsigI17PMv`HOT|gcFZCAfL%E)#% z?=OD>mq^Ks<3ktdM_JU)GK@1I-SIL3C3sMEeT;g4zzBvG>Sh@tMFklK|vOmGy%OwENSKJiA*+xdYlvUXf}b_UnV$8!;d6@)yO6a!O|thEcd(5AE1q~C%bF(~NTg_sj=9^f+C~=x zS7MvYD$!=X)Qh}CbrG|X$+O?p$3&-;>SnqwOpMx^)7Br^ODbBbUb|;CpybfeO#My# zI-KL}0s^nK^jp+}LBt4@X0}s|YR?1?)AtQ3S-!#%A_Qct@`kZ|W^ZJLKImAti{t9# z=if_y*g%0nj?GpSi-;okDAqPLjO#g*NthQgqYXtSt*RPaFJU`BAEL|3@Wb@6VIusL z#`&EdtLxjy&t7NjO430e>DVPascc^59!;>TBMG};;z+-;^7mA34tPBCbXNB_|6 zfGn{Sb+|41)&0gyoyCQoodq!e*g5VW25^7_Bd1FoM28)FqoYS z2xvf5I0q0`-mabLh>-a5d7! z@8(DhaNh9iy`3%?sGB7pH*m0XiQqYGhS8Xbg=teoYy5g0D#}w+kC2R4uD$%yq&Ct& z0#n+CjTZR2WGXq+E{|VB;B6StHlg!QUNB56U@A2J)-?E4mjuIj{A?Fk0(ODvKW`UY zS;S!IZ*%hoH9dUIPc@^1z z(LykBwfHL&;YwBXKVvNXG5ueSgSi^fPS2%bD{|13E>xHBKfEidf}GrzzF-?`1S(kjl`RhvG<$v@CKnOkPh z3!|hfF8Jj^VwYUez*01Sl*ys`gSDo;!({hW7mUW+;q3_hdVUK2T&iH!;{cAdyTUsl z{R7+H@Evv~=9_^qcfRxWfIUc`Yb`WpzbJADWq|jnia~F^r%Ac;7_~a}tD5-KK%Oks zcsF!V$CT_1x{nl}CI`?T?&f7wyKyL_q<(J%YBnMV1q?1+jC2A>s2& zvI)dqDBo-~H@od{8W1;fef-ds-Z*rBZ>xU@^@WMP znv8!IOZMkDGc>{tMCY%Ap{!yd8LOh=4uWMP`FJ;ZyfR@WKV#wAyM8E-EX=j5k$i16 zMSTiOnl~@<&&0{YudMZ|NxA&P+|KvqJmUS>W;Ujbjf!1Ye=S&RD6j<(^e$`sVlRrL zFwDZ=j)MHaZ8wr9Hj=(!Ir6S*SfSZr7RLw6B+TvpO62%y`;sHOfE*Ywzoq_5^SgCf zs#8T{@{c}sPYufl5JK0z3XfNbjl5oz_9VJ<7^>+&b3ScJ->-_E@C-3U!a_m$0DnLX z#uL~w3@_|b0TO^7^=Fg`R=a|j{ytCYqM8T)}z-#!q*vUm%e>5ig+C!mr!Ekq}7mK`&IfDqW7q&|EVSU z?d3Xwru0GcTSe}TqhxD+sIc?a$g&w~IN!~R_P4lB?|-T%HTq~I7=<5}J$BrVBRq;2 z)EN*-wk2v)5o8|;_l~=4*3{j6ez31F)2@D*5Z%A;6LZQ))ks8mhi_)SW8Y%kh)sKj zh*QRb3Z5brxxYaB;%@n5LqySmz~Q-tsSVcr4S0aMvW~q?Kc?aEz0WY);LFD7Y{t-} zWDx$Ttm?N1{Jf;jl==wj$#))s`8zh!0mENd>S8lSAKL2e7H6lti{CVSC7a`#O+s4v ze!=*w;Kpw9`zM|}nDQgYBM2(ka(2gt?(#!Jqo+G!El_HYIuN8BK0R=|^;LFi8@u@S zH>wx92=e2MTYt@zJ@P|~m%lNQeODtSGh~=u{sqJF$I0rAQrpi=FP_;LdEK)Ta*c;-@#|!nEej?Y zjlweM-o*Os=rGI3s?bCLn)nzS(y4ELom1~*l0_JQ+DAqqX0|GamHa7UVxba>)4J{3 z+Za3g2=sU3TADnGMuAu;C9Mtm z(HRBI!@&jS=K_31fRVw;4h(^(XT$&8ME))_remLsP3NPI{l2q-S%r%_vau8cXP%D= z%F+9e_AzP%#9HN=bRGTDh~hV}yaQa`_^62TsZ>FA-S5>OXk!X_M^C|yK~3no`^}i(YN5K9G)1`GIg~skK01sHg{& zAvUV{i*qEV*OHO*cG?>^cbhgQaWe-q<&f2_T6r0<$&cS)7lskJdoSJy!&_J9ov)OB z-;XXCP>%b??z(8<%lRS)PkqVk=IYEUx^O{?fTb_1mJ9^6Ly8ah3Ks{Fhk4pjn~M5nkLcPk%-D;tDC1=8V2c{B@9TlhJho3(dw@j}j!H}-x(DO$JKCvc z&XDTv*W@g*E38$X)a3B8=f~|%z+0(san?~Cy=)tDL`0*zFHUXo!2~5Q& z>6uIncEl)tLM2qFOSf5E_JX;C$`5>lmOp+k-6c+UzqJ}qvuBVg)4}|P{5qv=2)&h- zLjJ-ljt7%`^i$A!C35SD&LVgaFKwoUblyHF83D9nckXWz= z49p)-exvbVuV_5!@q!>n;Yj7XE^lPo9Hq&3Is!9)(s;i;;EKk(B%(|fa6`yeR|MZ0 z{a$&C_V8Vt)7J>|>`!=cb#QSEit)w1as1Wex_dy~97=9x^uF2BdJ})}=zsYP`z6jRIB2#Jd1Yf~yY-rnn7U98|L6ya-a zE&3(JsqeqAH!bm5PU*sTe=;LxMS0*Ck#zl8^uqQA(UM0kW5mi-46%Rp`<{_#Li;<6 zQq9rDU;PDGt=W_6Z70%ZC)ZdDLI+4u>J*R;Gqz3W9wt5awcNO8IISi+>4sSbr;9ud z2Xh}qWW;mkF&25C@ajOm`7md9V)wj?)BZ=LuZN{JAM)+-e3j2ZX0TVnWR zuj=D#csidRP}TL4?YynMhM8?*Vf)ejm0x`O4Fii{igEO)2@luf&23pL+^Sc@*COfZ z(o($x$QPMKeLru1P>xA?&^{*WM?(E6zlw~&RZy2(a6HeHwKs8d1D&CJfO!sZFR_C;&bwl9 z0?Hpqli}p%2T&V0=)c1x{|?wSc_eL_QaRC-&-!?l-f0@A8LNAKGO#5vyY3aKZJ3^> zNv4bzy*D!GysKXGJ_&9?Cfr3_;rbR6vli@Ix%OFpzE59n35iNICJCFAr~n;ew?Oo| z7*YXn#1RGWQt)^ZhU9&7J&uX(+$s-VKS5^xqA}KvCsh|-uorWke&P=#;Wj7Ka9Md$i8Io#&r`E#F`F{sKYHK%BPl zX7X6mgxfRS=JJHHhx8A=LswR)L)9rSl2E#n__uyGv|*xsdh0FO#2fFPod=Aw;SnF; zZeniV95oM9OnpiVN8TgzP4igpWJ}-+KG4Y}A*MzIT7pYkj95&Uw^mAQuRn*g~z?} zj}40oWA(5beS+7UW7n!mQ)m$%D5NqWvQ?AcZi&XMf$<|rsq3s4U~YViQ@?)m&ioKU zxRIf}Z4JL+B-cix7aG#TQ2U|*#p;|pXx_?Obu4|9y<_(Jcjj^!Lvs&DlI8noOz(jj zr%}ho`wu_Tqg;2p*Of_9`l@erHfNVDAx8PQf`?@9noroQ!xt0W$XnU7NhoR$qV--s zEg9P{MlLpPni@BnaeZQpYX}A1qi`ge{}B1#a>R6GIx7s3nxLKXXGBb58ob{{-0*ITjfdS6JKXnnYvUdV}tY_7&fGd#A6%y2S za4(vV^Vvw;7=XVJWOJ2b2pw->zdewPW8qaz(xa^rP}y@yinqC5k31XHG1lST($H zH*Q^&_#gwtDzm~$d5d)j{GmO$B4>~lg)2Z4d4#7aUtUMuZ7uWrqMWx3iT+)V#R56= z9V+z1OeFjkW1*0JSt?qpGDer@w>JrU9@Qorz5*xYpXlE|knf)?TbzN6w5Rw~ebrX%UZ+-*Smi4Ro$&jF%M@KXBUsl}N zu4`PrBS#?S`WPv)r%{%fM$sVWp4%r2uY@hD1fPNyl(Jf;!&Ix8kj~o_T*!Qf{#oL) za>n21iwz=ruQuJ){wAL{^H@@r9USf{mebc#t)DtxuD|_te zI;=eF4|E0E-+1hKAKD*(_7k$Va~9o~<3)}~l?W=6k*PxsLD(hX%L%wKfVvqH74d*H z8f-Q7O*0qPAG$A0sS=g3y?MiLP81VaU5KqPP3}AI8a9IN9FKT(M{P^o^lOExM&j0i zBjVIIF6l>ujbA!6^CG!D`$?E(oY1O=+f6(Z-LXF^2Hqu&!j9R{KPBvuJ6V}Uz@86< z^jUERd?r@seiJjmZ=!gCqXn;iT@W1oN9j0F4F4eHOX*MFklI z2A}-{9w9yv{!2=BVEFI3>EHQ3YNL4c5uby2nt~hV2tcs+eV$_EY4y;iDs&EMi$^3V zQyS;vMF-;eW$UW;|couPsgUl~l9jbNF-$N7#YVjn(^}weZtC z)K-nB`18Gj%a1n%H|Vgr|LAeL<-I9 zkZX~iktGY(6dMz6Io)>@(rf)gBB&X!kXaA)Q+#AI)_iv0Ro(BqWr2}*9t0aM$MYkR z-(2FxlfXTN%Ghr%RvnyIlY3X^^z=Z*pYvfNo~eL`*`V*yhhV`c4gB*RP0UajuLw(V zHJ5RK2!$TxWt2nIqM7IC?nsNQ|`Z`e#JZ8 z;aAL4`j8l>a#m%vQt<0rr)}`Nb5->(;(W!QsJkZkYWw@HijZ$+bD-`>dA_gL+GWBhCq z*`GGX_l0_5mdI-7?OdT*1vfjB!SE@`(^Jat)CM#PUq>7;P2u2mf+rmFIcdEWSv9Z4 z^fL>C*M<>JS2<*wYdAe`7eO1Ow6%>jm(#ZPkfR`jB6Bf%cAS)hHK9O-Z{ipEH3?bo zlGl+mkTj*K2x4(fWkhOhK4RC`y>ZX<)yuTB0el0#CvTe%aBH%0Y`&USrHKd}2AYwO9+SZ+a$b03L{^ucR=gwJU64UH61Nqg`4q~R$)EtZww)WYUV zu(EU@3&2|0gr?2iOo(O(8#8dP9L50YrsEb=m_7dFEBj4a3!MKsZFG4)V)J1SM=&-c zRU;G%yCDl^YuuXMvv^j7_rv$PyKr`uzJUqb+a~z*7oL1v&VAv%>Gr->Lx*K=Xzrcd zDFa~9ke%1! zXj{12oEbys&I%xN=C+fo-6df+DlR*uAefz>pC5F2PKPU;721}kRcA?8tK<6xD z9H4)WWen1UQkPb}KFjp%5L6w!SZf2_lUFX|XBRC?oP zyPSxOF(`~_ETMKFCa0fc`uR68t!JvF+U5OsZ!33$lndECH?0$+6UdQ*w4asP1=ZS|u=x>q3g#W8ZsowB$KmLzvSthuFqNMsRn&5bx1Sm|%7&)QLo$gSX$9QCxKRLald|CFRMQ z)+iI-S!O){&{;RMXkg??)k=35Dj;weTXVc&yuJDwuHw~nA#6N&=iyBLaz6Xa2q~(} zlq*QI{4=~zKBp)uf2p&Vn_}wq8SqQZiXuU+-0uVo0}@T{j)9Z(QiZRj3`R*39-@;= zBv(Q)!wtFT!N60QnGJ;09Je``+Szz~GjJBK|Jvd=)7-}4MnxH;8{~_B&*#O0xm-oS zF%Rv;{h@6dJi=+BKsy;~e$B6OrpRz)$qA3smucrEq>Jkk%9@elpP)(*B@ept&s9p! zG7LUn(X+?3ldn2mAo7cf;WQ}ad{=llA)wWxi*;DMsaHFws5rv};4&~^L(!buQ6RvM zLb||ZWWQ<${wvBsM*fm+0|ggB!^zRY)#Q%`8Ms*IFPuv)2N07wvys>V$|pboIrzEG zT^?7402|MbM9qKk(to$|69^T!GkdqtQ@W*&2zXEAnwkOvS-1t~oQkZTw7`-o$2xJy zj)`06tekA!Z-!~4^6=z`8t8Dqz;0K-aw zZzzvV)i*=WraYF^kpvZLhC4)N+nR!OnV$L&B%Ym?Z>eld^WRqqK?qop7kkwS{Y+EO zl1%vIa7_p$E2z$S3p!?zTGQ`U`9T6XREq1U=Aa362mCI`Br4)y!L#H(XEm`3hc_5Y(5j`EmD^4q;X+T|Wujw2QrG#N)X?Sw(W~_{#ZnRnlE$#NugSVneCAY|EApvr3V7ydz@-Ykh6qK(1cJLPxE7abX)s0 zihI6?hno^FR8+G1(e5TsjZ0@3Zb+z_mG2sKRN_qa3Kp?u;_1PAJl}X{HvfXV77pp& z>O^M7o@EVDDavC_IxfyPByFPs!~$`s#T<^4CpT!b$2q!F^qfm)lpyf{h~FXqTwZbj zd5OG`7xsT7FAAzxvX7Nyfi!IPAN6KeNP-{%+zY-79w1E=lIwr&A_Pj%AVVPY0^-HL zDlh-yrTbbkH4koQ95j(_`D#*xrrrO2#2DR`VkOFRXS!*q==xnE`Ezc=?VLFQ8 zI}2KT$DUakd8-QuR5r{>vbqdwRhDr&Ojb|uo4ti{L_u&|E_*ANHUH^~+FKZVlM#?cKLo{GA8So8TnIqkg^V~lsW>yjy-U%Ox74cyUmyQeJpwn;B=*3Xeo=SVE_kXzi z3V^8Ac3rx=yGwHDZjg|Y?nXjNy1P52LlF>>kPaz9LJ$x{O1cCo2`Q1g22k1VeSXim z_nx>{Mfhf|HM5xc-hSWb0TH4W=Z-zgqTsjopgc&kdxwUpz&c8-TX~Y^q0bnvYO$># zLHmjqgl5OYoe~W9sX|&1=3X(V`DC6_(9GUf%0R$IZ3h#d=3Ko>*Vb8+vd@+!?TJJ+ zy$LL(ncW7%OJyPliI3@}8lz;y?Mb3p9jk))nu}fOlC;}({SaVz^#FSC?qBucSpt1{ z!`Jc(^SiwMh8hiUOM>0de@F~o!%iV%LrXbG{Q#i?R$!?n0TEp}uh_sb3P}ZVH8l#( ztM-g*I|u@C129sYKo8!f9Rx4Au9v^}-u-9X!oNZ+tp$BIZ`~NM+X`ep@?R%xLbJAE zSSTs!Pt_*>vYKhFHXk9H`1)?6S=!T8${1`z9-*gNr^k-W3O4<1pkf8QWe)vgtjfE` zcv`V+HHxRKPg6cIn!MLSl^L{WX7fw89DqP5t$T>a{VFtZMK2$z=bozRzKLrpe)&sA z&0B@@OlnuM2Tq^=O0?T%7w+oE+lj|^;R_~cy+SW|Yxn&(Q-aK95@&~V8j1Muyt_lKVR`H0QL@Silh!HE zMOV>T($E=_-IPt|F7n@+92bS5uyav-^k;i|#^0K{&8Gup+A(X3t2{rK)4c5IOml8# zo_ZwzG=p5$BDKf6&4Xj@YO>iF$aQI6<+}hfa~Of^eFydXzB9k!{M=Ffk#YYc0f{c5#4M&x8;MkwYYa#qsu zIcdWe*SCCc)KF!tY`TRA-n1;#w4xmhFO6WIR^G+Ld@o-5>3~0Ofh$BAIr*6l-?x=+ z51Dc|{L@DPyl@b>2ePQ)#hAYben0f~$0?+}s0{JifD)E84Q$=rG zgj(+%;NHLer1W3CYPz<2O<6cEx7w!lwjz%eHX2jFq=b5KC20pBfw75Ld)FR!P75WhT& z0yyg)aE1$T2jJIH1^#yg&M^g^=jz(4<9C4bz^`ipaSOx=e!nnbfK2lffW3zO2UZyh z@m6Z~Ms3+&)0MOgpAi~eTpFHv)8fX-g%fWI=H{;2;A zeKN2C&a(w|E zn4cGK^?ZekHfmZl94hS`9NJEz{g}s3h6a5wo1pi|F+;z{S*h=dtDHCOqr9M`SjA0~ z*C-stJ$!rt8Ul>Lq}k@4ji|-k@>Vz;PseQrdfmb&*Ts_p?iE0Y^Bk!`pMumUw$5EBaAq#D zXN2dq?>0WTEh& z0r0`iuKaK#KwxC9^y_sUpHf>5;qgsX1FkImxsK2Iqh$Z@tmE?oSkmBjn=2t4Lf$asp2NCfzAlS!`gR*ivZpF42gZn|pY_gyanS7r z)l!r|8Asb0^LL*QnG4W^gi)Bv)5hy?!Z19W1+fF%V-ObPMr=&k$PG^)TFph$r}E{& zjf?d4)9Ii(&sO%X)1d|9cJJs#kH8oM<$s2+)`DOAdl?c}a-vMMc%QrAd~}%?*mh!L z%|07$ZaWl)Sb*dF6vR}nRwRJu95W-1Mj_B%Q~YSXN;!d*!+2e*zY!+M%4&s=&e*jo z&;241XQ!M(?pv7{uIxJ~b`wIwhP0hB_j>b8uQsC&?42yrGgRAob!)s5=qda4;N%Bx z-PWN&_*cGz1W4>}Zu#G2>z8v8zkA33DXTP1xuVLcS!VR?;tcW2-!{!<_3n*3Gg^W80WwcJ@)t%2HD#xM7H!va`?X`{2|owPynf zQR}+~w_{RgytEmJ*hpvJLhy>mZ%NsWt1+bc?OVc-;f_Z=tQnnEpnsx3?Ck7zfS>V- z+zV}q1)&Uyg!w|KR09n?(U0eIrt-Emsu)4;5&G%fu9@fodc6Gyg<}_wFDrF{vZ2={#1XgfarJRWeU)h z7qIn6@h$KtBLB)g)-v6XD&-_XSCydJWG2XwZAm~|%y>i`hBlRn)QoJR0;l>V*WYckAAOh%btnTQOwuKdq5b^B=%?|Ojn|Oy z?jP>1LiibmqE!GiC4reLp%FUJB zLmm+7_V6jrCS4kgQ)`8tHAcU`LNqP9v_RQ+tK-XO_-s{TNU6I*-n8RgE2`=SwD526 zC>qL^#kai>zGpZD7bQYf+VW`Ftoa^3TzwPxA?-^_@cLHei~CsCWY5nGN?xb0*XU_` zwF*C$5-`(wk4!sDtlY8!nfrF+)>s}sA(BHIO2R0j(d1GT_kgFaA|Y>5eOE_W#epYH zW)&pziwgaR`vDwh`oig7@w3xj`YiYpF-YX_PU#PHJ>hQuSecAp(DJA{7IWxuJ(%UW#$Rs|LJs{;OA z*4g#ibq^oeR#9K+B*XQo7lhyNgz{?i?&aF7bv7DAd_pf9qDG&k6)+r7F6^jfc}_E; z4L|#M$U4NB^AiRtb_w-x=t`V-QLeBPwiD;!Gv97Aa)g8Lkp477Ow8(tvx`i2N!|R) zcpE}~Ubo*%+uVNo*)>SBxHR9#3Y+t54rtebo}Y%AG2uMn7WZEA99LoY(eX|Ux~aTR z`RJkgaco_tW;kAu0B5N#6~a+a(+2CjOlD23bOEg3JHfa>ktjQm?fLPk*>oO+<1NH&>t z^aAMauV0?eaqLb85-n%9d=0?aeaGAwdN@(=qPLK8g#=;Rn%?NL4R#1z z9S2mGYB|-&$0|w*qA9W6TYZ~IDEf=TO#`x{yhsCBNKu}Z!qEQKcMiBHe5<)O;_jFq zikw$dTjHX^H0-i;Al?qn4YD=qld zv*yzgkvClM*>Ln!b59FFDT0Ggz)I>*BFTI&>}}O zwLqT{){JtVD)+N%3MBE9h@s$~lvE5k4VhMD-bbT%N50>N$>!vd$2uXhO2Dhj=yWn= znvj(GhCF+{T8OEC9}>Gwcc`Nl$+%^vHp5)4A^%~u!y=t~V$8fL22>sw`jfFF&bza% zu}vXf#zHpJc}$zLvyh_piYqE%{WTR^Qev;)=*CQqF!?;)ZY^3tdWKdw2di4I(L-gx zVUw0-hCSUk?aAXEDj@$_HS&aJEyuki=t6^}@PRecJ1CmHYP$FLr(iTzI*@woK)eZz z%egq5hIsfIuk~vCxgwLk`Q06w zfbwUWX$~i4zEdWm>Fz>>iFG6~bW;|O5$!q_)t4IIC@2KPyL%gFlFila$&#TpDXH6~ z&o4YCdhD(;)Mb{mDMOg^dG-Ea$93NQIViB?KjOjb(Rx38VsY26fq%c<S&++_e*hcI$-)tgb>QIS$?6Oq)w}HB z1$(8xN#vy}r*B$H@%d8TK8wG)GBI|jUKxDQ{MHcGTRG45UWL#nO}}qW9(>S~Os2#T zjmPW8ZwChNM)jz$+b_ub5wKb7)CrphGA#v%tWt%?`Oa@cWtcRO9W*dSVBv+lVo&CK z$X?Vas3zJ;ldP#{owWJ7qnQt4X%oMs;bV^vWN;pbOp_`V7b%AqqGquVEl-K?ovHR9 z2c%}K-tas0m?vZ`J;|cE(?)dnRVP`azTk9A#p0IKx3$a`5p9>VoXNW5e{bHbAUI^a zyUQPvmTGHH+{x7CV(dv~*)n8x4W{Z0pSUshz4yp}cTg zEG7#_Tvc`=njr^vY8CPr<#_5&7jZKZji)#>BJ+1uhQ1JkG|`eOgF+{Q`>D)dvNX_+ zsXuOj+bBzVLX+PSRx6KfBQwN`teL9bKbSdfQ&UtmEshXI?|x*HFJX(!H#qL9!jbf9 zjtN91J3J=NM{Dq8-5{?!#dTQv9F!&*pHPa_6Xt9zZ_P4W=rImAWs`eH#9e>_n+kHc z%_`T-_&&EHvR%_7;r8Ttf9h(DGACN4+b1J-5h9->n*yI|PB^LO& z@eX?Jm5%~7KQ$G!Qdg9pJ3!Av34+{CiS5LPAYZIE^xZp{rrQ^I;<6`4qt{nCtkrQU z;Tf;CfgLw=`M+ws5dsN- zqZwpu&i{Bz49DNQa`^uJT{(Yh`2j~y{Cq$$<8q4Os%G$C|KgfH3CY3rHaUcta&w;HMT4v;ZpX)-rJS~Cx1ke5|HEcb-j!{+bs zPH#eB{`4vYoB5gbI^sc33DgsbSJcY#6T4`S&)9AIRvj|v;SX026g+b6KHm;IZ4B#E z->d4Xcz>Hjw+|O|foglmf@U}9?|!L3f7eJrEyRiS#Q)uw2WMTmUtb&EjS@?5usY5n z37%NYX}Q>Xw0duY4e{X3_(ma9>Q@@$FhwcW;KDAJ{Lyj`YX_$(+j4|mvn1Zt<}MI^ znfrho_p_mi_;;=K1P^7LZPcl_%vtL2vUK!n?&=6sBjX%k%~|FjlyR6FzPRl~AA{xn zTB@e}q5+VF=U4LZ6p)8&9&<#9?;n>S(fedCe!FLYlI=z_i0Y4s9|;9f%F5c#)4|2s z`N!-uGz!9H%de%q$yFOZFy#y|y8)#&up7g{dt>>(`K*7+y7gLp>HF}Zn#+|gh-|Z_ zbwhuFZVOY!WZ|(7o`)FavT?3%uh~M^i-$=U1a{Wc3rwa*GmAWIiSUiGLui|xbFMqfs70b6UbKrh&h-MUL z$r=@|8s6>z{-&1E`eUSY#MvdIY=@7sOQFcPx-XU8AK+Gh zs~>{vP@&LdNe{kCR4f#j zoCxj8Z0l5OlA4Jc-H5t&IH&%0c6H(dB0`$kN(XCYy%b$LU3-NFC|7WdhmjEGK%eYl zh`Ih^_&i(;a}1NZS+qS~>`$KKEjpp0q z&C8RQyd1`W%xYc9tr{S=g8x?i^3IKqNJ*KU6hsU*QAj8_60V+(;Hgw`H5Pt8PIewn zPGB6>9L&SS_oTyHGD8zZyq%=~YU+Yo~nLzmTzzQZI zU;FW@OOcwIhOC)rlI9GJQrvM9)5ShlR4&6fSKf2B59nW>u(haG$%WeSbMH!ll5f-O z*R83Yy)>yPDZn{dmrY@#9aR7!T*DZL0T5X^wA1qn;GCaY(5e})KA1^WSk73REGW7To_r3 z&B>U{S0Cd5`sOV*Cfc`{Y0kE7TVKCoo9J}qGu zz1NPVqll~yl@!uEjkOc(=;+a_b~@MHeep4Z4ZdA2heOMFbnk1%Eu*z(kOR*-pOPRo zCw4*SJJfNVgpF3asiz;v2Ue@)D2i>axMNFK=shE!U{eV4{?6E?-K_jA_Z-@Sh!L%` zkOD8|zGu;6teR$`C)8d>yX7G?%lk}cQ8Weg=@wHUSGRA3iJzuFXNhvOiKW5QH4W^i zgvxu-Cl4h^yl>FMD_ZLpgP!rcw2Kv2@>L4RSMrs7VM6pU$RJiX*hj>{GlaMg+j5Hl`r9$nD?*|YyiqPlCX zj7U>(JD(tEuq@?kdF`ybFg7>(Xvq;_8Y#L}bqA3`hD}Nsbm?Yz;YaPKjOnCGaLH$f5rU;g{djGw`?>Pr zTZ9|0@+6nP1Qz;ZD2u$4H!V{m?hn3zwU6Y2tNp?0df>uMd22d%+crPR;B@Jc_!tFPjtNZSMg-$_qoW;ZRV*2D3 zFNcxt-e{&D&6(!<6*;D=RBzUWf>v~CAM+&KDvbL%bNaL+VpKj)aME)htbKR1FkNi=}i}=UW(+A z-^*K4ATru83qQ_#zQ#lLg)$-C2t9$qRbJDLRKjss;=L1k*db&xe-0~NmE_+^nm=5w zYHoa=pqnmx;?R7VhsZQ93SH#FPKi)ci6YT9kBd`)OG`z-AL!{rZ zlR%7jji-x*jVfc|a5X(4XK%&|rX#%y@j%yHYJ3!bIpJSSPW+-N_<6-22-$y*N&saq zfRXpIkbPPB;sxN~et|~(&%O0ODV&dshNjx2oLT_o!s+M!@R;KF@-uJ|8|HEB>4kg= zWa&e!W=y-cUrJR)K5Az`k#nR>%`{_UT@#OS zNiw|_Rw#G2DN*aE?J8dblv-PAijs_92;vOkMlahSAKh3U}A|eX%{|h%1 zu$?c<;w-PRhcpAcy*yg-%9%6PcBbZ13=yr1*X*rgTAW&CO3>1<8sxv2kMhsaa=q_( zs}#744%0HNGJ zkLMHd^gFE55FvKeTyN;Cat9*qUQN<{Nx?4fulylfTHdvESE{?v-e^zyq;OHgjHowEp#yTWFPMvJq^P8 zOo+*HnYO=Z2Xgi`S9$wNAa9@kLm%|ESjgyCG^9ZoF2jwy%(chX+{c32UcbZ1s8Kxc5s;qoc=+fv;dk-uiHuiE@bO_*96DE z8Uil^VlJR`4FUmdBOG9~c+Q*4|Mb`YQ^J3N7JWN*I)c;H@@*NpuYi(W&L|tszL`ru zB&7}SMu-ah9XdTkNn6TXo8B?#Lu2dsfnBO)^0gxyD)xG2+`akl5H^w*;TGMsL>bR@ZNCb1r;3QetBwjt!3FMW`xm)=P`_3qg6;C%k?m9;4V+7x&Ji-*_3Nu`heVY~-#H~QM zY4P>`YuHEIGT0xgDd|%%kS1van_8u?Z-YeBgeJzvZMFsZmYCkBp*0e(!OQvcGM>15 z45@GF-OecpKueVD_@HNm)09^fOCuwu)8@oi1&nE5WV|y#(?Ke=K5DOmk@ixDC~sB! zTD!JzEL6ZgQu3Wr)%mkZ3#XM zAzF#}+kPdBH!UkPn?@`qr;-pSbI6Di89xyf^YW}LgiIRA5k|l*#DHX}=5TwOidyZJ zc?OT+f$6Xi-_wLnOXR}1LXs|?F-IBxDHYBJsoF-y&El)TP`oKVp*Ir4TcVL*GRhw2 zw$=+1t9nb~W)H>KLCclpj<|a2dy4=VDpz_54^vcTN@LFEK-7z4+DLufI<^>cJ5QQo zRjbYr?!|ktW@xmEV}wc^35?$a@G@Hu(5tHHK#HWwHGT?hJ;kv7L<0hA$)qe$x_0QBB(hta+kHdy#)a`#$A=`;fJi}qoi>r=-l2} z<^0yjrp96vJn92Lat=JhCoS;`-r1p9mgAi$_YW`DyDtZHUEQFShNJ*{UYWF)fb` z+DOTr(ZT2}n^{y`Vjt_-{Ipm3J&6ntiRjzp{xN-BUn^;it$Bj~!E%@0IB&TG+RPIo z2cHP_*Ld~|URJEf0&S>Igdzn!ij~ZQVJHzSWA}pOhV{;0yhRTVc`rf{dL%E*lzq;K zgs8X?c#N41*5F{id$X%KS)h*)`nr!0s0RJj`2__I-_Y37YU}_h_+_F4TU1V0T1iFv zvfl`Bs3hfXQ;4&G09ra;4jvGTsv^*6#HtCdA6c8Q$e1|0SXg^er~_oS+!VKYI4IQk z*nzG!@H4?<^NYKgn^2fr*itA0v^fCmmy?OTg#(2&aILAeIne#h2|WKLh5^NIPxzy6 z5r7(!1K5EaEx>J4e}ki!1H;i<|2%$aBY@E`PQXN5w=e?f`(MldAAjXPIgGXTQ&0vT z)^k{R=<^TK`racGazsA=;Fsm%UBPmK?0c$db}J1kEW^I;wiTwg}4NEpppN>8{LUDXFnyVp{QB#hegWw~H z)|rg~>N4|EEib)6kUZ}_Ukq;BBqfFv_}kHOx$g(l^O{*`Y8XF^ZBB`Dn7e%e{Pc4}9LY1Epo`k#i+^#G8 zx;7qNwzOQ~YWn8P+N&7fpELpi-c)`U*^{-)QSX2S30~yU7c~BF`Bl6C`V4G9sXxaX z?9SAJiZ_7*c4Mqe>1tVt1kg$ML>U((b)KSZmU|kD#ghzR^nT}q<0hXWVf|iNEy(Eg z@^0DtK@xn2&E5`-Ce7*9hrzjY7>@x9wQ-gASq0+9!E1j}tDn>1l|J68 z3?BYc0=w1xZ|@(-^oI5U!bi%>DmT#dNN_!KPod^u>*@jwg*a0vuqv=hvI1?%tYEbQ zjZOdeQ+`3E01S$*E>?hYa`C*>2LLn~pkXfmfQu+UQBuHjhyNA#@FxLXe(9G4vg@9R zV?us;dvKoq;q2_mDb}bEr*kz7+sg+rD|vNP#v(=rgNPSFD8!j}Rfy;!XU0qn2tQ(> zvmiZ|G{7I`N}||s9^zw$qeJv^IyzP1IDVBpYWQdgz)p}2v4q_nrNAYF{htCf*=zEzm-&$KzHG6VWPo};Y$8$zcI3PRw7 z(>wB&#MxKVyQSZqhh3s9B^nE*61r8JiT66-=|S^-P(0ghsK+l*sOEp9kkUYbDL1k= zl%T#dh;gO#sqklv!^NyG#Mp}!{+5OPn?$Pu`vXWi-2usgWb&o+CBww8lTKz%wqP1G zX9rtnXWPpT-0Lm$bCccJKtK1-C79V?t>&fJH<#a8tJnJM|BR*HStit`W4VxYc}-~j zK*z$p)=N(}mX>GUD~*+}UCTH)9WFSp(ap_4UIFSJGF;K7k3`9Wgzg){bs$mAwhn#wk z%?Wr-!7$v(-{oHKuX0ZTBD?ZB@PA-LgA>3eE}6qZ4?29ox5 zDhZ082u6tOPzPb6+0dt_i4l#Gs?7l}G$NzfPlxN>TE&GynNO%_@tr@BEsj2CY|-PR z9AmsQuHm~RpwTjJcOOdY{;G@*LT^yhY;m~oBfAEW=BsL`KqHpJ#Y_+ZL&Lq%e#nOo z8&T34ALer|ESd13ij;_KFp>T0z1Pw|#JD+h2u`ac`>hPek@GgRGpZ0A=cKc@OdtQzb9#=1VQ=MZS?Nt9?zZ z2xSSM2KKJn>E&KZu60>V?(Nf_B(2wZT+2OQkI;}6vaLM4AF%g)CY!eu->=Uve!Jqu z$zyYx$pokdD_}O+@M=C;7ih%pgo1)By!lpvsc&8Xssw%w2Fs{R1Nk8*M+YZ>=*_{N z{hIC;8Jq0#h$k@caFtvBskpE3cYfrX0MduwPP{@Yz056v)dSGe!v{nJ0GjY+PY)0u z084OB53v02x~+fJhLeh(U$?80{mH8*;_VDR8f#_BFtIS&*Od0ClpeU=gtXoUb0RN4 zTOqXtUIu4l|Ee@K_&l`}JMEN_idee{%YfCbs?;GT_BVwjPEGnyYvvMbCnd}u1W=#H zN<5>1tP(h1=sBkw&-(cWzrV637cl5S2>#WE; zxO4N~!F3CZzivHT5cZY*K>^zzuopl9lr4UMzaV2{fTwrBWUpX-aT$dE7@Nc<{&|Hs zK!*x0SIS9U(7Kwg=;c&*Ib z!>8{n0$3W6hFs4h3w>!$m#9#fUZ&zBbG8vGio+#9w4f+re21@HBeAE_V7EwX8O0wV zGu@xwuvLi>4MBN0RNoIh|HkeSjskJy%oaqYs!v6t?F&Back5UP?GTkDOqf&djyzfA zgP!3ZgB({8T^u#6D+;Xg+GgrJtM_soZ)qHqUZk4r_lY@>zH3cx9*tmZ&S`Vf)qEf* z`hNc%(szcPg6+wS3h2>z1L}6a) z=Z7y4SKN(zyUBcd{M~L>z~@=?vSliJ?7zF7aFa-9uv5Mm- zZ`y_vM78g;3GB2ly-y5#r?Lb+?d(4q$4!%vPWt+e1HlixL-^kzu?NBzE>3VS4v;GXiU|PF?IjA$fBFsl zNf;~roEn}$r>qvwBJw55V~T|r`{1`*;uO_*pl)vU4-&Gn9pvJ&lZP+j0rn)Ek9EkP!SWtoEv z>F=apj?)SvNO?*0#LKEL0;f*#F>x{dVhJ9>H^h<(OZ)#4;Nu$5|oL>sy(kvJ0m zmoWa-8~m5Z)i!*3bg{G1x_ioA>cNBrO9;U8mtcQjN07G#bpTf`V<85oU9npT2o@w>MlX6dS;uHc#~W!MU%Du zc7yxdL0j^&;D-dhXtg-}Azv8QSqgH!$-JC&gR4Cqc51#2BNb{Z-<~_O^VHc3p;9eJ zA2{<7T(fy2W76q$JemYU-arwuz@v`WBQ`4-<@|B38&P3ybL!%~n#7~NJyTMuV4<|v zCxoW-&n>9NM}@jq;;PgJmf1(M(tQMM)G~GV#l%D#ukZ<&kv1%jPYObdDgXDUbtB(J-1=3@7M{44TT>3`u zbAge*l64%mgjQ(P4!O5q&zBMIA!|iFmdI}y^S9Pd;HXMNeIx(zwg{9)q}mdZZa+^q zyyj8N5axkGGsqDpweTx{%(-(Qf^VcD2N_ifmGqs;d#s>=Jd5*h{edN4<^?MX!rn!0 zbV+-v7?iJ5x+Ez^>jcH8EUn9bS(B^8SvoZBA9HFUZyd?XfBW|mfq^Fxdg#B1<>;KFI(qUh(99=IlL0#AV@C2 z^9TJY%7eR+@L4KVR|t4CttnZbDBr&yCAwMYYQhg(ZlA(!RBISWCmssG2$>XGcl5r17~u=0`qLmO&oy% zn18rVQb|}{l9mH>8C+cLX<&7^Z-MU|;Ge~T|K#MDmH+8P89P&1W@QcGOK=gu{5Ug9 zNebV%HSp5hLi9$=scPZoV0IbfC|EnYh?<%>TZsOX+KL&U^V=p4z^D#BoW|U^f9Giu z!Q>G<{~>cLoU50W8ZOC({FdQ2>MHE~QN)X{Us>;qKk$6JXm?(&b3c@{L5V7J>mI-T zos?CLZ^*>a?j35__aY}5K1AJVO!Z>NUAW|t7Audq9z zKrC8Lip|q-dOI*T>X%yNFh6(O;LbQqYec8n>~W)HuqfC11RvolubDprEAV7BHYtL6 ze{Z3q+hkh&bx+n28qr%s8^4_M4!Kg zM8JW;udak2TsJ>J@1U_Ue_ns>nQ&aHFo4J&1Pmi`0RUN7?gl_^f4%%4cfWtaGHMzV zT_(gGPlfdVEJBO4eGBFOPBU-0fdB2}vP{fg=7_jeWEkxW6ps4O>avgBI0PifGIQS| zL0a;lql(5yMM0tr-k~52;w62PtOlFA+H_t!0pbza<}UN9r=k0*U#~QXPEA~uDJCrAsTu1>9jH3Ztqer}xLCUN} zCNvPEooq%g`|EEDkKOu*5h03W$_~k|$pT^1CR8mbKCIAD9Z&=dBJ5nODl8+ISPZ40(U@L@e%M^d*)N zqza(e6#lN*kim)y9R>zSLEY49f(wDf`K6+QltE*QSmos^r8tGypui^Z$-tC37?dvn z=bz4b6qx)ZFyVjN76}5{6I8(WP5}cX*+9~8$d`NqCzwc((2xKaD%Xv?8^aA9ZE-DI zmx*@(aS5y?IWBRR9L?|jCdQY6lSA?IFqfvAH>COa>sh* zTdA&#%LZNu2gZ`dcz@UF^E`gs^(ADBi@)m_CJpc0wt_Ps;+9}7@5j$sCAkBe{4&{E zLHQd9kQv<{?o={CoFF;{PL>~&^D^>0&>W72#Gzv>)AlbzKokVE@9u}$`a*jMv&Tb- zKMr7cD3N?tCtH)~D%|QNku3mc9bQaT?S5KfX?H((t994?-5+*H&jw=HwiYzvK7bDc3k80 z%YJ+R{>q326xPTiMs=zUT$Ls3gFG4SH zJ_KNZ0Y3{gHqF&p*IBi{s>Pp$lS|zPz_9@i94|W;hzqRy08V(|FE=MI`|q?}|6Mov zCtog|hO7m*rfIGxrjWjl57~OZPU$H#D?R%JK6mLm}+C%#RM_KhWj6f@fbfD0|nVl z+7F{+!EmM-DVyl-E}tZpu8|79{4{iMpM}e3QPzYcZr?;|z#(70B&AYuYORFJ%Zcx) z_<&Ffrtjz8qL})y{x_V0lft~wXI>&<%xli$NLtU$vj{&Qpu-?UJ%`38G(XU#rHbWZ zuKH?4ie)z%MTRrg6<@SS9XjTP+F~=mzPX9tEJ1AfjCM;pnDSdkpU;@7$m!l|meKR~ z7FWI;kem$629jhyxI=KDVBpALAS5BgZ=&ml{aq#gN}hKsKNf~F3qi~tG+l;y9;;uw zUPt_|$%X#5P1&?%u3N$}e%=YdVgk8pFD@kF)>YI;_O6<1F%2hUe# zoOi=W(G82InSA_FAk1xw0%p6CTu49BTZ0hEbLV|Y&XJMkxob?zB#F!;jf1{}4(u7D ztF0qs3A>0mp8C|KiX&5$=Hl!PXtoJ7PqOqM#5Xnjkq}SY z1fWyCT%Rtg7dxnmE_t!M1JHj7TW4%PWhht>s@|=_%pUR)Tb)^x^nE-bP+Jna$Cc6b z9%BLS95Dn#aJx(4V3XcQ;+2a}P!wWc4K(dbumX_AufTR49!!d<&P6xv*u!Vdx_o;ZPdMF55Y9J}3I zg8q+R;7@{E7V0~QbDLlfCYLh0baJGtREQENv^m5l&)>_xj41V!~Pk9E0pek>UrtFZ1heBRHvW`9v6Lua%V#49L zQ|OISp!u~ErIur!!O%>}w`HGN2!0C@cd3L<_OUwgftIo(648-dXgk?wMvoBs=Jmp< z_i|lHqiccBT~dVV9Xf9vOWF9PG85~B69*^Wl27C!#4>Oq$bJ{F^fC&{*voK>kow4Z zLYj+1Eo=dKh$OjRp``hpX#r*ldBvl;<#Lfb%+v`8uAbWR?7HMN*ybe^TFtkm{f_%e zDB!um^>nTT7u@~+w+i_$q1+ALaPAe=%hKaDI#h_)Jvs=JZTTlr3LzeJOiK&VnVoX+ zOVc}kLNIGvv?B3z-Ab+s@?lkZjn?0iUPg++F z#8wz0U@HF-LUfPr-FDyVN00EkMT#8T`n$sH@9I&y_$DAV^hp>|BU;@hgZuUD*X-gd z+wI7GREq))rqhTfbk0)HAWM3`!M~Cj!~1srj3+hY+)X`gj;-+JV`JqyWJ8BSBIOhA z{M-p@IRnCr;-FN$+Zf-OSw5=1KPA}d!1!waC1mV7-Xe;h!>p{v(^q7-M4s+OrxDn{ zUN5g;f!|2{tira~N|?KSq)uMxulXGUv*w%2c$bI%{REzc3l+cy%Us!ENx%*> zUB@54>m88)jqpQ8;>S=E0t%K4fO86jrxc1N_GVTVK);;R&qxFXUd_bzo`aM5k4ORu z1rwNoaxixQ7qk_u?SQ5^^Pf2rfGZPR0R_)R{R~Hb5pP}@-AgMAeDc>5>z6r`Yp%@y z_8a_@+|E64;L%po-Q!W$3g~h{px7etXCz(a&LpFKp1tzW&q*~OS7KUc#@vf&xWRjd zANQq(Y}b|m#0EQN)7}FYBFly$&Vi@w6$MM<{%xEr3N}KU(Va;nYVI^H+3@y`-&&CM z+?tH`F2;H9$Qyec?Vi4Itl7|cRxl{bR?=C8?1%4!hf)NOLd-YRXId|spIjI&zE|%k z=04GiX7|WJv;Yo_=KHON0sF(VMP}_5f93m3N5(YTG=p?IT!{i> zOM$~xyD(7Wdi5en&+lVJod9D)f{AkaRiD*1j`L)~w%bzM+u`y?^b9eH4|-s@Z;fc^ zFK=B_eFgS`0=sWyMqYbsw`@((T8|v*;61J8X!oYqJNR=eOkgnBQ74D-0eOLh@&)qw z!gy}o ziq*2v*5&iHtu4{YbG{Zbi?<2E-Cx!ju*3NB(1CpJ00!zwp0r5s#3|2hDHYM6v_x`- zX#&g`#$}6OEi9}Ue9;u1?*^6aFz(n52e@ORd;=*08pF@i51Sy2=EDdBJ=hr9{YD2Q zkPgdL^52PcKYFk!nokjPPav`;?)}6IMOv9{wus)^1z73!R-6a3UgvS%zKRGB3$dJc zS>Eu{yI|2P^w*`WPnILt>GF%sz{KJtxJ<@gVi8;||2uE(Pb#Gk6JmjUI7w!mjg-WckLa7MtZ=4&h%d^$ zE*;$cQ)E-@+KUg)ODq8*913L|k7;*uS!Pc1%dnv82?Uqj;FtmoPo);6EnzWY(Jgvn z^QDFPQEPX!bvd@)&!^D&4jpVw+*+=?ujOP26$8 z+mf!KLUwzJhG@+YTbmDe9)I#h;{%BmacNU$%}A|`FaC&x#>k6+$d-3^Alz9Kn{7W$ zQ?22ynp4n)n&qP!j%Eu4>-#gBsiiL@YF)Vkz98?vy8`@R1wjD=b`w~EL4!cRmj=;- zaBsx$i0rH!temV|tlYrR!VerFC=kTow9hZELOE*6?ZVQXIGP8XRhn-kBd#3h=tS?riO0Ps)KjT+52ydVm-Yx5=4buORGwzz!TeRn>Xq z3rVEGkmRkfsN!N8SZR>lA3lQ6l)(!B#r`?Ui#gjjuX|@J$73Q4lS-!p7xzVq?w_X3 zoi)WnEed$JmAZy^eIkP6T9c*Tjd($GpsOVyLpWswILa!Tt@R1{E5!(No5RlJC; z#XlzvL~O18LK6HS%}L`G9`!s-uGKcuD_p%-AB7iqMGaqMdt-cZ&XAa`q*^*8EQL=; z2K;jfKo9I+>46?6@STV{?nl4brBTEYl=HrdjSIeqgNgt8%fQ~!NtYd+{D)6 zhtq(BO#lh5A6Oboth$9@c2-r*?F(254W$yOH5ts?A_wO!-nZzQ zOH5388R}RVzhZ=$_c<1il-1vI^xP1dGNa8qx2gwiI-a>k)!P|cR+05Ku1`F5fQq(6 zRix8;Fh%jLLtZ8J1w+$ievbl>f9$Kc0t}FU^iT2+F2P#;)$m^zQ2!*?fLgzD2yXq7 z>z`%VpV7nL8zcZyE1*Z77hn_R0gLm^<$vLw{HYdE&(ZsR{Xr2-Xc-Eo`P`u5PA@b; zxagzOGohlq-Ofi-?-iFWm_NXPTlvlaDwxhUin!JTmbd+o&P#Kro~M>cHI{d0I)W_4ZHlQRb_g(f&9oIGQi z@$Odqgs}LtGQQCfp0D{B{ZoGF*mOqR(ARskA>*Zzb!q1{7pc@w($m#sHFDRy*c&OU zt@7T8Jt@PXUnb^g(-}Ho@{4&jYD!DWEwzZtp@5}#1ML2G7 zX6_5GJoZz!$}FuA9q`NP4cqk+Bx^=f`8_aYMzYs8dnzmnZNn)4d%)@aI+2XGx?Ns8Ecv@U<8H{VX16yd+_wH$KmC9;r%eC3 zqG`6qVFi1poxX9kR$*52e5pH@ACDF-7G(Zw?G&VW`vv3o*>OGBdfWUYf9;XkcT{m{ z`@9N0v)i17i;GNtyz}J$e*o5Ah@1cb literal 0 HcmV?d00001 diff --git a/certificates/CertificateTool/Asset/SecurityCertificatesAssets/AssetData/PKITrustData/manifest.data b/certificates/CertificateTool/Asset/SecurityCertificatesAssets/AssetData/PKITrustData/manifest.data new file mode 100644 index 0000000000000000000000000000000000000000..75e08df6e660a74e4a575b965af090d8c30ea9fb GIT binary patch literal 495 zcmYc)$jK}&F)+Bn$i&RT%Er#Y$;HjX%f~Me8;9Fmxnld6}JSdtj)8WxnFUs4Q{7jZ92tn>kzoSNdDS_u~xax5-RErFU0 zQwuT6GcP5z0&G^ifTUwVK~Ab`urtt-%(Tqp#FA8~5z3DDm}PD=FfjNFDBRs^=JAHR z{!zts&!FNdcIOuFyO-x3vHnu*w>Qb>S<|iql^ow|E9CdsK=;_oy(tCEUrS!x+T8Qi z)f=uA6P5HzH2vv0r<$N5}@Kgrn2` zdGmet#Pz8WY3E9|x`iELHubvFvD_%{?&+Od6?1?}ZcbUd&M~b}ymnv3x_8U-)LfSf z&FrccO#ksZ{zmhJyd6L#v2ViqO?OPWR2GrsdrfI!Lw_4+M}_j+48}2w)KWv_FQ~&{dn$zsZvkETvp9|6UV^8AjzQ4V9Mam5Xz9l(8w^E jVLihRhT9DP7!?^^7}FWMfFT0}OpFkkK@dtqDaN$`0gAdK literal 0 HcmV?d00001 diff --git a/certificates/CertificateTool/Asset/SecurityCertificatesAssets/Info.plist b/certificates/CertificateTool/Asset/SecurityCertificatesAssets/Info.plist new file mode 100644 index 00000000..23d794fb --- /dev/null +++ b/certificates/CertificateTool/Asset/SecurityCertificatesAssets/Info.plist @@ -0,0 +1,25 @@ + + + + + CFBundleShortVersionString + 1.0.0 + CFBundleIdentifier + com.apple.MobileAsset.PKITrustServices.PKITrustData + CFBundleName + PKI Trust Data + CFBundleInfoDictionaryVersion + 1.0 + CFBundleVersion + 1.0 + MobileAssetProperties + + FormatVersion + 1 + ContentVersion + 2014081900 + __AssetDefaultGarbageCollectionBehavior + NeverCollected + + + diff --git a/certificates/CertificateTool/BuildOSXRootKeychain/X509Anchors b/certificates/CertificateTool/BuildOSXRootKeychain/X509Anchors new file mode 100644 index 0000000000000000000000000000000000000000..5356c9b19c78bca09d127e6fb7916a8a7102b76a GIT binary patch literal 282984 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ⅇafA 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 literal 0 HcmV?d00001 diff --git a/certificates/CertificateTool/BuildOSXRootKeychain/buildRootKeychain.rb b/certificates/CertificateTool/BuildOSXRootKeychain/buildRootKeychain.rb new file mode 100644 index 00000000..1797ac24 --- /dev/null +++ b/certificates/CertificateTool/BuildOSXRootKeychain/buildRootKeychain.rb @@ -0,0 +1,628 @@ +#!/usr/bin/env ruby -wKU +require 'FileUtils' +require 'singleton' + +# ============================================================================= +# Class: Utilities +# +# Description: This class provides utility functions for the rest of the +# script. +# +# This is a singleton class meaning only one instance. +# All of the methods are Class methods and are called by +# Utilities.method_name +# ============================================================================= +class Utilities + include Singleton + + # Provide a way to fail and die upon an error + def self.bail(reason = nil) + puts "reason" if !reason.nil? + exit(-1) + end + + # Check to see if a path is valid and possibly a directory + def self.check_path(path, is_dir = true) + Utilities.bail(path + " does not exist") if !FileTest.exists? path + if is_dir + Utilities.bail(path + " is not a directory") if !FileTest.directory? path + end + true + end + + # Add quotes to a string. This is useful for outputing file paths + def self.quote_str(str) + result = "'" + str + "'" + result + end + + # convert a hex string to binary + def self.hex_to_bin(s) + s.scan(/../).map { |x| x.hex.chr }.join + end + + # convert a binary string to hex + def self.bin_to_hex(s) + s.each_byte.map { |b| b.to_s(16) }.join + end + +end + +# ============================================================================= +# Class: CertTools +# +# Description: This class provides functions for getting required file paths +# needed for this script. It also provides support for saving +# and restoring the keychain list and creating keychains. +# +# This is a singleton class meaning only one instance. +# All of the methods are Class methods and are called by +# Utilities.method_name +# ============================================================================== +class CertTools + include Singleton + + attr_reader :build_dir + attr_reader :project_dir + attr_reader :certificate_dir + attr_reader :distrusted_certs_dir + attr_reader :revoked_certs_dir + attr_reader :root_certs_dir + attr_reader :intermediate_certs_dir + attr_reader :security_tool_path + attr_reader :output_keychain_path + attr_writer :saved_kc_list + + # Initialize the single instance with the path strings needed by this script + def initialize() + + @saved_kc_list = nil; + @build_dir = ENV["BUILT_PRODUCTS_DIR"] + @project_dir = ENV["PROJECT_DIR"] + @certificate_dir = File.join(@project_dir, "..") + + @distrusted_certs_dir = File.join(certificate_dir, "distrusted") + @revoked_certs_dir = File.join(certificate_dir, "revoked") + @root_certs_dir = File.join(certificate_dir, "roots") + @intermediate_certs_dir = File.join(certificate_dir, "certs") + + Utilities.check_path(@distrusted_certs_dir) + Utilities.check_path(@revoked_certs_dir) + Utilities.check_path(@root_certs_dir) + Utilities.check_path(@intermediate_certs_dir) + + @security_tool_path = '/usr/bin/security' + Utilities.check_path(@security_tool_path, false) + + @output_keychain_path = File.join(@build_dir , "BuiltKeychains") + FileUtils.mkdir_p(@output_keychain_path) if !FileTest.exists? @output_keychain_path + + output_variables = false + if output_variables + puts "=================================================" + puts "CertTools variables" + puts " " + puts "@build_dir = #{@build_dir}" + puts "@project_dir = #{@project_dir}" + puts "@certificate_dir = #{@certificate_dir}" + puts "@distrusted_certs_dir = #{@distrusted_certs_dir}" + puts "@revoked_certs_dir = #{@revoked_certs_dir}" + puts "@root_certs_dir = #{@root_certs_dir}" + puts "@intermediate_certs_dir = #{@intermediate_certs_dir}" + puts "@security_tool_path = #{@security_tool_path}" + puts "@output_keychain_path = #{@output_keychain_path}" + puts "=================================================" + puts " " + end + end + + # Get the Build (output) directory path + def self.build_dir + CertTools.instance.build_dir + end + + # Get the directory path to the top level cedrtificates submodule + def self.certificate_dir + CertTools.instance.certificate_dir + end + + # Get the directory path to the certs directory + def self.distrusted_certs_dir + CertTools.instance.distrusted_certs_dir + end + + # Get the directory path to the revoked directory + def self.revoked_certs_dir + CertTools.instance.revoked_certs_dir + end + + # Get the directory path to the roots directory + def self.root_certs_dir + CertTools.instance.root_certs_dir + end + + # Get the directory path to the certs directory + def self.intermediate_certs_dir + CertTools.instance.intermediate_certs_dir + end + + # Get the path to the security tool + def self.security_tool_path + CertTools.instance.security_tool_path + end + + # Get the directory path to the output directory for the generated keychains + def self.output_keychain_path + CertTools.instance.output_keychain_path + end + + # Save the current keychain list + def self.saveKeychainList() + cmd_str = CertTools.instance.security_tool_path + " list -d user" + temp = `#{cmd_str}` + CertTools.instance.saved_kc_list = temp + $? + end + + # Restore the keychain list from a previous call to saveKeychainList + def self.restoreKeychainList() + return if CertTools.instance.saved_kc_list.nil? + st = CertTools.instance.security_tool_path + cmd_str = "echo -n " + Utilities.quote_str(CertTools.instance.saved_kc_list) + " | xargs " + st + " list -d user -s" + `#{cmd_str}` + $? + end + + # Create a new Keychain file + def self.createKeychain(path, name) + FileUtils.rm_rf(path) if FileTest.exists? path + cmd_str = CertTools.security_tool_path + " create-keychain -p " + Utilities.quote_str(name) + " " + Utilities.quote_str(path) + `#{cmd_str}` + $? + end + + +end + +# ============================================================================= +# Class: BuildRootKeychains +# +# Description: This class provides the necessary functionality to create the +# SystemRootCertificates.keychain and the +# SystemTrustSettings.plist output files. +# ============================================================================= +class BuildRootKeychains + + attr_reader :root_cert_file_name + attr_reader :root_cert_kc_path + attr_reader :settings_file_name + attr_reader :setting_file_path + attr_reader :temp_kc_name + attr_reader :temp_kc_path + + + attr :verbose + + # Initialize this instance with the paths to the output files + def initialize(verbose = true) + @verbose = verbose + + @root_cert_file_name = "SystemRootCertificates.keychain" + @root_cert_kc_path = File.join(CertTools.output_keychain_path, @root_cert_file_name) + + @settings_file_name = "SystemTrustSettings.plist" + @setting_file_path = File.join(CertTools.output_keychain_path, @settings_file_name) + + @temp_kc_name = "SystemTempCertificates.keychain" + @temp_kc_path = File.join(CertTools.build_dir, @temp_kc_name) + + end + + # Create the SystemRootCertificates.keychain + def create_root_keychain() + puts "Creating empty System Root certificates keychain at #{@root_cert_kc_path}" if @verbose + CertTools.createKeychain(@root_cert_kc_path, @root_cert_file_name) + end + + # Create the SystemTrustSettings.plist file + def create_setting_file() + puts "Creating empty Setting file at #{@setting_file_path}" if @verbose + FileUtils.rm_rf(@setting_file_path) if FileTest.exists? @setting_file_path + cmd_str = CertTools.security_tool_path + " add-trusted-cert -o " + Utilities.quote_str(@setting_file_path) + `#{cmd_str}` + $? + end + + # Add all of the root certificates in the root directory to the SystemRootCertificates.keychain + def add_roots() + puts "Adding root certs to #{@root_cert_file_name}" if @verbose + num_root_certs = 0 + Dir.foreach(CertTools.root_certs_dir) do |f| + next if f[0].chr == "." + #puts "Processing root #{f}" if @verbose + full_root_path = File.join(CertTools.root_certs_dir, f) + if f == "AppleDEVID.cer" + puts " sipping intermediate #{f} for trust" if @verbose + cmd_str = CertTools.security_tool_path + " -q add-certificates -k " + Utilities.quote_str(@root_cert_kc_path) + " " + + Utilities.quote_str(full_root_path) + + `#{cmd_str}` + Utilities.bail("Security tool add-certificates returned an error for #{full_root_path}") if $? != 0 + else + cmd_str = CertTools.security_tool_path + cmd_str += " -q add-trusted-cert -i " + cmd_str += Utilities.quote_str(@setting_file_path) + cmd_str += " -o " + cmd_str += Utilities.quote_str(@setting_file_path) + cmd_str += " -k " + cmd_str += Utilities.quote_str(@root_cert_kc_path) + cmd_str += " " + cmd_str += Utilities.quote_str(full_root_path) + cmd_result = `#{cmd_str}` + Utilities.bail("Security tool add-trusted-cer returned an error for #{full_root_path}") if $? != 0 + new_num_certs = get_num_root_certs + if new_num_certs <= num_root_certs then + puts "Root #{f} was not added! result = #{cmd_result.to_s}" + puts cmd_str + end + num_root_certs = new_num_certs + end + end + true + end + + # Create a temp keychain needed by this script + def create_temp_keychain() + puts "Creating empty temp keychain at #{@temp_kc_path}" if @verbose + CertTools.createKeychain(@temp_kc_path, @temp_kc_name) + end + + # Delete the temp keychain + def delete_temp_keychain() + FileUtils.rm_rf(@temp_kc_path) if FileTest.exists? @temp_kc_path + end + + # Process a directory of certificates that are not to be trusted. + def process_certs(message, dir) + puts message if @verbose + Dir.foreach(dir) do |f| + next if f[0].chr == "." + full_path = File.join(dir, f) + #puts "Processing #{f}" if @verbose + cmd_str = CertTools.security_tool_path + #cmd_str += " -q add-trusted-cert -i " + cmd_str += " add-trusted-cert -i " + cmd_str += Utilities.quote_str(@setting_file_path) + cmd_str += " -o " + cmd_str += Utilities.quote_str(@setting_file_path) + cmd_str += " -k " + cmd_str += Utilities.quote_str(@temp_kc_path) + cmd_str += " -r deny " + cmd_str += Utilities.quote_str(full_path) + `#{cmd_str}` + Utilities.bail("Security add-trusted-cert returned an error for #{full_path}") if $? != 0 + end + end + + # Process the distrusted certificates + def distrust_certs() + process_certs("Explicitly distrusting certs", CertTools.distrusted_certs_dir) + end + + # Process the revoked certificates + def revoked_certs() + process_certs("Explicitly distrusting certs", CertTools.revoked_certs_dir) + end + + def get_num_root_certs() + cmd_str = CertTools.security_tool_path + " find-certificate -a " + Utilities.quote_str(@root_cert_kc_path) + cert_str = `#{cmd_str}` + Utilities.bail(" find-certificate failed") if $? != 0 + cert_list = cert_str.split + labl_list = cert_list.grep(/issu/) + labl_list.length + end + + # Ensure that all of the certs in the directory were added to the SystemRootCertificates.keychain file + def check_all_roots_added() + + #cmd_str = CertTools.security_tool_path + " find-certificate -a " + Utilities.quote_str(@root_cert_kc_path) + #cert_str = `#{cmd_str}` + #Utilities.bail(" find-certificate failed") if $? != 0 + #cert_list = cert_str.split + #labl_list = cert_list.grep(/labl/) + #num_items_in_kc = labl_list.length + num_items_in_kc = get_num_root_certs + + file_system_entries = Dir.entries(CertTools.root_certs_dir) + num_file_system_entries = file_system_entries.length + file_system_entries.each do |f| + if f[0].chr == "." + num_file_system_entries = num_file_system_entries - 1 + end + end + + puts "num_items_in_kc = #{num_items_in_kc}" if @verbose + puts "num_file_system_entries = #{num_file_system_entries}" if @verbose + num_items_in_kc == num_file_system_entries + end + + # Set the file access for the SystemRootCertificates.keychain and + # SystemTrustSettings.plist files + def set_file_priv() + FileUtils.chmod 0644, @setting_file_path + FileUtils.chmod 0644, @root_cert_kc_path + end + + # Do all of the processing to create the SystemRootCertificates.keychain and + # SystemTrustSettings.plist files + def do_processing() + result = create_root_keychain + Utilities.bail("create_root_keychain failed") if result != 0 + Utilities.bail("create_setting_file failed") if create_setting_file != 0 + add_roots() + Utilities.bail("create_temp_keychain failed") if create_temp_keychain != 0 + distrust_certs() + revoked_certs() + delete_temp_keychain() + Utilities.bail("check_all_roots_added failes") if !check_all_roots_added + set_file_priv() + end +end + +# ============================================================================= +# Class: BuildCAKeychain +# +# Description: This class provides the necessary functionality to create the +# SystemCACertificates.keychain output file. +# ============================================================================= +class BuildCAKeychain + + attr_reader :cert_kc_name + attr_reader :cert_kc_path + + attr :verbose + + # Initialize the output path for this instance + def initialize(verbose = true) + @verbose = verbose + + @cert_kc_name = "SystemCACertificates.keychain" + @cert_kc_path = File.join(CertTools.output_keychain_path, @cert_kc_name) + end + + + # Add all of the certificates in the certs directory to the + # SystemCACertificates.keychain file + def do_processing() + CertTools.createKeychain(@cert_kc_path, @cert_kc_name) + cert_path = CertTools.intermediate_certs_dir + + puts "Adding intermediate cderts to #{@cert_kc_path}" if @verbose + puts "Intermediates #{cert_path}" if @verbose + + Dir.foreach(cert_path) do |f| + next if f[0].chr == "." + full_path = File.join(cert_path, f) + puts "Processing #{f}" if @verbose + cmd_str = CertTools.security_tool_path + cmd_str += " -q add-certificates " + cmd_str += " -k " + cmd_str += Utilities.quote_str(@cert_kc_path) + cmd_str += " " + cmd_str += Utilities.quote_str(full_path) + `#{cmd_str}` + Utilities.bail("Security add-certificates returned an error for #{full_path}") if $? != 0 + end + + FileUtils.chmod 0644, @cert_kc_path + end +end + + +# ============================================================================= +# Class: BuildEVRoots +# +# Description: This class provides the necessary functionality to create the +# EVRoots.plist output file. +# ============================================================================= +class BuildEVRoots + attr_reader :open_ssl_tool_path + attr_reader :plistbuddy_tool_path + attr_reader :evroots_kc_name + attr_reader :evroots_kc_path + attr_reader :evroots_plist_name + attr_reader :evroots_plist_path + attr_reader :evroots_config_path + + attr :verbose + attr :evroots_config_data + + # Initilaize this instance with the paths to the openssl and PlistBuddy tools + # along with the output paths for the EVRoots.keychain and EVRoots.plist files + # + # The use of the openssl and PListBuddy tools should be removed. These were + # kept to ensure that the outputs between this new script and the original + # shell scripts remain the same + def initialize(verbose = true) + + @verbose = verbose + + @open_ssl_tool_path = "/usr/bin/openssl" + @plistbuddy_tool_path = "/usr/libexec/PlistBuddy" + @evroots_config_path = File.join(CertTools.certificate_dir, "CertificateTool/BuildOSXRootKeychain/evroot.config") + @evroots_config_data = nil + + Utilities.check_path(@evroots_config_path, false) + + @evroots_kc_name = "EVRoots.keychain" + @evroots_kc_path = File.join(CertTools.build_dir, @evroots_kc_name) + + @evroots_plist_name = "EVRoots.plist" + @evroots_plist_path = File.join(CertTools.output_keychain_path, @evroots_plist_name) + + end + + # Get and cache the data in the evroot.config file. + def get_config_data() + return @evroots_config_data if !@evroots_config_data.nil? + + @evroots_config_data = "" + File.open(@evroots_config_path, "r") do |file| + file.each do |line| + line.gsub!(/^#.*\n/, '') + next if line.empty? + line.gsub!(/^\s*\n/, '') + next if line.empty? + @evroots_config_data += line + end + end + @evroots_config_data + end + + # Break the string from the get_config_data method into an array of lines. + def get_cert_lines() + lines_str = get_config_data + lines = lines_str.split("\n") + lines + end + + # The processing for the EVRoots.plist requires two passes. This first pass + # adds the certs in the evroot.config file to the EVRoots.keychain + def pass_one() + lines = get_cert_lines + lines.each do |line| + items = line.split('"') + items.shift + items.each do |cert_file| + next if cert_file.empty? || cert_file == " " + cert_file.gsub!(/\"/, '') + puts "Adding cert from file #{cert_file}" if @verbose + cert_to_add = File.join(CertTools.root_certs_dir, cert_file) + Utilities.bail("#{cert_to_add} does not exist") if !FileTest.exists?(cert_to_add) + + quoted_cert_to_add = Utilities.quote_str(cert_to_add) + cmd_str = CertTools.security_tool_path + " -q add-certificates -k " + @evroots_kc_path + " " + quoted_cert_to_add + `#{cmd_str}` + Utilities.bail("#{cmd_str} failed") if $? != 0 && $? != 256 + end # items.each do |cert_file| + end # lines.each do |line| + end + + # The second pass does the work to create the EVRoots.plist + def pass_two() + lines = get_cert_lines + lines.sort! + lines.each do |line| + # Split the line using a doulbe quote. This is needed to ensure that file names with spaces work + items = line.split('"') + + # Get the oid string which is the first item in the array. + oid_str = items.shift + oid_str.gsub!(/\s/, '') + + # For each line in the evroot.config there may be multiple certs for a single oid string. + # This is supported by adding an array in the EVRoots.plist + index = 0 + cmd_str = @plistbuddy_tool_path + " -c " + '"' + "add :#{oid_str} array" + '"' + " " + @evroots_plist_path + `#{cmd_str}` + Utilities.bail("#{cmd_str} failed") if $? != 0 + + # Loop through all of the cert file names in the line. + items.each do |cert_file| + # Get the full path to the cert file. + next if cert_file.empty? || cert_file == " " + cert_file.gsub!(/\"/, '') + cert_to_hash = File.join(CertTools.root_certs_dir, cert_file) + Utilities.bail("#{cert_to_hash} does not exist") if !FileTest.exists?(cert_to_hash) + + # Use the openssl command line tool (yuck!) to get the fingerprint of the certificate + cmd_str = @open_ssl_tool_path + " x509 -inform DER -in " + Utilities.quote_str(cert_to_hash) + " -fingerprint -noout" + finger_print = `#{cmd_str}` + Utilities.bail("#{cmd_str} failed") if $? != 0 + + # Post process the data from the openssl tool to get just the hex hash fingerprint. + finger_print.gsub!(/SHA1 Fingerprint=/, '') + finger_print.gsub!(/:/,'').chomp! + puts "Certificate fingerprint for #{cert_file} SHA1: #{finger_print}" if @verbose + + # Convert the hex hash string to binary data and write that data out to a temp file + binary_finger_print = Utilities.hex_to_bin(finger_print) + FileUtils.rm_f "/tmp/certsha1hashtmp" + File.open("/tmp/certsha1hashtmp", "w") { |f| f.write binary_finger_print } + + # Use the PlistBuddy tool to add the binary data to the EVRoots.plist array for the oid + cmd_str = @plistbuddy_tool_path + " -c " + '"' + "add :#{oid_str}:#{index} data" + '"' + " -c " + '"' + + "import :#{oid_str}:#{index} " + "/tmp/certsha1hashtmp" + '"' + " " + @evroots_plist_path + `#{cmd_str}` + Utilities.bail("#{cmd_str} failed") if $? != 0 + + # Verify the hash value by using the PListbuddy tool to read back in the binary hash data + cmd_str = @plistbuddy_tool_path + " -c " + '"' + "print :#{oid_str}:#{index} data" + '" ' + @evroots_plist_path + file_binary_finger_print = `#{cmd_str}` + Utilities.bail("#{cmd_str} failed") if $? != 0 + file_binary_finger_print.chomp! + + # Convert the binary data into hex data to make comparision easier + hex_finger_print = Utilities.bin_to_hex(binary_finger_print) + hex_file_finger_print = Utilities.bin_to_hex(file_binary_finger_print) + + # Compare the two hex strings to ensure the all is well + if hex_finger_print != hex_file_finger_print + puts "### BUILD FAILED: data verification error" + puts "You likely need to install a newer version of #{@plistbuddy_tool_path} see for details" + CertTools.restoreKeychainList + FileUtils.rm_f @evroots_plist_path + exit 1 + end + + # All is well prepare for the next item to add to the array + index += 1 + + end # items.each do |cert_file| + end # lines.each do |line| + end # def pass_two() + + # Do all of the necessary work for this class + def do_processing() + CertTools.saveKeychainList + CertTools.createKeychain(@evroots_kc_path, @evroots_kc_name) + pass_one + puts "Removing #{@evroots_plist_path}" if @verbose + FileUtils.rm_f @evroots_plist_path + pass_two + FileUtils.chmod 0644, @evroots_plist_path + puts "Built #{@evroots_plist_path} successfully" if @verbose + end + +end + +# Make the SystemRootCertificates.keychain and SystemTrustSettings.plist files + +# To get verbose logging set this true +verbose = false; + +brkc = BuildRootKeychains.new(verbose) +brkc.do_processing + +# Make the SystemCACertificates.keychain file +bcakc = BuildCAKeychain.new(verbose) +bcakc.do_processing + +# Make the EVRoots.plist file +bevr = BuildEVRoots.new(verbose) +bevr.do_processing + +# M I C R O S O F T H A C K ! +# It turns out that the Mac Office (2008) rolled there own solution to roots. +# The X509Anchors file used to hold the roots in old version of OSX. This was +# an implementation detail and was NOT part of the API set. Unfortunately, +# Microsoft used the keychain directly instead of using the supplied APIs. When +# the X509Anchors file was removed it broke Mac Office. So this file is now +# supplied to keep Office from breaking. It is NEVER updated and there is no +# code to update this file. We REALLY should see if this is still necessary +x509_anchors_path = File.join(CertTools.certificate_dir, "CertificateTool/BuildOSXRootKeychain/X509Anchors") +output_dir = File.join(CertTools.output_keychain_path, "X509Anchors") +FileUtils.cp x509_anchors_path, output_dir + +puts "That's all folks!" diff --git a/certificates/CertificateTool/BuildOSXRootKeychain/certsha1hashtmp b/certificates/CertificateTool/BuildOSXRootKeychain/certsha1hashtmp new file mode 100644 index 0000000000000000000000000000000000000000..b54eb314fdf0f518a4936f2e7b7618840848a61a GIT binary patch literal 100 fcmdm?oXwywE7lgw7@8xv#QfCj|A%+)pt2YM-CQZ= literal 0 HcmV?d00001 diff --git a/certificates/CertificateTool/BuildOSXRootKeychain/evroot.config b/certificates/CertificateTool/BuildOSXRootKeychain/evroot.config new file mode 100755 index 00000000..1f5c2864 --- /dev/null +++ b/certificates/CertificateTool/BuildOSXRootKeychain/evroot.config @@ -0,0 +1,462 @@ +# ------------------------------------------------------------------------------ +# Extended Validation CA Policy OIDs +# Last updated: 19 Aug 2014, MKC/KCM +# +# Each uncommented non-empty line contains a mapping from a CA-defined EV OID +# to the certificate file(s) in ./roots which are authoritative for that OID. +# These lines are processed by the buildEVRoots script to generate the plist. +# + +# Actalis +# source: , +# confirmed by http://portal.actalis.it/cms/translations/en/actalis/Info/Solutions/Documents/ActalisCA_Audit_Statement.pdf +# +# (1.3.159.1.17.1) = 06062B811F011101 +# +# roots: Actalis Authentication Root CA.cer +# +1.3.159.1.17.1 "Actalis Authentication Root CA.cer" + + +# AffirmTrust +# source: +# confirmed by http://www.affirmtrust.com/images/AffirmTrust_CPS_v1.1_12-23-2010.pdf +# +# (1.3.6.1.4.1.34697.2.1) = +# +# roots: AffirmTrust-Commercial.der, AffirmTrust-Networking.der, AffirmTrust-Premium.der, AffirmTrust-Premium-ECC.der +# +1.3.6.1.4.1.34697.2.1 "AffirmTrust-Commercial.der" +1.3.6.1.4.1.34697.2.2 "AffirmTrust-Networking.der" +1.3.6.1.4.1.34697.2.3 "AffirmTrust-Premium.der" +1.3.6.1.4.1.34697.2.4 "AffirmTrust-Premium-ECC.der" + + +# Buypass (Norway) +# TestURL: https://valid.evident.ca23.ssl.buypass.no/ +# TestURL: https://valid.evident.ca13.ssl.buypass.no +# source: +# confirmed by https://cert.webtrust.org/ViewSeal?id=848 +# confirmed by http://www.buypass.no/Bedrift/Produkter+og+tjenester/SSL/SSL%20dokumentasjon +# +# (2.16.578.1.26.1.3.3) = 0608608442011A010303 +# +# root: Buypass Class 3 CA 1 Buypass AS-983163327 +# +# confirmed by email with John Arild Amdahl Johansen on Nov.12 2013 +# +2.16.578.1.26.1.3.3 "Buypass Class 3 Root CA.cer" "BuypassClass3CA1.cer" + + +# Certigna +# TestURL: http://www.certigna.fr/ca/ACcertigna.crt +# confirmed by +# 86F27C4BE875508EE8793C4BFC61791530729830 +# source +# +# (1.2.250.1.177.1.18.2.2) +# +# root: Certigna.cer +# +1.2.250.1.177.1.18.2.2 "Certigna.cer" + + +# Certum (Unizeto) (Poland) +# source: +# source: , +# +# ( 1 2 616 1 113527 2 5 1 1 ) = 060B2A84680186F67702050101 +# +# root: Certum Trusted Network CA +# root: Certum CA +# +1.2.616.1.113527.2.5.1.1 "Unizeto-CertumCA.cer" "Poland-Certum-CTNCA.der" "Certum Trusted Network CA 2.cer" + + +# China Internet Network Information Center (CNNIC) (China) +# source: +# +# ( 1 3 6 1 4 1 29836 1 10 ) = +# +# root: China Internet Network Information Center EV Certificates Root +# +1.3.6.1.4.1.29836.1.10 "CNNICEVRoot.der" + + +# Comodo +# source: +# confirmed by +# +# (1.3.6.1.4.1.6449.1.2.1.5.1) = 060C2B06010401B2310102010501 +# +# root: COMODO Certification Authority +# subordinate CA of: Add Trust External CA Root +# +1.3.6.1.4.1.6449.1.2.1.5.1 "COMODOCertificationAuthority.crt" "AddTrust External CA Root.crt" + + +# Cybertrust (aka Verizon Business) +# source: +# confirmed by +# +# (1.3.6.1.4.1.6334.1.100.1) = 060A2B06010401B13E016401 +# +# root: GTE Cybertrust Global Root +# root: Baltimore Cybertrust Root +# +1.3.6.1.4.1.6334.1.100.1 "BTCTRT.cer" "GTEGB18.cer" + + +# DigiCert +# source: +# confirmed by +# confirmed by +# +# (2.16.840.1.114412.2.1) = 06096086480186FD6C0201 // EV CA-1 +# (2.16.840.1.114412.1.3.0.2) = 060B6086480186FD6C01030002 // EV CA-2 +# +# root: DigiCert High Assurance EV Root CA +# previously a subordinate CA of: Entrust.net Secure Server Certification Authority +# +2.16.840.1.114412.1.3.0.2 "DigiCertHighAssuranceEVRootCA.crt" + +# A14B48D943EE0A0E40904F3CE0A4C09193515D3F +# F517A24F9A48C6C9F8A200269FDC0F482CAB3089 +# DF3C24F9BFD666761B268073FE06D1CC8D4F82A4 +# 7E04DE896A3E666D00E687D33FFAD93BE83D349E +# DDFB16CD4931C973A2037D3FC83A4D7D775D05E4 +# TestURL: https://assured-id-root-g2.digicert.com +# TestURL: https://assured-id-root-g3.digicert.com +# TestURL: https://global-root-g2.digicert.com +# TestURL: https://global-root-g3.digicert.com +# TestURL: https://trusted-root-g4.digicert.com +# confirmed by +2.16.840.1.114412.2.1 "DigiCertHighAssuranceEVRootCA.crt" "DigiCertAssuredIDRootG2.der" "DigiCertAssuredIDRootG3.der" "DigiCertGlobalRootG2.der" "DigiCertGlobalRootG3.der" "DigiCertTrustedRootG4.der" + + +# DigiNotar +# source: +# confirmed by +# +# (2.16.528.1.1001.1.1.1.12.6.1.1.1) = 060E6084100187690101010C06010101 +# +# root: DigiNotar Root CA +# +# removed per +# 2.16.528.1.1001.1.1.1.12.6.1.1.1 "DigiNotarRootCA2007.crt" + + +# D-Trust +# open .D-Trust root certificates +# +# 1.3.6.1.4.1.4788.2.202.1 +# +# root: D-TRUST_Root_Class_3_CA_2_EV_2009.cer +# +1.3.6.1.4.1.4788.2.202.1 "D-TRUST_Root_Class_3_CA_2_EV_2009.cer" + + +# E-Tugra +# source: +# Test URL: https://sslev.e-tugra.com.tr +# +2.16.792.3.0.4.1.1.4 "E-Tugra.der" + +# Entrust +# 503006091D97D4F5AE39F7CBE7927D7D652D3431 +# B31EB1B740E36C8402DADC37D44DF5D4674952F9 +# 8CF427FD790C3AD166068DE81E57EFBB932272D4 +# 20d80640df9b25f512253a11eaf7598aeb14b547 +# TestURL: https://2048test.entrust.net/ +# TestURL: https://validev.entrust.net/ +# TestURL: https://validg2.entrust.net/ +# TestURL: https://validec.entrust.net/ +# source: +# confirmed by +# +# (2.16.840.1.114028.10.1.2) = 060A6086480186FA6C0A0102 +# +# root: Entrust.net Secure Server Certification Authority +# root: Entrust Root Certification Authority +# +# confirmed by +2.16.840.1.114028.10.1.2 "EntrustEVRoot.crt" "EntrustRoot-G2.der" "EntrustRoot-EC1.der" "entrust2048.der" + + +# GeoTrust +# source: +# confirmed by +# G3 root added: +# +# (1.3.6.1.4.1.14370.1.6) = 06092B06010401F0220106 +# +# root: GeoTrust Primary Certification Authority +# subordinate CA of: Equifax Secure Certificate Authority +# +1.3.6.1.4.1.14370.1.6 "geotrust-primary-ca.crt" "Equifax_Secure_Certificate_Auth" "GeoTrust Primary Certification Authority - G3.cer" + + +# GlobalSign +# source: +# confirmed by +# +# (1.3.6.1.4.1.4146.1.1) = 06092B06010401A0320101 +# +# root: GlobalSign Root CA - R3 +# root: GlobalSign Root CA - R2 +# root: GlobalSign Root CA +# +1.3.6.1.4.1.4146.1.1 "GlobalSignRootCA-R2.cer" "globalSignRoot.cer" "GlobalSign-Root-R3.der" + + +# Go Daddy (aka Starfield Technologies) +# source: +# confirmed by +# +# (2.16.840.1.114413.1.7.23.3) = 060B6086480186FD6D01071703 +# (2.16.840.1.114414.1.7.23.3) = 060B6086480186FD6E01071703 +# +# root: Go Daddy Class 2 Certification Authority (for 114413) +# root: Starfield Class 2 Certificate Authority (for 114414) +# root: Starfield Root Certificate Authority - G2 (for 114414) +# root: Starfield Services Root Certificate Authority - G2 (for 114414) +# previously subordinate CA of: Valicert Class 2 Policy Validation Authority (both) +# +2.16.840.1.114413.1.7.23.3 "GD-Class2-root.crt" "GoDaddyRootCertificateAuthorityG2.der" +2.16.840.1.114414.1.7.23.3 "SF-Class2-root.crt" "StarfieldRootCertificateAuthorityG2.der" +2.16.840.1.114414.1.7.24.3 "StarfieldServicesRootCertificateAuthorityG2.der" + + +# Izenpe +# source: +# source: +# confirmed by +# +# (1.3.6.1.4.1.14777.6.1.1) = +# (1.3.6.1.4.1.14777.6.1.2) = +# +# root: Izenpe.com +# root: Izenpe.com/emailAddress=Info@izenpe.com +# +1.3.6.1.4.1.14777.6.1.1 "Izenpe-RAIZ2007.crt" "Izenpe-ca_raiz2003.crt" +1.3.6.1.4.1.14777.6.1.2 "Izenpe-RAIZ2007.crt" "Izenpe-ca_raiz2003.crt" + + +# KEYNECTIS (aka Certplus) +# source: +# confirmed by +# +# (1.3.6.1.4.1.22234.2.5.2.3.1) = +# +# root: Class 2 Primary CA +# +1.3.6.1.4.1.22234.2.5.2.3.1 "certplus_class2.der" + + +# Logius (aka Staat der Nederlanden) +# source: application for root trust store inclusion for Logius EV certificate +# confirmed by , +# +# +# +# (2.16.528.1.1003.1.2.7) = 060960841001876B010207 +# +# root: Staat der Nederlanden EV Root CA +# +2.16.528.1.1003.1.2.7 "Staat der Nederlanden EV Root CA.cer" + + +# Network Solutions +# source: +# confirmed by +# +# (1.3.6.1.4.1.782.1.2.1.8.1) = 060C2B06010401860E0102010801 +# +# root: Network Solutions Certificate Authority +# subordinate CA of: AddTrust External CA Root +# +1.3.6.1.4.1.782.1.2.1.8.1 "NetworkSolutionsEVRoot.crt" "AddTrust External CA Root.crt" + + +# QuoVadis +# source: +# confirmed by +# +# (1.3.6.1.4.1.8024.0.2.100.1.2) = 060C2B06010401BE580002640102 +# +# root: QuoVadis Root Certification Authority +# root: QuoVadis Root CA 2 +# +1.3.6.1.4.1.8024.0.2.100.1.2 "qvrca.crt" "qvrca2.crt" + + +# Secom (aka SECOM Trust Systems Co., Ltd.) +# TestURL: https://scrootca2test.secomtrust.net also consider: https://fmctest.secomtrust.net/ +# FEB8C432DCF9769ACEAE3DD8908FFD288665647D +# source: +# +# (1.2.392.200091.100.721.1) = 060A2A83088C9B1B64855101 +# +# root: Security Communication RootCA1 +# +1.2.392.200091.100.721.1 "SCRoot1ca.cer" "SECOM-EVRoot1ca.cer" "SECOM-RootCA2.cer" + + +# StartCom +# source: +# confirmed by , +# +# (1.3.6.1.4.1.23223.2) = +# (1.3.6.1.4.1.23223.1.1.1) = +# +# root: StartCom Certification Authority +# +1.3.6.1.4.1.23223.2 "startcom-sfsca.der" "startcomSHA2.der" "StartCom May 2013 G2.der" +1.3.6.1.4.1.23223.1.1.1 "startcom-sfsca.der" "startcomSHA2.der" "StartCom May 2013 G2.der" + + +# SwissCom +# source : SwissCom Root Certificates +# TestURL: https://test-quarz-ev-ca-2.pre.swissdigicert.ch/ +# confirmed by , +# +# +# previously, we had noted these additional OIDs for SwissCom: +# (2.16.756.1.83.20.1.1) = 06086085740153140101 +# (the 21.0 OID was listed on +# (2.16.756.1.83.21.0) = 060760857401531500 +# +# (2.16.756.1.83.2.2) = 060760857401530202 +# +# E7A19029D3D552DC0D0FC692D3EA880D152E1A6B +# +2.16.756.1.83.2.2 "Swisscom Root EV CA 2.cer" + + +# SwissSign +# source: +# repository: https://swisssign.com/english/gold/view-category.html +# +# (2.16.756.1.89.1.2.1.1) = ... +# +# root: SwissSign Gold CA - G2 +# +2.16.756.1.89.1.2.1.1 "SwissSign-Gold_G2.der" + + +# TrustCenter (DE) +# source: +# +# (1.2.276.0.44.1.1.1.4) = ... +# +# root: TC TrustCenter Universal CA III +# +1.2.276.0.44.1.1.1.4 "trustCenter-root-5.der" + + +# Trustwave (aka SecureTrust, formerly XRamp) +# source: +# +# (2.16.840.1.114404.1.1.2.4.1) = 060C6086480186FD640101020401 +# +# root: SecureTrust CA +# root: Secure Global CA +# root: XRamp Global CA +# subordinate CA of: Entrust.net Secure Server Certification Authority +# +2.16.840.1.114404.1.1.2.4.1 "Trustwave-STCA.der" "Trustwave-SGCA.der" "XGCA.crt" "EntrustRootCA1024.crt" + + +# Thawte +# source: +# G3 EV root added: +# +# (2.16.840.1.113733.1.7.48.1) = 060B6086480186F84501073001 +# +# root: thawte Primary Root CA +# subordinate CA of: Thawte Premium Server CA +# +2.16.840.1.113733.1.7.48.1 "thawte-primary-root-ca.crt" "serverpremium.crt" "Thawte_Premium_Server_CA.cer" "thawte Primary Root CA - G3.cer" + + +# T-TeleSec +# source: T-Systems / Telesec.de root certificates +# +# (1.3.6.1.4.1.7879.13.24.1) +# +# root: T-TeleSec GlobalRoot Class 2 T-TeleSec GlobalRoot Class 3 +# +1.3.6.1.4.1.7879.13.24.1 "T-TeleSec GlobalRoot Class 2.cer" "T-TeleSec GlobalRoot Class 3.cer" + + +# VeriSign +# source: +# +# (2.16.840.1.113733.1.7.23.6) = 060B6086480186F84501071706 +# +# root: VeriSign Class 3 Public Primary Certification Authority - G5 +# subordinate CA of: Class 3 Public Primary Certification Authority +# +# Symantec +# source: Symantec ECC root certificates May 2013 +# +# VeriSign +# source: Symantec ECC root certificates May 2013 +# EV OID correction: EV-enablement for Verisign root certificate already in the keychain +# +2.16.840.1.113733.1.7.23.6 "VeriSignC3PublicPrimaryCA-G5.cer" "PCA3ss_v4.509" "Symantec Class 3 Public Primary Certification Authority - G4.cer" "VeriSign Class 3 Public Primary Certification Authority - G4.cer" "VeriSign Universal Root Certification Authority.cer" + + +# Wells Fargo +# source: +# confirmed by +# +# (2.16.840.1.114171.500.9) = 060A6086480186FB7B837409 +# +# root: WellsSecure Public Root Certificate Authority +# +2.16.840.1.114171.500.9 "WellsSecurePRCA.der" + + +# Camerfirma +# TestURL: https://server2.camerfirma.com:8082 +# TestURL: https://www.camerfirma.com/ +# confirmed by +# +# (1.3.6.1.4.1.17326.10.14.2.1.2) = 060D2B0601040181872E0A0E020102 +# (1.3.6.1.4.1.17326.10.8.12.1.2) = 060D2B0601040181872E0A080C0102 +# +# 786A74AC76AB147F9C6A3050BA9EA87EFE9ACE3C +# 6E3A55A4190C195C93843CC0DB722E313061F0B1 +# +1.3.6.1.4.1.17326.10.14.2.1.2 "ROOT-CHAMBERSIGN.crt" "ROOT-CHAMBERS.crt" "root_chambers-2008.der" +1.3.6.1.4.1.17326.10.8.12.1.2 "root_chambersign-2008.der" + + +# Firmaprofesional +# AEC5FB3FC8E1BFC4E54F03075A9AE800B7F7B6FA +# Firmaprofesional-CIF-A62634068.der +# TestURL: https://publifirma.firmaprofesional.com/ +# confirmed by +# +# (1.3.6.1.4.1.13177.10.1.3.10) = 060B2B06010401E6790A01030A +# +1.3.6.1.4.1.13177.10.1.3.10 "Firmaprofesional-CIF-A62634068.der" + + +# TWCA +# TestURL (4096): https://evssldemo3.twca.com.tw/index.html +# TestURL (2048): https://evssldemo.twca.com.tw/index.html +# confirmed with Robin Lin of TWCA on August 13 2013 +# +# (1.3.6.1.4.1.40869.1.1.22.3) = 060C2B0601040182BF2501011603 +# +# 9CBB4853F6A4F6D352A4E83252556013F5ADAF65 +# CF9E876DD3EBFC422697A3B5A37AA076A9062348 +# +1.3.6.1.4.1.40869.1.1.22.3 "TWCARootCA-4096.der" "twca-root-1.der" + + + +# ------------------------------------------------------------------------------ + diff --git a/certificates/CertificateTool/BuildiOSAsset/BuildAsset.rb b/certificates/CertificateTool/BuildiOSAsset/BuildAsset.rb new file mode 100644 index 00000000..87fde456 --- /dev/null +++ b/certificates/CertificateTool/BuildiOSAsset/BuildAsset.rb @@ -0,0 +1,222 @@ +# +# BuildAsset.rb +# CertificateTool +# +# Copyright 2012 Apple Inc. All rights reserved. +# + +require 'FileUtils' + +class BuildPKIAsset + attr_reader :ios_SDK_path + attr_reader :base_path + attr_reader :output_directory + attr_reader :asset_directory + attr_reader :asset_top_directory + attr_reader :asset_data_directory + attr_reader :staging_directory + attr_reader :info_plist_path + attr :verbose + + def validate_path(path, isDir = true) + return false if path.nil? || path.empty? + return false if !FileTest.exists?(path) + return false if isDir != FileTest.directory?(path) + true + end + + def output_str(str, header = false) + return if !@verbose + + puts "=====================================================" if header + puts str if !str.nil? + end + + def ensure_directory(path) + FileUtils.mkdir_p path if !validate_path(path) + validate_path(path) + end + + + def initialize(input_dir, output_directory, project_path, staging_directory, verbose = false) + + @verbose = verbose + + output_str(nil, true) + output_str "In BuildPKIAsset.initialize" + output_str "input_dir = #{input_dir}" + output_str "output_directory = #{output_directory}" + output_str "staging_directory = #{staging_directory}" + output_str(nil, true) + output_str( " ") + + # Check the input parameter + if !ensure_directory(input_dir) + puts "Invalid base directory given: #{input_dir}" + exit + end + + @base_path = File.expand_path(input_dir) + + @info_plist_path = File.join(File.join(File.expand_path(project_path), "CertificateTool"), "Info.plist") + + if !FileTest.exists? @info_plist_path + puts "Could not find the Info.plist file" + exit + end + + + if output_directory.nil? || output_directory.empty? + puts "No output directory was given" + exit + end + + asset_tool_path = `xcodebuild -sdk iphoneos.internal -find assettool` + if asset_tool_path.nil? + puts "Unable to find the mobile asset tool in the iPhone SDK" + exit + end + + + @output_directory = File.expand_path(output_directory) + + @asset_directory = File.join(@output_directory, "Assets") + ensure_directory(@asset_directory) + + @asset_top_directory = File.join(@asset_directory, "SecurityCertificatesAssets") + ensure_directory(@asset_top_directory) + + @asset_data_directory = File.join(@asset_top_directory, "AssetData/PKITrustData") + ensure_directory(@asset_data_directory) + + @staging_directory = File.expand_path(staging_directory) + ensure_directory(@staging_directory) + + + output_str(nil, true) + output_str "@base_path = #{@base_path }" + output_str "@output_directory = #{@output_directory }" + output_str "@asset_directory = #{@asset_directory }" + output_str "@asset_top_directory = #{@asset_top_directory }" + output_str "@asset_data_directory = #{@asset_data_directory }" + output_str "@staging_directory = #{@staging_directory }" + output_str "@info_plist_path = #{@info_plist_path}" + output_str "Done with BuildPKIAsset.initialize" + output_str(nil, true) + output_str( " ") + + end + + def stage + + output_str(nil, true) + output_str "In BuildPKIAsset.stage" + output_str(nil, true) + output_str( " ") + + #copy over the files into the asset directory + input_plist_file_path = @info_plist_path + + output_str(nil, true) + output_str "input_plist_file_path = #{input_plist_file_path}" + + FileUtils.cp(input_plist_file_path, @asset_top_directory) + + output_str "About to copy over the plist files" + + # copy all of the necessary files into the asset data directory + file_list = %w(AppleESCertificates.plist AssetVersion.plist Blocked.plist GrayListedKeys.plist EVRoots.plist certsIndex.data certsTable.data manifest.data) + file_list.each do |file| + file_path = File.join(@base_path, file) + if !FileTest.exists?(file_path) + output_str(nil, true) + output_str( " ") + puts "#{file_path} is missing in the base directory" + exit + end + FileUtils.cp(file_path, @asset_data_directory) + end + + output_str "Completed copying over the plist files" + + output_str "About to call assettool stage" + `xcrun -sdk iphoneos.internal assettool stage -p #{@asset_directory} -s #{@staging_directory}` + output_str "Completed call to assettool stage" + output_str(nil, true) + output_str( " ") + + output_str(nil, true) + output_str "Done with BuildPKIAsset.stage" + output_str(nil, true) + output_str( " ") + end + + def sign + output_str(nil, true) + output_str "In BuildPKIAsset.sign" + output_str "About to call assettool sign" + `xcrun -sdk iphoneos.internal assettool sign -s #{@staging_directory}` + output_str "Completed call to assettool sign" + output_str "Done with BuildPKIAsset.sign" + output_str(nil, true) + output_str( " ") + end + +end + +@verbose = false + +def do_output_str(str, header = false) + return if !@verbose + + puts "=====================================================" if header + puts str if !str.nil? +end + +build_dir = ENV["BUILT_PRODUCTS_DIR"] +project_dir = ENV["PROJECT_DIR"] + +do_output_str "Environment variables" +do_output_str " " +do_output_str "build_dir = #{build_dir}" +do_output_str "project_dir = #{project_dir}" +do_output_str(nil, true) +do_output_str(" ") + +input_path = File.join(build_dir, "asset_out") +output_path = File.join(build_dir, "Asset") +staging_path = File.join(build_dir, "staging") +asset_name = "com_apple_MobileAsset_PKITrustServices_PKITrustData" +full_asset_path = File.join(staging_path, asset_name) + +do_output_str(nil, true) +do_output_str "Path variables" +do_output_str " " +do_output_str "input_path = #{input_path}" +do_output_str "output_path = #{output_path}" +do_output_str "staging_path = #{staging_path}" +do_output_str "full_asset_path = #{full_asset_path}" +do_output_str(nil, true) +do_output_str(" ") + +do_output_str(nil, true) +do_output_str "Creating a BuildPKIAsset object to stage and sign the asset" +b = BuildPKIAsset.new(input_path, output_path, project_dir, staging_path, @verbose) +b.stage +b.sign + +do_output_str "Finished with BuildAsset" +do_output_str(nil, true) +do_output_str(" ") + +do_output_str(nil, true) +do_output_str "Output Path variables" +do_output_str(" ") +do_output_str "build_dir = #{build_dir}" +do_output_str "full_asset_path = #{full_asset_path}" + +#FileUtils.cp_r(full_asset_path, build_dir) + +do_output_str "That's all folks!" +do_output_str(nil, true) +do_output_str(" ") \ No newline at end of file diff --git a/certificates/CertificateTool/BuildiOSAsset/BuildPListFiles.rb b/certificates/CertificateTool/BuildiOSAsset/BuildPListFiles.rb new file mode 100644 index 00000000..4664772c --- /dev/null +++ b/certificates/CertificateTool/BuildiOSAsset/BuildPListFiles.rb @@ -0,0 +1,63 @@ +# +# BuildPListFiles.rb +# CertificateTool +# +# Copyright 2012 Apple Inc. All rights reserved. +# + +@verbose = false + +def do_output_str(str, header = false) + return if !@verbose + + puts "=====================================================" if header + puts str if !str.nil? +end + +do_output_str(nil, true) +do_output_str(" ") +do_output_str "Entering BuildPlistFiles.rb" +do_output_str(nil, true) +do_output_str(" ") + +build_dir = ENV["BUILT_PRODUCTS_DIR"] +sdk_name = ENV["SDK_NAME"] +top_level_directory = ENV["PROJECT_DIR"] + +do_output_str(nil, true) +do_output_str("Environment variables") +do_output_str(" ") + +do_output_str "build_dir = #{build_dir}" +do_output_str "sdk_name = #{sdk_name}" +do_output_str "top_level_directory = #{top_level_directory}" +do_output_str(nil, true) +do_output_str(" ") + +top_level_directory = File.join(top_level_directory, "..") +output_directory = File.join(build_dir, "asset_out") +tool_path = File.join(build_dir, "CertificateTool") + +do_output_str(nil, true) +do_output_str("Path variables") +do_output_str "top_level_directory = #{top_level_directory}" +do_output_str "output_directory = #{output_directory}" +do_output_str "tool_path = #{tool_path}" +do_output_str(nil, true) +do_output_str(" ") + +cmd_str = tool_path + " --top_level_directory " + "'" + top_level_directory + "' " + " --output_directory " + "'" + output_directory + "'" +do_output_str(nil, true) +do_output_str "Executing command: #{cmd_str}" +do_output_str(nil, true) +do_output_str(" ") + +`#{cmd_str}` + +do_output_str(nil, true) +do_output_str "Completed BuildPlistFiles.rb" +do_output_str(nil, true) +do_output_str(" ") + + + \ No newline at end of file diff --git a/certificates/CertificateTool/CertificateTool.xcodeproj/project.pbxproj b/certificates/CertificateTool/CertificateTool.xcodeproj/project.pbxproj new file mode 100644 index 00000000..b821d87a --- /dev/null +++ b/certificates/CertificateTool/CertificateTool.xcodeproj/project.pbxproj @@ -0,0 +1,653 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 5D3D603416826C99007B4B06 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D3D603316826C99007B4B06 /* Foundation.framework */; }; + 5D3D603716826C99007B4B06 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D3D603616826C99007B4B06 /* main.m */; }; + 5D3D604416826D90007B4B06 /* CertificateToolApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D3D604316826D90007B4B06 /* CertificateToolApp.m */; }; + 5D3D604716827A86007B4B06 /* PSUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D3D604616827A86007B4B06 /* PSUtilities.m */; }; + 5D3D604A16827B1A007B4B06 /* PSCert.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D3D604916827B1A007B4B06 /* PSCert.m */; }; + 5D3D604D16827B8B007B4B06 /* PSCertKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D3D604C16827B8B007B4B06 /* PSCertKey.m */; }; + 5D3D605016827BF7007B4B06 /* PSCerts.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D3D604F16827BF7007B4B06 /* PSCerts.m */; }; + 5D3D605616827E04007B4B06 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D3D605516827E04007B4B06 /* Security.framework */; }; + 5D5ECF03169F554500DA8F21 /* PSAssetConstants.c in Sources */ = {isa = PBXBuildFile; fileRef = 5D5ECF02169F554400DA8F21 /* PSAssetConstants.c */; }; + 727A591317345ADF00C8C901 /* DataConversion.m in Sources */ = {isa = PBXBuildFile; fileRef = 727A591217345ADF00C8C901 /* DataConversion.m */; }; + 72C8759E16B1E4D2003ECF12 /* PSCertData.m in Sources */ = {isa = PBXBuildFile; fileRef = 72C8759D16B1E4D2003ECF12 /* PSCertData.m */; }; + 72C94EC6178C6C1400F7E87D /* Info.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 72C94EC5178C6B8100F7E87D /* Info.plist */; }; + 72C94EC8178C6C3A00F7E87D /* AppleESCertificates.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 72C94EBD178C6B8100F7E87D /* AppleESCertificates.plist */; }; + 72C94EC9178C6C3A00F7E87D /* AssetVersion.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 72C94EBE178C6B8100F7E87D /* AssetVersion.plist */; }; + 72C94ECA178C6C3A00F7E87D /* Blocked.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 72C94EBF178C6B8100F7E87D /* Blocked.plist */; }; + 72C94ECB178C6C3A00F7E87D /* certsIndex.data in CopyFiles */ = {isa = PBXBuildFile; fileRef = 72C94EC0178C6B8100F7E87D /* certsIndex.data */; }; + 72C94ECC178C6C3A00F7E87D /* certsTable.data in CopyFiles */ = {isa = PBXBuildFile; fileRef = 72C94EC1178C6B8100F7E87D /* certsTable.data */; }; + 72C94ECD178C6C3A00F7E87D /* EVRoots.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 72C94EC2178C6B8100F7E87D /* EVRoots.plist */; }; + 72C94ECE178C6C3A00F7E87D /* GrayListedKeys.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 72C94EC3178C6B8100F7E87D /* GrayListedKeys.plist */; }; + 72C94ECF178C6C3A00F7E87D /* manifest.data in CopyFiles */ = {isa = PBXBuildFile; fileRef = 72C94EC4178C6B8100F7E87D /* manifest.data */; }; + 72E91D8C16C5A7DA0033D920 /* ValidateAsset.c in Sources */ = {isa = PBXBuildFile; fileRef = 5D3D605316827D17007B4B06 /* ValidateAsset.c */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 7280A8CC16D2AC69000DD5AC /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 5D3D602816826C99007B4B06 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5D3D602F16826C99007B4B06; + remoteInfo = CertificateTool; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 72C94EC7178C6C1F00F7E87D /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = SecurityCertificatesAssets/AssetData; + dstSubfolderSpec = 16; + files = ( + 72C94EC8178C6C3A00F7E87D /* AppleESCertificates.plist in CopyFiles */, + 72C94EC9178C6C3A00F7E87D /* AssetVersion.plist in CopyFiles */, + 72C94ECA178C6C3A00F7E87D /* Blocked.plist in CopyFiles */, + 72C94ECB178C6C3A00F7E87D /* certsIndex.data in CopyFiles */, + 72C94ECC178C6C3A00F7E87D /* certsTable.data in CopyFiles */, + 72C94ECD178C6C3A00F7E87D /* EVRoots.plist in CopyFiles */, + 72C94ECE178C6C3A00F7E87D /* GrayListedKeys.plist in CopyFiles */, + 72C94ECF178C6C3A00F7E87D /* manifest.data in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 72CF429816E66DD70039F148 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = SecurityCertificatesAssets; + dstSubfolderSpec = 16; + files = ( + 72C94EC6178C6C1400F7E87D /* Info.plist in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 5D0A2B8C1694AA7000024C1B /* BuildAsset.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; name = BuildAsset.rb; path = BuildiOSAsset/BuildAsset.rb; sourceTree = SOURCE_ROOT; }; + 5D0A2B8D1694AA7000024C1B /* BuildPListFiles.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; name = BuildPListFiles.rb; path = BuildiOSAsset/BuildPListFiles.rb; sourceTree = SOURCE_ROOT; }; + 5D3D603016826C99007B4B06 /* CertificateTool */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = CertificateTool; sourceTree = BUILT_PRODUCTS_DIR; }; + 5D3D603316826C99007B4B06 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 5D3D603616826C99007B4B06 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 5D3D603916826C99007B4B06 /* CertificateTool-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CertificateTool-Prefix.pch"; sourceTree = ""; }; + 5D3D604216826D90007B4B06 /* CertificateToolApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CertificateToolApp.h; sourceTree = ""; }; + 5D3D604316826D90007B4B06 /* CertificateToolApp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CertificateToolApp.m; sourceTree = ""; }; + 5D3D604516827A86007B4B06 /* PSUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSUtilities.h; sourceTree = ""; }; + 5D3D604616827A86007B4B06 /* PSUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSUtilities.m; sourceTree = ""; }; + 5D3D604816827B1A007B4B06 /* PSCert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSCert.h; sourceTree = ""; }; + 5D3D604916827B1A007B4B06 /* PSCert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSCert.m; sourceTree = ""; }; + 5D3D604B16827B8B007B4B06 /* PSCertKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSCertKey.h; sourceTree = ""; }; + 5D3D604C16827B8B007B4B06 /* PSCertKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSCertKey.m; sourceTree = ""; }; + 5D3D604E16827BF6007B4B06 /* PSCerts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSCerts.h; sourceTree = ""; }; + 5D3D604F16827BF7007B4B06 /* PSCerts.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSCerts.m; sourceTree = ""; }; + 5D3D605216827CDB007B4B06 /* ValidateAsset.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ValidateAsset.h; sourceTree = ""; }; + 5D3D605316827D17007B4B06 /* ValidateAsset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ValidateAsset.c; sourceTree = ""; }; + 5D3D605516827E04007B4B06 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 5D5ECF01169F490200DA8F21 /* PSAssetConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSAssetConstants.h; sourceTree = ""; }; + 5D5ECF02169F554400DA8F21 /* PSAssetConstants.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = PSAssetConstants.c; sourceTree = ""; }; + 5DFB2FED169741DA00B3EEEA /* buildRootKeychain.rb */ = {isa = PBXFileReference; lastKnownFileType = text.script.ruby; name = buildRootKeychain.rb; path = BuildOSXRootKeychain/buildRootKeychain.rb; sourceTree = ""; }; + 5DFB2FF21697420300B3EEEA /* BuildOSXAsset */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = BuildOSXAsset; sourceTree = BUILT_PRODUCTS_DIR; }; + 7278ECD916D28ADC0026AB4F /* AssetVersion.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = AssetVersion.plist; sourceTree = ""; }; + 727A591117345AC100C8C901 /* DataConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataConversion.h; sourceTree = ""; }; + 727A591217345ADF00C8C901 /* DataConversion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DataConversion.m; sourceTree = ""; }; + 7280A8CB16D2AC45000DD5AC /* BuildOSXAsset copy */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "BuildOSXAsset copy"; sourceTree = BUILT_PRODUCTS_DIR; }; + 72C8759C16B1E4D2003ECF12 /* PSCertData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSCertData.h; sourceTree = ""; }; + 72C8759D16B1E4D2003ECF12 /* PSCertData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSCertData.m; sourceTree = ""; }; + 72C8BAB916C58FEE00A65BAD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 72C94EBD178C6B8100F7E87D /* AppleESCertificates.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = AppleESCertificates.plist; sourceTree = ""; }; + 72C94EBE178C6B8100F7E87D /* AssetVersion.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = AssetVersion.plist; sourceTree = ""; }; + 72C94EBF178C6B8100F7E87D /* Blocked.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = Blocked.plist; sourceTree = ""; }; + 72C94EC0178C6B8100F7E87D /* certsIndex.data */ = {isa = PBXFileReference; lastKnownFileType = file; path = certsIndex.data; sourceTree = ""; }; + 72C94EC1178C6B8100F7E87D /* certsTable.data */ = {isa = PBXFileReference; lastKnownFileType = file; path = certsTable.data; sourceTree = ""; }; + 72C94EC2178C6B8100F7E87D /* EVRoots.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = EVRoots.plist; sourceTree = ""; }; + 72C94EC3178C6B8100F7E87D /* GrayListedKeys.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = GrayListedKeys.plist; sourceTree = ""; }; + 72C94EC4178C6B8100F7E87D /* manifest.data */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = manifest.data; sourceTree = ""; }; + 72C94EC5178C6B8100F7E87D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 72CF429A16E66DD70039F148 /* Release */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Release; sourceTree = BUILT_PRODUCTS_DIR; }; + BE0875B819871FC000357E99 /* AppleBaselineEscrowCertificates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppleBaselineEscrowCertificates.h; path = ../../../Security/sec/Security/AppleBaselineEscrowCertificates.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 5D3D602D16826C99007B4B06 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5D3D605616827E04007B4B06 /* Security.framework in Frameworks */, + 5D3D603416826C99007B4B06 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 5D0A2B8A1694A96500024C1B /* BuildOSXAsset */ = { + isa = PBXGroup; + children = ( + 5DFB2FED169741DA00B3EEEA /* buildRootKeychain.rb */, + ); + name = BuildOSXAsset; + sourceTree = ""; + }; + 5D3D602716826C99007B4B06 = { + isa = PBXGroup; + children = ( + 72C94EB9178C6B8100F7E87D /* Asset */, + 5D0A2B8A1694A96500024C1B /* BuildOSXAsset */, + 5D3D603516826C99007B4B06 /* CertificateTool */, + 5D3D607016827F5F007B4B06 /* BuildiOSAsset */, + 72CF429B16E66DD70039F148 /* Release */, + 5D3D603216826C99007B4B06 /* Frameworks */, + 5D3D603116826C99007B4B06 /* Products */, + ); + sourceTree = ""; + }; + 5D3D603116826C99007B4B06 /* Products */ = { + isa = PBXGroup; + children = ( + 5D3D603016826C99007B4B06 /* CertificateTool */, + 5DFB2FF21697420300B3EEEA /* BuildOSXAsset */, + 7280A8CB16D2AC45000DD5AC /* BuildOSXAsset copy */, + 72CF429A16E66DD70039F148 /* Release */, + ); + name = Products; + sourceTree = ""; + }; + 5D3D603216826C99007B4B06 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 5D3D605516827E04007B4B06 /* Security.framework */, + 5D3D603316826C99007B4B06 /* Foundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 5D3D603516826C99007B4B06 /* CertificateTool */ = { + isa = PBXGroup; + children = ( + 5D3D605116827CAA007B4B06 /* Asset Validation Source */, + 5D3D604116826D09007B4B06 /* Source */, + 5D3D603816826C99007B4B06 /* Supporting Files */, + ); + path = CertificateTool; + sourceTree = ""; + }; + 5D3D603816826C99007B4B06 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 7278ECD916D28ADC0026AB4F /* AssetVersion.plist */, + 5D3D603916826C99007B4B06 /* CertificateTool-Prefix.pch */, + 72C8BAB916C58FEE00A65BAD /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 5D3D604116826D09007B4B06 /* Source */ = { + isa = PBXGroup; + children = ( + 5D5ECEE2169F24E100DA8F21 /* Utilities */, + 5D3D603616826C99007B4B06 /* main.m */, + 5D3D604216826D90007B4B06 /* CertificateToolApp.h */, + 5D3D604316826D90007B4B06 /* CertificateToolApp.m */, + 5D3D604516827A86007B4B06 /* PSUtilities.h */, + 5D3D604616827A86007B4B06 /* PSUtilities.m */, + 5D3D604816827B1A007B4B06 /* PSCert.h */, + 5D3D604916827B1A007B4B06 /* PSCert.m */, + 5D3D604B16827B8B007B4B06 /* PSCertKey.h */, + 5D3D604C16827B8B007B4B06 /* PSCertKey.m */, + 5D3D604E16827BF6007B4B06 /* PSCerts.h */, + 5D3D604F16827BF7007B4B06 /* PSCerts.m */, + 5D5ECF01169F490200DA8F21 /* PSAssetConstants.h */, + 5D5ECF02169F554400DA8F21 /* PSAssetConstants.c */, + 72C8759C16B1E4D2003ECF12 /* PSCertData.h */, + 72C8759D16B1E4D2003ECF12 /* PSCertData.m */, + 727A591117345AC100C8C901 /* DataConversion.h */, + 727A591217345ADF00C8C901 /* DataConversion.m */, + BE0875B819871FC000357E99 /* AppleBaselineEscrowCertificates.h */, + ); + name = Source; + sourceTree = ""; + }; + 5D3D605116827CAA007B4B06 /* Asset Validation Source */ = { + isa = PBXGroup; + children = ( + 5D3D605216827CDB007B4B06 /* ValidateAsset.h */, + 5D3D605316827D17007B4B06 /* ValidateAsset.c */, + ); + name = "Asset Validation Source"; + sourceTree = ""; + }; + 5D3D607016827F5F007B4B06 /* BuildiOSAsset */ = { + isa = PBXGroup; + children = ( + 5D0A2B8C1694AA7000024C1B /* BuildAsset.rb */, + 5D0A2B8D1694AA7000024C1B /* BuildPListFiles.rb */, + ); + name = BuildiOSAsset; + path = BuildAsset; + sourceTree = ""; + }; + 5D5ECEE2169F24E100DA8F21 /* Utilities */ = { + isa = PBXGroup; + children = ( + ); + name = Utilities; + sourceTree = ""; + }; + 72C94EB9178C6B8100F7E87D /* Asset */ = { + isa = PBXGroup; + children = ( + 72C94EBA178C6B8100F7E87D /* SecurityCertificatesAssets */, + ); + path = Asset; + sourceTree = ""; + }; + 72C94EBA178C6B8100F7E87D /* SecurityCertificatesAssets */ = { + isa = PBXGroup; + children = ( + 72C94EBB178C6B8100F7E87D /* AssetData */, + 72C94EC5178C6B8100F7E87D /* Info.plist */, + ); + path = SecurityCertificatesAssets; + sourceTree = ""; + }; + 72C94EBB178C6B8100F7E87D /* AssetData */ = { + isa = PBXGroup; + children = ( + 72C94EBC178C6B8100F7E87D /* PKITrustData */, + ); + path = AssetData; + sourceTree = ""; + }; + 72C94EBC178C6B8100F7E87D /* PKITrustData */ = { + isa = PBXGroup; + children = ( + 72C94EBD178C6B8100F7E87D /* AppleESCertificates.plist */, + 72C94EBE178C6B8100F7E87D /* AssetVersion.plist */, + 72C94EBF178C6B8100F7E87D /* Blocked.plist */, + 72C94EC0178C6B8100F7E87D /* certsIndex.data */, + 72C94EC1178C6B8100F7E87D /* certsTable.data */, + 72C94EC2178C6B8100F7E87D /* EVRoots.plist */, + 72C94EC3178C6B8100F7E87D /* GrayListedKeys.plist */, + 72C94EC4178C6B8100F7E87D /* manifest.data */, + ); + path = PKITrustData; + sourceTree = ""; + }; + 72CF429B16E66DD70039F148 /* Release */ = { + isa = PBXGroup; + children = ( + ); + path = Release; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 5D3D602F16826C99007B4B06 /* CertificateTool */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5D3D603E16826C99007B4B06 /* Build configuration list for PBXNativeTarget "CertificateTool" */; + buildPhases = ( + 5D3D602C16826C99007B4B06 /* Sources */, + 5D3D602D16826C99007B4B06 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = CertificateTool; + productName = CertificateTool; + productReference = 5D3D603016826C99007B4B06 /* CertificateTool */; + productType = "com.apple.product-type.tool"; + }; + 5DFB2FF11697420300B3EEEA /* BuildOSXAsset */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5DFB2FFB1697420300B3EEEA /* Build configuration list for PBXNativeTarget "BuildOSXAsset" */; + buildPhases = ( + 5DFB2FFE1697422700B3EEEA /* Run Script */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = BuildOSXAsset; + productName = BuildOSXAsset; + productReference = 5DFB2FF21697420300B3EEEA /* BuildOSXAsset */; + productType = "com.apple.product-type.tool"; + }; + 7280A8C616D2AC45000DD5AC /* BuildiOSAsset */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7280A8C816D2AC45000DD5AC /* Build configuration list for PBXNativeTarget "BuildiOSAsset" */; + buildPhases = ( + 7280A8C716D2AC45000DD5AC /* Run Script */, + ); + buildRules = ( + ); + dependencies = ( + 7280A8CD16D2AC69000DD5AC /* PBXTargetDependency */, + ); + name = BuildiOSAsset; + productName = BuildOSXAsset; + productReference = 7280A8CB16D2AC45000DD5AC /* BuildOSXAsset copy */; + productType = "com.apple.product-type.tool"; + }; + 72CF429916E66DD70039F148 /* Release */ = { + isa = PBXNativeTarget; + buildConfigurationList = 72CF42A216E66DD70039F148 /* Build configuration list for PBXNativeTarget "Release" */; + buildPhases = ( + 72CF429816E66DD70039F148 /* CopyFiles */, + 72C94EC7178C6C1F00F7E87D /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Release; + productName = Release; + productReference = 72CF429A16E66DD70039F148 /* Release */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 5D3D602816826C99007B4B06 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + ORGANIZATIONNAME = ""; + }; + buildConfigurationList = 5D3D602B16826C99007B4B06 /* Build configuration list for PBXProject "CertificateTool" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 5D3D602716826C99007B4B06; + productRefGroup = 5D3D603116826C99007B4B06 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 5D3D602F16826C99007B4B06 /* CertificateTool */, + 5DFB2FF11697420300B3EEEA /* BuildOSXAsset */, + 7280A8C616D2AC45000DD5AC /* BuildiOSAsset */, + 72CF429916E66DD70039F148 /* Release */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + 5DFB2FFE1697422700B3EEEA /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "ruby ./BuildOSXRootKeychain/buildRootKeychain.rb"; + showEnvVarsInLog = 0; + }; + 7280A8C716D2AC45000DD5AC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"About to call BuildPListFiles.rb\"\nruby $PROJECT_DIR/BuildiOSAsset/BuildPListFiles.rb\n\necho \"Done with BuildPListFiles.rb\"\n\n\necho \"About to call BuildAsset.rb\"\nruby $PROJECT_DIR/BuildiOSAsset/BuildAsset.rb\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 5D3D602C16826C99007B4B06 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 72E91D8C16C5A7DA0033D920 /* ValidateAsset.c in Sources */, + 727A591317345ADF00C8C901 /* DataConversion.m in Sources */, + 72C8759E16B1E4D2003ECF12 /* PSCertData.m in Sources */, + 5D3D603716826C99007B4B06 /* main.m in Sources */, + 5D3D604416826D90007B4B06 /* CertificateToolApp.m in Sources */, + 5D3D604716827A86007B4B06 /* PSUtilities.m in Sources */, + 5D3D604A16827B1A007B4B06 /* PSCert.m in Sources */, + 5D3D604D16827B8B007B4B06 /* PSCertKey.m in Sources */, + 5D3D605016827BF7007B4B06 /* PSCerts.m in Sources */, + 5D5ECF03169F554500DA8F21 /* PSAssetConstants.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 7280A8CD16D2AC69000DD5AC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5D3D602F16826C99007B4B06 /* CertificateTool */; + targetProxy = 7280A8CC16D2AC69000DD5AC /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 5D3D603C16826C99007B4B06 /* 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_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = ""; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = ""; + SUPPORTED_PLATFORMS = macosx; + VALID_ARCHS = x86_64; + }; + name = Debug; + }; + 5D3D603D16826C99007B4B06 /* 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_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = ""; + SDKROOT = ""; + SUPPORTED_PLATFORMS = macosx; + VALID_ARCHS = x86_64; + }; + name = Release; + }; + 5D3D603F16826C99007B4B06 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "CertificateTool/CertificateTool-Prefix.pch"; + HEADER_SEARCH_PATHS = /usr/local/include; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /usr/lib/system, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + USER_HEADER_SEARCH_PATHS = ../../../sec/Security; + }; + name = Debug; + }; + 5D3D604016826C99007B4B06 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "CertificateTool/CertificateTool-Prefix.pch"; + HEADER_SEARCH_PATHS = /usr/local/include; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /usr/lib/system, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + USER_HEADER_SEARCH_PATHS = ../../../sec/Security; + }; + name = Release; + }; + 5DFB2FFC1697420300B3EEEA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "BuildOSXAsset/BuildOSXAsset-Prefix.pch"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 5DFB2FFD1697420300B3EEEA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "BuildOSXAsset/BuildOSXAsset-Prefix.pch"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 7280A8C916D2AC45000DD5AC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "BuildOSXAsset/BuildOSXAsset-Prefix.pch"; + PRODUCT_NAME = "BuildOSXAsset copy"; + }; + name = Debug; + }; + 7280A8CA16D2AC45000DD5AC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "BuildOSXAsset/BuildOSXAsset-Prefix.pch"; + PRODUCT_NAME = "BuildOSXAsset copy"; + }; + name = Release; + }; + 72CF42A016E66DD70039F148 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_UNDECLARED_SELECTOR = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + 72CF42A116E66DD70039F148 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + ENABLE_NS_ASSERTIONS = NO; + GCC_WARN_UNDECLARED_SELECTOR = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 5D3D602B16826C99007B4B06 /* Build configuration list for PBXProject "CertificateTool" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5D3D603C16826C99007B4B06 /* Debug */, + 5D3D603D16826C99007B4B06 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5D3D603E16826C99007B4B06 /* Build configuration list for PBXNativeTarget "CertificateTool" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5D3D603F16826C99007B4B06 /* Debug */, + 5D3D604016826C99007B4B06 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5DFB2FFB1697420300B3EEEA /* Build configuration list for PBXNativeTarget "BuildOSXAsset" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5DFB2FFC1697420300B3EEEA /* Debug */, + 5DFB2FFD1697420300B3EEEA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7280A8C816D2AC45000DD5AC /* Build configuration list for PBXNativeTarget "BuildiOSAsset" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7280A8C916D2AC45000DD5AC /* Debug */, + 7280A8CA16D2AC45000DD5AC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 72CF42A216E66DD70039F148 /* Build configuration list for PBXNativeTarget "Release" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 72CF42A016E66DD70039F148 /* Debug */, + 72CF42A116E66DD70039F148 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 5D3D602816826C99007B4B06 /* Project object */; +} diff --git a/certificates/CertificateTool/CertificateTool.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/certificates/CertificateTool/CertificateTool.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..aa04453f --- /dev/null +++ b/certificates/CertificateTool/CertificateTool.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/certificates/CertificateTool/CertificateTool/AppleBaselineEscrowCertificates.h b/certificates/CertificateTool/CertificateTool/AppleBaselineEscrowCertificates.h new file mode 120000 index 00000000..aa17d8d2 --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/AppleBaselineEscrowCertificates.h @@ -0,0 +1 @@ +./../../Security/sec/Security/AppleBaselineEscrowCertificates.h \ No newline at end of file diff --git a/certificates/CertificateTool/CertificateTool/AssetVersion.plist b/certificates/CertificateTool/CertificateTool/AssetVersion.plist new file mode 100644 index 00000000..24920721 --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/AssetVersion.plist @@ -0,0 +1,8 @@ + + + + + VersionNumber + 2014081900 + + diff --git a/certificates/CertificateTool/CertificateTool/CertificateTool-Prefix.pch b/certificates/CertificateTool/CertificateTool/CertificateTool-Prefix.pch new file mode 100644 index 00000000..a1b6faa7 --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/CertificateTool-Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'CertificateTool' target in the 'CertificateTool' project +// + +#ifdef __OBJC__ + // #import +#endif diff --git a/certificates/CertificateTool/CertificateTool/CertificateToolApp.h b/certificates/CertificateTool/CertificateTool/CertificateToolApp.h new file mode 100644 index 00000000..c41bc186 --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/CertificateToolApp.h @@ -0,0 +1,59 @@ +// +// CertificateToolApp.h +// CertificateTool +// +// Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. +// + +#import +#import "PSCertData.h" + +@interface CertificateToolApp : NSObject +{ +@private + NSString* _app_name; + + // file system paths used by this object + NSString* _root_directory; + NSString* _revoked_directory; + NSString* _distrusted_directory; + NSString* _certs_directory; + NSString* _evroot_config_path; + NSString* _ev_plist_path; + NSString* _info_plist_path; + NSString* _top_level_directory; + //NSString* _outputDir; + NSString* _version_number_plist_path; + NSNumber* _version_number; + + PSCertData* _certRootsData; + + NSMutableDictionary* _EVRootsData; + NSMutableArray* _blacked_listed_keys; + NSMutableArray* _gray_listed_keys; + NSData* _derData; +} + +@property (readonly) NSString* app_name; +@property (readonly) NSString* root_directory; +@property (readonly) NSString* revoked_directory; +@property (readonly) NSString* distrusted_directory; +@property (readonly) NSString* certs_directory; +@property (readonly) NSString* evroot_config_path; +@property (readonly) NSString* ev_plist_path; +@property (readonly) NSString* info_plist_path; +@property (readonly) NSString* top_level_directory; +@property (readonly) NSString* output_directory; +@property (readonly) NSString* version_number_plist_path; +@property (readonly) NSNumber* version_number; + +- (id)init:(int)argc withArguments:(const char**)argv; + +- (BOOL)processCertificates; + +- (BOOL)outputPlistsToDirectory; + +- (BOOL)createManifest; + + +@end diff --git a/certificates/CertificateTool/CertificateTool/CertificateToolApp.m b/certificates/CertificateTool/CertificateTool/CertificateToolApp.m new file mode 100644 index 00000000..a065ab86 --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/CertificateToolApp.m @@ -0,0 +1,795 @@ +// +// CertificateToolApp.m +// CertificateTool +// +// Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. +// + +#import "CertificateToolApp.h" +#import "PSCerts.h" +#import "PSUtilities.h" +#import "PSAssetConstants.h" +#import "PSCertData.h" +#import "PSCert.h" +#import +#import +#import +#import "AppleBaselineEscrowCertificates.h" + + +@interface CertificateToolApp (PrivateMethods) + +- (void)usage; +- (NSString*)checkPath:(NSString*)name basePath:(NSString *)basePath isDirectory:(BOOL)isDirectory; + +- (BOOL)buildEVRootsData:(NSDictionary *)certs; +- (BOOL)ensureDirectoryPath:(NSString *)dir_path; + +@end + +@implementation CertificateToolApp + + +@synthesize app_name = _app_name; +@synthesize root_directory = _root_directory; +@synthesize revoked_directory = _revoked_directory; +@synthesize distrusted_directory = _distrusted_directory; +@synthesize certs_directory = _certs_directory; +@synthesize evroot_config_path = _evroot_config_path; +@synthesize ev_plist_path = _ev_plist_path; +@synthesize info_plist_path = _info_plist_path; +@synthesize top_level_directory = _top_level_directory; +@synthesize output_directory = _output_directory; +@synthesize version_number_plist_path = _version_number_plist_path; +@synthesize version_number = _version_number; + + +- (id)init:(int)argc withArguments:(const char**)argv +{ + if ((self = [super init])) + { + _app_name = [[NSString alloc] initWithUTF8String:argv[0]]; + + // set all of the directory paths to nil + _root_directory = nil; + _revoked_directory = nil; + _distrusted_directory = nil; + _certs_directory = nil; + _evroot_config_path = nil; + _ev_plist_path = nil; + _info_plist_path = nil; + _top_level_directory = nil; + _output_directory = nil; + _version_number_plist_path = nil; + _version_number = nil; + + + _certRootsData = nil; + _blacked_listed_keys = nil; + _gray_listed_keys = nil; + + _EVRootsData = [NSMutableDictionary dictionary]; + _derData = nil; + + + // Parse the command line arguments and set up the directory paths + for (int iCnt = 1; iCnt < argc; iCnt++) + { + const char* arg = argv[iCnt]; + if (!strcmp(arg, "-h") || !strcmp(arg, "--help")) + { + [self usage]; + return nil; + } + else if (!strcmp(arg, "-r") || !strcmp(arg, "--roots_dir")) + { + if ((iCnt + 1) == argc) + { + [self usage]; + return nil; + } + + _root_directory = [[NSString stringWithUTF8String:argv[iCnt + 1]] stringByExpandingTildeInPath]; + iCnt++; + + } + else if (!strcmp(arg, "-k") || !strcmp(arg, "--revoked_dir")) + { + if ((iCnt + 1) == argc) + { + [self usage]; + return nil; + } + + _revoked_directory = [[NSString stringWithUTF8String:argv[iCnt + 1]] stringByExpandingTildeInPath]; + iCnt++; + } + else if (!strcmp(arg, "-d") || !strcmp(arg, "--distrusted_dir")) + { + if ((iCnt + 1) == argc) + { + [self usage]; + return nil; + } + + _distrusted_directory = [[NSString stringWithUTF8String:argv[iCnt + 1]] stringByExpandingTildeInPath]; + iCnt++; + } + else if (!strcmp(arg, "-c") || !strcmp(arg, "--certs_dir")) + { + if ((iCnt + 1) == argc) + { + [self usage]; + return nil; + } + + _certs_directory = [[NSString stringWithUTF8String:argv[iCnt + 1]] stringByExpandingTildeInPath]; + iCnt++; + } + else if (!strcmp(arg, "-e") || !strcmp(arg, "--evroot.config")) + { + if ((iCnt + 1) == argc) + { + [self usage]; + return nil; + } + + _evroot_config_path = [[NSString stringWithUTF8String:argv[iCnt + 1]] stringByExpandingTildeInPath]; + iCnt++; + } + + else if (!strcmp(arg, "-i") || !strcmp(arg, "--info_plist_path")) + { + if ((iCnt + 1) == argc) + { + [self usage]; + return nil; + } + + _info_plist_path = [[NSString stringWithUTF8String:argv[iCnt + 1]] stringByExpandingTildeInPath]; + iCnt++; + } + else if (!strcmp(arg, "-t") || !strcmp(arg, "--top_level_directory")) + { + if ((iCnt + 1) == argc) + { + [self usage]; + return nil; + } + + _top_level_directory = [[NSString stringWithUTF8String:argv[iCnt + 1]] stringByExpandingTildeInPath]; + iCnt++; + } + else if (!strcmp(arg, "-o") || !strcmp(arg, "--output_directory")) + { + if ((iCnt + 1) == argc) + { + [self usage]; + return nil; + } + + _output_directory = [[NSString stringWithUTF8String:argv[iCnt + 1]] stringByExpandingTildeInPath]; + iCnt++; + } + else if (!strcmp(arg, "-v") || !strcmp(arg, "--version_number")) + { + if ((iCnt + 1) == argc) + { + [self usage]; + return nil; + } + + NSString* temp_number_str = [NSString stringWithUTF8String:argv[iCnt + 1]]; + if (nil != temp_number_str) + { + NSInteger value = [temp_number_str integerValue]; + if (value > 0) + { + _version_number = [NSNumber numberWithInteger:value]; + } + } + } + } + + if (nil == _root_directory) + { + _root_directory = [self checkPath:@"roots" basePath:_top_level_directory isDirectory:YES]; + if (nil == _root_directory) + { + [self usage]; + return nil; + } + } + + if (nil == _revoked_directory) + { + _revoked_directory = [self checkPath:@"revoked" basePath:_top_level_directory isDirectory:YES]; + if (nil == _revoked_directory) + { + [self usage]; + return nil; + } + } + + if (nil == _distrusted_directory) + { + _distrusted_directory = [self checkPath:@"distrusted" basePath:_top_level_directory isDirectory:YES]; + if (nil == _distrusted_directory) + { + [self usage]; + return nil; + } + } + + if (nil == _certs_directory) + { + _certs_directory = [self checkPath:@"certs" basePath:_top_level_directory isDirectory:YES]; + if (nil == _certs_directory) + { + [self usage]; + return nil; + } + } + + if (nil == _evroot_config_path) + { + _evroot_config_path = [self checkPath:@"EVRoots/evroot.config" basePath:_top_level_directory isDirectory:NO]; + if (nil == _evroot_config_path) + { + [self usage]; + return nil; + } + } + if (nil == _info_plist_path) + { + _info_plist_path = [self checkPath:@"assetData/Info.plist" basePath:_top_level_directory isDirectory:NO]; + if (nil == _info_plist_path) + { + [self usage]; + return nil; + } + } + if (nil == _version_number_plist_path) + { + _version_number_plist_path = [self checkPath:@"CertificateTool/CertificateTool/AssetVersion.plist" basePath:_top_level_directory isDirectory:NO]; + if (nil == _info_plist_path) + { + [self usage]; + return nil; + } + } + } + return self; +} + +- (void)usage +{ + printf("%s usage:\n", [self.app_name UTF8String]); + printf(" [-h, --help] \tPrint out this help message\n"); + printf(" [-r, --roots_dir] \tThe full path to the directory with the certificate roots\n"); + printf(" [-k, --revoked_dir] \tThe full path to the directory with the revoked certificates\n"); + printf(" [-d, --distrusted_dir] \tThe full path to the directory with the distrusted certificates\n"); + printf(" [-c, --certs_dir] \tThe full path to the directory with the cert certificates\n"); + printf(" [-e, --evroot.config] \tThe full path to the evroot.config file\n"); + printf(" [-i, --info_plist_path]) \tThe full path to the Infor.plist file\n"); + printf(" [-t, --top_level_directory] \tThe full path to the top level security_certificates directory\n"); + printf(" [-o, --output_directory] \tThe full path to the directory to write out the results\n"); + printf(" [-v, --version_number] \tThe version number of the asset\n"); + printf("\n"); +} + +- (NSString*)checkPath:(NSString*)name basePath:(NSString *)basePath isDirectory:(BOOL)isDirectory +{ + NSString* result = nil; + if (nil == name) + { + return result; + } + + NSFileManager* fileManager = [NSFileManager defaultManager]; + BOOL isDir = NO; + + if ([name hasPrefix:@"/"] || [name hasPrefix:@"~"]) + { + name = [name hasPrefix:@"~"] ? [name stringByExpandingTildeInPath] : name; + // This is a full path + if (![fileManager fileExistsAtPath:name isDirectory:&isDir] || isDir != isDirectory) + { + NSLog(@"%@ is invalid", name); + return result; + } + result = name; + } + else + { + NSString* full_path = nil; + if (nil == basePath) + { + NSLog(@"%@ is not a full path but basePath is nil", name); + return result; + } + + full_path = [basePath stringByAppendingPathComponent:name]; + if (![fileManager fileExistsAtPath:full_path isDirectory:&isDir] || isDir != isDirectory) + { + NSLog(@"%@ is invalid", full_path); + return result; + } + result = full_path; + } + return result; +} + +/* -------------------------------------------------------------------------- + Read in the evroot.config file and create a dictionary on the cert file + names and relate then to their EVRoot OIDs + -------------------------------------------------------------------------- */ +- (BOOL)buildEVRootsData:(NSDictionary *)certs +{ + BOOL result = NO; + + if (nil == _EVRootsData || nil == _evroot_config_path) + { + return result; + } + + // Read file into memory it is not that big + NSError* error = nil; + NSData* fileData = [NSData dataWithContentsOfFile:self.evroot_config_path + options:NSDataReadingMappedIfSafe error:&error]; + if (nil == fileData) + { + return result; + } + + // Turn the data into a string so that it can be edited + NSMutableString* evconfig_data = [[NSMutableString alloc] initWithData:fileData + encoding:NSUTF8StringEncoding]; + if (nil == evconfig_data) + { + return result; + } + + // Use Regex to remove all of the comments + NSRegularExpression* regex_comments = + [NSRegularExpression regularExpressionWithPattern:@"^#.*\n" + options:NSRegularExpressionAnchorsMatchLines error:&error]; + + NSRange full_string_range = NSMakeRange(0, [evconfig_data length]); + NSUInteger num_replacements = + [regex_comments replaceMatchesInString:evconfig_data + options:0 range:full_string_range withTemplate:@""]; + + if (0 == num_replacements) + { + return result; + } + + // Use Regex to remove all of the blank lines + NSRegularExpression* regex_blankLines = + [NSRegularExpression regularExpressionWithPattern:@"^\n" + options:NSRegularExpressionAnchorsMatchLines error:&error]; + + full_string_range = NSMakeRange(0, [evconfig_data length]); + num_replacements = [regex_blankLines replaceMatchesInString:evconfig_data + options:0 range:full_string_range withTemplate:@""]; + + if (0 == num_replacements) + { + return result; + } + + // Break the single string into an array of lines. + NSArray* strings = [evconfig_data componentsSeparatedByString:@"\n"]; + if (nil == strings) + { + return result; + } + + // Process each line in the array + for (NSString* aLine in strings) + { + if (nil == aLine || [aLine length] < 2) + { + continue; + } + NSRegularExpression* regex_oid_str = [NSRegularExpression regularExpressionWithPattern:@"^[[0-9]+.]+" + options:NSRegularExpressionAnchorsMatchLines error:&error]; + + full_string_range = NSMakeRange(0, [aLine length]); + NSArray* oid_str_matchs = [regex_oid_str matchesInString:aLine options:0 range:full_string_range]; + NSTextCheckingResult* ck_result = [oid_str_matchs objectAtIndex:0]; + NSRange result_range = [ck_result rangeAtIndex:0]; + NSString* oid_str = [aLine substringToIndex:result_range.length]; + NSString* remainder_str = [aLine substringFromIndex:(result_range.length + 1)]; + NSArray* items = [remainder_str componentsSeparatedByString:@"\""]; + + // The first item should be an OID string + NSUInteger num_items = [items count]; + //NSString* oid_str = [items objectAtIndex:0]; + NSUInteger iCnt = 0; + + NSMutableArray* cert_digests = [NSMutableArray array]; + // loop through the names of all of the cert files + for (iCnt = 1; iCnt < num_items; iCnt++) + { + NSString* cert_file_name = [items objectAtIndex:iCnt]; + if (cert_file_name == nil || [cert_file_name hasPrefix:@" "] || [cert_file_name length] < 2) + { + continue; + } + //NSLog(@"cert_file_name = %@", cert_file_name); + + // find the PSCert record for the file + PSCert* aCert = [certs objectForKey:cert_file_name]; + if (nil != aCert) + { + [cert_digests addObject:aCert.certificate_hash]; + } + else + { + NSLog(@"buildEVRootsData: could not find the cert for %@", cert_file_name); + } + } + + NSMutableArray* exisiting_certs = [_EVRootsData objectForKey:oid_str]; + if (nil != exisiting_certs) + { + [cert_digests addObjectsFromArray:exisiting_certs]; + } + + [_EVRootsData setObject:cert_digests forKey:oid_str]; + } + + result = YES; + return result; +} + +- (BOOL)ensureDirectoryPath:(NSString *)dir_path +{ + BOOL result = NO; + + if (nil == dir_path) + { + return result; + } + + NSFileManager* fileManager = [NSFileManager defaultManager]; + NSError* error = nil; + BOOL isDir = NO; + + if (![fileManager fileExistsAtPath:dir_path isDirectory:&isDir]) + { + result = [fileManager createDirectoryAtPath:dir_path withIntermediateDirectories:YES attributes:nil error:&error]; + if (nil != error) + { + result = NO; + } + + } + else if (isDir) + { + result = YES; + } + + return result; +} + + +- (BOOL)processCertificates +{ + BOOL result = NO; + + // From the roots directory, create the index and table data for the asset + PSAssetFlags certFlags = isAnchor | hasFullCert; + NSNumber* flags = [NSNumber numberWithUnsignedLong:certFlags]; + PSCerts* pscerts_roots = [[PSCerts alloc] initWithCertFilePath:self.root_directory withFlags:flags]; + _certRootsData = [[PSCertData alloc] initWithCertificates:pscerts_roots.certs]; + + + // From the black and gray listed certs create an array of the keys. + NSMutableArray* gray_certs = [NSMutableArray array]; + certFlags = isGrayListed | hasFullCert; + flags = [NSNumber numberWithUnsignedLong:certFlags]; + PSCerts* pscerts_gray = [[PSCerts alloc] initWithCertFilePath:self.distrusted_directory withFlags:flags]; + [gray_certs addObjectsFromArray:pscerts_gray.certs]; + + _gray_listed_keys = [NSMutableArray array]; + for (PSCert* aCert in gray_certs) + { + [_gray_listed_keys addObject:aCert.public_key_hash]; + } + + NSMutableArray* black_certs = [NSMutableArray array]; + certFlags = isBlackListed | hasFullCert; + flags = [NSNumber numberWithUnsignedLong:certFlags]; + PSCerts* pscerts_black = [[PSCerts alloc] initWithCertFilePath:self.revoked_directory withFlags:flags]; + [black_certs addObjectsFromArray:pscerts_black.certs]; + + _blacked_listed_keys = [NSMutableArray array]; + for (PSCert* aCert in black_certs) + { + [_blacked_listed_keys addObject:aCert.public_key_hash]; + } + +/* + On iOS the intermediate certs are not used + certFlags = hasFullCert; + flags = [NSNumber numberWithUnsignedLong:certFlags]; + pscerts = [[PSCerts alloc] initWithCertFilePath:self.certs_directory withFlags:flags]; + [certs addObjectsFromArray:pscerts.certs]; +*/ + // now create the evroots.plist data + NSMutableDictionary* file_name_to_cert = [NSMutableDictionary dictionary]; + + for (PSCert* aCert in pscerts_roots.certs) + { + NSString* just_file_name = [aCert.file_path lastPathComponent]; + [file_name_to_cert setObject:aCert forKey:just_file_name]; + } + + if (![self buildEVRootsData:file_name_to_cert]) + { + NSLog(@"Unable to create the EVPlist data"); + } + + result = YES; + return result; +} + + +- (BOOL)outputPlistsToDirectory +{ + BOOL result = NO; + NSError* error = nil; + NSString* path_str = nil; + + if (nil != _EVRootsData) + { + if (![self ensureDirectoryPath:self.output_directory]) + { + NSLog(@"Error unable to ensure the output directory!"); + return result; + } + + NSData* evroots_data = [NSPropertyListSerialization dataWithPropertyList:_EVRootsData + format:NSPropertyListBinaryFormat_v1_0 /*NSPropertyListXMLFormat_v1_0*/ options:0 + error:&error]; + if (nil != error) + { + NSLog(@"Error converting out the evroot data into data: error %@", error); + return result; + } + + path_str = [self.output_directory stringByAppendingPathComponent:@"EVRoots.plist"]; + if (![evroots_data writeToFile:path_str options:0 error:&error]) + { + NSLog(@"Error writing out the evroot.plist data: error %@", error); + return result; + } + } + + if (nil != _gray_listed_keys) + { + NSData* graylist_roots_data = [NSPropertyListSerialization dataWithPropertyList:_gray_listed_keys + format:NSPropertyListBinaryFormat_v1_0 /*NSPropertyListXMLFormat_v1_0*/ options:0 + error:&error]; + if (nil != error) + { + NSLog(@"Error converting out the gray listed keys into data: error %@", error); + return result; + } + + path_str = [self.output_directory stringByAppendingPathComponent:@"GrayListedKeys.plist"]; + if (![graylist_roots_data writeToFile:path_str options:0 error:&error]) + { + NSLog(@"Error writing out the GrayListedKeys.plist data: error %@", error); + return result; + } + + } + + if (nil != _blacked_listed_keys) + { + NSData* blacklist_roots_data = [NSPropertyListSerialization dataWithPropertyList:_blacked_listed_keys + format:NSPropertyListBinaryFormat_v1_0 /*NSPropertyListXMLFormat_v1_0*/ options:0 + error:&error]; + if (nil != error) + { + NSLog(@"Error converting out the blacked listed keys into data: error %@", error); + return result; + } + + path_str = [self.output_directory stringByAppendingPathComponent:@"Blocked.plist"]; + if (![blacklist_roots_data writeToFile:path_str options:0 error:&error]) + { + NSLog(@"Error writing out the BlackListKeys.plist data: error %@", error); + return result; + } + } + + NSData* index_data = _certRootsData.cert_index_data; + path_str = [self.output_directory stringByAppendingPathComponent:@"certsIndex.data"]; + if (nil != index_data) + { + if (![index_data writeToFile:path_str options:0 error:&error]) + { + NSLog(@"Error writing out the certsIndex data: error %@", error); + return result; + } + } + + NSData* cert_table_data = _certRootsData.cert_table; + path_str = [self.output_directory stringByAppendingPathComponent:@"certsTable.data"]; + if (nil != cert_table_data) + { + if (![cert_table_data writeToFile:path_str options:0 error:&error]) + { + NSLog(@"Error writing out the certsTable data: error %@", error); + return result; + } + } + + path_str = [self.output_directory stringByAppendingPathComponent:@"AssetVersion.plist"]; + + NSFileManager* fileManager = [NSFileManager defaultManager]; + // check to see if the file exists; + if ([fileManager fileExistsAtPath:path_str]) + { + if (![fileManager removeItemAtPath:path_str error:&error]) + { + NSLog(@"Unable to remove the older version of the AssetVersion.plist file!"); + return result; + } + } + + if (![[NSFileManager defaultManager] copyItemAtPath:self.version_number_plist_path toPath:path_str error:&error]) + { + NSLog(@"Error copying over the AssetVersion.plist file: error %@", error); + return result; + } + + // Create a Dictionary to hold the escrow certificates and write that to disk + int numProductionRoots = kNumberOfBaseLineEscrowRoots; + NSData* productionCerts[numProductionRoots]; + struct RootRecord* pRootRecord = NULL; + + int iCnt; + for (iCnt = 0; iCnt < numProductionRoots; iCnt++) + { + pRootRecord = kBaseLineEscrowRoots[iCnt]; + if (NULL != pRootRecord && pRootRecord->_length > 0 && NULL != pRootRecord->_bytes) + { + productionCerts[iCnt] = [NSData dataWithBytes:pRootRecord->_bytes length:pRootRecord->_length] ; + } + } + NSArray* productionCertArray = [NSArray arrayWithObjects:productionCerts count:numProductionRoots]; + + NSArray* valueArray = [NSArray arrayWithObjects:productionCertArray, nil]; + NSArray* keyArray = [NSArray arrayWithObjects:(__bridge NSString *)kSecCertificateProductionEscrowKey, nil]; + NSDictionary* escrowCertificates = [NSDictionary dictionaryWithObjects:valueArray forKeys:keyArray]; + + + int numProductionPCSRoots = kNumberOfBaseLinePCSEscrowRoots; + NSData* productionPCSCerts[numProductionPCSRoots]; + struct RootRecord* pPCSRootRecord = NULL; + + for (iCnt = 0; iCnt < numProductionPCSRoots; iCnt++) + { + pPCSRootRecord = kBaseLinePCSEscrowRoots[iCnt]; + if (NULL != pPCSRootRecord && pPCSRootRecord->_length > 0 && NULL != pPCSRootRecord->_bytes) + { + productionPCSCerts[iCnt] = [NSData dataWithBytes:pPCSRootRecord->_bytes length:pPCSRootRecord->_length] ; + } + } + NSArray* productionPCSCertArray = [NSArray arrayWithObjects:productionPCSCerts count:numProductionPCSRoots]; + + + NSArray* valuePCSArray = [NSArray arrayWithObjects:productionPCSCertArray, nil]; + NSArray* keyPCSArray = [NSArray arrayWithObjects:(__bridge NSString *)kSecCertificateProductionPCSEscrowKey, nil]; + NSDictionary* escrowPCSCertificates = [NSDictionary dictionaryWithObjects:valuePCSArray forKeys:keyPCSArray]; + + NSMutableDictionary *mergedEscrowCertificates = [NSMutableDictionary dictionaryWithDictionary:escrowCertificates]; + [mergedEscrowCertificates addEntriesFromDictionary:escrowPCSCertificates]; + + NSData* escrowCertPList = [NSPropertyListSerialization dataWithPropertyList:mergedEscrowCertificates + format:NSPropertyListBinaryFormat_v1_0 + options:0 + error:&error]; + if (nil != error) + { + NSLog(@"Error creating the Escrow certificate Plist: error %@", error); + return result; + } + + NSString* outputEscrowFileName = [NSString stringWithFormat:@"%@.plist", (__bridge NSString *)kSecCertificateEscrowFileName]; + path_str = [self.output_directory stringByAppendingPathComponent:outputEscrowFileName]; + if (![escrowCertPList writeToFile:path_str options:0 error:&error]) + { + NSLog(@"Error writing out the escrow certificate data: error %@", error); + return result; + } + + return YES; +} + +- (BOOL)createManifest +{ + BOOL result = NO; + + if (nil == self.version_number_plist_path) + { + return result; + } + + + unsigned char hash_buffer[CC_SHA256_DIGEST_LENGTH]; + + NSString* evroots_str = @"EVRoots.plist"; + NSString* blocked_str = @"Blocked.plist"; + NSString* graylistedkeys_str = @"GrayListedKeys.plist"; + NSString* certsIndex_str = @"certsIndex.data"; + NSString* certsTable_str = @"certsTable.data"; + NSString* assetVersion_str = @"AssetVersion.plist"; + NSString* escrowCertificate_str = [NSString stringWithFormat:@"%@.plist", (__bridge NSString *)kSecCertificateEscrowFileName]; + NSError* error = nil; + + NSInputStream* input_stream = [NSInputStream inputStreamWithFileAtPath:self.version_number_plist_path]; + [input_stream open]; + NSDictionary* version_number_dict = [NSPropertyListSerialization propertyListWithStream:input_stream options:0 format:nil error:&error]; + if (nil != error) + { + [input_stream close]; + NSLog(@"Error getting the version number info %@", error); + return result; + } + [input_stream close]; + NSNumber* version_number = [version_number_dict objectForKey:@"VersionNumber"]; + + + NSArray* file_list = [NSArray arrayWithObjects:evroots_str, blocked_str, graylistedkeys_str, certsIndex_str, certsTable_str, assetVersion_str, escrowCertificate_str, nil]; + NSMutableDictionary* manifest_dict = [NSMutableDictionary dictionary]; + + for (NSString* file_path in file_list) + { + NSString* full_path = [self.output_directory stringByAppendingPathComponent:file_path]; + NSData* hash_data = [NSData dataWithContentsOfFile:full_path options:0 error:&error]; + if (nil != error) + { + NSLog(@"Error getting the data for file %@", file_path); + return result; + } + memset(hash_buffer, 0, CC_SHA256_DIGEST_LENGTH); + CC_SHA256([hash_data bytes], (CC_LONG)[hash_data length] , hash_buffer); + NSData* hash_value = [NSData dataWithBytes:hash_buffer length:CC_SHA256_DIGEST_LENGTH]; + [manifest_dict setObject:hash_value forKey:file_path]; + } + + // Add the version number to the manifest dictionary + if (nil != version_number) + { + [manifest_dict setObject:version_number forKey:@"VersionNumber"]; + } + + NSData* manifest_property_list = [NSPropertyListSerialization dataWithPropertyList:manifest_dict format:NSPropertyListBinaryFormat_v1_0 options:0 error:&error]; + if (nil != error) + { + NSLog(@"Error converting the manifest_dict into a propertylist data object"); + return result; + } + + + NSString* path_str = [self.output_directory stringByAppendingPathComponent:@"manifest.data"]; + if (![manifest_property_list writeToFile:path_str options:0 error:&error]) + { + NSLog(@"Error writing out the manifest data: error %@", error); + return result; + } + result = YES; + + + return result; +} + + +@end diff --git a/certificates/CertificateTool/CertificateTool/DataConversion.h b/certificates/CertificateTool/CertificateTool/DataConversion.h new file mode 100644 index 00000000..a8d31ec9 --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/DataConversion.h @@ -0,0 +1,53 @@ +// +// DataConversion.h +// FIPSCAVS +// +// Created by James Murphy on 04/26/13. +// Copyright 2013 Apple. All rights reserved. +// +// This is confidential and proprietary code of Apple Inc. It may not be +// used, copied or modified in any way without Apple's expressed +// written permission in each case. No redistribution of this +// Apple Confidential code is allowed. +// + +#import + +/*! ========================================================================= + @class NSData + + @abstract Extend the NSData object to convert to a hex string + ========================================================================= */ +@interface NSData (DataConversion) + +/*! ------------------------------------------------------------------------- + @method toHexString + + @result returns a NSString object with the hex characters that + represent the value of the NSData object. + ------------------------------------------------------------------------- */ +- (NSString *)toHexString; + +@end + + +/*! ========================================================================= + @class NSString + + @abstract Extend the NSString object to convert hex string into a + binary value in a NSData object. + ========================================================================= */ +@interface NSString (DataConversion) + +/*! ------------------------------------------------------------------------- + @method hextStringToData + + @result Convert a NSString that contains a set of hex characters + into a binary value. If the conversion cannot be done then + nil will be returned. + ------------------------------------------------------------------------- */ +- (NSData *)hexStringToData; + +@end + + diff --git a/certificates/CertificateTool/CertificateTool/DataConversion.m b/certificates/CertificateTool/CertificateTool/DataConversion.m new file mode 100644 index 00000000..da9670a5 --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/DataConversion.m @@ -0,0 +1,103 @@ +// +// DataConversion.m +// FIPSCAVS +// +// Created by James Murphy on 04/26/13. +// Copyright 2013 Apple. All rights reserved. +// +// This is confidential and proprietary code of Apple Inc. It may not be +// used, copied or modified in any way without Apple's expressed +// written permission in each case. No redistribution of this +// Apple Confidential code is allowed. +// + +#import "DataConversion.h" +#import + +/* ========================================================================== + Static data used to convert between binary and HEX data + ========================================================================== */ + +static char byteMap[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; +static int byteMapLen = sizeof(byteMap); + +/* ========================================================================== + Static functions to lookup the appropriate hex value from binary data ot + binary data from a hex value + ========================================================================== */ + +static uint8_t nibbleFromChar(char c) +{ + if(c >= '0' && c <= '9') return c - '0'; + if(c >= 'a' && c <= 'f') return c - 'a' + 10; + if(c >= 'A' && c <= 'F') return c - 'A' + 10; + return 255; +} + +static char nibbleToChar(uint8_t nibble) +{ + if(nibble < byteMapLen) return byteMap[nibble]; + return '*'; +} + +/* ========================================================================== + Extend the NSData class to convert a binary value into a hex string + ========================================================================== */ +@implementation NSData (DataConversion) + +- (NSString *)toHexString +{ + NSString* result = nil; + + unsigned char* data_bytes = (unsigned char*)[self bytes]; + int data_len = (int)[self length]; + int len = ((data_len * 2) + 1); + + unsigned char buffer[len]; + int iCnt; + for (iCnt = 0; iCnt < data_len; iCnt++) + { + buffer[iCnt * 2] = nibbleToChar(data_bytes[iCnt] >> 4); + buffer[iCnt * 2 + 1] = nibbleToChar(data_bytes[iCnt] & 0x0F); + } + + buffer[data_len * 2] = 0; + result = [NSString stringWithUTF8String:(const char *)buffer]; + return result; +} + +@end + +/* ========================================================================== + Extend the NSString class to convert a hex string into a binary value + ========================================================================== */ + +@implementation NSString (DataConversion) + +- (NSData *)hexStringToData +{ + NSData* result = nil; + + const char* utf8_str = [self UTF8String]; + int len = (int)(strlen(utf8_str) / 2); + uint8_t buffer[len]; + uint8_t* p = NULL; + + memset(buffer, 0, len); + int iCnt; + for (iCnt = 0, (p = (uint8_t*)utf8_str); iCnt < len; iCnt++) + { + buffer[iCnt] = (nibbleFromChar(*p) << 4) | nibbleFromChar(*(p+1)); + p += 2; + } + buffer[len] = 0; + result = [NSData dataWithBytes:buffer length:len]; + return result; +} + +@end + + + + + diff --git a/certificates/CertificateTool/CertificateTool/Info.plist b/certificates/CertificateTool/CertificateTool/Info.plist new file mode 100644 index 00000000..23d794fb --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/Info.plist @@ -0,0 +1,25 @@ + + + + + CFBundleShortVersionString + 1.0.0 + CFBundleIdentifier + com.apple.MobileAsset.PKITrustServices.PKITrustData + CFBundleName + PKI Trust Data + CFBundleInfoDictionaryVersion + 1.0 + CFBundleVersion + 1.0 + MobileAssetProperties + + FormatVersion + 1 + ContentVersion + 2014081900 + __AssetDefaultGarbageCollectionBehavior + NeverCollected + + + diff --git a/certificates/CertificateTool/CertificateTool/PSAssetConstants.c b/certificates/CertificateTool/CertificateTool/PSAssetConstants.c new file mode 100644 index 00000000..1b61e4c2 --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/PSAssetConstants.c @@ -0,0 +1,19 @@ +// +// PSAssetConstants.c +// CertificateTool +// +// Created by James Murphy on 1/10/13. +// Copyright (c) 2013 James Murphy. All rights reserved. +// + +#include "PSAssetConstants.h" + +const CFStringRef kPSAssertVersionNumberKey = CFSTR("VersionNumber"); +const CFStringRef kPSAssertCertificatesKey = CFSTR("Certificates"); +const CFStringRef kPSAssetCertDataKey = CFSTR("CertData"); +const CFStringRef kPSAssetCertHashKey = CFSTR("CertHash"); +const CFStringRef kPSAssetCertEVOIDSKey = CFSTR("CertEVOIDS"); +const CFStringRef kPSAssetCertFlagsKey = CFSTR("CertFlags"); +const CFStringRef kPAAssertAdditionalDataKey= CFSTR("CertAdditionalData"); + + diff --git a/certificates/CertificateTool/CertificateTool/PSAssetConstants.h b/certificates/CertificateTool/CertificateTool/PSAssetConstants.h new file mode 100644 index 00000000..9f4fe498 --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/PSAssetConstants.h @@ -0,0 +1,33 @@ +// +// PSAssetConstants.h +// CertificateTool +// +// Copyright (c) 2013 Apple. All rights reserved. +// + +#ifndef _PSAssetConstants_h +#define _PSAssetConstants_h + +#include + +enum +{ + isAnchor = (1UL << 0), + isBlackListed = (1UL << 1), + isGrayListed = (1UL << 2), + hasFullCert = (1UL << 3), + hasCertHash = (1UL << 4) +}; + +typedef unsigned long PSAssetFlags; + +extern const CFStringRef kPSAssertCertificatesKey; +extern const CFStringRef kPSAssertVersionNumberKey; +extern const CFStringRef kPSAssetCertDataKey; +extern const CFStringRef kPSAssetCertHashKey; +extern const CFStringRef kPSAssetCertEVOIDSKey; +extern const CFStringRef kPSAssetCertFlagsKey; +extern const CFStringRef kPSAssertAdditionalDataKey; + + +#endif diff --git a/certificates/CertificateTool/CertificateTool/PSCert.h b/certificates/CertificateTool/CertificateTool/PSCert.h new file mode 100644 index 00000000..2a9c596a --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/PSCert.h @@ -0,0 +1,30 @@ +// +// PSCert.h +// CertificateTool +// +// Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. +// + +#import + +@interface PSCert : NSObject +{ +@private + NSData* _cert_data; + NSNumber* _flags; + NSData* _normalized_subject_hash; + NSData* _certificate_hash; + NSData* _public_key_hash; + NSString* _file_path; +} + +@property (readonly) NSData* cert_data; +@property (readonly) NSData* normalized_subject_hash; +@property (readonly) NSData* certificate_hash; +@property (readonly) NSData* public_key_hash; +@property (readonly) NSString* file_path; +@property (readonly) NSNumber* flags; + +- (id)initWithCertFilePath:(NSString *)filePath withFlags:(NSNumber*)flags; + +@end diff --git a/certificates/CertificateTool/CertificateTool/PSCert.m b/certificates/CertificateTool/CertificateTool/PSCert.m new file mode 100644 index 00000000..6d119233 --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/PSCert.m @@ -0,0 +1,204 @@ +// +// PSCert.m +// CertificateTool +// +// Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. +// + +#import "PSCert.h" +#import "PSUtilities.h" +#import "PSAssetConstants.h" +//#import +#import +#import +#import + +#import "DataConversion.h" + +/* In OS X 10.9, the following symbols are exported: +_SecCertificateCopyIssuerSequence (SecCertificateRef) SecCertificatePriv.h +_SecCertificateCopySubjectSequence (SecCertificateRef) SecCertificatePriv.h +_SecCertificateGetNormalizedIssuerContent (SecCertificateRefP) SecCertificateInternal.h +_SecCertificateGetNormalizedSubjectContent (SecCertificateRefP) SecCertificateInternal.h +_SecCertificateCopyNormalizedIssuerContent (SecCertificateRef) SecCertificate.h +_SecCertificateCopyNormalizedSubjectContent (SecCertificateRef) SecCertificate.h + */ +// This is from the SecCertificatePriv.h file +CFDataRef SecCertificateCopyIssuerSequence(SecCertificateRef certificate); +CFDataRef SecCertificateCopySubjectSequence(SecCertificateRef certificate); + +// This is from the SecCertificateInternal.h file +typedef struct __SecCertificate *SecCertificateRefP; +SecCertificateRefP SecCertificateCreateWithDataP(CFAllocatorRef allocator, CFDataRef der_certificate); +CFDataRef SecCertificateGetNormalizedIssuerContent(SecCertificateRefP certificate); +CFDataRef SecCertificateGetNormalizedSubjectContent(SecCertificateRefP certificate); + + +@interface PSCert (PrivateMethods) + +- (NSData *)getNormalizedSubjectHash:(SecCertificateRef)cert_ref; +- (NSData *)getCertificateHash; +- (NSData *)getPublicKeyHash:(SecCertificateRef)cert_ref; +- (NSData *)createCertRecord; + +@end + +@implementation PSCert + +@synthesize cert_data = _cert_data; +@synthesize normalized_subject_hash = _normalized_subject_hash; +@synthesize certificate_hash = _certificate_hash; +@synthesize public_key_hash = _public_key_hash; +@synthesize file_path = _file_path; +@synthesize flags = _flags; + + +- (id)initWithCertFilePath:(NSString *)filePath withFlags:(NSNumber*)flags +{ + if ((self = [super init])) + { + _file_path = filePath; + _flags = flags; + _cert_data = [PSUtilities readFile:filePath]; + if (NULL == _cert_data) + { + NSLog(@"PSCert: Unable to read data for file %@", filePath); + return nil; + } + + PSAssetFlags assetFlags = [_flags unsignedLongValue]; + + + SecCertificateRef certRef = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)(_cert_data)); + if (NULL == certRef) + { + NSLog(@"Unable to create a SecCertificateRef from the cert data for file %@", filePath); + return nil; + } + + _certificate_hash = [self getCertificateHash]; + + if (isAnchor & assetFlags) + { + _normalized_subject_hash = [self getNormalizedSubjectHash:certRef]; + if (NULL == _normalized_subject_hash) + { + NSLog(@"PSCert: Unable to get the normalized subject hash for file %@", filePath); + return nil; + } + } + else + { + _normalized_subject_hash = nil; + } + + + if ( (isGrayListed & assetFlags) || (isBlackListed & assetFlags) ) + { + _public_key_hash = [self getPublicKeyHash:certRef]; + if (NULL == _public_key_hash) + { + NSLog(@"PSCert: Unable to get the public key hash for file %@", filePath); + return nil; + } + } + else + { + _public_key_hash = nil; + } + + if (NULL != certRef) + { + CFRelease(certRef); + } + } + return self; +} + +- (NSData *)getNormalizedSubjectHash:(SecCertificateRef)cert_ref +{ + NSData* result = nil; + + if (NULL == cert_ref) + { + return result; + } + SecCertificateRefP iosCertRef = NULL; + NSData* normalized_subject = NULL; + CFDataRef cert_data = SecCertificateCopyData(cert_ref); + if (NULL == cert_data) + { + NSLog(@"SecCertificateCopyData returned NULL"); + return result; + } + + iosCertRef = SecCertificateCreateWithDataP(NULL, cert_data); + CFRelease(cert_data); + + if (NULL != iosCertRef) + { + CFDataRef temp_data = SecCertificateGetNormalizedIssuerContent(iosCertRef); + + if (NULL == temp_data) + { + NSLog(@"SecCertificateGetNormalizedIssuerContent return NULL"); + CFRelease(iosCertRef); + return result; + } + normalized_subject = [NSData dataWithBytes:CFDataGetBytePtr(temp_data) length:CFDataGetLength(temp_data)]; + CFRelease(iosCertRef); + } + + if (NULL == normalized_subject) + { + + NSLog(@"SecCertificateGetNormalizedIssuerContent returned NULL"); + return result; + } + + unsigned char subject_digest[CCSHA1_OUTPUT_SIZE]; + memset(subject_digest, 0, CCSHA1_OUTPUT_SIZE); + const struct ccdigest_info* digest_info = ccsha1_di(); + + ccdigest(digest_info, (unsigned long)[normalized_subject length], [normalized_subject bytes], subject_digest); + + result = [NSData dataWithBytes:subject_digest length:CCSHA1_OUTPUT_SIZE]; + + return result; +} + +- (NSData *)getCertificateHash +{ + NSData* result = nil; + unsigned char certificate_digest[CCSHA1_OUTPUT_SIZE]; + const struct ccdigest_info* digest_info = ccsha1_di(); + + ccdigest(digest_info, (unsigned long)[_cert_data length], [_cert_data bytes], certificate_digest); + //(void)CC_SHA1([_cert_data bytes], (CC_LONG)[_cert_data length], certificate_digest); + + result = [NSData dataWithBytes:certificate_digest length:CCSHA1_OUTPUT_SIZE]; + return result; +} + +extern CFDataRef SecCertificateCopyPublicKeySHA1DigestFromCertificateData(CFAllocatorRef allocator, CFDataRef der_certificate); + +- (NSData *)getPublicKeyHash:(SecCertificateRef)cert_ref; +{ + NSData* result = nil; + + CFDataRef derBits = SecCertificateCopyData(cert_ref); + if (NULL == derBits) + { + return result; + } + + CFDataRef hashBits = SecCertificateCopyPublicKeySHA1DigestFromCertificateData(kCFAllocatorDefault, derBits); + CFRelease(derBits); + if (NULL != hashBits) + { + result = CFBridgingRelease(hashBits); + } + + return result; +} +@end diff --git a/certificates/CertificateTool/CertificateTool/PSCertData.h b/certificates/CertificateTool/CertificateTool/PSCertData.h new file mode 100644 index 00000000..8128d88c --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/PSCertData.h @@ -0,0 +1,25 @@ +// +// PSCertData.h +// CertificateTool +// +// Created by local on 1/24/13. +// Copyright (c) 2013 James Murphy. All rights reserved. +// + +#import + +@interface PSCertData : NSObject +{ +@private + NSArray* _certs; + NSData* _cert_index_data; + NSData* _cert_table; +} + +@property (readonly)NSData* cert_index_data; +@property (readonly)NSData* cert_table; + +- (id)initWithCertificates:(NSArray *)certs; + + +@end diff --git a/certificates/CertificateTool/CertificateTool/PSCertData.m b/certificates/CertificateTool/CertificateTool/PSCertData.m new file mode 100644 index 00000000..0e46da8c --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/PSCertData.m @@ -0,0 +1,144 @@ +// +// PSCertData.m +// CertificateTool +// +// Created by local on 1/24/13. +// Copyright (c) 2013 James Murphy. All rights reserved. +// + +#import "PSCertData.h" +#import "PSCert.h" + +@interface PSCertData (PrivateMethods) +- (BOOL)createIndexAndTableDataFromArray; +@end + + +@implementation PSCertData + +@synthesize cert_index_data = _cert_index_data; +@synthesize cert_table = _cert_table; + +- (id)initWithCertificates:(NSArray *)certs; +{ + + if ((self = [super init])) + { + _certs = certs; + _cert_index_data = nil; + _cert_table = nil; + + if (![self createIndexAndTableDataFromArray]) + { + NSLog(@"Unable to create the index and certificate data"); + self = nil; + } + } + return self; +} + +- (BOOL)createIndexAndTableDataFromArray +{ + BOOL result = NO; + + // Create a dictionary keyed by the normalized subject hash for the cert + NSMutableDictionary* records = [NSMutableDictionary dictionary]; + + for (PSCert* aCert in _certs) + { + // Get the hash + NSData* normalized_subject_hash = aCert.normalized_subject_hash; + if (nil == normalized_subject_hash) + { + NSLog(@"Could not get the normalized hash for the cert at %@", aCert.file_path); + continue; + } + + // See if there is already an entry with this value + NSMutableArray* items = [records objectForKey:normalized_subject_hash]; + if (nil == items) + { + // new item + items = [NSMutableArray array]; + } + [items addObject:aCert]; + + + [records setObject:items forKey:normalized_subject_hash]; + } + + // With all of the certificates in the dictionary get the array of keys and sort it + NSArray* keys = [records allKeys]; + + [keys sortedArrayUsingComparator: ^NSComparisonResult(id obj1, id obj2) + { + NSData* data1 = (NSData*)obj1; + NSData* data2 = (NSData *)obj2; + NSUInteger length1 = [data1 length]; + NSUInteger length2 = [data2 length]; + + + size_t compareLength = (size_t)((length1 <= length2) ? length1 : length2); + int memcmp_result = memcmp([data1 bytes], [data2 bytes], compareLength); + NSComparisonResult result = NSOrderedSame; + if (memcmp_result < 0) + { + result = NSOrderedAscending; + } + else if (memcmp_result > 0) + { + result = NSOrderedDescending; + } + return result; + }]; + + NSMutableData* indexData = [NSMutableData data]; + NSMutableData* tableData = [NSMutableData data]; + + UInt32 record_ofset = 0; + unsigned char paddingBuffer[7]; + memset(paddingBuffer, 0xFF, 7); + + for (NSData* keyData in keys) + { + // First write out the table data + NSArray* certs = [records objectForKey:keyData]; + NSMutableData* aRecord = nil; + + for (PSCert* aCert in certs) + { + //int32_t flags = (int32_t)[aCert.flags unsignedLongValue]; + int32_t record_length = (int32_t)(sizeof(int32_t) + sizeof(int32_t) + [aCert.cert_data length]); + int32_t aligned_record_length = ((record_length + 7) / 8) * 8; + int32_t padding = aligned_record_length - record_length; + int32_t cert_data_length = (int32_t)[aCert.cert_data length]; + + aRecord = [NSMutableData data]; + [aRecord appendBytes:&aligned_record_length length:sizeof(aligned_record_length)]; + [aRecord appendBytes:&cert_data_length length:sizeof(cert_data_length)]; + [aRecord appendData:aCert.cert_data]; + + if (padding > 0) + { + [aRecord appendBytes:paddingBuffer length:padding]; + } + + [tableData appendData:aRecord]; + + // Now update the index + [indexData appendData:keyData]; + [indexData appendBytes:&record_ofset length:sizeof(record_ofset)]; + + record_ofset += aligned_record_length; + } + } + + _cert_index_data = indexData; + _cert_table = tableData; + + result = YES; + + return result; +} + +@end diff --git a/certificates/CertificateTool/CertificateTool/PSCertKey.h b/certificates/CertificateTool/CertificateTool/PSCertKey.h new file mode 100644 index 00000000..97d9d566 --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/PSCertKey.h @@ -0,0 +1,21 @@ +// +// PSCertKey.h +// CertificateTool +// +// Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. +// + +#import + + +@interface PSCertKey : NSObject +{ +@private + NSString* _key_hash; +} + +@property (readonly) NSString* key_hash; + +- (id)initWithCertFilePath:(NSString *)filePath; + +@end diff --git a/certificates/CertificateTool/CertificateTool/PSCertKey.m b/certificates/CertificateTool/CertificateTool/PSCertKey.m new file mode 100644 index 00000000..ba162f67 --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/PSCertKey.m @@ -0,0 +1,45 @@ +// +// PSCertKey.m +// CertificateTool +// +// Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. +// + +#import "PSCertKey.h" +#import +#import "PSUtilities.h" + +@implementation PSCertKey + +@synthesize key_hash = _key_hash; + + +- (id)initWithCertFilePath:(NSString *)filePath +{ + if ((self = [super init])) + { + _key_hash = nil; + + CFDataRef temp_cf_data = CFBridgingRetain([PSUtilities readFile:filePath]); + if (NULL == temp_cf_data) + { + NSLog(@"PSCertKey: Unable to read data for file %@", filePath); + return nil; + } + + SecCertificateRef aCert = [PSUtilities getCertificateFromData:temp_cf_data]; + CFRelease(temp_cf_data); + if (NULL != aCert) + { + CFDataRef temp_key_data = [PSUtilities getKeyDataFromCertificate:aCert]; + if (NULL != temp_key_data) + { + _key_hash = [PSUtilities digestAndEncode:temp_key_data useSHA1:YES]; + } + CFRelease(aCert); + } + } + return self; +} + +@end diff --git a/certificates/CertificateTool/CertificateTool/PSCertRecord.h b/certificates/CertificateTool/CertificateTool/PSCertRecord.h new file mode 100644 index 00000000..351ed940 --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/PSCertRecord.h @@ -0,0 +1,20 @@ +// +// PSCertRecord.h +// CertificateTool +// +// Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. +// + +#import +#import + +@interface PSCertRecord : NSObject +{ +@private + NSData* _cert_record; +} +@property (readonly) NSData* cert_record; + +- (id)initWithCertData:(NSData *)cert_data withFlags:(NSNumber *)flags; + +@end \ No newline at end of file diff --git a/certificates/CertificateTool/CertificateTool/PSCertRecord.m b/certificates/CertificateTool/CertificateTool/PSCertRecord.m new file mode 100644 index 00000000..f9421004 --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/PSCertRecord.m @@ -0,0 +1,54 @@ +// +// PSCertRecord.m +// CertificateTool +// +// Created by James Murphy on 12/19/12. +// Copyright (c) 2012 James Murphy. All rights reserved. +// + +#import "PSCertRecord.h" + +@interface PSCertRecord (PrivateMethod) + +- (BOOL)ceateCertRecord:(NSData *)cert_data withFlags:(NSNumber *)flags + +@end + +@implementation PSCertRecord + + +- (id)initWithCertData:(NSData *)cert_data withFlags:(NSNumber *)flags +{ + if ((self = [super init])) + { + _cert_record = nil; + if (![self ceateCertRecord:cert_data withFlags:flags]) + { + NSLog(@"Could not create the certificate record"); + _cert_record = nil; + } + } + return self; +} + +- (BOOL)ceateCertRecord:(NSData *)cert_data withFlags:(NSNumber *)flags +{ + BOOL result = NO; + + if (nil == cert_data) + { + return result; + } + + UInt32 flag_value = 0; + if (nil != flags) + { + flag_value = (UInt32)[flags unsignedIntValue]; + } + + + + +} + +@end \ No newline at end of file diff --git a/certificates/CertificateTool/CertificateTool/PSCerts.h b/certificates/CertificateTool/CertificateTool/PSCerts.h new file mode 100644 index 00000000..cb7583db --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/PSCerts.h @@ -0,0 +1,22 @@ +// +// PSCerts.h +// CertificateTool +// +// Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. +// + +#import + +@interface PSCerts : NSObject +{ + NSString* _cert_dir_path; + NSMutableArray* _certs; + NSNumber* _flags; + +} + +@property (readonly) NSArray* certs; + +- (id)initWithCertFilePath:(NSString *)filePath withFlags:(NSNumber *)flags; + +@end diff --git a/certificates/CertificateTool/CertificateTool/PSCerts.m b/certificates/CertificateTool/CertificateTool/PSCerts.m new file mode 100644 index 00000000..e582ee94 --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/PSCerts.m @@ -0,0 +1,81 @@ +// +// PSCerts.m +// CertificateTool +// +// Created by James Murphy on 12/19/12. +// Copyright (c) 2012 James Murphy. All rights reserved. +// + +#import "PSCerts.h" +#import "PSCertKey.h" +#import "PSCert.h" + +@interface PSCerts (PrivateMethods) + +- (BOOL)get_certs; + +@end + +@implementation PSCerts + +@synthesize certs = _certs; + +- (BOOL)get_certs +{ + BOOL result = NO; + if (nil != _cert_dir_path) + { + + NSFileManager* fileManager = [NSFileManager defaultManager]; + BOOL isDir = NO; + if (![fileManager fileExistsAtPath:_cert_dir_path isDirectory:&isDir] || !isDir) + { + return result; + } + + NSDirectoryEnumerator* enumer = [fileManager enumeratorAtPath:_cert_dir_path]; + if (nil == enumer) + { + return result; + } + + for(NSString* cert_path_str in enumer) + { + if ([cert_path_str hasPrefix:@"."]) + { + continue; + } + + //NSLog(@"Processing file %@", cert_path_str); + + NSString* full_path = [_cert_dir_path stringByAppendingPathComponent:cert_path_str]; + + PSCert* aCert = [[PSCert alloc] initWithCertFilePath:full_path withFlags:_flags]; + if (nil != aCert) + { + [_certs addObject:aCert]; + } + } + result = YES; + } + return result; +} + +- (id)initWithCertFilePath:(NSString *)filePath withFlags:(NSNumber *)flags +{ + if (self = [super init]) + { + _cert_dir_path = filePath; + _flags = flags; + _certs = [NSMutableArray array]; + if (![self get_certs]) + { + NSLog(@"Could not get certificates for path %@", filePath); + self = nil; + } + + } + return self; +} + +@end diff --git a/certificates/CertificateTool/CertificateTool/PSUtilities.h b/certificates/CertificateTool/CertificateTool/PSUtilities.h new file mode 100644 index 00000000..44adf54a --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/PSUtilities.h @@ -0,0 +1,28 @@ +// +// PSUtilities.h +// CertificateTool +// +// Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. +// + +#import +#import +#import + +@interface PSUtilities : NSObject + ++ (NSString*)digestAndEncode:(CFDataRef)cfData useSHA1:(BOOL)useSHA1; + ++ (NSData *)readFile:(NSString *)file_path; + ++ (SecCertificateRef)getCertificateFromData:(CFDataRef)data; + ++ (CFDataRef)getKeyDataFromCertificate:(SecCertificateRef)cert; + ++ (NSString *)getCommonNameFromCertificate:(SecCertificateRef)cert; + ++ (SecKeyRef)getPrivateKeyWithName:(NSString *)keyName; + ++ (NSString *)signAndEncode:(CFDataRef)data usingKey:(SecKeyRef)key useSHA1:(BOOL)useSHA1; + +@end diff --git a/certificates/CertificateTool/CertificateTool/PSUtilities.m b/certificates/CertificateTool/CertificateTool/PSUtilities.m new file mode 100644 index 00000000..ba3136ac --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/PSUtilities.m @@ -0,0 +1,382 @@ +// +// PSUtilities.m +// CertificateTool +// +// Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. +// + +#import "PSUtilities.h" + +@implementation PSUtilities + ++ (void)outputError:(NSString *)message withError:(CFErrorRef)error +{ + NSString* output = nil; + if (nil != error) + { + CFStringRef aCFStr = CFErrorCopyDescription(error); + if (NULL != aCFStr) + { + output = [NSString stringWithFormat:@"%@ error: %@", message, aCFStr]; + CFRelease(aCFStr); + } + } + + if (nil == output) + { + output = message; + } + + NSLog(@"%@",output); + if (NULL != error) + { + CFRelease(error); + } +} + ++ (NSString *)digestAndEncode:(CFDataRef)cfData useSHA1:(BOOL)useSHA1; +{ + CFErrorRef cfError = NULL; + NSString* result = nil; + CFTypeRef digestType = kSecDigestSHA2; + CFIndex digestLength = 256; + + if (useSHA1) + { + digestType = kSecDigestSHA1; + digestLength = 0; + } + + SecTransformRef digestXForm = SecDigestTransformCreate(digestType, digestLength, &cfError); + if (NULL != cfError) + { + if (NULL != digestXForm) + { + CFRelease(digestXForm); + } + CFRelease(cfData); + [PSUtilities outputError:@"Could not create the digesting transform." withError:cfError]; + return result; + } + + if (!SecTransformSetAttribute(digestXForm, kSecTransformInputAttributeName, cfData, &cfError)) + { + CFRelease(cfData); + CFRelease(digestXForm); + [PSUtilities outputError:@"Could not set the input attribute" withError:cfError]; + return result; + } + + SecTransformRef base64Xform = SecEncodeTransformCreate(kSecBase64Encoding, &cfError); + + if (NULL != cfError) + { + + if (NULL != base64Xform) + { + CFRelease(base64Xform); + } + CFRelease(cfData); + CFRelease(digestXForm); + [PSUtilities outputError:@"Could not create the encoding transform." withError:cfError]; + return result; + } + + SecGroupTransformRef groupXForm = SecTransformCreateGroupTransform(); + if (NULL == groupXForm) + { + CFRelease(digestXForm); + CFRelease(base64Xform); + NSLog(@"Could not create the group transform"); + return result; + } + + SecTransformConnectTransforms(digestXForm, kSecTransformOutputAttributeName, + base64Xform, kSecTransformInputAttributeName, + groupXForm, &cfError); + CFRelease(digestXForm); + CFRelease(base64Xform); + + if (NULL != cfError) + { + if (NULL != groupXForm) + { + CFRelease(groupXForm); + } + [PSUtilities outputError:@"Could not connect the transforms" withError:cfError]; + return result; + } + + CFDataRef cfResult = (CFDataRef)SecTransformExecute(groupXForm, &cfError); + CFRelease(groupXForm); + if (NULL != cfError) + { + if (NULL != cfResult) + { + CFRelease(cfResult); + } + + [PSUtilities outputError:@"Could not execute the transform." withError:cfError]; + return result; + } + const void* pPtr = (const void*)CFDataGetBytePtr(cfResult); + NSUInteger len = (NSUInteger)CFDataGetLength(cfResult); + + NSData* temp_data = [[NSData alloc] initWithBytes:pPtr length:len]; + CFRelease(cfResult); + result = [[NSString alloc] initWithData:temp_data encoding:NSUTF8StringEncoding]; + + return result; + +} + ++ (NSData *)readFile:(NSString *)file_path +{ + NSData* result = NULL; + + NSError* error = nil; + + if (nil == file_path) + { + NSLog(@"PSUtilities.readFile called with a nil file path"); + return result; + + } + + NSFileManager* fileManager = [NSFileManager defaultManager]; + BOOL isDir = NO; + if (![fileManager fileExistsAtPath:file_path isDirectory:&isDir]) + { + NSLog(@"PSUtilities.readFile %@ does not exist", file_path); + return result; + } + + if (isDir) + { + NSLog(@"PSUtilities.readFile %@ does exist but it is a directory", file_path); + return result; + } + + + NSData* temp_data = [NSData dataWithContentsOfFile:file_path options:0 error:&error]; + if (nil != error) + { + NSLog(@"NSData dataWithContentsOfFile returned error %@", file_path); + return result; + } + + result = temp_data; + + return result; +} + ++ (SecCertificateRef)getCertificateFromData:(CFDataRef)data +{ + SecCertificateRef result = NULL; + SecExternalFormat inputFormat = kSecFormatUnknown; + SecExternalItemType itemType = kSecItemTypeUnknown; + SecItemImportExportFlags flags = 0; + CFArrayRef outItems = NULL; + + OSStatus err = SecItemImport(data, NULL, &inputFormat, &itemType, flags, + NULL, NULL, &outItems); + if (errSecSuccess != err) + { + NSLog(@"Could not import data"); + } + + if (NULL != outItems) + { + CFIndex num_items = CFArrayGetCount(outItems); + if (num_items > 0) + { + CFTypeRef anItem = (CFTypeRef)CFArrayGetValueAtIndex(outItems, 0); + if (NULL != anItem && (CFGetTypeID(anItem) == SecCertificateGetTypeID())) + { + result = (SecCertificateRef)anItem; + } + } + + if (NULL != result) + { + CFRetain(result); + } + CFRelease(outItems); + } + return result; +} + ++ (CFDataRef)getKeyDataFromCertificate:(SecCertificateRef)cert +{ + CFDataRef result = NULL; + + if (NULL == cert) + { + return result; + } + + SecKeyRef aPublicKey = NULL; + OSStatus err = SecCertificateCopyPublicKey(cert, &aPublicKey); + if (errSecSuccess == err && NULL != aPublicKey) + { + err = SecItemExport(aPublicKey, kSecFormatBSAFE, 0, NULL, &result); + if (errSecSuccess != err) + { + result = NULL; + } + CFRelease(aPublicKey); + } + return result; +} + ++ (SecKeyRef)getPrivateKeyWithName:(NSString *)keyName +{ + SecKeyRef result = NULL; + NSArray* key_array = [NSArray arrayWithObjects:kSecClass, kSecAttrLabel, kSecReturnRef, nil]; + NSArray* obj_array = [NSArray arrayWithObjects:kSecClassKey, keyName, kCFBooleanTrue, nil]; + NSDictionary* query = [NSDictionary dictionaryWithObjects:obj_array forKeys:key_array]; + + OSStatus err = SecItemCopyMatching((__bridge CFDictionaryRef)(query), (CFTypeRef *)&result); + if (errSecSuccess != err) + { + NSLog(@"Unable to find the Private Key"); + } + return result; +} + ++ (NSString *)signAndEncode:(CFDataRef)data usingKey:(SecKeyRef)key useSHA1:(BOOL)useSHA1 +{ + NSString* result = nil; + if (NULL == data || NULL == key) + { + return result; + } + + CFTypeRef digestType = kSecDigestHMACSHA2; + CFIndex digestLength = 256; + + if (useSHA1) + { + digestType = kSecDigestSHA1; + digestLength = 0; + } + + CFErrorRef error = NULL; + SecTransformRef signXForm = SecSignTransformCreate(key, &error); + if (NULL != error) + { + if (NULL != signXForm) + { + CFRelease(signXForm); + } + [PSUtilities outputError:@"Unable to create the signing transform" withError:error]; + return result; + } + + if (!SecTransformSetAttribute(signXForm, kSecTransformInputAttributeName, data, &error)) + { + CFRelease(signXForm); + [PSUtilities outputError:@"Could not set the input attribute" withError:error]; + return result; + } + + if (!SecTransformSetAttribute(signXForm, kSecDigestTypeAttribute, digestType, &error)) + { + CFRelease(signXForm); + [PSUtilities outputError:@"Unable to set the digest type attribute" withError:error]; + return result; + } + + CFNumberRef digest_length_number = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &digestLength); + if (!SecTransformSetAttribute(signXForm, kSecDigestLengthAttribute, digest_length_number, &error)) + { + CFRelease(signXForm); + CFRelease(digest_length_number); + [PSUtilities outputError:@"Unable to set the digest length attribute" withError:error]; + return result; + } + CFRelease(digest_length_number); + + if (!SecTransformSetAttribute(signXForm, kSecInputIsAttributeName, kSecInputIsPlainText, &error)) + { + CFRelease(signXForm); + [PSUtilities outputError:@"Unable to set the is plain text attribute" withError:error]; + return result; + } + + SecTransformRef base64Xform = SecEncodeTransformCreate(kSecBase64Encoding, &error); + if (NULL != error) + { + if (NULL != base64Xform) + { + CFRelease(base64Xform); + } + CFRelease(signXForm); + [PSUtilities outputError:@"Could not create the encoding transform." withError:error]; + return result; + } + + SecGroupTransformRef groupXForm = SecTransformCreateGroupTransform(); + if (NULL == groupXForm) + { + CFRelease(signXForm); + CFRelease(base64Xform); + NSLog(@"Could not create the group transform"); + return result; + } + + SecTransformConnectTransforms(signXForm, kSecTransformOutputAttributeName, + base64Xform, kSecTransformInputAttributeName, + groupXForm, &error); + CFRelease(signXForm); + CFRelease(base64Xform); + if (NULL != error) + { + CFRelease(groupXForm); + [PSUtilities outputError:@"Could connect the signing and encoding transforms." withError:error]; + return result; + } + + CFDataRef cfResult = (CFDataRef)SecTransformExecute(groupXForm, &error); + CFRelease(groupXForm); + if (NULL != error) + { + if (NULL != cfResult) + { + CFRelease( cfResult); + } + [PSUtilities outputError:@"Could not execute the transform." withError:error]; + return result; + } + const void* pPtr = (const void*)CFDataGetBytePtr(cfResult); + NSUInteger len = (NSUInteger)CFDataGetLength(cfResult); + + NSData* temp_data = [[NSData alloc] initWithBytes:pPtr length:len]; + CFRelease(cfResult); + result = [[NSString alloc] initWithData:temp_data encoding:NSUTF8StringEncoding]; + return result; +} + ++ (NSString *)getCommonNameFromCertificate:(SecCertificateRef)cert +{ + NSString* result = nil; + + if (NULL == cert) + { + return result; + } + + CFStringRef commonName = NULL; + OSStatus err = SecCertificateCopyCommonName(cert, &commonName); + if (errSecSuccess != err) + { + return result; + } + + result = [NSString stringWithString:(__bridge NSString *)(commonName)]; + + + return result; +} + +@end diff --git a/certificates/CertificateTool/CertificateTool/ValidateAsset.c b/certificates/CertificateTool/CertificateTool/ValidateAsset.c new file mode 100644 index 00000000..f4bed1d8 --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/ValidateAsset.c @@ -0,0 +1,409 @@ +// +// ValidateAsset.c +// CertificateTool +// +// Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. +// + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static int ValidateFilesInDirectory(const char* dir_path, int num_files, const char * files[]) +{ + + int result = 0; // Assume all is well + DIR* dirp = NULL; + struct dirent* dp = NULL; + + dirp = opendir(dir_path); + if (NULL == dirp) + { + return -1; + } + + for (int iCnt = 0; iCnt < num_files; iCnt++) + { + int name_length = (int)strlen(files[iCnt]); + int found = 0; + while (NULL != (dp = readdir(dirp))) + { + if (dp->d_namlen == name_length && 0 == strcmp(dp->d_name, files[iCnt])) + { + found = 1; + break; + } + } + if (0 == found) + { + (void)closedir(dirp); + + return -1; + } + rewinddir(dirp); + } + (void)closedir(dirp); + return result; +} + +static int ReadFileIntoCFDataRef(const char* file_path, CFDataRef* out_data) +{ + int result = -1; // guilt until proven + FILE* infile = NULL; + void* buffer = NULL; + int numbytes = 0; + + if (NULL == file_path || NULL == out_data) + { + return result; + } + + infile = fopen(file_path, "r"); + if (NULL == infile) + { + return result; + } + + fseek(infile, 0L, SEEK_END); + numbytes = (int)ftell(infile); + + fseek(infile, 0L, SEEK_SET); + buffer = calloc(numbytes, sizeof(char)); + if (NULL == buffer) + { + fclose(infile); + return result; + } + + fread(buffer, sizeof(char), numbytes, infile); + fclose(infile); + + *out_data = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)buffer, numbytes); + free(buffer); + result = (NULL != *out_data) ? 0 : -1; + return result; +} + +static int CreateHashForData(CFDataRef cfData, int useSHA1, CFDataRef* out_hash) +{ + int result = -1; // Guilty until proven + CCDigestAlgorithm algo = (useSHA1) ? kCCDigestSHA1 :kCCDigestSHA256; + size_t digest_length = (useSHA1) ? CC_SHA1_DIGEST_LENGTH : CC_SHA256_DIGEST_LENGTH; + UInt8 buffer[digest_length]; + + if (NULL == cfData || NULL == out_hash) + { + return result; + } + + *out_hash = NULL; + + memset(buffer, 0, digest_length); + + if (!CCDigest(algo, CFDataGetBytePtr(cfData), CFDataGetLength(cfData), buffer)) + { + *out_hash = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)buffer, digest_length); + } + else + { + return result; + } + + result = (NULL == *out_hash) ? -1 : 0; + return result; +} + +static int Base64Data(CFDataRef cfData, int for_encoding, CFDataRef* encoded_data) +{ + int result = -1; // Guilty until proven + CNEncodings encoding = kCNEncodingBase64; + CNStatus status = kCCSuccess; + CNEncodingDirection direction = (for_encoding) ? kCNEncode : kCNDecode; + unsigned char buffer[1024]; + size_t encoded_data_length = 1024; + + if (NULL == cfData || NULL == encoded_data) + { + return result; + } + memset(buffer, 0, 1024); + *encoded_data = NULL; + + status = CNEncode(encoding, direction, CFDataGetBytePtr(cfData), CFDataGetLength(cfData), buffer, &encoded_data_length); + if (kCCSuccess == status) + { + *encoded_data = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)buffer, encoded_data_length); + result = (NULL == *encoded_data) ? -1 : 0; + } + return result; +} + +static int CreatePropertyListFromData(CFDataRef prop_data, CFTypeID output_type, CFTypeRef* plistRef) +{ + int result = -1; // Guilt until proven + CFPropertyListRef aPlistRef = NULL; + CFPropertyListFormat list_format = kCFPropertyListXMLFormat_v1_0; + CFErrorRef error = NULL; + + if (NULL == prop_data || NULL == plistRef) + { + return result; + } + + *plistRef = NULL; + + aPlistRef = CFPropertyListCreateWithData(kCFAllocatorDefault, prop_data, 0, &list_format, &error); + if (NULL != error || NULL == aPlistRef) + { + if (NULL != aPlistRef) + { + CFRelease(aPlistRef); + } + + if (NULL != error) + { + CFRelease(error); + } + return result; + } + + if (CFGetTypeID(aPlistRef) != output_type) + { + CFRelease(aPlistRef); + return result; + } + + *plistRef = aPlistRef; + result = (NULL == *plistRef) ? -1 : 0; + return result; +} + + + +int ValidateAsset(const char* asset_dir_path, unsigned long current_version) +{ + const char* files[] = + { + "AssertVersion.plist", + "Blocked.plist", + "EVRoots.plist", + "certsIndex.data", + "certsTable.data", + "manifest.data" + }; + int num_files = (sizeof(files) / sizeof(const char*)); + int iCnt = 0; + const char* file_name = NULL; + char wd_buf[1024]; + + const char* current_working_directory_path = getcwd(wd_buf, 1024); + CFDataRef file_data = NULL; + CFDataRef hash_data = NULL; + CFDataRef manifest_hash_data = NULL; + CFStringRef key_name = NULL; + CFDictionaryRef manifest_dict = NULL; + CFNumberRef manifest_version = NULL; + unsigned long manifest_verson_number; + int iResult = -1; + OSStatus err = errSecSuccess; + CMSDecoderRef cmsDecoder = NULL; + size_t numSigners = 0; + SecPolicyRef x509Policy = NULL; + CMSSignerStatus signedStatus = kCMSSignerUnsigned; + OSStatus resultCode = errSecSuccess; + CFDataRef cmsMsg = NULL; + + // parameter check + if (NULL == asset_dir_path) + { + return iResult; + } + + if (ValidateFilesInDirectory(asset_dir_path, num_files, files)) + { + return iResult; + } + + if (chdir(asset_dir_path)) + { + return iResult; + } + + if (ReadFileIntoCFDataRef("manifest.data", &file_data)) + { + (void)chdir(current_working_directory_path); + return iResult; + } + + if (NULL == file_data) + { + return iResult; + } + + err = CMSDecoderCreate(&cmsDecoder); + if (errSecSuccess != err) + { + CFRelease(file_data); + (void)chdir(current_working_directory_path); + return iResult; + } + + err = CMSDecoderUpdateMessage(cmsDecoder, CFDataGetBytePtr(file_data), CFDataGetLength(file_data)); + CFRelease(file_data); + if (errSecSuccess != err) + { + CFRelease(cmsDecoder); + (void)chdir(current_working_directory_path); + return iResult; + } + + err = CMSDecoderFinalizeMessage(cmsDecoder); + if (errSecSuccess != err) + { + CFRelease(cmsDecoder); + (void)chdir(current_working_directory_path); + return iResult; + } + + err = CMSDecoderGetNumSigners(cmsDecoder, &numSigners); + if (errSecSuccess != err || 0 == numSigners) + { + CFRelease(cmsDecoder); + (void)chdir(current_working_directory_path); + return iResult; + } + + x509Policy = SecPolicyCreateBasicX509(); + if (NULL == x509Policy) + { + CFRelease(cmsDecoder); + (void)chdir(current_working_directory_path); + return iResult; + } + + err = CMSDecoderCopySignerStatus(cmsDecoder, 0, x509Policy, true, &signedStatus, NULL, &resultCode); + CFRelease(x509Policy); + if (errSecSuccess != err || kCMSSignerValid != signedStatus || errSecSuccess != resultCode) + { + CFRelease(cmsDecoder); + (void)chdir(current_working_directory_path); + return iResult; + } + + err = CMSDecoderCopyContent(cmsDecoder, &cmsMsg); + CFRelease(cmsDecoder); + if (errSecSuccess != err) + { + (void)chdir(current_working_directory_path); + return iResult; + } + + if (CreatePropertyListFromData(cmsMsg, CFDictionaryGetTypeID(), (CFTypeRef *)&manifest_dict)) + { + if (NULL != manifest_dict) + { + CFRelease(manifest_dict); + } + CFRelease(cmsMsg); + (void)chdir(current_working_directory_path); + return iResult; + } + CFRelease(cmsMsg); + + // Validate the hash for the files in the manifest + for (iCnt = 0; iCnt < num_files; iCnt++) + { + file_name = files[iCnt]; + // bypass the manifest file for now + if (!strcmp("manifest.data", file_name)) + { + continue; + } + + if (ReadFileIntoCFDataRef(file_name, &file_data)) + { + CFRelease(manifest_dict); + (void)chdir(current_working_directory_path); + return iResult; + } + + if (CreateHashForData(file_data, 0, &hash_data)) + { + if (NULL != file_data) + { + CFRelease(file_data); + } + CFRelease(manifest_dict); + (void)chdir(current_working_directory_path); + return iResult; + } + CFRelease(file_data); + + key_name = CFStringCreateWithCString(kCFAllocatorDefault, file_name, kCFStringEncodingUTF8); + if (NULL == key_name) + { + CFRelease(manifest_dict); + (void)chdir(current_working_directory_path); + return iResult; + } + + manifest_hash_data = (CFDataRef)CFDictionaryGetValue(manifest_dict, key_name); + if (NULL == manifest_hash_data) + { + CFRelease(key_name); + CFRelease(hash_data); + CFRelease(manifest_dict); + (void)chdir(current_working_directory_path); + return iResult; + } + CFRelease(key_name); + + if (!CFEqual(hash_data, manifest_hash_data)) + { + CFRelease(hash_data); + CFRelease(manifest_dict); + (void)chdir(current_working_directory_path); + return iResult; + } + CFRelease(hash_data); + } + + + // Get the version + manifest_version = (CFNumberRef)CFDictionaryGetValue(manifest_dict, CFSTR("VersionNumber")); + if (NULL == manifest_version) + { + CFRelease(manifest_dict); + (void)chdir(current_working_directory_path); + return iResult; + } + + if (!CFNumberGetValue(manifest_version, kCFNumberLongType, &manifest_verson_number)) + { + CFRelease(manifest_version); + CFRelease(manifest_dict); + (void)chdir(current_working_directory_path); + return iResult; + } + + CFRelease(manifest_version); + if (manifest_verson_number < current_version) + { + CFRelease(manifest_dict); + (void)chdir(current_working_directory_path); + return iResult; + } + + iResult = 0; + return iResult; +} diff --git a/certificates/CertificateTool/CertificateTool/ValidateAsset.h b/certificates/CertificateTool/CertificateTool/ValidateAsset.h new file mode 100644 index 00000000..de5596a8 --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/ValidateAsset.h @@ -0,0 +1,14 @@ +// +// ValidateAsset.h +// CertificateTool +// +// Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. +// + +#ifndef CertificateTool_ValidateAsset_h +#define CertificateTool_ValidateAsset_h + +int ValidateAsset(const char* asset_dir_path, unsigned long current_version); + + +#endif diff --git a/certificates/CertificateTool/CertificateTool/main.m b/certificates/CertificateTool/CertificateTool/main.m new file mode 100644 index 00000000..4bedc0d1 --- /dev/null +++ b/certificates/CertificateTool/CertificateTool/main.m @@ -0,0 +1,78 @@ +// +// main.m +// CertificateTool +// +// Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. +// + +#import +#import "CertificateToolApp.h" +#import "ValidateAsset.h" + +/* + printf("%s usage:\n", [self.app_name UTF8String]); + printf(" [-h, --help] \tPrint out this help message\n"); + printf(" [-r, --roots_dir] \tThe full path to the directory with the certificate roots\n"); + printf(" [-k, --revoked_dir] \tThe full path to the directory with the revoked certificates\n"); + printf(" [-d, --distrusted_dir] \tThe full path to the directory with the distrusted certificates\n"); + printf(" [-c, --certs_dir] \tThe full path to the directory with the cert certificates\n"); + printf(" [-e, --ev_plist_path] \tThe full path to the EVRoots.plist file\n"); + printf(" [-t, --top_level_directory] \tThe full path to the top level security_certificates directory\n"); + printf(" [-o, --output_directory] \tThe full path to the directory to write out the results\n"); + printf("\n"); + */ + +int main(int argc, const char * argv[]) +{ + +/* ============================================================ + This section is only used to help debug this tool + Uncommenting out the HARDCODE line will allow for testing + this tool with having to run the BuildiOSAsset script + ============================================================ */ +//#define HARDCODE 1 + +#ifdef HARDCODE + + const char* myArgv[] = + { + "foo", + "--top_level_directory", + "/Volumes/Data/RestoreStuff/Branches/PR-14030167/security/certificates/CertificateTool/..", + "--output_directory", + "~/asset_out" + }; + + int myArgc = (sizeof(myArgv) / sizeof(const char*)); + + argc = myArgc; + argv = myArgv; +#endif // HARDCODE + + + @autoreleasepool + { + CertificateToolApp* app = [[CertificateToolApp alloc] init:argc withArguments:argv]; + if (![app processCertificates]) + { + NSLog(@"Could not process the certificate directories"); + return -1; + } + + if (![app outputPlistsToDirectory]) + { + NSLog(@"Could not output the plists"); + return -1; + } + + if (![app createManifest]) + { + NSLog(@"Could not create the manifest"); + return -1; + } + + + } + return 0; +} + diff --git a/certificates/EVRoots/evroot.config b/certificates/EVRoots/evroot.config new file mode 100755 index 00000000..1f5c2864 --- /dev/null +++ b/certificates/EVRoots/evroot.config @@ -0,0 +1,462 @@ +# ------------------------------------------------------------------------------ +# Extended Validation CA Policy OIDs +# Last updated: 19 Aug 2014, MKC/KCM +# +# Each uncommented non-empty line contains a mapping from a CA-defined EV OID +# to the certificate file(s) in ./roots which are authoritative for that OID. +# These lines are processed by the buildEVRoots script to generate the plist. +# + +# Actalis +# source: , +# confirmed by http://portal.actalis.it/cms/translations/en/actalis/Info/Solutions/Documents/ActalisCA_Audit_Statement.pdf +# +# (1.3.159.1.17.1) = 06062B811F011101 +# +# roots: Actalis Authentication Root CA.cer +# +1.3.159.1.17.1 "Actalis Authentication Root CA.cer" + + +# AffirmTrust +# source: +# confirmed by http://www.affirmtrust.com/images/AffirmTrust_CPS_v1.1_12-23-2010.pdf +# +# (1.3.6.1.4.1.34697.2.1) = +# +# roots: AffirmTrust-Commercial.der, AffirmTrust-Networking.der, AffirmTrust-Premium.der, AffirmTrust-Premium-ECC.der +# +1.3.6.1.4.1.34697.2.1 "AffirmTrust-Commercial.der" +1.3.6.1.4.1.34697.2.2 "AffirmTrust-Networking.der" +1.3.6.1.4.1.34697.2.3 "AffirmTrust-Premium.der" +1.3.6.1.4.1.34697.2.4 "AffirmTrust-Premium-ECC.der" + + +# Buypass (Norway) +# TestURL: https://valid.evident.ca23.ssl.buypass.no/ +# TestURL: https://valid.evident.ca13.ssl.buypass.no +# source: +# confirmed by https://cert.webtrust.org/ViewSeal?id=848 +# confirmed by http://www.buypass.no/Bedrift/Produkter+og+tjenester/SSL/SSL%20dokumentasjon +# +# (2.16.578.1.26.1.3.3) = 0608608442011A010303 +# +# root: Buypass Class 3 CA 1 Buypass AS-983163327 +# +# confirmed by email with John Arild Amdahl Johansen on Nov.12 2013 +# +2.16.578.1.26.1.3.3 "Buypass Class 3 Root CA.cer" "BuypassClass3CA1.cer" + + +# Certigna +# TestURL: http://www.certigna.fr/ca/ACcertigna.crt +# confirmed by +# 86F27C4BE875508EE8793C4BFC61791530729830 +# source +# +# (1.2.250.1.177.1.18.2.2) +# +# root: Certigna.cer +# +1.2.250.1.177.1.18.2.2 "Certigna.cer" + + +# Certum (Unizeto) (Poland) +# source: +# source: , +# +# ( 1 2 616 1 113527 2 5 1 1 ) = 060B2A84680186F67702050101 +# +# root: Certum Trusted Network CA +# root: Certum CA +# +1.2.616.1.113527.2.5.1.1 "Unizeto-CertumCA.cer" "Poland-Certum-CTNCA.der" "Certum Trusted Network CA 2.cer" + + +# China Internet Network Information Center (CNNIC) (China) +# source: +# +# ( 1 3 6 1 4 1 29836 1 10 ) = +# +# root: China Internet Network Information Center EV Certificates Root +# +1.3.6.1.4.1.29836.1.10 "CNNICEVRoot.der" + + +# Comodo +# source: +# confirmed by +# +# (1.3.6.1.4.1.6449.1.2.1.5.1) = 060C2B06010401B2310102010501 +# +# root: COMODO Certification Authority +# subordinate CA of: Add Trust External CA Root +# +1.3.6.1.4.1.6449.1.2.1.5.1 "COMODOCertificationAuthority.crt" "AddTrust External CA Root.crt" + + +# Cybertrust (aka Verizon Business) +# source: +# confirmed by +# +# (1.3.6.1.4.1.6334.1.100.1) = 060A2B06010401B13E016401 +# +# root: GTE Cybertrust Global Root +# root: Baltimore Cybertrust Root +# +1.3.6.1.4.1.6334.1.100.1 "BTCTRT.cer" "GTEGB18.cer" + + +# DigiCert +# source: +# confirmed by +# confirmed by +# +# (2.16.840.1.114412.2.1) = 06096086480186FD6C0201 // EV CA-1 +# (2.16.840.1.114412.1.3.0.2) = 060B6086480186FD6C01030002 // EV CA-2 +# +# root: DigiCert High Assurance EV Root CA +# previously a subordinate CA of: Entrust.net Secure Server Certification Authority +# +2.16.840.1.114412.1.3.0.2 "DigiCertHighAssuranceEVRootCA.crt" + +# A14B48D943EE0A0E40904F3CE0A4C09193515D3F +# F517A24F9A48C6C9F8A200269FDC0F482CAB3089 +# DF3C24F9BFD666761B268073FE06D1CC8D4F82A4 +# 7E04DE896A3E666D00E687D33FFAD93BE83D349E +# DDFB16CD4931C973A2037D3FC83A4D7D775D05E4 +# TestURL: https://assured-id-root-g2.digicert.com +# TestURL: https://assured-id-root-g3.digicert.com +# TestURL: https://global-root-g2.digicert.com +# TestURL: https://global-root-g3.digicert.com +# TestURL: https://trusted-root-g4.digicert.com +# confirmed by +2.16.840.1.114412.2.1 "DigiCertHighAssuranceEVRootCA.crt" "DigiCertAssuredIDRootG2.der" "DigiCertAssuredIDRootG3.der" "DigiCertGlobalRootG2.der" "DigiCertGlobalRootG3.der" "DigiCertTrustedRootG4.der" + + +# DigiNotar +# source: +# confirmed by +# +# (2.16.528.1.1001.1.1.1.12.6.1.1.1) = 060E6084100187690101010C06010101 +# +# root: DigiNotar Root CA +# +# removed per +# 2.16.528.1.1001.1.1.1.12.6.1.1.1 "DigiNotarRootCA2007.crt" + + +# D-Trust +# open .D-Trust root certificates +# +# 1.3.6.1.4.1.4788.2.202.1 +# +# root: D-TRUST_Root_Class_3_CA_2_EV_2009.cer +# +1.3.6.1.4.1.4788.2.202.1 "D-TRUST_Root_Class_3_CA_2_EV_2009.cer" + + +# E-Tugra +# source: +# Test URL: https://sslev.e-tugra.com.tr +# +2.16.792.3.0.4.1.1.4 "E-Tugra.der" + +# Entrust +# 503006091D97D4F5AE39F7CBE7927D7D652D3431 +# B31EB1B740E36C8402DADC37D44DF5D4674952F9 +# 8CF427FD790C3AD166068DE81E57EFBB932272D4 +# 20d80640df9b25f512253a11eaf7598aeb14b547 +# TestURL: https://2048test.entrust.net/ +# TestURL: https://validev.entrust.net/ +# TestURL: https://validg2.entrust.net/ +# TestURL: https://validec.entrust.net/ +# source: +# confirmed by +# +# (2.16.840.1.114028.10.1.2) = 060A6086480186FA6C0A0102 +# +# root: Entrust.net Secure Server Certification Authority +# root: Entrust Root Certification Authority +# +# confirmed by +2.16.840.1.114028.10.1.2 "EntrustEVRoot.crt" "EntrustRoot-G2.der" "EntrustRoot-EC1.der" "entrust2048.der" + + +# GeoTrust +# source: +# confirmed by +# G3 root added: +# +# (1.3.6.1.4.1.14370.1.6) = 06092B06010401F0220106 +# +# root: GeoTrust Primary Certification Authority +# subordinate CA of: Equifax Secure Certificate Authority +# +1.3.6.1.4.1.14370.1.6 "geotrust-primary-ca.crt" "Equifax_Secure_Certificate_Auth" "GeoTrust Primary Certification Authority - G3.cer" + + +# GlobalSign +# source: +# confirmed by +# +# (1.3.6.1.4.1.4146.1.1) = 06092B06010401A0320101 +# +# root: GlobalSign Root CA - R3 +# root: GlobalSign Root CA - R2 +# root: GlobalSign Root CA +# +1.3.6.1.4.1.4146.1.1 "GlobalSignRootCA-R2.cer" "globalSignRoot.cer" "GlobalSign-Root-R3.der" + + +# Go Daddy (aka Starfield Technologies) +# source: +# confirmed by +# +# (2.16.840.1.114413.1.7.23.3) = 060B6086480186FD6D01071703 +# (2.16.840.1.114414.1.7.23.3) = 060B6086480186FD6E01071703 +# +# root: Go Daddy Class 2 Certification Authority (for 114413) +# root: Starfield Class 2 Certificate Authority (for 114414) +# root: Starfield Root Certificate Authority - G2 (for 114414) +# root: Starfield Services Root Certificate Authority - G2 (for 114414) +# previously subordinate CA of: Valicert Class 2 Policy Validation Authority (both) +# +2.16.840.1.114413.1.7.23.3 "GD-Class2-root.crt" "GoDaddyRootCertificateAuthorityG2.der" +2.16.840.1.114414.1.7.23.3 "SF-Class2-root.crt" "StarfieldRootCertificateAuthorityG2.der" +2.16.840.1.114414.1.7.24.3 "StarfieldServicesRootCertificateAuthorityG2.der" + + +# Izenpe +# source: +# source: +# confirmed by +# +# (1.3.6.1.4.1.14777.6.1.1) = +# (1.3.6.1.4.1.14777.6.1.2) = +# +# root: Izenpe.com +# root: Izenpe.com/emailAddress=Info@izenpe.com +# +1.3.6.1.4.1.14777.6.1.1 "Izenpe-RAIZ2007.crt" "Izenpe-ca_raiz2003.crt" +1.3.6.1.4.1.14777.6.1.2 "Izenpe-RAIZ2007.crt" "Izenpe-ca_raiz2003.crt" + + +# KEYNECTIS (aka Certplus) +# source: +# confirmed by +# +# (1.3.6.1.4.1.22234.2.5.2.3.1) = +# +# root: Class 2 Primary CA +# +1.3.6.1.4.1.22234.2.5.2.3.1 "certplus_class2.der" + + +# Logius (aka Staat der Nederlanden) +# source: application for root trust store inclusion for Logius EV certificate +# confirmed by , +# +# +# +# (2.16.528.1.1003.1.2.7) = 060960841001876B010207 +# +# root: Staat der Nederlanden EV Root CA +# +2.16.528.1.1003.1.2.7 "Staat der Nederlanden EV Root CA.cer" + + +# Network Solutions +# source: +# confirmed by +# +# (1.3.6.1.4.1.782.1.2.1.8.1) = 060C2B06010401860E0102010801 +# +# root: Network Solutions Certificate Authority +# subordinate CA of: AddTrust External CA Root +# +1.3.6.1.4.1.782.1.2.1.8.1 "NetworkSolutionsEVRoot.crt" "AddTrust External CA Root.crt" + + +# QuoVadis +# source: +# confirmed by +# +# (1.3.6.1.4.1.8024.0.2.100.1.2) = 060C2B06010401BE580002640102 +# +# root: QuoVadis Root Certification Authority +# root: QuoVadis Root CA 2 +# +1.3.6.1.4.1.8024.0.2.100.1.2 "qvrca.crt" "qvrca2.crt" + + +# Secom (aka SECOM Trust Systems Co., Ltd.) +# TestURL: https://scrootca2test.secomtrust.net also consider: https://fmctest.secomtrust.net/ +# FEB8C432DCF9769ACEAE3DD8908FFD288665647D +# source: +# +# (1.2.392.200091.100.721.1) = 060A2A83088C9B1B64855101 +# +# root: Security Communication RootCA1 +# +1.2.392.200091.100.721.1 "SCRoot1ca.cer" "SECOM-EVRoot1ca.cer" "SECOM-RootCA2.cer" + + +# StartCom +# source: +# confirmed by , +# +# (1.3.6.1.4.1.23223.2) = +# (1.3.6.1.4.1.23223.1.1.1) = +# +# root: StartCom Certification Authority +# +1.3.6.1.4.1.23223.2 "startcom-sfsca.der" "startcomSHA2.der" "StartCom May 2013 G2.der" +1.3.6.1.4.1.23223.1.1.1 "startcom-sfsca.der" "startcomSHA2.der" "StartCom May 2013 G2.der" + + +# SwissCom +# source : SwissCom Root Certificates +# TestURL: https://test-quarz-ev-ca-2.pre.swissdigicert.ch/ +# confirmed by , +# +# +# previously, we had noted these additional OIDs for SwissCom: +# (2.16.756.1.83.20.1.1) = 06086085740153140101 +# (the 21.0 OID was listed on +# (2.16.756.1.83.21.0) = 060760857401531500 +# +# (2.16.756.1.83.2.2) = 060760857401530202 +# +# E7A19029D3D552DC0D0FC692D3EA880D152E1A6B +# +2.16.756.1.83.2.2 "Swisscom Root EV CA 2.cer" + + +# SwissSign +# source: +# repository: https://swisssign.com/english/gold/view-category.html +# +# (2.16.756.1.89.1.2.1.1) = ... +# +# root: SwissSign Gold CA - G2 +# +2.16.756.1.89.1.2.1.1 "SwissSign-Gold_G2.der" + + +# TrustCenter (DE) +# source: +# +# (1.2.276.0.44.1.1.1.4) = ... +# +# root: TC TrustCenter Universal CA III +# +1.2.276.0.44.1.1.1.4 "trustCenter-root-5.der" + + +# Trustwave (aka SecureTrust, formerly XRamp) +# source: +# +# (2.16.840.1.114404.1.1.2.4.1) = 060C6086480186FD640101020401 +# +# root: SecureTrust CA +# root: Secure Global CA +# root: XRamp Global CA +# subordinate CA of: Entrust.net Secure Server Certification Authority +# +2.16.840.1.114404.1.1.2.4.1 "Trustwave-STCA.der" "Trustwave-SGCA.der" "XGCA.crt" "EntrustRootCA1024.crt" + + +# Thawte +# source: +# G3 EV root added: +# +# (2.16.840.1.113733.1.7.48.1) = 060B6086480186F84501073001 +# +# root: thawte Primary Root CA +# subordinate CA of: Thawte Premium Server CA +# +2.16.840.1.113733.1.7.48.1 "thawte-primary-root-ca.crt" "serverpremium.crt" "Thawte_Premium_Server_CA.cer" "thawte Primary Root CA - G3.cer" + + +# T-TeleSec +# source: T-Systems / Telesec.de root certificates +# +# (1.3.6.1.4.1.7879.13.24.1) +# +# root: T-TeleSec GlobalRoot Class 2 T-TeleSec GlobalRoot Class 3 +# +1.3.6.1.4.1.7879.13.24.1 "T-TeleSec GlobalRoot Class 2.cer" "T-TeleSec GlobalRoot Class 3.cer" + + +# VeriSign +# source: +# +# (2.16.840.1.113733.1.7.23.6) = 060B6086480186F84501071706 +# +# root: VeriSign Class 3 Public Primary Certification Authority - G5 +# subordinate CA of: Class 3 Public Primary Certification Authority +# +# Symantec +# source: Symantec ECC root certificates May 2013 +# +# VeriSign +# source: Symantec ECC root certificates May 2013 +# EV OID correction: EV-enablement for Verisign root certificate already in the keychain +# +2.16.840.1.113733.1.7.23.6 "VeriSignC3PublicPrimaryCA-G5.cer" "PCA3ss_v4.509" "Symantec Class 3 Public Primary Certification Authority - G4.cer" "VeriSign Class 3 Public Primary Certification Authority - G4.cer" "VeriSign Universal Root Certification Authority.cer" + + +# Wells Fargo +# source: +# confirmed by +# +# (2.16.840.1.114171.500.9) = 060A6086480186FB7B837409 +# +# root: WellsSecure Public Root Certificate Authority +# +2.16.840.1.114171.500.9 "WellsSecurePRCA.der" + + +# Camerfirma +# TestURL: https://server2.camerfirma.com:8082 +# TestURL: https://www.camerfirma.com/ +# confirmed by +# +# (1.3.6.1.4.1.17326.10.14.2.1.2) = 060D2B0601040181872E0A0E020102 +# (1.3.6.1.4.1.17326.10.8.12.1.2) = 060D2B0601040181872E0A080C0102 +# +# 786A74AC76AB147F9C6A3050BA9EA87EFE9ACE3C +# 6E3A55A4190C195C93843CC0DB722E313061F0B1 +# +1.3.6.1.4.1.17326.10.14.2.1.2 "ROOT-CHAMBERSIGN.crt" "ROOT-CHAMBERS.crt" "root_chambers-2008.der" +1.3.6.1.4.1.17326.10.8.12.1.2 "root_chambersign-2008.der" + + +# Firmaprofesional +# AEC5FB3FC8E1BFC4E54F03075A9AE800B7F7B6FA +# Firmaprofesional-CIF-A62634068.der +# TestURL: https://publifirma.firmaprofesional.com/ +# confirmed by +# +# (1.3.6.1.4.1.13177.10.1.3.10) = 060B2B06010401E6790A01030A +# +1.3.6.1.4.1.13177.10.1.3.10 "Firmaprofesional-CIF-A62634068.der" + + +# TWCA +# TestURL (4096): https://evssldemo3.twca.com.tw/index.html +# TestURL (2048): https://evssldemo.twca.com.tw/index.html +# confirmed with Robin Lin of TWCA on August 13 2013 +# +# (1.3.6.1.4.1.40869.1.1.22.3) = 060C2B0601040182BF2501011603 +# +# 9CBB4853F6A4F6D352A4E83252556013F5ADAF65 +# CF9E876DD3EBFC422697A3B5A37AA076A9062348 +# +1.3.6.1.4.1.40869.1.1.22.3 "TWCARootCA-4096.der" "twca-root-1.der" + + + +# ------------------------------------------------------------------------------ + diff --git a/certificates/assetData/Info.plist b/certificates/assetData/Info.plist new file mode 100644 index 00000000..5c578999 --- /dev/null +++ b/certificates/assetData/Info.plist @@ -0,0 +1,27 @@ + + + + + CFBundleShortVersionString + 1.0.0 + CFBundleIdentifier + com.apple.MobileAsset.PKITrustServices.PKITrustData + CFBundleName + PKI Trust Data + CFBundleInfoDictionaryVersion + 1.0 + CFBundleVersion + 1.0 + MobileAssetProperties + + FormatVersion + 1 + ContentVersion + 1 + __RequiredByOS + + __AssetDefaultGarbageCollectionBehavior + NeverCollected + + + diff --git a/certificates/certs/AppleDEVID.cer b/certificates/certs/AppleDEVID.cer new file mode 100644 index 0000000000000000000000000000000000000000..d3337393b5ba6a1cf74377a707350da14c3d5215 GIT binary patch literal 1032 zcmXqLVqr08VtTWHnTe5!i9@1l<%&bo6nPAI**LY@JlekVGBR?rG8iNoavN~6F^96S z2{VNT8wwi;f;e2lT#f|=IjIVsdC7W)Y6dDGL2hALh@f+7QAuW6W^!UlW`3T6V`)i7 zeo0 zbl-oSljF(%uo;@7&!^1YX}Xx}?3M!$A0>P_^+vP8H8V3IJHBhupLxp9tPUw{HuRU- z^=X?)q|>_%E18%jCbDeXT%l(y-{8vYn!lSbD!Sh4`3;Wi+eeHr^(@8)6k6|SjZgP01 zRV-S)X8EH_KJAewnV1K6f%kseUUfDfdeA7ldyFj2P| z2(WR1lX7wj8xtD~6EHQSCT?ImSiuyb8Jb!xmM3+SuU47Q+4Y1MDAFV_?vyg zB%_^I_FEqeu*`BPS@b4azToMqyWTl6%7wb|7mrTf_ilDqL2A=nvBy#Z;+?uH&i>`8 zi16gms5gGcP$j*kY|XZ7vD zgfB}yma`q&9rZ|F-p#e{$@H)40^1doit>wY9SbNuYOC5GyO`nSe6t=8%l^&QuO>9; zO`VnSrQ+NdKCWQ9MZf%S$gOLc+H15Y%(wGpg~Wq3vz&HSxkO3d%qT^yj_qTOn kM|4=VT-S5o^j^utZ?dN2cw%U$%SrWO_IFKB{k|3e0G_UPUH||9 literal 0 HcmV?d00001 diff --git a/certificates/certs/DODCA_13.cer b/certificates/certs/DODCA_13.cer new file mode 100644 index 0000000000000000000000000000000000000000..bcf3ec2b24f338928787250f6b1be1f0d154787e GIT binary patch literal 1080 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 DD_&|2 literal 0 HcmV?d00001 diff --git a/certificates/certs/DODCA_16.cer b/certificates/certs/DODCA_16.cer new file mode 100644 index 0000000000000000000000000000000000000000..15b3a27f1b5aea15b5cb122b15d2e3de59f416d8 GIT binary patch literal 1072 zcmXqLV$m^ZVisAz%*4pV#3*CH%f_kI=F#?@mywZ`mBAp|klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5#612aPtLo-tg1CuCmUPB`=*A&b(2&abSLIwg5%Q;>AU4ZuL8k!k2 z&PVnqBP#=QV=se2V<%H%Bg5@wE=g~C%2(*#vYp}ceCiCRxSLXsTffd#T9+r?(iG4> ze};zaYN?e|H^k&??wpXnrq1@MrmRTY&2*Vwe%3}8OQ$CjE*$&(H{^=x%Xw}WHVO8x z`}$XR#_Yi24tJKnI%^U-_U~zUko3U%|Dm5R&Od(mt=MsUY?1W zk%4h>6Jw)66JxCbAJFZx{EUqMSy+HE)Mg+L;w!TN97aW^< zjI*I&nt?1x0UwJPi%3BBxrm(yerG9jbDivWoHvIx>3OCB4@g>th1Gz$fsw(0AH)*| znGO^HQU(Sf0Rg8tU=%=Ta0LAQqsX*1p0F(}Zl(Qp{FfwSIxS+9b zL1TAYV@FO(B39kWd8)=KSoEqICFhp{rGQBd#ssTM&IbyD(kajaL`nrJNd}1r+b5?M zm1L%6CMTAp7NwTu1L@5CyqwJ966>VQyu_kPUN2`zmtt0ZT@%Q;1$xZPsnu^@H187}KyG zc6ARBer)r^lDqUsuHfW*5@$2bWAg5p@dWcro;2RJ-E|*Rv$jw65zY3P|BM%}{A*sC z*?vS~`r^4iHq;(AH)D)jC{i#%`Tmmjv(ukDR%h_GVQVNT&wvnZeDMmp>J047y!n3 BY;XVo literal 0 HcmV?d00001 diff --git a/certificates/certs/DODCA_17.cer b/certificates/certs/DODCA_17.cer new file mode 100644 index 0000000000000000000000000000000000000000..50e509eebda7e45c9b60e300acf3a6c319e9f3fb GIT binary patch literal 1072 zcmXqLV$m^ZVisAz%*4pV#3*OL%f_kI=F#?@mywZ`mBAp|klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5#612aPtLvsU5W1}c>UPB`=*9^=x2&abSLIwg5%Q;>AU4ZuL0xfHt zkL*uIRtDzAUIv54PNv32hRrTN6C5sbCapBmIK^n*cp~6to_OHyH#z2aY~|cGb;cc+ zmHH!O9g_U)@@D~!-zAJWrY}7%O;j=9im<#s^)cuFpBc>8HF`dt*t6uV@h7?2=D{-A z8*iOaJIVfn{lbn(^{roW6Mrx^{okZ$=C@pQyXEbPf=r*PtJzf^>U`x8p1D<+iJ6gs zad8u4qd^m6tpOj<4uqjd6veD294(oEEbq8FljT& zC@Cqh($`Ne%F#_e1>4nvMrW_A(fBt2&Zta}8 z>nkP+yGV7)Otkp^7qNTnI+}a6`_CD-^8!x<9tdtRjh?h1Ws{Bg)tseoJ{Cr&-+9h@ zzp7@{gqz`}kDmQxw7Yv|-JU#Mheivo{b5FGIp5F6Zk_%?m}fcT*?b`xV~Y(J+v98J zt~Je?Tb8)>MB9?El_^0h1(w{m+ZyJ`H_Nri;<07T`y$pv{~Kpo7u8qozoKjk06TVV ASpWb4 literal 0 HcmV?d00001 diff --git a/certificates/certs/DODCA_18.cer b/certificates/certs/DODCA_18.cer new file mode 100644 index 0000000000000000000000000000000000000000..71be2a2d5d8041012c427c0e7a4ef6f5bd4202bb GIT binary patch literal 1072 zcmXqLV$m^ZVisAz%*4pV#He7v%f_kI=F#?@mywZ`mBAp|klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5#612aPtLvuqjW1}c>UPB`=*9^=x2&abSLIwg5%Q;>AU4ZuL8d?}M z&PVnqBP#=QV=se2V<%H%Bg2ISwffHreYd}hTpdv8a3f}}Ag_n!{MG3KaWzLJmSuK` zpSt^g!o26Xri(7G_tx>^m;TCAp4;GA6wAIxe1dGVfHC*Jr7ov$oIUp5^6k!NrsWxS zlWPm-&RSRh{Vub?F0W6gQtDos{Wc0d<;kDEW9578oA!2X-kIUII*xSTbg}c=$;8aa zz__@HvC*K3vDSbO=yq9tM#ldvEWj9QGmr=Im05uC&>-SjvYRJvSJgkJkoVOKj!iwr z*-$XeKo+Eck420{#AxA3&ed`C;+0-nBJcht)huLuy3>FMB(1{2YQWsU$Y8(^;t7LH z2MPcw0|StN0*j`Bx&b#EXF{6?V=5CPH!CuS6Pd$h(0CK1MV_VcqCw+11B(S_3ryOK zGD=Dctn~Ghi*oeRQ;PLcGK&-Sax-)E(^E@;V)npPplW0QN(Vs7*%3$>88l8@(Ac-2 zvAeCYBPS&htM24HRpS&adR2{*^GktJz@!Faf>kBw0|i0p6leh=r2>^CgT#aFlT(XI zGSf1X6H8KyQp@szbY^~DPG)h5by8+tVo@b>8Uf}7<|am9ko|s>xAf-k#V-%%>CcgS zuRG(S$}QE^tjRm#t#?YFP`917R%P~coBm>(@0lzOJxuyfq+VaF5%R9%y}nEOsLzIs z4&!?%OP_X}Phk^cQAlOjbM)Ufzvvi^luk?2h0J|n@7lIWNA)k8>SQ2?2 z)w@>)cNZr1?d6U%5N7+c_086)YeV95o*iK=+o_st>QS=b=FF`(kFWW7)cBk`=YqEV z{=yBltv4Tx8yH;)x&fh3s;}Xuy-8w@_ z@cL`zvkAZc=04kYd>N_15;D`$9WT4f);=4z{*?9uxuqoiJ(m literal 0 HcmV?d00001 diff --git a/certificates/certs/DODCA_19.cer b/certificates/certs/DODCA_19.cer new file mode 100644 index 0000000000000000000000000000000000000000..e5795f7886267831681c5a23ad5a66cae499a89f GIT binary patch literal 1348 zcmXqLVs$WRV$oQ@%*4pV#HeAw%f_kI=F#?@mywZ`mBAp|klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5!p0}~@-BLh=&V}mGhUPBWQ*U%EoH3+AMKa-a zG%+e6dz6utfw_s1p8+V&#ni;e$Z(B$g7ayYb)0VxUvkrq`trf9>hTd}kNXpTbh`Vu zv4@KXFjt-b-fX!b%^}L=%8Iko4tQLi*E!KMVX5Ne%daPG{NnmYM&tVH9u2O?7V*A} zR&Lu)gv>KuKK1W(jfJLsGm>wA65Ms9$7K2Wv+Yio?Wg{~trqpcq+eXO;cUn%zbRXd zUi{mAU6AGEmlCJPAD&LQedS<5z=h+lG}6Vs?##R&xBjQ$7VDP#c3Z*|BaPFxB)zg{ z)Vn$TVQZB*_Ha4#@C&1#BCPM_4TQBO^=WM}x+9 zKr^8t225?nIE?cwE-pq$I+eoSsq) zSEZkvr)r#n#nGxp$@!%~DPUHFF~O>m^MQh(d<^s%A}0ftB!k3*?UNmyQ;SM6(=wA2 zOH!?qGV>CPDv`4duzUb!8%Bnu>ektbrA;_{y-i(V`%--8lSU(YnC2lUI() z@Gs|**;V*fEA3D3ib$I?hZAmDcJ2Gb(RgywI!UL@PSzF^7iHca7MZO_58K?7mU(t) zZua?ZE57Ms>LrU}{~p!2^?v`CZpo9Gv5zB`8NFMfGvNZ~elt0T&rB{qR=#_l?D$H5 z#@4QNv;IGI&C5W}yGE{8;(eSPPip)EHfu#a gb*!y%zOClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5!p0}~@-BSQmIWAi9+UPBWw*8t2l2&abSLIwg5%Q;>AU4ZuL8W|Wg zF)AT@l#!KzxrvdV0VvMJ)WpchaN;Dl_Tp6Q>dO=I#Vg*w&|~D;{o&SGP1p5v?;0;% zWcDvd;fL^NRp!-QVO^>(4wq_r=cRngkr%pn@8dSElmj~g7S^9&TGYVL{fObvWtmkI zrl;gAt@lZZExAxX?`*)KriKMJVZJKq~9^y z(tSCP(cj0`A65mdy11eu?f=15MIY8WXrI}*ImzMSltPcLhr4D3CM4N*bi}oIUgK$Y z(%zYD(R$?aKJLTKCVV#}Go9})KHJL7dHnJGiJ#tIZLz--E|c&3Kel(->iw$h%(cfi z+uuF2u50_n?VR-t=W1D8HayK~OJur~`m7`FXyK z<>;kk7ANZEX6ERpr4R%IGmd1|;jqiYF zLPZRi+Kh1+=UH4_nwk=lkJU^CxB-l9B2WYJlZy-B4l-!$fGc5YtI0`8ggH4qr5LVC zKRHj;I0cKNRgIGKOMz0rtO#R*RVC*G1wr{3=rcr41}aGgi3i&!J36Npm1L%6CMTAp zS|?@ZB^Fg8XB%Mo0L(Uw48}W@I^HX_S{`zGQ{fq6V*lY^+{=K&Ve=Vgx@H&sESKN4 z>9Lr8i|LjBTl$+qS9l#>=cUCFWYxMZxnbpn`8A$47J^6luAi3g&J^4}^V(_A|Mfxr zRt@uO;%=|~sXOz{(0e|TfmLOH~bg; zUcE@^twH(&J#mc{c2gU=WahT0O>bu|5>u}dOGA3Ime`CSA61}DSO literal 0 HcmV?d00001 diff --git a/certificates/certs/DODCA_25.der b/certificates/certs/DODCA_25.der new file mode 100644 index 0000000000000000000000000000000000000000..85ad96e4e06c968216b66f1522d2f11922b01b2e GIT binary patch literal 1421 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 I%-`Pu0IsvitN;K2 literal 0 HcmV?d00001 diff --git a/certificates/certs/DODCA_29.cer b/certificates/certs/DODCA_29.cer new file mode 100644 index 0000000000000000000000000000000000000000..f31173f56b617f92e42ffbc0daf8b89b64eba315 GIT binary patch literal 1360 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 literal 0 HcmV?d00001 diff --git a/certificates/certs/DODEMAILCA_14.cer b/certificates/certs/DODEMAILCA_14.cer new file mode 100644 index 0000000000000000000000000000000000000000..4a4a88e6b4d5c461e37332468021c56d0b07a106 GIT binary patch literal 1086 zcmXqLVzDx4Vpdwf%*4pV#K>pB%f_kI=F#?@mywZ`mBAp|klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5#6149E#LlXl71G6Y`UPB`w*8<8lh^2<*P$x4B^Sk)FD7gAMdinru z*9F?qI3L-!jI0dIjlB#8jh#%5jSS~b@7izr+rPv^&3oy^<4p-4H|%%fm%ep(vYthB zMBeM(8xo$`%g)B1)UBW9*B_C^#3S)efBr|CUXKZ}`cr=2zBet+^6QhSw_PHZLf%&| zI5zbdXG6g>16hy)J{B<+5%#s;kH31bqG%82tAjp05*$4YcjF9rK+-BKtOm>tj0^_+ zAf7PDbf5r`GB5xMD6nW6s2gyzaVE5RFs3pwa9^0={Ai29sdv-ZdBBc@k{=N?_N?qZSc!lNGl!#W=) z&Dp=GaO2W7P3;P9Yyp=_3TEZhF8--_BeuZ1`IqM9-VYa4ycF^~GXF-nFI^BNq{@?& z$!eO~YPv3BQRorYOD0{m4fcg$^LDC!5w&VREOU-?rNmR)hYphLB?lkwm~`lERrV<* Js~Iwk;Q({>X=(rf literal 0 HcmV?d00001 diff --git a/certificates/certs/DODEMAILCA_15.cer b/certificates/certs/DODEMAILCA_15.cer new file mode 100644 index 0000000000000000000000000000000000000000..dab427574e821cc3c2d6394f812ac0b1621bd1da GIT binary patch literal 1078 zcmXqLVlgskVwPIK%*4pV#3*gR%f_kI=F#?@mywZ`mBAp|klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5#612aPtLo;Iw6VoVhUPB`=*A&b(h^2<*P$x4B^Sk)FD7gAMdinru z*EKXXXq=DiTSis}=EhzIgT_v##zuy%nN#O4-S%X@&FA?HS7(W`|G8$l?&h^UVPyx@ z9$5D`uFOp9^3p!E)hj75?)vYlhR2R#vks?ye)y-QtET<$>D?!^mhHVJUK}bpeL}TM z%b)!jd0nMhEayBVFRwbZlR+*eq$A$?$?Oj&+(m=#Yacn4y5L|A^Lp=`=4;ztTBM3C z6=-H+W@KPo+{D;u(8O44zy}OIS$;;w|12!Pcxp3{2l16zfL?15@hsWR6Su4CA5+Nt z>IKK99^-5%m}VdgQozR|#v(FxYfr`MxnagOUpyAiiFms)rK@Y60S`!8g@x6Cxq*?v zfFHyY2AK{N08$19AOQsyO#^iUZZ^(@HV?*BCPr>nWDX}Xhs&VxCP<4sOXEd@#&ZT1 z3(OXnv>9cTloVL$>n9iG=%uF=>!oBCC+g*9=IE!VmH@@sTVqE~N+MR>$$6^ADOmKX8YSnK0;PZn4#otlO3nugf>JBc0z`TRDoF;3 z2iqs77L{bCWhN(+O5`*G%n{5@jEoFjKi9@A7vFQj zXXa9^`B}GhI$!N8{yBNuYL?5tQ!Xqzn$>#zgdD%NxaQyGQY$Q9+1D(Yyn1)-7KP-> zdPX;ut`#fe^o)E0+iv!MITU|q(xvD)0em?uTb!kUk z<6HOs72W@S&30|lc8dO?xHMGgn%I`lXR~Iv-B@F+D#9mfInm7Lz+H}wJ0i;Ls+*Ig z#BaKB&vpKI?rOTR;Ea$%6@ls@z1rrpIjwEI_Ooj(s}}ho^H}b$?2V-KnX4Z0pIO#+ zR;zY-)!ymCPu73`*jeya_OQC+HV)SUgU(0S7x7)oynFSC)75>OPH!tam_3svZr{ug HU)KNta2#`1 literal 0 HcmV?d00001 diff --git a/certificates/certs/DODEMAILCA_16.cer b/certificates/certs/DODEMAILCA_16.cer new file mode 100644 index 0000000000000000000000000000000000000000..e8e22808db3810e276b841450fa15623bd29f1c0 GIT binary patch literal 1078 zcmXqLVlgskVwPIK%*4pV#3*aP%f_kI=F#?@mywZ`mBAp|klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5#612aPtLvsTY1LG)hUPB`=*9^=xh^2<*P$x4B^Sk)FD7gAMdinru z*EKXVXq=DiTSis}=EhzIgT_v##zuz2Eqi1qSxcXIcHnf3t4DL?hwyh#z2AO_eqR4~ zNp#-Jo=l;6UVQRyCjW(8RgdhA789&v&Hb;8K;`N8N#O-XZ7nE@PMRMSXd318yFc3 z_(42jkm*1HAZ1_x5>Q~#G*CC-X5&m~^I%M6V&rB;=5Qi&xC|O^g0#r9G+s1lJZE6B zz-)m@n^8tdNr9EVesWQcUV2KgUP@+hqF!!hj(&P-2~f-)m=;ux3_z&?NI5$K2_u8X zi3=M07BqIZHFo5rBx2Q_oTqA>f<>>YQF4AMPzspfU`(*8ia#?UwnRfGIM@CqetTJgX-ng{rlEka=OT4sG>Ia zy41way=(sEPu6`P=YQOirM^&JZ~4jR_Ad(WX>Gr-Mvy!2Rk!Kl(y6xV(mBNMwn_Z* zm?X`hmngn6C&VSwQ$buel4~~OD`%Gl&%-Z;w1^8o_EllHv93zt`eUzt^CR_pHZE*d ztSc@w&zN}I_0j(uQf~zkqIM>pIly4EH22KTIscB$JuWrxK!I=5LCYU)rw%UQzwq-V E00~`Yvj6}9 literal 0 HcmV?d00001 diff --git a/certificates/certs/DODEMAILCA_17.cer b/certificates/certs/DODEMAILCA_17.cer new file mode 100644 index 0000000000000000000000000000000000000000..828bbf989458341592d8850727810d90b5afb67b GIT binary patch literal 1078 zcmXqLVlgskVwPIK%*4pV#3*mT%f_kI=F#?@mywZ`mBAp|klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5#612aPtLvur8LyIVJUPB`=*9^=xh^2<*P$x4B^Sk)FD7gAMdinru z*EKXZXq=DiTSis}=EhzIgT_v##zuw{F>Pjh-<|m=8-IAFm`wf4Q>(vS*|My2ufV$P zo4tG+CCfImy*Uv-&s4DDuJ{TiA?@Gl8zN_P$sJv+l4sNNC}rmcPQKMAYz`Ff`8$WZ z!0%DfDY65JLxiMw~!;aeVADl8kCk8U}6yZIKK99^-5%m}VdgQozR|#v-Do;afY@7*g9*n6>jNGiq98P2omqFuAkQRBC#)}4x=L{?s zm@P1AGs-9_DX`MlPcF*QOHV1*OUW!w)XUAx(N9k;0gBlJ(}Jpz0Vp*9DQ8C@VPw!a zaY19>g2wK)#*UnnM69}#^Hhyfu;^7aO3p6@N&yobj0skioDUQPrBC?=9z1Oon+<5)}Svmg(=A7rbbG}`c(cv|bX<<8;cG^;Ta}Bq7 z^PDSxy6@BlKHG2Ldih&U#}u~9<=c`D);^1SZMA!vcEO^6*O!yCVnzR6PM%_URJ<;v F2LKiHX>9-i literal 0 HcmV?d00001 diff --git a/certificates/certs/DODEMAILCA_18.cer b/certificates/certs/DODEMAILCA_18.cer new file mode 100644 index 0000000000000000000000000000000000000000..1b0870364b40e307d7342c4a953ee23ceb858fea GIT binary patch literal 1078 zcmXqLVlgskVwPIK%*4pV#HeV%%f_kI=F#?@mywZ`mBAp|klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5#612aPtLvteoBg-gpUPB`=*9^=xh^2<*P$x4B^Sk)FD7gAMdinru z*EO^-Xq=DiTSis}=EhzIgT_v##zuy<7GHKZPrg3?s`;Fy5~|A*?j>{n6I01kS^erN zt4ryMr4cQgx)@hhKZ;yrcX+0v}mi(S$h5Y z)~||8%!~|-i<=l54VoBh4fue;C(F;s_@9LZ7*A~m@*uu43(#u~BAz9?dE$0e{bLGw zU%lYi)MK0t1=9>&`PQjvA)hIc?6etBua4;rVRdPO15R_Vh79i3qP)RaK zJlH-twWuUBEi*Z>B(*5DEFVZ`=I7;P7MEBjW#%OoRU)SmV2)sJVq|1!sNPi`b7IQb z!fxMryUyJ-UNg&GRP|DxUzhE!!tOf-rk%DvfBYXE5TC@pcDh+{)%CN7pZ%1-bmDxP zW~*_s`<2tCy{|a0rhU2oT4~zuSIVM=`kNAOxiGK&vUf$|QP;3&O+}66&#p$ws4>jH zK4(Ep-Z{+^D)stVo8|pd<>vi(@~d2D?$+i5I?CH0uFr8uClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5!p0}~@-BSQmY1G6Y`UPBWw*8t2lh^2<*P$x4B^Sk)FD7gAMdinru z*EO^>Xkt`C_AVnU19KB2KLb#li>Zl`kzv)&<#B8R%Z#sidoNyoIY+nh=XIHinp-wD zy3uOIj$*zkn!j@Ozlw5u1oE++`SPUuq-NlE`#tLAzox#Lr1E*ga=t5>>p$%@Z(s07 zy+caj=>u>7PmQ5WBK5x3OCG*muqb5bBM}b9FEKG4~zUTK&w>i)ls&UvO#nYfcP;tqtt8wuWom;}+9h?2N zIXhzd?b)kqADHjkn{nf=htjnF72B%s%`bXZSkh#*mFJ(%+`n(N(l(jgUwBGKVfS1W z@Ap%u?$MZYD15eH)7QDneeSOOBz$l^lgvx;FtHEoR^)L@GchwVFfMLl5;SOH;x*s{ zMxiV}BjbM-7GPRwGmr=Im05tn+aTguvYRJvSJgkJkoVOKj!iwr*-$XeKo+Eck420{ zggLi%=K;s}-`v-$$Xd^kDdFo$xoyA$l2&11HDGRFWH1l{@q|I9a~QAzDJGy;I7m!^ zCBVSXfSZjoq0NIam5Gs?6`8|{%;7@j2qANXkvSp;_8^1hSu7093``anEih=)%P1)+ zu+rC0F3QnM$t+IP%gxNuPfslY^6i01R@KM=lxTsJvm=l&GHCqA#-Ysy%pmNHj4X{G z4I1A8&4h{=Ftr)uFwV2MxHL5-Bp<7p3UC7$+eDxS+*}C6lPy9c9`}(+F2R1P^#I1Jb-IglqUAHc5 zf?;^XpYVfyn*D1E3}yvdC6|CB`u-{-|%xczB@MC+E58`-_mi{8F{ z!oBDAex*n3XMA_mc^y36`J|VnV!h(LgBh=8&t7`G_p8yG8(ckA7mDl@(giGcbt*5v zGIME$UkmF?MS+^f8z)7wR=sHHi@Tn6y_>p2)?VDc`=GDc!i@Cqf_y*M zl`5OBd9nG7m+tm7iQ;76IUjyJoNjhjO(v2fVDnSv!qSEq86j)mN8uVNyTWs~Uk;qM kf`RX275B;S`iE*R95&ha-}FZ}6Z`7`Ce7@w63^+X0KUh=d;kCd literal 0 HcmV?d00001 diff --git a/certificates/certs/DODEMAILCA_20.cer b/certificates/certs/DODEMAILCA_20.cer new file mode 100644 index 0000000000000000000000000000000000000000..447f2646c778904b9441ad06cca04efe1dc52e3d GIT binary patch literal 1354 zcmXqLVs$fUV$oZ`%*4pV#Hek+%f_kI=F#?@mywZ`mBAp|klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5!p0}~@-BSQlVQ?n>>UPBWw*8t2lh^2<*P$x4B^Sk)FD7gAMdinru z*EKRQXkt`C_AVnU19KB2KLb#li>Zl`kzu>kgie_T?%NA@slL%${7sj!BlMZrMgO@c zgXb*M{Mq67@$OtBwfXGEird^BnG|f6Uh+D<`*fp!qT_{cC*EZ&JNCVzYKu;Q?7wcK zZBa&*6Ac1CD0r*##p=2Y^L;l_WOlF>V^W)k5b!`jkZ9No{mw4(r+WnjBRMY78Om@=al1oe+ zAsq?YsfH_y8-7jyk!5zJSv%#!*~G+$ha#qIJN3wL(@m*FCT2zk#>Gucf(A`Yyas&0 zD3s-AWc<&<0!%Ay2J#@jG7B(x8$>)ycJsvTs`|$i^1gb(v8l&68w#cw$buB`v52vV zY}%j4kh{~tQ$K<0OU2d77S)x8y9{_h(kd*h2FwkN38T|^zCAF>su~%95-pH&b_5be295vNIJDV-8HAmYk)`pY zLE}51nNSe}rZ!_7#(5SOm!_tK5$*B+}zZ&u}HZ_mEoz^d(H=*MzB*ID+KX5i|d2iH$4d6*&R;qMo-=hOxj=S6QE zv;~=Nb1275-D6s2dLe0J*{7S9{|{`vvEuf+g_*yW{)_!$$GVlL_4^sS3x_tiL~|Z~ z)*N$A&%0D(<&U=!I@7%8sD&Rsu>?>ty81pwGC!(9LX literal 0 HcmV?d00001 diff --git a/certificates/certs/DODEMAILCA_21.cer b/certificates/certs/DODEMAILCA_21.cer new file mode 100644 index 0000000000000000000000000000000000000000..039167487d9ac01565291d434be7eda126efe6a8 GIT binary patch literal 1427 zcmXqLV(m9*Vkuw1%*4pV#OP(f%f_kI=F#?@mywZ`mBAp|klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5#U14AP-Lo*XYL*poMUPDtL*A&V%h^2<*P$x4B^Sk)FD7gAMdinru z*EKRUXkt`C_AVnU19KB2KLb#li>Zl`kzv+bjyuW=T-;}WJv{HE^^LsquYVqEPO9Q* z{@HI)*L0wF&P6Ak(;a+Cfl4bI#3LN5c-&^&sjkSQrCkyR7w9$ll?}jN*(#o@@HA^l*u< zxASsYX>ZA!xm%34t&i{JzTmRTX8G8>uIGizI8o_(JNdkKmbKxVt+ui0 zdp3nH)xG-mkIxP3_KWVt5+(Ts!A@;?`Ufh+4({A$)UL|J%*epFxQQvspouBWfDagj zviyvU|5;doX{F6T9>iB>0S0e_h-b-ep156A|CmDFS1&j=^%!SE!88L|kODpyF&2@) z^cI=_tCw$_E8CLNGBfr9_w~Ke20S2X6&6+l<_1Ov10fJk7-Tw!0UMBF0*W=x2MH>$ zG)^~YoMOPu#+lIO!I;X#$jyq(;Y8+eA#;R~Il{;s5uoi{VAFtJVP-?&v7_)fP7EKbzR&CJnHPb~rR?SW}u)yM#p z`hk?QBakpMX#B^*divU`DdnnP<@Pf6 z?IwB4JWn|tQ?hQ}u*BlF$+8VoRpd{9l;3vXfAz9E{6GGxZrfyZt!$=>cloQoxClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5#U14AP-BLgE-1M?_xUPDtL*A&V%h^2<*P$x4B^Sk)FD7gAMdinru z*EKRSXkt`C_AVnU19KB2KLb#li>Zl`kzpAFo2qid&#wtb*w{2!-Swo?<@arIeJW#e z?90(zmwYnj2CH13zW>Gx_VX3zX1z!`Do}Yj|G2F2?2f|>A3tdR2>$zEsi8*3NxdEm z_DQZ=>^YcDe}Bi=s2lGsy76wqr=17>uY9}UtNQH9H`S`zs)CxU|Hcd2Bu$>~ROxYG zF5AWJ%BnNN@3DoRl53wV@?FT;@S+-D?j=_ri$|AcJr`Pk(kJ%uiF*0tr#LM?a{3=z z^gOY#awhks9`4ktoi-Ap=LB}^A4rih;<&hBfl!aY>CHJy3LMt#4dV`3dgY^=@trr{ z0)y78tLx1TT_XEEHtI)8hGS>MUj6d98uxfB;ycp+$n4q3#LURRxVVWa%AkoU%zzIV zg|hsNjQ?3!fN7=8Kpw5`5-|B zmd5D@jZ+M`**Fv0JQ!1%7`a)IIh@EGE@X}nGDjGhBLcLY3v3$DE6i*tJa!Zw2MUiD zg(qlW4|1S9i-m!ifyn}+1qN+;86_nJR{HwMMLBvYnZ=2ExtTfo>8T|^zCAGQs~Q=A zQa_M#b_5be295vNIJDV-IgOo>k)`pYLE}51nNSe}rZ!_7#(5SOm!_tKe-t*M7LiHk_ehzb9#lg;0xeoa`0Cvrl;-mpFE GnA!kr*ThT! literal 0 HcmV?d00001 diff --git a/certificates/certs/DODEMAILCA_23.cer b/certificates/certs/DODEMAILCA_23.cer new file mode 100644 index 0000000000000000000000000000000000000000..42802f297ab16714fa571aec986d5aa2b6c72c36 GIT binary patch literal 1427 zcmXqLV(m9*Vkuw1%*4pV#OP_j%f_kI=F#?@mywZ`mBAp|klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5#U14AP-Lo*X&Bhx5xUPDtL*A&V%h^2<*P$x4B^Sk)FD7gAMdinru z*EKRWXkt`C_AVnU19KB2KLb#li>Zl`kzwx_P2cdzF3jw`Z1U@V*_ecxI6U7dQJBFW&Ax^l+w&8yurKnPD8jryJW}Xu$vx+3QBgb3 z?{t4rf1z)~j~g$&P2$dYi}x{o5ZeEVB}Z0x|7w|gyqs@N&klQgbHej!OY7BA6AvDl zouRVy?4?TO{KGZ}Tje}{+65FQEpXgbkl@8n(2#LURRxVVWa%AkoU%zzIV zg|hsNjQ?3!fN7=8KpwiVZa8Yn1Eu9^Fe|N zERE9*8mAa=vvDT0c`&9jF>yEjacHvva~eA%BTM5)gT{A2Goc~|Ol`(EjPoomE=^4d$;WD@0^9(` zHW8=+`N_ova0eMQcEFV|wbkULB*L7Wo>B}~rJtOqYMg?_(W*wt`K3T9V9tgy!K#w; zfr6l70q8SC!2nc}3=$8vPj+-pEh@=O%S=uzNwrSO%u6h)M9zP};s%)i7#ZxoeS5-x zCH(BZw=a*l2HkRvmRM$HX~4Cu?)A6MKg*N!HrqGXJ`|E_yPQ1bOUajWh0|aCK9Xe> z`)KC!HHROW{diIF<;IbKcU_I4zq*=Jd5(VaJ@Zn&zuN6CGuNC~kJcoYv!6B!xy=!} zDT1LkX4y_LoA}gReb#eP_Oot#o}RRL;m!QOD_;+A99(P}eZeug@yL|alw?hx*bniA z?OAiDO?rB~>920db*7wCk8Us6e7o=}Uz?qsc<0_cCvoX5-z!cS|Hx# zU-i~05!VV;pITm2-etmY&^dR<7ryDMHyM2ESl-vyCBWQLa%Y|I&!;m>q*gBC%H?Jk JopRJZ82~6P&z=AP literal 0 HcmV?d00001 diff --git a/certificates/certs/DODEMAILCA_24.cer b/certificates/certs/DODEMAILCA_24.cer new file mode 100644 index 0000000000000000000000000000000000000000..f4250e5ecf81d155a910bc49494a1f009a8d1e0a GIT binary patch literal 1427 zcmXqLV(m9*Vkuw1%*4pV#OP|k%f_kI=F#?@mywZ`mBAp|klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5#U14AP-BLgEdL(?d6UPDtL*A&V%h^2<*P$x4B^Sk)FD7gAMdinru z*EKRRXkt`C_AVnU19KB2KLb#li>Zl`kzuJ`MAgE3&t^q`WBPdY${kbXS=D(ODJ4<` zHq&I!9GYLkV#8xONs)tB$Zx@Q^A(p)9#fyI@hkNDCUF+Yb4GhURL=XFv0CrUd2^Oc zKe$q7c`Asg9^508wZJJ?nqy1*LMNrw!ZU9%F_NF zOOK{`n>8eDd!xGh0{`;GX9HJ!zf>7I!9;EGlbEx+Gt^2r%@;mffA)#pO!xowhurt1 zw(K&}T+H|3(4y$7SDUqnqgJLaUrUce`{CM zFJ1$=x@#AYZ*x}PsIijg@n-gl`$;LYTzmY^uIF1fC&KJL6Eha3DOrAM{k@8vUCg&^X0_n~gJ}&4V$OiIJNXnZt?9;X>vJA#;S0IU+#Yxxl6Yy~50f!ed9_aiH*c zQFwv|_8-DzsjVg_B@yQ2^ps+_D*faXB4vrT&!VBNTRfmZi z=$^Rr_Ij_oOXhjO{L?p{2bFFOJh4hP^MjyfOQ=nE(DUqgTg^-Tt&l&C);eLS4q=kek^z@i%YNjreyg zda(Uc+ypk^DT;~CIklgyvs2$bzP;lA(b=0OJ%1hl?*0DHmOY!lieGBGdN{|+D#w1_ z`WMl%X3@*kMBTXEvX5VBSoM6J%noh8Uy4QZnwNJf9{D{enSZIR KB5l#}87lzWVbIV3 literal 0 HcmV?d00001 diff --git a/certificates/certs/DODEMAILCA_25.der b/certificates/certs/DODEMAILCA_25.der new file mode 100644 index 0000000000000000000000000000000000000000..35bcbbaecd705c74a13e52717e081c1ff5438e1a GIT binary patch literal 1427 zcmXqLV(m9*Vkuw1%*4pV#OQCp%f_kI=F#?@mywZ`mBAp|klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab80M14Ba-Lvv#@W1}b_*9?hk5K9fqp-yHN=6CUTQE>Hj^z;GRu4`m! z(8Q>O>|I7y2IeM4eg>d87gG}>Bf}#1;`Fs|2;;B*kw1b#uheTzzJ-Q1>0v<_|mXE$i;MxFy;4L`R2AeVo&4*~y<* zSG=4e%WUgwCn;X@o>Qsm-{B|o=bgQ|x2eUFCun=^ZpZqsy-T#dU5H6CJn{I|_U#qd zX8R?@Z56tGsw8$tmY}nzX!Fj@|J~_=DV;2j>iUK+-BKtOm>tj0^@sAf7PDbPfYHAjJd}Yn%@fRA6bG zZqPWzfSZjoq0NIam5Gs?6`8|{%;7@j2qANXkvSqj+quA|0lmV^hQeb<;c=kwcu{zQ z2KFEa%ClG)m>HNXFj`>Hrk7DtQedU8pInrqmy%hWsF$0Wqo1By0_58R)4r;a0VwqY zDQ8C@VPw$wkBvi{4Vcr|85vm`KN>W?1DXjHF<@#l#$lXiadByCN=QCdGZo+lFt&+6 z4aiR}E`U48ps@q4gsH72CnXW)E&+L zZO_hIsH~V^TsiB}%>+TEt8X;iCn%UdYH8V&@vZh>x3}O<+5NZA+<944=XSEkW2ISJ z!i1T(eni|Zy0Ee@FX6wiBAZ`4@Z##}txl)W4x?S*1?p^z3O2-UkA2#mDbC{E5RFj&!E#YmWS3r1ha@vdXfTI@OM@@pF1N) z@P&TIQmdzaM{ZpBH)qBZqqTkNBB85qo!DOH^gB{w(he@|S!rhsejiEBQro_LqO8Os GyEy>pOWJJ! literal 0 HcmV?d00001 diff --git a/certificates/certs/DODEMAILCA_26.der b/certificates/certs/DODEMAILCA_26.der new file mode 100644 index 0000000000000000000000000000000000000000..be2fefbcd220a67905a49880ed2304b497820abb GIT binary patch literal 1427 zcmXqLV(m9*Vkuw1%*4pV#29G6%f_kI=F#?@mywZ`mBAp|klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab80M14Ba-Lvv$GBl9RA*9?hk5K9fqp-yHN=6CUTQE>Hj^z;GRu4`mw z(8Q>O>|I7y2IeM4eg>d87gG}>Bg2|_foNMT_P_7W`yJchXB)MEAt9jh5R+?~zlBL- zjLd%ZgsjRl%cgT*>wI?O_SBkiEB1G8PgAsn#rtIq{^7;yPbF z=76+Nx4T*DKUP+*j?sFm8XF`1yO4kD4$=PjDb>v9->sg+!S!VC;)Suz*KLo_zv3cb zwJ1LRN!yfs<^`son{PbaAvwQlSLt~M)(f|lmt?74&n$2~7F*HH9`Cwl?zP3FYX*E+B%qV0Z@>eRR$*Z^U~XV!Fc1Rqgh8fr7_b2;CZJg3e2}05OXGBd z#wiBeY@7*g9*n6>jNGiq98P2o7cxf(nInwM5dqrH1vU-n6=pUR9y-i++l?3|$8IQ3@x-_Rcsr9sQ;l`?W$uhp*W;?+0V ze_bQzSoGRG|D~;trL-=YQ`<6i{tD*QC-uH(cuK3hSY09-x-CuojqSBvK3*$%|Gs9{ zjXT^Dwx6EP4X{?$eEQ{l!m9*-nS_HJRm*Ii%DN~4 E00*wgJpcdz literal 0 HcmV?d00001 diff --git a/certificates/certs/DODEMAILCA_27.cer b/certificates/certs/DODEMAILCA_27.cer new file mode 100644 index 0000000000000000000000000000000000000000..ac68bd1268ea74c76af0dc46dcd129592c9b8596 GIT binary patch literal 1366 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 MCyA|WQJ9nr0RObW2mk;8 literal 0 HcmV?d00001 diff --git a/certificates/certs/DODEMAILCA_30.cer b/certificates/certs/DODEMAILCA_30.cer new file mode 100644 index 0000000000000000000000000000000000000000..f56ad824e14036c1eb1dc1c5e5d50d336a53f8d5 GIT binary patch literal 1366 zcmXqLVhu8AVzFAl%*4pV#KgGMfR~L^tIebBJ1-+6D=ULRv>~?vCmVAp3!5-gXt1G# zff$IxCCneH7p$k?o?n()l$V>DS7OLxzy*@w7G`$IcR}I>czYU(8Hj-7n1y+PatcBD z`6UX@jtWKwa^k#(h6a`f7KUa9#s(HqK(09w*C3V}mP4J)EX?oX@1o%9>*(nNv|ZQO zz@Ujy3E8`htPIRejQk8haW1ANMn;Bbno3th)Gp4D3W_`0(p+43Fk$oN3sd&}m6;N{ z|67aB?2`vdir=3(H1pHUlewovE|>h@C-CXJ?*7xe*%rT>5#X50_%K{&+vz8#WY*LL znec7wV^^~?GF`tok?ZJFj%`AfJs}6HUVaRak8QR}H`uIsTh_|QQZe9$gibG8>AU2j zij1{Mb4r&?VY_UUEwrAEU2~uCf&S+biaZdcVmrjYm53yw`a#@SFX%|I5UfR9CtMZ`2Q zO@nh!m}+$Qnf;A%i8=^EeFHfD{uWg8>gnOofHjfVlz4O9Sx~SmF(0 z4Y=7j6WTl&Q<)gKS&=!M$Q(grju0|O7-%vV*Z`o@nWa#8(gx-rd*oRR4D<|i7HBQd zXj985DJihh*H13W(M!oJPSnfI%mH!qfhj1+-#^6J(MS)-1tt_mHV$nzU`AnQWMpal zV$k@}zzQZ}z|^LP&792Q;?mTVl6)k?;ypw33e1xY6ySOp+eDyx^OK7U;Eph8oB&tC z)YjOXladH?XL?F8T$z4yo~m&QFt4c^8Gv#dkaBhe5=N><$@!%~DPX3AF~O>m^MQh( z91T>2$kRY2$sqAy`{bhh;$r92qLR$C%;dz9)PTgyBI~5gyu_kP?UFiE9wM;=hf&hv{*E= z($d5+uXaa-L0HGUC#zCiZ!U02vfBRC@bbilkJ190(hIIeua4XjV$Wsk&D9+!9D**3|4J^hSt@0ErBul$_It`tClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5!p15*QYLlYAdQ^P26UPB1i7|bO>}f_;2IeM4eg>d87gG}>Bg4#q%%krUw&w0!9eqyp-}|$#3;Rqi zIa?obKkb>Bz0h`R>Ea)1PP*~-OX>wD{CMW~QsvI;%I)l-Q5!u|;*N#gW~<~E&G3R@#*gSI_Ch(#f!7lWqYd@&giP@i$7_hYq(G%`^$l=I%|`!xQVvf_F;KPZTnwtoQ;KkOvkm<%$7+c8vH*WBU{;!Uuym&Z;^K_|DTXq!J035`?p&$8!cFV z_56+gXI{&9ag?4tcyPMCjqaL>lRn5DjBWgt?=i1s8vkNG(UiL7Ow5c7jEkF?1Pz*) zcn$b~VJXYc$oQXy1(;&m4CFz4Wfow%Xb|x%+07HTtLh(9$ouLA$EF_RY$%v!APZ8! z$0Eie;w^KnkC)@=nY9a;4p&S#tem_~aGe1UNLq!3)quHyk-Hzeg@oZoC$3njHyhF+^onPPGk-jGDirRBaF-uF|Y?2EYD(LU}j*lz-WO% zn_fmqNr9EVesWQcUP@+hqF!!hj(&P-36O6OOgpMZ2B4%1q?{drgponxKQ<0+Hefbk zXJlk){Akel4rnG+#DJ;I7>9A5#l@wmDIxh-%~XIJz}O}NH6TB^xB%`TgT@ZH5~jAA zoRmbElhad*;i~kL^HhyfusB-PC^^3rC9=15eaq zFRdH9uje}!*v=DuA{(=u&*_W?ug-@^ z)L-}R)#&7uY+m|!Rq>g-CKvRYx9+*Jz`a-S|1*)stZnx?FNn1VyqNm@VtBztSI!g3 zE4nX*T+C0}P|)(sXXCujhd;AktnKHVwqGdAee#qE)@y(5WqH^<=W5fJiT?2#Q^fYh r=O3BA>{cfKiCR_8oT)Jv!t9Huyx3QCXaCKX-MWu|J^EiQq_Y(Osfo)N literal 0 HcmV?d00001 diff --git a/certificates/certs/DODINTERMEDIATECA_1.cer b/certificates/certs/DODINTERMEDIATECA_1.cer new file mode 100644 index 0000000000000000000000000000000000000000..ff3daab96b7cda7c59e5bd02433b5e8095e76f6f GIT binary patch literal 1360 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 literal 0 HcmV?d00001 diff --git a/certificates/certs/DOD_CLASS_3_CA-10.cer b/certificates/certs/DOD_CLASS_3_CA-10.cer new file mode 100644 index 0000000000000000000000000000000000000000..e560e4ccd76f1e448d5e7d3f9ffb38a952d44a63 GIT binary patch literal 1050 zcmXqLVi7ZFVy<7n%*4pV#Hen-%f_kI=F#?@mywZ`mBApClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq=|Hq(E}a!ool~1!o_} z;9vz~g`oWW5(Q^R137VC17ia-Ljwa#QzH|@C?MC;z|6n`$~B0mh7+U=Bp^-@bn!(sWM4C~GB7vxG8i;=GBq|bbe8v3%AW|?z@u3=%_E0l`?uf+{m3&p&m(FW9IY05z(UeG8Gp>}!S#NVvB@%DH+&Omv z!-?_)h3B&w8}HXo@SJZR?p2Yh{!%%UT~YGg0^gviL3@j&XUWL0^3CH&5OcoyQFNzm zW-t>oBLm~&CdPXPO^mk;WPyH=U6xS2UDwJ@&wHi5wt)d3NSdFK z@jnX-Fgn`|_(6PO5TDh68AuuMfCN-Pyaq-F19=cnnFSc94I(*nmVSuo&vooQB5pk) z{1E@*v$_8a3_uDLSTqgP4Y=7j6WTl&Q<)gKS&=!M$Q&+%#%7QfA(k40ss3bEjGdZy&wJ5bLA4q5B=jCJ;mslrd<|P(YA}2s#wqpjSyk)ZkCMg%c z6?fz{QxCpY-1cJ0)m5_JA3LrJd#!aShv6Tq$b~z*o6>(|oZ52Z#`GtC5C5pV_FQ!0 ziaXb#hP#KFPg|y!v^|-kCv{3%@bZSU2ad|~6<%($J|3F8*>itJ|0U(ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq=|Hq(E}a!ool~1!o_} z;9vz~g`oWW5(Q^R137VC17ibYBLhQI0|P_jC?MC;z}V0N$~B0ih7%+W#34=)aPdbt z!P!yQ)Sz)bvZonY8JHV;84MabnHn1z?x}1It+0E-WoNgB-DtPf^gR9<{Qf^$*0L13 zJ=EC6=E8Gnn&8%pQzr8Xo%ZR__~&QX%~ANpM9Qme{q4h31-=BZ+&iPa?ELi5B^fav z1S@0TY>{$hRuNyYCPJ_4#PnsX_cUD3-YuD}v9)5)wC%u7dJ89GiYMGWgrXmf-E147>mgIQ!Uw_Pd$9~zvIhd&!rX@R++3>X}|}P z=4WL5&%y$X%{Bvm5MLO?XEk63QU*LA0TmFhfsw&L9>h~-0Y+(qNY0$4A7c7*9ea<6 zTTci-#J~7#?mq(qkOBo3O#^iUZZ^(@HV?*BCPr>nWDX}Xhs&U`8KgysrN*GDts*BS zvA{}SKc!gLSTEVQAUjhpIU_MQNiQX{I8iS*GekPAo|+N-fI=(wX^rIhn;J)=8OpiA9yj2@sg;n1Ly8-C<1$ ziznR^lDX@)FN^y5W3_eM%IIvbCyUMce4lP}d6n7WVzt$c(YY|FFz>^Yb&pxUubbbr z$S11ndt_&uXC8Y-5MQL_qa7Bf3S&6$tB9YRShVo`jqTm1U#Mjo?``m~ZaTm>o5j?d eKTgtOZpQhmR*{j0`A_>-T`g>#|Ndo4g$Dq=|3v8k literal 0 HcmV?d00001 diff --git a/certificates/certs/DOD_CLASS_3_CA-6.cer b/certificates/certs/DOD_CLASS_3_CA-6.cer new file mode 100644 index 0000000000000000000000000000000000000000..a7d587b714776eb03dac4ad08146097f3f570d34 GIT binary patch literal 1049 zcmXqLVi7fHVy;`j%*4pV#HeV%%f_kI=F#?@mywZ`mBApClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq=|Hq(E}a!ool~1!o_} z;9vz~g`oWW5(Q^R137VC17iad14}~_12ZG@C?MAo$Tf#@4dSTb1W5yNh!X@{{1HxY zcGNX9Xq=DiX+~BC=EhzIgT_v##zux6&r6PZT`w@;dHB>P$@Yr>@;|@#{{LCYdsZce zr+7ik*(b+N$@|N8c1Qc2>Dit6+pIfe{oLg*HtyLPeKw6P`(=ukNs!y&f*GQ(g?2t- za1NE(d4aFpV~%=_PU%+Ugau>cUQWczu%DE#Wh?1Y~Z!< zCl{HR85tNCH!85n>RD6nW6s2gyzaVE5RFs3pwa|?iMdI7DVfEIdbyc7`pJ2!#woxQp=x9RP7^@d7>GgX0wm<9 zYLuK`3RD72LNF#+b#gvX5S0Fast_pcs$8^-W;_ literal 0 HcmV?d00001 diff --git a/certificates/certs/DOD_CLASS_3_CA-7.cer b/certificates/certs/DOD_CLASS_3_CA-7.cer new file mode 100644 index 0000000000000000000000000000000000000000..45441e1e9e289707d8a4aa5a6b96562dfc6daf5f GIT binary patch literal 1049 zcmXqLVi7fHVy;`j%*4pV#HeDx%f_kI=F#?@mywZ`mBApClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq=|Hq(E}a!ool~1!o_} z;9vz~g`oWW5(Q^R137VC17ia-0~137Ln8yTC?MAo$Tfm;4dSTb1W5yNh!X@{{1HxY zcGNXDXq=DiX+~BC=EhzIgT_v##zuxcEK5}U*Pq&9vtq}3^*5Xjr@j?kS)eiV?w#rX z)63EqT6Ng{T6*qHc)W6d*PWwUvzHv@{yc5j?YI1ljhjE6TDX?GcM-Eb&w`%(CzdSP zXUe&bRb@c(!|_Gw|^Tl+9h4PCY~;Z2^? z`K~fCGcqtPZeqM=(8PGlKo;l)Sw0pq77?bS^3HeuA14;8U zGX7^_0mf#V0Y8W@4C1pIFas$A9*}?vh}Xc#U?30TDYF2hv_T|i&e9Jt{ke|4N5ris zgdgHxd^Y!=fdNQ?0*j`Bx&b#EXF{6?V=5CPH!CuS6Pd$h(AW&pBE(W-P}NqElag3q zrLUh-tZS^7Y+R6?sh6CQn46@Rl3ARnmz$ZRpPZ*^oB~V{szwIjGy$ZIff$r7KthhH zM#=f5KqbH=1Y?3#C+7nNLFo^u3XuYVN|Hh1!3K>RK(3HyX+O5_9x%yrDbl(*$ok56Xh z%uC|XWp@{-u)Rx8hl)l~SOdDL6@r{Dj!Os@$;+YQyH38$|a>Dyl4EGQZE z-RPi6*2PNh%?EW)vAetq^Ht$Jf4nf=E+P2f(#yOH8(!awsmiK)v)?lBPuh*v@Ok@7 dyH~1)p1JYeS+g)9ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq=|Hq(E}a!ool~1!o_} z;9vz~g`oWW5(Q^R137VC17ibALvsU5V^br8C?MAo$Tfv>4dSTb1W5yNh!X@{{1HxY zcGR^nXq=DiX+~BC=EhzIgT_v##zuzY*FsfFFZBHVul1+q4UhJOtA*B{E0)&eZ&^{d zUwP?;rG1UZO`hlv-NNkK;y5%^bTpGHu06`!cAX<9>KoIFnEEN_#LsMQ zInBh($iTR`iSeF66XPudS)dnW`B=nQL}t1k7x=Mlf~2PMO`Ceh$kL{{e76kvK+^n- zjQ?3!fU((Tzz^aJgZQil%s|S32PB{Z;x#Zb7|4To$}GSrZ4k+sv-Cquf39Qi5pnAY z;fMGapUwSeU;t8}z@llOZotjPnb79Jn99V+&5F$7MCNcAG&X~@2(i={RJB#)q$Czt z>FcKy>l*7N8y93}>Lq6+<|gT-WELmtTl4Ov0utDPnkSpX_8dn%JE;VRew4ibRg2p** zjWY+zMfS<5MJ1VOnaPPIsYR(}`9L}|KQAYPsM-xV7T%{r z^&`xD*WdB=6&1F1TiADWZi+5_@`K|p;ews!M|4+3AZ1&C@iu-M^ c1}&O2_1yiZTemfMNnEddFTKHc=0Ep60I}*vNB{r; literal 0 HcmV?d00001 diff --git a/certificates/certs/DOD_CLASS_3_CA-9.cer b/certificates/certs/DOD_CLASS_3_CA-9.cer new file mode 100644 index 0000000000000000000000000000000000000000..e1819508fa8b8004612e56268f9c99b4492db5ae GIT binary patch literal 1049 zcmXqLVi7fHVy;`j%*4pV#HeM!%f_kI=F#?@mywZ`mBApClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq=|Hq(E}a!ool~1!o_} z;9vz~g`oWW5(Q^R137VC17ia-LjywtBLfrjC?MC;z|6n`$~B0ih7%+W#34=)aPdbt z!P!yQ(x7oZvZonY8JHV;84MabnHn1z&R=*emgF0^_`-+xoA#bg<(~KUT5y*7gvaW- z?&)zScBb;*;rYuY?$74kJ5kGN=Bx$MU$>V1y6Tl6ezH(>n#r1Tmm`*~SM^xh>MDId zb5p^t33}mu4zin)j>k<>{H(BQ@dcSJsnw2F(Tl%y-*>eKh4fsIP z{EUqMSy+Iv*=E2G;tPZLtOm?L%76zXpaSAGFftg(gLuj;z$k4H$(ghCLrj0JWA71h z>j~k9_!pne{byhRQlP-1X`pVv&BmF~=E0cC#K_Hx%;7}la2Yfm?f(WM}FnXC&q(>7`^AC+g*9=IAHqsT!vMQ-rFK0XR(nX=5M;r3;Xd zqpDGIeko81FbTn!VAaX_KtWLY1FAx#K%kOjka(~`;|7o`+QnG6euU8bs6p literal 0 HcmV?d00001 diff --git a/certificates/certs/DOD_CLASS_3_EMAIL_CA-10.cer b/certificates/certs/DOD_CLASS_3_EMAIL_CA-10.cer new file mode 100644 index 0000000000000000000000000000000000000000..6e838aea45d4d3d1b46a4ad715fff8b6ca18de16 GIT binary patch literal 1056 zcmXqLVv#XuVs2f)%*4pV#HeAw%f_kI=F#?@mywZ`mBApClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq=|Hq(E}a!ool~1!o_} z;9vz~g`oWW5(Q^R137VC17ia-Ljwa#Q&R)OC?MC;z|6n`$~8!(h7%MFlT1{ju_? zvP7w1{Ow6;fzmapd+W4>tvHmY9g*x;<2~a3>F1i?K`znjiu!tfg|zd2TJExZrAk0Z zt;Rf=?~PoyAKssQX`jKV7#E)UiTmo3WfJxu&nY`>w`pTQO{LeYC&!j>Eeg86WV?Re zO6T3@s-AtwWMXDyU|ih9c+a4T@s@!s&?mBdEMhDo`R2+?E-SqL!egH>ztV@hNZ^vq zbOSz+G(RKbe-;*Cq_!FGgZRQAKC1yUkTT!_38;X04U7y1@*tiv3ovFIL~`aV{Seci z>)3ll+r50!&FTCRlZHK2Q*p41uZ;2@$9y86+NT(6|BQ3VD{s6$Xt<4H_3M zXq>;GaZX#~%z<)|eR671NoHDRa$-qpQEFK}kj~7{%gHP*u};d&ODw8HPJqD7#|%t) z%Tptl&)ihBW68{=rd)^SJ>b~BJ{O0e&!W>TP6wiG!aZ^^f z>!PB>H~HSTw=@0=?LYKMB*K)@=FtDyk2gp>c(l{7=E{A!2Dx)v@)xbnmb%qy_kEYr lwQU??cCx)Q-$&coisWZK33*Za;cL>2*n8q9U-mb10svR}OZxx- literal 0 HcmV?d00001 diff --git a/certificates/certs/DOD_CLASS_3_EMAIL_CA-5.cer b/certificates/certs/DOD_CLASS_3_EMAIL_CA-5.cer new file mode 100644 index 0000000000000000000000000000000000000000..3a5fbaf4a60dffc0e2f33384bddbdd9457e1c12e GIT binary patch literal 1055 zcmXqLVv#mzVs2T$%*4pV#He7v%f_kI=F#?@mywZ`mBApClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq=|Hq(E}a!ool~1!o_} z;9vz~g`oWW5(Q^R137VC17ibYBLhQI10z%8C?MC;z}V0N$~8!#h7;rsWFbxvbMZ$w z!PVE%(+B7VT~mX``N&>pWMyD(>}4=$>||3UxmYTM?=Jr#XU@_OG5xuY zy+_2YCxjp3Uwk(ApMe2LfdY%Bfw}=V8)rhB2V*J|BR4BDhZC8@Wzg6R(jvrCV^Gyr zk&}{GV5P60QmkvNmuy^+ovD|ck(isLmy%hWsF$0Wqo16oYMcU07pg`E;FJNRje!`H zIzU2>sz%BAr9dUXgal)PRVU{I1wpA0s0xt|fl87=;=u-u8$hm*XK7qv(74o~anXXt z`3oB7v^CBgC>Pl$rxulDre!84mZTP?mgNKK%>2BZ%;FO3q|Cg;qDtfh2+VuTz?8T8 z_z(AoDsRruwmU$3>Z6?lqmcC|g+zo%H?{nT5Msd`dV j*DbCwpIDut@%{OWSxv9~eEc2 literal 0 HcmV?d00001 diff --git a/certificates/certs/DOD_CLASS_3_EMAIL_CA-6.cer b/certificates/certs/DOD_CLASS_3_EMAIL_CA-6.cer new file mode 100644 index 0000000000000000000000000000000000000000..242b35b99503e5338fef495d0ed02980424ce796 GIT binary patch literal 1055 zcmXqLVv#mzVs2T$%*4pV#HeJz%f_kI=F#?@mywZ`mBApClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq=|Hq(E}a!ool~1!o_} z;9vz~g`oWW5(Q^R137VC17iad14}~_0}CVLC?MAo$Tf#@4N|D#1bG8lh!ezI{1HxY z^>y_00lGog%%E{Tvey||8JHV;84MabnHn1zR$cy;<$bNL>+Y7kcmi zGGRmT%p>cb*A_*_hcTr_DhVvT()iQ+%f!oWiG4XsgjQ_idVZEwir;=AKf`qW9fcYO z$tgi@PO9l|_OrMw-@8)W@!OHxzB!Z6DzpFHJv;7r&zuc6g{HYyC!W0#>Tpf;isjUd zn|~LoA3M37iJ6gsad8vlJ%c93TVRjK^0A1qh`d;>Y+4nq5GA7d)$8PkX<`i)N!twg zfc})_XJq`(!UBxbHUoYTUl_z^HDCr(20S1E6%en1k-9tq(z9O#-OUL zA}1xWz)D{~rC8TkFWI;tJ5w(?BQZBgFD0`$Q7<<$M?X1F)i?#1E>w*Sz$pVr8v`*Y zb%2B%RgIGKOMyy&2?@pot4_`b3W8E0P!%E_0+l3##DfhQH-KCr&(gTUpmC`|eS7%i>pJKE+jaKxM&+axo1B>7qx|?u=>2QkTen?*bRywTL#4Pv zS?lwTOe^gJe2;Fs3m3NS?N)9o*z$>K_S)8cn{?ug_Oz$=FI=-z##(x{;q#VN1+J$y jIIll^A#cYNme}rJ5A3e3*<8L&ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq=|Hq(E}a!ool~1!o_} z;9vz~g`oWW5(Q^R137VC17ia-Ljxc*G_{BVaxD$a3@o5rgA{5wLEb~%&~2Ij_I27|^{4~{0Ja=9( zYy0|t-G>Cfp0ir=E$;Ej+YK{Qck%4`_nh_b3BKL&Gmbu4+QogyVZNdEg57?3>E*pQ z9|*tLv*fwcOsCKpyhTguiYzz&m6wlM7R6ugTe>0c+pMB3Uw-O_XJ3vBTikCR)^q3C zvCm(_Qsgo!nV1#tk4>$g?!AFlbzA(70$p z0tDtgW?;$_ zYs#JT{nzy46RJ;jUI<)>J57^xiLvMvx5QF_bXaM9?+z5Lom zbthhySkK-!OLWeRpG#JR@rXS&dha^j>BVuAHl^viR&YK%a`NS6jz*;hLw7-oP3ha$ jhhMn#f3-sQ7Jfamb(f+Z?PRq5EPTgjU&4_?zPow>BcoJ) literal 0 HcmV?d00001 diff --git a/certificates/certs/DOD_CLASS_3_EMAIL_CA-8.cer b/certificates/certs/DOD_CLASS_3_EMAIL_CA-8.cer new file mode 100644 index 0000000000000000000000000000000000000000..4aff73fc429aa8ca911a1a685d6158d6420179ee GIT binary patch literal 1055 zcmXqLVv#mzVs2T$%*4pV#Hee)%f_kI=F#?@mywZ`mBApClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq=|Hq(E}a!ool~1!o_} z;9vz~g`oWW5(Q^R137VC17ibALvsU5V{=1`C?MAo$Tfv>4N|D#1bG8lh!ezI{1HxY z^>y_00lGog!k}?Jvey||8JHV;84MabnHn1z9{99OmUw3JsP03o@AIlQ=75vDsoSpp zYdM|MeXuTIU*BAtQ!@`qHvbp+tk~au*}a8Rdd6FWrVVrTeH25&jk-@MwpdHg|77!i zRz;Yx>1Ww_yQ}37TkmoV|5~{{>Z4eNMU{@Jpraj!m-mX7XKp*^U!9`T_5SERqxi)5 zCnCB>jr5tA85tNCH!*HilQkxZ6ih3AYQP8d zrz}4s<9`+wV4SuY@PqimAU>-BGmtXi0STypcnypU2J#@DG7B(b8$@#EEd3DEpX=Cr zMBI8p_#ytqXLJ7<7=RQguxJ{n8*sC6CbW4lrZO>dvm$dikvUujjm;n}LM$}~Rc#eH zDTxJE`uZuwy2g6R#s%4#ddV4yxk-8{nZ=2ExtTfo$$6^ADZq50YGeRT89>??h(W0X zB;=@Sl$>7*R02#$FeX@aaz0QHlnQ~W5a|%8BpDMK>xbLp7Ocnb$3luuG zSu8mCVdmKf=YBc*@2#lxFpU4@oiO$9u1AG>2_lOG=YJ{kyAZNd{?MI$lU+GhJ06H~ h-Q%2Ol(S@_pwey&kF00m)rYJ<`>~YjXe*@z0sv!RMKJ&X literal 0 HcmV?d00001 diff --git a/certificates/certs/DOD_CLASS_3_EMAIL_CA-9.cer b/certificates/certs/DOD_CLASS_3_EMAIL_CA-9.cer new file mode 100644 index 0000000000000000000000000000000000000000..3d0eca4da4e3d13d871c890bbcd07ae38acbb690 GIT binary patch literal 1055 zcmXqLVv#mzVs2T$%*4pV#Hek+%f_kI=F#?@mywZ`mBApClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq=|Hq(E}a!ool~1!o_} z;9vz~g`oWW5(Q^R137VC17ia-LjywtBO@cjC?MC;z|6n`$~8!#h7;rsWFbxvbMZ$w z!PVE%(+B7VT}y+;`N&>pWMyD(>}4=$>||RT_{UFuXxRSf;_ zlK-NG*)VR7&N-Ld4ae*DR6KiZc`frZs{r#M`}B1ukBhA6@mRWPx7laDHRk%V38e?U z`n2}$W8J@TA`>$s1LNW*#(M@$jJLoZk>z6%V-Z<(DfsPvy9ZyywisQ#=c08>HEH^O z13sWXW%(Hy|Ff_F4%v9 zT*uxc;?@(w5AiQPoBPke0Hi>HMbkjtfSZjoq0NIam5Gs?6`8|{%;7Rn^MQh(R0vdsNQXcr$sqAygT@UYSIDz8t}tj^YS6f7 zLF4=djdR)>XAYE$?2}WAN;1*5aSFZsZ?aPe`D z2AMZEgkG(!eZ2IThnWSxla=3>?d|XU`WerOgdX==Cudh`v>?_eto>EJNPX!x$^7_x jx0UL0q_RIabo|-1;$~sA*^#+*E)m-#7VJ4j9%f_kI=F#?@mywZ`mBAp|klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5#6149ENLo*XoQ`0DMUPB`w*AU7zh^2<*P$x4B^Sk)FD7gAMdinru z*EKXWXq=DiTSis}=EhzIgT_v##zuzO_1<&e{rtk}JJl)dIPZeo^Fp8dOZnqAeEk2D zjeVhQ^UF6&Kgpl}TX1K7@Y2W4dQ!@pRJA7T?%#Z6%9UyRvDVp;e$C`|dGee3_XpjBZ~+os=%kDIlC%u7dJ6>8ZCRkN+K2Q*pVu4m5(kxI( zGDtjF)i^CVwWuUBEi*Z>B(*5DEFVZ`=I7;P7MG|RCnaU(B^Fg8rxjq%U~Xb$WDt!G z-RYTM(p!0vH8L`~N%!e9F}GH4v-5HS#>_(c5`FK|e8j|OowL+!d?oTk!Jv839uq5_ z*>j?wEBWvD?&MnHRbe9%A;xh)EYLpXNmWhWTzO`TamvVRU4o?1Ki}F7om%KG;W~-U< L)KhtL8ZQ9=vt4U2 literal 0 HcmV?d00001 diff --git a/certificates/certs/DOD_EMAIL_CA-12.cer b/certificates/certs/DOD_EMAIL_CA-12.cer new file mode 100644 index 0000000000000000000000000000000000000000..226ad5d1e33ece2336b57c4a50f5425b03417df9 GIT binary patch literal 1086 zcmXqLVzDx4Vpdwf%*4pV#K>d7%f_kI=F#?@mywZ`mBAp|klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5#6149E#Lt|4D6VoVhUPB`w*8<8lh^2<*P$x4B^Sk)FD7gAMdinru z*9F?tI3L-!jI0dIjlB#8jh#%5jSP>Kmc8p*wB#bATXm3g*s^Mo4_jU}28W#2&dJiP zJJP4MW7Fwmx0T%|HUD#0#(wgWncgjP+-wCP&eRa<4kDtU`%CVqJTw8*nG-ZW^uW?;3z zVu4wkNk&OYft9{~a#4<6azDe1xf)E9gGQ9m7EV01f^J@6^JwoRFVu5 z4^}l!OHM5+$xO>kPAo|+N-fI=(wX^rIhn;Js>Vr4nR$stmB?uYm@}B07#SI~&e8kxhrDl&EplbKYL-Je@O1W>}l^5d*g*So46!32pqb%g{NJ{z-{KfioJ;* zMK9C>W~WV-d!Z!!(fhyd>!t8w!i#&_&r|$l`W?HTU>#a#$#_r4)Jv;o4T({s} z!twRpg!)9UdovGS`qp-@ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5#U14AP-Lo;Jj1LG)hUPDtL*A&V%2&abSLIwg5%Q;>AU4ZuL8W|ci zF)AT@l#!KzxrvdV0VvMJ)WpchaCeGl%G^z_znVrq6M3vW=NNay@_5gK$2gXlYgQ|Z zRC4^2(z{hClGLD|95k)EW%{=R9+evxdvdg2UcbFR(^o+0(Z7ONo5@^rBI5G3VjKU- zCRyt3p2^1?HUHSta@`Kzgfm;Z%6;NzKU-?QY(2}%GePs#G^8{y%@q9{;`?OIA7^)dYN5kZe}j2y6KDOlnHgbi9n23eg=m$Ed#9fIEaZB6 zn!p?3Gt&EJvxNM%37l0I{$K5_uH4p02i_Hb*Q(10KH2%!k%^g+fpKvYQ;Mmk-oDBuj3}itH_*lePL^x*(KU#eC zdC84$_FM1#zOq&9t1Ql2sryDd* zG2mw7Olb39Ol4x^W<}<3B6GNqIYP)BVPuX7&~`4cX+Wn9iG=%r*9C+g*9=IE!VmH_$oz*MhlWB^L{K+4$> zNEjJ3{$u0NW&`Fic1A{)#*YS#?|^1PMGTnQjByy}SzKJ2ni7(a)l3Dr0gP=TPy_Ol ziwocmGHC38D`9G@$w^6sIXOM07_Le`IZxF%1&gCqjgs?Afl|Oc4P$~;CFcVLK?MTP zXNV#Js3aLA9&DfN=$u+ql9`s7oLG`-os^lESX7Ce|9}MzF#jt;Ce7%%8^IrMSOy%xr{H>Pj?H||cT?b{yq$!7wS{N)atmx_5k+I#Y) z9VC-BJr*h0f3d-PNuj;Sy9Zxh%6(;R6tcbYhoO0s{2^AIWChMc?sKE%CYLW$<`zpX zhPb1UchhLm$%er*aa+huYx`b-2 zGzQC~0W0I2eHZTG+NAPZ$SnNqk5kt1b*GOCYF%Yv{T(0iJcK=cr6+rzSD0{`Hvq~y By@vn* literal 0 HcmV?d00001 diff --git a/certificates/certs/DoDCA22.cer b/certificates/certs/DoDCA22.cer new file mode 100644 index 0000000000000000000000000000000000000000..3d80ac7b07a18134aa7be3731d8802fb5304f27c GIT binary patch literal 1421 zcmXqLV(m0&Vkum}%*4pV#OPtb%f_kI=F#?@mywZ`mBAp|klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5#U14AP-BLhPVQ_CoEUPDtL*A&V%2&abSLIwg5%Q;>AU4ZuL8W|Zh zF)AT@l#!KzxrvdV0VvMJ)WpchF#FHL)$$(;Ok7#xIseF9zp6I*(uB;-a_4Rc1s6stxA)SMX?#_0rzEQUUOV&FqcqX8S9h1cZ}d;pJ->2wsKkq?{hhs< z=McE&@>x*Pv( z$YeipXuj~NmfVYfi}vrEwKprFIIP3!*jni$;(K|e9|tA>S%2{N8T~xdOLwhq2wXg( zv3*<4|H%)&6@AbYPUp6;k<{qTk(}&l8*Mwi<+>~rGb01z;wGjjgC?dh13qB*$?`KY z{%2tUrjj-Tc@STj1(+5ZL_AA&^Th3{`o|RVzIws2smC}Q3Z@yzf)wzvh_Q%h7{~_( z_FcWZcHwD-LlL5G2FqOh4R}D(DlDu9%nghT20|d7FvxTc12!PV1QctW4-!;hX`F7* zIK_aQjWeOmgE5tfk((8n!->q{Lgok|bA*vOB0$@@z@`Dc!pw%kV@Kg}pzwH6c!CD@ zAP35`SQwZYm@F__V9=(QQBqQ1rLUh{l%toDS)8bso0+4Zo>~Ir+XGX*s*wRG-2*9S zM<8Kj(D;vyLz@kl$JiMeSsFhYG`<6x2^BG5YBR=RoM&-yX=+MHK2|do;07?Zi9ij= zPcANiJIJ811FnRrttKZW5$5Fdlw!Cl{p37V;}k58Ry9h_F9k{g^E8YJR+XF&6a*Cr zK%XIs1fY^+ka)0tvZHfqQAuW6W^!Uls&!IkUSd%ta{dDrG{F4F$guogm}&C4pIiRj z_`g$!_uag0E5fci{#C0>|FdaA@9LWt&&os3ny-l4d3{f^O8dlfyQlA+@#3jP__^PF z#<^Rj%zVGo@y1dKF~)cQpY3_`gYDv#gINsU-tNf1_n3P|h;#$v+_MYa&+{3d*XZ2j z`K!9^&%8$`r_Hn2D6g{lj0o$dWQ)LT%M8!`GnME-zK?5c+}|X9xNOE*>?;0apO)C{J$3D_GKX)TeC@4% z)@^P0wtWXoR|x$Q^tgTG*2h<`zVJKz$-6!;ytI7J8lLHIg823=pRu)~uIAd&`L;F6 I%m1qa0IIs!ZvX%Q literal 0 HcmV?d00001 diff --git a/certificates/certs/DoDCA23.cer b/certificates/certs/DoDCA23.cer new file mode 100644 index 0000000000000000000000000000000000000000..77ab504e2116f504f5c01f16705385696870555d GIT binary patch literal 1421 zcmXqLV(m0&Vkum}%*4pV#OQ6n%f_kI=F#?@mywZ`mBAp|klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5#U14AP-Lo;Iw6VoVhUPDtL*A&V%2&abSLIwg5%Q;>AU4ZuL8W|fj zF)AT@l#!KzxrvdV0VvMJ)WpchaBX>;vP>@1jTy64>X-hHUOZ#g>#bMnWmi{udc94Y z|MP@c;*S20|1t~pj`}4n)tJWp%Q`gem^jBKTHlIq-}t`kN8i8rwpagJqSneZq|przpq~UGkF*$OJ?`&~k0&n}VnUdatQ`V+3z31&c%EZjbz__@HDaxRUDa?Qm7=E(+ zjEw(TSb(Xd%|IT+S7rgGg$5DNlHELUyQ=;%g}kp`aBS)^&W3_%2C^Upd@N!tBC8y~ z3oVvu=GDI5Wn+8vPfn2k*$4w3khBU5s{wNZBZGkuh$jp(ox^|)NHGD$8s~!q6<8Xl z8#GQa;AZ1YX!Br9Wn$!JMdolKbGVQ>LdYCpWR3{Xb}q1KK(8>fq43yIcpNA^UKF07 zfj!89@+=kxW(Fn;j20NQ>1C9Z6jg8tU=%=Ta0QvU7RIh4e07~~j z%GnV}7#TGFW8=_f1LiSyMn;y#j|PqJfM!BP44B%CaTw=WTwI!(5|WSAOa-_BjBO%N z1M-uL3*ZhiXzYM1VQQ<%NlAn`IX$Hqu1Y^SPt`aDi=$PIlJiS}QouY7V}eyB=K}>n z1p?4#h#~=~BpDrr>bFfOfO@yF9&H+b!P#h;V7q{z+EV`hx=i^-9e_qR$g#u#}A%(1_6%K2}Ck@vK{ zGvav)=3cmCtY_!@c52YNM;7yv>(AzhR4|m)XBFhkd$KyhiAPR{J^0?qCHlR6$M@#k z+uYT7+vD-!M{B2e-#=A3*&@?oMUB~+;_bKnC8gb)Uv|&3SryIS{#y3uO6Idm>hhN? z?w0bZS~uD=F<4>PyQe`#V%{uXeh_}7VQI~Ar0UB2?m zoJB(;MLDYY&bLLpY823)bZ%$Jz8h17Kc35Kbl-Kruf^y}pClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5#U14AP-BLgF2L&GR>UPDtL*A&V%2&abSLIwg5%Q;>AU4ZuL8krb0 zF)AT@l#!KzxrvdV0VvMJ)Wpcha7baDr)tgb8tY4H_qrc?Op~(D*j*HtaMSEvNsFzR z%^&ug*ZH3s?0D-V`D2bKmudRaUpLY&D+ON3JNP6ag6ZS;>h|=Pj=Ux8u^i#@(Y8se zS&U72+$?_0+4ak6|4+w*>DM<^1-wq*_tZ@4bD&+#pFjV9{(pPJYeBx5&3*MZpMHrY z7Qd4T4Vmte`|Vi>yQ{ZbHuLi{r`@!RNtFuyu?^AUq8J#pX&FOJu zaeQyqy!XAi@5P3>pDsQ+XPIUDE5`GfNp{@ByRU5ZQde>s?)oI;bz|ERqj%~or$RRM zPnOuNHk0#>P5Alm4s85tNCH!(#SG%?k}A6do@MPtd>~ z^!1aAa`aL%ixc&7GjsIQQ%it+dtj}8f}jEc z=rcr-0929;5)Zadc63fHD#=XCOinCGwNA>+ODw8H&VRsy2AKaC88)8U?sxh?aJLSp z;A~+-(Qmdp^^@GnwAOfszUH}pP9vLp>S`_vvD4SrooU|~x=T%UR_IFOn~ytR^#!vt zDm;0ZV^eu8Hk$E4merZY;H$?({W_l<7F)vV)RX@BSj~60c_OxF_GCXw@h(ot?up+s zJ4s8_!YY9T|BkbnU~bnI&6tT~#*DZFL8B!S;*I;!NIZth4ZKt2=GDbyIF{oYso}lMbhR7n$r)erI`j!|op`^;dIdsVxHl DbQ8%P literal 0 HcmV?d00001 diff --git a/certificates/certs/GeoTrust_True_Credentials_CA_2.cer b/certificates/certs/GeoTrust_True_Credentials_CA_2.cer new file mode 100644 index 0000000000000000000000000000000000000000..a0b08d79f3923f410e2ac4b2289d47592ae3cdf5 GIT binary patch literal 699 zcmXqLV%l!d#H6r*nTe5!iBZ~smyJ`a&7A-4f18*?ZNn=n&ou%V2B z6o|tmEbLlXnwgeZp%9#!Tw0W>;F*`KXQ*bN0+MAGmPM0Ibt)~+%u6jUR&aLIH8hYD z=QS`gG%zqXG%+m98 zlY@%`Wm6TLi&9fk^GY%kb3pbf7#TFqNA?yYD+6<5FM~m2CsSi1!=~vvOD72}ZT+7y zYudtgq0@@1ME7jB`YpFq=CrFXi-}R-fmzo4jG0|qTrFKx{G6t5>}zy3{m=Pe;=1~z zM>RVekG@k*3OcoA89$eFK4;~vx)>X`)Ob-aKc0gv&H@CT2zk#>GGvHqJ5N1A0f6pONuD3kxthjv2^;_D}#ZzA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_ERUG!!uq0`ZuIxq&=|p#1z21!qSC zIdNVCa|3fDQ$rJDQv=f|ab81XAlJ;$7|b;&CeJb@0|kiHlFq3`C7EfN$%!SI`FRSC zr6n2pMVTd;sl_mdGYj*3rljVD6qOd2D1e-1XwWzx+0Tru49tza3hpO;wYa)YdX;(9iO+rEut1@4pW8ljksYTm?_bucue`sS^RM;WNZ%B7rH%FnUZ&35 ztMf_m@s1xm6J0xQM=E4_|7hqFc=qLy@|ydi$uitrGxtao?!BFERrJZ_{;7+dYp%~S zyJnr2{_JI@aKVQn{mH@H1$<@Ep0f>hu}x=UW@KPo+{F0Vpo#IlfjrQcvdS#LIA{?0 zwu42TFHG#_&g7ea7lx!dF5vLcH;@G>;A0VE5&3SM;B(;OlLiyfw<1NNtgqV2D-Ia& zfu#8v8UM4e0Asri97VFiAU=ly8<1jRWH3+#sZn5&GmtUhVdF|@^I%K`s^wus;V~IB zUIwX?XK6fb(0Ib2v3EgZ*Mi3Ow#Js6l*9rnef{L39KGa>#M~skl+5Bpz1++k{p37V zV;5kMs~Q=A(gTnJv7Lc*ekn`_%mZ>ji3=!!NL~FcXs)=Su5I|*JRbr_IfXN>f#$S z-n-wOFF#r~TOfBvoAdi)I``&JeD};D_Kx7OB;U%5Zz5bhWnSi6ojVqF@A>D%AnBv$ OPGl9SExWM2tQY{V)>Fd( literal 0 HcmV?d00001 diff --git a/certificates/certs/IDENTRUSTECA2.cer b/certificates/certs/IDENTRUSTECA2.cer new file mode 100644 index 0000000000000000000000000000000000000000..26b26123095ca4e7c5e9c7214f510115fc3daa8a GIT binary patch literal 1434 zcmXqLVx4Bt#8S6_nTe5!iIL5KmyJ`a&7D}#ZrA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_ERUG!!!s0r8lHd4W8Ip#1z21t4u? zAScdiU}0ctU~Xt?Vr*a*CC+PT0_2)Oxdz4LS*K*60I^)sIkl)HGc7YYu_QA;PrYkmHODni!Rkz0JtVz}&>h&j1wXVrpV!WLSBX zf4$bfQ^}z|0(m9=2`ArXUsqk6*|S3MyO#A;Zuu>ltT8Mb?H_B3UweO2BznpLAyvZ! z2~GoXyY#cI$2|+m{SN+I`8ain^}nR#RGBaCO0%3g^Y31snNecaTXt52J#=UFfh_NH zHQU6Cl1wKX2y;D%ZLy2r6yE;(@~(x46NJ~6{Cc|fzu>`2S#H_pT`cauwI+P}nYZD2 zPJ*xO>X74?@2$!z?D|lp$IInCxz8&!Z1yHd{kC-tD#QE%vjHdG;$;Pe}JkkV;wXvFc67o-a}& zua|%M|99Hd0?YF~7re`sv<2LKSI`+I8&og3e&H_J6*JQdPkU`y=4#aO?d_tcT=q8- zni~@@atX&hikHvgn4OdTd+lPO=3KdduXXO|KYCzu{pvf0{Yr*Mzu8;0P}u1_uV_D x(Dc^gFz@+0pDmj6UE%D*PwTkCKenB)-Rr|G3w0ecqk9GIq_wg#bX@^#}j} literal 0 HcmV?d00001 diff --git a/certificates/certs/IDENTRUSTECA3.cer b/certificates/certs/IDENTRUSTECA3.cer new file mode 100644 index 0000000000000000000000000000000000000000..13ea96533d20c1bf15644f14c7e3f14592254e6f GIT binary patch literal 1399 zcmXqLVl6gkVu@bB%*4pV#K>#F%f_kI=F#?@mywZ`mBGN*klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrKxF8j2Z+fOyQpyg;5pP=0=i0+2Q` zkQ3)MG&C?aHZU|cwlp%10&>j_jEyXyT!UirtWz>jfLJc+oLW?pnUo}H$Z^I7O^iy&-ezQFU~XdMX8?+GF*PwVGTgN1 zFb}^RHiboee%58nbNeTY&hS)3>cAht9n_qG0js z+4)UrKU~H3hX2>&`e0DO@^{%B%jrprHt}~vFHyb{FxU3u=l!4N&3_E)HHc6e|+yx zwbG>B-&QkTy3EAP$iTR`iOI~MiOI-778ug9d@N!tBL9;6PGnc@&J()uFzAuWLLNPK z{euSbAZcY5U_xmSdHbaOg8GqwXDwFW&wPJv<@qPbPtkx6q=281@jnX-FwM0Y2!Z&* zAU=ly8<1jRWH2xWi7Bw?7-$*ruyG}{c`&8|)$%Z+@R(3|%m$4IK)U2v8h02pZZ*(Z zptV4wO)aCOq`*pFKe;GJFD0`$Q7<<$2gK0_#(a>!e~7cAksgq1(Act|v2j6tTWwBC zB20aHN->h2JXPZqpe9u#15j!PQed``s!?)&DNHIkAIJh_44^b3YXFrbgT#aFli`Uo zH7K<#ACgFYGK)*BlQQ!Xiz*EoFSBuIvjH<6J0l}Y<1vHA!v0BKh+cttGSF8@nk#7QwW9puVnpUk4M@x^g82%yNCD<8MurU=jvq2yqjE_r z{rL>DgG}%CPj^+B{GnC-Vl1 zE5fzZ*>Kr~dcV#S_E%O%=F5LsZMsk)PC9haoUeW-<5=ZWuD-kTer7$(Y4O);3+&@2 zUy^$(ICt5UO)o9pH$A`B-zq5c>ftPJ^FJ*DMfNi*e(O5=J3fz}_CRON?6dCH=Ui9T zuM6Tj@vwo-x8dCzUAD>Dw|=MG{CBHih1v_drPmsZ?R%Bm)D@Sz%zpNmZ<=I-p~_Bu znKhsHcV!Dy8`c|y?JaD2BQ2j=%A1<4^5)pqZ)=a7NKv}o*>P*(vjqxOVs7a#)-d~b F0syi0?@a&z literal 0 HcmV?d00001 diff --git a/certificates/certs/ORCECA2.cer b/certificates/certs/ORCECA2.cer new file mode 100644 index 0000000000000000000000000000000000000000..76dafaeee92367a22c4471a3d2b7b5af4079b728 GIT binary patch literal 1037 zcmXqLV&ODsVlG<1%*4pV#HeJz%f_kI=F#?@mywZ`mBGNClLFH0@T%T3KIG2}7e0?BX-GrKxF8j2VQfq2Zq+(4c}P=0=ig0rK6 zoH(z6xq+FHp`o#Xfst{PI4_W4W@Kb&1m+s#l4qHcfda&8N$1p}lFYQs{~`w2Ij_I27|^ z&06|kW=Q@GPw^?)C*Ntj=ifb1OVE0@Oo!Q|JB@Z-n@>;VulTaCBlC8?$~z91O?j1j zm#*^L<@@o@i*lKpyq-H%VqNB2TW-!j`cR}VdVcavrj*4eyZ*kNSa(e5?r$N_tb%1* zRx5om%0D(=eW5N-+NL9}8Y|gX-tpVa#LURRxVVY&ra=?qRd8U+3NtePXW=kl15!+k z3UwB;8Zm-0L3zp0YP+ZHr7w>36E-IJP}sGCx( zmtT~umz1mQhjy3N4`P5KaSnt{5az1Pmmg zc!7B`a@qstG-hC;6V)u-R=RC!3?rYF=w4oRao2Os|NE~$SMoi7HCN%skszjHF4J#+ zm?>$tL-50VUC!f*Mx5CU-(KIAf9Kk=@4{#1qDhCg#9HnClLFH0@T%T3KIG2}7e0?BX-GrKxF8j2VQfq2Zq+(4c}P=0=ig0rK6 zoH(z6xq+FHrJEVk9HJ;OUh;$7i|i-;}hJuV9ONZPcwtDIEI`lz+)|H_1Qioyc&?&{}9~_@|po zkH7IWwEptq($^hNI^27V*XhMrMpdO1CkFRrU)Xu_@}ot52kp7ps|1;t85tNCH!ch3ou684CFz4Wfow(HHduM!J^I=CU$dY z^3A^sLsA_VaCqn&$buB`v52vV%$l);Z{xqIy7phcD7PgnK63hrcM#AXO^^b4mL^68 zAV#M~skl+5Bpz1++k{p37VV;5i;s~Q=A z;vPtW*v>#YzZ50|<^egNganj8BqfN#WRO&_eKI^kQ;Sl|@*xqMlUZD1os^lESX2p& zm<5e(3mTi-8XKVQNli}FO)1vPFG|)+&d;T%Tb$T9wAp~!hMkd-#mvCOzzD`SU}{s# zC@BGj7SMGFrvW`z3=$~<1`<%bz&sf_?E&*2GceJ0KD;fEa_n2zhQ=i^=eWiHZ|-%w z)n+ezECWcb4B&$E5-c)!%>Ai+(LNSDUu6 zaAM#=Pyb;{P*&X$)5WUpVs-kvoHL%n_J|oywmGP=if1>HE~DYtaMX-W0~0Z OQN*eD`Mt7>VOIgm5?Y4< literal 0 HcmV?d00001 diff --git a/certificates/certs/ORCECAHW3.cer b/certificates/certs/ORCECAHW3.cer new file mode 100644 index 0000000000000000000000000000000000000000..6841cdf5171a06eacbd51273d3908f24c8ca4cda GIT binary patch literal 1431 zcmXqLVx4Tz#8SP0nTe5!iIKyAmyJ`a&7D}#ZrA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_ERUG!!!s0r8lHd4W8Ip#1z21t4u? zAScdiU}0cpXlQ6`Vr*g-CC+PT0^}M%xdsK~S*K*60I^)sIkl)HGc7YYu_QA;Pr)X&Lb{ZwZy5Ot{WP-;2zf4a8qfAXF z&X7p#O#V0h63@&-KC`T+3%;w_kv&0dMWmv5FqhestaWl9RoxbBx9qtvnfLk@-ZqDI z3*J?S8opCY`qT5PAg1QlBv-3#w^)BD2%gJj&Y%6gZ+k+6C_~*Dh2)AS3!g>WuDyJQ z*Ja^~+-BR&Q|+}%T32*h)=#XAI-GZCy#m{*rzUnP_Z@FJAGP*9^!x65+X*iUcZRoe zYhG~T@ML0UWMEv}#1v`J#1v{E3k*V8J{B<+5mSa4PIuovm*YQv;CNofvSY2kYuOFt zLDI@Bz*N#8^7cvl1@$8V&swa$pZWgU%JWZsH&G0-yLVdF|@^I%K`s^wus;W44`m<<|FfON^TG#)T$+-qR6z-WO% zn_fmqNr9EVesWQcUP@+hqF!!hj(&P-36O6OjDJ-l15m;QQed``L1W8;#>NHpZM8Wm zi78YSnK!laV(fhBPsi;GKBQ$q5wdu1oJRzkps+rj0_W97?-d7eC^?_`4@V>6(88k z_rKz6kHP~Lwr(GWbou+b=GW(^>ZR;A{ciE(Lc`8&`)2Q4bmOPxythv@zADH~nWYw4 zDt+#$(5YW`Cw5jPZDM>JX{znAhcRIWpM@k(#r55$Jx!siQx|)GU*_h++sk@oheqHo z);nt-KFXEJl?e7*t*FIwhnZ=5{4(_!1x)#vY@;>yfkvBzKqgU&)G zhW2X)i;M36{+)d`Z;`*`QI+5z!OPQ*1T0K=aFx4sy5)8kmY&S$X@(zWey!|@{XD~| x_k}~{hR>gUKUyzwc(EwUC7VC~q+=^Dhx66M3r}CY+GSV~q0e+TYzfDT0057x?5_X- literal 0 HcmV?d00001 diff --git a/certificates/certs/ORCECAHW4.cer b/certificates/certs/ORCECAHW4.cer new file mode 100644 index 0000000000000000000000000000000000000000..560f9fa6d45748b91cd17ee035792c01fd9ef709 GIT binary patch literal 1396 zcmXqLVl6OeVu@J5%*4pV#K>pB%f_kI=F#?@mywZ`mBGN*klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrKxF8j2Z+fOyQpyg;5pP=0=i0+2Q` zkQ3)MG&C?XFf=qaF*G)a0&>j_OpOhoT!RAgtWz>jfLJc+oLW?pnU^Ve~_~R$XOoY3MK|kj7rFUW@KexZerwT0E%-lH8CG!n9uTUsp_*%v=?JxOmFdhwaW= zE-9xLT=dyn+_%d(cZ$=}IS(&;t~eyIHfek6gXf{5n=YDe(VhJwD&IA%!hOHm&)oKl z{WIJeWRIOzh|N0wH@dLm$npa&pS$X!dcxs{VcI>(lXDF5dd*^e$Mxt9Ofr*~R6}dmXu=8Z&)wv=)E${J!67_Lh#9 z$KU@5c<|6ZLU(pvTuI!{eW8}~TMiZ-mx(Sr0Vbk016dHC zk420{Bs%2a{pj+$x?i3rG?#}Fg~x=#V>W0!0MaGT(zwH*ajSvO0<8ra zZE6`MB?VUc`pHE(dMTO3iF&!2IUtTcF!F=^{X?7`jr4$AgT|Hxjg1TH+iG)C5@G7o zQ;L!F9kOH%fRE?7JOJP#U`9KyZR{*6E`2wgU86+NTpA1i#sX?h_ z`H&RqlUZD1os^lESX61yc$tkun+=%j*clmF8jl$?9yYLoi5M`o>0$FtW^r+8YD!5y zl9%E=L-Y#FlYzcM(p*7XuNCDN7b9|BYCvLU5zJSpXx127Y*GD|oO{`nHMDBl%;L50WS0VoY zz4x2jEO^g6j=ovO#1W*T(xeN7Vu+uwdCJp5tS3G-#y)wX!4Y&EzSM+()l_|_N{JncBmH&Y(6V4 zP-Uo>;}CrQ=e-Y$_!ZW0bMjZ4drsh(v2>c{GEVLD)lVeONUT2{u|a)9fO^G}L-KJh yHI8pI?sWZ%@L@Fk!uCR_T3^me%a2#|b?oO%#{-#WJ;6=&IqqH&tlzK2DFXnNi`)_b literal 0 HcmV?d00001 diff --git a/certificates/certs/ORCECASW3.cer b/certificates/certs/ORCECASW3.cer new file mode 100644 index 0000000000000000000000000000000000000000..bd15e82f59804994244b2b87451b0f0c90476e62 GIT binary patch literal 1431 zcmXqLVx4Tz#8SP0nTe5!iILramyJ`a&7D}#ZrA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_ERUG!!!s0r8lHd4W8Ip#1z21t4u? zAScdiU}0cpXlQ6`Y;J52CC+PT0^}M%xdsK~S*K*60I^)sIkl)HGc7YYu_QA;Pr&|tse62c`#mJwy z@T1*r@yRwK_YIoXu1od$kddXO*{O8X%;|59=_ze7w(pv{&yT7d-I@EdxcJx(^SAr< zh&?yr*%~S=yV#29?APn;H}?xAXkOX2wmG@OigkIxkz^aM%Z$g;7R-L}Hv6711IzZA zoAli1c&qwg;np*3syw53aTrXDxgViO)4 ztGiL>f60OVI0e5~DN`bxLoeW$lE9F7u1ggJZrJ~e&+jYE6+bceu@TsAO-x4jQ?3!fC;Y6KnTPa2Jtxz z*nkuhBZGl4NKAo6$3V+~hm9+t&4V!&sFsHjg~x=#V>W0!0n#PU(s;n2aj${N0;2^6 zZF(6cB?VUc`pHE(dMTO3iF&!2Ir{0TB|yGCF#c7I3_uAJNP*c#28}HX8XFhXx7FsP zB*OHirxYXfCg-Udr(n^kYLuK`3X@9C2eLr9186WJe*l#vgT#aFli?{eH7K<#ACgji zGK)*BlQQ!Xiz*Eo-?4FMvjKA-J0l}Y<3oeSdj|F}5d)?+V;sKnEG{lhO$o`z?zLG+ zCN%ca)`O0SOqdGwlumL{esM99ctB!i5zND=MGi3gF*3yV`gL%u__KqFX`h&MwB3xe z9W8Sc9ap~Fc*=R@(b;QzmV10FZTY`q{_D1v26?-jI_=o%O_*+^`%Sy5sarc~=_z&Q zjeN2FA5Jyu*hQ}txbglNqeg^bikZmFw#?ckdb_mW9>1sNtaNbcy)(b7RNC(4@fh=; ztlsD*a?RVR{CIoonj6xSYv**VdA;)AxlZ+K8x}G4zx(Rj)9^d)sJ(N+#?G1uP3{t@ zzuD^3nG>5$lHTy{5SnH&D~ogX7NZ3YvC?+y8@~ literal 0 HcmV?d00001 diff --git a/certificates/certs/ORCECASW4.cer b/certificates/certs/ORCECASW4.cer new file mode 100644 index 0000000000000000000000000000000000000000..197deee1595b49bb4f6d1afa78ea7cbd8e60a012 GIT binary patch literal 1396 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 literal 0 HcmV?d00001 diff --git a/certificates/certs/Thawte_SGC_CA.der.cer b/certificates/certs/Thawte_SGC_CA.der.cer new file mode 100644 index 0000000000000000000000000000000000000000..14dfab308e727031d1a16fdce96388a53cb51805 GIT binary patch literal 807 zcmXqLVpcY2V(MAI%*4pV#A3j}z+}M7#;Mij(e|B}k&%^^!64p{+klgeIh2J>m?<>a zP~1Qi#NiU=3rj7^49-l?(^2ruOV%?qH!uZBa0}}>=Oh*vD;O&TlqTh5CMyIKW#%Rp zRVp~A7L{bCWhN(L=zfI*ZvuOWzQWMph=X=)i| z;Dh9VC`Ut817(Nk>Sea^b5VB_3O?W{;QRpxX_-v&}Pk<6Dhxw z{}_3*PuZK_uuK0T%j5&be>jbmUvigd7an0gcIoUR{jZ$KXa9RFW!V4V`R9)9x<>bA zm_6fK%TRqJ#ml;-l=)M^q*}hDuZpWP%~}jgC;ZrdJf}mNZEDTQrz`H2F4U>YxPSGO zOnXFvBoi|u1LNYxe+G@e4TONMmlbAY{LjK+zy_q47#R$>L1O$YEWpTOGZ19sOlb39 zZ2RHF$OskE0LcroC>qEwku{Julr#{B1c3lB3d#~oQhgGWQge)T4NVOUK`P~0vdsFtF3>9hM+-=^feFYORTfdxL z0GWXi6S^k()xCvxFHMM_&wZ|JpKxIR-N%g2**XjD#`79T6kCrU@ ozNn@;!KVBy-#HJadPezRV0ej&6*#H0l literal 0 HcmV?d00001 diff --git a/certificates/certs/Thawte_SSL_Domain_CA_der.cer b/certificates/certs/Thawte_SSL_Domain_CA_der.cer new file mode 100644 index 0000000000000000000000000000000000000000..2564007596a0738ef9aa71b380bed60f90c8c0a2 GIT binary patch literal 823 zcmXqLVm3BtVw$snnTe5!iN%0{fzg1MjZ>@5qwPB{BO@y-gF)jFLv903Hs(+kHeseH zM?+BqVGxHym?u27xFoeGPr*5{Ak|RFKma7nF3btyDum>h=NZZxNQ1<aga)8VF9Q?ASJ0q3eJv(Y6dEB_i{3di5G)qbd!N57CV%Ht<_7;&oz(}=QS`f zFa=^Th!W>D1aXaxj7=>~Eu##AQGKaupbT-k45rgH0!k`16?{rk^k6<@hWju$*hj%7 zKQ}QG7%Ywkjq{O1laZByxv>`*qMb~QjSL@R?{3`wsc5ObYhUuWDc0-4{*~kyYEF5) zjPaN9fkcaZFGfN84+U%?&8_;EbPmkToG<8jSSN{r-{0s`>+PZ+29uqShrj)8zCi82 zZotIiM9)BtIia2L|%e@mG`z|f~ zm=pR+?`e?!#7`$4zJ0$Uxb8&G1n!UCIx9GggtwQ^o-viFYxZfw&IpM!c}M^7eO)S@ zCiT&XyYY#{=~XO(lh4i;)6H9uA8nT3@~Zc3rz7)et_N#Fe_hbH9UZ^vg1S%Ey1Ub6 Q8@ou|-yX*@L&hr^0ICE3eE#E{2;3narW%fY1C z*5jnDc53qF6SKyVl-)l6|R%a>M2&DjS$qE$!JJ=6Za74HHx2 z#=@6e{+pF`_iOJ|mF!I1rugk;r#^4~goA9;6T5S4_ncSms`541TeY%^J1SX6UxLry zTh?a<$Hy`Ug`Q9|_U)ObFRv`0_GkUpn>WRom>C%u7dJ6=7&I}p7zhEwT2`2m@jnZP z0UMBFVq`Gj1Bvm2#8`mIt<69e#1~{yGf-Iqj6g#<0~tsJi3Sv9mL-;?`XnZ$=9uUj z8JJk;S{NG0f|T>Ih_Q(9`X4%aOL&5k_}zdQt}lw-e~L7u4CF!5$}GSn+92}wN&5x$ zBLUA^tiGT5{@Tj(PmrIYfiXyd0*j7;mH`hNS3;WyV=B-YJd7wjCKMjCLE{OKE_s&5 z0|t$I4NMjoEih=)%P1)+u+rC0F3QnM$t+IP%gxNuPfslY^6i1?UDe0{l;VLDm~CXx z*s`FpaY21sZB9xeOka9RF+y*0o~m&Q7M-d_$@!%)spNbh3zY4E1|u>aP)RaKJlH-N zp7K+JQp@roIlw2gxWqasGcU2I(xCAj8;3RAU?%&gW zf7)4&N7G6eCijvtqOO^ulN;^hp*Jv_&bt(o_Xd*!T2 zE9d^zzp7<;^<4fV-r6%-LPD=jyzuZ4xv|3MsZy)DcTH7WDf>*#Y30Y($281sJ!LcH zLRjg%dGFqv2<_eNbm(e%PFzn5P-}m;?|0@sv8lJkbS=W7o1g~O( zeg2GW=2y-iRXy4=WSs(Px13`7tsEa$GqGAdIY(bUb*{lF_gQww_Gxk){_X#NkL|xV Ha<38rf;I)f literal 0 HcmV?d00001 diff --git a/certificates/certs/VERISIGNCLIENTEXTERNALCERTIFICATIONAUTHORITY_G3.cer b/certificates/certs/VERISIGNCLIENTEXTERNALCERTIFICATIONAUTHORITY_G3.cer new file mode 100644 index 0000000000000000000000000000000000000000..2868129258596eeb036d6f8a3995cd5ed5f7a05f GIT binary patch literal 1481 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 H_pbl|NKl3x literal 0 HcmV?d00001 diff --git a/certificates/certs/acClasse0_0.cer b/certificates/certs/acClasse0_0.cer new file mode 100644 index 0000000000000000000000000000000000000000..dc037a30ee6d751b0a694da575ac6a7486e5bd1d GIT binary patch literal 711 zcmXqLVmfTl#JG9^GZP~dlc0ftfguo?7@8RxTL3u>2E1&XT5TR}-+37sSy>qjWb@omcsGj~u_z zkMsH#>(pWjuFT;4KYMNJ=Xqr{|1!79cFnu;`*i5n>TQmXWmfn#dGOx4bM0P$!Nu(r zf3hcveA)JN`+vwaZuETQypWmARQbQviyvU|5;c-!D%21^oT4Uix`W@ z!P+h_DF0{4=m~&#^sHs}1Bq(#k9n24W2&&sY5IwdE9>w(d`9vibz&%DCv8 zTMR@&3KUrQ40sH<*f_Krs~Fvx*_n|80vILCO^l2T+#!F<^rqctJAdf*w5N>87Oxso zcOGNgsJuZSMTvJ)%hslob9cPx6j;%IwRKwAmBx;Ucjph(x6SPq`mluS?%N_8y>6L> zH#Qu;*?j-koySg>=cu@UU!-_n!d7ygy-rq7foWyjhZB#4-?v^nA**@w?TOPCclG}# zsQj2ByP4sxM9ilAi-JEV{4c)IYcZO_;1v_^)cpLO_c2~6J>R|oPQh= wD>ut5o<8eJ_AmY5v`=%jU%YvweVyB)|CyMBVIZH$1($CklJ%{M(}TVN0IVJo!2kdN literal 0 HcmV?d00001 diff --git a/certificates/certs/acClasse0_1.cer b/certificates/certs/acClasse0_1.cer new file mode 100644 index 0000000000000000000000000000000000000000..ec431c1344f97a393ba3891834c0112df93ea8ed GIT binary patch literal 783 zcmXqLV&*nzV*I>-nTe5!Nx;Cszz~Q{Oe~EJjeraTUN%mxHjlRNyo`*jtPBS7hTI06 zY|No7Y{E=#L52bbd>{^&FuS{FfUa{uuz{R7FVF-tBQua@1A{0a*TT@q7-T4jYhX&i z07DT2A&`;W!rYF|y3Rh1!NIP&1_q7ukzK;b%D~*%%V5yh$<)}$@bO5dMw~N?)<=>0 z7a_%&vkxqDJ-@x^^eth-q-Ccrub(X+Q@MMtaJ*Smyo2GntIqo-{Mp((Ph;+rh-;ZG zyI1`TzC7>ir>I#8$6JMOteKrDwaO-2_nU3ke%76(caQvFWVvwX^NgM8OBcv$`0yV2 z=kn`g{FEb>3}5RVe@JvjL-potXvBVlof~=~rOkGvG1cV&l+i ztYUO$W@k1KWaCU|^I&ZI;l#)YavUQYa)<)smbrC$=|G7D%X1AK(=EqOW;kvrpX+?_EAQTi`3!Lmc>+R{d)Mu) zw^ICYa`x4;Twggpy;?hgD_8a0pW>r&r?!94v5Ok*AcG3x5y&GFMEKn1d;M($e>rSF>ulUPt{rP%b>g%<)W;L1zyVSJY`fuF@01HqO5&!@I literal 0 HcmV?d00001 diff --git a/certificates/certs/acClasse1_0.cer b/certificates/certs/acClasse1_0.cer new file mode 100644 index 0000000000000000000000000000000000000000..5d0f286a323a40208acd8bd2c5d111b92711e8d3 GIT binary patch literal 782 zcmXqLV&*bvV*Ip#nTe5!Nx;Cszz~Q{Oe{?;%z+F8UN%mxHjlRNyo`*jtPBS7hTI06 zY|No7Y{E=#L52bbd>{^&FuS{FfUa{uuz{R7FVF-tBQua@1A{0a*TT@q7-T4jYhX&i z07DT2A&`;W!rYF|y3Rh1!NIP&h6auEkX^#a%D~*%!(hD962eq;d+ol>RqKDg6n5Y`w}E{_x27GyF22tRxkSPu4in& zeQ}ze9Lx3{o07lsyZryWm+zDb&qto*w<2dNTYsI{qdzsjSt0I2%FFimIqqLCn+NW3 zyt_ci;OL>RQZ2fMRxC4W3Ql-3F*7nSE^gdl(6|;H8nXP1jQ?3!n3vH}*UCAJ2A|#Asy`mzdc*dm>7iQ%L3|uLul-}# zCBA%CW66o@bGMs!e!cvvZT_VO&01+)v6Cx24quqP`$^K7rIw{WJIbZ^GcR-!xXy8W z+G_c5miK+zj~*A;c~;=_l>goJRZkon-F(yH4;eH`P1V$BdQ^PGsm}h+>=Ux-8GmGN zMrqIZ)cCf`sdZZ5%R?!723!+)&iM=UJ&KzaKCj99`q6|bY>W8kTJMyp5)pD}W6nQP uliOWt^3!zZXMf&1*Y)3?{=~jgEa7$g{{Nm*aUt&984_jWtpISK&HL=Tq$ literal 0 HcmV?d00001 diff --git a/certificates/certs/acClasse1_1.cer b/certificates/certs/acClasse1_1.cer new file mode 100644 index 0000000000000000000000000000000000000000..236068ff86cbcf40c1076acb10f510c63dd043c2 GIT binary patch literal 711 zcmXqLVmfTl#JG9^GZP~dlc0ftfguo?7@C=x0NDl%2E1&XT5TR}-+37sSy>qjK(2+MkulIzFxSA8 zfB}Xg20|bsxrMnMopqgk9D{>hbqx&~=OMdMyH>HrspD4W=0gtA zOFnFP<=Az!`dHxmGoLcHO1Vj%I2CB_pJ&u?QKNmIF ze!uH%pZ0%r+t#WuBW#^$dCv)MCT2zk#>JTi>EN)CM`Za}#8^a1 z=kJML{a(i?D&)ncW9N4+7QfB&z(5`(t;`}}Al4xAe8t~hTTZcQ>;9A`t4~m_jElax z#XuCKK!JtNfX9G~jYF%kiqV~!of$bGfKkHS#K_1XzWHFB>A6+&^TbMQq+;Kev*~=9 zDYLUHz|*il>5JxDj$7|u^ho`mDCC@MS8n!na~#_P#=2{*^+h5ZOebVd{v>+bZsX?* zMsInQ0vu;v&~5w}c(B%cO0FkoyTt3$yWd{)H!}Q?I4gn6O?*Oq-KH{~UtZ~Z0<4NY z7vDI2BWnLvqi4ZId$iBp*q~-Bb!ORzc^`H@Ym-YkE_u}dzPtM0qOZRmb6l)Cy8iuc zwl}wpBcA>3eKq&7ezeKuZ9f^dJMQ}MHG9|NcK*)+xdo5EmT#2)VyvBAC1a*=VylvF u{L<6U*2?r5=O`6N9=y;}p?dn`4l%7e&;BR<@zFitnLlf4mvqJ7A3p(LQ4t0J literal 0 HcmV?d00001 diff --git a/certificates/certs/acClasse2_0.cer b/certificates/certs/acClasse2_0.cer new file mode 100644 index 0000000000000000000000000000000000000000..715f8738b0ddd1ed31d4b1163e580365d7d641dd GIT binary patch literal 782 zcmXqLV&*bvV*Ip#nTe5!Nx;Cszz~Q{Of1bUfwX}EFB_*;n@8JsUPeY%Rt5ukLv903 zHs(+kHen{WAVUEIJ`jgXnBCnoK-W1S*g#I47ifZ+kr`OGK@^Z{VQ6FwG871+3`_|a zU?^fB1TvCanA_1=*V)H0IM`L!$e?i^vP&3Q8JHV;7z`Ram>L^uTTJ-4^Q%I);O)mmD1)lf4*>+kJ8W}y`!bEa^XCZ}$b+PnStJa^8bqG2_}gpC zDK>50pVDOY3Cfjm(Kok1^sBOn8HliPXtM!hg`JrN&SEkU1?g8{;WOYd;9}#@YOG>( zXJ%(M5M<*_X!Brf`{BgM2yz@F8*+dGqn5dek&z**FaC|Jz^%`WCyvka32LsG^guoL zp3J=sQu&9r{87z$z93ynqWEYBQ^_;F40iGVVOwsrz29G3m3_veJ@vt6(G|_ISqXEQ z^>;qta@liCUSwt0#R)QhH2&psyUREVr#R`Xy&iM_+}@va|I4@C`daI@%>Giw7Om&g z8=q=7aBWTwsXa11=tM^S>+_2@n58SXxXwOMrMDxkIwn-5bphB%p!I80RTI73CjQg literal 0 HcmV?d00001 diff --git a/certificates/certs/acClasse2_1.cer b/certificates/certs/acClasse2_1.cer new file mode 100644 index 0000000000000000000000000000000000000000..759f2cd9d7ae07a3c0b88dc5cb0460d2e4d14163 GIT binary patch literal 712 zcmXqLVme~b#JFYwGZP~dlc0ftfguo?7@C=x8v!{C2E1&XT5TR}-+37sSy>qjSTVa^<~KU*|AjL{J|$vpNG4p82A?Y#+z4vk6rxE zdF741gKQzpOE2{ZJh$ES@Ae`r&x=eGaDCoYx6k*5H`klY{@n}bH?KdLnw{Ry z`JjFE`~A83wGZS@^&IY7kat3yiJ6gsadDBW zVtaDuT)*`l&Mj9bDv8Ryt*R>5n5hs{-)!I}|J_I4=Xg&*IcLJRUgmqQYi)Udu}{x# z-YjPosCoO~9^FF>{eSxXV}km`13R4jRgEgl?iIee-B{ttZ|AC5^xueM?%xkq{-nTe5!Nx;Cszz~Q{ObrZ-EPxCHUN%mxHjlRNyo`*jtPBS7hTI06 zY|No7Y{E=#L52bbd>{^&FuS{FfUa{uuz{R7FVF-tBQua@1A{0a*TT@q7-T4jYhX&i z07DT2A&`;W!rYF|y3Rh1!NIP&#s-b^kzK;b%D~*%%V5yh$<)}$u;Yo-k+bKHJy?3V zaX}PgX|rJdbn)N|&dgPwuX}761jH_}`EevW$s25_XbtNAJ$Glx3Ww07J1*=mLw%0y zIM?2{DCf}9C%u7dLJ&Xj}^p4q1Li#{VoV%uGxyV86%;gZLZ< zY(R>Mk-lEfD>xEMf*CY#iEbz-VD-W`VPq3`9Zt6NsD-`v!^-mnxl4prL=H6PzaoIUYz=fwEW4GgJ~&py3wanhaDvs2n_X8fam zW(D^1Gu{QrFNiKWuXRpej@A2x&$@y|CO_8-g@iovzm?Z>(Lnh^o_tI) z6&q(C*7}kDlJD&PsO>DgHdY~rKi@krak5`kQK^2`LX)IJ+AWgS`67p;%B2<^`f&QI zgv)JJqr3S`>WX~t92#Wb&#L+_lDqfobn#s}cCCeKCGl$tM9woLS?BZhck4OSoStoQ t@otO3iIsc#4_)2*a?O#Ii*2pGm8WR3@8qjmkI<|r`6QKh4Z+$K3vyimhcbIR-1S&=rDf7irxv4icJ(rxOG3`y4&HK%Q}KVUguY1+?|I#0iz1_r zi>In`CqLO-qI;q3#@{37I9QpO85tNCXBwn~14EXdk?}tZ3n)AdWPv`BiNW6&QWI?-R7dabGFxUK50X}9kuVTz5P81hZ?7$<*tB(jN|V(mC|AZs-`rv# z3R0lJ!e_u^z{SR))mX*o&dkn?91_4dVQyk%U`VM{65*8c*uB$xbL@33@7x7f_phyR zUemiNV3((gOvBByHB!NA8hswU=nhGI7Vt(TxoYv})e0vjUvK)t?$q3!-jzM8+|2K& z%)(bEo-Kd><@yv?J)H`x6$$aT`UM}wAN84*;>#szD{(x^YQ-C#`)1F0vd`9?De_vn zN%>Dkk4FDG>CT;d)8(bp#7|h1?e=;wp<=b%$CRHB&IKiFH!OXua`)ucy9IMr7kTFF zS{3rlm;2|{_w9_9Ydy~oj6JqSfZMscVhVd*<=zn2 qDSn%N_s`ALw*3Ex!*xQP$oAXoT1`ca&$?_>omwg_>whTg;}-xxEB+b) literal 0 HcmV?d00001 diff --git a/certificates/certs/acClasse4.cer b/certificates/certs/acClasse4.cer new file mode 100644 index 0000000000000000000000000000000000000000..df33b8f7f90dac26edf6bb795a7c1ab2f4dc1a96 GIT binary patch literal 794 zcmXqLViq%KV*Iy&nTe5!NzlN+z|g?J)WXu-($WaXVKCrj!CV7V z0tOh07zlxk^UFmvzyCm+x?HzM?n}SYQL~L6WA##!_XlG&4uAEqfZO0OY-24JM zq`i-nmGD2Z6819RbYCDpXpgHc6EhMk-lEe7f!1*$9x26Aj1+HAmRVP|H6vl!tlCIeBBLIoB+10Dk| zHV&=EDn@r^c2)yHHqL}L55~41PK=CDXQIY3a}y&YL&B$U;pv|^qCeF*e6XLl}#G`nKbZT?;}o-c;>f zbz*k2liG6~zDZJvJ=bh*XmvB}`M4x&Rm6$^AJYRbRy~io_SW;y+BCbnr4kpoZ~qr^ zKCz-InPHu5PQ~OpV`s(eK1ThWLZVm8q*TS>bKZcBp!d5Mpzc?>s(}#_JrtQnCs$#u0z4yi<0DSZj6aWAK literal 0 HcmV?d00001 diff --git a/certificates/certs/acClasse5.cer b/certificates/certs/acClasse5.cer new file mode 100644 index 0000000000000000000000000000000000000000..6c0afe59319e7bba6a2063a24058d1e130261ddc GIT binary patch literal 774 zcmXqLVrDXEVtloLnTe5!NzlN+z|g?J)WXujzzoPRU@+iiQ0_f>Nh@wPX4*>FB3B(1LNYxWd@Cl!NDQR&&c?ng#{R*Y+%303WN9@ z25dlziIKrT7U(}&J{B<+kwvE&Q+LHUw0{20E@L2aBJRD7mYRV)NLrai!a%G+cg4=! z72NVOkAG3dJgKF9x{Fd|L;rRBuL}4dKXtL}`@dx(j1^zf)z*7kJkyY>$~Y=nrds+p z?il;}`&@5?uTNI|De}#Edhrv8Y{MGKXHKp@oo(|XBKot#7W+qj5P%GcqtP4l)P;2ZSs?BjbM-7Eo9k$N~dKmXAe@MWleA%kakMlbz2? z=g(U07*&$H=|P`?JV;uZMZ!R=LFD<0zrD7cV$;_BDNRjsYTahoH%FBn5wqf>7f5+Ho2#X-G3UpT{oXu zZF4aERH;F-A_*INR_I+3)}fO`Gom-^IO8t+)C${KVN6<@>y^VE4x>l O2~Wh6)B7u0jRFCUm;Dz2 literal 0 HcmV?d00001 diff --git a/certificates/certs/belgiumrs.crt b/certificates/certs/belgiumrs.crt new file mode 100644 index 0000000000000000000000000000000000000000..7f230eccfca88fadef927c08f1760cd783f4dbe4 GIT binary patch literal 1023 zcmXqLV*YK=#PoOpGZP~d6E_P32z+KJID}zC}A-4f18*?ZN zn=q4;tD&TUIEcd~Ea0A#pOlyroSB}dkXNQ#oMh&tTBR$i>ve$jESFVc|;|H>b*q!u+}GR<2mBvEBE$!fS(xQKerWT{?fl zM`VUm#M3Hqw7IgnouxQz7kyuI3jrm!ZFaOSWK*PO^@&o$bYv4hoNUC4|uyR?r6 zFWw(nJvom3o>9M0$*O1*<&Xofa?brTo3w&c{MAC;^Er=OWbd`>8FSl|JW>p>n5q}^ z;OQ~LpSK-;Wi4FNHF@@OMYeWX^~*;Vp7hy}&&15gz__^ayFud@a16=vGcx{XVFAWG zn*l#COl5^Zd{zTyAY~v665wMIV-XSfz!Nq*@m09hHq+_3^Y88y>AU^RzzHO+z+!D+ zX<*LAnqa}m$Y`Kvpu@(Y%?3;@>`aVe3K=CO1y=g{MX3e(#hE4fMU{G~nJIcnkVpg4 z238<5j|AnqDo8zjImXkmq$1i2_+Av0pXWg3;Q?b@)%& zW(59Y|9EQm<4W(cS)U~2cf_!V-#>jPBBa6cc2TNm&8>zHjT)Snj^+tO)<(o$`>pd} zx)J9={=3&~`w#lMUp)6}p2oY}za>sAyy6beWVfh`H?ci_e$Q#6##^cNwpw=24F4~< ztQ>g!*kg_04_Ov6cMhwxEkAFavN|t5Zh6p6zVd(C2B~IhK{Eb!Qrz#EQu+%Q%nqDT zxq9mUi`f&`@_c^tMDBP0ys3@HnKOQC9GaB-uY1LlPp8(lC#~LDllz)Kxa{Ne(0gHX Qj>^vPIIle=?WOp80LqMb9RL6T literal 0 HcmV?d00001 diff --git a/certificates/certs/e-Visa.crt b/certificates/certs/e-Visa.crt new file mode 100644 index 0000000000000000000000000000000000000000..20997e5a7fc6f902ccce2c7b397db99348e37702 GIT binary patch literal 1097 zcmXqLVsSNSV%A;2%*4pVB*^fnYwGq}*=5%|J4zP5mp@%?z{|#|)#lOmotKf3m6gFD z+mPFUlZ`o)g-w_#G}w^WfE&c&5@reW40bfsH_!!fxrNojGK&)xJo8FYi}DgnGV}8i za}vT22vmm%)-K84XMugxw)xDKt)0M`6UK&;=BeXh6X@v zW@>3{9wp9eh~Sz=8N}mtjDdk3#4+l`Ii}ck>PS;;KMs@BH`Iz-khG6)V=80qH~XKH!Xa8oZ)isy6(bj0*AgHn5M#3^>*K( z?Qi%$9T1+%xHDAC{cla$w+6elI~GqowAt*d^3=eoKUbXF>|Mjun-UTi<0E9*9DY=G zk5X#V5P5LUS6(O1`H0p6?W^suDAIL-epwM9fW&}0^SrDI(MT|w{sg6^&xJJ2ip#S+vTRm!3o?khW zhny&YnS!~Ak&&TaWB2wmOT6c-a=SdsVaw;I6^;(svBxLfefrg`wKB$T(mN&7#dq9G z`SrG_g!^!>T>3g^#Zjdr2R3bPh@8e<=gp-i$`i98CL%vV>|ioRvEjkRJogF zZJ&NAF7cUQnO6ALU!A!xHI6m~bt+zFJohi8+O*+S?L&rMR`CryEd}3F<+%Fs4? zT(WvcvDMQRQ5I$f#^nYl-~11qyphZ2+eD$|9AAoNS1dTWOf{vycb}2g=kS2SXB=B{ z=GPU@zW(Z1koU)@i&WKkg3KhqjYW;3>rI`8XFmADlO<_Q?kC?EtSHuo2@pwy!m#}e%vj@gTQ zcytX;emHqg*ZqE5=k9Z|_kFG|cZvD7S%z=&${kzsXS_eF{Ob4P%O#Fa9cTEca62+F zGcqtP&NN5|ds~*Dk?}tZ3n=6aWP!mT%f}+dB9if1#a7$3i1VEu(-AS(DGiLb)g=t% zLDI@B5(Z)oBF|U+?X~3;o3`#xX|nnR<;u9|n_CP-K?)RD_zZXqxY#(f8mk!Hnc10< zLjoB3%uS4p3~6en-rrVaE}ePq@hR~Q*Sf{BWUHjEF|Pb^OWy1ApKCQ!ysl+GH(USv zRnD^CTh3^e&ua6U>zn7HWt5(Oq47`N;s)`nvIk{1CO=&IkG0P5eK*ffgRu3Ryx$ow z>VCv@;ii#z)}Adkt3OqmC5HZyIPRHk9bMbgksOl9+1LCzJ^gXTs}C^`6YsF)ZJruq z?{R!CkMV1!4Q_ff(|Oz=S;iFd}R|?)y`@E|C#=usj~QdoX)NO zR9ng5o1#96o}AiS9gfZWvO~IH&bc$b&yzj=<=%AsvUQ0v`)g`w|5gKF+3wFG{`uq`d#9 literal 0 HcmV?d00001 diff --git a/certificates/distrusted/DigiNotar Extended Validation CA.cer b/certificates/distrusted/DigiNotar Extended Validation CA.cer new file mode 100644 index 0000000000000000000000000000000000000000..ca6362b9032cf7829fff35e405b6778d235b7b97 GIT binary patch literal 1542 zcma)5X;4#V6wP~C1T;Ymi=e<06(K?LMOnh4AfcKdh8b|7h-j84WDH46f{7N9q%@*c zM@PV=icvr0lz~wSC_yV7%m^+hR8;IsOR4&&{q@bcbMF1loO>?Nkzk<1 zn+$juf?*rn{WeeaOYR4!Z(miKvi8N70y4>xrswEK$q+;&;=o4cRA5QMuOX1AFfWoh z157sqE2?FevQQD$DmAxy zOC`X?feieCFVlzV=L;73$2pLhpF$x0ZvmcQ!QTRqe+7J{QK3>1Dni!sC1Md@C6-D5 zpB^3L_NfOD5r@}7);OSptY94k;WBx#v1j8J`z;cz5O`(HPS6ac?<}@Xzm^!_!8&O% zuVqPVN`&gVkzC`xiFe`1w)c+JgAx9$+MV*-#dtTX=M{6pxBkT2>lfZXz5bDy=>1EX z$C;}uyk^o(KBgZz&fRVKYmpyz4;0%fN&b7_y%=@wHm5{_IbNP_6_!CW$bRI!V|v zsYqC&pKx2wyIjh=qKC1VvObgfEf& z)g@QRL@7d*65&flh!Rz76AMwLH(;C9yApyyAYd8%3_kir6G|s2U#L|`7z*r?7!tk; zRjSz0k={au1W?RFtj)dXrE`aI4{ikwa+0W_ zr&#AVwzC?Z?&~DzzaFpf;Jo1A&yF{Kd_$yVT8x$7eJeayfXW-@*~M&KznxK9+qKuW z_epB4>F~09mC)Trnp@?1t=(N&UwZ!Yk9`ZEzWT#UeW~i<__y=(=?w)P3!+BE_ZSBf zDq{Q;H;;eE8NGfp#8J7hJa)k?v#HnA#D6;sjKrvkUM>kWOmg)iVmL;!P$TNdh+69Yd3ML z;cJGHXJcK0c_-}ITTD^ej|P@f?7HPq_Qf0Ii!GkEZn9!!^i;gdPk&DV!<{>_&crl@ zroIe{xTxVhB@5m~rJkvYL1-by5_V5s_rb%0$X@pcH^^HG2fm>ls!6gj1=9tWddiDz z(*vl@;Vbuh^XgYq0kJ_}ZIyP19zTs(-P}_4E0KJspPn7nOUZQ~?5V%?;U%5d*+?!w zUpJ+uV`@%Zm8RFi{+KaBaeR1JS!&h8p?t>?VTX(7Xtw2Mkl5GxqR6naQ|8_|kT46x z2F9RQoYwWH{*kmHQ<8RqSv%r&T0zlo#L}{WnTe5!iG|V7WWNC~8>d#AN85K^Mn-N{27^RHZUas>=1>+kVJ1Hx zLpcK(5QmFLG`J)&u|y#ywMfA)6-eeJ=B1?O85$WFfaIBZG_lGn_!p%o=4BQqmSmnb%MBoD8vbTE}7|> ze)%PdMG8)OVR}e*BP0U6J@d;_i!xF(Q$Y41TMxFoiAf3B$Be8D%uP)E3(98lPF^^4!F zjK=;|*&pW?8BgQ;zNuyDQuQP19|Mau%Xg*c{qwoA<iYlk>CH^%5yh4(8t7JFl<(n%6p$>8$TWmVLWpQRnqiC4}8}dWN}MHt+EjitB|#o^WP; z^mXGp8T)&-|K5AQw}+hGVKHa9C%u7dJ5`8ZH8QBaPTR{TKEOiDo4I-8T-JX+TZYK&Uob{Y5)pu)7 zy2H+eaZ6&*vj(BuscoPMG!>XTm9Xc|p#1z2Shj3pVVE)Pi-9M|8S*Sn1`Y;x3v3ox zwOK&Dm|T>jhvXxWCtdP$kusQ1Vo7RoiF1&TuDg*QP_=<9$S6J*F&2?Mu~V#XuC8WQ zElxaiTld|c)%~dpk+UJN-~nbsMuz@Bx<1=)>Ry%K`~LKo?HS^wbN#M;hU2`+qsNE8Y!%Z#ad_YL%f+i1%zjFF)m=+|8RxcZ>9#)6?TfW;ILp3| zJt5!Ny1D!Nf158izqoPO&)Flp;N}XSv#LRUTpJa>%fEEK8RFI`JnKMQNsiVGqgQ{* zck?b?WH>{quBPVsttD&UY}b>LEd1dSaLc)0r{(TJ2ldBWKZyEGyYeIEahs-__H}Fa z*B13B+QO$_ey?SGL_FYXN@lipwrgChzWAvqzw?K$TiSfJp6|AE_H#bZ>2t4LeJsuY zs-MwsmhhBFE+%#lZ>faU_5N?UZ-nw@sA*ZIt&4rUbLS?V40*X(6PPVO ztlGTfjAyrm$xHK-)tbj!YVut~_1`2$vYd21z35udqMCZmN!PrNb~~-O^6%A+u|C)X5HMQhW{_b@NHdD_u-}fuJs-3o^HJuv2^{M!sVKb6Ph#4n^<@K v;XKHZ*HdAA*qEuo-ldg8_I_v>$6B3M-Pn!H57(_KIlAPt-!AhR)lEAArK7fA literal 0 HcmV?d00001 diff --git a/certificates/distrusted/DigiNotar Qualified CA.cer b/certificates/distrusted/DigiNotar Qualified CA.cer new file mode 100644 index 0000000000000000000000000000000000000000..8fbb028c41a22b882b4138624f4c8ecd0d187e46 GIT binary patch literal 1541 zcmXqLVq-LDVt%=RnTe5!Ng(=a!kiTGjPr_orhk94u5~ovW#iOp^Jx3d%gD&e%3u(0 z$Zf#M#vIDRCd}mLV<==G0OD{7bGl@vXZq!rBo-M;8AyP{n1u!5VhTa|`6UX@j)n>b za&YrF8N~!M^V0GiQh-|XKw9dylzhZgMFHk(XmzPviMbf#$1 zLtE~x{_+bKeDJte*7s_r$J>oHi%NyPJcPr(3E%!VEz+R=|4+V~ZAq~k-9EZ9$Nm*c z%0556eYwN4e59?L*OgiTr=`CJh6miVL zM#>@Bf%(Dq=rdd7w_SHUS$Vhr;?=VfB7wo0?`JH1{grpquRho0b;A05sT}r9%!~|- zi<=lX0YhY+ffXBvHXAT`uro5U=o#o3XuH28}z|_!3$K7~3-$nVA_`nb=qi8kZWV!yLiHC?*YcM0t5RitYNz1;qwc zaD_|;c~Uvf`FSasAa@q)C?pmu(~QGQBka!Ij5VqS_uacWUnW^!t=o`EySAMz|V237_Z z3(OXnv>8EN3RQyU+M*o&B4AF^&q*vvEiQ2m^3h8!$}!*r8Nv?=Ar@dJW&@{wSw0pq z7Lh$Zzi(a2$zojja@VP+i|ZDt^e>V`PS?O3&D;bG(7+taZ{C0ImbEx8QT;EtNb2I> zFuUWN3@5Aihy8vkA0<9zX-DUg+pce)uU}ZJ!+rg?{<#bFH~H#M*StS{M00gSO-+|f ztJfa?_4Pi!N6Mbw_;Pfshw|#FiSOSyzHH~@@4oWJPbK_h(3VxH+#IVMKHhycWulOB zpsQHz-sK?;**WWWXYM$iZTeR0$6gKVhwc#$fo?m??{FY%&w9~3%X!M{;)QlN-@7l>z*bZEB{Of%&c2@((@)L( z9xG5^rRmZ6?Nt9NmF<~A`a0S9s?4j3WqE8A%5Gdc;dOK29;dJ3^}Ll!4^BQ5Ash3` zV`25r^FL>A)@9x4ZdomJU*A=8`oxnL)_w|B|B_k0*~*7wqP)1d>F*qE$FtWaM(W%@ z@^4na4GyM$X=%pX57R%eIfN~-I6GA)L-f0Y=%3IdYvh_j97IbrX1nj4(-Qmk{eufq zQ>N4h-oJ6-*!0of42+EY1s!HU4C z75!EXXBUgyUetcD>c?a|o9G+KT#I#MqFdet%2qrGU|GIu{ydSallP|0+ZaDlX2-GR Fd;rMUOT_>H literal 0 HcmV?d00001 diff --git a/certificates/distrusted/DigiNotar Services 1024 CA.cer b/certificates/distrusted/DigiNotar Services 1024 CA.cer new file mode 100644 index 0000000000000000000000000000000000000000..18955cf16c5e7c823e44ff986b3e4f6abacec221 GIT binary patch literal 1403 zcmXqLVl6jlVvb+H%*4pVBw!|180zdKJ@?t^#VL;WRV)m6**LY@JlekVGBUEVG8n`g zavN~6F^96S2{ZZm7z!B(fH+*joGzK^nSS{tiA9D|1`;4KW?@0Nm_kr~eu;v!qoIO< z9NaukMlr$6ytI6W6rk2TkXF6C90NIVUITLjb0ZT&VkTG|or%JR>Uub7L=qL1QOVVl;pj~{k2h%%>6J;^j>%s-doymW-!a9kTT*4og2|U=@^4zJYwCMeKkMPo*^=6O zSfuK7ZG%$IezZ&H@6>zo$$#B4j)krN7Ov!cc5Jns^Plxq%oA@dvs{+=Zic_aip!hV zr!~EtzvphzPd1jlLN_H;p0A!9+#Sip%*epFxQTIvK@;N=11mNTZ8l)^uro5U=o#o3 zXu- zV$x8n%gf7A?9@*#C^o2qD`Yarlge?<&r8V!xvp48A+cB?H#HB$Nlj76&r`@REm9~? zO)AbTNmbB5H%t?#z9>~8v7jI)GdVFSCsm;&Um-Ck2dt~0C_kk%xujSjF)u}-7@7q1 z44gr(muImturjb%V79=d%?RpJs1h{S7Uk#{0n@L3PGU)Fafx$~k6v<7jsYLY5Pnd& zumH0Tn}IBd&&MLhBJ%If6i=S~_c8UyJ_^nB7xP^EyD1epDFO2la}zKaml|~%lt?_> zz3oi#<2@5uQuiln7fh+LE-;#Bzp5+!wcf+VZ9HdAhwjL+6Ew1v77x+9w)4bBj%imn zsIf_`St=NqHMvdrR@SN#2B|A0EDW2QcW^$MXV-S3Zso)6vy*nXxUp8Rjh?bAiDSC56mM-J_t(+#AFQlFudcHZFx^L~_gYFKWE&6|C@~t_h z{&m8#X&y!qi!;Scrx|kxJv{v(sw2khR)g2}%vmAMw@!CzNo%@rJ!U(z@kx?&$)Dqb zn><3xmoM1B8@GCW&Q)`*q!iCNzh5W)OPZ0=JNsGB6fuF+nvl&)@5Eo9c#(apC*O5p z?q>(~zO2}oy{TubNL*~ud1Z&WY+kBUpG3N8yxRORM!71+ZmELIiRLGsGfPe{Dvo-v zI7zG_Ccd)fK<7tpRmLA}nsc7=9(J&r5hUtnYp5svARt6B=5K8M66Kn^w-Y}8n)miq zf!1^e8TG>GhlzZbwGYJH%TPG?TZR4Ym1T#&1oc0EwDe}9|GrImpEf4y`sL5M%#!oS zp6hD&x2O9VZ9>v^OP{+WbYIkM$B!c$9!Vy@{$RP~-x|6XE@!cBrK0mgqF#I|C<6^o0 Ri}GV1@8~Tg`2IeM4eg=akMlPl%Mn;C~!l@fsg1$fA zWvl#uZEw`%Fsr#fuMYm7+oC(y-=vT;O=bQ(ftQloRJ$r2f5y&_+Oj=&QC`CRAJZ2W zgg5-uoWQ73e@S}bwFQZvy&rUCtyVnp?(R@;JAO9iaFunm}n_NaoNr9EVepzBpW=dj7 zW`3R?N_5KuV@g(;MZ!R=L8K#N|ARi$Bi0t#N#8ZBTN+RBT=z8)0x1w?Wc<&3xh8jpbl6<8Yg88q%TXxzcZm(U`>*q+G<1guPKEC!8B4b)+dU}6-LhB~6Wyd1@L z{p5mTgDSW}CWAbw9OwMJluVF2i**zdixqNH^FW-`6ovdeh5XVYh4R#-;>?m%1r2n= zG=b`iQWX*l3UV@&6O(dM6-x3I5_59Ex(bT&Q%aLdiWL&`QWT1zX;II>8RQRn78?UA z1B(S_3ryOKpe}_fL33?Uj(!m^BkAWPmZTP!I0yOYB^Tuw@PQ2B2Zay|FcY&G$b$HM zEMhDoHU)xHmvrB~_HXa|s4UHQLa!6=1|z3yV1{OH0tRSKe$q4>;ehDFP5gQbE$6yD z_s1IjT>)R5zRFF1ox=K#?P#;_dW)zX=Tf_(SJ&PuvETdGT5w;$##y&L z6?2+vkIZ)5+jKdH*=k|hf_r=i)*HFn$`?F2nw`yHHRI#|Rot)q_G#@q=zGvZTlZj} z@w1TfYtswD?@YN>=$G-Y=EvVzLg|NhdrxeTmXg;@oTfN2qjfo-<;{H?B`$YLXodMm z-d*{x-t6M>_h)WCEVA$K%bl_3^2}DDoH{G%m1Rk?1fg^$=%ma*0X-I_R#&XxXW3ywP*I7(~W z@wg>imp|v%ftGWRen+a literal 0 HcmV?d00001 diff --git a/certificates/distrusted/DigiNotarRootCA2007.crt b/certificates/distrusted/DigiNotarRootCA2007.crt new file mode 100644 index 0000000000000000000000000000000000000000..00a5ab28647d753f1cbb757b4f8ee51bde9965d9 GIT binary patch literal 1422 zcmXqLV(l_$VlG<1%*4pVB*0U4YtBR-Kb?91L@z{4w(&9GW#iOp^Jx3d%gD&e%3u(0 z$Zf#M#vIDRCd}mLV<==G0OD{7bGl@vXZq!rBo-M;8AyP{n1u!5VhTa|`6UX@j)n>b za&YrF8N~!M^V0GiQh-|XKw9s?#f`PbQZp>SPtKoOZ@Y72Y5T4~j~Cqq zc2il7-q?0n>}JP?jqS1px7xPwi*#3=7r0nrwn(VDyv?ifS@nG;!HlJTZR<=TW~&HS zgej@YF?M?g7XEHJ6FDujBPt{K=uTcH^V8mY(!3_rX>qf%zZHuQoltti?WA<`BaVF^ zmCwwSy{5(AtRNbp-lX^Ik>BiU9v2DLkKP&eqtbA^7?II^N&?I8EdlJH=TSY&&qq&N5ic9@(DYcV;%3~ z-gTzDlzn}xv(9K)=Eb{bI_6)za57Et4qN)sDOIy_lYDB=JV8mY|dcVDOw}CsqMw9nQUsn+BIuobL3aV)vO7i{_vD zkg+#gcGLadeD=Aw`qGcP%bnV}U(0FY_T=ESk4}ppeu?sp$lm&7iSgQ)0@*tcKD{m$ znK+C2;46mIJ?wwZ3kfRetXr_x>cJwd8<8(HFH4v%StA%Pxpk}be6T6*Ya5`s&n~HnLi8o+vB9kGV9IG^WH^!A90wiSJqE@dW!LK!R?wRWgRg?o?~Y0 z6RI}Kr$-#Ij)?5s(9;vJ`9|C6jKxQ|o@aV1oI5BN<~?<#a>fmV8;4(S2n{^@^sn}g zue$~32Zww!k?g7DG&_|jt}4#mG^3cOyyWmz-s3BTe2y;hoRd{Wy+t;VXlt_CQZ+hDEp>5`lr$_I%9NhjI0CYZBZ2$lO literal 0 HcmV?d00001 diff --git a/certificates/distrusted/DigiNotarRootCAG2.cer b/certificates/distrusted/DigiNotarRootCAG2.cer new file mode 100644 index 0000000000000000000000000000000000000000..6f69f3f43765c7396a2c96f2e533d88d6a4b475b GIT binary patch literal 1428 zcmXqLVx3^n#9Xm}nTe5!Nr0Pym_kr~eu;v!qk_AU zp@M-N+(=GFF~Q8dw0wsYpzb`7ZoRx5137VC14{#Q17kyDQ%eJ*C~;mRWG-FY(8Q#K z>~%&~2IeLveg=akCN8EXCPs$+>jW5o``B$;!~Au|dF4qOON4EuZY}WdPJOEPSnVP@VJVctN4XKnOaebQ+rw3dk&NfC-v@qa-zRWK(w~>=z_A;4SkGed>x!M z3l>|duFjaW_L)iL`zhj=vh@`VSXWN8T*DK?czkKmhJJpD-bI$T?wCw*SvtYNb;rBs zPqM#cn%}s(s6qeg&u_kJuY(sXY>mIL_mr-T+PZ=nwo-cvla*&WcdoOsj!X|WGjrm7 zm@2?AD|qLNx`!KfDc_o{EYI%UG~ zYkp}hOx6u&?mueJNx4)I?_aPx$5}$^WzK_!u%kzxF|57s`!=xm*elMDoLq};1-tvt zo^koX$$dB4W0nRl?p=L(j~;i`emBA7B@v>lWb*!bvIR4FeZKt3@oaefRMj01+dn5v zuYaT1dFpam&fUO?ZpIEbJf`TrVlCReMP^~h_T$f9dev!fx~?c0&+uecOz%RA^_E(1 z5==cJ^eY#g^3i%yw?eQZ@a=wn>pa$t4epjt(jT=a9_d@tev*lqk%4islYxT)KQOV& z3NtePXJIv922uumAOU`m01Gfru^GsM_4P;CB)D(H}KAbO<{WjTuc5>slIsqgY^^Nhb}Mg zXSY03@|jw(Wy+aw&UuRMYo;v}mgYV>Gd)K3qv%$XJ9~b}y;*HPMSWA}%s*En?3ONJ zyX^c^#*DY0Ng(DcD?|COqiESqR%vBEK8N(Jm0l^OB-qzUh5vVvK7K#?^5(NYH{|;sI^FcNJ5TdMWaFG1zrWQ2*UJRv z>$o=li!E5Qr{VM`#Y2aalx|D-3G};eke;QayyS|^_pC+6_kW&YT@m_X@ATFc_co{A z^m3g_DeO<#RDP_BL`=$meS`%Lw%KO6qN zb6fTQo9)s439C#JO|?HWF?M;);ZjQcH5Iesx=eL<-gAtd2zXJFN>Rf?zabb zoctR9#6Fl6RyZTc|8d-(%Acpt9NiJaYIq{)+sgd^*^fVzU4FIixg+Cup5-pVnh);2 iznQHQapL-nN3u^eH+MhHDLa|moGVqCSM2lPz-a&%q*gHi literal 0 HcmV?d00001 diff --git a/certificates/distrusted/DigiNotar_PKIoverheid_CA.cer b/certificates/distrusted/DigiNotar_PKIoverheid_CA.cer new file mode 100644 index 0000000000000000000000000000000000000000..a8c7e7a1f4cf9db53897feaa057f92b8990d14c6 GIT binary patch literal 1164 zcmXqLV(BnwVlG&~%*4pV#KLHpxxs*!jZ>@5qwPB{BO@y-gF&Prw*e;`b0`a&Fq5B; zp`3vXh{Gi;8eEc?SfY@UTBP8Y3M6w9^HNgt47Ch2K=RDOidf|p{L4~{GEy^B6r3Fm ze)%PdMG8)O zVS0u@6Cif#AtVC4J@XM(A*@Z!Q*cU6Day<$OU*NAVpKx*E+Z=ga}y&!15licsfm%1 z;m+Pm%l)#rc3UrMeOS-1cHb6*j2Y}_7gQaYa=!3qm-&<6*WqPnx}W9zd)FR%!frQ< zCByQDiZ#*xbzk=G2-#6+&2H#vIXR?8!Makre|O@9+Kp?T$xqOm>&mz?Mc4PR{?6wC zSN*hNR+p8TyIrq*<23X8qBl!A3+`BGw=Y|z@@(!T73qE7{$A0S6t8+_#6Bg2HQ4!O z&Ytz|r}v!xyVu%9sPSXA_wKh_&aYPWm$-C>>Ca;Stxm?LBhPZ)xg79!L0Qk5y0k8* zZ);^Hectw4#O<~3b$x>ex$mOQ_PLa7S6~fq^?ku0x#%0uvvms(INe{qrYZJ##&(Hk zo!+yuf1RuR`B`T<6Eh6-WB|sTF&l?A8!(}; zGck&(XOxr_Sn2DRmzV3M0HY`m6h(S@Ir_;3#rg%=nXm{k;0Ku`%*gnkh1Gx=NEz^f z1o%M$EWnh=X3*FG5>RHTG$?Nn;cmOeU%ohFtE)RSdv;?;vD3o2UKAo3)0TVBE}-(!*Q~=?Bk5%cK2zDFwEUTP;207IM zGZ`?|F*5K>X_wmX`?&SdyX!ZSEBONMA8U!ewEN~)LoO-P=_U6?erfUByLUav^bMVY60B`kBczc+Dly??SC1e!1+!ss> V<8zo0=(0xY@5gto^531JQUL;>v2g$Z literal 0 HcmV?d00001 diff --git a/certificates/distrusted/EASEE-gas CA.cer b/certificates/distrusted/EASEE-gas CA.cer new file mode 100644 index 0000000000000000000000000000000000000000..85eedfcccb61ab2bb4a4d9b2b3efa7bdbd7f973d GIT binary patch literal 1497 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 literal 0 HcmV?d00001 diff --git a/certificates/distrusted/TRIALOrgCA.cer b/certificates/distrusted/TRIALOrgCA.cer new file mode 100644 index 0000000000000000000000000000000000000000..7e7789f73221af56588d820ad43dab49e8ed48bf GIT binary patch literal 1605 zcmXqLVskWTV$oc{%*4pV#KLIE`rm+;jZ>@5qwPB{BO^B}gF%=fw*e;`b0`a&Fq5B; zp`?L0h{MGr5a8{ZUzS>wk(!yJ5aJpfVyI)F1(IUsQ4R_6bo5a`SD+A-pI@Tj?5Lot z;BI6fC(dhNVQ64vX=r9(Xk-*6&TC{~U~FUpTxHdvAHG8tr=S*J}3t&g-%Z4sp$zj)(dt=j?SZ zI~M!vX!Bx^LcxVJze%h;G6Z9 z=fCVpV)Jk)4v`Vs^<&XFl}q+F(gVJqGTTz(yT0dxRPVQ6uV0Az-SVC5&%&s#5T(4? zF@N3Ko-ONIHgMP2ReoIjc@BG?lKYX zE5(QyF|5!J)eKvkjquC@~w>M0!!MrcOUKC93;QU?)tkQ zOZJB}M0s5K`S0m0sU3^f+|ATI#rAOi;+d=yM1q}PRCE4Y;%fi;*;W<#f};v5#oK>B zcV=Q{WMEv}#K>pR#K>j94@_XP!iH;$cAINBakXL)b8Y>91OdGPAN$(E&Ps#56z}aBj*`l=>W_#j11-W#%4u|&o4bZcQ)>p^&_b%QJtmn zBDM$eVhzql+J$a%dM-2P^jGeqTbFOKdz!N{taHWnrGJ7KR~^auab&h*ZDE16uqjXZ z^}1_^^e<$6G*^_+PHXF(X-H~fKi)N&~ovy)g<1S;7zV?$j zVpiE|T4|xn#fc@E zsbIwl&W;MY3hqV*a^k#(1_s84MuvvQ7KVmV;=D#cu8}d2Yi48_Wsrqxy^Mhr#ClMKEHfagp6I>zN$BRjwJP3-{2*P0JCJ0?UXWbAq~Ipa**lfSHjzf)(l@bN43 z&o~sSH+}7tmFK^OneDTg6|Vl}`l0e%J?RJ1$syM#ZJJnnGXH4U{rOuJKfN(HQB-$l z%8%3g9c%A~*8B~uzZBWa(7e2BFaHJAE_Q7-;B>~@bM8M$et5d!SV~{l?b|m#w{LrF zqPq5L@-%tFYrL`QvR_Ody>v4=&cw{fz__@HvD%=CvD|mRb&crBYkx^1oV5P5LUS6(Okevz3J$iXL`UUwp znaP={#rmL}l#-vTn_rZ!3l^-@1?CbykkR}gyI6oZmCc~B5hS3@Qe{xlAd(Q>{$fIF z@7hyli?1`BYP|5!Y`XNqs3j2wVW@crPuA5j&;l9=%(}{$Sr_CYg`oWW5?G#XVqr97 z{cjKka)LaIzk#oT_X5ua?rpA6?6nbNN`rSVT`(euF zNUds#d5L9}_MXPVvopC){Ga{tip9alJ-@ZKFPxPmb-hXIHs_UzWpZ(@ANMrAx%XI# zE92!?qs3C{MVjqzCOB@WF-Z3LfAaBhN$+*#uh zM{TD34LxQ5g$tT*6s@zL{-$#6=l-mT`~I|CJ~Ce+_stV7{m1L{s(#&D-qEpUrSmb# z?`u+Cdy5$~E?RfEJj!CR=S`^_X$FlSzIR*N@$|~HRGmT7B})om(3;Nk>6btEy<%u4(2fou`FZgeDw|-Ssocp}1tlKPLNPsfyFP znErp;%Id~Hv0$EE?4-AG+Ol2iJJv4Lj=J=w=~$`Ft;DOh>ss2sIA^Ip?yq$c2(CEz zmCs4@{c39mZqwH5ItG<9E_R8pUE6;A?YAQ}nV!?bzPk9H`E_dV%J3Trck_H#icFem MwC9n~`!vH|04}x1LI3~& literal 0 HcmV?d00001 diff --git a/certificates/distrusted/TU Delft CA.cer b/certificates/distrusted/TU Delft CA.cer new file mode 100644 index 0000000000000000000000000000000000000000..4db82a4e95528fea689c6915e072b928abed3f86 GIT binary patch literal 1517 zcmXqLVtr}Q#C&l9GZP~dlYrTeTM4H%C6+NLzwrO%Q7B=+%f_kI=F#?@mywZ`mBAq1 zklTQhjX9KsO_<5g$56;X0L0-E=5)zS&-BYLNh~syGLQg?F$)XA#T0__^Gg(*9Ss!> z>68X|KId{7;rZlDTr zfSgNePFjgVXkKPnYEf}!Nu@%5nnFlwaz|wj@obh`s}~?qO~&2d+X*`*jP_#==yz-asAVaQx93@Z@erW{7vw}#JIfo z`cbX(7Y2rNiJR(%%~=05>f}51@U?qGeWo=W#r)#Z22W^oUypWAB0h5x(r;PNlg6SLcxjBEWi_2*1EZGCb} z$>*rp?DrzI`peGSH~5J!aylcszHhy_=4Ef|73_6qLT$aXsw&ydKTSR3BA~hZ?SiHd z1{+g-skXhr0S_7Z!|!obw;zAw-7dI@^YKh3W=00a#Z8QxfFZKZz>1ASn+=!@*clmF z^bB+iv|xM##x}W(l9B=|ef_e;oXnKOlFa-(J(PHr2Zp|^GK++PSc6DM#{LI=rbnzT zvXj1RShqBu;JNM#jviTIM#ldv90qJaiiwfIpz#<;mjX-UK7+>H28}z|_!3$K7~3-$ zfq<2Xjm4mGsewAo5loC?(ojc~mzSg1uAf{`Y)}PP$YhWwmE)YBmy!u`XR(e#VzEMQ zY95G_nxc@Or;uM-q)?uk1WZP$3L5B!X#&+3r79#A6y#(kCnn{jDwO0aBWni(uY=KFe5!9tnC1|cK%F!;C3_Ugj`yFwd6eeUI)*beuc{?rKT6K?MRHx z3Cfs}%5v#uvYBAgdxi5$J2gAII1d>-xp}3w#h5MoP19YEe|vM&r~m#T;uPsRQKw{Q z%lp8ES%N>O{8}t|WdBx|2=3NXXXiwTUcG%dY281=c9xW<^4xx!L9C${k23B4_h9mW zeb0AFv7tIy@&|o*{_P7bM8p@FS9#~=WhIW zvijv#x%lZyX{x_YFHyVPI4%0bnui7MyQ1sVHXOg5eKs7-)Np$#!dlQ$b?Eo3Ls^*%u1bnCiX?sfwEM(<>q`62 zRc{g>_eU1ZZJKhn`{PG_W4m=fj{n=oXr2|b`HOQ?$;Qlr%{?2_J<9diU$yvM{ZW)J zSMt*670dS%JKORaH#$x1-o{oNt1<1>9rZoF;rU-Kvo4HY62Wz#N&MFPi(v!8Vnj#d7x+ juG!)w%;%Fn-_Kh$@pZMwH`Z#gpw&OK-%a-pdhq}ND&tLI literal 0 HcmV?d00001 diff --git a/certificates/ota_cert_tool/BuildAsset/BuildAsset-Prefix.pch b/certificates/ota_cert_tool/BuildAsset/BuildAsset-Prefix.pch new file mode 100644 index 00000000..558d816e --- /dev/null +++ b/certificates/ota_cert_tool/BuildAsset/BuildAsset-Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'BuildAsset' target in the 'BuildAsset' project +// + +#ifdef __OBJC__ + #import +#endif diff --git a/certificates/ota_cert_tool/BuildAsset/BuildAsset.1 b/certificates/ota_cert_tool/BuildAsset/BuildAsset.1 new file mode 100644 index 00000000..c1f9e640 --- /dev/null +++ b/certificates/ota_cert_tool/BuildAsset/BuildAsset.1 @@ -0,0 +1,79 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. +.\"See Also: +.\"man mdoc.samples for a complete listing of options +.\"man mdoc for the short list of editing options +.\"/usr/share/misc/mdoc.template +.Dd 12/18/12 \" DATE +.Dt BuildAsset 1 \" Program name and manual section number +.Os Darwin +.Sh NAME \" Section Header - required - don't modify +.Nm BuildAsset, +.\" The following lines are read in generating the apropos(man -k) database. Use only key +.\" words here as the database is built based on the words here and in the .ND line. +.Nm Other_name_for_same_program(), +.Nm Yet another name for the same program. +.\" Use .Nm macro to designate other names for the documented program. +.Nd This line parsed for whatis database. +.Sh SYNOPSIS \" Section Header - required - don't modify +.Nm +.Op Fl abcd \" [-abcd] +.Op Fl a Ar path \" [-a path] +.Op Ar file \" [file] +.Op Ar \" [file ...] +.Ar arg0 \" Underlined argument - use .Ar anywhere to underline +arg2 ... \" Arguments +.Sh DESCRIPTION \" Section Header - required - don't modify +Use the .Nm macro to refer to your program throughout the man page like such: +.Nm +Underlining is accomplished with the .Ar macro like this: +.Ar underlined text . +.Pp \" Inserts a space +A list of items with descriptions: +.Bl -tag -width -indent \" Begins a tagged list +.It item a \" Each item preceded by .It macro +Description of item a +.It item b +Description of item b +.El \" Ends the list +.Pp +A list of flags and their descriptions: +.Bl -tag -width -indent \" Differs from above in tag removed +.It Fl a \"-a flag as a list item +Description of -a flag +.It Fl b +Description of -b flag +.El \" Ends the list +.Pp +.\" .Sh ENVIRONMENT \" May not be needed +.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 +.\" .It Ev ENV_VAR_1 +.\" Description of ENV_VAR_1 +.\" .It Ev ENV_VAR_2 +.\" Description of ENV_VAR_2 +.\" .El +.Sh FILES \" File used or created by the topic of the man page +.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact +.It Pa /usr/share/file_name +FILE_1 description +.It Pa /Users/joeuser/Library/really_long_file_name +FILE_2 description +.El \" Ends the list +.\" .Sh DIAGNOSTICS \" May not be needed +.\" .Bl -diag +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .El +.Sh SEE ALSO +.\" List links in ascending order by section, alphabetically within a section. +.\" Please do not reference files that do not exist without filing a bug report +.Xr a 1 , +.Xr b 1 , +.Xr c 1 , +.Xr a 2 , +.Xr b 2 , +.Xr a 3 , +.Xr b 3 +.\" .Sh BUGS \" Document known, unremedied bugs +.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file diff --git a/certificates/ota_cert_tool/BuildAsset/main.m b/certificates/ota_cert_tool/BuildAsset/main.m new file mode 100644 index 00000000..0a2f72ab --- /dev/null +++ b/certificates/ota_cert_tool/BuildAsset/main.m @@ -0,0 +1,14 @@ +// +// main.m +// BuildAsset +// +// Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. +// + +#import + +int main(int argc, const char * argv[]) +{ + return 0; +} + diff --git a/certificates/ota_cert_tool/Scripts/BuildAsset.rb b/certificates/ota_cert_tool/Scripts/BuildAsset.rb new file mode 100644 index 00000000..fcd45ac3 --- /dev/null +++ b/certificates/ota_cert_tool/Scripts/BuildAsset.rb @@ -0,0 +1,39 @@ +# +# BuildAsset.rb +# ios_ota_cert_tool +# +# Copyright 2012 Apple Inc. All rights reserved. +# + +require "FileUtils" + +build_dir = ENV["BUILT_PRODUCTS_DIR"] +project_dir = ENV["PROJECT_DIR"] +input_path = File.expand_path("~/tmp/asset_out") +output_path = File.join(build_dir, "Asset") +script_path = File.join(project_dir, "Scripts/File.rb") +staging_path = File.expand_path("~/tmp/staging") +asset_name = "com_apple_MobileAsset_PKITrustServices_PKITrustData" +full_asset_path = File.join(staging_path, asset_name) + + +require script_path + + +puts "Creating the BuildPKIAsset instance" +b = BuildPKIAsset.new(input_path, output_path, staging_path) +puts "Calling stage on the BuildPKIAsset instance" +b.stage +puts "Calling stage on the BuildPKIAsset sign" +b.sign + +puts "Finished with BuildPKIAsset" + +puts "build_dir = #{build_dir}" +puts "full_asset_path = #{full_asset_path}" + +FileUtils.cp_r(full_asset_path, build_dir) + +puts "That's all folks!" + + diff --git a/certificates/ota_cert_tool/Scripts/BuildPlistFiles.rb b/certificates/ota_cert_tool/Scripts/BuildPlistFiles.rb new file mode 100644 index 00000000..cef35dbe --- /dev/null +++ b/certificates/ota_cert_tool/Scripts/BuildPlistFiles.rb @@ -0,0 +1,35 @@ +# +# BuildPlistFiles.rb +# ios_ota_cert_tool +# +# Copyright 2012 Apple Inc. All rights reserved. +# + +puts "Entering BuildPlistFiles.rb" + +build_dir = ENV["BUILT_PRODUCTS_DIR"] +executable_path = ENV["EXECUTABLE_PATH"] +sdk_name = ENV["SDK_NAME"] +top_level_directory = ENV["PROJECT_DIR"] + + +top_level_directory = File.join(top_level_directory, "..") + +output_directory = File.expand_path("~/tmp/asset_out") + +tool_path = File.join(build_dir, "ios_ota_cert_tool") + +#sdk_name = sdk_name.nil? ? " " : "-sdk #{sdk_name} " + + +#cmd_str = "xcrun " + sdk_name + "-run ios_ota_cert_tool --top_level_directory " + "'" + top_level_directory + "' " + " --output_directory " + "'" + output_directory + "'" + +cmd_str = tool_path + " --top_level_directory " + "'" + top_level_directory + "' " + " --output_directory " + "'" + output_directory + "'" + +puts "Executing command: #{cmd_str}" +exec cmd_str + + + + + diff --git a/certificates/ota_cert_tool/Scripts/File.rb b/certificates/ota_cert_tool/Scripts/File.rb new file mode 100644 index 00000000..8132f895 --- /dev/null +++ b/certificates/ota_cert_tool/Scripts/File.rb @@ -0,0 +1,141 @@ +# +# File.rb +# ios_ota_cert_tool +# +# Copyright 2012 Apple Inc. All rights reserved. +# + +require 'FileUtils' + +class BuildPKIAsset + attr_reader :ios_SDK_path + attr_reader :base_path + attr_reader :output_directory + attr_reader :asset_directory + attr_reader :asset_top_directory + attr_reader :asset_data_directory + attr_reader :staging_directory + attr :verbose + + def validate_path(path, isDir = true) + return false if path.nil? || path.empty? + return false if !FileTest.exists?(path) + return false if isDir != FileTest.directory?(path) + true + end + + def ensure_directory(path) + if !FileTest.exists?(path) + FileUtils.mkdir_p(path) + end + end + + def initialize(input_dir, output_directory, staging_directory = "/tmp/staging") + + @verbose = true + + puts "In BuildPKIAsset.initialize" if @verbose + puts "input_dir = #{input_dir}" if @verbose + puts "output_directory = #{output_directory}" if @verbose + puts "staging_directory = #{staging_directory}" if @verbose + + # Check the input parameter + if !validate_path(input_dir) + puts "Invalid base directory given: #{input_dir}" + exit + end + + @base_path = File.expand_path(input_dir) + + if output_directory.nil? || output_directory.empty? + puts "No output directory was given" + exit + end + + exit if `xcodebuild -sdk iphoneos.internal -find assettool`.nil? + + @output_directory = File.expand_path(output_directory) + + @asset_directory = File.join(@output_directory, "Assets") + ensure_directory(@asset_directory) + + @asset_top_directory = File.join(@asset_directory, "SecurityCertificatesAssets") + ensure_directory(@asset_top_directory) + + @asset_data_directory = File.join(@asset_top_directory, "AssetData/PKITrustData") + ensure_directory(@asset_data_directory) + + @staging_directory = File.expand_path(staging_directory) + ensure_directory(@staging_directory) + + + puts "@base_path = #{@base_path }" if @verbose + puts "@output_directory = #{@output_directory }" if @verbose + puts "@asset_directory = #{@asset_directory }" if @verbose + puts "@asset_top_directory = #{@asset_top_directory }" if @verbose + puts "@asset_data_directory = #{@asset_data_directory }" if @verbose + puts "@staging_directory = #{@staging_directory }" if @verbose + + puts "Done with BuildPKIAsset.initialize" if @verbose + + end + + def stage + + puts "In BuildPKIAsset.stage" if @verbose + + #copy over the files into the asset directory + input_plist_file_path = File.join(@base_path, "Info.plist") + if !FileTest.exists?(input_plist_file_path) + puts "The asset data Info.plist file is missing #{input_plist_file_path}" + exit + end + + puts "input_plist_file_path = #{input_plist_file_path}" if @verbose + + FileUtils.cp(input_plist_file_path, @asset_top_directory) + + puts "About to copy over the plist files" if @verbose + + # copy all of the necessary files into the asset data directory + file_list = %w(EVRoots.plist certs.plist revoked.plist Manifest.plist distrusted.plist roots.plist) + file_list.each do |file| + file_path = File.join(@base_path, file) + if !FileTest.exists?(file_path) + puts "#{file_path} is missing in the base directory" + exit + end + FileUtils.cp(file_path, @asset_data_directory) + end + + puts "Completed copying over the plist files" if @verbose + + puts "About to call assettool stage" if @verbose + `xcrun -sdk iphoneos.internal assettool stage -p #{@asset_directory} -s #{@staging_directory}` + puts "Completed call to assettool stage" if @verbose + + puts "Done with BuildPKIAsset.stage" if @verbose + end + + def sign + puts "In BuildPKIAsset.sign" if @verbose + puts "About to call assettool sign" if @verbose + `xcrun -sdk iphoneos.internal assettool sign -s #{@staging_directory}` + puts "Completed call to assettool sign" if @verbose + puts "Done with BuildPKIAsset.sign" if @verbose + end + +end + +=begin + The following code is here ONLY for testing +=end + +#b = BuildPKIAsset.new(File.expand_path("~/cert_out"), File.expand_path("~/bobby_cert")) +#b.stage +#b.sign +#puts "That's all folks@" + + + + diff --git a/certificates/ota_cert_tool/SecuritydAssertHelper/Readme.txt b/certificates/ota_cert_tool/SecuritydAssertHelper/Readme.txt new file mode 100644 index 00000000..e69de29b diff --git a/certificates/ota_cert_tool/SecuritydAssertHelper/SecuritydAssertHelper.1 b/certificates/ota_cert_tool/SecuritydAssertHelper/SecuritydAssertHelper.1 new file mode 100644 index 00000000..0971969b --- /dev/null +++ b/certificates/ota_cert_tool/SecuritydAssertHelper/SecuritydAssertHelper.1 @@ -0,0 +1,79 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. +.\"See Also: +.\"man mdoc.samples for a complete listing of options +.\"man mdoc for the short list of editing options +.\"/usr/share/misc/mdoc.template +.Dd 12/18/12 \" DATE +.Dt SecuritydAssertHelper 1 \" Program name and manual section number +.Os Darwin +.Sh NAME \" Section Header - required - don't modify +.Nm SecuritydAssertHelper, +.\" The following lines are read in generating the apropos(man -k) database. Use only key +.\" words here as the database is built based on the words here and in the .ND line. +.Nm Other_name_for_same_program(), +.Nm Yet another name for the same program. +.\" Use .Nm macro to designate other names for the documented program. +.Nd This line parsed for whatis database. +.Sh SYNOPSIS \" Section Header - required - don't modify +.Nm +.Op Fl abcd \" [-abcd] +.Op Fl a Ar path \" [-a path] +.Op Ar file \" [file] +.Op Ar \" [file ...] +.Ar arg0 \" Underlined argument - use .Ar anywhere to underline +arg2 ... \" Arguments +.Sh DESCRIPTION \" Section Header - required - don't modify +Use the .Nm macro to refer to your program throughout the man page like such: +.Nm +Underlining is accomplished with the .Ar macro like this: +.Ar underlined text . +.Pp \" Inserts a space +A list of items with descriptions: +.Bl -tag -width -indent \" Begins a tagged list +.It item a \" Each item preceded by .It macro +Description of item a +.It item b +Description of item b +.El \" Ends the list +.Pp +A list of flags and their descriptions: +.Bl -tag -width -indent \" Differs from above in tag removed +.It Fl a \"-a flag as a list item +Description of -a flag +.It Fl b +Description of -b flag +.El \" Ends the list +.Pp +.\" .Sh ENVIRONMENT \" May not be needed +.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 +.\" .It Ev ENV_VAR_1 +.\" Description of ENV_VAR_1 +.\" .It Ev ENV_VAR_2 +.\" Description of ENV_VAR_2 +.\" .El +.Sh FILES \" File used or created by the topic of the man page +.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact +.It Pa /usr/share/file_name +FILE_1 description +.It Pa /Users/joeuser/Library/really_long_file_name +FILE_2 description +.El \" Ends the list +.\" .Sh DIAGNOSTICS \" May not be needed +.\" .Bl -diag +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .El +.Sh SEE ALSO +.\" List links in ascending order by section, alphabetically within a section. +.\" Please do not reference files that do not exist without filing a bug report +.Xr a 1 , +.Xr b 1 , +.Xr c 1 , +.Xr a 2 , +.Xr b 2 , +.Xr a 3 , +.Xr b 3 +.\" .Sh BUGS \" Document known, unremedied bugs +.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file diff --git a/certificates/ota_cert_tool/SecuritydAssertHelper/SecuritydAssertHelper.m b/certificates/ota_cert_tool/SecuritydAssertHelper/SecuritydAssertHelper.m new file mode 100644 index 00000000..f47f290b --- /dev/null +++ b/certificates/ota_cert_tool/SecuritydAssertHelper/SecuritydAssertHelper.m @@ -0,0 +1,39 @@ +// +// SecuritydAssertHelper.m +// SecuritydAssertHelper +// +// Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. +// + +#import +#include +#import + +static NSString * const PKITrustDataAssetType = @"com.apple.MobileAsset.PKITrustServices.PKITrustData"; + + +int main (int argc, const char * argv[]) +{ + @autoreleasepool + { + ASAssetQuery* assetQuery = [[ASAssetQuery alloc] initWithAssetType:PKITrustDataAssetType]; + + if (nil == assetQuery) + { + NSLog(@"Could not create an ASAssetQuery object"); + exit(EXIT_FAILURE); + } + + NSError* error = nil; + NSArray* foundAssets = nil; + + foundAssets = [assetQuery runQueryAndReturnError:&error]; + if (nil == foundAssets) + { + NSLog(@"running assetQuery fails: %@", [error localizedDescription]); + exit(EXIT_FAILURE); + } + + return 0; + } +} diff --git a/certificates/ota_cert_tool/TestValidator/Readme.txt b/certificates/ota_cert_tool/TestValidator/Readme.txt new file mode 100644 index 00000000..e69de29b diff --git a/certificates/ota_cert_tool/TestValidator/Resources/EVRoots.plist b/certificates/ota_cert_tool/TestValidator/Resources/EVRoots.plist new file mode 100644 index 00000000..d7998fe3 --- /dev/null +++ b/certificates/ota_cert_tool/TestValidator/Resources/EVRoots.plist @@ -0,0 +1,309 @@ + + + + + 1.2.276.0.44.1.1.1.4 + + + llbNe1eWmJXQ4UFGaAb7uMYRBoc= + + + 1.2.392.200091.100.721.1 + + + NrErSfmBntdMnrw4D8ZWj12ssvc= + + + /rjEMtz5dprOrj3YkI/9KIZlZH0= + + + XzuM8vgQs314tM7sGRnDczS5x3Q= + + + 1.2.616.1.113527.2.5.1.1 + + + YlLcQPcRQ6Iv3p73NI4GQlGxgRg= + + + B+Ay4CC3LD8ZLwYoolk6GacPBp4= + + + 1.3.6.1.4.1.14370.1.6 + + + MjwRjhv3uLZSVOLiEA3WApA38JY= + + + 0jIJrSPTFCMhdOQNf51iE5eGYzo= + + + 1.3.6.1.4.1.14777.6.1.1 + + + MHeekxUCLpSFaj/4vPgVsIL5rv0= + + + Sj+Na9wOHs/NcuN33vLX/5LBm8c= + + + 1.3.6.1.4.1.14777.6.1.2 + + + MHeekxUCLpSFaj/4vPgVsIL5rv0= + + + Sj+Na9wOHs/NcuN33vLX/5LBm8c= + + + 1.3.6.1.4.1.22234.2.5.2.3.1 + + + dCB0QXKc3ZLseTHYIxCNwoGS4rs= + + + 1.3.6.1.4.1.23223.1.1.1 + + + Piv38gMblvOM5sTYqF0+LVhHag8= + + + o/EzP+JCv8/F0U6POUKYQGgQ0aA= + + + 1.3.6.1.4.1.23223.2 + + + Piv38gMblvOM5sTYqF0+LVhHag8= + + + o/EzP+JCv8/F0U6POUKYQGgQ0aA= + + + 1.3.6.1.4.1.29836.1.10 + + + T5mqk/sr0TcmoZlKzn/wBfKTXR4= + + + 1.3.6.1.4.1.34697.2.1 + + + uCNrAC8dFoZTAVVsEaQ3yuv/w7s= + + + 2KYzLOADb7GF9mNPfWoGZSYyKCc= + + + KTYhAosg7QL1ZsUy0dbtkJ9FAC8= + + + +bW2MkVfnL7sV1+A3OluLMeyeLc= + + + 1.3.6.1.4.1.34697.2.2 + + + uCNrAC8dFoZTAVVsEaQ3yuv/w7s= + + + 2KYzLOADb7GF9mNPfWoGZSYyKCc= + + + KTYhAosg7QL1ZsUy0dbtkJ9FAC8= + + + +bW2MkVfnL7sV1+A3OluLMeyeLc= + + + 1.3.6.1.4.1.34697.2.3 + + + uCNrAC8dFoZTAVVsEaQ3yuv/w7s= + + + 2KYzLOADb7GF9mNPfWoGZSYyKCc= + + + KTYhAosg7QL1ZsUy0dbtkJ9FAC8= + + + +bW2MkVfnL7sV1+A3OluLMeyeLc= + + + 1.3.6.1.4.1.34697.2.4 + + + uCNrAC8dFoZTAVVsEaQ3yuv/w7s= + + + 2KYzLOADb7GF9mNPfWoGZSYyKCc= + + + KTYhAosg7QL1ZsUy0dbtkJ9FAC8= + + + +bW2MkVfnL7sV1+A3OluLMeyeLc= + + + 1.3.6.1.4.1.4146.1.1 + + + deCrthOFEiccBPhf3d445LckLv4= + + + Lxc/femWZ6+levgKotGxL6yDAzg= + + + 1ptWEUjwHHfFRXjBCSbfW4Vpdq0= + + + 1.3.6.1.4.1.6334.1.100.1 + + + 1N4g0F5m/FP+GlCILHjbKFLK5HQ= + + + l4F5UNgclnDMNNgJz3lEMTZ+9HQ= + + + 1.3.6.1.4.1.6449.1.2.1.5.1 + + + ZjG/nvdPnrbJ1aYMumq+0fe973s= + + + Avrz4pFDVGhgeFdpTfXkW2iFGGg= + + + 1.3.6.1.4.1.782.1.2.1.8.1 + + + dPijw+/ns5AGS4OQPCFkYCDl384= + + + Avrz4pFDVGhgeFdpTfXkW2iFGGg= + + + 1.3.6.1.4.1.8024.0.2.100.1.2 + + + 3j9AvVCT05tsYPbavAdiAQCJdsk= + + + yjr7zxJANktEshYgiIBIORmTfPc= + + + 2.16.578.1.26.1.3.3 + + + YVc6Ed8O2H7VkmUi6tBW10SzI3E= + + + 2.16.756.1.89.1.2.1.1 + + + 2MU4ircwGxtu1HrmRSU6b58aJ2E= + + + 2.16.840.1.113733.1.7.23.6 + + + TrbVeEmbHM9fWB6tVr49m2dEpeU= + + + dCwxkuYH5CTrRUlUK+G7xT5hdOI= + + + 2.16.840.1.113733.1.7.48.1 + + + kcbW7j6KyGOE5UjCmSlcdWyBe4E= + + + Yn+NeCdlY5nSfX+QRMn+s/M++po= + + + 4KsFlCByVJMFYGICNnD3zS78ZmY= + + + 2.16.840.1.114028.10.1.2 + + + maab5hr+iGtNK4IAfLhU/DF+FTk= + + + sx6xt0DjbIQC2tw31E311GdJUvk= + + + 2.16.840.1.114171.500.9 + + + 57T2nWHskGnbfpCnQBo89H1P6O4= + + + 2.16.840.1.114404.1.1.2.4.1 + + + h4LGwwQ1O8/SlpLSWT59RNk0/xE= + + + OkRzWuWBkB8khmFGHjucxF/1Ohs= + + + uAGG0euchqVBBM8wVPNMUrflWMY= + + + maab5hr+iGtNK4IAfLhU/DF+FTk= + + + 2.16.840.1.114412.1.3.0.2 + + + X7fuBjPiWdutDEya5tOPGmHH3CU= + + + maab5hr+iGtNK4IAfLhU/DF+FTk= + + + 2.16.840.1.114412.2.1 + + + X7fuBjPiWdutDEya5tOPGmHH3CU= + + + maab5hr+iGtNK4IAfLhU/DF+FTk= + + + 2.16.840.1.114413.1.7.23.3 + + + J5a65j8YAeJ3Jhug13dwAo8g7uQ= + + + MXoq0H8rM171ocNOS1fot9jx/KY= + + + R76rySLq6A54eDRip59FwlT95os= + + + 2.16.840.1.114414.1.7.23.3 + + + rX4cKLBk749gA0AgFMPQ4zcOtYo= + + + MXoq0H8rM171ocNOS1fot9jx/KY= + + + tRwGfO4rDD34VastkvT+OdTnDw4= + + + 2.16.840.1.114414.1.7.24.3 + + + klqPjSxtBOBmX1lq/yLYY+glbz8= + + + + diff --git a/certificates/ota_cert_tool/TestValidator/Resources/Manifest.plist b/certificates/ota_cert_tool/TestValidator/Resources/Manifest.plist new file mode 100644 index 00000000..395e05e0 --- /dev/null +++ b/certificates/ota_cert_tool/TestValidator/Resources/Manifest.plist @@ -0,0 +1,20 @@ + + + + + EVRoots.plist + 2DSUDoeDGu7n5qcQ4MJuqSe+mPux2gxdzRsZ2CC6/aM= + Signature + 4joI/liDTHr0p0He4G8Hbqcb8O+hWxtwJOTTvr8+/AzFXeB+wpUDm8fDlNrDzVHgBfIsNdysrCwHhBf2pIPQYhJpA2UBr6Z2SNc89sBUcfxckSa2UfUyGOIH0JwOSMy/vvjn7mW/+6tdAdVyONodQwocZsy+cPT3ek5J3orLNuXVeLbXNP/C+tx05QCbgglPOwHhmOeTKfSD0FI5t6NevRD2iCDRd/GpPcjIVjupFWfZSfZD6nwqSHat5I+yqz1cqbnd/Po/pfBeQWc7La8qXph+5jY3wUYIrHja9rd0fZ8ne+OmKmZpn01obf6FvEfTnK0L3HVZklJmI+ZkOhVw5g== + Version + 100 + certs.plist + ddvbGaCoaSKIXoQByhxh5evEjZAaMdZPikDoWs63fTw= + distrusted.plist + fgUHS1biDcTRxgnxS2GLtf4Dc+q+Q+RUyMeXpzTX9uo= + revoked.plist + HHh8/j4++4pjm7gCOtha9CUZWV+4+C4V2s8aSSOuxeU= + roots.plist + rNmY9zrEPhSHWFzE8u9Ldm6Y6AjlZhALWWp4JKtqf1E= + + diff --git a/certificates/ota_cert_tool/TestValidator/Resources/certs.plist b/certificates/ota_cert_tool/TestValidator/Resources/certs.plist new file mode 100644 index 00000000..66d0d502 --- /dev/null +++ b/certificates/ota_cert_tool/TestValidator/Resources/certs.plist @@ -0,0 +1,97 @@ + + + + + certs + + 87xA8meJcpqggM5+uaayqL8IjZPsbaR+bNdXXW8PRiM= + E0bY+VpIdwauX3FNoAMWUtJa8XURfYDRsCFWDeVeNXs= + xun04Rf0yzSDZ1H7N1PAYnAKkyQDH2vtd3C7Nq6gL4Q= + Bf9xJrg1Q//oiG8HVdMaEaR18Eqz+YqRJ7I5NkGi9X8= + mFiPYDK+OPcrj+K8Q8STU2QKpTUWpoxyStYC3/+CWXA= + pYUhsDgBeIZkadtRVZrXg97JiC688jrVv1PNspzEZHg= + hbeHkAi7KNzu86r5aACDcefX/R0JG8+6n6F+IwSO9uk= + r0NxZoBk+80h9BaXV8NiLNOxhb8BV+kJbiQgTRbhdDY= + 6NroEpQIA8OoGS4SxAXdldJu3X54BLM3pmG/LggXufU= + 2zluKvIhNhWdi7Rxr3hWHqe+N3vH2ehA9cqFy/vMVEs= + RVy9Ta3/ALkTcEjpGIsM18AImk6r/UEM9+gqQs7KbHg= + evydAaYvA6LeljeTbUr+aAkNLeGNA/KciM+wsbpjWH8= + BkqdsZl/ZjaY019Fjv/st6fltETEW+L70n6eECwhlRw= + 73a5GGoVytvc4rQKnjD31Q4GyK44G9Awy7Q9N5CSz4o= + iie5BwN3Z/G6szlr8CwJiXYGMHSLcc72LotWfvs7+q8= + A4kXVEH4hHHaNaO+XOmxjnzMr78kXPG1/TYC9uoD1YE= + y7wlQrstwTP0iH+sKIrBMUQi82CQYf9zsZfbrPARip4= + Yzi/MWMVvV4+Ayw5Q2w6D68LFU4+HzvhkQet+jYy+gk= + UXiiil7F+h/+eIM0b0E7dezQ1N4ufX5QICDLiAlyvvk= + fv1pgg07tyuJRrOBiG7oqVz1k5v9cjm55y6ejZolKHU= + LgcILt6/OJFx0Ki2N5Gb56J6d928Pknb3wOOlBsaMxY= + TL5AMGa71zvOIkr7nm8eZt+JIKxmrLYh3zU5MRZD+t0= + ysaAhBVUWvmZhmLXfnJNCdDmIWwsWbKJ8lGBVb5aFZE= + +b3yMa/P4GHOu6ULupJX9U4UFAZ02nghFjijWZgeCUs= + 5m/XCjYDEQpUKDr+EiMXV7pi5H+jlonoOB3DxCXehGw= + QXYKQ25qATbfXvqwX+nQYG/bN5bNXNpjRYwZh7i4XXs= + C8YCYLvgOctLsfGbG2Ot48/cxgXlyeXNLvL+GTGlRdo= + bw5MMCCAKotMNKlCy8pjjf/tWps5oCoSrvPgbDN4cHQ= + M0kfxYUSFclMbZRORCJizE/l3ZMZ3iYc7C01kDBNj64= + kaQBq3oIWuOwN3Omj6CvIICd2/oghP72NJ7yY/fwuYQ= + NUryGKtaRv6qys1iAaAMoARI/6w/Z+c95R6a6dPTabg= + WiS3Cysta2+hO/yvHEgEw7PeFOw2Y0NfHHChdP3LXxQ= + vIvBRd1nro1rTvBq/fkIJ3z1dK3OYxcVPR5T7HLa87c= + ByNleW1wRFtQgL0ZO0as5FHBTV9DO8qRqRs+a2URmQc= + koATSiHH6fCbNzSEwKFh7ZVBHT63tcnLbXxh9iBP+MI= + bjzPaWZkZKTDJGrsvGw10jj0RSjTYnjFskajhjEEKkI= + Jzbg2hk77WGBVJiAy7HxpIOHGhs/nQB6U3sl6J3XZ8A= + 9C/cmuE2m4btS5DAjJVcFtk3fLZ8hqNTyr7wuuDg4tM= + YAfVMQNOBfhVzd+2z8OJ68f8RWCwDV7LjxoDXBP6V8c= + hLjsSvFsGj3wa7nlCEPo+o3MN/l6L7j2Jm4UWUzygzA= + ToHhj7Uy/UlGNZLtPN8XaDJUTa7CP8t4g3HEpfD0M0s= + 70kOlVvTKY3uOcoehb7TgbyQZl+HKnIdXN7Lh8iLih0= + /98zYyCf3r2uRgMACvYTL6q29ctoW7ez1bG/c9It/u0= + B2anQxAGqSNQspdUhGen2qeleUTb4EGzM8mnLh3W3KQ= + xpy5M+kHrslK7Ll/QIo7R6wN/W3Syj+bL96ZlHn2pCQ= + VHu7yiQXTCQ1KGALxSGDAYBsS+ZPIQUmej7mNEwZxx8= + a7Uyd2LGwAE+cVG6U3pXs4ZXavXjrz03nl5xpHNc4tQ= + qVzNKtHJqAQOKomMPaFkYujsuYzTwO17C29ZE5NrabI= + IQnFMaC2f4qYzH4/x9b6f8nLYEUl47yxNLGMIeDyMJs= + j4sE9GOcQN8iyR9/DyxPf+eEsV+l4lCyPdciNJIHiK8= + pTQZG9isJl68Xg2vmliYwzorgQBgas9OmBQ9kPtZx64= + gn+UaQO+PgXHykCW2mpJCaZT8+TdKatQ49gVBKPQfLw= + T8mVFqXFsnp7bvWuN3r/ro5q06ftfuOP4Viz7g+Vcz4= + lBl1tJ8yJYr58DYkVW3uE7A5qdfHFaio9vdwjCIvSDE= + LQpl3AeOUDfrv+pB9o9jkIbBb1bHGnR6MSHuEnpwrIY= + nWcyHLX/EwAuTQuXUzjliGgQdOlWbfS141BlZWQNhJU= + 9hVnTmx7cI5x9bVHpRd8RqayZ5RG9u0ThtgvI9oANnA= + wP00Lqdf93TtrVXvpJZFdr34raFzhH++/RwforHTkGY= + WC3tVc1/SqXK/4Sf54kexCuIHhTY2bkKow5Ox6KnLWI= + sd1yHjWLPhDdZwepmXHHf+ttHTu9NVfilcCfMbKDEJU= + Gwsv8ObX1IZ8L0bSyCWfJX45OKVaXScfVwMGrpgJ7vU= + srwK9wITk9qLX5+LpgMZ9ZvkML/7hUoQclBJWwAN9FQ= + 5TBFQEN6YQ2ncDhfHYAv9t+CXNoHrw8mobS1pZDvtPA= + JzpLUlxNOVTvg7hy1GUWab4EBwTvgn3BvIxs5lVtlY8= + DIy9/x9fiJCojZY2OPXWs2JTQDVvPKl3blfthe02IsQ= + O4fX5NIWsdmwWnoyK7Wz9dSt3Y5jyqV44sAtZKmEfQA= + MQ9urO4tbw1EruMuXQb1E3F+JKD1ersDUxHx7wYd8k0= + 8msLzhiDrPFqi0jC3ZZmOX469wagfVm0X4Iy6G+Oia4= + Ju0UizPzd7oBtoqal/6yOR++19UeP264O+vC+6kJILE= + bE8QUi2cnLp/StLp26mfiOBEc0/2lZhj/Giv8/LeZfU= + wRSAWhLvjUef3G6tp5Mq9ngadfWj+NYHwDOyqmiV9XA= + k5fpANfmRTQa3mv0TTKeQkALHrT0JQfEnhZfXiCziKo= + XjBoHo6A+pYAQ1hxoHaEJ1mZVWnT6SMsUJ3W/Q/TM+o= + eIyXibn6nc0ZDtE588lnOD/leUQCU4pGuBmNUWMoJ6c= + CK3BplEJKc1A/zZYhC/c7KGlireWLkzmWai+vQUnWyI= + +2M/Lao6rj1VTIqWDp8j+e6pBE8z/oSX/qJcSEDBvMk= + YRNhRyVZpanMXsuWOavQl2atNYJyfXHfCv3/GZS43Y8= + BKznRzLfZIgNaNgFk+tTlhb3tClanaP0zQiwghVf6eo= + S5b7frWjyG713VfAmDXcErRHaN2uP/XYw7X2lzGlGeY= + LPCLBmDtahRKWWBsyBt8JnnNPoJLSRomiocCj1TITUY= + or32GShkTVoPXMyTybM55gCtGtBeRoLYbBR3zjmZfP8= + EIWm9FTQyRGY/dqxGjHHFtXc1o35HAOc4Y3Km+s83j0= + YKUrkNM/s08qzVJFb8tBSJfH88W9/tQya5NSw1KFcHk= + 5GPT0Eg/VkdnHJC8uDoi56y8uylxJmPEaRYhflm3F5I= + uBifNTlSZhxz/syRpdtkHMMbppbJQDBM4Kqviu10clk= + B2Pyei+pb/WVvi6qRsNNiCmynLZgLsXlWgvsOafpPT4= + O0q2Y/WVkceQnZKoQs/8kXWPGsU/+QyhNPZJy6zN9TA= + 1mTS5UStgTg3w3DPiRSeWxznlS61oAgYf1VgOGCjI+w= + + + diff --git a/certificates/ota_cert_tool/TestValidator/Resources/distrusted.plist b/certificates/ota_cert_tool/TestValidator/Resources/distrusted.plist new file mode 100644 index 00000000..3610a3b4 --- /dev/null +++ b/certificates/ota_cert_tool/TestValidator/Resources/distrusted.plist @@ -0,0 +1,22 @@ + + + + + distrusted + + vE4tp9J3d3jfPN2xNhVBY6ThIN4= + TAjJjXbxmMc+3zzXL3UNsXZ5l8w= + vF2UO9mrewMlc2HC2y3u/KuPZaE= + vEz72tJsagGp6brK5aN+oiSPohk= + /tyUSQxv71x/xvESmU8WSa37gmU= + PHARlaSL3db+ve9aainuEuth3VM= + iGi/4I41xDs4a2L3KDuEgcgM100= + KQ3bPwdS5QvUIWguJEreW1qW8iE= + dmQ9VsPpsbv/yTSyrrPcBQP4uN0= + x/MqaiDVoST82wUuIM8Hsy40hQ4= + NM81UGGaMDxmJ4EnLHpwixHzKtA= + YFuH6JCFja3KNqPXAMqB0OE2lxs= + MlcOhkaBC6Z7MrTE35pOJvOzjlw= + + + diff --git a/certificates/ota_cert_tool/TestValidator/Resources/revoked.plist b/certificates/ota_cert_tool/TestValidator/Resources/revoked.plist new file mode 100644 index 00000000..bf5a17b1 --- /dev/null +++ b/certificates/ota_cert_tool/TestValidator/Resources/revoked.plist @@ -0,0 +1,18 @@ + + + + + revoked + + q/lo389KN9d7RYxfct5ARMNlu8I= + q/lo389KN9d7RYxfct5ARMNlu8I= + q/lo389KN9d7RYxfct5ARMNlu8I= + 3zPAr5L+N/y22BYW0NmxkdX6bqU= + iGi/4I41xDs4a2L3KDuEgcgM100= + iGi/4I41xDs4a2L3KDuEgcgM100= + /tyUSQxv71x/xvESmU8WSa37gmU= + oT/TfARbtKMRK9ibGgfpBLLSbiY= + xhaTThYX7BaujJR284ZtxXRuhHc= + + + diff --git a/certificates/ota_cert_tool/TestValidator/Resources/roots.plist b/certificates/ota_cert_tool/TestValidator/Resources/roots.plist new file mode 100644 index 00000000..9fa64a85 --- /dev/null +++ b/certificates/ota_cert_tool/TestValidator/Resources/roots.plist @@ -0,0 +1,193 @@ + + + + + roots + + 2pj2QBlN8SjHiIvI40eandMXlf8IfGSQUvuvsC6u8YQ= + 0cM56ieE64cPk0/FY05Kqa1VBQFkAfJkZdN6V0ZjNZ8= + LcYsP2wMyQILunfhxRFRECS5Q+5ZiFbaWiLiIrcneiA= + ex+Njv9dc0n+236uicKarMQXBPFQOuPIwuuhAiXQ9Wg= + eTy/RVm5/eOKsi3xaGn2mIGuFMSwE5rHiKeKGvzKAvs= + 6KL0QWV2eJdfK5fXdXGcfUnZIjRVRUDsFNkuFv4n0ss= + dcnUNhy5bpk6vZYgzwQ76UB6RjPyAvD0wOF4Ucxgic0= + LccOWI00DeWWauMvb8eWvbXebXwlzSSaS+ZOnfkDYyM= + psUeDaXKCpMJ0uTA5Awq+RB6roIDhX/hmOPnaeNDCFw= + jHIJJ5rATideFtB/07d16AFUtZaARuMfUt0ldmMk6ac= + aH+kUTgieP/wyLEfjUPVdmccbrK86rQT+4PZZdBtL/I= + B5HKB0myB4Kq08fXvQzfyUhYNYQ+steZYAnOQ6tsaSc= + gJUhCAXbS7w1XkQo2P1uws3jq1+5eplCmI649NzQYBY= + vXH99tqX5M9i0WR63SWBsH15rfg5frTsupxehIiCFCM= + cKc/fzdrYAdCSJBFNLEUgtW/DmmOzEmN9SV36/LpO5o= + CoHsWpKXd/FFkErzjV1Qn2a14sWPzbUxBYsOF/PwtBs= + A3arHVTF+YA85LLiAaDufu97V7Y26Kk8m41IYMlvX6c= + d0BzEsY6FT1bwAtOUXWc39rCN9wqM7Z5RumOm/poCuM= + fTtGWmAU5SbAr/zuISfSMRcnrYEcJoQtAGrzcwbMgL0= + 4++2EYqS47hY/YBvaQ4x1GuVyhvXVtorMDf+L4fMkTc= + BqLJozeas8FWFZonyp7NvU73Uwm0Cc9wrsqaEjMPOA4= + LUdDfeF5USFaEvPFjlHHKaWAJu8fzApfs9ncAS9gDRk= + Bts68tt7ruAMA7lXgoi73lQdkG6wBpMnQTKV/7SGAI4= + evydAaYvA6LeljeTbUr+aAkNLeGNA/KciM+wsbpjWH8= + sLFzDsvH/0UFFCxJ8Slebtpryu1+LGjFvpG1oRAB8CQ= + DYO2EbZIoadeuFWEAHlTdcrZLiZO2OnXp1fB9e4rsi0= + fH7UJAuyU7s1w3bhLgCwJ/FlnfnYJnQiqT7tde3Hrfs= + n5dERjvhNxR1Tho77PmMCMwgXkqzICj04oMMShsndbg= + ox8JMFO9EsH1w8bv1JgCP9KRTXdY0F1pjOCEtQYm4OU= + 6sAiDFyf7MUSHTcghy0GcHtSZr4l1Ou1argEu7+F/gM= + Fq9XqfZ2sKsSYJWqXrre8iqzERnWRKyVzUuT2/Pyaus= + D06c3SZLAlVQ0XCAY0AhT+lENMmwL2l+xxD8X+r7Xjg= + t7ErFx+CHaqZDND+UIexKESLqOUYT4TFHgK1yPuWKyQ= + y7WvGF6UKiQC+erLwO1buHbuo8EiNiPQBEfk87pVS2U= + kqnZgz/hlE2zZui/rnqVtkgMLWxsKhvmXUI2tgj8obs= + 6wTPXrHzmvp2LyuxIPKWy6Ugwbl9sViVZbgcuaF7ckQ= + 44k2DQ/brrPSUFhLRzAxTiIvOcFWoCAUTo2WBWF5FQY= + 47ai2y7XzkiEL3rFMkHHtx1UFEv7QMEfPx0LQvXuoS0= + D5k8iu+Xuq9WhxQO1ZrRghu0r6zwqppYtdV6M4o6+8s= + wKb03GOiS/3PVO8qaggqCnLeNYA+L/X/Unrl2HIG39U= + gye8jJ1plHs948J1EVNyZ/WcIbn6e2E/r7zNU7cCQAA= + NB3pixOSq/f0q5CpYM8l1L1uxluaUc5u0GfQDsfOm38= + OkPiIP5/PqllPR4hdC6sK3XCD9iYAwW8UCyvjC2bQaE= + g848Eiloilk9SF+BlzwPkZVDHto3zF42Qw55x6iIY4s= + RGQKCg5NAA+9V00rige9tNHf7TtFuqunb3hXeMcBGWE= + HAHG9Nuy/vwiVYsryjJWP0mESs/DK3vksP9Zn56Mevc= + 4oOTdz2oRaZ58ggMx/tEo7ehw3kst+t3Kf3Lao2Zrqc= + 16eg+11+JzHXcelITrze9x1fDD4KKUh4K8g+4OppnvQ= + vYHOO09lkdEaZ7X8ekf97yVSG/mqThi5498uNKeAO+g= + PwblVoHUlvW+Fp61OJ+fK4/2HhcI32iBckhJzV0ny2k= + DCzWPfeAb6OZ7egJEWtXW/h5ifBlGPmAjIYFAxeLr2Y= + thkaUNDDl399qZvNqshqIn2uuWeexwujsMnZInHBcNM= + PpCZtQFej0hsALzqnREe5yH6ujVaibzx32lWHj3GMlw= + Q0ig6URMeMsmXgWNXolEtNhPlmK9Jtslf4k0pEPHAWE= + dDHl9MPBzkaQd08LYeBUQIg7qaAe0Aumq9eAbtOxGM8= + kr9RGavsytCxMy3E4dBfunW1Z5BE7gyibpMfdE8vM88= + lZ3FiAxFfNkuVEeqpWCdsJ7Ue9AsF6Dt79yBnnVsdOU= + lnbyhzVsiaEmg9ZSNAmMt3xPHBjyPA5UHeDhlnJbfr4= + mnOSmlAPGgv0ncsEboA5FpaWVXNF6fgT8Q/5OA2yJpU= + Na5b3dj3rmNc/7pWgqjwC5X0hGLHEI7poOUpKwdKr7I= + QdT23PEwuYQ6O5qVMJU+kl/dhOi3rrjyBbj645NSYX0= + ZjnRPKuF3xrZojxEOzpgkB4rE41Fb6cRg1eBCIhOxr8= + bcRxcuAcvLC/YlgNiV/iuKya1PhzgB4MELnIN9IesXc= + c8F2Q08bxtWt9FsOducnKHyN5XYWwebmFBorLLx9jkw= + YvJAJ4xWTE3Yv32dT282bqiU0i9fNNmJqYOs7C//7VA= + CCl6QEfbojaAxzHbbjF2U8p4SOG+vToLAXmnB/ks8Xg= + z1b/RqShhhCd2WWEte61ilEMQnWw5flPQLuuhl4Z9nM= + LydOSKukrHt2WTMQF3VQbcMO4472rNXASTLP4EEjQiA= + Xwti6rXjU+plIWUWWPu2U1n0QygKSvvRBNd9EPnwTAc= + 7MPpw0B1A77gkaqVL0E0j/iLqoY7ImS++sgHkBV06Tk= + C17tToRkA89V4GWEhEDtKoJ1i/W5qh8lPUYTz6CA/z8= + BKz7OyR5PzAPZ++H5E3XLLmyiyBPOJp81a4oeFx9Qs0= + iU68CyPaKlDAGGt/jyXvH2spNa8yqUWE74Cq+HejoG4= + BASAKL8fKGTUj5rU2DKUNmqCiFZVPzsUMD+QFH9dQO8= + YrkmcmYhKDKo4i2rkz2RxwESdKz3FwP5zJeDN1Gm6U8= + w4Rr8kuek8pkJ0wOxnwezF4CT/ys0tdAGTUOgf5UauQ= + N9UQBsUS6qtiZCHx7IySAT/F+CrpjuUz60YZuN600Gw= + /4VqLSUdzYjTZlb0UBJnmM+rqt5AeZxyLeTStds2pzo= + y7Ui17fxJ61qAROGW98c1BAufQdZr2NafPRyDcljxTs= + 69QQQOS7PsdCyeOB0x7ypBpItmhclufO88HfbNQzHJk= + tBsvv7k+6rPg+msoStuTLNs3Zu1Lx9FIN6jy2a6HSiM= + ykLdQXRf0LgeuQI2LPnYv3Gdob0bHvyUb1tMmfQsG54= + RRQLMkfrnMjFtPDXtTCR9zKSCJ5uWmPidJ3TrKkZjto= + pTElGI0hEKqWSwLHt8baMgMXCJTl+3H/+2Zn1eaBCjY= + +eZ9M2xRACrAVMYyAi1m3aLn4//xCtBh7THYu7QQz7I= + BocmAzGnJAPZCfEF5pvPDTLhvSST/8bZIG0RvNZ3Bzk= + dnyVWnZBLImvaI6QoccPVWz9a2Al2+oQQW1+toMfjEA= + xXus8jj5M2w9+6YtErz1gjYD5YQsROYvVEjMfl9MrVk= + t6fsQZRUQRdhIl7PMNmVhfhRNWB3v4MnSxFYj9BVIbg= + 1o93MLHsKz+2mMltdlQMmZdBWiVzfc1h1Elg23fScj0= + byvEy2MsJOrmeCwPOXWJMtHh3Js+Bw+TAwc//ziyiOI= + bPsJiT39+UV+MwNZKqR1W8hZq2umouEcEc3cJAmr2gI= + lA70ZTZxPY4utLUB6AtqvY606ZKNukR4TOfX6YWV3+g= + sId67i05J034MfZv3ut3F1V8JY/J61UjGp+KZHp1Qz8= + I4BCA8pF2M3nFrjBO/O0SEV/oGzBAlCZf6AUWDF8QeU= + vw/u+546WBrV+enbdYmYV0PSYQhcTTFPb11yWapCFhI= + b9s/dsi4AadTONilCnwCh59hmLV+WU0xjTgykA/tzXk= + j90pjRyTsiv8Qqqxw6FfDQGDLKChrvKNVoDwbmx/1O8= + bTeVcxqV+Likcbmq5cTwVpGxwRoUD9S5ga2JHDZ/r9M= + bPX2WENtEFB+up30Y5h0gLyFYKjibvRpHh08moeKCVI= + fxLNX35eKQ7H2FF51bcsIKW+dQj/21v4GrloSn/J9mc= + ipaKrdiLIFGWcqRSo9bjHqy3HCa8r2WzL5eTvy/6VKk= + bGHaw6Le8DFQa+A20qb+QBmU+9E9+cjUZlmSdMRG7Jg= + 5gbd7uLuf1ze9dkFj/i30KnwQod/ahce2P9pYOTMXqU= + FfC6AKOsevOsiEwHKxARoHe9d8CX9AFksvhZir2Dhgw= + 0XzY7NWGtxIjikgs5G+lKTlwdC8nbYq2qeRu4CiPM1U= + vUaf9F+q58VMy9adPzsAIlXZsGsQsdD6OIv5a5GLLOk= + 52hWNO+s9prOk5prJVt7T6vvQpNbUKJlrLXLYCfkTnA= + LxBi+L+E5+uDoPZMmNiR++LIEbF/+sC84abcnHw9y7c= + VwFPPL4XgqqbeSHF46la/SbVcn2UddAULmttJ3mBM8A= + un8RNjiQdbjobFPAlfoU9cg7awF6AkTtdjcRRiDTo7E= + XFhGjVX1jkl+dDmC0rUAELbRZTdKz4On1KMtt2jEQI4= + 8AhzPsUA3EmHY8ySZMb86kDsIgAOkn0FPOnJC/oEbLI= + pF7eO7vwnIrhXHLvwHJo1pOiHJlv1R5nygeUYP1tiHM= + haDdfdcgrbf/Bfg9VCsgncf/RSj31nexg4n+peXEnoY= + GPH8fyBd+K3d63/gB91X4683WpxNjXNUa/Tx/tHhjTU= + DCWKEqVnSu8l8oun3Prs7qNI5UHm9cxO5jtxs2FgasM= + 7zy0F/yOv2+Xh2yeTs453h6l/mSRQdECi30RwLIpjO0= + afrJvVX7CseNU7vuXPHVl5if0KqrIKJRUb3xcz7n0SI= + r4tnYqHlKCKBYaldXFWe4mYnj3XXnoMBiaUDUGq9a0w= + 515y7Z9WDuxutIAAc6Q/w60ZGVo5IoIBeJWXSpkCa2w= + oi26aB6XN24tOX1yiq46m2KWuf26YLwuEfZH8sZ1+zc= + UTss7LgQ1M3l3YU5Gt/Gwt1g2Hu3NtK1IUhKpHoOvvY= + tEELc+Lm6spH+8Qvj6QBivQ4HcVM+qhEUEYe7QlFTek= + q3A2NlxxVKopwsKfXUGRFjsWKiIlARNX1W0H/6e8H3I= + FGX6IFOXuHb6pvCplY5VkOQPzH+qT7fCyGd1Iftftlg= + zYCChM90b/L9brWKodWcStSzylb9xidKiSang18yMT0= + eQi0AxTBOBALUY0HNYB/+/z4UYoAlTNxBbo4axU92Sc= + ZoyDlH2mO3JL7OF0PDGg5q7Q247Fsxvjd7t4T5G2cW8= + 1B2CnowWWYIq+T/OYr/83iZPyE6LlQxf8nXQUjVGlaM= + LOHLC/nS+eECmT++IVFSw7LdDKveHGjlMZuDkVTbt/U= + Vo1pBaLIhwikswJRkO3P7bGXSmBqE8blKQ/LKuY+2rU= + x2apvvLUBxyGOjGqSSDoE7LRmGCMt7fP4hFDuDbfCeo= + 4XiQ7gmj+/T0i5xBShfWN7elBkfpvHUjInJ/zBdCqRE= + IdsgEjZguy7UGCBdoR7nqFpl4rxuVbWvfniZyKJm2S4= + Yt0L6bn1ChY+oPjnXAU7HspX6lXIaI9kfGiB8sg1e5U= + OyIuVmcR6ZIwDcCxWrlHPa/e+MhNDO99Mxe0wYIdFDY= + vmxNoru5ulm285OXaDdCRsPABZk/qY8CDR3tvtSKgdU= + JIMCqXf0D33WordwWGrfqsPrHoX9GhAtvXhjxyuPjvI= + 5rj4dmSF+Aeuf42sFnBGHwfAoT7vOh/3F1ONerrTkbQ= + jaCE/Pmc4Hci+JsyBZOYBvpcuBHhyBP2oQjH0zazQI4= + MmaWflnNaACNndMggRGFxwQgXo2V/dhPHHsxHmcE/DI= + 6/PAKoeJsft9URmV1mO3KQbZE84NXhBWiop34lhhZ+c= + KDSZHPZ3Rm0iuqw7AFXluRHZqeVfW4W6AtxWZ4LDDoo= + Ocdcrs7okgyQnxMkkWQTULV+JwKmWpkVRbAdG+SiIgs= + SJjGiIwM/7DT4xrKijfU41Ff90bQJjXYZkbPoKMYWuc= + jXIvganBE8B5HfE2opZtsmyVCpcdtGtBmfTqVLeL+58= + 9Z2z9F1X/OyUzNUW5sjMsg3UNj/rLETYZW6V9Q/djfg= + Wzi9Ep6D1aDK0jkhCJSQ1Q1KrjcEKPjd///6TBVk4YQ= + 9QdKj1uaW4FC80q+FS9gNk13Dq517j7s60W2uZZQl4g= + P58n1YMgS54JyKPSBmxLV9OiR5w2k2UIgFBWmBBdvOk= + pDENUK8YpkRxkDcqhq+vi5Uf+0Mdg38eVoi0WXHtFVc= + h8Z4v7iyXzj36XszaVa7zxRLusqlNkfmGiMlvBBVMWs= + y2sF2ejlfNiCsQtNtw3kux3kK6SKe9Axi2Nb9ud4Gp0= + MJtKh/bKVskxaaqpnG2YiFTXiSvVQ34tB7KcvtpV010= + wbSCmaulII/pYwrOVcpooD7aWlGciAKg06Zzvo+OVX0= + QgD1BDrIWQ67Un0gntFQMCn7y9QcobUG7CfxWt59rGk= + 8cG1CuWiDdgDDsn2vCSCPdNntSVXWbTnG2H86fc3XXM= + 5Mc0MNeltQkl30M3Cg0hbpp5udbbg3Ogxp6xzDHHxSo= + RATjO14UDc+ZgFH9/IAox8gWFcXuc3sRG1iCM6m1NaA= + xHDPVH4jArl3+yndcaiae2wfYHd7Ayn1YBfzKL9Pa+Y= + l4zZZvL6oHunqpUA2cAunXfyza2mrWunSvS5HGZZPFA= + v9iP4RAcQa4+gBv4vlY1Dum60aa5vVFe3FxtW4cRrEQ= + ofBcy4DC1xDsfUeavcu4eeWNfttxSf54qHiE49C60Pk= + k+Zex2LwVdxxijMlgsQaBEMNcuPLh+i4l7Z1FvDRqjk= + 2OD+vB2y440AlA830n1BNE2ZPnNLmdVlbZd41NgUNiQ= + Q/JXQS1EDWJ0dpdPh32o8fwkRFZaNnrmDt3CekElMa4= + bqVHQdAEZn7tG0gWY0qjp55uS5aVD4J52vyNm9iBITc= + w43LOJWTkzWGkepNTzzklc50iZbmTtGJHYl6D8TdVcY= + b/945ACnDBEBHNhZd8RZ+1r5aj3wVAgg0PS4YHh15Y8= + hfsvkd0SJ1oBRbY2U0+EAkrWi2m47ohoT/cRN1gFs0g= + Od97aCt7k4+EcVSBzN6NYNjyLsWYh30KqsErWRgrAxI= + 9MFJVRowE6Nbx7/+F6fzRJvBq1taCudLBsI7kABMAQQ= + WNAXJ5zU3GOr3bGWpsmQbDDE4IeD6ujBYJlU1pNVWWs= + vCP5ijE8uS3ju/w6Wp9EYaw5SUxK4VqenfEx6ZtzAZo= + qtnO7Vqmsc6ihZao5OGr7ZOG1uvJ1KrZrN4Po2ugadA= + ms+rfkPI2IDQayYqlN7u5LRlmYnD0Mrxm69kBeQat98= + UYR8jL0umnLJHiktKuJH194eP9JwVHog731hDzi4hCw= + lEVUI52R7Z7+3PkG1egRMWC0b8gW3Gvcd7idoptlYrk= + pLazmW/C8waz/YaBvWNBPYxQCcxPoynCzPDi+hsUAwU= + pxJyrqqjz+hyf3+znw+z0eVCbpBgsG7m8T6aPFgzzUM= + A0WLar7swhSVPZcUmvRTkWkd6fnNzCZHhjo9Z8lcJDs= + Qckjhmq0yta3rVeAgVguAgeXpsvfT/94zoOWs4k31/U= + zs3ckFCZ2NrfxbHSCbc3y+LBjPssEMD/C88NMob8GqI= + + + diff --git a/certificates/ota_cert_tool/TestValidator/TestValidator.1 b/certificates/ota_cert_tool/TestValidator/TestValidator.1 new file mode 100644 index 00000000..9402bb94 --- /dev/null +++ b/certificates/ota_cert_tool/TestValidator/TestValidator.1 @@ -0,0 +1,79 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. +.\"See Also: +.\"man mdoc.samples for a complete listing of options +.\"man mdoc for the short list of editing options +.\"/usr/share/misc/mdoc.template +.Dd 12/13/12 \" DATE +.Dt TestValidator 1 \" Program name and manual section number +.Os Darwin +.Sh NAME \" Section Header - required - don't modify +.Nm TestValidator, +.\" The following lines are read in generating the apropos(man -k) database. Use only key +.\" words here as the database is built based on the words here and in the .ND line. +.Nm Other_name_for_same_program(), +.Nm Yet another name for the same program. +.\" Use .Nm macro to designate other names for the documented program. +.Nd This line parsed for whatis database. +.Sh SYNOPSIS \" Section Header - required - don't modify +.Nm +.Op Fl abcd \" [-abcd] +.Op Fl a Ar path \" [-a path] +.Op Ar file \" [file] +.Op Ar \" [file ...] +.Ar arg0 \" Underlined argument - use .Ar anywhere to underline +arg2 ... \" Arguments +.Sh DESCRIPTION \" Section Header - required - don't modify +Use the .Nm macro to refer to your program throughout the man page like such: +.Nm +Underlining is accomplished with the .Ar macro like this: +.Ar underlined text . +.Pp \" Inserts a space +A list of items with descriptions: +.Bl -tag -width -indent \" Begins a tagged list +.It item a \" Each item preceded by .It macro +Description of item a +.It item b +Description of item b +.El \" Ends the list +.Pp +A list of flags and their descriptions: +.Bl -tag -width -indent \" Differs from above in tag removed +.It Fl a \"-a flag as a list item +Description of -a flag +.It Fl b +Description of -b flag +.El \" Ends the list +.Pp +.\" .Sh ENVIRONMENT \" May not be needed +.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 +.\" .It Ev ENV_VAR_1 +.\" Description of ENV_VAR_1 +.\" .It Ev ENV_VAR_2 +.\" Description of ENV_VAR_2 +.\" .El +.Sh FILES \" File used or created by the topic of the man page +.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact +.It Pa /usr/share/file_name +FILE_1 description +.It Pa /Users/joeuser/Library/really_long_file_name +FILE_2 description +.El \" Ends the list +.\" .Sh DIAGNOSTICS \" May not be needed +.\" .Bl -diag +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .El +.Sh SEE ALSO +.\" List links in ascending order by section, alphabetically within a section. +.\" Please do not reference files that do not exist without filing a bug report +.Xr a 1 , +.Xr b 1 , +.Xr c 1 , +.Xr a 2 , +.Xr b 2 , +.Xr a 3 , +.Xr b 3 +.\" .Sh BUGS \" Document known, unremedied bugs +.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file diff --git a/certificates/ota_cert_tool/TestValidator/TestValidator.m b/certificates/ota_cert_tool/TestValidator/TestValidator.m new file mode 100644 index 00000000..43dde58d --- /dev/null +++ b/certificates/ota_cert_tool/TestValidator/TestValidator.m @@ -0,0 +1,30 @@ +// +// TestValidator.m +// TestValidator +// +// Created by James Murphy on 12/13/12. +// Copyright 2012 James Murphy. All rights reserved. +// + +#import +#import "ValidateAsset.h" + +int main (int argc, const char * argv[]) +{ + @autoreleasepool + { + NSLog(@"Starting the TestValidator"); + NSString* resource_path = [[NSBundle mainBundle] resourcePath]; + const char* asset_dir_path = [resource_path UTF8String]; + if (ValidateAsset(asset_dir_path, 99)) + { + NSLog(@"The assert did not validate"); + } + else + { + NSLog(@"The assert validated!"); + } + + } + return 0; +} diff --git a/certificates/ota_cert_tool/assertValidation/assertValidation-Prefix.pch b/certificates/ota_cert_tool/assertValidation/assertValidation-Prefix.pch new file mode 100644 index 00000000..cec4ccd9 --- /dev/null +++ b/certificates/ota_cert_tool/assertValidation/assertValidation-Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'assertValidation' target in the 'assertValidation' project +// + +#ifdef __OBJC__ + #import +#endif diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool.xcodeproj/project.pbxproj b/certificates/ota_cert_tool/ios_ota_cert_tool.xcodeproj/project.pbxproj new file mode 100644 index 00000000..b63ca055 --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool.xcodeproj/project.pbxproj @@ -0,0 +1,904 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 5D002A70167A528D00D1437B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D74F1E01677F50000737A36 /* Foundation.framework */; }; + 5D002A7B167A531D00D1437B /* ValidateAsset.c in Sources */ = {isa = PBXBuildFile; fileRef = 5D002A62167A4C0900D1437B /* ValidateAsset.c */; }; + 5D002A9D167AA3A900D1437B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D74F1E01677F50000737A36 /* Foundation.framework */; }; + 5D002AA2167AA3A900D1437B /* TestValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D002AA1167AA3A900D1437B /* TestValidator.m */; }; + 5D002AAD167AA3D400D1437B /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D002AAC167AA3D400D1437B /* Security.framework */; }; + 5D6D9C77167B91E70095F399 /* ValidateAsset.c in Sources */ = {isa = PBXBuildFile; fileRef = 5D002A62167A4C0900D1437B /* ValidateAsset.c */; }; + 5D74F1E11677F50000737A36 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D74F1E01677F50000737A36 /* Foundation.framework */; }; + 5D74F1E41677F50000737A36 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D74F1E31677F50000737A36 /* main.m */; }; + 5D74F1F01677F58300737A36 /* PSIOSCertToolApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D74F1EF1677F58300737A36 /* PSIOSCertToolApp.m */; }; + 5D74F1F51677F8EA00737A36 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D74F1F41677F8EA00737A36 /* Security.framework */; }; + 5D74F1F81677FA0100737A36 /* PSCert.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D74F1F71677FA0100737A36 /* PSCert.m */; }; + 5D74F1FC1678088B00737A36 /* PSCerts.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D74F1FB1678088B00737A36 /* PSCerts.m */; }; + 5D74F2021678F86D00737A36 /* PSUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D74F2011678F86D00737A36 /* PSUtilities.m */; }; + 5D74F20516790D1000737A36 /* PSCertKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D74F20416790D1000737A36 /* PSCertKey.m */; }; + 5DBE737D167AA8060093F583 /* certs.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5DBE7376167AA7CB0093F583 /* certs.plist */; }; + 5DBE737E167AA8060093F583 /* distrusted.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5DBE7377167AA7CB0093F583 /* distrusted.plist */; }; + 5DBE737F167AA8060093F583 /* EVRoots.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5DBE7378167AA7CB0093F583 /* EVRoots.plist */; }; + 5DBE7380167AA8060093F583 /* Manifest.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5DBE7379167AA7CB0093F583 /* Manifest.plist */; }; + 5DBE7381167AA8060093F583 /* revoked.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5DBE737A167AA7CB0093F583 /* revoked.plist */; }; + 5DBE7382167AA8060093F583 /* roots.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5DBE737B167AA7CB0093F583 /* roots.plist */; }; + 5DDDFE441680F7EE00B26843 /* ValidateAsset.c in Sources */ = {isa = PBXBuildFile; fileRef = 5D002A62167A4C0900D1437B /* ValidateAsset.c */; }; + 5DDDFE461680F7EE00B26843 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D74F1E01677F50000737A36 /* Foundation.framework */; }; + 5DDDFE6C1680F87B00B26843 /* libassertValidation_osx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DDDFE4B1680F7EE00B26843 /* libassertValidation_osx.a */; }; + 5DDDFE721680FCCB00B26843 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D74F1E01677F50000737A36 /* Foundation.framework */; }; + 5DDDFE771680FCCB00B26843 /* SecuritydAssertHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DDDFE761680FCCB00B26843 /* SecuritydAssertHelper.m */; }; + 5DDDFE791680FCCB00B26843 /* SecuritydAssertHelper.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5DDDFE781680FCCB00B26843 /* SecuritydAssertHelper.1 */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 5D002AA9167AA3B300D1437B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 5D74F1D51677F50000737A36 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5D002A6E167A528D00D1437B; + remoteInfo = assertValidation; + }; + 5DEE57561681364D00C1BAF7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 5D74F1D51677F50000737A36 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5D74F1DC1677F50000737A36; + remoteInfo = ios_ota_cert_tool; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 5D002A6D167A528D00D1437B /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/${PRODUCT_NAME}"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5DBE737C167AA7EF0093F583 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 7; + files = ( + 5DBE737D167AA8060093F583 /* certs.plist in CopyFiles */, + 5DBE737E167AA8060093F583 /* distrusted.plist in CopyFiles */, + 5DBE737F167AA8060093F583 /* EVRoots.plist in CopyFiles */, + 5DBE7380167AA8060093F583 /* Manifest.plist in CopyFiles */, + 5DBE7381167AA8060093F583 /* revoked.plist in CopyFiles */, + 5DBE7382167AA8060093F583 /* roots.plist in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5DDDFE471680F7EE00B26843 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/${PRODUCT_NAME}"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5DDDFE6F1680FCCB00B26843 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + 5DDDFE791680FCCB00B26843 /* SecuritydAssertHelper.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 5D002A61167A4BB400D1437B /* ValidateAsset.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ValidateAsset.h; path = ../ios_ota_cert_tool/ValidateAsset.h; sourceTree = ""; }; + 5D002A62167A4C0900D1437B /* ValidateAsset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ValidateAsset.c; path = ../ios_ota_cert_tool/ValidateAsset.c; sourceTree = ""; }; + 5D002A6F167A528D00D1437B /* libassertValidation.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libassertValidation.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 5D002A73167A528D00D1437B /* assertValidation-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "assertValidation-Prefix.pch"; sourceTree = ""; }; + 5D002A9C167AA3A900D1437B /* TestValidator */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = TestValidator; sourceTree = BUILT_PRODUCTS_DIR; }; + 5D002AA0167AA3A900D1437B /* AspenFamily.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = AspenFamily.xcconfig; path = AppleInternal/XcodeConfig/AspenFamily.xcconfig; sourceTree = DEVELOPER_DIR; }; + 5D002AA1167AA3A900D1437B /* TestValidator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestValidator.m; sourceTree = ""; }; + 5D002AA3167AA3A900D1437B /* TestValidator.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = TestValidator.1; sourceTree = ""; }; + 5D002AA5167AA3A900D1437B /* Readme.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Readme.txt; sourceTree = ""; }; + 5D002AAC167AA3D400D1437B /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.Internal.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; + 5D74F1DD1677F50000737A36 /* ios_ota_cert_tool */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ios_ota_cert_tool; sourceTree = BUILT_PRODUCTS_DIR; }; + 5D74F1E01677F50000737A36 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 5D74F1E31677F50000737A36 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 5D74F1E61677F50000737A36 /* ios_ota_cert_tool-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ios_ota_cert_tool-Prefix.pch"; sourceTree = ""; }; + 5D74F1E71677F50000737A36 /* ios_ota_cert_tool.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = ios_ota_cert_tool.1; sourceTree = ""; }; + 5D74F1EE1677F58300737A36 /* PSIOSCertToolApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSIOSCertToolApp.h; sourceTree = ""; }; + 5D74F1EF1677F58300737A36 /* PSIOSCertToolApp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSIOSCertToolApp.m; sourceTree = ""; }; + 5D74F1F41677F8EA00737A36 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 5D74F1F61677FA0100737A36 /* PSCert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSCert.h; sourceTree = ""; }; + 5D74F1F71677FA0100737A36 /* PSCert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSCert.m; sourceTree = ""; }; + 5D74F1FA1678088B00737A36 /* PSCerts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSCerts.h; sourceTree = ""; }; + 5D74F1FB1678088B00737A36 /* PSCerts.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSCerts.m; sourceTree = ""; }; + 5D74F2001678F86D00737A36 /* PSUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSUtilities.h; sourceTree = ""; }; + 5D74F2011678F86D00737A36 /* PSUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSUtilities.m; sourceTree = ""; }; + 5D74F20316790D1000737A36 /* PSCertKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSCertKey.h; sourceTree = ""; }; + 5D74F20416790D1000737A36 /* PSCertKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSCertKey.m; sourceTree = ""; }; + 5DBE7376167AA7CB0093F583 /* certs.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = certs.plist; sourceTree = ""; }; + 5DBE7377167AA7CB0093F583 /* distrusted.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = distrusted.plist; sourceTree = ""; }; + 5DBE7378167AA7CB0093F583 /* EVRoots.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = EVRoots.plist; sourceTree = ""; }; + 5DBE7379167AA7CB0093F583 /* Manifest.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Manifest.plist; sourceTree = ""; }; + 5DBE737A167AA7CB0093F583 /* revoked.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = revoked.plist; sourceTree = ""; }; + 5DBE737B167AA7CB0093F583 /* roots.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = roots.plist; sourceTree = ""; }; + 5DDDFE4B1680F7EE00B26843 /* libassertValidation_osx.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libassertValidation_osx.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 5DDDFE711680FCCB00B26843 /* SecuritydAssertHelper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = SecuritydAssertHelper; sourceTree = BUILT_PRODUCTS_DIR; }; + 5DDDFE751680FCCB00B26843 /* AspenFamily.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = AspenFamily.xcconfig; path = AppleInternal/XcodeConfig/AspenFamily.xcconfig; sourceTree = DEVELOPER_DIR; }; + 5DDDFE761680FCCB00B26843 /* SecuritydAssertHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecuritydAssertHelper.m; sourceTree = ""; }; + 5DDDFE781680FCCB00B26843 /* SecuritydAssertHelper.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = SecuritydAssertHelper.1; sourceTree = ""; }; + 5DDDFE7A1680FCCB00B26843 /* Readme.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Readme.txt; sourceTree = ""; }; + 5DDDFE7F1680FE9C00B26843 /* File.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; name = File.rb; path = Scripts/File.rb; sourceTree = ""; }; + 5DDDFE80168113DE00B26843 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 5DEE572F16812BA000C1BAF7 /* BuildPlistFiles.rb */ = {isa = PBXFileReference; lastKnownFileType = text.script.ruby; name = BuildPlistFiles.rb; path = Scripts/BuildPlistFiles.rb; sourceTree = ""; }; + 5DEE57371681309E00C1BAF7 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 5DEE573A1681309E00C1BAF7 /* BuildAsset-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BuildAsset-Prefix.pch"; sourceTree = ""; }; + 5DEE5744168131CF00C1BAF7 /* BuildAsset.rb */ = {isa = PBXFileReference; lastKnownFileType = text.script.ruby; name = BuildAsset.rb; path = Scripts/BuildAsset.rb; sourceTree = ""; }; + 5DEE574A1681361900C1BAF7 /* BuildAsset */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = BuildAsset; sourceTree = BUILT_PRODUCTS_DIR; }; + 5DEE574D1681361A00C1BAF7 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 5DEE57501681361A00C1BAF7 /* BuildAsset-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BuildAsset-Prefix.pch"; sourceTree = ""; }; + 5DEE57511681361A00C1BAF7 /* BuildAsset.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = BuildAsset.1; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 5D002A6C167A528D00D1437B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5D002A70167A528D00D1437B /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5D002A99167AA3A900D1437B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5DDDFE6C1680F87B00B26843 /* libassertValidation_osx.a in Frameworks */, + 5D002AAD167AA3D400D1437B /* Security.framework in Frameworks */, + 5D002A9D167AA3A900D1437B /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5D74F1DA1677F50000737A36 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5D74F1F51677F8EA00737A36 /* Security.framework in Frameworks */, + 5D74F1E11677F50000737A36 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5DDDFE451680F7EE00B26843 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5DDDFE461680F7EE00B26843 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5DDDFE6E1680FCCB00B26843 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5DDDFE721680FCCB00B26843 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 5D002A71167A528D00D1437B /* assertValidation */ = { + isa = PBXGroup; + children = ( + 5D002A61167A4BB400D1437B /* ValidateAsset.h */, + 5D002A62167A4C0900D1437B /* ValidateAsset.c */, + 5D002A72167A528D00D1437B /* Supporting Files */, + ); + path = assertValidation; + sourceTree = ""; + }; + 5D002A72167A528D00D1437B /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 5D002A73167A528D00D1437B /* assertValidation-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 5D002A9E167AA3A900D1437B /* TestValidator */ = { + isa = PBXGroup; + children = ( + 5DBE7375167AA7CA0093F583 /* Resources */, + 5D002AA1167AA3A900D1437B /* TestValidator.m */, + 5D002AA3167AA3A900D1437B /* TestValidator.1 */, + 5D002AA5167AA3A900D1437B /* Readme.txt */, + 5D002A9F167AA3A900D1437B /* Supporting Files */, + ); + path = TestValidator; + sourceTree = ""; + }; + 5D002A9F167AA3A900D1437B /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 5D002AA0167AA3A900D1437B /* AspenFamily.xcconfig */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 5D74F1D41677F50000737A36 = { + isa = PBXGroup; + children = ( + 5DDDFE7E1680FE5900B26843 /* Scripts */, + 5D74F1E21677F50000737A36 /* ios_ota_cert_tool */, + 5D74F1E51677F50000737A36 /* Supporting Files */, + 5D002A71167A528D00D1437B /* assertValidation */, + 5D002A9E167AA3A900D1437B /* TestValidator */, + 5DDDFE731680FCCB00B26843 /* SecuritydAssertHelper */, + 5DEE57361681309E00C1BAF7 /* BuildAsset */, + 5DEE574C1681361900C1BAF7 /* BuildAsset */, + 5D74F1DF1677F50000737A36 /* Frameworks */, + 5D74F1DE1677F50000737A36 /* Products */, + ); + sourceTree = ""; + }; + 5D74F1DE1677F50000737A36 /* Products */ = { + isa = PBXGroup; + children = ( + 5D74F1DD1677F50000737A36 /* ios_ota_cert_tool */, + 5D002A6F167A528D00D1437B /* libassertValidation.a */, + 5D002A9C167AA3A900D1437B /* TestValidator */, + 5DDDFE4B1680F7EE00B26843 /* libassertValidation_osx.a */, + 5DDDFE711680FCCB00B26843 /* SecuritydAssertHelper */, + 5DEE574A1681361900C1BAF7 /* BuildAsset */, + ); + name = Products; + sourceTree = ""; + }; + 5D74F1DF1677F50000737A36 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 5D002AAC167AA3D400D1437B /* Security.framework */, + 5D74F1F41677F8EA00737A36 /* Security.framework */, + 5D74F1E01677F50000737A36 /* Foundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 5D74F1E21677F50000737A36 /* ios_ota_cert_tool */ = { + isa = PBXGroup; + children = ( + 5DDDFE80168113DE00B26843 /* Info.plist */, + 5D74F1E31677F50000737A36 /* main.m */, + 5D74F1E71677F50000737A36 /* ios_ota_cert_tool.1 */, + 5D74F1EE1677F58300737A36 /* PSIOSCertToolApp.h */, + 5D74F1EF1677F58300737A36 /* PSIOSCertToolApp.m */, + 5D74F1F61677FA0100737A36 /* PSCert.h */, + 5D74F1F71677FA0100737A36 /* PSCert.m */, + 5D74F1FA1678088B00737A36 /* PSCerts.h */, + 5D74F1FB1678088B00737A36 /* PSCerts.m */, + 5D74F2001678F86D00737A36 /* PSUtilities.h */, + 5D74F2011678F86D00737A36 /* PSUtilities.m */, + 5D74F20316790D1000737A36 /* PSCertKey.h */, + 5D74F20416790D1000737A36 /* PSCertKey.m */, + ); + path = ios_ota_cert_tool; + sourceTree = ""; + }; + 5D74F1E51677F50000737A36 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 5D74F1E61677F50000737A36 /* ios_ota_cert_tool-Prefix.pch */, + ); + name = "Supporting Files"; + path = ios_ota_cert_tool; + sourceTree = ""; + }; + 5DBE7375167AA7CA0093F583 /* Resources */ = { + isa = PBXGroup; + children = ( + 5DBE7376167AA7CB0093F583 /* certs.plist */, + 5DBE7377167AA7CB0093F583 /* distrusted.plist */, + 5DBE7378167AA7CB0093F583 /* EVRoots.plist */, + 5DBE7379167AA7CB0093F583 /* Manifest.plist */, + 5DBE737A167AA7CB0093F583 /* revoked.plist */, + 5DBE737B167AA7CB0093F583 /* roots.plist */, + ); + path = Resources; + sourceTree = ""; + }; + 5DDDFE731680FCCB00B26843 /* SecuritydAssertHelper */ = { + isa = PBXGroup; + children = ( + 5DDDFE761680FCCB00B26843 /* SecuritydAssertHelper.m */, + 5DDDFE781680FCCB00B26843 /* SecuritydAssertHelper.1 */, + 5DDDFE7A1680FCCB00B26843 /* Readme.txt */, + 5DDDFE741680FCCB00B26843 /* Supporting Files */, + ); + path = SecuritydAssertHelper; + sourceTree = ""; + }; + 5DDDFE741680FCCB00B26843 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 5DDDFE751680FCCB00B26843 /* AspenFamily.xcconfig */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 5DDDFE7E1680FE5900B26843 /* Scripts */ = { + isa = PBXGroup; + children = ( + 5DDDFE7F1680FE9C00B26843 /* File.rb */, + 5DEE572F16812BA000C1BAF7 /* BuildPlistFiles.rb */, + 5DEE5744168131CF00C1BAF7 /* BuildAsset.rb */, + ); + name = Scripts; + sourceTree = ""; + }; + 5DEE57361681309E00C1BAF7 /* BuildAsset */ = { + isa = PBXGroup; + children = ( + 5DEE57371681309E00C1BAF7 /* main.m */, + 5DEE57391681309E00C1BAF7 /* Supporting Files */, + ); + path = BuildAsset; + sourceTree = ""; + }; + 5DEE57391681309E00C1BAF7 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 5DEE573A1681309E00C1BAF7 /* BuildAsset-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 5DEE574C1681361900C1BAF7 /* BuildAsset */ = { + isa = PBXGroup; + children = ( + 5DEE574D1681361A00C1BAF7 /* main.m */, + 5DEE57511681361A00C1BAF7 /* BuildAsset.1 */, + 5DEE574F1681361A00C1BAF7 /* Supporting Files */, + ); + path = BuildAsset; + sourceTree = ""; + }; + 5DEE574F1681361A00C1BAF7 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 5DEE57501681361A00C1BAF7 /* BuildAsset-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 5D002A6E167A528D00D1437B /* assertValidation */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5D002A78167A528D00D1437B /* Build configuration list for PBXNativeTarget "assertValidation" */; + buildPhases = ( + 5D002A6B167A528D00D1437B /* Sources */, + 5D002A6C167A528D00D1437B /* Frameworks */, + 5D002A6D167A528D00D1437B /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = assertValidation; + productName = assertValidation; + productReference = 5D002A6F167A528D00D1437B /* libassertValidation.a */; + productType = "com.apple.product-type.library.static"; + }; + 5D002A9B167AA3A900D1437B /* TestValidator */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5D002AA6167AA3A900D1437B /* Build configuration list for PBXNativeTarget "TestValidator" */; + buildPhases = ( + 5D002A98167AA3A900D1437B /* Sources */, + 5D002A99167AA3A900D1437B /* Frameworks */, + 5DBE737C167AA7EF0093F583 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + 5D002AAA167AA3B300D1437B /* PBXTargetDependency */, + ); + name = TestValidator; + productName = TestValidator; + productReference = 5D002A9C167AA3A900D1437B /* TestValidator */; + productType = "com.apple.product-type.tool"; + }; + 5D74F1DC1677F50000737A36 /* ios_ota_cert_tool */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5D74F1EB1677F50000737A36 /* Build configuration list for PBXNativeTarget "ios_ota_cert_tool" */; + buildPhases = ( + 5D74F1D91677F50000737A36 /* Sources */, + 5D74F1DA1677F50000737A36 /* Frameworks */, + 5D0A2B8616949CE000024C1B /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ios_ota_cert_tool; + productName = ios_ota_cert_tool; + productReference = 5D74F1DD1677F50000737A36 /* ios_ota_cert_tool */; + productType = "com.apple.product-type.tool"; + }; + 5DDDFE421680F7EE00B26843 /* assertValidation OSX */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5DDDFE481680F7EE00B26843 /* Build configuration list for PBXNativeTarget "assertValidation OSX" */; + buildPhases = ( + 5DDDFE431680F7EE00B26843 /* Sources */, + 5DDDFE451680F7EE00B26843 /* Frameworks */, + 5DDDFE471680F7EE00B26843 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "assertValidation OSX"; + productName = assertValidation; + productReference = 5DDDFE4B1680F7EE00B26843 /* libassertValidation_osx.a */; + productType = "com.apple.product-type.library.static"; + }; + 5DDDFE701680FCCB00B26843 /* SecuritydAssertHelper */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5DDDFE7B1680FCCB00B26843 /* Build configuration list for PBXNativeTarget "SecuritydAssertHelper" */; + buildPhases = ( + 5DDDFE6D1680FCCB00B26843 /* Sources */, + 5DDDFE6E1680FCCB00B26843 /* Frameworks */, + 5DDDFE6F1680FCCB00B26843 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SecuritydAssertHelper; + productName = SecuritydAssertHelper; + productReference = 5DDDFE711680FCCB00B26843 /* SecuritydAssertHelper */; + productType = "com.apple.product-type.tool"; + }; + 5DEE57491681361900C1BAF7 /* BuildAsset */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5DEE57531681361A00C1BAF7 /* Build configuration list for PBXNativeTarget "BuildAsset" */; + buildPhases = ( + 5DEE57581681368B00C1BAF7 /* BiuldPlistFiles */, + 5DEE5759168138EF00C1BAF7 /* BuildAsset */, + ); + buildRules = ( + ); + dependencies = ( + 5DEE57571681364D00C1BAF7 /* PBXTargetDependency */, + ); + name = BuildAsset; + productName = BuildAsset; + productReference = 5DEE574A1681361900C1BAF7 /* BuildAsset */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 5D74F1D51677F50000737A36 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0460; + ORGANIZATIONNAME = "James Murphy"; + }; + buildConfigurationList = 5D74F1D81677F50000737A36 /* Build configuration list for PBXProject "ios_ota_cert_tool" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 5D74F1D41677F50000737A36; + productRefGroup = 5D74F1DE1677F50000737A36 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 5D74F1DC1677F50000737A36 /* ios_ota_cert_tool */, + 5D002A6E167A528D00D1437B /* assertValidation */, + 5D002A9B167AA3A900D1437B /* TestValidator */, + 5DDDFE421680F7EE00B26843 /* assertValidation OSX */, + 5DDDFE701680FCCB00B26843 /* SecuritydAssertHelper */, + 5DEE57491681361900C1BAF7 /* BuildAsset */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + 5D0A2B8616949CE000024C1B /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = ""; + }; + 5DEE57581681368B00C1BAF7 /* BiuldPlistFiles */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = BiuldPlistFiles; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"Running BuildPlistFiles.rb\"\nruby ./Scripts/BuildPlistFiles.rb"; + showEnvVarsInLog = 0; + }; + 5DEE5759168138EF00C1BAF7 /* BuildAsset */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = BuildAsset; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"Running BuildAsset.rb\"\nruby ./Scripts/BuildAsset.rb"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 5D002A6B167A528D00D1437B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5D002A7B167A531D00D1437B /* ValidateAsset.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5D002A98167AA3A900D1437B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5D002AA2167AA3A900D1437B /* TestValidator.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5D74F1D91677F50000737A36 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5D74F1E41677F50000737A36 /* main.m in Sources */, + 5D74F1F01677F58300737A36 /* PSIOSCertToolApp.m in Sources */, + 5D74F1F81677FA0100737A36 /* PSCert.m in Sources */, + 5D74F1FC1678088B00737A36 /* PSCerts.m in Sources */, + 5D74F2021678F86D00737A36 /* PSUtilities.m in Sources */, + 5D74F20516790D1000737A36 /* PSCertKey.m in Sources */, + 5D6D9C77167B91E70095F399 /* ValidateAsset.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5DDDFE431680F7EE00B26843 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5DDDFE441680F7EE00B26843 /* ValidateAsset.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5DDDFE6D1680FCCB00B26843 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5DDDFE771680FCCB00B26843 /* SecuritydAssertHelper.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 5D002AAA167AA3B300D1437B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5D002A6E167A528D00D1437B /* assertValidation */; + targetProxy = 5D002AA9167AA3B300D1437B /* PBXContainerItemProxy */; + }; + 5DEE57571681364D00C1BAF7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5D74F1DC1677F50000737A36 /* ios_ota_cert_tool */; + targetProxy = 5DEE57561681364D00C1BAF7 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 5D002A79167A528D00D1437B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/assertValidation.dst; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "assertValidation/assertValidation-Prefix.pch"; + HEADER_SEARCH_PATHS = "$(SDKROOT)/usr/local/include"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos.internal; + SKIP_INSTALL = YES; + USER_HEADER_SEARCH_PATHS = "$(SDKROOT)/usr/local/include"; + }; + name = Debug; + }; + 5D002A7A167A528D00D1437B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/assertValidation.dst; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "assertValidation/assertValidation-Prefix.pch"; + HEADER_SEARCH_PATHS = "$(SDKROOT)/usr/local/include"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos.internal; + SKIP_INSTALL = YES; + USER_HEADER_SEARCH_PATHS = "$(SDKROOT)/usr/local/include"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 5D002AA7167AA3A900D1437B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx.internal; + }; + name = Debug; + }; + 5D002AA8167AA3A900D1437B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx.internal; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 5D74F1E91677F50000737A36 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 5D74F1EA1677F50000737A36 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + SDKROOT = macosx; + }; + name = Release; + }; + 5D74F1EC1677F50000737A36 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "ios_ota_cert_tool/ios_ota_cert_tool-Prefix.pch"; + HEADER_SEARCH_PATHS = /usr/local/include; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 5D74F1ED1677F50000737A36 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "ios_ota_cert_tool/ios_ota_cert_tool-Prefix.pch"; + HEADER_SEARCH_PATHS = /usr/local/include; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 5DDDFE491680F7EE00B26843 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/assertValidation.dst; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "assertValidation/assertValidation-Prefix.pch"; + HEADER_SEARCH_PATHS = "$(SDKROOT)/usr/local/include"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = assertValidation_osx; + SDKROOT = macosx.internal; + SKIP_INSTALL = YES; + USER_HEADER_SEARCH_PATHS = "$(SDKROOT)/usr/local/include"; + }; + name = Debug; + }; + 5DDDFE4A1680F7EE00B26843 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/assertValidation.dst; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "assertValidation/assertValidation-Prefix.pch"; + HEADER_SEARCH_PATHS = "$(SDKROOT)/usr/local/include"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = assertValidation_osx; + SDKROOT = macosx.internal; + SKIP_INSTALL = YES; + USER_HEADER_SEARCH_PATHS = "$(SDKROOT)/usr/local/include"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 5DDDFE7C1680FCCB00B26843 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos.internal; + }; + name = Debug; + }; + 5DDDFE7D1680FCCB00B26843 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos.internal; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 5DEE57541681361A00C1BAF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "BuildAsset/BuildAsset-Prefix.pch"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 5DEE57551681361A00C1BAF7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "BuildAsset/BuildAsset-Prefix.pch"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 5D002A78167A528D00D1437B /* Build configuration list for PBXNativeTarget "assertValidation" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5D002A79167A528D00D1437B /* Debug */, + 5D002A7A167A528D00D1437B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5D002AA6167AA3A900D1437B /* Build configuration list for PBXNativeTarget "TestValidator" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5D002AA7167AA3A900D1437B /* Debug */, + 5D002AA8167AA3A900D1437B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5D74F1D81677F50000737A36 /* Build configuration list for PBXProject "ios_ota_cert_tool" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5D74F1E91677F50000737A36 /* Debug */, + 5D74F1EA1677F50000737A36 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5D74F1EB1677F50000737A36 /* Build configuration list for PBXNativeTarget "ios_ota_cert_tool" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5D74F1EC1677F50000737A36 /* Debug */, + 5D74F1ED1677F50000737A36 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5DDDFE481680F7EE00B26843 /* Build configuration list for PBXNativeTarget "assertValidation OSX" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5DDDFE491680F7EE00B26843 /* Debug */, + 5DDDFE4A1680F7EE00B26843 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5DDDFE7B1680FCCB00B26843 /* Build configuration list for PBXNativeTarget "SecuritydAssertHelper" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5DDDFE7C1680FCCB00B26843 /* Debug */, + 5DDDFE7D1680FCCB00B26843 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5DEE57531681361A00C1BAF7 /* Build configuration list for PBXNativeTarget "BuildAsset" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5DEE57541681361A00C1BAF7 /* Debug */, + 5DEE57551681361A00C1BAF7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 5D74F1D51677F50000737A36 /* Project object */; +} diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/certificates/ota_cert_tool/ios_ota_cert_tool.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..e373fe16 --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/CommonBaseXX.c b/certificates/ota_cert_tool/ios_ota_cert_tool/CommonBaseXX.c new file mode 100644 index 00000000..b555013d --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/CommonBaseXX.c @@ -0,0 +1,9 @@ +// +// CommonBaseXX.c +// ios_ota_cert_tool +// +// Created by James Murphy on 12/13/12. +// Copyright (c) 2012 James Murphy. All rights reserved. +// + +#include diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/CommonBaseXX.h b/certificates/ota_cert_tool/ios_ota_cert_tool/CommonBaseXX.h new file mode 100644 index 00000000..882ee9aa --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/CommonBaseXX.h @@ -0,0 +1,273 @@ +/* + * Copyright (c) 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@ + */ + + +#ifndef COMMON_BASE_XX_H +#define COMMON_BASE_XX_H + +#if !defined(COMMON_NUMERICS_H) +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + /*! + @enum CNEncodings + @abstract Encodings available through CommonBaseXX(). + + @constant kCNEncodingBase64 Base64 Encoding. + @constant kCNEncodingBase32 Base32 Encoding. + @constant kCNEncodingBase32HEX Base32 Encoding - + @constant kCNEncodingBase32Recovery Base32 Simplified Encoding. + */ + enum { + kCNEncodingBase64 = 0x0001, + kCNEncodingBase32 = 0x0002, + kCNEncodingBase32Recovery = 0x0003, + kCNEncodingBase32HEX = 0x0004, + kCNEncodingBase16 = 0x0005, + kCNEncodingCustom = 0xcafe + }; + typedef uint32_t CNEncodings; + + /*! + @enum kCNEncodingDirection + @abstract Determine whether the CNEncoderRef is to be used + to encode or decode. + + @constant kCNEncode Encode (base256 to baseXX) + @constant kCNDecode Decode (baseXX to base256) + */ + + enum { + kCNEncode = 0x0001, + kCNDecode = 0x0002, + }; + typedef uint32_t CNEncodingDirection; + + /*! + @typedef CNEncoderRef + @abstract Opaque reference to a CNEncoder object. + */ + + typedef struct _CNEncoder *CNEncoderRef; + + /*! + @function CNEncode + @abstract One-Shot baseXX encode or decode. + @param encoding selects one of the base encodings above. + @param direction Designate the direction (encode or decode) + @param in The bytes to be processed. + @param inLen The number of bytes to be processed. + @param out The destination of the processed data. + @param outLen The length of the processed data. + @result kCCSuccess or one of kCCParamErr, kCCMemoryFailure. + + */ + + CNStatus + CNEncode(CNEncodings encoding, + CNEncodingDirection direction, + const void *in, const size_t inLen, + void *out, size_t *outLen) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_5_0); + + + + + /*! + @function CCEncoderCreate + @abstract Create a base encoder context. + @param encoding selects one of the base encodings above. + @param direction Designate the direction (encode or decode) for this + CNEncoderRef. + @param coderRef A (required) pointer to the returned CNEncoderRef. + */ + + CNStatus + CNEncoderCreate(CNEncodings encoding, + CNEncodingDirection direction, + CNEncoderRef *encoderRef) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_5_0); + + /*! + @function CCEncoderCreateCustom + @abstract Create a custom base encoder context. + @param name A name for this encoder (optional) + @param baseNum The base of the encoding (16, 32, 64) + @param charMap A string containing the characters to map an encoded + byte to for output. + @param padding The character to use for padding (usually '=') + @param direction Designate the direction (encode or decode) for this + CNEncoderRef. + @param coderRef A (required) pointer to the returned CNEncoderRef. + */ + + CNStatus + CNEncoderCreateCustom( + const void *name, + const uint8_t baseNum, + const void *charMap, + const char padChar, + CNEncodingDirection direction, + CNEncoderRef *coderRef) /* RETURNED */ + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_5_0); + + /*! + @function CNEncoderRelease + @abstract Release a CNEncoderRef and associated objects. + */ + CNStatus + CNEncoderRelease(CNEncoderRef *coderRef) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_5_0); + + + /*! + @function CNEncoderGetOutputLength + @abstract Determine the size required to hold the result of processing the + input. + + @param coderRef A CNEncoderRef obtained through CNEncoderCreate() + or CNEncoderCreateCustom(). + + @param inLen The number of bytes to be processed. + + @result The length required for the encoding. Zero (0) will be returned in + the result of a NULL input pointer for the "in" parameter. + */ + + size_t + CNEncoderGetOutputLength(CNEncoderRef coderRef, const size_t inLen) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_6_0); + + /*! + @function CNEncoderGetOutputLengthFromEncoding + @abstract Determine the size required to hold the result of processing the + input given an encoding constant and direction and length. + + @param encoding selects one of the base encodings above. + @param direction Designate the direction (encode or decode) for this + CNEncoderRef. + + @param inLen The number of bytes to be processed. + + @result The length required for the encoding. Zero (0) will be returned in + the result of a NULL input pointer for the "in" parameter. + */ + + size_t + CNEncoderGetOutputLengthFromEncoding(CNEncodings encoding, + CNEncodingDirection direction, + const size_t inLen) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_6_0); + + /*! + @function CNEncoderUpdate + @abstract Encode or decode the input string to or from the designated + encoded format. + + @param coderRef A CNEncoderRef obtained through CNEncoderCreate() + or CNEncoderCreateCustom(). + + @param in The bytes to be processed. + + @param inLen The number of bytes to be processed. + + @param out The destination of the processed data. + + @param outLen The length of the processed data. + + @result kCCSuccess or one of kCCParamErr, kCCMemoryFailure. + */ + + CNStatus + CNEncoderUpdate(CNEncoderRef coderRef, const void *in, const size_t inLen, void *out, + size_t *outLen) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_6_0); + + + /*! + @function CNEncoderFinal + @abstract Complete coding for all available inputs, padding where necessary. + + @param coderRef A CNEncoderRef obtained through CNEncoderCreate() + or CNEncoderCreateCustom(). + + @param out The destination of the processed data. + + @param outLen The length of the processed data. + + @result kCCSuccess or one of kCCParamErr, kCCMemoryFailure. + */ + + CNStatus + CNEncoderFinal(CNEncoderRef coderRef, void *out, size_t *outLen) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_6_0); + + + /*! + @function CNEncoderBlocksize + @abstract Get the number of bytes per block of input (base256) to output (base of encoder). + + @param encoding The encoding format. + + @param inputSize The number of raw bytes upon which an encoding operation should be performed + if padding should not be added. If CNEncode is called with this many bytes + the resulting coded bytes will not need padding. + @param outputSize The output block size in bytes for this encoding. + + @result kCCSuccess or kCCParamErr. + */ + + + + CNStatus + CNEncoderBlocksize(CNEncodings encoding, size_t *inputSize, size_t *outputSize) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_6_0); + + /*! + @function CNEncoderBlocksizeFromRef + @abstract Get the number of bytes per block of input (base256) to output (base of encoder). + + @param encoderRef A CNEncoderRef gotten from CNEncoderCreate or CNEncoderCreateCustom. + + @param inputSize The number of raw bytes upon which an encoding operation should be performed + if padding should not be added. If CNEncode is called with this many bytes + the resulting coded bytes will not need padding. + @param outputSize The output block size in bytes for this encoding. + + @result kCCSuccess or kCCParamErr. + */ + + CNStatus + CNEncoderBlocksizeFromRef(CNEncoderRef encoderRef, size_t *inputSize, size_t *outputSize) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_6_0); + + +#ifdef __cplusplus +} +#endif + +#endif /* COMMON_BASE_XX_H */ diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/CommonBuffering.c b/certificates/ota_cert_tool/ios_ota_cert_tool/CommonBuffering.c new file mode 100644 index 00000000..76b47693 --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/CommonBuffering.c @@ -0,0 +1,114 @@ +// +// CommonBuffering.c +// CommonCrypto +// + +#include +#include "ccMemory.h" +#include "CommonBufferingPriv.h" +#include + + +CNBufferRef +CNBufferCreate(size_t chunksize) +{ + CNBufferRef retval = CC_XMALLOC(sizeof(CNBuffer)); + __Require_Quiet(NULL != retval, errOut); + retval->chunksize = chunksize; + retval->bufferPos = 0; + retval->buf = CC_XMALLOC(chunksize); + __Require_Quiet(NULL != retval->buf, errOut); + return retval; + +errOut: + if(retval) { + if(retval->buf) CC_XFREE(retval->buf, chunksize); + CC_XFREE(retval, sizeof(CNBuffer)); + } + return NULL; +} + +CNStatus +CNBufferRelease(CNBufferRef *bufRef) +{ + CNBufferRef ref; + + __Require_Quiet(NULL != bufRef, out); + ref = *bufRef; + if(ref->buf) CC_XFREE(ref->buf, chunksize); + if(ref) CC_XFREE(ref, sizeof(CNBuffer)); +out: + return kCNSuccess; +} + + + +CNStatus +CNBufferProcessData(CNBufferRef bufRef, + void *ctx, const void *in, const size_t inLen, void *out, size_t *outLen, + cnProcessFunction pFunc, cnSizeFunction sizeFunc) +{ + size_t blocksize = bufRef->chunksize; + uint8_t *input = (uint8_t *) in, *output = out; + size_t inputLen = inLen, outputLen, inputUsing, outputAvailable; + + outputAvailable = outputLen = *outLen; + + if(sizeFunc(ctx, bufRef->bufferPos + inLen) > outputAvailable) return kCNBufferTooSmall; + *outLen = 0; + if(bufRef->bufferPos > 0) { + inputUsing = CC_XMIN(blocksize - bufRef->bufferPos, inputLen); + CC_XMEMCPY(&bufRef->buf[bufRef->bufferPos], in, inputUsing); + bufRef->bufferPos += inputUsing; + if(bufRef->bufferPos < blocksize) { + return kCNSuccess; + } + pFunc(ctx, bufRef->buf, blocksize, output, &outputLen); + inputLen -= inputUsing; input += inputUsing; + output += outputLen; *outLen = outputLen; outputAvailable -= outputLen; + bufRef->bufferPos = 0; + } + + inputUsing = inputLen - inputLen % blocksize; + if(inputUsing > 0) { + outputLen = outputAvailable; + pFunc(ctx, input, inputUsing, output, &outputLen); + inputLen -= inputUsing; input += inputUsing; + *outLen += outputLen; + } + + if(inputLen > blocksize) { + return kCNAlignmentError; + } else if(inputLen > 0) { + CC_XMEMCPY(bufRef->buf, input, inputLen); + bufRef->bufferPos = inputLen; + } + return kCNSuccess; + +} + +CNStatus +CNBufferFlushData(CNBufferRef bufRef, + void *ctx, void *out, size_t *outLen, + cnProcessFunction pFunc, cnSizeFunction sizeFunc) +{ + // size_t outputLen, outputAvailable; + // outputAvailable = outputLen = *outLen; + + if(bufRef->bufferPos > 0) { + if(bufRef->bufferPos > bufRef->chunksize) return kCNAlignmentError; + if(sizeFunc(ctx, bufRef->bufferPos) > *outLen) return kCNBufferTooSmall; + pFunc(ctx, bufRef->buf, bufRef->bufferPos, out, outLen); + } else { + *outLen = 0; + } + return kCNSuccess; +} + + + +bool +CNBufferEmpty(CNBufferRef bufRef) +{ + return bufRef->bufferPos == 0; +} diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/CommonBufferingPriv.h b/certificates/ota_cert_tool/ios_ota_cert_tool/CommonBufferingPriv.h new file mode 100644 index 00000000..27a39a02 --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/CommonBufferingPriv.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2010,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@ + */ + +#ifndef CC_CommonBufferingPriv_h +#define CC_CommonBufferingPriv_h + +#include "CommonNumerics.h" +#include + +typedef struct CNBuffer_t { + size_t chunksize; + size_t bufferPos; + uint8_t *buf; +} CNBuffer, *CNBufferRef; + +CNBufferRef +CNBufferCreate(size_t chunksize); + +CNStatus +CNBufferRelease(CNBufferRef *bufRef); + +typedef int (*cnProcessFunction)(void *ctx, const void *in, size_t inLen, void *out, size_t *outLen); +typedef size_t (*cnSizeFunction)(void *ctx, size_t inLen); + +CNStatus +CNBufferProcessData(CNBufferRef bufRef, + void *ctx, const void *in, const size_t inLen, void *out, size_t *outLen, + cnProcessFunction pFunc, cnSizeFunction sizeFunc); + +CNStatus +CNBufferFlushData(CNBufferRef bufRef, + void *ctx, void *out, size_t *outLen, + cnProcessFunction pFunc, cnSizeFunction sizeFunc); + + +bool +CNBufferEmpty(CNBufferRef bufRef); + + + + + +#endif /* CC_CommonBufferingPriv_h */ diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/Info.plist b/certificates/ota_cert_tool/ios_ota_cert_tool/Info.plist new file mode 100644 index 00000000..5c578999 --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/Info.plist @@ -0,0 +1,27 @@ + + + + + CFBundleShortVersionString + 1.0.0 + CFBundleIdentifier + com.apple.MobileAsset.PKITrustServices.PKITrustData + CFBundleName + PKI Trust Data + CFBundleInfoDictionaryVersion + 1.0 + CFBundleVersion + 1.0 + MobileAssetProperties + + FormatVersion + 1 + ContentVersion + 1 + __RequiredByOS + + __AssetDefaultGarbageCollectionBehavior + NeverCollected + + + diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/PSCert.h b/certificates/ota_cert_tool/ios_ota_cert_tool/PSCert.h new file mode 100644 index 00000000..925d6544 --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/PSCert.h @@ -0,0 +1,22 @@ +// +// PSCert.h +// ios_ota_cert_tool +// +// Created by James Murphy on 12/11/12. +// Copyright (c) 2012 James Murphy. All rights reserved. +// + +#import + + +@interface PSCert : NSObject +{ +@private + NSString* _cert_hash; +} + +@property (readonly) NSString* cert_hash; + +- (id)initWithCertFilePath:(NSString *)filePath; + +@end diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/PSCert.m b/certificates/ota_cert_tool/ios_ota_cert_tool/PSCert.m new file mode 100644 index 00000000..ab52e67b --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/PSCert.m @@ -0,0 +1,37 @@ +// +// PSCert.m +// ios_ota_cert_tool +// +// Created by James Murphy on 12/11/12. +// Copyright (c) 2012 James Murphy. All rights reserved. +// + +#import "PSCert.h" +#import "PSUtilities.h" + +@implementation PSCert + +@synthesize cert_hash = _cert_hash; + + +- (id)initWithCertFilePath:(NSString *)filePath +{ + if ((self = [super init])) + { + _cert_hash = nil; + + CFDataRef temp_cf_data = [PSUtilities readFile:filePath]; + if (NULL == temp_cf_data) + { + NSLog(@"PSCert: Unable to read data for file %@", filePath); + return nil; + } + _cert_hash = [PSUtilities digestAndEncode:temp_cf_data useSHA1:NO]; + CFRelease(temp_cf_data); + } + return self; +} + + + +@end diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/PSCertKey.h b/certificates/ota_cert_tool/ios_ota_cert_tool/PSCertKey.h new file mode 100644 index 00000000..81b4ee72 --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/PSCertKey.h @@ -0,0 +1,21 @@ +// +// PSCertKey.h +// ios_ota_cert_tool +// +// Created by James Murphy on 12/12/12. +// Copyright (c) 2012 James Murphy. All rights reserved. +// + +#import + +@interface PSCertKey : NSObject +{ +@private + NSString* _key_hash; +} + +@property (readonly) NSString* key_hash; + +- (id)initWithCertFilePath:(NSString *)filePath; + +@end diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/PSCertKey.m b/certificates/ota_cert_tool/ios_ota_cert_tool/PSCertKey.m new file mode 100644 index 00000000..1da3bfaa --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/PSCertKey.m @@ -0,0 +1,47 @@ +// +// PSCertKey.m +// ios_ota_cert_tool +// +// Created by James Murphy on 12/12/12. +// Copyright (c) 2012 James Murphy. All rights reserved. +// + +#import "PSCertKey.h" +#import +#import "PSUtilities.h" + +@implementation PSCertKey + +@synthesize key_hash = _key_hash; + + +- (id)initWithCertFilePath:(NSString *)filePath +{ + if ((self = [super init])) + { + _key_hash = nil; + + CFDataRef temp_cf_data = [PSUtilities readFile:filePath]; + if (NULL == temp_cf_data) + { + NSLog(@"PSCertKey: Unable to read data for file %@", filePath); + return nil; + } + + SecCertificateRef aCert = [PSUtilities getCertificateFromData:temp_cf_data]; + CFRelease(temp_cf_data); + if (NULL != aCert) + { + CFDataRef temp_key_data = [PSUtilities getKeyDataFromCertificate:aCert]; + if (NULL != temp_key_data) + { + _key_hash = [PSUtilities digestAndEncode:temp_key_data useSHA1:YES]; + CFRelease(temp_key_data); + } + CFRelease(aCert); + } + } + return self; +} + +@end diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/PSCerts.h b/certificates/ota_cert_tool/ios_ota_cert_tool/PSCerts.h new file mode 100644 index 00000000..1d987266 --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/PSCerts.h @@ -0,0 +1,23 @@ +// +// PSCerts.h +// ios_ota_cert_tool +// +// Created by James Murphy on 12/11/12. +// Copyright (c) 2012 James Murphy. All rights reserved. +// + +#import + +@interface PSCerts : NSObject +{ + NSString* _cert_dir_path; + NSMutableArray* _certs; + +} + +@property (readonly) NSArray* certs; + +- (id)initWithCertFilePath:(NSString *)filePath forBadCerts:(BOOL)forBad; + + +@end diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/PSCerts.m b/certificates/ota_cert_tool/ios_ota_cert_tool/PSCerts.m new file mode 100644 index 00000000..7d5123d0 --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/PSCerts.m @@ -0,0 +1,86 @@ +// +// PSCerts.m +// ios_ota_cert_tool +// +// Created by James Murphy on 12/11/12. +// Copyright (c) 2012 James Murphy. All rights reserved. +// + +#import "PSCerts.h" +#import "PSCertKey.h" +#import "PSCert.h" + +@interface PSCerts (PrivateMethods) + +- (void)get_certs:(BOOL)forBadCerts; + +@end + +@implementation PSCerts + +@synthesize certs = _certs; + +- (void)get_certs:(BOOL)forBad +{ + if (nil != _cert_dir_path) + { + @autoreleasepool + { + NSFileManager* fileManager = [NSFileManager defaultManager]; + BOOL isDir = NO; + if (![fileManager fileExistsAtPath:_cert_dir_path isDirectory:&isDir] || !isDir) + { + return; + } + + NSDirectoryEnumerator* enumer = [fileManager enumeratorAtPath:_cert_dir_path]; + if (nil == enumer) + { + return; + } + + for(NSString* cert_path_str in enumer) + { + if ([cert_path_str hasPrefix:@"."]) + { + continue; + } + + NSLog(@"Processing file %@", cert_path_str); + + NSString* full_path = [_cert_dir_path stringByAppendingPathComponent:cert_path_str]; + + if (forBad) + { + PSCertKey* aCertKey = [[PSCertKey alloc] initWithCertFilePath:full_path]; + if (nil != aCertKey) + { + [_certs addObject:aCertKey.key_hash]; + } + } + else + { + PSCert* aCert = [[PSCert alloc] initWithCertFilePath:full_path]; + if (nil != aCert) + { + [_certs addObject:aCert.cert_hash]; + } + + } + } + } + } +} + +- (id)initWithCertFilePath:(NSString *)filePath forBadCerts:(BOOL)forBad +{ + if (self = [super init]) + { + _cert_dir_path = filePath; + _certs = [NSMutableArray array]; + [self get_certs:forBad]; + } + return self; +} + +@end diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/PSIOSCertToolApp.h b/certificates/ota_cert_tool/ios_ota_cert_tool/PSIOSCertToolApp.h new file mode 100644 index 00000000..90732426 --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/PSIOSCertToolApp.h @@ -0,0 +1,51 @@ +// +// PSIOSCertToolApp.h +// ios_ota_cert_tool +// +// Created by James Murphy on 12/11/12. +// Copyright (c) 2012 James Murphy. All rights reserved. +// + +#import + +@interface PSIOSCertToolApp : NSObject +{ +@private + NSString* _app_name; + NSString* _root_directory; + NSString* _revoked_directory; + NSString* _distrusted_directory; + NSString* _certs_directory; + NSString* _ev_plist_path; + NSString* _info_plist_path; + NSString* _top_level_directory; + NSString* _outputDir; + + NSArray* _roots; + NSArray* _revoked; + NSArray* _distrusted; + NSArray* _certs; + + NSArray* _plist_name_array; + +} + +@property (readonly) NSString* app_name; +@property (readonly) NSString* root_directory; +@property (readonly) NSString* revoked_directory; +@property (readonly) NSString* distrusted_directory; +@property (readonly) NSString* certs_directory; +@property (readonly) NSString* ev_plist_path; +@property (readonly) NSString* info_plist_path; +@property (readonly) NSString* top_level_directory; +@property (readonly) NSString* output_directory; + +- (id)init:(int)argc withArguments:(const char**)argv; + +- (BOOL)processCertificates; + +- (BOOL)outputPlistsToDirectory; + +- (BOOL)validate; + +@end diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/PSIOSCertToolApp.m b/certificates/ota_cert_tool/ios_ota_cert_tool/PSIOSCertToolApp.m new file mode 100644 index 00000000..9fb46ba7 --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/PSIOSCertToolApp.m @@ -0,0 +1,503 @@ +// +// PSIOSCertToolApp.m +// ios_ota_cert_tool +// +// Created by James Murphy on 12/11/12. +// Copyright (c) 2012 James Murphy. All rights reserved. +// + +#import "PSIOSCertToolApp.h" +#import "PSCerts.h" +#import "PSUtilities.h" +#import "ValidateAsset.h" +#import + + +@interface PSIOSCertToolApp (PrivateMethods) + +- (void)usage; +- (NSString*)checkPath:(NSString*)name basePath:(NSString *)basePath isDirectory:(BOOL)isDirectory; +- (BOOL)outputPlistToPath:(NSString *)path withData:(id)data; +- (BOOL)buildManifest:(NSString *)path; +- (NSNumber*)getNextVersionNumber; +@end + +@implementation PSIOSCertToolApp + +@synthesize app_name = _app_name; +@synthesize root_directory = _root_directory; +@synthesize revoked_directory = _revoked_directory; +@synthesize distrusted_directory = _distrusted_directory; +@synthesize certs_directory = _certs_directory; +@synthesize ev_plist_path = _ev_plist_path; +@synthesize info_plist_path = _info_plist_path; +@synthesize top_level_directory = _top_level_directory; +@synthesize output_directory = _output_directory; + + +- (id)init:(int)argc withArguments:(const char**)argv +{ + if ((self = [super init])) + { + _app_name = [[NSString alloc] initWithUTF8String:argv[0]]; + _root_directory = nil; + _revoked_directory = nil; + _distrusted_directory = nil; + _certs_directory = nil; + _ev_plist_path = nil; + _info_plist_path = nil; + _top_level_directory = nil; + _output_directory = nil; + + _roots = nil; + _revoked = nil; + _distrusted = nil; + _certs = nil; + _plist_name_array = [NSArray arrayWithObjects:@"roots.plist", @"revoked.plist", @"distrusted.plist", @"certs.plist", nil]; + + for (int iCnt = 1; iCnt < argc; iCnt++) + { + const char* arg = argv[iCnt]; + if (!strcmp(arg, "-h") || !strcmp(arg, "--help")) + { + [self usage]; + return nil; + } + else if (!strcmp(arg, "-r") || !strcmp(arg, "--roots_dir")) + { + if ((iCnt + 1) == argc) + { + [self usage]; + return nil; + } + + _root_directory = [[NSString stringWithUTF8String:argv[iCnt + 1]] stringByExpandingTildeInPath]; + iCnt++; + + } + else if (!strcmp(arg, "-k") || !strcmp(arg, "--revoked_dir")) + { + if ((iCnt + 1) == argc) + { + [self usage]; + return nil; + } + + _revoked_directory = [[NSString stringWithUTF8String:argv[iCnt + 1]] stringByExpandingTildeInPath]; + iCnt++; + } + else if (!strcmp(arg, "-d") || !strcmp(arg, "--distrusted_dir")) + { + if ((iCnt + 1) == argc) + { + [self usage]; + return nil; + } + + _distrusted_directory = [[NSString stringWithUTF8String:argv[iCnt + 1]] stringByExpandingTildeInPath]; + iCnt++; + } + else if (!strcmp(arg, "-c") || !strcmp(arg, "--certs_dir")) + { + if ((iCnt + 1) == argc) + { + [self usage]; + return nil; + } + + _certs_directory = [[NSString stringWithUTF8String:argv[iCnt + 1]] stringByExpandingTildeInPath]; + iCnt++; + } + else if (!strcmp(arg, "-e") || !strcmp(arg, "--ev_plist_path")) + { + if ((iCnt + 1) == argc) + { + [self usage]; + return nil; + } + + _ev_plist_path = [[NSString stringWithUTF8String:argv[iCnt + 1]] stringByExpandingTildeInPath]; + iCnt++; + } + + else if (!strcmp(arg, "-i") || !strcmp(arg, "--info_plist_path")) + { + if ((iCnt + 1) == argc) + { + [self usage]; + return nil; + } + + _info_plist_path = [[NSString stringWithUTF8String:argv[iCnt + 1]] stringByExpandingTildeInPath]; + iCnt++; + } + else if (!strcmp(arg, "-t") || !strcmp(arg, "--top_level_directory")) + { + if ((iCnt + 1) == argc) + { + [self usage]; + return nil; + } + + _top_level_directory = [[NSString stringWithUTF8String:argv[iCnt + 1]] stringByExpandingTildeInPath]; + iCnt++; + } + else if (!strcmp(arg, "-o") || !strcmp(arg, "--output_directory")) + { + if ((iCnt + 1) == argc) + { + [self usage]; + return nil; + } + + _output_directory = [[NSString stringWithUTF8String:argv[iCnt + 1]] stringByExpandingTildeInPath]; + iCnt++; + } + } + + if (nil == _root_directory) + { + _root_directory = [self checkPath:@"roots" basePath:_top_level_directory isDirectory:YES]; + if (nil == _root_directory) + { + [self usage]; + return nil; + } + } + + if (nil == _revoked_directory) + { + _revoked_directory = [self checkPath:@"revoked" basePath:_top_level_directory isDirectory:YES]; + if (nil == _revoked_directory) + { + [self usage]; + return nil; + } + } + + if (nil == _distrusted_directory) + { + _distrusted_directory = [self checkPath:@"distrusted" basePath:_top_level_directory isDirectory:YES]; + if (nil == _distrusted_directory) + { + [self usage]; + return nil; + } + } + + if (nil == _certs_directory) + { + _certs_directory = [self checkPath:@"certs" basePath:_top_level_directory isDirectory:YES]; + if (nil == _certs_directory) + { + [self usage]; + return nil; + } + } + + if (nil == _ev_plist_path) + { + _ev_plist_path = [self checkPath:@"EVRoots/EVRoots.plist" basePath:_top_level_directory isDirectory:NO]; + if (nil == _ev_plist_path) + { + [self usage]; + return nil; + } + } + if (nil == _info_plist_path) + { + _info_plist_path = [self checkPath:@"assetData/Info.plist" basePath:_top_level_directory isDirectory:NO]; + if (nil == _info_plist_path) + { + [self usage]; + return nil; + } + } + } + return self; +} + +- (void)usage +{ + printf("%s usage:\n", [self.app_name UTF8String]); + printf(" [-h, --help] \tPrint out this help message\n"); + printf(" [-r, --roots_dir] \tThe full path to the directory with the certificate roots\n"); + printf(" [-k, --revoked_dir] \tThe full path to the directory with the revoked certificates\n"); + printf(" [-d, --distrusted_dir] \tThe full path to the directory with the distrusted certificates\n"); + printf(" [-c, --certs_dir] \tThe full path to the directory with the cert certificates\n"); + printf(" [-e, --ev_plist_path] \tThe full path to the EVRoots.plist file\n"); + printf(" [-i, --info_plist_path]) \tThe full path to the Infor.plist file\n"); + printf(" [-t, --top_level_directory] \tThe full path to the top level security_certificates directory\n"); + printf(" [-o, --output_directory] \tThe full path to the directory to write out the results\n"); + printf("\n"); +} + +- (NSString*)checkPath:(NSString*)name basePath:(NSString *)basePath isDirectory:(BOOL)isDirectory +{ + NSString* result = nil; + if (nil == name) + { + return result; + } + + NSFileManager* fileManager = [NSFileManager defaultManager]; + BOOL isDir = NO; + + if ([name hasPrefix:@"/"] || [name hasPrefix:@"~"]) + { + name = [name hasPrefix:@"~"] ? [name stringByExpandingTildeInPath] : name; + // This is a full path + if (![fileManager fileExistsAtPath:name isDirectory:&isDir] || isDir != isDirectory) + { + NSLog(@"%@ is invalid", name); + return result; + } + result = name; + } + else + { + NSString* full_path = nil; + if (nil == basePath) + { + NSLog(@"%@ is not a full path but basePath is nil", name); + return result; + } + + full_path = [basePath stringByAppendingPathComponent:name]; + if (![fileManager fileExistsAtPath:full_path isDirectory:&isDir] || isDir != isDirectory) + { + NSLog(@"%@ is invalid", full_path); + return result; + } + result = full_path; + } + return result; +} + + +- (BOOL)processCertificates +{ + BOOL result = NO; + + NSString* path = self.root_directory; + PSCerts* root_certs = [[PSCerts alloc] initWithCertFilePath:path forBadCerts:NO]; + _roots = root_certs.certs; + + path = self.revoked_directory; + PSCerts* revoked_certs = [[PSCerts alloc] initWithCertFilePath:path forBadCerts:YES]; + _revoked = revoked_certs.certs; + + path = self.distrusted_directory; + PSCerts* distrusted_certs = [[PSCerts alloc] initWithCertFilePath:path forBadCerts:YES]; + _distrusted = distrusted_certs.certs; + + path = self.certs_directory; + PSCerts* certs_certs = [[PSCerts alloc] initWithCertFilePath:path forBadCerts:NO]; + _certs = certs_certs.certs; + + result = (nil != _roots && nil != _revoked && nil != _distrusted && nil != _certs); + return result; +} + +- (BOOL)outputPlistsToDirectory +{ + BOOL result = NO; + + NSString* path = self.output_directory; + + NSFileManager* fileManager = [NSFileManager defaultManager]; + BOOL isDir = NO; + NSError* error = nil; + + if (![fileManager fileExistsAtPath:path isDirectory:&isDir]) + { + // The directory does not exist so make it. + if (![fileManager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&error]) + { + return result; + } + + } + + // Now make all of the plists files + if (nil == _roots || nil == _revoked || nil == _distrusted || nil == _certs) + { + return result; + } + + NSArray* plist_data = [NSArray arrayWithObjects:_roots, _revoked, _distrusted, _certs, nil]; + NSDictionary* plist_input = [NSDictionary dictionaryWithObjects:plist_data forKeys:_plist_name_array]; + NSEnumerator* dict_enum = [plist_input keyEnumerator]; + + for (NSString* file_name in dict_enum) + { + NSString* full_path = [path stringByAppendingPathComponent:file_name]; + NSArray* data = [plist_input objectForKey:file_name]; + + NSMutableDictionary* rootObj = [NSMutableDictionary dictionaryWithCapacity:1]; + NSString* key_str = [file_name stringByDeletingPathExtension]; + [rootObj setObject:data forKey:key_str]; + + if (![self outputPlistToPath:full_path withData:rootObj]) + { + NSLog(@"Failed to write out plist for %@#", file_name); + } + } + + // Now output the EVRoots plist + NSString* full_path = [path stringByAppendingPathComponent:@"EVRoots.plist"]; + if (![fileManager copyItemAtPath:_ev_plist_path toPath:full_path error:&error]) + { + NSLog(@"Failed to copy the EVRoots.plist file"); + } + + // And the Info plist + full_path = [path stringByAppendingPathComponent:@"Info.plist"]; + if (![fileManager copyItemAtPath:_info_plist_path toPath:full_path error:&error]) + { + NSLog(@"Failed to copy the Info.plist file"); + } + + + return [self buildManifest:path]; +} + +- (BOOL)outputPlistToPath:(NSString *)path withData:(id)data +{ + BOOL result = NO; + NSError* error = nil; + + + NSData* prop_data = [NSPropertyListSerialization dataWithPropertyList:data format:NSPropertyListXMLFormat_v1_0 options:0 error:&error]; + if (nil != prop_data) + { + result = [prop_data writeToFile:path atomically:NO]; + } + return result; +} + +- (NSNumber*)getNextVersionNumber +{ + // This needs to read from a file location and then update the + // version number. For now just hard code and I'll fix this later + NSNumber* result = nil; + NSUInteger version = 100; + result = [NSNumber numberWithUnsignedInteger:version]; + + return result; +} + + +- (BOOL)buildManifest:(NSString *)path +{ + BOOL result = NO; + NSMutableDictionary* manifest_dict = [NSMutableDictionary dictionary]; + + NSNumber* versionNumber = [self getNextVersionNumber]; + [manifest_dict setObject:versionNumber forKey:@"Version"]; + + for (NSString* plist_file_path in _plist_name_array) + { + NSString* full_path = [self checkPath:plist_file_path basePath:path isDirectory:NO]; + if (nil == full_path) + { + NSLog(@"Could not find the %@ file", plist_file_path); + return result; + } + + CFDataRef dataRef = [PSUtilities readFile:full_path]; + if (NULL == dataRef) + { + NSLog(@"Could not read the file %@", plist_file_path); + return result; + } + + + + NSString* plist_file_data = [PSUtilities digestAndEncode:dataRef useSHA1:NO]; + CFRelease(dataRef); + if (nil == plist_file_data) + { + NSLog(@"Could not hash the file %@", plist_file_path); + return result; + } + + [manifest_dict setObject:plist_file_data forKey:plist_file_path]; + } + + // Now add the EVRoots plist + NSString* evRoots_path = [self checkPath:@"EVRoots.plist" basePath:path isDirectory:NO]; + if (nil == evRoots_path) + { + NSLog(@"Could not find the EVRoots.plist file"); + return result; + } + + CFDataRef dataRef = [PSUtilities readFile:evRoots_path]; + if (NULL == dataRef) + { + NSLog(@"Could not read the file %@", evRoots_path); + return result; + } + + NSString* ev_plist_file_data = [PSUtilities digestAndEncode:dataRef useSHA1:NO]; + CFRelease(dataRef); + if (nil == ev_plist_file_data) + { + NSLog(@"Could not hash the file %@", ev_plist_file_data); + return result; + } + + [manifest_dict setObject:ev_plist_file_data forKey:@"EVRoots.plist"]; + + + NSString* full_path = [path stringByAppendingPathComponent:@"Manifest.plist"]; + if (![self outputPlistToPath:full_path withData:manifest_dict]) + { + NSLog(@"Unable to write out the Manifest plist"); + return result; + } + + CFDataRef manifest_file_data = [PSUtilities readFile:full_path]; + if (NULL == manifest_file_data) + { + NSLog(@"Unable to read in the Manifest plist"); + return result; + } + + SecKeyRef signing_key = [PSUtilities getPrivateKeyWithName:@"Manifest Private Key"]; + + if (NULL == signing_key) + { + NSLog(@"Unable to get the signing key"); + return result; + } + + NSString* signature = [PSUtilities signAndEncode:manifest_file_data usingKey:signing_key useSHA1:YES]; + if (nil == signature) + { + NSLog(@"Unable to sign the manifest data"); + return result; + } + + [manifest_dict setObject:signature forKey:@"Signature"]; + + if (![self outputPlistToPath:full_path withData:manifest_dict]) + { + NSLog(@"Unable to write out the Manifest plist"); + return result; + } + return YES; +} + +- (BOOL)validate +{ + BOOL result = NO; + + NSString* path = self.output_directory; + + result = (ValidateAsset([path UTF8String], 99)) ? NO : YES; + + return result; +} +@end diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/PSUtilities.h b/certificates/ota_cert_tool/ios_ota_cert_tool/PSUtilities.h new file mode 100644 index 00000000..d9352043 --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/PSUtilities.h @@ -0,0 +1,28 @@ +// +// PSUtilities.h +// ios_ota_cert_tool +// +// Created by James Murphy on 12/12/12. +// Copyright (c) 2012 James Murphy. All rights reserved. +// + +#import +#import +#import + +@interface PSUtilities : NSObject + ++ (NSString*)digestAndEncode:(CFDataRef)cfData useSHA1:(BOOL)useSHA1; + ++ (CFDataRef)readFile:(NSString *)file_path; + ++ (SecCertificateRef)getCertificateFromData:(CFDataRef)data; + ++ (CFDataRef)getKeyDataFromCertificate:(SecCertificateRef)cert; + ++ (SecKeyRef)getPrivateKeyWithName:(NSString *)keyName; + ++ (NSString *)signAndEncode:(CFDataRef)data usingKey:(SecKeyRef)key useSHA1:(BOOL)useSHA1; + + +@end diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/PSUtilities.m b/certificates/ota_cert_tool/ios_ota_cert_tool/PSUtilities.m new file mode 100644 index 00000000..2393673c --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/PSUtilities.m @@ -0,0 +1,333 @@ +// +// PSUtilities.m +// ios_ota_cert_tool +// +// Created by James Murphy on 12/12/12. +// Copyright (c) 2012 James Murphy. All rights reserved. +// + +#import "PSUtilities.h" +#import + +@implementation PSUtilities + ++ (void)outputError:(NSString *)message withError:(CFErrorRef)error +{ + NSString* output = nil; + if (nil != error) + { + CFStringRef aCFStr = CFErrorCopyDescription(error); + if (NULL != aCFStr) + { + output = [NSString stringWithFormat:@"%@ error: %@", message, aCFStr]; + CFRelease(aCFStr); + } + } + + if (nil == output) + { + output = message; + } + + NSLog(@"%@",output); + if (NULL != error) + { + CFRelease(error); + } +} + ++ (NSString *)digestAndEncode:(CFDataRef)cfData useSHA1:(BOOL)useSHA1; +{ + CFErrorRef cfError = NULL; + NSString* result = nil; + CFTypeRef digestType = kSecDigestSHA2; + CFIndex digestLength = 256; + + if (useSHA1) + { + digestType = kSecDigestSHA1; + digestLength = 0; + } + + SecTransformRef digestXForm = SecDigestTransformCreate(digestType, digestLength, &cfError); + if (NULL != cfError) + { + CFRelease(cfData); + [PSUtilities outputError:@"Could not create the digesting transform." withError:cfError]; + return result; + } + + if (!SecTransformSetAttribute(digestXForm, kSecTransformInputAttributeName, cfData, &cfError)) + { + CFRelease(cfData); + CFRelease(digestXForm); + [PSUtilities outputError:@"Could not set the input attribute" withError:cfError]; + return result; + } + + SecTransformRef base64Xform = SecEncodeTransformCreate(kSecBase64Encoding, &cfError); + + if (NULL != cfError) + { + CFRelease(digestXForm); + [PSUtilities outputError:@"Could not create the encoding transform." withError:cfError]; + return result; + } + + SecGroupTransformRef groupXForm = SecTransformCreateGroupTransform(); + if (NULL == groupXForm) + { + CFRelease(digestXForm); + CFRelease(base64Xform); + NSLog(@"Could not create the group transform"); + return result; + } + + SecTransformConnectTransforms(digestXForm, kSecTransformOutputAttributeName, + base64Xform, kSecTransformInputAttributeName, + groupXForm, &cfError); + CFRelease(digestXForm); + CFRelease(base64Xform); + + if (NULL != cfError) + { + [PSUtilities outputError:@"Could not connect the transforms" withError:cfError]; + return result; + } + + CFDataRef cfResult = (CFDataRef)SecTransformExecute(groupXForm, &cfError); + CFRelease(groupXForm); + if (NULL != cfError) + { + [PSUtilities outputError:@"Could not execute the transform." withError:cfError]; + return result; + } + const void* pPtr = (const void*)CFDataGetBytePtr(cfResult); + NSUInteger len = (NSUInteger)CFDataGetLength(cfResult); + + NSData* temp_data = [[NSData alloc] initWithBytes:pPtr length:len]; + result = [[NSString alloc] initWithData:temp_data encoding:NSUTF8StringEncoding]; + + return result; + +} + ++ (CFDataRef)readFile:(NSString *)file_path +{ + CFDataRef result = NULL; + + @autoreleasepool + { + NSError* error = nil; + + if (nil == file_path) + { + NSLog(@"PSUtilities.readFile called with a nil file path"); + return result; + + } + + NSFileManager* fileManager = [NSFileManager defaultManager]; + BOOL isDir = NO; + if (![fileManager fileExistsAtPath:file_path isDirectory:&isDir]) + { + NSLog(@"PSUtilities.readFile %@ does not exist", file_path); + return result; + } + + if (isDir) + { + NSLog(@"PSUtilities.readFile %@ does exist but it is a directory", file_path); + return result; + } + + + NSData* temp_data = [NSData dataWithContentsOfFile:file_path options:0 error:&error]; + if (nil != error) + { + NSLog(@"NSData dataWithContentsOfFile returned error %@", file_path); + return result; + } + + result = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)[temp_data bytes], (CFIndex)[temp_data length]); + + } + + return result; +} + ++ (SecCertificateRef)getCertificateFromData:(CFDataRef)data +{ + SecCertificateRef result = NULL; + SecExternalFormat inputFormat = kSecFormatUnknown; + SecExternalItemType itemType = kSecItemTypeUnknown; + SecItemImportExportFlags flags = 0; + CFArrayRef outItems = NULL; + + OSStatus err = SecKeychainItemImport(data, NULL, &inputFormat, &itemType, flags, + NULL, NULL, &outItems); + if (errSecSuccess != err) + { + NSLog(@"Could not import data"); + } + + if (NULL != outItems) + { + CFIndex num_items = CFArrayGetCount(outItems); + if (num_items > 0) + { + CFTypeRef anItem = (CFTypeRef)CFArrayGetValueAtIndex(outItems, 0); + if (NULL != anItem && (CFGetTypeID(anItem) == SecCertificateGetTypeID())) + { + result = (SecCertificateRef)anItem; + } + } + + if (NULL != result) + { + CFRetain(result); + } + CFRelease(outItems); + } + return result; +} + ++ (CFDataRef)getKeyDataFromCertificate:(SecCertificateRef)cert +{ + CFDataRef result = NULL; + + if (NULL == cert) + { + return result; + } + + SecKeyRef aPublicKey = NULL; + OSStatus err = SecCertificateCopyPublicKey(cert, &aPublicKey); + if (errSecSuccess == err && NULL != aPublicKey) + { + err = SecItemExport(aPublicKey, kSecFormatBSAFE, 0, NULL, &result); + if (errSecSuccess != err) + { + result = NULL; + } + CFRelease(aPublicKey); + } + return result; +} + ++ (SecKeyRef)getPrivateKeyWithName:(NSString *)keyName +{ + SecKeyRef result = NULL; + NSArray* key_array = [NSArray arrayWithObjects:kSecClass, kSecAttrLabel, kSecReturnRef, nil]; + NSArray* obj_array = [NSArray arrayWithObjects:kSecClassKey, keyName, kCFBooleanTrue, nil]; + NSDictionary* query = [NSDictionary dictionaryWithObjects:obj_array forKeys:key_array]; + + OSStatus err = SecItemCopyMatching(CFBridgingRetain(query), (CFTypeRef *)&result); + if (errSecSuccess != err) + { + NSLog(@"Unable to find the Private Key"); + } + return result; +} + ++ (NSString *)signAndEncode:(CFDataRef)data usingKey:(SecKeyRef)key useSHA1:(BOOL)useSHA1 +{ + NSString* result = nil; + if (NULL == data || NULL == key) + { + return result; + } + + CFTypeRef digestType = kSecDigestHMACSHA2; + CFIndex digestLength = 256; + + if (useSHA1) + { + digestType = kSecDigestSHA1; + digestLength = 0; + } + + CFErrorRef error = NULL; + SecTransformRef signXForm = SecSignTransformCreate(key, &error); + if (NULL != error) + { + [PSUtilities outputError:@"Unable to create the signing transform" withError:error]; + return result; + } + + if (!SecTransformSetAttribute(signXForm, kSecTransformInputAttributeName, data, &error)) + { + CFRelease(signXForm); + [PSUtilities outputError:@"Could not set the input attribute" withError:error]; + return result; + } + + if (!SecTransformSetAttribute(signXForm, kSecDigestTypeAttribute, digestType, &error)) + { + CFRelease(signXForm); + [PSUtilities outputError:@"Unable to set the digest type attribute" withError:error]; + return result; + } + + CFNumberRef digest_length_number = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &digestLength); + if (!SecTransformSetAttribute(signXForm, kSecDigestLengthAttribute, digest_length_number, &error)) + { + CFRelease(signXForm); + CFRelease(digest_length_number); + [PSUtilities outputError:@"Unable to set the digest length attribute" withError:error]; + return result; + } + CFRelease(digest_length_number); + + if (!SecTransformSetAttribute(signXForm, kSecInputIsAttributeName, kSecInputIsPlainText, &error)) + { + CFRelease(signXForm); + [PSUtilities outputError:@"Unable to set the is plain text attribute" withError:error]; + return result; + } + + SecTransformRef base64Xform = SecEncodeTransformCreate(kSecBase64Encoding, &error); + if (NULL != error) + { + CFRelease(signXForm); + [PSUtilities outputError:@"Could not create the encoding transform." withError:error]; + return result; + } + + SecGroupTransformRef groupXForm = SecTransformCreateGroupTransform(); + if (NULL == groupXForm) + { + CFRelease(signXForm); + CFRelease(base64Xform); + NSLog(@"Could not create the group transform"); + return result; + } + + SecTransformConnectTransforms(signXForm, kSecTransformOutputAttributeName, + base64Xform, kSecTransformInputAttributeName, + groupXForm, &error); + CFRelease(signXForm); + CFRelease(base64Xform); + if (NULL != error) + { + [PSUtilities outputError:@"Could connect the signing and encoding transforms." withError:error]; + return result; + } + + CFDataRef cfResult = (CFDataRef)SecTransformExecute(groupXForm, &error); + CFRelease(groupXForm); + if (NULL != error) + { + [PSUtilities outputError:@"Could not execute the transform." withError:error]; + return result; + } + const void* pPtr = (const void*)CFDataGetBytePtr(cfResult); + NSUInteger len = (NSUInteger)CFDataGetLength(cfResult); + + NSData* temp_data = [[NSData alloc] initWithBytes:pPtr length:len]; + result = [[NSString alloc] initWithData:temp_data encoding:NSUTF8StringEncoding]; + return result; +} + + +@end diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/ValidateAsset.c b/certificates/ota_cert_tool/ios_ota_cert_tool/ValidateAsset.c new file mode 100644 index 00000000..3a797d43 --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/ValidateAsset.c @@ -0,0 +1,508 @@ +// +// ValidateAsset.c +// ios_ota_cert_tool +// +// Created by James Murphy on 12/13/12. +// Copyright (c) 2012 James Murphy. All rights reserved. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static const char* kPublicManifestKeyData = "MIIBCgKCAQEA7eev+hip+8Vg1kj/q4qnpN37X8vaKZouAyoXZ6gy+2D2wKxR0KORuV9bCFkcyT+LST/Rhn+64YNSZ7UvkQRlU34vZcF7FWuPfEbLGcCG7e1hlshHVUUah+07Qyu82f6OAg8PBFvYwvZHZMcXlvZJQjdNtbIORQfdlrGpRN1C6xKfbX6IKE9LViGQJmljdRuaK/SxmKyMsLfsTCzh+6yxMpPtY75PuSfrVcDSlGhr108QfP5n2WQ9frtyFgdowlXr/kECWSUrj8qDk1JymVd2ZyF3dlTWdzSO17vDt6caQyjQmTyGrGRGOM6THSq9mB/fv1Q5gxEfIIb8SejTvu4GSwIDAQAB"; + +static int ValidateFilesInDirectory(const char* dir_path, int num_files, const char * files[]) +{ + + int result = 0; // Assume all is well + DIR* dirp = NULL; + struct dirent* dp = NULL; + + dirp = opendir(dir_path); + if (NULL == dirp) + { + return -1; + } + + for (int iCnt = 0; iCnt < num_files; iCnt++) + { + int name_length = (int)strlen(files[iCnt]); + int found = 0; + while (NULL != (dp = readdir(dirp))) + { + if (dp->d_namlen == name_length && 0 == strcmp(dp->d_name, files[iCnt])) + { + found = 1; + } + } + if (0 == found) + { + (void)closedir(dirp); + + return -1; + } + rewinddir(dirp); + } + (void)closedir(dirp); + return result; +} + +static int ReadFileIntoCFDataRef(const char* file_path, CFDataRef* out_data) +{ + int result = -1; // guilt until proven + FILE* infile = NULL; + void* buffer = NULL; + int numbytes = 0; + + if (NULL == file_path || NULL == out_data) + { + return result; + } + + infile = fopen(file_path, "r"); + if (NULL == infile) + { + return result; + } + + fseek(infile, 0L, SEEK_END); + numbytes = (int)ftell(infile); + + fseek(infile, 0L, SEEK_SET); + buffer = calloc(numbytes, sizeof(char)); + if (NULL == buffer) + { + fclose(infile); + return result; + } + + fread(buffer, sizeof(char), numbytes, infile); + fclose(infile); + + *out_data = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)buffer, numbytes); + free(buffer); + result = (NULL != *out_data) ? 0 : -1; + return result; +} + +static int CreateHashForData(CFDataRef cfData, int useSHA1, CFDataRef* out_hash) +{ + int result = -1; // Guilty until proven + CCDigestAlgorithm algo = (useSHA1) ? kCCDigestSHA1 :kCCDigestSHA256; + size_t digest_length = (useSHA1) ? CC_SHA1_DIGEST_LENGTH : CC_SHA256_DIGEST_LENGTH; + UInt8 buffer[digest_length]; + + if (NULL == cfData || NULL == out_hash) + { + return result; + } + + *out_hash = NULL; + + memset(buffer, 0, digest_length); + + if (!CCDigest(algo, CFDataGetBytePtr(cfData), CFDataGetLength(cfData), buffer)) + { + *out_hash = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)buffer, digest_length); + } + else + { + return result; + } + + result = (NULL == *out_hash) ? -1 : 0; + return result; +} + +static int Base64Data(CFDataRef cfData, int for_encoding, CFDataRef* encoded_data) +{ + int result = -1; // Guilty until proven + CNEncodings encoding = kCNEncodingBase64; + CNStatus status = kCCSuccess; + CNEncodingDirection direction = (for_encoding) ? kCNEncode : kCNDecode; + unsigned char buffer[1024]; + size_t encoded_data_length = 1024; + + if (NULL == cfData || NULL == encoded_data) + { + return result; + } + memset(buffer, 0, 1024); + *encoded_data = NULL; + + status = CNEncode(encoding, direction, CFDataGetBytePtr(cfData), CFDataGetLength(cfData), buffer, &encoded_data_length); + if (kCCSuccess == status) + { + *encoded_data = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)buffer, encoded_data_length); + result = (NULL == *encoded_data) ? -1 : 0; + } + return result; +} + +static int CreatePropertyListFromData(CFDataRef prop_data, CFTypeID output_type, CFTypeRef* plistRef) +{ + int result = -1; // Guilt until proven + CFPropertyListRef aPlistRef = NULL; + CFPropertyListFormat list_format = kCFPropertyListXMLFormat_v1_0; + CFErrorRef error = NULL; + + if (NULL == prop_data || NULL == plistRef) + { + return result; + } + + *plistRef = NULL; + + aPlistRef = CFPropertyListCreateWithData(kCFAllocatorDefault, prop_data, 0, &list_format, &error); + if (NULL != error || NULL == aPlistRef) + { + if (NULL != error) + { + CFRelease(error); + } + return result; + } + + if (CFGetTypeID(aPlistRef) != output_type) + { + CFRelease(aPlistRef); + return result; + } + + *plistRef = aPlistRef; + result = (NULL == *plistRef) ? -1 : 0; + return result; +} + + +static int TearOffSignatureAndHashManifest(CFDictionaryRef manifestDict, CFDataRef* signature, CFDataRef* manifest_data) +{ + int result = -1; + CFMutableDictionaryRef new_manifest_dict = NULL; + CFStringRef sig_data_str = NULL; + CFDataRef sig_data = NULL; + CFDataRef prop_list = NULL; + CFDataRef decoded_sig_data = NULL; + + if (NULL == manifestDict || NULL == signature || NULL == manifest_data) + { + return result; + } + *signature = NULL; + *manifest_data = NULL; + + new_manifest_dict = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, CFDictionaryGetCount(manifestDict), manifestDict); + sig_data_str = (CFStringRef)CFDictionaryGetValue(new_manifest_dict, CFSTR("Signature")); + if (NULL == sig_data_str) + { + CFRelease(new_manifest_dict); + return result; + } + + sig_data = CFStringCreateExternalRepresentation(kCFAllocatorDefault, sig_data_str, kCFStringEncodingUTF8, 0); + if (NULL == sig_data) + { + CFRelease(sig_data_str); + CFRelease(new_manifest_dict); + return result; + } + + if (Base64Data(sig_data, 0, &decoded_sig_data)) + { + CFRelease(sig_data); + CFRelease(new_manifest_dict); + return result; + } + + *signature = decoded_sig_data; + + CFDictionaryRemoveValue(new_manifest_dict, CFSTR("Signature")); + prop_list = CFPropertyListCreateXMLData (kCFAllocatorDefault, new_manifest_dict); + CFRelease(new_manifest_dict); + if (NULL == prop_list) + { + return result; + } + + (void)CreateHashForData(prop_list, 1, manifest_data); + + result = (NULL == *manifest_data) ? -1 : 0; + return result; +} + +static int GetPublicManifestKey(CCRSACryptorRef* key_ref) +{ + int result = -1; + + CFStringRef encoded_key_data_str = NULL; + CFDataRef encoded_key_data_str_data = NULL; + CFDataRef decoded_key_data = NULL; + CCCryptorStatus ccStatus = kCCSuccess; + + if (NULL == key_ref) + { + return result; + } + *key_ref = NULL; + + encoded_key_data_str = CFStringCreateWithCString(kCFAllocatorDefault, kPublicManifestKeyData, kCFStringEncodingUTF8); + if (NULL == encoded_key_data_str) + { + return result; + } + + encoded_key_data_str_data = CFStringCreateExternalRepresentation(kCFAllocatorDefault, encoded_key_data_str, kCFStringEncodingUTF8, 0); + if (NULL == encoded_key_data_str_data) + { + CFRelease(encoded_key_data_str); + return result; + } + CFRelease(encoded_key_data_str); + + if (Base64Data(encoded_key_data_str_data, 0, &decoded_key_data)) + { + CFRelease(encoded_key_data_str_data); + return result; + } + CFRelease(encoded_key_data_str_data); + + ccStatus = CCRSACryptorImport(CFDataGetBytePtr(decoded_key_data), CFDataGetLength(decoded_key_data), key_ref); + CFRelease(decoded_key_data); + + if (kCCSuccess != ccStatus) + { + *key_ref = NULL; + } + else + { + result = 0; + } + return result; +} + + +static int ValidateSignature(CFDataRef signature, CFDataRef data) +{ + int result = -1; + CCRSACryptorRef key_ref = NULL; + CCCryptorStatus ccStatus = kCCSuccess; + + + if (NULL == signature || NULL == data) + { + return result; + } + + // Get the key + if (GetPublicManifestKey(&key_ref)) + { + return result; + } + + const void *hash_data_ptr = CFDataGetBytePtr(data); + size_t hash_data_len = CFDataGetLength(data); + + const void* sig_data_pre = CFDataGetBytePtr(signature); + size_t sig_dat_len = CFDataGetLength(signature); + + ccStatus = CCRSACryptorVerify( + key_ref, + ccPKCS1Padding, + hash_data_ptr, + hash_data_len, + kCCDigestSHA1, + 0, + sig_data_pre, + sig_dat_len); + + + CCRSACryptorRelease(key_ref); + + result = (kCCSuccess == ccStatus) ? 0 : -1; + return result; +} + +int ValidateAsset(const char* asset_dir_path, unsigned long current_version) +{ + const char* files[] = + { + "certs.plist", + "distrusted.plist", + "EVRoots.plist", + "Manifest.plist", + "revoked.plist", + "roots.plist" + }; + int num_files = (sizeof(files) / sizeof(const char*)); + int iCnt = 0; + const char* file_name = NULL; + char wd_buf[1024]; + + const char* current_working_directory_path = getcwd(wd_buf, 1024); + CFDataRef file_data = NULL; + CFDataRef hash_data = NULL; + CFDataRef encoded_hash_data = NULL; + CFStringRef manifest_hash_data_str = NULL; + CFDataRef signature_data = NULL; + CFStringRef key_name = NULL; + CFDictionaryRef manifest_dict = NULL; + CFNumberRef manifest_version = NULL; + CFStringRef encoded_hash_str = NULL; + CFDataRef manifest_data = NULL; + unsigned long manifest_verson_number; + int iResult = -1; + + // parameter check + if (NULL == asset_dir_path) + { + return iResult; + } + + if (ValidateFilesInDirectory(asset_dir_path, num_files, files)) + { + return iResult; + } + + if (chdir(asset_dir_path)) + { + return iResult; + } + + if (ReadFileIntoCFDataRef("Manifest.plist", &file_data)) + { + (void)chdir(current_working_directory_path); + return iResult; + } + + if (CreatePropertyListFromData(file_data, CFDictionaryGetTypeID(), (CFTypeRef *)&manifest_dict)) + { + CFRelease(file_data); + (void)chdir(current_working_directory_path); + return iResult; + } + CFRelease(file_data); + + // Validate the hash for the files in the manifest + for (iCnt = 0; iCnt < num_files; iCnt++) + { + file_name = files[iCnt]; + // bypass the manifest file for now + if (!strcmp("Manifest.plist", file_name)) + { + continue; + } + + if (ReadFileIntoCFDataRef(file_name, &file_data)) + { + CFRelease(manifest_dict); + (void)chdir(current_working_directory_path); + return iResult; + } + + if (CreateHashForData(file_data, 0, &hash_data)) + { + CFRelease(file_data); + CFRelease(manifest_dict); + (void)chdir(current_working_directory_path); + return iResult; + } + CFRelease(file_data); + + + if (Base64Data(hash_data, 1, &encoded_hash_data)) + { + CFRelease(hash_data); + CFRelease(manifest_dict); + (void)chdir(current_working_directory_path); + return iResult; + } + CFRelease(hash_data); + + encoded_hash_str = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, encoded_hash_data, kCFStringEncodingUTF8); + if (NULL == encoded_hash_str) + { + CFRelease(encoded_hash_data); + CFRelease(manifest_dict); + (void)chdir(current_working_directory_path); + return iResult; + } + CFRelease(encoded_hash_data); + + key_name = CFStringCreateWithCString(kCFAllocatorDefault, file_name, kCFStringEncodingUTF8); + if (NULL == key_name) + { + CFRelease(encoded_hash_str); + CFRelease(manifest_dict); + (void)chdir(current_working_directory_path); + return iResult; + } + + manifest_hash_data_str = (CFStringRef)CFDictionaryGetValue(manifest_dict, key_name); + if (NULL == manifest_hash_data_str) + { + CFRelease(key_name); + CFRelease(encoded_hash_str); + CFRelease(manifest_dict); + (void)chdir(current_working_directory_path); + return iResult; + } + CFRelease(key_name); + + if (!CFEqual(encoded_hash_str, manifest_hash_data_str)) + { + CFRelease(encoded_hash_str); + CFRelease(manifest_dict); + (void)chdir(current_working_directory_path); + return iResult; + } + CFRelease(encoded_hash_str); + } + + // Get the version + manifest_version = (CFNumberRef)CFDictionaryGetValue(manifest_dict, CFSTR("Version")); + if (NULL == manifest_version) + { + CFRelease(manifest_dict); + (void)chdir(current_working_directory_path); + return iResult; + } + + if (!CFNumberGetValue(manifest_version, kCFNumberLongType, &manifest_verson_number)) + { + CFRelease(manifest_version); + CFRelease(manifest_dict); + (void)chdir(current_working_directory_path); + return iResult; + } + CFRelease(manifest_version); + if (manifest_verson_number < current_version) + { + CFRelease(manifest_dict); + (void)chdir(current_working_directory_path); + return iResult; + } + + // Deal with the signature + if (TearOffSignatureAndHashManifest(manifest_dict, &signature_data, &manifest_data)) + { + CFRelease(manifest_dict); + (void)chdir(current_working_directory_path); + return iResult; + } + + iResult = ValidateSignature(signature_data, manifest_data); + CFRelease(signature_data); + CFRelease(manifest_data); + CFRelease(manifest_dict); + (void)chdir(current_working_directory_path); + return iResult; +} \ No newline at end of file diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/ValidateAsset.h b/certificates/ota_cert_tool/ios_ota_cert_tool/ValidateAsset.h new file mode 100644 index 00000000..f46a8faf --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/ValidateAsset.h @@ -0,0 +1,16 @@ +// +// ValidateAsset.h +// ios_ota_cert_tool +// +// Created by James Murphy on 12/13/12. +// Copyright (c) 2012 James Murphy. All rights reserved. +// + +#ifndef ios_ota_cert_tool_ValidateAsset_h +#define ios_ota_cert_tool_ValidateAsset_h + +int ValidateAsset(const char* asset_dir_path, unsigned long current_version); + + + +#endif diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/ccMemory.h b/certificates/ota_cert_tool/ios_ota_cert_tool/ccMemory.h new file mode 100644 index 00000000..1db423da --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/ccMemory.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2010,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@ + */ + +/* + * ccMemory.h + * CommonCrypto + */ + +#ifndef CCMEMORY_H +#define CCMEMORY_H + +#ifdef KERNEL +#define CC_XMALLOC(s) OSMalloc((s), CC_OSMallocTag) +#define CC_XFREE(p, s) OSFree((p), (s), CC_OSMallocTag) +#else /* KERNEL */ +#include +#include + +#define CC_XMALLOC(s) malloc(s) +#define CC_XCALLOC(c, s) calloc((c), (s)) +#define CC_XREALLOC(p, s) realloc((p), (s)) +#define CC_XFREE(p, s) free(p) +#define CC_XMEMCPY(s1, s2, n) memcpy((s1), (s2), (n)) +#define CC_XMEMCMP(s1, s2, n) memcmp((s1), (s2), (n)) +#define CC_XMEMSET(s1, s2, n) memset((s1), (s2), (n)) +#define CC_XZEROMEM(p, n) memset((p), 0, (n)) +#define CC_XSTRCMP(s1, s2) strcmp((s1), (s2)) +#define CC_XSTORE32H(x, y) do { \ +(y)[0] = (unsigned char)(((x)>>24)&255); \ +(y)[1] = (unsigned char)(((x)>>16)&255); \ +(y)[2] = (unsigned char)(((x)>>8)&255); \ +(y)[3] = (unsigned char)((x)&255); \ +} while(0) +#define CC_XSTORE64H(x, y) \ +{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ +(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ +(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ +(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } + +#define CC_XMIN(a,b) (((a)<(b))?(a):(b)) + + +#define CC_XQSORT(base, nelement, width, comparfunc) qsort((base), (nelement), (width), (comparfunc)) + +#define CC_XALIGNED(PTR,NBYTE) (!(((size_t)(PTR))%(NBYTE))) +#endif + + + + +#endif /* CCMEMORY_H */ diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/ios_ota_cert_tool-Prefix.pch b/certificates/ota_cert_tool/ios_ota_cert_tool/ios_ota_cert_tool-Prefix.pch new file mode 100644 index 00000000..d0953106 --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/ios_ota_cert_tool-Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'ios_ota_cert_tool' target in the 'ios_ota_cert_tool' project +// + +#ifdef __OBJC__ + #import +#endif diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/ios_ota_cert_tool.1 b/certificates/ota_cert_tool/ios_ota_cert_tool/ios_ota_cert_tool.1 new file mode 100644 index 00000000..7dd1de9f --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/ios_ota_cert_tool.1 @@ -0,0 +1,79 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. +.\"See Also: +.\"man mdoc.samples for a complete listing of options +.\"man mdoc for the short list of editing options +.\"/usr/share/misc/mdoc.template +.Dd 12/11/12 \" DATE +.Dt ios_ota_cert_tool 1 \" Program name and manual section number +.Os Darwin +.Sh NAME \" Section Header - required - don't modify +.Nm ios_ota_cert_tool, +.\" The following lines are read in generating the apropos(man -k) database. Use only key +.\" words here as the database is built based on the words here and in the .ND line. +.Nm Other_name_for_same_program(), +.Nm Yet another name for the same program. +.\" Use .Nm macro to designate other names for the documented program. +.Nd This line parsed for whatis database. +.Sh SYNOPSIS \" Section Header - required - don't modify +.Nm +.Op Fl abcd \" [-abcd] +.Op Fl a Ar path \" [-a path] +.Op Ar file \" [file] +.Op Ar \" [file ...] +.Ar arg0 \" Underlined argument - use .Ar anywhere to underline +arg2 ... \" Arguments +.Sh DESCRIPTION \" Section Header - required - don't modify +Use the .Nm macro to refer to your program throughout the man page like such: +.Nm +Underlining is accomplished with the .Ar macro like this: +.Ar underlined text . +.Pp \" Inserts a space +A list of items with descriptions: +.Bl -tag -width -indent \" Begins a tagged list +.It item a \" Each item preceded by .It macro +Description of item a +.It item b +Description of item b +.El \" Ends the list +.Pp +A list of flags and their descriptions: +.Bl -tag -width -indent \" Differs from above in tag removed +.It Fl a \"-a flag as a list item +Description of -a flag +.It Fl b +Description of -b flag +.El \" Ends the list +.Pp +.\" .Sh ENVIRONMENT \" May not be needed +.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 +.\" .It Ev ENV_VAR_1 +.\" Description of ENV_VAR_1 +.\" .It Ev ENV_VAR_2 +.\" Description of ENV_VAR_2 +.\" .El +.Sh FILES \" File used or created by the topic of the man page +.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact +.It Pa /usr/share/file_name +FILE_1 description +.It Pa /Users/joeuser/Library/really_long_file_name +FILE_2 description +.El \" Ends the list +.\" .Sh DIAGNOSTICS \" May not be needed +.\" .Bl -diag +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .El +.Sh SEE ALSO +.\" List links in ascending order by section, alphabetically within a section. +.\" Please do not reference files that do not exist without filing a bug report +.Xr a 1 , +.Xr b 1 , +.Xr c 1 , +.Xr a 2 , +.Xr b 2 , +.Xr a 3 , +.Xr b 3 +.\" .Sh BUGS \" Document known, unremedied bugs +.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file diff --git a/certificates/ota_cert_tool/ios_ota_cert_tool/main.m b/certificates/ota_cert_tool/ios_ota_cert_tool/main.m new file mode 100644 index 00000000..cbd3b1c5 --- /dev/null +++ b/certificates/ota_cert_tool/ios_ota_cert_tool/main.m @@ -0,0 +1,71 @@ +// +// main.m +// ios_ota_cert_tool +// +// Created by James Murphy on 12/11/12. +// Copyright (c) 2012 James Murphy. All rights reserved. +// + +#import +#import "PSIOSCertToolApp.h" + +/* + printf("%s usage:\n", [self.app_name UTF8String]); + printf(" [-h, --help] \tPrint out this help message\n"); + printf(" [-r, --roots_dir] \tThe full path to the directory with the certificate roots\n"); + printf(" [-k, --revoked_dir] \tThe full path to the directory with the revoked certificates\n"); + printf(" [-d, --distrusted_dir] \tThe full path to the directory with the distrusted certificates\n"); + printf(" [-c, --certs_dir] \tThe full path to the directory with the cert certificates\n"); + printf(" [-e, --ev_plist_path] \tThe full path to the EVRoots.plist file\n"); + printf(" [-t, --top_level_directory] \tThe full path to the top level security_certificates directory\n"); + printf(" [-o, --output_directory] \tThe full path to the directory to write out the results\n"); + printf("\n"); +*/ + +int main(int argc, const char * argv[]) +{ +//#define HARDCODE 1 + +#ifdef HARDCODE + + const char* myArgv[] = + { + "foo", + "--top_level_directory", + "~/PR-10636667/security/certificates", + "--output_directory", + "~/cert_out" + }; + + int myArgc = (sizeof(myArgv) / sizeof(const char*)); + + argc = myArgc; + argv = myArgv; +#endif // HARDCODE + + + @autoreleasepool + { + PSIOSCertToolApp* app = [[PSIOSCertToolApp alloc] init:argc withArguments:argv]; + if (![app processCertificates]) + { + NSLog(@"Could not process the certificate directories"); + return -1; + } + + if (![app outputPlistsToDirectory]) + { + NSLog(@"Could not output the plists"); + return -1; + } + + if (![app validate]) + { + NSLog(@"Could not validate the output plists"); + return -1; + } + + } + return 0; +} + diff --git a/certificates/removed/AOLTimeWarner1.der b/certificates/removed/AOLTimeWarner1.der new file mode 100644 index 0000000000000000000000000000000000000000..49df4b3fda67b87533dfd8f51a543e173324b727 GIT binary patch literal 1002 zcmXqLVt!`O#B^=}GZP~d6CAW;Q!O?20?yJs-8C%{KU8Ww&TIWWAbL}xu0=}x^6h!oPd&ML zeN{wY`-czR9)6Dw9f`~|NZMwwsE1o{W}<0s-TR{(CD{~&`kWr#=bt7JwBr1n_^Bc{ z)?1fy8!E`V=r2lg+`L;t@%E`go1Qn@cJj`DANbz4TIdru&%-qi{pIx=PE{20#EKOb zEV_Qks`V`2tRoK?He6MGbw~Tj6kUrsosQut8mW>p+g!GsFwE{_tS*aGtrwMP;ixH2 zRp464q9~a%Vk{yH%?!j&w@qMhZ3y1jf8vI1&Axac z19_0NGK++PSOazid>{q%%hlx~e}HpYMcjiLe!uJ;LwguiHB>J-oa#VDmn~*{>|j`_(J+|3_A@$ZI`+*?XnuhWHJZ8X0`WcU5QI69NDfylgrE literal 0 HcmV?d00001 diff --git a/certificates/removed/AOLTimeWarner2.der b/certificates/removed/AOLTimeWarner2.der new file mode 100644 index 0000000000000000000000000000000000000000..11bacade59612fff151e17c9bf45e6225049b3cb GIT binary patch literal 1514 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 JPBeIR767vB2!{Xw literal 0 HcmV?d00001 diff --git a/certificates/removed/JCSSecureSignRootCA11.cer b/certificates/removed/JCSSecureSignRootCA11.cer new file mode 100644 index 0000000000000000000000000000000000000000..1f36f7c0c0c389c7566630eaf370a2a4a4f8f384 GIT binary patch literal 881 zcmXqLV$L;aVhUZr%*4pV#K>sC%f_kI=F#?@mywZ`mBApwklTQhjX9KsO_<3mz);&j z6U5;XR`NZ!)qnFgG#s zGZ-{6axpbAGBW%vU$srONF9r~Phtkv}k(=n^9Nt@RHnzMh&vnve- zGd}Zfo7}(h$_=wm8~${i(pe~KJk{{l0qIZgl4iCg+wZ?SS*v+P*-l~k?dSZQTKkor z>q&i@%DIVktBYUxLWR96KlyRh2CV(c%IoUyR`^%LF8DXg4c+UhvR=}^&RcIVoMoDK zqMPk9!^BThI8uE!ny@icbw2uVoH_FR)oU-78*P3z!=dfyS#_cAGu7v|3)&g1ziDaP6{|}h zlV>g1$N4RM`#l3bkTgFd<9`+wVDe!z;0N)AL3~yNW*~(e%D}_~3}r@!1q&_2()5;x z$t%ub`z8B!r_xaiwHto^Zx+{A-g8r2*k0bx&M|A#lB4VSjb?Dyq-k!OU8@@8>Ac!U zPdl%wV7(aMW2T(nPR}Ify50yq@xuD<^M_ybxMfUYaw5Eb_jClrPnFsKcD2&h)XlBC z=JD@X`?N~BE5J&2FYlh}kO1zTPU}M#NHnfZo%w#>lR5j3w61pC6q0{O_3Yb?<5l9`{U;Fnrbo?n!0C~hDMQpF|A2UDe^;F*`KXJ~3*43gj$)`3YVIOil57b_Sl z1mx#rCRZYx=2%*ikzbTqQfa7YAP>^UEG&^xQc_^0uU}qXu2%-MHyP*vz2y8{eM1EU zIk;mv8N~!M^V0Gikd+w7iSt@o8kiZG8W|ZGn^;7N^BN*^hq&(==Of1!BP#=QV=pkq zI++?98E!;2Rdw!|wriPwMt+3e@(>xeyf3eMJ@yz*5&!VnZ_lP3rjyDxTv)o4@j3&u zkdh?FkN<+ov(K@A-JdC?_RsI-#rnBA4ziIMdCPu8Y?v$6f7$-y9Z9yv6?_k@?w$yC z|gY;YAJqVzqECE(7!nww>^q37k7A7bWQoR zMx)VThDwPyk>Z^vk7dafp8UJLWT~oa=24H;k`G4zzwf_6E-oV2j=9X+< dX}4hM|81Vk!nc&pye(|fo_XGC`&Zqf69DKC2I>F+ literal 0 HcmV?d00001 diff --git a/certificates/removed/ValiCertClass2PVA.cer b/certificates/removed/ValiCertClass2PVA.cer new file mode 100644 index 0000000000000000000000000000000000000000..90f10c1d52955eaa27c3b193bb6dc6f05ac87109 GIT binary patch literal 747 zcmXqLVtQ`S#1z29$Y{XJ#;Mij(e|B}k&%^^!Ju)sp^AYL8*?ZNyRdXvVos)WYEg*- zh>?<5l9`{U;Fnrbo?n!0C~hDMQpF|A2UDe^;F*`KXJ~3*43gj$)`3YVIOil57b_Sk z1mx#rCRZYx=2%*ikzbTqQfa7YAP>^UEG&^xQc_^0uU}qXu2%-MHyP*vz2y8{eM1EU zIk;mv8N~!M^V0Gikd+w7iSt@o8kiZG85kH^nwmt3^BN*^hq&(==Of1!BP#=QV=pkq zI++?98O~W1o_f0aMC7E<>#J{+@cn#u^INEUWU4zKYv`TVGt6vaf@3cmoVR$h*Rk`h zsuQP5Hdox{n!7=|KF_XPtBs0WnR>-jSXaeYCLn+7!PXG#e}zvj$2k3Lcra0lE85a5 z{j+^&jkNui_>^Lk$6JK*&py{*(L!a;76%q9dD;c)#e%ZU;@g~2?JH?<5l9`{U;Fnrbo?n!0C~hDMQpF|A2UDe^;F*`KXJ~3*43gj$)`3YVIOil57b_Sm z1mx#rCRZYx=2%*ikzbTqQfa7YAP>^UEG&^xQc_^0uU}qXu2%-MHyP*vz2y8{eM1EU zIk;mv8N~!M^V0Gikd+w7iSt@o8kiZG85kHD85>85^BN*^hq&(==Of1!BP#=QV=pkq zI++?986M9FoF?<)>PEK4tnkA{rIS~mpSSGKXR)Aby1w>~_F^__BL;S!jMOH-El; zb?kk!LXnyMcMeVZ_&j0K^fxy=?(9Fvq;O1SiH46sR9WuEn9q0b%@ZhG*l|31wqx$8 z4LkZo->o&)KJU&FQ(DM1LuH2Ma?i-6cYkbmPD=cI`O$??dnRT^2K2S^0%u!jlW(_pZjGCm%!$eM|B=e$||f-|5VWIblL9w%8)M~Z%h*FxyW+bd-cir zuIp^NR&FRXjy-WS{QmkCrkm?K+h4v=owTFAwQAk9J#yv|TInYzp4V!$dwb0C{sBA5 eIg)3DeVZJ&_S}15o4}#K?^>6=sD5#e=sN%}p$eD) literal 0 HcmV?d00001 diff --git a/certificates/removed/persbasi.crt b/certificates/removed/persbasi.crt new file mode 100644 index 0000000000000000000000000000000000000000..79308aa16e704b41445fe15ec3e8d49896d199f7 GIT binary patch literal 805 zcmXqLVpcS0V(MDJ%*4pV#K>U4%f_kI=F#?@mywZ$mBFC#v>~?vCmVAp3!5-gl%t`j zfiQ@}A9##2f{u#Ny0k1!qUFVK7H?GKxtSKvn1_fmAq@fNj@H&d)WF6X&%w zGcW`~Fo+W8H8LG2j?CL@NW`* z<}t-|S=7FKr(gW;@5)Py?)G}lo)*5K;>s!ez|EQ56U)Sv*r#V537qWxp!dD`)P+30 zw@fC;ig!+bU}_QWb>Is}!Al#L>VUe$SrZ;BU+xfeQ~%1%&bRyS#d-y}FsJWCl7` z_tDJk4YpOC*CQ8AVU*XtE94z~Xl?zf=t^uMmIG(&}_4ZuYV5n{s!TtbbyEdinMZ4`TOKG^6mZp|b!_dc#^O0kfk(GhDu@@M#olK353@6iW{$O`G zzq3d0!@~E%t~spt@2QIgnmG#QZ nPmLmjZkK8VMDqOLmVC12=K5*9`T@7u55JOMZT#S?wqYj#OJ5H| literal 0 HcmV?d00001 diff --git a/certificates/revoked/*.EGO.GOV.TR.cer b/certificates/revoked/*.EGO.GOV.TR.cer new file mode 100644 index 0000000000000000000000000000000000000000..21fbebe0d90cb3253d73b4ede4259fda347d30c9 GIT binary patch literal 1345 zcmXqLVzo7BVo_bd%*4pV#KfU)z{|#|)#lOmotKf3m6gGuagCv^fi)X*C<`->Nyyvt~sgMB}Mspnb``#rFo^vr3%5RMJ1VOnc0cOM>Z;WWLD*-mgJ-sWg2oD zaDue62{VNR8O9mJfH+({p-5&qW#*)3DjeC6lUkB_bbe;8LRqQ;Pz=I$KfI?bH7_Ug z$oxzsQxzQbj?U9l&`8!)@CI3!tDsC(dhVXkY<^<_6}bhEd|YMutG98I)^~ zhw2=Dpm%}J;oxC&^z(KMax{bru)_s-47eZ;W_ES=HXBbn41{+8GzzkOihf84EyK2=ugNj zi@SK`{Ackc@{dk$6F+@;MN8MdC+|+o@MWlQl_*#vXSV1_GW(|4n=i#)eeS9C$6;E| zeHG2+lh??W-eg`KX=?U<#k%Ez3xB+Hu~Mns7h(~@{N>`+DLr5JX*X4$6E z-q}3mi#Y$1pHhJvnGXC@my8koxcEbhoWF!n%=c3-X5PNj*(tJAx$ltoB)3}{%)0}p zY|ML~B4sx9?3LT|*y}p(E?aEpD{)Ho(`|n7X-vBv`uIH+(!JJC$P3IUOij}htbJs@ zd%50HuFBLkjp0jWk48>9{3M;@MbT1Ly+4fn9R@;2<)m4{`Fx%1ONvBha)lp^5Gz(( zTI1>`aVe@);#11y=g{<>lpiC8b5cWL;WZqL-YXt5;H_ zUtF4Mzz;G;7-TG~0Z{*c15c2EJd2ZogMr-wn*~;F7I=-w%+U`Cg=U=i;9#HlU{9a; zVk5oeq8x+9RWO$@GO{$zHE5h=kOvbnU}{UkYcMRw3*Z2lc|aB}$HdAj!{Z3TXc&Qxt(^|X5uo6^-L-?O@B(ht7< zFsu5=S`V$O3~w11r?Muq7`>$W}#f7H+UH^zt rP3Uf(SLk9F#S6S8vkm?Kq^dmq|7V_*ncSyaAt%E2M|Bm%bF=~g+z#A$ literal 0 HcmV?d00001 diff --git a/certificates/revoked/*.google.com.cer b/certificates/revoked/*.google.com.cer new file mode 100644 index 0000000000000000000000000000000000000000..81503a39a728bdf805a0b6477c3d969614bb4fa7 GIT binary patch literal 1459 zcmXqLVqI_0#4>#WGZP~dlK@x81c!4%d8y&+4mnkO9sF&;%f_kI=F#?@mywZ`mBAp- zklTQhjX9KsO_(Vp$dDf>59Dz0usQm9I|ezz1lZvMJO*4K6buI~PZ5(Z)*9ybp^ zkf-3}>ErIH;2G@W>T4)!APkaW=Hb!O1Ip>S`-ka;1R2PQ^BNi%8X1@wSeTj`nnnS+ z#z2m_p{0qjk$IFs8j^cLgAIiZ1i|hR=5kKV$xO>H%F9eN6f+P339<|G`sSDBl_X~7 zDTHOFmctZt33IvU=cnhSDtP84!`&eQbVoW^ST8w0*PwAea!4?;GB7vxG8i;=GBq|b ztofOF^2GGd9%s|PXrvc-h^0BO$^Tj_bZL&u%Sp$+HUGT+J|Rt^#WAIU=PvWU9s?We zy@`)4ryn&F{mA6{_|+MEE?364TFW?=vLDx7`Iq^=bg%ytuLE}?{$pHrZpp+@h$oQXy)qok8K#_ADu>4_e z0*VRWDEi~Q(lR1b?K`thro8CYwg4O3yN^CsZd$P8^{h~($|F5d9aqf_lXny;WmO-P z{I>a+ltgRYLI%5svKO^K&p&hedG0wm9(l*P#xcc*TkfAqF*08y!v5+mOAhao)?$rs z?d_4`hw=>t3a8w>YwdKo;fuk<$!+EzuUW2on)rTZ(uQp>?k8Mn)ZuCItIV3ZQBtIi zoA=s`Y_*iTkrxlQOgO%0NsdWh@3uo5y%;@XEj9$oa3<#mFH$_=%wVHZWE5~~LT*g) z#qGg9^CXL{J-A=loiFjROkn%)w$c2v-v9hm%Nd7j9`Pzq3=p(@=Ggv^v37Y&gXP|D O_Zd#AN85K^Mn+av27|_phTI06Y|No7Y{E>T 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 FQUFbQ?V$hw literal 0 HcmV?d00001 diff --git a/certificates/revoked/DigiNotar092706.cer b/certificates/revoked/DigiNotar092706.cer new file mode 100644 index 0000000000000000000000000000000000000000..05b9468bb2382fb0575180c0bd2aa58a5c1a7418 GIT binary patch literal 1340 zcmXqLVzn@6Vp+I=nTe5!iG^KVfZ2eTjZ>@5qwPB{BO@y-gF&eww*e;`b0`a&FjHu- zp@e}Lh{Gk!?;hf+;GADnkYAKol9``psBWMNlHnGX1Ittadi zD0t>2>lrE=D1sC+3rnFXbkE68O3YCR%Fiz`kQ3)MFf*_;GB-3ZH8wVi66ZBEgmR6H z4WbO}keub`V<==G0C5(lOJ;heUw%nqk)gDKB*Y#exR`=7$XN=`js{IkO2|HCWMyD( zV&Z22igPhFF)=b+Iw#7dyCSY7eeK_U@7<1{*m=JA&li)OKXsg+CkWeCJ>GQQIz4B? z+5e(mtJ3xf}}DrL@HU>|s&+i@cA(uXTn#dvbW?!8ywxRL*4a`xqVlM*I-bD^m3i8kLY^7W=a z$Pcp!xva5utw^4pcgj}v)a|9JoZHxKr-m_cH6?5+c70&17FaTC=am4NZ@$sdK|#V% z%j%c&J$&I9l0KuS{p!ifIj1j&Ok(3Sas1wxZ$Iy3O=;+c=La{Jzc_q^!E~xafq)n5 zJ=NXwBbTP^aZlKv@VKm7IP~trlB%8ORhDJd-%C+)iO6Wm68LHR)J}Tm-akrT5?DHS zhvsU8{<_!KE3GJU-MrhR+V|V0O#+ni!i5gn$W2R+y3T zKMRKe8<1jRWHbl{i7Bx77 z^~=l4^$JRpax#;3OF+3oFF8L~-#H*y-#<4m6O`ihGD>oD4ER8X@`Eg50cJ@ygT@6Q z0cDoP83v708$_1z$j(pv&n~`ozlGavXM?MK8-mytRxT+Ypj-;fC`%1oK`xYMu`{qS zuv%cTz^u&#pO=%hrt~Tv-aN_cVK3Gx zv*$J+ntQ<|H=^XdWqvf4Ip!{GZF3r4xVW@9m`-CaZXk zheoe44XL-EE2ZTXt6h=#lj-U6<@=^4&n;EpFzHGwdef{NQMB8jPGTa1SAMRk|F3oD E0qF?sR{#J2 literal 0 HcmV?d00001 diff --git a/certificates/revoked/DigiNotar100406.cer b/certificates/revoked/DigiNotar100406.cer new file mode 100644 index 0000000000000000000000000000000000000000..c25eb8290bd398bf664704be94d2e6271f81976c GIT binary patch literal 1374 zcmXqLVvRCrVmZ8knTe5!iG^KVfY*SRjZ>@5qwPB{BO@y-gF&eww*e;`b0`a&FjHu- zp@e}Lh{Gk!?;hf+;GADnkYAKol9``psBWMNlHnGX1Ittadi zD0t>2>lrE=D1sC+3rnFXbkE68O3YCR%Fiz`kQ3)MFf%kTFflYRH8C`d66ZBEgmR66 zT!RE8XZiUU3K6mV&dRp@M-N+@G9`VuG1@ zY55K*K)rb&y?S{$22D&#$YH_A%D~*j#LoZ}=VEGNVq~~Nr175Voy)yy?7kdd`Hk2X@-G1br}dx>IsT!+LMfmgQ@TT*Z%l=zP6p zmFlNh@3@OM+jm{7t@(P+Xug2)(T!fa<0cv&y71ER(8QEFPDkt8-5lmwt4;;o+iEFy zpo4j-efLb^MCYxun>N2w$Unc(Wzj4BY=`;%+Tm*#1|Mow%AC8vKJY%b<3!%24_B;; z@#Kizd#}K8Bmc?d?925gB~1DzQ5B^!8C8wxU7v3`d`L+CGD+b&^D^7Ta_L7}q#c)@ z?0L5LmB%(#F^rH=TGD*-a!e50d-f`p@%)i39J_`)$HeMV3F)svTVPG1h0#Kvjj_`NaT ze%{HN($Edh4{k1harg*>=~RaT0Wa2js=Mb$E=}3vp0GdRaap%;=-r1URXfkCEX%6D zm!jknkdACWm@3&2x1kM|8td&Wc z>2X>+r)*m2eo0r(TQqdtWZ!Yt(rK=XH1b+7vIlA#(r1RAKt1~nV z?3tJu85kEgF}4{rF*X?p0h5}nFeBrC77hb8AjQPUXb=n%Q(*Bi@G|gVvNJJ?>1LFa6jv34h%DogouBxhU3}|)3%A?O23Pww z1hFlwTv9$j`52f{mKwN%Tqw_CXJBJswZLM5S(^zyFDIvG>Lz98={pDc=o=XrTIeUI z6zC-vXGvoewFZ1iwu08QZ_Z(afr|v$4oL7P67IR}GLw`p0(rETw zE@^x+D`E_)jh}F-vHW>IPs-w&-a`2cGu;oBrl|a#XRT4TQ%xgrB2TW)50?2g0gP84 zXRd!QddYRR3a3^YtG{aFsn~t14o0f4Gwy5pe!pZx=;pp3&&^NdtqODbwl}y@d7AB( bUq)TQX)daZRF5sQQSJHgK!Z(byP6{a`N8v7 literal 0 HcmV?d00001 diff --git a/certificates/revoked/DigiNotarRootCA1.cer b/certificates/revoked/DigiNotarRootCA1.cer new file mode 100644 index 0000000000000000000000000000000000000000..4d97a65ccb909a87f078407272cd06da31836959 GIT binary patch literal 1356 zcmXqLV)Za+V%fNWnTe5!iN$S>%}E1ZHcqWJkGAi;jEt_C*_cCF*o2uv zgAGLtgg_iFVQ$yFlA_Y$61}|C5<_bPOOPnHuu*w=xn3$lM&CIgSRpenIlrhtPa&yN zp(r&?PeCImGdHuOSRp4fF-cF;P}M*gqFF{GSyRE#($Z1^$!rB5kmA%7Ln{LdkTPar zLuA?D)a25lRE6NwqO#N?1?SYFlFYQse)%PdMTSxa5)kVJ;bICw z`S~RZ&W?r(26FIF<75;Q%*;#6cSr$h%>!xG%gZrnVp2j5Sw>a{<|Zb72B0_>Qxg*- z!P~_m&p7k#;%z$;ibom4U$C$&s?SkcfjUP|dyzI$(Yf)ml`_}!RyAN=h zZ<$uySZgdb!}9y&{HgV}J2#fL?+WyI(OqCSmF4J-ZHL8fc5K+#E?aP`Z419hchz}; zizQ}@gsRKiyegkn-)9ocSnAid&Lm>Cif~1klByhIw|8LS@1`@6(=t1vGJ=opYeJnCH!J&FvG~vlr8nG8N;f~^*!NNS%uLy9TKvrlq7mv%dcPhi9rE0`ld&;t zZth%%@{BS+MXlTxhgQF`nKezHKW}G>yrRY^-FJU&Fx$m-5_cbMvO0ae!=i6ZwB}C9 z%QJpTFrW8mYD?pm&g4J&+M=UMO^VfL(sh+9(>|>U(p~I+HRzlDzjG~Y1CT?CJdzy;pYaxs2L?(-iNp zr5~MAH7hsCr}oT)l!i_7-1`B!jspwIM(wMBN)cMa>7#uGf(eGRxl()=te!19L8Kpw3@khbT+%FI=6Z(AObm_4c?nobF*i0c^jCk| z5V!nv-d*$VU1ckqj+OLXeJNp>teLXp^Y-Lx2Ah)fSN+LpJ~?lu&Uyo0HcqWJkGAi;jEt_C*_cCF*o2uv zgAGLtgg_iFVQ$yFlA_Y$61}|C5<_bPOOPnHuu*w=xn3$lM&CIgSRpenIlrhtPa&yN zp(r&?PeCImGdHuOSRp4fF-cF;P}M*gqFF{GSyRE#($Z1^$!rB5kmA%7Ln{LdkTPar zLuA?D)a25lRE6NwqO#N?1?SYFlFYQsC~;mxV*?8y*USjSHHb&@q@RzWkbwZilbkM@>6w1{C5c6bQU($b>jmLr3PJh# zB?``th6)C9@KEDq6cfzMOUrji0cyI2ThB6C=Z# z4G{+!_TEtB;MSh?FE7l1b-r}@1OdmG!@TW+<$aAGPu0Ba$$D#1V!Hd*{hzxJaGGzK zR@_)?EH%UO`{ewo^|m`VmbUK-^mx%-U^kWJ=#6cM#cp1 zW{ZTX%iFvvpH<&y63kfY*S5|iVz!EKMVOMR9Ame4VBznkGm+CWJEAgzkM87UGC%FT zC(Ua@ofbDM`&+U2&P>pT9w{C2+_;mmF>7w_ zT!-?EGCxJF+!lvczp|M%O`kt+XNtU{#wgu)e{C?^#dQ*QA8oQaeZ9k?Z%wr3PRYwN zeo8Q(_h@QM+})NEykTlS!Vs^yjOGCEfF0YOge?ULYaQC&B$RdgbMdIdbgj{S&=ccI~;8wrVnC z$EJzD3}db?I~c^ld6p}A(PgD&FBaakWSjmqua{{;k4UwB!&&J$yN*N@DX-raHvd?a zld&edebdQj@~pgPeKgFvFQ2fJIo9z$?pNi#CCs2hOt8`KB`#y0Vc zl9B=|ef|98;sWHH3)BQON1jE;K+8a5f!YFz2k7JlA~Mo9BRAy zKNmyx?|_!+pWh~3kTQ^jWU6nq?2Zg9JO*6SEMew)hRjS1jmUWkSV}QBHZr*Fay@Xi zz=o~ZcSNUBQ$FcznDyAy~ro=#=|%EZRv}>waVn+JLZ=g_V!Pn zB01%@(!F~k6I81&I?vttDA2shUgven<7ba!dzW&1O_tqUb1|5E#gAv1{}WmjY}+|< eCf@dGlvb#{U$S}%e@b{n{fpezv(H|%a{>TK2IU(7 literal 0 HcmV?d00001 diff --git a/certificates/revoked/DigiNotarServices1024CA.cer b/certificates/revoked/DigiNotarServices1024CA.cer new file mode 100644 index 0000000000000000000000000000000000000000..28d0c5cc2f1df7d1da535a903b73581d94e72d47 GIT binary patch literal 977 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 literal 0 HcmV?d00001 diff --git a/certificates/revoked/Micros CA 2.cer b/certificates/revoked/Micros CA 2.cer new file mode 100644 index 0000000000000000000000000000000000000000..8bea232b233f2a044fa067b60941dcd9bb943dba GIT binary patch literal 1095 zcmXqLVsSQTV%A>3%*4pV#FFiKiPeCYjZ>@5qwPB{BO@y-gF)kJLv903Hs(+kHesgF zU_(Izeh`O4n8PzCCo?ZUv)E9;fDa_ZF3j$nk(r#Bo^PmVAP*AZ5|#)lDlIN4Pb^DS z@W{_e$;?YH)=}`xOV%?qHZTM!VHVaxDDf{!Pt41#N-W9D&r|R$E-nSCS8#UJQSeDE zOU+R*GL$!vg}aWEQA{8?(V+xpfnIWcu7R95uc3i~iGiV^g^{tTag;c(k%57+ktLLC zkcP`MzKKPZIf;2GF#oX&b2#Vcl;$R7CK}2bNJD%h;+vUVlwYh6Tv=R_nhW!ZkbwZi zC!A1eXGeo3MkVBcWMpMvZerwT0E%-lH8CU^v%^MP-=PmP}6RD_5TVb>j@XD1V3(EcaS&h%g?=9%cZWKx*8fe z=k%HA;~P)vpU=;c%v#?+H%Q`VHfxvH&YjOMti0s1Y0s~>p$ZHaDtNb=sLMT{_w)1o zO`F>%z31+!zbTjc{^FJ8{fp|42sM0KU*za_|5MNDk8i51zP4rb-!s0wME8!q+K!4- z9@oBWE~>7-Kc~fE&d0awf)?h;xNTbzC0Cww`{Q0#w_Dp!Ubu9hiJ6gsadG1&gU0m+ zLcq|I6=r1o&%$BA2Ber68G+FZ6yswNV-Y!)Ju%$bFM6`*sY4!+K;0EdEXJG-RYc>NP5J!Q<)xg=nk&RcI zjgf`1X=*St2pAX`=&^ACg;-hHnHa^CGD=Dctn~GZi*xi)5|+NRqkb+p@{ywzm_LBg z%E+*3>Ys3R4%MwImUzzR%6Q3dD3Nho+vSPj&843h_HgHi>Ka{=7ujNSep2ga9m^x3 z&sJr(_eS-ITg_ao;xF#mDlWA4N!|C0wiSnW`Yq4@r#byy(Au8dKPkUX)_vU7z$ChU z$MM|u1y-EO>lS|5+7uTr6R}0t^WbWhGv`ybvVEwSG>^IU^MkKTC;8SNNe(jlU?c9-dj(azV0D#4fYXATM literal 0 HcmV?d00001 diff --git a/certificates/revoked/Trustwave Organization Issuing CA, Level 2 2.cer b/certificates/revoked/Trustwave Organization Issuing CA, Level 2 2.cer new file mode 100644 index 0000000000000000000000000000000000000000..a0d142e190d275a50f104c7cb01a44ba62a1ae81 GIT binary patch literal 1190 zcmXqLVp(L+#N4%jnTe5!iN$fk>OBU$Y@Awc9&O)w85vnw84Mbm47m+B*_cCF*o2uv zgAL^jWI!BlVbSvPa=nV8#N2}7)a25l%#upIKbT+R51&yKvcQsNOC^)AUm1L%6CMT9;=I1FmmX>7XgA6v16X!Ls zFf;-JV-s@|qbPA+BV?{Y<7!k#3L5Z(jOP&M@XX1{%*)R#HWV=60|~JUvpZ)1ElAHd zR5Xx>xKtvfsI<7GJh3cQ!6QE>B{MI*SO?@vJwsyyLx?lA5K8=u(i8JCs~}GFEG{ku zs#kD!)KTzBElbT&Ffx=kkc9^!C!?4^a-u^C%mPpl88k5}A%`*}D+6;ABR>OBoQtW6 zk&$7q@U8>;zRiyRmz=Rs|8|FMUKY=!Fxk(i;~r?O`?eR19V)92kEk{?Ik3XFftFmt9Kb4l@@Id{tgtqPUAKfa&e zdHBcEhFeNgWiv!s|U}vzxnf~G;HyM(!77($9XsXU0_sq`^oM$hgUh_ zl{Y;ae;d0V64hJ1c{>v`BLm~ kqAHne`E6m9FpM}+c8At)cmN`_Gk420{WD-Zp z#@+LmOpK0OAN=;wq|dk0)*6DNR92Zq!a%G+ft9{~a#4;RI9aEHqYe~p`VsEVj(R`| zgJ_U01(pzlAOjvYE^RhO7RJW663h$+PHg;e9y2ow&=LcE16?)_pdc$NI}@XrBGhc_y;Jc_VDrfs4TJEt@14vP`jj2Lo_c>+l%DZU=!<_HOT@|I*7vH*j+=2@T;x%{ zX@T{nZyiNvbaS4}NwoieY46EP4N2#mdEacn`VkTicE#$vb<-#YzcVg@F_HRmAS9a~v+|Tt~uTqk_<<=~1UsA)kjpM)L z2Yw~9%zd5=XPqte6Q>CqZ8JO*+-9wlI4%5e6HACmo`TJ)v+bOZKSy|YTv+yJ<@?M3 hw{@0WTY;R+~rLcV0$DR#pas#x;hv2G(rMp)AZiCLxFC z1bK%9g$9QxxaOp0mlWmaWo9b`m*$lwmnsCO7L{bCWo9Q9AK9qjky(|ST9T7mlxfIq zzzNdMCd?EPWEf`<1LAP;gd&;cl$n#Bsc>XNPHIW!(fOIV3T3GZKrsm0{qUZ$)V!R` zBl9znOjU5yJ33EKK_gjH!5d^@u7ZM*fq|)koH(zcp@9Vunj4s#8b*op8iBZ`P_9Aa zVpR7C81RAI!y(M>lbV*DUz}(N6=6q+$QVe0-7GBZ?H%H*;G0^Mom!>fl$ZzfYNnx@ zfeJ{LSy(nzH?ue=HCHb?yCgXmtSAYhMlZi8-B8Ow10J%RjAGK6Am2J*Rcp}1sDvC3 zjI0dIO^o~uKyfanCPqev!x16Np13BjJG*gS)3-er89vPZDw^5ddGpL9hO5>m>h>ub zd^U-n@uuSVPpKcA&d(VQXJ;%huV&rmdphU0^#r>Q-&iva++F0*VlF$+rmG?B@hl5ma=~zSc$;C=;%7WNMDyKVFO(>7)-H;B-SS^!&z%{psxA}t zPCxUh-XOKrZ4%%9$EPQpVV>iX@H}U(UgY9hRhRs|`<8voKQN*Dq3yfF$;nT5O!45< zWbHAN%jTA{kkfoJyP)gD((g7b`*=(}?rc%wQW6Mw%y9dy|I;Ps{k*cK?s(O@b#esr zHH!tUU+xuP2{25XU`yAW$DV@Ffxc%S%>Y#{SGJ2}#gxYJ4h4FMY7KW^)nJZpN^R++PfB)dV9qeADBK-tKq0j*%If|OY+Xot5b8&=h&Oh zp!ZS!xv}c8(8JooCF!SqG^)a`@i%nJ=`XdpFT!x*be~+_w`!r(-o`AY6TN#9O|+gL zTA|&3<-^}Mt!LKkERag-YMycaet+sog-kWeT`pElzV^FHJG literal 0 HcmV?d00001 diff --git a/certificates/roots/00_BCA.cer b/certificates/roots/00_BCA.cer new file mode 100644 index 0000000000000000000000000000000000000000..754fe3b8fe87d57dab6cdad1b2c0df51b4119d24 GIT binary patch literal 1134 zcmXqLV#zXSVh&os%*4pV#K>sC%f_kI=F#?@mywZ`mBAp&klTQhjX9KsO_<3mz>wE~ z8^qz_Vety^_B7NqPzQ0jc@zSQQqxkCOG=9pa}*qli}RB+6H7Al^Az0jixj|01r7Ki zN;#a0GE>r1ogEG2#CZ*j4ULS<4NMIz3{9iNc@05aGeZ+oOH<1zn%dpOsD$iQMpg#q zCPsb+gC<5UrY1&4hAYp5GOV>L_dL(O`+ldvq_veVUvF5LxpQ7W%O}rSzUtP;Qyf@+ zWtm#~XkM$@cH1av*F?bwPl`UDJ`wk+{*%ow&F5K%b2n?p`0(sG+Rw1>*xd&+nI!XL zPyBfDZO-T7nr`QHg2&U}^-6xrVrL1xd}#gGm+Bhg9|C^n?np^@n7T+oh%M9I^1$|_ ziK(?)zB-=r^LX}q@zYq%KqZ6Yx7nVWDTQ%lYW;VQJoi@k>^83@qDiIyiWY0sY)&)Z z-M?4MTkIdJ;T$uT-!Z?B=IWCpeXs{n41DGMmF}n#h8G33iOP z&Pwkyn0@$6UP>5S%bkh;6Mn{iF5R5W#LURRxVVYY5*Q+;27JJ%ljUb*{LjJyOebvM zsFW23@mUR+fs{cmNP#>{nn8*|(t?BqaZ6%o8hee+Ao~PaY7DBDR2Y<@rcreRRZvRf z;*opWy5{+;mZuHfPj>Bkv8wmQian2;wmxp&^SF8P@IU-1CNx5J(;A_P zYagW4EHPLhUa&Z1F@zV{N;VoNA zZ@tXriCcTu^Q}1JsnfZ2#wjJjnb~)jY~bjNYfdj|>U`pJs&$I~qw5(PV}1UGv8dOX z_0=eKFXzAd+mVs=@;%*4pV#A1=WGtGdPjZ>@5qwPB{BO@y-gF)jKLlFZZHs(+kE@5uh zypp2Q;u5{Q)DlAn13Qo?w}^RpdAVLHLPp;?AUNL0z{El!GcP&6s6bC4sZyaRHBC=J zBPTOAv!qxdCo?fgPt#D7vO#Ca_(4ULRU49!gqObw&Nc?}_43nLJB zsCui3Q3*MM7+D#Zn;7{S44N3Zn3@; zb7%EZ2Nj0;k|_)4a%gVu;QrcPJ~#C2lf!k_vr<;KinL9Qo^BM7Z+l`_8qecDdv|yq zEbH`?{Ci-<-pM4)bS6oXCj+kR62u)};(EM5Lu_UwYv8laWTWnR8=-&4XeWFSs;tUhi zChy_%%$T_Uhx_HZQ=Ja-`QFc0JAYV0F)7Wt;M&y#><^ik85tNCmlzZo2(ob|w0SVL z{cvJrWMN@uVqiCr2PPv~Wflnou?CUQCyf^c8}{Ak+{v-n@aIAmPO+T@2C^Upd@N!t zxTL{3<6AAeBLjIx-GcGAZp@wd~ru`x`{!ceG!)TT@^Cf4$84XSdnc#@%k6dqJDm z_%_SMXPyqi+GW4(Ue4*{7dMWID|eO%`y?%LndIEne*?^agQ>)FR?K>|cBP%O|LF0KtZUas>=1>+kVJ62A z!^Uod#tsmdORlkj!I43iA%vlbp_HMRp@cz!!JQ!$$kGF{(ir{##T6KW88R7?88U$4 zMPM=$sIC|YE5SNa8FGO#3P3fvKr)pf2Z*zQDvH2nxG*FF*{KY93}ryF2q=>ZGy`O+ zJ5YTRgNLDnff&dw+`{~hx*dJkXJzI!K{4o*M++vD#)cS*Nf8xNUu?{T|yYw8rfn5`V#Zfg>bR44d3 z%d9%Ul6c$r&bA!RtLLtAy%!Md_Elgkm+1b-GEIHW?>8zNj&FT%Iq}1huQfMM9Gj?E zE^x7P-t7(s&WpU6|1AX{i>~%{*IZ$^@s@>KxJO3(+dkKI8;`8WS@gwk&Hnusyzehx zUGjdD=bys#DKl)||No`dk$>xNyqDvf`q!anKfF#1WKEBMy?>h0HC%u7n>QF81MsA zldLc!<9`-b17;v)AP5rRW8q@q@V4oZZGD-))_@Nr#1B%#0?ajR$RP{NFu;&yWKi^8 zGh@yfRf!274cOOA;HwIM7u9mCXt~G!EuS`jKRZ3A_2!TFvi6*p!@4?Gx`s`=TFE~_9^e+)x{SeKh0C53t}`5d9WY4r z++ZB_Dn$9fJ%@lj4SS#6nXu>1wvt@Y&5w84Gu<++f3s85Wh$>#d}e7lvsB_f{gj1S M=5FU&M30040IUIXMF0Q* literal 0 HcmV?d00001 diff --git a/certificates/roots/A-Trust-Qual-02a.crt b/certificates/roots/A-Trust-Qual-02a.crt new file mode 100644 index 0000000000000000000000000000000000000000..36a442b890a7144abbe3902abfeb61c3543d4e67 GIT binary patch literal 975 zcmXqLVm@uq#I$(s^F)ASkCnGBZa}y&!gFzD`7gG}>Bg3?btFQNMh}^-rcZ=NG znSU4ldBrm=yI;@K>^k%M9(#<(G07%IcPGw=H9P08>;LvHE_=m_unvo` z&CmXwoa=955oj}K-{&=RWKP(|%xYQpeTt6ArWEspK9LR9T4y`ADy{$ir2d_bw(-wC zo3%cR!ufwU9qp56ydT_iP;|-Nce5r5UD9}&B(9oZ`2M`%l+U%FpV%m_p71C4eDd;R zLJWnT*JVyDc$++{_Hn<)-GrYvo{6niyLdr=?{i+x`*~O1Jhce^lES?!>P*8{i^w+( zk*O_)S@EG0eN>*R%xZ3_+Sl;$UAzMOs&erh?nj}krd4n-&71x~dtJoWh5-A2)=bQd z42+A-3``98fhj>&n33^63#$P$kTMVi3GlISv2ZxqYO5?e=z7k84@4`zvMd~5o+O>DWwbLS@a9PW^Rzh5Qo zddB@e<#40VHqX6oazUl0=T`5LlV2{<%<%A))Ksl6Th|mpgJ6~!v zI(D^N-7-0Nz?eV2!dby)~Zm0kN literal 0 HcmV?d00001 diff --git a/certificates/roots/A-Trust-nQual-01.cer b/certificates/roots/A-Trust-nQual-01.cer new file mode 100644 index 0000000000000000000000000000000000000000..efa28178eacad9e97813f83d866530d5792fcb7f GIT binary patch literal 865 zcmXqLVvaRvVsc%;%*4pV#LV!>$$*!QQ>)FR?K>|cBP%O|L8u|O0Vf-CC<~h~lVgaX zfB_$f!zIk_s2fsLT3li%X&?>~;T9Hvis<4&ZP(7Ge!qLeXezs3ueDm~ZF4>Y z4dn;fDQR6TmyKWA+TLE)X!)#CGWGqd2-p9wdyN0={~>r&U&EwJ`m2upKA&v~QXFUD+WR36ldooq;YO-!e-}vA&|HC_ZTfV?8 z_vIFeFco|;J-=pUa7eZJjq`3ZPyE(7W2GZ||A~y2;G=69P3L+wCp>GsqN7%KXdt}SfZ9QL=?n_p+| zy-;<3uJMAEawq?Exe4xNnrCPF{*L$kAG*=UnH;*()l=i9{oL&5H$CH1=+k~lwVL}g zpXyIP_i5X9d7iu1j^NVKmq|G*5QZuV9YvI3)Iy)ur zubZ+`Zf?_C|M%0z`Ozno-@l7;Hw>R}`T48AGP~3-Tw}c$VSatcmbQr#*F6r|W0I!g*n9okW_LG-+q%EJ5-c~pxVC)BLsNm$t^W=O PiEvxoTNbG?QQ#N=l*&py literal 0 HcmV?d00001 diff --git a/certificates/roots/A-Trust-nQual-03.cer b/certificates/roots/A-Trust-nQual-03.cer new file mode 100644 index 0000000000000000000000000000000000000000..33e776369ffba008bce7aedac491db7ac0d42017 GIT binary patch literal 979 zcmXqLVm@!s#I$_@GZP~d6EkCuoB=Nzr&gOs+jm|@Mpjk^gT`J%ZUas>=1>+kVJ62A zLk|Nt5QmG$-cdKCsI<65!9BHDPa#cDAviNRBef_aHM69+xU#q;H8)iuGgl!sCpEjI zNKe5fu_QIGEVU>*HKRzuJvYh2P|`pgWD+-z0MsPiyui}L99;urm=rUnl!2T$uYsw7 zg`v5TkpU1yiSrsFa|fM!n;4algOrh#fw_s1pTVGsk&CH`k&$7oZDJnt=Lyya9JyN> z&c4xFJU4rH-XW)!?|~u@7p%|?Tpal6p7IA1m;X~adf&VyWskuDz~pFK+HV zz|z<1lK8%U`N>}gRnN5QB-^tl6nnBhNT`@9;C<((VC1>NdWYFvt5oiDJ3YD`w#Vzz zQl8n{o$c;6Use-fI{!-fh^ODv%P+TdtmavlH0ere`^~KDUs~rsF;-Gt`t*eHuEWP2 z@5CR=I>W%1YqVlpyBR}L`D{6PlhYGyDmqG7UsryeT$p-l?(u91UE3JH=U0E&8`k!> zzu{8SSAO|#ckRgsU*5c~IkMrfZqn9Sh1WJ_y?Ar;?bV_;`@$K|v4+mScQK(uU^6h$ zF)%JRGcYmW2c`yDVMfOPEUX61K*~T6B*4eQ#lqo|H8nl7QqbRk4S>s>w| ze*Bom8#Z1+6+XVDvHN>A2~R7$bLAW#FIR?9&Q3=|$<-U#t9@r&j@fYW!*ZtuTaWau z|M$`U%X@z}hO*a8zkklXz&UsgUZLZY5w7Bxho9;F3!5L0Ifq^A*(&~DTzshTt_`Y5L{o$mU zjW70D9TyMyw*A}M;tYGt}RpE%kw>ns4AZ*?gE literal 0 HcmV?d00001 diff --git a/certificates/roots/APCAroot.der b/certificates/roots/APCAroot.der new file mode 100644 index 0000000000000000000000000000000000000000..7873c4c39879e04cb4623408fc351d745c6a03ee GIT binary patch literal 932 zcmXqLVqRd-#MH5XnTe5!iP6x2myJ`a&7D}#ZvA-4f18*?ZNn=q4CfT4_m z6o|tmEbNt7keHWRoT}iSUzS>wmz$bbVkl-H0+Qtx=5;J6$jMAjEXmBzb9OY46X!KB zH#7o5Qv)D~66ZBU=2FL!CPpP>$1}1rFgG#sGZ-{6axpbAGBPaBeNf`p-oKRXUdE!^ zZ8N=7cnd#pvCi&W_3(_|r7Y`%Ra>Sf_IB+%Hfs*smbSnr=6od;b@5&GQX-ErlN|hY=YC!1;!$kIHZMiT+C=$wjM|gJ%Kj^Pl}bA&A3SyTVA$J^ ztm_Lb65k*Jt0NeU4!Y?SEbdxL-FAc^A_Yx+}7`{g3j! z$ro69{=U!Md!g#&Qmd>Y<6~aDtm0a_)f<=Jxb|V+7yDOy8o7>%%4HRYccd=)9JTJu zp;b4ZN8H<1H@7u!z7|*hd}d99=^C&^X&b78p&kd@N!tA|X+y)$9w;OmX9#7W^vPBPNfEXAZdO^#{VoVz+}N@ z5DDT7vIH3fEb%k&K}``724bK%=i=diHht-{IcuKI-urCI{-?X<7%Cemf@HXPq#idd zdfYtyar3IjO&cFK?|Iy`{c-d1$IY98NrN9`v@pmjRs&`rg&c*z^aqSWMh43)m$GsT zt2c|&-S~fYv#t1@HNo&)-J4q%J8P<5>+$TJY4m)9%C*D)zi#T_Y}a`l@^JC8O&r_@ zT34L7G^g;J?EHj37RJI4=iT9sza3%k$>hc6O-PlB}eNjR;I=7J*8OgB(Nq; z&Gz2J)qh1l>G1e|8gNgp3{HrD-X{3oAhq+`4FCq+VSFckL~s!(6-~8 z{jXzL-Iht>f0U;*?#)|%wCB)kLD$}DS3I7uM&$v&!*cI+-5T4QPD!vo+a6u=QbDqQ IlXPbY0Cezuk8%uP)E3yXR>iTa6K+jlzH-<8df=V-pFE7!5$M}JsBr-S2*M?0Ma^Z^1_!Oae3_J_rRAiW}^D zR*}5t%cixnwKx5HXxS6Di(6sJz3S#2{~w3-ZWnxM-ScVV!PvP=xP7#5Zj$)Ab-p(f zGb01z;$(wF16g3|mgQp+V-X3u(P4FBenr~b&d=2r1yfEkF_~R3;0H+yGcx{XVKra| zQU>xM0c92m1F;6|I`}{e_(3{YfVqy(P)=-^{%y)(Ypz@f|vBZ^c_ytQ%>8EzAt~<0b$F8Rf|ki zCzl4@TRwL!UwdazVV0PUq-^t#S(>T)zSz&Y`QdX^yJBI3@975?v+Z~PdSKvtzU^|V zfTYC5=}a57i<~mnEZFN8bxUG@_Ke00e`oEB6ZJSND7y22X3Uls9pCND)@@JvE0=Vy zph7^#Bl^~!B^JBV--g=7h2Ouz?BLV5c6~>m6{oDOm0Cs*35r z<<}aFY7r#|4-_lqPM-SLvUa!D<8Mumb*9Jr$xoc}>z~fz8)Z^Ed^cJ6&;BLrkx;4j z==0x|7iPUE==ZF;_H-{7-)-H`z58E3UQ&Dd_|(D|w-(nNJ@lhw5{q=(nk7oX4%^oJ z^C>(3dy3Hk)A?ogc~2+gEm)?uXot?ei`uP!muH;V#i+e8r$lx~@zm$BZe4DLNzJ@rc*6(=~BFSC?? zHSh8K3u*bRZ&sDn?avll@Ota%&G0Q{r{~`8m8+-Zt zVglSY+wNza;lC*|#NE!Mx*|7hvR?74G>wY0vLgEz^y};G(Chmo(skzL)|%frb9t6N GoCW~9rDq}l literal 0 HcmV?d00001 diff --git a/certificates/roots/AddTrust Class 1 CA Root.crt b/certificates/roots/AddTrust Class 1 CA Root.crt new file mode 100644 index 0000000000000000000000000000000000000000..d6a842059130eec14002d35430445576f0e55036 GIT binary patch literal 1052 zcmXqLVv#UtVrE#t%*4pV#K>sC%f_kI=F#?@mywZ`mBAp@klTQhjX9KsO_(Xz)lkGh z2*lwM=5|a;2`MTqE>UoFGL$ut28nVDi@-%gLIM>0QcKG7i?R(B4dg-6%)%0IY3H28 z;$j6u1!qTvp#1z2137VC0|Nt7V*^72V+&)$C~;mRWG=m&(Zr~P8~}{049rc8{0s(7 zj9g4jjEoG^rd?6=On8+2!jYZl-jN4)gq6=8G(G*_@>Gp%g-j4O@o3z{a)Ow8>y;OH;3U*-`m`9t-NcUsKSlKvU%PW(K;ru2MG z@%^QGzk}{<6irq5Wtx_G@4n8*ygdfDbyS3Izcw|^m~fh5!*oU45=G@y6YbpXvE87tr2(r63p1Cb z(<$D8QHvbyz;q9cc18xB+!Sf~v%GhAGX9#DY+~f$K6Bmlw||SomKD24eR+NN<=1P! zUC(HCy2S2xv$TEjZjWzBo1ARUV{vuohn->CEAxx|JdGb0)o3Zt+GF=$L+kD0|1!$E zoWnWOeZ7;|bbtKMnVTSYL&m#ytD*kQ3pKGn?qxSiRG5eBzc6M`zb|(@TWf0By8iIR zAHD=_SsBc6{(=AHs^IRwyJf=6KK=)Ngj)ar literal 0 HcmV?d00001 diff --git a/certificates/roots/AddTrust External CA Root.crt b/certificates/roots/AddTrust External CA Root.crt new file mode 100644 index 0000000000000000000000000000000000000000..8a99c54a99fbe7d188e8349044bbf835338815b0 GIT binary patch literal 1082 zcmXqLVlgvlVwPLL%*4pV#K>sC%f_kI=F#?@mywZ`mBAq2klTQhjX9KsO_(Xz)lkGh z2*lwM=5|a;2`MTqE>UoFGE_5A0f}-8%fdxnD@sy}@)C0tLP7!*{8CHG^NX?#l?)U> z>X?NkG1WOcDg@={ml(*2^BNc!m>L@x8kkrZTSSTT8XjN?rvBY=YQMRKuAJRO$F&7v$3OVnzc89ta_Yo{keA2e z`77qma!f!mNNh*Jt^yXWhK4aLSy*%>fBq$A#xwu(vU-c)21|O=7}o zpAG)XtF8Q7ZrndN|6ykS?(0t1vt6DXU;8fCF}^6Oki&d)W$Kd11yjtwGwAaknpAY_ zf<@77krl2-Vzp|wZ@G5l-I}w)F56FP-*skC{gt>gGb=(_aQkxO{;<->uV*!{yKU#v zPTh9dDPMHcj_TjoB)8i0+;|888*y*(5iaqn(`z5X>60`I?kALv!$}}rd+fLyRuno|Argo zyVp48xF<9RZun_r`~1&0HR0n8VoUc&{b@g6QQ4_D>yZyTSDWdcPxk_kT$;B1PMzPo zg1<7BuX&gPMRfc2iaj`Z->vky%Gx(yoVK)1E)YoHHJ8oQOX9M2)tNx2g;mKHpY2|F zRQr(GK4IQxdz0%btCw@~I;_sR+uwEg+qWJmC)U6#u3zUbPg2YfRdBYM`MhSY%8iv1 z#fv-a!=w!@B(@at&pLa8Z(g6C^uwMR&8OuJKf3rFV=4A5OW;5LW3PBaw%*G#K73KL eD)|+-^sdfJR+9^zH04HD}zCbA-4f18*?ZNn=n(btD%U2 z5QxJi%ixJT%zFUWGHJO4HD%R7J-X~gajz~rIwWE7iAkN7|4O7nT5sS(gCGO zIhn}{&W;K}`S~RVa^k!O1_q|a28ISEhNcEl;=D%4Tspa;iBSpJ`;4p%%uS5^3bAUB*t_}4 zd0#9~FWi~`sqSZNyISHrnIDhdENlFscvR(#AdmfRwW6xyjMLf0e_of+F{tIMl1q|1 z=6&FAZBqGV7diEB_TDa=w_Dt_lux)CIH{O<3q$7P&mw;BF5clhUvALo7a%)%l+B*##$CtNX3!Ohb>%|GdlwHpy zHSGmAS4?P82#OYbUvZ)N+f|PV7Yt<1H~dWaSNWvl(_MzwQ(RxCPRVrGb>Qlj9lL5- z1XsK^WSus}FG8_z{)L3UOw5c7jEfsD8Z@3WkOju5EFX&)i%6rL`He{%iIX51pQwI+#qRw78YQtVl&_eafBHe|Ff_fFas%r#y*gUGD~BdL1S|RRudLxEJ>qJ zv;$)nIo5%R9vJJ449wp}y?&_NQVtWFTz1z?W9K^Q9fv=r>{5`Zn5wBB&bp^Y>&wo- z&|B?H_xQ!c4S%ev)Z-N1y?&E|q|npJKfQl8zi_#_$x(HGM``|lfj?d$7vewsdT&-- zD{ba_Ofh$h=nlX0b7Gd-MltlUJ+{d?Y zLWztkRD=r{1l8hynFbv7IK$@tLj6WTZ+yzLg)VAwN^d5e{qHo(MKL$#=wl_>cz2=a a=i+03-B`8JSodbxCqFA=9_`J#6W9R8n17W3 literal 0 HcmV?d00001 diff --git a/certificates/roots/AddTrust Qualified CA Root.crt b/certificates/roots/AddTrust Qualified CA Root.crt new file mode 100644 index 0000000000000000000000000000000000000000..f861b27c377ab23e69782cccdb90d7ef70521529 GIT binary patch literal 1058 zcmXqLVv#dwVrE;w%*4pV#K>sC%f_kI=F#?@mywZ`mBAq0klTQhjX9KsO_(Xz)lkGh z2*lwM=5|a;2`MTqE>UoFGL$ut28nVDi@-%gLIM>0QcKG7i?R)s4HQAr%)(M|>A=#& zoXoV$)D#70M}?sL{1O8>ab5!h15;xILjw~NQ-dgRUL#~K{T$N7sDvB{jI0dIO^o~u z22G4yOihf83{T`{{ky{%)xKoD`#!<=^(`j1lWZz0w!bvk`i4hF>xkI@2X6{rcYPJi zd+X0T@sf~)uBRyDp(RSf#|2aVD+$fo*%zbFalSBXb2?+>$5^+|8!DE5<8!KdTrYj* z!iVh|f3;rC+q_{X%c{TMj&IqxLuwyB@(Wb!>@vOT`ITNA8TvUpQ*XRvVrFDuT-z#oY%7JEAVi6;75{ eF(`Q|x8k0Sx_N!`x_Ra2KNxKM?>+Oyv4sFyv4XDv literal 0 HcmV?d00001 diff --git a/certificates/roots/AffirmTrust-Commercial.der b/certificates/roots/AffirmTrust-Commercial.der new file mode 100644 index 0000000000000000000000000000000000000000..ac4443c70d12575d5be3907e6a217f33bbb478ba GIT binary patch literal 848 zcmXqLV)ij;Vlr94%*4pV#8F<(rmnVfV~qhX8>d#AN85K^Mn-N{1_KvEZUas>=1>+k zVW!YvLlFZZ5QmG0+c7OIvnV&DsI<7mP~JcmB+ASqh9s)soS&PUT9llbm}4L(&TD93 zU}$7%XkuVyU=}6LYYgNW8$!8MvZaYp3EBCKtPIRejQk7+O^jSjO^l2T-=zK1*|isn zeq~cSEzh{=aj`3#i>Jb^p(P&EeFQMhpe2@C&<=P~duiC1+GoH8W z(E3)>N+aFfGD+s2Hb#5do;q6?|I%sSlou!N{Z#TuIren*G40&7tRH?|4$(N z-PZ0)m7}Ywei+;Dct3OcV}*m)G&;{u`MuNi?PCXV!7C*nxD6j^t7Xmh317EH!ETpp z73=4{vol54)%qzUA2BVnVrM#O{`a{1yB8nJWQ#>VO<%J0L{;TYr&ZeZG5^k~`7cgu zG+pnqD@0Dlz$kU@Gn>hA0e)4Ft*+#qk^24flKDCnt<~YoN*cVLrS;o2Zk6uudwhql z(vXRnk%4islYs*`x@7rS#8^b;PCgdg9d~NI{d_t8r!%MSQTaBd-+&(&o3g@;jQ?3! z4VZzH0Ut{U@*7c0_B|YQ^ay8}Id8Ufn5rBU|OlN3nG`mc(4C5A1s@ z!MJg9^4>i^5*udC+j!2Y;L*xjHq~17h5z#3Y?f2G_1HU9iox1+i}lUxu?Bw|g*!hT zV$*(`ex&cD^QM?=(N3m4Nq_u4Z8cuCDgQFpqJYQWtY7H49J-xmvC=rq<72M0aW8L= zeS-Pi%cpYdOzL>&7nOBO&oBBLWa{Y3G)-S-)2w1o#f_fsuI^jjXPF3|^qqAka{D!= mc~O3;Tc@m(zOT7K?BjlhdF)o=DO*{#Dl5+9nrc10<~;z`+d!89 literal 0 HcmV?d00001 diff --git a/certificates/roots/AffirmTrust-Networking.der b/certificates/roots/AffirmTrust-Networking.der new file mode 100644 index 0000000000000000000000000000000000000000..d64e89dec68ce83c11ddd3a04c24439db34a807c GIT binary patch literal 848 zcmXqLV)ij;Vlr94%*4pV#8KnVVkvWFrmg`m8>d#AN85K^Mn+av1_KvEZUas>=1>+k zVW!YvLlFZZ5QmG0+c7OIvnV&DsI<7mP~JcmB+ASqh9s)sms(PuUzDAhmu?^@&TD93 zU}$7%XkuVtWD+ILYYgNW8$!8MvZaYp3EBCKtPIRejQk7+O^jSjO^l2TTUyQ-i|b`i z$;nO(TJU=D`N}CiPp34@JRO?ilG>l1@`&wmjJfAG{n;%oa=M=q<{J2&X=#0=b6#%V zKeN@w<)$t-Os7fNn!TvvyK&WhVOD1M%|E-X)>TGb{c^2v_pAxZ*|WBHl(h56#qXS_ z`)hTu_MP2jc9VTLIC|t3Da%~RTC22cCZk?%>gjzdX`w3K4lWy|uRlE0df=Xbz3tl_ ze?ERx4!*NLb$b5IpALn+wR@*tIk#^?oVxP8zsoMD@iAz=wsHGlo3P(L;L;s6$G~|a z=1we&3&K}Ox4+f>RsF7q>+#C8PRY}bKkvGjC7yp&?slT~+m}g=W`A#+d@QQ_%p&@)3e8Eh{hC8W?&DNzxdiXbapGf@} zF8ef6kIO#i#>KBsIk)75FmOE(^=&WB-5xP5>Td2Oh6P_{d+a-GzGRo#gPQi%=~AML z?&&Rx-n(An=Y)W>1(840)7?)WU%+lvdr>DgN75>7Ywh2O`Ar-5aZJ7~;{I`w`El2I nHpk1?r>vNK|668rQ^F@tCzH2P3?Z#DVrG+gVty@KyZ<%-?OIG! literal 0 HcmV?d00001 diff --git a/certificates/roots/AffirmTrust-Premium-ECC.der b/certificates/roots/AffirmTrust-Premium-ECC.der new file mode 100644 index 0000000000000000000000000000000000000000..c5c8fe33c291164619f64e554bda4deae3115084 GIT binary patch literal 514 zcmXqLV*F>&#MruknTe5!iKAq?YS(f5st^M%HV&;ek8`#x%*+O^hTI06Y|No7Y{E>T z!GKu(<3(7?dZ z$kNcn$iT=XN}SgO$TK#Ca;aranSlTsJJ{_^jBKphjVugG%t;I^yasX7qH~!qEUYx$ zZe=s6>XfL=*`&{N)MD6epN9NeeC>?Tt1lw)FZv``>+5+uTO;9IvF3vL;k}#A>O6CQ zB=szLhpnD|#S#D8U-*|~_=FZ^PnGqPaGF|i#@uG&quHt2nv0zb91LWEK_JV=BE}*z zYrSUG0YOt!wLk-g!&(0vuCBXgW55rR7G`Ap&%$cJ45SSBKmz2E&8X=6V3`tu!bAO9|V zRLErD6xr^4CGh^P%bZ40=Q`@bZRf;0Wq)PY-TI+v^3TZpbt%6ho_5PUPTse*@oYX* GPbC0MBd8<* literal 0 HcmV?d00001 diff --git a/certificates/roots/AffirmTrust-Premium.der b/certificates/roots/AffirmTrust-Premium.der new file mode 100644 index 0000000000000000000000000000000000000000..832df1d8219ae219f28c393def73495c5cd6a617 GIT binary patch literal 1354 zcmXqLVs$fUV%A&0%*4pV#F5)0;IcPQE73Bp^SkPNR*jJ7)ewipeQvrvozO0PMp`!z`)SR z($K`vz}PHGoYw@%Gd6^BsbNJElM=GS8Ce;ao0#|+44Rm@n3|Xv8IB0uUm5?;@$TKP z^Sd5@Tl3JSV%DA;AL^?X7;D|>Rft}voBw?BO|ycmjPregi(8}9Sr!PW9h@G1 z!$VVe+rxbmeebvO1WU}4Q(5HS|6x%p_vtU1^_P}Jyi@Z%xoSoAted|q?zx1EKK;>i z;-<$VUNLo9xf9K;s@r$13UxfgtmLgbvA6qK=lZncFaK-5v{`fO(&obtGv;*usA34a z_a$^{&hK3*caysBbC(;vPCBDDYxeF{NzFc6*s2UpXzqW@<~x0-%n?KFtMPk+g~aE~ z4A)F6PgFEy*HiVJEAi>wXYInCt-CDQJR*PAqfwO3cay!yTKe$(BvZu~4>uJh?a z_&W_hwfO!C8Jzk%e%xVusW;0maQQ{0BV5ZZJaRVw{9n7eE&TDWYpoUKyPRKn)PK9N zPdQg^|3$N$h?tM>mPm$3ePzB>_UvKLUYpIAJ-i>C_)$M;MVZ?ir&PNoatGO&qug|N zO#i(7>ZVY|_q*=+Fiig~GF9Dp{|je#w@Vx|#S*M%)m?h_*5cJ0MmZagFi+0oKIRPb zI`|G0Kg>^iS>$eDC-9V;`Q$7ohMc2Q>JpE1-LG$w;*LBLX;i*>PeNvx<=-uA)jHQw z%x>=Wc-tahw^XTLYlqX9rtMdPCsg?9O8srjce!rOSTfD&0mCD`>{mzM6|LF5|KF=s zD}LPhwyCmfTRIanBLm}NCj$oqSztnyPG!LC0Ze6#44cD!1(N)%o~(JbLuS2^@`=r! zQGs*HGm;Dkgm$)0w9u@k_5Xzd^?s#Xb$~>DRH%|O6n5SPc zty#hBUJZYyaL3Y8vl$%Aj@@5#?s3Gm?RNKeeSU4?aAQ&9*9v?6t4sgfTy!Olg-?9# zKgSPGHx>PIX)<K5|O)a~6N+qdY*hQA3H z43_krU`bkeEtQ7Syo3kUD(~( zHu=Tull)f8t9C5>P~rCLkGcNSu9naD|FPU$n6W@#gZ<@OD~c<26k7ep-ghZcCu3^&{|=bhIK=4l4<32g7AmH#y+C`-8~wJtp) zY0{9td5zTL`5&r1)?Q`2nZ9jh(d1XUXAg?StJm!NSDVfXZQCQUZ0m}+ zEzLREnGTod-}!hrGkfR5T+S~aR|S-DRn=CBFASaLG}DmtZh~Mht3lnfKDUc=MQ$Az zf5JMg=ZMNy>GLA&n;d>Dp6A%Mhvh={v=dqlCV%(8XIp$X;%KX_UH`v%nh&<^;LMPe Hk#Gh8r)NyP literal 0 HcmV?d00001 diff --git a/certificates/roots/AmericaOnline1.der b/certificates/roots/AmericaOnline1.der new file mode 100644 index 0000000000000000000000000000000000000000..900dc146b483a95f7a64e2a2c82fc9af4107ac4e GIT binary patch literal 936 zcmXqLVqRj<#MHBZnTe5!iILHOmyJ`a&7D}zC@A-4f18*?ZNn=n&ou%V2B z6o|tmEbN$@T9lcbsNkQMlbM&Q;F*`KXJ}?%0+MAG){YLH83(THL@@;GXR1pab9C{LqkJLBLfp-AeTOlXkt`C_BBO}8K{TE9z*_hoAzto!XUvg2wtYZP2>XzQm@RhFN-!?s?R(DzV z^p`1ZCl|k8(6&Dzb&hvP$03iSUY7es9!G{gmE2NtVhgKfjM&mgQ&}Gft&8klWSkKp zv+RoK_8arB-zi*OH*5dwK4X5Rzw&y|+0EW3SsuN6dY7t*@;#nowl?RQIG&~1-3qi8 zvs%nrzu->$)j5BPRxYTmc(UCvR4#S*mBbB-32z0AijGcFmHRQlOQOR4ew~52U4Zm$ znakO;+Jf0PykEms@uOwtKgC|3hHX4e-_i;yr7rs~KL7E&+XiobySp7pJ9<`fYFJkt zpZ-wp>6iHj4y;pIaAM(2{%h50O_@fv%bA!N85kEQ8zdU=10z{hn33^63#$P$kTQ@3 z3GlIqv4}9Ny}9^X<+r?&mG#E9jpEmR&Kut|kOxUCvq%_-HDFi32U5TfGLQwB4BL>S z0hk7X(ZI-1({)i^!o2Chjtz_7hD|+@lsJcV(b+>uYKdnB#IB#&l4^26uxss#m8@y+ zOFrku&z-scTleqRL7P}-EXvn98nRb)Z~VFwZLi#P4sPCi@TF&ggxGWr;U0wt(t1|z zr{$h77)*`+;=1^N)CNYs)q4*p=Ox=WcpYVbd*@O9@q0vD?6_&$ z=AYBz-EQ-^{{0+qIRDsTkF{>g9;&-@$@0zKcBs5Q`O|}1seOMQ+`oQ&dCrEP>vq}v YE!iUYB7(PJ&*c>jRx{t0o^h)N0Fn7|x&QzG literal 0 HcmV?d00001 diff --git a/certificates/roots/AmericaOnline2.der b/certificates/roots/AmericaOnline2.der new file mode 100644 index 0000000000000000000000000000000000000000..b29d3de19246fb6333c1925e028171f9f4f1f98d GIT binary patch literal 1448 zcmXqLVqId;#N4xhnTe5!iILHOmyJ`a&7D}zC@A-4f18*?ZNn=n&ou%V2B z6o|tmEbN$@T9lcbsNkQMlbM&Q;F*`KXJ}?%0+MAG)#aGeeWLQ`L!{PHS27} zmOD(h{Te@CUtUwVr!;v%>|=Hwk2k7Em=(VK=d%|2KfCwgv8&Qsa+Mx$yj`!Dvc7Fk zxRTa2_r`FSrm*0>Z6b`^f9gw?M6LU{OK|J#h^U4w<`taAHAe2tF-Mj*dwdBG%WE`K zm+*fxTjS7`E!S&!?0B^ApJKUwtnXEX--;zmC1i43XDoKSsC(&nZm;CWwUyf&?f0@Z zsp|?vux_nj-Kl?@Cwsz#I*~|=-BVPApI)3Ra{qFZuiJ+P%OE5E$1R(xoIl0gi?^4( z`*@S|f`wYj%z1i@qU|xuN=uJVPuzE}?amdC+k3V4dxhS5Q5*1kON021Df=01U)|bO z^B^K!d}qXijyAXSoVfz-5k?nGYbv!SEQ%5kR5o3!f98o-^zswxpPKK*?T#yd{$gof z@*&>X#0x!_a-tOZPH8MYr}c8`agX!U@?|Hfo;Y^w;6WbNHEKsLm0o(Nm43iBdg-j! z=c}bw%oTBc%D-S%>OFmpz31|$q&0hJ-guSTvwrf;l=-3IYWwp~n;XttoUmJFZKsJ* z(hg@uwj!Q|F}ZF>e`%gKxYv27F#7H`bG!QiUw5#psy*Ga^`8yX=IuZBIUj5noH9>2 zN4#rCmpV^~`-hdA4>a^FP=75e`Ix=0yx^4fm)f!i73oaOj0}v6lMNCL_<@OBR+y3T zKMSh?GmtWn1qtx6h_Q(Hx*p81*j>CbbD_fXw_lYODvMm7XCM!fR%Vef5Np7$fDfdA zA7mg4FdMcZCqrN!1SUg9hV*QLTHeN+pGjv&`YD~+xqXT1$>m2rgiPa3`Mfd0 zKQ8dkrs>t{sfV7Pdd|zETAlRx*ZeK*+g;t(H!q#;(X({#M=|Z$Wja-+2|0od)6cA& z6!c8{S?1f7Kg@J>%J(OFTukQP86EUiVuQ1j(z1=^>+WS9J$qbc;l`yh0>35pNfq2Z zILUjTX4G7J(|u2C1Al}*P%Tw%my5ZxYwm_Mn=@~VH=q1|k7p0Zor&{ST(~Z3UcA(F z$Dg{RE)HymU;j{Qh;cv1^jL7d%m2T#jLy`i1oFKOS1Yr6ET?31Xqnkv$@k0u2z^#N z5NX)zGv~(n`%BK8(VYB$N^V(qe1D~-_^q#3tjV7$vd@QGV zZTY+Iy1I=kS6_bkaod57uR0DqzdYfk#-u6L8P(IZxYBi7nJfgJFehHQrD}GZBSLrK z^1$^5T%KQ-Wwx{Hy113~X+51~eO+SFpE(u+XO3B4+A409|9740-mgWGDH}_)EaD}6 z?w>DYi88ygUw`JD7dLlpocfH(TXA9Z)r0>1>oRkLZ!=Eb8Y3rhHzn$ngoa%*i{M|G zUIzXh=J(UP=BBM=%9{9J_>_KZ^Pcv}Id@b7#aL9+er>*aXqV=`SsoTmGr#P&_A-?G rxxY`*Smcy{Nc`_}zxxa8|Her!;P;-m<4DLJwhgZRY7-ar{aXnDFOg-3 literal 0 HcmV?d00001 diff --git a/certificates/roots/AppCAG2.cer b/certificates/roots/AppCAG2.cer new file mode 100644 index 0000000000000000000000000000000000000000..81df994a027cd5a5fa59522afe1869df1a50a0cd GIT binary patch literal 932 zcmXqLVqRd-#MH5XnTe5!iP6x2myJ`a&7D}#ZhA-4f18*?ZNn=q4CfFYj& z4~WAh%$PQ&>WngY%_;4YHpt4E z-8t;|?R=m~qT|&LO+# z1T9WOZQa#A_ckv08xeM>Syo}skrvMO>J?L`A5-mXeqcA5_u}!|;*~4@NHRF+Deb5- zcKllLH>&V?(@l?#m^Uk0+jVmrI@6^x_X!+`>U-N!YnQKMk!^m?{l+3ggL`$ssX5(k z!Hx`$b$rwStJa^8nC+uHT?mjm65^bMzNU# zn}=73Hjk-x=*if81lU_=3D1 zZ;kahrZnxDac=JFZ)dNcR*C9a;X2PQv8i^-Rn`wurtyXPdLdgKS>Lzu2ECs%L;9nR zkJZJ`ZI^rOs`T4j`4fh6zpc~@7>R^7?9q`K&Z_UW Hon`<4)ecXc literal 0 HcmV?d00001 diff --git a/certificates/roots/Apple Root CA - G2.cer b/certificates/roots/Apple Root CA - G2.cer new file mode 100644 index 0000000000000000000000000000000000000000..739b8141312801fc4e88396bf4366075e2711173 GIT binary patch literal 1430 zcmXqLVx45r#9Xz2nTe5!iG%UM)2+?viys*9vTOAw3^$fWUI6;DJ!c3vT26E!Oh9(9k#s-EKh6V@Moh?3yZ7ptT%{oZtmbE?IX_gbDkv37-N%oe}J zzP5HeiJHX2V)W^R!|$N@`QHwFe7wtbLBLg^?oW5`O>9&C@O4{}9^)$g`tk5`oHG2U-jvVF(JFAtQy>@PC8|Gm+-ur_evqs<>KYls!+pFOkI zyw>maT8D@Bjeoz}a@j5VxYux+X5^hik_|o4CC79w3k0jliufP7(wJt`o^Grz!truT zd5cLk8RGj7?_MQ5Sw1#If5q{d-@GFGL~T_}KFzvQ>X@dqh4C8q`U&%RUM2mQ z9cjbyXqw5BL}ue|2zV0PvXSiivJZh)`o?5)W*}w22NK{1 z39tY&9UF2g175L?oeT7jmWF>&3sQpoaUAA37lOmwM#Iu zvEs(Zt*#Cgt5+O2_q#UPJmcH*-|LSZ_I@L8rY0QHHl=9OE2g*IxleeOO*jx$J&Y#WKm>kMqyI%SzoNwLx|7a?QVA>=u=J?w@!2U}iCt+`i2!(e>BKPs%5fi}#0h8g95*leD~AbVWzkY72)$XN3NX zKK@{S-@NGbnHkUaFWU19&c)8#u)Swc2lF=;T`x`$uV~zj- literal 0 HcmV?d00001 diff --git a/certificates/roots/Apple Root CA - G3.cer b/certificates/roots/Apple Root CA - G3.cer new file mode 100644 index 0000000000000000000000000000000000000000..228bfa39cbd5acfe53fb9d196e3c1bbbd28649f8 GIT binary patch literal 583 zcmXqLVsbWUVm!HknTe5!i9`43pN>mMy{8&*v2kd%d7QIlVP-Z+HbQ8gAnH8xlJyL^4LCu9Y{E>T!3J{TyoM$QCdLMa7KWAvW>Mn2#+FE2`Z=V` zK!A-M?0+UkHdgIM76v8eBnFllFZFF5ik7^ctW?w}EOS?2>c^vt{R;1hh~4CSx{Ot; zJf%9`&*JiK8JDf~U*)$MCB>e6*%Iw<;4c`(@HZlYXX#gd9ba~L;nG{vr%%r}jCrd) zw_3sa#?FwNaWj`#1#%fKb~11^i`@ju(^Y`3K= md8u*U0 zbl-oSljF(%uo;@7&!^1YX}Xx}?3M!$A0>P_^+vP8H8V3IJHBhupLxp9tPUw{HuRU- z^=X?)q|>_%E18%jCbDeXT%l(y-{8vYn!lSbD!Sh4`3;Wi+eeHr^(@8)6k6|SjZgP01 zRV-S)X8EH_KJAewnV1K6f%kseUUfDfdeA7ldyFj2P| z2(WR1lX7wj8xtD~6EHQSCT?ImSiuyb8Jb!xmM3+SuU47Q+4Y1MDAFV_?vyg zB%_^I_FEqeu*`BPS@b4azToMqyWTl6%7wb|7mrTf_ilDqL2A=nvBy#Z;+?uH&i>`8 zi16gms5gGcP$j*kY|XZ7vD zgfB}yma`q&9rZ|F-p#e{$@H)40^1doit>wY9SbNuYOC5GyO`nSe6t=8%l^&QuO>9; zO`VnSrQ+NdKCWQ9MZf%S$gOLc+H15Y%(wGpg~Wq3vz&HSxkO3d%qT^yj_qTOn kM|4=VT-S5o^j^utZ?dN2cw%U$%SrWO_IFKB{k|3e0G_UPUH||9 literal 0 HcmV?d00001 diff --git a/certificates/roots/AppleIncRoot042506.cer b/certificates/roots/AppleIncRoot042506.cer new file mode 100644 index 0000000000000000000000000000000000000000..8a9ff247419dd22a07c837ba7394aeabdd0f14e2 GIT binary patch literal 1215 zcmXqLV%crb#JqR`GZP~d5E<~YacZ@Bw0-AgWMpM!Fi0}wHsEAq4rO5zW(o~96gCh9 zakzxJ9199^QWZS&lJyML3{*gZ+`_UDLFd$>lFYQsBg2!4D>>yS-j;I@c+L7YuChh5U7`KHvAiEsOqE5wMI&W5Px=0B&b;#hyADPKr1x`dQTTp(jgCTo z!8UtFgP!fq=lSQ_e%AKXkUH`2+}53ZH{)ckownU-we|}?AHyW>jf!G=C0A{DZzqYZ zUR*fIJvj8>dVR;uKYl+hIQwj|k87R0Pjj_t->jT;Rj-bAq&^<-@B zm%W!-{69S|b&uzbviZg$sSC@eoYZAvW@KPo+{9P~43RPeK43h`@-s62XJG-R8#V)e z5MLO?XEk63QUIB4HrbfL%co zBPgB8DzG#$asX{)0b&Md!c0zKWi)8~WT3^yq0I(NqwGwKVsaTJB?ZM+`ugSN<$8&r zl&P1TpQ{gMB`4||G#-X4W-@5pCe^q(C^aWDF)uk)0hmHdGBS%5lHrLqRUxTTAu+E~ zp&+rS1js5bF3n9XR!B@vPAw>b=t%?WNd@6N1&|%Uq@D!K48=g%l*FPGg_6{wT%d-$ z6ouscyp&8(HYirePg5u@PSruNs30Gx7i1YwCER{crYR^&OfJa;IuB@ONosCtUP-YY za{2^jO7!e*{cX?eJDxY@8r; zW8atJ+3zl;@Sm>qH@UIM?q|jS>=W#7YAu_)gB31Y9ND;kmOoeaf9*e!%UL;V#2vx} zUUwk!R<>!CBEM2a=7;zgw~E zguTASugG_6SFxo3)|+Pa2irq$E}yy6$m#cutA+FG76xsX-aFYzMMzw9>OIdRD+ Xyc@&=R&`yy_2kb5PImJRrKO4hMS!&; literal 0 HcmV?d00001 diff --git a/certificates/roots/AppleROOTCA.der b/certificates/roots/AppleROOTCA.der new file mode 100644 index 0000000000000000000000000000000000000000..8ccb85c5e90e419865b0ee0fa1879d118972f878 GIT binary patch literal 1470 zcmXqLV%=rX#Ik4sGZP~d6CP z=PUbaB?G1x5_UfVI4{>bu9)%j;;FPbD%pY;7Vmx{t#w#_>bxqRCGOqPSH#SXPaom; zJtvZR@uXzY*I2%*_3^VmsWR^h?e~r4{g`5^Eb1*9DZ6>f_iuCNoe$V`Fd`tmpJR){ z_tR^16!HtU*)tmSYFiGSy|?&P}}Cv)wz?N+O`U-*Rg11Ex849w|xU7HD>CH|}cOXb|xx zip8iWV{^akz0~6W>2axhJa3fEHx@}Y;^HehmRXJQmH%_u1;D7Mnq zFE20GO9Z8Hz2y8{{bWS?O@t+1ePFuJE!N8@$;~lnJPbF3$)ItYRO9BL)SS%3yyR4c z{5*w{jLc#MBqJ1(Disp*DisP6i%Nj3;^NZW)MACiU+kS1-9J#~>6I6pV~4 zo(Ap)t}wmVXU(Q9MQ z=(W$146|OW*T1@6F1)P2-dtCYDdukS$xnql)Ew@M_LjQXSMGf#JM*Elj@{b)eLI)@ z<1>{EOx}3--quNWffbC!T}zZtE$R3u7bEW|rdv0aYt_q6#~IR6cTX$qcaP&yI~r>0 sd(5DFX1d66PWfH#$8RxmwyQWz-7B0R$@TtKJzw70gD%ciURNIj0LeB5MF0Q* literal 0 HcmV?d00001 diff --git a/certificates/roots/Autoridad de Certificacion Raiz del Estado Venezolano.cer b/certificates/roots/Autoridad de Certificacion Raiz del Estado Venezolano.cer new file mode 100644 index 0000000000000000000000000000000000000000..320b5f6959f14f50986f5dd3c5ba38894f2e5e1a GIT binary patch literal 2463 zcmXqL;+$>J#NNDsnTe5!iILHOmyJ`a&7#9x?>WR@i67@8TF zfTXyDb%TLYskw;?eqh@Yb1)s?nv`t*v4`-=C)rtXz+8TCn=8xU%)YF|G6Zm8%yn33zWR zDF3cWMf}fVnbrT;+3L;f*(0KbZ`L!!Yj5zsHUH#>2;;1DrA>3OQUuQmFu zk3C~!-?Nz#L28k+g=VD6Ox;&HQ;a9Y<>B{Fl^k0hx`%J{y5sINyTIG()|rc$6WQ#~ zW&Hlx=F5DidC@LWv43k$ZsSYeywSwU`kYJm;y#ae%m&+~rllWEQJu;3`Bh12-Lgrd z!WS7tU$@14sg~@hf1xL+5@(U!ICoD$+;_twEq&Se6X#THYKtsp?04V0+?eS%|C70| z(h`(?fBH+e$DZB4g0RWYpT%1!#=k$>c}=JNTi0*1 z>S(<^6BfQZ<6|1OQfm8zW1F8AGchwVFfMLlx(7@Vw+w`UIa^kkk?}tZhXEUq0+w3_ z<{&X476SvlCVsU1xj>qYHK8qziD`ilk3f*8o36XAk%57MiGi`1u7QCpNFyJM7>mf- z-Ab~@9$aEv@wY4>X!6?`2YuIF2Ik!WkOF0vCPsH4$GHKkvV~2IYD=0Jl}58Vp{(8n ztYARJzbro}{#bx@4jUxy1j&fI5RgIgEWQTb1}Y1b7AUmIWn`2TSn2DRmzV3Ir2_q& zK+KT*3&sNr~mx^i!B$w=X`a4Q+C)VE9u3wip2781MyDbS&iatJHIVdkNljn}-LZPPUp7Czoz zY_t6P{hiWxuSVSdarV1~mfCvRNvkK-vwoXla`KR5`{NC^_7{b7UOi&Dbw*g#zJN*b z{mVs>ycrLrKCFIlHot06^!)vkAE zJJcj~G@_MVE9bnQ<@!LO+UBP<#KL__s=C_J#HdUm|V@Xc`u$}^Er$;?fJC{CsI?sA3vaXD(9A7Q`75(>q2I}(#cyO z9+heFQir27#b0OF?4SvkwYrSvPFm^Nq%x^HwqcfNsw-3S6DR8vZ$dtbynHU_E%VmY zb7#Qos4I{BjaeEr1d#AN85K^Mn+av27??!ZUas>=1>+kVW#8^ zLp}o@5Qj^cH8CYOGtW@afFH!?7Ul>}Eh@`QPAxW6GEjgBNjj$%m1L%6CMT9;=I1Fm zmX>7X7iE@Y0@a8ah=9~E3-daHjL{9s&o9w+b~KO^=QS_{0#gGEQ$qvuC~;mR5ZA!K z9L%M&Ynm99kb{Gfm4Ug5k)Oe!iIIz`iII`v^n>*-B1-?V#63U7&OIN)l*HYzGiv{e zP~+;wLMm}S`PPn|e$BS?H&0bFS$0O~%bB_Dakf0X;`*&>c3NtY#S2&Lv3~v3ZO7-x zYK4t)4ve|G(l=+net-1QPt&_RS!~;8Y0N6v?4Vh8pwLY)+j;%dFvs7|WGtI~w|`r- zG413E-c29M_n943P&e9n=6ckrZ{m(-zQ1>eHYU%R9M_y(zeBXVsHWDJGdptXv$qDT zUEFSpGA@noOx^ZCQ`oE({`}n>emvxQHmx~Fl=vF-Dw5}>;{in?b-j+YfWMXDyU|ih9_!k%=Kfwt> zR+y3TKMSh?GmtW9oC%C$Sp}BHi3W{*294cp90{!@jDkQ-2K5HoY#iEbz!b*L#AF~Z zB^#2FS*!p=B^jv-C`m%WIUv{|0Irx(%q63wq`*pFzr4I$FEcMKzbF@&yt4Jc$x$yk zLqEXVQ$Hs&FS}SDs59Ou-q0-G+|(@IFy7ES-WW(3=oO@-8PtQECeKn~P-alFplCtC zl00DA!jUS8O3_#{0(xFS&PWEbAP4ZVh_Q$?&HtrbtnhJq_a-0TeNIQ~)6S;6fQFqi zB5`qupbbe4ovjEEtHsmYb zZru06^lIk+50;{Sd*VNwxBjwE+1@qn$d+lb`}%qB9na--`rP^Rqy5(s|NA>q0nskd AvH$=8 literal 0 HcmV?d00001 diff --git a/certificates/roots/BIT-AdminCA-CD-T01.crt b/certificates/roots/BIT-AdminCA-CD-T01.crt new file mode 100644 index 0000000000000000000000000000000000000000..bb6c8554d18c49fbe694acef023a69c8c9c9996d GIT binary patch literal 1105 zcmXqLV(~R-Vm4jC%*4pV#K>sC%f_kI=F#?@mywZ`mBAp_klTQhjX9KsO_<5q!;sH_ z2gKnLW=%}V&CD|tG~fsExrI4`Q;W(nlT(Wgl?)UhLXys@MJ1VOnaPPInfZANj-@3T z`9+x}nLst-2BIJ}%))$*AY+^zb)8*wLktWJNZFBW?w-ce$!^B(MI6_TA`tdnD{^VRb7sdLU|&F8*v z*JycXbEa|fzi8gKojc9M@6UTVeGz-zWu2E(xBbwZwMXaSkB&9L;esvGSfj4^?)-Dr z&-!G}xyFC-0>xk6ZV7$L+;m2B@3+NCvyPp9p}2dl-5*XSW=00a#f{$$8ow9_0b^8F zn33^63x@$4kYZwFFlbx{5>#MmTxQU?*r0I%8%IKG38NshD5F8+WCIU24sAAIDr0A2 zGO&@d3dzVURsf=sj8p~GWTAjaNvR3}MTyBJz?7yCT#{Ilnwy$eqG#X^H;GZqI-{hd zz)D}gyu4hmAUjhJoKW?WGxQ7cb25`F^_>HPs6$0EieqID#bYvHlbW6XI4=h_-KFX3M$c^f%x05c0PZ7?#- zudB-4y{4xxVM^*n=YWg*bF&=(3Ozb|OkOSR?Wws|j;R&rzA$YF{^i{NmAr0cH z2|}KYB`>Tu-%gFu3_1DCb>6%wf-NCM8t2Uqd<|V3sJ-|^z_XV;BElE+moWZu`);Ry z`^pz@ksq5FWV!zYh-?4+5LKJ=^Y>!zt^>=BIBLVaHTJX36BluMs`G47gP7lc{<$_X zKSU1&mCm^GL#*?H?{f`~<5M;Ko^>~R&b*~=`|?+%!Off%_g7m<3v^v9d*boWva6y) zx-soATgsv`)>Bi|x0HRn)%1I-i$JpT;l;;}u^i_={c&6W^O&w>fzwXjZ#c8{qQYk9 O%Oc0`ZVbqsS_J@53XS3b literal 0 HcmV?d00001 diff --git a/certificates/roots/BTCTRT.cer b/certificates/roots/BTCTRT.cer new file mode 100644 index 0000000000000000000000000000000000000000..da96dbb2c93d063581e5a96ebb4e258c37923087 GIT binary patch literal 891 zcmXqLVlFpmVv1kD%*4pV#KOeDu+xB-jZ>@5qwPB{BO@y-gF%!bw*e;`b0`a&Fq5aN zp^$+9h{Gk!>6DmLl9`)dlxiq!AP5rU7UpuUOiC>ZDJm^4F;p^800}Y+OTrZ@Afy$7 z^7Bg!!|F<^IChw;MQFb8lbttNLc@n^wolb5B&#(PO+Vy_3-8?#l#`0j4ZA-VJ!F6KYLwB<*Txh2chm4;Ok`xj_^5t{jZv1`*~o4BuY=WRVPuSW00l6ig{BHp=w z3v#oilJ}-Oliz;s!>9RryQQ~(3g{@Fbm-AzvEErmOso4O?!FWdd{<|>dct};gDF)P zjBS^v@_+r)H!tbDyNeEE>~7huMwi?#S?FE(*LcS$OK$5so2!4GH_A#LR&jcjY`GEu Dq-#{f literal 0 HcmV?d00001 diff --git a/certificates/roots/Buypass Class 2 Root CA.cer b/certificates/roots/Buypass Class 2 Root CA.cer new file mode 100644 index 0000000000000000000000000000000000000000..47d3400beb8045c2698e334efc202e160d3b205f GIT binary patch literal 1373 zcmXqLVvRItVs>1>%*4n9L*4Ezka4LI4DLs{5_nf&|>Weuc3 z94;Oar_#!T#NuKF$6#Gc3u8kwV`C$8Lj?mlkTf%oI853(2c*bIAt*n;M8Vn7Ku(<3 z(7@2Z$jrdP*uua#N}SgOnM-y1nwXT3y~N1Mz}&>d&tTBR#KqLa#K>^{c-;4c>{rTv zJ1c(q@-_3xJ0r&1i`(R%MDp%>UfLY=`jt$gsK;(u_ESCUHr$yu_toKqNo`FU#dE^g z{(Gl<;L$So-1_u9PtCiJUb~A8Qa@kSZ{Ak-`1#j)s}p`+{y2A1N!JsZX=|bzUT*zj z*uFUM&+)p2`F+9VSEe5fHJ)TAp@jEsPe$;eKTfo%f_lz2<4@^;M@; zpWn~sy3Ox9*>A;yv(%X)0^NsLgxtCKcS@vJPXK`;!@S9ATMRiB|pGX(1 z{j})k@9$zMX_@mq0~b9Kl}Kmvs=u1E)pxV;gT&Xd`(DoAH@YtCZKD^(7&MXd)BRVy zH`pAKR|!7(ci4QMNRa)PM`u1IPQLgzJ^Omly8Rie9h?`0n+8{W2>y}i#GZ2Odj4!5 z3*O{4N$btJ7Zr2yepTFCvdZ^W5wqv*BzB&F(%!~|-i=7M{4ETX5S5}yj@jnZz0W**?kOc|wv52vVoNOq6kTj|3 ztJ|EP*^@!*KHb zIfeIZpQg=wxum4NO6e;ES)#Y`L@^Q__xAj;~+h9Mf(J?<^!lM^Ie=8NsTWEbzc`o?J8 zfmLh1U##+deTDsz$9JW^4NK-{o$K4QDdEdvr3=chr$kj{-sRu#5WXfmGT`RonGf^+ z^)gnfD~sNnG`E`5H|n{!he4FYGp^ic{SPkfes;emPqFD>hNbV884+noXS^oF9sZ@x zvawRMWagQDYZdOPCCI!E3tYDN)sw~c%l{|d`55J!W2Ef-Zq15!@4SRKZDI=#?W_EC zs69iL`)^F<8MX_vYC~pfowSsaT<@*r{5d%`D∓W7#JwuU+7}FmM0$M$V5XkE`*n JnIRUo008NES5E){ literal 0 HcmV?d00001 diff --git a/certificates/roots/Buypass Class 3 Root CA.cer b/certificates/roots/Buypass Class 3 Root CA.cer new file mode 100644 index 0000000000000000000000000000000000000000..24e5adbb0d859d830f2c27e62342850b2b35399a GIT binary patch literal 1373 zcmXqLVvRItVs>1>%*4n9L*4Ezka4LI4DLs{5_nf&|>Weuc3 z94;Oar_#!T#NuKF$6#Gc3u8kwV`C$8Lj?mlkTf%oI853(2c*bYAt*n;M8Vn7Ku(<3 z(7@2Z$jrdP$imbjN}SgOnM-y1nwXT3y~N1Mz}&>d&tTBR#KqLa#K^Gp7S~j775ue>tg;F2s6Ci_|>?|`&#G^)?V+-4PQ5Fn8k=32`u)_=Kg5H zep}q~`W=nx?631b>mBqL*An=A=G2SVf3sKX&6=;l>a@=X;-<|xeB}M%n(S_?%KFWo=WQQ#&R<~Q-MVwm z6qU;U+U%9C8T{H8KHic!ow?(bXHxEo3&}}$6Zj)m^)KARx-@OkdFirEEh!s)EQ1ah z?E28-&9q_Lb|z*<2FArs1`Y=Nz?3U1%*gnkh1Gx=NEyh21o&9QSVY`+oc;ea|J{#G zZ}k26eyVQhv&lYezz34%2dQTP<{dWVR0hmAz*NS_z@VV)Xv#9-kV8_!`$wie*X`Fl zGMTVrVSd>!F|j2c<~lDY9QtJQgKPec#;3cZZ>j1mSsq%bV)X3<_oqEsKPIo)#C|A# z{_Qg-x>oJW%75r7aK`X@!|vTDZY<(U34gWd>!Fo~qL&o1-uzKw)HvU^qd{)v8NsDC zpTsu1&;4_$LGj4x3+@Gu3r{sma_HoKiY=ehB_e#qOlH!Dr)=hTmOYy=+oC@vTiUJ7 z*(u(Rkv%vhHnsM9SMkDGAyM+0&LZlETKTtjR7+V;*)E%~eCwR&nwjBIvnN+M8%Q%> zPdeeSY}KEXCtlYl1~aZu=*XKB@3QlBLZiu>{L8hsJmOz(nXpH9r408PnX8L36dG8r z{n^;BzuU`@*Q-tD^&>M)wXe5s9Qjn5c)o63S+ZA^L+a%AA94*nZBN^-_4EA+)=79F zmMFEz&bj)mWkN{S*H4{lj2X=yi;Q2KWSO{0&_vMg)dgosdFIIzc>V|4hJSI)dw6=m zzSk#{&*q+a^22OZ#@x4iW2YCm@NVNXz4MSKcK3q7DW~hiUJL3kp5%JMr|{;UlQV%%ZK)2w-M7YFQ+6NTy+5_$Qd{MJPiv`Wo)7mb-kkX4>mzlqN%P0S zs9SH}JyVZ+;d)`NOyG)))h>@ObZ0&OVZHl~@AZ^Vf%~4VS{?P$@EzNp;{C!&T=S3b GoDKkgi$p^J literal 0 HcmV?d00001 diff --git a/certificates/roots/BuypassClass2CA1.cer b/certificates/roots/BuypassClass2CA1.cer new file mode 100755 index 0000000000000000000000000000000000000000..436ac0a1a7680a8d1650f24974058aa8c81ce32e GIT binary patch literal 855 zcmXqLVh%QFVzOSq%*4pV#K>sC%f_kI=F#?@mywZ`mBGN- z8pPq^5pgQ5EJ!RaR&Wf~wX`rcG&43fGKWbsBcz>kK#GhMoE;Sm4dldm4a^J;42=y9 zj7$wIqr`a)k-5~htcg(x*)xo+49rc8{0s(7j9g4jjEoH3Hteo9zTJOz{M4>q=cDeu z8=?+c+@91TvtIZLf4-TU!V$eQg#{*yOfH-2-MDL2u7BXQ=8Kq1TUSmrX;+H;cjor< znd_$=Tyfmt?o!d7yc0FknNL4c_;h`Gyx~H9^Go~Q?OVBah0i?2G-vA-dp>h6wzwLp za`2FQ*~X5TChOhW%UG`Wu=k(6>L~kR-40EiDM1M)Q><@2u(&wa*iQ7zWTT@Dx3+4g z@mW>yD+a|gJ)KmodU=wZzUbV>Cv*E=yze|G;u9h((8-CgaCK&2bA8;+eLO1y-YOkm%j#41 z`|Ue9_mpqn)oWuk_+5|2B*iV8HF4thU~#=WYZK;9OR?OWp0Q~i>uKNT@$%tqR~6=H z{LUA)`1(z7(zn`~aq>JbR=cQZ7CG3O1+DLim{5H1O`=Za!Z+<(?Qi+sRAex?H{llF zWhsx9cCFkZ-9398=Vg88D>z{K-EvWE+J)-K`77LoW~nPL(d|=jo}{qwx@i4JJ&AW; eJnHr9KQ5Hmx{!Oyf+Pi_IkMlbyx;HBkpTd>NIwVw literal 0 HcmV?d00001 diff --git a/certificates/roots/BuypassClass3CA1.cer b/certificates/roots/BuypassClass3CA1.cer new file mode 100755 index 0000000000000000000000000000000000000000..faed8e85ed664c3760ea025527a27da7697b7c8e GIT binary patch literal 855 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 literal 0 HcmV?d00001 diff --git a/certificates/roots/C4_PCA_G3v2.509 b/certificates/roots/C4_PCA_G3v2.509 new file mode 100644 index 0000000000000000000000000000000000000000..e079369bf519b9b2d8434335fabf0a3df8eba3b6 GIT binary patch literal 1054 zcmXqLVv#avVrF6zWO%b+d3RoE7UTINHD~mv#9cSwW#iOp^Jx3d%gD&e%3#oV%8=WD zlZ`o)g-w_#G}utwKorE`66Om_Ey@heOwZF%@XSlrGn6-w1xauVi@_umLW)X@OBDQ4 zOUm<$vJI^aEFcODHIg+I3@t4!6<{hMMkweixaAiqB$k$BPP-qpA&NtR98BD`H8n)6rUx)q<6_O>3n?i{rLdSmC8H%-Sb*-n*xdceQsLzLmszWGXUQ1!G@PD1S*v+9 zYhV)-gJ630=Z-}8c;?Ahqj?{Eyt2^9v~`o!?F~((aKL2UeYj*S4bX_5Sl3D-rO8yyfGhckTuw?hw;JsSsA~&qhtIyeeNseKI v;@cmNNliO%Y&x>rE#R}^(SF7iC9l6$sNZ`2J`!hmrG`GX1YS6Ua_8`q=7g{C9|-Av!en; zJSacEL?Ot~Ku(<3(8$2t(9*!tz|7PvN}SgOnM)Hpo0yc4y~fDOz}&>d&tTBR#KqLa z#K^GfaK-mKGZrt8iYu4cbeAQCKl$(MX`BsLU#wdCXpY(xs~0nid*uWr(RX|H)0*99dS90oKU6vUY`Lza-i>Qr*&?qwlDKZ% z+05X3Sh*(NnM2t~=+0Z7wFheXmsUC5j4HUffBAJrnQyaK_iguTt5_fxX1MNs6IX-d zcj=SsRvW2Z(aC;WoBiZboD!Go=@vuZHUDm3bl>$eVY=nU)Z_Pl&wRqAv{BdhsfSwT z>PM?S|Nb*c)9B@9J70PAg=hPAivL!%JDK;n{1&g!x7g#m%>=H7T>Jdsk-NvUdm^_I zgVw8U`C90I^7FhzzA2^b z*6J^BA0JM5fAuHR3Elb4>(evYmK%m%J@1|WpM~{!#F}_9>8F<#zc#!rZ!GG2;nULK zucsf{`eo?e5W2hS(=*@Mo==ZzEZnsr>ezypZS#e&GKG(MS?&~YNH1-LtbJbxfStA^HG(sZHx9Qf^JChHnKipR{ zKWLs%*te^5R(>g+^UGYQUuN=~@PF+5tFH=u=Ul|^L)<19Wu=_V!x)GtzB?J;?jw^d0+QtUdgpJeId8VKjAvN=ATWAm(0x*ofIbN z!?odM%_T`+C$~3y|9%UPzB{9CiSL;r=H`gl_miz0tCCmMSgrWFX3537i*&bX{h80$ z_efylkyB67Z-=T%+W&oFR=4@#!^ZW3V%-7L6C|4$4rKcl@3<(;Zue@Nq5lV`S-Fn{ zOP)?y)7vuDMsfYoTka?BTP7u)jt=0y-sr$OXZG7&+q&gg@~0_SzFktQdE4V$)150! zy|OHZQOCVMGnJw6%CySPi&Q+l)P_w zRacmf)QV+uw#IHwz96iy@b$!;3%#}L?{hy9-`O_LV&fE^h@Jf z%=}B8v-9@i7mUyAr}JO`R4w^e>U#glU#;0ybLVw#Tc$B{a)-lryR(6dPrZ6y>8`l- zpV6b^hXeEXHI#f7UbU$+zkL>>u&)7 literal 0 HcmV?d00001 diff --git a/certificates/roots/CA Disig Root R2.cer b/certificates/roots/CA Disig Root R2.cer new file mode 100644 index 0000000000000000000000000000000000000000..e5e2343aa815011b5044128b849639f2971c30be GIT binary patch literal 1389 zcmXqLV$C#YVh&uu%*4pV#K|yeN5}0AT?dm5c-c6$+C196^D;7WvoaV28FCwNvN4CU zun98-dm9QH2!c55!dy;8i6xoEIf-S7FhMS1E|<*W%yflBy<$B>Nds|^N@igJXGaBy zcu;4*IHwBb49)#I$S)@^iW}FUE}Z7ZUGMt)_7JtTU{ApbL)SN%={bEnJVnE z9a&yF?%l_%V#qPE#vtMS+I(A0de%HQD-6l+WGeRZ*^yIIKzvXkzmsxS~ zjY}qz!=|0~;b9Q7iI+Ni;&{%owU-T-?|Jd`VcNAzznQl|7Q1+! z&Yt(WH|_4s^Vd2Zzp+f}($vh&wvu^XTFX?(_xZr{y{9Gb&P~{KC@o>zMwWLcpSA6r zmFBSGx!~JISLW_->5(rEvI*|Jd%l6mKh>ck#y#M~>}T?g)lXbjM7Pd*bT8`a@t;;M zY2HtaLTaAm%-PImE52xxiO{vWO)ETiU#!w_*tbYb{{9nldBNh}6Sz{H7xC8oU}Fq5 zuHC@9}Ql}`Gee`Y>kcbvbt*>jThWlg@B($l^t?yx?hy{#f=i*o*lzn3?~mCDbY zx?;_@TMv&KR{y@}w)xVY^esstyEwlmZ^tN(mW2zxIO(|ttB=}vQW z3g79id#?E(tg*@K70&%#{o3Hd9pCjwuWnoF6J2=nh2g#z7Hl31r5?SybWg}KLh645 zUsLI`?I+oD_}>4w_&B5R$o6_Z(F>}XdzI#Dzh(XA=Dz0bfe%-#AH8`uEqa2mpIn&L z>kaRx?VhGAxa*U1TS>~)6B?!WWleWoGH3iU;$`|=v?t{-?UJ%hg>#$;31nFFm7uk)%le~((ozJI0Dq|XUT z)1QbeWS{L#B_fFGZP~d6N|@u21Wy3HcqWJkGAi;jEt= zeuhQ{1|SX>kEU}*W?rI#XI@EaQC@0^f?sM$d45qgP#`V8C^xYrGe1wkITa*p=x*Q& z(!&qLR$C%;dz9)MAC8{QMFFIdNV?0|N_VLj!X|LnG5Dab9C&?%;B4 z6QdGxU^22YFgG#sGZ-{6axpbAGBV7rD}J}vx?)v|v*Xu*`%^yYZR+*va|^koD0ITo z$cgP`^VRu5Z=a?!TZbI%nK|>!%LDxXd2hA|ZrXA2bo3p$pBaWJ4`=@>d7ZISVe0o| z{JrjLqS)>xu7339#(Z(zIj3w)r-v4vb#C40F7{O?xS{O)Wrmc!4m0nbxpDi*{AFxPxamlw=JhRx&#LURRxH#D$(Lf%UI%JhuBn-qF zL~4q>Esr0#owU?{_9_XJNsCT3H$@uogA@oeGX7^_HDCr(27Dj^evkkQFzK=x$b$HM zEMhF!^`oX~U^Fl?XdOQ8Y~Fu&?UGGA@9v1?_G>Je;dz>;;nnB2%4wywM=vX;S6(bW zx|Ml*#2TIu{bOOm{D!yKo~K&N=9}FL3HSozJ`RlLP ze3N^p^}K&>9PVWGy60f!3E#5Xd*3#0Z+x)e=fVm%ajCEwAN*`r%e;MKd57KOd-6ZF zb%&P3WJMcw96fH_x+cxZ{ZNF;%!g0yo|fwLIbVylsgPSSwMjGJ;zhAt?+@;)y1C`X z895)fhvgd$SMSw2ajrjaVQf8fsmYVIovtBq`_^eJ-ECh{`MP*B7w_MFC%=cS`L_M7 c{%l3f;}+Yd9%1=(Sog1p)`Xcm+0V=e09wS3Hvj+t literal 0 HcmV?d00001 diff --git a/certificates/roots/COMODOCertificationAuthority.crt b/certificates/roots/COMODOCertificationAuthority.crt new file mode 100644 index 0000000000000000000000000000000000000000..423a2be0636f4772c79e7c6031263e37cb88a072 GIT binary patch literal 1057 zcmXqLVv#jyVrE^y%*4pVB;ePm+trl%fSc)^ohg&sQ(FUGHcqWJkGAi;jEt6mZp|bgTjqXj7rEs$H>aS+{DPw zV9>l_zdwwUxW6-W&ir%&yN$rU$3d+?Y>=Pkd=1z zf!pGOI~h0svv_ot-`o1~cY3bl%RQERjcz6}ecZUhHqU&{BmGC07pZk0+Y##A@le@r z=_M7*Ecew6R~BwwsrrxCe!1+f%Yg^Em)u%o@jf&_g*DY}vWdTL@7iNm6eTb9onlQa zWG{Aq+9fHpm&Ny--<+i$Yj&%BXJTe#U|ihTXVBPfAPbCkSw0pq77^}`c!C7vS)2?U4D1%zEU;>` z$S5f(u+rC0F3QnM&d<$H$xluMG4vq`%NaRc!IPC9P&IOt0aH6L$`~2!X3U%YP5R|^ z%k35GWQ!y`FSkE&ZhCEha@E%rTi=J)C2XOh^3K3-b^3TO@L< zkZa^Rps%3s*gf%%hwGk?$L{Sa%Qim2plj&n^Y;1N^Bq(E8y^UJq0*+da`O^V;oy_BL*g_ah#K@!MD*l$mUL(;{fiyAyBp4E&~;Zc&l`Z@yn#LTKksX(CsgtuDSa0t7O=+sNWN0)=z%@ROU+h z^jH?Yeca8<#G7{-2rW2jEXul*_xEwuvd1^PdjFV+FFvNIvCqKOQ0{oezKBGNHP(+9 FQvr-NhT8xD literal 0 HcmV?d00001 diff --git a/certificates/roots/Certigna.cer b/certificates/roots/Certigna.cer new file mode 100644 index 0000000000000000000000000000000000000000..8a3782c78c2702b7bb2354de74cec53919b3e402 GIT binary patch literal 940 zcmXqLVqRg;#57?6GZP~d6DPyJJC7OpPkQ_};AP{~YV&CO&dbQi%F1A1V#sa4$;KSY z!Y0h*7Gx-7AOPZU@o>6iWad`pmt+^w$R2IeM4eg=akMlPl%Mn;Ac86QtxySCY+RIN$w&6a(y zVjil!6?9L0xTr>~!a?y#!n~*x$q$cgoHpsdL~f??L+zyRcORMQPh{Weah~r@JoU=BZyzSG13oEAz)h?ZNCi_H7 zSeNn2=Srf%Vjs?kzX^|jxrl29=e@`AbMo(aJZ|L{jas&A{u+>ZSySH~Cr`s(D&=63ODK z_I54`V&BwGsIFu6+VVVE=W~x(a9zxAK`D-dZb|c%c6>b4n|bG#RRr68CT2zk#>I_$ z3>tTWqeNDik?}tZs{u2RGLQwvkt`pJ7>kJ1+kcLh6Sk;C?qmEEbk+4+l;s^kgA|ao zGE1yMbOTle3oVwIkr!=ENQsLNWD7sYRV=`C$7UeN#+lIO!Pxf0iIEW`#K4Xm!NBwf zj9^BFR%W?Lh2NakKU|zR@Ac;c{GXOyxi$6KwS5_8wsm>(K3(rG@+;=XEe%ROC-mdJ z)~)>4=KqA5j-R%+Q_8-Ts8@fb$o8(mLpdJ@$sYdeb1pU;RL_XKQ+sSDkEYK;<3+F2 ztx{VqPkZ#X%(b9@tMsbJ^ATDy$#!4)DEZ}SRZOI&-$vF zmL$uU7`gxFb+-S%@VDJT@T#ElZjS?sE0<{K{uTYP!B6{(LA2r@!HFjO9N$;ZonHEX T`qTr{BJ^MFcDug&$xS@~re$4= literal 0 HcmV?d00001 diff --git a/certificates/roots/Certinomis - Root CA.cer b/certificates/roots/Certinomis - Root CA.cer new file mode 100644 index 0000000000000000000000000000000000000000..cd218e5fac61c621a88d1c084f4577f9a83dfe4d GIT binary patch literal 1430 zcmXqLVx45r#9Xz2nTe5!iILHOmyJ`a&7pY*L>WFGgNSy{3U1}T46-RF~Ii=H3Q`s!@&YUlKO8-CR_Oq>-W?3uRBF`z=B;L$^=B`!rf=6~ z-7cE(^4^D|K1)|`eZ}~wM=zy5CI9bY)ydr_7V&xZntYId6XB|7vZ^Iu@AFMw!aFwb zud|5Vuu}S2@yV!#H`5$et@K@H!nC%fZjFg45AztCmt+5?rw9S`=u zUA#bK%N))PT#pm>{rHjAaW?v6IqQS1#d!y7-Sqmr)t8+$<@)>7w|14*V$I`G87wcJ zUYoom>Cn+v zw%I=uF3IOkWWJoR?5gdoyX6yXO_$8)kNX~yPBh`RaQ>uJ`zOR0j+Ow5c7jEj>E5)Jr(Nm!Pjk?}tZ3owtc8SsPn z!XQ4Y0W**?kOc|wv52vVyr1avb?IS)7y2BpE*B~-nUqmca??N_B(2OMVIbCkT>)y2 z113X8hC17jTS~D~5q8!g>brKGIq_I3>y_P4q1R#YwgKlJyz)>}J6{=AH&JG${e^`S zWpw!cXH1O@-g`mmMn~)%^FO~+4p#JZ&r0BYb@i8G{DqR#=K)9e>+R&`Ub}UJ_%flM zD@hfv!m{3QU2-^V!)jpXJ7xQPFXqd&>fYP_xt#kYX)Kky#OdPQGbc`57Yl0kH=VLs zD75zJBd6C-=1k^1;1kWh`gpG3f&lR;$}6^VP2%5FbudB4;*8X?=>MO19w$1q>Fa4RNfW2^r3Y{8{2|17IzK3yxu`8*D#w-H_BK)ZsVX;? z{WbW+TOPk8r+Kz>B9DU7s%j}SJwBx=+t;Yq=b}aj`E$YZ##qa-D#V^b$vrN18 z$|v+8gYj(P8ObN}FEA=_ng>1S@wYp>=WF~l_2mjoQy=KPV0UDd7tOo2;fdq}ex}I` z>P1JpFNVm+dL4F{UKhHo=Abc)2&1g0LMFH5X77nq`hl~RTYeEO7;~E~vWk+*PvE#{j zV6+BxaTovqg*hz3s;Bw;F+}1k;pU^ONbT}}_>jOGq zkR1S>LZ>kT@%oe><^OYp0Acat^Dr7h3J_Qb2oO350Ro0@oG%h~e|#XTIT=kI54N@bhHFzz3(IeE| zX7S+dl*m|XW;#t=`JH`7%wy5EE!URsrzPc=?+O}jS6If#gFVaE|2lV@NXJ!tva7gx zTy}e>&|^Ata5dnJm<_`qWpBQAp- zX~-P;!p99maf?t)HwHEfL#Nq)f#C5 zvo(!D8KVsKvm~JdZqiOee(O^{i#hw|W#k_Kzh)Cq8vq9AY3XcFjsz$!0UV9S0{KY`(Sw)?H|O*uS5=5bT_tq35lMD*2}Qp!FA{XfE*1JBt9Lip=in zQHr(z8P&IUz3fX}J#?zBcg2Sid@JP^Ik!RLNlzgGnx@F|&?CvTVGQJCGvIO0KABbS z4?=A&xmJFYTqLPZN*qHD)Vo}y3Kkx-2hkL zD>QS~#aU)_ztA1etml=M#yikb`5UFwBqw^)G7EHlmXucamgI@j3Vo*7o|;tUp+Vmu zeqN;IDzTr|FylF+2E0} zyOOO+eXevnXy^Ovu4@~a9PlK+Z6YD+T0*tgmnD%V-}tl0YkYCuK)suvNsmUo8t!&C zx?9$1b|W}!oH)A6@WX}sn+~ho3cvOxo!bJ(9KA^}Eon0)Eo?;M zUhR3<1MYN($W1`~x^GWX1ph literal 0 HcmV?d00001 diff --git a/certificates/roots/Certum Trusted Network CA 2.cer b/certificates/roots/Certum Trusted Network CA 2.cer new file mode 100644 index 0000000000000000000000000000000000000000..40c85c56a9c0e6e754d8880b5abbac6c098ebc1f GIT binary patch literal 1495 zcmXqLV!dq8#Jqa}GZP~dlPJTENRdMO@caFS2aIhmU6ZU*7T@yPfR~L^tIebBJ1-+6 zFDrvVV}l{L0Vf-CC<~h~Q-F`5l7RwwO2`4n$jZRn z#Kg~F(8R>W)WpQdu=i)hk7rjKcv9xJNl!~jw^y=~D`l*G|2rnV=j54~?3ELr?R0vo z;63}+?CPB}V{guG@V?&SpsjxS#V&*0cAQenJ*U3cc2GGq{rK{CvsK@(;9{8G8ntTf z9nF)EOxa%-_{67t^|ZX05f%lJ+}p#c`5J8Lr_^ zCNw$icDnW<@xj5xwrPuFzev36IN2-isyWlBl*#a&rrL>Yre|A|TOBMcw^2`Fwck%&))Nq|z%k@1OS1o@|F<(SGcqtPb~11<;0GpnSz$)T z|17Kq%s|RO79_yOBE}-JZDEKd)8Pg7eO-HgUHKui?4lLlUjsgnG(Si^3ozHRA*V86 z_5`LfMuxe;hZGP~y9RsS92yP-eo#oOM) z8ILC|P~&Nzuz~qiR;mWa5x0s5(YyFQ7~fIfR@Y&>chZt+b&e|adQ~Jx4jtJg)J>#TOtYg+4t{|4^J$egjk8hi_TV=s# z^NZTfE6#k(sF145Po7XczvM*rP43WdmCUxy#~mFe{VwA+R~5HeZ}-b4M!M~%7mt0{ zkvP5?AJ@J+|KP8p>2c%4GmFe6oNJ6pat@nzC#wH{G!^STlZ7>yMx#QGS2f5-oq%UMO>)bmoor-j=*) zvt19?CT$GXomaZx`ALm{>reNrSjAqEwXq-YRk7t#(>jeoeb(;jtXy zV5OBpvzGq!*Kjr6Fx}rRwe{$ize$T0W&JTRV5_^&^PsqK+DR9!d-6?ha*D#&YNjmt ecucd;G$Ht0_D!aJmIkE{zQ-hIeQ-Fa(+dE#u7V-} literal 0 HcmV?d00001 diff --git a/certificates/roots/Chunghwa-ROOTeCA.der b/certificates/roots/Chunghwa-ROOTeCA.der new file mode 100644 index 0000000000000000000000000000000000000000..2ae55653898a9f1c3e47db696d90461de815f4b9 GIT binary patch literal 1460 zcmXqLV%=cS#5`jGGZP~dlYr=ny{Yao>vv3Nh8dwP;S~9L0HAC$2JoO~~v&^Fir}{PXWwN`~8YL_a6jGC!cj~6lqNz5wUZ(HoSdjAgn$vdI_tU?8`+9w= zmnc(2?TiTTggs}k^Ue}B4!)T9v+C;gip{f(zcaL*ll7fqv3|vyiok-d7=h+M#qWZ) zCT(#~JK@B5#au{~XScZF~7x%8(`4)$$VPJ1+WLaE7& zm1f#qv!?8v`{qp7#viJkF;Uy}d*pK~Rh9>39Bwgvl-8Tfr|NrEa?`U)^W{o&LkyXi z85tNCXBlJ|$O6-}EFX&)i-;W0_igE)9!^r@bUhGisaJ0AQ9N_ zgUe)Y2q33MULt$(5{`CUH3o!8hlBTDDPz z-6c!w*wVfVp%?BqBcz43;wop)=h8}FrfScY8CHC_E6wA#W@C5>+o?IPG+tPwt7(6{ zy45~)@(;7vzTRF3g?7nT@6`|3Zn5N7tmewWn5ev_BT!c{>t{(uQ$3YHKtgH-Mtj3x9-4R4$+?SAd_j= zX0N#{+n301T0MK6WhQr0f`fut|N7r%?{qo5WOwYJ9rNSWQt1W7%WnM0dtl5GpRr24 z{q43ovfLwG$wvlLOee+iZDU_A+0gGkA<$dT z_ipQ>OI$%*;mWQVQP}O+>GHfT zB6`J+Ug4L^a}K+|-7GaXXi|nvRg8VtEg%GW32}?dM%$(`j9?+%LJAMUf-D k_fwPSh3LN<&+<37T(MJV{qAL}J?F0$7pL#5#vg)n0F*6I0{{R3 literal 0 HcmV?d00001 diff --git a/certificates/roots/Class1_PCA_G2_v2.509 b/certificates/roots/Class1_PCA_G2_v2.509 new file mode 100644 index 0000000000000000000000000000000000000000..b6380726386cce73ea1688c0a66ec5b12ee13d66 GIT binary patch literal 774 zcmXqLVrDXEV#;O`@Hzf!)eO7B%aa9u*jjZ?oMgbu#;Mij(e|B}k&%^^!JzS=A-4f1 z8*?ZNn=n&ou%WntD2T%)%omnglo_0vo~NVWnU}0*Xk%anlHe9LcFsvGE>lv@)=O=r+_y)>JUG zw6st_H6N(VEx$-15u&XsHASJcI8`A(FQ?K_-ar~Eu)5o9~FY_ar`=r@Y0ns(JJbK|(??oS6Atb?vP|^+3D?)lV*BRUeMnI$TY7f2RQ|Rb z)q#n5%j(-tJlg)$3^8_c=|q_(>GU~ z)h&HqCpyo%=yl!e7+ucxYuUL8HBZ+aouJGU<8@*E#@Nrtw{hKmAUc`%F7uw_WnEkE z`X8PxT)Kntz_XLl*-LkH-dVHcZqZx6h2Q=6uw8z2BBiAI&{W4csl^c=C(N?R+BoCn Yk@h|3U2|O@WZ0>naHeDa!YVh;9nl3jUF!{a**LY@JlekVGBUEVG8i--G~_nm zWMd9xVH0Kw4K@@v5Cw6#g!#f!i!y^V)AMu`JoA$E3~daoKoZ=-#?Cp3#l;Fn3IU}_ zIhn}{0Y#a)iA9wP&Z$KunQ58Hi6xo&c?yoDB^mienI)A9x(e<_hE@g^5Z#6v$(jm= zmX;O@sOAHex#brrBto=RrKTv97N;uY=jBuy${WZ+^oqf>D1;Q17MCdarIwWE7iAmB ziSt@o7?>Jb7=S^PIIod~frWvgk+G?zsb$o#@MGhA#w-UM4c2h_|Kd3RhKXKTzxqcGa~~dvh#omiy7#yBE6sW7e5yMJ~Hpy z(YU}ahZ#FEe$19>zVT@8-v4hGK1+M0&-vxl^;b)^r+!mOX!CW^YhHRpcfsX#6`A=( zw{q5Td`O;T{%rRV1M#)xXFN?;oxjn4ao=`{Y3{{YAxb7Gy4%ENM@DZ6jI`R!E%HU^ Ye)@thYmHLkHo6t5_Xt%Vb=k5G0N@}G%m4rY literal 0 HcmV?d00001 diff --git a/certificates/roots/Class3_PCA_G2_v2.509 b/certificates/roots/Class3_PCA_G2_v2.509 new file mode 100644 index 0000000000000000000000000000000000000000..642b24a6ea071acc21607ae6211338962062ccfb GIT binary patch literal 774 zcmXqLVrDXEV#;O`sJ;1*{rn2K?E;nQzn6EK95di$xRnxarzoT`wYms4pdZy*cND+be|5K>fHT%zEYT2h{0lx-j< z&TDC5U}|V#00vRwyhauV76yh!#-^60mQlmPkB#$@V~&xPfw{347<-*ejg1Uv;w}ot z#$;YteR*e=&rJEq83uh~tqN|r?)Fz&6bDMk@49(;j>dR6MxK>mFe`4NoQhaWMD*g9x!1s1Kkzqdv;&U=^2u9L^m;7 zR_OWirxz5=JSGq|Wl6AaNUrvJ-dKn3l*`xO-3v>c6u<0&m*J8)R@J%8;|tTpRn=A`$9B8M&46fU30ng67aZS$_kaJ5Q? VZ$Ee!85?L^SrxHh?%d3Ye*uNI2VwvK literal 0 HcmV?d00001 diff --git a/certificates/roots/Class4_PCA_G2_v2.509 b/certificates/roots/Class4_PCA_G2_v2.509 new file mode 100644 index 0000000000000000000000000000000000000000..3cc5ab6770e6df8d0ca165d8e0e3baf94500e43b GIT binary patch literal 774 zcmXqLVrDXEV#;O`FzV==b?NJCVfP>PM-)a=jkYT<|XSH+89`YB)El*opTb4ixo^10!ou| zGLsboiZXK(iz*eIQ;SM6(=wA2OEUBG6dX%SGV+TuODYv~72J&stqd$6x(zjwH5Cjk zEiDvK%?B!T%P&$$glMZuO;IQZAHEh*10$~KS_ z=e4vjFg3I=0D~xTULy+w3j;$VV^d30%cx=D$Hw`{F~`Wtz}(mijJ-~##zux+AD*25 zd1PH{$WHd~pZ!PcGX#Ge5#Qi)=dnTYRjnkg9T(2Xyw!-V+naS~^F)BoV zh#5{{onDr=Xzkua@f<&cwhw{kS^>vbBsJcN_F8pt!Ir$&`cK1;Zq#-txE%~Iur3?hE?0;HjB>;n(|D{j0}v(&I2YaW}v%TdxQ=y-x(lUb=q#t z4(F~rtL}>I>TIlIv{5cp?9gwzll+Uxb&YG}b*%`O=!f VJeU^HSmg6oDaGIaRKvt=ngACd4a)!k literal 0 HcmV?d00001 diff --git a/certificates/roots/ComSign-CA.der b/certificates/roots/ComSign-CA.der new file mode 100644 index 0000000000000000000000000000000000000000..2b4585401fadfe3fea7a4aa5a16185a8e8bd4951 GIT binary patch literal 919 zcmXqLVxDZ!#8kb2nTe5!NkBw+TC+%K&#UU>r+-Y^%Uuk3**LY@JlekVGBUEVG8mW` z3L6NrF^94+3v)T==LTn{=P5Wl8VVTjfdsjP*`b1l+yLS#Ca9?;bMX2kew1tJfyx|}>XacixUTJU&Y*8cf6$MY8b>`uwCTH6{L z7_!tNbjRvumQVI6X5SC=Iy+~jUHmStb@jd3F9QLm>%nJ#{xUB1+5ECaq3fEXy6F>( zUsGo9sCrTC--m}=S#)g8L^LcyR z^S(;W3n_Cd++q`9uj`=d^sRBu$4-G0e5)$_EjYtB*c{;aW7_x8Be0jJuw+-uk?TdX zTWT!)QrOhB9xmVdhGXUyF5WAx#V3Rwn!f$WYA9PgljrrcQ+F>vYhCrB>v!qFPne5!g!Li`rTMz7FYlFt8Qm)SM2)mc}JLv>udAl56k?EEG6#O yl@uK>*0p?<@NBK%qOkVr!x^*w{pcxJaX;1Q%Myp4g@;_2`KB@9fZ9WqS9S zb@PFHYRg4l^52hrTfH-WQJY_|=+@75xn>6*-TnB+)Ff@?7Z$(p9WQk5BprVonznw9 z#__OAtx-Ndx|Iv=vHTNO=eu3c=Js=Q?MIIM743Gh)7C05-yD~^KI2g!-S8n%Mt{}(zork2H$Gl|M6z7=aDr<^6UV_F z-z4h3ge!&3dTD=TGm}h}=f5J>&%8TXxl`n&$!bk~z!>vPHOW&fLnT}e--%n~w}csIx6 zW0Fb$&+A+JcLlY4*~4CBb?^E1m_48Sq~4u*@psYuLp_h=V*9T1&5U)}eqsH}t))>` zs=L2Ua4y_*^Xv3ziyJ|2+_rbrv8&us*|xz`mx-B?fpKx;YlFrY2K>O(DJ#s#_@9N< zfEh>`G`4_5fv#>*O1} z9!YC5cdcWKw)?$GZDPPi19^~gWflnou?Fl4P%|_zKQJ;(4y_Eo_vN~@{OQj5@vr^A z?EG1Mqul%n&q4RcllCvU`(7#LRRf>N%YgF63GVZrUCO$A&3pMjbMe`cHy_?jT02v) z?omX+a!dBLFMDh~eS@>4wIvL!R3`l0c=_m@YZ(i&MXt}?Qtfk=-Q72uCp&_3-9u@{ zV;?mml%n^WaF;y)6n`!-nltHh@S>0dF;A;cUdzc*=vvy{m*K8?YTMENH~zCPv~*sp zpDwaJVDaa)2>zcN%r9Svi?BDHo36R8bq3c-C{m#Pjl(cQ;1Qp0MzpXUAXvGPRfI<~8ii%?JhAb&Eg+-S8m@X z!2UvYrhZ#g{n(__A-dc-rIz1*%c4U+?+!xFP{}>o!Y>-GeEh0^64LE!g}PMT|XmOr5|2x{MG5fjI{53 I$GPo;0Ca1U?*IS* literal 0 HcmV?d00001 diff --git a/certificates/roots/ComSign-Secured.der b/certificates/roots/ComSign-Secured.der new file mode 100644 index 0000000000000000000000000000000000000000..128f09462d40e727f91c2acae18711166a49bdc2 GIT binary patch literal 943 zcmXqLVqR^~#58#UGZP~dlOV%!4R_AXJ91omWPhoAHS>FEz{|#|)#lOmotKf3m6gH3 z#!%Wol8rf(g;`k0IX^czGd)isI5oMnC^bdF+0jtIfDa_eCCm<$G~_nm1c|T-GkN+L z$cghBm>3uvnHU-xn;RKKiSrs+8Wv{i`x^R`9Y@JVJ zY+kK-d`q#RSdr^}<%}G8j{ge-YCp}8J{gj4w^ZYeA`8FkZg$&+2YzYIko9Am{QGN% z_3HT3V*8(cp6Av6R`S)M`OZ&1HZH9f@VC3@m9#ck`gHSu_SB`5bkkNw?}+*$yG3!L zmw5F&qkmy4mYYIaoWHgly0OP`!kM|(GH$(W3Rr2Kaeiwo)070Ujm|fnWADbc=e^p! z`DFGt<|&*7_rwINv|p6Ks^!3wHQ!|5_KkroNC6*<7z=i3)T9TDOGXB< z^Y11J2du6ZnPORPlc@jms7^nT{Kw|rtzQq?BtH1d>bPlA{bAV!7uE%(BxFk* zQ=4<+YswQdsigT`{C59y{UpQu6ei}(H!-#{2@kN!Z;WF*_SLS&uTT42Dw|&HC9U9+ KxXXF!^ZEfMZ(M8u literal 0 HcmV?d00001 diff --git a/certificates/roots/Comodo_AAA_Certificate_Services.cer b/certificates/roots/Comodo_AAA_Certificate_Services.cer new file mode 100644 index 0000000000000000000000000000000000000000..5c715faed85eae3569262d7f3dd3fa93a62dff60 GIT binary patch literal 1078 zcmXqLVlgskVwPIK%*4pV#K>sC%f_kI=F#?@mywZ`mBFCeklTQhjX9KsO_<5u$xzxr z62#%)5ppj|O)N<*Qt(a8OU_6w1~Lr=4ER8j>^$tji8*QcMJa|-1`;3BO}8;hq+(!9=D%XaqM2>(L9Krh@_kR3etljY8_*?Y$UTeg!qEbyv!1#k$!E6ZWw>z%zdG%s za$rx9->Z+J>%N4{65={swaGZ)(XGzV&q@)W@7+27zPW8t&lLap8J}iMaBERNUbg@7 z8B?9^IQEp(rUM=uR!sbvIKNCGV8z7aXy`MkR z^P}$lH6^~%Gq$=PeX4o!=LCu4Npto!A6Kik>ry>_;O^XKrWpbXbNg@HyL7l^4sYBG z{gX`0j0}v68xI&X?lq7F#dY#EPc0sPf3X5{=a{Ob{zMQ z`qG)eTA#3;)$8-OkB9aj*;&%IO}94t%%#t6clD1w$U1!3gjuI{+TEx_e9O6J9%Sua z&7=Q0#_D{Ic_?T5yAv>AB-zo?y~ literal 0 HcmV?d00001 diff --git a/certificates/roots/Comodo_Secure_Certificate_Services.cer b/certificates/roots/Comodo_Secure_Certificate_Services.cer new file mode 100644 index 0000000000000000000000000000000000000000..e0512035607e5ea28abb6b4c97edba84d84f9e43 GIT binary patch literal 1091 zcmXqLVzD=9VpdsC%f_kI=F#?@mywZ`mBFCSklTQhjX9KsO_<5u$xzxr z62#%)5ppj|O)N<*Qt(a8OU_6w1~Lr=4ER8j>^$tji8*QcMJa|-1`;3Bg270+WPrSQSPVe>DimvKbEUZj92adR$}|4;m{8o z-p~6TUVT3ibg?M^{fX6%JM#3zwWenBoV_GBrCN82?5fi1n`fL}vnM6kVNd^>HD;${ z*6zOhV2b#gi!m4Wzh64_(9*Qkyz@;x7B~RK4Pu zxXo;pw$txdhZb8ty{%@kwwvpnWb$ztmHW&Ux1PN^=q|<0?Z$bR>Ce5>?eW(Qk~0>r zyJNI)*S>!)t24GO6&L-x_v-THv!1vZzwGGy^EUAHmA4^l1+;XMv#a+OO-)|f%O8*1?Fw086_nJR{HwMMLBxO z;1rge2x90%k`z*kf+Z+Dpi%>%)&-_*#u%FQ@={9(XhqE)z_?~)XlKk-maU5xuRWM( zbiV)j=dLM{X%FUUtcbh3{fo)7RhFBkiydvsH(K(t=lS}-?+?A$>Ah<4muI(nQx$*j zYIv=t(JJ-Nvgckj3(J;}pNrGyIsW1dI>YL*;-tMIi`+Sn>_4q94ppzO-+tytywzXR zW4!OD-|<;3_%Qpl;l-Ta9u2GS%rW1gDB{gqX#1wwIPYSfk=UCV$HlrMmzk_)4cDFg zeUsg=84iM+eu-mE@{%+fYZFhHSHdNO3FaEGZV~OaI)-UQ;viCoYd6LRh z7P95Bd78>)$;1;u0#CcmXYE}1Q+EHWnUfNy{bxM8FrIf$;U2y<+_LVjvIpPPy!opM E01?ipHvj+t literal 0 HcmV?d00001 diff --git a/certificates/roots/Comodo_Trusted_Certificate_Services.cer b/certificates/roots/Comodo_Trusted_Certificate_Services.cer new file mode 100644 index 0000000000000000000000000000000000000000..421c000db68e2e19c25970aaaf349a7017631b13 GIT binary patch literal 1095 zcmXqLVsSQTV%A>3%*4pV#K>sC%f_kI=F#?@mywZ`mBFCiklTQhjX9KsO_<5u$xzxr z62#%)5ppj|O)N<*Qt(a8OU_6w1~Lr=4ER8j>^$tji8*QcMJa|-1`;3Bg6f|e6xt) zs841g;SEPhI27JW)N9E;Go2-;x@OMPX>~?`mUwuo=}e?Z><>{nH7fX7eBsUzu#EbC(Gtd_u)yGg3DD(=CJ1#{MpMLUA8O!)Bo${ z-d+h6-#`31Rj}n%)53)-BuzjVOQSnIFtAF_amK%z4iXt+TRmYB2><)y*HU?b@g%M zg-st=n65`}x0|#kTd3>j6V?sZ6Fp-#y$*i$W4?RayZuuS9AKM&DLPJ2`pa<^Q_V}E zF;CvUW@2V!U|igI(xCB}fh;h_W%*ddSVWFiN9=ujOEvS-_eil7n~e@st4DtUCm&gU zM#ldvEWqT*X21_pE)3$c8ZZMXgT`i%h&)S;L6w2c0;>fUZDtuIB?VUc`pHE(ddc84 zmYfJ;=tC0~QksG#DLtTC1EAgoW^E=Iy7lr>O9<&j%_6|qW@I=qxzW0F%laKHLO#8h zKHM(Y72YOlBCu1xUT(vR&V+?shst>Zyk;|W-{}70_~=4&mzRtP+lIv%tObS!%Y$e0 zz4TfTk(ti7Ztl0GI*$8o*s`BQp2-#XI4xiP{udUeCG%bFPTcrq=H?P$-!y%qyvA(_ z!5*zAsm=!8Xq*--t>AP}cqpzy_JN=FmTOYEz9@r;Rc(3YjUv;f7$F!wF z#UFG}nX8uwsr#JXHvQ$zbsV`-mJWAW-Al8g6gMxHIPdpeFMRuqg18e$DmEkm0K_7h AD*ylh literal 0 HcmV?d00001 diff --git a/certificates/roots/D-TRUST_Root_Class_3_CA_2_2009.cer b/certificates/roots/D-TRUST_Root_Class_3_CA_2_2009.cer new file mode 100644 index 0000000000000000000000000000000000000000..1449f866336129f369b7dad1050d28facc41f037 GIT binary patch literal 1079 zcmXqLVlg&oVwPUO%*4pV#LU_J*?^agQ>)FR?K>|cBR4C9fv+LA0Vf-CC<~h~lZ&gN zsDUtu!^Oknq8n0FT3n*wo}1)hsBWMN5@zO+0}2O)28SpF<>!|uIOil57b_SmI6EpB zDHs_TSQ^NQ^BPzh8XA}ySQwj{T11KS8XtyH| z{>xjW-nyGcdA*%e%%XT<)m|RqtqiBsa*ky4Oo^I0EqzA2@D*wRE?#7bCr=pG;HoWkdHGfLxKgqi{ifbBAO}p3kcC!&{YKzIUXMe*5 zw#Jw3*WVz(dz6Wpk%4h>6QdL`M8pjEfpI7+%*gnkh1Gx=NEyh21o&9QSVaEb5;-#8 z;GW`MIVa0MtCN*IAAD>v-~&nXgVeJC(+`_L<7JS5JWJzggT@mEjSUOx7Syy=<)kDQ zSn2DhWEQ0+m*f{!>ZRzGfKrZLUTTTHv!5+A#i$w?fYJ<*0;d`vZ46>N0tq7!2Bsbz ze~@C3UZ4Od-RU^ny13dWrxulDre!84mZTP?mgNKK%>2BZ%;FLQ=LL=n?AvTJN=iU3 zC@(KZu{*gaM<42z_#&Xy@yVd%8gCq*oEUEu53*1Xs02Cv05b$I{V+1rPrq$&;{K93 zwTe{@1?NPBGCM@3Cb%%J+4R!De|Es3v>SE323rdZUp~q_{<+|`f@s?X-VgiMFqXEQ ztDEn;e|v)UoX@9ZAH`+dSUh+7Q-_30W{UqVY}p}xt7LKgmHQiJFs;eY⪙?DO#BN zPBrT3Go$C9?yvUz^?5?3@@q=W?IUYry9JM*yF;hsG zeQA?8+s)2)&(^j37I-D#N~Ff#=1*rds)O5dZ>V(?Tz@t3tliF22PWi29g8bTy&m&# G@go3thmqj` literal 0 HcmV?d00001 diff --git a/certificates/roots/D-TRUST_Root_Class_3_CA_2_EV_2009.cer b/certificates/roots/D-TRUST_Root_Class_3_CA_2_EV_2009.cer new file mode 100644 index 0000000000000000000000000000000000000000..c4347d3f5249399da3622cbe92e6efac8511c503 GIT binary patch literal 1095 zcmXqLVsSQTV%A>3%*4pV#LU_J#ekQMQ>)FR?K>|cBR4C9L4YB*0Vf-CC<~h~lZ&gN zsDUtu!^Oknq8n0FT3n*wo}1)hsAZr55@zO61PTX*28SpF<>!|uIOil57b_SmI6EpB zDY%9y7#SE?8pw(B8dw?{8kibbm>QUvMTzqoA#-V9V-uqivbPvn8JL?G`56qF7`d35 z7#SI6erz!**rmVSU_syB8kY0>lJ?B}+cf=B6<7K+3(ju>ep8i-XZGF_)qT$TN3vLH zd*2L(JvO#$7UulER;lW}_QRQ!TOD?qJNP*-o7^@2nso8uS;?30B>a6M);*HD#uF_X zb;D}M5s4JJ$Htqsc9#3`?7ulBTX=fD(BgkHSF)TDeUp%3_Lif1``7)G-=-Nh_Z%xU zY4;OkO^hnQ5K%DT2ganVFeBrC7FGjhAY~v665wMIV-dML zrOPKtSW8mx%=)6PTC?l3WbULJ@PVZHLF!q6sff*>@h(U}o~7}sLE|NZ#`Xn`EejeO z+v;;t5(}*K^;0s7Qj<&aiz@X}bW1=fNG~t7MBmxZ7MgNYjSN6(2S|Za50Ewnu^oYg z5fHnEff&Gaq~j0L0Wtt607`^9&bBVD_Q|P5C7EfN$%!SYMX6=^Ksqx&FDJ9O#K3KV z%L1o1hm4XEkTc55%TXMVT$G~^bx?c}(Ej*jP}+?*j!#aEH;PX!iwD`M2ULZel7JZm zn35P7Ox{*U*({mT@m@->lwE)GKbv22foiYYziHlk@bStq70#Cj&xcBHF}Qh7>K|L+ zGSMZv?>BkxSI|)PytvG)+~h^d{h*D4$BV1ZTFyJPwx>|>Q&jf)`!;@|>o>KeigfNQ zKdoiB@BHH2^Z6cAjNI~{7xpYz)*@-n{)yR@Q@gFS=6-x;IK%C{8_SB6yaTS3&Ir4| zUE;s9bHKVPm+B9df!CdFmtStY{Nbek&RfT(w_RvD{KP5u--bsietc@r9Zb}=a&%tj zNKUp;FO@TXmAB&V{F(kGzKxv?-gjqB*NoBM*XX#j=l`qP1h#o+uiIYMTP(U~#WS_1 S`G@c9U{-uJU+kk!$W{P-T}fq@Bx4S3l&wc0$|zVk9Nva&K5*c+-C zD6uhzvTzAYyJV(kmL%pV1ZSq_C6<&Hr7DCJl@^yMIOppbiW`W6R51(lxdewO1m))g zg&h?lObq12c?}E>K2#oFXLMibwfB>6?(QsX{RaK{mya&~u`sWx#_jvD z76GlL3@aY*`H?crr_n(xlMh(AnOAInM9+4_e-mJ z7KeR1%(K<#fks@iU+vz{$~Nq8IYl3@RP$IABK;-Yzko~XyJzbGxz}11E$X{pF1>Zd z^T?#j&l}g2OtIOXe^~Q}OIF=f9qGt+>E?-=UK33ug<^{&=3H!eyr+vPp(^gJr1JOT z8?Gis!EFz@&&y0c?Xz)Be(H@_^emG~@?DgR`FpiTKs@G3?>E9^qb6!Gw-NzQGG_{NGPCmO+ z(H^+W*XUi$2V297+j)*y++Ylik!H5&3%x zALGgsf7lPXUlsfFca_=HnSaYdrr+0Jx@S>>|2FQp{H0RcY?0`l6Zem;9K6umaG579`V%W-}4AvaY#L2%2TlIuq*VzMWgJp=$9pG2bo literal 0 HcmV?d00001 diff --git a/certificates/roots/Deutsche_Telekom_Root_CA_2.der b/certificates/roots/Deutsche_Telekom_Root_CA_2.der new file mode 100644 index 0000000000000000000000000000000000000000..d5e2a129285f690f656b395da034df3752b0b1a3 GIT binary patch literal 931 zcmXqLVxDi%#MHiknTe5!iBZjfmyJ`a&7D}zCyA-4f18*?ZNn=q4$tD%g6 z6o|tmEbNk6T2h>xk*W}qnvD1apmyO)Y`kfpAh2 zqY`q!FtRc*H!<=v7&I|*F*PwVGOXraZ2F*EQ)Ht^>v|i3Czko9v0m%$zDn$!>iH!< zWwBI3+LDzHN-a09EPYxrnJI6T6lvwq)t z7!kqf8DHdRBg)3u7rS=Vj>%ij&U?N5MV4-m$!)9mF{OdGZhtoX`L1w=(UA~Q7oMN9 zL*K5wFTt^3aa)(?yI|ISNuR6tA}VKJ%93$fee~+`^BMfpo;*yPQI>dOV$C%>hDQ?v z+8@s4dbW1@CD~(EwWs&oVm7(j7tQ!Ji+#J;wmh$TCT2zk#>Gws4&VeJ%f}+dB4T*B zQhL|d;OpWKI;(WWbGSBZ&owsS2S&fFFbjtP8zbX?CPr2RK9B%Eki)_POo433p$trZ zz))snn358?)-vU}=4;`9QHQ&Q!%wiNd?+bDknlMD_sh;@&HJY{)#P0{Z2Nv*L*8!9 zEif`<+Zy0IFvgw@oXPx6oW}%OiZghrjnc=Z2<<~VCvl}iIQBlfP z;nTlX8ThZ8pXKAN-M4`GvE74}S1wgw+PvaXkh}G~QJ>w`H%>9X;@ERd`I_AMuNl%V$%~?PEjNu^__Tm^HlK3%%qd*CyDXD6 S+9rLLXu0wG;(6AvlyCq5mtQCV literal 0 HcmV?d00001 diff --git a/certificates/roots/DigiCertAssuredIDRootCA.crt b/certificates/roots/DigiCertAssuredIDRootCA.crt new file mode 100644 index 0000000000000000000000000000000000000000..391ffc14d3d58e371d34cb61b6f6d7e875022792 GIT binary patch literal 955 zcmXqLV%~1h#58{aGZP~dlK{{22T#Rsxc%#Yn(#;ZgMp<1FB_*;n@8JsUPeY%RtAGq zLv903Hs(+kHesgFU_(&@VGxH)n8zhEJ<~b0s6@dtFWFGiKpZ5@Ei6!8Uapq{lu8Cl z=_Tjq8mbs5fuxv)rQtdpi;GK(Qd1N>T@-@y^Gg(*9S!8fc@4}A4Gj$-AWEFq7|4Tj z>E($l>kpv3$06|T!a+IaJyM9L+h==h%z5~h3H&n`6knO%QngN5Be>BBw7H*e@m z{L|pyyuA6^;XIcEiKf%U{zcB|F3Y|CagjH#_J8i8Tk{ew^i425RuS5+u<-oTT&@$I zHHI^cbCh1TUoeVVv`e^2@U5lz+?iHI3!nX3a`URVVd=WoTBUXNjBah;G%8PQy!9kp z{79V)--a!dmW6HJyJ`B{Rm(qYKf1zxs@R493#Yy2h?gk$XJTe#U|gJRkZ8aMj8s{E zM#ldvEWm`+X21{P3xoKq2FyUpKo%sx$0Eie;`(~g`Y)4CHyP>%b}wJ9IQMhz34Q~4 zkhC(3gn?KCb_J;E5Eu=N42$^o+<)};!{egjs+1}FzZa$5FnZ!tnzXL{^{1;h?}cri zf99Ns#!lYp2{A%G5l=4LHha28OgGJxTH*dG>{#V$p&RLqE%)m=ZKgcip{Ap-*LJf; z=lA&kN{^!6kyGbAS1*C7!+57pUd^V36yI8$>&C2N9s*gf$ z3C-8lS@wCKo4)UGx>knZ{f6f}#%cS7c}4O**UKjh$o=Y-R?W@nU%EY!apR@MY6}Gl f=dOKp_~+r7f!np&InL=l3)r;$7niI4q7R<{?GSav literal 0 HcmV?d00001 diff --git a/certificates/roots/DigiCertAssuredIDRootG2.der b/certificates/roots/DigiCertAssuredIDRootG2.der new file mode 100644 index 0000000000000000000000000000000000000000..40db2f333a839819fc315dc43e7fb5c5fe6a9b80 GIT binary patch literal 922 zcmXqLVxDHu#8kI{nTe5!Nq~E@jMX*E^jGQ1`wy?5^~KwOmyJ`a&7{?6BzdL_zL`E-}+o8Pbt(e zb^6}R;+N!-KHq+o6VPMd!ZYps_S4J{PUS8X@saMl`<7utP|f;@IU6m6FTNDwIKZ$$ zMqBV!d4bvNb>}ME?=%%W<18r%&0N1YWB&fT+bTDInp>b5`epV1sfnLYI^@e<+&6jm zz~H^#qVy;T+e*DKVkc)Neegb?d+5{ID2@RUXt-TF{W~t zsOODbHp^Y~DtFkk?1@>>{!n^-VBgs{I=_DW%l%+gv#R?^`c%VSCT2zk#>Gws4hHsJIWzRrj@t?QSJv$f+dAEB z`8DKF1|~CLC^IsgS{mB(_=IC#ruyjB&78JqQl_3o&g@#2E1gR> z8k%>VR6Mgf=WMsktZVx{E*YgA>^ksS-|GE=$5$q{T?}~4e7m?j-^()i?LD>QTWi;A zJ6$YIdhDgmbUeWOLFS`rIeac@0xtb)SzrICT(eC2g}KSx;FF1~76q;MDiCWsWOZVr zaDmy4^Y6ZJnOu$b`O7|M(XN|}MKPa!58mb5D8qXsdEeSEBELJ|EOO-YIddZ1;X)qs zs literal 0 HcmV?d00001 diff --git a/certificates/roots/DigiCertAssuredIDRootG3.der b/certificates/roots/DigiCertAssuredIDRootG3.der new file mode 100644 index 0000000000000000000000000000000000000000..e18997f41000c0924f0a23a6897a1ed087852e7e GIT binary patch literal 586 zcmXqLVsbNRVm!NmnTe5!Nq~D{)Gyil3$}W?tUs%=Am@z%7aNCGo5wj@7G`FHR6}k9 zPB!LH7B*p~&|pJR17Q${OPI$cGdH(7#CZ*k4J-@{4UG(dAWEFq7{oD! za_QxaG6MlNcCg=>7};308(A2Xn3EV-B%kkD<;^g-@O~dSGwr3ihg>}{a>JD z{???R__R9tr+1`XE4j}c3+9^J8_RTaW#m1ksBcrX_MkVKPu%(&);RE#zHV;(tQ< zalxn3qI)%+AI?uKN}LxbFex%@XY+A^=N2y`)XZwHJ~3&tWHP8R3;tm6G%49?=A&(k qt!JD3lDj1^sW5J$@bbG$@+O@zy7pBu?YRD{X~|isu9K!RZUF#IYGZP~dlK_YHgRlusZW|YtW}S?jc-+f?myJ`a&7D}zCz zA-4f18*?ZNn=n&ou%W1dFo?q?%;S=op6Q%gRHERSmux6$APy4d78WQkFV{-}N+koO z^pf*)4HXRJKvK-Y;&2`AIr&M6ISN7f`6UX@js|k#yar~5hK2?Z5GBrQ4CKMN^l(BG zqY|>m8Ce;an;7{S44N3Zn3@dd`IJs!)JE3#aq8T|A z&M;11?q{$)_`CCwOos5ek9w8vwzD}fG;*FhC*8dN{#olnw@25~jV;t*_#-WJ|60ik06Z{$usNcN*7A>Z>YdMz&_;#V8wj@Ao_KA}aTB!TxfA z{eKw0wccFeA`oG;vQ*;g#YOwvAE{@3nPvRLlOv(~O8ge9mi-G?dHK}Zo%fH=DT`a+ zZ9Z|{9i?Zv=R~CXvQGayyICYf{CKqHJfr=e-u=4F?Q~`Jc1NRIJXhZTXuP_+H^P3a z^b1doMFqDES?+${B=*UN%a47$hjQ?3! zfC;G0fFHyc2Ju-9n1PgmEJ%QlMT|v+`Cfo&*hQb+X&)9pl9oO^eUt6QPy>08v@(l? zfmj1}1*qu{7!8aJr{|cj@(>o{`gPZ3j(^aGFZb86e66hHSga!P$6LGQfbPz#$Nzmf zC?9cpNA8@elIJrtR|{@^T(Dr_S)Y!XlY1r>JX*~!vv2as|H)UMuqRwzynk*q=f|sk zkAuJTCI7NtetS#W{iL*O7xNr@Kk06LRqi!^Zp0()$O8__Z*?`AT67HFks3>ujWo?Cxj#WeU z^4IG{MPAb-4oIsket75QefOHJTU0n$4c_SP<=*eQKVav| c&#z}N3avfSacqW3d@q;Hv6ok;PR+ds0Q5RPs{Pom;myJ`a&7m8Ce;an;7{S44N3Zn3@aHzbQTHIERDpF(!1g)GQaJ{9Zplk- zye@a|@AU_#r!O{6V{hxNd-12ggQTEo);V)vP&-Tc!p2{-S^Rub$w8x&gcgr9D_VnJeCX{_;|J2P} zlz02&x_&wBDQX2hucLu6-|8C^Skma^IW)V_ne~}jhi)FnV1keK@Hao#ijU%z$=y=4>cw?qzQ zVDbWnG9yDmy2g}zK9A(rhIe13OI+=&wK>}DRsV9|ZEf-U8{&)0wTy%<8`GUyls~zq zo4)DT|D%6HB9Fdi`2qHg8zibR_3{p5LfoBYYm zyzW}IGxc}J?B04s;o;2qU^mg*8M8lpHn?hM_^7vK-s7%Yx2D;d3NMZS@UtMGz}-N8^%tYFG2u-sL@JUi+4LlJwK^__B94 Uy+>lhq8Hsv%iC;f{?uq20B`eLrT_o{ literal 0 HcmV?d00001 diff --git a/certificates/roots/DigiCertGlobalRootG3.der b/certificates/roots/DigiCertGlobalRootG3.der new file mode 100644 index 0000000000000000000000000000000000000000..6dda6a38dc3d4d361acd02e4b52d4759d26ca563 GIT binary patch literal 579 zcmXqLVzM`AVm!KlnTe5!Nq{vpY|p2-C8nl_m+)U*?OJ5O#m1r4=5fxJg_+qP(U9AK zlZ`o)g-w_#G}utoKp4c~66SHqOwV*qEh~a|;WUmzV3M0HuD260TGTzWX6 z%s_yR9qeZ&MmARMMivGo<|GD|yUTCx?%Kiqo4a1|(uaNfia#62O6@Uub??~hJr|~a z`*7w0_pZd~K)1Siy7S-lCG&{CVK4Z4zD3WWdCm)a$6V{RmzRh{npMnYc77)yoKtjf zUB~i;*;}2@rQcEh&n&a}k=^gdpVegNSN3)(r*KAf72LSq%!wCQY literal 0 HcmV?d00001 diff --git a/certificates/roots/DigiCertHighAssuranceEVRootCA.crt b/certificates/roots/DigiCertHighAssuranceEVRootCA.crt new file mode 100644 index 0000000000000000000000000000000000000000..dae0196507d9166bbf9de6ed93ed5bd91d2a6f7c GIT binary patch literal 969 zcmXqLVm@ln#I$w+GZP~dlK|727_}^JhuQtym7mtRsg@h?vTHrk&& ztLnL}Q0ws3DJJQQxMViOXD)Ntcx3yg{tGjftaOaDx_oEKHJjTd7E8R&_^LL2_gWe( zWby8^XKvxdy5w!Em&G4m((=PUDRAG9qi=3oOnS`rlw%^#5e>)C->0KGMe7P*nC|y2 z;KS3U1MC5c*hY*|CU8utq&? zd&l;QPp7z6SghtsIkZ15c52JPg{pGxu~Grt3PNWbcjs{jTI}#X&BV;ez_>WsAklyi z7{#*ujEw(TSb)i@&43@o7Y6ZJ4VZzHfh)yU1V#fRgNzj0^gGw*%(v-CW8(-{yshZ|Lo0pNehH&82Z8W| zU7xFN3a0j%{+jp4b?dyFK8D^qCcbdi>Dyd!?)Ky0%ED_;6{j%X3T>aIlJc!9?aaM7 z=4V%!Y|Nakd}3aOl6Haf<4||QM9KFNM_cv%48AQe6jMI&{86fy@#+0i(hF>VoQmr< z>`vh5)a7A|3EF<-C)bRNqVe;E_SKjrTkLgNQvXCvo9oE*Ox~A0j}8cg?>JE=G%@s( zN9K(^T1?UWE>{!`Z-3cUpcXqJVcs5ZaZdd$r{$b8PO_^XycF~OmEz6}p*c2l_Rss% i5HmaZ>>Kx0s_N+r%s(?U)rMSO`QxRY@Z$0p@?HQubYDLJ literal 0 HcmV?d00001 diff --git a/certificates/roots/DigiCertTrustedRootG4.der b/certificates/roots/DigiCertTrustedRootG4.der new file mode 100644 index 0000000000000000000000000000000000000000..99bcc84b7e68b5b28e4444f6fa21bc7c2baf497d GIT binary patch literal 1428 zcmXqLVx3^n#9Xm}nTe5!Nq}{>bojhJMWaWS?0c7&m&O?IvTn?JkswJuAWqo zP1e*s_a@Ho#N;1}iL*^!vmT3k6D_sp^~v*R*O)lOZ>&mtSAN1{MOt|H{E&z~9_{V^ z%MEUZy*pJM`*`h1|G1~7&kaxCnjCkhufO5ewuv(wCR84-IKFM;k*!%07R&;@H?Ej3 z(PORc_}XMAFtK2DXp^JS_1i4PT6q&0YZQI1>{%zxTpC-EcGJqxWtOqSeva!=o=Xlr zTe%?p?h^Gq3;iv(3Py;3SBY`!Px*c@v!iTAnQdgOQ(1fG^vo)c4-XazNvF*!Id#ul z?m1ubx@TA3Pnu*k&-M<(6Ia#FZL?e?wd)Q{*>Wi{_qFlOqxZd87|ztnOg-HHU2)SU z!R@>2KV9u9&~Z#ywJ}-3WvWzJQr)+P4ZmNcEHl2?$^LNf_GivZBz7z-XMD&%g-20# zQ;4Q&XUw*5U*l71pZrEK z{)j?gcK*iIZQcHduDQm~Rrs?|?&yL3MH}n5)MkEtlBqvKR`=`8m78RrN;5GtGB7T7 zGH@{92PS7(VMfOPEUX61K+1p*B)|_6U;*Z-HUn7@pN~b1MdZ!($4!?CV^e(Y>!sU2 z-!)^M48K2eDg$OPU@Bu|*qwN@c4f{!@gozZ4=-HA(EB(ggFozi`MQFie`k5k+~v@ z;|G_o$XKF&XYNn+bq1|Fzoq+H+4VTN((ZIU8a!-?Xwiwjs2;$JM? zvV8rD@42RPYNEQXEwY&TxuW}v?-ZoX1m*e!D1M{-ku zW1+3RZ-H_fkJp{XOJ|IxwD59pPM7gN@Ge`S#Ng5cOA~=sMNvkM7okS?3O#RXhzIyS z+vj_+bj^iRza4itFI{!{FsqBdj@j%-zaF{nP!7&v%TEujciZY?pQjO3sdj0}ilph6 zfR&$*WHWvetKHnrfA0t)=$1ze_=^}`TkG{L*Rlgt&`^}&Rl)f&LXk-+o%1iN!lfsC)s~w6 z?Tp>inj~vqxWQ7QGU@KxG3!Bhh+^5 ouE}lQ!_OaFs=4ZwaQTyaJ&lTM*#+DM*S6cTUo72o{&QL#0GZBIfB*mh literal 0 HcmV?d00001 diff --git a/certificates/roots/DoDCLASS3RootCA.cer b/certificates/roots/DoDCLASS3RootCA.cer new file mode 100644 index 0000000000000000000000000000000000000000..f2b0490eda2463e73e056aa4db4fc0eb1dd7a206 GIT binary patch literal 619 zcmXqLVoEn?V!W_`nTe5!iIK&CmyJ`a&7D}zCzA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_HPULE;5?dm73ZNP*;-g@u7~3eG-` z!NCf~3PJh#B?``t26E!O1_lPEhL(oLhQ8+UZLM!n~IIsJ;JRSYI z8R=&jI96|)CT4o5b>h?L1zg9|f|5QbmQEF4w?`{XbLj)^U?yfp2FAtu2D%2az(ADc zV-aH!$(ghCLrj0JWA71h>j~k9_!pne{b#@fk``uRHDG3B{EzG(U_3GdJ+i*g<>z$e zGZ~pZ&g_o6Iutf5F*u%>u^?3DtbN|b$uVnxNzB?UQ=I=-#i_r2e&G3iZS!AV@AB~H zxS2U+jr}uz-Rb-qlgs>*?*CtKHu1-@HXcJ0g*)~7D}GzUXadGvz%}ryj4~Ut#pT3IH6e%W41s literal 0 HcmV?d00001 diff --git a/certificates/roots/DoDRootCA2.der b/certificates/roots/DoDRootCA2.der new file mode 100644 index 0000000000000000000000000000000000000000..30dcdb99970446186087ecc550638784b0db6687 GIT binary patch literal 884 zcmXqLVlFUfVv1P6%*4pV#K>yE%f_kI=F#?@mywZ`mBAp|klTQhjX9KsO_(V(*igbi z48-9Q<`2~i)>ClLFH0@T%T3KIG2}7e0?BX-GrQ!wAn^jcJq^VSL_l)P!n{B^g`oWW z5(Q^R1tSAFab5!xLnA|DLsJ6-LxU)BUL#9GBLhZl`k>P;O!Ee3RYyR8YTr1qSqeO}QO@X86pVbbJ*;gGrd}IEetgEw zQ?XBE%h}T+b{1!g4BxF5`jq<0L@zA%|GVVU)497Qn*5pf`HQa1zJMc6_ai(0XKntq zBFFZ0SYaXSwB7R?o;J8fraNwUeRyrcl7>8XerR z&v8l0)lK!cuh_Z)R3-D5ljQg)WCYryudB?_Q zJr?oJ{{yaCFN)3HByc8~iJ6gsak0IDt${2s@?`l~#8^Z;OLp_b?W+366!N}$!Lg~w zI2#J48E}K7`B_+iDX7hWAH)%6Wc<&qi)+!{Xg2M+%TxSb>oJ-x** z1wYRCWGI*KaOFqE{Jx0`@(Wldq^)ApKKHO{($?CC4=zr7zR*hd%*MI$tS)ccXI}P| zDzH4r!t=E5=EwEd75F|XRjDp1o_WT83A_5V6^o|6ZQ3bzc^-HBp@W|~z9!wzxPN?4 zX5ib6F?T{jH2FC#XRTpAc$>#}T|QTpnCHj+6E9gzx%_Ra&i0&>PTP7|Dv BM{588 literal 0 HcmV?d00001 diff --git a/certificates/roots/E-Tugra.der b/certificates/roots/E-Tugra.der new file mode 100644 index 0000000000000000000000000000000000000000..ed68c11b82371f71b634b4f51834fc3cb10d6741 GIT binary patch literal 1615 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 literal 0 HcmV?d00001 diff --git a/certificates/roots/ECARootCA.der b/certificates/roots/ECARootCA.der new file mode 100644 index 0000000000000000000000000000000000000000..8d6942294e26248b5ec005d05fc188c54a9f5efa GIT binary patch literal 668 zcmXqLVwz#l#KgFOnTe5!iILBMmyJ`a&7D}#ZzA-4f18*?ZNn=n&ou%U#3 z7>L6q%pa;3tf%0fUzS>wmz$bbV#s5_1(M+wW_ERUG!!uq0`ZuIxq&=|p#1z21!qSC zIdNVC69Y3t6GHW4A$Lhk-mWpk$RH4yQozR|#)4g%41?K;f5&u-GM*jBUNnM2=VSC5P14lV7Bk6$+_i`u9%EfSu5{TNeTTB*H- Jf{)gf8~}K=$RGd! literal 0 HcmV?d00001 diff --git a/certificates/roots/EchoworxRootCA2.cer b/certificates/roots/EchoworxRootCA2.cer new file mode 100644 index 0000000000000000000000000000000000000000..0e2f06982bc630a6abcf26b90e754452df6fdd24 GIT binary patch literal 1259 zcmXqLVtH=R#C(1MGZP~d6C;BGFB_*;n@8JsUPeY%RtAH{UPEpJPB!LH7B*ofXGcQ; z13nOkLzvw^uOzW3Gan|xF3cX1UzDF$l5Z$$APrK(B`o5aoRMFiUsR#soL^LsUzAvq znV)AUZy*bj<`x!nPAw|QOv_9Liz@`D7L{ctrxqJZ8AyN>FbfO9^#|qWmnb+p8X3rm z^BR~M8W@-v8kkrb8b^uq8XEw)=1}gSb8i!)0&1j&Rqr-=?JU6)Ivst_xLG3p^B8S^9pbU5%*e_~Zq~fB zT#V^v{Ji%4U0sYk=e!jpo6KcTO%7(A_iWeStv3wJ?B1EKt=eF;({XLYeoYI-+DlJO zrFW@q*m?Tkt#vyuiYm2UwTM1%Uv|yuuv^2TAE7xxO15!baQYLoo?*)3l}kQaEjXfZ{z(M?g2E)5?em|VIiIq@lQ*kcVo%GJ zpGzG2rgbwhGB0jo3;>3Qj{!e0)@6km8UM4e8ZZMX18$H2KMM;mZL)zAjVvFF7>kJY z!$#=^tL?27o31_*TDLA>wa8LogT`GT#mX#=n+zJ)H(*t>uyOK|#tDNhi8KK-T>!}K z3M`%m?gp-G+}do6EQ~(|xfq!l4a^Ko*f@X!tgP%zjA9xYB_#z``ugSN<$9^myrq|% zpR1pos9yxkB1Zbj1;u&=DQU=Q4w#LBX^xR0fBBjp`!7nx3tK(DoUltJ`AXJ4^*kfR z!oJ=&roB}QGJ;+@dNlsGZS0lpss0yvvhv5GBOhDdnphtB!7^R!Z_aw-1q_ z51-p|YMCo+4f`1!7d2>1bDI2no5z-krMCO3oF<(9lE3vu+_6cSr=~DT_?HNK*R)DD zESxi4_V?<-fFEAnw}mWTHYhG?pXd13^UOcybfNAB^Mh{Up{w&kF1~c#yYv+M@w?hh p@s~wDdfmHkkm~8{&9K{NMIYzPBWg~Qw9fRrx6U|z>b<|yDgdmLvlIXT literal 0 HcmV?d00001 diff --git a/certificates/roots/EntrustEVRoot.crt b/certificates/roots/EntrustEVRoot.crt new file mode 100644 index 0000000000000000000000000000000000000000..6590868cc391ba2bbd4c2757dc4e55617c91512e GIT binary patch literal 1173 zcmXqLVwq^r#9X<6nTe5!iN!TLAjE)|jZ>@5qwPB{BO@y-gF)j4Lv903Hs(+kHesgF zU_&tj5fFzJSuFfdaE0)SOqGs z5R{)^qTrlbRFavNnVeXXnV+ZNSXz>iUzAx=X&@)gYhY$*Xk>0=U}S7!6eZ4U1m&87 zxI@uPO^iy&5yQyJz}&>h&tTBR$i>ve$jGp5>NaPmU&nH_@;&ZP@v#hNeRsH0&@sd8 z?VEqI82cAmX#Dvu;FhN6D<`#4%J10415-OTocwRtZOnXodvmp&LQCA+O<@|#e>~Xf zP-uSiv^(E)t&9UoQ}p|nW58uAarXCLt;ku* zQ^j>$=gH?eSLX7>%=qWA{HU^fOx)kR=W<)VWw>5!YmQ#j)w}VrX2U<#!j853_Vlj_ zn&!PKu=k0uq2voc-}$%KY|gs6$1{|guAt}4L2KiN2(nX{P%3~qwft*Qh%G6 z^Jz8|_^!8T)0bMfDf2f zWce8x|Ff_FlQo+GKZq|3;U_U3}qt}Gvm7z-|GaCZ7u%kId)B4EHL%@JmJBsf-MhuNZ8&&a9wy;b-!Ti9DoEVVvC0^vwnXiiG^qMy$gTZzr>@VQbz|Pkk58O?9|^ix?O(sQ*{L|F zd)4mcn&-c!$Z+{y+_P%Ue60)r>+5gTzS{WKK=okDEt5;p70qF9=9nE;dnEWR-BWhb z>Ym@P|5v?h^;#a#@L_q3*A%^Y)|oazjt|amNj}f$ylYPLo&E&t&rw^pRIj_mJ;9>% eeWPsJrSIVdW}El_(O6%o+8QnVPp&>{iwyviEV63= literal 0 HcmV?d00001 diff --git a/certificates/roots/EntrustRoot-EC1.der b/certificates/roots/EntrustRoot-EC1.der new file mode 100644 index 0000000000000000000000000000000000000000..ae9933cab4f4f764f56a9dcd4715a0ddace1f809 GIT binary patch literal 765 zcmXqLV)|*&#MH2WnTe5!iI-tnccmr+5CmM9_|t%kjYF%=B%S$cM z&q+;B%+W1LEy^u6v@|e>s5H<>)>JSuFf>v?F-k#KAuYd1A+fY1BfluKDm6u+v^Z5E zKQE`!(AdBbq?K7%3#vmQC_leM!8x_4Br`2DIk6-&KTp9CqOqhBXppP3p@Ez@ub~kT zS{RxdnHrl#iSrtpL%60O?lACSnSlTsJ2=Le7};308(A2Xn3EV-T7*wt*p=&8{V3(KZ#CMlIK(Vdy@k9QoZ{rHLL===rWqOW$dNw)b13*@q^s4rab2-lXGiAU91)*2g-kaoOETSJG*`+b>p!866T<;&DQ+%GugB6COSlitoHUFB}~aueS(ef_=l{+WM%|NpIg zww%czdgk?3bGEJ39DiS{cY96w`S92BJ~fUPHIp)Oi*Mwstx;s!F>||`W3+0*x(gms G@7MqXmHJZv literal 0 HcmV?d00001 diff --git a/certificates/roots/EntrustRoot-G2.der b/certificates/roots/EntrustRoot-G2.der new file mode 100644 index 0000000000000000000000000000000000000000..011ca95b3f2d50a21c5023263fea135139625a60 GIT binary patch literal 1090 zcmXqLVzD!5Vpdzg%*4pV#Nrj)qhY|y#;Mij(e|B}k&&B~!Ju)UA-4f18*?ZNn=n&o zu%VcN2#CWa%=8fYYIDi|3USSp|xrJ$>jmS3chSXz>iUzAyunxarzoT`wYms4p7 zR1DI}EUXFDp%9dxU!vfgT2zvmmYJMbl9`{U;0V!JQVBH3-N-;roYw$orGdGjxsj=< zNt8IRu>sH^AlDSc9r_+@VpKwoG)7hi<|amd27@L>E~X|%MuuH2+lp?_$B^Q8gf z^0HS(JEl5HoxGLk7g2Qn-?yg9{l$rFTuaq&Y>vO|>L*il&ClplQ5XOBX2}a#4Gj#g zavP36pS52oTwP{yhCWyO-mGlCxYW-w~sB)7Pcj%*l8Dd7lG5Qr@2M9^|MnF@NvH4q?EAk4$Ir3*BChi+bB&*oPg41-?Ju70HrXTD zy>3q6^X+w8gEty0J?{^s<9zX}@c&** z?E|0o`WN)9)PE&@gga#373pa+jBQq|O5MzIca3e%jokHDKbP^J zweGM`nwv9u))CwNP133M%lKng{du}c^wie1$M)D>XnFC9t!RU)`=(0A?|1XGb38Vg?IFcWiVscx hA1JU!G=%ZSAJ&bX3+qdoXL(+~<5%6~k>Bn54FJ1YmpA|b literal 0 HcmV?d00001 diff --git a/certificates/roots/Equifax_Secure_Certificate_Auth b/certificates/roots/Equifax_Secure_Certificate_Auth new file mode 100644 index 0000000000000000000000000000000000000000..c44db27440eea7a3bb31f074f7e78371561bc439 GIT binary patch literal 804 zcmXqLVpcF{V(MJL%*4pV#A15y%XtG{HcqWJkGAi;jEtyK7--W?Eu}p{{{8NQ7Hh1uCKtoSIx(l&avIT2zvmmYJMblB(cXT9T1p zlvz?~AScdiX<=YtWMpV&VrXg@CC+Pz%%!@0jq{Ox#K_9P+}O)t(Ade;*vN1&c4I_3 zN7B0mvvlP-awm#p%;1vycZ(%oxFt#P@Wq;Q^I0G4VEo``^5#+3RF;%AAG3qwSvQ|f zZ`kj|)c5Z$Bj=lk3?lx2et+P(>%1#k`=NY8!A#Nc$zmV*r)OvT#K>w;01QT1d6rCrbc56d z$qN#f#2ds?H}DO44Y)yZ#VpL?9OPqYAO*5ffJN9qu#w-$05u*!3T63OSb!;m%|IT+ zQD%`a5Ni9zim?Tynv|}XXQT;yqDaXH{;!k|4}C{hi*zM48M0k@wKhia%E3OmNuvA zKkw=ni3M#G59>|3#*q$nWUW&26x8^2fl-yEKukz*hW zQozR|#)4fMHNu&J{x^8U7`W>AtN2?xFQoDtT(i5yE8>|qak9FI;rk=sbzOhFIlh09 zBd_w7Nk1hS()Tj1Kl`BYPt^I8BM+v{xUksa5o6bTb@q>`j9o6eY^kL|2igP_6ytNU x`E%BB%B=siNW$bu>5^iZkG*%^ul>2XY|Etmccu!+?K^$KI;tf>GHlAqPyl$_>sSB) literal 0 HcmV?d00001 diff --git a/certificates/roots/Equifax_Secure_eBusiness_CA-1.cer b/certificates/roots/Equifax_Secure_eBusiness_CA-1.cer new file mode 100644 index 0000000000000000000000000000000000000000..79b0a3f98764a07fdf6cae1a80eebf704d1f8796 GIT binary patch literal 646 zcmXqLVrnvIVtl=TnTe5!iIK&CmyJ`a&7A-4f18*?ZNn=n&ou%V2B z6o|tmEbLlXnwgeZp%9#!Tw0W>;F*`KXQ*bN0+MAGmPM0Ibt)~+%u6jUR&aLIH8hYD z=e4vnFf%eVFfjmvC~;mR10*hOENz^R>^DYM2Ij_I27|^_GV!Yaq78vdHv|ahSG);D}~qW z>v(UKw>nj0}v6(+pA!1lc$f+B_KBemDWcpM{x;f!%-~7^bqq zjEw(TSPhtglz}`*K$%6tK&(N;tHLNq@OGq_S={}DB4!R*?lnFO4P-$I_*lePuuG#x zF*DHrrO_*9GYdX@8Rm2L=SrUgyt6)^NzHtwT6QLK`?Zk6vS(+mk-WR5_38uLKS>J9 zTf8GuKR)_7Rnh+ImAVKy_x2FGh=p6X{?K|~_0LPAt^CfP$#3^-zEgW8l3z5)^gfj7wSDkEI{sD4 z)9EklXV&v@aT+s71us{8XyJXWS$ggIltVvds(R8qeADD5xE|Tqzdr{Qn_$zxc zkLrms4bJ?wJ6P>5Zk~Gf#wq?o&gr+ePkx}(q_^*DhDP(wgVveV3b*{`@??b>8UM4e8ZZMX zpr9B?NP(q^kr&9}1Y%Y;E^RhO7RGb(jEsy1jo%C!FR*a{MOazcnV1Y356d+kUP{NSOkOsur42eKk0u;|@$ODpP3{Mzx7_xw3#XwPzOesSOP}~uyUl*vp z7{~^hgfO85Y$8Y`lOY$ZA{!`Q3^chEtU3{BULsIN7pTu0s2jWenLt}WuFD3RkOzdB zVA~<)r2<8Z4HV%%ViXh2C@Cqh($_C9FV_R-3jO4QVtoT`P`Jpms2BjV#R9nnGHp^A z>au`YKtH)CN8dmeq?nIIj75ZHRh9eVC!Oo1&T}~|m$1)&|FU+UfjmfBnFW{+8?Y+? zWhz;IP`t1JGx9U!6b;P6z!c5MP<>EhO7J4i&;QiYX9YYt%&M<#S~1b5W`&?&rH^Oi zniJn!Q)AqATMH~;T7TAm>lrhxH?jZTFPM08+vNP3hLAVMISP3DemA|*N~p**GrM?n zPIu;3hZ9p$%RhxHrdgkBb=YQ{EVaKjp zjj7AdobI}|KgGN6RM(~rFBOgEtyuM5KWL literal 0 HcmV?d00001 diff --git a/certificates/roots/FBCA-commonpolicy2.cer b/certificates/roots/FBCA-commonpolicy2.cer new file mode 100755 index 0000000000000000000000000000000000000000..8536f3516e962da10c1985b3040b89b10e65fca9 GIT binary patch literal 933 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 UoQ*rRqQcjj^RJh!zrA-p0Q?z-P5=M^ literal 0 HcmV?d00001 diff --git a/certificates/roots/GTEGB18.cer b/certificates/roots/GTEGB18.cer new file mode 100644 index 0000000000000000000000000000000000000000..e37fa29b1df9b2542fa399b40a0c7c8c03ae045b GIT binary patch literal 606 zcmXqLVu~_oVm!>m#JJRemyJ`a&7L6q z%nM2UCF>a~ z8z_PlG7C$gDRj@tPfE;D2+GedF_07IwX`s>Ff=wWFtRi-h!W>D1apmyO+nm&a#rJf zo>T+y?ADU|vC)9769?U*J_-Ag!luPS-b34)-p1s{P^?Z@xsiiVSyJDE0r#LC%u zk(~#OK4zf1a$iexzKpvWcspGwafz0VNBQFgHOuZ5FA`yHwf()C&){gYm~o>p$GmD2 zzxxg+O0Ms$z4N6kw03rKh{VeeuRh0YyxHv}xAVYMzg@qsKC1bek+{F_4eRvy=ndBw sx0)PLS?XQ!^+wfxM_)!bF}0FW`)4*&oF literal 0 HcmV?d00001 diff --git a/certificates/roots/GeoTrust Primary Certification Authority - G2.cer b/certificates/roots/GeoTrust Primary Certification Authority - G2.cer new file mode 100644 index 0000000000000000000000000000000000000000..75dfaf39fddbbd46f687e0324a3a5811372b0e3f GIT binary patch literal 690 zcmXqLVp?a=#ALdFnTe5!Nx){)7Y{CmNB>@{SjQ#U9nLo3V&l+i^EhYA!pv;YIKzRh;S%O`Pt6Z0DlINi@XSlrGqf}?2Z?hF8)zhJDi|3Um@A+t zP|#Iy%P&$$EG@~%FUqV+O;IQj)^y%uOt+RB%o$D#=XC zOinDx%+FJBglI0Q1RCaUWFRNbYhZ3@Xkcmp22tX?#uf&Kh89M~rk19bQG?m(Wd;Il z?BFnFVq|00Ze(FlVoqXU5#9LWFSDrg(>1T#%>|R*UurfBs&x(L_Uf$;v9`*K7iBsS zu1~eA{MUD#I~Un_ zdrXuKc%ydzT7uqQ#l=nr4hHFVBg36XaY+%f#^IJm#=l;lZtq!s#p^Cx$E%b+!x>90 zCdkb=ua~U-!EKMrrp|>2GkP6iGJ{J^9kE6m9FpM}+c z8AuuMfdu$L0xZB3%w`}9;`6bHv4|Y0Jk__*k6BjcPWElX=qYyg2KBngp$tsUz))sn z&^;=AKCGd-s$%c_bviSjzrS^VN*rhA^5=OOJ$sAxxv%7#F0{kzW6EXA`>G~a4xaUE z{J_t0L}jzdv}4Ow8QjlEEWZA;ueI|%U))p;FD>%wADMaQ>iG9Ibg*vyzw+v~V+ zio`+Hm_Hx>H8Zu>@baG5ES``<8yv| Nj$hFv^jcC-7XYbpb2$J2 literal 0 HcmV?d00001 diff --git a/certificates/roots/GeoTrust_Global_CA.cer b/certificates/roots/GeoTrust_Global_CA.cer new file mode 100644 index 0000000000000000000000000000000000000000..4ae42e81b7ab27da185c149c5cfa42e0c7d8ef11 GIT binary patch literal 856 zcmXqLVh%BAVzODl%*4pV#LQ$8X28qFsnzDu_MMlJk(HIfz{!x?fRl|ml!Z;0DKywn z%s>Rh;S%O`Pt6Z0DlINi@XSlrGn6)v1c@^X3&F+RbMliCa}=B%4dldm4U7y-jSLM; z41gd?oYx4MOBFks7?qHn&dAEZ+{DPwV9>ZE`H0 z6mGAWcxBJR8$Lf)IB#Qq>8r@j(Qzw6Kh08eFKb2jT#Fa1+q3ElmpnU?ux!Koh9{jG z{PR?=y>0%ycG<+^Gfp~5n2O9@JHu^~p8u(j?al|qriSYVyzkU)s0v^E>0NyGC5GOe zB0oe#O>Z7>TU=dqV&eXjq1tCJOt+h(mU8C)xn{}2Q-05`T&-Ryc{cRki8q(xEP|iL z`1k1k3s5%ullJU%-x5nnhV4_CEGKgF{j<=!D9bwQo3C9yKfCOD9l8Dl%SXS=f`u)w z#HnfDwp}5z*XXqbvqlh0;nUT|wht|KvzxUf&8d7PX7DBcfcA^R>?c2&m>C%u7Y7>z z8t?-nN>-SW@jnZz0W**?kOc|wv52vV9H^R+(cAfZHERlwVC|~f)E%eJ_!-E9q?K7D z48$6+D?m*#z+h)&Fnz3<^;ADLq)#(o%KVv9B2W4&w34PQQcs_E;k;Cw`^$rymYl!q zD8=eG+xwkYerV8Um4)V9uT#pj^mIP|wJx2o|5xFS$AFMY+fH zHOmzG^_HFFIkah}E5q?~f`Lj(50<{#ChEbN@+!{1h&tTBR$i>ve$jER;wQNEqTZNL?*8|PlT25)q z`^#D;cyw(?(H}P^=i{5Y=CZ`AoYwPxn9$_*FlaSTqkBQl-IR;3zv?XJZ?fglUN`;v zHjy@g%H7t&4dp!?4?QnsCF#q@{hF3>zf*mx#eBBwb|+7(Me-Kk+i>Eg8eg;MvG>v4 zmsk=`c`noVmTCR%^a+iLPv>?ehMTV`5xG?_`;jk@3_*EunPN{PO=3Mc%Jd@cgsZLDb_S zlVPG{+>Yt**OqTjnN_tv{-E&t*-5{7a~_0bimhb6mG`oFa$(uA%+@AxCT2zk#>Gws z4hDR{_><*lWc<&<0!$HX2K*qtFo@4;zzn1eWI+OaEMhDo{U5yRSLnH_tn&@{l{~Ba z-lMzHdyqpJm}r2Z%*f#FaQi^Os(&YV-hZDK;_A738Uv@}n$5y(Z5r&xr?Q`w?A*nm zyKV{B<*y$<@^|eoPWNg)?owUxV0~UrKC@<@v8C(bz9&1wb5{Kkn)W96nC=smoSjpW zf8PntNDs4X-f`Yk@$kuvf9Gx;3SM<)Lf6X=v2Hz6?^Z=gm=bbRTvM6jq*l?z>U;6vh=ZpX(UQTUo1KYI8Vet?pWMd9x zVH0L@ay67R5C?I%gazDl@{;D#ZXBDIdNV~3j<37Lqj72Aczv@HL@@;G_rtlX=ia0qY|mhT4XLYN9@iB*y;{bnfPJAYm%&-lUjH9=uk-|n%DfMFcSP^|pO-rV^4V-UGNZM8k1h|{k<)o*_D`ErPycp)6|$LBG40x&lDx?- zi5Gj1yKO4vYkMKtbu~BVYK7R;MK4cqS-k$FBJ5urGFiCQN_vl+$<}Vxo}K008*j@i zOkB+woHyZIwRy?T0{4kZfyrW(>o%@)RO2`yseRFHmB+Odt?SJu|8=wu=14kwv9~_I zT=Pvamo3g?nKC1yUkTQ@3 z3GlIqv4|v8r%Ac;PCwNdpkK>!)?~&1KYzWELm8NqfT7IDaIN@xjepsN-u-WOE!t;t zRKsX%&7Yh(I@)_V=LPT2j$0+@vF$0x;?1XQ6MZkcac;Idyx?(isPv~@@7G#Bblz#P z_?do}n)Uky0bxInas9P8dxX0naLV)|MR}r z*_rJ2ZPlOqdous(33;T7A|GKXaDFy3OTT)%0X$;N61lx5I1`pJY9Zx%Ta!?LEgc?CX+) z_6G-l(SCXS@3!wv@vWB}C2luvW|286zoa2wRN>@3o(?YAYiXg6{&<|!RLgt-09X)I A(*OVf literal 0 HcmV?d00001 diff --git a/certificates/roots/GlobalSignRoot-R4.cer b/certificates/roots/GlobalSignRoot-R4.cer new file mode 100644 index 0000000000000000000000000000000000000000..160d545fc28b8cebba1b65d475f09a4544933af4 GIT binary patch literal 485 zcmXqLVti=O#Mr)onTe5!Nl?pTiOe)EmU~W{G?sF|Fqy$*z{SR))#h=|mW7$gAiz+? zK#7exl!aSZ+C3*fDKRHFGd)ki)!A7gC_leM!P!wkS0Tv6P}o2aq>4+J3!w@o$c!v# zAScdiXk=(;XlwumQR2MD76yifmIlU#CI;qFG_Wz!K$wjk>?0;dsMnYo*_oXfSauw% zyxgCo$~RxnQc{L_$+}rjE!jE6P9<;L+4iF={9yPwr(eYjzo$C=mpjO?DX*CC|8d2q z5=&OyEVN&7W#_pb*~Lx<4hDQckIV8iGX7@)1{foo0Y8W@4C1pIFas$AS&#r9ix`VY z$cE~*t~(w%)c@wn`@PTjq|M@%tH{C4?7?8*%B09}XVSt2!pqJxZ+Lb@ar%T`BH_Bs zZ{FEl&O5atr)8?faItY{wRxPgWnpGE2ryJJ zP-0^aW#JZGeqAijbzXF! zJ=KIuzUuC48{>sX=lU+mcbsZbe^RdH^~HIfliH`W^H{ZdrOlrkIoWr5B3ql+VkZL! z13qA=$nrBX{%2tU1~;1lKZq|3;kJQGfj`#uh>s1x_GJG%e!}} z`NI52lP)}vaXlW%KME}v#q?GC%S;CWoE zA9wSd=rYX(oN9_$NlXTXm$vrDys~~+!P&Z^bdvRnn7Ur)s&z|Lp SnIFGfKh!$?Q~Pt;1akl<_O(j@ literal 0 HcmV?d00001 diff --git a/certificates/roots/GlobalSignRootCA-R2.cer b/certificates/roots/GlobalSignRootCA-R2.cer new file mode 100644 index 0000000000000000000000000000000000000000..4d937187ede7ff4298754f14e5399502f844f389 GIT binary patch literal 958 zcmXqLV%}xY#I$GuGZP~d6E_P35HRw$sXgO0;AP{~YV&CO&dbQi%F1BiW2j&t$HpAW z!YwTBo|B)Hm=m0to~IC$pI@Tj?5Lot5M*R1Y#<0y!6nRvPyrKUMiw-X6X!KBGc+zmHFpYDPz}E}G_kLH`6?d!&>ZtZw zcFJ>E+=}HrQG$D_nqKegdAWJbG*$NLUNg1W^|#2C@9*N@%2XpgZO74_RyupG3GI9x zS^MY$TU&gbXVzBBxDJyydn$N1X0+t2IP1M-K`l?E?}r__rxj0K&55pkxInXI;m^xc zJWs16O;p%(m;36?Ge2Lcb7>b(JT_N)&56@59xV8xKcUx3U|cJ ze=wOVaC%qNx%I2BeqY78Dq-)PoALLHRwf9?F)*I=`enc56+5#cQ(x05=0mglnV1xMeab8n24W4^4Mt6mzzAeynAsTIE|W36ZQ`2;UOQa4S2wOv_rG>< zhm3Q@W}aDpUg_B6B})5xYkr;2Dyw#I$IE7hB-d>#IVSI1Y3waA>(Gz(4!_%X3r(aB zhTL+qe{flAb#92#SF5D63i-Px$JdDU|DrA7C*cV9Tr zASvT|K)2_`58WjtVV*}>xB83T%X6u)Y+q5g`*Wql#NA)==N|mfW7-qT`1^3~&i5|4 zm2QT0T>n-!9sK`(b)LeJfRpiaeP@gJ@H}Naxxg{2IQZAnfGv5d{J(u9zWfck*_XNT rg&_aEjvK#aJ-@HIH}$+i#i0bD+o}#dS%2!BEF4mVzRzoXI9U$>x7>1) literal 0 HcmV?d00001 diff --git a/certificates/roots/GoDaddyRootCertificateAuthorityG2.der b/certificates/roots/GoDaddyRootCertificateAuthorityG2.der new file mode 100644 index 0000000000000000000000000000000000000000..3cdad66612f4e8cc4818c314745d0fd7e5429ef7 GIT binary patch literal 969 zcmXqLVm@ln#I$w+GZP~d6C;BGFB_*;n@8JsUPeZ4RtAH{WoRXN6YA9tO0TSdA7Ie>dNlZzp)Jx9K z)lu-wOV%?qG|&ghF$-(B=PQ6E6@v2fOB9?_i%K%nGLsWaQWYFaOEU6{GD|8IbQRo< z4CKUl4J?7s&;Sgg#CeU)4ULR}$kfu*GHQ^xvWZa%Irtb^8JL?G`56qF7`d357#SJ% z7bbCh{1s{PUHYWN;_nTf5igaRg_j*waAve_`S`5WbH4hkZ!OY(3%1-Ym~q^QaU-i8 zyWhJnzx?$h4V0d*mJG{&)WH7dvsh_^WnlHwpQhVN{8sih2|w9pzmmE6*P?x0qFMF# zxDRiW6k$E}>hKDdDb{W^M!cUH(v(j0X6Bmp2uf_fyh$cui^VUdo^zM)y0PEmvU?p{ zbE4+=2JPS_laew6Raq0ITpD|HRyt2pzQ4w*aTcHEQJIx5W97EZn`gjfdG2FJ!*B1{ zGe&P(lblsen8MTpk~+x)X@f+aLO(Id&r>-Or*e2W@MOoJGS!b&*_or%!wcCtl11pbr&l1 z`KPvT`Mzwjc#DP8E!OHEOr<;iF5P&2-M8!agii+x)OERCoc?RO zp0?oX2^-WKe!iF=_0oL)>L>SeHn)n;wY{n0UpdkAT0G0^hUV3?m~^)ae7P~m>;X85swAuG-$dtLsriJBjr{lsYTTZD}?Q6 ueeG2a{zo$Z>cn@fiTid%Y?Cu5kMFnT*;{6|q@Jqkc=X6+U(EMcGG75Um}y7= literal 0 HcmV?d00001 diff --git a/certificates/roots/HKPost-smartid_rt.cacert.crt b/certificates/roots/HKPost-smartid_rt.cacert.crt new file mode 100644 index 0000000000000000000000000000000000000000..19f91c27e6151c05dc3d0db9460831d30a63f74b GIT binary patch literal 820 zcmXqLVm2^nVv<Bu#0mlV#U+Lc267;AW?^v@afP7#{1OFcM+HLzIdNVCV*^t|Qy?}r zG>H=DHG*(WOpS~zqo`+56QdHcCm2~7n41{+84Q{jxtN+585!36x7hYFjmh)zqAd?6 z{B-EA{P}2af1Y(u{|xebTYYY1TWI8U>zcTeWcIy!x^! zhnD4Rcl>bm1e?XPD?E=rTl?e&^c-ncKPcQ1X*;j9WZMmUbb^7cZ+zez^nX+tEURa=h`fe@okR&v{|yNp_{v%iJ6gs zaj}|#ih&R?%4CHZ8UM3z7_b2;CProhK9CqcNQ?!TB#t46BrrJuLz0n!&+V$sx<~Cd z;~Kk}W;k;6`0TlL`<=RU)AKCXH)7rXtqVSHD%cw}ZP%&1+;?u>dC#@ zicRM4W~`XLO>bMe`jus#e`O}8md$h0zoV2h%l}i9sO84O>)L@Ya%E;5xT*DJVN>1g%6x-436XZ;sY=6nYzw?kH@lxOz(0D!-b8 z8-FjqwpCq!`s%y~vX3sx=*YV~`m=B1!a2XMX$BX!%@4le%olqtxv5aLq2$!JM@-o_ FqX2fFIMo0E literal 0 HcmV?d00001 diff --git a/certificates/roots/HaricaRootCA2011.der b/certificates/roots/HaricaRootCA2011.der new file mode 100644 index 0000000000000000000000000000000000000000..433bb684bf3e53e453f73d9e7e84369bef1181cc GIT binary patch literal 1077 zcmXqLVlgymVwPOM%*4pV#K>U4%f_kI=F#?@mywZ`mBFBKsv)-lCmVAp3!5;Ldyt`v zffI$bX zmFOurmX>7X7iE@I8af!*flOf*HYdfDp#1z2XGaAi14BatIdNV?Lqj72Gect&OH-pL zab9B(*AU7bwC-+VR6-77Mpg#qCPsb+gC<5UrY1&4hLyn#kM)*)>-&{(LwBm(4;`%# zzq31A5~oD?_uF=wytkJS^Khl{adN(x#B-J&$S5PUlvt4v0=UWx@DIQe{WUeoNE*HKJcja z{b{kUjpUea6?neM<2froU74aEljhE!Y1y=Jdx>86m80C%`X5ek-LkFZnl)KwsYX%pMCVz{ zFZ#B&>|9yWFXC|g&b>8`DLGptXEP<|s-*P0Y*Kx7F1Cax*(j#B{V5YOBLm~&#!iFA zHUoZO8j%%dWc<&)^Rr#FOI zl;1h38n}a`_0%?#e zYK8#D79)fF`%1@$)p_=tdfLpLy!>R$<$BY0sWhJS7vfhuz&yQ8H8=LMlIDt>MZ7Ct z+pDWb0&&y^KE*-!|Jgz=j)jtr{{WZ`M|XFZvpe$F2$wmgxfq18yD|uw=U@x zcUAKdo7ns>z4okca{8~&%tF&D*m^gnzwNW%H{YM>>t;^<&pz$iq2swbvzojYr$ V?*^M6UJSES?#{RLzNmhE2LLi_kQ@L2 literal 0 HcmV?d00001 diff --git a/certificates/roots/ICA-20090901.der b/certificates/roots/ICA-20090901.der new file mode 100644 index 0000000000000000000000000000000000000000..b8ffaf2ce1a106475ca5a97925272b97a35560bc GIT binary patch literal 1314 zcmXqLVwE#!Vqsgr%*4pV#KN$^e1QQk8>d#AN85K^Mn-N{27|`!hTI06Y|No7Y{E>= zQHE9q79b8YkD;fYv!jBpLSSiPPG(wWYKnq$YEcQ0m7G|TnV+ZNSXz>iUzAx=siRmppbgT?#iJ5XRF-#mtwJ(HM|R?oUJy62v;?FhQAZ(BuUOB}*1#I1oSVl4 zYL#Pha#3nZW(m-)fTH}e%#_q3h5R%$dxKMp$}*Eviw)$&c?~Rq(9i%3qQrR(k-0TQ`3j@sgFWtMHK5iek~dv^x?cxL`Ms6 zh1UBkh0p$WxhY<=PhV$J_-y$k6Me@xIW8DFq+ca~4KhS%;U1Hki15uGVW>qP}Gr)1949 zebP=Yx%`jW?pxF3y$q%5e;N|S{8TocS54II{*tiii?&+Hl1BUen&0`kkMBOLx01Q( zZv7dlJAs*#JogM3=-olYfyiH(ROT^RlSW3j$)IJRaIG+uU#Bd!TV!IIsc8EiE(c{o*Y$SJk7++$iTR`iBS(2B3cIgz(gb~ z%*gnkh1Gx=NEz^f1o%M$EWmWnX3+Q?B%r|3c;BG$jzQy1HWnZcnDQ?eG@fPS&}L&~ zWo2h#GH5&?)wnk#HLoNek#0*AvQibwDpL~k6tWVt^A)noz?mUCzbrAYQlYrAxFj_< zzpN5jLqUE@PO3r`P<39SLb9HMk&!tlcNi!HC+R7aDHP-+mgJ@8DpcjA=4I-KWMmdA z08t@4lR?ac83@d4sS1h7$@xVonR)37K&LrZr6y-6I3|}U_~j!R?wp^Kqh}xs@+cpR z7>h{d=?ls)t$Y~0g^?_-Mk)d|#QnTwF5gCH#Q-4SE>VGR~ z?2f!S*K@~L%V{S+Y~p7*6VdaF#c0g|_kFsD?@jJrHqCWiSjp2_-iz#4sU6V>OH^SE zkDs~Zc=`s3pp(BHSNwePah}n+d7`d2W7qticYF46oBs8;y%#CJu+}Unlvw)Xar-(& z;jAy2T9JH)n>B*1l4h;pm|U~6eOr9gGKoVM4t`;f%Z_!O)q!JtlYGx#=?u9j)s$r(JxyZ; wgHrRk3tBrj_XbDkrN&(Sbi0R9wK!*b_n!pDHx82zz75>5>U7c#Rf9#g088ZSHvj+t literal 0 HcmV?d00001 diff --git a/certificates/roots/IdenTrust_Root_X3.der b/certificates/roots/IdenTrust_Root_X3.der new file mode 100644 index 0000000000000000000000000000000000000000..95500f6bd1373c2dce681e3779ac7647a84ef251 GIT binary patch literal 846 zcmXqLV)imbp7(EZg*cIAj~}vT2q`KpE>UpK*E1A15Cy4X7Upva4p9io z&j$)SDnu9?$cghB7#LU@8yFcH8W~zfiSrs6g1Ckz28M>FQIuQI#HfVqXhv2B<|amd z27@L>E~X|%Muz+AUrrC;Xb#_UCMosXgr+ygFY9C*oQi&P^Kk8Phl3I#-49+Emw9SE zwpa9=yvC1jy`9JD)OUX_EAppa(zNRcy4j_*@^4P z-Bq|BeN3xswcg%>wMV(7R40@a9j(q&NgLp&$0Xa zPdXO75i7c?_QoRA()q%lzY;MHAE&>*I%{^X?5ss6 zTx-sJA~0K0Ynx{H=YL>|WnyMzU|j5E;9$THj3HTJM#ldvtOm?L%770fzz-5& z0j35v16dHCk420{Az=xANbwf&S15*z;pelr>~hlUS#T)JUzuK&f|!LT!du298=T>o{t;X zuDlc3)}8lq;@7rQzjme>uZoO5_h`9TvHNN5Gcz}sdz^n9=Kb|NKTnZS`>_u$yMv2z zoxiGi%nC~19kT+H`dpb@E zJ-bvpvHPd3QE%#&mo*#1%U&JbreV2XG*#xrxAJLOT)pMoHzsnk^s(R8+{X28Zj-60 F004`~O?LnQ literal 0 HcmV?d00001 diff --git a/certificates/roots/IdenTrust_Root_X6.der b/certificates/roots/IdenTrust_Root_X6.der new file mode 100644 index 0000000000000000000000000000000000000000..148891c15f18ae4edcf02f6ef00ef31f4c26d8cb GIT binary patch literal 1037 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 literal 0 HcmV?d00001 diff --git a/certificates/roots/Izenpe.com.cer b/certificates/roots/Izenpe.com.cer new file mode 100644 index 0000000000000000000000000000000000000000..71f9f88dd2a915982047b7b447940d2665519a9b GIT binary patch literal 1525 zcmbu8c{tPw7{~qQde$+9WJHc3jcU#8?}tIdBZD#HOraRt;h5IcxCUVyYbIwsid3%guz8R~azvZNj@{?kr)U4&=l$b-KHukgzt8)}_Y3loD?=|H-WE@-G@$WTD*{*59q z&>=DYhch3h@%@_sQVhSmwoQ!G5YvK<3!CjN7yO zb0uNG^~CnxRp)@uA%hTkM z&$Zsoh3nHi-!@CXGf8jkx}2O7m2@GA>eCHHSF_p|jr2M*DXgeqfibSrz3~JsAD5C| zkYclD9}!D+${9rBDOGiLD!R=b@a}^VZT{m%pTr4HTJ-XtraH<^y8F^>9gi9uSbPP1 zc_VINXXn*Ag=WNSG*#>`+Q!$(ua$1aD9$eyB-C24Vy>(u4hEs_Jd+$2OlrkC;CmGw z^>E`)X)6J$>}I(NnesZ#b;HzxVH@GfiL+x z)!J}eGVaj!%ZB&U!jg6xYtNhUf z1WXx8VJ+7NYzFRP+cIY=Y_FOqq`t29nB~t#BZ}csNiD)(3o$p2OT9vW9T}YEL@9TN z?6~D%>MN0!vnyrTMOv`}3=W6^MZ67=w+8a6M9EZOZMA`7YHs0?ypZ5=Q|cU0nkmeUNa{j>+*Po?-?0aaisIntNanlf}h3K_H2Q zv((qYIT}LdAZ6D`T#8J&?B$O0VzO~|OfOatlf!ZMW%}W$qFWD^7t52S7NHnYn^ACKyK}mF2P3THPFxPyN>qI-*~Qgsr=s1Mrvebz}m4I>Co7l znZ;V_G&Ac6I(eNMQ6rUnBD6eHZnEoJK_Zd#u&8i0r!MYGZszbG%kQxDuVv zNDOR!;u1e=wz_b3Nfp${?lTzdP-pWNn|<(am1oRwxwNYCE3W?9q~ZJedbQ7u{?sY^ zI31e!HHoS%{QXgssj~Z=Nnx6{&Fb^btcQnp)>gyss1ftiPyaX>3;)70=*tbgh^*~| zLK7FcrLj{D;l`8As$ntxdH&L_0unLh2sAcBRIc zuNd|=r#~292-KWQ{ne@XVYJDuB4b;Q;B-g+>t}{q{X?kSLi*TzUO(SoKRw6jkKfd% zUF)TUsRqm6Tp2al-7K~_9w2$1cTR+pgGU>!$DDSSCZk6QgN8$A36fcnChYMoe8SVe E04K$QhyVZp literal 0 HcmV?d00001 diff --git a/certificates/roots/JapanMinistryIAC-ApplicationCA2.der b/certificates/roots/JapanMinistryIAC-ApplicationCA2.der new file mode 100644 index 0000000000000000000000000000000000000000..b5e2b89c875b5f5db14de15d19afe1ae68e0ed27 GIT binary patch literal 1019 zcmXqLV*YN>#B_fFGZP~d6Stv}sj<0{1qd4OvTL9*P!Ebal`o-oDC!orRP z1v#0?i6xo&dCrbT3PJh#B?fZhyoSaG#)d|QrUpO|CC+P%%%!2tO^iy&-ehEDU~XdM zXE11D(#a0LQ3MQ z=UiWiRJG1}qAalD*T(dKr@8JAvO0wyuUlvO@r%<@*6+U4>ufasY*3ph*CS^kHSJD> z%k-qjMkg+cI{KE*sMxnUV`bc1_kBxt^(|zYes6Ng%-r-Xtg7#(oOrux$u6TDC&AbI zPK&cmcsRNBM2f~adH3T7ViVq#ncXqA4t!mGzUT&j#R|zLjtO>BGkW{BoEJ4)mUnmi zBVPxF;G1Py7b@0te(>)$%5{0Aw`;@7*PVB_=U4KtZp_>9tXq>ia{V?>-aws|f9Gl> zr|l@1T0HBGT;MA^D{F3XJG**B{qW^5MPj`)S!4tp+P=s+L1621Emfw9{y+3 zmp+@b=IQLc&!+5ux@(T1w1Ff@hMPwSBJg5W?~4_Cp3dL(eD)GUO#^k1Br}h~Div*Wr6!5G!|6GWa>NLPu|q&erorY_S%*!@#%qs#{F4rQ`uOF3ET}tNzl`-v#q5`j zw^y7v9y9OHq)EEVrhl^7npZrP=YajWWm62c{$kyJZ=S-cKf);|yLP3#f0X>>#*B5@ zTkV#G?l88~Df+D=$nZN_Ouyxl@VsBFM-QGZ@>9Coa>{$pCEYeDma<5BPp2enVR^9^ IyRQEQ0OjqC=l}o! literal 0 HcmV?d00001 diff --git a/certificates/roots/KIR-SZAFIR-Trusted.der b/certificates/roots/KIR-SZAFIR-Trusted.der new file mode 100644 index 0000000000000000000000000000000000000000..f75028af4c20e1dd5b17025fdac1805d1ec8ccd3 GIT binary patch literal 885 zcmXqLVlFgjVv1bA%*4pVB+BrN^Iz2~hK!yEDqG$vNXx$u+TwE2fR~L^tIebBJ1-+6 zD=ULRfFZX5CmVAp3!5-gfRCYuff|Uz#Ut-sl$e!Yo~Ynim6WIulwXyTnOv2cmkAOI z)^pS|6gLnBsbuEi3yyMh^9)i5^7ju>aCS716X!KFG&C|W1Cj=&=27Cj#>iY6*x1CV zgzPOwRtDxKMt%l^CPpr%CPqevHSYTTk%pE_U-5oe+M~UfY02KRT*a$6pPh+s$|_ws z{poJD_n!~ME!yOl$$WNY4P^f0km8`ge1e$RMKi&E}sb|z*<2FArs1`Y=Nz$lXyW@P-&!fL<_ zqzw2#0{kEW7GR=bGmr)G`B=nQM1m(RuKnLs_QCkd>q+VEiN?|y)>_D+3`{)0P-bMX z3<#b3#OePM=|>7Dx1O=>)OA?7+_O`9Q_5k>6V_%MS~6Qj*SIYfP;?MfXkGkI*lFVH zRSX9Mb{&2D&CxYT_Uo#s^5UEapLOJo`nNW?yE7a2Mb2Ysw2^KVE?pBui4i**?}@_gF-WeG2RT$G;UzuTC{yJjuE(#@)z) zwn90T4 zkjH=v#NiTV_V#r#+!G+qUTiI)6=OKU}bJuEmU^ z=B=T2vivvCccowL_?FtIIms+gqq zxFxU&UK@inh+b`unhu?G^UMqxBuKAM7(XH0E@$ zTsK|&AgLtf(fQNM=VtGGCeB-T`mN5i%bPE^w;idTyCm=QlO2~c56`j7pYzyH#9K+O z&g$@!FY9jaZeQ`k>L(L3BLm~&FoO^SAz=K;3NtePXW=kl15!+k3MGad6d62X+i-dt#19k0S7u~IeOWbs+V%eTaVOjt6wQ~G*?8k|!dL4zU#8qxS!TxXd71Mvo1dUZ_V2h7 z&kGl>{QvB*pCNG35jL0Hx6_MbzPjJ}D7dQpuhOmvHqV=y9~u^hD>5(1{+ep;d0*P7 zCEj4uf{$l;KIFC7GfXacnBA!pahU(A;pzAEzcs%%xOr~#MMKYB z8oyuN-tuNm);q0Tn=<1oCZ^jI^)u|RIjZ|$ZIkqsPJ!6t?*-oFaO+i1 z^U>%OZR4mvw{>kr?^d~abwAj=Ku>Nx`=sSQT=}oFu9fqBj%HKu?c2Y%OyUX;04e@k AI{*Lx literal 0 HcmV?d00001 diff --git a/certificates/roots/KMD-CA-Server.crt b/certificates/roots/KMD-CA-Server.crt new file mode 100644 index 0000000000000000000000000000000000000000..e09eded5c1b3a1391c5028bfba6b027941241928 GIT binary patch literal 862 zcmXqLVvaIsVscu*%*4pV#A1EwWRL+b8>d#AN85K^Mn+av27@$1ZUas>=1>+kVI~)E zLmmSz5Qj^c+1uB}kRPZT$m14f1M+m89Sy|{L_h+}!n_axh2YepveY6&1p_%YF3w46 zos&Q5q%bmz2xR7^o4nyg9n+8Nlg!>TMjBoI zS1oa}h~-lMn@Mc;o35{Boxeu(9n*|bUT5RS>rPE6^D}b(z-4mNa@lXrLlik7U==#I>E@y64ZT7v?R)n>wv`sLc*67ij@_$o{XI&FjH*3>~TeEbHpV0TlZysBZN{I)oisBa8P$3n3##1+P zow>Dk;AwB^^@?gT6DCZy=dpW!ZPW2@CksC}1ZKn>(JVMK`OO?dyYL%f-)4VVRW~>9 zzOuqOX&>1c;;Yjiwm8i36!Lm>rCOy=!>}di-Z?E9)zywWo-SC;=jE=MAkm^6kP^(f zxjF3GKCP_TU+>Rh-x#!Yo9_0+dpS=(v$UDVI$LU8Z2J9l-W#h0!4s3#zO>HUW7D1b cM&{EgRdc!gr7vDs3mw^hkTJFD_klwb0ifJN9RL6T literal 0 HcmV?d00001 diff --git a/certificates/roots/MPHPT_CA.cer b/certificates/roots/MPHPT_CA.cer new file mode 100644 index 0000000000000000000000000000000000000000..f79f2d4d367852b8c0e680164ae57da2b08677d4 GIT binary patch literal 952 zcmXqLV%}oV#589CGZP~d6C;BGFB_*;n@8JsUPeY%RtAG)Lv903Hs(+kHen{O07DrA zDG-NCSlBDEATcksI90(tzbv&VFE=%>#E{Q`2PDfa%<3E95fEaiW}pJ$%Yyj|&Z$Ku znQ58Hi6xo&c?yoDB^mienI)A5a^k!OMh3=)CI;rF21aI4;=G0+E>OVK($q4FK8|Q& zR6_PVBP#=Q6C*!^K@%evQxhX2L+`P`Os_Bbu3`DiZIjkLyZd{wSako&$b#r2slC=o z+cbKUcRk-d`~19V!n^j{^#Ah8d-QG@%g?BqOZ(Qg%)URX?vi(bi`kZ}&Q(EG6&VW~ zzTPsDyQda#Q}xyHtqYQQ8YQn7NG=oZvbpUNl~C-oXK~x!ub(vJWd5oj;96O>rt~t? z%1?nAwOlDwp4n&Se9yeMg8O4-_WGDh`DIydvfm0D z*ZfHqlAe>vvz+^j2FGsm%oE*BS`2fXvQF>VF2u^j%*epFxY(f3Kpq&WvdSzH24W2& z35UKf*~M^4zC5Wy^+VeKAO^+vRR*#k1$-=GEZC(%i9}YIh1GzWk@3F)ABe{fWU;US z(;%CHARA{wn+Idt4<|-OkPrhaa zzs6hdQ*O_vS2O&qzMVOCBBblwDf!p>`#*L_PI)C4AF*7#%kZz_S4PVZB~3cETi?0t zc$+QuBJM-tbKUthx({a?h3=Vey>;KR&=fiStFA%9i446;`S1M{r@AEc|9WsRh0jl} zGjZp(b1POfxnGUD8#=>kDQ|GG!;-eT-fOvu{Ix=t|GcoP|8_BJmxW?^>w8hPEpDYp z_p;a@ocLO0ap0+z1I|6A+3Lqx5AHnd)n%upXI(LM*7@&zXP2zWI2y81&fjwNt-s42 rwlO~c`?#~TV(O-tt_x;5Mb@(HWsQMPr#Kptwo0(jcU!0n(;8T*KXQ*zV3KD1L zk%Nn;>IPS3rsw4=1m)+KC^$PR7#SE?8p<2U!Y$=w6cfnIOUrji)hz}q)ypU~kQ3)M zurx3;G&3|bHZZh^66ZCtG&BM-A>6^?$R&DPxD)+-Z3W`CQ&T6rMZ9DQMQ-($*546@0Rj zw@Ga8(OGf+cTC~VTW|iosOx{CFS}_)Y5R@s3!hq_pXudxp;@x_z(OIJskvTXZX93g zYpmC5=}=lHQqv$bBjC7W`i=z+i6P5!{Nx|Zx4@4)X!V90vRuqUwbLE@TXMs?W9LV>5R4 zT=1WJ>#wa$%!~|-iyIpZ>cB}zR+y3TKMSh?GmtXi111z%evkkQFg>yX(*uyt$0Eie za+?3xeJAHLwx_pxC@++%TBfzzB*Q=+B(2OMVIbCkU4b-6fgp>Bflwo6YC=unz(`_b zIC+sTPVefO%{6wX|JeTL)tEY&<;4D5XDfF&Px!E8-}_JR6=&?ZawV4S+dHQ>2005> ztvvN{eb+C0?&2)FS9%V0^6NqpD_`qzm|s`^+%tcl?8b*nN^dWC6e6;5myG5TiEl!? z7Kw;FHZ(oq@PGRQ*0S(}GLfHt?0@oBH7Ta$LtUNx=6yf6D+-=rW(+G>E-*<>+N4o# z?HsAYEH-bM60gazeU7(k|D^rVwf(8>nv2K7TlQwJyL02`HtD1SZdSQr^biSrr(xdvuX z?hx`x6QdGxG%&IMYdgm7NTZZtamfjR~oWi(1?#;K}kN?-E{8N~9J?8blW%3*;i@VE0*UDLI zBP=(t!*+4N}r-IAiMKQddt&Ro9olgaXx z+m-ptauPdk`b`Tk(ONXFkhk>;NX>k2@vSdaeD}=%74B|95GP zzJ_;_N@ElE*Tj!9c{>sfJ6IGb-=lN5Wy0a8 z{$1z4EKgnfdd9`ytef0QMU}JiTayhMK3ttAuPJjVXG1__?1X6R6}$%L_t(~+`#86G z?@6~jg=Iez19vIvSMOUYn!NDJ)b@|_c7E>sY}>kH$L)PvcWVB;WzNdrIfc2!<@tVR z!}F!xsu#a3OZhtK+iKR=wl9}*nk!xnGWy)Djght}`7Z-w_=)aD&|#yfF~Ug^|^ Zz$|ZrWgC(fPX0Li#n1imhek0DbFv;RtV0|DJ{v&&ns5&(eu%B)-yCP&;u!9 z7FNep;+$Gkl9`s7oLG{o;8Zl`k>Sanx=9AP$8Pj#bMJ9G_dtExy?Z}@30<}^ zF5b+dzo)S0>HKX<33lI*D*FB_!05-J$(J)1DW7xPc;?Afd9#aMRzG@@ABjX}zU94KpZ#J7^Hcw zJy`eY{WsqBa(ZOuk95g(lM|=8h+Zz*V817;_Kin<@8Q*}3blhX9fM7_ZrFL0jqAt; z*RPJTd7ZA+w$^GrC5N6~x>&nO@XGH9Bc)jlC-3~_d08LFJpG(CgGjr2fyK(cyv^!m zGXfv5K2}^Ub+uK=Msw>dv7-$uzUA__tW=00a#f{Sq8mAb@0^?Vf zk420{MA6{nZ-(oBGj6r7(z>u*Z=-|ZavuXekTgFd<9`+wU>ajH;0N)AL3~yNW*}t{ z1QL*E@iy=@a9`lMz`4yaqokz3N?$*@C`T_ZwWK&dr?@yrFF8L~ADV>Vi3}+L!PAc( zP#bdG0h28-?id+%uk(JsJ^Xe3D&6hH?yXq|pDdMq^4#X-m&nxetyR%cy{cvps;28% z90*Tnp25~Ue`i@$UciH09Xfwp&q!>TIW>^)jqHw&|Lp-XO@|&oFlyMpfZP4VVZ-+` z(~TPZ#T6@gGGp$=nXF^ls`e`2e!WDh&dE>74_C7Pt0|PvHde`!WBtyWaUe_Rv|e1| z>2(^H>ke&6o2V9Vqo)#oI)eYT#+&tm(>~v+&Oflc<5O_?=7hL)>ojhe>g1caURHZ} z?@hG7dbU{2UKbXLrp=v|;sS-XRg1*@zA~O&l9QUT(6cPY`Q(i~X6ZRgr)<4)X6N24 Z(=f$*Hx9r4eR@fP&xX(i3#!960RX_ofnWdt literal 0 HcmV?d00001 diff --git a/certificates/roots/PCA1ss_v4.509 b/certificates/roots/PCA1ss_v4.509 new file mode 100644 index 0000000000000000000000000000000000000000..759f894454c468a22030059cffca2bbcc08a6920 GIT binary patch literal 577 zcmXqLVzM=8VqC@~$Z&R7eb|TlPxgfTQ(CjRXjP~IFB_*;n@8JsUPeYHRtAH3Lv903 zHs(+kHesgFU_)^OQ4ohqm@h1~C^I-SJx@o$GcQ@s(A>ZjB*87L=bV#RT&!TI5Kx+w zlbNg#P?VXQSX8OtoLW?pnUYW;3>rI`8XFm&O772H9G0j%)1&ZP`n{dKueZ-@ zYv7v5_sc?cy<11q)8Z8iW~;>V%AZNioyZJBLgF{^MFyp40M-|{f_Qq8Ta2g8}r4!Ty~nh#kb1%|0L-zW@~Ru zRWi#E%&BoY^LdWm5q5i#4gCK9Crm2)`Dl;V%l@+q8o0h6)%@6`6uV>N-A3ib)vBUy z29;tzUa@*lsh2$@bK>##F9HrW!iVGKgI{<&Y1>l0&~!t!>aHD^`&Qdq%w;fPnDO~y G;S>PVCenTY literal 0 HcmV?d00001 diff --git a/certificates/roots/PCA2ss_v4.509 b/certificates/roots/PCA2ss_v4.509 new file mode 100644 index 0000000000000000000000000000000000000000..8db922981114008c39b5190e970f1e847dd4ec9d GIT binary patch literal 576 zcmXqLVzM!4VqD53pey~yOT2gS#MjUNf9-bN$8EsN#;Mij(e|B}k&%g&!64p{+klge zIh2J>m?<>aP~1Qi#NiU=3rj7^49-l?(^2ruOV%?qH!uZBa0}}>=Oh*vD;OyRlqTh5 zCMyIKW#%RpRVp~A7L{bCWhN(EReSnx|* zKid!WMS6*ZyIq_$d7tA%=G~$VlVe^#Kf{q@Z@1a&&wuY6<*NZrYA%v}%7+VINvgQB z%q!i0Vi|)x6Eh@>4ee D8=TE8 literal 0 HcmV?d00001 diff --git a/certificates/roots/PCA3ss_v4.509 b/certificates/roots/PCA3ss_v4.509 new file mode 100644 index 0000000000000000000000000000000000000000..c61d2958f7551844584f87b277b2f2ec0de5a4cb GIT binary patch literal 576 zcmXqLVzM!4VqD53P_XNXtiVl8lWi8Ks+rI1+Hb(i#;Mij(e|B}k&%g&!64p{+klge zIh2J>m?<>aP~1Qi#NiU=3rj7^49-l?(^2ruOV%?qH!uZBa0}}>=Oh*vD;O&TlqTh5 zCMyIKW#%RpRVp~A7L{bCWhN(#8@*@)h;-ChwfZuu8f1+M3oy$*#wX)X#kJIaXSD z$@0Cw(}&XgToaD&+;(5>tbZ!5#&^m@-|{ai zOz}z8Ys_$6&cw{fz=-TTV3aTe-L>0CNc+5w8iT)x@ZDv<|8NPm^nBKkNuQ)&v+d}w z`yXCR-6Pwdqq8FLO!18+2ZBHNT~j+y#u(l>DNga@#f|@;Ur>xVn<@U-MP`nqi)Clb zojDBrVZBT<-!7Wq>hol`z!KXJM$CL4&;59DGO*`a()?%h57cfinsd_3Dto@)ivKCR FDFB5J(X9Xg literal 0 HcmV?d00001 diff --git a/certificates/roots/Poland-Certum-CTNCA.der b/certificates/roots/Poland-Certum-CTNCA.der new file mode 100644 index 0000000000000000000000000000000000000000..cf29ccc1b794186fe4c9689bfdfddb232c2b45bd GIT binary patch literal 959 zcmXqLV%}}g#I$$;GZP~d6Elm;0Rvt(POUbNw(q=*jI68-26cwq2Apinp)72|OaVTI zN(Krb4wtZGXkKPjYDvCANNRFMUVct~dS+^|La?5ro}s#dDo72tu$*&hQAug80*J~? z%S=uz$;{7Fa4ap!$S=w)se~EEEG!9C7*bSPT#}li;Fnrbo?n!$;OuB1C(dhNVQ64v zWN2hyZfqVU&TC|8Xk=^%*6fSU_!i&(yw3l4*wv`z(>i~BUY&78xh+!tJg54eHF-tN zG6qHWA1r!#>0wE!-Y21+ zz#lbFbnCyaiGM9Nf1~cjU1ugbmHVikoM4fE`@@;veR9(y?XD*HJ!92)>scx6z02da z{?DSzmZ$#7-!Liqy2atVA>-jU_XKstW94@QT#S=ko_UYmSmRW{)St^kPKUGwxUT%^ z$;8aaz_{4Sz`=kYm?&h085#exuo^G}DFa!M03VAOiwH;A+0*R*RlXfP`*!z)J&#(< z-Acb3@PVZHLF!q6sgn&klz|Bo7|M(c%T}yaI>%_cZ1Ml33m$X3 zvd6EzT1R$NgHj9FIj;L3&a)5@0_9^{1SKg{Ii zy}4??Vq?HfwxuinPc^@=>ffWyUuWvNwsbvp;=EqMr2oD1#>|&{)UUYr?&5WmDL*f= zL}up_!y|JvN|;Ul8%wG!eaTz0-ER7^vKQ*p7N^~PxbBl<^r;zP&BX;z+N3TSI_}cn zrz;#)mhbn%uaVC_nptUq(7vUN<<8qn$+*!J8%TB(rytMlE n{8`-UOs1L}9i~42`C?9JhosxJ?IvIA&RNd7Y4I`eyT1+q$_H;s literal 0 HcmV?d00001 diff --git a/certificates/roots/ROOT-CHAMBERS.crt b/certificates/roots/ROOT-CHAMBERS.crt new file mode 100644 index 0000000000000000000000000000000000000000..82e42ec90cae53f25d5618ea16541d482540825c GIT binary patch literal 1217 zcmXqLV%clZ#JqF?GZP~d6C;BGFB_*;n@8JsUPeY%RtAH5Lv903Hs(+kHen{$P(yVC zRS<_uSkBQ|!8tKEwJ0sKC^u0d*ipgR(@nwA!pPjj*vP`%P}x8cq>x)!Dx;*Nz)D}g zyu4g5IU_MQDYd9LGd)i)zbM^M$v^?5h*?ZJ@BT5p@H_!o(6y`r?aVS^1%RA8oVghc<_ne#rbdo=ag zH}@6Sc=$I&MBF}{W*@>^UyXQr=fxHHAf>x`+}u)CzoCM zzfvYf=EY5nF2L|`Fc1Ppx2!ND<9`+o12!PV#K>b{0}_*GF$Ko5;R5{yx^3Ff6q8(( zgPvmaVJWBxm^Ac&3JhdHy7^edSVSIA`MS~fRF%E@nmpJD_hlfC8+n>`aVe1~88n6k~d{pcvJ&86~+n$mtB2If3bn zk%7l?`XQ;d14=dXe^2-pT{_ z+=0_}ji;;Y9lc(Ij7^-oejnC9vy1z_eR;K8t(A~U-?V-kR<8U@Q#53Ac@F4xC|$jA zURL<{2aoI5S(l$b?mo}j#^gkU{}qwle|Q7F|JwYbqZ1*my_GZHiuF|UQ@3y4QQk?K$ Q)rA>*EVdTgbpN;m0N#tNp8x;= literal 0 HcmV?d00001 diff --git a/certificates/roots/ROOT-CHAMBERSIGN.crt b/certificates/roots/ROOT-CHAMBERSIGN.crt new file mode 100644 index 0000000000000000000000000000000000000000..11ee9c17d2174dbe7f03ea98c5f2e10abb90c0d2 GIT binary patch literal 1225 zcmXqLVmWHi#JqL^GZP~d6C;BGFB_*;n@8JsUPeY%RtAGwLv903Hs(+kHen{$P(yVC zRS<_uSkBQ|!8tKEwJ0sKC^u0d*ipgR(@nwA!pPjj*vP`%P}x8cq>x)!Dx;*Nz)D}g zyu4g5IU_MQDYd9LGd)i)zbM^M!9WhAh*?PXMn;B31&c1scUl)Me*8x5 zd6DKn{wEi17hd0WeV!c)*QD-*uwPq@^gDbPCUAV&&gr+nQ{VI2<@uKE0 zTyWD#;Mk9?E{85S*WcdrWRXo)Xa!gK${VjFjkfFmi?Nq}w{gasQ){a-T^~>55B>J+ zZRxAj7e--|-8xsOcBQht%idqfe&OTx^>1~2C+$A4B7S*#Ez2iSj)FCluGO+!GXCwe zjhp+o)X5{g%q#0+J_W26TDtJON5Inemrh6t|JqQ$u}P*pi$DGj_tgIP&UMdRIaQe$ znHM)P1^~mu$3O@e)w05jjQ?3U4A_7a6C;m-JxENR#lpbMz+{2Z0)sX^Xlh9=%0W*p z`bep#2$(kXfNBh6K?d-#h_Q$`&oP_7VV;5Sv2*cj1y(<0UixdLhyfo+njd5*3ow1N z83?j*CbW4lw*7EoWCRH@up4NBlnAl_(`%zVnhg#}d{BCYs1+hkZ8XSS1(pzlAcFul zZf!P37RJVQJuXH@14p2@Ie-GJtn5sTV#Y8Z7ZhXqxS$xr*BK?bIml@am`Q`_wVj-{_+R>y#{+d-4Uh?W&EKOt$jmEbOXT`lbK>l^bit zuj;Z~w2x?b)EL>Z@4#cX$twRQ>{VN2p!;IFTDWOv$ux;?qL0?ANQN;nZQ8{z^6FSu z+QBy0(C&Sc_RU$sa@^Bq-V4pD&g=iy|IhfkRD8nTH8amFZ42j2ce{N}?2y~XCo2QK z_FtSNdO6Gh0VtWlHqEj;-D$8)~)CGMVO Nv85BFzN+qjtPCX$ z#MzibS-6A+f`T0tf>V=Ai!w_p6+H8j4P_0aK~mhpA}CTu1|}8?Va5h>;=Bfi21Y<& zU~Fk*93{?cWQN40$m}LYC1j^EvNA9?G4eAQG%<29H37Y}y+5?@Qp4Tq%*y2-Bm#_V zlG49%O=Z9PO#1V@o0l9zve(Y9*(Z7Sx7%vR3^|Ecp(pewR&;9oR@Y4Uf4{%S`lRRV ztxKkyV|-<|HMzQ8?XTqB1B!cFF6#Qb9rn9(!`#wZWBuv5Qm?evD=s~#th8f?bd+#= zc=N>%3eR8oD?4pqSX$fp@?~Q2lo^F;dvvoNeE0qEahsNfVI!~RLxzKa{60ZHSfWr7RC z{a4X3zOZp_kAW;m0UwJP3wCML6a$O~MuvF1wz9k(rZ#?NGIEtO_W!*qBv={5_s+0$ z&)xc;7mtZ5zUX2M;kEi5vh!NRt?7ng)S z44C{(ny>Og`X09v`|ZVfr#?G2A@knzE&BJS)?N^@x3#PHwHL|wDj0C};Fk$YIb;nJ z{wMS(hj6X`w=nPM#VW0git}oNuJ+RKnVzv48JDm1z;88^sl0c6#4t?@0e5y0*Yh-?!EJ(DvK^ nW@IRLJ}lwC_vL6yvZnNz)9fc1maM#fNXb9_difg#*2H@Nk2go$ literal 0 HcmV?d00001 diff --git a/certificates/roots/SCRoot1ca.cer b/certificates/roots/SCRoot1ca.cer new file mode 100644 index 0000000000000000000000000000000000000000..27d0266c51590d8c9b59f40957ce1e9ca390ac44 GIT binary patch literal 862 zcmXqLVvaIsVscu*%*4pV#K>U4%f_kI=F#?@mywZ`mBApuklTQhjX9KsO_<3mz)-?K z48-9Q<_~st_V-l?DJm^4(aTFMF;q8D1<7y=%LS(<=jN8?WhN(6QdHcw-{L&n41{+84Q{jxtN+5 z85uTj{#SoFcjJ4pn((DOxn*7Y-uqL2`@HM=@L99w>;HFJ4_?096`i6qYgWFFm0D&X z>rAyfS7ovakIkx;n|rq==U7jAx|iLL!VQw@D>-?VP2KO^!}BY2hV_jXN(;RUEh^Vc zpOm?|v+k8*2HOmgY3-L1&GzJ~hs_Irci=$SU!(I&ZuT8gzTUgy^9|KC)1MSreA#BT zWv=yfHRr_(_jpDY`6wH-Ge&&#+b5F|mbU(^W9*5|zFMJftL1OWJ#w(UeYSSzq=q@> zcX_6z%)O)ZJ*E48;yuwRL81$4gHC#{P&|2T>dW(AZdOU7GPRoGvEhtgc%wCv#=U411aPn2BsWf5Hm7lIILW;`-y*SU`DO1;7AT4A{kt!Rn;8HNfKyfg literal 0 HcmV?d00001 diff --git a/certificates/roots/SECOM-EVRoot1ca.cer b/certificates/roots/SECOM-EVRoot1ca.cer new file mode 100644 index 0000000000000000000000000000000000000000..c24822d58af84078f561a1117b1ab853dcde419c GIT binary patch literal 897 zcmXqLVy-o4VoF`W%*4pV#K>U4%f_kI=F#?@mywZ`mBApvklTQhjX9KsO_<3mz);md z8N}fdmI-!s_V-l?DJm^4Q3$RqE=kQTR&e&$)A0#$(KFOC&;Tjp7FG;SO)f3UEU8p* z&d<#)&C5(qEXmBzQ*aGa2+GedadtE`kQ3)MFgGv*LL);XW1}c>USnh~9bC}FsD$io zMpg#qCPsb+gC<5UrY1&4hCTIf!e^^I_%~;lQ{~Ezu3rrgzOrjNzv|;MG3%B2wS22( z#sBH0-}RrY%4TVCIkoIjM&IAifF%AUg?#7OEp(k)1J>G1%kRFri0}M8&raKGDS8%9 z<#M)$cg=h6!FRSQQ>@)(>x3t4bJs0onI2L3Ucsv=yGLpN8+rbhEroAC@;%uhA$%sx zEcW6oxxj48yo9n26YkHOFK(E7D)CW@>_Ip79m#j)j8ixFafSxjZr%Hz{q@?!Pzjxt znKQgrIUF?>NiAXcIq}|lW{;x|A$Ry&CS)iaoiy!^-cu&mRR`ije&oLLJRh6mz5e~I zLt!z;Ov9YA4B`*1{`Sb$e)CDeenX$@^F5iE85tNCI~h0_$O2rEDGRu`s zW7%8v0BI%z6}QTNEbRr;9f~g=I2bNDD|4y(%++&~TD}Dy)H$gvdP8ITYE|K_ZV%g- z{;TyI>6j!N_D?eXQ|Ob1#o2RKmp=?FGsS84~p`4$37JE59Uhw>Gx&7U&!8yoQ_xf=LoADD#%<^&ws*ZEyu|XGaMFc MJ@06KTi#y+0RGclk^lez literal 0 HcmV?d00001 diff --git a/certificates/roots/SECOM-RootCA2.cer b/certificates/roots/SECOM-RootCA2.cer new file mode 100644 index 0000000000000000000000000000000000000000..a42b51999e61426079da0e4a7399e6d3888d586b GIT binary patch literal 891 zcmXqLVlFpmVv1kD%*4pV#K>U4%f_kI=F#?@mywa1mBAp^klTQhjX9KsO_<3mz);md z8N}fdmI-!s_V-l?DJm^4Q3$RqE=kQTR&e&$)A0#$(KA#xPz5RD7M2T6O)f3UEU8p* z&d<#)&C5(qEXmBzQwYk>FL8D>GLRGJHLx@=H3DJ-17pi5ab6G;&ZV{WO^iy&9%f`^ zU~XdMXE11D9*eMzQw*#-0Hac?9RHf`TKs_nVBrGKKRX0(6wZ;ZFs}cpPe&LJzbr3W$P`+ z2?7VNU32O@wEv5R&{Urg*6(IdT$`&!Qm@_N@x6Gjj%T&?5z&2CVauZO%QAyjR_#3T zI%`&J&;?ztY*R5#ftCwdr>xi*%-x^Vh5OrgzfRxLvFhl);LuGIkJRqm&??DRp?5n` z>R0PmuZatvi(TzoWO;wejskfN`|dvuammd#&0113v(Mj)%(DKIFLqu2ub04Uza}xO zHR?RUAJ<-0*^tc~a8TDq?5>N6x>V_JCT2zk#>Gws4hFKo_>|>i5n~bIYF$~L$~vRQ zq45X*bRCP2TyJd78}Nao`577iv#yLvlfQh+Lgn4xROX)+ z|JSqZ+@VXi&-DH&{KKqyFelbHK4n{~b!WarS;f~oi#+5d?fWLb{`gD$-C4iKEJC5z zo<6zz+m5y7k!;+t<$I?4XIOoGsmJBKZGCu5Qbx`8zl*zC7OY9yr_I@J@*#_H_iW8D zn|}=E=aq9l`mNel;wF?c@tw)lH?t-_ciA_=u;{8M(>JE4U*uoc+?*D=^8cHzpEKS6 zn?^CMVmaLv-Cn3Uaqp5XRlIv=eGOM;U{@5k_p-dm>dC!)n|b5X*q&9!ag7=^%WKtN JGpy@12LJ#sRXYFx literal 0 HcmV?d00001 diff --git a/certificates/roots/SF-Class2-root.crt b/certificates/roots/SF-Class2-root.crt new file mode 100644 index 0000000000000000000000000000000000000000..53a86ac2a010c22a604a8955755060c9c2b7cb1e GIT binary patch literal 1043 zcmXqLV&OMvV*0*-nTe5!iIKs8myJ`a&7D}zCXA-4f18*?ZNn=n&ou%W7f zGKj+^EE8OkSd^BTnvIsU;t9aEv$)9=A4sQT&!TE z;G9}il9`s7oLG{XpQqqhT9T1plvz?~AScdiU}9iqWNBz_Y-wl~CC+P%%%!7Cniv(3 zgMpEifw_s1m%*Tkk%Os;k&$7$(TRUA3zxC9uH_L-xqr_0{Rw7?cKd~^f7>jZ|Kae$ zTUT!6X$MdEt+K?f<-@!e@o%20yL{DHW?y~pf!2o;>x1>@onmF2EZ3hVW4YY-SJbv* z7S*)Z<@L`ak9o~h6$yE*cKma_ z+08VYjXQQW{hecFCvd|0JzHv8)oe)#+y8}uHU@g}`)tdLH^s8$999mSrQNDFNoG0I z<|p>N>p3c$c9_||nseE7^PbF8U(d{a@i(Pcyummx&MS82NxAkdbEOVk%@a0Nj=MiQ z-uC^q?`4Nx+3l|2m2pbXX1Vd>+O7QVPc91>S2Hm(FK#?)(0Ir|78uL2d@N!tBKzaF zUp#kLzU@nN=$bp%1rG78?09a_I0+=L%+lCp(AeI9Rn5YjC0X=~+9qHE=K;A%n1$7V znUV27ay$c*J20LZ8Cd7qcg($bQYv)en#|9iBX7-SY?ty6U%9Z7Q|tD3{Y`Rbj>l!) zXl`FP{k^BDT{)X$MAH7gh#g$%_HQ=dRZNpV8S<;>jIEEujmGum^O~!6FFO9!M7-~& zpu?9xI$FM>^~;lD^;9o2a4Sg3X8aW2@nvuKTaC!OzGB_t%_lac9@ni}x@u2wTkhTP zC8vHUIC5uv`0~4CUs!Ba<=3CGt&er5?)zFe!TC(D{455pcFmWeN)ZgouO16IYeu_s z-0gA9N@ZK|RB@H#mZ^$Uch+7sSuK2R?VdZ2Y%S03wJR-HC=tngQfW*7oU3tK*OzX) b!j=1DyMv(HEcr^lr2YKU-#pNl7oP$Erje6H literal 0 HcmV?d00001 diff --git a/certificates/roots/SKEE_Certification_Centre_Root_CA.crt b/certificates/roots/SKEE_Certification_Centre_Root_CA.crt new file mode 100644 index 0000000000000000000000000000000000000000..d64bd4ade28de299dfaadda33227f49316721fb3 GIT binary patch literal 1031 zcmXqLVqrFDVtT!RnTe5!Ng$-*=Yrz5_6$C!I&VBKeCB1q%f_kI=F#?@mywZ`mBFCY zklTQhjX9KsO_<5m)lkVm0mR|rk#r1J2u>|3$xO>EDNao-%FN9y&Q2}PE-g0HFi-=j zVdjx{byaYNs7X#N$;{6K^72ZGQWb*o^Gg(*9StQ6#Nf7ZGKz5)WM?`QXX~Y=8YoHd z8yOe^p)r(<0to;)Muz4_#-^60mQe%cv?fL+W{M zgQMQ7*(;`gc6s-ko9BN?U*hhKNw1V|tX`OERQ0+~+<)2)uIh=4l5>vt_~=#cU&;C> zGiGXU($Ad*Zx097UYPtW=e2?N!#%b8gJz%0t4{r7vGKqnqxVUhG9DxbA2gf#|IL(L zX6xq2EH~nRTC?R?e#zfzi5F|a-?Axq8yQ4I|2@0n*}^{sd-^67-=4m_Msc0(!LJ_e zIqG}otClo|ZunmM&2~vj_BH?K=N#7Z-!;0tr%Nb!#>vj#0O`(*LTw!}Q4iSAGk-eeIK_T@JfkQ7t>Qz4yADS6a&1n4@!=A0Fc9nDxeQ@kcuu zotrtb3%!|`85tNCH+C5`wj1yR6N0QTBjbM-Rs&`rWxxj#;0Fn?0Mj3vfh>s6$0Eie zBJ?TB?p2t~{xQkhCg`oq-J-hc+89L9#P5!C8!O7Big10%vi+ zS)9nx1x(Yx=wf83{`TYm?jJ4I({@U&Z+Dc+lHg_YKW>+| zQ`48%vs19$DEgT<%ZVp3&q|7?#EQ)jp8D_i?Ts!^tqRtdXFuC)T%>VwbNGU9Oky2u z+}oCUD`;G~XWPBjoHe-QU*4HL&fdAOZ@`If=!^h6>J(26E!O28ISE24+CQ($F|coYx4M zONr4d&jw-@VfZ8)2&Z??wd z*zKDs;vC5a#!6j2@A`K0^E!o|oU6C={rBZPhga{Me!B0yy=eN1rlRCve#f3#fvGAB zqn5J$niM|w*HXq$r7z|8gsBDjRY;~rgfd4Q5Lwq#6B=I-U9QY#HvO~8)>&>-pWNr= zW_5jf@sn)R?qk9a{;jI|n`toR^Cj2TKc9@Ejqbh3iIqRSM5$y$LtpHa?`#a-E3d@q znFervZkYasM|_>-jrg<12W3um9#Z=5D)cr^X!6|T)lGUkUpqOvoc5ApXyTpsvpd|* z=eYP=o$eyz_@XL{u&d8*u49#wEp^>^da0_6P`KG&C37ZbMh3>k#=zj`2gZ)9FeBrC z7FGjhAY~v365wOuV&QOq#MAvPxFg7b8zjWf!U9YJY{w2qMcpj=Kp!fz-TPwN9Nm2%5ny0PE0wm?W=WLz5O!1`QPkxwoaO6cVB06*Z;;Ie*Q>B$?(0Q Fvj7PRF}45z literal 0 HcmV?d00001 diff --git a/certificates/roots/SoneraClass2.crt b/certificates/roots/SoneraClass2.crt new file mode 100644 index 0000000000000000000000000000000000000000..85c1c66bfee13097c9f6759700e86f10cdc0b4d7 GIT binary patch literal 804 zcmXqLVpcF{V&Yi9%*4pV#3*aP%f_kI=F#?@mywZ`mBGN$klTQhjX9KsO_<5e(~uu1 z59DwOvjykpr4}U`N*aiR1ek>dAOZ@`If=!^Mhec326E!O28ISE24)84MwTW9QR2Kt z$XrT{ZemnIb|@n&19KB2KZ8LNBNtN>BO}8EaWB)kr#|pbJMQvJ%>0kX-o5n=x~A3- z^H-#=+|MlI+mmnPe$_E!i7?ASQ=VBZ&VOQL|95VFAue%tV*KyU$FKJL#nwoxT`sMB z`>f@0_|vtTN4{8TJYQPfVwSo2Z(P~l#kw;uPw-RLsFg_m7-Fq9w=8MCCoN ze$Qo^dU4y%LaR&;d;TpCosM^WwV$zK`7W6Ug@x}U!W#psVzNuz_?nq#9PV3@_o>V% zPrdn2@#i}dFSbm6RqB$>lAur+-ahy9z6BGMZM#$+-cr1Mn2DK@fpM`hF!=d_u_G(Y z$oQXy)qojD83=*|_*l4DIJ_3DifFkUXJfz(65?lJ0VV-9=5TUNtPm{g(OSJw;ph zdY`EJQQdr4!*34ft91KK=`7NRMQ;6g?x`~If^62WM9cTt&lOAA*l!4JQB){!Dr~%E zGs|q>vS{9{oLTY{tAGA{@3hO$Z{8W6-YIu(y3UDv;}np*?n~^EjY4-$S+CHWD-y+8 zy8X@dd#AN85K^Mn-N{27?GgZUas>=1>+kVJ1Hx zLpcK(5QmFLG`J)&u|y#ywMfA)6-eeJ=B1?O8EP7+gXEcc6tK!GxP~bN<>!|uI6E51 ziSrs77#bN^7#bQ{8d*k(^BNgJxduiSQ8cu@wU2T+-$0o`Q{GilE;B7RJAL2aM(VWxT~f0SnHBg&ra$EFFC0q_ct`HFjnVi zLI%tBn}>qbEIO84vvyc^=&b$O8Iw1Mh(t^ay&CYZZS9ie`k3}_eb3Yf8>qcseMw$m!Ox@hVwsK1?r-HXdW#nNZc;n8D7${hdh6;Zp#s;?$M=il%)ct;Oz1O>I(b?7_2mQmD%Ln@ zM5HZs%PnBKF7VSkQ(7v{}BKh_GDF#X@X@aZpxN||M8jvX-x;mhz8>-=(ghr_$i zL~(_BTU(R`?nv%#nIiTq>@yQHBLm}NCj$oqeqdsj6=r1o&%$cJ45SSBKmzoYHLd)_lXx@PU64yIbR?WRlz6He|w@?y%pE05EQ4bq?c z_Q^Ud-f7lv*CZts*YPUgN93bsH%;!xE-??MZp)l7OC*2#y2kSv?`O{1xApnM`X9f9 z-Nk&)rh}>*{+%!+n;x9emI%$K&HG@6RUr=;w+rR!s{xRXSH*Tbo~{K7o13E0uQpn|p7* O{1hMHDf8~lbv*zZq*{Ui literal 0 HcmV?d00001 diff --git a/certificates/roots/StarfieldRootCertificateAuthorityG2.der b/certificates/roots/StarfieldRootCertificateAuthorityG2.der new file mode 100644 index 0000000000000000000000000000000000000000..cf6588c801db52a03751774b92da032ff0c00fa8 GIT binary patch literal 993 zcmXqLV!mt8#B_84GZP~d6C;BGFB_*;n@8JsUPeZ4RtAH{enV~pPB!LH7B*p~&|pIW z13nOkLzvyMD6=X*FVRrgKoBItF3c62oL^E>oRXN6YN%?U3=-rLmI*FNEK18v%}G%R zNlnhk%g@PA&rB`WQSi)5)-yCRFaRlI7S=>43(C(gQE*NzD#=XCOinCGRd6gV$;dCt zEU8q`Rd6>lkQ3)MumnOw12BjZ=QTDrG%^MvQ%h6Js6puBCPpRXU}a=wU~XdMXE11D z-d`>a1oOIxgTU`Ca++d%i^=IX| zlXqLq{r#tsVMb!fd9@~oBcjv*#k4g3Mo8warek|YaTNWi( z7H4wc#k8=QU7J7DFFCvSj*(%_#Pbj01%G6(@{GASbIQd{6>DlMF}~T+m0oT5 zC|$2-DzloN^IR{(Z+u&Mc5i=VUaz!^VKHBI(C_Ts)<-T^2Kt?y@FksH@`R0B6)$7$ z(TL}{&sq({XQ> z^=Zx&S8i*E#_zQ?Mqg)~is-A=dN(1mIOV5VNu27!uW77$^_HS5wSEV5_qAqz0RZW3 Bb(jDE literal 0 HcmV?d00001 diff --git a/certificates/roots/StarfieldServicesRootCertificateAuthorityG2.der b/certificates/roots/StarfieldServicesRootCertificateAuthorityG2.der new file mode 100644 index 0000000000000000000000000000000000000000..42f3c1b9ea851d77a1b156995ee2a5296e08767b GIT binary patch literal 1011 zcmXqLVt#MX#B_ZDGZP~d6C;BGFB_*;n@8JsUPeZ4RtAH{8HU^joNUaYENsF|p}~d% z27Dk6hcLTiQD#+sUZSC}fgnhPU6?C4IlrW&I3+PB)lk(y86?OhEE8OkSd^BTnvI#U`uuza;ap9t6a2L{-?Pgs zl5d(Nte71a!_crvKeGN?`%hKpw&$7BL9-@2EPQ-Jm)9@<+X>H`+dfN$t<&CCBJ%qD zZ?(r#yJV;7Wm!i|>2weKuexAzL2&b}mJ*S}>GN1JtnT+YM9F&jop+vS{XFa%L&52w zch$A)te)>N{OS7bP{MiPNG9!uGbZl$cix+jn#*)vXX3JD&+oNLc-Ex(Ew;*Cx%Hii z-Y#C|9meeDD+ZAek_f&-n9TI)D_j}ew*jYqV9Z;Uo_wC|NGvNvHXns%A{7~Pv#u&3(uFc z-8&&E+u?A&)=l=m-0_F!{wv=;_NzD4Zza=ncR@G1FMsz|YpU&DnV4j*u}xR&n?PI2 z$%5sV)^67!V7OH{5j|q J(7RD%7XbdRdH(W)WpQd zu&vW9nti*1+1{qz55*Lir&g`!TO4{)b*9(R3t^7!6MPjDmWZ@lpZ&YZZc93I*4u~t z-UlYO7Pvlens-lA`3fWN0)fgMx0&~TUa5ca*aQC4^SVU1cI^EYmh|yx(KaL1o0~rG zO+Cu1lXrDezC<^JqexS}gMwO>2LD&NdiC#9Hk#XRKR)sMBgQv>r*u9%lXuzd8kc0{ zy6YxQssC%7c5l1Oz0732cf!AVXHT~79_JllpKjJGI*Y$r?lG0IwDgtsQs=3!L|f)^ z^s42B&R%`zlI0~s*@Q=H&V;$De3c1V{jTlqG^5rZKK?JJmThCbYo?sO=fCKqQ`XOx zy|I3yCTQZ(`>jD+N}1_(myA`JR&|(|Op(^+RgV*vGR$Y0{U~2fBqDlgPIrXO;az@K zG2b6f)3$rhzGunP*fYNKc^}?cwfkY7)SLc?+kAX0i(rBjy42+AN3>*yjfk|0bn33^63#$P$kTT!{3Gjmi zSb*7t%|I5!=VK9L5%E5{#UXpG%;u#ssd;W@o$ahVeA|#y888b0QyC*eak#zC)u~2x z=C`L!dMz1O7yR7ujo>!-_gnA1Er~h$vCs3tpS+pEXXkg_I%~ys!zzl?KHlVlKJ%qC zS*g8qCYYb#>0^(Y;_9aLY+u!_g)5h23QgKjYj(w@{d(X>&E#vPXT_eVcgp@aWaRPp z_RI_Y@gXH=)})&VCf(%WGH<`QSlpxUlDO=*>wj;jzW%%7%GYcDOQK6(9KDpV={9Gb zYIpUnph@%WUK}l7X!F3UI6Lut+a2fs{}ul!$EtXJy`0OR#KIchbSrO(v1+BaUWjD( z868`LmlxUozc6y!x7E0;dMsmelAIh16kpNnRD$Mb0S9(k9^-)>mAvMRoP zvUau5Hs&Qxdb&qAt(em@TV_3soY1AwdNsCW<3&D&h}ptRHzY56TkZbWHPm3qyIEJB zJ!*eH#^OqIPv%~p)Wpv4a5&0yk!ync;%~S3wKq% QFTSxYI9&JJg@@NY02MY#g8%>k literal 0 HcmV?d00001 diff --git a/certificates/roots/SwissSign-Gold_G2.der b/certificates/roots/SwissSign-Gold_G2.der new file mode 100644 index 0000000000000000000000000000000000000000..4f228c2e26cc126a09cb156d66403d1594a98033 GIT binary patch literal 1470 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 literal 0 HcmV?d00001 diff --git a/certificates/roots/Swisscom Root CA 2.cer b/certificates/roots/Swisscom Root CA 2.cer new file mode 100644 index 0000000000000000000000000000000000000000..297822f8eb26f0d34d7e1b876c7a3a94e7ed1538 GIT binary patch literal 1501 zcmXqLV!dh5#C&i8GZP~dlYrbjjTauDp1wa^<0Tg*k-p7q9`HtzZI(&3r7&+2(Q+(nGajqYmj+>`K*FPs0v()y2I=Z%`9 z>F-xx+G!G>ZS^_D?A)OZ=Y=y)ojCn^>myq|#rv;xt~~fzFwN(GR>X|$;!mW5p4PE5 z$j0A#W;c~(duE5_LdOKvMDMAV8A&o5xmi08m^Fzg+ONC4@b8{{nS{1&!BaeUYP%iv zXVBiiaQA8Z2gk!@!e3m={BckvXl_U7-9znqCCV2>{%W~L?Orzb@02GOyOzecC6~3H zUjN@y<4?m|pUO+SpB#A4_%6Va!&JFId!^Wxp1jtV+XT-W-VIihzONhQ#pLkk$boGy z4W&3Vo+ccYKQf_DASuCx_YK#+P>DjFrC&Df5l#9p^LU@^ExGW`Hg#v4WG6oMeytN^ zvZ3p*kl(ZouM6tuS$h$S>a!H{1T4I zm~554Wcmf^ncLfpyc2Gmdw+qae(L=EcK`OSzIcwBRndQ<_AQ(^KeX0w19#?`4O3Pu zZ~t`JE8tFi(FU6DKdW{kk!{ z+h2LZ?59(*^zZlFpBku{u#j8xNla+O_7#6-zEkz};oE%Kr@!TeCjVc75T@1>Kc61% zKL4DbiJ6gsadBgtL1VK4A22b?@-s62XJG+mq&5Rt5MPl+%s|9Ih>bm=wS+O4i4o2K ziUFmCLCQG{*nkuhBRfP3ABz}^h_9N0Qm6Ojt4p{R=HGiH)Ohrxjh=x#NQ*Lygn?KC zb_J+86_`{R8H~6#Es;K5yRRv{b7xll=Pw8K1Z#Il+Es2}v7*R4ZMM|gHNw_>`;$J* zxj(OZVXz0EW7R2z<>J!YD&9Cu{Oq(=;Bd_Q{|S-xXImF{+j_{TGTEfpel>cjZ}7Bs zX_du=&uLm|a=pgQUHLV6E22tg?YMp`!o$UVh0iY^PcE-RLgp(Rcn+UKeM%m0*{f+T%Az56 z&(*Eq&H7yxd|g`S7%J}^h?h*)$@YGqk-_c!c+J5i&iBjirY0^}-xBIEF-Yc^>O`#z z2bGi)BiFkMw#qW9nDn3D{9n9CLHJO^Dn*?_OTG*JF$XVS>{BXo^O2pl&cATuLsrdc zkzaPtE44k(YtEZ=TdgN~rSkoBHk%r&TP98q)3&&=+&eaH2EVsQm5Nd6#QAH!XS~$f z8Jc=7Hu180!430&^LMUapcl4%acbaO>(wIreFB+Z#CNgIe%F;Z=l%YSUng#HKXy8K zL0n|ccCQEPC#x%ls%=ft@BR3HnFDJpYs@Kj$rx^74WEemLrdSg-b%QyB=GX=-BYTMufCnBzpu2>Tji&#+mw@< hiotW#TvrK;KY4z(;*sS+ZJ~L~=1CuY#&^^3CIA_?ay0+| literal 0 HcmV?d00001 diff --git a/certificates/roots/Swisscom Root EV CA 2.cer b/certificates/roots/Swisscom Root EV CA 2.cer new file mode 100644 index 0000000000000000000000000000000000000000..355ddc15e749c84e2aa1c5ed7ddf3f3a0db58695 GIT binary patch literal 1508 zcmXqLVtruH#C&1_GZP~dlOV&VUn!4Dk}voE6_90-FFO@sz{|#|)#lOmotKf3o0Y*J z-H_XWlZ`o)g-w_#Im1xUfFH!+66Odl&nzxZ&d)VeHBbf#aSO}1WTt19B<3hMrxulD zre!84mZT~KrxulECZ`q~${EOjlram7!gMMG<>!|uxP~b>J1Q6%$cghB8XA}xnHX4_ zm>O6_iSrtRxIiYDOFxG+F)1Mj0wXH}a}yIkgFzD$7gG}xBg2vJvijk#!gIbC#3pYj z4B||1(J)?I<;V5w#;cs}KryM%bs=g;&bYEW`U_On7hbCJv$ycu%y4Y#spzu@wVJQ1 z%Nz13i)~juEwg23gHfE++{qtb*d*vIj|-QK2#njK6UM#c#{2H3EjBw2sjLt_zCh7T zx++{#W4Ye`Le&YMU79lkmOObVog_JhbMfcHd)|N9`{uUr-1BoiID^s;m}?5k{k|l) zyj7y4@`-<|$m<~UM;l#loZ)q@UnhJiTibs5p+_rn%c7m<@7pqWvs#w^;txuM>@_aac;d2(aq-5SpIHwzZpR<9eX%d}nYr{^m7DyM{qe~X5dn>XsrjGg*JZIhH&H3v zRpuQbC%IQN!F3gnkOSjffk($J*o(MQ4{Y15s(DLnUbks?;@hW%;muoZ3gP z6az{NgOqa^umLG1MrMc>J{B<+5!ahb8}n>Ce0vKoxgE@NmHT|8VXlEZNQ*Lygn?KC zb_J;U6_`{R8Kzhjv&|3kHi)_MZ)1$=&+C2pU)xjWzZL1*!P2MU-M^~3&vMJnh;P*k zO}Q4%?fRbl^z~lLrYn!Dbo1{E+wA&R7dC_YbIAO&E`E775A8(vv#HH}@?pZZD~IM8 z=*ho7UUekk_^aw$0jI0fPBUzYTD^6$d_!jo%hcZ9dd|uFudG<{BsuqH%99yNFNq^ltQ%>aDxi1j{O`ExFB@gb8UcGAOjZcPqpIW5diC{hcHd#uKYkE!l zWbI8|k3YVVcv`wmv;FyT8{qUWVc1omsbLJ-Gc+Z)wX} z8Lk~(96#rLOjMgOd3$x*n~8CE1MP1Y^RH!z;JnMiG?mNla@qZ50&)$uFU~GWxoCWR z((y-rE{{1+`W=dG=M$Q@pZ_GQz`d%)8*M(>FI}Zxxz?~&{_h{j%%gXA+Si;tw&jq4 zTwUIz>-C9cQT?x{`tA|TQ>=+JpLv08&rh~oBeA77GgmykW78m)5P0W$h@#x7q;mgX zH~KegTk%#Doy>5Ia`!s4__fq^uGKb1p(nTm=iD#3_Q63^_QcNqt!78p|4`a-O7`=$ zZIb-+6H~KZm7J*QKkOfy+9ZFIxARtM(eL*k-P46PpSUR5p{_P-W@WwH6CL~NcOUQh ic2Apr_^N%4wDQ{}n`Om{oV^tuM%EpAu~u#WqVE6`K6B#$ literal 0 HcmV?d00001 diff --git a/certificates/roots/Symantec Class 1 Public Primary Certification Authority - G4.cer b/certificates/roots/Symantec Class 1 Public Primary Certification Authority - G4.cer new file mode 100644 index 0000000000000000000000000000000000000000..13c1dd348d831e44ef6e70091be7211c0a3df0ac GIT binary patch literal 684 zcmXqLVp?I)#H71`nTe5!NkB2rcBo-Gd7%BvmCgo%%D+Cl}<|Yg+ND z0XBAU*fKG)v1&K6Feou6F|b@u+bVr~-R6XMZm&9$ORcr05 zE*(--T3n*wms(PuUzBa=YTyh~z$|P7SKyqJSX``Ns1Q(^l#`jP5Kxqvn^;t-;G9}i zl9`s73^rK7v9u&3zbLb$QbAY2-ONBvoY&CM(7@2b01TqUd5z5tjSLKpj7=>~Eu#jj zvzr)|kOP>Jm4Ug5k)Oe!iIIz`iII`vxaD=vl$A4^lzd*f-eebhT>Yi_#mwSg*&EFs z%qm~taHz4D@%WjZz5TV{D<4<+F#F#8{kPphL+9?S?huaK>A$6W{%K6o-?x2}$MVL7 zH{v=DpRsgsjJkN|=`Dfz`nMQ;|LVEb{M1wD$~1pBaj|sP8JGRi#}8i-+!T;7opZ0A z(pSfpwE1TpmaSxHI4D1L()@d$J>K7zEl>PYfB)UIB}Esu+5N9jUw?X%XeP()WPwM| zrmxAnv*z2Pb8_x8cXntgXrVp@Qvcz;yp86mVJw>N?&v7Ua9Bmf2yI!txmd#3gqoK%szdSeR91_Ycj)Q zBcTUpPXD&d>3seo8my=WaqYMqq zy%$>vZGLWcQ8B|?*Wy|5IvLe4jxgr*mbu3cpHoRX?qha-1DnhCuklQGZ-%_opWs(@ z!mrtZXV!EZ^ZonZeEYDawOr#M_lfi-0db2(+u2^t-f#8er84{ek_R&^L_;gy6*0s} RF8*@K_`(0Z7eg#H`2kO_g@ynC literal 0 HcmV?d00001 diff --git a/certificates/roots/Symantec Class 2 Public Primary Certification Authority - G4.cer b/certificates/roots/Symantec Class 2 Public Primary Certification Authority - G4.cer new file mode 100644 index 0000000000000000000000000000000000000000..bc76429b97ea10e2f488aee3cce1088bb83d1834 GIT binary patch literal 684 zcmXqLVp?I)#H71`nTe5!Nx(!rRmj15dsu^R!|BSXXX>MULxO7NS zX>o~yUusEteo?letAR5}0kg0TT!C{=VsWv8kwQReQch;FLO@YwZemfTf^%w7NoHDR zGT2}R$I_CF{G!Z~N(Eg7cM}6Sab811Ljwa-12BjZ=QXx4Ff_CdfZJNDzv6F#=0Ut2jW%(Hy|Ff_F`IHG`FxA zTsowvw75jUFSVpRzbM<#)xa5~fLYiEuE04bvA9^lNFks!DJL^oA)qKTH?gQv!8x_4 zBr`2D8EmkEV`)i7eo6C)$T*)uO$Pb9aVws%Mt-z)LU^chQfcZAyd!dx~#N!UA4d(P@;mLmR58aInpvnn{Lu8d~R zQV=*}_(A)Ysm_Jpv!?rfX!6#+5pTAbTX%gjudHhQ!n~NIg}oYf3;)O{{9x4I6*^0B zgXEgZtD)0U4ey)xUZ%9MIhYs$B^T#q4?T{_FS=RIC-O`ii*UFxssTv-Y zAM{b2lsF7FFv|# znsUoBjW!kIEJnTXV%2SN`}?2CCa!SMOqXq+En7c({>-z6*FyFs?Y3N#A>=VpVd?3O RcmL)8iF(o$8oAzZB>;irgS`L% literal 0 HcmV?d00001 diff --git a/certificates/roots/Symantec Class 3 Public Primary Certification Authority - G4.cer b/certificates/roots/Symantec Class 3 Public Primary Certification Authority - G4.cer new file mode 100644 index 0000000000000000000000000000000000000000..101d36135c74e6a2ca8d43ec42f8a163c5bba4ec GIT binary patch literal 683 zcmXqLVp?v{#H71`nTe5!Nx-La>nx2qWritVJ6$eJWV&a-#m1r4=5fxJg_+r)af%_g z0Vf-CC<~h~Q)sZEtbsI$!zC;dT$!7gSCX2n;GADnkYAKol9``pC~qJOlI9i`gG+}L zl@^yM_@$PV=NDxgx*9lx6fg_hz!f;>Bo-Gd7%K#nCgo%%D+Cl}<|YFaU!nab9C{Ln8x2BV$ubQ_HBq>g+ND z0XBAU*fKG)v1&K6Feou6F|dT6f3?}t*M6bmgFJnUqGRpTKeuwbKj#lTaq-K{*{32? z|NH!W#l2ni>ZNaQ40Vl?gszvhE&pY4GWE*8;zuo(KYTosgzxUU+OZ(s_Jsci`~HOi zf=?#9tvwun`s0$UsbMb;EOs(*FyI4*yDUE=<9`+wV7#*#@PqimAU>-BGmrwuoGc%U z7>kI?+&z~Hzsnv{-KX@ibE%G~wTWCDa;jj?U@%B!GGy49mXUg!^@2q$-{%vhi90T6 z9NFk)92oKYla0WMb?y~qr_xl!+w20u@|Nn(?AWnag~@>V)$->nY+lVxIu;*tYsQ!I mz5e|Yb0)^PXFK=`$Zmevd5T-6Ve935*JJ(lhCeymCp8)HvT^7bTWt=I0s88_0sBxrN2x z(ji5q#U%=UsU_w4McIa~2F@S_%)&Ns13zh^KJU&yJuFB=5 z(;2_i&yu_Uo63H_ymGgL?$)~%SC;)Wf7QxboxA;+us2)H@3Q261zBASZI;$gFE(6^ z_w`adnRR2zD>NF;}R~@ zCU>9Jd%NQ93%CAJIO7qye!XMXcCt-4x%6S|0_zR`R&3k*esp|tcZ-gyr|aE% zXclaiFoQry_bS}N7W%*f|zb|>1d(75zwew}I3tz{0!EE=Z zzdMT$#&2D*&S%jt&(rK~VrF|Ep9r_8vv{&!)i~kU9rHQKyW?iaNo{KSux?qoV1tYM zLd~NeHd~#W@nOfC%X|%N<;n&=|0`3Hm7>chJA0RIzHOan?REF#iFI4eyQX$n31k#l z?2Im`yXt)MPrU!rXVqr!J}A6(4;NMwh!bJstuA9fbWB(5%ev(`{Chh1{dJhOExxYw zY^J;EjozjHjY3v}wVTgymwuKjSS-!_>es9n&-BbJ&&)h$WzVyH-4ExP8z$%Fue!;f zWjJy7oXcA@emDD66*mQ>U*cQyHsR=|SkoEj+w0^aWmWcs?Ygxj>c*L8d*lTArF;55 zAH2PN-<1u~sr_OZpTmx7Ns9UM??`RWRcYRlbmxJ4qEtuqIlub9caHH!&06w#tIxN) zhRa^a3Mv{Kuq4*XJh1ccwcpw;#1K`xav{T&=GO(gC4MZqB-5z7okQ@1TJ^RoPx+bM zims?S$nEot&7J%)W|MVkNT$_-cRotH*35duvDP)2)ho!f?1;(NICi78cWTrwM)$9M z@@$oK>HOERTV5PkDO%&_#a?vZ?c|k-lS;!jJbY(vma1`7^n`ZVncRHI<}ZJ5i9T|C mZd~cs9RBm;(rvky_goKt{;n{$V&(MZ?-b@piWZ65vH$=sGK97O literal 0 HcmV?d00001 diff --git a/certificates/roots/T-TeleSec GlobalRoot Class 2.cer b/certificates/roots/T-TeleSec GlobalRoot Class 2.cer new file mode 100644 index 0000000000000000000000000000000000000000..0911a562934374fbb203efb9d9d94edf0eb1d0b3 GIT binary patch literal 967 zcmXqLVm@rp#I$+=GZP~d6CHzYMDH8?d{!96EGDKRG~KOd+nC$YF#!N@>PoY%m@ z(7?dZ(7?pN&?HKn*Vq`uH8M7}G_{Nx9FA;aR6-6sMpg#qCPsb+gC<5UrY1&4hE?&m zq~l){PkeeS=F6gI?oU5wgeI`cGA-FWJMyz!*Lst+e|Qhw^pJd)*?&^ukK!tJ$+sI~ z)}$Vff6G);U85^~ZP(6*LlRA5Ex*z>a2yL!ZhUffr>Ffl|2%UK4GaFG`<`bM{I#6! zd+GR$i2SbH zFE>x`t217jH>LT5$uGs#ulkA>*e|(f5dFT*H*0FNv&#wrQJJTV;YVkDe8#3Rah1Z+ z?ZIk+&YQRer$#(Hz+ZOrKyOXs=c0mn`TwN)ZpND)+mvrov(Ll-QIzHN8*?k>&2O_~ zj+5+mS#6gB5E-RP6P@KBfjv+~`;{(&KKZ(lEjAt8EWt$~c zuVqngiAa5PTf6JIYOr}yaQvQIj7ge{mZ=v$vr?)%m@hlEK*5XMJwq76@XU9Y+k zU0TChrRiShu)S{cRqqpCn0E*OeZ_7T literal 0 HcmV?d00001 diff --git a/certificates/roots/T-TeleSec GlobalRoot Class 3.cer b/certificates/roots/T-TeleSec GlobalRoot Class 3.cer new file mode 100644 index 0000000000000000000000000000000000000000..f81b63aa1e1b222d41e2b079e2088f3680dbd977 GIT binary patch literal 967 zcmXqLVm@rp#I$+=GZP~d6CHzYMDH8?d{!96EGDKRG~KOd+nC$YF#!Pr1foY%m@ z(7?dZ(7?#j)GSJz*Vq`uH8M7}G_{Nx9FA;aR6-6sMpg#qCPsb+gC<5UrY1&4hP|be zKO`yTtE_uaRko&f?@g7fJGTEh`@!kK>xz!BxY@HpWPN$MzFj_F@Fi&Ljma#J-P#Hr zy|h1Q>4Y+0^Emv#(&Fu>7#n++J(Fz{SNomi-SGf$MW)m)WRxd35 zEtOro@yEH9oI0O^uO1e0+0nN2Ter65t;NP6H-8mLeOD5d>6n;ZpZ4@{R>KCB&-dG0 zJN`=6m$u8xZH4B5b`MwX97j74NC z^Y=3A#HK8vRT9CknH8t(|99>bawr3nC@_>68NzJePr17HR`I5Yed{KyouNMcALGUi zK@2;5pGYf~NY@>B7niA}x<2Nb?5#_cCqGZue9+c@k0p}-W8{^TR_~eXRaxXtx~-gk zuW6HX!TdSj))yMyt!7=Sb9v_}_iv{@eS5xkr-%I>vF!(Qzr5mH|K{`7=dAOV$#n$> zUYp!_reyNBowt^$vX)dv)j8NTd8-K;2kY?x)Y3XEdC2Q{u7GK2A9)yQoc1vUx(PYMuRdbS|yFzQ}f3+nG;lCc0UZ=FXD3 sVDKo`k7YxAw?bX{LEEWK7u{xA+f?kxUwDBxWl@Ekrr+elOF~4V0eot3SpWb4 literal 0 HcmV?d00001 diff --git a/certificates/roots/TDC_ocesca.cer b/certificates/roots/TDC_ocesca.cer new file mode 100644 index 0000000000000000000000000000000000000000..3c62b7a0b94e0bf0d25b7bbecc918d72b2318687 GIT binary patch literal 1309 zcmXqLVwE&#Vqsjs%*4pV#A4^M_lN;68>d#AN85K^Mn+av1_MJwZUas>=1>+kVI~)E zLmmSz5Qj^cImE@;P{cq8#A6ob2J#gAon3mRR+{DPwV9>=kJowN8%Oth6%jBt(W*_a^~a3XZFrK%=(9I$0;+Je-rvVeU609(hu8n zzMAJ_zWXv>XWvIJWi3t4_Uhaen(_1T!-HNmZ5BsX9!c!D6t`YV&G+h)1xoHMH&eDt zPW$sl^2w&@YJOfmr~6g9LnLH8605IvWZa6~`s%Ed!NG>+vVc|o7q8s4`0!rr%R`<3 zw*9YuS9vbf(3bi3N7QI>Nml>L!%3QjhEJ`RB#6hAJi8_Q_NBbM^ub2#0--I-JI|7yR<$0A-XZMt24#A@coqN$!NAGT}%s*dct%f!scz__@H$=slc z$=HA&7%8&CjEw(TSPhtglmQ<|fFC5l0*q-kgT^-?0R@)ECkBlV4I1yUacDILG-@(3 zG8!~qG|*?`&}IWhK06bmm~uu*Nr9EVetCJhUUF(tNoHDRc4CQMO16GcYC(Q+W=Vcg zr9tCdxDF=)nrxv3H97L!n$3Pq81OXNm1EmIjBLkEy(+Ctm%{1~L z#mX!a24W2&30qs=gr(F8NvfyI28enWue1IsWFQMtz{euSf=e2lt-sZ>J2J2c81PAR zgqi6XSefVnqlsk#a^?c&dSK>aWZ>GRrsj6Jcm?O@Y;J>@f4d%rR|#I;G37d^K;Ghw z7R(p7eR6ixOj=%a<97|~Gs6P)5DCAo8o#F(PxVxEoR_{lq5GNg4{knV=h``sxFq{e zGTN2ImYnRCVSXxcg3-tR^mNwP8HLMc^{vdP^++n(%kYYE<_@-|z(&81U$;yQ*{NK`Fl&Bn?*p5Zol-)Rw2n8q z6j|PRWOM9B=vPs{6RdoyYNZOD5E@*|IEl*1h$IJL#2vd{Qs~AwsrJ literal 0 HcmV?d00001 diff --git a/certificates/roots/TDC_rootca.cer b/certificates/roots/TDC_rootca.cer new file mode 100644 index 0000000000000000000000000000000000000000..1cf8633bed4479cd4ef6586110191da4b050967b GIT binary patch literal 1071 zcmXqLV$n8eVisP&%*4pV#A0=3sgD6K8>d#AN85K^Mn+av1_Nh9ZUas>=1>+kVI~)E zLs0`^5Qj^cC&a~B!85NUwJ0yO#8B2i8YIjuEP^bo5R{)^qTuXkAScdiU}#`sU}|V) zY;0&ACC+OE;hGzOxYV(viBSpJ@riJ?6UgFl~CE68}L`c)59VcI@%KpDhOGq^y7aKG&VAeC%*u+WgL?_a8U~r2mr7 zk^6Fi_1gYZ*ZiJjB;>fQl8H@z$lk`6%CKB-S>drgI~!M6)k2sy)?^OS4 zEWYw**IvhtD^Q81$kz3(?>eDy|r~Jc6#1Ea^d)# zIZwJ2I2Fah(*Co)iGKXy{Av}IxWn}YRYFHDZ53FsP4QuGMP{f==GRlxWK3GcRm&fJ z(^sES@wbxAYSFbQ=Y#*>uvotnet$V4>i?wIZ`R%VWX|mFxNZ7LT`otZ-MgPHXJTe# zU|ih9s0s`bMFT-L&V)7(#3=OnF)(Ehu7$`OH8yTRai$h^*kuVTz z5XnhlJpQ*ecg=}g^8z?pIkwt_tq3rX1u5WT5o5tF%>$AaW??m8W@P*iR18k&-)h+% z8CV1i_@p_)O!W+`O!N$xnOG(uCnaD$0460y20!OB7w^gnNVC;%U-IknP2bB@_O|1DlACke+EHlsUS4kq8| z_Fj6c=#kgWM>yk4x^D{pJ`}dm=10LPlU`>B;hw)UnL{d%>Ah-O_|57H=bkTn($3gM rTnP8%dZ+rx@tyF`*%l@j8NSv%pCbDwlR0U}OjcIg>=QctZ@+_4o$I~c6HrefZ2z9frZkftM z$f?^}xRV=7d2VTCp{YYQEv!OGyW9Qao_o)^fA-h+`+j}C=X^h(b3QMKj@k^-L6C)j z18_L#btW1CVNqxk#%{(E766oxFvy*t1ffv~3W!pNyLl1TL8^*?QAY>*Qvw1ltRP#0 zKBTK)2=$HsFkN3)_W)hL)cC}h)J$DhXK0HimHl->;|K9@uNEm_+SAjuvI0jCK1F&C7)qWGvE4VWE9jNr^S(5<7>;{ zckb0+N#V0)K#e3J0GK@~LyS=bZ)VFcMx@9h2V`g&CP@M$XJ>U8Tr&Z>C_UBiV zXJ^IZuyn2VlF!agJNvChJbH{DwV(^?6E;WtIoS&Dd+gwC*3R$6lu3QtIiX4Y-ABrO z-ZWCl=5xd!gGsNXPmA?Gyyl*Q@;Yp*gx1V%Ud?#MImy81-Hy+Yl%?nCw z3e0nt38}iR17%;dZEjmIC-*Pf{bPStA(&N1td_n1w2>2;`lnsXY(mab=gUO2@;l&T^ zOB-`}zlpbgWZxM!Ue>%4-W=2EQ|URYmUP3xc|Ocdi5T#OTVinku}Da(vq6mvh#u#{ zu--Y3jHE_h@sUjx!#5&02pwU4y=RdfHI^aUt4W;0FZ%52q8ZpWd%@C08nlO3Q|*KT@VAU zg-|F^euY6arh@5!v{Hyx4B=TOEMo@lFqN8YZ*Cr&dekf__F$SBH8nkrs&KzZa;)aQ>GHTtr% zjgp#bYvwsg((#VfwbcCEx}tlCAwS-1%1W>@s(H~in@cahIMeesWv@4@y{hu6y# zr^AHEt6WX19Q4|+C*wHTpE%XhE?6J_388gj)3a}x4@ek|bYJ!BE)V<}#|8-Su_)n7 z<8K-ov$T|lSF8RMzF&?K#V3|9gU<-a?;KT#Dt8z3EOyqPWaqs-f0ouVL})FEBEPH_ z@${c_wAF&9>=(nt4dp{T4nDf9F13IEjHb>)ru8M92f52wOq1NiHQ@!~kadQWr_6TF z%}x6lHb+dfXHpxJ)eX=v?W=n%xj}b$ZPtSeDwP+&o(4mXqy2C?sW#nn&t{CG4=| Q3=5S_n^O&olxy_<0;Q6R2mk;8 literal 0 HcmV?d00001 diff --git a/certificates/roots/TWCARootCA-4096.der b/certificates/roots/TWCARootCA-4096.der new file mode 100644 index 0000000000000000000000000000000000000000..6927c52beb79d15a2169b05277faa8545efa2f4e GIT binary patch literal 1349 zcmXqLVs$iVV%A*1%*4pV#Kg1DfR~L^tIebBJ1-+6H!Fidpdq&bCmVAp3!5-gNVuVp zfdGiZCCnM(=o#+lr|ax!C}6+`65|$T56aIkQ2>g_7)XIcn1zKy!krxz+;j4i5_1%w zvIcVEyoN>wW=7^fY+-C1CC+PXU}$7)XlQC`X=)io3oDzLl#o5f$jZRn#Kg~F(8R>W z)WpQduz~gViPt?x^12k?_xa8#7ERNmIUn)RtK?Z`WAM)pZpHeX=6AMh=7eH!2C2kr^_+D4Y9K~@^g zKdQx!N$g0v=B_&N+y_Y^-?hnKFWZ;KYkpX0AfvTl#xl{p@BT`feRwp{x&POxYXa(? zKJV`y{McGB`_!uyQOY1`R zeMUMd3~I@VW`2v^w%gZk)?Jf3VbRn@=g!}1dd_YlIql^R#Z{Vh%PjWwX?iK9RmyKZ zyp=Qk-nA?2ZlASoJySAIINi97e*yo?6I1K=hfZXzI&Uj_Apaic6vpQ3CemjdmVVeV zJN@d6iPpI1TNhkJk?$^;|&1cG< z_kPcQtv%5P0{R^b3fnjNZf9B9ve;<-x_8;)-J3T4%Xv7Vr(?x*k8>w{Pk&}RAD_kL zv{6p3T)%I@vq^kxe^`|+sXa6dtTnpB&&15gz_?i1KoOjjW%(Hy|Ff_Fvjm#~KQJN7 z3WNBp2FySTIT-=-2QV2iGQ^uSmc5@Qd-dton@q_qVh7hPCmmCXs%(LY@?*Cio$K*1{dqEE#hF_Y?yr+ELzj>N*-wy^R$ltrg zy-BxpyR*mS=ie%iwZt|=CQSKLF{9sRa^PEs3GDY%l2uOo6|ye8K1Hg-=%Z4J(z>O~ zZU|-iBrIlnr~T$i@+9uKefnkDi?^xm>1V#d^~op2ZLek0(`m0wk_9!+O#Qg_{rfu& z5gsqScf3kn^YTx_)~zR8f37(=|K`qDNgaJhK6*C`t$o(ra&6wB*Ub|1vvy0XBp4T* zdGp=qbIi@k+V}I8{5z?9SmmAQq>Z){{ngs`rWLCQzgn^``QX~x7G@iPiZtwo)-DQ}?yr@z>?& smRW6OHuf*O_&g?rG4^!DmyndkVdA|DJ%1zpA7g){$0Gz-*d;kCd literal 0 HcmV?d00001 diff --git a/certificates/roots/Taiwan-GRCA2.der b/certificates/roots/Taiwan-GRCA2.der new file mode 100644 index 0000000000000000000000000000000000000000..ce32bae49bd43888cbf2a41abe9bfb8c213f4b07 GIT binary patch literal 1359 zcmXqLV)Zs?Vm4mD%*4pVB*?JMyMz6a^1Bl;LTi`tu`T>$z{|#|)#lOmotKf3o0Y-9 z-jLgXlZ`o)g-w_#B;3%zKo7*>;!$_cFH0@T%T3KIQ3%SDcA zFgG#rGZ-{6aWOS9F*0oXKi#HrA7g}y`uaXb?Q2Do42-1XXV+Z0QvYIMLa{-(0K>0< zX)6B$p7mHwy%=8Eay31eN2|$BB4&qyn$)$pW4fDI0{PzG=Sg;deME>OPF4-6O)B`$%lp0j-J@Z1&*b^r`IpkZ9zA7Pap_#Z#e}Bhxet84v#)D5nd|B4e5G!$ z?xR=73sW07o|w(6Ea0+f*L?Y8(v(+hlQh*Uo~^xZ`;v=0?#qK~ZF6;tPIsq-J^Qk* zV(9`);|QBOEBbr4Wa<9xD1JFLpqS;pV27R4HKvl^I!E&NbxA9ew=*bcRE=2_{MFIE*~mY&)dmYxXI+tei^?*wm-~Xa-E5owNRqX@6p3m zn~Nj!;^uBS#Ib&T%-TIMppaso+#O}tDNsT zJv%mVv%#gp+;eVSxiwzKF1LjA&AdOo{20iYdpm17pEwgUBLm}NCj$oqeqhp-6=r1o z&%$cJ45SQXK>~a%Vk{z8(`6sbsnVHq`sj@3vg~SFZEs4>8t{Rn`9bPgfVqVYIh6sk z1~8Q|GEA_3dMMaQugJk#+j2tb-J`qF{miY{hYHJk3}Ze%zO|F9&HcneTlU2^%Zl@+OnjTC zV)gT+!A15JjkRjEwJrDCPIfGeR_f>?QVQo47d+j!Znq=1b zx;-lO-rbY_Sjf#^urz#g-rO50I|^nc1QncEdEx)DId26LDe8Py0Fxz>F|HO8nv?TpZ~fp dTACNSPVdZlolcWm-*}%-Tp{pEeD0@jZvah2Q@#KI literal 0 HcmV?d00001 diff --git a/certificates/roots/TeliaSoneraRootCAv1.der b/certificates/roots/TeliaSoneraRootCAv1.der new file mode 100644 index 0000000000000000000000000000000000000000..e8b22b7783eec2b75027fe83d32db8f9095cc4ae GIT binary patch literal 1340 zcmXqLVzn@6Vpdqd%*4pVB*-vzpV)%$dTt-9Et`sdb)TJPz{|#|)#lOmotKf3m6gH3 z+)%_oh>bavg^PzfBsC{9F*rXjwJ6b0-ar;4%FH8%B&raUpI@Tj?5I#?Xdoxf3)F02 zXkln%U|?zxCC+PXgv2G^;3g&|WJfZxGB7tW@iQ1SF>x_9F)=b6+V@)hgW}@PnQEbR zbB~6KO^o^bUU7eLLzV8Oi9N}NAKs{ZIK1>yQH?e<@Vz0PCX8iqTm zrEj!+;}5ofRY=utT;XolsXWy{Y(o8uaCVR9lI!-nrf)QtX4Cq2@8_D@=HGFi(HN zd>c@`(x6xJGG|{#dhC9i=@P-aHIt5>iYq#JeA<=Ux(l|*XEMKe^(f#YkIjcQpM!Nj z$b5a9V`*93Aa){XgYwx2c6aXDxG&gk+VyBgM)$s_`-|RP`nB|}(Az&VBvz`G-O=zC zP>{J?FIKMmHoxJ!=k8$E-LVgR9XqGfJf&^E1FeBrC7FGjhAZ5S}65wZH0j7O6aQcB@!iOltqHAOG%m&;Q4F z8Mgyf{th}yrXM6XUdT?@*|6fl0S9x_Z!Iw~kJmd@{9AsKH{ca-OWC);_szk_s{ZqZ zdFu67UE_JC9`e|iE1@Xq>_ql!OZT6cnf>;Nf4Ikxsp0F=#P-9lpd|>wN zn?mqo@d6X^xyc!F*>4W}w(Sr$(2sTFb$7lhy(*G#XG|}f$J&zi_~U;JLmY)49arR= z_dt&K;el%B)(JCrJkr8Gor?YS>MGDT7>e=pv#tH9y7 zy3GC~VZpzWQ!jj$;S>9s-4@|1apehb-_p6!6YrF%1lS+b`h9czoUPZMUAXx|vRky! zW9{}=HzGT(OxQ2B`R26VoY{Z*Tj`S0X}MtlozF>b literal 0 HcmV?d00001 diff --git a/certificates/roots/Thawte_Personal_Basic_CA.cer b/certificates/roots/Thawte_Personal_Basic_CA.cer new file mode 100755 index 0000000000000000000000000000000000000000..de1f5481de0740b5300a9d67914d7d85ca4df92a GIT binary patch literal 820 zcmXqLVm2^nVw$;tnTe5!Nr1OcROsQF-Q~R&k5%sX7<@9|W#iOp^Jx3d%gD&e%3#oV z+K}6TlZ`o)g-w_#%F$5NKp4c~5atO_EiOqd%2RMoEJ!sJG7ta>vkP;AxC$Zp<#~ou z1`;4KE@8otjKuPiR0Ze!yyDWFlFYnxLk$BpkQ}$LymM+%NoHDRa$-qlex5>bYEfBc za%!=HOJ-SSF;K)%(Lf%gl37>+YDz$AQE`4=Vvd4SVsU1&g0myoFqoq`8O05M#iR=rj}8|%(sp6kzXGSz$)T z|17Kq%s>j+&A=4M40LRV^}iiItDM{f7c5zn(t6fIX3o{Fz_a=XYd5l=zs`8i$bQFSQJnTEybGuk} yC@y%{RJ_tnKQl+QWaZiW%dh`!HDH-y>a|?jSVhN0>@C-k`wgp7rS=!9eE9##2f{;qSVyf#LOH8XGcSA15LQQIT^)d z3ZRN~)1ZnRO2BT=OU}hNYhy=Of1~BP#=Q zV=pjvJDD0A8Lnhrzp`OUN_62%_ZvKc+g=q-+|UwNtIOM8Ep)$CwN#_T%1I|#eg4#H z@Aq|*?XqpJ7T?`@Zd!`eA(1?nH8s!rU-IKJ`L;u#bFR^EOZbwp+-6Ehb0K?8nZ zRLcr8GX7^_HDCr($ZiIvMrNR6{ni5j DY&jQ- literal 0 HcmV?d00001 diff --git a/certificates/roots/Thawte_Personal_Premium_CA.cer b/certificates/roots/Thawte_Personal_Premium_CA.cer new file mode 100755 index 0000000000000000000000000000000000000000..e2c6d8c0d4ea201d735c36057e327b7972eca741 GIT binary patch literal 828 zcmXqLVzw}7Vp_O>nTe5!Nx*@1Q}6;QH|GG(#(p7zvNs02Y@Awc9&O)w85vnw84McF z8*&?PvN4CUun99oIU0%@2!l8r!aU)r#U-glc?!;n1*wKY1_B^qc41BsS0N<7JkLkPAtjH&r=9aEh@`Q zPAyh&$t=q(28tLe8z_QQG7C#VO$kUXD$dVK%uxs^O3lqI%~f!AG}JQCfIFL$QB1l3 zsz$c}qQ;>F>;k>y{9FS$ab8O^14AGLgD7!cBM`^X$k^1<)G}%q`nYjEa;!44GB7vx z0%Nw5sj-paWZKOi>@Meb_UL_B_+HpGhxPtFb+JG*N5PyN>$m>|YK7)Ko$WO1UxMM` zwC%-K9_#!r7@1G$*vh-@=I2i?H?MXG-7WL|B=sj>S+45ijTx?f>;mt_oGv(*=6cRk#+;@uC~Cbb`qPZNW=@-Kb(AtOGcqtP7B&zx;0H#t ztS}?ve->5)W*~*^W?)KW20C_E3fGIzTMSRC=PxQ-pleomyzKzTA-}h`W~oTF|A|tb zQ{>BWe{IZRYn4XX@cwN=OO=@43+=tA8#k?AP0in1y2g4zkkrx@=50sZwNBl2{E_kX zkg%iXtPeaZ&My2Ts?2n|O8ZJupp*NN#qwV+9rXMV8=hUK-%(Tqp#FEVXJcZ!Y zqO#27)M5pf%(Bd4popQOfjmehv#4wUMbEp{=$O=R@y?Sa^xB2@GSXAU+}}%hm|6vW(avJ)x7L3Z z_IQ0;?>zDE^R}dxGWotg&ACW1@W$*5=@)kKPGS=&zB2jrbS;KCF@8LIeu)PC`Q(y! zOVBHiW4^xbC%u7YiE*8t?;S zSXP*k@jnZz0W*+7b~7*?G6Nl(I$=!*f7s1u1}0b3j$a7)IO$&Y70V7zrDMyIo0-4Q zEWfeosl<-htp3-UN_+OkU%FE^i&g04`l7>kRO^=b_K7cj&|d#=R@B3UJ1NRGPI|ro DjsX_6 literal 0 HcmV?d00001 diff --git a/certificates/roots/Thawte_Server_CA.cer b/certificates/roots/Thawte_Server_CA.cer new file mode 100755 index 0000000000000000000000000000000000000000..6dcb9f63b4e81c7fc398e002b387e707d271d931 GIT binary patch literal 806 zcmXqLVpcL}V(MPN%*4pVBw(`S|2Kp6K1*$k#hn&TNh>wrW#iOp^Jx3d%gD&e%3#oV z#E{#7lZ`o)g-w_#%F$5NKp4c~5atO_EiOqd%2RMoEJ!sJG7ta>vkP;AxC$Zp<#~p( z2GSrgE@6?7jKuPiR0Ze!yyDWFlFYnxh2&&I4FffhG`Fz4b81mZW?E))Vo7Fxojp=U$pAbtrpckE55h~-fG>dP%@=Wj=%KeOOC{^Y`F$` zqLNH6gAOF!_MJKJQ5KJj#o2%R9;a{?9R0U3TXUPf=Lzd8>MW`P)AgTE$UUIpH1oQT z^S#4g6>~%8#~zM&c;Ly+=nXsWY^lC)W_4(5nv&49c3viCMh3>k!Ulo{{J_|h6=r1o z&%$cJ45X0V3`}#(K*#QL$aKs7 z|0jT{Z{5V5YfZX(=c^a4l04)6g5}f|@oXWfYsccRosIk7S+@U%$BoFn99^BV;b&dt xf_4ebYWXG68UNy^foT?F!p@lu&8=K{x4xY0k1N(S^h#b(@=3m1>5``1YXIO35KsUB literal 0 HcmV?d00001 diff --git a/certificates/roots/Thawte_Timestamping_CA.cer b/certificates/roots/Thawte_Timestamping_CA.cer new file mode 100755 index 0000000000000000000000000000000000000000..a391b92b3ff9d9a98ca1dc3a0d683f97578d9d70 GIT binary patch literal 692 zcmXqLV%lKP#3Z?ZnTe5!Ng(~i!xxYD$?W|z(YkM$a=WJiFB_*;n@8JsUPeY%RtAH{ zZbNPZPB!LH7B*p~C`Ut417Q${LzpK#wYVg;C{MvTu^`n@#6Son%r4CBQd*Rhm{*pW zlap%54>S!Z$|cMel95YxAPo}W78ZdBC^)AUm1L%6CMT9;=I0s88_0sBnT5rm z(jl3-KwA=X3o`T46`UOnb_6a=bO&5HUd?Zs<$Wn`w;lt;F=@D-}xH%EB8&=J$IYP zW98QCD;*#BEUDa}E!F+$hjo{o>zcwz3|l5R&iEbw_Sbg3t{)xdOw5c7jEjX01P%Cs zK`txI$oQXy)qojDA-frv0+@l0^?tcZypi>HC70p+qmEy~LRP;#^mKZk#J`CrdF<3u zPA>FOPg%Z~adK#3p18l|9qBusrUI7A|4+?6aX!udj*rxpMmDD)`G;y7#l&|#D=0E_ zdEwU^{p9k`3y=F%Qw*PL{gCJ|lL|V@>u4&Sxn1q6_?d%}ao#mCkD41M{?h+FYr7Z# DB?sx8 literal 0 HcmV?d00001 diff --git a/certificates/roots/TrustisFPSRootCA.der b/certificates/roots/TrustisFPSRootCA.der new file mode 100644 index 0000000000000000000000000000000000000000..e79ccd2cbcb905153e1f396ce2f718e139a2860c GIT binary patch literal 875 zcmXqLVoo<`V)9?W%*4pVBp@xncALUamCI(?-;aOnSrBQ!%f_kI=F#?@mywZ`mBGN( zklTQhjX9KsO_<5u$xy;T48-9Q<_{?!3zuNw*>#I$_)oHkQ8s6cnOp%{? zDSFqx`h@*!Uq838(9F_*I*~i{|C{`XtGXxe`J@&0^IT`S#r{lA;_+ThrWLXhL}AEnQ%!rz;I7FY7@yY4M>;G(F_WXF_?&-N*c zD=~D&$!9NJlegTv=k4O6XX}%F^;<8An9kDk>v?4~L!)isL{3MmEe{`m`t{)?*CNNe zD<3l-?+~??xgs^?`uvngpk!3Kc_{J_YP6=r1o&%$cJ45SR?K?2GwzzA*- z+4ZYXwX!?hQB|>xyYTg<6uxf7bOTwC0zMWo7VOff=>{0=j0|-V|Nojw*3OaepSMAK zPhXG7f1L%l+@lY_Z`57S`l`eu`m>!M`|;ePnOvdw=PN?}-Y+=*_Lxh3$k)XW`ajf!D)nn_ zYh3&=*H1^fA^pu-h50;5iC3rpcYdpT@K&s*R;&G*)OT(Cti2QB@4uV>W&bT!G;P3av%BO}9lQ@tB&azZoN3ZDvRsBHGXaYoVo$HxSV&Q9i+dtb%5 z1#{ks`5N`&yQ>z{Ys19rn#Mloj@NLR*YWQ%n(^jLMAuTl1Q@_LeZ$Q$;;^+NU&P>dV42+8#=NdH5G7x6t)MjI3VQexN zVPavEV_|S+a5Ufs#-c1g3kxurv>EV&IKqsK|5;cKn1PgmEJ%QlMT|vcy$j1B$2yPZ z+kTczZ{D<2Jv(=DiGc}7TAoGMK-)lbf%*c~Hsy?xk^(Dz{p6w?y<%|6DFLM%z2y8{ z{a|-zM?Ii~fdJecqKqJW8IWTTm>7XE$jFc^#oo%bgCteU@ETpPw~##xk03Uahi3ly8!0l$T4KU-+-mbMhYN(!SU@s7;!Y zBmGXrjYoWQ(9+vWCr&(XemVcSI){~?q`cMgh#2wnmG<3FmS0v=o~y`o8ty7U!+rx+3#`-cjS-zs$Xa?MBB%D@}uzbC)a|lB8E0 z5BJ=Y6&jc>>b1|5{mIqR8RnG+BDXc?<{ZsD;~u)m;QN`F`a_3j$YlG8HN38>NOfJr mAhn){H#Eh>W5=YOAGZW(e)3nAzm>B_-sRz4<%+=Q<6;2Db z=0j28XdoxfYhY$*Xkcz=X>4d{5hc!RWNBywWLlaSn3_gW(WWLwC1h_fvNA9?G4eAQ zG%<29H8CcKLNJ9hCdvBMnx7u|k{#C$pt$2c?hZ^xOo6$kSTopOTgGERS%G`YXK zT_UVO?Z|~Y2lDUVTX1Ni*n$*6Z+vae9oueSoLUY zQQP}P+1(%bZ(okI-&M57MP<(8;?3XJhwD43&0Sftiy`Qf_u1eYcW$#*zOJ~?`sTf#w4B1*&bz86_nJR{HwMMLBxK;8arrN;P`P`MLVRAwNn<@qrWTvMxgPenf} z2-q}*Rb-v#@m@!Eq2eiZJj#lH_XyM{2t*Zqox!)}&CdF}Rr#@(Wxo9HV9j(|$y#_~ z`x>{?!20GVbOvw>8ur+$x`_& e*M1!HSv+f_`Ig?N8s4(=bPnyv*z=a@ogn~YA8Swm literal 0 HcmV?d00001 diff --git a/certificates/roots/TubitakSurum3.cer b/certificates/roots/TubitakSurum3.cer new file mode 100644 index 0000000000000000000000000000000000000000..49d447b348d8e6b747761715be73f327c9a08c04 GIT binary patch literal 1307 zcmXqLVih-NV*bB?nTe5!iBZsimyJ`a&7D}zB3qqZTp0Vf-CC<~h~Q%I1Z zgn<}{!_LF+o|;sZs-Uajou8bTnv-ehZr}=%;o`9iIlQMRJF_xX!6`E*Gq*T3N1-fL zAtW_BFFz+gD>GZcu_*EA{E{OZi*gecyi1Epb4!87gdCpZbYw$_qqm`lfg8vmZXWy4 zoYLaN90k{$)a;U?{5+smph4b6nFS?alTZwD%_}a+EIGWV`0yT}X`!y(j;@Bv28s}q zq`VV>mIS93m1L%6W+xU`=I1H+rWR$VR%IG`8F+vcG4nXWodD6U;C*;oHbRqvM`l%S zYKcN{;*t3|iIqn-CLh^Yd}JfgvS6Tp5AVrUFgB1A=QS`lurM+)G&D9hFpm=FH3V@D zq1@5nBrQ0b7?qF{BqJ*Wa}y&!C{=PXH8C9XFE_Ueqo zpU10mHl1d?ZM6T=>(=uNc|#9JTZ9+vC_PqrQN-Y_bVPLad(%$~75$E$tC<;}vvY^i zkP6iGJvcM!P z%f}+dBC@xm{bc{QC0yLAULXB8QF-oauP!44K9Dp&BjbM-7GOqaGvEjDg+Y8)17;wF z9Lm6K4-92S2HBclp8X~-x2sJOo5fo4-1|bVWzJ!>Z|8Ox?m2RQkJbUN5loYw}+MIXWFz`$jp0xOTFS^i+N#}jko3bI#;%9x;MIfD}=7CJ#_i> zr3;Rq)y%wRPtDa$ar7)IP58f`|EtBkRmZ_D`~ZENE*y-f~R- zs&}K%CNV`F;e`#G;&{A-=PBGsa#%g#Rf?DX8eT@BO4k+o?UETM94?F}s{gUvR(k+S;D7#lnZDBx+~h%sI%;rNrKv)2iaOa-V&7MN3ni3eViXjpmP4 XSG+azo2qki&V*ZURyx_N-Npm}F{kxH literal 0 HcmV?d00001 diff --git a/certificates/roots/UCAGlobalRoot.cer b/certificates/roots/UCAGlobalRoot.cer new file mode 100644 index 0000000000000000000000000000000000000000..7f3cc92dc3f404d224d183ad21351c5c76b125ab GIT binary patch literal 1430 zcmXqLVx45r#9Xz2nTe5!iIKyAmyJ`a&7D}#ZRA-4f18*?ZNn=q5JpP`@u zKZwI6%n_QG8B$bQTw*9;AO;d*7UmCic2scB$xlkmQ3%SD zHa9dfhH)t}yNO8&*{O`I49rbT{0s(7Ok7M&OpFY-Ha}$xu>V&4{fN_R_6v=x# zUp7v@pwT+h-N{SG#zNie%>SP`lGnF>em{F%vkPpvla8;PeDUW6lhZ5J z)pRr_OtKD5-Y(7;QoMS7%^R!L1;%R>e=DhNZd;?g@_K#lX%2-?>m9!ScX2PgtA1Bl zW8teZ%bx-Z7Wg_WQQs6Ps-2^&vRx&);=8j%6~C|G;}>h%oqC@~6fRkvx9Gt1n%$3u zy-(fVoz3wxa|=t+)x&N(%U}K9_50-qD<0Et{rv0LTEy;73BB_El=^mNo1-#nT3>Be zES);L?PFJG`j6v0X&c`#27@eacHvvQ#?B} zBb>zqXEDQBEN~VpoW%xbvBOy$a2BV5EXWc*7BLo)n};v|Xqc3KCiarmqU(i=wj8l& z&_zzhz#Iom#*7RXIx0_btoqJvvcQk?(91egkIsS?W&Oaz+WK*~gR`ScIkZA{8Sz~` zR@l06x@W_;mJ1(tZ7-a1qB48gQI{7^i`J^@hU-7OW~li~vNJ@pZhM`(S*C8D(Vi=% zx15T1_&sfQDBcu%|B6fTvLx=?tMXWTPSm^kTeeP^yGJ@ibIsE0|DHyKh3D$bT5>-rmoBcJtT)p^x5H`o%A8R=$&7rEj`)_I%%?CN1%5BAJ_&H+B|@{CMdbsKor= ztL=!)i|R_Q+wQ83b$?7+)49zN%;f1n~!BI-s0o$e zWLbCdd$*R|f@cBO49u=S@3shj56J9?_vD%f_kI=F#?@mywZ`mBGN+klTQhjX9KsO_<5q&rr~S zAH?Aj<_OKp3@IutE`bR#1BIL&6@v2fOAO@1c@0bq41o{~qQrTPEDeo}VO;VIZDLeH zb{r!s19KB2KZ8LNBNtN>BO}A+SoTwGYPH#qep_(zooPChCB?8vH2&JlD~#L2m>DDc zzglFflpTuGKKf02|N7sKfBB>StiIk{;A=4B;=D~|yC+@S{Zc?9Q^U;V#Ydg%5j85; z>Y1!QG-f9z*ncs;m;3aUMv(uXm9oh-+`C?_JCfn{5<(sxeMCHor-0ZR1-f_D1 z%J&z{aep`Y2E4c?|9>5meYgKKMVr~zRZq&=|DLfi^2vvl*6TN)ZPj^{;C3dzZ^7#i zCPzOyNhGWjdh1py^Yq5bX;J&`MO~{%pB6p2Jm6EF^u1|;Udyg|JC`b^^_IV3YAK6x z5!fc1nDb<@Lhbh6UHlVEkN4i+!<4W>bH!d;XC`Jw2FAsWiwqj)8*l?7NtU051sJJp z20S2+Fbk^zGb7`FgJcj-l_ka?ij6~?4H(Dl%#3gr6P(2iXR*LptZ)_^oW%}jall!e z2C^Va_*lePL~hHQe$Mv!?_`)V`|R#0Iav>Z?eCDI5tzn+(a6YPk+Z$yRUzv_GqF&ivfs8pLZS_KF|hrp4Sl-2ta(+8*Ysst8u#}e%i&g@ z+GkuZ7v~@^9HKMl=~lkG;u`C+87~KEepQm6VEN@vQpN|HHupC>SY3B-=b1L;So&$@ z!V7&RO4l4;Gq2e8YTpq?p{<)^9m?1guB7bHbYtr}CqH?Xz`Nh8qPE=8zp8!u+jZ8K z8LShzTfW==y7sf`myYNwvnJ>5+jl(vT*&y=*?AGG>tPL6cGJgZ C{y_5p literal 0 HcmV?d00001 diff --git a/certificates/roots/UTN-USERFirst-ClientAuthentication.der b/certificates/roots/UTN-USERFirst-ClientAuthentication.der new file mode 100644 index 0000000000000000000000000000000000000000..c011000539487b8549ec3f0c05d22589fab1a8be GIT binary patch literal 1190 zcmXqLVp(L+#N4%jnTe5!Nx)?vPj>)=$`--PW~!>`Cp!&z**LY@JlekVGBUEVG8iJijR0P|-jhB+o4@kx^1oV5P5LUS6(OTAW%`QdC-8qL-YX zYiMR*0#d>(tQ#8QrwcN|EwiY&MAtbdGc~V7!LhU?14w5kCzfR9=P4xSr6{=OCT8Xs z$cgh>S{j%eSQ?reS(q9`iSrslxyELu7EwdbLrsiI$dSUx%D~*j$j@NV#K^_e#K_37 z$+C6Hr`pwy)=6&W>&_lbDBWY3`qN9webLS{9%r&!q7^S3Z=>?0EFd?d*c3ul8}DE3>NN zoBis~E%j*IVtJ)!9*M_%K4)%Rp(nlVilKteo~Ew8C45V-cRK$Oi&`&RcwI2^)~sFXd z!t{naO^eog?d{V3&&|2z*mVUK*C%Hi7D(d*=FVM) zvPT6ng67>{)Os|AV_C(sVE>ITwqF*RH+k9Nl*eo83eWDD|B_ky%?pWMd9xVH0Kw4TfJijR0P|-jhB+o4@kx^1oV5P5LUS6(OTAW%`QdC-8qL-YX zYbb9Z3sS-?EEXE#rwcN|EwiY&MAsv+D5X5HDAhntoY&IQz}&#n(8AEb#3)Lf*AT|F zG%|`B#4c}QR6-7BMpg#qCPsb+gC<5UrY1&4hK=73Ti9<|QGedDDKPy)?)*#tBR)T$ zul?RMsJKALX2}n;zJ1&nyKQ;y?+1nA*^4@UGu;0tWmwKLi?M2>(PM2! zc8k2jOXHOHxX!K)IC#>a|MpYus>{*8jUD6`T%94lr@Q@d=jGT1eVbOT`qr1(!FKdl zr{ZUhxtV&L##b+*8T=v9k z?~cFK=w0pG-dTJhZ^;EYv2KxvWiHJ1$!ngR^_+8b(wEgn3q7Klm>C%u7dP%SXxwJN z4NL^G{46ZM)OyT-AH)%6Wc<&7yha!W4CK}~M@*b|u^P@#b#$P`r;EdvcU4sAAIu3%?o zgtJ)TEH*fc9XWP^nFtuWj12CQ{P#+Z&78je&svSR(!STa>F@liwXgI1|901Qtn)f*-GL{%Ul@{QcO1z1bl!8f@8o>8Wn4;|Jd-&5{+~D@vZ+HX z_BrDdp{Y+@O*VID?mfSywZAlQUaggdm57JXvER$BrFwar9N1s5a7aprVp#<1bxyv zzTPvg?s&%2rp6Ol>Oa*xw5~=3OqKs&Efc=GR>U$%d)CP*le88q@%-;ptBqIIcE2tv fyE1EDAg@;7yvCnbtm6uV>IIDE$nBo{BW(o$-*t@E literal 0 HcmV?d00001 diff --git a/certificates/roots/UTN-USERFirst-NetworkApplication.der b/certificates/roots/UTN-USERFirst-NetworkApplication.der new file mode 100644 index 0000000000000000000000000000000000000000..e82877d1b464fe79a0c3b3aca04ba7058e8b487c GIT binary patch literal 1128 zcmXqLVo5P*V)j|U%*4pVB;c}-r#pZ_WsBftGXw7f#^naQY@Awc9&O)w85vnw84Ma1 z8*&?PvN4CUun9AT2E#ZUKu(CExPd50hFzF1I5DS0!6z|0Rlzy4q|#8%Kn5hiB`g|} zk*W|H>>3mj6dD|&;Fnrbo?n!0sAwP$lIIqd$S5f(u+rBrFE7_CElw>eDJm^4(M!(H zHPklH1Sw$_RtgRA(*+sfmRVF>q6;-b!LgtqCo?&*Br`v+*g#I4*V59!+`!V%!o!&Sj4ykRk~d#8V3q5iu+_CI%sHMDn5R#lkg+?1(OrV(knQ1(E5Gh2$7g3e{nC9PWy zB-RIV{KycU*l>F3)pyobUs_n=5+axPm=wL+QE~L5wUAeSU8?%dC80-m<~uJrDyuW| zK+uv3AJNSYGdQxHk1=kjs{WcSqhx>j{r?pgth~!a=UuvZOz-jSaA~7OJMv$&Ewe9J z{j^}xY8N?&fZuZ#Cq2o@TX5puqXws6FZExXGh*ql>D?}~*wjY!?!3e6rY~h;W@KPo z+&IyovCn`Tm^ftlSy+In_?Q7dh$GC%_@9N`$btm;Sj1RFezl#v{b1M2im%=) zu8H3NaQR`Dh>d|iNLrr7!@$kJWr5QIhc-KCGE6SYK~0AGSQ8&|+S3E-L5?+GrUAwp zBg2xj&ol zaFR9N`+95jl*5NtF3`PyQBz*_U%&nC6|P$K7xO|@9_?oOZD_ym#hy0~+CLbtgjqZ} z<I5a{#VpjZd>|C>};{2{f<=i^H+kUKCH=` z@6XD^+_=0&^GMX*l<=ap*5}P7md!Y}mTk)&j>RljHJ41AC6w;fli)h{qw=f`40AHJ z&Iq{tzE5vb>P8Pc#eJd%TD)6%7H8Y9s}KJwKdt6|{@o@6om6QDud^9Di{2ELy$R`) QZ{=ak`nAkrjr@@o04N=tZU6uP literal 0 HcmV?d00001 diff --git a/certificates/roots/UTN-USERFirst-Object.crt b/certificates/roots/UTN-USERFirst-Object.crt new file mode 100644 index 0000000000000000000000000000000000000000..3fa090748822fe7819dbbacf7ba9a926c5d5b9f2 GIT binary patch literal 1130 zcmXqLVo5V-V)k3W%*4pVB;c}-r#pZ_WsBftGu;Q9JijR0P|-jhB+o4@kx^1oV5P5LUS6(OTAW%`QdC-8qL-YX zYba|V4N}4^ED{>xrwcN|EwiY&MAttlD>b>qKu(<3($c`(z|zpd*wDxzN}Sga$~7@C zHj5gx?rvgKLJnd^RtDxKMt%l^CPpr%CPqevbE_Kd7cWk%SY^l%I#qC6=!`{BgXr(CqYY+ljlL-z+fw_2l`4!?PF9zHIYVXlD7w?VJxXp2_U^JSDj! zE9)P3*~xuhl%AyTTrCw>ez2AOE^p5McWlSYvmECw=fD2@-4yZde_Hn~S$#yt@b2|( z7oU81e_yPBQ_$q=3$Ju8WY^pOkWt7W}Qv)-gm*uyOlfs^4qNCrKc}Owd-4!3P%-fU}~Jd z?*o5Jh(c0M=9P!O$9QKtGx7>e>#3N#KVZ>DmsMHk#jDQe^I!R)5*q)(M9eeIF2L<% za-oG`(vGB^pM%%tY}H;Qv`W&S^H$vR$;bLcIR1SwXpmUY*6Mqr_Ifw-zr3s8=ZdYF nq_aTz>70o{@>A}MPbogU`QX7qRt1KNy~07VE9}lP$e#cJidUEa literal 0 HcmV?d00001 diff --git a/certificates/roots/UTN_DATACorp_SGC.cer b/certificates/roots/UTN_DATACorp_SGC.cer new file mode 100644 index 0000000000000000000000000000000000000000..88ccd75116032a36e6c0b50064e76750cced0042 GIT binary patch literal 1122 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 literal 0 HcmV?d00001 diff --git a/certificates/roots/VeriSign Class 3 Public Primary Certification Authority - G4.cer b/certificates/roots/VeriSign Class 3 Public Primary Certification Authority - G4.cer new file mode 100644 index 0000000000000000000000000000000000000000..b75f420b93919d355097e2ae97396828664fb83b GIT binary patch literal 904 zcmXqLVs0^LV&+=F%*4pVB%t5$Pq~LriQgk#NMmCAn#~4WY#dr`9_MUXn3)Y4PZ@F> zaI!Invaks=g$5gn8;F89T*7=|sYRK=ndx~t3Z8k%dWP}_vLFd=VKJD5LP$|*afyOo zYDsy1QMRF#fdxc?p+>T%f{}rNxdKcj#0Ujl1-JYng~Za5jQpa^s?-#P(&AKw{Jfk> zLstW5kX~kC8<-Xa=bXgiVg+M`fYPL#%w&atqRiaHqDlql)S{Biw9MqhlFa-(1xJWk zC6z$4-AxSS#CZ+O4Gj%U4Zt8uoY&aGz|hdb$k^1<)G}&#dA7_zfQ=m-k4%hgtlEt% z3`)#N3@ppTs%nC6rOf8jjkyuGW|Hkc#%GdVwj#{lzY^3HZZ>yj{t7uZOCl~*E9D;B zw_Y#nwE{M&wi7y7Iv*G$ZeAD5xV-va&8B^)QWF{4*4^r_zRx^XLVl4s6fFi2%GNK@pIP)mris19>_u>6l%OW;HWoibl%+at0q z$`{sLt1)FecQ$kH1m4>@9!|1+tDKk&8Rpn}SSnjaNQnwXX3cwlHFA?|kj~7)v&S{> cOKT-o7hb&g`M^_NE3Z|$%Wt%4-PIES0Cj2`@Bjb+ literal 0 HcmV?d00001 diff --git a/certificates/roots/VeriSign Universal Root Certification Authority.cer b/certificates/roots/VeriSign Universal Root Certification Authority.cer new file mode 100644 index 0000000000000000000000000000000000000000..1353d28fd986ba4777b6b6dc9e435bf611484f16 GIT binary patch literal 1213 zcmXqLV%cfX#Jq3;GZP~dlYoQNkrc(v!ivm%yPpV29hEiUW#iOp^Jx3d%gD&h%3#pA z*O1$QlZ`o)g-w_#G}utwKorE`66Om_Ey@heOwZF%@XSlrGn6-w1xauVi@_umLW)X@ zOBDQ4OUm<$vJI^aEFcODHIg+Ij0_Ac6ksYLMkweixaAiqB$k$BTXk78o_|azpsrq)Eec!%*cY5@6e|u7AJcIZBqj#T_ zx)?cH$ra{hp5`ufr8P1zZL=YjFZmV}?t>VjMT zh<(}}meruz%f!scz__?^lR@Kp1Abr{k`-oT{LjK_zzn1e_&@^uAORL&ZeTOWW#iCh zV`ODzXXIf?G>BgqyCB*i(jeR*RE#q-H!(d`KRq+eK+!1C<5 zHNAb=htD@;UGb36sg~3;P!&_oC@Cqh($~+)PtVr_rqj$~U{29X&d=2^D+Y^!Oaf&X zSw0pq7Lje`zcM}C=LZX2J@ks*sEqyMbaqMPXa(j(V6-wac>VaXf%%zEdi9ej<;iFA ze16vQ@!mPH({yKnfATMtUpdV^?sKh^KhOGEW;Au;#_~ODX6@Vf#8B~AZmgbD zw|7S34cGP=6OO)aGdO0t|HJ>op&iZM?^!3Y6@J<=WAgSlXPXi~T0HZgK0_<27XYJz B$!h=r literal 0 HcmV?d00001 diff --git a/certificates/roots/VeriSignC3PublicPrimaryCA-G5.cer b/certificates/roots/VeriSignC3PublicPrimaryCA-G5.cer new file mode 100644 index 0000000000000000000000000000000000000000..9818d19d00739f1370bbde9759f98e7294c6e503 GIT binary patch literal 1239 zcmXqLV!3S4#Jqa}GZP~dlYqpni}TcKU+nf$j5vEH+uF;3myJ`a&7D}zDf zDMM}pPB!LH7B*p~&|pJx15pr%OPDV#wJ0+ZAHEh*10$~Lqzuz)Bq)JWD;FfuSOQ-G<27@?r6;Fe#ckXTxhkzbTqm71bZTAZqo zpO;f<=xX2$(#tGt1Jk15oRe5wtYEAVP@0sJnXC{{l$o1YRH@*cT2zvmmYJMbl9`{U z;0Q6Rq!MVhyQzVkIIn@3p`n3=0T@Jy^BS8Om>ZfI8Jk*~T1E{o&o(hCAx9=7D+6;A zBR_*d6C)Q>6C)$TdKC^1%_`G*2|TNwdt3Y6so7)WDzjVr!9Pu=pWz&fQ(8sUzkXbM z!mu+|>4ny+Wlo#>f9wq1zHz(v=70Tl?BQ?TJKs)A5=}gxz`Nwey&n$_Cvn(@2*36` z6&cd1_EfuHdj9LL3nv~j_PpVooE7AKssBYmpzp=b%-!|V7D!E-9>m7D^+J4dU zg&V#sQvI}EW>UJu(=Ti+?OuN3=ynE37+PwSCm+Najefwa${%+|+ zV@X*Vhtnl0l8TdWiu_xn6?DA+DvRfn-emUZfO>87Laa8?dvn zYV$EONwJ9ZKfNr~wx+i)`|$aOtScT8I@OYT2C8Dp86_nJR{Hum`RVz3WxzaC49r7% z$@#hZWyN4IkV&AdB+JJl#v)RGId%D=yKi=XFyQ>`Z2606y|JM&aE$6CEUW{y6yd{%yxq52h)cJewkF(RgyoyG1RU z+`{>Nw|VZWGTmO%E$MQ}v5Ga*E5bkFR9#aRH`6Lram%f@>z}uzYEA9h+jcLmQLI^4 z;LN?hE1I-&HRO4@k34-Yr6&3Ci(tOM)~SD+*A#(ax4;xJwkvQ5H1Bj%HnSF1%xbNs~@I-k}E KUR&`tIST-5H^c1! literal 0 HcmV?d00001 diff --git a/certificates/roots/VerisignSHA1_1024_PCA1_G1.cer b/certificates/roots/VerisignSHA1_1024_PCA1_G1.cer new file mode 100644 index 0000000000000000000000000000000000000000..bcd5ebb39f00078c46dbf9bb8d52c067b104b184 GIT binary patch literal 576 zcmXqLVzM!4VqD53V4o@1IOoGGug}H*cX}*(a@T;DjZ>@5qwPB{BO@y-gF(C@w*e;` zb0`a&FjHu-p}2u4h{Gk!7nWL-8JwA(r=#GRm#k-KZeR+M;10D~xTULy+w z3j-q~V^d30%P87Apm9F3pBY&hm>YW;3>rI`8XFm&O772H9G0j%)1&ZP`n{dKueZ-@ zYv7v5_sc?cy<11q)8Z8iW~;>V%AZNioyZJBLgF{^MFyp40Kn7sHUY&`QlqKs?0SBzus}qv{4r*IKjjDY;*g0 zu16BnOq0&+pRHcm8GrH!=a+L^W$$b4eR{iXPKN4JgPLufqW{t_u6-D=#-=98yMI^9 zbsu(v$?WElkvY2nWncnjN#SKJ394=wLu+*Z=;LP+q9R<(4WIaQ315=O$x3HdbPGWJff{{W%X;MyR zvO+*nW^Q6prGj&6QAuW6W^!UlW`3T6V`)i7eoEl7(|Kl8d(@v z7#JBDn_8M$M$z5@jq{QH%*e{X+}O)t(Ade;*vPOgs(UeSmU44L_IbNzFyFPx)}+D@hf1 zmU*T7Pb_1QXJTe#U_^EvFiMz#?rONafWPD9(~Rhr>IV7c+aD`O2+DjF`4A!0(|y12 z<^&bNng!K|t0X1&7VTBo&tP@`*VU>shaM-ncAxfao^h}s^TNEirXExGK7Z*g^2v;A zpG>>9@m-ZpTAsMsdZ{`Kwl@5qwPB{BO@y-gF(C@w*e;` zb0`a&FjHu-p}2u4h{Gk!7nWL-8JwA(r=#GRm#k-KZeR+M;10D~xTULy+w z3j-q~V^d30%P87Apm9F3pBY&hm>YW;3>rI`8XFl-#zfBhB;Ca*vPIxNi^J{5;p?+p z9r{~%xGx&tyeWA89aDt7>UXUbF08BGFw0le&zrn+7Q-s#+G}fC7bUwMFH%4A#phUQ z;U&xW{!SlC?{iH!)~Ap^ga5}G<@f?kvn40no^PC`a5{Kt>vP+EwX^=IxEkLn6Mf6S zs4&GRRj)C_bvY9=BLgF{^MFyp40M-3QP4_O5lJHs#}7xdxz5z_D@vYyl71(CrS!8? zFN)_X-I$SA%$zv!Xw3#!hdh_Ly&E=8D@oMlUFmvh$t107vr4Du*$4l1otYrJLfhwO z+;Ywvr3Tk8r6$;>U-Jkp&9tBR)q~qTQz^4)+P;$~EZV%Pbc!WCGX1h^Qup)!DLB_L F0RZd!%as5C literal 0 HcmV?d00001 diff --git a/certificates/roots/Visa Information Delivery Root CA.cer b/certificates/roots/Visa Information Delivery Root CA.cer new file mode 100644 index 0000000000000000000000000000000000000000..9b66226bd6ad091d728bf9086ac719f3680fd7e9 GIT binary patch literal 1021 zcmXqLV*Y8+#Po0hGZP~dlR$L%^%XuF*5ACG@4diq%e6-aylk9WZ60mkc^Mg5Ss4r} z4Y>_C*_cCF*o2uvgAI8NxIr8)VU{q@U`IoJ16>f8TUaeDvp7+~Gp{7IC@--jGe0je zMZ?8OtU%i9~8PqzKf zII==*;=>z%bmlKnNVuwRxJ|ZmO0wXk7xof|cb;L+t77xp-}`6zq_d_a$O)UAHK4m+j%>%+%=Jx`6F(|Id%1 z*JLuJSMNH!<-<^!-?Tc%!~|-i)#(44fui4Ei25(_@9N`Sb_u;Sd0t|4D{Go(;I=w&_LBd zl#N514Vd8AnHa@54fTxljP*?PObvM8!b}DX27Dl`{2;SffV$WWWI=pB7BLnP|E^nQ z|I^ErXDw@}t-ak*+WNh*3ORy+DH#|+j0~KvTOF^mmlze5F`S>-UAOgRy7ZTIKa6kH zhig~yJT>pVt-2^tN5`&3k&TwS)ytId{gUTW+bb7TEth1;zE*YU02*t=EyuWTddzRe$HnhU2Fg&q=9 pe!wy>;~m!_(da{WY#*B2$8DTbE%2gvrqjI*N{_!vu4bRX4FIlJcVYkl literal 0 HcmV?d00001 diff --git a/certificates/roots/Visa eCommerce Root.cer b/certificates/roots/Visa eCommerce Root.cer new file mode 100644 index 0000000000000000000000000000000000000000..26eeb8a5748ffbaa7366b872d498a3985b8c32ca GIT binary patch literal 934 zcmXqLVqRp>#MHHbnTe5!NkF*G)K}J??bE@ZsjOEg$Rru?vT6C)$T`tW;Ua(N4H zC2X9cep>uCyM05e|A{%>Q=MWHvQ_capFNHKbC0| zt2Y>b*eK#Bn7`Fwy|n96ulIG^)_htZA7L-#mSEGn@ImeQa64nU-|in*iB4w^OAXf=!Nu=4olXSZNAo8-&j&ke%tZ*}+EbJ>I{ zSnB97WR^_z+M}>(W#vDHS zn=*O&yYBC|C067XZvL(#exXD)^ZUPSn<@Kzy&Ze}9u;4BJVB}0`RwQSuZqvPc5PVZ z`QN8@ZehofGT8~yvhV($`Tp*2!qSaZVucsQF4PFwJ^dRONJ3j!+24N2X literal 0 HcmV?d00001 diff --git a/certificates/roots/WISeKey-owgrgaca.cer b/certificates/roots/WISeKey-owgrgaca.cer new file mode 100644 index 0000000000000000000000000000000000000000..1b2d11a0675f00c4075e320ff491c6bb3029865d GIT binary patch literal 1013 zcmXqLV*Y5*#B_53GZP~dlYpab(eW?Y@{P{5A1`Ty+@EE@%f_kI=F#?@mywZ`mBFB~ z%aGfElZ`o)g-w{r*~3u4fDgps5@rwg3{LeNOCE1dsaR=j~#aDc&*6SsJwV*irO~8eTthh+ol)@uyJa$F|sf=nTs-l zOkh9`bYKbw209~y_rm|&?RlGj9(3O5@mb@5tlmjZ$6r$zWR@&h?djidEBD?vfA5|p z-#)1soD?`E+wr?ZQohx7?}nVfpJsKpzxo(iIr>MtpMSxvyX}bN+>)d2$E>sX*NEJ< z`BFS*CF^~LJ0%srewZdiG6_r6?D_4xK_S<9cY;Axx^c|WnHPWPS_T#W?pZZmHKyn$ zhumsEo5ziY^O=|ZKJZVoBlK3w)d1#gk6IQlGg~ES#rROd`f{XK>$?kd_wa+a0s9kA)Tc&12 a@YXrI^XJDLm3VVk|KW_2fA-zy;spRCq;fI< literal 0 HcmV?d00001 diff --git a/certificates/roots/WellsSecurePRCA.der b/certificates/roots/WellsSecurePRCA.der new file mode 100644 index 0000000000000000000000000000000000000000..1b8a339a022c1cb39661347f12f070e1466de771 GIT binary patch literal 1217 zcmXqLV%clZ#JqF?GZP~d6C>H7BQ7!7Z^UJzoLL4o*!jElM?%F^~eO;N}rVR^gPGm#yIEXlQ0&0+MCs z(M8gu5Kx+wlbNg#l%HRs;G9}il9`s7oLG{o;8>xr4@?O^iy&LCDC;z}&>h&tTBR$i>ve$jI<6f6Ly=NBta%^DI~# zRo}0UmIfmWcg)?>wV_^Sq$@xf3n>E%ugoJ14*1KKYM>qvoK>XU)my zx1Ub#7JRff?)A6cw^NHWwyY6Kdg*2Stl4NCYw6UzEmLo6#mw&0LTA?n$DBT#LURR zxVVYY1Q;R)2K>OZAS=ws_@9N`Sb_xPS&V?us<%LAfmWMFMoCG5mA-y*QI1|g zcBWoADAlEb5}jUhey)CbaY0dXq8?DzfDfdVA7mB_FfAW5kOlGiSj1RF)TT-b+*b#N3nA^p-mQD`uv&%JAiN|&59v)PJdt8zhJEaFB_*;n@8JsUPeY%RtAH{ zCPQumPB!LH7B*p~&|pJ30~rv9TUfNbyj-uMC^5I7I5oMnD6^zeFF8NgP{lwAB+n%* z9T5bSQwWAi0vSbRnaQce3Z8k%hPnpYAXUu5DiBrfIr&M6ISS6HMJ1VOnaPPInfZAN zj-@3T`5=Q0O%c#NO$Rdl&#n?LKl7De^TfDX} zTPwfr0h`#P+0i%COR{4d`ZedaN#C5qJ0rJDKqKNw>V|r+8I|)N95$?L(B9f}z`EYt>cf+t6IVZ%wchjM{FiK9lbS~!i86hk6J5^a zFYsD9WrOdn=POOBiY!(*p0SxCSo`|KvYzd2r%xGM-?TOF{#|9)rt`e`I#>9bl-ZK6 zzwongbgf|)mrVH*rK;3xqO<8+hOAKT%q%6Z^U;yNvE$; zee2q+_~+osnyX26zdjw+z5Mq|Dibp!1LNYx`38-1420P@wb>Y17@N#Rm{{24SQwlc z91XaENkW#Ng$0-}+YIlCR6+} z{UEq^yT@aJZ@l;IFP+@BDs+j*E~eY}BK1V0t>=o>x?eYc74KUnWVT!W`ocyQH-*JI zxhv-}*4b;GW0-vZ@5xEUot-K3o@+mmnW%GV=egQ*`GzwuKihXnZo&snk;)k5)xMW* zDa!lKtepGsy!w2B*)kox8@f^)4R`S6Oi)=eJEpLI*X}wQ>DyTi{EB;C-d?ud;mfA( zl^dVDpCxs{Hgo2?6&i~l+HC%?NpQ~j8i!|hpF7tsx?#0-W$!1GnMbY&JY@UJ*&<;5 Y?ugHqH|jM`he~Rix;Rg6VOHG(0Gwrz!vFvP literal 0 HcmV?d00001 diff --git a/certificates/roots/ac-racine.der b/certificates/roots/ac-racine.der new file mode 100644 index 0000000000000000000000000000000000000000..9b1e3e4c0561fa7cf7ec856f2f33a2fd4beb5dc4 GIT binary patch literal 887 zcmXqLVlFmlVv1hC%*4pVBwzppmgdIhrsl>LW*`nP8>d#AN85K^Mn+av27^#TZUas> z=1>+kVJ5dALtz6!5Qj^c%Q>~EB-1ZHH?!DK#y|=r$So}F=&TTwn4FoHs-UY7l%HRs z;Oq#~!i=oNKu(<3z`)SZz!GGofkBiwub~kVmsZv`F)AT@kdc*vxrvdV!Jvtei>Zl` zk>R82>_;g(T?@(uu5=XsI&wzizptpkPTO1qRg*;b>!KPmwpSNS={dB&Qor5r!UFj{ zM^4t&GQRgz&tsN6Tg~%DLdxTs^h-gLHL=2;$r>ES>fk8+)~Q3ud+?!KE>qA%X*_`))phD?;=w+csK|wo4!YL z*}Y|%j8{yYFL*OCGcqtPwl}af;0DI1EI$hiFqO0!@PjzQjEw(TSPhtglz}WrfR9Ct zMdU}E;^GyHMW6lHD!BWf6HBabUsDxw5ChW?Fo+o$)c1-^+oZkh`h+RkT>-8}az7ou zyIOhM+RR?@d2vrrfOAS3tB*!4)Ao(#MKibxSkA7wp}_QE{q_crNzRJQdRO^ZPL}`8 zpdR%Q~l-rq8}=P)2Eux z;rYLR(#A;#+e@`iJK#@fQ}I>J_>F*CX`B0uzZfor{-lD4A*Dd@z+I zDb?vk{^QWxQvby#&s=%ae|O;tUG|OF)nvH#r+u$H*Ey$a(yQ-*&*QHv3$wnTUl(~^ wWZ{gtQR{tD4{3(GpJj+&(sY37S<~-1OVUIZc^v;UFX`KY&oVmiZaDJ+0N;f~DgXcg literal 0 HcmV?d00001 diff --git a/certificates/roots/ac_offline_raiz_certicamara.crt b/certificates/roots/ac_offline_raiz_certicamara.crt new file mode 100644 index 0000000000000000000000000000000000000000..fc082687c8a277e9bfcdf731e8e53d564f056ad5 GIT binary patch literal 1642 zcmXqLVoNhLKtPqrVcx@G?A_F;bUIQ~j zLnCt|0~0eN%P4VPV*>*d10y3t6C(qosDX7{6O$5hU@@{XFgG#rGZ-{6aWOS9F*2;q z?pz#v#zUFo_u=z_(>U~Ya8%{mOb~Bd`SPuvu!;Mo3k7#h+Fa;8_0C&-^@Y|A%avJ9 zuUPcwY3Xf;Q%Rlu0rMDb)uJU@WKP$ZZ?AoGxxQF(L)NAn9bLMvB`dyf-f`f{t+Ps< zCB9Ljmcfp@y&^6`R2&;DI9;d+qk#?(4~mw z@qbgzA9WnM(ce}Y_fvOyyYZ(AbN%i;vTf#;8>f7_vBzspvqTizpU+pW?CKHaRQ>RC zTQ5tUxR7ynxQCDbZ8f>qXC^%F{+Urzz`t1Qf|bR6^XZSG?=>V|Zn!bA*(u70r87g& zW=(uXgX5V5r*phfT0H!-4Gt{(&~|&Z=k@8i9^F5g4+N#p7W#hZlirL}r<>PiJ-#4m z$g{TnYB*Ds!HYJv-~Gy6A?;80+q`>yxYQ$F&N9C-Dd(u}5%Cbo?dH96%qO1s#(niw za(?p~i$kC7@6G!CP&x6#3ANK^Cl-D-=wGsU(ZajIo9}&?WhCD`vC`n+O8MZ~!HYzL z?eEUrEMV;*z}m3}We(RSti2BiV0G_%&;-?VX0MXECOW(tQN8 zH~wfyVbIN2N<6y8TkUC-K-26c&DAE~=XFk0nBKSD>3G`V3on;k`>N1;VrG0Z3kfrE!Kq<5YvjNo*`Y z9)m$+r-3#bhc+89r?N9Kipgh`loVL$>z9|8>m`G-VsauV!|5gG=jx{vB>Ty2Ev%Z(pK3vj%@~&9fzuD>rvl9o_Js zqef?Op^Tz%`ogI~4yMh`{Ux`JV?KD6aWw|r^}I66$oT#2<)=%ZR-K+MG$CeJ_0ie) zcUvl-_&?(um#-3|2YX%DfvXBmQ(WHfFJIJ|?jh~K%(}4i&H1FqwyI@m`_;DZR@#^U z-!i;pSJg?zsRyS9zF4jEV`H1bOZ(HN(U-(uYW-^#7I%2pk(3&J)jHv2wat!`SL@A~ zR99sjG8Elzkovk_)}wOcdCNym4PuwSPFDWoGyPjmH#Hq_zbdQe0AT=Yqa<%H)y{(Ppe$#gI z62HCf#WN0zI@3Jl6gJOMjx1j3QoKi{azdE-=3|<5i}^olTE4G~(J(47U2|*4iPE$` zvwbYx`=s+{`!agwSAF1FJ?FjYG( ztNWrw(4uQ@g1`REk|~+jKb@P&KjqlhjLY7-|CgA{b=&WE*_Y_Hu*H@`-KSBZyp!Wq zx1n t`A0PL!p1+Ug~_GHGRoTPV{X26FHhjJ=9jy4;7$r_=bwseF*<6_D*@#&oJjxx literal 0 HcmV?d00001 diff --git a/certificates/roots/belgiumrca.crt b/certificates/roots/belgiumrca.crt new file mode 100644 index 0000000000000000000000000000000000000000..49b80450bb2df433e60d87bffe70c9a6006f0ab4 GIT binary patch literal 920 zcmXqLVxD5q#8k6@nTe5!Ng#roH78i*_NIVviTIySmjxK`vT)VgB58D_5-6*zS8= z;kCiUsM4>GE}cK&BQnD&V(oFkqYe&PQ9nzB)Z1Uqd0ObFq;pY7VwFMMBE_9IcmMxZ z^4gH`xpiFx|3oq0vd$HZ{%e)e3VwOZPCaN4@oLY_)El$5biDR-3%Y+PShVc4NUWsi z#{8_ym;dfLr2EFzp3^>J-=8b*8G0H`i}rt)cr`7lR$HT9G$;AesZ+JAYfj{{=Nj$H z*um#*KIp_YFO*?9O5_hFfQ|o@ZG3#Io*+|=;Xb^UVd`PO7t7eQXF zdgFRC&n@TjRx%l`i}`z^bH7vd^^XakuD5>+*Q=__5^j*a^Y}utoNb}u#)K>LI8Lqp zFy**MX-MN|>9yr^UTo^W-MpsXB>Tnw!#BS=A5IB6C)$Tv0^8=N&idvyZ4v0Ew_KWNkUh5`p=cW zXLu>!zuNnt=a`XhzW0y?k=UC#GG0(-VAevYd%rS3sd! z#Fp4Y9i6ulE_Eu}-@DEzVV3t$r+}Fy_5BPs?O3^_JE7VC(oz)Tf9OBFK3j8r{@MAf zc-$^_9G$yp>ijkKqU$~--hY2MdzR7-ox;BnvTqocSSU=5I)2qWd6)m}RsX`=^pbCK zD_`yUwN?2;r}RP*UbS0}A1wL}-m<8Fh-9R_^B z=#b@SWc<&<0*pvD1AY)+7{q5aUA{a;;$b!t^V-aH!Y3+Lb<>>Bxe38sk z?pAAlwBg$ zHSI;<`~APXRF`*dOV*B^5^?doV9_?YotBPbzM6YXgSl_r>*G7Sa%#EisVPw}H)XE7 zaX@(Aj6c)nwA6DYBS^>RxC)B6C~IJZ0B zPwv`kQls_x*p2x3kh!;g&k8>OE5g*A7I$J9gV2Kbedk2}?UrAj_di9r#zhw zt=#jrb>r$r$7j4poic;lE$8~kGw|85^OlCYtO(v>R+cjJPTp%**9IQQV*3f~9n IyZc(p0H$+TRR910 literal 0 HcmV?d00001 diff --git a/certificates/roots/certSIGN ROOT CA.cer b/certificates/roots/certSIGN ROOT CA.cer new file mode 100644 index 0000000000000000000000000000000000000000..f49be65d6093ff1e64e3c8771c58d744684ceb2c GIT binary patch literal 828 zcmXqLVzw}7Vp3SZ%*4pV#HPT;DptT`z{|#|)#lOmotKf3m6gH3+K}6TlZ`o)g-w_# z$lp-VfFH!+66Q!wEh-82boVoqG!O>~aSIE;gcO4O{X-O-9S!8fc@4}A%neKo&5aBU zOrpejjSZ2wlo{T{sD$iTMpg#qCPsb+gC<5UrY1&4hV8~X>rSY8^=-YqMMHX3_=Fc1 zl`g03x;**Cl{IaN4p|A|86hpcd$K~9SpVOjJxgm{EPKD#VU7CtzqNl=emuVRgFvv# zgzmJHD>_!Mk6O&|a^EhuchSYwI^s=@aY;H0nNm0JJ*v%6cjOPVaX9bWN59U+x?Zz5 zYr1XI!3%R5y;eQh#26#nA3yWR#Xudfua;QQC_ z6FuAQmE+e993_V@bQo`|xn6SrPRm7SzEaDDsty{jDo*q1=vmI~>CO|A(N}8{c=R}R z3Kz?PxbLyiKLj3K*j45I`<^)igH*J}<4bdj?Tp%IEIb*gfBoJXbE%*gnkh1Gx=NEz?}BTSYbB)|fU`(p;OAU+?97>me*p4qomJvV=>X}h+`sh#^m z_JW&FkV6@mB!HpJ$Y6I#rc=-K&yUi(&+1b*&e+0iG(t z*&=L3?>R3oT=>|b<>Ye-qY@jBJpTFKSH8<#p4^raGCjE{;A-gkUka0%7R^4aJlRhy zv}{2^W$sx;`Sbd^dn6xs82*TqYUDgIeObxzgd@>s!uvLr{*`9pyd9ZeG&%FTq2sj< zi~a4J_KH>hT=isMhw9x#b!C~YhU_e6TcjrJT~JaO(3!hOkv)9H?K?} bNnu}T=2T|}OW$wrHbnV(x`af;J2e9Ue~Ubw literal 0 HcmV?d00001 diff --git a/certificates/roots/certplus_class2.der b/certificates/roots/certplus_class2.der new file mode 100644 index 0000000000000000000000000000000000000000..ce76c058995d9991e6246ad479ae89d45befe770 GIT binary patch literal 918 zcmXqLVxDBs#8kC_nTe5!Nsys+ulMI0w;pGHn{qw=@KP6L170>xtu~Lg@4SqRtgH+M zwuamWoNUaYENsF|Zb62E2K*onmoSHOYEel+PHC~Bw1Ff@h*?<3IVZ8WSiwjkpeQpp zv8YnP+0j5woY&IQz}&#x(A>b(z#vMT*AT=tGcq={G_{PP)c7VwC1eLPvNA9?G4eAQ zG%<29H8C>D; z!N=dkRe8E69*~|{Ju{4V{kuzh+`}JNdRCiss;jiz+xX^Xgx^2E`%(KG*RJ6>D#7>u zQt-Q+3v-1Sg?sNbBz>Q{(xt{#Dw>w8>Z%|p5JE8kX(W_YF8QV|ai>rP=<)gISsgsHakIrCPwdh-P`RuQC z(?U&T(lZZybb9Q*=8uL-@v^QR2d6Z@!wQ?MuIWi~sl5VcFc463d-; zVYctx+UL(VosBt>HTB2RZ@ouiD>(L5vt9E%FKHH_tjFgr#8t7E R8?S8>xVn4#{zZLTLI4HvVU7R* literal 0 HcmV?d00001 diff --git a/certificates/roots/cisco-ca2048.der b/certificates/roots/cisco-ca2048.der new file mode 100644 index 0000000000000000000000000000000000000000..8f368232118ccd8c45c19fb33c7f8600af8bf900 GIT binary patch literal 839 zcmXqLVs zC}tqS#vIDRCCuxbS)81&5L{VYlA2p=C~Y7K5@!|`f`|v@=a(orJ1Q6%m{=IdiSrtm z05zK!85o)y8byio8d*ZPMy4i4QREui#HfJmKt@&u<|am727@L>4yGnXMurWucCKE& zo~wNMqrz=l(vqfBbhsZ&3T<&P+J9iR-cp&uYkTslSFGBVcS*Fv!*%YWKg}1;?Cg1< zmQmnUabHn<-j_tylcFcii`_C!?407fqGg5QjEdPi{ql8!g>ufyuGLoAZFofcf3r*e zHd~c)&R6@jR>)_CeN*5U44K|ox?J^KWL8t^`|YouKk6;*&ii!Ne_348obv))DHr^5 z&uO2D{+h5<-Mu&SOZ_?Nf_nwh3fJ<^E@NC_BXnt{{etYc-F*t(RTCd?&3L!q`4PsF z6~WxvUbFa9h4`9$`;z~@e?433cJMOcg!PANuOH75SG`jF+dU#8m)n3q<5Pz#$f0cm%8>coKBMW1bxhNyZ1P0_F2c`*NkTWvOo!io~*l}e|InVas zQ+_T1N$*2yE|-eSym)ZT!+YC5A1lemunl4FB&Q{u z`ljA!R=2sD;mLPp?l-;H%lExDSh7am<ZFMe9!$3}%3y8vzW6=-QIPCpsgU`s1qZwe6Xcw^6XgCaKG!JuklPdh Ds}4@V literal 0 HcmV?d00001 diff --git a/certificates/roots/cnnicroot.cer b/certificates/roots/cnnicroot.cer new file mode 100755 index 0000000000000000000000000000000000000000..d163190ae6e5d5ba70d6b762c33f4bef8ff419ec GIT binary patch literal 857 zcmXqLVh%NEVzOPp%*4pV#Nuhpz-YkB#;Mij(e|B}k&%^^!NACn+klgeIh2J>n914C zkk5bz#NiTVb@ub~bT$+=5Crj=g}K0dg&=?b5Cb`JUITLj6GJl~X=!K@CC+Pv%q7dr zCPpP>r!lfJFgG#sGZ-{6axpbAGBR8?{cc}ezV=0QvG}2j`ENt_aq;gZv;l=MC z&fjS5(fV~(jG~f&&e5iGw;s>RGk@5wb7v<{)UJ-u`+ry6mN$IG`0>6a<3ZuS9zlvn zLhs+Yu{oq{SINfhwbu{4_!fE8_r%_{@*=nHN4TgONopOhtLs~5vB99)y@=EBgTd{? z(q)>vGt2zKe@dq;njE%0e`eloE|xihj~nDqCr=UJTKO=g$?#{7`rBnQ8NL-vmiV#I zq;2utszVZ$->Ong&rf*0*Ld>$;MK*}&t{t_=*zxeDVr>{py4*N{!cZjwoARcSMCe4 zYESpz-M?kQ4YhsB@x|u#YR@LIEUrJVuzdSxt5c_Eo@QcZWMEueY)}Y{5YB`)55~41 zPK=B!EX+&{><03{IFeOnkuVTz5J~-HxK``?_q##UxQ;U&rX*zh-S!NR+D}#ZTA-4f18*?ZNn=n(bx1q3s zAc(^*%;i*+Sdv+slUSAr6XX)+a>*>tOjk(ME7mgc8JL?G`56qF7`d357#SHReKR~*+wpfMwg{g~^_rKYLswJJck+j+o0Y^m5tzxRB+mi})k^KOPbJG4rZ8 zcLka&DW^FrZm>yN^dn1@&;E7b!;qDC*=Am!WfRhE$!yPm^xU!6%|%QrOuw)Gs!vmX#;RjXCzf+syq|2fG%$=)1YoRimBb&6ZQ5`x}9=GF*7nS zE^hp9(D(-&QL@5}jQ?3!4VZzHfh;iQWcgUcSVVd^d1lNl;!xdrK>cgLtGeVsWu?>P-2WRjMVeMC_UMcMv{%#r8hPw}1Kajlo|mc2w@ zy-`SAI9_03*}1N2^H+y06Pc&ZuzH@;p~~^6GK06hHtENf_}@ow`0S0?WA7Y&MUK(e pCV8Lo`<}B=0Xs56esaw;7G!uh?~q%0)7MD09z~ya&a+Qf007(-bTj|} literal 0 HcmV?d00001 diff --git a/certificates/roots/entrust2048.der b/certificates/roots/entrust2048.der new file mode 100644 index 0000000000000000000000000000000000000000..ce27297ade38c499c2db43ee85c55863b024de67 GIT binary patch literal 1070 zcmXqLV$m{aVisD!%*4pV#A1d#AN85K^Mn+av27|^eh9U++Y|No7T*BP0 zc_l@q#U*-qsU?OE26iA(ZV~hH@^ZaYgp9s(KybW~fr*7eW?piBQGuR9Ql&ysYMP#c zMowmKW=XL^PG(|~o~EIyfilNcj^BP$im;<>c zhNgx_QA5>RO^iy&5yZ&Kz}&>h&tTBR$i>ve$jGqP*L$T<+oo5G71%|^Qna+aFYf2| z^6h)uP_{IEdxgV+Vy6=s2W|&z-;LW*Hp6ssx76GkVJklQ=clYYV>rYfPC8%yV7_b z|Jl34^I%!0r{v!QEB1CSPS-y+e@~%g!VcY+IwvQTrBzRPw7%k6YH+O0wK<#4Ycl`T zUlOqCipM!tqtLFun^JuEp3Gn`yZ1{7b3a8l4 z0_0EzW&>a-Gcs7u?hl)7@H}{CO;zP`-|5#Sr%w3ICV$Gf#x1#jTAIo)2Wdt1Q_qTu zKl%SNocZ?zk55MMv4$q$8Narzy%lTw@m$_FQNbxqJn!tMt`}U*e_j8cJad1zj@-%J zv!q<6zLxM`CV#dzTtI&|3ujcz*1Q|CRu8YuyO>iMS1BWM^zj9s$=0bhZ|~dgTlRFS z)Zwj?hxf)s@BXj+K11@f&}8)(X5D;)3v%0}*4&HwesR?b^=1Dm8;?}ZG!EY-v|;4~ zr<}>B!tVXcZQ313?^lna{o$tXR Z8g_pFN9~%pS!FLHCmgM5HWf?_1ORo~ir)YL literal 0 HcmV?d00001 diff --git a/certificates/roots/expressz.cer b/certificates/roots/expressz.cer new file mode 100644 index 0000000000000000000000000000000000000000..ecdaa6d54de96a00de2e3d09d975ee164e4aab40 GIT binary patch literal 1363 zcmd5+ZD?Cn7|#7j`We@n(TdV>HtD90rZ?G~Zh~~Johef?l;ED*srYK#7p_^m0)%UawEB)bbf1P{Y z_j#Y^Iq!YX(Q@{ET27rPD6%BWQcQC?${xx4@_#!eNwwRw?1-mAD|0B_s>3Dwx;@p} zIHVK5S&-Iu4t0&vwl#a*Atfk)-u-GDR4(&_gX0Glp6oMr+Ho4YkglJ2kKOQK*01 z<2hLC^oXstvi+aC&yKC`wq&;{*&*oo>vA@0o4tOP;x`_wKhuM*&Wz0;srd2G(AoFT zHSNlMzmWdXUPe0eXx3yyT!%G1Ji=LOJ1t5O{*#pX-Ht5F4wqGTSw=<1A*QC zz(y2^5u`Jg#zu%BY=jYqK$;O`M&J_~5+W(CNAwWp0*F{T*h@kjfto=2S00C!&Mt)e zKmrFT@W3(t%et9D!A#K;fI~^P+O2!_4TASdfvZzBKJY`Ocd-0Q{zm5b`SIyX=XQK` z%s2VMrQsR7d+dwO*}pcguWFc%)ZTt?a?8Svxoa=A7wGwqhM!G-FjqJ^=f1fxe{r$n zvC_)VuO54K)6KRA2HLlN8kih>`CWhA)SG`yo&M#WJLzW@!v)t{6B9L~*d87HcIwKh N5_$V^b!eM9{V$}2;6eZZ literal 0 HcmV?d00001 diff --git a/certificates/roots/geotrust-primary-ca.crt b/certificates/roots/geotrust-primary-ca.crt new file mode 100644 index 0000000000000000000000000000000000000000..3a1ea378bb33ba1cf08ffd493a79f2491b6b8f40 GIT binary patch literal 896 zcmXqLVy-c0VoF)S%*4pVBp|V7Yu4Y)ZK77mIqPrzID}zCV zA-4f18*?ZNn=n&ou%VcN2#CWa%7X7iE@I8pw(B8kiXx8krk_L6kVJv6+Fnp_!4fsimo9 z6b)@|VpKx*CL=2Ya}y&!gFzD`7gG}>Bg4KOqSgPe)YPW0ZBD5^;S{WU|62=(LgF>X z$gDXog6rRx{heBOF416jRdYPkUdFUj??ij^7aGjjyRdcM6syl+9Snx&Z@kNz#&q*7 zbI&HC~nZez!Rl-3wg-;U$kcReV5xt7&-?(t5K2fH;+Fh4YyoDvsw zAhJNoG`yqh<5aHZ>w64~8BN~4cPo65&9uU_D0}+sv`XVM*L;rK1e=#qwoEw~V^H#FekA~})XFgo|aNm{C!WpJk`zF6y zx7KOXg!~786n#yTjXOQB&GtKW{J9?|!}nXq-_J~%S-x$mQe4-9)n9g0%s6EsIrC)E zyo$5lYt~CHC>GNFbI5U5t7Q*9neySsSMBewPF1*F+cEL)GG1*d5k|X)4^9iFvd86~J>$K^ XwRg49i_Q0z`$AhTgR`Q&{y*+s=?M^(c^~lZh~D=Te_Cm7jYHrTe3bCn+UY_8xc>PI5*uOYrvT&=F^d32rt=+6WJIlK_-j-LG zxSBIKZ^F51^OBtf?h};)lf^36ZCvN5#&JSY`=Z+_k83Gf*PBiL>u4R!k#zQAZ+(8b z=9^;1`&XZW=GRZ2aGr^ok%4islYs*`K4tkC8UM4eFf%c*8OQ=-QoZ1}SGXUY>_qu%TMa?eF@@E5@d{ox&{l0X|i75Ur&)wrZ`^=~Po7KT;b@RY& z&Gu)K)7+O^E$ivFDgWn|ygc}p;>9&}o{PMn9Zrwb-`vHwTW9aeRZcag2XEA0U2bUQ zm+Wl0o?}CzNzdgOE1gZg@waPQ&pi|tF{AwOcj-0X=Kio-wLHZ2!`Giz4O9PRN6abQ yEO$NVm67-#hXmP^l`5OQ<@{Zd#@BRr#_3y!T>SMGRDb%Oty3o0;?`BM_%Q%)LQbs! literal 0 HcmV?d00001 diff --git a/certificates/roots/kisa-root-rsa-3280.der b/certificates/roots/kisa-root-rsa-3280.der new file mode 100644 index 0000000000000000000000000000000000000000..23dca20c1df4c8df64dc6a7be5fe6858bf8a3d3e GIT binary patch literal 887 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 literal 0 HcmV?d00001 diff --git a/certificates/roots/netlockQA-01-minositett.cer b/certificates/roots/netlockQA-01-minositett.cer new file mode 100644 index 0000000000000000000000000000000000000000..6e6a95ee06f10df788c3d698e37b1ecbed1a1a52 GIT binary patch literal 1749 zcmds1Yfuwc6wWS51Tj#E#Yd4|?4XoE*aRJo)<>WSDk{$rwGVERn`D#Cu4Z?GNmVe_ zbP(IA)<@%GibJbbs^Y5%g&A5!3xeQps!CI}3?Ol~>{n6=ff8E`4zjN;Q zoqN7Zd6lOrucEdhh$Kjoc!yFcLlS(MzCTn1p-{-EWzCvUDnuDnAXlo%%mPgW6)yes zQwOJtCb$6cf@UNYCx!Z}V`d>Ci!<6mCS*7d6b!US;8-47XfVSpBx#0HgC$_7IwBvk zB2No0$hz$`G;wxKDm6vg3sUR)ip->04r7oYfEk>}hAeImM}zn@2J$?}(Z33wEux8` zqW>WuLPUkrteKm_B7wo2lB^;XGe||HP$?-Cr5Qa|qnS5IrPXS*nlX=mpDV3iV))Zn zNhoANULssZd5Qj{mmp-va^v=WKk?l1f{^VmH88aUZ>=N)uKTuxMO7WeH`oiSUaD>#m<3^6ra)_aaBGulcd7V@rKqmu_}>x3ICZ>C~AnUrzMp z2d3b7xm)pTOVh%z(C(_PYmpIK2P?Gn=>dsDC&u|FA6(qxsNU`O{~27=Ipmw3hMcpl zXUQ+Vju=pSqN;uE7JH>GZ~S*F$RJtMl1eYxNO{S6DiY7$Ff~E^B@d>Qcp(Wn6(+^P zrI;LhLy2*sGNj0tN%-!h5-PcuG)H+!!_;XRbJMfZXU2kb4`PAvWUv7QeWNT*KX_`M z^E@15fs6nJ$kQOt0}YUIW5eK;1q`B{0zixnIw8;50c79;8;;u%?-3bXNDmxOtbrJ0 z7n~eR+eKc2(l`m&IEz)P4Up4?SU2KD2JwhR_C(;q7@RI0VCF2)1bN6pJ1`>#I}I1Z ztp5j5%rg-{571)`48%UgB9PO=nGn`9wXc@lfIEU1?vWk_v7FN*0Um1u4rFNJu!5$i8J!az)0gfEX?A@J#t#n!xRtr zm-}%NK%*RxW*)(lz#M(^uNn_$+9U8Y=uZea;CC?mluD{48&3m^6rC z@+kSh5St-tP4&F53c`+y+VR?seX-5)PrDpH*x2QSY_%2=O*;LZK679zKC-#E*cWf=bUQJfw+){GMgK^E2 z7+q6vss59?9ggMk3UPnAs&RFGZ0EMn1ODH0^zChx8N+`#Ml3tho-unw*UQ%fZK{uN zRc=1OYp1XGKd3MHHm>kaVXw`*yPZspjSN>ZuV2|P zB_+D>rTYz@z-_OJCT?hntJUT0uNJ!Bs#>a1V&$ZhtUiBgwfFlv$#&VcSBvlNJU1;x z>X1mD%bJ>J{V#m^3*{XwmN6`DulV+JN?Y98R|n$CUf&d19Gh2F!?V;ow4O~;vwq$z zwX0dXEmSzNW*pymYw?VUe=Bc4jXEN;lZly;fpM|0fuI3DFsfyR85#exuo^G}DP%VT zQzJ9bvB%#`s`LBtb=uPOB&{VMd<7FOvXd zcBRY_U*oQMf9{O9OF0RJF^ksRseJrAkHKAjE3d{2rnygM{T2SQ>}JizA9v!F)i@_M p6kiaLzUREMS@qMiIr^ff{w-VG#a`OYb2qRh`^k@s=gJo~0sz#869oVO literal 0 HcmV?d00001 diff --git a/certificates/roots/popFinnVrkrootc.der b/certificates/roots/popFinnVrkrootc.der new file mode 100644 index 0000000000000000000000000000000000000000..9b0c306528939f6c01a86537a164faa52f41b86e GIT binary patch literal 1054 zcmXqLVv#avVrE*v%*4pV#LU>Xz<`&HQ>)FR?K>|cBP%O|LE~aWZUas>=1>+kVJ0_E zLjeOm5QjsU-7PaOCowO@P|-jhB*G;u5tf)*T#{dunw?o(l3J9Rom!k-TCCvgXsBtR z4pPD`tl*qlRFavNnVeXXnV+ZNSXz>iUzAx=sSuo6RF;{XT5Kq3AP!L~5SCb!o0^xG zT9BAimYP#q0+V7E76=RSR&dWR(^Ck_&o2R5U?3;XYhYw(WN2Y%Y-(&^5GBrQWDMmR z8dyXP5nnVhDj^3yBP#=Q6C*!^K@%evQxhX2!-iJTTPK*!FD!O5&ykj!W^gE~RVZEg z)9(4tyBZVJe+aL%+4H?^)v7O_RW-N#D_tko*w)3mNj7zp#fvRxG-mx4H~TpGYUR0u z&E1Orhk4gJ-mjSJ@mSu;<&RCSqC)msr4|*ZesSMJ0rDwlbuE>`I{t1-o*Qz@Df7Sy z|LYQu>`r91OtIBzI979R@AY8$*Bv{To!;FV{yw}cmZ$r2oRH&u#RHaK)N(m~S!`Zd zzVV&djSCsKw#-<%Al1z)ySHwYZ^DirCwTu9+P$-EZ`^Y8N8W^Y_I!!gWwkS&={~`-0{O`9W%ce8yu2vLHQtEMhDow_iS- zed(eK_n*~|7o@*hH^;mD%Le3t2c~;qz%w$et@Yp!5u6wCZawd8A$`RqXJ_wfaesDF zHB|ZWeTfJyo!fEW&xU*rRH;r%f4EWJbG^xh*Bj5=T*Mnx@8sQ)F#Wu0(RP1L-K6>c z3lD^bhw&ZBm_AW{PRb!oBgU6kPTbnjI735E;<(PA*RzAB-T!i8f~2nU=a0J!Z_R5} z-YfN9?@3kV_QP}AJavXw{Oyl?j#>;ftzyY4bC7FlY( ze5+2)Ho^Aite^I5yLaXP^hS-AfB$maS_K^E`7?~~)!?H?wXbSNfyPGVt^-va=#kA#u{ literal 0 HcmV?d00001 diff --git a/certificates/roots/qvrca.crt b/certificates/roots/qvrca.crt new file mode 100644 index 0000000000000000000000000000000000000000..77e783a39ac84e67b76804a293f287933df5a9cf GIT binary patch literal 1492 zcmXqLV!dF{#Ij=nGZP~d6N}ZhfNld`HcqWJkGAi;jEtBr`ux z!LhU?BfluKq|#8&KnJ9ZSy&Zr0zUNya^k!Oh6culmWCF_KoBL)YXst&L%9R*z$Qi| zH>RRp-BHPSaBf zaZs`NF4cM`!sql7b*JeU<~Mg8e!|8a&9F33u7IWF(ZMTLtFN!MW|v^?``f(cRoYDn z>5Q(g;ZiepeSKSITXXZ?lq_p+@q<_U_oiA{O}$_nYUX#pGTcy0?nY#)XN1Cxy4CS@ z^Iu-`ebZdB@_5dTcbZbLr$UZytePrYDCecw z#e65r_23f8xO}s-hZk+w{x8PjQP7?rF3!&;>}FzSWMEv}#1v%E#N=mS%f_M2225G( zjEpRX2KolNFunm}n_@;uNkOrdzJ7jkae-c8X?__ff#s*A6$8^ws$Oz_t^q$V?Z^r< zGX7^_HDCr(z)+R~2`R8NF$w}Xyghd51EWFXZ-d4wFguu-3>uG1H695{ z&B;v6OHNe)rp%IzR0UiqF;yX{QXw&~QlTKRs07F=E-uYYEmlZOPEIW-ff$emHUMZy zoYn*fg18s6q57vQZhk#p;#e5O`)_nRYxHiC5sdk zB_@|-CZ`tbfYqb83z3;p6$0{swp8jFD8YTjC?*C9Ibgt*mzTrCO)n|eKo%4>d@N!t zBHiA(Z!c@^WRrYjX}R*l^p>pC@9!Hlt^>&{votO+L^Bp5Y*AOI?*%#{F8~z=Dc!S!21sOf%>3oaJKmKfb$fN$D@I z+>H%=oMAiXNG1G>J$Sw9j$p-wYq1BnUtMc7li8~4Oo*zbVPmzhQs6GPoQ1pR{bI@S zR4eJfRQ&pk!J=ocB9+>IO#jOF_tlw6OT>-@NxV`#xAEh%md2;MR<>z;a*m1>n!85s i=8C6WSOK)aiTW&Cy5CsxFu*cX^eV{R9Air5#8B literal 0 HcmV?d00001 diff --git a/certificates/roots/qvrca2.crt b/certificates/roots/qvrca2.crt new file mode 100644 index 0000000000000000000000000000000000000000..42127f823686338b34166e3ecf1b2e27d84535e0 GIT binary patch literal 1467 zcmXqLV%=`g#5{iiGZP~d6B8?^0WTY;R+~rLcV0$DR#pZBS3_fS zS+nZ{f8&XDK9a4n9P?Ley0m`QZ(M66H^FWH;x;uYxqo#s5>_#D62!HvN}7!gY7;{Q zPrqIL;Mt``bzigdCAM>M>;8Rd_nzz6W`UP?4!Mc{i2b|d*8h2)QFERdKU10Z-F{cJ zwoH}jp=;^?R;LAY=V~NqzrUVv`1s^Ky=D_X*Z;UJD12m2dD+2r+nKT&t5&);KVp5h zGwk3L^L~%QWTiLasq9m`yzloPi{g5^;cpRKQ5UjASy{`B%+%#5C|#p|=T z)SbN&!=&wF`Eb+Jsk%<>*RO7#;JiIY_~X61-;Vs~w7*#Tb<*L9SGzhcOn7rA_g?3r z)WT`qyv%>+?2i^(GwJrLf0Z?BU$6fzcKY^NRqdzpzh}*V6nMren8)K8-`W$v5G-dR|#W%xw*>(i&VPdxblwBb5;@`C@y3;B2Hh>E_NzWLIkt@}Rp zOp}x9m(5v{Xuh+p*!cSNY4en8o0j-AK3aHjS9<(Z_QmRg@5BVE_qclbY+|{z`u)|v zJb~u|vN#NXPQ1m_pAy4-*s5E>KCd_3*6P~7+USmxalg+b-sv_jzwBaU%9+G6Nlf6z zJazZq){2jRyq1k-VrFDuT-><9pmD7MKQOh*3NtePXJIv922uvxAOU_B7GPFjGmr&w z_*lePM5J1h_IUUhtFl~qci|iJ5lOd;Q?d>6K+?)A=?19{SQRYvT;fipMBRj$D}jlc zk-?5j%y&Lp^on(bvHGm~>Cc2+n~#`%`+Pu+hj*)cO6-pzxHyn{qv1F_pPoe_1tOM zt(1S^$CG20FIhTl4)1y$T9w-{Q{`(8#fO!ZE8stQtdoHUi{U&JfWU_qL%Enx|r7HnHwxP z>|e(HG-ZEsGAS>-etE#u@4HUSe%7~$@#wX*{gsKIZDbzqY>J6paQNj7kG+zM1VtqC zHnmA-*m;;sb!?BF7B}bkd-WuaM-wGuE`3zIyGz`uX?kH}u;I%2-)fWg7d>1&S@ukq zS`??ng>%<=8^pF$EVXL)>Frv2)ouDG9f6&DLX-|L24p(V`?BeM?vFROK0e;~{{F=N Z5G`)igKCmTf&^GouQmz1I%IfO4*(18XjlLM literal 0 HcmV?d00001 diff --git a/certificates/roots/qvrca3.crt b/certificates/roots/qvrca3.crt new file mode 100644 index 0000000000000000000000000000000000000000..6410587fe66e459b9df9dee42a0211149212b348 GIT binary patch literal 1697 zcmb`Hdo0c$@Xvr zjIe^}8j#wug(fP0wp=+Jglug|HiFiu5+D;g-O!l6Rkj*=s}hXp|Adf8ICs^Q^bpvZ|&@NyZ}tuQa4Ly%u9p z2HMd}8&0Q%4v`hrfeH0kM^(Rx1|f=+M1fin$(5G$W(>=kS3tetM|~P zl3vVGh5Hd3{k6GA_fHq;Z4SK%I4NB;Fny!Z{4{md<)~6mkE#8Mon7yI#2dwaXV}|| zc8cc(&qrr{E3rnLWRnMdM8~COTfDJ-@g1#3XN=oSMSae^&6=R^#@v8YU`%ySfw>jj zKx+)OCb^%anljQBi_0BbdQ?~$rgrJLH<-T8?4%KeSpM~j9n?0~w!^oiPvR>22SnN1 zq+#A+Ri|qnJ;=V@bjglJs>lsB!*R-w<$WA`bx*G(t7x4y?akYO^^zoqkN)hzVHLKT z5nN)Ha8lT|&y85%a@gWyZC9Z*w$9ZmK3C;6*45j~y(DuX$6Q`-=!sLBBC%oY+{NEg zL`~N&7$v=_=3m$7pzP~>e^;8Ra-;pH!>*mbKVb6?Box1(#*klo0;-Vkg?h?3mpObe zJ!7xq%`)5LZABDlLGE=Zg+Hl!7Be6kKmkPp;2b0X(jX<-d(|WYz!C-vp=BGymn*j+KT(|@Z^=GFj^?t+oM18%Dr3Q#6@|dTFq46>$V?8K zi@-=U!s3z{OeQN5VX&G1rn1OiGxDFq&YW+LWDVNvU3!JiNLZd`w&@+2o@VL zfHr-;6hP7nMUcpCG#Zb`GdL8@iCG3TB%Bk-2sdDIB52G=E~KzLq7nup10DxyE(eMj z5=LdVg*Yy--Z?L&g&3aS>^oB11NK4eWm_8)06D)Mj?b+d@xy(66I%1{4wRVr9oVN^c;Wp@3U#VEKk9k5&Ov&` z*`vB639C=)7W2Hf3^rd&T#)+3H{d!R^1_rNbZB-*!%J42?|zz)SC*8bSxP$X6RbK+ z`XeQ-fAnKz%$DEy=grEQ z2Cb5%x7tZATk>Xu-D9SdTrw}Y;vM$7oHNz}bBt=LAd=((}N)@NO?`i_<` zM@odW)YGA(&$3njrIYdr{~4R1@VP8-Ab-d$87ERJ%;!CXa6}e>xT5P@9Q2>H`K3AQ59y14rKUh_j>DQ`YT{@Len*7u*uAo vT!v<z1rz7*%>{Ot1${J#G=MD2x9FjSRN_ literal 0 HcmV?d00001 diff --git a/certificates/roots/root_chambers-2008.der b/certificates/roots/root_chambers-2008.der new file mode 100644 index 0000000000000000000000000000000000000000..96b35e4f99bf06092b89952b539e427ec595ff2f GIT binary patch literal 1875 zcmXqLV)r*_Vl`jD%*4pV#L2MumQ&r5jq7e1@Un4gwRyCC=VfGMWo0mETxZB_z{$oO z%EBhhr=}_-mlhSJ=9MTUrlb_578ffdmMD~$m+K`b z=B5^Lusr>O*BU4TTH@K!&gib2?fWnVT3JS(qD28%To0xP*lqofVwn8Wn=| z9Q6z}4b(xB%)$!J8Hu?`sYS&K`DqHy`ME&zlT#If^7Bg+bQO#Y3@i-f#Cd_Fg@K`= zk&&gTL6kVJv4w%TF^oI(Jk-Rbgd8c1tPIReO#BQ6O-x)&O-zgo>lscLm}@sgd0FLD zOsQR5FD3uY^y=Q*r+Hn9?9?_*2-=lwtr3yGbaU>MWuNb+@PvN*_WYBQQbXLsq+{DO zA2#NE+W)lHC@W-vk!0jQ`R?ns32m(^`HuxRm)j{!GgZvq%yF|oFXem7q~L3O8zyvh zJ#O!1yS#S--=moerQ7&!&Ene4ofyCt^l@H&*_+e+7vy-)&or==IpQi1vF6(47uTP@ zI?Bjiel74BbA6Y`Qs0cyoiF#y^OG$6YUDj9H$js7_nEn+clN8D?Vns>Sy>#X%6BT} zb-57x=@duzqRFcR4!`CsOEI}*xxGw~lef(E$jWuLS?jmfrs_|L5O@<)v%c=pHi?@T zX8T2X-d~xRO+_<_f9xK-~-`|o|qIPdHw&8zdpCAsqV^GvwR8GrL}m+6_x zC|^nQN!yPcT)X~DrOK>LjNBX7$4vX&VDvl2cE-mA_Fnh)t)HTIGjx`CUc%huoE^z0 z*EPmSm_C@Wd!LQJxzf(M*XQSzD=xFOX#DMQ%g|Q)ap%_yTldyI2sk3txmkIZfMM(H zb@}ftj3vqhnV1B}@vT+*QNF-TsSrSY~wZovWH8V&&|u@xW&@Uc>`aVeG8rW$1y=g{1^GFd$(3kj z8FG#U7L&jn$;dE4XuXo@p~aRT^zOaf`m&!i4sw>C=t5wn@UB|2?h*7L(V zV>@2(uRX8Ke^1pa?u`G^gIjgis9cI*zqjaoW=n$c3jto?mC6@dpY~NRn`c`jTx9%p zRqe54d5$mt80%HeYwLt?-g~5-JL#CEzt}6Ax+=FTu32s?UY9n7EnmH$CPUcx+gyVW z`RbM`%32ftPS7;{H2J>C(qrF$yzk*p@~T;P`D@6J-fgqO+Qpizj8{h~aeQyu^-Ax7 z`>ZWnT^F-j-@K#e>R|oqPW=n(*B9TY-7sBZaMWr|_`JW8Zw(?J zF6!)T{d!~Z#uG~wpUMbNf5*4?zUIpJCc)8{pJWNQux&G9Iuf)_>C&A|icV6u96o5C ze8a^P^XS5^Gai@Cxy}f2byaS#WvMbpLfbvyT6;2(?xk%c6`u1$Qfv} zDM$3fQswK-B~PB}o%}aL-RaosWAip#h_+ZdJK$cO#Eh-3*54|(y!b9v&DQ+;LierR z$M;IC=E%2c$ab)ol-!lt^=#kOn9F9@-#Y}UBv_=g7{2NM+;r^T&d|@+h7+UiY~>JL jTc*mzTdmjrh-Vqw9yNhn^SN*CR`k>~9Q|;!+~WcO<#gK$ literal 0 HcmV?d00001 diff --git a/certificates/roots/root_chambersign-2008.der b/certificates/roots/root_chambersign-2008.der new file mode 100644 index 0000000000000000000000000000000000000000..74d17527c2ebb7dee136eef4496ec192d0e2e111 GIT binary patch literal 1869 zcmXqLV)ry?Vl`aA%*4pV#K~~-?B$nNYn9I#@Un4gwRyCC=VfGMWo0mETw};>z{$oO z%EBhhr=}_-mlhSJ=9MTUrlb_578ffdmMD~$m+K`b z=B5^Lusr>O*BU4TTH@K!&gib2?fWnVT3JS(qD28%To0xP*lqofVwn8Wn=| z9Q6#<4OBsr%))Z+Ir&M6ISS4hiMdIsMa7xvc?v=K`6UXv3PuJ776x+Syg<^zz|hdh z*wDlvN}Si&!ob`Z#vN+jX<|}Bju1vx2IeLveg=akCN8EXCPsz>_roqfv6@}xx<&Z* z|AX5kyUiUXrUtpc7N4ux(Px^&W~Aqy^x2bTf31tz#=*=+N&$uk-U8g8&zq2ZOQt6E)LKdBpUE3QjJu=D-{PHI>k<~Mbqz}1m9{tI z!OwkCD;jspIaZWjKKPFzbVGZ{3-t-6vOdOZr~jF*H=||0&dJ65FU}AYd7J#>)QpY@ z@tJR3nWxv;w8?e!?E5sar9ai=27^!Sc0=(f%_=Sl6@$g*TdP(w)~a3m$=4V8@vpS; zR!wVhYsYPhcds0-5*?YM!b<%W#S}wRwIw$k=sj=)G_TZ4ktD3B5nd{%VyCCJ|v%7oO{Yhz+wOM|W z?Ox0O>=)TmHb)n2cKY4TX&28CbUf+E71qN2M^c{rSlIl+PH6TDxhrPA`i0+mHNG{k z6uy*raN=%{119~BJ>EXIGll*KOqrw599jIfX5pugfA4w4`zU5X(7DNF^E{$cy}- zU||6kc5DW=Aie^NnSqIc5gQAT$zY&mpuxtW%?2#-*qIo`WHL%h3as??3-WU^lPl3m zG35LREFgjTk&&UHqrTwYB#oP_Q{4Vf2w(Y8|GpG&_OBW~8Bdi;^&4)h@--uaItqkd z-L?HXJ2)i&VZx#noIBsVj;uLm`tgp$%a7?#*Y9$Dz0e&on9#av0iB7&L=7L z>DQFCzU;7!o$*3(`NO@oPEsYa3f5=j1jKrt|NomW_L+|R^+u~mhONcf$qL^LT{$fI zz7*6s6hzry$aY#;VymIglv`Rfm9y6)`Peb#@JW;7Ob_<{B{qlT8 zUe}iJme)({FT7i|sy#aS#pFlXE3WJ)s>qgpYxyMh^z2pbSN;7M{@u))Z)3=>!NgcQ zf5{J@}2%a ze`!8DKvs9rPo{ULBOE< jD3{-G^RCSO*7Me?K0&bJ%gfp8u7(^aX}HMkH2)v~nv>>) literal 0 HcmV?d00001 diff --git a/certificates/roots/serverbasic.crt b/certificates/roots/serverbasic.crt new file mode 100644 index 0000000000000000000000000000000000000000..8588ce58a2444d04bd9bc358c401d9e1c4ff93b9 GIT binary patch literal 791 zcmXqLViq=NVyaod%*4pV#K>sC%f_kI=F#?@mywZ$mBFC#h#|KDCmVAp3!5-gl%t`j zfiQ@}AMV8=hUK-%(Tqp#FEVXJcZ!YqO#27)M5pf%(Bd4popQQ zfjCGdv#6z}D&|=jR&8iSt^T8CVz? z8h}BRIIod`p^-5VnOd4!MhzElHqJ+mKSovt=Eh!N9Ck7_HZojZ5|DS|e^~aj^Re4r z@nn>`FIsizR*UMN6<^!~Z?$e!D4EhG$6tE#B}d{{wp@ceQAwtkK?jm<`_7#AD2vC% z;_SbDk5f1cj{e)2t+`F#^Mv&kbrw~D>H5znJn-aZ z^oAXGwp8CYvpTdjO-bllJ1-M6BLm}NVFN(}eqe0M3NtePXJIv922#jw2BtY?pkvv8 z`DDiYo_faZU2C(iqCwxOn=A4?rJmgie4J2_(~>B-Q0jz-U8HlZ|5V$B-P^g7W>l4S z-R1aK>;=YaCsSi1!zDAbtnTZF zqUYUebWG~Ec<0FydhNn{8R@BF?(Zc$Os#^xXlJqYTkF3Hd%V7_cb@q7d0SFTnS9@$ z=3Jy0cw_d3^b5OqC$WhXUzvP*x)#Hn7(bppzeI!nd~(UVCFqsMF<)Qz@y}IOZN=N% zf+J3JvhHmb+)-@5ioN%XlkanfxiaQV%!~|-i-ipY4fugEEGx{&_@9N=wue#B(wSB};{CmAjN`|kTB z=H&c*ca+=jgU1BrKYDG@a65VUh*RyJU#lbYu5J(P5PZC(RWiHDX9)b1uGC1kHMvNA9?G4V4PG%;~8 zH8C+V9F2UQU%JZ9d(PG!Yvyr3`FZoy>e&9RmI6)J*9ShZe#qdFb^g{vHfO<^t3*_V z)+)VV$aOxla>rBoPVe-+i5~C&UV4zw@pPv|g2v%;?X?@sSDD{SiPUlnf8xFKhk4Ca zv*!&5w|%~nK6~1WbJve?1z*Vaoc4J!H*2}ach#o_YYapbR3F!uMm_cT;aAPf&ho1% zu|4mD^^qmVFMKVrTN*3H@oBc|rEhCk)a*j7k~Ef9Z!%c_!~D?2UDquBetGX{U_Mh# z(W8}dS0}qW>3)#G2vQnPp^*}(h4QnM{VzJSmnWKtJgH; ztW@ev?T%S9_ej*ue^;AUW4Cw8j>dCmXBbo*%um0tFaANs+k1~Tp45q~n6&D?c0%%} zr*S(UpZZlF&}O&DM1qGiLqkyJ$-|v7cJ8~3>?O`bw|xDaU2>$TKU^?QG>%$(>pJ)=RyOm=hqZp|5HOBH@KB_tUyd2?+S`|`Y_ z=S7x1zc$I_M&s8%vazdTMzEi25(_@9N` z1c3w;SiB894cysSfJ_DhdjnfG4sA9@R#tW1&{qKwqc z6urD0{et|Q%;e0}V*MguR?r3WDs_RGfe&ORKgbdmU~XhHkOlGiSj1RFCT1A5i^_IB z+WK*gnTAO(cTG~qYvi;G%%;G!%gC_8(JNhRQe#s<-oxuRHd|VMW)kHL2z;-*SEah6 z&HCq-J(D=6?fiCNwQ>SmWsjg=;HAn2@8vy+Pt%^cha(BU)WVc&WMEz zc{Np>5V zz4p)})s{_npX{xR%$fb+!;R;sKE0f7QP;We%x_EaMEj!KRugZeGD^y>4OkM+RpY&9 zPGPZ@YoKK7nZCd7%S)!puDH0~Pkdvh+M!hy;n7EZmp`4yDn8}ZruYS(61^rb)p9)K zR%J|Leb`hSHTw>GG)Hdj-0QuHH~)wztUBa+-~KtnrobnMez5MWlk%3TUtaz-|P!;IW1hFgCWa^2bar`9Op+3WRPi~#9-i literal 0 HcmV?d00001 diff --git a/certificates/roots/staatdernederlandenrootca.cer b/certificates/roots/staatdernederlandenrootca.cer new file mode 100644 index 0000000000000000000000000000000000000000..c88e9060f6d33f6fa0c9cd5ee008106f7009e874 GIT binary patch literal 958 zcmXqLV%}xY#I$GuGZP~d6AQzPXWNcy?CC+PT3gns@SQ?rdTSU>y+9pONWDhd3GB7tW@-rATF>*0AF)}jD zxU@A;u&QyH$c)0=eP^BvOJ7sxtJ<6;A+s$p>S`kA{(BRIkEg%8`}x*U9-(=rp>{gz z9S+&w@7z^N{Cem(-`8(f%YuFTd-h0_nYYe;amw@fCI1=1oQv#~I_A`0`y`OM-!VKlu60S5;tqV#yvq;Z1ASn+=#u*qIo`^fF3H3as??%gf943bHfv%TkLnQZrNZ@^bVG@^dniGgFK8i-57O z3+7cC@PQ2E2O7=70!)2u2C^VNABz}^$coz6dy2+R`3cVwQMt_r)v6L{|uJnZM-U?suYF^x1ecKdqRwB$4;e>KKmbKw)j)Lt2R^ zesD(o(Pi3XSvxbWaerRSR9A(ZXO+t@-jLD!b4Wow@WjWOSd;Y3RzZVf441BdzFf2I zgJHOaP*d?sWBp~JTev4qai8;Rca@XTi*QFG!^gZzUli;U0wixm^s5zKsE_wQ&k$NfEb zl&tg=GLy=sl7VMb*t!A(H4h6Av*4{_f2aD{dOf^3qyK~-+$qU8%|MR4Y S9#p9@s$rJ3UKrtOG#LOU9%{q@ literal 0 HcmV?d00001 diff --git a/certificates/roots/startcom-sfsca.der b/certificates/roots/startcom-sfsca.der new file mode 100644 index 0000000000000000000000000000000000000000..b60dea2484a21bf1e4bbe23e4d25380281637cf6 GIT binary patch literal 1997 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 H=vwqQK|K4m literal 0 HcmV?d00001 diff --git a/certificates/roots/swisscom-sdcs-root.crt b/certificates/roots/swisscom-sdcs-root.crt new file mode 100644 index 0000000000000000000000000000000000000000..ef97f1ff3c352a21fe2c4e98006c6deb65eaf601 GIT binary patch literal 1501 zcmXqLV!dh5#C&i8GZP~dlRyl2YYg}ENXPr(XYA|et}rv;W#iOp^Jx3d%gD&e%3zRU z$Zf#M#vIDRCd`zaVJK+858`kMa|D-X78fVy=NhUSD1(H!g=Jha(=$sFa}=CYi%K%n zGLsWaQWb(zi^?*SQ;Q9y4J1Lzn1zL4Iu(NQ^Gg(*9Tf}>4IYCR(TW)b~_}!1%NgAcDajULH|Ke7? zu~6)%%n`k3Q?=61T+qz3X*ID(^xViW|C&`{yl?Kg_?;`Cbk=7D{W>-K)18$+=gxGu z_tT8uvaC0@ntP@oGxNXaw{I{0FT3>Y1UW`|(+%|uwH9Rk&X9W*t#)$nhUvw()=gAbZ~a-{bvxweIRDg&2z7SdGwo~v z-=C9@({}mwS~s2+O{v~F3`mT7cIc~}4d)}8b`rS%nnmO|{vyT+?e4Tq;LI1zoC2fmC`lT|qb+?wj zmrH2Pbh>=zNAf>8XUo=Q+mamxHW$n7x%}%?t(g0x@cQaXaU5L@* zEfX^%1LNYxHiO1y13qA4mgQ$;{LjJy%t&npvLL=9i-sV5xnX+3i zK+^k?%8$Ep>|qxy7ECQrDC@a?SMJ{Y!XwJ>n}uT*tBCq)I@n|#S$SjoGMA;iUmnaY zmvbmk`*Z82*^|mATkZGEPTjX#aN7CX$22UhIL^682S**9`7d_m-S<9MjxAlw^sI+n zNG_lGV*Y}~pEdUi9S>Nvp}u3~%<@?q4=lCRi>b+cq_g3bdDfDLQ4hZcJZ*lzbhlQ= z^Pby(bK|ByfF!k?onedSXh3QQ7D|j^tSRnzAlZKe>V!` zd;ho4P4Ls1^E!R&TF-ah@@v-r=A96gmQWD8>TJaom3Jo`7ffcHG$(7`pPed4H;Xpa z?OQih`}M{Hw;nSlaK~k?X$ec*S1A5ZR+#_av3A#&|BMz$@d_`Q5?Z)atb5m~&JCN6 z|LMOGvUPIO+;it6f7?o&(>iS`+7$agL@By3==b)M{}N_1IHr79rS)c;lk>UGw8j(N f^DRS|RWFN~_O)Dy|79Tcbym(7zTlr$(HCU^O*C`X literal 0 HcmV?d00001 diff --git a/certificates/roots/swisssign.der b/certificates/roots/swisssign.der new file mode 100644 index 0000000000000000000000000000000000000000..7ee92c811117a2a12e8aa92e1dc68fbe0bf96714 GIT binary patch literal 953 zcmXqLV%}=d#58vSGZP~d69=2Xp~}_ewx0}m**LY@JlekVGBUEVG8mK@avN~6F^96S z2{So+7z!B(fH+*joWbRp#l^vy>3N1m1_mH8W?@aZn1ZvTf<{oVqk^Zmf^TA_f|-J$ zrKP2Up@o%!ft9I+rlGunEZiPWMlpfpLzhAJ~J!tb_!*3$X9mQV^F*6Tw1Gv zX}wI&t%XO{n*SG7T@aeUbbpfX+lfc6-r`_A&GPeSs>=7LMpvJ2>z=vs&^Gn=ciXZu zm$2eJCSUInfZ_n&u9P7x0? zJzX1m;KklU%JcsQ3F*IH=b@)`Mft1dp6@KyR&vs%Qd1&0H`Qyq-TBrOv@|RD$;Upk zgB{siJvp;CEwE7BSYo<#=eO!ZyB>(FDM$-VHO^S5xWG*D8H2JXYwM%P(A5Wvk3Nc< zRC=@NuEdv&rH>mN=7>3-=4ID0o|L1V=Dl9!aL^Ifd{O^fnoP`$42+B24O|Vlfr&zv zpM?dOzSs#8^b8T`xRqsdeQ~$HuPJ!4;YB``zor!0Am^ znT5%K0Xe9FsSy~|j0}s7Ugop!ogQ@cL#Ck5(-*rxJa>B_9C}CA*YnhrM(LXiOOM`M zJVDh)PKWDHEnoVFcCEXcPQ+X^{uW-E`0|O?9LLHPa;o7Lli9p%XXf>7f8{@)+vuU< z%i~oaUKz}o^J;$JvE-;#tK4?&zw@^s+rDRhJGWt=!rijXE4%dndE|R7*`ijlp;t2F zM&11XQKA9M^6j68v`vv)`YqdPF+=3k9gA*NiFFn^t4}exH-%F;DPU#gUW>&!Yea(C zkGTI0Ez&)6{qt4_^|xF3^j+>T?mTO_vfE9+T=r>3-`<>0Z6Ti-`lbe6PH~cOS5+|b coAIkG^{~6u>r;(x*~yO^TsEHHdN5N707XGt#Q*>R literal 0 HcmV?d00001 diff --git a/certificates/roots/tc_Universal_CA-I.cer b/certificates/roots/tc_Universal_CA-I.cer new file mode 100644 index 0000000000000000000000000000000000000000..9d7d804c7bd782ebfc59de3b3b63a49226775ac8 GIT binary patch literal 993 zcmXqLV!mt8#B_84GZP~d6QArN21W*^H`@~$DtfoE8St`kYPET^edlFlWMySAs5Im@ z;ACSCWnmL$a&a}3F^~drxP*m6oE1WfN{dUJQ}aqvixk{*lROMn43t2!+``gmvY~mI zWvNBQi8%_+j)rOmDj-$N!m@Z&DR>&liSrtm85kQG8Je1!7+FM#^BS2N8W|fJ8JSv| zT1E||)0!BSkOPX5m4Ug5k)Oe!iIIz`iII_ENxAYgm-Q3A7%mt1qSij=v&BvRxO?Xv zUl^`ERx(j#T7?|vg4wgCdU<_Ks$p7jYR&H`mNLtG@gIL~-v607BJ|R#?T=ZMF8-Ku zONoP__i~L|?3wb)=QB4sR~ffheLh#U zFLe64ULk%F<3|AnhdtYc_XOU%K0_$#y;ZaEB(~D-Ni{+l)dgAnTW4=8kM@Y1`{aGp z+Rq2)UAgY+cPh+8agUvNbbdLH2cxs*hP(FD@}5my#dAPm+h02~^*N7Y&iggqk=#9T zLhYMp(^=#upHcF>KD}+5Fqe(9a(Uf{JI~Il$XhqhHnD0pdCbJj$iTQb*&xwC9vIcK z$}AEFVhtjbmXzu&nYXXe<#pwsuA@_zz7{AgHsA*-5N2fj&%$cJ45SSBKmz2CD~br&GVa zJvLqapX#UZXK_<|>{1d$qw4i}8INvE`0HwV{==sIY&YLW?c1EBxaIn4)0$wrW$GUn z>fVx4o_pr*8ynqu>L#)Lhs-MXob*c4eVcu=*3r3U+p1G<6E~VSiE>JHi5c8@bMl&d zQH8gFn@C?g-}*Pl^;ZjA-}W)@P1~kJFL);v-&yp9-)euNvOwn?4~M)0hRv6EnY%;? zRxxFDd@wipAo+65mDJ*InLQ~}tSVbIH;8HTG}*JwIsR8bdmg{ewt0_5_un*=*`+EK gWGnSXiAUzal0~*3URa)QJW%~MRzCme1@7xJ0Ce$l@Bjb+ literal 0 HcmV?d00001 diff --git a/certificates/roots/tc_Universal_CA-II.cer b/certificates/roots/tc_Universal_CA-II.cer new file mode 100644 index 0000000000000000000000000000000000000000..affe426db6301175e0ced127ff65f33459f926c5 GIT binary patch literal 1507 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 fqqj-C@A7 literal 0 HcmV?d00001 diff --git a/certificates/roots/tc_class_4_ii.cer b/certificates/roots/tc_class_4_ii.cer new file mode 100644 index 0000000000000000000000000000000000000000..2b56d01ccf2e32b5f7105c114450ac684442c306 GIT binary patch literal 954 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 Z;Z=`b@jPRW(Dw*?y&|UY#r+FK^Z=7V*<=6! literal 0 HcmV?d00001 diff --git a/certificates/roots/trustCenter-root-5.der b/certificates/roots/trustCenter-root-5.der new file mode 100644 index 0000000000000000000000000000000000000000..50484fa222170007a8e153eec67091bbe4e9edd4 GIT binary patch literal 997 zcmXqLVt#1Q#B_22GZP~d6JN3_10w^INUyOd)03Pp2E1&XT5TR}-+37sSy>qjstvgf zIN6v(S=fY`TwD!h45UCDE@9yiXN8cW(&7^5)Vz|^A_e!{Bo9Ls10|3wx3DytY-nC) zS!z*nVvd5dqoIa@8b}qhusj}B3Z9;x26E!O29{uGVQ6Y(9wp9eWNBz*3`C}urj}6y z>$oOHCFHI9yROr&v4yz zd_Vu+tcRP{{S4mv^rhSUgva-LFW3K`R=0U;(GTyn9F=D?I~~-&Y8_nb{ANk;iNtN+ zFI8%#OO$!!MyoPjR6DvoJX2XTItjBuO~_n%mB-<$af5UJoW*5Yu3Ogc zueWQrFFSfx>z=|R~Xsl54P#QgtE%!~|-i<1o!4dj8*Evw8T zVIbBZ688LIw5oH%gKs?#3-|OrZO}jB@yLK5q(GRF@jnZz0W**?-~$Qpg9KQBiImMi z7R2Xc5o5uwA2rPaqk)m3`S|)*^}bv-mK!tnRp)l!;6c%KpCv;dU1m4JC6g;>5n;`qQ zH*eNR$!|)_3rkO^Dv3LgJKb#ER^HgO;sdHit~b2c*!z!cXW!_{#`|#T>o29JcFno4 zck^W<6`yx?kIGoQJ%ew2dKqH;=V_t5tw_u??~hiW7@6?anezZrjkNfap;p4i@$<~)&JXxf5sEK2W dSjdO>^6C>*ckuFQNV}K2@0D4h`fqq6y@h-W-A1z7L{bCWo9QTcw|=Prj{rKCmxxflUR9VWAc%W#YZ+8 zavN}h3}EA73JEgg2igGSu=B7v`guDBIU0r;gn$INcziXIH5H5u3``Y}>~YG>NzYU` zvLPq6B=hL}%v^=CR0W_IgzbKKPg!bSPUeyMnNYiPQj0Pb9QBUQ(=(70=QS`jFf}wb zG%zwZG>;PJH8eFaHZp>8hp^9@7?qHtiIJ6oxrvdV!Jvtei>Zl`k>OMj>$PO&8#3{C zFIC5W;z>x1&bBVmuHdb8-K$jcqKEn5F+nZcse4vV*|2-!^b?siEl0OZ%*heXS`xZ; zN$ZQLb(9xopf$j#QfVvNB73QSMt(#WUuo~ z+}!rYZ<%9W%O2)8U#(?M$RB#Q;@vADuU?V!pSd0cSpMWN{UI2+_PNq4?^7ad_ndZZ zn)z8bq(gx1)k7&e+jRNg=YH2Ty%3D`I=EBhRmjb>*)^TDEVGhMz6`RNH|PDOuWC=8 zJ(Z~G&byy;rXt$EXw&H!`ySTbi#|PTCmnxSQJC%u7Yi8h8Sns8maH%fs{u13&Yr(H z!2Pj|ipE{78A}rX-F_uxzK2oDq;+qe|MQ7O>@KZx5vM|2?tWjh^K_?T(e3^NnVQqJ z7O#^~o-X64)m@`?ux7%Gl^O>wPdv6(qun86>;E^)FI~2fm~*){Gxo!=rE)6Li{1ZZ uvS&PhGHc6Q{)O%BOy}A!dH6lt^Z)e6qDd|(%&M>MMd!^w`N?n1-QxfXF_+H( literal 0 HcmV?d00001 diff --git a/certificates/roots/turktrust-root2.cer b/certificates/roots/turktrust-root2.cer new file mode 100644 index 0000000000000000000000000000000000000000..5327d5f5c2deb19d271eb494301e3fb5efb2e6cd GIT binary patch literal 1088 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 KPx0{2ivM3ide~I} literal 0 HcmV?d00001 diff --git a/codesign_wrapper/MISBase.h b/codesign_wrapper/MISBase.h new file mode 100644 index 00000000..85a8a8ae --- /dev/null +++ b/codesign_wrapper/MISBase.h @@ -0,0 +1,44 @@ +#ifndef MISBASE_H +#define MISBASE_H + +/* Define the decoration we use to indicate public functions */ +#if defined(__GNUC__) +#define MIS_EXPORT extern __attribute__((visibility ("default"))) +#else +#define MIS_EXPORT +#endif + +/* Define ssize_t if needed */ +#if defined(__WIN32__) +typedef long ssize_t; +#endif + +/* Maximum path length */ +#if !defined(MAXPATHLEN) +#if defined(__WIN32__) +/* + * On windows, we handle paths up to length MAX_PATH. However, + * we convert paths into UTF8 in a number of places and since + * each character in the path can map to up to 4 bytes in UTF8, + * we need to account for that. + */ +#define MAXPATHLEN (MAX_PATH * 4) +#else +#define MAXPATHLEN 1024 +#endif +#endif + +/* + * The crazy CF situation on Windows requires this macro so we can build + * against either version + * The version of CF used by iTunes uses the system encoding as the file + * encoding. However we need paths to be UTF8 when we pass them into + * various file system APIs so we use CFStringGetCString instead. I'm + * told that the other CF does return UTF8 so if iTunes ever moves to + * that we can switch back to CFStringGetFileSystemRepresentation (5513199) + */ +#if defined(__WIN32__) +#define CFStringGetFileSystemRepresentation(str, buf, len) CFStringGetCString(str, buf, len, kCFStringEncodingUTF8) +#endif + +#endif diff --git a/codesign_wrapper/MISEntitlement.c b/codesign_wrapper/MISEntitlement.c new file mode 100644 index 00000000..79a5f7cd --- /dev/null +++ b/codesign_wrapper/MISEntitlement.c @@ -0,0 +1,100 @@ +#include "MISEntitlement.h" + +static const CFStringRef kEntitlementAllValuesAllowed = CFSTR("*"); + +static Boolean whitelistArrayAllowsEntitlementValue(CFArrayRef whitelist, CFStringRef value) +{ + Boolean allowed = false; + + CFIndex i, count = CFArrayGetCount(whitelist); + for (i = 0; (i < count) && (allowed == false); i++) { + CFStringRef item = (CFStringRef) CFArrayGetValueAtIndex(whitelist, i); + if (CFGetTypeID(item) == CFStringGetTypeID()) { + + CFIndex len = CFStringGetLength(item); + if (len > 0) { + if (CFStringGetCharacterAtIndex(item, len-1) != '*') { + + /* Not a wildcard, must be an exact match */ + allowed = CFStringCompare(item, value, 0) == kCFCompareEqualTo; + } else { + + /* Last character is a wildcard - do some matching */ + CFStringRef wildcardPrefix = CFStringCreateWithSubstring(kCFAllocatorDefault, item, CFRangeMake(0, len-1)); + allowed = CFStringHasPrefix(value, wildcardPrefix); + CFRelease(wildcardPrefix); + } + } + } else { + + /* Unexpected item in whitelist - bail */ + break; + } + } + + return allowed; +} + +Boolean MISEntitlementDictionaryAllowsEntitlementValue(CFDictionaryRef entitlements, CFStringRef entitlement, CFTypeRef value) +{ + Boolean allowsEntitlement = false; + + /* NULL is never a valid entitlement value */ + if (value != NULL) { + + /* Make sure the entitlement is present */ + CFTypeRef storedValue = CFDictionaryGetValue(entitlements, entitlement); + if (storedValue != NULL) { + + /* + * Handling depends on the type + * If the value matches our constant, the entitlement is permitted + * to have any value. + * If the value in the dictionary is a boolean, then the entitlement + * value must be a boolean with the same value + * If the value in the dictionary is an array (of strings), then the + * entitlement must be either one of those strings OR an array that + * includes only present strings + */ + if (CFEqual(storedValue, kEntitlementAllValuesAllowed) == true) { + + /* XXX: Does this need to restrict the value to some types */ + allowsEntitlement = true; + } else if (CFGetTypeID(storedValue) == CFBooleanGetTypeID()) { + allowsEntitlement = CFEqual(storedValue, value); + } else if (CFGetTypeID(storedValue) == CFStringGetTypeID()) { + if (CFGetTypeID(value) == CFStringGetTypeID()) { + CFArrayRef array = CFArrayCreate(kCFAllocatorDefault, (const void **) &storedValue, 1, &kCFTypeArrayCallBacks); + allowsEntitlement = whitelistArrayAllowsEntitlementValue(array, (CFStringRef) value); + CFRelease(array); + } + } else if (CFGetTypeID(storedValue) == CFArrayGetTypeID()) { + + /* value is either a single string or array of strings */ + if (CFGetTypeID(value) == CFStringGetTypeID()) { + allowsEntitlement = whitelistArrayAllowsEntitlementValue((CFArrayRef) storedValue, (CFStringRef) value); + } else if (CFGetTypeID(value) == CFArrayGetTypeID()) { + + /* + * Assume allowed, will set back to false if we encounter + * elements that are not permitted + */ + allowsEntitlement = true; + + /* Make sure each element is a string and in the array */ + CFIndex i, count = CFArrayGetCount((CFArrayRef) value); + for (i = 0; (i < count) && (allowsEntitlement == true); i++) { + CFTypeRef element = CFArrayGetValueAtIndex((CFArrayRef) value, i); + if (CFGetTypeID(element) == CFStringGetTypeID()) { + allowsEntitlement = whitelistArrayAllowsEntitlementValue((CFArrayRef) storedValue, (CFStringRef) element); + } else { + allowsEntitlement = false; + } + } + } + } + } + } + + return allowsEntitlement; +} diff --git a/codesign_wrapper/MISEntitlement.h b/codesign_wrapper/MISEntitlement.h new file mode 100644 index 00000000..8ad1e661 --- /dev/null +++ b/codesign_wrapper/MISEntitlement.h @@ -0,0 +1,23 @@ +/* + * MISEntitlements.h + * Constants and interfaces for dealing with entitlements + */ + +#ifndef MISENTITLEMENT_H +#define MISENTITLEMENT_H + +#include + +#include + + +/* Return an array of all known entitlements */ +MIS_EXPORT CFArrayRef MISEntitlementCopyAllEntitlements(void); + +/* + * Check if the entitlement dictionary permits an entitlement to have the + * given value + */ +Boolean MISEntitlementDictionaryAllowsEntitlementValue(CFDictionaryRef entitlements, CFStringRef entitlement, CFTypeRef value); + +#endif diff --git a/codesign_wrapper/Makefile b/codesign_wrapper/Makefile new file mode 100644 index 00000000..3fa7c3df --- /dev/null +++ b/codesign_wrapper/Makefile @@ -0,0 +1,31 @@ +SRCS := codesign_wrapper.c MISEntitlement.c codesign.c # MISCrypto_OpenSSL.c +OBJS := $(SRCS:.c=.o) +CFLAGS := -Wall -Wmost -Werror -g -O2 -I. -std=c99 -DDEBUG_ASSERT_PRODUCTION_CODE=0 +LDFLAGS := -framework CoreFoundation -framework Security +VERSION := 0.5.4 + +all: codesign_wrapper check_entitlements + +codesign_wrapper: $(OBJS) + +check_entitlements: check_entitlements.o + +tags: $(SRCS) + ctags $(SRCS) + +clean: + rm -f tags $(OBJS) codesign_wrapper + +zip: + (cd ..; zip -r codesign_wrapper-$(VERSION).zip codesign_wrapper -x \*/.git/\*) + +sign: + rm -r AccelerometerGraph.app + cp -R ../codesign_wrapper-unused/AccelerometerGraph.app . + cp ../codesign_wrapper-unused/Core_OS_IMG_v1_profile_052808.mobileprovision AccelerometerGraph.app/embedded.mobileprovision + CODESIGN_ALLOCATE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate ./codesign_wrapper -s "iPhone Developer: Katherine Kojima" -f -vvvv -r'=designated => anchor apple generic' AccelerometerGraph.app + +demosign: + rm -r AccelerometerGraph.app + cp -R ../codesign_wrapper-unused/AccelerometerGraph.app . + CODESIGN_ALLOCATE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate ./codesign_wrapper --no-profile -s "iPhone Developer: Katherine Kojima" -f -vvvv -r'=designated => anchor apple generic' AccelerometerGraph.app diff --git a/codesign_wrapper/check_entitlements.c b/codesign_wrapper/check_entitlements.c new file mode 100644 index 00000000..0ab4da76 --- /dev/null +++ b/codesign_wrapper/check_entitlements.c @@ -0,0 +1,400 @@ +/* + * check_entitlements.c + * + * + * Created by Conrad Sauerwald on 7/9/08. + * Copyright 2008 __MyCompanyName__. All rights reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG_ASSERT_PRODUCTION_CODE 0 +#include + +#include + +#define log(format, args...) \ + fprintf(stderr, "codesign_wrapper " format "\n", ##args); +#define cflog(format, args...) do { \ +CFStringRef logstr = CFStringCreateWithFormat(NULL, NULL, CFSTR(format), ##args); \ +if (logstr) { CFShow(logstr); CFRelease(logstr); } \ +} while(0); \ + +enum { CSMAGIC_EMBEDDED_ENTITLEMENTS = 0xfade7171 }; + +typedef struct { + uint32_t type; + uint32_t offset; +} cs_blob_index; + +CFDataRef +extract_entitlements_blob(const uint8_t *data, size_t length) +{ + CFDataRef entitlements = NULL; + cs_blob_index *csbi = (cs_blob_index *)data; + + require(data && length, out); + require(csbi->type == ntohl(CSMAGIC_EMBEDDED_ENTITLEMENTS), out); + require(length == ntohl(csbi->offset), out); + entitlements = CFDataCreate(kCFAllocatorDefault, + (uint8_t*)(data + sizeof(cs_blob_index)), + (CFIndex)(length - sizeof(cs_blob_index))); +out: + return entitlements; +} + +typedef struct { + bool valid_application_identifier; + bool valid_keychain_access_group; + bool illegal_entitlement; +} filter_whitelist_ctx; + +void +filter_entitlement(const void *key, const void *value, + filter_whitelist_ctx *ctx) +{ + if (CFEqual(key, CFSTR("application-identifier"))) { + // value isn't string + if (CFGetTypeID(value) != CFStringGetTypeID()) { + cflog("ERR: Illegal entitlement value %@ for key %@", value, key); + return; + } + + // log it for posterity + cflog("NOTICE: application-identifier := '%@'", value); + + // - put in an application-identifier that is messed up: .. + // split ident by periods and make sure the first two are not the same + // - put in an application-identifier they're not allowed to have: but we have no way to tell, although "apple" is illegal + // is apple, superseded by doesn't have at least 2 components split by a period + + CFArrayRef identifier_pieces = CFStringCreateArrayBySeparatingStrings(kCFAllocatorDefault, value, CFSTR(".")); /* No separators in the string returns array with that string; string == sep returns two empty strings */ + if (!identifier_pieces || (CFArrayGetCount(identifier_pieces) < 2)) { + cflog("ERR: Malformed identifier %@ := %@", key, value); + return; + } + + // doubled-up identifier + if (CFEqual(CFArrayGetValueAtIndex(identifier_pieces, 0), + CFArrayGetValueAtIndex(identifier_pieces, 1))) { + cflog("ERR: Malformed identifier %@ := %@", key, value); + return; + } + + // incomplete identifier: "blabla." + if (CFEqual(CFArrayGetValueAtIndex(identifier_pieces, 1), CFSTR(""))) { + cflog("ERR: Malformed identifier %@ := %@", key, value); + return; + } + + ctx->valid_application_identifier = true; + return; + } + + if (CFEqual(key, CFSTR("keychain-access-groups"))) { + // if there is one, false until proven correct + ctx->valid_keychain_access_group = false; + + // log it for posterity - we're not expecting people to use it yet + cflog("NOTICE: keychain-access-groups := %@", value); + + // - put in keychain-access-groups containing "apple" + if (CFGetTypeID(value) == CFStringGetTypeID()) { + if (CFEqual(CFSTR("apple"), value) || + (CFStringFind(value, CFSTR("*"), 0).location != kCFNotFound)) { + cflog("ERR: Illegal keychain access group value %@ for key %@", value, key); + return; + } + } else if (CFGetTypeID(value) == CFArrayGetTypeID()) { + CFIndex i, count = CFArrayGetCount(value); + for (i=0; ivalid_keychain_access_group = true; + return; + } + + // - double check there's no "get-task-allow" + // - nothing else should be allowed + cflog("ERR: Illegal entitlement key '%@' := '%@'", key, value); + ctx->illegal_entitlement = true; +} + +bool +filter_entitlements(CFDictionaryRef entitlements) +{ + if (!entitlements) + return true; + + // did not put in an application-identifier: that keeps us from identifying the app securely + filter_whitelist_ctx ctx = { /* valid_application_identifier */ false, + /* valid_keychain_access_group */ true, + /* illegal_entitlement */ false }; + CFDictionaryApplyFunction(entitlements, + (CFDictionaryApplierFunction)filter_entitlement, &ctx); + return (ctx.valid_application_identifier && ctx.valid_keychain_access_group && + !ctx.illegal_entitlement); +} + +static pid_t kill_child = -1; +void child_timeout(int sig) +{ + if (kill_child != -1) { + kill(kill_child, sig); + kill_child = -1; + } +} + +pid_t fork_child(void (*pre_exec)(void *arg), void *pre_exec_arg, + const char * const argv[]) +{ + unsigned delay = 1, maxDelay = 60; + for (;;) { + pid_t pid; + switch (pid = fork()) { + case -1: /* fork failed */ + switch (errno) { + case EINTR: + continue; /* no problem */ + case EAGAIN: + if (delay < maxDelay) { + sleep(delay); + delay *= 2; + continue; + } + /* fall through */ + default: + perror("fork"); + return -1; + } + assert(-1); /* unreached */ + + case 0: /* child */ + if (pre_exec) + pre_exec(pre_exec_arg); + execv(argv[0], (char * const *)argv); + perror("execv"); + _exit(1); + + default: /* parent */ + return pid; + break; + } + break; + } + return -1; +} + + +int fork_child_timeout(void (*pre_exec)(), char *pre_exec_arg, + const char * const argv[], int timeout) +{ + int exit_status = -1; + pid_t child_pid = fork_child(pre_exec, pre_exec_arg, argv); + if (timeout) { + kill_child = child_pid; + alarm(timeout); + } + while (1) { + int err = wait4(child_pid, &exit_status, 0, NULL); + if (err == -1) { + perror("wait4"); + if (errno == EINTR) + continue; + } + if (err == child_pid) { + if (WIFSIGNALED(exit_status)) { + log("child %d received signal %d", child_pid, WTERMSIG(exit_status)); + kill(child_pid, SIGHUP); + return -2; + } + if (WIFEXITED(exit_status)) + return WEXITSTATUS(exit_status); + return -1; + } + } +} + + +void dup_io(int arg[]) +{ + dup2(arg[0], arg[1]); + close(arg[0]); +} + + +int fork_child_timeout_output(int child_fd, int *parent_fd, const char * const argv[], int timeout) +{ + int output[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, output)) + return -1; + fcntl(output[1], F_SETFD, 1); /* close in child */ + int redirect_child[] = { output[0], child_fd }; + int err = fork_child_timeout(dup_io, (void*)redirect_child, argv, timeout); + if (!err) { + close(output[0]); /* close the child side in the parent */ + *parent_fd = output[1]; + } + return err; +} + +ssize_t read_fd(int fd, void **buffer) +{ + int err = -1; + size_t capacity = 1024; + char * data = malloc(capacity); + size_t size = 0; + while (1) { + int bytes_left = capacity - size; + int bytes_read = read(fd, data + size, bytes_left); + if (bytes_read >= 0) { + size += bytes_read; + if (capacity == size) { + capacity *= 2; + data = realloc(data, capacity); + if (!data) { + err = -1; + break; + } + continue; + } + err = 0; + } else + err = -1; + break; + } + if (0 == size) { + if (data) + free(data); + return err; + } + + *buffer = data; + return size; +} + +static char * codesign_binary = "/usr/bin/codesign"; + +int +main(int argc, char *argv[]) +{ +#if 0 + if (argc == 1) { + CFArrayRef empty_array = CFArrayCreate(NULL, NULL, 0, NULL); + CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, + 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + // empty + require(!filter_entitlements(dict), fail_test); + + CFDictionarySetValue(dict, CFSTR("get-task-allow"), kCFBooleanTrue); + + // no get-task-allow allowed + require(!filter_entitlements(dict), fail_test); + CFDictionaryRemoveValue(dict, CFSTR("get-task-allow")); + + CFDictionarySetValue(dict, CFSTR("application-identifier"), empty_array); + require(!filter_entitlements(dict), fail_test); + + CFDictionarySetValue(dict, CFSTR("application-identifier"), CFSTR("apple")); + require(!filter_entitlements(dict), fail_test); + CFDictionarySetValue(dict, CFSTR("application-identifier"), CFSTR("AJ$K#GK$.AJ$K#GK$.hoi")); + require(!filter_entitlements(dict), fail_test); + CFDictionarySetValue(dict, CFSTR("application-identifier"), CFSTR("AJ$K#GK$.")); + require(!filter_entitlements(dict), fail_test); + CFDictionarySetValue(dict, CFSTR("application-identifier"), CFSTR("AJ$K#GK$.hoi")); + require(filter_entitlements(dict), fail_test); + + CFDictionarySetValue(dict, CFSTR("keychain-access-groups"), CFSTR("apple")); + require(!filter_entitlements(dict), fail_test); + const void *ary[] = { CFSTR("test"), CFSTR("apple") }; + CFArrayRef ka_array = CFArrayCreate(NULL, ary, sizeof(ary)/sizeof(*ary), NULL); + CFDictionarySetValue(dict, CFSTR("keychain-access-groups"), ka_array); + require(!filter_entitlements(dict), fail_test); + CFDictionarySetValue(dict, CFSTR("keychain-access-groups"), CFSTR("AJ$K#GK$.joh")); + require(filter_entitlements(dict), fail_test); + CFDictionarySetValue(dict, CFSTR("this-should-not"), CFSTR("be-there")); + require(!filter_entitlements(dict), fail_test); + + exit(0); +fail_test: + fprintf(stderr, "failed internal test\n"); + exit(1); + } +#endif + + if (argc != 2) { + fprintf(stderr, "usage: %s \n", argv[0]); + exit(1); + } + + do { + + fprintf(stderr, "NOTICE: check_entitlements on %s", argv[1]); + + int exit_status; + const char * const extract_entitlements[] = + { codesign_binary, "--display", "--entitlements", "-", argv[1], NULL }; + int entitlements_fd; + if ((exit_status = fork_child_timeout_output(STDOUT_FILENO, &entitlements_fd, + extract_entitlements, 0))) { + fprintf(stderr, "ERR: failed to extract entitlements: %d\n", exit_status); + break; + } + + void *entitlements = NULL; + size_t entitlements_size = read_fd(entitlements_fd, &entitlements); + if (entitlements_size == -1) + break; + close(entitlements_fd); + + if (entitlements && entitlements_size) { + CFDataRef ent = extract_entitlements_blob(entitlements, entitlements_size); + free(entitlements); + require(ent, out); + CFPropertyListRef entitlements_dict = + CFPropertyListCreateFromXMLData(kCFAllocatorDefault, + ent, kCFPropertyListImmutable, NULL); + CFRelease(ent); + require(entitlements_dict, out); + if (!filter_entitlements(entitlements_dict)) { + fprintf(stderr, "ERR: bad entitlements\n"); + exit(1); + } + exit(0); + } else { + fprintf(stderr, "ERR: no entitlements!\n"); + } + } while (0); +out: + return 1; +} \ No newline at end of file diff --git a/codesign_wrapper/codesign.c b/codesign_wrapper/codesign.c new file mode 100644 index 00000000..72c03a37 --- /dev/null +++ b/codesign_wrapper/codesign.c @@ -0,0 +1,276 @@ + +#include "codesign.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define DEBUG_ASSERT_PRODUCTION_CODE 0 +#include + +/* + * Magic numbers used by Code Signing + */ +enum { + CSMAGIC_REQUIREMENT = 0xfade0c00, /* single Requirement blob */ + CSMAGIC_REQUIREMENTS = 0xfade0c01, /* Requirements vector (internal requirements) */ + CSMAGIC_CODEDIRECTORY = 0xfade0c02, /* CodeDirectory blob */ + CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0, /* embedded form of signature data */ + CSMAGIC_DETACHED_SIGNATURE = 0xfade0cc1, /* multi-arch collection of embedded signatures */ + + CSSLOT_CODEDIRECTORY = 0, /* slot index for CodeDirectory */ +}; + + +/* + * Structure of an embedded-signature SuperBlob + */ +typedef struct __BlobIndex { + uint32_t type; /* type of entry */ + uint32_t offset; /* offset of entry */ +} CS_BlobIndex; + +typedef struct __SuperBlob { + uint32_t magic; /* magic number */ + uint32_t length; /* total length of SuperBlob */ + uint32_t count; /* number of index entries following */ + CS_BlobIndex index[]; /* (count) entries */ + /* followed by Blobs in no particular order as indicated by offsets in index */ +} CS_SuperBlob; + + +/* + * C form of a CodeDirectory. + */ +typedef struct __CodeDirectory { + uint32_t magic; /* magic number (CSMAGIC_CODEDIRECTORY) */ + uint32_t length; /* total length of CodeDirectory blob */ + uint32_t version; /* compatibility version */ + uint32_t flags; /* setup and mode flags */ + uint32_t hashOffset; /* offset of hash slot element at index zero */ + uint32_t identOffset; /* offset of identifier string */ + uint32_t nSpecialSlots; /* number of special hash slots */ + uint32_t nCodeSlots; /* number of ordinary (code) hash slots */ + uint32_t codeLimit; /* limit to main image signature range */ + uint8_t hashSize; /* size of each hash in bytes */ + uint8_t hashType; /* type of hash (cdHashType* constants) */ + uint8_t spare1; /* unused (must be zero) */ + uint8_t pageSize; /* log2(page size in bytes); 0 => infinite */ + uint32_t spare2; /* unused (must be zero) */ + /* followed by dynamic content as located by offset fields above */ +} CS_CodeDirectory; + + + //assert(page < ntohl(cd->nCodeSlots)); + //return base + ntohl(cd->hashOffset) + page * 20; + + +static CFMutableDictionaryRef lc_code_sig(uint8_t *lc_code_signature, size_t lc_code_signature_len) +{ + CFDataRef codedir = NULL; + CFDataRef message = NULL; + CFMutableDictionaryRef code_signature = + CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + require(code_signature, out); + + CS_SuperBlob *sb = (CS_SuperBlob*)lc_code_signature; + require(ntohl(sb->magic) == CSMAGIC_EMBEDDED_SIGNATURE, out); + uint32_t count; + for (count = 0; count < ntohl(sb->count); count++) { + //uint32_t type = ntohl(sb->index[count].type); + uint32_t offset = ntohl(sb->index[count].offset); + uint8_t *bytes = lc_code_signature + offset; + //fprintf(stderr, "blob[%d]: (type: 0x%.08x, offset: %p)\n", count, type, (void*)offset); + uint32_t magic = ntohl(*(uint32_t*)bytes); + uint32_t length = ntohl(*(uint32_t*)(bytes+4)); + //fprintf(stderr, " magic: 0x%.08x length: %d\n", magic, length); + switch(magic) { + case 0xfade0c01: //write_data("requirements", bytes, length); + break; + case 0xfade0c02: //write_data("codedir", bytes, length); + codedir = CFDataCreate(kCFAllocatorDefault, bytes, length); + require(codedir, out); + CFDictionarySetValue(code_signature, CFSTR("CodeDirectory"), codedir); + CFRelease(codedir); + uint8_t *cursor = bytes; + require_string(htonl(*(uint32_t*)(cursor+8)) >= 0x20001, out, "incompatible version"); + require_string(htonl(*(uint32_t*)(cursor+8)) <= 0x2F000, out, "incompatible version"); + uint32_t hash_offset = htonl(*(uint32_t*)(cursor+16)); + require_string(htonl(*(uint32_t*)(cursor+24)) >= 5, out, "no entitlements slot yet"); + require_string(*(cursor+36) == 20, out, "unexpected hash size"); + require_string(*(cursor+37) == 1, out, "unexpected hash type"); + message = CFDataCreate(kCFAllocatorDefault, cursor+hash_offset-5*20, 20); + require(message, out); + CFDictionarySetValue(code_signature, CFSTR("EntitlementsCDHash"), message); + CFRelease(message); + break; + case 0xfade0b01: //write_data("signed", lc_code_signature, bytes-lc_code_signature); + if (length == 8) { + fprintf(stderr, "Ad-hoc signed binary\n"); + goto out; + } else { + message = CFDataCreate(kCFAllocatorDefault, bytes+8, length-8); + require(message, out); + CFDictionarySetValue(code_signature, CFSTR("SignedData"), message); + CFRelease(message); + } + break; + case 0xfade7171: + { + unsigned char digest[CC_SHA1_DIGEST_LENGTH]; + CCDigest(kCCDigestSHA1, bytes, length, digest); + message = CFDataCreate(kCFAllocatorDefault, digest, sizeof(digest)); + require(message, out); + CFDictionarySetValue(code_signature, CFSTR("EntitlementsHash"), message); + CFRelease(message); + message = CFDataCreate(kCFAllocatorDefault, bytes+8, length-8); + require(message, out); + CFDictionarySetValue(code_signature, CFSTR("Entitlements"), message); + CFRelease(message); + break; + } + default: + fprintf(stderr, "Skipping block with magic: 0x%x\n", magic); + break; + } + } + return code_signature; +out: + if (code_signature) CFRelease(code_signature); + return NULL; +} + +#if 1 +static FILE * +open_bundle(const char * path, const char * mode) +{ + char full_path[1024] = {}; + CFStringRef path_cfstring = NULL; + CFURLRef path_url = NULL; + CFBundleRef bundle = NULL; + + path_cfstring = CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path); + require(path_cfstring, out); + path_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path_cfstring, kCFURLPOSIXPathStyle, true); + require(path_url, out); + bundle = CFBundleCreate(kCFAllocatorDefault, path_url); + require(bundle, out); + CFURLRef exec = CFBundleCopyExecutableURL(bundle); + require(exec, out); + require(CFURLGetFileSystemRepresentation(exec, true, (uint8_t*)full_path, sizeof(full_path)), out); +out: + if (path_cfstring) CFRelease(path_cfstring); + if (path_url) CFRelease(path_url); + if (bundle) CFRelease(bundle); + + return fopen(full_path, "r"); +} +#else +static FILE * +open_bundle(const char *path, const char *mode) +{ + char full_path[1024] = {}; + const char *slash; + char *dot; + slash = rindex(path, '/'); + if (!slash) slash = path; + require(strlcpy(full_path, path, sizeof(full_path)) < sizeof(full_path), out); + require(strlcat(full_path, "/", sizeof(full_path)), out); + require(strlcat(full_path, slash, sizeof(full_path)), out); + require(dot = rindex(full_path, '.'), out); + *dot = '\0'; + return fopen(full_path, "r"); +out: + return NULL; +} +#endif + +CFMutableDictionaryRef load_code_signature(FILE *binary, size_t slice_offset) +{ + bool signature_found = false; + CFMutableDictionaryRef result = NULL; + union { + struct load_command lc; + struct linkedit_data_command le_lc; + } cmd; + do { + require(1 == fread(&cmd.lc, sizeof(cmd.lc), 1, binary), out); + if (cmd.lc.cmd == LC_CODE_SIGNATURE) { + require(1 == fread((uint8_t *)&cmd.lc + sizeof(cmd.lc), sizeof(cmd.le_lc) - sizeof(cmd.lc), 1, binary), out); + require_noerr(fseek(binary, slice_offset+cmd.le_lc.dataoff, SEEK_SET), out); + size_t length = cmd.le_lc.datasize; + uint8_t *data = malloc(length); + require(length && data, out); + require(1 == fread(data, length, 1, binary), out); + signature_found = true; + result = lc_code_sig(data, length); + free(data); + break; + } + require_noerr(fseek(binary, cmd.lc.cmdsize-sizeof(cmd.lc), SEEK_CUR), out); + } while(cmd.lc.cmd || cmd.lc.cmdsize); /* count lc */ +out: + if (!signature_found) + fprintf(stderr, "No LC_CODE_SIGNATURE segment found\n"); + return result; +} + +CFArrayRef load_code_signatures(const char *path) +{ + bool fully_parsed_binary = false; + CFMutableDictionaryRef result = NULL; + CFMutableArrayRef results = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + + FILE *binary = open_bundle(path, "r"); + require(binary, out); + + struct mach_header header; + require(1 == fread(&header, sizeof(header), 1, binary), out); + if (header.magic == 0xfeedface) { + result = load_code_signature(binary, 0 /*non fat*/); + require(result, out); + CFArrayAppendValue(results, result); + } + else + { + struct fat_header fat; + require(!fseek(binary, 0L, SEEK_SET), out); + require(1 == fread(&fat, sizeof(fat), 1, binary), out); + require(htonl(fat.magic) == FAT_MAGIC, out); + uint32_t slice, slices = htonl(fat.nfat_arch); + struct fat_arch *archs = calloc(slices, sizeof(struct fat_arch)); + require(slices == fread(archs, sizeof(struct fat_arch), slices, binary), out); + for (slice = 0; slice < slices; slice++) { + uint32_t slice_offset = htonl(archs[slice].offset); + require(!fseek(binary, slice_offset, SEEK_SET), out); + require(1 == fread(&header, sizeof(header), 1, binary), out); + require(header.magic == 0xfeedface, out); + result = load_code_signature(binary, slice_offset); + require(result, out); + CFArrayAppendValue(results, result); + CFRelease(result); + } + } + fully_parsed_binary = true; +out: + if (!fully_parsed_binary) { + if (results) { + CFRelease(results); + results = NULL; + } + } + if (binary) + fclose(binary); + return results; +} diff --git a/codesign_wrapper/codesign.h b/codesign_wrapper/codesign.h new file mode 100644 index 00000000..75486061 --- /dev/null +++ b/codesign_wrapper/codesign.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2004,2011 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@ + * + * cmsutil.h + */ + +#ifndef _CODESIGN_H_ +#define _CODESIGN_H_ 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern CFMutableDictionaryRef load_code_signature(FILE *binary, size_t slice_offset); +extern CFArrayRef load_code_signatures(const char *path); + +#ifdef __cplusplus +} +#endif + +#endif /* _CODESIGN_H_ */ diff --git a/codesign_wrapper/codesign_wrapper.c b/codesign_wrapper/codesign_wrapper.c new file mode 100644 index 00000000..87f1a629 --- /dev/null +++ b/codesign_wrapper/codesign_wrapper.c @@ -0,0 +1,1019 @@ +/* + cc -g -O0 -Wall -Werror -Wmost -stabs -o codesign_wrapper codesign_wrapper.c -framework CoreFoundation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* for CMS */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +/* entitlement whitelist checking */ +#include + +#define DEBUG_ASSERT_PRODUCTION_CODE 0 +#include + +#include "codesign_wrapper.h" +#include "codesign.h" + +extern bool do_verify(const char *path, CFArrayRef certificates); + +static char * codesign_binary = "/usr/bin/codesign"; +static char * processing_path = "/var/tmp/signingbox"; +static char * processing_file = "codesign_wrapper"; +static char * processing_prefix = NULL; +static char * auditing_postfix = "_auditing.plist"; +static char * audition_plist_path = NULL; +static char * entitlements_plist_path = NULL; +static char * entitlements_postfix = "_entitlements.plist"; + + +#define CODESIGN_WRAPPER_VERSION "0.7.10" +#define log(format, args...) \ + fprintf(stderr, "codesign_wrapper-" CODESIGN_WRAPPER_VERSION ": " format "\n", ##args); +#define cflog(format, args...) do { \ +CFStringRef logstr = CFStringCreateWithFormat(NULL, NULL, CFSTR(format), ##args);\ +if (logstr) { CFShow(logstr); CFRelease(logstr); } \ +} while(0); \ + +const char *_root_ca_name = ANCHOR; + +static pid_t kill_child = -1; +static void child_timeout(int sig) +{ + if (kill_child != -1) { + kill(kill_child, sig); + kill_child = -1; + } +} + +static void +close_all_fd(void *arg __unused) +/* close down any files that might have been open at this point + but make sure 0, 1 and 2 are set to /dev/null so they don't + get reused */ +{ + int maxDescriptors = getdtablesize (); + int i; + + int devnull = open(_PATH_DEVNULL, O_RDWR, 0); + + if (devnull >= 0) for (i = 0; i < 3; ++i) + dup2(devnull, i); + + for (i = 3; i < maxDescriptors; ++i) + close (i); +} + + +static pid_t +fork_child(void (*pre_exec)(void *arg), void *pre_exec_arg, + const char * const argv[]) +{ + unsigned delay = 1, maxDelay = 60; + for (;;) { + pid_t pid; + switch (pid = fork()) { + case -1: /* fork failed */ + switch (errno) { + case EINTR: + continue; /* no problem */ + case EAGAIN: + if (delay < maxDelay) { + sleep(delay); + delay *= 2; + continue; + } + /* fall through */ + default: + perror("fork"); + return -1; + } + assert(-1); /* unreached */ + + case 0: /* child */ + if (pre_exec) + pre_exec(pre_exec_arg); + execv(argv[0], (char * const *)argv); + perror("execv"); + _exit(1); + + default: /* parent */ + return pid; + break; + } + break; + } + return -1; +} + + +static int +fork_child_timeout(void (*pre_exec)(), char *pre_exec_arg, + const char * const argv[], int timeout) +{ + int exit_status = -1; + pid_t child_pid = fork_child(pre_exec, pre_exec_arg, argv); + if (timeout) { + kill_child = child_pid; + alarm(timeout); + } + while (1) { + int err = wait4(child_pid, &exit_status, 0, NULL); + if (err == -1) { + perror("wait4"); + if (errno == EINTR) + continue; + } + if (err == child_pid) { + if (WIFSIGNALED(exit_status)) { + log("child %d received signal %d", child_pid, WTERMSIG(exit_status)); + kill(child_pid, SIGHUP); + return -2; + } + if (WIFEXITED(exit_status)) + return WEXITSTATUS(exit_status); + return -1; + } + } +} + + +static void +dup_io(int arg[]) +{ + dup2(arg[0], arg[1]); + close(arg[0]); +} + + +static int +fork_child_timeout_output(int child_fd, int *parent_fd, const char * const argv[], int timeout) +{ + int output[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, output)) + return -1; + fcntl(output[1], F_SETFD, 1); /* close in child */ + int redirect_child[] = { output[0], child_fd }; + int err = fork_child_timeout(dup_io, (void*)redirect_child, argv, timeout); + if (!err) { + close(output[0]); /* close the child side in the parent */ + *parent_fd = output[1]; + } + return err; +} + + +static void +pass_signal_to_children(int sig) +{ + signal(sig, SIG_DFL); + kill(0, sig); +} + + +static int +mk_temp_dir(const char *path) +{ + char *pos = NULL, *tmp_path = strdup(path); + if (!path) return -1; + pos = index(tmp_path, '/'); + if (!pos) return -1; + while ((pos = index(pos + 1, '/'))) { + *pos = '\0'; + if ((0 != mkdir(tmp_path, 0755)) && + errno != EEXIST) + return -1; + *pos = '/'; + } + if ((0 != mkdir(tmp_path, 0755)) && + errno != EEXIST) + return -1; + return 0; +} + + +static int +lock_file(const char *lock_file_prefix, const char *lock_filename) +{ + int err = -1; + pid_t pid; + char *tempfile = NULL; + do { + if (!asprintf(&tempfile, "%s.%d", lock_file_prefix, getpid())) + break; + FILE *temp = fopen(tempfile, "w"); + if (temp == NULL) + break; + if (fprintf(temp, "%d\n", getpid()) <= 0) + break; + fclose(temp); + if(!link(tempfile, lock_filename)) { + unlink(tempfile); + err = 0; + break; + } + FILE* lock = fopen(lock_filename, "r"); + if (lock == NULL) + break; + if (fscanf(lock, "%d\n", &pid) <= 0) + break; + if (kill(pid, 0)) { + if (!unlink(lock_filename) && + !link(tempfile, lock_filename)) { + unlink(tempfile); + err = 0; + break; + } + } + } while(0); + unlink(tempfile); + if (tempfile) + free(tempfile); + + return err; +} + + +static ssize_t +read_fd(int fd, void **buffer) +{ + int err = -1; + size_t capacity = 1024; + char * data = malloc(capacity); + size_t size = 0; + while (1) { + int bytes_left = capacity - size; + int bytes_read = read(fd, data + size, bytes_left); + if (bytes_read >= 0) { + size += bytes_read; + if (capacity == size) { + capacity *= 2; + data = realloc(data, capacity); + if (!data) { + err = -1; + break; + } + continue; + } + err = 0; + } else + err = -1; + break; + } + if (0 == size) { + if (data) + free(data); + return err; + } + + *buffer = data; + return size; +} + +enum { CSMAGIC_EMBEDDED_ENTITLEMENTS = 0xfade7171 }; + +typedef struct { + uint32_t type; + uint32_t offset; +} cs_blob_index; + +static CFDataRef +extract_entitlements_blob(const uint8_t *data, size_t length) +{ + CFDataRef entitlements = NULL; + cs_blob_index *csbi = (cs_blob_index *)data; + + require(data && length, out); + require(csbi->type == ntohl(CSMAGIC_EMBEDDED_ENTITLEMENTS), out); + require(length == ntohl(csbi->offset), out); + entitlements = CFDataCreate(kCFAllocatorDefault, + (uint8_t*)(data + sizeof(cs_blob_index)), + (CFIndex)(length - sizeof(cs_blob_index))); +out: + return entitlements; +} + +static CFDataRef +build_entitlements_blob(const uint8_t *data, size_t length) +{ + cs_blob_index csbi = { htonl(CSMAGIC_EMBEDDED_ENTITLEMENTS), + htonl(length+sizeof(csbi)) }; + CFMutableDataRef blob = CFDataCreateMutable(kCFAllocatorDefault, sizeof(csbi)+length); + if (data) { + CFDataAppendBytes(blob, (uint8_t*)&csbi, sizeof(csbi)); + CFDataAppendBytes(blob, data, length); + } + return blob; +} + +static CFMutableDictionaryRef +dump_auditing_info(const char *path) +{ + int exit_status; + CFMutableDictionaryRef dict = NULL; + void *requirements = NULL; + ssize_t requirements_size = 0; + void *entitlements = NULL; + ssize_t entitlements_size = 0; + + do { + const char * const extract_requirements[] = + { codesign_binary, "--display", "-v", "-v", path, NULL }; + int requirements_fd; + if ((exit_status = fork_child_timeout_output(STDERR_FILENO, &requirements_fd, + extract_requirements, 0))) { + fprintf(stderr, "failed to extract requirements data: %d\n", exit_status); + break; + } + + requirements_size = read_fd(requirements_fd, &requirements); + if (requirements_size == -1) + break; + close(requirements_fd); + + } while(0); + + do { + const char * const extract_entitlements[] = + { codesign_binary, "--display", "--entitlements", "-", path, NULL }; + int entitlements_fd; + if ((exit_status = fork_child_timeout_output(STDOUT_FILENO, &entitlements_fd, + extract_entitlements, 0))) { + fprintf(stderr, "failed to extract entitlements: %d\n", exit_status); + break; + } + + entitlements_size = read_fd(entitlements_fd, &entitlements); + if (entitlements_size == -1) + break; + close(entitlements_fd); + + } while(0); + + do { + dict = CFDictionaryCreateMutable( + kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + if (requirements && requirements_size) { + CFDataRef req = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, + requirements, requirements_size, kCFAllocatorMalloc); + CFDictionarySetValue(dict, CFSTR("Requirements"), req); + CFRelease(req); + } + + if (entitlements && entitlements_size) { + CFDataRef ent = extract_entitlements_blob(entitlements, entitlements_size); + free(entitlements); + require(ent, out); + CFPropertyListRef entitlements_dict = + CFPropertyListCreateWithData(kCFAllocatorDefault, + ent, kCFPropertyListImmutable, NULL, NULL); + CFRelease(ent); + require(entitlements_dict, out); + CFDictionarySetValue(dict, CFSTR("Entitlements"), entitlements_dict); + CFRelease(entitlements_dict); + } + } while (0); + + return dict; +out: + return NULL; +} + +static int +write_data(const char *path, CFDataRef data) +{ + int fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, 0644); + ssize_t length = CFDataGetLength(data); + if (fd < 0) + return -1; + int bytes_written = write(fd, CFDataGetBytePtr(data), length); + close(fd); + CFRelease(data); + if (bytes_written != length) { + fprintf(stderr, "failed to write auditing info to %s\n", path); + unlink(path); + return -1; + } + return 0; + +} + +static int +write_auditing_data(const char *path, CFMutableDictionaryRef info) +{ + CFTypeRef entitlements = CFDictionaryGetValue(info, CFSTR("Entitlements")); + if (entitlements) { + CFDataRef entitlements_xml = CFPropertyListCreateXMLData(kCFAllocatorDefault, entitlements); + if (!entitlements_xml) + return -1; + CFDictionarySetValue(info, CFSTR("Entitlements"), entitlements_xml); + CFRelease(entitlements_xml); + } + + CFDataRef plist = CFPropertyListCreateXMLData(kCFAllocatorDefault, info); + if (!plist) + return -1; + + return write_data(path, plist); /* consumes plist */ +} + +static int +write_filtered_entitlements(const char *path, CFDictionaryRef info) +{ + CFDataRef plist = CFPropertyListCreateXMLData(kCFAllocatorDefault, info); + if (!plist) + return -1; + CFDataRef entitlements_blob = + build_entitlements_blob(CFDataGetBytePtr(plist), CFDataGetLength(plist)); + CFRelease(plist); + if (!entitlements_blob) + return -1; + return write_data(path, entitlements_blob); /* consumes entitlements_blob */ + +} + +static CFDataRef +cfdata_read_file(const char *filename) +{ + int data_file = open(filename, O_RDONLY); + if (data_file == -1) + return NULL; + void *data = NULL; + ssize_t size = read_fd(data_file, &data); + if (size > 0) + return CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, + data, size, kCFAllocatorMalloc); + + return NULL; +} + +static CFDictionaryRef +load_profile(const char *profile_path) +{ + SecCmsMessageRef cmsg = NULL; + CFDictionaryRef entitlements = NULL; + CFArrayRef certificates = NULL; + CFDictionaryRef profile = NULL; + + CFDataRef message = cfdata_read_file(profile_path); + require(message, out); + SecAsn1Item encoded_message = { CFDataGetLength(message), + (uint8_t*)CFDataGetBytePtr(message) }; + require_noerr(SecCmsMessageDecode(&encoded_message, + NULL, NULL, NULL, NULL, NULL, NULL, &cmsg), out); + + /* expected to be a signed data message at the top level */ + SecCmsContentInfoRef cinfo; + SecCmsSignedDataRef sigd; + require(cinfo = SecCmsMessageContentLevel(cmsg, 0), out); + require(SecCmsContentInfoGetContentTypeTag(cinfo) == + SEC_OID_PKCS7_SIGNED_DATA, out); + require(sigd = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(cinfo), out); + + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + policy = SecPolicyCreateBasicX509(); + int nsigners = SecCmsSignedDataSignerInfoCount(sigd); + require(nsigners == 1, out); + require_noerr(SecCmsSignedDataVerifySignerInfo(sigd, 0, NULL, policy, &trust), out); + SecCertificateRef apple_ca_cert = NULL; + CFArrayRef apple_ca_cert_anchors = NULL; + require(apple_ca_cert = SecCertificateCreateWithBytes(NULL, _profile_anchor, sizeof(_profile_anchor)), out); + require(apple_ca_cert_anchors = CFArrayCreate(kCFAllocatorDefault, (const void **)&apple_ca_cert, 1, NULL), out); + require_noerr(SecTrustSetAnchorCertificates(trust, apple_ca_cert_anchors), out); + log("using %s for profile evaluation", _root_ca_name); + SecTrustResultType trust_result; + require_noerr(SecTrustEvaluate(trust, &trust_result), out); +#if WWDR + /* doesn't mean much, but I don't have the root */ + require(trust_result == kSecTrustResultRecoverableTrustFailure, out); +#else + require(trust_result == kSecTrustResultUnspecified, out); +#endif + CFRelease(apple_ca_cert_anchors); + + // FIXME require proper intermediate and leaf certs + // require_noerr(SecCertificateCopyCommonName(SecCertificateRef certificate, CFStringRef *commonName); + CFRelease(trust); + + CFRelease(policy); + SecCmsSignerInfoRef sinfo = SecCmsSignedDataGetSignerInfo(sigd, 0); + require(sinfo, out); + CFStringRef commonname = SecCmsSignerInfoGetSignerCommonName(sinfo); + require(commonname, out); +#if WWDR + require(CFEqual(CFSTR("Alpha Config Profile Signing Certificate"), commonname), out); +#else + require(CFEqual(CFSTR("Apple iPhone OS Provisioning Profile Signing"), commonname) || + CFEqual(CFSTR("TEST Apple iPhone OS Provisioning Profile Signing TEST"), commonname), out); +#endif + CFRelease(commonname); + + /* attached CMS */ + const SecAsn1Item *content = SecCmsMessageGetContent(cmsg); + require(content && content->Length && content->Data, out); + + CFDataRef attached_contents = CFDataCreate(kCFAllocatorDefault, + content->Data, content->Length); + CFPropertyListRef plist = CFPropertyListCreateWithData(kCFAllocatorDefault, + attached_contents, kCFPropertyListImmutable, NULL, NULL); + CFRelease(attached_contents); + require(plist && CFGetTypeID(plist) == CFDictionaryGetTypeID(), out); + + CFTypeRef profile_certificates = CFDictionaryGetValue(plist, CFSTR("DeveloperCertificates")); + if (profile_certificates && CFGetTypeID(profile_certificates) == CFArrayGetTypeID()) + { + certificates = CFArrayCreateCopy(kCFAllocatorDefault, profile_certificates); +#if 0 + CFIndex i, cert_count = CFArrayGetCount(certificates); + for (i = 0; i < cert_count; i++) { + SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, CFArrayGetValueAtIndex(certificates, i)); + CFShow(cert); + CFRelease(cert); + } +#endif + } + + CFTypeRef profile_entitlements = CFDictionaryGetValue(plist, CFSTR("Entitlements")); + if (profile_entitlements && CFGetTypeID(profile_entitlements) == CFDictionaryGetTypeID()) + { + entitlements = CFDictionaryCreateCopy(kCFAllocatorDefault, + (CFDictionaryRef)profile_entitlements); + } + CFRelease(plist); + +out: + if (cmsg) SecCmsMessageDestroy(cmsg); + if (entitlements && certificates) { + const void *keys[] = { CFSTR("Entitlements"), CFSTR("Certificates") }; + const void *vals[] = { entitlements, certificates }; + profile = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, 2, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + } + if (entitlements) CFRelease(entitlements); + if (certificates) CFRelease(certificates); + return profile; +} + +typedef struct { + CFDictionaryRef whitelist; + CFMutableDictionaryRef filtered_list; + bool allowed_entitlements; +} filter_whitelist_ctx; + +static void +filter_entitlement(const void *key, const void *value, + filter_whitelist_ctx *ctx) +{ + /* filter out get-task-allow, no error */ + if (CFEqual(key, CFSTR("get-task-allow"))) + return; + + /* whitelist data protection entitlement, otherwise validate */ + if (!CFEqual(key, CFSTR("DataProtectionClass")) && + !CFEqual(key, CFSTR("data-protection-class")) && + !MISEntitlementDictionaryAllowsEntitlementValue(ctx->whitelist, key, value)) { + ctx->allowed_entitlements = false; + cflog("Illegal entitlement key/value pair: %@, %@", key, value); + return; + } + + if (ctx->filtered_list) + CFDictionarySetValue(ctx->filtered_list, key, value); +} + +static bool +filter_entitlements(CFDictionaryRef whitelist, CFDictionaryRef entitlements, + CFMutableDictionaryRef filtered_entitlements) +{ + if (!entitlements) + return true; + + filter_whitelist_ctx ctx = { whitelist, filtered_entitlements, true }; + CFDictionaryApplyFunction(entitlements, + (CFDictionaryApplierFunction)filter_entitlement, &ctx); + return ctx.allowed_entitlements; +} + +static SecCertificateRef +cms_verify_signer(CFDataRef message, CFDataRef detached) +{ + SecCertificateRef signer_cert = NULL; + require(message, out); + + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + policy = SecPolicyCreateBasicX509(); + + SecCmsMessageRef cmsg = NULL; + SecCmsContentInfoRef cinfo; + SecCmsSignedDataRef sigd = NULL; + + SecAsn1Item encoded_message = { CFDataGetLength(message), (uint8_t*)CFDataGetBytePtr(message) }; + require_noerr(SecCmsMessageDecode(&encoded_message, NULL, NULL, NULL, NULL, NULL, NULL, &cmsg), + out); + /* expected to be a signed data message at the top level */ + require(cinfo = SecCmsMessageContentLevel(cmsg, 0), out); + require(SecCmsContentInfoGetContentTypeTag(cinfo) == SEC_OID_PKCS7_SIGNED_DATA, out); + require(sigd = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(cinfo), out); + + if (detached) { + require(!SecCmsSignedDataHasDigests(sigd), out); + SECAlgorithmID **digestalgs = SecCmsSignedDataGetDigestAlgs(sigd); + SecCmsDigestContextRef digcx = SecCmsDigestContextStartMultiple(digestalgs); + SecCmsDigestContextUpdate(digcx, CFDataGetBytePtr(detached), CFDataGetLength(detached)); + SecCmsSignedDataSetDigestContext(sigd, digcx); + SecCmsDigestContextDestroy(digcx); + } + + int nsigners = SecCmsSignedDataSignerInfoCount(sigd); + require_quiet(nsigners == 1, out); + require_noerr_string(SecCmsSignedDataVerifySignerInfo(sigd, 0, NULL, policy, &trust), out, "bad signature"); + + signer_cert = SecTrustGetCertificateAtIndex(trust, 0); + CFRetain(signer_cert); + CFRelease(policy); + CFRelease(trust); + +out: + return signer_cert; + +} + +static bool +cms_verify(CFDataRef message, CFDataRef detached, CFArrayRef certificates) +{ + bool result = false; + SecCertificateRef signer_cert = cms_verify_signer(message, detached); + require(signer_cert, out); + if (certificates) { + CFDataRef cert_cfdata = SecCertificateCopyData(signer_cert); + CFRange all_certs = CFRangeMake(0, CFArrayGetCount(certificates)); + result = CFArrayContainsValue(certificates, all_certs, cert_cfdata); + CFRelease(cert_cfdata); + } else { + CFArrayRef commonNames = SecCertificateCopyCommonNames(signer_cert); + require(CFArrayGetCount(commonNames) == 1, out); + CFStringRef commonName = (CFStringRef)CFArrayGetValueAtIndex(commonNames, 0); + require(commonName, out); + result = CFEqual(CFSTR("Apple iPhone OS Application Signing"), commonName) + || CFEqual(CFSTR("TEST Apple iPhone OS Application Signing TEST"), commonName); + CFRelease(commonNames); + } + + if (!result) + fprintf(stderr, "Disallowed signer\n"); + +out: + if (signer_cert) CFRelease(signer_cert); + return result; + +} + + +static bool +verify_code_signatures(CFArrayRef code_signatures, CFArrayRef certificates) +{ + require(code_signatures, out); + CFIndex i, signature_count = CFArrayGetCount(code_signatures); + + /* Each slice can have their own entitlements and be properly signed + but codesign(1) picks the first when listing and smashes that one + down when re-signing */ + CFDataRef first_entitlement_hash = NULL; + for (i = 0; i < signature_count; i++) { + CFDictionaryRef code_signature = CFArrayGetValueAtIndex(code_signatures, i); + + CFDataRef signature = CFDictionaryGetValue(code_signature, CFSTR("SignedData")); + require(signature, out); + CFDataRef code_directory = CFDictionaryGetValue(code_signature, CFSTR("CodeDirectory")); + require(code_directory, out); + CFDataRef entitlements = CFDictionaryGetValue(code_signature, CFSTR("Entitlements")); + CFDataRef entitlements_hash = CFDictionaryGetValue(code_signature, CFSTR("EntitlementsHash")); + CFDataRef entitlements_cdhash = CFDictionaryGetValue(code_signature, CFSTR("EntitlementsCDHash")); + require(entitlements, out); + require(entitlements_hash, out); + require(entitlements_cdhash, out); + require(CFEqual(entitlements_hash, entitlements_cdhash), out); + + if (!first_entitlement_hash) + first_entitlement_hash = entitlements_hash; + else + require(entitlements_hash && CFEqual(first_entitlement_hash, entitlements_hash), out); + + /* was the application signed by a certificate in the profile */ + require(cms_verify(signature, code_directory, certificates), out); + } + return true; +out: + return false; +} + + +static void +init() +{ + signal(SIGHUP, pass_signal_to_children); + signal(SIGINT, pass_signal_to_children); + signal(SIGTERM, pass_signal_to_children); + //signal(SIGCHLD, SIG_IGN); + signal(SIGALRM, child_timeout); + + const char *codesign_binary_env = getenv("CODESIGN"); + if (codesign_binary_env) + codesign_binary = strdup(codesign_binary_env); + + const char *processing_path_env = getenv("PROCESS_PATH"); + if (processing_path_env) + processing_path = strdup(processing_path_env); + + processing_prefix = calloc(1, strlen(processing_path) + + strlen(processing_file) + 1/*'/'*/ + 1/*'\0'*/); + strcat(processing_prefix, processing_path); + strcat(processing_prefix, "/"); + strcat(processing_prefix, processing_file); + + audition_plist_path = calloc(1, strlen(processing_prefix) + + strlen(auditing_postfix) + 1); + strcat(audition_plist_path, processing_prefix); + strcat(audition_plist_path, auditing_postfix); + + entitlements_plist_path = calloc(1, strlen(processing_prefix) + + strlen(entitlements_postfix) + 1); + strcat(entitlements_plist_path, processing_prefix); + strcat(entitlements_plist_path, entitlements_postfix); + +} + + +const struct option options[] = { + { "sign", required_argument, NULL, 's' }, + { "entitlements", required_argument, NULL, 'z' }, + { "no-profile", no_argument, NULL, 'Z' }, + { "verify", no_argument, NULL, 'V' }, /* map to V to let verbose v pass */ + { "timeout", required_argument, NULL, 't' }, + {} +}; + +struct securityd *gSecurityd; +void securityd_init(); +CFArrayRef SecAccessGroupsGetCurrent(void); + +CFArrayRef SecAccessGroupsGetCurrent(void) { + return NULL; +} + +OSStatus ServerCommandSendReceive(uint32_t id, CFTypeRef in, CFTypeRef *out); +OSStatus ServerCommandSendReceive(uint32_t id, CFTypeRef in, CFTypeRef *out) +{ + return -1; +} + + + +#ifndef UNIT_TESTING +int +main(int argc, char *argv[]) +{ + int err = 0; + + int ch; + bool sign_op = false, noprofile = false, + verify_op = false; + int timeout = 180; + + securityd_init(); + + while ((ch = getopt_long(argc, argv, "fvr:s:R:", options, NULL)) != -1) + { + switch (ch) { + case 's': sign_op = true; break; + case 'z': { log("codesign_wrapper reserves the entitlements option for itself"); + exit(1); /* XXX load entitlements from optarg */ + break; } + case 'Z': noprofile = true; break; + case 'V': verify_op = true; break; + case 't': timeout = atoi(optarg); break; + } + } + int arg_index_files = optind; + if ((!sign_op && !verify_op) || arg_index_files == argc) { + log("not a signing/verify operation, or no file to sign given"); + return 1; /* short circuit to codesign binary: not signing, no files */ + } + if (arg_index_files + 1 != argc) { + log("cannot sign more than one file in an operation"); + return 1; /* we don't do more than one file at a time, so we can rejigger */ + } + + init(); + if (mk_temp_dir(processing_path)) { + log("failed to create directory %s", processing_path); + return 1; + } + + CFMutableDictionaryRef auditing_info = + dump_auditing_info(argv[arg_index_files]); + if (!auditing_info) { + log("failed to extract auditing_info from %s", argv[arg_index_files]); + return 1; + } + + /* load up entitlements requested */ + CFDictionaryRef entitlements_requested = + CFDictionaryGetValue(auditing_info, CFSTR("Entitlements")); + require_string(entitlements_requested, out, "At least need an application-identifier entitlements"); + CFMutableDictionaryRef allowable_entitlements = NULL; + + if (noprofile) { + /* XXX if (verify_op) require it to be store signed */ + if (verify_op) { + /* load the code signature */ + CFArrayRef code_signatures = + load_code_signatures(argv[arg_index_files]); + require(code_signatures, out); + require(verify_code_signatures(code_signatures, NULL), out); + CFRelease(code_signatures); + } + + if (sign_op) { + /* do the same checks, pass signed in entitlements along for audit */ + require(CFDictionaryGetValue(entitlements_requested, + CFSTR("application-identifier")), out); + + CFDictionarySetValue(auditing_info, CFSTR("Entitlements"), + entitlements_requested); + + allowable_entitlements = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, entitlements_requested); + + /* For the 2-pass signing, where the app is signed first, then encrypted + and then resigned, we need to by pass the initial validation, so we + allow signing without checking the entitlements to the profile. */ +#if 0 + log("You shouldn't want to sign without a profile."); + exit(1); +#endif + } + + } else { + /* load up the profile */ + char profile_path[_POSIX_PATH_MAX] = {}; + snprintf(profile_path, sizeof(profile_path), "%s/embedded.mobileprovision", argv[arg_index_files]); + CFDictionaryRef profile = load_profile(profile_path); + require_action(profile, out, log("Failed to load provision profile from: %s", profile_path)); + CFDictionaryRef entitlements_whitelist = CFDictionaryGetValue(profile, CFSTR("Entitlements")); + require(entitlements_whitelist, out); + CFArrayRef certificates = CFDictionaryGetValue(profile, CFSTR("Certificates")); + require(certificates, out); + + if (sign_op) + require_noerr(unlink(profile_path), out); + + /* only allow identifiers whitelisted by profile */ + allowable_entitlements = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + require(allowable_entitlements, out); + require(filter_entitlements(entitlements_whitelist, + entitlements_requested, allowable_entitlements), out); + + /* must have valid application-identifier */ + require(CFDictionaryGetValue(allowable_entitlements, + CFSTR("application-identifier")), out); + + CFDictionarySetValue(auditing_info, CFSTR("Entitlements"), + allowable_entitlements); + + if (verify_op) { + /* load the code signature */ + CFArrayRef code_signatures = + load_code_signatures(argv[arg_index_files]); + require(code_signatures, out); + require(verify_code_signatures(code_signatures, certificates), out); + CFRelease(code_signatures); + } + } + + char *lock_filename = NULL; + + if (sign_op) { + if (!asprintf(&lock_filename, "%s.lock", processing_prefix)) { + log("failed to alloc %s.lock", processing_prefix); + return 1; + } + + while (lock_file(processing_prefix, lock_filename)) { + log("waiting for lock"); + sleep(1); + } + + err = write_auditing_data(audition_plist_path, auditing_info); + + if (!err && allowable_entitlements) { + err |= write_filtered_entitlements(entitlements_plist_path, allowable_entitlements); + } + + if (err) + log("failed to write auditing data"); + } + + if (!err) { + char *orig_args[argc+1+2]; + /* size_t argv_size = argc * sizeof(*argv); args = malloc(argv_size); */ + memcpy(orig_args, argv, (argc-1) * sizeof(*argv)); + + int arg = 0, argo = 0; + while (arg < argc - 1) { + if (strcmp("--no-profile", orig_args[arg]) && + strncmp("--timeout", orig_args[arg], strlen("--timeout"))) { + orig_args[argo] = argv[arg]; + argo++; + } + arg++; + } + if (entitlements_requested && allowable_entitlements) { + orig_args[argo++] = "--entitlements"; + orig_args[argo++] = entitlements_plist_path; + } + orig_args[argo++] = argv[arg_index_files]; + orig_args[argo++] = NULL; + orig_args[0] = codesign_binary; +#if DEBUG + log("Caling codesign with the following args:"); + int ix; + for(ix = 0; ix <= argc; ix++) + log(" %s", orig_args[ix] ? orig_args[ix] : "NULL"); +#endif + err = fork_child_timeout(NULL, NULL, (const char * const *)orig_args, timeout); + } + + if (sign_op) { + unlink(audition_plist_path); + unlink(entitlements_plist_path); + + free(audition_plist_path); + free(entitlements_plist_path); + + if (err == -2) { + log("executing codesign(1) timed out"); + const char * const kill_tokens[] = { "/usr/bin/killall", "Ingrian", NULL }; + fork_child_timeout(close_all_fd, NULL, kill_tokens, 0); + const char * const load_tokens[] = { "/usr/bin/killall", "-USR2", "securityd", NULL }; + fork_child_timeout(close_all_fd, NULL, load_tokens, 0); + } + + unlink(lock_filename); + free(lock_filename); + + if (err == -2) { + sleep(10); + log("delayed exit with timeout return value now we've tried to reload tokens"); + return 2; + } + } + + if (!err) + return 0; + else + log("failed to execute codesign(1)"); +out: + return 1; +} +#endif /* UNIT_TESTING */ + +/* vim: set et : set sw=4 : set ts=4 : set sts=4 : */ diff --git a/codesign_wrapper/codesign_wrapper.h b/codesign_wrapper/codesign_wrapper.h new file mode 100644 index 00000000..545d370c --- /dev/null +++ b/codesign_wrapper/codesign_wrapper.h @@ -0,0 +1,87 @@ + +#if WWDR +#define ANCHOR "WWDR CA" +#else +#define ANCHOR "Apple CA" +#endif + +/* subject:/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Root CA */ +/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Root CA */ +unsigned char _profile_anchor[1215]={ +0x30,0x82,0x04,0xBB,0x30,0x82,0x03,0xA3,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x02, +0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30, +0x62,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13, +0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, +0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x13,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,0x16,0x30,0x14,0x06, +0x03,0x55,0x04,0x03,0x13,0x0D,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74, +0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x30,0x36,0x30,0x34,0x32,0x35,0x32,0x31,0x34, +0x30,0x33,0x36,0x5A,0x17,0x0D,0x33,0x35,0x30,0x32,0x30,0x39,0x32,0x31,0x34,0x30, +0x33,0x36,0x5A,0x30,0x62,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, +0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x13,0x0A,0x41,0x70,0x70, +0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B, +0x13,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, +0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x03,0x13,0x0D,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,0xE4,0x91,0xA9,0x09,0x1F,0x91,0xDB,0x1E, +0x47,0x50,0xEB,0x05,0xED,0x5E,0x79,0x84,0x2D,0xEB,0x36,0xA2,0x57,0x4C,0x55,0xEC, +0x8B,0x19,0x89,0xDE,0xF9,0x4B,0x6C,0xF5,0x07,0xAB,0x22,0x30,0x02,0xE8,0x18,0x3E, +0xF8,0x50,0x09,0xD3,0x7F,0x41,0xA8,0x98,0xF9,0xD1,0xCA,0x66,0x9C,0x24,0x6B,0x11, +0xD0,0xA3,0xBB,0xE4,0x1B,0x2A,0xC3,0x1F,0x95,0x9E,0x7A,0x0C,0xA4,0x47,0x8B,0x5B, +0xD4,0x16,0x37,0x33,0xCB,0xC4,0x0F,0x4D,0xCE,0x14,0x69,0xD1,0xC9,0x19,0x72,0xF5, +0x5D,0x0E,0xD5,0x7F,0x5F,0x9B,0xF2,0x25,0x03,0xBA,0x55,0x8F,0x4D,0x5D,0x0D,0xF1, +0x64,0x35,0x23,0x15,0x4B,0x15,0x59,0x1D,0xB3,0x94,0xF7,0xF6,0x9C,0x9E,0xCF,0x50, +0xBA,0xC1,0x58,0x50,0x67,0x8F,0x08,0xB4,0x20,0xF7,0xCB,0xAC,0x2C,0x20,0x6F,0x70, +0xB6,0x3F,0x01,0x30,0x8C,0xB7,0x43,0xCF,0x0F,0x9D,0x3D,0xF3,0x2B,0x49,0x28,0x1A, +0xC8,0xFE,0xCE,0xB5,0xB9,0x0E,0xD9,0x5E,0x1C,0xD6,0xCB,0x3D,0xB5,0x3A,0xAD,0xF4, +0x0F,0x0E,0x00,0x92,0x0B,0xB1,0x21,0x16,0x2E,0x74,0xD5,0x3C,0x0D,0xDB,0x62,0x16, +0xAB,0xA3,0x71,0x92,0x47,0x53,0x55,0xC1,0xAF,0x2F,0x41,0xB3,0xF8,0xFB,0xE3,0x70, +0xCD,0xE6,0xA3,0x4C,0x45,0x7E,0x1F,0x4C,0x6B,0x50,0x96,0x41,0x89,0xC4,0x74,0x62, +0x0B,0x10,0x83,0x41,0x87,0x33,0x8A,0x81,0xB1,0x30,0x58,0xEC,0x5A,0x04,0x32,0x8C, +0x68,0xB3,0x8F,0x1D,0xDE,0x65,0x73,0xFF,0x67,0x5E,0x65,0xBC,0x49,0xD8,0x76,0x9F, +0x33,0x14,0x65,0xA1,0x77,0x94,0xC9,0x2D,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01, +0x7A,0x30,0x82,0x01,0x76,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04, +0x04,0x03,0x02,0x01,0x06,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04, +0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04, +0x14,0x2B,0xD0,0x69,0x47,0x94,0x76,0x09,0xFE,0xF4,0x6B,0x8D,0x2E,0x40,0xA6,0xF7, +0x47,0x4D,0x7F,0x08,0x5E,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16, +0x80,0x14,0x2B,0xD0,0x69,0x47,0x94,0x76,0x09,0xFE,0xF4,0x6B,0x8D,0x2E,0x40,0xA6, +0xF7,0x47,0x4D,0x7F,0x08,0x5E,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,0x1A,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,0x0D,0x06,0x09,0x2A, +0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x5C, +0x36,0x99,0x4C,0x2D,0x78,0xB7,0xED,0x8C,0x9B,0xDC,0xF3,0x77,0x9B,0xF2,0x76,0xD2, +0x77,0x30,0x4F,0xC1,0x1F,0x85,0x83,0x85,0x1B,0x99,0x3D,0x47,0x37,0xF2,0xA9,0x9B, +0x40,0x8E,0x2C,0xD4,0xB1,0x90,0x12,0xD8,0xBE,0xF4,0x73,0x9B,0xEE,0xD2,0x64,0x0F, +0xCB,0x79,0x4F,0x34,0xD8,0xA2,0x3E,0xF9,0x78,0xFF,0x6B,0xC8,0x07,0xEC,0x7D,0x39, +0x83,0x8B,0x53,0x20,0xD3,0x38,0xC4,0xB1,0xBF,0x9A,0x4F,0x0A,0x6B,0xFF,0x2B,0xFC, +0x59,0xA7,0x05,0x09,0x7C,0x17,0x40,0x56,0x11,0x1E,0x74,0xD3,0xB7,0x8B,0x23,0x3B, +0x47,0xA3,0xD5,0x6F,0x24,0xE2,0xEB,0xD1,0xB7,0x70,0xDF,0x0F,0x45,0xE1,0x27,0xCA, +0xF1,0x6D,0x78,0xED,0xE7,0xB5,0x17,0x17,0xA8,0xDC,0x7E,0x22,0x35,0xCA,0x25,0xD5, +0xD9,0x0F,0xD6,0x6B,0xD4,0xA2,0x24,0x23,0x11,0xF7,0xA1,0xAC,0x8F,0x73,0x81,0x60, +0xC6,0x1B,0x5B,0x09,0x2F,0x92,0xB2,0xF8,0x44,0x48,0xF0,0x60,0x38,0x9E,0x15,0xF5, +0x3D,0x26,0x67,0x20,0x8A,0x33,0x6A,0xF7,0x0D,0x82,0xCF,0xDE,0xEB,0xA3,0x2F,0xF9, +0x53,0x6A,0x5B,0x64,0xC0,0x63,0x33,0x77,0xF7,0x3A,0x07,0x2C,0x56,0xEB,0xDA,0x0F, +0x21,0x0E,0xDA,0xBA,0x73,0x19,0x4F,0xB5,0xD9,0x36,0x7F,0xC1,0x87,0x55,0xD9,0xA7, +0x99,0xB9,0x32,0x42,0xFB,0xD8,0xD5,0x71,0x9E,0x7E,0xA1,0x52,0xB7,0x1B,0xBD,0x93, +0x42,0x24,0x12,0x2A,0xC7,0x0F,0x1D,0xB6,0x4D,0x9C,0x5E,0x63,0xC8,0x4B,0x80,0x17, +0x50,0xAA,0x8A,0xD5,0xDA,0xE4,0xFC,0xD0,0x09,0x07,0x37,0xB0,0x75,0x75,0x21, +}; diff --git a/config/base.xcconfig b/config/base.xcconfig deleted file mode 100644 index 905215b6..00000000 --- a/config/base.xcconfig +++ /dev/null @@ -1,15 +0,0 @@ -ARCHS = $(ARCHS_STANDARD_32_64_BIT) -CODE_SIGN_IDENTITY = -; -GCC_VERSION = com.apple.compilers.llvm.clang.1_0 -DEBUG_INFORMATION_FORMAT = dwarf-with-dsym -SDKROOT = -CURRENT_PROJECT_VERSION = $(RC_ProjectSourceVersion) -VERSIONING_SYSTEM = apple-generic; - -DEAD_CODE_STRIPPING = YES - -// Debug symbols should be on obviously -GCC_GENERATE_DEBUGGING_SYMBOLS = YES -COPY_PHASE_STRIP = NO -STRIP_STYLE = debugging -STRIP_INSTALLED_PRODUCT = NO diff --git a/doc/C++Utilities.cwk b/doc/C++Utilities.cwk deleted file mode 100644 index b85c2bc69a8a2e152b79ffaebc15f46a68f11b8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 132909 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 diff --git a/evroots.h b/evroots.h new file mode 100644 index 00000000..dd9e877a --- /dev/null +++ b/evroots.h @@ -0,0 +1,2370 @@ +/* ANSI-C code produced by gperf version 3.0.3 */ +/* Command-line: gperf */ +/* Computed positions: -k'34,54,56,70,76,90,158,170-171,$' */ + +struct subject_to_ix_t { char *subject; int anchor_ix; }; + +#define TOTAL_KEYWORDS 172 +#define MIN_WORD_LENGTH 39 +#define MAX_WORD_LENGTH 299 +#define MIN_HASH_VALUE 39 +#define MAX_HASH_VALUE 362 +/* maximum key range = 324, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +subject_hash (register const char *str, register unsigned int len) +{ + static const unsigned short asso_values[] = + { + 5, 10, 10, 0, 0, 0, 0, 363, 363, 0, + 50, 5, 10, 10, 363, 10, 363, 0, 363, 15, + 363, 0, 15, 5, 0, 15, 50, 10, 15, 115, + 0, 15, 0, 60, 85, 5, 60, 35, 10, 0, + 15, 0, 0, 363, 363, 5, 5, 363, 0, 0, + 15, 20, 65, 0, 110, 5, 0, 0, 25, 363, + 363, 363, 115, 363, 363, 0, 50, 5, 20, 0, + 0, 20, 5, 0, 105, 15, 15, 10, 10, 0, + 75, 0, 0, 0, 0, 0, 5, 5, 115, 0, + 0, 363, 363, 363, 363, 363, 363, 0, 363, 5, + 10, 0, 363, 85, 10, 0, 60, 5, 0, 0, + 363, 10, 363, 363, 5, 0, 5, 0, 0, 0, + 363, 5, 20, 363, 363, 363, 363, 363, 363, 363, + 363, 363, 363, 363, 10, 363, 363, 363, 363, 363, + 363, 363, 363, 363, 363, 363, 0, 363, 363, 363, + 363, 363, 363, 363, 363, 363, 363, 363, 363, 10, + 363, 363, 363, 363, 363, 363, 363, 363, 363, 363, + 363, 363, 363, 363, 363, 363, 363, 0, 363, 363, + 363, 363, 363, 363, 363, 363, 0, 363, 15, 363, + 363, 363, 363, 363, 363, 5, 55, 363, 363, 363, + 363, 363, 363, 363, 363, 363, 363, 363, 363, 363, + 363, 363, 363, 363, 363, 363, 363, 363, 363, 363, + 363, 363, 363, 363, 363, 363, 363, 363, 363, 363, + 363, 363, 363, 363, 363, 363, 363, 363, 363, 363, + 363, 363, 363, 363, 363, 363, 363, 363, 363, 363, + 363, 363, 363, 363, 363, 363 + }; + register int hval = len; + + switch (hval) + { + default: + hval += asso_values[(unsigned char)str[170]]; + /*FALLTHROUGH*/ + case 170: + hval += asso_values[(unsigned char)str[169]]; + /*FALLTHROUGH*/ + case 169: + case 168: + case 167: + case 166: + case 165: + case 164: + case 163: + case 162: + case 161: + case 160: + case 159: + case 158: + hval += asso_values[(unsigned char)str[157]]; + /*FALLTHROUGH*/ + case 157: + case 156: + case 155: + case 154: + case 153: + case 152: + case 151: + case 150: + case 149: + case 148: + case 147: + case 146: + case 145: + case 144: + case 143: + case 142: + case 141: + case 140: + case 139: + case 138: + case 137: + case 136: + case 135: + case 134: + case 133: + case 132: + case 131: + case 130: + case 129: + case 128: + case 127: + case 126: + case 125: + case 124: + case 123: + case 122: + case 121: + case 120: + case 119: + case 118: + case 117: + case 116: + case 115: + case 114: + case 113: + case 112: + case 111: + case 110: + case 109: + case 108: + case 107: + case 106: + case 105: + case 104: + case 103: + case 102: + case 101: + case 100: + case 99: + case 98: + case 97: + case 96: + case 95: + case 94: + case 93: + case 92: + case 91: + case 90: + hval += asso_values[(unsigned char)str[89]]; + /*FALLTHROUGH*/ + case 89: + case 88: + case 87: + case 86: + case 85: + case 84: + case 83: + case 82: + case 81: + case 80: + case 79: + case 78: + case 77: + case 76: + hval += asso_values[(unsigned char)str[75]]; + /*FALLTHROUGH*/ + case 75: + case 74: + case 73: + case 72: + case 71: + case 70: + hval += asso_values[(unsigned char)str[69]]; + /*FALLTHROUGH*/ + case 69: + case 68: + case 67: + case 66: + case 65: + case 64: + case 63: + case 62: + case 61: + case 60: + case 59: + case 58: + case 57: + case 56: + hval += asso_values[(unsigned char)str[55]]; + /*FALLTHROUGH*/ + case 55: + case 54: + hval += asso_values[(unsigned char)str[53]]; + /*FALLTHROUGH*/ + case 53: + case 52: + case 51: + case 50: + case 49: + case 48: + case 47: + case 46: + case 45: + case 44: + case 43: + case 42: + case 41: + case 40: + case 39: + case 38: + case 37: + case 36: + case 35: + case 34: + hval += asso_values[(unsigned char)str[33]]; + break; + } + return hval + asso_values[(unsigned char)str[len - 1]]; +} + +#ifdef __GNUC__ +__inline +#ifdef __GNUC_STDC_INLINE__ +__attribute__ ((__gnu_inline__)) +#endif +#endif +const struct subject_to_ix_t * +subject_to_anchor_ix (register const char *str, register unsigned int len) +{ + static const struct subject_to_ix_t subject_wordlist[] = + { + {"1\0130\011\006\003U\004\006\023\002BE1\0300\026\006\003U\004\003\023\017BELGIUM ROOT CA", 26}, + {"1\0130\011\006\003U\004\006\023\002DK1\0140\012\006\003U\004\012\023\003TDC1\0240\022\006\003U\004\003\023\013TDC OCES CA", 151}, + {"1\0130\011\006\003U\004\006\023\002CN1\0160\014\006\003U\004\012\023\005CNNIC1\0230\021\006\003U\004\003\023\012CNNIC ROOT", 46}, + {"1\0130\011\006\003U\004\006\023\002CN1\0210\017\006\003U\004\012\023\010UNITRUST1\0210\017\006\003U\004\003\023\010UCA ROOT", 166}, + {"1\0130\011\006\003U\004\006\023\002FR1\0220\020\006\003U\004\012\014\011Dhimyotis1\0210\017\006\003U\004\003\014\010Certigna", 37}, + {"1\0130\011\006\003U\004\006\023\002ES1\0150\013\006\003U\004\012\023\004FNMT1\0300\026\006\003U\004\013\023\017FNMT CLASE 2 CA", 73}, + {"1\0130\011\006\003U\004\006\023\002BE1\0310\027\006\003U\004\003\023\020BELGIUM ROOT CA2", 27}, + {"1\0130\011\006\003U\004\006\023\002CN1\0210\017\006\003U\004\012\023\010UNITRUST1\0300\026\006\003U\004\003\023\017UCA GLOBAL ROOT", 165}, + {"1\0130\011\006\003U\004\006\023\002ES1\0240\022\006\003U\004\012\014\013IZENPE S.A.1\0230\021\006\003U\004\003\014\012Izenpe.com", 93}, + {"1\0130\011\006\003U\004\006\023\002US1\0260\024\006\003U\004\012\023\015GEOTRUST INC.1\0330\031\006\003U\004\003\023\022GEOTRUST GLOBAL CA", 76}, + {"1\0130\011\006\003U\004\006\023\002FI1\0170\015\006\003U\004\012\023\006SONERA1\0310\027\006\003U\004\003\023\020SONERA CLASS1 CA", 133}, + {"1\0260\024\006\003U\004\012\023\015CISCO SYSTEMS1\0330\031\006\003U\004\003\023\022CISCO ROOT CA 2048", 40}, + {"1\0130\011\006\003U\004\006\023\002GB1\0300\026\006\003U\004\012\023\017TRUSTIS LIMITED1\0340\032\006\003U\004\013\023\023TRUSTIS FPS ROOT CA", 157}, + {"1\0130\011\006\003U\004\006\023\002US1\0240\022\006\003U\004\012\014\013AffirmTrust1\0340\032\006\003U\004\003\014\023AffirmTrust Premium", 15}, + {"1\0130\011\006\003U\004\006\023\002FR1\0210\017\006\003U\004\012\023\010CERTPLUS1\0330\031\006\003U\004\003\023\022CLASS 2 PRIMARY CA", 38}, + {"1\0130\011\006\003U\004\006\023\002US1 0\036\006\003U\004\012\023\027SECURETRUST CORPORATION1\0270\025\006\003U\004\003\023\016SECURETRUST CA", 159}, + {"1\0130\011\006\003U\004\006\023\002US1\0240\022\006\003U\004\012\014\013AffirmTrust1\0370\035\006\003U\004\003\014\026AffirmTrust Commercial", 17}, + {"1\0130\011\006\003U\004\006\023\002US1 0\036\006\003U\004\012\023\027SECURETRUST CORPORATION1\0310\027\006\003U\004\003\023\020SECURE GLOBAL CA", 158}, + {"1\0130\011\006\003U\004\006\023\002US1\0300\026\006\003U\004\012\023\017U.S. GOVERNMENT1\0140\012\006\003U\004\013\023\003ECA1\0240\022\006\003U\004\003\023\013ECA ROOT CA", 60}, + {"1\0130\011\006\003U\004\006\023\002DK1\0250\023\006\003U\004\012\023\014TDC INTERNET1\0350\033\006\003U\004\013\023\024TDC INTERNET ROOT CA", 152}, + {"1\0130\011\006\003U\004\006\023\002US1\0200\016\006\003U\004\012\023\007EQUIFAX1-0+\006\003U\004\013\023$EQUIFAX SECURE CERTIFICATE AUTHORITY", 64}, + {"1\0130\011\006\003U\004\006\023\002US1\0240\022\006\003U\004\012\014\013AffirmTrust1 0\036\006\003U\004\003\014\027AffirmTrust Premium ECC", 14}, + {"1\0130\011\006\003U\004\006\023\002JP1\0300\026\006\003U\004\012\023\017SECOM TRUST.NET1'0%\006\003U\004\013\023\036SECURITY COMMUNICATION ROOTCA1", 125}, + {"1\0130\011\006\003U\004\006\023\002FI1\0170\015\006\003U\004\012\023\006SONERA1\0310\027\006\003U\004\003\023\020SONERA CLASS2 CA", 134}, + {"1$0\"\006\003U\004\012\023\033DIGITAL SIGNATURE TRUST CO.1\0270\025\006\003U\004\003\023\016DST ROOT CA X3", 84}, + {"1\0130\011\006\003U\004\006\023\002US1\0260\024\006\003U\004\012\023\015GEOTRUST INC.110/\006\003U\004\003\023(GEOTRUST PRIMARY CERTIFICATION AUTHORITY", 75}, + {"1\0130\011\006\003U\004\006\023\002AT1\0200\016\006\003U\004\012\023\007A-TRUST1\0310\027\006\003U\004\013\023\020A-TRUST-NQUAL-011\0310\027\006\003U\004\003\023\020A-TRUST-NQUAL-01", 4}, + {"1\0130\011\006\003U\004\006\023\002JP1\0160\014\006\003U\004\012\023\005LGPKI1\0320\030\006\003U\004\013\023\021APPLICATION CA G2", 23}, + {"1\0130\011\006\003U\004\006\023\002US1\0300\026\006\003U\004\012\023\017U.S. GOVERNMENT1\0150\013\006\003U\004\013\023\004FBCA1\0260\024\006\003U\004\003\023\015COMMON POLICY", 70}, + {"1\0130\011\006\003U\004\006\023\002CH1\0250\023\006\003U\004\012\023\014SWISSSIGN AG1\0370\035\006\003U\004\003\023\026SWISSSIGN GOLD CA - G2", 142}, + {"1\0130\011\006\003U\004\006\023\002FR1\0230\021\006\003U\004\012\023\012CERTINOMIS1\0340\032\006\003U\004\013\023\023AC RACINE - ROOT CA1\0230\021\006\003U\004\003\023\012CERTINOMIS", 8}, + {"1\0130\011\006\003U\004\006\023\002US1\0300\026\006\003U\004\012\023\017U.S. GOVERNMENT1\0140\012\006\003U\004\013\023\003DOD1\0140\012\006\003U\004\013\023\003PKI1\0340\032\006\003U\004\003\023\023DOD CLASS 3 ROOT CA", 56}, + {"1\0130\011\006\003U\004\006\023\002JP1+0)\006\003U\004\012\023\"JAPAN CERTIFICATION SERVICES, INC.1\0340\032\006\003U\004\003\023\023SECURESIGN ROOTCA11", 94}, + {"1\0130\011\006\003U\004\006\023\002BM1\0310\027\006\003U\004\012\023\020QUOVADIS LIMITED1\0330\031\006\003U\004\003\023\022QUOVADIS ROOT CA 2", 119}, + {"1\0130\011\006\003U\004\006\023\002US1\0270\025\006\003U\004\012\023\016VERISIGN, INC.1705\006\003U\004\013\023.CLASS 1 PUBLIC PRIMARY CERTIFICATION AUTHORITY", 104}, + {"1\0130\011\006\003U\004\006\023\002CH1\0250\023\006\003U\004\012\023\014SWISSSIGN AG1#0!\006\003U\004\003\023\032SWISSSIGN PLATINUM CA - G2", 143}, + {"1\0130\011\006\003U\004\006\023\002BM1\0310\027\006\003U\004\012\023\020QUOVADIS LIMITED1\0330\031\006\003U\004\003\023\022QUOVADIS ROOT CA 3", 120}, + {"1\0130\011\006\003U\004\006\023\002KR1\0150\013\006\003U\004\012\014\004KISA1.0,\006\003U\004\013\014%Korea Certification Authority Central1\0260\024\006\003U\004\003\014\015KISA RootCA 1", 95}, + {"1\0130\011\006\003U\004\006\023\002US1\0300\026\006\003U\004\012\023\017U.S. GOVERNMENT1\0140\012\006\003U\004\013\023\003DOD1\0140\012\006\003U\004\013\023\003PKI1\0260\024\006\003U\004\003\023\015DOD ROOT CA 2", 57}, + {"1\0130\011\006\003U\004\006\023\002US1\0150\013\006\003U\004\012\023\004VISA1/0-\006\003U\004\013\023&VISA INTERNATIONAL SERVICE ASSOCIATION1\0340\032\006\003U\004\003\023\023VISA ECOMMERCE ROOT", 123}, + {"1\0130\011\006\003U\004\006\023\002CH1\0160\014\006\003U\004\012\023\005ADMIN1\0210\017\006\003U\004\013\023\010SERVICES1\"0 \006\003U\004\013\023\031CERTIFICATION AUTHORITIES1\0260\024\006\003U\004\003\023\015ADMIN-ROOT-CA", 28}, + {"1\0130\011\006\003U\004\006\023\002CH1\0160\014\006\003U\004\012\023\005ADMIN1\0210\017\006\003U\004\013\023\010SERVICES1\"0 \006\003U\004\013\023\031CERTIFICATION AUTHORITIES1\0270\025\006\003U\004\003\023\016ADMINCA-CD-T01", 29}, + {"1\0130\011\006\003U\004\006\023\002JP1\0150\013\006\003U\004\012\014\004JPKI1)0'\006\003U\004\013\014 Prefectural Association For JPKI1\0210\017\006\003U\004\013\014\010BridgeCA", 0}, + {"1\0130\011\006\003U\004\006\023\002SE1\0240\022\006\003U\004\012\023\013ADDTRUST AB1&0$\006\003U\004\013\023\035ADDTRUST EXTERNAL TTP NETWORK1\"0 \006\003U\004\003\023\031ADDTRUST EXTERNAL CA ROOT", 11}, + {"1\0130\011\006\003U\004\006\023\002US1!0\037\006\003U\004\012\023\030NETWORK SOLUTIONS L.L.C.100.\006\003U\004\003\023'NETWORK SOLUTIONS CERTIFICATE AUTHORITY", 103}, + {"1\0130\011\006\003U\004\006\023\002SK1\0230\021\006\003U\004\007\023\012BRATISLAVA1\0230\021\006\003U\004\012\023\012DISIG A.S.1\0210\017\006\003U\004\003\023\010CA DISIG", 55}, + {"1\0130\011\006\003U\004\006\023\002US1\0270\025\006\003U\004\012\023\016VERISIGN, INC.1705\006\003U\004\013\023.CLASS 2 PUBLIC PRIMARY CERTIFICATION AUTHORITY", 106}, + {"1\0130\011\006\003U\004\006\023\002CH1\0250\023\006\003U\004\012\023\014SWISSSIGN AG1!0\037\006\003U\004\003\023\030SWISSSIGN SILVER CA - G2", 144}, + {"1\0130\011\006\003U\004\006\023\002BE1\0310\027\006\003U\004\012\023\020GLOBALSIGN NV-SA1\0200\016\006\003U\004\013\023\007ROOT CA1\0330\031\006\003U\004\003\023\022GLOBALSIGN ROOT CA", 78}, + {"1\0130\011\006\003U\004\006\023\002US1\0230\021\006\003U\004\012\023\012APPLE INC.1&0$\006\003U\004\013\023\035APPLE CERTIFICATION AUTHORITY1\0260\024\006\003U\004\003\023\015APPLE ROOT CA", 24}, + {"1\0130\011\006\003U\004\006\023\002US1%0#\006\003U\004\012\023\034STARFIELD TECHNOLOGIES, INC.1200\006\003U\004\013\023)STARFIELD CLASS 2 CERTIFICATION AUTHORITY", 132}, + {"1\0130\011\006\003U\004\006\023\002US1\0270\025\006\003U\004\012\023\016VERISIGN, INC.1705\006\003U\004\013\023.CLASS 3 PUBLIC PRIMARY CERTIFICATION AUTHORITY", 108}, + {"1\0130\011\006\003U\004\006\023\002JP1%0#\006\003U\004\012\023\034SECOM TRUST SYSTEMS CO.,LTD.1*0(\006\003U\004\013\023!SECURITY COMMUNICATION EV ROOTCA1", 126}, + {"1\0130\011\006\003U\004\006\023\002US1\0250\023\006\003U\004\012\023\014DIGICERT INC1\0310\027\006\003U\004\013\023\020WWW.DIGICERT.COM1 0\036\006\003U\004\003\023\027DIGICERT GLOBAL ROOT CA", 53}, + {"1\0300\026\006\011*\206H\206\367\015\001\011\001\026\011pki@sk.ee1\0130\011\006\003U\004\006\023\002EE1\"0 \006\003U\004\012\023\031AS SERTIFITSEERIMISKESKUS1\0200\016\006\003U\004\003\023\007JUUR-SK", 68}, + {"1\0130\011\006\003U\004\006\023\002US1\0340\032\006\003U\004\012\023\023AMERICA ONLINE INC.1604\006\003U\004\003\023-AMERICA ONLINE ROOT CERTIFICATION AUTHORITY 1", 18}, + {"1\0130\011\006\003U\004\006\023\002TW1\0220\020\006\003U\004\012\014\011TAIWAN-CA1\0200\016\006\003U\004\013\014\007Root CA1*0(\006\003U\004\003\014!TWCA Root Certification Authority", 164}, + {"1\0130\011\006\003U\004\006\023\002PL1\"0 \006\003U\004\012\023\031UNIZETO TECHNOLOGIES S.A.1'0%\006\003U\004\013\023\036CERTUM CERTIFICATION AUTHORITY1\"0 \006\003U\004\003\023\031CERTUM TRUSTED NETWORK CA", 116}, + {"1$0\"\006\003U\004\012\023\033DIGITAL SIGNATURE TRUST CO.1\0270\025\006\003U\004\003\023\016DST ROOT CA X4", 58}, + {"1\0130\011\006\003U\004\006\023\002TW1#0!\006\003U\004\012\014\032Chunghwa Telecom Co., Ltd.1*0(\006\003U\004\013\014!ePKI Root Certification Authority", 39}, + {"1\0130\011\006\003U\004\006\023\002SE1\0240\022\006\003U\004\012\023\013ADDTRUST AB1\0350\033\006\003U\004\013\023\024ADDTRUST TTP NETWORK1 0\036\006\003U\004\003\023\027ADDTRUST PUBLIC CA ROOT", 12}, + {"1\0130\011\006\003U\004\006\023\002SE1\0240\022\006\003U\004\012\023\013ADDTRUST AB1\0350\033\006\003U\004\013\023\024ADDTRUST TTP NETWORK1!0\037\006\003U\004\003\023\030ADDTRUST CLASS 1 CA ROOT", 10}, + {"1\0130\011\006\003U\004\006\023\002US1\0300\026\006\003U\004\012\023\017GTE CORPORATION1'0%\006\003U\004\013\023\036GTE CYBERTRUST SOLUTIONS, INC.1#0!\006\003U\004\003\023\032GTE CYBERTRUST GLOBAL ROOT", 82}, + {"1\0130\011\006\003U\004\006\023\002US1\0250\023\006\003U\004\012\023\014DIGICERT INC1\0310\027\006\003U\004\013\023\020WWW.DIGICERT.COM1+0)\006\003U\004\003\023\"DIGICERT HIGH ASSURANCE EV ROOT CA", 54}, + {"1\0130\011\006\003U\004\006\023\002US1!0\037\006\003U\004\012\023\030THE GO DADDY GROUP, INC.110/\006\003U\004\013\023(GO DADDY CLASS 2 CERTIFICATION AUTHORITY", 74}, + {"1\0130\011\006\003U\004\006\023\002DE1\0340\032\006\003U\004\012\023\023TC TRUSTCENTER GMBH1$0\"\006\003U\004\013\023\033TC TRUSTCENTER UNIVERSAL CA1&0$\006\003U\004\003\023\035TC TRUSTCENTER UNIVERSAL CA I", 149}, + {"1\0130\011\006\003U\004\006\023\002DE1\0340\032\006\003U\004\012\023\023TC TRUSTCENTER GMBH1$0\"\006\003U\004\013\023\033TC TRUSTCENTER UNIVERSAL CA1'0%\006\003U\004\003\023\036TC TRUSTCENTER UNIVERSAL CA II", 150}, + {"1\0130\011\006\003U\004\006\023\002DE1\0340\032\006\003U\004\012\023\023TC TRUSTCENTER GMBH1$0\"\006\003U\004\013\023\033TC TRUSTCENTER UNIVERSAL CA1(0&\006\003U\004\003\023\037TC TRUSTCENTER UNIVERSAL CA III", 156}, + {"1\0130\011\006\003U\004\006\023\002US1\0340\032\006\003U\004\012\023\023AMERICA ONLINE INC.1604\006\003U\004\003\023-AMERICA ONLINE ROOT CERTIFICATION AUTHORITY 2", 19}, + {"1\0130\011\006\003U\004\006\023\002KR1\0150\013\006\003U\004\012\023\004KISA1.0,\006\003U\004\013\023%KOREA CERTIFICATION AUTHORITY CENTRAL1\0260\024\006\003U\004\003\023\015KISA ROOTCA 3", 96}, + {"1\0130\011\006\003U\004\006\023\002PL1\0330\031\006\003U\004\012\023\022UNIZETO SP. Z O.O.1\0220\020\006\003U\004\003\023\011CERTUM CA", 167}, + {"1\0310\027\006\003U\004\012\023\020RSA SECURITY INC1\0350\033\006\003U\004\013\023\024RSA SECURITY 2048 V3", 124}, + {"1\0130\011\006\003U\004\006\023\002CH1\0210\017\006\003U\004\012\023\010SWISSCOM1%0#\006\003U\004\013\023\034DIGITAL CERTIFICATE SERVICES1\0330\031\006\003U\004\003\023\022SWISSCOM ROOT CA 1", 141}, + {"1\0130\011\006\003U\004\006\023\002US1\0250\023\006\003U\004\012\023\014DIGICERT INC1\0310\027\006\003U\004\013\023\020WWW.DIGICERT.COM1$0\"\006\003U\004\003\023\033DIGICERT ASSURED ID ROOT CA", 52}, + {"1\0130\011\006\003U\004\006\023\002DK1\0140\012\006\003U\004\012\023\003KMD1\0170\015\006\003U\004\013\023\006KMD-CA1\0260\024\006\003U\004\003\023\015KMD-CA SERVER1 0\036\006\012\011\222&\211\223\362,d\001\003\024\020infoca@kmd-ca.dk", 98}, + {"1\0130\011\006\003U\004\006\023\002DE1\0340\032\006\003U\004\012\023\023DEUTSCHE TELEKOM AG1\0370\035\006\003U\004\013\023\026T-TELESEC TRUST CENTER1#0!\006\003U\004\003\023\032DEUTSCHE TELEKOM ROOT CA 2", 51}, + {"1\0130\011\006\003U\004\006\023\002US1\0130\011\006\003U\004\010\023\002UT1\0270\025\006\003U\004\007\023\016SALT LAKE CITY1\0360\034\006\003U\004\012\023\025THE USERTRUST NETWORK1!0\037\006\003U\004\013\023\030HTTP://WWW.USERTRUST.COM1\0350\033\006\003U\004\003\023\024UTN-USERFIRST-OBJECT", 171}, + {"1\0130\011\006\003U\004\006\023\002NO1\0350\033\006\003U\004\012\014\024Buypass AS-9831633271\0350\033\006\003U\004\003\014\024Buypass Class 2 CA 1", 31}, + {"1\0130\011\006\003U\004\006\023\002US1\0130\011\006\003U\004\010\023\002UT1\0270\025\006\003U\004\007\023\016SALT LAKE CITY1\0360\034\006\003U\004\012\023\025THE USERTRUST NETWORK1!0\037\006\003U\004\013\023\030HTTP://WWW.USERTRUST.COM1\0370\035\006\003U\004\003\023\026UTN-USERFIRST-HARDWARE", 169}, + {"1\0130\011\006\003U\004\006\023\002US1\0130\011\006\003U\004\010\023\002UT1\0270\025\006\003U\004\007\023\016SALT LAKE CITY1\0360\034\006\003U\004\012\023\025THE USERTRUST NETWORK1!0\037\006\003U\004\013\023\030HTTP://WWW.USERTRUST.COM1\0330\031\006\003U\004\003\023\022UTN - DATACORP SGC", 172}, + {"1\0130\011\006\003U\004\006\023\002JP1%0#\006\003U\004\012\023\034SECOM TRUST SYSTEMS CO.,LTD.1'0%\006\003U\004\013\023\036SECURITY COMMUNICATION ROOTCA2", 127}, + {"1\0130\011\006\003U\004\006\023\002AT1H0F\006\003U\004\012\014?A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH1\0300\026\006\003U\004\013\014\017A-Trust-Qual-021\0300\026\006\003U\004\003\014\017A-Trust-Qual-02", 7}, + {"1\0130\011\006\003U\004\006\023\002NO1\0350\033\006\003U\004\012\014\024Buypass AS-9831633271\0350\033\006\003U\004\003\014\024Buypass Class 3 CA 1", 32}, + {"1\0130\011\006\003U\004\006\023\002US1\0350\033\006\003U\004\012\023\024AOL TIME WARNER INC.1\0340\032\006\003U\004\013\023\023AMERICA ONLINE INC.1705\006\003U\004\003\023.AOL TIME WARNER ROOT CERTIFICATION AUTHORITY 1", 20}, + {"1\0130\011\006\003U\004\006\023\002US1\0240\022\006\003U\004\012\014\013AffirmTrust1\0370\035\006\003U\004\003\014\026AffirmTrust Networking", 16}, + {"1\0130\011\006\003U\004\006\023\002US1\0300\026\006\003U\004\012\023\017U.S. GOVERNMENT1\0150\013\006\003U\004\013\023\004FPKI1!0\037\006\003U\004\003\023\030FEDERAL COMMON POLICY CA", 71}, + {"1\0130\011\006\003U\004\006\023\002IL1\0260\024\006\003U\004\012\023\015STARTCOM LTD.1+0)\006\003U\004\013\023\"SECURE DIGITAL CERTIFICATE SIGNING1)0'\006\003U\004\003\023 STARTCOM CERTIFICATION AUTHORITY", 139}, + {"1\0130\011\006\003U\004\006\023\002AT1H0F\006\003U\004\012\014?A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH1\0310\027\006\003U\004\013\014\020A-Trust-nQual-031\0310\027\006\003U\004\003\014\020A-Trust-nQual-03", 5}, + {"1\0130\011\006\003U\004\006\023\002US1\0250\023\006\003U\004\012\023\014THAWTE, INC.1806\006\003U\004\013\023/(C) 2007 THAWTE, INC. - FOR AUTHORIZED USE ONLY1$0\"\006\003U\004\003\023\033THAWTE PRIMARY ROOT CA - G2", 154}, + {"1\0130\011\006\003U\004\006\023\002US1\0130\011\006\003U\004\010\023\002UT1\0270\025\006\003U\004\007\023\016SALT LAKE CITY1\0360\034\006\003U\004\012\023\025THE USERTRUST NETWORK1!0\037\006\003U\004\013\023\030HTTP://WWW.USERTRUST.COM1+0)\006\003U\004\003\023\"UTN-USERFIRST-NETWORK APPLICATIONS", 170}, + {"1\0130\011\006\003U\004\006\023\002ZA1\0250\023\006\003U\004\010\023\014WESTERN CAPE1\0240\022\006\003U\004\007\023\013DURBANVILLE1\0170\015\006\003U\004\012\023\006THAWTE1\0350\033\006\003U\004\013\023\024THAWTE CERTIFICATION1\0370\035\006\003U\004\003\023\026THAWTE TIMESTAMPING CA", 155}, + {"1\0130\011\006\003U\004\006\023\002EU1'0%\006\003U\004\012\023\036AC CAMERFIRMA SA CIF A827432871#0!\006\003U\004\013\023\032HTTP://WWW.CHAMBERSIGN.ORG1 0\036\006\003U\004\003\023\027GLOBAL CHAMBERSIGN ROOT", 122}, + {"1\0130\011\006\003U\004\006\023\002HK1\0260\024\006\003U\004\012\023\015HONGKONG POST1 0\036\006\003U\004\003\023\027HONGKONG POST ROOT CA 1", 83}, + {"1\0130\011\006\003U\004\006\023\002EU1'0%\006\003U\004\012\023\036AC CAMERFIRMA SA CIF A827432871#0!\006\003U\004\013\023\032HTTP://WWW.CHAMBERSIGN.ORG1\"0 \006\003U\004\003\023\031CHAMBERS OF COMMERCE ROOT", 121}, + {"1\0130\011\006\003U\004\006\023\002CH1\0200\016\006\003U\004\012\023\007WISEKEY1\0330\031\006\003U\004\013\023\022COPYRIGHT (C) 20051\"0 \006\003U\004\013\023\031OISTE FOUNDATION ENDORSED1(0&\006\003U\004\003\023\037OISTE WISEKEY GLOBAL ROOT GA CA", 181}, + {"1\0130\011\006\003U\004\006\023\002US1\0340\032\006\003U\004\012\023\023EQUIFAX SECURE INC.1-0+\006\003U\004\003\023$EQUIFAX SECURE GLOBAL EBUSINESS CA-1", 67}, + {"1\0130\011\006\003U\004\006\023\002US1\0350\033\006\003U\004\012\023\024AOL TIME WARNER INC.1\0340\032\006\003U\004\013\023\023AMERICA ONLINE INC.1705\006\003U\004\003\023.AOL TIME WARNER ROOT CERTIFICATION AUTHORITY 2", 21}, + {"1\0130\011\006\003U\004\006\023\002JP1\0340\032\006\003U\004\012\023\023JAPANESE GOVERNMENT1\0260\024\006\003U\004\013\023\015APPLICATIONCA", 22}, + {"1\0130\011\006\003U\004\006\023\002DE1\0340\032\006\003U\004\012\023\023TC TRUSTCENTER GMBH1\"0 \006\003U\004\013\023\031TC TRUSTCENTER CLASS 2 CA1%0#\006\003U\004\003\023\034TC TRUSTCENTER CLASS 2 CA II", 146}, + {"1\0130\011\006\003U\004\006\023\002US1\0240\022\006\003U\004\012\023\013WELLS FARGO1,0*\006\003U\004\013\023#WELLS FARGO CERTIFICATION AUTHORITY1/0-\006\003U\004\003\023&WELLS FARGO ROOT CERTIFICATE AUTHORITY", 180}, + {"1\0130\011\006\003U\004\006\023\002CA1\0200\016\006\003U\004\010\023\007ONTARIO1\0200\016\006\003U\004\007\023\007TORONTO1\0350\033\006\003U\004\012\023\024ECHOWORX CORPORATION1\0370\035\006\003U\004\013\023\026CERTIFICATION SERVICES1\0320\030\006\003U\004\003\023\021ECHOWORX ROOT CA2", 61}, + {"1\0130\011\006\003U\004\006\023\002BM1\0310\027\006\003U\004\012\023\020QUOVADIS LIMITED1%0#\006\003U\004\013\023\034ROOT CERTIFICATION AUTHORITY1.0,\006\003U\004\003\023%QUOVADIS ROOT CERTIFICATION AUTHORITY", 118}, + {"1\0130\011\006\003U\004\006\023\002DE1\0340\032\006\003U\004\012\023\023TC TRUSTCENTER GMBH1\"0 \006\003U\004\013\023\031TC TRUSTCENTER CLASS 3 CA1%0#\006\003U\004\003\023\034TC TRUSTCENTER CLASS 3 CA II", 147}, + {"1\0130\011\006\003U\004\006\023\002GB1\0330\031\006\003U\004\010\023\022GREATER MANCHESTER1\0200\016\006\003U\004\007\023\007SALFORD1\0320\030\006\003U\004\012\023\021COMODO CA LIMITED1'0%\006\003U\004\003\023\036COMODO CERTIFICATION AUTHORITY", 50}, + {"1\0130\011\006\003U\004\006\023\002IE1\0220\020\006\003U\004\012\023\011BALTIMORE1\0230\021\006\003U\004\013\023\012CYBERTRUST1\"0 \006\003U\004\003\023\031BALTIMORE CYBERTRUST ROOT", 30}, + {"1 0\036\006\003U\004\013\023\027GLOBALSIGN ROOT CA - R21\0230\021\006\003U\004\012\023\012GLOBALSIGN1\0230\021\006\003U\004\003\023\012GLOBALSIGN", 80}, + {"1\0130\011\006\003U\004\006\023\002GB1\0330\031\006\003U\004\010\014\022Greater Manchester1\0200\016\006\003U\004\007\014\007Salford1\0320\030\006\003U\004\012\014\021Comodo CA Limited1%0#\006\003U\004\003\014\034Trusted Certificate Services", 49}, + {"1\0130\011\006\003U\004\006\023\002HU1\0210\017\006\003U\004\007\023\010BUDAPEST1'0%\006\003U\004\012\023\036NETLOCK HALOZATBIZTONSAGI KFT.1\0320\030\006\003U\004\013\023\021TANUSITVANYKIADOK1200\006\003U\004\003\023)NETLOCK UZLETI (CLASS B) TANUSITVANYKIADO", 173}, + {"1\0130\011\006\003U\004\006\023\002HU1\0210\017\006\003U\004\007\023\010BUDAPEST1'0%\006\003U\004\012\023\036NETLOCK HALOZATBIZTONSAGI KFT.1\0320\030\006\003U\004\013\023\021TANUSITVANYKIADOK1402\006\003U\004\003\023+NETLOCK EXPRESSZ (CLASS C) TANUSITVANYKIADO", 69}, + {"1 0\036\006\003U\004\013\023\027GLOBALSIGN ROOT CA - R31\0230\021\006\003U\004\012\023\012GLOBALSIGN1\0230\021\006\003U\004\003\023\012GLOBALSIGN", 77}, + {"1\0130\011\006\003U\004\006\023\002HU1\0210\017\006\003U\004\007\014\010Budapest1\0250\023\006\003U\004\012\014\014NetLock Kft.1705\006\003U\004\013\014.Tan\303\272s\303\255tv\303\241nykiad\303\263k (Certification Services)1503\006\003U\004\003\014,NetLock Arany (Class Gold) F\305\221tan\303\272s\303\255tv\303\241ny", 101}, + {"1\0130\011\006\003U\004\006\023\002FI1\0200\016\006\003U\004\010\023\007FINLAND1!0\037\006\003U\004\012\023\030VAESTOREKISTERIKESKUS CA1)0'\006\003U\004\013\023 CERTIFICATION AUTHORITY SERVICES1\0310\027\006\003U\004\013\023\020VARMENNEPALVELUT1\0310\027\006\003U\004\003\023\020VRK GOV. ROOT CA", 117}, + {"1\0130\011\006\003U\004\006\023\002US1\0360\034\006\003U\004\013\023\025WWW.XRAMPSECURITY.COM1$0\"\006\003U\004\012\023\033XRAMP SECURITY SERVICES INC1-0+\006\003U\004\003\023$XRAMP GLOBAL CERTIFICATION AUTHORITY", 182}, + {"1\0130\011\006\003U\004\006\023\002US1\0260\024\006\003U\004\012\023\015ENTRUST, INC.1907\006\003U\004\013\0230WWW.ENTRUST.NET/CPS IS INCORPORATED BY REFERENCE1\0370\035\006\003U\004\013\023\026(C) 2006 ENTRUST, INC.1-0+\006\003U\004\003\023$ENTRUST ROOT CERTIFICATION AUTHORITY", 62}, + {"1$0\"\006\003U\004\007\023\033VALICERT VALIDATION NETWORK1\0270\025\006\003U\004\012\023\016VALICERT, INC.1503\006\003U\004\013\023,VALICERT CLASS 1 POLICY VALIDATION AUTHORITY1!0\037\006\003U\004\003\023\030HTTP://WWW.VALICERT.COM/1 0\036\006\011*\206H\206\367\015\001\011\001\026\021info@valicert.com", 174}, + {"1\0130\011\006\003U\004\006\023\002SE1\0240\022\006\003U\004\012\023\013ADDTRUST AB1\0350\033\006\003U\004\013\023\024ADDTRUST TTP NETWORK1#0!\006\003U\004\003\023\032ADDTRUST QUALIFIED CA ROOT", 13}, + {"1\0130\011\006\003U\004\006\023\002US1\0240\022\006\003U\004\012\023\013ENTRUST.NET1;09\006\003U\004\013\0232WWW.ENTRUST.NET/CPS INCORP. BY REF. (LIMITS LIAB.)1%0#\006\003U\004\013\023\034(C) 1999 ENTRUST.NET LIMITED1:08\006\003U\004\003\0231ENTRUST.NET SECURE SERVER CERTIFICATION AUTHORITY", 63}, + {"1\0130\011\006\003U\004\006\023\002ES1B0@\006\003U\004\003\0149Autoridad de Certificacion Firmaprofesional CIF A62634068", 72}, + {"1\0130\011\006\003U\004\006\023\002US1\0340\032\006\003U\004\012\023\023EQUIFAX SECURE INC.1&0$\006\003U\004\003\023\035EQUIFAX SECURE EBUSINESS CA-1", 65}, + {"1\0130\011\006\003U\004\006\023\002US1\0130\011\006\003U\004\010\023\002UT1\0270\025\006\003U\004\007\023\016SALT LAKE CITY1\0360\034\006\003U\004\012\023\025THE USERTRUST NETWORK1!0\037\006\003U\004\013\023\030HTTP://WWW.USERTRUST.COM1604\006\003U\004\003\023-UTN-USERFIRST-CLIENT AUTHENTICATION AND EMAIL", 168}, + {"1\0130\011\006\003U\004\006\023\002NL1\0360\034\006\003U\004\012\023\025STAAT DER NEDERLANDEN1&0$\006\003U\004\003\023\035STAAT DER NEDERLANDEN ROOT CA", 136}, + {"1\0130\011\006\003U\004\006\023\002DK1\0140\012\006\003U\004\012\023\003KMD1\0170\015\006\003U\004\013\023\006KMD-CA1#0!\006\003U\004\003\023\032KMD-CA KVALIFICERET PERSON", 97}, + {"1\0130\011\006\003U\004\006\023\002GB1\0330\031\006\003U\004\010\014\022Greater Manchester1\0200\016\006\003U\004\007\014\007Salford1\0320\030\006\003U\004\012\014\021Comodo CA Limited1!0\037\006\003U\004\003\014\030AAA Certificate Services", 47}, + {"1\0130\011\006\003U\004\006\023\002US1\0250\023\006\003U\004\012\023\014THAWTE, INC.1(0&\006\003U\004\013\023\037CERTIFICATION SERVICES DIVISION1806\006\003U\004\013\023/(C) 2006 THAWTE, INC. - FOR AUTHORIZED USE ONLY1\0370\035\006\003U\004\003\023\026THAWTE PRIMARY ROOT CA", 153}, + {"1\0130\011\006\003U\004\006\023\002NL1\0360\034\006\003U\004\012\014\025Staat der Nederlanden1+0)\006\003U\004\003\014\"Staat der Nederlanden Root CA - G2", 135}, + {"1\0130\011\006\003U\004\006\023\002GB1\0330\031\006\003U\004\010\014\022Greater Manchester1\0200\016\006\003U\004\007\014\007Salford1\0320\030\006\003U\004\012\014\021Comodo CA Limited1$0\"\006\003U\004\003\014\033Secure Certificate Services", 48}, + {"1$0\"\006\003U\004\007\023\033VALICERT VALIDATION NETWORK1\0270\025\006\003U\004\012\023\016VALICERT, INC.1503\006\003U\004\013\023,VALICERT CLASS 2 POLICY VALIDATION AUTHORITY1!0\037\006\003U\004\003\023\030HTTP://WWW.VALICERT.COM/1 0\036\006\011*\206H\206\367\015\001\011\001\026\021info@valicert.com", 175}, + {"1\0130\011\006\003U\004\006\023\002US1\0200\016\006\003U\004\010\023\007ARIZONA1\0230\021\006\003U\004\007\023\012SCOTTSDALE1%0#\006\003U\004\012\023\034STARFIELD TECHNOLOGIES, INC.1200\006\003U\004\003\023)STARFIELD ROOT CERTIFICATE AUTHORITY - G2", 137}, + {"1\0130\011\006\003U\004\006\023\002US1\0200\016\006\003U\004\010\023\007ARIZONA1\0230\021\006\003U\004\007\023\012SCOTTSDALE1\0320\030\006\003U\004\012\023\021GODADDY.COM, INC.110/\006\003U\004\003\023(GO DADDY ROOT CERTIFICATE AUTHORITY - G2", 81}, + {"1$0\"\006\003U\004\007\023\033VALICERT VALIDATION NETWORK1\0270\025\006\003U\004\012\023\016VALICERT, INC.1503\006\003U\004\013\023,VALICERT CLASS 3 POLICY VALIDATION AUTHORITY1!0\037\006\003U\004\003\023\030HTTP://WWW.VALICERT.COM/1 0\036\006\011*\206H\206\367\015\001\011\001\026\021info@valicert.com", 176}, + {"1\0130\011\006\003U\004\006\023\002CO1G0E\006\003U\004\012\014>Sociedad Cameral de Certificaci\303\263n Digital - Certic\303\241mara S.A.1#0!\006\003U\004\003\014\032AC Ra\303\255z Certic\303\241mara S.A.", 9}, + {"1?0=\006\003U\004\003\0146T\303\234RKTRUST Elektronik Sertifika Hizmet Sa\304\237lay\304\261c\304\261s\304\2611\0130\011\006\003U\004\006\023\002TR1\0170\015\006\003U\004\007\014\006Ankara1]0[\006\003U\004\012\014TT\303\234RKTRUST Bilgi \304\260leti\305\237im ve Bili\305\237im G\303\274venli\304\237i Hizmetleri A.\305\236. (c) Kas\304\261m 2005", 162}, + {"1\0130\011\006\003U\004\006\023\002ZA1\0250\023\006\003U\004\010\023\014WESTERN CAPE1\0220\020\006\003U\004\007\023\011CAPE TOWN1\0350\033\006\003U\004\012\023\024THAWTE CONSULTING CC1(0&\006\003U\004\013\023\037CERTIFICATION SERVICES DIVISION1!0\037\006\003U\004\003\023\030THAWTE PREMIUM SERVER CA1(0&\006\011*\206H\206\367\015\001\011\001\026\031premium-server@thawte.com", 130}, + {"1\0130\011\006\003U\004\006\023\002US1\0200\016\006\003U\004\010\023\007ARIZONA1\0230\021\006\003U\004\007\023\012SCOTTSDALE1%0#\006\003U\004\012\023\034STARFIELD TECHNOLOGIES, INC.1;09\006\003U\004\003\0232STARFIELD SERVICES ROOT CERTIFICATE AUTHORITY - G2", 138}, + {"1\0130\011\006\003U\004\006\023\002US1\0270\025\006\003U\004\012\023\016EQUIFAX SECURE1&0$\006\003U\004\013\023\035EQUIFAX SECURE EBUSINESS CA-2", 66}, + {"1?0=\006\003U\004\003\0146T\303\234RKTRUST Elektronik Sertifika Hizmet Sa\304\237lay\304\261c\304\261s\304\2611\0130\011\006\003U\004\006\023\002TR1\0170\015\006\003U\004\007\014\006Ankara1^0\\\006\003U\004\012\014UT\303\234RKTRUST Bilgi \304\260leti\305\237im ve Bili\305\237im G\303\274venli\304\237i Hizmetleri A.\305\236. (c) Aral\304\261k 2007", 163}, + {"1\0130\011\006\003U\004\006\023\002DE1\0340\032\006\003U\004\012\023\023TC TRUSTCENTER GMBH1\"0 \006\003U\004\013\023\031TC TRUSTCENTER CLASS 4 CA1%0#\006\003U\004\003\023\034TC TRUSTCENTER CLASS 4 CA II", 148}, + {"1\0130\011\006\003U\004\006\023\002US1\0350\033\006\003U\004\012\023\024APPLE COMPUTER, INC.1-0+\006\003U\004\013\023$APPLE COMPUTER CERTIFICATE AUTHORITY1)0'\006\003U\004\003\023 APPLE ROOT CERTIFICATE AUTHORITY", 25}, + {"1\0130\011\006\003U\004\006\023\002ZA1\0250\023\006\003U\004\010\023\014WESTERN CAPE1\0220\020\006\003U\004\007\023\011CAPE TOWN1\0350\033\006\003U\004\012\023\024THAWTE CONSULTING CC1(0&\006\003U\004\013\023\037CERTIFICATION SERVICES DIVISION1\0310\027\006\003U\004\003\023\020THAWTE SERVER CA1&0$\006\011*\206H\206\367\015\001\011\001\026\027server-certs@thawte.com", 128}, + {"1\0130\011\006\003U\004\006\023\002ZA1\0250\023\006\003U\004\010\023\014WESTERN CAPE1\0220\020\006\003U\004\007\023\011CAPE TOWN1\0320\030\006\003U\004\012\023\021THAWTE CONSULTING1(0&\006\003U\004\013\023\037CERTIFICATION SERVICES DIVISION1#0!\006\003U\004\003\023\032THAWTE PERSONAL PREMIUM CA1*0(\006\011*\206H\206\367\015\001\011\001\026\033personal-premium@thawte.com", 114}, + {"1\0130\011\006\003U\004\006\023\002CH1\0220\020\006\003U\004\012\023\011SWISSSIGN1200\006\003U\004\003\023)SWISSSIGN CA (RSA IK MAY 6 1999 18:00:58)1\0370\035\006\011*\206H\206\367\015\001\011\001\026\020ca@SwissSign.com", 145}, + {"1\0130\011\006\003U\004\006\023\002ZA1\0250\023\006\003U\004\010\023\014WESTERN CAPE1\0220\020\006\003U\004\007\023\011CAPE TOWN1\0320\030\006\003U\004\012\023\021THAWTE CONSULTING1(0&\006\003U\004\013\023\037CERTIFICATION SERVICES DIVISION1$0\"\006\003U\004\003\023\033THAWTE PERSONAL FREEMAIL CA1+0)\006\011*\206H\206\367\015\001\011\001\026\034personal-freemail@thawte.com", 112}, + {"1\0130\011\006\003U\004\006\023\002HU1\0200\016\006\003U\004\010\023\007HUNGARY1\0210\017\006\003U\004\007\023\010BUDAPEST1'0%\006\003U\004\012\023\036NETLOCK HALOZATBIZTONSAGI KFT.1\0320\030\006\003U\004\013\023\021TANUSITVANYKIADOK1604\006\003U\004\003\023-NETLOCK KOZJEGYZOI (CLASS A) TANUSITVANYKIADO", 99}, + {"1\0130\011\006\003U\004\006\023\002HU1\0210\017\006\003U\004\007\023\010BUDAPEST1'0%\006\003U\004\012\023\036NETLOCK HALOZATBIZTONSAGI KFT.1\0320\030\006\003U\004\013\023\021TANUSITVANYKIADOK1B0@\006\003U\004\003\0239NETLOCK MINOSITETT KOZJEGYZOI (CLASS QA) TANUSITVANYKIADO1\0360\034\006\011*\206H\206\367\015\001\011\001\026\017info@netlock.hu", 102}, + {"1\0130\011\006\003U\004\006\023\002ZA1\0250\023\006\003U\004\010\023\014WESTERN CAPE1\0220\020\006\003U\004\007\023\011CAPE TOWN1\0320\030\006\003U\004\012\023\021THAWTE CONSULTING1(0&\006\003U\004\013\023\037CERTIFICATION SERVICES DIVISION1!0\037\006\003U\004\003\023\030THAWTE PERSONAL BASIC CA1(0&\006\011*\206H\206\367\015\001\011\001\026\031personal-basic@thawte.com", 110}, + {"1\0130\011\006\003U\004\006\023\002AT1\0200\016\006\003U\004\010\023\007AUSTRIA1\0170\015\006\003U\004\007\023\006VIENNA1:08\006\003U\004\012\0231ARGE DATEN - AUSTRIAN SOCIETY FOR DATA PROTECTION1%0#\006\003U\004\013\023\034A-CERT CERTIFICATION SERVICE1\0300\026\006\003U\004\003\023\017A-CERT ADVANCED1\0350\033\006\011*\206H\206\367\015\001\011\001\026\016info@a-cert.at", 3}, + {"1\0130\011\006\003U\004\006\023\002AT1\201\2130\201\210\006\003U\004\012\036\201\200\000A\000-\000T\000r\000u\000s\000t\000 \000G\000e\000s\000.\000 \000f\000\374\000r\000 \000S\000i\000c\000h\000e\000r\000h\000e\000i\000t\000s\000s\000y\000s\000t\000e\000m\000e\000 \000i\000m\000 \000e\000l\000e\000k\000t\000r\000.\000 \000D\000a\000t\000e\000n\000v\000e\000r\000k\000e\000h\000r\000 \000G\000m\000b\000H1\0300\026\006\003U\004\013\023\017A-TRUST-QUAL-011\0300\026\006\003U\004\003\023\017A-TRUST-QUAL-01", 6}, + {"1\0130\011\006\003U\004\006\023\002US1 0\036\006\003U\004\012\014\027Wells Fargo WellsSecure1\0340\032\006\003U\004\013\014\023Wells Fargo Bank NA1604\006\003U\004\003\014-WellsSecure Public Root Certificate Authority", 179}, + {"1?0=\006\003U\004\003\0146T\303\234RKTRUST Elektronik Sertifika Hizmet Sa\304\237lay\304\261c\304\261s\304\2611\0130\011\006\003U\004\006\014\002TR1\0170\015\006\003U\004\007\014\006ANKARA1V0T\006\003U\004\012\014M(c) 2005 T\303\234RKTRUST Bilgi \304\260leti\305\237im ve Bili\305\237im G\303\274venli\304\237i Hizmetleri A.\305\236.", 161}, + {"1806\006\003U\004\003\014/EBG Elektronik Sertifika Hizmet Sa\304\237lay\304\261c\304\261s\304\2611705\006\003U\004\012\014.EBG Bili\305\237im Teknolojileri ve Hizmetleri A.\305\236.1\0130\011\006\003U\004\006\023\002TR", 59}, + {"1\0130\011\006\003U\004\006\023\002US1\0270\025\006\003U\004\012\023\016VERISIGN, INC.1\0370\035\006\003U\004\013\023\026VERISIGN TRUST NETWORK1:08\006\003U\004\013\0231(C) 1999 VERISIGN, INC. - FOR AUTHORIZED USE ONLY1E0C\006\003U\004\003\023China Internet Network Information Center EV Certificates Root", 45}, + {"1\0130\011\006\003U\004\006\023\002US1\0270\025\006\003U\004\012\023\016VERISIGN, INC.1\0370\035\006\003U\004\013\023\026VERISIGN TRUST NETWORK1:08\006\003U\004\013\0231(C) 1999 VERISIGN, INC. - FOR AUTHORIZED USE ONLY1E0C\006\003U\004\003\023\006\003U\004\013\0247www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)1%0#\006\003U\004\013\023\034(C) 1999 ENTRUST.NET LIMITED1301\006\003U\004\003\023*ENTRUST.NET CERTIFICATION AUTHORITY (2048)", 1}, + {"1\0130\011\006\003U\004\006\023\002ES1\0220\020\006\003U\004\010\023\011BARCELONA1\0220\020\006\003U\004\007\023\011BARCELONA1.0,\006\003U\004\012\023%IPS INTERNET PUBLISHING SERVICES S.L.1+0)\006\003U\004\012\024\"ips@mail.ips.es C.I.F. B-609294521/0-\006\003U\004\013\023&IPS CA CLASEA3 CERTIFICATION AUTHORITY1/0-\006\003U\004\003\023&IPS CA CLASEA3 CERTIFICATION AUTHORITY1\0360\034\006\011*\206H\206\367\015\001\011\001\026\017ips@mail.ips.es", 90}, + {"1\0130\011\006\003U\004\006\023\002JP1\0340\032\006\003U\004\012\023\023JAPANESE GOVERNMENT1\0160\014\006\003U\004\013\023\005MPHPT1&0$\006\003U\004\013\023\035MPHPT CERTIFICATION AUTHORITY", 100}, + {"1\0130\011\006\003U\004\006\023\002ES1\0220\020\006\003U\004\010\023\011BARCELONA1\0220\020\006\003U\004\007\023\011BARCELONA1.0,\006\003U\004\012\023%IPS INTERNET PUBLISHING SERVICES S.L.1+0)\006\003U\004\012\024\"ips@mail.ips.es C.I.F. B-609294521301\006\003U\004\013\023*IPS CA CHAINED CAS CERTIFICATION AUTHORITY1301\006\003U\004\003\023*IPS CA CHAINED CAS CERTIFICATION AUTHORITY1\0360\034\006\011*\206H\206\367\015\001\011\001\026\017ips@mail.ips.es", 86}, + {"1\0130\011\006\003U\004\006\023\002US1\0270\025\006\003U\004\012\023\016VERISIGN, INC.1\0370\035\006\003U\004\013\023\026VERISIGN TRUST NETWORK1:08\006\003U\004\013\0231(C) 1999 VERISIGN, INC. - FOR AUTHORIZED USE ONLY1E0C\006\003U\004\003\023T\303\274rkiye Bilimsel ve Teknolojik Ara\305\237t\304\261rma Kurumu - T\303\234B\304\260TAK1H0F\006\003U\004\013\014?Ulusal Elektronik ve Kriptoloji Ara\305\237t\304\261rma Enstit\303\274s\303\274 - UEKAE1#0!\006\003U\004\013\014\032Kamu Sertifikasyon Merkezi1J0H\006\003U\004\003\014AT\303\234B\304\260TAK UEKAE K\303\266k Sertifika Hizmet Sa\304\237lay\304\261c\304\261s\304\261 - S\303\274r\303\274m 3", 160}, + {"1\0130\011\006\003U\004\006\023\002US1\0270\025\006\003U\004\012\023\016VERISIGN, INC.1\0370\035\006\003U\004\013\023\026VERISIGN TRUST NETWORK1:08\006\003U\004\013\0231(C) 2006 VERISIGN, INC. - FOR AUTHORIZED USE ONLY1E0C\006\003U\004\003\023= MIN_WORD_LENGTH) + { + register int key = subject_hash (str, len); + + if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE) + { + register const struct subject_to_ix_t *resword; + + switch (key - 39) + { + case 0: + if (len == 39) + { + resword = &subject_wordlist[0]; + goto compare; + } + break; + case 10: + if (len == 49) + { + resword = &subject_wordlist[1]; + goto compare; + } + break; + case 11: + if (len == 50) + { + resword = &subject_wordlist[2]; + goto compare; + } + break; + case 12: + if (len == 51) + { + resword = &subject_wordlist[3]; + goto compare; + } + break; + case 13: + if (len == 52) + { + resword = &subject_wordlist[4]; + goto compare; + } + break; + case 15: + if (len == 54) + { + resword = &subject_wordlist[5]; + goto compare; + } + break; + case 16: + if (len == 40) + { + resword = &subject_wordlist[6]; + goto compare; + } + break; + case 19: + if (len == 58) + { + resword = &subject_wordlist[7]; + goto compare; + } + break; + case 22: + if (len == 56) + { + resword = &subject_wordlist[8]; + goto compare; + } + break; + case 27: + if (len == 66) + { + resword = &subject_wordlist[9]; + goto compare; + } + break; + case 28: + if (len == 57) + { + resword = &subject_wordlist[10]; + goto compare; + } + break; + case 29: + if (len == 53) + { + resword = &subject_wordlist[11]; + goto compare; + } + break; + case 30: + if (len == 69) + { + resword = &subject_wordlist[12]; + goto compare; + } + break; + case 31: + if (len == 65) + { + resword = &subject_wordlist[13]; + goto compare; + } + break; + case 32: + if (len == 61) + { + resword = &subject_wordlist[14]; + goto compare; + } + break; + case 33: + if (len == 72) + { + resword = &subject_wordlist[15]; + goto compare; + } + break; + case 34: + if (len == 68) + { + resword = &subject_wordlist[16]; + goto compare; + } + break; + case 35: + if (len == 74) + { + resword = &subject_wordlist[17]; + goto compare; + } + break; + case 36: + if (len == 75) + { + resword = &subject_wordlist[18]; + goto compare; + } + break; + case 38: + if (len == 67) + { + resword = &subject_wordlist[19]; + goto compare; + } + break; + case 39: + if (len == 78) + { + resword = &subject_wordlist[20]; + goto compare; + } + break; + case 40: + if (len == 69) + { + resword = &subject_wordlist[21]; + goto compare; + } + break; + case 41: + if (len == 80) + { + resword = &subject_wordlist[22]; + goto compare; + } + break; + case 43: + if (len == 57) + { + resword = &subject_wordlist[23]; + goto compare; + } + break; + case 44: + if (len == 63) + { + resword = &subject_wordlist[24]; + goto compare; + } + break; + case 49: + if (len == 88) + { + resword = &subject_wordlist[25]; + goto compare; + } + break; + case 51: + if (len == 85) + { + resword = &subject_wordlist[26]; + goto compare; + } + break; + case 53: + if (len == 57) + { + resword = &subject_wordlist[27]; + goto compare; + } + break; + case 54: + if (len == 78) + { + resword = &subject_wordlist[28]; + goto compare; + } + break; + case 55: + if (len == 69) + { + resword = &subject_wordlist[29]; + goto compare; + } + break; + case 56: + if (len == 85) + { + resword = &subject_wordlist[30]; + goto compare; + } + break; + case 58: + if (len == 97) + { + resword = &subject_wordlist[31]; + goto compare; + } + break; + case 59: + if (len == 88) + { + resword = &subject_wordlist[32]; + goto compare; + } + break; + case 60: + if (len == 69) + { + resword = &subject_wordlist[33]; + goto compare; + } + break; + case 61: + if (len == 95) + { + resword = &subject_wordlist[34]; + goto compare; + } + break; + case 64: + if (len == 73) + { + resword = &subject_wordlist[35]; + goto compare; + } + break; + case 65: + if (len == 69) + { + resword = &subject_wordlist[36]; + goto compare; + } + break; + case 66: + if (len == 100) + { + resword = &subject_wordlist[37]; + goto compare; + } + break; + case 67: + if (len == 91) + { + resword = &subject_wordlist[38]; + goto compare; + } + break; + case 68: + if (len == 107) + { + resword = &subject_wordlist[39]; + goto compare; + } + break; + case 69: + if (len == 108) + { + resword = &subject_wordlist[40]; + goto compare; + } + break; + case 70: + if (len == 109) + { + resword = &subject_wordlist[41]; + goto compare; + } + break; + case 71: + if (len == 90) + { + resword = &subject_wordlist[42]; + goto compare; + } + break; + case 72: + if (len == 111) + { + resword = &subject_wordlist[43]; + goto compare; + } + break; + case 74: + if (len == 98) + { + resword = &subject_wordlist[44]; + goto compare; + } + break; + case 75: + if (len == 74) + { + resword = &subject_wordlist[45]; + goto compare; + } + break; + case 76: + if (len == 95) + { + resword = &subject_wordlist[46]; + goto compare; + } + break; + case 77: + if (len == 71) + { + resword = &subject_wordlist[47]; + goto compare; + } + break; + case 78: + if (len == 87) + { + resword = &subject_wordlist[48]; + goto compare; + } + break; + case 79: + if (len == 98) + { + resword = &subject_wordlist[49]; + goto compare; + } + break; + case 80: + if (len == 104) + { + resword = &subject_wordlist[50]; + goto compare; + } + break; + case 81: + if (len == 95) + { + resword = &subject_wordlist[51]; + goto compare; + } + break; + case 82: + if (len == 96) + { + resword = &subject_wordlist[52]; + goto compare; + } + break; + case 83: + if (len == 97) + { + resword = &subject_wordlist[53]; + goto compare; + } + break; + case 84: + if (len == 93) + { + resword = &subject_wordlist[54]; + goto compare; + } + break; + case 85: + if (len == 99) + { + resword = &subject_wordlist[55]; + goto compare; + } + break; + case 86: + if (len == 95) + { + resword = &subject_wordlist[56]; + goto compare; + } + break; + case 87: + if (len == 126) + { + resword = &subject_wordlist[57]; + goto compare; + } + break; + case 89: + if (len == 63) + { + resword = &subject_wordlist[58]; + goto compare; + } + break; + case 90: + if (len == 94) + { + resword = &subject_wordlist[59]; + goto compare; + } + break; + case 91: + if (len == 100) + { + resword = &subject_wordlist[60]; + goto compare; + } + break; + case 92: + if (len == 101) + { + resword = &subject_wordlist[61]; + goto compare; + } + break; + case 93: + if (len == 117) + { + resword = &subject_wordlist[62]; + goto compare; + } + break; + case 94: + if (len == 108) + { + resword = &subject_wordlist[63]; + goto compare; + } + break; + case 95: + if (len == 99) + { + resword = &subject_wordlist[64]; + goto compare; + } + break; + case 97: + if (len == 121) + { + resword = &subject_wordlist[65]; + goto compare; + } + break; + case 98: + if (len == 122) + { + resword = &subject_wordlist[66]; + goto compare; + } + break; + case 99: + if (len == 123) + { + resword = &subject_wordlist[67]; + goto compare; + } + break; + case 100: + if (len == 99) + { + resword = &subject_wordlist[68]; + goto compare; + } + break; + case 101: + if (len == 100) + { + resword = &subject_wordlist[69]; + goto compare; + } + break; + case 103: + if (len == 62) + { + resword = &subject_wordlist[70]; + goto compare; + } + break; + case 104: + if (len == 58) + { + resword = &subject_wordlist[71]; + goto compare; + } + break; + case 106: + if (len == 100) + { + resword = &subject_wordlist[72]; + goto compare; + } + break; + case 107: + if (len == 101) + { + resword = &subject_wordlist[73]; + goto compare; + } + break; + case 108: + if (len == 102) + { + resword = &subject_wordlist[74]; + goto compare; + } + break; + case 109: + if (len == 113) + { + resword = &subject_wordlist[75]; + goto compare; + } + break; + case 110: + if (len == 149) + { + resword = &subject_wordlist[76]; + goto compare; + } + break; + case 111: + if (len == 75) + { + resword = &subject_wordlist[77]; + goto compare; + } + break; + case 112: + if (len == 151) + { + resword = &subject_wordlist[78]; + goto compare; + } + break; + case 113: + if (len == 147) + { + resword = &subject_wordlist[79]; + goto compare; + } + break; + case 114: + if (len == 93) + { + resword = &subject_wordlist[80]; + goto compare; + } + break; + case 115: + if (len == 139) + { + resword = &subject_wordlist[81]; + goto compare; + } + break; + case 116: + if (len == 75) + { + resword = &subject_wordlist[82]; + goto compare; + } + break; + case 117: + if (len == 131) + { + resword = &subject_wordlist[83]; + goto compare; + } + break; + case 119: + if (len == 68) + { + resword = &subject_wordlist[84]; + goto compare; + } + break; + case 120: + if (len == 89) + { + resword = &subject_wordlist[85]; + goto compare; + } + break; + case 121: + if (len == 125) + { + resword = &subject_wordlist[86]; + goto compare; + } + break; + case 122: + if (len == 141) + { + resword = &subject_wordlist[87]; + goto compare; + } + break; + case 123: + if (len == 132) + { + resword = &subject_wordlist[88]; + goto compare; + } + break; + case 124: + if (len == 163) + { + resword = &subject_wordlist[89]; + goto compare; + } + break; + case 125: + if (len == 139) + { + resword = &subject_wordlist[90]; + goto compare; + } + break; + case 126: + if (len == 125) + { + resword = &subject_wordlist[91]; + goto compare; + } + break; + case 127: + if (len == 71) + { + resword = &subject_wordlist[92]; + goto compare; + } + break; + case 128: + if (len == 127) + { + resword = &subject_wordlist[93]; + goto compare; + } + break; + case 129: + if (len == 138) + { + resword = &subject_wordlist[94]; + goto compare; + } + break; + case 131: + if (len == 90) + { + resword = &subject_wordlist[95]; + goto compare; + } + break; + case 132: + if (len == 131) + { + resword = &subject_wordlist[96]; + goto compare; + } + break; + case 133: + if (len == 67) + { + resword = &subject_wordlist[97]; + goto compare; + } + break; + case 134: + if (len == 118) + { + resword = &subject_wordlist[98]; + goto compare; + } + break; + case 136: + if (len == 130) + { + resword = &subject_wordlist[99]; + goto compare; + } + break; + case 137: + if (len == 141) + { + resword = &subject_wordlist[100]; + goto compare; + } + break; + case 138: + if (len == 127) + { + resword = &subject_wordlist[101]; + goto compare; + } + break; + case 139: + if (len == 118) + { + resword = &subject_wordlist[102]; + goto compare; + } + break; + case 140: + if (len == 129) + { + resword = &subject_wordlist[103]; + goto compare; + } + break; + case 141: + if (len == 90) + { + resword = &subject_wordlist[104]; + goto compare; + } + break; + case 142: + if (len == 76) + { + resword = &subject_wordlist[105]; + goto compare; + } + break; + case 143: + if (len == 127) + { + resword = &subject_wordlist[106]; + goto compare; + } + break; + case 144: + if (len == 153) + { + resword = &subject_wordlist[107]; + goto compare; + } + break; + case 146: + if (len == 155) + { + resword = &subject_wordlist[108]; + goto compare; + } + break; + case 147: + if (len == 76) + { + resword = &subject_wordlist[109]; + goto compare; + } + break; + case 148: + if (len == 167) + { + resword = &subject_wordlist[110]; + goto compare; + } + break; + case 149: + if (len == 163) + { + resword = &subject_wordlist[111]; + goto compare; + } + break; + case 151: + if (len == 130) + { + resword = &subject_wordlist[112]; + goto compare; + } + break; + case 152: + if (len == 176) + { + resword = &subject_wordlist[113]; + goto compare; + } + break; + case 153: + if (len == 187) + { + resword = &subject_wordlist[114]; + goto compare; + } + break; + case 154: + if (len == 103) + { + resword = &subject_wordlist[115]; + goto compare; + } + break; + case 156: + if (len == 195) + { + resword = &subject_wordlist[116]; + goto compare; + } + break; + case 157: + if (len == 81) + { + resword = &subject_wordlist[117]; + goto compare; + } + break; + case 159: + if (len == 83) + { + resword = &subject_wordlist[118]; + goto compare; + } + break; + case 160: + if (len == 174) + { + resword = &subject_wordlist[119]; + goto compare; + } + break; + case 161: + if (len == 85) + { + resword = &subject_wordlist[120]; + goto compare; + } + break; + case 162: + if (len == 81) + { + resword = &subject_wordlist[121]; + goto compare; + } + break; + case 164: + if (len == 123) + { + resword = &subject_wordlist[122]; + goto compare; + } + break; + case 165: + if (len == 169) + { + resword = &subject_wordlist[123]; + goto compare; + } + break; + case 166: + if (len == 90) + { + resword = &subject_wordlist[124]; + goto compare; + } + break; + case 167: + if (len == 126) + { + resword = &subject_wordlist[125]; + goto compare; + } + break; + case 168: + if (len == 187) + { + resword = &subject_wordlist[126]; + goto compare; + } + break; + case 169: + if (len == 143) + { + resword = &subject_wordlist[127]; + goto compare; + } + break; + case 172: + if (len == 131) + { + resword = &subject_wordlist[128]; + goto compare; + } + break; + case 173: + if (len == 187) + { + resword = &subject_wordlist[129]; + goto compare; + } + break; + case 174: + if (len == 123) + { + resword = &subject_wordlist[130]; + goto compare; + } + break; + case 176: + if (len == 190) + { + resword = &subject_wordlist[131]; + goto compare; + } + break; + case 177: + if (len == 206) + { + resword = &subject_wordlist[132]; + goto compare; + } + break; + case 178: + if (len == 152) + { + resword = &subject_wordlist[133]; + goto compare; + } + break; + case 179: + if (len == 78) + { + resword = &subject_wordlist[134]; + goto compare; + } + break; + case 182: + if (len == 191) + { + resword = &subject_wordlist[135]; + goto compare; + } + break; + case 184: + if (len == 118) + { + resword = &subject_wordlist[136]; + goto compare; + } + break; + case 185: + if (len == 134) + { + resword = &subject_wordlist[137]; + goto compare; + } + break; + case 187: + if (len == 196) + { + resword = &subject_wordlist[138]; + goto compare; + } + break; + case 188: + if (len == 207) + { + resword = &subject_wordlist[139]; + goto compare; + } + break; + case 189: + if (len == 118) + { + resword = &subject_wordlist[140]; + goto compare; + } + break; + case 190: + if (len == 209) + { + resword = &subject_wordlist[141]; + goto compare; + } + break; + case 191: + if (len == 175) + { + resword = &subject_wordlist[142]; + goto compare; + } + break; + case 192: + if (len == 201) + { + resword = &subject_wordlist[143]; + goto compare; + } + break; + case 194: + if (len == 203) + { + resword = &subject_wordlist[144]; + goto compare; + } + break; + case 195: + if (len == 204) + { + resword = &subject_wordlist[145]; + goto compare; + } + break; + case 198: + if (len == 207) + { + resword = &subject_wordlist[146]; + goto compare; + } + break; + case 199: + if (len == 133) + { + resword = &subject_wordlist[147]; + goto compare; + } + break; + case 204: + if (len == 183) + { + resword = &subject_wordlist[148]; + goto compare; + } + break; + case 209: + if (len == 128) + { + resword = &subject_wordlist[149]; + goto compare; + } + break; + case 213: + if (len == 202) + { + resword = &subject_wordlist[150]; + goto compare; + } + break; + case 214: + if (len == 193) + { + resword = &subject_wordlist[151]; + goto compare; + } + break; + case 219: + if (len == 143) + { + resword = &subject_wordlist[152]; + goto compare; + } + break; + case 224: + if (len == 138) + { + resword = &subject_wordlist[153]; + goto compare; + } + break; + case 228: + if (len == 202) + { + resword = &subject_wordlist[154]; + goto compare; + } + break; + case 229: + if (len == 193) + { + resword = &subject_wordlist[155]; + goto compare; + } + break; + case 233: + if (len == 202) + { + resword = &subject_wordlist[156]; + goto compare; + } + break; + case 234: + if (len == 193) + { + resword = &subject_wordlist[157]; + goto compare; + } + break; + case 245: + if (len == 274) + { + resword = &subject_wordlist[158]; + goto compare; + } + break; + case 247: + if (len == 276) + { + resword = &subject_wordlist[159]; + goto compare; + } + break; + case 254: + if (len == 208) + { + resword = &subject_wordlist[160]; + goto compare; + } + break; + case 257: + if (len == 286) + { + resword = &subject_wordlist[161]; + goto compare; + } + break; + case 265: + if (len == 274) + { + resword = &subject_wordlist[162]; + goto compare; + } + break; + case 266: + if (len == 180) + { + resword = &subject_wordlist[163]; + goto compare; + } + break; + case 267: + if (len == 276) + { + resword = &subject_wordlist[164]; + goto compare; + } + break; + case 270: + if (len == 99) + { + resword = &subject_wordlist[165]; + goto compare; + } + break; + case 275: + if (len == 284) + { + resword = &subject_wordlist[166]; + goto compare; + } + break; + case 278: + if (len == 202) + { + resword = &subject_wordlist[167]; + goto compare; + } + break; + case 279: + if (len == 193) + { + resword = &subject_wordlist[168]; + goto compare; + } + break; + case 297: + if (len == 91) + { + resword = &subject_wordlist[169]; + goto compare; + } + break; + case 310: + if (len == 299) + { + resword = &subject_wordlist[170]; + goto compare; + } + break; + case 323: + if (len == 202) + { + resword = &subject_wordlist[171]; + goto compare; + } + break; + } + return 0; + compare: + { + register const char *s = resword->subject; + + if (*str == *s && !memcmp (str + 1, s + 1, len - 1)) + return resword; + } + } + } + return 0; +} + +#undef TOTAL_KEYWORD +#undef MIN_WORD_LENGTH +#undef MAX_WORD_LENGTH +#undef MIN_HASH_VALUE +#undef MAX_HASH_VALUE +struct anchorslist_t { int length; char *data; int next_same_subject; }; +/* Anchors 172 using 196113 bytes. */ +const struct anchorslist_t anchorslist[] = { + /* Anchor: 0 00_BCA.cer serial: #{a.serial.to_s} + C=JP,O=JPKI,OU=Prefectural Association For JPKI,OU=BridgeCA + */ + { 1134, "\x30\x82\x04\x6a\x30\x82\x03\x52\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x5a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4a\x50\x31\x0d\x30\x0b\x06\x03\x55\x04\x0a\x0c\x04\x4a\x50\x4b\x49\x31\x29\x30\x27\x06\x03\x55\x04\x0b\x0c\x20\x50\x72\x65\x66\x65\x63\x74\x75\x72\x61\x6c\x20\x41\x73\x73\x6f\x63\x69\x61\x74\x69\x6f\x6e\x20\x46\x6f\x72\x20\x4a\x50\x4b\x49\x31\x11\x30\x0f\x06\x03\x55\x04\x0b\x0c\x08\x42\x72\x69\x64\x67\x65\x43\x41\x30\x1e\x17\x0d\x30\x33\x31\x32\x32\x37\x30\x35\x30\x38\x31\x35\x5a\x17\x0d\x31\x33\x31\x32\x32\x36\x31\x34\x35\x39\x35\x39\x5a\x30\x5a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4a\x50\x31\x0d\x30\x0b\x06\x03\x55\x04\x0a\x0c\x04\x4a\x50\x4b\x49\x31\x29\x30\x27\x06\x03\x55\x04\x0b\x0c\x20\x50\x72\x65\x66\x65\x63\x74\x75\x72\x61\x6c\x20\x41\x73\x73\x6f\x63\x69\x61\x74\x69\x6f\x6e\x20\x46\x6f\x72\x20\x4a\x50\x4b\x49\x31\x11\x30\x0f\x06\x03\x55\x04\x0b\x0c\x08\x42\x72\x69\x64\x67\x65\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xd4\xe7\x52\x68\x3b\x2b\x79\xbc\xe7\x6b\xdd\xef\xb9\x30\x92\xad\x79\xe9\xeb\xb0\xa1\x69\xb9\x9e\x8f\x04\xf2\x49\x9a\x4d\x27\x3b\xc7\x64\x40\x04\xfa\x6a\x35\x39\x4c\x29\xd6\x7a\xb6\xdb\x32\x62\xba\x91\x11\xe0\xe4\x72\xf3\xcb\xc8\x5e\xf2\x7f\xf2\x3c\xfa\x29\xe7\x6a\xc3\x6d\xb3\x2b\x5c\x4c\x0c\xbc\xc5\x8f\x00\xbe\xc6\xdd\xe0\x99\x02\x19\x6f\x5d\xc8\xf8\xe4\xf6\x9c\xf3\x73\x7c\x8b\x43\xae\x11\xc7\x67\xee\x8d\x19\xf6\x6a\x07\x04\x55\xd3\xc2\xaf\xf5\xe9\x27\x28\x17\xf0\x50\xf9\x6d\xb8\x64\x67\x40\x95\xa2\x20\x12\x06\x69\x47\x39\xc0\xb7\x62\x91\x65\x7d\xb4\xf5\x41\xca\x4e\x48\xe6\xfb\xa3\xe5\x5d\x29\x51\x22\x30\xc7\xdb\x06\xe5\x36\x22\x56\x08\x69\x2a\xff\x47\x59\xce\xed\x13\xcd\xb6\x4a\xa4\x15\x62\x75\xfe\x72\xa3\x28\x7c\xb3\x66\x37\xbb\x8f\xbd\x2a\x4b\x16\xfe\x05\x31\x9c\x36\x04\xc7\x6b\x56\x00\x52\xba\x20\x28\x1f\x94\xa4\x17\xed\x99\xbe\x1d\xb3\xe5\xe5\x90\x42\x75\x76\xfc\x28\x92\x24\x9b\x08\x36\x96\x14\xa0\xfe\x60\x3e\x01\xda\xcd\x1b\xbe\x30\x9b\xc3\xcc\x6e\x64\x56\x06\x84\xdc\x91\xff\x60\xf9\x5d\xf3\x75\xb3\x63\x02\x03\x01\x00\x01\xa3\x82\x01\x39\x30\x82\x01\x35\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x6d\x06\x03\x55\x1d\x1f\x04\x66\x30\x64\x30\x62\xa0\x60\xa0\x5e\xa4\x5c\x30\x5a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4a\x50\x31\x0d\x30\x0b\x06\x03\x55\x04\x0a\x0c\x04\x4a\x50\x4b\x49\x31\x29\x30\x27\x06\x03\x55\x04\x0b\x0c\x20\x50\x72\x65\x66\x65\x63\x74\x75\x72\x61\x6c\x20\x41\x73\x73\x6f\x63\x69\x61\x74\x69\x6f\x6e\x20\x46\x6f\x72\x20\x4a\x50\x4b\x49\x31\x11\x30\x0f\x06\x03\x55\x04\x0b\x0c\x08\x42\x72\x69\x64\x67\x65\x43\x41\x30\x81\x83\x06\x03\x55\x1d\x11\x04\x7c\x30\x7a\xa4\x78\x30\x76\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4a\x50\x31\x27\x30\x25\x06\x03\x55\x04\x0a\x0c\x1e\xe5\x85\xac\xe7\x9a\x84\xe5\x80\x8b\xe4\xba\xba\xe8\xaa\x8d\xe8\xa8\xbc\xe3\x82\xb5\xe3\x83\xbc\xe3\x83\x93\xe3\x82\xb9\x31\x1e\x30\x1c\x06\x03\x55\x04\x0b\x0c\x15\xe9\x83\xbd\xe9\x81\x93\xe5\xba\x9c\xe7\x9c\x8c\xe5\x8d\x94\xe8\xad\xb0\xe4\xbc\x9a\x31\x1e\x30\x1c\x06\x03\x55\x04\x0b\x0c\x15\xe3\x83\x96\xe3\x83\xaa\xe3\x83\x83\xe3\x82\xb8\xe8\xaa\x8d\xe8\xa8\xbc\xe5\xb1\x80\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xd4\x17\x32\x20\xaa\x40\xd9\x11\xd8\xe6\x99\x99\x08\x0b\xb5\xff\x26\x47\xca\x7c\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x13\x8c\x9a\x38\xad\xe4\xcd\x3c\x2e\x42\xb2\xf0\x0a\xbb\x54\x58\x4f\xc3\xf2\x5c\x55\x58\x1d\xb2\xac\x12\x91\xad\xe0\x64\x7c\xa4\x30\xa0\x1c\x41\x80\x88\x08\x47\x48\xda\xc6\x87\xd0\x9a\x81\x93\x17\x00\x3b\xe5\x1b\x48\x26\x30\xe9\xd7\xa3\x0a\xe2\x41\x08\xb1\xae\xda\x64\x9b\x1d\x13\x07\xcb\x4d\x02\x56\x69\xb5\x95\xa4\x64\x2f\x91\xf1\x39\xe3\x3a\x41\xeb\x93\x69\xc5\x00\x40\xb7\x7b\x36\xdd\x2b\x44\x7b\x31\x1e\x2d\x24\xb0\xd0\x0a\x78\x44\x59\xb8\x39\xd2\xb7\xf4\xc1\x9f\xda\x17\xcb\x80\x69\x57\x84\xb4\x75\xda\xe9\x6d\x0c\x5e\xad\xdd\x49\xed\x17\x01\xca\xcb\x6d\x7e\x33\x64\x74\x13\x69\x6b\xdd\xa4\xb0\x08\x8e\x5e\x83\x67\x74\x82\x89\xe4\x4c\xca\x85\x94\x2f\xe2\xd7\x68\xb1\x5d\x4c\xfe\x56\x04\x27\x7e\x36\x8e\x7c\x22\x8b\xa7\x0f\xd5\xf8\xc7\x1c\xde\xd9\xa7\x91\x55\xa8\x95\xfd\x69\xd0\xd0\xe4\x8f\x35\x2e\xe7\xed\x85\xf2\xeb\x14\x1d\x9d\xa3\x94\xe0\xa4\x56\xfc\xb9\xde\xd4\x40\xdf\xe4\x87\xd6\x0b\xf8\xa1\x6d\x50\x26\x85\x93\x1b\x72\xb9\x16\x59\xcb\x11\xe9\xa0\x8f\x1b\xed\xa6\x57\x7c\xd3\x0f\xa0\x14\xce\xe2\x8f\x6a\x5f\x18", 0 }, + /* Anchor: 1 2048CA.cer serial: #{a.serial.to_s} + O=Entrust.net,OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.),OU=(c) 1999 Entrust.net Limited,CN=Entrust.net Certification Authority (2048) + */ + { 1120, "\x30\x82\x04\x5c\x30\x82\x03\x44\xa0\x03\x02\x01\x02\x02\x04\x38\x63\xb9\x66\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xb4\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x31\x40\x30\x3e\x06\x03\x55\x04\x0b\x14\x37\x77\x77\x77\x2e\x65\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x2f\x43\x50\x53\x5f\x32\x30\x34\x38\x20\x69\x6e\x63\x6f\x72\x70\x2e\x20\x62\x79\x20\x72\x65\x66\x2e\x20\x28\x6c\x69\x6d\x69\x74\x73\x20\x6c\x69\x61\x62\x2e\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0b\x13\x1c\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x33\x30\x31\x06\x03\x55\x04\x03\x13\x2a\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x28\x32\x30\x34\x38\x29\x30\x1e\x17\x0d\x39\x39\x31\x32\x32\x34\x31\x37\x35\x30\x35\x31\x5a\x17\x0d\x31\x39\x31\x32\x32\x34\x31\x38\x32\x30\x35\x31\x5a\x30\x81\xb4\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x31\x40\x30\x3e\x06\x03\x55\x04\x0b\x14\x37\x77\x77\x77\x2e\x65\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x2f\x43\x50\x53\x5f\x32\x30\x34\x38\x20\x69\x6e\x63\x6f\x72\x70\x2e\x20\x62\x79\x20\x72\x65\x66\x2e\x20\x28\x6c\x69\x6d\x69\x74\x73\x20\x6c\x69\x61\x62\x2e\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0b\x13\x1c\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x33\x30\x31\x06\x03\x55\x04\x03\x13\x2a\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x28\x32\x30\x34\x38\x29\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xad\x4d\x4b\xa9\x12\x86\xb2\xea\xa3\x20\x07\x15\x16\x64\x2a\x2b\x4b\xd1\xbf\x0b\x4a\x4d\x8e\xed\x80\x76\xa5\x67\xb7\x78\x40\xc0\x73\x42\xc8\x68\xc0\xdb\x53\x2b\xdd\x5e\xb8\x76\x98\x35\x93\x8b\x1a\x9d\x7c\x13\x3a\x0e\x1f\x5b\xb7\x1e\xcf\xe5\x24\x14\x1e\xb1\x81\xa9\x8d\x7d\xb8\xcc\x6b\x4b\x03\xf1\x02\x0c\xdc\xab\xa5\x40\x24\x00\x7f\x74\x94\xa1\x9d\x08\x29\xb3\x88\x0b\xf5\x87\x77\x9d\x55\xcd\xe4\xc3\x7e\xd7\x6a\x64\xab\x85\x14\x86\x95\x5b\x97\x32\x50\x6f\x3d\xc8\xba\x66\x0c\xe3\xfc\xbd\xb8\x49\xc1\x76\x89\x49\x19\xfd\xc0\xa8\xbd\x89\xa3\x67\x2f\xc6\x9f\xbc\x71\x19\x60\xb8\x2d\xe9\x2c\xc9\x90\x76\x66\x7b\x94\xe2\xaf\x78\xd6\x65\x53\x5d\x3c\xd6\x9c\xb2\xcf\x29\x03\xf9\x2f\xa4\x50\xb2\xd4\x48\xce\x05\x32\x55\x8a\xfd\xb2\x64\x4c\x0e\xe4\x98\x07\x75\xdb\x7f\xdf\xb9\x08\x55\x60\x85\x30\x29\xf9\x7b\x48\xa4\x69\x86\xe3\x35\x3f\x1e\x86\x5d\x7a\x7a\x15\xbd\xef\x00\x8e\x15\x22\x54\x17\x00\x90\x26\x93\xbc\x0e\x49\x68\x91\xbf\xf8\x47\xd3\x9d\x95\x42\xc1\x0e\x4d\xdf\x6f\x26\xcf\xc3\x18\x21\x62\x66\x43\x70\xd6\xd5\xc0\x07\xe1\x02\x03\x01\x00\x01\xa3\x74\x30\x72\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x55\xe4\x81\xd1\x11\x80\xbe\xd8\x89\xb9\x08\xa3\x31\xf9\xa1\x24\x09\x16\xb9\x70\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x55\xe4\x81\xd1\x11\x80\xbe\xd8\x89\xb9\x08\xa3\x31\xf9\xa1\x24\x09\x16\xb9\x70\x30\x1d\x06\x09\x2a\x86\x48\x86\xf6\x7d\x07\x41\x00\x04\x10\x30\x0e\x1b\x08\x56\x35\x2e\x30\x3a\x34\x2e\x30\x03\x02\x04\x90\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x59\x47\xac\x21\x84\x8a\x17\xc9\x9c\x89\x53\x1e\xba\x80\x85\x1a\xc6\x3c\x4e\x3e\xb1\x9c\xb6\x7c\xc6\x92\x5d\x18\x64\x02\xe3\xd3\x06\x08\x11\x61\x7c\x63\xe3\x2b\x9d\x31\x03\x70\x76\xd2\xa3\x28\xa0\xf4\xbb\x9a\x63\x73\xed\x6d\xe5\x2a\xdb\xed\x14\xa9\x2b\xc6\x36\x11\xd0\x2b\xeb\x07\x8b\xa5\xda\x9e\x5c\x19\x9d\x56\x12\xf5\x54\x29\xc8\x05\xed\xb2\x12\x2a\x8d\xf4\x03\x1b\xff\xe7\x92\x10\x87\xb0\x3a\xb5\xc3\x9d\x05\x37\x12\xa3\xc7\xf4\x15\xb9\xd5\xa4\x39\x16\x9b\x53\x3a\x23\x91\xf1\xa8\x82\xa2\x6a\x88\x68\xc1\x79\x02\x22\xbc\xaa\xa6\xd6\xae\xdf\xb0\x14\x5f\xb8\x87\xd0\xdd\x7c\x7f\x7b\xff\xaf\x1c\xcf\xe6\xdb\x07\xad\x5e\xdb\x85\x9d\xd0\x2b\x0d\x33\xdb\x04\xd1\xe6\x49\x40\x13\x2b\x76\xfb\x3e\xe9\x9c\x89\x0f\x15\xce\x18\xb0\x85\x78\x21\x4f\x6b\x4f\x0e\xfa\x36\x67\xcd\x07\xf2\xff\x08\xd0\xe2\xde\xd9\xbf\x2a\xaf\xb8\x87\x86\x21\x3c\x04\xca\xb7\x94\x68\x7f\xcf\x3c\xe9\x98\xd7\x38\xff\xec\xc0\xd9\x50\xf0\x2e\x4b\x58\xae\x46\x6f\xd0\x2e\xc3\x60\xda\x72\x55\x72\xbd\x4c\x45\x9e\x61\xba\xbf\x84\x81\x92\x03\xd1\xd2\x69\x7c\xc5", 2 }, + /* Anchor: 2 entrust2048.der serial: #{a.serial.to_s} + O=Entrust.net,OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.),OU=(c) 1999 Entrust.net Limited,CN=Entrust.net Certification Authority (2048) + */ + { 1070, "\x30\x82\x04\x2a\x30\x82\x03\x12\xa0\x03\x02\x01\x02\x02\x04\x38\x63\xde\xf8\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xb4\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x31\x40\x30\x3e\x06\x03\x55\x04\x0b\x14\x37\x77\x77\x77\x2e\x65\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x2f\x43\x50\x53\x5f\x32\x30\x34\x38\x20\x69\x6e\x63\x6f\x72\x70\x2e\x20\x62\x79\x20\x72\x65\x66\x2e\x20\x28\x6c\x69\x6d\x69\x74\x73\x20\x6c\x69\x61\x62\x2e\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0b\x13\x1c\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x33\x30\x31\x06\x03\x55\x04\x03\x13\x2a\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x28\x32\x30\x34\x38\x29\x30\x1e\x17\x0d\x39\x39\x31\x32\x32\x34\x31\x37\x35\x30\x35\x31\x5a\x17\x0d\x32\x39\x30\x37\x32\x34\x31\x34\x31\x35\x31\x32\x5a\x30\x81\xb4\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x31\x40\x30\x3e\x06\x03\x55\x04\x0b\x14\x37\x77\x77\x77\x2e\x65\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x2f\x43\x50\x53\x5f\x32\x30\x34\x38\x20\x69\x6e\x63\x6f\x72\x70\x2e\x20\x62\x79\x20\x72\x65\x66\x2e\x20\x28\x6c\x69\x6d\x69\x74\x73\x20\x6c\x69\x61\x62\x2e\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0b\x13\x1c\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x33\x30\x31\x06\x03\x55\x04\x03\x13\x2a\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x28\x32\x30\x34\x38\x29\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xad\x4d\x4b\xa9\x12\x86\xb2\xea\xa3\x20\x07\x15\x16\x64\x2a\x2b\x4b\xd1\xbf\x0b\x4a\x4d\x8e\xed\x80\x76\xa5\x67\xb7\x78\x40\xc0\x73\x42\xc8\x68\xc0\xdb\x53\x2b\xdd\x5e\xb8\x76\x98\x35\x93\x8b\x1a\x9d\x7c\x13\x3a\x0e\x1f\x5b\xb7\x1e\xcf\xe5\x24\x14\x1e\xb1\x81\xa9\x8d\x7d\xb8\xcc\x6b\x4b\x03\xf1\x02\x0c\xdc\xab\xa5\x40\x24\x00\x7f\x74\x94\xa1\x9d\x08\x29\xb3\x88\x0b\xf5\x87\x77\x9d\x55\xcd\xe4\xc3\x7e\xd7\x6a\x64\xab\x85\x14\x86\x95\x5b\x97\x32\x50\x6f\x3d\xc8\xba\x66\x0c\xe3\xfc\xbd\xb8\x49\xc1\x76\x89\x49\x19\xfd\xc0\xa8\xbd\x89\xa3\x67\x2f\xc6\x9f\xbc\x71\x19\x60\xb8\x2d\xe9\x2c\xc9\x90\x76\x66\x7b\x94\xe2\xaf\x78\xd6\x65\x53\x5d\x3c\xd6\x9c\xb2\xcf\x29\x03\xf9\x2f\xa4\x50\xb2\xd4\x48\xce\x05\x32\x55\x8a\xfd\xb2\x64\x4c\x0e\xe4\x98\x07\x75\xdb\x7f\xdf\xb9\x08\x55\x60\x85\x30\x29\xf9\x7b\x48\xa4\x69\x86\xe3\x35\x3f\x1e\x86\x5d\x7a\x7a\x15\xbd\xef\x00\x8e\x15\x22\x54\x17\x00\x90\x26\x93\xbc\x0e\x49\x68\x91\xbf\xf8\x47\xd3\x9d\x95\x42\xc1\x0e\x4d\xdf\x6f\x26\xcf\xc3\x18\x21\x62\x66\x43\x70\xd6\xd5\xc0\x07\xe1\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x55\xe4\x81\xd1\x11\x80\xbe\xd8\x89\xb9\x08\xa3\x31\xf9\xa1\x24\x09\x16\xb9\x70\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x3b\x9b\x8f\x56\x9b\x30\xe7\x53\x99\x7c\x7a\x79\xa7\x4d\x97\xd7\x19\x95\x90\xfb\x06\x1f\xca\x33\x7c\x46\x63\x8f\x96\x66\x24\xfa\x40\x1b\x21\x27\xca\xe6\x72\x73\xf2\x4f\xfe\x31\x99\xfd\xc8\x0c\x4c\x68\x53\xc6\x80\x82\x13\x98\xfa\xb6\xad\xda\x5d\x3d\xf1\xce\x6e\xf6\x15\x11\x94\x82\x0c\xee\x3f\x95\xaf\x11\xab\x0f\xd7\x2f\xde\x1f\x03\x8f\x57\x2c\x1e\xc9\xbb\x9a\x1a\x44\x95\xeb\x18\x4f\xa6\x1f\xcd\x7d\x57\x10\x2f\x9b\x04\x09\x5a\x84\xb5\x6e\xd8\x1d\x3a\xe1\xd6\x9e\xd1\x6c\x79\x5e\x79\x1c\x14\xc5\xe3\xd0\x4c\x93\x3b\x65\x3c\xed\xdf\x3d\xbe\xa6\xe5\x95\x1a\xc3\xb5\x19\xc3\xbd\x5e\x5b\xbb\xff\x23\xef\x68\x19\xcb\x12\x93\x27\x5c\x03\x2d\x6f\x30\xd0\x1e\xb6\x1a\xac\xde\x5a\xf7\xd1\xaa\xa8\x27\xa6\xfe\x79\x81\xc4\x79\x99\x33\x57\xba\x12\xb0\xa9\xe0\x42\x6c\x93\xca\x56\xde\xfe\x6d\x84\x0b\x08\x8b\x7e\x8d\xea\xd7\x98\x21\xc6\xf3\xe7\x3c\x79\x2f\x5e\x9c\xd1\x4c\x15\x8d\xe1\xec\x22\x37\xcc\x9a\x43\x0b\x97\xdc\x80\x90\x8d\xb3\x67\x9b\x6f\x48\x08\x15\x56\xcf\xbf\xf1\x2b\x7c\x5e\x9a\x76\xe9\x59\x90\xc5\x7c\x83\x35\x11\x65\x51", 0 }, + /* Anchor: 3 a-cert-advanced.crt serial: #{a.serial.to_s} + C=AT,ST=Austria,L=Vienna,O=ARGE DATEN - Austrian Society for Data Protection,OU=A-CERT Certification Service,CN=A-CERT ADVANCED,1.2.840.113549.1.9.1=#160E696E666F40612D636572742E6174 + */ + { 1751, "\x30\x82\x06\xd3\x30\x82\x05\xbb\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xcc\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x41\x54\x31\x10\x30\x0e\x06\x03\x55\x04\x08\x13\x07\x41\x75\x73\x74\x72\x69\x61\x31\x0f\x30\x0d\x06\x03\x55\x04\x07\x13\x06\x56\x69\x65\x6e\x6e\x61\x31\x3a\x30\x38\x06\x03\x55\x04\x0a\x13\x31\x41\x52\x47\x45\x20\x44\x41\x54\x45\x4e\x20\x2d\x20\x41\x75\x73\x74\x72\x69\x61\x6e\x20\x53\x6f\x63\x69\x65\x74\x79\x20\x66\x6f\x72\x20\x44\x61\x74\x61\x20\x50\x72\x6f\x74\x65\x63\x74\x69\x6f\x6e\x31\x25\x30\x23\x06\x03\x55\x04\x0b\x13\x1c\x41\x2d\x43\x45\x52\x54\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x31\x18\x30\x16\x06\x03\x55\x04\x03\x13\x0f\x41\x2d\x43\x45\x52\x54\x20\x41\x44\x56\x41\x4e\x43\x45\x44\x31\x1d\x30\x1b\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0e\x69\x6e\x66\x6f\x40\x61\x2d\x63\x65\x72\x74\x2e\x61\x74\x30\x1e\x17\x0d\x30\x34\x31\x30\x32\x33\x31\x34\x31\x34\x31\x34\x5a\x17\x0d\x31\x31\x31\x30\x32\x33\x31\x34\x31\x34\x31\x34\x5a\x30\x81\xcc\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x41\x54\x31\x10\x30\x0e\x06\x03\x55\x04\x08\x13\x07\x41\x75\x73\x74\x72\x69\x61\x31\x0f\x30\x0d\x06\x03\x55\x04\x07\x13\x06\x56\x69\x65\x6e\x6e\x61\x31\x3a\x30\x38\x06\x03\x55\x04\x0a\x13\x31\x41\x52\x47\x45\x20\x44\x41\x54\x45\x4e\x20\x2d\x20\x41\x75\x73\x74\x72\x69\x61\x6e\x20\x53\x6f\x63\x69\x65\x74\x79\x20\x66\x6f\x72\x20\x44\x61\x74\x61\x20\x50\x72\x6f\x74\x65\x63\x74\x69\x6f\x6e\x31\x25\x30\x23\x06\x03\x55\x04\x0b\x13\x1c\x41\x2d\x43\x45\x52\x54\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x31\x18\x30\x16\x06\x03\x55\x04\x03\x13\x0f\x41\x2d\x43\x45\x52\x54\x20\x41\x44\x56\x41\x4e\x43\x45\x44\x31\x1d\x30\x1b\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0e\x69\x6e\x66\x6f\x40\x61\x2d\x63\x65\x72\x74\x2e\x61\x74\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xdd\xeb\x97\x23\x2f\xa6\x9d\xfe\x81\x60\xa6\xca\xf9\x01\xf9\x93\xae\xfd\xb5\x41\x6a\x79\x3f\x23\x95\x9c\x4c\x7b\x0f\x1e\x36\x21\xee\xc3\xd2\xa8\xc5\x60\x73\x2f\xa2\xa4\xb0\xaf\xb9\xb8\xae\xc6\x6a\xdc\x3e\xb1\xb0\x18\x9e\xd1\x06\x13\xcd\x0f\xf8\x98\x35\x84\x00\xcc\x7b\xe1\x6b\xe5\x5d\x1b\x73\xa4\x12\xde\x09\x15\xb5\xf5\x02\x5b\xf4\x48\xbd\xf3\x0c\xdf\xda\x31\xbe\x6a\x89\x98\xe8\x0f\x9c\x95\x3b\x1f\xaf\xa7\x98\xbb\x6c\xab\xad\x6d\xbf\xd9\x15\x26\x2f\xf6\xe1\x8e\x70\x5d\x6d\xe8\x75\xeb\x7b\xda\xc1\x79\xec\x4a\x06\xea\xce\xfc\xc3\x40\x54\x54\xb3\x5c\x32\x78\x12\xf5\xb6\x59\xce\x67\x46\xdf\xf7\x7a\x25\xb9\x06\x82\x83\x45\xff\xc0\xdc\x80\x20\x49\x5b\xfb\x74\x26\xb7\x08\xcf\x2a\x69\x5c\x83\x95\xb5\x4c\xf3\x3a\xba\xd4\xf3\xac\xee\x52\x04\xf7\x46\xd9\x25\xe6\x48\xc6\xec\x31\x07\xa4\x56\xfd\x1f\x47\xd3\x39\x8d\x6f\xf3\xe8\x11\xa1\xa3\xba\xda\x00\x34\x3c\x28\xb2\xb2\x05\x59\x8f\x08\x15\x79\x87\xb7\x28\x08\x35\xd6\x7c\xe7\xca\x57\x83\xbf\x5f\x7c\xb8\xad\xc3\x73\x5a\x17\x20\x66\x23\x27\x1d\x85\xa4\xa5\x94\xbc\x0b\x80\x13\x02\x03\x01\x00\x01\xa3\x82\x02\xbc\x30\x82\x02\xb8\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x37\x7f\x3e\x3e\x99\x71\x60\xca\x24\xd4\x91\x13\x79\xd0\x74\x29\xb4\xa8\x24\xd8\x30\x81\xf9\x06\x03\x55\x1d\x23\x04\x81\xf1\x30\x81\xee\x80\x14\x37\x7f\x3e\x3e\x99\x71\x60\xca\x24\xd4\x91\x13\x79\xd0\x74\x29\xb4\xa8\x24\xd8\xa1\x81\xd2\xa4\x81\xcf\x30\x81\xcc\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x41\x54\x31\x10\x30\x0e\x06\x03\x55\x04\x08\x13\x07\x41\x75\x73\x74\x72\x69\x61\x31\x0f\x30\x0d\x06\x03\x55\x04\x07\x13\x06\x56\x69\x65\x6e\x6e\x61\x31\x3a\x30\x38\x06\x03\x55\x04\x0a\x13\x31\x41\x52\x47\x45\x20\x44\x41\x54\x45\x4e\x20\x2d\x20\x41\x75\x73\x74\x72\x69\x61\x6e\x20\x53\x6f\x63\x69\x65\x74\x79\x20\x66\x6f\x72\x20\x44\x61\x74\x61\x20\x50\x72\x6f\x74\x65\x63\x74\x69\x6f\x6e\x31\x25\x30\x23\x06\x03\x55\x04\x0b\x13\x1c\x41\x2d\x43\x45\x52\x54\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x31\x18\x30\x16\x06\x03\x55\x04\x03\x13\x0f\x41\x2d\x43\x45\x52\x54\x20\x41\x44\x56\x41\x4e\x43\x45\x44\x31\x1d\x30\x1b\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0e\x69\x6e\x66\x6f\x40\x61\x2d\x63\x65\x72\x74\x2e\x61\x74\x82\x01\x00\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\xe6\x30\x47\x06\x03\x55\x1d\x25\x04\x40\x30\x3e\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x02\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x03\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x04\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x08\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x0a\x03\x04\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\xff\x30\x51\x06\x03\x55\x1d\x20\x04\x4a\x30\x48\x30\x46\x06\x08\x2a\x28\x00\x18\x01\x01\x01\x03\x30\x3a\x30\x38\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x2c\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x61\x2d\x63\x65\x72\x74\x2e\x61\x74\x2f\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x2d\x70\x6f\x6c\x69\x63\x79\x2e\x68\x74\x6d\x6c\x30\x3b\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x08\x04\x2e\x16\x2c\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x61\x2d\x63\x65\x72\x74\x2e\x61\x74\x2f\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x2d\x70\x6f\x6c\x69\x63\x79\x2e\x68\x74\x6d\x6c\x30\x19\x06\x03\x55\x1d\x11\x04\x12\x30\x10\x81\x0e\x69\x6e\x66\x6f\x40\x61\x2d\x63\x65\x72\x74\x2e\x61\x74\x30\x2f\x06\x03\x55\x1d\x12\x04\x28\x30\x26\x81\x0e\x69\x6e\x66\x6f\x40\x61\x2d\x63\x65\x72\x74\x2e\x61\x74\x86\x14\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x61\x2d\x63\x65\x72\x74\x2e\x61\x74\x30\x45\x06\x03\x55\x1d\x1f\x04\x3e\x30\x3c\x30\x3a\xa0\x38\xa0\x36\x86\x34\x68\x74\x74\x70\x73\x3a\x2f\x2f\x73\x65\x63\x75\x72\x65\x2e\x61\x2d\x63\x65\x72\x74\x2e\x61\x74\x2f\x63\x67\x69\x2d\x62\x69\x6e\x2f\x61\x2d\x63\x65\x72\x74\x2d\x61\x64\x76\x61\x6e\x63\x65\x64\x2e\x63\x67\x69\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x25\xf5\x22\xf8\x1f\x74\x6d\xab\xbd\xfb\xf7\xe4\xee\x3c\xbd\x21\x2f\x71\x56\x84\x76\x53\x7c\x51\x21\x41\x1d\x6c\xf7\x25\x10\x28\xce\x0c\xef\x68\x1b\x70\x1e\x48\xca\x67\x0b\x79\x97\xf0\x56\x3a\xd8\xdb\xbc\x77\xd1\x8c\x3b\x7b\x8a\x39\x41\x11\xcc\x4e\x3a\xb3\x42\xd5\xf7\xf2\x30\x7c\x07\xad\x7a\x6f\x7d\xfe\x98\xa5\x0e\x70\x9f\x19\x88\x60\x44\x1c\x51\x18\x86\x1c\xca\xab\xb8\x45\xf4\x5a\x4b\x83\x36\x04\x8a\xc1\xe7\xec\x81\x7b\x36\xed\xe7\x81\x6a\xe1\xe0\x34\x65\x5c\x4d\x81\xf5\xae\x61\xee\xfd\x9c\x8b\xa4\xbc\x4e\xc8\x94\x36\x3c\x2c\xc0\xd4\x3c\xd6\xde\xb5\xa4\x21\x7f\x76\xa2\x02\x7b\x95\x34\x5d\x5a\xb6\xf1\xc1\x42\xf5\x5c\x68\xa7\xc6\x79\xda\x43\xbe\x3e\xff\x2d\x29\x23\xd2\x4d\x12\xfe\xe2\x73\x6b\x69\x93\x07\x91\x32\x99\x1e\x75\xa2\xd6\x9a\xc0\xb5\xfa\x8a\xdf\x29\x37\x9b\xb2\x0e\xbd\x68\xc6\x82\xc7\xba\x3a\x8c\xd3\x8d\x46\x64\x7f\xed\x35\x5a\x3d\xff\x3f\x93\xa8\x39\xd9\xc1\xd9\xf5\x85\xa3\x42\xfb\xa9\xdb\x66\xf9\xad\x6c\x46\x27\x9a\xf9\x2d\x9e\x2f\x08\xf9\x85\xe3\xe4\xf8\x96\xeb\x63\x51\x80\x1a\xfe\x51\xae\x41\x38", 0 }, + /* Anchor: 4 A-Trust-nQual-01.cer serial: #{a.serial.to_s} + C=AT,O=A-Trust,OU=A-Trust-nQual-01,CN=A-Trust-nQual-01 + */ + { 865, "\x30\x82\x03\x5d\x30\x82\x02\x45\xa0\x03\x02\x01\x02\x02\x03\x00\xe2\x42\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x55\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x41\x54\x31\x10\x30\x0e\x06\x03\x55\x04\x0a\x13\x07\x41\x2d\x54\x72\x75\x73\x74\x31\x19\x30\x17\x06\x03\x55\x04\x0b\x13\x10\x41\x2d\x54\x72\x75\x73\x74\x2d\x6e\x51\x75\x61\x6c\x2d\x30\x31\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x41\x2d\x54\x72\x75\x73\x74\x2d\x6e\x51\x75\x61\x6c\x2d\x30\x31\x30\x1e\x17\x0d\x30\x34\x31\x31\x33\x30\x32\x33\x30\x30\x30\x30\x5a\x17\x0d\x31\x34\x31\x31\x33\x30\x32\x33\x30\x30\x30\x30\x5a\x30\x55\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x41\x54\x31\x10\x30\x0e\x06\x03\x55\x04\x0a\x13\x07\x41\x2d\x54\x72\x75\x73\x74\x31\x19\x30\x17\x06\x03\x55\x04\x0b\x13\x10\x41\x2d\x54\x72\x75\x73\x74\x2d\x6e\x51\x75\x61\x6c\x2d\x30\x31\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x41\x2d\x54\x72\x75\x73\x74\x2d\x6e\x51\x75\x61\x6c\x2d\x30\x31\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xff\xf5\x1c\x80\x11\x9e\x9e\x1e\x68\x58\xcc\xd2\x77\xdb\xc7\xf4\x8e\x67\x52\x50\x58\xba\x12\xa4\x6a\x3b\x16\xf7\x8c\x73\x4f\x4c\x8a\x4a\xf3\x60\x91\xeb\x3e\x65\x99\x29\xd9\x40\xd5\x2e\x08\xf0\xfe\x86\xd6\xcd\x65\xf7\xdd\xd8\x32\x95\x07\x4e\x8d\x3b\x26\x75\xdb\x37\x0e\x30\x28\x23\xe0\x6b\x64\x66\x8a\x84\xd3\x33\xe9\x3d\x3d\xdb\xa6\x81\x39\xe6\x79\x19\x65\xef\xea\x58\x45\xff\xeb\x8c\x33\xfc\xbf\xf8\x11\xd9\x2f\x28\x34\x8a\x1b\xf5\x2c\x3f\xbe\x4c\xb6\x60\x95\x63\x99\xb6\x12\x0e\xf7\x45\x51\x51\xcf\x87\x1c\x04\x83\x29\x1d\xe9\x78\x97\x31\x2a\x4a\x47\x43\xb5\x93\x98\xe5\xf9\xe4\xac\x4d\xf7\xde\x1c\x7a\xee\x7c\x6a\xdb\x5b\xd8\xf0\x4c\x9f\xf0\xee\x1f\x3d\x0e\x51\xb4\xdf\x1e\xa2\x14\x02\x70\xf4\x35\xcf\xac\xa9\x53\x54\x7b\x37\xd8\xcf\x46\x99\xc8\xfb\x2c\xcc\x3a\x2c\x1d\xdf\xe4\x1c\x2a\x11\xe2\xd6\x68\x82\xce\x8d\x29\x90\xe6\x81\xd4\x2c\x26\x7e\xc4\xf2\x36\x5f\x2a\x53\x43\x49\x50\xbf\x53\x6b\xa7\x1e\x6b\xb5\x93\x87\x04\xe2\x5a\x89\x76\xc8\x3f\x3c\x71\xdd\x9c\xcb\x7f\x3c\xc6\x96\xcd\x91\xfa\xc2\x3e\x66\x4d\x18\xba\x15\x02\x03\x01\x00\x01\xa3\x36\x30\x34\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x11\x06\x03\x55\x1d\x0e\x04\x0a\x04\x08\x4e\x59\xce\xc7\x02\x32\x87\x30\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xeb\xd2\x3d\x47\x58\x54\xf4\x66\xe5\xf6\xf5\x7b\x5b\xb0\x07\x42\x95\x09\x02\x51\x40\xbe\xfd\x88\xb7\xf7\x98\xf2\x9d\xa8\xb9\x05\x0f\x55\xa4\x99\x8a\x46\x8a\xb4\x06\x2b\x08\x3f\xda\xaf\x37\xd7\x07\x8d\xd0\x7a\xdf\x9d\x33\xa0\xa9\x1e\xc9\xfc\x8a\x46\x11\xbd\x02\x9e\x3e\x35\xef\xdc\x4b\xdf\xf8\x2d\x5b\xc7\x02\x40\x8a\x67\x27\x65\x5e\x96\xf9\xb3\x4e\x4e\x97\x68\xf2\x55\xe5\x8f\x19\x26\x7c\xdf\x99\xe5\x2f\x97\xce\xf2\xb6\xb6\xd5\x2d\x3f\x81\x2d\x60\xe5\x5a\xc4\x7c\x36\x98\xf3\x0d\x6e\xf0\xde\x63\xe7\xe8\x26\x48\x81\x9f\x72\x98\x8c\x66\x9b\x31\xa4\x7c\x9a\x86\x6a\xa1\xfe\x68\x7e\x3e\x22\x4b\xf5\xb2\x6a\x64\xd9\xb6\x2e\xaf\xfd\xf2\xb1\x9f\x5b\xc8\x23\xef\xee\x5a\x47\x31\x57\x90\xd3\xe7\xea\xfd\x1c\xba\x27\xd0\xd6\x05\xd1\x58\x37\xd7\xb5\xa1\xfa\x05\x83\x57\x9f\x55\x66\x8f\x9d\x73\x02\x43\x6f\xe9\x1e\x62\xa3\x05\x62\x8a\xa9\xef\xb4\x86\x91\x91\xae\xe3\x54\xbc\x34\x66\x24\x41\x8d\xd7\xf6\xb3\x47\x46\x40\xdb\x2d\xfa\x4a\x60\x39\xb2\xe8\xd6\xa7\xa4\xe1\x35\x10\x75\xb5\xfe\xc3\x52\x14\x0b\x38\xde\xa6\x59\x28\x91\x10\xc6", 0 }, + /* Anchor: 5 A-Trust-nQual-03.cer serial: #{a.serial.to_s} + C=AT,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,OU=A-Trust-nQual-03,CN=A-Trust-nQual-03 + */ + { 979, "\x30\x82\x03\xcf\x30\x82\x02\xb7\xa0\x03\x02\x01\x02\x02\x03\x01\x6c\x1e\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\x8d\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x41\x54\x31\x48\x30\x46\x06\x03\x55\x04\x0a\x0c\x3f\x41\x2d\x54\x72\x75\x73\x74\x20\x47\x65\x73\x2e\x20\x66\x2e\x20\x53\x69\x63\x68\x65\x72\x68\x65\x69\x74\x73\x73\x79\x73\x74\x65\x6d\x65\x20\x69\x6d\x20\x65\x6c\x65\x6b\x74\x72\x2e\x20\x44\x61\x74\x65\x6e\x76\x65\x72\x6b\x65\x68\x72\x20\x47\x6d\x62\x48\x31\x19\x30\x17\x06\x03\x55\x04\x0b\x0c\x10\x41\x2d\x54\x72\x75\x73\x74\x2d\x6e\x51\x75\x61\x6c\x2d\x30\x33\x31\x19\x30\x17\x06\x03\x55\x04\x03\x0c\x10\x41\x2d\x54\x72\x75\x73\x74\x2d\x6e\x51\x75\x61\x6c\x2d\x30\x33\x30\x1e\x17\x0d\x30\x35\x30\x38\x31\x37\x32\x32\x30\x30\x30\x30\x5a\x17\x0d\x31\x35\x30\x38\x31\x37\x32\x32\x30\x30\x30\x30\x5a\x30\x81\x8d\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x41\x54\x31\x48\x30\x46\x06\x03\x55\x04\x0a\x0c\x3f\x41\x2d\x54\x72\x75\x73\x74\x20\x47\x65\x73\x2e\x20\x66\x2e\x20\x53\x69\x63\x68\x65\x72\x68\x65\x69\x74\x73\x73\x79\x73\x74\x65\x6d\x65\x20\x69\x6d\x20\x65\x6c\x65\x6b\x74\x72\x2e\x20\x44\x61\x74\x65\x6e\x76\x65\x72\x6b\x65\x68\x72\x20\x47\x6d\x62\x48\x31\x19\x30\x17\x06\x03\x55\x04\x0b\x0c\x10\x41\x2d\x54\x72\x75\x73\x74\x2d\x6e\x51\x75\x61\x6c\x2d\x30\x33\x31\x19\x30\x17\x06\x03\x55\x04\x03\x0c\x10\x41\x2d\x54\x72\x75\x73\x74\x2d\x6e\x51\x75\x61\x6c\x2d\x30\x33\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xad\x3d\x61\x6e\x03\xf3\x90\x3b\xc0\x41\x0b\x84\x80\xcd\xec\x2a\xa3\x9d\x6b\xbb\x6e\xc2\x42\x84\xf7\x51\x14\xe1\xa0\xa8\x2d\x51\xa3\x51\xf2\xde\x23\xf0\x34\x44\xff\x94\xeb\xcc\x05\x23\x95\x40\xb9\x07\x78\xa5\x25\xf6\x0a\xbd\x45\x86\xe8\xd9\xbd\xc0\x04\x8e\x85\x44\x61\xef\x7f\xa7\xc9\xfa\xc1\x25\xcc\x85\x2c\x63\x3f\x05\x60\x73\x49\x05\xe0\x60\x78\x95\x10\x4b\xdc\xf9\x11\x59\xce\x71\x7f\x40\x9b\x8a\xaa\x24\xdf\x0b\x42\xe2\xdb\x56\xbc\x4a\xd2\xa5\x0c\x9b\xb7\x43\x3e\xdd\x83\xd3\x26\x10\x02\xcf\xea\x23\xc4\x49\x4e\xe5\xd3\xe9\xb4\x88\xab\x0c\xae\x62\x92\xd4\x65\x87\xd9\x6a\xd7\xf4\x85\x9f\xe4\x33\x22\x25\xa5\xe5\xc8\x33\xba\xc3\xc7\x41\xdc\x5f\xc6\x6a\xcc\x00\x0e\x6d\x32\xa8\xb6\x87\x36\x00\x62\x77\x9b\x1e\x1f\x34\xcb\x90\x3c\x78\x88\x74\x05\xeb\x79\xf5\x93\x71\x65\xca\x9d\xc7\x6b\x18\x2d\x3d\x5c\x4e\xe7\xd5\xf8\x3f\x31\x7d\x8f\x87\xec\x0a\x22\x2f\x23\xe9\xfe\xbb\x7d\xc9\xe0\xf4\xec\xeb\x7c\xc4\xb0\xc3\x2d\x62\xb5\x9a\x71\xd6\xb1\x6a\xe8\xec\xd9\xed\xd5\x72\xec\xbe\x57\x01\xce\x05\x55\x9f\xde\xd1\x60\x88\x10\xb3\x02\x03\x01\x00\x01\xa3\x36\x30\x34\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x11\x06\x03\x55\x1d\x0e\x04\x0a\x04\x08\x44\x6a\x95\x67\x55\x79\x11\x4f\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x55\xd4\x54\xd1\x59\x48\x5c\xb3\x93\x85\xaa\xbf\x63\x2f\xe4\x80\xce\x34\xa3\x34\x62\x3e\xf6\xd8\xee\x67\x88\x31\x04\x03\x6f\x0b\xd4\x07\xfb\x4e\x75\x0f\xd3\x2e\xd3\xc0\x17\xc7\xc6\x28\xec\x06\x0d\x11\x24\x0e\x0e\xa5\x5d\xbf\x8c\xb2\x13\x96\x71\xdc\xd4\xce\x0e\x0d\x0a\x68\x32\x6c\xb9\x41\x31\x19\xab\xb1\x07\x7b\x4d\x98\xd3\x5c\xb0\xd1\xf0\xa7\x42\xa0\xb5\xc4\x8e\xaf\xfe\xf1\x3f\xf4\xef\x4f\x46\x00\x76\xeb\x02\xfb\xf9\x9d\xd2\x40\x96\xc7\x88\x3a\xb8\x9f\x11\x79\xf3\x80\x65\xa8\xbd\x1f\xd3\x78\x81\xa0\x51\x4c\x37\xb4\xa6\x5d\x25\x70\xd1\x66\xc9\x68\xf9\x2e\x11\x14\x68\xf1\x54\x98\x08\xac\x26\x92\x0f\xde\x89\x9e\xd4\xfa\xb3\x79\x2b\xd2\xa3\x79\xd4\xec\x8b\xac\x87\x53\x68\x42\x4c\x51\x51\x74\x1e\x1b\x27\x2e\xe3\xf5\x1f\x29\x74\x4d\xed\xaf\xf7\xe1\x92\x99\x81\xe8\xbe\x3a\xc7\x17\x50\xf6\xb7\xc6\xfc\x9b\xb0\x8a\x6b\xd6\x88\x03\x91\x8f\x06\x77\x3a\x85\x02\xdd\x98\xd5\x43\x78\x3f\xc6\x30\x15\xac\x9b\x6b\xcb\x57\xb7\x89\x51\x8b\x3a\xe8\xc9\x84\x0c\xdb\xb1\x50\x20\x0a\x1a\x4a\xba\x6a\x1a\xbd\xec\x1b\xc8\xc5\x84\x9a\xcd", 0 }, + /* Anchor: 6 A-Trust-Qual-01.cer serial: #{a.serial.to_s} + C=AT,O=A-Trust Ges. für Sicherheitssysteme im elektr. Datenverkehr GmbH,OU=A-Trust-Qual-01,CN=A-Trust-Qual-01 + */ + { 1111, "\x30\x82\x04\x53\x30\x82\x03\x3b\xa0\x03\x02\x01\x02\x02\x03\x00\xe2\x43\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xcf\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x41\x54\x31\x81\x8b\x30\x81\x88\x06\x03\x55\x04\x0a\x1e\x81\x80\x00\x41\x00\x2d\x00\x54\x00\x72\x00\x75\x00\x73\x00\x74\x00\x20\x00\x47\x00\x65\x00\x73\x00\x2e\x00\x20\x00\x66\x00\xfc\x00\x72\x00\x20\x00\x53\x00\x69\x00\x63\x00\x68\x00\x65\x00\x72\x00\x68\x00\x65\x00\x69\x00\x74\x00\x73\x00\x73\x00\x79\x00\x73\x00\x74\x00\x65\x00\x6d\x00\x65\x00\x20\x00\x69\x00\x6d\x00\x20\x00\x65\x00\x6c\x00\x65\x00\x6b\x00\x74\x00\x72\x00\x2e\x00\x20\x00\x44\x00\x61\x00\x74\x00\x65\x00\x6e\x00\x76\x00\x65\x00\x72\x00\x6b\x00\x65\x00\x68\x00\x72\x00\x20\x00\x47\x00\x6d\x00\x62\x00\x48\x31\x18\x30\x16\x06\x03\x55\x04\x0b\x13\x0f\x41\x2d\x54\x72\x75\x73\x74\x2d\x51\x75\x61\x6c\x2d\x30\x31\x31\x18\x30\x16\x06\x03\x55\x04\x03\x13\x0f\x41\x2d\x54\x72\x75\x73\x74\x2d\x51\x75\x61\x6c\x2d\x30\x31\x30\x1e\x17\x0d\x30\x34\x31\x31\x33\x30\x32\x33\x30\x30\x30\x30\x5a\x17\x0d\x31\x34\x31\x31\x33\x30\x32\x33\x30\x30\x30\x30\x5a\x30\x81\xcf\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x41\x54\x31\x81\x8b\x30\x81\x88\x06\x03\x55\x04\x0a\x1e\x81\x80\x00\x41\x00\x2d\x00\x54\x00\x72\x00\x75\x00\x73\x00\x74\x00\x20\x00\x47\x00\x65\x00\x73\x00\x2e\x00\x20\x00\x66\x00\xfc\x00\x72\x00\x20\x00\x53\x00\x69\x00\x63\x00\x68\x00\x65\x00\x72\x00\x68\x00\x65\x00\x69\x00\x74\x00\x73\x00\x73\x00\x79\x00\x73\x00\x74\x00\x65\x00\x6d\x00\x65\x00\x20\x00\x69\x00\x6d\x00\x20\x00\x65\x00\x6c\x00\x65\x00\x6b\x00\x74\x00\x72\x00\x2e\x00\x20\x00\x44\x00\x61\x00\x74\x00\x65\x00\x6e\x00\x76\x00\x65\x00\x72\x00\x6b\x00\x65\x00\x68\x00\x72\x00\x20\x00\x47\x00\x6d\x00\x62\x00\x48\x31\x18\x30\x16\x06\x03\x55\x04\x0b\x13\x0f\x41\x2d\x54\x72\x75\x73\x74\x2d\x51\x75\x61\x6c\x2d\x30\x31\x31\x18\x30\x16\x06\x03\x55\x04\x03\x13\x0f\x41\x2d\x54\x72\x75\x73\x74\x2d\x51\x75\x61\x6c\x2d\x30\x31\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xa6\x86\x07\x71\x21\xbc\x53\x18\x43\x87\x7d\x71\xa2\x7b\x02\x37\x34\x59\x5d\x01\x62\x85\x59\xf2\xe8\x7c\xef\xb9\x23\x55\x1b\xbc\x0e\x5a\xbe\xde\xc8\x82\xc1\x97\xcf\xfb\x48\xfd\xfe\x47\x19\x46\xda\xb1\xc2\x34\x8b\xbc\x46\xd2\xda\x95\x94\x0e\x5c\xb5\x08\x0b\x46\xac\x60\xc4\x7b\x60\x4e\x43\x1c\xaa\xc0\x04\x61\xdb\x33\xdc\xb6\x6c\x09\xd5\xce\xd5\x0a\xef\x10\x11\x8b\x4d\x20\x01\x77\x18\x8b\xfe\x04\x96\x27\xac\xfb\xec\x24\xb0\xc7\xb5\xe0\xd3\x61\xf0\xc4\xf5\x7c\xd9\xc8\xc6\x91\x21\x77\x10\xd1\x89\x9e\xdb\x88\x00\x09\xd1\x0d\x69\xff\x39\x11\xe3\x15\xab\x4d\x47\x29\xa8\x31\xb1\xda\x38\x46\x57\x48\x68\x5f\xed\x8e\x45\xae\xb1\xc4\xa8\x6c\xa2\xf4\x4e\xac\xbf\xbf\x38\x0d\xef\xd3\xd5\xa4\xef\xb2\x49\xfc\x71\x67\x94\x98\x3c\xef\xff\xfa\x26\x88\x6f\xda\xfd\x5f\x4a\x41\xec\x7f\xeb\x55\xcd\xf0\xeb\x61\x51\x05\x67\x5f\xeb\xbf\x96\x22\xf6\x34\xac\x7b\xe0\x8d\x82\xfc\x68\x07\x5f\x90\x74\x5a\x43\xcd\xaa\xc4\x8e\x82\x69\x6f\x27\xf7\x0a\xb9\x3d\x0f\xbd\xe5\x20\x54\x50\xc0\x03\x4a\x18\x06\x07\x04\xd4\xa0\xcc\x94\x16\xcd\xd2\x49\x8f\x02\x03\x01\x00\x01\xa3\x36\x30\x34\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x11\x06\x03\x55\x1d\x0e\x04\x0a\x04\x08\x4b\x3c\x8c\x1d\x85\xe9\x6f\xad\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x21\x4b\xac\x98\x9c\xcc\x25\x18\x90\xf1\x30\x07\xac\x90\x0e\x7a\x57\xee\x5a\x84\xc6\x72\xa7\x48\xbf\xb4\xf2\xb3\xf7\xcd\x97\x6c\x85\xd9\xf8\xef\x1d\x3f\x09\xd3\x56\x8a\x89\xa9\x45\x56\x96\xd5\x79\x0d\x97\x29\xbd\x4e\xd9\xb1\xce\x41\x80\x0a\x82\xc7\x59\xda\x36\x7f\xb1\xd2\xf6\x51\x51\x51\x4c\x79\xa2\x74\xbb\xba\x3d\xd8\x16\x08\x14\x61\x25\x84\x04\x2d\x0a\x29\x84\xef\x50\x56\xf7\xe1\x00\x0d\x13\xc1\xb1\x12\x62\xa4\xf3\xfa\x79\x48\xe4\x6a\xfb\x09\x97\xbc\x7f\xa1\xc4\x9a\x12\x66\x0a\xd5\x10\xb1\xd4\x02\xb9\xf1\xa0\x95\x18\x78\x4f\xeb\x48\x1a\x23\x46\x72\x7c\x95\x10\x76\x7d\xde\x64\x95\x7a\x91\x6b\xd5\x50\x36\xf4\x24\xd1\x3e\xd7\xae\x1a\x30\x3c\xd6\x37\x80\xcf\xda\x5e\x62\x21\x44\xd4\x25\xef\xc4\xaf\x5c\x26\x2b\xf4\x05\xc0\x0b\x14\xb5\xa6\x00\x30\xa8\x44\xbc\xc8\x45\x98\x40\xfa\xc0\x30\x61\x49\xb0\x33\x5a\xea\x54\x23\xc0\xde\x40\x50\xbc\x80\xbd\xe6\xdc\x90\xbc\xdc\xb6\x74\x6d\x15\xb3\xe3\xba\x3f\x02\xda\x35\x7f\xec\xb9\x29\x44\x95\x0d\x3a\x5f\x69\x75\x57\x03\x1a\x61\xbe\x2f\x64\xa1\x6a\x37\x46\xce\x84\x15\xc4\x56", 0 }, + /* Anchor: 7 A-Trust-Qual-02a.crt serial: #{a.serial.to_s} + C=AT,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,OU=A-Trust-Qual-02,CN=A-Trust-Qual-02 + */ + { 975, "\x30\x82\x03\xcb\x30\x82\x02\xb3\xa0\x03\x02\x01\x02\x02\x03\x00\xe2\x48\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\x8b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x41\x54\x31\x48\x30\x46\x06\x03\x55\x04\x0a\x0c\x3f\x41\x2d\x54\x72\x75\x73\x74\x20\x47\x65\x73\x2e\x20\x66\x2e\x20\x53\x69\x63\x68\x65\x72\x68\x65\x69\x74\x73\x73\x79\x73\x74\x65\x6d\x65\x20\x69\x6d\x20\x65\x6c\x65\x6b\x74\x72\x2e\x20\x44\x61\x74\x65\x6e\x76\x65\x72\x6b\x65\x68\x72\x20\x47\x6d\x62\x48\x31\x18\x30\x16\x06\x03\x55\x04\x0b\x0c\x0f\x41\x2d\x54\x72\x75\x73\x74\x2d\x51\x75\x61\x6c\x2d\x30\x32\x31\x18\x30\x16\x06\x03\x55\x04\x03\x0c\x0f\x41\x2d\x54\x72\x75\x73\x74\x2d\x51\x75\x61\x6c\x2d\x30\x32\x30\x1e\x17\x0d\x30\x34\x31\x32\x30\x32\x32\x33\x30\x30\x30\x30\x5a\x17\x0d\x31\x34\x31\x32\x30\x32\x32\x33\x30\x30\x30\x30\x5a\x30\x81\x8b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x41\x54\x31\x48\x30\x46\x06\x03\x55\x04\x0a\x0c\x3f\x41\x2d\x54\x72\x75\x73\x74\x20\x47\x65\x73\x2e\x20\x66\x2e\x20\x53\x69\x63\x68\x65\x72\x68\x65\x69\x74\x73\x73\x79\x73\x74\x65\x6d\x65\x20\x69\x6d\x20\x65\x6c\x65\x6b\x74\x72\x2e\x20\x44\x61\x74\x65\x6e\x76\x65\x72\x6b\x65\x68\x72\x20\x47\x6d\x62\x48\x31\x18\x30\x16\x06\x03\x55\x04\x0b\x0c\x0f\x41\x2d\x54\x72\x75\x73\x74\x2d\x51\x75\x61\x6c\x2d\x30\x32\x31\x18\x30\x16\x06\x03\x55\x04\x03\x0c\x0f\x41\x2d\x54\x72\x75\x73\x74\x2d\x51\x75\x61\x6c\x2d\x30\x32\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\x96\x91\xab\xd7\x8e\xb0\x59\xb8\x01\xbd\xb4\x1e\xad\x99\xfd\xa1\xfc\xea\x0c\x96\x6b\x8f\x2e\x49\x48\xd8\xe9\xe4\x24\x82\xe1\xd8\xba\xcc\xeb\xde\x07\x5c\x48\xc6\x19\x82\x01\x47\x42\x09\xe1\x7c\xb9\x9f\xae\x8f\xf6\xee\x5e\x6b\xa8\xa8\x56\x88\x38\x56\xb3\xe6\xfe\xc9\x9d\x4f\x34\x38\x51\x3c\x9c\xbe\xf3\xac\x9c\x1c\xc8\x3d\x5c\x9a\x84\xae\xf7\x94\x2c\x14\xb2\x64\x37\x60\x8e\x14\xb0\x3b\x2a\xcd\x89\xb5\x22\xaf\xf7\xe4\x7f\xee\x2c\x2b\x33\xf9\x8e\x3c\xad\x4c\xa2\x57\x0f\xfb\x82\xc5\x8e\x1f\x01\xdf\x53\x8c\xc1\x15\xa4\xdd\xee\x9a\x92\x12\xd2\x28\xe9\x62\x17\x25\x60\x31\xef\xcf\x31\x94\xf3\x7d\xf3\xe4\x3c\x21\xab\x90\xfc\x6d\xcf\x63\xa7\xc6\x12\x00\x71\x49\xd7\x1c\xc8\xa0\xed\x63\x9a\x7d\xe3\x8f\x28\xdd\x60\xf9\xd8\xe6\x16\xab\x26\xd1\xd0\x2f\xbd\xe7\x0d\x09\xdf\x6e\xd4\xec\xe5\x38\x53\xf4\x64\x0b\xba\x5a\xcc\x80\xb5\x38\x59\xec\x80\x59\x65\x84\x31\x6a\x5f\x55\x91\x4c\x24\xe5\x24\x9a\x83\x84\x7a\xbe\x80\xf1\xee\x5f\x20\x07\xaa\x77\x17\x6c\x0b\xe2\x55\xaa\x96\x78\x08\x02\x9e\x97\xf0\x2b\xae\x58\xf5\x80\x50\x3f\xfe\x3b\x02\x03\x01\x00\x01\xa3\x36\x30\x34\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x11\x06\x03\x55\x1d\x0e\x04\x0a\x04\x08\x42\x3d\x2b\x24\xa6\xc1\x45\xce\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x46\xcb\x11\x63\x50\x0d\x9b\x3e\x45\xd4\x48\x2d\x92\x7c\x9d\xbd\xb6\x6a\xdb\x88\xb2\x9a\x97\xe8\x3a\x6b\xd3\x3c\x5f\x07\x7e\x12\x3a\x3e\xa1\x89\x0d\x3f\xa1\x78\x19\xf7\x83\xb4\x05\xe9\x9b\xbc\x5b\xf4\xbc\xbc\x96\x17\x5b\x1d\xca\x51\x87\x30\x94\x40\x72\x75\xb4\x10\xa2\x19\xd2\xe0\x9a\x14\xb1\xed\x35\xe3\x86\x16\xa7\x28\xe7\x43\x82\x47\x6c\x0b\x54\xfe\xfb\xea\x62\xba\xe6\x0b\xef\x64\xc3\x81\x4c\xb6\x49\xbd\x46\x1e\x52\x75\x35\xce\xab\xbc\x1e\x1f\xa7\x14\x83\x00\xe1\xea\x1a\x95\x2a\xf4\xb5\xac\x73\x7b\x45\x91\x7a\x91\xaa\x64\x15\xb6\xab\x51\xef\xb9\xe9\x28\x81\x41\x8a\x87\x3a\xda\x34\xc1\xc0\x33\x0f\x5f\x78\x43\x24\x34\x75\x0d\x23\xdc\xe8\x19\xd9\x96\x26\x8d\xc3\x62\x07\x76\x23\x10\xd2\x60\x68\x61\xe4\x67\x15\xda\xbe\x4f\x20\xca\xb2\x39\x89\x38\xe4\x0f\x2f\x3c\xcb\xfe\xc6\x9a\xc3\xa1\x7c\xf7\x5f\xa0\x06\x32\xc5\x10\x5a\xae\x0f\x24\x7b\xde\x50\x0f\x25\x2d\xbb\xf5\x1d\xdc\xb2\x2f\x16\x5a\x4e\x19\x61\x40\xbf\xd5\x5f\x07\xdc\xab\x62\xa7\xf2\x7a\x69\xcf\x1e\xaa\x12\xc2\x6e\x62\x7c\xd4\xba\x3d\xd8\x91\x87\xcf\xfa\x2d", 0 }, + /* Anchor: 8 ac-racine.der serial: #{a.serial.to_s} + C=FR,O=CertiNomis,OU=AC Racine - Root CA,CN=CertiNomis + */ + { 887, "\x30\x82\x03\x73\x30\x82\x02\x5b\xa0\x03\x02\x01\x02\x02\x10\x30\x30\x30\x30\x39\x37\x33\x37\x35\x37\x33\x38\x36\x30\x30\x30\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x55\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x13\x30\x11\x06\x03\x55\x04\x0a\x13\x0a\x43\x65\x72\x74\x69\x4e\x6f\x6d\x69\x73\x31\x1c\x30\x1a\x06\x03\x55\x04\x0b\x13\x13\x41\x43\x20\x52\x61\x63\x69\x6e\x65\x20\x2d\x20\x52\x6f\x6f\x74\x20\x43\x41\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x43\x65\x72\x74\x69\x4e\x6f\x6d\x69\x73\x30\x1e\x17\x0d\x30\x30\x31\x31\x30\x39\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x31\x32\x31\x31\x30\x39\x30\x30\x30\x30\x30\x30\x5a\x30\x55\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x13\x30\x11\x06\x03\x55\x04\x0a\x13\x0a\x43\x65\x72\x74\x69\x4e\x6f\x6d\x69\x73\x31\x1c\x30\x1a\x06\x03\x55\x04\x0b\x13\x13\x41\x43\x20\x52\x61\x63\x69\x6e\x65\x20\x2d\x20\x52\x6f\x6f\x74\x20\x43\x41\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x43\x65\x72\x74\x69\x4e\x6f\x6d\x69\x73\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xf1\x25\x9b\xe2\x64\xb9\x45\x70\x77\x10\xd4\x88\x71\xfa\xc4\xcc\x28\xff\x4d\x15\x10\xb9\x3d\x6d\x30\x25\x34\x61\x47\xd7\x15\x28\x1c\x3d\xd5\xa0\x94\x8c\xc2\xbf\x79\x2f\x87\x4e\xd0\xa0\x1f\xbc\xc4\xc9\x7e\x7d\x01\xef\x49\x27\x6e\x03\x19\xcd\x7b\x0c\xf4\x18\x16\x3d\xac\x0a\x42\x3c\xa9\x4f\xe8\x27\x27\x26\xbe\xf8\x39\x25\x59\x22\x25\xad\xf7\x02\xdf\x97\x8c\x30\x84\xd8\x59\x3a\x28\xa4\x22\x96\x69\x11\xd3\x97\x5a\xa4\x5c\xf3\x83\xf9\x71\x49\x4d\xdc\xbc\x26\xaf\x5b\x23\x09\x69\x87\x7d\x34\x92\xe1\xc0\x0a\xc5\xf0\xdb\x14\xb7\xc4\xeb\x57\xad\xa2\xcc\xa8\x15\x95\x13\x41\xb2\x21\x6f\x50\x5f\x24\xbe\x71\x45\x70\x14\x66\xe7\x50\x89\x4e\x36\x9f\xfc\x80\xa1\x25\x2b\x37\x81\x4b\x51\xf3\xd0\x36\x53\x9e\xd4\x00\x7c\xd6\x92\x20\x5f\xc8\x36\xa2\x3c\x31\x0e\x37\xe0\xa9\x2b\x35\x26\x60\x45\xb8\xb2\x89\xe3\x9b\x95\x2c\x47\xa7\x40\x13\xe6\x40\x21\xa3\x2f\x79\x9a\x57\xce\x88\x46\x64\x77\x6b\xd5\x06\x96\x0b\xca\x02\x4d\x0d\x05\xd8\x7c\x9a\xb4\x32\x42\xf7\x14\x94\xb0\x48\x40\x10\xa6\x97\xbc\x29\xa6\xde\xa6\x69\x01\xd4\x34\x43\xd0\x4b\x02\x03\x01\x00\x01\xa3\x3f\x30\x3d\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x86\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xf8\x5e\x21\xa3\xa8\xa3\x15\xe6\xf8\xb5\x11\xbb\xfe\x42\x04\x5d\x4d\x8e\x82\x7a\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x27\xbd\x14\x96\xb2\x2b\xa6\xd7\x90\x94\x2b\x8a\x50\x45\x32\x1e\xf9\x40\xf7\x45\x3a\x4b\x3d\x3c\x9b\xa8\xf3\xa3\x8c\x52\x50\x43\x64\x66\x05\x4c\x28\x7d\x02\xb7\xb1\x37\x72\x98\x0a\x70\x04\xcd\xac\xd8\x20\x02\xf0\xaf\xb7\x80\x48\x92\x43\x21\x03\x2e\xd5\x0f\xa9\x93\x1f\xfb\x00\x27\x5e\xe2\x43\xf8\xec\x5d\xbb\x33\x6a\xe6\xfa\xfe\x47\x9c\x6a\x28\x08\xbc\xf6\xb3\xb1\x5e\xfd\x65\x32\x71\x34\x2a\x83\x01\x79\x94\xda\x74\xde\x6d\x5c\x7b\xf4\xef\xa2\xf8\x24\x11\x97\x95\x37\x9c\x0c\xff\xbf\x92\xb1\x92\xc9\x18\x38\xa0\x5c\x67\xaa\xe3\xc8\xf6\x83\x68\x67\xf0\xe7\x24\x5f\xd0\xa2\xca\x8d\x14\xdf\xfd\x48\x55\xe8\xa0\x34\x18\xac\x89\xa3\xa5\xb0\x74\x99\x38\x43\xc1\x65\x04\x62\x65\x42\xe8\x6f\xe3\x55\x6d\x75\x4f\xa3\xc9\xcc\xd4\xec\x8f\xdd\xa1\xc8\x2d\x07\xb1\xd7\x26\x1c\x0a\xbf\x66\xf7\x79\xce\x89\x9c\x8a\x92\xea\xf7\x51\xe7\x5f\xd7\x23\x13\x05\xef\x9f\x7e\x59\xcf\x14\xa1\x98\x9d\x5a\xaf\x4c\x65\xc2\x29\x57\x47\xcd\x00\x5f\xa4\x82\xc0\x02\xe6\x82\xfb\x9c\xa4\x66\x14\xa2\x48\xc7\xfc\x9e\x62\xf6\xa0\xf3\x1c\x2c\xee\xd8\x43\x0e", 0 }, + /* Anchor: 9 ac_offline_raiz_certicamara.crt serial: #{a.serial.to_s} + C=CO,O=Sociedad Cameral de Certificación Digital - Certicámara S.A.,CN=AC Raíz Certicámara S.A. + */ + { 1642, "\x30\x82\x06\x66\x30\x82\x04\x4e\xa0\x03\x02\x01\x02\x02\x0f\x07\x7e\x52\x93\x7b\xe0\x15\xe3\x57\xf0\x69\x8c\xcb\xec\x0c\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x7b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4f\x31\x47\x30\x45\x06\x03\x55\x04\x0a\x0c\x3e\x53\x6f\x63\x69\x65\x64\x61\x64\x20\x43\x61\x6d\x65\x72\x61\x6c\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\xc3\xb3\x6e\x20\x44\x69\x67\x69\x74\x61\x6c\x20\x2d\x20\x43\x65\x72\x74\x69\x63\xc3\xa1\x6d\x61\x72\x61\x20\x53\x2e\x41\x2e\x31\x23\x30\x21\x06\x03\x55\x04\x03\x0c\x1a\x41\x43\x20\x52\x61\xc3\xad\x7a\x20\x43\x65\x72\x74\x69\x63\xc3\xa1\x6d\x61\x72\x61\x20\x53\x2e\x41\x2e\x30\x1e\x17\x0d\x30\x36\x31\x31\x32\x37\x32\x30\x34\x36\x32\x39\x5a\x17\x0d\x33\x30\x30\x34\x30\x32\x32\x31\x34\x32\x30\x32\x5a\x30\x7b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4f\x31\x47\x30\x45\x06\x03\x55\x04\x0a\x0c\x3e\x53\x6f\x63\x69\x65\x64\x61\x64\x20\x43\x61\x6d\x65\x72\x61\x6c\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\xc3\xb3\x6e\x20\x44\x69\x67\x69\x74\x61\x6c\x20\x2d\x20\x43\x65\x72\x74\x69\x63\xc3\xa1\x6d\x61\x72\x61\x20\x53\x2e\x41\x2e\x31\x23\x30\x21\x06\x03\x55\x04\x03\x0c\x1a\x41\x43\x20\x52\x61\xc3\xad\x7a\x20\x43\x65\x72\x74\x69\x63\xc3\xa1\x6d\x61\x72\x61\x20\x53\x2e\x41\x2e\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\xab\x6b\x89\xa3\x53\xcc\x48\x23\x08\xfb\xc3\xcf\x51\x96\x08\x2e\xb8\x08\x7a\x6d\x3c\x90\x17\x86\xa9\xe9\xed\x2e\x13\x34\x47\xb2\xd0\x70\xdc\xc9\x3c\xd0\x8d\xca\xee\x4b\x17\xab\xd0\x85\xb0\xa7\x23\x04\xcb\xa8\xa2\xfc\xe5\x75\xdb\x40\xca\x62\x89\x8f\x50\x9e\x01\x3d\x26\x5b\x18\x84\x1c\xcb\x7c\x37\xb7\x7d\xec\xd3\x7f\x73\x19\xb0\x6a\xb2\xd8\x88\x8a\x2d\x45\x74\xa8\xf7\xb3\xb8\xc0\xd4\xda\xcd\x22\x89\x74\x4d\x5a\x15\x39\x73\x18\x74\x4f\xb5\xeb\x99\xa7\xc1\x1e\x88\xb4\xc2\x93\x90\x63\x97\xf3\xa7\xa7\x12\xb2\x09\x22\x07\x33\xd9\x91\xcd\x0e\x9c\x1f\x0e\x20\xc7\xee\xbb\x33\x8d\x8f\xc2\xd2\x58\xa7\x5f\xfd\x65\x37\xe2\x88\xc2\xd8\x8f\x86\x75\x5e\xf9\x2d\xa7\x87\x33\xf2\x78\x37\x2f\x8b\xbc\x1d\x86\x37\x39\xb1\x94\xf2\xd8\xbc\x4a\x9c\x83\x18\x5a\x06\xfc\xf3\xd4\xd4\xba\x8c\x15\x09\x25\xf0\xf9\xb6\x8d\x04\x7e\x17\x12\x33\x6b\x57\x48\x4c\x4f\xdb\x26\x1e\xeb\xcc\x90\xe7\x8b\xf9\x68\x7c\x70\x0f\xa3\x2a\xd0\x3a\x38\xdf\x37\x97\xe2\x5b\xde\x80\x61\xd3\x80\xd8\x91\x83\x42\x5a\x4c\x04\x89\x68\x11\x3c\xac\x5f\x68\x80\x41\xcc\x60\x42\xce\x0d\x5a\x2a\x0c\x0f\x9b\x30\xc0\xa6\xf0\x86\xdb\xab\x49\xd7\x97\x6d\x48\x8b\xf9\x03\xc0\x52\x67\x9b\x12\xf7\xc2\xf2\x2e\x98\x65\x42\xd9\xd6\x9a\xe3\xd0\x19\x31\x0c\xad\x87\xd5\x57\x02\x7a\x30\xe8\x86\x26\xfb\x8f\x23\x8a\x54\x87\xe4\xbf\x3c\xee\xeb\xc3\x75\x48\x5f\x1e\x39\x6f\x81\x62\x6c\xc5\x2d\xc4\x17\x54\x19\xb7\x37\x8d\x9c\x37\x91\xc8\xf6\x0b\xd5\xea\x63\x6f\x83\xac\x38\xc2\xf3\x3f\xde\x9a\xfb\xe1\x23\x61\xf0\xc8\x26\xcb\x36\xc8\xa1\xf3\x30\x8f\xa4\xa3\xa2\xa1\xdd\x53\xb3\xde\xf0\x9a\x32\x1f\x83\x91\x79\x30\xc1\xa9\x1f\x53\x9b\x53\xa2\x15\x53\x3f\xdd\x9d\xb3\x10\x3b\x48\x7d\x89\x0f\xfc\xed\x03\xf5\xfb\x25\x64\x75\x0e\x17\x19\x0d\x8f\x00\x16\x67\x79\x7a\x40\xfc\x2d\x59\x07\xd9\x90\xfa\x9a\xad\x3d\xdc\x80\x8a\xe6\x5c\x35\xa2\x67\x4c\x11\x6b\xb1\xf8\x80\x64\x00\x2d\x6f\x22\x61\xc5\xac\x4b\x26\xe5\x5a\x10\x82\x9b\xa4\x83\x7b\x34\xf7\x9e\x89\x91\x20\x97\x8e\xb7\x42\xc7\x66\xc3\xd0\xe9\xa4\xd6\xf5\x20\x8d\xc4\xc3\x95\xac\x44\x0a\x9d\x5b\x73\x3c\x26\x3d\x2f\x4a\xbe\xa7\xc9\xa7\x10\x1e\xfb\x9f\x50\x69\xf3\x02\x03\x01\x00\x01\xa3\x81\xe6\x30\x81\xe3\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xd1\x09\xd0\xe9\xd7\xce\x79\x74\x54\xf9\x3a\x30\xb3\xf4\x6d\x2c\x03\x03\x1b\x68\x30\x81\xa0\x06\x03\x55\x1d\x20\x04\x81\x98\x30\x81\x95\x30\x81\x92\x06\x04\x55\x1d\x20\x00\x30\x81\x89\x30\x2b\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x1f\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x63\x65\x72\x74\x69\x63\x61\x6d\x61\x72\x61\x2e\x63\x6f\x6d\x2f\x64\x70\x63\x2f\x30\x5a\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x02\x30\x4e\x1a\x4c\x4c\x69\x6d\x69\x74\x61\x63\x69\x6f\x6e\x65\x73\x20\x64\x65\x20\x67\x61\x72\x61\x6e\x74\xed\x61\x73\x20\x64\x65\x20\x65\x73\x74\x65\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x64\x6f\x20\x73\x65\x20\x70\x75\x65\x64\x65\x6e\x20\x65\x6e\x63\x6f\x6e\x74\x72\x61\x72\x20\x65\x6e\x20\x6c\x61\x20\x44\x50\x43\x2e\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x5c\x94\xb5\xb8\x45\x91\x4d\x8e\x61\x1f\x03\x28\x0f\x53\x7c\xe6\xa4\x59\xa9\xb3\x8a\x7a\xc5\xb0\xff\x08\x7c\x2c\xa3\x71\x1c\x21\x13\x67\xa1\x95\x12\x40\x35\x83\x83\x8f\x74\xdb\x33\x5c\xf0\x49\x76\x0a\x81\x52\xdd\x49\xd4\x9a\x32\x33\xef\x9b\xa7\xcb\x75\xe5\x7a\xcb\x97\x12\x90\x5c\xba\x7b\xc5\x9b\xdf\xbb\x39\x23\xc8\xff\x98\xce\x0a\x4d\x22\x01\x48\x07\x7e\x8a\xc0\xd5\x20\x42\x94\x44\xef\xbf\x77\xa2\x89\x67\x48\x1b\x40\x03\x05\xa1\x89\xec\xcf\x62\xe3\x3d\x25\x76\x66\xbf\x26\xb7\xbb\x22\xbe\x6f\xff\x39\x57\x74\xba\x7a\xc9\x01\x95\xc1\x95\x51\xe8\xab\x2c\xf8\xb1\x86\x20\xe9\x3f\xcb\x35\x5b\xd2\x17\xe9\x2a\xfe\x83\x13\x17\x40\xee\x88\x62\x65\x5b\xd5\x3b\x60\xe9\x7b\x3c\xb8\xc9\xd5\x7f\x36\x02\x25\xaa\x68\xc2\x31\x15\xb7\x30\x65\xeb\x7f\x1d\x48\x79\xb1\xcf\x39\xe2\x42\x80\x16\xd3\xf5\x93\x23\xfc\x4c\x97\xc9\x5a\x37\x6c\x7c\x22\xd8\x4a\xcd\xd2\x8e\x36\x83\x39\x91\x90\x10\xc8\xf1\xc9\x35\x7e\x3f\xb8\xd3\x81\xc6\x20\x64\x1a\xb6\x50\xc2\x21\xa4\x78\xdc\xd0\x2f\x3b\x64\x93\x74\xf0\x96\x90\xf1\xef\xfb\x09\x5a\x34\x40\x96\xf0\x36\x12\xc1\xa3\x74\x8c\x93\x7e\x41\xde\x77\x8b\xec\x86\xd9\xd2\x0f\x3f\x2d\xd1\xcc\x40\xa2\x89\x66\x48\x1e\x20\xb3\x9c\x23\x59\x73\xa9\x44\x73\xbc\x24\x79\x90\x56\x37\xb3\xc6\x29\x7e\xa3\x0f\xf1\x29\x39\xef\x7e\x5c\x28\x32\x70\x35\xac\xda\xb8\xc8\x75\x66\xfc\x9b\x4c\x39\x47\x8e\x1b\x6f\x9b\x4d\x02\x54\x22\x33\xef\x61\xba\x9e\x29\x84\xef\x4e\x4b\x33\x47\x76\x97\x6a\xcb\x7e\x5f\xfd\x15\xa6\x9e\x42\x43\x5b\x66\x5a\x8a\x88\x0d\xf7\x16\xb9\x3f\x51\x65\x2b\x66\x6a\x8b\xd1\x38\x52\xa2\xd6\x46\x11\xfa\xfc\x9a\x1c\x74\x9e\x8f\x97\x0b\x02\x4f\x64\xc6\xf5\x68\xd3\x4b\x2d\xff\xa4\x37\x1e\x8b\x3f\xbf\x44\xbe\x61\x46\xa1\x84\x3d\x08\x27\x4c\x81\x20\x77\x89\x08\xea\x67\x40\x5e\x6c\x08\x51\x5f\x34\x5a\x8c\x96\x68\xcd\xd7\xf7\x89\xc2\x1c\xd3\x32\x00\xaf\x52\xcb\xd3\x60\x5b\x2a\x3a\x47\x7e\x6b\x30\x33\xa1\x62\x29\x7f\x4a\xb9\xe1\x2d\xe7\x14\x23\x0e\x0e\x18\x47\xe1\x79\xfc\x15\x55\xd0\xb1\xfc\x25\x71\x63\x75\x33\x1c\x23\x2b\xaf\x5c\xd9\xed\x47\x77\x60\x0e\x3b\x0f\x1e\xd2\xc0\xdc\x64\x05\x89\xfc\x78\xd6\x5c\x2c\x26\x43\xa9", 0 }, + /* Anchor: 10 AddTrust Class 1 CA Root.crt serial: #{a.serial.to_s} + C=SE,O=AddTrust AB,OU=AddTrust TTP Network,CN=AddTrust Class 1 CA Root + */ + { 1052, "\x30\x82\x04\x18\x30\x82\x03\x00\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x65\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1d\x30\x1b\x06\x03\x55\x04\x0b\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x41\x64\x64\x54\x72\x75\x73\x74\x20\x43\x6c\x61\x73\x73\x20\x31\x20\x43\x41\x20\x52\x6f\x6f\x74\x30\x1e\x17\x0d\x30\x30\x30\x35\x33\x30\x31\x30\x33\x38\x33\x31\x5a\x17\x0d\x32\x30\x30\x35\x33\x30\x31\x30\x33\x38\x33\x31\x5a\x30\x65\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1d\x30\x1b\x06\x03\x55\x04\x0b\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x41\x64\x64\x54\x72\x75\x73\x74\x20\x43\x6c\x61\x73\x73\x20\x31\x20\x43\x41\x20\x52\x6f\x6f\x74\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\x96\x96\xd4\x21\x49\x60\xe2\x6b\xe8\x41\x07\x0c\xde\xc4\xe0\xdc\x13\x23\xcd\xc1\x35\xc7\xfb\xd6\x4e\x11\x0a\x67\x5e\xf5\x06\x5b\x6b\xa5\x08\x3b\x5b\x29\x16\x3a\xe7\x87\xb2\x34\x06\xc5\xbc\x05\xa5\x03\x7c\x82\xcb\x29\x10\xae\xe1\x88\x81\xbd\xd6\x9e\xd3\xfe\x2d\x56\xc1\x15\xce\xe3\x26\x9d\x15\x2e\x10\xfb\x06\x8f\x30\x04\xde\xa7\xb4\x63\xb4\xff\xb1\x9c\xae\x3c\xaf\x77\xb6\x56\xc5\xb5\xab\xa2\xe9\x69\x3a\x3d\x0e\x33\x79\x32\x3f\x70\x82\x92\x99\x61\x6d\x8d\x30\x08\x8f\x71\x3f\xa6\x48\x57\x19\xf8\x25\xdc\x4b\x66\x5c\xa5\x74\x8f\x98\xae\xc8\xf9\xc0\x06\x22\xe7\xac\x73\xdf\xa5\x2e\xfb\x52\xdc\xb1\x15\x65\x20\xfa\x35\x66\x69\xde\xdf\x2c\xf1\x6e\xbc\x30\xdb\x2c\x24\x12\xdb\xeb\x35\x35\x68\x90\xcb\x00\xb0\x97\x21\x3d\x74\x21\x23\x65\x34\x2b\xbb\x78\x59\xa3\xd6\xe1\x76\x39\x9a\xa4\x49\x8e\x8c\x74\xaf\x6e\xa4\x9a\xa3\xd9\x9b\xd2\x38\x5c\x9b\xa2\x18\xcc\x75\x23\x84\xbe\xeb\xe2\x4d\x33\x71\x8e\x1a\xf0\xc2\xf8\xc7\x1d\xa2\xad\x03\x97\x2c\xf8\xcf\x25\xc6\xf6\xb8\x24\x31\xb1\x63\x5d\x92\x7f\x63\xf0\x25\xc9\x53\x2e\x1f\xbf\x4d\x02\x03\x01\x00\x01\xa3\x81\xd2\x30\x81\xcf\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x95\xb1\xb4\xf0\x94\xb6\xbd\xc7\xda\xd1\x11\x09\x21\xbe\xc1\xaf\x49\xfd\x10\x7b\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x81\x8f\x06\x03\x55\x1d\x23\x04\x81\x87\x30\x81\x84\x80\x14\x95\xb1\xb4\xf0\x94\xb6\xbd\xc7\xda\xd1\x11\x09\x21\xbe\xc1\xaf\x49\xfd\x10\x7b\xa1\x69\xa4\x67\x30\x65\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1d\x30\x1b\x06\x03\x55\x04\x0b\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x41\x64\x64\x54\x72\x75\x73\x74\x20\x43\x6c\x61\x73\x73\x20\x31\x20\x43\x41\x20\x52\x6f\x6f\x74\x82\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x2c\x6d\x64\x1b\x1f\xcd\x0d\xdd\xb9\x01\xfa\x96\x63\x34\x32\x48\x47\x99\xae\x97\xed\xfd\x72\x16\xa6\x73\x47\x5a\xf4\xeb\xdd\xe9\xf5\xd6\xfb\x45\xcc\x29\x89\x44\x5d\xbf\x46\x39\x3d\xe8\xee\xbc\x4d\x54\x86\x1e\x1d\x6c\xe3\x17\x27\x43\xe1\x89\x56\x2b\xa9\x6f\x72\x4e\x49\x33\xe3\x72\x7c\x2a\x23\x9a\xbc\x3e\xff\x28\x2a\xed\xa3\xff\x1c\x23\xba\x43\x57\x09\x67\x4d\x4b\x62\x06\x2d\xf8\xff\x6c\x9d\x60\x1e\xd8\x1c\x4b\x7d\xb5\x31\x2f\xd9\xd0\x7c\x5d\xf8\xde\x6b\x83\x18\x78\x37\x57\x2f\xe8\x33\x07\x67\xdf\x1e\xc7\x6b\x2a\x95\x76\xae\x8f\x57\xa3\xf0\xf4\x52\xb4\xa9\x53\x08\xcf\xe0\x4f\xd3\x7a\x53\x8b\xfd\xbb\x1c\x56\x36\xf2\xfe\xb2\xb6\xe5\x76\xbb\xd5\x22\x65\xa7\x3f\xfe\xd1\x66\xad\x0b\xbc\x6b\x99\x86\xef\x3f\x7d\xf3\x18\x32\xca\x7b\xc6\xe3\xab\x64\x46\x95\xf8\x26\x69\xd9\x55\x83\x7b\x2c\x96\x07\xff\x59\x2c\x44\xa3\xc6\xe5\xe9\xa9\xdc\xa1\x63\x80\x5a\x21\x5e\x21\xcf\x53\x54\xf0\xba\x6f\x89\xdb\xa8\xaa\x95\xcf\x8b\xe3\x71\xcc\x1e\x1b\x20\x44\x08\xc0\x7a\xb6\x40\xfd\xc4\xe4\x35\xe1\x1d\x16\x1c\xd0\xbc\x2b\x8e\xd6\x71\xd9", 0 }, + /* Anchor: 11 AddTrust External CA Root.crt serial: #{a.serial.to_s} + C=SE,O=AddTrust AB,OU=AddTrust External TTP Network,CN=AddTrust External CA Root + */ + { 1082, "\x30\x82\x04\x36\x30\x82\x03\x1e\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x6f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x26\x30\x24\x06\x03\x55\x04\x0b\x13\x1d\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6e\x61\x6c\x20\x54\x54\x50\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6e\x61\x6c\x20\x43\x41\x20\x52\x6f\x6f\x74\x30\x1e\x17\x0d\x30\x30\x30\x35\x33\x30\x31\x30\x34\x38\x33\x38\x5a\x17\x0d\x32\x30\x30\x35\x33\x30\x31\x30\x34\x38\x33\x38\x5a\x30\x6f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x26\x30\x24\x06\x03\x55\x04\x0b\x13\x1d\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6e\x61\x6c\x20\x54\x54\x50\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6e\x61\x6c\x20\x43\x41\x20\x52\x6f\x6f\x74\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xb7\xf7\x1a\x33\xe6\xf2\x00\x04\x2d\x39\xe0\x4e\x5b\xed\x1f\xbc\x6c\x0f\xcd\xb5\xfa\x23\xb6\xce\xde\x9b\x11\x33\x97\xa4\x29\x4c\x7d\x93\x9f\xbd\x4a\xbc\x93\xed\x03\x1a\xe3\x8f\xcf\xe5\x6d\x50\x5a\xd6\x97\x29\x94\x5a\x80\xb0\x49\x7a\xdb\x2e\x95\xfd\xb8\xca\xbf\x37\x38\x2d\x1e\x3e\x91\x41\xad\x70\x56\xc7\xf0\x4f\x3f\xe8\x32\x9e\x74\xca\xc8\x90\x54\xe9\xc6\x5f\x0f\x78\x9d\x9a\x40\x3c\x0e\xac\x61\xaa\x5e\x14\x8f\x9e\x87\xa1\x6a\x50\xdc\xd7\x9a\x4e\xaf\x05\xb3\xa6\x71\x94\x9c\x71\xb3\x50\x60\x0a\xc7\x13\x9d\x38\x07\x86\x02\xa8\xe9\xa8\x69\x26\x18\x90\xab\x4c\xb0\x4f\x23\xab\x3a\x4f\x84\xd8\xdf\xce\x9f\xe1\x69\x6f\xbb\xd7\x42\xd7\x6b\x44\xe4\xc7\xad\xee\x6d\x41\x5f\x72\x5a\x71\x08\x37\xb3\x79\x65\xa4\x59\xa0\x94\x37\xf7\x00\x2f\x0d\xc2\x92\x72\xda\xd0\x38\x72\xdb\x14\xa8\x45\xc4\x5d\x2a\x7d\xb7\xb4\xd6\xc4\xee\xac\xcd\x13\x44\xb7\xc9\x2b\xdd\x43\x00\x25\xfa\x61\xb9\x69\x6a\x58\x23\x11\xb7\xa7\x33\x8f\x56\x75\x59\xf5\xcd\x29\xd7\x46\xb7\x0a\x2b\x65\xb6\xd3\x42\x6f\x15\xb2\xb8\x7b\xfb\xef\xe9\x5d\x53\xd5\x34\x5a\x27\x02\x03\x01\x00\x01\xa3\x81\xdc\x30\x81\xd9\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xad\xbd\x98\x7a\x34\xb4\x26\xf7\xfa\xc4\x26\x54\xef\x03\xbd\xe0\x24\xcb\x54\x1a\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x81\x99\x06\x03\x55\x1d\x23\x04\x81\x91\x30\x81\x8e\x80\x14\xad\xbd\x98\x7a\x34\xb4\x26\xf7\xfa\xc4\x26\x54\xef\x03\xbd\xe0\x24\xcb\x54\x1a\xa1\x73\xa4\x71\x30\x6f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x26\x30\x24\x06\x03\x55\x04\x0b\x13\x1d\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6e\x61\x6c\x20\x54\x54\x50\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6e\x61\x6c\x20\x43\x41\x20\x52\x6f\x6f\x74\x82\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xb0\x9b\xe0\x85\x25\xc2\xd6\x23\xe2\x0f\x96\x06\x92\x9d\x41\x98\x9c\xd9\x84\x79\x81\xd9\x1e\x5b\x14\x07\x23\x36\x65\x8f\xb0\xd8\x77\xbb\xac\x41\x6c\x47\x60\x83\x51\xb0\xf9\x32\x3d\xe7\xfc\xf6\x26\x13\xc7\x80\x16\xa5\xbf\x5a\xfc\x87\xcf\x78\x79\x89\x21\x9a\xe2\x4c\x07\x0a\x86\x35\xbc\xf2\xde\x51\xc4\xd2\x96\xb7\xdc\x7e\x4e\xee\x70\xfd\x1c\x39\xeb\x0c\x02\x51\x14\x2d\x8e\xbd\x16\xe0\xc1\xdf\x46\x75\xe7\x24\xad\xec\xf4\x42\xb4\x85\x93\x70\x10\x67\xba\x9d\x06\x35\x4a\x18\xd3\x2b\x7a\xcc\x51\x42\xa1\x7a\x63\xd1\xe6\xbb\xa1\xc5\x2b\xc2\x36\xbe\x13\x0d\xe6\xbd\x63\x7e\x79\x7b\xa7\x09\x0d\x40\xab\x6a\xdd\x8f\x8a\xc3\xf6\xf6\x8c\x1a\x42\x05\x51\xd4\x45\xf5\x9f\xa7\x62\x21\x68\x15\x20\x43\x3c\x99\xe7\x7c\xbd\x24\xd8\xa9\x91\x17\x73\x88\x3f\x56\x1b\x31\x38\x18\xb4\x71\x0f\x9a\xcd\xc8\x0e\x9e\x8e\x2e\x1b\xe1\x8c\x98\x83\xcb\x1f\x31\xf1\x44\x4c\xc6\x04\x73\x49\x76\x60\x0f\xc7\xf8\xbd\x17\x80\x6b\x2e\xe9\xcc\x4c\x0e\x5a\x9a\x79\x0f\x20\x0a\x2e\xd5\x9e\x63\x26\x1e\x55\x92\x94\xd8\x82\x17\x5a\x7b\xd0\xbc\xc7\x8f\x4e\x86\x04", 0 }, + /* Anchor: 12 AddTrust Public CA Root.crt serial: #{a.serial.to_s} + C=SE,O=AddTrust AB,OU=AddTrust TTP Network,CN=AddTrust Public CA Root + */ + { 1049, "\x30\x82\x04\x15\x30\x82\x02\xfd\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x64\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1d\x30\x1b\x06\x03\x55\x04\x0b\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x20\x30\x1e\x06\x03\x55\x04\x03\x13\x17\x41\x64\x64\x54\x72\x75\x73\x74\x20\x50\x75\x62\x6c\x69\x63\x20\x43\x41\x20\x52\x6f\x6f\x74\x30\x1e\x17\x0d\x30\x30\x30\x35\x33\x30\x31\x30\x34\x31\x35\x30\x5a\x17\x0d\x32\x30\x30\x35\x33\x30\x31\x30\x34\x31\x35\x30\x5a\x30\x64\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1d\x30\x1b\x06\x03\x55\x04\x0b\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x20\x30\x1e\x06\x03\x55\x04\x03\x13\x17\x41\x64\x64\x54\x72\x75\x73\x74\x20\x50\x75\x62\x6c\x69\x63\x20\x43\x41\x20\x52\x6f\x6f\x74\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xe9\x1a\x30\x8f\x83\x88\x14\xc1\x20\xd8\x3c\x9b\x8f\x1b\x7e\x03\x74\xbb\xda\x69\xd3\x46\xa5\xf8\x8e\xc2\x0c\x11\x90\x51\xa5\x2f\x66\x54\x40\x55\xea\xdb\x1f\x4a\x56\xee\x9f\x23\x6e\xf4\x39\xcb\xa1\xb9\x6f\xf2\x7e\xf9\x5d\x87\x26\x61\x9e\x1c\xf8\xe2\xec\xa6\x81\xf8\x21\xc5\x24\xcc\x11\x0c\x3f\xdb\x26\x72\x7a\xc7\x01\x97\x07\x17\xf9\xd7\x18\x2c\x30\x7d\x0e\x7a\x1e\x62\x1e\xc6\x4b\xc0\xfd\x7d\x62\x77\xd3\x44\x1e\x27\xf6\x3f\x4b\x44\xb3\xb7\x38\xd9\x39\x1f\x60\xd5\x51\x92\x73\x03\xb4\x00\x69\xe3\xf3\x14\x4e\xee\xd1\xdc\x09\xcf\x77\x34\x46\x50\xb0\xf8\x11\xf2\xfe\x38\x79\xf7\x07\x39\xfe\x51\x92\x97\x0b\x5b\x08\x5f\x34\x86\x01\xad\x88\x97\xeb\x66\xcd\x5e\xd1\xff\xdc\x7d\xf2\x84\xda\xba\x77\xad\xdc\x80\x08\xc7\xa7\x87\xd6\x55\x9f\x97\x6a\xe8\xc8\x11\x64\xba\xe7\x19\x29\x3f\x11\xb3\x78\x90\x84\x20\x52\x5b\x11\xef\x78\xd0\x83\xf6\xd5\x48\x90\xd0\x30\x1c\xcf\x80\xf9\x60\xfe\x79\xe4\x88\xf2\xdd\x00\xeb\x94\x45\xeb\x65\x94\x69\x40\xba\xc0\xd5\xb4\xb8\xba\x7d\x04\x11\xa8\xeb\x31\x05\x96\x94\x4e\x58\x21\x8e\x9f\xd0\x60\xfd\x02\x03\x01\x00\x01\xa3\x81\xd1\x30\x81\xce\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x81\x3e\x37\xd8\x92\xb0\x1f\x77\x9f\x5c\xb4\xab\x73\xaa\xe7\xf6\x34\x60\x2f\xfa\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x81\x8e\x06\x03\x55\x1d\x23\x04\x81\x86\x30\x81\x83\x80\x14\x81\x3e\x37\xd8\x92\xb0\x1f\x77\x9f\x5c\xb4\xab\x73\xaa\xe7\xf6\x34\x60\x2f\xfa\xa1\x68\xa4\x66\x30\x64\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1d\x30\x1b\x06\x03\x55\x04\x0b\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x20\x30\x1e\x06\x03\x55\x04\x03\x13\x17\x41\x64\x64\x54\x72\x75\x73\x74\x20\x50\x75\x62\x6c\x69\x63\x20\x43\x41\x20\x52\x6f\x6f\x74\x82\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x03\xf7\x15\x4a\xf8\x24\xda\x23\x56\x16\x93\x76\xdd\x36\x28\xb9\xae\x1b\xb8\xc3\xf1\x64\xba\x20\x18\x78\x95\x29\x27\x57\x05\xbc\x7c\x2a\xf4\xb9\x51\x55\xda\x87\x02\xde\x0f\x16\x17\x31\xf8\xaa\x79\x2e\x09\x13\xbb\xaf\xb2\x20\x19\x12\xe5\x93\xf9\x4b\xf9\x83\xe8\x44\xd5\xb2\x41\x25\xbf\x88\x75\x6f\xff\x10\xfc\x4a\x54\xd0\x5f\xf0\xfa\xef\x36\x73\x7d\x1b\x36\x45\xc6\x21\x6d\xb4\x15\xb8\x4e\xcf\x9c\x5c\xa5\x3d\x5a\x00\x8e\x06\xe3\x3c\x6b\x32\x7b\xf2\x9f\xf0\xb6\xfd\xdf\xf0\x28\x18\x48\xf0\xc6\xbc\xd0\xbf\x34\x80\x96\xc2\x4a\xb1\x6d\x8e\xc7\x90\x45\xde\x2f\x67\xac\x45\x04\xa3\x7a\xdc\x55\x92\xc9\x47\x66\xd8\x1a\x8c\xc7\xed\x9c\x4e\x9a\xe0\x12\xbb\xb5\x6a\x4c\x84\xe1\xe1\x22\x0d\x87\x00\x64\xfe\x8c\x7d\x62\x39\x65\xa6\xef\x42\xb6\x80\x25\x12\x61\x01\xa8\x24\x13\x70\x00\x11\x26\x5f\xfa\x35\x50\xc5\x48\xcc\x06\x47\xe8\x27\xd8\x70\x8d\x5f\x64\xe6\xa1\x44\x26\x5e\x22\xec\x92\xcd\xff\x42\x9a\x44\x21\x6d\x5c\xc5\xe3\x22\x1d\x5f\x47\x12\xe7\xce\x5f\x5d\xfa\xd8\xaa\xb1\x33\x2d\xd9\x76\xf2\x4e\x3a\x33\x0c\x2b\xb3\x2d\x90\x06", 0 }, + /* Anchor: 13 AddTrust Qualified CA Root.crt serial: #{a.serial.to_s} + C=SE,O=AddTrust AB,OU=AddTrust TTP Network,CN=AddTrust Qualified CA Root + */ + { 1058, "\x30\x82\x04\x1e\x30\x82\x03\x06\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x67\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1d\x30\x1b\x06\x03\x55\x04\x0b\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1a\x41\x64\x64\x54\x72\x75\x73\x74\x20\x51\x75\x61\x6c\x69\x66\x69\x65\x64\x20\x43\x41\x20\x52\x6f\x6f\x74\x30\x1e\x17\x0d\x30\x30\x30\x35\x33\x30\x31\x30\x34\x34\x35\x30\x5a\x17\x0d\x32\x30\x30\x35\x33\x30\x31\x30\x34\x34\x35\x30\x5a\x30\x67\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1d\x30\x1b\x06\x03\x55\x04\x0b\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1a\x41\x64\x64\x54\x72\x75\x73\x74\x20\x51\x75\x61\x6c\x69\x66\x69\x65\x64\x20\x43\x41\x20\x52\x6f\x6f\x74\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xe4\x1e\x9a\xfe\xdc\x09\x5a\x87\xa4\x9f\x47\xbe\x11\x5f\xaf\x84\x34\xdb\x62\x3c\x79\x78\xb7\xe9\x30\xb5\xec\x0c\x1c\x2a\xc4\x16\xff\xe0\xec\x71\xeb\x8a\xf5\x11\x6e\xed\x4f\x0d\x91\xd2\x12\x18\x2d\x49\x15\x01\xc2\xa4\x22\x13\xc7\x11\x64\xff\x22\x12\x9a\xb9\x8e\x5c\x2f\x08\xcf\x71\x6a\xb3\x67\x01\x59\xf1\x5d\x46\xf3\xb0\x78\xa5\xf6\x0e\x42\x7a\xe3\x7f\x1b\xcc\xd0\xf0\xb7\x28\xfd\x2a\xea\x9e\xb3\xb0\xb9\x04\xaa\xfd\xf6\xc7\xb4\xb1\xb8\x2a\xa0\xfb\x58\xf1\x19\xa0\x6f\x70\x25\x7e\x3e\x69\x4a\x7f\x0f\x22\xd8\xef\xad\x08\x11\x9a\x29\x99\xe1\xaa\x44\x45\x9a\x12\x5e\x3e\x9d\x6d\x52\xfc\xe7\xa0\x3d\x68\x2f\xf0\x4b\x70\x7c\x13\x38\xad\xbc\x15\x25\xf1\xd6\xce\xab\xa2\xc0\x31\xd6\x2f\x9f\xe0\xff\x14\x59\xfc\x84\x93\xd9\x87\x7c\x4c\x54\x13\xeb\x9f\xd1\x2d\x11\xf8\x18\x3a\x3a\xde\x25\xd9\xf7\xd3\x40\xed\xa4\x06\x12\xc4\x3b\xe1\x91\xc1\x56\x35\xf0\x14\xdc\x65\x36\x09\x6e\xab\xa4\x07\xc7\x35\xd1\xc2\x03\x33\x36\x5b\x75\x26\x6d\x42\xf1\x12\x6b\x43\x6f\x4b\x71\x94\xfa\x34\x1d\xed\x13\x6e\xca\x80\x7f\x98\x2f\x6c\xb9\x65\xd8\xe9\x02\x03\x01\x00\x01\xa3\x81\xd4\x30\x81\xd1\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x39\x95\x8b\x62\x8b\x5c\xc9\xd4\x80\xba\x58\x0f\x97\x3f\x15\x08\x43\xcc\x98\xa7\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x81\x91\x06\x03\x55\x1d\x23\x04\x81\x89\x30\x81\x86\x80\x14\x39\x95\x8b\x62\x8b\x5c\xc9\xd4\x80\xba\x58\x0f\x97\x3f\x15\x08\x43\xcc\x98\xa7\xa1\x6b\xa4\x69\x30\x67\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1d\x30\x1b\x06\x03\x55\x04\x0b\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1a\x41\x64\x64\x54\x72\x75\x73\x74\x20\x51\x75\x61\x6c\x69\x66\x69\x65\x64\x20\x43\x41\x20\x52\x6f\x6f\x74\x82\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x19\xab\x75\xea\xf8\x8b\x65\x61\x95\x13\xba\x69\x04\xef\x86\xca\x13\xa0\xc7\xaa\x4f\x64\x1b\x3f\x18\xf6\xa8\x2d\x2c\x55\x8f\x05\xb7\x30\xea\x42\x6a\x1d\xc0\x25\x51\x2d\xa7\xbf\x0c\xb3\xed\xef\x08\x7f\x6c\x3c\x46\x1a\xea\x18\x43\xdf\x76\xcc\xf9\x66\x86\x9c\x2c\x68\xf5\xe9\x17\xf8\x31\xb3\x18\xc4\xd6\x48\x7d\x23\x4c\x68\xc1\x7e\xbb\x01\x14\x6f\xc5\xd9\x6e\xde\xbb\x04\x42\x6a\xf8\xf6\x5c\x7d\xe5\xda\xfa\x87\xeb\x0d\x35\x52\x67\xd0\x9e\x97\x76\x05\x93\x3f\x95\xc7\x01\xe6\x69\x55\x38\x7f\x10\x61\x99\xc9\xe3\x5f\xa6\xca\x3e\x82\x63\x48\xaa\xe2\x08\x48\x3e\xaa\xf2\xb2\x85\x62\xa6\xb4\xa7\xd9\xbd\x37\x9c\x68\xb5\x2d\x56\x7d\xb0\xb7\x3f\xa0\xb1\x07\xd6\xe9\x4f\xdc\xde\x45\x71\x30\x32\x7f\x1b\x2e\x09\xf9\xbf\x52\xa1\xee\xc2\x80\x3e\x06\x5c\x2e\x55\x40\xc1\x1b\xf5\x70\x45\xb0\xdc\x5d\xfa\xf6\x72\x5a\x77\xd2\x63\xcd\xcf\x58\x89\x00\x42\x63\x3f\x79\x39\xd0\x44\xb0\x82\x6e\x41\x19\xe8\xdd\xe0\xc1\x88\x5a\xd1\x1e\x71\x93\x1f\x24\x30\x74\xe5\x1e\xa8\xde\x3c\x27\x37\x7f\x83\xae\x9e\x77\xcf\xf0\x30\xb1\xff\x4b\x99\xe8\xc6\xa1", 0 }, + /* Anchor: 14 AffirmTrust-root-1.der serial: #{a.serial.to_s} + C=US,O=AffirmTrust,CN=AffirmTrust Premium ECC + */ + { 514, "\x30\x82\x01\xfe\x30\x82\x01\x85\xa0\x03\x02\x01\x02\x02\x08\x74\x97\x25\x8a\xc7\x3f\x7a\x54\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x03\x30\x45\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x0c\x0b\x41\x66\x66\x69\x72\x6d\x54\x72\x75\x73\x74\x31\x20\x30\x1e\x06\x03\x55\x04\x03\x0c\x17\x41\x66\x66\x69\x72\x6d\x54\x72\x75\x73\x74\x20\x50\x72\x65\x6d\x69\x75\x6d\x20\x45\x43\x43\x30\x1e\x17\x0d\x31\x30\x30\x31\x32\x39\x31\x34\x32\x30\x32\x34\x5a\x17\x0d\x34\x30\x31\x32\x33\x31\x31\x34\x32\x30\x32\x34\x5a\x30\x45\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x0c\x0b\x41\x66\x66\x69\x72\x6d\x54\x72\x75\x73\x74\x31\x20\x30\x1e\x06\x03\x55\x04\x03\x0c\x17\x41\x66\x66\x69\x72\x6d\x54\x72\x75\x73\x74\x20\x50\x72\x65\x6d\x69\x75\x6d\x20\x45\x43\x43\x30\x76\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04\x00\x22\x03\x62\x00\x04\x0d\x30\x5e\x1b\x15\x9d\x03\xd0\xa1\x79\x35\xb7\x3a\x3c\x92\x7a\xca\x15\x1c\xcd\x62\xf3\x9c\x26\x5c\x07\x3d\xe5\x54\xfa\xa3\xd6\xcc\x12\xea\xf4\x14\x5f\xe8\x8e\x19\xab\x2f\x2e\x48\xe6\xac\x18\x43\x78\xac\xd0\x37\xc3\xbd\xb2\xcd\x2c\xe6\x47\xe2\x1a\xe6\x63\xb8\x3d\x2e\x2f\x78\xc4\x4f\xdb\xf4\x0f\xa4\x68\x4c\x55\x72\x6b\x95\x1d\x4e\x18\x42\x95\x78\xcc\x37\x3c\x91\xe2\x9b\x65\x2b\x29\xa3\x42\x30\x40\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x9a\xaf\x29\x7a\xc0\x11\x35\x35\x26\x51\x30\x00\xc3\x6a\xfe\x40\xd5\xae\xd6\x3c\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x03\x03\x67\x00\x30\x64\x02\x30\x17\x09\xf3\x87\x88\x50\x5a\xaf\xc8\xc0\x42\xbf\x47\x5f\xf5\x6c\x6a\x86\xe0\xc4\x27\x74\xe4\x38\x53\xd7\x05\x7f\x1b\x34\xe3\xc6\x2f\xb3\xca\x09\x3c\x37\x9d\xd7\xe7\xb8\x46\xf1\xfd\xa1\xe2\x71\x02\x30\x42\x59\x87\x43\xd4\x51\xdf\xba\xd3\x09\x32\x5a\xce\x88\x7e\x57\x3d\x9c\x5f\x42\x6b\xf5\x07\x2d\xb5\xf0\x82\x93\xf9\x59\x6f\xae\x64\xfa\x58\xe5\x8b\x1e\xe3\x63\xbe\xb5\x81\xcd\x6f\x02\x8c\x79", 0 }, + /* Anchor: 15 AffirmTrust-root-2.der serial: #{a.serial.to_s} + C=US,O=AffirmTrust,CN=AffirmTrust Premium + */ + { 1354, "\x30\x82\x05\x46\x30\x82\x03\x2e\xa0\x03\x02\x01\x02\x02\x08\x6d\x8c\x14\x46\xb1\xa6\x0a\xee\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0c\x05\x00\x30\x41\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x0c\x0b\x41\x66\x66\x69\x72\x6d\x54\x72\x75\x73\x74\x31\x1c\x30\x1a\x06\x03\x55\x04\x03\x0c\x13\x41\x66\x66\x69\x72\x6d\x54\x72\x75\x73\x74\x20\x50\x72\x65\x6d\x69\x75\x6d\x30\x1e\x17\x0d\x31\x30\x30\x31\x32\x39\x31\x34\x31\x30\x33\x36\x5a\x17\x0d\x34\x30\x31\x32\x33\x31\x31\x34\x31\x30\x33\x36\x5a\x30\x41\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x0c\x0b\x41\x66\x66\x69\x72\x6d\x54\x72\x75\x73\x74\x31\x1c\x30\x1a\x06\x03\x55\x04\x03\x0c\x13\x41\x66\x66\x69\x72\x6d\x54\x72\x75\x73\x74\x20\x50\x72\x65\x6d\x69\x75\x6d\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\xc4\x12\xdf\xa9\x5f\xfe\x41\xdd\xdd\xf5\x9f\x8a\xe3\xf6\xac\xe1\x3c\x78\x9a\xbc\xd8\xf0\x7f\x7a\xa0\x33\x2a\xdc\x8d\x20\x5b\xae\x2d\x6f\xe7\x93\xd9\x36\x70\x6a\x68\xcf\x8e\x51\xa3\x85\x5b\x67\x04\xa0\x10\x24\x6f\x5d\x28\x82\xc1\x97\x57\xd8\x48\x29\x13\xb6\xe1\xbe\x91\x4d\xdf\x85\x0c\x53\x18\x9a\x1e\x24\xa2\x4f\x8f\xf0\xa2\x85\x0b\xcb\xf4\x29\x7f\xd2\xa4\x58\xee\x26\x4d\xc9\xaa\xa8\x7b\x9a\xd9\xfa\x38\xde\x44\x57\x15\xe5\xf8\x8c\xc8\xd9\x48\xe2\x0d\x16\x27\x1d\x1e\xc8\x83\x85\x25\xb7\xba\xaa\x55\x41\xcc\x03\x22\x4b\x2d\x91\x8d\x8b\xe6\x89\xaf\x66\xc7\xe9\xff\x2b\xe9\x3c\xac\xda\xd2\xb3\xc3\xe1\x68\x9c\x89\xf8\x7a\x00\x56\xde\xf4\x55\x95\x6c\xfb\xba\x64\xdd\x62\x8b\xdf\x0b\x77\x32\xeb\x62\xcc\x26\x9a\x9b\xbb\xaa\x62\x83\x4c\xb4\x06\x7a\x30\xc8\x29\xbf\xed\x06\x4d\x97\xb9\x1c\xc4\x31\x2b\xd5\x5f\xbc\x53\x12\x17\x9c\x99\x57\x29\x66\x77\x61\x21\x31\x07\x2e\x25\x49\x9d\x18\xf2\xee\xf3\x2b\x71\x8c\xb5\xba\x39\x07\x49\x77\xfc\xef\x2e\x92\x90\x05\x8d\x2d\x2f\x77\x7b\xef\x43\xbf\x35\xbb\x9a\xd8\xf9\x73\xa7\x2c\xf2\xd0\x57\xee\x28\x4e\x26\x5f\x8f\x90\x68\x09\x2f\xb8\xf8\xdc\x06\xe9\x2e\x9a\x3e\x51\xa7\xd1\x22\xc4\x0a\xa7\x38\x48\x6c\xb3\xf9\xff\x7d\xab\x86\x57\xe3\xba\xd6\x85\x78\x77\xba\x43\xea\x48\x7f\xf6\xd8\xbe\x23\x6d\x1e\xbf\xd1\x36\x6c\x58\x5c\xf1\xee\xa4\x19\x54\x1a\xf5\x03\xd2\x76\xe6\xe1\x8c\xbd\x3c\xb3\xd3\x48\x4b\xe2\xc8\xf8\x7f\x92\xa8\x76\x46\x9c\x42\x65\x3e\xa4\x1e\xc1\x07\x03\x5a\x46\x2d\xb8\x97\xf3\xb7\xd5\xb2\x55\x21\xef\xba\xdc\x4c\x00\x97\xfb\x14\x95\x27\x33\xbf\xe8\x43\x47\x46\xd2\x08\x99\x16\x60\x3b\x9a\x7e\xd2\xe6\xed\x38\xea\xec\x01\x1e\x3c\x48\x56\x49\x09\xc7\x4c\x37\x00\x9e\x88\x0e\xc0\x73\xe1\x6f\x66\xe9\x72\x47\x30\x3e\x10\xe5\x0b\x03\xc9\x9a\x42\x00\x6c\xc5\x94\x7e\x61\xc4\x8a\xdf\x7f\x82\x1a\x0b\x59\xc4\x59\x32\x77\xb3\xbc\x60\x69\x56\x39\xfd\xb4\x06\x7b\x2c\xd6\x64\x36\xd9\xbd\x48\xed\x84\x1f\x7e\xa5\x22\x8f\x2a\xb8\x42\xf4\x82\xb7\xd4\x53\x90\x78\x4e\x2d\x1a\xfd\x81\x6f\x44\xd7\x3b\x01\x74\x96\x42\xe0\x00\xe2\x2e\x6b\xea\xc5\xee\x72\xac\xbb\xbf\xfe\xea\xaa\xa8\xf8\xdc\xf6\xb2\x79\x8a\xb6\x67\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x9d\xc0\x67\xa6\x0c\x22\xd9\x26\xf5\x45\xab\xa6\x65\x52\x11\x27\xd8\x45\xac\x63\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0c\x05\x00\x03\x82\x02\x01\x00\xb3\x57\x4d\x10\x62\x4e\x3a\xe4\xac\xea\xb8\x1c\xaf\x32\x23\xc8\xb3\x49\x5a\x51\x9c\x76\x28\x8d\x79\xaa\x57\x46\x17\xd5\xf5\x52\xf6\xb7\x44\xe8\x08\x44\xbf\x18\x84\xd2\x0b\x80\xcd\xc5\x12\xfd\x00\x55\x05\x61\x87\x41\xdc\xb5\x24\x9e\x3c\xc4\xd8\xc8\xfb\x70\x9e\x2f\x78\x96\x83\x20\x36\xde\x7c\x0f\x69\x13\x88\xa5\x75\x36\x98\x08\xa6\xc6\xdf\xac\xce\xe3\x58\xd6\xb7\x3e\xde\xba\xf3\xeb\x34\x40\xd8\xa2\x81\xf5\x78\x3f\x2f\xd5\xa5\xfc\xd9\xa2\xd4\x5e\x04\x0e\x17\xad\xfe\x41\xf0\xe5\xb2\x72\xfa\x44\x82\x33\x42\xe8\x2d\x58\xf7\x56\x8c\x62\x3f\xba\x42\xb0\x9c\x0c\x5c\x7e\x2e\x65\x26\x5c\x53\x4f\x00\xb2\x78\x7e\xa1\x0d\x99\x2d\x8d\xb8\x1d\x8e\xa2\xc4\xb0\xfd\x60\xd0\x30\xa4\x8e\xc8\x04\x62\xa9\xc4\xed\x35\xde\x7a\x97\xed\x0e\x38\x5e\x92\x2f\x93\x70\xa5\xa9\x9c\x6f\xa7\x7d\x13\x1d\x7e\xc6\x08\x48\xb1\x5e\x67\xeb\x51\x08\x25\xe9\xe6\x25\x6b\x52\x29\x91\x9c\xd2\x39\x73\x08\x57\xde\x99\x06\xb4\x5b\x9d\x10\x06\xe1\xc2\x00\xa8\xb8\x1c\x4a\x02\x0a\x14\xd0\xc1\x41\xca\xfb\x8c\x35\x21\x7d\x82\x38\xf2\xa9\x54\x91\x19\x35\x93\x94\x6d\x6a\x3a\xc5\xb2\xd0\xbb\x89\x86\x93\xe8\x9b\xc9\x0f\x3a\xa7\x7a\xb8\xa1\xf0\x78\x46\xfa\xfc\x37\x2f\xe5\x8a\x84\xf3\xdf\xfe\x04\xd9\xa1\x68\xa0\x2f\x24\xe2\x09\x95\x06\xd5\x95\xca\xe1\x24\x96\xeb\x7c\xf6\x93\x05\xbb\xed\x73\xe9\x2d\xd1\x75\x39\xd7\xe7\x24\xdb\xd8\x4e\x5f\x43\x8f\x9e\xd0\x14\x39\xbf\x55\x70\x48\x99\x57\x31\xb4\x9c\xee\x4a\x98\x03\x96\x30\x1f\x60\x06\xee\x1b\x23\xfe\x81\x60\x23\x1a\x47\x62\x85\xa5\xcc\x19\x34\x80\x6f\xb3\xac\x1a\xe3\x9f\xf0\x7b\x48\xad\xd5\x01\xd9\x67\xb6\xa9\x72\x93\xea\x2d\x66\xb5\xb2\xb8\xe4\x3d\x3c\xb2\xef\x4c\x8c\xea\xeb\x07\xbf\xab\x35\x9a\x55\x86\xbc\x18\xa6\xb5\xa8\x5e\xb4\x83\x6c\x6b\x69\x40\xd3\x9f\xdc\xf1\xc3\x69\x6b\xb9\xe1\x6d\x09\xf4\xf1\xaa\x50\x76\x0a\x7a\x7d\x7a\x17\xa1\x55\x96\x42\x99\x31\x09\xdd\x60\x11\x8d\x05\x30\x7e\xe6\x8e\x46\xd1\x9d\x14\xda\xc7\x17\xe4\x05\x96\x8c\xc4\x24\xb5\x1b\xcf\x14\x07\xb2\x40\xf8\xa3\x9e\x41\x86\xbc\x04\xd0\x6b\x96\xc8\x2a\x80\x34\xfd\xbf\xef\x06\xa3\xdd\x58\xc5\x85\x3d\x3e\x8f\xfe\x9e\x29\xe0\xb6\xb8\x09\x68\x19\x1c\x18\x43", 0 }, + /* Anchor: 16 AffirmTrust-root-3.der serial: #{a.serial.to_s} + C=US,O=AffirmTrust,CN=AffirmTrust Networking + */ + { 848, "\x30\x82\x03\x4c\x30\x82\x02\x34\xa0\x03\x02\x01\x02\x02\x08\x7c\x4f\x04\x39\x1c\xd4\x99\x2d\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x44\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x0c\x0b\x41\x66\x66\x69\x72\x6d\x54\x72\x75\x73\x74\x31\x1f\x30\x1d\x06\x03\x55\x04\x03\x0c\x16\x41\x66\x66\x69\x72\x6d\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x69\x6e\x67\x30\x1e\x17\x0d\x31\x30\x30\x31\x32\x39\x31\x34\x30\x38\x32\x34\x5a\x17\x0d\x33\x30\x31\x32\x33\x31\x31\x34\x30\x38\x32\x34\x5a\x30\x44\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x0c\x0b\x41\x66\x66\x69\x72\x6d\x54\x72\x75\x73\x74\x31\x1f\x30\x1d\x06\x03\x55\x04\x03\x0c\x16\x41\x66\x66\x69\x72\x6d\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x69\x6e\x67\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xb4\x84\xcc\x33\x17\x2e\x6b\x94\x6c\x6b\x61\x52\xa0\xeb\xa3\xcf\x79\x94\x4c\xe5\x94\x80\x99\xcb\x55\x64\x44\x65\x8f\x67\x64\xe2\x06\xe3\x5c\x37\x49\xf6\x2f\x9b\x84\x84\x1e\x2d\xf2\x60\x9d\x30\x4e\xcc\x84\x85\xe2\x2c\xcf\x1e\x9e\xfe\x36\xab\x33\x77\x35\x44\xd8\x35\x96\x1a\x3d\x36\xe8\x7a\x0e\xd8\xd5\x47\xa1\x6a\x69\x8b\xd9\xfc\xbb\x3a\xae\x79\x5a\xd5\xf4\xd6\x71\xbb\x9a\x90\x23\x6b\x9a\xb7\x88\x74\x87\x0c\x1e\x5f\xb9\x9e\x2d\xfa\xab\x53\x2b\xdc\xbb\x76\x3e\x93\x4c\x08\x08\x8c\x1e\xa2\x23\x1c\xd4\x6a\xad\x22\xba\x99\x01\x2e\x6d\x65\xcb\xbe\x24\x66\x55\x24\x4b\x40\x44\xb1\x1b\xd7\xe1\xc2\x85\xc0\xde\x10\x3f\x3d\xed\xb8\xfc\xf1\xf1\x23\x53\xdc\xbf\x65\x97\x6f\xd9\xf9\x40\x71\x8d\x7d\xbd\x95\xd4\xce\xbe\xa0\x5e\x27\x23\xde\xfd\xa6\xd0\x26\x0e\x00\x29\xeb\x3c\x46\xf0\x3d\x60\xbf\x3f\x50\xd2\xdc\x26\x41\x51\x9e\x14\x37\x42\x04\xa3\x70\x57\xa8\x1b\x87\xed\x2d\xfa\x7b\xee\x8c\x0a\xe3\xa9\x66\x89\x19\xcb\x41\xf9\xdd\x44\x36\x61\xcf\xe2\x77\x46\xc8\x7d\xf6\xf4\x92\x81\x36\xfd\xdb\x34\xf1\x72\x7e\xf3\x0c\x16\xbd\xb4\x15\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x07\x1f\xd2\xe7\x9c\xda\xc2\x6e\xa2\x40\xb4\xb0\x7a\x50\x10\x50\x74\xc4\xc8\xbd\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x89\x57\xb2\x16\x7a\xa8\xc2\xfd\xd6\xd9\x9b\x9b\x34\xc2\x9c\xb4\x32\x14\x4d\xa7\xa4\xdf\xec\xbe\xa7\xbe\xf8\x43\xdb\x91\x37\xce\xb4\x32\x2e\x50\x55\x1a\x35\x4e\x76\x43\x71\x20\xef\x93\x77\x4e\x15\x70\x2e\x87\xc3\xc1\x1d\x6d\xdc\xcb\xb5\x27\xd4\x2c\x56\xd1\x52\x53\x3a\x44\xd2\x73\xc8\xc4\x1b\x05\x65\x5a\x62\x92\x9c\xee\x41\x8d\x31\xdb\xe7\x34\xea\x59\x21\xd5\x01\x7a\xd7\x64\xb8\x64\x39\xcd\xc9\xed\xaf\xed\x4b\x03\x48\xa7\xa0\x99\x01\x80\xdc\x65\xa3\x36\xae\x65\x59\x48\x4f\x82\x4b\xc8\x65\xf1\x57\x1d\xe5\x59\x2e\x0a\x3f\x6c\xd8\xd1\xf5\xe5\x09\xb4\x6c\x54\x00\x0a\xe0\x15\x4d\x87\x75\x6d\xb7\x58\x96\x5a\xdd\x6d\xd2\x00\xa0\xf4\x9b\x48\xbe\xc3\x37\xa4\xba\x36\xe0\x7c\x87\x85\x97\x1a\x15\xa2\xde\x2e\xa2\x5b\xbd\xaf\x18\xf9\x90\x50\xcd\x70\x59\xf8\x27\x67\x47\xcb\xc7\xa0\x07\x3a\x7d\xd1\x2c\x5d\x6c\x19\x3a\x66\xb5\x7d\xfd\x91\x6f\x82\xb1\xbe\x08\x93\xdb\x14\x47\xf1\xa2\x37\xc7\x45\x9e\x3c\xc7\x77\xaf\x64\xa8\x93\xdf\xf6\x69\x83\x82\x60\xf2\x49\x42\x34\xed\x5a\x00\x54\x85\x1c\x16\x36\x92\x0c\x5c\xfa\xa6\xad\xbf\xdb", 0 }, + /* Anchor: 17 AffirmTrust-root-4.der serial: #{a.serial.to_s} + C=US,O=AffirmTrust,CN=AffirmTrust Commercial + */ + { 848, "\x30\x82\x03\x4c\x30\x82\x02\x34\xa0\x03\x02\x01\x02\x02\x08\x77\x77\x06\x27\x26\xa9\xb1\x7c\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x30\x44\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x0c\x0b\x41\x66\x66\x69\x72\x6d\x54\x72\x75\x73\x74\x31\x1f\x30\x1d\x06\x03\x55\x04\x03\x0c\x16\x41\x66\x66\x69\x72\x6d\x54\x72\x75\x73\x74\x20\x43\x6f\x6d\x6d\x65\x72\x63\x69\x61\x6c\x30\x1e\x17\x0d\x31\x30\x30\x31\x32\x39\x31\x34\x30\x36\x30\x36\x5a\x17\x0d\x33\x30\x31\x32\x33\x31\x31\x34\x30\x36\x30\x36\x5a\x30\x44\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x0c\x0b\x41\x66\x66\x69\x72\x6d\x54\x72\x75\x73\x74\x31\x1f\x30\x1d\x06\x03\x55\x04\x03\x0c\x16\x41\x66\x66\x69\x72\x6d\x54\x72\x75\x73\x74\x20\x43\x6f\x6d\x6d\x65\x72\x63\x69\x61\x6c\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xf6\x1b\x4f\x67\x07\x2b\xa1\x15\xf5\x06\x22\xcb\x1f\x01\xb2\xe3\x73\x45\x06\x44\x49\x2c\xbb\x49\x25\x14\xd6\xce\xc3\xb7\xab\x2c\x4f\xc6\x41\x32\x94\x57\xfa\x12\xa7\x5b\x0e\xe2\x8f\x1f\x1e\x86\x19\xa7\xaa\xb5\x2d\xb9\x5f\x0d\x8a\xc2\xaf\x85\x35\x79\x32\x2d\xbb\x1c\x62\x37\xf2\xb1\x5b\x4a\x3d\xca\xcd\x71\x5f\xe9\x42\xbe\x94\xe8\xc8\xde\xf9\x22\x48\x64\xc6\xe5\xab\xc6\x2b\x6d\xad\x05\xf0\xfa\xd5\x0b\xcf\x9a\xe5\xf0\x50\xa4\x8b\x3b\x47\xa5\x23\x5b\x7a\x7a\xf8\x33\x3f\xb8\xef\x99\x97\xe3\x20\xc1\xd6\x28\x89\xcf\x94\xfb\xb9\x45\xed\xe3\x40\x17\x11\xd4\x74\xf0\x0b\x31\xe2\x2b\x26\x6a\x9b\x4c\x57\xae\xac\x20\x3e\xba\x45\x7a\x05\xf3\xbd\x9b\x69\x15\xae\x7d\x4e\x20\x63\xc4\x35\x76\x3a\x07\x02\xc9\x37\xfd\xc7\x47\xee\xe8\xf1\x76\x1d\x73\x15\xf2\x97\xa4\xb5\xc8\x7a\x79\xd9\x42\xaa\x2b\x7f\x5c\xfe\xce\x26\x4f\xa3\x66\x81\x35\xaf\x44\xba\x54\x1e\x1c\x30\x32\x65\x9d\xe6\x3c\x93\x5e\x50\x4e\x7a\xe3\x3a\xd4\x6e\xcc\x1a\xfb\xf9\xd2\x37\xae\x24\x2a\xab\x57\x03\x22\x28\x0d\x49\x75\x7f\xb7\x28\xda\x75\xbf\x8e\xe3\xdc\x0e\x79\x31\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x9d\x93\xc6\x53\x8b\x5e\xca\xaf\x3f\x9f\x1e\x0f\xe5\x99\x95\xbc\x24\xf6\x94\x8f\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x03\x82\x01\x01\x00\x58\xac\xf4\x04\x0e\xcd\xc0\x0d\xff\x0a\xfd\xd4\xba\x16\x5f\x29\xbd\x7b\x68\x99\x58\x49\xd2\xb4\x1d\x37\x4d\x7f\x27\x7d\x46\x06\x5d\x43\xc6\x86\x2e\x3e\x73\xb2\x26\x7d\x4f\x93\xa9\xb6\xc4\x2a\x9a\xab\x21\x97\x14\xb1\xde\x8c\xd3\xab\x89\x15\xd8\x6b\x24\xd4\xf1\x16\xae\xd8\xa4\x5c\xd4\x7f\x51\x8e\xed\x18\x01\xb1\x93\x63\xbd\xbc\xf8\x61\x80\x9a\x9e\xb1\xce\x42\x70\xe2\xa9\x7d\x06\x25\x7d\x27\xa1\xfe\x6f\xec\xb3\x1e\x24\xda\xe3\x4b\x55\x1a\x00\x3b\x35\xb4\x3b\xd9\xd7\x5d\x30\xfd\x81\x13\x89\xf2\xc2\x06\x2b\xed\x67\xc4\x8e\xc9\x43\xb2\x5c\x6b\x15\x89\x02\xbc\x62\xfc\x4e\xf2\xb5\x33\xaa\xb2\x6f\xd3\x0a\xa2\x50\xe3\xf6\x3b\xe8\x2e\x44\xc2\xdb\x66\x38\xa9\x33\x56\x48\xf1\x6d\x1b\x33\x8d\x0d\x8c\x3f\x60\x37\x9d\xd3\xca\x6d\x7e\x34\x7e\x0d\x9f\x72\x76\x8b\x1b\x9f\x72\xfd\x52\x35\x41\x45\x02\x96\x2f\x1c\xb2\x9a\x73\x49\x21\xb1\x49\x47\x45\x47\xb4\xef\x6a\x34\x11\xc9\x4d\x9a\xcc\x59\xb7\xd6\x02\x9e\x5a\x4e\x65\xb5\x94\xae\x1b\xdf\x29\xb0\x16\xf1\xbf\x00\x9e\x07\x3a\x17\x64\xb5\x04\xb5\x23\x21\x99\x0a\x95\x3b\x97\x7c\xef", 0 }, + /* Anchor: 18 AmericaOnline1.der serial: #{a.serial.to_s} + C=US,O=America Online Inc.,CN=America Online Root Certification Authority 1 + */ + { 936, "\x30\x82\x03\xa4\x30\x82\x02\x8c\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x63\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x41\x6d\x65\x72\x69\x63\x61\x20\x4f\x6e\x6c\x69\x6e\x65\x20\x49\x6e\x63\x2e\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2d\x41\x6d\x65\x72\x69\x63\x61\x20\x4f\x6e\x6c\x69\x6e\x65\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x31\x30\x1e\x17\x0d\x30\x32\x30\x35\x32\x38\x30\x36\x30\x30\x30\x30\x5a\x17\x0d\x33\x37\x31\x31\x31\x39\x32\x30\x34\x33\x30\x30\x5a\x30\x63\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x41\x6d\x65\x72\x69\x63\x61\x20\x4f\x6e\x6c\x69\x6e\x65\x20\x49\x6e\x63\x2e\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2d\x41\x6d\x65\x72\x69\x63\x61\x20\x4f\x6e\x6c\x69\x6e\x65\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x31\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xa8\x2f\xe8\xa4\x69\x06\x03\x47\xc3\xe9\x2a\x98\xff\x19\xa2\x70\x9a\xc6\x50\xb2\x7e\xa5\xdf\x68\x4d\x1b\x7c\x0f\xb6\x97\x68\x7d\x2d\xa6\x8b\x97\xe9\x64\x86\xc9\xa3\xef\xa0\x86\xbf\x60\x65\x9c\x4b\x54\x88\xc2\x48\xc5\x4a\x39\xbf\x14\xe3\x59\x55\xe5\x19\xb4\x74\xc8\xb4\x05\x39\x5c\x16\xa5\xe2\x95\x05\xe0\x12\xae\x59\x8b\xa2\x33\x68\x58\x1c\xa6\xd4\x15\xb7\xd8\x9f\xd7\xdc\x71\xab\x7e\x9a\xbf\x9b\x8e\x33\x0f\x22\xfd\x1f\x2e\xe7\x07\x36\xef\x62\x39\xc5\xdd\xcb\xba\x25\x14\x23\xde\x0c\xc6\x3d\x3c\xce\x82\x08\xe6\x66\x3e\xda\x51\x3b\x16\x3a\xa3\x05\x7f\xa0\xdc\x87\xd5\x9c\xfc\x72\xa9\xa0\x7d\x78\xe4\xb7\x31\x55\x1e\x65\xbb\xd4\x61\xb0\x21\x60\xed\x10\x32\x72\xc5\x92\x25\x1e\xf8\x90\x4a\x18\x78\x47\xdf\x7e\x30\x37\x3e\x50\x1b\xdb\x1c\xd3\x6b\x9a\x86\x53\x07\xb0\xef\xac\x06\x78\xf8\x84\x99\xfe\x21\x8d\x4c\x80\xb6\x0c\x82\xf6\x66\x70\x79\x1a\xd3\x4f\xa3\xcf\xf1\xcf\x46\xb0\x4b\x0f\x3e\xdd\x88\x62\xb8\x8c\xa9\x09\x28\x3b\x7a\xc7\x97\xe1\x1e\xe5\xf4\x9f\xc0\xc0\xae\x24\xa0\xc8\xa1\xd9\x0f\xd6\x7b\x26\x82\x69\x32\x3d\xa7\x02\x03\x01\x00\x01\xa3\x63\x30\x61\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x00\xad\xd9\xa3\xf6\x79\xf6\x6e\x74\xa9\x7f\x33\x3d\x81\x17\xd7\x4c\xcf\x33\xde\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x00\xad\xd9\xa3\xf6\x79\xf6\x6e\x74\xa9\x7f\x33\x3d\x81\x17\xd7\x4c\xcf\x33\xde\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x86\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x7c\x8a\xd1\x1f\x18\x37\x82\xe0\xb8\xb0\xa3\xed\x56\x95\xc8\x62\x61\x9c\x05\xa2\xcd\xc2\x62\x26\x61\xcd\x10\x16\xd7\xcc\xb4\x65\x34\xd0\x11\x8a\xad\xa8\xa9\x05\x66\xef\x74\xf3\x6d\x5f\x9d\x99\xaf\xf6\x8b\xfb\xeb\x52\xb2\x05\x98\xa2\x6f\x2a\xc5\x54\xbd\x25\xbd\x5f\xae\xc8\x86\xea\x46\x2c\xc1\xb3\xbd\xc1\xe9\x49\x70\x18\x16\x97\x08\x13\x8c\x20\xe0\x1b\x2e\x3a\x47\xcb\x1e\xe4\x00\x30\x95\x5b\xf4\x45\xa3\xc0\x1a\xb0\x01\x4e\xab\xbd\xc0\x23\x6e\x63\x3f\x80\x4a\xc5\x07\xed\xdc\xe2\x6f\xc7\xc1\x62\xf1\xe3\x72\xd6\x04\xc8\x74\x67\x0b\xfa\x88\xab\xa1\x01\xc8\x6f\xf0\x14\xaf\xd2\x99\xcd\x51\x93\x7e\xed\x2e\x38\xc7\xbd\xce\x46\x50\x3d\x72\xe3\x79\x25\x9d\x9b\x88\x2b\x10\x20\xdd\xa5\xb8\x32\x9f\x8d\xe0\x29\xdf\x21\x74\x86\x82\xdb\x2f\x82\x30\xc6\xc7\x35\x86\xb3\xf9\x96\x5f\x46\xdb\x0c\x45\xfd\xf3\x50\xc3\x6f\xc6\xc3\x48\xad\x46\xa6\xe1\x27\x47\x0a\x1d\x0e\x9b\xb6\xc2\x77\x7f\x63\xf2\xe0\x7d\x1a\xbe\xfc\xe0\xdf\xd7\xc7\xa7\x6c\xb0\xf9\xae\xba\x3c\xfd\x74\xb4\x11\xe8\x58\x0d\x80\xbc\xd3\xa8\x80\x3a\x99\xed\x75\xcc\x46\x7b", 0 }, + /* Anchor: 19 AmericaOnline2.der serial: #{a.serial.to_s} + C=US,O=America Online Inc.,CN=America Online Root Certification Authority 2 + */ + { 1448, "\x30\x82\x05\xa4\x30\x82\x03\x8c\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x63\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x41\x6d\x65\x72\x69\x63\x61\x20\x4f\x6e\x6c\x69\x6e\x65\x20\x49\x6e\x63\x2e\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2d\x41\x6d\x65\x72\x69\x63\x61\x20\x4f\x6e\x6c\x69\x6e\x65\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x32\x30\x1e\x17\x0d\x30\x32\x30\x35\x32\x38\x30\x36\x30\x30\x30\x30\x5a\x17\x0d\x33\x37\x30\x39\x32\x39\x31\x34\x30\x38\x30\x30\x5a\x30\x63\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x41\x6d\x65\x72\x69\x63\x61\x20\x4f\x6e\x6c\x69\x6e\x65\x20\x49\x6e\x63\x2e\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2d\x41\x6d\x65\x72\x69\x63\x61\x20\x4f\x6e\x6c\x69\x6e\x65\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x32\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\xcc\x41\x45\x1d\xe9\x3d\x4d\x10\xf6\x8c\xb1\x41\xc9\xe0\x5e\xcb\x0d\xb7\xbf\x47\x73\xd3\xf0\x55\x4d\xdd\xc6\x0c\xfa\xb1\x66\x05\x6a\xcd\x78\xb4\xdc\x02\xdb\x4e\x81\xf3\xd7\xa7\x7c\x71\xbc\x75\x63\xa0\x5d\xe3\x07\x0c\x48\xec\x25\xc4\x03\x20\xf4\xff\x0e\x3b\x12\xff\x9b\x8d\xe1\xc6\xd5\x1b\xb4\x6d\x22\xe3\xb1\xdb\x7f\x21\x64\xaf\x86\xbc\x57\x22\x2a\xd6\x47\x81\x57\x44\x82\x56\x53\xbd\x86\x14\x01\x0b\xfc\x7f\x74\xa4\x5a\xae\xf1\xba\x11\xb5\x9b\x58\x5a\x80\xb4\x37\x78\x09\x33\x7c\x32\x47\x03\x5c\xc4\xa5\x83\x48\xf4\x57\x56\x6e\x81\x36\x27\x18\x4f\xec\x9b\x28\xc2\xd4\xb4\xd7\x7c\x0c\x3e\x0c\x2b\xdf\xca\x04\xd7\xc6\x8e\xea\x58\x4e\xa8\xa4\xa5\x18\x1c\x6c\x45\x98\xa3\x41\xd1\x2d\xd2\xc7\x6d\x8d\x19\xf1\xad\x79\xb7\x81\x3f\xbd\x06\x82\x27\x2d\x10\x58\x05\xb5\x78\x05\xb9\x2f\xdb\x0c\x6b\x90\x90\x7e\x14\x59\x38\xbb\x94\x24\x13\xe5\xd1\x9d\x14\xdf\xd3\x82\x4d\x46\xf0\x80\x39\x52\x32\x0f\xe3\x84\xb2\x7a\x43\xf2\x5e\xde\x5f\x3f\x1d\xdd\xe3\xb2\x1b\xa0\xa1\x2a\x23\x03\x6e\x2e\x01\x15\x87\x5c\xa6\x75\x75\xc7\x97\x61\xbe\xde\x86\xdc\xd4\x48\xdb\xbd\x2a\xbf\x4a\x55\xda\xe8\x7d\x50\xfb\xb4\x80\x17\xb8\x94\xbf\x01\x3d\xea\xda\xba\x7c\xe0\x58\x67\x17\xb9\x58\xe0\x88\x86\x46\x67\x6c\x9d\x10\x47\x58\x32\xd0\x35\x7c\x79\x2a\x90\xa2\x5a\x10\x11\x23\x35\xad\x2f\xcc\xe4\x4a\x5b\xa7\xc8\x27\xf2\x83\xde\x5e\xbb\x5e\x77\xe7\xe8\xa5\x6e\x63\xc2\x0d\x5d\x61\xd0\x8c\xd2\x6c\x5a\x21\x0e\xca\x28\xa3\xce\x2a\xe9\x95\xc7\x48\xcf\x96\x6f\x1d\x92\x25\xc8\xc6\xc6\xc1\xc1\x0c\x05\xac\x26\xc4\xd2\x75\xd2\xe1\x2a\x67\xc0\x3d\x5b\xa5\x9a\xeb\xcf\x7b\x1a\xa8\x9d\x14\x45\xe5\x0f\xa0\x9a\x65\xde\x2f\x28\xbd\xce\x6f\x94\x66\x83\x48\x29\xd8\xea\x65\x8c\xaf\x93\xd9\x64\x9f\x55\x57\x26\xbf\x6f\xcb\x37\x31\x99\xa3\x60\xbb\x1c\xad\x89\x34\x32\x62\xb8\x43\x21\x06\x72\x0c\xa1\x5c\x6d\x46\xc5\xfa\x29\xcf\x30\xde\x89\xdc\x71\x5b\xdd\xb6\x37\x3e\xdf\x50\xf5\xb8\x07\x25\x26\xe5\xbc\xb5\xfe\x3c\x02\xb3\xb7\xf8\xbe\x43\xc1\x87\x11\x94\x9e\x23\x6c\x17\x8a\xb8\x8a\x27\x0c\x54\x47\xf0\xa9\xb3\xc0\x80\x8c\xa0\x27\xeb\x1d\x19\xe3\x07\x8e\x77\x70\xca\x2b\xf4\x7d\x76\xe0\x78\x67\x02\x03\x01\x00\x01\xa3\x63\x30\x61\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x4d\x45\xc1\x68\x38\xbb\x73\xa9\x69\xa1\x20\xe7\xed\xf5\x22\xa1\x23\x14\xd7\x9e\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x4d\x45\xc1\x68\x38\xbb\x73\xa9\x69\xa1\x20\xe7\xed\xf5\x22\xa1\x23\x14\xd7\x9e\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x86\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x67\x6b\x06\xb9\x5f\x45\x3b\x2a\x4b\x33\xb3\xe6\x1b\x6b\x59\x4e\x22\xcc\xb9\xb7\xa4\x25\xc9\xa7\xc4\xf0\x54\x96\x0b\x64\xf3\xb1\x58\x4f\x5e\x51\xfc\xb2\x97\x7b\x27\x65\xc2\xe5\xca\xe7\x0d\x0c\x25\x7b\x62\xe3\xfa\x9f\xb4\x87\xb7\x45\x46\xaf\x83\xa5\x97\x48\x8c\xa5\xbd\xf1\x16\x2b\x9b\x76\x2c\x7a\x35\x60\x6c\x11\x80\x97\xcc\xa9\x92\x52\xe6\x2b\xe6\x69\xed\xa9\xf8\x36\x2d\x2c\x77\xbf\x61\x48\xd1\x63\x0b\xb9\x5b\x52\xed\x18\xb0\x43\x42\x22\xa6\xb1\x77\xae\xde\x69\xc5\xcd\xc7\x1c\xa1\xb1\xa5\x1c\x10\xfb\x18\xbe\x1a\x70\xdd\xc1\x92\x4b\xbe\x29\x5a\x9d\x3f\x35\xbe\xe5\x7d\x51\xf8\x55\xe0\x25\x75\x23\x87\x1e\x5c\xdc\xba\x9d\xb0\xac\xb3\x69\xdb\x17\x83\xc9\xf7\xde\x0c\xbc\x08\xdc\x91\x9e\xa8\xd0\xd7\x15\x37\x73\xa5\x35\xb8\xfc\x7e\xc5\x44\x40\x06\xc3\xeb\xf8\x22\x80\x5c\x47\xce\x02\xe3\x11\x9f\x44\xff\xfd\x9a\x32\xcc\x7d\x64\x51\x0e\xeb\x57\x26\x76\x3a\xe3\x1e\x22\x3c\xc2\xa6\x36\xdd\x19\xef\xa7\xfc\x12\xf3\x26\xc0\x59\x31\x85\x4c\x9c\xd8\xcf\xdf\xa4\xcc\xcc\x29\x93\xff\x94\x6d\x76\x5c\x13\x08\x97\xf2\xed\xa5\x0b\x4d\xdd\xe8\xc9\x68\x0e\x66\xd3\x00\x0e\x33\x12\x5b\xbc\x95\xe5\x32\x90\xa8\xb3\xc6\x6c\x83\xad\x77\xee\x8b\x7e\x7e\xb1\xa9\xab\xd3\xe1\xf1\xb6\xc0\xb1\xea\x88\xc0\xe7\xd3\x90\xe9\x28\x92\x94\x7b\x68\x7b\x97\x2a\x0a\x67\x2d\x85\x02\x38\x10\xe4\x03\x61\xd4\xda\x25\x36\xc7\x08\x58\x2d\xa1\xa7\x51\xaf\x30\x0a\x49\xf5\xa6\x69\x87\x07\x2d\x44\x46\x76\x8e\x2a\xe5\x9a\x3b\xd7\x18\xa2\xfc\x9c\x38\x10\xcc\xc6\x3b\xd2\xb5\x17\x3a\x6f\xfd\xae\x25\xbd\xf5\x72\x59\x64\xb1\x74\x2a\x38\x5f\x18\x4c\xdf\xcf\x71\x04\x5a\x36\xd4\xbf\x2f\x99\x9c\xe8\xd9\xba\xb1\x95\xe6\x02\x4b\x21\xa1\x5b\xd5\xc1\x4f\x8f\xae\x69\x6d\x53\xdb\x01\x93\xb5\x5c\x1e\x18\xdd\x64\x5a\xca\x18\x28\x3e\x63\x04\x11\xfd\x1c\x8d\x00\x0f\xb8\x37\xdf\x67\x8a\x9d\x66\xa9\x02\x6a\x91\xff\x13\xca\x2f\x5d\x83\xbc\x87\x93\x6c\xdc\x24\x51\x16\x04\x25\x66\xfa\xb3\xd9\xc2\xba\x29\xbe\x9a\x48\x38\x82\x99\xf4\xbf\x3b\x4a\x31\x19\xf9\xbf\x8e\x21\x33\x14\xca\x4f\x54\x5f\xfb\xce\xfb\x8f\x71\x7f\xfd\x5e\x19\xa0\x0f\x4b\x91\xb8\xc4\x54\xbc\x06\xb0\x45\x8f\x26\x91\xa2\x8e\xfe\xa9", 0 }, + /* Anchor: 20 AOLTimeWarner1.der serial: #{a.serial.to_s} + C=US,O=AOL Time Warner Inc.,OU=America Online Inc.,CN=AOL Time Warner Root Certification Authority 1 + */ + { 1002, "\x30\x82\x03\xe6\x30\x82\x02\xce\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\x83\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x13\x14\x41\x4f\x4c\x20\x54\x69\x6d\x65\x20\x57\x61\x72\x6e\x65\x72\x20\x49\x6e\x63\x2e\x31\x1c\x30\x1a\x06\x03\x55\x04\x0b\x13\x13\x41\x6d\x65\x72\x69\x63\x61\x20\x4f\x6e\x6c\x69\x6e\x65\x20\x49\x6e\x63\x2e\x31\x37\x30\x35\x06\x03\x55\x04\x03\x13\x2e\x41\x4f\x4c\x20\x54\x69\x6d\x65\x20\x57\x61\x72\x6e\x65\x72\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x31\x30\x1e\x17\x0d\x30\x32\x30\x35\x32\x39\x30\x36\x30\x30\x30\x30\x5a\x17\x0d\x33\x37\x31\x31\x32\x30\x31\x35\x30\x33\x30\x30\x5a\x30\x81\x83\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x13\x14\x41\x4f\x4c\x20\x54\x69\x6d\x65\x20\x57\x61\x72\x6e\x65\x72\x20\x49\x6e\x63\x2e\x31\x1c\x30\x1a\x06\x03\x55\x04\x0b\x13\x13\x41\x6d\x65\x72\x69\x63\x61\x20\x4f\x6e\x6c\x69\x6e\x65\x20\x49\x6e\x63\x2e\x31\x37\x30\x35\x06\x03\x55\x04\x03\x13\x2e\x41\x4f\x4c\x20\x54\x69\x6d\x65\x20\x57\x61\x72\x6e\x65\x72\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x31\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\x99\xde\x8f\xc3\x25\xa3\x69\x34\xe8\x05\xf7\x74\xb9\xbf\x5a\x97\x19\xb9\x2f\x94\xd2\x93\xe5\x2d\x89\xca\x84\x7c\x3f\x10\x43\x1b\x8c\x8b\x7c\x84\x58\xf8\x24\x7c\x48\xcf\x2a\xfd\xc0\x15\xd9\x18\x7e\x84\x1a\x17\xd3\xdb\x9e\xd7\xca\xe4\xd9\xd7\xaa\x58\x51\x87\xf0\xf0\x8b\x48\x4e\xe2\xc2\xc4\x59\x69\x30\x62\xb6\x30\xa2\x8c\x0b\x11\x99\x61\x35\x6d\x7e\xef\xc5\xb1\x19\x06\x20\x12\x8e\x42\xe1\xdf\x0f\x96\x10\x52\xa8\xcf\x9c\x5f\x95\x14\xd8\xaf\x3b\x75\x0b\x31\x20\x1f\x44\x2f\xa2\x62\x41\xb3\xbb\x18\x21\xdb\xca\x71\x3c\x8c\xec\xb6\xb9\x0d\x9f\xef\x51\xef\x4d\x7b\x12\xf2\x0b\x0c\xe1\xac\x40\x8f\x77\x7f\xb0\xca\x78\x71\x0c\x5d\x16\x71\x70\xa2\xd7\xc2\x3a\x85\xcd\x0e\x9a\xc4\xe0\x00\xb0\xd5\x25\xea\xdc\x2b\xe4\x94\x2d\x38\x9c\x89\x41\x57\x64\x28\x65\x19\x1c\xb6\x44\xb4\xc8\x31\x6b\x8e\x01\x7b\x76\x59\x25\x7f\x15\x1c\x84\x08\x7c\x73\x65\x20\x0a\xa1\x04\x2e\x1a\x32\xa8\x9a\x20\xb1\x9c\x2c\x21\x59\xe7\xfb\xcf\xee\x70\x2d\x08\xca\x63\x3e\x2c\x9b\x93\x19\x6a\xa4\xc2\x97\xff\xb7\x86\x57\x88\x85\x6c\x9e\x15\x16\x2b\x4d\x2c\xb3\x02\x03\x01\x00\x01\xa3\x63\x30\x61\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xa1\x36\x30\x16\xcb\x86\x90\x00\x45\x80\x53\xb1\x8f\xc8\xd8\x3d\x7c\xbe\x5f\x12\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\xa1\x36\x30\x16\xcb\x86\x90\x00\x45\x80\x53\xb1\x8f\xc8\xd8\x3d\x7c\xbe\x5f\x12\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x86\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x8a\x20\x18\xa5\xbe\xb3\x2f\xb4\xa6\x84\x00\x40\x30\x29\xfa\xb4\x14\x73\x4c\x79\x45\xa7\xf6\x70\xe0\xe8\x7e\x64\x1e\x0a\x95\x7c\x6a\x61\xc2\xef\x4e\x1f\xbe\xff\xc9\x99\x1f\x07\x61\x4a\xe1\x5d\x4c\xcd\xad\xee\xd0\x52\x32\xd9\x59\x32\xbc\xda\x79\x72\xd6\x7b\x09\xe8\x02\x81\x35\xd3\x0a\xdf\x11\x1d\xc9\x79\xa0\x80\x4d\xfe\x5a\xd7\x56\xd6\xed\x0f\x2a\xaf\xa7\x18\x75\x33\x0c\xea\xc1\x61\x05\x4f\x6a\x9a\x89\xf2\x8d\xb9\x9f\x2e\xef\xb0\x5f\x5a\x00\xeb\xbe\xad\xa0\xf8\x44\x05\x67\xbc\xcb\x04\xef\x9e\x64\xc5\xe9\xc8\x3f\x05\xbf\xc6\x2f\x07\x1c\xc3\x36\x71\x86\xca\x38\x66\x4a\xcd\xd6\xb8\x4b\xc6\x6c\xa7\x97\x3b\xfa\x13\x2d\x6e\x23\x61\x87\xa1\x63\x42\xac\xc2\xcb\x97\x9f\x61\x68\xcf\x2d\x4c\x04\x9d\xd7\x25\x4f\x0a\x0e\x4d\x90\x8b\x18\x56\xa8\x93\x48\x57\xdc\x6f\xae\xbd\x9e\x67\x57\x77\x89\x50\xb3\xbe\x11\x9b\x45\x67\x83\x86\x19\x87\xd3\x98\xbd\x08\x1a\x16\x1f\x58\x82\x0b\xe1\x96\x69\x05\x4b\x8e\xec\x83\x51\x31\x07\xd5\xd4\x9f\xff\x59\x7b\xa8\x6e\x85\xcf\xd3\x4b\xa9\x49\xb0\x5f\xb0\x39\x28\x68\x0e\x73\xdd\x25\x9a\xde\x12", 0 }, + /* Anchor: 21 AOLTimeWarner2.der serial: #{a.serial.to_s} + C=US,O=AOL Time Warner Inc.,OU=America Online Inc.,CN=AOL Time Warner Root Certification Authority 2 + */ + { 1514, "\x30\x82\x05\xe6\x30\x82\x03\xce\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\x83\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x13\x14\x41\x4f\x4c\x20\x54\x69\x6d\x65\x20\x57\x61\x72\x6e\x65\x72\x20\x49\x6e\x63\x2e\x31\x1c\x30\x1a\x06\x03\x55\x04\x0b\x13\x13\x41\x6d\x65\x72\x69\x63\x61\x20\x4f\x6e\x6c\x69\x6e\x65\x20\x49\x6e\x63\x2e\x31\x37\x30\x35\x06\x03\x55\x04\x03\x13\x2e\x41\x4f\x4c\x20\x54\x69\x6d\x65\x20\x57\x61\x72\x6e\x65\x72\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x32\x30\x1e\x17\x0d\x30\x32\x30\x35\x32\x39\x30\x36\x30\x30\x30\x30\x5a\x17\x0d\x33\x37\x30\x39\x32\x38\x32\x33\x34\x33\x30\x30\x5a\x30\x81\x83\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x13\x14\x41\x4f\x4c\x20\x54\x69\x6d\x65\x20\x57\x61\x72\x6e\x65\x72\x20\x49\x6e\x63\x2e\x31\x1c\x30\x1a\x06\x03\x55\x04\x0b\x13\x13\x41\x6d\x65\x72\x69\x63\x61\x20\x4f\x6e\x6c\x69\x6e\x65\x20\x49\x6e\x63\x2e\x31\x37\x30\x35\x06\x03\x55\x04\x03\x13\x2e\x41\x4f\x4c\x20\x54\x69\x6d\x65\x20\x57\x61\x72\x6e\x65\x72\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x32\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\xb4\x37\x5a\x08\x16\x99\x14\xe8\x55\xb1\x1b\x24\x6b\xfc\xc7\x8b\xe6\x87\xa9\x89\xee\x8b\x99\xcd\x4f\x40\x86\xa4\xb6\x4d\xc9\xd9\xb1\xdc\x3c\x4d\x0d\x85\x4c\x15\x6c\x46\x8b\x52\x78\x9f\xf8\x23\xfd\x67\xf5\x24\x3a\x68\x5d\xd0\xf7\x64\x61\x41\x54\xa3\x8b\xa5\x08\xd2\x29\x5b\x9b\x60\x4f\x26\x83\xd1\x63\x12\x56\x49\x76\xa4\x16\xc2\xa5\x9d\x45\xac\x8b\x84\x95\xa8\x16\xb1\xec\x9f\xea\x24\x1a\xef\xb9\x57\x5c\x9a\x24\x21\x2c\x4d\x0e\x71\x1f\xa6\xac\x5d\x45\x74\x03\x98\xc4\x54\x8c\x16\x4a\x41\x77\x86\x95\x75\x0c\x47\x01\x66\x60\xfc\x15\xf1\x0f\xea\xf5\x14\x78\xc7\x0e\xd7\x6e\x81\x1c\x5e\xbf\x5e\xe7\x3a\x2a\xd8\x97\x17\x30\x7c\x00\xad\x08\x9d\x33\xaf\xb8\x99\x61\x80\x8b\xa8\x95\x7e\x14\xdc\x12\x6c\xa4\xd0\xd8\xef\x40\x49\x02\x36\xf9\x6e\xa9\xd6\x1d\x96\x56\x04\xb2\xb3\x2d\x16\x56\x86\x8f\xd9\x20\x57\x80\xcd\x67\x10\x6d\xb0\x4c\xf0\xda\x46\xb6\xea\x25\x2e\x46\xaf\x8d\xb0\x85\x38\x34\x8b\x14\x26\x82\x2b\xac\xae\x99\x0b\x8e\x14\xd7\x52\xbd\x9e\x69\xc3\x86\x02\x0b\xea\x76\x75\x31\x09\xce\x33\x19\x21\x85\x43\xe6\x89\x2d\x9f\x25\x37\x67\xf1\x23\x6a\xd2\x00\x6d\x97\xf9\x9f\xe7\x29\xca\xdd\x1f\xd7\x06\xea\xb8\xc9\xb9\x09\x21\x9f\xc8\x3f\x06\xc5\xd2\xe9\x12\x46\x00\x4e\x7b\x08\xeb\x42\x3d\x2b\x48\x6e\x9d\x67\xdd\x4b\x02\xe4\x44\xf3\x93\x19\xa5\x27\xce\x69\x7a\xbe\x67\xd3\xfc\x50\xa4\x2c\xab\xc3\x6b\xb9\xe3\x80\x4c\xcf\x05\x61\x4b\x2b\xdc\x1b\xb9\xa6\xd2\xd0\xaa\xf5\x2b\x73\xfb\xce\x90\x35\x9f\x0c\x52\x1c\xbf\x5c\x21\x61\x11\x5b\x15\x4b\xa9\x24\x51\xfc\xa4\x5c\xf7\x17\x9d\xb0\xd2\xfa\x07\xe9\x8f\x56\xe4\x1a\x8c\x68\x8a\x04\xd3\x7c\x5a\xe3\x9e\xa2\xa1\xca\x71\x5b\xa2\xd4\xa0\xe7\x29\x85\x5d\x03\x68\x2a\x4f\xd2\x06\xd7\x3d\xf9\xc3\x03\x2f\x3f\x65\xf9\x67\x1e\x47\x40\xd3\x63\x0f\xe3\xd5\x8e\xf9\x85\xab\x97\x4c\xb3\xd7\x26\xeb\x96\x0a\x94\xde\x85\x36\x9c\xc8\x7f\x81\x09\x02\x49\x2a\x0e\xf5\x64\x32\x0c\x82\xd1\xba\x6a\x82\x1b\xb3\x4b\x74\x11\xf3\x8c\x77\xd6\x9f\xbf\xdc\x37\xa4\xa7\x55\x04\x2f\xd4\x31\xe8\xd3\x46\xb9\x03\x7c\xda\x12\x4e\x59\x64\xb7\x51\x31\x31\x50\xa0\xca\x1c\x27\xd9\x10\x2e\xad\xd6\xbd\x10\x66\x2b\xc3\xb0\x22\x4a\x12\x5b\x02\x03\x01\x00\x01\xa3\x63\x30\x61\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x4f\x69\x6d\x03\x7e\x9d\x9f\x07\x18\x43\xbc\xb7\x10\x4e\xd5\xbf\xa9\xc4\x20\x28\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x4f\x69\x6d\x03\x7e\x9d\x9f\x07\x18\x43\xbc\xb7\x10\x4e\xd5\xbf\xa9\xc4\x20\x28\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x86\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x3b\xf3\xae\xca\xe8\x2e\x87\x85\xfb\x65\x59\xe7\xad\x11\x14\xa5\x57\xbc\x58\x9f\x24\x12\x57\xbb\xfb\x3f\x34\xda\xee\xad\x7a\x2a\x34\x72\x70\x31\x6b\xc7\x19\x98\x80\xc9\x82\xde\x37\x77\x5e\x54\x8b\x8e\xf2\xea\x67\x4f\xc9\x74\x84\x91\x56\x09\xd5\xe5\x7a\x9a\x81\xb6\x81\xc2\xad\x36\xe4\xf1\x54\x11\x53\xf3\x34\x45\x01\x26\xc8\xe5\x1a\xbc\x34\x44\x21\xde\xad\x25\xfc\x76\x16\x77\x21\x90\x80\x98\x57\x9d\x4e\xea\xec\x2f\xaa\x3c\x14\x7b\x57\xc1\x7e\x18\x14\x67\xee\x24\xc6\xbd\xba\x15\xb0\xd2\x18\xbd\xb7\x55\x81\xac\x53\xc0\xe8\xdd\x69\x12\x13\x42\xb7\x02\xb5\x05\x41\xca\x79\x50\x6e\x82\x0e\x71\x72\x93\x46\xe8\x9d\x0d\x5d\xbd\xae\xce\x29\xad\x63\xd5\x55\x16\x80\x30\x27\xff\x76\xba\xf7\xb8\xd6\x4a\xe3\xd9\xb5\xf9\x52\xd0\x4e\x40\xa9\xc7\xe5\xc2\x32\xc7\xaa\x76\x24\xe1\x6b\x05\x50\xeb\xc5\xbf\x0a\x54\xe5\xb9\x42\x3c\x24\xfb\xb7\x07\x9c\x30\x9f\x79\x5a\xe6\xe0\x40\x52\x15\xf4\xfc\xaa\xf4\x56\xf9\x44\x97\x87\xed\x0e\x65\x72\x5e\xbe\x26\xfb\x4d\xa4\x2d\x08\x07\xde\xd8\x5c\xa0\xdc\x81\x33\x99\x18\x25\x11\x77\xa7\xeb\xfd\x58\x09\x2c\x99\x6b\x1b\x8a\xf3\x52\x3f\x1a\x4d\x48\x60\xf1\xa0\xf6\x33\x02\x53\x8b\xed\x25\x09\xb8\x0d\x2d\xed\x97\x73\xec\xd7\x96\x1f\x8e\x60\x0e\xda\x10\x9b\x2f\x18\x24\xf6\xa6\x4d\x0a\xf9\x3b\xcb\x75\xc2\xcc\x2f\xce\x24\x69\xc9\x0a\x22\x8e\x59\xa7\xf7\x82\x0c\xd7\xd7\x6b\x35\x9c\x43\x00\x6a\xc4\x95\x67\xba\x9c\x45\xcb\xb8\x0e\x37\xf7\xdc\x4e\x01\x4f\xbe\x0a\xb6\x03\xd3\xad\x8a\x45\xf7\xda\x27\x4d\x29\xb1\x48\xdf\xe4\x11\xe4\x96\x46\xbd\x6c\x02\x3e\xd6\x51\xc8\x95\x17\x01\x15\xa9\xf2\xaa\xaa\xf2\xbf\x2f\x65\x1b\x6f\xd0\xb9\x1a\x93\xf5\x8e\x35\xc4\x80\x87\x3e\x94\x2f\x66\xe4\xe9\xa8\xff\x41\x9c\x70\x2a\x4f\x2a\x39\x18\x95\x1e\x7e\xfb\x61\x01\x3c\x51\x08\x2e\x28\x18\xa4\x16\x0f\x31\xfd\x3a\x6c\x23\x93\x20\x76\xe1\xfd\x07\x85\xd1\x5b\x3f\xd2\x1c\x73\x32\xdd\xfa\xb9\xf8\x8c\xcf\x02\x87\x7a\x9a\x96\xe4\xed\x4f\x89\x8d\x53\x43\xab\x0e\x13\xc0\x01\x15\xb4\x79\x38\xdb\xfc\x6e\x3d\x9e\x51\xb6\xb8\x13\x8b\x67\xcf\xf9\x7c\xd9\x22\x1d\xf6\x5d\xc5\x1c\x01\x2f\x98\xe8\x7a\x24\x18\xbc\x84\xd7\xfa\xdc\x72\x5b\xf7\xc1\x3a\x68", 0 }, + /* Anchor: 22 APCAroot.der serial: #{a.serial.to_s} + C=JP,O=Japanese Government,OU=ApplicationCA + */ + { 932, "\x30\x82\x03\xa0\x30\x82\x02\x88\xa0\x03\x02\x01\x02\x02\x01\x31\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x43\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4a\x50\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x4a\x61\x70\x61\x6e\x65\x73\x65\x20\x47\x6f\x76\x65\x72\x6e\x6d\x65\x6e\x74\x31\x16\x30\x14\x06\x03\x55\x04\x0b\x13\x0d\x41\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x43\x41\x30\x1e\x17\x0d\x30\x37\x31\x32\x31\x32\x31\x35\x30\x30\x30\x30\x5a\x17\x0d\x31\x37\x31\x32\x31\x32\x31\x35\x30\x30\x30\x30\x5a\x30\x43\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4a\x50\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x4a\x61\x70\x61\x6e\x65\x73\x65\x20\x47\x6f\x76\x65\x72\x6e\x6d\x65\x6e\x74\x31\x16\x30\x14\x06\x03\x55\x04\x0b\x13\x0d\x41\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xa7\x6d\xe0\x74\x4e\x87\x8f\xa5\x06\xde\x68\xa2\xdb\x86\x99\x4b\x64\x0d\x71\xf0\x0a\x05\x9b\x8e\xaa\xe1\xcc\x2e\xd2\x6a\x3b\xc1\x7a\xb4\x97\x61\x8d\x8a\xbe\xc6\x9a\x9c\x06\xb4\x86\x51\xe4\x37\x0e\x74\x78\x7e\x5f\x8a\x7f\x94\xa4\xd7\x47\x08\xfd\x50\x5a\x56\xe4\x68\xac\x28\x73\xa0\x7b\xe9\x7f\x18\x92\x40\x4f\x2d\x9d\xf5\xae\x44\x48\x73\x36\x06\x9e\x64\x2c\x3b\x34\x23\xdb\x5c\x26\xe4\x71\x79\x8f\xd4\x6e\x79\x22\xb9\x93\xc1\xca\xcd\xc1\x56\xed\x88\x6a\xd7\xa0\x39\x21\x04\x57\x2c\xa2\xf5\xbc\x47\x41\x4f\x5e\x34\x22\x95\xb5\x1f\x29\x6d\x5e\x4a\xf3\x4d\x72\xbe\x41\x56\x20\x87\xfc\xe9\x50\x47\xd7\x30\x14\xee\x5c\x8c\x55\xba\x59\x8d\x87\xfc\x23\xde\x93\xd0\x04\x8c\xfd\xef\x6d\xbd\xd0\x7a\xc9\xa5\x3a\x6a\x72\x33\xc6\x4a\x0d\x05\x17\x2a\x2d\x7b\xb1\xa7\xd8\xd6\xf0\xbe\xf4\x3f\xea\x0e\x28\x6d\x41\x61\x23\x76\x78\xc3\xb8\x65\xa4\xf3\x5a\xae\xcc\xc2\xaa\xd9\xe7\x58\xde\xb6\x7e\x9d\x85\x6e\x9f\x2a\x0a\x6f\x9f\x03\x29\x30\x97\x28\x1d\xbc\xb7\xcf\x54\x29\x4e\x51\x31\xf9\x27\xb6\x28\x26\xfe\xa2\x63\xe6\x41\x16\xf0\x33\x98\x47\x02\x03\x01\x00\x01\xa3\x81\x9e\x30\x81\x9b\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x54\x5a\xcb\x26\x3f\x71\xcc\x94\x46\x0d\x96\x53\xea\x6b\x48\xd0\x93\xfe\x42\x75\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x59\x06\x03\x55\x1d\x11\x04\x52\x30\x50\xa4\x4e\x30\x4c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4a\x50\x31\x18\x30\x16\x06\x03\x55\x04\x0a\x0c\x0f\xe6\x97\xa5\xe6\x9c\xac\xe5\x9b\xbd\xe6\x94\xbf\xe5\xba\x9c\x31\x23\x30\x21\x06\x03\x55\x04\x0b\x0c\x1a\xe3\x82\xa2\xe3\x83\x97\xe3\x83\xaa\xe3\x82\xb1\xe3\x83\xbc\xe3\x82\xb7\xe3\x83\xa7\xe3\x83\xb3\x43\x41\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x39\x6a\x44\x76\x77\x38\x3a\xec\xa3\x67\x46\x0f\xf9\x8b\x06\xa8\xfb\x6a\x90\x31\xce\x7e\xec\xda\xd1\x89\x7c\x7a\xeb\x2e\x0c\xbd\x99\x32\xe7\xb0\x24\xd6\xc3\xff\xf5\xb2\x88\x09\x87\x2c\xe3\x54\xe1\xa3\xa6\xb2\x08\x0b\xc0\x85\xa8\xc8\xd2\x9c\x71\xf6\x1d\x9f\x60\xfc\x38\x33\x13\xe1\x9e\xdc\x0b\x5f\xda\x16\x50\x29\x7b\x2f\x70\x91\x0f\x99\xba\x34\x34\x8d\x95\x74\xc5\x7e\x78\xa9\x66\x5d\xbd\xca\x21\x77\x42\x10\xac\x66\x26\x3d\xde\x91\xab\xfd\x15\xf0\x6f\xed\x6c\x5f\x10\xf8\xf3\x16\xf6\x03\x8a\x8f\xa7\x12\x11\x0c\xcb\xfd\x3f\x79\xc1\x9c\xfd\x62\xee\xa3\xcf\x54\x0c\xd1\x2b\x5f\x17\x3e\xe3\x3e\xbf\xc0\x2b\x3e\x09\x9b\xfe\x88\xa6\x7e\xb4\x92\x17\xfc\x23\x94\x81\xbd\x6e\xa7\xc5\x8c\xc2\xeb\x11\x45\xdb\xf8\x41\xc9\x96\x76\xea\x70\x5f\x79\x12\x6b\xe4\xa3\x07\x5a\x05\xef\x27\x49\xcf\x21\x9f\x8a\x4c\x09\x70\x66\xa9\x26\xc1\x2b\x11\x4e\x33\xd2\x0e\xfc\xd6\x6c\xd2\x0e\x32\x64\x68\xff\xad\x05\x78\x5f\x03\x1d\xa8\xe3\x90\xac\x24\xe0\x0f\x40\xa7\x4b\xae\x8b\x28\xb7\x82\xca\x18\x07\xe6\xb7\x5b\x74\xe9\x20\x19\x7f\xb2\x1b\x89\x54", 0 }, + /* Anchor: 23 AppCAG2.cer serial: #{a.serial.to_s} + C=JP,O=LGPKI,OU=Application CA G2 + */ + { 932, "\x30\x82\x03\xa0\x30\x82\x02\x88\xa0\x03\x02\x01\x02\x02\x01\x31\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x39\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4a\x50\x31\x0e\x30\x0c\x06\x03\x55\x04\x0a\x13\x05\x4c\x47\x50\x4b\x49\x31\x1a\x30\x18\x06\x03\x55\x04\x0b\x13\x11\x41\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x20\x43\x41\x20\x47\x32\x30\x1e\x17\x0d\x30\x36\x30\x33\x33\x31\x31\x35\x30\x30\x30\x30\x5a\x17\x0d\x31\x36\x30\x33\x33\x31\x31\x34\x35\x39\x35\x39\x5a\x30\x39\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4a\x50\x31\x0e\x30\x0c\x06\x03\x55\x04\x0a\x13\x05\x4c\x47\x50\x4b\x49\x31\x1a\x30\x18\x06\x03\x55\x04\x0b\x13\x11\x41\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x20\x43\x41\x20\x47\x32\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xb9\x35\xc6\x10\xf8\xdb\x68\xdb\x07\xc4\x40\x4c\xb0\x1d\x1e\x36\xdc\xc3\x41\xf6\xcf\x55\x15\x6d\x08\x7f\x5c\xc6\x68\x55\xe5\xe7\x57\xf1\x96\x51\xe6\xe1\x4d\x78\x0f\x6e\x40\x15\x70\x3b\x65\xfe\x11\xdf\xe7\xd3\xd6\x58\x35\x3b\xe1\x9f\x02\xfc\x94\x52\x46\x2e\xb3\x9e\x60\x9b\x02\x9e\xc9\x82\xd2\xf6\xe3\xae\x09\x4f\x84\x44\xb6\x62\x9b\x00\x51\x68\xb8\x3a\xad\xec\x64\xd1\x32\x4b\xe9\x94\x44\x83\xb4\x0e\xce\x21\x89\x6b\xb0\x36\xc0\x98\xc6\x4b\x9c\xc2\x3e\x5b\x60\x2a\x09\x31\x2b\x2d\xab\x4c\xde\xb1\xa0\xfd\x58\x56\xc2\x83\x1d\x20\xbc\xc4\x84\x09\x87\x7b\xa8\x95\x97\xc6\x25\x8e\x83\xe0\x3e\x93\x0d\xd1\xc7\x7d\x73\xa9\xa8\xfc\x19\x00\x40\x2e\x22\xb8\x7a\x33\x41\xf5\x78\xfd\x5a\x71\xe7\x82\xd9\x48\x88\x5c\xec\xa8\x85\x87\x2d\x6d\x80\x89\x67\x1a\x69\xbe\x10\xc0\x5a\x8e\xed\x88\x7d\x3e\x6f\x2c\x38\x6b\x37\xce\x47\xd8\xa2\x31\x30\xde\x7e\x53\x65\x6c\x8b\x86\x53\x41\x20\x6c\xbd\x48\xa5\x7e\xaf\x00\x5a\x56\x12\x58\x81\xd1\xdc\x89\x59\xf9\xb5\xee\xf8\x4d\x9a\xd8\x44\x29\x8b\x79\xa7\xf7\x22\xaa\xea\x7c\x5c\xb4\x16\x88\x20\x0d\x02\x03\x01\x00\x01\xa3\x81\xb2\x30\x81\xaf\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x7f\xb8\x5d\x8e\xc4\x18\x6b\xc6\x7d\xcc\x2e\xe9\xae\xce\x34\xe7\x17\x5d\xe0\xa1\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x4c\x06\x03\x55\x1d\x1f\x04\x45\x30\x43\x30\x41\xa0\x3f\xa0\x3d\xa4\x3b\x30\x39\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4a\x50\x31\x0e\x30\x0c\x06\x03\x55\x04\x0a\x13\x05\x4c\x47\x50\x4b\x49\x31\x1a\x30\x18\x06\x03\x55\x04\x0b\x13\x11\x41\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x20\x43\x41\x20\x47\x32\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x7f\xb8\x5d\x8e\xc4\x18\x6b\xc6\x7d\xcc\x2e\xe9\xae\xce\x34\xe7\x17\x5d\xe0\xa1\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x3c\xd8\x73\x36\x40\x06\x48\x4a\x54\x19\xf5\x27\x48\x39\x25\xa5\x6e\x42\xe7\xb6\xcd\x1b\xcb\x39\x34\xb7\x9b\xec\x4f\x2a\xbe\x77\xe4\xca\x84\xfc\x1d\xeb\x9b\x22\x40\xd5\xf4\xfb\x68\x87\x72\xfc\x47\x5d\x6a\x0e\x52\x4a\xe3\xb5\x5d\x48\xc6\x22\x96\xe6\x33\x6d\x6d\xab\xf6\xcd\xd7\xcb\x24\x5a\x8c\xa8\x45\x9e\x3e\x61\x82\x7d\x94\xd5\x05\xf0\x1a\x35\x5f\x71\x2f\x2e\x54\xb5\x41\x05\xef\x86\x0d\x52\xef\x9c\x98\x1b\xf1\x2c\x4c\x3a\xd1\xf3\x86\xd3\x8c\x3e\x7a\x2f\x86\x45\x8e\x83\x32\x26\x5b\xbf\x53\xca\x0e\x51\x56\xdc\x9a\xc2\x5a\x30\x19\x0d\xa7\x9e\xd5\xaa\x9b\x20\x39\x69\x78\x21\xf4\x97\x6d\xd1\x0e\x11\x4c\x2e\xd3\x1b\x5a\xb0\xf9\x97\x78\x5c\x2a\x8f\x52\x65\xee\x4c\x42\x25\xc2\x37\x30\x0e\x6d\x2b\x35\x94\x83\x06\xe8\xaf\x45\x3b\x04\x66\xa7\x30\xbb\xf9\xe0\x21\x3b\x63\x6e\x7d\x44\x5d\x3a\x6a\x53\xef\x11\x17\x24\xfd\x54\xb2\x5a\x6c\x73\x56\x21\xc9\x6c\x2d\x97\xa4\x42\xb3\x27\x61\x05\x21\x63\x6d\xea\x28\xbc\x4f\x1a\x6f\x42\xdc\x98\xab\x55\xd3\x1e\x1b\xc0\x92\x3f\x9b\xc1\xe6\x3b\x17\x56\xe2\xc4\x98\x43\x25\xee\xb6\xcb\x00", 0 }, + /* Anchor: 24 AppleIncRoot042506.cer serial: #{a.serial.to_s} + C=US,O=Apple Inc.,OU=Apple Certification Authority,CN=Apple Root CA + */ + { 1215, "\x30\x82\x04\xbb\x30\x82\x03\xa3\xa0\x03\x02\x01\x02\x02\x01\x02\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x62\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x13\x30\x11\x06\x03\x55\x04\x0a\x13\x0a\x41\x70\x70\x6c\x65\x20\x49\x6e\x63\x2e\x31\x26\x30\x24\x06\x03\x55\x04\x0b\x13\x1d\x41\x70\x70\x6c\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x16\x30\x14\x06\x03\x55\x04\x03\x13\x0d\x41\x70\x70\x6c\x65\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x1e\x17\x0d\x30\x36\x30\x34\x32\x35\x32\x31\x34\x30\x33\x36\x5a\x17\x0d\x33\x35\x30\x32\x30\x39\x32\x31\x34\x30\x33\x36\x5a\x30\x62\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x13\x30\x11\x06\x03\x55\x04\x0a\x13\x0a\x41\x70\x70\x6c\x65\x20\x49\x6e\x63\x2e\x31\x26\x30\x24\x06\x03\x55\x04\x0b\x13\x1d\x41\x70\x70\x6c\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x16\x30\x14\x06\x03\x55\x04\x03\x13\x0d\x41\x70\x70\x6c\x65\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xe4\x91\xa9\x09\x1f\x91\xdb\x1e\x47\x50\xeb\x05\xed\x5e\x79\x84\x2d\xeb\x36\xa2\x57\x4c\x55\xec\x8b\x19\x89\xde\xf9\x4b\x6c\xf5\x07\xab\x22\x30\x02\xe8\x18\x3e\xf8\x50\x09\xd3\x7f\x41\xa8\x98\xf9\xd1\xca\x66\x9c\x24\x6b\x11\xd0\xa3\xbb\xe4\x1b\x2a\xc3\x1f\x95\x9e\x7a\x0c\xa4\x47\x8b\x5b\xd4\x16\x37\x33\xcb\xc4\x0f\x4d\xce\x14\x69\xd1\xc9\x19\x72\xf5\x5d\x0e\xd5\x7f\x5f\x9b\xf2\x25\x03\xba\x55\x8f\x4d\x5d\x0d\xf1\x64\x35\x23\x15\x4b\x15\x59\x1d\xb3\x94\xf7\xf6\x9c\x9e\xcf\x50\xba\xc1\x58\x50\x67\x8f\x08\xb4\x20\xf7\xcb\xac\x2c\x20\x6f\x70\xb6\x3f\x01\x30\x8c\xb7\x43\xcf\x0f\x9d\x3d\xf3\x2b\x49\x28\x1a\xc8\xfe\xce\xb5\xb9\x0e\xd9\x5e\x1c\xd6\xcb\x3d\xb5\x3a\xad\xf4\x0f\x0e\x00\x92\x0b\xb1\x21\x16\x2e\x74\xd5\x3c\x0d\xdb\x62\x16\xab\xa3\x71\x92\x47\x53\x55\xc1\xaf\x2f\x41\xb3\xf8\xfb\xe3\x70\xcd\xe6\xa3\x4c\x45\x7e\x1f\x4c\x6b\x50\x96\x41\x89\xc4\x74\x62\x0b\x10\x83\x41\x87\x33\x8a\x81\xb1\x30\x58\xec\x5a\x04\x32\x8c\x68\xb3\x8f\x1d\xde\x65\x73\xff\x67\x5e\x65\xbc\x49\xd8\x76\x9f\x33\x14\x65\xa1\x77\x94\xc9\x2d\x02\x03\x01\x00\x01\xa3\x82\x01\x7a\x30\x82\x01\x76\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x2b\xd0\x69\x47\x94\x76\x09\xfe\xf4\x6b\x8d\x2e\x40\xa6\xf7\x47\x4d\x7f\x08\x5e\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x2b\xd0\x69\x47\x94\x76\x09\xfe\xf4\x6b\x8d\x2e\x40\xa6\xf7\x47\x4d\x7f\x08\x5e\x30\x82\x01\x11\x06\x03\x55\x1d\x20\x04\x82\x01\x08\x30\x82\x01\x04\x30\x82\x01\x00\x06\x09\x2a\x86\x48\x86\xf7\x63\x64\x05\x01\x30\x81\xf2\x30\x2a\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x1e\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x61\x70\x70\x6c\x65\x2e\x63\x6f\x6d\x2f\x61\x70\x70\x6c\x65\x63\x61\x2f\x30\x81\xc3\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x02\x30\x81\xb6\x1a\x81\xb3\x52\x65\x6c\x69\x61\x6e\x63\x65\x20\x6f\x6e\x20\x74\x68\x69\x73\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x62\x79\x20\x61\x6e\x79\x20\x70\x61\x72\x74\x79\x20\x61\x73\x73\x75\x6d\x65\x73\x20\x61\x63\x63\x65\x70\x74\x61\x6e\x63\x65\x20\x6f\x66\x20\x74\x68\x65\x20\x74\x68\x65\x6e\x20\x61\x70\x70\x6c\x69\x63\x61\x62\x6c\x65\x20\x73\x74\x61\x6e\x64\x61\x72\x64\x20\x74\x65\x72\x6d\x73\x20\x61\x6e\x64\x20\x63\x6f\x6e\x64\x69\x74\x69\x6f\x6e\x73\x20\x6f\x66\x20\x75\x73\x65\x2c\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x70\x6f\x6c\x69\x63\x79\x20\x61\x6e\x64\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x70\x72\x61\x63\x74\x69\x63\x65\x20\x73\x74\x61\x74\x65\x6d\x65\x6e\x74\x73\x2e\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x5c\x36\x99\x4c\x2d\x78\xb7\xed\x8c\x9b\xdc\xf3\x77\x9b\xf2\x76\xd2\x77\x30\x4f\xc1\x1f\x85\x83\x85\x1b\x99\x3d\x47\x37\xf2\xa9\x9b\x40\x8e\x2c\xd4\xb1\x90\x12\xd8\xbe\xf4\x73\x9b\xee\xd2\x64\x0f\xcb\x79\x4f\x34\xd8\xa2\x3e\xf9\x78\xff\x6b\xc8\x07\xec\x7d\x39\x83\x8b\x53\x20\xd3\x38\xc4\xb1\xbf\x9a\x4f\x0a\x6b\xff\x2b\xfc\x59\xa7\x05\x09\x7c\x17\x40\x56\x11\x1e\x74\xd3\xb7\x8b\x23\x3b\x47\xa3\xd5\x6f\x24\xe2\xeb\xd1\xb7\x70\xdf\x0f\x45\xe1\x27\xca\xf1\x6d\x78\xed\xe7\xb5\x17\x17\xa8\xdc\x7e\x22\x35\xca\x25\xd5\xd9\x0f\xd6\x6b\xd4\xa2\x24\x23\x11\xf7\xa1\xac\x8f\x73\x81\x60\xc6\x1b\x5b\x09\x2f\x92\xb2\xf8\x44\x48\xf0\x60\x38\x9e\x15\xf5\x3d\x26\x67\x20\x8a\x33\x6a\xf7\x0d\x82\xcf\xde\xeb\xa3\x2f\xf9\x53\x6a\x5b\x64\xc0\x63\x33\x77\xf7\x3a\x07\x2c\x56\xeb\xda\x0f\x21\x0e\xda\xba\x73\x19\x4f\xb5\xd9\x36\x7f\xc1\x87\x55\xd9\xa7\x99\xb9\x32\x42\xfb\xd8\xd5\x71\x9e\x7e\xa1\x52\xb7\x1b\xbd\x93\x42\x24\x12\x2a\xc7\x0f\x1d\xb6\x4d\x9c\x5e\x63\xc8\x4b\x80\x17\x50\xaa\x8a\xd5\xda\xe4\xfc\xd0\x09\x07\x37\xb0\x75\x75\x21", 0 }, + /* Anchor: 25 AppleROOTCA.der serial: #{a.serial.to_s} + C=US,O=Apple Computer\, Inc.,OU=Apple Computer Certificate Authority,CN=Apple Root Certificate Authority + */ + { 1470, "\x30\x82\x05\xba\x30\x82\x04\xa2\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\x86\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x13\x14\x41\x70\x70\x6c\x65\x20\x43\x6f\x6d\x70\x75\x74\x65\x72\x2c\x20\x49\x6e\x63\x2e\x31\x2d\x30\x2b\x06\x03\x55\x04\x0b\x13\x24\x41\x70\x70\x6c\x65\x20\x43\x6f\x6d\x70\x75\x74\x65\x72\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x41\x70\x70\x6c\x65\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x30\x35\x30\x32\x31\x30\x30\x30\x31\x38\x31\x34\x5a\x17\x0d\x32\x35\x30\x32\x31\x30\x30\x30\x31\x38\x31\x34\x5a\x30\x81\x86\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x13\x14\x41\x70\x70\x6c\x65\x20\x43\x6f\x6d\x70\x75\x74\x65\x72\x2c\x20\x49\x6e\x63\x2e\x31\x2d\x30\x2b\x06\x03\x55\x04\x0b\x13\x24\x41\x70\x70\x6c\x65\x20\x43\x6f\x6d\x70\x75\x74\x65\x72\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x41\x70\x70\x6c\x65\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xe4\x91\xa9\x09\x1f\x91\xdb\x1e\x47\x50\xeb\x05\xed\x5e\x79\x84\x2d\xeb\x36\xa2\x57\x4c\x55\xec\x8b\x19\x89\xde\xf9\x4b\x6c\xf5\x07\xab\x22\x30\x02\xe8\x18\x3e\xf8\x50\x09\xd3\x7f\x41\xa8\x98\xf9\xd1\xca\x66\x9c\x24\x6b\x11\xd0\xa3\xbb\xe4\x1b\x2a\xc3\x1f\x95\x9e\x7a\x0c\xa4\x47\x8b\x5b\xd4\x16\x37\x33\xcb\xc4\x0f\x4d\xce\x14\x69\xd1\xc9\x19\x72\xf5\x5d\x0e\xd5\x7f\x5f\x9b\xf2\x25\x03\xba\x55\x8f\x4d\x5d\x0d\xf1\x64\x35\x23\x15\x4b\x15\x59\x1d\xb3\x94\xf7\xf6\x9c\x9e\xcf\x50\xba\xc1\x58\x50\x67\x8f\x08\xb4\x20\xf7\xcb\xac\x2c\x20\x6f\x70\xb6\x3f\x01\x30\x8c\xb7\x43\xcf\x0f\x9d\x3d\xf3\x2b\x49\x28\x1a\xc8\xfe\xce\xb5\xb9\x0e\xd9\x5e\x1c\xd6\xcb\x3d\xb5\x3a\xad\xf4\x0f\x0e\x00\x92\x0b\xb1\x21\x16\x2e\x74\xd5\x3c\x0d\xdb\x62\x16\xab\xa3\x71\x92\x47\x53\x55\xc1\xaf\x2f\x41\xb3\xf8\xfb\xe3\x70\xcd\xe6\xa3\x4c\x45\x7e\x1f\x4c\x6b\x50\x96\x41\x89\xc4\x74\x62\x0b\x10\x83\x41\x87\x33\x8a\x81\xb1\x30\x58\xec\x5a\x04\x32\x8c\x68\xb3\x8f\x1d\xde\x65\x73\xff\x67\x5e\x65\xbc\x49\xd8\x76\x9f\x33\x14\x65\xa1\x77\x94\xc9\x2d\x02\x03\x01\x00\x01\xa3\x82\x02\x2f\x30\x82\x02\x2b\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x2b\xd0\x69\x47\x94\x76\x09\xfe\xf4\x6b\x8d\x2e\x40\xa6\xf7\x47\x4d\x7f\x08\x5e\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x2b\xd0\x69\x47\x94\x76\x09\xfe\xf4\x6b\x8d\x2e\x40\xa6\xf7\x47\x4d\x7f\x08\x5e\x30\x82\x01\x29\x06\x03\x55\x1d\x20\x04\x82\x01\x20\x30\x82\x01\x1c\x30\x82\x01\x18\x06\x09\x2a\x86\x48\x86\xf7\x63\x64\x05\x01\x30\x82\x01\x09\x30\x41\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x35\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x61\x70\x70\x6c\x65\x2e\x63\x6f\x6d\x2f\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x61\x75\x74\x68\x6f\x72\x69\x74\x79\x2f\x74\x65\x72\x6d\x73\x2e\x68\x74\x6d\x6c\x30\x81\xc3\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x02\x30\x81\xb6\x1a\x81\xb3\x52\x65\x6c\x69\x61\x6e\x63\x65\x20\x6f\x6e\x20\x74\x68\x69\x73\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x62\x79\x20\x61\x6e\x79\x20\x70\x61\x72\x74\x79\x20\x61\x73\x73\x75\x6d\x65\x73\x20\x61\x63\x63\x65\x70\x74\x61\x6e\x63\x65\x20\x6f\x66\x20\x74\x68\x65\x20\x74\x68\x65\x6e\x20\x61\x70\x70\x6c\x69\x63\x61\x62\x6c\x65\x20\x73\x74\x61\x6e\x64\x61\x72\x64\x20\x74\x65\x72\x6d\x73\x20\x61\x6e\x64\x20\x63\x6f\x6e\x64\x69\x74\x69\x6f\x6e\x73\x20\x6f\x66\x20\x75\x73\x65\x2c\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x70\x6f\x6c\x69\x63\x79\x20\x61\x6e\x64\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x70\x72\x61\x63\x74\x69\x63\x65\x20\x73\x74\x61\x74\x65\x6d\x65\x6e\x74\x73\x2e\x30\x44\x06\x03\x55\x1d\x1f\x04\x3d\x30\x3b\x30\x39\xa0\x37\xa0\x35\x86\x33\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x61\x70\x70\x6c\x65\x2e\x63\x6f\x6d\x2f\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x61\x75\x74\x68\x6f\x72\x69\x74\x79\x2f\x72\x6f\x6f\x74\x2e\x63\x72\x6c\x30\x55\x06\x08\x2b\x06\x01\x05\x05\x07\x01\x01\x04\x49\x30\x47\x30\x45\x06\x08\x2b\x06\x01\x05\x05\x07\x30\x02\x86\x39\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x61\x70\x70\x6c\x65\x2e\x63\x6f\x6d\x2f\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x61\x75\x74\x68\x6f\x72\x69\x74\x79\x2f\x63\x61\x73\x69\x67\x6e\x65\x72\x73\x2e\x68\x74\x6d\x6c\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x9d\xda\x2d\x28\x58\x2f\x7d\x76\x04\xb9\x04\xd3\x3e\xce\xb7\x66\x63\x4e\x8f\x2f\xd4\xfe\x4b\xad\x72\xbd\xa3\x39\xc6\x52\x4d\x05\x98\x52\xf5\x89\x51\x01\x24\x79\xbe\x1a\x32\xf7\xe5\x44\x8b\x4b\x44\x07\x39\x82\xd6\x5a\xca\xb4\x20\x5e\xd9\xae\x15\x5d\x1d\x8c\x1d\x32\xbf\x38\x31\x62\x48\x5d\xc7\xe1\x90\xb1\xf8\x24\x40\xf8\x5f\x58\x9b\x51\x5d\x57\x9d\xc1\xe5\xff\x3c\xcc\x72\x21\x6e\xc4\xe9\xe9\xa1\x77\xd7\x2c\x17\x26\xc3\x3f\xeb\x9a\xe8\x0b\x03\xba\xe9\xb3\x4a\x72\xeb\x33\x09\x5b\xad\xe6\x62\x31\x6a\xe8\xaf\x2f\xd5\xaf\x1e\x57\x76\x8f\x7f\x37\x2d\x2e\x02\x5c\xdd\x63\xc9\xf2\x71\xb8\x26\x40\xdf\x15\x8d\x75\x44\x3f\x79\xbd\xe6\x1d\x99\xe1\x43\x2c\x3e\xad\x6f\xbe\xb9\xa4\xfe\x0e\x35\x19\x51\x63\xb1\xc3\xde\xb5\x92\x3e\x51\x78\x01\x73\x8a\xa4\x23\xca\xa4\x88\xf1\x1e\x5c\x1f\x41\x16\x2d\x7e\x95\x0a\xaa\xe9\x89\x41\x98\x1b\x1a\xdd\xcb\x20\xbf\x47\x5e\x0c\x26\xc5\x55\x35\x4d\xc6\x30\x8b\x99\x67\x14\xc7\x09\x1f\xba\x47\xc7\xda\x01\x09\x87\x24\x42\x95\xbd\x13\x60\x19\x0a\xef\xea\x7f\x0e\x6e\xcd\xc1\x44\x43\x3a\x4a\xd5\xe3", 0 }, + /* Anchor: 26 belgiumrca.crt serial: #{a.serial.to_s} + C=BE,CN=Belgium Root CA + */ + { 920, "\x30\x82\x03\x94\x30\x82\x02\x7c\xa0\x03\x02\x01\x02\x02\x10\x58\x0b\x05\x6c\x53\x24\xdb\xb2\x50\x57\x18\x5f\xf9\xe5\xa6\x50\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x27\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x45\x31\x18\x30\x16\x06\x03\x55\x04\x03\x13\x0f\x42\x65\x6c\x67\x69\x75\x6d\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x1e\x17\x0d\x30\x33\x30\x31\x32\x36\x32\x33\x30\x30\x30\x30\x5a\x17\x0d\x31\x34\x30\x31\x32\x36\x32\x33\x30\x30\x30\x30\x5a\x30\x27\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x45\x31\x18\x30\x16\x06\x03\x55\x04\x03\x13\x0f\x42\x65\x6c\x67\x69\x75\x6d\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xc8\xa1\x71\xe9\x1c\x46\x42\x79\x78\x71\x6f\x9d\xae\xa9\xa8\xab\x28\xb7\x4d\xc7\x20\xeb\x30\x91\x5a\x75\xf5\xe2\xd2\xcf\xc8\x4c\x14\x98\x42\x58\xad\xc7\x11\xc5\x40\x40\x6a\x5a\xf9\x74\x12\x27\x87\xe9\x9c\xe5\x71\x4e\x22\x2c\xd1\x12\x18\xaa\x30\x5e\xa2\x21\xb9\xd9\xbb\xff\xf6\x74\xeb\x31\x01\xe7\x3b\x7e\x58\x0f\x91\x16\x4d\x76\x89\xa8\x01\x4f\xad\x22\x66\x70\xfa\x4b\x1d\x95\xc1\x30\x58\xea\xbc\xd9\x65\xd8\x9a\xb4\x88\xeb\x49\x46\x52\xdf\xd2\x53\x15\x76\xcb\x14\x5d\x19\x49\xb1\x6f\x6a\xd3\xd3\xfd\xbc\xc2\x2d\xec\x45\x3f\x09\x3f\x58\xbe\xfc\xd4\xef\x00\x8c\x81\x35\x72\xbf\xf7\x18\xea\x96\x62\x7d\x2b\x28\x7f\x15\x6c\x63\xd2\xca\xca\x7d\x05\xac\xc8\x6d\x07\x6d\x32\xbe\x68\xb8\x05\x40\xae\x54\x98\x56\x3e\x66\xf1\x30\xe8\xef\xc4\xab\x93\x5e\x07\xde\x32\x8f\x12\x74\xaa\x5b\x34\x23\x54\xc0\xea\x6c\xce\xfe\x36\x92\xa8\x09\x17\xea\xa1\x2d\xcf\x6c\xe3\x84\x1d\xde\x87\x2e\x33\x0b\x3c\x74\xe2\x21\x50\x38\x95\x2e\x5c\xe0\xe5\xc6\x31\xf9\xdb\x40\xfa\x6a\xa1\xa4\x8a\x93\x9b\xa7\x21\x06\x87\x1d\x27\xd3\xc4\xa1\xc9\x4c\xb0\x6f\x02\x03\x01\x00\x01\xa3\x81\xbb\x30\x81\xb8\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x42\x06\x03\x55\x1d\x20\x04\x3b\x30\x39\x30\x37\x06\x05\x60\x38\x01\x01\x01\x30\x2e\x30\x2c\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x20\x68\x74\x74\x70\x3a\x2f\x2f\x72\x65\x70\x6f\x73\x69\x74\x6f\x72\x79\x2e\x65\x69\x64\x2e\x62\x65\x6c\x67\x69\x75\x6d\x2e\x62\x65\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x10\xf0\x0c\x56\x9b\x61\xea\x57\x3a\xb6\x35\x97\x6d\x9f\xdd\xb9\x14\x8e\xdb\xe6\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x10\xf0\x0c\x56\x9b\x61\xea\x57\x3a\xb6\x35\x97\x6d\x9f\xdd\xb9\x14\x8e\xdb\xe6\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xc8\x6d\x22\x51\x8a\x61\xf8\x0f\x96\x6e\xd5\x20\xb2\x81\xf8\xc6\xdc\xa3\x16\x00\xda\xcd\x6a\xe7\x6b\x2a\xfa\x59\x48\xa7\x4c\x49\x37\xd7\x73\xa1\x6a\x01\x65\x5e\x32\xbd\xe7\x97\xd3\xd0\x2e\x3c\x73\xd3\x8c\x7b\x83\xef\xd6\x42\xc1\x3f\xa8\xa9\x5d\x0f\x37\xba\x76\xd2\x40\xbd\xcc\x2d\x3f\xd3\x44\x41\x49\x9c\xfd\x5b\x29\xf4\x02\x23\x22\x5b\x71\x1b\xbf\x58\xd9\x28\x4e\x2d\x45\xf4\xda\xe7\xb5\x63\x45\x44\x11\x0d\x2a\x7f\x33\x7f\x36\x49\xb4\xce\x6e\xa9\x02\x31\xae\x5c\xfd\xc8\x89\xbf\x42\x7b\xd7\xf1\x60\xf2\xd7\x87\xf6\x57\x2e\x7a\x7e\x6a\x13\x80\x1d\xdc\xe3\xd0\x63\x1e\x3d\x71\x31\xb1\x60\xd4\x9e\x08\xca\xab\xf0\x94\xc7\x48\x75\x54\x81\xf3\x1b\xad\x77\x9c\xe8\xb2\x8f\xdb\x83\xac\x8f\x34\x6b\xe8\xbf\xc3\xd9\xf5\x43\xc3\x64\x55\xeb\x1a\xbd\x36\x86\x36\xba\x21\x8c\x97\x1a\x21\xd4\xea\x2d\x3b\xac\xba\xec\xa7\x1d\xab\xbe\xb9\x4a\x9b\x35\x2f\x1c\x5c\x1d\x51\xa7\x1f\x54\xed\x12\x97\xff\xf2\x6e\x87\x7d\x46\xc9\x74\xd6\xef\xeb\x3d\x7d\xe6\x59\x6e\x06\x94\x04\xe4\xa2\x55\x87\x38\x28\x6a\x22\x5e\xe2\xbe\x74\x12\xb0\x04\x43\x2a", 0 }, + /* Anchor: 27 belgiumrca2.crt serial: #{a.serial.to_s} + C=BE,CN=Belgium Root CA2 + */ + { 914, "\x30\x82\x03\x8e\x30\x82\x02\x76\xa0\x03\x02\x01\x02\x02\x08\x2a\xff\xbe\x9f\xa2\xf0\xe9\x87\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x28\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x45\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x42\x65\x6c\x67\x69\x75\x6d\x20\x52\x6f\x6f\x74\x20\x43\x41\x32\x30\x1e\x17\x0d\x30\x37\x31\x30\x30\x34\x31\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x31\x31\x32\x31\x35\x30\x38\x30\x30\x30\x30\x5a\x30\x28\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x45\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x42\x65\x6c\x67\x69\x75\x6d\x20\x52\x6f\x6f\x74\x20\x43\x41\x32\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xc6\x73\x42\x1e\x92\xff\x75\x0f\x8b\xbf\x74\x86\xa7\x3f\xed\xb2\x18\x2d\x2d\x97\xf9\xa9\xfb\x98\x4a\x23\xdf\xd5\x8d\xe0\x8c\xc6\x32\x1c\x16\x2d\x07\x42\xd6\x2d\xb6\x6e\x2f\xa7\xf5\xfc\xc6\x85\x82\x5d\x95\xde\xb5\x22\x00\xcc\xa8\x53\x40\x9f\xaf\x0a\x35\xa2\x7a\xc7\xe1\xca\xf7\x60\x10\x67\x0e\xa7\x50\x73\x17\x53\x95\x9f\x22\x9f\x0c\x5d\x6f\xb6\x41\xbc\x8c\xeb\xda\x1d\x46\xbd\xa7\x94\xbf\xf3\x1a\xcb\xd4\xfb\x8d\x0e\x1e\x33\xc8\x96\xd7\xec\x8c\x53\xde\x93\x1e\x34\x1e\x8a\x50\x71\x26\x58\xb4\x5d\xc2\x88\x89\xda\x60\xd2\x89\x21\x3f\xde\xd7\x01\x18\x36\x6e\xe1\x2c\x70\x03\x04\x65\xef\x98\x06\x2b\x5d\x1e\x62\xdc\x55\x6b\xfe\x66\x64\x21\x5f\xf8\x2f\xe1\xd7\x9b\x29\xaf\x6f\xcd\x9f\xaa\x0c\x46\xd1\x88\xc5\x9d\xa2\x95\x9f\xac\x3f\x15\xae\xf2\x61\xdf\xef\xc3\x6b\x9a\x22\xd8\x2c\x71\xfd\x58\x1d\xec\x00\xa4\x38\x20\x95\x5a\xc7\xd5\x37\x63\xba\x4f\x9b\xaa\xfe\x56\x46\x2e\x63\xd9\x0b\x23\xd5\x8a\xfa\xb5\x23\xf0\x89\x1b\xa1\x14\x0d\x26\xda\x41\xf0\x38\x8f\x30\xed\x05\x26\x79\xc1\x4b\x4e\xa1\xb8\x7e\x55\x52\x3a\x69\x46\x84\x75\x02\x03\x01\x00\x01\xa3\x81\xbb\x30\x81\xb8\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x42\x06\x03\x55\x1d\x20\x04\x3b\x30\x39\x30\x37\x06\x05\x60\x38\x09\x01\x01\x30\x2e\x30\x2c\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x20\x68\x74\x74\x70\x3a\x2f\x2f\x72\x65\x70\x6f\x73\x69\x74\x6f\x72\x79\x2e\x65\x69\x64\x2e\x62\x65\x6c\x67\x69\x75\x6d\x2e\x62\x65\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x85\x8a\xeb\xf4\xc5\xbb\xbe\x0e\x59\x03\x94\xde\xd6\x80\x01\x15\xe3\x10\x9c\x39\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x85\x8a\xeb\xf4\xc5\xbb\xbe\x0e\x59\x03\x94\xde\xd6\x80\x01\x15\xe3\x10\x9c\x39\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x51\xd8\x85\xdd\xbb\x57\x6f\xcc\xa0\x6c\xb5\xa3\x20\x9c\x53\x09\xf3\x4a\x01\x0c\x74\xbf\x2b\xb3\x9a\x9a\xba\x18\xf2\x0b\x88\xac\x1c\xb3\x33\xaf\xce\xe5\x13\x01\x27\x92\x84\x58\x9a\x10\xb9\xf7\xcc\x14\x92\x6b\x74\x16\x8a\x96\xe8\x51\xef\xbf\xfa\x4a\x25\xa7\x89\xb6\x63\x2b\x5d\x94\x58\xd1\xcf\x11\x72\xb6\x1e\xb9\x39\x41\x16\x4d\x29\xbc\x35\x53\x0b\xda\xde\x8e\x0e\xcd\xa9\x95\x77\x25\xca\x94\x5a\xe9\xb2\x69\xae\xd8\xc0\x13\xbe\x98\xfc\x96\x9c\x84\x7f\x55\x13\xe6\x3c\x87\xe3\xbc\x20\xa4\xa4\x36\x68\x6b\x4d\x60\x66\x1c\xf9\xbf\xac\x80\x94\x66\x2e\xb9\x41\x8a\xd3\x65\xd3\x84\x80\x02\xef\x50\x1d\x5e\x46\xdc\xf7\xc9\xba\xb5\x34\x7c\x2a\xf3\xc6\xd8\x5f\x5f\x54\x9d\xdb\x4d\xcd\x11\xe7\xfd\x14\x02\x83\x66\x5e\xc8\xa6\x00\x12\xa0\x5f\xbe\xce\x14\xfe\xbb\x1f\xa7\x61\xf7\xab\x4a\xf1\x06\x14\x9f\xca\x49\x42\xc2\xa9\xbc\xed\x85\xb1\xab\x81\x41\xe6\x0d\xc5\x42\x69\x53\x87\x39\x9d\x4c\x1f\x00\x0e\x3e\x07\x0d\x75\x57\x44\xa8\x53\xb4\x36\x76\x64\x99\xdc\x6e\xeb\x3d\x46\x6e\x14\x5d\x5e\x47\x53\x8d\x78\x4d\xe0\x27\xbb\x8e\x85\x76", 0 }, + /* Anchor: 28 BIT-Admin-Root-CA.crt serial: #{a.serial.to_s} + C=ch,O=admin,OU=Services,OU=Certification Authorities,CN=Admin-Root-CA + */ + { 1369, "\x30\x82\x05\x55\x30\x82\x04\x3d\xa0\x03\x02\x01\x02\x02\x04\x3b\xf3\x81\xd0\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x6c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x63\x68\x31\x0e\x30\x0c\x06\x03\x55\x04\x0a\x13\x05\x61\x64\x6d\x69\x6e\x31\x11\x30\x0f\x06\x03\x55\x04\x0b\x13\x08\x53\x65\x72\x76\x69\x63\x65\x73\x31\x22\x30\x20\x06\x03\x55\x04\x0b\x13\x19\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x69\x65\x73\x31\x16\x30\x14\x06\x03\x55\x04\x03\x13\x0d\x41\x64\x6d\x69\x6e\x2d\x52\x6f\x6f\x74\x2d\x43\x41\x30\x1e\x17\x0d\x30\x31\x31\x31\x31\x35\x30\x38\x35\x31\x30\x37\x5a\x17\x0d\x32\x31\x31\x31\x31\x30\x30\x37\x35\x31\x30\x37\x5a\x30\x6c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x63\x68\x31\x0e\x30\x0c\x06\x03\x55\x04\x0a\x13\x05\x61\x64\x6d\x69\x6e\x31\x11\x30\x0f\x06\x03\x55\x04\x0b\x13\x08\x53\x65\x72\x76\x69\x63\x65\x73\x31\x22\x30\x20\x06\x03\x55\x04\x0b\x13\x19\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x69\x65\x73\x31\x16\x30\x14\x06\x03\x55\x04\x03\x13\x0d\x41\x64\x6d\x69\x6e\x2d\x52\x6f\x6f\x74\x2d\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xcb\xe0\xaf\x44\x14\x22\xfe\x6a\x17\x49\xf2\x5d\x9d\xcf\x5c\x02\x62\x0b\x80\xb9\x5a\xbf\xa8\x55\x33\x7b\xa3\x12\x24\x5e\x4c\x6f\x3b\x41\x89\x4e\x83\x3d\x9f\xb3\x95\x26\x34\xa6\xcc\x12\xf4\xcc\x9d\x87\x5e\x3d\x0c\x0d\x17\x2f\x85\x26\x3e\x2a\x26\x59\x73\xa1\xa8\xbc\x3b\xeb\xe5\x46\xb8\xf3\x59\x7b\x20\xb1\x5e\x40\x01\x6d\xba\x67\xb3\x6b\xeb\xef\xc5\xe2\xf9\x35\xdd\x0c\x6a\x06\xb6\x9a\x28\x9a\x70\xb3\x40\x29\x76\xc0\x71\x46\x11\x6b\x43\xaf\xe5\x56\x41\xfb\xe6\x1c\x39\x83\x4d\xb7\xf6\xa2\xb1\x66\xc9\xa8\x0d\xb2\xf0\x77\xbe\x36\xc1\x20\x27\x32\xb9\xcc\xd7\x5a\xca\xf6\x17\x41\x36\x4d\xfb\xbb\x55\x81\x63\x9c\x93\x5e\x83\x6b\x7f\xb8\x15\x77\x72\x7c\x7d\x4d\x09\x6b\x59\x95\xe6\xed\x30\xab\x44\x46\xd9\x15\x01\xa5\x5b\x89\x65\xb6\xe0\x28\xd9\x28\x08\x95\x7e\x08\x23\xb2\x22\xe8\xdf\x25\x4c\x3c\x68\xf7\x6e\xe7\x4b\xc7\x90\xfd\x84\x41\x26\xbe\x5c\x83\x3a\xd7\x23\x79\xb7\x1a\xf8\x07\x19\x82\x5a\x69\x58\xc5\xff\x88\x72\x2b\xc7\xbe\xf8\xd3\x2d\x33\x77\xa7\x16\x12\xa8\x8b\x21\xc6\x42\xae\x7a\x64\xaf\xf2\xb3\xc0\xed\x77\xe4\x69\x02\x03\x01\x00\x01\xa3\x82\x01\xfd\x30\x82\x01\xf9\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x81\x99\x06\x03\x55\x1d\x20\x04\x81\x91\x30\x81\x8e\x30\x81\x8b\x06\x08\x60\x85\x74\x01\x11\x03\x01\x00\x30\x7f\x30\x2b\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x02\x30\x1f\x1a\x1d\x54\x68\x69\x73\x20\x69\x73\x20\x74\x68\x65\x20\x41\x64\x6d\x69\x6e\x2d\x52\x6f\x6f\x74\x2d\x43\x41\x20\x43\x50\x53\x30\x50\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x44\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x66\x6f\x72\x6d\x61\x74\x69\x6b\x2e\x61\x64\x6d\x69\x6e\x2e\x63\x68\x2f\x50\x4b\x49\x2f\x6c\x69\x6e\x6b\x73\x2f\x43\x50\x53\x5f\x32\x5f\x31\x36\x5f\x37\x35\x36\x5f\x31\x5f\x31\x37\x5f\x33\x5f\x31\x5f\x30\x2e\x70\x64\x66\x30\x7f\x06\x03\x55\x1d\x1f\x04\x78\x30\x76\x30\x74\xa0\x72\xa0\x70\xa4\x6e\x30\x6c\x31\x16\x30\x14\x06\x03\x55\x04\x03\x13\x0d\x41\x64\x6d\x69\x6e\x2d\x52\x6f\x6f\x74\x2d\x43\x41\x31\x22\x30\x20\x06\x03\x55\x04\x0b\x13\x19\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x69\x65\x73\x31\x11\x30\x0f\x06\x03\x55\x04\x0b\x13\x08\x53\x65\x72\x76\x69\x63\x65\x73\x31\x0e\x30\x0c\x06\x03\x55\x04\x0a\x13\x05\x61\x64\x6d\x69\x6e\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x63\x68\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x82\x9f\xfa\x23\x73\x20\xf1\x97\x8b\xb2\x4c\x4d\xbe\x42\xc5\x7f\x66\xcd\x64\xe8\x30\x81\x99\x06\x03\x55\x1d\x23\x04\x81\x91\x30\x81\x8e\x80\x14\x82\x9f\xfa\x23\x73\x20\xf1\x97\x8b\xb2\x4c\x4d\xbe\x42\xc5\x7f\x66\xcd\x64\xe8\xa1\x70\xa4\x6e\x30\x6c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x63\x68\x31\x0e\x30\x0c\x06\x03\x55\x04\x0a\x13\x05\x61\x64\x6d\x69\x6e\x31\x11\x30\x0f\x06\x03\x55\x04\x0b\x13\x08\x53\x65\x72\x76\x69\x63\x65\x73\x31\x22\x30\x20\x06\x03\x55\x04\x0b\x13\x19\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x69\x65\x73\x31\x16\x30\x14\x06\x03\x55\x04\x03\x13\x0d\x41\x64\x6d\x69\x6e\x2d\x52\x6f\x6f\x74\x2d\x43\x41\x82\x04\x3b\xf3\x81\xd0\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x78\x4f\x7a\x5c\x26\x11\xa7\x2e\xae\x9a\x43\xca\x5c\x35\x82\x46\x7e\xc8\x36\x8f\x7a\x66\xb5\xa9\x32\x08\x1c\x0c\xe4\x6e\xa1\xf1\xc8\xc1\xd4\xe4\x80\xe7\x8c\xbd\x63\xb1\x0c\xdf\xf2\xb9\x3e\xc2\x0b\x71\x40\x69\x46\xa3\x6c\xf4\x5b\x0f\x0d\x21\x44\xc7\x2a\x2b\x3d\x1a\x0b\xc0\xa0\xc1\xcc\x88\xca\x1c\x3f\xac\x52\xb6\xf6\x67\xcd\x4c\x6d\xc4\xbe\x23\xfd\x41\x2b\x04\x6e\x77\xa5\x16\x78\xe9\x9b\x5c\x23\xcf\x81\x1a\x06\x21\x63\x6a\xdc\x29\x51\xb2\x3a\xf9\x9b\xf7\x5d\xb1\x2d\xf5\x04\x17\x06\x7f\x9c\xe8\x37\x85\x2d\xee\x31\xbc\x2e\x01\xf8\xc4\xeb\x6b\x8e\x34\xc5\x39\x39\xf6\x94\x98\xbb\x1f\x0e\x1e\x11\x2f\xa8\x8c\x07\x0a\x48\xa2\x8c\x6a\x99\x85\x34\xb7\x2a\x61\x85\x78\x1a\x29\x69\x1f\x9d\x25\x50\x51\x04\xca\x17\xc3\x39\x38\x07\x71\xe7\xd1\x98\x9b\xd5\xd1\x18\x15\x96\xbc\xe2\xf3\xc9\x67\x2b\xf1\x09\xb2\xce\x9c\xf4\x43\x26\x01\xfa\x57\x6b\x90\xa9\xb1\xbe\xe8\x35\xd5\x69\xff\xf0\x39\x15\x4e\xbc\x5f\xf0\xcf\x3b\xf4\xbe\x23\x3f\x45\x66\xc4\xb4\x96\x5d\xbe\x8f\x0d\xde\xc7\x6d\x09\x42\xf3\x89\xf9\xf1\x3f\xf5\x74\x4f\xdf\xb8\x65", 0 }, + /* Anchor: 29 BIT-AdminCA-CD-T01.crt serial: #{a.serial.to_s} + C=CH,O=admin,OU=Services,OU=Certification Authorities,CN=AdminCA-CD-T01 + */ + { 1105, "\x30\x82\x04\x4d\x30\x82\x03\x35\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x6d\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x0e\x30\x0c\x06\x03\x55\x04\x0a\x13\x05\x61\x64\x6d\x69\x6e\x31\x11\x30\x0f\x06\x03\x55\x04\x0b\x13\x08\x53\x65\x72\x76\x69\x63\x65\x73\x31\x22\x30\x20\x06\x03\x55\x04\x0b\x13\x19\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x69\x65\x73\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0e\x41\x64\x6d\x69\x6e\x43\x41\x2d\x43\x44\x2d\x54\x30\x31\x30\x1e\x17\x0d\x30\x36\x30\x31\x32\x35\x31\x33\x33\x36\x31\x39\x5a\x17\x0d\x31\x36\x30\x31\x32\x35\x31\x32\x33\x36\x31\x39\x5a\x30\x6d\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x0e\x30\x0c\x06\x03\x55\x04\x0a\x13\x05\x61\x64\x6d\x69\x6e\x31\x11\x30\x0f\x06\x03\x55\x04\x0b\x13\x08\x53\x65\x72\x76\x69\x63\x65\x73\x31\x22\x30\x20\x06\x03\x55\x04\x0b\x13\x19\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x69\x65\x73\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0e\x41\x64\x6d\x69\x6e\x43\x41\x2d\x43\x44\x2d\x54\x30\x31\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xd2\x34\x25\x31\x99\xa9\x2c\x38\x55\xf8\x63\x51\xf5\x30\x28\x48\xd9\x5e\x26\x04\x01\xe3\x10\x17\x24\x42\xd0\x7f\x9f\xf2\x48\xc7\xe8\x14\x0e\x0c\x9a\x32\xaa\x61\x74\x24\x07\xa3\x06\x3e\xe4\x0a\xc1\x1f\x57\x45\x14\x8f\x7f\xad\x6f\xa9\xbf\x18\x3e\xc7\x63\x46\x68\x29\x6f\x21\xc1\x71\x47\x79\xb7\x43\x7c\x45\x7e\xb0\x45\x95\x27\x3c\xc5\xbe\x6c\x20\xa8\xd9\x5a\x80\x53\x85\xc5\x6e\x79\x5c\xda\x01\xca\x69\xa9\xb4\xc1\xd4\xed\x6c\x14\xd7\x12\x4b\xf4\x89\xe2\x07\x7f\x10\x9f\x17\x15\xea\x4a\xc4\xab\xeb\x42\x24\x17\xfd\xbf\xc5\xba\xc0\x81\x5f\xd0\x0f\x9c\x87\x93\xa2\x1e\xf1\xf7\x80\x55\x6c\x22\xe5\x4b\x5a\x16\xab\x6e\xe0\xb8\x85\x12\x1d\x90\x33\x2c\x6c\x3b\x2c\xf5\x39\xcb\xca\xce\x43\x36\x83\xce\xf7\xb7\x28\x84\xee\x3c\xcc\x81\x93\xfe\x5b\x0d\xed\x89\xb9\x36\x17\xdf\x9e\xe9\x97\xa2\x07\x7e\xd3\x2c\xe9\x95\xb6\xf8\x29\x9a\xbc\x2c\xe1\xf8\x88\xac\x53\x57\x11\x84\x96\x05\x5a\xd4\x4d\xb9\xfc\xd5\x4e\x3b\xc9\x6c\xce\x81\xfe\x5f\x10\x73\xf4\xed\xb4\x55\xe5\x03\x82\xcc\x29\xbd\xf6\xa3\x62\x9a\xc6\xcb\xe8\x21\xbb\x9d\x3e\xfc\x09\x02\x03\x01\x00\x01\xa3\x81\xf7\x30\x81\xf4\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01\x00\x30\x81\xae\x06\x03\x55\x1d\x20\x04\x81\xa6\x30\x81\xa3\x30\x81\xa0\x06\x08\x60\x85\x74\x01\x11\x03\x15\x01\x30\x81\x93\x30\x48\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x02\x30\x3c\x1a\x3a\x54\x68\x69\x73\x20\x69\x73\x20\x74\x68\x65\x20\x41\x64\x6d\x69\x6e\x43\x41\x2d\x43\x44\x2d\x54\x30\x31\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x50\x72\x61\x63\x74\x69\x63\x65\x20\x53\x74\x61\x74\x65\x6d\x65\x6e\x74\x2e\x30\x47\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x3b\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x70\x6b\x69\x2e\x61\x64\x6d\x69\x6e\x2e\x63\x68\x2f\x70\x6f\x6c\x69\x63\x79\x2f\x43\x50\x53\x5f\x32\x5f\x31\x36\x5f\x37\x35\x36\x5f\x31\x5f\x31\x37\x5f\x33\x5f\x32\x31\x5f\x31\x2e\x70\x64\x66\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x2a\xc4\x69\x0a\xa1\xc6\x55\xc6\x03\x6e\x70\xce\x86\x81\xb3\xa4\x0f\xaa\x19\xdb\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x9f\x7e\x7a\x6d\xbb\xac\x8c\x8e\x60\x94\x65\xd1\x43\x50\xd1\xbf\x6d\x6a\x41\xfd\x12\xe2\xcd\xc6\x1f\x26\x66\xed\xca\x9d\x3a\x41\x65\x78\xce\xf4\x02\xb0\x53\xfa\x43\x8f\xe4\xd9\xbb\xae\x54\x80\x17\x25\x60\x12\x49\x81\x74\xe8\x3b\xb3\xdb\x65\x5c\x29\x54\xc9\xe6\x45\x9e\x9e\x94\x11\x84\x54\x72\x28\xcf\x37\xc0\xf5\x55\xa3\x51\x2b\xa3\xc8\x50\xe6\xe9\x0c\x14\x13\xd0\x2f\xa4\x01\xfc\x46\xf7\x3e\x2f\xdb\xd4\xf4\x4b\x14\xf8\xb2\x00\x1d\x0b\xfc\x50\x17\x2b\xf9\xf0\x5a\x7d\x6c\xf9\xfb\xa3\x0b\x8a\xc0\xa7\x32\x08\x7d\x57\x4b\x28\xbf\x06\x9e\x17\x14\x42\xe5\x2c\xe6\xa2\x80\x16\x4e\xff\x0f\x9d\x3c\x1c\xf8\x15\xc2\x52\x75\x98\xd4\xf8\x16\x89\xd0\x4d\xe7\x28\x08\xc7\x95\x28\x4e\xe6\x8b\x81\x49\x99\xda\x27\x3d\xe9\xfa\x79\x30\xd9\x6c\xa8\xdf\xab\x3a\x1b\x10\x8a\xd1\x76\xe4\x48\xfe\x39\x8a\x78\x88\x1b\x81\x66\xc3\x06\x64\xa2\x76\x05\xca\x94\x27\xb4\x76\xf1\xda\x82\xfb\xb5\x44\x10\x63\x43\xc3\xa3\xc6\xc6\x04\xc7\x0f\xcb\xf1\xb6\x8f\xe7\x5c\x8a\xa6\x51\x96\xc9\xdf\x80\xcc\xb5\xd1\x20\xb3\x43\xd3\x14\xc7\xdd\xb1\x50\x6d\x95\x7a", 0 }, + /* Anchor: 30 BTCTRT.cer serial: #{a.serial.to_s} + C=IE,O=Baltimore,OU=CyberTrust,CN=Baltimore CyberTrust Root + */ + { 891, "\x30\x82\x03\x77\x30\x82\x02\x5f\xa0\x03\x02\x01\x02\x02\x04\x02\x00\x00\xb9\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x5a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x45\x31\x12\x30\x10\x06\x03\x55\x04\x0a\x13\x09\x42\x61\x6c\x74\x69\x6d\x6f\x72\x65\x31\x13\x30\x11\x06\x03\x55\x04\x0b\x13\x0a\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x42\x61\x6c\x74\x69\x6d\x6f\x72\x65\x20\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x20\x52\x6f\x6f\x74\x30\x1e\x17\x0d\x30\x30\x30\x35\x31\x32\x31\x38\x34\x36\x30\x30\x5a\x17\x0d\x32\x35\x30\x35\x31\x32\x32\x33\x35\x39\x30\x30\x5a\x30\x5a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x45\x31\x12\x30\x10\x06\x03\x55\x04\x0a\x13\x09\x42\x61\x6c\x74\x69\x6d\x6f\x72\x65\x31\x13\x30\x11\x06\x03\x55\x04\x0b\x13\x0a\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x42\x61\x6c\x74\x69\x6d\x6f\x72\x65\x20\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x20\x52\x6f\x6f\x74\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xa3\x04\xbb\x22\xab\x98\x3d\x57\xe8\x26\x72\x9a\xb5\x79\xd4\x29\xe2\xe1\xe8\x95\x80\xb1\xb0\xe3\x5b\x8e\x2b\x29\x9a\x64\xdf\xa1\x5d\xed\xb0\x09\x05\x6d\xdb\x28\x2e\xce\x62\xa2\x62\xfe\xb4\x88\xda\x12\xeb\x38\xeb\x21\x9d\xc0\x41\x2b\x01\x52\x7b\x88\x77\xd3\x1c\x8f\xc7\xba\xb9\x88\xb5\x6a\x09\xe7\x73\xe8\x11\x40\xa7\xd1\xcc\xca\x62\x8d\x2d\xe5\x8f\x0b\xa6\x50\xd2\xa8\x50\xc3\x28\xea\xf5\xab\x25\x87\x8a\x9a\x96\x1c\xa9\x67\xb8\x3f\x0c\xd5\xf7\xf9\x52\x13\x2f\xc2\x1b\xd5\x70\x70\xf0\x8f\xc0\x12\xca\x06\xcb\x9a\xe1\xd9\xca\x33\x7a\x77\xd6\xf8\xec\xb9\xf1\x68\x44\x42\x48\x13\xd2\xc0\xc2\xa4\xae\x5e\x60\xfe\xb6\xa6\x05\xfc\xb4\xdd\x07\x59\x02\xd4\x59\x18\x98\x63\xf5\xa5\x63\xe0\x90\x0c\x7d\x5d\xb2\x06\x7a\xf3\x85\xea\xeb\xd4\x03\xae\x5e\x84\x3e\x5f\xff\x15\xed\x69\xbc\xf9\x39\x36\x72\x75\xcf\x77\x52\x4d\xf3\xc9\x90\x2c\xb9\x3d\xe5\xc9\x23\x53\x3f\x1f\x24\x98\x21\x5c\x07\x99\x29\xbd\xc6\x3a\xec\xe7\x6e\x86\x3a\x6b\x97\x74\x63\x33\xbd\x68\x18\x31\xf0\x78\x8d\x76\xbf\xfc\x9e\x8e\x5d\x2a\x86\xa7\x4d\x90\xdc\x27\x1a\x39\x02\x03\x01\x00\x01\xa3\x45\x30\x43\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xe5\x9d\x59\x30\x82\x47\x58\xcc\xac\xfa\x08\x54\x36\x86\x7b\x3a\xb5\x04\x4d\xf0\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01\x03\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x85\x0c\x5d\x8e\xe4\x6f\x51\x68\x42\x05\xa0\xdd\xbb\x4f\x27\x25\x84\x03\xbd\xf7\x64\xfd\x2d\xd7\x30\xe3\xa4\x10\x17\xeb\xda\x29\x29\xb6\x79\x3f\x76\xf6\x19\x13\x23\xb8\x10\x0a\xf9\x58\xa4\xd4\x61\x70\xbd\x04\x61\x6a\x12\x8a\x17\xd5\x0a\xbd\xc5\xbc\x30\x7c\xd6\xe9\x0c\x25\x8d\x86\x40\x4f\xec\xcc\xa3\x7e\x38\xc6\x37\x11\x4f\xed\xdd\x68\x31\x8e\x4c\xd2\xb3\x01\x74\xee\xbe\x75\x5e\x07\x48\x1a\x7f\x70\xff\x16\x5c\x84\xc0\x79\x85\xb8\x05\xfd\x7f\xbe\x65\x11\xa3\x0f\xc0\x02\xb4\xf8\x52\x37\x39\x04\xd5\xa9\x31\x7a\x18\xbf\xa0\x2a\xf4\x12\x99\xf7\xa3\x45\x82\xe3\x3c\x5e\xf5\x9d\x9e\xb5\xc8\x9e\x7c\x2e\xc8\xa4\x9e\x4e\x08\x14\x4b\x6d\xfd\x70\x6d\x6b\x1a\x63\xbd\x64\xe6\x1f\xb7\xce\xf0\xf2\x9f\x2e\xbb\x1b\xb7\xf2\x50\x88\x73\x92\xc2\xe2\xe3\x16\x8d\x9a\x32\x02\xab\x8e\x18\xdd\xe9\x10\x11\xee\x7e\x35\xab\x90\xaf\x3e\x30\x94\x7a\xd0\x33\x3d\xa7\x65\x0f\xf5\xfc\x8e\x9e\x62\xcf\x47\x44\x2c\x01\x5d\xbb\x1d\xb5\x32\xd2\x47\xd2\x38\x2e\xd0\xfe\x81\xdc\x32\x6a\x1e\xb5\xee\x3c\xd5\xfc\xe7\x81\x1d\x19\xc3\x24\x42\xea\x63\x39\xa9", 0 }, + /* Anchor: 31 BuypassClass2CA1.cer serial: #{a.serial.to_s} + C=NO,O=Buypass AS-983163327,CN=Buypass Class 2 CA 1 + */ + { 855, "\x30\x82\x03\x53\x30\x82\x02\x3b\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x4b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4e\x4f\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x0c\x14\x42\x75\x79\x70\x61\x73\x73\x20\x41\x53\x2d\x39\x38\x33\x31\x36\x33\x33\x32\x37\x31\x1d\x30\x1b\x06\x03\x55\x04\x03\x0c\x14\x42\x75\x79\x70\x61\x73\x73\x20\x43\x6c\x61\x73\x73\x20\x32\x20\x43\x41\x20\x31\x30\x1e\x17\x0d\x30\x36\x31\x30\x31\x33\x31\x30\x32\x35\x30\x39\x5a\x17\x0d\x31\x36\x31\x30\x31\x33\x31\x30\x32\x35\x30\x39\x5a\x30\x4b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4e\x4f\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x0c\x14\x42\x75\x79\x70\x61\x73\x73\x20\x41\x53\x2d\x39\x38\x33\x31\x36\x33\x33\x32\x37\x31\x1d\x30\x1b\x06\x03\x55\x04\x03\x0c\x14\x42\x75\x79\x70\x61\x73\x73\x20\x43\x6c\x61\x73\x73\x20\x32\x20\x43\x41\x20\x31\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\x8b\x3c\x07\x45\xd8\xf6\xdf\xe6\xc7\xca\xba\x8d\x43\xc5\x47\x8d\xb0\x5a\xc1\x38\xdb\x92\x84\x1c\xaf\x13\xd4\x0f\x6f\x36\x46\x20\xc4\x2e\xcc\x71\x70\x34\xa2\x34\xd3\x37\x2e\xd8\xdd\x3a\x77\x2f\xc0\xeb\x29\xe8\x5c\xd2\xb5\xa9\x91\x34\x87\x22\x59\xfe\xcc\xdb\xe7\x99\xaf\x96\xc1\xa8\xc7\x40\xdd\xa5\x15\x8c\x6e\xc8\x7c\x97\x03\xcb\xe6\x20\xf2\xd7\x97\x5f\x31\xa1\x2f\x37\xd2\xbe\xee\xbe\xa9\xad\xa8\x4c\x9e\x21\x66\x43\x3b\xa8\xbc\xf3\x09\xa3\x38\xd5\x59\x24\xc1\xc2\x47\x76\xb1\x88\x5c\x82\x3b\xbb\x2b\xa6\x04\xd7\x8c\x07\x8f\xcd\xd5\x41\x1d\xf0\xae\xb8\x29\x2c\x94\x52\x60\x34\x94\x3b\xda\xe0\x38\xd1\x9d\x33\x3e\x15\xf4\x93\x32\xc5\x00\xda\xb5\x29\x66\x0e\x3a\x78\x0f\x21\x52\x5f\x02\xe5\x92\x7b\x25\xd3\x92\x1e\x2f\x15\x9d\x81\xe4\x9d\x8e\xe8\xef\x89\xce\x14\x4c\x54\x1d\x1c\x81\x12\x4d\x70\xa8\xbe\x10\x05\x17\x7e\x1f\xd1\xb8\x57\x55\xed\xcd\xbb\x52\xc2\xb0\x1e\x78\xc2\x4d\x36\x68\xcb\x56\x26\xc1\x52\xc1\xbd\x76\xf7\x58\xd5\x72\x7e\x1f\x44\x76\xbb\x00\x89\x1d\x16\x9d\x51\x35\xef\x4d\xc2\x56\xef\x6b\xe0\x8c\x3b\x0d\xe9\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x3f\x8d\x9a\x59\x8b\xfc\x7b\x7b\x9c\xa3\xaf\x38\xb0\x39\xed\x90\x71\x80\xd6\xc8\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x15\x1a\x7e\x13\x8a\xb9\xe8\x07\xa3\x4b\x27\x32\xb2\x40\x91\xf2\x21\xd1\x64\x85\xbe\x63\x6a\xd2\xcf\x81\xc2\x15\xd5\x7a\x7e\x0c\x29\xac\x37\x1e\x1c\x7c\x76\x52\x95\xda\xb5\x7f\x23\xa1\x29\x77\x65\xc9\x32\x9d\xa8\x2e\x56\xab\x60\x76\xce\x16\xb4\x8d\x7f\x78\xc0\xd5\x99\x51\x83\x7f\x5e\xd9\xbe\x0c\xa8\x50\xed\x22\xc7\xad\x05\x4c\x76\xfb\xed\xee\x1e\x47\x64\xf6\xf7\x27\x7d\x5c\x28\x0f\x45\xc5\x5c\x62\x5e\xa6\x9a\x91\x91\xb7\x53\x17\x2e\xdc\xad\x60\x9d\x96\x64\x39\xbd\x67\x68\xb2\xae\x05\xcb\x4d\xe7\x5f\x1f\x57\x86\xd5\x20\x9c\x28\xfb\x6f\x13\x38\xf5\xf6\x11\x92\xf6\x7d\x99\x5e\x1f\x0c\xe8\xab\x44\x24\x29\x72\x40\x3d\x36\x52\xaf\x8c\x58\x90\x73\xc1\xec\x61\x2c\x79\xa1\xec\x87\xb5\x3f\xda\x4d\xd9\x21\x00\x30\xde\x90\xda\x0e\xd3\x1a\x48\xa9\x3e\x85\x0b\x14\x8b\x8c\xbc\x41\x9e\x6a\xf7\x0e\x70\xc0\x35\xf7\x39\xa2\x5d\x66\xd0\x7b\x59\x9f\xa8\x47\x12\x9a\x27\x23\xa4\x2d\x8e\x27\x83\x92\x20\xa1\xd7\x15\x7f\xf1\x2e\x18\xee\xf4\x48\x7f\x2f\x7f\xf1\xa1\x18\xb5\xa1\x0b\x94\xa0\x62\x20\x32\x9c\x1d\xf6\xd4\xef\xbf\x4c\x88\x68", 0 }, + /* Anchor: 32 BuypassClass3CA1.cer serial: #{a.serial.to_s} + C=NO,O=Buypass AS-983163327,CN=Buypass Class 3 CA 1 + */ + { 855, "\x30\x82\x03\x53\x30\x82\x02\x3b\xa0\x03\x02\x01\x02\x02\x01\x02\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x4b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4e\x4f\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x0c\x14\x42\x75\x79\x70\x61\x73\x73\x20\x41\x53\x2d\x39\x38\x33\x31\x36\x33\x33\x32\x37\x31\x1d\x30\x1b\x06\x03\x55\x04\x03\x0c\x14\x42\x75\x79\x70\x61\x73\x73\x20\x43\x6c\x61\x73\x73\x20\x33\x20\x43\x41\x20\x31\x30\x1e\x17\x0d\x30\x35\x30\x35\x30\x39\x31\x34\x31\x33\x30\x33\x5a\x17\x0d\x31\x35\x30\x35\x30\x39\x31\x34\x31\x33\x30\x33\x5a\x30\x4b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4e\x4f\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x0c\x14\x42\x75\x79\x70\x61\x73\x73\x20\x41\x53\x2d\x39\x38\x33\x31\x36\x33\x33\x32\x37\x31\x1d\x30\x1b\x06\x03\x55\x04\x03\x0c\x14\x42\x75\x79\x70\x61\x73\x73\x20\x43\x6c\x61\x73\x73\x20\x33\x20\x43\x41\x20\x31\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xa4\x8e\xd7\x74\xd9\x29\x64\xde\x5f\x1f\x87\x80\x91\xea\x4e\x39\xe6\x19\xc6\x44\x0b\x80\xd5\x0b\xaf\x53\x07\x8b\x12\xbd\xe6\x67\xf0\x02\xb1\x89\xf6\x60\x8a\xc4\x5b\xb0\x42\xd1\xc0\x21\xa8\xcb\xe1\x9b\xef\x64\x51\xb6\xa7\xcf\x15\xf5\x74\x80\x68\x04\x90\xa0\x58\xa2\xe6\x74\xa6\x53\x53\x55\x48\x63\x3f\x92\x56\xdd\x24\x4e\x8e\xf8\xba\x2b\xff\xf3\x34\x8a\x9e\x28\xd7\x34\x9f\xac\x2f\xd6\x0f\xf1\xa4\x2f\xbd\x52\xb2\x49\x85\x6d\x39\x35\xf0\x44\x30\x93\x46\x24\xf3\xb6\xe7\x53\xfb\xbc\x61\xaf\xa9\xa3\x14\xfb\xc2\x17\x17\x84\x6c\xe0\x7c\x88\xf8\xc9\x1c\x57\x2c\xf0\x3d\x7e\x94\xbc\x25\x93\x84\xe8\x9a\x00\x9a\x45\x05\x42\x57\x80\xf4\x4e\xce\xd9\xae\x39\xf6\xc8\x53\x10\x0c\x65\x3a\x47\x7b\x60\xc2\xd6\xfa\x91\xc9\xc6\x71\x6c\xbd\x91\x87\x3c\x91\x86\x49\xab\xf3\x0f\xa0\x6c\x26\x76\x5e\x1c\xac\x9b\x71\xe5\x8d\xbc\x9b\x21\x1e\x9c\xd6\x38\x7e\x24\x80\x15\x31\x82\x96\xb1\x49\xd3\x62\x37\x5b\x88\x0c\x0a\x62\x34\xfe\xa7\x48\x7e\x99\xb1\x30\x8b\x90\x37\x95\x1c\xa8\x1f\xa5\x2c\x8d\xf4\x55\xc8\xdb\xdd\x59\x0a\xc2\xad\x78\xa0\xf4\x8b\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x38\x14\xe6\xc8\xf0\xa9\xa4\x03\xf4\x4e\x3e\x22\xa3\x5b\xf2\xd6\xe0\xad\x40\x74\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x01\x67\xa3\x8c\xc9\x25\x3d\x13\x63\x5d\x16\x6f\xec\xa1\x3e\x09\x5c\x91\x15\x2a\x2a\xd9\x80\x21\x4f\x05\xdc\xbb\xa5\x89\xab\x13\x33\x2a\x9e\x38\xb7\x8c\x6f\x02\x72\x63\xc7\x73\x77\x1e\x09\x06\xba\x3b\x28\x7b\xa4\x47\xc9\x61\x6b\x08\x08\x20\xfc\x8a\x05\x8a\x1f\xbc\xba\xc6\xc2\xfe\xcf\x6e\xec\x13\x33\x71\x67\x2e\x69\xfa\xa9\x2c\x3f\x66\xc0\x12\x59\x4d\x0b\x54\x02\x92\x84\xbb\xdb\x12\xef\x83\x70\x70\x78\xc8\x53\xfa\xdf\xc6\xc6\xff\xdc\x88\x2f\x07\xc0\x49\x9d\x32\x57\x60\xd3\xf2\xf6\x99\x29\x5f\xe7\xaa\x01\xcc\xac\x33\xa8\x1c\x0a\xbb\x91\xc4\x03\xa0\x6f\xb6\x34\xf9\x86\xd3\xb3\x76\x54\x98\xf4\x4a\x81\xb3\x53\x9d\x4d\x40\xec\xe5\x77\x13\x45\xaf\x5b\xaa\x1f\xd8\x2f\x4c\x82\x7b\xfe\x2a\xc4\x58\xbb\x4f\xfc\x9e\xfd\x03\x65\x1a\x2a\x0e\xc3\xa5\x20\x16\x94\x6b\x79\xa6\xa2\x12\xb4\xbb\x1a\xa4\x23\x7a\x5f\xf0\xae\x84\x24\xe4\xf3\x2b\xfb\x8a\x24\xa3\x27\x98\x65\xda\x30\x75\x76\xfc\x19\x91\xe8\xdb\xeb\x9b\x3f\x32\xbf\x40\x97\x07\x26\xba\xcc\xf3\x94\x85\x4a\x7a\x27\x93\xcf\x90\x42\xd4\xb8\x5b\x16\xa6\xe7\xcb\x40\x03\xdd\x79", 0 }, + /* Anchor: 33 C1_PCA_G3v2.509 serial: #{a.serial.to_s} + C=US,O=VeriSign\, Inc.,OU=VeriSign Trust Network,OU=(c) 1999 VeriSign\, Inc. - For authorized use only,CN=VeriSign Class 1 Public Primary Certification Authority - G3 + */ + { 1054, "\x30\x82\x04\x1a\x30\x82\x03\x02\x02\x11\x00\x8b\x5b\x75\x56\x84\x54\x85\x0b\x00\xcf\xaf\x38\x48\xce\xb1\xa4\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xca\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x3a\x30\x38\x06\x03\x55\x04\x0b\x13\x31\x28\x63\x29\x20\x31\x39\x39\x39\x20\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3c\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x43\x6c\x61\x73\x73\x20\x31\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x33\x30\x1e\x17\x0d\x39\x39\x31\x30\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x33\x36\x30\x37\x31\x36\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xca\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x3a\x30\x38\x06\x03\x55\x04\x0b\x13\x31\x28\x63\x29\x20\x31\x39\x39\x39\x20\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3c\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x43\x6c\x61\x73\x73\x20\x31\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x33\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xdd\x84\xd4\xb9\xb4\xf9\xa7\xd8\xf3\x04\x78\x9c\xde\x3d\xdc\x6c\x13\x16\xd9\x7a\xdd\x24\x51\x66\xc0\xc7\x26\x59\x0d\xac\x06\x08\xc2\x94\xd1\x33\x1f\xf0\x83\x35\x1f\x6e\x1b\xc8\xde\xaa\x6e\x15\x4e\x54\x27\xef\xc4\x6d\x1a\xec\x0b\xe3\x0e\xf0\x44\xa5\x57\xc7\x40\x58\x1e\xa3\x47\x1f\x71\xec\x60\xf6\x6d\x94\xc8\x18\x39\xed\xfe\x42\x18\x56\xdf\xe4\x4c\x49\x10\x78\x4e\x01\x76\x35\x63\x12\x36\xdd\x66\xbc\x01\x04\x36\xa3\x55\x68\xd5\xa2\x36\x09\xac\xab\x21\x26\x54\x06\xad\x3f\xca\x14\xe0\xac\xca\xad\x06\x1d\x95\xe2\xf8\x9d\xf1\xe0\x60\xff\xc2\x7f\x75\x2b\x4c\xcc\xda\xfe\x87\x99\x21\xea\xba\xfe\x3e\x54\xd7\xd2\x59\x78\xdb\x3c\x6e\xcf\xa0\x13\x00\x1a\xb8\x27\xa1\xe4\xbe\x67\x96\xca\xa0\xc5\xb3\x9c\xdd\xc9\x75\x9e\xeb\x30\x9a\x5f\xa3\xcd\xd9\xae\x78\x19\x3f\x23\xe9\x5c\xdb\x29\xbd\xad\x55\xc8\x1b\x54\x8c\x63\xf6\xe8\xa6\xea\xc7\x37\x12\x5c\xa3\x29\x1e\x02\xd9\xdb\x1f\x3b\xb4\xd7\x0f\x56\x47\x81\x15\x04\x4a\xaf\x83\x27\xd1\xc5\x58\x88\xc1\xdd\xf6\xaa\xa7\xa3\x18\xda\x68\xaa\x6d\x11\x51\xe1\xbf\x65\x6b\x9f\x96\x76\xd1\x3d\x02\x03\x01\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xab\x66\x8d\xd7\xb3\xba\xc7\x9a\xb6\xe6\x55\xd0\x05\xf1\x9f\x31\x8d\x5a\xaa\xd9\xaa\x46\x26\x0f\x71\xed\xa5\xad\x53\x56\x62\x01\x47\x2a\x44\xe9\xfe\x3f\x74\x0b\x13\x9b\xb9\xf4\x4d\x1b\xb2\xd1\x5f\xb2\xb6\xd2\x88\x5c\xb3\x9f\xcd\xcb\xd4\xa7\xd9\x60\x95\x84\x3a\xf8\xc1\x37\x1d\x61\xca\xe7\xb0\xc5\xe5\x91\xda\x54\xa6\xac\x31\x81\xae\x97\xde\xcd\x08\xac\xb8\xc0\x97\x80\x7f\x6e\x72\xa4\xe7\x69\x13\x95\x65\x1f\xc4\x93\x3c\xfd\x79\x8f\x04\xd4\x3e\x4f\xea\xf7\x9e\xce\xcd\x67\x7c\x4f\x65\x02\xff\x91\x85\x54\x73\xc7\xff\x36\xf7\x86\x2d\xec\xd0\x5e\x4f\xff\x11\x9f\x72\x06\xd6\xb8\x1a\xf1\x4c\x0d\x26\x65\xe2\x44\x80\x1e\xc7\x9f\xe3\xdd\xe8\x0a\xda\xec\xa5\x20\x80\x69\x68\xa1\x4f\x7e\xe1\x6b\xcf\x07\x41\xfa\x83\x8e\xbc\x38\xdd\xb0\x2e\x11\xb1\x6b\xb2\x42\xcc\x9a\xbc\xf9\x48\x22\x79\x4a\x19\x0f\xb2\x1c\x3e\x20\x74\xd9\x6a\xc3\xbe\xf2\x28\x78\x13\x56\x79\x4f\x6d\x50\xea\x1b\xb0\xb5\x57\xb1\x37\x66\x58\x23\xf3\xdc\x0f\xdf\x0a\x87\xc4\xef\x86\x05\xd5\x38\x14\x60\x99\xa3\x4b\xde\x06\x96\x71\x2c\xf2\xdb\xb6\x1f\xa4\xef\x3f\xee", 0 }, + /* Anchor: 34 C2_PCA_G3v2.509 serial: #{a.serial.to_s} + C=US,O=VeriSign\, Inc.,OU=VeriSign Trust Network,OU=(c) 1999 VeriSign\, Inc. - For authorized use only,CN=VeriSign Class 2 Public Primary Certification Authority - G3 + */ + { 1053, "\x30\x82\x04\x19\x30\x82\x03\x01\x02\x10\x61\x70\xcb\x49\x8c\x5f\x98\x45\x29\xe7\xb0\xa6\xd9\x50\x5b\x7a\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xca\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x3a\x30\x38\x06\x03\x55\x04\x0b\x13\x31\x28\x63\x29\x20\x31\x39\x39\x39\x20\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3c\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x43\x6c\x61\x73\x73\x20\x32\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x33\x30\x1e\x17\x0d\x39\x39\x31\x30\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x33\x36\x30\x37\x31\x36\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xca\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x3a\x30\x38\x06\x03\x55\x04\x0b\x13\x31\x28\x63\x29\x20\x31\x39\x39\x39\x20\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3c\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x43\x6c\x61\x73\x73\x20\x32\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x33\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xaf\x0a\x0d\xc2\xd5\x2c\xdb\x67\xb9\x2d\xe5\x94\x27\xdd\xa5\xbe\xe0\xb0\x4d\x8f\xb3\x61\x56\x3c\xd6\x7c\xc3\xf4\xcd\x3e\x86\xcb\xa2\x88\xe2\xe1\xd8\xa4\x69\xc5\xb5\xe2\xbf\xc1\xa6\x47\x50\x5e\x46\x39\x8b\xd5\x96\xba\xb5\x6f\x14\xbf\x10\xce\x27\x13\x9e\x05\x47\x9b\x31\x7a\x13\xd8\x1f\xd9\xd3\x02\x37\x8b\xad\x2c\x47\xf0\x8e\x81\x06\xa7\x0d\x30\x0c\xeb\xf7\x3c\x0f\x20\x1d\xdc\x72\x46\xee\xa5\x02\xc8\x5b\xc3\xc9\x56\x69\x4c\xc5\x18\xc1\x91\x7b\x0b\xd5\x13\x00\x9b\xbc\xef\xc3\x48\x3e\x46\x60\x20\x85\x2a\xd5\x90\xb6\xcd\x8b\xa0\xcc\x32\xdd\xb7\xfd\x40\x55\xb2\x50\x1c\x56\xae\xcc\x8d\x77\x4d\xc7\x20\x4d\xa7\x31\x76\xef\x68\x92\x8a\x90\x1e\x08\x81\x56\xb2\xad\x69\xa3\x52\xd0\xcb\x1c\xc4\x23\x3d\x1f\x99\xfe\x4c\xe8\x16\x63\x8e\xc6\x08\x8e\xf6\x31\xf6\xd2\xfa\xe5\x76\xdd\xb5\x1c\x92\xa3\x49\xcd\xcd\x01\xcd\x68\xcd\xa9\x69\xba\xa3\xeb\x1d\x0d\x9c\xa4\x20\xa6\xc1\xa0\xc5\xd1\x46\x4c\x17\x6d\xd2\xac\x66\x3f\x96\x8c\xe0\x84\xd4\x36\xff\x22\x59\xc5\xf9\x11\x60\xa8\x5f\x04\x7d\xf2\x1a\xf6\x25\x42\x61\x0f\xc4\x4a\xb8\x3e\x89\x02\x03\x01\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x34\x26\x15\x3c\xc0\x8d\x4d\x43\x49\x1d\xbd\xe9\x21\x92\xd7\x66\x9c\xb7\xde\xc5\xb8\xd0\xe4\x5d\x5f\x76\x22\xc0\x26\xf9\x84\x3a\x3a\xf9\x8c\xb5\xfb\xec\x60\xf1\xe8\xce\x04\xb0\xc8\xdd\xa7\x03\x8f\x30\xf3\x98\xdf\xa4\xe6\xa4\x31\xdf\xd3\x1c\x0b\x46\xdc\x72\x20\x3f\xae\xee\x05\x3c\xa4\x33\x3f\x0b\x39\xac\x70\x78\x73\x4b\x99\x2b\xdf\x30\xc2\x54\xb0\xa8\x3b\x55\xa1\xfe\x16\x28\xcd\x42\xbd\x74\x6e\x80\xdb\x27\x44\xa7\xce\x44\x5d\xd4\x1b\x90\x98\x0d\x1e\x42\x94\xb1\x00\x2c\x04\xd0\x74\xa3\x02\x05\x22\x63\x63\xcd\x83\xb5\xfb\xc1\x6d\x62\x6b\x69\x75\xfd\x5d\x70\x41\xb9\xf5\xbf\x7c\xdf\xbe\xc1\x32\x73\x22\x21\x8b\x58\x81\x7b\x15\x91\x7a\xba\xe3\x64\x48\xb0\x7f\xfb\x36\x25\xda\x95\xd0\xf1\x24\x14\x17\xdd\x18\x80\x6b\x46\x23\x39\x54\xf5\x8e\x62\x09\x04\x1d\x94\x90\xa6\x9b\xe6\x25\xe2\x42\x45\xaa\xb8\x90\xad\xbe\x08\x8f\xa9\x0b\x42\x18\x94\xcf\x72\x39\xe1\xb1\x43\xe0\x28\xcf\xb7\xe7\x5a\x6c\x13\x6b\x49\xb3\xff\xe3\x18\x7c\x89\x8b\x33\x5d\xac\x33\xd7\xa7\xf9\xda\x3a\x55\xc9\x58\x10\xf9\xaa\xef\x5a\xb6\xcf\x4b\x4b\xdf\x2a", 0 }, + /* Anchor: 35 C3_PCA_G3v2.509 serial: #{a.serial.to_s} + C=US,O=VeriSign\, Inc.,OU=VeriSign Trust Network,OU=(c) 1999 VeriSign\, Inc. - For authorized use only,CN=VeriSign Class 3 Public Primary Certification Authority - G3 + */ + { 1054, "\x30\x82\x04\x1a\x30\x82\x03\x02\x02\x11\x00\x9b\x7e\x06\x49\xa3\x3e\x62\xb9\xd5\xee\x90\x48\x71\x29\xef\x57\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xca\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x3a\x30\x38\x06\x03\x55\x04\x0b\x13\x31\x28\x63\x29\x20\x31\x39\x39\x39\x20\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3c\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x43\x6c\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x33\x30\x1e\x17\x0d\x39\x39\x31\x30\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x33\x36\x30\x37\x31\x36\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xca\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x3a\x30\x38\x06\x03\x55\x04\x0b\x13\x31\x28\x63\x29\x20\x31\x39\x39\x39\x20\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3c\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x43\x6c\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x33\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xcb\xba\x9c\x52\xfc\x78\x1f\x1a\x1e\x6f\x1b\x37\x73\xbd\xf8\xc9\x6b\x94\x12\x30\x4f\xf0\x36\x47\xf5\xd0\x91\x0a\xf5\x17\xc8\xa5\x61\xc1\x16\x40\x4d\xfb\x8a\x61\x90\xe5\x76\x20\xc1\x11\x06\x7d\xab\x2c\x6e\xa6\xf5\x11\x41\x8e\xfa\x2d\xad\x2a\x61\x59\xa4\x67\x26\x4c\xd0\xe8\xbc\x52\x5b\x70\x20\x04\x58\xd1\x7a\xc9\xa4\x69\xbc\x83\x17\x64\xad\x05\x8b\xbc\xd0\x58\xce\x8d\x8c\xf5\xeb\xf0\x42\x49\x0b\x9d\x97\x27\x67\x32\x6e\xe1\xae\x93\x15\x1c\x70\xbc\x20\x4d\x2f\x18\xde\x92\x88\xe8\x6c\x85\x57\x11\x1a\xe9\x7e\xe3\x26\x11\x54\xa2\x45\x96\x55\x83\xca\x30\x89\xe8\xdc\xd8\xa3\xed\x2a\x80\x3f\x7f\x79\x65\x57\x3e\x15\x20\x66\x08\x2f\x95\x93\xbf\xaa\x47\x2f\xa8\x46\x97\xf0\x12\xe2\xfe\xc2\x0a\x2b\x51\xe6\x76\xe6\xb7\x46\xb7\xe2\x0d\xa6\xcc\xa8\xc3\x4c\x59\x55\x89\xe6\xe8\x53\x5c\x1c\xea\x9d\xf0\x62\x16\x0b\xa7\xc9\x5f\x0c\xf0\xde\xc2\x76\xce\xaf\xf7\x6a\xf2\xfa\x41\xa6\xa2\x33\x14\xc9\xe5\x7a\x63\xd3\x9e\x62\x37\xd5\x85\x65\x9e\x0e\xe6\x53\x24\x74\x1b\x5e\x1d\x12\x53\x5b\xc7\x2c\xe7\x83\x49\x3b\x15\xae\x8a\x68\xb9\x57\x97\x02\x03\x01\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x11\x14\x96\xc1\xab\x92\x08\xf7\x3f\x2f\xc9\xb2\xfe\xe4\x5a\x9f\x64\xde\xdb\x21\x4f\x86\x99\x34\x76\x36\x57\xdd\xd0\x15\x2f\xc5\xad\x7f\x15\x1f\x37\x62\x73\x3e\xd4\xe7\x5f\xce\x17\x03\xdb\x35\xfa\x2b\xdb\xae\x60\x09\x5f\x1e\x5f\x8f\x6e\xbb\x0b\x3d\xea\x5a\x13\x1e\x0c\x60\x6f\xb5\xc0\xb5\x23\x22\x2e\x07\x0b\xcb\xa9\x74\xcb\x47\xbb\x1d\xc1\xd7\xa5\x6b\xcc\x2f\xd2\x42\xfd\x49\xdd\xa7\x89\xcf\x53\xba\xda\x00\x5a\x28\xbf\x82\xdf\xf8\xba\x13\x1d\x50\x86\x82\xfd\x8e\x30\x8f\x29\x46\xb0\x1e\x3d\x35\xda\x38\x62\x16\x18\x4a\xad\xe6\xb6\x51\x6c\xde\xaf\x62\xeb\x01\xd0\x1e\x24\xfe\x7a\x8f\x12\x1a\x12\x68\xb8\xfb\x66\x99\x14\x14\x45\x5c\xae\xe7\xae\x69\x17\x81\x2b\x5a\x37\xc9\x5e\x2a\xf4\xc6\xe2\xa1\x5c\x54\x9b\xa6\x54\x00\xcf\xf0\xf1\xc1\xc7\x98\x30\x1a\x3b\x36\x16\xdb\xa3\x6e\xea\xfd\xad\xb2\xc2\xda\xef\x02\x47\x13\x8a\xc0\xf1\xb3\x31\xad\x4f\x1c\xe1\x4f\x9c\xaf\x0f\x0c\x9d\xf7\x78\x0d\xd8\xf4\x35\x56\x80\xda\xb7\x6d\x17\x8f\x9d\x1e\x81\x64\xe1\xfe\xc5\x45\xba\xad\x6b\xb9\x0a\x7a\x4e\x4f\x4b\x84\xee\x4b\xf1\x7d\xdd\x11", 0 }, + /* Anchor: 36 C4_PCA_G3v2.509 serial: #{a.serial.to_s} + C=US,O=VeriSign\, Inc.,OU=VeriSign Trust Network,OU=(c) 1999 VeriSign\, Inc. - For authorized use only,CN=VeriSign Class 4 Public Primary Certification Authority - G3 + */ + { 1054, "\x30\x82\x04\x1a\x30\x82\x03\x02\x02\x11\x00\xec\xa0\xa7\x8b\x6e\x75\x6a\x01\xcf\xc4\x7c\xcc\x2f\x94\x5e\xd7\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xca\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x3a\x30\x38\x06\x03\x55\x04\x0b\x13\x31\x28\x63\x29\x20\x31\x39\x39\x39\x20\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3c\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x43\x6c\x61\x73\x73\x20\x34\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x33\x30\x1e\x17\x0d\x39\x39\x31\x30\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x33\x36\x30\x37\x31\x36\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xca\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x3a\x30\x38\x06\x03\x55\x04\x0b\x13\x31\x28\x63\x29\x20\x31\x39\x39\x39\x20\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3c\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x43\x6c\x61\x73\x73\x20\x34\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x33\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xad\xcb\xa5\x11\x69\xc6\x59\xab\xf1\x8f\xb5\x19\x0f\x56\xce\xcc\xb5\x1f\x20\xe4\x9e\x26\x25\x4b\xe0\x73\x65\x89\x59\xde\xd0\x83\xe4\xf5\x0f\xb5\xbb\xad\xf1\x7c\xe8\x21\xfc\xe4\xe8\x0c\xee\x7c\x45\x22\x19\x76\x92\xb4\x13\xb7\x20\x5b\x09\xfa\x61\xae\xa8\xf2\xa5\x8d\x85\xc2\x2a\xd6\xde\x66\x36\xd2\x9b\x02\xf4\xa8\x92\x60\x7c\x9c\x69\xb4\x8f\x24\x1e\xd0\x86\x52\xf6\x32\x9c\x41\x58\x1e\x22\xbd\xcd\x45\x62\x95\x08\x6e\xd0\x66\xdd\x53\xa2\xcc\xf0\x10\xdc\x54\x73\x8b\x04\xa1\x46\x33\x33\x5c\x17\x40\xb9\x9e\x4d\xd3\xf3\xbe\x55\x83\xe8\xb1\x89\x8e\x5a\x7c\x9a\x96\x22\x90\x3b\x88\x25\xf2\xd2\x53\x88\x02\x0c\x0b\x78\xf2\xe6\x37\x17\x4b\x30\x46\x07\xe4\x80\x6d\xa6\xd8\x96\x2e\xe8\x2c\xf8\x11\xb3\x38\x0d\x66\xa6\x9b\xea\xc9\x23\x5b\xdb\x8e\xe2\xf3\x13\x8e\x1a\x59\x2d\xaa\x02\xf0\xec\xa4\x87\x66\xdc\xc1\x3f\xf5\xd8\xb9\xf4\xec\x82\xc6\xd2\x3d\x95\x1d\xe5\xc0\x4f\x84\xc9\xd9\xa3\x44\x28\x06\x6a\xd7\x45\xac\xf0\x6b\x6a\xef\x4e\x5f\xf8\x11\x82\x1e\x38\x63\x34\x66\x50\xd4\x3e\x93\x73\xfa\x30\xc3\x66\xad\xff\x93\x2d\x97\xef\x03\x02\x03\x01\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x8f\xfa\x25\x6b\x4f\x5b\xe4\xa4\x4e\x27\x55\xab\x22\x15\x59\x3c\xca\xb5\x0a\xd4\x4a\xdb\xab\xdd\xa1\x5f\x53\xc5\xa0\x57\x39\xc2\xce\x47\x2b\xbe\x3a\xc8\x56\xbf\xc2\xd9\x27\x10\x3a\xb1\x05\x3c\xc0\x77\x31\xbb\x3a\xd3\x05\x7b\x6d\x9a\x1c\x30\x8c\x80\xcb\x93\x93\x2a\x83\xab\x05\x51\x82\x02\x00\x11\x67\x6b\xf3\x88\x61\x47\x5f\x03\x93\xd5\x5b\x0d\xe0\xf1\xd4\xa1\x32\x35\x85\xb2\x3a\xdb\xb0\x82\xab\xd1\xcb\x0a\xbc\x4f\x8c\x5b\xc5\x4b\x00\x3b\x1f\x2a\x82\xa6\x7e\x36\x85\xdc\x7e\x3c\x67\x00\xb5\xe4\x3b\x52\xe0\xa8\xeb\x5d\x15\xf9\xc6\x6d\xf0\xad\x1d\x0e\x85\xb7\xa9\x9a\x73\x14\x5a\x5b\x8f\x41\x28\xc0\xd5\xe8\x2d\x4d\xa4\x5e\xcd\xaa\xd9\xed\xce\xdc\xd8\xd5\x3c\x42\x1d\x17\xc1\x12\x5d\x45\x38\xc3\x38\xf3\xfc\x85\x2e\x83\x46\x48\xb2\xd7\x20\x5f\x92\x36\x8f\xe7\x79\x0f\x98\x5e\x99\xe8\xf0\xd0\xa4\xbb\xf5\x53\xbd\x2a\xce\x59\xb0\xaf\x6e\x7f\x6c\xbb\xd2\x1e\x00\xb0\x21\xed\xf8\x41\x62\x82\xb9\xd8\xb2\xc4\xbb\x46\x50\xf3\x31\xc5\x8f\x01\xa8\x74\xeb\xf5\x78\x27\xda\xe7\xf7\x66\x43\xf3\x9e\x83\x3e\x20\xaa\xc3\x35\x60\x91\xce", 0 }, + /* Anchor: 37 Certigna.cer serial: #{a.serial.to_s} + C=FR,O=Dhimyotis,CN=Certigna + */ + { 940, "\x30\x82\x03\xa8\x30\x82\x02\x90\xa0\x03\x02\x01\x02\x02\x09\x00\xfe\xdc\xe3\x01\x0f\xc9\x48\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x34\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x12\x30\x10\x06\x03\x55\x04\x0a\x0c\x09\x44\x68\x69\x6d\x79\x6f\x74\x69\x73\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x43\x65\x72\x74\x69\x67\x6e\x61\x30\x1e\x17\x0d\x30\x37\x30\x36\x32\x39\x31\x35\x31\x33\x30\x35\x5a\x17\x0d\x32\x37\x30\x36\x32\x39\x31\x35\x31\x33\x30\x35\x5a\x30\x34\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x12\x30\x10\x06\x03\x55\x04\x0a\x0c\x09\x44\x68\x69\x6d\x79\x6f\x74\x69\x73\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x43\x65\x72\x74\x69\x67\x6e\x61\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xc8\x68\xf1\xc9\xd6\xd6\xb3\x34\x75\x26\x82\x1e\xec\xb4\xbe\xea\x5c\xe1\x26\xed\x11\x47\x61\xe1\xa2\x7c\x16\x78\x40\x21\xe4\x60\x9e\x5a\xc8\x63\xe1\xc4\xb1\x96\x92\xff\x18\x6d\x69\x23\xe1\x2b\x62\xf7\xdd\xe2\x36\x2f\x91\x07\xb9\x48\xcf\x0e\xec\x79\xb6\x2c\xe7\x34\x4b\x70\x08\x25\xa3\x3c\x87\x1b\x19\xf2\x81\x07\x0f\x38\x90\x19\xd3\x11\xfe\x86\xb4\xf2\xd1\x5e\x1e\x1e\x96\xcd\x80\x6c\xce\x3b\x31\x93\xb6\xf2\xa0\xd0\xa9\x95\x12\x7d\xa5\x9a\xcc\x6b\xc8\x84\x56\x8a\x33\xa9\xe7\x22\x15\x53\x16\xf0\xcc\x17\xec\x57\x5f\xe9\xa2\x0a\x98\x09\xde\xe3\x5f\x9c\x6f\xdc\x48\xe3\x85\x0b\x15\x5a\xa6\xba\x9f\xac\x48\xe3\x09\xb2\xf7\xf4\x32\xde\x5e\x34\xbe\x1c\x78\x5d\x42\x5b\xce\x0e\x22\x8f\x4d\x90\xd7\x7d\x32\x18\xb3\x0b\x2c\x6a\xbf\x8e\x3f\x14\x11\x89\x20\x0e\x77\x14\xb5\x3d\x94\x08\x87\xf7\x25\x1e\xd5\xb2\x60\x00\xec\x6f\x2a\x28\x25\x6e\x2a\x3e\x18\x63\x17\x25\x3f\x3e\x44\x20\x16\xf6\x26\xc8\x25\xae\x05\x4a\xb4\xe7\x63\x2c\xf3\x8c\x16\x53\x7e\x5c\xfb\x11\x1a\x08\xc1\x46\x62\x9f\x22\xb8\xf1\xc2\x8d\x69\xdc\xfa\x3a\x58\x06\xdf\x02\x03\x01\x00\x01\xa3\x81\xbc\x30\x81\xb9\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x1a\xed\xfe\x41\x39\x90\xb4\x24\x59\xbe\x01\xf2\x52\xd5\x45\xf6\x5a\x39\xdc\x11\x30\x64\x06\x03\x55\x1d\x23\x04\x5d\x30\x5b\x80\x14\x1a\xed\xfe\x41\x39\x90\xb4\x24\x59\xbe\x01\xf2\x52\xd5\x45\xf6\x5a\x39\xdc\x11\xa1\x38\xa4\x36\x30\x34\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x12\x30\x10\x06\x03\x55\x04\x0a\x0c\x09\x44\x68\x69\x6d\x79\x6f\x74\x69\x73\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x43\x65\x72\x74\x69\x67\x6e\x61\x82\x09\x00\xfe\xdc\xe3\x01\x0f\xc9\x48\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x85\x03\x1e\x92\x71\xf6\x42\xaf\xe1\xa3\x61\x9e\xeb\xf3\xc0\x0f\xf2\xa5\xd4\xda\x95\xe6\xd6\xbe\x68\x36\x3d\x7e\x6e\x1f\x4c\x8a\xef\xd1\x0f\x21\x6d\x5e\xa5\x52\x63\xce\x12\xf8\xef\x2a\xda\x6f\xeb\x37\xfe\x13\x02\xc7\xcb\x3b\x3e\x22\x6b\xda\x61\x2e\x7f\xd4\x72\x3d\xdd\x30\xe1\x1e\x4c\x40\x19\x8c\x0f\xd7\x9c\xd1\x83\x30\x7b\x98\x59\xdc\x7d\xc6\xb9\x0c\x29\x4c\xa1\x33\xa2\xeb\x67\x3a\x65\x84\xd3\x96\xe2\xed\x76\x45\x70\x8f\xb5\x2b\xde\xf9\x23\xd6\x49\x6e\x3c\x14\xb5\xc6\x9f\x35\x1e\x50\xd0\xc1\x8f\x6a\x70\x44\x02\x62\xcb\xae\x1d\x68\x41\xa7\xaa\x57\xe8\x53\xaa\x07\xd2\x06\xf6\xd5\x14\x06\x0b\x91\x03\x75\x2c\x6c\x72\xb5\x61\x95\x9a\x0d\x8b\xb9\x0d\xe7\xf5\xdf\x54\xcd\xde\xe6\xd8\xd6\x09\x08\x97\x63\xe5\xc1\x2e\xb0\xb7\x44\x26\xc0\x26\xc0\xaf\x55\x30\x9e\x3b\xd5\x36\x2a\x19\x04\xf4\x5c\x1e\xff\xcf\x2c\xb7\xff\xd0\xfd\x87\x40\x11\xd5\x11\x23\xbb\x48\xc0\x21\xa9\xa4\x28\x2d\xfd\x15\xf8\xb0\x4e\x2b\xf4\x30\x5b\x21\xfc\x11\x91\x34\xbe\x41\xef\x7b\x9d\x97\x75\xff\x97\x95\xc0\x96\x58\x2f\xea\xbb\x46\xd7\xbb\xe4\xd9\x2e", 0 }, + /* Anchor: 38 certplus_class2.der serial: #{a.serial.to_s} + C=FR,O=Certplus,CN=Class 2 Primary CA + */ + { 918, "\x30\x82\x03\x92\x30\x82\x02\x7a\xa0\x03\x02\x01\x02\x02\x11\x00\x85\xbd\x4b\xf3\xd8\xda\xe3\x69\xf6\x94\xd7\x5f\xc3\xa5\x44\x23\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x3d\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x11\x30\x0f\x06\x03\x55\x04\x0a\x13\x08\x43\x65\x72\x74\x70\x6c\x75\x73\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x13\x12\x43\x6c\x61\x73\x73\x20\x32\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x41\x30\x1e\x17\x0d\x39\x39\x30\x37\x30\x37\x31\x37\x30\x35\x30\x30\x5a\x17\x0d\x31\x39\x30\x37\x30\x36\x32\x33\x35\x39\x35\x39\x5a\x30\x3d\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x11\x30\x0f\x06\x03\x55\x04\x0a\x13\x08\x43\x65\x72\x74\x70\x6c\x75\x73\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x13\x12\x43\x6c\x61\x73\x73\x20\x32\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xdc\x50\x96\xd0\x12\xf8\x35\xd2\x08\x78\x7a\xb6\x52\x70\xfd\x6f\xee\xcf\xb9\x11\xcb\x5d\x77\xe1\xec\xe9\x7e\x04\x8d\xd6\xcc\x6f\x73\x43\x57\x60\xac\x33\x0a\x44\xec\x03\x5f\x1c\x80\x24\x91\xe5\xa8\x91\x56\x12\x82\xf7\xe0\x2b\xf4\xdb\xae\x61\x2e\x89\x10\x8d\x6b\x6c\xba\xb3\x02\xbd\xd5\x36\xc5\x48\x37\x23\xe2\xf0\x5a\x37\x52\x33\x17\x12\xe2\xd1\x60\x4d\xbe\x2f\x41\x11\xe3\xf6\x17\x25\x0c\x8b\x91\xc0\x1b\x99\x7b\x99\x56\x0d\xaf\xee\xd2\xbc\x47\x57\xe3\x79\x49\x7b\x34\x89\x27\x24\x84\xde\xb1\xec\xe9\x58\x4e\xfe\x4e\xdf\x5a\xbe\x41\xad\xac\x08\xc5\x18\x0e\xef\xd2\x53\xee\x6c\xd0\x9d\x12\x01\x13\x8d\xdc\x80\x62\xf7\x95\xa9\x44\x88\x4a\x71\x4e\x60\x55\x9e\xdb\x23\x19\x79\x56\x07\x0c\x3f\x63\x0b\x5c\xb0\xe2\xbe\x7e\x15\xfc\x94\x33\x58\x41\x38\x74\xc4\xe1\x8f\x8b\xdf\x26\xac\x1f\xb5\x8b\x3b\xb7\x43\x59\x6b\xb0\x24\xa6\x6d\x90\x8b\xc4\x72\xea\x5d\x33\x98\xb7\xcb\xde\x5e\x7b\xef\x94\xf1\x1b\x3e\xca\xc9\x21\xc1\xc5\x98\x02\xaa\xa2\xf6\x5b\x77\x9b\xf5\x7e\x96\x55\x34\x1c\x67\x69\xc0\xf1\x42\xe3\x47\xac\xfc\x28\x1c\x66\x55\x02\x03\x01\x00\x01\xa3\x81\x8c\x30\x81\x89\x30\x0f\x06\x03\x55\x1d\x13\x04\x08\x30\x06\x01\x01\xff\x02\x01\x0a\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xe3\x73\x2d\xdf\xcb\x0e\x28\x0c\xde\xdd\xb3\xa4\xca\x79\xb8\x8e\xbb\xe8\x30\x89\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x01\x06\x30\x37\x06\x03\x55\x1d\x1f\x04\x30\x30\x2e\x30\x2c\xa0\x2a\xa0\x28\x86\x26\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x63\x65\x72\x74\x70\x6c\x75\x73\x2e\x63\x6f\x6d\x2f\x43\x52\x4c\x2f\x63\x6c\x61\x73\x73\x32\x2e\x63\x72\x6c\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xa7\x54\xcf\x88\x44\x19\xcb\xdf\xd4\x7f\x00\xdf\x56\x33\x62\xb5\xf7\x51\x01\x90\xeb\xc3\x3f\xd1\x88\x44\xe9\x24\x5d\xef\xe7\x14\xbd\x20\xb7\x9a\x3c\x00\xfe\x6d\x9f\xdb\x90\xdc\xd7\xf4\x62\xd6\x8b\x70\x5d\xe7\xe5\x04\x48\xa9\x68\x7c\xc9\xf1\x42\xf3\x6c\x7f\xc5\x7a\x7c\x1d\x51\x88\xba\xd2\x0a\x3e\x27\x5d\xde\x2d\x51\x4e\xd3\x13\x64\x69\xe4\x2e\xe3\xd3\xe7\x9b\x09\x99\xa6\xe0\x95\x9b\xce\x1a\xd7\x7f\xbe\x3c\xce\x52\xb3\x11\x15\xc1\x0f\x17\xcd\x03\xbb\x9c\x25\x15\xba\xa2\x76\x89\xfc\x06\xf1\x18\xd0\x93\x4b\x0e\x7c\x82\xb7\xa5\xf4\xf6\x5f\xfe\xed\x40\xa6\x9d\x84\x74\x39\xb9\xdc\x1e\x85\x16\xda\x29\x1b\x86\x23\x00\xc9\xbb\x89\x7e\x6e\x80\x88\x1e\x2f\x14\xb4\x03\x24\xa8\x32\x6f\x03\x9a\x47\x2c\x30\xbe\x56\xc6\xa7\x42\x02\x70\x1b\xea\x40\xd8\xba\x05\x03\x70\x07\xa4\x96\xff\xfd\x48\x33\x0a\xe1\xdc\xa5\x81\x90\x9b\x4d\xdd\x7d\xe7\xe7\xb2\xcd\x5c\xc8\x6a\x95\xf8\xa5\xf6\x8d\xc4\x5d\x78\x08\xbe\x7b\x06\xd6\x49\xcf\x19\x36\x50\x23\x2e\x08\xe6\x9e\x05\x4d\x47\x18\xd5\x16\xe9\xb1\xd6\xb6\x10\xd5\xbb\x97\xbf\xa2\x8e\xb4\x54", 0 }, + /* Anchor: 39 Chunghwa-ROOTeCA.der serial: #{a.serial.to_s} + C=TW,O=Chunghwa Telecom Co.\, Ltd.,OU=ePKI Root Certification Authority + */ + { 1460, "\x30\x82\x05\xb0\x30\x82\x03\x98\xa0\x03\x02\x01\x02\x02\x10\x15\xc8\xbd\x65\x47\x5c\xaf\xb8\x97\x00\x5e\xe4\x06\xd2\xbc\x9d\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x5e\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x57\x31\x23\x30\x21\x06\x03\x55\x04\x0a\x0c\x1a\x43\x68\x75\x6e\x67\x68\x77\x61\x20\x54\x65\x6c\x65\x63\x6f\x6d\x20\x43\x6f\x2e\x2c\x20\x4c\x74\x64\x2e\x31\x2a\x30\x28\x06\x03\x55\x04\x0b\x0c\x21\x65\x50\x4b\x49\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x30\x34\x31\x32\x32\x30\x30\x32\x33\x31\x32\x37\x5a\x17\x0d\x33\x34\x31\x32\x32\x30\x30\x32\x33\x31\x32\x37\x5a\x30\x5e\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x57\x31\x23\x30\x21\x06\x03\x55\x04\x0a\x0c\x1a\x43\x68\x75\x6e\x67\x68\x77\x61\x20\x54\x65\x6c\x65\x63\x6f\x6d\x20\x43\x6f\x2e\x2c\x20\x4c\x74\x64\x2e\x31\x2a\x30\x28\x06\x03\x55\x04\x0b\x0c\x21\x65\x50\x4b\x49\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\xe1\x25\x0f\xee\x8d\xdb\x88\x33\x75\x67\xcd\xad\x1f\x7d\x3a\x4e\x6d\x9d\xd3\x2f\x14\xf3\x63\x74\xcb\x01\x21\x6a\x37\xea\x84\x50\x07\x4b\x26\x5b\x09\x43\x6c\x21\x9e\x6a\xc8\xd5\x03\xf5\x60\x69\x8f\xcc\xf0\x22\xe4\x1f\xe7\xf7\x6a\x22\x31\xb7\x2c\x15\xf2\xe0\xfe\x00\x6a\x43\xff\x87\x65\xc6\xb5\x1a\xc1\xa7\x4c\x6d\x22\x70\x21\x8a\x31\xf2\x97\x74\x89\x09\x12\x26\x1c\x9e\xca\xd9\x12\xa2\x95\x3c\xda\xe9\x67\xbf\x08\xa0\x64\xe3\xd6\x42\xb7\x45\xef\x97\xf4\xf6\xf5\xd7\xb5\x4a\x15\x02\x58\x7d\x98\x58\x4b\x60\xbc\xcd\xd7\x0d\x9a\x13\x33\x53\xd1\x61\xf9\x7a\xd5\xd7\x78\xb3\x9a\x33\xf7\x00\x86\xce\x1d\x4d\x94\x38\xaf\xa8\xec\x78\x51\x70\x8a\x5c\x10\x83\x51\x21\xf7\x11\x3d\x34\x86\x5e\xe5\x48\xcd\x97\x81\x82\x35\x4c\x19\xec\x65\xf6\x6b\xc5\x05\xa1\xee\x47\x13\xd6\xb3\x21\x27\x94\x10\x0a\xd9\x24\x3b\xba\xbe\x44\x13\x46\x30\x3f\x97\x3c\xd8\xd7\xd7\x6a\xee\x3b\x38\xe3\x2b\xd4\x97\x0e\xb9\x1b\xe7\x07\x49\x7f\x37\x2a\xf9\x77\x78\xcf\x54\xed\x5b\x46\x9d\xa3\x80\x0e\x91\x43\xc1\xd6\x5b\x5f\x14\xba\x9f\xa6\x8d\x24\x47\x40\x59\xbf\x72\x38\xb2\x36\x6c\x37\xff\x99\xd1\x5d\x0e\x59\x0a\xab\x69\xf7\xc0\xb2\x04\x45\x7a\x54\x00\xae\xbe\x53\xf6\xb5\xe7\xe1\xf8\x3c\xa3\x31\xd2\xa9\xfe\x21\x52\x64\xc5\xa6\x67\xf0\x75\x07\x06\x94\x14\x81\x55\xc6\x27\xe4\x01\x8f\x17\xc1\x6a\x71\xd7\xbe\x4b\xfb\x94\x58\x7d\x7e\x11\x33\xb1\x42\xf7\x62\x6c\x18\xd6\xcf\x09\x68\x3e\x7f\x6c\xf6\x1e\x8f\x62\xad\xa5\x63\xdb\x09\xa7\x1f\x22\x42\x41\x1e\x6f\x99\x8a\x3e\xd7\xf9\x3f\x40\x7a\x79\xb0\xa5\x01\x92\xd2\x9d\x3d\x08\x15\xa5\x10\x01\x2d\xb3\x32\x76\xa8\x95\x0d\xb3\x7a\x9a\xfb\x07\x10\x78\x11\x6f\xe1\x8f\xc7\xba\x0f\x25\x1a\x74\x2a\xe5\x1c\x98\x41\x99\xdf\x21\x87\xe8\x95\x06\x6a\x0a\xb3\x6a\x47\x76\x65\xf6\x3a\xcf\x8f\x62\x17\x19\x7b\x0a\x28\xcd\x1a\xd2\x83\x1e\x21\xc7\x2c\xbf\xbe\xff\x61\x68\xb7\x67\x1b\xbb\x78\x4d\x8d\xce\x67\xe5\xe4\xc1\x8e\xb7\x23\x66\xe2\x9d\x90\x75\x34\x98\xa9\x36\x2b\x8a\x9a\x94\xb9\x9d\xec\xcc\x8a\xb1\xf8\x25\x89\x5c\x5a\xb6\x2f\x8c\x1f\x6d\x79\x24\xa7\x52\x68\xc3\x84\x35\xe2\x66\x8d\x63\x0e\x25\x4d\xd5\x19\xb2\xe6\x79\x37\xa7\x22\x9d\x54\x31\x02\x03\x01\x00\x01\xa3\x6a\x30\x68\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x1e\x0c\xf7\xb6\x67\xf2\xe1\x92\x26\x09\x45\xc0\x55\x39\x2e\x77\x3f\x42\x4a\xa2\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x39\x06\x04\x67\x2a\x07\x00\x04\x31\x30\x2f\x30\x2d\x02\x01\x00\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x30\x07\x06\x05\x67\x2a\x03\x00\x00\x04\x14\x45\xb0\xc2\xc7\x0a\x56\x7c\xee\x5b\x78\x0c\x95\xf9\x18\x53\xc1\xa6\x1c\xd8\x10\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x09\xb3\x83\x53\x59\x01\x3e\x95\x49\xb9\xf1\x81\xba\xf9\x76\x20\x23\xb5\x27\x60\x74\xd4\x6a\x99\x34\x5e\x6c\x00\x53\xd9\x9f\xf2\xa6\xb1\x24\x07\x44\x6a\x2a\xc6\xa5\x8e\x78\x12\xe8\x47\xd9\x58\x1b\x13\x2a\x5e\x79\x9b\x9f\x0a\x2a\x67\xa6\x25\x3f\x06\x69\x56\x73\xc3\x8a\x66\x48\xfb\x29\x81\x57\x74\x06\xca\x9c\xea\x28\xe8\x38\x67\x26\x2b\xf1\xd5\xb5\x3f\x65\x93\xf8\x36\x5d\x8e\x8d\x8d\x40\x20\x87\x19\xea\xef\x27\xc0\x3d\xb4\x39\x0f\x25\x7b\x68\x50\x74\x55\x9c\x0c\x59\x7d\x5a\x3d\x41\x94\x25\x52\x08\xe0\x47\x2c\x15\x31\x19\xd5\xbf\x07\x55\xc6\xbb\x12\xb5\x97\xf4\x5f\x83\x85\xba\x71\xc1\xd9\x6c\x81\x11\x76\x0a\x0a\xb0\xbf\x82\x97\xf7\xea\x3d\xfa\xfa\xec\x2d\xa9\x28\x94\x3b\x56\xdd\xd2\x51\x2e\xae\xc0\xbd\x08\x15\x8c\x77\x52\x34\x96\xd6\x9b\xac\xd3\x1d\x8e\x61\x0f\x35\x7b\x9b\xae\x39\x69\x0b\x62\x60\x40\x20\x36\x8f\xaf\xfb\x36\xee\x2d\x08\x4a\x1d\xb8\xbf\x9b\x5c\xf8\xea\xa5\x1b\xa0\x73\xa6\xd8\xf8\x6e\xe0\x33\x04\x5f\x68\xaa\x27\x87\xed\xd9\xc1\x90\x9c\xed\xbd\xe3\x6a\x35\xaf\x63\xdf\xab\x18\xd9\xba\xe6\xe9\x4a\xea\x50\x8a\x0f\x61\x93\x1e\xe2\x2d\x19\xe2\x30\x94\x35\x92\x5d\x0e\xb6\x07\xaf\x19\x80\x8f\x47\x90\x51\x4b\x2e\x4d\xdd\x85\xe2\xd2\x0a\x52\x0a\x17\x9a\xfc\x1a\xb0\x50\x02\xe5\x01\xa3\x63\x37\x21\x4c\x44\xc4\x9b\x51\x99\x11\x0e\x73\x9c\x06\x8f\x54\x2e\xa7\x28\x5e\x44\x39\x87\x56\x2d\x37\xbd\x85\x44\x94\xe1\x0c\x4b\x2c\x9c\xc3\x92\x85\x34\x61\xcb\x0f\xb8\x9b\x4a\x43\x52\xfe\x34\x3a\x7d\xb8\xe9\x29\xdc\x76\xa9\xc8\x30\xf8\x14\x71\x80\xc6\x1e\x36\x48\x74\x22\x41\x5c\x87\x82\xe8\x18\x71\x8b\x41\x89\x44\xe7\x7e\x58\x5b\xa8\xb8\x8d\x13\xe9\xa7\x6c\xc3\x47\xed\xb3\x1a\x9d\x62\xae\x8d\x82\xea\x94\x9e\xdd\x59\x10\xc3\xad\xdd\xe2\x4d\xe3\x31\xd5\xc7\xec\xe8\xf2\xb0\xfe\x92\x1e\x16\x0a\x1a\xfc\xd9\xf3\xf8\x27\xb6\xc9\xbe\x1d\xb4\x6c\x64\x90\x7f\xf4\xe4\xc4\x5b\xd7\x37\xae\x42\x0e\xdd\xa4\x1a\x6f\x7c\x88\x54\xc5\x16\x6e\xe1\x7a\x68\x2e\xf8\x3a\xbf\x0d\xa4\x3c\x89\x3b\x78\xa7\x4e\x63\x83\x04\x21\x08\x67\x8d\xf2\x82\x49\xd0\x5b\xfd\xb1\xcd\x0f\x83\x84\xd4\x3e\x20\x85\xf7\x4a\x3d\x2b\x9c\xfd\x2a\x0a\x09\x4d\xea\x81\xf8\x11\x9c", 0 }, + /* Anchor: 40 cisco-ca2048.der serial: #{a.serial.to_s} + O=Cisco Systems,CN=Cisco Root CA 2048 + */ + { 839, "\x30\x82\x03\x43\x30\x82\x02\x2b\xa0\x03\x02\x01\x02\x02\x10\x5f\xf8\x7b\x28\x2b\x54\xdc\x8d\x42\xa3\x15\xb5\x68\xc9\xad\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x35\x31\x16\x30\x14\x06\x03\x55\x04\x0a\x13\x0d\x43\x69\x73\x63\x6f\x20\x53\x79\x73\x74\x65\x6d\x73\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x13\x12\x43\x69\x73\x63\x6f\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x32\x30\x34\x38\x30\x1e\x17\x0d\x30\x34\x30\x35\x31\x34\x32\x30\x31\x37\x31\x32\x5a\x17\x0d\x32\x39\x30\x35\x31\x34\x32\x30\x32\x35\x34\x32\x5a\x30\x35\x31\x16\x30\x14\x06\x03\x55\x04\x0a\x13\x0d\x43\x69\x73\x63\x6f\x20\x53\x79\x73\x74\x65\x6d\x73\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x13\x12\x43\x69\x73\x63\x6f\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x32\x30\x34\x38\x30\x82\x01\x20\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0d\x00\x30\x82\x01\x08\x02\x82\x01\x01\x00\xb0\x9a\xb9\xab\xa7\xaf\x0a\x77\xa7\xe2\x71\xb6\xb4\x66\x62\x94\x78\x88\x47\xc6\x62\x55\x84\x40\x32\xbf\xc0\xab\x2e\xa5\x1c\x71\xd6\xbc\x6e\x7b\xa8\xaa\xba\x6e\xd2\x15\x88\x48\x45\x9d\xa2\xfc\x83\xd0\xcc\xb9\x8c\xe0\x26\x68\x70\x4a\x78\xdf\x21\x17\x9e\xf4\x61\x05\xc9\x15\xc8\xcf\x16\xda\x35\x61\x89\x94\x43\xa8\x84\xa8\x31\x98\x78\x9b\xb9\x4e\x6f\x2c\x53\x12\x6c\xcd\x1d\xad\x2b\x24\xbb\x31\xc4\x2b\xff\x83\x44\x6f\xb6\x3d\x24\x77\x09\xea\xbf\x2a\xa8\x1f\x6a\x56\xf6\x20\x0f\x11\x54\x97\x81\x75\xa7\x25\xce\x59\x6a\x82\x65\xef\xb7\xea\xe7\xe2\x8d\x75\x8b\x6e\xf2\xdd\x4f\xa6\x5e\x62\x9c\xcf\x10\x0a\x64\xd0\x4e\x6d\xce\x2b\xcc\x5b\xf5\x60\xa5\x27\x47\x8d\x69\xf4\x7f\xce\x1b\x70\xde\x70\x1b\x20\xd6\x6e\xcd\xa6\x01\xa8\x3c\x12\xd2\xa9\x3f\xa0\x6b\x5e\xbb\x8e\x20\x8b\x7a\x91\xe3\xb5\x68\xee\xa0\xe7\xc4\x01\x74\xa8\x53\x0b\x2b\x4a\x9a\x0f\x65\x12\x0e\x82\x4d\x8e\x63\xfd\xef\xeb\x9b\x1a\xdb\x53\xa6\x13\x60\xaf\xc2\x7d\xd7\xc7\x6c\x17\x25\xd4\x73\xfb\x47\x64\x50\x81\x80\x94\x4c\xe1\xbf\xae\x4b\x1c\xdf\x92\xed\x2e\x05\xdf\x02\x01\x03\xa3\x51\x30\x4f\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x86\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x27\xf3\xc8\x15\x1e\x6e\x9a\x02\x09\x16\xad\x2b\xa0\x89\x60\x5f\xda\x7b\x2f\xaa\x30\x10\x06\x09\x2b\x06\x01\x04\x01\x82\x37\x15\x01\x04\x03\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x9d\x9d\x84\x84\xa3\x41\xa9\x7c\x77\x0c\xb7\x53\xca\x4e\x44\x50\x62\xef\x54\x7c\xd3\x75\x17\x1c\xe8\xe0\xc6\x48\x4b\xb6\xfe\x4c\x3a\x19\x81\x56\xb0\x56\xee\x19\x96\x62\xaa\x5a\xa3\x64\xc1\xf6\x4e\x54\x33\xc6\x77\xfe\xc5\x1c\xba\xe5\x5d\x25\xca\xf5\xf0\x93\x9a\x83\x11\x2e\xe6\xcb\xf8\x74\x45\xfe\xe7\x05\xb8\xab\xe7\xdf\xcb\x4b\xe1\x37\x84\xda\xb9\x8b\x97\x70\x1e\xf0\xe2\x8b\xd7\xb0\xd8\x0e\x9d\xb1\x69\xd6\x2a\x91\x7b\xa9\x49\x4f\x7e\xe6\x8e\x95\xd8\x83\x27\x3c\xd5\x68\x49\x0e\xd4\x9d\xf6\x2e\xeb\xa7\xbe\xeb\x30\xa4\xac\x1f\x44\xfc\x95\xab\x33\x06\xfb\x7d\x60\x0a\xde\xb4\x8a\x63\xb0\x9c\xa9\xf2\xa4\xb9\x53\x01\x87\xd0\x68\xa4\x27\x7f\xab\xff\xe9\xfa\xc9\x40\x38\x88\x67\xb4\x39\xc6\x84\x6f\x57\xc9\x53\xdb\xba\x8e\xee\xc0\x43\xb2\xf8\x09\x83\x6e\xff\x66\xcf\x3e\xef\x17\xb3\x58\x18\x25\x09\x34\x5e\xe3\xcb\xd6\x14\xb6\xec\xf2\x92\x6f\x74\xe4\x2f\x81\x2a\xd5\x92\x91\xe0\xe0\x97\x3c\x32\x68\x05\x85\x4b\xd1\xf7\x57\xe2\x52\x1d\x93\x1a\x54\x9f\x05\x70\xc0\x4a\x71\x60\x1e\x43\x0b\x60\x1e\xfe\xa3\xce\x81\x19\xe1\x0b\x35", 0 }, + /* Anchor: 41 Class1_PCA_G2_v2.509 serial: #{a.serial.to_s} + C=US,O=VeriSign\, Inc.,OU=Class 1 Public Primary Certification Authority - G2,OU=(c) 1998 VeriSign\, Inc. - For authorized use only,OU=VeriSign Trust Network + */ + { 774, "\x30\x82\x03\x02\x30\x82\x02\x6b\x02\x10\x4c\xc7\xea\xaa\x98\x3e\x71\xd3\x93\x10\xf8\x3d\x3a\x89\x91\x92\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xc1\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x3c\x30\x3a\x06\x03\x55\x04\x0b\x13\x33\x43\x6c\x61\x73\x73\x20\x31\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x32\x31\x3a\x30\x38\x06\x03\x55\x04\x0b\x13\x31\x28\x63\x29\x20\x31\x39\x39\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x30\x1e\x17\x0d\x39\x38\x30\x35\x31\x38\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x38\x30\x38\x30\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xc1\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x3c\x30\x3a\x06\x03\x55\x04\x0b\x13\x33\x43\x6c\x61\x73\x73\x20\x31\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x32\x31\x3a\x30\x38\x06\x03\x55\x04\x0b\x13\x31\x28\x63\x29\x20\x31\x39\x39\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xaa\xd0\xba\xbe\x16\x2d\xb8\x83\xd4\xca\xd2\x0f\xbc\x76\x31\xca\x94\xd8\x1d\x93\x8c\x56\x02\xbc\xd9\x6f\x1a\x6f\x52\x36\x6e\x75\x56\x0a\x55\xd3\xdf\x43\x87\x21\x11\x65\x8a\x7e\x8f\xbd\x21\xde\x6b\x32\x3f\x1b\x84\x34\x95\x05\x9d\x41\x35\xeb\x92\xeb\x96\xdd\xaa\x59\x3f\x01\x53\x6d\x99\x4f\xed\xe5\xe2\x2a\x5a\x90\xc1\xb9\xc4\xa6\x15\xcf\xc8\x45\xeb\xa6\x5d\x8e\x9c\x3e\xf0\x64\x24\x76\xa5\xcd\xab\x1a\x6f\xb6\xd8\x7b\x51\x61\x6e\xa6\x7f\x87\xc8\xe2\xb7\xe5\x34\xdc\x41\x88\xea\x09\x40\xbe\x73\x92\x3d\x6b\xe7\x75\x02\x03\x01\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\xa9\x4f\xc3\x0d\xc7\x67\xbe\x2c\xcb\xd9\xa8\xcd\x2d\x75\xe7\x7e\x15\x9e\x3b\x72\xeb\x7e\xeb\x5c\x2d\x09\x87\xd6\x6b\x6d\x60\x7c\xe5\xae\xc5\x90\x23\x0c\x5c\x4a\xd0\xaf\xb1\x5d\xf3\xc7\xb6\x0a\xdb\xe0\x15\x93\x0d\xdd\x03\xbc\xc7\x76\x8a\xb5\xdd\x4f\xc3\x9b\x13\x75\xb8\x01\xc0\xe6\xc9\x5b\x6b\xa5\xb8\x89\xdc\xac\xa4\xdd\x72\xed\x4e\xa1\xf7\x4f\xbc\x06\xd3\xea\xc8\x64\x74\x7b\xc2\x95\x41\x9c\x65\x73\x58\xf1\x90\x9a\x3c\x6a\xb1\x98\xc9\xc4\x87\xbc\xcf\x45\x6d\x45\xe2\x6e\x22\x3f\xfe\xbc\x0f\x31\x5c\xe8\xf2\xd9", 0 }, + /* Anchor: 42 Class2_PCA_G2_v2.509 serial: #{a.serial.to_s} + C=US,O=VeriSign\, Inc.,OU=Class 2 Public Primary Certification Authority - G2,OU=(c) 1998 VeriSign\, Inc. - For authorized use only,OU=VeriSign Trust Network + */ + { 775, "\x30\x82\x03\x03\x30\x82\x02\x6c\x02\x11\x00\xb9\x2f\x60\xcc\x88\x9f\xa1\x7a\x46\x09\xb8\x5b\x70\x6c\x8a\xaf\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xc1\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x3c\x30\x3a\x06\x03\x55\x04\x0b\x13\x33\x43\x6c\x61\x73\x73\x20\x32\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x32\x31\x3a\x30\x38\x06\x03\x55\x04\x0b\x13\x31\x28\x63\x29\x20\x31\x39\x39\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x30\x1e\x17\x0d\x39\x38\x30\x35\x31\x38\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x38\x30\x38\x30\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xc1\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x3c\x30\x3a\x06\x03\x55\x04\x0b\x13\x33\x43\x6c\x61\x73\x73\x20\x32\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x32\x31\x3a\x30\x38\x06\x03\x55\x04\x0b\x13\x31\x28\x63\x29\x20\x31\x39\x39\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xa7\x88\x01\x21\x74\x2c\xe7\x1a\x03\xf0\x98\xe1\x97\x3c\x0f\x21\x08\xf1\x9c\xdb\x97\xe9\x9a\xfc\xc2\x04\x06\x13\xbe\x5f\x52\xc8\xcc\x1e\x2c\x12\x56\x2c\xb8\x01\x69\x2c\xcc\x99\x1f\xad\xb0\x96\xae\x79\x04\xf2\x13\x39\xc1\x7b\x98\xba\x08\x2c\xe8\xc2\x84\x13\x2c\xaa\x69\xe9\x09\xf4\xc7\xa9\x02\xa4\x42\xc2\x23\x4f\x4a\xd8\xf0\x0e\xa2\xfb\x31\x6c\xc9\xe6\x6f\x99\x27\x07\xf5\xe6\xf4\x4c\x78\x9e\x6d\xeb\x46\x86\xfa\xb9\x86\xc9\x54\xf2\xb2\xc4\xaf\xd4\x46\x1c\x5a\xc9\x15\x30\xff\x0d\x6c\xf5\x2d\x0e\x6d\xce\x7f\x77\x02\x03\x01\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x72\x2e\xf9\x7f\xd1\xf1\x71\xfb\xc4\x9e\xf6\xc5\x5e\x51\x8a\x40\x98\xb8\x68\xf8\x9b\x1c\x83\xd8\xe2\x9d\xbd\xff\xed\xa1\xe6\x66\xea\x2f\x09\xf4\xca\xd7\xea\xa5\x2b\x95\xf6\x24\x60\x86\x4d\x44\x2e\x83\xa5\xc4\x2d\xa0\xd3\xae\x78\x69\x6f\x72\xda\x6c\xae\x08\xf0\x63\x92\x37\xe6\xbb\xc4\x30\x17\xad\x77\xcc\x49\x35\xaa\xcf\xd8\x8f\xd1\xbe\xb7\x18\x96\x47\x73\x6a\x54\x22\x34\x64\x2d\xb6\x16\x9b\x59\x5b\xb4\x51\x59\x3a\xb3\x0b\x14\xf4\x12\xdf\x67\xa0\xf4\xad\x32\x64\x5e\xb1\x46\x72\x27\x8c\x12\x7b\xc5\x44\xb4\xae", 0 }, + /* Anchor: 43 Class3_PCA_G2_v2.509 serial: #{a.serial.to_s} + C=US,O=VeriSign\, Inc.,OU=Class 3 Public Primary Certification Authority - G2,OU=(c) 1998 VeriSign\, Inc. - For authorized use only,OU=VeriSign Trust Network + */ + { 774, "\x30\x82\x03\x02\x30\x82\x02\x6b\x02\x10\x7d\xd9\xfe\x07\xcf\xa8\x1e\xb7\x10\x79\x67\xfb\xa7\x89\x34\xc6\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xc1\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x3c\x30\x3a\x06\x03\x55\x04\x0b\x13\x33\x43\x6c\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x32\x31\x3a\x30\x38\x06\x03\x55\x04\x0b\x13\x31\x28\x63\x29\x20\x31\x39\x39\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x30\x1e\x17\x0d\x39\x38\x30\x35\x31\x38\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x38\x30\x38\x30\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xc1\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x3c\x30\x3a\x06\x03\x55\x04\x0b\x13\x33\x43\x6c\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x32\x31\x3a\x30\x38\x06\x03\x55\x04\x0b\x13\x31\x28\x63\x29\x20\x31\x39\x39\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xcc\x5e\xd1\x11\x5d\x5c\x69\xd0\xab\xd3\xb9\x6a\x4c\x99\x1f\x59\x98\x30\x8e\x16\x85\x20\x46\x6d\x47\x3f\xd4\x85\x20\x84\xe1\x6d\xb3\xf8\xa4\xed\x0c\xf1\x17\x0f\x3b\xf9\xa7\xf9\x25\xd7\xc1\xcf\x84\x63\xf2\x7c\x63\xcf\xa2\x47\xf2\xc6\x5b\x33\x8e\x64\x40\x04\x68\xc1\x80\xb9\x64\x1c\x45\x77\xc7\xd8\x6e\xf5\x95\x29\x3c\x50\xe8\x34\xd7\x78\x1f\xa8\xba\x6d\x43\x91\x95\x8f\x45\x57\x5e\x7e\xc5\xfb\xca\xa4\x04\xeb\xea\x97\x37\x54\x30\x6f\xbb\x01\x47\x32\x33\xcd\xdc\x57\x9b\x64\x69\x61\xf8\x9b\x1d\x1c\x89\x4f\x5c\x67\x02\x03\x01\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x51\x4d\xcd\xbe\x5c\xcb\x98\x19\x9c\x15\xb2\x01\x39\x78\x2e\x4d\x0f\x67\x70\x70\x99\xc6\x10\x5a\x94\xa4\x53\x4d\x54\x6d\x2b\xaf\x0d\x5d\x40\x8b\x64\xd3\xd7\xee\xde\x56\x61\x92\x5f\xa6\xc4\x1d\x10\x61\x36\xd3\x2c\x27\x3c\xe8\x29\x09\xb9\x11\x64\x74\xcc\xb5\x73\x9f\x1c\x48\xa9\xbc\x61\x01\xee\xe2\x17\xa6\x0c\xe3\x40\x08\x3b\x0e\xe7\xeb\x44\x73\x2a\x9a\xf1\x69\x92\xef\x71\x14\xc3\x39\xac\x71\xa7\x91\x09\x6f\xe4\x71\x06\xb3\xba\x59\x57\x26\x79\x00\xf6\xf8\x0d\xa2\x33\x30\x28\xd4\xaa\x58\xa0\x9d\x9d\x69\x91\xfd", 0 }, + /* Anchor: 44 Class4_PCA_G2_v2.509 serial: #{a.serial.to_s} + C=US,O=VeriSign\, Inc.,OU=Class 4 Public Primary Certification Authority - G2,OU=(c) 1998 VeriSign\, Inc. - For authorized use only,OU=VeriSign Trust Network + */ + { 774, "\x30\x82\x03\x02\x30\x82\x02\x6b\x02\x10\x32\x88\x8e\x9a\xd2\xf5\xeb\x13\x47\xf8\x7f\xc4\x20\x37\x25\xf8\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xc1\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x3c\x30\x3a\x06\x03\x55\x04\x0b\x13\x33\x43\x6c\x61\x73\x73\x20\x34\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x32\x31\x3a\x30\x38\x06\x03\x55\x04\x0b\x13\x31\x28\x63\x29\x20\x31\x39\x39\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x30\x1e\x17\x0d\x39\x38\x30\x35\x31\x38\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x38\x30\x38\x30\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xc1\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x3c\x30\x3a\x06\x03\x55\x04\x0b\x13\x33\x43\x6c\x61\x73\x73\x20\x34\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x32\x31\x3a\x30\x38\x06\x03\x55\x04\x0b\x13\x31\x28\x63\x29\x20\x31\x39\x39\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xba\xf0\xe4\xcf\xf9\xc4\xae\x85\x54\xb9\x07\x57\xf9\x8f\xc5\x7f\x68\x11\xf8\xc4\x17\xb0\x44\xdc\xe3\x30\x73\xd5\x2a\x62\x2a\xb8\xd0\xcc\x1c\xed\x28\x5b\x7e\xbd\x6a\xdc\xb3\x91\x24\xca\x41\x62\x3c\xfc\x02\x01\xbf\x1c\x16\x31\x94\x05\x97\x76\x6e\xa2\xad\xbd\x61\x17\x6c\x4e\x30\x86\xf0\x51\x37\x2a\x50\xc7\xa8\x62\x81\xdc\x5b\x4a\xaa\xc1\xa0\xb4\x6e\xeb\x2f\xe5\x57\xc5\xb1\x2b\x40\x70\xdb\x5a\x4d\xa1\x8e\x1f\xbd\x03\x1f\xd8\x03\xd4\x8f\x4c\x99\x71\xbc\xe2\x82\xcc\x58\xe8\x98\x3a\x86\xd3\x86\x38\xf3\x00\x29\x1f\x02\x03\x01\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x85\x8c\x12\xc1\xa7\xb9\x50\x15\x7a\xcb\x3e\xac\xb8\x43\x8a\xdc\xaa\xdd\x14\xba\x89\x81\x7e\x01\x3c\x23\x71\x21\x88\x2f\x82\xdc\x63\xfa\x02\x45\xac\x45\x59\xd7\x2a\x58\x44\x5b\xb7\x9f\x81\x3b\x92\x68\x3d\xe2\x37\x24\xf5\x7b\x6c\x8f\x76\x35\x96\x09\xa8\x59\x9d\xb9\xce\x23\xab\x74\xd6\x83\xfd\x32\x73\x27\xd8\x69\x3e\x43\x74\xf6\xae\xc5\x89\x9a\xe7\x53\x7c\xe9\x7b\xf6\x4b\xf3\xc1\x65\x83\xde\x8d\x8a\x9c\x3c\x88\x8d\x39\x59\xfc\xaa\x3f\x22\x8d\xa1\xc1\x66\x50\x81\x72\x4c\xed\x22\x64\x4f\x4f\xca\x80\x91\xb6\x29", 0 }, + /* Anchor: 45 CNNICEVRoot.der serial: #{a.serial.to_s} + C=CN,O=China Internet Network Information Center,CN=China Internet Network Information Center EV Certificates Root + */ + { 1019, "\x30\x82\x03\xf7\x30\x82\x02\xdf\xa0\x03\x02\x01\x02\x02\x04\x48\x9f\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\x8a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4e\x31\x32\x30\x30\x06\x03\x55\x04\x0a\x0c\x29\x43\x68\x69\x6e\x61\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x20\x49\x6e\x66\x6f\x72\x6d\x61\x74\x69\x6f\x6e\x20\x43\x65\x6e\x74\x65\x72\x31\x47\x30\x45\x06\x03\x55\x04\x03\x0c\x3e\x43\x68\x69\x6e\x61\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x20\x49\x6e\x66\x6f\x72\x6d\x61\x74\x69\x6f\x6e\x20\x43\x65\x6e\x74\x65\x72\x20\x45\x56\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x73\x20\x52\x6f\x6f\x74\x30\x1e\x17\x0d\x31\x30\x30\x38\x33\x31\x30\x37\x31\x31\x32\x35\x5a\x17\x0d\x33\x30\x30\x38\x33\x31\x30\x37\x31\x31\x32\x35\x5a\x30\x81\x8a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4e\x31\x32\x30\x30\x06\x03\x55\x04\x0a\x0c\x29\x43\x68\x69\x6e\x61\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x20\x49\x6e\x66\x6f\x72\x6d\x61\x74\x69\x6f\x6e\x20\x43\x65\x6e\x74\x65\x72\x31\x47\x30\x45\x06\x03\x55\x04\x03\x0c\x3e\x43\x68\x69\x6e\x61\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x20\x49\x6e\x66\x6f\x72\x6d\x61\x74\x69\x6f\x6e\x20\x43\x65\x6e\x74\x65\x72\x20\x45\x56\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x73\x20\x52\x6f\x6f\x74\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\x9b\x7e\x73\xee\xbd\x3b\x78\xaa\x64\x43\x41\xf5\x50\xdf\x94\xf2\x2e\xb2\x8d\x4a\x8e\x46\x54\xd2\x21\x12\xc8\x39\x32\x42\x06\xe9\x83\xd5\x9f\x52\xed\xe5\x67\x03\x3b\x54\xc1\x8c\x99\x99\xcc\xe9\xc0\x0f\xff\x0d\xd9\x84\x11\xb2\xb8\xd1\xcb\x5b\xdc\x1e\xf9\x68\x31\x64\xe1\x9b\xfa\x74\xeb\x68\xb9\x20\x95\xf7\xc6\x0f\x8d\x47\xac\x5a\x06\xdd\x61\xab\xe2\xec\xd8\x9f\x17\x2d\x9c\xca\x3c\x35\x97\x55\x71\xcd\x43\x85\xb1\x47\x16\xf5\x2c\x53\x80\x76\xcf\xd3\x00\x64\xbd\x40\x99\xdd\xcc\xd8\xdb\xc4\x9f\xd6\x13\x5f\x41\x83\x8b\xf9\x0d\x87\x92\x56\x34\x6c\x1a\x10\x0b\x17\xd5\x5a\x1c\x97\x58\x84\x3c\x84\x1a\x2e\x5c\x91\x34\x6e\x19\x5f\x7f\x17\x69\xc5\x65\xef\x6b\x21\xc6\xd5\x50\x3a\xbf\x61\xb9\x05\x8d\xef\x6f\x34\x3a\xb2\x6f\x14\x63\xbf\x16\x3b\x9b\xa9\x2a\xfd\xb7\x2b\x38\x66\x06\xc5\x2c\xe2\xaa\x67\x1e\x45\xa7\x8d\x04\x66\x42\xf6\x8f\x2b\xef\x88\x20\x69\x8f\x32\x8c\x14\x73\xda\x2b\x86\x91\x63\x22\x9a\xf2\xa7\xdb\xce\x89\x8b\xab\x5d\xc7\x14\xc1\x5b\x30\x6a\x1f\xb1\xb7\x9e\x2e\x81\x01\x02\xed\xcf\x96\x5e\x63\xdb\xa8\xe6\x38\xb7\x02\x03\x01\x00\x01\xa3\x63\x30\x61\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x7c\x72\x4b\x39\xc7\xc0\xdb\x62\xa5\x4f\x9b\xaa\x18\x34\x92\xa2\xca\x83\x82\x59\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x7c\x72\x4b\x39\xc7\xc0\xdb\x62\xa5\x4f\x9b\xaa\x18\x34\x92\xa2\xca\x83\x82\x59\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x2a\xc3\xc7\x43\x37\x8f\xdd\xad\xa4\xb2\x0c\xee\xdc\x14\x6d\x8f\x28\xa4\x98\x49\xcb\x0c\x80\xea\xf3\xed\x23\x66\x75\x7d\xc5\xd3\x21\x67\x79\xd1\x73\xc5\xb5\x03\xb7\x58\xac\x0c\x54\x2f\xc6\x56\x13\x0f\x31\xda\x06\xe7\x65\x3b\x1d\x6f\x36\xdb\xc8\x1d\xf9\xfd\x80\x06\xca\xa3\x3d\x66\x16\xa8\x9d\x4c\x16\x7d\xc0\x95\x46\xb5\x51\xe4\xe2\x1f\xd7\xea\x06\x4d\x63\x8d\x96\x8c\xef\xe7\x33\x57\x42\x3a\xeb\x8c\xc1\x79\xc8\x4d\x76\x7d\xde\xf6\xb1\xb7\x81\xe0\xa0\xf9\xa1\x78\x46\x17\x1a\x56\x98\xf0\x4e\x3d\xab\x1c\xed\xec\x39\xdc\x07\x48\xf7\x63\xfe\x06\xae\xc2\xa4\x5c\x6a\x5b\x32\x88\xc5\xc7\x33\x85\xac\x66\x42\x47\xc2\x58\x24\x99\xe1\xe5\x3e\xe5\x75\x2c\x8e\x43\xd6\x5d\x3c\x78\x1e\xa8\x95\x82\x29\x50\xd1\xd1\x16\xba\xef\xc1\xbe\x7a\xd9\xb4\xd8\xcc\x1e\x4c\x46\xe1\x77\xb1\x31\xab\xbd\x2a\xc8\xce\x8f\x6e\xa1\x5d\x7f\x03\x75\x34\xe4\xad\x89\x45\x54\x5e\xbe\xae\x28\xa5\xbb\x3f\x78\x79\xeb\x73\xb3\x0a\x0d\xfd\xbe\xc9\xf7\x56\xac\xf6\xb7\xed\x2f\x9b\x21\x29\xc7\x38\xb6\x95\xc4\x04\xf2\xc3\x2d\xfd\x14\x2a\x90\x99\xb9\x07\xcc\x9f", 0 }, + /* Anchor: 46 cnnicroot.cer serial: #{a.serial.to_s} + C=CN,O=CNNIC,CN=CNNIC ROOT + */ + { 857, "\x30\x82\x03\x55\x30\x82\x02\x3d\xa0\x03\x02\x01\x02\x02\x04\x49\x33\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x32\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4e\x31\x0e\x30\x0c\x06\x03\x55\x04\x0a\x13\x05\x43\x4e\x4e\x49\x43\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x43\x4e\x4e\x49\x43\x20\x52\x4f\x4f\x54\x30\x1e\x17\x0d\x30\x37\x30\x34\x31\x36\x30\x37\x30\x39\x31\x34\x5a\x17\x0d\x32\x37\x30\x34\x31\x36\x30\x37\x30\x39\x31\x34\x5a\x30\x32\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4e\x31\x0e\x30\x0c\x06\x03\x55\x04\x0a\x13\x05\x43\x4e\x4e\x49\x43\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x43\x4e\x4e\x49\x43\x20\x52\x4f\x4f\x54\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xd3\x35\xf7\x3f\x73\x77\xad\xe8\x5b\x73\x17\xc2\xd1\x6f\xed\x55\xbc\x6e\xea\xe8\xa4\x79\xb2\x6c\xc3\xa3\xef\xe1\x9f\xb1\x3b\x48\x85\xf5\x9a\x5c\x21\x22\x10\x2c\xc5\x82\xce\xda\xe3\x9a\x6e\x37\xe1\x87\x2c\xdc\xb9\x0c\x5a\xba\x88\x55\xdf\xfd\xaa\xdb\x1f\x31\xea\x01\xf1\xdf\x39\x01\xc1\x13\xfd\x48\x52\x21\xc4\x55\xdf\xda\xd8\xb3\x54\x76\xba\x74\xb1\xb7\x7d\xd7\xc0\xe8\xf6\x59\xc5\x4d\xc8\xbd\xad\x1f\x14\xda\xdf\x58\x44\x25\x32\x19\x2a\xc7\x7e\x7e\x8e\xae\x38\xb0\x30\x7b\x47\x72\x09\x31\xf0\x30\xdb\xc3\x1b\x76\x29\xbb\x69\x76\x4e\x57\xf9\x1b\x64\xa2\x93\x56\xb7\x6f\x99\x6e\xdb\x0a\x04\x9c\x11\xe3\x80\x1f\xcb\x63\x94\x10\x0a\xa9\xe1\x64\x82\x31\xf9\x8c\x27\xed\xa6\x99\x00\xf6\x70\x93\x18\xf8\xa1\x34\x86\xa3\xdd\x7a\xc2\x18\x79\xf6\x7a\x65\x35\xcf\x90\xeb\xbd\x33\x93\x9f\x53\xab\x73\x3b\xe6\x9b\x34\x20\x2f\x1d\xef\xa9\x1d\x63\x1a\xa0\x80\xdb\x03\x2f\xf9\x26\x1a\x86\xd2\x8d\xbb\xa9\xbe\x52\x3a\x87\x67\x48\x0d\xbf\xb4\xa0\xd8\x26\xbe\x23\x5f\x73\x37\x7f\x26\xe6\x92\x04\xa3\x7f\xcf\x20\xa7\xb7\xf3\x3a\xca\xcb\x99\xcb\x02\x03\x01\x00\x01\xa3\x73\x30\x71\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x65\xf2\x31\xad\x2a\xf7\xf7\xdd\x52\x96\x0a\xc7\x02\xc1\x0e\xef\xa6\xd5\x3b\x11\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\xfe\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x65\xf2\x31\xad\x2a\xf7\xf7\xdd\x52\x96\x0a\xc7\x02\xc1\x0e\xef\xa6\xd5\x3b\x11\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x4b\x35\xee\xcc\xe4\xae\xbf\xc3\x6e\xad\x9f\x95\x3b\x4b\x3f\x5b\x1e\xdf\x57\x29\xa2\x59\xca\x38\xe2\xb9\x1a\xff\x9e\xe6\x6e\x32\xdd\x1e\xae\xea\x35\xb7\xf5\x93\x91\x4e\xda\x42\xe1\xc3\x17\x60\x50\xf2\xd1\x5c\x26\xb9\x82\xb7\xea\x6d\xe4\x9c\x84\xe7\x03\x79\x17\xaf\x98\x3d\x94\xdb\xc7\xba\x00\xe7\xb8\xbf\x01\x57\xc1\x77\x45\x32\x0c\x3b\xf1\xb4\x1c\x08\xb0\xfd\x51\xa0\xa1\xdd\x9a\x1d\x13\x36\x9a\x6d\xb7\xc7\x3c\xb9\xe1\xc5\xd9\x17\xfa\x83\xd5\x3d\x15\xa0\x3c\xbb\x1e\x0b\xe2\xc8\x90\x3f\xa8\x86\x0c\xfc\xf9\x8b\x5e\x85\xcb\x4f\x5b\x4b\x62\x11\x47\xc5\x45\x7c\x05\x2f\x41\xb1\x9e\x10\x69\x1b\x99\x96\xe0\x55\x79\xfb\x4e\x86\x99\xb8\x94\xda\x86\x38\x6a\x93\xa3\xe7\xcb\x6e\xe5\xdf\xea\x21\x55\x89\x9c\x7d\x7d\x7f\x98\xf5\x00\x89\xee\xe3\x84\xc0\x5c\x96\xb5\xc5\x46\xea\x46\xe0\x85\x55\xb6\x1b\xc9\x12\xd6\xc1\xcd\xcd\x80\xf3\x02\x01\x3c\xc8\x69\xcb\x45\x48\x63\xd8\x94\xd0\xec\x85\x0e\x3b\x4e\x11\x65\xf4\x82\x8c\xa6\x3d\xae\x2e\x22\x94\x09\xc8\x5c\xea\x3c\x81\x5d\x16\x2a\x03\x97\x16\x55\x09\xdb\x8a\x41\x82\x9e\x66\x9b\x11", 0 }, + /* Anchor: 47 Comodo_AAA_Certificate_Services.cer serial: #{a.serial.to_s} + C=GB,ST=Greater Manchester,L=Salford,O=Comodo CA Limited,CN=AAA Certificate Services + */ + { 1078, "\x30\x82\x04\x32\x30\x82\x03\x1a\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x7b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1b\x30\x19\x06\x03\x55\x04\x08\x0c\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4d\x61\x6e\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c\x07\x53\x61\x6c\x66\x6f\x72\x64\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x0c\x11\x43\x6f\x6d\x6f\x64\x6f\x20\x43\x41\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x0c\x18\x41\x41\x41\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x30\x1e\x17\x0d\x30\x34\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x38\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x7b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1b\x30\x19\x06\x03\x55\x04\x08\x0c\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4d\x61\x6e\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c\x07\x53\x61\x6c\x66\x6f\x72\x64\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x0c\x11\x43\x6f\x6d\x6f\x64\x6f\x20\x43\x41\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x0c\x18\x41\x41\x41\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xbe\x40\x9d\xf4\x6e\xe1\xea\x76\x87\x1c\x4d\x45\x44\x8e\xbe\x46\xc8\x83\x06\x9d\xc1\x2a\xfe\x18\x1f\x8e\xe4\x02\xfa\xf3\xab\x5d\x50\x8a\x16\x31\x0b\x9a\x06\xd0\xc5\x70\x22\xcd\x49\x2d\x54\x63\xcc\xb6\x6e\x68\x46\x0b\x53\xea\xcb\x4c\x24\xc0\xbc\x72\x4e\xea\xf1\x15\xae\xf4\x54\x9a\x12\x0a\xc3\x7a\xb2\x33\x60\xe2\xda\x89\x55\xf3\x22\x58\xf3\xde\xdc\xcf\xef\x83\x86\xa2\x8c\x94\x4f\x9f\x68\xf2\x98\x90\x46\x84\x27\xc7\x76\xbf\xe3\xcc\x35\x2c\x8b\x5e\x07\x64\x65\x82\xc0\x48\xb0\xa8\x91\xf9\x61\x9f\x76\x20\x50\xa8\x91\xc7\x66\xb5\xeb\x78\x62\x03\x56\xf0\x8a\x1a\x13\xea\x31\xa3\x1e\xa0\x99\xfd\x38\xf6\xf6\x27\x32\x58\x6f\x07\xf5\x6b\xb8\xfb\x14\x2b\xaf\xb7\xaa\xcc\xd6\x63\x5f\x73\x8c\xda\x05\x99\xa8\x38\xa8\xcb\x17\x78\x36\x51\xac\xe9\x9e\xf4\x78\x3a\x8d\xcf\x0f\xd9\x42\xe2\x98\x0c\xab\x2f\x9f\x0e\x01\xde\xef\x9f\x99\x49\xf1\x2d\xdf\xac\x74\x4d\x1b\x98\xb5\x47\xc5\xe5\x29\xd1\xf9\x90\x18\xc7\x62\x9c\xbe\x83\xc7\x26\x7b\x3e\x8a\x25\xc7\xc0\xdd\x9d\xe6\x35\x68\x10\x20\x9d\x8f\xd8\xde\xd2\xc3\x84\x9c\x0d\x5e\xe8\x2f\xc9\x02\x03\x01\x00\x01\xa3\x81\xc0\x30\x81\xbd\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xa0\x11\x0a\x23\x3e\x96\xf1\x07\xec\xe2\xaf\x29\xef\x82\xa5\x7f\xd0\x30\xa4\xb4\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x7b\x06\x03\x55\x1d\x1f\x04\x74\x30\x72\x30\x38\xa0\x36\xa0\x34\x86\x32\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x63\x6f\x6d\x6f\x64\x6f\x63\x61\x2e\x63\x6f\x6d\x2f\x41\x41\x41\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x53\x65\x72\x76\x69\x63\x65\x73\x2e\x63\x72\x6c\x30\x36\xa0\x34\xa0\x32\x86\x30\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x63\x6f\x6d\x6f\x64\x6f\x2e\x6e\x65\x74\x2f\x41\x41\x41\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x53\x65\x72\x76\x69\x63\x65\x73\x2e\x63\x72\x6c\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x08\x56\xfc\x02\xf0\x9b\xe8\xff\xa4\xfa\xd6\x7b\xc6\x44\x80\xce\x4f\xc4\xc5\xf6\x00\x58\xcc\xa6\xb6\xbc\x14\x49\x68\x04\x76\xe8\xe6\xee\x5d\xec\x02\x0f\x60\xd6\x8d\x50\x18\x4f\x26\x4e\x01\xe3\xe6\xb0\xa5\xee\xbf\xbc\x74\x54\x41\xbf\xfd\xfc\x12\xb8\xc7\x4f\x5a\xf4\x89\x60\x05\x7f\x60\xb7\x05\x4a\xf3\xf6\xf1\xc2\xbf\xc4\xb9\x74\x86\xb6\x2d\x7d\x6b\xcc\xd2\xf3\x46\xdd\x2f\xc6\xe0\x6a\xc3\xc3\x34\x03\x2c\x7d\x96\xdd\x5a\xc2\x0e\xa7\x0a\x99\xc1\x05\x8b\xab\x0c\x2f\xf3\x5c\x3a\xcf\x6c\x37\x55\x09\x87\xde\x53\x40\x6c\x58\xef\xfc\xb6\xab\x65\x6e\x04\xf6\x1b\xdc\x3c\xe0\x5a\x15\xc6\x9e\xd9\xf1\x59\x48\x30\x21\x65\x03\x6c\xec\xe9\x21\x73\xec\x9b\x03\xa1\xe0\x37\xad\xa0\x15\x18\x8f\xfa\xba\x02\xce\xa7\x2c\xa9\x10\x13\x2c\xd4\xe5\x08\x26\xab\x22\x97\x60\xf8\x90\x5e\x74\xd4\xa2\x9a\x53\xbd\xf2\xa9\x68\xe0\xa2\x6e\xc2\xd7\x6c\xb1\xa3\x0f\x9e\xbf\xeb\x68\xe7\x56\xf2\xae\xf2\xe3\x2b\x38\x3a\x09\x81\xb5\x6b\x85\xd7\xbe\x2d\xed\x3f\x1a\xb7\xb2\x63\xe2\xf5\x62\x2c\x82\xd4\x6a\x00\x41\x50\xf1\x39\x83\x9f\x95\xe9\x36\x96\x98\x6e", 0 }, + /* Anchor: 48 Comodo_Secure_Certificate_Services.cer serial: #{a.serial.to_s} + C=GB,ST=Greater Manchester,L=Salford,O=Comodo CA Limited,CN=Secure Certificate Services + */ + { 1091, "\x30\x82\x04\x3f\x30\x82\x03\x27\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x7e\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1b\x30\x19\x06\x03\x55\x04\x08\x0c\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4d\x61\x6e\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c\x07\x53\x61\x6c\x66\x6f\x72\x64\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x0c\x11\x43\x6f\x6d\x6f\x64\x6f\x20\x43\x41\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x24\x30\x22\x06\x03\x55\x04\x03\x0c\x1b\x53\x65\x63\x75\x72\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x30\x1e\x17\x0d\x30\x34\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x38\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x7e\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1b\x30\x19\x06\x03\x55\x04\x08\x0c\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4d\x61\x6e\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c\x07\x53\x61\x6c\x66\x6f\x72\x64\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x0c\x11\x43\x6f\x6d\x6f\x64\x6f\x20\x43\x41\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x24\x30\x22\x06\x03\x55\x04\x03\x0c\x1b\x53\x65\x63\x75\x72\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xc0\x71\x33\x82\x8a\xd0\x70\xeb\x73\x87\x82\x40\xd5\x1d\xe4\xcb\xc9\x0e\x42\x90\xf9\xde\x34\xb9\xa1\xba\x11\xf4\x25\x85\xf3\xcc\x72\x6d\xf2\x7b\x97\x6b\xb3\x07\xf1\x77\x24\x91\x5f\x25\x8f\xf6\x74\x3d\xe4\x80\xc2\xf8\x3c\x0d\xf3\xbf\x40\xea\xf7\xc8\x52\xd1\x72\x6f\xef\xc8\xab\x41\xb8\x6e\x2e\x17\x2a\x95\x69\x0c\xcd\xd2\x1e\x94\x7b\x2d\x94\x1d\xaa\x75\xd7\xb3\x98\xcb\xac\xbc\x64\x53\x40\xbc\x8f\xac\xac\x36\xcb\x5c\xad\xbb\xdd\xe0\x94\x17\xec\xd1\x5c\xd0\xbf\xef\xa5\x95\xc9\x90\xc5\xb0\xac\xfb\x1b\x43\xdf\x7a\x08\x5d\xb7\xb8\xf2\x40\x1b\x2b\x27\x9e\x50\xce\x5e\x65\x82\x88\x8c\x5e\xd3\x4e\x0c\x7a\xea\x08\x91\xb6\x36\xaa\x2b\x42\xfb\xea\xc2\xa3\x39\xe5\xdb\x26\x38\xad\x8b\x0a\xee\x19\x63\xc7\x1c\x24\xdf\x03\x78\xda\xe6\xea\xc1\x47\x1a\x0b\x0b\x46\x09\xdd\x02\xfc\xde\xcb\x87\x5f\xd7\x30\x63\x68\xa1\xae\xdc\x32\xa1\xba\xbe\xfe\x44\xab\x68\xb6\xa5\x17\x15\xfd\xbd\xd5\xa7\xa7\x9a\xe4\x44\x33\xe9\x88\x8e\xfc\xed\x51\xeb\x93\x71\x4e\xad\x01\xe7\x44\x8e\xab\x2d\xcb\xa8\xfe\x01\x49\x48\xf0\xc0\xdd\xc7\x68\xd8\x92\xfe\x3d\x02\x03\x01\x00\x01\xa3\x81\xc7\x30\x81\xc4\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x3c\xd8\x93\x88\xc2\xc0\x82\x09\xcc\x01\x99\x06\x93\x20\xe9\x9e\x70\x09\x63\x4f\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x81\x81\x06\x03\x55\x1d\x1f\x04\x7a\x30\x78\x30\x3b\xa0\x39\xa0\x37\x86\x35\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x63\x6f\x6d\x6f\x64\x6f\x63\x61\x2e\x63\x6f\x6d\x2f\x53\x65\x63\x75\x72\x65\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x53\x65\x72\x76\x69\x63\x65\x73\x2e\x63\x72\x6c\x30\x39\xa0\x37\xa0\x35\x86\x33\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x63\x6f\x6d\x6f\x64\x6f\x2e\x6e\x65\x74\x2f\x53\x65\x63\x75\x72\x65\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x53\x65\x72\x76\x69\x63\x65\x73\x2e\x63\x72\x6c\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x87\x01\x6d\x23\x1d\x7e\x5b\x17\x7d\xc1\x61\x32\xcf\x8f\xe7\xf3\x8a\x94\x59\x66\xe0\x9e\x28\xa8\x5e\xd3\xb7\xf4\x34\xe6\xaa\x39\xb2\x97\x16\xc5\x82\x6f\x32\xa4\xe9\x8c\xe7\xaf\xfd\xef\xc2\xe8\xb9\x4b\xaa\xa3\xf4\xe6\xda\x8d\x65\x21\xfb\xba\x80\xeb\x26\x28\x85\x1a\xfe\x39\x8c\xde\x5b\x04\x04\xb4\x54\xf9\xa3\x67\x9e\x41\xfa\x09\x52\xcc\x05\x48\xa8\xc9\x3f\x21\x04\x1e\xce\x48\x6b\xfc\x85\xe8\xc2\x7b\xaf\x7f\xb7\xcc\xf8\x5f\x3a\xfd\x35\xc6\x0d\xef\x97\xdc\x4c\xab\x11\xe1\x6b\xcb\x31\xd1\x6c\xfb\x48\x80\xab\xdc\x9c\x37\xb8\x21\x14\x4b\x0d\x71\x3d\xec\x83\x33\x6e\xd1\x6e\x32\x16\xec\x98\xc7\x16\x8b\x59\xa6\x34\xab\x05\x57\x2d\x93\xf7\xaa\x13\xcb\xd2\x13\xe2\xb7\x2e\x3b\xcd\x6b\x50\x17\x09\x68\x3e\xb5\x26\x57\xee\xb6\xe0\xb6\xdd\xb9\x29\x80\x79\x7d\x8f\xa3\xf0\xa4\x28\xa4\x15\xc4\x85\xf4\x27\xd4\x6b\xbf\xe5\x5c\xe4\x65\x02\x76\x54\xb4\xe3\x37\x66\x24\xd3\x19\x61\xc8\x52\x10\xe5\x8b\x37\x9a\xb9\xa9\xf9\x1d\xbf\xea\x99\x92\x61\x96\xff\x01\xcd\xa1\x5f\x0d\xbc\x71\xbc\x0e\xac\x0b\x1d\x47\x45\x1d\xc1\xec\x7c\xec\xfd\x29", 0 }, + /* Anchor: 49 Comodo_Trusted_Certificate_Services.cer serial: #{a.serial.to_s} + C=GB,ST=Greater Manchester,L=Salford,O=Comodo CA Limited,CN=Trusted Certificate Services + */ + { 1095, "\x30\x82\x04\x43\x30\x82\x03\x2b\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x7f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1b\x30\x19\x06\x03\x55\x04\x08\x0c\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4d\x61\x6e\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c\x07\x53\x61\x6c\x66\x6f\x72\x64\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x0c\x11\x43\x6f\x6d\x6f\x64\x6f\x20\x43\x41\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x25\x30\x23\x06\x03\x55\x04\x03\x0c\x1c\x54\x72\x75\x73\x74\x65\x64\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x30\x1e\x17\x0d\x30\x34\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x38\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x7f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1b\x30\x19\x06\x03\x55\x04\x08\x0c\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4d\x61\x6e\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x0c\x07\x53\x61\x6c\x66\x6f\x72\x64\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x0c\x11\x43\x6f\x6d\x6f\x64\x6f\x20\x43\x41\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x25\x30\x23\x06\x03\x55\x04\x03\x0c\x1c\x54\x72\x75\x73\x74\x65\x64\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xdf\x71\x6f\x36\x58\x53\x5a\xf2\x36\x54\x57\x80\xc4\x74\x08\x20\xed\x18\x7f\x2a\x1d\xe6\x35\x9a\x1e\x25\xac\x9c\xe5\x96\x7e\x72\x52\xa0\x15\x42\xdb\x59\xdd\x64\x7a\x1a\xd0\xb8\x7b\xdd\x39\x15\xbc\x55\x48\xc4\xed\x3a\x00\xea\x31\x11\xba\xf2\x71\x74\x1a\x67\xb8\xcf\x33\xcc\xa8\x31\xaf\xa3\xe3\xd7\x7f\xbf\x33\x2d\x4c\x6a\x3c\xec\x8b\xc3\x92\xd2\x53\x77\x24\x74\x9c\x07\x6e\x70\xfc\xbd\x0b\x5b\x76\xba\x5f\xf2\xff\xd7\x37\x4b\x4a\x60\x78\xf7\xf0\xfa\xca\x70\xb4\xea\x59\xaa\xa3\xce\x48\x2f\xa9\xc3\xb2\x0b\x7e\x17\x72\x16\x0c\xa6\x07\x0c\x1b\x38\xcf\xc9\x62\xb7\x3f\xa0\x93\xa5\x87\x41\xf2\xb7\x70\x40\x77\xd8\xbe\x14\x7c\xe3\xa8\xc0\x7a\x8e\xe9\x63\x6a\xd1\x0f\x9a\xc6\xd2\xf4\x8b\x3a\x14\x04\x56\xd4\xed\xb8\xcc\x6e\xf5\xfb\xe2\x2c\x58\xbd\x7f\x4f\x6b\x2b\xf7\x60\x24\x58\x24\xce\x26\xef\x34\x91\x3a\xd5\xe3\x81\xd0\xb2\xf0\x04\x02\xd7\x5b\xb7\x3e\x92\xac\x6b\x12\x8a\xf9\xe4\x05\xb0\x3b\x91\x49\x5c\xb2\xeb\x53\xea\xf8\x9f\x47\x86\xee\xbf\x95\xc0\xc0\x06\x9f\xd2\x5b\x5e\x11\x1b\xf4\xc7\x04\x35\x29\xd2\x55\x5c\xe4\xed\xeb\x02\x03\x01\x00\x01\xa3\x81\xc9\x30\x81\xc6\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xc5\x7b\x58\xbd\xed\xda\x25\x69\xd2\xf7\x59\x16\xa8\xb3\x32\xc0\x7b\x27\x5b\xf4\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x81\x83\x06\x03\x55\x1d\x1f\x04\x7c\x30\x7a\x30\x3c\xa0\x3a\xa0\x38\x86\x36\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x63\x6f\x6d\x6f\x64\x6f\x63\x61\x2e\x63\x6f\x6d\x2f\x54\x72\x75\x73\x74\x65\x64\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x53\x65\x72\x76\x69\x63\x65\x73\x2e\x63\x72\x6c\x30\x3a\xa0\x38\xa0\x36\x86\x34\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x63\x6f\x6d\x6f\x64\x6f\x2e\x6e\x65\x74\x2f\x54\x72\x75\x73\x74\x65\x64\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x53\x65\x72\x76\x69\x63\x65\x73\x2e\x63\x72\x6c\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xc8\x93\x81\x3b\x89\xb4\xaf\xb8\x84\x12\x4c\x8d\xd2\xf0\xdb\x70\xba\x57\x86\x15\x34\x10\xb9\x2f\x7f\x1e\xb0\xa8\x89\x60\xa1\x8a\xc2\x77\x0c\x50\x4a\x9b\x00\x8b\xd8\x8b\xf4\x41\xe2\xd0\x83\x8a\x4a\x1c\x14\x06\xb0\xa3\x68\x05\x70\x31\x30\xa7\x53\x9b\x0e\xe9\x4a\xa0\x58\x69\x67\x0e\xae\x9d\xf6\xa5\x2c\x41\xbf\x3c\x06\x6b\xe4\x59\xcc\x6d\x10\xf1\x96\x6f\x1f\xdf\xf4\x04\x02\xa4\x9f\x45\x3e\xc8\xd8\xfa\x36\x46\x44\x50\x3f\x82\x97\x91\x1f\x28\xdb\x18\x11\x8c\x2a\xe4\x65\x83\x57\x12\x12\x8c\x17\x3f\x94\x36\xfe\x5d\xb0\xc0\x04\x77\x13\xb8\xf4\x15\xd5\x3f\x38\xcc\x94\x3a\x55\xd0\xac\x98\xf5\xba\x00\x5f\xe0\x86\x19\x81\x78\x2f\x28\xc0\x7e\xd3\xcc\x42\x0a\xf5\xae\x50\xa0\xd1\x3e\xc6\xa1\x71\xec\x3f\xa0\x20\x8c\x66\x3a\x89\xb4\x8e\xd4\xd8\xb1\x4d\x25\x47\xee\x2f\x88\xc8\xb5\xe1\x05\x45\xc0\xbe\x14\x71\xde\x7a\xfd\x8e\x7b\x7d\x4d\x08\x96\xa5\x12\x73\xf0\x2d\xca\x37\x27\x74\x12\x27\x4c\xcb\xb6\x97\xe9\xd9\xae\x08\x6d\x5a\x39\x40\xdd\x05\x47\x75\x6a\x5a\x21\xb3\xa3\x18\xcf\x4e\xf7\x2e\x57\xb7\x98\x70\x5e\xc8\xc4\x78\xb0\x62", 0 }, + /* Anchor: 50 COMODOCertificationAuthority.crt serial: #{a.serial.to_s} + C=GB,ST=Greater Manchester,L=Salford,O=COMODO CA Limited,CN=COMODO Certification Authority + */ + { 1057, "\x30\x82\x04\x1d\x30\x82\x03\x05\xa0\x03\x02\x01\x02\x02\x10\x4e\x81\x2d\x8a\x82\x65\xe0\x0b\x02\xee\x3e\x35\x02\x46\xe5\x3d\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\x81\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1b\x30\x19\x06\x03\x55\x04\x08\x13\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4d\x61\x6e\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x13\x07\x53\x61\x6c\x66\x6f\x72\x64\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x13\x11\x43\x4f\x4d\x4f\x44\x4f\x20\x43\x41\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x27\x30\x25\x06\x03\x55\x04\x03\x13\x1e\x43\x4f\x4d\x4f\x44\x4f\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x30\x36\x31\x32\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x39\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x81\x81\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1b\x30\x19\x06\x03\x55\x04\x08\x13\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4d\x61\x6e\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x13\x07\x53\x61\x6c\x66\x6f\x72\x64\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x13\x11\x43\x4f\x4d\x4f\x44\x4f\x20\x43\x41\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x27\x30\x25\x06\x03\x55\x04\x03\x13\x1e\x43\x4f\x4d\x4f\x44\x4f\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xd0\x40\x8b\x8b\x72\xe3\x91\x1b\xf7\x51\xc1\x1b\x54\x04\x98\xd3\xa9\xbf\xc1\xe6\x8a\x5d\x3b\x87\xfb\xbb\x88\xce\x0d\xe3\x2f\x3f\x06\x96\xf0\xa2\x29\x50\x99\xae\xdb\x3b\xa1\x57\xb0\x74\x51\x71\xcd\xed\x42\x91\x4d\x41\xfe\xa9\xc8\xd8\x6a\x86\x77\x44\xbb\x59\x66\x97\x50\x5e\xb4\xd4\x2c\x70\x44\xcf\xda\x37\x95\x42\x69\x3c\x30\xc4\x71\xb3\x52\xf0\x21\x4d\xa1\xd8\xba\x39\x7c\x1c\x9e\xa3\x24\x9d\xf2\x83\x16\x98\xaa\x16\x7c\x43\x9b\x15\x5b\xb7\xae\x34\x91\xfe\xd4\x62\x26\x18\x46\x9a\x3f\xeb\xc1\xf9\xf1\x90\x57\xeb\xac\x7a\x0d\x8b\xdb\x72\x30\x6a\x66\xd5\xe0\x46\xa3\x70\xdc\x68\xd9\xff\x04\x48\x89\x77\xde\xb5\xe9\xfb\x67\x6d\x41\xe9\xbc\x39\xbd\x32\xd9\x62\x02\xf1\xb1\xa8\x3d\x6e\x37\x9c\xe2\x2f\xe2\xd3\xa2\x26\x8b\xc6\xb8\x55\x43\x88\xe1\x23\x3e\xa5\xd2\x24\x39\x6a\x47\xab\x00\xd4\xa1\xb3\xa9\x25\xfe\x0d\x3f\xa7\x1d\xba\xd3\x51\xc1\x0b\xa4\xda\xac\x38\xef\x55\x50\x24\x05\x65\x46\x93\x34\x4f\x2d\x8d\xad\xc6\xd4\x21\x19\xd2\x8e\xca\x05\x61\x71\x07\x73\x47\xe5\x8a\x19\x12\xbd\x04\x4d\xce\x4e\x9c\xa5\x48\xac\xbb\x26\xf7\x02\x03\x01\x00\x01\xa3\x81\x8e\x30\x81\x8b\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x0b\x58\xe5\x8b\xc6\x4c\x15\x37\xa4\x40\xa9\x30\xa9\x21\xbe\x47\x36\x5a\x56\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x49\x06\x03\x55\x1d\x1f\x04\x42\x30\x40\x30\x3e\xa0\x3c\xa0\x3a\x86\x38\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x63\x6f\x6d\x6f\x64\x6f\x63\x61\x2e\x63\x6f\x6d\x2f\x43\x4f\x4d\x4f\x44\x4f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x2e\x63\x72\x6c\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x3e\x98\x9e\x9b\xf6\x1b\xe9\xd7\x39\xb7\x78\xae\x1d\x72\x18\x49\xd3\x87\xe4\x43\x82\xeb\x3f\xc9\xaa\xf5\xa8\xb5\xef\x55\x7c\x21\x52\x65\xf9\xd5\x0d\xe1\x6c\xf4\x3e\x8c\x93\x73\x91\x2e\x02\xc4\x4e\x07\x71\x6f\xc0\x8f\x38\x61\x08\xa8\x1e\x81\x0a\xc0\x2f\x20\x2f\x41\x8b\x91\xdc\x48\x45\xbc\xf1\xc6\xde\xba\x76\x6b\x33\xc8\x00\x2d\x31\x46\x4c\xed\xe7\x9d\xcf\x88\x94\xff\x33\xc0\x56\xe8\x24\x86\x26\xb8\xd8\x38\x38\xdf\x2a\x6b\xdd\x12\xcc\xc7\x3f\x47\x17\x4c\xa2\xc2\x06\x96\x09\xd6\xdb\xfe\x3f\x3c\x46\x41\xdf\x58\xe2\x56\x0f\x3c\x3b\xc1\x1c\x93\x35\xd9\x38\x52\xac\xee\xc8\xec\x2e\x30\x4e\x94\x35\xb4\x24\x1f\x4b\x78\x69\xda\xf2\x02\x38\xcc\x95\x52\x93\xf0\x70\x25\x59\x9c\x20\x67\xc4\xee\xf9\x8b\x57\x61\xf4\x92\x76\x7d\x3f\x84\x8d\x55\xb7\xe8\xe5\xac\xd5\xf1\xf5\x19\x56\xa6\x5a\xfb\x90\x1c\xaf\x93\xeb\xe5\x1c\xd4\x67\x97\x5d\x04\x0e\xbe\x0b\x83\xa6\x17\x83\xb9\x30\x12\xa0\xc5\x33\x15\x05\xb9\x0d\xfb\xc7\x05\x76\xe3\xd8\x4a\x8d\xfc\x34\x17\xa3\xc6\x21\x28\xbe\x30\x45\x31\x1e\xc7\x78\xbe\x58\x61\x38\xac\x3b\xe2\x01\x65", 0 }, + /* Anchor: 51 Deutsche_Telekom_Root_CA_2.der serial: #{a.serial.to_s} + C=DE,O=Deutsche Telekom AG,OU=T-TeleSec Trust Center,CN=Deutsche Telekom Root CA 2 + */ + { 931, "\x30\x82\x03\x9f\x30\x82\x02\x87\xa0\x03\x02\x01\x02\x02\x01\x26\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x71\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x44\x65\x75\x74\x73\x63\x68\x65\x20\x54\x65\x6c\x65\x6b\x6f\x6d\x20\x41\x47\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x54\x2d\x54\x65\x6c\x65\x53\x65\x63\x20\x54\x72\x75\x73\x74\x20\x43\x65\x6e\x74\x65\x72\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1a\x44\x65\x75\x74\x73\x63\x68\x65\x20\x54\x65\x6c\x65\x6b\x6f\x6d\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x32\x30\x1e\x17\x0d\x39\x39\x30\x37\x30\x39\x31\x32\x31\x31\x30\x30\x5a\x17\x0d\x31\x39\x30\x37\x30\x39\x32\x33\x35\x39\x30\x30\x5a\x30\x71\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x44\x65\x75\x74\x73\x63\x68\x65\x20\x54\x65\x6c\x65\x6b\x6f\x6d\x20\x41\x47\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x54\x2d\x54\x65\x6c\x65\x53\x65\x63\x20\x54\x72\x75\x73\x74\x20\x43\x65\x6e\x74\x65\x72\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1a\x44\x65\x75\x74\x73\x63\x68\x65\x20\x54\x65\x6c\x65\x6b\x6f\x6d\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x32\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xab\x0b\xa3\x35\xe0\x8b\x29\x14\xb1\x14\x85\xaf\x3c\x10\xe4\x39\x6f\x35\x5d\x4a\xae\xdd\xea\x61\x8d\x95\x49\xf4\x6f\x64\xa3\x1a\x60\x66\xa4\xa9\x40\x22\x84\xd9\xd4\xa5\xe5\x78\x93\x0e\x68\x01\xad\xb9\x4d\x5c\x3a\xce\xd3\xb8\xa8\x42\x40\xdf\xcf\xa3\xba\x82\x59\x6a\x92\x1b\xac\x1c\x9a\xda\x08\x2b\x25\x27\xf9\x69\x23\x47\xf1\xe0\xeb\x2c\x7a\x9b\xf5\x13\x02\xd0\x7e\x34\x7c\xc2\x9e\x3c\x00\x59\xab\xf5\xda\x0c\xf5\x32\x3c\x2b\xac\x50\xda\xd6\xc3\xde\x83\x94\xca\xa8\x0c\x99\x32\x0e\x08\x48\x56\x5b\x6a\xfb\xda\xe1\x58\x58\x01\x49\x5f\x72\x41\x3c\x15\x06\x01\x8e\x5d\xad\xaa\xb8\x93\xb4\xcd\x9e\xeb\xa7\xe8\x6a\x2d\x52\x34\xdb\x3a\xef\x5c\x75\x51\xda\xdb\xf3\x31\xf9\xee\x71\x98\x32\xc4\x54\x15\x44\x0c\xf9\x9b\x55\xed\xad\xdf\x18\x08\xa0\xa3\x86\x8a\x49\xee\x53\x05\x8f\x19\x4c\xd5\xde\x58\x79\x9b\xd2\x6a\x1c\x42\xab\xc5\xd5\xa7\xcf\x68\x0f\x96\xe4\xe1\x61\x98\x76\x61\xc8\x91\x7c\xd6\x3e\x00\xe2\x91\x50\x87\xe1\x9d\x0a\xe6\xad\x97\xd2\x1d\xc6\x3a\x7d\xcb\xbc\xda\x03\x34\xd5\x8e\x5b\x01\xf5\x6a\x07\xb7\x16\xb6\x6e\x4a\x7f\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x31\xc3\x79\x1b\xba\xf5\x53\xd7\x17\xe0\x89\x7a\x2d\x17\x6c\x0a\xb3\x2b\x9d\x33\x30\x0f\x06\x03\x55\x1d\x13\x04\x08\x30\x06\x01\x01\xff\x02\x01\x05\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x94\x64\x59\xad\x39\x64\xe7\x29\xeb\x13\xfe\x5a\xc3\x8b\x13\x57\xc8\x04\x24\xf0\x74\x77\xc0\x60\xe3\x67\xfb\xe9\x89\xa6\x83\xbf\x96\x82\x7c\x6e\xd4\xc3\x3d\xef\x9e\x80\x6e\xbb\x29\xb4\x98\x7a\xb1\x3b\x54\xeb\x39\x17\x47\x7e\x1a\x8e\x0b\xfc\x1f\x31\x59\x31\x04\xb2\xce\x17\xf3\x2c\xc7\x62\x36\x55\xe2\x22\xd8\x89\x55\xb4\x98\x48\xaa\x64\xfa\xd6\x1c\x36\xd8\x44\x78\x5a\x5a\x23\x3a\x57\x97\xf5\x7a\x30\x4f\xae\x9f\x6a\x4c\x4b\x2b\x8e\xa0\x03\xe3\x3e\xe0\xa9\xd4\xd2\x7b\xd2\xb3\xa8\xe2\x72\x3c\xad\x9e\xff\x80\x59\xe4\x9b\x45\xb4\xf6\x3b\xb0\xcd\x39\x19\x98\x32\xe5\xea\x21\x61\x90\xe4\x31\x21\x8e\x34\xb1\xf7\x2f\x35\x4a\x85\x10\xda\xe7\x8a\x37\x21\xbe\x59\x63\xe0\xf2\x85\x88\x31\x53\xd4\x54\x14\x85\x70\x79\xf4\x2e\x06\x77\x27\x75\x2f\x1f\xb8\x8a\xf9\xfe\xc5\xba\xd8\x36\xe4\x83\xec\xe7\x65\xb7\xbf\x63\x5a\xf3\x46\xaf\x81\x94\x37\xd4\x41\x8c\xd6\x23\xd6\x1e\xcf\xf5\x68\x1b\x44\x63\xa2\x5a\xba\xa7\x35\x59\xa1\xe5\x70\x05\x9b\x0e\x23\x57\x99\x94\x0a\x6d\xba\x39\x63\x28\x86\x92\xf3\x18\x84\xd8\xfb\xd1\xcf\x05\x56\x64\x57", 0 }, + /* Anchor: 52 DigiCertAssuredIDRootCA.crt serial: #{a.serial.to_s} + C=US,O=DigiCert Inc,OU=www.digicert.com,CN=DigiCert Assured ID Root CA + */ + { 955, "\x30\x82\x03\xb7\x30\x82\x02\x9f\xa0\x03\x02\x01\x02\x02\x10\x0c\xe7\xe0\xe5\x17\xd8\x46\xfe\x8f\xe5\x60\xfc\x1b\xf0\x30\x39\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x65\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x13\x0c\x44\x69\x67\x69\x43\x65\x72\x74\x20\x49\x6e\x63\x31\x19\x30\x17\x06\x03\x55\x04\x0b\x13\x10\x77\x77\x77\x2e\x64\x69\x67\x69\x63\x65\x72\x74\x2e\x63\x6f\x6d\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1b\x44\x69\x67\x69\x43\x65\x72\x74\x20\x41\x73\x73\x75\x72\x65\x64\x20\x49\x44\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x1e\x17\x0d\x30\x36\x31\x31\x31\x30\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x33\x31\x31\x31\x31\x30\x30\x30\x30\x30\x30\x30\x5a\x30\x65\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x13\x0c\x44\x69\x67\x69\x43\x65\x72\x74\x20\x49\x6e\x63\x31\x19\x30\x17\x06\x03\x55\x04\x0b\x13\x10\x77\x77\x77\x2e\x64\x69\x67\x69\x63\x65\x72\x74\x2e\x63\x6f\x6d\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1b\x44\x69\x67\x69\x43\x65\x72\x74\x20\x41\x73\x73\x75\x72\x65\x64\x20\x49\x44\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xad\x0e\x15\xce\xe4\x43\x80\x5c\xb1\x87\xf3\xb7\x60\xf9\x71\x12\xa5\xae\xdc\x26\x94\x88\xaa\xf4\xce\xf5\x20\x39\x28\x58\x60\x0c\xf8\x80\xda\xa9\x15\x95\x32\x61\x3c\xb5\xb1\x28\x84\x8a\x8a\xdc\x9f\x0a\x0c\x83\x17\x7a\x8f\x90\xac\x8a\xe7\x79\x53\x5c\x31\x84\x2a\xf6\x0f\x98\x32\x36\x76\xcc\xde\xdd\x3c\xa8\xa2\xef\x6a\xfb\x21\xf2\x52\x61\xdf\x9f\x20\xd7\x1f\xe2\xb1\xd9\xfe\x18\x64\xd2\x12\x5b\x5f\xf9\x58\x18\x35\xbc\x47\xcd\xa1\x36\xf9\x6b\x7f\xd4\xb0\x38\x3e\xc1\x1b\xc3\x8c\x33\xd9\xd8\x2f\x18\xfe\x28\x0f\xb3\xa7\x83\xd6\xc3\x6e\x44\xc0\x61\x35\x96\x16\xfe\x59\x9c\x8b\x76\x6d\xd7\xf1\xa2\x4b\x0d\x2b\xff\x0b\x72\xda\x9e\x60\xd0\x8e\x90\x35\xc6\x78\x55\x87\x20\xa1\xcf\xe5\x6d\x0a\xc8\x49\x7c\x31\x98\x33\x6c\x22\xe9\x87\xd0\x32\x5a\xa2\xba\x13\x82\x11\xed\x39\x17\x9d\x99\x3a\x72\xa1\xe6\xfa\xa4\xd9\xd5\x17\x31\x75\xae\x85\x7d\x22\xae\x3f\x01\x46\x86\xf6\x28\x79\xc8\xb1\xda\xe4\x57\x17\xc4\x7e\x1c\x0e\xb0\xb4\x92\xa6\x56\xb3\xbd\xb2\x97\xed\xaa\xa7\xf0\xb7\xc5\xa8\x3f\x95\x16\xd0\xff\xa1\x96\xeb\x08\x5f\x18\x77\x4f\x02\x03\x01\x00\x01\xa3\x63\x30\x61\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x86\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x45\xeb\xa2\xaf\xf4\x92\xcb\x82\x31\x2d\x51\x8b\xa7\xa7\x21\x9d\xf3\x6d\xc8\x0f\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x45\xeb\xa2\xaf\xf4\x92\xcb\x82\x31\x2d\x51\x8b\xa7\xa7\x21\x9d\xf3\x6d\xc8\x0f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xa2\x0e\xbc\xdf\xe2\xed\xf0\xe3\x72\x73\x7a\x64\x94\xbf\xf7\x72\x66\xd8\x32\xe4\x42\x75\x62\xae\x87\xeb\xf2\xd5\xd9\xde\x56\xb3\x9f\xcc\xce\x14\x28\xb9\x0d\x97\x60\x5c\x12\x4c\x58\xe4\xd3\x3d\x83\x49\x45\x58\x97\x35\x69\x1a\xa8\x47\xea\x56\xc6\x79\xab\x12\xd8\x67\x81\x84\xdf\x7f\x09\x3c\x94\xe6\xb8\x26\x2c\x20\xbd\x3d\xb3\x28\x89\xf7\x5f\xff\x22\xe2\x97\x84\x1f\xe9\x65\xef\x87\xe0\xdf\xc1\x67\x49\xb3\x5d\xeb\xb2\x09\x2a\xeb\x26\xed\x78\xbe\x7d\x3f\x2b\xf3\xb7\x26\x35\x6d\x5f\x89\x01\xb6\x49\x5b\x9f\x01\x05\x9b\xab\x3d\x25\xc1\xcc\xb6\x7f\xc2\xf1\x6f\x86\xc6\xfa\x64\x68\xeb\x81\x2d\x94\xeb\x42\xb7\xfa\x8c\x1e\xdd\x62\xf1\xbe\x50\x67\xb7\x6c\xbd\xf3\xf1\x1f\x6b\x0c\x36\x07\x16\x7f\x37\x7c\xa9\x5b\x6d\x7a\xf1\x12\x46\x60\x83\xd7\x27\x04\xbe\x4b\xce\x97\xbe\xc3\x67\x2a\x68\x11\xdf\x80\xe7\x0c\x33\x66\xbf\x13\x0d\x14\x6e\xf3\x7f\x1f\x63\x10\x1e\xfa\x8d\x1b\x25\x6d\x6c\x8f\xa5\xb7\x61\x01\xb1\xd2\xa3\x26\xa1\x10\x71\x9d\xad\xe2\xc3\xf9\xc3\x99\x51\xb7\x2b\x07\x08\xce\x2e\xe6\x50\xb2\xa7\xfa\x0a\x45\x2f\xa2\xf0\xf2", 0 }, + /* Anchor: 53 DigiCertGlobalRootCA.crt serial: #{a.serial.to_s} + C=US,O=DigiCert Inc,OU=www.digicert.com,CN=DigiCert Global Root CA + */ + { 947, "\x30\x82\x03\xaf\x30\x82\x02\x97\xa0\x03\x02\x01\x02\x02\x10\x08\x3b\xe0\x56\x90\x42\x46\xb1\xa1\x75\x6a\xc9\x59\x91\xc7\x4a\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x61\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x13\x0c\x44\x69\x67\x69\x43\x65\x72\x74\x20\x49\x6e\x63\x31\x19\x30\x17\x06\x03\x55\x04\x0b\x13\x10\x77\x77\x77\x2e\x64\x69\x67\x69\x63\x65\x72\x74\x2e\x63\x6f\x6d\x31\x20\x30\x1e\x06\x03\x55\x04\x03\x13\x17\x44\x69\x67\x69\x43\x65\x72\x74\x20\x47\x6c\x6f\x62\x61\x6c\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x1e\x17\x0d\x30\x36\x31\x31\x31\x30\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x33\x31\x31\x31\x31\x30\x30\x30\x30\x30\x30\x30\x5a\x30\x61\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x13\x0c\x44\x69\x67\x69\x43\x65\x72\x74\x20\x49\x6e\x63\x31\x19\x30\x17\x06\x03\x55\x04\x0b\x13\x10\x77\x77\x77\x2e\x64\x69\x67\x69\x63\x65\x72\x74\x2e\x63\x6f\x6d\x31\x20\x30\x1e\x06\x03\x55\x04\x03\x13\x17\x44\x69\x67\x69\x43\x65\x72\x74\x20\x47\x6c\x6f\x62\x61\x6c\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xe2\x3b\xe1\x11\x72\xde\xa8\xa4\xd3\xa3\x57\xaa\x50\xa2\x8f\x0b\x77\x90\xc9\xa2\xa5\xee\x12\xce\x96\x5b\x01\x09\x20\xcc\x01\x93\xa7\x4e\x30\xb7\x53\xf7\x43\xc4\x69\x00\x57\x9d\xe2\x8d\x22\xdd\x87\x06\x40\x00\x81\x09\xce\xce\x1b\x83\xbf\xdf\xcd\x3b\x71\x46\xe2\xd6\x66\xc7\x05\xb3\x76\x27\x16\x8f\x7b\x9e\x1e\x95\x7d\xee\xb7\x48\xa3\x08\xda\xd6\xaf\x7a\x0c\x39\x06\x65\x7f\x4a\x5d\x1f\xbc\x17\xf8\xab\xbe\xee\x28\xd7\x74\x7f\x7a\x78\x99\x59\x85\x68\x6e\x5c\x23\x32\x4b\xbf\x4e\xc0\xe8\x5a\x6d\xe3\x70\xbf\x77\x10\xbf\xfc\x01\xf6\x85\xd9\xa8\x44\x10\x58\x32\xa9\x75\x18\xd5\xd1\xa2\xbe\x47\xe2\x27\x6a\xf4\x9a\x33\xf8\x49\x08\x60\x8b\xd4\x5f\xb4\x3a\x84\xbf\xa1\xaa\x4a\x4c\x7d\x3e\xcf\x4f\x5f\x6c\x76\x5e\xa0\x4b\x37\x91\x9e\xdc\x22\xe6\x6d\xce\x14\x1a\x8e\x6a\xcb\xfe\xcd\xb3\x14\x64\x17\xc7\x5b\x29\x9e\x32\xbf\xf2\xee\xfa\xd3\x0b\x42\xd4\xab\xb7\x41\x32\xda\x0c\xd4\xef\xf8\x81\xd5\xbb\x8d\x58\x3f\xb5\x1b\xe8\x49\x28\xa2\x70\xda\x31\x04\xdd\xf7\xb2\x16\xf2\x4c\x0a\x4e\x07\xa8\xed\x4a\x3d\x5e\xb5\x7f\xa3\x90\xc3\xaf\x27\x02\x03\x01\x00\x01\xa3\x63\x30\x61\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x86\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x03\xde\x50\x35\x56\xd1\x4c\xbb\x66\xf0\xa3\xe2\x1b\x1b\xc3\x97\xb2\x3d\xd1\x55\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x03\xde\x50\x35\x56\xd1\x4c\xbb\x66\xf0\xa3\xe2\x1b\x1b\xc3\x97\xb2\x3d\xd1\x55\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xcb\x9c\x37\xaa\x48\x13\x12\x0a\xfa\xdd\x44\x9c\x4f\x52\xb0\xf4\xdf\xae\x04\xf5\x79\x79\x08\xa3\x24\x18\xfc\x4b\x2b\x84\xc0\x2d\xb9\xd5\xc7\xfe\xf4\xc1\x1f\x58\xcb\xb8\x6d\x9c\x7a\x74\xe7\x98\x29\xab\x11\xb5\xe3\x70\xa0\xa1\xcd\x4c\x88\x99\x93\x8c\x91\x70\xe2\xab\x0f\x1c\xbe\x93\xa9\xff\x63\xd5\xe4\x07\x60\xd3\xa3\xbf\x9d\x5b\x09\xf1\xd5\x8e\xe3\x53\xf4\x8e\x63\xfa\x3f\xa7\xdb\xb4\x66\xdf\x62\x66\xd6\xd1\x6e\x41\x8d\xf2\x2d\xb5\xea\x77\x4a\x9f\x9d\x58\xe2\x2b\x59\xc0\x40\x23\xed\x2d\x28\x82\x45\x3e\x79\x54\x92\x26\x98\xe0\x80\x48\xa8\x37\xef\xf0\xd6\x79\x60\x16\xde\xac\xe8\x0e\xcd\x6e\xac\x44\x17\x38\x2f\x49\xda\xe1\x45\x3e\x2a\xb9\x36\x53\xcf\x3a\x50\x06\xf7\x2e\xe8\xc4\x57\x49\x6c\x61\x21\x18\xd5\x04\xad\x78\x3c\x2c\x3a\x80\x6b\xa7\xeb\xaf\x15\x14\xe9\xd8\x89\xc1\xb9\x38\x6c\xe2\x91\x6c\x8a\xff\x64\xb9\x77\x25\x57\x30\xc0\x1b\x24\xa3\xe1\xdc\xe9\xdf\x47\x7c\xb5\xb4\x24\x08\x05\x30\xec\x2d\xbd\x0b\xbf\x45\xbf\x50\xb9\xa9\xf3\xeb\x98\x01\x12\xad\xc8\x88\xc6\x98\x34\x5f\x8d\x0a\x3c\xc6\xe9\xd5\x95\x95\x6d\xde", 0 }, + /* Anchor: 54 DigiCertHighAssuranceEVRootCA.crt serial: #{a.serial.to_s} + C=US,O=DigiCert Inc,OU=www.digicert.com,CN=DigiCert High Assurance EV Root CA + */ + { 969, "\x30\x82\x03\xc5\x30\x82\x02\xad\xa0\x03\x02\x01\x02\x02\x10\x02\xac\x5c\x26\x6a\x0b\x40\x9b\x8f\x0b\x79\xf2\xae\x46\x25\x77\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x6c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x13\x0c\x44\x69\x67\x69\x43\x65\x72\x74\x20\x49\x6e\x63\x31\x19\x30\x17\x06\x03\x55\x04\x0b\x13\x10\x77\x77\x77\x2e\x64\x69\x67\x69\x63\x65\x72\x74\x2e\x63\x6f\x6d\x31\x2b\x30\x29\x06\x03\x55\x04\x03\x13\x22\x44\x69\x67\x69\x43\x65\x72\x74\x20\x48\x69\x67\x68\x20\x41\x73\x73\x75\x72\x61\x6e\x63\x65\x20\x45\x56\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x1e\x17\x0d\x30\x36\x31\x31\x31\x30\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x33\x31\x31\x31\x31\x30\x30\x30\x30\x30\x30\x30\x5a\x30\x6c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x13\x0c\x44\x69\x67\x69\x43\x65\x72\x74\x20\x49\x6e\x63\x31\x19\x30\x17\x06\x03\x55\x04\x0b\x13\x10\x77\x77\x77\x2e\x64\x69\x67\x69\x63\x65\x72\x74\x2e\x63\x6f\x6d\x31\x2b\x30\x29\x06\x03\x55\x04\x03\x13\x22\x44\x69\x67\x69\x43\x65\x72\x74\x20\x48\x69\x67\x68\x20\x41\x73\x73\x75\x72\x61\x6e\x63\x65\x20\x45\x56\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xc6\xcc\xe5\x73\xe6\xfb\xd4\xbb\xe5\x2d\x2d\x32\xa6\xdf\xe5\x81\x3f\xc9\xcd\x25\x49\xb6\x71\x2a\xc3\xd5\x94\x34\x67\xa2\x0a\x1c\xb0\x5f\x69\xa6\x40\xb1\xc4\xb7\xb2\x8f\xd0\x98\xa4\xa9\x41\x59\x3a\xd3\xdc\x94\xd6\x3c\xdb\x74\x38\xa4\x4a\xcc\x4d\x25\x82\xf7\x4a\xa5\x53\x12\x38\xee\xf3\x49\x6d\x71\x91\x7e\x63\xb6\xab\xa6\x5f\xc3\xa4\x84\xf8\x4f\x62\x51\xbe\xf8\xc5\xec\xdb\x38\x92\xe3\x06\xe5\x08\x91\x0c\xc4\x28\x41\x55\xfb\xcb\x5a\x89\x15\x7e\x71\xe8\x35\xbf\x4d\x72\x09\x3d\xbe\x3a\x38\x50\x5b\x77\x31\x1b\x8d\xb3\xc7\x24\x45\x9a\xa7\xac\x6d\x00\x14\x5a\x04\xb7\xba\x13\xeb\x51\x0a\x98\x41\x41\x22\x4e\x65\x61\x87\x81\x41\x50\xa6\x79\x5c\x89\xde\x19\x4a\x57\xd5\x2e\xe6\x5d\x1c\x53\x2c\x7e\x98\xcd\x1a\x06\x16\xa4\x68\x73\xd0\x34\x04\x13\x5c\xa1\x71\xd3\x5a\x7c\x55\xdb\x5e\x64\xe1\x37\x87\x30\x56\x04\xe5\x11\xb4\x29\x80\x12\xf1\x79\x39\x88\xa2\x02\x11\x7c\x27\x66\xb7\x88\xb7\x78\xf2\xca\x0a\xa8\x38\xab\x0a\x64\xc2\xbf\x66\x5d\x95\x84\xc1\xa1\x25\x1e\x87\x5d\x1a\x50\x0b\x20\x12\xcc\x41\xbb\x6e\x0b\x51\x38\xb8\x4b\xcb\x02\x03\x01\x00\x01\xa3\x63\x30\x61\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x86\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xb1\x3e\xc3\x69\x03\xf8\xbf\x47\x01\xd4\x98\x26\x1a\x08\x02\xef\x63\x64\x2b\xc3\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\xb1\x3e\xc3\x69\x03\xf8\xbf\x47\x01\xd4\x98\x26\x1a\x08\x02\xef\x63\x64\x2b\xc3\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x1c\x1a\x06\x97\xdc\xd7\x9c\x9f\x3c\x88\x66\x06\x08\x57\x21\xdb\x21\x47\xf8\x2a\x67\xaa\xbf\x18\x32\x76\x40\x10\x57\xc1\x8a\xf3\x7a\xd9\x11\x65\x8e\x35\xfa\x9e\xfc\x45\xb5\x9e\xd9\x4c\x31\x4b\xb8\x91\xe8\x43\x2c\x8e\xb3\x78\xce\xdb\xe3\x53\x79\x71\xd6\xe5\x21\x94\x01\xda\x55\x87\x9a\x24\x64\xf6\x8a\x66\xcc\xde\x9c\x37\xcd\xa8\x34\xb1\x69\x9b\x23\xc8\x9e\x78\x22\x2b\x70\x43\xe3\x55\x47\x31\x61\x19\xef\x58\xc5\x85\x2f\x4e\x30\xf6\xa0\x31\x16\x23\xc8\xe7\xe2\x65\x16\x33\xcb\xbf\x1a\x1b\xa0\x3d\xf8\xca\x5e\x8b\x31\x8b\x60\x08\x89\x2d\x0c\x06\x5c\x52\xb7\xc4\xf9\x0a\x98\xd1\x15\x5f\x9f\x12\xbe\x7c\x36\x63\x38\xbd\x44\xa4\x7f\xe4\x26\x2b\x0a\xc4\x97\x69\x0d\xe9\x8c\xe2\xc0\x10\x57\xb8\xc8\x76\x12\x91\x55\xf2\x48\x69\xd8\xbc\x2a\x02\x5b\x0f\x44\xd4\x20\x31\xdb\xf4\xba\x70\x26\x5d\x90\x60\x9e\xbc\x4b\x17\x09\x2f\xb4\xcb\x1e\x43\x68\xc9\x07\x27\xc1\xd2\x5c\xf7\xea\x21\xb9\x68\x12\x9c\x3c\x9c\xbf\x9e\xfc\x80\x5c\x9b\x63\xcd\xec\x47\xaa\x25\x27\x67\xa0\x37\xf3\x00\x82\x7d\x54\xd7\xa9\xf8\xe9\x2e\x13\xa3\x77\xe8\x1f\x4a", 0 }, + /* Anchor: 55 disig-root-1.der serial: #{a.serial.to_s} + C=SK,L=Bratislava,O=Disig a.s.,CN=CA Disig + */ + { 1043, "\x30\x82\x04\x0f\x30\x82\x02\xf7\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x4a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x4b\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0a\x42\x72\x61\x74\x69\x73\x6c\x61\x76\x61\x31\x13\x30\x11\x06\x03\x55\x04\x0a\x13\x0a\x44\x69\x73\x69\x67\x20\x61\x2e\x73\x2e\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x13\x08\x43\x41\x20\x44\x69\x73\x69\x67\x30\x1e\x17\x0d\x30\x36\x30\x33\x32\x32\x30\x31\x33\x39\x33\x34\x5a\x17\x0d\x31\x36\x30\x33\x32\x32\x30\x31\x33\x39\x33\x34\x5a\x30\x4a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x4b\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0a\x42\x72\x61\x74\x69\x73\x6c\x61\x76\x61\x31\x13\x30\x11\x06\x03\x55\x04\x0a\x13\x0a\x44\x69\x73\x69\x67\x20\x61\x2e\x73\x2e\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x13\x08\x43\x41\x20\x44\x69\x73\x69\x67\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\x92\xf6\x31\xc1\x7d\x88\xfd\x99\x01\xa9\xd8\x7b\xf2\x71\x75\xf1\x31\xc6\xf3\x75\x66\xfa\x51\x28\x46\x84\x97\x78\x34\xbc\x6c\xfc\xbc\x45\x59\x88\x26\x18\x4a\xc4\x37\x1f\xa1\x4a\x44\xbd\xe3\x71\x04\xf5\x44\x17\xe2\x3f\xfc\x48\x58\x6f\x5c\x9e\x7a\x09\xba\x51\x37\x22\x23\x66\x43\x21\xb0\x3c\x64\xa2\xf8\x6a\x15\x0e\x3f\xeb\x51\xe1\x54\xa9\xdd\x06\x99\xd7\x9a\x3c\x54\x8b\x39\x03\x3f\x0f\xc5\xce\xc6\xeb\x83\x72\x02\xa8\x1f\x71\xf3\x2d\xf8\x75\x08\xdb\x62\x4c\xe8\xfa\xce\xf9\xe7\x6a\x1f\xb6\x6b\x35\x82\xba\xe2\x8f\x16\x92\x7d\x05\x0c\x6c\x46\x03\x5d\xc0\xed\x69\xbf\x3a\xc1\x8a\xa0\xe8\x8e\xd9\xb9\x45\x28\x87\x08\xec\xb4\xca\x15\xbe\x82\xdd\xb5\x44\x8b\x2d\xad\x86\x0c\x68\x62\x6d\x85\x56\xf2\xac\x14\x63\x3a\xc6\xd1\x99\xac\x34\x78\x56\x4b\xcf\xb6\xad\x3f\x8c\x8a\xd7\x04\xe5\xe3\x78\x4c\xf5\x86\xaa\xf5\x8f\xfa\x3d\x6c\x71\xa3\x2d\xca\x67\xeb\x68\x7b\x6e\x33\xa9\x0c\x82\x28\xa8\x4c\x6a\x21\x40\x15\x20\x0c\x26\x5b\x83\xc2\xa9\x16\x15\xc0\x24\x82\x5d\x2b\x16\xad\xca\x63\xf6\x74\x00\xb0\xdf\x43\xc4\x10\x60\x56\x67\x63\x45\x02\x03\x01\x00\x01\xa3\x81\xff\x30\x81\xfc\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x8d\xb2\x49\x68\x9d\x72\x08\x25\xb9\xc0\x27\xf5\x50\x93\x56\x48\x46\x71\xf9\x8f\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x36\x06\x03\x55\x1d\x11\x04\x2f\x30\x2d\x81\x13\x63\x61\x6f\x70\x65\x72\x61\x74\x6f\x72\x40\x64\x69\x73\x69\x67\x2e\x73\x6b\x86\x16\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x64\x69\x73\x69\x67\x2e\x73\x6b\x2f\x63\x61\x30\x66\x06\x03\x55\x1d\x1f\x04\x5f\x30\x5d\x30\x2d\xa0\x2b\xa0\x29\x86\x27\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x64\x69\x73\x69\x67\x2e\x73\x6b\x2f\x63\x61\x2f\x63\x72\x6c\x2f\x63\x61\x5f\x64\x69\x73\x69\x67\x2e\x63\x72\x6c\x30\x2c\xa0\x2a\xa0\x28\x86\x26\x68\x74\x74\x70\x3a\x2f\x2f\x63\x61\x2e\x64\x69\x73\x69\x67\x2e\x73\x6b\x2f\x63\x61\x2f\x63\x72\x6c\x2f\x63\x61\x5f\x64\x69\x73\x69\x67\x2e\x63\x72\x6c\x30\x1a\x06\x03\x55\x1d\x20\x04\x13\x30\x11\x30\x0f\x06\x0d\x2b\x81\x1e\x91\x93\xe6\x0a\x00\x00\x00\x01\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x5d\x34\x74\x61\x4c\xaf\x3b\xd8\xff\x9f\x6d\x58\x36\x1c\x3d\x0b\x81\x0d\x12\x2b\x46\x10\x80\xfd\xe7\x3c\x27\xd0\x7a\xc8\xa9\xb6\x7e\x74\x30\x33\xa3\x3a\x8a\x7b\x74\xc0\x79\x79\x42\x93\x6d\xff\xb1\x29\x14\x82\xab\x21\x8c\x2f\x17\xf9\x3f\x26\x2f\xf5\x59\xc6\xef\x80\x06\xb7\x9a\x49\x29\xec\xce\x7e\x71\x3c\x6a\x10\x41\xc0\xf6\xd3\x9a\xb2\x7c\x5a\x91\x9c\xc0\xac\x5b\xc8\x4d\x5e\xf7\xe1\x53\xff\x43\x77\xfc\x9e\x4b\x67\x6c\xd7\xf3\x83\xd1\xa0\xe0\x7f\x25\xdf\xb8\x98\x0b\x9a\x32\x38\x6c\x30\xa0\xf3\xff\x08\x15\x33\xf7\x50\x4a\x7b\x3e\xa3\x3e\x20\xa9\xdc\x2f\x56\x80\x0a\xed\x41\x50\xb0\xc9\xf4\xec\xb2\xe3\x26\x44\x00\x0e\x6f\x9e\x06\xbc\x22\x96\x53\x70\x65\xc4\x50\x0a\x46\x6b\xa4\x2f\x27\x81\x12\x27\x13\x5f\x10\xa1\x76\xce\x8a\x7b\x37\xea\xc3\x39\x61\x03\x95\x98\x3a\xe7\x6c\x88\x25\x08\xfc\x79\x68\x0d\x87\x7d\x62\xf8\xb4\x5f\xfb\xc5\xd8\x4c\xbd\x58\xbc\x3f\x43\x5b\xd4\x1e\x01\x4d\x3c\x63\xbe\x23\xef\x8c\xcd\x5a\x50\xb8\x68\x54\xf9\x0a\x99\x33\x11\x00\xe1\x9e\xc2\x46\x77\x82\xf5\x59\x06\x8c\x21\x4c\x87\x09\xcd\xe5\xa8", 0 }, + /* Anchor: 56 DoDCLASS3RootCA.cer serial: #{a.serial.to_s} + C=US,O=U.S. Government,OU=DoD,OU=PKI,CN=DoD CLASS 3 Root CA + */ + { 619, "\x30\x82\x02\x67\x30\x82\x01\xd0\xa0\x03\x02\x01\x02\x02\x01\x04\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x61\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x18\x30\x16\x06\x03\x55\x04\x0a\x13\x0f\x55\x2e\x53\x2e\x20\x47\x6f\x76\x65\x72\x6e\x6d\x65\x6e\x74\x31\x0c\x30\x0a\x06\x03\x55\x04\x0b\x13\x03\x44\x6f\x44\x31\x0c\x30\x0a\x06\x03\x55\x04\x0b\x13\x03\x50\x4b\x49\x31\x1c\x30\x1a\x06\x03\x55\x04\x03\x13\x13\x44\x6f\x44\x20\x43\x4c\x41\x53\x53\x20\x33\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x1e\x17\x0d\x30\x30\x30\x35\x31\x39\x31\x33\x31\x33\x30\x30\x5a\x17\x0d\x32\x30\x30\x35\x31\x34\x31\x33\x31\x33\x30\x30\x5a\x30\x61\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x18\x30\x16\x06\x03\x55\x04\x0a\x13\x0f\x55\x2e\x53\x2e\x20\x47\x6f\x76\x65\x72\x6e\x6d\x65\x6e\x74\x31\x0c\x30\x0a\x06\x03\x55\x04\x0b\x13\x03\x44\x6f\x44\x31\x0c\x30\x0a\x06\x03\x55\x04\x0b\x13\x03\x50\x4b\x49\x31\x1c\x30\x1a\x06\x03\x55\x04\x03\x13\x13\x44\x6f\x44\x20\x43\x4c\x41\x53\x53\x20\x33\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xb5\x30\xfe\x64\xbe\xea\xcc\x6d\xed\x81\x2c\xf7\x7f\xe9\x19\xba\x0e\x69\x6a\x28\xe1\xa9\xa9\xcb\x95\x58\x1f\xf1\xe6\x9a\x69\x53\xe0\x88\x3f\x91\xc5\x51\xb9\x63\x97\xa8\xe6\x21\x8c\x13\x5e\x36\x3c\xa8\x57\xfa\xf8\x70\x2c\x4c\x6a\xcb\xbf\x30\xa7\x4c\x16\xe4\x32\x5c\xf8\x12\xb0\x51\xf8\x16\x57\x8d\x2f\xb4\x4d\xfa\x2e\xa8\x94\xe8\x2a\x61\xd4\x57\x0d\x47\xce\x6e\x2c\x2f\x7e\x98\x67\xcc\x00\x08\xab\xb6\x96\x16\x35\xc2\x85\x91\xe5\x5b\xa0\x0a\xc7\x66\x52\x62\xf3\x61\x75\x95\x17\xae\xbc\x2a\x56\x29\xa5\xe0\x2b\x53\x02\x03\x01\x00\x01\xa3\x2f\x30\x2d\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x6c\x9c\xa5\xf0\x5c\x8f\x6d\x41\x8d\xc4\x17\x3b\x90\x57\xc2\x0f\xa3\xcd\x6d\xfe\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\xaf\x71\x44\xf9\x97\x23\xcc\x68\x69\x8c\x43\x07\x41\xba\x88\x20\xb3\x22\x00\x41\xc8\x98\xa0\x55\x1c\xcd\x3f\x6e\xb1\x93\x5c\xad\xfa\x18\x9a\xbb\x1c\x73\x6f\xfd\x24\x42\x8f\x87\x9f\x51\xcf\xbe\x86\x9f\xe9\xd7\x8a\x48\x4f\x08\xd9\x69\x94\xac\x3f\xe6\x0f\x2d\x97\x0f\x28\x93\x76\x4f\x62\xdf\xff\xa0\xcd\x61\xf8\xa6\x86\x0c\x31\x34\x20\xdc\x7f\x2f\xa8\xfb\x39\xbe\x95\xee\x38\x59\x02\x62\xc1\xde\x6c\x15\x4f\xe0\xdf\x9d\xbb\xe4\x79\x73\x24\xfd\x63\x64\x95\xf7\x4a\xa8\x99\x1f\x48\x65\x95\xc7\x7b\xbf\x78\x32\xe7\x7a", 0 }, + /* Anchor: 57 DoDRootCA2.der serial: #{a.serial.to_s} + C=US,O=U.S. Government,OU=DoD,OU=PKI,CN=DoD Root CA 2 + */ + { 884, "\x30\x82\x03\x70\x30\x82\x02\x58\xa0\x03\x02\x01\x02\x02\x01\x05\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x5b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x18\x30\x16\x06\x03\x55\x04\x0a\x13\x0f\x55\x2e\x53\x2e\x20\x47\x6f\x76\x65\x72\x6e\x6d\x65\x6e\x74\x31\x0c\x30\x0a\x06\x03\x55\x04\x0b\x13\x03\x44\x6f\x44\x31\x0c\x30\x0a\x06\x03\x55\x04\x0b\x13\x03\x50\x4b\x49\x31\x16\x30\x14\x06\x03\x55\x04\x03\x13\x0d\x44\x6f\x44\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x32\x30\x1e\x17\x0d\x30\x34\x31\x32\x31\x33\x31\x35\x30\x30\x31\x30\x5a\x17\x0d\x32\x39\x31\x32\x30\x35\x31\x35\x30\x30\x31\x30\x5a\x30\x5b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x18\x30\x16\x06\x03\x55\x04\x0a\x13\x0f\x55\x2e\x53\x2e\x20\x47\x6f\x76\x65\x72\x6e\x6d\x65\x6e\x74\x31\x0c\x30\x0a\x06\x03\x55\x04\x0b\x13\x03\x44\x6f\x44\x31\x0c\x30\x0a\x06\x03\x55\x04\x0b\x13\x03\x50\x4b\x49\x31\x16\x30\x14\x06\x03\x55\x04\x03\x13\x0d\x44\x6f\x44\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x32\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xc0\x2c\xc1\xf6\x8d\x3b\xac\xff\x3f\x3c\xd6\x71\xbe\xb8\x74\x22\x07\xec\x70\x41\x15\xfc\xab\x40\xe3\x07\xaa\xc1\xc3\xd8\x9f\xfe\xda\x4c\x3a\xbf\x3f\xc8\xd8\x28\x7b\x4b\x36\x01\xc0\xac\x45\x25\xc3\xd2\x0e\x0a\x8f\x85\x18\x64\x10\x3d\x1a\x13\x70\x2a\x6f\x8e\xd7\xdc\x8d\x93\xb3\x41\x0f\x38\x21\xcd\xad\xab\xc2\x3d\x2a\x05\xd3\x57\x11\x37\x0d\xcd\x8c\x51\xf9\x93\xe3\xcc\x46\x49\x21\x8e\x14\xb4\xcd\xcb\x14\x3e\x38\xcd\x72\x31\xee\xab\x12\xf2\x65\xea\x34\x2e\x56\x5d\xff\xee\x63\x75\xcb\x6d\xba\x91\x34\xfc\x9e\xf3\xf4\x2d\x1c\xbe\x50\xc4\x42\xdf\x59\x88\xff\x6a\xb3\xfa\xa8\x6c\x3d\xcb\x56\x71\x71\x05\x96\xbb\x9f\x80\xe5\x80\x45\x59\x67\x41\xb0\xeb\xc3\xad\x60\xa4\x80\x75\x06\x17\x9c\x0e\xf4\x43\xe0\x99\x0e\x1b\xfb\x7f\xf5\xb3\xcc\xb2\x81\x82\xb1\xfd\x32\xc1\xb8\xbe\x41\xa4\x64\xb5\x60\x3a\x5a\x51\x30\x8c\xce\xde\x41\x2c\x19\x47\x5c\x49\x10\x64\xb9\x74\xa9\x87\x41\xaf\x7d\x6e\xba\xc1\xb8\xa1\xbf\x65\x31\x3a\x04\x67\xf9\xb5\xbb\x8e\x92\x8a\x00\x63\xb8\xb1\xe6\x8c\x38\x5f\x83\xff\x50\xd5\x3b\xa2\x5d\x6b\xb2\x10\xcc\x63\x02\x03\x01\x00\x01\xa3\x3f\x30\x3d\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x49\x74\xbb\x0c\x5e\xba\x7a\xfe\x02\x54\xef\x7b\xa0\xc6\x95\xc6\x09\x80\x70\x96\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x86\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x98\x91\x8d\x3f\x89\xc8\xbb\xf5\xc0\x69\x73\x29\x3b\x35\xac\xba\xb3\x08\x76\x3d\x70\x09\x92\xe9\x84\x44\x21\x01\x7d\x14\x76\x1b\xee\x51\x6c\x1d\x8d\x15\x37\x2d\x7b\x31\x69\xf4\x9a\x44\xb8\xaf\x46\xcc\x34\xfa\x23\xcb\x03\x27\x19\xd2\x83\x21\x75\x2b\xe7\xe0\x1b\x99\x26\xdc\x84\x40\x95\xe8\xa8\xd2\xcc\xf6\x58\x5c\x66\xef\x3f\x4a\x97\x10\x82\x1d\xba\x0a\xa2\xdd\x5b\x06\x2b\x9d\xa7\x64\x4e\xeb\x2e\x01\x35\xa4\xb4\x3f\x13\xad\x55\xe4\xd5\x73\xa8\x69\x9b\x11\xf1\x98\xf2\x31\x1e\x6f\x40\xd4\xf8\x78\x9f\x8e\x91\xa0\x6f\x70\x04\x90\x66\xaa\x06\x2b\xce\xe1\x7a\x92\xb5\x7d\xe1\xe0\xd1\x96\xe7\xa1\x3a\x2d\xcc\xb1\x9d\x1f\x05\x44\xed\x87\x99\xd3\x4d\x1a\x70\x39\xc1\x04\x0c\xe5\x7e\xd9\xf1\xaf\xd7\x20\x0e\xf1\x22\x7a\x25\xa4\x73\x99\xcc\x3f\xa4\x07\x27\x96\xa8\xa2\x95\xed\x82\xb9\x16\xd3\x9e\x0b\x87\xc2\xc1\xf2\x88\xf5\x62\xdf\x68\xdf\xc7\xbc\x69\x51\xed\xb1\x5c\xdc\x54\x54\x29\x0f\x09\x39\x9a\xac\x03\xc1\xdb\x0c\x4d\xae\x6f\x0a\x7a\x16\x49\xf1\xbf\x91\xd2\x38\x94\xd3\xf6\x95\x2c\xb7\x6c\xc9\x42\xb6\x8d\xca\x90\x8d\x85\xd9", 0 }, + /* Anchor: 58 DST Root CA X4.cer serial: #{a.serial.to_s} + O=Digital Signature Trust Co.,CN=DST Root CA X4 + */ + { 831, "\x30\x82\x03\x3b\x30\x82\x02\x23\xa0\x03\x02\x01\x02\x02\x11\x00\xd0\x1e\x46\x50\x00\x00\x29\x8c\x00\x00\x00\x02\x00\x00\x00\x02\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x3f\x31\x24\x30\x22\x06\x03\x55\x04\x0a\x13\x1b\x44\x69\x67\x69\x74\x61\x6c\x20\x53\x69\x67\x6e\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6f\x2e\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0e\x44\x53\x54\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x58\x34\x30\x1e\x17\x0d\x30\x30\x30\x39\x31\x33\x30\x36\x32\x32\x35\x30\x5a\x17\x0d\x32\x30\x30\x39\x31\x33\x30\x36\x32\x32\x35\x30\x5a\x30\x3f\x31\x24\x30\x22\x06\x03\x55\x04\x0a\x13\x1b\x44\x69\x67\x69\x74\x61\x6c\x20\x53\x69\x67\x6e\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6f\x2e\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0e\x44\x53\x54\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x58\x34\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xad\x85\x7d\xce\x14\x46\x18\xf2\x04\x9e\x21\x8b\xab\xd0\xee\x32\xa4\xe4\xfa\xf0\x79\xc3\xae\x32\xdf\x22\xeb\x4b\xe4\xf6\x47\x47\x04\x06\x8f\x30\x8f\x6f\xd3\xc5\xa3\xf8\xa1\x6e\x82\x7c\x46\xf7\xc6\x84\x10\x2a\xa5\x00\xa8\xe3\xbc\xf0\x60\x48\x69\x5a\x6d\x63\x07\xe2\xff\x38\x4f\xdd\x04\x18\xb2\x9f\xdf\x24\xad\xf5\x36\x36\x20\x4a\x4a\x89\xb6\x27\x9f\x11\x05\xe0\x30\x1c\x61\x32\x70\xef\xa5\x7b\x0c\xa3\x56\xf6\xc3\x0c\xb5\x32\xe0\x28\x5e\x63\x4e\x7d\xbd\xf3\x23\x3c\x07\xed\x09\x15\xe3\xa9\x26\x48\xa2\x54\x1b\xf4\x57\x4f\x70\x0a\x1a\xf7\x49\x85\xc0\x1e\xeb\x2a\x78\x84\x27\xbb\xe9\xa5\xda\xd4\x49\xc4\x92\xd3\xe7\x81\xac\x74\x94\x3c\xb7\x6f\xc3\x29\xf8\x44\x6a\x7e\x95\x2c\x1b\x59\x87\x1b\x83\x91\x29\x4a\x91\x34\x19\x12\x5d\x72\x18\x9c\xd1\x80\xe3\xbc\x8a\x02\x60\x7a\x5e\xed\x19\x23\xf7\x73\xd8\x45\x34\x32\x53\x86\xe1\x0b\xcf\x1c\x93\xcb\x4c\xa9\xbb\xd1\x62\xa3\x11\xa9\x1f\xaf\xa1\xb6\xe4\xae\x3e\x4b\x2c\x23\x90\x08\x75\x79\x58\x4a\x31\x5a\x1f\xb4\x13\x64\xa9\x20\x57\xbb\x46\x45\x7e\xf8\xc9\xa9\x20\x07\x34\x87\x5b\x59\x02\x03\x01\x00\x01\xa3\x32\x30\x30\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xf0\x83\xea\x73\xc8\x3f\x5b\x9b\x5b\x37\x5f\xf5\x4c\x8f\x5a\xf7\xf4\x86\x48\xbd\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x84\x1b\xce\x70\x97\x97\x84\x59\xde\xda\x74\x7e\x97\x5b\xf8\xa4\x18\xde\x6c\x6a\x5b\xe9\xab\xf1\x62\xc7\xac\x95\x4f\x31\x3a\x0a\xb8\x65\x3f\x92\xc1\x76\x47\xfa\x93\x1d\x5b\x48\xf2\xf5\xf0\xce\x39\x83\x4a\xf0\xdb\x30\x3f\x31\x63\xa1\x27\x7f\x92\xe9\x4f\x81\x13\x4c\xcf\x18\x2b\xae\xf1\x84\x1a\x66\x26\xd1\xee\xc9\xe6\xdc\x78\x87\x51\xa6\x4d\x32\xee\x5c\xf0\x3d\x31\xd1\xb7\x0c\xc4\x38\xd8\x01\x55\x5c\x1c\x2a\x0d\x88\xbe\x77\x43\x83\xcb\x5b\x6e\xe7\x6d\x8e\xb0\xc0\x6d\x1f\x7c\x52\xa6\x81\x5d\xdb\x97\x1a\xd8\x59\xfb\x94\x0e\x01\xa9\xc8\xfc\x07\xc2\x47\xd5\x16\xfc\xfd\xaa\x36\x95\x99\xfd\x76\x54\x97\xdf\x2f\xa5\xbc\xa2\x60\x4f\xb6\x0b\x5e\x6f\xa5\x1a\x4f\xf9\x35\xa0\x9e\xd8\x23\x49\x5d\x19\xff\xa7\x82\x95\x5b\x46\x10\xfe\x2c\x2d\xdc\x52\xd4\xfa\x18\xef\xc1\x10\xf6\x6e\xf1\x84\xd5\xfe\x16\xe2\x0c\x7e\x6f\xde\x48\x55\xa8\xc2\x1e\x29\x3e\xa8\xf0\x8b\x97\x18\x6e\xc5\xe9\xae\xaf\x2b\x03\xf5\x17\x51\x70\x4d\x77\xf8\x50\x2f\xe2\xbe\x19\x9e\xee\xf7\x54\x1f\xb0\x7f\x56\xfe\x00\x11\xb4\xfc\x74\xd7\xc4\x78\x5c\x6b\x90\x36\xe1", 0 }, + /* Anchor: 59 EBG_KOKSM.cer serial: #{a.serial.to_s} + CN=EBG Elektronik Sertifika Hizmet Sağlayıcısı,O=EBG Bilişim Teknolojileri ve Hizmetleri A.Ş.,C=TR + */ + { 1515, "\x30\x82\x05\xe7\x30\x82\x03\xcf\xa0\x03\x02\x01\x02\x02\x08\x4c\xaf\x73\x42\x1c\x8e\x74\x02\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\x80\x31\x38\x30\x36\x06\x03\x55\x04\x03\x0c\x2f\x45\x42\x47\x20\x45\x6c\x65\x6b\x74\x72\x6f\x6e\x69\x6b\x20\x53\x65\x72\x74\x69\x66\x69\x6b\x61\x20\x48\x69\x7a\x6d\x65\x74\x20\x53\x61\xc4\x9f\x6c\x61\x79\xc4\xb1\x63\xc4\xb1\x73\xc4\xb1\x31\x37\x30\x35\x06\x03\x55\x04\x0a\x0c\x2e\x45\x42\x47\x20\x42\x69\x6c\x69\xc5\x9f\x69\x6d\x20\x54\x65\x6b\x6e\x6f\x6c\x6f\x6a\x69\x6c\x65\x72\x69\x20\x76\x65\x20\x48\x69\x7a\x6d\x65\x74\x6c\x65\x72\x69\x20\x41\x2e\xc5\x9e\x2e\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x30\x1e\x17\x0d\x30\x36\x30\x38\x31\x37\x30\x30\x32\x31\x30\x39\x5a\x17\x0d\x31\x36\x30\x38\x31\x34\x30\x30\x33\x31\x30\x39\x5a\x30\x81\x80\x31\x38\x30\x36\x06\x03\x55\x04\x03\x0c\x2f\x45\x42\x47\x20\x45\x6c\x65\x6b\x74\x72\x6f\x6e\x69\x6b\x20\x53\x65\x72\x74\x69\x66\x69\x6b\x61\x20\x48\x69\x7a\x6d\x65\x74\x20\x53\x61\xc4\x9f\x6c\x61\x79\xc4\xb1\x63\xc4\xb1\x73\xc4\xb1\x31\x37\x30\x35\x06\x03\x55\x04\x0a\x0c\x2e\x45\x42\x47\x20\x42\x69\x6c\x69\xc5\x9f\x69\x6d\x20\x54\x65\x6b\x6e\x6f\x6c\x6f\x6a\x69\x6c\x65\x72\x69\x20\x76\x65\x20\x48\x69\x7a\x6d\x65\x74\x6c\x65\x72\x69\x20\x41\x2e\xc5\x9e\x2e\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\xee\xa0\x84\x61\xd0\x3a\x6a\x66\x10\x32\xd8\x31\x38\x7f\xa7\xa7\xe5\xfd\xa1\xe1\xfb\x97\x77\xb8\x71\x96\xe8\x13\x96\x46\x83\x4f\xb6\xf2\x5f\x72\x56\x6e\x13\x60\xa5\x01\x91\xe2\x5b\xc5\xcd\x57\x1f\x77\x63\x51\xff\x2f\x3d\xdb\xb9\x3f\xaa\xa9\x35\xe7\x79\xd0\xf5\xd0\x24\xb6\x21\xea\xeb\x23\x94\xfe\x29\xbf\xfb\x89\x91\x0c\x64\x9a\x05\x4a\x2b\xcc\x0c\xee\xf1\x3d\x9b\x82\x69\xa4\x4c\xf8\x9a\x6f\xe7\x22\xda\x10\xba\x5f\x92\xfc\x18\x27\x0a\xa8\xaa\x44\xfa\x2e\x2c\xb4\xfb\x46\x9a\x08\x03\x83\x72\xab\x88\xe4\x6a\x72\xc9\xe5\x65\x1f\x6e\x2a\x0f\x9d\xb3\xe8\x3b\xe4\x0c\x6e\x7a\xda\x57\xfd\xd7\xeb\x79\x8b\x5e\x20\x06\xd3\x76\x0b\x6c\x02\x95\xa3\x96\xe4\xcb\x76\x51\xd1\x28\x9d\xa1\x1a\xfc\x44\xa2\x4d\xcc\x7a\x76\xa8\x0d\x3d\xbf\x17\x4f\x22\x88\x50\xfd\xae\xb6\xec\x90\x50\x4a\x5b\x9f\x95\x41\xaa\xca\x0f\xb2\x4a\xfe\x80\x99\x4e\xa3\x46\x15\xab\xf8\x73\x42\x6a\xc2\x66\x76\xb1\x0a\x26\x15\xdd\x93\x92\xec\xdb\xa9\x5f\x54\x22\x52\x91\x70\x5d\x13\xea\x48\xec\x6e\x03\x6c\xd9\xdd\x6c\xfc\xeb\x0d\x03\xff\xa6\x83\x12\x9b\xf1\xa9\x93\x0f\xc5\x26\x4c\x31\xb2\x63\x99\x61\x72\xe7\x2a\x64\x99\xd2\xb8\xe9\x75\xe2\x7c\xa9\xa9\x9a\x1a\xaa\xc3\x56\xdb\x10\x9a\x3c\x83\x52\xb6\x7b\x96\xb7\xac\x87\x77\xa8\xb9\xf2\x67\x0b\x94\x43\xb3\xaf\x3e\x73\xfa\x42\x36\xb1\x25\xc5\x0a\x31\x26\x37\x56\x67\xba\xa3\x0b\x7d\xd6\xf7\x89\xcd\x67\xa1\xb7\x3a\x1e\x66\x4f\xf6\xa0\x55\x14\x25\x4c\x2c\x33\x0d\xa6\x41\x8c\xbd\x04\x31\x6a\x10\x72\x0a\x9d\x0e\x2e\x76\xbd\x5e\xf3\x51\x89\x8b\xa8\x3f\x55\x73\xbf\xdb\x3a\xc6\x24\x05\x96\x92\x48\xaa\x4b\x8d\x2a\x03\xe5\x57\x91\x10\xf4\x6a\x28\x15\x6e\x47\x77\x84\x5c\x51\x74\x9f\x19\xe9\xe6\x1e\x63\x16\x39\xe3\x11\x15\xe3\x58\x1a\x44\xbd\xcb\xc4\x6c\x66\xd7\x84\x06\xdf\x30\xf4\x37\xa2\x43\x22\x79\xd2\x10\x6c\xdf\xbb\xe6\x13\x11\xfc\x9d\x84\x0a\x13\x7b\xf0\x3b\xd0\xfc\xa3\x0a\xd7\x89\xea\x96\x7e\x8d\x48\x85\x1e\x64\x5f\xdb\x54\xa2\xac\xd5\x7a\x02\x79\x6b\xd2\x8a\xf0\x67\xda\x65\x72\x0d\x14\x70\xe4\xe9\x8e\x78\x8f\x32\x74\x7c\x57\xf2\xd6\xd6\xf4\x36\x89\x1b\xf8\x29\x6c\x8b\xb9\xf6\x97\xd1\xa4\x2e\xaa\xbe\x0b\x19\xc2\x45\xe9\x70\x5d\x02\x03\x00\x9d\xd9\xa3\x63\x30\x61\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xe7\xce\xc6\x4f\xfc\x16\x67\x96\xfa\x4a\xa3\x07\xc1\x04\xa7\xcb\x6a\xde\xda\x47\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\xe7\xce\xc6\x4f\xfc\x16\x67\x96\xfa\x4a\xa3\x07\xc1\x04\xa7\xcb\x6a\xde\xda\x47\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x9b\x98\x9a\x5d\xbe\xf3\x28\x23\x76\xc6\x6c\xf7\x7f\xe6\x40\x9e\xc0\x36\xdc\x95\x0d\x1d\xad\x15\xc5\x36\xd8\xd5\x39\xef\xf2\x1e\x22\x5e\xb3\x82\xb4\x5d\xbb\x4c\x1a\xca\x92\x0d\xdf\x47\x24\x1e\xb3\x24\xda\x91\x88\xe9\x83\x70\xdd\x93\xd7\xe9\xba\xb3\xdf\x16\x5a\x3e\xde\xe0\xc8\xfb\xd3\xfd\x6c\x29\xf8\x15\x46\xa0\x68\x26\xcc\x93\x52\xae\x82\x01\x93\x90\xca\x77\xca\x4d\x49\xef\xe2\x5a\xd9\x2a\xbd\x30\xce\x4c\xb2\x81\xb6\x30\xce\x59\x4f\xda\x59\x1d\x6a\x7a\xa4\x45\xb0\x82\x26\x81\x86\x76\xf5\xf5\x10\x00\xb8\xee\xb3\x09\xe8\x4f\x87\x02\x07\xae\x24\x5c\xf0\x5f\xac\x0a\x30\xcc\x8a\x40\xa0\x73\x04\xc1\xfb\x89\x24\xf6\x9a\x1c\x5c\xb7\x3c\x0a\x67\x36\x05\x08\x31\xb3\xaf\xd8\x01\x68\x2a\xe0\x78\x8f\x74\xde\xb8\x51\xa4\x8c\x6c\x20\x3d\xa2\xfb\xb3\xd4\x09\xfd\x7b\xc2\x80\xaa\x93\x6c\x29\x98\x21\xa8\xbb\x16\xf3\xa9\x12\x5f\x74\xb5\x87\x98\xf2\x95\x26\xdf\x34\xef\x8a\x53\x91\x88\x5d\x1a\x94\xa3\x3f\x7c\x22\xf8\xd7\x88\xba\xa6\x8c\x96\xa8\x3d\x52\x34\x62\x9f\x00\x1e\x54\x55\x42\x67\xc6\x4d\x46\x8f\xbb\x14\x45\x3d\x0a\x96\x16\x8e\x10\xa1\x97\x99\xd5\xd3\x30\x85\xcc\xde\xb4\x72\xb7\xbc\x8a\x3c\x18\x29\x68\xfd\xdc\x71\x07\xee\x24\x39\x6a\xfa\xed\xa5\xac\x38\x2f\xf9\x1e\x10\x0e\x06\x71\x1a\x10\x4c\xfe\x75\x7e\xff\x1e\x57\x39\x42\xca\xd7\xe1\x15\xa1\x56\x55\x59\x1b\xd1\xa3\xaf\x11\xd8\x4e\xc3\xa5\x2b\xef\x90\xbf\xc0\xec\x82\x13\x5b\x8d\xd6\x72\x2c\x93\x4e\x8f\x6a\x29\xdf\x85\x3c\xd3\x0d\xe0\xa2\x18\x12\xcc\x55\x2f\x47\xb7\xa7\x9b\x02\xfe\x41\xf6\x88\x4c\x6d\xda\xa9\x01\x47\x83\x64\x27\x62\x10\x82\xd6\x12\x7b\x5e\x03\x1f\x34\xa9\xc9\x91\xfe\xaf\x5d\x6d\x86\x27\xb7\x23\xaa\x75\x18\xca\x20\xe7\xb0\x0f\xd7\x89\x0e\xa6\x67\x22\x63\xf4\x83\x41\x2b\x06\x4b\xbb\x58\xd5\xd1\xd7\xb7\xb9\x10\x63\xd8\x89\x4a\xb4\xaa\xdd\x16\x63\xf5\x6e\xbe\x60\xa1\xf8\xed\xe8\xd6\x90\x4f\x1a\xc6\xc5\xa0\x29\xd3\xa7\x21\xa8\xf5\x5a\x3c\xf7\xc7\x49\xa2\x21\x9a\x4a\x95\x52\x20\x96\x72\x9a\x66\xcb\xf7\xd2\x86\x43\x7c\x22\xbe\x96\xf9\xbd\x01\xa8\x47\xdd\xe5\x3b\x40\xf9\x75\x2b\x9b\x2b\x46\x64\x86\x8d\x1e\xf4\x8f\xfb\x07\x77\xd0\xea\x49\xa2\x1c\x8d\x52\x14\xa6\x0a\x93", 0 }, + /* Anchor: 60 ECARootCA.der serial: #{a.serial.to_s} + C=US,O=U.S. Government,OU=ECA,CN=ECA Root CA + */ + { 668, "\x30\x82\x02\x98\x30\x82\x02\x01\xa0\x03\x02\x01\x02\x02\x01\x0e\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x4b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x18\x30\x16\x06\x03\x55\x04\x0a\x13\x0f\x55\x2e\x53\x2e\x20\x47\x6f\x76\x65\x72\x6e\x6d\x65\x6e\x74\x31\x0c\x30\x0a\x06\x03\x55\x04\x0b\x13\x03\x45\x43\x41\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0b\x45\x43\x41\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x1e\x17\x0d\x30\x34\x30\x36\x31\x34\x31\x30\x32\x30\x30\x39\x5a\x17\x0d\x34\x30\x30\x36\x31\x34\x31\x30\x32\x30\x30\x39\x5a\x30\x4b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x18\x30\x16\x06\x03\x55\x04\x0a\x13\x0f\x55\x2e\x53\x2e\x20\x47\x6f\x76\x65\x72\x6e\x6d\x65\x6e\x74\x31\x0c\x30\x0a\x06\x03\x55\x04\x0b\x13\x03\x45\x43\x41\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0b\x45\x43\x41\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xae\x4a\xf6\x79\x72\x12\xea\x80\x0a\x22\x90\xe4\x3a\x57\x10\x65\xd3\x06\x76\x77\x28\xca\x00\x84\x21\x4f\xa4\xb6\xa6\x37\xa1\xfe\x52\x55\x55\xd4\xef\xf8\xad\xee\x42\x75\x11\x4c\xd1\xe2\x28\xb6\xbe\xd8\x50\xb5\xbc\x30\xf5\xa0\x27\xa5\x0c\x5c\x12\x65\xd9\x93\xc7\x84\xca\x21\x84\x3f\x2f\x9c\x09\x03\x25\x94\x16\x3e\x79\xf3\xad\x2a\x08\xdb\x40\xd0\xd9\xde\x50\x7d\xd7\xda\xb3\x50\x9c\x01\x97\x60\x4c\xc6\xc9\x54\xd5\x7b\x09\x43\x0f\x52\x2b\x5d\x25\x3d\xb4\x26\xe1\xab\x1a\xf0\x4f\x1e\xe7\x34\xd4\x92\x76\x41\x5a\x71\x02\x03\x01\x00\x01\xa3\x81\x8b\x30\x81\x88\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\xf6\xb8\x04\x27\x0e\x56\x16\xd9\xb9\x63\xd9\xfd\xa1\x54\x65\x41\xa0\x08\x48\x2f\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xf6\xb8\x04\x27\x0e\x56\x16\xd9\xb9\x63\xd9\xfd\xa1\x54\x65\x41\xa0\x08\x48\x2f\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x86\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x25\x06\x03\x55\x1d\x20\x04\x1e\x30\x1c\x30\x0c\x06\x0a\x60\x86\x48\x01\x65\x03\x02\x01\x0c\x01\x30\x0c\x06\x0a\x60\x86\x48\x01\x65\x03\x02\x01\x0c\x02\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x1e\x1d\x04\x41\x8d\x9c\x67\x6d\x3d\x68\x16\xf9\xab\x4c\x16\xd4\x44\x74\x75\xce\x0e\x1b\x3b\x0b\xca\xa8\xc7\x7d\xa4\x38\x4c\x46\x8c\x99\x4c\x0b\x00\x94\x6d\x6b\xf7\x38\x29\x55\x8b\x8b\x06\xce\x0e\xcb\xe0\x26\x4f\x82\x69\x69\x92\x2f\x4d\xe0\x45\x6f\xdc\x89\x56\xff\xa8\x35\x7b\xaa\x1f\x4f\xc9\xdd\x5c\x3a\x56\xa7\x65\x30\x27\x3e\x88\x36\x8b\xcd\xb2\x2f\x78\xb6\x7c\xaf\x43\x08\x2f\x38\xba\x8c\x44\x41\xb8\x2a\x2b\x68\xf1\xf5\xb2\x23\x15\x3c\x25\x02\xa2\x13\x93\xd7\xc6\x02\x6e\x66\x75\x3f\x38\x20\x4c\x2a\xd4\x6c", 0 }, + /* Anchor: 61 EchoworxRootCA2.cer serial: #{a.serial.to_s} + C=CA,ST=Ontario,L=Toronto,O=Echoworx Corporation,OU=Certification Services,CN=Echoworx Root CA2 + */ + { 1259, "\x30\x82\x04\xe7\x30\x82\x03\xcf\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\x8d\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x08\x13\x07\x4f\x6e\x74\x61\x72\x69\x6f\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x13\x07\x54\x6f\x72\x6f\x6e\x74\x6f\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x13\x14\x45\x63\x68\x6f\x77\x6f\x72\x78\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x31\x1a\x30\x18\x06\x03\x55\x04\x03\x13\x11\x45\x63\x68\x6f\x77\x6f\x72\x78\x20\x52\x6f\x6f\x74\x20\x43\x41\x32\x30\x1e\x17\x0d\x30\x35\x31\x30\x30\x36\x31\x30\x34\x39\x31\x33\x5a\x17\x0d\x33\x30\x31\x30\x30\x37\x31\x30\x34\x39\x31\x33\x5a\x30\x81\x8d\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x08\x13\x07\x4f\x6e\x74\x61\x72\x69\x6f\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x13\x07\x54\x6f\x72\x6f\x6e\x74\x6f\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x13\x14\x45\x63\x68\x6f\x77\x6f\x72\x78\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x31\x1a\x30\x18\x06\x03\x55\x04\x03\x13\x11\x45\x63\x68\x6f\x77\x6f\x72\x78\x20\x52\x6f\x6f\x74\x20\x43\x41\x32\x30\x82\x01\x20\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0d\x00\x30\x82\x01\x08\x02\x82\x01\x01\x00\xba\xd5\x3f\xe4\x19\x15\xd7\x95\x01\x7f\xeb\x3e\x25\x0a\xee\x29\x0c\x6b\xef\xbb\x37\xae\x3a\x7f\x46\x93\xad\x9a\x11\xc8\x2c\x88\x8e\xe6\x0b\x04\x58\xff\x0c\x32\xb7\xeb\x54\x48\xa2\x76\x32\x3a\x42\x1e\x9a\x9e\xcd\x0a\x01\x67\x36\x0f\x0d\x3f\x8f\x8a\x8a\x01\x0c\xce\x4b\x20\x19\x82\x37\x1d\xca\x93\x53\x05\x9e\xe6\xba\xfd\xb5\xd8\x30\x36\x3e\xee\x35\xad\x7a\xb0\x32\xb9\x41\xad\x58\xbf\x29\x38\x21\x7d\xd2\xe5\x35\x1b\xba\x26\xb0\xb9\xcb\xc1\xda\xae\xb9\xd1\x15\x22\x85\xd5\x38\x5b\xcf\x3f\x76\xd6\x42\xc3\x46\x80\xa2\xf8\x55\x6c\xe5\xe5\x6e\x2b\x92\xef\x21\xf9\x21\x34\x0a\x80\x6f\x2a\xd3\x80\xed\xd3\xf7\x37\xd9\x82\x4f\x2e\xa6\x61\x24\x00\xd3\xc3\x2f\x5f\xbc\xcb\xb7\x46\x3c\x1f\xdd\xea\x59\x34\x23\x99\xaf\xf0\xf1\x12\x29\x7d\x36\x4e\x5b\xf0\x81\x14\x88\x89\x31\xd1\x93\xcf\xbe\x88\xe3\xcb\x05\x69\x46\xa7\xb6\x5f\xa9\x31\x17\x90\xf5\x19\x86\x0a\xd0\x42\xfc\x5c\xaf\x00\x94\xa3\xa9\xa4\xf1\x3a\xa0\xc4\x20\xcf\xe4\x58\x0f\xa0\x71\x62\x3c\xb7\x9f\xe6\xcc\xcf\x64\xb0\x49\x0d\x6a\x7b\x18\xbc\x84\xd4\xf9\xa4\x40\x8e\x96\x8b\x02\x01\x03\xa3\x82\x01\x50\x30\x82\x01\x4c\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x3b\xe1\x81\x1b\xa0\xab\x3f\x3b\x21\x82\xd5\xe2\x12\xae\xae\x50\xab\x14\xa5\x13\x30\x81\xba\x06\x03\x55\x1d\x23\x04\x81\xb2\x30\x81\xaf\x80\x14\x3b\xe1\x81\x1b\xa0\xab\x3f\x3b\x21\x82\xd5\xe2\x12\xae\xae\x50\xab\x14\xa5\x13\xa1\x81\x93\xa4\x81\x90\x30\x81\x8d\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x08\x13\x07\x4f\x6e\x74\x61\x72\x69\x6f\x31\x10\x30\x0e\x06\x03\x55\x04\x07\x13\x07\x54\x6f\x72\x6f\x6e\x74\x6f\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x13\x14\x45\x63\x68\x6f\x77\x6f\x72\x78\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x31\x1a\x30\x18\x06\x03\x55\x04\x03\x13\x11\x45\x63\x68\x6f\x77\x6f\x72\x78\x20\x52\x6f\x6f\x74\x20\x43\x41\x32\x82\x01\x00\x30\x50\x06\x03\x55\x1d\x20\x04\x49\x30\x47\x30\x45\x06\x0b\x2b\x06\x01\x04\x01\xf9\x11\x0a\x01\x03\x01\x30\x36\x30\x34\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x65\x63\x68\x6f\x77\x6f\x72\x78\x2e\x63\x6f\x6d\x2f\x63\x61\x2f\x72\x6f\x6f\x74\x32\x2f\x63\x70\x73\x2e\x70\x64\x66\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x6f\xa7\xac\xf8\xbf\xd1\x1a\x5f\x13\x3a\xe3\xd3\x60\xba\x24\x63\xd4\x6a\xbe\x27\x6e\x32\x21\x71\x8e\x8d\xec\x35\x8d\x7a\xa0\x68\x52\xe9\x41\x48\x81\xff\x3d\x81\x8d\x1d\x8c\x7b\xfe\x59\xc9\x79\xf8\xa2\xc4\xf1\x84\xed\x34\x39\xc4\xf8\x04\x97\x16\xfd\x6c\xaf\x33\xa0\x00\x29\x3b\xb5\x37\xdc\xeb\x9b\xa9\x9e\xcc\xec\x39\x47\x9c\x57\x82\xa0\xea\x08\x01\x99\xc6\xd6\x4b\xb0\x2b\x00\xf9\x09\x72\x81\xd9\xae\xf8\x1f\x37\x2a\x36\x71\x56\xd0\x8b\x01\x14\x26\x2a\xad\x58\x7f\xad\x08\x09\x3b\x30\xc0\xf0\xf3\x86\x6c\x7d\x03\x78\x3d\x31\x8f\x00\x41\xa2\x80\x28\x96\x42\x93\xfb\xb6\x48\xb4\x91\x75\x3d\xbe\x7a\x42\x90\xcb\xf4\x6f\xb5\xe8\x5e\xc6\x92\x69\xca\x94\x02\x18\x4f\x74\x13\x4b\x7c\x85\x19\x80\xa1\x9c\x97\x1d\xfb\xab\x71\x50\xf8\x4a\x8b\xdb\x12\x38\xe9\x80\x21\xa2\x87\x9e\x41\xfd\x49\xcc\xfe\x03\x67\x12\x8b\x80\x37\xc1\x46\x17\x55\xab\x6e\x54\xd1\xe9\x45\xbd\xa5\xca\x07\xc7\xdd\x2b\x82\x5f\xd3\x14\xf1\x4a\xde\xdf\x30\x65\x49\x4d\x4b\x00\xbb\x4c\xa8\x8e\x09\x99\xc4\x26\x42\x92\x2a\xcc\x8c\xef\x3b\x68\xc7\xca\xef\x4f\x42\xaa", 0 }, + /* Anchor: 62 EntrustEVRoot.crt serial: #{a.serial.to_s} + C=US,O=Entrust\, Inc.,OU=www.entrust.net/CPS is incorporated by reference,OU=(c) 2006 Entrust\, Inc.,CN=Entrust Root Certification Authority + */ + { 1173, "\x30\x82\x04\x91\x30\x82\x03\x79\xa0\x03\x02\x01\x02\x02\x04\x45\x6b\x50\x54\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xb0\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0a\x13\x0d\x45\x6e\x74\x72\x75\x73\x74\x2c\x20\x49\x6e\x63\x2e\x31\x39\x30\x37\x06\x03\x55\x04\x0b\x13\x30\x77\x77\x77\x2e\x65\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x2f\x43\x50\x53\x20\x69\x73\x20\x69\x6e\x63\x6f\x72\x70\x6f\x72\x61\x74\x65\x64\x20\x62\x79\x20\x72\x65\x66\x65\x72\x65\x6e\x63\x65\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x28\x63\x29\x20\x32\x30\x30\x36\x20\x45\x6e\x74\x72\x75\x73\x74\x2c\x20\x49\x6e\x63\x2e\x31\x2d\x30\x2b\x06\x03\x55\x04\x03\x13\x24\x45\x6e\x74\x72\x75\x73\x74\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x30\x36\x31\x31\x32\x37\x32\x30\x32\x33\x34\x32\x5a\x17\x0d\x32\x36\x31\x31\x32\x37\x32\x30\x35\x33\x34\x32\x5a\x30\x81\xb0\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0a\x13\x0d\x45\x6e\x74\x72\x75\x73\x74\x2c\x20\x49\x6e\x63\x2e\x31\x39\x30\x37\x06\x03\x55\x04\x0b\x13\x30\x77\x77\x77\x2e\x65\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x2f\x43\x50\x53\x20\x69\x73\x20\x69\x6e\x63\x6f\x72\x70\x6f\x72\x61\x74\x65\x64\x20\x62\x79\x20\x72\x65\x66\x65\x72\x65\x6e\x63\x65\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x28\x63\x29\x20\x32\x30\x30\x36\x20\x45\x6e\x74\x72\x75\x73\x74\x2c\x20\x49\x6e\x63\x2e\x31\x2d\x30\x2b\x06\x03\x55\x04\x03\x13\x24\x45\x6e\x74\x72\x75\x73\x74\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xb6\x95\xb6\x43\x42\xfa\xc6\x6d\x2a\x6f\x48\xdf\x94\x4c\x39\x57\x05\xee\xc3\x79\x11\x41\x68\x36\xed\xec\xfe\x9a\x01\x8f\xa1\x38\x28\xfc\xf7\x10\x46\x66\x2e\x4d\x1e\x1a\xb1\x1a\x4e\xc6\xd1\xc0\x95\x88\xb0\xc9\xff\x31\x8b\x33\x03\xdb\xb7\x83\x7b\x3e\x20\x84\x5e\xed\xb2\x56\x28\xa7\xf8\xe0\xb9\x40\x71\x37\xc5\xcb\x47\x0e\x97\x2a\x68\xc0\x22\x95\x62\x15\xdb\x47\xd9\xf5\xd0\x2b\xff\x82\x4b\xc9\xad\x3e\xde\x4c\xdb\x90\x80\x50\x3f\x09\x8a\x84\x00\xec\x30\x0a\x3d\x18\xcd\xfb\xfd\x2a\x59\x9a\x23\x95\x17\x2c\x45\x9e\x1f\x6e\x43\x79\x6d\x0c\x5c\x98\xfe\x48\xa7\xc5\x23\x47\x5c\x5e\xfd\x6e\xe7\x1e\xb4\xf6\x68\x45\xd1\x86\x83\x5b\xa2\x8a\x8d\xb1\xe3\x29\x80\xfe\x25\x71\x88\xad\xbe\xbc\x8f\xac\x52\x96\x4b\xaa\x51\x8d\xe4\x13\x31\x19\xe8\x4e\x4d\x9f\xdb\xac\xb3\x6a\xd5\xbc\x39\x54\x71\xca\x7a\x7a\x7f\x90\xdd\x7d\x1d\x80\xd9\x81\xbb\x59\x26\xc2\x11\xfe\xe6\x93\xe2\xf7\x80\xe4\x65\xfb\x34\x37\x0e\x29\x80\x70\x4d\xaf\x38\x86\x2e\x9e\x7f\x57\xaf\x9e\x17\xae\xeb\x1c\xcb\x28\x21\x5f\xb6\x1c\xd8\xe7\xa2\x04\x22\xf9\xd3\xda\xd8\xcb\x02\x03\x01\x00\x01\xa3\x81\xb0\x30\x81\xad\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x2b\x06\x03\x55\x1d\x10\x04\x24\x30\x22\x80\x0f\x32\x30\x30\x36\x31\x31\x32\x37\x32\x30\x32\x33\x34\x32\x5a\x81\x0f\x32\x30\x32\x36\x31\x31\x32\x37\x32\x30\x35\x33\x34\x32\x5a\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x68\x90\xe4\x67\xa4\xa6\x53\x80\xc7\x86\x66\xa4\xf1\xf7\x4b\x43\xfb\x84\xbd\x6d\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x68\x90\xe4\x67\xa4\xa6\x53\x80\xc7\x86\x66\xa4\xf1\xf7\x4b\x43\xfb\x84\xbd\x6d\x30\x1d\x06\x09\x2a\x86\x48\x86\xf6\x7d\x07\x41\x00\x04\x10\x30\x0e\x1b\x08\x56\x37\x2e\x31\x3a\x34\x2e\x30\x03\x02\x04\x90\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x93\xd4\x30\xb0\xd7\x03\x20\x2a\xd0\xf9\x63\xe8\x91\x0c\x05\x20\xa9\x5f\x19\xca\x7b\x72\x4e\xd4\xb1\xdb\xd0\x96\xfb\x54\x5a\x19\x2c\x0c\x08\xf7\xb2\xbc\x85\xa8\x9d\x7f\x6d\x3b\x52\xb3\x2a\xdb\xe7\xd4\x84\x8c\x63\xf6\x0f\xcb\x26\x01\x91\x50\x6c\xf4\x5f\x14\xe2\x93\x74\xc0\x13\x9e\x30\x3a\x50\xe3\xb4\x60\xc5\x1c\xf0\x22\x44\x8d\x71\x47\xac\xc8\x1a\xc9\xe9\x9b\x9a\x00\x60\x13\xff\x70\x7e\x5f\x11\x4d\x49\x1b\xb3\x15\x52\x7b\xc9\x54\xda\xbf\x9d\x95\xaf\x6b\x9a\xd8\x9e\xe9\xf1\xe4\x43\x8d\xe2\x11\x44\x3a\xbf\xaf\xbd\x83\x42\x73\x52\x8b\xaa\xbb\xa7\x29\xcf\xf5\x64\x1c\x0a\x4d\xd1\xbc\xaa\xac\x9f\x2a\xd0\xff\x7f\x7f\xda\x7d\xea\xb1\xed\x30\x25\xc1\x84\xda\x34\xd2\x5b\x78\x83\x56\xec\x9c\x36\xc3\x26\xe2\x11\xf6\x67\x49\x1d\x92\xab\x8c\xfb\xeb\xff\x7a\xee\x85\x4a\xa7\x50\x80\xf0\xa7\x5c\x4a\x94\x2e\x5f\x05\x99\x3c\x52\x41\xe0\xcd\xb4\x63\xcf\x01\x43\xba\x9c\x83\xdc\x8f\x60\x3b\xf3\x5a\xb4\xb4\x7b\xae\xda\x0b\x90\x38\x75\xef\x81\x1d\x66\xd2\xf7\x57\x70\x36\xb3\xbf\xfc\x28\xaf\x71\x25\x85\x5b\x13\xfe\x1e\x7f\x5a\xb4\x3c", 0 }, + /* Anchor: 63 EntrustRootCA1024.crt serial: #{a.serial.to_s} + C=US,O=Entrust.net,OU=www.entrust.net/CPS incorp. by ref. (limits liab.),OU=(c) 1999 Entrust.net Limited,CN=Entrust.net Secure Server Certification Authority + */ + { 1244, "\x30\x82\x04\xd8\x30\x82\x04\x41\xa0\x03\x02\x01\x02\x02\x04\x37\x4a\xd2\x43\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xc3\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x31\x3b\x30\x39\x06\x03\x55\x04\x0b\x13\x32\x77\x77\x77\x2e\x65\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x2f\x43\x50\x53\x20\x69\x6e\x63\x6f\x72\x70\x2e\x20\x62\x79\x20\x72\x65\x66\x2e\x20\x28\x6c\x69\x6d\x69\x74\x73\x20\x6c\x69\x61\x62\x2e\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0b\x13\x1c\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x3a\x30\x38\x06\x03\x55\x04\x03\x13\x31\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x20\x53\x65\x63\x75\x72\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x39\x39\x30\x35\x32\x35\x31\x36\x30\x39\x34\x30\x5a\x17\x0d\x31\x39\x30\x35\x32\x35\x31\x36\x33\x39\x34\x30\x5a\x30\x81\xc3\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x31\x3b\x30\x39\x06\x03\x55\x04\x0b\x13\x32\x77\x77\x77\x2e\x65\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x2f\x43\x50\x53\x20\x69\x6e\x63\x6f\x72\x70\x2e\x20\x62\x79\x20\x72\x65\x66\x2e\x20\x28\x6c\x69\x6d\x69\x74\x73\x20\x6c\x69\x61\x62\x2e\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0b\x13\x1c\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x3a\x30\x38\x06\x03\x55\x04\x03\x13\x31\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x20\x53\x65\x63\x75\x72\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x81\x9d\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8b\x00\x30\x81\x87\x02\x81\x81\x00\xcd\x28\x83\x34\x54\x1b\x89\xf3\x0f\xaf\x37\x91\x31\xff\xaf\x31\x60\xc9\xa8\xe8\xb2\x10\x68\xed\x9f\xe7\x93\x36\xf1\x0a\x64\xbb\x47\xf5\x04\x17\x3f\x23\x47\x4d\xc5\x27\x19\x81\x26\x0c\x54\x72\x0d\x88\x2d\xd9\x1f\x9a\x12\x9f\xbc\xb3\x71\xd3\x80\x19\x3f\x47\x66\x7b\x8c\x35\x28\xd2\xb9\x0a\xdf\x24\xda\x9c\xd6\x50\x79\x81\x7a\x5a\xd3\x37\xf7\xc2\x4a\xd8\x29\x92\x26\x64\xd1\xe4\x98\x6c\x3a\x00\x8a\xf5\x34\x9b\x65\xf8\xed\xe3\x10\xff\xfd\xb8\x49\x58\xdc\xa0\xde\x82\x39\x6b\x81\xb1\x16\x19\x61\xb9\x54\xb6\xe6\x43\x02\x01\x03\xa3\x82\x01\xd7\x30\x82\x01\xd3\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x82\x01\x19\x06\x03\x55\x1d\x1f\x04\x82\x01\x10\x30\x82\x01\x0c\x30\x81\xde\xa0\x81\xdb\xa0\x81\xd8\xa4\x81\xd5\x30\x81\xd2\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x31\x3b\x30\x39\x06\x03\x55\x04\x0b\x13\x32\x77\x77\x77\x2e\x65\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x2f\x43\x50\x53\x20\x69\x6e\x63\x6f\x72\x70\x2e\x20\x62\x79\x20\x72\x65\x66\x2e\x20\x28\x6c\x69\x6d\x69\x74\x73\x20\x6c\x69\x61\x62\x2e\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0b\x13\x1c\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x3a\x30\x38\x06\x03\x55\x04\x03\x13\x31\x45\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x20\x53\x65\x63\x75\x72\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x0d\x30\x0b\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4c\x31\x30\x29\xa0\x27\xa0\x25\x86\x23\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x65\x6e\x74\x72\x75\x73\x74\x2e\x6e\x65\x74\x2f\x43\x52\x4c\x2f\x6e\x65\x74\x31\x2e\x63\x72\x6c\x30\x2b\x06\x03\x55\x1d\x10\x04\x24\x30\x22\x80\x0f\x31\x39\x39\x39\x30\x35\x32\x35\x31\x36\x30\x39\x34\x30\x5a\x81\x0f\x32\x30\x31\x39\x30\x35\x32\x35\x31\x36\x30\x39\x34\x30\x5a\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x06\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\xf0\x17\x62\x13\x55\x3d\xb3\xff\x0a\x00\x6b\xfb\x50\x84\x97\xf3\xed\x62\xd0\x1a\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xf0\x17\x62\x13\x55\x3d\xb3\xff\x0a\x00\x6b\xfb\x50\x84\x97\xf3\xed\x62\xd0\x1a\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x19\x06\x09\x2a\x86\x48\x86\xf6\x7d\x07\x41\x00\x04\x0c\x30\x0a\x1b\x04\x56\x34\x2e\x30\x03\x02\x04\x90\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x90\xdc\x30\x02\xfa\x64\x74\xc2\xa7\x0a\xa5\x7c\x21\x8d\x34\x17\xa8\xfb\x47\x0e\xff\x25\x7c\x8d\x13\x0a\xfb\xe4\x98\xb5\xef\x8c\xf8\xc5\x10\x0d\xf7\x92\xbe\xf1\xc3\xd5\xd5\x95\x6a\x04\xbb\x2c\xce\x26\x36\x65\xc8\x31\xc6\xe7\xee\x3f\xe3\x57\x75\x84\x7a\x11\xef\x46\x4f\x18\xf4\xd3\x98\xbb\xa8\x87\x32\xba\x72\xf6\x3c\xe2\x3d\x9f\xd7\x1d\xd9\xc3\x60\x43\x8c\x58\x0e\x22\x96\x2f\x62\xa3\x2c\x1f\xba\xad\x05\xef\xab\x32\x78\x87\xa0\x54\x73\x19\xb5\x5c\x05\xf9\x52\x3e\x6d\x2d\x45\x0b\xf7\x0a\x93\xea\xed\x06\xf9\xb2", 0 }, + /* Anchor: 64 Equifax_Secure_Certificate_Auth serial: #{a.serial.to_s} + C=US,O=Equifax,OU=Equifax Secure Certificate Authority + */ + { 804, "\x30\x82\x03\x20\x30\x82\x02\x89\xa0\x03\x02\x01\x02\x02\x04\x35\xde\xf4\xcf\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x4e\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0e\x06\x03\x55\x04\x0a\x13\x07\x45\x71\x75\x69\x66\x61\x78\x31\x2d\x30\x2b\x06\x03\x55\x04\x0b\x13\x24\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x39\x38\x30\x38\x32\x32\x31\x36\x34\x31\x35\x31\x5a\x17\x0d\x31\x38\x30\x38\x32\x32\x31\x36\x34\x31\x35\x31\x5a\x30\x4e\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0e\x06\x03\x55\x04\x0a\x13\x07\x45\x71\x75\x69\x66\x61\x78\x31\x2d\x30\x2b\x06\x03\x55\x04\x0b\x13\x24\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xc1\x5d\xb1\x58\x67\x08\x62\xee\xa0\x9a\x2d\x1f\x08\x6d\x91\x14\x68\x98\x0a\x1e\xfe\xda\x04\x6f\x13\x84\x62\x21\xc3\xd1\x7c\xce\x9f\x05\xe0\xb8\x01\xf0\x4e\x34\xec\xe2\x8a\x95\x04\x64\xac\xf1\x6b\x53\x5f\x05\xb3\xcb\x67\x80\xbf\x42\x02\x8e\xfe\xdd\x01\x09\xec\xe1\x00\x14\x4f\xfc\xfb\xf0\x0c\xdd\x43\xba\x5b\x2b\xe1\x1f\x80\x70\x99\x15\x57\x93\x16\xf1\x0f\x97\x6a\xb7\xc2\x68\x23\x1c\xcc\x4d\x59\x30\xac\x51\x1e\x3b\xaf\x2b\xd6\xee\x63\x45\x7b\xc5\xd9\x5f\x50\xd2\xe3\x50\x0f\x3a\x88\xe7\xbf\x14\xfd\xe0\xc7\xb9\x02\x03\x01\x00\x01\xa3\x82\x01\x09\x30\x82\x01\x05\x30\x70\x06\x03\x55\x1d\x1f\x04\x69\x30\x67\x30\x65\xa0\x63\xa0\x61\xa4\x5f\x30\x5d\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0e\x06\x03\x55\x04\x0a\x13\x07\x45\x71\x75\x69\x66\x61\x78\x31\x2d\x30\x2b\x06\x03\x55\x04\x0b\x13\x24\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x0d\x30\x0b\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4c\x31\x30\x1a\x06\x03\x55\x1d\x10\x04\x13\x30\x11\x81\x0f\x32\x30\x31\x38\x30\x38\x32\x32\x31\x36\x34\x31\x35\x31\x5a\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x06\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x48\xe6\x68\xf9\x2b\xd2\xb2\x95\xd7\x47\xd8\x23\x20\x10\x4f\x33\x98\x90\x9f\xd4\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x48\xe6\x68\xf9\x2b\xd2\xb2\x95\xd7\x47\xd8\x23\x20\x10\x4f\x33\x98\x90\x9f\xd4\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x1a\x06\x09\x2a\x86\x48\x86\xf6\x7d\x07\x41\x00\x04\x0d\x30\x0b\x1b\x05\x56\x33\x2e\x30\x63\x03\x02\x06\xc0\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x58\xce\x29\xea\xfc\xf7\xde\xb5\xce\x02\xb9\x17\xb5\x85\xd1\xb9\xe3\xe0\x95\xcc\x25\x31\x0d\x00\xa6\x92\x6e\x7f\xb6\x92\x63\x9e\x50\x95\xd1\x9a\x6f\xe4\x11\xde\x63\x85\x6e\x98\xee\xa8\xff\x5a\xc8\xd3\x55\xb2\x66\x71\x57\xde\xc0\x21\xeb\x3d\x2a\xa7\x23\x49\x01\x04\x86\x42\x7b\xfc\xee\x7f\xa2\x16\x52\xb5\x67\x67\xd3\x40\xdb\x3b\x26\x58\xb2\x28\x77\x3d\xae\x14\x77\x61\xd6\xfa\x2a\x66\x27\xa0\x0d\xfa\xa7\x73\x5c\xea\x70\xf1\x94\x21\x65\x44\x5f\xfa\xfc\xef\x29\x68\xa9\xa2\x87\x79\xef\x79\xef\x4f\xac\x07\x77\x38", 0 }, + /* Anchor: 65 Equifax_Secure_eBusiness_CA-1.cer serial: #{a.serial.to_s} + C=US,O=Equifax Secure Inc.,CN=Equifax Secure eBusiness CA-1 + */ + { 646, "\x30\x82\x02\x82\x30\x82\x01\xeb\xa0\x03\x02\x01\x02\x02\x01\x04\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x30\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x49\x6e\x63\x2e\x31\x26\x30\x24\x06\x03\x55\x04\x03\x13\x1d\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x65\x42\x75\x73\x69\x6e\x65\x73\x73\x20\x43\x41\x2d\x31\x30\x1e\x17\x0d\x39\x39\x30\x36\x32\x31\x30\x34\x30\x30\x30\x30\x5a\x17\x0d\x32\x30\x30\x36\x32\x31\x30\x34\x30\x30\x30\x30\x5a\x30\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x49\x6e\x63\x2e\x31\x26\x30\x24\x06\x03\x55\x04\x03\x13\x1d\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x65\x42\x75\x73\x69\x6e\x65\x73\x73\x20\x43\x41\x2d\x31\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xce\x2f\x19\xbc\x17\xb7\x77\xde\x93\xa9\x5f\x5a\x0d\x17\x4f\x34\x1a\x0c\x98\xf4\x22\xd9\x59\xd4\xc4\x68\x46\xf0\xb4\x35\xc5\x85\x03\x20\xc6\xaf\x45\xa5\x21\x51\x45\x41\xeb\x16\x58\x36\x32\x6f\xe2\x50\x62\x64\xf9\xfd\x51\x9c\xaa\x24\xd9\xf4\x9d\x83\x2a\x87\x0a\x21\xd3\x12\x38\x34\x6c\x8d\x00\x6e\x5a\xa0\xd9\x42\xee\x1a\x21\x95\xf9\x52\x4c\x55\x5a\xc5\x0f\x38\x4f\x46\xfa\x6d\xf8\x2e\x35\xd6\x1d\x7c\xeb\xe2\xf0\xb0\x75\x80\xc8\xa9\x13\xac\xbe\x88\xef\x3a\x6e\xab\x5f\x2a\x38\x62\x02\xb0\x12\x7b\xfe\x8f\xa6\x03\x02\x03\x01\x00\x01\xa3\x66\x30\x64\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x4a\x78\x32\x52\x11\xdb\x59\x16\x36\x5e\xdf\xc1\x14\x36\x40\x6a\x47\x7c\x4c\xa1\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x4a\x78\x32\x52\x11\xdb\x59\x16\x36\x5e\xdf\xc1\x14\x36\x40\x6a\x47\x7c\x4c\xa1\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x03\x81\x81\x00\x75\x5b\xa8\x9b\x03\x11\xe6\xe9\x56\x4c\xcd\xf9\xa9\x4c\xc0\x0d\x9a\xf3\xcc\x65\x69\xe6\x25\x76\xcc\x59\xb7\xd6\x54\xc3\x1d\xcd\x99\xac\x19\xdd\xb4\x85\xd5\xe0\x3d\xfc\x62\x20\xa7\x84\x4b\x58\x65\xf1\xe2\xf9\x95\x21\x3f\xf5\xd4\x7e\x58\x1e\x47\x87\x54\x3e\x58\xa1\xb5\xb5\xf8\x2a\xef\x71\xe7\xbc\xc3\xf6\xb1\x49\x46\xe2\xd7\xa0\x6b\xe5\x56\x7a\x9a\x27\x98\x7c\x46\x62\x14\xe7\xc9\xfc\x6e\x03\x12\x79\x80\x38\x1d\x48\x82\x8d\xfc\x17\xfe\x2a\x96\x2b\xb5\x62\xa6\xa6\x3d\xbd\x7f\x92\x59\xcd\x5a\x2a\x82\xb2\x37\x79", 0 }, + /* Anchor: 66 Equifax_Secure_eBusiness_CA-2.cer serial: #{a.serial.to_s} + C=US,O=Equifax Secure,OU=Equifax Secure eBusiness CA-2 + */ + { 804, "\x30\x82\x03\x20\x30\x82\x02\x89\xa0\x03\x02\x01\x02\x02\x04\x37\x70\xcf\xb5\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x4e\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x31\x26\x30\x24\x06\x03\x55\x04\x0b\x13\x1d\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x65\x42\x75\x73\x69\x6e\x65\x73\x73\x20\x43\x41\x2d\x32\x30\x1e\x17\x0d\x39\x39\x30\x36\x32\x33\x31\x32\x31\x34\x34\x35\x5a\x17\x0d\x31\x39\x30\x36\x32\x33\x31\x32\x31\x34\x34\x35\x5a\x30\x4e\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x31\x26\x30\x24\x06\x03\x55\x04\x0b\x13\x1d\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x65\x42\x75\x73\x69\x6e\x65\x73\x73\x20\x43\x41\x2d\x32\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xe4\x39\x39\x93\x1e\x52\x06\x1b\x28\x36\xf8\xb2\xa3\x29\xc5\xed\x8e\xb2\x11\xbd\xfe\xeb\xe7\xb4\x74\xc2\x8f\xff\x05\xe7\xd9\x9d\x06\xbf\x12\xc8\x3f\x0e\xf2\xd6\xd1\x24\xb2\x11\xde\xd1\x73\x09\x8a\xd4\xb1\x2c\x98\x09\x0d\x1e\x50\x46\xb2\x83\xa6\x45\x8d\x62\x68\xbb\x85\x1b\x20\x70\x32\xaa\x40\xcd\xa6\x96\x5f\xc4\x71\x37\x3f\x04\xf3\xb7\x41\x24\x39\x07\x1a\x1e\x2e\x61\x58\xa0\x12\x0b\xe5\xa5\xdf\xc5\xab\xea\x37\x71\xcc\x1c\xc8\x37\x3a\xb9\x97\x52\xa7\xac\xc5\x6a\x24\x94\x4e\x9c\x7b\xcf\xc0\x6a\xd6\xdf\x21\xbd\x02\x03\x01\x00\x01\xa3\x82\x01\x09\x30\x82\x01\x05\x30\x70\x06\x03\x55\x1d\x1f\x04\x69\x30\x67\x30\x65\xa0\x63\xa0\x61\xa4\x5f\x30\x5d\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x31\x26\x30\x24\x06\x03\x55\x04\x0b\x13\x1d\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x65\x42\x75\x73\x69\x6e\x65\x73\x73\x20\x43\x41\x2d\x32\x31\x0d\x30\x0b\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4c\x31\x30\x1a\x06\x03\x55\x1d\x10\x04\x13\x30\x11\x81\x0f\x32\x30\x31\x39\x30\x36\x32\x33\x31\x32\x31\x34\x34\x35\x5a\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x06\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x50\x9e\x0b\xea\xaf\x5e\xb9\x20\x48\xa6\x50\x6a\xcb\xfd\xd8\x20\x7a\xa7\x82\x76\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x50\x9e\x0b\xea\xaf\x5e\xb9\x20\x48\xa6\x50\x6a\xcb\xfd\xd8\x20\x7a\xa7\x82\x76\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x1a\x06\x09\x2a\x86\x48\x86\xf6\x7d\x07\x41\x00\x04\x0d\x30\x0b\x1b\x05\x56\x33\x2e\x30\x63\x03\x02\x06\xc0\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x0c\x86\x82\xad\xe8\x4e\x1a\xf5\x8e\x89\x27\xe2\x35\x58\x3d\x29\xb4\x07\x8f\x36\x50\x95\xbf\x6e\xc1\x9e\xeb\xc4\x90\xb2\x85\xa8\xbb\xb7\x42\xe0\x0f\x07\x39\xdf\xfb\x9e\x90\xb2\xd1\xc1\x3e\x53\x9f\x03\x44\xb0\x7e\x4b\xf4\x6f\xe4\x7c\x1f\xe7\xe2\xb1\xe4\xb8\x9a\xef\xc3\xbd\xce\xde\x0b\x32\x34\xd9\xde\x28\xed\x33\x6b\xc4\xd4\xd7\x3d\x12\x58\xab\x7d\x09\x2d\xcb\x70\xf5\x13\x8a\x94\xa1\x27\xa4\xd6\x70\xc5\x6d\x94\xb5\xc9\x7d\x9d\xa0\xd2\xc6\x08\x49\xd9\x66\x9b\xa6\xd3\xf4\x0b\xdc\xc5\x26\x57\xe1\x91\x30\xea\xcd", 0 }, + /* Anchor: 67 Equifax_Secure_Global_eBusiness serial: #{a.serial.to_s} + C=US,O=Equifax Secure Inc.,CN=Equifax Secure Global eBusiness CA-1 + */ + { 660, "\x30\x82\x02\x90\x30\x82\x01\xf9\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x30\x5a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x49\x6e\x63\x2e\x31\x2d\x30\x2b\x06\x03\x55\x04\x03\x13\x24\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x47\x6c\x6f\x62\x61\x6c\x20\x65\x42\x75\x73\x69\x6e\x65\x73\x73\x20\x43\x41\x2d\x31\x30\x1e\x17\x0d\x39\x39\x30\x36\x32\x31\x30\x34\x30\x30\x30\x30\x5a\x17\x0d\x32\x30\x30\x36\x32\x31\x30\x34\x30\x30\x30\x30\x5a\x30\x5a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x49\x6e\x63\x2e\x31\x2d\x30\x2b\x06\x03\x55\x04\x03\x13\x24\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x47\x6c\x6f\x62\x61\x6c\x20\x65\x42\x75\x73\x69\x6e\x65\x73\x73\x20\x43\x41\x2d\x31\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xba\xe7\x17\x90\x02\x65\xb1\x34\x55\x3c\x49\xc2\x51\xd5\xdf\xa7\xd1\x37\x8f\xd1\xe7\x81\x73\x41\x52\x60\x9b\x9d\xa1\x17\x26\x78\xad\xc7\xb1\xe8\x26\x94\x32\xb5\xde\x33\x8d\x3a\x2f\xdb\xf2\x9a\x7a\x5a\x73\x98\xa3\x5c\xe9\xfb\x8a\x73\x1b\x5c\xe7\xc3\xbf\x80\x6c\xcd\xa9\xf4\xd6\x2b\xc0\xf7\xf9\x99\xaa\x63\xa2\xb1\x47\x02\x0f\xd4\xe4\x51\x3a\x12\x3c\x6c\x8a\x5a\x54\x84\x70\xdb\xc1\xc5\x90\xcf\x72\x45\xcb\xa8\x59\xc0\xcd\x33\x9d\x3f\xa3\x96\xeb\x85\x33\x21\x1c\x3e\x1e\x3e\x60\x6e\x76\x9c\x67\x85\xc5\xc8\xc3\x61\x02\x03\x01\x00\x01\xa3\x66\x30\x64\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\xbe\xa8\xa0\x74\x72\x50\x6b\x44\xb7\xc9\x23\xd8\xfb\xa8\xff\xb3\x57\x6b\x68\x6c\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xbe\xa8\xa0\x74\x72\x50\x6b\x44\xb7\xc9\x23\xd8\xfb\xa8\xff\xb3\x57\x6b\x68\x6c\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x03\x81\x81\x00\x30\xe2\x01\x51\xaa\xc7\xea\x5f\xda\xb9\xd0\x65\x0f\x30\xd6\x3e\xda\x0d\x14\x49\x6e\x91\x93\x27\x14\x31\xef\xc4\xf7\x2d\x45\xf8\xec\xc7\xbf\xa2\x41\x0d\x23\xb4\x92\xf9\x19\x00\x67\xbd\x01\xaf\xcd\xe0\x71\xfc\x5a\xcf\x64\xc4\xe0\x96\x98\xd0\xa3\x40\xe2\x01\x8a\xef\x27\x07\xf1\x65\x01\x8a\x44\x2d\x06\x65\x75\x52\xc0\x86\x10\x20\x21\x5f\x6c\x6b\x0f\x6c\xae\x09\x1c\xaf\xf2\xa2\x18\x34\xc4\x75\xa4\x73\x1c\xf1\x8d\xdc\xef\xad\xf9\xb3\x76\xb4\x92\xbf\xdc\x95\x10\x1e\xbe\xcb\xc8\x3b\x5a\x84\x60\x19\x56\x94\xa9\x55", 0 }, + /* Anchor: 68 Estonia-Juur-SK.cer serial: #{a.serial.to_s} + 1.2.840.113549.1.9.1=#1609706B6940736B2E6565,C=EE,O=AS Sertifitseerimiskeskus,CN=Juur-SK + */ + { 1258, "\x30\x82\x04\xe6\x30\x82\x03\xce\xa0\x03\x02\x01\x02\x02\x04\x3b\x8e\x4b\xfc\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x5d\x31\x18\x30\x16\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x09\x70\x6b\x69\x40\x73\x6b\x2e\x65\x65\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x45\x31\x22\x30\x20\x06\x03\x55\x04\x0a\x13\x19\x41\x53\x20\x53\x65\x72\x74\x69\x66\x69\x74\x73\x65\x65\x72\x69\x6d\x69\x73\x6b\x65\x73\x6b\x75\x73\x31\x10\x30\x0e\x06\x03\x55\x04\x03\x13\x07\x4a\x75\x75\x72\x2d\x53\x4b\x30\x1e\x17\x0d\x30\x31\x30\x38\x33\x30\x31\x34\x32\x33\x30\x31\x5a\x17\x0d\x31\x36\x30\x38\x32\x36\x31\x34\x32\x33\x30\x31\x5a\x30\x5d\x31\x18\x30\x16\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x09\x70\x6b\x69\x40\x73\x6b\x2e\x65\x65\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x45\x31\x22\x30\x20\x06\x03\x55\x04\x0a\x13\x19\x41\x53\x20\x53\x65\x72\x74\x69\x66\x69\x74\x73\x65\x65\x72\x69\x6d\x69\x73\x6b\x65\x73\x6b\x75\x73\x31\x10\x30\x0e\x06\x03\x55\x04\x03\x13\x07\x4a\x75\x75\x72\x2d\x53\x4b\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\x81\x71\x36\x3e\x33\x07\xd6\xe3\x30\x8d\x13\x7e\x77\x32\x46\xcb\xcf\x19\xb2\x60\x31\x46\x97\x86\xf4\x98\x46\xa4\xc2\x65\x45\xcf\xd3\x40\x7c\xe3\x5a\x22\xa8\x10\x78\x33\xcc\x88\xb1\xd3\x81\x4a\xf6\x62\x17\x7b\x5f\x4d\x0a\x2e\xd0\xcf\x8b\x23\xee\x4f\x02\x4e\xbb\xeb\x0e\xca\xbd\x18\x63\xe8\x80\x1c\x8d\xe1\x1c\x8d\x3d\xe0\xff\x5b\x5f\xea\x64\xe5\x97\xe8\x3f\x99\x7f\x0c\x0a\x09\x33\x00\x1a\x53\xa7\x21\xe1\x38\x4b\xd6\x83\x1b\xad\xaf\x64\xc2\xf9\x1c\x7a\x8c\x66\x48\x4d\x66\x1f\x18\x0a\xe2\x3e\xbb\x1f\x07\x65\x93\x85\xb9\x1a\xb0\xb9\xc4\xfb\x0d\x11\xf6\xf5\xd6\xf9\x1b\xc7\x2c\x2b\xb7\x18\x51\xfe\xe0\x7b\xf6\xa8\x48\xaf\x6c\x3b\x4f\x2f\xef\xf8\xd1\x47\x1e\x26\x57\xf0\x51\x1d\x33\x96\xff\xef\x59\x3d\xda\x4d\xd1\x15\x34\xc7\xea\x3f\x16\x48\x7b\x91\x1c\x80\x43\x0f\x3d\xb8\x05\x3e\xd1\xb3\x95\xcd\xd8\xca\x0f\xc2\x43\x67\xdb\xb7\x93\xe0\x22\x82\x2e\xbe\xf5\x68\x28\x83\xb9\xc1\x3b\x69\x7b\x20\xda\x4e\x9c\x6d\xe1\xba\xcd\x8f\x7a\x6c\xb0\x09\x22\xd7\x8b\x0b\xdb\x1c\xd5\x5a\x26\x5b\x0d\xc0\xea\xe5\x60\xd0\x9f\xfe\x35\xdf\x3f\x02\x03\x01\x00\x01\xa3\x82\x01\xac\x30\x82\x01\xa8\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x82\x01\x16\x06\x03\x55\x1d\x20\x04\x82\x01\x0d\x30\x82\x01\x09\x30\x82\x01\x05\x06\x0a\x2b\x06\x01\x04\x01\xce\x1f\x01\x01\x01\x30\x81\xf6\x30\x81\xd0\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x02\x30\x81\xc3\x1e\x81\xc0\x00\x53\x00\x65\x00\x65\x00\x20\x00\x73\x00\x65\x00\x72\x00\x74\x00\x69\x00\x66\x00\x69\x00\x6b\x00\x61\x00\x61\x00\x74\x00\x20\x00\x6f\x00\x6e\x00\x20\x00\x76\x00\xe4\x00\x6c\x00\x6a\x00\x61\x00\x73\x00\x74\x00\x61\x00\x74\x00\x75\x00\x64\x00\x20\x00\x41\x00\x53\x00\x2d\x00\x69\x00\x73\x00\x20\x00\x53\x00\x65\x00\x72\x00\x74\x00\x69\x00\x66\x00\x69\x00\x74\x00\x73\x00\x65\x00\x65\x00\x72\x00\x69\x00\x6d\x00\x69\x00\x73\x00\x6b\x00\x65\x00\x73\x00\x6b\x00\x75\x00\x73\x00\x20\x00\x61\x00\x6c\x00\x61\x00\x6d\x00\x2d\x00\x53\x00\x4b\x00\x20\x00\x73\x00\x65\x00\x72\x00\x74\x00\x69\x00\x66\x00\x69\x00\x6b\x00\x61\x00\x61\x00\x74\x00\x69\x00\x64\x00\x65\x00\x20\x00\x6b\x00\x69\x00\x6e\x00\x6e\x00\x69\x00\x74\x00\x61\x00\x6d\x00\x69\x00\x73\x00\x65\x00\x6b\x00\x73\x30\x21\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x15\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x73\x6b\x2e\x65\x65\x2f\x63\x70\x73\x2f\x30\x2b\x06\x03\x55\x1d\x1f\x04\x24\x30\x22\x30\x20\xa0\x1e\xa0\x1c\x86\x1a\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x73\x6b\x2e\x65\x65\x2f\x6a\x75\x75\x72\x2f\x63\x72\x6c\x2f\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x04\xaa\x7a\x47\xa3\xe4\x89\xaf\x1a\xcf\x0a\x40\xa7\x18\x3f\x6f\xef\xe9\x7d\xbe\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x04\xaa\x7a\x47\xa3\xe4\x89\xaf\x1a\xcf\x0a\x40\xa7\x18\x3f\x6f\xef\xe9\x7d\xbe\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\xe6\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x7b\xc1\x18\x94\x53\xa2\x09\xf3\xfe\x26\x67\x9a\x50\xe4\xc3\x05\x2f\x2b\x35\x78\x91\x4c\x7c\xa8\x11\x11\x79\x4c\x49\x59\xac\xc8\xf7\x85\x65\x5c\x46\xbb\x3b\x10\xa0\x02\xaf\xcd\x4f\xb5\xcc\x36\x2a\xec\x5d\xfe\xef\xa0\x91\xc9\xb6\x93\x6f\x7c\x80\x54\xec\xc7\x08\x70\x0d\x8e\xfb\x82\xec\x2a\x60\x78\x69\x36\x36\xd1\xc5\x9c\x8b\x69\xb5\x40\xc8\x94\x65\x77\xf2\x57\x21\x66\x3b\xce\x85\x40\xb6\x33\x63\x1a\xbf\x79\x1e\xfc\x5c\x1d\xd3\x1d\x93\x1b\x8b\x0c\x5d\x85\xbd\x99\x30\x32\x18\x09\x91\x52\xe9\x7c\xa1\xba\xff\x64\x92\x9a\xec\xfe\x35\xee\x8c\x2f\xae\xfc\x20\x86\xec\x4a\xde\x1b\x78\x32\x37\xa6\x81\xd2\x9d\xaf\x5a\x12\x16\xca\x99\x5b\xfc\x6f\x6d\x0e\xc5\xa0\x1e\x86\xc9\x91\xd0\x5c\x98\x82\x5f\x63\x0c\x8a\x5a\xab\xd8\x95\xa6\xcc\xcb\x8a\xd6\xbf\x64\x4b\x8e\xca\x8a\xb2\xb0\xe9\x21\x32\x9e\xaa\xa8\x85\x98\x34\x81\x39\x21\x3b\xa8\x3a\x52\x32\x3d\xf6\x6b\x37\x86\x06\x5a\x15\x98\xdc\xf0\x11\x66\xfe\x34\x20\xb7\x03\xf4\x41\x10\x7d\x39\x84\x79\x96\x72\x63\xb6\x96\x02\xe5\x6b\xb9\xad\x19\x4d\xbb\xc6\x44\xdb\x36\xcb\x2a\x9c\x8e", 0 }, + /* Anchor: 69 expressz.cer serial: #{a.serial.to_s} + C=HU,L=Budapest,O=NetLock Halozatbiztonsagi Kft.,OU=Tanusitvanykiadok,CN=NetLock Expressz (Class C) Tanusitvanykiado + */ + { 1363, "\x30\x82\x05\x4f\x30\x82\x04\xb8\xa0\x03\x02\x01\x02\x02\x01\x68\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x30\x81\x9b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0f\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0a\x13\x1e\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x48\x61\x6c\x6f\x7a\x61\x74\x62\x69\x7a\x74\x6f\x6e\x73\x61\x67\x69\x20\x4b\x66\x74\x2e\x31\x1a\x30\x18\x06\x03\x55\x04\x0b\x13\x11\x54\x61\x6e\x75\x73\x69\x74\x76\x61\x6e\x79\x6b\x69\x61\x64\x6f\x6b\x31\x34\x30\x32\x06\x03\x55\x04\x03\x13\x2b\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x45\x78\x70\x72\x65\x73\x73\x7a\x20\x28\x43\x6c\x61\x73\x73\x20\x43\x29\x20\x54\x61\x6e\x75\x73\x69\x74\x76\x61\x6e\x79\x6b\x69\x61\x64\x6f\x30\x1e\x17\x0d\x39\x39\x30\x32\x32\x35\x31\x34\x30\x38\x31\x31\x5a\x17\x0d\x31\x39\x30\x32\x32\x30\x31\x34\x30\x38\x31\x31\x5a\x30\x81\x9b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0f\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0a\x13\x1e\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x48\x61\x6c\x6f\x7a\x61\x74\x62\x69\x7a\x74\x6f\x6e\x73\x61\x67\x69\x20\x4b\x66\x74\x2e\x31\x1a\x30\x18\x06\x03\x55\x04\x0b\x13\x11\x54\x61\x6e\x75\x73\x69\x74\x76\x61\x6e\x79\x6b\x69\x61\x64\x6f\x6b\x31\x34\x30\x32\x06\x03\x55\x04\x03\x13\x2b\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x45\x78\x70\x72\x65\x73\x73\x7a\x20\x28\x43\x6c\x61\x73\x73\x20\x43\x29\x20\x54\x61\x6e\x75\x73\x69\x74\x76\x61\x6e\x79\x6b\x69\x61\x64\x6f\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xeb\xec\xb0\x6c\x61\x8a\x23\x25\xaf\x60\x20\xe3\xd9\x9f\xfc\x93\x0b\xdb\x5d\x8d\xb0\xa1\xb3\x40\x3a\x82\xce\xfd\x75\xe0\x78\x32\x03\x86\x5a\x86\x95\x91\xed\x53\xfa\x9d\x40\xfc\xe6\xe8\xdd\xd9\x5b\x7a\x03\xbd\x5d\xf3\x3b\x0c\xc3\x51\x79\x9b\xad\x55\xa0\xe9\xd0\x03\x10\xaf\x0a\xba\x14\x42\xd9\x52\x26\x11\x22\xc7\xd2\x20\xcc\x82\xa4\x9a\xa9\xfe\xb8\x81\x76\x9d\x6a\xb7\xd2\x36\x75\x3e\xb1\x86\x09\xf6\x6e\x6d\x7e\x4e\xb7\x7a\xec\xae\x71\x84\xf6\x04\x33\x08\x25\x32\xeb\x74\xac\x16\x44\xc6\xe4\x40\x93\x1d\x7f\xad\x02\x03\x01\x00\x01\xa3\x82\x02\x9f\x30\x82\x02\x9b\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01\x04\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x00\x06\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x82\x02\x60\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x0d\x04\x82\x02\x51\x16\x82\x02\x4d\x46\x49\x47\x59\x45\x4c\x45\x4d\x21\x20\x45\x7a\x65\x6e\x20\x74\x61\x6e\x75\x73\x69\x74\x76\x61\x6e\x79\x20\x61\x20\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x4b\x66\x74\x2e\x20\x41\x6c\x74\x61\x6c\x61\x6e\x6f\x73\x20\x53\x7a\x6f\x6c\x67\x61\x6c\x74\x61\x74\x61\x73\x69\x20\x46\x65\x6c\x74\x65\x74\x65\x6c\x65\x69\x62\x65\x6e\x20\x6c\x65\x69\x72\x74\x20\x65\x6c\x6a\x61\x72\x61\x73\x6f\x6b\x20\x61\x6c\x61\x70\x6a\x61\x6e\x20\x6b\x65\x73\x7a\x75\x6c\x74\x2e\x20\x41\x20\x68\x69\x74\x65\x6c\x65\x73\x69\x74\x65\x73\x20\x66\x6f\x6c\x79\x61\x6d\x61\x74\x61\x74\x20\x61\x20\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x4b\x66\x74\x2e\x20\x74\x65\x72\x6d\x65\x6b\x66\x65\x6c\x65\x6c\x6f\x73\x73\x65\x67\x2d\x62\x69\x7a\x74\x6f\x73\x69\x74\x61\x73\x61\x20\x76\x65\x64\x69\x2e\x20\x41\x20\x64\x69\x67\x69\x74\x61\x6c\x69\x73\x20\x61\x6c\x61\x69\x72\x61\x73\x20\x65\x6c\x66\x6f\x67\x61\x64\x61\x73\x61\x6e\x61\x6b\x20\x66\x65\x6c\x74\x65\x74\x65\x6c\x65\x20\x61\x7a\x20\x65\x6c\x6f\x69\x72\x74\x20\x65\x6c\x6c\x65\x6e\x6f\x72\x7a\x65\x73\x69\x20\x65\x6c\x6a\x61\x72\x61\x73\x20\x6d\x65\x67\x74\x65\x74\x65\x6c\x65\x2e\x20\x41\x7a\x20\x65\x6c\x6a\x61\x72\x61\x73\x20\x6c\x65\x69\x72\x61\x73\x61\x20\x6d\x65\x67\x74\x61\x6c\x61\x6c\x68\x61\x74\x6f\x20\x61\x20\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x4b\x66\x74\x2e\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x68\x6f\x6e\x6c\x61\x70\x6a\x61\x6e\x20\x61\x20\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x6e\x65\x74\x6c\x6f\x63\x6b\x2e\x6e\x65\x74\x2f\x64\x6f\x63\x73\x20\x63\x69\x6d\x65\x6e\x20\x76\x61\x67\x79\x20\x6b\x65\x72\x68\x65\x74\x6f\x20\x61\x7a\x20\x65\x6c\x6c\x65\x6e\x6f\x72\x7a\x65\x73\x40\x6e\x65\x74\x6c\x6f\x63\x6b\x2e\x6e\x65\x74\x20\x65\x2d\x6d\x61\x69\x6c\x20\x63\x69\x6d\x65\x6e\x2e\x20\x49\x4d\x50\x4f\x52\x54\x41\x4e\x54\x21\x20\x54\x68\x65\x20\x69\x73\x73\x75\x61\x6e\x63\x65\x20\x61\x6e\x64\x20\x74\x68\x65\x20\x75\x73\x65\x20\x6f\x66\x20\x74\x68\x69\x73\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x69\x73\x20\x73\x75\x62\x6a\x65\x63\x74\x20\x74\x6f\x20\x74\x68\x65\x20\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x43\x50\x53\x20\x61\x76\x61\x69\x6c\x61\x62\x6c\x65\x20\x61\x74\x20\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x6e\x65\x74\x6c\x6f\x63\x6b\x2e\x6e\x65\x74\x2f\x64\x6f\x63\x73\x20\x6f\x72\x20\x62\x79\x20\x65\x2d\x6d\x61\x69\x6c\x20\x61\x74\x20\x63\x70\x73\x40\x6e\x65\x74\x6c\x6f\x63\x6b\x2e\x6e\x65\x74\x2e\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x03\x81\x81\x00\x10\xad\x7f\xd7\x0c\x32\x80\x0a\xd8\x86\xf1\x79\x98\xb5\xad\xd4\xcd\xb3\x36\xc4\x96\x48\xc1\x5c\xcd\x9a\xd9\x05\x2e\x9f\xbe\x50\xeb\xf4\x26\x14\x10\x2d\xd4\x66\x17\xf8\x9e\xc1\x27\xfd\xf1\xed\xe4\x7b\x4b\xa0\x6c\xb5\xab\x9a\x57\x70\xa6\xed\xa0\xa4\xed\x2e\xf5\xfd\xfc\xbd\xfe\x4d\x37\x08\x0c\xbc\xe3\x96\x83\x22\xf5\x49\x1b\x7f\x4b\x2b\xb4\x54\xc1\x80\x7c\x99\x4e\x1d\xd0\x8c\xee\xd0\xac\xe5\x92\xfa\x75\x56\xfe\x64\xa0\x13\x8f\xb8\xb8\x16\x9d\x61\x05\x67\x80\xc8\xd0\xd8\xa5\x07\x02\x34\x98\x04\x8d\x33\x04\xd4", 0 }, + /* Anchor: 70 FBCA-commonpolicy2.cer serial: #{a.serial.to_s} + C=us,O=U.S. Government,OU=FBCA,CN=Common Policy + */ + { 933, "\x30\x82\x03\xa1\x30\x82\x02\x89\xa0\x03\x02\x01\x02\x02\x10\x29\x36\x47\xaa\xe3\x8a\xac\x86\x4a\x23\x56\xf2\xca\xb7\x61\xaf\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x4e\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x75\x73\x31\x18\x30\x16\x06\x03\x55\x04\x0a\x13\x0f\x55\x2e\x53\x2e\x20\x47\x6f\x76\x65\x72\x6e\x6d\x65\x6e\x74\x31\x0d\x30\x0b\x06\x03\x55\x04\x0b\x13\x04\x46\x42\x43\x41\x31\x16\x30\x14\x06\x03\x55\x04\x03\x13\x0d\x43\x6f\x6d\x6d\x6f\x6e\x20\x50\x6f\x6c\x69\x63\x79\x30\x1e\x17\x0d\x30\x37\x31\x30\x31\x35\x31\x35\x35\x38\x30\x30\x5a\x17\x0d\x32\x37\x31\x30\x31\x35\x31\x36\x30\x38\x30\x30\x5a\x30\x4e\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x75\x73\x31\x18\x30\x16\x06\x03\x55\x04\x0a\x13\x0f\x55\x2e\x53\x2e\x20\x47\x6f\x76\x65\x72\x6e\x6d\x65\x6e\x74\x31\x0d\x30\x0b\x06\x03\x55\x04\x0b\x13\x04\x46\x42\x43\x41\x31\x16\x30\x14\x06\x03\x55\x04\x03\x13\x0d\x43\x6f\x6d\x6d\x6f\x6e\x20\x50\x6f\x6c\x69\x63\x79\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\x97\x8d\xbd\x33\x27\xe4\xad\x5b\xfb\x78\xbd\x2f\x47\x47\x6e\xc7\x78\xe9\x93\x9c\xa4\xde\xc9\x1c\xfd\x2f\x1b\x39\x38\xac\x47\x17\xc0\x7e\x77\x29\x00\x3b\x03\x1f\x68\x0f\xcd\x4d\xa5\xee\x77\xb8\x2c\x62\x6b\x31\xf6\xfa\x72\x09\x7d\x30\x29\x06\x7c\xe7\x7c\xa3\x3d\x84\x18\x8a\x1d\xae\x2c\x92\xa8\x1f\xe8\x5e\x4f\x8d\x8e\xeb\x3f\x1a\xf8\x9c\x0a\x67\x9d\xb0\x67\x4d\xf0\x2e\xd0\x30\xde\xc3\x94\xb0\xa0\xcf\x2e\x0a\x34\x7f\x54\x09\xd3\x36\xbd\xa4\x49\x57\x52\x73\xe9\x9d\xfe\xe4\x48\x79\x46\x1b\x5b\x8d\x32\xe4\xa5\x48\x64\xf3\x22\x0d\x92\x9d\x08\x15\xbf\x60\x3c\x83\xf7\x47\x22\x25\x22\xad\x29\x71\xb7\x77\xef\x17\xc9\xa2\xb6\x94\x5e\xc8\x30\x90\xa4\x14\x48\x5c\x56\x57\x0b\x41\x4c\x05\xd4\x2a\x4c\x3f\xae\x12\x9b\x59\x11\x75\x70\x07\x22\x69\x2d\x2c\xd3\x31\xcc\x92\x7e\xcc\xcd\xa4\x7e\x94\x47\xaa\x9c\x09\x08\xf6\x4b\xaf\x52\xe8\x6a\x40\x91\xc5\x55\xbd\x40\xb1\xc8\x6d\x57\x86\x95\x17\xe6\x1f\x73\xbe\x47\x2e\x3e\x8b\x4c\x17\xb9\xb9\x25\x1c\xa5\x52\x17\x36\x08\x59\xc0\x42\xbe\x0a\x2b\xb4\x56\x51\x3c\x1b\x55\xc9\x8c\x90\x77\xeb\x02\x03\x01\x00\x01\xa3\x7b\x30\x79\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x2f\x58\x97\xd8\xa9\x05\x98\xa5\x56\x1f\xfb\xd9\xab\x75\xef\x02\x3c\x36\x34\xc7\x30\x12\x06\x09\x2b\x06\x01\x04\x01\x82\x37\x15\x01\x04\x05\x02\x03\x01\x00\x01\x30\x23\x06\x09\x2b\x06\x01\x04\x01\x82\x37\x15\x02\x04\x16\x04\x14\x76\xb7\x60\x96\xdd\x14\x56\x29\xac\x75\x85\xd3\x70\x63\xc1\xbc\x47\x86\x1c\x8b\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x60\xae\xf3\x48\x16\x40\x72\xa6\x08\x88\xc9\xbc\x47\x2c\x24\x4b\x5d\xa0\x91\x73\xed\x65\x78\x90\xf0\x67\x90\x7a\xa5\xbf\x0a\xad\xb6\x2a\xf9\x99\x67\xdf\x83\xc5\x77\x1f\x34\x09\x38\xf9\x7e\x9e\x41\xe0\x48\x60\xfe\xe2\xaa\x5d\x87\x88\xea\x88\xfd\x5c\x45\xb2\xc9\x6a\xda\x7d\xa4\xad\xb1\x4f\xbf\x1c\x0d\x9f\x1e\x9a\xc0\xd5\x14\x73\x38\x2b\x8a\x78\x40\x6e\x30\xf7\x62\xe1\xcd\x99\xfc\x51\x69\x67\x6c\x11\xdd\xb8\x10\xa3\x68\xde\x26\xa5\x56\xfd\x36\x6c\x37\x98\x6c\xfb\xee\x7c\x3c\x6c\x6b\x70\x3f\xf7\x48\x37\x09\x8f\x0b\x42\x81\xad\x46\x46\xb8\x0b\x83\x06\xf4\x1b\x38\xa0\x7f\x4f\xcd\x0b\xef\x83\x89\x87\x97\x1c\x8a\x30\x67\xdc\xfd\x54\xa1\x03\x7e\x01\xcb\x85\x4c\xb1\x0b\x29\xc3\xbe\xec\x7c\xe1\x3f\x0f\x09\x52\x3c\x2f\xa7\x9a\x48\xfe\x37\xe9\x11\x06\x58\xe1\x36\x41\x8a\xc4\xb6\xbf\x8e\xdd\xce\x4a\xb3\xbc\x1a\xc0\xcd\xfa\x1a\x99\xd2\x71\x9b\xfa\xcf\xbc\xf2\xc4\x54\xa3\x88\x35\x76\xcc\x1b\x2c\x46\x6f\x0c\xb4\xd1\xc3\x61\x76\x92\x74\x11\xea\x4b\x80\x8d\x1c\x89\x11\x8b\xec\x5b\xff\x17\xc9\x48\xfc\xe7\xe0\x06\x11\xe2\x84\x5e", 0 }, + /* Anchor: 71 FederalCommonPolicyCA.cer serial: #{a.serial.to_s} + C=US,O=U.S. Government,OU=FPKI,CN=Federal Common Policy CA + */ + { 1124, "\x30\x82\x04\x60\x30\x82\x03\x48\xa0\x03\x02\x01\x02\x02\x02\x01\x30\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x30\x59\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x18\x30\x16\x06\x03\x55\x04\x0a\x13\x0f\x55\x2e\x53\x2e\x20\x47\x6f\x76\x65\x72\x6e\x6d\x65\x6e\x74\x31\x0d\x30\x0b\x06\x03\x55\x04\x0b\x13\x04\x46\x50\x4b\x49\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x46\x65\x64\x65\x72\x61\x6c\x20\x43\x6f\x6d\x6d\x6f\x6e\x20\x50\x6f\x6c\x69\x63\x79\x20\x43\x41\x30\x1e\x17\x0d\x31\x30\x31\x32\x30\x31\x31\x36\x34\x35\x32\x37\x5a\x17\x0d\x33\x30\x31\x32\x30\x31\x31\x36\x34\x35\x32\x37\x5a\x30\x59\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x18\x30\x16\x06\x03\x55\x04\x0a\x13\x0f\x55\x2e\x53\x2e\x20\x47\x6f\x76\x65\x72\x6e\x6d\x65\x6e\x74\x31\x0d\x30\x0b\x06\x03\x55\x04\x0b\x13\x04\x46\x50\x4b\x49\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x46\x65\x64\x65\x72\x61\x6c\x20\x43\x6f\x6d\x6d\x6f\x6e\x20\x50\x6f\x6c\x69\x63\x79\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xd8\x75\xfb\x35\x16\x34\x5a\x41\xbf\x5a\xaf\x5c\x30\x04\x14\x1c\xad\x78\x44\xb5\xea\x26\xea\x75\x61\xc7\xcd\x36\x79\xf8\x7c\xd8\xbd\x29\x51\x66\x59\x21\xe3\x79\xab\xd4\x78\xbe\xb0\x2d\xb0\xa1\xd5\xb2\x35\x16\x23\xd0\xcc\x1e\xbe\x0e\xe8\xab\xdc\xc3\xc9\xd6\x12\xd7\xa7\x72\x68\x18\x31\xb8\x17\x22\xb2\x3e\x7e\xba\x08\x6d\xc6\xfd\xd1\x58\x2c\x69\xa0\x03\xf0\x2a\xa3\xf6\x3f\x21\x25\x3d\xdf\xb7\x32\xc5\x8e\x27\xb3\x23\xa5\xe0\x52\xb3\x5d\x96\xe9\xb0\xb8\xc5\xc5\x9f\xbb\xc5\xa0\x6e\x82\x40\xbb\xc5\x27\x05\x36\x49\xd6\x26\x27\x69\x0c\x34\x8f\xcf\x27\x7a\x2a\x0a\xa3\x41\x5f\x8d\x1d\x03\x86\x83\x15\xe0\x55\xc1\xc5\x98\x2c\x9e\xec\x1a\x72\xdc\x48\xc1\x3e\xf9\x84\xd2\x84\x82\xc1\x1b\xc3\x74\x36\xb7\xb9\xc7\x36\x32\x7a\xf8\x32\xb6\xd0\x36\xae\x22\x18\x31\x8c\x50\x73\x21\x9e\xfe\x83\x3b\x30\x88\x24\xe3\xe9\xc1\x7e\xde\xed\x98\xc7\x1f\x92\x10\x8a\x9f\x5b\x62\x2f\x9d\xa4\xbc\xd5\x85\x6f\x3a\xfd\xc9\x53\xa7\x20\x4b\xaa\xdb\x20\xab\x21\x4e\x1d\x0d\x4e\xe6\x98\x85\xe5\xab\x11\x47\x5d\x9d\x3f\xc4\x23\xc0\xe3\x14\x06\x6e\xfe\x9d\x02\x03\x01\x00\x01\xa3\x82\x01\x30\x30\x82\x01\x2c\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x81\xe9\x06\x08\x2b\x06\x01\x05\x05\x07\x01\x0b\x04\x81\xdc\x30\x81\xd9\x30\x3f\x06\x08\x2b\x06\x01\x05\x05\x07\x30\x05\x86\x33\x68\x74\x74\x70\x3a\x2f\x2f\x68\x74\x74\x70\x2e\x66\x70\x6b\x69\x2e\x67\x6f\x76\x2f\x66\x63\x70\x63\x61\x2f\x63\x61\x43\x65\x72\x74\x73\x49\x73\x73\x75\x65\x64\x42\x79\x66\x63\x70\x63\x61\x2e\x70\x37\x63\x30\x81\x95\x06\x08\x2b\x06\x01\x05\x05\x07\x30\x05\x86\x81\x88\x6c\x64\x61\x70\x3a\x2f\x2f\x6c\x64\x61\x70\x2e\x66\x70\x6b\x69\x2e\x67\x6f\x76\x2f\x63\x6e\x3d\x46\x65\x64\x65\x72\x61\x6c\x25\x32\x30\x43\x6f\x6d\x6d\x6f\x6e\x25\x32\x30\x50\x6f\x6c\x69\x63\x79\x25\x32\x30\x43\x41\x2c\x6f\x75\x3d\x46\x50\x4b\x49\x2c\x6f\x3d\x55\x2e\x53\x2e\x25\x32\x30\x47\x6f\x76\x65\x72\x6e\x6d\x65\x6e\x74\x2c\x63\x3d\x55\x53\x3f\x63\x41\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x3b\x62\x69\x6e\x61\x72\x79\x2c\x63\x72\x6f\x73\x73\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x50\x61\x69\x72\x3b\x62\x69\x6e\x61\x72\x79\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xad\x0c\x7a\x75\x5c\xe5\xf3\x98\xc4\x79\x98\x0e\xac\x28\xfd\x97\xf4\xe7\x02\xfc\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x03\x82\x01\x01\x00\x8f\x73\xda\xe1\x7f\x80\xb1\x87\xf6\xec\x2c\xcf\xd1\x84\x63\x1e\xf6\xf1\x88\xb7\x9a\xf2\x11\xb5\xef\x54\xad\x8a\x6e\x18\x37\x28\xef\x5c\x1b\xe4\xef\x50\xb7\x6c\x26\x18\x23\x22\x4d\x1d\x26\x47\x20\xe9\x09\x9c\xe2\x70\x62\x71\xab\x11\xcf\x91\x89\xe8\xb3\xf5\x2a\xa0\x47\xc0\x14\xcb\x4e\x42\xc1\xdd\x0c\x0e\x1b\xf0\x87\x5b\xec\xe5\x77\xd7\xaa\xe0\x54\xd7\x45\xf4\x85\x3e\xec\xb4\x1d\xde\x7c\x8a\x7f\x5b\x4d\x9c\x96\x8a\xd0\xa2\x32\x9f\xda\x6c\x31\x0c\xf8\xa4\xef\x7e\x73\xe8\x91\xdc\x08\x7a\x70\x5a\xa0\xaf\x62\x81\x59\xf8\x00\x74\xa2\xc8\xdd\x54\xca\x41\x56\x47\xbd\xe9\xc0\x4f\xed\x20\xdd\xe3\xa5\x09\xdf\xae\x28\xc2\xfc\xd1\xc8\x17\xd8\x12\xc7\x6f\xde\x2e\xe9\xbd\x9a\x91\xf2\x3c\x5a\x94\x2e\x91\x22\x80\x89\xa1\x8c\x58\xcc\x83\x7a\x26\x19\x75\x02\xa5\x0e\x7d\x0a\x26\x73\x51\xea\x86\xcb\x07\xa8\xc8\xfd\x63\x5a\x35\x9b\xd2\xaf\xbf\x4f\x31\x48\xc1\x84\x70\xdb\x35\x7b\x9a\x19\x0f\xe5\x8f\xf4\x6a\x0c\x6f\x33\xd9\xeb\x1c\x70\xa2\x0d\xe3\xb9\x50\x03\x61\x02\xff\x4a\xec\x92\xa4\xdc\x2d\xee\x2a\x34\x93\x07\xb7\x2c\xe7\x18\x8f", 0 }, + /* Anchor: 72 Firmaprofesional_CIF_A62634068.cer serial: #{a.serial.to_s} + C=ES,CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 + */ + { 1560, "\x30\x82\x06\x14\x30\x82\x03\xfc\xa0\x03\x02\x01\x02\x02\x08\x53\xec\x3b\xee\xfb\xb2\x48\x5f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x51\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x42\x30\x40\x06\x03\x55\x04\x03\x0c\x39\x41\x75\x74\x6f\x72\x69\x64\x61\x64\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\x6f\x6e\x20\x46\x69\x72\x6d\x61\x70\x72\x6f\x66\x65\x73\x69\x6f\x6e\x61\x6c\x20\x43\x49\x46\x20\x41\x36\x32\x36\x33\x34\x30\x36\x38\x30\x1e\x17\x0d\x30\x39\x30\x35\x32\x30\x30\x38\x33\x38\x31\x35\x5a\x17\x0d\x33\x30\x31\x32\x33\x31\x30\x38\x33\x38\x31\x35\x5a\x30\x51\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x42\x30\x40\x06\x03\x55\x04\x03\x0c\x39\x41\x75\x74\x6f\x72\x69\x64\x61\x64\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\x6f\x6e\x20\x46\x69\x72\x6d\x61\x70\x72\x6f\x66\x65\x73\x69\x6f\x6e\x61\x6c\x20\x43\x49\x46\x20\x41\x36\x32\x36\x33\x34\x30\x36\x38\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\xca\x96\x6b\x8e\xea\xf8\xfb\xf1\xa2\x35\xe0\x7f\x4c\xda\xe0\xc3\x52\xd7\x7d\xb6\x10\xc8\x02\x5e\xb3\x43\x2a\xc4\x4f\x6a\xb2\xca\x1c\x5d\x28\x9a\x78\x11\x1a\x69\x59\x57\xaf\xb5\x20\x42\xe4\x8b\x0f\xe6\xdf\x5b\xa6\x03\x92\x2f\xf5\x11\xe4\x62\xd7\x32\x71\x38\xd9\x04\x0c\x71\xab\x3d\x51\x7e\x0f\x07\xdf\x63\x05\x5c\xe9\xbf\x94\x6f\xc1\x29\x82\xc0\xb4\xda\x51\xb0\xc1\x3c\xbb\xad\x37\x4a\x5c\xca\xf1\x4b\x36\x0e\x24\xab\xbf\xc3\x84\x77\xfd\xa8\x50\xf4\xb1\xe7\xc6\x2f\xd2\x2d\x59\x8d\x7a\x0a\x4e\x96\x69\x52\x02\xaa\x36\x98\xec\xfc\xfa\x14\x83\x0c\x37\x1f\xc9\x92\x37\x7f\xd7\x81\x2d\xe5\xc4\xb9\xe0\x3e\x34\xfe\x67\xf4\x3e\x66\xd1\xd3\xf4\x40\xcf\x5e\x62\x34\x0f\x70\x06\x3e\x20\x18\x5a\xce\xf7\x72\x1b\x25\x6c\x93\x74\x14\x93\xa3\x73\xb1\x0e\xaa\x87\x10\x23\x59\x5f\x20\x05\x19\x47\xed\x68\x8e\x92\x12\xca\x5d\xfc\xd6\x2b\xb2\x92\x3c\x20\xcf\xe1\x5f\xaf\x20\xbe\xa0\x76\x7f\x76\xe5\xec\x1a\x86\x61\x33\x3e\xe7\x7b\xb4\x3f\xa0\x0f\x8e\xa2\xb9\x6a\x6f\xb9\x87\x26\x6f\x41\x6c\x88\xa6\x50\xfd\x6a\x63\x0b\xf5\x93\x16\x1b\x19\x8f\xb2\xed\x9b\x9b\xc9\x90\xf5\x01\x0c\xdf\x19\x3d\x0f\x3e\x38\x23\xc9\x2f\x8f\x0c\xd1\x02\xfe\x1b\x55\xd6\x4e\xd0\x8d\x3c\xaf\x4f\xa4\xf3\xfe\xaf\x2a\xd3\x05\x9d\x79\x08\xa1\xcb\x57\x31\xb4\x9c\xc8\x90\xb2\x67\xf4\x18\x16\x93\x3a\xfc\x47\xd8\xd1\x78\x96\x31\x1f\xba\x2b\x0c\x5f\x5d\x99\xad\x63\x89\x5a\x24\x20\x76\xd8\xdf\xfd\xab\x4e\xa6\x22\xaa\x9d\x5e\xe6\x27\x8a\x7d\x68\x29\xa3\xe7\x8a\xb8\xda\x11\xbb\x17\x2d\x99\x9d\x13\x24\x46\xf7\xc5\xe2\xd8\x9f\x8e\x7f\xc7\x8f\x74\x6d\x5a\xb2\xe8\x72\xf5\xac\xee\x24\x10\xad\x2f\x14\xda\xff\x2d\x9a\x46\x71\x47\xbe\x42\xdf\xbb\x01\xdb\xf4\x7f\xd3\x28\x8f\x31\x59\x5b\xd3\xc9\x02\xa6\xb4\x52\xca\x6e\x97\xfb\x43\xc5\x08\x26\x6f\x8a\xf4\xbb\xfd\x9f\x28\xaa\x0d\xd5\x45\xf3\x13\x3a\x1d\xd8\xc0\x78\x8f\x41\x67\x3c\x1e\x94\x64\xae\x7b\x0b\xc5\xe8\xd9\x01\x88\x39\x1a\x97\x86\x64\x41\xd5\x3b\x87\x0c\x6e\xfa\x0f\xc6\xbd\x48\x14\xbf\x39\x4d\xd4\x9e\x41\xb6\x8f\x96\x1d\x63\x96\x93\xd9\x95\x06\x78\x31\x68\x9e\x37\x06\x3b\x80\x89\x45\x61\x39\x23\xc7\x1b\x44\xa3\x15\xe5\x1c\xf8\x92\x30\xbb\x02\x03\x01\x00\x01\xa3\x81\xef\x30\x81\xec\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01\x01\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x65\xcd\xeb\xab\x35\x1e\x00\x3e\x7e\xd5\x74\xc0\x1c\xb4\x73\x47\x0e\x1a\x64\x2f\x30\x81\xa6\x06\x03\x55\x1d\x20\x04\x81\x9e\x30\x81\x9b\x30\x81\x98\x06\x04\x55\x1d\x20\x00\x30\x81\x8f\x30\x2f\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x23\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x66\x69\x72\x6d\x61\x70\x72\x6f\x66\x65\x73\x69\x6f\x6e\x61\x6c\x2e\x63\x6f\x6d\x2f\x63\x70\x73\x30\x5c\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x02\x30\x50\x1e\x4e\x00\x50\x00\x61\x00\x73\x00\x65\x00\x6f\x00\x20\x00\x64\x00\x65\x00\x20\x00\x6c\x00\x61\x00\x20\x00\x42\x00\x6f\x00\x6e\x00\x61\x00\x6e\x00\x6f\x00\x76\x00\x61\x00\x20\x00\x34\x00\x37\x00\x20\x00\x42\x00\x61\x00\x72\x00\x63\x00\x65\x00\x6c\x00\x6f\x00\x6e\x00\x61\x00\x20\x00\x30\x00\x38\x00\x30\x00\x31\x00\x37\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x17\x7d\xa0\xf9\xb4\xdd\xc5\xc5\xeb\xad\x4b\x24\xb5\xa1\x02\xab\xdd\xa5\x88\x4a\xb2\x0f\x55\x4b\x2b\x57\x8c\x3b\xe5\x31\xdd\xfe\xc4\x32\xf1\xe7\x5b\x64\x96\x36\x32\x18\xec\xa5\x32\x77\xd7\xe3\x44\xb6\xc0\x11\x2a\x80\xb9\x3d\x6a\x6e\x7c\x9b\xd3\xad\xfc\xc3\xd6\xa3\xe6\x64\x29\x7c\xd1\xe1\x38\x1e\x82\x2b\xff\x27\x65\xaf\xfb\x16\x15\xc4\x2e\x71\x84\xe5\xb5\xff\xfa\xa4\x47\xbd\x64\x32\xbb\xf6\x25\x84\xa2\x27\x42\xf5\x20\xb0\xc2\x13\x10\x11\xcd\x10\x15\xba\x42\x90\x2a\xd2\x44\xe1\x96\x26\xeb\x31\x48\x12\xfd\x2a\xda\xc9\x06\xcf\x74\x1e\xa9\x4b\xd5\x87\x28\xf9\x79\x34\x92\x3e\x2e\x44\xe8\xf6\x8f\x4f\x8f\x35\x3f\x25\xb3\x39\xdc\x63\x2a\x90\x6b\x20\x5f\xc4\x52\x12\x4e\x97\x2c\x2a\xac\x9d\x97\xde\x48\xf2\xa3\x66\xdb\xc2\xd2\x83\x95\xa6\x66\xa7\x9e\x25\x0f\xe9\x0b\x33\x91\x65\x0a\x5a\xc3\xd9\x54\x12\xdd\xaf\xc3\x4e\x0e\x1f\x26\x5e\x0d\xdc\xb3\x8d\xec\xd5\x81\x70\xde\xd2\x4f\x24\x05\xf3\x6c\x4e\xf5\x4c\x49\x66\x8d\xd1\xff\xd2\x0b\x25\x41\x48\xfe\x51\x84\xc6\x42\xaf\x80\x04\xcf\xd0\x7e\x64\x49\xe4\xf2\xdf\xa2\xec\xb1\x4c\xc0\x2a\x1d\xe7\xb4\xb1\x65\xa2\xc4\xbc\xf1\x98\xf4\xaa\x70\x07\x63\xb4\xb8\xda\x3b\x4c\xfa\x40\x22\x30\x5b\x11\xa6\xf0\x05\x0e\xc6\x02\x03\x48\xab\x86\x9b\x85\xdd\xdb\xdd\xea\xa2\x76\x80\x73\x7d\xf5\x9c\x04\xc4\x45\x8d\xe7\xb9\x1c\x8b\x9e\xea\xd7\x75\xd1\x72\xb1\xde\x75\x44\xe7\x42\x7d\xe2\x57\x6b\x7d\xdc\x99\xbc\x3d\x83\x28\xea\x80\x93\x8d\xc5\x4c\x65\xc1\x70\x81\xb8\x38\xfc\x43\x31\xb2\xf6\x03\x34\x47\xb2\xac\xfb\x22\x06\xcb\x1e\xdd\x17\x47\x1c\x5f\x66\xb9\xd3\x1a\xa2\xda\x11\xb1\xa4\xbc\x23\xc9\xe4\xbe\x87\xff\xb9\x94\xb6\xf8\x5d\x20\x4a\xd4\x5f\xe7\xbd\x68\x7b\x65\xf2\x15\x1e\xd2\x3a\xa9\x2d\xe9\xd8\x6b\x24\xac\x97\x58\x44\x47\xad\x59\x18\xf1\x21\x65\x70\xde\xce\x34\x60\xa8\x40\xf1\xf3\x3c\xa4\xc3\x28\x23\x8c\xfe\x27\x33\x43\x40\xa0\x17\x3c\xeb\xea\x3b\xb0\x72\xa6\xa3\xb9\x4a\x4b\x5e\x16\x48\xf4\xb2\xbc\xc8\x8c\x92\xc5\x9d\x9f\xac\x72\x36\xbc\x34\x80\x34\x6b\xa9\x8b\x92\xc0\xb8\x17\xed\xec\x76\x53\xf5\x24\x01\x8c\xb3\x22\xe8\x4b\x7c\x55\xc6\x9d\xfa\xa3\x14\xbb\x65\x85\x6e\x6e\x4f\x12\x7e\x0a\x3c\x9d\x95", 0 }, + /* Anchor: 73 fnmtclass2.cer serial: #{a.serial.to_s} + C=ES,O=FNMT,OU=FNMT Clase 2 CA + */ + { 765, "\x30\x82\x02\xf9\x30\x82\x02\x62\xa0\x03\x02\x01\x02\x02\x04\x36\xf1\x1b\x19\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x36\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x0d\x30\x0b\x06\x03\x55\x04\x0a\x13\x04\x46\x4e\x4d\x54\x31\x18\x30\x16\x06\x03\x55\x04\x0b\x13\x0f\x46\x4e\x4d\x54\x20\x43\x6c\x61\x73\x65\x20\x32\x20\x43\x41\x30\x1e\x17\x0d\x39\x39\x30\x33\x31\x38\x31\x34\x35\x36\x31\x39\x5a\x17\x0d\x31\x39\x30\x33\x31\x38\x31\x35\x32\x36\x31\x39\x5a\x30\x36\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x0d\x30\x0b\x06\x03\x55\x04\x0a\x13\x04\x46\x4e\x4d\x54\x31\x18\x30\x16\x06\x03\x55\x04\x0b\x13\x0f\x46\x4e\x4d\x54\x20\x43\x6c\x61\x73\x65\x20\x32\x20\x43\x41\x30\x81\x9d\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8b\x00\x30\x81\x87\x02\x81\x81\x00\x98\x3f\xad\x19\x36\x93\x3d\x3e\xfe\x76\x42\x14\xfd\x35\x6f\xf1\xfa\xad\x22\x7a\x58\xe3\x46\xd0\x5d\xc6\x5a\xf9\x62\x2d\x8f\x31\x5e\xfe\xb4\x30\xfe\x50\x74\xac\xd6\x9d\x1d\xe0\x62\xc6\x49\xdd\x14\x12\x7d\x71\x0b\xac\x06\xc1\x3f\xd7\x06\x87\xe0\x90\x89\xd6\xe5\xe3\x03\xb2\xf2\x27\xb1\x9f\x33\xc8\xaa\x6b\x36\x4a\xa3\xc4\x3f\x79\x41\x9d\x89\x46\x2f\x2b\x3e\x63\xd4\x38\x56\x91\xaa\x1d\xb1\x0d\x42\x75\x4d\xf3\x87\x4e\xe3\x0f\x4d\xcc\xb4\x6c\xbf\x62\x13\x87\xea\xd0\x9b\x8e\xb6\xe2\xff\x19\xf4\x94\x09\xd5\x96\x61\x02\x01\x03\xa3\x82\x01\x14\x30\x82\x01\x10\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x58\x06\x03\x55\x1d\x1f\x04\x51\x30\x4f\x30\x4d\xa0\x4b\xa0\x49\xa4\x47\x30\x45\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x0d\x30\x0b\x06\x03\x55\x04\x0a\x13\x04\x46\x4e\x4d\x54\x31\x18\x30\x16\x06\x03\x55\x04\x0b\x13\x0f\x46\x4e\x4d\x54\x20\x43\x6c\x61\x73\x65\x20\x32\x20\x43\x41\x31\x0d\x30\x0b\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4c\x31\x30\x2b\x06\x03\x55\x1d\x10\x04\x24\x30\x22\x80\x0f\x31\x39\x39\x39\x30\x33\x31\x38\x31\x34\x35\x36\x31\x39\x5a\x81\x0f\x32\x30\x31\x39\x30\x33\x31\x38\x31\x34\x35\x36\x31\x39\x5a\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x06\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x40\x9a\x76\x44\x97\x74\x07\xc4\xac\x14\xcb\x1e\x8d\x4f\x3a\x45\x7c\x30\xd7\x61\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x40\x9a\x76\x44\x97\x74\x07\xc4\xac\x14\xcb\x1e\x8d\x4f\x3a\x45\x7c\x30\xd7\x61\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x19\x06\x09\x2a\x86\x48\x86\xf6\x7d\x07\x41\x00\x04\x0c\x30\x0a\x1b\x04\x56\x34\x2e\x30\x03\x02\x04\x90\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x61\x4c\xa0\x7c\x59\x63\x5b\x66\xf8\xee\x65\x13\xce\x43\x80\x47\xb9\xb2\x35\xc9\xc8\x84\xc7\x6b\x73\x60\x45\xe4\x9d\x37\x9d\xf5\x8e\x25\xb9\xf9\xaa\xaa\xca\xe3\xf8\x43\x9c\x2f\xa0\x89\x05\xb1\x45\x32\x94\x2a\x1e\x03\x8d\x5d\xa6\xde\xcf\x57\x95\xda\xdf\x26\x60\x5f\xcb\xdf\x95\x1e\xb8\xce\x08\xd8\xf8\x8a\xc9\x4f\xa9\x68\x75\x93\xe3\x2f\x05\x4c\x64\x60\x02\xa2\x42\x1e\x6f\x86\x68\x65\x55\x0e\xd8\x43\x6f\xf2\x91\x31\x3e\xa3\x47\x3c\x28\x05\xaf\x45\xb6\x9d\x22\x4c\x26\x7b\x4b\x7d\x5b\x15\xf9\x19\x46\xdf\x08\x5d", 0 }, + /* Anchor: 74 GD-Class2-root.crt serial: #{a.serial.to_s} + C=US,O=The Go Daddy Group\, Inc.,OU=Go Daddy Class 2 Certification Authority + */ + { 1028, "\x30\x82\x04\x00\x30\x82\x02\xe8\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x63\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x21\x30\x1f\x06\x03\x55\x04\x0a\x13\x18\x54\x68\x65\x20\x47\x6f\x20\x44\x61\x64\x64\x79\x20\x47\x72\x6f\x75\x70\x2c\x20\x49\x6e\x63\x2e\x31\x31\x30\x2f\x06\x03\x55\x04\x0b\x13\x28\x47\x6f\x20\x44\x61\x64\x64\x79\x20\x43\x6c\x61\x73\x73\x20\x32\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x30\x34\x30\x36\x32\x39\x31\x37\x30\x36\x32\x30\x5a\x17\x0d\x33\x34\x30\x36\x32\x39\x31\x37\x30\x36\x32\x30\x5a\x30\x63\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x21\x30\x1f\x06\x03\x55\x04\x0a\x13\x18\x54\x68\x65\x20\x47\x6f\x20\x44\x61\x64\x64\x79\x20\x47\x72\x6f\x75\x70\x2c\x20\x49\x6e\x63\x2e\x31\x31\x30\x2f\x06\x03\x55\x04\x0b\x13\x28\x47\x6f\x20\x44\x61\x64\x64\x79\x20\x43\x6c\x61\x73\x73\x20\x32\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x82\x01\x20\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0d\x00\x30\x82\x01\x08\x02\x82\x01\x01\x00\xde\x9d\xd7\xea\x57\x18\x49\xa1\x5b\xeb\xd7\x5f\x48\x86\xea\xbe\xdd\xff\xe4\xef\x67\x1c\xf4\x65\x68\xb3\x57\x71\xa0\x5e\x77\xbb\xed\x9b\x49\xe9\x70\x80\x3d\x56\x18\x63\x08\x6f\xda\xf2\xcc\xd0\x3f\x7f\x02\x54\x22\x54\x10\xd8\xb2\x81\xd4\xc0\x75\x3d\x4b\x7f\xc7\x77\xc3\x3e\x78\xab\x1a\x03\xb5\x20\x6b\x2f\x6a\x2b\xb1\xc5\x88\x7e\xc4\xbb\x1e\xb0\xc1\xd8\x45\x27\x6f\xaa\x37\x58\xf7\x87\x26\xd7\xd8\x2d\xf6\xa9\x17\xb7\x1f\x72\x36\x4e\xa6\x17\x3f\x65\x98\x92\xdb\x2a\x6e\x5d\xa2\xfe\x88\xe0\x0b\xde\x7f\xe5\x8d\x15\xe1\xeb\xcb\x3a\xd5\xe2\x12\xa2\x13\x2d\xd8\x8e\xaf\x5f\x12\x3d\xa0\x08\x05\x08\xb6\x5c\xa5\x65\x38\x04\x45\x99\x1e\xa3\x60\x60\x74\xc5\x41\xa5\x72\x62\x1b\x62\xc5\x1f\x6f\x5f\x1a\x42\xbe\x02\x51\x65\xa8\xae\x23\x18\x6a\xfc\x78\x03\xa9\x4d\x7f\x80\xc3\xfa\xab\x5a\xfc\xa1\x40\xa4\xca\x19\x16\xfe\xb2\xc8\xef\x5e\x73\x0d\xee\x77\xbd\x9a\xf6\x79\x98\xbc\xb1\x07\x67\xa2\x15\x0d\xdd\xa0\x58\xc6\x44\x7b\x0a\x3e\x62\x28\x5f\xba\x41\x07\x53\x58\xcf\x11\x7e\x38\x74\xc5\xf8\xff\xb5\x69\x90\x8f\x84\x74\xea\x97\x1b\xaf\x02\x01\x03\xa3\x81\xc0\x30\x81\xbd\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xd2\xc4\xb0\xd2\x91\xd4\x4c\x11\x71\xb3\x61\xcb\x3d\xa1\xfe\xdd\xa8\x6a\xd4\xe3\x30\x81\x8d\x06\x03\x55\x1d\x23\x04\x81\x85\x30\x81\x82\x80\x14\xd2\xc4\xb0\xd2\x91\xd4\x4c\x11\x71\xb3\x61\xcb\x3d\xa1\xfe\xdd\xa8\x6a\xd4\xe3\xa1\x67\xa4\x65\x30\x63\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x21\x30\x1f\x06\x03\x55\x04\x0a\x13\x18\x54\x68\x65\x20\x47\x6f\x20\x44\x61\x64\x64\x79\x20\x47\x72\x6f\x75\x70\x2c\x20\x49\x6e\x63\x2e\x31\x31\x30\x2f\x06\x03\x55\x04\x0b\x13\x28\x47\x6f\x20\x44\x61\x64\x64\x79\x20\x43\x6c\x61\x73\x73\x20\x32\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x82\x01\x00\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x32\x4b\xf3\xb2\xca\x3e\x91\xfc\x12\xc6\xa1\x07\x8c\x8e\x77\xa0\x33\x06\x14\x5c\x90\x1e\x18\xf7\x08\xa6\x3d\x0a\x19\xf9\x87\x80\x11\x6e\x69\xe4\x96\x17\x30\xff\x34\x91\x63\x72\x38\xee\xcc\x1c\x01\xa3\x1d\x94\x28\xa4\x31\xf6\x7a\xc4\x54\xd7\xf6\xe5\x31\x58\x03\xa2\xcc\xce\x62\xdb\x94\x45\x73\xb5\xbf\x45\xc9\x24\xb5\xd5\x82\x02\xad\x23\x79\x69\x8d\xb8\xb6\x4d\xce\xcf\x4c\xca\x33\x23\xe8\x1c\x88\xaa\x9d\x8b\x41\x6e\x16\xc9\x20\xe5\x89\x9e\xcd\x3b\xda\x70\xf7\x7e\x99\x26\x20\x14\x54\x25\xab\x6e\x73\x85\xe6\x9b\x21\x9d\x0a\x6c\x82\x0e\xa8\xf8\xc2\x0c\xfa\x10\x1e\x6c\x96\xef\x87\x0d\xc4\x0f\x61\x8b\xad\xee\x83\x2b\x95\xf8\x8e\x92\x84\x72\x39\xeb\x20\xea\x83\xed\x83\xcd\x97\x6e\x08\xbc\xeb\x4e\x26\xb6\x73\x2b\xe4\xd3\xf6\x4c\xfe\x26\x71\xe2\x61\x11\x74\x4a\xff\x57\x1a\x87\x0f\x75\x48\x2e\xcf\x51\x69\x17\xa0\x02\x12\x61\x95\xd5\xd1\x40\xb2\x10\x4c\xee\xc4\xac\x10\x43\xa6\xa5\x9e\x0a\xd5\x95\x62\x9a\x0d\xcf\x88\x82\xc5\x32\x0c\xe4\x2b\x9f\x45\xe6\x0d\x9f\x28\x9c\xb1\xb9\x2a\x5a\x57\xad\x37\x0f\xaf\x1d\x7f\xdb\xbd\x9f", 0 }, + /* Anchor: 75 geotrust-primary-ca.crt serial: #{a.serial.to_s} + C=US,O=GeoTrust Inc.,CN=GeoTrust Primary Certification Authority + */ + { 896, "\x30\x82\x03\x7c\x30\x82\x02\x64\xa0\x03\x02\x01\x02\x02\x10\x18\xac\xb5\x6a\xfd\x69\xb6\x15\x3a\x63\x6c\xaf\xda\xfa\xc4\xa1\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x58\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0a\x13\x0d\x47\x65\x6f\x54\x72\x75\x73\x74\x20\x49\x6e\x63\x2e\x31\x31\x30\x2f\x06\x03\x55\x04\x03\x13\x28\x47\x65\x6f\x54\x72\x75\x73\x74\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x30\x36\x31\x31\x32\x37\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x33\x36\x30\x37\x31\x36\x32\x33\x35\x39\x35\x39\x5a\x30\x58\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0a\x13\x0d\x47\x65\x6f\x54\x72\x75\x73\x74\x20\x49\x6e\x63\x2e\x31\x31\x30\x2f\x06\x03\x55\x04\x03\x13\x28\x47\x65\x6f\x54\x72\x75\x73\x74\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xbe\xb8\x15\x7b\xff\xd4\x7c\x7d\x67\xad\x83\x64\x7b\xc8\x42\x53\x2d\xdf\xf6\x84\x08\x20\x61\xd6\x01\x59\x6a\x9c\x44\x11\xaf\xef\x76\xfd\x95\x7e\xce\x61\x30\xbb\x7a\x83\x5f\x02\xbd\x01\x66\xca\xee\x15\x8d\x6f\xa1\x30\x9c\xbd\xa1\x85\x9e\x94\x3a\xf3\x56\x88\x00\x31\xcf\xd8\xee\x6a\x96\x02\xd9\xed\x03\x8c\xfb\x75\x6d\xe7\xea\xb8\x55\x16\x05\x16\x9a\xf4\xe0\x5e\xb1\x88\xc0\x64\x85\x5c\x15\x4d\x88\xc7\xb7\xba\xe0\x75\xe9\xad\x05\x3d\x9d\xc7\x89\x48\xe0\xbb\x28\xc8\x03\xe1\x30\x93\x64\x5e\x52\xc0\x59\x70\x22\x35\x57\x88\x8a\xf1\x95\x0a\x83\xd7\xbc\x31\x73\x01\x34\xed\xef\x46\x71\xe0\x6b\x02\xa8\x35\x72\x6b\x97\x9b\x66\xe0\xcb\x1c\x79\x5f\xd8\x1a\x04\x68\x1e\x47\x02\xe6\x9d\x60\xe2\x36\x97\x01\xdf\xce\x35\x92\xdf\xbe\x67\xc7\x6d\x77\x59\x3b\x8f\x9d\xd6\x90\x15\x94\xbc\x42\x34\x10\xc1\x39\xf9\xb1\x27\x3e\x7e\xd6\x8a\x75\xc5\xb2\xaf\x96\xd3\xa2\xde\x9b\xe4\x98\xbe\x7d\xe1\xe9\x81\xad\xb6\x6f\xfc\xd7\x0e\xda\xe0\x34\xb0\x0d\x1a\x77\xe7\xe3\x08\x98\xef\x58\xfa\x9c\x84\xb7\x36\xaf\xc2\xdf\xac\xd2\xf4\x10\x06\x70\x71\x35\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x2c\xd5\x50\x41\x97\x15\x8b\xf0\x8f\x36\x61\x5b\x4a\xfb\x6b\xd9\x99\xc9\x33\x92\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x5a\x70\x7f\x2c\xdd\xb7\x34\x4f\xf5\x86\x51\xa9\x26\xbe\x4b\xb8\xaa\xf1\x71\x0d\xdc\x61\xc7\xa0\xea\x34\x1e\x7a\x77\x0f\x04\x35\xe8\x27\x8f\x6c\x90\xbf\x91\x16\x24\x46\x3e\x4a\x4e\xce\x2b\x16\xd5\x0b\x52\x1d\xfc\x1f\x67\xa2\x02\x45\x31\x4f\xce\xf3\xfa\x03\xa7\x79\x9d\x53\x6a\xd9\xda\x63\x3a\xf8\x80\xd7\xd3\x99\xe1\xa5\xe1\xbe\xd4\x55\x71\x98\x35\x3a\xbe\x93\xea\xae\xad\x42\xb2\x90\x6f\xe0\xfc\x21\x4d\x35\x63\x33\x89\x49\xd6\x9b\x4e\xca\xc7\xe7\x4e\x09\x00\xf7\xda\xc7\xef\x99\x62\x99\x77\xb6\x95\x22\x5e\x8a\xa0\xab\xf4\xb8\x78\x98\xca\x38\x19\x99\xc9\x72\x9e\x78\xcd\x4b\xac\xaf\x19\xa0\x73\x12\x2d\xfc\xc2\x41\xba\x81\x91\xda\x16\x5a\x31\xb7\xf9\xb4\x71\x80\x12\x48\x99\x72\x73\x5a\x59\x53\xc1\x63\x52\x33\xed\xa7\xc9\xd2\x39\x02\x70\xfa\xe0\xb1\x42\x66\x29\xaa\x9b\x51\xed\x30\x54\x22\x14\x5f\xd9\xab\x1d\xc1\xe4\x94\xf0\xf8\xf5\x2b\xf7\xea\xca\x78\x46\xd6\xb8\x91\xfd\xa6\x0d\x2b\x1a\x14\x01\x3e\x80\xf0\x42\xa0\x95\x07\x5e\x6d\xcd\xcc\x4b\xa4\x45\x8d\xab\x12\xe8\xb3\xde\x5a\xe5\xa0\x7c\xe8\x0f\x22\x1d\x5a\xe9\x59", 0 }, + /* Anchor: 76 GeoTrust_Global_CA.cer serial: #{a.serial.to_s} + C=US,O=GeoTrust Inc.,CN=GeoTrust Global CA + */ + { 856, "\x30\x82\x03\x54\x30\x82\x02\x3c\xa0\x03\x02\x01\x02\x02\x03\x02\x34\x56\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x42\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0a\x13\x0d\x47\x65\x6f\x54\x72\x75\x73\x74\x20\x49\x6e\x63\x2e\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x13\x12\x47\x65\x6f\x54\x72\x75\x73\x74\x20\x47\x6c\x6f\x62\x61\x6c\x20\x43\x41\x30\x1e\x17\x0d\x30\x32\x30\x35\x32\x31\x30\x34\x30\x30\x30\x30\x5a\x17\x0d\x32\x32\x30\x35\x32\x31\x30\x34\x30\x30\x30\x30\x5a\x30\x42\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0a\x13\x0d\x47\x65\x6f\x54\x72\x75\x73\x74\x20\x49\x6e\x63\x2e\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x13\x12\x47\x65\x6f\x54\x72\x75\x73\x74\x20\x47\x6c\x6f\x62\x61\x6c\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xda\xcc\x18\x63\x30\xfd\xf4\x17\x23\x1a\x56\x7e\x5b\xdf\x3c\x6c\x38\xe4\x71\xb7\x78\x91\xd4\xbc\xa1\xd8\x4c\xf8\xa8\x43\xb6\x03\xe9\x4d\x21\x07\x08\x88\xda\x58\x2f\x66\x39\x29\xbd\x05\x78\x8b\x9d\x38\xe8\x05\xb7\x6a\x7e\x71\xa4\xe6\xc4\x60\xa6\xb0\xef\x80\xe4\x89\x28\x0f\x9e\x25\xd6\xed\x83\xf3\xad\xa6\x91\xc7\x98\xc9\x42\x18\x35\x14\x9d\xad\x98\x46\x92\x2e\x4f\xca\xf1\x87\x43\xc1\x16\x95\x57\x2d\x50\xef\x89\x2d\x80\x7a\x57\xad\xf2\xee\x5f\x6b\xd2\x00\x8d\xb9\x14\xf8\x14\x15\x35\xd9\xc0\x46\xa3\x7b\x72\xc8\x91\xbf\xc9\x55\x2b\xcd\xd0\x97\x3e\x9c\x26\x64\xcc\xdf\xce\x83\x19\x71\xca\x4e\xe6\xd4\xd5\x7b\xa9\x19\xcd\x55\xde\xc8\xec\xd2\x5e\x38\x53\xe5\x5c\x4f\x8c\x2d\xfe\x50\x23\x36\xfc\x66\xe6\xcb\x8e\xa4\x39\x19\x00\xb7\x95\x02\x39\x91\x0b\x0e\xfe\x38\x2e\xd1\x1d\x05\x9a\xf6\x4d\x3e\x6f\x0f\x07\x1d\xaf\x2c\x1e\x8f\x60\x39\xe2\xfa\x36\x53\x13\x39\xd4\x5e\x26\x2b\xdb\x3d\xa8\x14\xbd\x32\xeb\x18\x03\x28\x52\x04\x71\xe5\xab\x33\x3d\xe1\x38\xbb\x07\x36\x84\x62\x9c\x79\xea\x16\x30\xf4\x5f\xc0\x2b\xe8\x71\x6b\xe4\xf9\x02\x03\x01\x00\x01\xa3\x53\x30\x51\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xc0\x7a\x98\x68\x8d\x89\xfb\xab\x05\x64\x0c\x11\x7d\xaa\x7d\x65\xb8\xca\xcc\x4e\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\xc0\x7a\x98\x68\x8d\x89\xfb\xab\x05\x64\x0c\x11\x7d\xaa\x7d\x65\xb8\xca\xcc\x4e\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x35\xe3\x29\x6a\xe5\x2f\x5d\x54\x8e\x29\x50\x94\x9f\x99\x1a\x14\xe4\x8f\x78\x2a\x62\x94\xa2\x27\x67\x9e\xd0\xcf\x1a\x5e\x47\xe9\xc1\xb2\xa4\xcf\xdd\x41\x1a\x05\x4e\x9b\x4b\xee\x4a\x6f\x55\x52\xb3\x24\xa1\x37\x0a\xeb\x64\x76\x2a\x2e\x2c\xf3\xfd\x3b\x75\x90\xbf\xfa\x71\xd8\xc7\x3d\x37\xd2\xb5\x05\x95\x62\xb9\xa6\xde\x89\x3d\x36\x7b\x38\x77\x48\x97\xac\xa6\x20\x8f\x2e\xa6\xc9\x0c\xc2\xb2\x99\x45\x00\xc7\xce\x11\x51\x22\x22\xe0\xa5\xea\xb6\x15\x48\x09\x64\xea\x5e\x4f\x74\xf7\x05\x3e\xc7\x8a\x52\x0c\xdb\x15\xb4\xbd\x6d\x9b\xe5\xc6\xb1\x54\x68\xa9\xe3\x69\x90\xb6\x9a\xa5\x0f\xb8\xb9\x3f\x20\x7d\xae\x4a\xb5\xb8\x9c\xe4\x1d\xb6\xab\xe6\x94\xa5\xc1\xc7\x83\xad\xdb\xf5\x27\x87\x0e\x04\x6c\xd5\xff\xdd\xa0\x5d\xed\x87\x52\xb7\x2b\x15\x02\xae\x39\xa6\x6a\x74\xe9\xda\xc4\xe7\xbc\x4d\x34\x1e\xa9\x5c\x4d\x33\x5f\x92\x09\x2f\x88\x66\x5d\x77\x97\xc7\x1d\x76\x13\xa9\xd5\xe5\xf1\x16\x09\x11\x35\xd5\xac\xdb\x24\x71\x70\x2c\x98\x56\x0b\xd9\x17\xb4\xd1\xe3\x51\x2b\x5e\x75\xe8\xd5\xd0\xdc\x4f\x34\xed\xc2\x05\x66\x80\xa1\xcb\xe6\x33", 0 }, + /* Anchor: 77 GlobalSign-Root-R3.der serial: #{a.serial.to_s} + OU=GlobalSign Root CA - R3,O=GlobalSign,CN=GlobalSign + */ + { 867, "\x30\x82\x03\x5f\x30\x82\x02\x47\xa0\x03\x02\x01\x02\x02\x0b\x04\x00\x00\x00\x00\x01\x21\x58\x53\x08\xa2\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x30\x4c\x31\x20\x30\x1e\x06\x03\x55\x04\x0b\x13\x17\x47\x6c\x6f\x62\x61\x6c\x53\x69\x67\x6e\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x2d\x20\x52\x33\x31\x13\x30\x11\x06\x03\x55\x04\x0a\x13\x0a\x47\x6c\x6f\x62\x61\x6c\x53\x69\x67\x6e\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x47\x6c\x6f\x62\x61\x6c\x53\x69\x67\x6e\x30\x1e\x17\x0d\x30\x39\x30\x33\x31\x38\x31\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x39\x30\x33\x31\x38\x31\x30\x30\x30\x30\x30\x5a\x30\x4c\x31\x20\x30\x1e\x06\x03\x55\x04\x0b\x13\x17\x47\x6c\x6f\x62\x61\x6c\x53\x69\x67\x6e\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x2d\x20\x52\x33\x31\x13\x30\x11\x06\x03\x55\x04\x0a\x13\x0a\x47\x6c\x6f\x62\x61\x6c\x53\x69\x67\x6e\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x47\x6c\x6f\x62\x61\x6c\x53\x69\x67\x6e\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xcc\x25\x76\x90\x79\x06\x78\x22\x16\xf5\xc0\x83\xb6\x84\xca\x28\x9e\xfd\x05\x76\x11\xc5\xad\x88\x72\xfc\x46\x02\x43\xc7\xb2\x8a\x9d\x04\x5f\x24\xcb\x2e\x4b\xe1\x60\x82\x46\xe1\x52\xab\x0c\x81\x47\x70\x6c\xdd\x64\xd1\xeb\xf5\x2c\xa3\x0f\x82\x3d\x0c\x2b\xae\x97\xd7\xb6\x14\x86\x10\x79\xbb\x3b\x13\x80\x77\x8c\x08\xe1\x49\xd2\x6a\x62\x2f\x1f\x5e\xfa\x96\x68\xdf\x89\x27\x95\x38\x9f\x06\xd7\x3e\xc9\xcb\x26\x59\x0d\x73\xde\xb0\xc8\xe9\x26\x0e\x83\x15\xc6\xef\x5b\x8b\xd2\x04\x60\xca\x49\xa6\x28\xf6\x69\x3b\xf6\xcb\xc8\x28\x91\xe5\x9d\x8a\x61\x57\x37\xac\x74\x14\xdc\x74\xe0\x3a\xee\x72\x2f\x2e\x9c\xfb\xd0\xbb\xbf\xf5\x3d\x00\xe1\x06\x33\xe8\x82\x2b\xae\x53\xa6\x3a\x16\x73\x8c\xdd\x41\x0e\x20\x3a\xc0\xb4\xa7\xa1\xe9\xb2\x4f\x90\x2e\x32\x60\xe9\x57\xcb\xb9\x04\x92\x68\x68\xe5\x38\x26\x60\x75\xb2\x9f\x77\xff\x91\x14\xef\xae\x20\x49\xfc\xad\x40\x15\x48\xd1\x02\x31\x61\x19\x5e\xb8\x97\xef\xad\x77\xb7\x64\x9a\x7a\xbf\x5f\xc1\x13\xef\x9b\x62\xfb\x0d\x6c\xe0\x54\x69\x16\xa9\x03\xda\x6e\xe9\x83\x93\x71\x76\xc6\x69\x85\x82\x17\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x8f\xf0\x4b\x7f\xa8\x2e\x45\x24\xae\x4d\x50\xfa\x63\x9a\x8b\xde\xe2\xdd\x1b\xbc\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x03\x82\x01\x01\x00\x4b\x40\xdb\xc0\x50\xaa\xfe\xc8\x0c\xef\xf7\x96\x54\x45\x49\xbb\x96\x00\x09\x41\xac\xb3\x13\x86\x86\x28\x07\x33\xca\x6b\xe6\x74\xb9\xba\x00\x2d\xae\xa4\x0a\xd3\xf5\xf1\xf1\x0f\x8a\xbf\x73\x67\x4a\x83\xc7\x44\x7b\x78\xe0\xaf\x6e\x6c\x6f\x03\x29\x8e\x33\x39\x45\xc3\x8e\xe4\xb9\x57\x6c\xaa\xfc\x12\x96\xec\x53\xc6\x2d\xe4\x24\x6c\xb9\x94\x63\xfb\xdc\x53\x68\x67\x56\x3e\x83\xb8\xcf\x35\x21\xc3\xc9\x68\xfe\xce\xda\xc2\x53\xaa\xcc\x90\x8a\xe9\xf0\x5d\x46\x8c\x95\xdd\x7a\x58\x28\x1a\x2f\x1d\xde\xcd\x00\x37\x41\x8f\xed\x44\x6d\xd7\x53\x28\x97\x7e\xf3\x67\x04\x1e\x15\xd7\x8a\x96\xb4\xd3\xde\x4c\x27\xa4\x4c\x1b\x73\x73\x76\xf4\x17\x99\xc2\x1f\x7a\x0e\xe3\x2d\x08\xad\x0a\x1c\x2c\xff\x3c\xab\x55\x0e\x0f\x91\x7e\x36\xeb\xc3\x57\x49\xbe\xe1\x2e\x2d\x7c\x60\x8b\xc3\x41\x51\x13\x23\x9d\xce\xf7\x32\x6b\x94\x01\xa8\x99\xe7\x2c\x33\x1f\x3a\x3b\x25\xd2\x86\x40\xce\x3b\x2c\x86\x78\xc9\x61\x2f\x14\xba\xee\xdb\x55\x6f\xdf\x84\xee\x05\x09\x4d\xbd\x28\xd8\x72\xce\xd3\x62\x50\x65\x1e\xeb\x92\x97\x83\x31\xd9\xb3\xb5\xca\x47\x58\x3f\x5f", 0 }, + /* Anchor: 78 GlobalSign-RootCA-2028exp.cer serial: #{a.serial.to_s} + C=BE,O=GlobalSign nv-sa,OU=Root CA,CN=GlobalSign Root CA + */ + { 889, "\x30\x82\x03\x75\x30\x82\x02\x5d\xa0\x03\x02\x01\x02\x02\x0b\x04\x00\x00\x00\x00\x01\x15\x4b\x5a\xc3\x94\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x57\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x45\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x47\x6c\x6f\x62\x61\x6c\x53\x69\x67\x6e\x20\x6e\x76\x2d\x73\x61\x31\x10\x30\x0e\x06\x03\x55\x04\x0b\x13\x07\x52\x6f\x6f\x74\x20\x43\x41\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x13\x12\x47\x6c\x6f\x62\x61\x6c\x53\x69\x67\x6e\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x1e\x17\x0d\x39\x38\x30\x39\x30\x31\x31\x32\x30\x30\x30\x30\x5a\x17\x0d\x32\x38\x30\x31\x32\x38\x31\x32\x30\x30\x30\x30\x5a\x30\x57\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x45\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x47\x6c\x6f\x62\x61\x6c\x53\x69\x67\x6e\x20\x6e\x76\x2d\x73\x61\x31\x10\x30\x0e\x06\x03\x55\x04\x0b\x13\x07\x52\x6f\x6f\x74\x20\x43\x41\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x13\x12\x47\x6c\x6f\x62\x61\x6c\x53\x69\x67\x6e\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xda\x0e\xe6\x99\x8d\xce\xa3\xe3\x4f\x8a\x7e\xfb\xf1\x8b\x83\x25\x6b\xea\x48\x1f\xf1\x2a\xb0\xb9\x95\x11\x04\xbd\xf0\x63\xd1\xe2\x67\x66\xcf\x1c\xdd\xcf\x1b\x48\x2b\xee\x8d\x89\x8e\x9a\xaf\x29\x80\x65\xab\xe9\xc7\x2d\x12\xcb\xab\x1c\x4c\x70\x07\xa1\x3d\x0a\x30\xcd\x15\x8d\x4f\xf8\xdd\xd4\x8c\x50\x15\x1c\xef\x50\xee\xc4\x2e\xf7\xfc\xe9\x52\xf2\x91\x7d\xe0\x6d\xd5\x35\x30\x8e\x5e\x43\x73\xf2\x41\xe9\xd5\x6a\xe3\xb2\x89\x3a\x56\x39\x38\x6f\x06\x3c\x88\x69\x5b\x2a\x4d\xc5\xa7\x54\xb8\x6c\x89\xcc\x9b\xf9\x3c\xca\xe5\xfd\x89\xf5\x12\x3c\x92\x78\x96\xd6\xdc\x74\x6e\x93\x44\x61\xd1\x8d\xc7\x46\xb2\x75\x0e\x86\xe8\x19\x8a\xd5\x6d\x6c\xd5\x78\x16\x95\xa2\xe9\xc8\x0a\x38\xeb\xf2\x24\x13\x4f\x73\x54\x93\x13\x85\x3a\x1b\xbc\x1e\x34\xb5\x8b\x05\x8c\xb9\x77\x8b\xb1\xdb\x1f\x20\x91\xab\x09\x53\x6e\x90\xce\x7b\x37\x74\xb9\x70\x47\x91\x22\x51\x63\x16\x79\xae\xb1\xae\x41\x26\x08\xc8\x19\x2b\xd1\x46\xaa\x48\xd6\x64\x2a\xd7\x83\x34\xff\x2c\x2a\xc1\x6c\x19\x43\x4a\x07\x85\xe7\xd3\x7c\xf6\x21\x68\xef\xea\xf2\x52\x9f\x7f\x93\x90\xcf\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x60\x7b\x66\x1a\x45\x0d\x97\xca\x89\x50\x2f\x7d\x04\xcd\x34\xa8\xff\xfc\xfd\x4b\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xd6\x73\xe7\x7c\x4f\x76\xd0\x8d\xbf\xec\xba\xa2\xbe\x34\xc5\x28\x32\xb5\x7c\xfc\x6c\x9c\x2c\x2b\xbd\x09\x9e\x53\xbf\x6b\x5e\xaa\x11\x48\xb6\xe5\x08\xa3\xb3\xca\x3d\x61\x4d\xd3\x46\x09\xb3\x3e\xc3\xa0\xe3\x63\x55\x1b\xf2\xba\xef\xad\x39\xe1\x43\xb9\x38\xa3\xe6\x2f\x8a\x26\x3b\xef\xa0\x50\x56\xf9\xc6\x0a\xfd\x38\xcd\xc4\x0b\x70\x51\x94\x97\x98\x04\xdf\xc3\x5f\x94\xd5\x15\xc9\x14\x41\x9c\xc4\x5d\x75\x64\x15\x0d\xff\x55\x30\xec\x86\x8f\xff\x0d\xef\x2c\xb9\x63\x46\xf6\xaa\xfc\xdf\xbc\x69\xfd\x2e\x12\x48\x64\x9a\xe0\x95\xf0\xa6\xef\x29\x8f\x01\xb1\x15\xb5\x0c\x1d\xa5\xfe\x69\x2c\x69\x24\x78\x1e\xb3\xa7\x1c\x71\x62\xee\xca\xc8\x97\xac\x17\x5d\x8a\xc2\xf8\x47\x86\x6e\x2a\xc4\x56\x31\x95\xd0\x67\x89\x85\x2b\xf9\x6c\xa6\x5d\x46\x9d\x0c\xaa\x82\xe4\x99\x51\xdd\x70\xb7\xdb\x56\x3d\x61\xe4\x6a\xe1\x5c\xd6\xf6\xfe\x3d\xde\x41\xcc\x07\xae\x63\x52\xbf\x53\x53\xf4\x2b\xe9\xc7\xfd\xb6\xf7\x82\x5f\x85\xd2\x41\x18\xdb\x81\xb3\x04\x1c\xc5\x1f\xa4\x80\x6f\x15\x20\xc9\xde\x0c\x88\x0a\x1d\xd6\x66\x55\xe2\xfc\x48\xc9\x29\x26\x69\xe0", 79 }, + /* Anchor: 79 globalSignRoot.cer serial: #{a.serial.to_s} + C=BE,O=GlobalSign nv-sa,OU=Root CA,CN=GlobalSign Root CA + */ + { 889, "\x30\x82\x03\x75\x30\x82\x02\x5d\xa0\x03\x02\x01\x02\x02\x0b\x02\x00\x00\x00\x00\x00\xd6\x78\xb7\x94\x05\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x30\x57\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x45\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x47\x6c\x6f\x62\x61\x6c\x53\x69\x67\x6e\x20\x6e\x76\x2d\x73\x61\x31\x10\x30\x0e\x06\x03\x55\x04\x0b\x13\x07\x52\x6f\x6f\x74\x20\x43\x41\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x13\x12\x47\x6c\x6f\x62\x61\x6c\x53\x69\x67\x6e\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x1e\x17\x0d\x39\x38\x30\x39\x30\x31\x31\x32\x30\x30\x30\x30\x5a\x17\x0d\x31\x34\x30\x31\x32\x38\x31\x32\x30\x30\x30\x30\x5a\x30\x57\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x45\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x47\x6c\x6f\x62\x61\x6c\x53\x69\x67\x6e\x20\x6e\x76\x2d\x73\x61\x31\x10\x30\x0e\x06\x03\x55\x04\x0b\x13\x07\x52\x6f\x6f\x74\x20\x43\x41\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x13\x12\x47\x6c\x6f\x62\x61\x6c\x53\x69\x67\x6e\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xda\x0e\xe6\x99\x8d\xce\xa3\xe3\x4f\x8a\x7e\xfb\xf1\x8b\x83\x25\x6b\xea\x48\x1f\xf1\x2a\xb0\xb9\x95\x11\x04\xbd\xf0\x63\xd1\xe2\x67\x66\xcf\x1c\xdd\xcf\x1b\x48\x2b\xee\x8d\x89\x8e\x9a\xaf\x29\x80\x65\xab\xe9\xc7\x2d\x12\xcb\xab\x1c\x4c\x70\x07\xa1\x3d\x0a\x30\xcd\x15\x8d\x4f\xf8\xdd\xd4\x8c\x50\x15\x1c\xef\x50\xee\xc4\x2e\xf7\xfc\xe9\x52\xf2\x91\x7d\xe0\x6d\xd5\x35\x30\x8e\x5e\x43\x73\xf2\x41\xe9\xd5\x6a\xe3\xb2\x89\x3a\x56\x39\x38\x6f\x06\x3c\x88\x69\x5b\x2a\x4d\xc5\xa7\x54\xb8\x6c\x89\xcc\x9b\xf9\x3c\xca\xe5\xfd\x89\xf5\x12\x3c\x92\x78\x96\xd6\xdc\x74\x6e\x93\x44\x61\xd1\x8d\xc7\x46\xb2\x75\x0e\x86\xe8\x19\x8a\xd5\x6d\x6c\xd5\x78\x16\x95\xa2\xe9\xc8\x0a\x38\xeb\xf2\x24\x13\x4f\x73\x54\x93\x13\x85\x3a\x1b\xbc\x1e\x34\xb5\x8b\x05\x8c\xb9\x77\x8b\xb1\xdb\x1f\x20\x91\xab\x09\x53\x6e\x90\xce\x7b\x37\x74\xb9\x70\x47\x91\x22\x51\x63\x16\x79\xae\xb1\xae\x41\x26\x08\xc8\x19\x2b\xd1\x46\xaa\x48\xd6\x64\x2a\xd7\x83\x34\xff\x2c\x2a\xc1\x6c\x19\x43\x4a\x07\x85\xe7\xd3\x7c\xf6\x21\x68\xef\xea\xf2\x52\x9f\x7f\x93\x90\xcf\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x00\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x60\x7b\x66\x1a\x45\x0d\x97\xca\x89\x50\x2f\x7d\x04\xcd\x34\xa8\xff\xfc\xfd\x4b\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x03\x82\x01\x01\x00\xae\xaa\x9f\xfc\xb7\xd2\xcb\x1f\x5f\x39\x29\x28\x18\x9e\x34\xc9\x6c\x4f\x6f\x1a\xf0\x64\xa2\x70\x4a\x4f\x13\x86\x9b\x60\x28\x9e\xe8\x81\x49\x98\x7d\x0a\xbb\xe5\xb0\x9d\x3d\x36\xdb\x8f\x05\x51\xff\x09\x31\x2a\x1f\xdd\x89\x77\x9e\x0f\x2e\x6c\x95\x04\xed\x86\xcb\xb4\x00\x3f\x84\x02\x4d\x80\x6a\x2a\x2d\x78\x0b\xae\x6f\x2b\xa2\x83\x44\x83\x1f\xcd\x50\x82\x4c\x24\xaf\xbd\xf7\xa5\xb4\xc8\x5a\x0f\xf4\xe7\x47\x5e\x49\x8e\x37\x96\xfe\x9a\x88\x05\x3a\xd9\xc0\xdb\x29\x87\xe6\x19\x96\x47\xa7\x3a\xa6\x8c\x8b\x3c\x77\xfe\x46\x63\xa7\x53\xda\x21\xd1\xac\x7e\x49\xa2\x4b\xe6\xc3\x67\x59\x2f\xb3\x8a\x0e\xbb\x2c\xbd\xa9\xaa\x42\x7c\x35\xc1\xd8\x7f\xd5\xa7\x31\x3a\x4e\x63\x43\x39\xaf\x08\xb0\x61\x34\x8c\xd3\x98\xa9\x43\x34\xf6\x0f\x87\x29\x3b\x9d\xc2\x56\x58\x98\x77\xc3\xf7\x1b\xac\xf6\x9d\xf8\x3e\xaa\xa7\x54\x45\xf0\xf5\xf9\xd5\x31\x65\xfe\x6b\x58\x9c\x71\xb3\x1e\xd7\x52\xea\x32\x17\xfc\x40\x60\x1d\xc9\x79\x24\xb2\xf6\x6c\xfd\xa8\x66\x0e\x82\xdd\x98\xcb\xda\xc2\x44\x4f\x2e\xa0\x7b\xf2\xf7\x6b\x2c\x76\x11\x84\x46\x8a\x78\xa3\xe3", 0 }, + /* Anchor: 80 GlobalSignRootCA-R2.cer serial: #{a.serial.to_s} + OU=GlobalSign Root CA - R2,O=GlobalSign,CN=GlobalSign + */ + { 958, "\x30\x82\x03\xba\x30\x82\x02\xa2\xa0\x03\x02\x01\x02\x02\x0b\x04\x00\x00\x00\x00\x01\x0f\x86\x26\xe6\x0d\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x4c\x31\x20\x30\x1e\x06\x03\x55\x04\x0b\x13\x17\x47\x6c\x6f\x62\x61\x6c\x53\x69\x67\x6e\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x2d\x20\x52\x32\x31\x13\x30\x11\x06\x03\x55\x04\x0a\x13\x0a\x47\x6c\x6f\x62\x61\x6c\x53\x69\x67\x6e\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x47\x6c\x6f\x62\x61\x6c\x53\x69\x67\x6e\x30\x1e\x17\x0d\x30\x36\x31\x32\x31\x35\x30\x38\x30\x30\x30\x30\x5a\x17\x0d\x32\x31\x31\x32\x31\x35\x30\x38\x30\x30\x30\x30\x5a\x30\x4c\x31\x20\x30\x1e\x06\x03\x55\x04\x0b\x13\x17\x47\x6c\x6f\x62\x61\x6c\x53\x69\x67\x6e\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x2d\x20\x52\x32\x31\x13\x30\x11\x06\x03\x55\x04\x0a\x13\x0a\x47\x6c\x6f\x62\x61\x6c\x53\x69\x67\x6e\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x47\x6c\x6f\x62\x61\x6c\x53\x69\x67\x6e\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xa6\xcf\x24\x0e\xbe\x2e\x6f\x28\x99\x45\x42\xc4\xab\x3e\x21\x54\x9b\x0b\xd3\x7f\x84\x70\xfa\x12\xb3\xcb\xbf\x87\x5f\xc6\x7f\x86\xd3\xb2\x30\x5c\xd6\xfd\xad\xf1\x7b\xdc\xe5\xf8\x60\x96\x09\x92\x10\xf5\xd0\x53\xde\xfb\x7b\x7e\x73\x88\xac\x52\x88\x7b\x4a\xa6\xca\x49\xa6\x5e\xa8\xa7\x8c\x5a\x11\xbc\x7a\x82\xeb\xbe\x8c\xe9\xb3\xac\x96\x25\x07\x97\x4a\x99\x2a\x07\x2f\xb4\x1e\x77\xbf\x8a\x0f\xb5\x02\x7c\x1b\x96\xb8\xc5\xb9\x3a\x2c\xbc\xd6\x12\xb9\xeb\x59\x7d\xe2\xd0\x06\x86\x5f\x5e\x49\x6a\xb5\x39\x5e\x88\x34\xec\xbc\x78\x0c\x08\x98\x84\x6c\xa8\xcd\x4b\xb4\xa0\x7d\x0c\x79\x4d\xf0\xb8\x2d\xcb\x21\xca\xd5\x6c\x5b\x7d\xe1\xa0\x29\x84\xa1\xf9\xd3\x94\x49\xcb\x24\x62\x91\x20\xbc\xdd\x0b\xd5\xd9\xcc\xf9\xea\x27\x0a\x2b\x73\x91\xc6\x9d\x1b\xac\xc8\xcb\xe8\xe0\xa0\xf4\x2f\x90\x8b\x4d\xfb\xb0\x36\x1b\xf6\x19\x7a\x85\xe0\x6d\xf2\x61\x13\x88\x5c\x9f\xe0\x93\x0a\x51\x97\x8a\x5a\xce\xaf\xab\xd5\xf7\xaa\x09\xaa\x60\xbd\xdc\xd9\x5f\xdf\x72\xa9\x60\x13\x5e\x00\x01\xc9\x4a\xfa\x3f\xa4\xea\x07\x03\x21\x02\x8e\x82\xca\x03\xc2\x9b\x8f\x02\x03\x01\x00\x01\xa3\x81\x9c\x30\x81\x99\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x9b\xe2\x07\x57\x67\x1c\x1e\xc0\x6a\x06\xde\x59\xb4\x9a\x2d\xdf\xdc\x19\x86\x2e\x30\x36\x06\x03\x55\x1d\x1f\x04\x2f\x30\x2d\x30\x2b\xa0\x29\xa0\x27\x86\x25\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x67\x6c\x6f\x62\x61\x6c\x73\x69\x67\x6e\x2e\x6e\x65\x74\x2f\x72\x6f\x6f\x74\x2d\x72\x32\x2e\x63\x72\x6c\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x9b\xe2\x07\x57\x67\x1c\x1e\xc0\x6a\x06\xde\x59\xb4\x9a\x2d\xdf\xdc\x19\x86\x2e\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x99\x81\x53\x87\x1c\x68\x97\x86\x91\xec\xe0\x4a\xb8\x44\x0b\xab\x81\xac\x27\x4f\xd6\xc1\xb8\x1c\x43\x78\xb3\x0c\x9a\xfc\xea\x2c\x3c\x6e\x61\x1b\x4d\x4b\x29\xf5\x9f\x05\x1d\x26\xc1\xb8\xe9\x83\x00\x62\x45\xb6\xa9\x08\x93\xb9\xa9\x33\x4b\x18\x9a\xc2\xf8\x87\x88\x4e\xdb\xdd\x71\x34\x1a\xc1\x54\xda\x46\x3f\xe0\xd3\x2a\xab\x6d\x54\x22\xf5\x3a\x62\xcd\x20\x6f\xba\x29\x89\xd7\xdd\x91\xee\xd3\x5c\xa2\x3e\xa1\x5b\x41\xf5\xdf\xe5\x64\x43\x2d\xe9\xd5\x39\xab\xd2\xa2\xdf\xb7\x8b\xd0\xc0\x80\x19\x1c\x45\xc0\x2d\x8c\xe8\xf8\x2d\xa4\x74\x56\x49\xc5\x05\xb5\x4f\x15\xde\x6e\x44\x78\x39\x87\xa8\x7e\xbb\xf3\x79\x18\x91\xbb\xf4\x6f\x9d\xc1\xf0\x8c\x35\x8c\x5d\x01\xfb\xc3\x6d\xb9\xef\x44\x6d\x79\x46\x31\x7e\x0a\xfe\xa9\x82\xc1\xff\xef\xab\x6e\x20\xc4\x50\xc9\x5f\x9d\x4d\x9b\x17\x8c\x0c\xe5\x01\xc9\xa0\x41\x6a\x73\x53\xfa\xa5\x50\xb4\x6e\x25\x0f\xfb\x4c\x18\xf4\xfd\x52\xd9\x8e\x69\xb1\xe8\x11\x0f\xde\x88\xd8\xfb\x1d\x49\xf7\xaa\xde\x95\xcf\x20\x78\xc2\x60\x12\xdb\x25\x40\x8c\x6a\xfc\x7e\x42\x38\x40\x64\x12\xf7\x9e\x81\xe1\x93\x2e", 0 }, + /* Anchor: 81 GoDaddyRootCertificateAuthorityG2.der serial: #{a.serial.to_s} + C=US,ST=Arizona,L=Scottsdale,O=GoDaddy.com\, Inc.,CN=Go Daddy Root Certificate Authority - G2 + */ + { 969, "\x30\x82\x03\xc5\x30\x82\x02\xad\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x30\x81\x83\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0e\x06\x03\x55\x04\x08\x13\x07\x41\x72\x69\x7a\x6f\x6e\x61\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0a\x53\x63\x6f\x74\x74\x73\x64\x61\x6c\x65\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x13\x11\x47\x6f\x44\x61\x64\x64\x79\x2e\x63\x6f\x6d\x2c\x20\x49\x6e\x63\x2e\x31\x31\x30\x2f\x06\x03\x55\x04\x03\x13\x28\x47\x6f\x20\x44\x61\x64\x64\x79\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x32\x30\x1e\x17\x0d\x30\x39\x30\x39\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x33\x37\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x81\x83\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0e\x06\x03\x55\x04\x08\x13\x07\x41\x72\x69\x7a\x6f\x6e\x61\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0a\x53\x63\x6f\x74\x74\x73\x64\x61\x6c\x65\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x13\x11\x47\x6f\x44\x61\x64\x64\x79\x2e\x63\x6f\x6d\x2c\x20\x49\x6e\x63\x2e\x31\x31\x30\x2f\x06\x03\x55\x04\x03\x13\x28\x47\x6f\x20\x44\x61\x64\x64\x79\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x32\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xbf\x71\x62\x08\xf1\xfa\x59\x34\xf7\x1b\xc9\x18\xa3\xf7\x80\x49\x58\xe9\x22\x83\x13\xa6\xc5\x20\x43\x01\x3b\x84\xf1\xe6\x85\x49\x9f\x27\xea\xf6\x84\x1b\x4e\xa0\xb4\xdb\x70\x98\xc7\x32\x01\xb1\x05\x3e\x07\x4e\xee\xf4\xfa\x4f\x2f\x59\x30\x22\xe7\xab\x19\x56\x6b\xe2\x80\x07\xfc\xf3\x16\x75\x80\x39\x51\x7b\xe5\xf9\x35\xb6\x74\x4e\xa9\x8d\x82\x13\xe4\xb6\x3f\xa9\x03\x83\xfa\xa2\xbe\x8a\x15\x6a\x7f\xde\x0b\xc3\xb6\x19\x14\x05\xca\xea\xc3\xa8\x04\x94\x3b\x46\x7c\x32\x0d\xf3\x00\x66\x22\xc8\x8d\x69\x6d\x36\x8c\x11\x18\xb7\xd3\xb2\x1c\x60\xb4\x38\xfa\x02\x8c\xce\xd3\xdd\x46\x07\xde\x0a\x3e\xeb\x5d\x7c\xc8\x7c\xfb\xb0\x2b\x53\xa4\x92\x62\x69\x51\x25\x05\x61\x1a\x44\x81\x8c\x2c\xa9\x43\x96\x23\xdf\xac\x3a\x81\x9a\x0e\x29\xc5\x1c\xa9\xe9\x5d\x1e\xb6\x9e\x9e\x30\x0a\x39\xce\xf1\x88\x80\xfb\x4b\x5d\xcc\x32\xec\x85\x62\x43\x25\x34\x02\x56\x27\x01\x91\xb4\x3b\x70\x2a\x3f\x6e\xb1\xe8\x9c\x88\x01\x7d\x9f\xd4\xf9\xdb\x53\x6d\x60\x9d\xbf\x2c\xe7\x58\xab\xb8\x5f\x46\xfc\xce\xc4\x1b\x03\x3c\x09\xeb\x49\x31\x5c\x69\x46\xb3\xe0\x47\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x3a\x9a\x85\x07\x10\x67\x28\xb6\xef\xf6\xbd\x05\x41\x6e\x20\xc1\x94\xda\x0f\xde\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x03\x82\x01\x01\x00\x99\xdb\x5d\x79\xd5\xf9\x97\x59\x67\x03\x61\xf1\x7e\x3b\x06\x31\x75\x2d\xa1\x20\x8e\x4f\x65\x87\xb4\xf7\xa6\x9c\xbc\xd8\xe9\x2f\xd0\xdb\x5a\xee\xcf\x74\x8c\x73\xb4\x38\x42\xda\x05\x7b\xf8\x02\x75\xb8\xfd\xa5\xb1\xd7\xae\xf6\xd7\xde\x13\xcb\x53\x10\x7e\x8a\x46\xd1\x97\xfa\xb7\x2e\x2b\x11\xab\x90\xb0\x27\x80\xf9\xe8\x9f\x5a\xe9\x37\x9f\xab\xe4\xdf\x6c\xb3\x85\x17\x9d\x3d\xd9\x24\x4f\x79\x91\x35\xd6\x5f\x04\xeb\x80\x83\xab\x9a\x02\x2d\xb5\x10\xf4\xd8\x90\xc7\x04\x73\x40\xed\x72\x25\xa0\xa9\x9f\xec\x9e\xab\x68\x12\x99\x57\xc6\x8f\x12\x3a\x09\xa4\xbd\x44\xfd\x06\x15\x37\xc1\x9b\xe4\x32\xa3\xed\x38\xe8\xd8\x64\xf3\x2c\x7e\x14\xfc\x02\xea\x9f\xcd\xff\x07\x68\x17\xdb\x22\x90\x38\x2d\x7a\x8d\xd1\x54\xf1\x69\xe3\x5f\x33\xca\x7a\x3d\x7b\x0a\xe3\xca\x7f\x5f\x39\xe5\xe2\x75\xba\xc5\x76\x18\x33\xce\x2c\xf0\x2f\x4c\xad\xf7\xb1\xe7\xce\x4f\xa8\xc4\x9b\x4a\x54\x06\xc5\x7f\x7d\xd5\x08\x0f\xe2\x1c\xfe\x7e\x17\xb8\xac\x5e\xf6\xd4\x16\xb2\x43\x09\x0c\x4d\xf6\xa7\x6b\xb4\x99\x84\x65\xca\x7a\x88\xe2\xe2\x44\xbe\x5c\xf7\xea\x1c\xf5", 0 }, + /* Anchor: 82 GTEGB18.cer serial: #{a.serial.to_s} + C=US,O=GTE Corporation,OU=GTE CyberTrust Solutions\, Inc.,CN=GTE CyberTrust Global Root + */ + { 606, "\x30\x82\x02\x5a\x30\x82\x01\xc3\x02\x02\x01\xa5\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x30\x75\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x18\x30\x16\x06\x03\x55\x04\x0a\x13\x0f\x47\x54\x45\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x27\x30\x25\x06\x03\x55\x04\x0b\x13\x1e\x47\x54\x45\x20\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x20\x53\x6f\x6c\x75\x74\x69\x6f\x6e\x73\x2c\x20\x49\x6e\x63\x2e\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1a\x47\x54\x45\x20\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x20\x47\x6c\x6f\x62\x61\x6c\x20\x52\x6f\x6f\x74\x30\x1e\x17\x0d\x39\x38\x30\x38\x31\x33\x30\x30\x32\x39\x30\x30\x5a\x17\x0d\x31\x38\x30\x38\x31\x33\x32\x33\x35\x39\x30\x30\x5a\x30\x75\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x18\x30\x16\x06\x03\x55\x04\x0a\x13\x0f\x47\x54\x45\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x27\x30\x25\x06\x03\x55\x04\x0b\x13\x1e\x47\x54\x45\x20\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x20\x53\x6f\x6c\x75\x74\x69\x6f\x6e\x73\x2c\x20\x49\x6e\x63\x2e\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1a\x47\x54\x45\x20\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x20\x47\x6c\x6f\x62\x61\x6c\x20\x52\x6f\x6f\x74\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\x95\x0f\xa0\xb6\xf0\x50\x9c\xe8\x7a\xc7\x88\xcd\xdd\x17\x0e\x2e\xb0\x94\xd0\x1b\x3d\x0e\xf6\x94\xc0\x8a\x94\xc7\x06\xc8\x90\x97\xc8\xb8\x64\x1a\x7a\x7e\x6c\x3c\x53\xe1\x37\x28\x73\x60\x7f\xb2\x97\x53\x07\x9f\x53\xf9\x6d\x58\x94\xd2\xaf\x8d\x6d\x88\x67\x80\xe6\xed\xb2\x95\xcf\x72\x31\xca\xa5\x1c\x72\xba\x5c\x02\xe7\x64\x42\xe7\xf9\xa9\x2c\xd6\x3a\x0d\xac\x8d\x42\xaa\x24\x01\x39\xe6\x9c\x3f\x01\x85\x57\x0d\x58\x87\x45\xf8\xd3\x85\xaa\x93\x69\x26\x85\x70\x48\x80\x3f\x12\x15\xc7\x79\xb4\x1f\x05\x2f\x3b\x62\x99\x02\x03\x01\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x03\x81\x81\x00\x6d\xeb\x1b\x09\xe9\x5e\xd9\x51\xdb\x67\x22\x61\xa4\x2a\x3c\x48\x77\xe3\xa0\x7c\xa6\xde\x73\xa2\x14\x03\x85\x3d\xfb\xab\x0e\x30\xc5\x83\x16\x33\x81\x13\x08\x9e\x7b\x34\x4e\xdf\x40\xc8\x74\xd7\xb9\x7d\xdc\xf4\x76\x55\x7d\x9b\x63\x54\x18\xe9\xf0\xea\xf3\x5c\xb1\xd9\x8b\x42\x1e\xb9\xc0\x95\x4e\xba\xfa\xd5\xe2\x7c\xf5\x68\x61\xbf\x8e\xec\x05\x97\x5f\x5b\xb0\xd7\xa3\x85\x34\xc4\x24\xa7\x0d\x0f\x95\x93\xef\xcb\x94\xd8\x9e\x1f\x9d\x5c\x85\x6d\xc7\xaa\xae\x4f\x1f\x22\xb5\xcd\x95\xad\xba\xa7\xcc\xf9\xab\x0b\x7a\x7f", 0 }, + /* Anchor: 83 HKPost-smartid_rt.cacert.crt serial: #{a.serial.to_s} + C=HK,O=Hongkong Post,CN=Hongkong Post Root CA 1 + */ + { 820, "\x30\x82\x03\x30\x30\x82\x02\x18\xa0\x03\x02\x01\x02\x02\x02\x03\xe8\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x47\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x4b\x31\x16\x30\x14\x06\x03\x55\x04\x0a\x13\x0d\x48\x6f\x6e\x67\x6b\x6f\x6e\x67\x20\x50\x6f\x73\x74\x31\x20\x30\x1e\x06\x03\x55\x04\x03\x13\x17\x48\x6f\x6e\x67\x6b\x6f\x6e\x67\x20\x50\x6f\x73\x74\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x31\x30\x1e\x17\x0d\x30\x33\x30\x35\x31\x35\x30\x35\x31\x33\x31\x34\x5a\x17\x0d\x32\x33\x30\x35\x31\x35\x30\x34\x35\x32\x32\x39\x5a\x30\x47\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x4b\x31\x16\x30\x14\x06\x03\x55\x04\x0a\x13\x0d\x48\x6f\x6e\x67\x6b\x6f\x6e\x67\x20\x50\x6f\x73\x74\x31\x20\x30\x1e\x06\x03\x55\x04\x03\x13\x17\x48\x6f\x6e\x67\x6b\x6f\x6e\x67\x20\x50\x6f\x73\x74\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x31\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xac\xff\x38\xb6\xe9\x66\x02\x49\xe3\xa2\xb4\xe1\x90\xf9\x40\x8f\x79\xf9\xe2\xbd\x79\xfe\x02\xbd\xee\x24\x92\x1d\x22\xf6\xda\x85\x72\x69\xfe\xd7\x3f\x09\xd4\xdd\x91\xb5\x02\x9c\xd0\x8d\x5a\xe1\x55\xc3\x50\x86\xb9\x29\x26\xc2\xe3\xd9\xa0\xf1\x69\x03\x28\x20\x80\x45\x22\x2d\x56\xa7\x3b\x54\x95\x56\x22\x59\x1f\x28\xdf\x1f\x20\x3d\x6d\xa2\x36\xbe\x23\xa0\xb1\x6e\xb5\xb1\x27\x3f\x39\x53\x09\xea\xab\x6a\xe8\x74\xb2\xc2\x65\x5c\x8e\xbf\x7c\xc3\x78\x84\xcd\x9e\x16\xfc\xf5\x2e\x4f\x20\x2a\x08\x9f\x77\xf3\xc5\x1e\xc4\x9a\x52\x66\x1e\x48\x5e\xe3\x10\x06\x8f\x22\x98\xe1\x65\x8e\x1b\x5d\x23\x66\x3b\xb8\xa5\x32\x51\xc8\x86\xaa\xa1\xa9\x9e\x7f\x76\x94\xc2\xa6\x6c\xb7\x41\xf0\xd5\xc8\x06\x38\xe6\xd4\x0c\xe2\xf3\x3b\x4c\x6d\x50\x8c\xc4\x83\x27\xc1\x13\x84\x59\x3d\x9e\x75\x74\xb6\xd8\x02\x5e\x3a\x90\x7a\xc0\x42\x36\x72\xec\x6a\x4d\xdc\xef\xc4\x00\xdf\x13\x18\x57\x5f\x26\x78\xc8\xd6\x0a\x79\x77\xbf\xf7\xaf\xb7\x76\xb9\xa5\x0b\x84\x17\x5d\x10\xea\x6f\xe1\xab\x95\x11\x5f\x6d\x3c\xa3\x5c\x4d\x83\x5b\xf2\xb3\x19\x8a\x80\x8b\x0b\x87\x02\x03\x01\x00\x01\xa3\x26\x30\x24\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01\x03\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\xc6\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x0e\x46\xd5\x3c\xae\xe2\x87\xd9\x5e\x81\x8b\x02\x98\x41\x08\x8c\x4c\xbc\xda\xdb\xee\x27\x1b\x82\xe7\x6a\x45\xec\x16\x8b\x4f\x85\xa0\xf3\xb2\x70\xbd\x5a\x96\xba\xca\x6e\x6d\xee\x46\x8b\x6e\xe7\x2a\x2e\x96\xb3\x19\x33\xeb\xb4\x9f\xa8\xb2\x37\xee\x98\xa8\x97\xb6\x2e\xb6\x67\x27\xd4\xa6\x49\xfd\x1c\x93\x65\x76\x9e\x42\x2f\xdc\x22\x6c\x9a\x4f\xf2\x5a\x15\x39\xb1\x71\xd7\x2b\x51\xe8\x6d\x1c\x98\xc0\xd9\x2a\xf4\xa1\x82\x7b\xd5\xc9\x41\xa2\x23\x01\x74\x38\x55\x8b\x0f\xb9\x2e\x67\xa2\x20\x04\x37\xda\x9c\x0b\xd3\x17\x21\xe0\x8f\x97\x79\x34\x6f\x84\x48\x02\x20\x33\x1b\xe6\x34\x44\x9f\x91\x70\xf4\x80\x5e\x84\x43\xc2\x29\xd2\x6c\x12\x14\xe4\x61\x8d\xac\x10\x90\x9e\x84\x50\xbb\xf0\x96\x6f\x45\x9f\x8a\xf3\xca\x6c\x4f\xfa\x11\x3a\x15\x15\x46\xc3\xcd\x1f\x83\x5b\x2d\x41\x12\xed\x50\x67\x41\x13\x3d\x21\xab\x94\x8a\xaa\x4e\x7c\xc1\xb1\xfb\xa7\xd6\xb5\x27\x2f\x97\xab\x6e\xe0\x1d\xe2\xd1\x1c\x2c\x1f\x44\xe2\xfc\xbe\x91\xa1\x9c\xfb\xd6\x29\x53\x73\x86\x9f\x53\xd8\x43\x0e\x5d\xd6\x63\x82\x71\x1d\x80\x74\xca\xf6\xe2\x02\x6b\xd9\x5a", 0 }, + /* Anchor: 84 IdenTrust_Root_X3.der serial: #{a.serial.to_s} + O=Digital Signature Trust Co.,CN=DST Root CA X3 + */ + { 846, "\x30\x82\x03\x4a\x30\x82\x02\x32\xa0\x03\x02\x01\x02\x02\x10\x44\xaf\xb0\x80\xd6\xa3\x27\xba\x89\x30\x39\x86\x2e\xf8\x40\x6b\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x3f\x31\x24\x30\x22\x06\x03\x55\x04\x0a\x13\x1b\x44\x69\x67\x69\x74\x61\x6c\x20\x53\x69\x67\x6e\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6f\x2e\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0e\x44\x53\x54\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x58\x33\x30\x1e\x17\x0d\x30\x30\x30\x39\x33\x30\x32\x31\x31\x32\x31\x39\x5a\x17\x0d\x32\x31\x30\x39\x33\x30\x31\x34\x30\x31\x31\x35\x5a\x30\x3f\x31\x24\x30\x22\x06\x03\x55\x04\x0a\x13\x1b\x44\x69\x67\x69\x74\x61\x6c\x20\x53\x69\x67\x6e\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6f\x2e\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0e\x44\x53\x54\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x58\x33\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xdf\xaf\xe9\x97\x50\x08\x83\x57\xb4\xcc\x62\x65\xf6\x90\x82\xec\xc7\xd3\x2c\x6b\x30\xca\x5b\xec\xd9\xc3\x7d\xc7\x40\xc1\x18\x14\x8b\xe0\xe8\x33\x76\x49\x2a\xe3\x3f\x21\x49\x93\xac\x4e\x0e\xaf\x3e\x48\xcb\x65\xee\xfc\xd3\x21\x0f\x65\xd2\x2a\xd9\x32\x8f\x8c\xe5\xf7\x77\xb0\x12\x7b\xb5\x95\xc0\x89\xa3\xa9\xba\xed\x73\x2e\x7a\x0c\x06\x32\x83\xa2\x7e\x8a\x14\x30\xcd\x11\xa0\xe1\x2a\x38\xb9\x79\x0a\x31\xfd\x50\xbd\x80\x65\xdf\xb7\x51\x63\x83\xc8\xe2\x88\x61\xea\x4b\x61\x81\xec\x52\x6b\xb9\xa2\xe2\x4b\x1a\x28\x9f\x48\xa3\x9e\x0c\xda\x09\x8e\x3e\x17\x2e\x1e\xdd\x20\xdf\x5b\xc6\x2a\x8a\xab\x2e\xbd\x70\xad\xc5\x0b\x1a\x25\x90\x74\x72\xc5\x7b\x6a\xab\x34\xd6\x30\x89\xff\xe5\x68\x13\x7b\x54\x0b\xc8\xd6\xae\xec\x5a\x9c\x92\x1e\x3d\x64\xb3\x8c\xc6\xdf\xbf\xc9\x41\x70\xec\x16\x72\xd5\x26\xec\x38\x55\x39\x43\xd0\xfc\xfd\x18\x5c\x40\xf1\x97\xeb\xd5\x9a\x9b\x8d\x1d\xba\xda\x25\xb9\xc6\xd8\xdf\xc1\x15\x02\x3a\xab\xda\x6e\xf1\x3e\x2e\xf5\x5c\x08\x9c\x3c\xd6\x83\x69\xe4\x10\x9b\x19\x2a\xb6\x29\x57\xe3\xe5\x3d\x9b\x9f\xf0\x02\x5d\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xc4\xa7\xb1\xa4\x7b\x2c\x71\xfa\xdb\xe1\x4b\x90\x75\xff\xc4\x15\x60\x85\x89\x10\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xa3\x1a\x2c\x9b\x17\x00\x5c\xa9\x1e\xee\x28\x66\x37\x3a\xbf\x83\xc7\x3f\x4b\xc3\x09\xa0\x95\x20\x5d\xe3\xd9\x59\x44\xd2\x3e\x0d\x3e\xbd\x8a\x4b\xa0\x74\x1f\xce\x10\x82\x9c\x74\x1a\x1d\x7e\x98\x1a\xdd\xcb\x13\x4b\xb3\x20\x44\xe4\x91\xe9\xcc\xfc\x7d\xa5\xdb\x6a\xe5\xfe\xe6\xfd\xe0\x4e\xdd\xb7\x00\x3a\xb5\x70\x49\xaf\xf2\xe5\xeb\x02\xf1\xd1\x02\x8b\x19\xcb\x94\x3a\x5e\x48\xc4\x18\x1e\x58\x19\x5f\x1e\x02\x5a\xf0\x0c\xf1\xb1\xad\xa9\xdc\x59\x86\x8b\x6e\xe9\x91\xf5\x86\xca\xfa\xb9\x66\x33\xaa\x59\x5b\xce\xe2\xa7\x16\x73\x47\xcb\x2b\xcc\x99\xb0\x37\x48\xcf\xe3\x56\x4b\xf5\xcf\x0f\x0c\x72\x32\x87\xc6\xf0\x44\xbb\x53\x72\x6d\x43\xf5\x26\x48\x9a\x52\x67\xb7\x58\xab\xfe\x67\x76\x71\x78\xdb\x0d\xa2\x56\x14\x13\x39\x24\x31\x85\xa2\xa8\x02\x5a\x30\x47\xe1\xdd\x50\x07\xbc\x02\x09\x90\x00\xeb\x64\x63\x60\x9b\x16\xbc\x88\xc9\x12\xe6\xd2\x7d\x91\x8b\xf9\x3d\x32\x8d\x65\xb4\xe9\x7c\xb1\x57\x76\xea\xc5\xb6\x28\x39\xbf\x15\x65\x1c\xc8\xf6\x77\x96\x6a\x0a\x8d\x77\x0b\xd8\x91\x0b\x04\x8e\x07\xdb\x29\xb6\x0a\xee\x9d\x82\x35\x35\x10", 0 }, + /* Anchor: 85 IdenTrust_Root_X6.der serial: #{a.serial.to_s} + C=US,O=Digital Signature Trust,OU=DST ACES,CN=DST ACES CA X6 + */ + { 1037, "\x30\x82\x04\x09\x30\x82\x02\xf1\xa0\x03\x02\x01\x02\x02\x10\x0d\x5e\x99\x0a\xd6\x9d\xb7\x78\xec\xd8\x07\x56\x3b\x86\x15\xd9\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x5b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1e\x06\x03\x55\x04\x0a\x13\x17\x44\x69\x67\x69\x74\x61\x6c\x20\x53\x69\x67\x6e\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x31\x11\x30\x0f\x06\x03\x55\x04\x0b\x13\x08\x44\x53\x54\x20\x41\x43\x45\x53\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0e\x44\x53\x54\x20\x41\x43\x45\x53\x20\x43\x41\x20\x58\x36\x30\x1e\x17\x0d\x30\x33\x31\x31\x32\x30\x32\x31\x31\x39\x35\x38\x5a\x17\x0d\x31\x37\x31\x31\x32\x30\x32\x31\x31\x39\x35\x38\x5a\x30\x5b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1e\x06\x03\x55\x04\x0a\x13\x17\x44\x69\x67\x69\x74\x61\x6c\x20\x53\x69\x67\x6e\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x31\x11\x30\x0f\x06\x03\x55\x04\x0b\x13\x08\x44\x53\x54\x20\x41\x43\x45\x53\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0e\x44\x53\x54\x20\x41\x43\x45\x53\x20\x43\x41\x20\x58\x36\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xb9\x3d\xf5\x2c\xc9\x94\xdc\x75\x8a\x95\x5d\x63\xe8\x84\x77\x76\x66\xb9\x59\x91\x5c\x46\xdd\x92\x3e\x9f\xf9\x0e\x03\xb4\x3d\x61\x92\xbd\x23\x26\xb5\x63\xee\x92\xd2\x9e\xd6\x3c\xc8\x0d\x90\x5f\x64\x81\xb1\xa8\x08\x0d\x4c\xd8\xf9\xd3\x05\x28\x52\xb4\x01\x25\xc5\x95\x1c\x0c\x7e\x3e\x10\x84\x75\xcf\xc1\x19\x91\x63\xcf\xe8\xa8\x91\x88\xb9\x43\x52\xbb\x80\xb1\x55\x89\x8b\x31\xfa\xd0\xb7\x76\xbe\x41\x3d\x30\x9a\xa4\x22\x25\x17\x73\xe8\x1e\xe2\xd3\xac\x2a\xbd\x5b\x38\x21\xd5\x2a\x4b\xd7\x55\x7d\xe3\x3a\x55\xbd\xd7\x6d\x6b\x02\x57\x6b\xe6\x47\x7c\x08\xc8\x82\xba\xde\xa7\x87\x3d\xa1\x6d\xb8\x30\x56\xc2\xb3\x02\x81\x5f\x2d\xf5\xe2\x9a\x30\x18\x28\xb8\x66\xd3\xcb\x01\x96\x6f\xea\x8a\x45\x55\xd6\xe0\x9d\xff\x67\x2b\x17\x02\xa6\x4e\x1a\x6a\x11\x0b\x7e\xb7\x7b\xe7\x98\xd6\x8c\x76\x6f\xc1\x3b\xdb\x50\x93\x7e\xe5\xd0\x8e\x1f\x37\xb8\xbd\xba\xc6\x9f\x6c\xe9\x7c\x33\xf2\x32\x3c\x26\x47\xfa\x27\x24\x02\xc9\x7e\x1d\x5b\x88\x42\x13\x6a\x35\x7c\x7d\x35\xe9\x2e\x66\x91\x72\x93\xd5\x32\x26\xc4\x74\xf5\x53\xa3\xb3\x5d\x9a\xf6\x09\xcb\x02\x03\x01\x00\x01\xa3\x81\xc8\x30\x81\xc5\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\xc6\x30\x1f\x06\x03\x55\x1d\x11\x04\x18\x30\x16\x81\x14\x70\x6b\x69\x2d\x6f\x70\x73\x40\x74\x72\x75\x73\x74\x64\x73\x74\x2e\x63\x6f\x6d\x30\x62\x06\x03\x55\x1d\x20\x04\x5b\x30\x59\x30\x57\x06\x0a\x60\x86\x48\x01\x65\x03\x02\x01\x01\x01\x30\x49\x30\x47\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x3b\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x74\x72\x75\x73\x74\x64\x73\x74\x2e\x63\x6f\x6d\x2f\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x73\x2f\x70\x6f\x6c\x69\x63\x79\x2f\x41\x43\x45\x53\x2d\x69\x6e\x64\x65\x78\x2e\x68\x74\x6d\x6c\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x09\x72\x06\x4e\x18\x43\x0f\xe5\xd6\xcc\xc3\x6a\x8b\x31\x7b\x78\x8f\xa8\x83\xb8\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xa3\xd8\x8e\xd6\xb2\xdb\xce\x05\xe7\x32\xcd\x01\xd3\x04\x03\xe5\x76\xe4\x56\x2b\x9c\x99\x90\xe8\x08\x30\x6c\xdf\x7d\x3d\xee\xe5\xbf\xb5\x24\x40\x84\x49\xe1\xd1\x28\xae\xc4\xc2\x3a\x53\x30\x88\xf1\xf5\x77\x6e\x51\xca\xfa\xff\x99\xaf\x24\x5f\x1b\xa0\xfd\xf2\xac\x84\xca\xdf\xa9\xf0\x5f\x04\x2e\xad\x16\xbf\x21\x97\x10\x81\x3d\xe3\xff\x87\x8d\x32\xdc\x94\xe5\x47\x8a\x5e\x6a\x13\xc9\x94\x95\x3d\xd2\xee\xc8\x34\x95\xd0\x80\xd4\xad\x32\x08\x80\x54\x3c\xe0\xbd\x52\x53\xd7\x52\x7c\xb2\x69\x3f\x7f\x7a\xcf\x6a\x74\xca\xfa\x04\x2a\x9c\x4c\x5a\x06\xa5\xe9\x20\xad\x45\x66\x0f\x69\xf1\xdd\xbf\xe9\xe3\x32\x8b\xfa\xe0\xc1\x86\x4d\x72\x3c\x2e\xd8\x93\x78\x0a\x2a\xf8\xd8\xd2\x27\x3d\x19\x89\x5f\x5a\x7b\x8a\x3b\xcc\x0c\xda\x51\xae\xc7\x0b\xf7\x2b\xb0\x37\x05\xec\xbc\x57\x23\xe2\x38\xd2\x9b\x68\xf3\x56\x12\x88\x4f\x42\x7c\xb8\x31\xc4\xb5\xdb\xe4\xc8\x21\x34\xe9\x48\x11\x35\xee\xfa\xc7\x92\x57\xc5\x9f\x34\xe4\xc7\xf6\xf7\x0e\x0b\x4c\x9c\x68\x78\x7b\x71\x31\xc7\xeb\x1e\xe0\x67\x41\xf3\xb7\xa0\xa7\xcd\xe5\x7a\x33\x36\x6a\xfa\x9a\x2b", 0 }, + /* Anchor: 86 ipscaCAC.der serial: #{a.serial.to_s} + C=ES,ST=Barcelona,L=Barcelona,O=IPS Internet publishing Services s.l.,O=ips@mail.ips.es C.I.F. B-60929452,OU=IPS CA Chained CAs Certification Authority,CN=IPS CA Chained CAs Certification Authority,1.2.840.113549.1.9.1=#160F697073406D61696C2E6970732E6573 + */ + { 2051, "\x30\x82\x07\xff\x30\x82\x07\x68\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x82\x01\x1c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x12\x30\x10\x06\x03\x55\x04\x08\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x2e\x30\x2c\x06\x03\x55\x04\x0a\x13\x25\x49\x50\x53\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x70\x75\x62\x6c\x69\x73\x68\x69\x6e\x67\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x73\x2e\x6c\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0a\x14\x22\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x20\x43\x2e\x49\x2e\x46\x2e\x20\x20\x42\x2d\x36\x30\x39\x32\x39\x34\x35\x32\x31\x33\x30\x31\x06\x03\x55\x04\x0b\x13\x2a\x49\x50\x53\x20\x43\x41\x20\x43\x68\x61\x69\x6e\x65\x64\x20\x43\x41\x73\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x33\x30\x31\x06\x03\x55\x04\x03\x13\x2a\x49\x50\x53\x20\x43\x41\x20\x43\x68\x61\x69\x6e\x65\x64\x20\x43\x41\x73\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x1e\x17\x0d\x30\x31\x31\x32\x33\x31\x31\x31\x31\x34\x35\x34\x5a\x17\x0d\x32\x35\x31\x32\x32\x39\x31\x31\x31\x34\x35\x34\x5a\x30\x82\x01\x1c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x12\x30\x10\x06\x03\x55\x04\x08\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x2e\x30\x2c\x06\x03\x55\x04\x0a\x13\x25\x49\x50\x53\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x70\x75\x62\x6c\x69\x73\x68\x69\x6e\x67\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x73\x2e\x6c\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0a\x14\x22\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x20\x43\x2e\x49\x2e\x46\x2e\x20\x20\x42\x2d\x36\x30\x39\x32\x39\x34\x35\x32\x31\x33\x30\x31\x06\x03\x55\x04\x0b\x13\x2a\x49\x50\x53\x20\x43\x41\x20\x43\x68\x61\x69\x6e\x65\x64\x20\x43\x41\x73\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x33\x30\x31\x06\x03\x55\x04\x03\x13\x2a\x49\x50\x53\x20\x43\x41\x20\x43\x68\x61\x69\x6e\x65\x64\x20\x43\x41\x73\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xa9\x39\x96\x49\x88\x70\x33\x28\x7c\xe8\x57\xdc\x48\x92\x2d\xde\x2d\x7a\x79\xe9\x48\xf1\x15\xe8\x67\x63\xe7\x3e\x0e\x1d\x67\x52\x25\x4e\xd2\xdf\xff\xbe\x61\x8c\x3f\xa0\x76\x2d\x31\x5f\xc7\xd1\x41\x29\x10\x62\x91\x87\x16\xee\xb6\x88\x71\x20\xe2\xeb\x63\xab\xd2\xc0\x06\xe5\x45\x20\x1b\x8a\xee\x18\xb1\x3b\x5e\xd0\xa7\x9f\x1e\x31\x8e\x06\xc5\x67\x8b\x53\x8d\xd8\x22\xe5\x68\x7d\x19\x58\x5f\x3f\xb3\xa8\xf5\xa8\x62\xf0\x4a\x9a\xa3\xe6\xa5\x15\xb8\x6f\x07\xa2\xc3\xdf\x16\x59\xa8\xcd\xa3\xf5\xc9\x83\xf0\x6c\xd8\x01\x02\x03\x01\x00\x01\xa3\x82\x04\x4b\x30\x82\x04\x47\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x07\x94\xa8\x70\x6c\x0a\xa4\xee\x99\xb8\x55\xdd\x2e\x4c\x45\x77\xf6\x36\xaf\xb9\x30\x82\x01\x4e\x06\x03\x55\x1d\x23\x04\x82\x01\x45\x30\x82\x01\x41\x80\x14\x07\x94\xa8\x70\x6c\x0a\xa4\xee\x99\xb8\x55\xdd\x2e\x4c\x45\x77\xf6\x36\xaf\xb9\xa1\x82\x01\x24\xa4\x82\x01\x20\x30\x82\x01\x1c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x12\x30\x10\x06\x03\x55\x04\x08\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x2e\x30\x2c\x06\x03\x55\x04\x0a\x13\x25\x49\x50\x53\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x70\x75\x62\x6c\x69\x73\x68\x69\x6e\x67\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x73\x2e\x6c\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0a\x14\x22\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x20\x43\x2e\x49\x2e\x46\x2e\x20\x20\x42\x2d\x36\x30\x39\x32\x39\x34\x35\x32\x31\x33\x30\x31\x06\x03\x55\x04\x0b\x13\x2a\x49\x50\x53\x20\x43\x41\x20\x43\x68\x61\x69\x6e\x65\x64\x20\x43\x41\x73\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x33\x30\x31\x06\x03\x55\x04\x03\x13\x2a\x49\x50\x53\x20\x43\x41\x20\x43\x68\x61\x69\x6e\x65\x64\x20\x43\x41\x73\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x82\x01\x00\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0c\x06\x03\x55\x1d\x0f\x04\x05\x03\x03\x07\xff\x80\x30\x6b\x06\x03\x55\x1d\x25\x04\x64\x30\x62\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x02\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x03\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x04\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x08\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x01\x15\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x01\x16\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x0a\x03\x01\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x0a\x03\x04\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x1a\x06\x03\x55\x1d\x11\x04\x13\x30\x11\x81\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x1a\x06\x03\x55\x1d\x12\x04\x13\x30\x11\x81\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x43\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x0d\x04\x36\x16\x34\x43\x68\x61\x69\x6e\x65\x64\x20\x43\x41\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x69\x73\x73\x75\x65\x64\x20\x62\x79\x20\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x30\x2a\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x02\x04\x1d\x16\x1b\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x30\x38\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x04\x04\x2b\x16\x29\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x69\x70\x73\x32\x30\x30\x32\x43\x41\x43\x2e\x63\x72\x6c\x30\x3d\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x03\x04\x30\x16\x2e\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x72\x65\x76\x6f\x63\x61\x74\x69\x6f\x6e\x43\x41\x43\x2e\x68\x74\x6d\x6c\x3f\x30\x3a\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x07\x04\x2d\x16\x2b\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x72\x65\x6e\x65\x77\x61\x6c\x43\x41\x43\x2e\x68\x74\x6d\x6c\x3f\x30\x38\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x08\x04\x2b\x16\x29\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x70\x6f\x6c\x69\x63\x79\x43\x41\x43\x2e\x68\x74\x6d\x6c\x30\x6f\x06\x03\x55\x1d\x1f\x04\x68\x30\x66\x30\x2f\xa0\x2d\xa0\x2b\x86\x29\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x69\x70\x73\x32\x30\x30\x32\x43\x41\x43\x2e\x63\x72\x6c\x30\x33\xa0\x31\xa0\x2f\x86\x2d\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x62\x61\x63\x6b\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x69\x70\x73\x32\x30\x30\x32\x43\x41\x43\x2e\x63\x72\x6c\x30\x2f\x06\x08\x2b\x06\x01\x05\x05\x07\x01\x01\x04\x23\x30\x21\x30\x1f\x06\x08\x2b\x06\x01\x05\x05\x07\x30\x01\x86\x13\x68\x74\x74\x70\x3a\x2f\x2f\x6f\x63\x73\x70\x2e\x69\x70\x73\x2e\x65\x73\x2f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x4e\x24\x6f\x63\x69\xeb\xa3\xd0\x7a\x40\xd8\x13\x3a\x0a\x23\x59\x2a\xd7\x30\xaa\x57\x1d\xae\xa1\x2d\x1c\x4b\xd8\x66\x4f\x10\x58\x34\xe7\xdc\x76\x11\x1b\x37\xa7\x0e\xd1\x94\x92\x59\x72\xdb\xa9\x65\xa9\xb4\xeb\x3b\xc1\x9c\x67\xd0\x2f\x86\x61\x7a\xf5\xe5\xe9\x24\xfa\x44\x00\x26\x3a\x29\x2e\x8f\xc9\x1b\x88\x54\xa0\xba\x38\xc2\x25\x8d\x70\xbf\x9f\xfb\xcf\x38\x01\x5b\x37\x4b\x37\x3a\x8a\x0b\x5f\x29\xd5\x3d\x8a\x65\xaf\x01\xda\xa2\x9f\x40\x2a\xb3\x57\xf2\x77\x7e\x02\x3f\xef\x6e\x7e\xf5\xe9\x2a\x28\xd2\xe2\x13\x94", 0 }, + /* Anchor: 87 ipscaCLASE1.der serial: #{a.serial.to_s} + C=ES,ST=Barcelona,L=Barcelona,O=IPS Internet publishing Services s.l.,O=ips@mail.ips.es C.I.F. B-60929452,OU=IPS CA CLASE1 Certification Authority,CN=IPS CA CLASE1 Certification Authority,1.2.840.113549.1.9.1=#160F697073406D61696C2E6970732E6573 + */ + { 2038, "\x30\x82\x07\xf2\x30\x82\x07\x5b\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x82\x01\x12\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x12\x30\x10\x06\x03\x55\x04\x08\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x2e\x30\x2c\x06\x03\x55\x04\x0a\x13\x25\x49\x50\x53\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x70\x75\x62\x6c\x69\x73\x68\x69\x6e\x67\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x73\x2e\x6c\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0a\x14\x22\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x20\x43\x2e\x49\x2e\x46\x2e\x20\x20\x42\x2d\x36\x30\x39\x32\x39\x34\x35\x32\x31\x2e\x30\x2c\x06\x03\x55\x04\x0b\x13\x25\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x31\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x2e\x30\x2c\x06\x03\x55\x04\x03\x13\x25\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x31\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x1e\x17\x0d\x30\x31\x31\x32\x33\x31\x31\x31\x31\x31\x30\x33\x5a\x17\x0d\x32\x35\x31\x32\x32\x39\x31\x31\x31\x31\x30\x33\x5a\x30\x82\x01\x12\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x12\x30\x10\x06\x03\x55\x04\x08\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x2e\x30\x2c\x06\x03\x55\x04\x0a\x13\x25\x49\x50\x53\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x70\x75\x62\x6c\x69\x73\x68\x69\x6e\x67\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x73\x2e\x6c\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0a\x14\x22\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x20\x43\x2e\x49\x2e\x46\x2e\x20\x20\x42\x2d\x36\x30\x39\x32\x39\x34\x35\x32\x31\x2e\x30\x2c\x06\x03\x55\x04\x0b\x13\x25\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x31\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x2e\x30\x2c\x06\x03\x55\x04\x03\x13\x25\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x31\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xe7\x9f\x91\xef\xeb\xe8\x16\xe1\x74\xbc\x89\x13\xa1\xd7\x6e\x47\xc6\x5f\x3f\x12\x94\xe6\xef\xe1\x33\xe1\xab\x82\xab\x9f\x03\x01\xe6\x74\x6f\x8a\x17\x97\xcf\x57\x2f\x0c\x76\x2e\xe6\x6e\xa7\xca\xda\xf7\x8b\x14\x15\x40\x0d\xb3\x6a\xd9\xed\xbe\xb3\x6a\xbc\x02\x2d\x1c\x85\x2d\xef\x97\xff\xcf\x97\xda\xeb\x47\x5d\x1e\x53\xbf\x5d\x54\xde\x27\x74\x63\x19\x7e\x95\xd4\x31\x96\xe5\xcf\x4f\xca\xab\x75\x2f\x93\x90\x2c\x59\x4c\x1f\xbf\x56\x28\x90\x88\x62\xe1\x13\x1e\x06\xd3\x82\x56\xfd\xe3\x2d\x25\x75\xac\x3b\x22\x6a\x9f\x02\x03\x01\x00\x01\xa3\x82\x04\x52\x30\x82\x04\x4e\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x6d\x5b\xa3\x01\x8e\x61\x37\x9d\x04\x78\xb6\xaf\x9b\x96\x1d\x02\x41\xe5\xdb\x79\x30\x82\x01\x44\x06\x03\x55\x1d\x23\x04\x82\x01\x3b\x30\x82\x01\x37\x80\x14\x6d\x5b\xa3\x01\x8e\x61\x37\x9d\x04\x78\xb6\xaf\x9b\x96\x1d\x02\x41\xe5\xdb\x79\xa1\x82\x01\x1a\xa4\x82\x01\x16\x30\x82\x01\x12\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x12\x30\x10\x06\x03\x55\x04\x08\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x2e\x30\x2c\x06\x03\x55\x04\x0a\x13\x25\x49\x50\x53\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x70\x75\x62\x6c\x69\x73\x68\x69\x6e\x67\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x73\x2e\x6c\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0a\x14\x22\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x20\x43\x2e\x49\x2e\x46\x2e\x20\x20\x42\x2d\x36\x30\x39\x32\x39\x34\x35\x32\x31\x2e\x30\x2c\x06\x03\x55\x04\x0b\x13\x25\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x31\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x2e\x30\x2c\x06\x03\x55\x04\x03\x13\x25\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x31\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x82\x01\x00\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0c\x06\x03\x55\x1d\x0f\x04\x05\x03\x03\x07\xff\x80\x30\x6b\x06\x03\x55\x1d\x25\x04\x64\x30\x62\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x02\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x03\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x04\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x08\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x01\x15\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x01\x16\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x0a\x03\x01\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x0a\x03\x04\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x1a\x06\x03\x55\x1d\x11\x04\x13\x30\x11\x81\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x1a\x06\x03\x55\x1d\x12\x04\x13\x30\x11\x81\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x42\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x0d\x04\x35\x16\x33\x43\x4c\x41\x53\x45\x31\x20\x43\x41\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x69\x73\x73\x75\x65\x64\x20\x62\x79\x20\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x30\x2a\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x02\x04\x1d\x16\x1b\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x30\x3b\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x04\x04\x2e\x16\x2c\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x69\x70\x73\x32\x30\x30\x32\x43\x4c\x41\x53\x45\x31\x2e\x63\x72\x6c\x30\x40\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x03\x04\x33\x16\x31\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x72\x65\x76\x6f\x63\x61\x74\x69\x6f\x6e\x43\x4c\x41\x53\x45\x31\x2e\x68\x74\x6d\x6c\x3f\x30\x3d\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x07\x04\x30\x16\x2e\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x72\x65\x6e\x65\x77\x61\x6c\x43\x4c\x41\x53\x45\x31\x2e\x68\x74\x6d\x6c\x3f\x30\x3b\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x08\x04\x2e\x16\x2c\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x70\x6f\x6c\x69\x63\x79\x43\x4c\x41\x53\x45\x31\x2e\x68\x74\x6d\x6c\x30\x75\x06\x03\x55\x1d\x1f\x04\x6e\x30\x6c\x30\x32\xa0\x30\xa0\x2e\x86\x2c\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x69\x70\x73\x32\x30\x30\x32\x43\x4c\x41\x53\x45\x31\x2e\x63\x72\x6c\x30\x36\xa0\x34\xa0\x32\x86\x30\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x62\x61\x63\x6b\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x69\x70\x73\x32\x30\x30\x32\x43\x4c\x41\x53\x45\x31\x2e\x63\x72\x6c\x30\x2f\x06\x08\x2b\x06\x01\x05\x05\x07\x01\x01\x04\x23\x30\x21\x30\x1f\x06\x08\x2b\x06\x01\x05\x05\x07\x30\x01\x86\x13\x68\x74\x74\x70\x3a\x2f\x2f\x6f\x63\x73\x70\x2e\x69\x70\x73\x2e\x65\x73\x2f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x5a\x70\x47\x4c\x6c\x25\x34\xcf\x66\xce\x5f\xe8\xb2\x25\xa7\xeb\x51\xb8\xcf\x13\xee\x4a\xcc\x9c\xf6\x8c\x1d\x58\x5c\x2d\x9d\xee\x43\x32\xd8\x78\x5b\xa7\xc8\x15\xc9\xf5\x05\x42\x97\x7e\x17\x62\x20\x04\x18\xfd\xcf\x72\x11\x36\x40\xcd\x7e\x81\xe1\x76\xc7\xb9\x8f\x67\x14\x50\x7f\x9f\x9e\x8f\x63\x8f\xc1\x0f\x13\x61\x8f\x85\x75\x66\x0a\x32\x0f\xe8\xab\x8f\xa7\xcc\xb3\xcf\xcf\x60\x0b\xea\xf2\xf9\xb9\x1f\x48\x5c\xe3\x1d\x44\x2d\x2b\x5e\x48\xfe\x34\x40\x1d\xfc\x89\xcb\x0c\x14\xaf\x0b\x66\x92\x56\x48\x5f\x41\x39\x3a", 0 }, + /* Anchor: 88 ipscaCLASE3.der serial: #{a.serial.to_s} + C=ES,ST=Barcelona,L=Barcelona,O=IPS Internet publishing Services s.l.,O=ips@mail.ips.es C.I.F. B-60929452,OU=IPS CA CLASE3 Certification Authority,CN=IPS CA CLASE3 Certification Authority,1.2.840.113549.1.9.1=#160F697073406D61696C2E6970732E6573 + */ + { 2038, "\x30\x82\x07\xf2\x30\x82\x07\x5b\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x82\x01\x12\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x12\x30\x10\x06\x03\x55\x04\x08\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x2e\x30\x2c\x06\x03\x55\x04\x0a\x13\x25\x49\x50\x53\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x70\x75\x62\x6c\x69\x73\x68\x69\x6e\x67\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x73\x2e\x6c\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0a\x14\x22\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x20\x43\x2e\x49\x2e\x46\x2e\x20\x20\x42\x2d\x36\x30\x39\x32\x39\x34\x35\x32\x31\x2e\x30\x2c\x06\x03\x55\x04\x0b\x13\x25\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x33\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x2e\x30\x2c\x06\x03\x55\x04\x03\x13\x25\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x33\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x1e\x17\x0d\x30\x31\x31\x32\x33\x31\x31\x31\x31\x39\x33\x31\x5a\x17\x0d\x32\x35\x31\x32\x32\x39\x31\x31\x31\x39\x33\x31\x5a\x30\x82\x01\x12\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x12\x30\x10\x06\x03\x55\x04\x08\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x2e\x30\x2c\x06\x03\x55\x04\x0a\x13\x25\x49\x50\x53\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x70\x75\x62\x6c\x69\x73\x68\x69\x6e\x67\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x73\x2e\x6c\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0a\x14\x22\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x20\x43\x2e\x49\x2e\x46\x2e\x20\x20\x42\x2d\x36\x30\x39\x32\x39\x34\x35\x32\x31\x2e\x30\x2c\x06\x03\x55\x04\x0b\x13\x25\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x33\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x2e\x30\x2c\x06\x03\x55\x04\x03\x13\x25\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x33\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xbd\xed\x90\x85\x82\xf1\xa0\xdd\x8f\xdc\x35\x68\xe1\x7c\x3e\xe8\x6c\x9b\xda\xf0\xe3\x7f\x3b\xc1\x25\x1b\xc7\xf9\x61\x48\x5c\xed\xca\x22\xd0\xb5\x74\x99\x36\x5b\xb8\x85\x9e\xc6\x49\x9d\xbe\xb9\x43\xa3\x43\x2b\x18\x70\x7d\x0e\x17\x9c\xbb\x81\x48\xfa\x8c\x54\x9e\x84\x1c\x1f\xbe\x23\x5a\x76\xa6\x0d\x23\xed\x83\xad\x79\xcf\xbe\xa3\x7c\xac\x4b\xac\xdf\xd6\xbd\x35\x1d\x28\x7c\x8b\xce\x7e\x01\xc1\x9c\x80\xb3\xb8\x67\xbf\x70\xf6\x3b\x44\x1a\x54\x9d\xac\x58\x42\x2d\x48\xc9\x25\x21\x2c\x5d\xdc\xd2\x6e\x41\x05\xae\x43\x02\x03\x01\x00\x01\xa3\x82\x04\x52\x30\x82\x04\x4e\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xfb\xa3\x8c\xf7\x67\x8b\x40\xaa\x4d\x36\xaf\x30\x80\xea\x9a\x3b\xe0\x2f\x68\xe8\x30\x82\x01\x44\x06\x03\x55\x1d\x23\x04\x82\x01\x3b\x30\x82\x01\x37\x80\x14\xfb\xa3\x8c\xf7\x67\x8b\x40\xaa\x4d\x36\xaf\x30\x80\xea\x9a\x3b\xe0\x2f\x68\xe8\xa1\x82\x01\x1a\xa4\x82\x01\x16\x30\x82\x01\x12\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x12\x30\x10\x06\x03\x55\x04\x08\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x2e\x30\x2c\x06\x03\x55\x04\x0a\x13\x25\x49\x50\x53\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x70\x75\x62\x6c\x69\x73\x68\x69\x6e\x67\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x73\x2e\x6c\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0a\x14\x22\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x20\x43\x2e\x49\x2e\x46\x2e\x20\x20\x42\x2d\x36\x30\x39\x32\x39\x34\x35\x32\x31\x2e\x30\x2c\x06\x03\x55\x04\x0b\x13\x25\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x33\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x2e\x30\x2c\x06\x03\x55\x04\x03\x13\x25\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x33\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x82\x01\x00\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0c\x06\x03\x55\x1d\x0f\x04\x05\x03\x03\x07\xff\x80\x30\x6b\x06\x03\x55\x1d\x25\x04\x64\x30\x62\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x02\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x03\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x04\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x08\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x01\x15\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x01\x16\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x0a\x03\x01\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x0a\x03\x04\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x1a\x06\x03\x55\x1d\x11\x04\x13\x30\x11\x81\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x1a\x06\x03\x55\x1d\x12\x04\x13\x30\x11\x81\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x42\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x0d\x04\x35\x16\x33\x43\x4c\x41\x53\x45\x33\x20\x43\x41\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x69\x73\x73\x75\x65\x64\x20\x62\x79\x20\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x30\x2a\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x02\x04\x1d\x16\x1b\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x30\x3b\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x04\x04\x2e\x16\x2c\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x69\x70\x73\x32\x30\x30\x32\x43\x4c\x41\x53\x45\x33\x2e\x63\x72\x6c\x30\x40\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x03\x04\x33\x16\x31\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x72\x65\x76\x6f\x63\x61\x74\x69\x6f\x6e\x43\x4c\x41\x53\x45\x33\x2e\x68\x74\x6d\x6c\x3f\x30\x3d\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x07\x04\x30\x16\x2e\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x72\x65\x6e\x65\x77\x61\x6c\x43\x4c\x41\x53\x45\x33\x2e\x68\x74\x6d\x6c\x3f\x30\x3b\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x08\x04\x2e\x16\x2c\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x70\x6f\x6c\x69\x63\x79\x43\x4c\x41\x53\x45\x33\x2e\x68\x74\x6d\x6c\x30\x75\x06\x03\x55\x1d\x1f\x04\x6e\x30\x6c\x30\x32\xa0\x30\xa0\x2e\x86\x2c\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x69\x70\x73\x32\x30\x30\x32\x43\x4c\x41\x53\x45\x33\x2e\x63\x72\x6c\x30\x36\xa0\x34\xa0\x32\x86\x30\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x62\x61\x63\x6b\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x69\x70\x73\x32\x30\x30\x32\x43\x4c\x41\x53\x45\x33\x2e\x63\x72\x6c\x30\x2f\x06\x08\x2b\x06\x01\x05\x05\x07\x01\x01\x04\x23\x30\x21\x30\x1f\x06\x08\x2b\x06\x01\x05\x05\x07\x30\x01\x86\x13\x68\x74\x74\x70\x3a\x2f\x2f\x6f\x63\x73\x70\x2e\x69\x70\x73\x2e\x65\x73\x2f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x22\xbb\x61\x6e\x47\xc3\x28\x42\x56\x30\xdd\x0b\x45\x73\xf0\x48\xec\x38\x24\x51\x47\x92\x20\xce\x3d\x26\x83\x14\xd0\x7d\xda\xe1\x8f\x89\x6d\x0c\x50\xe2\xaf\xe7\xeb\x20\x1b\x12\xe3\x04\x4d\x4c\xaa\xa1\xbf\xc7\x99\x2f\xcd\x90\xb2\x6a\xba\xbd\xd1\xbc\x60\x6c\x78\x35\xe0\xc4\xdc\x9e\x3c\x68\xc5\x73\xde\xc8\x4c\xd5\x9f\xe5\x7d\x7e\xe0\x25\xed\x05\xff\x93\x4c\xa3\x44\x32\x0d\x54\xa4\xf6\xc2\xcf\xef\x44\x92\x3c\xd3\x71\x88\xf5\xe6\xd8\xcb\x6c\x0a\x7f\x9a\x62\xcb\x66\x60\x8e\x57\xb7\x02\x1a\xe5\xc6\x49\x30\x4d\xcc", 0 }, + /* Anchor: 89 ipscaCLASEA1.der serial: #{a.serial.to_s} + C=ES,ST=Barcelona,L=Barcelona,O=IPS Internet publishing Services s.l.,O=ips@mail.ips.es C.I.F. B-60929452,OU=IPS CA CLASEA1 Certification Authority,CN=IPS CA CLASEA1 Certification Authority,1.2.840.113549.1.9.1=#160F697073406D61696C2E6970732E6573 + */ + { 2051, "\x30\x82\x07\xff\x30\x82\x07\x68\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x82\x01\x14\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x12\x30\x10\x06\x03\x55\x04\x08\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x2e\x30\x2c\x06\x03\x55\x04\x0a\x13\x25\x49\x50\x53\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x70\x75\x62\x6c\x69\x73\x68\x69\x6e\x67\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x73\x2e\x6c\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0a\x14\x22\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x20\x43\x2e\x49\x2e\x46\x2e\x20\x20\x42\x2d\x36\x30\x39\x32\x39\x34\x35\x32\x31\x2f\x30\x2d\x06\x03\x55\x04\x0b\x13\x26\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x41\x31\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x2f\x30\x2d\x06\x03\x55\x04\x03\x13\x26\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x41\x31\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x1e\x17\x0d\x30\x31\x31\x32\x33\x31\x31\x31\x32\x31\x34\x31\x5a\x17\x0d\x32\x35\x31\x32\x32\x39\x31\x31\x32\x31\x34\x31\x5a\x30\x82\x01\x14\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x12\x30\x10\x06\x03\x55\x04\x08\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x2e\x30\x2c\x06\x03\x55\x04\x0a\x13\x25\x49\x50\x53\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x70\x75\x62\x6c\x69\x73\x68\x69\x6e\x67\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x73\x2e\x6c\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0a\x14\x22\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x20\x43\x2e\x49\x2e\x46\x2e\x20\x20\x42\x2d\x36\x30\x39\x32\x39\x34\x35\x32\x31\x2f\x30\x2d\x06\x03\x55\x04\x0b\x13\x26\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x41\x31\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x2f\x30\x2d\x06\x03\x55\x04\x03\x13\x26\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x41\x31\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xcf\x20\xf3\xd0\x60\x48\xaa\x02\xc4\x15\xd9\xe4\x2f\x8d\x9e\x55\x11\x2d\x29\xcc\x51\x66\x68\x00\x65\xda\x14\x55\x9f\xea\xae\xdf\xeb\xdb\x8d\xd6\x75\xda\x51\xf4\xc4\xcc\xfb\x2d\xbd\x35\x1f\x13\xb7\xe9\x66\x61\x7c\x94\x40\xf3\xfb\x60\x2f\x8c\x18\x34\xf3\xa8\x55\x9e\xb6\xb4\x6f\x40\x0f\x03\x45\x67\x6a\x72\x72\x5b\x66\x48\x96\x42\x85\x18\xc0\x81\xe1\x62\x6a\x87\xb2\x41\xee\x2e\x39\x8c\x84\xd5\x5e\xd8\x4f\x57\x6b\xec\x8e\x52\x8c\xf7\xb3\xe7\x9e\x18\xa6\xcf\xc1\x5b\xaf\xe4\x59\x72\xcc\xfa\xf6\xf4\x69\xb4\xca\xb1\x02\x03\x01\x00\x01\xa3\x82\x04\x5b\x30\x82\x04\x57\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x2f\xcc\xec\x6c\x67\xbe\x4f\xf8\xaa\x3c\x88\x8d\x12\xfb\xc7\x9d\x4c\x5b\xf4\x5e\x30\x82\x01\x46\x06\x03\x55\x1d\x23\x04\x82\x01\x3d\x30\x82\x01\x39\x80\x14\x2f\xcc\xec\x6c\x67\xbe\x4f\xf8\xaa\x3c\x88\x8d\x12\xfb\xc7\x9d\x4c\x5b\xf4\x5e\xa1\x82\x01\x1c\xa4\x82\x01\x18\x30\x82\x01\x14\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x12\x30\x10\x06\x03\x55\x04\x08\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x2e\x30\x2c\x06\x03\x55\x04\x0a\x13\x25\x49\x50\x53\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x70\x75\x62\x6c\x69\x73\x68\x69\x6e\x67\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x73\x2e\x6c\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0a\x14\x22\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x20\x43\x2e\x49\x2e\x46\x2e\x20\x20\x42\x2d\x36\x30\x39\x32\x39\x34\x35\x32\x31\x2f\x30\x2d\x06\x03\x55\x04\x0b\x13\x26\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x41\x31\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x2f\x30\x2d\x06\x03\x55\x04\x03\x13\x26\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x41\x31\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x82\x01\x00\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0c\x06\x03\x55\x1d\x0f\x04\x05\x03\x03\x07\xff\x80\x30\x6b\x06\x03\x55\x1d\x25\x04\x64\x30\x62\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x02\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x03\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x04\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x08\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x01\x15\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x01\x16\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x0a\x03\x01\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x0a\x03\x04\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x1a\x06\x03\x55\x1d\x11\x04\x13\x30\x11\x81\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x1a\x06\x03\x55\x1d\x12\x04\x13\x30\x11\x81\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x43\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x0d\x04\x36\x16\x34\x43\x4c\x41\x53\x45\x41\x31\x20\x43\x41\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x69\x73\x73\x75\x65\x64\x20\x62\x79\x20\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x30\x2a\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x02\x04\x1d\x16\x1b\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x30\x3c\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x04\x04\x2f\x16\x2d\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x69\x70\x73\x32\x30\x30\x32\x43\x4c\x41\x53\x45\x41\x31\x2e\x63\x72\x6c\x30\x41\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x03\x04\x34\x16\x32\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x72\x65\x76\x6f\x63\x61\x74\x69\x6f\x6e\x43\x4c\x41\x53\x45\x41\x31\x2e\x68\x74\x6d\x6c\x3f\x30\x3e\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x07\x04\x31\x16\x2f\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x72\x65\x6e\x65\x77\x61\x6c\x43\x4c\x41\x53\x45\x41\x31\x2e\x68\x74\x6d\x6c\x3f\x30\x3c\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x08\x04\x2f\x16\x2d\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x70\x6f\x6c\x69\x63\x79\x43\x4c\x41\x53\x45\x41\x31\x2e\x68\x74\x6d\x6c\x30\x77\x06\x03\x55\x1d\x1f\x04\x70\x30\x6e\x30\x33\xa0\x31\xa0\x2f\x86\x2d\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x69\x70\x73\x32\x30\x30\x32\x43\x4c\x41\x53\x45\x41\x31\x2e\x63\x72\x6c\x30\x37\xa0\x35\xa0\x33\x86\x31\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x62\x61\x63\x6b\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x69\x70\x73\x32\x30\x30\x32\x43\x4c\x41\x53\x45\x41\x31\x2e\x63\x72\x6c\x30\x2f\x06\x08\x2b\x06\x01\x05\x05\x07\x01\x01\x04\x23\x30\x21\x30\x1f\x06\x08\x2b\x06\x01\x05\x05\x07\x30\x01\x86\x13\x68\x74\x74\x70\x3a\x2f\x2f\x6f\x63\x73\x70\x2e\x69\x70\x73\x2e\x65\x73\x2f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x19\x8d\xa4\x84\x2e\x2f\xe2\x69\x5e\x9e\xa4\x5c\xcb\xc3\x27\xf2\x67\x16\x71\xaf\x3c\xb7\x80\x98\xf4\xb0\x89\x32\xa9\x48\xb7\xb8\xb9\xe7\xd0\x4d\x90\xc3\x01\xeb\xab\x57\xb0\xda\x7d\x37\x64\x21\x9d\x3a\x2b\x74\xa3\xa3\x91\xd8\x19\x26\x60\x9b\xec\x35\x1d\x30\x91\x10\x41\x3d\x18\xe5\x6e\xc9\x03\xa5\xaf\x1d\xab\x40\x16\xef\x1f\x79\x12\x78\x22\x66\x93\x8c\x8d\x17\xcf\x70\xdd\x25\xbc\xfa\x3b\xef\xa2\x80\x2c\x34\x97\x81\x18\xe6\x06\xb2\x9f\x60\x45\xa4\x09\xbe\xed\x9a\x44\x71\xda\x51\xfc\xe0\x8e\x1f\xcd\x25\x34\x3a", 0 }, + /* Anchor: 90 ipscaCLASEA3.der serial: #{a.serial.to_s} + C=ES,ST=Barcelona,L=Barcelona,O=IPS Internet publishing Services s.l.,O=ips@mail.ips.es C.I.F. B-60929452,OU=IPS CA CLASEA3 Certification Authority,CN=IPS CA CLASEA3 Certification Authority,1.2.840.113549.1.9.1=#160F697073406D61696C2E6970732E6573 + */ + { 2051, "\x30\x82\x07\xff\x30\x82\x07\x68\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x82\x01\x14\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x12\x30\x10\x06\x03\x55\x04\x08\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x2e\x30\x2c\x06\x03\x55\x04\x0a\x13\x25\x49\x50\x53\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x70\x75\x62\x6c\x69\x73\x68\x69\x6e\x67\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x73\x2e\x6c\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0a\x14\x22\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x20\x43\x2e\x49\x2e\x46\x2e\x20\x20\x42\x2d\x36\x30\x39\x32\x39\x34\x35\x32\x31\x2f\x30\x2d\x06\x03\x55\x04\x0b\x13\x26\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x41\x33\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x2f\x30\x2d\x06\x03\x55\x04\x03\x13\x26\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x41\x33\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x1e\x17\x0d\x30\x31\x31\x32\x33\x31\x31\x31\x32\x33\x35\x39\x5a\x17\x0d\x32\x35\x31\x32\x32\x39\x31\x31\x32\x33\x35\x39\x5a\x30\x82\x01\x14\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x12\x30\x10\x06\x03\x55\x04\x08\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x2e\x30\x2c\x06\x03\x55\x04\x0a\x13\x25\x49\x50\x53\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x70\x75\x62\x6c\x69\x73\x68\x69\x6e\x67\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x73\x2e\x6c\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0a\x14\x22\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x20\x43\x2e\x49\x2e\x46\x2e\x20\x20\x42\x2d\x36\x30\x39\x32\x39\x34\x35\x32\x31\x2f\x30\x2d\x06\x03\x55\x04\x0b\x13\x26\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x41\x33\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x2f\x30\x2d\x06\x03\x55\x04\x03\x13\x26\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x41\x33\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xc1\x61\xfa\x55\x94\x12\x69\xc1\x2b\x91\x7a\x75\xae\x88\x00\xbb\xef\x3c\xee\x9f\x31\x66\x30\xf4\xb1\x40\x9b\x02\x6c\x8d\xc7\x4a\x4d\x51\x25\x3e\xe8\x14\x28\xbc\x20\x3c\xb1\xf1\x8c\xed\x7d\x91\xd9\x97\x22\xa3\xd5\xcc\x63\xb1\xab\xd9\x2b\x23\x0b\xdd\xa6\x97\xdf\x05\x84\x54\x16\xba\x3a\xcb\xcc\x63\x6b\x8d\x20\xa5\xd6\x9e\x05\x71\x46\x75\x58\xf5\xf6\x64\x7b\x0b\x66\x9d\x3e\x87\x95\x3d\x3c\xb5\x39\x37\x52\x54\xbb\x16\x17\xc5\xbf\xad\xd8\x8b\x33\x2f\xe9\xf8\xfa\xd5\x81\x33\xff\xb7\x9e\x85\xa6\xef\x4c\x39\xe0\xe3\x02\x03\x01\x00\x01\xa3\x82\x04\x5b\x30\x82\x04\x57\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xfc\x9e\x85\x1a\xdc\x06\x25\x71\x21\xf0\x2f\x8b\x12\x55\xd0\xc5\x80\xee\x06\xae\x30\x82\x01\x46\x06\x03\x55\x1d\x23\x04\x82\x01\x3d\x30\x82\x01\x39\x80\x14\xfc\x9e\x85\x1a\xdc\x06\x25\x71\x21\xf0\x2f\x8b\x12\x55\xd0\xc5\x80\xee\x06\xae\xa1\x82\x01\x1c\xa4\x82\x01\x18\x30\x82\x01\x14\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x12\x30\x10\x06\x03\x55\x04\x08\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x2e\x30\x2c\x06\x03\x55\x04\x0a\x13\x25\x49\x50\x53\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x70\x75\x62\x6c\x69\x73\x68\x69\x6e\x67\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x73\x2e\x6c\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0a\x14\x22\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x20\x43\x2e\x49\x2e\x46\x2e\x20\x20\x42\x2d\x36\x30\x39\x32\x39\x34\x35\x32\x31\x2f\x30\x2d\x06\x03\x55\x04\x0b\x13\x26\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x41\x33\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x2f\x30\x2d\x06\x03\x55\x04\x03\x13\x26\x49\x50\x53\x20\x43\x41\x20\x43\x4c\x41\x53\x45\x41\x33\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x82\x01\x00\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0c\x06\x03\x55\x1d\x0f\x04\x05\x03\x03\x07\xff\x80\x30\x6b\x06\x03\x55\x1d\x25\x04\x64\x30\x62\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x02\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x03\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x04\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x08\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x01\x15\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x01\x16\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x0a\x03\x01\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x0a\x03\x04\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x1a\x06\x03\x55\x1d\x11\x04\x13\x30\x11\x81\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x1a\x06\x03\x55\x1d\x12\x04\x13\x30\x11\x81\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x43\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x0d\x04\x36\x16\x34\x43\x4c\x41\x53\x45\x41\x33\x20\x43\x41\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x69\x73\x73\x75\x65\x64\x20\x62\x79\x20\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x30\x2a\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x02\x04\x1d\x16\x1b\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x30\x3c\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x04\x04\x2f\x16\x2d\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x69\x70\x73\x32\x30\x30\x32\x43\x4c\x41\x53\x45\x41\x33\x2e\x63\x72\x6c\x30\x41\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x03\x04\x34\x16\x32\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x72\x65\x76\x6f\x63\x61\x74\x69\x6f\x6e\x43\x4c\x41\x53\x45\x41\x33\x2e\x68\x74\x6d\x6c\x3f\x30\x3e\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x07\x04\x31\x16\x2f\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x72\x65\x6e\x65\x77\x61\x6c\x43\x4c\x41\x53\x45\x41\x33\x2e\x68\x74\x6d\x6c\x3f\x30\x3c\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x08\x04\x2f\x16\x2d\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x70\x6f\x6c\x69\x63\x79\x43\x4c\x41\x53\x45\x41\x33\x2e\x68\x74\x6d\x6c\x30\x77\x06\x03\x55\x1d\x1f\x04\x70\x30\x6e\x30\x33\xa0\x31\xa0\x2f\x86\x2d\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x69\x70\x73\x32\x30\x30\x32\x43\x4c\x41\x53\x45\x41\x33\x2e\x63\x72\x6c\x30\x37\xa0\x35\xa0\x33\x86\x31\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x62\x61\x63\x6b\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x69\x70\x73\x32\x30\x30\x32\x43\x4c\x41\x53\x45\x41\x33\x2e\x63\x72\x6c\x30\x2f\x06\x08\x2b\x06\x01\x05\x05\x07\x01\x01\x04\x23\x30\x21\x30\x1f\x06\x08\x2b\x06\x01\x05\x05\x07\x30\x01\x86\x13\x68\x74\x74\x70\x3a\x2f\x2f\x6f\x63\x73\x70\x2e\x69\x70\x73\x2e\x65\x73\x2f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x18\x6f\x09\x37\x40\x9a\xd2\x94\x11\xd1\x7f\xcb\x83\x7d\xea\xb4\xa7\xe2\xd8\x93\xde\xda\x24\x6a\x75\x1b\x30\x0e\x82\xf7\x09\x39\xfe\x6d\x13\x76\xd1\x5f\xf0\x6c\xa0\xc0\xc3\x2c\x5c\xed\xe2\x4e\xae\x8c\xac\xca\xd3\xe4\x10\x5e\x30\x66\x18\xa9\x68\xa0\xa3\x69\x62\x51\x39\x91\x82\x79\x4d\x63\x33\xb9\x99\x7b\xda\x50\x3f\x37\xa8\x7d\x3f\xff\x54\xb8\xbc\xcc\xa6\x94\x03\x89\x59\x06\xf6\x08\xe3\x88\x27\xb5\x94\x28\x68\x5c\x49\x9d\xae\x4d\x1c\x77\x5e\xfa\x66\xdb\x3d\x89\x47\x6f\xc7\x3a\x83\x49\x9f\xf5\x2d\xed\x38\x3b", 0 }, + /* Anchor: 91 ipscaTimestamping.der serial: #{a.serial.to_s} + C=ES,ST=Barcelona,L=Barcelona,O=IPS Internet publishing Services s.l.,O=ips@mail.ips.es C.I.F. B-60929452,OU=IPS CA Timestamping Certification Authority,CN=IPS CA Timestamping Certification Authority,1.2.840.113549.1.9.1=#160F697073406D61696C2E6970732E6573 + */ + { 2117, "\x30\x82\x08\x41\x30\x82\x07\xaa\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x82\x01\x1e\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x12\x30\x10\x06\x03\x55\x04\x08\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x2e\x30\x2c\x06\x03\x55\x04\x0a\x13\x25\x49\x50\x53\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x70\x75\x62\x6c\x69\x73\x68\x69\x6e\x67\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x73\x2e\x6c\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0a\x14\x22\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x20\x43\x2e\x49\x2e\x46\x2e\x20\x20\x42\x2d\x36\x30\x39\x32\x39\x34\x35\x32\x31\x34\x30\x32\x06\x03\x55\x04\x0b\x13\x2b\x49\x50\x53\x20\x43\x41\x20\x54\x69\x6d\x65\x73\x74\x61\x6d\x70\x69\x6e\x67\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x34\x30\x32\x06\x03\x55\x04\x03\x13\x2b\x49\x50\x53\x20\x43\x41\x20\x54\x69\x6d\x65\x73\x74\x61\x6d\x70\x69\x6e\x67\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x1e\x17\x0d\x30\x31\x31\x32\x33\x31\x31\x31\x32\x36\x34\x33\x5a\x17\x0d\x32\x35\x31\x32\x32\x39\x31\x31\x32\x36\x34\x33\x5a\x30\x82\x01\x1e\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x12\x30\x10\x06\x03\x55\x04\x08\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x2e\x30\x2c\x06\x03\x55\x04\x0a\x13\x25\x49\x50\x53\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x70\x75\x62\x6c\x69\x73\x68\x69\x6e\x67\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x73\x2e\x6c\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0a\x14\x22\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x20\x43\x2e\x49\x2e\x46\x2e\x20\x20\x42\x2d\x36\x30\x39\x32\x39\x34\x35\x32\x31\x34\x30\x32\x06\x03\x55\x04\x0b\x13\x2b\x49\x50\x53\x20\x43\x41\x20\x54\x69\x6d\x65\x73\x74\x61\x6d\x70\x69\x6e\x67\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x34\x30\x32\x06\x03\x55\x04\x03\x13\x2b\x49\x50\x53\x20\x43\x41\x20\x54\x69\x6d\x65\x73\x74\x61\x6d\x70\x69\x6e\x67\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\xe9\x93\x76\x7f\x85\x3c\xfd\xa0\x01\xbd\x11\x2f\x46\x42\x0f\x2b\x7f\x05\x9b\xc6\x6b\xf5\x51\x71\xac\x9a\x52\x1f\x1f\x95\x27\xcc\x90\xef\x96\x3f\x8e\x51\x36\xfd\x16\x00\xce\x37\xa5\x21\x94\x46\x6b\xed\xe4\xff\xa1\x7e\xea\x9f\xd1\xa2\x9b\x38\xf3\x13\xc4\xb9\x98\xba\x65\x45\x43\xf9\xd7\xbd\x15\x9d\x94\x2e\x00\x60\xde\x98\x1a\xb9\x3c\xc9\xf5\xe1\xfc\xd6\xc4\x24\xdf\xe7\xe3\xc8\x84\x19\x12\xb4\x1c\x5c\xb3\xf5\xe2\x16\x61\x27\x60\xf2\xf0\x2d\xe4\xf0\xf3\xac\xf8\xa0\x79\x84\x9d\x45\xe2\xf6\x01\xf0\x44\xe5\x91\x02\x03\x01\x00\x01\xa3\x82\x04\x89\x30\x82\x04\x85\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x91\xd9\x42\xbc\x9c\xa9\xca\xd0\x1c\x37\x13\x52\x57\x16\xa0\x0d\x1e\x29\x1d\x3e\x30\x82\x01\x50\x06\x03\x55\x1d\x23\x04\x82\x01\x47\x30\x82\x01\x43\x80\x14\x91\xd9\x42\xbc\x9c\xa9\xca\xd0\x1c\x37\x13\x52\x57\x16\xa0\x0d\x1e\x29\x1d\x3e\xa1\x82\x01\x26\xa4\x82\x01\x22\x30\x82\x01\x1e\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x12\x30\x10\x06\x03\x55\x04\x08\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x42\x61\x72\x63\x65\x6c\x6f\x6e\x61\x31\x2e\x30\x2c\x06\x03\x55\x04\x0a\x13\x25\x49\x50\x53\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x70\x75\x62\x6c\x69\x73\x68\x69\x6e\x67\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x73\x2e\x6c\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0a\x14\x22\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x20\x43\x2e\x49\x2e\x46\x2e\x20\x20\x42\x2d\x36\x30\x39\x32\x39\x34\x35\x32\x31\x34\x30\x32\x06\x03\x55\x04\x0b\x13\x2b\x49\x50\x53\x20\x43\x41\x20\x54\x69\x6d\x65\x73\x74\x61\x6d\x70\x69\x6e\x67\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x34\x30\x32\x06\x03\x55\x04\x03\x13\x2b\x49\x50\x53\x20\x43\x41\x20\x54\x69\x6d\x65\x73\x74\x61\x6d\x70\x69\x6e\x67\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x82\x01\x00\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0c\x06\x03\x55\x1d\x0f\x04\x05\x03\x03\x07\xff\x80\x30\x6b\x06\x03\x55\x1d\x25\x04\x64\x30\x62\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x02\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x03\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x04\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x08\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x01\x15\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x01\x16\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x0a\x03\x01\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x0a\x03\x04\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x1a\x06\x03\x55\x1d\x11\x04\x13\x30\x11\x81\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x1a\x06\x03\x55\x1d\x12\x04\x13\x30\x11\x81\x0f\x69\x70\x73\x40\x6d\x61\x69\x6c\x2e\x69\x70\x73\x2e\x65\x73\x30\x48\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x0d\x04\x3b\x16\x39\x54\x69\x6d\x65\x73\x74\x61\x6d\x70\x69\x6e\x67\x20\x43\x41\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x69\x73\x73\x75\x65\x64\x20\x62\x79\x20\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x30\x2a\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x02\x04\x1d\x16\x1b\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x30\x41\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x04\x04\x34\x16\x32\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x69\x70\x73\x32\x30\x30\x32\x54\x69\x6d\x65\x73\x74\x61\x6d\x70\x69\x6e\x67\x2e\x63\x72\x6c\x30\x46\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x03\x04\x39\x16\x37\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x72\x65\x76\x6f\x63\x61\x74\x69\x6f\x6e\x54\x69\x6d\x65\x73\x74\x61\x6d\x70\x69\x6e\x67\x2e\x68\x74\x6d\x6c\x3f\x30\x43\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x07\x04\x36\x16\x34\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x72\x65\x6e\x65\x77\x61\x6c\x54\x69\x6d\x65\x73\x74\x61\x6d\x70\x69\x6e\x67\x2e\x68\x74\x6d\x6c\x3f\x30\x41\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x08\x04\x34\x16\x32\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x70\x6f\x6c\x69\x63\x79\x54\x69\x6d\x65\x73\x74\x61\x6d\x70\x69\x6e\x67\x2e\x68\x74\x6d\x6c\x30\x81\x81\x06\x03\x55\x1d\x1f\x04\x7a\x30\x78\x30\x38\xa0\x36\xa0\x34\x86\x32\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x69\x70\x73\x32\x30\x30\x32\x54\x69\x6d\x65\x73\x74\x61\x6d\x70\x69\x6e\x67\x2e\x63\x72\x6c\x30\x3c\xa0\x3a\xa0\x38\x86\x36\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x62\x61\x63\x6b\x2e\x69\x70\x73\x2e\x65\x73\x2f\x69\x70\x73\x32\x30\x30\x32\x2f\x69\x70\x73\x32\x30\x30\x32\x54\x69\x6d\x65\x73\x74\x61\x6d\x70\x69\x6e\x67\x2e\x63\x72\x6c\x30\x2f\x06\x08\x2b\x06\x01\x05\x05\x07\x01\x01\x04\x23\x30\x21\x30\x1f\x06\x08\x2b\x06\x01\x05\x05\x07\x30\x01\x86\x13\x68\x74\x74\x70\x3a\x2f\x2f\x6f\x63\x73\x70\x2e\x69\x70\x73\x2e\x65\x73\x2f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\xc4\xa3\x02\x74\x60\x01\x09\x4c\x18\x5d\x4f\x74\xd1\x6d\x73\x0c\x27\xd3\x48\x30\xb5\x4f\x11\x55\x19\x19\xc7\x23\x8b\x28\xa9\xfa\x78\x0f\x7e\x2c\x27\xf6\x9d\x92\x00\xf6\x18\xc8\x24\x00\xc5\x5f\xf8\x2d\x4c\x63\xfc\x90\x15\x5e\x27\x98\xe6\xa5\xf4\xae\xd2\x36\xb1\xb5\x25\x1f\x0e\x78\x3a\x11\x8e\x93\x38\xae\xd3\xbd\xa9\x86\xee\x1c\x3d\xd3\x5b\x8e\xff\xcb\xf6\x99\x49\x9c\x4f\xe1\xc7\x28\x70\x6a\x4f\x3a\x4b\xea\x7e\xb9\xe7\x74\xa4\x4a\x63\x45\x94\x93\xfe\xd0\x83\x96\xaa\xa4\x85\xe7\x8b\x61\xa0\xa2\x59\x13\x65\xb4", 0 }, + /* Anchor: 92 Izenpe-ca_raiz2003.crt serial: #{a.serial.to_s} + C=ES,O=IZENPE S.A. - CIF A-01337260-RMerc.Vitoria-Gasteiz T1055 F62 S8,L=Avda del Mediterraneo Etorbidea 3 - 01010 Vitoria-Gasteiz,CN=Izenpe.com,1.2.840.113549.1.9.1=#160F496E666F40697A656E70652E636F6D + */ + { 1123, "\x30\x82\x04\x5f\x30\x82\x03\x47\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xd0\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x48\x30\x46\x06\x03\x55\x04\x0a\x13\x3f\x49\x5a\x45\x4e\x50\x45\x20\x53\x2e\x41\x2e\x20\x2d\x20\x43\x49\x46\x20\x41\x2d\x30\x31\x33\x33\x37\x32\x36\x30\x2d\x52\x4d\x65\x72\x63\x2e\x56\x69\x74\x6f\x72\x69\x61\x2d\x47\x61\x73\x74\x65\x69\x7a\x20\x54\x31\x30\x35\x35\x20\x46\x36\x32\x20\x53\x38\x31\x42\x30\x40\x06\x03\x55\x04\x07\x13\x39\x41\x76\x64\x61\x20\x64\x65\x6c\x20\x4d\x65\x64\x69\x74\x65\x72\x72\x61\x6e\x65\x6f\x20\x45\x74\x6f\x72\x62\x69\x64\x65\x61\x20\x33\x20\x2d\x20\x30\x31\x30\x31\x30\x20\x56\x69\x74\x6f\x72\x69\x61\x2d\x47\x61\x73\x74\x65\x69\x7a\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x49\x7a\x65\x6e\x70\x65\x2e\x63\x6f\x6d\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x49\x6e\x66\x6f\x40\x69\x7a\x65\x6e\x70\x65\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x30\x33\x30\x31\x33\x30\x32\x33\x30\x30\x30\x30\x5a\x17\x0d\x31\x38\x30\x31\x33\x30\x32\x33\x30\x30\x30\x30\x5a\x30\x81\xd0\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x48\x30\x46\x06\x03\x55\x04\x0a\x13\x3f\x49\x5a\x45\x4e\x50\x45\x20\x53\x2e\x41\x2e\x20\x2d\x20\x43\x49\x46\x20\x41\x2d\x30\x31\x33\x33\x37\x32\x36\x30\x2d\x52\x4d\x65\x72\x63\x2e\x56\x69\x74\x6f\x72\x69\x61\x2d\x47\x61\x73\x74\x65\x69\x7a\x20\x54\x31\x30\x35\x35\x20\x46\x36\x32\x20\x53\x38\x31\x42\x30\x40\x06\x03\x55\x04\x07\x13\x39\x41\x76\x64\x61\x20\x64\x65\x6c\x20\x4d\x65\x64\x69\x74\x65\x72\x72\x61\x6e\x65\x6f\x20\x45\x74\x6f\x72\x62\x69\x64\x65\x61\x20\x33\x20\x2d\x20\x30\x31\x30\x31\x30\x20\x56\x69\x74\x6f\x72\x69\x61\x2d\x47\x61\x73\x74\x65\x69\x7a\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x49\x7a\x65\x6e\x70\x65\x2e\x63\x6f\x6d\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x49\x6e\x66\x6f\x40\x69\x7a\x65\x6e\x70\x65\x2e\x63\x6f\x6d\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xb5\x6e\xda\x02\x5d\x78\x69\xdf\x12\x16\x0f\xe0\x71\x97\xc9\xd4\x0b\x19\x32\x89\xac\xd6\x7e\x9b\x74\x7b\xaf\x2d\xf9\x0b\x7d\xfa\x56\x63\x29\x94\x9d\x13\x0d\x8e\x9a\x3e\x2a\xbe\xbf\xa8\xbd\x19\x83\x5c\xed\xe2\x5a\x95\x95\x39\x60\xe5\xdc\x91\xc9\x8c\x0c\xc5\x09\xef\x19\x10\x13\x43\x1f\xe4\x0d\x63\x06\x47\x98\xf0\x5a\x31\x81\x4e\x60\x57\x5b\x00\x55\x47\x5a\xfc\xac\xd7\x9d\x82\xdf\x4f\x21\x70\x52\x7a\xc5\x65\x86\x9a\x3b\xe5\xd9\xe3\x22\x12\x5f\x4f\xda\x74\x76\x2d\x6b\x9e\xdf\xaf\x03\x0a\xef\x9a\x93\xb8\xf7\x82\x30\x17\x68\x23\x9d\x3f\x56\xbb\x05\xfa\xfe\x45\x6d\xd7\xd9\x20\xb9\x47\x85\xf2\xa7\xc8\x87\x94\xbe\x49\x3c\x72\x43\xfd\x60\x64\x2e\xb7\xb3\xc3\x34\x0f\x74\x00\xb0\xf2\x6f\x44\x1b\xba\xbd\x91\x4c\x25\x36\x92\xf7\xda\x64\x4e\xba\x34\xb7\x66\x44\xfa\x99\x04\xf3\x26\x27\x8b\x88\x4d\xd7\xd3\x8b\x34\xb8\x85\x2a\x56\x49\x39\x32\x18\xdc\x1c\x57\xfb\x6a\x5d\x0d\xe4\x2c\xe3\xb5\x37\x27\x5d\x82\x4a\x37\x66\x7d\x10\x35\x6c\x92\x4e\x28\x94\x07\x46\x8b\x8e\x9e\x4a\x86\x57\x6e\x35\x0e\x3f\x98\x24\x12\x3e\xb0\x55\x90\x17\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xea\x56\x4f\xec\x3c\x83\xa1\x14\x88\x78\x81\xb2\x2b\x05\x22\xc0\x07\x41\x5b\x42\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x62\x9e\xe6\x13\x3c\xe1\xc3\xaa\x39\x1d\xfe\x7e\x4f\x99\x1c\x23\xeb\x78\x04\x9c\xa2\x21\x6c\xbb\xbc\x79\x4b\xb3\xf1\xbc\x74\xb6\x17\x3b\xcd\x5a\x37\xf3\x33\x83\xdd\xbc\x78\xc4\xd1\x4f\x1c\x58\x64\xbf\x1d\x77\xdb\xb0\xb0\x9e\x74\x4d\x57\xd7\xe8\xbd\x11\xe0\x3c\xb0\xeb\x08\xa4\x87\x77\xc7\x46\xb6\xad\xf6\xe7\xd7\x8b\xad\xe3\xe4\xaf\x75\x62\xca\xfb\x69\x7a\xa7\x17\x7f\x1d\x88\x08\x07\x62\x4a\xf0\x0b\x79\x2e\xc4\x70\x5b\xf4\x2d\x0a\x07\x3e\xa1\xf1\x0e\x39\xfc\xa0\xb2\x37\xb7\x77\xef\x05\x80\xab\x7f\x32\xca\x13\xc3\x95\xa3\xaf\xca\x81\x3a\x6d\xd5\x2e\x2b\x98\x53\x9b\x91\x18\x03\x92\x66\x3f\x2a\xe1\x43\x59\xa8\x0c\xec\xae\x79\x60\x40\x8f\x1c\xcc\x10\xc8\xfe\x38\x06\x35\x1f\xdd\x1c\x2e\xfe\xb0\xb3\x3b\x2a\x7a\xbc\x51\xad\xd4\xce\x1c\x17\x6f\xec\xc8\xc1\x10\x8a\x6f\x10\x44\x24\x5d\x4c\x55\x5c\x0c\xc5\xba\xe4\xfa\x9b\x6b\x7d\xd4\xb7\xe7\xc1\xf9\x7f\x22\xf9\x63\x1d\xa5\x42\xec\x39\x72\xca\x14\x58\x1c\x3e\x83\xe1\x1c\x7e\xe1\x02\xa9\xe2\xd5\x8b\xbe\x9c\x3a\x2e\x42\x3e\x80\xa3\x49\xfd\x87\x4c\x0a\xc4\x59\x43\x31\x04\x14", 0 }, + /* Anchor: 93 Izenpe-RAIZ2007.crt serial: #{a.serial.to_s} + C=ES,O=IZENPE S.A.,CN=Izenpe.com + */ + { 1524, "\x30\x82\x05\xf0\x30\x82\x03\xd8\xa0\x03\x02\x01\x02\x02\x0f\x06\xe8\x46\x27\x2f\x1f\x0a\x8f\xd1\x84\x5c\xe3\x69\xf6\xd5\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x38\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x0c\x0b\x49\x5a\x45\x4e\x50\x45\x20\x53\x2e\x41\x2e\x31\x13\x30\x11\x06\x03\x55\x04\x03\x0c\x0a\x49\x7a\x65\x6e\x70\x65\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x30\x37\x31\x32\x31\x33\x31\x33\x30\x38\x32\x37\x5a\x17\x0d\x33\x37\x31\x32\x31\x33\x30\x38\x32\x37\x32\x35\x5a\x30\x38\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x0c\x0b\x49\x5a\x45\x4e\x50\x45\x20\x53\x2e\x41\x2e\x31\x13\x30\x11\x06\x03\x55\x04\x03\x0c\x0a\x49\x7a\x65\x6e\x70\x65\x2e\x63\x6f\x6d\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\xc9\xd3\x7a\xca\x0f\x1e\xac\xa7\x86\xe8\x16\x65\x6a\xb1\xc2\x1b\x45\x32\x71\x95\xd9\xfe\x10\x5b\xcc\xaf\xe7\xa5\x79\x01\x8f\x89\xc3\xca\xf2\x55\x71\xf7\x77\xbe\x77\x94\xf3\x72\xa4\x2c\x44\xd8\x9e\x92\x9b\x14\x3a\xa1\xe7\x24\x90\x0a\x0a\x56\x8e\xc5\xd8\x26\x94\xe1\xd9\x48\xe1\x2d\x3e\xda\x0a\x72\xdd\xa3\x99\x15\xda\x81\xa2\x87\xf4\x7b\x6e\x26\x77\x89\x58\xad\xd6\xeb\x0c\xb2\x41\x7a\x73\x6e\x6d\xdb\x7a\x78\x41\xe9\x08\x88\x12\x7e\x87\x2e\x66\x11\x63\x6c\x54\xfb\x3c\x9d\x72\xc0\xbc\x2e\xff\xc2\xb7\xdd\x0d\x76\xe3\x3a\xd7\xf7\xb4\x68\xbe\xa2\xf5\xe3\x81\x6e\xc1\x46\x6f\x5d\x8d\xe0\x4d\xc6\x54\x55\x89\x1a\x33\x31\x0a\xb1\x57\xb9\xa3\x8a\x98\xc3\xec\x3b\x34\xc5\x95\x41\x69\x7e\x75\xc2\x3c\x20\xc5\x61\xba\x51\x47\xa0\x20\x90\x93\xa1\x90\x4b\xf3\x4e\x7c\x85\x45\x54\x9a\xd1\x05\x26\x41\xb0\xb5\x4d\x1d\x33\xbe\xc4\x03\xc8\x25\x7c\xc1\x70\xdb\x3b\xf4\x09\x2d\x54\x27\x48\xac\x2f\xe1\xc4\xac\x3e\xc8\xcb\x92\x4c\x53\x39\x37\x23\xec\xd3\x01\xf9\xe0\x09\x44\x4d\x4d\x64\xc0\xe1\x0d\x5a\x87\x22\xbc\xad\x1b\xa3\xfe\x26\xb5\x15\xf3\xa7\xfc\x84\x19\xe9\xec\xa1\x88\xb4\x44\x69\x84\x83\xf3\x89\xd1\x74\x06\xa9\xcc\x0b\xd6\xc2\xde\x27\x85\x50\x26\xca\x17\xb8\xc9\x7a\x87\x56\x2c\x1a\x01\x1e\x6c\xbe\x13\xad\x10\xac\xb5\x24\xf5\x38\x91\xa1\xd6\x4b\xda\xf1\xbb\xd2\xde\x47\xb5\xf1\xbc\x81\xf6\x59\x6b\xcf\x19\x53\xe9\x8d\x15\xcb\x4a\xcb\xa9\x6f\x44\xe5\x1b\x41\xcf\xe1\x86\xa7\xca\xd0\x6a\x9f\xbc\x4c\x8d\x06\x33\x5a\xa2\x85\xe5\x90\x35\xa0\x62\x5c\x16\x4e\xf0\xe3\xa2\xfa\x03\x1a\xb4\x2c\x71\xb3\x58\x2c\xde\x7b\x0b\xdb\x1a\x0f\xeb\xde\x21\x1f\x06\x77\x06\x03\xb0\xc9\xef\x99\xfc\xc0\xb9\x4f\x0b\x86\x28\xfe\xd2\xb9\xea\xe3\xda\xa5\xc3\x47\x69\x12\xe0\xdb\xf0\xf6\x19\x8b\xed\x7b\x70\xd7\x02\xd6\xed\x87\x18\x28\x2c\x04\x24\x4c\x77\xe4\x48\x8a\x1a\xc6\x3b\x9a\xd4\x0f\xca\xfa\x75\xd2\x01\x40\x5a\x8d\x79\xbf\x8b\xcf\x4b\xcf\xaa\x16\xc1\x95\xe4\xad\x4c\x8a\x3e\x17\x91\xd4\xb1\x62\xe5\x82\xe5\x80\x04\xa4\x03\x7e\x8d\xbf\xda\x7f\xa2\x0f\x97\x4f\x0c\xd3\x0d\xfb\xd7\xd1\xe5\x72\x7e\x1c\xc8\x77\xff\x5b\x9a\x0f\xb7\xae\x05\x46\xe5\xf1\xa8\x16\xec\x47\xa4\x17\x02\x03\x01\x00\x01\xa3\x81\xf6\x30\x81\xf3\x30\x81\xb0\x06\x03\x55\x1d\x11\x04\x81\xa8\x30\x81\xa5\x81\x0f\x69\x6e\x66\x6f\x40\x69\x7a\x65\x6e\x70\x65\x2e\x63\x6f\x6d\xa4\x81\x91\x30\x81\x8e\x31\x47\x30\x45\x06\x03\x55\x04\x0a\x0c\x3e\x49\x5a\x45\x4e\x50\x45\x20\x53\x2e\x41\x2e\x20\x2d\x20\x43\x49\x46\x20\x41\x30\x31\x33\x33\x37\x32\x36\x30\x2d\x52\x4d\x65\x72\x63\x2e\x56\x69\x74\x6f\x72\x69\x61\x2d\x47\x61\x73\x74\x65\x69\x7a\x20\x54\x31\x30\x35\x35\x20\x46\x36\x32\x20\x53\x38\x31\x43\x30\x41\x06\x03\x55\x04\x09\x0c\x3a\x41\x76\x64\x61\x20\x64\x65\x6c\x20\x4d\x65\x64\x69\x74\x65\x72\x72\x61\x6e\x65\x6f\x20\x45\x74\x6f\x72\x62\x69\x64\x65\x61\x20\x31\x34\x20\x2d\x20\x30\x31\x30\x31\x30\x20\x56\x69\x74\x6f\x72\x69\x61\x2d\x47\x61\x73\x74\x65\x69\x7a\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x1d\x1c\x65\x0e\xa8\xf2\x25\x7b\xb4\x91\xcf\xe4\xb1\xb1\xe6\xbd\x55\x74\x6c\x05\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\xc7\x81\x46\x6f\x21\x18\x4f\xa0\x05\xef\xe7\xd5\xba\x97\x50\xa2\x60\xed\xa5\x92\x14\x1a\x52\x9b\xf9\xf1\x88\x4a\xa0\xdc\x78\x75\xd1\xd5\x1f\x95\x4e\xc5\xe7\xb7\x69\xe6\x22\xf4\xf8\x29\xa8\x2a\x89\xbe\xcf\xcf\x76\x8f\xe3\x31\x73\x9d\x26\xd3\x1c\x1b\x47\x16\x29\x07\x68\x84\x8a\xd2\xfb\xb1\x1b\x24\x3e\xd2\x98\x18\x2c\x24\x8e\xaf\xf6\x7b\xea\x44\x16\x1b\x2a\xc4\xfa\xa0\x97\xe9\xea\x6c\x58\xa4\xef\x75\xab\x00\x62\xd1\x9d\xed\x13\x36\xdb\x22\x0b\xb6\xf0\xd1\xf4\x6e\x7b\x46\x87\xc2\x9d\xbc\xbd\xbe\x42\x3b\xb7\x73\xd0\x9a\x2a\x3c\xb4\x5b\x12\x16\x00\xaf\x19\x39\x8d\xad\x83\x50\x1c\xc8\x81\x4f\xbd\x02\x0f\x3d\x9e\x35\x96\xee\xef\xe4\xc2\x03\x7c\x29\x1c\x02\x7e\xbd\x34\x27\x5e\xaf\x53\xd6\x9d\x17\xbf\x57\x6c\xe9\xd0\x83\x10\xaf\xbf\x5d\x4d\xef\x90\x7b\x5d\x2b\xac\xec\xea\x7d\x00\x26\x17\xcc\x02\x5c\x63\xd7\x19\x18\xa7\xec\x2b\xc7\x8a\x3e\x58\x0e\x8a\x87\xe6\x83\x9f\x4e\xb2\x34\x1e\xac\x54\x09\x4f\x1d\x02\x0b\x39\x7e\x81\x08\x15\xb9\xa0\x69\x13\xc8\x32\x2b\xe3\xad\x6c\x13\xd6\x83\x9d\x23\x2d\xb2\x6d\xa2\x88\x86\x7e\xa8\x0d\x01\x26\x09\x40\xd9\xed\x28\x4e\x8c\x93\x24\x0f\xdb\xf1\x1e\x4d\x7a\x7a\x5a\xe2\xa5\x58\xf1\xdc\x8f\x5f\x99\x82\x0c\x2e\xcf\xb2\xdd\x98\xcc\x92\x94\x3f\xf9\x09\xb3\xa5\x96\x25\x5b\x37\xf5\x12\x85\x41\xe2\x19\x4c\xc6\x8a\x08\xc1\xdc\x18\x7a\x0f\x1e\x3f\x82\x59\xa2\x9a\x3e\x3f\xf9\xe0\x09\x9f\xfd\xc1\x91\x4b\x5d\xc9\x7b\xd6\xb6\x89\xfc\xdf\x1d\x7c\x86\xaa\xcd\x03\xf2\x0b\x52\x92\xf1\x62\x6f\x7f\x87\xea\xab\x76\xc9\x6c\x50\xc2\x19\x82\xaf\xaa\x1d\xf5\x20\x28\x68\x2e\xd5\xfc\x64\x37\x4f\xcf\xa5\x44\xc4\xbe\x72\xb4\x8c\x74\xb4\x6c\xa7\xfa\xf2\xbd\x74\x38\x43\x2b\xde\xaf\xf9\xdc\xd8\xe0\x9d\x9f\xdc\x3d\xca\xa5\x63\x44\xbf\x92\xa2\x4f\x4c\x80\x1c\xbb\x1a\xc3\x9a\x4a\x04\x55\x4d\xca\xee\x26\x0b\x1c\xbf\x02\xc5\x64\xd3\x9e\x7e\xd2\xd3\x91\x1c\x4b\xa2\xf5\x1c\xe5\x17\x1c\x0d\x0c\x52\xa3\x91\x1f\x9c\xf0\x21\xed\x02\x94\x6f\xa9\xa0\x49\xca\xe8\x43\x8c\xc4\xf4\x34\xda\x7c\x22\xa3\xc6\x66\x3e\xb8\x1b\x05\x88\x5d\xba\xbc\xf7\xbc\xe5\xdc\x14\x3d\xa7\x86\xa8\xb6\x59\x52\x21\x03\x5e\x8b\xe3\x04\xed\x4b\x2a\x1e\xa3\x4f\x50", 0 }, + /* Anchor: 94 JCSSecureSignRootCA11.cer serial: #{a.serial.to_s} + C=JP,O=Japan Certification Services\, Inc.,CN=SecureSign RootCA11 + */ + { 881, "\x30\x82\x03\x6d\x30\x82\x02\x55\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x58\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4a\x50\x31\x2b\x30\x29\x06\x03\x55\x04\x0a\x13\x22\x4a\x61\x70\x61\x6e\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x2c\x20\x49\x6e\x63\x2e\x31\x1c\x30\x1a\x06\x03\x55\x04\x03\x13\x13\x53\x65\x63\x75\x72\x65\x53\x69\x67\x6e\x20\x52\x6f\x6f\x74\x43\x41\x31\x31\x30\x1e\x17\x0d\x30\x39\x30\x34\x30\x38\x30\x34\x35\x36\x34\x37\x5a\x17\x0d\x32\x39\x30\x34\x30\x38\x30\x34\x35\x36\x34\x37\x5a\x30\x58\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4a\x50\x31\x2b\x30\x29\x06\x03\x55\x04\x0a\x13\x22\x4a\x61\x70\x61\x6e\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x2c\x20\x49\x6e\x63\x2e\x31\x1c\x30\x1a\x06\x03\x55\x04\x03\x13\x13\x53\x65\x63\x75\x72\x65\x53\x69\x67\x6e\x20\x52\x6f\x6f\x74\x43\x41\x31\x31\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xfd\x77\xaa\xa5\x1c\x90\x05\x3b\xcb\x4c\x9b\x33\x8b\x5a\x14\x45\xa4\xe7\x90\x16\xd1\xdf\x57\xd2\x21\x10\xa4\x17\xfd\xdf\xac\xd6\x1f\xa7\xe4\xdb\x7c\xf7\xec\xdf\xb8\x03\xda\x94\x58\xfd\x5d\x72\x7c\x8c\x3f\x5f\x01\x67\x74\x15\x96\xe3\x02\x3c\x87\xdb\xae\xcb\x01\x8e\xc2\xf3\x66\xc6\x85\x45\xf4\x02\xc6\x3a\xb5\x62\xb2\xaf\xfa\x9c\xbf\xa4\xe6\xd4\x80\x30\x98\xf3\x0d\xb6\x93\x8f\xa9\xd4\xd8\x36\xf2\xb0\xfc\x8a\xca\x2c\xa1\x15\x33\x95\x31\xda\xc0\x1b\xf2\xee\x62\x99\x86\x63\x3f\xbf\xdd\x93\x2a\x83\xa8\x76\xb9\x13\x1f\xb7\xce\x4e\x42\x85\x8f\x22\xe7\x2e\x1a\xf2\x95\x09\xb2\x05\xb5\x44\x4e\x77\xa1\x20\xbd\xa9\xf2\x4e\x0a\x7d\x50\xad\xf5\x05\x0d\x45\x4f\x46\x71\xfd\x28\x3e\x53\xfb\x04\xd8\x2d\xd7\x65\x1d\x4a\x1b\xfa\xcf\x3b\xb0\x31\x9a\x35\x6e\xc8\x8b\x06\xd3\x00\x91\xf2\x94\x08\x65\x4c\xb1\x34\x06\x00\x7a\x89\xe2\xf0\xc7\x03\x59\xcf\xd5\xd6\xe8\xa7\x32\xb3\xe6\x98\x40\x86\xc5\xcd\x27\x12\x8b\xcc\x7b\xce\xb7\x11\x3c\x62\x60\x07\x23\x3e\x2b\x40\x6e\x94\x80\x09\x6d\xb6\xb3\x6f\x77\x6f\x35\x08\x50\xfb\x02\x87\xc5\x3e\x89\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x5b\xf8\x4d\x4f\xb2\xa5\x86\xd4\x3a\xd2\xf1\x63\x9a\xa0\xbe\x09\xf6\x57\xb7\xde\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xa0\xa1\x38\x16\x66\x2e\xa7\x56\x1f\x21\x9c\x06\xfa\x1d\xed\xb9\x22\xc5\x38\x26\xd8\x4e\x4f\xec\xa3\x7f\x79\xde\x46\x21\xa1\x87\x77\x8f\x07\x08\x9a\xb2\xa4\xc5\xaf\x0f\x32\x98\x0b\x7c\x66\x29\xb6\x9b\x7d\x25\x52\x49\x43\xab\x4c\x2e\x2b\x6e\x7a\x70\xaf\x16\x0e\xe3\x02\x6c\xfb\x42\xe6\x18\x9d\x45\xd8\x55\xc8\xe8\x3b\xdd\xe7\xe1\xf4\x2e\x0b\x1c\x34\x5c\x6c\x58\x4a\xfb\x8c\x88\x50\x5f\x95\x1c\xbf\xed\xab\x22\xb5\x65\xb3\x85\xba\x9e\x0f\xb8\xad\xe5\x7a\x1b\x8a\x50\x3a\x1d\xbd\x0d\xbc\x7b\x54\x50\x0b\xb9\x42\xaf\x55\xa0\x18\x81\xad\x65\x99\xef\xbe\xe4\x9c\xbf\xc4\x85\xab\x41\xb2\x54\x6f\xdc\x25\xcd\xed\x78\xe2\x8e\x0c\x8d\x09\x49\xdd\x63\x7b\x5a\x69\x96\x02\x21\xa8\xbd\x52\x59\xe9\x7d\x35\xcb\xc8\x52\xca\x7f\x81\xfe\xd9\x6b\xd3\xf7\x11\xed\x25\xdf\xf8\xe7\xf9\xa4\xfa\x72\x97\x84\x53\x0d\xa5\xd0\x32\x18\x51\x76\x59\x14\x6c\x0f\xeb\xec\x5f\x80\x8c\x75\x43\x83\xc3\x85\x98\xff\x4c\x9e\x2d\x0d\xe4\x77\x83\x93\x4e\xb5\x96\x07\x8b\x28\x13\x9b\x8c\x19\x8d\x41\x27\x49\x40\xee\xde\xe6\x23\x44\x39\xdc\xa1\x22\xd6\xba\x03\xf2", 0 }, + /* Anchor: 95 kisa-root-rsa-3280.der serial: #{a.serial.to_s} + C=KR,O=KISA,OU=Korea Certification Authority Central,CN=KISA RootCA 1 + */ + { 887, "\x30\x82\x03\x73\x30\x82\x02\x5b\xa0\x03\x02\x01\x02\x02\x01\x04\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x64\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4b\x52\x31\x0d\x30\x0b\x06\x03\x55\x04\x0a\x0c\x04\x4b\x49\x53\x41\x31\x2e\x30\x2c\x06\x03\x55\x04\x0b\x0c\x25\x4b\x6f\x72\x65\x61\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x43\x65\x6e\x74\x72\x61\x6c\x31\x16\x30\x14\x06\x03\x55\x04\x03\x0c\x0d\x4b\x49\x53\x41\x20\x52\x6f\x6f\x74\x43\x41\x20\x31\x30\x1e\x17\x0d\x30\x35\x30\x38\x32\x34\x30\x38\x30\x35\x34\x36\x5a\x17\x0d\x32\x35\x30\x38\x32\x34\x30\x38\x30\x35\x34\x36\x5a\x30\x64\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4b\x52\x31\x0d\x30\x0b\x06\x03\x55\x04\x0a\x0c\x04\x4b\x49\x53\x41\x31\x2e\x30\x2c\x06\x03\x55\x04\x0b\x0c\x25\x4b\x6f\x72\x65\x61\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x43\x65\x6e\x74\x72\x61\x6c\x31\x16\x30\x14\x06\x03\x55\x04\x03\x0c\x0d\x4b\x49\x53\x41\x20\x52\x6f\x6f\x74\x43\x41\x20\x31\x30\x82\x01\x20\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0d\x00\x30\x82\x01\x08\x02\x82\x01\x01\x00\xbc\x04\xe4\xfa\x13\x39\xf0\x34\x96\x20\x6b\x6c\x68\xbb\xfa\xdb\x77\xff\x27\xf7\xac\xec\x2f\xe7\xfd\xf0\x7f\x6d\x6f\x8c\x2a\xcd\x25\x09\x5b\x24\xf4\xa1\x68\xfc\x28\xec\xc9\x25\xe2\xac\xed\xde\xc8\x33\x84\xf5\xb0\xa5\x09\x3a\xa7\xb1\x47\x48\xc5\xcc\x4f\x8c\x79\x9c\xf9\x06\x57\x7d\xdd\xee\x38\xf6\xcf\x14\xb2\x9c\xea\xd3\xc0\x5d\x77\x62\xf0\x47\x0d\xb9\x1a\x40\x53\x5c\x64\x70\xaf\x08\x5a\xc0\xf7\xcf\x75\xf9\x6c\x8d\x64\x28\x1e\x20\xfe\xb7\x1b\x19\xd3\x5a\x66\x83\x72\xe2\xb0\x9b\xbd\xd3\x25\x15\x0d\x32\x6f\x64\x37\x94\x85\x46\xc8\x72\xbe\x77\xd5\x6e\x1f\x28\x2f\xc7\x69\xed\xe7\x83\x89\x33\x58\xd3\xde\xa0\xbf\x40\xe8\x43\x50\xee\xdc\x4d\x6b\xbc\xa5\xea\xa6\xc8\x61\x8e\xf5\xc3\x64\xaf\x06\x15\xdc\x29\x8b\x3f\x75\x8c\xbc\x71\x44\xdb\xfc\xad\xb5\x17\x1d\x6d\x89\x83\xcf\xc6\x33\xbd\xbf\x45\xa2\xfe\x0a\x9f\xa3\x11\x5f\x0f\xb9\x1f\x9c\x1a\xc2\x46\xcc\x9c\x28\x66\x9f\x70\x26\x3c\x2e\xdf\xaa\x80\xfe\x8c\xc5\x04\x09\x25\x4f\xcd\x93\x47\x3c\x37\xea\x02\x67\x92\xfe\xfc\x22\x24\x5c\xac\xd2\x2c\xe0\x5c\x01\x33\x8a\xc1\x19\xdb\x02\x01\x03\xa3\x32\x30\x30\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xbf\xb6\x27\xd8\x03\x5a\x76\x65\x4c\x61\x01\x41\x56\x31\xe5\x8b\x7b\x3a\xd9\xcc\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x13\xaf\x51\x0b\xde\x8a\x6a\x5b\xe6\x9a\x0a\xc8\xb1\x90\x4a\x4e\xa1\x02\x9d\xcc\x88\xd2\xab\x66\xbd\x3d\xec\xbb\xb1\x42\x95\x6a\xb2\x5c\x5a\xff\xa1\x63\x64\x96\xa9\x68\x15\x7f\x25\x5e\x8a\xf8\xa4\x73\xc1\x80\x8a\x85\x0a\x0e\x52\xe8\x32\xe7\x45\xf8\x4e\x65\x80\x91\x99\x74\x43\xe5\x45\x9d\x49\x2a\xf0\x94\x95\xdd\xe9\xe1\x30\xd2\x13\x6e\xc9\x4e\xb1\x77\xe5\x04\xcf\xad\x5a\x1e\x94\x09\x5a\xd7\x3c\x08\x1c\xae\x7a\xe9\x14\x32\xc1\x45\xad\xd2\x26\x48\x72\xac\xa8\x41\xda\xf0\x21\x87\x39\x5e\xdf\xfc\x64\xff\x61\x74\x2a\x9c\xd9\x9b\x8b\x5f\xc2\x37\x93\xd8\xa3\x37\x2f\x3b\x93\x6b\xb2\x1b\x07\xa7\x7f\x09\x50\xef\xd3\x3a\xbe\x21\x6b\x8a\x90\x3b\x27\x4a\x51\x4e\x6b\x9e\x9c\x87\x9d\xf8\x78\x90\x31\xed\x11\x27\xc6\xa8\x59\xbe\xfc\x18\x0b\xfb\x8e\x7e\x2e\x42\xe1\xed\xe7\x09\x21\xbd\xb9\x13\xc5\x56\x67\xf4\x26\xa6\x42\x43\x90\x44\x54\xb4\x71\x9b\x76\xe4\x1a\x12\xac\x1a\x28\x00\xdf\x9b\xc1\xd5\xf8\xdb\x5c\xa3\xf8\x92\xb1\xbd\xb4\xd4\xf9\x50\xd9\x00\x02\x4f\xdb\x83\xd0\x11\x4f\xa4\x42\x56\x61\x3a\x7e\x13\x32\xd3\x84\x1f\xc9\xba", 0 }, + /* Anchor: 96 kisa-root-wrsa.der serial: #{a.serial.to_s} + C=KR,O=KISA,OU=Korea Certification Authority Central,CN=KISA RootCA 3 + */ + { 1366, "\x30\x82\x05\x52\x30\x82\x04\x3a\xa0\x03\x02\x01\x02\x02\x01\x02\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x64\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4b\x52\x31\x0d\x30\x0b\x06\x03\x55\x04\x0a\x13\x04\x4b\x49\x53\x41\x31\x2e\x30\x2c\x06\x03\x55\x04\x0b\x13\x25\x4b\x6f\x72\x65\x61\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x43\x65\x6e\x74\x72\x61\x6c\x31\x16\x30\x14\x06\x03\x55\x04\x03\x13\x0d\x4b\x49\x53\x41\x20\x52\x6f\x6f\x74\x43\x41\x20\x33\x30\x1e\x17\x0d\x30\x34\x31\x31\x31\x39\x30\x36\x33\x39\x35\x31\x5a\x17\x0d\x31\x34\x31\x31\x31\x39\x30\x36\x33\x39\x35\x31\x5a\x30\x64\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4b\x52\x31\x0d\x30\x0b\x06\x03\x55\x04\x0a\x13\x04\x4b\x49\x53\x41\x31\x2e\x30\x2c\x06\x03\x55\x04\x0b\x13\x25\x4b\x6f\x72\x65\x61\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x43\x65\x6e\x74\x72\x61\x6c\x31\x16\x30\x14\x06\x03\x55\x04\x03\x13\x0d\x4b\x49\x53\x41\x20\x52\x6f\x6f\x74\x43\x41\x20\x33\x30\x82\x01\x20\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0d\x00\x30\x82\x01\x08\x02\x82\x01\x01\x00\xde\xba\xed\x17\x65\xae\xd1\xbd\x4a\x3d\xac\xdb\x80\x72\xcc\x58\xe1\xe7\xe1\x93\xda\xcc\x30\x7a\xcf\xef\x0b\xae\x2d\xa7\x43\xab\xbf\xa7\x42\xcf\x08\x56\x08\xa4\x47\x1d\x7d\xfa\x86\xef\xd8\x30\x97\x26\x34\x61\x3c\x80\x0e\xf8\xd4\xeb\x9f\xfc\x22\x30\x1b\xa1\x6d\x3e\xe3\x4c\xd2\x55\x4e\x16\x40\x37\xc2\xf6\x07\x6e\xdb\x07\xb5\xa5\x8c\x96\x81\xe2\x9b\x5c\x7e\x94\x61\xc8\xce\x84\x3c\xb1\xfa\x00\xe6\x72\xd3\x09\x85\x77\xe9\xdc\x5e\x21\x4f\xb4\xe4\x4e\xf4\xe2\x17\xab\x50\xaf\x1c\xff\xa1\x39\x58\x75\x5b\x12\xb2\x96\xb9\x8d\xf0\x70\x62\x48\x5b\x56\x28\x2a\xa5\x87\x91\x36\xb9\x1e\x24\xf5\xb9\xba\x7b\xb6\x52\x51\x5b\x17\x5a\x60\x05\x6c\x9c\xc2\xe6\xc6\x8c\x3e\xf9\xea\xdd\x3c\x8c\xff\x89\xde\x43\x70\xac\x1d\xb8\xf1\x75\xcd\x38\xca\x53\x0d\x47\x68\x6a\xc6\x3c\x18\xca\xbd\xe1\xb4\xbe\x0e\xf4\xd0\xe3\xd2\x13\xfa\xb0\x51\x11\x11\xd4\x41\xab\xe8\xf4\x39\x8e\xe1\x34\x84\x4f\x0b\x93\xaa\x6a\x38\xfc\xe5\xc6\x78\x47\xae\x76\x17\xfa\xa1\x80\x37\x06\x00\x15\x08\xfd\x6b\x23\x8e\xfa\x72\x0d\x95\xd6\x4b\x62\xb1\x68\xc2\xdd\x34\x9b\x5d\x02\x01\x03\xa3\x82\x02\x0f\x30\x82\x02\x0b\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x8f\x81\xf0\xda\xa6\xcd\x74\x3c\xbe\x66\xf4\x15\x6b\x46\xa4\xfe\x06\x28\xcc\xaa\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x8f\x81\xf0\xda\xa6\xcd\x74\x3c\xbe\x66\xf4\x15\x6b\x46\xa4\xfe\x06\x28\xcc\xaa\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x82\x01\x2e\x06\x03\x55\x1d\x20\x04\x82\x01\x25\x30\x82\x01\x21\x30\x82\x01\x1d\x06\x04\x55\x1d\x20\x00\x30\x82\x01\x13\x30\x30\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x24\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x72\x6f\x6f\x74\x63\x61\x2e\x6f\x72\x2e\x6b\x72\x2f\x72\x63\x61\x2f\x63\x70\x73\x2e\x68\x74\x6d\x6c\x30\x81\xde\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x02\x30\x81\xd1\x1e\x81\xce\xc7\x74\x00\x20\xc7\x78\xc9\x9d\xc1\x1c\xb2\x94\x00\x20\xac\xf5\xc7\x78\xc7\x78\xc9\x9d\xc1\x1c\xc7\x85\xb2\xc8\xb2\xe4\x00\x28\x00\x54\x00\x68\x00\x69\x00\x73\x00\x20\x00\x63\x00\x65\x00\x72\x00\x74\x00\x69\x00\x66\x00\x69\x00\x63\x00\x61\x00\x74\x00\x65\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x63\x00\x63\x00\x72\x00\x65\x00\x64\x00\x69\x00\x74\x00\x65\x00\x64\x00\x20\x00\x75\x00\x6e\x00\x64\x00\x65\x00\x72\x00\x20\x00\x45\x00\x6c\x00\x65\x00\x63\x00\x74\x00\x72\x00\x6f\x00\x6e\x00\x69\x00\x63\x00\x20\x00\x53\x00\x69\x00\x67\x00\x6e\x00\x61\x00\x74\x00\x75\x00\x72\x00\x65\x00\x20\x00\x41\x00\x63\x00\x74\x00\x20\x00\x6f\x00\x66\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x52\x00\x65\x00\x70\x00\x75\x00\x62\x00\x6c\x00\x69\x00\x63\x00\x20\x00\x6f\x00\x66\x00\x20\x00\x4b\x00\x6f\x00\x72\x00\x65\x00\x61\x00\x29\x30\x33\x06\x03\x55\x1d\x11\x04\x2c\x30\x2a\xa4\x28\x30\x26\x31\x24\x30\x22\x06\x03\x55\x04\x03\x0c\x1b\xed\x95\x9c\xea\xb5\xad\xec\xa0\x95\xeb\xb3\xb4\xeb\xb3\xb4\xed\x98\xb8\xec\xa7\x84\xed\x9d\xa5\xec\x9b\x90\x30\x33\x06\x03\x55\x1d\x12\x04\x2c\x30\x2a\xa4\x28\x30\x26\x31\x24\x30\x22\x06\x03\x55\x04\x03\x0c\x1b\xed\x95\x9c\xea\xb5\xad\xec\xa0\x95\xeb\xb3\xb4\xeb\xb3\xb4\xed\x98\xb8\xec\xa7\x84\xed\x9d\xa5\xec\x9b\x90\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0c\x06\x03\x55\x1d\x24\x04\x05\x30\x03\x80\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xcf\xd6\xf7\x0e\xfd\xb0\x8c\x6e\x05\x15\x8e\xa8\x5c\x2b\xb2\x5a\xd1\x1e\x57\xa6\x5e\x18\xaa\x82\x11\x08\xfc\x99\xb7\x5b\xa7\xe3\xc8\xd2\xa2\xd3\xf9\x24\x34\xf7\xe3\xe4\xae\x89\x54\x47\xd3\x69\x49\xc9\x80\xc1\x11\xeb\xe2\x29\xc7\xf6\x06\x8b\x5f\xba\xe2\x5e\xcf\xab\xc3\xce\xcf\xee\x92\x25\xdc\x9f\x39\x1e\x0e\x03\xf4\xde\x90\x5b\xa1\x70\x99\x5c\xc7\x73\x4e\xc9\xa4\x75\x49\x7b\x25\xa1\x9f\x82\x92\x8d\x4d\xec\x61\xc5\x0c\x32\xa7\xc7\x38\x38\x80\x55\x3a\x2a\x83\x1d\x9c\x64\x79\xb9\x0d\xa7\x35\x4a\x68\xef\x8f\xff\x05\xd8\xba\x4e\x56\x61\xd8\xf8\x4a\x70\x98\x08\x96\x93\xd8\x60\xc7\x3a\xec\x5f\x9f\x1d\x2b\x35\x4f\x48\x14\xa1\x9a\xbb\x6f\xee\xd2\x03\x86\x53\xf1\x10\xc7\x07\x54\x62\x5e\x36\x8e\xe2\x1c\x2b\x1d\x17\x4d\xe6\xf5\x5a\xef\x8a\xba\x82\xe8\x77\xd9\x28\x11\x7e\x37\x87\x4a\x94\x0a\xc9\x40\xe9\x35\xa5\x3a\xfb\x64\x3e\xf2\x5f\x16\x7a\xf3\x76\xd7\xce\xee\x3f\x44\x1d\x45\xaa\x5f\x11\xaa\x53\x1c\x3a\x1f\x52\x51\x62\x54\x0f\xa3\x90\x35\xcf\x4d\x6f\xba\xc7\xbe\x2c\x09\xf1\x35\xf8\x01\xbb\x24\xdd\x30\xbc\x48\x0f\xee\xd9", 0 }, + /* Anchor: 97 KMD-CA-KPerson.crt serial: #{a.serial.to_s} + C=DK,O=KMD,OU=KMD-CA,CN=KMD-CA Kvalificeret Person + */ + { 890, "\x30\x82\x03\x76\x30\x82\x02\x5e\xa0\x03\x02\x01\x02\x02\x04\x3a\x1b\x04\x05\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x51\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4b\x31\x0c\x30\x0a\x06\x03\x55\x04\x0a\x13\x03\x4b\x4d\x44\x31\x0f\x30\x0d\x06\x03\x55\x04\x0b\x13\x06\x4b\x4d\x44\x2d\x43\x41\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1a\x4b\x4d\x44\x2d\x43\x41\x20\x4b\x76\x61\x6c\x69\x66\x69\x63\x65\x72\x65\x74\x20\x50\x65\x72\x73\x6f\x6e\x30\x1e\x17\x0d\x30\x30\x31\x31\x32\x31\x32\x33\x32\x34\x35\x39\x5a\x17\x0d\x31\x35\x31\x31\x32\x32\x32\x33\x32\x34\x35\x39\x5a\x30\x51\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4b\x31\x0c\x30\x0a\x06\x03\x55\x04\x0a\x13\x03\x4b\x4d\x44\x31\x0f\x30\x0d\x06\x03\x55\x04\x0b\x13\x06\x4b\x4d\x44\x2d\x43\x41\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1a\x4b\x4d\x44\x2d\x43\x41\x20\x4b\x76\x61\x6c\x69\x66\x69\x63\x65\x72\x65\x74\x20\x50\x65\x72\x73\x6f\x6e\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xda\xe2\x17\x85\xdd\xeb\x20\xfb\x66\x50\x44\xdf\x5e\xd4\x04\x33\x9b\x9f\xeb\xd1\x31\x57\x3a\xa7\x7c\x0d\x40\xe0\xdd\x10\x32\x5e\xdb\x3d\x67\x70\x2c\xfd\x34\x9b\xe1\xa0\xb1\x9d\x38\x98\x72\x83\xb5\x55\x3e\x1d\x0f\xd9\xcf\x8a\x67\xd5\x88\xf6\x65\x8e\x29\x92\x36\x6e\x9d\x96\x90\xb8\xee\x8c\x27\x31\x6e\x14\xeb\xba\xb6\x37\x59\xf7\x3a\x83\x02\xc1\xaa\xa1\x55\xf3\x05\xa0\x69\x92\xa6\xbd\x55\xa2\xce\x3c\x3d\x2b\x28\xb6\xe5\xfd\xf2\x5f\x87\xce\x86\x8e\x90\xab\x69\x6f\x55\xbb\x9b\xb6\xf5\x45\x5c\x07\x79\xd4\x62\x7e\xff\x66\x1e\x77\xe6\xb8\x3a\xbd\x9b\xcf\x64\x5c\xa8\x74\xbc\xd4\x1d\xe9\xcb\x0b\x03\xe2\x68\x09\x47\x9c\x51\x12\xfe\x63\xa8\xf7\xf0\x34\xff\x95\xed\xb9\x1c\x5f\xea\x5f\x3b\x89\x15\x85\x9f\xd5\xfb\xc3\x12\x3d\xd4\x07\x81\xc5\x7f\x88\x1d\xf0\x3f\x69\xb0\x81\x6c\x88\x04\xd7\x35\xad\xe0\x62\x74\x64\xe2\xcf\xcb\xa7\x9d\x6b\xb9\xe6\x17\x0d\x7e\xcb\xed\x2c\x96\xd3\xb3\xd3\x87\x86\xc4\x7b\x9d\xa4\x6e\xcb\xe4\xb8\xd3\x69\xc3\x9c\x3e\x6f\x9c\xe3\x4e\x14\x4b\x22\x1e\x7e\x3a\xc3\xe4\xf4\xae\xdb\xbb\x87\xa8\xf8\x3a\xf9\x02\x03\x01\x00\x01\xa3\x56\x30\x54\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01\x00\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x79\x62\xea\x9a\x12\x38\xd8\x9c\x63\xec\x38\x9f\x0e\xc5\xbe\x0e\x54\x21\x28\x3d\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x79\x62\xea\x9a\x12\x38\xd8\x9c\x63\xec\x38\x9f\x0e\xc5\xbe\x0e\x54\x21\x28\x3d\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xd3\x0b\xfc\xfe\x36\x3a\xe2\x7d\x69\x45\x7f\xd1\xf2\x2d\xb8\x8c\x9c\xd4\x98\x6a\x5a\xf4\xaa\x9f\x96\xd7\x8f\xef\x5e\xc8\x47\xa0\x72\x9f\x1b\x1c\xb1\xd8\xe3\x60\xf5\x3b\xec\xf4\x94\xd8\xa9\x76\x36\x0f\x49\xd3\x09\xd3\x06\x4e\x11\x48\x6b\xfb\x5e\x74\x49\xd0\xd0\xd4\xff\xf3\x40\xbf\x00\x51\xa2\xc4\x06\x44\x6d\xed\x97\x73\x5c\xf5\x47\xdc\xf1\x11\xaa\x77\xfd\x22\xba\x58\x06\x49\xd9\x29\xf0\x80\xa1\x57\x21\x03\xa4\x6b\xf5\x65\x37\x49\xdf\x1b\x32\x84\x5f\x30\xb2\xa0\xf1\xcd\x0c\xf0\x6e\x84\x3f\x00\x93\x70\xe1\x6b\x89\x29\x1b\xb6\xf3\x46\xcd\xdf\x2b\xf0\x8f\x96\x7d\x46\x08\x37\xfa\x7c\x0c\x8f\x49\x4f\xda\x9f\x8d\x53\x83\x9d\x83\xd1\x31\x49\xba\x28\xfb\xea\xdb\xb4\xec\xac\x6a\xee\x2a\xba\xb2\x69\x5f\x78\x91\x67\x3c\x72\x8f\x00\xbf\x7c\xc5\x2d\xe0\xad\x82\x1b\xd4\x89\x10\x5d\xc7\xef\x10\xee\x6e\x6d\xe0\x29\x2e\x4a\xbd\x16\x20\xda\xea\x8c\x83\xc5\x5b\x64\x2b\x33\x5a\xfc\xdb\x2d\x3d\x15\xdd\x7a\x46\x4a\x8b\xe0\xb3\xa0\x2e\x1e\xaf\x07\x92\xa7\x4c\x0a\x6f\xeb\x6a\xd6\x77\x0e\xf3\x5b\x06\x27\x8d\x8e\xbf\xbd\x76\x18\xd4\x0c", 0 }, + /* Anchor: 98 KMD-CA-Server.crt serial: #{a.serial.to_s} + C=DK,O=KMD,OU=KMD-CA,CN=KMD-CA Server,0.9.2342.19200300.100.1.3=#1410696E666F6361406B6D642D63612E646B + */ + { 862, "\x30\x82\x03\x5a\x30\x82\x02\x42\xa0\x03\x02\x01\x02\x02\x04\x3b\xca\xc9\x52\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x66\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4b\x31\x0c\x30\x0a\x06\x03\x55\x04\x0a\x13\x03\x4b\x4d\x44\x31\x0f\x30\x0d\x06\x03\x55\x04\x0b\x13\x06\x4b\x4d\x44\x2d\x43\x41\x31\x16\x30\x14\x06\x03\x55\x04\x03\x13\x0d\x4b\x4d\x44\x2d\x43\x41\x20\x53\x65\x72\x76\x65\x72\x31\x20\x30\x1e\x06\x0a\x09\x92\x26\x89\x93\xf2\x2c\x64\x01\x03\x14\x10\x69\x6e\x66\x6f\x63\x61\x40\x6b\x6d\x64\x2d\x63\x61\x2e\x64\x6b\x30\x1e\x17\x0d\x39\x38\x31\x30\x31\x36\x31\x39\x31\x39\x32\x31\x5a\x17\x0d\x31\x38\x31\x30\x31\x32\x31\x39\x31\x39\x32\x31\x5a\x30\x66\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4b\x31\x0c\x30\x0a\x06\x03\x55\x04\x0a\x13\x03\x4b\x4d\x44\x31\x0f\x30\x0d\x06\x03\x55\x04\x0b\x13\x06\x4b\x4d\x44\x2d\x43\x41\x31\x16\x30\x14\x06\x03\x55\x04\x03\x13\x0d\x4b\x4d\x44\x2d\x43\x41\x20\x53\x65\x72\x76\x65\x72\x31\x20\x30\x1e\x06\x0a\x09\x92\x26\x89\x93\xf2\x2c\x64\x01\x03\x14\x10\x69\x6e\x66\x6f\x63\x61\x40\x6b\x6d\x64\x2d\x63\x61\x2e\x64\x6b\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\x9b\x0b\xa5\xb4\xa0\x17\x14\x3b\x22\x11\x60\x7f\x97\xfe\x45\xf0\x71\x9d\xb0\xa4\xc7\x90\xbb\xc9\x38\xdf\x09\x9b\xe9\xfc\x13\xf6\x2c\x10\xf7\x38\xa8\xe0\x2d\x1c\x2f\x01\x2a\x02\x53\x72\x39\x34\xc8\x5c\x72\x1a\x3a\xba\x16\x55\x7f\x51\xc2\xf8\x07\x39\x1e\x65\xd4\x51\xdf\xaf\xf7\x66\xbb\x80\x39\xe8\x84\xf3\xf2\x46\x0b\xfc\x73\xa7\xff\xf9\x1d\x9f\x15\xe9\xf7\xed\x20\x5e\x99\x81\x43\xb5\x9b\xde\x6a\x65\x57\x67\x64\xe8\xef\x10\x31\x36\x23\x0a\x80\xf4\xcf\xb3\xf4\x65\xec\x5e\x8b\x0e\xc6\x20\xbf\x56\xc3\xdf\xa1\x6b\x8d\xa8\x4d\xa1\x24\xe6\x4d\xb6\x11\xa0\xad\xb5\x78\x83\x95\xc2\xb6\x5e\x35\x2c\xe8\xf7\x0d\xd6\xf1\xf8\xf4\x9f\xe5\x76\x20\x1d\x63\xb0\xe8\x7e\x02\xf8\xd7\x92\x36\xef\x01\x59\x32\xd3\xfe\x7b\x18\xc9\x72\x04\xd2\x8f\xec\x92\x06\x3f\xb2\xd7\xab\x05\x9f\xac\x15\xee\x02\x98\x75\x0d\x43\x33\xe3\xae\xca\x94\x76\x4e\x32\x43\xf0\x0a\x34\xd9\x39\xa6\xfb\x09\xc2\xd0\x5c\x20\x98\xd7\x6b\x39\x73\x94\x00\x93\x0a\x5f\xdf\x98\x50\x46\xe3\x9a\x36\x8e\x9d\xfd\x71\x4c\xe8\x9f\x66\xa1\xf8\x96\x94\x64\xd3\xdc\xfc\x75\x11\x7d\x02\x03\x01\x00\x01\xa3\x10\x30\x0e\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x3e\x50\x3a\x55\x9d\x82\xd9\xc2\x5b\xb0\x8d\x12\x04\x87\xbd\xbf\xe3\x3d\x1b\x12\x38\xe5\x02\x3b\x3f\x40\xfb\x40\x6c\xab\xa8\xce\xe8\x36\xa1\xaa\xee\x12\x5d\x37\xa3\x45\x6f\x42\xf2\x3d\xc1\x77\xfe\x95\x73\x9a\xd6\x15\x27\x36\x86\x28\x5e\xac\xa5\xac\x4e\x12\xf7\x81\xf6\x48\xb5\xc5\x1a\x17\x50\xaa\x5a\x0b\x14\xb0\x78\x1a\x53\xcc\x49\x2d\x59\xae\x37\x3b\x2b\x51\xcb\x4b\x1b\xaf\x21\x26\x1c\x90\x90\x93\x3f\x0c\x3e\xe7\xd6\xb2\xc7\xf6\xc9\x71\xf3\x80\x51\x68\x5c\xc4\x29\x70\xcc\x93\xec\x9c\x31\x3e\x57\xd8\x56\xf6\x9b\xf4\xaa\x7e\x9d\x6e\xdf\x23\x20\xce\x1b\x4c\x1d\x98\x17\xab\x67\xe1\x84\x40\x9c\x49\x12\x4a\xe2\xd4\x7b\x24\x8e\x28\x31\x84\x6c\xde\xce\x2a\x1c\x25\xab\x41\xb8\xe5\xa0\xab\x0e\x4a\x47\x29\x60\x18\x84\x23\x50\x64\x53\x09\xb3\x83\x56\xd6\xbe\x2a\x6a\x9b\xf5\xdf\x9c\x07\xb1\x52\xb5\xb6\x2d\xb7\x61\xde\x6c\xe5\xf3\x04\x86\x37\x5d\x43\x39\x2a\xd1\x82\xfb\xe5\x9e\xec\x3a\xa0\x53\x91\x62\xad\xe9\x3b\x6e\xbc\x3c\x8b\x65\xec\x1c\xf2\xca\x25\x37\x1e\x6f\xa5\xe8\xe8\x3b\x12\xc4\xb7\xc1\x01\x65\x7a\xfb\xc0\xc2\x91", 0 }, + /* Anchor: 99 kozjegyzoi.cer serial: #{a.serial.to_s} + C=HU,ST=Hungary,L=Budapest,O=NetLock Halozatbiztonsagi Kft.,OU=Tanusitvanykiadok,CN=NetLock Kozjegyzoi (Class A) Tanusitvanykiado + */ + { 1665, "\x30\x82\x06\x7d\x30\x82\x05\x65\xa0\x03\x02\x01\x02\x02\x02\x01\x03\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x30\x81\xaf\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x10\x30\x0e\x06\x03\x55\x04\x08\x13\x07\x48\x75\x6e\x67\x61\x72\x79\x31\x11\x30\x0f\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0a\x13\x1e\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x48\x61\x6c\x6f\x7a\x61\x74\x62\x69\x7a\x74\x6f\x6e\x73\x61\x67\x69\x20\x4b\x66\x74\x2e\x31\x1a\x30\x18\x06\x03\x55\x04\x0b\x13\x11\x54\x61\x6e\x75\x73\x69\x74\x76\x61\x6e\x79\x6b\x69\x61\x64\x6f\x6b\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2d\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x4b\x6f\x7a\x6a\x65\x67\x79\x7a\x6f\x69\x20\x28\x43\x6c\x61\x73\x73\x20\x41\x29\x20\x54\x61\x6e\x75\x73\x69\x74\x76\x61\x6e\x79\x6b\x69\x61\x64\x6f\x30\x1e\x17\x0d\x39\x39\x30\x32\x32\x34\x32\x33\x31\x34\x34\x37\x5a\x17\x0d\x31\x39\x30\x32\x31\x39\x32\x33\x31\x34\x34\x37\x5a\x30\x81\xaf\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x10\x30\x0e\x06\x03\x55\x04\x08\x13\x07\x48\x75\x6e\x67\x61\x72\x79\x31\x11\x30\x0f\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0a\x13\x1e\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x48\x61\x6c\x6f\x7a\x61\x74\x62\x69\x7a\x74\x6f\x6e\x73\x61\x67\x69\x20\x4b\x66\x74\x2e\x31\x1a\x30\x18\x06\x03\x55\x04\x0b\x13\x11\x54\x61\x6e\x75\x73\x69\x74\x76\x61\x6e\x79\x6b\x69\x61\x64\x6f\x6b\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2d\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x4b\x6f\x7a\x6a\x65\x67\x79\x7a\x6f\x69\x20\x28\x43\x6c\x61\x73\x73\x20\x41\x29\x20\x54\x61\x6e\x75\x73\x69\x74\x76\x61\x6e\x79\x6b\x69\x61\x64\x6f\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xbc\x74\x8c\x0f\xbb\x4c\xf4\x37\x1e\xa9\x05\x82\xd8\xe6\xe1\x6c\x70\xea\x78\xb5\x6e\xd1\x38\x44\x0d\xa8\x83\xce\x5d\xd2\xd6\xd5\x81\xc5\xd4\x4b\xe7\x5b\x94\x70\x26\xdb\x3b\x9d\x6a\x4c\x62\xf7\x71\xf3\x64\xd6\x61\x3b\x3d\xeb\x73\xa3\x37\xd9\xcf\xea\x8c\x92\x3b\xcd\xf7\x07\xdc\x66\x74\x97\xf4\x45\x22\xdd\xf4\x5c\xe0\xbf\x6d\xf3\xbe\x65\x33\xe4\x15\x3a\xbf\xdb\x98\x90\x55\x38\xc4\xed\xa6\x55\x63\x0b\xb0\x78\x04\xf4\xe3\x6e\xc1\x3f\x8e\xfc\x51\x78\x1f\x92\x9e\x83\xc2\xfe\xd9\xb0\xa9\xc9\xbc\x5a\x00\xff\xa9\xa8\x98\x74\xfb\xf6\x2c\x3e\x15\x39\x0d\xb6\x04\x55\xa8\x0e\x98\x20\x42\xb3\xb1\x25\xad\x7e\x9a\x6f\x5d\x53\xb1\xab\x0c\xfc\xeb\xe0\xf3\x7a\xb3\xa8\xb3\xff\x46\xf6\x63\xa2\xd8\x3a\x98\x7b\xb6\xac\x85\xff\xb0\x25\x4f\x74\x63\xe7\x13\x07\xa5\x0a\x8f\x05\xf7\xc0\x64\x6f\x7e\xa7\x27\x80\x96\xde\xd4\x2e\x86\x60\xc7\x6b\x2b\x5e\x73\x7b\x17\xe7\x91\x3f\x64\x0c\xd8\x4b\x22\x34\x2b\x9b\x32\xf2\x48\x1f\x9f\xa1\x0a\x84\x7a\xe2\xc2\xad\x97\x3d\x8e\xd5\xc1\xf9\x56\xa3\x50\xe9\xc6\xb4\xfa\x98\xa2\xee\x95\xe6\x2a\x03\x8c\xdf\x02\x03\x01\x00\x01\xa3\x82\x02\x9f\x30\x82\x02\x9b\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x00\x06\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01\x04\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x82\x02\x60\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x0d\x04\x82\x02\x51\x16\x82\x02\x4d\x46\x49\x47\x59\x45\x4c\x45\x4d\x21\x20\x45\x7a\x65\x6e\x20\x74\x61\x6e\x75\x73\x69\x74\x76\x61\x6e\x79\x20\x61\x20\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x4b\x66\x74\x2e\x20\x41\x6c\x74\x61\x6c\x61\x6e\x6f\x73\x20\x53\x7a\x6f\x6c\x67\x61\x6c\x74\x61\x74\x61\x73\x69\x20\x46\x65\x6c\x74\x65\x74\x65\x6c\x65\x69\x62\x65\x6e\x20\x6c\x65\x69\x72\x74\x20\x65\x6c\x6a\x61\x72\x61\x73\x6f\x6b\x20\x61\x6c\x61\x70\x6a\x61\x6e\x20\x6b\x65\x73\x7a\x75\x6c\x74\x2e\x20\x41\x20\x68\x69\x74\x65\x6c\x65\x73\x69\x74\x65\x73\x20\x66\x6f\x6c\x79\x61\x6d\x61\x74\x61\x74\x20\x61\x20\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x4b\x66\x74\x2e\x20\x74\x65\x72\x6d\x65\x6b\x66\x65\x6c\x65\x6c\x6f\x73\x73\x65\x67\x2d\x62\x69\x7a\x74\x6f\x73\x69\x74\x61\x73\x61\x20\x76\x65\x64\x69\x2e\x20\x41\x20\x64\x69\x67\x69\x74\x61\x6c\x69\x73\x20\x61\x6c\x61\x69\x72\x61\x73\x20\x65\x6c\x66\x6f\x67\x61\x64\x61\x73\x61\x6e\x61\x6b\x20\x66\x65\x6c\x74\x65\x74\x65\x6c\x65\x20\x61\x7a\x20\x65\x6c\x6f\x69\x72\x74\x20\x65\x6c\x6c\x65\x6e\x6f\x72\x7a\x65\x73\x69\x20\x65\x6c\x6a\x61\x72\x61\x73\x20\x6d\x65\x67\x74\x65\x74\x65\x6c\x65\x2e\x20\x41\x7a\x20\x65\x6c\x6a\x61\x72\x61\x73\x20\x6c\x65\x69\x72\x61\x73\x61\x20\x6d\x65\x67\x74\x61\x6c\x61\x6c\x68\x61\x74\x6f\x20\x61\x20\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x4b\x66\x74\x2e\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x68\x6f\x6e\x6c\x61\x70\x6a\x61\x6e\x20\x61\x20\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x6e\x65\x74\x6c\x6f\x63\x6b\x2e\x6e\x65\x74\x2f\x64\x6f\x63\x73\x20\x63\x69\x6d\x65\x6e\x20\x76\x61\x67\x79\x20\x6b\x65\x72\x68\x65\x74\x6f\x20\x61\x7a\x20\x65\x6c\x6c\x65\x6e\x6f\x72\x7a\x65\x73\x40\x6e\x65\x74\x6c\x6f\x63\x6b\x2e\x6e\x65\x74\x20\x65\x2d\x6d\x61\x69\x6c\x20\x63\x69\x6d\x65\x6e\x2e\x20\x49\x4d\x50\x4f\x52\x54\x41\x4e\x54\x21\x20\x54\x68\x65\x20\x69\x73\x73\x75\x61\x6e\x63\x65\x20\x61\x6e\x64\x20\x74\x68\x65\x20\x75\x73\x65\x20\x6f\x66\x20\x74\x68\x69\x73\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x69\x73\x20\x73\x75\x62\x6a\x65\x63\x74\x20\x74\x6f\x20\x74\x68\x65\x20\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x43\x50\x53\x20\x61\x76\x61\x69\x6c\x61\x62\x6c\x65\x20\x61\x74\x20\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x6e\x65\x74\x6c\x6f\x63\x6b\x2e\x6e\x65\x74\x2f\x64\x6f\x63\x73\x20\x6f\x72\x20\x62\x79\x20\x65\x2d\x6d\x61\x69\x6c\x20\x61\x74\x20\x63\x70\x73\x40\x6e\x65\x74\x6c\x6f\x63\x6b\x2e\x6e\x65\x74\x2e\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x03\x82\x01\x01\x00\x48\x24\x46\xf7\xba\x56\x6f\xfa\xc8\x28\x03\x40\x4e\xe5\x31\x39\x6b\x26\x6b\x53\x7f\xdb\xdf\xdf\xf3\x71\x3d\x26\xc0\x14\x0e\xc6\x67\x7b\x23\xa8\x0c\x73\xdd\x01\xbb\xc6\xca\x6e\x37\x39\x55\xd5\xc7\x8c\x56\x20\x0e\x28\x0a\x0e\xd2\x2a\xa4\xb0\x49\x52\xc6\x38\x07\xfe\xbe\x0a\x09\x8c\xd1\x98\xcf\xca\xda\x14\x31\xa1\x4f\xd2\x39\xfc\x0f\x11\x2c\x43\xc3\xdd\xab\x93\xc7\x55\x3e\x47\x7c\x18\x1a\x00\xdc\xf3\x7b\xd8\xf2\x7f\x52\x6c\x20\xf4\x0b\x5f\x69\x52\xf4\xee\xf8\xb2\x29\x60\xeb\xe3\x49\x31\x21\x0d\xd6\xb5\x10\x41\xe2\x41\x09\x6c\xe2\x1a\x9a\x56\x4b\x77\x02\xf6\xa0\x9b\x9a\x27\x87\xe8\x55\x29\x71\xc2\x90\x9f\x45\x78\x1a\xe1\x15\x64\x3d\xd0\x0e\xd8\xa0\x76\x9f\xae\xc5\xd0\x2e\xea\xd6\x0f\x56\xec\x64\x7f\x5a\x9b\x14\x58\x01\x27\x7e\x13\x50\xc7\x6b\x2a\xe6\x68\x3c\xbf\x5c\xa0\x0a\x1b\xe1\x0e\x7a\xe9\xe2\x80\xc3\xe9\xe9\xf6\xfd\x6c\x11\x9e\xd0\xe5\x28\x27\x2b\x54\x32\x42\x14\x82\x75\xe6\x4a\xf0\x2b\x66\x75\x63\x8c\xa2\xfb\x04\x3e\x83\x0e\x9b\x36\xf0\x18\xe4\x26\x20\xc3\x8c\xf0\x28\x07\xad\x3c\x17\x66\x88\xb5\xfd\xb6\x88", 0 }, + /* Anchor: 100 MPHPT_CA.cer serial: #{a.serial.to_s} + C=JP,O=Japanese Government,OU=MPHPT,OU=MPHPT Certification Authority + */ + { 952, "\x30\x82\x03\xb4\x30\x82\x02\x9c\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x63\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4a\x50\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x4a\x61\x70\x61\x6e\x65\x73\x65\x20\x47\x6f\x76\x65\x72\x6e\x6d\x65\x6e\x74\x31\x0e\x30\x0c\x06\x03\x55\x04\x0b\x13\x05\x4d\x50\x48\x50\x54\x31\x26\x30\x24\x06\x03\x55\x04\x0b\x13\x1d\x4d\x50\x48\x50\x54\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x30\x32\x30\x33\x31\x34\x30\x37\x35\x30\x32\x36\x5a\x17\x0d\x31\x32\x30\x33\x31\x33\x31\x34\x35\x39\x35\x39\x5a\x30\x63\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4a\x50\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x4a\x61\x70\x61\x6e\x65\x73\x65\x20\x47\x6f\x76\x65\x72\x6e\x6d\x65\x6e\x74\x31\x0e\x30\x0c\x06\x03\x55\x04\x0b\x13\x05\x4d\x50\x48\x50\x54\x31\x26\x30\x24\x06\x03\x55\x04\x0b\x13\x1d\x4d\x50\x48\x50\x54\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\x8d\xc6\x51\x69\x4a\xf4\x6f\x45\x56\x6f\x03\x86\x92\xae\xe6\xdd\xfb\xa3\x16\x5b\x8f\xa9\x59\x70\x5b\xc4\x65\x8d\x3b\x62\xb6\x28\x8d\x63\xba\xe7\xbb\x9b\xcf\x9e\x96\x13\xba\xbf\x3c\x8f\xfa\x4a\x6e\xe2\xee\xa6\x04\xf9\x5a\x7c\xd2\xbe\xad\x84\x9b\xdf\x9a\x7e\xd2\x4b\x70\x44\x36\xb4\x6a\x89\xaa\x52\x7a\x78\x68\xa1\x80\xf5\xda\x32\x1e\xde\x26\x50\xd9\x25\xea\xc7\xb5\xa0\x63\x0c\x81\x19\xd4\x30\x19\xa6\x13\x8a\x3c\xdb\x44\x5a\x60\x73\x42\xbc\xa3\x86\xbd\xf5\xf2\x28\x1e\x1c\xfd\x27\xc0\x0a\xa9\x76\xac\x75\xd3\x02\xa9\xf2\x51\x68\x7d\xf4\x60\x9e\xc7\x9c\xeb\xd1\x60\x62\xfa\x1c\x1a\xc6\x84\x9e\xd7\xe1\x1c\xe2\x8f\x29\x3d\x6b\xdf\xb7\x54\xe0\x6c\x61\xc9\xc8\x97\x1f\x62\x38\x3a\x22\x62\x10\x3a\xaf\x4a\x23\xb8\x8b\xbc\xfc\x90\x35\xa1\x34\xd9\xad\x2d\x0c\xc9\x4f\xd2\x2d\xd1\x5d\x27\x37\xb6\x3b\x5c\x27\xa9\x35\x0b\x5d\x0c\x9b\xcc\x9c\xf7\x69\xde\xa8\x0b\xf1\x79\x6b\xaf\x5c\xd2\x6f\x76\x6a\x46\x1d\xf6\x71\x81\xac\xfc\x63\x12\x1b\x9c\x69\x0c\xa7\x0b\xf4\x28\x08\xbb\x37\x69\xc8\x8b\x82\x2a\x00\x9c\x42\x6a\xcb\xb8\xb7\x12\x05\x02\x03\x01\x00\x01\xa3\x73\x30\x71\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x60\xc2\xf7\xa4\xba\x00\xd2\x1f\x77\x62\x78\x25\xf0\x66\xff\x52\x00\x21\xef\x7a\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x60\xc2\xf7\xa4\xba\x00\xd2\x1f\x77\x62\x78\x25\xf0\x66\xff\x52\x00\x21\xef\x7a\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x05\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x34\xf4\x7c\x0c\xde\xba\x89\x66\x41\xb3\xf9\x52\x9b\x5b\xce\xce\x1a\x91\x91\x70\xcb\x4f\xac\x4b\x2e\xf2\x6d\x8c\xf2\xea\x98\x4e\x3a\xf6\xcc\xc6\xc8\x54\x8a\xce\xca\x1f\xeb\x2f\xbf\xf1\x88\x19\x94\xea\x1e\x5f\x58\xa7\x17\x8a\x31\xfd\x21\xf5\x01\x39\xf0\x74\x82\x2c\x3d\xb5\xee\x44\xb8\xed\x6b\x16\xe8\x5e\xf0\x61\xe7\x2d\x9f\x7c\x2d\xe1\x9b\x32\x55\xbc\x9f\x3b\xb5\xbe\xa6\x55\x64\x1e\x2f\xd5\x45\x52\x13\x61\x00\x8d\x22\x6f\xef\x4e\x21\x95\x44\x60\x8f\xfa\xe0\xc1\x64\x0e\x4e\x1e\x89\x61\xb9\xb6\xce\xa8\xa8\x82\x47\xd5\x5e\xdd\x55\x98\x3a\xa5\x0d\x53\x73\x40\xa4\x86\x7e\x8d\xd6\x6d\x61\x0f\x7d\x12\xd3\xfc\xe8\x3e\x7f\xf6\xd1\x6a\xba\x38\x21\x77\x85\xef\x15\x26\xb4\x46\x75\xc5\xbd\x04\x3f\xc1\x91\xeb\x24\xa3\x51\xca\x84\xc0\x43\x8c\x75\x6b\x27\xc7\x05\xc1\xb9\xc3\x4a\x8a\x3e\x2a\x2e\x3b\x78\x95\x9a\xcf\xf7\x0e\xcd\xa4\xac\x68\xc5\x54\xb1\x1e\x4f\x39\xab\xda\xfd\xa6\xe1\x86\x01\xe7\xfd\xe3\x89\x75\x78\x95\xb2\x5c\x8a\xd0\x36\x2c\x72\x3b\x1d\x07\x76\x81\x51\xfc\x19\x96\x89\xb1\x60\xec\xc6\xe8\x28\x23\x40\xf8\x49\x77", 0 }, + /* Anchor: 101 NetLockAranyClassGoldF.cer serial: #{a.serial.to_s} + C=HU,L=Budapest,O=NetLock Kft.,OU=Tanúsítványkiadók (Certification Services),CN=NetLock Arany (Class Gold) Főtanúsítvány + */ + { 1049, "\x30\x82\x04\x15\x30\x82\x02\xfd\xa0\x03\x02\x01\x02\x02\x06\x49\x41\x2c\xe4\x00\x10\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x30\x81\xa7\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0f\x06\x03\x55\x04\x07\x0c\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x0c\x0c\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x4b\x66\x74\x2e\x31\x37\x30\x35\x06\x03\x55\x04\x0b\x0c\x2e\x54\x61\x6e\xc3\xba\x73\xc3\xad\x74\x76\xc3\xa1\x6e\x79\x6b\x69\x61\x64\xc3\xb3\x6b\x20\x28\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x29\x31\x35\x30\x33\x06\x03\x55\x04\x03\x0c\x2c\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x41\x72\x61\x6e\x79\x20\x28\x43\x6c\x61\x73\x73\x20\x47\x6f\x6c\x64\x29\x20\x46\xc5\x91\x74\x61\x6e\xc3\xba\x73\xc3\xad\x74\x76\xc3\xa1\x6e\x79\x30\x1e\x17\x0d\x30\x38\x31\x32\x31\x31\x31\x35\x30\x38\x32\x31\x5a\x17\x0d\x32\x38\x31\x32\x30\x36\x31\x35\x30\x38\x32\x31\x5a\x30\x81\xa7\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0f\x06\x03\x55\x04\x07\x0c\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x0c\x0c\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x4b\x66\x74\x2e\x31\x37\x30\x35\x06\x03\x55\x04\x0b\x0c\x2e\x54\x61\x6e\xc3\xba\x73\xc3\xad\x74\x76\xc3\xa1\x6e\x79\x6b\x69\x61\x64\xc3\xb3\x6b\x20\x28\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x29\x31\x35\x30\x33\x06\x03\x55\x04\x03\x0c\x2c\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x41\x72\x61\x6e\x79\x20\x28\x43\x6c\x61\x73\x73\x20\x47\x6f\x6c\x64\x29\x20\x46\xc5\x91\x74\x61\x6e\xc3\xba\x73\xc3\xad\x74\x76\xc3\xa1\x6e\x79\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xc4\x24\x5e\x73\xbe\x4b\x6d\x14\xc3\xa1\xf4\xe3\x97\x90\x6e\xd2\x30\x45\x1e\x3c\xee\x67\xd9\x64\xe0\x1a\x8a\x7f\xca\x30\xca\x83\xe3\x20\xc1\xe3\xf4\x3a\xd3\x94\x5f\x1a\x7c\x5b\x6d\xbf\x30\x4f\x84\x27\xf6\x9f\x1f\x49\xbc\xc6\x99\x0a\x90\xf2\x0f\xf5\x7f\x43\x84\x37\x63\x51\x8b\x7a\xa5\x70\xfc\x7a\x58\xcd\x8e\x9b\xed\xc3\x46\x6c\x84\x70\x5d\xda\xf3\x01\x90\x23\xfc\x4e\x30\xa9\x7e\xe1\x27\x63\xe7\xed\x64\x3c\xa0\xb8\xc9\x33\x63\xfe\x16\x90\xff\xb0\xb8\xfd\xd7\xa8\xc0\xc0\x94\x43\x0b\xb6\xd5\x59\xa6\x9e\x56\xd0\x24\x1f\x70\x79\xaf\xdb\x39\x54\x0d\x65\x75\xd9\x15\x41\x94\x01\xaf\x5e\xec\xf6\x8d\xf1\xff\xad\x64\xfe\x20\x9a\xd7\x5c\xeb\xfe\xa6\x1f\x08\x64\xa3\x8b\x76\x55\xad\x1e\x3b\x28\x60\x2e\x87\x25\xe8\xaa\xaf\x1f\xc6\x64\x46\x20\xb7\x70\x7f\x3c\xde\x48\xdb\x96\x53\xb7\x39\x77\xe4\x1a\xe2\xc7\x16\x84\x76\x97\x5b\x2f\xbb\x19\x15\x85\xf8\x69\x85\xf5\x99\xa7\xa9\xf2\x34\xa7\xa9\xb6\xa6\x03\xfc\x6f\x86\x3d\x54\x7c\x76\x04\x9b\x6b\xf9\x40\x5d\x00\x34\xc7\x2e\x99\x75\x9d\xe5\x88\x03\xaa\x4d\xf8\x03\xd2\x42\x76\xc0\x1b\x02\x03\x00\xa8\x8b\xa3\x45\x30\x43\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01\x04\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xcc\xfa\x67\x93\xf0\xb6\xb8\xd0\xa5\xc0\x1e\xf3\x53\xfd\x8c\x53\xdf\x83\xd7\x96\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x03\x82\x01\x01\x00\xab\x7f\xee\x1c\x16\xa9\x9c\x3c\x51\x00\xa0\xc0\x11\x08\x05\xa7\x99\xe6\x6f\x01\x88\x54\x61\x6e\xf1\xb9\x18\xad\x4a\xad\xfe\x81\x40\x23\x94\x2f\xfb\x75\x7c\x2f\x28\x4b\x62\x24\x81\x82\x0b\xf5\x61\xf1\x1c\x6e\xb8\x61\x38\xeb\x81\xfa\x62\xa1\x3b\x5a\x62\xd3\x94\x65\xc4\xe1\xe6\x6d\x82\xf8\x2f\x25\x70\xb2\x21\x26\xc1\x72\x51\x1f\x8c\x2c\xc3\x84\x90\xc3\x5a\x8f\xba\xcf\xf4\xa7\x65\xa5\xeb\x98\xd1\xfb\x05\xb2\x46\x75\x15\x23\x6a\x6f\x85\x63\x30\x80\xf0\xd5\x9e\x1f\x29\x1c\xc2\x6c\xb0\x50\x59\x5d\x90\x5b\x3b\xa8\x0d\x30\xcf\xbf\x7d\x7f\xce\xf1\x9d\x83\xbd\xc9\x46\x6e\x20\xa6\xf9\x61\x51\xba\x21\x2f\x7b\xbe\xa5\x15\x63\xa1\xd4\x95\x87\xf1\x9e\xb9\xf3\x89\xf3\x3d\x85\xb8\xb8\xdb\xbe\xb5\xb9\x29\xf9\xda\x37\x05\x00\x49\x94\x03\x84\x44\xe7\xbf\x43\x31\xcf\x75\x8b\x25\xd1\xf4\xa6\x64\xf5\x92\xf6\xab\x05\xeb\x3d\xe9\xa5\x0b\x36\x62\xda\xcc\x06\x5f\x36\x8b\xb6\x5e\x31\xb8\x2a\xfb\x5e\xf6\x71\xdf\x44\x26\x9e\xc4\xe6\x0d\x91\xb4\x2e\x75\x95\x80\x51\x6a\x4b\x30\xa6\xb0\x62\xa1\x93\xf1\x9b\xd8\xce\xc4\x63\x75\x3f\x59\x47\xb1", 0 }, + /* Anchor: 102 netlockQA-01-minositett.cer serial: #{a.serial.to_s} + C=HU,L=Budapest,O=NetLock Halozatbiztonsagi Kft.,OU=Tanusitvanykiadok,CN=NetLock Minositett Kozjegyzoi (Class QA) Tanusitvanykiado,1.2.840.113549.1.9.1=#160F696E666F406E65746C6F636B2E6875 + */ + { 1749, "\x30\x82\x06\xd1\x30\x82\x05\xb9\xa0\x03\x02\x01\x02\x02\x01\x7b\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xc9\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0f\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0a\x13\x1e\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x48\x61\x6c\x6f\x7a\x61\x74\x62\x69\x7a\x74\x6f\x6e\x73\x61\x67\x69\x20\x4b\x66\x74\x2e\x31\x1a\x30\x18\x06\x03\x55\x04\x0b\x13\x11\x54\x61\x6e\x75\x73\x69\x74\x76\x61\x6e\x79\x6b\x69\x61\x64\x6f\x6b\x31\x42\x30\x40\x06\x03\x55\x04\x03\x13\x39\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x4d\x69\x6e\x6f\x73\x69\x74\x65\x74\x74\x20\x4b\x6f\x7a\x6a\x65\x67\x79\x7a\x6f\x69\x20\x28\x43\x6c\x61\x73\x73\x20\x51\x41\x29\x20\x54\x61\x6e\x75\x73\x69\x74\x76\x61\x6e\x79\x6b\x69\x61\x64\x6f\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x69\x6e\x66\x6f\x40\x6e\x65\x74\x6c\x6f\x63\x6b\x2e\x68\x75\x30\x1e\x17\x0d\x30\x33\x30\x33\x33\x30\x30\x31\x34\x37\x31\x31\x5a\x17\x0d\x32\x32\x31\x32\x31\x35\x30\x31\x34\x37\x31\x31\x5a\x30\x81\xc9\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0f\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0a\x13\x1e\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x48\x61\x6c\x6f\x7a\x61\x74\x62\x69\x7a\x74\x6f\x6e\x73\x61\x67\x69\x20\x4b\x66\x74\x2e\x31\x1a\x30\x18\x06\x03\x55\x04\x0b\x13\x11\x54\x61\x6e\x75\x73\x69\x74\x76\x61\x6e\x79\x6b\x69\x61\x64\x6f\x6b\x31\x42\x30\x40\x06\x03\x55\x04\x03\x13\x39\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x4d\x69\x6e\x6f\x73\x69\x74\x65\x74\x74\x20\x4b\x6f\x7a\x6a\x65\x67\x79\x7a\x6f\x69\x20\x28\x43\x6c\x61\x73\x73\x20\x51\x41\x29\x20\x54\x61\x6e\x75\x73\x69\x74\x76\x61\x6e\x79\x6b\x69\x61\x64\x6f\x31\x1e\x30\x1c\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x0f\x69\x6e\x66\x6f\x40\x6e\x65\x74\x6c\x6f\x63\x6b\x2e\x68\x75\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xc7\x52\x25\xb2\xd8\x3d\xd4\x84\x55\x09\xa7\x1b\xbd\x6c\xb9\x14\xf4\x8a\x02\xdb\x76\xfc\x6a\x2a\x78\xab\xe5\x77\xf0\x6e\xe0\x8c\x23\x67\xdb\xa5\x64\x99\xb9\xdd\x01\x3e\x6f\xef\x2d\x9a\x3c\x22\xf0\x5d\xc9\x57\xa0\x55\x41\x7f\xf2\x43\x5e\x58\x82\x53\x31\x65\xce\x1e\xf2\x26\xba\x00\x54\x1e\xaf\xb0\xbc\x1c\xe4\x52\x8c\xa0\x32\xaf\xb7\x37\xb1\x53\x67\x68\x74\x67\x50\xf6\x2d\x2e\x64\xde\xae\x26\x79\xdf\xdf\x99\x86\xab\xab\x7f\x85\xec\xa0\xfb\x80\xcc\xf4\xb8\x0c\x1e\x93\x45\x63\xb9\xdc\xb8\x5b\x9b\xed\x5b\x39\xd4\x5f\x62\xb0\xa7\x8e\x7c\x66\x38\x2c\xaa\xb1\x08\x63\x17\x67\x7d\xcc\xbd\xb3\xf1\xc3\x3f\xcf\x50\x39\xed\xd1\x19\x83\x15\xdb\x87\x12\x27\x96\xb7\xda\xea\xe5\x9d\xbc\xba\xea\x39\x4f\x8b\xef\x74\x9a\xe7\xc5\xd0\xd2\xea\x86\x51\x1c\xe4\xfe\x64\x08\x28\x04\x79\x05\xeb\xca\xc5\x71\x0e\x0b\xef\xab\xea\xec\x12\x11\xa1\x18\x05\x32\x69\xd1\x0c\x2c\x1a\x3d\x25\x99\x3f\xb5\x7c\xca\x6d\xb0\xae\x99\x99\xfa\x08\x60\xe7\x19\xc2\xf2\xbd\x51\xd3\xcc\xd3\x02\xac\xc1\x11\x0c\x80\xce\xab\xdc\x94\x9d\x6b\xa3\x39\x53\x3a\xd6\x85\x02\x03\x00\xc5\x7d\xa3\x82\x02\xc0\x30\x82\x02\xbc\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01\x04\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x82\x02\x75\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x0d\x04\x82\x02\x66\x16\x82\x02\x62\x46\x49\x47\x59\x45\x4c\x45\x4d\x21\x20\x45\x7a\x65\x6e\x20\x74\x61\x6e\x75\x73\x69\x74\x76\x61\x6e\x79\x20\x61\x20\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x4b\x66\x74\x2e\x20\x4d\x69\x6e\x6f\x73\x69\x74\x65\x74\x74\x20\x53\x7a\x6f\x6c\x67\x61\x6c\x74\x61\x74\x61\x73\x69\x20\x53\x7a\x61\x62\x61\x6c\x79\x7a\x61\x74\x61\x62\x61\x6e\x20\x6c\x65\x69\x72\x74\x20\x65\x6c\x6a\x61\x72\x61\x73\x6f\x6b\x20\x61\x6c\x61\x70\x6a\x61\x6e\x20\x6b\x65\x73\x7a\x75\x6c\x74\x2e\x20\x41\x20\x6d\x69\x6e\x6f\x73\x69\x74\x65\x74\x74\x20\x65\x6c\x65\x6b\x74\x72\x6f\x6e\x69\x6b\x75\x73\x20\x61\x6c\x61\x69\x72\x61\x73\x20\x6a\x6f\x67\x68\x61\x74\x61\x73\x20\x65\x72\x76\x65\x6e\x79\x65\x73\x75\x6c\x65\x73\x65\x6e\x65\x6b\x2c\x20\x76\x61\x6c\x61\x6d\x69\x6e\x74\x20\x65\x6c\x66\x6f\x67\x61\x64\x61\x73\x61\x6e\x61\x6b\x20\x66\x65\x6c\x74\x65\x74\x65\x6c\x65\x20\x61\x20\x4d\x69\x6e\x6f\x73\x69\x74\x65\x74\x74\x20\x53\x7a\x6f\x6c\x67\x61\x6c\x74\x61\x74\x61\x73\x69\x20\x53\x7a\x61\x62\x61\x6c\x79\x7a\x61\x74\x62\x61\x6e\x2c\x20\x61\x7a\x20\x41\x6c\x74\x61\x6c\x61\x6e\x6f\x73\x20\x53\x7a\x65\x72\x7a\x6f\x64\x65\x73\x69\x20\x46\x65\x6c\x74\x65\x74\x65\x6c\x65\x6b\x62\x65\x6e\x20\x65\x6c\x6f\x69\x72\x74\x20\x65\x6c\x6c\x65\x6e\x6f\x72\x7a\x65\x73\x69\x20\x65\x6c\x6a\x61\x72\x61\x73\x20\x6d\x65\x67\x74\x65\x74\x65\x6c\x65\x2e\x20\x41\x20\x64\x6f\x6b\x75\x6d\x65\x6e\x74\x75\x6d\x6f\x6b\x20\x6d\x65\x67\x74\x61\x6c\x61\x6c\x68\x61\x74\x6f\x6b\x20\x61\x20\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x6e\x65\x74\x6c\x6f\x63\x6b\x2e\x68\x75\x2f\x64\x6f\x63\x73\x2f\x20\x63\x69\x6d\x65\x6e\x20\x76\x61\x67\x79\x20\x6b\x65\x72\x68\x65\x74\x6f\x6b\x20\x61\x7a\x20\x69\x6e\x66\x6f\x40\x6e\x65\x74\x6c\x6f\x63\x6b\x2e\x6e\x65\x74\x20\x65\x2d\x6d\x61\x69\x6c\x20\x63\x69\x6d\x65\x6e\x2e\x20\x57\x41\x52\x4e\x49\x4e\x47\x21\x20\x54\x68\x65\x20\x69\x73\x73\x75\x61\x6e\x63\x65\x20\x61\x6e\x64\x20\x74\x68\x65\x20\x75\x73\x65\x20\x6f\x66\x20\x74\x68\x69\x73\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x61\x72\x65\x20\x73\x75\x62\x6a\x65\x63\x74\x20\x74\x6f\x20\x74\x68\x65\x20\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x51\x75\x61\x6c\x69\x66\x69\x65\x64\x20\x43\x50\x53\x20\x61\x76\x61\x69\x6c\x61\x62\x6c\x65\x20\x61\x74\x20\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x6e\x65\x74\x6c\x6f\x63\x6b\x2e\x68\x75\x2f\x64\x6f\x63\x73\x2f\x20\x6f\x72\x20\x62\x79\x20\x65\x2d\x6d\x61\x69\x6c\x20\x61\x74\x20\x69\x6e\x66\x6f\x40\x6e\x65\x74\x6c\x6f\x63\x6b\x2e\x6e\x65\x74\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x09\x6a\x62\x16\x92\xb0\x5a\xbb\x55\x0e\xcb\x75\x32\x3a\x32\xe5\xb2\x21\xc9\x28\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x91\x6a\x50\x9c\xdb\x78\x81\x9b\x3f\x8b\x42\xe3\x3b\xfc\xa6\xc3\xee\x43\xe0\xcf\xf3\xe2\x80\x35\x49\x45\x76\x02\xe2\xe3\x2f\x05\xc5\xf1\x2a\xe7\xc0\x41\x33\xc6\xb6\x9b\xd0\x33\x39\xcd\xc0\xdb\xa1\xad\x6c\x37\x02\x4c\x58\x41\x3b\xf2\x97\x92\xc6\x48\xa8\xcd\xe5\x8a\x39\x89\x61\xf9\x52\x97\xe9\xbd\xf6\xf9\x94\x74\xe8\x71\x0e\xbc\x77\x86\xc3\x06\xcc\x5a\x7c\x4a\x7e\x34\x50\x30\x2e\xfb\x7f\x32\x9a\x8d\x3d\xf3\x20\x5b\xf8\x6a\xca\x86\xf3\x31\x4c\x2c\x59\x80\x02\x7d\xfe\x38\xc9\x30\x75\x1c\xb7\x55\xe3\xbc\x9f\xba\xa8\x6d\x84\x28\x05\x75\xb3\x8b\x0d\xc0\x91\x54\x21\xe7\xa6\x0b\xb4\x99\xf5\x51\x41\xdc\xcd\xa3\x47\x22\xd9\xc7\x01\x81\xc4\xdc\x47\x4f\x26\xea\x1f\xed\xdb\xcd\x0d\x98\xf4\xa3\x9c\xb4\x73\x32\x4a\x96\x99\xfe\xbc\x7f\xc8\x25\x58\xf8\x58\xf3\x76\x66\x89\x54\xa4\xa6\x3e\xc4\x50\x5c\xba\x89\x18\x82\x75\x48\x21\xd2\x4f\x13\xe8\x60\x7e\x07\x76\xdb\x10\xb5\x51\xe6\xaa\xb9\x68\xaa\xcd\xf6\x9d\x90\x75\x12\xea\x38\x1a\xca\x44\xe8\xb7\x99\xa7\x2a\x68\x95\x66\x95\xab\xad\xef\x89\xcb\x60\xa9\x06\x12\xc6\x94\x47\xe9\x28", 0 }, + /* Anchor: 103 NetworkSolutionsEVRoot.crt serial: #{a.serial.to_s} + C=US,O=Network Solutions L.L.C.,CN=Network Solutions Certificate Authority + */ + { 1002, "\x30\x82\x03\xe6\x30\x82\x02\xce\xa0\x03\x02\x01\x02\x02\x10\x57\xcb\x33\x6f\xc2\x5c\x16\xe6\x47\x16\x17\xe3\x90\x31\x68\xe0\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x62\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x21\x30\x1f\x06\x03\x55\x04\x0a\x13\x18\x4e\x65\x74\x77\x6f\x72\x6b\x20\x53\x6f\x6c\x75\x74\x69\x6f\x6e\x73\x20\x4c\x2e\x4c\x2e\x43\x2e\x31\x30\x30\x2e\x06\x03\x55\x04\x03\x13\x27\x4e\x65\x74\x77\x6f\x72\x6b\x20\x53\x6f\x6c\x75\x74\x69\x6f\x6e\x73\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x30\x36\x31\x32\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x39\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x62\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x21\x30\x1f\x06\x03\x55\x04\x0a\x13\x18\x4e\x65\x74\x77\x6f\x72\x6b\x20\x53\x6f\x6c\x75\x74\x69\x6f\x6e\x73\x20\x4c\x2e\x4c\x2e\x43\x2e\x31\x30\x30\x2e\x06\x03\x55\x04\x03\x13\x27\x4e\x65\x74\x77\x6f\x72\x6b\x20\x53\x6f\x6c\x75\x74\x69\x6f\x6e\x73\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xe4\xbc\x7e\x92\x30\x6d\xc6\xd8\x8e\x2b\x0b\xbc\x46\xce\xe0\x27\x96\xde\xde\xf9\xfa\x12\xd3\x3c\x33\x73\xb3\x04\x2f\xbc\x71\x8c\xe5\x9f\xb6\x22\x60\x3e\x5f\x5d\xce\x09\xff\x82\x0c\x1b\x9a\x51\x50\x1a\x26\x89\xdd\xd5\x61\x5d\x19\xdc\x12\x0f\x2d\x0a\xa2\x43\x5d\x17\xd0\x34\x92\x20\xea\x73\xcf\x38\x2c\x06\x26\x09\x7a\x72\xf7\xfa\x50\x32\xf8\xc2\x93\xd3\x69\xa2\x23\xce\x41\xb1\xcc\xe4\xd5\x1f\x36\xd1\x8a\x3a\xf8\x8c\x63\xe2\x14\x59\x69\xed\x0d\xd3\x7f\x6b\xe8\xb8\x03\xe5\x4f\x6a\xe5\x98\x63\x69\x48\x05\xbe\x2e\xff\x33\xb6\xe9\x97\x59\x69\xf8\x67\x19\xae\x93\x61\x96\x44\x15\xd3\x72\xb0\x3f\xbc\x6a\x7d\xec\x48\x7f\x8d\xc3\xab\xaa\x71\x2b\x53\x69\x41\x53\x34\xb5\xb0\xb9\xc5\x06\x0a\xc4\xb0\x45\xf5\x41\x5d\x6e\x89\x45\x7b\x3d\x3b\x26\x8c\x74\xc2\xe5\xd2\xd1\x7d\xb2\x11\xd4\xfb\x58\x32\x22\x9a\x80\xc9\xdc\xfd\x0c\xe9\x7f\x5e\x03\x97\xce\x3b\x00\x14\x87\x27\x70\x38\xa9\x8e\x6e\xb3\x27\x76\x98\x51\xe0\x05\xe3\x21\xab\x1a\xd5\x85\x22\x3c\x29\xb5\x9a\x16\xc5\x80\xa8\xf4\xbb\x6b\x30\x8f\x2f\x46\x02\xa2\xb1\x0c\x22\xe0\xd3\x02\x03\x01\x00\x01\xa3\x81\x97\x30\x81\x94\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x21\x30\xc9\xfb\x00\xd7\x4e\x98\xda\x87\xaa\x2a\xd0\xa7\x2e\xb1\x40\x31\xa7\x4c\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x52\x06\x03\x55\x1d\x1f\x04\x4b\x30\x49\x30\x47\xa0\x45\xa0\x43\x86\x41\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x6e\x65\x74\x73\x6f\x6c\x73\x73\x6c\x2e\x63\x6f\x6d\x2f\x4e\x65\x74\x77\x6f\x72\x6b\x53\x6f\x6c\x75\x74\x69\x6f\x6e\x73\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x2e\x63\x72\x6c\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xbb\xae\x4b\xe7\xb7\x57\xeb\x7f\xaa\x2d\xb7\x73\x47\x85\x6a\xc1\xe4\xa5\x1d\xe4\xe7\x3c\xe9\xf4\x59\x65\x77\xb5\x7a\x5b\x5a\x8d\x25\x36\xe0\x7a\x97\x2e\x38\xc0\x57\x60\x83\x98\x06\x83\x9f\xb9\x76\x7a\x6e\x50\xe0\xba\x88\x2c\xfc\x45\xcc\x18\xb0\x99\x95\x51\x0e\xec\x1d\xb8\x88\xff\x87\x50\x1c\x82\xc2\xe3\xe0\x32\x80\xbf\xa0\x0b\x47\xc8\xc3\x31\xef\x99\x67\x32\x80\x4f\x17\x21\x79\x0c\x69\x5c\xde\x5e\x34\xae\x02\xb5\x26\xea\x50\xdf\x7f\x18\x65\x2c\xc9\xf2\x63\xe1\xa9\x07\xfe\x7c\x71\x1f\x6b\x33\x24\x6a\x1e\x05\xf7\x05\x68\xc0\x6a\x12\xcb\x2e\x5e\x61\xcb\xae\x28\xd3\x7e\xc2\xb4\x66\x91\x26\x5f\x3c\x2e\x24\x5f\xcb\x58\x0f\xeb\x28\xec\xaf\x11\x96\xf3\xdc\x7b\x6f\xc0\xa7\x88\xf2\x53\x77\xb3\x60\x5e\xae\xae\x28\xda\x35\x2c\x6f\x34\x45\xd3\x26\xe1\xde\xec\x5b\x4f\x27\x6b\x16\x7c\xbd\x44\x04\x18\x82\xb3\x89\x79\x17\x10\x71\x3d\x7a\xa2\x16\x4e\xf5\x01\xcd\xa4\x6c\x65\x68\xa1\x49\x76\x5c\x43\xc9\xd8\xbc\x36\x67\x6c\xa5\x94\xb5\xd4\xcc\xb9\xbd\x6a\x35\x56\x21\xde\xd8\xc3\xeb\xfb\xcb\xa4\x60\x4c\xb0\x55\xa0\xa0\x7b\x57\xb2", 0 }, + /* Anchor: 104 PCA1ss_v4.509 serial: #{a.serial.to_s} + C=US,O=VeriSign\, Inc.,OU=Class 1 Public Primary Certification Authority + */ + { 577, "\x30\x82\x02\x3d\x30\x82\x01\xa6\x02\x11\x00\xcd\xba\x7f\x56\xf0\xdf\xe4\xbc\x54\xfe\x22\xac\xb3\x72\xaa\x55\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x02\x05\x00\x30\x5f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x37\x30\x35\x06\x03\x55\x04\x0b\x13\x2e\x43\x6c\x61\x73\x73\x20\x31\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x39\x36\x30\x31\x32\x39\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x38\x30\x38\x30\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x5f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x37\x30\x35\x06\x03\x55\x04\x0b\x13\x2e\x43\x6c\x61\x73\x73\x20\x31\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xe5\x19\xbf\x6d\xa3\x56\x61\x2d\x99\x48\x71\xf6\x67\xde\xb9\x8d\xeb\xb7\x9e\x86\x80\x0a\x91\x0e\xfa\x38\x25\xaf\x46\x88\x82\xe5\x73\xa8\xa0\x9b\x24\x5d\x0d\x1f\xcc\x65\x6e\x0c\xb0\xd0\x56\x84\x18\x87\x9a\x06\x9b\x10\xa1\x73\xdf\xb4\x58\x39\x6b\x6e\xc1\xf6\x15\xd5\xa8\xa8\x3f\xaa\x12\x06\x8d\x31\xac\x7f\xb0\x34\xd7\x8f\x34\x67\x88\x09\xcd\x14\x11\xe2\x4e\x45\x56\x69\x1f\x78\x02\x80\xda\xdc\x47\x91\x29\xbb\x36\xc9\x63\x5c\xc5\xe0\xd7\x2d\x87\x7b\xa1\xb7\x32\xb0\x7b\x30\xba\x2a\x2f\x31\xaa\xee\xa3\x67\xda\xdb\x02\x03\x01\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x02\x05\x00\x03\x81\x81\x00\x4c\x3f\xb8\x8b\xc6\x68\xdf\xee\x43\x33\x0e\x5d\xe9\xa6\xcb\x07\x84\x4d\x7a\x33\xff\x92\x1b\xf4\x36\xad\xd8\x95\x22\x36\x68\x11\x6c\x7c\x42\xcc\xf3\x9c\x2e\xc4\x07\x3f\x14\xb0\x0f\x4f\xff\x90\x92\x76\xf9\xe2\xbc\x4a\xe9\x8f\xcd\xa0\x80\x0a\xf7\xc5\x29\xf1\x82\x22\x5d\xb8\xb1\xdd\x81\x23\xa3\x7b\x25\x15\x46\x30\x79\x16\xf8\xea\x05\x4b\x94\x7f\x1d\xc2\x1c\xc8\xe3\xb7\xf4\x10\x40\x3c\x13\xc3\x5f\x1f\x53\xe8\x48\xe4\x86\xb4\x7b\xa1\x35\xb0\x7b\x25\xba\xb8\xd3\x8e\xab\x3f\x38\x9d\x00\x34\x00\x98\xf3\xd1\x71\x94", 105 }, + /* Anchor: 105 VerisignSHA1_1024_PCA1_G1.cer serial: #{a.serial.to_s} + C=US,O=VeriSign\, Inc.,OU=Class 1 Public Primary Certification Authority + */ + { 576, "\x30\x82\x02\x3c\x30\x82\x01\xa5\x02\x10\x3f\x69\x1e\x81\x9c\xf0\x9a\x4a\xf3\x73\xff\xb9\x48\xa2\xe4\xdd\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x5f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x37\x30\x35\x06\x03\x55\x04\x0b\x13\x2e\x43\x6c\x61\x73\x73\x20\x31\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x39\x36\x30\x31\x32\x39\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x38\x30\x38\x30\x32\x32\x33\x35\x39\x35\x39\x5a\x30\x5f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x37\x30\x35\x06\x03\x55\x04\x0b\x13\x2e\x43\x6c\x61\x73\x73\x20\x31\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xe5\x19\xbf\x6d\xa3\x56\x61\x2d\x99\x48\x71\xf6\x67\xde\xb9\x8d\xeb\xb7\x9e\x86\x80\x0a\x91\x0e\xfa\x38\x25\xaf\x46\x88\x82\xe5\x73\xa8\xa0\x9b\x24\x5d\x0d\x1f\xcc\x65\x6e\x0c\xb0\xd0\x56\x84\x18\x87\x9a\x06\x9b\x10\xa1\x73\xdf\xb4\x58\x39\x6b\x6e\xc1\xf6\x15\xd5\xa8\xa8\x3f\xaa\x12\x06\x8d\x31\xac\x7f\xb0\x34\xd7\x8f\x34\x67\x88\x09\xcd\x14\x11\xe2\x4e\x45\x56\x69\x1f\x78\x02\x80\xda\xdc\x47\x91\x29\xbb\x36\xc9\x63\x5c\xc5\xe0\xd7\x2d\x87\x7b\xa1\xb7\x32\xb0\x7b\x30\xba\x2a\x2f\x31\xaa\xee\xa3\x67\xda\xdb\x02\x03\x01\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x58\x15\x29\x39\x3c\x77\xa3\xda\x5c\x25\x03\x7c\x60\xfa\xee\x09\x99\x3c\x27\x10\x70\xc8\x0c\x09\xe6\xb3\x87\xcf\x0a\xe2\x18\x96\x35\x62\xcc\xbf\x9b\x27\x79\x89\x5f\xc9\xc4\x09\xf4\xce\xb5\x1d\xdf\x2a\xbd\xe5\xdb\x86\x9c\x68\x25\xe5\x30\x7c\xb6\x89\x15\xfe\x67\xd1\xad\xe1\x50\xac\x3c\x7c\x62\x4b\x8f\xba\x84\xd7\x12\x15\x1b\x1f\xca\x5d\x0f\xc1\x52\x94\x2a\x11\x99\xda\x7b\xcf\x0c\x36\x13\xd5\x35\xdc\x10\x19\x59\xea\x94\xc1\x00\xbf\x75\x8f\xd9\xfa\xfd\x76\x04\xdb\x62\xbb\x90\x6a\x03\xd9\x46\x35\xd9\xf8\x7c\x5b", 0 }, + /* Anchor: 106 PCA2ss_v4.509 serial: #{a.serial.to_s} + C=US,O=VeriSign\, Inc.,OU=Class 2 Public Primary Certification Authority + */ + { 576, "\x30\x82\x02\x3c\x30\x82\x01\xa5\x02\x10\x2d\x1b\xfc\x4a\x17\x8d\xa3\x91\xeb\xe7\xff\xf5\x8b\x45\xbe\x0b\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x02\x05\x00\x30\x5f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x37\x30\x35\x06\x03\x55\x04\x0b\x13\x2e\x43\x6c\x61\x73\x73\x20\x32\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x39\x36\x30\x31\x32\x39\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x38\x30\x38\x30\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x5f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x37\x30\x35\x06\x03\x55\x04\x0b\x13\x2e\x43\x6c\x61\x73\x73\x20\x32\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xb6\x5a\x8b\xa3\x0d\x6a\x23\x83\x80\x6b\xcf\x39\x87\xf4\x21\x13\x33\x06\x4c\x25\xa2\xed\x55\x12\x97\xc5\xa7\x80\xb9\xfa\x83\xc1\x20\xa0\xfa\x2f\x15\x0d\x7c\xa1\x60\x6b\x7e\x79\x2c\xfa\x06\x0f\x3a\xae\xf6\x1b\x6f\xb1\xd2\xff\x2f\x28\x52\x5f\x83\x7d\x4b\xc4\x7a\xb7\xf8\x66\x1f\x80\x54\xfc\xb7\xc2\x8e\x59\x4a\x14\x57\x46\xd1\x9a\x93\xbe\x41\x91\x03\xbb\x15\x80\x93\x5c\xeb\xe7\xcc\x08\x6c\x3f\x3e\xb3\x4a\xfc\xff\x4b\x6c\x23\xd5\x50\x82\x26\x44\x19\x8e\x23\xc3\x71\xea\x19\x24\x47\x04\x9e\x75\xbf\xc8\xa6\x00\x1f\x02\x03\x01\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x02\x05\x00\x03\x81\x81\x00\x8a\x1b\x2b\xfa\x39\xc1\x74\xd7\x5e\xd8\x19\x64\xa2\x58\x4a\x2d\x37\xe0\x33\x47\x0f\xac\xed\xf7\xaa\xdb\x1e\xe4\x8b\x06\x5c\x60\x27\xca\x45\x52\xce\x16\xef\x3f\x06\x64\xe7\x94\x68\x7c\x60\x33\x15\x11\x69\xaf\x9d\x62\x8d\xa3\x03\x54\x6b\xa6\xbe\xe5\xee\x05\x18\x60\x04\xbf\x42\x80\xfd\xd0\xa8\xa8\x1e\x01\x3b\xf7\xa3\x5c\xaf\xa3\xdc\xe6\x26\x80\x23\x3c\xb8\x44\x74\xf7\x0a\xae\x49\x8b\x61\x78\xcc\x24\xbf\x88\x8a\xa7\x0e\xea\x73\x19\x41\xfd\x4d\x03\xf0\x88\xd1\xe5\x78\x8d\xa5\x2a\x4f\xf6\x97\x0d\x17\x77\xca\xd8", 107 }, + /* Anchor: 107 VerisignSHA1_1024_PCA2_G1.cer serial: #{a.serial.to_s} + C=US,O=VeriSign\, Inc.,OU=Class 2 Public Primary Certification Authority + */ + { 576, "\x30\x82\x02\x3c\x30\x82\x01\xa5\x02\x10\x0a\xba\x1e\x00\x62\x32\xe8\xb4\x36\x26\x5d\x1f\x7c\xcd\x89\x66\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x5f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x37\x30\x35\x06\x03\x55\x04\x0b\x13\x2e\x43\x6c\x61\x73\x73\x20\x32\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x39\x36\x30\x31\x32\x39\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x38\x30\x38\x30\x32\x32\x33\x35\x39\x35\x39\x5a\x30\x5f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x37\x30\x35\x06\x03\x55\x04\x0b\x13\x2e\x43\x6c\x61\x73\x73\x20\x32\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xb6\x5a\x8b\xa3\x0d\x6a\x23\x83\x80\x6b\xcf\x39\x87\xf4\x21\x13\x33\x06\x4c\x25\xa2\xed\x55\x12\x97\xc5\xa7\x80\xb9\xfa\x83\xc1\x20\xa0\xfa\x2f\x15\x0d\x7c\xa1\x60\x6b\x7e\x79\x2c\xfa\x06\x0f\x3a\xae\xf6\x1b\x6f\xb1\xd2\xff\x2f\x28\x52\x5f\x83\x7d\x4b\xc4\x7a\xb7\xf8\x66\x1f\x80\x54\xfc\xb7\xc2\x8e\x59\x4a\x14\x57\x46\xd1\x9a\x93\xbe\x41\x91\x03\xbb\x15\x80\x93\x5c\xeb\xe7\xcc\x08\x6c\x3f\x3e\xb3\x4a\xfc\xff\x4b\x6c\x23\xd5\x50\x82\x26\x44\x19\x8e\x23\xc3\x71\xea\x19\x24\x47\x04\x9e\x75\xbf\xc8\xa6\x00\x1f\x02\x03\x01\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x80\xd3\xa0\x0f\x88\xc9\xe5\x68\x5b\x84\x7b\x80\x1f\xa7\xb7\xe3\x23\x58\x11\x1c\xf5\x14\xf0\x58\x12\x8c\x8b\xdf\x71\xd9\x90\x24\x11\x7c\xa0\x7b\xc3\x7a\x19\x19\xbd\x72\xbd\x20\xbf\x00\x3a\xdf\xfa\xd5\x7a\xcc\xc2\xe3\x62\x45\x8b\xcb\x49\x83\x98\xc1\x70\x69\xd0\x9e\x5e\x82\x8c\x35\x47\x8e\x4f\x1b\xb4\x1f\x63\x01\xad\xe4\x96\xd6\xb1\xee\x7a\x2c\x66\x6e\x17\x36\xaf\x1a\x7e\x38\x06\x86\x2c\x6b\x4d\xcb\x27\x92\x6e\x78\xbf\x00\xd5\x01\xc0\xb1\x07\xc3\x09\xaa\x64\x85\x28\xf2\x9d\x73\x9e\xcf\x60\x3a\x0a\x1d\x4a\x48", 0 }, + /* Anchor: 108 PCA3ss_v4.509 serial: #{a.serial.to_s} + C=US,O=VeriSign\, Inc.,OU=Class 3 Public Primary Certification Authority + */ + { 576, "\x30\x82\x02\x3c\x30\x82\x01\xa5\x02\x10\x70\xba\xe4\x1d\x10\xd9\x29\x34\xb6\x38\xca\x7b\x03\xcc\xba\xbf\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x02\x05\x00\x30\x5f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x37\x30\x35\x06\x03\x55\x04\x0b\x13\x2e\x43\x6c\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x39\x36\x30\x31\x32\x39\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x38\x30\x38\x30\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x5f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x37\x30\x35\x06\x03\x55\x04\x0b\x13\x2e\x43\x6c\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xc9\x5c\x59\x9e\xf2\x1b\x8a\x01\x14\xb4\x10\xdf\x04\x40\xdb\xe3\x57\xaf\x6a\x45\x40\x8f\x84\x0c\x0b\xd1\x33\xd9\xd9\x11\xcf\xee\x02\x58\x1f\x25\xf7\x2a\xa8\x44\x05\xaa\xec\x03\x1f\x78\x7f\x9e\x93\xb9\x9a\x00\xaa\x23\x7d\xd6\xac\x85\xa2\x63\x45\xc7\x72\x27\xcc\xf4\x4c\xc6\x75\x71\xd2\x39\xef\x4f\x42\xf0\x75\xdf\x0a\x90\xc6\x8e\x20\x6f\x98\x0f\xf8\xac\x23\x5f\x70\x29\x36\xa4\xc9\x86\xe7\xb1\x9a\x20\xcb\x53\xa5\x85\xe7\x3d\xbe\x7d\x9a\xfe\x24\x45\x33\xdc\x76\x15\xed\x0f\xa2\x71\x64\x4c\x65\x2e\x81\x68\x45\xa7\x02\x03\x01\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x02\x05\x00\x03\x81\x81\x00\xbb\x4c\x12\x2b\xcf\x2c\x26\x00\x4f\x14\x13\xdd\xa6\xfb\xfc\x0a\x11\x84\x8c\xf3\x28\x1c\x67\x92\x2f\x7c\xb6\xc5\xfa\xdf\xf0\xe8\x95\xbc\x1d\x8f\x6c\x2c\xa8\x51\xcc\x73\xd8\xa4\xc0\x53\xf0\x4e\xd6\x26\xc0\x76\x01\x57\x81\x92\x5e\x21\xf1\xd1\xb1\xff\xe7\xd0\x21\x58\xcd\x69\x17\xe3\x44\x1c\x9c\x19\x44\x39\x89\x5c\xdc\x9c\x00\x0f\x56\x8d\x02\x99\xed\xa2\x90\x45\x4c\xe4\xbb\x10\xa4\x3d\xf0\x32\x03\x0e\xf1\xce\xf8\xe8\xc9\x51\x8c\xe6\x62\x9f\xe6\x9f\xc0\x7d\xb7\x72\x9c\xc9\x36\x3a\x6b\x9f\x4e\xa8\xff\x64\x0d\x64", 109 }, + /* Anchor: 109 VerisignSHA1_1024_PCA3_G1.cer serial: #{a.serial.to_s} + C=US,O=VeriSign\, Inc.,OU=Class 3 Public Primary Certification Authority + */ + { 576, "\x30\x82\x02\x3c\x30\x82\x01\xa5\x02\x10\x3c\x91\x31\xcb\x1f\xf6\xd0\x1b\x0e\x9a\xb8\xd0\x44\xbf\x12\xbe\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x5f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x37\x30\x35\x06\x03\x55\x04\x0b\x13\x2e\x43\x6c\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x39\x36\x30\x31\x32\x39\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x38\x30\x38\x30\x32\x32\x33\x35\x39\x35\x39\x5a\x30\x5f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x37\x30\x35\x06\x03\x55\x04\x0b\x13\x2e\x43\x6c\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xc9\x5c\x59\x9e\xf2\x1b\x8a\x01\x14\xb4\x10\xdf\x04\x40\xdb\xe3\x57\xaf\x6a\x45\x40\x8f\x84\x0c\x0b\xd1\x33\xd9\xd9\x11\xcf\xee\x02\x58\x1f\x25\xf7\x2a\xa8\x44\x05\xaa\xec\x03\x1f\x78\x7f\x9e\x93\xb9\x9a\x00\xaa\x23\x7d\xd6\xac\x85\xa2\x63\x45\xc7\x72\x27\xcc\xf4\x4c\xc6\x75\x71\xd2\x39\xef\x4f\x42\xf0\x75\xdf\x0a\x90\xc6\x8e\x20\x6f\x98\x0f\xf8\xac\x23\x5f\x70\x29\x36\xa4\xc9\x86\xe7\xb1\x9a\x20\xcb\x53\xa5\x85\xe7\x3d\xbe\x7d\x9a\xfe\x24\x45\x33\xdc\x76\x15\xed\x0f\xa2\x71\x64\x4c\x65\x2e\x81\x68\x45\xa7\x02\x03\x01\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x10\x72\x52\xa9\x05\x14\x19\x32\x08\x41\xf0\xc5\x6b\x0a\xcc\x7e\x0f\x21\x19\xcd\xe4\x67\xdc\x5f\xa9\x1b\xe6\xca\xe8\x73\x9d\x22\xd8\x98\x6e\x73\x03\x61\x91\xc5\x7c\xb0\x45\x40\x6e\x44\x9d\x8d\xb0\xb1\x96\x74\x61\x2d\x0d\xa9\x45\xd2\xa4\x92\x2a\xd6\x9a\x75\x97\x6e\x3f\x53\xfd\x45\x99\x60\x1d\xa8\x2b\x4c\xf9\x5e\xa7\x09\xd8\x75\x30\xd7\xd2\x65\x60\x3d\x67\xd6\x48\x55\x75\x69\x3f\x91\xf5\x48\x0b\x47\x69\x22\x69\x82\x96\xbe\xc9\xc8\x38\x86\x4a\x7a\x2c\x73\x19\x48\x69\x4e\x6b\x7c\x65\xbf\x0f\xfc\x70\xce\x88\x90", 0 }, + /* Anchor: 110 persbasi.crt serial: #{a.serial.to_s} + C=ZA,ST=Western Cape,L=Cape Town,O=Thawte Consulting,OU=Certification Services Division,CN=Thawte Personal Basic CA,1.2.840.113549.1.9.1=#1619706572736F6E616C2D6261736963407468617774652E636F6D + */ + { 805, "\x30\x82\x03\x21\x30\x82\x02\x8a\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x30\x81\xcb\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6f\x77\x6e\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x13\x11\x54\x68\x61\x77\x74\x65\x20\x43\x6f\x6e\x73\x75\x6c\x74\x69\x6e\x67\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x54\x68\x61\x77\x74\x65\x20\x50\x65\x72\x73\x6f\x6e\x61\x6c\x20\x42\x61\x73\x69\x63\x20\x43\x41\x31\x28\x30\x26\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x19\x70\x65\x72\x73\x6f\x6e\x61\x6c\x2d\x62\x61\x73\x69\x63\x40\x74\x68\x61\x77\x74\x65\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x39\x36\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x30\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xcb\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6f\x77\x6e\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x13\x11\x54\x68\x61\x77\x74\x65\x20\x43\x6f\x6e\x73\x75\x6c\x74\x69\x6e\x67\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x54\x68\x61\x77\x74\x65\x20\x50\x65\x72\x73\x6f\x6e\x61\x6c\x20\x42\x61\x73\x69\x63\x20\x43\x41\x31\x28\x30\x26\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x19\x70\x65\x72\x73\x6f\x6e\x61\x6c\x2d\x62\x61\x73\x69\x63\x40\x74\x68\x61\x77\x74\x65\x2e\x63\x6f\x6d\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xbc\xbc\x93\x53\x6d\xc0\x50\x4f\x82\x15\xe6\x48\x94\x35\xa6\x5a\xbe\x6f\x42\xfa\x0f\x47\xee\x77\x75\x72\xdd\x8d\x49\x9b\x96\x57\xa0\x78\xd4\xca\x3f\x51\xb3\x69\x0b\x91\x76\x17\x22\x07\x97\x6a\xc4\x51\x93\x4b\xe0\x8d\xef\x37\x95\xa1\x0c\x4d\xda\x34\x90\x1d\x17\x89\x97\xe0\x35\x38\x57\x4a\xc0\xf4\x08\x70\xe9\x3c\x44\x7b\x50\x7e\x61\x9a\x90\xe3\x23\xd3\x88\x11\x46\x27\xf5\x0b\x07\x0e\xbb\xdd\xd1\x7f\x20\x0a\x88\xb9\x56\x0b\x2e\x1c\x80\xda\xf1\xe3\x9e\x29\xef\x14\xbd\x0a\x44\xfb\x1b\x5b\x18\xd1\xbf\x23\x93\x21\x02\x03\x01\x00\x01\xa3\x13\x30\x11\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x03\x81\x81\x00\x2d\xe2\x99\x6b\xb0\x3d\x7a\x89\xd7\x59\xa2\x94\x01\x1f\x2b\xdd\x12\x4b\x53\xc2\xad\x7f\xaa\xa7\x00\x5c\x91\x40\x57\x25\x4a\x38\xaa\x84\x70\xb9\xd9\x80\x0f\xa5\x7b\x5c\xfb\x73\xc6\xbd\xd7\x8a\x61\x5c\x03\xe3\x2d\x27\xa8\x17\xe0\x84\x85\x42\xdc\x5e\x9b\xc6\xb7\xb2\x6d\xbb\x74\xaf\xe4\x3f\xcb\xa7\xb7\xb0\xe0\x5d\xbe\x78\x83\x25\x94\xd2\xdb\x81\x0f\x79\x07\x6d\x4f\xf4\x39\x15\x5a\x52\x01\x7b\xde\x32\xd6\x4d\x38\xf6\x12\x5c\x06\x50\xdf\x05\x5b\xbd\x14\x4b\xa1\xdf\x29\xba\x3b\x41\x8d\xf7\x63\x56\xa1\xdf\x22\xb1", 111 }, + /* Anchor: 111 Thawte_Personal_Basic_CA.cer serial: #{a.serial.to_s} + C=ZA,ST=Western Cape,L=Cape Town,O=Thawte Consulting,OU=Certification Services Division,CN=Thawte Personal Basic CA,1.2.840.113549.1.9.1=#1619706572736F6E616C2D6261736963407468617774652E636F6D + */ + { 820, "\x30\x82\x03\x30\x30\x82\x02\x99\xa0\x03\x02\x01\x02\x02\x10\x0d\x8e\x15\x12\xe1\xac\xbb\x77\x8d\x38\xe3\x24\xdf\x8c\x30\xf2\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xcb\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6f\x77\x6e\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x13\x11\x54\x68\x61\x77\x74\x65\x20\x43\x6f\x6e\x73\x75\x6c\x74\x69\x6e\x67\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x54\x68\x61\x77\x74\x65\x20\x50\x65\x72\x73\x6f\x6e\x61\x6c\x20\x42\x61\x73\x69\x63\x20\x43\x41\x31\x28\x30\x26\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x19\x70\x65\x72\x73\x6f\x6e\x61\x6c\x2d\x62\x61\x73\x69\x63\x40\x74\x68\x61\x77\x74\x65\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x39\x36\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x31\x30\x31\x30\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xcb\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6f\x77\x6e\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x13\x11\x54\x68\x61\x77\x74\x65\x20\x43\x6f\x6e\x73\x75\x6c\x74\x69\x6e\x67\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x54\x68\x61\x77\x74\x65\x20\x50\x65\x72\x73\x6f\x6e\x61\x6c\x20\x42\x61\x73\x69\x63\x20\x43\x41\x31\x28\x30\x26\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x19\x70\x65\x72\x73\x6f\x6e\x61\x6c\x2d\x62\x61\x73\x69\x63\x40\x74\x68\x61\x77\x74\x65\x2e\x63\x6f\x6d\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xbc\xbc\x93\x53\x6d\xc0\x50\x4f\x82\x15\xe6\x48\x94\x35\xa6\x5a\xbe\x6f\x42\xfa\x0f\x47\xee\x77\x75\x72\xdd\x8d\x49\x9b\x96\x57\xa0\x78\xd4\xca\x3f\x51\xb3\x69\x0b\x91\x76\x17\x22\x07\x97\x6a\xc4\x51\x93\x4b\xe0\x8d\xef\x37\x95\xa1\x0c\x4d\xda\x34\x90\x1d\x17\x89\x97\xe0\x35\x38\x57\x4a\xc0\xf4\x08\x70\xe9\x3c\x44\x7b\x50\x7e\x61\x9a\x90\xe3\x23\xd3\x88\x11\x46\x27\xf5\x0b\x07\x0e\xbb\xdd\xd1\x7f\x20\x0a\x88\xb9\x56\x0b\x2e\x1c\x80\xda\xf1\xe3\x9e\x29\xef\x14\xbd\x0a\x44\xfb\x1b\x5b\x18\xd1\xbf\x23\x93\x21\x02\x03\x01\x00\x01\xa3\x13\x30\x11\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x88\x3b\xfe\xb8\xf9\x7a\x42\x46\x11\xa0\xa4\xa2\x64\x85\xcd\x48\x1c\x9c\xd5\x8a\x51\xcd\x2f\xc1\x7d\xb1\x07\xcf\xd7\x01\xde\x32\x3f\x96\xe4\x84\xfe\xd1\x5e\xad\x0c\x7e\x0e\x63\x49\x6a\x0e\x10\xe4\x97\xd0\x3f\xc5\xa7\x29\xd9\xa6\x53\x1e\x4b\x1e\x3f\x54\xfa\xc0\x84\x35\x73\xea\x91\xa9\xdc\x5d\x93\x57\x05\x06\x0c\x07\xb9\xaf\x0b\x44\x39\x88\x21\xa0\xee\x82\x73\xa9\x46\x2f\x69\x6c\x25\x74\xa9\xcd\xdf\xa7\xd7\xfd\x85\x30\x04\x94\x35\x4a\xa7\x1b\x33\x24\x2c\x44\x16\xed\x0a\xc4\xdf\x80\xaa\x65\x1a\xbf\x71\x26\xf0", 0 }, + /* Anchor: 112 persfree.crt serial: #{a.serial.to_s} + C=ZA,ST=Western Cape,L=Cape Town,O=Thawte Consulting,OU=Certification Services Division,CN=Thawte Personal Freemail CA,1.2.840.113549.1.9.1=#161C706572736F6E616C2D667265656D61696C407468617774652E636F6D + */ + { 817, "\x30\x82\x03\x2d\x30\x82\x02\x96\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x30\x81\xd1\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6f\x77\x6e\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x13\x11\x54\x68\x61\x77\x74\x65\x20\x43\x6f\x6e\x73\x75\x6c\x74\x69\x6e\x67\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1b\x54\x68\x61\x77\x74\x65\x20\x50\x65\x72\x73\x6f\x6e\x61\x6c\x20\x46\x72\x65\x65\x6d\x61\x69\x6c\x20\x43\x41\x31\x2b\x30\x29\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x1c\x70\x65\x72\x73\x6f\x6e\x61\x6c\x2d\x66\x72\x65\x65\x6d\x61\x69\x6c\x40\x74\x68\x61\x77\x74\x65\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x39\x36\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x30\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xd1\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6f\x77\x6e\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x13\x11\x54\x68\x61\x77\x74\x65\x20\x43\x6f\x6e\x73\x75\x6c\x74\x69\x6e\x67\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1b\x54\x68\x61\x77\x74\x65\x20\x50\x65\x72\x73\x6f\x6e\x61\x6c\x20\x46\x72\x65\x65\x6d\x61\x69\x6c\x20\x43\x41\x31\x2b\x30\x29\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x1c\x70\x65\x72\x73\x6f\x6e\x61\x6c\x2d\x66\x72\x65\x65\x6d\x61\x69\x6c\x40\x74\x68\x61\x77\x74\x65\x2e\x63\x6f\x6d\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd4\x69\xd7\xd4\xb0\x94\x64\x5b\x71\xe9\x47\xd8\x0c\x51\xb6\xea\x72\x91\xb0\x84\x5e\x7d\x2d\x0d\x8f\x7b\x12\xdf\x85\x25\x75\x28\x74\x3a\x42\x2c\x63\x27\x9f\x95\x7b\x4b\xef\x7e\x19\x87\x1d\x86\xea\xa3\xdd\xb9\xce\x96\x64\x1a\xc2\x14\x6e\x44\xac\x7c\xe6\x8f\xe8\x4d\x0f\x71\x1f\x40\x38\xa6\x00\xa3\x87\x78\xf6\xf9\x94\x86\x5e\xad\xea\xc0\x5e\x76\xeb\xd9\x14\xa3\x5d\x6e\x7a\x7c\x0c\xa5\x4b\x55\x7f\x06\x19\x29\x7f\x9e\x9a\x26\xd5\x6a\xbb\x38\x24\x08\x6a\x98\xc7\xb1\xda\xa3\x98\x91\xfd\x79\xdb\xe5\x5a\xc4\x1c\xb9\x02\x03\x01\x00\x01\xa3\x13\x30\x11\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x03\x81\x81\x00\xc7\xec\x92\x7e\x4e\xf8\xf5\x96\xa5\x67\x62\x2a\xa4\xf0\x4d\x11\x60\xd0\x6f\x8d\x60\x58\x61\xac\x26\xbb\x52\x35\x5c\x08\xcf\x30\xfb\xa8\x4a\x96\x8a\x1f\x62\x42\x23\x8c\x17\x0f\xf4\xba\x64\x9c\x17\xac\x47\x29\xdf\x9d\x98\x5e\xd2\x6c\x60\x71\x5c\xa2\xac\xdc\x79\xe3\xe7\x6e\x00\x47\x1f\xb5\x0d\x28\xe8\x02\x9d\xe4\x9a\xfd\x13\xf4\xa6\xd9\x7c\xb1\xf8\xdc\x5f\x23\x26\x09\x91\x80\x73\xd0\x14\x1b\xde\x43\xa9\x83\x25\xf2\xe6\x9c\x2f\x15\xca\xfe\xa6\xab\x8a\x07\x75\x8b\x0c\xdd\x51\x84\x6b\xe4\xf8\xd1\xce\x77\xa2\x81", 113 }, + /* Anchor: 113 Thawte_Personal_Freemail_CA.cer serial: #{a.serial.to_s} + C=ZA,ST=Western Cape,L=Cape Town,O=Thawte Consulting,OU=Certification Services Division,CN=Thawte Personal Freemail CA,1.2.840.113549.1.9.1=#161C706572736F6E616C2D667265656D61696C407468617774652E636F6D + */ + { 832, "\x30\x82\x03\x3c\x30\x82\x02\xa5\xa0\x03\x02\x01\x02\x02\x10\x12\x3d\xf0\xe7\xda\x2a\x22\x47\xa4\x38\x89\xe0\x8a\xee\xc9\x67\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xd1\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6f\x77\x6e\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x13\x11\x54\x68\x61\x77\x74\x65\x20\x43\x6f\x6e\x73\x75\x6c\x74\x69\x6e\x67\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1b\x54\x68\x61\x77\x74\x65\x20\x50\x65\x72\x73\x6f\x6e\x61\x6c\x20\x46\x72\x65\x65\x6d\x61\x69\x6c\x20\x43\x41\x31\x2b\x30\x29\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x1c\x70\x65\x72\x73\x6f\x6e\x61\x6c\x2d\x66\x72\x65\x65\x6d\x61\x69\x6c\x40\x74\x68\x61\x77\x74\x65\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x39\x36\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x31\x30\x31\x30\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xd1\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6f\x77\x6e\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x13\x11\x54\x68\x61\x77\x74\x65\x20\x43\x6f\x6e\x73\x75\x6c\x74\x69\x6e\x67\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1b\x54\x68\x61\x77\x74\x65\x20\x50\x65\x72\x73\x6f\x6e\x61\x6c\x20\x46\x72\x65\x65\x6d\x61\x69\x6c\x20\x43\x41\x31\x2b\x30\x29\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x1c\x70\x65\x72\x73\x6f\x6e\x61\x6c\x2d\x66\x72\x65\x65\x6d\x61\x69\x6c\x40\x74\x68\x61\x77\x74\x65\x2e\x63\x6f\x6d\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd4\x69\xd7\xd4\xb0\x94\x64\x5b\x71\xe9\x47\xd8\x0c\x51\xb6\xea\x72\x91\xb0\x84\x5e\x7d\x2d\x0d\x8f\x7b\x12\xdf\x85\x25\x75\x28\x74\x3a\x42\x2c\x63\x27\x9f\x95\x7b\x4b\xef\x7e\x19\x87\x1d\x86\xea\xa3\xdd\xb9\xce\x96\x64\x1a\xc2\x14\x6e\x44\xac\x7c\xe6\x8f\xe8\x4d\x0f\x71\x1f\x40\x38\xa6\x00\xa3\x87\x78\xf6\xf9\x94\x86\x5e\xad\xea\xc0\x5e\x76\xeb\xd9\x14\xa3\x5d\x6e\x7a\x7c\x0c\xa5\x4b\x55\x7f\x06\x19\x29\x7f\x9e\x9a\x26\xd5\x6a\xbb\x38\x24\x08\x6a\x98\xc7\xb1\xda\xa3\x98\x91\xfd\x79\xdb\xe5\x5a\xc4\x1c\xb9\x02\x03\x01\x00\x01\xa3\x13\x30\x11\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x1e\x98\x60\xd4\xe5\xf2\x54\x60\xb0\x3d\x1a\x81\x64\x47\xf7\x5b\xa3\xd9\x6f\xc3\x29\x0b\xa7\xd2\xa9\x81\x49\xf6\xc3\x6d\x85\x14\x28\x45\x44\x01\xf4\x71\x5c\x95\x2e\x14\x0f\x1a\x2b\xd1\xa9\x6b\xc1\x5f\x67\x3d\x16\xf1\x72\x20\xaf\xbe\x16\xca\x0e\x30\x5f\xc9\xcb\xa5\x93\x2c\xc3\x67\x54\x1e\x72\x22\x8a\x23\x76\x6c\x94\x1d\x51\x52\x6c\x9d\xc4\xe0\x47\x02\xd7\xcc\xbf\xf0\x80\x7b\x18\x6e\x25\xdc\x62\x61\xd6\xa6\xfe\xc1\x1d\x7f\xd9\xb3\xfd\x8d\x5c\x45\x10\x5a\xc6\x65\x64\x9a\xeb\x2c\xf5\x03\x4f\xd6\x48\x62\xfb\x2e", 0 }, + /* Anchor: 114 persprem.crt serial: #{a.serial.to_s} + C=ZA,ST=Western Cape,L=Cape Town,O=Thawte Consulting,OU=Certification Services Division,CN=Thawte Personal Premium CA,1.2.840.113549.1.9.1=#161B706572736F6E616C2D7072656D69756D407468617774652E636F6D + */ + { 813, "\x30\x82\x03\x29\x30\x82\x02\x92\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x30\x81\xcf\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6f\x77\x6e\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x13\x11\x54\x68\x61\x77\x74\x65\x20\x43\x6f\x6e\x73\x75\x6c\x74\x69\x6e\x67\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1a\x54\x68\x61\x77\x74\x65\x20\x50\x65\x72\x73\x6f\x6e\x61\x6c\x20\x50\x72\x65\x6d\x69\x75\x6d\x20\x43\x41\x31\x2a\x30\x28\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x1b\x70\x65\x72\x73\x6f\x6e\x61\x6c\x2d\x70\x72\x65\x6d\x69\x75\x6d\x40\x74\x68\x61\x77\x74\x65\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x39\x36\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x30\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xcf\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6f\x77\x6e\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x13\x11\x54\x68\x61\x77\x74\x65\x20\x43\x6f\x6e\x73\x75\x6c\x74\x69\x6e\x67\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1a\x54\x68\x61\x77\x74\x65\x20\x50\x65\x72\x73\x6f\x6e\x61\x6c\x20\x50\x72\x65\x6d\x69\x75\x6d\x20\x43\x41\x31\x2a\x30\x28\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x1b\x70\x65\x72\x73\x6f\x6e\x61\x6c\x2d\x70\x72\x65\x6d\x69\x75\x6d\x40\x74\x68\x61\x77\x74\x65\x2e\x63\x6f\x6d\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xc9\x66\xd9\xf8\x07\x44\xcf\xb9\x8c\x2e\xf0\xa1\xef\x13\x45\x6c\x05\xdf\xde\x27\x16\x51\x36\x41\x11\x6c\x6c\x3b\xed\xfe\x10\x7d\x12\x9e\xe5\x9b\x42\x9a\xfe\x60\x31\xc3\x66\xb7\x73\x3a\x48\xae\x4e\xd0\x32\x37\x94\x88\xb5\x0d\xb6\xd9\xf3\xf2\x44\xd9\xd5\x88\x12\xdd\x76\x4d\xf2\x1a\xfc\x6f\x23\x1e\x7a\xf1\xd8\x98\x45\x4e\x07\x10\xef\x16\x42\xd0\x43\x75\x6d\x4a\xde\xe2\xaa\xc9\x31\xff\x1f\x00\x70\x7c\x66\xcf\x10\x25\x08\xba\xfa\xee\x00\xe9\x46\x03\x66\x27\x11\x15\x3b\xaa\x5b\xf2\x98\xdd\x36\x42\xb2\xda\x88\x75\x02\x03\x01\x00\x01\xa3\x13\x30\x11\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x03\x81\x81\x00\x69\x36\x89\xf7\x34\x2a\x33\x72\x2f\x6d\x3b\xd4\x22\xb2\xb8\x6f\x9a\xc5\x36\x66\x0e\x1b\x3c\xa1\xb1\x75\x5a\xe6\xfd\x35\xd3\xf8\xa8\xf2\x07\x6f\x85\x67\x8e\xde\x2b\xb9\xe2\x17\xb0\x3a\xa0\xf0\x0e\xa2\x00\x9a\xdf\xf3\x14\x15\x6e\xbb\xc8\x85\x5a\x98\x80\xf9\xff\xbe\x74\x1d\x3d\xf3\xfe\x30\x25\xd1\x37\x34\x67\xfa\xa5\x71\x79\x30\x61\x29\x72\xc0\xe0\x2c\x4c\xfb\x56\xe4\x3a\xa8\x6f\xe5\x32\x59\x52\xdb\x75\x28\x50\x59\x0c\xf8\x0b\x19\xe4\xac\xd9\xaf\x96\x8d\x2f\x50\xdb\x07\xc3\xea\x1f\xab\x33\xe0\xf5\x2b\x31\x89", 115 }, + /* Anchor: 115 Thawte_Personal_Premium_CA.cer serial: #{a.serial.to_s} + C=ZA,ST=Western Cape,L=Cape Town,O=Thawte Consulting,OU=Certification Services Division,CN=Thawte Personal Premium CA,1.2.840.113549.1.9.1=#161B706572736F6E616C2D7072656D69756D407468617774652E636F6D + */ + { 828, "\x30\x82\x03\x38\x30\x82\x02\xa1\xa0\x03\x02\x01\x02\x02\x10\x40\x05\xb2\x53\xa0\x1a\x46\x43\x50\x09\x81\x8f\x12\x10\x76\xec\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xcf\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6f\x77\x6e\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x13\x11\x54\x68\x61\x77\x74\x65\x20\x43\x6f\x6e\x73\x75\x6c\x74\x69\x6e\x67\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1a\x54\x68\x61\x77\x74\x65\x20\x50\x65\x72\x73\x6f\x6e\x61\x6c\x20\x50\x72\x65\x6d\x69\x75\x6d\x20\x43\x41\x31\x2a\x30\x28\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x1b\x70\x65\x72\x73\x6f\x6e\x61\x6c\x2d\x70\x72\x65\x6d\x69\x75\x6d\x40\x74\x68\x61\x77\x74\x65\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x39\x36\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x31\x30\x31\x30\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xcf\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6f\x77\x6e\x31\x1a\x30\x18\x06\x03\x55\x04\x0a\x13\x11\x54\x68\x61\x77\x74\x65\x20\x43\x6f\x6e\x73\x75\x6c\x74\x69\x6e\x67\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1a\x54\x68\x61\x77\x74\x65\x20\x50\x65\x72\x73\x6f\x6e\x61\x6c\x20\x50\x72\x65\x6d\x69\x75\x6d\x20\x43\x41\x31\x2a\x30\x28\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x1b\x70\x65\x72\x73\x6f\x6e\x61\x6c\x2d\x70\x72\x65\x6d\x69\x75\x6d\x40\x74\x68\x61\x77\x74\x65\x2e\x63\x6f\x6d\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xc9\x66\xd9\xf8\x07\x44\xcf\xb9\x8c\x2e\xf0\xa1\xef\x13\x45\x6c\x05\xdf\xde\x27\x16\x51\x36\x41\x11\x6c\x6c\x3b\xed\xfe\x10\x7d\x12\x9e\xe5\x9b\x42\x9a\xfe\x60\x31\xc3\x66\xb7\x73\x3a\x48\xae\x4e\xd0\x32\x37\x94\x88\xb5\x0d\xb6\xd9\xf3\xf2\x44\xd9\xd5\x88\x12\xdd\x76\x4d\xf2\x1a\xfc\x6f\x23\x1e\x7a\xf1\xd8\x98\x45\x4e\x07\x10\xef\x16\x42\xd0\x43\x75\x6d\x4a\xde\xe2\xaa\xc9\x31\xff\x1f\x00\x70\x7c\x66\xcf\x10\x25\x08\xba\xfa\xee\x00\xe9\x46\x03\x66\x27\x11\x15\x3b\xaa\x5b\xf2\x98\xdd\x36\x42\xb2\xda\x88\x75\x02\x03\x01\x00\x01\xa3\x13\x30\x11\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\xba\x64\x0a\xe8\xf3\xb4\x31\xc9\x27\x6f\xa2\x76\xa0\x2d\x36\x71\xc7\x86\xc0\x08\xc2\x4e\xed\xda\x9a\x24\x19\x87\xfc\x5a\x23\x9c\x72\x4d\x08\xdf\xad\x5c\xc3\x3b\x24\x81\x1d\x57\x8f\xb6\x12\xa5\x22\x03\xef\x12\xbd\xd1\x2d\x5e\x96\x8f\x26\x26\x4f\x4b\x1b\x7c\x3b\xa0\x52\x1a\xa5\xa8\x37\x86\xc4\x47\x2a\xca\xdd\x41\xf8\x68\xf5\xc2\x13\x41\x29\x9a\xf0\x0c\xa8\xcd\xa1\xfc\x15\x23\x02\xdb\x7a\x2b\xd4\x62\x51\x42\x47\xc4\xa3\x1f\xf4\xd2\xc5\x4d\x54\x10\xeb\xda\xf0\xcc\xa7\x4f\x37\x0c\xbd\x3c\xcb\x10\xe3\x1a\xe8\x15", 0 }, + /* Anchor: 116 Poland-Certum-CTNCA.der serial: #{a.serial.to_s} + C=PL,O=Unizeto Technologies S.A.,OU=Certum Certification Authority,CN=Certum Trusted Network CA + */ + { 959, "\x30\x82\x03\xbb\x30\x82\x02\xa3\xa0\x03\x02\x01\x02\x02\x03\x04\x44\xc0\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x7e\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x50\x4c\x31\x22\x30\x20\x06\x03\x55\x04\x0a\x13\x19\x55\x6e\x69\x7a\x65\x74\x6f\x20\x54\x65\x63\x68\x6e\x6f\x6c\x6f\x67\x69\x65\x73\x20\x53\x2e\x41\x2e\x31\x27\x30\x25\x06\x03\x55\x04\x0b\x13\x1e\x43\x65\x72\x74\x75\x6d\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x43\x65\x72\x74\x75\x6d\x20\x54\x72\x75\x73\x74\x65\x64\x20\x4e\x65\x74\x77\x6f\x72\x6b\x20\x43\x41\x30\x1e\x17\x0d\x30\x38\x31\x30\x32\x32\x31\x32\x30\x37\x33\x37\x5a\x17\x0d\x32\x39\x31\x32\x33\x31\x31\x32\x30\x37\x33\x37\x5a\x30\x7e\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x50\x4c\x31\x22\x30\x20\x06\x03\x55\x04\x0a\x13\x19\x55\x6e\x69\x7a\x65\x74\x6f\x20\x54\x65\x63\x68\x6e\x6f\x6c\x6f\x67\x69\x65\x73\x20\x53\x2e\x41\x2e\x31\x27\x30\x25\x06\x03\x55\x04\x0b\x13\x1e\x43\x65\x72\x74\x75\x6d\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x43\x65\x72\x74\x75\x6d\x20\x54\x72\x75\x73\x74\x65\x64\x20\x4e\x65\x74\x77\x6f\x72\x6b\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xe3\xfb\x7d\xa3\x72\xba\xc2\xf0\xc9\x14\x87\xf5\x6b\x01\x4e\xe1\x6e\x40\x07\xba\x6d\x27\x5d\x7f\xf7\x5b\x2d\xb3\x5a\xc7\x51\x5f\xab\xa4\x32\xa6\x61\x87\xb6\x6e\x0f\x86\xd2\x30\x02\x97\xf8\xd7\x69\x57\xa1\x18\x39\x5d\x6a\x64\x79\xc6\x01\x59\xac\x3c\x31\x4a\x38\x7c\xd2\x04\xd2\x4b\x28\xe8\x20\x5f\x3b\x07\xa2\xcc\x4d\x73\xdb\xf3\xae\x4f\xc7\x56\xd5\x5a\xa7\x96\x89\xfa\xf3\xab\x68\xd4\x23\x86\x59\x27\xcf\x09\x27\xbc\xac\x6e\x72\x83\x1c\x30\x72\xdf\xe0\xa2\xe9\xd2\xe1\x74\x75\x19\xbd\x2a\x9e\x7b\x15\x54\x04\x1b\xd7\x43\x39\xad\x55\x28\xc5\xe2\x1a\xbb\xf4\xc0\xe4\xae\x38\x49\x33\xcc\x76\x85\x9f\x39\x45\xd2\xa4\x9e\xf2\x12\x8c\x51\xf8\x7c\xe4\x2d\x7f\xf5\xac\x5f\xeb\x16\x9f\xb1\x2d\xd1\xba\xcc\x91\x42\x77\x4c\x25\xc9\x90\x38\x6f\xdb\xf0\xcc\xfb\x8e\x1e\x97\x59\x3e\xd5\x60\x4e\xe6\x05\x28\xed\x49\x79\x13\x4b\xba\x48\xdb\x2f\xf9\x72\xd3\x39\xca\xfe\x1f\xd8\x34\x72\xf5\xb4\x40\xcf\x31\x01\xc3\xec\xde\x11\x2d\x17\x5d\x1f\xb8\x50\xd1\x5e\x19\xa7\x69\xde\x07\x33\x28\xca\x50\x95\xf9\xa7\x54\xcb\x54\x86\x50\x45\xa9\xf9\x49\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x08\x76\xcd\xcb\x07\xff\x24\xf6\xc5\xcd\xed\xbb\x90\xbc\xe2\x84\x37\x46\x75\xf7\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xa6\xa8\xad\x22\xce\x01\x3d\xa6\xa3\xff\x62\xd0\x48\x9d\x8b\x5e\x72\xb0\x78\x44\xe3\xdc\x1c\xaf\x09\xfd\x23\x48\xfa\xbd\x2a\xc4\xb9\x55\x04\xb5\x10\xa3\x8d\x27\xde\x0b\x82\x63\xd0\xee\xde\x0c\x37\x79\x41\x5b\x22\xb2\xb0\x9a\x41\x5c\xa6\x70\xe0\xd4\xd0\x77\xcb\x23\xd3\x00\xe0\x6c\x56\x2f\xe1\x69\x0d\x0d\xd9\xaa\xbf\x21\x81\x50\xd9\x06\xa5\xa8\xff\x95\x37\xd0\xaa\xfe\xe2\xb3\xf5\x99\x2d\x45\x84\x8a\xe5\x42\x09\xd7\x74\x02\x2f\xf7\x89\xd8\x99\xe9\xbc\x27\xd4\x47\x8d\xba\x0d\x46\x1c\x77\xcf\x14\xa4\x1c\xb9\xa4\x31\xc4\x9c\x28\x74\x03\x34\xff\x33\x19\x26\xa5\xe9\x0d\x74\xb7\x3e\x97\xc6\x76\xe8\x27\x96\xa3\x66\xdd\xe1\xae\xf2\x41\x5b\xca\x98\x56\x83\x73\x70\xe4\x86\x1a\xd2\x31\x41\xba\x2f\xbe\x2d\x13\x5a\x76\x6f\x4e\xe8\x4e\x81\x0e\x3f\x5b\x03\x22\xa0\x12\xbe\x66\x58\x11\x4a\xcb\x03\xc4\xb4\x2a\x2a\x2d\x96\x17\xe0\x39\x54\xbc\x48\xd3\x76\x27\x9d\x9a\x2d\x06\xa6\xc9\xec\x39\xd2\xab\xdb\x9f\x9a\x0b\x27\x02\x35\x29\xb1\x40\x95\xe7\xf9\xe8\x9c\x55\x88\x19\x46\xd6\xb7\x34\xf5\x7e\xce\x39\x9a\xd9\x38\xf1\x51\xf7\x4f\x2c", 0 }, + /* Anchor: 117 popFinnVrkrootc.der serial: #{a.serial.to_s} + C=FI,ST=Finland,O=Vaestorekisterikeskus CA,OU=Certification Authority Services,OU=Varmennepalvelut,CN=VRK Gov. Root CA + */ + { 1054, "\x30\x82\x04\x1a\x30\x82\x03\x02\xa0\x03\x02\x01\x02\x02\x03\x01\x86\xa0\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xa3\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x49\x31\x10\x30\x0e\x06\x03\x55\x04\x08\x13\x07\x46\x69\x6e\x6c\x61\x6e\x64\x31\x21\x30\x1f\x06\x03\x55\x04\x0a\x13\x18\x56\x61\x65\x73\x74\x6f\x72\x65\x6b\x69\x73\x74\x65\x72\x69\x6b\x65\x73\x6b\x75\x73\x20\x43\x41\x31\x29\x30\x27\x06\x03\x55\x04\x0b\x13\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x53\x65\x72\x76\x69\x63\x65\x73\x31\x19\x30\x17\x06\x03\x55\x04\x0b\x13\x10\x56\x61\x72\x6d\x65\x6e\x6e\x65\x70\x61\x6c\x76\x65\x6c\x75\x74\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x56\x52\x4b\x20\x47\x6f\x76\x2e\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x1e\x17\x0d\x30\x32\x31\x32\x31\x38\x31\x33\x35\x33\x30\x30\x5a\x17\x0d\x32\x33\x31\x32\x31\x38\x31\x33\x35\x31\x30\x38\x5a\x30\x81\xa3\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x49\x31\x10\x30\x0e\x06\x03\x55\x04\x08\x13\x07\x46\x69\x6e\x6c\x61\x6e\x64\x31\x21\x30\x1f\x06\x03\x55\x04\x0a\x13\x18\x56\x61\x65\x73\x74\x6f\x72\x65\x6b\x69\x73\x74\x65\x72\x69\x6b\x65\x73\x6b\x75\x73\x20\x43\x41\x31\x29\x30\x27\x06\x03\x55\x04\x0b\x13\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x53\x65\x72\x76\x69\x63\x65\x73\x31\x19\x30\x17\x06\x03\x55\x04\x0b\x13\x10\x56\x61\x72\x6d\x65\x6e\x6e\x65\x70\x61\x6c\x76\x65\x6c\x75\x74\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x56\x52\x4b\x20\x47\x6f\x76\x2e\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xb0\x85\x15\xda\xc8\x03\x37\xd0\xa3\x46\x37\x6c\x1b\x1e\x96\x30\xc2\x5a\x85\x12\x67\x23\xf2\xbb\x9f\xe7\x8a\x81\x60\x27\xf8\x13\xa9\x3c\xbc\xf7\x86\xaa\xaa\xf4\xf3\x25\x29\xb4\xfe\x75\xae\x1e\x81\x86\x8a\x05\xb2\x1d\x65\xb2\x38\xe8\xb4\xcc\x28\x9a\xfb\x17\x36\xf1\x93\xd5\x79\xce\xc1\x83\x8b\x21\x4f\xc3\x0d\xad\x41\xdf\x78\x9d\x48\xe3\x1f\x42\x44\xfc\x3c\x6d\x21\x20\x6b\xad\x22\x84\x24\x42\x8f\x17\x4d\xc2\x50\x1f\x64\xcd\x2d\x39\x22\x56\x88\xfd\xb2\x63\x9d\x54\xda\x42\x69\xc0\xc8\x4f\xd7\x18\xe2\x3e\xc8\x69\x84\x94\x3d\x2c\x80\xc6\x7c\xce\xbd\xd7\x53\x1f\xeb\x88\xb9\xa6\xcb\xbb\x85\x57\xef\x57\x76\x5d\x0c\x8b\xd3\x5e\x12\x41\x9f\x21\xc0\x39\xf4\x26\x6d\x08\xfa\x38\xb3\xa1\x77\xb1\xee\x16\xd8\xd0\x68\xda\xb4\x98\xa5\xa0\x65\x46\x4a\x6b\x8d\x7e\xaa\x4d\x60\xb8\xf8\xc8\x0d\xfc\x71\x3e\xee\x39\x87\x81\xb4\xd9\xf8\x6e\x90\xee\x3f\x0e\x61\xd7\x1d\x2b\x68\xe6\x2e\xe1\x42\x44\x26\x78\x2c\x58\xf2\x7d\x16\x7f\x61\xc0\x49\x24\x2a\x89\x87\xb6\x5d\x2f\x29\x19\xf8\xa6\xe7\x8e\x52\x9e\x41\x4b\x5a\x0e\xaa\xb8\xc2\x66\x42\x53\x02\x03\x01\x00\x01\xa3\x55\x30\x53\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\xc6\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xdb\xe9\xe1\x9b\xd2\xd1\x24\x0b\xfc\xab\xe3\xa0\x67\xea\xae\x9c\x4b\x77\xf4\xb0\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xad\x7d\x48\x0f\x54\x11\x9e\x58\xee\xaf\x0d\x9b\x12\x2f\x21\xa4\xcd\x9b\xba\x84\x47\xe6\xc9\x25\x55\x23\xe3\xdf\x18\x58\x2a\x2c\xdb\x5e\xf7\xcd\x54\xf5\x51\x24\x7b\x62\x67\xe1\xb1\x1f\x49\xaf\x34\xd0\xeb\xb1\xcc\xd9\xa2\x0d\x52\x7f\x42\x4b\x88\x60\x97\xcf\x25\x72\xb7\x4f\x29\x2d\x62\x9f\x4f\xa1\xc0\x55\x57\x56\x0e\xc4\x68\x97\x91\x1f\x9c\x64\xc2\x29\x32\x01\xe9\xd4\xc8\xda\xb8\x81\x98\x28\x2e\x18\xc7\x2c\xfc\xeb\x9b\x52\x96\xdf\xf4\xc8\x90\x19\x2d\x23\xf3\xf1\xbb\x71\xda\x9e\x85\x23\xbd\x1a\xef\x2e\xe4\x7a\x79\xb7\xc3\x9d\x86\x49\x2d\x63\xb9\x2d\x74\xcf\x65\x0f\x32\x66\x89\xdf\x3b\x21\xee\x29\x6f\x39\x63\xd9\x15\xc1\x6e\xf6\xdf\x80\x3e\x50\x78\x19\x8a\xdd\x03\xa3\x14\xa5\x37\xa7\xb5\x2c\x7c\xb6\x11\x87\xe7\x05\xf2\xbc\xb6\xde\xd4\xff\x97\x81\x28\x84\xfe\xfe\x6c\x46\x85\x10\x41\x9f\x4d\x75\x8c\x07\xd4\x99\x67\x6f\x75\x8a\x6f\xe4\x50\x92\xf6\x99\xd5\x10\xb8\xc4\xa9\x7b\xf7\x17\x8d\x4b\xbf\xd7\x95\x9f\x09\xdc\x44\x0f\x1e\x32\xc3\xc0\xcf\xd3\x79\x0d\xe4\xc7\x3b\x87\xf0\x90\x34\x88\x21\x62\x49\x92\x04\x04\x1f\xbc", 0 }, + /* Anchor: 118 qvrca.crt serial: #{a.serial.to_s} + C=BM,O=QuoVadis Limited,OU=Root Certification Authority,CN=QuoVadis Root Certification Authority + */ + { 1492, "\x30\x82\x05\xd0\x30\x82\x04\xb8\xa0\x03\x02\x01\x02\x02\x04\x3a\xb6\x50\x8b\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x7f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4d\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x25\x30\x23\x06\x03\x55\x04\x0b\x13\x1c\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x2e\x30\x2c\x06\x03\x55\x04\x03\x13\x25\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x30\x31\x30\x33\x31\x39\x31\x38\x33\x33\x33\x33\x5a\x17\x0d\x32\x31\x30\x33\x31\x37\x31\x38\x33\x33\x33\x33\x5a\x30\x7f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4d\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x25\x30\x23\x06\x03\x55\x04\x0b\x13\x1c\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x2e\x30\x2c\x06\x03\x55\x04\x03\x13\x25\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xbf\x61\xb5\x95\x53\xba\x57\xfc\xfa\xf2\x67\x0b\x3a\x1a\xdf\x11\x80\x64\x95\xb4\xd1\xbc\xcd\x7a\xcf\xf6\x29\x96\x2e\x24\x54\x40\x24\x38\xf7\x1a\x85\xdc\x58\x4c\xcb\xa4\x27\x42\x97\xd0\x9f\x83\x8a\xc3\xe4\x06\x03\x5b\x00\xa5\x51\x1e\x70\x04\x74\xe2\xc1\xd4\x3a\xab\xd7\xad\x3b\x07\x18\x05\x8e\xfd\x83\xac\xea\x66\xd9\x18\x1b\x68\x8a\xf5\x57\x1a\x98\xba\xf5\xed\x76\x3d\x7c\xd9\xde\x94\x6a\x3b\x4b\x17\xc1\xd5\x8f\xbd\x65\x38\x3a\x95\xd0\x3d\x55\x36\x4e\xdf\x79\x57\x31\x2a\x1e\xd8\x59\x65\x49\x58\x20\x98\x7e\xab\x5f\x7e\x9f\xe9\xd6\x4d\xec\x83\x74\xa9\xc7\x6c\xd8\xee\x29\x4a\x85\x2a\x06\x14\xf9\x54\xe6\xd3\xda\x65\x07\x8b\x63\x37\x12\xd7\xd0\xec\xc3\x7b\x20\x41\x44\xa3\xed\xcb\xa0\x17\xe1\x71\x65\xce\x1d\x66\x31\xf7\x76\x01\x19\xc8\x7d\x03\x58\xb6\x95\x49\x1d\xa6\x12\x26\xe8\xc6\x0c\x76\xe0\xe3\x66\xcb\xea\x5d\xa6\x26\xee\xe5\xcc\x5f\xbd\x67\xa7\x01\x27\x0e\xa2\xca\x54\xc5\xb1\x7a\x95\x1d\x71\x1e\x4a\x29\x8a\x03\xdc\x6a\x45\xc1\xa4\x19\x5e\x6f\x36\xcd\xc3\xa2\xb0\xb7\xfe\x5c\x38\xe2\x52\xbc\xf8\x44\x43\xe6\x90\xbb\x02\x03\x01\x00\x01\xa3\x82\x02\x52\x30\x82\x02\x4e\x30\x3d\x06\x08\x2b\x06\x01\x05\x05\x07\x01\x01\x04\x31\x30\x2f\x30\x2d\x06\x08\x2b\x06\x01\x05\x05\x07\x30\x01\x86\x21\x68\x74\x74\x70\x73\x3a\x2f\x2f\x6f\x63\x73\x70\x2e\x71\x75\x6f\x76\x61\x64\x69\x73\x6f\x66\x66\x73\x68\x6f\x72\x65\x2e\x63\x6f\x6d\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x82\x01\x1a\x06\x03\x55\x1d\x20\x04\x82\x01\x11\x30\x82\x01\x0d\x30\x82\x01\x09\x06\x09\x2b\x06\x01\x04\x01\xbe\x58\x00\x01\x30\x81\xfb\x30\x81\xd4\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x02\x30\x81\xc7\x1a\x81\xc4\x52\x65\x6c\x69\x61\x6e\x63\x65\x20\x6f\x6e\x20\x74\x68\x65\x20\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x62\x79\x20\x61\x6e\x79\x20\x70\x61\x72\x74\x79\x20\x61\x73\x73\x75\x6d\x65\x73\x20\x61\x63\x63\x65\x70\x74\x61\x6e\x63\x65\x20\x6f\x66\x20\x74\x68\x65\x20\x74\x68\x65\x6e\x20\x61\x70\x70\x6c\x69\x63\x61\x62\x6c\x65\x20\x73\x74\x61\x6e\x64\x61\x72\x64\x20\x74\x65\x72\x6d\x73\x20\x61\x6e\x64\x20\x63\x6f\x6e\x64\x69\x74\x69\x6f\x6e\x73\x20\x6f\x66\x20\x75\x73\x65\x2c\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x70\x72\x61\x63\x74\x69\x63\x65\x73\x2c\x20\x61\x6e\x64\x20\x74\x68\x65\x20\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x50\x6f\x6c\x69\x63\x79\x2e\x30\x22\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x16\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x71\x75\x6f\x76\x61\x64\x69\x73\x2e\x62\x6d\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x8b\x4b\x6d\xed\xd3\x29\xb9\x06\x19\xec\x39\x39\xa9\xf0\x97\x84\x6a\xcb\xef\xdf\x30\x81\xae\x06\x03\x55\x1d\x23\x04\x81\xa6\x30\x81\xa3\x80\x14\x8b\x4b\x6d\xed\xd3\x29\xb9\x06\x19\xec\x39\x39\xa9\xf0\x97\x84\x6a\xcb\xef\xdf\xa1\x81\x84\xa4\x81\x81\x30\x7f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4d\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x25\x30\x23\x06\x03\x55\x04\x0b\x13\x1c\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x2e\x30\x2c\x06\x03\x55\x04\x03\x13\x25\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x82\x04\x3a\xb6\x50\x8b\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x8a\xd4\x14\xb5\xfe\xf4\x9a\x92\xa7\x19\xd4\xa4\x7e\x72\x18\x8f\xd9\x68\x7c\x52\x24\xdd\x67\x6f\x39\x7a\xc4\xaa\x5e\x3d\xe2\x58\xb0\x4d\x70\x98\x84\x61\xe8\x1b\xe3\x69\x18\x0e\xce\xfb\x47\x50\xa0\x4e\xff\xf0\x24\x1f\xbd\xb2\xce\xf5\x27\xfc\xec\x2f\x53\xaa\x73\x7b\x03\x3d\x74\x6e\xe6\x16\x9e\xeb\xa5\x2e\xc4\xbf\x56\x27\x50\x2b\x62\xba\xbe\x4b\x1c\x3c\x55\x5c\x41\x1d\x24\xbe\x82\x20\x47\x5d\xd5\x44\x7e\x7a\x16\x68\xdf\x7d\x4d\x51\x70\x78\x57\x1d\x33\x1e\xfd\x02\x99\x9c\x0c\xcd\x0a\x05\x4f\xc7\xbb\x8e\xa4\x75\xfa\x4a\x6d\xb1\x80\x8e\x09\x56\xb9\x9c\x1a\x60\xfe\x5d\xc1\xd7\x7a\xdc\x11\x78\xd0\xd6\x5d\xc1\xb7\xd5\xad\x32\x99\x03\x3a\x8a\xcc\x54\x25\x39\x31\x81\x7b\x13\x22\x51\xba\x46\x6c\xa1\xbb\x9e\xfa\x04\x6c\x49\x26\x74\x8f\xd2\x73\xeb\xcc\x30\xa2\xe6\xea\x59\x22\x87\xf8\x97\xf5\x0e\xfd\xea\xcc\x92\xa4\x16\xc4\x52\x18\xea\x21\xce\xb1\xf1\xe6\x84\x81\xe5\xba\xa9\x86\x28\xf2\x43\x5a\x5d\x12\x9d\xac\x1e\xd9\xa8\xe5\x0a\x6a\xa7\x7f\xa0\x87\x29\xcf\xf2\x89\x4d\xd4\xec\xc5\xe2\xe6\x7a\xd0\x36\x23\x8a\x4a\x74\x36\xf9", 0 }, + /* Anchor: 119 qvrca2.crt serial: #{a.serial.to_s} + C=BM,O=QuoVadis Limited,CN=QuoVadis Root CA 2 + */ + { 1467, "\x30\x82\x05\xb7\x30\x82\x03\x9f\xa0\x03\x02\x01\x02\x02\x02\x05\x09\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x45\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4d\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x13\x12\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x32\x30\x1e\x17\x0d\x30\x36\x31\x31\x32\x34\x31\x38\x32\x37\x30\x30\x5a\x17\x0d\x33\x31\x31\x31\x32\x34\x31\x38\x32\x33\x33\x33\x5a\x30\x45\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4d\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x13\x12\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x32\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\x9a\x18\xca\x4b\x94\x0d\x00\x2d\xaf\x03\x29\x8a\xf0\x0f\x81\xc8\xae\x4c\x19\x85\x1d\x08\x9f\xab\x29\x44\x85\xf3\x2f\x81\xad\x32\x1e\x90\x46\xbf\xa3\x86\x26\x1a\x1e\xfe\x7e\x1c\x18\x3a\x5c\x9c\x60\x17\x2a\x3a\x74\x83\x33\x30\x7d\x61\x54\x11\xcb\xed\xab\xe0\xe6\xd2\xa2\x7e\xf5\x6b\x6f\x18\xb7\x0a\x0b\x2d\xfd\xe9\x3e\xef\x0a\xc6\xb3\x10\xe9\xdc\xc2\x46\x17\xf8\x5d\xfd\xa4\xda\xff\x9e\x49\x5a\x9c\xe6\x33\xe6\x24\x96\xf7\x3f\xba\x5b\x2b\x1c\x7a\x35\xc2\xd6\x67\xfe\xab\x66\x50\x8b\x6d\x28\x60\x2b\xef\xd7\x60\xc3\xc7\x93\xbc\x8d\x36\x91\xf3\x7f\xf8\xdb\x11\x13\xc4\x9c\x77\x76\xc1\xae\xb7\x02\x6a\x81\x7a\xa9\x45\x83\xe2\x05\xe6\xb9\x56\xc1\x94\x37\x8f\x48\x71\x63\x22\xec\x17\x65\x07\x95\x8a\x4b\xdf\x8f\xc6\x5a\x0a\xe5\xb0\xe3\x5f\x5e\x6b\x11\xab\x0c\xf9\x85\xeb\x44\xe9\xf8\x04\x73\xf2\xe9\xfe\x5c\x98\x8c\xf5\x73\xaf\x6b\xb4\x7e\xcd\xd4\x5c\x02\x2b\x4c\x39\xe1\xb2\x95\x95\x2d\x42\x87\xd7\xd5\xb3\x90\x43\xb7\x6c\x13\xf1\xde\xdd\xf6\xc4\xf8\x89\x3f\xd1\x75\xf5\x92\xc3\x91\xd5\x8a\x88\xd0\x90\xec\xdc\x6d\xde\x89\xc2\x65\x71\x96\x8b\x0d\x03\xfd\x9c\xbf\x5b\x16\xac\x92\xdb\xea\xfe\x79\x7c\xad\xeb\xaf\xf7\x16\xcb\xdb\xcd\x25\x2b\xe5\x1f\xfb\x9a\x9f\xe2\x51\xcc\x3a\x53\x0c\x48\xe6\x0e\xbd\xc9\xb4\x76\x06\x52\xe6\x11\x13\x85\x72\x63\x03\x04\xe0\x04\x36\x2b\x20\x19\x02\xe8\x74\xa7\x1f\xb6\xc9\x56\x66\xf0\x75\x25\xdc\x67\xc1\x0e\x61\x60\x88\xb3\x3e\xd1\xa8\xfc\xa3\xda\x1d\xb0\xd1\xb1\x23\x54\xdf\x44\x76\x6d\xed\x41\xd8\xc1\xb2\x22\xb6\x53\x1c\xdf\x35\x1d\xdc\xa1\x77\x2a\x31\xe4\x2d\xf5\xe5\xe5\xdb\xc8\xe0\xff\xe5\x80\xd7\x0b\x63\xa0\xff\x33\xa1\x0f\xba\x2c\x15\x15\xea\x97\xb3\xd2\xa2\xb5\xbe\xf2\x8c\x96\x1e\x1a\x8f\x1d\x6c\xa4\x61\x37\xb9\x86\x73\x33\xd7\x97\x96\x9e\x23\x7d\x82\xa4\x4c\x81\xe2\xa1\xd1\xba\x67\x5f\x95\x07\xa3\x27\x11\xee\x16\x10\x7b\xbc\x45\x4a\x4c\xb2\x04\xd2\xab\xef\xd5\xfd\x0c\x51\xce\x50\x6a\x08\x31\xf9\x91\xda\x0c\x8f\x64\x5c\x03\xc3\x3a\x8b\x20\x3f\x6e\x8d\x67\x3d\x3a\xd6\xfe\x7d\x5b\x88\xc9\x5e\xfb\xcc\x61\xdc\x8b\x33\x77\xd3\x44\x32\x35\x09\x62\x04\x92\x16\x10\xd8\x9e\x27\x47\xfb\x3b\x21\xe3\xf8\xeb\x1d\x5b\x02\x03\x01\x00\x01\xa3\x81\xb0\x30\x81\xad\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x1a\x84\x62\xbc\x48\x4c\x33\x25\x04\xd4\xee\xd0\xf6\x03\xc4\x19\x46\xd1\x94\x6b\x30\x6e\x06\x03\x55\x1d\x23\x04\x67\x30\x65\x80\x14\x1a\x84\x62\xbc\x48\x4c\x33\x25\x04\xd4\xee\xd0\xf6\x03\xc4\x19\x46\xd1\x94\x6b\xa1\x49\xa4\x47\x30\x45\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4d\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x13\x12\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x32\x82\x02\x05\x09\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x3e\x0a\x16\x4d\x9f\x06\x5b\xa8\xae\x71\x5d\x2f\x05\x2f\x67\xe6\x13\x45\x83\xc4\x36\xf6\xf3\xc0\x26\x0c\x0d\xb5\x47\x64\x5d\xf8\xb4\x72\xc9\x46\xa5\x03\x18\x27\x55\x89\x78\x7d\x76\xea\x96\x34\x80\x17\x20\xdc\xe7\x83\xf8\x8d\xfc\x07\xb8\xda\x5f\x4d\x2e\x67\xb2\x84\xfd\xd9\x44\xfc\x77\x50\x81\xe6\x7c\xb4\xc9\x0d\x0b\x72\x53\xf8\x76\x07\x07\x41\x47\x96\x0c\xfb\xe0\x82\x26\x93\x55\x8c\xfe\x22\x1f\x60\x65\x7c\x5f\xe7\x26\xb3\xf7\x32\x90\x98\x50\xd4\x37\x71\x55\xf6\x92\x21\x78\xf7\x95\x79\xfa\xf8\x2d\x26\x87\x66\x56\x30\x77\xa6\x37\x78\x33\x52\x10\x58\xae\x3f\x61\x8e\xf2\x6a\xb1\xef\x18\x7e\x4a\x59\x63\xca\x8d\xa2\x56\xd5\xa7\x2f\xbc\x56\x1f\xcf\x39\xc1\xe2\xfb\x0a\xa8\x15\x2c\x7d\x4d\x7a\x63\xc6\x6c\x97\x44\x3c\xd2\x6f\xc3\x4a\x17\x0a\xf8\x90\xd2\x57\xa2\x19\x51\xa5\x2d\x97\x41\xda\x07\x4f\xa9\x50\xda\x90\x8d\x94\x46\xe1\x3e\xf0\x94\xfd\x10\x00\x38\xf5\x3b\xe8\x40\xe1\xb4\x6e\x56\x1a\x20\xcc\x6f\x58\x8d\xed\x2e\x45\x8f\xd6\xe9\x93\x3f\xe7\xb1\x2c\xdf\x3a\xd6\x22\x8c\xdc\x84\xbb\x22\x6f\xd0\xf8\xe4\xc6\x39\xe9\x04\x88\x3c\xc3\xba\xeb\x55\x7a\x6d\x80\x99\x24\xf5\x6c\x01\xfb\xf8\x97\xb0\x94\x5b\xeb\xfd\xd2\x6f\xf1\x77\x68\x0d\x35\x64\x23\xac\xb8\x55\xa1\x03\xd1\x4d\x42\x19\xdc\xf8\x75\x59\x56\xa3\xf9\xa8\x49\x79\xf8\xaf\x0e\xb9\x11\xa0\x7c\xb7\x6a\xed\x34\xd0\xb6\x26\x62\x38\x1a\x87\x0c\xf8\xe8\xfd\x2e\xd3\x90\x7f\x07\x91\x2a\x1d\xd6\x7e\x5c\x85\x83\x99\xb0\x38\x08\x3f\xe9\x5e\xf9\x35\x07\xe4\xc9\x62\x6e\x57\x7f\xa7\x50\x95\xf7\xba\xc8\x9b\xe6\x8e\xa2\x01\xc5\xd6\x66\xbf\x79\x61\xf3\x3c\x1c\xe1\xb9\x82\x5c\x5d\xa0\xc3\xe9\xd8\x48\xbd\x19\xa2\x11\x14\x19\x6e\xb2\x86\x1b\x68\x3e\x48\x37\x1a\x88\xb7\x5d\x96\x5e\x9c\xc7\xef\x27\x62\x08\xe2\x91\x19\x5c\xd2\xf1\x21\xdd\xba\x17\x42\x82\x97\x71\x81\x53\x31\xa9\x9f\xf6\x7d\x62\xbf\x72\xe1\xa3\x93\x1d\xcc\x8a\x26\x5a\x09\x38\xd0\xce\xd7\x0d\x80\x16\xb4\x78\xa5\x3a\x87\x4c\x8d\x8a\xa5\xd5\x46\x97\xf2\x2c\x10\xb9\xbc\x54\x22\xc0\x01\x50\x69\x43\x9e\xf4\xb2\xef\x6d\xf8\xec\xda\xf1\xe3\xb1\xef\xdf\x91\x8f\x54\x2a\x0b\x25\xc1\x26\x19\xc4\x52\x10\x05\x65\xd5\x82\x10\xea\xc2\x31\xcd\x2e", 0 }, + /* Anchor: 120 qvrca3.crt serial: #{a.serial.to_s} + C=BM,O=QuoVadis Limited,CN=QuoVadis Root CA 3 + */ + { 1697, "\x30\x82\x06\x9d\x30\x82\x04\x85\xa0\x03\x02\x01\x02\x02\x02\x05\xc6\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x45\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4d\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x13\x12\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x33\x30\x1e\x17\x0d\x30\x36\x31\x31\x32\x34\x31\x39\x31\x31\x32\x33\x5a\x17\x0d\x33\x31\x31\x31\x32\x34\x31\x39\x30\x36\x34\x34\x5a\x30\x45\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4d\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x13\x12\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x33\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\xcc\x57\x42\x16\x54\x9c\xe6\x98\xd3\xd3\x4d\xee\xfe\xed\xc7\x9f\x43\x39\x4a\x65\xb3\xe8\x16\x88\x34\xdb\x0d\x59\x91\x74\xcf\x92\xb8\x04\x40\xad\x02\x4b\x31\xab\xbc\x8d\x91\x68\xd8\x20\x0e\x1a\x01\xe2\x1a\x7b\x4e\x17\x5d\xe2\x8a\xb7\x3f\x99\x1a\xcd\xeb\x61\xab\xc2\x65\xa6\x1f\xb7\xb7\xbd\xb7\x8f\xfc\xfd\x70\x8f\x0b\xa0\x67\xbe\x01\xa2\x59\xcf\x71\xe6\x0f\x29\x76\xff\xb1\x56\x79\x45\x2b\x1f\x9e\x7a\x54\xe8\xa3\x29\x35\x68\xa4\x01\x4f\x0f\xa4\x2e\x37\xef\x1b\xbf\xe3\x8f\x10\xa8\x72\xab\x58\x57\xe7\x54\x86\xc8\xc9\xf3\x5b\xda\x2c\xda\x5d\x8e\x6e\x3c\xa3\x3e\xda\xfb\x82\xe5\xdd\xf2\x5c\xb2\x05\x33\x6f\x8a\x36\xce\xd0\x13\x4e\xff\xbf\x4a\x0c\x34\x4c\xa6\xc3\x21\xbd\x50\x04\x55\xeb\xb1\xbb\x9d\xfb\x45\x1e\x64\x15\xde\x55\x01\x8c\x02\x76\xb5\xcb\xa1\x3f\x42\x69\xbc\x2f\xbd\x68\x43\x16\x56\x89\x2a\x37\x61\x91\xfd\xa6\xae\x4e\xc0\xcb\x14\x65\x94\x37\x4b\x92\x06\xef\x04\xd0\xc8\x9c\x88\xdb\x0b\x7b\x81\xaf\xb1\x3d\x2a\xc4\x65\x3a\x78\xb6\xee\xdc\x80\xb1\xd2\xd3\x99\x9c\x3a\xee\x6b\x5a\x6b\xb3\x8d\xb7\xd5\xce\x9c\xc2\xbe\xa5\x4b\x2f\x16\xb1\x9e\x68\x3b\x06\x6f\xae\x7d\x9f\xf8\xde\xec\xcc\x29\xa7\x98\xa3\x25\x43\x2f\xef\xf1\x5f\x26\xe1\x88\x4d\xf8\x5e\x6e\xd7\xd9\x14\x6e\x19\x33\x69\xa7\x3b\x84\x89\x93\xc4\x53\x55\x13\xa1\x51\x78\x40\xf8\xb8\xc9\xa2\xee\x7b\xba\x52\x42\x83\x9e\x14\xed\x05\x52\x5a\x59\x56\xa7\x97\xfc\x9d\x3f\x0a\x29\xd8\xdc\x4f\x91\x0e\x13\xbc\xde\x95\xa4\xdf\x8b\x99\xbe\xac\x9b\x33\x88\xef\xb5\x81\xaf\x1b\xc6\x22\x53\xc8\xf6\xc7\xee\x97\x14\xb0\xc5\x7c\x78\x52\xc8\xf0\xce\x6e\x77\x60\x84\xa6\xe9\x2a\x76\x20\xed\x58\x01\x17\x30\x93\xe9\x1a\x8b\xe0\x73\x63\xd9\x6a\x92\x94\x49\x4e\xb4\xad\x4a\x85\xc4\xa3\x22\x30\xfc\x09\xed\x68\x22\x73\xa6\x88\x0c\x55\x21\x58\xc5\xe1\x3a\x9f\x2a\xdd\xca\xe1\x90\xe0\xd9\x73\xab\x6c\x80\xb8\xe8\x0b\x64\x93\xa0\x9c\x8c\x19\xff\xb3\xd2\x0c\xec\x91\x26\x87\x8a\xb3\xa2\xe1\x70\x8f\x2c\x0a\xe5\xcd\x6d\x68\x51\xeb\xda\x3f\x05\x7f\x8b\x32\xe6\x13\x5c\x6b\xfe\x5f\x40\xe2\x22\xc8\xb4\xb4\x64\x4f\xd6\xba\x7d\x48\x3e\xa8\x69\x0c\xd7\xbb\x86\x71\xc9\x73\xb8\x3f\x3b\x9d\x25\x4b\xda\xff\x40\xeb\x02\x03\x01\x00\x01\xa3\x82\x01\x95\x30\x82\x01\x91\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x81\xe1\x06\x03\x55\x1d\x20\x04\x81\xd9\x30\x81\xd6\x30\x81\xd3\x06\x09\x2b\x06\x01\x04\x01\xbe\x58\x00\x03\x30\x81\xc5\x30\x81\x93\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x02\x30\x81\x86\x1a\x81\x83\x41\x6e\x79\x20\x75\x73\x65\x20\x6f\x66\x20\x74\x68\x69\x73\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x63\x6f\x6e\x73\x74\x69\x74\x75\x74\x65\x73\x20\x61\x63\x63\x65\x70\x74\x61\x6e\x63\x65\x20\x6f\x66\x20\x74\x68\x65\x20\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x33\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x50\x6f\x6c\x69\x63\x79\x20\x2f\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x50\x72\x61\x63\x74\x69\x63\x65\x20\x53\x74\x61\x74\x65\x6d\x65\x6e\x74\x2e\x30\x2d\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x21\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x71\x75\x6f\x76\x61\x64\x69\x73\x67\x6c\x6f\x62\x61\x6c\x2e\x63\x6f\x6d\x2f\x63\x70\x73\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xf2\xc0\x13\xe0\x82\x43\x3e\xfb\xee\x2f\x67\x32\x96\x35\x5c\xdb\xb8\xcb\x02\xd0\x30\x6e\x06\x03\x55\x1d\x23\x04\x67\x30\x65\x80\x14\xf2\xc0\x13\xe0\x82\x43\x3e\xfb\xee\x2f\x67\x32\x96\x35\x5c\xdb\xb8\xcb\x02\xd0\xa1\x49\xa4\x47\x30\x45\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4d\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x13\x12\x51\x75\x6f\x56\x61\x64\x69\x73\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x33\x82\x02\x05\xc6\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x4f\xad\xa0\x2c\x4c\xfa\xc0\xf2\x6f\xf7\x66\x55\xab\x23\x34\xee\xe7\x29\xda\xc3\x5b\xb6\xb0\x83\xd9\xd0\xd0\xe2\x21\xfb\xf3\x60\xa7\x3b\x5d\x60\x53\x27\xa2\x9b\xf6\x08\x22\x2a\xe7\xbf\xa0\x72\xe5\x9c\x24\x6a\x31\xb1\x90\x7a\x27\xdb\x84\x11\x89\x27\xa6\x77\x5a\x38\xd7\xbf\xac\x86\xfc\xee\x5d\x83\xbc\x06\xc6\xd1\x77\x6b\x0f\x6d\x24\x2f\x4b\x7a\x6c\xa7\x07\x96\xca\xe3\x84\x9f\xad\x88\x8b\x1d\xab\x16\x8d\x5b\x66\x17\xd9\x16\xf4\x8b\x80\xd2\xdd\xf8\xb2\x76\xc3\xfc\x38\x13\xaa\x0c\xde\x42\x69\x2b\x6e\xf3\x3c\xeb\x80\x27\xdb\xf5\xa6\x44\x0d\x9f\x5a\x55\x59\x0b\xd5\x0d\x52\x48\xc5\xae\x9f\xf2\x2f\x80\xc5\xea\x32\x50\x35\x12\x97\x2e\xc1\xe1\xff\xf1\x23\x88\x51\x38\x9f\xf2\x66\x56\x76\xe7\x0f\x51\x97\xa5\x52\x0c\x4d\x49\x51\x95\x36\x3d\xbf\xa2\x4b\x0c\x10\x1d\x86\x99\x4c\xaa\xf3\x72\x11\x93\xe4\xea\xf6\x9b\xda\xa8\x5d\xa7\x4d\xb7\x9e\x02\xae\x73\x00\xc8\xda\x23\x03\xe8\xf9\xea\x19\x74\x62\x00\x94\xcb\x22\x20\xbe\x94\xa7\x59\xb5\x82\x6a\xbe\x99\x79\x7a\xa9\xf2\x4a\x24\x52\xf7\x74\xfd\xba\x4e\xe6\xa8\x1d\x02\x6e\xb1\x0d\x80\x44\xc1\xae\xd3\x23\x37\x5f\xbb\x85\x7c\x2b\x92\x2e\xe8\x7e\xa5\x8b\xdd\x99\xe1\xbf\x27\x6f\x2d\x5d\xaa\x7b\x87\xfe\x0a\xdd\x4b\xfc\x8e\xf5\x26\xe4\x6e\x70\x42\x6e\x33\xec\x31\x9e\x7b\x93\xc1\xe4\xc9\x69\x1a\x3d\xc0\x6b\x4e\x22\x6d\xee\xab\x58\x4d\xc6\xd0\x41\xc1\x2b\xea\x4f\x12\x87\x5e\xeb\x45\xd8\x6c\xf5\x98\x02\xd3\xa0\xd8\x55\x8a\x06\x99\x19\xa2\xa0\x77\xd1\x30\x9e\xac\xcc\x75\xee\x83\xf5\xb0\x62\x39\xcf\x6c\x57\xe2\x4c\xd2\x91\x0b\x0e\x75\x28\x1b\x9a\xbf\xfd\x1a\x43\xf1\xca\x77\xfb\x3b\x8f\x61\xb8\x69\x28\x16\x42\x04\x5e\x70\x2a\x1c\x21\xd8\x8f\xe1\xbd\x23\x5b\x2d\x74\x40\x92\xd9\x63\x19\x0d\x73\xdd\x69\xbc\x62\x47\xbc\xe0\x74\x2b\xb2\xeb\x7d\xbe\x41\x1b\xb5\xc0\x46\xc5\xa1\x22\xcb\x5f\x4e\xc1\x28\x92\xde\x18\xba\xd5\x2a\x28\xbb\x11\x8b\x17\x93\x98\x99\x60\x94\x5c\x23\xcf\x5a\x27\x97\x5e\x0b\x05\x06\x93\x37\x1e\x3b\x69\x36\xeb\xa9\x9e\x61\x1d\x8f\x32\xda\x8e\x0c\xd6\x74\x3e\x7b\x09\x24\xda\x01\x77\x47\xc4\x3b\xcd\x34\x8c\x99\xf5\xca\xe1\x25\x61\x33\xb2\x59\x1b\xe2\x6e\xd7\x37\x57\xb6\x0d\xa9\x12\xda", 0 }, + /* Anchor: 121 ROOT-CHAMBERS.crt serial: #{a.serial.to_s} + C=EU,O=AC Camerfirma SA CIF A82743287,OU=http://www.chambersign.org,CN=Chambers of Commerce Root + */ + { 1217, "\x30\x82\x04\xbd\x30\x82\x03\xa5\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x7f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x27\x30\x25\x06\x03\x55\x04\x0a\x13\x1e\x41\x43\x20\x43\x61\x6d\x65\x72\x66\x69\x72\x6d\x61\x20\x53\x41\x20\x43\x49\x46\x20\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x23\x30\x21\x06\x03\x55\x04\x0b\x13\x1a\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x63\x68\x61\x6d\x62\x65\x72\x73\x69\x67\x6e\x2e\x6f\x72\x67\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x43\x68\x61\x6d\x62\x65\x72\x73\x20\x6f\x66\x20\x43\x6f\x6d\x6d\x65\x72\x63\x65\x20\x52\x6f\x6f\x74\x30\x1e\x17\x0d\x30\x33\x30\x39\x33\x30\x31\x36\x31\x33\x34\x33\x5a\x17\x0d\x33\x37\x30\x39\x33\x30\x31\x36\x31\x33\x34\x34\x5a\x30\x7f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x27\x30\x25\x06\x03\x55\x04\x0a\x13\x1e\x41\x43\x20\x43\x61\x6d\x65\x72\x66\x69\x72\x6d\x61\x20\x53\x41\x20\x43\x49\x46\x20\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x23\x30\x21\x06\x03\x55\x04\x0b\x13\x1a\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x63\x68\x61\x6d\x62\x65\x72\x73\x69\x67\x6e\x2e\x6f\x72\x67\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x43\x68\x61\x6d\x62\x65\x72\x73\x20\x6f\x66\x20\x43\x6f\x6d\x6d\x65\x72\x63\x65\x20\x52\x6f\x6f\x74\x30\x82\x01\x20\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0d\x00\x30\x82\x01\x08\x02\x82\x01\x01\x00\xb7\x36\x55\xe5\xa5\x5d\x18\x30\xe0\xda\x89\x54\x91\xfc\xc8\xc7\x52\xf8\x2f\x50\xd9\xef\xb1\x75\x73\x65\x47\x7d\x1b\x5b\xba\x75\xc5\xfc\xa1\x88\x24\xfa\x2f\xed\xca\x08\x4a\x39\x54\xc4\x51\x7a\xb5\xda\x60\xea\x38\x3c\x81\xb2\xcb\xf1\xbb\xd9\x91\x23\x3f\x48\x01\x70\x75\xa9\x05\x2a\xad\x1f\x71\xf3\xc9\x54\x3d\x1d\x06\x6a\x40\x3e\xb3\x0c\x85\xee\x5c\x1b\x79\xc2\x62\xc4\xb8\x36\x8e\x35\x5d\x01\x0c\x23\x04\x47\x35\xaa\x9b\x60\x4e\xa0\x66\x3d\xcb\x26\x0a\x9c\x40\xa1\xf4\x5d\x98\xbf\x71\xab\xa5\x00\x68\x2a\xed\x83\x7a\x0f\xa2\x14\xb5\xd4\x22\xb3\x80\xb0\x3c\x0c\x5a\x51\x69\x2d\x58\x18\x8f\xed\x99\x9e\xf1\xae\xe2\x95\xe6\xf6\x47\xa8\xd6\x0c\x0f\xb0\x58\x58\xdb\xc3\x66\x37\x9e\x9b\x91\x54\x33\x37\xd2\x94\x1c\x6a\x48\xc9\xc9\xf2\xa5\xda\xa5\x0c\x23\xf7\x23\x0e\x9c\x32\x55\x5e\x71\x9c\x84\x05\x51\x9a\x2d\xfd\xe6\x4e\x2a\x34\x5a\xde\xca\x40\x37\x67\x0c\x54\x21\x55\x77\xda\x0a\x0c\xcc\x97\xae\x80\xdc\x94\x36\x4a\xf4\x3e\xce\x36\x13\x1e\x53\xe4\xac\x4e\x3a\x05\xec\xdb\xae\x72\x9c\x38\x8b\xd0\x39\x3b\x89\x0a\x3e\x77\xfe\x75\x02\x01\x03\xa3\x82\x01\x44\x30\x82\x01\x40\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01\x0c\x30\x3c\x06\x03\x55\x1d\x1f\x04\x35\x30\x33\x30\x31\xa0\x2f\xa0\x2d\x86\x2b\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x63\x68\x61\x6d\x62\x65\x72\x73\x69\x67\x6e\x2e\x6f\x72\x67\x2f\x63\x68\x61\x6d\x62\x65\x72\x73\x72\x6f\x6f\x74\x2e\x63\x72\x6c\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xe3\x94\xf5\xb1\x4d\xe9\xdb\xa1\x29\x5b\x57\x8b\x4d\x76\x06\x76\xe1\xd1\xa2\x8a\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x27\x06\x03\x55\x1d\x11\x04\x20\x30\x1e\x81\x1c\x63\x68\x61\x6d\x62\x65\x72\x73\x72\x6f\x6f\x74\x40\x63\x68\x61\x6d\x62\x65\x72\x73\x69\x67\x6e\x2e\x6f\x72\x67\x30\x27\x06\x03\x55\x1d\x12\x04\x20\x30\x1e\x81\x1c\x63\x68\x61\x6d\x62\x65\x72\x73\x72\x6f\x6f\x74\x40\x63\x68\x61\x6d\x62\x65\x72\x73\x69\x67\x6e\x2e\x6f\x72\x67\x30\x58\x06\x03\x55\x1d\x20\x04\x51\x30\x4f\x30\x4d\x06\x0b\x2b\x06\x01\x04\x01\x81\x87\x2e\x0a\x03\x01\x30\x3e\x30\x3c\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x30\x68\x74\x74\x70\x3a\x2f\x2f\x63\x70\x73\x2e\x63\x68\x61\x6d\x62\x65\x72\x73\x69\x67\x6e\x2e\x6f\x72\x67\x2f\x63\x70\x73\x2f\x63\x68\x61\x6d\x62\x65\x72\x73\x72\x6f\x6f\x74\x2e\x68\x74\x6d\x6c\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x0c\x41\x97\xc2\x1a\x86\xc0\x22\x7c\x9f\xfb\x90\xf3\x1a\xd1\x03\xb1\xef\x13\xf9\x21\x5f\x04\x9c\xda\xc9\xa5\x8d\x27\x6c\x96\x87\x91\xbe\x41\x90\x01\x72\x93\xe7\x1e\x7d\x5f\xf6\x89\xc6\x5d\xa7\x40\x09\x3d\xac\x49\x45\x45\xdc\x2e\x8d\x30\x68\xb2\x09\xba\xfb\xc3\x2f\xcc\xba\x0b\xdf\x3f\x77\x7b\x46\x7d\x3a\x12\x24\x8e\x96\x8f\x3c\x05\x0a\x6f\xd2\x94\x28\x1d\x6d\x0c\xc0\x2e\x88\x22\xd5\xd8\xcf\x1d\x13\xc7\xf0\x48\xd7\xd7\x05\xa7\xcf\xc7\x47\x9e\x3b\x3c\x34\xc8\x80\x4f\xd4\x14\xbb\xfc\x0d\x50\xf7\xfa\xb3\xec\x42\x5f\xa9\xdd\x6d\xc8\xf4\x75\xcf\x7b\xc1\x72\x26\xb1\x01\x1c\x5c\x2c\xfd\x7a\x4e\xb4\x01\xc5\x05\x57\xb9\xe7\x3c\xaa\x05\xd9\x88\xe9\x07\x46\x41\xce\xef\x41\x81\xae\x58\xdf\x83\xa2\xae\xca\xd7\x77\x1f\xe7\x00\x3c\x9d\x6f\x8e\xe4\x32\x09\x1d\x4d\x78\x34\x78\x34\x3c\x94\x9b\x26\xed\x4f\x71\xc6\x19\x7a\xbd\x20\x22\x48\x5a\xfe\x4b\x7d\x03\xb7\xe7\x58\xbe\xc6\x32\x4e\x74\x1e\x68\xdd\xa8\x68\x5b\xb3\x3e\xee\x62\x7d\xd9\x80\xe8\x0a\x75\x7a\xb7\xee\xb4\x65\x9a\x21\x90\xe0\xaa\xd0\x98\xbc\x38\xb5\x73\x3c\x8b\xf8\xdc", 0 }, + /* Anchor: 122 ROOT-CHAMBERSIGN.crt serial: #{a.serial.to_s} + C=EU,O=AC Camerfirma SA CIF A82743287,OU=http://www.chambersign.org,CN=Global Chambersign Root + */ + { 1225, "\x30\x82\x04\xc5\x30\x82\x03\xad\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x7d\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x27\x30\x25\x06\x03\x55\x04\x0a\x13\x1e\x41\x43\x20\x43\x61\x6d\x65\x72\x66\x69\x72\x6d\x61\x20\x53\x41\x20\x43\x49\x46\x20\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x23\x30\x21\x06\x03\x55\x04\x0b\x13\x1a\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x63\x68\x61\x6d\x62\x65\x72\x73\x69\x67\x6e\x2e\x6f\x72\x67\x31\x20\x30\x1e\x06\x03\x55\x04\x03\x13\x17\x47\x6c\x6f\x62\x61\x6c\x20\x43\x68\x61\x6d\x62\x65\x72\x73\x69\x67\x6e\x20\x52\x6f\x6f\x74\x30\x1e\x17\x0d\x30\x33\x30\x39\x33\x30\x31\x36\x31\x34\x31\x38\x5a\x17\x0d\x33\x37\x30\x39\x33\x30\x31\x36\x31\x34\x31\x38\x5a\x30\x7d\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x27\x30\x25\x06\x03\x55\x04\x0a\x13\x1e\x41\x43\x20\x43\x61\x6d\x65\x72\x66\x69\x72\x6d\x61\x20\x53\x41\x20\x43\x49\x46\x20\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x23\x30\x21\x06\x03\x55\x04\x0b\x13\x1a\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x63\x68\x61\x6d\x62\x65\x72\x73\x69\x67\x6e\x2e\x6f\x72\x67\x31\x20\x30\x1e\x06\x03\x55\x04\x03\x13\x17\x47\x6c\x6f\x62\x61\x6c\x20\x43\x68\x61\x6d\x62\x65\x72\x73\x69\x67\x6e\x20\x52\x6f\x6f\x74\x30\x82\x01\x20\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0d\x00\x30\x82\x01\x08\x02\x82\x01\x01\x00\xa2\x70\xa2\xd0\x9f\x42\xae\x5b\x17\xc7\xd8\x7d\xcf\x14\x83\xfc\x4f\xc9\xa1\xb7\x13\xaf\x8a\xd7\x9e\x3e\x04\x0a\x92\x8b\x60\x56\xfa\xb4\x32\x2f\x88\x4d\xa1\x60\x08\xf4\xb7\x09\x4e\xa0\x49\x2f\x49\xd6\xd3\xdf\x9d\x97\x5a\x9f\x94\x04\x70\xec\x3f\x59\xd9\xb7\xcc\x66\x8b\x98\x52\x28\x09\x02\xdf\xc5\x2f\x84\x8d\x7a\x97\x77\xbf\xec\x40\x9d\x25\x72\xab\xb5\x3f\x32\x98\xfb\xb7\xb7\xfc\x72\x84\xe5\x35\x87\xf9\x55\xfa\xa3\x1f\x0e\x6f\x2e\x28\xdd\x69\xa0\xd9\x42\x10\xc6\xf8\xb5\x44\xc2\xd0\x43\x7f\xdb\xbc\xe4\xa2\x3c\x6a\x55\x78\x0a\x77\xa9\xd8\xea\x19\x32\xb7\x2f\xfe\x5c\x3f\x1b\xee\xb1\x98\xec\xca\xad\x7a\x69\x45\xe3\x96\x0f\x55\xf6\xe6\xed\x75\xea\x65\xe8\x32\x56\x93\x46\x89\xa8\x25\x8a\x65\x06\xee\x6b\xbf\x79\x07\xd0\xf1\xb7\xaf\xed\x2c\x4d\x92\xbb\xc0\xa8\x5f\xa7\x67\x7d\x04\xf2\x15\x08\x70\xac\x92\xd6\x7d\x04\xd2\x33\xfb\x4c\xb6\x0b\x0b\xfb\x1a\xc9\xc4\x8d\x03\xa9\x7e\x5c\xf2\x50\xab\x12\xa5\xa1\xcf\x48\x50\xa5\xef\xd2\xc8\x1a\x13\xfa\xb0\x7f\xb1\x82\x1c\x77\x6a\x0f\x5f\xdc\x0b\x95\x8f\xef\x43\x7e\xe6\x45\x09\x25\x02\x01\x03\xa3\x82\x01\x50\x30\x82\x01\x4c\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01\x0c\x30\x3f\x06\x03\x55\x1d\x1f\x04\x38\x30\x36\x30\x34\xa0\x32\xa0\x30\x86\x2e\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x63\x68\x61\x6d\x62\x65\x72\x73\x69\x67\x6e\x2e\x6f\x72\x67\x2f\x63\x68\x61\x6d\x62\x65\x72\x73\x69\x67\x6e\x72\x6f\x6f\x74\x2e\x63\x72\x6c\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x43\x9c\x36\x9f\xb0\x9e\x30\x4d\xc6\xce\x5f\xad\x10\xab\xe5\x03\xa5\xfa\xa9\x14\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x2a\x06\x03\x55\x1d\x11\x04\x23\x30\x21\x81\x1f\x63\x68\x61\x6d\x62\x65\x72\x73\x69\x67\x6e\x72\x6f\x6f\x74\x40\x63\x68\x61\x6d\x62\x65\x72\x73\x69\x67\x6e\x2e\x6f\x72\x67\x30\x2a\x06\x03\x55\x1d\x12\x04\x23\x30\x21\x81\x1f\x63\x68\x61\x6d\x62\x65\x72\x73\x69\x67\x6e\x72\x6f\x6f\x74\x40\x63\x68\x61\x6d\x62\x65\x72\x73\x69\x67\x6e\x2e\x6f\x72\x67\x30\x5b\x06\x03\x55\x1d\x20\x04\x54\x30\x52\x30\x50\x06\x0b\x2b\x06\x01\x04\x01\x81\x87\x2e\x0a\x01\x01\x30\x41\x30\x3f\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x33\x68\x74\x74\x70\x3a\x2f\x2f\x63\x70\x73\x2e\x63\x68\x61\x6d\x62\x65\x72\x73\x69\x67\x6e\x2e\x6f\x72\x67\x2f\x63\x70\x73\x2f\x63\x68\x61\x6d\x62\x65\x72\x73\x69\x67\x6e\x72\x6f\x6f\x74\x2e\x68\x74\x6d\x6c\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x3c\x3b\x70\x91\xf9\x04\x54\x27\x91\xe1\xed\xed\xfe\x68\x7f\x61\x5d\xe5\x41\x65\x4f\x32\xf1\x18\x05\x94\x6a\x1c\xde\x1f\x70\xdb\x3e\x7b\x32\x02\x34\xb5\x0c\x6c\xa1\x8a\x7c\xa5\xf4\x8f\xff\xd4\xd8\xad\x17\xd5\x2d\x04\xd1\x3f\x58\x80\xe2\x81\x59\x88\xbe\xc0\xe3\x46\x93\x24\xfe\x90\xbd\x26\xa2\x30\x2d\xe8\x97\x26\x57\x35\x89\x74\x96\x18\xf6\x15\xe2\xaf\x24\x19\x56\x02\x02\xb2\xba\x0f\x14\xea\xc6\x8a\x66\xc1\x86\x45\x55\x8b\xbe\x92\xbe\x9c\xa4\x04\xc7\x49\x3c\x9e\xe8\x29\x7a\x89\xd7\xfe\xaf\xff\x68\xf5\xa5\x17\x90\xbd\xac\x99\xcc\xa5\x86\x57\x09\x67\x46\xdb\xd6\x16\xc2\x46\xf1\xe4\xa9\x50\xf5\x8f\xd1\x92\x15\xd3\x5f\x3e\xc6\x00\x49\x3a\x6e\x58\xb2\xd1\xd1\x27\x0d\x25\xc8\x32\xf8\x20\x11\xcd\x7d\x32\x33\x48\x94\x54\x4c\xdd\xdc\x79\xc4\x30\x9f\xeb\x8e\xb8\x55\xb5\xd7\x88\x5c\xc5\x6a\x24\x3d\xb2\xd3\x05\x03\x51\xc6\x07\xef\xcc\x14\x72\x74\x3d\x6e\x72\xce\x18\x28\x8c\x4a\xa0\x77\xe5\x09\x2b\x45\x44\x47\xac\xb7\x67\x7f\x01\x8a\x05\x5a\x93\xbe\xa1\xc1\xff\xf8\xe7\x0e\x67\xa4\x47\x49\x76\x5d\x75\x90\x1a\xf5\x26\x8f\xf0", 0 }, + /* Anchor: 123 Root_CA_der.crt serial: #{a.serial.to_s} + C=US,O=VISA,OU=Visa International Service Association,CN=Visa eCommerce Root + */ + { 934, "\x30\x82\x03\xa2\x30\x82\x02\x8a\xa0\x03\x02\x01\x02\x02\x10\x13\x86\x35\x4d\x1d\x3f\x06\xf2\xc1\xf9\x65\x05\xd5\x90\x1c\x62\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x6b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0d\x30\x0b\x06\x03\x55\x04\x0a\x13\x04\x56\x49\x53\x41\x31\x2f\x30\x2d\x06\x03\x55\x04\x0b\x13\x26\x56\x69\x73\x61\x20\x49\x6e\x74\x65\x72\x6e\x61\x74\x69\x6f\x6e\x61\x6c\x20\x53\x65\x72\x76\x69\x63\x65\x20\x41\x73\x73\x6f\x63\x69\x61\x74\x69\x6f\x6e\x31\x1c\x30\x1a\x06\x03\x55\x04\x03\x13\x13\x56\x69\x73\x61\x20\x65\x43\x6f\x6d\x6d\x65\x72\x63\x65\x20\x52\x6f\x6f\x74\x30\x1e\x17\x0d\x30\x32\x30\x36\x32\x36\x30\x32\x31\x38\x33\x36\x5a\x17\x0d\x32\x32\x30\x36\x32\x34\x30\x30\x31\x36\x31\x32\x5a\x30\x6b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0d\x30\x0b\x06\x03\x55\x04\x0a\x13\x04\x56\x49\x53\x41\x31\x2f\x30\x2d\x06\x03\x55\x04\x0b\x13\x26\x56\x69\x73\x61\x20\x49\x6e\x74\x65\x72\x6e\x61\x74\x69\x6f\x6e\x61\x6c\x20\x53\x65\x72\x76\x69\x63\x65\x20\x41\x73\x73\x6f\x63\x69\x61\x74\x69\x6f\x6e\x31\x1c\x30\x1a\x06\x03\x55\x04\x03\x13\x13\x56\x69\x73\x61\x20\x65\x43\x6f\x6d\x6d\x65\x72\x63\x65\x20\x52\x6f\x6f\x74\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xaf\x57\xde\x56\x1e\x6e\xa1\xda\x60\xb1\x94\x27\xcb\x17\xdb\x07\x3f\x80\x85\x4f\xc8\x9c\xb6\xd0\xf4\x6f\x4f\xcf\x99\xd8\xe1\xdb\xc2\x48\x5c\x3a\xac\x39\x33\xc7\x1f\x6a\x8b\x26\x3d\x2b\x35\xf5\x48\xb1\x91\xc1\x02\x4e\x04\x96\x91\x7b\xb0\x33\xf0\xb1\x14\x4e\x11\x6f\xb5\x40\xaf\x1b\x45\xa5\x4a\xef\x7e\xb6\xac\xf2\xa0\x1f\x58\x3f\x12\x46\x60\x3c\x8d\xa1\xe0\x7d\xcf\x57\x3e\x33\x1e\xfb\x47\xf1\xaa\x15\x97\x07\x55\x66\xa5\xb5\x2d\x2e\xd8\x80\x59\xb2\xa7\x0d\xb7\x46\xec\x21\x63\xff\x35\xab\xa5\x02\xcf\x2a\xf4\x4c\xfe\x7b\xf5\x94\x5d\x84\x4d\xa8\xf2\x60\x8f\xdb\x0e\x25\x3c\x9f\x73\x71\xcf\x94\xdf\x4a\xea\xdb\xdf\x72\x38\x8c\xf3\x96\xbd\xf1\x17\xbc\xd2\xba\x3b\x45\x5a\xc6\xa7\xf6\xc6\x17\x8b\x01\x9d\xfc\x19\xa8\x2a\x83\x16\xb8\x3a\x48\xfe\x4e\x3e\xa0\xab\x06\x19\xe9\x53\xf3\x80\x13\x07\xed\x2d\xbf\x3f\x0a\x3c\x55\x20\x39\x2c\x2c\x00\x69\x74\x95\x4a\xbc\x20\xb2\xa9\x79\xe5\x18\x89\x91\xa8\xdc\x1c\x4d\xef\xbb\x7e\x37\x0b\x5d\xfe\x39\xa5\x88\x52\x8c\x00\x6c\xec\x18\x7c\x41\xbd\xf6\x8b\x75\x77\xba\x60\x9d\x84\xe7\xfe\x2d\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x15\x38\x83\x0f\x3f\x2c\x3f\x70\x33\x1e\xcd\x46\xfe\x07\x8c\x20\xe0\xd7\xc3\xb7\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x5f\xf1\x41\x7d\x7c\x5c\x08\xb9\x2b\xe0\xd5\x92\x47\xfa\x67\x5c\xa5\x13\xc3\x03\x21\x9b\x2b\x4c\x89\x46\xcf\x59\x4d\xc9\xfe\xa5\x40\xb6\x63\xcd\xdd\x71\x28\x95\x67\x11\xcc\x24\xac\xd3\x44\x6c\x71\xae\x01\x20\x6b\x03\xa2\x8f\x18\xb7\x29\x3a\x7d\xe5\x16\x60\x53\x78\x3c\xc0\xaf\x15\x83\xf7\x8f\x52\x33\x24\xbd\x64\x93\x97\xee\x8b\xf7\xdb\x18\xa8\x6d\x71\xb3\xf7\x2c\x17\xd0\x74\x25\x69\xf7\xfe\x6b\x3c\x94\xbe\x4d\x4b\x41\x8c\x4e\xe2\x73\xd0\xe3\x90\x22\x73\x43\xcd\xf3\xef\xea\x73\xce\x45\x8a\xb0\xa6\x49\xff\x4c\x7d\x9d\x71\x88\xc4\x76\x1d\x90\x5b\x1d\xee\xfd\xcc\xf7\xee\xfd\x60\xa5\xb1\x7a\x16\x71\xd1\x16\xd0\x7c\x12\x3c\x6c\x69\x97\xdb\xae\x5f\x39\x9a\x70\x2f\x05\x3c\x19\x46\x04\x99\x20\x36\xd0\x60\x6e\x61\x06\xbb\x16\x42\x8c\x70\xf7\x30\xfb\xe0\xdb\x66\xa3\x00\x01\xbd\xe6\x2c\xda\x91\x5f\xa0\x46\x8b\x4d\x6a\x9c\x3d\x3d\xdd\x05\x46\xfe\x76\xbf\xa0\x0a\x3c\xe4\x00\xe6\x27\xb7\xff\x84\x2d\xde\xba\x22\x27\x96\x10\x71\xeb\x22\xed\xdf\xdf\x33\x9c\xcf\xe3\xad\xae\x8e\xd4\x8e\xe6\x4f\x51\xaf\x16\x92\xe0\x5c\xf6\x07\x0f", 0 }, + /* Anchor: 124 RSA_Root_CA.der serial: #{a.serial.to_s} + O=RSA Security Inc,OU=RSA Security 2048 V3 + */ + { 869, "\x30\x82\x03\x61\x30\x82\x02\x49\xa0\x03\x02\x01\x02\x02\x10\x0a\x01\x01\x01\x00\x00\x02\x7c\x00\x00\x00\x0a\x00\x00\x00\x02\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x3a\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x52\x53\x41\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x49\x6e\x63\x31\x1d\x30\x1b\x06\x03\x55\x04\x0b\x13\x14\x52\x53\x41\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x32\x30\x34\x38\x20\x56\x33\x30\x1e\x17\x0d\x30\x31\x30\x32\x32\x32\x32\x30\x33\x39\x32\x33\x5a\x17\x0d\x32\x36\x30\x32\x32\x32\x32\x30\x33\x39\x32\x33\x5a\x30\x3a\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x52\x53\x41\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x49\x6e\x63\x31\x1d\x30\x1b\x06\x03\x55\x04\x0b\x13\x14\x52\x53\x41\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x32\x30\x34\x38\x20\x56\x33\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xb7\x8f\x55\x71\xd2\x80\xdd\x7b\x69\x79\xa7\xf0\x18\x50\x32\x3c\x62\x67\xf6\x0a\x95\x07\xdd\xe6\x1b\xf3\x9e\xd9\xd2\x41\x54\x6b\xad\x9f\x7c\xbe\x19\xcd\xfb\x46\xab\x41\x68\x1e\x18\xea\x55\xc8\x2f\x91\x78\x89\x28\xfb\x27\x29\x60\xff\xdf\x8f\x8c\x3b\xc9\x49\x9b\xb5\xa4\x94\xce\x01\xea\x3e\xb5\x63\x7b\x7f\x26\xfd\x19\xdd\xc0\x21\xbd\x84\xd1\x2d\x4f\x46\xc3\x4e\xdc\xd8\x37\x39\x3b\x28\xaf\xcb\x9d\x1a\xea\x2b\xaf\x21\xa5\xc1\x23\x22\xb8\xb8\x1b\x5a\x13\x87\x57\x83\xd1\xf0\x20\xe7\xe8\x4f\x23\x42\xb0\x00\xa5\x7d\x89\xe9\xe9\x61\x73\x94\x98\x71\x26\xbc\x2d\x6a\xe0\xf7\x4d\xf0\xf1\xb6\x2a\x38\x31\x81\x0d\x29\xe1\x00\xc1\x51\x0f\x4c\x52\xf8\x04\x5a\xaa\x7d\x72\xd3\xb8\x87\x2a\xbb\x63\x10\x03\x2a\xb3\xa1\x4f\x0d\x5a\x5e\x46\xb7\x3d\x0e\xf5\x74\xec\x99\x9f\xf9\x3d\x24\x81\x88\xa6\xdd\x60\x54\xe8\x95\x36\x3d\xc6\x09\x93\x9a\xa3\x12\x80\x00\x55\x99\x19\x47\xbd\xd0\xa5\x7c\xc3\xba\xfb\x1f\xf7\xf5\x0f\xf8\xac\xb9\xb5\xf4\x37\x98\x13\x18\xde\x85\x5b\xb7\x0c\x82\x3b\x87\x6f\x95\x39\x58\x30\xda\x6e\x01\x68\x17\x22\xcc\xc0\x0b\x02\x03\x01\x00\x01\xa3\x63\x30\x61\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x07\xc3\x51\x30\xa4\xaa\xe9\x45\xae\x35\x24\xfa\xff\x24\x2c\x33\xd0\xb1\x9d\x8c\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x07\xc3\x51\x30\xa4\xaa\xe9\x45\xae\x35\x24\xfa\xff\x24\x2c\x33\xd0\xb1\x9d\x8c\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x5f\x3e\x86\x76\x6e\xb8\x35\x3c\x4e\x36\x1c\x1e\x79\x98\xbf\xfd\xd5\x12\x11\x79\x52\x0e\xee\x31\x89\xbc\xdd\x7f\xf9\xd1\xc6\x15\x21\xe8\x8a\x01\x54\x0d\x3a\xfb\x54\xb9\xd6\x63\xd4\xb1\xaa\x96\x4d\xa2\x42\x4d\xd4\x53\x1f\x8b\x10\xde\x7f\x65\xbe\x60\x13\x27\x71\x88\xa4\x73\xe3\x84\x63\xd1\xa4\x55\xe1\x50\x93\xe6\x1b\x0e\x79\xd0\x67\xbc\x46\xc8\xbf\x3f\x17\x0d\x95\xe6\xc6\x90\x69\xde\xe7\xb4\x2f\xde\x95\x7d\xd0\x12\x3f\x3d\x3e\x7f\x4d\x3f\x14\x68\xf5\x11\x50\xd5\xc1\xf4\x90\xa5\x08\x1d\x31\x60\xff\x60\x8c\x23\x54\x0a\xaf\xfe\xa1\x6e\xc5\xd1\x7a\x2a\x68\x78\xcf\x1e\x82\x0a\x20\xb4\x1f\xad\xe5\x85\xb2\x6a\x68\x75\x4e\xad\x25\x37\x94\x85\xbe\xbd\xa1\xd4\xea\xb7\x0c\x4b\x3c\x9d\xe8\x12\x00\xf0\x5f\xac\x0d\xe1\xac\x70\x63\x73\xf7\x7f\x79\x9f\x32\x25\x42\x74\x05\x80\x28\xbf\xbd\xc1\x24\x96\x58\x15\xb1\x17\x21\xe9\x89\x4b\xdb\x07\x88\x67\xf4\x15\xad\x70\x3e\x2f\x4d\x85\x3b\xc2\xb7\xdb\xfe\x98\x68\x23\x89\xe1\x74\x0f\xde\xf4\xc5\x84\x63\x29\x1b\xcc\xcb\x07\xc9\x00\xa4\xa9\xd7\xc2\x22\x4f\x67\xd7\x77\xec\x20\x05\x61\xde", 0 }, + /* Anchor: 125 SCRoot1ca.cer serial: #{a.serial.to_s} + C=JP,O=SECOM Trust.net,OU=Security Communication RootCA1 + */ + { 862, "\x30\x82\x03\x5a\x30\x82\x02\x42\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x50\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4a\x50\x31\x18\x30\x16\x06\x03\x55\x04\x0a\x13\x0f\x53\x45\x43\x4f\x4d\x20\x54\x72\x75\x73\x74\x2e\x6e\x65\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0b\x13\x1e\x53\x65\x63\x75\x72\x69\x74\x79\x20\x43\x6f\x6d\x6d\x75\x6e\x69\x63\x61\x74\x69\x6f\x6e\x20\x52\x6f\x6f\x74\x43\x41\x31\x30\x1e\x17\x0d\x30\x33\x30\x39\x33\x30\x30\x34\x32\x30\x34\x39\x5a\x17\x0d\x32\x33\x30\x39\x33\x30\x30\x34\x32\x30\x34\x39\x5a\x30\x50\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4a\x50\x31\x18\x30\x16\x06\x03\x55\x04\x0a\x13\x0f\x53\x45\x43\x4f\x4d\x20\x54\x72\x75\x73\x74\x2e\x6e\x65\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0b\x13\x1e\x53\x65\x63\x75\x72\x69\x74\x79\x20\x43\x6f\x6d\x6d\x75\x6e\x69\x63\x61\x74\x69\x6f\x6e\x20\x52\x6f\x6f\x74\x43\x41\x31\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xb3\xb3\xfe\x7f\xd3\x6d\xb1\xef\x16\x7c\x57\xa5\x0c\x6d\x76\x8a\x2f\x4b\xbf\x64\xfb\x4c\xee\x8a\xf0\xf3\x29\x7c\xf5\xff\xee\x2a\xe0\xe9\xe9\xba\x5b\x64\x22\x9a\x9a\x6f\x2c\x3a\x26\x69\x51\x05\x99\x26\xdc\xd5\x1c\x6a\x71\xc6\x9a\x7d\x1e\x9d\xdd\x7c\x6c\xc6\x8c\x67\x67\x4a\x3e\xf8\x71\xb0\x19\x27\xa9\x09\x0c\xa6\x95\xbf\x4b\x8c\x0c\xfa\x55\x98\x3b\xd8\xe8\x22\xa1\x4b\x71\x38\x79\xac\x97\x92\x69\xb3\x89\x7e\xea\x21\x68\x06\x98\x14\x96\x87\xd2\x61\x36\xbc\x6d\x27\x56\x9e\x57\xee\xc0\xc0\x56\xfd\x32\xcf\xa4\xd9\x8e\xc2\x23\xd7\x8d\xa8\xf3\xd8\x25\xac\x97\xe4\x70\x38\xf4\xb6\x3a\xb4\x9d\x3b\x97\x26\x43\xa3\xa1\xbc\x49\x59\x72\x4c\x23\x30\x87\x01\x58\xf6\x4e\xbe\x1c\x68\x56\x66\xaf\xcd\x41\x5d\xc8\xb3\x4d\x2a\x55\x46\xab\x1f\xda\x1e\xe2\x40\x3d\xdb\xcd\x7d\xb9\x92\x80\x9c\x37\xdd\x0c\x96\x64\x9d\xdc\x22\xf7\x64\x8b\xdf\x61\xde\x15\x94\x52\x15\xa0\x7d\x52\xc9\x4b\xa8\x21\xc9\xc6\xb1\xed\xcb\xc3\x95\x60\xd1\x0f\xf0\xab\x70\xf8\xdf\xcb\x4d\x7e\xec\xd6\xfa\xab\xd9\xbd\x7f\x54\xf2\xa5\xe9\x79\xfa\xd9\xd6\x76\x24\x28\x73\x02\x03\x01\x00\x01\xa3\x3f\x30\x3d\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xa0\x73\x49\x99\x68\xdc\x85\x5b\x65\xe3\x9b\x28\x2f\x57\x9f\xbd\x33\xbc\x07\x48\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x68\x40\xa9\xa8\xbb\xe4\x4f\x5d\x79\xb3\x05\xb5\x17\xb3\x60\x13\xeb\xc6\x92\x5d\xe0\xd1\xd3\x6a\xfe\xfb\xbe\x9b\x6d\xbf\xc7\x05\x6d\x59\x20\xc4\x1c\xf0\xb7\xda\x84\x58\x02\x63\xfa\x48\x16\xef\x4f\xa5\x0b\xf7\x4a\x98\xf2\x3f\x9e\x1b\xad\x47\x6b\x63\xce\x08\x47\xeb\x52\x3f\x78\x9c\xaf\x4d\xae\xf8\xd5\x4f\xcf\x9a\x98\x2a\x10\x41\x39\x52\xc4\xdd\xd9\x9b\x0e\xef\x93\x01\xae\xb2\x2e\xca\x68\x42\x24\x42\x6c\xb0\xb3\x3a\x3e\xcd\xe9\xda\x48\xc4\x15\xcb\xe9\xf9\x07\x0f\x92\x50\x49\x8a\xdd\x31\x97\x5f\xc9\xe9\x37\xaa\x3b\x59\x65\x97\x94\x32\xc9\xb3\x9f\x3e\x3a\x62\x58\xc5\x49\xad\x62\x0e\x71\xa5\x32\xaa\x2f\xc6\x89\x76\x43\x40\x13\x13\x67\x3d\xa2\x54\x25\x10\xcb\xf1\x3a\xf2\xd9\xfa\xdb\x49\x56\xbb\xa6\xfe\xa7\x41\x35\xc3\xe0\x88\x61\xc9\x88\xc7\xdf\x36\x10\x22\x98\x59\xea\xb0\x4a\xfb\x56\x16\x73\x6e\xac\x4d\xf7\x22\xa1\x4f\xad\x1d\x7a\x2d\x45\x27\xe5\x30\xc1\x5e\xf2\xda\x13\xcb\x25\x42\x51\x95\x47\x03\x8c\x6c\x21\xcc\x74\x42\xed\x53\xff\x33\x8b\x8f\x0f\x57\x01\x16\x2f\xcf\xa6\xee\xc9\x70\x22\x14\xbd\xfd\xbe\x6c\x0b\x03", 0 }, + /* Anchor: 126 SECOM-EVRoot1ca.cer serial: #{a.serial.to_s} + C=JP,O=SECOM Trust Systems CO.\,LTD.,OU=Security Communication EV RootCA1 + */ + { 897, "\x30\x82\x03\x7d\x30\x82\x02\x65\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x60\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4a\x50\x31\x25\x30\x23\x06\x03\x55\x04\x0a\x13\x1c\x53\x45\x43\x4f\x4d\x20\x54\x72\x75\x73\x74\x20\x53\x79\x73\x74\x65\x6d\x73\x20\x43\x4f\x2e\x2c\x4c\x54\x44\x2e\x31\x2a\x30\x28\x06\x03\x55\x04\x0b\x13\x21\x53\x65\x63\x75\x72\x69\x74\x79\x20\x43\x6f\x6d\x6d\x75\x6e\x69\x63\x61\x74\x69\x6f\x6e\x20\x45\x56\x20\x52\x6f\x6f\x74\x43\x41\x31\x30\x1e\x17\x0d\x30\x37\x30\x36\x30\x36\x30\x32\x31\x32\x33\x32\x5a\x17\x0d\x33\x37\x30\x36\x30\x36\x30\x32\x31\x32\x33\x32\x5a\x30\x60\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4a\x50\x31\x25\x30\x23\x06\x03\x55\x04\x0a\x13\x1c\x53\x45\x43\x4f\x4d\x20\x54\x72\x75\x73\x74\x20\x53\x79\x73\x74\x65\x6d\x73\x20\x43\x4f\x2e\x2c\x4c\x54\x44\x2e\x31\x2a\x30\x28\x06\x03\x55\x04\x0b\x13\x21\x53\x65\x63\x75\x72\x69\x74\x79\x20\x43\x6f\x6d\x6d\x75\x6e\x69\x63\x61\x74\x69\x6f\x6e\x20\x45\x56\x20\x52\x6f\x6f\x74\x43\x41\x31\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xbc\x7f\xec\x57\x9b\x24\xe0\xfe\x9c\xba\x42\x79\xa9\x88\x8a\xfa\x80\xe0\xf5\x07\x29\x43\xea\x8e\x0a\x34\x36\x8d\x1c\xfa\xa7\xb5\x39\x78\xff\x97\x75\xf7\x2f\xe4\xaa\x6b\x04\x84\x44\xca\xa6\xe2\x68\x8e\xfd\x55\x50\x62\x0f\xa4\x71\x0e\xce\x07\x38\x2d\x42\x85\x50\xad\x3c\x96\x6f\x8b\xd5\xa2\x0e\xcf\xde\x49\x89\x3d\xd6\x64\x2e\x38\xe5\x1e\x6c\xb5\x57\x8a\x9e\xef\x48\x0e\xcd\x7a\x69\x16\x87\x44\xb5\x90\xe4\x06\x9d\xae\xa1\x04\x97\x58\x79\xef\x20\x4a\x82\x6b\x8c\x22\xbf\xec\x1f\x0f\xe9\x84\x71\xed\xf1\x0e\xe4\xb8\x18\x13\xcc\x56\x36\x5d\xd1\x9a\x1e\x51\x6b\x39\x6e\x60\x76\x88\x34\x0b\xf3\xb3\xd1\xb0\x9d\xca\x61\xe2\x64\x1d\xc1\x46\x07\xb8\x63\xdd\x1e\x33\x65\xb3\x8e\x09\x55\x52\x3d\xb5\xbd\xff\x07\xeb\xad\x61\x55\x18\x2c\xa9\x69\x98\x4a\xaa\x40\xc5\x33\x14\x65\x74\x00\xf9\x91\xde\xaf\x03\x48\xc5\x40\x54\xdc\x0f\x84\x90\x68\x20\xc5\x92\x96\xdc\x2e\xe5\x02\x45\xaa\xc0\x5f\x54\xf8\x6d\xea\x49\xcf\x5d\x6c\x4b\xaf\xef\x9a\xc2\x56\x5c\xc6\x35\x56\x42\x6a\x30\x5f\xc2\xab\xf6\xe2\x3d\x3f\xb3\xc9\x11\x8f\x31\x4c\xd7\x9f\x49\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x35\x4a\xf5\x4d\xaf\x3f\xd7\x82\x38\xac\xab\x71\x65\x17\x75\x8c\x9d\x55\x93\xe6\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xa8\x87\xe9\xec\xf8\x40\x67\x5d\xc3\xc1\x66\xc7\x40\x4b\x97\xfc\x87\x13\x90\x5a\xc4\xef\xa0\xca\x5f\x8b\xb7\xa7\xb7\xf1\xd6\xb5\x64\xb7\x8a\xb3\xb8\x1b\xcc\xda\xfb\xac\x66\x88\x41\xce\xe8\xfc\xe4\xdb\x1e\x88\xa6\xed\x27\x50\x1b\x02\x30\x24\x46\x79\xfe\x04\x87\x70\x97\x40\x73\xd1\xc0\xc1\x57\x19\x9a\x69\xa5\x27\x99\xab\x9d\x62\x84\xf6\x51\xc1\x2c\xc9\x23\x15\xd8\x28\xb7\xab\x25\x13\xb5\x46\xe1\x86\x02\xff\x26\x8c\xc4\x88\x92\x1d\x56\xfe\x19\x67\xf2\x55\xe4\x80\xa3\x6b\x9c\xab\x77\xe1\x51\x71\x0d\x20\xdb\x10\x9a\xdb\xbd\x76\x79\x07\x77\x99\x28\xad\x9a\x5e\xda\xb1\x4f\x44\x2c\x35\x8e\xa5\x96\xc7\xfd\x83\xf0\x58\xc6\x79\xd6\x98\x7c\xa8\x8d\xfe\x86\x3e\x07\x16\x92\xe1\x7b\xe7\x1d\xec\x33\x76\x7e\x42\x2e\x4a\x85\xf9\x91\x89\x68\x84\x03\x81\xa5\x9b\x9a\xbe\xe3\x37\xc5\x54\xab\x56\x3b\x18\x2d\x41\xa4\x0c\xf8\x42\xdb\x99\xa0\xe0\x72\x6f\xbb\x5d\xe1\x16\x4f\x53\x0a\x64\xf9\x4e\xf4\xbf\x4e\x54\xbd\x78\x6c\x88\xea\xbf\x9c\x13\x24\xc2\x70\x69\xa2\x7f\x0f\xc8\x3c\xad\x08\xc9\xb0\x98\x40\xa3\x2a\xe7\x88\x83\xed\x77\x8f\x74", 0 }, + /* Anchor: 127 SECOM-RootCA2.cer serial: #{a.serial.to_s} + C=JP,O=SECOM Trust Systems CO.\,LTD.,OU=Security Communication RootCA2 + */ + { 891, "\x30\x82\x03\x77\x30\x82\x02\x5f\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x30\x5d\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4a\x50\x31\x25\x30\x23\x06\x03\x55\x04\x0a\x13\x1c\x53\x45\x43\x4f\x4d\x20\x54\x72\x75\x73\x74\x20\x53\x79\x73\x74\x65\x6d\x73\x20\x43\x4f\x2e\x2c\x4c\x54\x44\x2e\x31\x27\x30\x25\x06\x03\x55\x04\x0b\x13\x1e\x53\x65\x63\x75\x72\x69\x74\x79\x20\x43\x6f\x6d\x6d\x75\x6e\x69\x63\x61\x74\x69\x6f\x6e\x20\x52\x6f\x6f\x74\x43\x41\x32\x30\x1e\x17\x0d\x30\x39\x30\x35\x32\x39\x30\x35\x30\x30\x33\x39\x5a\x17\x0d\x32\x39\x30\x35\x32\x39\x30\x35\x30\x30\x33\x39\x5a\x30\x5d\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4a\x50\x31\x25\x30\x23\x06\x03\x55\x04\x0a\x13\x1c\x53\x45\x43\x4f\x4d\x20\x54\x72\x75\x73\x74\x20\x53\x79\x73\x74\x65\x6d\x73\x20\x43\x4f\x2e\x2c\x4c\x54\x44\x2e\x31\x27\x30\x25\x06\x03\x55\x04\x0b\x13\x1e\x53\x65\x63\x75\x72\x69\x74\x79\x20\x43\x6f\x6d\x6d\x75\x6e\x69\x63\x61\x74\x69\x6f\x6e\x20\x52\x6f\x6f\x74\x43\x41\x32\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xd0\x15\x39\x52\xb1\x52\xb3\xba\xc5\x59\x82\xc4\x5d\x52\xae\x3a\x43\x65\x80\x4b\xc7\xf2\x96\xbc\xdb\x36\x97\xd6\xa6\x64\x8c\xa8\x5e\xf0\xe3\x0a\x1c\xf7\xdf\x97\x3d\x4b\xae\xf6\x5d\xec\x21\xb5\x41\xab\xcd\xb9\x7e\x76\x9f\xbe\xf9\x3e\x36\x34\xa0\x3b\xc1\xf6\x31\x11\x45\x74\x93\x3d\x57\x80\xc5\xf9\x89\x99\xca\xe5\xab\x6a\xd4\xb5\xda\x41\x90\x10\xc1\xd6\xd6\x42\x89\xc2\xbf\xf4\x38\x12\x95\x4c\x54\x05\xf7\x36\xe4\x45\x83\x7b\x14\x65\xd6\xdc\x0c\x4d\xd1\xde\x7e\x0c\xab\x3b\xc4\x15\xbe\x3a\x56\xa6\x5a\x6f\x76\x69\x52\xa9\x7a\xb9\xc8\xeb\x6a\x9a\x5d\x52\xd0\x2d\x0a\x6b\x35\x16\x09\x10\x84\xd0\x6a\xca\x3a\x06\x00\x37\x47\xe4\x7e\x57\x4f\x3f\x8b\xeb\x67\xb8\x88\xaa\xc5\xbe\x53\x55\xb2\x91\xc4\x7d\xb9\xb0\x85\x19\x06\x78\x2e\xdb\x61\x1a\xfa\x85\xf5\x4a\x91\xa1\xe7\x16\xd5\x8e\xa2\x39\xdf\x94\xb8\x70\x1f\x28\x3f\x8b\xfc\x40\x5e\x63\x83\x3c\x83\x2a\x1a\x99\x6b\xcf\xde\x59\x6a\x3b\xfc\x6f\x16\xd7\x1f\xfd\x4a\x10\xeb\x4e\x82\x16\x3a\xac\x27\x0c\x53\xf1\xad\xd5\x24\xb0\x6b\x03\x50\xc1\x2d\x3c\x16\xdd\x44\x34\x27\x1a\x75\xfb\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x0a\x85\xa9\x77\x65\x05\x98\x7c\x40\x81\xf8\x0f\x97\x2c\x38\xf1\x0a\xec\x3c\xcf\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x03\x82\x01\x01\x00\x4c\x3a\xa3\x44\xac\xb9\x45\xb1\xc7\x93\x7e\xc8\x0b\x0a\x42\xdf\x64\xea\x1c\xee\x59\x6c\x08\xba\x89\x5f\x6a\xca\x4a\x95\x9e\x7a\x8f\x07\xc5\xda\x45\x72\x82\x71\x0e\x3a\xd2\xcc\x6f\xa7\xb4\xa1\x23\xbb\xf6\x24\x9f\xcb\x17\xfe\x8c\xa6\xce\xc2\xd2\xdb\xcc\x8d\xfc\x71\xfc\x03\x29\xc1\x6c\x5d\x33\x5f\x64\xb6\x65\x3b\x89\x6f\x18\x76\x78\xf5\xdc\xa2\x48\x1f\x19\x3f\x8e\x93\xeb\xf1\xfa\x17\xee\xcd\x4e\xe3\x04\x12\x55\xd6\xe5\xe4\xdd\xfb\x3e\x05\x7c\xe2\x1d\x5e\xc6\xa7\xbc\x97\x4f\x68\x3a\xf5\xe9\x2e\x0a\x43\xb6\xaf\x57\x5c\x62\x68\x7c\xb7\xfd\xa3\x8a\x84\xa0\xac\x62\xbe\x2b\x09\x87\x34\xf0\x6a\x01\xbb\x9b\x29\x56\x3c\xfe\x00\x37\xcf\x23\x6c\xf1\x4e\xaa\xb6\x74\x46\x12\x6c\x91\xee\x34\xd5\xec\x9a\x91\xe7\x44\xbe\x90\x31\x72\xd5\x49\x02\xf6\x02\xe5\xf4\x1f\xeb\x7c\xd9\x96\x55\xa9\xff\xec\x8a\xf9\x99\x47\xff\x35\x5a\x02\xaa\x04\xcb\x8a\x5b\x87\x71\x29\x91\xbd\xa4\xb4\x7a\x0d\xbd\x9a\xf5\x57\x23\x00\x07\x21\x17\x3f\x4a\x39\xd1\x05\x49\x0b\xa7\xb6\x37\x81\xa5\x5d\x8c\xaa\x33\x5e\x81\x28\x7c\xa7\x7d\x27\xeb\x00\xae\x8d\x37", 0 }, + /* Anchor: 128 serverbasic.crt serial: #{a.serial.to_s} + C=ZA,ST=Western Cape,L=Cape Town,O=Thawte Consulting cc,OU=Certification Services Division,CN=Thawte Server CA,1.2.840.113549.1.9.1=#16177365727665722D6365727473407468617774652E636F6D + */ + { 791, "\x30\x82\x03\x13\x30\x82\x02\x7c\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x30\x81\xc4\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6f\x77\x6e\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x6f\x6e\x73\x75\x6c\x74\x69\x6e\x67\x20\x63\x63\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x54\x68\x61\x77\x74\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x41\x31\x26\x30\x24\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x17\x73\x65\x72\x76\x65\x72\x2d\x63\x65\x72\x74\x73\x40\x74\x68\x61\x77\x74\x65\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x39\x36\x30\x38\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x30\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xc4\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6f\x77\x6e\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x6f\x6e\x73\x75\x6c\x74\x69\x6e\x67\x20\x63\x63\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x54\x68\x61\x77\x74\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x41\x31\x26\x30\x24\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x17\x73\x65\x72\x76\x65\x72\x2d\x63\x65\x72\x74\x73\x40\x74\x68\x61\x77\x74\x65\x2e\x63\x6f\x6d\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd3\xa4\x50\x6e\xc8\xff\x56\x6b\xe6\xcf\x5d\xb6\xea\x0c\x68\x75\x47\xa2\xaa\xc2\xda\x84\x25\xfc\xa8\xf4\x47\x51\xda\x85\xb5\x20\x74\x94\x86\x1e\x0f\x75\xc9\xe9\x08\x61\xf5\x06\x6d\x30\x6e\x15\x19\x02\xe9\x52\xc0\x62\xdb\x4d\x99\x9e\xe2\x6a\x0c\x44\x38\xcd\xfe\xbe\xe3\x64\x09\x70\xc5\xfe\xb1\x6b\x29\xb6\x2f\x49\xc8\x3b\xd4\x27\x04\x25\x10\x97\x2f\xe7\x90\x6d\xc0\x28\x42\x99\xd7\x4c\x43\xde\xc3\xf5\x21\x6d\x54\x9f\x5d\xc3\x58\xe1\xc0\xe4\xd9\x5b\xb0\xb8\xdc\xb4\x7b\xdf\x36\x3a\xc2\xb5\x66\x22\x12\xd6\x87\x0d\x02\x03\x01\x00\x01\xa3\x13\x30\x11\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x03\x81\x81\x00\x07\xfa\x4c\x69\x5c\xfb\x95\xcc\x46\xee\x85\x83\x4d\x21\x30\x8e\xca\xd9\xa8\x6f\x49\x1a\xe6\xda\x51\xe3\x60\x70\x6c\x84\x61\x11\xa1\x1a\xc8\x48\x3e\x59\x43\x7d\x4f\x95\x3d\xa1\x8b\xb7\x0b\x62\x98\x7a\x75\x8a\xdd\x88\x4e\x4e\x9e\x40\xdb\xa8\xcc\x32\x74\xb9\x6f\x0d\xc6\xe3\xb3\x44\x0b\xd9\x8a\x6f\x9a\x29\x9b\x99\x18\x28\x3b\xd1\xe3\x40\x28\x9a\x5a\x3c\xd5\xb5\xe7\x20\x1b\x8b\xca\xa4\xab\x8d\xe9\x51\xd9\xe2\x4c\x2c\x59\xa9\xda\xb9\xb2\x75\x1b\xf6\x42\xf2\xef\xc7\xf2\x18\xf9\x89\xbc\xa3\xff\x8a\x23\x2e\x70\x47", 129 }, + /* Anchor: 129 Thawte_Server_CA.cer serial: #{a.serial.to_s} + C=ZA,ST=Western Cape,L=Cape Town,O=Thawte Consulting cc,OU=Certification Services Division,CN=Thawte Server CA,1.2.840.113549.1.9.1=#16177365727665722D6365727473407468617774652E636F6D + */ + { 806, "\x30\x82\x03\x22\x30\x82\x02\x8b\xa0\x03\x02\x01\x02\x02\x10\x34\xa4\xff\xf6\x30\xaf\x4c\xa5\x3c\x33\x17\x42\xa1\x94\x66\x75\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xc4\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6f\x77\x6e\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x6f\x6e\x73\x75\x6c\x74\x69\x6e\x67\x20\x63\x63\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x54\x68\x61\x77\x74\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x41\x31\x26\x30\x24\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x17\x73\x65\x72\x76\x65\x72\x2d\x63\x65\x72\x74\x73\x40\x74\x68\x61\x77\x74\x65\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x39\x36\x30\x38\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x31\x30\x31\x30\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xc4\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6f\x77\x6e\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x6f\x6e\x73\x75\x6c\x74\x69\x6e\x67\x20\x63\x63\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x54\x68\x61\x77\x74\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x41\x31\x26\x30\x24\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x17\x73\x65\x72\x76\x65\x72\x2d\x63\x65\x72\x74\x73\x40\x74\x68\x61\x77\x74\x65\x2e\x63\x6f\x6d\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd3\xa4\x50\x6e\xc8\xff\x56\x6b\xe6\xcf\x5d\xb6\xea\x0c\x68\x75\x47\xa2\xaa\xc2\xda\x84\x25\xfc\xa8\xf4\x47\x51\xda\x85\xb5\x20\x74\x94\x86\x1e\x0f\x75\xc9\xe9\x08\x61\xf5\x06\x6d\x30\x6e\x15\x19\x02\xe9\x52\xc0\x62\xdb\x4d\x99\x9e\xe2\x6a\x0c\x44\x38\xcd\xfe\xbe\xe3\x64\x09\x70\xc5\xfe\xb1\x6b\x29\xb6\x2f\x49\xc8\x3b\xd4\x27\x04\x25\x10\x97\x2f\xe7\x90\x6d\xc0\x28\x42\x99\xd7\x4c\x43\xde\xc3\xf5\x21\x6d\x54\x9f\x5d\xc3\x58\xe1\xc0\xe4\xd9\x5b\xb0\xb8\xdc\xb4\x7b\xdf\x36\x3a\xc2\xb5\x66\x22\x12\xd6\x87\x0d\x02\x03\x01\x00\x01\xa3\x13\x30\x11\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\xbe\x40\x69\x41\x6f\xc6\xdb\xc1\xa7\xbf\x07\xc0\x45\xe4\xd0\xb5\x43\x1e\x4c\x95\x33\x35\xe9\x5e\xc2\x3e\x28\xf6\xa8\x0d\x50\xd5\xff\xe2\x0c\x0f\xfc\x50\x02\x8e\xae\x91\xb9\xad\x34\x8a\x8d\x9f\x27\x71\xaa\x19\xcc\x4b\xe8\x04\xca\xd4\x17\x6b\x12\x1a\xd6\xc6\x5f\xd6\xcd\x5e\xff\x89\x76\xbf\xd8\x48\xd8\x59\xbd\x08\x8a\x89\x1d\x57\xcd\x45\x1e\x52\xba\x12\x9a\x84\xfa\x18\x89\x5f\xe8\xf9\x30\x35\x6a\x01\x60\xb9\x99\x80\x83\x85\x0a\x6e\xda\xf4\xc9\x8f\x5e\x73\x2d\x31\x4a\x63\xa0\x74\xf2\x1f\x8b\x22\xd2\x29\x3e\xeb", 0 }, + /* Anchor: 130 serverpremium.crt serial: #{a.serial.to_s} + C=ZA,ST=Western Cape,L=Cape Town,O=Thawte Consulting cc,OU=Certification Services Division,CN=Thawte Premium Server CA,1.2.840.113549.1.9.1=#16197072656D69756D2D736572766572407468617774652E636F6D + */ + { 811, "\x30\x82\x03\x27\x30\x82\x02\x90\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x30\x81\xce\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6f\x77\x6e\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x6f\x6e\x73\x75\x6c\x74\x69\x6e\x67\x20\x63\x63\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x54\x68\x61\x77\x74\x65\x20\x50\x72\x65\x6d\x69\x75\x6d\x20\x53\x65\x72\x76\x65\x72\x20\x43\x41\x31\x28\x30\x26\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x19\x70\x72\x65\x6d\x69\x75\x6d\x2d\x73\x65\x72\x76\x65\x72\x40\x74\x68\x61\x77\x74\x65\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x39\x36\x30\x38\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x30\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xce\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6f\x77\x6e\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x6f\x6e\x73\x75\x6c\x74\x69\x6e\x67\x20\x63\x63\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x54\x68\x61\x77\x74\x65\x20\x50\x72\x65\x6d\x69\x75\x6d\x20\x53\x65\x72\x76\x65\x72\x20\x43\x41\x31\x28\x30\x26\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x19\x70\x72\x65\x6d\x69\x75\x6d\x2d\x73\x65\x72\x76\x65\x72\x40\x74\x68\x61\x77\x74\x65\x2e\x63\x6f\x6d\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\x36\x36\x6a\x8b\xd7\xc2\x5b\x9e\xda\x81\x41\x62\x8f\x38\xee\x49\x04\x55\xd6\xd0\xef\x1c\x1b\x95\x16\x47\xef\x18\x48\x35\x3a\x52\xf4\x2b\x6a\x06\x8f\x3b\x2f\xea\x56\xe3\xaf\x86\x8d\x9e\x17\xf7\x9e\xb4\x65\x75\x02\x4d\xef\xcb\x09\xa2\x21\x51\xd8\x9b\xd0\x67\xd0\xba\x0d\x92\x06\x14\x73\xd4\x93\xcb\x97\x2a\x00\x9c\x5c\x4e\x0c\xbc\xfa\x15\x52\xfc\xf2\x44\x6e\xda\x11\x4a\x6e\x08\x9f\x2f\x2d\xe3\xf9\xaa\x3a\x86\x73\xb6\x46\x53\x58\xc8\x89\x05\xbd\x83\x11\xb8\x73\x3f\xaa\x07\x8d\xf4\x42\x4d\xe7\x40\x9d\x1c\x37\x02\x03\x01\x00\x01\xa3\x13\x30\x11\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x03\x81\x81\x00\x26\x48\x2c\x16\xc2\x58\xfa\xe8\x16\x74\x0c\xaa\xaa\x5f\x54\x3f\xf2\xd7\xc9\x78\x60\x5e\x5e\x6e\x37\x63\x22\x77\x36\x7e\xb2\x17\xc4\x34\xb9\xf5\x08\x85\xfc\xc9\x01\x38\xff\x4d\xbe\xf2\x16\x42\x43\xe7\xbb\x5a\x46\xfb\xc1\xc6\x11\x1f\xf1\x4a\xb0\x28\x46\xc9\xc3\xc4\x42\x7d\xbc\xfa\xab\x59\x6e\xd5\xb7\x51\x88\x11\xe3\xa4\x85\x19\x6b\x82\x4c\xa4\x0c\x12\xad\xe9\xa4\xae\x3f\xf1\xc3\x49\x65\x9a\x8c\xc5\xc8\x3e\x25\xb7\x94\x99\xbb\x92\x32\x71\x07\xf0\x86\x5e\xed\x50\x27\xa6\x0d\xa6\x23\xf9\xbb\xcb\xa6\x07\x14\x42", 131 }, + /* Anchor: 131 Thawte_Premium_Server_CA.cer serial: #{a.serial.to_s} + C=ZA,ST=Western Cape,L=Cape Town,O=Thawte Consulting cc,OU=Certification Services Division,CN=Thawte Premium Server CA,1.2.840.113549.1.9.1=#16197072656D69756D2D736572766572407468617774652E636F6D + */ + { 826, "\x30\x82\x03\x36\x30\x82\x02\x9f\xa0\x03\x02\x01\x02\x02\x10\x36\x12\x22\x96\xc5\xe3\x38\xa5\x20\xa1\xd2\x5f\x4c\xd7\x09\x54\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xce\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6f\x77\x6e\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x6f\x6e\x73\x75\x6c\x74\x69\x6e\x67\x20\x63\x63\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x54\x68\x61\x77\x74\x65\x20\x50\x72\x65\x6d\x69\x75\x6d\x20\x53\x65\x72\x76\x65\x72\x20\x43\x41\x31\x28\x30\x26\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x19\x70\x72\x65\x6d\x69\x75\x6d\x2d\x73\x65\x72\x76\x65\x72\x40\x74\x68\x61\x77\x74\x65\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x39\x36\x30\x38\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x31\x30\x31\x30\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xce\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6f\x77\x6e\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x6f\x6e\x73\x75\x6c\x74\x69\x6e\x67\x20\x63\x63\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x54\x68\x61\x77\x74\x65\x20\x50\x72\x65\x6d\x69\x75\x6d\x20\x53\x65\x72\x76\x65\x72\x20\x43\x41\x31\x28\x30\x26\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x19\x70\x72\x65\x6d\x69\x75\x6d\x2d\x73\x65\x72\x76\x65\x72\x40\x74\x68\x61\x77\x74\x65\x2e\x63\x6f\x6d\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\x36\x36\x6a\x8b\xd7\xc2\x5b\x9e\xda\x81\x41\x62\x8f\x38\xee\x49\x04\x55\xd6\xd0\xef\x1c\x1b\x95\x16\x47\xef\x18\x48\x35\x3a\x52\xf4\x2b\x6a\x06\x8f\x3b\x2f\xea\x56\xe3\xaf\x86\x8d\x9e\x17\xf7\x9e\xb4\x65\x75\x02\x4d\xef\xcb\x09\xa2\x21\x51\xd8\x9b\xd0\x67\xd0\xba\x0d\x92\x06\x14\x73\xd4\x93\xcb\x97\x2a\x00\x9c\x5c\x4e\x0c\xbc\xfa\x15\x52\xfc\xf2\x44\x6e\xda\x11\x4a\x6e\x08\x9f\x2f\x2d\xe3\xf9\xaa\x3a\x86\x73\xb6\x46\x53\x58\xc8\x89\x05\xbd\x83\x11\xb8\x73\x3f\xaa\x07\x8d\xf4\x42\x4d\xe7\x40\x9d\x1c\x37\x02\x03\x01\x00\x01\xa3\x13\x30\x11\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x65\x90\xac\x88\x0f\x56\xd9\xe6\x30\x34\xd4\x26\xc7\xd0\x50\xf1\x92\xde\x6b\xd4\x39\x88\x09\x22\xc6\xa6\x63\x83\x03\xf7\x99\x77\xd8\xb2\xe5\x18\xb8\x5d\x63\xf3\xd4\x73\xfb\x6c\x9c\x99\x78\xf1\x4b\x78\x7d\x19\x24\xc3\x2b\x02\x84\xf8\xbc\x22\xd9\x8a\x22\xd7\xa0\xfc\x71\xec\x91\x87\x20\xf1\xb8\xec\xb1\xe5\x55\x80\xac\x3d\x52\xc8\x39\x0e\xc2\xf0\xc0\x05\x4f\xd6\x82\x75\x8c\xbd\x5f\xd2\xdc\x76\x9a\x05\x12\xc9\xaf\x72\xc3\xdc\x25\x7e\xa4\x4d\x8e\x17\xa5\xe0\x87\x7f\xe1\x9a\x5a\xe1\x60\xdc\x64\x23\x3c\x42\x2e\x4d", 0 }, + /* Anchor: 132 SF-Class2-root.crt serial: #{a.serial.to_s} + C=US,O=Starfield Technologies\, Inc.,OU=Starfield Class 2 Certification Authority + */ + { 1043, "\x30\x82\x04\x0f\x30\x82\x02\xf7\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x68\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x25\x30\x23\x06\x03\x55\x04\x0a\x13\x1c\x53\x74\x61\x72\x66\x69\x65\x6c\x64\x20\x54\x65\x63\x68\x6e\x6f\x6c\x6f\x67\x69\x65\x73\x2c\x20\x49\x6e\x63\x2e\x31\x32\x30\x30\x06\x03\x55\x04\x0b\x13\x29\x53\x74\x61\x72\x66\x69\x65\x6c\x64\x20\x43\x6c\x61\x73\x73\x20\x32\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x30\x34\x30\x36\x32\x39\x31\x37\x33\x39\x31\x36\x5a\x17\x0d\x33\x34\x30\x36\x32\x39\x31\x37\x33\x39\x31\x36\x5a\x30\x68\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x25\x30\x23\x06\x03\x55\x04\x0a\x13\x1c\x53\x74\x61\x72\x66\x69\x65\x6c\x64\x20\x54\x65\x63\x68\x6e\x6f\x6c\x6f\x67\x69\x65\x73\x2c\x20\x49\x6e\x63\x2e\x31\x32\x30\x30\x06\x03\x55\x04\x0b\x13\x29\x53\x74\x61\x72\x66\x69\x65\x6c\x64\x20\x43\x6c\x61\x73\x73\x20\x32\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x82\x01\x20\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0d\x00\x30\x82\x01\x08\x02\x82\x01\x01\x00\xb7\x32\xc8\xfe\xe9\x71\xa6\x04\x85\xad\x0c\x11\x64\xdf\xce\x4d\xef\xc8\x03\x18\x87\x3f\xa1\xab\xfb\x3c\xa6\x9f\xf0\xc3\xa1\xda\xd4\xd8\x6e\x2b\x53\x90\xfb\x24\xa4\x3e\x84\xf0\x9e\xe8\x5f\xec\xe5\x27\x44\xf5\x28\xa6\x3f\x7b\xde\xe0\x2a\xf0\xc8\xaf\x53\x2f\x9e\xca\x05\x01\x93\x1e\x8f\x66\x1c\x39\xa7\x4d\xfa\x5a\xb6\x73\x04\x25\x66\xeb\x77\x7f\xe7\x59\xc6\x4a\x99\x25\x14\x54\xeb\x26\xc7\xf3\x7f\x19\xd5\x30\x70\x8f\xaf\xb0\x46\x2a\xff\xad\xeb\x29\xed\xd7\x9f\xaa\x04\x87\xa3\xd4\xf9\x89\xa5\x34\x5f\xdb\x43\x91\x82\x36\xd9\x66\x3c\xb1\xb8\xb9\x82\xfd\x9c\x3a\x3e\x10\xc8\x3b\xef\x06\x65\x66\x7a\x9b\x19\x18\x3d\xff\x71\x51\x3c\x30\x2e\x5f\xbe\x3d\x77\x73\xb2\x5d\x06\x6c\xc3\x23\x56\x9a\x2b\x85\x26\x92\x1c\xa7\x02\xb3\xe4\x3f\x0d\xaf\x08\x79\x82\xb8\x36\x3d\xea\x9c\xd3\x35\xb3\xbc\x69\xca\xf5\xcc\x9d\xe8\xfd\x64\x8d\x17\x80\x33\x6e\x5e\x4a\x5d\x99\xc9\x1e\x87\xb4\x9d\x1a\xc0\xd5\x6e\x13\x35\x23\x5e\xdf\x9b\x5f\x3d\xef\xd6\xf7\x76\xc2\xea\x3e\xbb\x78\x0d\x1c\x42\x67\x6b\x04\xd8\xf8\xd6\xda\x6f\x8b\xf2\x44\xa0\x01\xab\x02\x01\x03\xa3\x81\xc5\x30\x81\xc2\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xbf\x5f\xb7\xd1\xce\xdd\x1f\x86\xf4\x5b\x55\xac\xdc\xd7\x10\xc2\x0e\xa9\x88\xe7\x30\x81\x92\x06\x03\x55\x1d\x23\x04\x81\x8a\x30\x81\x87\x80\x14\xbf\x5f\xb7\xd1\xce\xdd\x1f\x86\xf4\x5b\x55\xac\xdc\xd7\x10\xc2\x0e\xa9\x88\xe7\xa1\x6c\xa4\x6a\x30\x68\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x25\x30\x23\x06\x03\x55\x04\x0a\x13\x1c\x53\x74\x61\x72\x66\x69\x65\x6c\x64\x20\x54\x65\x63\x68\x6e\x6f\x6c\x6f\x67\x69\x65\x73\x2c\x20\x49\x6e\x63\x2e\x31\x32\x30\x30\x06\x03\x55\x04\x0b\x13\x29\x53\x74\x61\x72\x66\x69\x65\x6c\x64\x20\x43\x6c\x61\x73\x73\x20\x32\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x82\x01\x00\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x05\x9d\x3f\x88\x9d\xd1\xc9\x1a\x55\xa1\xac\x69\xf3\xf3\x59\xda\x9b\x01\x87\x1a\x4f\x57\xa9\xa1\x79\x09\x2a\xdb\xf7\x2f\xb2\x1e\xcc\xc7\x5e\x6a\xd8\x83\x87\xa1\x97\xef\x49\x35\x3e\x77\x06\x41\x58\x62\xbf\x8e\x58\xb8\x0a\x67\x3f\xec\xb3\xdd\x21\x66\x1f\xc9\x54\xfa\x72\xcc\x3d\x4c\x40\xd8\x81\xaf\x77\x9e\x83\x7a\xbb\xa2\xc7\xf5\x34\x17\x8e\xd9\x11\x40\xf4\xfc\x2c\x2a\x4d\x15\x7f\xa7\x62\x5d\x2e\x25\xd3\x00\x0b\x20\x1a\x1d\x68\xf9\x17\xb8\xf4\xbd\x8b\xed\x28\x59\xdd\x4d\x16\x8b\x17\x83\xc8\xb2\x65\xc7\x2d\x7a\xa5\xaa\xbc\x53\x86\x6d\xdd\x57\xa4\xca\xf8\x20\x41\x0b\x68\xf0\xf4\xfb\x74\xbe\x56\x5d\x7a\x79\xf5\xf9\x1d\x85\xe3\x2d\x95\xbe\xf5\x71\x90\x43\xcc\x8d\x1f\x9a\x00\x0a\x87\x29\xe9\x55\x22\x58\x00\x23\xea\xe3\x12\x43\x29\x5b\x47\x08\xdd\x8c\x41\x6a\x65\x06\xa8\xe5\x21\xaa\x41\xb4\x95\x21\x95\xb9\x7d\xd1\x34\xab\x13\xd6\xad\xbc\xdc\xe2\x3d\x39\xcd\xbd\x3e\x75\x70\xa1\x18\x59\x03\xc9\x22\xb4\x8f\x9c\xd5\x5e\x2a\xd7\xa5\xb6\xd4\x0a\x6d\xf8\xb7\x40\x11\x46\x9a\x1f\x79\x0e\x62\xbf\x0f\x97\xec\xe0\x2f\x1f\x17\x94", 0 }, + /* Anchor: 133 SoneraClass1.crt serial: #{a.serial.to_s} + C=FI,O=Sonera,CN=Sonera Class1 CA + */ + { 804, "\x30\x82\x03\x20\x30\x82\x02\x08\xa0\x03\x02\x01\x02\x02\x01\x24\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x39\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x49\x31\x0f\x30\x0d\x06\x03\x55\x04\x0a\x13\x06\x53\x6f\x6e\x65\x72\x61\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x53\x6f\x6e\x65\x72\x61\x20\x43\x6c\x61\x73\x73\x31\x20\x43\x41\x30\x1e\x17\x0d\x30\x31\x30\x34\x30\x36\x31\x30\x34\x39\x31\x33\x5a\x17\x0d\x32\x31\x30\x34\x30\x36\x31\x30\x34\x39\x31\x33\x5a\x30\x39\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x49\x31\x0f\x30\x0d\x06\x03\x55\x04\x0a\x13\x06\x53\x6f\x6e\x65\x72\x61\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x53\x6f\x6e\x65\x72\x61\x20\x43\x6c\x61\x73\x73\x31\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xb5\x89\x1f\x2b\x4f\x67\x0a\x79\xff\xc5\x1e\xf8\x7f\x3c\xed\xd1\x7e\xda\xb0\xcd\x6d\x2f\x36\xac\x34\xc6\xdb\xd9\x64\x17\x08\x63\x30\x33\x22\x8a\x4c\xee\x8e\xbb\x0f\x0d\x42\x55\xc9\x9d\x2e\xa5\xef\xf7\xa7\x8c\xc3\xab\xb9\x97\xcb\x8e\xef\x3f\x15\x67\xa8\x82\x72\x63\x53\x0f\x41\x8c\x7d\x10\x95\x24\xa1\x5a\xa5\x06\xfa\x92\x57\x9d\xfa\xa5\x01\xf2\x75\xe9\x1f\xbc\x56\x26\x52\x4e\x78\x19\x65\x58\x55\x03\x58\xc0\x14\xae\x8c\x7c\x55\x5f\x70\x5b\x77\x23\x06\x36\x97\xf3\x24\xb5\x9a\x46\x95\xe4\xdf\x0d\x0b\x05\x45\xe5\xd1\xf2\x1d\x82\xbb\xc6\x13\xe0\xfe\xaa\x7a\xfd\x69\x30\x94\xf3\xd2\x45\x85\xfc\xf2\x32\x5b\x32\xde\xe8\x6c\x5d\x1f\xcb\xa4\x22\x74\xb0\x80\x8e\x5d\x94\xf7\x06\x00\x4b\xa9\xd4\x5e\x2e\x35\x50\x09\xf3\x80\x97\xf4\x0c\x17\xae\x39\xd8\x5f\xcd\x33\xc1\x1c\xca\x89\xc2\x22\xf7\x45\x12\xed\x5e\x12\x93\x9d\x63\xab\x82\x2e\xb9\xeb\x42\x41\x44\xcb\x4a\x1a\x00\x82\x0d\x9e\xf9\x8b\x57\x3e\x4c\xc7\x17\xed\x2c\x8b\x72\x33\x5f\x72\x7a\x38\x56\xd5\xe6\xd9\xae\x05\x1a\x1d\x75\x45\xb1\xcb\xa5\x25\x1c\x12\x57\x36\xfd\x22\x37\x02\x03\x01\x00\x01\xa3\x33\x30\x31\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x11\x06\x03\x55\x1d\x0e\x04\x0a\x04\x08\x47\xe2\x0c\x8b\xf6\x53\x88\x52\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x06\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x8b\x1a\xb2\xc9\x5d\x61\xb4\xe1\xb9\x2b\xb9\x53\xd1\xb2\x85\x9d\x77\x8e\x16\xee\x11\x3d\xdb\xc2\x63\xd9\x5b\x97\x65\xfb\x12\x67\xd8\x2a\x5c\xb6\xab\xe5\x5e\xc3\xb7\x16\x2f\xc8\xe8\xab\x1d\x8a\xfd\xab\x1a\x7c\xd5\x5f\x63\xcf\xdc\xb0\xdd\x77\xb9\xa8\xe6\xd2\x22\x38\x87\x07\x14\xd9\xff\xbe\x56\xb5\xfd\x07\x0e\x3c\x55\xca\x16\xcc\xa7\xa6\x77\x37\xfb\xdb\x5c\x1f\x4e\x59\x06\x87\xa3\x03\x43\xf5\x16\xab\xb7\x84\xbd\x4e\xef\x9f\x31\x37\xf0\x46\xf1\x40\xb6\xd1\x0c\xa5\x64\xf8\x63\x5e\x21\xdb\x55\x4e\x4f\x31\x76\x9c\x10\x61\x8e\xb6\x53\x3a\xa3\x11\xbe\xaf\x6d\x7c\x1e\xbd\xae\x2d\xe2\x0c\x69\xc7\x85\x53\x68\xa2\x61\xba\xc5\x3e\xb4\x79\x54\x78\x9e\x0a\xc7\x02\xbe\x62\xd1\x11\x82\x4b\x65\x2f\x91\x5a\xc2\xa8\x87\xb1\x56\x68\x94\x79\xf9\x25\xf7\xc1\xd5\xae\x1a\xb8\xbb\x3d\x8f\xa9\x8a\x38\x15\xf7\x73\xd0\x5a\x60\xd1\x80\xb0\xf0\xdc\xd5\x50\xcd\x4e\xee\x92\x48\x69\xed\xb2\x23\x1e\x30\xcc\xc8\x94\xc8\xb6\xf5\x3b\x86\x7f\x3f\xa6\x2e\x9f\xf6\x3e\x2c\xb5\x92\x96\x3e\xdf\x2c\x93\x8a\xff\x81\x8c\x0f\x0f\x59\x21\x19\x57\xbd\x55\x9a", 0 }, + /* Anchor: 134 SoneraClass2.crt serial: #{a.serial.to_s} + C=FI,O=Sonera,CN=Sonera Class2 CA + */ + { 804, "\x30\x82\x03\x20\x30\x82\x02\x08\xa0\x03\x02\x01\x02\x02\x01\x1d\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x39\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x49\x31\x0f\x30\x0d\x06\x03\x55\x04\x0a\x13\x06\x53\x6f\x6e\x65\x72\x61\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x53\x6f\x6e\x65\x72\x61\x20\x43\x6c\x61\x73\x73\x32\x20\x43\x41\x30\x1e\x17\x0d\x30\x31\x30\x34\x30\x36\x30\x37\x32\x39\x34\x30\x5a\x17\x0d\x32\x31\x30\x34\x30\x36\x30\x37\x32\x39\x34\x30\x5a\x30\x39\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x49\x31\x0f\x30\x0d\x06\x03\x55\x04\x0a\x13\x06\x53\x6f\x6e\x65\x72\x61\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x53\x6f\x6e\x65\x72\x61\x20\x43\x6c\x61\x73\x73\x32\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\x90\x17\x4a\x35\x9d\xca\xf0\x0d\x96\xc7\x44\xfa\x16\x37\xfc\x48\xbd\xbd\x7f\x80\x2d\x35\x3b\xe1\x6f\xa8\x67\xa9\xbf\x03\x1c\x4d\x8c\x6f\x32\x47\xd5\x41\x68\xa4\x13\x04\xc1\x35\x0c\x9a\x84\x43\xfc\x5c\x1d\xff\x89\xb3\xe8\x17\x18\xcd\x91\x5f\xfb\x89\xe3\xea\xbf\x4e\x5d\x7c\x1b\x26\xd3\x75\x79\xed\xe6\x84\xe3\x57\xe5\xad\x29\xc4\xf4\x3a\x28\xe7\xa5\x7b\x84\x36\x69\xb3\xfd\x5e\x76\xbd\xa3\x2d\x99\xd3\x90\x4e\x23\x28\x7d\x18\x63\xf1\x54\x3b\x26\x9d\x76\x5b\x97\x42\xb2\xff\xae\xf0\x4e\xec\xdd\x39\x95\x4e\x83\x06\x7f\xe7\x49\x40\xc8\xc5\x01\xb2\x54\x5a\x66\x1d\x3d\xfc\xf9\xe9\x3c\x0a\x9e\x81\xb8\x70\xf0\x01\x8b\xe4\x23\x54\x7c\xc8\xae\xf8\x90\x1e\x00\x96\x72\xd4\x54\xcf\x61\x23\xbc\xea\xfb\x9d\x02\x95\xd1\xb6\xb9\x71\x3a\x69\x08\x3f\x0f\xb4\xe1\x42\xc7\x88\xf5\x3f\x98\xa8\xa7\xba\x1c\xe0\x71\x71\xef\x58\x57\x81\x50\x7a\x5c\x6b\x74\x46\x0e\x83\x03\x98\xc3\x8e\xa8\x6e\xf2\x76\x32\x6e\x27\x83\xc2\x73\xf3\xdc\x18\xe8\xb4\x93\xea\x75\x44\x6b\x04\x60\x20\x71\x57\x87\x9d\xf3\xbe\xa0\x90\x23\x3d\x8a\x24\xe1\xda\x21\xdb\xc3\x02\x03\x01\x00\x01\xa3\x33\x30\x31\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x11\x06\x03\x55\x1d\x0e\x04\x0a\x04\x08\x4a\xa0\xaa\x58\x84\xd3\x5e\x3c\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x06\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x5a\xce\x87\xf9\x16\x72\x15\x57\x4b\x1d\xd9\x9b\xe7\xa2\x26\x30\xec\x93\x67\xdf\xd6\x2d\xd2\x34\xaf\xf7\x38\xa5\xce\xab\x16\xb9\xab\x2f\x7c\x35\xcb\xac\xd0\x0f\xb4\x4c\x2b\xfc\x80\xef\x6b\x8c\x91\x5f\x36\x76\xf7\xdb\xb3\x1b\x19\xea\xf4\xb2\x11\xfd\x61\x71\x44\xbf\x28\xb3\x3a\x1d\xbf\xb3\x43\xe8\x9f\xbf\xdc\x31\x08\x71\xb0\x9d\x8d\xd6\x34\x47\x32\x90\xc6\x65\x24\xf7\xa0\x4a\x7c\x04\x73\x8f\x39\x6f\x17\x8c\x72\xb5\xbd\x4b\xc8\x7a\xf8\x7b\x83\xc3\x28\x4e\x9c\x09\xea\x67\x3f\xb2\x67\x04\x1b\xc3\x14\xda\xf8\xe7\x49\x24\x91\xd0\x1d\x6a\xfa\x61\x39\xef\x6b\xe7\x21\x75\x06\x07\xd8\x12\xb4\x21\x20\x70\x42\x71\x81\xda\x3c\x9a\x36\xbe\xa6\x5b\x0d\x6a\x6c\x9a\x1f\x91\x7b\xf9\xf9\xef\x42\xba\x4e\x4e\x9e\xcc\x0c\x8d\x94\xdc\xd9\x45\x9c\x5e\xec\x42\x50\x63\xae\xf4\x5d\xc4\xb1\x12\xdc\xca\x3b\xa8\x2e\x9d\x14\x5a\x05\x75\xb7\xec\xd7\x63\xe2\xba\x35\xb6\x04\x08\x91\xe8\xda\x9d\x9c\xf6\x66\xb5\x18\xac\x0a\xa6\x54\x26\x34\x33\xd2\x1b\xc1\xd4\x7f\x1a\x3a\x8e\x0b\xaa\x32\x6e\xdb\xfc\x4f\x25\x9f\xd9\x32\xc7\x96\x5a\x70\xac\xdf\x4c", 0 }, + /* Anchor: 135 staatDerNederlandenRootCA-G2.crt serial: #{a.serial.to_s} + C=NL,O=Staat der Nederlanden,CN=Staat der Nederlanden Root CA - G2 + */ + { 1486, "\x30\x82\x05\xca\x30\x82\x03\xb2\xa0\x03\x02\x01\x02\x02\x04\x00\x98\x96\x8c\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x30\x5a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4e\x4c\x31\x1e\x30\x1c\x06\x03\x55\x04\x0a\x0c\x15\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4e\x65\x64\x65\x72\x6c\x61\x6e\x64\x65\x6e\x31\x2b\x30\x29\x06\x03\x55\x04\x03\x0c\x22\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4e\x65\x64\x65\x72\x6c\x61\x6e\x64\x65\x6e\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x2d\x20\x47\x32\x30\x1e\x17\x0d\x30\x38\x30\x33\x32\x36\x31\x31\x31\x38\x31\x37\x5a\x17\x0d\x32\x30\x30\x33\x32\x35\x31\x31\x30\x33\x31\x30\x5a\x30\x5a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4e\x4c\x31\x1e\x30\x1c\x06\x03\x55\x04\x0a\x0c\x15\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4e\x65\x64\x65\x72\x6c\x61\x6e\x64\x65\x6e\x31\x2b\x30\x29\x06\x03\x55\x04\x03\x0c\x22\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4e\x65\x64\x65\x72\x6c\x61\x6e\x64\x65\x6e\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x2d\x20\x47\x32\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\xc5\x59\xe7\x6f\x75\xaa\x3e\x4b\x9c\xb5\xb8\xac\x9e\x0b\xe4\xf9\xd9\xca\xab\x5d\x8f\xb5\x39\x10\x82\xd7\xaf\x51\xe0\x3b\xe1\x00\x48\x6a\xcf\xda\xe1\x06\x43\x11\x99\xaa\x14\x25\x12\xad\x22\xe8\x00\x6d\x43\xc4\xa9\xb8\xe5\x1f\x89\x4b\x67\xbd\x61\x48\xef\xfd\xd2\xe0\x60\x88\xe5\xb9\x18\x60\x28\xc3\x77\x2b\xad\xb0\x37\xaa\x37\xde\x64\x59\x2a\x46\x57\xe4\x4b\xb9\xf8\x37\x7c\xd5\x36\xe7\x80\xc1\xb6\xf3\xd4\x67\x9b\x96\xe8\xce\xd7\xc6\x0a\x53\xd0\x6b\x49\x96\xf3\xa3\x0b\x05\x77\x48\xf7\x25\xe5\x70\xac\x30\x14\x20\x25\xe3\x7f\x75\x5a\xe5\x48\xf8\x4e\x7b\x03\x07\x04\xfa\x82\x61\x87\x6e\xf0\x3b\xc4\xa4\xc7\xd0\xf5\x74\x3e\xa5\x5d\x1a\x08\xf2\x9b\x25\xd2\xf6\xac\x04\x26\x3e\x55\x3a\x62\x28\xa5\x7b\xb2\x30\xaf\xf8\x37\xc2\xd1\xba\xd6\x38\xfd\xf4\xef\x49\x30\x37\x99\x26\x21\x48\x85\x01\xa9\xe5\x16\xe7\xdc\x90\x55\xdf\x0f\xe8\x38\xcd\x99\x37\x21\x4f\x5d\xf5\x22\x6f\x6a\xc5\x12\x16\x60\x17\x55\xf2\x65\x66\xa6\xa7\x30\x91\x38\xc1\x38\x1d\x86\x04\x84\xba\x1a\x25\x78\x5e\x9d\xaf\xcc\x50\x60\xd6\x13\x87\x52\xed\x63\x1f\x6d\x65\x7d\xc2\x15\x18\x74\xca\xe1\x7e\x64\x29\x8c\x72\xd8\x16\x13\x7d\x0b\x49\x4a\xf1\x28\x1b\x20\x74\x6b\xc5\x3d\xdd\xb0\xaa\x48\x09\x3d\x2e\x82\x94\xcd\x1a\x65\xd9\x2b\x88\x9a\x99\xbc\x18\x7e\x9f\xee\x7d\x66\x7c\x3e\xbd\x94\xb8\x81\xce\xcd\x98\x30\x78\xc1\x6f\x67\xd0\xbe\x5f\xe0\x68\xed\xde\xe2\xb1\xc9\x2c\x59\x78\x92\xaa\xdf\x2b\x60\x63\xf2\xe5\x5e\xb9\xe3\xca\xfa\x7f\x50\x86\x3e\xa2\x34\x18\x0c\x09\x68\x28\x11\x1c\xe4\xe1\xb9\x5c\x3e\x47\xba\x32\x3f\x18\xcc\x5b\x84\xf5\xf3\x6b\x74\xc4\x72\x74\xe1\xe3\x8b\xa0\x4a\xbd\x8d\x66\x2f\xea\xad\x35\xda\x20\xd3\x88\x82\x61\xf0\x12\x22\xb6\xbc\xd0\xd5\xa4\xec\xaf\x54\x88\x25\x24\x3c\xa7\x6d\xb1\x72\x29\x3f\x3e\x57\xa6\x7f\x55\xaf\x6e\x26\xc6\xfe\xe7\xcc\x40\x5c\x51\x44\x81\x0a\x78\xde\x4a\xce\x55\xbf\x1d\xd5\xd9\xb7\x56\xef\xf0\x76\xff\x0b\x79\xb5\xaf\xbd\xfb\xa9\x69\x91\x46\x97\x68\x80\x14\x36\x1d\xb3\x7f\xbb\x29\x98\x36\xa5\x20\xfa\x82\x60\x62\x33\xa4\xec\xd6\xba\x07\xa7\x6e\xc5\xcf\x14\xa6\xe7\xd6\x92\x34\xd8\x81\xf5\xfc\x1d\x5d\xaa\x5c\x1e\xf6\xa3\x4d\x3b\xb8\xf7\x39\x02\x03\x01\x00\x01\xa3\x81\x97\x30\x81\x94\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x52\x06\x03\x55\x1d\x20\x04\x4b\x30\x49\x30\x47\x06\x04\x55\x1d\x20\x00\x30\x3f\x30\x3d\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x31\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x70\x6b\x69\x6f\x76\x65\x72\x68\x65\x69\x64\x2e\x6e\x6c\x2f\x70\x6f\x6c\x69\x63\x69\x65\x73\x2f\x72\x6f\x6f\x74\x2d\x70\x6f\x6c\x69\x63\x79\x2d\x47\x32\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x91\x68\x32\x87\x15\x1d\x89\xe2\xb5\xf1\xac\x36\x28\x34\x8d\x0b\x7c\x62\x88\xeb\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x03\x82\x02\x01\x00\xa8\x41\x4a\x67\x2a\x92\x81\x82\x50\x6e\xe1\xd7\xd8\xb3\x39\x3b\xf3\x02\x15\x09\x50\x51\xef\x2d\xbd\x24\x7b\x88\x86\x3b\xf9\xb4\xbc\x92\x09\x96\xb9\xf6\xc0\xab\x23\x60\x06\x79\x8c\x11\x4e\x51\xd2\x79\x80\x33\xfb\x9d\x48\xbe\xec\x41\x43\x81\x1f\x7e\x47\x40\x1c\xe5\x7a\x08\xca\xaa\x8b\x75\xad\x14\xc4\xc2\xe8\x66\x3c\x82\x07\xa7\xe6\x27\x82\x5b\x18\xe6\x0f\x6e\xd9\x50\x3e\x8a\x42\x18\x29\xc6\xb4\x56\xfc\x56\x10\xa0\x05\x17\xbd\x0c\x23\x7f\xf4\x93\xed\x9c\x1a\x51\xbe\xdd\x45\x41\xbf\x91\x24\xb4\x1f\x8c\xe9\x5f\xcf\x7b\x21\x99\x9f\x95\x9f\x39\x3a\x46\x1c\x6c\xf9\xcd\x7b\x9c\x90\xcd\x28\xa9\xc7\xa9\x55\xbb\xac\x62\x34\x62\x35\x13\x4b\x14\x3a\x55\x83\xb9\x86\x8d\x92\xa6\xc6\xf4\x07\x25\x54\xcc\x16\x57\x12\x4a\x82\x78\xc8\x14\xd9\x17\x82\x26\x2d\x5d\x20\x1f\x79\xae\xfe\xd4\x70\x16\x16\x95\x83\xd8\x35\x39\xff\x52\x5d\x75\x1c\x16\xc5\x13\x55\xcf\x47\xcc\x75\x65\x52\x4a\xde\xf0\xb0\xa7\xe4\x0a\x96\x0b\xfb\xad\xc2\xe2\x25\x84\xb2\xdd\xe4\xbd\x7e\x59\x6c\x9b\xf0\xf0\xd8\xe7\xca\xf2\xe9\x97\x38\x7e\x89\xbe\xcc\xfb\x39\x17\x61\x3f\x72\xdb\x3a\x91\xd8\x65\x01\x19\x1d\xad\x50\xa4\x57\x0a\x7c\x4b\xbc\x9c\x71\x73\x2a\x45\x51\x19\x85\xcc\x8e\xfd\x47\xa7\x74\x95\x1d\xa8\xd1\xaf\x4e\x17\xb1\x69\x26\xc2\xaa\x78\x57\x5b\xc5\x4d\xa7\xe5\x9e\x05\x17\x94\xca\xb2\x5f\xa0\x49\x18\x8d\x34\xe9\x26\x6c\x48\x1e\xaa\x68\x92\x05\xe1\x82\x73\x5a\x9b\xdc\x07\x5b\x08\x6d\x7d\x9d\xd7\x8d\x21\xd9\xfc\x14\x20\xaa\xc2\x45\xdf\x3f\xe7\x00\xb2\x51\xe4\xc2\xf8\x05\xb9\x79\x1a\x8c\x34\xf3\x9e\x5b\xe4\x37\x5b\x6b\x4a\xdf\x2c\x57\x8a\x40\x5a\x36\xba\xdd\x75\x44\x08\x37\x42\x70\x0c\xfe\xdc\x5e\x21\xa0\xa3\x8a\xc0\x90\x9c\x68\xda\x50\xe6\x45\x10\x47\x78\xb6\x4e\xd2\x65\xc9\xc3\x37\xdf\xe1\x42\x63\xb0\x57\x37\x45\x2d\x7b\x8a\x9c\xbf\x05\xea\x65\x55\x33\xf7\x39\x10\xc5\x28\x2a\x21\x7a\x1b\x8a\xc4\x24\xf9\x3f\x15\xc8\x9a\x15\x20\xf5\x55\x62\x96\xed\x6d\x93\x50\xbc\xe4\xaa\x78\xad\xd9\xcb\x0a\x65\x87\xa6\x66\xc1\xc4\x81\xa3\x77\x3a\x58\x1e\x0b\xee\x83\x8b\x9d\x1e\xd2\x52\xa4\xcc\x1d\x6f\xb0\x98\x6d\x94\x31\xb5\xf8\x71\x0a\xdc\xb9\xfc\x7d\x32\x60\xe6\xeb\xaf\x8a\x01", 0 }, + /* Anchor: 136 staatdernederlandenrootca.cer serial: #{a.serial.to_s} + C=NL,O=Staat der Nederlanden,CN=Staat der Nederlanden Root CA + */ + { 958, "\x30\x82\x03\xba\x30\x82\x02\xa2\xa0\x03\x02\x01\x02\x02\x04\x00\x98\x96\x8a\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x55\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4e\x4c\x31\x1e\x30\x1c\x06\x03\x55\x04\x0a\x13\x15\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4e\x65\x64\x65\x72\x6c\x61\x6e\x64\x65\x6e\x31\x26\x30\x24\x06\x03\x55\x04\x03\x13\x1d\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4e\x65\x64\x65\x72\x6c\x61\x6e\x64\x65\x6e\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x1e\x17\x0d\x30\x32\x31\x32\x31\x37\x30\x39\x32\x33\x34\x39\x5a\x17\x0d\x31\x35\x31\x32\x31\x36\x30\x39\x31\x35\x33\x38\x5a\x30\x55\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4e\x4c\x31\x1e\x30\x1c\x06\x03\x55\x04\x0a\x13\x15\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4e\x65\x64\x65\x72\x6c\x61\x6e\x64\x65\x6e\x31\x26\x30\x24\x06\x03\x55\x04\x03\x13\x1d\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4e\x65\x64\x65\x72\x6c\x61\x6e\x64\x65\x6e\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\x98\xd2\xb5\x51\x11\x7a\x81\xa6\x14\x98\x71\x6d\xbe\xcc\xe7\x13\x1b\xd6\x27\x0e\x7a\xb3\x6a\x18\x1c\xb6\x61\x5a\xd5\x61\x09\xbf\xde\x90\x13\xc7\x67\xee\xdd\xf3\xda\xc5\x0c\x12\x9e\x35\x55\x3e\x2c\x27\x88\x40\x6b\xf7\xdc\xdd\x22\x61\xf5\xc2\xc7\x0e\xf5\xf6\xd5\x76\x53\x4d\x8f\x8c\xbc\x18\x76\x37\x85\x9d\xe8\xca\x49\xc7\xd2\x4f\x98\x13\x09\xa2\x3e\x22\x88\x9c\x7f\xd6\xf2\x10\x65\xb4\xee\x5f\x18\xd5\x17\xe3\xf8\xc5\xfd\xe2\x9d\xa2\xef\x53\x0e\x85\x77\xa2\x0f\xe1\x30\x47\xee\x00\xe7\x33\x7d\x44\x67\x1a\x0b\x51\xe8\x8b\xa0\x9e\x50\x98\x68\x34\x52\x1f\x2e\x6d\x01\xf2\x60\x45\xf2\x31\xeb\xa9\x31\x68\x29\xbb\x7a\x41\x9e\xc6\x19\x7f\x94\xb4\x51\x39\x03\x7f\xb2\xde\xa7\x32\x9b\xb4\x47\x8e\x6f\xb4\x4a\xae\xe5\xaf\xb1\xdc\xb0\x1b\x61\xbc\x99\x72\xde\xe4\x89\xb7\x7a\x26\x5d\xda\x33\x49\x5b\x52\x9c\x0e\xf5\x8a\xad\xc3\xb8\x3d\xe8\x06\x6a\xc2\xd5\x2a\x0b\x6c\x7b\x84\xbd\x56\x05\xcb\x86\x65\x92\xec\x44\x2b\xb0\x8e\xb9\xdc\x70\x0b\x46\xda\xad\xbc\x63\x88\x39\xfa\xdb\x6a\xfe\x23\xfa\xbc\xe4\x48\xf4\x67\x2b\x6a\x11\x10\x21\x49\x02\x03\x01\x00\x01\xa3\x81\x91\x30\x81\x8e\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x4f\x06\x03\x55\x1d\x20\x04\x48\x30\x46\x30\x44\x06\x04\x55\x1d\x20\x00\x30\x3c\x30\x3a\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x2e\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x70\x6b\x69\x6f\x76\x65\x72\x68\x65\x69\x64\x2e\x6e\x6c\x2f\x70\x6f\x6c\x69\x63\x69\x65\x73\x2f\x72\x6f\x6f\x74\x2d\x70\x6f\x6c\x69\x63\x79\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xa8\x7d\xeb\xbc\x63\xa4\x74\x13\x74\x00\xec\x96\xe0\xd3\x34\xc1\x2c\xbf\x6c\xf8\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x05\x84\x87\x55\x74\x36\x61\xc1\xbb\xd1\xd4\xc6\x15\xa8\x13\xb4\x9f\xa4\xfe\xbb\xee\x15\xb4\x2f\x06\x0c\x29\xf2\xa8\x92\xa4\x61\x0d\xfc\xab\x5c\x08\x5b\x51\x13\x2b\x4d\xc2\x2a\x61\xc8\xf8\x09\x58\xfc\x2d\x02\xb2\x39\x7d\x99\x66\x81\xbf\x6e\x5c\x95\x45\x20\x6c\xe6\x79\xa7\xd1\xd8\x1c\x29\xfc\xc2\x20\x27\x51\xc8\xf1\x7c\x5d\x34\x67\x69\x85\x11\x30\xc6\x00\xd2\xd7\xf3\xd3\x7c\xb6\xf0\x31\x57\x28\x12\x82\x73\xe9\x33\x2f\xa6\x55\xb4\x0b\x91\x94\x47\x9c\xfa\xbb\x7a\x42\x32\xe8\xae\x7e\x2d\xc8\xbc\xac\x14\xbf\xd9\x0f\xd9\x5b\xfc\xc1\xf9\x7a\x95\xe1\x7d\x7e\x96\xfc\x71\xb0\xc2\x4c\xc8\xdf\x45\x34\xc9\xce\x0d\xf2\x9c\x64\x08\xd0\x3b\xc3\x29\xc5\xb2\xed\x90\x04\xc1\xb1\x29\x91\xc5\x30\x6f\xc1\xa9\x72\x33\xcc\xfe\x5d\x16\x17\x2c\x11\x69\xe7\x7e\xfe\xc5\x83\x08\xdf\xbc\xdc\x22\x3a\x2e\x20\x69\x23\x39\x56\x60\x67\x90\x8b\x2e\x76\x39\xfb\x11\x88\x97\xf6\x7c\xbd\x4b\xb8\x20\x16\x67\x05\x8d\xe2\x3b\xc1\x72\x3f\x94\x95\x37\xc7\x5d\xb9\x9e\xd8\x93\xa1\x17\x8f\xff\x0c\x66\x15\xc1\x24\x7c\x32\x7c\x03\x1d\x3b\xa1\x58\x45\x32\x93", 0 }, + /* Anchor: 137 StarfieldRootCertificateAuthorityG2.der serial: #{a.serial.to_s} + C=US,ST=Arizona,L=Scottsdale,O=Starfield Technologies\, Inc.,CN=Starfield Root Certificate Authority - G2 + */ + { 993, "\x30\x82\x03\xdd\x30\x82\x02\xc5\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x30\x81\x8f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0e\x06\x03\x55\x04\x08\x13\x07\x41\x72\x69\x7a\x6f\x6e\x61\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0a\x53\x63\x6f\x74\x74\x73\x64\x61\x6c\x65\x31\x25\x30\x23\x06\x03\x55\x04\x0a\x13\x1c\x53\x74\x61\x72\x66\x69\x65\x6c\x64\x20\x54\x65\x63\x68\x6e\x6f\x6c\x6f\x67\x69\x65\x73\x2c\x20\x49\x6e\x63\x2e\x31\x32\x30\x30\x06\x03\x55\x04\x03\x13\x29\x53\x74\x61\x72\x66\x69\x65\x6c\x64\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x32\x30\x1e\x17\x0d\x30\x39\x30\x39\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x33\x37\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x81\x8f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0e\x06\x03\x55\x04\x08\x13\x07\x41\x72\x69\x7a\x6f\x6e\x61\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0a\x53\x63\x6f\x74\x74\x73\x64\x61\x6c\x65\x31\x25\x30\x23\x06\x03\x55\x04\x0a\x13\x1c\x53\x74\x61\x72\x66\x69\x65\x6c\x64\x20\x54\x65\x63\x68\x6e\x6f\x6c\x6f\x67\x69\x65\x73\x2c\x20\x49\x6e\x63\x2e\x31\x32\x30\x30\x06\x03\x55\x04\x03\x13\x29\x53\x74\x61\x72\x66\x69\x65\x6c\x64\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x32\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xbd\xed\xc1\x03\xfc\xf6\x8f\xfc\x02\xb1\x6f\x5b\x9f\x48\xd9\x9d\x79\xe2\xa2\xb7\x03\x61\x56\x18\xc3\x47\xb6\xd7\xca\x3d\x35\x2e\x89\x43\xf7\xa1\x69\x9b\xde\x8a\x1a\xfd\x13\x20\x9c\xb4\x49\x77\x32\x29\x56\xfd\xb9\xec\x8c\xdd\x22\xfa\x72\xdc\x27\x61\x97\xee\xf6\x5a\x84\xec\x6e\x19\xb9\x89\x2c\xdc\x84\x5b\xd5\x74\xfb\x6b\x5f\xc5\x89\xa5\x10\x52\x89\x46\x55\xf4\xb8\x75\x1c\xe6\x7f\xe4\x54\xae\x4b\xf8\x55\x72\x57\x02\x19\xf8\x17\x71\x59\xeb\x1e\x28\x07\x74\xc5\x9d\x48\xbe\x6c\xb4\xf4\xa4\xb0\xf3\x64\x37\x79\x92\xc0\xec\x46\x5e\x7f\xe1\x6d\x53\x4c\x62\xaf\xcd\x1f\x0b\x63\xbb\x3a\x9d\xfb\xfc\x79\x00\x98\x61\x74\xcf\x26\x82\x40\x63\xf3\xb2\x72\x6a\x19\x0d\x99\xca\xd4\x0e\x75\xcc\x37\xfb\x8b\x89\xc1\x59\xf1\x62\x7f\x5f\xb3\x5f\x65\x30\xf8\xa7\xb7\x4d\x76\x5a\x1e\x76\x5e\x34\xc0\xe8\x96\x56\x99\x8a\xb3\xf0\x7f\xa4\xcd\xbd\xdc\x32\x31\x7c\x91\xcf\xe0\x5f\x11\xf8\x6b\xaa\x49\x5c\xd1\x99\x94\xd1\xa2\xe3\x63\x5b\x09\x76\xb5\x56\x62\xe1\x4b\x74\x1d\x96\xd4\x26\xd4\x08\x04\x59\xd0\x98\x0e\x0e\xe6\xde\xfc\xc3\xec\x1f\x90\xf1\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x7c\x0c\x32\x1f\xa7\xd9\x30\x7f\xc4\x7d\x68\xa3\x62\xa8\xa1\xce\xab\x07\x5b\x27\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x03\x82\x01\x01\x00\x11\x59\xfa\x25\x4f\x03\x6f\x94\x99\x3b\x9a\x1f\x82\x85\x39\xd4\x76\x05\x94\x5e\xe1\x28\x93\x6d\x62\x5d\x09\xc2\xa0\xa8\xd4\xb0\x75\x38\xf1\x34\x6a\x9d\xe4\x9f\x8a\x86\x26\x51\xe6\x2c\xd1\xc6\x2d\x6e\x95\x20\x4a\x92\x01\xec\xb8\x8a\x67\x7b\x31\xe2\x67\x2e\x8c\x95\x03\x26\x2e\x43\x9d\x4a\x31\xf6\x0e\xb5\x0c\xbb\xb7\xe2\x37\x7f\x22\xba\x00\xa3\x0e\x7b\x52\xfb\x6b\xbb\x3b\xc4\xd3\x79\x51\x4e\xcd\x90\xf4\x67\x07\x19\xc8\x3c\x46\x7a\x0d\x01\x7d\xc5\x58\xe7\x6d\xe6\x85\x30\x17\x9a\x24\xc4\x10\xe0\x04\xf7\xe0\xf2\x7f\xd4\xaa\x0a\xff\x42\x1d\x37\xed\x94\xe5\x64\x59\x12\x20\x77\x38\xd3\x32\x3e\x38\x81\x75\x96\x73\xfa\x68\x8f\xb1\xcb\xce\x1f\xc5\xec\xfa\x9c\x7e\xcf\x7e\xb1\xf1\x07\x2d\xb6\xfc\xbf\xca\xa4\xbf\xd0\x97\x05\x4a\xbc\xea\x18\x28\x02\x90\xbd\x54\x78\x09\x21\x71\xd3\xd1\x7d\x1d\xd9\x16\xb0\xa9\x61\x3d\xd0\x0a\x00\x22\xfc\xc7\x7b\xcb\x09\x64\x45\x0b\x3b\x40\x81\xf7\x7d\x7c\x32\xf5\x98\xca\x58\x8e\x7d\x2a\xee\x90\x59\x73\x64\xf9\x36\x74\x5e\x25\xa1\xf5\x66\x05\x2e\x7f\x39\x15\xa9\x2a\xfb\x50\x8b\x8e\x85\x69\xf4", 0 }, + /* Anchor: 138 StarfieldServicesRootCertificateAuthorityG2.der serial: #{a.serial.to_s} + C=US,ST=Arizona,L=Scottsdale,O=Starfield Technologies\, Inc.,CN=Starfield Services Root Certificate Authority - G2 + */ + { 1011, "\x30\x82\x03\xef\x30\x82\x02\xd7\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x30\x81\x98\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0e\x06\x03\x55\x04\x08\x13\x07\x41\x72\x69\x7a\x6f\x6e\x61\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0a\x53\x63\x6f\x74\x74\x73\x64\x61\x6c\x65\x31\x25\x30\x23\x06\x03\x55\x04\x0a\x13\x1c\x53\x74\x61\x72\x66\x69\x65\x6c\x64\x20\x54\x65\x63\x68\x6e\x6f\x6c\x6f\x67\x69\x65\x73\x2c\x20\x49\x6e\x63\x2e\x31\x3b\x30\x39\x06\x03\x55\x04\x03\x13\x32\x53\x74\x61\x72\x66\x69\x65\x6c\x64\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x32\x30\x1e\x17\x0d\x30\x39\x30\x39\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x33\x37\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x81\x98\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0e\x06\x03\x55\x04\x08\x13\x07\x41\x72\x69\x7a\x6f\x6e\x61\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0a\x53\x63\x6f\x74\x74\x73\x64\x61\x6c\x65\x31\x25\x30\x23\x06\x03\x55\x04\x0a\x13\x1c\x53\x74\x61\x72\x66\x69\x65\x6c\x64\x20\x54\x65\x63\x68\x6e\x6f\x6c\x6f\x67\x69\x65\x73\x2c\x20\x49\x6e\x63\x2e\x31\x3b\x30\x39\x06\x03\x55\x04\x03\x13\x32\x53\x74\x61\x72\x66\x69\x65\x6c\x64\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x32\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xd5\x0c\x3a\xc4\x2a\xf9\x4e\xe2\xf5\xbe\x19\x97\x5f\x8e\x88\x53\xb1\x1f\x3f\xcb\xcf\x9f\x20\x13\x6d\x29\x3a\xc8\x0f\x7d\x3c\xf7\x6b\x76\x38\x63\xd9\x36\x60\xa8\x9b\x5e\x5c\x00\x80\xb2\x2f\x59\x7f\xf6\x87\xf9\x25\x43\x86\xe7\x69\x1b\x52\x9a\x90\xe1\x71\xe3\xd8\x2d\x0d\x4e\x6f\xf6\xc8\x49\xd9\xb6\xf3\x1a\x56\xae\x2b\xb6\x74\x14\xeb\xcf\xfb\x26\xe3\x1a\xba\x1d\x96\x2e\x6a\x3b\x58\x94\x89\x47\x56\xff\x25\xa0\x93\x70\x53\x83\xda\x84\x74\x14\xc3\x67\x9e\x04\x68\x3a\xdf\x8e\x40\x5a\x1d\x4a\x4e\xcf\x43\x91\x3b\xe7\x56\xd6\x00\x70\xcb\x52\xee\x7b\x7d\xae\x3a\xe7\xbc\x31\xf9\x45\xf6\xc2\x60\xcf\x13\x59\x02\x2b\x80\xcc\x34\x47\xdf\xb9\xde\x90\x65\x6d\x02\xcf\x2c\x91\xa6\xa6\xe7\xde\x85\x18\x49\x7c\x66\x4e\xa3\x3a\x6d\xa9\xb5\xee\x34\x2e\xba\x0d\x03\xb8\x33\xdf\x47\xeb\xb1\x6b\x8d\x25\xd9\x9b\xce\x81\xd1\x45\x46\x32\x96\x70\x87\xde\x02\x0e\x49\x43\x85\xb6\x6c\x73\xbb\x64\xea\x61\x41\xac\xc9\xd4\x54\xdf\x87\x2f\xc7\x22\xb2\x26\xcc\x9f\x59\x54\x68\x9f\xfc\xbe\x2a\x2f\xc4\x55\x1c\x75\x40\x60\x17\x85\x02\x55\x39\x8b\x7f\x05\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x9c\x5f\x00\xdf\xaa\x01\xd7\x30\x2b\x38\x88\xa2\xb8\x6d\x4a\x9c\xf2\x11\x91\x83\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x03\x82\x01\x01\x00\x4b\x36\xa6\x84\x77\x69\xdd\x3b\x19\x9f\x67\x23\x08\x6f\x0e\x61\xc9\xfd\x84\xdc\x5f\xd8\x36\x81\xcd\xd8\x1b\x41\x2d\x9f\x60\xdd\xc7\x1a\x68\xd9\xd1\x6e\x86\xe1\x88\x23\xcf\x13\xde\x43\xcf\xe2\x34\xb3\x04\x9d\x1f\x29\xd5\xbf\xf8\x5e\xc8\xd5\xc1\xbd\xee\x92\x6f\x32\x74\xf2\x91\x82\x2f\xbd\x82\x42\x7a\xad\x2a\xb7\x20\x7d\x4d\xbc\x7a\x55\x12\xc2\x15\xea\xbd\xf7\x6a\x95\x2e\x6c\x74\x9f\xcf\x1c\xb4\xf2\xc5\x01\xa3\x85\xd0\x72\x3e\xad\x73\xab\x0b\x9b\x75\x0c\x6d\x45\xb7\x8e\x94\xac\x96\x37\xb5\xa0\xd0\x8f\x15\x47\x0e\xe3\xe8\x83\xdd\x8f\xfd\xef\x41\x01\x77\xcc\x27\xa9\x62\x85\x33\xf2\x37\x08\xef\x71\xcf\x77\x06\xde\xc8\x19\x1d\x88\x40\xcf\x7d\x46\x1d\xff\x1e\xc7\xe1\xce\xff\x23\xdb\xc6\xfa\x8d\x55\x4e\xa9\x02\xe7\x47\x11\x46\x3e\xf4\xfd\xbd\x7b\x29\x26\xbb\xa9\x61\x62\x37\x28\xb6\x2d\x2a\xf6\x10\x86\x64\xc9\x70\xa7\xd2\xad\xb7\x29\x70\x79\xea\x3c\xda\x63\x25\x9f\xfd\x68\xb7\x30\xec\x70\xfb\x75\x8a\xb7\x6d\x60\x67\xb2\x1e\xc8\xb9\xe9\xd8\xa8\x6f\x02\x8b\x67\x0d\x4d\x26\x57\x71\xda\x20\xfc\xc1\x4a\x50\x8d\xb1\x28\xba", 0 }, + /* Anchor: 139 startcom-sfsca.der serial: #{a.serial.to_s} + C=IL,O=StartCom Ltd.,OU=Secure Digital Certificate Signing,CN=StartCom Certification Authority + */ + { 1997, "\x30\x82\x07\xc9\x30\x82\x05\xb1\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x7d\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x4c\x31\x16\x30\x14\x06\x03\x55\x04\x0a\x13\x0d\x53\x74\x61\x72\x74\x43\x6f\x6d\x20\x4c\x74\x64\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0b\x13\x22\x53\x65\x63\x75\x72\x65\x20\x44\x69\x67\x69\x74\x61\x6c\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x69\x67\x6e\x69\x6e\x67\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x53\x74\x61\x72\x74\x43\x6f\x6d\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x30\x36\x30\x39\x31\x37\x31\x39\x34\x36\x33\x36\x5a\x17\x0d\x33\x36\x30\x39\x31\x37\x31\x39\x34\x36\x33\x36\x5a\x30\x7d\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x4c\x31\x16\x30\x14\x06\x03\x55\x04\x0a\x13\x0d\x53\x74\x61\x72\x74\x43\x6f\x6d\x20\x4c\x74\x64\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0b\x13\x22\x53\x65\x63\x75\x72\x65\x20\x44\x69\x67\x69\x74\x61\x6c\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x69\x67\x6e\x69\x6e\x67\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x53\x74\x61\x72\x74\x43\x6f\x6d\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\xc1\x88\xdb\x09\xbc\x6c\x46\x7c\x78\x9f\x95\x7b\xb5\x33\x90\xf2\x72\x62\xd6\xc1\x36\x20\x22\x24\x5e\xce\xe9\x77\xf2\x43\x0a\xa2\x06\x64\xa4\xcc\x8e\x36\xf8\x38\xe6\x23\xf0\x6e\x6d\xb1\x3c\xdd\x72\xa3\x85\x1c\xa1\xd3\x3d\xb4\x33\x2b\xd3\x2f\xaf\xfe\xea\xb0\x41\x59\x67\xb6\xc4\x06\x7d\x0a\x9e\x74\x85\xd6\x79\x4c\x80\x37\x7a\xdf\x39\x05\x52\x59\xf7\xf4\x1b\x46\x43\xa4\xd2\x85\x85\xd2\xc3\x71\xf3\x75\x62\x34\xba\x2c\x8a\x7f\x1e\x8f\xee\xed\x34\xd0\x11\xc7\x96\xcd\x52\x3d\xba\x33\xd6\xdd\x4d\xde\x0b\x3b\x4a\x4b\x9f\xc2\x26\x2f\xfa\xb5\x16\x1c\x72\x35\x77\xca\x3c\x5d\xe6\xca\xe1\x26\x8b\x1a\x36\x76\x5c\x01\xdb\x74\x14\x25\xfe\xed\xb5\xa0\x88\x0f\xdd\x78\xca\x2d\x1f\x07\x97\x30\x01\x2d\x72\x79\xfa\x46\xd6\x13\x2a\xa8\xb9\xa6\xab\x83\x49\x1d\xe5\xf2\xef\xdd\xe4\x01\x8e\x18\x0a\x8f\x63\x53\x16\x85\x62\xa9\x0e\x19\x3a\xcc\xb5\x66\xa6\xc2\x6b\x74\x07\xe4\x2b\xe1\x76\x3e\xb4\x6d\xd8\xf6\x44\xe1\x73\x62\x1f\x3b\xc4\xbe\xa0\x53\x56\x25\x6c\x51\x09\xf7\xaa\xab\xca\xbf\x76\xfd\x6d\x9b\xf3\x9d\xdb\xbf\x3d\x66\xbc\x0c\x56\xaa\xaf\x98\x48\x95\x3a\x4b\xdf\xa7\x58\x50\xd9\x38\x75\xa9\x5b\xea\x43\x0c\x02\xff\x99\xeb\xe8\x6c\x4d\x70\x5b\x29\x65\x9c\xdd\xaa\x5d\xcc\xaf\x01\x31\xec\x0c\xeb\xd2\x8d\xe8\xea\x9c\x7b\xe6\x6e\xf7\x27\x66\x0c\x1a\x48\xd7\x6e\x42\xe3\x3f\xde\x21\x3e\x7b\xe1\x0d\x70\xfb\x63\xaa\xa8\x6c\x1a\x54\xb4\x5c\x25\x7a\xc9\xa2\xc9\x8b\x16\xa6\xbb\x2c\x7e\x17\x5e\x05\x4d\x58\x6e\x12\x1d\x01\xee\x12\x10\x0d\xc6\x32\x7f\x18\xff\xfc\xf4\xfa\xcd\x6e\x91\xe8\x36\x49\xbe\x1a\x48\x69\x8b\xc2\x96\x4d\x1a\x12\xb2\x69\x17\xc1\x0a\x90\xd6\xfa\x79\x22\x48\xbf\xba\x7b\x69\xf8\x70\xc7\xfa\x7a\x37\xd8\xd8\x0d\xd2\x76\x4f\x57\xff\x90\xb7\xe3\x91\xd2\xdd\xef\xc2\x60\xb7\x67\x3a\xdd\xfe\xaa\x9c\xf0\xd4\x8b\x7f\x72\x22\xce\xc6\x9f\x97\xb6\xf8\xaf\x8a\xa0\x10\xa8\xd9\xfb\x18\xc6\xb6\xb5\x5c\x52\x3c\x89\xb6\x19\x2a\x73\x01\x0a\x0f\x03\xb3\x12\x60\xf2\x7a\x2f\x81\xdb\xa3\x6e\xff\x26\x30\x97\xf5\x8b\xdd\x89\x57\xb6\xad\x3d\xb3\xaf\x2b\xc5\xb7\x76\x02\xf0\xa5\xd6\x2b\x9a\x86\x14\x2a\x72\xf6\xe3\x33\x8c\x5d\x09\x4b\x13\xdf\xbb\x8c\x74\x13\x52\x4b\x02\x03\x01\x00\x01\xa3\x82\x02\x52\x30\x82\x02\x4e\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\xae\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x4e\x0b\xef\x1a\xa4\x40\x5b\xa5\x17\x69\x87\x30\xca\x34\x68\x43\xd0\x41\xae\xf2\x30\x64\x06\x03\x55\x1d\x1f\x04\x5d\x30\x5b\x30\x2c\xa0\x2a\xa0\x28\x86\x26\x68\x74\x74\x70\x3a\x2f\x2f\x63\x65\x72\x74\x2e\x73\x74\x61\x72\x74\x63\x6f\x6d\x2e\x6f\x72\x67\x2f\x73\x66\x73\x63\x61\x2d\x63\x72\x6c\x2e\x63\x72\x6c\x30\x2b\xa0\x29\xa0\x27\x86\x25\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x73\x74\x61\x72\x74\x63\x6f\x6d\x2e\x6f\x72\x67\x2f\x73\x66\x73\x63\x61\x2d\x63\x72\x6c\x2e\x63\x72\x6c\x30\x82\x01\x5d\x06\x03\x55\x1d\x20\x04\x82\x01\x54\x30\x82\x01\x50\x30\x82\x01\x4c\x06\x0b\x2b\x06\x01\x04\x01\x81\xb5\x37\x01\x01\x01\x30\x82\x01\x3b\x30\x2f\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x23\x68\x74\x74\x70\x3a\x2f\x2f\x63\x65\x72\x74\x2e\x73\x74\x61\x72\x74\x63\x6f\x6d\x2e\x6f\x72\x67\x2f\x70\x6f\x6c\x69\x63\x79\x2e\x70\x64\x66\x30\x35\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x29\x68\x74\x74\x70\x3a\x2f\x2f\x63\x65\x72\x74\x2e\x73\x74\x61\x72\x74\x63\x6f\x6d\x2e\x6f\x72\x67\x2f\x69\x6e\x74\x65\x72\x6d\x65\x64\x69\x61\x74\x65\x2e\x70\x64\x66\x30\x81\xd0\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x02\x30\x81\xc3\x30\x27\x16\x20\x53\x74\x61\x72\x74\x20\x43\x6f\x6d\x6d\x65\x72\x63\x69\x61\x6c\x20\x28\x53\x74\x61\x72\x74\x43\x6f\x6d\x29\x20\x4c\x74\x64\x2e\x30\x03\x02\x01\x01\x1a\x81\x97\x4c\x69\x6d\x69\x74\x65\x64\x20\x4c\x69\x61\x62\x69\x6c\x69\x74\x79\x2c\x20\x72\x65\x61\x64\x20\x74\x68\x65\x20\x73\x65\x63\x74\x69\x6f\x6e\x20\x2a\x4c\x65\x67\x61\x6c\x20\x4c\x69\x6d\x69\x74\x61\x74\x69\x6f\x6e\x73\x2a\x20\x6f\x66\x20\x74\x68\x65\x20\x53\x74\x61\x72\x74\x43\x6f\x6d\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x50\x6f\x6c\x69\x63\x79\x20\x61\x76\x61\x69\x6c\x61\x62\x6c\x65\x20\x61\x74\x20\x68\x74\x74\x70\x3a\x2f\x2f\x63\x65\x72\x74\x2e\x73\x74\x61\x72\x74\x63\x6f\x6d\x2e\x6f\x72\x67\x2f\x70\x6f\x6c\x69\x63\x79\x2e\x70\x64\x66\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x38\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x0d\x04\x2b\x16\x29\x53\x74\x61\x72\x74\x43\x6f\x6d\x20\x46\x72\x65\x65\x20\x53\x53\x4c\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x16\x6c\x99\xf4\x66\x0c\x34\xf5\xd0\x85\x5e\x7d\x0a\xec\xda\x10\x4e\x38\x1c\x5e\xdf\xa6\x25\x05\x4b\x91\x32\xc1\xe8\x3b\xf1\x3d\xdd\x44\x09\x5b\x07\x49\x8a\x29\xcb\x66\x02\xb7\xb1\x9a\xf7\x25\x98\x09\x3c\x8e\x1b\xe1\xdd\x36\x87\x2b\x4b\xbb\x68\xd3\x39\x66\x3d\xa0\x26\xc7\xf2\x39\x91\x1d\x51\xab\x82\x7b\x7e\xd5\xce\x5a\xe4\xe2\x03\x57\x70\x69\x97\x08\xf9\x5e\x58\xa6\x0a\xdf\x8c\x06\x9a\x45\x16\x16\x38\x0a\x5e\x57\xf6\x62\xc7\x7a\x02\x05\xe6\xbc\x1e\xb5\xf2\x9e\xf4\xa9\x29\x83\xf8\xb2\x14\xe3\x6e\x28\x87\x44\xc3\x90\x1a\xde\x38\xa9\x3c\xac\x43\x4d\x64\x45\xce\xdd\x28\xa9\x5c\xf2\x73\x7b\x04\xf8\x17\xe8\xab\xb1\xf3\x2e\x5c\x64\x6e\x73\x31\x3a\x12\xb8\xbc\xb3\x11\xe4\x7d\x8f\x81\x51\x9a\x3b\x8d\x89\xf4\x4d\x93\x66\x7b\x3c\x03\xed\xd3\x9a\x1d\x9a\xf3\x65\x50\xf5\xa0\xd0\x75\x9f\x2f\xaf\xf0\xea\x82\x43\x98\xf8\x69\x9c\x89\x79\xc4\x43\x8e\x46\x72\xe3\x64\x36\x12\xaf\xf7\x25\x1e\x38\x89\x90\x77\x7e\xc3\x6b\x6a\xb9\xc3\xcb\x44\x4b\xac\x78\x90\x8b\xe7\xc7\x2c\x1e\x4b\x11\x44\xc8\x34\x52\x27\xcd\x0a\x5d\x9f\x85\xc1\x89\xd5\x1a\x78\xf2\x95\x10\x53\x32\xdd\x80\x84\x66\x75\xd9\xb5\x68\x28\xfb\x61\x2e\xbe\x84\xa8\x38\xc0\x99\x12\x86\xa5\x1e\x67\x64\xad\x06\x2e\x2f\xa9\x70\x85\xc7\x96\x0f\x7c\x89\x65\xf5\x8e\x43\x54\x0e\xab\xdd\xa5\x80\x39\x94\x60\xc0\x34\xc9\x96\x70\x2c\xa3\x12\xf5\x1f\x48\x7b\xbd\x1c\x7e\x6b\xb7\x9d\x90\xf4\x22\x3b\xae\xf8\xfc\x2a\xca\xfa\x82\x52\xa0\xef\xaf\x4b\x55\x93\xeb\xc1\xb5\xf0\x22\x8b\xac\x34\x4e\x26\x22\x04\xa1\x87\x2c\x75\x4a\xb7\xe5\x7d\x13\xd7\xb8\x0c\x64\xc0\x36\xd2\xc9\x2f\x86\x12\x8c\x23\x09\xc1\x1b\x82\x3b\x73\x49\xa3\x6a\x57\x87\x94\xe5\xd6\x78\xc5\x99\x43\x63\xe3\x4d\xe0\x77\x2d\xe1\x65\x99\x72\x69\x04\x1a\x47\x09\xe6\x0f\x01\x56\x24\xfb\x1f\xbf\x0e\x79\xa9\x58\x2e\xb9\xc4\x09\x01\x7e\x95\xba\x6d\x00\x06\x3e\xb2\xea\x4a\x10\x39\xd8\xd0\x2b\xf5\xbf\xec\x75\xbf\x97\x02\xc5\x09\x1b\x08\xdc\x55\x37\xe2\x81\xfb\x37\x84\x43\x62\x20\xca\xe7\x56\x4b\x65\xea\xfe\x6c\xc1\x24\x93\x24\xa1\x34\xeb\x05\xff\x9a\x22\xae\x9b\x7d\x3f\xf1\x65\x51\x0a\xa6\x30\x6a\xb3\xf4\x88\x1c\x80\x0d\xfc\x72\x8a\xe8\x83\x5e", 140 }, + /* Anchor: 140 startcomSHA2.der serial: #{a.serial.to_s} + C=IL,O=StartCom Ltd.,OU=Secure Digital Certificate Signing,CN=StartCom Certification Authority + */ + { 1931, "\x30\x82\x07\x87\x30\x82\x05\x6f\xa0\x03\x02\x01\x02\x02\x01\x2d\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x30\x7d\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x4c\x31\x16\x30\x14\x06\x03\x55\x04\x0a\x13\x0d\x53\x74\x61\x72\x74\x43\x6f\x6d\x20\x4c\x74\x64\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0b\x13\x22\x53\x65\x63\x75\x72\x65\x20\x44\x69\x67\x69\x74\x61\x6c\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x69\x67\x6e\x69\x6e\x67\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x53\x74\x61\x72\x74\x43\x6f\x6d\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x30\x36\x30\x39\x31\x37\x31\x39\x34\x36\x33\x37\x5a\x17\x0d\x33\x36\x30\x39\x31\x37\x31\x39\x34\x36\x33\x36\x5a\x30\x7d\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x4c\x31\x16\x30\x14\x06\x03\x55\x04\x0a\x13\x0d\x53\x74\x61\x72\x74\x43\x6f\x6d\x20\x4c\x74\x64\x2e\x31\x2b\x30\x29\x06\x03\x55\x04\x0b\x13\x22\x53\x65\x63\x75\x72\x65\x20\x44\x69\x67\x69\x74\x61\x6c\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x69\x67\x6e\x69\x6e\x67\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x53\x74\x61\x72\x74\x43\x6f\x6d\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\xc1\x88\xdb\x09\xbc\x6c\x46\x7c\x78\x9f\x95\x7b\xb5\x33\x90\xf2\x72\x62\xd6\xc1\x36\x20\x22\x24\x5e\xce\xe9\x77\xf2\x43\x0a\xa2\x06\x64\xa4\xcc\x8e\x36\xf8\x38\xe6\x23\xf0\x6e\x6d\xb1\x3c\xdd\x72\xa3\x85\x1c\xa1\xd3\x3d\xb4\x33\x2b\xd3\x2f\xaf\xfe\xea\xb0\x41\x59\x67\xb6\xc4\x06\x7d\x0a\x9e\x74\x85\xd6\x79\x4c\x80\x37\x7a\xdf\x39\x05\x52\x59\xf7\xf4\x1b\x46\x43\xa4\xd2\x85\x85\xd2\xc3\x71\xf3\x75\x62\x34\xba\x2c\x8a\x7f\x1e\x8f\xee\xed\x34\xd0\x11\xc7\x96\xcd\x52\x3d\xba\x33\xd6\xdd\x4d\xde\x0b\x3b\x4a\x4b\x9f\xc2\x26\x2f\xfa\xb5\x16\x1c\x72\x35\x77\xca\x3c\x5d\xe6\xca\xe1\x26\x8b\x1a\x36\x76\x5c\x01\xdb\x74\x14\x25\xfe\xed\xb5\xa0\x88\x0f\xdd\x78\xca\x2d\x1f\x07\x97\x30\x01\x2d\x72\x79\xfa\x46\xd6\x13\x2a\xa8\xb9\xa6\xab\x83\x49\x1d\xe5\xf2\xef\xdd\xe4\x01\x8e\x18\x0a\x8f\x63\x53\x16\x85\x62\xa9\x0e\x19\x3a\xcc\xb5\x66\xa6\xc2\x6b\x74\x07\xe4\x2b\xe1\x76\x3e\xb4\x6d\xd8\xf6\x44\xe1\x73\x62\x1f\x3b\xc4\xbe\xa0\x53\x56\x25\x6c\x51\x09\xf7\xaa\xab\xca\xbf\x76\xfd\x6d\x9b\xf3\x9d\xdb\xbf\x3d\x66\xbc\x0c\x56\xaa\xaf\x98\x48\x95\x3a\x4b\xdf\xa7\x58\x50\xd9\x38\x75\xa9\x5b\xea\x43\x0c\x02\xff\x99\xeb\xe8\x6c\x4d\x70\x5b\x29\x65\x9c\xdd\xaa\x5d\xcc\xaf\x01\x31\xec\x0c\xeb\xd2\x8d\xe8\xea\x9c\x7b\xe6\x6e\xf7\x27\x66\x0c\x1a\x48\xd7\x6e\x42\xe3\x3f\xde\x21\x3e\x7b\xe1\x0d\x70\xfb\x63\xaa\xa8\x6c\x1a\x54\xb4\x5c\x25\x7a\xc9\xa2\xc9\x8b\x16\xa6\xbb\x2c\x7e\x17\x5e\x05\x4d\x58\x6e\x12\x1d\x01\xee\x12\x10\x0d\xc6\x32\x7f\x18\xff\xfc\xf4\xfa\xcd\x6e\x91\xe8\x36\x49\xbe\x1a\x48\x69\x8b\xc2\x96\x4d\x1a\x12\xb2\x69\x17\xc1\x0a\x90\xd6\xfa\x79\x22\x48\xbf\xba\x7b\x69\xf8\x70\xc7\xfa\x7a\x37\xd8\xd8\x0d\xd2\x76\x4f\x57\xff\x90\xb7\xe3\x91\xd2\xdd\xef\xc2\x60\xb7\x67\x3a\xdd\xfe\xaa\x9c\xf0\xd4\x8b\x7f\x72\x22\xce\xc6\x9f\x97\xb6\xf8\xaf\x8a\xa0\x10\xa8\xd9\xfb\x18\xc6\xb6\xb5\x5c\x52\x3c\x89\xb6\x19\x2a\x73\x01\x0a\x0f\x03\xb3\x12\x60\xf2\x7a\x2f\x81\xdb\xa3\x6e\xff\x26\x30\x97\xf5\x8b\xdd\x89\x57\xb6\xad\x3d\xb3\xaf\x2b\xc5\xb7\x76\x02\xf0\xa5\xd6\x2b\x9a\x86\x14\x2a\x72\xf6\xe3\x33\x8c\x5d\x09\x4b\x13\xdf\xbb\x8c\x74\x13\x52\x4b\x02\x03\x01\x00\x01\xa3\x82\x02\x10\x30\x82\x02\x0c\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x4e\x0b\xef\x1a\xa4\x40\x5b\xa5\x17\x69\x87\x30\xca\x34\x68\x43\xd0\x41\xae\xf2\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x4e\x0b\xef\x1a\xa4\x40\x5b\xa5\x17\x69\x87\x30\xca\x34\x68\x43\xd0\x41\xae\xf2\x30\x82\x01\x5a\x06\x03\x55\x1d\x20\x04\x82\x01\x51\x30\x82\x01\x4d\x30\x82\x01\x49\x06\x0b\x2b\x06\x01\x04\x01\x81\xb5\x37\x01\x01\x01\x30\x82\x01\x38\x30\x2e\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x73\x74\x61\x72\x74\x73\x73\x6c\x2e\x63\x6f\x6d\x2f\x70\x6f\x6c\x69\x63\x79\x2e\x70\x64\x66\x30\x34\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x73\x74\x61\x72\x74\x73\x73\x6c\x2e\x63\x6f\x6d\x2f\x69\x6e\x74\x65\x72\x6d\x65\x64\x69\x61\x74\x65\x2e\x70\x64\x66\x30\x81\xcf\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x02\x30\x81\xc2\x30\x27\x16\x20\x53\x74\x61\x72\x74\x20\x43\x6f\x6d\x6d\x65\x72\x63\x69\x61\x6c\x20\x28\x53\x74\x61\x72\x74\x43\x6f\x6d\x29\x20\x4c\x74\x64\x2e\x30\x03\x02\x01\x01\x1a\x81\x96\x4c\x69\x6d\x69\x74\x65\x64\x20\x4c\x69\x61\x62\x69\x6c\x69\x74\x79\x2c\x20\x72\x65\x61\x64\x20\x74\x68\x65\x20\x73\x65\x63\x74\x69\x6f\x6e\x20\x2a\x4c\x65\x67\x61\x6c\x20\x4c\x69\x6d\x69\x74\x61\x74\x69\x6f\x6e\x73\x2a\x20\x6f\x66\x20\x74\x68\x65\x20\x53\x74\x61\x72\x74\x43\x6f\x6d\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x50\x6f\x6c\x69\x63\x79\x20\x61\x76\x61\x69\x6c\x61\x62\x6c\x65\x20\x61\x74\x20\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x73\x74\x61\x72\x74\x73\x73\x6c\x2e\x63\x6f\x6d\x2f\x70\x6f\x6c\x69\x63\x79\x2e\x70\x64\x66\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x38\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x0d\x04\x2b\x16\x29\x53\x74\x61\x72\x74\x43\x6f\x6d\x20\x46\x72\x65\x65\x20\x53\x53\x4c\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b\x05\x00\x03\x82\x02\x01\x00\x8e\x8f\xe7\xdc\x94\x79\x7c\xf1\x85\x7f\x9f\x49\x6f\x6b\xca\x5d\xfb\x8c\xfe\x04\xc5\xc1\x62\xd1\x7d\x42\x8a\xbc\x53\xb7\x94\x03\x66\x30\x3f\xb1\xe7\x0a\xa7\x50\x20\x55\x25\x7f\x76\x7a\x14\x0d\xeb\x04\x0e\x40\xe6\x3e\xd8\x88\xab\x07\x27\x83\xa9\x75\xa6\x37\x73\xc7\xfd\x4b\xd2\x4d\xad\x17\x40\xc8\x46\xbe\x3b\x7f\x51\xfc\xc3\xb6\x05\x31\xdc\xcd\x85\x22\x4e\x71\xb7\xf2\x71\x5e\xb0\x1a\xc6\xba\x93\x8b\x78\x92\x4a\x85\xf8\x78\x0f\x83\xfe\x2f\xad\x2c\xf7\xe4\xa4\xbb\x2d\xd0\xe7\x0d\x3a\xb8\x3e\xce\xf6\x78\xf6\xae\x47\x24\xca\xa3\x35\x36\xce\xc7\xc6\x87\x98\xda\xec\xfb\xe9\xb2\xce\x27\x9b\x88\xc3\x04\xa1\xf6\x0b\x59\x68\xaf\xc9\xdb\x10\x0f\x4d\xf6\x64\x63\x5c\xa5\x12\x6f\x92\xb2\x93\x94\xc7\x88\x17\x0e\x93\xb6\x7e\x62\x8b\x90\x7f\xab\x4e\x9f\xfc\xe3\x75\x14\x4f\x2a\x32\xdf\x5b\x0d\xe0\xf5\x7b\x93\x0d\xab\xa1\xcf\x87\xe1\xa5\x04\x45\xe8\x3c\x12\xa5\x09\xc5\xb0\xd1\xb7\x53\xf3\x60\x14\xba\x85\x69\x6a\x21\x7c\x1f\x75\x61\x17\x20\x17\x7b\x6c\x3b\x41\x29\x5c\xe1\xac\x5a\xd1\xcd\x8c\x9b\xeb\x60\x1d\x19\xec\xf7\xe5\xb0\xda\xf9\x79\x18\xa5\x45\x3f\x49\x43\x57\xd2\xdd\x24\xd5\x2c\xa3\xfd\x91\x8d\x27\xb5\xe5\xeb\x14\x06\x9a\x4c\x7b\x21\xbb\x3a\xad\x30\x06\x18\xc0\xd8\xc1\x6b\x2c\x7f\x59\x5c\x5d\x91\xb1\x70\x22\x57\xeb\x8a\x6b\x48\x4a\xd5\x0f\x29\xec\xc6\x40\xc0\x2f\x88\x4c\x68\x01\x17\x77\xf4\x24\x19\x4f\xbd\xfa\xe1\xb2\x20\x21\x4b\xdd\x1a\xd8\x29\x7d\xaa\xb8\xde\x54\xec\x21\x55\x80\x6c\x1e\xf5\x30\xc8\xa3\x10\xe5\xb2\xe6\x2a\x14\x31\xc3\x85\x2d\x8c\x98\xb1\x86\x5a\x4f\x89\x59\x2d\xb9\xc7\xf7\x1c\xc8\x8a\x7f\xc0\x9d\x05\x4a\xe6\x42\x4f\x62\xa3\x6d\x29\xa4\x1f\x85\xab\xdb\xe5\x81\xc8\xad\x2a\x3d\x4c\x5d\x5b\x84\x26\x71\xc4\x85\x5e\x71\x24\xca\xa5\x1b\x6c\xd8\x61\xd3\x1a\xe0\x54\xdb\xce\xba\xa9\x32\xb5\x22\xf6\x73\x41\x09\x5d\xb8\x17\x5d\x0e\x0f\x99\x90\xd6\x47\xda\x6f\x0a\x3a\x62\x28\x14\x67\x82\xd9\xf1\xd0\x80\x59\x9b\xcb\x31\xd8\x9b\x0f\x8c\x77\x4e\xb5\x68\x8a\xf2\x6c\xf6\x24\x0e\x2d\x6c\x70\xc5\x73\xd1\xde\x14\xd0\x71\x8f\xb6\xd3\x7b\x02\xf6\xe3\xb8\xd4\x09\x6e\x6b\x9e\x75\x84\x39\xe6\x7f\x25\xa5\xf2\x48\x00\xc0\xa4\x01\xda\x3f", 0 }, + /* Anchor: 141 swisscom-sdcs-root.crt serial: #{a.serial.to_s} + C=ch,O=Swisscom,OU=Digital Certificate Services,CN=Swisscom Root CA 1 + */ + { 1501, "\x30\x82\x05\xd9\x30\x82\x03\xc1\xa0\x03\x02\x01\x02\x02\x10\x5c\x0b\x85\x5c\x0b\xe7\x59\x41\xdf\x57\xcc\x3f\x7f\x9d\xa8\x36\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x64\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x63\x68\x31\x11\x30\x0f\x06\x03\x55\x04\x0a\x13\x08\x53\x77\x69\x73\x73\x63\x6f\x6d\x31\x25\x30\x23\x06\x03\x55\x04\x0b\x13\x1c\x44\x69\x67\x69\x74\x61\x6c\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x13\x12\x53\x77\x69\x73\x73\x63\x6f\x6d\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x31\x30\x1e\x17\x0d\x30\x35\x30\x38\x31\x38\x31\x32\x30\x36\x32\x30\x5a\x17\x0d\x32\x35\x30\x38\x31\x38\x32\x32\x30\x36\x32\x30\x5a\x30\x64\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x63\x68\x31\x11\x30\x0f\x06\x03\x55\x04\x0a\x13\x08\x53\x77\x69\x73\x73\x63\x6f\x6d\x31\x25\x30\x23\x06\x03\x55\x04\x0b\x13\x1c\x44\x69\x67\x69\x74\x61\x6c\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x13\x12\x53\x77\x69\x73\x73\x63\x6f\x6d\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x31\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\xd0\xb9\xb0\xa8\x0c\xd9\xbb\x3f\x21\xf8\x1b\xd5\x33\x93\x80\x16\x65\x20\x75\xb2\x3d\x9b\x60\x6d\x46\xc8\x8c\x31\x6f\x17\xc3\xfa\x9a\x6c\x56\xed\x3c\xc5\x91\x57\xc3\xcd\xab\x96\x49\x90\x2a\x19\x4b\x1e\xa3\x6d\x57\xdd\xf1\x2b\x62\x28\x75\x45\x5e\xaa\xd6\x5b\xfa\x0b\x25\xd8\xa1\x16\xf9\x1c\xc4\x2e\xe6\x95\x2a\x67\xcc\xd0\x29\x6e\x3c\x85\x34\x38\x61\x49\xb1\x00\x9f\xd6\x3a\x71\x5f\x4d\x6d\xce\x5f\xb9\xa9\xe4\x89\x7f\x6a\x52\xfa\xca\x9b\xf2\xdc\xa9\xf9\x9d\x99\x47\x3f\x4e\x29\x5f\xb4\xa6\x8d\x5d\x7b\x0b\x99\x11\x03\x03\xfe\xe7\xdb\xdb\xa3\xff\x1d\xa5\xcd\x90\x1e\x01\x1f\x35\xb0\x7f\x00\xdb\x90\x6f\xc6\x7e\x7b\xd1\xee\x7a\x7a\xa7\xaa\x0c\x57\x6f\xa4\x6d\xc5\x13\x3b\xb0\xa5\xd9\xed\x32\x1c\xb4\x5e\x67\x8b\x54\xdc\x73\x87\xe5\xd3\x17\x7c\x66\x50\x72\x5d\xd4\x1a\x58\xc1\xd9\xcf\xd8\x89\x02\x6f\xa7\x49\xb4\x36\x5d\xd0\xa4\xde\x07\x2c\xb6\x75\xb7\x28\x91\xd6\x97\xbe\x28\xf5\x98\x1e\xea\x5b\x26\xc9\xbd\xb0\x97\x73\xda\xae\x91\x26\xeb\x68\xc1\xf9\x39\x15\xd6\x67\x4b\x0a\x6d\x4f\xcb\xcf\xb0\xe4\x42\x71\x8c\x53\x79\xe7\xee\xe1\xdb\x1d\xa0\x6e\x1d\x8c\x1a\x77\x35\x5c\x16\x1e\x2b\x53\x1f\x34\x8b\xd1\x6c\xfc\xf2\x67\x07\x7a\xf5\xad\xed\xd6\x9a\xab\xa1\xb1\x4b\xe1\xcc\x37\x5f\xfd\x7f\xcd\x4d\xae\xb8\x1f\x9c\x43\xf9\x2a\x58\x55\x43\x45\xbc\x96\xcd\x70\x0e\xfc\xc9\xe3\x66\xba\x4e\x8d\x3b\x81\xcb\x15\x64\x7b\xb9\x94\xe8\x5d\x33\x52\x85\x71\x2e\x4f\x8e\xa2\x06\x11\x51\xc9\xe3\xcb\xa1\x6e\x31\x08\x64\x0c\xc2\xd2\x3c\xf5\x36\xe8\xd7\xd0\x0e\x78\x23\x20\x91\xc9\x24\x2a\x65\x29\x5b\x22\xf7\x21\xce\x83\x5e\xa4\xf3\xde\x4b\xd3\x68\x8f\x46\x75\x5c\x83\x09\x6e\x29\x6b\xc4\x70\x8c\xf5\x9d\xd7\x20\x2f\xff\x46\xd2\x2b\x38\xc2\x2f\x75\x1c\x3d\x7e\xda\xa5\xef\x1e\x60\x85\x69\x42\xd3\xcc\xf8\x63\xfe\x1e\x43\x39\x85\xa6\xb6\x63\x41\x10\xb3\x73\x1e\xbc\xd3\xfa\xca\x7d\x16\x47\xe2\xa7\xd5\xd0\xa3\x8a\x0a\x08\x96\x62\x56\x6e\x34\xdb\xd9\x02\xb9\x30\x75\xe3\x04\xd2\xe7\x8f\xc2\xb0\x11\x40\x0a\xac\xd5\x71\x02\x62\x8b\x31\xbe\xdd\xc6\x23\x58\x31\x42\x43\x2d\x74\xf9\xc6\x9e\xa6\x8a\x0f\xe9\xfe\xbf\x83\xe6\x43\x57\x24\xba\xef\x46\x34\xaa\xd7\x12\x01\x38\xed\x02\x03\x01\x00\x01\xa3\x81\x86\x30\x81\x83\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x86\x30\x1d\x06\x03\x55\x1d\x21\x04\x16\x30\x14\x30\x12\x06\x07\x60\x85\x74\x01\x53\x00\x01\x06\x07\x60\x85\x74\x01\x53\x00\x01\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01\x07\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x03\x25\x2f\xde\x6f\x82\x01\x3a\x5c\x2c\xdc\x2b\xa1\x69\xb5\x67\xd4\x8c\xd3\xfd\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x03\x25\x2f\xde\x6f\x82\x01\x3a\x5c\x2c\xdc\x2b\xa1\x69\xb5\x67\xd4\x8c\xd3\xfd\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x35\x10\xcb\xec\xa6\x04\x0d\x0d\x0f\xcd\xc0\xdb\xab\xa8\xf2\x88\x97\x0c\xdf\x93\x2f\x4d\x7c\x40\x56\x31\x7a\xeb\xa4\x0f\x60\xcd\x7a\xf3\xbe\xc3\x27\x8e\x03\x3e\xa4\xdd\x12\xef\x7e\x1e\x74\x06\x3c\x3f\x31\xf2\x1c\x7b\x91\x31\x21\xb4\xf0\xd0\x6c\x97\xd4\xe9\x97\xb2\x24\x56\x1e\x56\xc3\x35\xbd\x88\x05\x0f\x5b\x10\x1a\x64\xe1\xc7\x82\x30\xf9\x32\xad\x9e\x50\x2c\xe7\x78\x05\xd0\x31\xb1\x5a\x98\x8a\x75\x4e\x90\x5c\x6a\x14\x2a\xe0\x52\x47\x82\x60\xe6\x1e\xda\x81\xb1\xfb\x14\x0b\x5a\xf1\x9f\xd2\x95\xba\x3e\xd0\x1b\xd6\x15\x1d\xa3\xbe\x86\xd5\xdb\x0f\xc0\x49\x64\xbb\x2e\x50\x19\x4b\xd2\x24\xf8\xdd\x1e\x07\x56\xd0\x38\xa0\x95\x70\x20\x76\x8c\xd7\xdd\x1e\xde\x9f\x71\xc4\x23\xef\x83\x13\x5c\xa3\x24\x15\x4d\x29\x40\x3c\x6a\xc4\xa9\xd8\xb7\xa6\x44\xa5\x0d\xf4\xe0\x9d\x77\x1e\x40\x70\x26\xfc\xda\xd9\x36\xe4\x79\xe4\xb5\x3f\xbc\x9b\x65\xbe\xbb\x11\x96\xcf\xdb\xc6\x28\x39\x3a\x08\xce\x47\x5b\x53\x5a\xc5\x99\xfe\x5d\xa9\xdd\xef\x4c\xd4\xc6\xa5\xad\x02\xe6\x8c\x07\x12\x1e\x6f\x03\xd1\x6f\xa0\xa3\xf3\x29\xbd\x12\xc7\x50\xa2\xb0\x7f\x88\xa9\x99\x77\x9a\xb1\xc0\xa5\x39\x2e\x5c\x7c\x69\xe2\x2c\xb0\xea\x37\x6a\xa4\xe1\x5a\xe1\xf5\x50\xe5\x83\xef\xa5\xbb\x2a\x88\xe7\x8c\xdb\xfd\x6d\x5e\x97\x19\xa8\x7e\x66\x75\x6b\x71\xea\xbf\xb1\xc7\x6f\xa0\xf4\x8e\xa4\xec\x34\x51\x5b\x8c\x26\x03\x70\xa1\x77\xd5\x01\x12\x57\x00\x35\xdb\x23\xde\x0e\x8a\x28\x99\xfd\xb1\x10\x6f\x4b\xff\x38\x2d\x60\x4e\x2c\x9c\xeb\x67\xb5\xad\x49\xee\x4b\x1f\xac\xaf\xfb\x0d\x90\x5a\x66\x60\x70\x5d\xaa\xcd\x78\xd4\x24\xee\xc8\x41\xa0\x93\x01\x92\x9c\x6a\x9e\xfc\xb9\x24\xc5\xb3\x15\x82\x7e\xbe\xae\x95\x2b\xeb\xb1\xc0\xda\xe3\x01\x60\x0b\x5e\x69\xac\x84\x56\x61\xbe\x71\x17\xfe\x1d\x13\x0f\xfe\xc6\x87\x45\xe9\xfe\x32\xa0\x1a\x0d\x13\xa4\x94\x55\x71\xa5\x16\x8b\xba\xca\x89\xb0\xb2\xc7\xfc\x8f\xd8\x54\xb5\x93\x62\x9d\xce\xcf\x59\xfb\x3d\x18\xce\x2a\xcb\x35\x15\x82\x5d\xff\x54\x22\x5b\x71\x52\xfb\xb7\xc9\xfe\x60\x9b\x00\x41\x64\xf0\xaa\x2a\xec\xb6\x42\x43\xce\x89\x66\x81\xc8\x8b\x9f\x39\x54\x03\x25\xd3\x16\x35\x8e\x84\xd0\x5f\xfa\x30\x1a\xf5\x9a\x6c\xf4\x0e\x53\xf9\x3a\x5b\xd1\x1c", 0 }, + /* Anchor: 142 SwissSign-Gold_G2.der serial: #{a.serial.to_s} + C=CH,O=SwissSign AG,CN=SwissSign Gold CA - G2 + */ + { 1470, "\x30\x82\x05\xba\x30\x82\x03\xa2\xa0\x03\x02\x01\x02\x02\x09\x00\xbb\x40\x1c\x43\xf5\x5e\x4f\xb0\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x45\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x13\x0c\x53\x77\x69\x73\x73\x53\x69\x67\x6e\x20\x41\x47\x31\x1f\x30\x1d\x06\x03\x55\x04\x03\x13\x16\x53\x77\x69\x73\x73\x53\x69\x67\x6e\x20\x47\x6f\x6c\x64\x20\x43\x41\x20\x2d\x20\x47\x32\x30\x1e\x17\x0d\x30\x36\x31\x30\x32\x35\x30\x38\x33\x30\x33\x35\x5a\x17\x0d\x33\x36\x31\x30\x32\x35\x30\x38\x33\x30\x33\x35\x5a\x30\x45\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x13\x0c\x53\x77\x69\x73\x73\x53\x69\x67\x6e\x20\x41\x47\x31\x1f\x30\x1d\x06\x03\x55\x04\x03\x13\x16\x53\x77\x69\x73\x73\x53\x69\x67\x6e\x20\x47\x6f\x6c\x64\x20\x43\x41\x20\x2d\x20\x47\x32\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\xaf\xe4\xee\x7e\x8b\x24\x0e\x12\x6e\xa9\x50\x2d\x16\x44\x3b\x92\x92\x5c\xca\xb8\x5d\x84\x92\x42\x13\x2a\xbc\x65\x57\x82\x40\x3e\x57\x24\xcd\x50\x8b\x25\x2a\xb7\x6f\xfc\xef\xa2\xd0\xc0\x1f\x02\x24\x4a\x13\x96\x8f\x23\x13\xe6\x28\x58\x00\xa3\x47\xc7\x06\xa7\x84\x23\x2b\xbb\xbd\x96\x2b\x7f\x55\xcc\x8b\xc1\x57\x1f\x0e\x62\x65\x0f\xdd\x3d\x56\x8a\x73\xda\xae\x7e\x6d\xba\x81\x1c\x7e\x42\x8c\x20\x35\xd9\x43\x4d\x84\xfa\x84\xdb\x52\x2c\xf3\x0e\x27\x77\x0b\x6b\xbf\x11\x2f\x72\x78\x9f\x2e\xd8\x3e\xe6\x18\x37\x5a\x2a\x72\xf9\xda\x62\x90\x92\x95\xca\x1f\x9c\xe9\xb3\x3c\x2b\xcb\xf3\x01\x13\xbf\x5a\xcf\xc1\xb5\x0a\x60\xbd\xdd\xb5\x99\x64\x53\xb8\xa0\x96\xb3\x6f\xe2\x26\x77\x91\x8c\xe0\x62\x10\x02\x9f\x34\x0f\xa4\xd5\x92\x33\x51\xde\xbe\x8d\xba\x84\x7a\x60\x3c\x6a\xdb\x9f\x2b\xec\xde\xde\x01\x3f\x6e\x4d\xe5\x50\x86\xcb\xb4\xaf\xed\x44\x40\xc5\xca\x5a\x8c\xda\xd2\x2b\x7c\xa8\xee\xbe\xa6\xe5\x0a\xaa\x0e\xa5\xdf\x05\x52\xb7\x55\xc7\x22\x5d\x32\x6a\x97\x97\x63\x13\xdb\xc9\xdb\x79\x36\x7b\x85\x3a\x4a\xc5\x52\x89\xf9\x24\xe7\x9d\x77\xa9\x82\xff\x55\x1c\xa5\x71\x69\x2b\xd1\x02\x24\xf2\xb3\x26\xd4\x6b\xda\x04\x55\xe5\xc1\x0a\xc7\x6d\x30\x37\x90\x2a\xe4\x9e\x14\x33\x5e\x16\x17\x55\xc5\x5b\xb5\xcb\x34\x89\x92\xf1\x9d\x26\x8f\xa1\x07\xd4\xc6\xb2\x78\x50\xdb\x0c\x0c\x0b\x7c\x0b\x8c\x41\xd7\xb9\xe9\xdd\x8c\x88\xf7\xa3\x4d\xb2\x32\xcc\xd8\x17\xda\xcd\xb7\xce\x66\x9d\xd4\xfd\x5e\xff\xbd\x97\x3e\x29\x75\xe7\x7e\xa7\x62\x58\xaf\x25\x34\xa5\x41\xc7\x3d\xbc\x0d\x50\xca\x03\x03\x0f\x08\x5a\x1f\x95\x73\x78\x62\xbf\xaf\x72\x14\x69\x0e\xa5\xe5\x03\x0e\x78\x8e\x26\x28\x42\xf0\x07\x0b\x62\x20\x10\x67\x39\x46\xfa\xa9\x03\xcc\x04\x38\x7a\x66\xef\x20\x83\xb5\x8c\x4a\x56\x8e\x91\x00\xfc\x8e\x5c\x82\xde\x88\xa0\xc3\xe2\x68\x6e\x7d\x8d\xef\x3c\xdd\x65\xf4\x5d\xac\x51\xef\x24\x80\xae\xaa\x56\x97\x6f\xf9\xad\x7d\xda\x61\x3f\x98\x77\x3c\xa5\x91\xb6\x1c\x8c\x26\xda\x65\xa2\x09\x6d\xc1\xe2\x54\xe3\xb9\xca\x4c\x4c\x80\x8f\x77\x7b\x60\x9a\x1e\xdf\xb6\xf2\x48\x1e\x0e\xba\x4e\x54\x6d\x98\xe0\xe1\xa2\x1a\xa2\x77\x50\xcf\xc4\x63\x92\xec\x47\x19\x9d\xeb\xe6\x6b\xce\xc1\x02\x03\x01\x00\x01\xa3\x81\xac\x30\x81\xa9\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x5b\x25\x7b\x96\xa4\x65\x51\x7e\xb8\x39\xf3\xc0\x78\x66\x5e\xe8\x3a\xe7\xf0\xee\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x5b\x25\x7b\x96\xa4\x65\x51\x7e\xb8\x39\xf3\xc0\x78\x66\x5e\xe8\x3a\xe7\xf0\xee\x30\x46\x06\x03\x55\x1d\x20\x04\x3f\x30\x3d\x30\x3b\x06\x09\x60\x85\x74\x01\x59\x01\x02\x01\x01\x30\x2e\x30\x2c\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x20\x68\x74\x74\x70\x3a\x2f\x2f\x72\x65\x70\x6f\x73\x69\x74\x6f\x72\x79\x2e\x73\x77\x69\x73\x73\x73\x69\x67\x6e\x2e\x63\x6f\x6d\x2f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x27\xba\xe3\x94\x7c\xf1\xae\xc0\xde\x17\xe6\xe5\xd8\xd5\xf5\x54\xb0\x83\xf4\xbb\xcd\x5e\x05\x7b\x4f\x9f\x75\x66\xaf\x3c\xe8\x56\x7e\xfc\x72\x78\x38\x03\xd9\x2b\x62\x1b\x00\xb9\xf8\xe9\x60\xcd\xcc\xce\x51\x8a\xc7\x50\x31\x6e\xe1\x4a\x7e\x18\x2f\x69\x59\xb6\x3d\x64\x81\x2b\xe3\x83\x84\xe6\x22\x87\x8e\x7d\xe0\xee\x02\x99\x61\xb8\x1e\xf4\xb8\x2b\x88\x12\x16\x84\xc2\x31\x93\x38\x96\x31\xa6\xb9\x3b\x53\x3f\xc3\x24\x93\x56\x5b\x69\x92\xec\xc5\xc1\xbb\x38\x00\xe3\xec\x17\xa9\xb8\xdc\xc7\x7c\x01\x83\x9f\x32\x47\xba\x52\x22\x34\x1d\x32\x7a\x09\x56\xa7\x7c\x25\x36\xa9\x3d\x4b\xda\xc0\x82\x6f\x0a\xbb\x12\xc8\x87\x4b\x27\x11\xf9\x1e\x2d\xc7\x93\x3f\x9e\xdb\x5f\x26\x6b\x52\xd9\x2e\x8a\xf1\x14\xc6\x44\x8d\x15\xa9\xb7\xbf\xbd\xde\xa6\x1a\xee\xae\x2d\xfb\x48\x77\x17\xfe\xbb\xec\xaf\x18\xf5\x2a\x51\xf0\x39\x84\x97\x95\x6c\x6e\x1b\xc3\x2b\xc4\x74\x60\x79\x25\xb0\x0a\x27\xdf\xdf\x5e\xd2\x39\xcf\x45\x7d\x42\x4b\xdf\xb3\x2c\x1e\xc5\xc6\x5d\xca\x55\x3a\xa0\x9c\x69\x9a\x8f\xda\xef\xb2\xb0\x3c\x9f\x87\x6c\x12\x2b\x65\x70\x15\x52\x31\x1a\x24\xcf\x6f\x31\x23\x50\x1f\x8c\x4f\x8f\x23\xc3\x74\x41\x63\x1c\x55\xa8\x14\xdd\x3e\xe0\x51\x50\xcf\xf1\x1b\x30\x56\x0e\x92\xb0\x82\x85\xd8\x83\xcb\x22\x64\xbc\x2d\xb8\x25\xd5\x54\xa2\xb8\x06\xea\xad\x92\xa4\x24\xa0\xc1\x86\xb5\x4a\x13\x6a\x47\xcf\x2e\x0b\x56\x95\x54\xcb\xce\x9a\xdb\x6a\xb4\xa6\xb2\xdb\x41\x08\x86\x27\x77\xf7\x6a\xa0\x42\x6c\x0b\x38\xce\xd7\x75\x50\x32\x92\xc2\xdf\x2b\x30\x22\x48\xd0\xd5\x41\x38\x25\x5d\xa4\xe9\x5d\x9f\xc6\x94\x75\xd0\x45\xfd\x30\x97\x43\x8f\x90\xab\x0a\xc7\x86\x73\x60\x4a\x69\x2d\xde\xa5\x78\xd7\x06\xda\x6a\x9e\x4b\x3e\x77\x3a\x20\x13\x22\x01\xd0\xbf\x68\x9e\x63\x60\x6b\x35\x4d\x0b\x6d\xba\xa1\x3d\xc0\x93\xe0\x7f\x23\xb3\x55\xad\x72\x25\x4e\x46\xf9\xd2\x16\xef\xb0\x64\xc1\x01\x9e\xe9\xca\xa0\x6a\x98\x0e\xcf\xd8\x60\xf2\x2f\x49\xb8\xe4\x42\xe1\x38\x35\x16\xf4\xc8\x6e\x4f\xf7\x81\x56\xe8\xba\xa3\xbe\x23\xaf\xae\xfd\x6f\x03\xe0\x02\x3b\x30\x76\xfa\x1b\x6d\x41\xcf\x01\xb1\xe9\xb8\xc9\x66\xf4\xdb\x26\xf3\x3a\xa4\x74\xf2\x49\x24\x5b\xc9\xb0\xd0\x57\xc1\xfa\x3e\x7a\xe1\x97\xc9", 0 }, + /* Anchor: 143 SwissSign-Platinum_G2.der serial: #{a.serial.to_s} + C=CH,O=SwissSign AG,CN=SwissSign Platinum CA - G2 + */ + { 1477, "\x30\x82\x05\xc1\x30\x82\x03\xa9\xa0\x03\x02\x01\x02\x02\x08\x4e\xb2\x00\x67\x0c\x03\x5d\x4f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x49\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x13\x0c\x53\x77\x69\x73\x73\x53\x69\x67\x6e\x20\x41\x47\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1a\x53\x77\x69\x73\x73\x53\x69\x67\x6e\x20\x50\x6c\x61\x74\x69\x6e\x75\x6d\x20\x43\x41\x20\x2d\x20\x47\x32\x30\x1e\x17\x0d\x30\x36\x31\x30\x32\x35\x30\x38\x33\x36\x30\x30\x5a\x17\x0d\x33\x36\x31\x30\x32\x35\x30\x38\x33\x36\x30\x30\x5a\x30\x49\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x13\x0c\x53\x77\x69\x73\x73\x53\x69\x67\x6e\x20\x41\x47\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1a\x53\x77\x69\x73\x73\x53\x69\x67\x6e\x20\x50\x6c\x61\x74\x69\x6e\x75\x6d\x20\x43\x41\x20\x2d\x20\x47\x32\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\xca\xdf\xa2\x02\xe2\xda\xf8\xfc\x07\x16\xb1\xde\x60\xaa\xde\x96\x5c\x64\x1f\xc7\x2f\x7e\xcf\x67\xfa\x44\x42\xd6\x76\x63\x95\xae\xeb\xaf\x72\x20\x8a\x45\x47\x86\x62\x78\x86\xd6\x20\x39\x26\xf4\xae\xa3\xfd\x23\xe7\xa5\x9c\xb5\x22\x21\x19\xb7\x37\x93\x22\xc0\x50\x9c\x82\x7b\xd4\xd5\x04\x44\x5c\xcb\xb4\xc2\x9f\x92\xbe\x24\xd8\x7b\x67\x22\xe2\x69\x5f\xe5\x05\x78\xd4\x87\xd9\x71\x70\x33\x25\x53\xb4\x87\x3b\x29\x90\x28\x36\x9a\x55\x44\x30\x68\xa4\x83\x97\x7f\x0d\x1e\x9c\x76\xff\x15\x9d\x60\x97\x00\x8d\x8a\x85\x03\xec\x80\xbe\xea\x2c\x6e\x10\x51\x92\xcc\x7e\xd5\xa3\x33\xd8\xd6\x49\xde\x58\x2a\xaf\xf6\x16\xeb\x4b\x7b\x90\x32\x97\xb9\xba\x9d\x58\xf1\xf8\x57\x49\x04\x1e\xa2\x5d\x06\x70\xdd\x71\xdb\xf9\xdd\x8b\x9a\x1b\x8c\xcf\x3d\xa3\x4d\xce\xcb\x7c\xf6\xbb\x9c\xa0\xfa\x09\xce\x23\x62\xb2\xe9\x0d\x1f\xe2\x72\x28\x8f\x9f\xac\x68\x20\x7d\x6f\x3b\xa8\x85\x31\x09\x7f\x0b\xc7\xe8\x65\xe9\xe3\x78\x0e\x09\x67\x30\x8b\x34\x82\xfb\x5d\xe0\xcc\x9d\x81\x6d\x62\xee\x08\x1e\x04\x2c\x4e\x9b\xec\xfe\xa9\x4f\x5f\xfd\x69\x78\xef\x09\x1f\xa1\xb4\xbf\xfa\xf3\xef\x90\x1e\x4c\x05\x8b\x1e\xea\x7a\x91\x7a\xc3\xd7\xe5\xfb\x30\xbc\x6c\x1b\x10\x58\x98\xf7\x1a\x5f\xd0\x29\x32\x03\x13\x46\x4d\x61\x6a\x85\x4c\x52\x74\x2f\x06\x1f\x7b\x11\xe2\x84\x97\xc6\x99\xf3\x6d\x7f\xd7\x67\x83\x7e\x13\x68\xd8\x71\x28\x5a\xd8\xce\xdd\xe8\x10\x14\x9a\xfe\x6d\x23\x87\x6e\x8e\x5a\x70\x3c\xd5\x8d\x09\x00\xa7\xaa\xbc\xb0\x31\x37\x6d\xc8\x84\x14\x1e\x5b\xbd\x45\x63\x20\x6b\x4b\x74\x8c\xbd\xdb\x3a\x0e\xc1\xcf\x5a\x16\x8f\xa5\x98\xf2\x76\x89\xb2\x13\x12\x3b\x0b\x77\x77\xac\xbb\xe5\x3c\x29\x4a\x92\x72\xca\x61\x1a\x2b\x5e\x4c\xe2\x83\x74\x77\xfa\x35\x48\x7a\x85\x4d\x8d\x9a\x53\xc4\xdf\x78\xca\x97\x91\x48\x2b\x45\x2b\x01\xf7\x1c\x1a\xa2\xed\x18\xba\x0a\xbd\x83\xfa\x6f\xbc\x8d\x57\x93\x3b\xd4\xd4\xa6\xce\x1e\xf1\xa0\xb1\xce\xab\xfd\x2b\x28\x9a\x4f\x1b\xd7\xc3\x72\xdb\xa4\xc4\xbf\x5d\x4c\xf5\xdd\x7b\x96\x69\xee\x68\x80\xe6\xe7\x98\xba\x36\xb7\xfe\x6e\xed\x2b\xbd\x20\xf8\x65\x19\xda\x55\x09\x7e\x25\xdc\xfe\x61\x62\x72\xf9\x7e\x18\x02\xef\x63\xb4\xd0\xfb\xaf\xe5\x3b\x63\x8c\x67\x8f\x02\x03\x01\x00\x01\xa3\x81\xac\x30\x81\xa9\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x50\xaf\xcc\x07\x87\x15\x47\x6f\x38\xc5\xb4\x65\xd1\xde\x95\xaa\xe9\xdf\x9c\xcc\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x50\xaf\xcc\x07\x87\x15\x47\x6f\x38\xc5\xb4\x65\xd1\xde\x95\xaa\xe9\xdf\x9c\xcc\x30\x46\x06\x03\x55\x1d\x20\x04\x3f\x30\x3d\x30\x3b\x06\x09\x60\x85\x74\x01\x59\x01\x01\x01\x01\x30\x2e\x30\x2c\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x20\x68\x74\x74\x70\x3a\x2f\x2f\x72\x65\x70\x6f\x73\x69\x74\x6f\x72\x79\x2e\x73\x77\x69\x73\x73\x73\x69\x67\x6e\x2e\x63\x6f\x6d\x2f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x08\x85\xa6\xf5\x16\x0c\xfc\x44\x1a\xc1\x63\xe0\xf9\x55\x46\x08\xfc\x70\x1c\x42\x28\x96\x8e\xb7\xc5\xc1\x41\x75\x4e\x09\x71\x79\xe5\x6d\x96\xca\x4b\xa5\x88\x60\xd0\x30\x74\xb8\xca\x08\xdc\xb4\x30\x9e\x40\x07\x16\x6b\x65\x95\x77\x01\xae\xa4\xb7\x35\x0b\x81\xda\x71\x15\xa9\x74\x17\x38\x7b\x58\xca\xf9\x2f\xfb\xc0\x65\x76\x8d\x5b\x01\xb9\x7d\xde\x82\x3d\x64\xb8\xbe\x14\x74\xa3\x0a\x54\xd3\x2c\x95\x18\x17\x35\xf5\x51\x6b\x3f\x8f\xa2\x96\x61\x39\x78\x6b\x4b\xe5\xa6\xa0\xf8\x53\xdf\x51\x10\x93\x62\xe7\x80\x2f\xe2\xd1\xe0\xbc\x8e\x36\x46\x77\x33\xec\xb8\xfb\x8e\x9a\x2c\x89\x4d\x31\x11\x0f\x26\x9e\x04\xbb\xb7\x04\x8d\x0b\xf2\xb9\xfc\x5a\x9d\x3b\x16\xb7\x2f\xc8\x98\xab\xfe\x8a\x50\x59\x2e\xa3\x3b\xfc\x29\x5d\x8b\xc1\x4b\xc9\xe2\x8a\x13\x1d\xb1\xbf\xbb\x42\x1d\x52\xdd\x4e\xd8\x14\x5e\x10\xc6\x31\x07\xef\x71\x27\xf7\x1b\x39\x09\xdc\x82\xea\x8b\xb3\x95\x86\x5e\xfd\xf5\xda\x5d\x31\xa6\xe0\x31\xb6\x94\xe6\x44\x49\x74\xc5\x16\xe5\xf7\x1f\x03\x61\x28\xc5\xc8\xcb\x12\xa0\x42\x4b\xf9\x6b\x88\x08\x8d\xb4\x32\x18\xf3\x75\x9f\xc4\x7f\x00\x4f\x05\x95\x9c\xa3\x17\x02\xc3\xb3\x53\x9b\xaa\x20\x39\x29\x2b\x66\xfa\x9d\xaf\x5e\xb3\x92\xd2\xb5\xa6\xe1\x1a\xf9\x2d\x41\x69\x81\x14\xb4\xb4\xb5\xed\x89\x3d\xce\xfb\xa9\x9d\x35\x42\x44\xb1\x1c\x14\x73\x81\xcf\x2a\x01\x35\x9a\x31\xd5\x2d\x8f\x6d\x84\xdf\x80\x4d\x57\xe3\x3f\xc5\x84\x75\xda\x89\xc6\x30\xbb\xeb\x8f\xcb\x22\x08\xa0\xae\xaa\xf1\x03\x6c\x3a\x4b\x4d\x09\xa5\x0e\x72\xc6\x56\x6b\x21\x42\x4e\x23\x25\x14\x68\xae\x76\x0a\x7c\x0c\x07\x70\x64\xf9\x9a\x2f\xf6\x05\x39\x26\xc6\x0c\x8f\x19\x7f\x43\x5e\x6e\xf4\x5b\x15\x2f\xdb\x61\x5d\xe6\x67\x2f\x3f\x08\x94\xf9\x60\xb4\x98\x31\xda\x74\xf1\x84\x93\x71\x4d\x5f\xfb\x60\x58\xd1\xfb\xc4\xc1\x6d\x89\xa2\xbb\x20\x1f\x9d\x71\x91\xcb\x32\x9b\x13\x3d\x3e\x7d\x92\x52\x35\xac\x92\x94\xa2\xd3\x18\xc2\x7c\xc7\xea\xaf\x76\x05\x16\xdd\x67\x27\xc2\x7e\x1c\x07\x22\x21\xf3\x40\x0a\x1b\x34\x07\x44\x13\xc2\x84\x6a\x8e\xdf\x19\x5a\xbf\x7f\xeb\x1d\xe2\x1a\x38\xd1\x5c\xaf\x47\x92\x6b\x80\xb5\x30\xa5\xc9\x8d\xd8\xab\x31\x81\x1f\xdf\xc2\x66\x37\xd3\x93\xa9\x85\x86\x79\x65\xd2", 0 }, + /* Anchor: 144 SwissSign-Silver_G2.der serial: #{a.serial.to_s} + C=CH,O=SwissSign AG,CN=SwissSign Silver CA - G2 + */ + { 1473, "\x30\x82\x05\xbd\x30\x82\x03\xa5\xa0\x03\x02\x01\x02\x02\x08\x4f\x1b\xd4\x2f\x54\xbb\x2f\x4b\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x47\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x13\x0c\x53\x77\x69\x73\x73\x53\x69\x67\x6e\x20\x41\x47\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x53\x77\x69\x73\x73\x53\x69\x67\x6e\x20\x53\x69\x6c\x76\x65\x72\x20\x43\x41\x20\x2d\x20\x47\x32\x30\x1e\x17\x0d\x30\x36\x31\x30\x32\x35\x30\x38\x33\x32\x34\x36\x5a\x17\x0d\x33\x36\x31\x30\x32\x35\x30\x38\x33\x32\x34\x36\x5a\x30\x47\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x13\x0c\x53\x77\x69\x73\x73\x53\x69\x67\x6e\x20\x41\x47\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x53\x77\x69\x73\x73\x53\x69\x67\x6e\x20\x53\x69\x6c\x76\x65\x72\x20\x43\x41\x20\x2d\x20\x47\x32\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\xc4\xf1\x87\x7f\xd3\x78\x31\xf7\x38\xc9\xf8\xc3\x99\x43\xbc\xc7\xf7\xbc\x37\xe7\x4e\x71\xba\x4b\x8f\xa5\x73\x1d\x5c\x6e\x98\xae\x03\x57\xae\x38\x37\x43\x2f\x17\x3d\x1f\xc8\xce\x68\x10\xc1\x78\xae\x19\x03\x2b\x10\xfa\x2c\x79\x83\xf6\xe8\xb9\x68\xb9\x55\xf2\x04\x44\xa7\x39\xf9\xfc\x04\x8b\x1e\xf1\xa2\x4d\x27\xf9\x61\x7b\xba\xb7\xe5\xa2\x13\xb6\xeb\x61\x3e\xd0\x6c\xd1\xe6\xfb\xfa\x5e\xed\x1d\xb4\x9e\xa0\x35\x5b\xa1\x92\xcb\xf0\x49\x92\xfe\x85\x0a\x05\x3e\xe6\xd9\x0b\xe2\x4f\xbb\xdc\x95\x37\xfc\x91\xe9\x32\x35\x22\xd1\x1f\x3a\x4e\x27\x85\x9d\xb0\x15\x94\x32\xda\x61\x0d\x47\x4d\x60\x42\xae\x92\x47\xe8\x83\x5a\x50\x58\xe9\x8a\x8b\xb9\x5d\xa1\xdc\xdd\x99\x4a\x1f\x36\x67\xbb\x48\xe4\x83\xb6\x37\xeb\x48\x3a\xaf\x0f\x67\x8f\x17\x07\xe8\x04\xca\xef\x6a\x31\x87\xd4\xc0\xb6\xf9\x94\x71\x7b\x67\x64\xb8\xb6\x91\x4a\x42\x7b\x65\x2e\x30\x6a\x0c\xf5\x90\xee\x95\xe6\xf2\xcd\x82\xec\xd9\xa1\x4a\xec\xf6\xb2\x4b\xe5\x45\x85\xe6\x6d\x78\x93\x04\x2e\x9c\x82\x6d\x36\xa9\xc4\x31\x64\x1f\x86\x83\x0b\x2a\xf4\x35\x0a\x78\xc9\x55\xcf\x41\xb0\x47\xe9\x30\x9f\x99\xbe\x61\xa8\x06\x84\xb9\x28\x7a\x5f\x38\xd9\x1b\xa9\x38\xb0\x83\x7f\x73\xc1\xc3\x3b\x48\x2a\x82\x0f\x21\x9b\xb8\xcc\xa8\x35\xc3\x84\x1b\x83\xb3\x3e\xbe\xa4\x95\x69\x01\x3a\x89\x00\x78\x04\xd9\xc9\xf4\x99\x19\xab\x56\x7e\x5b\x8b\x86\x39\x15\x91\xa4\x10\x2c\x09\x32\x80\x60\xb3\x93\xc0\x2a\xb6\x18\x0b\x9d\x7e\x8d\x49\xf2\x10\x4a\x7f\xf9\xd5\x46\x2f\x19\x92\xa3\x99\xa7\x26\xac\xbb\x8c\x3c\xe6\x0e\xbc\x47\x07\xdc\x73\x51\xf1\x70\x64\x2f\x08\xf9\xb4\x47\x1d\x30\x6c\x44\xea\x29\x37\x85\x92\x68\x66\xbc\x83\x38\xfe\x7b\x39\x2e\xd3\x50\xf0\x1f\xfb\x5e\x60\xb6\xa9\xa6\xfa\x27\x41\xf1\x9b\x18\x72\xf2\xf5\x84\x74\x4a\xc9\x67\xc4\x54\xae\x48\x64\xdf\x8c\xd1\x6e\xb0\x1d\xe1\x07\x8f\x08\x1e\x99\x9c\x71\xe9\x4c\xd8\xa5\xf7\x47\x12\x1f\x74\xd1\x51\x9e\x86\xf3\xc2\xa2\x23\x40\x0b\x73\xdb\x4b\xa6\xe7\x73\x06\x8c\xc1\xa0\xe9\xc1\x59\xac\x46\xfa\xe6\x2f\xf8\xcf\x71\x9c\x46\x6d\xb9\xc4\x15\x8d\x38\x79\x03\x45\x48\xef\xc4\x5d\xd7\x08\xee\x87\x39\x22\x86\xb2\x0d\x0f\x58\x43\xf7\x71\xa9\x48\x2e\xfd\xea\xd6\x1f\x02\x03\x01\x00\x01\xa3\x81\xac\x30\x81\xa9\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x17\xa0\xcd\xc1\xe4\x41\xb6\x3a\x5b\x3b\xcb\x45\x9d\xbd\x1c\xc2\x98\xfa\x86\x58\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x17\xa0\xcd\xc1\xe4\x41\xb6\x3a\x5b\x3b\xcb\x45\x9d\xbd\x1c\xc2\x98\xfa\x86\x58\x30\x46\x06\x03\x55\x1d\x20\x04\x3f\x30\x3d\x30\x3b\x06\x09\x60\x85\x74\x01\x59\x01\x03\x01\x01\x30\x2e\x30\x2c\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x20\x68\x74\x74\x70\x3a\x2f\x2f\x72\x65\x70\x6f\x73\x69\x74\x6f\x72\x79\x2e\x73\x77\x69\x73\x73\x73\x69\x67\x6e\x2e\x63\x6f\x6d\x2f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x73\xc6\x81\xe0\x27\xd2\x2d\x0f\xe0\x95\x30\xe2\x9a\x41\x7f\x50\x2c\x5f\x5f\x62\x61\xa9\x86\x6a\x69\x18\x0c\x74\x49\xd6\x5d\x84\xea\x41\x52\x18\x6f\x58\xad\x50\x56\x20\x6a\xc6\xbd\x28\x69\x58\x91\xdc\x91\x11\x35\xa9\x3a\x1d\xbc\x1a\xa5\x60\x9e\xd8\x1f\x7f\x45\x91\x69\xd9\x7e\xbb\x78\x72\xc1\x06\x0f\x2a\xce\x8f\x85\x70\x61\xac\xa0\xcd\x0b\xb8\x39\x29\x56\x84\x32\x4e\x86\xbb\x3d\xc4\x2a\xd9\xd7\x1f\x72\xee\xfe\x51\xa1\x22\x41\xb1\x71\x02\x63\x1a\x82\xb0\x62\xab\x5e\x57\x12\x1f\xdf\xcb\xdd\x75\xa0\xc0\x5d\x79\x90\x8c\x1b\xe0\x50\xe6\xde\x31\xfe\x98\x7b\x70\x5f\xa5\x90\xd8\xad\xf8\x02\xb6\x6f\xd3\x60\xdd\x40\x4b\x22\xc5\x3d\xad\x3a\x7a\x9f\x1a\x1a\x47\x91\x79\x33\xba\x82\xdc\x32\x69\x03\x96\x6e\x1f\x4b\xf0\x71\xfe\xe3\x67\x72\xa0\xb1\xbf\x5c\x8b\xe4\xfa\x99\x22\xc7\x84\xb9\x1b\x8d\x23\x97\x3f\xed\x25\xe0\xcf\x65\xbb\xf5\x61\x04\xef\xdd\x1e\xb2\x5a\x41\x22\x5a\xa1\x9f\x5d\x2c\xe8\x5b\xc9\x6d\xa9\x0c\x0c\x78\xaa\x60\xc6\x56\x8f\x01\x5a\x0c\x68\xbc\x69\x19\x79\xc4\x1f\x7e\x97\x05\xbf\xc5\xe9\x24\x51\x5e\xd4\xd5\x4b\x53\xed\xd9\x23\x5a\x36\x03\x65\xa3\xc1\x03\xad\x41\x30\xf3\x46\x1b\x85\x90\xaf\x65\xb5\xd5\xb1\xe4\x16\x5b\x78\x75\x1d\x97\x7a\x6d\x59\xa9\x2a\x8f\x7b\xde\xc3\x87\x89\x10\x99\x49\x73\x78\xc8\x3d\xbd\x51\x35\x74\x2a\xd5\xf1\x7e\x69\x1b\x2a\xbb\x3b\xbd\x25\xb8\x9a\x5a\x3d\x72\x61\x90\x66\x87\xee\x0c\xd6\x4d\xd4\x11\x74\x0b\x6a\xfe\x0b\x03\xfc\xa3\x55\x57\x89\xfe\x4a\xcb\xae\x5b\x17\x05\xc8\xf2\x8d\x23\x31\x53\x38\xd2\x2d\x6a\x3f\x82\xb9\x8d\x08\x6a\xf7\x5e\x41\x74\x6e\xc3\x11\x7e\x07\xac\x29\x60\x91\x3f\x38\xca\x57\x10\x0d\xbd\x30\x2f\xc7\xa5\xe6\x41\xa0\xda\xae\x05\x87\x9a\xa0\xa4\x65\x6c\x4c\x09\x0c\x89\xba\xb8\xd3\xb9\xc0\x93\x8a\x30\xfa\x8d\xe5\x9a\x6b\x15\x01\x4e\x67\xaa\xda\x62\x56\x3e\x84\x08\x66\xd2\xc4\x36\x7d\xa7\x3e\x10\xfc\x88\xe0\xd4\x80\xe5\x00\xbd\xaa\xf3\x4e\x06\xa3\x7a\x6a\xf9\x62\x72\xe3\x09\x4f\xeb\x9b\x0e\x01\x23\xf1\x9f\xbb\x7c\xdc\xdc\x6c\x11\x97\x25\xb2\xf2\xb4\x63\x14\xd2\x06\x2a\x67\x8c\x83\xf5\xce\xea\x07\xd8\x9a\x6a\x1e\xec\xe4\x0a\xbb\x2a\x4c\xeb\x09\x60\x39\xce\xca\x62\xd8\x2e\x6e", 0 }, + /* Anchor: 145 swisssign.der serial: #{a.serial.to_s} + C=CH,O=SwissSign,CN=SwissSign CA (RSA IK May 6 1999 18:00:58),1.2.840.113549.1.9.1=#161063614053776973735369676E2E636F6D + */ + { 953, "\x30\x82\x03\xb5\x30\x82\x02\x9d\xa0\x03\x02\x01\x02\x02\x08\x06\x10\xc2\x79\xab\x77\x3d\xf2\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x76\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x12\x30\x10\x06\x03\x55\x04\x0a\x13\x09\x53\x77\x69\x73\x73\x53\x69\x67\x6e\x31\x32\x30\x30\x06\x03\x55\x04\x03\x13\x29\x53\x77\x69\x73\x73\x53\x69\x67\x6e\x20\x43\x41\x20\x28\x52\x53\x41\x20\x49\x4b\x20\x4d\x61\x79\x20\x36\x20\x31\x39\x39\x39\x20\x31\x38\x3a\x30\x30\x3a\x35\x38\x29\x31\x1f\x30\x1d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x10\x63\x61\x40\x53\x77\x69\x73\x73\x53\x69\x67\x6e\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x30\x30\x31\x31\x32\x36\x32\x33\x32\x37\x34\x31\x5a\x17\x0d\x33\x31\x31\x31\x32\x36\x32\x33\x32\x37\x34\x31\x5a\x30\x76\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x12\x30\x10\x06\x03\x55\x04\x0a\x13\x09\x53\x77\x69\x73\x73\x53\x69\x67\x6e\x31\x32\x30\x30\x06\x03\x55\x04\x03\x13\x29\x53\x77\x69\x73\x73\x53\x69\x67\x6e\x20\x43\x41\x20\x28\x52\x53\x41\x20\x49\x4b\x20\x4d\x61\x79\x20\x36\x20\x31\x39\x39\x39\x20\x31\x38\x3a\x30\x30\x3a\x35\x38\x29\x31\x1f\x30\x1d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x10\x63\x61\x40\x53\x77\x69\x73\x73\x53\x69\x67\x6e\x2e\x63\x6f\x6d\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xac\x39\x7e\x39\xe6\x36\x77\x8b\x42\x55\x02\x40\x6f\x23\x40\xbc\x30\x7d\xba\xce\x66\x85\x30\x35\x7f\x1c\x6c\xda\xa1\xc4\xad\x37\xff\x15\x25\xa0\x55\x60\x02\xdf\x92\x4d\xed\x91\xc4\xd5\xda\x08\x05\xcb\x04\xf9\xf9\x65\x24\xf7\xe5\x32\xd5\xe7\xb6\x8b\x99\xb1\xc2\xb6\x27\xef\xdd\x86\x6a\x69\xa4\x06\xbe\x37\x9d\x96\xd2\x01\x30\x98\xa1\x26\x16\x7e\x87\x72\xd8\x48\xab\x14\x6f\xec\x44\x27\x7c\x79\x65\x47\xfc\x8c\xff\x90\xd6\x0e\x7b\xcb\x5b\x3c\x4a\x70\x45\x58\xdf\xe7\x8b\x93\x64\x17\x56\x35\xcb\x7d\x55\xc0\xe8\xbd\xc2\x23\x9f\xfd\x52\x12\x2f\xeb\xae\x48\x2e\x22\xd4\x23\xf5\x29\xbc\xf7\x04\x3b\x3a\x1e\x1b\x75\x1a\x94\x58\x09\xb2\x7f\x2b\x46\xdc\xf6\x82\x52\xa5\x6a\x53\xe4\xf1\x8e\x36\xc1\x88\x6b\x0a\x8c\x6c\x9b\xb2\xa0\x38\x21\xb1\x74\x35\xa5\xb9\xf6\x7b\xc2\xba\xe0\x14\xac\x70\x66\x55\x65\x33\x68\xa1\x21\xa0\x36\x21\xe6\x00\x23\x49\x05\x85\xe2\x59\x55\xab\xc1\x73\xc5\xe2\x5e\x92\x75\xd9\x82\xdd\x18\xf4\x68\xa5\xe3\x80\x40\x9c\x16\x41\xcb\x0d\x07\x2c\x33\x92\x6c\x2b\x66\x4b\xaf\x24\xc3\x52\xc4\x05\x6f\x15\x4f\xda\x29\x02\x03\x01\x00\x01\xa3\x47\x30\x45\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x06\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x96\xd7\x71\xcd\x39\x2a\xd4\xfc\x88\xb1\x8a\xab\x53\x78\x69\xef\x8f\x47\x7e\x16\x30\x09\x06\x03\x55\x1d\x23\x04\x02\x30\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xa3\x32\xe9\x6f\x07\xbd\x97\x52\xd5\xf0\x69\x11\x4c\xe5\xe8\xbb\xf0\xe7\x46\xe0\x13\x55\xdc\x1d\x4d\x49\xca\x94\x81\x1b\xd9\xa1\x75\xc5\xd9\xa3\x90\x25\x3c\x1e\x2c\x0a\xfc\x7d\x0e\x67\xf0\x87\x2a\xdd\xb2\xc8\x5c\xd1\x33\xf6\x57\x75\x61\xe9\xe4\x2a\x9c\x41\x79\xa8\x1e\x25\x57\x38\x93\x06\x4a\x3d\x99\x6e\x8e\xb7\xea\x4f\x9f\x0b\x32\xe1\x21\xe9\xc7\x7a\xf0\xea\x30\x98\x9c\xea\x9f\x51\xc6\x63\x5a\xaa\xaa\x46\xba\xbf\xdc\xfd\x70\x6b\x3f\x8c\x9f\x87\x0b\x31\x51\x20\xdd\x76\xb3\xa9\x8a\x2f\xfe\x48\x6f\x4a\xa4\xb4\x26\x78\xb0\x8d\x19\x68\xd8\x7e\x9f\xff\x5a\x15\x50\xa6\x6f\x3f\xe7\x54\x86\x94\x1e\xa5\xf6\x6b\x3a\xa3\x00\x59\x95\xb8\xa2\xda\x7a\x16\x89\x72\x43\x27\x94\x34\xde\x94\x09\x13\x62\x50\xa9\x79\xbd\x38\xa3\x6c\xac\x14\x53\x07\xc4\x47\xfd\x55\x72\x2d\xcc\xd7\xf3\xb5\x40\x27\xed\xb5\x0e\x2f\x44\xde\x01\xb9\xcd\x31\xa9\x8b\x46\x2f\x77\x1d\xe5\x68\x8e\xbd\x6c\xf2\x86\x54\xf3\x00\x8e\x95\x51\xd3\x64\x42\x18\x47\x25\x20\x32\x4e\x98\xfa\x76\x65\xc3\x47\x3a\xeb\xca\x81\x46\x6b\x63\xe3\x80\x44\xb1\xcf\xb5\xc1\x69\x22", 0 }, + /* Anchor: 146 tc_class_2_ii.cer serial: #{a.serial.to_s} + C=DE,O=TC TrustCenter GmbH,OU=TC TrustCenter Class 2 CA,CN=TC TrustCenter Class 2 CA II + */ + { 1198, "\x30\x82\x04\xaa\x30\x82\x03\x92\xa0\x03\x02\x01\x02\x02\x0e\x2e\x6a\x00\x01\x00\x02\x1f\xd7\x52\x21\x2c\x11\x5c\x3b\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x76\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x47\x6d\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0b\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x43\x6c\x61\x73\x73\x20\x32\x20\x43\x41\x31\x25\x30\x23\x06\x03\x55\x04\x03\x13\x1c\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x43\x6c\x61\x73\x73\x20\x32\x20\x43\x41\x20\x49\x49\x30\x1e\x17\x0d\x30\x36\x30\x31\x31\x32\x31\x34\x33\x38\x34\x33\x5a\x17\x0d\x32\x35\x31\x32\x33\x31\x32\x32\x35\x39\x35\x39\x5a\x30\x76\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x47\x6d\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0b\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x43\x6c\x61\x73\x73\x20\x32\x20\x43\x41\x31\x25\x30\x23\x06\x03\x55\x04\x03\x13\x1c\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x43\x6c\x61\x73\x73\x20\x32\x20\x43\x41\x20\x49\x49\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xab\x80\x87\x9b\x8e\xf0\xc3\x7c\x87\xd7\xe8\x24\x82\x11\xb3\x3c\xdd\x43\x62\xee\xf8\xc3\x45\xda\xe8\xe1\xa0\x5f\xd1\x2a\xb2\xea\x93\x68\xdf\xb4\xc8\xd6\x43\xe9\xc4\x75\x59\x7f\xfc\xe1\x1d\xf8\x31\x70\x23\x1b\x88\x9e\x27\xb9\x7b\xfd\x3a\xd2\xc9\xa9\xe9\x14\x2f\x90\xbe\x03\x52\xc1\x49\xcd\xf6\xfd\xe4\x08\x66\x0b\x57\x8a\xa2\x42\xa0\xb8\xd5\x7f\x69\x5c\x90\x32\xb2\x97\x0d\xca\x4a\xdc\x46\x3e\x02\x55\x89\x53\xe3\x1a\x5a\xcb\x36\xc6\x07\x56\xf7\x8c\xcf\x11\xf4\x4c\xbb\x30\x70\x04\x95\xa5\xf6\x39\x8c\xfd\x73\x81\x08\x7d\x89\x5e\x32\x1e\x22\xa9\x22\x45\x4b\xb0\x66\x2e\x30\xcc\x9f\x65\xfd\xfc\xcb\x81\xa9\xf1\xe0\x3b\xaf\xa3\x86\xd1\x89\xea\xc4\x45\x79\x50\x5d\xae\xe9\x21\x74\x92\x4d\x8b\x59\x82\x8f\x94\xe3\xe9\x4a\xf1\xe7\x49\xb0\x14\xe3\xf5\x62\xcb\xd5\x72\xbd\x1f\xb9\xd2\x9f\xa0\xcd\xa8\xfa\x01\xc8\xd9\x0d\xdf\xda\xfc\x47\x9d\xb3\xc8\x54\xdf\x49\x4a\xf1\x21\xa9\xfe\x18\x4e\xee\x48\xd4\x19\xbb\xef\x7d\xe4\xe2\x9d\xcb\x5b\xb6\x6e\xff\xe3\xcd\x5a\xe7\x74\x82\x05\xba\x80\x25\x38\xcb\xe4\x69\x9e\xaf\x41\xaa\x1a\x84\xf5\x02\x03\x01\x00\x01\xa3\x82\x01\x34\x30\x82\x01\x30\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xe3\xab\x54\x4c\x80\xa1\xdb\x56\x43\xb7\x91\x4a\xcb\xf3\x82\x7a\x13\x5c\x08\xab\x30\x81\xed\x06\x03\x55\x1d\x1f\x04\x81\xe5\x30\x81\xe2\x30\x81\xdf\xa0\x81\xdc\xa0\x81\xd9\x86\x35\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x74\x72\x75\x73\x74\x63\x65\x6e\x74\x65\x72\x2e\x64\x65\x2f\x63\x72\x6c\x2f\x76\x32\x2f\x74\x63\x5f\x63\x6c\x61\x73\x73\x5f\x32\x5f\x63\x61\x5f\x49\x49\x2e\x63\x72\x6c\x86\x81\x9f\x6c\x64\x61\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x74\x72\x75\x73\x74\x63\x65\x6e\x74\x65\x72\x2e\x64\x65\x2f\x43\x4e\x3d\x54\x43\x25\x32\x30\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x25\x32\x30\x43\x6c\x61\x73\x73\x25\x32\x30\x32\x25\x32\x30\x43\x41\x25\x32\x30\x49\x49\x2c\x4f\x3d\x54\x43\x25\x32\x30\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x25\x32\x30\x47\x6d\x62\x48\x2c\x4f\x55\x3d\x72\x6f\x6f\x74\x63\x65\x72\x74\x73\x2c\x44\x43\x3d\x74\x72\x75\x73\x74\x63\x65\x6e\x74\x65\x72\x2c\x44\x43\x3d\x64\x65\x3f\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x52\x65\x76\x6f\x63\x61\x74\x69\x6f\x6e\x4c\x69\x73\x74\x3f\x62\x61\x73\x65\x3f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x8c\xd7\xdf\x7e\xee\x1b\x80\x10\xb3\x83\xf5\xdb\x11\xea\x6b\x4b\xa8\x92\x18\xd9\xf7\x07\x39\xf5\x2c\xbe\x06\x75\x7a\x68\x53\x15\x1c\xea\x4a\xed\x5e\xfc\x23\xb2\x13\xa0\xd3\x09\xff\xf6\xf6\x2e\x6b\x41\x71\x79\xcd\xe2\x6d\xfd\xae\x59\x6b\x85\x1d\xb8\x4e\x22\x9a\xed\x66\x39\x6e\x4b\x94\xe6\x55\xfc\x0b\x1b\x8b\x77\xc1\x53\x13\x66\x89\xd9\x28\xd6\x8b\xf3\x45\x4a\x63\xb7\xfd\x7b\x0b\x61\x5d\xb8\x6d\xbe\xc3\xdc\x5b\x79\xd2\xed\x86\xe5\xa2\x4d\xbe\x5e\x74\x7c\x6a\xed\x16\x38\x1f\x7f\x58\x81\x5a\x1a\xeb\x32\x88\x2d\xb2\xf3\x39\x77\x80\xaf\x5e\xb6\x61\x75\x29\xdb\x23\x4d\x88\xca\x50\x28\xcb\x85\xd2\xd3\x10\xa2\x59\x6e\xd3\x93\x54\x00\x7a\xa2\x46\x95\x86\x05\x9c\xa9\x19\x98\xe5\x31\x72\x0c\x00\xe2\x67\xd9\x40\xe0\x24\x33\x7b\x6f\x2c\xb9\x5c\xab\x65\x9d\x2c\xac\x76\xea\x35\x99\xf5\x97\xb9\x0f\x24\xec\xc7\x76\x21\x28\x65\xae\x57\xe8\x07\x88\x75\x4a\x56\xa0\xd2\x05\x3a\xa4\xe6\x8d\x92\x88\x2c\xf3\xf2\xe1\xc1\xc6\x61\xdb\x41\xc5\xc7\x9b\xf7\x0e\x1a\x51\x45\xc2\x61\x6b\xdc\x64\x27\x17\x8c\x5a\xb7\xda\x74\x28\xcd\x97\xe4\xbd", 0 }, + /* Anchor: 147 tc_class_3_ii.cer serial: #{a.serial.to_s} + C=DE,O=TC TrustCenter GmbH,OU=TC TrustCenter Class 3 CA,CN=TC TrustCenter Class 3 CA II + */ + { 1198, "\x30\x82\x04\xaa\x30\x82\x03\x92\xa0\x03\x02\x01\x02\x02\x0e\x4a\x47\x00\x01\x00\x02\xe5\xa0\x5d\xd6\x3f\x00\x51\xbf\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x76\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x47\x6d\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0b\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x43\x6c\x61\x73\x73\x20\x33\x20\x43\x41\x31\x25\x30\x23\x06\x03\x55\x04\x03\x13\x1c\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x43\x6c\x61\x73\x73\x20\x33\x20\x43\x41\x20\x49\x49\x30\x1e\x17\x0d\x30\x36\x30\x31\x31\x32\x31\x34\x34\x31\x35\x37\x5a\x17\x0d\x32\x35\x31\x32\x33\x31\x32\x32\x35\x39\x35\x39\x5a\x30\x76\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x47\x6d\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0b\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x43\x6c\x61\x73\x73\x20\x33\x20\x43\x41\x31\x25\x30\x23\x06\x03\x55\x04\x03\x13\x1c\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x43\x6c\x61\x73\x73\x20\x33\x20\x43\x41\x20\x49\x49\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xb4\xe0\xbb\x51\xbb\x39\x5c\x8b\x04\xc5\x4c\x79\x1c\x23\x86\x31\x10\x63\x43\x55\x27\x3f\xc6\x45\xc7\xa4\x3d\xec\x09\x0d\x1a\x1e\x20\xc2\x56\x1e\xde\x1b\x37\x07\x30\x22\x2f\x6f\xf1\x06\xf1\xab\xad\xd6\xc8\xab\x61\xa3\x2f\x43\xc4\xb0\xb2\x2d\xfc\xc3\x96\x69\x7b\x7e\x8a\xe4\xcc\xc0\x39\x12\x90\x42\x60\xc9\xcc\x35\x68\xee\xda\x5f\x90\x56\x5f\xcd\x1c\x4d\x5b\x58\x49\xeb\x0e\x01\x4f\x64\xfa\x2c\x3c\x89\x58\xd8\x2f\x2e\xe2\xb0\x68\xe9\x22\x3b\x75\x89\xd6\x44\x1a\x65\xf2\x1b\x97\x26\x1d\x28\x6d\xac\xe8\xbd\x59\x1d\x2b\x24\xf6\xd6\x84\x03\x66\x88\x24\x00\x78\x60\xf1\xf8\xab\xfe\x02\xb2\x6b\xfb\x22\xfb\x35\xe6\x16\xd1\xad\xf6\x2e\x12\xe4\xfa\x35\x6a\xe5\x19\xb9\x5d\xdb\x3b\x1e\x1a\xfb\xd3\xff\x15\x14\x08\xd8\x09\x6a\xba\x45\x9d\x14\x79\x60\x7d\xaf\x40\x8a\x07\x73\xb3\x93\x96\xd3\x74\x34\x8d\x3a\x37\x29\xde\x5c\xec\xf5\xee\x2e\x31\xc2\x20\xdc\xbe\xf1\x4f\x7f\x23\x52\xd9\x5b\xe2\x64\xd9\x9c\xaa\x07\x08\xb5\x45\xbd\xd1\xd0\x31\xc1\xab\x54\x9f\xa9\xd2\xc3\x62\x60\x03\xf1\xbb\x39\x4a\x92\x4a\x3d\x0a\xb9\x9d\xc5\xa0\xfe\x37\x02\x03\x01\x00\x01\xa3\x82\x01\x34\x30\x82\x01\x30\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xd4\xa2\xfc\x9f\xb3\xc3\xd8\x03\xd3\x57\x5c\x07\xa4\xd0\x24\xa7\xc0\xf2\x00\xd4\x30\x81\xed\x06\x03\x55\x1d\x1f\x04\x81\xe5\x30\x81\xe2\x30\x81\xdf\xa0\x81\xdc\xa0\x81\xd9\x86\x35\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x74\x72\x75\x73\x74\x63\x65\x6e\x74\x65\x72\x2e\x64\x65\x2f\x63\x72\x6c\x2f\x76\x32\x2f\x74\x63\x5f\x63\x6c\x61\x73\x73\x5f\x33\x5f\x63\x61\x5f\x49\x49\x2e\x63\x72\x6c\x86\x81\x9f\x6c\x64\x61\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x74\x72\x75\x73\x74\x63\x65\x6e\x74\x65\x72\x2e\x64\x65\x2f\x43\x4e\x3d\x54\x43\x25\x32\x30\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x25\x32\x30\x43\x6c\x61\x73\x73\x25\x32\x30\x33\x25\x32\x30\x43\x41\x25\x32\x30\x49\x49\x2c\x4f\x3d\x54\x43\x25\x32\x30\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x25\x32\x30\x47\x6d\x62\x48\x2c\x4f\x55\x3d\x72\x6f\x6f\x74\x63\x65\x72\x74\x73\x2c\x44\x43\x3d\x74\x72\x75\x73\x74\x63\x65\x6e\x74\x65\x72\x2c\x44\x43\x3d\x64\x65\x3f\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x52\x65\x76\x6f\x63\x61\x74\x69\x6f\x6e\x4c\x69\x73\x74\x3f\x62\x61\x73\x65\x3f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x36\x60\xe4\x70\xf7\x06\x20\x43\xd9\x23\x1a\x42\xf2\xf8\xa3\xb2\xb9\x4d\x8a\xb4\xf3\xc2\x9a\x55\x31\x7c\xc4\x3b\x67\x9a\xb4\xdf\x4d\x0e\x8a\x93\x4a\x17\x8b\x1b\x8d\xca\x89\xe1\xcf\x3a\x1e\xac\x1d\xf1\x9c\x32\xb4\x8e\x59\x76\xa2\x41\x85\x25\x37\xa0\x13\xd0\xf5\x7c\x4e\xd5\xea\x96\xe2\x6e\x72\xc1\xbb\x2a\xfe\x6c\x6e\xf8\x91\x98\x46\xfc\xc9\x1b\x57\x5b\xea\xc8\x1a\x3b\x3f\xb0\x51\x98\x3c\x07\xda\x2c\x59\x01\xda\x8b\x44\xe8\xe1\x74\xfd\xa7\x68\xdd\x54\xba\x83\x46\xec\xc8\x46\xb5\xf8\xaf\x97\xc0\x3b\x09\x1c\x8f\xce\x72\x96\x3d\x33\x56\x70\xbc\x96\xcb\xd8\xd5\x7d\x20\x9a\x83\x9f\x1a\xdc\x39\xf1\xc5\x72\xa3\x11\x03\xfd\x3b\x42\x52\x29\xdb\xe8\x01\xf7\x9b\x5e\x8c\xd6\x8d\x86\x4e\x19\xfa\xbc\x1c\xbe\xc5\x21\xa5\x87\x9e\x78\x2e\x36\xdb\x09\x71\xa3\x72\x34\xf8\x6c\xe3\x06\x09\xf2\x5e\x56\xa5\xd3\xdd\x98\xfa\xd4\xe6\x06\xf4\xf0\xb6\x20\x63\x4b\xea\x29\xbd\xaa\x82\x66\x1e\xfb\x81\xaa\xa7\x37\xad\x13\x18\xe6\x92\xc3\x81\xc1\x33\xbb\x88\x1e\xa1\xe7\xe2\xb4\xbd\x31\x6c\x0e\x51\x3d\x6f\xfb\x96\x56\x80\xe2\x36\x17\xd1\xdc\xe4", 0 }, + /* Anchor: 148 tc_class_4_ii.cer serial: #{a.serial.to_s} + C=DE,O=TC TrustCenter GmbH,OU=TC TrustCenter Class 4 CA,CN=TC TrustCenter Class 4 CA II + */ + { 954, "\x30\x82\x03\xb6\x30\x82\x02\x9e\xa0\x03\x02\x01\x02\x02\x0e\x05\xc0\x00\x01\x00\x02\x41\xd0\x06\x0a\x4d\xce\x75\x10\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x76\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x47\x6d\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0b\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x43\x6c\x61\x73\x73\x20\x34\x20\x43\x41\x31\x25\x30\x23\x06\x03\x55\x04\x03\x13\x1c\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x43\x6c\x61\x73\x73\x20\x34\x20\x43\x41\x20\x49\x49\x30\x1e\x17\x0d\x30\x36\x30\x33\x32\x33\x31\x34\x31\x30\x32\x33\x5a\x17\x0d\x32\x35\x31\x32\x33\x31\x32\x32\x35\x39\x35\x39\x5a\x30\x76\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x47\x6d\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0b\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x43\x6c\x61\x73\x73\x20\x34\x20\x43\x41\x31\x25\x30\x23\x06\x03\x55\x04\x03\x13\x1c\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x43\x6c\x61\x73\x73\x20\x34\x20\x43\x41\x20\x49\x49\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xb5\xcd\x4c\x9c\xad\xae\x51\xbb\x7c\x48\xc5\x0d\x29\x86\x7a\x14\xad\xd9\x50\x3d\x09\x72\x20\x0d\x14\xb6\x63\xc6\xfe\x58\x9e\xe0\x21\x5e\xf3\x8f\x22\x19\xdc\x4e\x91\x20\xcd\x6f\x88\x29\xa2\xb3\xc1\xac\x2a\x72\xba\x8b\x54\xb8\x40\x5f\xf2\xaa\xf8\x43\x86\xc2\x30\x5c\xcc\xa7\x5d\x7f\xc6\x08\x49\xe4\x0e\x39\x2f\x8e\x18\xd6\x91\xdd\x23\x16\x79\x80\xdb\x6c\x48\x1d\xbc\xc1\xdf\x28\x10\x63\xd1\x81\xe3\xdd\xdf\x2f\x79\x75\xa2\x1b\x78\xf2\x94\x01\xe6\x10\x62\x79\xcb\xa0\x7d\x02\xc0\x34\x82\x7b\xc7\xc0\xad\x1d\x4c\xd7\x6a\x96\x76\x5b\xbf\x26\x84\x48\xfd\x87\xf6\x84\x0a\xaa\x92\x07\x99\x48\x3c\x61\xbc\x4e\x85\x58\xc7\x97\x2d\xfd\x81\x4a\xa1\xc6\x9b\x12\xf5\x42\x50\xd1\x64\x3e\x89\x68\x82\x22\x70\xdd\xf5\xfa\xe3\x28\x42\x2f\x4e\x32\xf3\xb3\xa3\x36\x8a\x6a\xd6\x62\x5c\xac\xfa\x01\x6d\xb4\xe0\x72\x2e\x95\x68\xb4\xf1\x93\x0c\xc6\x8a\x82\xd2\x1d\x53\xea\x7c\xe0\x3f\x42\xb7\x12\x5a\xb8\xcd\xda\xa5\x06\x67\xcb\xa1\x77\x7d\xa5\x96\xf0\x92\x1e\x67\x0e\x1d\x42\x46\xe6\xf9\xed\xfb\x47\x53\x7f\x57\x04\x46\x1f\x46\x5f\xc7\xae\xe0\x8f\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x86\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x1f\xea\xbb\x3e\x25\x1b\x06\xbd\xa5\xdd\x62\x05\x7e\xc6\x4c\x5a\xbf\xe8\x0f\x43\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x58\xa4\x2b\x9b\x4c\xf7\xe4\xa4\x92\xa4\x9c\x65\x98\x19\x62\x22\xfc\x72\x32\xe9\x04\x5d\xc4\xc4\x70\x2d\x5a\x46\xde\x4c\x47\x8a\x25\xb9\xa2\xdd\xee\xea\x12\xaf\x48\x8d\xef\x2b\x67\xdb\x3b\xcc\x34\x98\x2a\xf7\x08\x47\xff\x22\xaf\x7b\xf1\xf4\xeb\xe2\x38\x02\x33\x18\x75\x28\x1b\x9e\x76\x65\xac\x88\x03\x72\xf2\x38\x47\x1d\x8c\xf5\x9f\x0a\x88\x53\x10\x14\xbb\x80\xe5\x0c\xb3\x5d\x8d\x17\xee\x1e\x19\x1c\x86\x8d\x14\x67\x78\x8c\x92\xcb\x1e\x21\x49\xf7\x7f\xd3\x18\xbf\x9c\x79\xf8\x5d\x08\x79\xb5\xaa\x6a\x4d\x92\x36\x6c\xbc\x79\xeb\x0e\x3d\x79\x8a\xd8\xf6\xa3\x56\x70\x5d\xde\xdb\x4f\x79\xd2\x7a\xd2\x95\x5c\x86\x27\x65\xbe\xa0\xd3\x07\x81\x40\x55\xdd\x10\xcb\xe0\x4b\x88\x82\xc0\x90\x7d\x38\xe7\xbf\x96\xe1\x97\xba\x9a\xab\x42\x0f\xd3\x9f\xd8\x9e\x15\x33\x11\xcb\xf7\x82\x79\xf5\xb5\xc0\x41\x56\x92\xe1\xdf\x55\x03\xad\x48\xcf\xd3\xf2\x2e\xb1\xc7\x2d\x56\x4c\x64\x74\x2a\x31\xce\xdc\x75\xa9\x54\x47\xa4\xa7\x42\x72\x09\xe7\xe1\x02\xa6\x47\xb2\x04\xcd\x42\x13\xe1\x61\x0c\xe0\x78\x3a\x22\x20\xa2\x1c\x60\x42\x86\x87\xf7\xa5\xe6", 0 }, + /* Anchor: 149 tc_Universal_CA-I.cer serial: #{a.serial.to_s} + C=DE,O=TC TrustCenter GmbH,OU=TC TrustCenter Universal CA,CN=TC TrustCenter Universal CA I + */ + { 993, "\x30\x82\x03\xdd\x30\x82\x02\xc5\xa0\x03\x02\x01\x02\x02\x0e\x1d\xa2\x00\x01\x00\x02\xec\xb7\x60\x80\x78\x8d\xb6\x06\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x79\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x47\x6d\x62\x48\x31\x24\x30\x22\x06\x03\x55\x04\x0b\x13\x1b\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x55\x6e\x69\x76\x65\x72\x73\x61\x6c\x20\x43\x41\x31\x26\x30\x24\x06\x03\x55\x04\x03\x13\x1d\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x55\x6e\x69\x76\x65\x72\x73\x61\x6c\x20\x43\x41\x20\x49\x30\x1e\x17\x0d\x30\x36\x30\x33\x32\x32\x31\x35\x35\x34\x32\x38\x5a\x17\x0d\x32\x35\x31\x32\x33\x31\x32\x32\x35\x39\x35\x39\x5a\x30\x79\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x47\x6d\x62\x48\x31\x24\x30\x22\x06\x03\x55\x04\x0b\x13\x1b\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x55\x6e\x69\x76\x65\x72\x73\x61\x6c\x20\x43\x41\x31\x26\x30\x24\x06\x03\x55\x04\x03\x13\x1d\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x55\x6e\x69\x76\x65\x72\x73\x61\x6c\x20\x43\x41\x20\x49\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xa4\x77\x23\x96\x44\xaf\x90\xf4\x31\xa7\x10\xf4\x26\x87\x9c\xf3\x38\xd9\x0f\x5e\xde\xcf\x41\xe8\x31\xad\xc6\x74\x91\x24\x96\x78\x1e\x09\xa0\x9b\x9a\x95\x4a\x4a\xf5\x62\x7c\x02\xa8\xca\xac\xfb\x5a\x04\x76\x39\xde\x5f\xf1\xf9\xb3\xbf\xf3\x03\x58\x55\xd2\xaa\xb7\xe3\x04\x22\xd1\xf8\x94\xda\x22\x08\x00\x8d\xd3\x7c\x26\x5d\xcc\x77\x79\xe7\x2c\x78\x39\xa8\x26\x73\x0e\xa2\x5d\x25\x69\x85\x4f\x55\x0e\x9a\xef\xc6\xb9\x44\xe1\x57\x3d\xdf\x1f\x54\x22\xe5\x6f\x65\xaa\x33\x84\x3a\xf3\xce\x7a\xbe\x55\x97\xae\x8d\x12\x0f\x14\x33\xe2\x50\x70\xc3\x49\x87\x13\xbc\x51\xde\xd7\x98\x12\x5a\xef\x3a\x83\x33\x92\x06\x75\x8b\x92\x7c\x12\x68\x7b\x70\x6a\x0f\xb5\x9b\xb6\x77\x5b\x48\x59\x9d\xe4\xef\x5a\xad\xf3\xc1\x9e\xd4\xd7\x45\x4e\xca\x56\x34\x21\xbc\x3e\x17\x5b\x6f\x77\x0c\x48\x01\x43\x29\xb0\xdd\x3f\x96\x6e\xe6\x95\xaa\x0c\xc0\x20\xb6\xfd\x3e\x36\x27\x9c\xe3\x5c\xcf\x4e\x81\xdc\x19\xbb\x91\x90\x7d\xec\xe6\x97\x04\x1e\x93\xcc\x22\x49\xd7\x97\x86\xb6\x13\x0a\x3c\x43\x23\x77\x7e\xf0\xdc\xe6\xcd\x24\x1f\x3b\x83\x9b\x34\x3a\x83\x34\xe3\x02\x03\x01\x00\x01\xa3\x63\x30\x61\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x92\xa4\x75\x2c\xa4\x9e\xbe\x81\x44\xeb\x79\xfc\x8a\xc5\x95\xa5\xeb\x10\x75\x73\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x86\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x92\xa4\x75\x2c\xa4\x9e\xbe\x81\x44\xeb\x79\xfc\x8a\xc5\x95\xa5\xeb\x10\x75\x73\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x28\xd2\xe0\x86\xd5\xe6\xf8\x7b\xf0\x97\xdc\x22\x6b\x3b\x95\x14\x56\x0f\x11\x30\xa5\x9a\x4f\x3a\xb0\x3a\xe0\x06\xcb\x65\xf5\xed\xc6\x97\x27\xfe\x25\xf2\x57\xe6\x5e\x95\x8c\x3e\x64\x60\x15\x5a\x7f\x2f\x0d\x01\xc5\xb1\x60\xfd\x45\x35\xcf\xf0\xb2\xbf\x06\xd9\xef\x5a\xbe\xb3\x62\x21\xb4\xd7\xab\x35\x7c\x53\x3e\xa6\x27\xf1\xa1\x2d\xda\x1a\x23\x9d\xcc\xdd\xec\x3c\x2d\x9e\x27\x34\x5d\x0f\xc2\x36\x79\xbc\xc9\x4a\x62\x2d\xed\x6b\xd9\x7d\x41\x43\x7c\xb6\xaa\xca\xed\x61\xb1\x37\x82\x15\x09\x1a\x8a\x16\x30\xd8\xec\xc9\xd6\x47\x72\x78\x4b\x10\x46\x14\x8e\x5f\x0e\xaf\xec\xc7\x2f\xab\x10\xd7\xb6\xf1\x6e\xec\x86\xb2\xc2\xe8\x0d\x92\x73\xdc\xa2\xf4\x0f\x3a\xbf\x61\x23\x10\x89\x9c\x48\x40\x6e\x70\x00\xb3\xd3\xba\x37\x44\x58\x11\x7a\x02\x6a\x88\xf0\x37\x34\xf0\x19\xe9\xac\xd4\x65\x73\xf6\x69\x8c\x64\x94\x3a\x79\x85\x29\xb0\x16\x2b\x0c\x82\x3f\x06\x9c\xc7\xfd\x10\x2b\x9e\x0f\x2c\xb6\x9e\xe3\x15\xbf\xd9\x36\x1c\xba\x25\x1a\x52\x3d\x1a\xec\x22\x0c\x1c\xe0\xa4\xa2\x3d\xf0\xe8\x39\xcf\x81\xc0\x7b\xed\x5d\x1f\x6f\xc5\xd0\x0b\xd7\x98", 0 }, + /* Anchor: 150 tc_Universal_CA-II.cer serial: #{a.serial.to_s} + C=DE,O=TC TrustCenter GmbH,OU=TC TrustCenter Universal CA,CN=TC TrustCenter Universal CA II + */ + { 1507, "\x30\x82\x05\xdf\x30\x82\x03\xc7\xa0\x03\x02\x01\x02\x02\x0e\x19\x33\x00\x01\x00\x02\x28\x1a\x9a\x04\xbc\xf2\x55\x45\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x7a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x47\x6d\x62\x48\x31\x24\x30\x22\x06\x03\x55\x04\x0b\x13\x1b\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x55\x6e\x69\x76\x65\x72\x73\x61\x6c\x20\x43\x41\x31\x27\x30\x25\x06\x03\x55\x04\x03\x13\x1e\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x55\x6e\x69\x76\x65\x72\x73\x61\x6c\x20\x43\x41\x20\x49\x49\x30\x1e\x17\x0d\x30\x36\x30\x33\x32\x32\x31\x35\x35\x38\x33\x34\x5a\x17\x0d\x33\x30\x31\x32\x33\x31\x32\x32\x35\x39\x35\x39\x5a\x30\x7a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x47\x6d\x62\x48\x31\x24\x30\x22\x06\x03\x55\x04\x0b\x13\x1b\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x55\x6e\x69\x76\x65\x72\x73\x61\x6c\x20\x43\x41\x31\x27\x30\x25\x06\x03\x55\x04\x03\x13\x1e\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x55\x6e\x69\x76\x65\x72\x73\x61\x6c\x20\x43\x41\x20\x49\x49\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\x8b\xd4\x77\x6b\x34\x6c\xe5\x36\xd8\x6a\x5c\x5e\x38\xee\xfc\xd5\x1d\x79\x03\x3b\x7b\x83\x62\x44\x82\x4e\x88\xed\xde\x83\xff\xee\xcc\x50\x62\x05\x05\x95\x99\x76\x98\xf6\xb9\xf2\x5f\xd8\x06\x91\x92\xc2\xf6\x2d\x66\x17\x1f\xfd\x53\x03\xe8\xa8\x8d\x63\xa9\x6e\xe1\xd6\x1b\x8c\xbc\x98\xb3\x8b\x3b\xd4\xe4\x2e\xca\x7d\x85\x49\x26\x5b\x79\xb8\x1a\x8b\x40\x9e\x7f\xbb\xc9\x3f\x63\x2c\xcf\xd1\x5a\x7c\xba\x28\x22\x41\x12\x5a\x4d\xf9\x17\x77\xfc\x85\xfd\xc2\x49\xe0\x2a\x18\x7f\xe9\xa0\x2c\x9c\xf9\x44\xfc\x0c\x68\x39\x42\xf5\x27\x05\xbe\x8e\x15\x7a\x60\x9d\xf0\x3b\xc7\x3c\xe6\x3e\x16\xbc\xaf\x76\xde\x6a\xb7\xa2\xe1\xab\x46\x45\xeb\x8c\x65\x7d\xd1\x97\xf3\x97\x11\x25\xab\x59\xeb\xa0\x22\xd9\x82\xdd\x98\xed\x7e\xe2\xfa\xa0\x61\x0a\x4a\x32\xde\x2c\x17\xf7\x6d\x44\xea\x81\x47\x59\x97\x57\x37\x03\x39\xdd\x5e\x82\x22\xd4\x33\xb8\xfa\x26\x09\xb6\xbc\x39\x88\x2f\x51\x15\x4e\x9b\xc3\x3b\xdf\x13\x82\x88\xdd\x4b\x34\xf2\x33\xd6\x90\xe9\xf3\x53\xdc\x35\x7c\xc0\xc3\xd9\x7c\x78\xb3\xcd\x70\x3f\x8d\x6a\xe0\xa3\x81\x48\xe4\x29\xad\x63\xb8\xf0\xfc\x28\x64\x3b\x99\xb3\x7d\xfe\x9a\x9d\x88\xf6\x99\x22\x08\x91\x47\x16\x89\x35\x78\x5d\x77\xa1\xcf\xbf\x49\xe1\xfd\x24\x94\x2b\x69\x36\x7b\xe8\x1c\xe6\x2a\x90\x8a\x5b\xd5\x3b\x34\x59\x42\xdc\x6d\xcf\xbb\x0f\x41\x1c\x55\xcd\xf5\x0d\x5b\x2e\x16\x22\x26\xef\x61\x1e\x97\xfc\xe2\x53\xc8\xcf\x5b\xa3\xc7\xa9\xf1\xba\x0e\x86\x12\xcb\x13\xca\x15\xc7\xec\xe4\x36\x8d\xda\x5c\x13\x3d\x65\xd2\x0e\x5d\x70\x74\xdc\xbf\x8f\x7a\x6a\xc1\x2e\x0f\xd3\xc6\x5e\x0f\x2b\x59\x6c\xcc\x61\x6c\xfe\xc0\x61\x4e\xd9\xe6\x4f\x46\xb2\x5a\xe2\x19\x14\x70\x84\xf8\x20\x00\xed\x01\xa7\x97\x7e\xc3\xbd\x12\x5c\x92\x23\x17\xa0\xa5\x1d\x45\x17\x15\x23\x9a\x92\x08\xb5\x22\x88\x8d\xdc\x2b\x24\xeb\xe0\xb1\x17\x68\xd3\xaf\x61\xbd\xd9\x85\x78\xf6\x8d\xba\x78\xca\x37\x8d\x63\xbe\xe7\xac\x1f\xdf\xa5\x47\x09\xb9\xc8\x25\x31\x54\x46\x51\x11\x55\x0d\x89\x5c\x8d\xda\xd2\x18\x2d\x73\xf2\xb8\xd5\x27\xf5\x48\x22\x37\xd1\x62\xf7\x7b\x0d\xc8\x38\x8b\xa1\x4a\xb0\xfc\xd0\xf1\xeb\xb7\x86\x63\xe7\xe0\x0e\x73\x7f\xfd\x72\x51\xb5\xe9\x7d\xe2\x55\x05\x64\x78\x67\x7f\x02\x03\x01\x00\x01\xa3\x63\x30\x61\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\xcd\xd7\x90\xa1\x6e\xa3\xbf\xdb\x30\xd6\xda\x32\x25\x90\x0c\xe6\x39\x1e\x80\x65\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x86\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xcd\xd7\x90\xa1\x6e\xa3\xbf\xdb\x30\xd6\xda\x32\x25\x90\x0c\xe6\x39\x1e\x80\x65\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x7e\x16\x88\xe8\x13\x0e\x36\xcc\x6e\x2a\x85\x07\x38\xc6\x56\x89\x7a\xe3\x47\x21\x66\x4c\x50\x08\x31\x5a\x51\xd0\xfc\xa6\x5e\x14\x75\xde\x4c\x3b\xec\xf1\xed\xcc\x7e\x11\x07\x4a\x61\xee\xea\xb3\x8e\x3a\xa4\x33\xc6\xed\x8a\x42\x66\x4f\xf1\x3c\x7b\xc9\xa5\x05\x41\x99\xb1\xec\x2c\x5b\xee\xdc\x96\xd2\x88\x53\x4b\x78\x34\xb9\x6e\xe6\xbb\x0f\xc5\x7a\xa6\x7c\x0e\x18\xdf\x6f\x0f\x74\x4c\xd1\xa9\xf1\xa1\xe9\xd8\x54\x64\xcc\x5e\x96\x78\xa2\x56\x1a\xc1\x73\xb2\x15\xc6\x57\x05\xdf\xda\xf7\x48\x24\x8a\x8e\x7f\x6a\xa9\xf9\x4d\xe9\x3e\x6a\xce\x60\x2c\x7d\x2d\x90\x08\xf6\x63\x8f\x15\xd0\x2d\x9c\x8c\xff\xf1\xfd\xfc\x0c\x16\x50\x56\x14\xfb\xba\x97\x86\xee\xb4\x49\x03\x54\xee\x1b\x59\x7f\x30\x3a\x02\x82\x86\x21\xae\xfe\xf0\x15\xf2\xdf\x4e\x83\xe6\x99\xc5\xba\x35\xf7\x20\x90\x8c\x38\xed\x75\xcf\xe1\x2e\xf7\x04\x30\xfb\x51\xad\x8e\x82\x24\x40\xca\x7d\x29\x5d\xd5\xd9\xf7\x65\x64\xfc\xaa\x9f\x74\xb8\x7d\x92\x5d\xd2\x84\x29\xe0\x13\xea\x8a\xf7\xd0\xab\xc4\xae\xef\x15\xc5\xc2\x89\xf2\x7b\xb6\x3b\x49\x98\x61\xf3\x4e\x72\x91\x37\x8c\x49\x92\xe9\xc8\xec\x2a\xa0\xf7\x49\x6e\x7c\x0d\x24\xc6\x6b\x6c\xf2\x38\x2f\xca\x70\x05\xe5\x7f\xdf\xc6\x2b\x2b\x80\x80\xd5\xda\x6f\xcb\x40\xbb\xd8\x1b\xf0\x24\xc9\x10\xc8\x44\x02\x7e\x2e\xd3\x98\xaa\xa2\x0d\xf1\x2b\xd0\xda\xfa\x8e\x1c\xff\x54\xe8\xe1\x4a\x6e\xdd\xa8\xd6\x78\xb5\x37\xa5\xac\x64\xd5\x14\x23\xc7\x0e\xa5\xeb\xe1\x09\x38\xd7\xc0\x7c\x60\xa5\x5d\x98\x8f\x8c\x02\xd5\xdc\x56\xa8\xf3\x4d\x58\xa9\x0b\xd4\x7c\x64\x74\x01\x32\xf2\xdf\x0f\x4a\x8a\xa9\x02\xa2\xa2\x1d\x84\x77\xc2\xf1\xcc\x97\xbd\x34\x19\x74\x5d\xe2\x74\x3e\x75\x27\xf7\xaf\xbf\xee\x7c\x0e\x6d\x54\x88\xa6\x56\xe2\x26\xad\x31\x12\x3c\x1e\x41\x79\x6d\x17\xea\x13\x5e\x1f\xf5\x5c\x9f\x49\x59\xa3\xb2\x2f\xa3\x42\xc3\xfa\xa8\x7e\xbf\xa5\x9f\x48\xc9\x60\x62\x62\x0a\xdf\xbd\x45\xde\xe3\x42\xb5\x51\x96\xfd\xc4\xf5\x1a\x99\xb8\x52\xa2\x44\xcd\x2d\x61\x8c\x15\x8f\x81\xd5\x5d\xa2\xd4\x90\x3d\x8c\x6e\x40\x61\xc3\x59\x5d\xd8\xd9\xe1\xf6\x74\x47\x22\x79\x74\x7d\xda\xca\xa3\x6f\x37\x15\x36\xf0\x2c\x1a\x71\x3c\x11\x76\xdf\x5d\x1a\x3e\x54\x63\x78\x6b\x65\x7e\x1f", 0 }, + /* Anchor: 151 TDC_ocesca.cer serial: #{a.serial.to_s} + C=DK,O=TDC,CN=TDC OCES CA + */ + { 1309, "\x30\x82\x05\x19\x30\x82\x04\x01\xa0\x03\x02\x01\x02\x02\x04\x3e\x48\xbd\xc4\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x31\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4b\x31\x0c\x30\x0a\x06\x03\x55\x04\x0a\x13\x03\x54\x44\x43\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0b\x54\x44\x43\x20\x4f\x43\x45\x53\x20\x43\x41\x30\x1e\x17\x0d\x30\x33\x30\x32\x31\x31\x30\x38\x33\x39\x33\x30\x5a\x17\x0d\x33\x37\x30\x32\x31\x31\x30\x39\x30\x39\x33\x30\x5a\x30\x31\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4b\x31\x0c\x30\x0a\x06\x03\x55\x04\x0a\x13\x03\x54\x44\x43\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0b\x54\x44\x43\x20\x4f\x43\x45\x53\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xac\x62\xf6\x61\x20\xb2\xcf\xc0\xc6\x85\xd7\xe3\x79\xe6\xcc\xed\xf2\x39\x92\xa4\x97\x2e\x64\xa3\x84\x5b\x87\x9c\x4c\xfd\xa4\xf3\xc4\x5f\x21\xbd\x56\x10\xeb\xdb\x2e\x61\xec\x93\x69\xe3\xa3\xcc\xbd\x99\xc3\x05\xfc\x06\xb8\xca\x36\x1c\xfe\x90\x8e\x49\x4c\xc4\x56\x9a\x2f\x56\xbc\xcf\x7b\x0c\xf1\x6f\x47\xa6\x0d\x43\x4d\xe2\xe9\x1d\x39\x34\xcd\x8d\x2c\xd9\x12\x98\xf9\xe3\xe1\xc1\x4a\x7c\x86\x38\xc4\xa9\xc4\x61\x88\xd2\x5e\xaf\x1a\x26\x4d\xd5\xe4\xa0\x22\x47\x84\xd9\x64\xb7\x19\x96\xfc\xec\x19\xe4\xb2\x97\x26\x4e\x4a\x4c\xcb\x8f\x24\x8b\x54\x18\x1c\x48\x61\x7b\xd5\x88\x68\xda\x5d\xb5\xea\xcd\x1a\x30\xc1\x80\x83\x76\x50\xaa\x4f\xd1\xd4\xdd\x38\xf0\xef\x16\xf4\xe1\x0c\x50\x06\xbf\xea\xfb\x7a\x49\xa1\x28\x2b\x1c\xf6\xfc\x15\x32\xa3\x74\x6a\x8f\xa9\xc3\x62\x29\x71\x31\xe5\x3b\xa4\x60\x17\x5e\x74\xe6\xda\x13\xed\xe9\x1f\x1f\x1b\xd1\xb2\x68\x73\xc6\x10\x34\x75\x46\x10\x10\xe3\x90\x00\x76\x40\xcb\x8b\xb7\x43\x09\x21\xff\xab\x4e\x93\xc6\x58\xe9\xa5\x82\xdb\x77\xc4\x3a\x99\xb1\x72\x95\x49\x04\xf0\xb7\x2b\xfa\x7b\x59\x8e\xdd\x02\x03\x01\x00\x01\xa3\x82\x02\x37\x30\x82\x02\x33\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x81\xec\x06\x03\x55\x1d\x20\x04\x81\xe4\x30\x81\xe1\x30\x81\xde\x06\x08\x2a\x81\x50\x81\x29\x01\x01\x01\x30\x81\xd1\x30\x2f\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x23\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x63\x65\x72\x74\x69\x66\x69\x6b\x61\x74\x2e\x64\x6b\x2f\x72\x65\x70\x6f\x73\x69\x74\x6f\x72\x79\x30\x81\x9d\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x02\x30\x81\x90\x30\x0a\x16\x03\x54\x44\x43\x30\x03\x02\x01\x01\x1a\x81\x81\x43\x65\x72\x74\x69\x66\x69\x6b\x61\x74\x65\x72\x20\x66\x72\x61\x20\x64\x65\x6e\x6e\x65\x20\x43\x41\x20\x75\x64\x73\x74\x65\x64\x65\x73\x20\x75\x6e\x64\x65\x72\x20\x4f\x49\x44\x20\x31\x2e\x32\x2e\x32\x30\x38\x2e\x31\x36\x39\x2e\x31\x2e\x31\x2e\x31\x2e\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x73\x20\x66\x72\x6f\x6d\x20\x74\x68\x69\x73\x20\x43\x41\x20\x61\x72\x65\x20\x69\x73\x73\x75\x65\x64\x20\x75\x6e\x64\x65\x72\x20\x4f\x49\x44\x20\x31\x2e\x32\x2e\x32\x30\x38\x2e\x31\x36\x39\x2e\x31\x2e\x31\x2e\x31\x2e\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x81\x81\x06\x03\x55\x1d\x1f\x04\x7a\x30\x78\x30\x48\xa0\x46\xa0\x44\xa4\x42\x30\x40\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4b\x31\x0c\x30\x0a\x06\x03\x55\x04\x0a\x13\x03\x54\x44\x43\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0b\x54\x44\x43\x20\x4f\x43\x45\x53\x20\x43\x41\x31\x0d\x30\x0b\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4c\x31\x30\x2c\xa0\x2a\xa0\x28\x86\x26\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x6f\x63\x65\x73\x2e\x63\x65\x72\x74\x69\x66\x69\x6b\x61\x74\x2e\x64\x6b\x2f\x6f\x63\x65\x73\x2e\x63\x72\x6c\x30\x2b\x06\x03\x55\x1d\x10\x04\x24\x30\x22\x80\x0f\x32\x30\x30\x33\x30\x32\x31\x31\x30\x38\x33\x39\x33\x30\x5a\x81\x0f\x32\x30\x33\x37\x30\x32\x31\x31\x30\x39\x30\x39\x33\x30\x5a\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x60\xb5\x85\xec\x56\x64\x7e\x12\x19\x27\x67\x1d\x50\x15\x4b\x73\xae\x3b\xf9\x12\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x60\xb5\x85\xec\x56\x64\x7e\x12\x19\x27\x67\x1d\x50\x15\x4b\x73\xae\x3b\xf9\x12\x30\x1d\x06\x09\x2a\x86\x48\x86\xf6\x7d\x07\x41\x00\x04\x10\x30\x0e\x1b\x08\x56\x36\x2e\x30\x3a\x34\x2e\x30\x03\x02\x04\x90\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x0a\xba\x26\x26\x46\xd3\x73\xa8\x09\xf3\x6b\x0b\x30\x99\xfd\x8a\xe1\x57\x7a\x11\xd3\xb8\x94\xd7\x09\x10\x6e\xa3\xb1\x38\x03\xd1\xb6\xf2\x43\x41\x29\x62\xa7\x72\xd8\xfb\x7c\x05\xe6\x31\x70\x27\x54\x18\x4e\x8a\x7c\x4e\xe5\xd1\xca\x8c\x78\x88\xcf\x1b\xd3\x90\x8b\xe6\x23\xf8\x0b\x0e\x33\x43\x7d\x9c\xe2\x0a\x19\x8f\xc9\x01\x3e\x74\x5d\x74\xc9\x8b\x1c\x03\xe5\x18\xc8\x01\x4c\x3f\xcb\x97\x05\x5d\x98\x71\xa6\x98\x6f\xb6\x7c\xbd\x37\x7f\xbe\xe1\x93\x25\x6d\x6f\xf0\x0a\xad\x17\x18\xe1\x03\xbc\x07\x29\xc8\xad\x26\xe8\xf8\x61\xf0\xfd\x21\x09\x7e\x9a\x8e\xa9\x68\x7d\x48\x62\x72\xbd\x00\xea\x01\x99\xb8\x06\x82\x51\x81\x4e\xf1\xf5\xb4\x91\x54\xb9\x23\x7a\x00\x9a\x9f\x5d\x8d\xe0\x3c\x64\xb9\x1a\x12\x92\x2a\xc7\x82\x44\x72\x39\xdc\xe2\x3c\xc6\xd8\x55\xf5\x15\x4e\xc8\x05\x0e\xdb\xc6\xd0\x62\xa6\xec\x15\xb4\xb5\x02\x82\xdb\xac\x8c\xa2\x81\xf0\x9b\x99\x31\xf5\x20\x20\xa8\x88\x61\x0a\x07\x9f\x94\xfc\xd0\xd7\x1b\xcc\x2e\x17\xf3\x04\x27\x76\x67\xeb\x54\x83\xfd\xa4\x90\x7e\x06\x3d\x04\xa3\x43\x2d\xda\xfc\x0b\x62\xea\x2f\x5f\x62\x53", 0 }, + /* Anchor: 152 TDC_rootca.cer serial: #{a.serial.to_s} + C=DK,O=TDC Internet,OU=TDC Internet Root CA + */ + { 1071, "\x30\x82\x04\x2b\x30\x82\x03\x13\xa0\x03\x02\x01\x02\x02\x04\x3a\xcc\xa5\x4c\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x43\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4b\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x13\x0c\x54\x44\x43\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x31\x1d\x30\x1b\x06\x03\x55\x04\x0b\x13\x14\x54\x44\x43\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x1e\x17\x0d\x30\x31\x30\x34\x30\x35\x31\x36\x33\x33\x31\x37\x5a\x17\x0d\x32\x31\x30\x34\x30\x35\x31\x37\x30\x33\x31\x37\x5a\x30\x43\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4b\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x13\x0c\x54\x44\x43\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x31\x1d\x30\x1b\x06\x03\x55\x04\x0b\x13\x14\x54\x44\x43\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xc4\xb8\x40\xbc\x91\xd5\x63\x1f\xd7\x99\xa0\x8b\x0c\x40\x1e\x74\xb7\x48\x9d\x46\x8c\x02\xb2\xe0\x24\x5f\xf0\x19\x13\xa7\x37\x83\x6b\x5d\xc7\x8e\xf9\x84\x30\xce\x1a\x3b\xfa\xfb\xce\x8b\x6d\x23\xc6\xc3\x6e\x66\x9f\x89\xa5\xdf\xe0\x42\x50\x67\xfa\x1f\x6c\x1e\xf4\xd0\x05\xd6\xbf\xca\xd6\x4e\xe4\x68\x60\x6c\x46\xaa\x1c\x5d\x63\xe1\x07\x86\x0e\x65\x00\xa7\x2e\xa6\x71\xc6\xbc\xb9\x81\xa8\x3a\x7d\x1a\xd2\xf9\xd1\xac\x4b\xcb\xce\x75\xaf\xdc\x7b\xfa\x81\x73\xd4\xfc\xba\xbd\x41\x88\xd4\x74\xb3\xf9\x5e\x38\x3a\x3c\x43\xa8\xd2\x95\x4e\x77\x6d\x13\x0c\x9d\x8f\x78\x01\xb7\x5a\x20\x1f\x03\x37\x35\xe2\x2c\xdb\x4b\x2b\x2c\x78\xb9\x49\xdb\xc4\xd0\xc7\x9c\x9c\xe4\x8a\x20\x09\x21\x16\x56\x66\xff\x05\xec\x5b\xe3\xf0\xcf\xab\x24\x24\x5e\xc3\x7f\x70\x7a\x12\xc4\xd2\xb5\x10\xa0\xb6\x21\xe1\x8d\x78\x69\x55\x44\x69\xf5\xca\x96\x1c\x34\x85\x17\x25\x77\xe2\xf6\x2f\x27\x98\x78\xfd\x79\x06\x3a\xa2\xd6\x5a\x43\xc1\xff\xec\x04\x3b\xee\x13\xef\xd3\x58\x5a\xff\x92\xeb\xec\xae\xda\xf2\x37\x03\x47\x41\xb6\x97\xc9\x2d\x0a\x41\x22\xbb\xbb\xe6\xa7\x02\x03\x01\x00\x01\xa3\x82\x01\x25\x30\x82\x01\x21\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x65\x06\x03\x55\x1d\x1f\x04\x5e\x30\x5c\x30\x5a\xa0\x58\xa0\x56\xa4\x54\x30\x52\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4b\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x13\x0c\x54\x44\x43\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x31\x1d\x30\x1b\x06\x03\x55\x04\x0b\x13\x14\x54\x44\x43\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x52\x6f\x6f\x74\x20\x43\x41\x31\x0d\x30\x0b\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4c\x31\x30\x2b\x06\x03\x55\x1d\x10\x04\x24\x30\x22\x80\x0f\x32\x30\x30\x31\x30\x34\x30\x35\x31\x36\x33\x33\x31\x37\x5a\x81\x0f\x32\x30\x32\x31\x30\x34\x30\x35\x31\x37\x30\x33\x31\x37\x5a\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x06\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x6c\x64\x01\xc7\xfd\x85\x6d\xac\xc8\xda\x9e\x50\x08\x85\x08\xb5\x3c\x56\xa8\x50\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x6c\x64\x01\xc7\xfd\x85\x6d\xac\xc8\xda\x9e\x50\x08\x85\x08\xb5\x3c\x56\xa8\x50\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x09\x2a\x86\x48\x86\xf6\x7d\x07\x41\x00\x04\x10\x30\x0e\x1b\x08\x56\x35\x2e\x30\x3a\x34\x2e\x30\x03\x02\x04\x90\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x4e\x43\xcc\xd1\xdd\x1d\x10\x1b\x06\x7f\xb7\xa4\xfa\xd3\xd9\x4d\xfb\x23\x9f\x23\x54\x5b\xe6\x8b\x2f\x04\x28\x8b\xb5\x27\x6d\x89\xa1\xec\x98\x69\xdc\xe7\x8d\x26\x83\x05\x79\x74\xec\xb4\xb9\xa3\x97\xc1\x35\x00\xfd\x15\xda\x39\x81\x3a\x95\x31\x90\xde\x97\xe9\x86\xa8\x99\x77\x0c\xe5\x5a\xa0\x84\xff\x12\x16\xac\x6e\xb8\x8d\xc3\x7b\x92\xc2\xac\x2e\xd0\x7d\x28\xec\xb6\xf3\x60\x38\x69\x6f\x3e\xd8\x04\x55\x3e\x9e\xcc\x55\xd2\xba\xfe\xbb\x47\x04\xd7\x0a\xd9\x16\x0a\x34\x29\xf5\x58\x13\xd5\x4f\xcf\x8f\x56\x4b\xb3\x1e\xee\xd3\x98\x79\xda\x08\x1e\x0c\x6f\xb8\xf8\x16\x27\xef\xc2\x6f\x3d\xf6\xa3\x4b\x3e\x0e\xe4\x6d\x6c\xdb\x3b\x41\x12\x9b\xbd\x0d\x47\x23\x7f\x3c\x4a\xd0\xaf\xc0\xaf\xf6\xef\x1b\xb5\x15\xc4\xeb\x83\xc4\x09\x5f\x74\x8b\xd9\x11\xfb\xc2\x56\xb1\x3c\xf8\x70\xca\x34\x8d\x43\x40\x13\x8c\xfd\x99\x03\x54\x79\xc6\x2e\xea\x86\xa1\xf6\x3a\xd4\x09\xbc\xf4\xbc\x66\xcc\x3d\x58\xd0\x57\x49\x0a\xee\x25\xe2\x41\xee\x13\xf9\x9b\x38\x34\xd1\x00\xf5\x7e\xe7\x94\x1d\xfc\x69\x03\x62\xb8\x99\x05\x05\x3d\x6b\x78\x12\xbd\xb0\x6f\x65", 0 }, + /* Anchor: 153 thawte-primary-root-ca.crt serial: #{a.serial.to_s} + C=US,O=thawte\, Inc.,OU=Certification Services Division,OU=(c) 2006 thawte\, Inc. - For authorized use only,CN=thawte Primary Root CA + */ + { 1060, "\x30\x82\x04\x20\x30\x82\x03\x08\xa0\x03\x02\x01\x02\x02\x10\x34\x4e\xd5\x57\x20\xd5\xed\xec\x49\xf4\x2f\xce\x37\xdb\x2b\x6d\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xa9\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x13\x0c\x74\x68\x61\x77\x74\x65\x2c\x20\x49\x6e\x63\x2e\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x38\x30\x36\x06\x03\x55\x04\x0b\x13\x2f\x28\x63\x29\x20\x32\x30\x30\x36\x20\x74\x68\x61\x77\x74\x65\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x1f\x30\x1d\x06\x03\x55\x04\x03\x13\x16\x74\x68\x61\x77\x74\x65\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x1e\x17\x0d\x30\x36\x31\x31\x31\x37\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x33\x36\x30\x37\x31\x36\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xa9\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x13\x0c\x74\x68\x61\x77\x74\x65\x2c\x20\x49\x6e\x63\x2e\x31\x28\x30\x26\x06\x03\x55\x04\x0b\x13\x1f\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6f\x6e\x31\x38\x30\x36\x06\x03\x55\x04\x0b\x13\x2f\x28\x63\x29\x20\x32\x30\x30\x36\x20\x74\x68\x61\x77\x74\x65\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x1f\x30\x1d\x06\x03\x55\x04\x03\x13\x16\x74\x68\x61\x77\x74\x65\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xac\xa0\xf0\xfb\x80\x59\xd4\x9c\xc7\xa4\xcf\x9d\xa1\x59\x73\x09\x10\x45\x0c\x0d\x2c\x6e\x68\xf1\x6c\x5b\x48\x68\x49\x59\x37\xfc\x0b\x33\x19\xc2\x77\x7f\xcc\x10\x2d\x95\x34\x1c\xe6\xeb\x4d\x09\xa7\x1c\xd2\xb8\xc9\x97\x36\x02\xb7\x89\xd4\x24\x5f\x06\xc0\xcc\x44\x94\x94\x8d\x02\x62\x6f\xeb\x5a\xdd\x11\x8d\x28\x9a\x5c\x84\x90\x10\x7a\x0d\xbd\x74\x66\x2f\x6a\x38\xa0\xe2\xd5\x54\x44\xeb\x1d\x07\x9f\x07\xba\x6f\xee\xe9\xfd\x4e\x0b\x29\xf5\x3e\x84\xa0\x01\xf1\x9c\xab\xf8\x1c\x7e\x89\xa4\xe8\xa1\xd8\x71\x65\x0d\xa3\x51\x7b\xee\xbc\xd2\x22\x60\x0d\xb9\x5b\x9d\xdf\xba\xfc\x51\x5b\x0b\xaf\x98\xb2\xe9\x2e\xe9\x04\xe8\x62\x87\xde\x2b\xc8\xd7\x4e\xc1\x4c\x64\x1e\xdd\xcf\x87\x58\xba\x4a\x4f\xca\x68\x07\x1d\x1c\x9d\x4a\xc6\xd5\x2f\x91\xcc\x7c\x71\x72\x1c\xc5\xc0\x67\xeb\x32\xfd\xc9\x92\x5c\x94\xda\x85\xc0\x9b\xbf\x53\x7d\x2b\x09\xf4\x8c\x9d\x91\x1f\x97\x6a\x52\xcb\xde\x09\x36\xa4\x77\xd8\x7b\x87\x50\x44\xd5\x3e\x6e\x29\x69\xfb\x39\x49\x26\x1e\x09\xa5\x80\x7b\x40\x2d\xeb\xe8\x27\x85\xc9\xfe\x61\xfd\x7e\xe6\x7c\x97\x1d\xd5\x9d\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x7b\x5b\x45\xcf\xaf\xce\xcb\x7a\xfd\x31\x92\x1a\x6a\xb6\xf3\x46\xeb\x57\x48\x50\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x79\x11\xc0\x4b\xb3\x91\xb6\xfc\xf0\xe9\x67\xd4\x0d\x6e\x45\xbe\x55\xe8\x93\xd2\xce\x03\x3f\xed\xda\x25\xb0\x1d\x57\xcb\x1e\x3a\x76\xa0\x4c\xec\x50\x76\xe8\x64\x72\x0c\xa4\xa9\xf1\xb8\x8b\xd6\xd6\x87\x84\xbb\x32\xe5\x41\x11\xc0\x77\xd9\xb3\x60\x9d\xeb\x1b\xd5\xd1\x6e\x44\x44\xa9\xa6\x01\xec\x55\x62\x1d\x77\xb8\x5c\x8e\x48\x49\x7c\x9c\x3b\x57\x11\xac\xad\x73\x37\x8e\x2f\x78\x5c\x90\x68\x47\xd9\x60\x60\xe6\xfc\x07\x3d\x22\x20\x17\xc4\xf7\x16\xe9\xc4\xd8\x72\xf9\xc8\x73\x7c\xdf\x16\x2f\x15\xa9\x3e\xfd\x6a\x27\xb6\xa1\xeb\x5a\xba\x98\x1f\xd5\xe3\x4d\x64\x0a\x9d\x13\xc8\x61\xba\xf5\x39\x1c\x87\xba\xb8\xbd\x7b\x22\x7f\xf6\xfe\xac\x40\x79\xe5\xac\x10\x6f\x3d\x8f\x1b\x79\x76\x8b\xc4\x37\xb3\x21\x18\x84\xe5\x36\x00\xeb\x63\x20\x99\xb9\xe9\xfe\x33\x04\xbb\x41\xc8\xc1\x02\xf9\x44\x63\x20\x9e\x81\xce\x42\xd3\xd6\x3f\x2c\x76\xd3\x63\x9c\x59\xdd\x8f\xa6\xe1\x0e\xa0\x2e\x41\xf7\x2e\x95\x47\xcf\xbc\xfd\x33\xf3\xf6\x0b\x61\x7e\x7e\x91\x2b\x81\x47\xc2\x27\x30\xee\xa7\x10\x5d\x37\x8f\x5c\x39\x2b\xe4\x04\xf0\x7b\x8d\x56\x8c\x68", 0 }, + /* Anchor: 154 thawte_Primary_Root_CA_G2_ECC.cer serial: #{a.serial.to_s} + C=US,O=thawte\, Inc.,OU=(c) 2007 thawte\, Inc. - For authorized use only,CN=thawte Primary Root CA - G2 + */ + { 652, "\x30\x82\x02\x88\x30\x82\x02\x0d\xa0\x03\x02\x01\x02\x02\x10\x35\xfc\x26\x5c\xd9\x84\x4f\xc9\x3d\x26\x3d\x57\x9b\xae\xd7\x56\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x03\x30\x81\x84\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x13\x0c\x74\x68\x61\x77\x74\x65\x2c\x20\x49\x6e\x63\x2e\x31\x38\x30\x36\x06\x03\x55\x04\x0b\x13\x2f\x28\x63\x29\x20\x32\x30\x30\x37\x20\x74\x68\x61\x77\x74\x65\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1b\x74\x68\x61\x77\x74\x65\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x2d\x20\x47\x32\x30\x1e\x17\x0d\x30\x37\x31\x31\x30\x35\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x33\x38\x30\x31\x31\x38\x32\x33\x35\x39\x35\x39\x5a\x30\x81\x84\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0a\x13\x0c\x74\x68\x61\x77\x74\x65\x2c\x20\x49\x6e\x63\x2e\x31\x38\x30\x36\x06\x03\x55\x04\x0b\x13\x2f\x28\x63\x29\x20\x32\x30\x30\x37\x20\x74\x68\x61\x77\x74\x65\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1b\x74\x68\x61\x77\x74\x65\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x52\x6f\x6f\x74\x20\x43\x41\x20\x2d\x20\x47\x32\x30\x76\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04\x00\x22\x03\x62\x00\x04\xa2\xd5\x9c\x82\x7b\x95\x9d\xf1\x52\x78\x87\xfe\x8a\x16\xbf\x05\xe6\xdf\xa3\x02\x4f\x0d\x07\xc6\x00\x51\xba\x0c\x02\x52\x2d\x22\xa4\x42\x39\xc4\xfe\x8f\xea\xc9\xc1\xbe\xd4\x4d\xff\x9f\x7a\x9e\xe2\xb1\x7c\x9a\xad\xa7\x86\x09\x73\x87\xd1\xe7\x9a\xe3\x7a\xa5\xaa\x6e\xfb\xba\xb3\x70\xc0\x67\x88\xa2\x35\xd4\xa3\x9a\xb1\xfd\xad\xc2\xef\x31\xfa\xa8\xb9\xf3\xfb\x08\xc6\x91\xd1\xfb\x29\x95\xa3\x42\x30\x40\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x9a\xd8\x00\x30\x00\xe7\x6b\x7f\x85\x18\xee\x8b\xb6\xce\x8a\x0c\xf8\x11\xe1\xbb\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x03\x03\x69\x00\x30\x66\x02\x31\x00\xdd\xf8\xe0\x57\x47\x5b\xa7\xe6\x0a\xc3\xbd\xf5\x80\x8a\x97\x35\x0d\x1b\x89\x3c\x54\x86\x77\x28\xca\xa1\xf4\x79\xde\xb5\xe6\x38\xb0\xf0\x65\x70\x8c\x7f\x02\x54\xc2\xbf\xff\xd8\xa1\x3e\xd9\xcf\x02\x31\x00\xc4\x8d\x94\xfc\xdc\x53\xd2\xdc\x9d\x78\x16\x1f\x15\x33\x23\x53\x52\xe3\x5a\x31\x5d\x9d\xca\xae\xbd\x13\x29\x44\x0d\x27\x5b\xa8\xe7\x68\x9c\x12\xf7\x58\x3f\x2e\x72\x02\x57\xa3\x8f\xa1\x14\x2e", 0 }, + /* Anchor: 155 Thawte_Timestamping_CA.cer serial: #{a.serial.to_s} + C=ZA,ST=Western Cape,L=Durbanville,O=Thawte,OU=Thawte Certification,CN=Thawte Timestamping CA + */ + { 692, "\x30\x82\x02\xb0\x30\x82\x02\x19\xa0\x03\x02\x01\x02\x02\x10\x67\xc8\xe1\xe8\xe3\xbe\x1c\xbd\xfc\x91\x3b\x8e\xa6\x23\x87\x49\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\x8b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x14\x30\x12\x06\x03\x55\x04\x07\x13\x0b\x44\x75\x72\x62\x61\x6e\x76\x69\x6c\x6c\x65\x31\x0f\x30\x0d\x06\x03\x55\x04\x0a\x13\x06\x54\x68\x61\x77\x74\x65\x31\x1d\x30\x1b\x06\x03\x55\x04\x0b\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x31\x1f\x30\x1d\x06\x03\x55\x04\x03\x13\x16\x54\x68\x61\x77\x74\x65\x20\x54\x69\x6d\x65\x73\x74\x61\x6d\x70\x69\x6e\x67\x20\x43\x41\x30\x1e\x17\x0d\x39\x37\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x31\x30\x31\x30\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x81\x8b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5a\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0c\x57\x65\x73\x74\x65\x72\x6e\x20\x43\x61\x70\x65\x31\x14\x30\x12\x06\x03\x55\x04\x07\x13\x0b\x44\x75\x72\x62\x61\x6e\x76\x69\x6c\x6c\x65\x31\x0f\x30\x0d\x06\x03\x55\x04\x0a\x13\x06\x54\x68\x61\x77\x74\x65\x31\x1d\x30\x1b\x06\x03\x55\x04\x0b\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x31\x1f\x30\x1d\x06\x03\x55\x04\x03\x13\x16\x54\x68\x61\x77\x74\x65\x20\x54\x69\x6d\x65\x73\x74\x61\x6d\x70\x69\x6e\x67\x20\x43\x41\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd6\x2b\x58\x78\x61\x45\x86\x53\xea\x34\x7b\x51\x9c\xed\xb0\xe6\x2e\x18\x0e\xfe\xe0\x5f\xa8\x27\xd3\xb4\xc9\xe0\x7c\x59\x4e\x16\x0e\x73\x54\x60\xc1\x7f\xf6\x9f\x2e\xe9\x3a\x85\x24\x15\x3c\xdb\x47\x04\x63\xc3\x9e\xc4\x94\x1a\x5a\xdf\x4c\x7a\xf3\xd9\x43\x1d\x3c\x10\x7a\x79\x25\xdb\x90\xfe\xf0\x51\xe7\x30\xd6\x41\x00\xfd\x9f\x28\xdf\x79\xbe\x94\xbb\x9d\xb6\x14\xe3\x23\x85\xd7\xa9\x41\xe0\x4c\xa4\x79\xb0\x2b\x1a\x8b\xf2\xf8\x3b\x8a\x3e\x45\xac\x71\x92\x00\xb4\x90\x41\x98\xfb\x5f\xed\xfa\xb7\x2e\x8a\xf8\x88\x37\x02\x03\x01\x00\x01\xa3\x13\x30\x11\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x4b\xe9\xaa\x17\x81\x05\xfb\x79\x0a\x31\x9f\xc5\x41\xf4\x56\x54\xab\xe9\xc2\xe5\x97\x8e\x18\xfe\x91\xc9\x0c\x3e\x26\x64\xc9\xa1\x4c\x27\x64\xa7\xbd\x01\x93\x55\x71\x6e\x17\x4f\x39\xdc\x1b\xdc\x49\x35\x10\x39\x23\xff\xca\x9b\xc8\xcf\x66\x3f\xdc\x4c\x1a\xd4\x81\x06\x42\x52\x1f\xe1\x26\xb1\x16\x17\xba\xe6\x70\x72\x31\x44\xe8\x4e\x8d\x5b\xe4\xd3\xf9\xd0\xe3\x8f\x25\x64\x31\xe7\x2a\xf8\x18\x88\x36\x1a\x52\xc5\x0d\x41\x35\x1b\x69\xb7\x26\xf5\x17\xcc\xc1\x19\x5e\x4b\x7c\x5c\xe2\x83\x80\x91\xfa\x2f\xfb\x9a\xb7\x16", 0 }, + /* Anchor: 156 trustCenter-root-5.der serial: #{a.serial.to_s} + C=DE,O=TC TrustCenter GmbH,OU=TC TrustCenter Universal CA,CN=TC TrustCenter Universal CA III + */ + { 997, "\x30\x82\x03\xe1\x30\x82\x02\xc9\xa0\x03\x02\x01\x02\x02\x0e\x63\x25\x00\x01\x00\x02\x14\x8d\x33\x15\x02\xe4\x6c\xf4\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x7b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x47\x6d\x62\x48\x31\x24\x30\x22\x06\x03\x55\x04\x0b\x13\x1b\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x55\x6e\x69\x76\x65\x72\x73\x61\x6c\x20\x43\x41\x31\x28\x30\x26\x06\x03\x55\x04\x03\x13\x1f\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x55\x6e\x69\x76\x65\x72\x73\x61\x6c\x20\x43\x41\x20\x49\x49\x49\x30\x1e\x17\x0d\x30\x39\x30\x39\x30\x39\x30\x38\x31\x35\x32\x37\x5a\x17\x0d\x32\x39\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5a\x30\x7b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x47\x6d\x62\x48\x31\x24\x30\x22\x06\x03\x55\x04\x0b\x13\x1b\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x55\x6e\x69\x76\x65\x72\x73\x61\x6c\x20\x43\x41\x31\x28\x30\x26\x06\x03\x55\x04\x03\x13\x1f\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6e\x74\x65\x72\x20\x55\x6e\x69\x76\x65\x72\x73\x61\x6c\x20\x43\x41\x20\x49\x49\x49\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xc2\xda\x9c\x62\xb0\xb9\x71\x12\xb0\x0b\xc8\x1a\x57\xb2\xae\x83\x14\x99\xb3\x34\x4b\x9b\x90\xa2\xc5\xe7\xe7\x2f\x02\xa0\x4d\x2d\xa4\xfa\x85\xda\x9b\x25\x85\x2d\x40\x28\x20\x6d\xea\xe0\xbd\xb1\x48\x83\x22\x29\x44\x9f\x4e\x83\xee\x35\x51\x13\x73\x74\xd5\xbc\xf2\x30\x66\x94\x53\xc0\x40\x36\x2f\x0c\x84\x65\xce\x0f\x6e\xc2\x58\x93\xe8\x2c\x0b\x3a\xe9\xc1\x8e\xfb\xf2\x6b\xca\x3c\xe2\x9c\x4e\x8e\xe4\xf9\x7d\xd3\x27\x9f\x1b\xd5\x67\x78\x87\x2d\x7f\x0b\x47\xb3\xc7\xe8\xc9\x48\x7c\xaf\x2f\xcc\x0a\xd9\x41\xef\x9f\xfe\x9a\xe1\xb2\xae\xf9\x53\xb5\xe5\xe9\x46\x9f\x60\xe3\xdf\x8d\xd3\x7f\xfb\x96\x7e\xb3\xb5\x72\xf8\x4b\xad\x08\x79\xcd\x69\x89\x40\x27\xf5\x2a\xc1\xad\x43\xec\xa4\x53\xc8\x61\xb6\xf7\xd2\x79\x2a\x67\x18\x76\x48\x6d\x5b\x25\x01\xd1\x26\xc5\xb7\x57\x69\x23\x15\x5b\x61\x8a\xad\xf0\x1b\x2d\xd9\xaf\x5c\xf1\x26\x90\x69\xa9\xd5\x0c\x40\xf5\x33\x80\x43\x8f\x9c\xa3\x76\x2a\x45\xb4\xaf\xbf\x7f\x3e\x87\x3f\x76\xc5\xcd\x2a\xde\x20\xc5\x16\x58\xcb\xf9\x1b\xf5\x0f\xcb\x0d\x11\x52\x64\xb8\xd2\x76\x62\x77\x83\xf1\x58\x9f\xff\x02\x03\x01\x00\x01\xa3\x63\x30\x61\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x56\xe7\xe1\x5b\x25\x43\x80\xe0\xf6\x8c\xe1\x71\xbc\x8e\xe5\x80\x2f\xc4\x48\xe2\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x56\xe7\xe1\x5b\x25\x43\x80\xe0\xf6\x8c\xe1\x71\xbc\x8e\xe5\x80\x2f\xc4\x48\xe2\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x83\xc7\xaf\xea\x7f\x4d\x0a\x3c\x39\xb1\x68\xbe\x7b\x6d\x89\x2e\xe9\xb3\x09\xe7\x18\x57\x8d\x85\x9a\x17\xf3\x76\x42\x50\x13\x0f\xc7\x90\x6f\x33\xad\xc5\x49\x60\x2b\x6c\x49\x58\x19\xd4\xe2\xbe\xb7\xbf\xab\x49\xbc\x94\xc8\xab\xbe\x28\x6c\x16\x68\xe0\xc8\x97\x46\x20\xa0\x68\x67\x60\x88\x39\x20\x51\xd8\x68\x01\x11\xce\xa7\xf6\x11\x07\xf6\xec\xec\xac\x1a\x1f\xb2\x66\x6e\x56\x67\x60\x7a\x74\x5e\xc0\x6d\x97\x36\xae\xb5\x0d\x5d\x66\x73\xc0\x25\x32\x45\xd8\x4a\x06\x07\x8f\xc4\xb7\x07\xb1\x4d\x06\x0d\xe1\xa5\xeb\xf4\x75\xca\xba\x9c\xd0\xbd\xb3\xd3\x32\x24\x4c\xee\x7e\xe2\x76\x04\x4b\x49\x53\xd8\xf2\xe9\x54\x33\xfc\xe5\x71\x1f\x3d\x14\x5c\x96\x4b\xf1\x3a\xf2\x00\xbb\x6c\xb4\xfa\x96\x55\x08\x88\x09\xc1\xcc\x91\x19\x29\xb0\x20\x2d\xff\xcb\x38\xa4\x40\xe1\x17\xbe\x79\x61\x80\xff\x07\x03\x86\x4c\x4e\x7b\x06\x9f\x11\x86\x8d\x89\xee\x27\xc4\xdb\xe2\xbc\x19\x8e\x0b\xc3\xc3\x13\xc7\x2d\x03\x63\x3b\xd3\xe8\xe4\xa2\x2a\xc2\x82\x08\x94\x16\x54\xf0\xef\x1f\x27\x90\x25\xb8\x0d\x0e\x28\x1b\x47\x77\x47\xbd\x1c\xa8\x25\xf1\x94\xb4\x66", 0 }, + /* Anchor: 157 TrustisFPSRootCA.der serial: #{a.serial.to_s} + C=GB,O=Trustis Limited,OU=Trustis FPS Root CA + */ + { 875, "\x30\x82\x03\x67\x30\x82\x02\x4f\xa0\x03\x02\x01\x02\x02\x10\x1b\x1f\xad\xb6\x20\xf9\x24\xd3\x36\x6b\xf7\xc7\xf1\x8c\xa0\x59\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x45\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x18\x30\x16\x06\x03\x55\x04\x0a\x13\x0f\x54\x72\x75\x73\x74\x69\x73\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x1c\x30\x1a\x06\x03\x55\x04\x0b\x13\x13\x54\x72\x75\x73\x74\x69\x73\x20\x46\x50\x53\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x1e\x17\x0d\x30\x33\x31\x32\x32\x33\x31\x32\x31\x34\x30\x36\x5a\x17\x0d\x32\x34\x30\x31\x32\x31\x31\x31\x33\x36\x35\x34\x5a\x30\x45\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x18\x30\x16\x06\x03\x55\x04\x0a\x13\x0f\x54\x72\x75\x73\x74\x69\x73\x20\x4c\x69\x6d\x69\x74\x65\x64\x31\x1c\x30\x1a\x06\x03\x55\x04\x0b\x13\x13\x54\x72\x75\x73\x74\x69\x73\x20\x46\x50\x53\x20\x52\x6f\x6f\x74\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xc5\x50\x7b\x9e\x3b\x35\xd0\xdf\xc4\x8c\xcd\x8e\x9b\xed\xa3\xc0\x36\x99\xf4\x42\xea\xa7\x3e\x80\x83\x0f\xa6\xa7\x59\x87\xc9\x90\x45\x43\x7e\x00\xea\x86\x79\x2a\x03\xbd\x3d\x37\x99\x89\x66\xb7\xe5\x8a\x56\x86\x93\x9c\x68\x4b\x68\x04\x8c\x93\x93\x02\x3e\x30\xd2\x37\x3a\x22\x61\x89\x1c\x85\x4e\x7d\x8f\xd5\xaf\x7b\x35\xf6\x7e\x28\x47\x89\x31\xdc\x0e\x79\x64\x1f\x99\xd2\x5b\xba\xfe\x7f\x60\xbf\xad\xeb\xe7\x3c\x38\x29\x6a\x2f\xe5\x91\x0b\x55\xff\xec\x6f\x58\xd5\x2d\xc9\xde\x4c\x66\x71\x8f\x0c\xd7\x04\xda\x07\xe6\x1e\x18\xe3\xbd\x29\x02\xa8\xfa\x1c\xe1\x5b\xb9\x83\xa8\x41\x48\xbc\x1a\x71\x8d\xe7\x62\xe5\x2d\xb2\xeb\xdf\x7c\xcf\xdb\xab\x5a\xca\x31\xf1\x4c\x22\xf3\x05\x13\xf7\x82\xf9\x73\x79\x0c\xbe\xd7\x4b\x1c\xc0\xd1\x15\x3c\x93\x41\x64\xd1\xe6\xbe\x23\x17\x22\x00\x89\x5e\x1f\x6b\xa5\xac\x6e\xa7\x4b\x8c\xed\xa3\x72\xe6\xaf\x63\x4d\x2f\x85\xd2\x14\x35\x9a\x2e\x4e\x8c\xea\x32\x98\x28\x86\xa1\x91\x09\x41\x3a\xb4\xe1\xe3\xf2\xfa\xf0\xc9\x0a\xa2\x41\xdd\xa9\xe3\x03\xc7\x88\x15\x3b\x1c\xd4\x1a\x94\xd7\x9f\x64\x59\x12\x6d\x02\x03\x01\x00\x01\xa3\x53\x30\x51\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\xba\xfa\x71\x25\x79\x8b\x57\x41\x25\x21\x86\x0b\x71\xeb\xb2\x64\x0e\x8b\x21\x67\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xba\xfa\x71\x25\x79\x8b\x57\x41\x25\x21\x86\x0b\x71\xeb\xb2\x64\x0e\x8b\x21\x67\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x7e\x58\xff\xfd\x35\x19\x7d\x9c\x18\x4f\x9e\xb0\x2b\xbc\x8e\x8c\x14\xff\x2c\xa0\xda\x47\x5b\xc3\xef\x81\x2d\xaf\x05\xea\x74\x48\x5b\xf3\x3e\x4e\x07\xc7\x6d\xc5\xb3\x93\xcf\x22\x35\x5c\xb6\x3f\x75\x27\x5f\x09\x96\xcd\xa0\xfe\xbe\x40\x0c\x5c\x12\x55\xf8\x93\x82\xca\x29\xe9\x5e\x3f\x56\x57\x8b\x38\x36\xf7\x45\x1a\x4c\x28\xcd\x9e\x41\xb8\xed\x56\x4c\x84\xa4\x40\xc8\xb8\xb0\xa5\x2b\x69\x70\x04\x6a\xc3\xf8\xd4\x12\x32\xf9\x0e\xc3\xb1\xdc\x32\x84\x44\x2c\x6f\xcb\x46\x0f\xea\x66\x41\x0f\x4f\xf1\x58\xa5\xa6\x0d\x0d\x0f\x61\xde\xa5\x9e\x5d\x7d\x65\xa1\x3c\x17\xe7\xa8\x55\x4e\xef\xa0\xc7\xed\xc6\x44\x7f\x54\xf5\xa3\xe0\x8f\xf0\x7c\x55\x22\x8f\x29\xb6\x81\xa3\xe1\x6d\x4e\x2c\x1b\x80\x67\xec\xad\x20\x9f\x0c\x62\x61\xd5\x97\xff\x43\xed\x2d\xc1\xda\x5d\x29\x2a\x85\x3f\xac\x65\xee\x86\x0f\x05\x8d\x90\x5f\xdf\xee\x9f\xf4\xbf\xee\x1d\xfb\x98\xe4\x7f\x90\x2b\x84\x78\x10\x0e\x6c\x49\x53\xef\x15\x5b\x65\x46\x4a\x5d\xaf\xba\xfb\x3a\x72\x1d\xcd\xf6\x25\x88\x1e\x97\xcc\x21\x9c\x29\x01\x0d\x65\xeb\x57\xd9\xf3\x57\x96\xbb\x48\xcd\x81", 0 }, + /* Anchor: 158 Trustwave-SGCA.der serial: #{a.serial.to_s} + C=US,O=SecureTrust Corporation,CN=Secure Global CA + */ + { 960, "\x30\x82\x03\xbc\x30\x82\x02\xa4\xa0\x03\x02\x01\x02\x02\x10\x07\x56\x22\xa4\xe8\xd4\x8a\x89\x4d\xf4\x13\xc8\xf0\xf8\xea\xa5\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x4a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1e\x06\x03\x55\x04\x0a\x13\x17\x53\x65\x63\x75\x72\x65\x54\x72\x75\x73\x74\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x53\x65\x63\x75\x72\x65\x20\x47\x6c\x6f\x62\x61\x6c\x20\x43\x41\x30\x1e\x17\x0d\x30\x36\x31\x31\x30\x37\x31\x39\x34\x32\x32\x38\x5a\x17\x0d\x32\x39\x31\x32\x33\x31\x31\x39\x35\x32\x30\x36\x5a\x30\x4a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1e\x06\x03\x55\x04\x0a\x13\x17\x53\x65\x63\x75\x72\x65\x54\x72\x75\x73\x74\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x53\x65\x63\x75\x72\x65\x20\x47\x6c\x6f\x62\x61\x6c\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xaf\x35\x2e\xd8\xac\x6c\x55\x69\x06\x71\xe5\x13\x68\x24\xb3\x4f\xd8\xcc\x21\x47\xf8\xf1\x60\x38\x89\x89\x03\xe9\xbd\xea\x5e\x46\x53\x09\xdc\x5c\xf5\x5a\xe8\xf7\x45\x2a\x02\xeb\x31\x61\xd7\x29\x33\x4c\xce\xc7\x7c\x0a\x37\x7e\x0f\xba\x32\x98\xe1\x1d\x97\xaf\x8f\xc7\xdc\xc9\x38\x96\xf3\xdb\x1a\xfc\x51\xed\x68\xc6\xd0\x6e\xa4\x7c\x24\xd1\xae\x42\xc8\x96\x50\x63\x2e\xe0\xfe\x75\xfe\x98\xa7\x5f\x49\x2e\x95\xe3\x39\x33\x64\x8e\x1e\xa4\x5f\x90\xd2\x67\x3c\xb2\xd9\xfe\x41\xb9\x55\xa7\x09\x8e\x72\x05\x1e\x8b\xdd\x44\x85\x82\x42\xd0\x49\xc0\x1d\x60\xf0\xd1\x17\x2c\x95\xeb\xf6\xa5\xc1\x92\xa3\xc5\xc2\xa7\x08\x60\x0d\x60\x04\x10\x96\x79\x9e\x16\x34\xe6\xa9\xb6\xfa\x25\x45\x39\xc8\x1e\x65\xf9\x93\xf5\xaa\xf1\x52\xdc\x99\x98\x3d\xa5\x86\x1a\x0c\x35\x33\xfa\x4b\xa5\x04\x06\x15\x1c\x31\x80\xef\xaa\x18\x6b\xc2\x7b\xd7\xda\xce\xf9\x33\x20\xd5\xf5\xbd\x6a\x33\x2d\x81\x04\xfb\xb0\x5c\xd4\x9c\xa3\xe2\x5c\x1d\xe3\xa9\x42\x75\x5e\x7b\xd4\x77\xef\x39\x54\xba\xc9\x0a\x18\x1b\x12\x99\x49\x2f\x88\x4b\xfd\x50\x62\xd1\x73\xe7\x8f\x7a\x43\x02\x03\x01\x00\x01\xa3\x81\x9d\x30\x81\x9a\x30\x13\x06\x09\x2b\x06\x01\x04\x01\x82\x37\x14\x02\x04\x06\x1e\x04\x00\x43\x00\x41\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x86\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xaf\x44\x04\xc2\x41\x7e\x48\x83\xdb\x4e\x39\x02\xec\xec\x84\x7a\xe6\xce\xc9\xa4\x30\x34\x06\x03\x55\x1d\x1f\x04\x2d\x30\x2b\x30\x29\xa0\x27\xa0\x25\x86\x23\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x73\x65\x63\x75\x72\x65\x74\x72\x75\x73\x74\x2e\x63\x6f\x6d\x2f\x53\x47\x43\x41\x2e\x63\x72\x6c\x30\x10\x06\x09\x2b\x06\x01\x04\x01\x82\x37\x15\x01\x04\x03\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x63\x1a\x08\x40\x7d\xa4\x5e\x53\x0d\x77\xd8\x7a\xae\x1f\x0d\x0b\x51\x16\x03\xef\x18\x7c\xc8\xe3\xaf\x6a\x58\x93\x14\x60\x91\xb2\x84\xdc\x88\x4e\xbe\x39\x8a\x3a\xf3\xe6\x82\x89\x5d\x01\x37\xb3\xab\x24\xa4\x15\x0e\x92\x35\x5a\x4a\x44\x5e\x4e\x57\xfa\x75\xce\x1f\x48\xce\x66\xf4\x3c\x40\x26\x92\x98\x6c\x1b\xee\x24\x46\x0c\x17\xb3\x52\xa5\xdb\xa5\x91\x91\xcf\x37\xd3\x6f\xe7\x27\x08\x3a\x4e\x19\x1f\x3a\xa7\x58\x5c\x17\xcf\x79\x3f\x8b\xe4\xa7\xd3\x26\x23\x9d\x26\x0f\x58\x69\xfc\x47\x7e\xb2\xd0\x8d\x8b\x93\xbf\x29\x4f\x43\x69\x74\x76\x67\x4b\xcf\x07\x8c\xe6\x02\xf7\xb5\xe1\xb4\x43\xb5\x4b\x2d\x14\x9f\xf9\xdc\x26\x0d\xbf\xa6\x47\x74\x06\xd8\x88\xd1\x3a\x29\x30\x84\xce\xd2\x39\x80\x62\x1b\xa8\xc7\x57\x49\xbc\x6a\x55\x51\x67\x15\x4a\xbe\x35\x07\xe4\xd5\x75\x98\x37\x79\x30\x14\xdb\x29\x9d\x6c\xc5\x69\xcc\x47\x55\xa2\x30\xf7\xcc\x5c\x7f\xc2\xc3\x98\x1c\x6b\x4e\x16\x80\xeb\x7a\x78\x65\x45\xa2\x00\x1a\xaf\x0c\x0d\x55\x64\x34\x48\xb8\x92\xb9\xf1\xb4\x50\x29\xf2\x4f\x23\x1f\xda\x6c\xac\x1f\x44\xe1\xdd\x23\x78\x51\x5b\xc7\x16", 0 }, + /* Anchor: 159 Trustwave-STCA.der serial: #{a.serial.to_s} + C=US,O=SecureTrust Corporation,CN=SecureTrust CA + */ + { 956, "\x30\x82\x03\xb8\x30\x82\x02\xa0\xa0\x03\x02\x01\x02\x02\x10\x0c\xf0\x8e\x5c\x08\x16\xa5\xad\x42\x7f\xf0\xeb\x27\x18\x59\xd0\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x48\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1e\x06\x03\x55\x04\x0a\x13\x17\x53\x65\x63\x75\x72\x65\x54\x72\x75\x73\x74\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0e\x53\x65\x63\x75\x72\x65\x54\x72\x75\x73\x74\x20\x43\x41\x30\x1e\x17\x0d\x30\x36\x31\x31\x30\x37\x31\x39\x33\x31\x31\x38\x5a\x17\x0d\x32\x39\x31\x32\x33\x31\x31\x39\x34\x30\x35\x35\x5a\x30\x48\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1e\x06\x03\x55\x04\x0a\x13\x17\x53\x65\x63\x75\x72\x65\x54\x72\x75\x73\x74\x20\x43\x6f\x72\x70\x6f\x72\x61\x74\x69\x6f\x6e\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0e\x53\x65\x63\x75\x72\x65\x54\x72\x75\x73\x74\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xab\xa4\x81\xe5\x95\xcd\xf5\xf6\x14\x8e\xc2\x4f\xca\xd4\xe2\x78\x95\x58\x9c\x41\xe1\x0d\x99\x40\x24\x17\x39\x91\x33\x66\xe9\xbe\xe1\x83\xaf\x62\x5c\x89\xd1\xfc\x24\x5b\x61\xb3\xe0\x11\x11\x41\x1c\x1d\x6e\xf0\xb8\xbb\xf8\xde\xa7\x81\xba\xa6\x48\xc6\x9f\x1d\xbd\xbe\x8e\xa9\x41\x3e\xb8\x94\xed\x29\x1a\xd4\x8e\xd2\x03\x1d\x03\xef\x6d\x0d\x67\x1c\x57\xd7\x06\xad\xca\xc8\xf5\xfe\x0e\xaf\x66\x25\x48\x04\x96\x0b\x5d\xa3\xba\x16\xc3\x08\x4f\xd1\x46\xf8\x14\x5c\xf2\xc8\x5e\x01\x99\x6d\xfd\x88\xcc\x86\xa8\xc1\x6f\x31\x42\x6c\x52\x3e\x68\xcb\xf3\x19\x34\xdf\xbb\x87\x18\x56\x80\x26\xc4\xd0\xdc\xc0\x6f\xdf\xde\xa0\xc2\x91\x16\xa0\x64\x11\x4b\x44\xbc\x1e\xf6\xe7\xfa\x63\xde\x66\xac\x76\xa4\x71\xa3\xec\x36\x94\x68\x7a\x77\xa4\xb1\xe7\x0e\x2f\x81\x7a\xe2\xb5\x72\x86\xef\xa2\x6b\x8b\xf0\x0f\xdb\xd3\x59\x3f\xba\x72\xbc\x44\x24\x9c\xe3\x73\xb3\xf7\xaf\x57\x2f\x42\x26\x9d\xa9\x74\xba\x00\x52\xf2\x4b\xcd\x53\x7c\x47\x0b\x36\x85\x0e\x66\xa9\x08\x97\x16\x34\x57\xc1\x66\xf7\x80\xe3\xed\x70\x54\xc7\x93\xe0\x2e\x28\x15\x59\x87\xba\xbb\x02\x03\x01\x00\x01\xa3\x81\x9d\x30\x81\x9a\x30\x13\x06\x09\x2b\x06\x01\x04\x01\x82\x37\x14\x02\x04\x06\x1e\x04\x00\x43\x00\x41\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x86\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x42\x32\xb6\x16\xfa\x04\xfd\xfe\x5d\x4b\x7a\xc3\xfd\xf7\x4c\x40\x1d\x5a\x43\xaf\x30\x34\x06\x03\x55\x1d\x1f\x04\x2d\x30\x2b\x30\x29\xa0\x27\xa0\x25\x86\x23\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x73\x65\x63\x75\x72\x65\x74\x72\x75\x73\x74\x2e\x63\x6f\x6d\x2f\x53\x54\x43\x41\x2e\x63\x72\x6c\x30\x10\x06\x09\x2b\x06\x01\x04\x01\x82\x37\x15\x01\x04\x03\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x30\xed\x4f\x4a\xe1\x58\x3a\x52\x72\x5b\xb5\xa6\xa3\x65\x18\xa6\xbb\x51\x3b\x77\xe9\x9d\xea\xd3\x9f\x5c\xe0\x45\x65\x7b\x0d\xca\x5b\xe2\x70\x50\xb2\x94\x05\x14\xae\x49\xc7\x8d\x41\x07\x12\x73\x94\x7e\x0c\x23\x21\xfd\xbc\x10\x7f\x60\x10\x5a\x72\xf5\x98\x0e\xac\xec\xb9\x7f\xdd\x7a\x6f\x5d\xd3\x1c\xf4\xff\x88\x05\x69\x42\xa9\x05\x71\xc8\xb7\xac\x26\xe8\x2e\xb4\x8c\x6a\xff\x71\xdc\xb8\xb1\xdf\x99\xbc\x7c\x21\x54\x2b\xe4\x58\xa2\xbb\x57\x29\xae\x9e\xa9\xa3\x19\x26\x0f\x99\x2e\x08\xb0\xef\xfd\x69\xcf\x99\x1a\x09\x8d\xe3\xa7\x9f\x2b\xc9\x36\x34\x7b\x24\xb3\x78\x4c\x95\x17\xa4\x06\x26\x1e\xb6\x64\x52\x36\x5f\x60\x67\xd9\x9c\xc5\x05\x74\x0b\xe7\x67\x23\xd2\x08\xfc\x88\xe9\xae\x8b\x7f\xe1\x30\xf4\x37\x7e\xfd\xc6\x32\xda\x2d\x9e\x44\x30\x30\x6c\xee\x07\xde\xd2\x34\xfc\xd2\xff\x40\xf6\x4b\xf4\x66\x46\x06\x54\xa6\xf2\x32\x0a\x63\x26\x30\x6b\x9b\xd1\xdc\x8b\x47\xba\xe1\xb9\xd5\x62\xd0\xa2\xa0\xf4\x67\x05\x78\x29\x63\x1a\x6f\x04\xd6\xf8\xc6\x4c\xa3\x9a\xb1\x37\xb4\x8d\xe5\x28\x4b\x1d\x9e\x2c\xc2\xb8\x68\xbc\xed\x02\xee\x31", 0 }, + /* Anchor: 160 TubitakSurum3.cer serial: #{a.serial.to_s} + C=TR,L=Gebze - Kocaeli,O=Türkiye Bilimsel ve Teknolojik Araştırma Kurumu - TÜBÄ°TAK,OU=Ulusal Elektronik ve Kriptoloji Araştırma Enstitüsü - UEKAE,OU=Kamu Sertifikasyon Merkezi,CN=TÜBÄ°TAK UEKAE Kök Sertifika Hizmet Sağlayıcısı - Sürüm 3 + */ + { 1307, "\x30\x82\x05\x17\x30\x82\x03\xff\xa0\x03\x02\x01\x02\x02\x01\x11\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x82\x01\x2b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x18\x30\x16\x06\x03\x55\x04\x07\x0c\x0f\x47\x65\x62\x7a\x65\x20\x2d\x20\x4b\x6f\x63\x61\x65\x6c\x69\x31\x47\x30\x45\x06\x03\x55\x04\x0a\x0c\x3e\x54\xc3\xbc\x72\x6b\x69\x79\x65\x20\x42\x69\x6c\x69\x6d\x73\x65\x6c\x20\x76\x65\x20\x54\x65\x6b\x6e\x6f\x6c\x6f\x6a\x69\x6b\x20\x41\x72\x61\xc5\x9f\x74\xc4\xb1\x72\x6d\x61\x20\x4b\x75\x72\x75\x6d\x75\x20\x2d\x20\x54\xc3\x9c\x42\xc4\xb0\x54\x41\x4b\x31\x48\x30\x46\x06\x03\x55\x04\x0b\x0c\x3f\x55\x6c\x75\x73\x61\x6c\x20\x45\x6c\x65\x6b\x74\x72\x6f\x6e\x69\x6b\x20\x76\x65\x20\x4b\x72\x69\x70\x74\x6f\x6c\x6f\x6a\x69\x20\x41\x72\x61\xc5\x9f\x74\xc4\xb1\x72\x6d\x61\x20\x45\x6e\x73\x74\x69\x74\xc3\xbc\x73\xc3\xbc\x20\x2d\x20\x55\x45\x4b\x41\x45\x31\x23\x30\x21\x06\x03\x55\x04\x0b\x0c\x1a\x4b\x61\x6d\x75\x20\x53\x65\x72\x74\x69\x66\x69\x6b\x61\x73\x79\x6f\x6e\x20\x4d\x65\x72\x6b\x65\x7a\x69\x31\x4a\x30\x48\x06\x03\x55\x04\x03\x0c\x41\x54\xc3\x9c\x42\xc4\xb0\x54\x41\x4b\x20\x55\x45\x4b\x41\x45\x20\x4b\xc3\xb6\x6b\x20\x53\x65\x72\x74\x69\x66\x69\x6b\x61\x20\x48\x69\x7a\x6d\x65\x74\x20\x53\x61\xc4\x9f\x6c\x61\x79\xc4\xb1\x63\xc4\xb1\x73\xc4\xb1\x20\x2d\x20\x53\xc3\xbc\x72\xc3\xbc\x6d\x20\x33\x30\x1e\x17\x0d\x30\x37\x30\x38\x32\x34\x31\x31\x33\x37\x30\x37\x5a\x17\x0d\x31\x37\x30\x38\x32\x31\x31\x31\x33\x37\x30\x37\x5a\x30\x82\x01\x2b\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x18\x30\x16\x06\x03\x55\x04\x07\x0c\x0f\x47\x65\x62\x7a\x65\x20\x2d\x20\x4b\x6f\x63\x61\x65\x6c\x69\x31\x47\x30\x45\x06\x03\x55\x04\x0a\x0c\x3e\x54\xc3\xbc\x72\x6b\x69\x79\x65\x20\x42\x69\x6c\x69\x6d\x73\x65\x6c\x20\x76\x65\x20\x54\x65\x6b\x6e\x6f\x6c\x6f\x6a\x69\x6b\x20\x41\x72\x61\xc5\x9f\x74\xc4\xb1\x72\x6d\x61\x20\x4b\x75\x72\x75\x6d\x75\x20\x2d\x20\x54\xc3\x9c\x42\xc4\xb0\x54\x41\x4b\x31\x48\x30\x46\x06\x03\x55\x04\x0b\x0c\x3f\x55\x6c\x75\x73\x61\x6c\x20\x45\x6c\x65\x6b\x74\x72\x6f\x6e\x69\x6b\x20\x76\x65\x20\x4b\x72\x69\x70\x74\x6f\x6c\x6f\x6a\x69\x20\x41\x72\x61\xc5\x9f\x74\xc4\xb1\x72\x6d\x61\x20\x45\x6e\x73\x74\x69\x74\xc3\xbc\x73\xc3\xbc\x20\x2d\x20\x55\x45\x4b\x41\x45\x31\x23\x30\x21\x06\x03\x55\x04\x0b\x0c\x1a\x4b\x61\x6d\x75\x20\x53\x65\x72\x74\x69\x66\x69\x6b\x61\x73\x79\x6f\x6e\x20\x4d\x65\x72\x6b\x65\x7a\x69\x31\x4a\x30\x48\x06\x03\x55\x04\x03\x0c\x41\x54\xc3\x9c\x42\xc4\xb0\x54\x41\x4b\x20\x55\x45\x4b\x41\x45\x20\x4b\xc3\xb6\x6b\x20\x53\x65\x72\x74\x69\x66\x69\x6b\x61\x20\x48\x69\x7a\x6d\x65\x74\x20\x53\x61\xc4\x9f\x6c\x61\x79\xc4\xb1\x63\xc4\xb1\x73\xc4\xb1\x20\x2d\x20\x53\xc3\xbc\x72\xc3\xbc\x6d\x20\x33\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\x8a\x6d\x4b\xff\x10\x88\x3a\xc3\xf6\x7e\x94\xe8\xea\x20\x64\x70\xae\x21\x81\xbe\x3a\x7b\x3c\xdb\xf1\x1d\x52\x7f\x59\xfa\xf3\x22\x4c\x95\xa0\x90\xbc\x48\x4e\x11\xab\xfb\xb7\xb5\x8d\x7a\x83\x28\x8c\x26\x46\xd8\x4e\x95\x40\x87\x61\x9f\xc5\x9e\x6d\x81\x87\x57\x6c\x8a\x3b\xb4\x66\xea\xcc\x40\xfc\xe3\xaa\x6c\xb2\xcb\x01\xdb\x32\xbf\xd2\xeb\x85\xcf\xa1\x0d\x55\xc3\x5b\x38\x57\x70\xb8\x75\xc6\x79\xd1\x14\x30\xed\x1b\x58\x5b\x6b\xef\x35\xf2\xa1\x21\x4e\xc5\xce\x7c\x99\x5f\x6c\xb9\xb8\x22\x93\x50\xa7\xcd\x4c\x70\x6a\xbe\x6a\x05\x7f\x13\x9c\x2b\x1e\xea\xfe\x47\xce\x04\xa5\x6f\xac\x93\x2e\x7c\x2b\x9f\x9e\x79\x13\x91\xe8\xea\x9e\xca\x38\x75\x8e\x62\xb0\x95\x93\x2a\xe5\xdf\xe9\x5e\x97\x6e\x20\x5f\x5f\x84\x7a\x44\x39\x19\x40\x1c\xba\x55\x2b\xfb\x30\xb2\x81\xef\x84\xe3\xdc\xec\x98\x38\x39\x03\x85\x08\xa9\x54\x03\x05\x29\xf0\xc9\x8f\x8b\xea\x0b\x86\x65\x19\x11\xd3\xe9\x09\x23\xde\x68\x93\x03\xc9\x36\x1c\x21\x6e\xce\x8c\x66\xf1\x99\x30\xd8\xd7\xb3\xc3\x1d\xf8\x81\x2e\xa8\xbd\x82\x0b\x66\xfe\x82\xcb\xe1\xe0\x1a\x82\xc3\x40\x81\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xbd\x88\x87\xc9\x8f\xf6\xa4\x0a\x0b\xaa\xeb\xc5\xfe\x91\x23\x9d\xab\x4a\x8a\x32\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x1d\x7c\xfa\x49\x8f\x34\xe9\xb7\x26\x92\x16\x9a\x05\x74\xe7\x4b\xd0\x6d\x39\x6c\xc3\x26\xf6\xce\xb8\x31\xbc\xc4\xdf\xbc\x2a\xf8\x37\x91\x18\xdc\x04\xc8\x64\x99\x2b\x18\x6d\x80\x03\x59\xc9\xae\xf8\x58\xd0\x3e\xed\xc3\x23\x9f\x69\x3c\x86\x38\x1c\x9e\xef\xda\x27\x78\xd1\x84\x37\x71\x8a\x3c\x4b\x39\xcf\x7e\x45\x06\xd6\x2d\xd8\x8a\x4d\x78\x12\xd6\xad\xc2\xd3\xcb\xd2\xd0\x41\xf3\x26\x36\x4a\x9b\x95\x6c\x0c\xee\xe5\xd1\x43\x27\x66\xc1\x88\xf7\x7a\xb3\x20\x6c\xea\xb0\x69\x2b\xc7\x20\xe8\x0c\x03\xc4\x41\x05\x99\xe2\x3f\xe4\x6b\xf8\xa0\x86\x81\xc7\x84\xc6\x1f\xd5\x4b\x81\x12\xb2\x16\x21\x2c\x13\xa1\x80\xb2\x5e\x0c\x4a\x13\x9e\x20\xd8\x62\x40\xab\x90\xea\x64\x4a\x2f\xac\x0d\x01\x12\x79\x45\xa8\x2f\x87\x19\x68\xc8\xe2\x85\xc7\x30\xb2\x75\xf9\x38\x3f\xb2\xc0\x93\xb4\x6b\xe2\x03\x44\xce\x67\xa0\xdf\x89\xd6\xad\x8c\x76\xa3\x13\xc3\x94\x61\x2b\x6b\xd9\x6c\xc1\x07\x0a\x22\x07\x85\x6c\x85\x24\x46\xa9\xbe\x3f\x8b\x78\x84\x82\x7e\x24\x0c\x9d\xfd\x81\x37\xe3\x25\xa8\xed\x36\x4e\x95\x2c\xc9\x9c\x90\xda\xec\xa9\x42\x3c\xad\xb6\x02", 0 }, + /* Anchor: 161 turktrust-root1.cer serial: #{a.serial.to_s} + CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı,C=TR,L=ANKARA,O=(c) 2005 TÜRKTRUST Bilgi Ä°letişim ve Bilişim Güvenliği Hizmetleri A.Ş. + */ + { 1023, "\x30\x82\x03\xfb\x30\x82\x02\xe3\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xb7\x31\x3f\x30\x3d\x06\x03\x55\x04\x03\x0c\x36\x54\xc3\x9c\x52\x4b\x54\x52\x55\x53\x54\x20\x45\x6c\x65\x6b\x74\x72\x6f\x6e\x69\x6b\x20\x53\x65\x72\x74\x69\x66\x69\x6b\x61\x20\x48\x69\x7a\x6d\x65\x74\x20\x53\x61\xc4\x9f\x6c\x61\x79\xc4\xb1\x63\xc4\xb1\x73\xc4\xb1\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x0c\x02\x54\x52\x31\x0f\x30\x0d\x06\x03\x55\x04\x07\x0c\x06\x41\x4e\x4b\x41\x52\x41\x31\x56\x30\x54\x06\x03\x55\x04\x0a\x0c\x4d\x28\x63\x29\x20\x32\x30\x30\x35\x20\x54\xc3\x9c\x52\x4b\x54\x52\x55\x53\x54\x20\x42\x69\x6c\x67\x69\x20\xc4\xb0\x6c\x65\x74\x69\xc5\x9f\x69\x6d\x20\x76\x65\x20\x42\x69\x6c\x69\xc5\x9f\x69\x6d\x20\x47\xc3\xbc\x76\x65\x6e\x6c\x69\xc4\x9f\x69\x20\x48\x69\x7a\x6d\x65\x74\x6c\x65\x72\x69\x20\x41\x2e\xc5\x9e\x2e\x30\x1e\x17\x0d\x30\x35\x30\x35\x31\x33\x31\x30\x32\x37\x31\x37\x5a\x17\x0d\x31\x35\x30\x33\x32\x32\x31\x30\x32\x37\x31\x37\x5a\x30\x81\xb7\x31\x3f\x30\x3d\x06\x03\x55\x04\x03\x0c\x36\x54\xc3\x9c\x52\x4b\x54\x52\x55\x53\x54\x20\x45\x6c\x65\x6b\x74\x72\x6f\x6e\x69\x6b\x20\x53\x65\x72\x74\x69\x66\x69\x6b\x61\x20\x48\x69\x7a\x6d\x65\x74\x20\x53\x61\xc4\x9f\x6c\x61\x79\xc4\xb1\x63\xc4\xb1\x73\xc4\xb1\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x0c\x02\x54\x52\x31\x0f\x30\x0d\x06\x03\x55\x04\x07\x0c\x06\x41\x4e\x4b\x41\x52\x41\x31\x56\x30\x54\x06\x03\x55\x04\x0a\x0c\x4d\x28\x63\x29\x20\x32\x30\x30\x35\x20\x54\xc3\x9c\x52\x4b\x54\x52\x55\x53\x54\x20\x42\x69\x6c\x67\x69\x20\xc4\xb0\x6c\x65\x74\x69\xc5\x9f\x69\x6d\x20\x76\x65\x20\x42\x69\x6c\x69\xc5\x9f\x69\x6d\x20\x47\xc3\xbc\x76\x65\x6e\x6c\x69\xc4\x9f\x69\x20\x48\x69\x7a\x6d\x65\x74\x6c\x65\x72\x69\x20\x41\x2e\xc5\x9e\x2e\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xca\x52\x05\xd6\x63\x03\xd8\x1c\x5f\xdd\xd2\x7b\x5d\xf2\x0c\x60\x61\x5b\x6b\x3b\x74\x2b\x78\x0d\x7d\x45\xbd\x22\x74\xe8\x8c\x03\xc1\xc6\x11\x2a\x3d\x95\xbc\xa9\x94\xb0\xbb\x91\x97\xc8\x69\x7c\x84\xc5\xb4\x91\x6c\x6c\x13\x6a\xa4\x55\xad\xa4\x85\xe8\x95\x7e\xb3\x00\xaf\x00\xc2\x05\x18\xf5\x70\x9d\x36\x8b\xae\xcb\xe4\x1b\x81\x7f\x93\x88\xfb\x6a\x55\xbb\x7d\x85\x92\xce\xba\x58\x9f\xdb\x32\xc5\xbd\x5d\xef\x22\x4a\x2f\x41\x07\x7e\x49\x61\xb3\x86\xec\x4e\xa6\x41\x6e\x84\xbc\x03\xec\xf5\x3b\x1c\xc8\x1f\xc2\xee\xa8\xee\xea\x12\x4a\x8d\x14\xcf\xf3\x0a\xe0\x50\x39\xf9\x08\x35\xf8\x11\x59\xad\xe7\x22\xea\x4b\xca\x14\x06\xde\x42\xba\xb2\x99\xf3\x2d\x54\x88\x10\x06\xea\xe1\x1a\x3e\x3d\x67\x1f\xfb\xce\xfb\x7c\x82\xe8\x11\x5d\x4a\xc1\xb9\x14\xea\x54\xd9\x66\x9b\x7c\x89\x7d\x04\x9a\x62\xc9\xe9\x52\x3c\x9e\x9c\xef\xd2\xf5\x26\xe4\xe6\xe5\x18\x7c\x8b\x6e\xdf\x6c\xcc\x78\x5b\x4f\x72\xb2\xcb\x5c\x3f\x8c\x05\x8d\xd1\x4c\x8c\xad\x92\xc7\xe1\x78\x7f\x65\x6c\x49\x06\x50\x2c\x9e\x32\xc2\xd7\x4a\xc6\x75\x8a\x59\x4e\x75\x6f\x47\x5e\xc1\x02\x03\x01\x00\x01\xa3\x10\x30\x0e\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x15\xf5\x55\xff\x37\x96\x80\x59\x21\xa4\xfc\xa1\x15\x4c\x20\xf6\xd4\x5f\xda\x03\x24\xfc\xcf\x90\x1a\xf4\x21\x0a\x9a\xee\x3a\xb1\x6a\xef\xef\xf8\x60\xd1\x4c\x36\x66\x45\x1d\xf3\x66\x02\x74\x04\x7b\x92\x30\xa8\xde\x0a\x76\x0f\xef\x95\x6e\xbd\xc9\x37\xe6\x1a\x0d\xac\x89\x48\x5b\xcc\x83\x36\xc2\xf5\x46\x5c\x59\x82\x56\xb4\xd5\xfe\x23\xb4\xd8\x54\x1c\x44\xab\xc4\xa7\xe5\x14\xce\x3c\x41\x61\x7c\x43\xe6\xcd\xc4\x81\x09\x8b\x24\xfb\x54\x25\xd6\x16\xa8\x96\x0c\x67\x07\x6f\xb3\x50\x47\xe3\x1c\x24\x28\xdd\x2a\x98\xa4\x61\xfe\xdb\xea\x12\x37\xbc\x01\x1a\x34\x85\xbd\x6e\x4f\xe7\x91\x72\x07\x44\x85\x1e\x58\xca\x54\x44\xdd\xf7\xac\xb9\xcb\x89\x21\x72\xdb\x8f\xc0\x69\x29\x97\x2a\xa3\xae\x18\x23\x97\x1c\x41\x2a\x8b\x7c\x2a\xc1\x7c\x90\xe8\xa9\x28\xc0\xd3\x91\xc6\xad\x28\x87\x40\x68\xb5\xff\xec\xa7\xd2\xd3\x38\x18\x9c\xd3\x7d\x69\x5d\xf0\xc6\xa5\x1e\x24\x1b\xa3\x47\xfc\x69\x07\x68\xe7\xe4\x9a\xb4\xed\x0f\xa1\x87\x87\x02\xce\x87\xd2\x48\x4e\xe1\xbc\xff\xcb\xf1\x72\x92\x44\x64\x03\x25\xea\xde\x5b\x6e\x9f\xc9\xf2\x4e\xac\xdd\xc7", 0 }, + /* Anchor: 162 turktrust-root2.cer serial: #{a.serial.to_s} + CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı,C=TR,L=Ankara,O=TÜRKTRUST Bilgi Ä°letişim ve Bilişim Güvenliği Hizmetleri A.Ş. (c) Kasım 2005 + */ + { 1088, "\x30\x82\x04\x3c\x30\x82\x03\x24\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xbe\x31\x3f\x30\x3d\x06\x03\x55\x04\x03\x0c\x36\x54\xc3\x9c\x52\x4b\x54\x52\x55\x53\x54\x20\x45\x6c\x65\x6b\x74\x72\x6f\x6e\x69\x6b\x20\x53\x65\x72\x74\x69\x66\x69\x6b\x61\x20\x48\x69\x7a\x6d\x65\x74\x20\x53\x61\xc4\x9f\x6c\x61\x79\xc4\xb1\x63\xc4\xb1\x73\xc4\xb1\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x0f\x30\x0d\x06\x03\x55\x04\x07\x0c\x06\x41\x6e\x6b\x61\x72\x61\x31\x5d\x30\x5b\x06\x03\x55\x04\x0a\x0c\x54\x54\xc3\x9c\x52\x4b\x54\x52\x55\x53\x54\x20\x42\x69\x6c\x67\x69\x20\xc4\xb0\x6c\x65\x74\x69\xc5\x9f\x69\x6d\x20\x76\x65\x20\x42\x69\x6c\x69\xc5\x9f\x69\x6d\x20\x47\xc3\xbc\x76\x65\x6e\x6c\x69\xc4\x9f\x69\x20\x48\x69\x7a\x6d\x65\x74\x6c\x65\x72\x69\x20\x41\x2e\xc5\x9e\x2e\x20\x28\x63\x29\x20\x4b\x61\x73\xc4\xb1\x6d\x20\x32\x30\x30\x35\x30\x1e\x17\x0d\x30\x35\x31\x31\x30\x37\x31\x30\x30\x37\x35\x37\x5a\x17\x0d\x31\x35\x30\x39\x31\x36\x31\x30\x30\x37\x35\x37\x5a\x30\x81\xbe\x31\x3f\x30\x3d\x06\x03\x55\x04\x03\x0c\x36\x54\xc3\x9c\x52\x4b\x54\x52\x55\x53\x54\x20\x45\x6c\x65\x6b\x74\x72\x6f\x6e\x69\x6b\x20\x53\x65\x72\x74\x69\x66\x69\x6b\x61\x20\x48\x69\x7a\x6d\x65\x74\x20\x53\x61\xc4\x9f\x6c\x61\x79\xc4\xb1\x63\xc4\xb1\x73\xc4\xb1\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x0f\x30\x0d\x06\x03\x55\x04\x07\x0c\x06\x41\x6e\x6b\x61\x72\x61\x31\x5d\x30\x5b\x06\x03\x55\x04\x0a\x0c\x54\x54\xc3\x9c\x52\x4b\x54\x52\x55\x53\x54\x20\x42\x69\x6c\x67\x69\x20\xc4\xb0\x6c\x65\x74\x69\xc5\x9f\x69\x6d\x20\x76\x65\x20\x42\x69\x6c\x69\xc5\x9f\x69\x6d\x20\x47\xc3\xbc\x76\x65\x6e\x6c\x69\xc4\x9f\x69\x20\x48\x69\x7a\x6d\x65\x74\x6c\x65\x72\x69\x20\x41\x2e\xc5\x9e\x2e\x20\x28\x63\x29\x20\x4b\x61\x73\xc4\xb1\x6d\x20\x32\x30\x30\x35\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xa9\x36\x7e\xc3\x91\x43\x4c\xc3\x19\x98\x08\xc8\xc7\x58\x7b\x4f\x16\x8c\xa5\xce\x49\x01\x1f\x73\x0e\xac\x75\x13\xa6\xfa\x9e\x2c\x20\xde\xd8\x90\x0e\x0a\xd1\x69\xd2\x27\xfb\xaa\x77\x9f\x27\x52\x25\xe2\xcb\x5d\xd8\xd8\x83\x50\x17\x7d\x8a\xb5\x82\x3f\x04\x8e\xb4\xd5\xf0\x49\xa7\x64\xb7\x1e\x2e\x5f\x20\x9c\x50\x75\x4f\xaf\xe1\xb5\x41\x14\xf4\x98\x92\x88\xc7\xe5\xe5\x64\x47\x61\x47\x79\xfd\xc0\x51\xf1\xc1\x99\xe7\xdc\xce\x6a\xfb\xaf\xb5\x01\x30\xdc\x46\x1c\xef\x8a\xec\x95\xef\xdc\xff\xaf\x10\x1c\xeb\x9d\xd8\xb0\xaa\x6a\x85\x18\x0d\x17\xc9\x3e\xbf\xf1\x9b\xd0\x09\x89\x42\xfd\xa0\x42\xb4\x9d\x89\x51\x55\x29\xcf\x1b\x70\xbc\x84\x54\xad\xc1\x13\x1f\x98\xf4\x2e\x76\x60\x8b\x5d\x3f\x9a\xad\xca\x0c\xbf\xa7\x56\x5b\x8f\x77\xb8\xd5\x9e\x79\x49\x92\x3f\xe0\xf1\x97\x24\x7a\x6c\x9b\x17\x0f\x6d\xef\x53\x98\x91\x2b\xe4\x0f\xbe\x59\x79\x07\x78\xbb\x97\x95\xf4\x9f\x69\xd4\x58\x87\x0a\xa9\xe3\xcc\xb6\x58\x19\x9f\x26\x21\xb1\xc4\x59\x8d\xb2\x41\x75\xc0\xad\x69\xce\x9c\x00\x08\xf2\x36\xff\x3e\xf0\xa1\x0f\x1a\xac\x14\xfd\xa6\x60\x0f\x02\x03\x01\x00\x01\xa3\x43\x30\x41\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xd9\x37\xb3\x4e\x05\xfd\xd9\xcf\x9f\x12\x16\xae\xb6\x89\x2f\xeb\x25\x3a\x88\x1c\x30\x0f\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x05\x03\x03\x07\x06\x00\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x72\x60\x96\xb7\xc9\xdc\xd8\x29\x5e\x23\x85\x5f\xb2\xb3\x2d\x76\xfb\x88\xd7\x17\xfe\x7b\x6d\x45\xb8\xf6\x85\x6c\x9f\x22\xfc\x2a\x10\x22\xec\xaa\xb9\x30\xf6\xab\x58\xd6\x39\x10\x31\x99\x29\x00\xbd\x89\x66\x41\xfb\x74\xde\x91\xc1\x18\x0b\x9f\xb5\x61\xcb\x9d\x3a\xbe\xf5\xa8\x94\xa3\x22\x55\x6e\x17\x49\xff\xd2\x29\xf1\x38\x26\x5d\xef\xa5\xaa\x3a\xf9\x71\x7b\xe6\xda\x58\x1d\xd3\x74\xc2\x01\xfa\x3e\x69\x58\x5f\xad\xcb\x68\xbe\x14\x2e\x9b\x6c\xc0\xb6\xdc\xa0\x26\xfa\x77\x1a\xe2\x24\xda\x1a\x37\xe0\x67\xad\xd1\x73\x83\x0d\xa5\x1a\x1d\x6e\x12\x92\x7e\x84\x62\x00\x17\xbd\xbc\x25\x18\x57\xf2\xd7\xa9\x6f\x59\x88\xbc\x34\xb7\x2e\x85\x78\x9d\x96\xdc\x14\xc3\x2c\x8a\x52\x9b\x96\x8c\x52\x66\x3d\x86\x16\x8b\x47\xb8\x51\x09\x8c\xea\x7d\xcd\x88\x72\xb3\x60\x33\xb1\xf0\x0a\x44\xef\x0f\xf5\x09\x37\x88\x24\x0e\x2c\x6b\x20\x3a\xa2\xfa\x11\xf2\x40\x35\x9c\x44\x68\x63\x3b\xac\x33\x6f\x63\xbc\x2c\xbb\xf2\xd2\xcb\x76\x7d\x7d\x88\xd8\x1d\xc8\x05\x1d\x6e\xbc\x94\xa9\x66\x8c\x77\x71\xc7\xfa\x91\xfa\x2f\x51\x9e\xe9\x39\x52\xb6\xe7\x04\x42", 0 }, + /* Anchor: 163 turktrust-root3.cer serial: #{a.serial.to_s} + CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı,C=TR,L=Ankara,O=TÜRKTRUST Bilgi Ä°letişim ve Bilişim Güvenliği Hizmetleri A.Ş. (c) Aralık 2007 + */ + { 1089, "\x30\x82\x04\x3d\x30\x82\x03\x25\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xbf\x31\x3f\x30\x3d\x06\x03\x55\x04\x03\x0c\x36\x54\xc3\x9c\x52\x4b\x54\x52\x55\x53\x54\x20\x45\x6c\x65\x6b\x74\x72\x6f\x6e\x69\x6b\x20\x53\x65\x72\x74\x69\x66\x69\x6b\x61\x20\x48\x69\x7a\x6d\x65\x74\x20\x53\x61\xc4\x9f\x6c\x61\x79\xc4\xb1\x63\xc4\xb1\x73\xc4\xb1\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x0f\x30\x0d\x06\x03\x55\x04\x07\x0c\x06\x41\x6e\x6b\x61\x72\x61\x31\x5e\x30\x5c\x06\x03\x55\x04\x0a\x0c\x55\x54\xc3\x9c\x52\x4b\x54\x52\x55\x53\x54\x20\x42\x69\x6c\x67\x69\x20\xc4\xb0\x6c\x65\x74\x69\xc5\x9f\x69\x6d\x20\x76\x65\x20\x42\x69\x6c\x69\xc5\x9f\x69\x6d\x20\x47\xc3\xbc\x76\x65\x6e\x6c\x69\xc4\x9f\x69\x20\x48\x69\x7a\x6d\x65\x74\x6c\x65\x72\x69\x20\x41\x2e\xc5\x9e\x2e\x20\x28\x63\x29\x20\x41\x72\x61\x6c\xc4\xb1\x6b\x20\x32\x30\x30\x37\x30\x1e\x17\x0d\x30\x37\x31\x32\x32\x35\x31\x38\x33\x37\x31\x39\x5a\x17\x0d\x31\x37\x31\x32\x32\x32\x31\x38\x33\x37\x31\x39\x5a\x30\x81\xbf\x31\x3f\x30\x3d\x06\x03\x55\x04\x03\x0c\x36\x54\xc3\x9c\x52\x4b\x54\x52\x55\x53\x54\x20\x45\x6c\x65\x6b\x74\x72\x6f\x6e\x69\x6b\x20\x53\x65\x72\x74\x69\x66\x69\x6b\x61\x20\x48\x69\x7a\x6d\x65\x74\x20\x53\x61\xc4\x9f\x6c\x61\x79\xc4\xb1\x63\xc4\xb1\x73\xc4\xb1\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x0f\x30\x0d\x06\x03\x55\x04\x07\x0c\x06\x41\x6e\x6b\x61\x72\x61\x31\x5e\x30\x5c\x06\x03\x55\x04\x0a\x0c\x55\x54\xc3\x9c\x52\x4b\x54\x52\x55\x53\x54\x20\x42\x69\x6c\x67\x69\x20\xc4\xb0\x6c\x65\x74\x69\xc5\x9f\x69\x6d\x20\x76\x65\x20\x42\x69\x6c\x69\xc5\x9f\x69\x6d\x20\x47\xc3\xbc\x76\x65\x6e\x6c\x69\xc4\x9f\x69\x20\x48\x69\x7a\x6d\x65\x74\x6c\x65\x72\x69\x20\x41\x2e\xc5\x9e\x2e\x20\x28\x63\x29\x20\x41\x72\x61\x6c\xc4\xb1\x6b\x20\x32\x30\x30\x37\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xab\xb7\x3e\x0a\x8c\xc8\xa5\x58\x15\xe6\x8a\xef\x27\x3d\x4a\xb4\xe8\x25\xd3\xcd\x33\xc2\x20\xdc\x19\xee\x88\x3f\x4d\x62\xf0\xdd\x13\x77\x8f\x61\xa9\x2a\xb5\xd4\xf2\xb9\x31\x58\x29\x3b\x2f\x3f\x6a\x9c\x6f\x73\x76\x25\xee\x34\x20\x80\xee\xea\xb7\xf0\xc4\x0a\xcd\x2b\x86\x94\xc9\xe3\x60\xb1\x44\x52\xb2\x5a\x29\xb4\x91\x97\x83\xd8\xb7\xa6\x14\x2f\x29\x49\xa2\xf3\x05\x06\xfb\xb4\x4f\xda\xa1\x6c\x9a\x66\x9f\xf0\x43\x09\xca\xea\x72\x8f\xeb\x00\xd7\x35\x39\xd7\x56\x17\x47\x17\x30\xf4\xbe\xbf\x3f\xc2\x68\xaf\x36\x40\xc1\xa9\xf4\xa9\xa7\xe8\x10\x6b\x08\x8a\xf7\x86\x1e\xdc\x9a\x2a\x15\x06\xf6\xa3\xf0\xf4\xe0\xc7\x14\xd4\x51\x7f\xcf\xb4\xdb\x6d\xaf\x47\x96\x17\x9b\x77\x71\xd8\xa7\x71\x9d\x24\x0c\xf6\x94\x3f\x85\x31\x12\x4f\xba\xee\x4e\x82\xb8\xb9\x3e\x8f\x23\x37\x5e\xcc\xa2\xaa\x75\xf7\x18\x6f\x09\xd3\xae\xa7\x54\x28\x34\xfb\xe1\xe0\x3b\x60\x7d\xa0\xbe\x79\x89\x86\xc8\x9f\x2d\xf9\x0a\x4b\xc4\x50\xa2\xe7\xfd\x79\x16\xc7\x7a\x0b\x18\xcf\xce\x4c\xef\x7d\xd6\x07\x6f\x98\xf1\xaf\xb1\xc1\x7a\xd7\x81\x35\xb8\xaa\x17\xb4\xe0\xcb\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x29\xc5\x90\xab\x25\xaf\x11\xe4\x61\xbf\xa3\xff\x88\x61\x91\xe6\x0e\xfe\x9c\x81\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x10\x0d\xda\xf8\x3a\xec\x28\xd1\x14\x95\x82\xb1\x12\x2c\x51\x7a\x41\x25\x36\x4c\x9f\xec\x3f\x1f\x84\x9d\x65\x54\x5c\xa8\x16\x02\x40\xfa\x6e\x1a\x37\x84\xef\x72\x9d\x86\x0a\x55\x9d\x56\x28\xac\x66\x2c\xd0\x3a\x56\x93\x34\x07\x25\xad\x08\xb0\x8f\xc8\x0f\x09\x59\xca\x9d\x98\x1c\xe5\x54\xf8\xb9\x45\x7f\x6a\x97\x6f\x88\x68\x4d\x4a\x06\x26\x37\x88\x02\x0e\xb6\xc6\xd6\x72\x99\xce\x6b\x77\xda\x62\x31\xa4\x56\x1f\xae\x5f\x8d\x77\xda\x5d\xf6\x88\xfc\x1a\xd9\x9e\xb5\x81\xf0\x32\xb8\xe3\x88\xd0\x9c\xf3\x6a\xa0\xb9\x9b\x14\x59\x35\x36\x4f\xcf\xf3\x8e\x5e\x5d\x17\xad\x15\x95\xd8\xdd\xb2\xd5\x15\x6e\x00\x4e\xb3\x4b\xcf\x66\x94\xe4\xe0\xcd\xb5\x05\xda\x63\x57\x8b\xe5\xb3\xaa\xdb\xc0\x2e\x1c\x90\x44\xdb\x1a\x5d\x18\xa4\xee\xbe\x04\x5b\x99\xd5\x71\x5f\x55\x65\x64\x62\xd5\xa2\x9b\x04\x59\x86\xc8\x62\x77\xe7\x7c\x82\x45\x6a\x3d\x17\xbf\xec\x9d\x75\x0c\xae\xa3\x6f\x5a\xd3\x2f\x98\x36\xf4\xf0\xf5\x19\xab\x11\x5d\xc8\xa6\xe3\x2a\x58\x6a\x42\x09\xc3\xbd\x92\x26\x66\x32\x0d\x5d\x08\x55\x74\xff\x8c\x98\xd0\x0a\xa6\x84\x6a\xd1\x39\x7d", 0 }, + /* Anchor: 164 twca-root-1.der serial: #{a.serial.to_s} + C=TW,O=TAIWAN-CA,OU=Root CA,CN=TWCA Root Certification Authority + */ + { 895, "\x30\x82\x03\x7b\x30\x82\x02\x63\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x5f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x57\x31\x12\x30\x10\x06\x03\x55\x04\x0a\x0c\x09\x54\x41\x49\x57\x41\x4e\x2d\x43\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x0b\x0c\x07\x52\x6f\x6f\x74\x20\x43\x41\x31\x2a\x30\x28\x06\x03\x55\x04\x03\x0c\x21\x54\x57\x43\x41\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x30\x38\x30\x38\x32\x38\x30\x37\x32\x34\x33\x33\x5a\x17\x0d\x33\x30\x31\x32\x33\x31\x31\x35\x35\x39\x35\x39\x5a\x30\x5f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x57\x31\x12\x30\x10\x06\x03\x55\x04\x0a\x0c\x09\x54\x41\x49\x57\x41\x4e\x2d\x43\x41\x31\x10\x30\x0e\x06\x03\x55\x04\x0b\x0c\x07\x52\x6f\x6f\x74\x20\x43\x41\x31\x2a\x30\x28\x06\x03\x55\x04\x03\x0c\x21\x54\x57\x43\x41\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xb0\x7e\x72\xb8\xa4\x03\x94\xe6\xa7\xde\x09\x38\x91\x4a\x11\x40\x87\xa7\x7c\x59\x64\x14\x7b\xb5\x11\x10\xdd\xfe\xbf\xd5\xc0\xbb\x56\xe2\x85\x25\xf4\x35\x72\x0f\xf8\x53\xd0\x41\xe1\x44\x01\xc2\xb4\x1c\xc3\x31\x42\x16\x47\x85\x33\x22\x76\xb2\x0a\x6f\x0f\xe5\x25\x50\x4f\x85\x86\xbe\xbf\x98\x2e\x10\x67\x1e\xbe\x11\x05\x86\x05\x90\xc4\x59\xd0\x7c\x78\x10\xb0\x80\x5c\xb7\xe1\xc7\x2b\x75\xcb\x7c\x9f\xae\xb5\xd1\x9d\x23\x37\x63\xa7\xdc\x42\xa2\x2d\x92\x04\x1b\x50\xc1\x7b\xb8\x3e\x1b\xc9\x56\x04\x8b\x2f\x52\x9b\xad\xa9\x56\xe9\xc1\xff\xad\xa9\x58\x87\x30\xb6\x81\xf7\x97\x45\xfc\x19\x57\x3b\x2b\x6f\xe4\x47\xf4\x99\x45\xfe\x1d\xf1\xf8\x97\xa3\x88\x1d\x37\x1c\x5c\x8f\xe0\x76\x25\x9a\x50\xf8\xa0\x54\xff\x44\x90\x76\x23\xd2\x32\xc6\xc3\xab\x06\xbf\xfc\xfb\xbf\xf3\xad\x7d\x92\x62\x02\x5b\x29\xd3\x35\xa3\x93\x9a\x43\x64\x60\x5d\xb2\xfa\x32\xff\x3b\x04\xaf\x4d\x40\x6a\xf9\xc7\xe3\xef\x23\xfd\x6b\xcb\xe5\x0f\x8b\x38\x0d\xee\x0a\xfc\xfe\x0f\x98\x9f\x30\x31\xdd\x6c\x52\x65\xf9\x8b\x81\xbe\x22\xe1\x1c\x58\x03\xba\x91\x1b\x89\x07\x02\x03\x01\x00\x01\xa3\x42\x30\x40\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x6a\x38\x5b\x26\x8d\xde\x8b\x5a\xf2\x4f\x7a\x54\x83\x19\x18\xe3\x08\x35\xa6\xba\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x3c\xd5\x77\x3d\xda\xdf\x89\xba\x87\x0c\x08\x54\x6a\x20\x50\x92\xbe\xb0\x41\x3d\xb9\x26\x64\x83\x0a\x2f\xe8\x40\xc0\x97\x28\x27\x82\x30\x4a\xc9\x93\xff\x6a\xe7\xa6\x00\x7f\x89\x42\x9a\xd6\x11\xe5\x53\xce\x2f\xcc\xf2\xda\x05\xc4\xfe\xe2\x50\xc4\x3a\x86\x7d\xcc\xda\x7e\x10\x09\x3b\x92\x35\x2a\x53\xb2\xfe\xeb\x2b\x05\xd9\x6c\x5d\xe6\xd0\xef\xd3\x6a\x66\x9e\x15\x28\x85\x7a\xe8\x82\x00\xac\x1e\xa7\x09\x69\x56\x42\xd3\x68\x51\x18\xbe\x54\x9a\xbf\x44\x41\xba\x49\xbe\x20\xba\x69\x5c\xee\xb8\x77\xcd\xce\x6c\x1f\xad\x83\x96\x18\x7d\x0e\xb5\x14\x39\x84\xf1\x28\xe9\x2d\xa3\x9e\x7b\x1e\x7a\x72\x5a\x83\xb3\x79\x6f\xef\xb4\xfc\xd0\x0a\xa5\x58\x4f\x46\xdf\xfb\x6d\x79\x59\xf2\x84\x22\x52\xae\x0f\xcc\xfb\x7c\x3b\xe7\x6a\xca\x47\x61\xc3\x7a\xf8\xd3\x92\x04\x1f\xb8\x20\x84\xe1\x36\x54\x16\xc7\x40\xde\x3b\x8a\x73\xdc\xdf\xc6\x09\x4c\xdf\xec\xda\xff\xd4\x53\x42\xa1\xc9\xf2\x62\x1d\x22\x83\x3c\x97\xc5\xf9\x19\x62\x27\xac\x65\x22\xd7\xd3\x3c\xc6\xe5\x8e\xb2\x53\xcc\x49\xce\xbc\x30\xfe\x7b\x0e\x33\x90\xfb\xed\xd2\x14\x91\x1f\x07\xaf", 0 }, + /* Anchor: 165 UCAGlobalRoot.cer serial: #{a.serial.to_s} + C=CN,O=UniTrust,CN=UCA Global Root + */ + { 1430, "\x30\x82\x05\x92\x30\x82\x03\x7a\xa0\x03\x02\x01\x02\x02\x01\x08\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x3a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4e\x31\x11\x30\x0f\x06\x03\x55\x04\x0a\x13\x08\x55\x6e\x69\x54\x72\x75\x73\x74\x31\x18\x30\x16\x06\x03\x55\x04\x03\x13\x0f\x55\x43\x41\x20\x47\x6c\x6f\x62\x61\x6c\x20\x52\x6f\x6f\x74\x30\x1e\x17\x0d\x30\x38\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x33\x37\x31\x32\x33\x31\x30\x30\x30\x30\x30\x30\x5a\x30\x3a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4e\x31\x11\x30\x0f\x06\x03\x55\x04\x0a\x13\x08\x55\x6e\x69\x54\x72\x75\x73\x74\x31\x18\x30\x16\x06\x03\x55\x04\x03\x13\x0f\x55\x43\x41\x20\x47\x6c\x6f\x62\x61\x6c\x20\x52\x6f\x6f\x74\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\xda\xb3\xe5\x06\x50\x3f\xf6\x73\xf7\xc4\x32\xbf\x46\xa5\x25\x62\x33\x87\xb0\x68\xfe\xa7\xdf\x88\x03\x63\x7d\x02\x96\xfd\xeb\x87\xc9\xee\xe2\x08\xbb\x9d\xbb\xbb\xe4\x41\x8f\xc7\x30\x89\x0f\x6d\x24\xc0\x04\x6c\x14\x94\x81\x4d\xa0\x0d\x74\x66\xf3\xf0\x85\xaf\xf8\x64\x19\xde\xb9\xe9\x81\x93\xd0\x28\x85\x99\x47\x42\x4a\x2c\x3c\x38\x27\x4a\xcc\xff\xf9\x6c\x19\xd7\xb5\xf3\xef\x9b\xae\x5b\x34\x06\xd7\x8f\xa2\x13\x06\x9c\x8a\x84\x42\xd5\xb3\xa3\x90\x68\x6d\x81\x90\xee\x4d\x84\xec\x4c\x70\x4e\x2d\xde\x24\x39\xce\x19\x00\x43\x93\x78\xf9\x08\x86\x1d\x43\xd1\xf4\x72\xbc\x05\xc0\x67\xfa\xc0\x51\xd2\xc9\x85\x07\x24\xae\x39\x1e\x7a\xcd\x41\xd2\x36\xab\x61\xea\x2b\xab\xf0\x20\x55\x99\x3c\x6d\x2d\x1c\x2e\x2e\x75\x96\xd8\x72\x97\xe0\x0c\xca\x69\x73\xee\x75\x2b\x15\x09\xe0\x8e\x6d\xbb\xda\x13\xff\x46\xa8\xe8\x00\x0c\xac\x07\x2f\x1d\xb9\xba\xb9\xd1\xa0\xf7\x99\x9e\x74\x5c\x19\x05\x66\x31\xcf\x3e\x2a\x52\xfe\x6f\x9f\xf3\xb9\xbd\xf9\xc1\x81\xf5\x37\xda\x2e\x4c\x81\x25\x5d\xf6\xd9\x94\x9a\xd3\x35\x8b\x20\x28\x37\x5f\x51\xeb\x7d\x62\xc7\xa9\x93\xd1\xf9\xd0\x34\xcb\xa9\x27\x26\x2c\x28\x90\x92\x3b\x55\x63\xb7\x17\x0e\x54\x73\xab\xaf\x7c\xec\x3a\xab\x70\x33\xac\x21\xfb\x22\x26\xb3\x86\xac\x23\xa9\xd7\x7f\x6d\xcb\x08\x20\xf2\xaf\x40\xf5\xff\x44\x47\x71\xdd\x27\xdd\x13\x28\xa1\xea\x76\x39\xf9\x10\xa0\xa0\x4d\x40\xa4\x27\xb2\x59\x15\x2b\x6c\x2d\x24\xb7\x24\x63\x78\xf7\x43\x18\x7a\x0f\x4d\x11\xe3\xe8\xac\x87\x42\x8d\xe7\x58\x71\xa4\xab\x6e\xa2\xc0\x97\x7c\xbb\xe3\x13\x4b\xca\xdb\xbb\x6b\x08\xf9\x69\xb4\x04\x72\xd5\xc3\x46\xb9\x77\xea\xff\xba\xfb\xe9\xf0\x3a\x0c\x35\xf6\x8f\x0f\xae\x06\x84\x16\xdd\x94\x55\xd4\xef\xca\x27\xb7\x03\x3c\xc5\x1c\x26\x2a\xf5\x3c\xa8\xa5\x95\x9b\x86\xf1\x8a\x89\x67\xf8\xc7\x0c\x66\xb1\xed\x41\xbf\x82\xa6\x00\x68\x3a\x22\x34\xee\x1e\xeb\xe5\x6f\x89\x74\x4f\x6a\xaa\x6a\xa8\x57\x67\x52\xd4\x20\x61\xc1\xce\x53\xcb\xfd\x24\x7f\x5f\x26\xdf\xa1\x08\x69\x96\xa0\x9e\xfe\x49\x43\xe2\xd3\xea\xda\xc4\xf1\x88\x31\x21\x6e\x1c\xe1\xcd\xf3\x75\x0e\x20\x44\x16\xcc\x7d\x73\x74\x35\x45\x2c\x3b\x81\xd4\x20\xec\xb6\x09\x8c\x3e\x48\xb2\x49\x02\x03\x01\x00\x01\xa3\x81\xa2\x30\x81\x9f\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x06\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x63\x06\x03\x55\x1d\x25\x04\x5c\x30\x5a\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x02\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x03\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x04\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x05\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x06\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x07\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x08\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x09\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xd9\xc3\xd3\xf8\x80\x92\x67\xcc\x5d\xd2\x3a\xa2\xd7\x71\xa2\xb4\xc4\x38\x80\x2d\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\xd0\x88\x79\xca\x08\xaa\xf7\x0b\x34\xa0\x4e\x09\xc2\xe9\x7e\x35\x48\x89\x70\x84\x23\x2f\x51\xc3\x2b\x2f\x5e\xdb\x53\x6b\x5b\x75\x08\x2a\x54\xba\x32\x0e\xd5\xc6\x71\x85\xb1\x97\x49\x80\xf6\x84\xd0\xf0\xba\xb7\x71\x94\xc8\x79\x6b\xa6\xc5\x44\xe8\x42\xa2\xad\x25\x2d\x57\x2f\xe6\xd6\x31\x29\xfa\x19\x89\x54\x29\x7e\xb7\x7e\x47\x36\x69\x2d\x6e\x32\xbc\xd4\x75\xda\x42\x73\xb8\x4e\xe5\x83\x40\x73\xb2\x5d\xdf\xd4\x44\x73\xa6\x62\x0b\xdb\xaa\x6e\x05\x8c\xc8\x7f\x46\x4f\x39\x85\x90\x9d\xbc\x1b\x54\x29\xac\xa5\xd7\xfe\xe5\x58\x56\x57\x6d\x2c\x99\xa1\x49\x21\xd5\x61\xc6\x8c\x61\xe1\x75\x24\xc1\x01\xdd\x2d\x1b\x36\xc3\x2f\x12\xcc\x0b\xd6\x78\x8b\x75\x80\xe9\x41\xb9\x88\xb1\xca\x3c\xa9\x16\xc6\x4e\x15\xe3\x72\x36\xf6\xd4\xa0\x41\x85\xaf\x8a\x65\x70\x4d\xb5\x44\x10\x50\xec\xed\xdf\x6d\xe6\xd9\xc6\xc0\x12\xf1\x4b\x3a\x2f\x73\xe9\x3c\xa9\xee\x1b\xaa\x2f\x35\xa5\x9b\x9f\x4d\xc5\x34\x84\x5f\x26\x14\x69\xb3\x23\xb1\x89\x72\x14\xf8\xe9\x4d\x51\x22\x03\xff\x4a\x86\xc4\x1c\xe8\x7b\x79\x0a\xdb\x47\x25\x81\x7e\xfc\x34\x84\xac\x59\xb8\x58\x43\xe4\x3d\x43\x09\x54\x74\xc2\xd0\xfd\xd9\xef\x6e\x59\xf7\x72\x60\x99\x76\x6f\xf5\x27\xa7\xbb\x83\xa4\x4a\x81\xec\x29\x81\xf4\x77\x4b\xe1\x42\x12\x55\xd4\x86\x2a\x12\xb6\xf0\x55\x9b\x01\x2e\xdd\xf6\xa8\xe3\x19\xc3\xce\x47\x2f\xc0\x78\x61\x18\x5a\xc7\x65\xfc\x9d\x46\x5b\x57\xdc\x7c\x0e\xbb\x96\x83\x10\x7c\x55\x18\x09\x04\xae\xd1\xf7\x8b\x2a\x3e\xa0\xe6\x50\xd6\x30\x36\xd7\xe7\x8b\x38\x53\xec\x49\x44\xe0\xcf\xa4\xdf\xf1\x53\x7b\x8b\x5a\xb6\xf6\x11\x90\x4b\xd6\x75\xf3\xfe\x02\xf3\x29\xaf\xf0\x23\x72\x7d\x14\xed\xa9\x5d\xdf\x7a\x81\x9e\x9b\x92\x22\xfc\x1e\xf8\x01\x45\x41\x97\xc7\x6b\x01\x61\xbe\x33\x68\xf2\xa0\x65\x84\x66\xbc\xe0\x2a\xa4\x68\xd3\x71\xec\xc7\x08\xde\xa3\xc3\xc9\x36\x4a\x34\xf1\x17\xe2\x80\xaf\x20\x21\x93\x94\x1e\xe6\x15\xd3\x54\x62\xf1\xb5\x38\x2f\xe3\xcc\xb9\x67\x04\xa9\xba\xe5\xee\xf9\x10\x6e\xcb\x2e\x7e\x13\xaf\x92\x14\xfe\xf3\x27\x73\x7b\x38\xfc\x73\x6d\xb9\xb9\x88\xf6\x6e\x8c\x0b\xf5\xfc\xff\x09\x0e\xb3\x2d\x5e\x7b\x75\xe3\x92\x24\xe2\xe6\xe1\x58\x3e\x4b\x28\x03\x75\x6b\x18\x9b\x47\x0c", 0 }, + /* Anchor: 166 UCARoot.cer serial: #{a.serial.to_s} + C=CN,O=UniTrust,CN=UCA Root + */ + { 904, "\x30\x82\x03\x84\x30\x82\x02\x6c\xa0\x03\x02\x01\x02\x02\x01\x09\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x33\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4e\x31\x11\x30\x0f\x06\x03\x55\x04\x0a\x13\x08\x55\x6e\x69\x54\x72\x75\x73\x74\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x13\x08\x55\x43\x41\x20\x52\x6f\x6f\x74\x30\x1e\x17\x0d\x30\x34\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x32\x39\x31\x32\x33\x31\x30\x30\x30\x30\x30\x30\x5a\x30\x33\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4e\x31\x11\x30\x0f\x06\x03\x55\x04\x0a\x13\x08\x55\x6e\x69\x54\x72\x75\x73\x74\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x13\x08\x55\x43\x41\x20\x52\x6f\x6f\x74\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xb3\x5d\x07\xca\x86\x26\x7d\x6b\xe2\xfb\x38\x09\x0e\xcc\x82\xc2\x6a\x1a\x00\xa2\x15\x5f\xd6\xe9\xd4\x01\xb7\x56\x03\x01\x59\x8f\xf5\x38\x69\x24\x76\xc2\x5e\x2b\xc5\xf6\x2b\xbf\xaf\xfb\x41\xfd\x0f\x5a\xfc\xab\xd7\x83\x70\x4d\x30\x98\xd1\x9e\xb2\x76\xbb\x92\xd6\xbb\xe9\x10\x28\x69\x28\x36\x44\xe8\xf1\x2c\xd7\x58\x7c\x24\xd6\x7f\x02\x3a\xf0\x81\x6b\x61\x60\x3f\xf4\x33\xde\x6d\xe5\xea\x28\x52\x4f\xfc\xa9\x1d\x63\x7c\x0b\xba\xea\xae\xc4\x68\x46\xe4\xde\x8f\xc1\xa7\xb2\xb6\x58\x5a\x6d\x1d\x2c\xd9\x8c\x3a\xb7\x88\xcb\x85\xd4\xf7\xe8\x03\x5e\xfd\xb2\x4d\x50\xe8\xd6\x1f\xff\xae\x02\x3f\x8b\x4f\x96\x21\x3c\x9b\xd7\x25\xc9\x1d\x3f\xfb\x98\xb1\x59\xe4\xf0\xa9\x3b\xaf\xb3\xcd\x85\x2c\xe2\x60\x46\xcc\x6f\x8e\xa0\xeb\xf0\x34\xc5\xf1\x42\x18\x60\xae\x12\xed\x46\x75\x1c\xe5\xd8\xa9\x96\x5a\xbe\xde\x5a\xd6\x78\x67\x96\x5b\x93\x77\x50\xf2\x6e\x1b\xde\x96\x51\x4a\xa6\xd6\x4b\x43\x75\x21\x66\x8d\x77\xec\x02\x84\x76\x5c\x44\x10\xb6\x1d\x61\x6c\xe4\xa3\x20\x7d\xb7\x8d\xba\x0f\x91\x75\xc7\x8d\xdf\xbc\x02\x60\xa8\x29\xa8\xbd\x3d\x43\x02\x03\x01\x00\x01\xa3\x81\xa2\x30\x81\x9f\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x06\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x63\x06\x03\x55\x1d\x25\x04\x5c\x30\x5a\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x02\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x03\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x04\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x05\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x06\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x07\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x08\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x09\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xdb\x1f\x35\xf3\x6b\x4c\xff\x42\x31\x64\x9b\xcd\xbb\x5a\x1e\x1d\x48\x10\xb7\xee\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x38\x6c\xb7\x88\xf1\xad\xfa\x58\x37\x74\xd1\xe8\x70\xde\x9c\x27\x59\xcb\xe4\x15\xd7\xa0\xc3\x60\xd7\x88\x80\x04\xc5\x30\x4c\x3d\xd4\x1a\xeb\x06\x5e\x59\x47\xe6\xbc\x66\xcb\xe0\x08\xfc\xe8\x35\xec\x62\x7d\xca\xc0\xda\xc1\x78\xaf\xe5\x46\x6f\xfb\x89\x82\x23\x8f\xf6\xd7\x53\x66\x55\xa0\xde\x25\x12\x3b\x71\x36\x16\x55\x12\x76\xfb\x3d\xf8\x54\x5b\x31\xba\x00\x06\xf8\x7d\x55\xe5\xa7\x76\x83\xaa\x5c\x4a\x97\xa6\x2a\x28\xdf\xbd\xc6\x6c\x0b\x23\x95\x8e\x33\x7f\x1e\x5e\x40\x1f\x13\x54\x2c\x9c\xe5\xb5\x0e\xdd\x17\x28\xae\x6b\x01\xd3\x52\x29\xf5\x22\x1f\x90\x39\xf4\xdc\x62\x68\xf0\x3c\x86\x47\xec\xb8\x05\x45\xbb\xb7\x0c\x96\x94\xc6\x67\xcb\x23\x71\xd0\x8e\x74\x22\xd6\x41\xeb\x03\xa8\xb6\xea\xbe\xc4\x01\x12\xb5\xb3\x5d\x40\x76\x06\x20\xd4\x64\xb8\x29\x46\x06\x8a\xce\x1f\x93\x9a\x10\xee\xfb\xaa\x5a\xb4\xdc\x2f\xd5\x2b\xcb\xf6\xd7\x05\x84\x98\x05\x91\x0b\x84\xf7\x3d\xfa\xd6\xf9\x7a\xfa\x2c\x15\xea\x36\x82\x43\xb7\xb7\xb8\xe3\xf3\x71\x01\xed\x43\x43\xa2\x05\x45\xc3\x28\x05\x07\x35\xe3\x01\xa5\x38\x1e\x80\xd4\xd7\xc3\xd9\xde", 0 }, + /* Anchor: 167 Unizeto-CertumCA.cer serial: #{a.serial.to_s} + C=PL,O=Unizeto Sp. z o.o.,CN=Certum CA + */ + { 784, "\x30\x82\x03\x0c\x30\x82\x01\xf4\xa0\x03\x02\x01\x02\x02\x03\x01\x00\x20\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x3e\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x50\x4c\x31\x1b\x30\x19\x06\x03\x55\x04\x0a\x13\x12\x55\x6e\x69\x7a\x65\x74\x6f\x20\x53\x70\x2e\x20\x7a\x20\x6f\x2e\x6f\x2e\x31\x12\x30\x10\x06\x03\x55\x04\x03\x13\x09\x43\x65\x72\x74\x75\x6d\x20\x43\x41\x30\x1e\x17\x0d\x30\x32\x30\x36\x31\x31\x31\x30\x34\x36\x33\x39\x5a\x17\x0d\x32\x37\x30\x36\x31\x31\x31\x30\x34\x36\x33\x39\x5a\x30\x3e\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x50\x4c\x31\x1b\x30\x19\x06\x03\x55\x04\x0a\x13\x12\x55\x6e\x69\x7a\x65\x74\x6f\x20\x53\x70\x2e\x20\x7a\x20\x6f\x2e\x6f\x2e\x31\x12\x30\x10\x06\x03\x55\x04\x03\x13\x09\x43\x65\x72\x74\x75\x6d\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xce\xb1\xc1\x2e\xd3\x4f\x7c\xcd\x25\xce\x18\x3e\x4f\xc4\x8c\x6f\x80\x6a\x73\xc8\x5b\x51\xf8\x9b\xd2\xdc\xbb\x00\x5c\xb1\xa0\xfc\x75\x03\xee\x81\xf0\x88\xee\x23\x52\xe9\xe6\x15\x33\x8d\xac\x2d\x09\xc5\x76\xf9\x2b\x39\x80\x89\xe4\x97\x4b\x90\xa5\xa8\x78\xf8\x73\x43\x7b\xa4\x61\xb0\xd8\x58\xcc\xe1\x6c\x66\x7e\x9c\xf3\x09\x5e\x55\x63\x84\xd5\xa8\xef\xf3\xb1\x2e\x30\x68\xb3\xc4\x3c\xd8\xac\x6e\x8d\x99\x5a\x90\x4e\x34\xdc\x36\x9a\x8f\x81\x88\x50\xb7\x6d\x96\x42\x09\xf3\xd7\x95\x83\x0d\x41\x4b\xb0\x6a\x6b\xf8\xfc\x0f\x7e\x62\x9f\x67\xc4\xed\x26\x5f\x10\x26\x0f\x08\x4f\xf0\xa4\x57\x28\xce\x8f\xb8\xed\x45\xf6\x6e\xee\x25\x5d\xaa\x6e\x39\xbe\xe4\x93\x2f\xd9\x47\xa0\x72\xeb\xfa\xa6\x5b\xaf\xca\x53\x3f\xe2\x0e\xc6\x96\x56\x11\x6e\xf7\xe9\x66\xa9\x26\xd8\x7f\x95\x53\xed\x0a\x85\x88\xba\x4f\x29\xa5\x42\x8c\x5e\xb6\xfc\x85\x20\x00\xaa\x68\x0b\xa1\x1a\x85\x01\x9c\xc4\x46\x63\x82\x88\xb6\x22\xb1\xee\xfe\xaa\x46\x59\x7e\xcf\x35\x2c\xd5\xb6\xda\x5d\xf7\x48\x33\x14\x54\xb6\xeb\xd9\x6f\xce\xcd\x88\xd6\xab\x1b\xda\x96\x3b\x1d\x59\x02\x03\x01\x00\x01\xa3\x13\x30\x11\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xb8\x8d\xce\xef\xe7\x14\xba\xcf\xee\xb0\x44\x92\x6c\xb4\x39\x3e\xa2\x84\x6e\xad\xb8\x21\x77\xd2\xd4\x77\x82\x87\xe6\x20\x41\x81\xee\xe2\xf8\x11\xb7\x63\xd1\x17\x37\xbe\x19\x76\x24\x1c\x04\x1a\x4c\xeb\x3d\xaa\x67\x6f\x2d\xd4\xcd\xfe\x65\x31\x70\xc5\x1b\xa6\x02\x0a\xba\x60\x7b\x6d\x58\xc2\x9a\x49\xfe\x63\x32\x0b\x6b\xe3\x3a\xc0\xac\xab\x3b\xb0\xe8\xd3\x09\x51\x8c\x10\x83\xc6\x34\xe0\xc5\x2b\xe0\x1a\xb6\x60\x14\x27\x6c\x32\x77\x8c\xbc\xb2\x72\x98\xcf\xcd\xcc\x3f\xb9\xc8\x24\x42\x14\xd6\x57\xfc\xe6\x26\x43\xa9\x1d\xe5\x80\x90\xce\x03\x54\x28\x3e\xf7\x3f\xd3\xf8\x4d\xed\x6a\x0a\x3a\x93\x13\x9b\x3b\x14\x23\x13\x63\x9c\x3f\xd1\x87\x27\x79\xe5\x4c\x51\xe3\x01\xad\x85\x5d\x1a\x3b\xb1\xd5\x73\x10\xa4\xd3\xf2\xbc\x6e\x64\xf5\x5a\x56\x90\xa8\xc7\x0e\x4c\x74\x0f\x2e\x71\x3b\xf7\xc8\x47\xf4\x69\x6f\x15\xf2\x11\x5e\x83\x1e\x9c\x7c\x52\xae\xfd\x02\xda\x12\xa8\x59\x67\x18\xdb\xbc\x70\xdd\x9b\xb1\x69\xed\x80\xce\x89\x40\x48\x6a\x0e\x35\xca\x29\x66\x15\x21\x94\x2c\xe8\x60\x2a\x9b\x85\x4a\x40\xf3\x6b\x8a\x24\xec\x06\x16\x2c\x73", 0 }, + /* Anchor: 168 UTN-USERFirst-ClientAuthentication.der serial: #{a.serial.to_s} + C=US,ST=UT,L=Salt Lake City,O=The USERTRUST Network,OU=http://www.usertrust.com,CN=UTN-USERFirst-Client Authentication and Email + */ + { 1190, "\x30\x82\x04\xa2\x30\x82\x03\x8a\xa0\x03\x02\x01\x02\x02\x10\x44\xbe\x0c\x8b\x50\x00\x24\xb4\x11\xd3\x36\x25\x25\x67\xc9\x89\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xae\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x13\x02\x55\x54\x31\x17\x30\x15\x06\x03\x55\x04\x07\x13\x0e\x53\x61\x6c\x74\x20\x4c\x61\x6b\x65\x20\x43\x69\x74\x79\x31\x1e\x30\x1c\x06\x03\x55\x04\x0a\x13\x15\x54\x68\x65\x20\x55\x53\x45\x52\x54\x52\x55\x53\x54\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x21\x30\x1f\x06\x03\x55\x04\x0b\x13\x18\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2e\x63\x6f\x6d\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2d\x55\x54\x4e\x2d\x55\x53\x45\x52\x46\x69\x72\x73\x74\x2d\x43\x6c\x69\x65\x6e\x74\x20\x41\x75\x74\x68\x65\x6e\x74\x69\x63\x61\x74\x69\x6f\x6e\x20\x61\x6e\x64\x20\x45\x6d\x61\x69\x6c\x30\x1e\x17\x0d\x39\x39\x30\x37\x30\x39\x31\x37\x32\x38\x35\x30\x5a\x17\x0d\x31\x39\x30\x37\x30\x39\x31\x37\x33\x36\x35\x38\x5a\x30\x81\xae\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x13\x02\x55\x54\x31\x17\x30\x15\x06\x03\x55\x04\x07\x13\x0e\x53\x61\x6c\x74\x20\x4c\x61\x6b\x65\x20\x43\x69\x74\x79\x31\x1e\x30\x1c\x06\x03\x55\x04\x0a\x13\x15\x54\x68\x65\x20\x55\x53\x45\x52\x54\x52\x55\x53\x54\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x21\x30\x1f\x06\x03\x55\x04\x0b\x13\x18\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2e\x63\x6f\x6d\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2d\x55\x54\x4e\x2d\x55\x53\x45\x52\x46\x69\x72\x73\x74\x2d\x43\x6c\x69\x65\x6e\x74\x20\x41\x75\x74\x68\x65\x6e\x74\x69\x63\x61\x74\x69\x6f\x6e\x20\x61\x6e\x64\x20\x45\x6d\x61\x69\x6c\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xb2\x39\x85\xa4\xf2\x7d\xab\x41\x3b\x62\x46\x37\xae\xcd\xc1\x60\x75\xbc\x39\x65\xf9\x4a\x1a\x47\xa2\xb9\xcc\x48\xcc\x6a\x98\xd5\x4d\x35\x19\xb9\xa4\x42\xe5\xce\x49\xe2\x8a\x2f\x1e\x7c\xd2\x31\x07\xc7\x4e\xb4\x83\x64\x9d\x2e\x29\xd5\xa2\x64\xc4\x85\xbd\x85\x51\x35\x79\xa4\x4e\x68\x90\x7b\x1c\x7a\xa4\x92\xa8\x17\xf2\x98\x15\xf2\x93\xcc\xc9\xa4\x32\x95\xbb\x0c\x4f\x30\xbd\x98\xa0\x0b\x8b\xe5\x6e\x1b\xa2\x46\xfa\x78\xbc\xa2\x6f\xab\x59\x5e\xa5\x2f\xcf\xca\xda\x6d\xaa\x2f\xeb\xac\xa1\xb3\x6a\xaa\xb7\x2e\x67\x35\x8b\x79\xe1\x1e\x69\x88\xe2\xe6\x46\xcd\xa0\xa5\xea\xbe\x0b\xce\x76\x3a\x7a\x0e\x9b\xea\xfc\xda\x27\x5b\x3d\x73\x1f\x22\xe6\x48\x61\xc6\x4c\xf3\x69\xb1\xa8\x2e\x1b\xb6\xd4\x31\x20\x2c\xbc\x82\x8a\x8e\xa4\x0e\xa5\xd7\x89\x43\xfc\x16\x5a\xaf\x1d\x71\xd7\x11\x59\xda\xba\x87\x0d\xaf\xfa\xf3\xe1\xc2\xf0\xa4\xc5\x67\x8c\xd6\xd6\x54\x3a\xde\x0a\xa4\xba\x03\x77\xb3\x65\xc8\xfd\x1e\xd3\x74\x62\xaa\x18\xca\x68\x93\x1e\xa1\x85\x7e\xf5\x47\x65\xcb\xf8\x4d\x57\x28\x74\xd2\x34\xff\x30\xb6\xee\xf6\x62\x30\x14\x8c\x2c\xeb\x02\x03\x01\x00\x01\xa3\x81\xb9\x30\x81\xb6\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\xc6\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x89\x82\x67\x7d\xc4\x9d\x26\x70\x00\x4b\xb4\x50\x48\x7c\xde\x3d\xae\x04\x6e\x7d\x30\x58\x06\x03\x55\x1d\x1f\x04\x51\x30\x4f\x30\x4d\xa0\x4b\xa0\x49\x86\x47\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2e\x63\x6f\x6d\x2f\x55\x54\x4e\x2d\x55\x53\x45\x52\x46\x69\x72\x73\x74\x2d\x43\x6c\x69\x65\x6e\x74\x41\x75\x74\x68\x65\x6e\x74\x69\x63\x61\x74\x69\x6f\x6e\x61\x6e\x64\x45\x6d\x61\x69\x6c\x2e\x63\x72\x6c\x30\x1d\x06\x03\x55\x1d\x25\x04\x16\x30\x14\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x02\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x04\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xb1\x6d\x61\x5d\xa6\x1a\x7f\x7c\xab\x4a\xe4\x30\xfc\x53\x6f\x25\x24\xc6\xca\xed\xe2\x31\x5c\x2b\x0e\xee\xee\x61\x55\x6f\x04\x3e\xcf\x39\xde\xc5\x1b\x49\x94\xe4\xeb\x20\x4c\xb4\xe6\x9e\x50\x2e\x72\xd9\x8d\xf5\xaa\xa3\xb3\x4a\xda\x56\x1c\x60\x97\x80\xdc\x82\xa2\xad\x4a\xbd\x8a\x2b\xff\x0b\x09\xb4\xc6\xd7\x20\x04\x45\xe4\xcd\x80\x01\xba\xba\x2b\x6e\xce\xaa\xd7\x92\xfe\xe4\xaf\xeb\xf4\x26\x1d\x16\x2a\x7f\x6c\x30\x95\x37\x2f\x33\x12\xac\x7f\xdd\xc7\xd1\x11\x8c\x51\x98\xb2\xd0\xa3\x91\xd0\xad\xf6\x9f\x9e\x83\x93\x1e\x1d\x42\xb8\x46\xaf\x6b\x66\xf0\x9b\x7f\xea\xe3\x03\x02\xe5\x02\x51\xc1\xaa\xd5\x35\x9d\x72\x40\x03\x89\xba\x31\x1d\xc5\x10\x68\x52\x9e\xdf\xa2\x85\xc5\x5c\x08\xa6\x78\xe6\x53\x4f\xb1\xe8\xb7\xd3\x14\x9e\x93\xa6\xc3\x64\xe3\xac\x7e\x71\xcd\xbc\x9f\xe9\x03\x1b\xcc\xfb\xe9\xac\x31\xc1\xaf\x7c\x15\x74\x02\x99\xc3\xb2\x47\xa6\xc2\x32\x61\xd7\xc7\x6f\x48\x24\x51\x27\xa1\xd5\x87\x55\xf2\x7b\x8f\x98\x3d\x16\x9e\xee\x75\xb6\xf8\xd0\x8e\xf2\xf3\xc6\xae\x28\x5b\xa7\xf0\xf3\x36\x17\xfc\xc3\x05\xd3\xca\x03\x4a\x54", 0 }, + /* Anchor: 169 UTN-USERFirst-Hardware.crt serial: #{a.serial.to_s} + C=US,ST=UT,L=Salt Lake City,O=The USERTRUST Network,OU=http://www.usertrust.com,CN=UTN-USERFirst-Hardware + */ + { 1144, "\x30\x82\x04\x74\x30\x82\x03\x5c\xa0\x03\x02\x01\x02\x02\x10\x44\xbe\x0c\x8b\x50\x00\x24\xb4\x11\xd3\x36\x2a\xfe\x65\x0a\xfd\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\x97\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x13\x02\x55\x54\x31\x17\x30\x15\x06\x03\x55\x04\x07\x13\x0e\x53\x61\x6c\x74\x20\x4c\x61\x6b\x65\x20\x43\x69\x74\x79\x31\x1e\x30\x1c\x06\x03\x55\x04\x0a\x13\x15\x54\x68\x65\x20\x55\x53\x45\x52\x54\x52\x55\x53\x54\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x21\x30\x1f\x06\x03\x55\x04\x0b\x13\x18\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2e\x63\x6f\x6d\x31\x1f\x30\x1d\x06\x03\x55\x04\x03\x13\x16\x55\x54\x4e\x2d\x55\x53\x45\x52\x46\x69\x72\x73\x74\x2d\x48\x61\x72\x64\x77\x61\x72\x65\x30\x1e\x17\x0d\x39\x39\x30\x37\x30\x39\x31\x38\x31\x30\x34\x32\x5a\x17\x0d\x31\x39\x30\x37\x30\x39\x31\x38\x31\x39\x32\x32\x5a\x30\x81\x97\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x13\x02\x55\x54\x31\x17\x30\x15\x06\x03\x55\x04\x07\x13\x0e\x53\x61\x6c\x74\x20\x4c\x61\x6b\x65\x20\x43\x69\x74\x79\x31\x1e\x30\x1c\x06\x03\x55\x04\x0a\x13\x15\x54\x68\x65\x20\x55\x53\x45\x52\x54\x52\x55\x53\x54\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x21\x30\x1f\x06\x03\x55\x04\x0b\x13\x18\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2e\x63\x6f\x6d\x31\x1f\x30\x1d\x06\x03\x55\x04\x03\x13\x16\x55\x54\x4e\x2d\x55\x53\x45\x52\x46\x69\x72\x73\x74\x2d\x48\x61\x72\x64\x77\x61\x72\x65\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xb1\xf7\xc3\x38\x3f\xb4\xa8\x7f\xcf\x39\x82\x51\x67\xd0\x6d\x9f\xd2\xff\x58\xf3\xe7\x9f\x2b\xec\x0d\x89\x54\x99\xb9\x38\x99\x16\xf7\xe0\x21\x79\x48\xc2\xbb\x61\x74\x12\x96\x1d\x3c\x6a\x72\xd5\x3c\x10\x67\x3a\x39\xed\x2b\x13\xcd\x66\xeb\x95\x09\x33\xa4\x6c\x97\xb1\xe8\xc6\xec\xc1\x75\x79\x9c\x46\x5e\x8d\xab\xd0\x6a\xfd\xb9\x2a\x55\x17\x10\x54\xb3\x19\xf0\x9a\xf6\xf1\xb1\x5d\xb6\xa7\x6d\xfb\xe0\x71\x17\x6b\xa2\x88\xfb\x00\xdf\xfe\x1a\x31\x77\x0c\x9a\x01\x7a\xb1\x32\xe3\x2b\x01\x07\x38\x6e\xc3\xa5\x5e\x23\xbc\x45\x9b\x7b\x50\xc1\xc9\x30\x8f\xdb\xe5\x2b\x7a\xd3\x5b\xfb\x33\x40\x1e\xa0\xd5\x98\x17\xbc\x8b\x87\xc3\x89\xd3\x5d\xa0\x8e\xb2\xaa\xaa\xf6\x8e\x69\x88\x06\xc5\xfa\x89\x21\xf3\x08\x9d\x69\x2e\x09\x33\x9b\x29\x0d\x46\x0f\x8c\xcc\x49\x34\xb0\x69\x51\xbd\xf9\x06\xcd\x68\xad\x66\x4c\xbc\x3e\xac\x61\xbd\x0a\x88\x0e\xc8\xdf\x3d\xee\x7c\x04\x4c\x9d\x0a\x5e\x6b\x91\xd6\xee\xc7\xed\x28\x8d\xab\x4d\x87\x89\x73\xd0\x6e\xa4\xd0\x1e\x16\x8b\x14\xe1\x76\x44\x03\x7f\x63\xac\xe4\xcd\x49\x9c\xc5\x92\xf4\xab\x32\xa1\x48\x5b\x02\x03\x01\x00\x01\xa3\x81\xb9\x30\x81\xb6\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\xc6\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xa1\x72\x5f\x26\x1b\x28\x98\x43\x95\x5d\x07\x37\xd5\x85\x96\x9d\x4b\xd2\xc3\x45\x30\x44\x06\x03\x55\x1d\x1f\x04\x3d\x30\x3b\x30\x39\xa0\x37\xa0\x35\x86\x33\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2e\x63\x6f\x6d\x2f\x55\x54\x4e\x2d\x55\x53\x45\x52\x46\x69\x72\x73\x74\x2d\x48\x61\x72\x64\x77\x61\x72\x65\x2e\x63\x72\x6c\x30\x31\x06\x03\x55\x1d\x25\x04\x2a\x30\x28\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x05\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x06\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x07\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x47\x19\x0f\xde\x74\xc6\x99\x97\xaf\xfc\xad\x28\x5e\x75\x8e\xeb\x2d\x67\xee\x4e\x7b\x2b\xd7\x0c\xff\xf6\xde\xcb\x55\xa2\x0a\xe1\x4c\x54\x65\x93\x60\x6b\x9f\x12\x9c\xad\x5e\x83\x2c\xeb\x5a\xae\xc0\xe4\x2d\xf4\x00\x63\x1d\xb8\xc0\x6c\xf2\xcf\x49\xbb\x4d\x93\x6f\x06\xa6\x0a\x22\xb2\x49\x62\x08\x4e\xff\xc8\xc8\x14\xb2\x88\x16\x5d\xe7\x01\xe4\x12\x95\xe5\x45\x34\xb3\x8b\x69\xbd\xcf\xb4\x85\x8f\x75\x51\x9e\x7d\x3a\x38\x3a\x14\x48\x12\xc6\xfb\xa7\x3b\x1a\x8d\x0d\x82\x40\x07\xe8\x04\x08\x90\xa1\x89\xcb\x19\x50\xdf\xca\x1c\x01\xbc\x1d\x04\x19\x7b\x10\x76\x97\x3b\xee\x90\x90\xca\xc4\x0e\x1f\x16\x6e\x75\xef\x33\xf8\xd3\x6f\x5b\x1e\x96\xe3\xe0\x74\x77\x74\x7b\x8a\xa2\x6e\x2d\xdd\x76\xd6\x39\x30\x82\xf0\xab\x9c\x52\xf2\x2a\xc7\xaf\x49\x5e\x7e\xc7\x68\xe5\x82\x81\xc8\x6a\x27\xf9\x27\x88\x2a\xd5\x58\x50\x95\x1f\xf0\x3b\x1c\x57\xbb\x7d\x14\x39\x62\x2b\x9a\xc9\x94\x92\x2a\xa3\x22\x0c\xff\x89\x26\x7d\x5f\x23\x2b\x47\xd7\x15\x1d\xa9\x6a\x9e\x51\x0d\x2a\x51\x9e\x81\xf9\xd4\x3b\x5e\x70\x12\x7f\x10\x32\x9c\x1e\xbb\x9d\xf8\x66\xa8", 0 }, + /* Anchor: 170 UTN-USERFirst-NetworkApplication.der serial: #{a.serial.to_s} + C=US,ST=UT,L=Salt Lake City,O=The USERTRUST Network,OU=http://www.usertrust.com,CN=UTN-USERFirst-Network Applications + */ + { 1128, "\x30\x82\x04\x64\x30\x82\x03\x4c\xa0\x03\x02\x01\x02\x02\x10\x44\xbe\x0c\x8b\x50\x00\x24\xb4\x11\xd3\x36\x30\x4b\xc0\x33\x77\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xa3\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x13\x02\x55\x54\x31\x17\x30\x15\x06\x03\x55\x04\x07\x13\x0e\x53\x61\x6c\x74\x20\x4c\x61\x6b\x65\x20\x43\x69\x74\x79\x31\x1e\x30\x1c\x06\x03\x55\x04\x0a\x13\x15\x54\x68\x65\x20\x55\x53\x45\x52\x54\x52\x55\x53\x54\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x21\x30\x1f\x06\x03\x55\x04\x0b\x13\x18\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2e\x63\x6f\x6d\x31\x2b\x30\x29\x06\x03\x55\x04\x03\x13\x22\x55\x54\x4e\x2d\x55\x53\x45\x52\x46\x69\x72\x73\x74\x2d\x4e\x65\x74\x77\x6f\x72\x6b\x20\x41\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x73\x30\x1e\x17\x0d\x39\x39\x30\x37\x30\x39\x31\x38\x34\x38\x33\x39\x5a\x17\x0d\x31\x39\x30\x37\x30\x39\x31\x38\x35\x37\x34\x39\x5a\x30\x81\xa3\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x13\x02\x55\x54\x31\x17\x30\x15\x06\x03\x55\x04\x07\x13\x0e\x53\x61\x6c\x74\x20\x4c\x61\x6b\x65\x20\x43\x69\x74\x79\x31\x1e\x30\x1c\x06\x03\x55\x04\x0a\x13\x15\x54\x68\x65\x20\x55\x53\x45\x52\x54\x52\x55\x53\x54\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x21\x30\x1f\x06\x03\x55\x04\x0b\x13\x18\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2e\x63\x6f\x6d\x31\x2b\x30\x29\x06\x03\x55\x04\x03\x13\x22\x55\x54\x4e\x2d\x55\x53\x45\x52\x46\x69\x72\x73\x74\x2d\x4e\x65\x74\x77\x6f\x72\x6b\x20\x41\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x73\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xb3\xfb\x91\xa1\xe4\x36\x55\x85\xac\x06\x34\x5b\xa0\x9a\x58\xb2\xf8\xb5\x0f\x05\x77\x83\xae\x32\xb1\x76\x92\x68\xec\x23\x4a\xc9\x76\x3f\xe3\x9c\xb6\x37\x79\x03\xb9\xab\x69\x8d\x07\x25\xb6\x19\x67\xe4\xb0\x1b\x18\x73\x61\x4a\xe8\x7e\xcd\xd3\x2f\x64\xe3\xa6\x7c\x0c\xfa\x17\x80\xa3\x0d\x47\x89\x4f\x51\x71\x2f\xee\xfc\x3f\xf9\xb8\x16\x80\x87\x89\x93\x25\x20\x9a\x43\x82\x69\x24\x76\x28\x59\x35\xa1\x1d\xc0\x7f\x83\x06\x64\x16\x20\x2c\xd3\x49\xa4\x85\xb4\xc0\x61\x7f\x51\x08\xf8\x68\x15\x91\x80\xcb\xa5\xd5\xee\x3b\x3a\xf4\x84\x04\x5e\x60\x59\xa7\x8c\x34\x72\xee\xb8\x78\xc5\xd1\x3b\x12\x4a\x6f\x7e\x65\x27\xb9\xa4\x55\xc5\xb9\x6f\x43\xa4\xc5\x1d\x2c\x99\xc0\x52\xa4\x78\x4c\x15\xb3\x40\x98\x08\x6b\x43\xc6\x01\xb0\x7a\x7b\xf5\x6b\x1c\x22\x3f\xcb\xef\xff\xa8\xd0\x3a\x4b\x76\x15\x9e\xd2\xd1\xc6\x2e\xe3\xdb\x57\x1b\x32\xa2\xb8\x6f\xe8\x86\xa6\x3f\x70\xab\xe5\x70\x92\xab\x44\x1e\x40\x50\xfb\x9c\xa3\x62\xe4\x6c\x6e\xa0\xc8\xde\xe2\x80\x42\xfa\xe9\x2f\xe8\xce\x32\x04\x8f\x7c\x8d\xb7\x1c\xa3\x35\x3c\x15\xdd\x9e\xc3\xae\x97\xa5\x02\x03\x01\x00\x01\xa3\x81\x91\x30\x81\x8e\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\xc6\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xfa\x86\xc9\xdb\xe0\xba\xe9\x78\xf5\x4b\xa8\xd6\x15\xdf\xf0\xd3\xe1\x6a\x14\x3c\x30\x4f\x06\x03\x55\x1d\x1f\x04\x48\x30\x46\x30\x44\xa0\x42\xa0\x40\x86\x3e\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2e\x63\x6f\x6d\x2f\x55\x54\x4e\x2d\x55\x53\x45\x52\x46\x69\x72\x73\x74\x2d\x4e\x65\x74\x77\x6f\x72\x6b\x41\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x73\x2e\x63\x72\x6c\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xa4\xf3\x25\xcc\xd1\xd4\x91\x83\x22\xd0\xcc\x32\xab\x9b\x96\x4e\x34\x91\x54\x20\x25\x34\x61\x5f\x2a\x02\x15\xe1\x8b\xaa\xff\x7d\x64\x51\xcf\x0a\xff\xbc\x7d\xd8\x21\x6a\x78\xcb\x2f\x51\x6f\xf8\x42\x1d\x33\xbd\xeb\xb5\x7b\x94\xc3\xc3\xa9\xa0\x2d\xdf\xd1\x29\x1f\x1d\xfe\x8f\x3f\xbb\xa8\x45\x2a\x7f\xd1\x6e\x55\x24\xe2\xbb\x02\xfb\x31\x3f\xbe\xe8\xbc\xec\x40\x2b\xf8\x01\xd4\x56\x38\xe4\xca\x44\x82\xb5\x61\x20\x21\x67\x65\xf6\xf0\x0b\xe7\x34\xf8\xa5\xc2\x9c\xa3\x5c\x40\x1f\x85\x93\x95\x06\xde\x4f\xd4\x27\xa9\xb6\xa5\xfc\x16\xcd\x73\x31\x3f\xb8\x65\x27\xcf\xd4\x53\x1a\xf0\xac\x6e\x9f\x4f\x05\x0c\x03\x81\xa7\x84\x29\xc4\x5a\xbd\x64\x57\x72\xad\x3b\xcf\x37\x18\xa6\x98\xc6\xad\x06\xb4\xdc\x08\xa3\x04\xd5\x29\xa4\x96\x9a\x12\x67\x4a\x8c\x60\x45\x9d\xf1\x23\x9a\xb0\x00\x9c\x68\xb5\x98\x50\xd3\xef\x8e\x2e\x92\x65\xb1\x48\x3e\x21\xbe\x15\x30\x2a\x0d\xb5\x0c\xa3\x6b\x3f\xae\x7f\x57\xf5\x1f\x96\x7c\xdf\x6f\xdd\x82\x30\x2c\x65\x1b\x40\x4a\xcd\x68\xb9\x72\xec\x71\x76\xec\x54\x8e\x1f\x85\x0c\x01\x6a\xfa\xa6\x38\xac\x1f\xc4\x84", 0 }, + /* Anchor: 171 UTN-USERFirst-Object.crt serial: #{a.serial.to_s} + C=US,ST=UT,L=Salt Lake City,O=The USERTRUST Network,OU=http://www.usertrust.com,CN=UTN-USERFirst-Object + */ + { 1130, "\x30\x82\x04\x66\x30\x82\x03\x4e\xa0\x03\x02\x01\x02\x02\x10\x44\xbe\x0c\x8b\x50\x00\x24\xb4\x11\xd3\x36\x2d\xe0\xb3\x5f\x1b\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\x95\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x13\x02\x55\x54\x31\x17\x30\x15\x06\x03\x55\x04\x07\x13\x0e\x53\x61\x6c\x74\x20\x4c\x61\x6b\x65\x20\x43\x69\x74\x79\x31\x1e\x30\x1c\x06\x03\x55\x04\x0a\x13\x15\x54\x68\x65\x20\x55\x53\x45\x52\x54\x52\x55\x53\x54\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x21\x30\x1f\x06\x03\x55\x04\x0b\x13\x18\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2e\x63\x6f\x6d\x31\x1d\x30\x1b\x06\x03\x55\x04\x03\x13\x14\x55\x54\x4e\x2d\x55\x53\x45\x52\x46\x69\x72\x73\x74\x2d\x4f\x62\x6a\x65\x63\x74\x30\x1e\x17\x0d\x39\x39\x30\x37\x30\x39\x31\x38\x33\x31\x32\x30\x5a\x17\x0d\x31\x39\x30\x37\x30\x39\x31\x38\x34\x30\x33\x36\x5a\x30\x81\x95\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x13\x02\x55\x54\x31\x17\x30\x15\x06\x03\x55\x04\x07\x13\x0e\x53\x61\x6c\x74\x20\x4c\x61\x6b\x65\x20\x43\x69\x74\x79\x31\x1e\x30\x1c\x06\x03\x55\x04\x0a\x13\x15\x54\x68\x65\x20\x55\x53\x45\x52\x54\x52\x55\x53\x54\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x21\x30\x1f\x06\x03\x55\x04\x0b\x13\x18\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2e\x63\x6f\x6d\x31\x1d\x30\x1b\x06\x03\x55\x04\x03\x13\x14\x55\x54\x4e\x2d\x55\x53\x45\x52\x46\x69\x72\x73\x74\x2d\x4f\x62\x6a\x65\x63\x74\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xce\xaa\x81\x3f\xa3\xa3\x61\x78\xaa\x31\x00\x55\x95\x11\x9e\x27\x0f\x1f\x1c\xdf\x3a\x9b\x82\x68\x30\xc0\x4a\x61\x1d\xf1\x2f\x0e\xfa\xbe\x79\xf7\xa5\x23\xef\x55\x51\x96\x84\xcd\xdb\xe3\xb9\x6e\x3e\x31\xd8\x0a\x20\x67\xc7\xf4\xd9\xbf\x94\xeb\x47\x04\x3e\x02\xce\x2a\xa2\x5d\x87\x04\x09\xf6\x30\x9d\x18\x8a\x97\xb2\xaa\x1c\xfc\x41\xd2\xa1\x36\xcb\xfb\x3d\x91\xba\xe7\xd9\x70\x35\xfa\xe4\xe7\x90\xc3\x9b\xa3\x9b\xd3\x3c\xf5\x12\x99\x77\xb1\xb7\x09\xe0\x68\xe6\x1c\xb8\xf3\x94\x63\x88\x6a\x6a\xfe\x0b\x76\xc9\xbe\xf4\x22\xe4\x67\xb9\xab\x1a\x5e\x77\xc1\x85\x07\xdd\x0d\x6c\xbf\xee\x06\xc7\x77\x6a\x41\x9e\xa7\x0f\xd7\xfb\xee\x94\x17\xb7\xfc\x85\xbe\xa4\xab\xc4\x1c\x31\xdd\xd7\xb6\xd1\xe4\xf0\xef\xdf\x16\x8f\xb2\x52\x93\xd7\xa1\xd4\x89\xa1\x07\x2e\xbf\xe1\x01\x12\x42\x1e\x1a\xe1\xd8\x95\x34\xdb\x64\x79\x28\xff\xba\x2e\x11\xc2\xe5\xe8\x5b\x92\x48\xfb\x47\x0b\xc2\x6c\xda\xad\x32\x83\x41\xf3\xa5\xe5\x41\x70\xfd\x65\x90\x6d\xfa\xfa\x51\xc4\xf9\xbd\x96\x2b\x19\x04\x2c\xd3\x6d\xa7\xdc\xf0\x7f\x6f\x83\x65\xe2\x6a\xab\x87\x86\x75\x02\x03\x01\x00\x01\xa3\x81\xaf\x30\x81\xac\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\xc6\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xda\xed\x64\x74\x14\x9c\x14\x3c\xab\xdd\x99\xa9\xbd\x5b\x28\x4d\x8b\x3c\xc9\xd8\x30\x42\x06\x03\x55\x1d\x1f\x04\x3b\x30\x39\x30\x37\xa0\x35\xa0\x33\x86\x31\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2e\x63\x6f\x6d\x2f\x55\x54\x4e\x2d\x55\x53\x45\x52\x46\x69\x72\x73\x74\x2d\x4f\x62\x6a\x65\x63\x74\x2e\x63\x72\x6c\x30\x29\x06\x03\x55\x1d\x25\x04\x22\x30\x20\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x03\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x08\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x0a\x03\x04\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x08\x1f\x52\xb1\x37\x44\x78\xdb\xfd\xce\xb9\xda\x95\x96\x98\xaa\x55\x64\x80\xb5\x5a\x40\xdd\x21\xa5\xc5\xc1\xf3\x5f\x2c\x4c\xc8\x47\x5a\x69\xea\xe8\xf0\x35\x35\xf4\xd0\x25\xf3\xc8\xa6\xa4\x87\x4a\xbd\x1b\xb1\x73\x08\xbd\xd4\xc3\xca\xb6\x35\xbb\x59\x86\x77\x31\xcd\xa7\x80\x14\xae\x13\xef\xfc\xb1\x48\xf9\x6b\x25\x25\x2d\x51\xb6\x2c\x6d\x45\xc1\x98\xc8\x8a\x56\x5d\x3e\xee\x43\x4e\x3e\x6b\x27\x8e\xd0\x3a\x4b\x85\x0b\x5f\xd3\xed\x6a\xa7\x75\xcb\xd1\x5a\x87\x2f\x39\x75\x13\x5a\x72\xb0\x02\x81\x9f\xbe\xf0\x0f\x84\x54\x20\x62\x6c\x69\xd4\xe1\x4d\xc6\x0d\x99\x43\x01\x0d\x12\x96\x8c\x78\x9d\xbf\x50\xa2\xb1\x44\xaa\x6a\xcf\x17\x7a\xcf\x6f\x0f\xd4\xf8\x24\x55\x5f\xf0\x34\x16\x49\x66\x3e\x50\x46\xc9\x63\x71\x38\x31\x62\xb8\x62\xb9\xf3\x53\xad\x6c\xb5\x2b\xa2\x12\xaa\x19\x4f\x09\xda\x5e\xe7\x93\xc6\x8e\x14\x08\xfe\xf0\x30\x80\x18\xa0\x86\x85\x4d\xc8\x7d\xd7\x8b\x03\xfe\x6e\xd5\xf7\x9d\x16\xac\x92\x2c\xa0\x23\xe5\x9c\x91\x52\x1f\x94\xdf\x17\x94\x73\xc3\xb3\xc1\xc1\x71\x05\x20\x00\x78\xbd\x13\x52\x1d\xa8\x3e\xcd\x00\x1f\xc8", 0 }, + /* Anchor: 172 UTN_DATACorp_SGC.cer serial: #{a.serial.to_s} + C=US,ST=UT,L=Salt Lake City,O=The USERTRUST Network,OU=http://www.usertrust.com,CN=UTN - DATACorp SGC + */ + { 1122, "\x30\x82\x04\x5e\x30\x82\x03\x46\xa0\x03\x02\x01\x02\x02\x10\x44\xbe\x0c\x8b\x50\x00\x21\xb4\x11\xd3\x2a\x68\x06\xa9\xad\x69\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\x93\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x13\x02\x55\x54\x31\x17\x30\x15\x06\x03\x55\x04\x07\x13\x0e\x53\x61\x6c\x74\x20\x4c\x61\x6b\x65\x20\x43\x69\x74\x79\x31\x1e\x30\x1c\x06\x03\x55\x04\x0a\x13\x15\x54\x68\x65\x20\x55\x53\x45\x52\x54\x52\x55\x53\x54\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x21\x30\x1f\x06\x03\x55\x04\x0b\x13\x18\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2e\x63\x6f\x6d\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x13\x12\x55\x54\x4e\x20\x2d\x20\x44\x41\x54\x41\x43\x6f\x72\x70\x20\x53\x47\x43\x30\x1e\x17\x0d\x39\x39\x30\x36\x32\x34\x31\x38\x35\x37\x32\x31\x5a\x17\x0d\x31\x39\x30\x36\x32\x34\x31\x39\x30\x36\x33\x30\x5a\x30\x81\x93\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x13\x02\x55\x54\x31\x17\x30\x15\x06\x03\x55\x04\x07\x13\x0e\x53\x61\x6c\x74\x20\x4c\x61\x6b\x65\x20\x43\x69\x74\x79\x31\x1e\x30\x1c\x06\x03\x55\x04\x0a\x13\x15\x54\x68\x65\x20\x55\x53\x45\x52\x54\x52\x55\x53\x54\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x21\x30\x1f\x06\x03\x55\x04\x0b\x13\x18\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2e\x63\x6f\x6d\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x13\x12\x55\x54\x4e\x20\x2d\x20\x44\x41\x54\x41\x43\x6f\x72\x70\x20\x53\x47\x43\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xdf\xee\x58\x10\xa2\x2b\x6e\x55\xc4\x8e\xbf\x2e\x46\x09\xe7\xe0\x08\x0f\x2e\x2b\x7a\x13\x94\x1b\xbd\xf6\xb6\x80\x8e\x65\x05\x93\x00\x1e\xbc\xaf\xe2\x0f\x8e\x19\x0d\x12\x47\xec\xac\xad\xa3\xfa\x2e\x70\xf8\xde\x6e\xfb\x56\x42\x15\x9e\x2e\x5c\xef\x23\xde\x21\xb9\x05\x76\x27\x19\x0f\x4f\xd6\xc3\x9c\xb4\xbe\x94\x19\x63\xf2\xa6\x11\x0a\xeb\x53\x48\x9c\xbe\xf2\x29\x3b\x16\xe8\x1a\xa0\x4c\xa6\xc9\xf4\x18\x59\x68\xc0\x70\xf2\x53\x00\xc0\x5e\x50\x82\xa5\x56\x6f\x36\xf9\x4a\xe0\x44\x86\xa0\x4d\x4e\xd6\x47\x6e\x49\x4a\xcb\x67\xd7\xa6\xc4\x05\xb9\x8e\x1e\xf4\xfc\xff\xcd\xe7\x36\xe0\x9c\x05\x6c\xb2\x33\x22\x15\xd0\xb4\xe0\xcc\x17\xc0\xb2\xc0\xf4\xfe\x32\x3f\x29\x2a\x95\x7b\xd8\xf2\xa7\x4e\x0f\x54\x7c\xa1\x0d\x80\xb3\x09\x03\xc1\xff\x5c\xdd\x5e\x9a\x3e\xbc\xae\xbc\x47\x8a\x6a\xae\x71\xca\x1f\xb1\x2a\xb8\x5f\x42\x05\x0b\xec\x46\x30\xd1\x72\x0b\xca\xe9\x56\x6d\xf5\xef\xdf\x78\xbe\x61\xba\xb2\xa5\xae\x04\x4c\xbc\xa8\xac\x69\x15\x97\xbd\xef\xeb\xb4\x8c\xbf\x35\xf8\xd4\xc3\xd1\x28\x0e\x5c\x3a\x9f\x70\x18\x33\x20\x77\xc4\xa2\xaf\x02\x03\x01\x00\x01\xa3\x81\xab\x30\x81\xa8\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\xc6\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x53\x32\xd1\xb3\xcf\x7f\xfa\xe0\xf1\xa0\x5d\x85\x4e\x92\xd2\x9e\x45\x1d\xb4\x4f\x30\x3d\x06\x03\x55\x1d\x1f\x04\x36\x30\x34\x30\x32\xa0\x30\xa0\x2e\x86\x2c\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2e\x63\x6f\x6d\x2f\x55\x54\x4e\x2d\x44\x41\x54\x41\x43\x6f\x72\x70\x53\x47\x43\x2e\x63\x72\x6c\x30\x2a\x06\x03\x55\x1d\x25\x04\x23\x30\x21\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x01\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x0a\x03\x03\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x04\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x27\x35\x97\x00\x8a\x8b\x28\xbd\xc6\x33\x30\x1e\x29\xfc\xe2\xf7\xd5\x98\xd4\x40\xbb\x60\xca\xbf\xab\x17\x2c\x09\x36\x7f\x50\xfa\x41\xdc\xae\x96\x3a\x0a\x23\x3e\x89\x59\xc9\xa3\x07\xed\x1b\x37\xad\xfc\x7c\xbe\x51\x49\x5a\xde\x3a\x0a\x54\x08\x16\x45\xc2\x99\xb1\x87\xcd\x8c\x68\xe0\x69\x03\xe9\xc4\x4e\x98\xb2\x3b\x8c\x16\xb3\x0e\xa0\x0c\x98\x50\x9b\x93\xa9\x70\x09\xc8\x2c\xa3\x8f\xdf\x02\xe4\xe0\x71\x3a\xf1\xb4\x23\x72\xa0\xaa\x01\xdf\xdf\x98\x3e\x14\x50\xa0\x31\x26\xbd\x28\xe9\x5a\x30\x26\x75\xf9\x7b\x60\x1c\x8d\xf3\xcd\x50\x26\x6d\x04\x27\x9a\xdf\xd5\x0d\x45\x47\x29\x6b\x2c\xe6\x76\xd9\xa9\x29\x7d\x32\xdd\xc9\x36\x3c\xbd\xae\x35\xf1\x11\x9e\x1d\xbb\x90\x3f\x12\x47\x4e\x8e\xd7\x7e\x0f\x62\x73\x1d\x52\x26\x38\x1c\x18\x49\xfd\x30\x74\x9a\xc4\xe5\x22\x2f\xd8\xc0\x8d\xed\x91\x7a\x4c\x00\x8f\x72\x7f\x5d\xda\xdd\x1b\x8b\x45\x6b\xe7\xdd\x69\x97\xa8\xc5\x56\x4c\x0f\x0c\xf6\x9f\x7a\x91\x37\xf6\x97\x82\xe0\xdd\x71\x69\xff\x76\x3f\x60\x4d\x3c\xcf\xf7\x99\xf9\xc6\x57\xf4\xc9\x55\x39\x78\xba\x2c\x79\xc9\xa6\x88\x2b\xf4\x08", 0 }, + /* Anchor: 173 uzleti.cer serial: #{a.serial.to_s} + C=HU,L=Budapest,O=NetLock Halozatbiztonsagi Kft.,OU=Tanusitvanykiadok,CN=NetLock Uzleti (Class B) Tanusitvanykiado + */ + { 1359, "\x30\x82\x05\x4b\x30\x82\x04\xb4\xa0\x03\x02\x01\x02\x02\x01\x69\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x30\x81\x99\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0f\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0a\x13\x1e\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x48\x61\x6c\x6f\x7a\x61\x74\x62\x69\x7a\x74\x6f\x6e\x73\x61\x67\x69\x20\x4b\x66\x74\x2e\x31\x1a\x30\x18\x06\x03\x55\x04\x0b\x13\x11\x54\x61\x6e\x75\x73\x69\x74\x76\x61\x6e\x79\x6b\x69\x61\x64\x6f\x6b\x31\x32\x30\x30\x06\x03\x55\x04\x03\x13\x29\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x55\x7a\x6c\x65\x74\x69\x20\x28\x43\x6c\x61\x73\x73\x20\x42\x29\x20\x54\x61\x6e\x75\x73\x69\x74\x76\x61\x6e\x79\x6b\x69\x61\x64\x6f\x30\x1e\x17\x0d\x39\x39\x30\x32\x32\x35\x31\x34\x31\x30\x32\x32\x5a\x17\x0d\x31\x39\x30\x32\x32\x30\x31\x34\x31\x30\x32\x32\x5a\x30\x81\x99\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0f\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0a\x13\x1e\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x48\x61\x6c\x6f\x7a\x61\x74\x62\x69\x7a\x74\x6f\x6e\x73\x61\x67\x69\x20\x4b\x66\x74\x2e\x31\x1a\x30\x18\x06\x03\x55\x04\x0b\x13\x11\x54\x61\x6e\x75\x73\x69\x74\x76\x61\x6e\x79\x6b\x69\x61\x64\x6f\x6b\x31\x32\x30\x30\x06\x03\x55\x04\x03\x13\x29\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x55\x7a\x6c\x65\x74\x69\x20\x28\x43\x6c\x61\x73\x73\x20\x42\x29\x20\x54\x61\x6e\x75\x73\x69\x74\x76\x61\x6e\x79\x6b\x69\x61\x64\x6f\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xb1\xea\x04\xec\x20\xa0\x23\xc2\x8f\x38\x60\xcf\xc7\x46\xb3\xd5\x1b\xfe\xfb\xb9\x99\x9e\x04\xdc\x1c\x7f\x8c\x4a\x81\x98\xee\xa4\xd4\xca\x8a\x17\xb9\x22\x7f\x83\x0a\x75\x4c\x9b\xc0\x69\xd8\x64\x39\xa3\xed\x92\xa3\xfd\x5b\x5c\x74\x1a\xc0\x47\xca\x3a\x69\x76\x9a\xba\xe2\x44\x17\xfc\x4c\xa3\xd5\xfe\xb8\x97\x88\xaf\x88\x03\x89\x1f\xa4\xf2\x04\x3e\xc8\x07\x0b\xe6\xf9\xb3\x2f\x7a\x62\x14\x09\x46\x14\xca\x64\xf5\x8b\x80\xb5\x62\xa8\xd8\x6b\xd6\x71\x93\x2d\xb3\xbf\x09\x54\x58\xed\x06\xeb\xa8\x7b\xdc\x43\xb1\xa1\x69\x02\x03\x01\x00\x01\xa3\x82\x02\x9f\x30\x82\x02\x9b\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01\x04\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x00\x06\x30\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x82\x02\x60\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x0d\x04\x82\x02\x51\x16\x82\x02\x4d\x46\x49\x47\x59\x45\x4c\x45\x4d\x21\x20\x45\x7a\x65\x6e\x20\x74\x61\x6e\x75\x73\x69\x74\x76\x61\x6e\x79\x20\x61\x20\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x4b\x66\x74\x2e\x20\x41\x6c\x74\x61\x6c\x61\x6e\x6f\x73\x20\x53\x7a\x6f\x6c\x67\x61\x6c\x74\x61\x74\x61\x73\x69\x20\x46\x65\x6c\x74\x65\x74\x65\x6c\x65\x69\x62\x65\x6e\x20\x6c\x65\x69\x72\x74\x20\x65\x6c\x6a\x61\x72\x61\x73\x6f\x6b\x20\x61\x6c\x61\x70\x6a\x61\x6e\x20\x6b\x65\x73\x7a\x75\x6c\x74\x2e\x20\x41\x20\x68\x69\x74\x65\x6c\x65\x73\x69\x74\x65\x73\x20\x66\x6f\x6c\x79\x61\x6d\x61\x74\x61\x74\x20\x61\x20\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x4b\x66\x74\x2e\x20\x74\x65\x72\x6d\x65\x6b\x66\x65\x6c\x65\x6c\x6f\x73\x73\x65\x67\x2d\x62\x69\x7a\x74\x6f\x73\x69\x74\x61\x73\x61\x20\x76\x65\x64\x69\x2e\x20\x41\x20\x64\x69\x67\x69\x74\x61\x6c\x69\x73\x20\x61\x6c\x61\x69\x72\x61\x73\x20\x65\x6c\x66\x6f\x67\x61\x64\x61\x73\x61\x6e\x61\x6b\x20\x66\x65\x6c\x74\x65\x74\x65\x6c\x65\x20\x61\x7a\x20\x65\x6c\x6f\x69\x72\x74\x20\x65\x6c\x6c\x65\x6e\x6f\x72\x7a\x65\x73\x69\x20\x65\x6c\x6a\x61\x72\x61\x73\x20\x6d\x65\x67\x74\x65\x74\x65\x6c\x65\x2e\x20\x41\x7a\x20\x65\x6c\x6a\x61\x72\x61\x73\x20\x6c\x65\x69\x72\x61\x73\x61\x20\x6d\x65\x67\x74\x61\x6c\x61\x6c\x68\x61\x74\x6f\x20\x61\x20\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x4b\x66\x74\x2e\x20\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x68\x6f\x6e\x6c\x61\x70\x6a\x61\x6e\x20\x61\x20\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x6e\x65\x74\x6c\x6f\x63\x6b\x2e\x6e\x65\x74\x2f\x64\x6f\x63\x73\x20\x63\x69\x6d\x65\x6e\x20\x76\x61\x67\x79\x20\x6b\x65\x72\x68\x65\x74\x6f\x20\x61\x7a\x20\x65\x6c\x6c\x65\x6e\x6f\x72\x7a\x65\x73\x40\x6e\x65\x74\x6c\x6f\x63\x6b\x2e\x6e\x65\x74\x20\x65\x2d\x6d\x61\x69\x6c\x20\x63\x69\x6d\x65\x6e\x2e\x20\x49\x4d\x50\x4f\x52\x54\x41\x4e\x54\x21\x20\x54\x68\x65\x20\x69\x73\x73\x75\x61\x6e\x63\x65\x20\x61\x6e\x64\x20\x74\x68\x65\x20\x75\x73\x65\x20\x6f\x66\x20\x74\x68\x69\x73\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x69\x73\x20\x73\x75\x62\x6a\x65\x63\x74\x20\x74\x6f\x20\x74\x68\x65\x20\x4e\x65\x74\x4c\x6f\x63\x6b\x20\x43\x50\x53\x20\x61\x76\x61\x69\x6c\x61\x62\x6c\x65\x20\x61\x74\x20\x68\x74\x74\x70\x73\x3a\x2f\x2f\x77\x77\x77\x2e\x6e\x65\x74\x6c\x6f\x63\x6b\x2e\x6e\x65\x74\x2f\x64\x6f\x63\x73\x20\x6f\x72\x20\x62\x79\x20\x65\x2d\x6d\x61\x69\x6c\x20\x61\x74\x20\x63\x70\x73\x40\x6e\x65\x74\x6c\x6f\x63\x6b\x2e\x6e\x65\x74\x2e\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x04\x05\x00\x03\x81\x81\x00\x04\xdb\xae\x8c\x17\xaf\xf8\x0e\x90\x31\x4e\xcd\x3e\x09\xc0\x6d\x3a\xb0\xf8\x33\x4c\x47\x4c\xe3\x75\x88\x10\x97\xac\xb0\x38\x15\x91\xc6\x29\x96\xcc\x21\xc0\x6d\x3c\xa5\x74\xcf\xd8\x82\xa5\x39\xc3\x65\xe3\x42\x70\xbb\x22\x90\xe3\x7d\xdb\x35\x76\xe1\xa0\xb5\xda\x9f\x70\x6e\x93\x1a\x30\x39\x1d\x30\xdb\x2e\xe3\x7c\xb2\x91\xb2\xd1\x37\x29\xfa\xb9\xd6\x17\x5c\x47\x4f\xe3\x1d\x38\xeb\x9f\xd5\x7b\x95\xa8\x28\x9e\x15\x4a\xd1\xd1\xd0\x2b\x00\x97\xa0\xe2\x92\x36\x2b\x63\xac\x58\x01\x6b\x33\x29\x50\x86\x83\xf1\x01\x48", 0 }, + /* Anchor: 174 ValiCertClass1PVA.cer serial: #{a.serial.to_s} + L=ValiCert Validation Network,O=ValiCert\, Inc.,OU=ValiCert Class 1 Policy Validation Authority,CN=http://www.valicert.com/,1.2.840.113549.1.9.1=#1611696E666F4076616C69636572742E636F6D + */ + { 747, "\x30\x82\x02\xe7\x30\x82\x02\x50\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xbb\x31\x24\x30\x22\x06\x03\x55\x04\x07\x13\x1b\x56\x61\x6c\x69\x43\x65\x72\x74\x20\x56\x61\x6c\x69\x64\x61\x74\x69\x6f\x6e\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x61\x6c\x69\x43\x65\x72\x74\x2c\x20\x49\x6e\x63\x2e\x31\x35\x30\x33\x06\x03\x55\x04\x0b\x13\x2c\x56\x61\x6c\x69\x43\x65\x72\x74\x20\x43\x6c\x61\x73\x73\x20\x31\x20\x50\x6f\x6c\x69\x63\x79\x20\x56\x61\x6c\x69\x64\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x76\x61\x6c\x69\x63\x65\x72\x74\x2e\x63\x6f\x6d\x2f\x31\x20\x30\x1e\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x11\x69\x6e\x66\x6f\x40\x76\x61\x6c\x69\x63\x65\x72\x74\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x39\x39\x30\x36\x32\x35\x32\x32\x32\x33\x34\x38\x5a\x17\x0d\x31\x39\x30\x36\x32\x35\x32\x32\x32\x33\x34\x38\x5a\x30\x81\xbb\x31\x24\x30\x22\x06\x03\x55\x04\x07\x13\x1b\x56\x61\x6c\x69\x43\x65\x72\x74\x20\x56\x61\x6c\x69\x64\x61\x74\x69\x6f\x6e\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x61\x6c\x69\x43\x65\x72\x74\x2c\x20\x49\x6e\x63\x2e\x31\x35\x30\x33\x06\x03\x55\x04\x0b\x13\x2c\x56\x61\x6c\x69\x43\x65\x72\x74\x20\x43\x6c\x61\x73\x73\x20\x31\x20\x50\x6f\x6c\x69\x63\x79\x20\x56\x61\x6c\x69\x64\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x76\x61\x6c\x69\x63\x65\x72\x74\x2e\x63\x6f\x6d\x2f\x31\x20\x30\x1e\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x11\x69\x6e\x66\x6f\x40\x76\x61\x6c\x69\x63\x65\x72\x74\x2e\x63\x6f\x6d\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd8\x59\x82\x7a\x89\xb8\x96\xba\xa6\x2f\x68\x6f\x58\x2e\xa7\x54\x1c\x06\x6e\xf4\xea\x8d\x48\xbc\x31\x94\x17\xf0\xf3\x4e\xbc\xb2\xb8\x35\x92\x76\xb0\xd0\xa5\xa5\x01\xd7\x00\x03\x12\x22\x19\x08\xf8\xff\x11\x23\x9b\xce\x07\xf5\xbf\x69\x1a\x26\xfe\x4e\xe9\xd1\x7f\x9d\x2c\x40\x1d\x59\x68\x6e\xa6\xf8\x58\xb0\x9d\x1a\x8f\xd3\x3f\xf1\xdc\x19\x06\x81\xa8\x0e\xe0\x3a\xdd\xc8\x53\x45\x09\x06\xe6\x0f\x70\xc3\xfa\x40\xa6\x0e\xe2\x56\x05\x0f\x18\x4d\xfc\x20\x82\xd1\x73\x55\x74\x8d\x76\x72\xa0\x1d\x9d\x1d\xc0\xdd\x3f\x71\x02\x03\x01\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x50\x68\x3d\x49\xf4\x2c\x1c\x06\x94\xdf\x95\x60\x7f\x96\x7b\x17\xfe\x4f\x71\xad\x64\xc8\xdd\x77\xd2\xef\x59\x55\xe8\x3f\xe8\x8e\x05\x2a\x21\xf2\x07\xd2\xb5\xa7\x52\xfe\x9c\xb1\xb6\xe2\x5b\x77\x17\x40\xea\x72\xd6\x23\xcb\x28\x81\x32\xc3\x00\x79\x18\xec\x59\x17\x89\xc9\xc6\x6a\x1e\x71\xc9\xfd\xb7\x74\xa5\x25\x45\x69\xc5\x48\xab\x19\xe1\x45\x8a\x25\x6b\x19\xee\xe5\xbb\x12\xf5\x7f\xf7\xa6\x8d\x51\xc3\xf0\x9d\x74\xb7\xa9\x3e\xa0\xa5\xff\xb6\x49\x03\x13\xda\x22\xcc\xed\x71\x82\x2b\x99\xcf\x3a\xb7\xf5\x2d\x72\xc8", 0 }, + /* Anchor: 175 ValiCertClass2PVA.cer serial: #{a.serial.to_s} + L=ValiCert Validation Network,O=ValiCert\, Inc.,OU=ValiCert Class 2 Policy Validation Authority,CN=http://www.valicert.com/,1.2.840.113549.1.9.1=#1611696E666F4076616C69636572742E636F6D + */ + { 747, "\x30\x82\x02\xe7\x30\x82\x02\x50\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xbb\x31\x24\x30\x22\x06\x03\x55\x04\x07\x13\x1b\x56\x61\x6c\x69\x43\x65\x72\x74\x20\x56\x61\x6c\x69\x64\x61\x74\x69\x6f\x6e\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x61\x6c\x69\x43\x65\x72\x74\x2c\x20\x49\x6e\x63\x2e\x31\x35\x30\x33\x06\x03\x55\x04\x0b\x13\x2c\x56\x61\x6c\x69\x43\x65\x72\x74\x20\x43\x6c\x61\x73\x73\x20\x32\x20\x50\x6f\x6c\x69\x63\x79\x20\x56\x61\x6c\x69\x64\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x76\x61\x6c\x69\x63\x65\x72\x74\x2e\x63\x6f\x6d\x2f\x31\x20\x30\x1e\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x11\x69\x6e\x66\x6f\x40\x76\x61\x6c\x69\x63\x65\x72\x74\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x39\x39\x30\x36\x32\x36\x30\x30\x31\x39\x35\x34\x5a\x17\x0d\x31\x39\x30\x36\x32\x36\x30\x30\x31\x39\x35\x34\x5a\x30\x81\xbb\x31\x24\x30\x22\x06\x03\x55\x04\x07\x13\x1b\x56\x61\x6c\x69\x43\x65\x72\x74\x20\x56\x61\x6c\x69\x64\x61\x74\x69\x6f\x6e\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x61\x6c\x69\x43\x65\x72\x74\x2c\x20\x49\x6e\x63\x2e\x31\x35\x30\x33\x06\x03\x55\x04\x0b\x13\x2c\x56\x61\x6c\x69\x43\x65\x72\x74\x20\x43\x6c\x61\x73\x73\x20\x32\x20\x50\x6f\x6c\x69\x63\x79\x20\x56\x61\x6c\x69\x64\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x76\x61\x6c\x69\x63\x65\x72\x74\x2e\x63\x6f\x6d\x2f\x31\x20\x30\x1e\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x11\x69\x6e\x66\x6f\x40\x76\x61\x6c\x69\x63\x65\x72\x74\x2e\x63\x6f\x6d\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xce\x3a\x71\xca\xe5\xab\xc8\x59\x92\x55\xd7\xab\xd8\x74\x0e\xf9\xee\xd9\xf6\x55\x47\x59\x65\x47\x0e\x05\x55\xdc\xeb\x98\x36\x3c\x5c\x53\x5d\xd3\x30\xcf\x38\xec\xbd\x41\x89\xed\x25\x42\x09\x24\x6b\x0a\x5e\xb3\x7c\xdd\x52\x2d\x4c\xe6\xd4\xd6\x7d\x5a\x59\xa9\x65\xd4\x49\x13\x2d\x24\x4d\x1c\x50\x6f\xb5\xc1\x85\x54\x3b\xfe\x71\xe4\xd3\x5c\x42\xf9\x80\xe0\x91\x1a\x0a\x5b\x39\x36\x67\xf3\x3f\x55\x7c\x1b\x3f\xb4\x5f\x64\x73\x34\xe3\xb4\x12\xbf\x87\x64\xf8\xda\x12\xff\x37\x27\xc1\xb3\x43\xbb\xef\x7b\x6e\x2e\x69\xf7\x02\x03\x01\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x3b\x7f\x50\x6f\x6f\x50\x94\x99\x49\x62\x38\x38\x1f\x4b\xf8\xa5\xc8\x3e\xa7\x82\x81\xf6\x2b\xc7\xe8\xc5\xce\xe8\x3a\x10\x82\xcb\x18\x00\x8e\x4d\xbd\xa8\x58\x7f\xa1\x79\x00\xb5\xbb\xe9\x8d\xaf\x41\xd9\x0f\x34\xee\x21\x81\x19\xa0\x32\x49\x28\xf4\xc4\x8e\x56\xd5\x52\x33\xfd\x50\xd5\x7e\x99\x6c\x03\xe4\xc9\x4c\xfc\xcb\x6c\xab\x66\xb3\x4a\x21\x8c\xe5\xb5\x0c\x32\x3e\x10\xb2\xcc\x6c\xa1\xdc\x9a\x98\x4c\x02\x5b\xf3\xce\xb9\x9e\xa5\x72\x0e\x4a\xb7\x3f\x3c\xe6\x16\x68\xf8\xbe\xed\x74\x4c\xbc\x5b\xd5\x62\x1f\x43\xdd", 0 }, + /* Anchor: 176 ValiCertClass3PVA.cer serial: #{a.serial.to_s} + L=ValiCert Validation Network,O=ValiCert\, Inc.,OU=ValiCert Class 3 Policy Validation Authority,CN=http://www.valicert.com/,1.2.840.113549.1.9.1=#1611696E666F4076616C69636572742E636F6D + */ + { 747, "\x30\x82\x02\xe7\x30\x82\x02\x50\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xbb\x31\x24\x30\x22\x06\x03\x55\x04\x07\x13\x1b\x56\x61\x6c\x69\x43\x65\x72\x74\x20\x56\x61\x6c\x69\x64\x61\x74\x69\x6f\x6e\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x61\x6c\x69\x43\x65\x72\x74\x2c\x20\x49\x6e\x63\x2e\x31\x35\x30\x33\x06\x03\x55\x04\x0b\x13\x2c\x56\x61\x6c\x69\x43\x65\x72\x74\x20\x43\x6c\x61\x73\x73\x20\x33\x20\x50\x6f\x6c\x69\x63\x79\x20\x56\x61\x6c\x69\x64\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x76\x61\x6c\x69\x63\x65\x72\x74\x2e\x63\x6f\x6d\x2f\x31\x20\x30\x1e\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x11\x69\x6e\x66\x6f\x40\x76\x61\x6c\x69\x63\x65\x72\x74\x2e\x63\x6f\x6d\x30\x1e\x17\x0d\x39\x39\x30\x36\x32\x36\x30\x30\x32\x32\x33\x33\x5a\x17\x0d\x31\x39\x30\x36\x32\x36\x30\x30\x32\x32\x33\x33\x5a\x30\x81\xbb\x31\x24\x30\x22\x06\x03\x55\x04\x07\x13\x1b\x56\x61\x6c\x69\x43\x65\x72\x74\x20\x56\x61\x6c\x69\x64\x61\x74\x69\x6f\x6e\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x61\x6c\x69\x43\x65\x72\x74\x2c\x20\x49\x6e\x63\x2e\x31\x35\x30\x33\x06\x03\x55\x04\x0b\x13\x2c\x56\x61\x6c\x69\x43\x65\x72\x74\x20\x43\x6c\x61\x73\x73\x20\x33\x20\x50\x6f\x6c\x69\x63\x79\x20\x56\x61\x6c\x69\x64\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x21\x30\x1f\x06\x03\x55\x04\x03\x13\x18\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x76\x61\x6c\x69\x63\x65\x72\x74\x2e\x63\x6f\x6d\x2f\x31\x20\x30\x1e\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x01\x16\x11\x69\x6e\x66\x6f\x40\x76\x61\x6c\x69\x63\x65\x72\x74\x2e\x63\x6f\x6d\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xe3\x98\x51\x96\x1c\xe8\xd5\xb1\x06\x81\x6a\x57\xc3\x72\x75\x93\xab\xcf\x9e\xa6\xfc\xf3\x16\x52\xd6\x2d\x4d\x9f\x35\x44\xa8\x2e\x04\x4d\x07\x49\x8a\x38\x29\xf5\x77\x37\xe7\xb7\xab\x5d\xdf\x36\x71\x14\x99\x8f\xdc\xc2\x92\xf1\xe7\x60\x92\x97\xec\xd8\x48\xdc\xbf\xc1\x02\x20\xc6\x24\xa4\x28\x4c\x30\x5a\x76\x6d\xb1\x5c\xf3\xdd\xde\x9e\x10\x71\xa1\x88\xc7\x5b\x9b\x41\x6d\xca\xb0\xb8\x8e\x15\xee\xad\x33\x2b\xcf\x47\x04\x5c\x75\x71\x0a\x98\x24\x98\x29\xa7\x49\x59\xa5\xdd\xf8\xb7\x43\x62\x61\xf3\xd3\xe2\xd0\x55\x3f\x02\x03\x01\x00\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x56\xbb\x02\x58\x84\x67\x08\x2c\xdf\x1f\xdb\x7b\x49\x33\xf5\xd3\x67\x9d\xf4\xb4\x0a\x10\xb3\xc9\xc5\x2c\xe2\x92\x6a\x71\x78\x27\xf2\x70\x83\x42\xd3\x3e\xcf\xa9\x54\xf4\xf1\xd8\x92\x16\x8c\xd1\x04\xcb\x4b\xab\xc9\x9f\x45\xae\x3c\x8a\xa9\xb0\x71\x33\x5d\xc8\xc5\x57\xdf\xaf\xa8\x35\xb3\x7f\x89\x87\xe9\xe8\x25\x92\xb8\x7f\x85\x7a\xae\xd6\xbc\x1e\x37\x58\x2a\x67\xc9\x91\xcf\x2a\x81\x3e\xed\xc6\x39\xdf\xc0\x3e\x19\x9c\x19\xcc\x13\x4d\x82\x41\xb5\x8c\xde\xe0\x3d\x60\x08\x20\x0f\x45\x7e\x6b\xa2\x7f\xa3\x8c\x15\xee", 0 }, + /* Anchor: 177 VASLatvijasPasts-SSI-RCA.crt serial: #{a.serial.to_s} + C=LV,O=VAS Latvijas Pasts - Vien.reg.Nr.40003052790,OU=Sertifikacijas pakalpojumi,CN=VAS Latvijas Pasts SSI(RCA) + */ + { 1965, "\x30\x82\x07\xa9\x30\x82\x05\x91\xa0\x03\x02\x01\x02\x02\x10\x63\x06\x86\xa7\xc5\x37\x65\xa5\x43\x90\xa8\x6a\x58\xcc\xd4\x32\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\x8f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4c\x56\x31\x35\x30\x33\x06\x03\x55\x04\x0a\x13\x2c\x56\x41\x53\x20\x4c\x61\x74\x76\x69\x6a\x61\x73\x20\x50\x61\x73\x74\x73\x20\x2d\x20\x56\x69\x65\x6e\x2e\x72\x65\x67\x2e\x4e\x72\x2e\x34\x30\x30\x30\x33\x30\x35\x32\x37\x39\x30\x31\x23\x30\x21\x06\x03\x55\x04\x0b\x13\x1a\x53\x65\x72\x74\x69\x66\x69\x6b\x61\x63\x69\x6a\x61\x73\x20\x70\x61\x6b\x61\x6c\x70\x6f\x6a\x75\x6d\x69\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1b\x56\x41\x53\x20\x4c\x61\x74\x76\x69\x6a\x61\x73\x20\x50\x61\x73\x74\x73\x20\x53\x53\x49\x28\x52\x43\x41\x29\x30\x1e\x17\x0d\x30\x36\x30\x39\x31\x33\x30\x39\x32\x32\x31\x30\x5a\x17\x0d\x32\x34\x30\x39\x31\x33\x30\x39\x32\x37\x35\x37\x5a\x30\x81\x8f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4c\x56\x31\x35\x30\x33\x06\x03\x55\x04\x0a\x13\x2c\x56\x41\x53\x20\x4c\x61\x74\x76\x69\x6a\x61\x73\x20\x50\x61\x73\x74\x73\x20\x2d\x20\x56\x69\x65\x6e\x2e\x72\x65\x67\x2e\x4e\x72\x2e\x34\x30\x30\x30\x33\x30\x35\x32\x37\x39\x30\x31\x23\x30\x21\x06\x03\x55\x04\x0b\x13\x1a\x53\x65\x72\x74\x69\x66\x69\x6b\x61\x63\x69\x6a\x61\x73\x20\x70\x61\x6b\x61\x6c\x70\x6f\x6a\x75\x6d\x69\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1b\x56\x41\x53\x20\x4c\x61\x74\x76\x69\x6a\x61\x73\x20\x50\x61\x73\x74\x73\x20\x53\x53\x49\x28\x52\x43\x41\x29\x30\x82\x02\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x00\x30\x82\x02\x0a\x02\x82\x02\x01\x00\x9b\xb8\xf9\xfd\x61\x55\x2f\x4f\xa4\xa5\x14\xb5\x2e\x8e\xb9\x24\x8f\xac\xfb\xb1\x54\x3f\x40\xff\x4f\xc5\xe5\x86\x68\x7b\x53\x93\xfb\x35\x82\x35\xa8\x50\x2e\x94\x52\xa0\xdb\x83\x3e\x75\xda\x15\x70\xac\x09\xcf\xee\x82\x49\xad\x36\x49\xb9\xb4\x71\x8b\xb4\x00\xa1\x42\x06\xca\x08\x0a\x63\x97\xb6\x08\xfc\xee\xb4\xdc\x98\x78\x19\x82\xc9\xf8\x7f\x64\x3e\xaa\xc9\xfe\xb1\x8d\xeb\xb0\x64\xf5\xbc\xf3\xc4\x3e\x3a\x90\xea\x4e\x8e\x3f\x1b\x19\xbc\x6a\x83\xc3\x91\x3c\x6c\x55\xfb\x0a\x52\xc0\xe8\xe1\x5d\x77\x85\x33\xc5\x49\xdf\xec\x6a\xbf\xbf\x6c\x37\xfe\x8e\x49\xa2\x15\x18\xce\x8b\x8e\x6b\x1e\x38\xa3\x30\x6f\x88\x81\x7e\x72\x56\x44\x1a\xc4\x7a\x39\x0f\xf6\xc4\x8f\x96\xd4\xb2\xeb\x00\x4e\x5c\xde\xbb\xe7\x3b\xb7\xe6\x24\x05\x93\x6b\x4d\xe6\x91\x44\xbf\xee\x98\x1b\xc7\x85\x1b\x11\x41\x7b\x22\x36\xa7\xbe\x3e\xe8\x7a\x37\xdc\x18\xde\x90\x9d\x8f\xcd\xb2\xd7\x9a\x3f\xe2\x17\x7f\x5b\x0c\xe1\xef\x3f\x66\x3d\x6e\x24\xe4\xb0\xce\xc3\x0c\x88\x6c\x94\xda\x38\x25\x7c\x52\x39\xe3\x73\x14\xb3\x00\x45\x63\x9a\x0c\x42\x40\x5e\x04\xc6\xf7\x72\x64\xce\xc9\x6e\x33\xb3\xe4\xd3\x6d\x24\x95\x37\x93\x7e\xf2\x00\x5d\x19\x8b\x1f\xf3\x43\x73\xa8\x9f\x45\xd2\x06\xa9\xec\xb4\x42\xbb\xfa\xee\x0c\xc7\x4f\x3f\x51\x1f\xd1\xaf\xd0\xac\x18\x7f\x87\x81\x22\xfe\xa9\xdd\x07\x96\x6d\x7c\xf8\x4e\xd9\x4d\x3a\x50\x69\xd5\x41\x7e\xc5\xda\x74\xd8\x8e\x73\xe5\x7e\x83\xe1\xc3\x19\x81\xb7\xbd\xbf\x40\x8e\xbe\x2e\x9a\xa2\x0c\xaa\x4e\x02\x2e\xbb\x2a\xe1\x08\x5d\x31\x03\xc9\xac\x27\xb0\xaf\xdc\xd5\xc8\x14\x7d\x40\x9d\x55\x89\x21\xf9\x90\xcc\xd4\xc9\x60\x41\x73\xab\xe8\xcd\xd8\x3a\x55\x39\x0a\x82\x99\xfe\x9b\xf5\xf5\x3c\x1c\x91\xcb\xc0\xfa\x46\x54\xae\x21\xfc\x2a\xac\x5c\x7b\xde\x7a\x97\x71\xfd\x6c\x6b\xcd\x48\x9a\xa4\xdb\x81\x7c\x18\x37\x2f\x90\x7d\x61\x94\xbd\x17\xc9\x5c\xb6\x54\x16\x77\xca\x09\x4a\xaa\xe9\xbc\x4f\x94\x75\x01\x5a\x56\xbc\x92\xd2\x8f\xb9\xd7\x97\xde\x56\x74\x01\xf7\x16\x71\x49\xb1\xf5\x18\x46\x99\x41\xee\x62\xe1\xb3\x2c\x65\x75\x69\x29\x72\x43\x03\xf8\x9b\x1f\xfa\x38\xf4\x9e\xec\x40\x10\x8e\xac\x97\xd5\xb0\x33\xbe\x9f\x18\xdc\x2d\xf7\x41\x78\x54\x4a\x62\x44\xe7\x02\x03\x01\x00\x01\xa3\x82\x01\xfd\x30\x82\x01\xf9\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x18\x06\x08\x2b\x06\x01\x05\x05\x07\x01\x03\x04\x0c\x30\x0a\x30\x08\x06\x06\x04\x00\x8e\x46\x01\x01\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xcc\xc3\xf5\x66\xff\x73\xac\x38\x5a\x96\x1b\x21\x89\xb8\x81\x4c\x1f\xcb\x5e\x25\x30\x10\x06\x09\x2b\x06\x01\x04\x01\x82\x37\x15\x01\x04\x03\x02\x01\x00\x30\x82\x01\x89\x06\x03\x55\x1d\x20\x04\x82\x01\x80\x30\x82\x01\x7c\x30\x82\x01\x78\x06\x0b\x2b\x06\x01\x04\x01\x81\xc4\x59\x01\x01\x02\x30\x82\x01\x67\x30\x82\x01\x38\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x02\x30\x82\x01\x2a\x1e\x82\x01\x26\x00\x53\x00\x69\x00\x73\x00\x20\x00\x69\x00\x72\x00\x20\x00\x73\x00\x65\x00\x72\x00\x74\x00\x69\x00\x66\x00\x69\x00\x6b\x00\x61\x00\x74\x00\x73\x00\x2c\x00\x20\x00\x6b\x00\x6f\x00\x20\x00\x69\x00\x7a\x00\x64\x00\x65\x00\x76\x00\x69\x00\x73\x00\x20\x00\x56\x00\x41\x00\x53\x00\x20\x00\x4c\x00\x61\x00\x74\x00\x76\x00\x69\x00\x6a\x00\x61\x00\x73\x00\x20\x00\x50\x00\x61\x00\x73\x00\x74\x00\x73\x00\x2c\x00\x20\x00\x6e\x00\x6f\x00\x64\x00\x72\x00\x6f\x00\x73\x00\x69\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x61\x00\x74\x00\x62\x00\x69\x00\x6c\x00\x73\x00\x74\x00\x69\x00\x62\x00\x75\x00\x20\x00\x45\x00\x6c\x00\x65\x00\x6b\x00\x74\x00\x72\x00\x6f\x00\x6e\x00\x69\x00\x73\x00\x6b\x00\x6f\x00\x20\x00\x64\x00\x6f\x00\x6b\x00\x75\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x75\x00\x20\x00\x6c\x00\x69\x00\x6b\x00\x75\x00\x6d\x00\x61\x00\x6d\x00\x20\x00\x75\x00\x6e\x00\x20\x00\x45\x00\x69\x00\x72\x00\x6f\x00\x70\x00\x61\x00\x73\x00\x20\x00\x50\x00\x61\x00\x72\x00\x6c\x00\x61\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x61\x00\x20\x00\x64\x00\x69\x00\x72\x00\x65\x00\x6b\x00\x74\x00\x69\x00\x76\x00\x61\x00\x69\x00\x20\x00\x31\x00\x39\x00\x39\x00\x39\x00\x2f\x00\x39\x00\x33\x00\x2f\x00\x45\x00\x4b\x30\x29\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x1d\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x65\x2d\x6d\x65\x2e\x6c\x76\x2f\x72\x65\x70\x6f\x73\x69\x74\x6f\x72\x79\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x1f\x28\x4a\x35\x90\x21\x63\x68\x0a\x2f\x78\xaf\xa3\x1e\x82\x26\x97\xa3\x3f\x27\x19\xd2\x4b\xa3\x42\x7a\x06\x13\x65\x5b\xc1\x04\xcb\xeb\x7d\x7c\xef\x94\xf2\xf1\x89\xf5\xb7\xdf\x52\x02\x21\x69\xd2\xea\x96\x34\xe5\xa0\xcf\x97\xb8\x9c\x55\x0e\x10\x85\xa3\x14\x5e\x2c\x05\xf8\xb5\x3a\x76\xf3\xf9\x7a\xb8\xde\xb6\x0c\x27\x69\xf2\xcb\x94\x91\x0b\x1d\xb9\xd5\x8e\x6f\x99\x2f\xcd\xf2\x19\x56\x39\x3a\x48\x56\xf0\x01\xff\x82\x75\xb6\xb2\xfd\xd1\xd4\xf5\xf2\x63\x57\x4c\x4d\xa1\x7e\xcc\x10\xba\x04\x69\xef\xf4\x14\xfc\xb3\x97\x1f\x45\xee\x6f\x4a\x28\x7f\xd1\xc6\x27\xbc\xc7\xa3\xa9\x6b\x7b\xed\x82\x13\x6f\xab\xde\x0f\xfb\x71\xeb\x5c\x11\x1a\xa9\x2c\xd0\x30\x9f\xfc\x36\x37\x56\xef\x95\xe9\xba\xb7\x13\xb6\xae\x9f\x02\x61\xad\x9e\xec\x6b\x04\x6f\x36\x9f\x0f\x99\xf7\xc2\xc9\xc8\x4c\x28\xb9\x28\xd4\x21\xd7\x9e\x54\xd5\xc0\xce\xf4\x8e\xe4\x55\x94\x7b\x8f\x24\xc6\x38\xfc\xab\x7a\xa4\x56\x77\x3d\xa8\x45\xef\x64\x92\xa4\xd0\x4a\x7e\xbb\x73\x8b\xf4\x0d\x52\x73\xb8\x3a\x48\x5e\x43\x80\xd3\xa9\x70\x77\x62\xff\xc7\x28\x1c\x73\x1e\x43\xe6\x27\x24\x5b\x49\xb9\xe6\x36\xa4\x8e\xfd\xc5\x2d\x2f\x7a\xa5\x79\x12\x7a\xd7\x21\xb2\x25\x6d\xc8\x0f\xa2\xc3\x61\x4b\xe5\x48\xe2\x57\xba\x9f\xf2\x8a\x21\xdd\xdb\x64\xf0\xda\x19\xdf\xce\xc0\x9b\x80\x39\xc2\x77\x77\x63\x15\x53\x72\x84\xfa\xa4\x8f\x07\x37\x86\x21\x7d\x50\xfa\x3d\x6a\x37\xdb\x91\x0e\x37\xb3\xfd\xce\x0b\xca\x7b\x61\xd0\x9c\x74\x9c\x7d\x38\x68\x6d\xe9\x7b\x1d\xd6\xf1\x2a\xb4\xef\x3b\x60\x52\x77\x05\xe6\x02\xc2\x5f\x8c\x5b\xbc\xf0\x7d\xb7\x73\xc7\x91\x6b\xb2\x2a\xb3\x63\xa3\x34\xd5\xab\xad\x25\x71\x47\xff\x1a\x3e\x7a\xb6\x8d\x95\x76\xc3\xee\xa6\xcd\x03\x09\x6c\xee\x45\x67\x98\xcf\x99\x48\x76\xc1\xce\x8a\x74\x9a\x68\x52\x01\x34\x22\xc8\xed\xe2\x14\x0b\x84\xbd\x6e\x10\x8c\xb1\x72\x9b\xbe\xe8\x08\xd7\x57\xd5\x7f\xea\xb4\x01\x3d\x4e\xe4\xe2\xe8\x67\xe7\x8c\x7e\xe9\xe7\x42\x11\xef\x95\x46\xc8\x91\xd6\xbe\x27\x17\x80\x19\x34\x98\xe7\xc6\xdf\x1e\xfc\x21\x5f\x9e\x86\x3d\xbc\x7e\xf0\x9c\xbd\x72\x9e\xf4\x47\x82\x5b\x71\x67\xf3\xfa\xdc\x54\x4c\xa8\x5c\xd8\x59\xc7\xd0\x07\x0e\x13\x33\x27\xbc\xf4\x69\xf0\x6b\x21", 0 }, + /* Anchor: 178 VeriSignC3PublicPrimaryCA-G5.cer serial: #{a.serial.to_s} + 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 + */ + { 1239, "\x30\x82\x04\xd3\x30\x82\x03\xbb\xa0\x03\x02\x01\x02\x02\x10\x18\xda\xd1\x9e\x26\x7d\xe8\xbb\x4a\x21\x58\xcd\xcc\x6b\x3b\x4a\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\xca\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x3a\x30\x38\x06\x03\x55\x04\x0b\x13\x31\x28\x63\x29\x20\x32\x30\x30\x36\x20\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3c\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x43\x6c\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x35\x30\x1e\x17\x0d\x30\x36\x31\x31\x30\x38\x30\x30\x30\x30\x30\x30\x5a\x17\x0d\x33\x36\x30\x37\x31\x36\x32\x33\x35\x39\x35\x39\x5a\x30\x81\xca\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0a\x13\x0e\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x31\x1f\x30\x1d\x06\x03\x55\x04\x0b\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x54\x72\x75\x73\x74\x20\x4e\x65\x74\x77\x6f\x72\x6b\x31\x3a\x30\x38\x06\x03\x55\x04\x0b\x13\x31\x28\x63\x29\x20\x32\x30\x30\x36\x20\x56\x65\x72\x69\x53\x69\x67\x6e\x2c\x20\x49\x6e\x63\x2e\x20\x2d\x20\x46\x6f\x72\x20\x61\x75\x74\x68\x6f\x72\x69\x7a\x65\x64\x20\x75\x73\x65\x20\x6f\x6e\x6c\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3c\x56\x65\x72\x69\x53\x69\x67\x6e\x20\x43\x6c\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6c\x69\x63\x20\x50\x72\x69\x6d\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x20\x2d\x20\x47\x35\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xaf\x24\x08\x08\x29\x7a\x35\x9e\x60\x0c\xaa\xe7\x4b\x3b\x4e\xdc\x7c\xbc\x3c\x45\x1c\xbb\x2b\xe0\xfe\x29\x02\xf9\x57\x08\xa3\x64\x85\x15\x27\xf5\xf1\xad\xc8\x31\x89\x5d\x22\xe8\x2a\xaa\xa6\x42\xb3\x8f\xf8\xb9\x55\xb7\xb1\xb7\x4b\xb3\xfe\x8f\x7e\x07\x57\xec\xef\x43\xdb\x66\x62\x15\x61\xcf\x60\x0d\xa4\xd8\xde\xf8\xe0\xc3\x62\x08\x3d\x54\x13\xeb\x49\xca\x59\x54\x85\x26\xe5\x2b\x8f\x1b\x9f\xeb\xf5\xa1\x91\xc2\x33\x49\xd8\x43\x63\x6a\x52\x4b\xd2\x8f\xe8\x70\x51\x4d\xd1\x89\x69\x7b\xc7\x70\xf6\xb3\xdc\x12\x74\xdb\x7b\x5d\x4b\x56\xd3\x96\xbf\x15\x77\xa1\xb0\xf4\xa2\x25\xf2\xaf\x1c\x92\x67\x18\xe5\xf4\x06\x04\xef\x90\xb9\xe4\x00\xe4\xdd\x3a\xb5\x19\xff\x02\xba\xf4\x3c\xee\xe0\x8b\xeb\x37\x8b\xec\xf4\xd7\xac\xf2\xf6\xf0\x3d\xaf\xdd\x75\x91\x33\x19\x1d\x1c\x40\xcb\x74\x24\x19\x21\x93\xd9\x14\xfe\xac\x2a\x52\xc7\x8f\xd5\x04\x49\xe4\x8d\x63\x47\x88\x3c\x69\x83\xcb\xfe\x47\xbd\x2b\x7e\x4f\xc5\x95\xae\x0e\x9d\xd4\xd1\x43\xc0\x67\x73\xe3\x14\x08\x7e\xe5\x3f\x9f\x73\xb8\x33\x0a\xcf\x5d\x3f\x34\x87\x96\x8a\xee\x53\xe8\x25\x15\x02\x03\x01\x00\x01\xa3\x81\xb2\x30\x81\xaf\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\x06\x30\x6d\x06\x08\x2b\x06\x01\x05\x05\x07\x01\x0c\x04\x61\x30\x5f\xa1\x5d\xa0\x5b\x30\x59\x30\x57\x30\x55\x16\x09\x69\x6d\x61\x67\x65\x2f\x67\x69\x66\x30\x21\x30\x1f\x30\x07\x06\x05\x2b\x0e\x03\x02\x1a\x04\x14\x8f\xe5\xd3\x1a\x86\xac\x8d\x8e\x6b\xc3\xcf\x80\x6a\xd4\x48\x18\x2c\x7b\x19\x2e\x30\x25\x16\x23\x68\x74\x74\x70\x3a\x2f\x2f\x6c\x6f\x67\x6f\x2e\x76\x65\x72\x69\x73\x69\x67\x6e\x2e\x63\x6f\x6d\x2f\x76\x73\x6c\x6f\x67\x6f\x2e\x67\x69\x66\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x7f\xd3\x65\xa7\xc2\xdd\xec\xbb\xf0\x30\x09\xf3\x43\x39\xfa\x02\xaf\x33\x31\x33\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x93\x24\x4a\x30\x5f\x62\xcf\xd8\x1a\x98\x2f\x3d\xea\xdc\x99\x2d\xbd\x77\xf6\xa5\x79\x22\x38\xec\xc4\xa7\xa0\x78\x12\xad\x62\x0e\x45\x70\x64\xc5\xe7\x97\x66\x2d\x98\x09\x7e\x5f\xaf\xd6\xcc\x28\x65\xf2\x01\xaa\x08\x1a\x47\xde\xf9\xf9\x7c\x92\x5a\x08\x69\x20\x0d\xd9\x3e\x6d\x6e\x3c\x0d\x6e\xd8\xe6\x06\x91\x40\x18\xb9\xf8\xc1\xed\xdf\xdb\x41\xaa\xe0\x96\x20\xc9\xcd\x64\x15\x38\x81\xc9\x94\xee\xa2\x84\x29\x0b\x13\x6f\x8e\xdb\x0c\xdd\x25\x02\xdb\xa4\x8b\x19\x44\xd2\x41\x7a\x05\x69\x4a\x58\x4f\x60\xca\x7e\x82\x6a\x0b\x02\xaa\x25\x17\x39\xb5\xdb\x7f\xe7\x84\x65\x2a\x95\x8a\xbd\x86\xde\x5e\x81\x16\x83\x2d\x10\xcc\xde\xfd\xa8\x82\x2a\x6d\x28\x1f\x0d\x0b\xc4\xe5\xe7\x1a\x26\x19\xe1\xf4\x11\x6f\x10\xb5\x95\xfc\xe7\x42\x05\x32\xdb\xce\x9d\x51\x5e\x28\xb6\x9e\x85\xd3\x5b\xef\xa5\x7d\x45\x40\x72\x8e\xb7\x0e\x6b\x0e\x06\xfb\x33\x35\x48\x71\xb8\x9d\x27\x8b\xc4\x65\x5f\x0d\x86\x76\x9c\x44\x7a\xf6\x95\x5c\xf6\x5d\x32\x08\x33\xa4\x54\xb6\x18\x3f\x68\x5c\xf2\x42\x4a\x85\x38\x54\x83\x5f\xd1\xe8\x2c\xf2\xac\x11\xd6\xa8\xed\x63\x6a", 0 }, + /* Anchor: 179 WellsSecurePRCA.der serial: #{a.serial.to_s} + C=US,O=Wells Fargo WellsSecure,OU=Wells Fargo Bank NA,CN=WellsSecure Public Root Certificate Authority + */ + { 1217, "\x30\x82\x04\xbd\x30\x82\x03\xa5\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\x85\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1e\x06\x03\x55\x04\x0a\x0c\x17\x57\x65\x6c\x6c\x73\x20\x46\x61\x72\x67\x6f\x20\x57\x65\x6c\x6c\x73\x53\x65\x63\x75\x72\x65\x31\x1c\x30\x1a\x06\x03\x55\x04\x0b\x0c\x13\x57\x65\x6c\x6c\x73\x20\x46\x61\x72\x67\x6f\x20\x42\x61\x6e\x6b\x20\x4e\x41\x31\x36\x30\x34\x06\x03\x55\x04\x03\x0c\x2d\x57\x65\x6c\x6c\x73\x53\x65\x63\x75\x72\x65\x20\x50\x75\x62\x6c\x69\x63\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x30\x37\x31\x32\x31\x33\x31\x37\x30\x37\x35\x34\x5a\x17\x0d\x32\x32\x31\x32\x31\x34\x30\x30\x30\x37\x35\x34\x5a\x30\x81\x85\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1e\x06\x03\x55\x04\x0a\x0c\x17\x57\x65\x6c\x6c\x73\x20\x46\x61\x72\x67\x6f\x20\x57\x65\x6c\x6c\x73\x53\x65\x63\x75\x72\x65\x31\x1c\x30\x1a\x06\x03\x55\x04\x0b\x0c\x13\x57\x65\x6c\x6c\x73\x20\x46\x61\x72\x67\x6f\x20\x42\x61\x6e\x6b\x20\x4e\x41\x31\x36\x30\x34\x06\x03\x55\x04\x03\x0c\x2d\x57\x65\x6c\x6c\x73\x53\x65\x63\x75\x72\x65\x20\x50\x75\x62\x6c\x69\x63\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xee\x6f\xb4\xbd\x79\xe2\x8f\x08\x21\x9e\x38\x04\x41\x25\xef\xab\x5b\x1c\x53\x92\xac\x6d\x9e\xdd\xc2\xc4\x2e\x45\x94\x03\x35\x88\x67\x74\x57\xe3\xdf\x8c\xb8\xa7\x76\x8f\x3b\xf7\xa8\xc4\xdb\x29\x63\x0e\x91\x68\x36\x8a\x97\x8e\x8a\x71\x68\x09\x07\xe4\xe8\xd4\x0e\x4f\xf8\xd6\x2b\x4c\xa4\x16\xf9\xef\x43\x98\x8f\xb3\x9e\x52\xdf\x6d\x91\x39\x8f\x38\xbd\x77\x8b\x43\x63\xeb\xb7\x93\xfc\x30\x4c\x1c\x01\x93\xb6\x13\xfb\xf7\xa1\x1f\xbf\x25\xe1\x74\x37\x2c\x1e\xa4\x5e\x3c\x68\xf8\x4b\xbf\x0d\xb9\x1e\x2e\x36\xe8\xa9\xe4\xa7\xf8\x0f\xcb\x82\x75\x7c\x35\x2d\x22\xd6\xc2\xbf\x0b\xf3\xb4\xfc\x6c\x95\x61\x1e\x57\xd7\x04\x81\x32\x83\x52\x79\xe6\x83\x63\xcf\xb7\xcb\x63\x8b\x11\xe2\xbd\x5e\xeb\xf6\x8d\xed\x95\x72\x28\xb4\xac\x12\x62\xe9\x4a\x33\xe6\x83\x32\xae\x05\x75\x95\xbd\x84\x95\xdb\x2a\x5c\x9b\x8e\x2e\x0c\xb8\x81\x2b\x41\xe6\x38\x56\x9f\x49\x9b\x6c\x76\xfa\x8a\x5d\xf7\x01\x79\x81\x7c\xc1\x83\x40\x05\xfe\x71\xfd\x0c\x3f\xcc\x4e\x60\x09\x0e\x65\x47\x10\x2f\x01\xc0\x05\x3f\x8f\xf8\xb3\x41\xef\x5a\x42\x7e\x59\xef\xd2\x97\x0c\x65\x02\x03\x01\x00\x01\xa3\x82\x01\x34\x30\x82\x01\x30\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x39\x06\x03\x55\x1d\x1f\x04\x32\x30\x30\x30\x2e\xa0\x2c\xa0\x2a\x86\x28\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x70\x6b\x69\x2e\x77\x65\x6c\x6c\x73\x66\x61\x72\x67\x6f\x2e\x63\x6f\x6d\x2f\x77\x73\x70\x72\x63\x61\x2e\x63\x72\x6c\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04\x04\x03\x02\x01\xc6\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x26\x95\x19\x10\xd9\xe8\xa1\x97\x91\xff\xdc\x19\xd9\xb5\x04\x3e\xd2\x73\x0a\x6a\x30\x81\xb2\x06\x03\x55\x1d\x23\x04\x81\xaa\x30\x81\xa7\x80\x14\x26\x95\x19\x10\xd9\xe8\xa1\x97\x91\xff\xdc\x19\xd9\xb5\x04\x3e\xd2\x73\x0a\x6a\xa1\x81\x8b\xa4\x81\x88\x30\x81\x85\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1e\x06\x03\x55\x04\x0a\x0c\x17\x57\x65\x6c\x6c\x73\x20\x46\x61\x72\x67\x6f\x20\x57\x65\x6c\x6c\x73\x53\x65\x63\x75\x72\x65\x31\x1c\x30\x1a\x06\x03\x55\x04\x0b\x0c\x13\x57\x65\x6c\x6c\x73\x20\x46\x61\x72\x67\x6f\x20\x42\x61\x6e\x6b\x20\x4e\x41\x31\x36\x30\x34\x06\x03\x55\x04\x03\x0c\x2d\x57\x65\x6c\x6c\x73\x53\x65\x63\x75\x72\x65\x20\x50\x75\x62\x6c\x69\x63\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x82\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xb9\x15\xb1\x44\x91\xcc\x23\xc8\x2b\x4d\x77\xe3\xf8\x9a\x7b\x27\x0d\xcd\x72\xbb\x99\x00\xca\x7c\x66\x19\x50\xc6\xd5\x98\xed\xab\xbf\x03\x5a\xe5\x4d\xe5\x1e\xc8\x4f\x71\x97\x86\xd5\xe3\x1d\xfd\x90\xc9\x3c\x75\x77\x57\x7a\x7d\xf8\xde\xf4\xd4\xd5\xf7\x95\xe6\x74\x6e\x1d\x3c\xae\x7c\x9d\xdb\x02\x03\x05\x2c\x71\x4b\x25\x3e\x07\xe3\x5e\x9a\xf5\x66\x17\x29\x88\x1a\x38\x9f\xcf\xaa\x41\x03\x84\x97\x6b\x93\x38\x7a\xca\x30\x44\x1b\x24\x44\x33\xd0\xe4\xd1\xdc\x28\x38\xf4\x13\x43\x35\x35\x29\x63\xa8\x7c\xa2\xb5\xad\x38\xa4\xed\xad\xfd\xc6\x9a\x1f\xff\x97\x73\xfe\xfb\xb3\x35\xa7\x93\x86\xc6\x76\x91\x00\xe6\xac\x51\x16\xc4\x27\x32\x5c\xdb\x73\xda\xa5\x93\x57\x8e\x3e\x6d\x35\x26\x08\x59\xd5\xe7\x44\xd7\x76\x20\x63\xe7\xac\x13\x67\xc3\x6d\xb1\x70\x46\x7c\xd5\x96\x11\x3d\x89\x6f\x5d\xa8\xa1\xeb\x8d\x0a\xda\xc3\x1d\x33\x6c\xa3\xea\x67\x19\x9a\x99\x7f\x4b\x3d\x83\x51\x2a\x1d\xca\x2f\x86\x0c\xa2\x7e\x10\x2d\x2b\xd4\x16\x95\x0b\x07\xaa\x2e\x14\x92\x49\xb7\x29\x6f\xd8\x6d\x31\x7d\xf5\xfc\xa1\x10\x07\x87\xce\x2f\x59\xdc\x3e\x58\xdb", 0 }, + /* Anchor: 180 wf_root.crt serial: #{a.serial.to_s} + C=US,O=Wells Fargo,OU=Wells Fargo Certification Authority,CN=Wells Fargo Root Certificate Authority + */ + { 1001, "\x30\x82\x03\xe5\x30\x82\x02\xcd\xa0\x03\x02\x01\x02\x02\x04\x39\xe4\x97\x9e\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\x82\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x57\x65\x6c\x6c\x73\x20\x46\x61\x72\x67\x6f\x31\x2c\x30\x2a\x06\x03\x55\x04\x0b\x13\x23\x57\x65\x6c\x6c\x73\x20\x46\x61\x72\x67\x6f\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x2f\x30\x2d\x06\x03\x55\x04\x03\x13\x26\x57\x65\x6c\x6c\x73\x20\x46\x61\x72\x67\x6f\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x30\x30\x31\x30\x31\x31\x31\x36\x34\x31\x32\x38\x5a\x17\x0d\x32\x31\x30\x31\x31\x34\x31\x36\x34\x31\x32\x38\x5a\x30\x81\x82\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x57\x65\x6c\x6c\x73\x20\x46\x61\x72\x67\x6f\x31\x2c\x30\x2a\x06\x03\x55\x04\x0b\x13\x23\x57\x65\x6c\x6c\x73\x20\x46\x61\x72\x67\x6f\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x2f\x30\x2d\x06\x03\x55\x04\x03\x13\x26\x57\x65\x6c\x6c\x73\x20\x46\x61\x72\x67\x6f\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xd5\xa8\x33\x3b\x26\xf9\x34\xff\xcd\x9b\x7e\xe5\x04\x47\xce\x00\xe2\x7d\x77\xe7\x31\xc2\x2e\x27\xa5\x4d\x68\xb9\x31\xba\x8d\x43\x59\x97\xc7\x73\xaa\x7f\x3d\x5c\x40\x9e\x05\xe5\xa1\xe2\x89\xd9\x4c\xb8\x3f\x9b\xf9\x0c\xb4\xc8\x62\x19\x2c\x45\xae\x91\x1e\x73\x71\x41\xc4\x4b\x13\xfd\x70\xc2\x25\xac\x22\xf5\x75\x0b\xb7\x53\xe4\xa5\x2b\xdd\xce\xbd\x1c\x3a\x7a\xc3\xf7\x13\x8f\x26\x54\x9c\x16\x6b\x6b\xaf\xfb\xd8\x96\xb1\x60\x9a\x48\xe0\x25\x22\x24\x79\x34\xce\x0e\x26\x00\x0b\x4e\xab\xfd\x8b\xce\x82\xd7\x2f\x08\x70\x68\xc1\xa8\x0a\xf9\x74\x4f\x07\xab\xa4\xf9\xe2\x83\x7e\x27\x73\x74\x3e\xb8\xf9\x38\x42\xfc\xa5\xa8\x5b\x48\x23\xb3\xeb\xe3\x25\xb2\x80\xae\x96\xd4\x0a\x9c\xc2\x78\x9a\xc6\x68\x18\xae\x37\x62\x37\x5e\x51\x75\xa8\x58\x63\xc0\x51\xee\x40\x78\x7e\xa8\xaf\x1a\xa0\xe1\xb0\x78\x9d\x50\x8c\x7b\xe7\xb3\xfc\x8e\x23\xb0\xdb\x65\x00\x70\x84\x01\x08\x00\x14\x6e\x54\x86\x9a\xba\xcc\xf9\x37\x10\xf6\xe0\xde\x84\x2d\x9d\xa4\x85\x37\xd3\x87\xe3\x15\xd0\xc1\x17\x90\x7e\x19\x21\x6a\x12\xa9\x76\xfd\x12\x02\xe9\x4f\x21\x5e\x17\x02\x03\x01\x00\x01\xa3\x61\x30\x5f\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x4c\x06\x03\x55\x1d\x20\x04\x45\x30\x43\x30\x41\x06\x0b\x60\x86\x48\x01\x86\xfb\x7b\x87\x07\x01\x0b\x30\x32\x30\x30\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x01\x16\x24\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x65\x6c\x6c\x73\x66\x61\x72\x67\x6f\x2e\x63\x6f\x6d\x2f\x63\x65\x72\x74\x70\x6f\x6c\x69\x63\x79\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xd2\x27\xdd\x9c\x0a\x77\x2b\xbb\x22\xf2\x02\xb5\x4a\x4a\x91\xf9\xd1\x2d\xbe\xe4\xbb\x1a\x68\xef\x0e\xa4\x00\xe9\xee\xe7\xef\xee\xf6\xf9\xe5\x74\xa4\xc2\xd8\x52\x58\xc4\x74\xfb\xce\x6b\xb5\x3b\x29\x79\x18\x5a\xef\x9b\xed\x1f\x6b\x36\xee\x48\x25\x25\x14\xb6\x56\xa2\x10\xe8\xee\xa7\x7f\xd0\x3f\xa3\xd0\xc3\x5d\x26\xee\x07\xcc\xc3\xc1\x24\x21\x87\x1e\xdf\x2a\x12\x53\x6f\x41\x16\xe7\xed\xae\x94\xfa\x8c\x72\xfa\x13\x47\xf0\x3c\x7e\xae\x7d\x11\x3a\x13\xec\xed\xfa\x6f\x72\x64\x7b\x9d\x7d\x7f\x26\xfd\x7a\xfb\x25\xad\xea\x3e\x29\x7f\x4c\xe3\x00\x57\x32\xb0\xb3\xe9\xed\x53\x17\xd9\x8b\xb2\x14\x0e\x30\xe8\xe5\xd5\x13\xc6\x64\xaf\xc4\x00\xd5\xd8\x58\x24\xfc\xf5\x8f\xec\xf1\xc7\x7d\xa5\xdb\x0f\x27\xd1\xc6\xf2\x40\x88\xe6\x1f\xf6\x61\xa8\xf4\x42\xc8\xb9\x37\xd3\xa9\xbe\x2c\x56\x78\xc2\x72\x9b\x59\x5d\x35\x40\x8a\xe8\x4e\x63\x1a\xb6\xe9\x20\x6a\x51\xe2\xce\xa4\x90\xdf\x76\x70\x99\x5c\x70\x43\x4d\xb7\xb6\xa7\x19\x64\x4e\x92\xb7\xc5\x91\x3c\x7f\x48\x16\x65\x7b\x16\xfd\xcb\xfc\xfb\xd9\xd5\xd6\x4f\x21\x65\x3b\x4a\x7f\x47\xa3\xfb", 0 }, + /* Anchor: 181 WISeKey-owgrgaca.cer serial: #{a.serial.to_s} + C=CH,O=WISeKey,OU=Copyright (c) 2005,OU=OISTE Foundation Endorsed,CN=OISTE WISeKey Global Root GA CA + */ + { 1013, "\x30\x82\x03\xf1\x30\x82\x02\xd9\xa0\x03\x02\x01\x02\x02\x10\x41\x3d\x72\xc7\xf4\x6b\x1f\x81\x43\x7d\xf1\xd2\x28\x54\xdf\x9a\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\x8a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x10\x30\x0e\x06\x03\x55\x04\x0a\x13\x07\x57\x49\x53\x65\x4b\x65\x79\x31\x1b\x30\x19\x06\x03\x55\x04\x0b\x13\x12\x43\x6f\x70\x79\x72\x69\x67\x68\x74\x20\x28\x63\x29\x20\x32\x30\x30\x35\x31\x22\x30\x20\x06\x03\x55\x04\x0b\x13\x19\x4f\x49\x53\x54\x45\x20\x46\x6f\x75\x6e\x64\x61\x74\x69\x6f\x6e\x20\x45\x6e\x64\x6f\x72\x73\x65\x64\x31\x28\x30\x26\x06\x03\x55\x04\x03\x13\x1f\x4f\x49\x53\x54\x45\x20\x57\x49\x53\x65\x4b\x65\x79\x20\x47\x6c\x6f\x62\x61\x6c\x20\x52\x6f\x6f\x74\x20\x47\x41\x20\x43\x41\x30\x1e\x17\x0d\x30\x35\x31\x32\x31\x31\x31\x36\x30\x33\x34\x34\x5a\x17\x0d\x33\x37\x31\x32\x31\x31\x31\x36\x30\x39\x35\x31\x5a\x30\x81\x8a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x10\x30\x0e\x06\x03\x55\x04\x0a\x13\x07\x57\x49\x53\x65\x4b\x65\x79\x31\x1b\x30\x19\x06\x03\x55\x04\x0b\x13\x12\x43\x6f\x70\x79\x72\x69\x67\x68\x74\x20\x28\x63\x29\x20\x32\x30\x30\x35\x31\x22\x30\x20\x06\x03\x55\x04\x0b\x13\x19\x4f\x49\x53\x54\x45\x20\x46\x6f\x75\x6e\x64\x61\x74\x69\x6f\x6e\x20\x45\x6e\x64\x6f\x72\x73\x65\x64\x31\x28\x30\x26\x06\x03\x55\x04\x03\x13\x1f\x4f\x49\x53\x54\x45\x20\x57\x49\x53\x65\x4b\x65\x79\x20\x47\x6c\x6f\x62\x61\x6c\x20\x52\x6f\x6f\x74\x20\x47\x41\x20\x43\x41\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xcb\x4f\xb3\x00\x9b\x3d\x36\xdd\xf9\xd1\x49\x6a\x6b\x10\x49\x1f\xec\xd8\x2b\xb2\xc6\xf8\x32\x81\x29\x43\x95\x4c\x9a\x19\x23\x21\x15\x45\xde\xe3\xc8\x1c\x51\x55\x5b\xae\x93\xe8\x37\xff\x2b\x6b\xe9\xd4\xea\xbe\x2a\xdd\xa8\x51\x2b\xd7\x66\xc3\x61\x5c\x60\x02\xc8\xf5\xce\x72\x7b\x3b\xb8\xf2\x4e\x65\x08\x9a\xcd\xa4\x6a\x19\xc1\x01\xbb\x73\xa6\xd7\xf6\xc3\xdd\xcd\xbc\xa4\x8b\xb5\x99\x61\xb8\x01\xa2\xa3\xd4\x4d\xd4\x05\x3d\x91\xad\xf8\xb4\x08\x71\x64\xaf\x70\xf1\x1c\x6b\x7e\xf6\xc3\x77\x9d\x24\x73\x7b\xe4\x0c\x8c\xe1\xd9\x36\xe1\x99\x8b\x05\x99\x0b\xed\x45\x31\x09\xca\xc2\x00\xdb\xf7\x72\xa0\x96\xaa\x95\x87\xd0\x8e\xc7\xb6\x61\x73\x0d\x76\x66\x8c\xdc\x1b\xb4\x63\xa2\x9f\x7f\x93\x13\x30\xf1\xa1\x27\xdb\xd9\xff\x2c\x55\x88\x91\xa0\xe0\x4f\x07\xb0\x28\x56\x8c\x18\x1b\x97\x44\x8e\x89\xdd\xe0\x17\x6e\xe7\x2a\xef\x8f\x39\x0a\x31\x84\x82\xd8\x40\x14\x49\x2e\x7a\x41\xe4\xa7\xfe\xe3\x64\xcc\xc1\x59\x71\x4b\x2c\x21\xa7\x5b\x7d\xe0\x1d\xd1\x2e\x81\x9b\xc3\xd8\x68\xf7\xbd\x96\x1b\xac\x70\xb1\x16\x14\x0b\xdb\x60\xb9\x26\x01\x05\x02\x03\x01\x00\x01\xa3\x51\x30\x4f\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x86\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xb3\x03\x7e\xae\x36\xbc\xb0\x79\xd1\xdc\x94\x26\xb6\x11\xbe\x21\xb2\x69\x86\x94\x30\x10\x06\x09\x2b\x06\x01\x04\x01\x82\x37\x15\x01\x04\x03\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x4b\xa1\xff\x0b\x87\x6e\xb3\xf9\xc1\x43\xb1\x48\xf3\x28\xc0\x1d\x2e\xc9\x09\x41\xfa\x94\x00\x1c\xa4\xa4\xab\x49\x4f\x8f\x3d\x1e\xef\x4d\x6f\xbd\xbc\xa4\xf6\xf2\x26\x30\xc9\x10\xca\x1d\x88\xfb\x74\x19\x1f\x85\x45\xbd\xb0\x6c\x51\xf9\x36\x7e\xdb\xf5\x4c\x32\x3a\x41\x4f\x5b\x47\xcf\xe8\x0b\x2d\xb6\xc4\x19\x9d\x74\xc5\x47\xc6\x3b\x6a\x0f\xac\x14\xdb\x3c\xf4\x73\x9c\xa9\x05\xdf\x00\xdc\x74\x78\xfa\xf8\x35\x60\x59\x02\x13\x18\x7c\xbc\xfb\x4d\xb0\x20\x6d\x43\xbb\x60\x30\x7a\x67\x33\x5c\xc5\x99\xd1\xf8\x2d\x39\x52\x73\xfb\x8c\xaa\x97\x25\x5c\x72\xd9\x08\x1e\xab\x4e\x3c\xe3\x81\x31\x9f\x03\xa6\xfb\xc0\xfe\x29\x88\x55\xda\x84\xd5\x50\x03\xb6\xe2\x84\xa3\xa6\x36\xaa\x11\x3a\x01\xe1\x18\x4b\xd6\x44\x68\xb3\x3d\xf9\x53\x74\x84\xb3\x46\x91\x46\x96\x00\xb7\x80\x2c\xb6\xe1\xe3\x10\xe2\xdb\xa2\xe7\x28\x8f\x01\x96\x62\x16\x3e\x00\xe3\x1c\xa5\x36\x81\x18\xa2\x4c\x52\x76\xc0\x11\xa3\x6e\xe6\x1d\xba\xe3\x5a\xbe\x36\x53\xc5\x3e\x75\x8f\x86\x69\x29\x58\x53\xb5\x9c\xbb\x6f\x9f\x5c\xc5\x18\xec\xdd\x2f\xe1\x98\xc9\xfc\xbe\xdf\x0a\x0d", 0 }, + /* Anchor: 182 XGCA.crt serial: #{a.serial.to_s} + C=US,OU=www.xrampsecurity.com,O=XRamp Security Services Inc,CN=XRamp Global Certification Authority + */ + { 1076, "\x30\x82\x04\x30\x30\x82\x03\x18\xa0\x03\x02\x01\x02\x02\x10\x50\x94\x6c\xec\x18\xea\xd5\x9c\x4d\xd5\x97\xef\x75\x8f\xa0\xad\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\x82\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1e\x30\x1c\x06\x03\x55\x04\x0b\x13\x15\x77\x77\x77\x2e\x78\x72\x61\x6d\x70\x73\x65\x63\x75\x72\x69\x74\x79\x2e\x63\x6f\x6d\x31\x24\x30\x22\x06\x03\x55\x04\x0a\x13\x1b\x58\x52\x61\x6d\x70\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x49\x6e\x63\x31\x2d\x30\x2b\x06\x03\x55\x04\x03\x13\x24\x58\x52\x61\x6d\x70\x20\x47\x6c\x6f\x62\x61\x6c\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x30\x34\x31\x31\x30\x31\x31\x37\x31\x34\x30\x34\x5a\x17\x0d\x33\x35\x30\x31\x30\x31\x30\x35\x33\x37\x31\x39\x5a\x30\x81\x82\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1e\x30\x1c\x06\x03\x55\x04\x0b\x13\x15\x77\x77\x77\x2e\x78\x72\x61\x6d\x70\x73\x65\x63\x75\x72\x69\x74\x79\x2e\x63\x6f\x6d\x31\x24\x30\x22\x06\x03\x55\x04\x0a\x13\x1b\x58\x52\x61\x6d\x70\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x49\x6e\x63\x31\x2d\x30\x2b\x06\x03\x55\x04\x03\x13\x24\x58\x52\x61\x6d\x70\x20\x47\x6c\x6f\x62\x61\x6c\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\x98\x24\x1e\xbd\x15\xb4\xba\xdf\xc7\x8c\xa5\x27\xb6\x38\x0b\x69\xf3\xb6\x4e\xa8\x2c\x2e\x21\x1d\x5c\x44\xdf\x21\x5d\x7e\x23\x74\xfe\x5e\x7e\xb4\x4a\xb7\xa6\xad\x1f\xae\xe0\x06\x16\xe2\x9b\x5b\xd9\x67\x74\x6b\x5d\x80\x8f\x29\x9d\x86\x1b\xd9\x9c\x0d\x98\x6d\x76\x10\x28\x58\xe4\x65\xb0\x7f\x4a\x98\x79\x9f\xe0\xc3\x31\x7e\x80\x2b\xb5\x8c\xc0\x40\x3b\x11\x86\xd0\xcb\xa2\x86\x36\x60\xa4\xd5\x30\x82\x6d\xd9\x6e\xd0\x0f\x12\x04\x33\x97\x5f\x4f\x61\x5a\xf0\xe4\xf9\x91\xab\xe7\x1d\x3b\xbc\xe8\xcf\xf4\x6b\x2d\x34\x7c\xe2\x48\x61\x1c\x8e\xf3\x61\x44\xcc\x6f\xa0\x4a\xa9\x94\xb0\x4d\xda\xe7\xa9\x34\x7a\x72\x38\xa8\x41\xcc\x3c\x94\x11\x7d\xeb\xc8\xa6\x8c\xb7\x86\xcb\xca\x33\x3b\xd9\x3d\x37\x8b\xfb\x7a\x3e\x86\x2c\xe7\x73\xd7\x0a\x57\xac\x64\x9b\x19\xeb\xf4\x0f\x04\x08\x8a\xac\x03\x17\x19\x64\xf4\x5a\x25\x22\x8d\x34\x2c\xb2\xf6\x68\x1d\x12\x6d\xd3\x8a\x1e\x14\xda\xc4\x8f\xa6\xe2\x23\x85\xd5\x7a\x0d\xbd\x6a\xe0\xe9\xec\xec\x17\xbb\x42\x1b\x67\xaa\x25\xed\x45\x83\x21\xfc\xc1\xc9\x7c\xd5\x62\x3e\xfa\xf2\xc5\x2d\xd3\xfd\xd4\x65\x02\x03\x01\x00\x01\xa3\x81\x9f\x30\x81\x9c\x30\x13\x06\x09\x2b\x06\x01\x04\x01\x82\x37\x14\x02\x04\x06\x1e\x04\x00\x43\x00\x41\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\x86\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\xc6\x4f\xa2\x3d\x06\x63\x84\x09\x9c\xce\x62\xe4\x04\xac\x8d\x5c\xb5\xe9\xb6\x1b\x30\x36\x06\x03\x55\x1d\x1f\x04\x2f\x30\x2d\x30\x2b\xa0\x29\xa0\x27\x86\x25\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x6c\x2e\x78\x72\x61\x6d\x70\x73\x65\x63\x75\x72\x69\x74\x79\x2e\x63\x6f\x6d\x2f\x58\x47\x43\x41\x2e\x63\x72\x6c\x30\x10\x06\x09\x2b\x06\x01\x04\x01\x82\x37\x15\x01\x04\x03\x02\x01\x01\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x91\x15\x39\x03\x01\x1b\x67\xfb\x4a\x1c\xf9\x0a\x60\x5b\xa1\xda\x4d\x97\x62\xf9\x24\x53\x27\xd7\x82\x64\x4e\x90\x2e\xc3\x49\x1b\x2b\x9a\xdc\xfc\xa8\x78\x67\x35\xf1\x1d\xf0\x11\xbd\xb7\x48\xe3\x10\xf6\x0d\xdf\x3f\xd2\xc9\xb6\xaa\x55\xa4\x48\xba\x02\xdb\xde\x59\x2e\x15\x5b\x3b\x9d\x16\x7d\x47\xd7\x37\xea\x5f\x4d\x76\x12\x36\xbb\x1f\xd7\xa1\x81\x04\x46\x20\xa3\x2c\x6d\xa9\x9e\x01\x7e\x3f\x29\xce\x00\x93\xdf\xfd\xc9\x92\x73\x89\x89\x64\x9e\xe7\x2b\xe4\x1c\x91\x2c\xd2\xb9\xce\x7d\xce\x6f\x31\x99\xd3\xe6\xbe\xd2\x1e\x90\xf0\x09\x14\x79\x5c\x23\xab\x4d\xd2\xda\x21\x1f\x4d\x99\x79\x9d\xe1\xcf\x27\x9f\x10\x9b\x1c\x88\x0d\xb0\x8a\x64\x41\x31\xb8\x0e\x6c\x90\x24\xa4\x9b\x5c\x71\x8f\xba\xbb\x7e\x1c\x1b\xdb\x6a\x80\x0f\x21\xbc\xe9\xdb\xa6\xb7\x40\xf4\xb2\x8b\xa9\xb1\xe4\xef\x9a\x1a\xd0\x3d\x69\x99\xee\xa8\x28\xa3\xe1\x3c\xb3\xf0\xb2\x11\x9c\xcf\x7c\x40\xe6\xdd\xe7\x43\x7d\xa2\xd8\x3a\xb5\xa9\x8d\xf2\x34\x99\xc4\xd4\x10\xe1\x06\xfd\x09\x84\x10\x3b\xee\xc4\x4c\xf4\xec\x27\x7c\x42\xc2\x74\x7c\x82\x8a\x09\xc9\xb4\x03\x25\xbc", 0 }, +}; diff --git a/iCloudStat/com.apple.icloudKeychainStats.plist b/iCloudStat/com.apple.icloudKeychainStats.plist new file mode 100644 index 00000000..3d4bbf6f --- /dev/null +++ b/iCloudStat/com.apple.icloudKeychainStats.plist @@ -0,0 +1,19 @@ + + + + + Label + com.apple.iCloudKeychainStats + ProgramArguments + + /usr/libexec/iCloudKeychainStats + + + StartInterval + 86400 + Umask + 18 + UserName + _securityd + + diff --git a/iCloudStat/main.c b/iCloudStat/main.c new file mode 100644 index 00000000..28c257e7 --- /dev/null +++ b/iCloudStat/main.c @@ -0,0 +1,260 @@ +// +// main.c +// iCloudStats +// +// Created by local on 7/20/13. +// +// + +#include + +#import "SOSCloudCircle.h" +#import + +static const CFStringRef gMessageTracerPrefix = CFSTR("com.apple.message."); +static const CFStringRef gClientIsUsingiCloudKeychainSyncing = CFSTR("com.apple.icloudkeychain.deviceIsUsingICloudKeychain"); +static const CFStringRef gNumberOfPeers = CFSTR("com.apple.icloudkeychain.numberOfPeers"); +static const CFStringRef gNumberOfItemsBeingSynced = CFSTR("com.apple.icloudkeychain.numberOfItemsBeingSynced"); + +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) +static const char* gTopLevelKeyForiCloudKeychainTracing = "com.apple.icloudkeychain"; +#endif + +#if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR) +static const char* gTopLevelKeyForiCloudKeychainTracing = "com.apple.icloudkeychain"; +#endif + +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)) +#include + + +static bool OSX_SetCloudKeychainTraceValueForKey(CFStringRef key, int64_t value) +{ + bool result = false; + + if (NULL == key) + { + return result; + } + + aslmsg mAsl = NULL; + mAsl = asl_new(ASL_TYPE_MSG); + if (NULL == mAsl) + { + return result; + } + + + CFStringRef key_str = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@%@"), gMessageTracerPrefix, key); + if (NULL == key_str) + { + asl_free(mAsl); + return result; + } + + CFStringRef value_str = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%lld"), value); + if (NULL == value_str) + { + asl_free(mAsl); + CFRelease(key_str); + return result; + } + + CFIndex key_str_numBytes = CFStringGetMaximumSizeForEncoding(CFStringGetLength(key_str), kCFStringEncodingUTF8); + key_str_numBytes += 1; // For null + char key_buffer[key_str_numBytes]; + memset(key_buffer, 0, key_str_numBytes); + if (!CFStringGetCString(key_str, key_buffer, key_str_numBytes, kCFStringEncodingUTF8)) + { + asl_free(mAsl); + CFRelease(key_str); + CFRelease(value_str); + return result; + } + CFRelease(key_str); + + CFIndex value_str_numBytes = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value_str), kCFStringEncodingUTF8); + value_str_numBytes += 1; // For null + char value_buffer[value_str_numBytes]; + memset(value_buffer, 0, value_str_numBytes); + if (!CFStringGetCString(value_str, value_buffer, value_str_numBytes, kCFStringEncodingUTF8)) + { + asl_free(mAsl); + CFRelease(value_str); + return result; + } + CFRelease(value_str); + + asl_set(mAsl, key_buffer, value_buffer); + asl_log(NULL, mAsl, ASL_LEVEL_NOTICE, "%s", gTopLevelKeyForiCloudKeychainTracing); + asl_free(mAsl); + return true; +} +#endif + +#if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR) +#import + +static bool iOS_SetCloudKeychainTraceValueForKey(CFStringRef key, int64_t value) +{ + if (NULL == key) + { + return false; + } + + if (0LL == value) + { + ADClientClearScalarKey(key); + } + + ADClientSetValueForScalarKey(key, value); + return true; +} +#endif + +static bool ClientIsInCircle() +{ + bool result = false; + CFErrorRef error = NULL; + SOSCCStatus status = kSOSCCError; + + status = SOSCCThisDeviceIsInCircle(&error); + if (NULL != error) + { + CFRelease(error); + } + else + { + switch (status) + { + case kSOSCCInCircle: + { + result = true; + } + break; + + // kSOSCCRequestPending + // While this device will be in a circle, it is not in + // one yet. For now, this will be treated as if the device + // was not in a circle and will wait for the device to + // be in a circle and have that turn on this daemon with + // launchctl + case kSOSCCRequestPending: + case kSOSCCCircleAbsent: + case kSOSCCError: + default: + break; + } + } + return result; +} + + +static bool sendTraceMessage(CFStringRef key, int64_t value) +{ + +#if (TARGET_IPHONE_SIMULATOR) + return false; +#endif + +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) + return OSX_SetCloudKeychainTraceValueForKey(key, value); +#endif + +#if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR) + return iOS_SetCloudKeychainTraceValueForKey(key, value); +#endif + +} + +static int64_t GetNumberOfPeers() +{ + int64_t result = 0LL; + + CFErrorRef error = NULL; + CFArrayRef peers = NULL; + + peers = SOSCCCopyPeerPeerInfo(&error); + if (NULL != error) + { + CFRelease(error); + if (NULL != peers) + { + CFRelease(peers); + } + return result; + } + + if (NULL != peers) + { + result = (int64_t)CFArrayGetCount(peers); + CFRelease(peers); + } + + return result; +} + +static int64_t GetNumberOfItemsBeingSyncedForType(CFTypeRef class) +{ + int64_t result = 0; + + CFTypeRef keys[] = {kSecClass, kSecAttrSynchronizable, kSecMatchLimit, kSecReturnAttributes}; + CFTypeRef values[] = {class, kCFBooleanTrue, kSecMatchLimitAll, kCFBooleanTrue}; + + CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, (sizeof(keys)/sizeof(keys[0])), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + if (NULL == query) + { + return result; + } + + CFArrayRef query_result = NULL; + OSStatus status = SecItemCopyMatching(query, (CFTypeRef *)&query_result); + CFRelease(query); + if (noErr != status || NULL == query_result) + { + if (NULL != query_result) + { + CFRelease(query_result); + } + return result; + } + + result = (int64_t)CFArrayGetCount(query_result); + CFRelease(query_result); + return result; +} + +static int64_t GetNumberOfItemsBeingSynced() +{ + int64_t result = 0; + + result = GetNumberOfItemsBeingSyncedForType(kSecClassInternetPassword); + result += GetNumberOfItemsBeingSyncedForType(kSecClassGenericPassword); + + return result; +} + + +int main(int argc, const char * argv[]) +{ + int64_t value = 0; + if (!ClientIsInCircle()) + { + // This will clear the value in the backend database if it had been previously set + sendTraceMessage(gClientIsUsingiCloudKeychainSyncing, value); + return 0; + } + + value = 1; + sendTraceMessage(gClientIsUsingiCloudKeychainSyncing, value); + + value = GetNumberOfPeers(); + sendTraceMessage(gNumberOfPeers, value); + + value = GetNumberOfItemsBeingSynced(); + sendTraceMessage(gNumberOfItemsBeingSynced, value); + + return 0; +} + diff --git a/iCloudStats/com.apple.iCloudStats.plist b/iCloudStats/com.apple.iCloudStats.plist deleted file mode 100644 index 08282eec..00000000 --- a/iCloudStats/com.apple.iCloudStats.plist +++ /dev/null @@ -1,21 +0,0 @@ - - - - - Label - com.apple.iCloudStats - ProgramArguments - - /usr/libexec/iCloudStats - - - StartInterval - 604800 - - - diff --git a/iCloudStats/iCloudStats.1 b/iCloudStats/iCloudStats.1 deleted file mode 100644 index 516ef44c..00000000 --- a/iCloudStats/iCloudStats.1 +++ /dev/null @@ -1,79 +0,0 @@ -.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. -.\"See Also: -.\"man mdoc.samples for a complete listing of options -.\"man mdoc for the short list of editing options -.\"/usr/share/misc/mdoc.template -.Dd 7/20/13 \" DATE -.Dt iCloudStats 1 \" Program name and manual section number -.Os Darwin -.Sh NAME \" Section Header - required - don't modify -.Nm iCloudStats, -.\" The following lines are read in generating the apropos(man -k) database. Use only key -.\" words here as the database is built based on the words here and in the .ND line. -.Nm Other_name_for_same_program(), -.Nm Yet another name for the same program. -.\" Use .Nm macro to designate other names for the documented program. -.Nd This line parsed for whatis database. -.Sh SYNOPSIS \" Section Header - required - don't modify -.Nm -.Op Fl abcd \" [-abcd] -.Op Fl a Ar path \" [-a path] -.Op Ar file \" [file] -.Op Ar \" [file ...] -.Ar arg0 \" Underlined argument - use .Ar anywhere to underline -arg2 ... \" Arguments -.Sh DESCRIPTION \" Section Header - required - don't modify -Use the .Nm macro to refer to your program throughout the man page like such: -.Nm -Underlining is accomplished with the .Ar macro like this: -.Ar underlined text . -.Pp \" Inserts a space -A list of items with descriptions: -.Bl -tag -width -indent \" Begins a tagged list -.It item a \" Each item preceded by .It macro -Description of item a -.It item b -Description of item b -.El \" Ends the list -.Pp -A list of flags and their descriptions: -.Bl -tag -width -indent \" Differs from above in tag removed -.It Fl a \"-a flag as a list item -Description of -a flag -.It Fl b -Description of -b flag -.El \" Ends the list -.Pp -.\" .Sh ENVIRONMENT \" May not be needed -.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 -.\" .It Ev ENV_VAR_1 -.\" Description of ENV_VAR_1 -.\" .It Ev ENV_VAR_2 -.\" Description of ENV_VAR_2 -.\" .El -.Sh FILES \" File used or created by the topic of the man page -.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact -.It Pa /usr/share/file_name -FILE_1 description -.It Pa /Users/joeuser/Library/really_long_file_name -FILE_2 description -.El \" Ends the list -.\" .Sh DIAGNOSTICS \" May not be needed -.\" .Bl -diag -.\" .It Diagnostic Tag -.\" Diagnostic informtion here. -.\" .It Diagnostic Tag -.\" Diagnostic informtion here. -.\" .El -.Sh SEE ALSO -.\" List links in ascending order by section, alphabetically within a section. -.\" Please do not reference files that do not exist without filing a bug report -.Xr a 1 , -.Xr b 1 , -.Xr c 1 , -.Xr a 2 , -.Xr b 2 , -.Xr a 3 , -.Xr b 3 -.\" .Sh BUGS \" Document known, unremedied bugs -.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file diff --git a/iCloudStats/main.c b/iCloudStats/main.c deleted file mode 100644 index d5f79a68..00000000 --- a/iCloudStats/main.c +++ /dev/null @@ -1,274 +0,0 @@ -// -// main.c -// iCloudStats -// -// Created by local on 7/20/13. -// -// - -#include - -#import "SOSCloudCircle.h" -#import - -static const CFStringRef gMessageTracerPrefix = CFSTR("com.apple.message."); - -static const CFStringRef gClientIsUsingiCloudKeychainSyncing = CFSTR("com.apple.cloudkeychain.deviceIsUsingICloudKeychain"); -static const CFStringRef gClientIsNotUsingiCloudKeychainSyncing = CFSTR("com.apple.cloudkeychain.deviceIsNotUsingICloudKeychain"); -static const CFStringRef gNumberOfPeers = CFSTR("com.apple.cloudkeychain.numberOfPeers"); -static const CFStringRef gNumberOfItemsBeingSynced = CFSTR("com.apple.cloudkeychain.numberOfItemsBeingSynced"); - -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)) -#include - -static const char* gMessageTracerDomainField = "com.apple.message.domain"; -static const const char* gTopLevelKeyForiCloudKeychainTracing = "com.apple.cloudkeychain"; - -static bool OSX_SetCloudKeychainTraceValueForKey(CFStringRef key, int64_t value) -{ - bool result = false; - - if (NULL == key) - { - return result; - } - - aslmsg mAsl = NULL; - mAsl = asl_new(ASL_TYPE_MSG); - if (NULL == mAsl) - { - return result; - } - - CFIndex key_length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(key), kCFStringEncodingUTF8); - key_length += 1; // For null - char base_key_buffer[key_length]; - memset(base_key_buffer, 0,key_length); - if (!CFStringGetCString(key, base_key_buffer, key_length, kCFStringEncodingUTF8)) - { - asl_free(mAsl); - return result; - } - - - CFStringRef key_str = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@%@"), gMessageTracerPrefix, key); - if (NULL == key_str) - { - asl_free(mAsl); - return result; - } - - CFStringRef value_str = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%lld"), value); - if (NULL == value_str) - { - asl_free(mAsl); - CFRelease(key_str); - return result; - } - - CFIndex key_str_numBytes = CFStringGetMaximumSizeForEncoding(CFStringGetLength(key_str), kCFStringEncodingUTF8); - key_str_numBytes += 1; // For null - char key_buffer[key_str_numBytes]; - memset(key_buffer, 0, key_str_numBytes); - if (!CFStringGetCString(key_str, key_buffer, key_str_numBytes, kCFStringEncodingUTF8)) - { - asl_free(mAsl); - CFRelease(key_str); - CFRelease(value_str); - return result; - } - CFRelease(key_str); - - CFIndex value_str_numBytes = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value_str), kCFStringEncodingUTF8); - value_str_numBytes += 1; // For null - char value_buffer[value_str_numBytes]; - memset(value_buffer, 0, value_str_numBytes); - if (!CFStringGetCString(value_str, value_buffer, value_str_numBytes, kCFStringEncodingUTF8)) - { - asl_free(mAsl); - CFRelease(value_str); - return result; - } - CFRelease(value_str); - - asl_set(mAsl, gMessageTracerDomainField, base_key_buffer); - - asl_set(mAsl, key_buffer, value_buffer); - asl_log(NULL, mAsl, ASL_LEVEL_NOTICE, "%s is %lld", key_buffer, value); - asl_free(mAsl); - return true; -} -#endif - -#if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR) -#import - -static bool iOS_SetCloudKeychainTraceValueForKey(CFStringRef key, int64_t value) -{ - if (NULL == key) - { - return false; - } - - ADClientSetValueForScalarKey(key, value); - return true; -} -#endif - -static bool ClientIsInCircle() -{ - bool result = false; - CFErrorRef error = NULL; - SOSCCStatus status = kSOSCCError; - - status = SOSCCThisDeviceIsInCircle(&error); - if (NULL != error) - { - CFRelease(error); - } - else - { - switch (status) - { - case kSOSCCInCircle: - { - result = true; - } - break; - - // kSOSCCRequestPending - // While this device will be in a circle, it is not in - // one yet. For now, this will be treated as if the device - // was not in a circle and will wait for the device to - // be in a circle and have that turn on this daemon with - // launchctl - case kSOSCCRequestPending: - case kSOSCCCircleAbsent: - case kSOSCCError: - default: - break; - } - } - return result; -} - - -static bool sendTraceMessage(CFStringRef key, int64_t value) -{ - -#if (TARGET_IPHONE_SIMULATOR) - return false; -#endif - -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) - return OSX_SetCloudKeychainTraceValueForKey(key, value); -#endif - -#if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR) - return iOS_SetCloudKeychainTraceValueForKey(key, value); -#endif - -} - -int64_t GetNumberOfPeers() -{ - int64_t result = 0; - - CFErrorRef error = NULL; - CFArrayRef peers = NULL; - - peers = SOSCCCopyPeerPeerInfo(&error); - if (NULL != error) - { - CFRelease(error); - if (NULL != peers) - { - CFRelease(peers); - } - return result; - } - - if (NULL != peers) - { - result = (int64_t)CFArrayGetCount(peers); - CFRelease(peers); - } - - return result; -} - - -int64_t GetNumberOfItemsBeingSynced() -{ - int64_t result = 0; - - - CFTypeRef classTypes[] = {kSecClassInternetPassword, kSecClassGenericPassword}; - - - CFArrayRef classTypesArray = CFArrayCreate(kCFAllocatorDefault, - (const void **)classTypes, (sizeof(classTypes)/sizeof(classTypes[0])), - &kCFTypeArrayCallBacks); - if (NULL == classTypesArray) - { - return result; - } - - CFTypeRef keys[] = {kSecClass, kSecAttrSynchronizable, kSecReturnAttributes}; - CFTypeRef values[] = {classTypesArray, kCFBooleanTrue, kCFBooleanTrue}; - - CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, (sizeof(keys)/sizeof(keys[0])), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFRelease(classTypesArray); - if (NULL == query) - { - return result; - } - - CFArrayRef query_result = NULL; - OSStatus status = SecItemCopyMatching(query, (CFTypeRef *)&query_result); - if (noErr != status) - { - CFRelease(query); - if (NULL != query_result) - { - CFRelease(query_result); - } - return result; - } - CFRelease(query); - - if (NULL != query_result) - { - result = 1; // There is at least one item being synced - if (CFArrayGetTypeID() == CFGetTypeID(query_result)) - { - result = (int64_t)CFArrayGetCount(query_result); - } - CFRelease(query_result); - } - - return result; -} - - -int main(int argc, const char * argv[]) -{ - int64_t value = 1; - if (!ClientIsInCircle()) - { - sendTraceMessage(gClientIsNotUsingiCloudKeychainSyncing, value); - return 0; - } - - sendTraceMessage(gClientIsUsingiCloudKeychainSyncing, value); - - value = GetNumberOfPeers(); - sendTraceMessage(gNumberOfPeers, value); - - value = GetNumberOfItemsBeingSynced(); - sendTraceMessage(gNumberOfItemsBeingSynced, value); - - - return 0; -} - diff --git a/include/security_agent_client b/include/security_agent_client deleted file mode 120000 index c01356e3..00000000 --- a/include/security_agent_client +++ /dev/null @@ -1 +0,0 @@ -./libsecurity_agent/lib \ No newline at end of file diff --git a/lib/generateErrStrings.pl b/lib/generateErrStrings.pl deleted file mode 100644 index 18cc2b0d..00000000 --- a/lib/generateErrStrings.pl +++ /dev/null @@ -1,343 +0,0 @@ -#!/usr/bin/perl -# -# Copyright (c) 2003-2004 Apple Computer, 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@ -# -# generateErrStrings.pl - create error strings files from the Security header files -# -# Usage: -# -# perl generateErrStrings.pl -# -# Currently supported files are SecBase.h, SecureTransport.h,cssmapple.h, -# cssmerr.h and Authorization.h. These are used by: -# -# void cssmPerror(const char *how, CSSM_RETURN error); -# -# which is in SecBase.cpp. -# -# Paths of input files: -# -# ./libsecurity_authorization/lib/Authorization.h -# ./libsecurity_cssm/lib/cssmapple.h -# ./libsecurity_cssm/lib/cssmerr.h -# ./libsecurity_keychain/lib/SecBase.h -# ./libsecurity_ssl/lib/SecureTransport.h -# -# Sample run: -# -# perl generateErrStrings.pl "YES" "SecErrorMessages.strings" Authorization.h SecBase.h \ -# cssmapple.h cssmerr.h SecureTransport.h -# -# Input to script: header file(s) containing enum declarations -# Output: C++ program with one cout statement per decl -# -# The input headers are scanned for enums containing error numbers and -# optional comments. Only certain prefixes for the identifiers in the -# enums are considered, to avoid non-error message type defines. See -# the line in the file with CSSM_ERRCODE for acceptable prefixes. -# -# There are three styles of comments that this script parses: -# -# Style A [see /System/Library/Frameworks/Security.framework/Headers/SecBase.h]: -# -# errSSLProtocol = -9800, /* SSL protocol error */ -# -# Style B [see /System/Library/Frameworks/Security.framework/Headers/cssmapple.h]: -# -# /* a code signature match failed */ -# CSSMERR_CSP_APPLE_SIGNATURE_MISMATCH = CSSM_CSP_PRIVATE_ERROR + 2, -# -# Style C [see /System/Library/Frameworks/Security.framework/Headers/cssmerr.h]: -# -# CSSM_CSSM_BASE_CSSM_ERROR = -# CSSM_CSSM_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT + 0x10, -# CSSMERR_CSSM_SCOPE_NOT_SUPPORTED = CSSM_CSSM_BASE_CSSM_ERROR + 1, -# -# Style A has the comment after the comment. Style has the comment before the value, -# and Style C has no comment. In cases where both Style A and B apply, the -# comment at the end of the line is used. -# -# The final output after the generated Objective-C++ program is run looks like: -# -# /* errSSLProtocol */ -# "-9800" = "SSL protocol error"; -# -# /* errSSLNegotiation */ -# "-9801" = "Cipher Suite negotiation failure"; -# -# The appropriate byte order marker for UTF-16 is written to the start of the file. -# Note that the list of errors must be numerically unique across all input files, -# or the strings file will be invalid. Comments in "Style B" may span multiple lines. -# C++ style comments are not supported. Double quotes in a comment are hardened with -# "\" in the output. -# -# The English versions of the error messages can be seen with: -# -# cat /System/Library/Frameworks/Security.framework/Resources/English.lproj/SecErrorMessages.strings -# -# find -H -X -x . -name "*.h" -print0 2>/dev/null | xargs -0 grep -ri err -# ----------------------------------------------------------------------------------- - -# Style questions: -# - what should I make PROGNAME? -# - should I use a special call to make the temp file in the .mm file? -# - -#use strict; -#use warnings; - -die "Usage: $0 <.strings file> \n" if ($#ARGV < 3); - -$GENDEBUGSTRINGS=$ARGV[0]; # If "YES", include all strings & don't localize -$TMPDIR=$ARGV[1]; # temporary directory for program compile, link, run -$TARGETSTR=$ARGV[2]; # path of .strings file, e.g. - # ${DERIVED_SRC}/English.lproj/SecErrorMessages.strings -@INPUTFILES=@ARGV[3 .. 9999]; # list of input files - -$#INPUTFILES = $#ARGV - 3; # truncate to actual number of files - -print "gend: $GENDEBUGSTRINGS, tmpdir: $TMPDIR, targetstr: $TARGETSTR\n"; -$PROGNAME="${TMPDIR}/generateErrStrings.mm"; -open PROGRAM,"> $PROGNAME" or die "can't open $PROGNAME: $!"; -select PROGRAM; - -printAdditionalIncludes(); -printInputIncludes(); -printMainProgram(); - -# ----------------------------------------------------------------------------------- -# Parse error headers and build array of all relevant lines -open(ERR, "cat " . join(" ", @INPUTFILES) . "|") or die "Cannot open error header files"; -$/="\};"; #We set the section termination string - very important -processInput(); -close(ERR); -# ----------------------------------------------------------------------------------- - -printTrailer(); -select STDOUT; -close PROGRAM; - -compileLinkAndRun(); - -# 4: Done! -exit; - -# ----------------------------------------------------------------------------------- -# Subroutines -# ----------------------------------------------------------------------------------- - -sub processInput -{ - # 3: Read input, process each line, output it. - while ( $line = ) - { - ($enum) = ($line =~ /\n\s*enum\s*{\s*([^}]*)};/); - while ($enum ne '') #basic filter for badly formed enums - { - #Drop leading whitespace - $enum =~ s/^\s+//; - # print "A:", $enum,"\n"; - ($leadingcomment) = ($enum =~ m%^(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|(//.*)%); - if ($leadingcomment ne '') - { - $enum = substr($enum, length($leadingcomment)); - $leadingcomment = substr($leadingcomment, 2); # drop leading "/*" - $leadingcomment = substr($leadingcomment, 0, -2); # drop trailing "*/" - $leadingcomment = cleanupComment($leadingcomment); - } - next if ($enum eq ''); #basic filter for badly formed enums - - # Check for C++ style comments at start of line - if ($enum =~ /\s*(\/\/)/) - { - #Drop everything before the end of line - $enum =~ s/[^\n]*[\n]*//; - next; - } - ($identifier) = ($enum =~ /\s*([_A-Za-z][_A-Za-z0-9]*)/); - -# print "identifier: ", $identifier,"\n" if ($identifier ne ''); - - #Drop everything before the comma - $enum =~ s/[^,]*,//; - - # Now look for trailing comment. We only consider them - # trailing if they come before the end of the line - ($trailingcomment) = ($enum =~ /^[ \t]*\/\*((.)*)?\*\//); - # ($trailingcomment) = ($enum =~ m%^(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|(//.*)%); - $trailingcomment = cleanupComment($trailingcomment); - - #Drop everything before the end of line - $enum =~ s/[^\n]*[\n]*//; - # print "B:", $enum,"\n"; - # print "lc:$leadingcomment, id:$identifier, tc:$trailingcomment\n"; - # print "===========================================\n"; - - writecomment($leadingcomment, $identifier, $trailingcomment); - } - } -} - -sub writecomment -{ - # Leading comment, id, trailing comment - # To aid localizers, we will not output a line with no comment - # - # Output is e.g. - # tmp << "/* errAuthorizationSuccess */\n\"" << errAuthorizationSuccess - # << "\" = \"The operation completed successfully.\"\n" << endl; - - my($mylc,$myid,$mytc) = @_; - if ($myid =~ /(CSSM_ERRCODE|CSSMERR_|errSec|errCS|errAuth|errSSL)[_A-Za-z][_A-Za-z0-9]*/) - { - $errormessage = ''; - if ($mytc ne '') - { $errormessage = $mytc; } - elsif ($mylc ne '') - { $errormessage = $mylc; } - elsif ($GENDEBUGSTRINGS eq "YES") - { $errormessage = $myid; } - - if ($errormessage ne '') - { - print "\ttmp << \"/* ", $myid, " */\\n\\\"\" << "; - print $myid, " << \"\\\" = \\\""; - print $errormessage, "\\\";\\n\" << endl;\n"; - } - } -}; - - -sub printAdditionalIncludes -{ - #This uses the "here" construct to dump out lines verbatim - print <<"AdditionalIncludes"; - -#include -#include -#include -#include - -using namespace std; -AdditionalIncludes -} - -sub printInputIncludes -{ - #Now "#include" each of the input files - print "\n#include \"$_\"" foreach @INPUTFILES; - print "\n"; -} - -sub printMainProgram -{ - #Output the main part of the program using the "here" construct - print <<"MAINPROGRAM"; - -void writeStrings(const char *stringsFileName); -void createStringsTemp(); - -int main (int argc, char * const argv[]) -{ - const char *stringsFileName = NULL; - - if (argc == 2) - stringsFileName = argv[1]; - else - if (argc == 1) - stringsFileName = "SecErrorMessages.strings"; - else - return -1; - - cout << "Strings file to create: " << stringsFileName << endl; - createStringsTemp(); - writeStrings(stringsFileName); -} - -void writeStrings(const char *stringsFileName) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:@"generateErrStrings.tmp"]; - NSData *rawstrings = [fh readDataToEndOfFile]; - UInt32 encoding = CFStringConvertEncodingToNSStringEncoding (kCFStringEncodingUTF8); - NSString *instring = [[NSString alloc] initWithData:rawstrings encoding:(NSStringEncoding)encoding]; - - if (instring) - { - NSString *path = [NSString stringWithUTF8String:stringsFileName]; - NSFileManager *fm = [NSFileManager defaultManager]; - if ([fm fileExistsAtPath:path]) - [fm removeFileAtPath:path handler:nil]; - BOOL bx = [fm createFileAtPath:path contents:nil attributes:nil]; - NSFileHandle *fs = [NSFileHandle fileHandleForWritingAtPath:path]; - [fs writeData:[instring dataUsingEncoding:NSUnicodeStringEncoding]]; - } - - [pool release]; -} - -void createStringsTemp() -{ - ofstream tmp("generateErrStrings.tmp") ; - -MAINPROGRAM -} - -sub cleanupComment -{ - my $comment = shift @_; -# print "A:",$comment,"\n"; - if ($comment ne '') - { - $comment =~ s/\s\s+/ /g; # Squeeze multiple spaces to one - $comment =~ s/^\s+//; # Drop leading whitespace - $comment =~ s/\s+$//; # Drop trailing whitespace - $comment =~ s/[\"]/\\\\\\"/g; # Replace double quotes with \" (backslash is sextupled to make it through regex and printf) - } -# print "B:",$comment,"\n"; - $comment; -} - -sub printTrailer -{ - print " tmp.close();\n"; - print "}\n"; -} - -sub compileLinkAndRun -{ - $status = system( <<"MAINPROGRAM"); -(cd ${TMPDIR} ; /usr/bin/cc -x objective-c++ -pipe -Wno-trigraphs -fpascal-strings -fasm-blocks -g -O0 -Wreturn-type -fmessage-length=0 -F$ENV{'BUILT_PRODUCTS_DIR'} -I$ENV{'BUILT_PRODUCTS_DIR'}/SecurityPieces/Headers -I$ENV{'BUILT_PRODUCTS_DIR'}/SecurityPieces/PrivateHeaders -c generateErrStrings.mm -o generateErrStrings.o) -MAINPROGRAM - die "$compile exited funny: $?" unless $status == 0; - - $status = system( <<"LINKERSTEP"); -(cd ${TMPDIR} ; /usr/bin/clang++ -o generateErrStrings generateErrStrings.o -framework Foundation ) -LINKERSTEP - die "$linker exited funny: $?" unless $status == 0; - - $status = system( <<"RUNSTEP"); -(cd ${TMPDIR} ; ./generateErrStrings $TARGETSTR ) -RUNSTEP - die "$built program exited funny: $?" unless $status == 0; -} - diff --git a/libsecurity_apple_csp/lib/ascContext.h b/libsecurity_apple_csp/lib/ascContext.h deleted file mode 100644 index 55d2ad8d..00000000 --- a/libsecurity_apple_csp/lib/ascContext.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * ascContext.h - glue between BlockCrytpor and ComCryption (a.k.a. Apple - * Secure Compression). - * Written by Doug Mitchell 4/4/2001 - */ - -#ifdef ASC_CSP_ENABLE - -#ifndef _ASC_CONTEXT_H_ -#define _ASC_CONTEXT_H_ - -#include "AppleCSPContext.h" -#include - -/* symmetric encrypt/decrypt context */ -class ASCContext : public AppleCSPContext { -public: - ASCContext(AppleCSPSession &session) : - AppleCSPContext(session), - mCcObj(NULL) { } - ~ASCContext(); - - // called by CSPFullPluginSession - void init( - const Context &context, - bool encoding = true); - void update( - void *inp, - size_t &inSize, // in/out - void *outp, - size_t &outSize); // in/out - void final( - CssmData &out); - - size_t inputSize( - size_t outSize); // input for given output size - size_t outputSize( - bool final = false, - size_t inSize = 0); // output for given input size - void minimumProgress( - size_t &in, - size_t &out); // minimum progress chunks - -private: - comcryptObj mCcObj; - - /* - * For first implementation, we have to cope with the fact that the final - * decrypt call down to the comcryption engine requires *some* ciphertext. - * On decrypt, we'll just save one byte on each update in preparation for - * the final call. Hopefull we'll have time to fix deComcryptData() so this - * is unneccesary. - */ - unsigned char mDecryptBuf; - bool mDecryptBufValid; - -}; /* RC4Context */ - -#endif /*_ASC_CONTEXT_H_ */ -#endif /* ASC_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/ascFactory.h b/libsecurity_apple_csp/lib/ascFactory.h deleted file mode 100644 index afe7d148..00000000 --- a/libsecurity_apple_csp/lib/ascFactory.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// ascAlgFactory.h - algorithm factory for ASC -// Written by Doug Mitchell 4/4/2001 -// - -#ifdef ASC_CSP_ENABLE - -#ifndef _ASC_ALG_FACTORY_H_ -#define _ASC_ALG_FACTORY_H_ - -#include -#include "AppleCSP.h" - -class AppleCSPSession; - -/* Algorithm factory */ -class AscAlgFactory : public AppleCSPAlgorithmFactory { -public: - - AscAlgFactory( - Allocator *normAlloc, - Allocator *privAlloc); - ~AscAlgFactory() { } - - bool setup( - AppleCSPSession &session, - CSPFullPluginSession::CSPContext * &cspCtx, - const Context &context); - -}; - - -#endif /*_ASC_ALG_FACTORY_H_ */ -#endif /* ASC_CSP_ENABLE */ diff --git a/libsecurity_apple_csp/lib/boxes-ref.h b/libsecurity_apple_csp/lib/boxes-ref.h deleted file mode 100644 index ca261820..00000000 --- a/libsecurity_apple_csp/lib/boxes-ref.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - - -#ifndef _AES_BOXES_H_ -#define _AES_BOXES_H_ - -#include "rijndael-alg-ref.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define AES_MUL_BY_LOOKUP 1 - -#if AES_MUL_BY_LOOKUP -extern const word8 mulBy0x02[256]; -extern const word8 mulBy0x03[256]; -extern const word8 mulBy0x0e[256]; -extern const word8 mulBy0x0b[256]; -extern const word8 mulBy0x0d[256]; -extern const word8 mulBy0x09[256]; -#else -extern const unsigned char Logtable[256]; -extern const unsigned char Alogtable[256]; -#endif /* AES_MUL_BY_LOOKUP */ - -extern const unsigned char S[256]; -extern const unsigned char Si[256]; -extern const unsigned char iG[4][4]; -extern const unsigned long rcon[30]; - -#ifdef __cplusplus -} -#endif - -#endif /* _AES_BOXES_H_ */ diff --git a/libsecurity_apple_csp/lib/pbkdDigest.cpp b/libsecurity_apple_csp/lib/pbkdDigest.cpp deleted file mode 100644 index 06dbea05..00000000 --- a/libsecurity_apple_csp/lib/pbkdDigest.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please - * obtain a copy of the License at http://www.apple.com/publicsource and - * read it before using this file. - * - * This 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. - */ -/* - * pbkdDigest.cpp - SHA1/MD5 digest object for HMAC and PBE routines - */ - -#include "pbkdDigest.h" -#include -#include - -/* the casts are necessary to cover the polymorphous context types */ -DigestOps Md2Ops = { - (DigestInitFcn)CC_MD2_Init, - (DigestUpdateFcn)CC_MD2_Update, - (DigestFinalFcn)CC_MD2_Final -}; -DigestOps Md5Ops = { - (DigestInitFcn)CC_MD5_Init, - (DigestUpdateFcn)CC_MD5_Update, - (DigestFinalFcn)CC_MD5_Final -}; -DigestOps Sha1Ops = { - (DigestInitFcn)CC_SHA1_Init, - (DigestUpdateFcn)CC_SHA1_Update, - (DigestFinalFcn)CC_SHA1_Final -}; - -/* Ops on a DigestCtx - all return zero on error, like the underlying digests do */ -int DigestCtxInit( - DigestCtx *ctx, - CSSM_ALGORITHMS hashAlg) -{ - switch(hashAlg) { - case CSSM_ALGID_SHA1: - ctx->ops = &Sha1Ops; - break; - case CSSM_ALGID_MD5: - ctx->ops = &Md5Ops; - break; - case CSSM_ALGID_MD2: - ctx->ops = &Md2Ops; - break; - default: - return 0; - } - ctx->hashAlg = hashAlg; - return ctx->ops->init(&ctx->dig); -} - -void DigestCtxFree( - DigestCtx *ctx) -{ - memset(ctx, 0, sizeof(DigestCtx)); -} - -int DigestCtxUpdate( - DigestCtx *ctx, - const void *textPtr, - uint32 textLen) -{ - return ctx->ops->update(&ctx->dig, textPtr, textLen); -} - -int DigestCtxFinal( - DigestCtx *ctx, - void *digest) -{ - return ctx->ops->final(digest, &ctx->dig); -} diff --git a/libsecurity_apple_csp/lib/pbkdDigest.h b/libsecurity_apple_csp/lib/pbkdDigest.h deleted file mode 100644 index 28421fc2..00000000 --- a/libsecurity_apple_csp/lib/pbkdDigest.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please - * obtain a copy of the License at http://www.apple.com/publicsource and - * read it before using this file. - * - * This 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. - */ -/* - * pbkdDigest.h - SHA1/MD5 digest object for HMAC and PBE routines - */ - -#ifndef _PBKD_DIGEST_H_ -#define _PBKD_DIGEST_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define kSHA1DigestSize CC_SHA1_DIGEST_LENGTH -#define kSHA1BlockSize CC_SHA1_BLOCK_BYTES - -#define kMD5DigestSize CC_MD5_DIGEST_LENGTH -#define kMD5BlockSize CC_MD5_BLOCK_BYTES - -#define kMD2DigestSize CC_MD2_DIGEST_LENGTH -#define kMD2BlockSize CC_MD2_BLOCK_BYTES - -#define kMaxDigestSize kSHA1DigestSize - -typedef int (*DigestInitFcn)(void *ctx); -typedef int (*DigestUpdateFcn)(void *ctx, const void *data, unsigned long len); -typedef int (*DigestFinalFcn)(void *md, void *c); - -/* callouts to eay/libmd implementations */ -typedef struct { - DigestInitFcn init; - DigestUpdateFcn update; - DigestFinalFcn final; -} DigestOps; - -typedef struct { - union { - CC_SHA1_CTX sha1Context; - CC_MD5_CTX md5Context; - CC_MD2_CTX md2Context; - } dig; - DigestOps *ops; - CSSM_ALGORITHMS hashAlg; -} DigestCtx; - -/* Ops on a DigestCtx - all return zero on error, like the underlying digests do */ -int DigestCtxInit( - DigestCtx *ctx, - CSSM_ALGORITHMS hashAlg); -void DigestCtxFree( - DigestCtx *ctx); -int DigestCtxUpdate( - DigestCtx *ctx, - const void *textPtr, - uint32 textLen); -int DigestCtxFinal( - DigestCtx *ctx, - void *digest); - -#ifdef __cplusplus -} -#endif - -#endif /* _PBKD_DIGEST_H_ */ - diff --git a/libsecurity_apple_csp/lib/pbkdf2.c b/libsecurity_apple_csp/lib/pbkdf2.c deleted file mode 100644 index 87827638..00000000 --- a/libsecurity_apple_csp/lib/pbkdf2.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - - -/* - File: pbkdf2.c - Contains: Apple Data Security Services PKCS #5 PBKDF2 function definition. - Copyright: (C) 1999 by Apple Computer, Inc., all rights reserved - Written by: Michael Brouwer -*/ -#include "pbkdf2.h" -#include -#include -/* Will write hLen bytes into dataPtr according to PKCS #5 2.0 spec. - See: http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-5.html for details. - tempBuffer is a pointer to at least MAX (hLen, saltLen + 4) + hLen bytes. */ -static void -F (PRF prf, uint32 hLen, - const void *passwordPtr, uint32 passwordLen, - const void *saltPtr, uint32 saltLen, - uint32 iterationCount, - uint32 blockNumber, - void *dataPtr, - void *tempBuffer) -{ - uint8 *inBlock, *outBlock, *resultBlockPtr; - uint32 iteration; - outBlock = (uint8*)tempBuffer; - inBlock = outBlock + hLen; - /* Set up inBlock to contain Salt || INT (blockNumber). */ - memcpy (inBlock, saltPtr, saltLen); - - inBlock[saltLen + 0] = (uint8)(blockNumber >> 24); - inBlock[saltLen + 1] = (uint8)(blockNumber >> 16); - inBlock[saltLen + 2] = (uint8)(blockNumber >> 8); - inBlock[saltLen + 3] = (uint8)(blockNumber); - - /* Caculate U1 (result goes to outBlock) and copy it to resultBlockPtr. */ - resultBlockPtr = (uint8*)dataPtr; - prf (passwordPtr, passwordLen, inBlock, saltLen + 4, outBlock); - memcpy (resultBlockPtr, outBlock, hLen); - /* Calculate U2 though UiterationCount. */ - for (iteration = 2; iteration <= iterationCount; iteration++) - { - uint8 *tempBlock; - uint32 byte; - /* Swap inBlock and outBlock pointers. */ - tempBlock = inBlock; - inBlock = outBlock; - outBlock = tempBlock; - /* Now inBlock conatins Uiteration-1. Calclulate Uiteration into outBlock. */ - prf (passwordPtr, passwordLen, inBlock, hLen, outBlock); - /* Xor data in dataPtr (U1 \xor U2 \xor ... \xor Uiteration-1) with - outBlock (Uiteration). */ - for (byte = 0; byte < hLen; byte++) - resultBlockPtr[byte] ^= outBlock[byte]; - } -} -void pbkdf2 (PRF prf, uint32 hLen, - const void *passwordPtr, uint32 passwordLen, - const void *saltPtr, uint32 saltLen, - uint32 iterationCount, - void *dkPtr, uint32 dkLen, - void *tempBuffer) -{ - uint32 completeBlocks = dkLen / hLen; - uint32 partialBlockSize = dkLen % hLen; - uint32 blockNumber; - uint8 *dataPtr = (uint8*)dkPtr; - uint8 *blkBuffer = (uint8*)tempBuffer; - /* First calculate all the complete hLen sized blocks required. */ - for (blockNumber = 1; blockNumber <= completeBlocks; blockNumber++) - { - F (prf, hLen, passwordPtr, passwordLen, saltPtr, saltLen, - iterationCount, blockNumber, dataPtr, blkBuffer + hLen); - dataPtr += hLen; - } - /* Finally if the requested output size was not an even multiple of hLen, calculate - the final block and copy the first partialBlockSize bytes of it to the output. */ - if (partialBlockSize > 0) - { - F (prf, hLen, passwordPtr, passwordLen, saltPtr, saltLen, - iterationCount, blockNumber, blkBuffer, blkBuffer + hLen); - memcpy (dataPtr, blkBuffer, partialBlockSize); - } -} diff --git a/libsecurity_apple_csp/lib/pbkdf2.h b/libsecurity_apple_csp/lib/pbkdf2.h deleted file mode 100644 index 377b303f..00000000 --- a/libsecurity_apple_csp/lib/pbkdf2.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - - -/* - File: pbkdf2.h - Contains: Apple Data Security Services PKCS #5 PBKDF2 function declaration. - Copyright: (C) 1999 by Apple Computer, Inc., all rights reserved - Written by: Michael Brouwer -*/ - -#ifndef __PBKDF2__ -#define __PBKDF2__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* This function should generate a pseudo random octect stream - of hLen bytes long (The value hLen is specified as an argument to pbkdf2 - and should be constant for any given prf function.) which is output in the buffer - pointed to by randomPtr (the caller of this function is responsible for allocation - of the buffer). - The inputs to the pseudo random function are the first keyLen octets pointed - to by keyPtr and the first textLen octets pointed to by textPtr. - Both keyLen and textLen can have any nonzero value. - A good prf would be a HMAC-SHA-1 algorithm where the keyPtr octets serve as - HMAC's "key" and the textPtr octets serve as HMAC's "text". */ -typedef void (*PRF)(const void *keyPtr, uint32 keyLen, - const void *textPtr, uint32 textLen, - void *randomPtr); - -/* This function implements the PBKDF2 key derrivation algorithm described in - http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-5.html - The output is a derived key of dkLen bytes which is written to the buffer - pointed to by dkPtr. - The caller should ensure dkPtr is at least dkLen bytes long. - The Key is derived from passwordPtr (which is passwordLen bytes long) and from - saltPtr (which is saltLen bytes long). The algorithm used is desacribed in - PKCS #5 version 2.0 and iterationCount iterations are performed. - The argument prf is a pointer to a psuedo random number generator declared above. - It should write exactly hLen bytes into its output buffer each time it is called. - The argument tempBuffer should point to a buffer MAX (hLen, saltLen + 4) + 2 * hLen - bytes long. This buffer is used during the calculation for intermediate results. - Security Considerations: - The argument saltPtr should be a pointer to a buffer of at least 8 random bytes - (64 bits). Thus saltLen should be >= 8. - For each session a new salt should be generated. - The value of iterationCount should be at least 1000 (one thousand). - A good prf would be a HMAC-SHA-1 algorithm where the password serves as - HMAC's "key" and the data serves as HMAC's "text". */ -void pbkdf2 (PRF prf, uint32 hLen, - const void *passwordPtr, uint32 passwordLen, - const void *saltPtr, uint32 saltLen, - uint32 iterationCount, - void *dkPtr, uint32 dkLen, - void *tempBuffer); - -#ifdef __cplusplus -} -#endif - -#endif /* __PBKDF2__ */ diff --git a/libsecurity_apple_csp/lib/rijndael-alg-ref.c b/libsecurity_apple_csp/lib/rijndael-alg-ref.c deleted file mode 100644 index ff329cc6..00000000 --- a/libsecurity_apple_csp/lib/rijndael-alg-ref.c +++ /dev/null @@ -1,620 +0,0 @@ -/* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - - -/* rijndael-alg-ref.c v2.0 August '99 - * Reference ANSI C code - * authors: Paulo Barreto - * Vincent Rijmen - * - * PPC and 128-bit block optimization by Doug Mitchell May 2001. - */ - -#include -#include -#include - -#include "rijndael-alg-ref.h" -#include - -#define SC ((BC - 4) >> 1) - -#include "boxes-ref.h" - -static const word8 shifts[3][4][2] = { - { { 0, 0 }, - { 1, 3 }, - { 2, 2 }, - { 3, 1 } - }, - { { 0, 0 }, - { 1, 5 }, - { 2, 4 }, - { 3, 3 } - }, - { { 0, 0 }, - { 1, 7 }, - { 3, 5 }, - { 4, 4 } - } -}; - -#if !GLADMAN_AES_128_ENABLE - -/* 128 bit key/word shift table in bits */ -static const word8 shifts128[4][2] = { - { 0, 0 }, - { 8, 24 }, - { 16, 16 }, - { 24, 8 } -}; - -#endif /* GLADMAN_AES_128_ENABLE */ - -#if !AES_MUL_BY_LOOKUP -/* - * Profiling measurements showed that the mul routine is where a large propertion of - * the time is spent. Since the first argument to mul is always one of six - * constants (2, 3, 0xe, etc.), we implement six 256x256 byte lookup tables to - * do the multiplies. This eliminates the need for the log/antilog tables, so - * it's only adding one kilobyte of const data. Throughput improvement for this - * mod is a factor of 3.3 for encrypt and 4.1 for decrypt in the 128-bit optimized - * case. Improvement for the general case (with a 256 bit key) is 1.46 for encrypt - * and 1.88 for decrypt. (Decrypt wins more for this enhancement because the - * InvMixColumn does four muls, vs. 2 muls for MixColumn). Measurements taken - * on a 500 MHz G4 with 1 MB of L2 cache. - */ - -/* - * The mod 255 op in mul is really expensive... - * - * We know that b <= (254 * 2), so there are only two cases. Either return b, - * or return b-255. - * - * On a G4 this single optimization results in a 24% speedup for encrypt and - * a 25% speedup for decrypt. - */ -static inline word8 mod255(word32 b) -{ - if(b >= 255) { - b -= 255; - } - return b; -} - -word8 mul(word8 a, word8 b) { - /* multiply two elements of GF(2^m) - * needed for MixColumn and InvMixColumn - */ - if (a && b) return Alogtable[mod255(Logtable[a] + Logtable[b])]; - else return 0; -} -#endif /* !AES_MUL_BY_LOOKUP */ - -static -void KeyAddition(word8 a[4][MAXBC], word8 rk[4][MAXBC], word8 BC) { - /* Exor corresponding text input and round key input bytes - */ - int i, j; - - for(i = 0; i < 4; i++) - for(j = 0; j < BC; j++) a[i][j] ^= rk[i][j]; -} - -static -void ShiftRow(word8 a[4][MAXBC], word8 d, word8 BC) { - /* Row 0 remains unchanged - * The other three rows are shifted a variable amount - */ - word8 tmp[MAXBC]; - int i, j; - - for(i = 1; i < 4; i++) { - for(j = 0; j < BC; j++) tmp[j] = a[i][(j + shifts[SC][i][d]) % BC]; - for(j = 0; j < BC; j++) a[i][j] = tmp[j]; - } -} - -static -void Substitution(word8 a[4][MAXBC], const word8 box[256], word8 BC) { - /* Replace every byte of the input by the byte at that place - * in the nonlinear S-box - */ - int i, j; - - for(i = 0; i < 4; i++) - for(j = 0; j < BC; j++) a[i][j] = box[a[i][j]] ; -} - -static -void MixColumn(word8 a[4][MAXBC], word8 BC) { - /* Mix the four bytes of every column in a linear way - */ - word8 b[4][MAXBC]; - int i, j; - - for(j = 0; j < BC; j++) { - for(i = 0; i < 4; i++) { - #if AES_MUL_BY_LOOKUP - b[i][j] = mulBy0x02[a[i][j]] - ^ mulBy0x03[a[(i + 1) % 4][j]] - ^ a[(i + 2) % 4][j] - ^ a[(i + 3) % 4][j]; - #else - b[i][j] = mul(2,a[i][j]) - ^ mul(3,a[(i + 1) % 4][j]) - ^ a[(i + 2) % 4][j] - ^ a[(i + 3) % 4][j]; - #endif - } - } - for(i = 0; i < 4; i++) { - for(j = 0; j < BC; j++) a[i][j] = b[i][j]; - } -} - -static -void InvMixColumn(word8 a[4][MAXBC], word8 BC) { - /* Mix the four bytes of every column in a linear way - * This is the opposite operation of Mixcolumn - */ - word8 b[4][MAXBC]; - int i, j; - - for(j = 0; j < BC; j++) { - for(i = 0; i < 4; i++) { - #if AES_MUL_BY_LOOKUP - b[i][j] = mulBy0x0e[a[i][j]] - ^ mulBy0x0b[a[(i + 1) % 4][j]] - ^ mulBy0x0d[a[(i + 2) % 4][j]] - ^ mulBy0x09[a[(i + 3) % 4][j]]; - #else - b[i][j] = mul(0xe,a[i][j]) - ^ mul(0xb,a[(i + 1) % 4][j]) - ^ mul(0xd,a[(i + 2) % 4][j]) - ^ mul(0x9,a[(i + 3) % 4][j]); - #endif - } - } - for(i = 0; i < 4; i++) { - for(j = 0; j < BC; j++) a[i][j] = b[i][j]; - } -} - -int rijndaelKeySched ( - word8 k[4][MAXKC], - int keyBits, - int blockBits, - word8 W[MAXROUNDS+1][4][MAXBC]) { - - /* Calculate the necessary round keys - * The number of calculations depends on keyBits and blockBits - */ - int KC, BC, ROUNDS; - int i, j, t, rconpointer = 0; - word8 tk[4][MAXKC]; - - switch (keyBits) { - case 128: KC = 4; break; - case 192: KC = 6; break; - case 256: KC = 8; break; - default : return (-1); - } - - switch (blockBits) { - case 128: BC = 4; break; - case 192: BC = 6; break; - case 256: BC = 8; break; - default : return (-2); - } - - switch (keyBits >= blockBits ? keyBits : blockBits) { - case 128: ROUNDS = 10; break; - case 192: ROUNDS = 12; break; - case 256: ROUNDS = 14; break; - default : return (-3); /* this cannot happen */ - } - - - for(j = 0; j < KC; j++) - for(i = 0; i < 4; i++) - tk[i][j] = k[i][j]; - t = 0; - /* copy values into round key array */ - for(j = 0; (j < KC) && (t < (ROUNDS+1)*BC); j++, t++) - for(i = 0; i < 4; i++) W[t / BC][i][t % BC] = tk[i][j]; - - while (t < (ROUNDS+1)*BC) { /* while not enough round key material calculated */ - /* calculate new values */ - for(i = 0; i < 4; i++) - tk[i][0] ^= S[tk[(i+1)%4][KC-1]]; - tk[0][0] ^= rcon[rconpointer++]; - - if (KC != 8) - for(j = 1; j < KC; j++) - for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1]; - else { - for(j = 1; j < KC/2; j++) - for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1]; - for(i = 0; i < 4; i++) tk[i][KC/2] ^= S[tk[i][KC/2 - 1]]; - for(j = KC/2 + 1; j < KC; j++) - for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1]; - } - /* copy values into round key array */ - for(j = 0; (j < KC) && (t < (ROUNDS+1)*BC); j++, t++) - for(i = 0; i < 4; i++) W[t / BC][i][t % BC] = tk[i][j]; - } - - return 0; -} - -int rijndaelEncrypt ( - word8 a[4][MAXBC], - int keyBits, - int blockBits, - word8 rk[MAXROUNDS+1][4][MAXBC]) -{ - /* Encryption of one block, general case. - */ - int r, BC, ROUNDS; - - switch (blockBits) { - case 128: BC = 4; break; - case 192: BC = 6; break; - case 256: BC = 8; break; - default : return (-2); - } - - switch (keyBits >= blockBits ? keyBits : blockBits) { - case 128: ROUNDS = 10; break; - case 192: ROUNDS = 12; break; - case 256: ROUNDS = 14; break; - default : return (-3); /* this cannot happen */ - } - - /* begin with a key addition - */ - KeyAddition(a,rk[0],BC); - - /* ROUNDS-1 ordinary rounds - */ - for(r = 1; r < ROUNDS; r++) { - Substitution(a,S,BC); - ShiftRow(a,0,BC); - MixColumn(a,BC); - KeyAddition(a,rk[r],BC); - } - - /* Last round is special: there is no MixColumn - */ - Substitution(a,S,BC); - ShiftRow(a,0,BC); - KeyAddition(a,rk[ROUNDS],BC); - - return 0; -} - -int rijndaelDecrypt ( - word8 a[4][MAXBC], - int keyBits, - int blockBits, - word8 rk[MAXROUNDS+1][4][MAXBC]) -{ - int r, BC, ROUNDS; - - switch (blockBits) { - case 128: BC = 4; break; - case 192: BC = 6; break; - case 256: BC = 8; break; - default : return (-2); - } - - switch (keyBits >= blockBits ? keyBits : blockBits) { - case 128: ROUNDS = 10; break; - case 192: ROUNDS = 12; break; - case 256: ROUNDS = 14; break; - default : return (-3); /* this cannot happen */ - } - - /* To decrypt: apply the inverse operations of the encrypt routine, - * in opposite order - * - * (KeyAddition is an involution: it 's equal to its inverse) - * (the inverse of Substitution with table S is Substitution with the - * inverse table of S) - * (the inverse of Shiftrow is Shiftrow over a suitable distance) - */ - - /* First the special round: - * without InvMixColumn - * with extra KeyAddition - */ - KeyAddition(a,rk[ROUNDS],BC); - Substitution(a,Si,BC); - ShiftRow(a,1,BC); - - /* ROUNDS-1 ordinary rounds - */ - for(r = ROUNDS-1; r > 0; r--) { - KeyAddition(a,rk[r],BC); - InvMixColumn(a,BC); - Substitution(a,Si,BC); - ShiftRow(a,1,BC); - } - - /* End with the extra key addition - */ - - KeyAddition(a,rk[0],BC); - - return 0; -} - -#if !GLADMAN_AES_128_ENABLE - -/* - * All of these 128-bit-key-and-block routines require 32-bit word-aligned - * char array pointers.ÊThe key schedule arrays are easy; they come from - * keyInstance which has a 4-byte-aligned element preceeding the key schedule. - * Others require manual alignment of a local variable by the caller. - */ - -static inline void KeyAddition128( - word8 a[4][BC_128_OPT], - word8 rk[4][MAXBC]) { - - /* these casts are endian-independent */ - ((word32 *)a)[0] ^= *((word32 *)(&rk[0])); - ((word32 *)a)[1] ^= *((word32 *)(&rk[1])); - ((word32 *)a)[2] ^= *((word32 *)(&rk[2])); - ((word32 *)a)[3] ^= *((word32 *)(&rk[3])); -} - -static void Substitution128( - word8 a[4][BC_128_OPT], - const word8 box[256]) { - /* Replace every byte of the input by the byte at that place - * in the nonlinear S-box - */ - int i, j; - - /* still to be optimized - larger S boxes? */ - for(i = 0; i < 4; i++) { - for(j = 0; j < BC_128_OPT; j++) { - a[i][j] = box[a[i][j]]; - } - } -} - -#if defined(__ppc__) && defined(__GNUC__) - -static inline void rotateWordLeft( - word8 *word, // known to be word aligned - unsigned rotCount) // in bits -{ - word32 lword = *((word32 *)word); - asm("rlwnm %0,%1,%2,0,31" : "=r"(lword) : "0"(lword), "r"(rotCount)); - *((word32 *)word) = lword; -} - -#else - -/* - * Insert your machine/compiler dependent code here, - * or just use this, which works on any platform and compiler - * which supports the __attribute__((aligned(4))) directive. - */ -static void rotateWordLeft( - word8 *word, // known to be word aligned - unsigned rotCount) // in bits -{ - word8 tmp[BC_128_OPT] __attribute__((aligned(4))); - unsigned bytes = rotCount / 8; - - tmp[0] = word[bytes & (BC_128_OPT-1)]; - tmp[1] = word[(1+bytes) & (BC_128_OPT-1)]; - tmp[2] = word[(2+bytes) & (BC_128_OPT-1)]; - tmp[3] = word[(3+bytes) & (BC_128_OPT-1)]; - *((word32 *)word) = *((word32 *)tmp); -} -#endif - -static inline void ShiftRow128( - word8 a[4][BC_128_OPT], - word8 d) { - /* Row 0 remains unchanged - * The other three rows are shifted (actually rotated) a variable amount - */ - int i; - - for(i = 1; i < 4; i++) { - rotateWordLeft(a[i], shifts128[i][d]); - } -} - -/* - * The following two routines are where most of the time is spent in this - * module. Further optimization would have to focus here. - */ -static void MixColumn128(word8 a[4][BC_128_OPT]) { - /* Mix the four bytes of every column in a linear way - */ - word8 b[4][BC_128_OPT]; - int i, j; - - for(j = 0; j < BC_128_OPT; j++) { - for(i = 0; i < 4; i++) { - #if AES_MUL_BY_LOOKUP - b[i][j] = mulBy0x02[a[i][j]] - ^ mulBy0x03[a[(i + 1) % 4][j]] - ^ a[(i + 2) % 4][j] - ^ a[(i + 3) % 4][j]; - #else - b[i][j] = mul(2,a[i][j]) - ^ mul(3,a[(i + 1) % 4][j]) - ^ a[(i + 2) % 4][j] - ^ a[(i + 3) % 4][j]; - #endif - } - } - memmove(a, b, 4 * BC_128_OPT); -} - -static void InvMixColumn128(word8 a[4][BC_128_OPT]) { - /* Mix the four bytes of every column in a linear way - * This is the opposite operation of Mixcolumn - */ - word8 b[4][BC_128_OPT]; - int i, j; - - for(j = 0; j < BC_128_OPT; j++) { - for(i = 0; i < 4; i++) { - #if AES_MUL_BY_LOOKUP - b[i][j] = mulBy0x0e[a[i][j]] - ^ mulBy0x0b[a[(i + 1) % 4][j]] - ^ mulBy0x0d[a[(i + 2) % 4][j]] - ^ mulBy0x09[a[(i + 3) % 4][j]]; - #else - b[i][j] = mul(0xe,a[i][j]) - ^ mul(0xb,a[(i + 1) % 4][j]) - ^ mul(0xd,a[(i + 2) % 4][j]) - ^ mul(0x9,a[(i + 3) % 4][j]); - #endif - } - } - memmove(a, b, 4 * BC_128_OPT); -} - -int rijndaelKeySched128 ( - word8 k[4][KC_128_OPT], - word8 W[MAXROUNDS+1][4][MAXBC]) { - - /* Calculate the necessary round keys - * The number of calculations depends on keyBits and blockBits - */ - int i, j, t, rconpointer = 0; - word8 tk[4][KC_128_OPT]; - unsigned numSchedRows = (ROUNDS_128_OPT + 1) * BC_128_OPT; - - for(j = 0; j < KC_128_OPT; j++) - for(i = 0; i < 4; i++) - tk[i][j] = k[i][j]; - t = 0; - /* copy values into round key array */ - for(j = 0; (j < KC_128_OPT) && (t < numSchedRows); j++, t++) { - for(i = 0; i < 4; i++) { - W[t / BC_128_OPT][i][t % BC_128_OPT] = tk[i][j]; - } - } - - while (t < numSchedRows) { - /* while not enough round key material calculated */ - /* calculate new values */ - for(i = 0; i < 4; i++) { - tk[i][0] ^= S[tk[(i+1)%4][KC_128_OPT-1]]; - } - tk[0][0] ^= rcon[rconpointer++]; - - for(j = 1; j < KC_128_OPT; j++) { - for(i = 0; i < 4; i++) { - tk[i][j] ^= tk[i][j-1]; - } - } - - /* copy values into round key array */ - for(j = 0; (j < KC_128_OPT) && (t < numSchedRows); j++, t++) { - for(i = 0; i < 4; i++) { - W[t / BC_128_OPT][i][t % BC_128_OPT] = tk[i][j]; - } - } - } - - return 0; -} - -int rijndaelEncrypt128 ( - word8 a[4][BC_128_OPT], - word8 rk[MAXROUNDS+1][4][MAXBC]) -{ - /* Encryption of one block. - */ - int r; - - /* begin with a key addition - */ - KeyAddition128(a,rk[0]); - - /* ROUNDS-1 ordinary rounds - */ - for(r = 1; r < ROUNDS_128_OPT; r++) { - Substitution128(a,S); - ShiftRow128(a,0); - MixColumn128(a); - KeyAddition128(a,rk[r]); - } - - /* Last round is special: there is no MixColumn - */ - Substitution128(a,S); - ShiftRow128(a,0); - KeyAddition128(a,rk[ROUNDS_128_OPT]); - - return 0; -} - -int rijndaelDecrypt128 ( - word8 a[4][BC_128_OPT], - word8 rk[MAXROUNDS+1][4][MAXBC]) -{ - int r; - - /* To decrypt: apply the inverse operations of the encrypt routine, - * in opposite order - * - * (KeyAddition is an involution: it 's equal to its inverse) - * (the inverse of Substitution with table S is Substitution with the - * inverse table of S) - * (the inverse of Shiftrow is Shiftrow over a suitable distance) - */ - - /* First the special round: - * without InvMixColumn - * with extra KeyAddition - */ - KeyAddition128(a,rk[ROUNDS_128_OPT]); - Substitution128(a,Si); - ShiftRow128(a,1); - - /* ROUNDS-1 ordinary rounds - */ - for(r = ROUNDS_128_OPT-1; r > 0; r--) { - KeyAddition128(a,rk[r]); - InvMixColumn128(a); - Substitution128(a,Si); - ShiftRow128(a,1); - } - - /* End with the extra key addition - */ - - KeyAddition128(a,rk[0]); - - return 0; -} - -#endif /* !GLADMAN_AES_128_ENABLE */ - diff --git a/libsecurity_apple_csp/lib/rijndael-alg-ref.h b/libsecurity_apple_csp/lib/rijndael-alg-ref.h deleted file mode 100644 index 9b78ad0c..00000000 --- a/libsecurity_apple_csp/lib/rijndael-alg-ref.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - - -/* rijndael-alg-ref.h v2.0 August '99 - * Reference ANSI C code - * authors: Paulo Barreto - * Vincent Rijmen - */ -#ifndef __RIJNDAEL_ALG_H -#define __RIJNDAEL_ALG_H - -#include "aesCommon.h" - -#define MAXBC (MAX_AES_BLOCK_BITS/32) -#define MAXKC (MAX_AES_KEY_BITS/32) -#define MAXROUNDS 14 - -#ifdef __cplusplus -extern "C" { -#endif - -typedef unsigned char word8; -typedef unsigned short word16; -typedef unsigned int word32; - - -int rijndaelKeySched (word8 k[4][MAXKC], int keyBits, int blockBits, - word8 rk[MAXROUNDS+1][4][MAXBC]); -int rijndaelEncrypt (word8 a[4][MAXBC], int keyBits, int blockBits, - word8 rk[MAXROUNDS+1][4][MAXBC]); -#ifndef __APPLE__ -int rijndaelEncryptRound (word8 a[4][MAXBC], int keyBits, int blockBits, - word8 rk[MAXROUNDS+1][4][MAXBC], int rounds); -#endif -int rijndaelDecrypt (word8 a[4][MAXBC], int keyBits, int blockBits, - word8 rk[MAXROUNDS+1][4][MAXBC]); -#ifndef __APPLE__ -int rijndaelDecryptRound (word8 a[4][MAXBC], int keyBits, int blockBits, - word8 rk[MAXROUNDS+1][4][MAXBC], int rounds); -#endif - -#if !GLADMAN_AES_128_ENABLE - -/* - * Optimized routines for 128-bit block and key. - */ -#define ROUNDS_128_OPT 10 -#define BC_128_OPT 4 -#define KC_128_OPT 4 - -/* - * These require 32-bit word-aligned a, k, and rk arrays - */ -int rijndaelKeySched128 (word8 k[4][KC_128_OPT], - word8 rk[MAXROUNDS+1][4][MAXBC]); -int rijndaelEncrypt128 (word8 a[4][BC_128_OPT], - word8 rk[MAXROUNDS+1][4][MAXBC]); -int rijndaelDecrypt128 (word8 a[4][BC_128_OPT], - word8 rk[MAXROUNDS+1][4][MAXBC]); - -#endif /* !GLADMAN_AES_128_ENABLE */ - -#ifdef __cplusplus -} -#endif - -#endif /* __RIJNDAEL_ALG_H */ diff --git a/libsecurity_apple_csp/lib/rijndaelApi.c b/libsecurity_apple_csp/lib/rijndaelApi.c deleted file mode 100644 index 67e84235..00000000 --- a/libsecurity_apple_csp/lib/rijndaelApi.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - - -/* - * rijndaelApi.c - AES API layer - * - * Based on rijndael-api-ref.h v2.0 written by Paulo Barreto - * and Vincent Rijmen - */ -#include -#include - -#include "rijndael-alg-ref.h" -#include "rijndaelApi.h" - -#ifdef ALTIVEC_ENABLE -/* this goes somewhere else and gets init'd by the plugin object.... */ -/* as of 4/11/2001, the vectorized routines do NOT work */ -int gHasAltivec = 0; -#endif - -int doAES128 = 1; - -#define CBC_DEBUG 0 -#if CBC_DEBUG -static void dumpChainBuf(cipherInstance *cipher, char *op) -{ - int t,j; - int columns = cipher->blockLen / 32; - - printf("chainBuf %s: ", op); - for (j = 0; j < columns; j++) { - for(t = 0; t < 4; t++) { - printf("%02x ", cipher->chainBlock[t][j]); - } - } - printf("\n"); -} -#else -#define dumpChainBuf(c, o) -#endif - -int makeKey( - keyInstance *key, - int keyLen, // in BITS - int blockLen, // in BITS - word8 *keyMaterial, - int enable128Opt) -{ - unsigned keyBytes; - unsigned i; - - if (key == NULL) { - return BAD_KEY_INSTANCE; - } - if(keyMaterial == NULL) { - return BAD_KEY_MAT; - } - if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) { - key->keyLen = keyLen; - } else { - return BAD_KEY_MAT; - } - key->blockLen = blockLen; - key->columns = blockLen / 32; - - /* initialize key schedule */ -#if !GLADMAN_AES_128_ENABLE - if(enable128Opt && - (keyLen == MIN_AES_KEY_BITS) && - (blockLen == MIN_AES_BLOCK_BITS)) { - /* optimized, 128 bit key and block size */ - word8 k[4][KC_128_OPT] __attribute__((aligned(4))); - - for(i = 0; i < (MIN_AES_KEY_BITS/8); i++) { - /* speed this up */ - k[i % 4][i / 4] = keyMaterial[i]; - } - rijndaelKeySched128 (k, key->keySched); - memset(k, 0, 4 * KC_128_OPT); - } - else -#endif /* !GLADMAN_AES_128_ENABLE */ - { - - /* general case */ - word8 k[4][MAXKC]; - - keyBytes = keyLen / 8; - for(i = 0; i < keyBytes; i++) { - k[i % 4][i / 4] = keyMaterial[i]; - } - rijndaelKeySched (k, key->keyLen, key->blockLen, key->keySched); - memset(k, 0, 4 * MAXKC); - } - return TRUE; -} - -/* - * Simplified single-block encrypt/decrypt. - */ -#define AES_CONSISTENCY_CHECK 1 - -int rijndaelBlockEncrypt( - keyInstance *key, - word8 *input, - word8 *outBuffer) -{ - int t; - unsigned j; - word8 localBlock[4][MAXBC]; // working memory: encrypt/decrypt in place here - - #if AES_CONSISTENCY_CHECK - if (key == NULL || - (key->keyLen != 128 && key->keyLen != 192 && key->keyLen != 256) || - (key->blockLen != 128 && key->blockLen != 192 && key->blockLen != 256)) { - return BAD_KEY_INSTANCE; - } - #endif /* AES_CONSISTENCY_CHECK */ - - #if defined(__ppc__) && defined(ALTIVEC_ENABLE) - if(gHasAltivec && (key->blockLen == 128)) { - vBlockEncrypt128(key, input, outBuffer); - return 128; - } - #endif - - for (j = 0; j < key->columns; j++) { - for(t = 0; t < 4; t++) - /* parse input stream into rectangular array */ - localBlock[t][j] = input[4*j+t]; - } - rijndaelEncrypt (localBlock, key->keyLen, key->blockLen, key->keySched); - for (j = 0; j < key->columns; j++) { - /* parse rectangular array into output ciphertext bytes */ - for(t = 0; t < 4; t++) - outBuffer[4*j+t] = (word8) localBlock[t][j]; - } - memset(localBlock, 0, 4 * MAXBC); - return key->blockLen; -} - -int rijndaelBlockDecrypt( - keyInstance *key, - word8 *input, - word8 *outBuffer) -{ - int t; - unsigned j; - word8 localBlock[4][MAXBC]; // working memory: encrypt/decrypt in place here - - #if AES_CONSISTENCY_CHECK - if (key == NULL || - (key->keyLen != 128 && key->keyLen != 192 && key->keyLen != 256) || - (key->blockLen != 128 && key->blockLen != 192 && key->blockLen != 256)) { - return BAD_KEY_INSTANCE; - } - #endif /* AES_CONSISTENCY_CHECK */ - - #if defined(__ppc__) && defined(ALTIVEC_ENABLE) - if(gHasAltivec && (cipher->blockLen == 128)) { - vBlockDecrypt128(key, input, outBuffer); - return 128; - } - #endif - - for (j = 0; j < key->columns; j++) { - for(t = 0; t < 4; t++) - /* parse input stream into rectangular array */ - localBlock[t][j] = input[4*j+t]; - } - rijndaelDecrypt (localBlock, key->keyLen, key->blockLen, key->keySched); - for (j = 0; j < key->columns; j++) { - /* parse rectangular array into output ciphertext bytes */ - for(t = 0; t < 4; t++) - outBuffer[4*j+t] = (word8) localBlock[t][j]; - } - memset(localBlock, 0, 4 * MAXBC); - return key->blockLen; -} - -#if !GLADMAN_AES_128_ENABLE -/* - * Optimized routines for 128 bit block and 128 bit key. - */ -int rijndaelBlockEncrypt128( - keyInstance *key, - word8 *input, - word8 *outBuffer) -{ - int j; - word8 localBlock[4][BC_128_OPT] __attribute__((aligned(4))); - word8 *row0 = localBlock[0]; - word8 *row1 = localBlock[1]; - word8 *row2 = localBlock[2]; - word8 *row3 = localBlock[3]; - - /* parse input stream into rectangular array */ - for (j = 0; j < BC_128_OPT; j++) { - *row0++ = *input++; - *row1++ = *input++; - *row2++ = *input++; - *row3++ = *input++; - } - rijndaelEncrypt128 (localBlock, key->keySched); - - /* parse rectangular array into output ciphertext bytes */ - row0 = localBlock[0]; - row1 = localBlock[1]; - row2 = localBlock[2]; - row3 = localBlock[3]; - - for (j = 0; j < BC_128_OPT; j++) { - *outBuffer++ = *row0++; - *outBuffer++ = *row1++; - *outBuffer++ = *row2++; - *outBuffer++ = *row3++; - } - memset(localBlock, 0, 4*BC_128_OPT); - return MIN_AES_BLOCK_BITS; -} - -int rijndaelBlockDecrypt128( - keyInstance *key, - word8 *input, - word8 *outBuffer) -{ - int j; - word8 localBlock[4][BC_128_OPT] __attribute__((aligned(4))); - word8 *row0 = localBlock[0]; - word8 *row1 = localBlock[1]; - word8 *row2 = localBlock[2]; - word8 *row3 = localBlock[3]; - - /* parse input stream into rectangular array */ - for (j = 0; j < BC_128_OPT; j++) { - *row0++ = *input++; - *row1++ = *input++; - *row2++ = *input++; - *row3++ = *input++; - } - - rijndaelDecrypt128 (localBlock, key->keySched); - - /* parse rectangular array into output ciphertext bytes */ - row0 = localBlock[0]; - row1 = localBlock[1]; - row2 = localBlock[2]; - row3 = localBlock[3]; - - for (j = 0; j < BC_128_OPT; j++) { - *outBuffer++ = *row0++; - *outBuffer++ = *row1++; - *outBuffer++ = *row2++; - *outBuffer++ = *row3++; - } - memset(localBlock, 0, 4*BC_128_OPT); - return MIN_AES_BLOCK_BITS; -} -#endif /* !GLADMAN_AES_128_ENABLE */ - diff --git a/libsecurity_apple_csp/lib/rijndaelApi.h b/libsecurity_apple_csp/lib/rijndaelApi.h deleted file mode 100644 index 38e79001..00000000 --- a/libsecurity_apple_csp/lib/rijndaelApi.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - - -/* - * rijndaelApi.h - AES API layer - * - * Based on rijndael-api-ref.h v2.0 written by Paulo Barreto - * and Vincent Rijmen - */ - -#ifndef _RIJNDAEL_API_REF_H_ -#define _RIJNDAEL_API_REF_H_ - -#include -#include "rijndael-alg-ref.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Error Codes */ -#define BAD_KEY_MAT -1 /* Key material not of correct - length */ -#define BAD_KEY_INSTANCE -2 /* Key passed is not valid */ - -#define MAX_AES_KEY_SIZE (MAX_AES_KEY_BITS / 8) -#define MAX_AES_BLOCK_SIZE (MAX_AES_BLOCK_BITS / 8) -#define MAX_AES_IV_SIZE MAX_AES_BLOCK_SIZE - -#define TRUE 1 -#define FALSE 0 - -/* The structure for key information */ -typedef struct { - word32 keyLen; /* Length of the key in bits */ - word32 blockLen; /* Length of block in bits */ - word32 columns; /* optimization, blockLen / 32 */ - word8 keySched[MAXROUNDS+1][4][MAXBC]; -} keyInstance; - -int makeKey( - keyInstance *key, - int keyLen, // in BITS - int blockLen, // in BITS - word8 *keyMaterial, - int enable128Opt); - -/* - * Simplified single-block encrypt/decrypt. - */ -int rijndaelBlockEncrypt( - keyInstance *key, - word8 *input, - word8 *outBuffer); -int rijndaelBlockDecrypt( - keyInstance *key, - word8 *input, - word8 *outBuffer); - -#if !GLADMAN_AES_128_ENABLE -/* - * Optimized routines for 128 bit block and 128 bit key. - */ -int rijndaelBlockEncrypt128( - keyInstance *key, - word8 *input, - word8 *outBuffer); -int rijndaelBlockDecrypt128( - keyInstance *key, - word8 *input, - word8 *outBuffer); -#endif /* !GLADMAN_AES_128_ENABLE */ - -#if defined(__ppc__) && defined(ALTIVEC_ENABLE) -/* - * dmitch addenda 4/11/2001: 128-bit only vectorized encrypt/decrypt with no CBC - */ -void vBlockEncrypt128( - keyInstance *key, - word8 *input, - word8 *outBuffer); -void vBlockDecrypt128( - keyInstance *key, - word8 *input, - word8 *outBuffer); - -/* temp switch for runtime enable/disable */ -extern int doAES128; - -#endif /* __ppc__ && ALTIVEC_ENABLE */ - -/* ptr to one of several (possibly optimized) encrypt/decrypt functions */ -typedef int (*aesCryptFcn)( - keyInstance *key, - word8 *input, - word8 *outBuffer); - -#ifdef __cplusplus -} -#endif // cplusplus - -#endif // RIJNDAEL_API_REF - - diff --git a/libsecurity_apple_csp/libsecurity_apple_csp.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_apple_csp/libsecurity_apple_csp.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 7e8cf9b3..00000000 --- a/libsecurity_apple_csp/libsecurity_apple_csp.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,19 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 0539107D0A37721E00B9E848 - - primary - - - 4CA1FEBD052A3C8100F22E42 - - primary - - - - - diff --git a/libsecurity_apple_cspdl/libsecurity_apple_cspdl.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_apple_cspdl/libsecurity_apple_cspdl.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 988e9b5a..00000000 --- a/libsecurity_apple_cspdl/libsecurity_apple_cspdl.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 4CA1FEBD052A3C8100F22E42 - - primary - - - - - diff --git a/libsecurity_apple_file_dl/libsecurity_apple_file_dl.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_apple_file_dl/libsecurity_apple_file_dl.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 988e9b5a..00000000 --- a/libsecurity_apple_file_dl/libsecurity_apple_file_dl.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 4CA1FEBD052A3C8100F22E42 - - primary - - - - - diff --git a/libsecurity_apple_x509_cl/libsecurity_apple_x509_cl.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_apple_x509_cl/libsecurity_apple_x509_cl.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 669930db..00000000 --- a/libsecurity_apple_x509_cl/libsecurity_apple_x509_cl.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,19 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 4CA1FEBD052A3C8100F22E42 - - primary - - - C207F276053B21E600FF85CB - - primary - - - - - diff --git a/libsecurity_apple_x509_tp/lib/cuEnc64.c b/libsecurity_apple_x509_tp/lib/cuEnc64.c deleted file mode 100644 index 14d02f54..00000000 --- a/libsecurity_apple_x509_tp/lib/cuEnc64.c +++ /dev/null @@ -1,587 +0,0 @@ -/* - * Copyright (c) 1998-2003,2010 Apple Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please - * obtain a copy of the License at http://www.apple.com/publicsource and - * read it before using this file. - * - * This 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. - * - * cuEnc64.c - encode/decode in 64-char IA5 format, per RFC 1421 - */ - -#include "cuEnc64.h" -#include -#include -#include - -#ifndef NULL -#define NULL ((void *)0) -#endif /* NULL */ - -/* - * map a 6-bit binary value to a printable character. - */ -static const -unsigned char bintoasc[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -/* - * Map an 7-bit printable character to its corresponding binary value. - * Any illegal characters return high bit set. - */ -static const -unsigned char asctobin[] = -{ - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x3e, 0x80, 0x80, 0x80, 0x3f, - 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, - 0x3c, 0x3d, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, - 0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, - 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80 -}; - -/* - * map 6 bits to a printing char - */ -#define ENC(c) (bintoasc[((c) & 0x3f)]) - -#define PAD '=' - -/* - * map one group of up to 3 bytes at inp to 4 bytes at outp. - * Count is number of valid bytes in *inp; if less than 3, the - * 1 or two extras must be zeros. - */ -static void encChunk(const unsigned char *inp, - unsigned char *outp, - int count) -{ - unsigned char c1, c2, c3, c4; - - c1 = *inp >> 2; - c2 = ((inp[0] << 4) & 0x30) | ((inp[1] >> 4) & 0xf); - c3 = ((inp[1] << 2) & 0x3c) | ((inp[2] >> 6) & 0x3); - c4 = inp[2] & 0x3f; - *outp++ = ENC(c1); - *outp++ = ENC(c2); - if (count == 1) { - *outp++ = PAD; - *outp = PAD; - } else { - *outp++ = ENC(c3); - if (count == 2) { - *outp = PAD; - } - else { - *outp = ENC(c4); - } - } -} - -/* - * Given input buffer inbuf, length inlen, encode to 64-char IA5 format. - * Result is fmalloc'd and returned; it is terminated by Microsoft-style - * newline and NULL. Its length (including the trailing newline and NULL) - * is returned in *outlen. - */ - -unsigned char *cuEnc64(const unsigned char *inbuf, - unsigned inlen, - unsigned *outlen) // RETURNED -{ - return cuEnc64WithLines(inbuf, inlen, 0, outlen); -} - -unsigned char *cuEnc64WithLines(const unsigned char *inbuf, - unsigned inlen, - unsigned linelen, - unsigned *outlen) -{ - unsigned outTextLen; - unsigned len; // to malloc, liberal - unsigned olen = 0; // actual output size - unsigned char *outbuf; - unsigned char endbuf[3]; - unsigned i; - unsigned char *outp; - unsigned numLines; - unsigned thisLine; - - outTextLen = ((inlen + 2) / 3) * 4; - if(linelen) { - /* - * linelen must be 0 mod 4 for this to work; round up... - */ - if((linelen & 0x03) != 0) { - linelen = (linelen + 3) & 0xfffffffc; - } - numLines = (outTextLen + linelen - 1)/ linelen; - } - else { - numLines = 1; - } - - /* - * Total output size = encoded text size plus one newline per - * line of output, plus trailing NULL. We always generate newlines - * as \n; when decoding, we tolerate \r\n (Microsoft) or \n. - */ - len = outTextLen + (2 * numLines) + 1; - outbuf = (unsigned char*)malloc(len); - outp = outbuf; - thisLine = 0; - - while(inlen) { - if(inlen < 3) { - for(i=0; i<3; i++) { - if(i < inlen) { - endbuf[i] = inbuf[i]; - } - else { - endbuf[i] = 0; - } - } - encChunk(endbuf, outp, inlen); - inlen = 0; - } - else { - encChunk(inbuf, outp, 3); - inlen -= 3; - inbuf += 3; - } - outp += 4; - thisLine += 4; - olen += 4; - if((linelen != 0) && (thisLine >= linelen) && inlen) { - /* - * last trailing newline added below - * Note we don't split 4-byte output chunks over newlines - */ - *outp++ = '\n'; - olen++; - thisLine = 0; - } - } - *outp++ = '\n'; - *outp = '\0'; - olen += 2; - *outlen = olen; - return outbuf; -} - -static inline int isWhite(unsigned char c) -{ - switch(c) { - case '\n': - case '\r': - case ' ': - case '\t': - case '\0': - return 1; - default: - return 0; - } -} - -/* - * Strip off all whitespace from a (supposedly) enc64-format string. - * Returns a malloc'd string. - */ -static unsigned char *stringCleanse(const unsigned char *inbuf, - unsigned inlen, - unsigned *outlen) -{ - unsigned char *news; // cleansed inbuf - unsigned newsDex; // index into news - unsigned i; - - news = (unsigned char*)malloc(inlen); - newsDex = 0; - for(i=0; i 0) { - goto errorOut; - } - } - else { - goto errorOut; - } - } else if (*bp & 0x80 || (c3 = asctobin[*bp]) & 0x80) { - goto errorOut; - } else { - bp++; - inlen--; - if (*bp == PAD) { - /* - * Three input bytes, two output - */ - c4 = 0; - thisOlen = 2; - if (c3 & 3) { - goto errorOut; - } - } else if (*bp & 0x80 || (c4 = asctobin[*bp]) & 0x80) { - goto errorOut; - } else { - /* - * Normal non-pad case - */ - thisOlen = 3; - } - bp++; - inlen--; - } - j = (c1 << 2) | (c2 >> 4); - *outp++ = j; - if(thisOlen > 1) { - j = (c2 << 4) | (c3 >> 2); - *outp++ = j; - if(thisOlen == 3) { - j = (c3 << 6) | c4; - *outp++ = j; - } - } - olen += thisOlen; - } - free(news); - *outlen = olen; - return outbuf; /* normal return */ - -errorOut: - free(news); - free(outbuf); - return (unsigned char*) NULL; -} - -/* - * Determine if specified input data is valid enc64 format. Returns 1 - * if valid, 0 if not. - * This doesn't do a full enc64 parse job; it scans for legal characters - * and proper sync when a possible pad is found. - */ -int cuIsValidEnc64(const unsigned char *inbuf, - unsigned inlen) -{ - int padChars = 0; // running count of PAD chars - int validEncChars = 0; - unsigned char c; - - /* - * -- scan inbuf - * -- skip whitespace - * -- count valid chars - * -- ensure not more than 2 PAD chars, only at end - * -- ensure valid chars mod 4 == 0 - */ - - while(inlen) { - c = *inbuf++; - inlen--; - if(isWhite(c)) { - continue; - } - if(c == PAD) { - if(++padChars > 2) { - return 0; // max of 2 PAD chars at end - } - } - else if(padChars > 0) { - return 0; // no normal chars after seeing PAD - } - else if((c & 0x80) || ((asctobin[c]) & 0x80)) { - return 0; // invalid encoded char - } - validEncChars++; - } - if((validEncChars & 0x03) != 0) { - return 0; - } - else { - return 1; - } -} - -/* - * Text parsing routines. - * - * Search incoming text for specified string. Does not assume inText is - * NULL terminated. Returns pointer to start of found string in inText. - */ -static const char *findStr( - const char *inText, - unsigned inTextLen, - const char *str) // NULL terminated - search for this -{ - /* probably not the hottest string search algorithm... */ - const char *cp; - size_t srchStrLen = strlen(str); - char c = str[0]; - - /* last char * we can search in inText for start of str */ - const char *endCp = inText + inTextLen - srchStrLen; - - for(cp=inText; cp<=endCp; cp++) { - if(*cp == c) { - if(!memcmp(cp, str, srchStrLen)) { - return cp; - } - } - } - return NULL; -} - -/* - * Obtain one line from current text. Returns a mallocd, NULL-terminated string - * which caller must free(). Also returns the number of chars consumed including - * the returned chars PLUS EOL terminators (\n and/or \r). - * - * ALWAYS returns a mallocd string if there is ANY data remaining per the - * incoming inTextLen. Returns NULL if inTextLen is zero. - */ -static const char *getLine( - const char *inText, - unsigned inTextLen, // RETURNED - unsigned *consumed) // RETURNED - -{ - *consumed = 0; - const char *cp = inText; - const char *newline = NULL; // if we found a newline, this points to the first one - - while(inTextLen) { - char c = *cp; - if((c == '\r') || (c == '\n')) { - if(newline == NULL) { - /* first newline */ - newline = cp; - } - } - else if(newline != NULL) { - /* non newline after newline, done */ - break; - } - (*consumed)++; - inTextLen--; - cp++; - } - ptrdiff_t linelen; - if(newline) { - linelen = newline - inText; - } - else { - linelen = *consumed; - } - char *rtn = (char *)malloc(linelen + 1); - memmove(rtn, inText, linelen); - rtn[linelen] = 0; - return rtn; -} - -#define UNSUPPORTED_FORMAT_ERR -25256 - -/* - * Given input buffer containing a PEM-encoded certificate, convert to DER - * and return in outbuf. Result is malloced and must be freed by caller; - * its length is returned in *outlen. Returns 0 on success. - */ -int cuConvertPem( - const unsigned char *inbuf, - unsigned inlen, - unsigned char **outbuf, // RETURNED (caller must free) - unsigned *outlen) // RETURNED -{ - unsigned lenToGo = (inlen) ? inlen : 0; - const char *currCp = (inbuf) ? (const char *)inbuf : NULL; - const char *currLine = NULL; // mallocd by getLine() - unsigned consumed; - int ortn = 0; - const char *start64; - unsigned base64Len; - const char *end64; - unsigned char *decData; - unsigned decDataLen; - - /* search to START line, parse it to get type/format/alg */ - const char *startLine = findStr(currCp, lenToGo, "-----BEGIN"); - if(startLine != NULL) { - /* possibly skip over leading garbage */ - consumed = (unsigned)(startLine - currCp); - lenToGo -= consumed; - currCp = startLine; - - /* get C string of START line */ - currLine = getLine(startLine, lenToGo, &consumed); - if(currLine == NULL) { - /* somehow got here with no data */ - // assert(lenToGo == 0); - ortn = UNSUPPORTED_FORMAT_ERR; - goto errOut; - } - // assert(consumed <= lenToGo); - currCp += consumed; - lenToGo -= consumed; - - free((void *)currLine); - } - - /* Skip empty lines. */ - for( ; ; ) { - currLine = getLine(currCp, lenToGo, &consumed); - if(currLine == NULL) { - /* out of data */ - ortn = UNSUPPORTED_FORMAT_ERR; - goto errOut; - } - int skipThis = 0; - size_t lineLen = strlen(currLine); - if(lineLen == 0) { - /* empty line */ - skipThis = 1; - } - free((void *)currLine); - - if(!skipThis) { - /* looks like good stuff; process */ - break; - } - /* skip this line */ - // assert(consumed <= lenToGo); - currCp += consumed; - lenToGo -= consumed; - } - if(lenToGo == 0) { - /* no valid base64 data */ - ortn = UNSUPPORTED_FORMAT_ERR; - goto errOut; - } - - /* - * currCP points to start of base64 data - mark it and search for end line. - * We skip everything after the end line. - */ - start64 = currCp; - base64Len = lenToGo; // if no END - end64 = findStr(currCp, lenToGo, "-----END"); - if(end64 != NULL) { - if(end64 == start64) { - /* Empty, nothing between START and END */ - ortn = UNSUPPORTED_FORMAT_ERR; - goto errOut; - } - base64Len = (unsigned)(end64 - start64); - } - /* else no END, no reason to complain about that as long as base64 decode works OK */ - - /* Base 64 decode */ - decData = cuDec64((const unsigned char *)start64, base64Len, &decDataLen); - if(decData == NULL) { - /* bad base64 data */ - ortn = UNSUPPORTED_FORMAT_ERR; - goto errOut; - } - - if(outlen) { - *outlen = decDataLen; - } - if(outbuf) { - *outbuf = decData; - } - else { - free((void *)decData); - } - -errOut: - return ortn; -} diff --git a/libsecurity_apple_x509_tp/lib/cuEnc64.h b/libsecurity_apple_x509_tp/lib/cuEnc64.h deleted file mode 100644 index 2b3abeb5..00000000 --- a/libsecurity_apple_x509_tp/lib/cuEnc64.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 1998-2003,2010 Apple Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please - * obtain a copy of the License at http://www.apple.com/publicsource and - * read it before using this file. - * - * This 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. - * - * cuEnc64.h - encode/decode in 64-char IA5 format, per RFC 1421 - */ - -#ifndef _CU_ENC64_H_ -#define _CU_ENC64_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Given input buffer inbuf, length inlen, decode from 64-char IA5 format to - * binary. Result is malloced and returned; its length is returned in *outlen. - * NULL return indicates corrupted input. - */ -unsigned char *cuEnc64(const unsigned char *inbuf, - unsigned inlen, - unsigned *outlen); // RETURNED - -/* - * Enc64, with embedded newlines every lineLen in result. A newline is - * the UNIX \n. Result is mallocd. - */ -unsigned char *cuEnc64WithLines(const unsigned char *inbuf, - unsigned inlen, - unsigned linelen, - unsigned *outlen); // RETURNED - -/* - * Given input buffer inbuf, length inlen, decode from 64-char IA5 format to - * binary. Result is malloced and returned; its length is returned in *outlen. - * NULL return indicates corrupted input. All whitespace in inbuf is - * ignored. - */ -unsigned char *cuDec64(const unsigned char *inbuf, - unsigned inlen, - unsigned *outlen); - -/* - * Determine if specified input data is valid enc64 format. Returns 1 - * if valid, 0 if not. - */ -int cuIsValidEnc64(const unsigned char *inbuf, - unsigned inbufLen); - -/* - * Given input buffer containing a PEM-encoded certificate, convert to DER - * and return in outbuf. Result is malloced and must be freed by caller; - * its length is returned in *outlen. Returns 0 on success. - */ -int cuConvertPem(const unsigned char *inbuf, - unsigned inlen, - unsigned char **outbuf, // RETURNED (caller must free) - unsigned *outlen); // RETURNED - -#ifdef __cplusplus -} -#endif - -#endif /*_CU_ENC64_H_*/ diff --git a/libsecurity_apple_x509_tp/lib/ocspRequest.cpp b/libsecurity_apple_x509_tp/lib/ocspRequest.cpp deleted file mode 100644 index b752e49a..00000000 --- a/libsecurity_apple_x509_tp/lib/ocspRequest.cpp +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (c) 2004 Apple Computer, 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@ - */ - -/* - * ocspRequest.cpp - OCSP Request class - */ - -#include "ocspRequest.h" -#include "certGroupUtils.h" -#include "tpdebugging.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* preencoded DER NULL */ -static uint8 nullParam[2] = {5, 0}; - -/* size of nonce we generate, in bytes */ -#define OCSP_NONCE_SIZE 8 - -/* - * The only constructor. Subject and issuer must remain valid for the - * lifetime of this object (they are not refcounted). - */ -OCSPRequest::OCSPRequest( - TPCertInfo &subject, - TPCertInfo &issuer, - bool genNonce) - : mCoder(NULL), - mSubject(subject), - mIssuer(issuer), - mGenNonce(genNonce), - mCertID(NULL) -{ - SecAsn1CoderCreate(&mCoder); - mNonce.Data = NULL; - mNonce.Length = 0; - mEncoded.Data = NULL; - mEncoded.Length = 0; -} - -OCSPRequest::~OCSPRequest() -{ - delete mCertID; - if(mCoder) { - SecAsn1CoderRelease(mCoder); - } -} - -const CSSM_DATA *OCSPRequest::encode() -{ - /* fields obtained from issuer */ - CSSM_DATA_PTR issuerName; - CSSM_DATA_PTR issuerKey; - CSSM_KEY_PTR issuerPubKey; - /* from subject */ - CSSM_DATA_PTR subjectSerial=NULL; - - CSSM_RETURN crtn; - uint8 issuerNameHash[CC_SHA1_DIGEST_LENGTH]; - uint8 pubKeyHash[CC_SHA1_DIGEST_LENGTH]; - SecAsn1OCSPRequest singleReq; - SecAsn1OCSPCertID &certId = singleReq.reqCert; - SecAsn1OCSPSignedRequest signedReq; - SecAsn1OCSPRequest *reqArray[2] = { &singleReq, NULL }; - SecAsn1OCSPTbsRequest &tbs = signedReq.tbsRequest; - uint8 version = 0; - CSSM_DATA vers = {1, &version}; - uint8 nonceBytes[OCSP_NONCE_SIZE]; - CSSM_DATA nonceData = {OCSP_NONCE_SIZE, nonceBytes}; - OCSPNonce *nonce = NULL; - NSS_CertExtension *extenArray[2] = {NULL, NULL}; - - if(mEncoded.Data) { - /* already done */ - return &mEncoded; - } - - /* - * One single request, no extensions - */ - memset(&singleReq, 0, sizeof(singleReq)); - - /* algId refers to the hash we'll perform in issuer name and key */ - certId.algId.algorithm = CSSMOID_SHA1; - certId.algId.parameters.Data = nullParam; - certId.algId.parameters.Length = sizeof(nullParam); - - /* gather fields from two certs */ - crtn = mSubject.fetchField(&CSSMOID_X509V1IssuerNameStd, &issuerName); - if(crtn) { - CssmError::throwMe(crtn); - } - crtn = mIssuer.fetchField(&CSSMOID_CSSMKeyStruct, &issuerKey); - if(crtn) { - goto errOut; - } - crtn = mSubject.fetchField(&CSSMOID_X509V1SerialNumber, &subjectSerial); - if(crtn) { - goto errOut; - } - - /* SHA1(issuerName) */ - ocspdSha1(issuerName->Data, (CC_LONG)issuerName->Length, issuerNameHash); - - /* SHA1(issuer public key) */ - if(issuerKey->Length != sizeof(CSSM_KEY)) { - tpErrorLog("OCSPRequest::encode: malformed issuer key\n"); - crtn = CSSMERR_TP_INTERNAL_ERROR; - goto errOut; - } - issuerPubKey = (CSSM_KEY_PTR)issuerKey->Data; - ocspdSha1(issuerPubKey->KeyData.Data, (CC_LONG)issuerPubKey->KeyData.Length, pubKeyHash); - - /* build the CertID from those components */ - certId.issuerNameHash.Data = issuerNameHash; - certId.issuerNameHash.Length = CC_SHA1_DIGEST_LENGTH; - certId.issuerPubKeyHash.Data = pubKeyHash; - certId.issuerPubKeyHash.Length = CC_SHA1_DIGEST_LENGTH; - certId.serialNumber = *subjectSerial; - - /* - * Build top level request with one entry in requestList, no signature, - * one optional extension (a nonce) - */ - memset(&signedReq, 0, sizeof(signedReq)); - tbs.version = &vers; - tbs.requestList = reqArray; - - /* one extension - the nonce */ - if(mGenNonce) { - DevRandomGenerator drg; - drg.random(nonceBytes, OCSP_NONCE_SIZE); - nonce = new OCSPNonce(mCoder, false, nonceData); - extenArray[0] = nonce->nssExt(); - tbs.requestExtensions = extenArray; - SecAsn1AllocCopyItem(mCoder, &nonceData, &mNonce); - } - - /* Encode */ - if(SecAsn1EncodeItem(mCoder, &signedReq, kSecAsn1OCSPSignedRequestTemplate, - &mEncoded)) { - tpErrorLog("OCSPRequest::encode: error encoding OCSP req\n"); - crtn = CSSMERR_TP_INTERNAL_ERROR; - goto errOut; - } - /* save a copy of the CertID */ - mCertID = new OCSPClientCertID(*issuerName, issuerPubKey->KeyData, *subjectSerial); - -errOut: - if(issuerName) { - mIssuer.freeField(&CSSMOID_X509V1IssuerNameStd, issuerName); - } - if(issuerKey) { - mIssuer.freeField(&CSSMOID_CSSMKeyStruct, issuerKey); - } - if(subjectSerial) { - mSubject.freeField(&CSSMOID_X509V1SerialNumber, subjectSerial); - } - if(nonce) { - delete nonce; - } - if(crtn) { - CssmError::throwMe(crtn); - } - return &mEncoded; -} - -const CSSM_DATA *OCSPRequest::nonce() -{ - /* not legal before encode() called */ - assert(mEncoded.Data != NULL); - if(mNonce.Data) { - return &mNonce; - } - else { - return NULL; - } -} - -OCSPClientCertID *OCSPRequest::certID() -{ - encode(); - return mCertID; -} - diff --git a/libsecurity_apple_x509_tp/lib/ocspRequest.h b/libsecurity_apple_x509_tp/lib/ocspRequest.h deleted file mode 100644 index 627e60c2..00000000 --- a/libsecurity_apple_x509_tp/lib/ocspRequest.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2004 Apple Computer, 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@ - */ - -/* - * ocspRequest.h - OCSP Request class - */ - -#ifndef _OCSP_REQUEST_H_ -#define _OCSP_REQUEST_H_ - -#include "TPCertInfo.h" -#include -#include - -class OCSPClientCertID; - -class OCSPRequest -{ - NOCOPY(OCSPRequest) -public: - /* - * The only constructor. Subject and issuer must remain valid for the - * lifetime of this object (they are not refcounted). - */ - OCSPRequest( - TPCertInfo &subject, - TPCertInfo &issuer, - bool genNonce); - - ~OCSPRequest(); - - /* - * Obtain encoded OCSP request suitable for posting to responder. - * This object owns and maintains the memory. - */ - const CSSM_DATA *encode(); - - /* - * Obtain this request's nonce (which we randomly generate at encode() time), - * This object owns and maintains the memory. Result is NULL} if we - * didn't generate a nonce. - */ - const CSSM_DATA *nonce(); - - /* - * Obtain this request's CertID. Used to look up matching SingleResponse - * in the OCSPResponse. - */ - OCSPClientCertID *certID(); - -private: - SecAsn1CoderRef mCoder; - TPCertInfo &mSubject; - TPCertInfo &mIssuer; - bool mGenNonce; - CSSM_DATA mNonce; - CSSM_DATA mEncoded; /* lazily evaluated */ - OCSPClientCertID *mCertID; /* calculated during encode() */ - -}; - -#endif /* _OCSP_REQUEST_H_ */ - diff --git a/libsecurity_apple_x509_tp/libsecurity_apple_x509_tp.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_apple_x509_tp/libsecurity_apple_x509_tp.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 988e9b5a..00000000 --- a/libsecurity_apple_x509_tp/libsecurity_apple_x509_tp.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 4CA1FEBD052A3C8100F22E42 - - primary - - - - - diff --git a/libsecurity_asn1/config/base.xcconfig b/libsecurity_asn1/config/base.xcconfig deleted file mode 100644 index ae4cd0fd..00000000 --- a/libsecurity_asn1/config/base.xcconfig +++ /dev/null @@ -1,16 +0,0 @@ -CODE_SIGN_IDENTITY = -; -GCC_VERSION = com.apple.compilers.llvm.clang.1_0 -DEBUG_INFORMATION_FORMAT = dwarf-with-dsym -CURRENT_PROJECT_VERSION = $(RC_ProjectSourceVersion) -VERSIONING_SYSTEM = apple-generic; -DEAD_CODE_STRIPPING = YES; - -ARCHS = $(ARCHS_STANDARD_32_64_BIT) - -INDIGO_INSTALL_PATH_PREFIX[sdk=iphonesimulator*] = $(SDKROOT) - -// Debug symbols should be on obviously -GCC_GENERATE_DEBUGGING_SYMBOLS = YES -COPY_PHASE_STRIP = NO -STRIP_STYLE = debugging -STRIP_INSTALLED_PRODUCT = NO diff --git a/libsecurity_asn1/config/lib.xcconfig b/libsecurity_asn1/config/lib.xcconfig deleted file mode 100644 index a08d1b74..00000000 --- a/libsecurity_asn1/config/lib.xcconfig +++ /dev/null @@ -1,33 +0,0 @@ -#include "base.xcconfig" - -PRODUCT_NAME = $(TARGET_NAME) -EXECUTABLE_PREFIX = - -CODE_SIGN_IDENTITY = - -HEADER_SEARCH_PATHS[sdk=macosx*] = $(PROJECT_DIR) $(PROJECT_DIR)/../include $(BUILT_PRODUCTS_DIR)/derived_src $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers $(inherited) - -HEADER_SEARCH_PATHS[sdk=iphone*] = $(PROJECT_DIR) $(PROJECT_DIR)/../sec $(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include $(inherited) - -INSTALL_PATH = $(INDIGO_INSTALL_PATH_PREFIX)/usr/local/lib -INSTALL_PATH_ACTUAL[sdk=iphonesimulator*] = /usr/local/lib -PRIVATE_HEADERS_FOLDER_PATH[sdk=iphone*] = $(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include/security_asn1 -PUBLIC_HEADERS_FOLDER_PATH[sdk=iphone*] = $(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include/security_asn1 -PRIVATE_HEADERS_FOLDER_PATH[sdk=macosx*] = /usr/local/include/security_asn1 -PUBLIC_HEADERS_FOLDER_PATH[sdk=macosx*] = /usr/local/include/security_asn1 - -ALWAYS_SEARCH_USER_PATHS = NO - -GCC_C_LANGUAGE_STANDARD = gnu99 - -WARNING_CFLAGS = -Wmost -Wno-four-char-constants -Wno-unknown-pragmas $(inherited) - -GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO - -GCC_SYMBOLS_PRIVATE_EXTERN = NO -GCC_WARN_64_TO_32_BIT_CONVERSION = YES -GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES -GCC_WARN_ABOUT_RETURN_TYPE = YES -GCC_WARN_UNUSED_VARIABLE = YES - -SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator diff --git a/libsecurity_asn1/lib/SecNssCoder.cpp b/libsecurity_asn1/lib/SecNssCoder.cpp deleted file mode 100644 index 5b077fe9..00000000 --- a/libsecurity_asn1/lib/SecNssCoder.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (c) 2003-2006,2008,2010 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@ - * - * SecNssCoder.cpp: simple C++ wrapper for PLArenaPool and the - * high-level ANS1 encode/decode routines. - */ - -#include -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) - -#include "SecNssCoder.h" -#include -#include -#include -#include -#include - -#ifdef NDEBUG -#define THROW_ENABLE 1 -#else -/* disable link against Security framework when true */ -#define THROW_ENABLE 0 -#endif - -#if THROW_ENABLE -#define THROW_ERROR Security::CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR) -#else -#define THROW_ERROR -#endif - -SecNssCoder::SecNssCoder(PRUint32 chunkSize /* = SNC_CHUNKSIZE_DEF */) - : mPool(NULL) -{ - mPool = PORT_NewArena(chunkSize); - if(mPool == NULL) { - THROW_ERROR; - } -} - -SecNssCoder::~SecNssCoder() -{ - if(mPool != NULL) { - /* - * Note: we're asking for a memory zero here, but - * PORT_FreeArena doesn't do that (yet). - */ - PORT_FreeArena(mPool, PR_TRUE); - mPool = NULL; - } -} - -PRErrorCode SecNssCoder::decode( - const void *src, // BER-encoded source - size_t len, - const SecAsn1Template *templ, - void *dest) -{ - SECStatus prtn; - - assert(mPool != NULL); - prtn = SEC_ASN1Decode(mPool, dest, templ, (const char *)src, len); - if(prtn) { - return PR_GetError(); - } - else { - return 0; - } -} - -PRErrorCode SecNssCoder::encodeItem( - const void *src, - const SecAsn1Template *templ, - SECItem &dest) -{ - assert(mPool != NULL); - - dest.Data = NULL; - dest.Length = 0; - - SECItem *rtnItem = SEC_ASN1EncodeItem(mPool, &dest, src, templ); - if(rtnItem == NULL) { - return PR_GetError(); - } - else { - return 0; - } -} - -void *SecNssCoder::malloc(size_t len) -{ - assert(mPool != NULL); - void *rtn = PORT_ArenaAlloc(mPool, len); - if(rtn == NULL) { - THROW_ERROR; - } - return rtn; -} - -/* malloc item.Data, set item.Length */ -void SecNssCoder::allocItem( - SECItem &item, - size_t len) -{ - item.Data = (uint8 *)malloc(len); - item.Length = len; -} - -/* malloc and copy */ -void SecNssCoder::allocCopyItem( - const void *src, - size_t len, - SECItem &dest) -{ - allocItem(dest, len); - memmove(dest.Data, src, len); -} - -/* - * This is pretty much a copy of SEC_ASN1EncodeItem, with a Allocator - * malloc replacing the sec_asn1e_allocate_item to alloc the output data. - */ -PRErrorCode SecNssEncodeItem( - const void *src, - const SecAsn1Template *templ, - Security::Allocator &alloc, - SECItem &dest) -{ - unsigned long encoding_length = 0; - SECStatus rv; - - dest.Data = NULL; - dest.Length = 0; - - rv = SEC_ASN1Encode (src, templ, - sec_asn1e_encode_item_count, &encoding_length); - if (rv != SECSuccess) { - return PR_GetError(); - } - - /* replace this... - dest = sec_asn1e_allocate_item (poolp, dest, encoding_length); - if (dest == NULL) - return NULL; - ... with this: */ - dest.Data = (uint8 *)alloc.malloc(encoding_length); - dest.Length = 0; - /* end replacement */ - - rv = SEC_ASN1Encode (src, templ, sec_asn1e_encode_item_store, &dest); - if (rv != SECSuccess) { - return PR_GetError(); - } - - assert(encoding_length == dest.Length); - return 0; -} - -PRErrorCode SecNssEncodeItemOdata( - const void *src, - const SecAsn1Template *templ, - CssmOwnedData &odata) -{ - Allocator &alloc = odata.allocator; - SECItem sitem; - PRErrorCode prtn; - - prtn = SecNssEncodeItem(src, templ, alloc, sitem); - if(prtn) { - return prtn; - } - odata.set(sitem.Data, sitem.Length); - return 0; -} - -#endif /* TARGET_OS_MAC */ diff --git a/libsecurity_asn1/lib/SecNssCoder.h b/libsecurity_asn1/lib/SecNssCoder.h deleted file mode 100644 index fa16abe5..00000000 --- a/libsecurity_asn1/lib/SecNssCoder.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2003-2006,2008,2010 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@ - * - * SecNssCoder.h: simple C++ wrapper for PLArenaPool and the - * high-level ANS1 encode/decode routines. - */ -#ifndef _SEC_NSS_CODER_H_ -#define _SEC_NSS_CODER_H_ - -#include -#include -#include -#include -#include -#include - -/* - * Default chunk size for new arena pool. - * FIXME: analyze & measure different defaults here. I'm pretty sure - * that only performance - not correct behavior - is affected by - * an arena pool's chunk size. - */ -#define SNC_CHUNKSIZE_DEF 1024 - -class SecNssCoder -{ -public: - SecNssCoder( - PRUint32 chunkSize = SNC_CHUNKSIZE_DEF); - ~SecNssCoder(); - - /* - * BER decode an untyped item per the specified - * template array. The result is allocated - * by this object's PLArenaPool and is freed when - * this object is deleted. - * - * The dest pointer is a template-specific struct allocated - * by the caller and must be zeroed by the caller. - * - * This does not throw any exceptions; error status - * (obtained from PR_GetError() is returned. - */ - PRErrorCode decode( - const void *src, // BER-encoded source - size_t len, - const SecAsn1Template *templ, - void *dest); - - /* convenience routine, decode from an SECItem */ - PRErrorCode decodeItem( - const SECItem &item, // BER-encoded source - const SecAsn1Template *templ, - void *dest) - { - return decode(item.Data, item.Length, templ, dest); - } - - - /* - * BER-encode. This object's arena pool retains a copy of - * the encoded data. - * - * The src pointer is a template-specific struct. - * - * This does not throw any exceptions; error status - * (obtained from PR_GetError() is returned. - */ - PRErrorCode encodeItem( - const void *src, - const SecAsn1Template *templ, - SECItem &dest); - - /* - * Some alloc-related methods which come in handy when using - * this class. All memory is allocated using this object's - * arena pool. Caller never has to free it. Used for - * temp allocs of memory which only needs a scope which is the - * same as this object. - * - * These throw a CssmError in the highly unlikely event of - * a malloc failure. - */ - void *malloc( - size_t len); - - /* allocate space for num copies of specified type */ - template T *mallocn(unsigned num = 1) - { return reinterpret_cast(malloc(sizeof(T) * num)); } - - /* malloc item.Data, set item.Length */ - void allocItem( - SECItem &item, - size_t len); - - /* malloc and copy, various forms */ - void allocCopyItem( - const void *src, - size_t len, - SECItem &dest); - - void allocCopyItem( - const SECItem &src, - SECItem &dest) - { allocCopyItem(src.Data, src.Length, dest); } - - void allocCopyItem( - const CssmData &src, - SECItem &dest) - { allocCopyItem(src.data(), src.length(), dest); } - - PLArenaPool *pool() const { return mPool;} - -private: - PLArenaPool *mPool; -}; - -/* - * Stateless function to BER-encode directly into a Allocator's - * space. The only persistent allocated memory is allocated by - * the Allocator. - * - * The src pointer is a template-specific struct. - * - * This does not throw any exceptions; error status - * (obtained from PR_GetError() is returned. - */ -PRErrorCode SecNssEncodeItem( - const void *src, - const SecAsn1Template *templ, - Allocator &alloc, - SECItem &dest); - -/* - * Same thing, using a CssmOwnedData. - */ -PRErrorCode SecNssEncodeItemOdata( - const void *src, - const SecAsn1Template *templ, - CssmOwnedData &odata); - -#endif /* _SEC_NSS_CODER_H_ */ diff --git a/libsecurity_asn1/lib/oidsalg.c b/libsecurity_asn1/lib/oidsalg.c deleted file mode 100644 index 4eae7bf2..00000000 --- a/libsecurity_asn1/lib/oidsalg.c +++ /dev/null @@ -1,497 +0,0 @@ -/* - * Copyright (c) 2000-2004,2008,2010 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@ - */ - -/* - * oidsalg.c - OIDs defining crypto algorithms - */ - -#include -#include "SecAsn1Types.h" -#include "oidsbase.h" - -static const uint8_t - OID_MD2[] = { OID_RSA_HASH, 2 }, - OID_MD4[] = { OID_RSA_HASH, 4 }, - OID_MD5[] = { OID_RSA_HASH, 5 }, - OID_RSAEncryption[] = { OID_PKCS_1, 1 }, - OID_MD2WithRSA[] = { OID_PKCS_1, 2 }, - OID_MD4WithRSA[] = { OID_PKCS_1, 3 }, - OID_MD5WithRSA[] = { OID_PKCS_1, 4 }, - OID_SHA1WithRSA[] = { OID_PKCS_1, 5 }, - OID_RSAWithOAEP[] = { OID_PKCS_1, 7 }, - OID_OAEP_MGF1[] = { OID_PKCS_1, 8 }, - OID_OAEP_ID_PSPECIFIED[]= { OID_PKCS_1, 9 }, - OID_SHA224WithRSA[] = { OID_PKCS_1, 14 }, - OID_SHA256WithRSA[] = { OID_PKCS_1, 11 }, - OID_SHA384WithRSA[] = { OID_PKCS_1, 12 }, - OID_SHA512WithRSA[] = { OID_PKCS_1, 13 }, - OID_PKCS_3_ARC[] = { OID_PKCS_3 }, - OID_DHKeyAgreement[] = { OID_PKCS_3, 1 }, - /* BSAFE-specific DSA */ - OID_OIW_DSA[] = { OID_OIW_ALGORITHM, 12 }, - OID_OIW_DSAWithSHA1[] = { OID_OIW_ALGORITHM, 27 }, - /* DSA from CMS */ - OID_CMS_DSA[] = { 0x2A, 0x86, 0x48, 0xCE, 0x38, 4, 1 }, - OID_CMS_DSAWithSHA1[] = { 0x2A, 0x86, 0x48, 0xCE, 0x38, 4, 3 }, - /* DSA from JDK 1.1 */ - OID_JDK_DSA[] = { 0x2B, 0x0E, 0x03, 0x02, 0x0c }, - OID_JDK_DSAWithSHA1[] = { 0x2B, 0x0E, 0x03, 0x02, 0x0D }, - - OID_OIW_SHA1[] = { OID_OIW_ALGORITHM, 26 }, - OID_OIW_RSAWithSHA1[] = { OID_OIW_ALGORITHM, 29 }, - OID_OIW_DES_CBC[] = { OID_OIW_ALGORITHM, 7 }, - - OID_SHA224[] = { OID_NIST_HASHALG, 4}, - OID_SHA256[] = { OID_NIST_HASHALG, 1}, - OID_SHA384[] = { OID_NIST_HASHALG, 2}, - OID_SHA512[] = { OID_NIST_HASHALG, 3}, - - /* ANSI X9.42 */ - OID_ANSI_DH_PUB_NUMBER[]= { OID_ANSI_X9_42, 1 }, - OID_ANSI_DH_STATIC[] = { OID_ANSI_X9_42_SCHEME, 1 }, - OID_ANSI_DH_EPHEM[] = { OID_ANSI_X9_42_SCHEME, 2 }, - OID_ANSI_DH_ONE_FLOW[] = { OID_ANSI_X9_42_SCHEME, 3 }, - OID_ANSI_DH_HYBRID1[] = { OID_ANSI_X9_42_SCHEME, 4 }, - OID_ANSI_DH_HYBRID2[] = { OID_ANSI_X9_42_SCHEME, 5 }, - OID_ANSI_DH_HYBRID_ONEFLOW[] = { OID_ANSI_X9_42_SCHEME, 6 }, - /* sic - enumerated in reverse order in the spec */ - OID_ANSI_MQV1[] = { OID_ANSI_X9_42_SCHEME, 8 }, - OID_ANSI_MQV2[] = { OID_ANSI_X9_42_SCHEME, 7 }, - - OID_ANSI_DH_STATIC_SHA1[] = { OID_ANSI_X9_42_NAMED_SCHEME, 1 }, - OID_ANSI_DH_EPHEM_SHA1[] = { OID_ANSI_X9_42_NAMED_SCHEME, 2 }, - OID_ANSI_DH_ONE_FLOW_SHA1[] = { OID_ANSI_X9_42_NAMED_SCHEME, 3 }, - OID_ANSI_DH_HYBRID1_SHA1[] = { OID_ANSI_X9_42_NAMED_SCHEME, 4 }, - OID_ANSI_DH_HYBRID2_SHA1[] = { OID_ANSI_X9_42_NAMED_SCHEME, 5 }, - OID_ANSI_DH_HYBRID_ONEFLOW_SHA1[] = { OID_ANSI_X9_42_NAMED_SCHEME, 6 }, - /* sic - enumerated in reverse order in the spec */ - OID_ANSI_MQV1_SHA1[] = { OID_ANSI_X9_42_NAMED_SCHEME, 8 }, - OID_ANSI_MQV2_SHA1[] = { OID_ANSI_X9_42_NAMED_SCHEME, 7 }; - -const SecAsn1Oid - CSSMOID_MD2 = {OID_RSA_HASH_LENGTH+1, (uint8_t *)OID_MD2}, - CSSMOID_MD4 = {OID_RSA_HASH_LENGTH+1, (uint8_t *)OID_MD4}, - CSSMOID_MD5 = {OID_RSA_HASH_LENGTH+1, (uint8_t *)OID_MD5}, - CSSMOID_RSA = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_RSAEncryption}, - CSSMOID_MD2WithRSA = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_MD2WithRSA}, - CSSMOID_MD4WithRSA = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_MD4WithRSA}, - CSSMOID_MD5WithRSA = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_MD5WithRSA}, - CSSMOID_SHA1WithRSA = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_SHA1WithRSA}, - CSSMOID_RSAWithOAEP = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_RSAWithOAEP}, - CSSMOID_OAEP_MGF1 = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_OAEP_MGF1}, - CSSMOID_OAEP_ID_PSPECIFIED = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_OAEP_ID_PSPECIFIED}, - CSSMOID_SHA224WithRSA = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_SHA224WithRSA}, - CSSMOID_SHA256WithRSA = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_SHA256WithRSA}, - CSSMOID_SHA384WithRSA = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_SHA384WithRSA}, - CSSMOID_SHA512WithRSA = {OID_PKCS_1_LENGTH+1, (uint8_t *)OID_SHA512WithRSA}, - CSSMOID_PKCS3 = {OID_PKCS_3_LENGTH, (uint8_t *)OID_PKCS_3_ARC}, - CSSMOID_DH = {OID_PKCS_3_LENGTH+1, (uint8_t *)OID_DHKeyAgreement}, - CSSMOID_DSA = {OID_OIW_ALGORITHM_LENGTH+1, (uint8_t *)OID_OIW_DSA}, - CSSMOID_DSA_CMS = { 7, (uint8_t *)OID_CMS_DSA}, - CSSMOID_DSA_JDK = { 5, (uint8_t *)OID_JDK_DSA}, - CSSMOID_SHA1WithDSA = {OID_OIW_ALGORITHM_LENGTH+1, (uint8_t *)OID_OIW_DSAWithSHA1}, - CSSMOID_SHA1WithDSA_CMS = { 7, (uint8_t *)OID_CMS_DSAWithSHA1}, - CSSMOID_SHA1WithDSA_JDK = { 5, (uint8_t *)OID_JDK_DSAWithSHA1}, - CSSMOID_SHA1 = {OID_OIW_ALGORITHM_LENGTH+1, (uint8_t *)OID_OIW_SHA1}, - CSSMOID_SHA224 = {OID_NIST_HASHALG_LENGTH+1, (uint8_t *)OID_SHA224}, - CSSMOID_SHA256 = {OID_NIST_HASHALG_LENGTH+1, (uint8_t *)OID_SHA256}, - CSSMOID_SHA384 = {OID_NIST_HASHALG_LENGTH+1, (uint8_t *)OID_SHA384}, - CSSMOID_SHA512 = {OID_NIST_HASHALG_LENGTH+1, (uint8_t *)OID_SHA512}, - CSSMOID_SHA1WithRSA_OIW = {OID_OIW_ALGORITHM_LENGTH+1, (uint8_t *)OID_OIW_RSAWithSHA1}, - CSSMOID_DES_CBC = {OID_OIW_ALGORITHM_LENGTH+1, (uint8_t *)OID_OIW_DES_CBC}, - CSSMOID_ANSI_DH_PUB_NUMBER = {OID_ANSI_X9_42_LEN + 1, (uint8_t *)OID_ANSI_DH_PUB_NUMBER}, - CSSMOID_ANSI_DH_STATIC = {OID_ANSI_X9_42_SCHEME_LEN + 1, (uint8_t *)OID_ANSI_DH_STATIC}, - CSSMOID_ANSI_DH_ONE_FLOW = {OID_ANSI_X9_42_SCHEME_LEN + 1, (uint8_t *)OID_ANSI_DH_ONE_FLOW}, - CSSMOID_ANSI_DH_EPHEM = {OID_ANSI_X9_42_SCHEME_LEN + 1, (uint8_t *)OID_ANSI_DH_EPHEM}, - CSSMOID_ANSI_DH_HYBRID1 = {OID_ANSI_X9_42_SCHEME_LEN + 1, (uint8_t *)OID_ANSI_DH_HYBRID1}, - CSSMOID_ANSI_DH_HYBRID2 = {OID_ANSI_X9_42_SCHEME_LEN + 1, (uint8_t *)OID_ANSI_DH_HYBRID2}, - CSSMOID_ANSI_DH_HYBRID_ONEFLOW = {OID_ANSI_X9_42_SCHEME_LEN + 1, - (uint8_t *)OID_ANSI_DH_HYBRID_ONEFLOW}, - CSSMOID_ANSI_MQV1 = {OID_ANSI_X9_42_SCHEME_LEN + 1, (uint8_t *)OID_ANSI_MQV1}, - CSSMOID_ANSI_MQV2 = {OID_ANSI_X9_42_SCHEME_LEN + 1, (uint8_t *)OID_ANSI_MQV2}, - CSSMOID_ANSI_DH_STATIC_SHA1 = {OID_ANSI_X9_42_NAMED_SCHEME_LEN + 1, - (uint8_t *)OID_ANSI_DH_STATIC_SHA1}, - CSSMOID_ANSI_DH_ONE_FLOW_SHA1 = {OID_ANSI_X9_42_NAMED_SCHEME_LEN + 1, - (uint8_t *)OID_ANSI_DH_ONE_FLOW_SHA1}, - CSSMOID_ANSI_DH_EPHEM_SHA1 = {OID_ANSI_X9_42_NAMED_SCHEME_LEN + 1, - (uint8_t *)OID_ANSI_DH_EPHEM_SHA1}, - CSSMOID_ANSI_DH_HYBRID1_SHA1 = {OID_ANSI_X9_42_NAMED_SCHEME_LEN + 1, - (uint8_t *)OID_ANSI_DH_HYBRID1_SHA1}, - CSSMOID_ANSI_DH_HYBRID2_SHA1 = {OID_ANSI_X9_42_NAMED_SCHEME_LEN + 1, - (uint8_t *)OID_ANSI_DH_HYBRID2_SHA1}, - CSSMOID_ANSI_DH_HYBRID_ONEFLOW_SHA1 = {OID_ANSI_X9_42_NAMED_SCHEME_LEN + 1, - (uint8_t *)OID_ANSI_DH_HYBRID_ONEFLOW_SHA1}, - CSSMOID_ANSI_MQV1_SHA1 = {OID_ANSI_X9_42_NAMED_SCHEME_LEN + 1, - (uint8_t *)OID_ANSI_MQV1_SHA1}, - CSSMOID_ANSI_MQV2_SHA1 = {OID_ANSI_X9_42_NAMED_SCHEME_LEN + 1, - (uint8_t *)OID_ANSI_MQV2_SHA1}; - - -/* iSignTP OBJECT IDENTIFIER ::= - * { appleTrustPolicy 1 } - * { 1 2 840 113635 100 1 1 } - * - * BER = 06 09 2A 86 48 86 F7 63 64 01 01 - */ -static const uint8_t -APPLE_TP_ISIGN[] = {APPLE_TP_OID, 1}, - -/* AppleX509Basic OBJECT IDENTIFIER ::= - * { appleTrustPolicy 2 } - * { 1 2 840 113635 100 1 2 } - * - * BER = 06 09 2A 86 48 86 F7 63 64 01 01 - */ -APPLE_TP_X509_BASIC[] = {APPLE_TP_OID, 2}, - -/* AppleSSLPolicy := {appleTrustPolicy 3 } */ -APPLE_TP_SSL[] = {APPLE_TP_OID, 3}, - -/* AppleLocalCertGenPolicy := {appleTrustPolicy 4 } */ -APPLE_TP_LOCAL_CERT_GEN[] = {APPLE_TP_OID, 4}, - -/* AppleCSRGenPolicy := {appleTrustPolicy 5 } */ -APPLE_TP_CSR_GEN[] = {APPLE_TP_OID, 5}, - -/* Apple CRL-based revocation policy := {appleTrustPolicy 6 } */ -APPLE_TP_REVOCATION_CRL[] = {APPLE_TP_OID, 6}, - -/* Apple OCSP-based revocation policy := {appleTrustPolicy 7 } */ -APPLE_TP_REVOCATION_OCSP[] = {APPLE_TP_OID, 7}, - -/* Apple S/MIME trust policy := {appleTrustPolicy 8 } */ -APPLE_TP_SMIME[] = {APPLE_TP_OID, 8}, - -/* Apple EAP trust policy := {appleTrustPolicy 9 } */ -APPLE_TP_EAP[] = {APPLE_TP_OID, 9}, - -/* - * NOTE: "Apple Code Signing Policy", CSSMOID_APPLE_TP_CODE_SIGN, was renamed - * to "Apple Software Update Signing Policy", CSSMOID_APPLE_TP_SW_UPDATE_SIGNING, - * on 8/16/06. For compatibility, we keep the TP_CODE_SIGN OID here until - * SoftwareUpdate converts to the new symbol. - * - * Apple Code Signing Policy := { appleTrustPolicy 10 } - * Apple Software Update Signing Policy := { appleTrustPolicy 10 } - */ -APPLE_SW_UPDATE_SIGNING[] = {APPLE_TP_OID, 10}, -#define APPLE_TP_CODE_SIGN APPLE_SW_UPDATE_SIGNING - -/* Apple IPSec Policy := { appleTrustPolicy 11 } */ -APPLE_TP_IP_SEC[] = {APPLE_TP_OID, 11}, - -/* Apple iChat Policy := { appleTrustPolicy 12 } */ -APPLE_TP_ICHAT[] = {APPLE_TP_OID, 12}, - -/* Apple Resource Signing Policy := { appleTrustPolicy 13 } */ -APPLE_TP_RESOURCE_SIGN[] = {APPLE_TP_OID, 13}, - -/* Apple PKINIT Client Cert Policy := { appleTrustPolicy 14 } */ -APPLE_TP_PKINIT_CLIENT[] = {APPLE_TP_OID, 14}, - -/* Apple PKINIT Server Cert Policy := { appleTrustPolicy 15 } */ -APPLE_TP_PKINIT_SERVER[] = {APPLE_TP_OID, 15}, - -/* Apple Code Signing Cert Policy := { appleTrustPolicy 16 } */ -APPLE_TP_CODE_SIGNING[] = {APPLE_TP_OID, 16}, - -/* Apple Package Signing Cert Policy := { appleTrustPolicy 17 } */ -APPLE_TP_PACKAGE_SIGNING[] = {APPLE_TP_OID, 17}, - -/* AppleID Sharing Cert Policy := { appleTrustPolicy 18 } */ -APPLE_TP_APPLEID_SHARING[] = {APPLE_TP_OID, 18}, -/* appleIDValidationPolicy */ - -/* Apple MacAppStore receipt verification policy := { appleTrustPolicy 19 } */ -APPLE_TP_MACAPPSTORE_RECEIPT[] = {APPLE_TP_OID, 19}, - -/* Apple Time Stamping Server Cert Policy := { appleTrustPolicy 20 } */ -APPLE_TP_TIMESTAMPING[] = {APPLE_TP_OID, 20}, - -/* Apple Revocation Policy := { appleTrustPolicy 21 } */ -APPLE_TP_REVOCATION[] = {APPLE_TP_OID, 21}, - -/* Apple Passbook Signing Policy := { appleTrustPolicy 22 } */ -APPLE_TP_PASSBOOK_SIGNING[] = {APPLE_TP_OID, 22}, - -/* Apple Mobile Store Policy := { appleTrustPolicy 23 } */ -APPLE_TP_MOBILE_STORE[] = {APPLE_TP_OID, 23}, - -/* Apple Escrow Service Policy := { appleTrustPolicy 24 } */ -APPLE_TP_ESCROW_SERVICE[] = {APPLE_TP_OID, 24}, - -/* Apple Configuration Profile Signing Policy := { appleTrustPolicy 25 } */ -APPLE_TP_PROFILE_SIGNING[] = {APPLE_TP_OID, 25}, - -/* Apple QA Configuration Profile Signing Policy := { appleTrustPolicy 26 } */ -APPLE_TP_QA_PROFILE_SIGNING[] = {APPLE_TP_OID, 26}, - -/* Apple Test Mobile Store Policy := { appleTrustPolicy 27 } */ -APPLE_TP_TEST_MOBILE_STORE[] = {APPLE_TP_OID, 27}, - -/* - * fee OBJECT IDENTIFIER ::= - * { appleSecurityAlgorithm 1 } - * { 1 2 840 113635 100 2 1 } - * - * BER = 06 09 2A 86 48 86 F7 63 64 02 01 - */ -APPLE_FEE[] = {APPLE_ALG_OID, 1}, - -/* - * asc OBJECT IDENTIFIER ::= - * { appleSecurityAlgorithm 2 } - * { 1 2 840 113635 100 2 2 } - * - * BER = 06 09 2A 86 48 86 F7 63 64 02 02 - */ -APPLE_ASC[] = {APPLE_ALG_OID, 2}, - -/* - * fee_MD5 OBJECT IDENTIFIER ::= - * { appleSecurityAlgorithm 3 } - * { 1 2 840 113635 100 2 3 } - * - * BER = 06 09 2A 86 48 86 F7 63 64 02 03 - */ -APPLE_FEE_MD5[] = {APPLE_ALG_OID, 3}, - -/* - * fee_SHA1 OBJECT IDENTIFIER ::= - * { appleSecurityAlgorithm 4 } - * { 1 2 840 113635 100 2 4 } - * - * BER = 06 09 2A 86 48 86 F7 63 64 02 04 - */ -APPLE_FEE_SHA1[] = {APPLE_ALG_OID, 4}, - -/* - * feed OBJECT IDENTIFIER ::= - * { appleSecurityAlgorithm 5 } - * { 1 2 840 113635 100 2 5 } - * - * BER = 06 09 2A 86 48 86 F7 63 64 02 05 - */ -APPLE_FEED[] = {APPLE_ALG_OID, 5}, - -/* - * feedExp OBJECT IDENTIFIER ::= - * { appleSecurityAlgorithm 6 } - * { 1 2 840 113635 100 2 6 } - * - * BER = 06 09 2A 86 48 86 F7 63 64 02 06 - */ -APPLE_FEEDEXP[] = {APPLE_ALG_OID, 6}, - -/* - * AppleECDSA OBJECT IDENTIFIER ::= - * { appleSecurityAlgorithm 7 } - * { 1 2 840 113635 100 2 7 } - * - * BER = 06 09 2A 86 48 86 F7 63 64 02 07 - */ -APPLE_ECDSA[] = {APPLE_ALG_OID, 7}, - -/* .mac cert OIDs */ -OID_DOTMAC_CERT[] = { APPLE_DOTMAC_CERT_OID }, -OID_DOTMAC_CERT_REQ[] = { APPLE_DOTMAC_CERT_REQ_OID }, -OID_DOTMAC_CERT_REQ_IDENTITY[] = { APPLE_DOTMAC_CERT_REQ_OID, 1 }, /* deprecated */ -OID_DOTMAC_CERT_REQ_EMAIL_SIGN[] = { APPLE_DOTMAC_CERT_REQ_OID, 2 }, /* deprecated */ -OID_DOTMAC_CERT_REQ_EMAIL_ENCRYPT[] = { APPLE_DOTMAC_CERT_REQ_OID, 3 }, /* deprecated */ -OID_DOTMAC_CERT_REQ_ARCHIVE_LIST[] = { APPLE_DOTMAC_CERT_REQ_OID, 4 }, -OID_DOTMAC_CERT_REQ_ARCHIVE_STORE[] = { APPLE_DOTMAC_CERT_REQ_OID, 5 }, -OID_DOTMAC_CERT_REQ_ARCHIVE_FETCH[] = { APPLE_DOTMAC_CERT_REQ_OID, 6 }, -OID_DOTMAC_CERT_REQ_ARCHIVE_REMOVE[] = { APPLE_DOTMAC_CERT_REQ_OID, 7 }, -OID_DOTMAC_CERT_REQ_SHARED_SERVICES[] = { APPLE_DOTMAC_CERT_REQ_OID, 8 }, /* treadstone - Shared Services */ - -/* OIDs for specifying OID/values pairs in a cert request */ -OID_DOTMAC_CERT_REQ_VALUE_USERNAME[] = { APPLE_DOTMAC_CERT_REQ_VALUE_OID, 1 }, -OID_DOTMAC_CERT_REQ_VALUE_PASSWORD[] = { APPLE_DOTMAC_CERT_REQ_VALUE_OID, 2 }, -OID_DOTMAC_CERT_REQ_VALUE_HOSTNAME[] = { APPLE_DOTMAC_CERT_REQ_VALUE_OID, 3 }, -OID_DOTMAC_CERT_REQ_VALUE_RENEW[] = { APPLE_DOTMAC_CERT_REQ_VALUE_OID, 4 }, -OID_DOTMAC_CERT_REQ_VALUE_ASYNC[] = { APPLE_DOTMAC_CERT_REQ_VALUE_OID, 5 }, -OID_DOTMAC_CERT_REQ_VALUE_IS_PENDING[] = { APPLE_DOTMAC_CERT_REQ_VALUE_OID, 6 }, -OID_DOTMAC_CERT_REQ_VALUE_TYPE_ICHAT[] = { APPLE_DOTMAC_CERT_REQ_VALUE_OID, 7 }, -OID_DOTMAC_CERT_REQ_VALUE_TYPE_SHARED_SERVICE[] = { APPLE_DOTMAC_CERT_REQ_VALUE_OID, 8 }, -OID_DOTMAC_CERT_REQ_VALUE_TYPE_EMAIL_ENCRYPT[] = { APPLE_DOTMAC_CERT_REQ_VALUE_OID, 9 }, -OID_DOTMAC_CERT_REQ_VALUE_TYPE_EMAIL_SIGN[] = { APPLE_DOTMAC_CERT_REQ_VALUE_OID, 10 } -; - -const SecAsn1Oid - -CSSMOID_APPLE_ISIGN = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_ISIGN}, -CSSMOID_APPLE_X509_BASIC = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_X509_BASIC}, -CSSMOID_APPLE_TP_SSL = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_SSL}, -CSSMOID_APPLE_TP_LOCAL_CERT_GEN = - {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_LOCAL_CERT_GEN}, -CSSMOID_APPLE_TP_CSR_GEN = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_CSR_GEN}, -CSSMOID_APPLE_TP_REVOCATION_CRL = - {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_REVOCATION_CRL}, -CSSMOID_APPLE_TP_REVOCATION_OCSP = - {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_REVOCATION_OCSP}, -CSSMOID_APPLE_TP_SMIME = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_SMIME}, -CSSMOID_APPLE_TP_EAP = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_EAP}, -/* CSSMOID_APPLE_TP_CODE_SIGN here for temporary compatibility */ -CSSMOID_APPLE_TP_CODE_SIGN = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_CODE_SIGN}, -CSSMOID_APPLE_TP_SW_UPDATE_SIGNING = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_SW_UPDATE_SIGNING}, -CSSMOID_APPLE_TP_IP_SEC = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_IP_SEC}, -CSSMOID_APPLE_TP_ICHAT = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_ICHAT}, -CSSMOID_APPLE_TP_RESOURCE_SIGN = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_RESOURCE_SIGN}, -CSSMOID_APPLE_TP_PKINIT_CLIENT = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_PKINIT_CLIENT}, -CSSMOID_APPLE_TP_PKINIT_SERVER = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_PKINIT_SERVER}, -CSSMOID_APPLE_TP_CODE_SIGNING = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_CODE_SIGNING}, -CSSMOID_APPLE_TP_PACKAGE_SIGNING = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_PACKAGE_SIGNING}, -CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_MACAPPSTORE_RECEIPT}, -CSSMOID_APPLE_TP_APPLEID_SHARING = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_APPLEID_SHARING}, -CSSMOID_APPLE_TP_TIMESTAMPING = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_TIMESTAMPING}, -CSSMOID_APPLE_TP_REVOCATION = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_REVOCATION}, -CSSMOID_APPLE_TP_PASSBOOK_SIGNING = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_PASSBOOK_SIGNING}, -CSSMOID_APPLE_TP_MOBILE_STORE = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_MOBILE_STORE}, -CSSMOID_APPLE_TP_ESCROW_SERVICE = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_ESCROW_SERVICE}, -CSSMOID_APPLE_TP_PROFILE_SIGNING = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_PROFILE_SIGNING}, -CSSMOID_APPLE_TP_QA_PROFILE_SIGNING = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_QA_PROFILE_SIGNING}, -CSSMOID_APPLE_TP_TEST_MOBILE_STORE = {APPLE_TP_OID_LENGTH+1, (uint8_t *)APPLE_TP_TEST_MOBILE_STORE}, -CSSMOID_APPLE_FEE = {APPLE_ALG_OID_LENGTH+1, (uint8_t *)APPLE_FEE}, -CSSMOID_APPLE_ASC = {APPLE_ALG_OID_LENGTH+1, (uint8_t *)APPLE_ASC}, -CSSMOID_APPLE_FEE_MD5 = {APPLE_ALG_OID_LENGTH+1, (uint8_t *)APPLE_FEE_MD5}, -CSSMOID_APPLE_FEE_SHA1 = {APPLE_ALG_OID_LENGTH+1, (uint8_t *)APPLE_FEE_SHA1}, -CSSMOID_APPLE_FEED = {APPLE_ALG_OID_LENGTH+1, (uint8_t *)APPLE_FEED}, -CSSMOID_APPLE_FEEDEXP = {APPLE_ALG_OID_LENGTH+1, (uint8_t *)APPLE_FEEDEXP}, -CSSMOID_APPLE_ECDSA = {APPLE_ALG_OID_LENGTH+1, (uint8_t *)APPLE_ECDSA}, -/* .mac cert OIDs */ -CSSMOID_DOTMAC_CERT = { APPLE_DOTMAC_CERT_OID_LENGTH, - (uint8_t *)OID_DOTMAC_CERT }, -CSSMOID_DOTMAC_CERT_REQ = { APPLE_DOTMAC_CERT_REQ_OID_LENGTH, - (uint8_t *)OID_DOTMAC_CERT_REQ }, -/* This actually used to be for requesting an encrypted iChat cert; deprecated in Leopard */ -CSSMOID_DOTMAC_CERT_REQ_IDENTITY = { APPLE_DOTMAC_CERT_REQ_OID_LENGTH + 1, - (uint8_t *)OID_DOTMAC_CERT_REQ_IDENTITY}, -CSSMOID_DOTMAC_CERT_REQ_EMAIL_SIGN = { APPLE_DOTMAC_CERT_REQ_OID_LENGTH + 1, - (uint8_t *)OID_DOTMAC_CERT_REQ_EMAIL_SIGN}, -CSSMOID_DOTMAC_CERT_REQ_EMAIL_ENCRYPT = { APPLE_DOTMAC_CERT_REQ_OID_LENGTH + 1, - (uint8_t *)OID_DOTMAC_CERT_REQ_EMAIL_ENCRYPT}, -CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_LIST = { APPLE_DOTMAC_CERT_REQ_OID_LENGTH + 1, - (uint8_t *)OID_DOTMAC_CERT_REQ_ARCHIVE_LIST}, -CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_STORE = { APPLE_DOTMAC_CERT_REQ_OID_LENGTH + 1, - (uint8_t *)OID_DOTMAC_CERT_REQ_ARCHIVE_STORE}, -CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_FETCH = { APPLE_DOTMAC_CERT_REQ_OID_LENGTH + 1, - (uint8_t *)OID_DOTMAC_CERT_REQ_ARCHIVE_FETCH}, -CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_REMOVE = { APPLE_DOTMAC_CERT_REQ_OID_LENGTH + 1, - (uint8_t *)OID_DOTMAC_CERT_REQ_ARCHIVE_REMOVE}, -CSSMOID_DOTMAC_CERT_REQ_SHARED_SERVICES = { APPLE_DOTMAC_CERT_REQ_OID_LENGTH + 1, - (uint8_t *)OID_DOTMAC_CERT_REQ_SHARED_SERVICES}, -CSSMOID_DOTMAC_CERT_REQ_VALUE_USERNAME = { APPLE_DOTMAC_CERT_REQ_VALUE_OID_LENGTH + 1, - (uint8_t *)OID_DOTMAC_CERT_REQ_VALUE_USERNAME}, -CSSMOID_DOTMAC_CERT_REQ_VALUE_PASSWORD = { APPLE_DOTMAC_CERT_REQ_VALUE_OID_LENGTH + 1, - (uint8_t *)OID_DOTMAC_CERT_REQ_VALUE_PASSWORD}, -CSSMOID_DOTMAC_CERT_REQ_VALUE_HOSTNAME = { APPLE_DOTMAC_CERT_REQ_VALUE_OID_LENGTH + 1, - (uint8_t *)OID_DOTMAC_CERT_REQ_VALUE_HOSTNAME}, -CSSMOID_DOTMAC_CERT_REQ_VALUE_RENEW = { APPLE_DOTMAC_CERT_REQ_VALUE_OID_LENGTH + 1, - (uint8_t *)OID_DOTMAC_CERT_REQ_VALUE_RENEW}, -CSSMOID_DOTMAC_CERT_REQ_VALUE_ASYNC = { APPLE_DOTMAC_CERT_REQ_VALUE_OID_LENGTH + 1, - (uint8_t *)OID_DOTMAC_CERT_REQ_VALUE_ASYNC}, -CSSMOID_DOTMAC_CERT_REQ_VALUE_IS_PENDING = { APPLE_DOTMAC_CERT_REQ_VALUE_OID_LENGTH + 1, - (uint8_t *)OID_DOTMAC_CERT_REQ_VALUE_IS_PENDING} -; - -/* PKCS5 algorithms */ - -static const uint8_t - OID_PKCS5_DIGEST_ALG[] = { OID_RSA_HASH }, - OID_PKCS5_ENCRYPT_ALG[] = { OID_RSA_ENCRYPT }, - OID_PKCS5_HMAC_SHA1[] = { OID_RSA_HASH, 7 }, - OID_PKCS5_pbeWithMD2AndDES[] = { OID_PKCS_5, 1 }, - OID_PKCS5_pbeWithMD5AndDES[] = { OID_PKCS_5, 3 }, - OID_PKCS5_pbeWithMD2AndRC2[] = { OID_PKCS_5, 4 }, - OID_PKCS5_pbeWithMD5AndRC2[] = { OID_PKCS_5, 6 }, - OID_PKCS5_pbeWithSHA1AndDES[] = { OID_PKCS_5, 10 }, - OID_PKCS5_pbeWithSHA1AndRC2[] = { OID_PKCS_5, 11 }, - OID_PKCS5_PBKDF2[] = { OID_PKCS_5, 12 }, - OID_PKCS5_PBES2[] = { OID_PKCS_5, 13 }, - OID_PKCS5_PBMAC1[] = { OID_PKCS_5, 14 }, - OID_PKCS5_RC2_CBC[] = { OID_RSA_ENCRYPT, 2 }, - OID_PKCS5_DES_EDE3_CBC[] = { OID_RSA_ENCRYPT, 7 }, - OID_PKCS5_RC5_CBC[] = { OID_RSA_ENCRYPT, 9 }; - -const SecAsn1Oid - CSSMOID_PKCS5_DIGEST_ALG = { OID_RSA_HASH_LENGTH, (uint8_t *)OID_PKCS5_DIGEST_ALG }, - CSSMOID_PKCS5_ENCRYPT_ALG = { OID_RSA_ENCRYPT_LENGTH, (uint8_t *)OID_PKCS5_ENCRYPT_ALG }, - CSSMOID_PKCS5_HMAC_SHA1 = { OID_RSA_HASH_LENGTH+1, (uint8_t *)OID_PKCS5_HMAC_SHA1 }, - CSSMOID_PKCS5_pbeWithMD2AndDES = { OID_PKCS_5_LENGTH+1, (uint8_t *)OID_PKCS5_pbeWithMD2AndDES }, - CSSMOID_PKCS5_pbeWithMD5AndDES = { OID_PKCS_5_LENGTH+1, (uint8_t *)OID_PKCS5_pbeWithMD5AndDES }, - CSSMOID_PKCS5_pbeWithMD2AndRC2 = { OID_PKCS_5_LENGTH+1, (uint8_t *)OID_PKCS5_pbeWithMD2AndRC2 }, - CSSMOID_PKCS5_pbeWithMD5AndRC2 = { OID_PKCS_5_LENGTH+1, (uint8_t *)OID_PKCS5_pbeWithMD5AndRC2 }, - CSSMOID_PKCS5_pbeWithSHA1AndDES = { OID_PKCS_5_LENGTH+1, (uint8_t *)OID_PKCS5_pbeWithSHA1AndDES }, - CSSMOID_PKCS5_pbeWithSHA1AndRC2 = { OID_PKCS_5_LENGTH+1, (uint8_t *)OID_PKCS5_pbeWithSHA1AndRC2 }, - CSSMOID_PKCS5_PBKDF2 = { OID_PKCS_5_LENGTH+1, (uint8_t *)OID_PKCS5_PBKDF2 }, - CSSMOID_PKCS5_PBES2 = { OID_PKCS_5_LENGTH+1, (uint8_t *)OID_PKCS5_PBES2 }, - CSSMOID_PKCS5_PBMAC1 = { OID_PKCS_5_LENGTH+1, (uint8_t *)OID_PKCS5_PBMAC1 }, - CSSMOID_PKCS5_RC2_CBC = { OID_RSA_ENCRYPT_LENGTH+1, (uint8_t *)OID_PKCS5_RC2_CBC }, - CSSMOID_PKCS5_DES_EDE3_CBC = { OID_RSA_ENCRYPT_LENGTH+1, (uint8_t *)OID_PKCS5_DES_EDE3_CBC }, - CSSMOID_PKCS5_RC5_CBC = { OID_RSA_ENCRYPT_LENGTH+1, (uint8_t *)OID_PKCS5_RC5_CBC }; - -/* PKCS12 algorithms */ -#define OID_PKCS12_PbeIds OID_PKCS_12,1 -#define OID_PKCS12_PbeIds_Length OID_PKCS_12_LENGTH+1 - -static const uint8_t - OID_PKCS12_pbeWithSHAAnd128BitRC4[] = { OID_PKCS12_PbeIds, 1 }, - OID_PKCS12_pbeWithSHAAnd40BitRC4[] = { OID_PKCS12_PbeIds, 2 }, - OID_PKCS12_pbeWithSHAAnd3Key3DESCBC[] = { OID_PKCS12_PbeIds, 3 }, - OID_PKCS12_pbeWithSHAAnd2Key3DESCBC[] = { OID_PKCS12_PbeIds, 4 }, - OID_PKCS12_pbeWithSHAAnd128BitRC2CBC[] ={ OID_PKCS12_PbeIds, 5 }, - OID_PKCS12_pbewithSHAAnd40BitRC2CBC[] = { OID_PKCS12_PbeIds, 6 }; - - -const SecAsn1Oid -CSSMOID_PKCS12_pbeWithSHAAnd128BitRC4 = {OID_PKCS12_PbeIds_Length + 1, - (uint8_t *)OID_PKCS12_pbeWithSHAAnd128BitRC4 }, -CSSMOID_PKCS12_pbeWithSHAAnd40BitRC4 = {OID_PKCS12_PbeIds_Length + 1, - (uint8_t *)OID_PKCS12_pbeWithSHAAnd40BitRC4 }, -CSSMOID_PKCS12_pbeWithSHAAnd3Key3DESCBC = {OID_PKCS12_PbeIds_Length + 1, - (uint8_t *)OID_PKCS12_pbeWithSHAAnd3Key3DESCBC }, -CSSMOID_PKCS12_pbeWithSHAAnd2Key3DESCBC = {OID_PKCS12_PbeIds_Length + 1, - (uint8_t *)OID_PKCS12_pbeWithSHAAnd2Key3DESCBC }, -CSSMOID_PKCS12_pbeWithSHAAnd128BitRC2CBC = {OID_PKCS12_PbeIds_Length + 1, - (uint8_t *)OID_PKCS12_pbeWithSHAAnd128BitRC2CBC }, -CSSMOID_PKCS12_pbewithSHAAnd40BitRC2CBC = {OID_PKCS12_PbeIds_Length + 1, - (uint8_t *)OID_PKCS12_pbewithSHAAnd40BitRC2CBC }; - -/* ANSI X9.62 and Certicom elliptic curve algorithms */ -static const uint8_t - OID_ecPublicKey[] = { OID_ANSI_X9_62_PUBKEY_TYPE, 1 }, - OID_ECDSA_WithSHA1[] = { OID_ANSI_X9_62_SIG_TYPE, 1 }, - OID_ECDSA_WithSHA224[] = { OID_ANSI_X9_62_SIG_TYPE, 3, 1 }, - OID_ECDSA_WithSHA256[] = { OID_ANSI_X9_62_SIG_TYPE, 3, 2 }, - OID_ECDSA_WithSHA384[] = { OID_ANSI_X9_62_SIG_TYPE, 3, 3 }, - OID_ECDSA_WithSHA512[] = { OID_ANSI_X9_62_SIG_TYPE, 3, 4 }, - OID_ECDSA_WithSpecified[] = { OID_ANSI_X9_62_SIG_TYPE, 3 }; - -const SecAsn1Oid -CSSMOID_ecPublicKey = {OID_ANSI_X9_62_LEN+2, (uint8_t *)OID_ecPublicKey}, -CSSMOID_ECDSA_WithSHA1 = {OID_ANSI_X9_62_SIG_TYPE_LEN+1, (uint8_t *)OID_ECDSA_WithSHA1 }, -CSSMOID_ECDSA_WithSHA224 = {OID_ANSI_X9_62_SIG_TYPE_LEN+2, (uint8_t *)OID_ECDSA_WithSHA224 }, -CSSMOID_ECDSA_WithSHA256 = {OID_ANSI_X9_62_SIG_TYPE_LEN+2, (uint8_t *)OID_ECDSA_WithSHA256 }, -CSSMOID_ECDSA_WithSHA384 = {OID_ANSI_X9_62_SIG_TYPE_LEN+2, (uint8_t *)OID_ECDSA_WithSHA384 }, -CSSMOID_ECDSA_WithSHA512 = {OID_ANSI_X9_62_SIG_TYPE_LEN+2, (uint8_t *)OID_ECDSA_WithSHA512 }, -CSSMOID_ECDSA_WithSpecified = {OID_ANSI_X9_62_SIG_TYPE_LEN+1, (uint8_t *)OID_ECDSA_WithSpecified }; diff --git a/libsecurity_asn1/lib/oidsbase.h b/libsecurity_asn1/lib/oidsbase.h deleted file mode 100644 index 1dbaa516..00000000 --- a/libsecurity_asn1/lib/oidsbase.h +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Copyright (c) 1999-2001,2003-2004,2008-2010 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@ - * - * oidsbase.h -- Basic Object Identifier Macros and Data Types. - */ - -#include "SecAsn1Types.h" - -#ifndef _OIDSBASE_H_ -#define _OIDSBASE_H_ 1 - -#ifdef __cplusplus -extern "C" { -#endif - -#define SECASN1OID_DEF(NAME, VALUE, ARGS...) \ -static const uint8_t _##NAME[] = { VALUE, ## ARGS }; \ -const SecAsn1Oid NAME = { sizeof(_##NAME), (uint8_t *)_##NAME } - -/* Intel CSSM */ - -#define INTEL 96, 134, 72, 1, 134, 248, 77 -#define INTEL_LENGTH 7 - -#define INTEL_CDSASECURITY INTEL, 2 -#define INTEL_CDSASECURITY_LENGTH (INTEL_LENGTH + 1) - -#define INTEL_SEC_FORMATS INTEL_CDSASECURITY, 1 -#define INTEL_SEC_FORMATS_LENGTH (INTEL_CDSASECURITY_LENGTH + 1) - -#define INTEL_SEC_ALGS INTEL_CDSASECURITY, 2, 5 -#define INTEL_SEC_ALGS_LENGTH (INTEL_CDSASECURITY_LENGTH + 2) - -#define INTEL_SEC_OBJECT_BUNDLE INTEL_SEC_FORMATS, 4 -#define INTEL_SEC_OBJECT_BUNDLE_LENGTH (INTEL_SEC_FORMATS_LENGTH + 1) - -#define INTEL_CERT_AND_PRIVATE_KEY_2_0 INTEL_SEC_OBJECT_BUNDLE, 1 -#define INTEL_CERT_AND_PRIVATE_KEY_2_0_LENGTH (INTEL_SEC_OBJECT_BUNDLE_LENGTH + 1) - -/* Suffix specifying format or representation of a field value */ -/* Note that if a format suffix is not specified, a flat data -representation is implied */ -#define INTEL_X509_C_DATATYPE 1 -#define INTEL_X509_LDAPSTRING_DATATYPE 2 - -#define OID_ISO_CCITT_DIR_SERVICE 85 -#define OID_DS OID_ISO_CCITT_DIR_SERVICE -#define OID_DS_LENGTH 1 -#define OID_ATTR_TYPE OID_DS, 4 -#define OID_ATTR_TYPE_LENGTH OID_DS_LENGTH + 1 -#define OID_EXTENSION OID_DS, 29 -#define OID_EXTENSION_LENGTH OID_DS_LENGTH + 1 -#define OID_ISO_STANDARD 40 -#define OID_ISO_MEMBER 42 -#define OID_US OID_ISO_MEMBER, 134, 72 - -#define OID_ISO_IDENTIFIED_ORG 43 -#define OID_OSINET OID_ISO_IDENTIFIED_ORG, 4 -#define OID_GOSIP OID_ISO_IDENTIFIED_ORG, 5 -#define OID_DOD OID_ISO_IDENTIFIED_ORG, 6 -#define OID_OIW OID_ISO_IDENTIFIED_ORG, 14 - -#define OID_ITU_RFCDATA_MEMBER_LENGTH 1 -#define OID_ITU_RFCDATA 9 - -/* From the PKCS Standards */ -#define OID_ISO_MEMBER_LENGTH 1 -#define OID_US_LENGTH OID_ISO_MEMBER_LENGTH + 2 -#define OID_RSA OID_US, 134, 247, 13 -#define OID_RSA_LENGTH OID_US_LENGTH + 3 -#define OID_RSA_HASH OID_RSA, 2 -#define OID_RSA_HASH_LENGTH OID_RSA_LENGTH + 1 -#define OID_RSA_ENCRYPT OID_RSA, 3 -#define OID_RSA_ENCRYPT_LENGTH OID_RSA_LENGTH + 1 -#define OID_PKCS OID_RSA, 1 -#define OID_PKCS_LENGTH OID_RSA_LENGTH +1 -#define OID_PKCS_1 OID_PKCS, 1 -#define OID_PKCS_1_LENGTH OID_PKCS_LENGTH +1 -#define OID_PKCS_2 OID_PKCS, 2 -#define OID_PKCS_3 OID_PKCS, 3 -#define OID_PKCS_3_LENGTH OID_PKCS_LENGTH +1 -#define OID_PKCS_4 OID_PKCS, 4 -#define OID_PKCS_5 OID_PKCS, 5 -#define OID_PKCS_5_LENGTH OID_PKCS_LENGTH +1 -#define OID_PKCS_6 OID_PKCS, 6 -#define OID_PKCS_7 OID_PKCS, 7 -#define OID_PKCS_7_LENGTH OID_PKCS_LENGTH +1 -#define OID_PKCS_8 OID_PKCS, 8 -#define OID_PKCS_9 OID_PKCS, 9 -#define OID_PKCS_9_LENGTH OID_PKCS_LENGTH +1 -#define OID_PKCS_10 OID_PKCS, 10 -#define OID_PKCS_11 OID_PKCS, 11 -#define OID_PKCS_11_LENGTH OID_PKCS_LENGTH +1 -#define OID_PKCS_12 OID_PKCS, 12 -#define OID_PKCS_12_LENGTH OID_PKCS_LENGTH +1 - -/* ANSI X9.42 */ -#define OID_ANSI_X9_42 OID_US, 206, 62, 2 -#define OID_ANSI_X9_42_LEN OID_US_LENGTH + 3 -#define OID_ANSI_X9_42_SCHEME OID_ANSI_X9_42, 3 -#define OID_ANSI_X9_42_SCHEME_LEN OID_ANSI_X9_42_LEN + 1 -#define OID_ANSI_X9_42_NAMED_SCHEME OID_ANSI_X9_42, 4 -#define OID_ANSI_X9_42_NAMED_SCHEME_LEN OID_ANSI_X9_42_LEN + 1 - -/* ANSI X9.62 (1 2 840 10045) */ -#define OID_ANSI_X9_62 0x2A, 0x86, 0x48, 0xCE, 0x3D -#define OID_ANSI_X9_62_LEN 5 -#define OID_ANSI_X9_62_FIELD_TYPE OID_ANSI_X9_62, 1 -#define OID_ANSI_X9_62_PUBKEY_TYPE OID_ANSI_X9_62, 2 -#define OID_ANSI_X9_62_ELL_CURVE OID_ANSI_X9_62, 3 -#define OID_ANSI_X9_62_ELL_CURVE_LEN OID_ANSI_X9_62_LEN+1 -#define OID_ANSI_X9_62_C_TWO_CURVE OID_ANSI_X9_62_ELL_CURVE, 0 -#define OID_ANSI_X9_62_PRIME_CURVE OID_ANSI_X9_62_ELL_CURVE, 1 -#define OID_ANSI_X9_62_SIG_TYPE OID_ANSI_X9_62, 4 -#define OID_ANSI_X9_62_SIG_TYPE_LEN OID_ANSI_X9_62_LEN+1 - -/* PKIX */ -#define OID_PKIX OID_DOD, 1, 5, 5, 7 -#define OID_PKIX_LENGTH 6 -#define OID_PE OID_PKIX, 1 -#define OID_PE_LENGTH OID_PKIX_LENGTH + 1 -#define OID_QT OID_PKIX, 2 -#define OID_QT_LENGTH OID_PKIX_LENGTH + 1 -#define OID_KP OID_PKIX, 3 -#define OID_KP_LENGTH OID_PKIX_LENGTH + 1 -#define OID_OTHER_NAME OID_PKIX, 8 -#define OID_OTHER_NAME_LENGTH OID_PKIX_LENGTH + 1 -#define OID_PDA OID_PKIX, 9 -#define OID_PDA_LENGTH OID_PKIX_LENGTH + 1 -#define OID_QCS OID_PKIX, 11 -#define OID_QCS_LENGTH OID_PKIX_LENGTH + 1 -#define OID_AD OID_PKIX, 48 -#define OID_AD_LENGTH OID_PKIX_LENGTH + 1 -#define OID_AD_OCSP OID_AD, 1 -#define OID_AD_OCSP_LENGTH OID_AD_LENGTH + 1 - -/* ETSI */ -#define OID_ETSI 0x04, 0x00 -#define OID_ETSI_LENGTH 2 -#define OID_ETSI_QCS 0x04, 0x00, 0x8E, 0x46, 0x01 -#define OID_ETSI_QCS_LENGTH 5 - -#define OID_OIW_SECSIG OID_OIW, 3 -#define OID_OIW_LENGTH 2 -#define OID_OIW_SECSIG_LENGTH OID_OIW_LENGTH +1 - -#define OID_OIW_ALGORITHM OID_OIW_SECSIG, 2 -#define OID_OIW_ALGORITHM_LENGTH OID_OIW_SECSIG_LENGTH +1 - -/* NIST defined digest algorithm arc (2, 16, 840, 1, 101, 3, 4, 2) */ -#define OID_NIST_HASHALG 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02 -#define OID_NIST_HASHALG_LENGTH 8 - -/* Kerberos PKINIT */ -#define OID_KERBv5 0x2b, 6, 1, 5, 2 -#define OID_KERBv5_LEN 5 -#define OID_KERBv5_PKINIT OID_KERBv5, 3 -#define OID_KERBv5_PKINIT_LEN OID_KERBv5_LEN + 1 - -/* Certicom (1 3 132) */ -#define OID_CERTICOM 0x2B, 0x81, 0x04 -#define OID_CERTICOM_LEN 3 -#define OID_CERTICOM_ELL_CURVE OID_CERTICOM, 0 -#define OID_CERTICOM_ELL_CURVE_LEN OID_CERTICOM_LEN+1 - -/* - * Apple-specific OID bases - */ - -/* - * apple OBJECT IDENTIFIER ::= - * { iso(1) member-body(2) US(840) 113635 } - * - * BER = 06 06 2A 86 48 86 F7 63 - */ -#define APPLE_OID OID_US, 0x86, 0xf7, 0x63 -#define APPLE_OID_LENGTH OID_US_LENGTH + 3 - -/* appleDataSecurity OBJECT IDENTIFIER ::= - * { apple 100 } - * { 1 2 840 113635 100 } - * - * BER = 06 07 2A 86 48 86 F7 63 64 - */ -#define APPLE_ADS_OID APPLE_OID, 0x64 -#define APPLE_ADS_OID_LENGTH APPLE_OID_LENGTH + 1 - -/* - * appleTrustPolicy OBJECT IDENTIFIER ::= - * { appleDataSecurity 1 } - * { 1 2 840 113635 100 1 } - * - * BER = 06 08 2A 86 48 86 F7 63 64 01 - */ -#define APPLE_TP_OID APPLE_ADS_OID, 1 -#define APPLE_TP_OID_LENGTH APPLE_ADS_OID_LENGTH + 1 - -/* - * appleSecurityAlgorithm OBJECT IDENTIFIER ::= - * { appleDataSecurity 2 } - * { 1 2 840 113635 100 2 } - * - * BER = 06 08 2A 86 48 86 F7 63 64 02 - */ -#define APPLE_ALG_OID APPLE_ADS_OID, 2 -#define APPLE_ALG_OID_LENGTH APPLE_ADS_OID_LENGTH + 1 - -/* - * appleDotMacCertificate OBJECT IDENTIFIER ::= - * { appleDataSecurity 3 } - * { 1 2 840 113635 100 3 } - */ -#define APPLE_DOTMAC_CERT_OID APPLE_ADS_OID, 3 -#define APPLE_DOTMAC_CERT_OID_LENGTH APPLE_ADS_OID_LENGTH + 1 - -/* - * Basis of Policy OIDs for .mac TP requests - * - * dotMacCertificateRequest OBJECT IDENTIFIER ::= - * { appleDotMacCertificate 1 } - * { 1 2 840 113635 100 3 1 } - */ -#define APPLE_DOTMAC_CERT_REQ_OID APPLE_DOTMAC_CERT_OID, 1 -#define APPLE_DOTMAC_CERT_REQ_OID_LENGTH APPLE_DOTMAC_CERT_OID_LENGTH + 1 - -/* - * Basis of .mac Certificate Extensions - * - * dotMacCertificateExtension OBJECT IDENTIFIER ::= - * { appleDotMacCertificate 2 } - * { 1 2 840 113635 100 3 2 } - */ -#define APPLE_DOTMAC_CERT_EXTEN_OID APPLE_DOTMAC_CERT_OID, 2 -#define APPLE_DOTMAC_CERT_EXTEN_OID_LENGTH APPLE_DOTMAC_CERT_OID_LENGTH + 1 - -/* - * Basis of .mac Certificate request OID/value identifiers - * - * dotMacCertificateRequestValues OBJECT IDENTIFIER ::= - * { appleDotMacCertificate 3 } - * { 1 2 840 113635 100 3 3 } - */ -#define APPLE_DOTMAC_CERT_REQ_VALUE_OID APPLE_DOTMAC_CERT_OID, 3 -#define APPLE_DOTMAC_CERT_REQ_VALUE_OID_LENGTH APPLE_DOTMAC_CERT_OID_LENGTH + 1 - -/* - * Basis of Apple-specific extended key usages - * - * appleExtendedKeyUsage OBJECT IDENTIFIER ::= - * { appleDataSecurity 4 } - * { 1 2 840 113635 100 4 } - */ -#define APPLE_EKU_OID APPLE_ADS_OID, 4 -#define APPLE_EKU_OID_LENGTH APPLE_ADS_OID_LENGTH + 1 - -/* - * Basis of Apple Code Signing extended key usages - * appleCodeSigning OBJECT IDENTIFIER ::= - * { appleExtendedKeyUsage 1 } - * { 1 2 840 113635 100 4 1 } - */ -#define APPLE_EKU_CODE_SIGNING APPLE_EKU_OID, 1 -#define APPLE_EKU_CODE_SIGNING_LENGTH APPLE_EKU_OID_LENGTH + 1 - -/* - * Basis of Apple-specific Certificate Policy identifiers - * appleCertificatePolicies OBJECT IDENTIFIER ::= - * { appleDataSecurity 5 } - * { 1 2 840 113635 100 5 } - */ -#define APPLE_CERT_POLICIES APPLE_ADS_OID, 5 -#define APPLE_CERT_POLICIES_LENGTH APPLE_ADS_OID_LENGTH + 1 - -/* - * Basis of Apple-specific certificate extensions - * appleCertificateExtensions OBJECT IDENTIFIER ::= - * { appleDataSecurity 6 } - * { 1 2 840 113635 100 6 } - */ -#define APPLE_EXTENSION_OID APPLE_ADS_OID, 6 -#define APPLE_EXTENSION_OID_LENGTH APPLE_ADS_OID_LENGTH + 1 - -/* - * Basis of Apple-specific Code Signing certificate extensions - * appleCertificateExtensionCodeSigning OBJECT IDENTIFIER ::= - * { appleCertificateExtensions 1 } - * { 1 2 840 113635 100 6 1 } - */ -#define APPLE_EXTENSION_CODE_SIGNING APPLE_EXTENSION_OID, 1 -#define APPLE_EXTENSION_CODE_SIGNING_LENGTH APPLE_EXTENSION_OID_LENGTH + 1 - -/* - * Netscape OIDs. - */ -#define NETSCAPE_BASE_OID 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42 -#define NETSCAPE_BASE_OID_LEN 7 - -/* - * Netscape cert extension. - * - * netscape-cert-extension OBJECT IDENTIFIER ::= - * { 2 16 840 1 113730 1 } - * - * BER = 06 08 60 86 48 01 86 F8 42 01 - */ -#define NETSCAPE_CERT_EXTEN NETSCAPE_BASE_OID, 0x01 -#define NETSCAPE_CERT_EXTEN_LENGTH NETSCAPE_BASE_OID_LEN + 1 - -#define NETSCAPE_CERT_POLICY NETSCAPE_BASE_OID, 0x04 -#define NETSCAPE_CERT_POLICY_LENGTH NETSCAPE_BASE_OID_LEN + 1 - -/* - * Domain Component OID - */ -#define OID_ITU_RFCDATA_2342 OID_ITU_RFCDATA, 0x49, 0x86 -#define OID_ITU_RFCDATA_2342_LENGTH OID_ITU_RFCDATA_MEMBER_LENGTH + 2 - -#define OID_ITU_RFCDATA_2342_UCL OID_ITU_RFCDATA_2342, 0x49, 0x1F, 0x12, 0x8C -#define OID_ITU_RFCDATA_2342_UCL_LENGTH OID_ITU_RFCDATA_2342_LENGTH + 4 - -#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT OID_ITU_RFCDATA_2342_UCL, 0xE4 -#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_LENGTH OID_ITU_RFCDATA_2342_UCL_LENGTH + 1 - -#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT, 0x81 -#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_LENGTH OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_LENGTH + 1 - -#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_DOMAINCOMPONENT OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES, 0x99 -#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_DOMAINCOMPONENT_LENGTH OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_LENGTH + 1 - -#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_USERID OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES, 0x81 -#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_USERID_LENGTH OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_LENGTH + 1 - -#ifdef __cplusplus -} -#endif - -#endif /* _OIDSBASE_H_ */ diff --git a/libsecurity_asn1/lib/pkcs12Templates.h b/libsecurity_asn1/lib/pkcs12Templates.h deleted file mode 100644 index b5d6523e..00000000 --- a/libsecurity_asn1/lib/pkcs12Templates.h +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (c) 2003-2004,2008,2010 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@ - */ -/* - * pkcs12Templates.h - * - ******************************************************************* - * - * In a probably vain attempt to clarify the structure of a PKCS12 - * PFX, here is a high-level summary. - * - * The top level item in P12 is a PFX. - * - * PFX = { - * int version; - * ContentInfo authSafe; -- from PKCS7 - * MacData mac; -- optional, password integrity version - * } - * - * The authSafe in a PFX has two legal contentTypes in the P12 - * world, CT_Data (password integrity mode) or CT_SignedData - * (public key integrity mode). The current version of this library - * only supports password integrity mode. Thus the integrity of - * the whole authSafe item is protected by a MAC in the PFX. - * - * The authSafe.content field is a BER-encoded AuthenticatedSafe. - * - * AuthenticatedSafe = { - * SEQUENCE OF ContentInfo; - * } - * - * OK. Each ContentInfo in an AuthenticatedSafe can either be type - * CT_Data, CT_EnvData, or CT_EncryptedData. In the latter cases the - * content is decrypted to produce an encoded SafeContents; in the - * former case the content *is* an encoded SafeContents. - * - * A SafeContents is a sequence of SafeBags. - * - * Each SafeBag can be of several types: - * - * BT_KeyBag - * BT_ShroudedKeyBag - * BT_CertBag - * BT_CrlBag - * BT_SecretBag - * BT_SafeContentsBag - * - */ - -#ifndef _PKCS12_TEMPLATES_H_ -#define _PKCS12_TEMPLATES_H_ - -#include /* for NSS_Attribute */ -#include /* will be lib-specific place */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * MacData ::= SEQUENCE { - * mac DigestInfo, - * macSalt OCTET STRING, - * iterations INTEGER DEFAULT 1 - * } - */ -typedef struct { - NSS_P7_DigestInfo mac; - SecAsn1Item macSalt; - SecAsn1Item iterations; // optional -} NSS_P12_MacData; - -extern const SecAsn1Template NSS_P12_MacDataTemplate[]; - -/* - * PFX ::= SEQUENCE { - * version INTEGER {v3(3)}(v3,...), - * authSafe ContentInfo, - * macData MacData OPTIONAL - * } - */ - -/* - * First the top level PFX with unparsed ContentInfo.content. - */ -typedef struct { - SecAsn1Item version; - NSS_P7_RawContentInfo authSafe; - NSS_P12_MacData *macData; -} NSS_P12_RawPFX; - -extern const SecAsn1Template NSS_P12_RawPFXTemplate[]; - -/* - * And a PFX with a decoded ContentInfo.content. - */ -typedef struct { - SecAsn1Item version; - NSS_P7_DecodedContentInfo authSafe; - NSS_P12_MacData *macData; -} NSS_P12_DecodedPFX; - -extern const SecAsn1Template NSS_P12_DecodedPFXTemplate[]; - -/* - * The CSSMOID_PKCS7_Data-style ContentInfo.content of a PFX - * contains an encoded AuthenticatedSafe. - * - * AuthenticatedSafe ::= SEQUENCE OF ContentInfo - * -- Data if unencrypted - * -- EncryptedData if password-encrypted - * -- EnvelopedData if public key-encrypted - */ -typedef struct { - NSS_P7_DecodedContentInfo **info; -} NSS_P12_AuthenticatedSafe; - -extern const SecAsn1Template NSS_P12_AuthenticatedSafeTemplate[]; - -/* - * Individual BagTypes. - * Code on demand. - */ -typedef SecAsn1Item NSS_P12_KeyBag; -typedef NSS_EncryptedPrivateKeyInfo NSS_P12_ShroudedKeyBag; -typedef SecAsn1Item NSS_P12_SecretBag; -typedef SecAsn1Item NSS_P12_SafeContentsBag; - -/* - * CertBag - * - * CertBag ::= SEQUENCE { - * certId BAG-TYPE.&id ({CertTypes}), - * certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId}) - * } - * - * x509Certificate BAG-TYPE ::= - * {OCTET STRING IDENTIFIED BY {certTypes 1}} - * -- DER-encoded X.509 certificate stored in OCTET STRING - * sdsiCertificate BAG-TYPE ::= - * {IA5String IDENTIFIED BY {certTypes 2}} - * -- Base64-encoded SDSI certificate stored in IA5String - */ -typedef enum { - CT_Unknown, // --> ASN_ANY - CT_X509, - CT_SDSI, -} NSS_P12_CertBagType; - -typedef struct { - SecAsn1Oid bagType; - NSS_P12_CertBagType type; - SecAsn1Item certValue; -} NSS_P12_CertBag; - -extern const SecAsn1Template NSS_P12_CertBagTemplate[]; - -/* - * CRLBag - * - * CRLBag ::= SEQUENCE { - * certId BAG-TYPE.&id ({CertTypes}), - * certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId}) - * } - * - * x509Certificate BAG-TYPE ::= - * {OCTET STRING IDENTIFIED BY {certTypes 1}} - * -- DER-encoded X.509 certificate stored in OCTET STRING - * sdsiCertificate BAG-TYPE ::= - * {IA5String IDENTIFIED BY {certTypes 2}} - * -- Base64-encoded SDSI certificate stored in IA5String - */ -typedef enum { - CRT_Unknown, // --> ASN_ANY - CRT_X509, -} NSS_P12_CrlBagType; - -typedef struct { - SecAsn1Oid bagType; - NSS_P12_CrlBagType type; - SecAsn1Item crlValue; -} NSS_P12_CrlBag; - -extern const SecAsn1Template NSS_P12_CrlBagTemplate[]; - -/* - * BagId OIDs map to one of these for convenience. Our dynamic - * template chooser drops one of these into NSS_P12_SafeBag.type - * on decode. - */ -typedef enum { - BT_None = 0, - BT_KeyBag, - BT_ShroudedKeyBag, - BT_CertBag, - BT_CrlBag, - BT_SecretBag, - BT_SafeContentsBag -} NSS_P12_SB_Type; - -/* - * The ContentInfo.content values of each element in - * an AuthenticatedSafe map to a sequence of these - either directly - * (contentType CSSMOID_PKCS7_Data, octet string contents are - * the DER encoding of this) or indirectly (encrypted or - * shrouded, the decrypted content is the DER encoding of this). - */ -typedef struct { - SecAsn1Oid bagId; - NSS_P12_SB_Type type; - union { - NSS_P12_KeyBag *keyBag; - NSS_P12_ShroudedKeyBag *shroudedKeyBag; - NSS_P12_CertBag *certBag; - NSS_P12_CrlBag *crlBag; - NSS_P12_SecretBag *secretBag; - NSS_P12_SafeContentsBag *safeContentsBag; - } bagValue; - NSS_Attribute **bagAttrs; // optional -} NSS_P12_SafeBag; - -extern const SecAsn1Template NSS_P12_SafeBagTemplate[]; - -/* - * SafeContents, the contents of an element in an AuthenticatedSafe. - */ -typedef struct { - NSS_P12_SafeBag **bags; -} -NSS_P12_SafeContents; - -extern const SecAsn1Template NSS_P12_SafeContentsTemplate[]; - -/* - * PKCS12-specific algorithm parameters. - * A DER encoded version of this is the parameters value of - * a CSSM_X509_ALGORITHM_IDENTIFIER used in a - * NSS_P7_EncrContentInfo.encrAlg in P12 password privacy mode. - * - * pkcs-12PbeParams ::= SEQUENCE { - * salt OCTET STRING, - * iterations INTEGER - * } - * - * NOTE the P12 spec does place a limit on the value of iterations. - * I guess we have to assume in actual usage that it's - * restricted to (0..MAX), i.e., uint32-sized. - * - * We're also assuming that it is explicitly an unsigned value, - * so that the value bytes in the encoding of 0xff would be - * (0, 255). - */ -typedef struct { - SecAsn1Item salt; - SecAsn1Item iterations; -} NSS_P12_PBE_Params; - -extern const SecAsn1Template NSS_P12_PBE_ParamsTemplate[]; - -#ifdef __cplusplus -} -#endif - -#endif /* _PKCS12_TEMPLATES_H_ */ - diff --git a/libsecurity_asn1/lib/pkcs7Templates.h b/libsecurity_asn1/lib/pkcs7Templates.h deleted file mode 100644 index 45ea8846..00000000 --- a/libsecurity_asn1/lib/pkcs7Templates.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2003-2004,2008,2010 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@ - */ -/* - * pkcs7Templates.h - */ - -#ifndef _PKCS7_TEMPLATES_H_ -#define _PKCS7_TEMPLATES_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * DigestInfo ::= SEQUENCE { - * digestAlgorithm DigestAlgorithmIdentifier, - * digest Digest - * } - * - * Digest ::= OCTET STRING - */ -typedef struct { - SecAsn1AlgId digestAlgorithm; - SecAsn1Item digest; -} NSS_P7_DigestInfo; - -extern const SecAsn1Template NSS_P7_DigestInfoTemplate[]; - -/* - * Uninterpreted ContentInfo, with content stripped from its - * EXPLICIT CONTEXT_SPECIFIC wrapper - * - * ContentInfo ::= SEQUENCE { - * contentType ContentType, - * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL - * } - */ -typedef struct { - SecAsn1Oid contentType; - SecAsn1Item content; -} NSS_P7_RawContentInfo; - -extern const SecAsn1Template NSS_P7_RawContentInfoTemplate[]; - -// MARK: ---- ContentInfo.content types ----- - -/* - * Expand beyond ASN_ANY/CSSM_DATA as needed - */ -typedef SecAsn1Item NSS_P7_SignedData; -typedef SecAsn1Item NSS_P7_EnvelData; -typedef SecAsn1Item NSS_P7_SignEnvelData; -typedef SecAsn1Item NSS_P7_DigestedData; - -/* EncryptedData */ - -/* - * EncryptedContentInfo ::= SEQUENCE { - * contentType ContentType, - * contentEncryptionAlgorithm - * ContentEncryptionAlgorithmIdentifier, - * encryptedContent - * [0] IMPLICIT EncryptedContent OPTIONAL - * } - * - * EncryptedContent ::= OCTET STRING - */ - -typedef struct { - SecAsn1Oid contentType; - SecAsn1AlgId encrAlg; - SecAsn1Item encrContent; -} NSS_P7_EncrContentInfo; - -/* - * EncryptedData ::= SEQUENCE { - * version Version, - * encryptedContentInfo EncryptedContentInfo - * } - */ -typedef struct { - SecAsn1Item version; - NSS_P7_EncrContentInfo contentInfo; -} NSS_P7_EncryptedData; - -extern const SecAsn1Template NSS_P7_EncrContentInfoTemplate[]; -extern const SecAsn1Template NSS_P7_EncryptedDataTemplate[]; -extern const SecAsn1Template NSS_P7_PtrToEncryptedDataTemplate[]; - -/* the stub templates for unimplemented contentTypes */ -#define NSS_P7_PtrToSignedDataTemplate kSecAsn1PointerToAnyTemplate -#define NSS_P7_PtrToEnvelDataTemplate kSecAsn1PointerToAnyTemplate -#define NSS_P7_PtrToSignEnvelDataTemplate kSecAsn1PointerToAnyTemplate -#define NSS_P7_PtrToDigestedDataTemplate kSecAsn1PointerToAnyTemplate - -// MARK: ---- decoded ContentInfo ----- - -/* - * For convenience, out dynamic template chooser for ContentInfo.content - * drops one of these into the decoded struct. Thus, higher level - * code doesn't have to grunge around comparing OIDs to figure out - * what's there. - */ -typedef enum { - CT_None = 0, - CT_Data, - CT_SignedData, - CT_EnvData, - CT_SignedEnvData, - CT_DigestData, - CT_EncryptedData -} NSS_P7_CI_Type; - -/* - * Decoded ContentInfo. Decoded via SEC_ASN1_DYNAMIC per contentType. - */ -typedef struct { - SecAsn1Oid contentType; - NSS_P7_CI_Type type; - union { - SecAsn1Item *data; // CSSMOID_PKCS7_Data - // contents of Octet String - NSS_P7_SignedData *signedData; - // CSSMOID_PKCS7_SignedData - NSS_P7_EnvelData *envData; // CSSMOID_PKCS7_EnvelopedData - NSS_P7_SignEnvelData *signEnvelData; - // CSSMOID_PKCS7_SignedAndEnvelopedData - NSS_P7_DigestedData *digestedData; - // CSSMOID_PKCS7_DigestedData - NSS_P7_EncryptedData *encryptData; - //CSSMOID_PKCS7_EncryptedData - - } content; -} NSS_P7_DecodedContentInfo; - -extern const SecAsn1Template NSS_P7_DecodedContentInfoTemplate[]; - -#ifdef __cplusplus -} -#endif - -#endif /* _PKCS7_TEMPLATES_H_ */ - diff --git a/libsecurity_asn1/libsecurity_asn1.xcodeproj/project.pbxproj b/libsecurity_asn1/libsecurity_asn1.xcodeproj/project.pbxproj deleted file mode 100644 index 93f2d1c8..00000000 --- a/libsecurity_asn1/libsecurity_asn1.xcodeproj/project.pbxproj +++ /dev/null @@ -1,473 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 18312F9714E99A3F00F0BCAC /* SecNssCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434290534D3B800F287B2 /* SecNssCoder.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 1885B45314D9BB1A00519375 /* SecNssCoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434280534D3B800F287B2 /* SecNssCoder.cpp */; }; - 18B6B2A714DB73A000EDDE5F /* secErrorStr.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434270534D3B800F287B2 /* secErrorStr.c */; }; - 4C28246B0F1BC75800CAADEC /* oidsocsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2824670F1BC75800CAADEC /* oidsocsp.c */; }; - 4C28246C0F1BC75800CAADEC /* oidsocsp.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C2824680F1BC75800CAADEC /* oidsocsp.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 795CA8220D38041D00BAE6A2 /* SecAsn1Coder.c in Sources */ = {isa = PBXBuildFile; fileRef = 0545C7B806502D1100543007 /* SecAsn1Coder.c */; }; - 795CA8230D38041D00BAE6A2 /* SecAsn1Coder.h in Headers */ = {isa = PBXBuildFile; fileRef = 0545C7B906502D1100543007 /* SecAsn1Coder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 795CA8240D38041D00BAE6A2 /* SecAsn1Templates.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6433F80534D3B800F287B2 /* SecAsn1Templates.c */; }; - 795CA8250D38041D00BAE6A2 /* SecAsn1Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6433F90534D3B800F287B2 /* SecAsn1Templates.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 795CA8260D38041D00BAE6A2 /* SecAsn1Types.h in Headers */ = {isa = PBXBuildFile; fileRef = 0554F5B609892C980085E7C5 /* SecAsn1Types.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 795CA8270D38041D00BAE6A2 /* certExtensionTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6433FA0534D3B800F287B2 /* certExtensionTemplates.c */; }; - 795CA8280D38041D00BAE6A2 /* certExtensionTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6433FB0534D3B800F287B2 /* certExtensionTemplates.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 795CA8290D38041D00BAE6A2 /* csrTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6433FC0534D3B800F287B2 /* csrTemplates.c */; }; - 795CA82A0D38041D00BAE6A2 /* csrTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6433FD0534D3B800F287B2 /* csrTemplates.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 795CA82B0D38041D00BAE6A2 /* keyTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6433FE0534D3B800F287B2 /* keyTemplates.c */; }; - 795CA82C0D38041D00BAE6A2 /* keyTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 0502B640068A5920006168D5 /* keyTemplates.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 795CA82D0D38041D00BAE6A2 /* nameTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434000534D3B800F287B2 /* nameTemplates.c */; }; - 795CA82E0D38041D00BAE6A2 /* nameTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434010534D3B800F287B2 /* nameTemplates.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 795CA82F0D38041D00BAE6A2 /* nsprPortX.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434020534D3B800F287B2 /* nsprPortX.c */; }; - 795CA8300D38041D00BAE6A2 /* nssUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434060534D3B800F287B2 /* nssUtils.c */; }; - 795CA8310D38041D00BAE6A2 /* nssUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434070534D3B800F287B2 /* nssUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 795CA8320D38041D00BAE6A2 /* ocspTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = 0502BF9A068B51E3006168D5 /* ocspTemplates.c */; }; - 795CA8330D38041D00BAE6A2 /* ocspTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6433FF0534D3B800F287B2 /* ocspTemplates.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 795CA8350D38041D00BAE6A2 /* secasn1d.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434210534D3B800F287B2 /* secasn1d.c */; }; - 795CA8360D38041D00BAE6A2 /* secasn1e.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434220534D3B800F287B2 /* secasn1e.c */; }; - 795CA8380D38041D00BAE6A2 /* secasn1u.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434240534D3B800F287B2 /* secasn1u.c */; }; - 795CA8390D38041D00BAE6A2 /* X509Templates.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C64342D0534D3B800F287B2 /* X509Templates.c */; }; - 795CA83A0D38041D00BAE6A2 /* X509Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64342E0534D3B800F287B2 /* X509Templates.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 795CA83B0D38041D00BAE6A2 /* osKeyTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = 0504B16106517A730011D5F5 /* osKeyTemplates.c */; }; - 795CA83C0D38041D00BAE6A2 /* osKeyTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 0504B16206517A730011D5F5 /* osKeyTemplates.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 795CAAD10D3BEDBB00BAE6A2 /* pkcs7Templates.c in Sources */ = {isa = PBXBuildFile; fileRef = 795CAACD0D3BEDBB00BAE6A2 /* pkcs7Templates.c */; }; - 795CAAD20D3BEDBB00BAE6A2 /* pkcs7Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 795CAACE0D3BEDBB00BAE6A2 /* pkcs7Templates.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 795CAAD30D3BEDBB00BAE6A2 /* pkcs12Templates.c in Sources */ = {isa = PBXBuildFile; fileRef = 795CAACF0D3BEDBB00BAE6A2 /* pkcs12Templates.c */; }; - 795CAAD40D3BEDBB00BAE6A2 /* pkcs12Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 795CAAD00D3BEDBB00BAE6A2 /* pkcs12Templates.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 798B80C10D3E8B6700AC1D04 /* secasn1.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434200534D3B800F287B2 /* secasn1.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 798B80E00D3E8BFC00AC1D04 /* secasn1t.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434230534D3B800F287B2 /* secasn1t.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 79BDD2D10D60CE82000D84D3 /* plarenas.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64340C0534D3B800F287B2 /* plarenas.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD2ED0D60CEF5000D84D3 /* prtypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64341E0534D3B800F287B2 /* prtypes.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD2F60D60CF24000D84D3 /* prcpucfg.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64340F0534D3B800F287B2 /* prcpucfg.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD2FC0D60CF66000D84D3 /* secerr.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434260534D3B800F287B2 /* secerr.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD3020D60CFC9000D84D3 /* protypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64341B0534D3B800F287B2 /* protypes.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD30C0D60D0E5000D84D3 /* seccomon.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434250534D3B800F287B2 /* seccomon.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD3100D60D116000D84D3 /* plstr.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64340D0534D3B800F287B2 /* plstr.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD3110D60D116000D84D3 /* prlog.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434170534D3B800F287B2 /* prlog.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD33F0D60D29A000D84D3 /* prerror.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434130534D3B800F287B2 /* prerror.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD3420D60D2B2000D84D3 /* prerr.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434120534D3B800F287B2 /* prerr.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD3490D60D4A4000D84D3 /* prbit.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64340E0534D3B800F287B2 /* prbit.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD34A0D60D4A4000D84D3 /* prmem.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434190534D3B800F287B2 /* prmem.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79EF5A780D3C1984009F5270 /* oidsalg.c in Sources */ = {isa = PBXBuildFile; fileRef = 79EF5A730D3C1984009F5270 /* oidsalg.c */; }; - 79EF5A790D3C1984009F5270 /* oidsalg.h in Headers */ = {isa = PBXBuildFile; fileRef = 79EF5A740D3C1984009F5270 /* oidsalg.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 79EF5A7A0D3C1984009F5270 /* oidsattr.c in Sources */ = {isa = PBXBuildFile; fileRef = 79EF5A750D3C1984009F5270 /* oidsattr.c */; }; - 79EF5A7B0D3C1984009F5270 /* oidsattr.h in Headers */ = {isa = PBXBuildFile; fileRef = 79EF5A760D3C1984009F5270 /* oidsattr.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 79EF5A7C0D3C1984009F5270 /* oidsbase.h in Headers */ = {isa = PBXBuildFile; fileRef = 79EF5A770D3C1984009F5270 /* oidsbase.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 79EF5BA30D3D6EF4009F5270 /* secport.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64342B0534D3B800F287B2 /* secport.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79EF5BA50D3D6EF8009F5270 /* secport.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C64342A0534D3B800F287B2 /* secport.c */; }; - 79EF5BC90D3D6F44009F5270 /* plarena.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C64340A0534D3B800F287B2 /* plarena.c */; }; - 79EF5BCA0D3D6F44009F5270 /* plarena.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64340B0534D3B800F287B2 /* plarena.h */; settings = {ATTRIBUTES = (Private, ); }; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 0502B640068A5920006168D5 /* keyTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = keyTemplates.h; sourceTree = ""; }; - 0502BF9A068B51E3006168D5 /* ocspTemplates.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ocspTemplates.c; sourceTree = ""; }; - 0504B16106517A730011D5F5 /* osKeyTemplates.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = osKeyTemplates.c; sourceTree = ""; }; - 0504B16206517A730011D5F5 /* osKeyTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = osKeyTemplates.h; sourceTree = ""; }; - 0545C78806502BAD00543007 /* security_asn1.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = security_asn1.exp; sourceTree = ""; }; - 0545C7B806502D1100543007 /* SecAsn1Coder.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SecAsn1Coder.c; sourceTree = ""; }; - 0545C7B906502D1100543007 /* SecAsn1Coder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecAsn1Coder.h; sourceTree = ""; }; - 0554F5B609892C980085E7C5 /* SecAsn1Types.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecAsn1Types.h; sourceTree = ""; }; - 05ABB7BB0989387700FA0183 /* asn1Templates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = asn1Templates.h; sourceTree = ""; }; - 05BE7E6B0A37669000C055B0 /* libsecurity_asn1.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; path = libsecurity_asn1.plist; sourceTree = ""; }; - 05BE7E6C0A37669000C055B0 /* libsecurity_asn1.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = libsecurity_asn1.txt; sourceTree = ""; }; - 18B647F514D9FD4500F538BF /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; - 18B647F614D9FD4500F538BF /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; - 18B647F714D9FD4500F538BF /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; - 18B647F814D9FD4500F538BF /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; - 4C2824670F1BC75800CAADEC /* oidsocsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = oidsocsp.c; sourceTree = ""; }; - 4C2824680F1BC75800CAADEC /* oidsocsp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oidsocsp.h; sourceTree = ""; }; - 4C6433F80534D3B800F287B2 /* SecAsn1Templates.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SecAsn1Templates.c; sourceTree = ""; }; - 4C6433F90534D3B800F287B2 /* SecAsn1Templates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecAsn1Templates.h; sourceTree = ""; }; - 4C6433FA0534D3B800F287B2 /* certExtensionTemplates.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = certExtensionTemplates.c; sourceTree = ""; }; - 4C6433FB0534D3B800F287B2 /* certExtensionTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = certExtensionTemplates.h; sourceTree = ""; }; - 4C6433FC0534D3B800F287B2 /* csrTemplates.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = csrTemplates.c; sourceTree = ""; }; - 4C6433FD0534D3B800F287B2 /* csrTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = csrTemplates.h; sourceTree = ""; }; - 4C6433FE0534D3B800F287B2 /* keyTemplates.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = keyTemplates.c; sourceTree = ""; }; - 4C6433FF0534D3B800F287B2 /* ocspTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ocspTemplates.h; sourceTree = ""; }; - 4C6434000534D3B800F287B2 /* nameTemplates.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = nameTemplates.c; sourceTree = ""; }; - 4C6434010534D3B800F287B2 /* nameTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = nameTemplates.h; sourceTree = ""; }; - 4C6434020534D3B800F287B2 /* nsprPortX.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = nsprPortX.c; sourceTree = ""; }; - 4C6434030534D3B800F287B2 /* nssilckt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = nssilckt.h; sourceTree = ""; }; - 4C6434040534D3B800F287B2 /* nssilock.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = nssilock.h; sourceTree = ""; }; - 4C6434050534D3B800F287B2 /* nsslocks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = nsslocks.h; sourceTree = ""; }; - 4C6434060534D3B800F287B2 /* nssUtils.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = nssUtils.c; sourceTree = ""; }; - 4C6434070534D3B800F287B2 /* nssUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = nssUtils.h; sourceTree = ""; }; - 4C64340A0534D3B800F287B2 /* plarena.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = plarena.c; sourceTree = ""; }; - 4C64340B0534D3B800F287B2 /* plarena.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = plarena.h; sourceTree = ""; }; - 4C64340C0534D3B800F287B2 /* plarenas.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = plarenas.h; sourceTree = ""; }; - 4C64340D0534D3B800F287B2 /* plstr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = plstr.h; sourceTree = ""; }; - 4C64340E0534D3B800F287B2 /* prbit.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prbit.h; sourceTree = ""; }; - 4C64340F0534D3B800F287B2 /* prcpucfg.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prcpucfg.h; sourceTree = ""; }; - 4C6434100534D3B800F287B2 /* prcvar.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prcvar.h; sourceTree = ""; }; - 4C6434110534D3B800F287B2 /* prenv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prenv.h; sourceTree = ""; }; - 4C6434120534D3B800F287B2 /* prerr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prerr.h; sourceTree = ""; }; - 4C6434130534D3B800F287B2 /* prerror.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prerror.h; sourceTree = ""; }; - 4C6434140534D3B800F287B2 /* prinit.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prinit.h; sourceTree = ""; }; - 4C6434150534D3B800F287B2 /* prinrval.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prinrval.h; sourceTree = ""; }; - 4C6434160534D3B800F287B2 /* prlock.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prlock.h; sourceTree = ""; }; - 4C6434170534D3B800F287B2 /* prlog.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prlog.h; sourceTree = ""; }; - 4C6434180534D3B800F287B2 /* prlong.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prlong.h; sourceTree = ""; }; - 4C6434190534D3B800F287B2 /* prmem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prmem.h; sourceTree = ""; }; - 4C64341A0534D3B800F287B2 /* prmon.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prmon.h; sourceTree = ""; }; - 4C64341B0534D3B800F287B2 /* protypes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = protypes.h; sourceTree = ""; }; - 4C64341C0534D3B800F287B2 /* prthread.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prthread.h; sourceTree = ""; }; - 4C64341D0534D3B800F287B2 /* prtime.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prtime.h; sourceTree = ""; }; - 4C64341E0534D3B800F287B2 /* prtypes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prtypes.h; sourceTree = ""; }; - 4C64341F0534D3B800F287B2 /* prvrsion.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = prvrsion.h; sourceTree = ""; }; - 4C6434200534D3B800F287B2 /* secasn1.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = secasn1.h; sourceTree = ""; }; - 4C6434210534D3B800F287B2 /* secasn1d.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = secasn1d.c; sourceTree = ""; }; - 4C6434220534D3B800F287B2 /* secasn1e.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = secasn1e.c; sourceTree = ""; }; - 4C6434230534D3B800F287B2 /* secasn1t.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = secasn1t.h; sourceTree = ""; }; - 4C6434240534D3B800F287B2 /* secasn1u.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = secasn1u.c; sourceTree = ""; }; - 4C6434250534D3B800F287B2 /* seccomon.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = seccomon.h; sourceTree = ""; }; - 4C6434260534D3B800F287B2 /* secerr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = secerr.h; sourceTree = ""; }; - 4C6434270534D3B800F287B2 /* secErrorStr.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = secErrorStr.c; sourceTree = ""; }; - 4C6434280534D3B800F287B2 /* SecNssCoder.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecNssCoder.cpp; sourceTree = ""; }; - 4C6434290534D3B800F287B2 /* SecNssCoder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecNssCoder.h; sourceTree = ""; }; - 4C64342A0534D3B800F287B2 /* secport.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = secport.c; sourceTree = ""; }; - 4C64342B0534D3B800F287B2 /* secport.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = secport.h; sourceTree = ""; }; - 4C64342D0534D3B800F287B2 /* X509Templates.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = X509Templates.c; sourceTree = ""; }; - 4C64342E0534D3B800F287B2 /* X509Templates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = X509Templates.h; sourceTree = ""; }; - 795CA7FF0D38013D00BAE6A2 /* libASN1.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libASN1.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 795CAACD0D3BEDBB00BAE6A2 /* pkcs7Templates.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkcs7Templates.c; sourceTree = ""; }; - 795CAACE0D3BEDBB00BAE6A2 /* pkcs7Templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pkcs7Templates.h; sourceTree = ""; }; - 795CAACF0D3BEDBB00BAE6A2 /* pkcs12Templates.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkcs12Templates.c; sourceTree = ""; }; - 795CAAD00D3BEDBB00BAE6A2 /* pkcs12Templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pkcs12Templates.h; sourceTree = ""; }; - 79EF5A730D3C1984009F5270 /* oidsalg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = oidsalg.c; sourceTree = ""; }; - 79EF5A740D3C1984009F5270 /* oidsalg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oidsalg.h; sourceTree = ""; }; - 79EF5A750D3C1984009F5270 /* oidsattr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = oidsattr.c; sourceTree = ""; }; - 79EF5A760D3C1984009F5270 /* oidsattr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oidsattr.h; sourceTree = ""; }; - 79EF5A770D3C1984009F5270 /* oidsbase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oidsbase.h; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 795CA7FD0D38013D00BAE6A2 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 05BE7E680A37663E00C055B0 /* docs */ = { - isa = PBXGroup; - children = ( - 05BE7E6B0A37669000C055B0 /* libsecurity_asn1.plist */, - 05BE7E6C0A37669000C055B0 /* libsecurity_asn1.txt */, - ); - path = docs; - sourceTree = ""; - }; - 18B647F414D9FD4500F538BF /* config */ = { - isa = PBXGroup; - children = ( - 18B647F514D9FD4500F538BF /* base.xcconfig */, - 18B647F614D9FD4500F538BF /* debug.xcconfig */, - 18B647F714D9FD4500F538BF /* lib.xcconfig */, - 18B647F814D9FD4500F538BF /* release.xcconfig */, - ); - path = config; - sourceTree = ""; - }; - 4C6433F70534D3B800F287B2 /* lib */ = { - isa = PBXGroup; - children = ( - 05ABB7BB0989387700FA0183 /* asn1Templates.h */, - 0545C7B806502D1100543007 /* SecAsn1Coder.c */, - 0545C7B906502D1100543007 /* SecAsn1Coder.h */, - 4C6433F80534D3B800F287B2 /* SecAsn1Templates.c */, - 4C6433F90534D3B800F287B2 /* SecAsn1Templates.h */, - 0554F5B609892C980085E7C5 /* SecAsn1Types.h */, - 4C6433FA0534D3B800F287B2 /* certExtensionTemplates.c */, - 4C6433FB0534D3B800F287B2 /* certExtensionTemplates.h */, - 4C6433FC0534D3B800F287B2 /* csrTemplates.c */, - 4C6433FD0534D3B800F287B2 /* csrTemplates.h */, - 4C6433FE0534D3B800F287B2 /* keyTemplates.c */, - 0502B640068A5920006168D5 /* keyTemplates.h */, - 4C6434000534D3B800F287B2 /* nameTemplates.c */, - 4C6434010534D3B800F287B2 /* nameTemplates.h */, - 795CAACD0D3BEDBB00BAE6A2 /* pkcs7Templates.c */, - 795CAACE0D3BEDBB00BAE6A2 /* pkcs7Templates.h */, - 795CAACF0D3BEDBB00BAE6A2 /* pkcs12Templates.c */, - 795CAAD00D3BEDBB00BAE6A2 /* pkcs12Templates.h */, - 4C6434020534D3B800F287B2 /* nsprPortX.c */, - 4C6434030534D3B800F287B2 /* nssilckt.h */, - 4C6434040534D3B800F287B2 /* nssilock.h */, - 4C6434050534D3B800F287B2 /* nsslocks.h */, - 4C6434060534D3B800F287B2 /* nssUtils.c */, - 4C6434070534D3B800F287B2 /* nssUtils.h */, - 0502BF9A068B51E3006168D5 /* ocspTemplates.c */, - 4C6433FF0534D3B800F287B2 /* ocspTemplates.h */, - 4C64340A0534D3B800F287B2 /* plarena.c */, - 4C64340B0534D3B800F287B2 /* plarena.h */, - 4C64340C0534D3B800F287B2 /* plarenas.h */, - 4C64340D0534D3B800F287B2 /* plstr.h */, - 4C64340E0534D3B800F287B2 /* prbit.h */, - 4C64340F0534D3B800F287B2 /* prcpucfg.h */, - 4C6434100534D3B800F287B2 /* prcvar.h */, - 4C6434110534D3B800F287B2 /* prenv.h */, - 4C6434120534D3B800F287B2 /* prerr.h */, - 4C6434130534D3B800F287B2 /* prerror.h */, - 4C6434140534D3B800F287B2 /* prinit.h */, - 4C6434150534D3B800F287B2 /* prinrval.h */, - 4C6434160534D3B800F287B2 /* prlock.h */, - 4C6434170534D3B800F287B2 /* prlog.h */, - 4C6434180534D3B800F287B2 /* prlong.h */, - 4C6434190534D3B800F287B2 /* prmem.h */, - 4C64341A0534D3B800F287B2 /* prmon.h */, - 4C64341B0534D3B800F287B2 /* protypes.h */, - 4C64341C0534D3B800F287B2 /* prthread.h */, - 4C64341D0534D3B800F287B2 /* prtime.h */, - 4C64341E0534D3B800F287B2 /* prtypes.h */, - 4C64341F0534D3B800F287B2 /* prvrsion.h */, - 4C6434200534D3B800F287B2 /* secasn1.h */, - 4C6434210534D3B800F287B2 /* secasn1d.c */, - 4C6434220534D3B800F287B2 /* secasn1e.c */, - 4C6434230534D3B800F287B2 /* secasn1t.h */, - 4C6434240534D3B800F287B2 /* secasn1u.c */, - 4C6434250534D3B800F287B2 /* seccomon.h */, - 4C6434260534D3B800F287B2 /* secerr.h */, - 4C6434270534D3B800F287B2 /* secErrorStr.c */, - 4C6434280534D3B800F287B2 /* SecNssCoder.cpp */, - 4C6434290534D3B800F287B2 /* SecNssCoder.h */, - 4C64342A0534D3B800F287B2 /* secport.c */, - 4C64342B0534D3B800F287B2 /* secport.h */, - 4C64342D0534D3B800F287B2 /* X509Templates.c */, - 4C64342E0534D3B800F287B2 /* X509Templates.h */, - 0504B16106517A730011D5F5 /* osKeyTemplates.c */, - 0504B16206517A730011D5F5 /* osKeyTemplates.h */, - 79EF5A730D3C1984009F5270 /* oidsalg.c */, - 79EF5A740D3C1984009F5270 /* oidsalg.h */, - 79EF5A750D3C1984009F5270 /* oidsattr.c */, - 79EF5A760D3C1984009F5270 /* oidsattr.h */, - 79EF5A770D3C1984009F5270 /* oidsbase.h */, - 4C2824670F1BC75800CAADEC /* oidsocsp.c */, - 4C2824680F1BC75800CAADEC /* oidsocsp.h */, - 0545C78806502BAD00543007 /* security_asn1.exp */, - ); - path = lib; - sourceTree = ""; - }; - 9D56980803E74D6100003D05 = { - isa = PBXGroup; - children = ( - 18B647F414D9FD4500F538BF /* config */, - 4C6433F70534D3B800F287B2 /* lib */, - 05BE7E680A37663E00C055B0 /* docs */, - 9D56981D03E74E4100003D05 /* Products */, - ); - sourceTree = ""; - }; - 9D56981D03E74E4100003D05 /* Products */ = { - isa = PBXGroup; - children = ( - 795CA7FF0D38013D00BAE6A2 /* libASN1.a */, - ); - name = Products; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 795CA7FB0D38013D00BAE6A2 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 79BDD3490D60D4A4000D84D3 /* prbit.h in Headers */, - 79BDD34A0D60D4A4000D84D3 /* prmem.h in Headers */, - 79BDD3100D60D116000D84D3 /* plstr.h in Headers */, - 79BDD3110D60D116000D84D3 /* prlog.h in Headers */, - 79BDD30C0D60D0E5000D84D3 /* seccomon.h in Headers */, - 79BDD3420D60D2B2000D84D3 /* prerr.h in Headers */, - 79BDD33F0D60D29A000D84D3 /* prerror.h in Headers */, - 79BDD2FC0D60CF66000D84D3 /* secerr.h in Headers */, - 79EF5BA30D3D6EF4009F5270 /* secport.h in Headers */, - 798B80C10D3E8B6700AC1D04 /* secasn1.h in Headers */, - 798B80E00D3E8BFC00AC1D04 /* secasn1t.h in Headers */, - 79BDD2F60D60CF24000D84D3 /* prcpucfg.h in Headers */, - 79BDD2ED0D60CEF5000D84D3 /* prtypes.h in Headers */, - 79EF5BCA0D3D6F44009F5270 /* plarena.h in Headers */, - 79BDD3020D60CFC9000D84D3 /* protypes.h in Headers */, - 79BDD2D10D60CE82000D84D3 /* plarenas.h in Headers */, - 795CA8230D38041D00BAE6A2 /* SecAsn1Coder.h in Headers */, - 795CA8250D38041D00BAE6A2 /* SecAsn1Templates.h in Headers */, - 795CA8260D38041D00BAE6A2 /* SecAsn1Types.h in Headers */, - 795CA8280D38041D00BAE6A2 /* certExtensionTemplates.h in Headers */, - 795CA82A0D38041D00BAE6A2 /* csrTemplates.h in Headers */, - 795CA82C0D38041D00BAE6A2 /* keyTemplates.h in Headers */, - 795CA82E0D38041D00BAE6A2 /* nameTemplates.h in Headers */, - 795CA8310D38041D00BAE6A2 /* nssUtils.h in Headers */, - 795CA8330D38041D00BAE6A2 /* ocspTemplates.h in Headers */, - 795CA83A0D38041D00BAE6A2 /* X509Templates.h in Headers */, - 795CA83C0D38041D00BAE6A2 /* osKeyTemplates.h in Headers */, - 795CAAD20D3BEDBB00BAE6A2 /* pkcs7Templates.h in Headers */, - 795CAAD40D3BEDBB00BAE6A2 /* pkcs12Templates.h in Headers */, - 79EF5A790D3C1984009F5270 /* oidsalg.h in Headers */, - 79EF5A7B0D3C1984009F5270 /* oidsattr.h in Headers */, - 79EF5A7C0D3C1984009F5270 /* oidsbase.h in Headers */, - 4C28246C0F1BC75800CAADEC /* oidsocsp.h in Headers */, - 18312F9714E99A3F00F0BCAC /* SecNssCoder.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 795CA7FE0D38013D00BAE6A2 /* libASN1 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 795CA8030D38017E00BAE6A2 /* Build configuration list for PBXNativeTarget "libASN1" */; - buildPhases = ( - 795CA7FB0D38013D00BAE6A2 /* Headers */, - 795CA7FC0D38013D00BAE6A2 /* Sources */, - 795CA7FD0D38013D00BAE6A2 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libASN1; - productName = libASN1; - productReference = 795CA7FF0D38013D00BAE6A2 /* libASN1.a */; - productType = "com.apple.product-type.library.static"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 9D56980C03E74D6100003D05 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0500; - }; - buildConfigurationList = C23B0CEC09A298C500B7FCED /* Build configuration list for PBXProject "libsecurity_asn1" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - English, - Japanese, - French, - German, - ); - mainGroup = 9D56980803E74D6100003D05; - productRefGroup = 9D56981D03E74E4100003D05 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 795CA7FE0D38013D00BAE6A2 /* libASN1 */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 795CA7FC0D38013D00BAE6A2 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 79EF5BC90D3D6F44009F5270 /* plarena.c in Sources */, - 795CA8220D38041D00BAE6A2 /* SecAsn1Coder.c in Sources */, - 795CA8240D38041D00BAE6A2 /* SecAsn1Templates.c in Sources */, - 79EF5BA50D3D6EF8009F5270 /* secport.c in Sources */, - 795CA8270D38041D00BAE6A2 /* certExtensionTemplates.c in Sources */, - 795CA8290D38041D00BAE6A2 /* csrTemplates.c in Sources */, - 795CA82B0D38041D00BAE6A2 /* keyTemplates.c in Sources */, - 795CA82D0D38041D00BAE6A2 /* nameTemplates.c in Sources */, - 795CA82F0D38041D00BAE6A2 /* nsprPortX.c in Sources */, - 795CA8300D38041D00BAE6A2 /* nssUtils.c in Sources */, - 795CA8320D38041D00BAE6A2 /* ocspTemplates.c in Sources */, - 795CA8350D38041D00BAE6A2 /* secasn1d.c in Sources */, - 795CA8360D38041D00BAE6A2 /* secasn1e.c in Sources */, - 795CA8380D38041D00BAE6A2 /* secasn1u.c in Sources */, - 795CA8390D38041D00BAE6A2 /* X509Templates.c in Sources */, - 795CA83B0D38041D00BAE6A2 /* osKeyTemplates.c in Sources */, - 795CAAD10D3BEDBB00BAE6A2 /* pkcs7Templates.c in Sources */, - 795CAAD30D3BEDBB00BAE6A2 /* pkcs12Templates.c in Sources */, - 79EF5A780D3C1984009F5270 /* oidsalg.c in Sources */, - 79EF5A7A0D3C1984009F5270 /* oidsattr.c in Sources */, - 4C28246B0F1BC75800CAADEC /* oidsocsp.c in Sources */, - 1885B45314D9BB1A00519375 /* SecNssCoder.cpp in Sources */, - 18B6B2A714DB73A000EDDE5F /* secErrorStr.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 795CA8090D3801A700BAE6A2 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18B647F614D9FD4500F538BF /* debug.xcconfig */; - buildSettings = { - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - }; - name = Debug; - }; - 795CA80D0D3801A700BAE6A2 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18B647F714D9FD4500F538BF /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - LIBRARY_STYLE = STATIC; - }; - name = Debug; - }; - 795CA8180D3801A900BAE6A2 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18B647F814D9FD4500F538BF /* release.xcconfig */; - buildSettings = { - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - }; - name = Release; - }; - 795CA81C0D3801A900BAE6A2 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18B647F714D9FD4500F538BF /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - LIBRARY_STYLE = STATIC; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 795CA8030D38017E00BAE6A2 /* Build configuration list for PBXNativeTarget "libASN1" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 795CA80D0D3801A700BAE6A2 /* Debug */, - 795CA81C0D3801A900BAE6A2 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C23B0CEC09A298C500B7FCED /* Build configuration list for PBXProject "libsecurity_asn1" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 795CA8090D3801A700BAE6A2 /* Debug */, - 795CA8180D3801A900BAE6A2 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 9D56980C03E74D6100003D05 /* Project object */; -} diff --git a/libsecurity_asn1/libsecurity_asn1.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_asn1/libsecurity_asn1.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index f262dc8b..00000000 --- a/libsecurity_asn1/libsecurity_asn1.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 795CA7FE0D38013D00BAE6A2 - - primary - - - - - diff --git a/libsecurity_authorization/libsecurity_authorization.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_authorization/libsecurity_authorization.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 988e9b5a..00000000 --- a/libsecurity_authorization/libsecurity_authorization.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 4CA1FEBD052A3C8100F22E42 - - primary - - - - - diff --git a/libsecurity_cdsa_client/libsecurity_cdsa_client.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_cdsa_client/libsecurity_cdsa_client.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 988e9b5a..00000000 --- a/libsecurity_cdsa_client/libsecurity_cdsa_client.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 4CA1FEBD052A3C8100F22E42 - - primary - - - - - diff --git a/libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 7ebc9c56..00000000 --- a/libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,19 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 4CA1FEBD052A3C8100F22E42 - - primary - - - C2C38A530535EDE600D7421F - - primary - - - - - diff --git a/libsecurity_cdsa_utilities/libsecurity_cdsa_utilities.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_cdsa_utilities/libsecurity_cdsa_utilities.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 0bbe8b3a..00000000 --- a/libsecurity_cdsa_utilities/libsecurity_cdsa_utilities.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,19 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 4CA2A5390523D32800978A7B - - primary - - - 4CF9C5B80535E557009B9B8D - - primary - - - - - diff --git a/libsecurity_cdsa_utils/lib/cuEnc64.c b/libsecurity_cdsa_utils/lib/cuEnc64.c deleted file mode 100644 index 59dfbdc9..00000000 --- a/libsecurity_cdsa_utils/lib/cuEnc64.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright (c) 1998-2003 Apple Computer, Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please - * obtain a copy of the License at http://www.apple.com/publicsource and - * read it before using this file. - * - * This 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. - * - * cuEnc64.c - encode/decode in 64-char IA5 format, per RFC 1421 - */ - -#include "cuEnc64.h" -#include - -#ifndef NULL -#define NULL ((void *)0) -#endif /* NULL */ - -/* - * map a 6-bit binary value to a printable character. - */ -static const -unsigned char bintoasc[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -/* - * Map an 7-bit printable character to its corresponding binary value. - * Any illegal characters return high bit set. - */ -static const -unsigned char asctobin[] = -{ - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x3e, 0x80, 0x80, 0x80, 0x3f, - 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, - 0x3c, 0x3d, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, - 0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, - 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80 -}; - -/* - * map 6 bits to a printing char - */ -#define ENC(c) (bintoasc[((c) & 0x3f)]) - -#define PAD '=' - -/* - * map one group of up to 3 bytes at inp to 4 bytes at outp. - * Count is number of valid bytes in *inp; if less than 3, the - * 1 or two extras must be zeros. - */ -static void encChunk(const unsigned char *inp, - unsigned char *outp, - int count) -{ - unsigned char c1, c2, c3, c4; - - c1 = *inp >> 2; - c2 = ((inp[0] << 4) & 0x30) | ((inp[1] >> 4) & 0xf); - c3 = ((inp[1] << 2) & 0x3c) | ((inp[2] >> 6) & 0x3); - c4 = inp[2] & 0x3f; - *outp++ = ENC(c1); - *outp++ = ENC(c2); - if (count == 1) { - *outp++ = PAD; - *outp = PAD; - } else { - *outp++ = ENC(c3); - if (count == 2) { - *outp = PAD; - } - else { - *outp = ENC(c4); - } - } -} - -/* - * Given input buffer inbuf, length inlen, encode to 64-char IA5 format. - * Result is fmalloc'd and returned; it is terminated by Microsoft-style - * newline and NULL. Its length (including the trailing newline and NULL) - * is returned in *outlen. - */ - -unsigned char *cuEnc64(const unsigned char *inbuf, - unsigned inlen, - unsigned *outlen) // RETURNED -{ - return cuEnc64WithLines(inbuf, inlen, 0, outlen); -} - -unsigned char *cuEnc64WithLines(const unsigned char *inbuf, - unsigned inlen, - unsigned linelen, - unsigned *outlen) -{ - unsigned outTextLen; - unsigned len; // to malloc, liberal - unsigned olen = 0; // actual output size - unsigned char *outbuf; - unsigned char endbuf[3]; - unsigned i; - unsigned char *outp; - unsigned numLines; - unsigned thisLine; - - outTextLen = ((inlen + 2) / 3) * 4; - if(linelen) { - /* - * linelen must be 0 mod 4 for this to work; round up... - */ - if((linelen & 0x03) != 0) { - linelen = (linelen + 3) & 0xfffffffc; - } - numLines = (outTextLen + linelen - 1)/ linelen; - } - else { - numLines = 1; - } - - /* - * Total output size = encoded text size plus one newline per - * line of output, plus trailing NULL. We always generate newlines - * as \n; when decoding, we tolerate \r\n (Microsoft) or \n. - */ - len = outTextLen + (2 * numLines) + 1; - outbuf = (unsigned char*)malloc(len); - outp = outbuf; - thisLine = 0; - - while(inlen) { - if(inlen < 3) { - for(i=0; i<3; i++) { - if(i < inlen) { - endbuf[i] = inbuf[i]; - } - else { - endbuf[i] = 0; - } - } - encChunk(endbuf, outp, inlen); - inlen = 0; - } - else { - encChunk(inbuf, outp, 3); - inlen -= 3; - inbuf += 3; - } - outp += 4; - thisLine += 4; - olen += 4; - if((linelen != 0) && (thisLine >= linelen) && inlen) { - /* - * last trailing newline added below - * Note we don't split 4-byte output chunks over newlines - */ - *outp++ = '\n'; - olen++; - thisLine = 0; - } - } - *outp++ = '\n'; - *outp = '\0'; - olen += 2; - *outlen = olen; - return outbuf; -} - -static inline int isWhite(unsigned char c) -{ - switch(c) { - case '\n': - case '\r': - case ' ': - case '\t': - case '\0': - return 1; - default: - return 0; - } -} - -/* - * Strip off all whitespace from a (supposedly) enc64-format string. - * Returns a malloc'd string. - */ -static unsigned char *stringCleanse(const unsigned char *inbuf, - unsigned inlen, - unsigned *outlen) -{ - unsigned char *news; // cleansed inbuf - unsigned newsDex; // index into news - unsigned i; - - news = (unsigned char*)malloc(inlen); - newsDex = 0; - for(i=0; i 0) { - goto errorOut; - } - } - else { - goto errorOut; - } - } else if (*bp & 0x80 || (c3 = asctobin[*bp]) & 0x80) { - goto errorOut; - } else { - bp++; - inlen--; - if (*bp == PAD) { - /* - * Three input bytes, two output - */ - c4 = 0; - thisOlen = 2; - if (c3 & 3) { - goto errorOut; - } - } else if (*bp & 0x80 || (c4 = asctobin[*bp]) & 0x80) { - goto errorOut; - } else { - /* - * Normal non-pad case - */ - thisOlen = 3; - } - bp++; - inlen--; - } - j = (c1 << 2) | (c2 >> 4); - *outp++ = j; - if(thisOlen > 1) { - j = (c2 << 4) | (c3 >> 2); - *outp++ = j; - if(thisOlen == 3) { - j = (c3 << 6) | c4; - *outp++ = j; - } - } - olen += thisOlen; - } - free(news); - *outlen = olen; - return outbuf; /* normal return */ - -errorOut: - free(news); - free(outbuf); - return (unsigned char*) NULL; -} - -/* - * Determine if specified input data is valid enc64 format. Returns 1 - * if valid, 0 if not. - * This doesn't do a full enc64 parse job; it scans for legal characters - * and proper sync when a possible pad is found. - */ -int cuIsValidEnc64(const unsigned char *inbuf, - unsigned inlen) -{ - int padChars = 0; // running count of PAD chars - int validEncChars = 0; - unsigned char c; - - /* - * -- scan inbuf - * -- skip whitespace - * -- count valid chars - * -- ensure not more than 2 PAD chars, only at end - * -- ensure valid chars mod 4 == 0 - */ - - while(inlen) { - c = *inbuf++; - inlen--; - if(isWhite(c)) { - continue; - } - if(c == PAD) { - if(++padChars > 2) { - return 0; // max of 2 PAD chars at end - } - } - else if(padChars > 0) { - return 0; // no normal chars after seeing PAD - } - else if((c & 0x80) || ((asctobin[c]) & 0x80)) { - return 0; // invalid encoded char - } - validEncChars++; - } - if((validEncChars & 0x03) != 0) { - return 0; - } - else { - return 1; - } -} diff --git a/libsecurity_cdsa_utils/lib/cuEnc64.h b/libsecurity_cdsa_utils/lib/cuEnc64.h deleted file mode 100644 index 77cb958b..00000000 --- a/libsecurity_cdsa_utils/lib/cuEnc64.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 1998-2003 Apple Computer, Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please - * obtain a copy of the License at http://www.apple.com/publicsource and - * read it before using this file. - * - * This 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. - * - * cuEnc64.h - encode/decode in 64-char IA5 format, per RFC 1421 - */ - -#ifndef _CU_ENC64_H_ -#define _CU_ENC64_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Given input buffer inbuf, length inlen, decode from 64-char IA5 format to - * binary. Result is malloced and returned; its length is returned in *outlen. - * NULL return indicates corrupted input. - */ -unsigned char *cuEnc64(const unsigned char *inbuf, - unsigned inlen, - unsigned *outlen); // RETURNED - -/* - * Enc64, with embedded newlines every lineLen in result. A newline is - * the UNIX \n. Result is mallocd. - */ -unsigned char *cuEnc64WithLines(const unsigned char *inbuf, - unsigned inlen, - unsigned linelen, - unsigned *outlen); // RETURNED - -/* - * Given input buffer inbuf, length inlen, decode from 64-char IA5 format to - * binary. Result is malloced and returned; its length is returned in *outlen. - * NULL return indicates corrupted input. All whitespace in inbuf is - * ignored. - */ -unsigned char *cuDec64(const unsigned char *inbuf, - unsigned inlen, - unsigned *outlen); - -/* - * Determine if specified input data is valid enc64 format. Returns 1 - * if valid, 0 if not. - */ -int cuIsValidEnc64(const unsigned char *inbuf, - unsigned inbufLen); - -#ifdef __cplusplus -} -#endif - -#endif /*_CU_ENC64_H_*/ diff --git a/libsecurity_cdsa_utils/libsecurity_cdsa_utils.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_cdsa_utils/libsecurity_cdsa_utils.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 988e9b5a..00000000 --- a/libsecurity_cdsa_utils/libsecurity_cdsa_utils.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 4CA1FEBD052A3C8100F22E42 - - primary - - - - - diff --git a/libsecurity_checkpw/libsecurity_checkpw.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_checkpw/libsecurity_checkpw.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index c4b3b597..00000000 --- a/libsecurity_checkpw/libsecurity_checkpw.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 1C6C40211121FC0C00031CDE - - primary - - - 1CD90B6611011176008DD07F - - primary - - - 4CA1FEBD052A3C8100F22E42 - - primary - - - - - diff --git a/libsecurity_cms/libsecurity_cms.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_cms/libsecurity_cms.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 988e9b5a..00000000 --- a/libsecurity_cms/libsecurity_cms.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 4CA1FEBD052A3C8100F22E42 - - primary - - - - - diff --git a/libsecurity_codesigning/CodeSigningHelper/main.c b/libsecurity_codesigning/CodeSigningHelper/main.c deleted file mode 100644 index 5069efa3..00000000 --- a/libsecurity_codesigning/CodeSigningHelper/main.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (c) 2012 Apple Computer, 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@ - */ - -/* - * A simple XPCService that returns the Info.plist for a specific pid, - * the use-case is is for service that is not running as the user or - * in a sandbox and can't access the file directly. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static CFDataRef -CopyDataFromURL(CFURLRef url) -{ - CFReadStreamRef stream = CFReadStreamCreateWithFile(NULL, url); - if (stream == NULL) - return NULL; - - if (!CFReadStreamOpen(stream)) { - CFRelease(stream); - return NULL; - } - - CFMutableDataRef data = CFDataCreateMutable(NULL, 0); - if (data == NULL) { - CFRelease(stream); - return NULL; - } - - UInt8 buf[4096]; - - while (1) { - /* limit to 100k */ - if (CFDataGetLength(data) > 100 * 1024) { - syslog(LOG_ERR, "refusing to handle back Info.plist that is more then 100K"); - CFRelease(stream); - CFRelease(data); - return NULL; - } - CFIndex readBytes = CFReadStreamRead(stream, buf, sizeof(buf)); - if (readBytes == 0) { - break; - } else if (readBytes <= 0) { - CFRelease(data); - CFRelease(stream); - return NULL; - } - - assert(readBytes <= sizeof(buf)); - CFDataAppendBytes(data, (void *)buf, readBytes); - } - - CFReadStreamClose(stream); - CFRelease(stream); - - return data; -} - -static void -fetchData(xpc_connection_t peer, xpc_object_t event) -{ - CFBundleRef bundle = NULL; - char path[MAXPATHLEN]; - pid_t pid; - - pid = (pid_t)xpc_dictionary_get_int64(event, "pid"); - if (pid <= 0) - return; - - xpc_object_t reply = xpc_dictionary_create_reply(event); - if (reply == NULL) - return; - - if (proc_pidpath(pid, path, sizeof(path)) == 0) { - xpc_dictionary_set_string(reply, "error", "no process for that pid"); - goto send; - } - path[sizeof(path) - 1] = '\0'; - - CFURLRef url = CFURLCreateFromFileSystemRepresentation(NULL, (const uint8_t *)path, strlen(path), 0); - if (url == NULL) { - xpc_dictionary_set_string(reply, "error", "failed to create URL"); - goto send; - } - - bundle = _CFBundleCreateWithExecutableURLIfMightBeBundle(NULL, url); - CFRelease(url); - if (bundle == NULL) { - xpc_dictionary_set_string(reply, "error", "Failed to create a bundle"); - goto send; - } - - CFURLRef infoPlistURL = _CFBundleCopyInfoPlistURL(bundle); - if (infoPlistURL == NULL) { - xpc_dictionary_set_string(reply, "error", "Info.plist missing"); - goto send; - } - - CFDataRef data = CopyDataFromURL(infoPlistURL); - CFRelease(infoPlistURL); - if (data == NULL) { - xpc_dictionary_set_string(reply, "error", "can't get content of Info.plist"); - goto send; - } - - xpc_dictionary_set_data(reply, "infoPlist", CFDataGetBytePtr(data), CFDataGetLength(data)); - CFRelease(data); - - CFURLRef bundleURL = CFBundleCopyBundleURL(bundle); - if (bundleURL == NULL) - goto send; - - data = CFURLCreateData(NULL, bundleURL, kCFStringEncodingUTF8, true); - CFRelease(bundleURL); - if (data == NULL) - goto send; - - xpc_dictionary_set_data(reply, "bundleURL", CFDataGetBytePtr(data), CFDataGetLength(data)); - CFRelease(data); - -send: - if (bundle) - CFRelease(bundle); - xpc_connection_send_message(peer, reply); - xpc_release(reply); -} - - -static void CodeSigningHelper_peer_event_handler(xpc_connection_t peer, xpc_object_t event) -{ - xpc_type_t type = xpc_get_type(event); - if (type == XPC_TYPE_ERROR) - return; - - assert(type == XPC_TYPE_DICTIONARY); - - const char *cmd = xpc_dictionary_get_string(event, "command"); - if (cmd == NULL) { - xpc_connection_cancel(peer); - } else if (strcmp(cmd, "fetchData") == 0) - fetchData(peer, event); - else { - syslog(LOG_ERR, "peer sent invalid command %s", cmd); - xpc_connection_cancel(peer); - } -} - -static void CodeSigningHelper_event_handler(xpc_connection_t peer) -{ - xpc_connection_set_event_handler(peer, ^(xpc_object_t event) { - CodeSigningHelper_peer_event_handler(peer, event); - }); - xpc_connection_resume(peer); -} - -int main(int argc, const char *argv[]) -{ - char *error = NULL; - if (sandbox_init("com.apple.CodeSigningHelper", SANDBOX_NAMED, &error)) { - syslog(LOG_ERR, "failed to enter sandbox: %s", error); - exit(EXIT_FAILURE); - } - xpc_main(CodeSigningHelper_event_handler); - return 0; -} - diff --git a/libsecurity_codesigning/lib/SecTask.c b/libsecurity_codesigning/lib/SecTask.c deleted file mode 100644 index e30eb909..00000000 --- a/libsecurity_codesigning/lib/SecTask.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright (c) 2009-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 -#include -#include -#include -#include -#include -#include -#include -#include - -#include "SecCode.h" -#include "SecCodePriv.h" -#include "SecRequirement.h" - -#include "SecTask.h" -#include "SecTaskPriv.h" - - -struct __SecTask { - CFRuntimeBase base; - - pid_t pid; - - audit_token_t *token; - audit_token_t token_storage; - - /* Track whether we've loaded entitlements independently since after the - * load, entitlements may legitimately be NULL */ - Boolean entitlementsLoaded; - CFDictionaryRef entitlements; -}; - -enum { - kSecCodeMagicEntitlement = 0xfade7171, /* entitlement blob */ -}; - - -CFTypeID _kSecTaskTypeID = _kCFRuntimeNotATypeID; - -static void SecTaskFinalize(CFTypeRef cfTask) -{ - SecTaskRef task = (SecTaskRef) cfTask; - - if (task->entitlements != NULL) { - CFRelease(task->entitlements); - task->entitlements = NULL; - } -} - - -// Define PRIdPID (proper printf format string for pid_t) -#define PRIdPID PRId32 - -static CFStringRef SecTaskCopyDebugDescription(CFTypeRef cfTask) -{ - SecTaskRef task = (SecTaskRef) cfTask; - const char *task_name; - int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, task->pid}; - struct kinfo_proc kp; - size_t len = sizeof(kp); - if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1 || len == 0) - task_name = strerror(errno); - else - task_name = kp.kp_proc.p_comm; - - return CFStringCreateWithFormat(CFGetAllocator(task), NULL, CFSTR("%s[%" PRIdPID "]"), task_name, task->pid); -} - -static void SecTaskRegisterClass(void) -{ - static const CFRuntimeClass SecTaskClass = { - .version = 0, - .className = "SecTask", - .init = NULL, - .copy = NULL, - .finalize = SecTaskFinalize, - .equal = NULL, - .hash = NULL, - .copyFormattingDesc = NULL, - .copyDebugDesc = SecTaskCopyDebugDescription, - }; - - _kSecTaskTypeID = _CFRuntimeRegisterClass(&SecTaskClass); -} - -CFTypeID SecTaskGetTypeID(void) -{ - static pthread_once_t secTaskRegisterClassOnce = PTHREAD_ONCE_INIT; - - /* Register the class with the CF runtime the first time through */ - pthread_once(&secTaskRegisterClassOnce, SecTaskRegisterClass); - - return _kSecTaskTypeID; -} - -static SecTaskRef SecTaskCreateWithPID(CFAllocatorRef allocator, pid_t pid) -{ - CFIndex extra = sizeof(struct __SecTask) - sizeof(CFRuntimeBase); - SecTaskRef task = (SecTaskRef) _CFRuntimeCreateInstance(allocator, SecTaskGetTypeID(), extra, NULL); - if (task != NULL) { - task->pid = pid; - task->entitlementsLoaded = false; - task->entitlements = NULL; - } - - return task; -} - -SecTaskRef SecTaskCreateWithAuditToken(CFAllocatorRef allocator, audit_token_t token) -{ - SecTaskRef task; - - task = SecTaskCreateWithPID(allocator, audit_token_to_pid(token)); - if (task != NULL) { -#if 0 - task->token_storage = token; - task->token = &task->token_storage; -#endif - } - - return task; -} - -SecTaskRef SecTaskCreateFromSelf(CFAllocatorRef allocator) -{ - return SecTaskCreateWithPID(allocator, getpid()); -} - -/* - * Determine if the given task meets a specified requirement. - */ -OSStatus -SecTaskValidateForRequirement(SecTaskRef task, CFStringRef requirement) -{ - OSStatus status; - SecCodeRef code = NULL; - SecRequirementRef req = NULL; - pid_t pid = task->pid; - if (pid <= 0) { - return errSecParam; - } - status = SecCodeCreateWithPID(pid, kSecCSDefaultFlags, &code); - //syslog(LOG_NOTICE, "SecTaskValidateForRequirement: SecCodeCreateWithPID=%d", status); - if (!status) { - status = SecRequirementCreateWithString(requirement, - kSecCSDefaultFlags, &req); - //syslog(LOG_NOTICE, "SecTaskValidateForRequirement: SecRequirementCreateWithString=%d", status); - } - if (!status) { - status = SecCodeCheckValidity(code, kSecCSDefaultFlags, req); - //syslog(LOG_NOTICE, "SecTaskValidateForRequirement: SecCodeCheckValidity=%d", status); - } - if (req) - CFRelease(req); - if (code) - CFRelease(code); - - return status; -} - -static CFRange myMakeRange(CFIndex loc, CFIndex len) { - CFRange r = {.location = loc, .length = len }; - return r; -} -struct csheader { - uint32_t magic; - uint32_t length; -}; - -static int -csops_task(SecTaskRef task, int ops, void *blob, size_t size) -{ - if (task->token) - return csops_audittoken(task->pid, ops, blob, size, task->token); - else - return csops(task->pid, ops, blob, size); -} - -static int SecTaskLoadEntitlements(SecTaskRef task, CFErrorRef *error) -{ - CFMutableDataRef data = NULL; - struct csheader header; - uint32_t bufferlen; - int ret; - - ret = csops_task(task, CS_OPS_ENTITLEMENTS_BLOB, &header, sizeof(header)); - if (ret != -1 || errno != ERANGE) { - /* no entitlements */ - task->entitlementsLoaded = true; - return 0; - } - - bufferlen = ntohl(header.length); - /* check for insane values */ - if (bufferlen > 1024 * 1024 || bufferlen < 8) { - ret = EINVAL; - goto out; - } - data = CFDataCreateMutable(NULL, bufferlen); - if (data == NULL) { - ret = ENOMEM; - goto out; - } - CFDataSetLength(data, bufferlen); - ret = csops_task(task, CS_OPS_ENTITLEMENTS_BLOB, CFDataGetMutableBytePtr(data), bufferlen); - if (ret) { - ret = errno; - goto out; - } - CFDataDeleteBytes(data, myMakeRange(0, 8)); - task->entitlements = CFPropertyListCreateWithData(NULL, data, 0, NULL, error); - task->entitlementsLoaded = true; - out: - if (data) - CFRelease(data); - if (ret && error) - *error = CFErrorCreate(NULL, kCFErrorDomainMach, ret, NULL); - - return ret; -} - -CFTypeRef SecTaskCopyValueForEntitlement(SecTaskRef task, CFStringRef entitlement, CFErrorRef *error) -{ - /* Load entitlements if necessary */ - if (task->entitlementsLoaded == false) { - SecTaskLoadEntitlements(task, error); - } - - CFTypeRef value = NULL; - if (task->entitlements != NULL) { - value = CFDictionaryGetValue(task->entitlements, entitlement); - - /* Return something the caller must release */ - if (value != NULL) { - CFRetain(value); - } - } - - return value; -} - -CFDictionaryRef SecTaskCopyValuesForEntitlements(SecTaskRef task, CFArrayRef entitlements, CFErrorRef *error) -{ - /* Load entitlements if necessary */ - if (task->entitlementsLoaded == false) { - SecTaskLoadEntitlements(task, error); - } - - /* Iterate over the passed in entitlements, populating the dictionary - * If entitlements were loaded but none were present, return an empty - * dictionary */ - CFMutableDictionaryRef values = NULL; - if (task->entitlementsLoaded == true) { - - CFIndex i, count = CFArrayGetCount(entitlements); - values = CFDictionaryCreateMutable(CFGetAllocator(task), count, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (task->entitlements != NULL) { - for (i = 0; i < count; i++) { - CFStringRef entitlement = CFArrayGetValueAtIndex(entitlements, i); - CFTypeRef value = CFDictionaryGetValue(task->entitlements, entitlement); - if (value != NULL) { - CFDictionarySetValue(values, entitlement, value); - } - } - } - } - - return values; -} diff --git a/libsecurity_codesigning/lib/SecTask.h b/libsecurity_codesigning/lib/SecTask.h deleted file mode 100644 index 7563b661..00000000 --- a/libsecurity_codesigning/lib/SecTask.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2008-2009 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _SECURITY_SECTASK_H_ -#define _SECURITY_SECTASK_H_ - -#include -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -/*! - @typedef SecTaskRef - @abstract CFType used for representing a task -*/ -typedef struct __SecTask *SecTaskRef; - -/*! - @function SecTaskGetTypeID - @abstract Returns the type ID for CF instances of SecTask. - @result A CFTypeID for SecTask -*/ -CFTypeID SecTaskGetTypeID(void); - -/*! - @function SecTaskCreateWithAuditToken - @abstract Create a SecTask object for the task that sent the mach message - represented by the audit token. - @param token The audit token of a mach message - @result The newly created SecTask object or NULL on error. The caller must - CFRelease the returned object. -*/ -SecTaskRef SecTaskCreateWithAuditToken(CFAllocatorRef allocator, audit_token_t token); - -/*! - @function SecTaskCreateFromSelf - @abstract Create a SecTask object for the current task. - @result The newly created SecTask object or NULL on error. The caller must - CFRelease the returned object. -*/ -SecTaskRef SecTaskCreateFromSelf(CFAllocatorRef allocator); - -/*! - @function SecTaskCopyValueForEntitlement - @abstract Returns the value of a single entitlement for the represented - task. - @param task A previously created SecTask object - @param entitlement The name of the entitlement to be fetched - @param error On a NULL return, this may be contain a CFError describing - the problem. This argument may be NULL if the caller is not interested in - detailed errors. - @result The value of the specified entitlement for the process or NULL if - the entitlement value could not be retrieved. The type of the returned - value will depend on the entitlement specified. The caller must release - the returned object. - @discussion A NULL return may indicate an error, or it may indicate that - the entitlement is simply not present. In the latter case, no CFError is - returned. -*/ -CFTypeRef SecTaskCopyValueForEntitlement(SecTaskRef task, CFStringRef entitlement, CFErrorRef *error); - -/*! - @function SecTaskCopyValuesForEntitlements - @abstract Returns the values of multiple entitlements for the represented - task. - @param task A previously created SecTask object - @param entitlements An array of entitlement names to be fetched - @param error On a NULL return, this will contain a CFError describing - the problem. This argument may be NULL if the caller is not interested in - detailed errors. If a requested entitlement is not present for the - returned dictionary, the entitlement is not set on the task. The caller - must CFRelease the returned value -*/ -CFDictionaryRef SecTaskCopyValuesForEntitlements(SecTaskRef task, CFArrayRef entitlements, CFErrorRef *error); - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECTASK_H_ */ diff --git a/libsecurity_codesigning/lib/cfmdiskrep.cpp b/libsecurity_codesigning/lib/cfmdiskrep.cpp deleted file mode 100644 index 465b6f92..00000000 --- a/libsecurity_codesigning/lib/cfmdiskrep.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2007 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@ - */ - -// -// cfmdiskrep - single-file CFM (PEF) executable disk representation -// -#include "cfmdiskrep.h" -#include - - -namespace Security { -namespace CodeSigning { - -using namespace UnixPlusPlus; - - -// -// Everything's lazy in here -// -CFMDiskRep::CFMDiskRep(const char *path) - : SingleDiskRep(path), mTriedRead(false) -{ - CODESIGN_DISKREP_CREATE_CFM(this, (char*)path); -} - -CFMDiskRep::~CFMDiskRep() -{ - if (mTriedRead) - delete mSigningData; -} - - -// -// CFM filter heuristic. -// We look for the PEF header within the first scanLength bytes -// of the file's data fork, at certain alignment boundaries (probably -// conservative). -// -bool CFMDiskRep::candidate(FileDesc &fd) -{ - static const char magicMarker[] = "Joy!peffpwpc"; - static const size_t magicLength = 12; - static const size_t scanLength = 128; - static const size_t scanAlignment = 4; - - char marker[scanLength]; - if (fd.read(marker, scanLength, 0) == scanLength) - for (size_t p = 0; p <= scanLength - magicLength; p += scanAlignment) - if (!memcmp(marker+p, magicMarker, magicLength)) - return true; - return false; -} - - -// -// Extract and return a component by slot number. -// If we have a Mach-O binary, use embedded components. -// Otherwise, look for and return the extended attribute, if any. -// -CFDataRef CFMDiskRep::component(CodeDirectory::SpecialSlot slot) -{ - if (!mTriedRead) - readSigningData(); - if (mSigningData) - return mSigningData->component(slot); - else - return NULL; -} - - -// -// The signing limit is the start of the signature if present, -// or the end of the file otherwise. -// -size_t CFMDiskRep::signingLimit() -{ - readSigningData(); - if (mSigningData) - return mSigningOffset; - else - return fd().fileSize(); -} - - -// -// Various other aspects of our DiskRep personality. -// -string CFMDiskRep::format() -{ - return "CFM/PEF binary"; -} - - -// -// Discard cached information -// -void CFMDiskRep::flush() -{ - mTriedRead = false; - ::free(mSigningData); -} - - -// -// In Mac OS X, a CFM binary must always be managed by the LaunchCFMApp -// system tool. Thus, we recommend that this be required as a host. -// -static const uint8_t cfm_ireqs[] = { // host => anchor apple and identifier com.apple.LaunchCFMApp - 0xfa, 0xde, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x14, 0xfa, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, - 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68, - 0x43, 0x46, 0x4d, 0x41, 0x70, 0x70, 0x00, 0x00, -}; - -const Requirements *CFMDiskRep::defaultRequirements(const Architecture *, const SigningContext &) -{ - return ((const Requirements *)cfm_ireqs)->clone(); // need to pass ownership -} - - -// -// Default to system-paged signing -// -size_t CFMDiskRep::pageSize(const SigningContext &) -{ - return segmentedPageSize; -} - - -// -// Locate, read, and cache embedded signing data from the CFM binary. -// -void CFMDiskRep::readSigningData() -{ - if (!mTriedRead) { // try it once - mSigningData = NULL; // preset failure - mTriedRead = true; // we've tried (and perhaps failed) - - FileDesc &fd = this->fd(); - fd.seek(fd.fileSize() - sizeof(Sentinel)); - Sentinel sentinel; - if (fd.read(&sentinel, sizeof(sentinel), fd.fileSize() - sizeof(Sentinel)) == sizeof(Sentinel)) - if (sentinel.magic == EmbeddedSignatureBlob::typeMagic) { - mSigningOffset = sentinel.offset; - if ((mSigningData = EmbeddedSignatureBlob::readBlob(fd, mSigningOffset))) - secdebug("cfmrep", "%zd signing bytes in %d blob(s) from %s(CFM)", - mSigningData->length(), mSigningData->count(), - mainExecutablePath().c_str()); - else - secdebug("cfmrep", "failed to read signing bytes from %s(CFM)", - mainExecutablePath().c_str()); - } - } -} - - -// -// CFMDiskRep::Writers -// -DiskRep::Writer *CFMDiskRep::writer() -{ - return new Writer(this); -} - -CFMDiskRep::Writer::~Writer() -{ - delete mSigningData; -} - - -// -// Write a component. -// Note that this isn't concerned with Mach-O writing; this is handled at -// a much higher level. If we're called, it's extended attribute time. -// -void CFMDiskRep::Writer::component(CodeDirectory::SpecialSlot slot, CFDataRef data) -{ - EmbeddedSignatureBlob::Maker::component(slot, data); -} - - -// -// Append the superblob we built to the CFM binary. -// Note: Aligning the signing blob to a 16-byte boundary is not strictly necessary, -// but it's what the Mach-O case does, and it probably improves performance a bit. -// -void CFMDiskRep::Writer::flush() -{ - delete mSigningData; // ditch previous blob just in case - mSigningData = Maker::make(); // assemble new signature SuperBlob - size_t start = LowLevelMemoryUtilities::alignUp(rep->signingLimit(), 16); - Sentinel sentinel; - sentinel.magic = EmbeddedSignatureBlob::typeMagic; - sentinel.offset = (uint32_t)start; - AutoFileDesc fd(rep->path(), O_RDWR); - fd.seek(start); - fd.writeAll(mSigningData, mSigningData->length()); - fd.writeAll(&sentinel, sizeof(sentinel)); -} - - -} // end namespace CodeSigning -} // end namespace Security diff --git a/libsecurity_codesigning/lib/cfmdiskrep.h b/libsecurity_codesigning/lib/cfmdiskrep.h deleted file mode 100644 index 3ea17ab8..00000000 --- a/libsecurity_codesigning/lib/cfmdiskrep.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2007 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@ - */ - -// -// cfmdiskrep - single-file CFM (PEF) executable disk representation -// -#ifndef _H_CFMDISKREP -#define _H_CFMDISKREP - -#include "singlediskrep.h" -#include "sigblob.h" -#include "signerutils.h" -#include -#include - -namespace Security { -namespace CodeSigning { - - -// -// A CFMDiskRep represents a single code file on disk containing a CFM (PEF) -// binary. It is considered self-contained, and does not depend on any other -// files in the system (even if it may be part of a larger bundle etc.) -// -// CFM is considered a legacy format that is not generated by Apple, but still -// supported for backward compatibility. This DiskRep supports writing signing -// data into the executable, using a simple back-of-file frame. It does not -// support embedded Info.plists or any other fancy stuff. -// -// This DiskRep does not support resource sealing. -// -class CFMDiskRep : public SingleDiskRep { -public: - CFMDiskRep(const char *path); - ~CFMDiskRep(); - - CFDataRef component(CodeDirectory::SpecialSlot slot); - size_t signingLimit(); - std::string format(); - void flush(); - - const Requirements *defaultRequirements(const Architecture *arch, const SigningContext &ctx); - size_t pageSize(const SigningContext &ctx); - - static bool candidate(UnixPlusPlus::FileDesc &fd); // could this reasonably be a CFM code? - -public: - // - // Signing sticks this structure at the very end of the file - // - struct Sentinel { - Endian magic; // EmbeddedSignatureBlob::magic() - Endian offset; // file absolute offset of EmbeddedSignatureBlob - }; - -public: - DiskRep::Writer *writer(); - class Writer; - friend class Writer; - -protected: - void readSigningData(); // read and cache signing data - -private: - bool mTriedRead; // tried to get signing data - size_t mSigningOffset; // where we found the signing data - EmbeddedSignatureBlob *mSigningData; // cached signing data -}; - - -// -// The write side of a FileDiskRep -// -class CFMDiskRep::Writer : public DiskRep::Writer, private EmbeddedSignatureBlob::Maker { - friend class CFMDiskRep; -public: - Writer(CFMDiskRep *r) : rep(r), mSigningData(NULL) { } - ~Writer(); - - void component(CodeDirectory::SpecialSlot slot, CFDataRef data); - virtual void flush(); - -protected: - RefPointer rep; - EmbeddedSignatureBlob *mSigningData; -}; - - -} // end namespace CodeSigning -} // end namespace Security - -#endif // !_H_CFMDISKREP diff --git a/libsecurity_codesigning/lib/opaquewhitelist.cpp b/libsecurity_codesigning/lib/opaquewhitelist.cpp deleted file mode 100644 index ae5b6e2a..00000000 --- a/libsecurity_codesigning/lib/opaquewhitelist.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright (c) 2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#include "opaquewhitelist.h" -#include "csutilities.h" -#include "StaticCode.h" -#include -#include -#include -#include -#include -#include -#include - -namespace Security { -namespace CodeSigning { - -using namespace SQLite; - - -static void traceHash(MessageTrace &trace, const char *key, CFDataRef hash); -static void attachOpaque(SecStaticCodeRef code); - - -// -// Open the database -// -OpaqueWhitelist::OpaqueWhitelist(const char *path, int flags) - : SQLite::Database(path ? path : opaqueDatabase, flags) -{ - SQLite::Statement createConditions(*this, - "CREATE TABLE IF NOT EXISTS conditions (" - " label text," - " weight real not null unique," - " source text," - " identifier text," - " version text," - " conditions text not null);" - ); - createConditions.execute(); - -} - -OpaqueWhitelist::~OpaqueWhitelist() -{ /* virtual */ } - - -// -// Check if a code object is whitelisted -// -bool OpaqueWhitelist::contains(SecStaticCodeRef codeRef, OSStatus reason, bool trace) -{ - // make our own copy of the code object, so we can poke at it without disturbing the original - SecPointer code = new SecStaticCode(SecStaticCode::requiredStatic(codeRef)->diskRep()); - - CFCopyRef current = code->cdHash(); // current cdhash - CFDataRef opaque = NULL; // holds computed opaque cdhash - bool match = false; // holds final result - - if (!current) - return false; // unsigned - - // collect auxiliary information for trace - CFRef info; - std::string team = ""; - CFStringRef cfVersion = NULL, cfShortVersion = NULL, cfExecutable = NULL; - if (errSecSuccess == SecCodeCopySigningInformation(code->handle(false), kSecCSSigningInformation, &info.aref())) { - if (CFStringRef cfTeam = CFStringRef(CFDictionaryGetValue(info, kSecCodeInfoTeamIdentifier))) - team = cfString(cfTeam); - if (CFDictionaryRef infoPlist = CFDictionaryRef(CFDictionaryGetValue(info, kSecCodeInfoPList))) { - if (CFTypeRef version = CFDictionaryGetValue(infoPlist, kCFBundleVersionKey)) - if (CFGetTypeID(version) == CFStringGetTypeID()) - cfVersion = CFStringRef(version); - if (CFTypeRef shortVersion = CFDictionaryGetValue(infoPlist, _kCFBundleShortVersionStringKey)) - if (CFGetTypeID(shortVersion) == CFStringGetTypeID()) - cfShortVersion = CFStringRef(shortVersion); - if (CFTypeRef executable = CFDictionaryGetValue(infoPlist, kCFBundleExecutableKey)) - if (CFGetTypeID(executable) == CFStringGetTypeID()) - cfExecutable = CFStringRef(executable); - } - } - - // compute and attach opaque signature - attachOpaque(code->handle(false)); - opaque = code->cdHash(); - - // lookup current cdhash in whitelist - SQLite::Statement lookup(*this, "SELECT opaque FROM whitelist WHERE current=:current"); - lookup.bind(":current") = current.get(); - while (lookup.nextRow()) { - CFRef expected = lookup[0].data(); - if (CFEqual(opaque, expected)) { - match = true; // actual opaque cdhash matches expected - break; - } - } - - if (trace) { - // send a trace indicating the result - MessageTrace trace("com.apple.security.assessment.whitelist2", code->identifier().c_str()); - traceHash(trace, "signature2", current); - traceHash(trace, "signature3", opaque); - trace.add("result", match ? "pass" : "fail"); - trace.add("reason", "%d", reason); - if (!team.empty()) - trace.add("teamid", "%s", team.c_str()); - if (cfVersion) - trace.add("version", "%s", cfString(cfVersion).c_str()); - if (cfShortVersion) - trace.add("version2", "%s", cfString(cfShortVersion).c_str()); - if (cfExecutable) - trace.add("execname", "%s", cfString(cfExecutable).c_str()); - trace.send(""); - } - - return match; -} - - -// -// Obtain special validation conditions for a static code, based on database configuration. -// -CFDictionaryRef OpaqueWhitelist::validationConditionsFor(SecStaticCodeRef code) -{ - // figure out which team key to use - std::string team = "UNKNOWN"; - CFStringRef cfId = NULL; - CFStringRef cfVersion = NULL; - CFRef info; // holds lifetimes for the above - if (errSecSuccess == SecCodeCopySigningInformation(code, kSecCSSigningInformation, &info.aref())) { - if (CFStringRef cfTeam = CFStringRef(CFDictionaryGetValue(info, kSecCodeInfoTeamIdentifier))) - team = cfString(cfTeam); - cfId = CFStringRef(CFDictionaryGetValue(info, kSecCodeInfoIdentifier)); - if (CFDictionaryRef infoPlist = CFDictionaryRef(CFDictionaryGetValue(info, kSecCodeInfoPList))) - if (CFTypeRef version = CFDictionaryGetValue(infoPlist, _kCFBundleShortVersionStringKey)) - if (CFGetTypeID(version) == CFStringGetTypeID()) - cfVersion = CFStringRef(version); - } - if (cfId == NULL) // unsigned; punt - return NULL; - - // find the highest weight matching condition. We perform no merging and the heaviest rule wins - SQLite::Statement matches(*this, - "SELECT conditions FROM conditions" - " WHERE (source = :source or source IS NULL)" - " AND (identifier = :identifier or identifier is NULL)" - " AND ((:version IS NULL AND version IS NULL) OR (version = :version OR version IS NULL))" - " ORDER BY weight DESC" - " LIMIT 1" - ); - matches.bind(":source") = team; - matches.bind(":identifier") = cfString(cfId); - if (cfVersion) - matches.bind(":version") = cfString(cfVersion); - if (matches.nextRow()) { - CFTemp conditions((const char*)matches[0]); - return conditions.yield(); - } - // no matches - return NULL; -} - - -// -// Convert a SHA1 hash to hex and add to a trace -// -static void traceHash(MessageTrace &trace, const char *key, CFDataRef hash) -{ - if (CFDataGetLength(hash) != sizeof(SHA1::Digest)) { - trace.add(key, "(unknown format)"); - } else { - const UInt8 *bytes = CFDataGetBytePtr(hash); - char s[2 * SHA1::digestLength + 1]; - for (unsigned n = 0; n < SHA1::digestLength; n++) - sprintf(&s[2*n], "%2.2x", bytes[n]); - trace.add(key, s); - } -} - - -// -// Add a code object to the whitelist -// -void OpaqueWhitelist::add(SecStaticCodeRef codeRef) -{ - // make our own copy of the code object - SecPointer code = new SecStaticCode(SecStaticCode::requiredStatic(codeRef)->diskRep()); - - CFCopyRef current = code->cdHash(); - attachOpaque(code->handle(false)); // compute and attach an opaque signature - CFDataRef opaque = code->cdHash(); - - SQLite::Statement insert(*this, "INSERT OR REPLACE INTO whitelist (current,opaque) VALUES (:current, :opaque)"); - insert.bind(":current") = current.get(); - insert.bind(":opaque") = opaque; - insert.execute(); -} - - -// -// Generate and attach an ad-hoc opaque signature -// -static void attachOpaque(SecStaticCodeRef code) -{ - CFTemp rules("{" // same resource rules as used for collection - "rules={" - "'^.*' = #T" - "'^Info\\.plist$' = {omit=#T,weight=10}" - "},rules2={" - "'^(Frameworks|SharedFrameworks|Plugins|Plug-ins|XPCServices|Helpers|MacOS)/' = {nested=#T, weight=0}" - "'^.*' = #T" - "'^Info\\.plist$' = {omit=#T,weight=10}" - "'^[^/]+$' = {top=#T, weight=0}" - "}" - "}"); - - CFRef signature = CFDataCreateMutable(NULL, 0); - CFTemp arguments("{%O=%O, %O=#N, %O=%O}", - kSecCodeSignerDetached, signature.get(), - kSecCodeSignerIdentity, /* kCFNull, */ - kSecCodeSignerResourceRules, rules.get()); - CFRef signer; - SecCSFlags flags = kSecCSSignOpaque | kSecCSSignNoV1 | kSecCSSignBundleRoot; - MacOSError::check(SecCodeSignerCreate(arguments, flags, &signer.aref())); - MacOSError::check(SecCodeSignerAddSignature(signer, code, kSecCSDefaultFlags)); - MacOSError::check(SecCodeSetDetachedSignature(code, signature, kSecCSDefaultFlags)); -} - - -} // end namespace CodeSigning -} // end namespace Security diff --git a/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj b/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj deleted file mode 100644 index fa010c9a..00000000 --- a/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj +++ /dev/null @@ -1,2043 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXAggregateTarget section */ - C26AC0EB143BCF01001C98CE /* SystemPolicy */ = { - isa = PBXAggregateTarget; - buildConfigurationList = C26AC0EC143BCF01001C98CE /* Build configuration list for PBXAggregateTarget "SystemPolicy" */; - buildPhases = ( - C26AC0F0143BCF18001C98CE /* ShellScript */, - C26AC0F4143BD1C4001C98CE /* CopyFiles */, - C2F24DFE14BCBBF200309FCD /* ShellScript */, - C2578CB11579627200D4FE48 /* CopyFiles */, - C25C18CD15CB0C470007A2DE /* CopyFiles */, - C25C18D015CB0FB30007A2DE /* CopyFiles */, - ); - dependencies = ( - ); - name = SystemPolicy; - productName = SystemPolicy; - }; - C26AC7090DAEB3A7005BFB40 /* DTrace */ = { - isa = PBXAggregateTarget; - buildConfigurationList = C26AC70D0DAEB3C6005BFB40 /* Build configuration list for PBXAggregateTarget "DTrace" */; - buildPhases = ( - C26AC7080DAEB3A7005BFB40 /* ShellScript */, - ); - dependencies = ( - ); - name = DTrace; - productName = DTrace; - }; - C2D383B80A23A8C4005C63A2 /* Requirements Language */ = { - isa = PBXAggregateTarget; - buildConfigurationList = C2D383C00A23A8E3005C63A2 /* Build configuration list for PBXAggregateTarget "Requirements Language" */; - buildPhases = ( - C2D383B70A23A8C4005C63A2 /* ShellScript */, - ); - dependencies = ( - ); - name = "Requirements Language"; - productName = "Requirements Language"; - }; - C2E2873F0B5D8F8F009336A0 /* Everything */ = { - isa = PBXAggregateTarget; - buildConfigurationList = C2E287470B5D8FD8009336A0 /* Build configuration list for PBXAggregateTarget "Everything" */; - buildPhases = ( - ); - dependencies = ( - C2E287410B5D8F97009336A0 /* PBXTargetDependency */, - C250F6C50B5EF4E40076098F /* PBXTargetDependency */, - C2E287430B5D8F9A009336A0 /* PBXTargetDependency */, - C26AC0F2143BD02B001C98CE /* PBXTargetDependency */, - C209697015BF53330093035F /* PBXTargetDependency */, - ); - name = Everything; - productName = Everything; - }; -/* End PBXAggregateTarget section */ - -/* Begin PBXBuildFile section */ - 18B965861472FBF6005A4D2E /* reqdumper.h in Headers */ = {isa = PBXBuildFile; fileRef = C21CFC5E0A250D1C006CD5B1 /* reqdumper.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18B965871472FC5B005A4D2E /* requirement.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D383360A237F47005C63A2 /* requirement.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18B965881472FC5B005A4D2E /* reqmaker.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C1DFC20A2F820500D1B02B /* reqmaker.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18B965891472FC5B005A4D2E /* reqreader.h in Headers */ = {isa = PBXBuildFile; fileRef = C2093AA70BB0948000EB8599 /* reqreader.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18B9658A1472FC5B005A4D2E /* reqinterp.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C1DFBA0A2F80EB00D1B02B /* reqinterp.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18B9658B1472FC5B005A4D2E /* reqparser.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D383340A237F47005C63A2 /* reqparser.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18B9658C1472FC9E005A4D2E /* codedirectory.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D383170A237F47005C63A2 /* codedirectory.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 18B965951472FE30005A4D2E /* cdbuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D383150A237F47005C63A2 /* cdbuilder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7A078F651996C1C2003D68DA /* dirscanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A078F631996C1C2003D68DA /* dirscanner.cpp */; }; - 7A078F661996C1C2003D68DA /* dirscanner.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A078F641996C1C2003D68DA /* dirscanner.h */; }; - 7A9DA65C1948D1BA004635E6 /* opaquewhitelist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A9DA65A1948D1BA004635E6 /* opaquewhitelist.cpp */; }; - 7A9DA65D1948D1BA004635E6 /* opaquewhitelist.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A9DA65B1948D1BA004635E6 /* opaquewhitelist.h */; }; - 7ACF261219958B6F00849B25 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2CC30A00B8519CC005FA59D /* CoreFoundation.framework */; }; - BEC3A75C16F78D21003E5634 /* SecTaskPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = BEC3A75B16F78D21003E5634 /* SecTaskPriv.h */; }; - C200424D15D425D9004AE0A1 /* libsecurity_codesigning.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C200424915D425B7004AE0A1 /* libsecurity_codesigning.a */; }; - C200424E15D425D9004AE0A1 /* libsecurity_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C200424A15D425B7004AE0A1 /* libsecurity_utilities.a */; }; - C2093AA80BB0948000EB8599 /* reqreader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2093AA60BB0948000EB8599 /* reqreader.cpp */; }; - C209696415BF52040093035F /* gkunpack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C209696315BF52040093035F /* gkunpack.cpp */; }; - C211070A158C1082001D7F76 /* gkmerge in CopyFiles */ = {isa = PBXBuildFile; fileRef = C2110704158BF5C8001D7F76 /* gkmerge */; }; - C21CFC5F0A250D1C006CD5B1 /* reqdumper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C21CFC5D0A250D1C006CD5B1 /* reqdumper.cpp */; }; - C21EA3DD0AD2F81300E6E31C /* SecCodeSigner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C21EA3DB0AD2F81300E6E31C /* SecCodeSigner.cpp */; }; - C21EA3E30AD2FA0900E6E31C /* CodeSigner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C21EA3E10AD2FA0900E6E31C /* CodeSigner.cpp */; }; - C22463610B86210100626F1B /* antlrplugin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2CC31130B85254F005FA59D /* antlrplugin.cpp */; }; - C2256BDD158BC0F200F72211 /* gkhandmake in CopyFiles */ = {isa = PBXBuildFile; fileRef = C278A19B158AB2C300FA6767 /* gkhandmake */; }; - C2256BDE158BC0F200F72211 /* gklist in CopyFiles */ = {isa = PBXBuildFile; fileRef = C278A19C158AB2C300FA6767 /* gklist */; }; - C236E3D70AD59446000F5140 /* signer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C236E3D50AD59446000F5140 /* signer.cpp */; }; - C236E3DB0AD595C2000F5140 /* signerutils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C236E3D90AD595C2000F5140 /* signerutils.cpp */; }; - C24EABAB1421432800C16AA9 /* policydb.h in Headers */ = {isa = PBXBuildFile; fileRef = C24EABAA1421432800C16AA9 /* policydb.h */; }; - C24EABAD1421433700C16AA9 /* policydb.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C24EABAC1421433700C16AA9 /* policydb.cpp */; }; - C250F6C30B5EF1910076098F /* SecIntegrity.h in Headers */ = {isa = PBXBuildFile; fileRef = C250F6C20B5EF1910076098F /* SecIntegrity.h */; }; - C259DFD60AD6D9BA00C9ACC6 /* sigblob.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C259DFD40AD6D9BA00C9ACC6 /* sigblob.cpp */; }; - C25C18CE15CB0C5C0007A2DE /* gkreport in CopyFiles */ = {isa = PBXBuildFile; fileRef = C25C18C615CB0BC10007A2DE /* gkreport */; }; - C25C18D115CB0FC30007A2DE /* com.apple.gkreport.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = C25C18CF15CB0FA00007A2DE /* com.apple.gkreport.plist */; }; - C26763D714FD9EBE00A46EDF /* drmaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C26763D514FD9EBE00A46EDF /* drmaker.cpp */; }; - C26763D814FD9EBE00A46EDF /* drmaker.h in Headers */ = {isa = PBXBuildFile; fileRef = C26763D614FD9EBE00A46EDF /* drmaker.h */; }; - C26AC0F5143BD1C8001C98CE /* SystemPolicy in CopyFiles */ = {isa = PBXBuildFile; fileRef = C26AC0F3143BD1B3001C98CE /* SystemPolicy */; }; - C26B45C10B8A9C0A003C0ACA /* ucspc in Frameworks */ = {isa = PBXBuildFile; fileRef = C26B45C00B8A9C00003C0ACA /* ucspc */; }; - C26FF62D0E5B375A00F640A0 /* SecIntegrityLib.h in Headers */ = {isa = PBXBuildFile; fileRef = C2CC31040B8523AD005FA59D /* SecIntegrityLib.h */; settings = {ATTRIBUTES = (); }; }; - C26FF62E0E5B375A00F640A0 /* SecCodeHostLib.h in Headers */ = {isa = PBXBuildFile; fileRef = C2BC1F340B580DA7003EC9DC /* SecCodeHostLib.h */; settings = {ATTRIBUTES = (); }; }; - C26FF62F0E5B376B00F640A0 /* CodeSigning.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D383180A237F47005C63A2 /* CodeSigning.h */; settings = {ATTRIBUTES = (); }; }; - C26FF6300E5B376B00F640A0 /* CSCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D3831C0A237F47005C63A2 /* CSCommon.h */; settings = {ATTRIBUTES = (); }; }; - C26FF6310E5B376B00F640A0 /* CSCommonPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D50CDF0E155A4F0059A195 /* CSCommonPriv.h */; settings = {ATTRIBUTES = (); }; }; - C26FF6320E5B376B00F640A0 /* SecCode.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D3831E0A237F47005C63A2 /* SecCode.h */; settings = {ATTRIBUTES = (); }; }; - C26FF6330E5B376B00F640A0 /* SecCodePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2E8AF240DE25CA7000F6D3B /* SecCodePriv.h */; settings = {ATTRIBUTES = (); }; }; - C26FF6340E5B376B00F640A0 /* SecStaticCode.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D383220A237F47005C63A2 /* SecStaticCode.h */; settings = {ATTRIBUTES = (); }; }; - C26FF6350E5B376B00F640A0 /* SecStaticCodePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2E8AF260DE25CA7000F6D3B /* SecStaticCodePriv.h */; settings = {ATTRIBUTES = (); }; }; - C26FF6360E5B376B00F640A0 /* SecRequirement.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D383260A237F47005C63A2 /* SecRequirement.h */; settings = {ATTRIBUTES = (); }; }; - C26FF6370E5B376B00F640A0 /* SecRequirementPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2E8AF250DE25CA7000F6D3B /* SecRequirementPriv.h */; settings = {ATTRIBUTES = (); }; }; - C26FF6380E5B376B00F640A0 /* SecCodeSigner.h in Headers */ = {isa = PBXBuildFile; fileRef = C21EA3DC0AD2F81300E6E31C /* SecCodeSigner.h */; settings = {ATTRIBUTES = (); }; }; - C26FF6390E5B376B00F640A0 /* SecCodeHost.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D383190A237F47005C63A2 /* SecCodeHost.h */; settings = {ATTRIBUTES = (); }; }; - C26FF63A0E5B376B00F640A0 /* SecIntegrity.h in Headers */ = {isa = PBXBuildFile; fileRef = C250F6C20B5EF1910076098F /* SecIntegrity.h */; settings = {ATTRIBUTES = (); }; }; - C273606E1433F09000A9A5FF /* SecAssessment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C273606C1433F09000A9A5FF /* SecAssessment.cpp */; }; - C273606F1433F09000A9A5FF /* SecAssessment.h in Headers */ = {isa = PBXBuildFile; fileRef = C273606D1433F09000A9A5FF /* SecAssessment.h */; settings = {ATTRIBUTES = (); }; }; - C27360D51436866D00A9A5FF /* xpcengine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C27360D41436866C00A9A5FF /* xpcengine.cpp */; }; - C28342E70E366E6800E54360 /* csdatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C28342E40E366E6800E54360 /* csdatabase.cpp */; }; - C28342EE0E36719D00E54360 /* detachedrep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C28342EB0E36719D00E54360 /* detachedrep.cpp */; }; - C29CDE2A1583F46F00A42059 /* gkclear in CopyFiles */ = {isa = PBXBuildFile; fileRef = C2578CC215798D0F00D4FE48 /* gkclear */; }; - C29CDE2B1583F46F00A42059 /* gkgenerate in CopyFiles */ = {isa = PBXBuildFile; fileRef = C2578CC315798D0F00D4FE48 /* gkgenerate */; }; - C29CDE2C1583F46F00A42059 /* gkrecord in CopyFiles */ = {isa = PBXBuildFile; fileRef = C2578CC415798D0F00D4FE48 /* gkrecord */; }; - C2A436150F2133B2007A41A6 /* slcrep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2A436130F2133B2007A41A6 /* slcrep.cpp */; }; - C2A436160F2133B2007A41A6 /* slcrep.h in Headers */ = {isa = PBXBuildFile; fileRef = C2A436140F2133B2007A41A6 /* slcrep.h */; }; - C2A976AA0B8A2E36008B4EA0 /* csutilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2A976A80B8A2E36008B4EA0 /* csutilities.cpp */; }; - C2BC1F350B580DA7003EC9DC /* SecCodeHostLib.h in Headers */ = {isa = PBXBuildFile; fileRef = C2BC1F340B580DA7003EC9DC /* SecCodeHostLib.h */; }; - C2BD519C0A9392FD000FE43D /* machorep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2BD519A0A9392FD000FE43D /* machorep.cpp */; }; - C2BD60FA0AC863FC0057FD3D /* csgeneric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2BD60F80AC863FC0057FD3D /* csgeneric.cpp */; }; - C2C1DF140A2E3D7200D1B02B /* requirement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383350A237F47005C63A2 /* requirement.cpp */; }; - C2C1DFBB0A2F80EB00D1B02B /* reqinterp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2C1DFB90A2F80EB00D1B02B /* reqinterp.cpp */; }; - C2C1DFC30A2F820500D1B02B /* reqmaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2C1DFC10A2F820500D1B02B /* reqmaker.cpp */; }; - C2C3BC5F0BA1D6FE00E869D1 /* cfmdiskrep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2C3BC5D0BA1D6FE00E869D1 /* cfmdiskrep.cpp */; }; - 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 */; }; - 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 */; }; - C2D383440A237F47005C63A2 /* cs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D3831A0A237F47005C63A2 /* cs.cpp */; }; - C2D383470A237F47005C63A2 /* SecCode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D3831D0A237F47005C63A2 /* SecCode.cpp */; }; - C2D383490A237F47005C63A2 /* cskernel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D3831F0A237F47005C63A2 /* cskernel.cpp */; }; - C2D3834B0A237F47005C63A2 /* SecStaticCode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383210A237F47005C63A2 /* SecStaticCode.cpp */; }; - C2D3834D0A237F47005C63A2 /* csprocess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383230A237F47005C63A2 /* csprocess.cpp */; }; - C2D3834F0A237F47005C63A2 /* SecRequirement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383250A237F47005C63A2 /* SecRequirement.cpp */; }; - C2D383510A237F47005C63A2 /* diskrep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383270A237F47005C63A2 /* diskrep.cpp */; }; - C2D383550A237F47005C63A2 /* filediskrep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D3832B0A237F47005C63A2 /* filediskrep.cpp */; }; - C2D383570A237F47005C63A2 /* Code.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D3832D0A237F47005C63A2 /* Code.cpp */; }; - C2D383590A237F47005C63A2 /* kerneldiskrep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D3832F0A237F47005C63A2 /* kerneldiskrep.cpp */; }; - C2D3835B0A237F47005C63A2 /* StaticCode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383310A237F47005C63A2 /* StaticCode.cpp */; }; - C2D3835D0A237F47005C63A2 /* reqparser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383330A237F47005C63A2 /* reqparser.cpp */; }; - C2D383610A237F47005C63A2 /* Requirements.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383370A237F47005C63A2 /* Requirements.cpp */; }; - C2DC2DCA145F594000AD2A3A /* xar++.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2353410145F1B110073F964 /* xar++.cpp */; }; - C2DC2DCB145F5CD000AD2A3A /* policyengine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C27360201432A61900A9A5FF /* policyengine.cpp */; }; - C2E2873D0B5D8D80009336A0 /* SecCodeHostLib.c in Sources */ = {isa = PBXBuildFile; fileRef = C2E2873C0B5D8D80009336A0 /* SecCodeHostLib.c */; }; - C2E911E20ADEBE3200275CB2 /* resources.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2E911E00ADEBE3200275CB2 /* resources.cpp */; }; - C2F4439A14C626D4000A01E6 /* quarantine++.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F4439814C626D4000A01E6 /* quarantine++.cpp */; }; - C2F4439B14C626D4000A01E6 /* quarantine++.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F4439914C626D4000A01E6 /* quarantine++.h */; }; - C2F6566E0BCBFB250078779E /* cserror.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F6566C0BCBFB250078779E /* cserror.cpp */; }; - EB68B111150DAEEA00B4013D /* RequirementLexer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB68B10B150DAEBB00B4013D /* RequirementLexer.cpp */; }; - EB68B112150DAEEA00B4013D /* RequirementParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB68B10D150DAEBB00B4013D /* RequirementParser.cpp */; }; - EB68B133150DB04400B4013D /* RequirementKeywords.h in Headers */ = {isa = PBXBuildFile; fileRef = EB68B10A150DAEBB00B4013D /* RequirementKeywords.h */; }; - EB68B134150DB04400B4013D /* RequirementLexer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EB68B10C150DAEBB00B4013D /* RequirementLexer.hpp */; }; - EB68B135150DB04400B4013D /* RequirementParser.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EB68B10E150DAEBB00B4013D /* RequirementParser.hpp */; }; - EB976FB81684D7C500A68EE6 /* ANTLRUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976F981684D77600A68EE6 /* ANTLRUtil.cpp */; }; - EB976FB91684D7C500A68EE6 /* ASTFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976F991684D77600A68EE6 /* ASTFactory.cpp */; }; - EB976FBA1684D7C500A68EE6 /* ASTNULLType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976F9A1684D77600A68EE6 /* ASTNULLType.cpp */; }; - EB976FBB1684D7C500A68EE6 /* ASTRefCount.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976F9B1684D77600A68EE6 /* ASTRefCount.cpp */; }; - EB976FBC1684D7C500A68EE6 /* BaseAST.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976F9C1684D77600A68EE6 /* BaseAST.cpp */; }; - EB976FBD1684D7C500A68EE6 /* BitSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976F9D1684D77600A68EE6 /* BitSet.cpp */; }; - EB976FBE1684D7C500A68EE6 /* CharBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976F9E1684D77600A68EE6 /* CharBuffer.cpp */; }; - EB976FBF1684D7C500A68EE6 /* CharScanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976F9F1684D77600A68EE6 /* CharScanner.cpp */; }; - EB976FC01684D7C500A68EE6 /* CommonAST.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FA01684D77600A68EE6 /* CommonAST.cpp */; }; - EB976FC11684D7C500A68EE6 /* CommonASTWithHiddenTokens.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FA11684D77600A68EE6 /* CommonASTWithHiddenTokens.cpp */; }; - EB976FC21684D7C500A68EE6 /* CommonHiddenStreamToken.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FA21684D77600A68EE6 /* CommonHiddenStreamToken.cpp */; }; - EB976FC31684D7C500A68EE6 /* CommonToken.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FA31684D77600A68EE6 /* CommonToken.cpp */; }; - EB976FC41684D7C500A68EE6 /* InputBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FA51684D77600A68EE6 /* InputBuffer.cpp */; }; - EB976FC51684D7C500A68EE6 /* LLkParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FA61684D77600A68EE6 /* LLkParser.cpp */; }; - EB976FC61684D7C500A68EE6 /* MismatchedCharException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FA81684D77600A68EE6 /* MismatchedCharException.cpp */; }; - EB976FC71684D7C500A68EE6 /* MismatchedTokenException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FA91684D77600A68EE6 /* MismatchedTokenException.cpp */; }; - EB976FC81684D7C500A68EE6 /* NoViableAltException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FAA1684D77600A68EE6 /* NoViableAltException.cpp */; }; - EB976FC91684D7C500A68EE6 /* NoViableAltForCharException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FAB1684D77600A68EE6 /* NoViableAltForCharException.cpp */; }; - EB976FCA1684D7C500A68EE6 /* Parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FAC1684D77600A68EE6 /* Parser.cpp */; }; - EB976FCB1684D7C500A68EE6 /* RecognitionException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FAD1684D77600A68EE6 /* RecognitionException.cpp */; }; - EB976FCC1684D7C500A68EE6 /* String.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FAE1684D77600A68EE6 /* String.cpp */; }; - EB976FCD1684D7C500A68EE6 /* Token.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FAF1684D77600A68EE6 /* Token.cpp */; }; - EB976FCE1684D7C500A68EE6 /* TokenBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FB01684D77600A68EE6 /* TokenBuffer.cpp */; }; - EB976FCF1684D7C500A68EE6 /* TokenRefCount.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FB11684D77600A68EE6 /* TokenRefCount.cpp */; }; - EB976FD01684D7C500A68EE6 /* TokenStreamBasicFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FB21684D77600A68EE6 /* TokenStreamBasicFilter.cpp */; }; - EB976FD11684D7C500A68EE6 /* TokenStreamHiddenTokenFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FB31684D77600A68EE6 /* TokenStreamHiddenTokenFilter.cpp */; }; - EB976FD21684D7C500A68EE6 /* TokenStreamRewriteEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FB41684D77600A68EE6 /* TokenStreamRewriteEngine.cpp */; }; - EB976FD31684D7C500A68EE6 /* TokenStreamSelector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FB51684D77600A68EE6 /* TokenStreamSelector.cpp */; }; - EB976FD41684D7C500A68EE6 /* TreeParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FB61684D77600A68EE6 /* TreeParser.cpp */; }; - EBB9FF7A1682E51300FF9774 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = EBB9FF791682E51300FF9774 /* main.c */; }; - EBB9FF7F1682E5A200FF9774 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBB9FF7E1682E5A200FF9774 /* CoreFoundation.framework */; }; - EBB9FFE21682E83600FF9774 /* com.apple.CodeSigningHelper.sb in CopyFiles */ = {isa = PBXBuildFile; fileRef = EBB9FF801682E65700FF9774 /* com.apple.CodeSigningHelper.sb */; }; - EBDAF04F166D65FA0042CDCE /* piddiskrep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EBDAF04D166D65FA0042CDCE /* piddiskrep.cpp */; }; - EBDAF050166D65FA0042CDCE /* piddiskrep.h in Headers */ = {isa = PBXBuildFile; fileRef = EBDAF04E166D65FA0042CDCE /* piddiskrep.h */; }; - EBF9A1581684E12700BCECA6 /* libsecurity_codesigning.plist in Copy OpenSourceVersions */ = {isa = PBXBuildFile; fileRef = EBF9A1551684E0F300BCECA6 /* libsecurity_codesigning.plist */; }; - EBF9A15A1684E14100BCECA6 /* libsecurity_codesigning.txt in OpenSourceLicenses */ = {isa = PBXBuildFile; fileRef = EBF9A1561684E0F300BCECA6 /* libsecurity_codesigning.txt */; }; - FEB30C9310DAC89D00557BA2 /* SecTask.c in Sources */ = {isa = PBXBuildFile; fileRef = FEB30C9210DAC89D00557BA2 /* SecTask.c */; }; - FEB30CA410DAC97400557BA2 /* SecTask.h in Headers */ = {isa = PBXBuildFile; fileRef = FEB30C9410DAC8A500557BA2 /* SecTask.h */; settings = {ATTRIBUTES = (); }; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 182BB504146F2823000BF1F3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 182BB4FC146F2823000BF1F3 /* libsecurityd.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; - remoteInfo = libsecurityd_client; - }; - 182BB506146F2823000BF1F3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 182BB4FC146F2823000BF1F3 /* libsecurityd.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA1FECD052A44A100F22E42; - remoteInfo = libsecurityd_server; - }; - 182BB508146F2823000BF1F3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 182BB4FC146F2823000BF1F3 /* libsecurityd.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = C2A788730B7AA65B00CFF85C; - remoteInfo = ucspc; - }; - 182BB50E146F28F6000BF1F3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 182BB4FC146F2823000BF1F3 /* libsecurityd.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 4C09A2920557240300FED7A3; - remoteInfo = libsecurityd_generate; - }; - 182BB510146F292B000BF1F3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; - proxyType = 1; - remoteGlobalIDString = C26AC0EB143BCF01001C98CE; - remoteInfo = SystemPolicy; - }; - 1844617C146E9A5200B12992 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; - proxyType = 1; - remoteGlobalIDString = C26AC7090DAEB3A7005BFB40; - remoteInfo = DTrace; - }; - C209696F15BF53330093035F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; - proxyType = 1; - remoteGlobalIDString = C209695F15BF52040093035F; - remoteInfo = gkunpack; - }; - C250F6C40B5EF4E40076098F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; - proxyType = 1; - remoteGlobalIDString = C2BC1F250B580D3A003EC9DC; - remoteInfo = libintegrity; - }; - C26AC0F1143BD02B001C98CE /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; - proxyType = 1; - remoteGlobalIDString = C26AC0EB143BCF01001C98CE; - remoteInfo = SystemPolicy; - }; - C2E287400B5D8F97009336A0 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_codesigning; - }; - C2E287420B5D8F9A009336A0 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; - proxyType = 1; - remoteGlobalIDString = C2BC1F2E0B580D4B003EC9DC; - remoteInfo = libcodehost; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - C2578CB11579627200D4FE48 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = /usr/local/bin; - dstSubfolderSpec = 0; - files = ( - C211070A158C1082001D7F76 /* gkmerge in CopyFiles */, - C2256BDD158BC0F200F72211 /* gkhandmake in CopyFiles */, - C2256BDE158BC0F200F72211 /* gklist in CopyFiles */, - C29CDE2A1583F46F00A42059 /* gkclear in CopyFiles */, - C29CDE2B1583F46F00A42059 /* gkgenerate in CopyFiles */, - C29CDE2C1583F46F00A42059 /* gkrecord in CopyFiles */, - ); - runOnlyForDeploymentPostprocessing = 1; - }; - C25C18CD15CB0C470007A2DE /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = /usr/libexec; - dstSubfolderSpec = 0; - files = ( - C25C18CE15CB0C5C0007A2DE /* gkreport in CopyFiles */, - ); - runOnlyForDeploymentPostprocessing = 1; - }; - C25C18D015CB0FB30007A2DE /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = /System/Library/LaunchDaemons; - dstSubfolderSpec = 0; - files = ( - C25C18D115CB0FC30007A2DE /* com.apple.gkreport.plist in CopyFiles */, - ); - runOnlyForDeploymentPostprocessing = 1; - }; - C26AC0F4143BD1C4001C98CE /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = private/var/db; - dstSubfolderSpec = 0; - files = ( - C26AC0F5143BD1C8001C98CE /* SystemPolicy in CopyFiles */, - ); - runOnlyForDeploymentPostprocessing = 1; - }; - EBB9FFE11682E80A00FF9774 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = /System/Library/Sandbox/Profiles; - dstSubfolderSpec = 0; - files = ( - EBB9FFE21682E83600FF9774 /* com.apple.CodeSigningHelper.sb in CopyFiles */, - ); - runOnlyForDeploymentPostprocessing = 1; - }; - EBF9A1501684E0DF00BCECA6 /* Copy OpenSourceVersions */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = /usr/local/OpenSourceVersions; - dstSubfolderSpec = 0; - files = ( - EBF9A1581684E12700BCECA6 /* libsecurity_codesigning.plist in Copy OpenSourceVersions */, - ); - name = "Copy OpenSourceVersions"; - runOnlyForDeploymentPostprocessing = 1; - }; - EBF9A1591684E12C00BCECA6 /* OpenSourceLicenses */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = /usr/local/OpenSourceLicenses; - dstSubfolderSpec = 0; - files = ( - EBF9A15A1684E14100BCECA6 /* libsecurity_codesigning.txt in OpenSourceLicenses */, - ); - name = OpenSourceLicenses; - runOnlyForDeploymentPostprocessing = 1; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 182BB4FC146F2823000BF1F3 /* libsecurityd.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurityd.xcodeproj; path = ../libsecurityd/libsecurityd.xcodeproj; sourceTree = ""; }; - 1844619F146E9AD100B12992 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; - 184461A0146E9AD100B12992 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; - 184461A1146E9AD100B12992 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; - 184461A2146E9AD100B12992 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; - 4CA1FEBE052A3C8100F22E42 /* libsecurity_codesigning.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_codesigning.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 7A078F631996C1C2003D68DA /* dirscanner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dirscanner.cpp; sourceTree = ""; }; - 7A078F641996C1C2003D68DA /* dirscanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dirscanner.h; sourceTree = ""; }; - 7A9DA65A1948D1BA004635E6 /* opaquewhitelist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = opaquewhitelist.cpp; sourceTree = ""; }; - 7A9DA65B1948D1BA004635E6 /* opaquewhitelist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = opaquewhitelist.h; sourceTree = ""; }; - BEC3A75B16F78D21003E5634 /* SecTaskPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTaskPriv.h; sourceTree = ""; }; - C200424915D425B7004AE0A1 /* libsecurity_codesigning.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_codesigning.a; path = ../../../usr/local/lib/libsecurity_codesigning.a; sourceTree = ""; }; - C200424A15D425B7004AE0A1 /* libsecurity_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_utilities.a; path = ../../../usr/local/lib/libsecurity_utilities.a; sourceTree = ""; }; - C2093AA60BB0948000EB8599 /* reqreader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = reqreader.cpp; sourceTree = ""; }; - C2093AA70BB0948000EB8599 /* reqreader.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = reqreader.h; sourceTree = ""; }; - C209696015BF52040093035F /* gkunpack */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = gkunpack; sourceTree = BUILT_PRODUCTS_DIR; }; - C209696315BF52040093035F /* gkunpack.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = gkunpack.cpp; sourceTree = ""; }; - C209697215BF57EB0093035F /* libsecurity_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libsecurity_utilities.a; sourceTree = ""; }; - C2110704158BF5C8001D7F76 /* gkmerge */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = gkmerge; sourceTree = ""; }; - C21CFC5D0A250D1C006CD5B1 /* reqdumper.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = reqdumper.cpp; sourceTree = ""; }; - C21CFC5E0A250D1C006CD5B1 /* reqdumper.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = reqdumper.h; sourceTree = ""; }; - C21EA3DB0AD2F81300E6E31C /* SecCodeSigner.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecCodeSigner.cpp; sourceTree = ""; }; - C21EA3DC0AD2F81300E6E31C /* SecCodeSigner.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCodeSigner.h; sourceTree = ""; }; - C21EA3E10AD2FA0900E6E31C /* CodeSigner.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CodeSigner.cpp; sourceTree = ""; }; - C21EA3E20AD2FA0900E6E31C /* CodeSigner.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CodeSigner.h; sourceTree = ""; }; - C235340E145F1B050073F964 /* xar++.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "xar++.h"; sourceTree = ""; }; - C2353410145F1B110073F964 /* xar++.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "xar++.cpp"; sourceTree = ""; }; - C236E3D50AD59446000F5140 /* signer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = signer.cpp; sourceTree = ""; }; - C236E3D60AD59446000F5140 /* signer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = signer.h; sourceTree = ""; }; - C236E3D90AD595C2000F5140 /* signerutils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = signerutils.cpp; sourceTree = ""; }; - C236E3DA0AD595C2000F5140 /* signerutils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = signerutils.h; sourceTree = ""; }; - C24EABAA1421432800C16AA9 /* policydb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = policydb.h; sourceTree = ""; }; - C24EABAC1421433700C16AA9 /* policydb.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = policydb.cpp; sourceTree = ""; }; - C250F6C20B5EF1910076098F /* SecIntegrity.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecIntegrity.h; sourceTree = ""; }; - C250F6C60B5EF5B50076098F /* SecIntegrity.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecIntegrity.cpp; sourceTree = ""; }; - C2578CC215798D0F00D4FE48 /* gkclear */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = gkclear; sourceTree = ""; }; - C2578CC315798D0F00D4FE48 /* gkgenerate */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = gkgenerate; sourceTree = ""; }; - C2578CC415798D0F00D4FE48 /* gkrecord */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = gkrecord; sourceTree = ""; }; - C259DFD40AD6D9BA00C9ACC6 /* sigblob.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = sigblob.cpp; sourceTree = ""; }; - C259DFD50AD6D9BA00C9ACC6 /* sigblob.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sigblob.h; sourceTree = ""; }; - C25C18C615CB0BC10007A2DE /* gkreport */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = gkreport; path = gke/gkreport; sourceTree = SOURCE_ROOT; }; - C25C18CF15CB0FA00007A2DE /* com.apple.gkreport.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.gkreport.plist; path = gke/com.apple.gkreport.plist; sourceTree = SOURCE_ROOT; }; - C26763D514FD9EBE00A46EDF /* drmaker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = drmaker.cpp; sourceTree = ""; }; - C26763D614FD9EBE00A46EDF /* drmaker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = drmaker.h; sourceTree = ""; }; - C26AC0F3143BD1B3001C98CE /* SystemPolicy */ = {isa = PBXFileReference; lastKnownFileType = text; name = SystemPolicy; path = cstemp/SystemPolicy; sourceTree = BUILT_PRODUCTS_DIR; }; - C26AC6FD0DAEB2C4005BFB40 /* security_codesigning.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = security_codesigning.d; sourceTree = ""; }; - C26B45C00B8A9C00003C0ACA /* ucspc */ = {isa = PBXFileReference; lastKnownFileType = text; name = ucspc; path = cstemp/ucspc; sourceTree = BUILT_PRODUCTS_DIR; }; - C27249D2143237CD0058B552 /* syspolicy.sql */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = syspolicy.sql; sourceTree = ""; }; - C273601D1432A60B00A9A5FF /* policyengine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = policyengine.h; sourceTree = ""; }; - C27360201432A61900A9A5FF /* policyengine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = policyengine.cpp; sourceTree = ""; }; - C273606C1433F09000A9A5FF /* SecAssessment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SecAssessment.cpp; sourceTree = ""; }; - C273606D1433F09000A9A5FF /* SecAssessment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = SecAssessment.h; sourceTree = ""; }; - C27360D41436866C00A9A5FF /* xpcengine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = xpcengine.cpp; sourceTree = ""; }; - C27360D71436868600A9A5FF /* xpcengine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xpcengine.h; sourceTree = ""; }; - C278A19B158AB2C300FA6767 /* gkhandmake */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = gkhandmake; sourceTree = ""; }; - C278A19C158AB2C300FA6767 /* gklist */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = gklist; sourceTree = ""; }; - C28342E40E366E6800E54360 /* csdatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = csdatabase.cpp; sourceTree = ""; }; - C28342E50E366E6800E54360 /* csdatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = csdatabase.h; sourceTree = ""; }; - C28342EB0E36719D00E54360 /* detachedrep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = detachedrep.cpp; sourceTree = ""; }; - C28342EC0E36719D00E54360 /* detachedrep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = detachedrep.h; sourceTree = ""; }; - C293E2C21554653700F3E396 /* sp-watch.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; name = "sp-watch.d"; path = "dtrace/sp-watch.d"; sourceTree = SOURCE_ROOT; }; - C2A436130F2133B2007A41A6 /* slcrep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = slcrep.cpp; sourceTree = ""; }; - C2A436140F2133B2007A41A6 /* slcrep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = slcrep.h; sourceTree = ""; }; - C2A976A80B8A2E36008B4EA0 /* csutilities.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = csutilities.cpp; sourceTree = ""; }; - C2A976A90B8A2E36008B4EA0 /* csutilities.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = csutilities.h; sourceTree = ""; }; - C2BC1F260B580D3A003EC9DC /* libintegrity.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libintegrity.a; sourceTree = BUILT_PRODUCTS_DIR; }; - C2BC1F2F0B580D4B003EC9DC /* libcodehost.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libcodehost.a; sourceTree = BUILT_PRODUCTS_DIR; }; - C2BC1F340B580DA7003EC9DC /* SecCodeHostLib.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCodeHostLib.h; sourceTree = ""; }; - C2BD519A0A9392FD000FE43D /* machorep.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = machorep.cpp; sourceTree = ""; }; - C2BD519B0A9392FD000FE43D /* machorep.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = machorep.h; sourceTree = ""; }; - C2BD60F80AC863FC0057FD3D /* csgeneric.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = csgeneric.cpp; sourceTree = ""; }; - C2BD60F90AC863FC0057FD3D /* csgeneric.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = csgeneric.h; sourceTree = ""; }; - C2C1DF8F0A2E4A2700D1B02B /* requirements.grammar */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = requirements.grammar; sourceTree = SOURCE_ROOT; }; - C2C1DFB90A2F80EB00D1B02B /* reqinterp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = reqinterp.cpp; sourceTree = ""; }; - C2C1DFBA0A2F80EB00D1B02B /* reqinterp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = reqinterp.h; sourceTree = ""; }; - C2C1DFC10A2F820500D1B02B /* reqmaker.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = reqmaker.cpp; sourceTree = ""; }; - C2C1DFC20A2F820500D1B02B /* reqmaker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = reqmaker.h; sourceTree = ""; }; - C2C3BC5D0BA1D6FE00E869D1 /* cfmdiskrep.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cfmdiskrep.cpp; sourceTree = ""; }; - C2C3BC5E0BA1D6FE00E869D1 /* cfmdiskrep.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cfmdiskrep.h; sourceTree = ""; }; - C2C3BCD10BA1E47E00E869D1 /* singlediskrep.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = singlediskrep.cpp; sourceTree = ""; }; - C2C3BCD20BA1E47E00E869D1 /* singlediskrep.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = singlediskrep.h; sourceTree = ""; }; - C2C4F4EE0E0980C700137848 /* codesigning_dtrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = codesigning_dtrace.h; path = cstemp/codesigning_dtrace.h; sourceTree = BUILT_PRODUCTS_DIR; }; - C2C931B30AB8BA1200F83950 /* SecCodeHost.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecCodeHost.cpp; sourceTree = ""; }; - C2CC30A00B8519CC005FA59D /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CoreFoundation.framework; sourceTree = ""; }; - C2CC31040B8523AD005FA59D /* SecIntegrityLib.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecIntegrityLib.h; sourceTree = ""; }; - C2CC310E0B852424005FA59D /* SecIntegrityLib.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SecIntegrityLib.c; sourceTree = ""; }; - C2CC31130B85254F005FA59D /* antlrplugin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = antlrplugin.cpp; path = lib/antlrplugin.cpp; sourceTree = ""; }; - C2CC31140B85254F005FA59D /* antlrplugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = antlrplugin.h; path = lib/antlrplugin.h; sourceTree = ""; }; - C2D383120A237F47005C63A2 /* bundlediskrep.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = bundlediskrep.cpp; sourceTree = ""; }; - C2D383130A237F47005C63A2 /* bundlediskrep.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bundlediskrep.h; sourceTree = ""; }; - C2D383140A237F47005C63A2 /* cdbuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cdbuilder.cpp; sourceTree = ""; }; - C2D383150A237F47005C63A2 /* cdbuilder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cdbuilder.h; sourceTree = ""; }; - C2D383160A237F47005C63A2 /* codedirectory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = codedirectory.cpp; sourceTree = ""; }; - C2D383170A237F47005C63A2 /* codedirectory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = codedirectory.h; sourceTree = ""; }; - C2D383180A237F47005C63A2 /* CodeSigning.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CodeSigning.h; sourceTree = ""; }; - C2D383190A237F47005C63A2 /* SecCodeHost.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCodeHost.h; sourceTree = ""; }; - C2D3831A0A237F47005C63A2 /* cs.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cs.cpp; sourceTree = ""; }; - C2D3831B0A237F47005C63A2 /* cs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cs.h; sourceTree = ""; }; - C2D3831C0A237F47005C63A2 /* CSCommon.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CSCommon.h; sourceTree = ""; }; - C2D3831D0A237F47005C63A2 /* SecCode.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecCode.cpp; sourceTree = ""; }; - C2D3831E0A237F47005C63A2 /* SecCode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCode.h; sourceTree = ""; }; - C2D3831F0A237F47005C63A2 /* cskernel.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cskernel.cpp; sourceTree = ""; }; - C2D383200A237F47005C63A2 /* cskernel.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cskernel.h; sourceTree = ""; }; - C2D383210A237F47005C63A2 /* SecStaticCode.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecStaticCode.cpp; sourceTree = ""; }; - C2D383220A237F47005C63A2 /* SecStaticCode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecStaticCode.h; sourceTree = ""; }; - C2D383230A237F47005C63A2 /* csprocess.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = csprocess.cpp; sourceTree = ""; }; - C2D383240A237F47005C63A2 /* csprocess.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = csprocess.h; sourceTree = ""; }; - C2D383250A237F47005C63A2 /* SecRequirement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecRequirement.cpp; sourceTree = ""; }; - C2D383260A237F47005C63A2 /* SecRequirement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecRequirement.h; sourceTree = ""; }; - C2D383270A237F47005C63A2 /* diskrep.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = diskrep.cpp; sourceTree = ""; }; - C2D383280A237F47005C63A2 /* diskrep.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = diskrep.h; sourceTree = ""; }; - C2D3832B0A237F47005C63A2 /* filediskrep.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = filediskrep.cpp; sourceTree = ""; }; - C2D3832C0A237F47005C63A2 /* filediskrep.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = filediskrep.h; sourceTree = ""; }; - C2D3832D0A237F47005C63A2 /* Code.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Code.cpp; sourceTree = ""; }; - C2D3832E0A237F47005C63A2 /* Code.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Code.h; sourceTree = ""; }; - C2D3832F0A237F47005C63A2 /* kerneldiskrep.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = kerneldiskrep.cpp; sourceTree = ""; }; - C2D383300A237F47005C63A2 /* kerneldiskrep.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = kerneldiskrep.h; sourceTree = ""; }; - C2D383310A237F47005C63A2 /* StaticCode.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = StaticCode.cpp; sourceTree = ""; }; - C2D383320A237F47005C63A2 /* StaticCode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = StaticCode.h; sourceTree = ""; }; - C2D383330A237F47005C63A2 /* reqparser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = reqparser.cpp; sourceTree = ""; }; - C2D383340A237F47005C63A2 /* reqparser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = reqparser.h; sourceTree = ""; }; - C2D383350A237F47005C63A2 /* requirement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = requirement.cpp; sourceTree = ""; }; - C2D383360A237F47005C63A2 /* requirement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = requirement.h; sourceTree = ""; }; - C2D383370A237F47005C63A2 /* Requirements.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Requirements.cpp; sourceTree = ""; }; - C2D383380A237F47005C63A2 /* Requirements.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Requirements.h; sourceTree = ""; }; - C2D383390A237F47005C63A2 /* security_codesigning.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = security_codesigning.exp; sourceTree = ""; }; - C2D50CDF0E155A4F0059A195 /* CSCommonPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSCommonPriv.h; sourceTree = ""; }; - C2E2873C0B5D8D80009336A0 /* SecCodeHostLib.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SecCodeHostLib.c; sourceTree = ""; }; - C2E8AF240DE25CA7000F6D3B /* SecCodePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCodePriv.h; sourceTree = ""; }; - C2E8AF250DE25CA7000F6D3B /* SecRequirementPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecRequirementPriv.h; sourceTree = ""; }; - C2E8AF260DE25CA7000F6D3B /* SecStaticCodePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecStaticCodePriv.h; sourceTree = ""; }; - C2E911E00ADEBE3200275CB2 /* resources.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = resources.cpp; sourceTree = ""; }; - C2E911E10ADEBE3200275CB2 /* resources.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = resources.h; sourceTree = ""; }; - C2F4439814C626D4000A01E6 /* quarantine++.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "quarantine++.cpp"; sourceTree = ""; }; - C2F4439914C626D4000A01E6 /* quarantine++.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "quarantine++.h"; sourceTree = ""; }; - C2F6071B107D575700A83618 /* codesign-watch.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; name = "codesign-watch.d"; path = "dtrace/codesign-watch.d"; sourceTree = SOURCE_ROOT; }; - C2F6566C0BCBFB250078779E /* cserror.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cserror.cpp; sourceTree = ""; }; - C2F6566D0BCBFB250078779E /* cserror.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cserror.h; sourceTree = ""; }; - EB68B10A150DAEBB00B4013D /* RequirementKeywords.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RequirementKeywords.h; sourceTree = ""; }; - EB68B10B150DAEBB00B4013D /* RequirementLexer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RequirementLexer.cpp; sourceTree = ""; }; - EB68B10C150DAEBB00B4013D /* RequirementLexer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = RequirementLexer.hpp; sourceTree = ""; }; - EB68B10D150DAEBB00B4013D /* RequirementParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RequirementParser.cpp; sourceTree = ""; }; - EB68B10E150DAEBB00B4013D /* RequirementParser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = RequirementParser.hpp; sourceTree = ""; }; - EB68B10F150DAEBB00B4013D /* RequirementParserTokenTypes.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = RequirementParserTokenTypes.hpp; sourceTree = ""; }; - EB68B110150DAEBB00B4013D /* RequirementParserTokenTypes.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = RequirementParserTokenTypes.txt; sourceTree = ""; }; - EB976F571684D77500A68EE6 /* ANTLRException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ANTLRException.hpp; sourceTree = ""; }; - EB976F581684D77500A68EE6 /* ANTLRUtil.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ANTLRUtil.hpp; sourceTree = ""; }; - EB976F591684D77500A68EE6 /* AST.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AST.hpp; sourceTree = ""; }; - EB976F5A1684D77500A68EE6 /* ASTArray.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ASTArray.hpp; sourceTree = ""; }; - EB976F5B1684D77500A68EE6 /* ASTFactory.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ASTFactory.hpp; sourceTree = ""; }; - EB976F5C1684D77500A68EE6 /* ASTNULLType.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ASTNULLType.hpp; sourceTree = ""; }; - EB976F5D1684D77500A68EE6 /* ASTPair.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ASTPair.hpp; sourceTree = ""; }; - EB976F5E1684D77500A68EE6 /* ASTRefCount.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ASTRefCount.hpp; sourceTree = ""; }; - EB976F5F1684D77500A68EE6 /* BaseAST.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = BaseAST.hpp; sourceTree = ""; }; - EB976F601684D77500A68EE6 /* BitSet.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = BitSet.hpp; sourceTree = ""; }; - EB976F611684D77500A68EE6 /* CharBuffer.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CharBuffer.hpp; sourceTree = ""; }; - EB976F621684D77500A68EE6 /* CharInputBuffer.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CharInputBuffer.hpp; sourceTree = ""; }; - EB976F631684D77500A68EE6 /* CharScanner.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CharScanner.hpp; sourceTree = ""; }; - EB976F641684D77500A68EE6 /* CharStreamException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CharStreamException.hpp; sourceTree = ""; }; - EB976F651684D77500A68EE6 /* CharStreamIOException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CharStreamIOException.hpp; sourceTree = ""; }; - EB976F661684D77500A68EE6 /* CircularQueue.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CircularQueue.hpp; sourceTree = ""; }; - EB976F671684D77500A68EE6 /* CommonAST.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CommonAST.hpp; sourceTree = ""; }; - EB976F681684D77500A68EE6 /* CommonASTWithHiddenTokens.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CommonASTWithHiddenTokens.hpp; sourceTree = ""; }; - EB976F691684D77500A68EE6 /* CommonHiddenStreamToken.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CommonHiddenStreamToken.hpp; sourceTree = ""; }; - EB976F6A1684D77500A68EE6 /* CommonToken.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CommonToken.hpp; sourceTree = ""; }; - EB976F6B1684D77500A68EE6 /* config.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = config.hpp; sourceTree = ""; }; - EB976F6C1684D77500A68EE6 /* InputBuffer.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = InputBuffer.hpp; sourceTree = ""; }; - EB976F6D1684D77500A68EE6 /* IOException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = IOException.hpp; sourceTree = ""; }; - EB976F6E1684D77500A68EE6 /* LexerSharedInputState.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = LexerSharedInputState.hpp; sourceTree = ""; }; - EB976F6F1684D77500A68EE6 /* LLkParser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = LLkParser.hpp; sourceTree = ""; }; - EB976F701684D77500A68EE6 /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; - EB976F711684D77500A68EE6 /* MismatchedCharException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MismatchedCharException.hpp; sourceTree = ""; }; - EB976F721684D77500A68EE6 /* MismatchedTokenException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MismatchedTokenException.hpp; sourceTree = ""; }; - EB976F731684D77500A68EE6 /* NoViableAltException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = NoViableAltException.hpp; sourceTree = ""; }; - EB976F741684D77500A68EE6 /* NoViableAltForCharException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = NoViableAltForCharException.hpp; sourceTree = ""; }; - EB976F751684D77500A68EE6 /* Parser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Parser.hpp; sourceTree = ""; }; - EB976F761684D77500A68EE6 /* ParserSharedInputState.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ParserSharedInputState.hpp; sourceTree = ""; }; - EB976F771684D77500A68EE6 /* RecognitionException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = RecognitionException.hpp; sourceTree = ""; }; - EB976F781684D77500A68EE6 /* RefCount.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = RefCount.hpp; sourceTree = ""; }; - EB976F791684D77500A68EE6 /* SemanticException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = SemanticException.hpp; sourceTree = ""; }; - EB976F7A1684D77500A68EE6 /* String.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = String.hpp; sourceTree = ""; }; - EB976F7B1684D77500A68EE6 /* Token.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Token.hpp; sourceTree = ""; }; - EB976F7C1684D77500A68EE6 /* TokenBuffer.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenBuffer.hpp; sourceTree = ""; }; - EB976F7D1684D77500A68EE6 /* TokenRefCount.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenRefCount.hpp; sourceTree = ""; }; - EB976F7E1684D77500A68EE6 /* TokenStream.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenStream.hpp; sourceTree = ""; }; - EB976F7F1684D77500A68EE6 /* TokenStreamBasicFilter.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenStreamBasicFilter.hpp; sourceTree = ""; }; - EB976F801684D77500A68EE6 /* TokenStreamException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenStreamException.hpp; sourceTree = ""; }; - EB976F811684D77500A68EE6 /* TokenStreamHiddenTokenFilter.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenStreamHiddenTokenFilter.hpp; sourceTree = ""; }; - EB976F821684D77500A68EE6 /* TokenStreamIOException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenStreamIOException.hpp; sourceTree = ""; }; - EB976F831684D77500A68EE6 /* TokenStreamRecognitionException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenStreamRecognitionException.hpp; sourceTree = ""; }; - EB976F841684D77500A68EE6 /* TokenStreamRetryException.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenStreamRetryException.hpp; sourceTree = ""; }; - EB976F851684D77500A68EE6 /* TokenStreamRewriteEngine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenStreamRewriteEngine.hpp; sourceTree = ""; }; - EB976F861684D77500A68EE6 /* TokenStreamSelector.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenStreamSelector.hpp; sourceTree = ""; }; - EB976F871684D77500A68EE6 /* TokenWithIndex.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TokenWithIndex.hpp; sourceTree = ""; }; - EB976F881684D77500A68EE6 /* TreeParser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TreeParser.hpp; sourceTree = ""; }; - EB976F891684D77500A68EE6 /* TreeParserSharedInputState.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TreeParserSharedInputState.hpp; sourceTree = ""; }; - EB976F8A1684D77500A68EE6 /* AUTHORS */ = {isa = PBXFileReference; lastKnownFileType = text; name = AUTHORS; path = antlr2/AUTHORS; sourceTree = ""; }; - EB976F8B1684D77500A68EE6 /* ChangeLog */ = {isa = PBXFileReference; lastKnownFileType = text; name = ChangeLog; path = antlr2/ChangeLog; sourceTree = ""; }; - EB976F8E1684D77500A68EE6 /* antlr.bpr */ = {isa = PBXFileReference; lastKnownFileType = text; path = antlr.bpr; sourceTree = ""; }; - EB976F8F1684D77500A68EE6 /* antlr.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = antlr.cpp; sourceTree = ""; }; - EB976F901684D77500A68EE6 /* README */ = {isa = PBXFileReference; lastKnownFileType = text; path = README; sourceTree = ""; }; - EB976F911684D77500A68EE6 /* doxygen.cfg */ = {isa = PBXFileReference; lastKnownFileType = text; name = doxygen.cfg; path = antlr2/doxygen.cfg; sourceTree = ""; }; - EB976F921684D77500A68EE6 /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; name = Makefile.in; path = antlr2/Makefile.in; sourceTree = ""; }; - EB976F931684D77500A68EE6 /* README */ = {isa = PBXFileReference; lastKnownFileType = text; name = README; path = antlr2/README; sourceTree = ""; }; - EB976F951684D77500A68EE6 /* cr_stripper.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = cr_stripper.sh; sourceTree = ""; }; - EB976F961684D77500A68EE6 /* make_change_log.tcl */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = make_change_log.tcl; sourceTree = ""; }; - EB976F981684D77600A68EE6 /* ANTLRUtil.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ANTLRUtil.cpp; sourceTree = ""; }; - EB976F991684D77600A68EE6 /* ASTFactory.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ASTFactory.cpp; sourceTree = ""; }; - EB976F9A1684D77600A68EE6 /* ASTNULLType.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ASTNULLType.cpp; sourceTree = ""; }; - EB976F9B1684D77600A68EE6 /* ASTRefCount.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ASTRefCount.cpp; sourceTree = ""; }; - EB976F9C1684D77600A68EE6 /* BaseAST.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = BaseAST.cpp; sourceTree = ""; }; - EB976F9D1684D77600A68EE6 /* BitSet.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = BitSet.cpp; sourceTree = ""; }; - EB976F9E1684D77600A68EE6 /* CharBuffer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CharBuffer.cpp; sourceTree = ""; }; - EB976F9F1684D77600A68EE6 /* CharScanner.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CharScanner.cpp; sourceTree = ""; }; - EB976FA01684D77600A68EE6 /* CommonAST.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CommonAST.cpp; sourceTree = ""; }; - EB976FA11684D77600A68EE6 /* CommonASTWithHiddenTokens.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CommonASTWithHiddenTokens.cpp; sourceTree = ""; }; - EB976FA21684D77600A68EE6 /* CommonHiddenStreamToken.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CommonHiddenStreamToken.cpp; sourceTree = ""; }; - EB976FA31684D77600A68EE6 /* CommonToken.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CommonToken.cpp; sourceTree = ""; }; - EB976FA41684D77600A68EE6 /* dll.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = dll.cpp; sourceTree = ""; }; - EB976FA51684D77600A68EE6 /* InputBuffer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InputBuffer.cpp; sourceTree = ""; }; - EB976FA61684D77600A68EE6 /* LLkParser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LLkParser.cpp; sourceTree = ""; }; - EB976FA71684D77600A68EE6 /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; - EB976FA81684D77600A68EE6 /* MismatchedCharException.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MismatchedCharException.cpp; sourceTree = ""; }; - EB976FA91684D77600A68EE6 /* MismatchedTokenException.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MismatchedTokenException.cpp; sourceTree = ""; }; - EB976FAA1684D77600A68EE6 /* NoViableAltException.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = NoViableAltException.cpp; sourceTree = ""; }; - EB976FAB1684D77600A68EE6 /* NoViableAltForCharException.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = NoViableAltForCharException.cpp; sourceTree = ""; }; - EB976FAC1684D77600A68EE6 /* Parser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Parser.cpp; sourceTree = ""; }; - EB976FAD1684D77600A68EE6 /* RecognitionException.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RecognitionException.cpp; sourceTree = ""; }; - EB976FAE1684D77600A68EE6 /* String.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = String.cpp; sourceTree = ""; }; - EB976FAF1684D77600A68EE6 /* Token.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Token.cpp; sourceTree = ""; }; - EB976FB01684D77600A68EE6 /* TokenBuffer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TokenBuffer.cpp; sourceTree = ""; }; - EB976FB11684D77600A68EE6 /* TokenRefCount.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TokenRefCount.cpp; sourceTree = ""; }; - EB976FB21684D77600A68EE6 /* TokenStreamBasicFilter.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TokenStreamBasicFilter.cpp; sourceTree = ""; }; - EB976FB31684D77600A68EE6 /* TokenStreamHiddenTokenFilter.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TokenStreamHiddenTokenFilter.cpp; sourceTree = ""; }; - EB976FB41684D77600A68EE6 /* TokenStreamRewriteEngine.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TokenStreamRewriteEngine.cpp; sourceTree = ""; }; - EB976FB51684D77600A68EE6 /* TokenStreamSelector.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TokenStreamSelector.cpp; sourceTree = ""; }; - EB976FB61684D77600A68EE6 /* TreeParser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TreeParser.cpp; sourceTree = ""; }; - EB976FB71684D77600A68EE6 /* TODO */ = {isa = PBXFileReference; lastKnownFileType = text; name = TODO; path = antlr2/TODO; sourceTree = ""; }; - EBB9FF6F1682E51300FF9774 /* com.apple.CodeSigningHelper.xpc */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = com.apple.CodeSigningHelper.xpc; sourceTree = BUILT_PRODUCTS_DIR; }; - EBB9FF701682E51300FF9774 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - EBB9FF741682E51300FF9774 /* CodeSigningHelper-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "CodeSigningHelper-Info.plist"; sourceTree = ""; }; - EBB9FF791682E51300FF9774 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; - EBB9FF7E1682E5A200FF9774 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; }; - EBB9FF801682E65700FF9774 /* com.apple.CodeSigningHelper.sb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = com.apple.CodeSigningHelper.sb; sourceTree = ""; }; - EBDAF04D166D65FA0042CDCE /* piddiskrep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = piddiskrep.cpp; sourceTree = ""; }; - EBDAF04E166D65FA0042CDCE /* piddiskrep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = piddiskrep.h; sourceTree = ""; }; - EBF9A1551684E0F300BCECA6 /* libsecurity_codesigning.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = libsecurity_codesigning.plist; path = antlr2/libsecurity_codesigning.plist; sourceTree = ""; }; - EBF9A1561684E0F300BCECA6 /* libsecurity_codesigning.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = libsecurity_codesigning.txt; path = antlr2/libsecurity_codesigning.txt; sourceTree = ""; }; - EBF9A1571684E0F300BCECA6 /* LICENSE.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = LICENSE.txt; path = antlr2/LICENSE.txt; sourceTree = ""; }; - FEB30C9210DAC89D00557BA2 /* SecTask.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecTask.c; sourceTree = ""; }; - FEB30C9410DAC8A500557BA2 /* SecTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTask.h; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C209695D15BF52040093035F /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - C200424D15D425D9004AE0A1 /* libsecurity_codesigning.a in Frameworks */, - C200424E15D425D9004AE0A1 /* libsecurity_utilities.a in Frameworks */, - 7ACF261219958B6F00849B25 /* CoreFoundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C2BC1F240B580D3A003EC9DC /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C2BC1F2D0B580D4B003EC9DC /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - C26B45C10B8A9C0A003C0ACA /* ucspc in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EBB9FF6C1682E51300FF9774 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - EBB9FF7F1682E5A200FF9774 /* CoreFoundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 182BB4FD146F2823000BF1F3 /* Products */ = { - isa = PBXGroup; - children = ( - 182BB505146F2823000BF1F3 /* libsecurityd_client.a */, - 182BB507146F2823000BF1F3 /* libsecurityd_server.a */, - 182BB509146F2823000BF1F3 /* ucspc.a */, - ); - name = Products; - sourceTree = ""; - }; - 1844619E146E9AD100B12992 /* config */ = { - isa = PBXGroup; - children = ( - 1844619F146E9AD100B12992 /* base.xcconfig */, - 184461A0146E9AD100B12992 /* debug.xcconfig */, - 184461A1146E9AD100B12992 /* lib.xcconfig */, - 184461A2146E9AD100B12992 /* release.xcconfig */, - ); - name = config; - path = ../config; - sourceTree = ""; - }; - 4C308388053237100028A8C6 /* lib */ = { - isa = PBXGroup; - children = ( - C2C1DF5F0A2E457E00D1B02B /* API */, - C2C1DF600A2E458D00D1B02B /* API Objects */, - C216C72D0AD59B22003B07D4 /* Signing Operations */, - C2C1DF630A2E45BF00D1B02B /* Code Directory */, - C2C1DF620A2E45B600D1B02B /* Requirements */, - C2C1DF640A2E45F500D1B02B /* Code Classes */, - C2C1DF610A2E459E00D1B02B /* Disk Representations */, - C2BC1F370B580DAE003EC9DC /* Static Support */, - C26AC6FF0DAEB2D0005BFB40 /* DTrace */, - C293E2B915543F0800F3E396 /* gke */, - C2CCF0360A3F524B0085795A /* Local Utilities */, - C2CC31160B852554005FA59D /* Security Plugins */, - FEB30C9110DAC6C400557BA2 /* Entitlements */, - C24EABA914213FAF00C16AA9 /* System Policy */, - ); - path = lib; - sourceTree = ""; - }; - 4CA1FEA7052A3C3800F22E42 = { - isa = PBXGroup; - children = ( - EBB9FF7E1682E5A200FF9774 /* CoreFoundation.framework */, - C209697215BF57EB0093035F /* libsecurity_utilities.a */, - 182BB4FC146F2823000BF1F3 /* libsecurityd.xcodeproj */, - 4C308388053237100028A8C6 /* lib */, - 1844619E146E9AD100B12992 /* config */, - C2D383F90A23A9D9005C63A2 /* cstemp */, - EB976F511684D73900A68EE6 /* antlr2 */, - EBB9FF721682E51300FF9774 /* CodeSigningHelper */, - C2CC30EF0B8519CF005FA59D /* Frameworks */, - 4CA1FEBF052A3C8100F22E42 /* Products */, - ); - sourceTree = ""; - }; - 4CA1FEBF052A3C8100F22E42 /* Products */ = { - isa = PBXGroup; - children = ( - 4CA1FEBE052A3C8100F22E42 /* libsecurity_codesigning.a */, - C2BC1F260B580D3A003EC9DC /* libintegrity.a */, - C2BC1F2F0B580D4B003EC9DC /* libcodehost.a */, - C209696015BF52040093035F /* gkunpack */, - EBB9FF6F1682E51300FF9774 /* com.apple.CodeSigningHelper.xpc */, - ); - name = Products; - sourceTree = ""; - }; - C216C72D0AD59B22003B07D4 /* Signing Operations */ = { - isa = PBXGroup; - children = ( - C236E3D60AD59446000F5140 /* signer.h */, - C236E3D50AD59446000F5140 /* signer.cpp */, - C236E3DA0AD595C2000F5140 /* signerutils.h */, - C236E3D90AD595C2000F5140 /* signerutils.cpp */, - ); - name = "Signing Operations"; - sourceTree = ""; - }; - C24EABA914213FAF00C16AA9 /* System Policy */ = { - isa = PBXGroup; - children = ( - C273606D1433F09000A9A5FF /* SecAssessment.h */, - C273606C1433F09000A9A5FF /* SecAssessment.cpp */, - 7A9DA65B1948D1BA004635E6 /* opaquewhitelist.h */, - 7A9DA65A1948D1BA004635E6 /* opaquewhitelist.cpp */, - C24EABAA1421432800C16AA9 /* policydb.h */, - C24EABAC1421433700C16AA9 /* policydb.cpp */, - C273601D1432A60B00A9A5FF /* policyengine.h */, - C27360201432A61900A9A5FF /* policyengine.cpp */, - C27360D71436868600A9A5FF /* xpcengine.h */, - C27360D41436866C00A9A5FF /* xpcengine.cpp */, - C27249D2143237CD0058B552 /* syspolicy.sql */, - ); - name = "System Policy"; - sourceTree = ""; - }; - C26AC6FF0DAEB2D0005BFB40 /* DTrace */ = { - isa = PBXGroup; - children = ( - C293E2C21554653700F3E396 /* sp-watch.d */, - C26AC6FD0DAEB2C4005BFB40 /* security_codesigning.d */, - C2F6071B107D575700A83618 /* codesign-watch.d */, - ); - name = DTrace; - sourceTree = ""; - }; - C293E2B915543F0800F3E396 /* gke */ = { - isa = PBXGroup; - children = ( - C2110704158BF5C8001D7F76 /* gkmerge */, - C278A19B158AB2C300FA6767 /* gkhandmake */, - C278A19C158AB2C300FA6767 /* gklist */, - C2578CC215798D0F00D4FE48 /* gkclear */, - C2578CC315798D0F00D4FE48 /* gkgenerate */, - C2578CC415798D0F00D4FE48 /* gkrecord */, - C25C18C615CB0BC10007A2DE /* gkreport */, - C25C18CF15CB0FA00007A2DE /* com.apple.gkreport.plist */, - C209696315BF52040093035F /* gkunpack.cpp */, - ); - path = gke; - sourceTree = SOURCE_ROOT; - }; - C2BC1F370B580DAE003EC9DC /* Static Support */ = { - isa = PBXGroup; - children = ( - C2CC31040B8523AD005FA59D /* SecIntegrityLib.h */, - C2CC310E0B852424005FA59D /* SecIntegrityLib.c */, - C2BC1F340B580DA7003EC9DC /* SecCodeHostLib.h */, - C2E2873C0B5D8D80009336A0 /* SecCodeHostLib.c */, - ); - name = "Static Support"; - sourceTree = ""; - }; - C2C1DF5F0A2E457E00D1B02B /* API */ = { - isa = PBXGroup; - children = ( - C2D383180A237F47005C63A2 /* CodeSigning.h */, - C2D3831C0A237F47005C63A2 /* CSCommon.h */, - C2D50CDF0E155A4F0059A195 /* CSCommonPriv.h */, - C2D3831E0A237F47005C63A2 /* SecCode.h */, - C2E8AF240DE25CA7000F6D3B /* SecCodePriv.h */, - C2D3831D0A237F47005C63A2 /* SecCode.cpp */, - C2D383220A237F47005C63A2 /* SecStaticCode.h */, - C2E8AF260DE25CA7000F6D3B /* SecStaticCodePriv.h */, - C2D383210A237F47005C63A2 /* SecStaticCode.cpp */, - C2D383260A237F47005C63A2 /* SecRequirement.h */, - C2E8AF250DE25CA7000F6D3B /* SecRequirementPriv.h */, - C2D383250A237F47005C63A2 /* SecRequirement.cpp */, - C21EA3DC0AD2F81300E6E31C /* SecCodeSigner.h */, - C21EA3DB0AD2F81300E6E31C /* SecCodeSigner.cpp */, - C2D383190A237F47005C63A2 /* SecCodeHost.h */, - C2C931B30AB8BA1200F83950 /* SecCodeHost.cpp */, - C250F6C20B5EF1910076098F /* SecIntegrity.h */, - C250F6C60B5EF5B50076098F /* SecIntegrity.cpp */, - C2D383390A237F47005C63A2 /* security_codesigning.exp */, - ); - name = API; - sourceTree = ""; - }; - C2C1DF600A2E458D00D1B02B /* API Objects */ = { - isa = PBXGroup; - children = ( - C2D3831B0A237F47005C63A2 /* cs.h */, - C2D3831A0A237F47005C63A2 /* cs.cpp */, - C2D3832E0A237F47005C63A2 /* Code.h */, - C2D3832D0A237F47005C63A2 /* Code.cpp */, - C2D383320A237F47005C63A2 /* StaticCode.h */, - C2D383310A237F47005C63A2 /* StaticCode.cpp */, - C2D383380A237F47005C63A2 /* Requirements.h */, - C2D383370A237F47005C63A2 /* Requirements.cpp */, - C21EA3E20AD2FA0900E6E31C /* CodeSigner.h */, - C21EA3E10AD2FA0900E6E31C /* CodeSigner.cpp */, - ); - name = "API Objects"; - sourceTree = ""; - }; - C2C1DF610A2E459E00D1B02B /* Disk Representations */ = { - isa = PBXGroup; - children = ( - C2D383280A237F47005C63A2 /* diskrep.h */, - C2D383270A237F47005C63A2 /* diskrep.cpp */, - C2D3832C0A237F47005C63A2 /* filediskrep.h */, - C2D3832B0A237F47005C63A2 /* filediskrep.cpp */, - C2D383130A237F47005C63A2 /* bundlediskrep.h */, - C2D383120A237F47005C63A2 /* bundlediskrep.cpp */, - C2D383300A237F47005C63A2 /* kerneldiskrep.h */, - C2D3832F0A237F47005C63A2 /* kerneldiskrep.cpp */, - C2C3BC5E0BA1D6FE00E869D1 /* cfmdiskrep.h */, - C2C3BC5D0BA1D6FE00E869D1 /* cfmdiskrep.cpp */, - C2BD519B0A9392FD000FE43D /* machorep.h */, - C2BD519A0A9392FD000FE43D /* machorep.cpp */, - C2A436140F2133B2007A41A6 /* slcrep.h */, - C2A436130F2133B2007A41A6 /* slcrep.cpp */, - C2C3BCD20BA1E47E00E869D1 /* singlediskrep.h */, - C2C3BCD10BA1E47E00E869D1 /* singlediskrep.cpp */, - C28342EC0E36719D00E54360 /* detachedrep.h */, - C28342EB0E36719D00E54360 /* detachedrep.cpp */, - EBDAF04D166D65FA0042CDCE /* piddiskrep.cpp */, - EBDAF04E166D65FA0042CDCE /* piddiskrep.h */, - ); - name = "Disk Representations"; - sourceTree = ""; - }; - C2C1DF620A2E45B600D1B02B /* Requirements */ = { - isa = PBXGroup; - children = ( - C2C1DF8F0A2E4A2700D1B02B /* requirements.grammar */, - EB68B10A150DAEBB00B4013D /* RequirementKeywords.h */, - EB68B10B150DAEBB00B4013D /* RequirementLexer.cpp */, - EB68B10C150DAEBB00B4013D /* RequirementLexer.hpp */, - EB68B10D150DAEBB00B4013D /* RequirementParser.cpp */, - EB68B10E150DAEBB00B4013D /* RequirementParser.hpp */, - EB68B10F150DAEBB00B4013D /* RequirementParserTokenTypes.hpp */, - EB68B110150DAEBB00B4013D /* RequirementParserTokenTypes.txt */, - C2D383360A237F47005C63A2 /* requirement.h */, - C2D383350A237F47005C63A2 /* requirement.cpp */, - C2C1DFC20A2F820500D1B02B /* reqmaker.h */, - C2C1DFC10A2F820500D1B02B /* reqmaker.cpp */, - C2093AA70BB0948000EB8599 /* reqreader.h */, - C2093AA60BB0948000EB8599 /* reqreader.cpp */, - C2C1DFBA0A2F80EB00D1B02B /* reqinterp.h */, - C2C1DFB90A2F80EB00D1B02B /* reqinterp.cpp */, - C2D383340A237F47005C63A2 /* reqparser.h */, - C2D383330A237F47005C63A2 /* reqparser.cpp */, - C21CFC5E0A250D1C006CD5B1 /* reqdumper.h */, - C21CFC5D0A250D1C006CD5B1 /* reqdumper.cpp */, - C26763D614FD9EBE00A46EDF /* drmaker.h */, - C26763D514FD9EBE00A46EDF /* drmaker.cpp */, - ); - name = Requirements; - sourceTree = ""; - }; - C2C1DF630A2E45BF00D1B02B /* Code Directory */ = { - isa = PBXGroup; - children = ( - C2D383170A237F47005C63A2 /* codedirectory.h */, - C2D383160A237F47005C63A2 /* codedirectory.cpp */, - C2D383150A237F47005C63A2 /* cdbuilder.h */, - C2D383140A237F47005C63A2 /* cdbuilder.cpp */, - ); - name = "Code Directory"; - sourceTree = ""; - }; - C2C1DF640A2E45F500D1B02B /* Code Classes */ = { - isa = PBXGroup; - children = ( - C2D383200A237F47005C63A2 /* cskernel.h */, - C2D3831F0A237F47005C63A2 /* cskernel.cpp */, - C2D383240A237F47005C63A2 /* csprocess.h */, - C2D383230A237F47005C63A2 /* csprocess.cpp */, - C2BD60F90AC863FC0057FD3D /* csgeneric.h */, - C2BD60F80AC863FC0057FD3D /* csgeneric.cpp */, - ); - name = "Code Classes"; - sourceTree = ""; - }; - C2CC30EF0B8519CF005FA59D /* Frameworks */ = { - isa = PBXGroup; - children = ( - C200424915D425B7004AE0A1 /* libsecurity_codesigning.a */, - C200424A15D425B7004AE0A1 /* libsecurity_utilities.a */, - C2CC30A00B8519CC005FA59D /* CoreFoundation.framework */, - EBB9FF701682E51300FF9774 /* Foundation.framework */, - ); - name = Frameworks; - path = /System/Library/Frameworks; - sourceTree = ""; - }; - C2CC31160B852554005FA59D /* Security Plugins */ = { - isa = PBXGroup; - children = ( - C2CC31140B85254F005FA59D /* antlrplugin.h */, - C2CC31130B85254F005FA59D /* antlrplugin.cpp */, - ); - name = "Security Plugins"; - path = ..; - sourceTree = ""; - }; - C2CCF0360A3F524B0085795A /* Local Utilities */ = { - isa = PBXGroup; - children = ( - C28342E50E366E6800E54360 /* csdatabase.h */, - C28342E40E366E6800E54360 /* csdatabase.cpp */, - C2F6566D0BCBFB250078779E /* cserror.h */, - C2F6566C0BCBFB250078779E /* cserror.cpp */, - C2E911E10ADEBE3200275CB2 /* resources.h */, - C2E911E00ADEBE3200275CB2 /* resources.cpp */, - C259DFD50AD6D9BA00C9ACC6 /* sigblob.h */, - C259DFD40AD6D9BA00C9ACC6 /* sigblob.cpp */, - C2A976A90B8A2E36008B4EA0 /* csutilities.h */, - C2A976A80B8A2E36008B4EA0 /* csutilities.cpp */, - C235340E145F1B050073F964 /* xar++.h */, - C2353410145F1B110073F964 /* xar++.cpp */, - C2F4439914C626D4000A01E6 /* quarantine++.h */, - C2F4439814C626D4000A01E6 /* quarantine++.cpp */, - 7A078F641996C1C2003D68DA /* dirscanner.h */, - 7A078F631996C1C2003D68DA /* dirscanner.cpp */, - ); - name = "Local Utilities"; - sourceTree = ""; - }; - C2D383F90A23A9D9005C63A2 /* cstemp */ = { - isa = PBXGroup; - children = ( - C2C4F4EE0E0980C700137848 /* codesigning_dtrace.h */, - C26AC0F3143BD1B3001C98CE /* SystemPolicy */, - C26B45C00B8A9C00003C0ACA /* ucspc */, - ); - path = cstemp; - sourceTree = BUILT_PRODUCTS_DIR; - }; - EB976F511684D73900A68EE6 /* antlr2 */ = { - isa = PBXGroup; - children = ( - EB976F561684D77500A68EE6 /* antlr */, - EB976F8A1684D77500A68EE6 /* AUTHORS */, - EB976F8B1684D77500A68EE6 /* ChangeLog */, - EB976F8C1684D77500A68EE6 /* contrib */, - EB976F911684D77500A68EE6 /* doxygen.cfg */, - EBF9A1551684E0F300BCECA6 /* libsecurity_codesigning.plist */, - EBF9A1561684E0F300BCECA6 /* libsecurity_codesigning.txt */, - EBF9A1571684E0F300BCECA6 /* LICENSE.txt */, - EB976F921684D77500A68EE6 /* Makefile.in */, - EB976F931684D77500A68EE6 /* README */, - EB976F941684D77500A68EE6 /* scripts */, - EB976F971684D77600A68EE6 /* src */, - EB976FB71684D77600A68EE6 /* TODO */, - ); - name = antlr2; - sourceTree = ""; - }; - EB976F561684D77500A68EE6 /* antlr */ = { - isa = PBXGroup; - children = ( - EB976F571684D77500A68EE6 /* ANTLRException.hpp */, - EB976F581684D77500A68EE6 /* ANTLRUtil.hpp */, - EB976F591684D77500A68EE6 /* AST.hpp */, - EB976F5A1684D77500A68EE6 /* ASTArray.hpp */, - EB976F5B1684D77500A68EE6 /* ASTFactory.hpp */, - EB976F5C1684D77500A68EE6 /* ASTNULLType.hpp */, - EB976F5D1684D77500A68EE6 /* ASTPair.hpp */, - EB976F5E1684D77500A68EE6 /* ASTRefCount.hpp */, - EB976F5F1684D77500A68EE6 /* BaseAST.hpp */, - EB976F601684D77500A68EE6 /* BitSet.hpp */, - EB976F611684D77500A68EE6 /* CharBuffer.hpp */, - EB976F621684D77500A68EE6 /* CharInputBuffer.hpp */, - EB976F631684D77500A68EE6 /* CharScanner.hpp */, - EB976F641684D77500A68EE6 /* CharStreamException.hpp */, - EB976F651684D77500A68EE6 /* CharStreamIOException.hpp */, - EB976F661684D77500A68EE6 /* CircularQueue.hpp */, - EB976F671684D77500A68EE6 /* CommonAST.hpp */, - EB976F681684D77500A68EE6 /* CommonASTWithHiddenTokens.hpp */, - EB976F691684D77500A68EE6 /* CommonHiddenStreamToken.hpp */, - EB976F6A1684D77500A68EE6 /* CommonToken.hpp */, - EB976F6B1684D77500A68EE6 /* config.hpp */, - EB976F6C1684D77500A68EE6 /* InputBuffer.hpp */, - EB976F6D1684D77500A68EE6 /* IOException.hpp */, - EB976F6E1684D77500A68EE6 /* LexerSharedInputState.hpp */, - EB976F6F1684D77500A68EE6 /* LLkParser.hpp */, - EB976F701684D77500A68EE6 /* Makefile.in */, - EB976F711684D77500A68EE6 /* MismatchedCharException.hpp */, - EB976F721684D77500A68EE6 /* MismatchedTokenException.hpp */, - EB976F731684D77500A68EE6 /* NoViableAltException.hpp */, - EB976F741684D77500A68EE6 /* NoViableAltForCharException.hpp */, - EB976F751684D77500A68EE6 /* Parser.hpp */, - EB976F761684D77500A68EE6 /* ParserSharedInputState.hpp */, - EB976F771684D77500A68EE6 /* RecognitionException.hpp */, - EB976F781684D77500A68EE6 /* RefCount.hpp */, - EB976F791684D77500A68EE6 /* SemanticException.hpp */, - EB976F7A1684D77500A68EE6 /* String.hpp */, - EB976F7B1684D77500A68EE6 /* Token.hpp */, - EB976F7C1684D77500A68EE6 /* TokenBuffer.hpp */, - EB976F7D1684D77500A68EE6 /* TokenRefCount.hpp */, - EB976F7E1684D77500A68EE6 /* TokenStream.hpp */, - EB976F7F1684D77500A68EE6 /* TokenStreamBasicFilter.hpp */, - EB976F801684D77500A68EE6 /* TokenStreamException.hpp */, - EB976F811684D77500A68EE6 /* TokenStreamHiddenTokenFilter.hpp */, - EB976F821684D77500A68EE6 /* TokenStreamIOException.hpp */, - EB976F831684D77500A68EE6 /* TokenStreamRecognitionException.hpp */, - EB976F841684D77500A68EE6 /* TokenStreamRetryException.hpp */, - EB976F851684D77500A68EE6 /* TokenStreamRewriteEngine.hpp */, - EB976F861684D77500A68EE6 /* TokenStreamSelector.hpp */, - EB976F871684D77500A68EE6 /* TokenWithIndex.hpp */, - EB976F881684D77500A68EE6 /* TreeParser.hpp */, - EB976F891684D77500A68EE6 /* TreeParserSharedInputState.hpp */, - ); - name = antlr; - path = antlr2/antlr; - sourceTree = ""; - }; - EB976F8C1684D77500A68EE6 /* contrib */ = { - isa = PBXGroup; - children = ( - EB976F8D1684D77500A68EE6 /* bcb4 */, - ); - name = contrib; - path = antlr2/contrib; - sourceTree = ""; - }; - EB976F8D1684D77500A68EE6 /* bcb4 */ = { - isa = PBXGroup; - children = ( - EB976F8E1684D77500A68EE6 /* antlr.bpr */, - EB976F8F1684D77500A68EE6 /* antlr.cpp */, - EB976F901684D77500A68EE6 /* README */, - ); - path = bcb4; - sourceTree = ""; - }; - EB976F941684D77500A68EE6 /* scripts */ = { - isa = PBXGroup; - children = ( - EB976F951684D77500A68EE6 /* cr_stripper.sh */, - EB976F961684D77500A68EE6 /* make_change_log.tcl */, - ); - name = scripts; - path = antlr2/scripts; - sourceTree = ""; - }; - EB976F971684D77600A68EE6 /* src */ = { - isa = PBXGroup; - children = ( - EB976F981684D77600A68EE6 /* ANTLRUtil.cpp */, - EB976F991684D77600A68EE6 /* ASTFactory.cpp */, - EB976F9A1684D77600A68EE6 /* ASTNULLType.cpp */, - EB976F9B1684D77600A68EE6 /* ASTRefCount.cpp */, - EB976F9C1684D77600A68EE6 /* BaseAST.cpp */, - EB976F9D1684D77600A68EE6 /* BitSet.cpp */, - EB976F9E1684D77600A68EE6 /* CharBuffer.cpp */, - EB976F9F1684D77600A68EE6 /* CharScanner.cpp */, - EB976FA01684D77600A68EE6 /* CommonAST.cpp */, - EB976FA11684D77600A68EE6 /* CommonASTWithHiddenTokens.cpp */, - EB976FA21684D77600A68EE6 /* CommonHiddenStreamToken.cpp */, - EB976FA31684D77600A68EE6 /* CommonToken.cpp */, - EB976FA41684D77600A68EE6 /* dll.cpp */, - EB976FA51684D77600A68EE6 /* InputBuffer.cpp */, - EB976FA61684D77600A68EE6 /* LLkParser.cpp */, - EB976FA71684D77600A68EE6 /* Makefile.in */, - EB976FA81684D77600A68EE6 /* MismatchedCharException.cpp */, - EB976FA91684D77600A68EE6 /* MismatchedTokenException.cpp */, - EB976FAA1684D77600A68EE6 /* NoViableAltException.cpp */, - EB976FAB1684D77600A68EE6 /* NoViableAltForCharException.cpp */, - EB976FAC1684D77600A68EE6 /* Parser.cpp */, - EB976FAD1684D77600A68EE6 /* RecognitionException.cpp */, - EB976FAE1684D77600A68EE6 /* String.cpp */, - EB976FAF1684D77600A68EE6 /* Token.cpp */, - EB976FB01684D77600A68EE6 /* TokenBuffer.cpp */, - EB976FB11684D77600A68EE6 /* TokenRefCount.cpp */, - EB976FB21684D77600A68EE6 /* TokenStreamBasicFilter.cpp */, - EB976FB31684D77600A68EE6 /* TokenStreamHiddenTokenFilter.cpp */, - EB976FB41684D77600A68EE6 /* TokenStreamRewriteEngine.cpp */, - EB976FB51684D77600A68EE6 /* TokenStreamSelector.cpp */, - EB976FB61684D77600A68EE6 /* TreeParser.cpp */, - ); - name = src; - path = antlr2/src; - sourceTree = ""; - }; - EBB9FF721682E51300FF9774 /* CodeSigningHelper */ = { - isa = PBXGroup; - children = ( - EBB9FF791682E51300FF9774 /* main.c */, - EBB9FF801682E65700FF9774 /* com.apple.CodeSigningHelper.sb */, - EBB9FF731682E51300FF9774 /* Supporting Files */, - ); - path = CodeSigningHelper; - sourceTree = ""; - }; - EBB9FF731682E51300FF9774 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - EBB9FF741682E51300FF9774 /* CodeSigningHelper-Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - FEB30C9110DAC6C400557BA2 /* Entitlements */ = { - isa = PBXGroup; - children = ( - FEB30C9410DAC8A500557BA2 /* SecTask.h */, - BEC3A75B16F78D21003E5634 /* SecTaskPriv.h */, - FEB30C9210DAC89D00557BA2 /* SecTask.c */, - ); - name = Entitlements; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 4CA1FEB9052A3C8100F22E42 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 18B965861472FBF6005A4D2E /* reqdumper.h in Headers */, - 18B965871472FC5B005A4D2E /* requirement.h in Headers */, - 18B965881472FC5B005A4D2E /* reqmaker.h in Headers */, - 7A9DA65D1948D1BA004635E6 /* opaquewhitelist.h in Headers */, - 18B965891472FC5B005A4D2E /* reqreader.h in Headers */, - 18B9658A1472FC5B005A4D2E /* reqinterp.h in Headers */, - 18B9658B1472FC5B005A4D2E /* reqparser.h in Headers */, - 18B9658C1472FC9E005A4D2E /* codedirectory.h in Headers */, - 18B965951472FE30005A4D2E /* cdbuilder.h in Headers */, - EB68B133150DB04400B4013D /* RequirementKeywords.h in Headers */, - BEC3A75C16F78D21003E5634 /* SecTaskPriv.h in Headers */, - EB68B134150DB04400B4013D /* RequirementLexer.hpp in Headers */, - EB68B135150DB04400B4013D /* RequirementParser.hpp in Headers */, - FEB30CA410DAC97400557BA2 /* SecTask.h in Headers */, - C26FF6310E5B376B00F640A0 /* CSCommonPriv.h in Headers */, - C26FF6330E5B376B00F640A0 /* SecCodePriv.h in Headers */, - C26FF6350E5B376B00F640A0 /* SecStaticCodePriv.h in Headers */, - C26FF6370E5B376B00F640A0 /* SecRequirementPriv.h in Headers */, - C26FF6380E5B376B00F640A0 /* SecCodeSigner.h in Headers */, - C26FF63A0E5B376B00F640A0 /* SecIntegrity.h in Headers */, - C26FF62D0E5B375A00F640A0 /* SecIntegrityLib.h in Headers */, - C26FF62E0E5B375A00F640A0 /* SecCodeHostLib.h in Headers */, - C273606F1433F09000A9A5FF /* SecAssessment.h in Headers */, - C26FF62F0E5B376B00F640A0 /* CodeSigning.h in Headers */, - C26FF6300E5B376B00F640A0 /* CSCommon.h in Headers */, - C26FF6320E5B376B00F640A0 /* SecCode.h in Headers */, - C26FF6340E5B376B00F640A0 /* SecStaticCode.h in Headers */, - C26FF6360E5B376B00F640A0 /* SecRequirement.h in Headers */, - C26FF6390E5B376B00F640A0 /* SecCodeHost.h in Headers */, - C2A436160F2133B2007A41A6 /* slcrep.h in Headers */, - C24EABAB1421432800C16AA9 /* policydb.h in Headers */, - C2F4439B14C626D4000A01E6 /* quarantine++.h in Headers */, - 7A078F661996C1C2003D68DA /* dirscanner.h in Headers */, - C26763D814FD9EBE00A46EDF /* drmaker.h in Headers */, - EBDAF050166D65FA0042CDCE /* piddiskrep.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C2BC1F220B580D3A003EC9DC /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - C250F6C30B5EF1910076098F /* SecIntegrity.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C2BC1F2B0B580D4B003EC9DC /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - C2BC1F350B580DA7003EC9DC /* SecCodeHostLib.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 4CA1FEBD052A3C8100F22E42 /* libsecurity_codesigning */ = { - isa = PBXNativeTarget; - buildConfigurationList = C263E67509A2971B000043F1 /* Build configuration list for PBXNativeTarget "libsecurity_codesigning" */; - buildPhases = ( - 4CA1FEB9052A3C8100F22E42 /* Headers */, - 4CA1FEBA052A3C8100F22E42 /* Sources */, - 4CA1FEBB052A3C8100F22E42 /* Frameworks */, - 1865FFD5147517A300FD79DF /* ShellScript */, - EBF9A1501684E0DF00BCECA6 /* Copy OpenSourceVersions */, - EBF9A1591684E12C00BCECA6 /* OpenSourceLicenses */, - ); - buildRules = ( - ); - dependencies = ( - 182BB50F146F28F6000BF1F3 /* PBXTargetDependency */, - 1844617D146E9A5200B12992 /* PBXTargetDependency */, - 182BB511146F292B000BF1F3 /* PBXTargetDependency */, - ); - name = libsecurity_codesigning; - productName = libsecurity_codesigning; - productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_codesigning.a */; - productType = "com.apple.product-type.library.static"; - }; - C209695F15BF52040093035F /* gkunpack */ = { - isa = PBXNativeTarget; - buildConfigurationList = C209696B15BF52040093035F /* Build configuration list for PBXNativeTarget "gkunpack" */; - buildPhases = ( - C209695C15BF52040093035F /* Sources */, - C209695D15BF52040093035F /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = gkunpack; - productName = gkunpack; - productReference = C209696015BF52040093035F /* gkunpack */; - productType = "com.apple.product-type.tool"; - }; - C2BC1F250B580D3A003EC9DC /* libintegrity */ = { - isa = PBXNativeTarget; - buildConfigurationList = C2BC1F270B580D3F003EC9DC /* Build configuration list for PBXNativeTarget "libintegrity" */; - buildPhases = ( - C2BC1F220B580D3A003EC9DC /* Headers */, - C2BC1F230B580D3A003EC9DC /* Sources */, - C2BC1F240B580D3A003EC9DC /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libintegrity; - productName = libintegrity; - productReference = C2BC1F260B580D3A003EC9DC /* libintegrity.a */; - productType = "com.apple.product-type.library.static"; - }; - C2BC1F2E0B580D4B003EC9DC /* libcodehost */ = { - isa = PBXNativeTarget; - buildConfigurationList = C2BC1F300B580D69003EC9DC /* Build configuration list for PBXNativeTarget "libcodehost" */; - buildPhases = ( - C26B45C30B8A9C1A003C0ACA /* Prepare ucspc */, - C2BC1F2B0B580D4B003EC9DC /* Headers */, - C2BC1F2C0B580D4B003EC9DC /* Sources */, - C2BC1F2D0B580D4B003EC9DC /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libcodehost; - productName = libcodehost; - productReference = C2BC1F2F0B580D4B003EC9DC /* libcodehost.a */; - productType = "com.apple.product-type.library.static"; - }; - EBB9FF6E1682E51300FF9774 /* CodeSigningHelper */ = { - isa = PBXNativeTarget; - buildConfigurationList = EBB9FF7B1682E51300FF9774 /* Build configuration list for PBXNativeTarget "CodeSigningHelper" */; - buildPhases = ( - EBB9FF6B1682E51300FF9774 /* Sources */, - EBB9FF6C1682E51300FF9774 /* Frameworks */, - EBB9FFE11682E80A00FF9774 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = CodeSigningHelper; - productName = CodeSigningHelper; - productReference = EBB9FF6F1682E51300FF9774 /* com.apple.CodeSigningHelper.xpc */; - productType = "com.apple.product-type.bundle"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 4CA1FEAB052A3C3800F22E42 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0500; - }; - buildConfigurationList = C263E67909A2971B000043F1 /* Build configuration list for PBXProject "libsecurity_codesigning" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - English, - Japanese, - French, - German, - en, - ); - mainGroup = 4CA1FEA7052A3C3800F22E42; - productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; - projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 182BB4FD146F2823000BF1F3 /* Products */; - ProjectRef = 182BB4FC146F2823000BF1F3 /* libsecurityd.xcodeproj */; - }, - ); - projectRoot = ""; - targets = ( - C2E2873F0B5D8F8F009336A0 /* Everything */, - 4CA1FEBD052A3C8100F22E42 /* libsecurity_codesigning */, - C2D383B80A23A8C4005C63A2 /* Requirements Language */, - C2BC1F250B580D3A003EC9DC /* libintegrity */, - C2BC1F2E0B580D4B003EC9DC /* libcodehost */, - C26AC7090DAEB3A7005BFB40 /* DTrace */, - C26AC0EB143BCF01001C98CE /* SystemPolicy */, - C209695F15BF52040093035F /* gkunpack */, - EBB9FF6E1682E51300FF9774 /* CodeSigningHelper */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXReferenceProxy section */ - 182BB505146F2823000BF1F3 /* libsecurityd_client.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libsecurityd_client.a; - remoteRef = 182BB504146F2823000BF1F3 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 182BB507146F2823000BF1F3 /* libsecurityd_server.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libsecurityd_server.a; - remoteRef = 182BB506146F2823000BF1F3 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 182BB509146F2823000BF1F3 /* ucspc.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = ucspc.a; - remoteRef = 182BB508146F2823000BF1F3 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - -/* Begin PBXShellScriptBuildPhase section */ - 1865FFD5147517A300FD79DF /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "ranlib \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\""; - }; - C26AC0F0143BCF18001C98CE /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 12; - files = ( - ); - inputPaths = ( - "$(PROJECT_DIR)/lib/syspolicy.sql", - ); - outputPaths = ( - "$(TEMPDIR)/SystemPolicy", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "mkdir -p \"$(dirname \"$SCRIPT_OUTPUT_FILE_0\")\"\nrm -f \"$SCRIPT_OUTPUT_FILE_0\"\nsqlite3 \"$SCRIPT_OUTPUT_FILE_0\" <$SRCROOT/lib/RequirementKeywords.h\n"; - }; - C2F24DFE14BCBBF200309FCD /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 8; - files = ( - ); - inputPaths = ( - "$(TEMPDIR)/SystemPolicy", - ); - outputPaths = ( - "$(DSTROOT)/private/var/db/.SystemPolicy-default", - ); - runOnlyForDeploymentPostprocessing = 1; - shellPath = /bin/bash; - shellScript = "cp \"$SCRIPT_INPUT_FILE_0\" \"$SCRIPT_OUTPUT_FILE_0\"\nchmod 444 \"$SCRIPT_OUTPUT_FILE_0\""; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 4CA1FEBA052A3C8100F22E42 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - EB976FB81684D7C500A68EE6 /* ANTLRUtil.cpp in Sources */, - EB976FB91684D7C500A68EE6 /* ASTFactory.cpp in Sources */, - EB976FBA1684D7C500A68EE6 /* ASTNULLType.cpp in Sources */, - EB976FBB1684D7C500A68EE6 /* ASTRefCount.cpp in Sources */, - EB976FBC1684D7C500A68EE6 /* BaseAST.cpp in Sources */, - EB976FBD1684D7C500A68EE6 /* BitSet.cpp in Sources */, - EB976FBE1684D7C500A68EE6 /* CharBuffer.cpp in Sources */, - EB976FBF1684D7C500A68EE6 /* CharScanner.cpp in Sources */, - EB976FC01684D7C500A68EE6 /* CommonAST.cpp in Sources */, - EB976FC11684D7C500A68EE6 /* CommonASTWithHiddenTokens.cpp in Sources */, - EB976FC21684D7C500A68EE6 /* CommonHiddenStreamToken.cpp in Sources */, - EB976FC31684D7C500A68EE6 /* CommonToken.cpp in Sources */, - EB976FC41684D7C500A68EE6 /* InputBuffer.cpp in Sources */, - EB976FC51684D7C500A68EE6 /* LLkParser.cpp in Sources */, - EB976FC61684D7C500A68EE6 /* MismatchedCharException.cpp in Sources */, - EB976FC71684D7C500A68EE6 /* MismatchedTokenException.cpp in Sources */, - EB976FC81684D7C500A68EE6 /* NoViableAltException.cpp in Sources */, - EB976FC91684D7C500A68EE6 /* NoViableAltForCharException.cpp in Sources */, - EB976FCA1684D7C500A68EE6 /* Parser.cpp in Sources */, - EB976FCB1684D7C500A68EE6 /* RecognitionException.cpp in Sources */, - EB976FCC1684D7C500A68EE6 /* String.cpp in Sources */, - EB976FCD1684D7C500A68EE6 /* Token.cpp in Sources */, - EB976FCE1684D7C500A68EE6 /* TokenBuffer.cpp in Sources */, - EB976FCF1684D7C500A68EE6 /* TokenRefCount.cpp in Sources */, - EB976FD01684D7C500A68EE6 /* TokenStreamBasicFilter.cpp in Sources */, - EB976FD11684D7C500A68EE6 /* TokenStreamHiddenTokenFilter.cpp in Sources */, - EB976FD21684D7C500A68EE6 /* TokenStreamRewriteEngine.cpp in Sources */, - EB976FD31684D7C500A68EE6 /* TokenStreamSelector.cpp in Sources */, - EB976FD41684D7C500A68EE6 /* TreeParser.cpp in Sources */, - C2D3833C0A237F47005C63A2 /* bundlediskrep.cpp in Sources */, - C2D3833E0A237F47005C63A2 /* cdbuilder.cpp in Sources */, - C2D383400A237F47005C63A2 /* codedirectory.cpp in Sources */, - C2D383440A237F47005C63A2 /* cs.cpp in Sources */, - C2D383470A237F47005C63A2 /* SecCode.cpp in Sources */, - C2D383490A237F47005C63A2 /* cskernel.cpp in Sources */, - C2D3834B0A237F47005C63A2 /* SecStaticCode.cpp in Sources */, - C2D3834D0A237F47005C63A2 /* csprocess.cpp in Sources */, - C2D3834F0A237F47005C63A2 /* SecRequirement.cpp in Sources */, - C2D383510A237F47005C63A2 /* diskrep.cpp in Sources */, - C2D383550A237F47005C63A2 /* filediskrep.cpp in Sources */, - 7A078F651996C1C2003D68DA /* dirscanner.cpp in Sources */, - C2D383570A237F47005C63A2 /* Code.cpp in Sources */, - C2D383590A237F47005C63A2 /* kerneldiskrep.cpp in Sources */, - C2D3835B0A237F47005C63A2 /* StaticCode.cpp in Sources */, - C2D3835D0A237F47005C63A2 /* reqparser.cpp in Sources */, - C2C1DF140A2E3D7200D1B02B /* requirement.cpp in Sources */, - C2D383610A237F47005C63A2 /* Requirements.cpp in Sources */, - C21CFC5F0A250D1C006CD5B1 /* reqdumper.cpp in Sources */, - C2C1DFBB0A2F80EB00D1B02B /* reqinterp.cpp in Sources */, - C2C1DFC30A2F820500D1B02B /* reqmaker.cpp in Sources */, - C22463610B86210100626F1B /* antlrplugin.cpp in Sources */, - C2BD519C0A9392FD000FE43D /* machorep.cpp in Sources */, - C2C931B40AB8BA1200F83950 /* SecCodeHost.cpp in Sources */, - C2BD60FA0AC863FC0057FD3D /* csgeneric.cpp in Sources */, - C21EA3DD0AD2F81300E6E31C /* SecCodeSigner.cpp in Sources */, - C21EA3E30AD2FA0900E6E31C /* CodeSigner.cpp in Sources */, - C236E3D70AD59446000F5140 /* signer.cpp in Sources */, - C236E3DB0AD595C2000F5140 /* signerutils.cpp in Sources */, - C259DFD60AD6D9BA00C9ACC6 /* sigblob.cpp in Sources */, - C2E911E20ADEBE3200275CB2 /* resources.cpp in Sources */, - C2A976AA0B8A2E36008B4EA0 /* csutilities.cpp in Sources */, - C2C3BC5F0BA1D6FE00E869D1 /* cfmdiskrep.cpp in Sources */, - C2C3BCD30BA1E47E00E869D1 /* singlediskrep.cpp in Sources */, - C2093AA80BB0948000EB8599 /* reqreader.cpp in Sources */, - C2F6566E0BCBFB250078779E /* cserror.cpp in Sources */, - C28342E70E366E6800E54360 /* csdatabase.cpp in Sources */, - C28342EE0E36719D00E54360 /* detachedrep.cpp in Sources */, - C2A436150F2133B2007A41A6 /* slcrep.cpp in Sources */, - FEB30C9310DAC89D00557BA2 /* SecTask.c in Sources */, - C24EABAD1421433700C16AA9 /* policydb.cpp in Sources */, - 7A9DA65C1948D1BA004635E6 /* opaquewhitelist.cpp in Sources */, - C273606E1433F09000A9A5FF /* SecAssessment.cpp in Sources */, - C27360D51436866D00A9A5FF /* xpcengine.cpp in Sources */, - C2DC2DCA145F594000AD2A3A /* xar++.cpp in Sources */, - C2DC2DCB145F5CD000AD2A3A /* policyengine.cpp in Sources */, - C2F4439A14C626D4000A01E6 /* quarantine++.cpp in Sources */, - C26763D714FD9EBE00A46EDF /* drmaker.cpp in Sources */, - EB68B111150DAEEA00B4013D /* RequirementLexer.cpp in Sources */, - EB68B112150DAEEA00B4013D /* RequirementParser.cpp in Sources */, - EBDAF04F166D65FA0042CDCE /* piddiskrep.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C209695C15BF52040093035F /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - C209696415BF52040093035F /* gkunpack.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C2BC1F230B580D3A003EC9DC /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - C2CC310F0B852424005FA59D /* SecIntegrityLib.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C2BC1F2C0B580D4B003EC9DC /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - C2E2873D0B5D8D80009336A0 /* SecCodeHostLib.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EBB9FF6B1682E51300FF9774 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - EBB9FF7A1682E51300FF9774 /* main.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 182BB50F146F28F6000BF1F3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = libsecurityd_generate; - targetProxy = 182BB50E146F28F6000BF1F3 /* PBXContainerItemProxy */; - }; - 182BB511146F292B000BF1F3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = C26AC0EB143BCF01001C98CE /* SystemPolicy */; - targetProxy = 182BB510146F292B000BF1F3 /* PBXContainerItemProxy */; - }; - 1844617D146E9A5200B12992 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = C26AC7090DAEB3A7005BFB40 /* DTrace */; - targetProxy = 1844617C146E9A5200B12992 /* PBXContainerItemProxy */; - }; - C209697015BF53330093035F /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = C209695F15BF52040093035F /* gkunpack */; - targetProxy = C209696F15BF53330093035F /* PBXContainerItemProxy */; - }; - C250F6C50B5EF4E40076098F /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = C2BC1F250B580D3A003EC9DC /* libintegrity */; - targetProxy = C250F6C40B5EF4E40076098F /* PBXContainerItemProxy */; - }; - C26AC0F2143BD02B001C98CE /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = C26AC0EB143BCF01001C98CE /* SystemPolicy */; - targetProxy = C26AC0F1143BD02B001C98CE /* PBXContainerItemProxy */; - }; - C2E287410B5D8F97009336A0 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 4CA1FEBD052A3C8100F22E42 /* libsecurity_codesigning */; - targetProxy = C2E287400B5D8F97009336A0 /* PBXContainerItemProxy */; - }; - C2E287430B5D8F9A009336A0 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = C2BC1F2E0B580D4B003EC9DC /* libcodehost */; - targetProxy = C2E287420B5D8F9A009336A0 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - C209696C15BF52040093035F /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = NO; - }; - name = Debug; - }; - C209696D15BF52040093035F /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = NO; - }; - name = Release; - }; - C263E67609A2971B000043F1 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 184461A0146E9AD100B12992 /* debug.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - HEADER_SEARCH_PATHS = ( - "$(PROJECT_DIR)/antlr2", - "$(inherited)", - "$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders", - ); - PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/security_codesigning; - SKIP_INSTALL = NO; - }; - name = Debug; - }; - C263E67809A2971B000043F1 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 184461A2146E9AD100B12992 /* release.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - HEADER_SEARCH_PATHS = ( - "$(PROJECT_DIR)/antlr2", - "$(inherited)", - "$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders", - ); - PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/security_codesigning; - SKIP_INSTALL = NO; - }; - name = Release; - }; - C263E67A09A2971B000043F1 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 184461A1146E9AD100B12992 /* lib.xcconfig */; - buildSettings = { - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - GCC_TREAT_WARNINGS_AS_ERRORS = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - HEADER_SEARCH_PATHS = ( - "$(PROJECT_DIR)/../include", - "$(BUILT_PRODUCTS_DIR)/derived_src", - "$(BUILT_PRODUCTS_DIR)", - "$(PROJECT_DIR)/lib", - /usr/local/include, - ); - TEMPDIR = "$(BUILT_PRODUCTS_DIR)/cstemp"; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - "$(inherited)", - ); - }; - name = Debug; - }; - C263E67C09A2971B000043F1 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 184461A1146E9AD100B12992 /* lib.xcconfig */; - buildSettings = { - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - GCC_TREAT_WARNINGS_AS_ERRORS = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - HEADER_SEARCH_PATHS = ( - "$(PROJECT_DIR)/../include", - "$(BUILT_PRODUCTS_DIR)/derived_src", - "$(BUILT_PRODUCTS_DIR)", - "$(PROJECT_DIR)/lib", - /usr/local/include, - ); - TEMPDIR = "$(BUILT_PRODUCTS_DIR)/cstemp"; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - "$(inherited)", - ); - }; - name = Release; - }; - C26AC0ED143BCF01001C98CE /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Debug; - }; - C26AC0EF143BCF01001C98CE /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Release; - }; - C26AC70A0DAEB3A8005BFB40 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Debug; - }; - C26AC70C0DAEB3A8005BFB40 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Release; - }; - C2BC1F280B580D3F003EC9DC /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 184461A0146E9AD100B12992 /* debug.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - SKIP_INSTALL = NO; - }; - name = Debug; - }; - C2BC1F2A0B580D3F003EC9DC /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 184461A2146E9AD100B12992 /* release.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - SKIP_INSTALL = NO; - }; - name = Release; - }; - C2BC1F310B580D69003EC9DC /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 184461A0146E9AD100B12992 /* debug.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - SKIP_INSTALL = NO; - }; - name = Debug; - }; - C2BC1F330B580D69003EC9DC /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 184461A2146E9AD100B12992 /* release.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - SKIP_INSTALL = NO; - }; - name = Release; - }; - C2D383C10A23A8E3005C63A2 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Debug; - }; - C2D383C30A23A8E3005C63A2 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Release; - }; - C2E287480B5D8FD8009336A0 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - HEADER_SEARCH_PATHS = ( - "$(PROJECT_DIR)/../include", - "$(BUILT_PRODUCTS_DIR)/derived_src", - "$(BUILT_PRODUCTS_DIR)", - "$(PROJECT_DIR)/lib", - /usr/local/include, - ); - }; - name = Debug; - }; - C2E2874A0B5D8FD8009336A0 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - HEADER_SEARCH_PATHS = ( - "$(PROJECT_DIR)/../include", - "$(BUILT_PRODUCTS_DIR)/derived_src", - "$(BUILT_PRODUCTS_DIR)", - "$(PROJECT_DIR)/lib", - /usr/local/include, - ); - }; - name = Release; - }; - EBB9FF7C1682E51300FF9774 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "CodeSigningHelper/CodeSigningHelper-Info.plist"; - INSTALL_PATH = /System/Library/Frameworks/Security.framework/Versions/A/XPCServices; - MACH_O_TYPE = mh_execute; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_NAME = "com.apple.$(TARGET_NAME:rfc1034identifier)"; - SKIP_INSTALL = NO; - WRAPPER_EXTENSION = xpc; - }; - name = Debug; - }; - EBB9FF7D1682E51300FF9774 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "CodeSigningHelper/CodeSigningHelper-Info.plist"; - INSTALL_PATH = /System/Library/Frameworks/Security.framework/Versions/A/XPCServices; - MACH_O_TYPE = mh_execute; - PRODUCT_NAME = "com.apple.$(TARGET_NAME:rfc1034identifier)"; - SKIP_INSTALL = NO; - WRAPPER_EXTENSION = xpc; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - C209696B15BF52040093035F /* Build configuration list for PBXNativeTarget "gkunpack" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C209696C15BF52040093035F /* Debug */, - C209696D15BF52040093035F /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C263E67509A2971B000043F1 /* Build configuration list for PBXNativeTarget "libsecurity_codesigning" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C263E67609A2971B000043F1 /* Debug */, - C263E67809A2971B000043F1 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C263E67909A2971B000043F1 /* Build configuration list for PBXProject "libsecurity_codesigning" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C263E67A09A2971B000043F1 /* Debug */, - C263E67C09A2971B000043F1 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C26AC0EC143BCF01001C98CE /* Build configuration list for PBXAggregateTarget "SystemPolicy" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C26AC0ED143BCF01001C98CE /* Debug */, - C26AC0EF143BCF01001C98CE /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C26AC70D0DAEB3C6005BFB40 /* Build configuration list for PBXAggregateTarget "DTrace" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C26AC70A0DAEB3A8005BFB40 /* Debug */, - C26AC70C0DAEB3A8005BFB40 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C2BC1F270B580D3F003EC9DC /* Build configuration list for PBXNativeTarget "libintegrity" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C2BC1F280B580D3F003EC9DC /* Debug */, - C2BC1F2A0B580D3F003EC9DC /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C2BC1F300B580D69003EC9DC /* Build configuration list for PBXNativeTarget "libcodehost" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C2BC1F310B580D69003EC9DC /* Debug */, - C2BC1F330B580D69003EC9DC /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C2D383C00A23A8E3005C63A2 /* Build configuration list for PBXAggregateTarget "Requirements Language" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C2D383C10A23A8E3005C63A2 /* Debug */, - C2D383C30A23A8E3005C63A2 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C2E287470B5D8FD8009336A0 /* Build configuration list for PBXAggregateTarget "Everything" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C2E287480B5D8FD8009336A0 /* Debug */, - C2E2874A0B5D8FD8009336A0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - EBB9FF7B1682E51300FF9774 /* Build configuration list for PBXNativeTarget "CodeSigningHelper" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - EBB9FF7C1682E51300FF9774 /* Debug */, - EBB9FF7D1682E51300FF9774 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; -} diff --git a/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 47700900..00000000 --- a/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,54 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 4CA1FEBD052A3C8100F22E42 - - primary - - - C209695F15BF52040093035F - - primary - - - C26AC0EB143BCF01001C98CE - - primary - - - C26AC7090DAEB3A7005BFB40 - - primary - - - C2BC1F250B580D3A003EC9DC - - primary - - - C2BC1F2E0B580D4B003EC9DC - - primary - - - C2D383B80A23A8C4005C63A2 - - primary - - - C2E2873F0B5D8F8F009336A0 - - primary - - - EBB9FF6E1682E51300FF9774 - - primary - - - - - diff --git a/libsecurity_comcryption/libsecurity_comcryption.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_comcryption/libsecurity_comcryption.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 2adfe6f3..00000000 --- a/libsecurity_comcryption/libsecurity_comcryption.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 7264321D00A8AD0A7F000001 - - primary - - - - - diff --git a/libsecurity_cryptkit/ckutils/badsig/badsig.c b/libsecurity_cryptkit/ckutils/badsig/badsig.c deleted file mode 100644 index 07270e8f..00000000 --- a/libsecurity_cryptkit/ckutils/badsig/badsig.c +++ /dev/null @@ -1,461 +0,0 @@ -/* Copyright 1996-1997 Apple Computer, Inc. - * - * badsig.c - Verify bad signature detect - * - * Revision History - * ---------------- - * 26 Aug 1996 Doug Mitchell at NeXT - * Created. - */ - -/* - * text size = {random, from 100 bytes to 1 megabyte, in - * geometrical steps, i.e. the number of - * bytes would be 10^r, where r is random out of - * {2,3,4,5,6}, plus a random integer in {0,..99}}; - * - * password size = constant; - * - * for loop_count - * text contents = {random data, random size as specified above}; - * passsword data = random; - * - Alternate between ECDSA and ElGamal on sucessive loops: - * generate signature, validate; - * for each byte of signature { - * corrupt text byte; - * verify bad signature; - * restore corrupted byte; - * } - * } - */ - -#import "Crypt.h" -#include "ckconfig.h" - -#if !CRYPTKIT_HIGH_LEVEL_SIG -#error Can not build this program against a lib with !CRYPTKIT_HIGH_LEVEL_SIG. -#endif - -#import -#import - -static unsigned char *passwdPool; /* all passwords come from here */ -static unsigned char *dataPool; /* plaintext comes from here */ - -#define MAX_DATA_SIZE ((1024 * 1024) + 100) /* bytes */ - -/* - * Defaults. - */ -#define LOOPS_DEF 1 -#define MIN_EXP 2 /* for data size 10**exp */ -#define MAX_EXP 4 -#define PWD_LENGTH 15 /* bytes */ -#define DEPTH_DEFAULT FEE_DEPTH_DEFAULT -#define INCR_DEFAULT 1 /* munge every incr bytes */ - -///#define DEPTH_DEFAULT FEE_DEPTH_5 - -static void usage(char **argv) -{ - printf("usage: %s [options]\n", argv[0]); - printf(" Options:\n"); - printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); - printf(" n=minExp (default=%d)\n", MIN_EXP); - printf(" x=maxExp (default=max=%d)\n", MAX_EXP); - printf(" p=passwdLength (default=%d)\n", PWD_LENGTH); - printf(" D=depth (default=%d)\n", DEPTH_DEFAULT); - printf(" i=increment (default=%d)\n", INCR_DEFAULT); - #if CRYPTKIT_ECDSA_ENABLE - printf(" e (ElGamal only, no ECDSA)\n"); - #endif - printf(" s=seed\n"); - printf(" v(erbose)\n"); - printf(" q(uiet)\n"); - printf(" h(elp)\n"); - exit(1); -} - -/* - * ...min <= return <= max - */ -static int genRand(int min, int max) -{ - - /* note random() only yields a 31-bit number... */ - - if(max == min) /* avoid % 1 ! */ - return(max); - else - return(min + (random() % (max-min+1))); -} - -static unsigned char *genPasswd(unsigned passwdLength) -{ - unsigned *ip = (unsigned *)passwdPool; - unsigned intCount = passwdLength / 4; - int i; - unsigned char *cp; - unsigned residue = passwdLength & 0x3; - - for (i=0; i MAX_ASCII) { - ac = MIN_ASCII; - } - } - break; - case DT_Random: - intCount = size >> 2; - ip = (unsigned *)dataPool; - for(i=0; i MAX_EXP) { - usage(argv); - } - break; - case 'D': - depth = atoi(&argp[2]); - break; - case 'i': - incr = atoi(&argp[2]); - break; - case 's': - seed = atoi(&argp[2]); - seedSpec = 1; - break; - case 'p': - passwdLen = atoi(&argp[2]); - if(passwdLen == 0) { - usage(argv); - } - break; - case 'e': - elGamalOnly = 1; - break; - case 'v': - verbose = 1; - break; - case 'q': - quiet = 1; - break; - case 'h': - default: - usage(argv); - } - } - - if(seedSpec == 0) { - time((long *)(&seed)); - } - srandom(seed); - passwdPool = malloc(passwdLen); - dataPool = malloc(MAX_DATA_SIZE); - - printf("Starting %s test: loops %d seed %d elGamalOnly %d depth %d\n", - argv[0], loops, seed, elGamalOnly, depth); - - #if 0 - /* debug only */ - { - char s[20]; - printf("attach, then CR to continue: "); - gets(s); - } - #endif 0 - - for(loop=1; ; loop++) { - - ptext = genData(minExp, maxExp, DT_Random, &ptextLen); - passwd = genPasswd(passwdLen); - - /* - * Alternate between ECDSA and ElGamal - */ - if(elGamalOnly) { - doECDSA = 0; - doECDSAVfy = 0; - } - else { - if(loop & 1) { - doECDSA = 1; - if(loop & 2) { - doECDSAVfy = 1; - } - else { - doECDSAVfy = 0; - } - } - else { - doECDSA = 0; - doECDSAVfy = 0; - } - } - if(!quiet) { - printf("..loop %d text size %d ECDSA %d ECDSAVfy %d\n", - loop, ptextLen, doECDSA, doECDSAVfy); - } - if(doTest(ptext, ptextLen, passwd, passwdLen, - verbose, quiet, depth, incr, - doECDSA, doECDSAVfy)) { - exit(1); - } - - if(loops && (loop == loops)) { - break; - } - } - if(!quiet) { - printf("%s test complete\n", argv[0]); - } - return 0; -} diff --git a/libsecurity_cryptkit/lib/CryptKitSA.h b/libsecurity_cryptkit/lib/CryptKitSA.h deleted file mode 100644 index ea9ace18..00000000 --- a/libsecurity_cryptkit/lib/CryptKitSA.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (c) 1998-2004 Apple Computer, Inc. All rights reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - ***************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include diff --git a/libsecurity_cryptkit/lib/NSFEEPublicKeyPrivate.h b/libsecurity_cryptkit/lib/NSFEEPublicKeyPrivate.h deleted file mode 100644 index ed0bc6fd..00000000 --- a/libsecurity_cryptkit/lib/NSFEEPublicKeyPrivate.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * NSFEEPublicKeyPrivate.h - * - * Revision History - * ---------------- - * 21 Aug 96 Doug Mitchell at NeXT - * Created. - */ - -#import "NSFEEPublicKey.h" -#import "elliptic.h" -#import "feeDebug.h" -#import "feePublicKey.h" - -@interface NSFEEPublicKey(Private) - -- (key)minus; -- (key)plus; -#if 0 -- (NSData *)privData; -#endif 0 -- (feePubKey)feePubKey; - -#if FEE_DEBUG -- (void)dump; -#endif FEE_DEBUG -@end diff --git a/libsecurity_cryptkit/lib/README b/libsecurity_cryptkit/lib/README deleted file mode 100644 index f0e6c555..00000000 --- a/libsecurity_cryptkit/lib/README +++ /dev/null @@ -1,221 +0,0 @@ - Apple FEE Library Source, v. 1.0 - Last Update: 26 Sep 2001 - - - NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE - ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER, - INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - EXPOSE YOU TO LIABILITY. - - -This directory contains the source code for Apple's Fast Elliptic -Encryption (FEE) library. All code is written in ANSI C. A UNIX -Makefile is provided. - -Note that all source files in this directory are best viewed with an -editor configured for 8-space tabs, a fixed pitch font, and a window -of at least 80 characters in width. - - -Public Header Files -------------------- - -These files contain the public API used by clients of the FEE library. - - Crypt.h - ------- - A top-level header which includes all of the other public headers. - Typically a client application will only include this file. - - feeTypes.h - ---------- - Common #defines and typedefs used throughout the library. - - feePublicKey.h - -------------- - Functions for generating and manipulating FEE public and private keys, - performing key exchange, and high-level digital signature operations. - - feeDigitalSignature.h - --------------------- - Low-level primitives for performing ElGamal digital signature - operations. Not normally used by clients; high-level functions - for performing signature operations are provided in feePublicKey.h. - - feeECDSA.h - ---------- - Low-level primitives for performing ECDSA digital signature operations. - Not normally used by clients; high-level functions for performing - signature operations are provided in feePublicKey.h. - - feeDES.h - -------- - DES symmetric encryption and decryption functions. - - feeHash.h - --------- - MD5 Hash functions. - - ckSHA1.h - ------ - SHA-1 hash functions. - - feeRandom.h - ----------- - Pseudo-random number generator. - - feeFunctions.h - -------------- - General-purpose C functions. - - feeFEED.h - --------- - Asymmetric encryption functions using the FEE Direct Embedding, - or FEED, algorithm. - - feeFEEDExp.h - ------------ - Asymmetric encryption functions using the Expanding FEED algorithm. - - enc64.h - ------- - Functions for performing encoding and decoding via base-64 IA5 - format, per RFC 1421. - - feeCipherFile.h - CipherFileTypes.h - ------------------ - High-level CipherFile support. Provides encapsulation of ciphertext, - digital signature, and public key strings in a portable format. - - falloc.h - -------- - Memory alloc/free routines. All memory mallocd by CryptKit and - returned to called must be freed via ffree(), declared here. - - -'C' Files ---------- - -In addition to the '.c' files associated with the abovementioned public -headers (e.g., feePublicKey.c, feeCipherFile.c), the FEE library -contains the following source files: - - giantIntegers.[ch] - -------------------- - Large-precision integer arithmetic package. - - elliptic.[ch] - ------------- - Elliptic Curve algebra, Apple "FEE" style. - - ellipticProj.[ch] - ----------------- - Elliptic Curve Algebra using projective coordinates. - - curveParams.[ch], curveParamData.h - ---------------------------------- - Elliptic curve parameters. Declarations of known curves. - - byteRep.[ch] - ------------ - Platform-independent implement implementation of portable - representation of all aggregate data types used in FEE library. - - ckutilities.[ch] - -------------- - Miscellaneous C utilities. - - feeCipherFileAtom.c - CipherFileDES.c - CipherFileFEED.c - ---------------- - CipherFile support. - - ckDES.c - ckMD5.c - ckSHA1_priv.c - ----------- - Low-level primitives for DES, MD5, SHA-1 algorithms. - - -Porting to other platforms --------------------------- - -The FEE library has been built and tested on the Macintosh platform using Metrowerks CodeWarrior, on the OpenStep OS on both the 68k and Pentium platforms, and on Windows NT (on which it was built using the Gnu gcc compiler). - -There are at least 3 files which need to be edited in order to port the -FEE library to other platforms. One is platform.c. This file has two -platform-specific functions: - - void NSGiantRaise(const char *reason); - - This function is called interally in the library in the unlikely - event of a fatal runtime error. The current versions of this - function use printf() to log the reason and call exit(1). - - unsigned createRandomSeed(); - - This function obtains a 32-bit number with which FEE's - pseudo-random number generator is seeded. The implementation - of this function is highly platform-specific and also depends - on the amount of security required from the RNG in a - particular application. Common (and simple) implementations - involve obtaining a high-precision system clock, process - ID values. etc. - - Note that this function is called during a call to feeRandAlloc() - in feeRandom.c. Clients of the FEE library can also avoid this - mechanism by instantiating the RNG via feeRandAllocWithSeed(), - passing in an application-specific seed. - -The file platform.h contains a definition for the endianness of the -current platform. Either __BIG_ENDIAN__ or __LITTLE_ENDIAN__ must -be #defined at compile time. If your compiler does not implicitly -define one of these symbols, edit platform.h appropriately. - -Another file which may be modified during a port is falloc.c. All -memory allocation calls in the library are performed via fmalloc() and -ffree() in falloc.c. The current implementation of falloc.c merely -passes these calls on to the standard malloc() and free(). A port to -another platform may require the use of different memory allocators. - -The giantIntegers module, which implements large integer arithmetic, -allows for specification of platform-dependent digit size. In addition, -provisions are made for implementation of platform-dependent routines -to perform low-level digit arithmetic (single and double precision add, -subtract with carry, double precision multiply, multiply an array -of digits by another digit). The current library contains assembly -languange macros for the Intel and PPC platforms. The specification of -the size of a giant digit, type giantDigit, is found in giantIntegers.h. -The files which use low-level platform-dependent giant arithmentic -include giantPortCommon.h, which select one of several possible header -files. The header giantPortGeneric.h can be specified; this has -no assembly language, but implements the necessary functions using -the C "unsigned long long" type and static lines functions. The API for -the low-level digit functions is the same in all three of the following -files: - - giantPortGeneric.h - giantPort_i486.h - giantPort_PPC.h - -Currently, the implementation of the PPC-specific giant digit routines -is in giantPort_PPC.c; the implementation of the Intels-specific giant -routines is found in both giantPort_i486.h and giantPort_i486.s. - -Building the library --------------------- - -This directory contains a UNIX Makefile. Just type 'make' in the current -(writable) directory to build the library. The result is libFEE.a. - - - Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - -Apple and Macintosh are trademarks of Apple Computer, Inc., registered -in the U.S.A. and other countries. OpenStep is a trademark of NeXT -Software, Inc. registered in the U.S.A. and other countries. All other -trademarks are the property of their respective owners. diff --git a/libsecurity_cryptkit/libsecurity_cryptkit.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_cryptkit/libsecurity_cryptkit.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 43c0bd93..00000000 --- a/libsecurity_cryptkit/libsecurity_cryptkit.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 0535DCBD074A944D00805B04 - - primary - - - 0536B294074BC91A00F9F1AD - - primary - - - 7264322800A8AD0A7F000001 - - primary - - - - - diff --git a/libsecurity_cssm/lib/certextensions.h b/libsecurity_cssm/lib/certextensions.h deleted file mode 100644 index 79e25af4..00000000 --- a/libsecurity_cssm/lib/certextensions.h +++ /dev/null @@ -1,640 +0,0 @@ -/* - * Copyright (c) 2000-2004 Apple Computer, 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@ - * - * CertExtensions.h -- X.509 Cert Extensions as C structs - */ - -#ifndef _CERT_EXTENSIONS_H_ -#define _CERT_EXTENSIONS_H_ - -#include - -/*** - *** Structs for declaring extension-specific data. - ***/ - -/* - * GeneralName, used in AuthorityKeyID, SubjectAltName, and - * IssuerAltName. - * - * For now, we just provide explicit support for the types which are - * represented as IA5Strings, OIDs, and octet strings. Constructed types - * such as EDIPartyName and x400Address are not explicitly handled - * right now and must be encoded and decoded by the caller. (See exception - * for Name and OtherName, below). In those cases the CE_GeneralName.name.Data field - * represents the BER contents octets; CE_GeneralName.name.Length is the - * length of the contents; the tag of the field is not needed - the BER - * encoding uses context-specific implicit tagging. The berEncoded field - * is set to CSSM_TRUE in these case. Simple types have berEncoded = CSSM_FALSE. - * - * In the case of a GeneralName in the form of a Name, we parse the Name - * into a CSSM_X509_NAME and place a pointer to the CSSM_X509_NAME in the - * CE_GeneralName.name.Data field. CE_GeneralName.name.Length is set to - * sizeof(CSSM_X509_NAME). In this case berEncoded is false. - * - * In the case of a GeneralName in the form of a OtherName, we parse the fields - * into a CE_OtherName and place a pointer to the CE_OtherName in the - * CE_GeneralName.name.Data field. CE_GeneralName.name.Length is set to - * sizeof(CE_OtherName). In this case berEncoded is false. - * - * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName - * - * GeneralName ::= CHOICE { - * otherName [0] OtherName - * rfc822Name [1] IA5String, - * dNSName [2] IA5String, - * x400Address [3] ORAddress, - * directoryName [4] Name, - * ediPartyName [5] EDIPartyName, - * uniformResourceIdentifier [6] IA5String, - * iPAddress [7] OCTET STRING, - * registeredID [8] OBJECT IDENTIFIER} - * - * OtherName ::= SEQUENCE { - * type-id OBJECT IDENTIFIER, - * value [0] EXPLICIT ANY DEFINED BY type-id } - * - * EDIPartyName ::= SEQUENCE { - * nameAssigner [0] DirectoryString OPTIONAL, - * partyName [1] DirectoryString } - */ -typedef enum __CE_GeneralNameType { - GNT_OtherName = 0, - GNT_RFC822Name, - GNT_DNSName, - GNT_X400Address, - GNT_DirectoryName, - GNT_EdiPartyName, - GNT_URI, - GNT_IPAddress, - GNT_RegisteredID -} CE_GeneralNameType; - -typedef struct __CE_OtherName { - CSSM_OID typeId; - CSSM_DATA value; // unparsed, BER-encoded -} CE_OtherName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -typedef struct __CE_GeneralName { - CE_GeneralNameType nameType; // GNT_RFC822Name, etc. - CSSM_BOOL berEncoded; - CSSM_DATA name; -} CE_GeneralName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -typedef struct __CE_GeneralNames { - uint32 numNames; - CE_GeneralName *generalName; -} CE_GeneralNames DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* - * id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } - * - * AuthorityKeyIdentifier ::= SEQUENCE { - * keyIdentifier [0] KeyIdentifier OPTIONAL, - * authorityCertIssuer [1] GeneralNames OPTIONAL, - * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } - * - * KeyIdentifier ::= OCTET STRING - * - * CSSM OID = CSSMOID_AuthorityKeyIdentifier - */ -typedef struct __CE_AuthorityKeyID { - CSSM_BOOL keyIdentifierPresent; - CSSM_DATA keyIdentifier; - CSSM_BOOL generalNamesPresent; - CE_GeneralNames *generalNames; - CSSM_BOOL serialNumberPresent; - CSSM_DATA serialNumber; -} CE_AuthorityKeyID DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* - * id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } - * SubjectKeyIdentifier ::= KeyIdentifier - * - * CSSM OID = CSSMOID_SubjectKeyIdentifier - */ -typedef CSSM_DATA CE_SubjectKeyID DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* - * id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } - * - * KeyUsage ::= BIT STRING { - * digitalSignature (0), - * nonRepudiation (1), - * keyEncipherment (2), - * dataEncipherment (3), - * keyAgreement (4), - * keyCertSign (5), - * cRLSign (6), - * encipherOnly (7), - * decipherOnly (8) } - * - * CSSM OID = CSSMOID_KeyUsage - * - */ -typedef uint16 CE_KeyUsage DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -#define CE_KU_DigitalSignature 0x8000 -#define CE_KU_NonRepudiation 0x4000 -#define CE_KU_KeyEncipherment 0x2000 -#define CE_KU_DataEncipherment 0x1000 -#define CE_KU_KeyAgreement 0x0800 -#define CE_KU_KeyCertSign 0x0400 -#define CE_KU_CRLSign 0x0200 -#define CE_KU_EncipherOnly 0x0100 -#define CE_KU_DecipherOnly 0x0080 - -/* - * id-ce-cRLReason OBJECT IDENTIFIER ::= { id-ce 21 } - * - * -- reasonCode ::= { CRLReason } - * - * CRLReason ::= ENUMERATED { - * unspecified (0), - * keyCompromise (1), - * cACompromise (2), - * affiliationChanged (3), - * superseded (4), - * cessationOfOperation (5), - * certificateHold (6), - * removeFromCRL (8) } - * - * CSSM OID = CSSMOID_CrlReason - * - */ -typedef uint32 CE_CrlReason DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -#define CE_CR_Unspecified 0 -#define CE_CR_KeyCompromise 1 -#define CE_CR_CACompromise 2 -#define CE_CR_AffiliationChanged 3 -#define CE_CR_Superseded 4 -#define CE_CR_CessationOfOperation 5 -#define CE_CR_CertificateHold 6 -#define CE_CR_RemoveFromCRL 8 - -/* - * id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } - * - * SubjectAltName ::= GeneralNames - * - * CSSM OID = CSSMOID_SubjectAltName - * - * GeneralNames defined above. - */ - -/* - * id-ce-extKeyUsage OBJECT IDENTIFIER ::= {id-ce 37} - * - * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId* - * - * KeyPurposeId ::= OBJECT IDENTIFIER - * - * CSSM OID = CSSMOID_ExtendedKeyUsage - */ -typedef struct __CE_ExtendedKeyUsage { - uint32 numPurposes; - CSSM_OID_PTR purposes; // in Intel pre-encoded format -} CE_ExtendedKeyUsage; - -/* - * id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } - * - * BasicConstraints ::= SEQUENCE { - * cA BOOLEAN DEFAULT FALSE, - * pathLenConstraint INTEGER (0..MAX) OPTIONAL } - * - * CSSM OID = CSSMOID_BasicConstraints - */ -typedef struct __CE_BasicConstraints { - CSSM_BOOL cA; - CSSM_BOOL pathLenConstraintPresent; - uint32 pathLenConstraint; -} CE_BasicConstraints DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* - * id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } - * - * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation - * - * PolicyInformation ::= SEQUENCE { - * policyIdentifier CertPolicyId, - * policyQualifiers SEQUENCE SIZE (1..MAX) OF - * PolicyQualifierInfo OPTIONAL } - * - * CertPolicyId ::= OBJECT IDENTIFIER - * - * PolicyQualifierInfo ::= SEQUENCE { - * policyQualifierId PolicyQualifierId, - * qualifier ANY DEFINED BY policyQualifierId } - * - * -- policyQualifierIds for Internet policy qualifiers - * - * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } - * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } - * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } - * - * PolicyQualifierId ::= - * OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) - * - * Qualifier ::= CHOICE { - * cPSuri CPSuri, - * userNotice UserNotice } - * - * CPSuri ::= IA5String - * - * UserNotice ::= SEQUENCE { - * noticeRef NoticeReference OPTIONAL, - * explicitText DisplayText OPTIONAL} - * - * NoticeReference ::= SEQUENCE { - * organization DisplayText, - * noticeNumbers SEQUENCE OF INTEGER } - * - * DisplayText ::= CHOICE { - * visibleString VisibleString (SIZE (1..200)), - * bmpString BMPString (SIZE (1..200)), - * utf8String UTF8String (SIZE (1..200)) } - * - * CSSM OID = CSSMOID_CertificatePolicies - * - * We only support down to the level of Qualifier, and then only the CPSuri - * choice. UserNotice is transmitted to and from this library as a raw - * CSSM_DATA containing the BER-encoded UserNotice sequence. - */ - -typedef struct __CE_PolicyQualifierInfo { - CSSM_OID policyQualifierId; // CSSMOID_QT_CPS, CSSMOID_QT_UNOTICE - CSSM_DATA qualifier; // CSSMOID_QT_CPS: IA5String contents - // CSSMOID_QT_UNOTICE : Sequence contents -} CE_PolicyQualifierInfo DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -typedef struct __CE_PolicyInformation { - CSSM_OID certPolicyId; - uint32 numPolicyQualifiers; // size of *policyQualifiers; - CE_PolicyQualifierInfo *policyQualifiers; -} CE_PolicyInformation DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -typedef struct __CE_CertPolicies { - uint32 numPolicies; // size of *policies; - CE_PolicyInformation *policies; -} CE_CertPolicies DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* - * netscape-cert-type, a bit string. - * - * CSSM OID = CSSMOID_NetscapeCertType - * - * Bit fields defined in oidsattr.h: CE_NCT_SSL_Client, etc. - */ -typedef uint16 CE_NetscapeCertType DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* - * CRLDistributionPoints. - * - * id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } - * - * cRLDistributionPoints ::= { - * CRLDistPointsSyntax } - * - * CRLDistPointsSyntax ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint - * - * NOTE: RFC 2459 claims that the tag for the optional DistributionPointName - * is IMPLICIT as shown here, but in practice it is EXPLICIT. It has to be - - * because the underlying type also uses an implicit tag for distinguish - * between CHOICEs. - * - * DistributionPoint ::= SEQUENCE { - * distributionPoint [0] DistributionPointName OPTIONAL, - * reasons [1] ReasonFlags OPTIONAL, - * cRLIssuer [2] GeneralNames OPTIONAL } - * - * DistributionPointName ::= CHOICE { - * fullName [0] GeneralNames, - * nameRelativeToCRLIssuer [1] RelativeDistinguishedName } - * - * ReasonFlags ::= BIT STRING { - * unused (0), - * keyCompromise (1), - * cACompromise (2), - * affiliationChanged (3), - * superseded (4), - * cessationOfOperation (5), - * certificateHold (6) } - * - * CSSM OID = CSSMOID_CrlDistributionPoints - */ - -/* - * Note that this looks similar to CE_CrlReason, but that's an enum and this - * is an OR-able bit string. - */ -typedef uint8 CE_CrlDistReasonFlags DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -#define CE_CD_Unspecified 0x80 -#define CE_CD_KeyCompromise 0x40 -#define CE_CD_CACompromise 0x20 -#define CE_CD_AffiliationChanged 0x10 -#define CE_CD_Superseded 0x08 -#define CE_CD_CessationOfOperation 0x04 -#define CE_CD_CertificateHold 0x02 - -typedef enum __CE_CrlDistributionPointNameType { - CE_CDNT_FullName, - CE_CDNT_NameRelativeToCrlIssuer -} CE_CrlDistributionPointNameType DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -typedef struct __CE_DistributionPointName { - CE_CrlDistributionPointNameType nameType; - union { - CE_GeneralNames *fullName; - CSSM_X509_RDN_PTR rdn; - } dpn; -} CE_DistributionPointName DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* - * The top-level CRLDistributionPoint. - * All fields are optional; NULL pointers indicate absence. - */ -typedef struct __CE_CRLDistributionPoint { - CE_DistributionPointName *distPointName; - CSSM_BOOL reasonsPresent; - CE_CrlDistReasonFlags reasons; - CE_GeneralNames *crlIssuer; -} CE_CRLDistributionPoint DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -typedef struct __CE_CRLDistPointsSyntax { - uint32 numDistPoints; - CE_CRLDistributionPoint *distPoints; -} CE_CRLDistPointsSyntax DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* - * Authority Information Access and Subject Information Access. - * - * CSSM OID = CSSMOID_AuthorityInfoAccess - * CSSM OID = CSSMOID_SubjectInfoAccess - * - * SubjAuthInfoAccessSyntax ::= - * SEQUENCE SIZE (1..MAX) OF AccessDescription - * - * AccessDescription ::= SEQUENCE { - * accessMethod OBJECT IDENTIFIER, - * accessLocation GeneralName } - */ -typedef struct __CE_AccessDescription { - CSSM_OID accessMethod; - CE_GeneralName accessLocation; -} CE_AccessDescription DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -typedef struct __CE_AuthorityInfoAccess { - uint32 numAccessDescriptions; - CE_AccessDescription *accessDescriptions; -} CE_AuthorityInfoAccess DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* - * Qualified Certificate Statement support, per RFC 3739. - * - * First, NameRegistrationAuthorities, a component of - * SemanticsInformation; it's the same as a GeneralNames - - * a sequence of GeneralName. - */ -typedef CE_GeneralNames CE_NameRegistrationAuthorities DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* - * SemanticsInformation, identified as the qcType field - * of a CE_QC_Statement for statementId value id-qcs-pkixQCSyntax-v2. - * Both fields optional; at least one must be present. - */ -typedef struct __CE_SemanticsInformation { - CSSM_OID *semanticsIdentifier; - CE_NameRegistrationAuthorities *nameRegistrationAuthorities; -} CE_SemanticsInformation DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* - * One Qualified Certificate Statement. - * The statementId OID is required; zero or one of {semanticsInfo, - * otherInfo} can be valid, depending on the value of statementId. - * For statementId id-qcs-pkixQCSyntax-v2 (CSSMOID_OID_QCS_SYNTAX_V2), - * the semanticsInfo field may be present; otherwise, DER-encoded - * information may be present in otherInfo. Both semanticsInfo and - * otherInfo are optional. - */ -typedef struct __CE_QC_Statement { - CSSM_OID statementId; - CE_SemanticsInformation *semanticsInfo; - CSSM_DATA *otherInfo; -} CE_QC_Statement DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* - * The top-level Qualified Certificate Statements extension. - */ -typedef struct __CE_QC_Statements { - uint32 numQCStatements; - CE_QC_Statement *qcStatements; -} CE_QC_Statements DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/*** CRL extensions ***/ - -/* - * cRLNumber, an integer. - * - * CSSM OID = CSSMOID_CrlNumber - */ -typedef uint32 CE_CrlNumber; - -/* - * deltaCRLIndicator, an integer. - * - * CSSM OID = CSSMOID_DeltaCrlIndicator - */ -typedef uint32 CE_DeltaCrl; - -/* - * IssuingDistributionPoint - * - * id-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-ce 28 } - * - * issuingDistributionPoint ::= SEQUENCE { - * distributionPoint [0] DistributionPointName OPTIONAL, - * onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE, - * onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE, - * onlySomeReasons [3] ReasonFlags OPTIONAL, - * indirectCRL [4] BOOLEAN DEFAULT FALSE } - * - * CSSM OID = CSSMOID_IssuingDistributionPoint - */ -typedef struct __CE_IssuingDistributionPoint { - CE_DistributionPointName *distPointName; // optional - CSSM_BOOL onlyUserCertsPresent; - CSSM_BOOL onlyUserCerts; - CSSM_BOOL onlyCACertsPresent; - CSSM_BOOL onlyCACerts; - CSSM_BOOL onlySomeReasonsPresent; - CE_CrlDistReasonFlags onlySomeReasons; - CSSM_BOOL indirectCrlPresent; - CSSM_BOOL indirectCrl; -} CE_IssuingDistributionPoint DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* - * NameConstraints - * - * id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } - * - * NameConstraints ::= SEQUENCE { - * permittedSubtrees [0] GeneralSubtrees OPTIONAL, - * excludedSubtrees [1] GeneralSubtrees OPTIONAL } - * - * GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree - * - * GeneralSubtree ::= SEQUENCE { - * base GeneralName, - * minimum [0] BaseDistance DEFAULT 0, - * maximum [1] BaseDistance OPTIONAL } - * - * BaseDistance ::= INTEGER (0..MAX) - */ -typedef struct __CE_GeneralSubtree { - CE_GeneralNames *base; - uint32 minimum; // default=0 - CSSM_BOOL maximumPresent; - uint32 maximum; // optional -} CE_GeneralSubtree DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -typedef struct __CE_GeneralSubtrees { - uint32 numSubtrees; - CE_GeneralSubtree *subtrees; -} CE_GeneralSubtrees DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -typedef struct __CE_NameConstraints { - CE_GeneralSubtrees *permitted; // optional - CE_GeneralSubtrees *excluded; // optional -} CE_NameConstraints DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* - * PolicyMappings - * - * id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } - * - * PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { - * issuerDomainPolicy CertPolicyId, - * subjectDomainPolicy CertPolicyId } - * - * Note that both issuer and subject policy OIDs are required, - * and are stored by value in this structure. - */ -typedef struct __CE_PolicyMapping { - CSSM_OID issuerDomainPolicy; - CSSM_OID subjectDomainPolicy; -} CE_PolicyMapping DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -typedef struct __CE_PolicyMappings { - uint32 numPolicyMappings; - CE_PolicyMapping *policyMappings; -} CE_PolicyMappings DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* - * PolicyConstraints - * - * id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } - * - * PolicyConstraints ::= SEQUENCE { - * requireExplicitPolicy [0] SkipCerts OPTIONAL, - * inhibitPolicyMapping [1] SkipCerts OPTIONAL } - * - * SkipCerts ::= INTEGER (0..MAX) - */ -typedef struct __CE_PolicyConstraints { - CSSM_BOOL requireExplicitPolicyPresent; - uint32 requireExplicitPolicy; // optional - CSSM_BOOL inhibitPolicyMappingPresent; - uint32 inhibitPolicyMapping; // optional -} CE_PolicyConstraints DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* - * InhibitAnyPolicy, an integer. - * - * CSSM OID = CSSMOID_InhibitAnyPolicy - */ -typedef uint32 CE_InhibitAnyPolicy DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* - * An enumerated list identifying one of the above per-extension - * structs. - */ -typedef enum __CE_DataType { - DT_AuthorityKeyID, // CE_AuthorityKeyID - DT_SubjectKeyID, // CE_SubjectKeyID - DT_KeyUsage, // CE_KeyUsage - DT_SubjectAltName, // implies CE_GeneralName - DT_IssuerAltName, // implies CE_GeneralName - DT_ExtendedKeyUsage, // CE_ExtendedKeyUsage - DT_BasicConstraints, // CE_BasicConstraints - DT_CertPolicies, // CE_CertPolicies - DT_NetscapeCertType, // CE_NetscapeCertType - DT_CrlNumber, // CE_CrlNumber - DT_DeltaCrl, // CE_DeltaCrl - DT_CrlReason, // CE_CrlReason - DT_CrlDistributionPoints, // CE_CRLDistPointsSyntax - DT_IssuingDistributionPoint,// CE_IssuingDistributionPoint - DT_AuthorityInfoAccess, // CE_AuthorityInfoAccess - DT_Other, // unknown, raw data as a CSSM_DATA - DT_QC_Statements, // CE_QC_Statements - DT_NameConstraints, // CE_NameConstraints - DT_PolicyMappings, // CE_PolicyMappings - DT_PolicyConstraints, // CE_PolicyConstraints - DT_InhibitAnyPolicy // CE_InhibitAnyPolicy -} CE_DataType; - -/* - * One unified representation of all the cert and CRL extensions we know about. - */ -typedef union { - CE_AuthorityKeyID authorityKeyID; - CE_SubjectKeyID subjectKeyID; - CE_KeyUsage keyUsage; - CE_GeneralNames subjectAltName; - CE_GeneralNames issuerAltName; - CE_ExtendedKeyUsage extendedKeyUsage; - CE_BasicConstraints basicConstraints; - CE_CertPolicies certPolicies; - CE_NetscapeCertType netscapeCertType; - CE_CrlNumber crlNumber; - CE_DeltaCrl deltaCrl; - CE_CrlReason crlReason; - CE_CRLDistPointsSyntax crlDistPoints; - CE_IssuingDistributionPoint issuingDistPoint; - CE_AuthorityInfoAccess authorityInfoAccess; - CE_QC_Statements qualifiedCertStatements; - CE_NameConstraints nameConstraints; - CE_PolicyMappings policyMappings; - CE_PolicyConstraints policyConstraints; - CE_InhibitAnyPolicy inhibitAnyPolicy; - CSSM_DATA rawData; // unknown, not decoded -} CE_Data DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -typedef struct __CE_DataAndType { - CE_DataType type; - CE_Data extension; - CSSM_BOOL critical; -} CE_DataAndType DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -#endif /* _CERT_EXTENSIONS_H_ */ diff --git a/libsecurity_cssm/lib/cssmapple.h b/libsecurity_cssm/lib/cssmapple.h deleted file mode 100644 index d31eb406..00000000 --- a/libsecurity_cssm/lib/cssmapple.h +++ /dev/null @@ -1,1158 +0,0 @@ -/* - * Copyright (c) 2000-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@ - * - * cssmapple.h -- CSSM features specific to Apple's Implementation - */ - -#ifndef _CSSMAPPLE_H_ -#define _CSSMAPPLE_H_ 1 - -#include -#include -#include /* for CSSM_APPLE_TP_CERT_REQUEST fields */ -#include /* ditto */ -#include /* for the BSD *_t types */ -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Guids for standard Apple addin modules. */ - -/* CSSM itself: {87191ca0-0fc9-11d4-849a-000502b52122} */ -extern const CSSM_GUID gGuidCssm; - -/* File based DL (aka "Keychain DL"): {87191ca1-0fc9-11d4-849a-000502b52122} */ -extern const CSSM_GUID gGuidAppleFileDL; - -/* Core CSP (local space): {87191ca2-0fc9-11d4-849a-000502b52122} */ -extern const CSSM_GUID gGuidAppleCSP; - -/* Secure CSP/DL (aka "Keychain CSPDL): {87191ca3-0fc9-11d4-849a-000502b52122} */ -extern const CSSM_GUID gGuidAppleCSPDL; - -/* X509 Certificate CL: {87191ca4-0fc9-11d4-849a-000502b52122} */ -extern const CSSM_GUID gGuidAppleX509CL; - -/* X509 Certificate TP: {87191ca5-0fc9-11d4-849a-000502b52122} */ -extern const CSSM_GUID gGuidAppleX509TP; - -/* DLAP/OpenDirectory access DL: {87191ca6-0fc9-11d4-849a-000502b52122} */ -extern const CSSM_GUID gGuidAppleLDAPDL; - -/* TP for ".mac" related policies: {87191ca7-0fc9-11d4-849a-000502b52122} */ -extern const CSSM_GUID gGuidAppleDotMacTP; - -/* Smartcard CSP/DL: {87191ca8-0fc9-11d4-849a-000502b52122} */ -extern const CSSM_GUID gGuidAppleSdCSPDL; - -/* DL for ".mac" certificate access: {87191ca9-0fc9-11d4-849a-000502b52122} */ -extern const CSSM_GUID gGuidAppleDotMacDL; - - -/* Apple defined WORDID values */ -enum -{ - CSSM_WORDID_KEYCHAIN_PROMPT = CSSM_WORDID_VENDOR_START, - CSSM_WORDID_KEYCHAIN_LOCK, - CSSM_WORDID_KEYCHAIN_CHANGE_LOCK, - CSSM_WORDID_PROCESS, - CSSM_WORDID__RESERVED_1, /* was used in 10.2 test seeds; no longer in use */ - CSSM_WORDID_SYMMETRIC_KEY, - CSSM_WORDID_SYSTEM, - CSSM_WORDID_KEY, - CSSM_WORDID_PIN, - CSSM_WORDID_PREAUTH, - CSSM_WORDID_PREAUTH_SOURCE, - CSSM_WORDID_ASYMMETRIC_KEY, - CSSM_WORDID__FIRST_UNUSED -}; - -/* Apple defined ACL subject and credential types */ -enum -{ - CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT = CSSM_WORDID_KEYCHAIN_PROMPT, - CSSM_ACL_SUBJECT_TYPE_PROCESS = CSSM_WORDID_PROCESS, - CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE = CSSM_WORDID_SIGNATURE, - CSSM_ACL_SUBJECT_TYPE_COMMENT = CSSM_WORDID_COMMENT, - 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 -}; - -enum -{ - CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT = CSSM_WORDID_KEYCHAIN_PROMPT, - CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK = CSSM_WORDID_KEYCHAIN_LOCK, - CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK = CSSM_WORDID_KEYCHAIN_CHANGE_LOCK, - CSSM_SAMPLE_TYPE_PROCESS = CSSM_WORDID_PROCESS, - CSSM_SAMPLE_TYPE_COMMENT = CSSM_WORDID_COMMENT, - CSSM_SAMPLE_TYPE_RETRY_ID = CSSM_WORDID_PROPAGATE, - CSSM_SAMPLE_TYPE_SYMMETRIC_KEY = CSSM_WORDID_SYMMETRIC_KEY, - CSSM_SAMPLE_TYPE_PREAUTH = CSSM_WORDID_PREAUTH, - CSSM_SAMPLE_TYPE_ASYMMETRIC_KEY = CSSM_WORDID_ASYMMETRIC_KEY - // there is no CSSM_SAMPLE_TYPE_PREAUTH_SOURCE -}; - - -/* Apple-defined ACL authorization tags */ -enum { - CSSM_ACL_AUTHORIZATION_CHANGE_ACL = CSSM_ACL_AUTHORIZATION_TAG_VENDOR_DEFINED_START, - CSSM_ACL_AUTHORIZATION_CHANGE_OWNER, - - // the "pre-auth" tags form a contiguous range of (up to) 64K pre-authorizations - CSSM_ACL_AUTHORIZATION_PREAUTH_BASE = - CSSM_ACL_AUTHORIZATION_TAG_VENDOR_DEFINED_START + 0x1000000, - CSSM_ACL_AUTHORIZATION_PREAUTH_END = CSSM_ACL_AUTHORIZATION_PREAUTH_BASE + 0x10000 -}; - -/* pre-authorization conversions (auth-tag to slot and back) */ -#define CSSM_ACL_AUTHORIZATION_PREAUTH(slot) \ - (CSSM_ACL_AUTHORIZATION_PREAUTH_BASE + (slot)) -#define CSSM_ACL_AUTHORIZATION_PREAUTH_SLOT(auth) \ - ((auth) - CSSM_ACL_AUTHORIZATION_PREAUTH_BASE) -#define CSSM_ACL_AUTHORIZATION_IS_PREAUTH(auth) \ - ((auth) >= CSSM_ACL_AUTHORIZATION_PREAUTH_BASE && \ - (auth) < CSSM_ACL_AUTHORIZATION_PREAUTH_END) - - -/* Parameters and structures for Apple-defined ACL subjects and samples */ - -enum { /* types of code signatures - item 1 of CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE subjects */ - CSSM_ACL_CODE_SIGNATURE_INVALID = 0, /* standard OS X code signature */ - CSSM_ACL_CODE_SIGNATURE_OSX = 1 /* standard OS X code signature */ -}; - -/* ACL subjects of type PROCESS */ - -enum { /* PROCESS_SUBJECT mask fields */ - CSSM_ACL_MATCH_UID = 0x01, /* match userid against uid field */ - CSSM_ACL_MATCH_GID = 0x02, /* match groupid against gid field */ - CSSM_ACL_MATCH_HONOR_ROOT = 0x100, /* let root (uid 0) match any userid */ - CSSM_ACL_MATCH_BITS = CSSM_ACL_MATCH_UID | CSSM_ACL_MATCH_GID -}; - -enum { /* PROCESS_SUBJECT structure version field */ - CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION = 0x101 -}; - -typedef struct cssm_acl_process_subject_selector { /* PROCESS_SUBJECT selector */ - uint16 version; /* version of this selector */ - uint16 mask; /* active fields mask */ - uint32 uid; /* effective user id match */ - uint32 gid; /* effective group id match */ -} CSSM_ACL_PROCESS_SUBJECT_SELECTOR; - -/* ACL subjects of type KEYCHAIN_PROMPT */ - -enum { /* KEYCHAIN_PROMPT structure version field */ - CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION = 0x101 -}; - -enum { /* KEYCHAIN_PROMPT operational flags */ - CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE = 0x0001, /* require re-entering of passphrase */ - /* the following bits are ignored by 10.4 and earlier */ - CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED = 0x0010, /* prompt for unsigned clients */ - CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED_ACT = 0x0020, /* UNSIGNED bit overrides system default */ - CSSM_ACL_KEYCHAIN_PROMPT_INVALID = 0x0040, /* prompt for invalid signed clients */ - CSSM_ACL_KEYCHAIN_PROMPT_INVALID_ACT = 0x0080, /* INVALID bit overrides system default */ -}; - -typedef struct cssm_acl_keychain_prompt_selector { /* KEYCHAIN_PROMPT selector */ - uint16 version; /* version of this selector */ - uint16 flags; /* flag bits */ -} CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR; - -/* ACL subjects of type CSSM_ACL_SUBJECT_TYPE_PREAUTH_SOURCE */ -typedef uint32 CSSM_ACL_PREAUTH_TRACKING_STATE; -enum { /* preauth tracking state */ - CSSM_ACL_PREAUTH_TRACKING_COUNT_MASK = 0xff, /* mask for count status */ - CSSM_ACL_PREAUTH_TRACKING_BLOCKED = 0, /* retries exhausted; the slot is blocked */ - /* 0 .. 255 is a count of (re)tries remaining */ - - /* bits or'ed into any count given */ - CSSM_ACL_PREAUTH_TRACKING_UNKNOWN = 0x40000000, /* status of slot is unknown (ignore count) */ - CSSM_ACL_PREAUTH_TRACKING_AUTHORIZED = 0x80000000 /* the slot is currently authorized (or'ed in) */ -}; - - -/* Apple defined values of a CSSM_DB_ACCESS_TYPE */ -enum { - CSSM_DB_ACCESS_RESET = 0x10000 /* clear pre-authentications (or'ed bit) */ -}; - - -/* Apple defined algorithm IDs */ -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) device, 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_SHA224WithECDSA, /* ECDSA signature on SHA224 digest */ - CSSM_ALGID_SHA256WithECDSA, /* ECDSA signature on SHA256 digest */ - CSSM_ALGID_SHA384WithECDSA, /* ECDSA signature on SHA384 digest */ - CSSM_ALGID_SHA512WithECDSA, /* ECDSA signature on SHA512 digest */ - CSSM_ALGID_ECDSA_SPECIFIED, /* ECDSA with separate digest algorithm specifier */ - CSSM_ALGID_ECDH_X963_KDF, /* ECDH with X9.63 key derivation */ - CSSM_ALGID__FIRST_UNUSED -}; - -/* Apple defined padding */ -enum -{ - /* RFC 2246 section E.2 for SSLv2 rollback detection */ - CSSM_PADDING_APPLE_SSLv2 = CSSM_PADDING_VENDOR_DEFINED -}; - - -/* Apple defined keyblob formats */ -enum { - CSSM_KEYBLOB_RAW_FORMAT_VENDOR_DEFINED = 0x80000000 -}; -enum { - /* X509 SubjectPublicKeyInfo */ - CSSM_KEYBLOB_RAW_FORMAT_X509 = CSSM_KEYBLOB_RAW_FORMAT_VENDOR_DEFINED, - /* OpenSSH v1 */ - CSSM_KEYBLOB_RAW_FORMAT_OPENSSH, - /* openssl-style DSA private key */ - CSSM_KEYBLOB_RAW_FORMAT_OPENSSL, - /* OpenSSH v2 */ - CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2 -}; - -/* Apple adds some "common" error codes. CDSA does not define an official start value for this. */ -enum -{ - CSSM_CUSTOM_COMMON_ERROR_EXTENT = 0x00e0, - - CSSM_ERRCODE_NO_USER_INTERACTION = 0x00e0, - CSSM_ERRCODE_USER_CANCELED = 0x00e1, - CSSM_ERRCODE_SERVICE_NOT_AVAILABLE = 0x00e2, - CSSM_ERRCODE_INSUFFICIENT_CLIENT_IDENTIFICATION = 0x00e3, - CSSM_ERRCODE_DEVICE_RESET = 0x00e4, - CSSM_ERRCODE_DEVICE_FAILED = 0x00e5, - CSSM_ERRCODE_IN_DARK_WAKE = 0x00e6 -}; - -enum { - CSSMERR_CSSM_NO_USER_INTERACTION = CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_NO_USER_INTERACTION, - CSSMERR_AC_NO_USER_INTERACTION = CSSM_AC_BASE_ERROR + CSSM_ERRCODE_NO_USER_INTERACTION, - CSSMERR_CSP_NO_USER_INTERACTION = CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_NO_USER_INTERACTION, - CSSMERR_CL_NO_USER_INTERACTION = CSSM_CL_BASE_ERROR + CSSM_ERRCODE_NO_USER_INTERACTION, - CSSMERR_DL_NO_USER_INTERACTION = CSSM_DL_BASE_ERROR + CSSM_ERRCODE_NO_USER_INTERACTION, - CSSMERR_TP_NO_USER_INTERACTION = CSSM_TP_BASE_ERROR + CSSM_ERRCODE_NO_USER_INTERACTION, - - CSSMERR_CSSM_USER_CANCELED = CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_USER_CANCELED, - CSSMERR_AC_USER_CANCELED = CSSM_AC_BASE_ERROR + CSSM_ERRCODE_USER_CANCELED, - CSSMERR_CSP_USER_CANCELED = CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_USER_CANCELED, - CSSMERR_CL_USER_CANCELED = CSSM_CL_BASE_ERROR + CSSM_ERRCODE_USER_CANCELED, - CSSMERR_DL_USER_CANCELED = CSSM_DL_BASE_ERROR + CSSM_ERRCODE_USER_CANCELED, - CSSMERR_TP_USER_CANCELED = CSSM_TP_BASE_ERROR + CSSM_ERRCODE_USER_CANCELED, - - CSSMERR_CSSM_SERVICE_NOT_AVAILABLE = CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_SERVICE_NOT_AVAILABLE, - CSSMERR_AC_SERVICE_NOT_AVAILABLE = CSSM_AC_BASE_ERROR + CSSM_ERRCODE_SERVICE_NOT_AVAILABLE, - CSSMERR_CSP_SERVICE_NOT_AVAILABLE = CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_SERVICE_NOT_AVAILABLE, - CSSMERR_CL_SERVICE_NOT_AVAILABLE = CSSM_CL_BASE_ERROR + CSSM_ERRCODE_SERVICE_NOT_AVAILABLE, - CSSMERR_DL_SERVICE_NOT_AVAILABLE = CSSM_DL_BASE_ERROR + CSSM_ERRCODE_SERVICE_NOT_AVAILABLE, - CSSMERR_TP_SERVICE_NOT_AVAILABLE = CSSM_TP_BASE_ERROR + CSSM_ERRCODE_SERVICE_NOT_AVAILABLE, - - CSSMERR_CSSM_INSUFFICIENT_CLIENT_IDENTIFICATION = CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_INSUFFICIENT_CLIENT_IDENTIFICATION, - CSSMERR_AC_INSUFFICIENT_CLIENT_IDENTIFICATION = CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INSUFFICIENT_CLIENT_IDENTIFICATION, - CSSMERR_CSP_INSUFFICIENT_CLIENT_IDENTIFICATION = CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INSUFFICIENT_CLIENT_IDENTIFICATION, - CSSMERR_CL_INSUFFICIENT_CLIENT_IDENTIFICATION = CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INSUFFICIENT_CLIENT_IDENTIFICATION, - CSSMERR_DL_INSUFFICIENT_CLIENT_IDENTIFICATION = CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INSUFFICIENT_CLIENT_IDENTIFICATION, - CSSMERR_TP_INSUFFICIENT_CLIENT_IDENTIFICATION = CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INSUFFICIENT_CLIENT_IDENTIFICATION, - - CSSMERR_CSSM_DEVICE_RESET = CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_DEVICE_RESET, - CSSMERR_AC_DEVICE_RESET = CSSM_AC_BASE_ERROR + CSSM_ERRCODE_DEVICE_RESET, - CSSMERR_CSP_DEVICE_RESET = CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_DEVICE_RESET, - CSSMERR_CL_DEVICE_RESET = CSSM_CL_BASE_ERROR + CSSM_ERRCODE_DEVICE_RESET, - CSSMERR_DL_DEVICE_RESET = CSSM_DL_BASE_ERROR + CSSM_ERRCODE_DEVICE_RESET, - CSSMERR_TP_DEVICE_RESET = CSSM_TP_BASE_ERROR + CSSM_ERRCODE_DEVICE_RESET, - - CSSMERR_CSSM_DEVICE_FAILED = CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_DEVICE_FAILED, - CSSMERR_AC_DEVICE_FAILED = CSSM_AC_BASE_ERROR + CSSM_ERRCODE_DEVICE_FAILED, - CSSMERR_CSP_DEVICE_FAILED = CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_DEVICE_FAILED, - CSSMERR_CL_DEVICE_FAILED = CSSM_CL_BASE_ERROR + CSSM_ERRCODE_DEVICE_FAILED, - CSSMERR_DL_DEVICE_FAILED = CSSM_DL_BASE_ERROR + CSSM_ERRCODE_DEVICE_FAILED, - CSSMERR_TP_DEVICE_FAILED = CSSM_TP_BASE_ERROR + CSSM_ERRCODE_DEVICE_FAILED, - - CSSMERR_CSSM_IN_DARK_WAKE = CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_IN_DARK_WAKE, - CSSMERR_AC_IN_DARK_WAKE = CSSM_AC_BASE_ERROR + CSSM_ERRCODE_IN_DARK_WAKE, - CSSMERR_CSP_IN_DARK_WAKE = CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_IN_DARK_WAKE, - CSSMERR_CL_IN_DARK_WAKE = CSSM_CL_BASE_ERROR + CSSM_ERRCODE_IN_DARK_WAKE, - CSSMERR_DL_IN_DARK_WAKE = CSSM_DL_BASE_ERROR + CSSM_ERRCODE_IN_DARK_WAKE, - CSSMERR_TP_IN_DARK_WAKE = CSSM_TP_BASE_ERROR + CSSM_ERRCODE_IN_DARK_WAKE -}; - -/* AppleCSPDL, AppleCSP private error codes. */ -enum { - CSSMERR_CSP_APPLE_ADD_APPLICATION_ACL_SUBJECT = CSSM_CSP_PRIVATE_ERROR + 0, - /* - * An attempt was made to use a public key which is incomplete due to - * the lack of algorithm-specific parameters. - */ - CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE = CSSM_CSP_PRIVATE_ERROR + 1, - - /* a code signature match failed */ - CSSMERR_CSP_APPLE_SIGNATURE_MISMATCH = CSSM_CSP_PRIVATE_ERROR + 2, - - /* Key StartDate/EndDate invalid */ - CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE = CSSM_CSP_PRIVATE_ERROR + 3, - CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE = CSSM_CSP_PRIVATE_ERROR + 4, - - /* Keychain Syncing error codes */ - CSSMERR_CSPDL_APPLE_DL_CONVERSION_ERROR = CSSM_CSP_PRIVATE_ERROR + 5, - - /* SSLv2 padding check: rollback attack detected */ - CSSMERR_CSP_APPLE_SSLv2_ROLLBACK = CSSM_CSP_PRIVATE_ERROR + 6 -}; - - -/* AppleFileDL record types. */ -enum -{ - CSSM_DL_DB_RECORD_GENERIC_PASSWORD = CSSM_DB_RECORDTYPE_APP_DEFINED_START + 0, - CSSM_DL_DB_RECORD_INTERNET_PASSWORD = CSSM_DB_RECORDTYPE_APP_DEFINED_START + 1, - CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD = CSSM_DB_RECORDTYPE_APP_DEFINED_START + 2, - - CSSM_DL_DB_RECORD_X509_CERTIFICATE = CSSM_DB_RECORDTYPE_APP_DEFINED_START + 0x1000, - CSSM_DL_DB_RECORD_USER_TRUST, - CSSM_DL_DB_RECORD_X509_CRL, - CSSM_DL_DB_RECORD_UNLOCK_REFERRAL, - CSSM_DL_DB_RECORD_EXTENDED_ATTRIBUTE, - CSSM_DL_DB_RECORD_METADATA = CSSM_DB_RECORDTYPE_APP_DEFINED_START + 0x8000 -}; - -/* AppleFileDL extentions: passthrough ids */ -enum { - // Toggle whether or not to autocommit after modifying the database. - // The input parameter is a CSSM_BOOL, where TRUE turns autocommit on - // and FALSE turns it off. - CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, - - // Commit any pending changes to the database. - CSSM_APPLEFILEDL_COMMIT, - - // Rollback and discard any pending changes to the database. - CSSM_APPLEFILEDL_ROLLBACK -}; - -/* UNLOCK_REFERRAL "type" attribute values */ -enum { - CSSM_APPLE_UNLOCK_TYPE_KEY_DIRECT = 1, // master secret key stored directly - CSSM_APPLE_UNLOCK_TYPE_WRAPPED_PRIVATE = 2 // master key wrapped by public key -}; - -/* Apple DL private error codes. */ -enum -{ - /* The OpenParameters argument passed to CSSM_DL_DbCreate or CSSM_DL_DbOpen - was neither NULL nor a pointer to a valid CSSM_APPLEDL_OPEN_PARAMETERS - structure. */ - CSSMERR_APPLEDL_INVALID_OPEN_PARAMETERS = CSSM_DL_PRIVATE_ERROR + 0, - - /* an operation failed because the disk was full */ - CSSMERR_APPLEDL_DISK_FULL = CSSM_DL_PRIVATE_ERROR + 1, - - /* an operation failed because a disk quota was exceeded */ - CSSMERR_APPLEDL_QUOTA_EXCEEDED = CSSM_DL_PRIVATE_ERROR + 2, - - /* an operation failed because a file was too large */ - CSSMERR_APPLEDL_FILE_TOO_BIG = CSSM_DL_PRIVATE_ERROR + 3, - - /* a keychain database's internal information ("blob") is invalid */ - CSSMERR_APPLEDL_INVALID_DATABASE_BLOB = CSSM_DL_PRIVATE_ERROR + 4, - CSSMERR_APPLEDL_INVALID_KEY_BLOB = CSSM_DL_PRIVATE_ERROR + 5, - - /* the internal data format version for a database's internal information ("blob") is invalid */ - CSSMERR_APPLEDL_INCOMPATIBLE_DATABASE_BLOB = CSSM_DL_PRIVATE_ERROR + 6, - CSSMERR_APPLEDL_INCOMPATIBLE_KEY_BLOB = CSSM_DL_PRIVATE_ERROR + 7, -}; - -/* Apple X509TP private error codes. */ -enum -{ - /* Host name mismatch */ - CSSMERR_APPLETP_HOSTNAME_MISMATCH = CSSM_TP_PRIVATE_ERROR + 0, - /* Non-understood extension with Critical flag true */ - CSSMERR_APPLETP_UNKNOWN_CRITICAL_EXTEN = CSSM_TP_PRIVATE_ERROR + 1, - /* Basic Constraints extension required per policy, but not present */ - CSSMERR_APPLETP_NO_BASIC_CONSTRAINTS = CSSM_TP_PRIVATE_ERROR + 2, - /* Invalid BasicConstraints.CA */ - CSSMERR_APPLETP_INVALID_CA = CSSM_TP_PRIVATE_ERROR + 3, - /* Invalid Authority Key ID */ - CSSMERR_APPLETP_INVALID_AUTHORITY_ID = CSSM_TP_PRIVATE_ERROR + 4, - /* Invalid Subject Key ID */ - CSSMERR_APPLETP_INVALID_SUBJECT_ID = CSSM_TP_PRIVATE_ERROR + 5, - /* Invalid Key Usage for policy */ - CSSMERR_APPLETP_INVALID_KEY_USAGE = CSSM_TP_PRIVATE_ERROR + 6, - /* Invalid Extended Key Usage for policy */ - CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE = CSSM_TP_PRIVATE_ERROR + 7, - /* Invalid Subject/Authority Key ID Linkage */ - CSSMERR_APPLETP_INVALID_ID_LINKAGE = CSSM_TP_PRIVATE_ERROR + 8, - /* PathLengthConstraint exceeded */ - CSSMERR_APPLETP_PATH_LEN_CONSTRAINT = CSSM_TP_PRIVATE_ERROR + 9, - /* Cert group terminated at a root cert which did not self-verify */ - CSSMERR_APPLETP_INVALID_ROOT = CSSM_TP_PRIVATE_ERROR + 10, - /* CRL expired/not valid yet */ - CSSMERR_APPLETP_CRL_EXPIRED = CSSM_TP_PRIVATE_ERROR + 11, - CSSMERR_APPLETP_CRL_NOT_VALID_YET = CSSM_TP_PRIVATE_ERROR + 12, - /* Cannot find appropriate CRL */ - CSSMERR_APPLETP_CRL_NOT_FOUND = CSSM_TP_PRIVATE_ERROR + 13, - /* specified CRL server down */ - CSSMERR_APPLETP_CRL_SERVER_DOWN = CSSM_TP_PRIVATE_ERROR + 14, - /* illegible CRL distribution point URL */ - CSSMERR_APPLETP_CRL_BAD_URI = CSSM_TP_PRIVATE_ERROR + 15, - /* Unknown critical cert/CRL extension */ - CSSMERR_APPLETP_UNKNOWN_CERT_EXTEN = CSSM_TP_PRIVATE_ERROR + 16, - CSSMERR_APPLETP_UNKNOWN_CRL_EXTEN = CSSM_TP_PRIVATE_ERROR + 17, - /* CRL not verifiable to anchor or root */ - CSSMERR_APPLETP_CRL_NOT_TRUSTED = CSSM_TP_PRIVATE_ERROR + 18, - /* CRL verified to untrusted root */ - CSSMERR_APPLETP_CRL_INVALID_ANCHOR_CERT = CSSM_TP_PRIVATE_ERROR + 19, - /* CRL failed policy verification */ - CSSMERR_APPLETP_CRL_POLICY_FAIL = CSSM_TP_PRIVATE_ERROR + 20, - /* IssuingDistributionPoint extension violation */ - CSSMERR_APPLETP_IDP_FAIL = CSSM_TP_PRIVATE_ERROR + 21, - /* Cert not found at specified issuerAltName */ - CSSMERR_APPLETP_CERT_NOT_FOUND_FROM_ISSUER = CSSM_TP_PRIVATE_ERROR + 22, - /* Bad cert obtained from specified issuerAltName */ - CSSMERR_APPLETP_BAD_CERT_FROM_ISSUER = CSSM_TP_PRIVATE_ERROR + 23, - /* S/MIME Email address mismatch */ - CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND = CSSM_TP_PRIVATE_ERROR + 24, - /* Appropriate S/MIME ExtendedKeyUsage not found */ - CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE = CSSM_TP_PRIVATE_ERROR + 25, - /* S/MIME KeyUsage incompatibility */ - CSSMERR_APPLETP_SMIME_BAD_KEY_USE = CSSM_TP_PRIVATE_ERROR + 26, - /* S/MIME, cert with KeyUsage flagged !critical */ - CSSMERR_APPLETP_SMIME_KEYUSAGE_NOT_CRITICAL = CSSM_TP_PRIVATE_ERROR + 27, - /* S/MIME, leaf with empty subject name and no email addrs - * in SubjectAltName */ - CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS = CSSM_TP_PRIVATE_ERROR + 28, - /* S/MIME, leaf with empty subject name, SubjectAltName - * not critical */ - CSSMERR_APPLETP_SMIME_SUBJ_ALT_NAME_NOT_CRIT = CSSM_TP_PRIVATE_ERROR + 29, - /* Appropriate SSL ExtendedKeyUsage not found */ - CSSMERR_APPLETP_SSL_BAD_EXT_KEY_USE = CSSM_TP_PRIVATE_ERROR + 30, - /* unparseable OCSP response */ - CSSMERR_APPLETP_OCSP_BAD_RESPONSE = CSSM_TP_PRIVATE_ERROR + 31, - /* unparseable OCSP request */ - CSSMERR_APPLETP_OCSP_BAD_REQUEST = CSSM_TP_PRIVATE_ERROR + 32, - /* OCSP service unavailable */ - CSSMERR_APPLETP_OCSP_UNAVAILABLE = CSSM_TP_PRIVATE_ERROR + 33, - /* OCSP status: cert unrecognized */ - CSSMERR_APPLETP_OCSP_STATUS_UNRECOGNIZED = CSSM_TP_PRIVATE_ERROR + 34, - /* revocation check not successful for each cert */ - CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK = CSSM_TP_PRIVATE_ERROR + 35, - /* general network error */ - CSSMERR_APPLETP_NETWORK_FAILURE = CSSM_TP_PRIVATE_ERROR + 36, - /* OCSP response not verifiable to anchor or root */ - CSSMERR_APPLETP_OCSP_NOT_TRUSTED = CSSM_TP_PRIVATE_ERROR + 37, - /* OCSP response verified to untrusted root */ - CSSMERR_APPLETP_OCSP_INVALID_ANCHOR_CERT = CSSM_TP_PRIVATE_ERROR + 38, - /* OCSP response signature error */ - CSSMERR_APPLETP_OCSP_SIG_ERROR = CSSM_TP_PRIVATE_ERROR + 39, - /* No signer for OCSP response found */ - CSSMERR_APPLETP_OCSP_NO_SIGNER = CSSM_TP_PRIVATE_ERROR + 40, - /* OCSP responder status: malformed request */ - CSSMERR_APPLETP_OCSP_RESP_MALFORMED_REQ = CSSM_TP_PRIVATE_ERROR + 41, - /* OCSP responder status: internal error */ - CSSMERR_APPLETP_OCSP_RESP_INTERNAL_ERR = CSSM_TP_PRIVATE_ERROR + 42, - /* OCSP responder status: try later */ - CSSMERR_APPLETP_OCSP_RESP_TRY_LATER = CSSM_TP_PRIVATE_ERROR + 43, - /* OCSP responder status: signature required */ - CSSMERR_APPLETP_OCSP_RESP_SIG_REQUIRED = CSSM_TP_PRIVATE_ERROR + 44, - /* OCSP responder status: unauthorized */ - CSSMERR_APPLETP_OCSP_RESP_UNAUTHORIZED = CSSM_TP_PRIVATE_ERROR + 45, - /* OCSP response nonce did not match request */ - CSSMERR_APPLETP_OCSP_NONCE_MISMATCH = CSSM_TP_PRIVATE_ERROR + 46, - /* Illegal cert chain length for Code Signing */ - CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH = CSSM_TP_PRIVATE_ERROR + 47, - /* Missing Basic Constraints for Code Signing */ - CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS = CSSM_TP_PRIVATE_ERROR + 48, - /* Bad PathLengthConstraint for Code Signing */ - CSSMERR_APPLETP_CS_BAD_PATH_LENGTH = CSSM_TP_PRIVATE_ERROR + 49, - /* Missing ExtendedKeyUsage for Code Signing */ - CSSMERR_APPLETP_CS_NO_EXTENDED_KEY_USAGE = CSSM_TP_PRIVATE_ERROR + 50, - /* Development style Code Signing Cert Detected */ - CSSMERR_APPLETP_CODE_SIGN_DEVELOPMENT = CSSM_TP_PRIVATE_ERROR + 51, - /* Illegal cert chain length for Resource Signing */ - CSSMERR_APPLETP_RS_BAD_CERT_CHAIN_LENGTH = CSSM_TP_PRIVATE_ERROR + 52, - /* Bad extended key usage for Resource Signing */ - CSSMERR_APPLETP_RS_BAD_EXTENDED_KEY_USAGE = CSSM_TP_PRIVATE_ERROR + 53, - /* Trust Setting: deny */ - CSSMERR_APPLETP_TRUST_SETTING_DENY = CSSM_TP_PRIVATE_ERROR + 54, - /* Invalid empty SubjectName */ - CSSMERR_APPLETP_INVALID_EMPTY_SUBJECT = CSSM_TP_PRIVATE_ERROR + 55, - /* Unknown critical Qualified Cert Statement ID */ - CSSMERR_APPLETP_UNKNOWN_QUAL_CERT_STATEMENT = CSSM_TP_PRIVATE_ERROR + 56, - /* Missing required extension */ - CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION = CSSM_TP_PRIVATE_ERROR + 57, - /* Extended key usage not marked critical */ - CSSMERR_APPLETP_EXT_KEYUSAGE_NOT_CRITICAL = CSSM_TP_PRIVATE_ERROR + 58, - /* Required name or identifier not present */ - CSSMERR_APPLETP_IDENTIFIER_MISSING = CSSM_TP_PRIVATE_ERROR + 59 -}; - -/* Apple .mac TP private error codes. */ -enum -{ - /* cert request queued */ - CSSMERR_APPLE_DOTMAC_REQ_QUEUED = CSSM_TP_PRIVATE_ERROR + 100, - /* cert request redirected */ - CSSMERR_APPLE_DOTMAC_REQ_REDIRECT = CSSM_TP_PRIVATE_ERROR + 101, - /* general server-reported error */ - CSSMERR_APPLE_DOTMAC_REQ_SERVER_ERR = CSSM_TP_PRIVATE_ERROR + 102, - /* server-reported parameter error */ - CSSMERR_APPLE_DOTMAC_REQ_SERVER_PARAM = CSSM_TP_PRIVATE_ERROR + 103, - /* server-reported authorization error */ - CSSMERR_APPLE_DOTMAC_REQ_SERVER_AUTH = CSSM_TP_PRIVATE_ERROR + 104, - /* server-reported unimplemented */ - CSSMERR_APPLE_DOTMAC_REQ_SERVER_UNIMPL = CSSM_TP_PRIVATE_ERROR + 105, - /* server-reported not available */ - CSSMERR_APPLE_DOTMAC_REQ_SERVER_NOT_AVAIL = CSSM_TP_PRIVATE_ERROR + 106, - /* server-reported already exists */ - CSSMERR_APPLE_DOTMAC_REQ_SERVER_ALREADY_EXIST = CSSM_TP_PRIVATE_ERROR + 107, - /* server-reported service error */ - CSSMERR_APPLE_DOTMAC_REQ_SERVER_SERVICE_ERROR = CSSM_TP_PRIVATE_ERROR + 108, - /* request already pending for specified user */ - CSSMERR_APPLE_DOTMAC_REQ_IS_PENDING = CSSM_TP_PRIVATE_ERROR + 109, - /* no request pending for specified user */ - CSSMERR_APPLE_DOTMAC_NO_REQ_PENDING = CSSM_TP_PRIVATE_ERROR + 110, - /* CSR failed to verify */ - CSSMERR_APPLE_DOTMAC_CSR_VERIFY_FAIL = CSSM_TP_PRIVATE_ERROR + 111, - /* server reported failed consistency check */ - CSSMERR_APPLE_DOTMAC_FAILED_CONSISTENCY_CHECK = CSSM_TP_PRIVATE_ERROR + 112 -}; - -enum -{ - CSSM_APPLEDL_OPEN_PARAMETERS_VERSION = 1 -}; - -enum cssm_appledl_open_parameters_mask -{ - kCSSM_APPLEDL_MASK_MODE = (1 << 0) -}; - -/* Pass a CSSM_APPLEDL_OPEN_PARAMETERS_PTR as the OpenParameters argument to - CSSM_DL_DbCreate or CSSM_DL_DbOpen. When using this struct, you must zero - out the entire struct before setting any additional parameters to ensure - forward compatibility. */ -typedef struct cssm_appledl_open_parameters -{ - uint32 length; /* Should be sizeof(CSSM_APPLEDL_OPEN_PARAMETERS). */ - uint32 version; /* Should be CSSM_APPLEDL_OPEN_PARAMETERS_VERSION. */ - - /* If no OpenParameters are specified, autoCommit is on (!CSSM_FALSE) by default. - When autoCommit is on (!CSSM_FALSE), changes made to the Db are written to disk - before returning from each function. - When autoCommit is off (CSSM_FALSE), changes made to the database are not guaranteed - to be written to disk until the Db is closed. This is useful for bulk writes. - Be aware that if autoCommit is off, changes made in previous calls to the DL might - get rolled back if a new modification operation fails. */ - CSSM_BOOL autoCommit; - - /* Mask marking which of the following fields are to be used. */ - uint32 mask; - - /* When calling DbCreate, the initial mode to create the database file with; ignored on DbOpen. You must set the kCSSM_APPLEDL_MASK_MODE bit in mask or mode is ignored. */ - mode_t mode; -} CSSM_APPLEDL_OPEN_PARAMETERS, *CSSM_APPLEDL_OPEN_PARAMETERS_PTR; - - -/* AppleCSPDL passthough ids */ -enum -{ - /* Tell the SecurityServer to lock the database specified by the DLDBHandle argument. - The InputParams and OutputParams arguments are ignored. */ - CSSM_APPLECSPDL_DB_LOCK = 0, - - /* Tell the SecurityServer to unlock the database specified by the DLDBHandle argument. - The InputParameters argument is a CSSM_DATA_PTR containing the password, or NULL if - the SecurityServer should prompt for the password. - The OutputParams argument is ignored. - The SecurityServer will put up UI (though the SecurityAgent) when this function is called - iff InputParameters is NULL. */ - CSSM_APPLECSPDL_DB_UNLOCK = 1, - - /* Ask the SecurityServer to get the db settings specified for the database - specified by the DLDBHandle argument. The settings are returned in the OutputParameters argument. - The OutputParameters argument is a pointer to a CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS_PTR. - Upon successful completion, the AppleCSPDL will have allocated a - CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS structure using the application-specified - allocators for the DL attachment specified by the DLDBHandle argument. The structure will contain - the current database settings for the specified database. The client should free the - CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS_PTR after it has finished using it. - The InputParameters argument is ignored. - The SecurityServer might put up UI (though the SecurityAgent) when this function is called. */ - CSSM_APPLECSPDL_DB_GET_SETTINGS = 2, - - /* Tell the SecurityServer to set the db settings specified in InputParameters on the database - specified by the DLDBHandle argument. - The InputParameters argument is a const CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS * containing - the new settings for the specified database. - The OutputParams argument is ignored. - The SecurityServer might put up UI (though the SecurityAgent) when this function is called. */ - CSSM_APPLECSPDL_DB_SET_SETTINGS = 3, - - /* Ask the SecurityServer whether the database specified by the DLDBHandle argument is locked. - The InputParameters argument is ignored. - The OutputParameters argument is a pointer to a CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS_PTR. - Upon successful completion, the AppleCSPDL will have allocated a - CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS structure using the application-specified - allocators for the DL attachment specified by the DLDBHandle argument. The structure will contain - the current lock status for the specified database. The client should free the - CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS_PTR after it has finished using it. - The SecurityServer will put up UI (though the SecurityAgent) when this function is called. */ - CSSM_APPLECSPDL_DB_IS_LOCKED = 4, - - /* Tell the SecurityServer to change the password for the database specified by - the DLDBHandle. - - The InputParameters argument is a const CSSM_APPLECSPDL_DB_CHANGE_PASSWORD_PARAMETERS * containing - a CSSM_ACCESS_CREDENTIALS * which determines how the password will be changed. If the - accessCredentials are NULL, the SecurityAgent will prompt for the old and the new password for the - specified database. If credentials are specified, there should be 2 entries: - 1. a 3-element list containing: - CSSM_WORDID_KEYCHAIN_LOCK, CSSM_SAMPLE_TYPE_PASSWORD, and the old password. - 2. a 3-element list containing: - CSSM_WORDID_KEYCHAIN_CHANGE_LOCK, CSSM_SAMPLE_TYPE_PASSWORD, and the new password. - - The OutputParams argument is ignored. - The SecurityServer might put up UI (though the SecurityAgent) when this function is called. */ - CSSM_APPLECSPDL_DB_CHANGE_PASSWORD =5, - - /* Return the SecurityServer database handle for the database specified by the DLDBHandle */ - CSSM_APPLECSPDL_DB_GET_HANDLE = 6, - - /* Given a CSSM_KEY for the CSPDL, return the SecurityServer key handle */ - CSSM_APPLESCPDL_CSP_GET_KEYHANDLE = 7, - - CSSM_APPLE_PRIVATE_CSPDL_CODE_8 = 8, - CSSM_APPLE_PRIVATE_CSPDL_CODE_9 = 9, - CSSM_APPLE_PRIVATE_CSPDL_CODE_10 = 10, - CSSM_APPLE_PRIVATE_CSPDL_CODE_11 = 11, - CSSM_APPLE_PRIVATE_CSPDL_CODE_12 = 12, - CSSM_APPLE_PRIVATE_CSPDL_CODE_13 = 13, - CSSM_APPLE_PRIVATE_CSPDL_CODE_14 = 14, - CSSM_APPLE_PRIVATE_CSPDL_CODE_15 = 15, - CSSM_APPLE_PRIVATE_CSPDL_CODE_16 = 16, - CSSM_APPLE_PRIVATE_CSPDL_CODE_17 = 17, - CSSM_APPLE_PRIVATE_CSPDL_CODE_18 = 18, - - /* Given a CSSM_KEY_PTR in any format, obtain the SHA-1 hash of the - * associated key blob. - * Key is specified in CSSM_CSP_CreatePassThroughContext. - * Hash is allocated bythe CSP, in the App's memory, and returned - * in *outData. */ - CSSM_APPLECSP_KEYDIGEST = 0x100 -}; - - - -/* AppleCSPDL passthough parameters */ -typedef struct cssm_applecspdl_db_settings_parameters -{ - uint32 idleTimeout; // seconds idle timeout lock - uint8 lockOnSleep; // lock database when system sleeps -} CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS, *CSSM_APPLECSPDL_DB_SETTINGS_PARAMETERS_PTR; - -/* AppleCSPDL passthough parameters */ -typedef struct cssm_applecspdl_db_is_locked_parameters -{ - uint8 isLocked; // True iff the database is locked -} CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS, *CSSM_APPLECSPDL_DB_IS_LOCKED_PARAMETERS_PTR; - -/* AppleCSPDL passthough parameters */ -typedef struct cssm_applecspdl_db_change_password_parameters -{ - CSSM_ACCESS_CREDENTIALS *accessCredentials; -} CSSM_APPLECSPDL_DB_CHANGE_PASSWORD_PARAMETERS, *CSSM_APPLECSPDL_DB_CHANGE_PASSWORD_PARAMETERS_PTR; - -/* Custom wrapped key formats */ -enum { - CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM = 100, - CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSL, // traditional openssl - CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1 // OpenSSH v1 -}; - -/* - * Custom context attributes for AppleCSP. - */ -enum { - CSSM_ATTRIBUTE_VENDOR_DEFINED = 0x800000 -}; - -enum { - /* - * Public Key attribute for use with CSSM_ALGID_FEED. - */ - CSSM_ATTRIBUTE_PUBLIC_KEY = - (CSSM_ATTRIBUTE_DATA_KEY | (CSSM_ATTRIBUTE_VENDOR_DEFINED + 0)), - - /* - * FEE key attributes. - * See CSSM_FEE_PRIME_TYPE_xxx, CSSM_FEE_CURVE_TYPE_xxx enums, below. - */ - CSSM_ATTRIBUTE_FEE_PRIME_TYPE = - (CSSM_ATTRIBUTE_DATA_UINT32 | (CSSM_ATTRIBUTE_VENDOR_DEFINED + 1)), - CSSM_ATTRIBUTE_FEE_CURVE_TYPE = - (CSSM_ATTRIBUTE_DATA_UINT32 | (CSSM_ATTRIBUTE_VENDOR_DEFINED + 2)), - - /* - * Apple Secure Compression (ComCryption) optimization. - * See CSSM_ASC_OPTIMIZE_xxx, enums, below. - */ - CSSM_ATTRIBUTE_ASC_OPTIMIZATION = - (CSSM_ATTRIBUTE_DATA_UINT32 | (CSSM_ATTRIBUTE_VENDOR_DEFINED + 3)), - - /* - * RSA blinding. Value is integer, nonzero (blinding on) or zero. - */ - CSSM_ATTRIBUTE_RSA_BLINDING = - (CSSM_ATTRIBUTE_DATA_UINT32 | (CSSM_ATTRIBUTE_VENDOR_DEFINED + 4)), - - /* - * Additional public key from which to obtain algorithm-specific - * parameters. - */ - CSSM_ATTRIBUTE_PARAM_KEY = - (CSSM_ATTRIBUTE_DATA_KEY | (CSSM_ATTRIBUTE_VENDOR_DEFINED + 5)), - - /* - * Prompt string for CSSM_ALGID_SECURE_PASSPHRASE key acquisition. - * Data is a UTF8-encoded external representation of a CFString. - */ - CSSM_ATTRIBUTE_PROMPT = - (CSSM_ATTRIBUTE_DATA_CSSM_DATA | (CSSM_ATTRIBUTE_VENDOR_DEFINED + 6)), - - /* - * Alert panel title for CSSM_ALGID_SECURE_PASSPHRASE key acquisition. - * Data is a UTF8-encoded external representation of a CFString. - */ - CSSM_ATTRIBUTE_ALERT_TITLE = - (CSSM_ATTRIBUTE_DATA_CSSM_DATA | (CSSM_ATTRIBUTE_VENDOR_DEFINED + 7)), - - /* - * Boolean to specify whether secure passphrase is being used to encrypt or to - * recover data. In the former case the user will be prompted to enter the - * passphrase twice. Value is integer, nonzero (verify passphrase) or zero. - */ - CSSM_ATTRIBUTE_VERIFY_PASSPHRASE = - (CSSM_ATTRIBUTE_DATA_UINT32 | (CSSM_ATTRIBUTE_VENDOR_DEFINED + 8)) - -}; - -/* - * FEE key pair prime modulus types. - */ -enum { - CSSM_FEE_PRIME_TYPE_DEFAULT = 0, /* default per key size */ - CSSM_FEE_PRIME_TYPE_MERSENNE, /* (2 ** q) - 1Ê*/ - CSSM_FEE_PRIME_TYPE_FEE, /* (2 ** q) - k */ - CSSM_FEE_PRIME_TYPE_GENERAL /* random prime */ -}; - -/* - * FEE curve types. Comments refer to equation - * - * y**2 = x**3 + c(x**2) + ax + b - */ -enum { - CSSM_FEE_CURVE_TYPE_DEFAULT = 0, /* default per key size */ - CSSM_FEE_CURVE_TYPE_MONTGOMERY, /* a==1, b==0 */ - CSSM_FEE_CURVE_TYPE_WEIERSTRASS, /* c==0. IEEE P1363 compliant. */ - CSSM_FEE_CURVE_TYPE_ANSI_X9_62 /* ANSI X9.62 compatible */ -}; - -/* - * Apple Secure Compression (ComCryption) optimization attributes. - */ -enum { - CSSM_ASC_OPTIMIZE_DEFAULT = 0, - CSSM_ASC_OPTIMIZE_SIZE, /* max compression (currently the default) */ - CSSM_ASC_OPTIMIZE_SECURITY, /* currently not implemented */ - CSSM_ASC_OPTIMIZE_TIME, /* min runtime */ - CSSM_ASC_OPTIMIZE_TIME_SIZE, /* implies loss of security */ - CSSM_ASC_OPTIMIZE_ASCII, /* optimized for ASCC text, not implemented */ -}; - -/* - * Apple custom CSSM_KEYATTR_FLAGS. - */ -enum { - /* - * When set, indicates a public key which is incomplete (though - * still valid) due to the lack of algorithm-specific parameters. - */ - CSSM_KEYATTR_PARTIAL = 0x00010000, - - /* - * When set, public keys are stored encrypted. Default is to store - * public keys in the clear. AppleCSPDL only. - */ - CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT = 0x00020000 -}; - -/* - * Name/OID pair used in CSSM_APPLE_TP_CERT_REQUEST - */ -typedef struct { - const char *string; - const CSSM_OID *oid; -} CSSM_APPLE_TP_NAME_OID; - -/* - * Certificate request passed to CSSM_TP_SubmitCredRequest() in the - * CSSM_TP_AUTHORITY_REQUEST_TYPE.Requests field. Used for requesting - * both locally-generated certs (CSSMOID_APPLE_TP_LOCAL_CERT_GEN) and - * cert signing requests (CSSMOID_APPLE_TP_CSR_GEN). - */ -typedef struct { - CSSM_CSP_HANDLE cspHand; // sign with this CSP - CSSM_CL_HANDLE clHand; // and this CL - uint32 serialNumber; - uint32 numSubjectNames;// size subjectNames[] - CSSM_APPLE_TP_NAME_OID *subjectNames; - - /* - * Issuer name can be expressed in the simplified CSSM_APPLE_TP_NAME_OID - * array, as is the subject name, or as an CSSM_X509_NAME, which is - * typically obtained from a signing cert. - * Exactly one of {issuerNames, issuerNameX509} must be non-NULL. - */ - uint32 numIssuerNames; // size issuerNames[] - CSSM_APPLE_TP_NAME_OID *issuerNames; // optional; NULL implies root - // (signer == subject) - CSSM_X509_NAME_PTR issuerNameX509; - const CSSM_KEY *certPublicKey; - const CSSM_KEY *issuerPrivateKey; - - /* Unfortunately there is no practical way to map any algorithm - * to its appropriate OID, and we need both.... */ - CSSM_ALGORITHMS signatureAlg; // e.g., CSSM_ALGID_SHA1WithRSA - CSSM_OID signatureOid; // e.g., CSSMOID_SHA1WithRSA - uint32 notBefore; // relative to "now" - uint32 notAfter; - uint32 numExtensions; - CE_DataAndType *extensions; // optional - - /* - * Optional challenge string for CSSMOID_APPLE_TP_CSR_GEN. - */ - const char *challengeString; -} CSSM_APPLE_TP_CERT_REQUEST; - -/* - * Options for X509TP's CSSM_TP_CertGroupVerify for policy CSSMOID_APPLE_TP_SSL. - * A pointer to, and length of, one of these is optionally placed in - * CSSM_TP_VERIFY_CONTEXT.Cred->Policy.PolicyIds[n].FieldValue. - */ -#define CSSM_APPLE_TP_SSL_OPTS_VERSION 1 - -/* - * Values for CSSM_APPLE_TP_SSL_OPTIONS.flags. - * - * Set this flag when evaluating a client cert. - */ -#define CSSM_APPLE_TP_SSL_CLIENT 0x00000001 - -typedef struct { - uint32 Version; // CSSM_APPLE_TP_SSL_OPTS_VERSION - - /* - * The domain name of the server (e.g., "store.apple.com".) In the - * SSL and TLS protocols, this must match the common name of the - * subject cert. Expressed as a C string, optionally NULL terminated - * if it is NULL terminated, the length field should include the NULL). - */ - uint32 ServerNameLen; - const char *ServerName; // optional - - /* new fields for struct version 1 */ - uint32 Flags; -} CSSM_APPLE_TP_SSL_OPTIONS; - -/* - * Options for X509TP's CSSM_TP_CertGroupVerify for policy - * CSSMOID_APPLE_TP_REVOCATION_CRL. A pointer to, and length of, one - * of these is optionally placed in - * CSSM_TP_VERIFY_CONTEXT.Cred->Policy.PolicyIds[n].FieldValue. - */ -#define CSSM_APPLE_TP_CRL_OPTS_VERSION 0 - -typedef uint32 CSSM_APPLE_TP_CRL_OPT_FLAGS; -enum { - // require CRL verification for each cert; default is "try" - CSSM_TP_ACTION_REQUIRE_CRL_PER_CERT = 0x00000001, - // enable fetch from network - CSSM_TP_ACTION_FETCH_CRL_FROM_NET = 0x00000002, - // if set and positive OCSP verify for given cert, no further revocation - // checking need be done on that cert - CSSM_TP_ACTION_CRL_SUFFICIENT = 0x00000004, - // require CRL verification for certs which claim a CRL provider - CSSM_TP_ACTION_REQUIRE_CRL_IF_PRESENT = 0x00000008 -}; - -typedef struct { - uint32 Version; // CSSM_APPLE_TP_CRL_OPTS_VERSION - CSSM_APPLE_TP_CRL_OPT_FLAGS CrlFlags; - - /* - * When non-NULL, store CRLs fetched from net here. - * This is most likely a pointer to one of the - * CSSM_TP_CALLERAUTH_CONTEXT.DBList entries but that - * is not a strict requirement. - */ - CSSM_DL_DB_HANDLE_PTR crlStore; -} CSSM_APPLE_TP_CRL_OPTIONS; - -/* - * Options for X509TP's CSSM_TP_CertGroupVerify for policy - * CSSMOID_APPLE_TP_SMIME. A pointer to, and length of, one - * of these is optionally placed in - * CSSM_TP_VERIFY_CONTEXT.Cred->Policy.PolicyIds[n].FieldValue. - */ -#define CSSM_APPLE_TP_SMIME_OPTS_VERSION 0 -typedef struct { - uint32 Version; // CSSM_APPLE_TP_SMIME_OPTS_VERSION - - /* - * Intended usage of the leaf cert. The cert's KeyUsage extension, - * if present, must be a superset of this. - */ - CE_KeyUsage IntendedUsage; - - /* - * The email address of the sender. If there is an email address - * in the sender's cert, that email address must match this one. - * Both (email address in the cert, and this one) are optional. - * Expressed as a C string, optionally NULL terminated (i.e., - * SenderEmail[SenderEmailLen - 1] may or may not be NULL). - */ - uint32 SenderEmailLen; - const char *SenderEmail; // optional -} CSSM_APPLE_TP_SMIME_OPTIONS; - - -/* - * Optional ActionData for all X509TP CertGroupVerify policies. - * A pointer to, and length of, one of these is optionally placed in - * CSSM_TP_VERIFY_CONTEXT.ActionData. - */ -typedef uint32 CSSM_APPLE_TP_ACTION_FLAGS; -enum { - CSSM_TP_ACTION_ALLOW_EXPIRED = 0x00000001, // allow expired certs - CSSM_TP_ACTION_LEAF_IS_CA = 0x00000002, // first cert is a CA - CSSM_TP_ACTION_FETCH_CERT_FROM_NET = 0x00000004, // enable net fetch of CA cert - CSSM_TP_ACTION_ALLOW_EXPIRED_ROOT = 0x00000008, // allow expired roots - CSSM_TP_ACTION_REQUIRE_REV_PER_CERT = 0x00000010, // require positive revocation - // check per cert - CSSM_TP_ACTION_TRUST_SETTINGS = 0x00000020, // use TrustSettings instead of - // anchors - CSSM_TP_ACTION_IMPLICIT_ANCHORS = 0x00000040 // properly self-signed certs are - // treated as anchors implicitly -}; - -#define CSSM_APPLE_TP_ACTION_VERSION 0 -typedef struct { - uint32 Version; // CSSM_APPLE_TP_ACTION_VERSION - CSSM_APPLE_TP_ACTION_FLAGS ActionFlags; // CSSM_TP_ACTION_ALLOW_EXPIRED, etc. -} CSSM_APPLE_TP_ACTION_DATA; - -/* - * Per-cert evidence returned from CSSM_TP_CertGroupVerify. - * An array of these is presented in CSSM_TP_VERIFY_CONTEXT_RESULT.Evidence[2]. - * Same number of these as in the cert group in Evidence[1]. - */ - -/* First, an array of bits indicating various status of the cert. */ -typedef uint32 CSSM_TP_APPLE_CERT_STATUS; -enum -{ - CSSM_CERT_STATUS_EXPIRED = 0x00000001, - CSSM_CERT_STATUS_NOT_VALID_YET = 0x00000002, - CSSM_CERT_STATUS_IS_IN_INPUT_CERTS = 0x00000004, - CSSM_CERT_STATUS_IS_IN_ANCHORS = 0x00000008, - CSSM_CERT_STATUS_IS_ROOT = 0x00000010, - CSSM_CERT_STATUS_IS_FROM_NET = 0x00000020, - /* settings found in per-user Trust Settings */ - CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_USER = 0x00000040, - /* settings found in Admin Trust Settings */ - CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_ADMIN = 0x00000080, - /* settings found in System Trust Settings */ - CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_SYSTEM = 0x00000100, - /* Trust Settings result = Trust */ - CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST = 0x00000200, - /* Trust Settings result = Deny */ - CSSM_CERT_STATUS_TRUST_SETTINGS_DENY = 0x00000400, - /* Per-cert error ignored due to Trust Settings */ - CSSM_CERT_STATUS_TRUST_SETTINGS_IGNORED_ERROR = 0x00000800 -}; - -typedef struct { - CSSM_TP_APPLE_CERT_STATUS StatusBits; - uint32 NumStatusCodes; - CSSM_RETURN *StatusCodes; - - /* index into raw cert group or AnchorCerts depending on IS_IN_ANCHORS */ - uint32 Index; - - /* nonzero if cert came from a DLDB */ - CSSM_DL_DB_HANDLE DlDbHandle; - CSSM_DB_UNIQUE_RECORD_PTR UniqueRecord; -} CSSM_TP_APPLE_EVIDENCE_INFO; - -/* - * CSSM_TP_VERIFY_CONTEXT_RESULT.Evidence[0], basically defines which version/flavor - * of remaining evidence is. - */ -#define CSSM_TP_APPLE_EVIDENCE_VERSION 0 -typedef struct -{ - uint32 Version; -} CSSM_TP_APPLE_EVIDENCE_HEADER; - - -/* - * Apple-specific CSSM_EVIDENCE_FORM values - * - * The form of the evidence returns from CSSM_TP_CertGroupVerify is: - * - * EvidenceForm contents of *Evidence - * ------------ --------------------- - * CSSM_EVIDENCE_FORM_APPLE_HEADER CSSM_TP_APPLE_EVIDENCE_HEADER - * CSSM_EVIDENCE_FORM_APPLE_CERTGROUP CSSM_CERTGROUP - * CSSM_EVIDENCE_FORM_APPLE_CERT_INFO array of CSSM_TP_APPLE_EVIDENCE_INFO, size - * CSSM_CERTGROUP.NumCerts - */ - -#define CSSM_EVIDENCE_FORM_APPLE_CUSTOM 0x80000000 -enum -{ - CSSM_EVIDENCE_FORM_APPLE_HEADER = CSSM_EVIDENCE_FORM_APPLE_CUSTOM + 0, - CSSM_EVIDENCE_FORM_APPLE_CERTGROUP = CSSM_EVIDENCE_FORM_APPLE_CUSTOM + 1, - CSSM_EVIDENCE_FORM_APPLE_CERT_INFO = CSSM_EVIDENCE_FORM_APPLE_CUSTOM + 2 -}; - -/* AppleX509CL extensions: passthrough ids */ -enum { - /* - * Obtain a signed Certificate Signing Request. - * Input = CSSM_APPLE_CL_CSR_REQUEST - * Output = allocated CSSM_DATA which points to a DER-encoded CSR. - */ - CSSM_APPLEX509CL_OBTAIN_CSR, - - /* - * Perform signature verify of a CSR. - * Input: CSSM_DATA referring to a DER-encoded CSR. - * Output: Nothing, returns CSSMERR_CL_VERIFICATION_FAILURE on - * on failure. - */ - CSSM_APPLEX509CL_VERIFY_CSR -}; - -/* - * Used in CL's CSSM_APPLEX509_OBTAIN_CSR Passthrough. This is the - * input; the output is a CSSM_DATA * containing the signed and - * DER-encoded CSR. - */ -typedef struct { - CSSM_X509_NAME_PTR subjectNameX509; - - /* Unfortunately there is no practical way to map any algorithm - * to its appropriate OID, and we need both.... */ - CSSM_ALGORITHMS signatureAlg; // e.g., CSSM_ALGID_SHA1WithRSA - CSSM_OID signatureOid; // e.g., CSSMOID_SHA1WithRSA - - CSSM_CSP_HANDLE cspHand; // sign with this CSP - const CSSM_KEY *subjectPublicKey; - const CSSM_KEY *subjectPrivateKey; - - /* - * Optional challenge string. - */ - const char *challengeString; -} CSSM_APPLE_CL_CSR_REQUEST; - -/* - * When a CRL with no NextUpdate field is encountered, we use this time - * as the NextUpdate attribute when storing in a DB. It represents the - * virtual end of time in CSSM_TIMESTRING form. - */ -#define CSSM_APPLE_CRL_END_OF_TIME "99991231235959" - -/* - * Default filesystem names and locations for SecurityServer features - * (included here for lack of a better place) - */ -#define kKeychainSuffix ".keychain" -#define kSystemKeychainName "System.keychain" -#define kSystemKeychainDir "/Library/Keychains/" -#define kSystemUnlockFile "/var/db/SystemKey" - - -void cssmPerror(const char *how, CSSM_RETURN error); - -/* Convert between CSSM_OID and CSSM_ALGORITHMS */ -bool cssmOidToAlg(const CSSM_OID *oid, CSSM_ALGORITHMS *alg); -const CSSM_OID *cssmAlgToOid(CSSM_ALGORITHMS algId); - -/* - * The MacOS OSStatus space has an embedding for UNIX errno values, similar to - * the way we embed CSSM_RETURN values in OSStatus. These are the base and limit - * values for this embedding. - */ -#define errSecErrnoBase 100000 -#define errSecErrnoLimit 100255 - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif /* _CSSMAPPLE_H_ */ diff --git a/libsecurity_cssm/lib/oidsalg.c b/libsecurity_cssm/lib/oidsalg.c deleted file mode 100644 index 23ec939f..00000000 --- a/libsecurity_cssm/lib/oidsalg.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2000-2004 Apple Computer, 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@ - */ - - -/* - * oidsalg.c - OIDs defining crypto algorithms - */ - -#include -#include -#include "cssmapple.h" -#include -#include - -#pragma mark ----- CSSM_OID <--> CSSM_ALGORITHMS ----- - -typedef struct { - const CSSM_OID *oid; - CSSM_ALGORITHMS alg; -} OidToAlgEnt; - -static const OidToAlgEnt oidToAlgMap[] = -{ - {&CSSMOID_RSA, CSSM_ALGID_RSA }, - {&CSSMOID_MD2WithRSA, CSSM_ALGID_MD2WithRSA }, - {&CSSMOID_MD5WithRSA, CSSM_ALGID_MD5WithRSA }, - {&CSSMOID_SHA1WithRSA, CSSM_ALGID_SHA1WithRSA }, - {&CSSMOID_SHA1WithRSA_OIW, CSSM_ALGID_SHA1WithRSA }, - {&CSSMOID_SHA1, CSSM_ALGID_SHA1}, - {&CSSMOID_MD5, CSSM_ALGID_MD5 }, - /* - * These OIDs have three variants - one for BSAFE, CMS, and JDK 1.1. - * On the oid-to-alg map, we'll handle either one, mapping to - * the same CSSM alg. When we map from alg to OID, we'll use - * the CMS variant (being first in the list). - */ - {&CSSMOID_DSA_CMS, CSSM_ALGID_DSA }, - {&CSSMOID_DSA, CSSM_ALGID_DSA }, - {&CSSMOID_DSA_JDK, CSSM_ALGID_DSA }, - {&CSSMOID_SHA1WithDSA_CMS, CSSM_ALGID_SHA1WithDSA }, - {&CSSMOID_SHA1WithDSA, CSSM_ALGID_SHA1WithDSA }, - {&CSSMOID_SHA1WithDSA_JDK, CSSM_ALGID_SHA1WithDSA }, - /* - * Multiple entries for Diffie-Hellman. We favor the PKCS3 version for - * mapping alg to OID. - */ - {&CSSMOID_DH, CSSM_ALGID_DH}, - {&CSSMOID_ANSI_DH_PUB_NUMBER, CSSM_ALGID_DH}, - {&CSSMOID_ANSI_DH_STATIC, CSSM_ALGID_DH}, - {&CSSMOID_ANSI_DH_ONE_FLOW, CSSM_ALGID_DH}, - {&CSSMOID_ANSI_DH_EPHEM, CSSM_ALGID_DH}, - {&CSSMOID_ANSI_DH_HYBRID1, CSSM_ALGID_DH}, - {&CSSMOID_ANSI_DH_HYBRID2, CSSM_ALGID_DH}, - {&CSSMOID_ANSI_DH_HYBRID_ONEFLOW, CSSM_ALGID_DH}, - {&CSSMOID_APPLE_FEE, CSSM_ALGID_FEE }, - {&CSSMOID_APPLE_ASC, CSSM_ALGID_ASC }, - {&CSSMOID_APPLE_FEE_MD5, CSSM_ALGID_FEE_MD5 }, - {&CSSMOID_APPLE_FEE_SHA1, CSSM_ALGID_FEE_SHA1 }, - {&CSSMOID_APPLE_FEED, CSSM_ALGID_FEED }, - {&CSSMOID_APPLE_FEEDEXP, CSSM_ALGID_FEEDEXP }, - /* the current valid alg --> OID mapping */ - {&CSSMOID_ECDSA_WithSHA1, CSSM_ALGID_SHA1WithECDSA}, - /* for backwards compatibility */ - {&CSSMOID_APPLE_ECDSA, CSSM_ALGID_SHA1WithECDSA }, - {&CSSMOID_SHA224, CSSM_ALGID_SHA224}, - {&CSSMOID_SHA256, CSSM_ALGID_SHA256}, - {&CSSMOID_SHA384, CSSM_ALGID_SHA384}, - {&CSSMOID_SHA512, CSSM_ALGID_SHA512}, - {&CSSMOID_SHA224WithRSA, CSSM_ALGID_SHA224WithRSA }, - {&CSSMOID_SHA256WithRSA, CSSM_ALGID_SHA256WithRSA }, - {&CSSMOID_SHA384WithRSA, CSSM_ALGID_SHA384WithRSA }, - {&CSSMOID_SHA512WithRSA, CSSM_ALGID_SHA512WithRSA }, - {&CSSMOID_RSAWithOAEP, CSSM_ALGMODE_PKCS1_EME_OAEP }, - {&CSSMOID_ECDSA_WithSHA224, CSSM_ALGID_SHA224WithECDSA }, - {&CSSMOID_ECDSA_WithSHA256, CSSM_ALGID_SHA256WithECDSA }, - {&CSSMOID_ECDSA_WithSHA384, CSSM_ALGID_SHA384WithECDSA }, - {&CSSMOID_ECDSA_WithSHA512, CSSM_ALGID_SHA512WithECDSA }, - /* AlgId.algorithm for ECDSA public key */ - {&CSSMOID_ecPublicKey, CSSM_ALGID_ECDSA }, - /* This OID is accompanied by an additional digest OID in AlgId.parameters */ - {&CSSMOID_ECDSA_WithSpecified, CSSM_ALGID_ECDSA_SPECIFIED }, - {NULL, 0} -}; - -#define NUM_OID_TO_ALGS (sizeof(oidToAlgMap) / sizeof(oidToAlgMap[0])) - -/* - * Compare two CSSM_DATAs (or two CSSM_OIDs), return true if identical. - */ -static bool compareCssmData( - const CSSM_DATA *data1, - const CSSM_DATA *data2) -{ - if((data1 == NULL) || (data1->Data == NULL) || - (data2 == NULL) || (data2->Data == NULL) || - (data1->Length != data2->Length)) { - return false; - } - if(data1->Length != data2->Length) { - return false; - } - if(memcmp(data1->Data, data2->Data, data1->Length) == 0) { - return true; - } - else { - return false; - } -} - -bool cssmOidToAlg( - const CSSM_OID *oid, - CSSM_ALGORITHMS *alg) // RETURNED -{ - const OidToAlgEnt *ent; - - for(ent=oidToAlgMap; ent->oid; ent++) { - if(compareCssmData(ent->oid, oid)) { - *alg = ent->alg; - return true; - } - } - return false; -} - -const CSSM_OID *cssmAlgToOid( - CSSM_ALGORITHMS algId) -{ - const OidToAlgEnt *ent; - - for(ent=oidToAlgMap; ent->oid; ent++) { - if(ent->alg == algId) { - return ent->oid; - } - } - return NULL; -} - - diff --git a/libsecurity_cssm/lib/oidsbase.h b/libsecurity_cssm/lib/oidsbase.h deleted file mode 100644 index becc8e06..00000000 --- a/libsecurity_cssm/lib/oidsbase.h +++ /dev/null @@ -1,497 +0,0 @@ -/* - * Copyright (c) 1999-2001,2003-2004,2008-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@ - * - * oidsbase.h -- Basic Object Identifier Macros and Data Types. - */ - -#ifndef _OIDSBASE_H_ -#define _OIDSBASE_H_ 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* Intel CSSM */ - -#define INTEL 96, 134, 72, 1, 134, 248, 77 -#define INTEL_LENGTH 7 - -#define INTEL_CDSASECURITY INTEL, 2 -#define INTEL_CDSASECURITY_LENGTH (INTEL_LENGTH + 1) - -#define INTEL_SEC_FORMATS INTEL_CDSASECURITY, 1 -#define INTEL_SEC_FORMATS_LENGTH (INTEL_CDSASECURITY_LENGTH + 1) - -#define INTEL_SEC_ALGS INTEL_CDSASECURITY, 2, 5 -#define INTEL_SEC_ALGS_LENGTH (INTEL_CDSASECURITY_LENGTH + 2) - -#define INTEL_SEC_OBJECT_BUNDLE INTEL_SEC_FORMATS, 4 -#define INTEL_SEC_OBJECT_BUNDLE_LENGTH (INTEL_SEC_FORMATS_LENGTH + 1) - -#define INTEL_CERT_AND_PRIVATE_KEY_2_0 INTEL_SEC_OBJECT_BUNDLE, 1 -#define INTEL_CERT_AND_PRIVATE_KEY_2_0_LENGTH (INTEL_SEC_OBJECT_BUNDLE_LENGTH + 1) - -/* Suffix specifying format or representation of a field value */ -/* Note that if a format suffix is not specified, a flat data -representation is implied */ -#define INTEL_X509_C_DATATYPE 1 -#define INTEL_X509_LDAPSTRING_DATATYPE 2 - -#define OID_ISO_CCITT_DIR_SERVICE 85 -#define OID_DS OID_ISO_CCITT_DIR_SERVICE -#define OID_DS_LENGTH 1 -#define OID_ATTR_TYPE OID_DS, 4 -#define OID_ATTR_TYPE_LENGTH OID_DS_LENGTH + 1 -#define OID_EXTENSION OID_DS, 29 -#define OID_EXTENSION_LENGTH OID_DS_LENGTH + 1 -#define OID_ISO_STANDARD 40 -#define OID_ISO_MEMBER 42 -#define OID_US OID_ISO_MEMBER, 134, 72 - -#define OID_ISO_IDENTIFIED_ORG 43 -#define OID_OSINET OID_ISO_IDENTIFIED_ORG, 4 -#define OID_GOSIP OID_ISO_IDENTIFIED_ORG, 5 -#define OID_DOD OID_ISO_IDENTIFIED_ORG, 6 -#define OID_OIW OID_ISO_IDENTIFIED_ORG, 14 - -#define OID_ITU_RFCDATA_MEMBER_LENGTH 1 -#define OID_ITU_RFCDATA 9 - -/* From the PKCS Standards */ -#define OID_ISO_MEMBER_LENGTH 1 -#define OID_US_LENGTH OID_ISO_MEMBER_LENGTH + 2 -#define OID_RSA OID_US, 134, 247, 13 -#define OID_RSA_LENGTH OID_US_LENGTH + 3 -#define OID_RSA_HASH OID_RSA, 2 -#define OID_RSA_HASH_LENGTH OID_RSA_LENGTH + 1 -#define OID_RSA_ENCRYPT OID_RSA, 3 -#define OID_RSA_ENCRYPT_LENGTH OID_RSA_LENGTH + 1 -#define OID_PKCS OID_RSA, 1 -#define OID_PKCS_LENGTH OID_RSA_LENGTH +1 -#define OID_PKCS_1 OID_PKCS, 1 -#define OID_PKCS_1_LENGTH OID_PKCS_LENGTH +1 -#define OID_PKCS_2 OID_PKCS, 2 -#define OID_PKCS_3 OID_PKCS, 3 -#define OID_PKCS_3_LENGTH OID_PKCS_LENGTH +1 -#define OID_PKCS_4 OID_PKCS, 4 -#define OID_PKCS_5 OID_PKCS, 5 -#define OID_PKCS_5_LENGTH OID_PKCS_LENGTH +1 -#define OID_PKCS_6 OID_PKCS, 6 -#define OID_PKCS_7 OID_PKCS, 7 -#define OID_PKCS_7_LENGTH OID_PKCS_LENGTH +1 -#define OID_PKCS_8 OID_PKCS, 8 -#define OID_PKCS_9 OID_PKCS, 9 -#define OID_PKCS_9_LENGTH OID_PKCS_LENGTH +1 -#define OID_PKCS_10 OID_PKCS, 10 -#define OID_PKCS_11 OID_PKCS, 11 -#define OID_PKCS_11_LENGTH OID_PKCS_LENGTH +1 -#define OID_PKCS_12 OID_PKCS, 12 -#define OID_PKCS_12_LENGTH OID_PKCS_LENGTH +1 - -/* ANSI X9.42 */ -#define OID_ANSI_X9_42 OID_US, 206, 62, 2 -#define OID_ANSI_X9_42_LEN OID_US_LENGTH + 3 -#define OID_ANSI_X9_42_SCHEME OID_ANSI_X9_42, 3 -#define OID_ANSI_X9_42_SCHEME_LEN OID_ANSI_X9_42_LEN + 1 -#define OID_ANSI_X9_42_NAMED_SCHEME OID_ANSI_X9_42, 4 -#define OID_ANSI_X9_42_NAMED_SCHEME_LEN OID_ANSI_X9_42_LEN + 1 - -/* ANSI X9.62 (1 2 840 10045) */ -#define OID_ANSI_X9_62 0x2A, 0x86, 0x48, 0xCE, 0x3D -#define OID_ANSI_X9_62_LEN 5 -#define OID_ANSI_X9_62_FIELD_TYPE OID_ANSI_X9_62, 1 -#define OID_ANSI_X9_62_PUBKEY_TYPE OID_ANSI_X9_62, 2 -#define OID_ANSI_X9_62_ELL_CURVE OID_ANSI_X9_62, 3 -#define OID_ANSI_X9_62_ELL_CURVE_LEN OID_ANSI_X9_62_LEN+1 -#define OID_ANSI_X9_62_C_TWO_CURVE OID_ANSI_X9_62_ELL_CURVE, 0 -#define OID_ANSI_X9_62_PRIME_CURVE OID_ANSI_X9_62_ELL_CURVE, 1 -#define OID_ANSI_X9_62_SIG_TYPE OID_ANSI_X9_62, 4 -#define OID_ANSI_X9_62_SIG_TYPE_LEN OID_ANSI_X9_62_LEN+1 - -/* PKIX */ -#define OID_PKIX OID_DOD, 1, 5, 5, 7 -#define OID_PKIX_LENGTH 6 -#define OID_PE OID_PKIX, 1 -#define OID_PE_LENGTH OID_PKIX_LENGTH + 1 -#define OID_QT OID_PKIX, 2 -#define OID_QT_LENGTH OID_PKIX_LENGTH + 1 -#define OID_KP OID_PKIX, 3 -#define OID_KP_LENGTH OID_PKIX_LENGTH + 1 -#define OID_OTHER_NAME OID_PKIX, 8 -#define OID_OTHER_NAME_LENGTH OID_PKIX_LENGTH + 1 -#define OID_PDA OID_PKIX, 9 -#define OID_PDA_LENGTH OID_PKIX_LENGTH + 1 -#define OID_QCS OID_PKIX, 11 -#define OID_QCS_LENGTH OID_PKIX_LENGTH + 1 -#define OID_AD OID_PKIX, 48 -#define OID_AD_LENGTH OID_PKIX_LENGTH + 1 -#define OID_AD_OCSP OID_AD, 1 -#define OID_AD_OCSP_LENGTH OID_AD_LENGTH + 1 - -/* ETSI */ -#define OID_ETSI 0x04, 0x00 -#define OID_ETSI_LENGTH 2 -#define OID_ETSI_QCS 0x04, 0x00, 0x8E, 0x46, 0x01 -#define OID_ETSI_QCS_LENGTH 5 - -#define OID_OIW_SECSIG OID_OIW, 3 -#define OID_OIW_LENGTH 2 -#define OID_OIW_SECSIG_LENGTH OID_OIW_LENGTH +1 - -#define OID_OIW_ALGORITHM OID_OIW_SECSIG, 2 -#define OID_OIW_ALGORITHM_LENGTH OID_OIW_SECSIG_LENGTH +1 - -/* NIST defined digest algorithm arc (2, 16, 840, 1, 101, 3, 4, 2) */ -#define OID_NIST_HASHALG 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02 -#define OID_NIST_HASHALG_LENGTH 8 - -/* Kerberos PKINIT */ -#define OID_KERBv5 0x2b, 6, 1, 5, 2 -#define OID_KERBv5_LEN 5 -#define OID_KERBv5_PKINIT OID_KERBv5, 3 -#define OID_KERBv5_PKINIT_LEN OID_KERBv5_LEN + 1 - -/* Certicom (1 3 132) */ -#define OID_CERTICOM 0x2B, 0x81, 0x04 -#define OID_CERTICOM_LEN 3 -#define OID_CERTICOM_ELL_CURVE OID_CERTICOM, 0 -#define OID_CERTICOM_ELL_CURVE_LEN OID_CERTICOM_LEN+1 - -/* - * Apple-specific OID bases - */ - -/* - * apple OBJECT IDENTIFIER ::= - * { iso(1) member-body(2) US(840) 113635 } - * - * BER = 06 06 2A 86 48 86 F7 63 - */ -#define APPLE_OID OID_US, 0x86, 0xf7, 0x63 -#define APPLE_OID_LENGTH OID_US_LENGTH + 3 - -/* appleDataSecurity OBJECT IDENTIFIER ::= - * { apple 100 } - * { 1 2 840 113635 100 } - * - * BER = 06 07 2A 86 48 86 F7 63 64 - */ -#define APPLE_ADS_OID APPLE_OID, 0x64 -#define APPLE_ADS_OID_LENGTH APPLE_OID_LENGTH + 1 - -/* - * appleTrustPolicy OBJECT IDENTIFIER ::= - * { appleDataSecurity 1 } - * { 1 2 840 113635 100 1 } - * - * BER = 06 08 2A 86 48 86 F7 63 64 01 - */ -#define APPLE_TP_OID APPLE_ADS_OID, 1 -#define APPLE_TP_OID_LENGTH APPLE_ADS_OID_LENGTH + 1 - -/* - * appleSecurityAlgorithm OBJECT IDENTIFIER ::= - * { appleDataSecurity 2 } - * { 1 2 840 113635 100 2 } - * - * BER = 06 08 2A 86 48 86 F7 63 64 02 - */ -#define APPLE_ALG_OID APPLE_ADS_OID, 2 -#define APPLE_ALG_OID_LENGTH APPLE_ADS_OID_LENGTH + 1 - -/* - * appleDotMacCertificate OBJECT IDENTIFIER ::= - * { appleDataSecurity 3 } - * { 1 2 840 113635 100 3 } - */ -#define APPLE_DOTMAC_CERT_OID APPLE_ADS_OID, 3 -#define APPLE_DOTMAC_CERT_OID_LENGTH APPLE_ADS_OID_LENGTH + 1 - -/* - * Basis of Policy OIDs for .mac TP requests - * - * dotMacCertificateRequest OBJECT IDENTIFIER ::= - * { appleDotMacCertificate 1 } - * { 1 2 840 113635 100 3 1 } - */ -#define APPLE_DOTMAC_CERT_REQ_OID APPLE_DOTMAC_CERT_OID, 1 -#define APPLE_DOTMAC_CERT_REQ_OID_LENGTH APPLE_DOTMAC_CERT_OID_LENGTH + 1 - -/* - * Basis of .mac Certificate Extensions - * - * dotMacCertificateExtension OBJECT IDENTIFIER ::= - * { appleDotMacCertificate 2 } - * { 1 2 840 113635 100 3 2 } - */ -#define APPLE_DOTMAC_CERT_EXTEN_OID APPLE_DOTMAC_CERT_OID, 2 -#define APPLE_DOTMAC_CERT_EXTEN_OID_LENGTH APPLE_DOTMAC_CERT_OID_LENGTH + 1 - -/* - * Basis of .mac Certificate request OID/value identifiers - * - * dotMacCertificateRequestValues OBJECT IDENTIFIER ::= - * { appleDotMacCertificate 3 } - * { 1 2 840 113635 100 3 3 } - */ -#define APPLE_DOTMAC_CERT_REQ_VALUE_OID APPLE_DOTMAC_CERT_OID, 3 -#define APPLE_DOTMAC_CERT_REQ_VALUE_OID_LENGTH APPLE_DOTMAC_CERT_OID_LENGTH + 1 - -/* - * Basis of Apple-specific extended key usages - * - * appleExtendedKeyUsage OBJECT IDENTIFIER ::= - * { appleDataSecurity 4 } - * { 1 2 840 113635 100 4 } - */ -#define APPLE_EKU_OID APPLE_ADS_OID, 4 -#define APPLE_EKU_OID_LENGTH APPLE_ADS_OID_LENGTH + 1 - -/* - * Basis of Apple Code Signing extended key usages - * appleCodeSigning OBJECT IDENTIFIER ::= - * { appleExtendedKeyUsage 1 } - * { 1 2 840 113635 100 4 1 } - */ -#define APPLE_EKU_CODE_SIGNING APPLE_EKU_OID, 1 -#define APPLE_EKU_CODE_SIGNING_LENGTH APPLE_EKU_OID_LENGTH + 1 - -/* -------------------------------------------------------------------------*/ - -/* - * Basis of Apple-specific Certificate Policy identifiers - * appleCertificatePolicies OBJECT IDENTIFIER ::= - * { appleDataSecurity 5 } - * { 1 2 840 113635 100 5 } - */ -#define APPLE_CERT_POLICIES APPLE_ADS_OID, 5 -#define APPLE_CERT_POLICIES_LENGTH APPLE_ADS_OID_LENGTH + 1 - -/* - * Base for MacAppStore Certificate Policy identifiers - * macAppStoreCertificatePolicyIDs OBJECT IDENTIFIER ::= - * { appleCertificatePolicies 6 } - * { 1 2 840 113635 100 5 6 } - */ -#define APPLE_CERT_POLICIES_MACAPPSTORE APPLE_CERT_POLICIES, 6 -#define APPLE_CERT_POLICIES_MACAPPSTORE_LENGTH APPLE_CERT_POLICIES_LENGTH + 1 - -/* - * MacAppStore receipt verification Certificate Policy identifier - * macAppStoreReceiptCertificatePolicyID OBJECT IDENTIFIER ::= - * { appleCertificatePolicies 6 1 } - * { 1 2 840 113635 100 5 6 1 } - */ -#define APPLE_CERT_POLICIES_MACAPPSTORE_RECEIPT APPLE_CERT_POLICIES_MACAPPSTORE, 1 -#define APPLE_CERT_POLICIES_MACAPPSTORE_RECEIPT_LENGTH APPLE_CERT_POLICIES_MACAPPSTORE_LENGTH + 1 - -/* - * Base for AppleID Certificate Policy identifiers - * macAppStoreCertificatePolicyIDs OBJECT IDENTIFIER ::= - * { appleCertificatePolicies 7 } - * { 1 2 840 113635 100 5 7 } - */ -#define APPLE_CERT_POLICIES_APPLEID APPLE_CERT_POLICIES, 7 -#define APPLE_CERT_POLICIES_APPLEID_LENGTH APPLE_CERT_POLICIES_LENGTH + 1 - -/* - * AppleID Sharing Certificate Policy identifier - * appleIDSharingPolicyID OBJECT IDENTIFIER ::= - * { appleCertificatePolicies 7 1 } - * { 1 2 840 113635 100 5 7 1 } - */ -#define APPLE_CERT_POLICIES_APPLEID_SHARING APPLE_CERT_POLICIES_APPLEID, 1 -#define APPLE_CERT_POLICIES_APPLEID_SHARING_LENGTH APPLE_CERT_POLICIES_APPLEID_LENGTH + 1 - -/* - * Apple Mobile Store Signing Policy identifier - * - * appleDemoContentReleaseSigningID ::= { appleCertificatePolicies 12} - * { 1 2 840 113635 100 5 12 } - */ -#define APPLE_CERT_POLICIES_MOBILE_STORE_SIGNING APPLE_CERT_POLICIES, 12 -#define APPLE_CERT_POLICIES_MOBILE_STORE_SIGNING_LENGTH APPLE_CERT_POLICIES_LENGTH + 1 - -/* - * Apple Test Mobile Store Signing Policy identifier - * - * appleDemoContentTestSigningID ::= { appleDemoContentReleaseSigningID 1} - * { 1 2 840 113635 100 5 12 1 } - */ -#define APPLE_CERT_POLICIES_TEST_MOBILE_STORE_SIGNING APPLE_CERT_POLICIES, 12, 1 -#define APPLE_CERT_POLICIES_TEST_MOBILE_STORE_SIGNING_LENGTH APPLE_CERT_POLICIES_LENGTH + 2 - - -/* -------------------------------------------------------------------------*/ - -/* - * Basis of Apple-specific certificate extensions - * appleCertificateExtensions OBJECT IDENTIFIER ::= - * { appleDataSecurity 6 } - * { 1 2 840 113635 100 6 } - */ -#define APPLE_EXTENSION_OID APPLE_ADS_OID, 6 -#define APPLE_EXTENSION_OID_LENGTH APPLE_ADS_OID_LENGTH + 1 - -/* - * Basis of Apple-specific Code Signing certificate extensions - * appleCertificateExtensionCodeSigning OBJECT IDENTIFIER ::= - * { appleCertificateExtensions 1 } - * { 1 2 840 113635 100 6 1 } - */ -#define APPLE_EXTENSION_CODE_SIGNING APPLE_EXTENSION_OID, 1 -#define APPLE_EXTENSION_CODE_SIGNING_LENGTH APPLE_EXTENSION_OID_LENGTH + 1 - -/* - * Basis of MacAppStore receipt verification certificate extensions - * macAppStoreReceiptExtension OBJECT IDENTIFIER ::= - * { appleCertificateExtensions 11 1 } - * { 1 2 840 113635 100 6 11 1 } - */ -#define APPLE_EXTENSION_MACAPPSTORE_RECEIPT APPLE_EXTENSION_OID, 11, 1 -#define APPLE_EXTENSION_MACAPPSTORE_RECEIPT_LENGTH APPLE_EXTENSION_OID_LENGTH + 2 - -/* - * Basis of Apple-specific Intermediate Certificate extensions - * appleCertificateExtensionIntermediateMarker OBJECT IDENTIFIER ::= - * { appleCertificateExtensions 2 } - * { 1 2 840 113635 100 6 2 } - */ -#define APPLE_EXTENSION_INTERMEDIATE_MARKER APPLE_EXTENSION_OID, 2 -#define APPLE_EXTENSION_INTERMEDIATE_MARKER_LENGTH APPLE_EXTENSION_OID_LENGTH + 1 - -/* - * Marker for the WWDR Intermediate Certificate - * appleCertificateExtensionWWDRIntermediate OBJECT IDENTIFIER ::= - * { appleCertificateExtensionIntermediateMarker 1 } - * { 1 2 840 113635 100 6 2 1 } - */ -#define APPLE_EXTENSION_WWDR_INTERMEDIATE APPLE_EXTENSION_INTERMEDIATE_MARKER, 1 -#define APPLE_EXTENSION_WWDR_INTERMEDIATE_LENGTH APPLE_EXTENSION_INTERMEDIATE_MARKER_LENGTH + 1 - -/* - * Marker for the iTunes Store Intermediate Certificate - * appleCertificateExtensioniTunesStoreIntermediate OBJECT IDENTIFIER ::= - * { appleCertificateExtensionIntermediateMarker 2 } - * { 1 2 840 113635 100 6 2 2 } - */ -#define APPLE_EXTENSION_ITMS_INTERMEDIATE APPLE_EXTENSION_INTERMEDIATE_MARKER, 2 -#define APPLE_EXTENSION_ITMS_INTERMEDIATE_LENGTH APPLE_EXTENSION_INTERMEDIATE_MARKER_LENGTH + 1 - -/* - * Marker for the Application Integration Intermediate Certificate - * appleCertificateExtensionApplicationIntegrationIntermediate OBJECT IDENTIFIER ::= - * { appleCertificateExtensionIntermediateMarker 3 } - * { 1 2 840 113635 100 6 2 3 } - */ -#define APPLE_EXTENSION_AAI_INTERMEDIATE APPLE_EXTENSION_INTERMEDIATE_MARKER, 3 -#define APPLE_EXTENSION_AAI_INTERMEDIATE_LENGTH APPLE_EXTENSION_INTERMEDIATE_MARKER_LENGTH + 1 - -/* - * Apple Apple ID Intermediate Marker (New subCA, no longer shared with push notification server cert issuer - * - * appleCertificateExtensionAppleIDIntermediate ::= - * { appleCertificateExtensionIntermediateMarker 7 } - * { 1 2 840 113635 100 6 2 7 } - * - * shared intermediate OID is APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID - * Apple Apple ID Intermediate Marker - * Same as APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLEID_2 on iOS -*/ -#define APPLE_EXTENSION_APPLEID_INTERMEDIATE APPLE_EXTENSION_INTERMEDIATE_MARKER, 7 -#define APPLE_EXTENSION_APPLEID_INTERMEDIATE_LENGTH APPLE_EXTENSION_INTERMEDIATE_MARKER_LENGTH + 1 - -/* - * Apple System Integration 2 Intermediate Marker (New subCA) - * - * appleCertificateExtensionSystemIntegration2Intermediate ::= - * { appleCertificateExtensionIntermediateMarker 10 } - * { 1 2 840 113635 100 6 2 10 } -*/ -#define APPLE_EXTENSION_SYSINT2_INTERMEDIATE APPLE_EXTENSION_INTERMEDIATE_MARKER, 10 -#define APPLE_EXTENSION_SYSINT2_INTERMEDIATE_LENGTH APPLE_EXTENSION_INTERMEDIATE_MARKER_LENGTH + 1 - -/* - * Apple Secure Escrow Service Marker - * - * appleEscrowService ::= { appleCertificateExtensions 23 1 } - * { 1 2 840 113635 100 6 23 1 } - */ -#define APPLE_EXTENSION_ESCROW_SERVICE APPLE_EXTENSION_OID, 23, 1 -#define APPLE_EXTENSION_ESCROW_SERVICE_LENGTH APPLE_EXTENSION_OID_LENGTH + 2 - -/* - * Marker for the AppleID Sharing Certificate - * appleID OBJECT IDENTIFIER ::= - * { appleExtendedKeyUsage 7} - * { 1 2 840 113635 100 4 7 } - */ - -#define APPLE_EXTENSION_APPLEID_SHARING APPLE_EKU_OID, 7 -#define APPLE_EXTENSION_APPLEID_SHARING_LENGTH APPLE_EKU_OID_LENGTH + 1 - -/* - * Netscape OIDs. - */ -#define NETSCAPE_BASE_OID 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42 -#define NETSCAPE_BASE_OID_LEN 7 - -/* - * Netscape cert extension. - * - * netscape-cert-extension OBJECT IDENTIFIER ::= - * { 2 16 840 1 113730 1 } - * - * BER = 06 08 60 86 48 01 86 F8 42 01 - */ -#define NETSCAPE_CERT_EXTEN NETSCAPE_BASE_OID, 0x01 -#define NETSCAPE_CERT_EXTEN_LENGTH NETSCAPE_BASE_OID_LEN + 1 - -#define NETSCAPE_CERT_POLICY NETSCAPE_BASE_OID, 0x04 -#define NETSCAPE_CERT_POLICY_LENGTH NETSCAPE_BASE_OID_LEN + 1 - -/* - * Domain Component OID - */ -#define OID_ITU_RFCDATA_2342 OID_ITU_RFCDATA, 0x49, 0x86 -#define OID_ITU_RFCDATA_2342_LENGTH OID_ITU_RFCDATA_MEMBER_LENGTH + 2 - -#define OID_ITU_RFCDATA_2342_UCL OID_ITU_RFCDATA_2342, 0x49, 0x1F, 0x12, 0x8C -#define OID_ITU_RFCDATA_2342_UCL_LENGTH OID_ITU_RFCDATA_2342_LENGTH + 4 - -#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT OID_ITU_RFCDATA_2342_UCL, 0xE4 -#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_LENGTH OID_ITU_RFCDATA_2342_UCL_LENGTH + 1 - -#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT, 0x81 -#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_LENGTH OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_LENGTH + 1 - -#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_DOMAINCOMPONENT OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES, 0x99 -#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_DOMAINCOMPONENT_LENGTH OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_LENGTH + 1 - -#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_USERID OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES, 0x81 -#define OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_USERID_LENGTH OID_ITU_RFCDATA_2342_UCL_DIRECTORYPILOT_ATTRIBUTES_LENGTH + 1 - -#ifdef __cplusplus -} -#endif - -#endif /* _OIDSBASE_H_ */ diff --git a/libsecurity_cssm/lib/transition.cpp b/libsecurity_cssm/lib/transition.cpp deleted file mode 100644 index b57487a1..00000000 --- a/libsecurity_cssm/lib/transition.cpp +++ /dev/null @@ -1,519 +0,0 @@ -/* - * Copyright (c) 2000-2004 Apple Computer, 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@ - */ - - -// -// transition - transition layer for CSSM API/SPI calls. -// -// This file defines all functions that connect the CSSM API (CSSM_*) -// to a plugin's SPI (CSSM_SPI_*) functions. The bulk of these functions -// is automatically generated by the Perl script transition.pl (thanks, Larry!) -// from the cssm*.h official header files, under control of the configuration -// file transition.cfg. Those that need special magic are marked "custom" in -// transition.cfg and are defined here. -// -// @@@ Reconsider CSP locking for context operations -// -#include "cssmint.h" -#include "attachfactory.h" -#include "manager.h" -#include "cssmcontext.h" -#include -#include -#include -#include -#include -#include -#include -#include - - -// -// Names for the standard Attachment types -// -typedef StandardAttachment CSPAttachment; -typedef StandardAttachment DLAttachment; -typedef StandardAttachment CLAttachment; -typedef StandardAttachment ACAttachment; -typedef StandardAttachment TPAttachment; - - -// -// A conditional locking class for always-right(TM) lock management. -// -class TransitLock { -public: - Attachment &attachment; - - TransitLock(Attachment &att) : attachment(att) - { - attachment.module.safeLock(); - } - - ~TransitLock() - { - attachment.module.safeUnlock(); - attachment.exit(); - } -}; - - -// -// Context management functions -// -CSSM_RETURN CSSMAPI -CSSM_CSP_CreateSignatureContext (CSSM_CSP_HANDLE CSPHandle, - CSSM_ALGORITHMS AlgorithmID, - const CSSM_ACCESS_CREDENTIALS *AccessCred, - const CSSM_KEY *Key, - CSSM_CC_HANDLE *NewContextHandle) -{ - BEGIN_API - HandleContext::Maker maker(CSPHandle); - maker.setup(AccessCred); - maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY); - maker.make(); - maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred); - maker.put(CSSM_ATTRIBUTE_KEY, Key); - Required(NewContextHandle) = maker(CSSM_ALGCLASS_SIGNATURE, AlgorithmID); - END_API(CSSM) -} - - -CSSM_RETURN CSSMAPI -CSSM_CSP_CreateSymmetricContext (CSSM_CSP_HANDLE CSPHandle, - CSSM_ALGORITHMS AlgorithmID, - CSSM_ENCRYPT_MODE Mode, - const CSSM_ACCESS_CREDENTIALS *AccessCred, - const CSSM_KEY *Key, - const CSSM_DATA *InitVector, - CSSM_PADDING Padding, - void *Reserved, - CSSM_CC_HANDLE *NewContextHandle) -{ - BEGIN_API - if (Reserved != NULL) - CssmError::throwMe(CSSM_ERRCODE_INVALID_POINTER); - HandleContext::Maker maker(CSPHandle); - maker.setup(Mode); - maker.setup(AccessCred); - maker.setup(Key); - maker.setup(InitVector); - maker.setup(Padding); - maker.make(); - maker.put(CSSM_ATTRIBUTE_MODE, Mode); - maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred); - maker.put(CSSM_ATTRIBUTE_KEY, Key); - maker.put(CSSM_ATTRIBUTE_INIT_VECTOR, InitVector); - maker.put(CSSM_ATTRIBUTE_PADDING, Padding); - Required(NewContextHandle) = maker(CSSM_ALGCLASS_SYMMETRIC, AlgorithmID); - END_API(CSSM) -} - - -CSSM_RETURN CSSMAPI -CSSM_CSP_CreateDigestContext (CSSM_CSP_HANDLE CSPHandle, - CSSM_ALGORITHMS AlgorithmID, - CSSM_CC_HANDLE *NewContextHandle) -{ - BEGIN_API - HandleContext::Maker maker(CSPHandle); - maker.make(); - Required(NewContextHandle) = maker(CSSM_ALGCLASS_DIGEST, AlgorithmID); - END_API(CSSM) -} - - -CSSM_RETURN CSSMAPI -CSSM_CSP_CreateMacContext (CSSM_CSP_HANDLE CSPHandle, - CSSM_ALGORITHMS AlgorithmID, - const CSSM_KEY *Key, - CSSM_CC_HANDLE *NewContextHandle) -{ - BEGIN_API - HandleContext::Maker maker(CSPHandle); - maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY); - maker.make(); - maker.put(CSSM_ATTRIBUTE_KEY, Key); - Required(NewContextHandle) = maker(CSSM_ALGCLASS_MAC, AlgorithmID); - END_API(CSSM) -} - - -CSSM_RETURN CSSMAPI -CSSM_CSP_CreateRandomGenContext (CSSM_CSP_HANDLE CSPHandle, - CSSM_ALGORITHMS AlgorithmID, - const CSSM_CRYPTO_DATA *Seed, - CSSM_SIZE Length, - CSSM_CC_HANDLE *NewContextHandle) -{ - BEGIN_API - HandleContext::Maker maker(CSPHandle); - maker.setup(Seed); - maker.setup(Length, CSSMERR_CSP_INVALID_ATTR_OUTPUT_SIZE); - maker.make(); - maker.put(CSSM_ATTRIBUTE_SEED, Seed); - maker.put(CSSM_ATTRIBUTE_OUTPUT_SIZE, (uint32_t)Length); - Required(NewContextHandle) = maker(CSSM_ALGCLASS_RANDOMGEN, AlgorithmID); - END_API(CSSM) -} - - -CSSM_RETURN CSSMAPI -CSSM_CSP_CreateAsymmetricContext (CSSM_CSP_HANDLE CSPHandle, - CSSM_ALGORITHMS AlgorithmID, - const CSSM_ACCESS_CREDENTIALS *AccessCred, - const CSSM_KEY *Key, - CSSM_PADDING Padding, - CSSM_CC_HANDLE *NewContextHandle) -{ - BEGIN_API - HandleContext::Maker maker(CSPHandle); - maker.setup(AccessCred, CSSMERR_CSP_MISSING_ATTR_ACCESS_CREDENTIALS); - maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY); - maker.setup(Padding); - maker.make(); - maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred); - maker.put(CSSM_ATTRIBUTE_KEY, Key); - maker.put(CSSM_ATTRIBUTE_PADDING, Padding); - Required(NewContextHandle) = maker(CSSM_ALGCLASS_ASYMMETRIC, AlgorithmID); - END_API(CSSM) -} - - -CSSM_RETURN CSSMAPI -CSSM_CSP_CreateDeriveKeyContext (CSSM_CSP_HANDLE CSPHandle, - CSSM_ALGORITHMS AlgorithmID, - CSSM_KEY_TYPE DeriveKeyType, - uint32 DeriveKeyLengthInBits, - const CSSM_ACCESS_CREDENTIALS *AccessCred, - const CSSM_KEY *BaseKey, - uint32 IterationCount, - const CSSM_DATA *Salt, - const CSSM_CRYPTO_DATA *Seed, - CSSM_CC_HANDLE *NewContextHandle) -{ - BEGIN_API - HandleContext::Maker maker(CSPHandle); - maker.setup(DeriveKeyType, CSSMERR_CSP_INVALID_ATTR_KEY_TYPE); - maker.setup(DeriveKeyLengthInBits, CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); - maker.setup(AccessCred); - maker.setup(BaseKey); - maker.setup(IterationCount); - maker.setup(Salt); - maker.setup(Seed); - maker.make(); - maker.put(CSSM_ATTRIBUTE_KEY_TYPE, DeriveKeyType); - maker.put(CSSM_ATTRIBUTE_KEY_LENGTH, DeriveKeyLengthInBits); - maker.put(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, AccessCred); - maker.put(CSSM_ATTRIBUTE_KEY, BaseKey); - maker.put(CSSM_ATTRIBUTE_ITERATION_COUNT, IterationCount); - maker.put(CSSM_ATTRIBUTE_SALT, Salt); - maker.put(CSSM_ATTRIBUTE_SEED, Seed); - Required(NewContextHandle) = maker(CSSM_ALGCLASS_DERIVEKEY, AlgorithmID); - END_API(CSSM) -} - - -CSSM_RETURN CSSMAPI -CSSM_CSP_CreateKeyGenContext (CSSM_CSP_HANDLE CSPHandle, - CSSM_ALGORITHMS AlgorithmID, - uint32 KeySizeInBits, - const CSSM_CRYPTO_DATA *Seed, - const CSSM_DATA *Salt, - const CSSM_DATE *StartDate, - const CSSM_DATE *EndDate, - const CSSM_DATA *Params, - CSSM_CC_HANDLE *NewContextHandle) -{ - BEGIN_API - HandleContext::Maker maker(CSPHandle); - maker.setup(KeySizeInBits, CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); - maker.setup(Seed); - maker.setup(Salt); - maker.setup(StartDate); - maker.setup(EndDate); - maker.setup(Params); - maker.make(); - maker.put(CSSM_ATTRIBUTE_KEY_LENGTH, KeySizeInBits); - maker.put(CSSM_ATTRIBUTE_SEED, Seed); - maker.put(CSSM_ATTRIBUTE_SALT, Salt); - maker.put(CSSM_ATTRIBUTE_START_DATE, StartDate); - maker.put(CSSM_ATTRIBUTE_END_DATE, EndDate); - maker.put(CSSM_ATTRIBUTE_ALG_PARAMS, Params); - Required(NewContextHandle) = maker(CSSM_ALGCLASS_KEYGEN, AlgorithmID); - END_API(CSSM) -} - - -CSSM_RETURN CSSMAPI -CSSM_CSP_CreatePassThroughContext (CSSM_CSP_HANDLE CSPHandle, - const CSSM_KEY *Key, - CSSM_CC_HANDLE *NewContextHandle) -{ - BEGIN_API - HandleContext::Maker maker(CSPHandle); - maker.setup(Key, CSSMERR_CSP_MISSING_ATTR_KEY); - maker.make(); - maker.put(CSSM_ATTRIBUTE_KEY, Key); - Required(NewContextHandle) = maker(CSSM_ALGCLASS_NONE, CSSM_ALGID_NONE); - END_API(CSSM) -} - - -// -// CSSM_GetContext makes a deep copy of a CSP context and hands it to the -// caller. The result is NOT a HandleContext, but a bare Context that is -// in no dictionaries etc. User must delete it by calling CSSM_FreeContext. -// -CSSM_RETURN CSSMAPI -CSSM_GetContext (CSSM_CC_HANDLE CCHandle, - CSSM_CONTEXT_PTR *ContextP) -{ - BEGIN_API -#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE - HandleContext &context = HandleObject::find((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); - Context *newContext = new(context.attachment) Context(context.type(), context.algorithm()); - try { - newContext->CSPHandle = context.attachment.handle(); - newContext->copyFrom(context, context.attachment); - Required(ContextP) = newContext; - } catch (...) { - context.attachment.free(newContext); - throw; - } - END_API(CSSM) -} - - -// -// Since we allocated all the data in one fell heap, our FreeContext -// function is disappointingly simple. -// -CSSM_RETURN CSSMAPI -CSSM_FreeContext (CSSM_CONTEXT_PTR ContextP) -{ - BEGIN_API - Context *context = &Context::required(ContextP); - context->destroy(context, HandleObject::find(context->CSPHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE)); - END_API(CSSM) -} - - -CSSM_RETURN CSSMAPI -CSSM_SetContext (CSSM_CC_HANDLE CCHandle, - const CSSM_CONTEXT *ContextP) -{ - BEGIN_API - const Context &source = Context::required(ContextP); -#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE - HandleContext &context = HandleObject::find((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); - - CSSM_CONTEXT_ATTRIBUTE *oldAttributes = context.ContextAttributes; - uint32 oldCount = context.NumberOfAttributes; - CSSM_CONTEXT_TYPE oldType = context.ContextType; - CSSM_ALGORITHMS oldAlgorithm = context.AlgorithmType; - - context.copyFrom(source, context.attachment); - context.ContextType = source.ContextType; - context.AlgorithmType = source.AlgorithmType; - - if (CSSM_RETURN err = context.validateChange(CSSM_CONTEXT_EVENT_UPDATE)) { - context.attachment.free(context.ContextAttributes); // free rejected attribute blob - context.ContextAttributes = oldAttributes; // restore... - context.NumberOfAttributes = oldCount; // ... old - context.ContextType = oldType; // ... values - context.AlgorithmType = oldAlgorithm; // ... in context - CssmError::throwMe(err); // tell the caller it failed - } - - context.attachment.free(oldAttributes); - END_API(CSSM) -} - - -CSSM_RETURN CSSMAPI -CSSM_DeleteContext (CSSM_CC_HANDLE CCHandle) -{ - BEGIN_API - HandleContext &context = enterContext(CCHandle); - StLock - _(context.attachment, true); - - // ignore error return from CSP event notify (can't decline deletion) - context.validateChange(CSSM_CONTEXT_EVENT_DELETE); - - context.destroy(&context, context.attachment); - END_API(CSSM) -} - - -// -// The GetContextAttribute API is fatally flawed. The standard implies a deep -// copy of the attribute value, but no release function exists. Instead, we -// return a shallow copy (sharing structure) which you need not release, but -// which becomes invalid when the source Context is destroyed. -// -CSSM_RETURN CSSMAPI -CSSM_GetContextAttribute (const CSSM_CONTEXT *Context, - uint32 AttributeType, - CSSM_CONTEXT_ATTRIBUTE_PTR *ContextAttribute) -{ - BEGIN_API - CSSM_ATTRIBUTE_TYPE type = CSSM_ATTRIBUTE_TYPE(AttributeType); // CDSA defect - Required(ContextAttribute) = Context::required(Context).find(type); - END_API(CSSM) -} - - -CSSM_RETURN CSSMAPI -CSSM_UpdateContextAttributes (CSSM_CC_HANDLE CCHandle, - uint32 NumberAttributes, - const CSSM_CONTEXT_ATTRIBUTE *ContextAttributes) -{ - BEGIN_API -#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE - HandleContext &context = HandleObject::find((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); - context.mergeAttributes(ContextAttributes, NumberAttributes); - END_API(CSSM) -} - - -CSSM_RETURN CSSMAPI -CSSM_DeleteContextAttributes (CSSM_CC_HANDLE CCHandle, - uint32 NumberOfAttributes, - const CSSM_CONTEXT_ATTRIBUTE *ContextAttributes) -{ - BEGIN_API - if (NumberOfAttributes == 0) - return CSSM_OK; // I suppose - Required(ContextAttributes); // preflight -#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE - HandleContext &context = HandleObject::find((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); - for (uint32 n = 0; n < NumberOfAttributes; n++) - context.deleteAttribute(ContextAttributes[n].AttributeType); - END_API(CSSM) -} - - -// -// Miscellaneous odds and ends - these functions just need a wee bit of -// manual massaging to fit. -// -CSSM_RETURN CSSMAPI -CSSM_DigestDataClone (CSSM_CC_HANDLE ccHandle, - CSSM_CC_HANDLE *newCCHandle) -{ - BEGIN_API -#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE - HandleContext &context = HandleObject::findAndLock((CSSM_HANDLE)ccHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); - TransitLock _(context.attachment); - HandleContext *newContext = - new(context.attachment) HandleContext(context.attachment, context.type(), context.algorithm()); - try { - newContext->CSPHandle = context.attachment.handle(); - newContext->copyFrom(context, context.attachment); - context.attachment.downcalls.DigestDataClone(context.attachment.handle(), ccHandle, newContext->handle()); - Required(newCCHandle) = newContext->handle(); - } catch (...) { - newContext->destroy(newContext, context.attachment); - throw; - } - END_API(CSSM) -} - - -CSSM_RETURN CSSMAPI -CSSM_QueryKeySizeInBits (CSSM_CSP_HANDLE CSPHandle, - CSSM_CC_HANDLE ccHandle, - const CSSM_KEY *key, - CSSM_KEY_SIZE_PTR keySize) -{ - //@@@ could afford not to lock attachment in have-CC case - BEGIN_API - Required(keySize); - Context *context; - CSPAttachment *attachment; - if (ccHandle == (CSSM_CC_HANDLE) HandleObject::invalidHandle) { - // key specified by CSPHandle and Key - attachment = &enterAttachment(CSPHandle); - context = NULL; - } else { - // key specified by ccHandle - HandleContext *ctx = &enterContext(ccHandle); - try { - attachment = &ctx->attachment; - context = ctx; - CSPHandle = context->CSPHandle; - key = &context->get(CSSM_ATTRIBUTE_KEY, - CSSMERR_CSP_INVALID_KEY); - } catch (...) { - attachment->exit(); - throw; - } - } - TransitLock _(*attachment); - CSSM_RETURN result = attachment->downcalls.QueryKeySizeInBits(CSPHandle, - ccHandle, context, key, keySize); - return result; - END_API(CSSM) -} - - -CSSM_RETURN CSSMAPI -CSSM_GenerateAlgorithmParams (CSSM_CC_HANDLE CCHandle, - uint32 ParamBits, - CSSM_DATA_PTR Param) -{ - BEGIN_API - // this function has more subtle locking than usual. Pay attention: - - // (1) Resolve context and ensure attachment exit - HandleContext &context = enterContext(CCHandle); - StLock _(context.attachment, true); - - // (2) Call CSP, acquiring module safe-lock for a moment (only) - CSSM_CONTEXT_ATTRIBUTE_PTR attributes; - uint32 count; - { - StLock _(context.attachment.module); - if (CSSM_RETURN err = - context.attachment.downcalls.GenerateAlgorithmParams(context.attachment.handle(), - CCHandle, &context, - ParamBits, Param, - &count, &attributes)) - CssmError::throwMe(err); - } - - // (3) Merge the attributes returned into the context, which will (again) acquire the module safe-lock internally - if (count) - context.mergeAttributes(attributes, count); - // the memory at (attributes, count) belongs to the CSP; don't free it here - END_API(CSSM) -} - - -// -// Include the auto-generated functions -// -#include diff --git a/libsecurity_cssm/libsecurity_cssm.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_cssm/libsecurity_cssm.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 988e9b5a..00000000 --- a/libsecurity_cssm/libsecurity_cssm.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 4CA1FEBD052A3C8100F22E42 - - primary - - - - - diff --git a/libsecurity_filedb/libsecurity_filedb.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_filedb/libsecurity_filedb.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 988e9b5a..00000000 --- a/libsecurity_filedb/libsecurity_filedb.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 4CA1FEBD052A3C8100F22E42 - - primary - - - - - diff --git a/libsecurity_keychain/lib/SecBase.h b/libsecurity_keychain/lib/SecBase.h deleted file mode 100644 index 69f42d29..00000000 --- a/libsecurity_keychain/lib/SecBase.h +++ /dev/null @@ -1,642 +0,0 @@ -/* - * Copyright (c) 2000-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@ - */ - -/*! - @header SecBase - SecBase contains common declarations for the Security functions. -*/ - -#ifndef _SECURITY_SECBASE_H_ -#define _SECURITY_SECBASE_H_ - -#include -#include - -#if defined(__clang__) -#define SEC_DEPRECATED_ATTRIBUTE DEPRECATED_ATTRIBUTE -#else -#define SEC_DEPRECATED_ATTRIBUTE -#endif - -#if defined(__cplusplus) -extern "C" { -#endif - -#ifndef __SEC_TYPES__ -#define __SEC_TYPES__ - -/*! - @typedef SecKeychainRef - @abstract Contains information about a keychain. -*/ -typedef struct OpaqueSecKeychainRef *SecKeychainRef; - -/*! - @typedef SecKeychainItemRef - @abstract Contains information about a keychain item. -*/ -typedef struct OpaqueSecKeychainItemRef *SecKeychainItemRef; - -/*! - @typedef SecKeychainSearchRef - @abstract Contains information about a keychain search. -*/ -typedef struct OpaqueSecKeychainSearchRef *SecKeychainSearchRef; - -/*! - @typedef SecKeychainAttrType - @abstract Represents a keychain attribute type. -*/ -typedef OSType SecKeychainAttrType; - -/*! - @struct SecKeychainAttribute - @abstract Contains keychain attributes. - @field tag A 4-byte attribute tag. - @field length The length of the buffer pointed to by data. - @field data A pointer to the attribute data. -*/ -struct SecKeychainAttribute -{ - SecKeychainAttrType tag; - UInt32 length; - void *data; -}; -typedef struct SecKeychainAttribute SecKeychainAttribute; - -/*! - @typedef SecKeychainAttributePtr - @abstract Represents a pointer to a keychain attribute structure. -*/ -typedef SecKeychainAttribute *SecKeychainAttributePtr; - -/*! - @typedef SecKeychainAttributeList - @abstract Represents a list of keychain attributes. - @field count An unsigned 32-bit integer that represents the number of keychain attributes in the array. - @field attr A pointer to the first keychain attribute in the array. -*/ -struct SecKeychainAttributeList -{ - UInt32 count; - SecKeychainAttribute *attr; -}; -typedef struct SecKeychainAttributeList SecKeychainAttributeList; - -/*! - @typedef SecKeychainStatus - @abstract Represents the status of a keychain. -*/ -typedef UInt32 SecKeychainStatus; -#endif - -/*! - @typedef SecTrustedApplicationRef - @abstract Contains information about a trusted application. -*/ -typedef struct OpaqueSecTrustedApplicationRef *SecTrustedApplicationRef; - -/*! - @typedef SecPolicyRef - @abstract Contains information about a policy. -*/ -typedef struct OpaqueSecPolicyRef *SecPolicyRef; - -/*! - @typedef SecCertificateRef - @abstract Contains information about a certificate. -*/ -typedef struct OpaqueSecCertificateRef *SecCertificateRef; - -/*! - @typedef SecAccessRef - @abstract Contains information about an access. -*/ -typedef struct OpaqueSecAccessRef *SecAccessRef; - -/*! - @typedef SecIdentityRef - @abstract Contains information about an identity. -*/ -typedef struct OpaqueSecIdentityRef *SecIdentityRef; - -/*! - @typedef SecKeyRef - @abstract Contains information about a key. -*/ -typedef struct OpaqueSecKeyRef *SecKeyRef; - -/*! - @typedef SecACLRef - @abstract Contains information about an access control list (ACL) entry. -*/ -typedef struct OpaqueSecTrustRef *SecACLRef; - -/*! - @typedef SecPasswordRef - @abstract Contains information about a password. -*/ -typedef struct OpaqueSecPasswordRef *SecPasswordRef; - -/*! - @typedef SecKeychainAttributeInfo - @abstract Represents an attribute. - @field count The number of tag-format pairs in the respective arrays. - @field tag A pointer to the first attribute tag in the array. - @field format A pointer to the first CSSM_DB_ATTRIBUTE_FORMAT in the array. - @discussion Each tag and format item form a pair. -*/ -struct SecKeychainAttributeInfo -{ - UInt32 count; - UInt32 *tag; - UInt32 *format; -}; -typedef struct SecKeychainAttributeInfo SecKeychainAttributeInfo; - -/*! - @function SecCopyErrorMessageString - @abstract Returns a string describing the specified error result code. - @param status An error result code of type OSStatus or CSSM_RETURN, as returned by a Security or CSSM function. - @reserved Reserved for future use. Your code should pass NULL in this parameter. - @result A reference to an error string, or NULL if no error string is available for the specified result code. Your code must release this reference by calling the CFRelease function. -*/ -CFStringRef SecCopyErrorMessageString(OSStatus status, void *reserved); - -/*! -@enum Security Error Codes -@abstract Result codes returned from Security framework functions. -@constant errSecSuccess No error. -@constant errSecUnimplemented Function or operation not implemented. -@constant errSecDskFull Disk Full error. -@constant errSecIO I/O error. -@constant errSecParam One or more parameters passed to a function were not valid. -@constant errSecWrPerm Write permissions error. -@constant errSecAllocate Failed to allocate memory. -@constant errSecUserCanceled User canceled the operation. -@constant errSecBadReq Bad parameter or invalid state for operation. -@constant errSecInternalComponent -@constant errSecCoreFoundationUnknown -@constant errSecNotAvailable No keychain is available. -@constant errSecReadOnly Read only error. -@constant errSecAuthFailed Authorization/Authentication failed. -@constant errSecNoSuchKeychain The keychain does not exist. -@constant errSecInvalidKeychain The keychain is not valid. -@constant errSecDuplicateKeychain A keychain with the same name already exists. -@constant errSecDuplicateCallback The specified callback is already installed. -@constant errSecInvalidCallback The specified callback is not valid. -@constant errSecDuplicateItem The item already exists. -@constant errSecItemNotFound The item cannot be found. -@constant errSecBufferTooSmall The buffer is too small. -@constant errSecDataTooLarge The data is too large. -@constant errSecNoSuchAttr The attribute does not exist. -@constant errSecInvalidItemRef The item reference is invalid. -@constant errSecInvalidSearchRef The search reference is invalid. -@constant errSecNoSuchClass The keychain item class does not exist. -@constant errSecNoDefaultKeychain A default keychain does not exist. -@constant errSecInteractionNotAllowed User interaction is not allowed. -@constant errSecReadOnlyAttr The attribute is read only. -@constant errSecWrongSecVersion The version is incorrect. -@constant errSecKeySizeNotAllowed The key size is not allowed. -@constant errSecNoStorageModule There is no storage module available. -@constant errSecNoCertificateModule There is no certificate module available. -@constant errSecNoPolicyModule There is no policy module available. -@constant errSecInteractionRequired User interaction is required. -@constant errSecDataNotAvailable The data is not available. -@constant errSecDataNotModifiable The data is not modifiable. -@constant errSecCreateChainFailed The attempt to create a certificate chain failed. -@constant errSecACLNotSimple The access control list is not in standard simple form. -@constant errSecPolicyNotFound The policy specified cannot be found. -@constant errSecInvalidTrustSetting The specified trust setting is invalid. -@constant errSecNoAccessForItem The specified item has no access control. -@constant errSecInvalidOwnerEdit Invalid attempt to change the owner of this item. -@constant errSecTrustNotAvailable No trust results are available. -@constant errSecUnsupportedFormat Import/Export format unsupported. -@constant errSecUnknownFormat Unknown format in import. -@constant errSecKeyIsSensitive Key material must be wrapped for export. -@constant errSecMultiplePrivKeys An attempt was made to import multiple private keys. -@constant errSecPassphraseRequired Passphrase is required for import/export. -@constant errSecInvalidPasswordRef The password reference was invalid. -@constant errSecInvalidTrustSettings The Trust Settings Record was corrupted. -@constant errSecNoTrustSettings No Trust Settings were found. -@constant errSecPkcs12VerifyFailure MAC verification failed during PKCS12 Import. -@constant errSecDecode Unable to decode the provided data. - -@discussion The assigned error space is discontinuous: e.g. -25240..-25279, -25290..-25329, -68608..-67585, and so on. -*/ - -/* - Note: the comments that appear after these errors are used to create SecErrorMessages.strings. - The comments must not be multi-line, and should be in a form meaningful to an end user. If - a different or additional comment is needed, it can be put in the header doc format, or on a - line that does not start with errZZZ. -*/ - -enum -{ - errSecSuccess = 0, /* No error. */ - errSecUnimplemented = -4, /* Function or operation not implemented. */ - errSecDskFull = -34, - errSecIO = -36, /*I/O error (bummers)*/ - - errSecParam = -50, /* One or more parameters passed to a function were not valid. */ - errSecWrPerm = -61, /* write permissions error*/ - errSecAllocate = -108, /* Failed to allocate memory. */ - errSecUserCanceled = -128, /* User canceled the operation. */ - errSecBadReq = -909, /* Bad parameter or invalid state for operation. */ - - errSecInternalComponent = -2070, - errSecCoreFoundationUnknown = -4960, - - errSecNotAvailable = -25291, /* No keychain is available. You may need to restart your computer. */ - errSecReadOnly = -25292, /* This keychain cannot be modified. */ - errSecAuthFailed = -25293, /* The user name or passphrase you entered is not correct. */ - errSecNoSuchKeychain = -25294, /* The specified keychain could not be found. */ - errSecInvalidKeychain = -25295, /* The specified keychain is not a valid keychain file. */ - errSecDuplicateKeychain = -25296, /* A keychain with the same name already exists. */ - errSecDuplicateCallback = -25297, /* The specified callback function is already installed. */ - errSecInvalidCallback = -25298, /* The specified callback function is not valid. */ - errSecDuplicateItem = -25299, /* The specified item already exists in the keychain. */ - errSecItemNotFound = -25300, /* The specified item could not be found in the keychain. */ - errSecBufferTooSmall = -25301, /* There is not enough memory available to use the specified item. */ - errSecDataTooLarge = -25302, /* This item contains information which is too large or in a format that cannot be displayed. */ - errSecNoSuchAttr = -25303, /* The specified attribute does not exist. */ - errSecInvalidItemRef = -25304, /* The specified item is no longer valid. It may have been deleted from the keychain. */ - errSecInvalidSearchRef = -25305, /* Unable to search the current keychain. */ - errSecNoSuchClass = -25306, /* The specified item does not appear to be a valid keychain item. */ - errSecNoDefaultKeychain = -25307, /* A default keychain could not be found. */ - errSecInteractionNotAllowed = -25308, /* User interaction is not allowed. */ - errSecReadOnlyAttr = -25309, /* The specified attribute could not be modified. */ - errSecWrongSecVersion = -25310, /* This keychain was created by a different version of the system software and cannot be opened. */ - errSecKeySizeNotAllowed = -25311, /* This item specifies a key size which is too large. */ - errSecNoStorageModule = -25312, /* A required component (data storage module) could not be loaded. You may need to restart your computer. */ - errSecNoCertificateModule = -25313, /* A required component (certificate module) could not be loaded. You may need to restart your computer. */ - errSecNoPolicyModule = -25314, /* A required component (policy module) could not be loaded. You may need to restart your computer. */ - errSecInteractionRequired = -25315, /* User interaction is required, but is currently not allowed. */ - errSecDataNotAvailable = -25316, /* The contents of this item cannot be retrieved. */ - errSecDataNotModifiable = -25317, /* The contents of this item cannot be modified. */ - errSecCreateChainFailed = -25318, /* One or more certificates required to validate this certificate cannot be found. */ - errSecInvalidPrefsDomain = -25319, /* The specified preferences domain is not valid. */ - errSecInDarkWake = -25320, /* In dark wake, no UI possible */ - - errSecACLNotSimple = -25240, /* The specified access control list is not in standard (simple) form. */ - errSecPolicyNotFound = -25241, /* The specified policy cannot be found. */ - errSecInvalidTrustSetting = -25242, /* The specified trust setting is invalid. */ - errSecNoAccessForItem = -25243, /* The specified item has no access control. */ - errSecInvalidOwnerEdit = -25244, /* Invalid attempt to change the owner of this item. */ - errSecTrustNotAvailable = -25245, /* No trust results are available. */ - errSecUnsupportedFormat = -25256, /* Import/Export format unsupported. */ - errSecUnknownFormat = -25257, /* Unknown format in import. */ - errSecKeyIsSensitive = -25258, /* Key material must be wrapped for export. */ - errSecMultiplePrivKeys = -25259, /* An attempt was made to import multiple private keys. */ - errSecPassphraseRequired = -25260, /* Passphrase is required for import/export. */ - errSecInvalidPasswordRef = -25261, /* The password reference was invalid. */ - errSecInvalidTrustSettings = -25262, /* The Trust Settings Record was corrupted. */ - errSecNoTrustSettings = -25263, /* No Trust Settings were found. */ - errSecPkcs12VerifyFailure = -25264, /* MAC verification failed during PKCS12 import (wrong password?) */ - errSecNotSigner = -26267, /* A certificate was not signed by its proposed parent. */ - - errSecDecode = -26275, /* Unable to decode the provided data. */ - - errSecServiceNotAvailable = -67585, /* The required service is not available. */ - errSecInsufficientClientID = -67586, /* The client ID is not correct. */ - errSecDeviceReset = -67587, /* A device reset has occurred. */ - errSecDeviceFailed = -67588, /* A device failure has occurred. */ - errSecAppleAddAppACLSubject = -67589, /* Adding an application ACL subject failed. */ - errSecApplePublicKeyIncomplete = -67590, /* The public key is incomplete. */ - errSecAppleSignatureMismatch = -67591, /* A signature mismatch has occurred. */ - errSecAppleInvalidKeyStartDate = -67592, /* The specified key has an invalid start date. */ - errSecAppleInvalidKeyEndDate = -67593, /* The specified key has an invalid end date. */ - errSecConversionError = -67594, /* A conversion error has occurred. */ - errSecAppleSSLv2Rollback = -67595, /* A SSLv2 rollback error has occurred. */ - errSecDiskFull = -34, /* The disk is full. */ - errSecQuotaExceeded = -67596, /* The quota was exceeded. */ - errSecFileTooBig = -67597, /* The file is too big. */ - errSecInvalidDatabaseBlob = -67598, /* The specified database has an invalid blob. */ - errSecInvalidKeyBlob = -67599, /* The specified database has an invalid key blob. */ - errSecIncompatibleDatabaseBlob = -67600, /* The specified database has an incompatible blob. */ - errSecIncompatibleKeyBlob = -67601, /* The specified database has an incompatible key blob. */ - errSecHostNameMismatch = -67602, /* A host name mismatch has occurred. */ - errSecUnknownCriticalExtensionFlag = -67603, /* There is an unknown critical extension flag. */ - errSecNoBasicConstraints = -67604, /* No basic constraints were found. */ - errSecNoBasicConstraintsCA = -67605, /* No basic CA constraints were found. */ - errSecInvalidAuthorityKeyID = -67606, /* The authority key ID is not valid. */ - errSecInvalidSubjectKeyID = -67607, /* The subject key ID is not valid. */ - errSecInvalidKeyUsageForPolicy = -67608, /* The key usage is not valid for the specified policy. */ - errSecInvalidExtendedKeyUsage = -67609, /* The extended key usage is not valid. */ - errSecInvalidIDLinkage = -67610, /* The ID linkage is not valid. */ - errSecPathLengthConstraintExceeded = -67611, /* The path length constraint was exceeded. */ - errSecInvalidRoot = -67612, /* The root or anchor certificate is not valid. */ - errSecCRLExpired = -67613, /* The CRL has expired. */ - errSecCRLNotValidYet = -67614, /* The CRL is not yet valid. */ - errSecCRLNotFound = -67615, /* The CRL was not found. */ - errSecCRLServerDown = -67616, /* The CRL server is down. */ - errSecCRLBadURI = -67617, /* The CRL has a bad Uniform Resource Identifier. */ - errSecUnknownCertExtension = -67618, /* An unknown certificate extension was encountered. */ - errSecUnknownCRLExtension = -67619, /* An unknown CRL extension was encountered. */ - errSecCRLNotTrusted = -67620, /* The CRL is not trusted. */ - errSecCRLPolicyFailed = -67621, /* The CRL policy failed. */ - errSecIDPFailure = -67622, /* The issuing distribution point was not valid. */ - errSecSMIMEEmailAddressesNotFound = -67623, /* An email address mismatch was encountered. */ - errSecSMIMEBadExtendedKeyUsage = -67624, /* The appropriate extended key usage for SMIME was not found. */ - errSecSMIMEBadKeyUsage = -67625, /* The key usage is not compatible with SMIME. */ - errSecSMIMEKeyUsageNotCritical = -67626, /* The key usage extension is not marked as critical. */ - errSecSMIMENoEmailAddress = -67627, /* No email address was found in the certificate. */ - errSecSMIMESubjAltNameNotCritical = -67628, /* The subject alternative name extension is not marked as critical. */ - errSecSSLBadExtendedKeyUsage = -67629, /* The appropriate extended key usage for SSL was not found. */ - errSecOCSPBadResponse = -67630, /* The OCSP response was incorrect or could not be parsed. */ - errSecOCSPBadRequest = -67631, /* The OCSP request was incorrect or could not be parsed. */ - errSecOCSPUnavailable = -67632, /* OCSP service is unavailable. */ - errSecOCSPStatusUnrecognized = -67633, /* The OCSP server did not recognize this certificate. */ - errSecEndOfData = -67634, /* An end-of-data was detected. */ - errSecIncompleteCertRevocationCheck = -67635, /* An incomplete certificate revocation check occurred. */ - errSecNetworkFailure = -67636, /* A network failure occurred. */ - errSecOCSPNotTrustedToAnchor = -67637, /* The OCSP response was not trusted to a root or anchor certificate. */ - errSecRecordModified = -67638, /* The record was modified. */ - errSecOCSPSignatureError = -67639, /* The OCSP response had an invalid signature. */ - errSecOCSPNoSigner = -67640, /* The OCSP response had no signer. */ - errSecOCSPResponderMalformedReq = -67641, /* The OCSP responder was given a malformed request. */ - errSecOCSPResponderInternalError = -67642, /* The OCSP responder encountered an internal error. */ - errSecOCSPResponderTryLater = -67643, /* The OCSP responder is busy, try again later. */ - errSecOCSPResponderSignatureRequired = -67644, /* The OCSP responder requires a signature. */ - errSecOCSPResponderUnauthorized = -67645, /* The OCSP responder rejected this request as unauthorized. */ - errSecOCSPResponseNonceMismatch = -67646, /* The OCSP response nonce did not match the request. */ - errSecCodeSigningBadCertChainLength = -67647, /* Code signing encountered an incorrect certificate chain length. */ - errSecCodeSigningNoBasicConstraints = -67648, /* Code signing found no basic constraints. */ - errSecCodeSigningBadPathLengthConstraint= -67649, /* Code signing encountered an incorrect path length constraint. */ - errSecCodeSigningNoExtendedKeyUsage = -67650, /* Code signing found no extended key usage. */ - errSecCodeSigningDevelopment = -67651, /* Code signing indicated use of a development-only certificate. */ - errSecResourceSignBadCertChainLength = -67652, /* Resource signing has encountered an incorrect certificate chain length. */ - errSecResourceSignBadExtKeyUsage = -67653, /* Resource signing has encountered an error in the extended key usage. */ - errSecTrustSettingDeny = -67654, /* The trust setting for this policy was set to Deny. */ - errSecInvalidSubjectName = -67655, /* An invalid certificate subject name was encountered. */ - errSecUnknownQualifiedCertStatement = -67656, /* An unknown qualified certificate statement was encountered. */ - errSecMobileMeRequestQueued = -67657, /* The MobileMe request will be sent during the next connection. */ - errSecMobileMeRequestRedirected = -67658, /* The MobileMe request was redirected. */ - errSecMobileMeServerError = -67659, /* A MobileMe server error occurred. */ - errSecMobileMeServerNotAvailable = -67660, /* The MobileMe server is not available. */ - errSecMobileMeServerAlreadyExists = -67661, /* The MobileMe server reported that the item already exists. */ - errSecMobileMeServerServiceErr = -67662, /* A MobileMe service error has occurred. */ - errSecMobileMeRequestAlreadyPending = -67663, /* A MobileMe request is already pending. */ - errSecMobileMeNoRequestPending = -67664, /* MobileMe has no request pending. */ - errSecMobileMeCSRVerifyFailure = -67665, /* A MobileMe CSR verification failure has occurred. */ - errSecMobileMeFailedConsistencyCheck = -67666, /* MobileMe has found a failed consistency check. */ - errSecNotInitialized = -67667, /* A function was called without initializing CSSM. */ - errSecInvalidHandleUsage = -67668, /* The CSSM handle does not match with the service type. */ - errSecPVCReferentNotFound = -67669, /* A reference to the calling module was not found in the list of authorized callers. */ - errSecFunctionIntegrityFail = -67670, /* A function address was not within the verified module. */ - errSecInternalError = -67671, /* An internal error has occurred. */ - errSecMemoryError = -67672, /* A memory error has occurred. */ - errSecInvalidData = -67673, /* Invalid data was encountered. */ - errSecMDSError = -67674, /* A Module Directory Service error has occurred. */ - errSecInvalidPointer = -67675, /* An invalid pointer was encountered. */ - errSecSelfCheckFailed = -67676, /* Self-check has failed. */ - errSecFunctionFailed = -67677, /* A function has failed. */ - errSecModuleManifestVerifyFailed = -67678, /* A module manifest verification failure has occurred. */ - errSecInvalidGUID = -67679, /* An invalid GUID was encountered. */ - errSecInvalidHandle = -67680, /* An invalid handle was encountered. */ - errSecInvalidDBList = -67681, /* An invalid DB list was encountered. */ - errSecInvalidPassthroughID = -67682, /* An invalid passthrough ID was encountered. */ - errSecInvalidNetworkAddress = -67683, /* An invalid network address was encountered. */ - errSecCRLAlreadySigned = -67684, /* The certificate revocation list is already signed. */ - errSecInvalidNumberOfFields = -67685, /* An invalid number of fields were encountered. */ - errSecVerificationFailure = -67686, /* A verification failure occurred. */ - errSecUnknownTag = -67687, /* An unknown tag was encountered. */ - errSecInvalidSignature = -67688, /* An invalid signature was encountered. */ - errSecInvalidName = -67689, /* An invalid name was encountered. */ - errSecInvalidCertificateRef = -67690, /* An invalid certificate reference was encountered. */ - errSecInvalidCertificateGroup = -67691, /* An invalid certificate group was encountered. */ - errSecTagNotFound = -67692, /* The specified tag was not found. */ - errSecInvalidQuery = -67693, /* The specified query was not valid. */ - errSecInvalidValue = -67694, /* An invalid value was detected. */ - errSecCallbackFailed = -67695, /* A callback has failed. */ - errSecACLDeleteFailed = -67696, /* An ACL delete operation has failed. */ - errSecACLReplaceFailed = -67697, /* An ACL replace operation has failed. */ - errSecACLAddFailed = -67698, /* An ACL add operation has failed. */ - errSecACLChangeFailed = -67699, /* An ACL change operation has failed. */ - errSecInvalidAccessCredentials = -67700, /* Invalid access credentials were encountered. */ - errSecInvalidRecord = -67701, /* An invalid record was encountered. */ - errSecInvalidACL = -67702, /* An invalid ACL was encountered. */ - errSecInvalidSampleValue = -67703, /* An invalid sample value was encountered. */ - errSecIncompatibleVersion = -67704, /* An incompatible version was encountered. */ - errSecPrivilegeNotGranted = -67705, /* The privilege was not granted. */ - errSecInvalidScope = -67706, /* An invalid scope was encountered. */ - errSecPVCAlreadyConfigured = -67707, /* The PVC is already configured. */ - errSecInvalidPVC = -67708, /* An invalid PVC was encountered. */ - errSecEMMLoadFailed = -67709, /* The EMM load has failed. */ - errSecEMMUnloadFailed = -67710, /* The EMM unload has failed. */ - errSecAddinLoadFailed = -67711, /* The add-in load operation has failed. */ - errSecInvalidKeyRef = -67712, /* An invalid key was encountered. */ - errSecInvalidKeyHierarchy = -67713, /* An invalid key hierarchy was encountered. */ - errSecAddinUnloadFailed = -67714, /* The add-in unload operation has failed. */ - errSecLibraryReferenceNotFound = -67715, /* A library reference was not found. */ - errSecInvalidAddinFunctionTable = -67716, /* An invalid add-in function table was encountered. */ - errSecInvalidServiceMask = -67717, /* An invalid service mask was encountered. */ - errSecModuleNotLoaded = -67718, /* A module was not loaded. */ - errSecInvalidSubServiceID = -67719, /* An invalid subservice ID was encountered. */ - errSecAttributeNotInContext = -67720, /* An attribute was not in the context. */ - errSecModuleManagerInitializeFailed = -67721, /* A module failed to initialize. */ - errSecModuleManagerNotFound = -67722, /* A module was not found. */ - errSecEventNotificationCallbackNotFound = -67723, /* An event notification callback was not found. */ - errSecInputLengthError = -67724, /* An input length error was encountered. */ - errSecOutputLengthError = -67725, /* An output length error was encountered. */ - errSecPrivilegeNotSupported = -67726, /* The privilege is not supported. */ - errSecDeviceError = -67727, /* A device error was encountered. */ - errSecAttachHandleBusy = -67728, /* The CSP handle was busy. */ - errSecNotLoggedIn = -67729, /* You are not logged in. */ - errSecAlgorithmMismatch = -67730, /* An algorithm mismatch was encountered. */ - errSecKeyUsageIncorrect = -67731, /* The key usage is incorrect. */ - errSecKeyBlobTypeIncorrect = -67732, /* The key blob type is incorrect. */ - errSecKeyHeaderInconsistent = -67733, /* The key header is inconsistent. */ - errSecUnsupportedKeyFormat = -67734, /* The key header format is not supported. */ - errSecUnsupportedKeySize = -67735, /* The key size is not supported. */ - errSecInvalidKeyUsageMask = -67736, /* The key usage mask is not valid. */ - errSecUnsupportedKeyUsageMask = -67737, /* The key usage mask is not supported. */ - errSecInvalidKeyAttributeMask = -67738, /* The key attribute mask is not valid. */ - errSecUnsupportedKeyAttributeMask = -67739, /* The key attribute mask is not supported. */ - errSecInvalidKeyLabel = -67740, /* The key label is not valid. */ - errSecUnsupportedKeyLabel = -67741, /* The key label is not supported. */ - errSecInvalidKeyFormat = -67742, /* The key format is not valid. */ - errSecUnsupportedVectorOfBuffers = -67743, /* The vector of buffers is not supported. */ - errSecInvalidInputVector = -67744, /* The input vector is not valid. */ - errSecInvalidOutputVector = -67745, /* The output vector is not valid. */ - errSecInvalidContext = -67746, /* An invalid context was encountered. */ - errSecInvalidAlgorithm = -67747, /* An invalid algorithm was encountered. */ - errSecInvalidAttributeKey = -67748, /* A key attribute was not valid. */ - errSecMissingAttributeKey = -67749, /* A key attribute was missing. */ - errSecInvalidAttributeInitVector = -67750, /* An init vector attribute was not valid. */ - errSecMissingAttributeInitVector = -67751, /* An init vector attribute was missing. */ - errSecInvalidAttributeSalt = -67752, /* A salt attribute was not valid. */ - errSecMissingAttributeSalt = -67753, /* A salt attribute was missing. */ - errSecInvalidAttributePadding = -67754, /* A padding attribute was not valid. */ - errSecMissingAttributePadding = -67755, /* A padding attribute was missing. */ - errSecInvalidAttributeRandom = -67756, /* A random number attribute was not valid. */ - errSecMissingAttributeRandom = -67757, /* A random number attribute was missing. */ - errSecInvalidAttributeSeed = -67758, /* A seed attribute was not valid. */ - errSecMissingAttributeSeed = -67759, /* A seed attribute was missing. */ - errSecInvalidAttributePassphrase = -67760, /* A passphrase attribute was not valid. */ - errSecMissingAttributePassphrase = -67761, /* A passphrase attribute was missing. */ - errSecInvalidAttributeKeyLength = -67762, /* A key length attribute was not valid. */ - errSecMissingAttributeKeyLength = -67763, /* A key length attribute was missing. */ - errSecInvalidAttributeBlockSize = -67764, /* A block size attribute was not valid. */ - errSecMissingAttributeBlockSize = -67765, /* A block size attribute was missing. */ - errSecInvalidAttributeOutputSize = -67766, /* An output size attribute was not valid. */ - errSecMissingAttributeOutputSize = -67767, /* An output size attribute was missing. */ - errSecInvalidAttributeRounds = -67768, /* The number of rounds attribute was not valid. */ - errSecMissingAttributeRounds = -67769, /* The number of rounds attribute was missing. */ - errSecInvalidAlgorithmParms = -67770, /* An algorithm parameters attribute was not valid. */ - errSecMissingAlgorithmParms = -67771, /* An algorithm parameters attribute was missing. */ - errSecInvalidAttributeLabel = -67772, /* A label attribute was not valid. */ - errSecMissingAttributeLabel = -67773, /* A label attribute was missing. */ - errSecInvalidAttributeKeyType = -67774, /* A key type attribute was not valid. */ - errSecMissingAttributeKeyType = -67775, /* A key type attribute was missing. */ - errSecInvalidAttributeMode = -67776, /* A mode attribute was not valid. */ - errSecMissingAttributeMode = -67777, /* A mode attribute was missing. */ - errSecInvalidAttributeEffectiveBits = -67778, /* An effective bits attribute was not valid. */ - errSecMissingAttributeEffectiveBits = -67779, /* An effective bits attribute was missing. */ - errSecInvalidAttributeStartDate = -67780, /* A start date attribute was not valid. */ - errSecMissingAttributeStartDate = -67781, /* A start date attribute was missing. */ - errSecInvalidAttributeEndDate = -67782, /* An end date attribute was not valid. */ - errSecMissingAttributeEndDate = -67783, /* An end date attribute was missing. */ - errSecInvalidAttributeVersion = -67784, /* A version attribute was not valid. */ - errSecMissingAttributeVersion = -67785, /* A version attribute was missing. */ - errSecInvalidAttributePrime = -67786, /* A prime attribute was not valid. */ - errSecMissingAttributePrime = -67787, /* A prime attribute was missing. */ - errSecInvalidAttributeBase = -67788, /* A base attribute was not valid. */ - errSecMissingAttributeBase = -67789, /* A base attribute was missing. */ - errSecInvalidAttributeSubprime = -67790, /* A subprime attribute was not valid. */ - errSecMissingAttributeSubprime = -67791, /* A subprime attribute was missing. */ - errSecInvalidAttributeIterationCount = -67792, /* An iteration count attribute was not valid. */ - errSecMissingAttributeIterationCount = -67793, /* An iteration count attribute was missing. */ - errSecInvalidAttributeDLDBHandle = -67794, /* A database handle attribute was not valid. */ - errSecMissingAttributeDLDBHandle = -67795, /* A database handle attribute was missing. */ - errSecInvalidAttributeAccessCredentials = -67796, /* An access credentials attribute was not valid. */ - errSecMissingAttributeAccessCredentials = -67797, /* An access credentials attribute was missing. */ - errSecInvalidAttributePublicKeyFormat = -67798, /* A public key format attribute was not valid. */ - errSecMissingAttributePublicKeyFormat = -67799, /* A public key format attribute was missing. */ - errSecInvalidAttributePrivateKeyFormat = -67800, /* A private key format attribute was not valid. */ - errSecMissingAttributePrivateKeyFormat = -67801, /* A private key format attribute was missing. */ - errSecInvalidAttributeSymmetricKeyFormat = -67802, /* A symmetric key format attribute was not valid. */ - errSecMissingAttributeSymmetricKeyFormat = -67803, /* A symmetric key format attribute was missing. */ - errSecInvalidAttributeWrappedKeyFormat = -67804, /* A wrapped key format attribute was not valid. */ - errSecMissingAttributeWrappedKeyFormat = -67805, /* A wrapped key format attribute was missing. */ - errSecStagedOperationInProgress = -67806, /* A staged operation is in progress. */ - errSecStagedOperationNotStarted = -67807, /* A staged operation was not started. */ - errSecVerifyFailed = -67808, /* A cryptographic verification failure has occurred. */ - errSecQuerySizeUnknown = -67809, /* The query size is unknown. */ - errSecBlockSizeMismatch = -67810, /* A block size mismatch occurred. */ - errSecPublicKeyInconsistent = -67811, /* The public key was inconsistent. */ - errSecDeviceVerifyFailed = -67812, /* A device verification failure has occurred. */ - errSecInvalidLoginName = -67813, /* An invalid login name was detected. */ - errSecAlreadyLoggedIn = -67814, /* The user is already logged in. */ - errSecInvalidDigestAlgorithm = -67815, /* An invalid digest algorithm was detected. */ - errSecInvalidCRLGroup = -67816, /* An invalid CRL group was detected. */ - errSecCertificateCannotOperate = -67817, /* The certificate cannot operate. */ - errSecCertificateExpired = -67818, /* An expired certificate was detected. */ - errSecCertificateNotValidYet = -67819, /* The certificate is not yet valid. */ - errSecCertificateRevoked = -67820, /* The certificate was revoked. */ - errSecCertificateSuspended = -67821, /* The certificate was suspended. */ - errSecInsufficientCredentials = -67822, /* Insufficient credentials were detected. */ - errSecInvalidAction = -67823, /* The action was not valid. */ - errSecInvalidAuthority = -67824, /* The authority was not valid. */ - errSecVerifyActionFailed = -67825, /* A verify action has failed. */ - errSecInvalidCertAuthority = -67826, /* The certificate authority was not valid. */ - errSecInvaldCRLAuthority = -67827, /* The CRL authority was not valid. */ - errSecInvalidCRLEncoding = -67828, /* The CRL encoding was not valid. */ - errSecInvalidCRLType = -67829, /* The CRL type was not valid. */ - errSecInvalidCRL = -67830, /* The CRL was not valid. */ - errSecInvalidFormType = -67831, /* The form type was not valid. */ - errSecInvalidID = -67832, /* The ID was not valid. */ - errSecInvalidIdentifier = -67833, /* The identifier was not valid. */ - errSecInvalidIndex = -67834, /* The index was not valid. */ - errSecInvalidPolicyIdentifiers = -67835, /* The policy identifiers are not valid. */ - errSecInvalidTimeString = -67836, /* The time specified was not valid. */ - errSecInvalidReason = -67837, /* The trust policy reason was not valid. */ - errSecInvalidRequestInputs = -67838, /* The request inputs are not valid. */ - errSecInvalidResponseVector = -67839, /* The response vector was not valid. */ - errSecInvalidStopOnPolicy = -67840, /* The stop-on policy was not valid. */ - errSecInvalidTuple = -67841, /* The tuple was not valid. */ - errSecMultipleValuesUnsupported = -67842, /* Multiple values are not supported. */ - errSecNotTrusted = -67843, /* The trust policy was not trusted. */ - errSecNoDefaultAuthority = -67844, /* No default authority was detected. */ - errSecRejectedForm = -67845, /* The trust policy had a rejected form. */ - errSecRequestLost = -67846, /* The request was lost. */ - errSecRequestRejected = -67847, /* The request was rejected. */ - errSecUnsupportedAddressType = -67848, /* The address type is not supported. */ - errSecUnsupportedService = -67849, /* The service is not supported. */ - errSecInvalidTupleGroup = -67850, /* The tuple group was not valid. */ - errSecInvalidBaseACLs = -67851, /* The base ACLs are not valid. */ - errSecInvalidTupleCredendtials = -67852, /* The tuple credentials are not valid. */ - errSecInvalidEncoding = -67853, /* The encoding was not valid. */ - errSecInvalidValidityPeriod = -67854, /* The validity period was not valid. */ - errSecInvalidRequestor = -67855, /* The requestor was not valid. */ - errSecRequestDescriptor = -67856, /* The request descriptor was not valid. */ - errSecInvalidBundleInfo = -67857, /* The bundle information was not valid. */ - errSecInvalidCRLIndex = -67858, /* The CRL index was not valid. */ - errSecNoFieldValues = -67859, /* No field values were detected. */ - errSecUnsupportedFieldFormat = -67860, /* The field format is not supported. */ - errSecUnsupportedIndexInfo = -67861, /* The index information is not supported. */ - errSecUnsupportedLocality = -67862, /* The locality is not supported. */ - errSecUnsupportedNumAttributes = -67863, /* The number of attributes is not supported. */ - errSecUnsupportedNumIndexes = -67864, /* The number of indexes is not supported. */ - errSecUnsupportedNumRecordTypes = -67865, /* The number of record types is not supported. */ - errSecFieldSpecifiedMultiple = -67866, /* Too many fields were specified. */ - errSecIncompatibleFieldFormat = -67867, /* The field format was incompatible. */ - errSecInvalidParsingModule = -67868, /* The parsing module was not valid. */ - errSecDatabaseLocked = -67869, /* The database is locked. */ - errSecDatastoreIsOpen = -67870, /* The data store is open. */ - errSecMissingValue = -67871, /* A missing value was detected. */ - errSecUnsupportedQueryLimits = -67872, /* The query limits are not supported. */ - errSecUnsupportedNumSelectionPreds = -67873, /* The number of selection predicates is not supported. */ - errSecUnsupportedOperator = -67874, /* The operator is not supported. */ - errSecInvalidDBLocation = -67875, /* The database location is not valid. */ - errSecInvalidAccessRequest = -67876, /* The access request is not valid. */ - errSecInvalidIndexInfo = -67877, /* The index information is not valid. */ - errSecInvalidNewOwner = -67878, /* The new owner is not valid. */ - errSecInvalidModifyMode = -67879, /* The modify mode is not valid. */ - errSecMissingRequiredExtension = -67880, /* A required certificate extension is missing. */ - errSecExtendedKeyUsageNotCritical = -67881, /* The extended key usage extension was not marked critical. */ - errSecTimestampMissing = -67882, /* A timestamp was expected but was not found. */ - errSecTimestampInvalid = -67883, /* The timestamp was not valid. */ - errSecTimestampNotTrusted = -67884, /* The timestamp was not trusted. */ - errSecTimestampServiceNotAvailable = -67885, /* The timestamp service is not available. */ - errSecTimestampBadAlg = -67886, /* An unrecognized or unsupported Algorithm Identifier in timestamp. */ - errSecTimestampBadRequest = -67887, /* The timestamp transaction is not permitted or supported. */ - errSecTimestampBadDataFormat = -67888, /* The timestamp data submitted has the wrong format. */ - errSecTimestampTimeNotAvailable = -67889, /* The time source for the Timestamp Authority is not available. */ - errSecTimestampUnacceptedPolicy = -67890, /* The requested policy is not supported by the Timestamp Authority. */ - errSecTimestampUnacceptedExtension = -67891, /* The requested extension is not supported by the Timestamp Authority. */ - errSecTimestampAddInfoNotAvailable = -67892, /* The additional information requested is not available. */ - errSecTimestampSystemFailure = -67893, /* The timestamp request cannot be handled due to system failure . */ - errSecSigningTimeMissing = -67894, /* A signing time was expected but was not found. */ - errSecTimestampRejection = -67895, /* A timestamp transaction was rejected. */ - errSecTimestampWaiting = -67896, /* A timestamp transaction is waiting. */ - errSecTimestampRevocationWarning = -67897, /* A timestamp authority revocation warning was issued. */ - errSecTimestampRevocationNotification = -67898, /* A timestamp authority revocation notification was issued. */ -}; - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECBASE_H_ */ diff --git a/libsecurity_keychain/lib/SecBasePriv.h b/libsecurity_keychain/lib/SecBasePriv.h deleted file mode 100644 index 869b8edb..00000000 --- a/libsecurity_keychain/lib/SecBasePriv.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2003-2008 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 SecBasePriv - SecBasePriv contains private error codes for the Security framework. - */ -#ifndef _SECURITY_SECBASEPRIV_H_ -#define _SECURITY_SECBASEPRIV_H_ - -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -/******************************************************* - *** Private OSStatus values unique to Security APIs *** - *******************************************************/ - -/* - Note: the comments that appear after these errors are used to create SecErrorMessages.strings. - The comments must not be multi-line, and should be in a form meaningful to an end user. If - a different or additional comment is needed, it can be put in the header doc format, or on a - line that does not start with errZZZ. -*/ - -enum -{ - priv_errSecUnimplemented = -4, /* Private version of errSecUnimplemented constant. */ - priv_errSecParam = -50, /* Private version of errSecParam constant. */ - priv_errSecDecode = -26275, /* Private version of errSecDecode constant. */ -}; - -enum -{ - errSecInvalidCertificate = priv_errSecDecode, // -26265, /* This certificate could not be decoded. */ - errSecPolicyDenied = -26270, /* The certificate chain was not trusted due to a policy not accepting it. */ - errSecInvalidKey = priv_errSecDecode, // -26274, /* The provided key material was not valid. */ - errSecInternal = -26276, /* An internal error occured in the Security framework. */ - errSecUnsupportedAlgorithm = priv_errSecUnimplemented, // -26268, /* An unsupported algorithm was encountered. */ - errSecUnsupportedOperation = priv_errSecUnimplemented, // -26271, /* The operation you requested is not supported by this key. */ - errSecUnsupportedPadding = priv_errSecParam, // -26273, /* The padding you requested is not supported. */ - errSecItemInvalidKey = priv_errSecParam, // -34000, /* A string key in dictionary is not one of the supported keys. */ - errSecItemInvalidKeyType = priv_errSecParam, // -34001, /* A key in a dictionary is neither a CFStringRef nor a CFNumberRef. */ - errSecItemInvalidValue = priv_errSecParam, // -34002, /* A value in a dictionary is an invalid (or unsupported) CF type. */ - errSecItemClassMissing = priv_errSecParam, // -34003, /* No kSecItemClass key was specified in a dictionary. */ - errSecItemMatchUnsupported = priv_errSecParam, // -34004, /* The caller passed one or more kSecMatch keys to a function which does not support matches. */ - errSecUseItemListUnsupported = priv_errSecParam, // -34005, /* The caller passed in a kSecUseItemList key to a function which does not support it. */ - errSecUseKeychainUnsupported = priv_errSecParam, // -34006, /* The caller passed in a kSecUseKeychain key to a function which does not support it. */ - errSecUseKeychainListUnsupported = priv_errSecParam, // -34007, /* The caller passed in a kSecUseKeychainList key to a function which does not support it. */ - errSecReturnDataUnsupported = priv_errSecParam, // -34008, /* The caller passed in a kSecReturnData key to a function which does not support it. */ - errSecReturnAttributesUnsupported = priv_errSecParam, // -34009, /* The caller passed in a kSecReturnAttributes key to a function which does not support it. */ - errSecReturnRefUnsupported = priv_errSecParam, // -34010, /* The caller passed in a kSecReturnRef key to a function which does not support it. */ - errSecValueRefUnsupported = priv_errSecParam, // -34012, /* The caller passed in a kSecValueRef key to a function which does not support it. */ - errSecValuePersistentRefUnsupported = priv_errSecParam, // -34013, /* The caller passed in a kSecValuePersistentRef key to a function which does not support it. */ - errSecReturnMissingPointer = priv_errSecParam, // -34014, /* The caller passed asked for something to be returned but did not pass in a result pointer. */ - errSecMatchLimitUnsupported = priv_errSecParam, // -34015, /* The caller passed in a kSecMatchLimit key to a call which does not support limits. */ - errSecItemIllegalQuery = priv_errSecParam, // -34016, /* The caller passed in a query which contained too many keys. */ -}; - -const char *cssmErrorString(CSSM_RETURN error); - -OSStatus SecKeychainErrFromOSStatus(OSStatus osStatus); - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECBASEPRIV_H_ */ diff --git a/libsecurity_keychain/lib/SecCertificate.h b/libsecurity_keychain/lib/SecCertificate.h deleted file mode 100644 index e50c9c25..00000000 --- a/libsecurity_keychain/lib/SecCertificate.h +++ /dev/null @@ -1,466 +0,0 @@ -/* - * Copyright (c) 2002-2010 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 SecCertificate - The functions provided in SecCertificate implement and manage a particular type of keychain item that represents a certificate. You can store a certificate in a keychain, but a certificate can also be a transient object. - - You can use a certificate as a keychain item in most functions. -*/ - -#ifndef _SECURITY_SECCERTIFICATE_H_ -#define _SECURITY_SECCERTIFICATE_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/* -#include -#include -*/ - -#if defined(__cplusplus) -extern "C" { -#endif - -/*! - @enum CertificateItemAttributes - @abstract Indicates the type of a certificate item attribute. - @constant kSecSubjectItemAttr Indicates a DER-encoded subject distinguished name. - @constant kSecIssuerItemAttr Indicates a DER-encoded issuer distinguished name. - @constant kSecSerialNumberItemAttr Indicates a DER-encoded certificate serial number (without the tag and length). - @constant kSecPublicKeyHashItemAttr Indicates a public key hash. - @constant kSecSubjectKeyIdentifierItemAttr Indicates a subject key identifier. - @constant kSecCertTypeItemAttr Indicates a certificate type. - @constant kSecCertEncodingItemAttr Indicates a certificate encoding. -*/ -enum -{ - kSecSubjectItemAttr = 'subj', - kSecIssuerItemAttr = 'issu', - kSecSerialNumberItemAttr = 'snbr', - kSecPublicKeyHashItemAttr = 'hpky', - kSecSubjectKeyIdentifierItemAttr = 'skid', - kSecCertTypeItemAttr = 'ctyp', - kSecCertEncodingItemAttr = 'cenc' -} /*DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER*/; - -/*! - @function SecCertificateGetTypeID - @abstract Returns the type identifier of SecCertificate instances. - @result The CFTypeID of SecCertificate instances. -*/ -CFTypeID SecCertificateGetTypeID(void) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -#pragma mark ---- Certificate Operations ---- - -/*! - @function SecCertificateCreateFromData - @abstract Creates a certificate based on the input data, type, and encoding. - @param data A pointer to the certificate data. - @param type The certificate type as defined in cssmtype.h. - @param encoding The certificate encoding as defined in cssmtype.h. - @param certificate On return, a reference to the newly created certificate. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This API is deprecated in 10.7 Please use the SecCertificateCreateWithData API instead. -*/ -OSStatus SecCertificateCreateFromData(const CSSM_DATA *data, CSSM_CERT_TYPE type, CSSM_CERT_ENCODING encoding, SecCertificateRef *certificate) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/*! - @function SecCertificateCreateWithData - @abstract Create a certificate reference given its DER representation as a CFData. - @param allocator CFAllocator to allocate the certificate data. Pass NULL to use the default allocator. - @param certificate DER encoded X.509 certificate. - @result On return, a reference to the certificate. Returns NULL if the passed-in data is not a valid DER-encoded X.509 certificate. -*/ -SecCertificateRef SecCertificateCreateWithData(CFAllocatorRef allocator, CFDataRef data) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @function SecCertificateAddToKeychain - @abstract Adds a certificate to the specified keychain. - @param certificate A reference to a certificate. - @param keychain A reference to the keychain in which to add the certificate. Pass NULL to add the certificate to the default keychain. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is successful only if the certificate was created using the SecCertificateCreateFromData or - SecCertificateCreateWithData functions, and the certificate has not yet been added to the specified keychain. -*/ -OSStatus SecCertificateAddToKeychain(SecCertificateRef certificate, SecKeychainRef keychain) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); - -/*! - @function SecCertificateGetData - @abstract Retrieves the data for a given certificate. - @param certificate A reference to the certificate from which to retrieve the data. - @param data On return, the CSSM_DATA structure pointed to by data is filled in. You must allocate the space for a CSSM_DATA structure before calling this function. This data pointer is only guaranteed to remain valid as long as the certificate remains unchanged and valid. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This API is deprecated in 10.7. Please use the SecCertificateCopyData API instead. -*/ -OSStatus SecCertificateGetData(SecCertificateRef certificate, CSSM_DATA_PTR data) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/*! - @function SecCertificateCopyData - @abstract Returns the DER representation of an X.509 certificate. - @param certificate A reference to a certificate. - @result On return, a data reference containing the DER encoded representation of the X.509 certificate. -*/ -CFDataRef SecCertificateCopyData(SecCertificateRef certificate) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @function SecCertificateGetType - @abstract Retrieves the type for a given certificate. - @param certificate A reference to the certificate from which to obtain the type. - @param certificateType On return, the certificate type of the certificate. Certificate types are defined in cssmtype.h. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This API is deprecated in 10.7. Please use the SecCertificateCopyValues API instead. -*/ -OSStatus SecCertificateGetType(SecCertificateRef certificate, CSSM_CERT_TYPE *certificateType) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/*! - @function SecCertificateGetSubject - @abstract Retrieves the subject name for a given certificate. - @param certificate A reference to the certificate from which to obtain the subject name. - @param subject On return, a pointer to a CSSM_X509_NAME struct which contains the subject's X.509 name (x509defs.h). This pointer remains valid until the certificate reference is released. The caller should not attempt to free this pointer. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Prior to Mac OS X 10.5, this function did not return any output in the subject parameter. Your code should check the returned pointer value (in addition to the function result) before attempting to use it. - For example: - const CSSM_X509_NAME *subject = NULL; - OSStatus status = SecCertificateGetSubject(certificate, &subject); - if ( (status == errSecSuccess) && (subject != NULL) ) { - // subject is valid - } - This API is deprecated in 10.7. Please use the SecCertificateCopyValues API instead. -*/ -OSStatus SecCertificateGetSubject(SecCertificateRef certificate, const CSSM_X509_NAME **subject) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/*! - @function SecCertificateGetIssuer - @abstract Retrieves the issuer name for a given certificate. - @param certificate A reference to the certificate from which to obtain the issuer name. - @param issuer On return, a pointer to a CSSM_X509_NAME struct which contains the issuer's X.509 name (x509defs.h). This pointer remains valid until the certificate reference is released. The caller should not attempt to free this pointer. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Prior to Mac OS X 10.5, this function did not return any output in the issuer parameter. Your code should check the returned pointer value (in addition to the function result) before attempting to use it. - For example: - const CSSM_X509_NAME *issuer = NULL; - OSStatus status = SecCertificateGetIssuer(certificate, &issuer); - if ( (status == errSecSuccess) && (issuer != NULL) ) { - // issuer is valid - } - This API is deprecated in 10.7. Please use the SecCertificateCopyValues API instead. -*/ -OSStatus SecCertificateGetIssuer(SecCertificateRef certificate, const CSSM_X509_NAME **issuer) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/*! - @function SecCertificateGetCLHandle - @abstract Retrieves the certificate library handle for a given certificate. - @param certificate A reference to the certificate from which to obtain the certificate library handle. - @param clHandle On return, the certificate library handle of the given certificate. This handle remains valid at least as long as the certificate does. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This API is deprecated in 10.7. Please use the SecCertificateCopyValues API instead. -*/ -OSStatus SecCertificateGetCLHandle(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/*! - @function SecCertificateGetAlgorithmID - @abstract Retrieves the algorithm identifier for a given certificate. - @param certificate A reference to the certificate from which to retrieve the algorithm identifier. - @param algid On return, a pointer to a CSSM_X509_ALGORITHM_IDENTIFIER struct which identifies the algorithm for this certificate (x509defs.h). This pointer remains valid until the certificate reference is released. The caller should not attempt to free this pointer. - @result A result code. See "Security Error Codes" (SecBase.h). - discussion This API is deprecated in 10.7. Please use the SecCertificateCopyValues API instead. -*/ -OSStatus SecCertificateGetAlgorithmID(SecCertificateRef certificate, const CSSM_X509_ALGORITHM_IDENTIFIER **algid) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/*! - @function SecCertificateCopyPublicKey - @abstract Retrieves the public key for a given certificate. - @param certificate A reference to the certificate from which to retrieve the public key. - @param key On return, a reference to the public key for the specified certificate. Your code must release this reference by calling the CFRelease function. - @result A result code. See "Security Error Codes" (SecBase.h). -*/ -OSStatus SecCertificateCopyPublicKey(SecCertificateRef certificate, SecKeyRef *key) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); - -/*! - @function SecCertificateCopyCommonName - @abstract Retrieves the common name of the subject of a given certificate. - @param certificate A reference to the certificate from which to retrieve the common name. - @param commonName On return, a reference to the common name. Your code must release this reference by calling the CFRelease function. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion All the data in this string comes from the certificate itself, and thus it's in whatever language the certificate itself is in. - Note that the certificate's common name field may not be present, or may be inadequate to describe the certificate; for display purposes, - you should consider using SecCertificateCopySubjectSummary instead of this function. -*/ -OSStatus SecCertificateCopyCommonName(SecCertificateRef certificate, CFStringRef *commonName) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/*! - @function SecCertificateCopySubjectSummary - @abstract Returns a simple string which hopefully represents a human understandable summary. - @param certificate A reference to the certificate from which to derive the subject summary string. - @result On return, a reference to the subject summary string. Your code must release this reference by calling the CFRelease function. - @discussion All the data in this string comes from the certificate itself, and thus it's in whatever language the certificate itself is in. -*/ -CFStringRef SecCertificateCopySubjectSummary(SecCertificateRef certificate) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @function SecCertificateCopyEmailAddresses - @abstract Returns an array of zero or more email addresses for the subject of a given certificate. - @param certificate A reference to the certificate from which to retrieve the email addresses. - @param emailAddresses On return, an array of zero or more CFStringRef elements corresponding to each email address found. - Your code must release this array reference by calling the CFRelease function. - @result A result code. See "Security Error Codes" (SecBase.h). -*/ -OSStatus SecCertificateCopyEmailAddresses(SecCertificateRef certificate, CFArrayRef *emailAddresses) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/*! - @function SecCertificateCopyPreference - @abstract Returns the preferred certificate for the specified name and key usage. If a preferred certificate does not exist for the specified name and key usage, NULL is returned. - @param name A string containing an email address (RFC822) or other name for which a preferred certificate is requested. - @param keyUsage A CSSM_KEYUSE key usage value, as defined in cssmtype.h. Pass 0 to ignore this parameter. - @param certificate On return, a reference to the preferred certificate, or NULL if none was found. You are responsible for releasing this reference by calling the CFRelease function. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function will typically be used to obtain the preferred encryption certificate for an email recipient. - This API is deprecated in 10.7. Please use the SecCertificateCopyPreferred API instead. -*/ -OSStatus SecCertificateCopyPreference(CFStringRef name, uint32 keyUsage, SecCertificateRef *certificate) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/*! - @function SecCertificateCopyPreferred - @abstract Returns the preferred certificate for the specified name and key usage. If a preferred certificate does not exist for the specified name and key usage, NULL is returned. - @param name A string containing an email address (RFC822) or other name for which a preferred certificate is requested. - @param keyUsage A CFArrayRef value, containing items defined in SecItem.h Pass NULL to ignore this parameter. (kSecAttrCanEncrypt, kSecAttrCanDecrypt, kSecAttrCanDerive, kSecAttrCanSign, kSecAttrCanVerify, kSecAttrCanWrap, kSecAttrCanUnwrap) - @result On return, a reference to the preferred certificate, or NULL if none was found. You are responsible for releasing this reference by calling the CFRelease function. - @discussion This function will typically be used to obtain the preferred encryption certificate for an email recipient. If a preferred certificate has not been set - for the supplied name, the returned reference will be NULL. Your code should then perform a search for possible certificates, using the SecItemCopyMatching API. -*/ -SecCertificateRef SecCertificateCopyPreferred(CFStringRef name, CFArrayRef keyUsage) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/*! - @function SecCertificateSetPreference - @abstract Sets the preferred certificate for a specified name, key usage, and date. - @param certificate A reference to the certificate which will be preferred. - @param name A string containing an email address (RFC822) or other name for which a preferred certificate will be associated. - @param keyUsage A CSSM_KEYUSE key usage value, as defined in cssmtype.h. Pass 0 to avoid specifying a particular key usage. - @param date (optional) A date reference. If supplied, the preferred certificate will be changed only if this date is later than the currently saved setting. Pass NULL if this preference should not be restricted by date. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function will typically be used to set the preferred encryption certificate for an email recipient, either manually (when encrypting email to a recipient) or automatically upon receipt of encrypted email. - This API is deprecated in 10.7. Plese use the SecCertificateSetPreferred API instead. -*/ -OSStatus SecCertificateSetPreference(SecCertificateRef certificate, CFStringRef name, uint32 keyUsage, CFDateRef date) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/*! - @function SecCertificateSetPreferred - @abstract Sets the preferred certificate for a specified name and optional key usage. - @param certificate A reference to the preferred certificate. If NULL is passed, any existing preference for the specified name is cleared instead. - @param name A string containing an email address (RFC822) or other name for which a preferred certificate will be associated. - @param keyUsage A CFArrayRef value, containing items defined in SecItem.h Pass NULL to ignore this parameter. (kSecAttrCanEncrypt, kSecAttrCanDecrypt, kSecAttrCanDerive, kSecAttrCanSign, kSecAttrCanVerify, kSecAttrCanWrap, kSecAttrCanUnwrap) - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function will typically be used to set the preferred encryption certificate for an email recipient, either manually (when encrypting email to a recipient) - or automatically upon receipt of encrypted email. -*/ -OSStatus SecCertificateSetPreferred(SecCertificateRef certificate, CFStringRef name, CFArrayRef keyUsage) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/*! - @enum kSecPropertyKey - @abstract Constants used to access dictionary entries returned by SecCertificateCopyValues - @constant kSecPropertyKeyType The type of the entry - @constant kSecPropertyKeyLabel The label of the entry - @constant kSecPropertyKeyLocalizedLabel The localized label of the entry - @constant kSecPropertyKeyValue The value of the entry - */ - -extern CFStringRef kSecPropertyKeyType __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFStringRef kSecPropertyKeyLabel __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFStringRef kSecPropertyKeyLocalizedLabel __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFStringRef kSecPropertyKeyValue __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/*! - @enum kSecPropertyType - @abstract Public Constants for property list values returned by SecCertificateCopyValues - @discussion Note that kSecPropertyTypeTitle and kSecPropertyTypeError are defined in SecTrust.h -*/ -extern CFStringRef kSecPropertyTypeWarning __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFStringRef kSecPropertyTypeSuccess __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFStringRef kSecPropertyTypeSection __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFStringRef kSecPropertyTypeData __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFStringRef kSecPropertyTypeString __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFStringRef kSecPropertyTypeURL __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFStringRef kSecPropertyTypeDate __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/*! - @function SecCertificateCopyValues - @abstract Creates a dictionary that represents a certificate's contents. - @param certificate The certificate from which to get values - @param keys An array of string OID values, or NULL. If present, this is - the subset of values from the certificate to return. If NULL, - all values will be returned. Only OIDs that are top level keys - in the returned dictionary can be specified. Unknown OIDs are - ignored. - @param error An optional pointer to a CFErrorRef. This value is - set if an error occurred. If not NULL the caller is - responsible for releasing the CFErrorRef. - @discussion The keys array will contain all of the keys used in the - returned dictionary. The top level keys in the returned - dictionary are OIDs, many of which are found in SecCertificateOIDs.h. - Each entry that is returned is itself a dictionary with four - entries, whose keys are kSecPropertyKeyType, kSecPropertyKeyLabel, - kSecPropertyKeyLocalizedLabel, kSecPropertyKeyValue. The label - entries may contain a descriptive (localized) string, or an - OID string. The kSecPropertyKeyType describes the type in the - value entry. The value entry may be any CFType, although it - is usually a CFStringRef, CFArrayRef or a CFDictionaryRef. -*/ -CFDictionaryRef SecCertificateCopyValues(SecCertificateRef certificate, CFArrayRef keys, CFErrorRef *error) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/*! - @enum Transform Key Value Constants - @discussion Predefined values for the kSecTransformAttrCertificateUsage attribute. - - - kSecCertificateUsageSigning - kSecCertificateUsageSigningAndEncrypting - kSecCertificateUsageDeriveAndSign - -*/ - -extern const CFStringRef kSecCertificateUsageSigning __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFStringRef kSecCertificateUsageSigningAndEncrypting __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFStringRef kSecCertificateUsageDeriveAndSign __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/*! - @function SecCertificateCopyLongDescription - @abstract Return the long description of a certificate - @param alloc The CFAllocator which should be used to allocate - memory for the dictionary and its storage for values. This - parameter may be NULL in which case the current default - CFAllocator is used. If this reference is not a valid - CFAllocator, the behavior is undefined. - @param certificate The certificate from which to retrieve the long description - @param error An optional pointer to a CFErrorRef. This value is - set if an error occurred. If not NULL the caller is - responsible for releasing the CFErrorRef. - @result A CFStringRef of the long description or NULL. If NULL and the error - parameter is supplied the error will be returned in the error parameter - @discussion Note that the format of this string may change in the future -*/ - -CFStringRef SecCertificateCopyLongDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/*! - @function SecCertificateCopyShortDescription - @abstract Return the short description of a certificate - @param alloc The CFAllocator which should be used to allocate - memory for the dictionary and its storage for values. This - parameter may be NULL in which case the current default - CFAllocator is used. If this reference is not a valid - CFAllocator, the behavior is undefined. - @param certificate The certificate from which to retrieve the short description - @param error An optional pointer to a CFErrorRef. This value is - set if an error occurred. If not NULL the caller is - responsible for releasing the CFErrorRef. - @result A CFStringRef of the short description or NULL. If NULL and the error - parameter is supplied the error will be returned in the error parameter - @discussion Note that the format of this string may change in the future -*/ - -CFStringRef SecCertificateCopyShortDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/*! - @function SecCertificateCopySerialNumber - @abstract Return the certificate's serial number. - @param certificate The certificate from which to get values - @param error An optional pointer to a CFErrorRef. This value is - set if an error occurred. If not NULL the caller is - responsible for releasing the CFErrorRef. - @discussion Return the content of a DER-encoded integer (without the - tag and length fields) for this certificate's serial - number. The caller must CFRelease the value returned. -*/ - -CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate, CFErrorRef *error) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/*! - @function SecCertificateCopyNormalizedIssuerContent - @abstract Return the certificate's normalized issuer - @param certificate The certificate from which to get values - @param error An optional pointer to a CFErrorRef. This value is - set if an error occurred. If not NULL the caller is - responsible for releasing the CFErrorRef. - @discussion The issuer is a sequence in the format used by - SecItemCopyMatching. The content returned is a DER-encoded - X.509 distinguished name. For a display version of the issuer, - call SecCertificateCopyValues. The caller must CFRelease - the value returned. -*/ - -CFDataRef SecCertificateCopyNormalizedIssuerContent(SecCertificateRef certificate, CFErrorRef *error) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/*! - @function SecCertificateCopyNormalizedSubjectContent - @abstract Return the certificate's normalized subject - @param certificate The certificate from which to get values - @param error An optional pointer to a CFErrorRef. This value is - set if an error occurred. If not NULL the caller is - responsible for releasing the CFErrorRef. - @discussion The subject is a sequence in the format used by - SecItemCopyMatching. The content returned is a DER-encoded - X.509 distinguished name. For a display version of the subject, - call SecCertificateCopyValues. The caller must CFRelease - the value returned. -*/ - -CFDataRef SecCertificateCopyNormalizedSubjectContent(SecCertificateRef certificate, CFErrorRef *error) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECCERTIFICATE_H_ */ diff --git a/libsecurity_keychain/lib/SecCertificatePriv.h b/libsecurity_keychain/lib/SecCertificatePriv.h deleted file mode 100644 index 2f48ab2f..00000000 --- a/libsecurity_keychain/lib/SecCertificatePriv.h +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 2002-2004,2012-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@ - */ - -#ifndef _SECURITY_SECCERTIFICATEPRIV_H_ -#define _SECURITY_SECCERTIFICATEPRIV_H_ - -#include -#include -#include -#include -#include -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -typedef uint32_t SecCertificateEscrowRootType; -enum { - kSecCertificateBaselineEscrowRoot = 0, - kSecCertificateProductionEscrowRoot = 1, -}; - -extern CFTypeRef kSecCertificateProductionEscrowKey; -extern CFTypeRef kSecCertificateEscrowFileName; - - -/* Return a certificate for the DER representation of this certificate. - Return NULL if the passed-in data is not a valid DER-encoded X.509 - certificate. */ -SecCertificateRef SecCertificateCreateWithBytes(CFAllocatorRef allocator, - const UInt8 *bytes, CFIndex length); - -/* Return the length of the DER representation of this certificate. */ -CFIndex SecCertificateGetLength(SecCertificateRef certificate); - -/* Return the bytes of the DER representation of this certificate. */ -const UInt8 *SecCertificateGetBytePtr(SecCertificateRef certificate); - -/* Return the SHA-1 hash of this certificate. */ -CFDataRef SecCertificateGetSHA1Digest(SecCertificateRef certificate); - -/* Deprecated; use SecCertificateCopyCommonName() instead. */ -OSStatus SecCertificateGetCommonName(SecCertificateRef certificate, CFStringRef *commonName); - -/* Deprecated; use SecCertificateCopyEmailAddresses() instead. */ -/* This should have been Copy instead of Get since the returned address is not autoreleased. */ -OSStatus SecCertificateGetEmailAddress(SecCertificateRef certificate, CFStringRef *emailAddress); - -/* Return an array of CFStringRefs representing the dns addresses in the - certificate if any. */ -CFArrayRef SecCertificateCopyDNSNames(SecCertificateRef certificate); - -/*! - @function SecCertificateCopyIssuerSummary - @abstract Return a simple string which hopefully represents a human understandable issuer. - @param certificate SecCertificate object created with SecCertificateCreateWithData(). - @discussion All the data in this string comes from the certificate itself - and thus it's in whatever language the certificate itself is in. - @result A CFStringRef which the caller should CFRelease() once it's no longer needed. -*/ -CFStringRef SecCertificateCopyIssuerSummary(SecCertificateRef certificate); - -/* - * Private API to infer a display name for a SecCertificateRef which - * may or may not be in a keychain. - */ -OSStatus SecCertificateInferLabel(SecCertificateRef certificate, CFStringRef *label); - -/* - * Subset of the above, useful for both certs and CRLs. - * Infer printable label for a given an CSSM_X509_NAME. Returns NULL - * if no appropriate printable name found. - */ -const CSSM_DATA *SecInferLabelFromX509Name( - const CSSM_X509_NAME *x509Name); - -/* Accessors for fields in the cached certificate */ - -/*! - @function SecCertificateCopyFieldValues - @abstract Retrieves the values for a particular field in a given certificate. - @param certificate A valid SecCertificateRef to the certificate. - @param field Pointer to the OID whose values should be returned. - @param fieldValues On return, a zero terminated list of CSSM_DATA_PTR's. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Return a zero terminated list of CSSM_DATA_PTR's with the - values of the field specified by field. Caller must call - SecCertificateReleaseFieldValues to free the storage allocated by this call. -*/ -OSStatus SecCertificateCopyFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR **fieldValues); - -/*! - @function SecCertificateReleaseFieldValues - @abstract Release the storage associated with the values returned by SecCertificateCopyFieldValues. - @param certificate A valid SecCertificateRef to the certificate. - @param field Pointer to the OID whose values were returned by SecCertificateCopyFieldValues. - @param fieldValues Pointer to a zero terminated list of CSSM_DATA_PTR's. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Release the storage associated with the values returned by SecCertificateCopyFieldValues. -*/ -OSStatus SecCertificateReleaseFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValues); - -/*! - @function SecCertificateCopyFirstFieldValue - @abstract Return a CSSM_DATA_PTR with the value of the first field specified by field. - @param certificate A valid SecCertificateRef to the certificate. - @param field Pointer to the OID whose value should be returned. - @param fieldValue On return, a CSSM_DATA_PTR to the field data. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Return a CSSM_DATA_PTR with the value of the first field specified by field. Caller must call - SecCertificateReleaseFieldValue to free the storage allocated by this call. -*/ -OSStatus SecCertificateCopyFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValue); - -/*! - @function SecCertificateReleaseFirstFieldValue - @abstract Release the storage associated with the values returned by SecCertificateCopyFirstFieldValue. - @param certificate A valid SecCertificateRef to the certificate. - @param field Pointer to the OID whose values were returned by SecCertificateCopyFieldValue. - @param fieldValue The field data to release. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Release the storage associated with the values returned by SecCertificateCopyFieldValue. -*/ -OSStatus SecCertificateReleaseFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR fieldValue); - -/*! - @function SecCertificateCopySubjectComponent - @abstract Retrieves a component of the subject distinguished name of a given certificate. - @param certificate A reference to the certificate from which to retrieve the common name. - @param component A component oid naming the component desired. See . - @param result On return, a reference to the string form of the component, if present in the subject. - Your code must release this reference by calling the CFRelease function. - @result A result code. See "Security Error Codes" (SecBase.h). - */ -OSStatus SecCertificateCopySubjectComponent(SecCertificateRef certificate, const CSSM_OID *component, - CFStringRef *result); - -/* Return the DER encoded issuer sequence for the certificate's issuer. */ -CFDataRef SecCertificateCopyIssuerSequence(SecCertificateRef certificate); - -/* Return the DER encoded subject sequence for the certificate's subject. */ -CFDataRef SecCertificateCopySubjectSequence(SecCertificateRef certificate); - - -/* Convenience functions for searching. -*/ - -OSStatus SecCertificateFindByIssuerAndSN(CFTypeRef keychainOrArray, const CSSM_DATA *issuer, - const CSSM_DATA *serialNumber, SecCertificateRef *certificate); - -OSStatus SecCertificateFindBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID, - SecCertificateRef *certificate); - -OSStatus SecCertificateFindByEmail(CFTypeRef keychainOrArray, const char *emailAddress, - SecCertificateRef *certificate); - - -/* These should go to SecKeychainSearchPriv.h. */ -OSStatus SecKeychainSearchCreateForCertificateByIssuerAndSN(CFTypeRef keychainOrArray, const CSSM_DATA *issuer, - const CSSM_DATA *serialNumber, SecKeychainSearchRef *searchRef); - -OSStatus SecKeychainSearchCreateForCertificateByIssuerAndSN_CF(CFTypeRef keychainOrArray, CFDataRef issuer, - CFDataRef serialNumber, SecKeychainSearchRef *searchRef); - -OSStatus SecKeychainSearchCreateForCertificateBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID, - SecKeychainSearchRef *searchRef); - -OSStatus SecKeychainSearchCreateForCertificateByEmail(CFTypeRef keychainOrArray, const char *emailAddress, - SecKeychainSearchRef *searchRef); - -/* Convenience function for generating digests; should be moved elsewhere. */ -CSSM_RETURN SecDigestGetData(CSSM_ALGORITHMS alg, CSSM_DATA* digest, const CSSM_DATA* data); - -/* Return true iff certificate is valid as of verifyTime. */ -/* DEPRECATED: Use SecCertificateIsValid instead. */ -bool SecCertificateIsValidX(SecCertificateRef certificate, CFAbsoluteTime verifyTime) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecCertificateIsValid - @abstract Check certificate validity on a given date. - @param certificate A certificate reference. - @result Returns true if the specified date falls within the certificate's validity period, false otherwise. -*/ -bool SecCertificateIsValid(SecCertificateRef certificate, CFAbsoluteTime verifyTime) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_2_0); - -/*! - @function SecCertificateNotValidBefore - @abstract Obtain the starting date of the given certificate. - @param certificate A certificate reference. - @result Returns the absolute time at which the given certificate becomes valid, - or 0 if this value could not be obtained. -*/ -CFAbsoluteTime SecCertificateNotValidBefore(SecCertificateRef certificate) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_2_0); - -/*! - @function SecCertificateNotValidAfter - @abstract Obtain the expiration date of the given certificate. - @param certificate A certificate reference. - @result Returns the absolute time at which the given certificate expires, - or 0 if this value could not be obtained. -*/ -CFAbsoluteTime SecCertificateNotValidAfter(SecCertificateRef certificate) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_2_0); - -/*! - @function SecCertificateIsSelfSigned - @abstract Determine if the given certificate is self-signed. - @param certRef A certificate reference. - @param isSelfSigned Will be set to true on return if the certificate is self-signed, false otherwise. - @result A result code. Returns errSecSuccess if the certificate's status can be determined. -*/ -OSStatus SecCertificateIsSelfSigned(SecCertificateRef certRef, Boolean *isSelfSigned) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/*! - @function SecCertificateCopyEscrowRoots - @abstract Retrieve the array of valid escrow certificates for a given root type. - @param escrowRootType An enumerated type indicating which root type to return. - @result An array of zero or more escrow certificates matching the provided type. -*/ -CFArrayRef SecCertificateCopyEscrowRoots(SecCertificateEscrowRootType escrowRootType) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECCERTIFICATEPRIV_H_ */ diff --git a/libsecurity_keychain/lib/SecCertificateRequest.h b/libsecurity_keychain/lib/SecCertificateRequest.h deleted file mode 100644 index cbbb3ca8..00000000 --- a/libsecurity_keychain/lib/SecCertificateRequest.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (c) 2002-2004 Apple Computer, 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 SecCertificateRequest - SecCertificateRequest implements a way to issue a certificate request to a - certificate authority. -*/ - -#ifndef _SECURITY_SECCERTIFICATEREQUEST_H_ -#define _SECURITY_SECCERTIFICATEREQUEST_H_ - -#include -#include - - -#if defined(__cplusplus) -extern "C" { -#endif - -struct SecCertificateRequestAttribute /* for optional oids */ -{ - CSSM_OID oid; - CSSM_DATA value; -}; -typedef struct SecCertificateRequestAttribute SecCertificateRequestAttribute; - -struct SecCertificateRequestAttributeList -{ - UInt32 count; - SecCertificateRequestAttribute *attr; -}; -typedef struct SecCertificateRequestAttributeList SecCertificateRequestAttributeList; - -/*! - @typedef SecCertificateRequestRef - @abstract Contains information about a certificate request. -*/ -typedef struct OpaqueSecCertificateRequestRef *SecCertificateRequestRef; - -/*! - @function SecCertificateRequestGetTypeID - Returns the type identifier of all SecCertificateRequest instances. -*/ -CFTypeID SecCertificateRequestGetTypeID(void); - -/*! - @function SecCertificateRequestCreate - - Create a certificate request operation based on a policy and certificate - type. If a policy is not specified, one will be chosen for the caller. - Once the requeste is created, a request reference is returned. - To submit the request call SecCertificateRequestSubmit(). - - @param policy A policy. - @param certificateType The certificate type (i.e. X509, PGP, etc). - These types are in cssmtype.h - @param requestType The identifier to the type of request to submit (i.e. - issue, verify, revoke, etc.). These are defined in cssmtype.h - @param privateKeyItemRef The keychain item private key to be used for this - certificate request. The private key item must be of class type - kSecAppleKeyItemClass. - @param attributeList An optional list of OIDs for the certificate request. - @param certRequest A returned reference to the certificate request. Call CFRelease when done with this certificate request. - @result errSecSuccess 0 No error. -*/ -OSStatus SecCertificateRequestCreate( - const CSSM_OID *policy, - CSSM_CERT_TYPE certificateType, - CSSM_TP_AUTHORITY_REQUEST_TYPE requestType, - SecKeyRef privateKeyItemRef, - SecKeyRef publicKeyItemRef, - const SecCertificateRequestAttributeList* attributeList, - SecCertificateRequestRef* certRequest); - -/*! - @function SecCertificateRequestSubmit - - Submit a certificate request to be processed by the Security framework. - Once the request is submitted, an estimated time is returned indicating - when the request results can be retrieved. Once the estimated time has - elapsed, obtain the result by calling SecCertificateRequestGetResult(). - - @param certRequest A reference to the certificate request. - @param estimatedTime The number of estimated seconds before the result - can be retrieved. - @result errSecSuccess 0 No error. -*/ -OSStatus SecCertificateRequestSubmit( - SecCertificateRequestRef certRequest, - sint32* estimatedTime); - -/*! - @function SecCertificateRequestGetType - Returns the certificate request type (i.e. issue, revoke, etc) for a given - certificate request item reference. - @param certRequestRef A reference to a submitted request. - @param requestType The returned request type. - @result errSecSuccess 0 No error. -*/ -OSStatus SecCertificateRequestGetType( - SecCertificateRequestRef certRequestRef, - CSSM_TP_AUTHORITY_REQUEST_TYPE* requestType); - -/*! - @function SecCertificateRequestGetResult - Get the results of a certificate request. If the request is still - pending, the estimated time will be returned which indicates when to - call this function again. - @param certRequestRef A reference for the submitted request. - @param keychain The keychain in which to store the new certificate (for - a new cert request) and the cert request item reference. Pass NULL - to specify the default keychain. - @param estimatedTime The number of estimated seconds before the result can - be retrieved. - @param certficateRef The returned certificate reference for a - CSSM_TP_AUTHORITY_REQUEST_CERTISSUE only. All other request types return - NULL here. Call CFRelease when done with this certificate reference. - @result errSecSuccess 0 No error. -*/ -OSStatus SecCertificateRequestGetResult( - SecCertificateRequestRef certRequestRef, - SecKeychainRef keychain, - sint32* estimatedTime, - SecCertificateRef* certificateRef); - -/*! - @function SecCertificateFindRequest - Find a pending certificate request and return a reference object - for it. The search criteria is based on the input parameters. - @param policy A policy. - @param certificateType The certificate type (i.e. X509, PGP, etc). - These types are in cssmtype.h - @param requestType The identifier to the type of request to find (i.e. - issue, verify, revoke, etc.). These are defined in cssmtype.h - @param privateKeyItemRef Optional private key to be used - for the certificate request. Matches the same argument as passed to - SecCertificateRequestCreate(). - @param publicKeyItemRef Optional public key to be used - for the certificate request. Matches the same argument as passed to - SecCertificateRequestCreate(). - @param attributeList An optional list of OID/value pairs for finding the - certificate request. - @param certRequest A returned reference to the certificate request. Call CFRelease when done with this reference. -*/ -OSStatus SecCertificateFindRequest( - const CSSM_OID *policy, - CSSM_CERT_TYPE certificateType, - CSSM_TP_AUTHORITY_REQUEST_TYPE requestType, - SecKeyRef privateKeyItemRef, - SecKeyRef publicKeyItemRef, - const SecCertificateRequestAttributeList* attributeList, - SecCertificateRequestRef* certRequest); - -/*! - @function SecCertificateRequestGetData - Get policy-specific data following a SecCertificateRequestSubmit. - @param certRequestRef A reference for the submitted request. - @param data Policy-specific data. - @result errSecSuccess 0 No error. -*/ - -OSStatus SecCertificateRequestGetData( - SecCertificateRequestRef certRequestRef, - CSSM_DATA *data); - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECCERTIFICATEREQUEST_H_ */ diff --git a/libsecurity_keychain/lib/SecIdentity.h b/libsecurity_keychain/lib/SecIdentity.h deleted file mode 100644 index c44b9cfc..00000000 --- a/libsecurity_keychain/lib/SecIdentity.h +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 2002-2010 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 SecIdentity - The functions provided in SecIdentity implement a convenient way to match private keys with certificates. -*/ - -#ifndef _SECURITY_SECIDENTITY_H_ -#define _SECURITY_SECIDENTITY_H_ - -#include -#include -#include -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -/*! - @function SecIdentityGetTypeID - @abstract Returns the type identifier of SecIdentity instances. - @result The CFTypeID of SecIdentity instances. -*/ -CFTypeID SecIdentityGetTypeID(void) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -/*! - @function SecIdentityCreateWithCertificate - @abstract Creates a new identity reference for the given certificate, assuming the associated private key is in one of the specified keychains. - @param keychainOrArray A reference to an array of keychains to search, a single keychain, or NULL to search the user's default keychain search list. - @param certificateRef A certificate reference. - @param identityRef On return, an identity reference. You are responsible for releasing this reference by calling the CFRelease function. - @result A result code. See "Security Error Codes" (SecBase.h). -*/ -OSStatus SecIdentityCreateWithCertificate( - CFTypeRef keychainOrArray, - SecCertificateRef certificateRef, - SecIdentityRef *identityRef) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/*! - @function SecIdentityCopyCertificate - @abstract Returns a reference to a certificate for the given identity reference. - @param identityRef An identity reference. - @param certificateRef On return, a reference to the found certificate. You are responsible for releasing this reference by calling the CFRelease function. - @result A result code. See "Security Error Codes" (SecBase.h). -*/ -OSStatus SecIdentityCopyCertificate( - SecIdentityRef identityRef, - SecCertificateRef *certificateRef) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -/*! - @function SecIdentityCopyPrivateKey - @abstract Returns the private key associated with an identity. - @param identityRef An identity reference. - @param privateKeyRef On return, a reference to the private key for the given identity. You are responsible for releasing this reference by calling the CFRelease function. - @result A result code. See "Security Error Codes" (SecBase.h). -*/ -OSStatus SecIdentityCopyPrivateKey( - SecIdentityRef identityRef, - SecKeyRef *privateKeyRef) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -/*! - @function SecIdentityCopyPreference - @abstract Returns the preferred identity for the specified name and key usage, optionally limiting the result to an identity issued by a certificate whose subject is one of the distinguished names in validIssuers. If a preferred identity does not exist, NULL is returned. - @param name A string containing a URI, RFC822 email address, DNS hostname, or other name which uniquely identifies the service requiring an identity. - @param keyUsage A CSSM_KEYUSE key usage value, as defined in cssmtype.h. Pass 0 to ignore this parameter. - @param validIssuers (optional) An array of CFDataRef instances whose contents are the subject names of allowable issuers, as returned by a call to SSLCopyDistinguishedNames (SecureTransport.h). Pass NULL if any issuer is allowed. - @param identity On return, a reference to the preferred identity, or NULL if none was found. You are responsible for releasing this reference by calling the CFRelease function. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This API is deprecated in 10.7. Please use the SecIdentityCopyPreferred API instead. -*/ -OSStatus SecIdentityCopyPreference(CFStringRef name, CSSM_KEYUSE keyUsage, CFArrayRef validIssuers, SecIdentityRef *identity) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/*! - @function SecIdentityCopyPreferred - @abstract Returns the preferred identity for the specified name and key usage, optionally limiting the result to an identity issued by a certificate whose subject is one of the distinguished names in validIssuers. If a preferred identity does not exist, NULL is returned. - @param name A string containing a URI, RFC822 email address, DNS hostname, or other name which uniquely identifies the service requiring an identity. - @param keyUsage A CFArrayRef value, containing items defined in SecItem.h Pass NULL to ignore this parameter. (kSecAttrCanEncrypt, kSecAttrCanDecrypt, kSecAttrCanDerive, kSecAttrCanSign, kSecAttrCanVerify, kSecAttrCanWrap, kSecAttrCanUnwrap) - @param validIssuers (optional) An array of CFDataRef instances whose contents are the subject names of allowable issuers, as returned by a call to SSLCopyDistinguishedNames (SecureTransport.h). Pass NULL if any issuer is allowed. - @param identity On return, a reference to the preferred identity, or NULL if none was found. You are responsible for releasing this reference by calling the CFRelease function. - @result An identity or NULL. if the preferred identity has not been set. Your code should then typically perform a search for possible identities using the SecItem APIs. - @discussion If a preferred identity has not been set for the supplied name, the returned identity reference will be NULL. Your code should then perform a search for possible identities, using the SecItemCopyMatching API. -*/ -SecIdentityRef SecIdentityCopyPreferred(CFStringRef name, CFArrayRef keyUsage, CFArrayRef validIssuers) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/*! - @function SecIdentitySetPreference - @abstract Sets the preferred identity for the specified name and key usage. - @param identity A reference to the identity which will be preferred. - @param name A string containing a URI, RFC822 email address, DNS hostname, or other name which uniquely identifies a service requiring this identity. - @param keyUsage A CSSM_KEYUSE key usage value, as defined in cssmtype.h. Pass 0 to specify any key usage. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This API is deprecated in 10.7. Please use the SecIdentitySetPreferred API instead. -*/ -OSStatus SecIdentitySetPreference(SecIdentityRef identity, CFStringRef name, CSSM_KEYUSE keyUsage) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/*! - @function SecIdentitySetPreferred - @abstract Sets the preferred identity for the specified name and key usage. - @param identity A reference to the identity which will be preferred. If NULL is passed, any existing preference for the specified name is cleared instead. - @param name A string containing a URI, RFC822 email address, DNS hostname, or other name which uniquely identifies a service requiring this identity. - @param keyUsage A CFArrayRef value, containing items defined in SecItem.h Pass NULL to specify any key usage. (kSecAttrCanEncrypt, kSecAttrCanDecrypt, kSecAttrCanDerive, kSecAttrCanSign, kSecAttrCanVerify, kSecAttrCanWrap, kSecAttrCanUnwrap) - @result A result code. See "Security Error Codes" (SecBase.h). -*/ -OSStatus SecIdentitySetPreferred(SecIdentityRef identity, CFStringRef name, CFArrayRef keyUsage) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/*! - @function SecIdentityCopySystemIdentity - @abstract Obtain the system-wide SecIdentityRef associated with - a specified domain. - @param domain Identifies the SecIdentityRef to be obtained, typically - in the form "com.apple.subdomain...". - @param idRef On return, the system SecIdentityRef assicated with - the specified domain. Caller must CFRelease this when - finished with it. - @param actualDomain (optional) The actual domain name of the - the returned identity is returned here. This - may be different from the requested domain. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion If no system SecIdentityRef exists for the specified - domain, a domain-specific alternate may be returned - instead, typically (but not exclusively) the - kSecIdentityDomainDefault SecIdentityRef. - */ -OSStatus SecIdentityCopySystemIdentity( - CFStringRef domain, - SecIdentityRef *idRef, - CFStringRef *actualDomain) /* optional */ - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/*! - @function SecIdentitySetSystemIdentity - @abstract Assign the supplied SecIdentityRef to the specified - domain. - @param domain Identifies the domain to which the specified - SecIdentityRef will be assigned. - @param idRef (optional) The identity to be assigned to the specified - domain. Pass NULL to delete a possible entry for the specified - domain; in this case, it is not an error if no identity - exists for the specified domain. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion The caller must be running as root. -*/ -OSStatus SecIdentitySetSystemIdentity( - CFStringRef domain, - SecIdentityRef idRef) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - - -/* - * Defined system identity domains. - */ - -/*! - @const kSecIdentityDomainDefault The system-wide default identity. - */ -extern const CFStringRef kSecIdentityDomainDefault __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/*! - @const kSecIdentityDomainKerberosKDC Kerberos KDC identity. -*/ -extern const CFStringRef kSecIdentityDomainKerberosKDC __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECIDENTITY_H_ */ diff --git a/libsecurity_keychain/lib/SecIdentityPriv.h b/libsecurity_keychain/lib/SecIdentityPriv.h deleted file mode 100644 index a9c8d137..00000000 --- a/libsecurity_keychain/lib/SecIdentityPriv.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2002-2010 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _SECURITY_SECIDENTITYPRIV_H_ -#define _SECURITY_SECIDENTITYPRIV_H_ - -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -/*! @function SecIdentityCreate - @abstract create a new identity object from the provided certificate and its associated private key. - @param allocator CFAllocator to allocate the identity object. Pass NULL to use the default allocator. - @param certificate A certificate reference. - @param privateKey A private key reference. - @result An identity reference. -*/ -SecIdentityRef SecIdentityCreate( - CFAllocatorRef allocator, - SecCertificateRef certificate, - SecKeyRef privateKey) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); - -/*! - @function SecIdentityCompare - @abstract Compares two SecIdentityRef instances for equality. - @param identity1 An identity reference. - @param identity2 An identity reference. - @param compareOptions A value containing option flags. Currently there are no compare options, so 0 should be passed for this parameter. - @result An enumerated value of type CFComparisonResult. See CFBase.h. - @discussion Two identities are considered equal if they contain identical certificate and private key components. - @deprecated in Mac OS X 10.5 and later; the CFEqual function should be used instead (CFBase.h). -*/ -CFComparisonResult SecIdentityCompare( - SecIdentityRef identity1, - SecIdentityRef identity2, - CFOptionFlags compareOptions) - DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER; - -/*! - @function SecIdentityFindPreferenceItem - @abstract Returns an identity preference item, given an identity string. - @param keychainOrArray A reference to an array of keychains to search, a single keychain, or NULL to search the user's default keychain search list. - @param idString A string containing a URI, hostname, or email (RFC822) address. - @param itemRef On return, a reference to the keychain item which was found. The caller is responsible for releasing this reference. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion An identity preference item maps a particular identity to a string, such as a URI or email address. It specifies that this identity should be preferred in transactions which match the provided string. - @deprecated in Mac OS X 10.7 and later; use SecIdentityCopyPreferred() instead (SecIdentity.h) - - WARNING: This function is based on an implementation detail and will go away - in a future release; its use should be avoided at all costs. It does not - provide a way to find a preference item based on key usage, and it can only - find preferences which are stored as keychain items, so it may fail to find - the item you expect. Please use the public API functions to manipulate - identity preferences. -*/ -OSStatus SecIdentityFindPreferenceItem( - CFTypeRef keychainOrArray, - CFStringRef idString, - SecKeychainItemRef *itemRef) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/*! - @function SecIdentityAddPreferenceItem - @abstract Adds a new identity preference item to the specified keychain. - @param keychainRef A reference to the keychain in which to store the preference item. Pass NULL to specify the user's default keychain. - @param identityRef An identity reference. - @param idString A string containing a URI, hostname, or email (RFC822) address. - @param itemRef On return, a reference to the new keychain item. The caller is responsible for releasing this reference. Pass NULL if the reference is not needed. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion An identity preference item maps a particular identity to a string, such as a URI or email address. It specifies that this identity should be preferred in transactions which match the provided string. - @deprecated in Mac OS X 10.5; use SecIdentitySetPreference() instead (SecIdentity.h). -*/ -OSStatus SecIdentityAddPreferenceItem( - SecKeychainRef keychainRef, - SecIdentityRef identityRef, - CFStringRef idString, - SecKeychainItemRef *itemRef) - DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER; - -/*! - @function SecIdentityUpdatePreferenceItem - @abstract Given an existing identity preference keychain item, update it with the provided identity. - @param itemRef An identity preference keychain item, as returned by SecIdentityFindPreferenceItem or SecIdentityAddPreferenceItem. - @param identityRef An identity reference. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is used to update an existing preference item when a different identity is preferred. - @deprecated in Mac OS X 10.5; use SecIdentitySetPreference() instead (SecIdentity.h). -*/ -OSStatus SecIdentityUpdatePreferenceItem( - SecKeychainItemRef itemRef, - SecIdentityRef identityRef) - DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER; - -/*! - @function SecIdentityCopyFromPreferenceItem - @abstract Given an existing identity preference keychain item, obtain a SecIdentityRef for the identity it specifies. - @param itemRef An identity preference keychain item, as returned by SecIdentityFindPreferenceItem or SecIdentityAddPreferenceItem. - @param identityRef On return, an identity reference. The caller is responsible for releasing this reference. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is used to obtain a SecIdentityRef from an existing preference item. - @deprecated in Mac OS X 10.5; use SecIdentityCopyPreference() instead (SecIdentity.h). -*/ -OSStatus SecIdentityCopyFromPreferenceItem( - SecKeychainItemRef itemRef, - SecIdentityRef *identityRef) - DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER; - -/*! - @function ConvertArrayToKeyUsage - @abstract Given an array of key usages defined in SecItem.h return the equivalent CSSM_KEYUSE - @param usage An CFArrayRef containing CFTypeRefs defined in SecItem.h - kSecAttrCanEncrypt, - kSecAttrCanDecrypt, - kSecAttrCanDerive, - kSecAttrCanSign, - kSecAttrCanVerify, - kSecAttrCanWrap, - kSecAttrCanUnwrap - If the CFArrayRef is NULL then the CSSM_KEYUSAGE will be CSSM_KEYUSE_ANY - @result A CSSM_KEYUSE. Derived from the passed in Array -*/ -CSSM_KEYUSE ConvertArrayToKeyUsage(CFArrayRef usage); - - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECIDENTITYPRIV_H_ */ diff --git a/libsecurity_keychain/lib/SecImportExport.c b/libsecurity_keychain/lib/SecImportExport.c deleted file mode 100644 index 70563223..00000000 --- a/libsecurity_keychain/lib/SecImportExport.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright (c) 2007-2010 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -//#include -#include -#include -#include -#include -#include -#include -#include "SecInternal.h" - -//#include -#include - -//#include "p12import.h" -#include "SecImportExport.h" - -CFStringRef kSecImportExportPassphrase = CFSTR("passphrase"); -CFStringRef kSecImportExportKeychain = CFSTR("keychain"); -CFStringRef kSecImportExportAccess = CFSTR("access"); - -CFStringRef kSecImportItemLabel = CFSTR("label"); -CFStringRef kSecImportItemKeyID = CFSTR("keyid"); -CFStringRef kSecImportItemTrust = CFSTR("trust"); -CFStringRef kSecImportItemCertChain = CFSTR("chain"); -CFStringRef kSecImportItemIdentity = CFSTR("identity"); - -#if 0 -static void collect_certs(const void *key, const void *value, void *context) -{ - if (!CFDictionaryContainsKey(value, CFSTR("key"))) { - CFDataRef cert_bytes = CFDictionaryGetValue(value, CFSTR("cert")); - if (!cert_bytes) - return; - SecCertificateRef cert = - SecCertificateCreateWithData(kCFAllocatorDefault, cert_bytes); - if (!cert) - return; - CFMutableArrayRef cert_array = (CFMutableArrayRef)context; - CFArrayAppendValue(cert_array, cert); - CFRelease(cert); - } -} - -typedef struct { - CFMutableArrayRef identities; - CFArrayRef certs; -} build_trust_chains_context; - -static void build_trust_chains(const void *key, const void *value, - void *context) -{ - CFMutableDictionaryRef identity_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, - 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - SecKeyRef private_key = NULL; - SecCertificateRef cert = NULL; - SecIdentityRef identity = NULL; - SecPolicyRef policy = NULL; - CFMutableArrayRef cert_chain = NULL, eval_chain = NULL; - SecTrustRef trust = NULL; - build_trust_chains_context * a_build_trust_chains_context = (build_trust_chains_context*)context; - - CFDataRef key_bytes = CFDictionaryGetValue(value, CFSTR("key")); - if(!key_bytes) goto out; //require(key_bytes, out); - CFDataRef cert_bytes = CFDictionaryGetValue(value, CFSTR("cert")); - if(!cert_bytes) goto out; //require(cert_bytes, out); - - /* p12import only passes up rsa keys */ -//FIXME: needs SecKeyCreateRSAPrivateKey implementation -//#if 0 -// private_key = SecKeyCreateRSAPrivateKey(kCFAllocatorDefault, -// CFDataGetBytePtr(key_bytes), CFDataGetLength(key_bytes), -// kSecKeyEncodingPkcs1); -//#endif - if(!private_key) goto out; //require(private_key, out); - cert = SecCertificateCreateWithData(kCFAllocatorDefault, cert_bytes); - if(!cert) goto out; //require(cert, out); - identity = SecIdentityCreate(kCFAllocatorDefault, cert, private_key); - if(!identity) goto out; //require(identity, out); - CFDictionarySetValue(identity_dict, kSecImportItemIdentity, identity); - - eval_chain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - if(!eval_chain) goto out; //require(eval_chain, out); - CFArrayAppendValue(eval_chain, cert); - CFRange all_certs = { 0, CFArrayGetCount(a_build_trust_chains_context->certs) }; - CFArrayAppendArray(eval_chain, a_build_trust_chains_context->certs, all_certs); - policy = SecPolicyCreateBasicX509(); - if(!policy) goto out; //require(policy, out); - SecTrustResultType result; - SecTrustCreateWithCertificates(eval_chain, policy, &trust); - if(!trust) goto out; //require(trust, out); - SecTrustEvaluate(trust, &result); - CFDictionarySetValue(identity_dict, kSecImportItemTrust, trust); - - cert_chain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - if(!cert_chain) goto out; //require(cert_chain, out); - CFIndex cert_chain_length = SecTrustGetCertificateCount(trust); - int i; - for (i = 0; i < cert_chain_length; i++) - CFArrayAppendValue(cert_chain, SecTrustGetCertificateAtIndex(trust, i)); - CFDictionarySetValue(identity_dict, kSecImportItemCertChain, cert_chain); - - CFArrayAppendValue(a_build_trust_chains_context->identities, identity_dict); -out: - CFReleaseSafe(identity_dict); - CFReleaseSafe(identity); - CFReleaseSafe(private_key); - CFReleaseSafe(cert); - CFReleaseSafe(policy); - CFReleaseSafe(cert_chain); - CFReleaseSafe(eval_chain); - CFReleaseSafe(trust); -} -#endif // if 0 - -OSStatus SecPKCS12Import(CFDataRef pkcs12_data, CFDictionaryRef options, CFArrayRef *items) -{ - // SecPKCS12Import is implemented on Mac OS X in terms of the existing - // SecKeychainItemImport API, which supports importing items into a - // specified keychain with initial access control settings for keys. - // - OSStatus status = errSecSuccess; - SecExternalFormat inputFormat = kSecFormatPKCS12; - SecExternalItemType itemType = kSecItemTypeAggregate; - SecItemImportExportFlags flags = 0; /* don't know if it's PEM armoured */ - SecKeyImportExportParameters keyParams; /* filled in below... */ - SecKeychainRef importKeychain = NULL; - SecAccessRef importAccess = NULL; - CFStringRef importPassword = NULL; - CFArrayRef tmpItems = NULL; /* items returned by SecKeychainItemImport */ - CFMutableArrayRef certs = NULL; /* certificates imported by this function */ - CFMutableArrayRef identities = NULL; /* items returned by this function */ - - if (options) { - importKeychain = (SecKeychainRef) CFDictionaryGetValue(options, kSecImportExportKeychain); - if (importKeychain) - CFRetain(importKeychain); - importAccess = (SecAccessRef) CFDictionaryGetValue(options, kSecImportExportAccess); - if (importAccess) - CFRetain(importAccess); - importPassword = (CFStringRef) CFDictionaryGetValue(options, kSecImportExportPassphrase); - if (importPassword) - CFRetain(importPassword); - } - - if (!importKeychain) { - // SecKeychainItemImport requires a keychain, so use default - status = SecKeychainCopyDefault(&importKeychain); - } - - memset(&keyParams, 0, sizeof(SecKeyImportExportParameters)); - keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; - keyParams.passphrase = importPassword; - keyParams.accessRef = importAccess; - - status = SecKeychainItemImport(pkcs12_data, - NULL, /* no filename */ - &inputFormat, - &itemType, - flags, - &keyParams, - importKeychain, - &tmpItems); - - // build an array of all non-identity certificates which were imported - if (!status) { - certs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFIndex i, count = CFArrayGetCount(tmpItems); - for (i=0; iKeyData.Data, (CC_LONG)cssmKey->KeyData.Length, &hash[0]); - CFDataRef digest = CFDataCreate(NULL, (const UInt8 *)hash, CC_SHA1_DIGEST_LENGTH); - if (digest) { - CFDictionaryAddValue(itemDict, kSecImportItemKeyID, digest); - CFRelease(digest); - } - } - CFRelease(itemKey); - } - } - - // trust - SecTrustRef trust = NULL; - SecPolicyRef policy = SecPolicyCreateBasicX509(); - CFMutableArrayRef certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(certArray, itemCert); - if (certs) { - CFArrayAppendArray(certArray, certs, CFRangeMake(0, CFArrayGetCount(certs))); - } - status = SecTrustCreateWithCertificates(certArray, policy, &trust); - if (policy) { - CFRelease(policy); - } - if (trust) { - CFDictionaryAddValue(itemDict, kSecImportItemTrust, trust); - CFRelease(trust); - } - - // certificate chain - if (certArray) { - CFDictionaryAddValue(itemDict, kSecImportItemCertChain, certArray); - CFRelease(certArray); - } - - // identity - CFDictionaryAddValue(itemDict, kSecImportItemIdentity, anItem); - - if (itemCert) - CFRelease(itemCert); - CFArrayAppendValue(identities, itemDict); - CFRelease(itemDict); - } - } - } - - if (items) - *items = identities; - else if (identities) - CFRelease(identities); - - if (certs) - CFRelease(certs); - if (tmpItems) - CFRelease(tmpItems); - if (importKeychain) - CFRelease(importKeychain); - if (importAccess) - CFRelease(importAccess); - if (importPassword) - CFRelease(importPassword); - - return status; - -//FIXME: needs SecAsn1Coder implementation -#if 0 - pkcs12_context context = {}; - SecAsn1CoderCreate(&context.coder); - if (options) - context.passphrase = CFDictionaryGetValue(options, kSecImportExportPassphrase); - context.items = CFDictionaryCreateMutable(kCFAllocatorDefault, - 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - int status = p12decode(&context, pkcs12_data); - if (!status) { - CFMutableArrayRef certs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFDictionaryApplyFunction(context.items, collect_certs, certs); - - CFMutableArrayRef identities = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - build_trust_chains_context a_build_trust_chains_context = { identities, certs }; - CFDictionaryApplyFunction(context.items, build_trust_chains, &a_build_trust_chains_context); - CFReleaseSafe(certs); - - /* ignoring certs that weren't picked up as part of the certchain for found keys */ - - *items = identities; - } - - CFReleaseSafe(context.items); - SecAsn1CoderRelease(context.coder); - - switch (status) { - case p12_noErr: return errSecSuccess; - case p12_passwordErr: return errSecAuthFailed; - case p12_decodeErr: return errSecDecode; - default: return errSecInternal; - }; - return errSecSuccess; -#endif -} - diff --git a/libsecurity_keychain/lib/SecImportExport.h b/libsecurity_keychain/lib/SecImportExport.h deleted file mode 100644 index f32a88c8..00000000 --- a/libsecurity_keychain/lib/SecImportExport.h +++ /dev/null @@ -1,675 +0,0 @@ -/* - * Copyright (c) 2000-2010,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@ - */ - -/*! - @header SecImportExport - contains import/export functionality for keys and certificates. -*/ -#ifndef _SECURITY_SEC_IMPORT_EXPORT_H_ -#define _SECURITY_SEC_IMPORT_EXPORT_H_ - -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Supported import/export Formats - */ -enum -{ - /* - * When importing: unknown format - * When exporting: default format for item - */ - kSecFormatUnknown = 0, - - /* - * Public and Private Key formats. - * Default for export is kSecFormatOpenSSL. - */ - kSecFormatOpenSSL, /* a.k.a. X509 for public keys */ - kSecFormatSSH, /* OpenSSH v.1 */ - kSecFormatBSAFE, - - /* Symmetric Key Formats */ - kSecFormatRawKey, /* raw unformatted key bits; default */ - - /* Formats for wrapped symmetric and private keys */ - kSecFormatWrappedPKCS8, - kSecFormatWrappedOpenSSL, /* traditional openssl */ - kSecFormatWrappedSSH, /* OpenSSH v.1 */ - kSecFormatWrappedLSH, - - /* Formats for certificates */ - kSecFormatX509Cert, /* DER encoded; default */ - - /* Aggregate Types */ - kSecFormatPEMSequence, /* sequence of certs and/or keys, implies PEM - * armour. Default format for multiple items */ - kSecFormatPKCS7, /* sequence of certs */ - kSecFormatPKCS12, /* set of certs and private keys */ - kSecFormatNetscapeCertSequence, /* sequence of certs, form netscape-cert-sequence */ - - /* Added in Mac OS X 10.5 */ - kSecFormatSSHv2 /* OpenSSH v.2. Note that OpenSSH v2 private keys - * are in format kSecFormatOpenSSL or - * kSecFormatWrappedOpenSSL. */ -}; -typedef uint32_t SecExternalFormat; - -/* - * Indication of basic item type when importing. - */ -enum { - kSecItemTypeUnknown, /* caller doesn't know what this is */ - kSecItemTypePrivateKey, - kSecItemTypePublicKey, - kSecItemTypeSessionKey, - kSecItemTypeCertificate, - kSecItemTypeAggregate /* PKCS7, PKCS12, kSecFormatPEMSequence, etc. */ -}; -typedef uint32_t SecExternalItemType; - -/* - * Flags passed to SecKeychainItemExport() and SecKeychainItemImport(). - */ -enum -{ - kSecItemPemArmour = 0x00000001, /* exported blob is PEM formatted */ -}; -typedef uint32_t SecItemImportExportFlags; - -/* - * SecKeyRef-specific flags, specified in SecKeyImportExportParameters.flags - */ -enum -{ - /* - * When true, prevents the importing of more than one private key - * in a given SecKeychainItemImport(). - */ - kSecKeyImportOnlyOne = 0x00000001, - - /* - * When true, passphrase for import/export is obtained by user prompt - * instead of by caller-supplied data (SecKeyImportExportParameters.passphrase). - * This is the preferred method for obtaining a user-supplied passphrase - * as it avoids having the cleartext passphrase appear in the app's - * address space at any time. - */ - kSecKeySecurePassphrase = 0x00000002, - - /* - * When true, imported private keys will have no Access Control List - * (ACL) attached to them. In the absence of both this bit and the accessRef - * field in SecKeyImportExportParameters (see below), imported private - * keys are given a default ACL. - */ - kSecKeyNoAccessControl = 0x00000004 -}; -typedef uint32_t SecKeyImportExportFlags; - -/* - * Version of a SecKeyImportExportParameters. - */ -#define SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION 0 - -/* - * Parameters specific to SecKeyRefs. - */ -typedef struct -{ - /* for import and export */ - uint32_t version; /* SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION */ - SecKeyImportExportFlags flags; /* SecKeyImportExportFlags bits */ - CFTypeRef passphrase; /* kSecFormatPKCS12, kSecFormatWrapped* - * formats only. Legal types are - * CFStringRef and CFDataRef. */ - CFStringRef alertTitle; /* title of secure passphrase alert panel */ - CFStringRef alertPrompt; /* prompt in secure passphrase alert panel */ - - /* for import only */ - SecAccessRef accessRef; /* specifies the initial ACL of imported - * key(s) */ - CSSM_KEYUSE keyUsage; /* CSSM_KEYUSE_DECRYPT, CSSM_KEYUSE_SIGN, - * etc. */ - CSSM_KEYATTR_FLAGS keyAttributes; /* CSSM_KEYATTR_PERMANENT, etc. */ -} SecKeyImportExportParameters; - - -typedef struct -{ - /* for import and export */ - uint32_t version; /* SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION */ - SecKeyImportExportFlags flags; /* SecKeyImportExportFlags bits */ - CFTypeRef passphrase; /* kSecFormatPKCS12, kSecFormatWrapped* - * formats only. Legal types are - * CFStringRef and CFDataRef. */ - CFStringRef alertTitle; /* title of secure passphrase alert panel */ - CFStringRef alertPrompt; /* prompt in secure passphrase alert panel */ - - /* for import only */ - SecAccessRef accessRef; /* specifies the initial ACL of imported - * key(s) */ - CFArrayRef keyUsage; /* An Array containing usage attributes from SecItem.h, e.g. - kSecAttrCanEncrypt;, kSecAttrCanDecrypt, kSecAttrCanDerive, etc. - */ - - CFArrayRef keyAttributes; /* An array containing zero or more key attributes - for an imported key. Possible values (from SecItem.h): - kSecAttrIsPermanent, kSecAttrIsSensitive, kSecAttrIsExtractable - Pass NULL in this field to use default attributes: - - kSecAttrIsPermanent if a keychain is specified - - kSecAttrIsSensitive for private keys - - kSecAttrIsExtractable by default - */ -} SecItemImportExportKeyParameters; - -/* - * SecKeychainItemExport() - * - * This function takes one or more SecKeychainItemRefs and creates an - * external representation of the item(s) in the form of a CFDataRef. - * Caller specifies the format of the external representation via a - * SecExternalFormat enum. Caller may specify kSecFormatUnknown for - * the format, in which case a the default format for the item - * being exported is used (as described in the SecExternalFormat enums). - * PEM armouring is optional and is specified by the kSecItemPemArmour - * flag in importFlags. - * - * If exactly one item is to be exported, the keychainItemOrArray argument - * can be a SecKeychainItem. Otherwise this argument is a CFArrayRef - * containing a number of SecKeychainItems. - * - * The following SecKeychainItems may be exported: - * - * SecCertificateRef - * SecKeyRef - * SecIdentityRef - * - * - * Key-related SecKeyImportExportParameters fields - * ----------------------------------------------- - * - * When exporting SecKeyRefs in one of the wrapped formats - * (kSecFormatWrappedOpenSSL, kSecFormatWrappedSSH, - * kSecFormatWrappedPKCS8), or in PKCS12 format, caller must - * either explicitly specify the passphrase field or set - * the kSecKeySecurePassphrase bit in SecKeyImportExportFlags. - * - * If kSecKeySecurePassphrase is selected, caller can optionally - * specify strings for the passphrase panel's title bar and for - * the prompt which appears in the panel via the alertTitle and - * alertPrompt fields in SecKeyImportExportParameters. - * - * If an explicit passphrase is specified, note that PKCS12 - * explicitly requires that passphrases are in Unicode format; - * passing in a CFStringRef as the passphrase is the safest way - * to ensure that this requirement is met (and that the result - * will be compatible with other implementations). If a CFDataRef - * is supplied as the passphrase for a PKCS12 export operation, - * the referent data is assumed to be in UTF8 form and will be - * converted as appropriate. - * - * If no key items are being exported, the keyParams argument may be NULL. - * @discussion This API has been deprecated. Please us the SecItemExport API instead. - */ -OSStatus SecKeychainItemExport( - CFTypeRef keychainItemOrArray, - SecExternalFormat outputFormat, - SecItemImportExportFlags flags, /* kSecItemPemArmor, etc. */ - const SecKeyImportExportParameters *keyParams, /* optional */ - CFDataRef *exportedData) /* external representation returned here */ - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* - * SecItemExport() - * - * This function takes one or more SecItemRefs and creates an - * external representation of the item(s) in the form of a CFDataRef. - * Caller specifies the format of the external representation via a - * SecExternalFormat enum. Caller may specify kSecFormatUnknown for - * the format, in which case a the default format for the item - * being exported is used (as described in the SecExternalFormat enums). - * PEM armouring is optional and is specified by the kSecItemPemArmour - * flag in importFlags. - * - * If exactly one item is to be exported, the keychainItemOrArray argument - * can be a SecKeychainItem. Otherwise this argument is a CFArrayRef - * containing a number of SecKeychainItems. - * - * The following SecKeychainItems may be exported: - * - * SecCertificateRef - * SecKeyRef - * SecIdentityRef - * - * - * Key-related SecItemExport fields - * ----------------------------------------------- - * - * When exporting SecKeyRefs in one of the wrapped formats - * (kSecFormatWrappedOpenSSL, kSecFormatWrappedSSH, - * kSecFormatWrappedPKCS8), or in PKCS12 format, caller must - * either explicitly specify the passphrase field or set - * the kSecKeySecurePassphrase bit in SecKeyImportExportFlags. - * - * If kSecKeySecurePassphrase is selected, caller can optionally - * specify strings for the passphrase panel's title bar and for - * the prompt which appears in the panel via the alertTitle and - * alertPrompt fields in SecItemImportExportKeyParameters. - * - * If an explicit passphrase is specified, note that PKCS12 - * explicitly requires that passphrases are in Unicode format; - * passing in a CFStringRef as the passphrase is the safest way - * to ensure that this requirement is met (and that the result - * will be compatible with other implementations). If a CFDataRef - * is supplied as the passphrase for a PKCS12 export operation, - * the referent data is assumed to be in UTF8 form and will be - * converted as appropriate. - * - * If no key items are being exported, the keyParams argument may be NULL. - * - */ -OSStatus SecItemExport( - CFTypeRef secItemOrArray, - SecExternalFormat outputFormat, - SecItemImportExportFlags flags, /* kSecItemPemArmor, etc. */ - const SecItemImportExportKeyParameters *keyParams, /* optional */ - CFDataRef *exportedData) /* external representation returned here */ - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -/* - * SecKeychainItemImport() - * - * This function takes a CFDataRef containing the external representation - * of one or more objects and creates SecKeychainItems corresponding to - * those objects and optionally imports those SecKeychainItems into a - * specified keychain. The format of the incoming representation is - * specified by one or more of the following: - * - * -- A SecExternalFormat. This optional in/out argument is used when - * the caller knows exactly what format the external representation - * is in. It's also used to return to the caller the format which the - * function actually determines the external representation to be in. - * A value of kSecFormatUnknown is specified on entry when the caller - * wishes to know the inferred format on return. - * - * -- A SecExternalItemType - optional, in/out. Used to specify what kind - * of item is in the incoming representation, if known by the caller. - * It's also used to return to the caller the item type which the - * function actually determines the external representation to contain. - * A value of kSecItemTypeUnknown is specified on entry when the caller - * wishes to know the inferred item type on return. - * - * -- fileNameOrExtension, a CFStringRef. This optional argument contains - * the name of the file from which the external representation was - * obtained; it can also be simply an extension like CFSTR(".p7r"). - * This is a convenience for apps like KeychainAccess which can import a - * number of different formats. - * - * The SecKeychainItemImport() call does its best to figure out what is - * in an incoming external item given the info provided by the above three - * arguments. In most cases, SecKeychainItemImport() can even figure out - * what's in an external item if none of these are specified, but it would - * be unwise for an application to count on that ability. - * - * PEM formatting is determined internally via inspection of the incoming - * data, so the kSecItemPemArmuor in the flags field is ignored. - * - * Zero, one, or both of the following occurs upon successful completion - * of this function: - * - * -- The imported item(s) is (are) imported to the specified importKeychain. - * If importKeychain is NULL, this step does not occur. - * - * -- The imported item(s) is (are) returned to the caller via the - * CRArrayRef *outItems argument. If outItems is NULL, this step - * does not occur. If outItems is NON-NULL, then *outItems will be - * a CFArrayRef containing a number of SecKeychainItems upon return. - * Caller must CFRelease the result. - * - * The possible types of returned SecKeychainItems are: - * - * SecCertificateRef - * SecKeyRef - * SecIdentityRef - * - * Note that when importing a PKCS12 blob, typically one SecIdentityRef - * and zero or more additional SecCertificateRefs are returned in - * outItems. No SecKeyRefs will appear there unless a key - * is found in the incoming blob with does not have a matching - * certificate. - * - * A typical case in which an app specifies the outItems - * argument and a NULL for importKeychain is when the app wishes to - * perform some user interaction, perhaps on a per-item basis, before - * committing to actually import the item(s). In this case, if the app - * does wish to proceed with the import, the standard import calls - * (SecCertificateAddToKeychain(), SecKeyAddToKeychain (implementation - * TBD)) would be used. - * - * Passing in NULL for both outItems and importKeychain - * is a perfectly acceptable way of using this function to determine, - * in a non-intrusive way, what is inside a given data blob. No effect - * other than returning inputFormat and/or itemType occurs in this - * case. - - * - * Key-related SecKeyImportExportParameters fields - * ----------------------------------------------- - * - * If importKeychain is NULL, the kSecKeyImportOnlyOne bit in the flags - * argument is ignored. Otherwise, if the kSecKeyImportOnlyOne bit is set, and - * there is more than one key in the incoming external representation, no - * items will be imported to the specified keychain and errSecMultipleKeys will - * be returned. - * - * The accessRef field allows the caller to specify the initial SecAccessRef - * for imported private keys. If more than one private key is being imported, - * all private keys get the same initial SecAccessRef. If this field is NULL - * when private keys are being imported, then the ACL attached to imported - * private keys depends on the kSecKeyNoAccessControl bit in the specified - * keyParams->flags. If this bit is 0, or keyParams is NULL, the default ACL - * will be used. If this bit is 1, no ACL will be attached to imported - * private keys. - * - * keyUsage and keyAttributes specify the low-level usage and attribute flags - * of imported keys. Each is a word of bits. The default value for keyUsage - * (used when keyParams is NULL or if keyParams->keyUsage is zero) is - * CSSM_KEYUSE_ANY. The default value for keyAttributes defaults is - * CSSM_KEYATTR_SENSITIVE | CSSM_KEYATTR_EXTRACTABLE; the CSSM_KEYATTR_PERMANENT - * bit is also added to the default if a non-NULL importKeychain is provided. - * - * The following are valid bits in keyAttributes: - * - * CSSM_KEYATTR_PERMANENT - * CSSM_KEYATTR_SENSITIVE - * CSSM_KEYATTR_EXTRACTABLE - * - * If the CSSM_KEYATTR_PERMANENT is set then the importKeychain argument must - * be valid or errSecInvalidKeychain will be returned if in fact any keys are found - * in the external representation. - * - * Note that if the caller does not set the CSSM_KEYATTR_EXTRACTABLE, this key - * will never be able to be extracted from the keychain in any form, not even - * in wrapped form. The CSSM_KEYATTR_SENSITIVE indicates that the key can only - * be extracted in wrapped form. - * - * The CSSM_KEYATTR_RETURN_xxx bits are always forced to - * CSSM_KEYATTR_RETURN_REF regardless of the specified keyAttributes - * field. - * - * When importing SecKeyRefs in one of the wrapped formats - * (kSecFormatWrappedOpenSSL, kSecFormatWrappedSSH, - * kSecFormatWrappedPKCS8), or in PKCS12 format, caller must - * either explicitly specify the passphrase field or set - * the kSecKeySecurePassphrase bit in SecKeyImportExportFlags. - * - * If kSecKeySecurePassphrase is selected, caller can optionally - * specify strings for the passphrase panel's title bar and for - * the prompt which appears in the panel via the alertTitle and - * alertPrompt fields in SecKeyImportExportParameters. - * - * If an explicit passphrase is specified, note that PKCS12 - * explicitly requires that passphrases are in Unicode format; - * passing in a CFStringRef as the passphrase is the safest way - * to ensure that this requirement is met (and that the result - * will be compatible with other implementations). If a CFDataRef - * is supplied as the passphrase for a PKCS12 export operation, - * the referent data is assumed to be in UTF8 form and will be - * converted as appropriate. - - * If no key items are being imported, the keyParams argument may be NULL. - * - * The SecItemImportExportFlags argument is currently unused; caller should pass - * in 0. - * - * @discussion This API has been deprecated. Please use the SecItemImport API instead. - */ -OSStatus SecKeychainItemImport( - CFDataRef importedData, - CFStringRef fileNameOrExtension, /* optional */ - SecExternalFormat *inputFormat, /* optional, IN/OUT */ - SecExternalItemType *itemType, /* optional, IN/OUT */ - SecItemImportExportFlags flags, - const SecKeyImportExportParameters *keyParams, /* optional */ - SecKeychainRef importKeychain, /* optional */ - CFArrayRef *outItems) /* optional */ - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/* - * SecItemImport() - * - * This function takes a CFDataRef containing the external representation - * of one or more objects and creates SecKeychainItems corresponding to - * those objects and optionally imports those SecKeychainItems into a - * specified keychain. The format of the incoming representation is - * specified by one or more of the following: - * - * -- A SecExternalFormat. This optional in/out argument is used when - * the caller knows exactly what format the external representation - * is in. It's also used to return to the caller the format which the - * function actually determines the external representation to be in. - * A value of kSecFormatUnknown is specified on entry when the caller - * wishes to know the inferred format on return. - * - * -- A SecExternalItemType - optional, in/out. Used to specify what kind - * of item is in the incoming representation, if known by the caller. - * It's also used to return to the caller the item type which the - * function actually determines the external representation to contain. - * A value of kSecItemTypeUnknown is specified on entry when the caller - * wishes to know the inferred item type on return. - * - * -- fileNameOrExtension, a CFStringRef. This optional argument contains - * the name of the file from which the external representation was - * obtained; it can also be simply an extension like CFSTR(".p7r"). - * This is a convenience for apps like KeychainAccess which can import a - * number of different formats. - * - * The SecItemImport() call does its best to figure out what is - * in an incoming external item given the info provided by the above three - * arguments. In most cases, SecItemImport() can even figure out - * what's in an external item if none of these are specified, but it would - * be unwise for an application to count on that ability. - * - * PEM formatting is determined internally via inspection of the incoming - * data, so the kSecItemPemArmuor in the flags field is ignored. - * - * Zero, one, or both of the following occurs upon successful completion - * of this function: - * - * -- The imported item(s) is (are) imported to the specified importKeychain. - * If importKeychain is NULL, this step does not occur. - * - * -- The imported item(s) is (are) returned to the caller via the - * CRArrayRef *outItems argument. If outItems is NULL, this step - * does not occur. If outItems is NON-NULL, then *outItems will be - * a CFArrayRef containing a number of SecKeychainItems upon return. - * Caller must CFRelease the result. - * - * The possible types of returned SecKeychainItems are: - * - * SecCertificateRef - * SecKeyRef - * SecIdentityRef - * - * Note that when importing a PKCS12 blob, typically one SecIdentityRef - * and zero or more additional SecCertificateRefs are returned in - * outItems. No SecKeyRefs will appear there unless a key - * is found in the incoming blob with does not have a matching - * certificate. - * - * A typical case in which an app specifies the outItems - * argument and a NULL for importKeychain is when the app wishes to - * perform some user interaction, perhaps on a per-item basis, before - * committing to actually import the item(s). In this case, if the app - * does wish to proceed with the import, the standard import calls - * (SecCertificateAddToKeychain(), SecKeyAddToKeychain (implementation - * TBD)) would be used. - * - * Passing in NULL for both outItems and importKeychain - * is a perfectly acceptable way of using this function to determine, - * in a non-intrusive way, what is inside a given data blob. No effect - * other than returning inputFormat and/or itemType occurs in this - * case. - - * - * Key-related SecItemImportExportKeyParameters fields - * ----------------------------------------------- - * - * If importKeychain is NULL, the kSecKeyImportOnlyOne bit in the flags - * argument is ignored. Otherwise, if the kSecKeyImportOnlyOne bit is set, and - * there is more than one key in the incoming external representation, no - * items will be imported to the specified keychain and errSecMultipleKeys will - * be returned. - * - * The accessRef field allows the caller to specify the initial SecAccessRef - * for imported private keys. If more than one private key is being imported, - * all private keys get the same initial SecAccessRef. If this field is NULL - * when private keys are being imported, then the ACL attached to imported - * private keys depends on the kSecKeyNoAccessControl bit in the specified - * keyParams->flags. If this bit is 0, or keyParams is NULL, the default ACL - * will be used. If this bit is 1, no ACL will be attached to imported - * private keys. - * - * keyUsage and keyAttributes specify the low-level usage and attribute flags - * of imported keys. These fields contain a CFArray whose values are constants - * from SecItem.h. - * - * Possible values in the keyUsage array: - * - * kSecAttrCanEncrypt - * kSecAttrCanDecrypt - * kSecAttrCanDerive - * kSecAttrCanSign - * kSecAttrCanVerify - * kSecAttrCanWrap - * kSecAttrCanUnwrap - * - * If keyUsage is set to NULL, then any key usage is permitted. - * - * Possible values in the keyAttributes array: - * - * kSecAttrIsPermanent - * kSecAttrIsSensitive - * kSecAttrIsExtractable - * - * If keyAttributes is set to NULL, then default values are used: - * kSecAttrIsPermanent if an import keychain is specified - * kSecAttrIsSensitive for non-public keys - * kSecAttrIsExtractable - * - * If the kSecAttrIsPermanent attribute is set, then the - * importKeychain argument must be valid or errSecInvalidKeychain - * will be returned even if keys were able to be imported. - * - * Note that if the caller provides a keyAttributes array but - * does not set kSecAttrIsExtractable, this key will never be - * able to be extracted from the keychain in any form, not even - * in wrapped form. kSecAttrIsSensitive indicates that the key - * can only be extracted in wrapped form. - * - * When importing SecKeyRefs in one of the wrapped formats - * (kSecFormatWrappedOpenSSL, kSecFormatWrappedSSH, - * kSecFormatWrappedPKCS8), or in PKCS12 format, caller must - * either explicitly specify the passphrase field or set - * the kSecKeySecurePassphrase bit in SecKeyImportExportFlags. - * - * If kSecKeySecurePassphrase is selected, caller can optionally - * specify strings for the passphrase panel's title bar and for - * the prompt which appears in the panel via the alertTitle and - * alertPrompt fields in SecItemImportExportKeyParameters. - * - * If an explicit passphrase is specified, note that PKCS12 - * explicitly requires that passphrases are in Unicode format; - * passing in a CFStringRef as the passphrase is the safest way - * to ensure that this requirement is met (and that the result - * will be compatible with other implementations). If a CFDataRef - * is supplied as the passphrase for a PKCS12 export operation, - * the referent data is assumed to be in UTF8 form and will be - * converted as appropriate. - - * If no key items are being imported, the keyParams argument may be NULL. - * - * The SecItemImportExportFlags argument is currently unused; caller should pass - * in 0. - */ - -OSStatus SecItemImport( - CFDataRef importedData, - CFStringRef fileNameOrExtension, /* optional */ - SecExternalFormat *inputFormat, /* optional, IN/OUT */ - SecExternalItemType *itemType, /* optional, IN/OUT */ - SecItemImportExportFlags flags, - const SecItemImportExportKeyParameters *keyParams, /* optional */ - SecKeychainRef importKeychain, /* optional */ - CFArrayRef *outItems) /* optional */ - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -/*! - @enum Import/Export options - @discussion Predefined key constants used when passing dictionary-based arguments to import/export functions. - @constant kSecImportExportPassphrase Specifies a passphrase represented by a CFStringRef to be used when exporting to (or importing from) PKCS#12 format. - @constant kSecImportExportKeychain Specifies a keychain represented by a SecKeychainRef to be used as the target when importing from PKCS#12 format. - @constant kSecImportExportAccess Specifies an access represented by a SecAccessRef for the initial access (ACL) of a key imported from PKCS#12 format. -*/ -extern CFStringRef kSecImportExportPassphrase; -extern CFStringRef kSecImportExportKeychain; -extern CFStringRef kSecImportExportAccess; - -/*! - @enum Import/Export item description - @discussion Predefined key constants used by functions which return a CFArray with a CFDictionary per item. - @constant kSecImportItemLabel A CFStringRef representing the item label. This implementation specific identifier cannot be expected to have any format. - @constant kSecImportItemKeyID A CFDataRef representing the key id. Typically this is the SHA-1 digest of the public key. - @constant kSecImportItemIdentity A SecIdentityRef representing the identity. - @constant kSecImportItemTrust A SecTrustRef set up with all relevant certificates. Not guaranteed to succesfully evaluate. - @constant kSecImportItemCertChain A CFArrayRef holding all relevant certificates for this item's identity. -*/ -extern CFStringRef kSecImportItemLabel; -extern CFStringRef kSecImportItemKeyID; -extern CFStringRef kSecImportItemTrust; -extern CFStringRef kSecImportItemCertChain; -extern CFStringRef kSecImportItemIdentity; - -/*! - @function SecPKCS12Import - @abstract Imports the contents of a PKCS12 formatted blob. - @param pkcs12_data The PKCS12 data to be imported. - @param options A dictionary containing import options. A kSecImportExportPassphrase entry is required at minimum. Only password-based PKCS12 blobs are currently supported. - @param items On return, an array containing a dictionary for every item extracted. Use kSecImportItem constants to access specific elements of these dictionaries. Your code must CFRelease the array when it is no longer needed. - @result errSecSuccess in case of success. errSecDecode means either the blob can't be read or it is malformed. - errSecAuthFailed means an incorrect password was supplied, or data in the container is damaged. -*/ -OSStatus SecPKCS12Import(CFDataRef pkcs12_data, CFDictionaryRef options, CFArrayRef *items); - -#ifdef __cplusplus -} -#endif - -#endif /* _SECURITY_SEC_IMPORT_EXPORT_H_ */ diff --git a/libsecurity_keychain/lib/SecInternal.h b/libsecurity_keychain/lib/SecInternal.h deleted file mode 100644 index 0d315de7..00000000 --- a/libsecurity_keychain/lib/SecInternal.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2007-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@ - */ - -/*! - @header SecInternal - SecInternal defines common internal constants macros and SPI functions. -*/ - -#ifndef _SECURITY_SECINTERNAL_H_ -#define _SECURITY_SECINTERNAL_H_ - -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -#define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) CFRelease(_cf); } -#define CFReleaseNull(CF) { CFTypeRef _cf = (CF); \ - if (_cf) { (CF) = NULL; CFRelease(_cf); } } - -#define AssignOrReleaseResult(CF,OUT) { \ - CFTypeRef _cf = (CF), *_out = (OUT); \ - if (_out) { *_out = _cf; } else { if (_cf) CFRelease(_cf); } } - -#define DICT_DECLARE(MAXVALUES) \ - CFIndex numValues = 0, maxValues = (MAXVALUES); \ - const void *keys[maxValues]; \ - const void *values[maxValues]; - -#define DICT_ADDPAIR(KEY,VALUE) do { \ - if (numValues < maxValues) { \ - keys[numValues] = (KEY); \ - values[numValues] = (VALUE); \ - numValues++; \ - } else \ - assert(false); \ -} while(0) - -#define DICT_CREATE(ALLOCATOR) CFDictionaryCreate((ALLOCATOR), keys, values, \ - numValues, NULL, &kCFTypeDictionaryValueCallBacks) - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECINTERNAL_H_ */ diff --git a/libsecurity_keychain/lib/SecItem.h b/libsecurity_keychain/lib/SecItem.h deleted file mode 100644 index b07aba9e..00000000 --- a/libsecurity_keychain/lib/SecItem.h +++ /dev/null @@ -1,1093 +0,0 @@ -/* - * Copyright (c) 2006-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@ - */ - -/*! - @header SecItem - SecItem defines CoreFoundation-based constants and functions for - access to Security items (certificates, keys, identities, and - passwords.) -*/ - -#ifndef _SECURITY_SECITEM_H_ -#define _SECURITY_SECITEM_H_ - -#include -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -/*! - @enum Class Key Constant - @discussion Predefined key constant used to get or set item class values in - a dictionary. Its value is one of the constants defined in the Value - Constants for kSecClass. - @constant kSecClass Specifies a dictionary key whose value is the item's - class code. You use this key to get or set a value of type CFTypeRef - that contains the item class code. -*/ -extern const CFTypeRef kSecClass - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @enum Class Value Constants - @discussion Predefined item class constants used to get or set values in - a dictionary. The kSecClass constant is the key and its value is one - of the constants defined here. Note: on Mac OS X 10.6, only items - of class kSecClassInternetPassword are supported. - @constant kSecClassInternetPassword Specifies Internet password items. - @constant kSecClassGenericPassword Specifies generic password items. - @constant kSecClassCertificate Specifies certificate items. - @constant kSecClassKey Specifies key items. - @constant kSecClassIdentity Specifies identity items. -*/ -extern const CFTypeRef kSecClassInternetPassword - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecClassGenericPassword - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); -extern const CFTypeRef kSecClassCertificate - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); -extern const CFTypeRef kSecClassKey - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); -extern const CFTypeRef kSecClassIdentity - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - -/*! - @enum Attribute Key Constants - @discussion Predefined item attribute keys used to get or set values in a - dictionary. Not all attributes apply to each item class. The table - below lists the currently defined attributes for each item class: - - kSecClassGenericPassword item attributes: - kSecAttrAccess (OS X only) - kSecAttrAccessGroup (iOS; also OS X if kSecAttrSynchronizable specified) - kSecAttrAccessible (iOS; also OS X if kSecAttrSynchronizable specified) - kSecAttrCreationDate - kSecAttrModificationDate - kSecAttrDescription - kSecAttrComment - kSecAttrCreator - kSecAttrType - kSecAttrLabel - kSecAttrIsInvisible - kSecAttrIsNegative - kSecAttrAccount - kSecAttrService - kSecAttrGeneric - - kSecClassInternetPassword item attributes: - kSecAttrAccess (OS X only) - kSecAttrAccessGroup (iOS; also OS X if kSecAttrSynchronizable specified) - kSecAttrAccessible (iOS; also OS X if kSecAttrSynchronizable specified) - kSecAttrCreationDate - kSecAttrModificationDate - kSecAttrDescription - kSecAttrComment - kSecAttrCreator - kSecAttrType - kSecAttrLabel - kSecAttrIsInvisible - kSecAttrIsNegative - kSecAttrAccount - kSecAttrSecurityDomain - kSecAttrServer - kSecAttrProtocol - kSecAttrAuthenticationType - kSecAttrPort - kSecAttrPath - - kSecClassCertificate item attributes: - kSecAttrCertificateType - kSecAttrCertificateEncoding - kSecAttrLabel - kSecAttrSubject - kSecAttrIssuer - kSecAttrSerialNumber - kSecAttrSubjectKeyID - kSecAttrPublicKeyHash - - kSecClassKey item attributes: - kSecAttrAccess (OS X only) - kSecAttrAccessGroup (iOS only) - kSecAttrAccessible (iOS only) - kSecAttrKeyClass - kSecAttrLabel - kSecAttrApplicationLabel - kSecAttrIsPermanent - kSecAttrApplicationTag - kSecAttrKeyType - kSecAttrPRF - kSecAttrSalt - kSecAttrRounds - kSecAttrKeySizeInBits - kSecAttrEffectiveKeySize - kSecAttrCanEncrypt - kSecAttrCanDecrypt - kSecAttrCanDerive - kSecAttrCanSign - kSecAttrCanVerify - kSecAttrCanWrap - kSecAttrCanUnwrap - - Note that the attributes kSecAttrCan* describe attributes of the - key itself at relatively high level. Some of these attributes are - mathematical -- for example, a DSA key cannot encrypt. Others are - key-level policy issues -- for example, it is good cryptographic - hygiene to use an RSA key either for encryption or signing but not - both. Compare these to the certificate-level policy values in - SecPolicy.h. - - kSecClassIdentity item attributes: - Since an identity is the combination of a private key and a - certificate, this class shares attributes of both kSecClassKey and - kSecClassCertificate. - - @constant kSecAttrAccessible Specifies a dictionary key whose value - indicates when your application needs access to an item's data. You - should choose the most restrictive option that meets your application's - needs to allow the system to protect that item in the best way possible. - See the "kSecAttrAccessible Value Constants" section for a list of - values which can be specified. - IMPORTANT: This attribute is currently not supported for OS X keychain - items, unless the kSecAttrSynchronizable attribute is also present. If - both attributes are specified on either OS X or iOS, the value for the - kSecAttrAccessible key may only be one whose name does not end with - "ThisDeviceOnly", as those cannot sync to another device. - - @constant kSecAttrAccess Specifies a dictionary key whose value - is a SecAccessRef describing the access control settings for this item. - This key is available on OS X only. - - @constant kSecAttrAccessGroup Specifies a dictionary key whose value is - a CFStringRef indicating which access group a item is in. The access - groups that a particular application has membership in are determined by - two entitlements for that application. The application-identifier - entitlement contains the application's single access group, unless - there is a keychain-access-groups entitlement present. The latter - has as its value a list of access groups; the first item in this list - is the default access group. Unless a specific access group is provided - as the value of kSecAttrAccessGroup when SecItemAdd is called, new items - are created in the application's default access group. Specifying this - attribute in SecItemCopyMatching, SecItemUpdate, or SecItemDelete calls - limits the search to the specified access group (of which the calling - application must be a member to obtain matching results.) To share - keychain items between multiple applications, each application must have - a common group listed in its keychain-access-groups entitlement, and each - must specify this shared access group name as the value for the - kSecAttrAccessGroup key in the dictionary passed to SecItem functions. - - @constant kSecAttrSynchronizable Specifies a dictionary key whose value is - a CFBooleanRef indicating whether the item in question can be synchronized. - To add a new item which can be synced to other devices, or to obtain - synchronizable results from a query, supply this key with a value of - kCFBooleanTrue. If the key is not supplied, or has a value of - kCFBooleanFalse, then no synchronizable items will be added or returned. - A predefined value, kSecAttrSynchronizableAny, may be provided instead of - kCFBooleanTrue if both synchronizable and non-synchronizable results are - desired. - - IMPORTANT: Specifying the kSecAttrSynchronizable key has several caveats: - - - Updating or deleting items using the kSecAttrSynchronizable key will - affect all copies of the item, not just the one on your local device. - Be sure that it makes sense to use the same password on all devices - before deciding to make a password synchronizable. - - Only password items can currently be synchronized. Keychain syncing - is not supported for certificates or cryptographic keys. - - Items stored or obtained using the kSecAttrSynchronizable key cannot - specify SecAccessRef-based access control with kSecAttrAccess. If a - password is intended to be shared between multiple applications, the - kSecAttrAccessGroup key must be specified, and each application - using this password must have a 'keychain-access-groups' entitlement - with the specified access group value. - - Items stored or obtained using the kSecAttrSynchronizable key may - not also specify a kSecAttrAccessible value which is incompatible - with syncing (namely, those whose names end with "ThisDeviceOnly".) - - Items stored or obtained using the kSecAttrSynchronizable key cannot - be specified by reference. You must pass kSecReturnAttributes and/or - kSecReturnData to retrieve results; kSecReturnRef is currently not - supported for synchronizable items. - - Persistent references to synchronizable items should be avoided; - while they may work locally, they cannot be moved between devices, - and may not resolve if the item is modified on some other device. - - When specifying a query that uses the kSecAttrSynchronizable key, - search keys are limited to the item's class and attributes. - The only search constant which may be used is kSecMatchLimit; other - constants using the kSecMatch prefix are not supported at this time. - - @constant kSecAttrSynchronizableAny Specifies that both synchronizable and - non-synchronizable results should be returned from this query. This may be - used as a value for the kSecAttrSynchronizable dictionary key in a call to - SecItemCopyMatching, SecItemUpdate, or SecItemDelete. - - @constant kSecAttrCreationDate (read-only) Specifies a dictionary key whose - value is the item's creation date. You use this key to get a value - of type CFDateRef that represents the date the item was created. - @constant kSecAttrModificationDate (read-only) Specifies a dictionary key - whose value is the item's modification date. You use this key to get - a value of type CFDateRef that represents the last time the item was - updated. - @constant kSecAttrDescription Specifies a dictionary key whose value is - the item's description attribute. You use this key to set or get a - value of type CFStringRef that represents a user-visible string - describing this particular kind of item (e.g., "disk image password"). - @constant kSecAttrComment Specifies a dictionary key whose value is the - item's comment attribute. You use this key to set or get a value of - type CFStringRef containing the user-editable comment for this item. - @constant kSecAttrCreator Specifies a dictionary key whose value is the - item's creator attribute. You use this key to set or get a value of - type CFNumberRef that represents the item's creator. This number is - the unsigned integer representation of a four-character code (e.g., - 'aCrt'). - @constant kSecAttrType Specifies a dictionary key whose value is the item's - type attribute. You use this key to set or get a value of type - CFNumberRef that represents the item's type. This number is the - unsigned integer representation of a four-character code (e.g., - 'aTyp'). - @constant kSecAttrLabel Specifies a dictionary key whose value is the - item's label attribute. You use this key to set or get a value of - type CFStringRef containing the user-visible label for this item. - @constant kSecAttrIsInvisible Specifies a dictionary key whose value is the - item's invisible attribute. You use this key to set or get a value - of type CFBooleanRef that indicates whether the item is invisible - (i.e., should not be displayed.) - @constant kSecAttrIsNegative Specifies a dictionary key whose value is the - item's negative attribute. You use this key to set or get a value of - type CFBooleanRef that indicates whether there is a valid password - associated with this keychain item. This is useful if your application - doesn't want a password for some particular service to be stored in - the keychain, but prefers that it always be entered by the user. - @constant kSecAttrAccount Specifies a dictionary key whose value is the - item's account attribute. You use this key to set or get a CFStringRef - that contains an account name. (Items of class - kSecClassGenericPassword, kSecClassInternetPassword have this - attribute.) - @constant kSecAttrService Specifies a dictionary key whose value is the - item's service attribute. You use this key to set or get a CFStringRef - that represents the service associated with this item. (Items of class - kSecClassGenericPassword have this attribute.) - @constant kSecAttrGeneric Specifies a dictionary key whose value is the - item's generic attribute. You use this key to set or get a value of - CFDataRef that contains a user-defined attribute. (Items of class - kSecClassGenericPassword have this attribute.) - @constant kSecAttrSecurityDomain Specifies a dictionary key whose value - is the item's security domain attribute. You use this key to set or - get a CFStringRef value that represents the Internet security domain. - (Items of class kSecClassInternetPassword have this attribute.) - @constant kSecAttrServer Specifies a dictionary key whose value is the - item's server attribute. You use this key to set or get a value of - type CFStringRef that contains the server's domain name or IP address. - (Items of class kSecClassInternetPassword have this attribute.) - @constant kSecAttrProtocol Specifies a dictionary key whose value is the - item's protocol attribute. You use this key to set or get a value of - type CFNumberRef that denotes the protocol for this item (see the - SecProtocolType enum in SecKeychainItem.h). (Items of class - kSecClassInternetPassword have this attribute.) - @constant kSecAttrAuthenticationType Specifies a dictionary key whose value - is the item's authentication type attribute. You use this key to set - or get a value of type CFNumberRef that denotes the authentication - scheme for this item (see the kSecAttrAuthenticationType value - constants below). - @constant kSecAttrPort Specifies a dictionary key whose value is the item's - port attribute. You use this key to set or get a CFNumberRef value - that represents an Internet port number. (Items of class - kSecClassInternetPassword have this attribute.) - @constant kSecAttrPath Specifies a dictionary key whose value is the item's - path attribute, typically this is the path component of the URL. You use - this key to set or get a CFStringRef value that represents a path. (Items - of class kSecClassInternetPassword have this attribute.) - @constant kSecAttrSubject (read-only) Specifies a dictionary key whose - value is the item's subject. You use this key to get a value of type - CFDataRef that contains the X.500 subject name of a certificate. - (Items of class kSecClassCertificate have this attribute.) - @constant kSecAttrIssuer (read-only) Specifies a dictionary key whose value - is the item's issuer. You use this key to get a value of type - CFDataRef that contains the X.500 issuer name of a certificate. (Items - of class kSecClassCertificate have this attribute.) - @constant kSecAttrSerialNumber (read-only) Specifies a dictionary key whose - value is the item's serial number. You use this key to get a value - of type CFDataRef that contains the serial number data of a - certificate. (Items of class kSecClassCertificate have this - attribute.) - @constant kSecAttrSubjectKeyID (read-only) Specifies a dictionary key whose - value is the item's subject key ID. You use this key to get a value - of type CFDataRef that contains the subject key ID of a certificate. - (Items of class kSecClassCertificate have this attribute.) - @constant kSecAttrPublicKeyHash (read-only) Specifies a dictionary key - whose value is the item's public key hash. You use this key to get a - value of type CFDataRef that contains the hash of a certificate's - public key. (Items of class kSecClassCertificate have this attribute.) - @constant kSecAttrCertificateType (read-only) Specifies a dictionary key - whose value is the item's certificate type. You use this key to get - a value of type CFNumberRef that denotes the certificate type (see the - CSSM_CERT_TYPE enum in cssmtype.h). (Items of class - kSecClassCertificate have this attribute.) - @constant kSecAttrCertificateEncoding (read-only) Specifies a dictionary - key whose value is the item's certificate encoding. You use this key - to get a value of type CFNumberRef that denotes the certificate - encoding (see the CSSM_CERT_ENCODING enum in cssmtype.h). (Items of - class kSecClassCertificate have this attribute.) - @constant kSecAttrKeyClass (read only) Specifies a dictionary key whose - value is one of kSecAttrKeyClassPublic, kSecAttrKeyClassPrivate or - kSecAttrKeyClassSymmetric. - @constant kSecAttrApplicationLabel Specifies a dictionary key whose value - is the key's application label attribute. This is different from the - kSecAttrLabel (which is intended to be human-readable). This attribute - is used to look up a key programmatically; in particular, for keys of - class kSecAttrKeyClassPublic and kSecAttrKeyClassPrivate, the value of - this attribute is the hash of the public key. This item is a type of CFDataRef. - Legacy keys may contain a UUID in this field as a CFStringRef. - @constant kSecAttrIsPermanent Specifies a dictionary key whose value is a - CFBooleanRef indicating whether the key in question will be stored - permanently. - @constant kSecAttrIsSensitive Specifies a dictionary key whose value is a - CFBooleanRef indicating that the key in question can only be exported - in a wrapped (encrypted) format. - @constant kSecAttrIsExtractable Specifies a dictionary key whose value is a - CFBooleanRef indicating whether the key in question can be exported from - its keychain container. - @constant kSecAttrApplicationTag Specifies a dictionary key whose value is a - CFDataRef containing private tag data. - @constant kSecAttrKeyType Specifies a dictionary key whose value is a - CFNumberRef indicating the algorithm associated with this key (see the - CSSM_ALGORITHMS enum in cssmtype.h). - @constant kSecAttrPRF Specifies a dictionary key whose value is the PRF - (pseudo-random function) for this key (see "kSecAttrPRF Value Constants".) - @constant kSecAttrSalt Specifies a dictionary key whose value is a - CFData containing the salt to use for this key. - @constant kSecAttrRounds Specifies a dictionary key whose value is the - number of rounds for the pseudo-random function specified by kSecAttrPRF. - @constant kSecAttrKeySizeInBits Specifies a dictionary key whose value - is a CFNumberRef indicating the number of bits in this key. - @constant kSecAttrEffectiveKeySize Specifies a dictionary key whose value - is a CFNumberRef indicating the effective number of bits in this key. - For example, a DES key has a kSecAttrKeySizeInBits of 64, but a - kSecAttrEffectiveKeySize of 56 bits. - @constant kSecAttrCanEncrypt Specifies a dictionary key whole value is a - CFBooleanRef indicating whether the key in question can be used to - encrypt data. - @constant kSecAttrCanDecrypt Specifies a dictionary key whole value is a - CFBooleanRef indicating whether the key in question can be used to - decrypt data. - @constant kSecAttrCanDerive Specifies a dictionary key whole value is a - CFBooleanRef indicating whether the key in question can be used to - derive another key. - @constant kSecAttrCanSign Specifies a dictionary key whole value is a - CFBooleanRef indicating whether the key in question can be used to - create a digital signature. - @constant kSecAttrCanVerify Specifies a dictionary key whole value is a - CFBooleanRef indicating whether the key in question can be used to - verify a digital signature. - @constant kSecAttrCanWrap Specifies a dictionary key whole value is a - CFBooleanRef indicating whether the key in question can be used to - wrap another key. - @constant kSecAttrCanUnwrap Specifies a dictionary key whole value is a - CFBooleanRef indicating whether the key in question can be used to - unwrap another key. -*/ -extern const CFTypeRef kSecAttrAccessible - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); -extern const CFTypeRef kSecAttrAccess - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecAttrAccessGroup - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_3_0); -extern const CFTypeRef kSecAttrSynchronizable - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern const CFTypeRef kSecAttrSynchronizableAny - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern const CFTypeRef kSecAttrCreationDate - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrModificationDate - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrDescription - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrComment - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrCreator - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrType - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrLabel - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrIsInvisible - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrIsNegative - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrAccount - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrService - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrGeneric - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrSecurityDomain - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrServer - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocol - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrAuthenticationType - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrPort - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrPath - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrSubject - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrIssuer - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrSerialNumber - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrSubjectKeyID - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrPublicKeyHash - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrCertificateType - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrCertificateEncoding - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrKeyClass - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrApplicationLabel - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrIsPermanent - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrIsSensitive - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrIsExtractable - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrApplicationTag - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrKeyType - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrPRF - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecAttrSalt - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecAttrRounds - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecAttrKeySizeInBits - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrEffectiveKeySize - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrCanEncrypt - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrCanDecrypt - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrCanDerive - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrCanSign - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrCanVerify - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrCanWrap - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrCanUnwrap - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @enum kSecAttrAccessible Value Constants - @discussion Predefined item attribute constants used to get or set values - in a dictionary. The kSecAttrAccessible constant is the key and its - value is one of the constants defined here. - When asking SecItemCopyMatching to return the item's data, the error - errSecInteractionNotAllowed will be returned if the item's data is not - available until a device unlock occurs. - @constant kSecAttrAccessibleWhenUnlocked Item data can only be accessed - while the device is unlocked. This is recommended for items that only - need be accesible while the application is in the foreground. Items - with this attribute will migrate to a new device when using encrypted - backups. - @constant kSecAttrAccessibleAfterFirstUnlock Item data can only be - accessed once the device has been unlocked after a restart. This is - recommended for items that need to be accesible by background - applications. Items with this attribute will migrate to a new device - when using encrypted backups. - @constant kSecAttrAccessibleAlways Item data can always be accessed - regardless of the lock state of the device. This is not recommended - for anything except system use. Items with this attribute will migrate - to a new device when using encrypted backups. - @constant kSecAttrAccessibleWhenUnlockedThisDeviceOnly Item data can only - be accessed while the device is unlocked. This is recommended for items - that only need be accesible while the application is in the foreground. - Items with this attribute will never migrate to a new device, so after - a backup is restored to a new device, these items will be missing. - @constant kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly Item data can - only be accessed once the device has been unlocked after a restart. - This is recommended for items that need to be accessible by background - applications. Items with this attribute will never migrate to a new - device, so after a backup is restored to a new device these items will - be missing. - @constant kSecAttrAccessibleAlwaysThisDeviceOnly Item data can always - be accessed regardless of the lock state of the device. This option - is not recommended for anything except system use. Items with this - attribute will never migrate to a new device, so after a backup is - restored to a new device, these items will be missing. -*/ -extern const CFTypeRef kSecAttrAccessibleWhenUnlocked - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); -extern const CFTypeRef kSecAttrAccessibleAfterFirstUnlock - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); -extern const CFTypeRef kSecAttrAccessibleAlways - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); -extern const CFTypeRef kSecAttrAccessibleWhenUnlockedThisDeviceOnly - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); -extern const CFTypeRef kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); -extern const CFTypeRef kSecAttrAccessibleAlwaysThisDeviceOnly - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); - -/*! - @enum kSecAttrProtocol Value Constants - @discussion Predefined item attribute constants used to get or set values - in a dictionary. The kSecAttrProtocol constant is the key and its - value is one of the constants defined here. - @constant kSecAttrProtocolFTP - @constant kSecAttrProtocolFTPAccount - @constant kSecAttrProtocolHTTP - @constant kSecAttrProtocolIRC - @constant kSecAttrProtocolNNTP - @constant kSecAttrProtocolPOP3 - @constant kSecAttrProtocolSMTP - @constant kSecAttrProtocolSOCKS - @constant kSecAttrProtocolIMAP - @constant kSecAttrProtocolLDAP - @constant kSecAttrProtocolAppleTalk - @constant kSecAttrProtocolAFP - @constant kSecAttrProtocolTelnet - @constant kSecAttrProtocolSSH - @constant kSecAttrProtocolFTPS - @constant kSecAttrProtocolHTTPS - @constant kSecAttrProtocolHTTPProxy - @constant kSecAttrProtocolHTTPSProxy - @constant kSecAttrProtocolFTPProxy - @constant kSecAttrProtocolSMB - @constant kSecAttrProtocolRTSP - @constant kSecAttrProtocolRTSPProxy - @constant kSecAttrProtocolDAAP - @constant kSecAttrProtocolEPPC - @constant kSecAttrProtocolIPP - @constant kSecAttrProtocolNNTPS - @constant kSecAttrProtocolLDAPS - @constant kSecAttrProtocolTelnetS - @constant kSecAttrProtocolIMAPS - @constant kSecAttrProtocolIRCS - @constant kSecAttrProtocolPOP3S -*/ -extern const CFTypeRef kSecAttrProtocolFTP - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolFTPAccount - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolHTTP - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolIRC - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolNNTP - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolPOP3 - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolSMTP - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolSOCKS - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolIMAP - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolLDAP - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolAppleTalk - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolAFP - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolTelnet - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolSSH - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolFTPS - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolHTTPS - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolHTTPProxy - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolHTTPSProxy - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolFTPProxy - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolSMB - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolRTSP - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolRTSPProxy - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolDAAP - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolEPPC - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolIPP - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolNNTPS - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolLDAPS - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolTelnetS - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolIMAPS - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolIRCS - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrProtocolPOP3S - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @enum kSecAttrAuthenticationType Value Constants - @discussion Predefined item attribute constants used to get or set values - in a dictionary. The kSecAttrAuthenticationType constant is the key - and its value is one of the constants defined here. - @constant kSecAttrAuthenticationTypeNTLM - @constant kSecAttrAuthenticationTypeMSN - @constant kSecAttrAuthenticationTypeDPA - @constant kSecAttrAuthenticationTypeRPA - @constant kSecAttrAuthenticationTypeHTTPBasic - @constant kSecAttrAuthenticationTypeHTTPDigest - @constant kSecAttrAuthenticationTypeHTMLForm - @constant kSecAttrAuthenticationTypeDefault -*/ -extern const CFTypeRef kSecAttrAuthenticationTypeNTLM - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrAuthenticationTypeMSN - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrAuthenticationTypeDPA - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrAuthenticationTypeRPA - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrAuthenticationTypeHTTPBasic - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrAuthenticationTypeHTTPDigest - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrAuthenticationTypeHTMLForm - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecAttrAuthenticationTypeDefault - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @enum kSecAttrKeyClass Value Constants - @discussion Predefined item attribute constants used to get or set values - in a dictionary. The kSecAttrKeyClass constant is the key - and its value is one of the constants defined here. - @constant kSecAttrKeyClassPublic - @constant kSecAttrKeyClassPrivate - @constant kSecAttrKeyClassSymmetric -*/ -extern const CFTypeRef kSecAttrKeyClassPublic - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); -extern const CFTypeRef kSecAttrKeyClassPrivate - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); -extern const CFTypeRef kSecAttrKeyClassSymmetric - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - -/*! - @enum kSecAttrKeyType Value Constants - @discussion Predefined item attribute constants used to get or set values - in a dictionary. The kSecAttrKeyType constant is the key - and its value is one of the constants defined here. - @constant kSecAttrKeyTypeRSA - @constant kSecAttrKeyTypeDSA - @constant kSecAttrKeyTypeAES - @constant kSecAttrKeyType3DES - @constant kSecAttrKeyTypeRC4 - @constant kSecAttrKeyTypeRC2 - @constant kSecAttrKeyTypeCAST - @constant kSecAttrKeyTypeECDSA (deprecated; use kSecAttrKeyTypeEC instead.) - @constant kSecAttrKeyTypeEC -*/ -extern const CFTypeRef kSecAttrKeyTypeRSA - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); -extern const CFTypeRef kSecAttrKeyTypeDSA - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecAttrKeyTypeAES - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecAttrKeyTypeDES - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecAttrKeyType3DES - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecAttrKeyTypeRC4 - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecAttrKeyTypeRC2 - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecAttrKeyTypeCAST - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecAttrKeyTypeECDSA - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecAttrKeyTypeEC - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); - -/*! - @enum kSecAttrPRF Value Constants - @discussion Predefined item attribute constants used to specify the PRF - to use with SecKeyDeriveFromPassword. - @constant kSecAttrPRFHmacAlgSHA1 - @constant kSecAttrPRFHmacAlgSHA224 - @constant kSecAttrPRFHmacAlgSHA256 - @constant kSecAttrPRFHmacAlgSHA384 - @constant kSecAttrPRFHmacAlgSHA512 -*/ -extern const CFTypeRef kSecAttrPRFHmacAlgSHA1 - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecAttrPRFHmacAlgSHA224 - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecAttrPRFHmacAlgSHA256 - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecAttrPRFHmacAlgSHA384 - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecAttrPRFHmacAlgSHA512 - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/*! - @enum Search Constants - @discussion Predefined search constants used to set values in a query - dictionary. You can specify a combination of search attributes and - item attributes when looking for matching items with the - SecItemCopyMatching function. - @constant kSecMatchPolicy Specifies a dictionary key whose value is a - SecPolicyRef. If provided, returned certificates or identities must - verify with this policy. - @constant kSecMatchItemList Specifies a dictionary key whose value is a - CFArray of SecKeychainItemRef items. If provided, returned items will be - limited to the subset which are contained in this list. - @constant kSecMatchSearchList Specifies a dictionary key whose value is a - CFArray of SecKeychainRef items. If provided, the search will be limited - to the keychains contained in this list. - @constant kSecMatchIssuers Specifies a dictionary key whose value is a - CFArray of X.500 names (of type CFDataRef). If provided, returned - certificates or identities will be limited to those whose - certificate chain contains one of the issuers provided in this list. - @constant kSecMatchEmailAddressIfPresent Specifies a dictionary key whose - value is a CFStringRef containing an RFC822 email address. If - provided, returned certificates or identities will be limited to those - that contain the address, or do not contain any email address. - @constant kSecMatchSubjectContains Specifies a dictionary key whose value - is a CFStringRef. If provided, returned certificates or identities - will be limited to those containing this string in the subject. - @constant kSecMatchSubjectStartsWith Specifies a dictionary key whose value - is a CFStringRef. If provided, returned certificates or identities - will be limited to those with subject names that start with this string. - @constant kSecMatchSubjectEndsWith Specifies a dictionary key whose value - is a CFStringRef. If provided, returned certificates or identities - will be limited to those with subject names that end with this string. - @constant kSecMatchSubjectWholeString Specifies a dictionary key whose - value is a CFStringRef. If provided, returned certificates or identities - will be limited to those matching this string exactly in the subject. - @constant kSecMatchCaseInsensitive Specifies a dictionary key whose value - is a CFBooleanRef. If this value is kCFBooleanFalse, or is not - provided, then case-sensitive string matching is performed. - @constant kSecMatchDiacriticInsensitive Specifies a dictionary key whose - value is a CFBooleanRef. If this value is kCFBooleanFalse, or is not - provided, then diacritic-sensitive string matching is performed. - @constant kSecMatchWidthInsensitive Specifies a dictionary key whose - value is a CFBooleanRef. If this value is kCFBooleanFalse, or is not - provided, then string matching is width-sensitive (e.g. 'a' != 0xFF41). - @constant kSecMatchTrustedOnly Specifies a dictionary key whose value is - a CFBooleanRef. If provided with a value of kCFBooleanTrue, only - certificates which can be verified back to a trusted anchor will be - returned. If this value is kCFBooleanFalse, or is not provided, then - both trusted and untrusted certificates may be returned. - @constant kSecMatchValidOnDate Specifies a dictionary key whose value is - of type CFDateRef. If provided, returned keys, certificates or - identities will be limited to those which are valid for the given date. - Pass a value of kCFNull to indicate the current date. - @constant kSecMatchLimit Specifies a dictionary key whose value is a - CFNumberRef. If provided, this value specifies the maximum number of - results to return. If not provided, results are limited to the first - item found. Predefined values are provided for a single item - (kSecMatchLimitOne) and all matching items (kSecMatchLimitAll). - @constant kSecMatchLimitOne Specifies that results are limited to the first - item found; used as a value for the kSecMatchLimit dictionary key. - @constant kSecMatchLimitAll Specifies that an unlimited number of results - may be returned; used as a value for the kSecMatchLimit dictionary - key. -*/ -extern const CFTypeRef kSecMatchPolicy - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecMatchItemList - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecMatchSearchList - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecMatchIssuers - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecMatchEmailAddressIfPresent - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecMatchSubjectContains - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecMatchSubjectStartsWith - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecMatchSubjectEndsWith - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecMatchSubjectWholeString - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecMatchCaseInsensitive - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecMatchDiacriticInsensitive - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecMatchWidthInsensitive - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern const CFTypeRef kSecMatchTrustedOnly - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecMatchValidOnDate - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecMatchLimit - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecMatchLimitOne - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecMatchLimitAll - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - - -/*! - @enum Return Type Key Constants - @discussion Predefined return type keys used to set values in a dictionary. - You use these keys to specify the type of results which should be - returned by the SecItemCopyMatching or SecItemAdd function. You can - specify zero or more of these return types. If more than one of these - result types is specified, the result is returned as a CFDictionaryRef - whose keys are the result types and values are the requested data. - @constant kSecReturnData Specifies a dictionary key whose value is of type - CFBooleanRef. A value of kCFBooleanTrue indicates that the data of - an item (CFDataRef) should be returned. For keys and password - items, data is secret (encrypted) and may require the user to enter - a password for access. - @constant kSecReturnAttributes Specifies a dictionary key whose value is - of type CFBooleanRef. A value of kCFBooleanTrue indicates that the - (non-encrypted) attributes of an item (in a CFDictionaryRef) should be - returned. - @constant kSecReturnRef Specifies a dictionary key whose value is a - CFBooleanRef. A value of kCFBooleanTrue indicates that a reference - should be returned. Depending on the item class requested, the - returned reference(s) may be of type SecKeychainItemRef, SecKeyRef, - SecCertificateRef, or SecIdentityRef. - @constant kSecReturnPersistentRef Specifies a dictionary key whose value - is of type CFBooleanRef. A value of kCFBooleanTrue indicates that a - persistent reference to an item (CFDataRef) should be returned. -*/ -extern const CFTypeRef kSecReturnData - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecReturnAttributes - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecReturnRef - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecReturnPersistentRef - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - - -/*! - @enum Value Type Key Constants - @discussion Predefined value type keys used to pass values in a dictionary. - You can specify zero or more of these types depending on the function - you are calling. For SecItemCopyMatching or SecItemAdd these are - used as keys in the results dictionary. - @constant kSecValueData Specifies a dictionary key whose value is of type - CFDataRef. For keys and password items, data is secret (encrypted) - and may require the user to enter a password for access. - @constant kSecValueRef Specifies a dictionary key whose value, depending - on the item class requested, is of type SecKeychainItemRef, SecKeyRef, - SecCertificateRef, or SecIdentityRef. - @constant kSecValuePersistentRef Specifies a dictionary key whose value - is of type CFDataRef. The bytes in this CFDataRef can be stored by - the caller and used on a subsequent invocation of the application (or - even a different application) to retrieve the item referenced by it. -*/ -extern const CFTypeRef kSecValueData - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecValueRef - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecValuePersistentRef - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - - -/*! - @enum Other Constants - @discussion Predefined constants used to set values in a dictionary. - @constant kSecUseItemList Specifies a dictionary key whose value is a - CFArray of items. If provided, this array is treated as the set of - all possible items to search, or add if the API being called is - SecItemAdd. The items in this array may be of type SecKeyRef, - SecCertificateRef, SecIdentityRef, or CFDataRef (for a persistent - item reference.) The items in the array must all be of the same - type. When this attribute is provided, no keychains are searched. - @constant kSecUseKeychain Specifies a dictionary key whose value is a - keychain reference. You use this key to specify a value of type - SecKeychainRef to which SecItemAdd will add the provided item(s). -*/ -extern const CFTypeRef kSecUseItemList - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern const CFTypeRef kSecUseKeychain - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/*! - @function SecItemCopyMatching - @abstract Returns one or more items which match a search query. - @param query A dictionary containing an item class specification and - optional attributes for controlling the search. See the "Keychain - Search Attributes" section for a description of currently defined - search attributes. - @param result On return, a CFTypeRef reference to the found item(s). The - exact type of the result is based on the search attributes supplied - in the query, as discussed below. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Attributes defining a search are specified by adding key/value - pairs to the query dictionary. - - A typical query consists of: - - * a kSecClass key, whose value is a constant from the Class - Constants section that specifies the class of item(s) to be searched - * one or more keys from the "Attribute Key Constants" section, whose value - is the attribute data to be matched - * one or more keys from the "Search Constants" section, whose value is - used to further refine the search - * a key from the "Return Type Key Constants" section, specifying the type of - results desired - - Result types are specified as follows: - - * To obtain the data of a matching item (CFDataRef), specify - kSecReturnData with a value of kCFBooleanTrue. - * To obtain the attributes of a matching item (CFDictionaryRef), specify - kSecReturnAttributes with a value of kCFBooleanTrue. - * To obtain a reference to a matching item (SecKeychainItemRef, - SecKeyRef, SecCertificateRef, or SecIdentityRef), specify kSecReturnRef - with a value of kCFBooleanTrue. - * To obtain a persistent reference to a matching item (CFDataRef), - specify kSecReturnPersistentRef with a value of kCFBooleanTrue. Note - that unlike normal references, a persistent reference may be stored - on disk or passed between processes. - * If more than one of these result types is specified, the result is - returned as a CFDictionaryRef containing all the requested data. - - By default, this function returns only the first match found. To obtain - more than one matching item at a time, specify kSecMatchLimit with a value - greater than 1. The result will be a CFArrayRef containing up to that - number of matching items; the items' types are described above. - - To filter a provided list of items down to those matching the query, - specify a kSecMatchItemList whose value is a CFArray of SecKeychainItemRef, - SecKeyRef, SecCertificateRef, or SecIdentityRef items. The objects in the - provided array must be of the same type. - - To convert from persistent item references to normal item references, - specify a kSecMatchItemList whose value is a CFArray containing one or - more CFDataRef elements (the persistent reference), and a kSecReturnRef - whose value is kCFBooleanTrue. The objects in the provided array must be - of the same type. -*/ -OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @function SecItemAdd - @abstract Add one or more items to a keychain. - @param attributes A dictionary containing an item class specification and - optional entries specifying the item's attribute values. See the - "Attribute Key Constants" section for a description of currently defined - attributes. - @param result On return, a CFTypeRef reference to the newly added item(s). - The exact type of the result is based on the values supplied - in attributes, as discussed below. Pass NULL if this result is not - required. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Attributes defining an item are specified by adding key/value - pairs to the attributes dictionary. To add multiple items to a keychain - at once use the kSecUseItemList key with an array of items as its value. - This is currently only supported for non password items. To add an item - to a particular keychain, supply kSecUseKeychain with a SecKeychainRef as - its value. - - Result types are specified as follows: - - * To obtain the data of the added item (CFDataRef), specify - kSecReturnData with a value of kCFBooleanTrue. - * To obtain all the attributes of the added item (CFDictionaryRef), - specify kSecReturnAttributes with a value of kCFBooleanTrue. - * To obtain a reference to the added item (SecKeychainItemRef, SecKeyRef, - SecCertificateRef, or SecIdentityRef), specify kSecReturnRef with a - value of kCFBooleanTrue. This is the default behavior if a result - type is not explicitly specified. - * To obtain a persistent reference to the added item (CFDataRef), specify - kSecReturnPersistentRef with a value of kCFBooleanTrue. Note that - unlike normal references, a persistent reference may be stored on disk - or passed between processes. - * If more than one of these result types is specified, the result is - returned as a CFDictionaryRef containing all the requested data. -*/ -OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @function SecItemUpdate - @abstract Modify zero or more items which match a search query. - @param query A dictionary containing an item class specification and - optional attributes for controlling the search. See the "Attribute - Constants" and "Search Constants" sections for a description of - currently defined search attributes. - @param attributesToUpdate A dictionary containing one or more attributes - whose values should be set to the ones specified. Only real keychain - attributes are permitted in this dictionary (no "meta" attributes are - allowed.) See the "Attribute Key Constants" section for a description of - currently defined value attributes. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Attributes defining a search are specified by adding key/value - pairs to the query dictionary. -*/ -OSStatus SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @function SecItemDelete - @abstract Delete zero or more items which match a search query. - @param query A dictionary containing an item class specification and - optional attributes for controlling the search. See the "Attribute - Constants" and "Search Constants" sections for a description of - currently defined search attributes. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Attributes defining a search are specified by adding key/value - pairs to the query dictionary. - - By default, this function deletes all items matching the specified query. - You can change this behavior by specifying one of the follow keys: - - * To delete an item identified by a transient reference, specify - kSecMatchItemList with a reference returned by using the kSecReturnRef - key in a previous call to SecItemCopyMatching or SecItemAdd. - * To delete an item identified by a persistent reference, specify - kSecMatchItemList with a persistent reference returned by using the - kSecReturnPersistentRef key to SecItemCopyMatching or SecItemAdd. - * If more than one of these result keys is specified, the behavior is - undefined. -*/ -OSStatus SecItemDelete(CFDictionaryRef query) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECITEM_H_ */ diff --git a/libsecurity_keychain/lib/SecItemConstants.c b/libsecurity_keychain/lib/SecItemConstants.c deleted file mode 100644 index cba8c4ef..00000000 --- a/libsecurity_keychain/lib/SecItemConstants.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (c) 2006-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@ - */ - -#define __CONSTANT_CFSTRINGS__ 1 -#include - -/* String constant declarations */ - -#define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); - -/* Class Key Constant */ -SEC_CONST_DECL (kSecClass, "class"); - -/* Class Value Constants */ -SEC_CONST_DECL (kSecClassGenericPassword, "genp"); -SEC_CONST_DECL (kSecClassInternetPassword, "inet"); -SEC_CONST_DECL (kSecClassAppleSharePassword, "apls"); -SEC_CONST_DECL (kSecClassCertificate, "cert"); -SEC_CONST_DECL (kSecClassKey, "keys"); -SEC_CONST_DECL (kSecClassIdentity, "idnt"); - -/* Attribute Key Constants */ -SEC_CONST_DECL (kSecAttrAccessible, "pdmn"); -SEC_CONST_DECL (kSecAttrAccessGroup, "agrp"); -SEC_CONST_DECL (kSecAttrAccess, "acls"); -SEC_CONST_DECL (kSecAttrCreationDate, "cdat"); -SEC_CONST_DECL (kSecAttrModificationDate, "mdat"); -SEC_CONST_DECL (kSecAttrDescription, "desc"); -SEC_CONST_DECL (kSecAttrComment, "icmt"); -SEC_CONST_DECL (kSecAttrCreator, "crtr"); -SEC_CONST_DECL (kSecAttrType, "type"); -SEC_CONST_DECL (kSecAttrLabel, "labl"); -SEC_CONST_DECL (kSecAttrIsInvisible, "invi"); -SEC_CONST_DECL (kSecAttrIsNegative, "nega"); -SEC_CONST_DECL (kSecAttrAccount, "acct"); -SEC_CONST_DECL (kSecAttrService, "svce"); -SEC_CONST_DECL (kSecAttrGeneric, "gena"); -SEC_CONST_DECL (kSecAttrSecurityDomain, "sdmn"); -SEC_CONST_DECL (kSecAttrServer, "srvr"); -SEC_CONST_DECL (kSecAttrProtocol, "ptcl"); -SEC_CONST_DECL (kSecAttrAuthenticationType, "atyp"); -SEC_CONST_DECL (kSecAttrPort, "port"); -SEC_CONST_DECL (kSecAttrPath, "path"); -SEC_CONST_DECL (kSecAttrVolume, "volm"); -SEC_CONST_DECL (kSecAttrAddress, "addr"); -SEC_CONST_DECL (kSecAttrAFPServerSignature, "afps"); -SEC_CONST_DECL (kSecAttrAlias, "alis"); -SEC_CONST_DECL (kSecAttrSubject, "subj"); -SEC_CONST_DECL (kSecAttrIssuer, "issr"); -SEC_CONST_DECL (kSecAttrSerialNumber, "slnr"); -SEC_CONST_DECL (kSecAttrSubjectKeyID, "skid"); -SEC_CONST_DECL (kSecAttrPublicKeyHash, "pkhh"); -SEC_CONST_DECL (kSecAttrCertificateType, "ctyp"); -SEC_CONST_DECL (kSecAttrCertificateEncoding, "cenc"); -SEC_CONST_DECL (kSecAttrKeyClass, "kcls"); -SEC_CONST_DECL (kSecAttrApplicationLabel, "klbl"); -SEC_CONST_DECL (kSecAttrIsPermanent, "perm"); -SEC_CONST_DECL (kSecAttrIsModifiable, "modi"); -SEC_CONST_DECL (kSecAttrIsPrivate, "priv"); -SEC_CONST_DECL (kSecAttrApplicationTag, "atag"); -SEC_CONST_DECL (kSecAttrKeyCreator, "crtr"); -SEC_CONST_DECL (kSecAttrKeyType, "type"); -SEC_CONST_DECL (kSecAttrPRF, "prf"); -SEC_CONST_DECL (kSecAttrSalt, "salt"); -SEC_CONST_DECL (kSecAttrRounds, "rounds"); -SEC_CONST_DECL (kSecAttrKeySizeInBits, "bsiz"); -SEC_CONST_DECL (kSecAttrEffectiveKeySize, "esiz"); -SEC_CONST_DECL (kSecAttrStartDate, "sdat"); -SEC_CONST_DECL (kSecAttrEndDate, "edat"); -SEC_CONST_DECL (kSecAttrIsSensitive, "sens"); -SEC_CONST_DECL (kSecAttrWasAlwaysSensitive, "asen"); -SEC_CONST_DECL (kSecAttrIsExtractable, "extr"); -SEC_CONST_DECL (kSecAttrWasNeverExtractable, "next"); -SEC_CONST_DECL (kSecAttrCanEncrypt, "encr"); -SEC_CONST_DECL (kSecAttrCanDecrypt, "decr"); -SEC_CONST_DECL (kSecAttrCanDerive, "drve"); -SEC_CONST_DECL (kSecAttrCanSign, "sign"); -SEC_CONST_DECL (kSecAttrCanVerify, "vrfy"); -SEC_CONST_DECL (kSecAttrCanSignRecover, "snrc"); -SEC_CONST_DECL (kSecAttrCanVerifyRecover, "vyrc"); -SEC_CONST_DECL (kSecAttrCanWrap, "wrap"); -SEC_CONST_DECL (kSecAttrCanUnwrap, "unwp"); -/* Attribute Constants (Private) */ -SEC_CONST_DECL (kSecAttrScriptCode, "scrp"); -SEC_CONST_DECL (kSecAttrHasCustomIcon, "cusi"); -SEC_CONST_DECL (kSecAttrCRLType, "crlt"); -SEC_CONST_DECL (kSecAttrCRLEncoding, "crle"); -SEC_CONST_DECL (kSecAttrSynchronizable, "sync"); -SEC_CONST_DECL (kSecAttrSynchronizableAny, "syna"); -SEC_CONST_DECL (kSecAttrTombstone, "tomb"); - -/* Search Constants */ -SEC_CONST_DECL (kSecMatchPolicy, "m_Policy"); -SEC_CONST_DECL (kSecMatchItemList, "m_ItemList"); -SEC_CONST_DECL (kSecMatchSearchList, "m_SearchList"); -SEC_CONST_DECL (kSecMatchIssuers, "m_Issuers"); -SEC_CONST_DECL (kSecMatchEmailAddressIfPresent, "m_EmailAddressIfPresent"); -SEC_CONST_DECL (kSecMatchSubjectContains, "m_SubjectContains"); -SEC_CONST_DECL (kSecMatchSubjectStartsWith, "m_SubjectStartsWith"); -SEC_CONST_DECL (kSecMatchSubjectEndsWith, "m_SubjectEndsWith"); -SEC_CONST_DECL (kSecMatchSubjectWholeString, "m_SubjectWholeString"); -SEC_CONST_DECL (kSecMatchCaseInsensitive, "m_CaseInsensitive"); -SEC_CONST_DECL (kSecMatchDiacriticInsensitive, "m_DiacriticInsensitive"); -SEC_CONST_DECL (kSecMatchWidthInsensitive, "m_WidthInsensitive"); -SEC_CONST_DECL (kSecMatchTrustedOnly, "m_TrustedOnly"); -SEC_CONST_DECL (kSecMatchValidOnDate, "m_ValidOnDate"); -SEC_CONST_DECL (kSecMatchLimit, "m_Limit"); -/* Could just use kCFBooleanTrue and kCFBooleanFalse for these 2. */ -SEC_CONST_DECL (kSecMatchLimitOne, "m_LimitOne"); -SEC_CONST_DECL (kSecMatchLimitAll, "m_LimitAll"); - -/* Return Type Key Constants */ -SEC_CONST_DECL (kSecReturnData, "r_Data"); -SEC_CONST_DECL (kSecReturnAttributes, "r_Attributes"); -SEC_CONST_DECL (kSecReturnRef, "r_Ref"); -SEC_CONST_DECL (kSecReturnPersistentRef, "r_PersistentRef"); - -/* Value Type Key Constants */ -SEC_CONST_DECL (kSecValueData, "v_Data"); -SEC_CONST_DECL (kSecValueRef, "v_Ref"); -SEC_CONST_DECL (kSecValuePersistentRef, "v_PersistentRef"); - -/* Other Constants */ -SEC_CONST_DECL (kSecUseItemList, "u_ItemList"); -SEC_CONST_DECL (kSecUseKeychain, "u_Keychain"); - -/* kSecAttrAccessible Value Constants. */ -SEC_CONST_DECL (kSecAttrAccessibleWhenUnlocked, "ak"); -SEC_CONST_DECL (kSecAttrAccessibleAfterFirstUnlock, "ck"); -SEC_CONST_DECL (kSecAttrAccessibleAlways, "dk"); -SEC_CONST_DECL (kSecAttrAccessibleWhenUnlockedThisDeviceOnly, "aku"); -SEC_CONST_DECL (kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, "cku"); -SEC_CONST_DECL (kSecAttrAccessibleAlwaysThisDeviceOnly, "dku"); - -/* kSecAttrProtocol Value Constants. */ -SEC_CONST_DECL (kSecAttrProtocolFTP, "ftp "); -SEC_CONST_DECL (kSecAttrProtocolFTPAccount, "ftpa"); -SEC_CONST_DECL (kSecAttrProtocolHTTP, "http"); -SEC_CONST_DECL (kSecAttrProtocolIRC, "irc "); -SEC_CONST_DECL (kSecAttrProtocolNNTP, "nntp"); -SEC_CONST_DECL (kSecAttrProtocolPOP3, "pop3"); -SEC_CONST_DECL (kSecAttrProtocolSMTP, "smtp"); -SEC_CONST_DECL (kSecAttrProtocolSOCKS, "sox "); -SEC_CONST_DECL (kSecAttrProtocolIMAP, "imap"); -SEC_CONST_DECL (kSecAttrProtocolLDAP, "ldap"); -SEC_CONST_DECL (kSecAttrProtocolAppleTalk, "atlk"); -SEC_CONST_DECL (kSecAttrProtocolAFP, "afp "); -SEC_CONST_DECL (kSecAttrProtocolTelnet, "teln"); -SEC_CONST_DECL (kSecAttrProtocolSSH, "ssh "); -SEC_CONST_DECL (kSecAttrProtocolFTPS, "ftps"); -SEC_CONST_DECL (kSecAttrProtocolHTTPS, "htps"); -SEC_CONST_DECL (kSecAttrProtocolHTTPProxy, "htpx"); -SEC_CONST_DECL (kSecAttrProtocolHTTPSProxy, "htsx"); -SEC_CONST_DECL (kSecAttrProtocolFTPProxy, "ftpx"); -SEC_CONST_DECL (kSecAttrProtocolSMB, "smb "); -SEC_CONST_DECL (kSecAttrProtocolRTSP, "rtsp"); -SEC_CONST_DECL (kSecAttrProtocolRTSPProxy, "rtsx"); -SEC_CONST_DECL (kSecAttrProtocolDAAP, "daap"); -SEC_CONST_DECL (kSecAttrProtocolEPPC, "eppc"); -SEC_CONST_DECL (kSecAttrProtocolIPP, "ipp "); -SEC_CONST_DECL (kSecAttrProtocolNNTPS, "ntps"); -SEC_CONST_DECL (kSecAttrProtocolLDAPS, "ldps"); -SEC_CONST_DECL (kSecAttrProtocolTelnetS, "tels"); -SEC_CONST_DECL (kSecAttrProtocolIMAPS, "imps"); -SEC_CONST_DECL (kSecAttrProtocolIRCS, "ircs"); -SEC_CONST_DECL (kSecAttrProtocolPOP3S, "pops"); - -/* kSecAttrAuthenticationType Value Constants. */ -SEC_CONST_DECL (kSecAttrAuthenticationTypeNTLM, "ntlm"); -SEC_CONST_DECL (kSecAttrAuthenticationTypeMSN, "msna"); -SEC_CONST_DECL (kSecAttrAuthenticationTypeDPA, "dpaa"); -SEC_CONST_DECL (kSecAttrAuthenticationTypeRPA, "rpaa"); -SEC_CONST_DECL (kSecAttrAuthenticationTypeHTTPBasic, "http"); -SEC_CONST_DECL (kSecAttrAuthenticationTypeHTTPDigest, "httd"); -SEC_CONST_DECL (kSecAttrAuthenticationTypeHTMLForm, "form"); -SEC_CONST_DECL (kSecAttrAuthenticationTypeDefault, "dflt"); - -/* kSecAttrKeyClass Value Constants. Based on - CSSM_KEYCLASS_PUBLIC_KEY = 0, - CSSM_KEYCLASS_PRIVATE_KEY = 1, - CSSM_KEYCLASS_SESSION_KEY = 2, - */ -SEC_CONST_DECL (kSecAttrKeyClassPublic, "0"); -SEC_CONST_DECL (kSecAttrKeyClassPrivate, "1"); -SEC_CONST_DECL (kSecAttrKeyClassSymmetric, "2"); - -/* kSecAttrKeyType Value Constants. Based on CSSM_ALGORITHMS. */ -SEC_CONST_DECL (kSecAttrKeyTypeDES, "14"); -SEC_CONST_DECL (kSecAttrKeyType3DES, "17"); -SEC_CONST_DECL (kSecAttrKeyTypeRC2, "23"); -SEC_CONST_DECL (kSecAttrKeyTypeRC4, "25"); -SEC_CONST_DECL (kSecAttrKeyTypeRSA, "42"); -SEC_CONST_DECL (kSecAttrKeyTypeDSA, "43"); -SEC_CONST_DECL (kSecAttrKeyTypeCAST, "56"); -SEC_CONST_DECL (kSecAttrKeyTypeECDSA, "73"); -SEC_CONST_DECL (kSecAttrKeyTypeEC, "73"); /* rdar://13326326 */ -SEC_CONST_DECL (kSecAttrKeyTypeAES, "2147483649"); /* */ - -SEC_CONST_DECL (kSecAttrPRFHmacAlgSHA1, "hsha1"); -SEC_CONST_DECL (kSecAttrPRFHmacAlgSHA224, "hsha224"); -SEC_CONST_DECL (kSecAttrPRFHmacAlgSHA256, "hsha256"); -SEC_CONST_DECL (kSecAttrPRFHmacAlgSHA384, "hsha384"); -SEC_CONST_DECL (kSecAttrPRFHmacAlgSHA512, "hsha512"); - - -/* Constants used by SecKeyGeneratePair() - in SecKey.h. Never used in - any SecItem apis directly. */ -SEC_CONST_DECL (kSecPrivateKeyAttrs, "private"); -SEC_CONST_DECL (kSecPublicKeyAttrs, "public"); -/* Used for SecKeyGenerateSymmetric */ -SEC_CONST_DECL (kSecSymmetricKeyAttrs, "symmetric"); - diff --git a/libsecurity_keychain/lib/SecItemPriv.h b/libsecurity_keychain/lib/SecItemPriv.h deleted file mode 100644 index 9b1fb7f0..00000000 --- a/libsecurity_keychain/lib/SecItemPriv.h +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (c) 2006-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@ - */ - -/*! - @header SecItemPriv - SecItemPriv defines private constants and SPI functions for access to - Security items (certificates, identities, keys, and keychain items.) - */ - -#ifndef _SECURITY_SECITEMPRIV_H_ -#define _SECURITY_SECITEMPRIV_H_ - -#include -#include -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - - /*! - @enum Class Value Constants (Private) - @discussion Predefined item class constants used to get or set values in - a dictionary. The kSecClass constant is the key and its value is one - of the constants defined here. - @constant kSecClassAppleSharePassword Specifies AppleShare password items. - */ - extern const CFTypeRef kSecClassAppleSharePassword; - - /*! - @enum Attribute Key Constants (Private) - @discussion Predefined item attribute keys used to get or set values in a - dictionary. Not all attributes apply to each item class. The table - below lists the currently defined attributes for each item class: - - kSecClassGenericPassword item attributes: - kSecAttrAccessGroup - kSecAttrCreationDate - kSecAttrModificationDate - kSecAttrDescription - kSecAttrComment - kSecAttrCreator - kSecAttrType - kSecAttrScriptCode (private) - kSecAttrLabel - kSecAttrAlias (private) - kSecAttrIsInvisible - kSecAttrIsNegative - kSecAttrHasCustomIcon (private) - kSecAttrProtected (private) - kSecAttrAccount - kSecAttrService - kSecAttrGeneric - - kSecClassInternetPassword item attributes: - kSecAttrAccessGroup - kSecAttrCreationDate - kSecAttrModificationDate - kSecAttrDescription - kSecAttrComment - kSecAttrCreator - kSecAttrType - kSecAttrScriptCode (private) - kSecAttrLabel - kSecAttrAlias (private) - kSecAttrIsInvisible - kSecAttrIsNegative - kSecAttrHasCustomIcon (private) - kSecAttrProtected (private) - kSecAttrAccount - kSecAttrSecurityDomain - kSecAttrServer - kSecAttrProtocol - kSecAttrAuthenticationType - kSecAttrPort - kSecAttrPath - - kSecClassAppleSharePassword item attributes: - kSecAttrAccessGroup - kSecAttrCreationDate - kSecAttrModificationDate - kSecAttrDescription - kSecAttrComment - kSecAttrCreator - kSecAttrType - kSecAttrScriptCode (private) - kSecAttrLabel - kSecAttrAlias (private) - kSecAttrIsInvisible - kSecAttrIsNegative - kSecAttrHasCustomIcon (private) - kSecAttrProtected (private) - kSecAttrAccount - kSecAttrVolume - kSecAttrAddress - kSecAttrAFPServerSignature - - kSecClassCertificate item attributes: - kSecAttrAccessGroup - kSecAttrCertificateType - kSecAttrCertificateEncoding - kSecAttrLabel - kSecAttrAlias (private) - kSecAttrSubject - kSecAttrIssuer - kSecAttrSerialNumber - kSecAttrSubjectKeyID - kSecAttrPublicKeyHash - - kSecClassKey item attributes: - kSecAttrAccessGroup - kSecAttrKeyClass - kSecAttrLabel - kSecAttrAlias (private) - kSecAttrApplicationLabel - kSecAttrIsPermanent - kSecAttrIsPrivate (private) - kSecAttrIsModifiable (private) - kSecAttrApplicationTag - kSecAttrKeyCreator (private) - kSecAttrKeyType - kSecAttrKeySizeInBits - kSecAttrEffectiveKeySize - kSecAttrStartDate (private) - kSecAttrEndDate (private) - kSecAttrIsSensitive (private) - kSecAttrWasAlwaysSensitive (private) - kSecAttrIsExtractable (private) - kSecAttrWasNeverExtractable (private) - kSecAttrCanEncrypt - kSecAttrCanDecrypt - kSecAttrCanDerive - kSecAttrCanSign - kSecAttrCanVerify - kSecAttrCanSignRecover (private) - kSecAttrCanVerifyRecover (private) - kSecAttrCanWrap - kSecAttrCanUnwrap - - kSecClassIdentity item attributes: - Since an identity is the combination of a private key and a - certificate, this class shares attributes of both kSecClassKey and - kSecClassCertificate. - - @constant kSecAttrScriptCode Specifies a dictionary key whose value is the - item's script code attribute. You use this tag to set or get a value - of type CFNumberRef that represents a script code for this item's - strings. (Note: use of this attribute is deprecated; string attributes - should always be stored in UTF-8 encoding. This is currently private - for use by syncing; new code should not ever access this attribute.) - @constant kSecAttrAlias Specifies a dictionary key whose value is the - item's alias. You use this key to get or set a value of type CFDataRef - which represents an alias. For certificate items, the alias is either - a single email address, an array of email addresses, or the common - name of the certificate if it does not contain any email address. - (Items of class kSecClassCertificate have this attribute.) - @constant kSecAttrHasCustomIcon Specifies a dictionary key whose value is the - item's custom icon attribute. You use this tag to set or get a value - of type CFBooleanRef that indicates whether the item should have an - application-specific icon. (Note: use of this attribute is deprecated; - custom item icons are not supported in Mac OS X. This is currently - private for use by syncing; new code should not use this attribute.) - @constant kSecAttrVolume Specifies a dictionary key whose value is the - item's volume attribute. You use this key to set or get a CFStringRef - value that represents an AppleShare volume name. (Items of class - kSecClassAppleSharePassword have this attribute.) - @constant kSecAttrAddress Specifies a dictionary key whose value is the - item's address attribute. You use this key to set or get a CFStringRef - value that contains the AppleTalk zone name, or the IP or domain name - that represents the server address. (Items of class - kSecClassAppleSharePassword have this attribute.) - @constant kSecAttrAFPServerSignature Specifies a dictionary key whose value - is the item's AFP server signature attribute. You use this key to set - or get a CFDataRef value containing 16 bytes that represents the - server's signature block. (Items of class kSecClassAppleSharePassword - have this attribute.) - @constant kSecAttrCRLType (read-only) Specifies a dictionary key whose - value is the item's certificate revocation list type. You use this - key to get a value of type CFNumberRef that denotes the CRL type (see - the CSSM_CRL_TYPE enum in cssmtype.h). (Items of class - kSecClassCertificate have this attribute.) - @constant kSecAttrCRLEncoding (read-only) Specifies a dictionary key whose - value is the item's certificate revocation list encoding. You use - this key to get a value of type CFNumberRef that denotes the CRL - encoding (see the CSSM_CRL_ENCODING enum in cssmtype.h). (Items of - class kSecClassCertificate have this attribute.) - @constant kSecAttrKeyCreator Specifies a dictionary key whose value is a - CFDataRef containing a CSSM_GUID structure representing the module ID of - the CSP that owns this key. - @constant kSecAttrIsPrivate Specifies a dictionary key whose value is a - CFBooleanRef indicating whether the raw key material of the key in - question is private. - @constant kSecAttrIsModifiable Specifies a dictionary key whose value is a - CFBooleanRef indicating whether any of the attributes of this key are - modifiable. - @constant kSecAttrStartDate Specifies a dictionary key whose value is a - CFDateRef indicating the earliest date on which this key may be used. - If kSecAttrStartDate is not present, the restriction does not apply. - @constant kSecAttrEndDate Specifies a dictionary key whose value is a - CFDateRef indicating the last date on which this key may be used. - If kSecAttrEndDate is not present, the restriction does not apply. - @constant kSecAttrWasAlwaysSensitive Specifies a dictionary key whose value - is a CFBooleanRef indicating that the key in question has always been - marked as sensitive. - @constant kSecAttrWasNeverExtractable Specifies a dictionary key whose value - is a CFBooleanRef indicating that the key in question has never been - marked as extractable. - @constant kSecAttrCanSignRecover Specifies a dictionary key whose value is a - CFBooleanRef indicating whether the key in question can be used to - perform sign recovery. - @constant kSecAttrCanVerifyRecover Specifies a dictionary key whose value is - a CFBooleanRef indicating whether the key in question can be used to - perform verify recovery. - @constant kSecAttrTombstone Specifies a dictionary key whose value is - a CFBooleanRef indicating that the item in question is a tombstone. - */ - extern CFTypeRef kSecAttrScriptCode; - extern CFTypeRef kSecAttrAlias; - extern CFTypeRef kSecAttrHasCustomIcon; - extern CFTypeRef kSecAttrVolume; - extern CFTypeRef kSecAttrAddress; - extern CFTypeRef kSecAttrAFPServerSignature; - extern CFTypeRef kSecAttrCRLType; - extern CFTypeRef kSecAttrCRLEncoding; - extern CFTypeRef kSecAttrKeyCreator; - extern CFTypeRef kSecAttrIsPrivate; - extern CFTypeRef kSecAttrIsModifiable; - extern CFTypeRef kSecAttrStartDate; - extern CFTypeRef kSecAttrEndDate; - extern CFTypeRef kSecAttrWasAlwaysSensitive; - extern CFTypeRef kSecAttrWasNeverExtractable; - extern CFTypeRef kSecAttrCanSignRecover; - extern CFTypeRef kSecAttrCanVerifyRecover; - extern CFTypeRef kSecAttrTombstone; - - /*! - @function SecItemCopyDisplayNames - @abstract Returns an array containing unique display names for each of the - certificates, keys, identities, or passwords in the provided items - array. - @param items An array containing items of type SecKeychainItemRef, - SecKeyRef, SecCertificateRef, or SecIdentityRef. All items in the - array should be of the same type. - @param displayNames On return, an array of CFString references containing - unique names for the supplied items. You are responsible for releasing - this array reference by calling the CFRelease function. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Use this function to obtain item names which are suitable for - display in a menu or list view. The returned names are guaranteed to - be unique across the set of provided items. - */ - OSStatus SecItemCopyDisplayNames(CFArrayRef items, CFArrayRef *displayNames); - - /*! - @function SecItemDeleteAll - @abstract Removes all items from the keychain and added root certificates - from the trust store. - @result A result code. See "Security Error Codes" (SecBase.h). - */ - OSStatus SecItemDeleteAll(void); - -/* Called by clients to push sync circle and message changes to us. - Requires caller to have the kSecEntitlementSyncKeychain entitlement. */ -bool _SecKeychainSyncUpdate(CFDictionaryRef updates, CFErrorRef *error); - -CFDataRef _SecItemGetPersistentReference(CFTypeRef raw_item); - -bool _SecKeychainBackupSyncable(CFDataRef keybag, CFDataRef password, CFDictionaryRef backup_in, CFDictionaryRef *backup_out); -bool _SecKeychainRestoreSyncable(CFDataRef keybag, CFDataRef password, CFDictionaryRef backup_in); - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECITEMPRIV_H_ */ diff --git a/libsecurity_keychain/lib/SecKey.h b/libsecurity_keychain/lib/SecKey.h deleted file mode 100644 index 84fa4169..00000000 --- a/libsecurity_keychain/lib/SecKey.h +++ /dev/null @@ -1,588 +0,0 @@ -/* - * Copyright (c) 2002-2010 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 SecKey - The functions provided in SecKey.h implement and manage a particular - type of keychain item that represents a key. A key can be stored in a - keychain, but a key can also be a transient object. - - You can use a key as a keychain item in most functions. -*/ - -#ifndef _SECURITY_SECKEY_H_ -#define _SECURITY_SECKEY_H_ - -#include -#include -#include -#include -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -/*! - @enum KeyItemAttributeConstants - @abstract Specifies keychain item attributes for keys. - @constant kSecKeyKeyClass type uint32 (CSSM_KEYCLASS), value - is one of CSSM_KEYCLASS_PUBLIC_KEY, CSSM_KEYCLASS_PRIVATE_KEY - or CSSM_KEYCLASS_SESSION_KEY. - @constant kSecKeyPrintName type blob, human readable name of - the key. Same as kSecLabelItemAttr for normal keychain items. - @constant kSecKeyAlias type blob, currently unused. - @constant kSecKeyPermanent type uint32, value is nonzero iff - this key is permanent (stored in some keychain). This is always - 1. - @constant kSecKeyPrivate type uint32, value is nonzero iff this - key is protected by a user login or a password, or both. - @constant kSecKeyModifiable type uint32, value is nonzero iff - attributes of this key can be modified. - @constant kSecKeyLabel type blob, for private and public keys - this contains the hash of the public key. This is used to - associate certificates and keys. Its value matches the value - of the kSecPublicKeyHashItemAttr of a certificate and it's used - to construct an identity from a certificate and a key. - For symmetric keys this is whatever the creator of the key - passed in during the generate key call. - @constant kSecKeyApplicationTag type blob, currently unused. - @constant kSecKeyKeyCreator type data, the data points to a - CSSM_GUID structure representing the moduleid of the csp owning - this key. - @constant kSecKeyKeyType type uint32, value is a CSSM_ALGORITHMS - representing the algorithm associated with this key. - @constant kSecKeyKeySizeInBits type uint32, value is the number - of bits in this key. - @constant kSecKeyEffectiveKeySize type uint32, value is the - effective number of bits in this key. For example a des key - has a kSecKeyKeySizeInBits of 64 but a kSecKeyEffectiveKeySize - of 56. - @constant kSecKeyStartDate type CSSM_DATE. Earliest date from - which this key may be used. If the value is all zeros or not - present, no restriction applies. - @constant kSecKeyEndDate type CSSM_DATE. Latest date at - which this key may be used. If the value is all zeros or not - present, no restriction applies. - @constant kSecKeySensitive type uint32, iff value is nonzero - this key cannot be wrapped with CSSM_ALGID_NONE. - @constant kSecKeyAlwaysSensitive type uint32, value is nonzero - iff this key has always been marked sensitive. - @constant kSecKeyExtractable type uint32, value is nonzero iff - this key can be wrapped. - @constant kSecKeyNeverExtractable type uint32, value is nonzero - iff this key was never marked extractable. - @constant kSecKeyEncrypt type uint32, value is nonzero iff this - key can be used in an encrypt operation. - @constant kSecKeyDecrypt type uint32, value is nonzero iff this - key can be used in a decrypt operation. - @constant kSecKeyDerive type uint32, value is nonzero iff this - key can be used in a deriveKey operation. - @constant kSecKeySign type uint32, value is nonzero iff this - key can be used in a sign operation. - @constant kSecKeyVerify type uint32, value is nonzero iff this - key can be used in a verify operation. - @constant kSecKeySignRecover type uint32. - @constant kSecKeyVerifyRecover type uint32. - key can unwrap other keys. - @constant kSecKeyWrap type uint32, value is nonzero iff this - key can wrap other keys. - @constant kSecKeyUnwrap type uint32, value is nonzero iff this - key can unwrap other keys. - @discussion - The use of these enumerations has been deprecated. Please - use the equivalent items defined in SecItem.h - @@@. -*/ -enum -{ - kSecKeyKeyClass = 0, - kSecKeyPrintName = 1, - kSecKeyAlias = 2, - kSecKeyPermanent = 3, - kSecKeyPrivate = 4, - kSecKeyModifiable = 5, - kSecKeyLabel = 6, - kSecKeyApplicationTag = 7, - kSecKeyKeyCreator = 8, - kSecKeyKeyType = 9, - kSecKeyKeySizeInBits = 10, - kSecKeyEffectiveKeySize = 11, - kSecKeyStartDate = 12, - kSecKeyEndDate = 13, - kSecKeySensitive = 14, - kSecKeyAlwaysSensitive = 15, - kSecKeyExtractable = 16, - kSecKeyNeverExtractable = 17, - kSecKeyEncrypt = 18, - kSecKeyDecrypt = 19, - kSecKeyDerive = 20, - kSecKeySign = 21, - kSecKeyVerify = 22, - kSecKeySignRecover = 23, - kSecKeyVerifyRecover = 24, - kSecKeyWrap = 25, - kSecKeyUnwrap = 26 -}; - -/*! - @typedef SecCredentialType - @abstract Determines the type of credential returned by SecKeyGetCredentials. -*/ -typedef uint32 SecCredentialType; - -/*! - @enum SecCredentialType - @abstract Determines the type of credential returned by SecKeyGetCredentials. - @constant kSecCredentialTypeWithUI Operations with this key are allowed to present UI if required. - @constant kSecCredentialTypeNoUI Operations with this key are not allowed to present UI, and will fail if UI is required. - @constant kSecCredentialTypeDefault The default setting for determining whether to present UI is used. This setting can be changed with a call to SecKeychainSetUserInteractionAllowed. -*/ -enum -{ - kSecCredentialTypeDefault = 0, - kSecCredentialTypeWithUI, - kSecCredentialTypeNoUI -}; - -/*! - @typedef SecPadding - @abstract Supported padding types. -*/ -typedef uint32_t SecPadding; -enum -{ - kSecPaddingNone = 0, - kSecPaddingPKCS1 = 1, - - /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is an MD2 - hash; standard ASN.1 padding will be done, as well as PKCS1 padding - of the underlying RSA operation. */ - kSecPaddingPKCS1MD2 = 0x8000, - - /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is an MD5 - hash; standard ASN.1 padding will be done, as well as PKCS1 padding - of the underlying RSA operation. */ - kSecPaddingPKCS1MD5 = 0x8001, - - /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is a SHA1 - hash; standard ASN.1 padding will be done, as well as PKCS1 padding - of the underlying RSA operation. */ - kSecPaddingPKCS1SHA1 = 0x8002, -}; - -/*! - @typedef SecKeySizes - @abstract Supported key lengths. -*/ -typedef uint32_t SecKeySizes; -enum -{ - kSecDefaultKeySize = 0, - - // Symmetric Keysizes - default is currently kSecAES128 for AES. - kSec3DES192 = 192, - kSecAES128 = 128, - kSecAES192 = 192, - kSecAES256 = 256, - - // Supported ECC Keys for Suite-B from RFC 4492 section 5.1.1. - // default is currently kSecp256r1 - kSecp192r1 = 192, - kSecp256r1 = 256, - kSecp384r1 = 384, - kSecp521r1 = 521, // Yes, 521 - - // Boundaries for RSA KeySizes - default is currently 2048 - // RSA keysizes must be multiples of 8 - kSecRSAMin = 1024, - kSecRSAMax = 4096 -}; - - -/*! - @function SecKeyGetTypeID - @abstract Returns the type identifier of SecKey instances. - @result The CFTypeID of SecKey instances. -*/ -CFTypeID SecKeyGetTypeID(void) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -/*! - @function SecKeyCreatePair - @abstract Creates an asymmetric key pair and stores it in a specified keychain. - @param keychainRef A reference to the keychain in which to store the private and public key items. Specify NULL for the default keychain. - @param algorithm An algorithm for the key pair. This parameter is ignored if a valid (non-zero) contextHandle is supplied. - @param keySizeInBits A key size for the key pair. This parameter is ignored if a valid (non-zero) contextHandle is supplied. - @param contextHandle (optional) A CSSM_CC_HANDLE, or 0. If this argument is supplied, the algorithm and keySizeInBits parameters are ignored. If extra parameters are needed to generate a key (some algorithms require this), you should create a context using CSSM_CSP_CreateKeyGenContext, using the CSPHandle obtained by calling SecKeychainGetCSPHandle. Then use CSSM_UpdateContextAttributes to add parameters, and dispose of the context using CSSM_DeleteContext after calling this function. - @param publicKeyUsage A bit mask indicating all permitted uses for the new public key. CSSM_KEYUSE bit mask values are defined in cssmtype.h. - @param publicKeyAttr A bit mask defining attribute values for the new public key. The bit mask values are equivalent to a CSSM_KEYATTR_FLAGS and are defined in cssmtype.h. - @param privateKeyUsage A bit mask indicating all permitted uses for the new private key. CSSM_KEYUSE bit mask values are defined in cssmtype.h. - @param privateKeyAttr A bit mask defining attribute values for the new private key. The bit mask values are equivalent to a CSSM_KEYATTR_FLAGS and are defined in cssmtype.h. - @param initialAccess (optional) A SecAccess object that determines the initial access rights to the private key. The public key is given "any/any" access rights by default. - @param publicKey (optional) On return, the keychain item reference of the generated public key. Use the SecKeyGetCSSMKey function to obtain the CSSM_KEY. The caller must call CFRelease on this value if it is returned. Pass NULL if a reference to this key is not required. - @param privateKey (optional) On return, the keychain item reference of the generated private key. Use the SecKeyGetCSSMKey function to obtain the CSSM_KEY. The caller must call CFRelease on this value if it is returned. Pass NULL if a reference to this key is not required. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This API is deprecated for 10.7 Plese use the SecKeyGeneratePair API -*/ -OSStatus SecKeyCreatePair( - SecKeychainRef keychainRef, - CSSM_ALGORITHMS algorithm, - uint32 keySizeInBits, - CSSM_CC_HANDLE contextHandle, - CSSM_KEYUSE publicKeyUsage, - uint32 publicKeyAttr, - CSSM_KEYUSE privateKeyUsage, - uint32 privateKeyAttr, - SecAccessRef initialAccess, - SecKeyRef* publicKey, - SecKeyRef* privateKey) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/*! - @function SecKeyGenerate - @abstract Creates a symmetric key and optionally stores it in a specified keychain. - @param keychainRef (optional) A reference to the keychain in which to store the generated key. Specify NULL to generate a transient key. - @param algorithm An algorithm for the symmetric key. This parameter is ignored if a valid (non-zero) contextHandle is supplied. - @param keySizeInBits A key size for the key pair. This parameter is ignored if a valid (non-zero) contextHandle is supplied. - @param contextHandle (optional) A CSSM_CC_HANDLE, or 0. If this argument is supplied, the algorithm and keySizeInBits parameters are ignored. If extra parameters are needed to generate a key (some algorithms require this), you should create a context using CSSM_CSP_CreateKeyGenContext, using the CSPHandle obtained by calling SecKeychainGetCSPHandle. Then use CSSM_UpdateContextAttributes to add parameters, and dispose of the context using CSSM_DeleteContext after calling this function. - @param keyUsage A bit mask indicating all permitted uses for the new key. CSSM_KEYUSE bit mask values are defined in cssmtype.h. - @param keyAttr A bit mask defining attribute values for the new key. The bit mask values are equivalent to a CSSM_KEYATTR_FLAGS and are defined in cssmtype.h. - @param initialAccess (optional) A SecAccess object that determines the initial access rights for the key. This parameter is ignored if the keychainRef is NULL. - @param keyRef On return, a reference to the generated key. Use the SecKeyGetCSSMKey function to obtain the CSSM_KEY. The caller must call CFRelease on this value if it is returned. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This API is deprecated for 10.7. Plese use the SecKeyGenerateSymmetric API -*/ -OSStatus SecKeyGenerate( - SecKeychainRef keychainRef, - CSSM_ALGORITHMS algorithm, - uint32 keySizeInBits, - CSSM_CC_HANDLE contextHandle, - CSSM_KEYUSE keyUsage, - uint32 keyAttr, - SecAccessRef initialAccess, - SecKeyRef* keyRef) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/*! - @function SecKeyGetCSSMKey - @abstract Returns a pointer to the CSSM_KEY for the given key item reference. - @param key A keychain key item reference. The key item must be of class type kSecPublicKeyItemClass, kSecPrivateKeyItemClass, or kSecSymmetricKeyItemClass. - @param cssmKey On return, a pointer to a CSSM_KEY structure for the given key. This pointer remains valid until the key reference is released. The caller should not attempt to modify or free this data. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion The CSSM_KEY is valid until the key item reference is released. This API is deprecated in 10.7. Its use should no longer be needed. -*/ -OSStatus SecKeyGetCSSMKey(SecKeyRef key, const CSSM_KEY **cssmKey) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;; - -/*! - @function SecKeyGetCSPHandle - @abstract Returns the CSSM_CSP_HANDLE for the given key reference. The handle is valid until the key reference is released. - @param keyRef A key reference. - @param cspHandle On return, the CSSM_CSP_HANDLE for the given keychain. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This API is deprecated in 10.7. Its use should no longer be needed. -*/ -OSStatus SecKeyGetCSPHandle(SecKeyRef keyRef, CSSM_CSP_HANDLE *cspHandle) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/*! - @function SecKeyGetCredentials - @abstract For a given key, return a pointer to a CSSM_ACCESS_CREDENTIALS structure which will allow the key to be used. - @param keyRef The key for which a credential is requested. - @param operation The type of operation to be performed with this key. See "Authorization tag type" for defined operations (cssmtype.h). - @param credentialType The type of credential requested. - @param outCredentials On return, a pointer to a CSSM_ACCESS_CREDENTIALS structure. This pointer remains valid until the key reference is released. The caller should not attempt to modify or free this data. - @result A result code. See "Security Error Codes" (SecBase.h). -*/ -OSStatus SecKeyGetCredentials( - SecKeyRef keyRef, - CSSM_ACL_AUTHORIZATION_TAG operation, - SecCredentialType credentialType, - const CSSM_ACCESS_CREDENTIALS **outCredentials) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -/*! - @function SecKeyGetBlockSize - @abstract Decrypt a block of ciphertext. - @param key The key for which the block length is requested. - @result The block length of the key in bytes. - @discussion If for example key is an RSA key the value returned by - this function is the size of the modulus. - */ -size_t SecKeyGetBlockSize(SecKeyRef key) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @function SecKeyGenerateSymmetric - @abstract Generates a random symmetric key with the specified length - and algorithm type. - - @param parameters A dictionary containing one or more key-value pairs. - See the discussion sections below for a complete overview of options. - @param error An optional pointer to a CFErrorRef. This value is set - if an error occurred. If not NULL, the caller is responsible for - releasing the CFErrorRef. - @result On return, a SecKeyRef reference to the symmetric key, or - NULL if the key could not be created. - - @discussion In order to generate a symmetric key, the parameters dictionary - must at least contain the following keys: - - * kSecAttrKeyType with a value of kSecAttrKeyTypeAES or any other - kSecAttrKeyType defined in SecItem.h - * kSecAttrKeySizeInBits with a value being a CFNumberRef containing - the requested key size in bits. Example sizes for AES keys are: - 128, 192, 256, 512. - - To store the generated symmetric key in a keychain, set these keys: - * kSecUseKeychain (value is a SecKeychainRef) - * kSecAttrLabel (a user-visible label whose value is a CFStringRef, - e.g. "My App's Encryption Key") - * kSecAttrApplicationLabel (a label defined by your application, whose - value is a CFStringRef and which can be used to find this key in a - subsequent call to SecItemCopyMatching, e.g. "ID-1234567890-9876-0151") - - To specify the generated key's access control settings, set this key: - * kSecAttrAccess (value is a SecAccessRef) - - The keys below may be optionally set in the parameters dictionary - (with a CFBooleanRef value) to override the default usage values: - - * kSecAttrCanEncrypt (defaults to true if not explicitly specified) - * kSecAttrCanDecrypt (defaults to true if not explicitly specified) - * kSecAttrCanWrap (defaults to true if not explicitly specified) - * kSecAttrCanUnwrap (defaults to true if not explicitly specified) - -*/ -SecKeyRef SecKeyGenerateSymmetric(CFDictionaryRef parameters, CFErrorRef *error) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - - -/*! - @function SecKeyCreateFromData - @abstract Creates a symmetric key with the given data and sets the - algorithm type specified. - - @param parameters A dictionary containing one or more key-value pairs. - See the discussion sections below for a complete overview of options. - @result On return, a SecKeyRef reference to the symmetric key. - - @discussion In order to generate a symmetric key the parameters dictionary must - at least contain the following keys: - - * kSecAttrKeyType with a value of kSecAttrKeyTypeAES or any other - kSecAttrKeyType defined in SecItem.h - - The keys below may be optionally set in the parameters dictionary - (with a CFBooleanRef value) to override the default usage values: - - * kSecAttrCanEncrypt (defaults to true if not explicitly specified) - * kSecAttrCanDecrypt (defaults to true if not explicitly specified) - * kSecAttrCanWrap (defaults to true if not explicitly specified) - * kSecAttrCanUnwrap (defaults to true if not explicitly specified) - -*/ -SecKeyRef SecKeyCreateFromData(CFDictionaryRef parameters, - CFDataRef keyData, CFErrorRef *error) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - - -/*! - @function SecKeyGeneratePair - @abstract Generate a private/public keypair. - @param parameters A dictionary containing one or more key-value pairs. - @result A result code. See "Security Error Codes" (SecBase.h). On success, - the result code will be errSecSuccess, and the output parameters will - contain the public SecKeyRef and private SecKeyRef. It is the caller's - responsibility to CFRelease these key references when finished with them. - - @discussion In order to generate a keypair the parameters dictionary must - at least contain the following keys: - - * kSecAttrKeyType with a value of kSecAttrKeyTypeRSA or any other - kSecAttrKeyType defined in SecItem.h - * kSecAttrKeySizeInBits with a value being a CFNumberRef containing - the requested key size in bits. Example sizes for RSA keys are: - 512, 768, 1024, 2048. - - Setting the following attributes explicitly will override the defaults below. - See SecItem.h for detailed information on these attributes including the types - of the values. - - * kSecAttrLabel default NULL - * kSecUseKeychain default NULL, which specifies the default keychain - * kSecAttrApplicationTag default NULL - * kSecAttrEffectiveKeySize default NULL same as kSecAttrKeySizeInBits - * kSecAttrCanEncrypt default false for private keys, true for public keys - * kSecAttrCanDecrypt default true for private keys, false for public keys - * kSecAttrCanDerive default true - * kSecAttrCanSign default true for private keys, false for public keys - * kSecAttrCanVerify default false for private keys, true for public keys - * kSecAttrCanWrap default false for private keys, true for public keys - * kSecAttrCanUnwrap default true for private keys, false for public keys - -*/ -OSStatus SecKeyGeneratePair(CFDictionaryRef parameters, - SecKeyRef *publicKey, SecKeyRef *privateKey) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - -/*! - @typedef SecKeyGeneratePairBlock - @abstract Delivers the result from an asynchronous key pair generation. - @param publicKey - the public key generated. You must retain publicKey if you wish to use it after your block returns. - @param privateKey - the private key generated. You must retain publicKey if you wish to use it after your block returns. - @param error - Any errors returned. You must retain error if you wish to use it after your block returns. - */ - -#ifdef __BLOCKS__ -typedef void (^SecKeyGeneratePairBlock)(SecKeyRef publicKey, SecKeyRef privateKey, CFErrorRef error); - - -/*! - @function SecKeyGeneratePairAsync - @abstract Generate a private/public keypair returning the values in a callback. - @param parameters A dictionary containing one or more key-value pairs. - @param deliveryQueue A dispatch queue to be used to deliver the results. - @param result A callback function to result when the operation has completed. - @result On success the function returns NULL. - - @discussion In order to generate a keypair the parameters dictionary must - at least contain the following keys: - - * kSecAttrKeyType with a value being kSecAttrKeyTypeRSA or any other - kSecAttrKeyType defined in SecItem.h - * kSecAttrKeySizeInBits with a value being a CFNumberRef or CFStringRef - containing the requested key size in bits. Example sizes for RSA - keys are: 512, 768, 1024, 2048. - - The values below may be set either in the top-level dictionary or in a - dictionary that is the value of the kSecPrivateKeyAttrs or - kSecPublicKeyAttrs key in the top-level dictionary. Setting these - attributes explicitly will override the defaults below. See SecItem.h - for detailed information on these attributes including the types of - the values. - - * kSecAttrLabel default NULL - * kSecAttrIsPermanent if this key is present and has a Boolean - value of true, the key or key pair will be added to the default - keychain. - * kSecAttrApplicationTag default NULL - * kSecAttrEffectiveKeySize default NULL same as kSecAttrKeySizeInBits - * kSecAttrCanEncrypt default false for private keys, true for public keys - * kSecAttrCanDecrypt default true for private keys, false for public keys - * kSecAttrCanDerive default true - * kSecAttrCanSign default true for private keys, false for public keys - * kSecAttrCanVerify default false for private keys, true for public keys - * kSecAttrCanWrap default false for private keys, true for public keys - * kSecAttrCanUnwrap default true for private keys, false for public keys - -*/ -void SecKeyGeneratePairAsync(CFDictionaryRef parameters, - dispatch_queue_t deliveryQueue, SecKeyGeneratePairBlock result) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -#endif /* __BLOCKS__ */ - -// Derive, Wrap, and Unwrap - -/*! - @function SecKeyDeriveFromPassword - @abstract Derives a symmetric key from a password. - - @param password The password from which the keyis to be derived. - @param parameters A dictionary containing one or more key-value pairs. - @param error If the call fails this will contain the error code. - - @discussion In order to derive a key the parameters dictionary must contain at least contain the following keys: - * kSecAttrSalt - a CFData for the salt value for mixing in the pseudo-random rounds. - * kSecAttrPRF - the algorithm to use for the pseudo-random-function. - If 0, this defaults to kSecAttrPRFHmacAlgSHA1. Possible values are: - - * kSecAttrPRFHmacAlgSHA1 - * kSecAttrPRFHmacAlgSHA224 - * kSecAttrPRFHmacAlgSHA256 - * kSecAttrPRFHmacAlgSHA384 - * kSecAttrPRFHmacAlgSHA512 - - * kSecAttrRounds - the number of rounds to call the pseudo random function. - If 0, a count will be computed to average 1/10 of a second. - * kSecAttrKeySizeInBits with a value being a CFNumberRef - containing the requested key size in bits. Example sizes for RSA keys are: - 512, 768, 1024, 2048. - - @result On success a SecKeyRef is returned. On failure this result is NULL and the - error parameter contains the reason. - -*/ -SecKeyRef SecKeyDeriveFromPassword(CFStringRef password, - CFDictionaryRef parameters, CFErrorRef *error) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/*! - @function SecKeyWrapSymmetric - @abstract Wraps a symmetric key with a symmetric key. - - @param keyToWrap The key which is to be wrapped. - @param wrappingKey The key wrapping key. - #param parameters The parameter list to use for wrapping the key. - @param error If the call fails this will contain the error code. - - @result On success a CFDataRef is returned. On failure this result is NULL and the - error parameter contains the reason. - - @discussion In order to wrap a key the parameters dictionary may contain the following key: - * kSecSalt - a CFData for the salt value for the encrypt. - -*/ -CFDataRef SecKeyWrapSymmetric(SecKeyRef keyToWrap, - SecKeyRef wrappingKey, CFDictionaryRef parameters, CFErrorRef *error) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/*! - @function SecKeyUnwrapSymmetric - @abstract Unwrap a wrapped symmetric key. - - @param keyToUnwrap The wrapped key to unwrap. - @param unwrappingKey The key unwrapping key. - #param parameters The parameter list to use for unwrapping the key. - @param error If the call fails this will contain the error code. - - @result On success a SecKeyRef is returned. On failure this result is NULL and the - error parameter contains the reason. - - @discussion In order to unwrap a key the parameters dictionary may contain the following key: - * kSecSalt - a CFData for the salt value for the decrypt. - -*/ -SecKeyRef SecKeyUnwrapSymmetric(CFDataRef *keyToUnwrap, - SecKeyRef unwrappingKey, CFDictionaryRef parameters, CFErrorRef *error) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECKEY_H_ */ diff --git a/libsecurity_keychain/lib/SecKeyPriv.h b/libsecurity_keychain/lib/SecKeyPriv.h deleted file mode 100644 index f65a90af..00000000 --- a/libsecurity_keychain/lib/SecKeyPriv.h +++ /dev/null @@ -1,445 +0,0 @@ -/* - * Copyright (c) 2002-2009 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@ - * - * SecKeyPriv.h - SPIs to SecKeyRef objects. - */ - -/*! - @header SecKeyPriv - The functions provided in SecKeyPriv.h implement and manage a particular - type of keychain item that represents a key. A key can be stored in a - keychain, but a key can also be a transient object. - - You can use a key as a keychain item in most functions. -*/ - -#ifndef _SECURITY_SECKEYPRIV_H_ -#define _SECURITY_SECKEYPRIV_H_ - -#include -#include -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -typedef struct SecRSAPublicKeyParams { - uint8_t *modulus; /* modulus */ - CFIndex modulusLength; - uint8_t *exponent; /* public exponent */ - CFIndex exponentLength; -} SecRSAPublicKeyParams; - -typedef uint32_t SecKeyEncoding; -enum { - /* Typically only used for symmetric keys. */ - kSecKeyEncodingRaw = 0, - - /* RSA keys are DER-encoded according to PKCS1. */ - kSecKeyEncodingPkcs1 = 1, - - /* RSA keys are DER-encoded according to PKCS1 with Apple Extensions. */ - kSecKeyEncodingApplePkcs1 = 2, - - /* RSA public key in SecRSAPublicKeyParams format. keyData is a pointer - to a SecRSAPublicKeyParams and keyDataLength is - sizeof(SecRSAPublicKeyParams). */ - kSecKeyEncodingRSAPublicParams = 3, -}; - -typedef OSStatus (*SecKeyInitMethod)(SecKeyRef, const uint8_t *, CFIndex, - SecKeyEncoding); -typedef void *(*SecKeyCopyMethod)(SecKeyRef); -typedef void (*SecKeyDestroyMethod)(SecKeyRef); -typedef void (*SecKeyDeleteMethod)(SecKeyRef); -typedef void (*SecKeyShowMethod)(SecKeyRef); -typedef OSStatus (*SecKeyRawSignMethod)(SecKeyRef key, SecPadding padding, - const uint8_t *dataToSign, size_t dataToSignLen, - uint8_t *sig, size_t *sigLen); -typedef OSStatus (*SecKeyRawVerifyMethod)( - SecKeyRef key, SecPadding padding, const uint8_t *signedData, - size_t signedDataLen, const uint8_t *sig, size_t sigLen); -typedef OSStatus (*SecKeyEncryptMethod)(SecKeyRef key, SecPadding padding, - const uint8_t *plainText, size_t plainTextLen, - uint8_t *cipherText, size_t *cipherTextLen); -typedef OSStatus (*SecKeyDecryptMethod)(SecKeyRef key, SecPadding padding, - const uint8_t *cipherText, size_t cipherTextLen, - uint8_t *plainText, size_t *plainTextLen); -typedef size_t (*SecKeyBlockSizeMethod)(SecKeyRef key); -typedef CFDictionaryRef (*SecKeyCopyDictionaryMethod)(SecKeyRef key); - -typedef struct { - const char *name; - SecKeyInitMethod init; - SecKeyCopyMethod copy; - SecKeyDestroyMethod destroy; - SecKeyDeleteMethod remove; - SecKeyShowMethod show; - SecKeyRawSignMethod rawSign; - SecKeyRawVerifyMethod rawVerify; - SecKeyEncryptMethod encrypt; - SecKeyDecryptMethod decrypt; - SecKeyBlockSizeMethod blockSize; - SecKeyCopyDictionaryMethod copyDictionary; - /* If known, the number of bytes to allocate for the key field in the SecKey struct. */ - int extraBytes; -} SecKeyDescriptor; - -/*! - @function SecKeyGetAlgorithmID - @abstract Returns a pointer to a CSSM_X509_ALGORITHM_IDENTIFIER structure for the given key. - @param key A key reference. - @param algid On return, a pointer to a CSSM_X509_ALGORITHM_IDENTIFIER structure. - @result A result code. See "Security Error Codes" (SecBase.h). -*/ -OSStatus SecKeyGetAlgorithmID(SecKeyRef key, const CSSM_X509_ALGORITHM_IDENTIFIER **algid) - DEPRECATED_IN_MAC_OS_X_VERSION_10_8_AND_LATER; - -enum { - kSecNullAlgorithmID = 0, - kSecRSAAlgorithmID = 1, - kSecDSAAlgorithmID = 2, /* unsupported, just here for reference. */ - kSecECDSAAlgorithmID = 3, -}; - -/*! - @function SecKeyGetAlgorithmId - @abstract Returns an enumerated constant value which identifies the algorithm for the given key. - @param key A key reference. - @result An algorithm identifier. -*/ -CFIndex SecKeyGetAlgorithmId(SecKeyRef key) - __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_NA); - -/*! - @function SecKeyGetStrengthInBits - @abstract Returns key strength in bits for the given key. - @param key A key reference. - @param algid A pointer to a CSSM_X509_ALGORITHM_IDENTIFIER structure, as returned from a call to SecKeyGetAlgorithmID. - @param strength On return, the key strength in bits. - @result A result code. See "Security Error Codes" (SecBase.h). -*/ -OSStatus SecKeyGetStrengthInBits(SecKeyRef key, const CSSM_X509_ALGORITHM_IDENTIFIER *algid, unsigned int *strength); - -/*! - @function SecKeyImportPair - @abstract Takes an asymmetric key pair and stores it in the keychain specified by the keychain parameter. - @param keychainRef A reference to the keychain in which to store the private and public key items. Specify NULL for the default keychain. - @param publicCssmKey A CSSM_KEY which is valid for the CSP returned by SecKeychainGetCSPHandle(). This may be a normal key or reference key. - @param privateCssmKey A CSSM_KEY which is valid for the CSP returned by SecKeychainGetCSPHandle(). This may be a normal key or reference key. - @param initialAccess A SecAccess object that determines the initial access rights to the private key. The public key is given an any/any acl by default. - @param publicKey Optional output pointer to the keychain item reference of the imported public key. The caller must call CFRelease on this value if it is returned. - @param privateKey Optional output pointer to the keychain item reference of the imported private key. The caller must call CFRelease on this value if it is returned. - @result A result code. See "Security Error Codes" (SecBase.h). - @deprecated in 10.5 and later. Use the SecKeychainItemImport function instead; see -*/ -OSStatus SecKeyImportPair( - SecKeychainRef keychainRef, - const CSSM_KEY *publicCssmKey, - const CSSM_KEY *privateCssmKey, - SecAccessRef initialAccess, - SecKeyRef* publicKey, - SecKeyRef* privateKey) - DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER; - -/*! - @function SecKeyCreate - @abstract Create a key reference from the supplied key data. - @param allocator CFAllocator to allocate the key data. Pass NULL to use the default allocator. - @param keyClass A descriptor for the particular class of key that is being created. - @param keyData Data from which to create the key. Specify the format of this data in the encoding parameter. - @param keyDataLength Length of the data pointed to by keyData. - @param encoding A value of type SecKeyEncoding which describes the format of keyData. - @result A key reference. - @discussion Warning: this function is NOT intended for use outside the Security stack in its current state. - IMPORTANT: on Mac OS X 10.5 and earlier, the SecKeyCreate function had a different parameter list. - The current parameter list matches the iPhone OS implementation. Existing clients of this function - on Mac OS X (and there should not be any outside the Security stack, per the warning above) must - migrate to the replacement function, SecKeyCreateWithCSSMKey. -*/ -SecKeyRef SecKeyCreate(CFAllocatorRef allocator, - const SecKeyDescriptor *keyClass, const uint8_t *keyData, - CFIndex keyDataLength, SecKeyEncoding encoding); - -/*! - @function SecKeyCreateWithCSSMKey - @abstract Generate a temporary floating key reference for a CSSM_KEY. - @param key A pointer to a CSSM_KEY structure. - @param keyRef On return, a key reference. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Warning: this function is NOT intended for use outside the Security stack in its current state. -*/ -OSStatus SecKeyCreateWithCSSMKey(const CSSM_KEY *key, SecKeyRef* keyRef); - -/*! - @enum Dictionary key constants for SecKeyGeneratePair API. - @discussion Predefined key constants used to get or set values in a dictionary. - @constant kSecPrivateKeyAttrs The value for this key is a CFDictionaryRef - containing attributes specific for the private key to be generated. - @constant kSecPublicKeyAttrs The value for this key is a CFDictionaryRef - containing attributes specific for the public key to be generated. -*/ -extern CFTypeRef kSecPrivateKeyAttrs; -extern CFTypeRef kSecPublicKeyAttrs; - -/*! - @function SecKeyGeneratePair - @abstract Generate a private/public keypair. - @param parameters A dictionary containing one or more key-value pairs. - See the discussion sections below for a complete overview of options. - @param publicKey On return, a SecKeyRef reference to the public key. - @param privateKey On return, a SecKeyRef reference to the private key. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion In order to generate a keypair the parameters dictionary must - at least contain the following keys: - - * kSecAttrKeyType with a value being kSecAttrKeyTypeRSA or any other - kSecAttrKeyType defined in SecItem.h - * kSecAttrKeySizeInBits with a value being a CFNumberRef or CFStringRef - containing the requested key size in bits. Example sizes for RSA - keys are: 512, 768, 1024, 2048. - - The values below may be set either in the top-level dictionary or in a - dictionary that is the value of the kSecPrivateKeyAttrs or - kSecPublicKeyAttrs key in the top-level dictionary. Setting these - attributes explicitly will override the defaults below. See SecItem.h - for detailed information on these attributes including the types of - the values. - - * kSecAttrLabel default NULL - * kSecAttrIsPermanent if this key is present and has a Boolean - value of true, the key or key pair will be added to the default - keychain. - * kSecAttrApplicationTag default NULL - * kSecAttrEffectiveKeySize default NULL same as kSecAttrKeySizeInBits - * kSecAttrCanEncrypt default false for private keys, true for public keys - * kSecAttrCanDecrypt default true for private keys, false for public keys - * kSecAttrCanDerive default true - * kSecAttrCanSign default true for private keys, false for public keys - * kSecAttrCanVerify default false for private keys, true for public keys - * kSecAttrCanWrap default false for private keys, true for public keys - * kSecAttrCanUnwrap default true for private keys, false for public keys - -*/ -OSStatus SecKeyGeneratePair(CFDictionaryRef parameters, - SecKeyRef *publicKey, SecKeyRef *privateKey); - - -/*! - @function SecKeyRawSign - @abstract Given a private key and data to sign, generate a digital signature. - @param key Private key with which to sign. - @param padding See Padding Types above, typically kSecPaddingPKCS1SHA1. - @param dataToSign The data to be signed, typically the digest of the actual data. - @param dataToSignLen Length of dataToSign in bytes. - @param sig Pointer to buffer in which the signature will be returned. - @param sigLen IN/OUT maximum length of sig buffer on input, actualy length of sig on output. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion If the padding argument is kSecPaddingPKCS1, PKCS1 padding - will be performed prior to signing. If this argument is kSecPaddingNone, - the incoming data will be signed "as is". - - When PKCS1 padding is performed, the maximum length of data that can - be signed is the value returned by SecKeyGetBlockSize() - 11. - - NOTE: The behavior this function with kSecPaddingNone is undefined if the - first byte of dataToSign is zero; there is no way to verify leading zeroes - as they are discarded during the calculation. - - If you want to generate a proper PKCS1 style signature with DER encoding of - the digest type - and the dataToSign is a SHA1 digest - use kSecPaddingPKCS1SHA1. -*/ -OSStatus SecKeyRawSign( - SecKeyRef key, - SecPadding padding, - const uint8_t *dataToSign, - size_t dataToSignLen, - uint8_t *sig, - size_t *sigLen); - - -/*! - @function SecKeyRawVerify - @abstract Given a public key, data which has been signed, and a signature, verify the signature. - @param key Public key with which to verify the signature. - @param padding See Padding Types above, typically kSecPaddingPKCS1SHA1. - @param signedData The data over which sig is being verified, typically the digest of the actual data. - @param signedDataLen Length of signedData in bytes. - @param sig Pointer to the signature to verify. - @param sigLen Length of sig in bytes. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion If the padding argument is kSecPaddingPKCS1, PKCS1 padding - will be checked during verification. If this argument is kSecPaddingNone, - the incoming data will be compared directly to sig. - - If you are verifying a proper PKCS1-style signature, with DER encoding of the digest - type - and the signedData is a SHA1 digest - use kSecPaddingPKCS1SHA1. -*/ -OSStatus SecKeyRawVerify( - SecKeyRef key, - SecPadding padding, - const uint8_t *signedData, - size_t signedDataLen, - const uint8_t *sig, - size_t sigLen); - - -/*! - @function SecKeyEncrypt - @abstract Encrypt a block of plaintext. - @param key Public key with which to encrypt the data. - @param padding See Padding Types above, typically kSecPaddingPKCS1. - @param plainText The data to encrypt. - @param plainTextLen Length of plainText in bytes, this must be less - or equal to the value returned by SecKeyGetBlockSize(). - @param cipherText Pointer to the output buffer. - @param cipherTextLen On input, specifies how much space is available at - cipherText; on return, it is the actual number of cipherText bytes written. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion If the padding argument is kSecPaddingPKCS1, PKCS1 padding - will be performed prior to encryption. If this argument is kSecPaddingNone, - the incoming data will be encrypted "as is". - - When PKCS1 padding is performed, the maximum length of data that can - be encrypted is the value returned by SecKeyGetBlockSize() - 11. - - When memory usage is a critical issue, note that the input buffer - (plainText) can be the same as the output buffer (cipherText). -*/ -OSStatus SecKeyEncrypt( - SecKeyRef key, - SecPadding padding, - const uint8_t *plainText, - size_t plainTextLen, - uint8_t *cipherText, - size_t *cipherTextLen); - - -/*! - @function SecKeyDecrypt - @abstract Decrypt a block of ciphertext. - @param key Private key with which to decrypt the data. - @param padding See SecPadding types above; typically kSecPaddingPKCS1. - @param cipherText The data to decrypt. - @param cipherTextLen Length of cipherText in bytes; this must be less - or equal to the value returned by SecKeyGetBlockSize(). - @param plainText Pointer to the output buffer. - @param plainTextLen On input, specifies how much space is available at - plainText; on return, it is the actual number of plainText bytes written. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion If the padding argument is kSecPaddingPKCS1, PKCS1 padding - will be removed after decryption. If this argument is kSecPaddingNone, - the decrypted data will be returned "as is". - - When memory usage is a critical issue, note that the input buffer - (plainText) can be the same as the output buffer (cipherText). -*/ -OSStatus SecKeyDecrypt( - SecKeyRef key, /* Private key */ - SecPadding padding, /* kSecPaddingNone, kSecPaddingPKCS1, kSecPaddingOAEP */ - const uint8_t *cipherText, - size_t cipherTextLen, /* length of cipherText */ - uint8_t *plainText, - size_t *plainTextLen); /* IN/OUT */ - -OSStatus SecKeyVerifyDigest( - SecKeyRef key, /* Private key */ - const SecAsn1AlgId *algId, /* algorithm oid/params */ - const uint8_t *digestData, /* signature over this digest */ - size_t digestDataLen, /* length of dataToDigest */ - const uint8_t *sig, /* signature to verify */ - size_t sigLen); /* length of sig */ - -OSStatus SecKeySignDigest( - SecKeyRef key, /* Private key */ - const SecAsn1AlgId *algId, /* algorithm oid/params */ - const uint8_t *digestData, /* signature over this digest */ - size_t digestDataLen, /* length of digestData */ - uint8_t *sig, /* signature, RETURNED */ - size_t *sigLen); /* IN/OUT */ - - -/* These are the named curves we support. These values come from RFC 4492 - section 5.1.1, with the exception of SSL_Curve_None which means - "ECDSA not negotiated". */ -typedef enum -{ - kSecECCurveNone = -1, - kSecECCurveSecp256r1 = 23, - kSecECCurveSecp384r1 = 24, - kSecECCurveSecp521r1 = 25 -} SecECNamedCurve; - -/* Return a named curve enum for ecPrivateKey. */ -SecECNamedCurve SecECKeyGetNamedCurve(SecKeyRef ecPrivateKey); -CFDataRef SecECKeyCopyPublicBits(SecKeyRef key); - -/* Given an RSA public key in encoded form return a SecKeyRef representing - that key. Supported encodings are kSecKeyEncodingPkcs1. */ -SecKeyRef SecKeyCreateRSAPublicKey(CFAllocatorRef allocator, - const uint8_t *keyData, CFIndex keyDataLength, - SecKeyEncoding encoding); - -CFDataRef SecKeyCopyModulus(SecKeyRef rsaPublicKey); -CFDataRef SecKeyCopyExponent(SecKeyRef rsaPublicKey); - -/*! - @function SecKeyCopyPublicBytes - @abstract Gets the bits of a public key - @param key Key to retrieve the bits. - @param publicBytes An out parameter to receive the public key bits - @result Errors if any when retrieving the public key bits.. - */ -OSStatus SecKeyCopyPublicBytes(SecKeyRef key, CFDataRef* publicBytes); - -/*! - @function SecKeyCreatePublicFromPrivate - @abstract Create a public SecKeyRef from a private SecKeyRef - @param privateKey The private SecKeyRef for which you want the public key - @result A public SecKeyRef, or NULL if the conversion failed - @discussion This is a "best attempt" function, hence the SPI nature. If the public - key bits are not in memory, it attempts to load from the keychain. If the public - key was not tracked on the keychain, it will fail. -*/ -SecKeyRef SecKeyCreatePublicFromPrivate(SecKeyRef privateKey); - -/*! - @function SecKeyCreateFromPublicData -*/ -SecKeyRef SecKeyCreateFromPublicData(CFAllocatorRef allocator, CFIndex algorithmID, CFDataRef publicBytes); - -OSStatus SecKeyRawVerifyOSX( - SecKeyRef key, - SecPadding padding, - const uint8_t *signedData, - size_t signedDataLen, - const uint8_t *sig, - size_t sigLen); - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECKEYPRIV_H_ */ - diff --git a/libsecurity_keychain/lib/SecKeychainPriv.h b/libsecurity_keychain/lib/SecKeychainPriv.h deleted file mode 100644 index aa7ce0b2..00000000 --- a/libsecurity_keychain/lib/SecKeychainPriv.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _SECURITY_SECKEYCHAINPRIV_H_ -#define _SECURITY_SECKEYCHAINPRIV_H_ - -#include -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -enum {kSecKeychainEnteredBatchModeEvent = 14, - kSecKeychainLeftBatchModeEvent = 15}; -enum {kSecKeychainEnteredBatchModeEventMask = 1 << kSecKeychainEnteredBatchModeEvent, - kSecKeychainLeftBatchModeEventMask = 1 << kSecKeychainLeftBatchModeEvent}; - - -/* Keychain management */ -OSStatus SecKeychainCreateNew(SecKeychainRef keychainRef, UInt32 passwordLength, const char* inPassword); -OSStatus SecKeychainMakeFromFullPath(const char *fullPathName, SecKeychainRef *keychainRef); -OSStatus SecKeychainIsValid(SecKeychainRef keychainRef, Boolean* isValid); -OSStatus SecKeychainChangePassword(SecKeychainRef keychainRef, UInt32 oldPasswordLength, const void *oldPassword, UInt32 newPasswordLength, const void *newPassword); -OSStatus SecKeychainOpenWithGuid(const CSSM_GUID *guid, uint32 subserviceId, uint32 subserviceType, const char* dbName, const CSSM_NET_ADDRESS *dbLocation, SecKeychainRef *keychain); -OSStatus SecKeychainSetBatchMode (SecKeychainRef kcRef, Boolean mode, Boolean rollback); - -/* Keychain list management */ -UInt16 SecKeychainListGetCount(void); -OSStatus SecKeychainListCopyKeychainAtIndex(UInt16 index, SecKeychainRef *keychainRef); -OSStatus SecKeychainListRemoveKeychain(SecKeychainRef *keychainRef); -OSStatus SecKeychainRemoveFromSearchList(SecKeychainRef keychainRef); - -/* Login keychain support */ -OSStatus SecKeychainLogin(UInt32 nameLength, const void* name, UInt32 passwordLength, const void* password); -OSStatus SecKeychainStash(); -OSStatus SecKeychainLogout(); -OSStatus SecKeychainCopyLogin(SecKeychainRef *keychainRef); -OSStatus SecKeychainResetLogin(UInt32 passwordLength, const void* password, Boolean resetSearchList); - -OSStatus SecKeychainVerifyKeyStorePassphrase(uint32_t retries); -OSStatus SecKeychainChangeKeyStorePassphrase(); - -/* Keychain synchronization */ -enum { - kSecKeychainNotSynchronized = 0, - kSecKeychainSynchronizedWithDotMac = 1 -}; -typedef UInt32 SecKeychainSyncState; - -OSStatus SecKeychainCopySignature(SecKeychainRef keychainRef, CFDataRef *keychainSignature); -OSStatus SecKeychainCopyBlob(SecKeychainRef keychainRef, CFDataRef *dbBlob); -OSStatus SecKeychainRecodeKeychain(SecKeychainRef keychainRef, CFArrayRef dbBlobArray, CFDataRef extraData); -OSStatus SecKeychainCreateWithBlob(const char* fullPathName, CFDataRef dbBlob, SecKeychainRef *kcRef); - -/* Keychain list manipulation */ -OSStatus SecKeychainAddDBToKeychainList (SecPreferencesDomain domain, const char* dbName, const CSSM_GUID *guid, uint32 subServiceType); -OSStatus SecKeychainDBIsInKeychainList (SecPreferencesDomain domain, const char* dbName, const CSSM_GUID *guid, uint32 subServiceType); -OSStatus SecKeychainRemoveDBFromKeychainList (SecPreferencesDomain domain, const char* dbName, const CSSM_GUID *guid, uint32 subServiceType); - -/* server operation (keychain inhibit) */ -void SecKeychainSetServerMode(); - -/* special calls */ -OSStatus SecKeychainCleanupHandles(); -OSStatus SecKeychainSystemKeychainCheckWouldDeadlock(); - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECKEYCHAINPRIV_H_ */ diff --git a/libsecurity_keychain/lib/SecPolicy.cpp b/libsecurity_keychain/lib/SecPolicy.cpp deleted file mode 100644 index bfbe5285..00000000 --- a/libsecurity_keychain/lib/SecPolicy.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Copyright (c) 2002-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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "SecBridge.h" - - -// String constant declarations - -#define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); - -SEC_CONST_DECL (kSecPolicyAppleX509Basic, "1.2.840.113635.100.1.2"); -SEC_CONST_DECL (kSecPolicyAppleSSL, "1.2.840.113635.100.1.3"); -SEC_CONST_DECL (kSecPolicyAppleSMIME, "1.2.840.113635.100.1.8"); -SEC_CONST_DECL (kSecPolicyAppleEAP, "1.2.840.113635.100.1.9"); -SEC_CONST_DECL (kSecPolicyAppleIPsec, "1.2.840.113635.100.1.11"); -SEC_CONST_DECL (kSecPolicyAppleiChat, "1.2.840.113635.100.1.12"); -SEC_CONST_DECL (kSecPolicyApplePKINITClient, "1.2.840.113635.100.1.14"); -SEC_CONST_DECL (kSecPolicyApplePKINITServer, "1.2.840.113635.100.1.15"); -SEC_CONST_DECL (kSecPolicyAppleCodeSigning, "1.2.840.113635.100.1.16"); -SEC_CONST_DECL (kSecPolicyApplePackageSigning, "1.2.840.113635.100.1.17"); -SEC_CONST_DECL (kSecPolicyAppleIDValidation, "1.2.840.113635.100.1.18"); -SEC_CONST_DECL (kSecPolicyMacAppStoreReceipt, "1.2.840.113635.100.1.19"); -SEC_CONST_DECL (kSecPolicyAppleTimeStamping, "1.2.840.113635.100.1.20"); -SEC_CONST_DECL (kSecPolicyAppleRevocation, "1.2.840.113635.100.1.21"); -SEC_CONST_DECL (kSecPolicyApplePassbookSigning, "1.2.840.113635.100.1.22"); -SEC_CONST_DECL (kSecPolicyAppleMobileStore, "1.2.840.113635.100.1.23"); -SEC_CONST_DECL (kSecPolicyAppleEscrowService, "1.2.840.113635.100.1.24"); -SEC_CONST_DECL (kSecPolicyAppleProfileSigner, "1.2.840.113635.100.1.25"); -SEC_CONST_DECL (kSecPolicyAppleQAProfileSigner, "1.2.840.113635.100.1.26"); -SEC_CONST_DECL (kSecPolicyAppleTestMobileStore, "1.2.840.113635.100.1.27"); - - -SEC_CONST_DECL (kSecPolicyOid, "SecPolicyOid"); -SEC_CONST_DECL (kSecPolicyName, "SecPolicyName"); -SEC_CONST_DECL (kSecPolicyClient, "SecPolicyClient"); -SEC_CONST_DECL (kSecPolicyRevocationFlags, "SecPolicyRevocationFlags"); -SEC_CONST_DECL (kSecPolicyTeamIdentifier, "SecPolicyTeamIdentifier"); - -SEC_CONST_DECL (kSecPolicyKU_DigitalSignature, "CE_KU_DigitalSignature"); -SEC_CONST_DECL (kSecPolicyKU_NonRepudiation, "CE_KU_NonRepudiation"); -SEC_CONST_DECL (kSecPolicyKU_KeyEncipherment, "CE_KU_KeyEncipherment"); -SEC_CONST_DECL (kSecPolicyKU_DataEncipherment, "CE_KU_DataEncipherment"); -SEC_CONST_DECL (kSecPolicyKU_KeyAgreement, "CE_KU_KeyAgreement"); -SEC_CONST_DECL (kSecPolicyKU_KeyCertSign, "CE_KU_KeyCertSign"); -SEC_CONST_DECL (kSecPolicyKU_CRLSign, "CE_KU_CRLSign"); -SEC_CONST_DECL (kSecPolicyKU_EncipherOnly, "CE_KU_EncipherOnly"); -SEC_CONST_DECL (kSecPolicyKU_DecipherOnly, "CE_KU_DecipherOnly"); - -// Private functions - -SecPolicyRef SecPolicyCreateWithSecAsn1Oid(SecAsn1Oid *oidPtr); -extern "C" { CFArrayRef SecPolicyCopyEscrowRootCertificates(void); } - -// -// CF boilerplate -// -CFTypeID -SecPolicyGetTypeID(void) -{ - BEGIN_SECAPI - return gTypes().Policy.typeID; - END_SECAPI1(_kCFRuntimeNotATypeID) -} - - -// -// Sec API bridge functions -// -OSStatus -SecPolicyGetOID(SecPolicyRef policyRef, CSSM_OID* oid) -{ - BEGIN_SECAPI - Required(oid) = Policy::required(policyRef)->oid(); - END_SECAPI -} - -OSStatus -SecPolicyGetValue(SecPolicyRef policyRef, CSSM_DATA* value) -{ - BEGIN_SECAPI - Required(value) = Policy::required(policyRef)->value(); - END_SECAPI -} - -CFDictionaryRef -SecPolicyCopyProperties(SecPolicyRef policyRef) -{ - /* can't use SECAPI macros, since this function does not return OSStatus */ - CFDictionaryRef result = NULL; - try { - result = Policy::required(policyRef)->properties(); - } - catch (...) { - if (result) { - CFRelease(result); - result = NULL; - } - }; - return result; -} - -OSStatus -SecPolicySetValue(SecPolicyRef policyRef, const CSSM_DATA *value) -{ - BEGIN_SECAPI - Required(value); - const CssmData newValue(value->Data, value->Length); - Policy::required(policyRef)->setValue(newValue); - END_SECAPI -} - -OSStatus -SecPolicySetProperties(SecPolicyRef policyRef, CFDictionaryRef properties) -{ - BEGIN_SECAPI - Policy::required(policyRef)->setProperties(properties); - END_SECAPI -} - -OSStatus -SecPolicyGetTPHandle(SecPolicyRef policyRef, CSSM_TP_HANDLE* tpHandle) -{ - BEGIN_SECAPI - Required(tpHandle) = Policy::required(policyRef)->tp()->handle(); - END_SECAPI -} - -OSStatus -SecPolicyCopyAll(CSSM_CERT_TYPE certificateType, CFArrayRef* policies) -{ - BEGIN_SECAPI - Required(policies); - CFMutableArrayRef currPolicies = NULL; - currPolicies = CFArrayCreateMutable(NULL, 0, NULL); - if ( currPolicies ) - { - SecPointer cursor(new PolicyCursor(NULL, NULL)); - SecPointer policy; - while ( cursor->next(policy) ) /* copies the next policy */ - { - CFArrayAppendValue(currPolicies, policy->handle()); /* 'SecPolicyRef' appended */ - CFRelease(policy->handle()); /* refcount bumped up when appended to array */ - } - *policies = CFArrayCreateCopy(NULL, currPolicies); - CFRelease(currPolicies); - CFRelease(cursor->handle()); - } - END_SECAPI -} - -OSStatus -SecPolicyCopy(CSSM_CERT_TYPE certificateType, const CSSM_OID *policyOID, SecPolicyRef* policy) -{ - Required(policy); - Required(policyOID); - - SecPolicySearchRef srchRef = NULL; - OSStatus ortn; - - ortn = SecPolicySearchCreate(certificateType, policyOID, NULL, &srchRef); - if(ortn) { - return ortn; - } - ortn = SecPolicySearchCopyNext(srchRef, policy); - CFRelease(srchRef); - return ortn; -} - -/* new in 10.6 */ -SecPolicyRef -SecPolicyCreateBasicX509(void) -{ - // return a SecPolicyRef object for the X.509 Basic policy - SecPolicyRef policy = nil; - SecPolicySearchRef policySearch = nil; - OSStatus status = SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_X509_BASIC, NULL, &policySearch); - if (!status) { - status = SecPolicySearchCopyNext(policySearch, &policy); - } - if (policySearch) { - CFRelease(policySearch); - } - return policy; -} - -/* new in 10.6 */ -SecPolicyRef -SecPolicyCreateSSL(Boolean server, CFStringRef hostname) -{ - // return a SecPolicyRef object for the SSL policy, given hostname and client options - SecPolicyRef policy = nil; - SecPolicySearchRef policySearch = nil; - OSStatus status = SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_SSL, NULL, &policySearch); - if (!status) { - status = SecPolicySearchCopyNext(policySearch, &policy); - } - if (!status && policy) { - // set options for client-side or server-side policy evaluation - char *strbuf = NULL; - const char *hostnamestr = NULL; - if (hostname) { - hostnamestr = CFStringGetCStringPtr(hostname, kCFStringEncodingUTF8); - if (hostnamestr == NULL) { - CFIndex maxLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(hostname), kCFStringEncodingUTF8) + 1; - strbuf = (char *)malloc(maxLen); - if (CFStringGetCString(hostname, strbuf, maxLen, kCFStringEncodingUTF8)) { - hostnamestr = strbuf; - } - } - } - uint32 hostnamelen = (hostnamestr) ? (uint32)strlen(hostnamestr) : 0; - uint32 flags = (!server) ? CSSM_APPLE_TP_SSL_CLIENT : 0; - CSSM_APPLE_TP_SSL_OPTIONS opts = {CSSM_APPLE_TP_SSL_OPTS_VERSION, hostnamelen, hostnamestr, flags}; - CSSM_DATA data = {sizeof(opts), (uint8*)&opts}; - SecPolicySetValue(policy, &data); - - if (strbuf) { - free(strbuf); - } - } - if (policySearch) { - CFRelease(policySearch); - } - return policy; -} - -SecPolicyRef -SecPolicyCreateWithSecAsn1Oid(SecAsn1Oid *oidPtr) -{ - SecPolicyRef policy = NULL; - try { - SecPointer policyObj; - PolicyCursor::policy(oidPtr, policyObj); - policy = policyObj->handle(); - } - catch (...) {} - - return policy; -} - -/* new in 10.7 */ -SecPolicyRef -SecPolicyCreateWithOID(CFTypeRef policyOID) -{ - // for now, we only accept the policy constants that are defined in SecPolicy.h - CFStringRef oidStr = (CFStringRef)policyOID; - CSSM_OID *oidPtr = NULL; - SecPolicyRef policy = NULL; - struct oidmap_entry_t { - const CFTypeRef oidstr; - const SecAsn1Oid *oidptr; - }; - const oidmap_entry_t oidmap[] = { - { kSecPolicyAppleX509Basic, &CSSMOID_APPLE_X509_BASIC }, - { kSecPolicyAppleSSL, &CSSMOID_APPLE_TP_SSL }, - { kSecPolicyAppleSMIME, &CSSMOID_APPLE_TP_SMIME }, - { kSecPolicyAppleEAP, &CSSMOID_APPLE_TP_EAP }, - { kSecPolicyAppleIPsec, &CSSMOID_APPLE_TP_IP_SEC }, - { kSecPolicyAppleiChat, &CSSMOID_APPLE_TP_ICHAT }, - { kSecPolicyApplePKINITClient, &CSSMOID_APPLE_TP_PKINIT_CLIENT }, - { kSecPolicyApplePKINITServer, &CSSMOID_APPLE_TP_PKINIT_SERVER }, - { kSecPolicyAppleCodeSigning, &CSSMOID_APPLE_TP_CODE_SIGNING }, - { kSecPolicyMacAppStoreReceipt, &CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT }, - { kSecPolicyAppleIDValidation, &CSSMOID_APPLE_TP_APPLEID_SHARING }, - { kSecPolicyAppleTimeStamping, &CSSMOID_APPLE_TP_TIMESTAMPING }, - { kSecPolicyAppleRevocation, &CSSMOID_APPLE_TP_REVOCATION }, - { kSecPolicyApplePassbookSigning, &CSSMOID_APPLE_TP_PASSBOOK_SIGNING }, - { kSecPolicyAppleMobileStore, &CSSMOID_APPLE_TP_MOBILE_STORE }, - { kSecPolicyAppleEscrowService, &CSSMOID_APPLE_TP_ESCROW_SERVICE }, - { kSecPolicyAppleProfileSigner, &CSSMOID_APPLE_TP_PROFILE_SIGNING }, - { kSecPolicyAppleQAProfileSigner, &CSSMOID_APPLE_TP_QA_PROFILE_SIGNING }, - { kSecPolicyAppleTestMobileStore, &CSSMOID_APPLE_TP_TEST_MOBILE_STORE }, - }; - unsigned int i, oidmaplen = sizeof(oidmap) / sizeof(oidmap_entry_t); - for (i=0; i -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -/*! - @enum Policy Constants - @discussion Predefined constants used to specify a policy. - @constant kSecPolicyAppleX509Basic - @constant kSecPolicyAppleSSL - @constant kSecPolicyAppleSMIME - @constant kSecPolicyAppleEAP - @constant kSecPolicyAppleIPsec - @constant kSecPolicyAppleiChat - @constant kSecPolicyApplePKINITClient - @constant kSecPolicyApplePKINITServer - @constant kSecPolicyAppleCodeSigning - @constant kSecPolicyMacAppStoreReceipt - @constant kSecPolicyAppleIDValidation - @constant kSecPolicyAppleTimeStamping - @constant kSecPolicyAppleRevocation - @constant kSecPolicyApplePassbookSigning -*/ -extern CFTypeRef kSecPolicyAppleX509Basic - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleSSL - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleSMIME - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleEAP - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleIPsec - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleiChat - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); -extern CFTypeRef kSecPolicyApplePKINITClient - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyApplePKINITServer - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyAppleCodeSigning - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPolicyMacAppStoreReceipt - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyAppleIDValidation - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleTimeStamping - __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleRevocation - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecPolicyApplePassbookSigning - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - -/*! - @enum Policy Value Constants - @abstract Predefined property key constants used to get or set values in - a dictionary for a policy instance. - @discussion - All policies will have the following read-only value: - kSecPolicyOid (the policy object identifier) - - Additional policy values which your code can optionally set: - kSecPolicyName (name which must be matched) - kSecPolicyClient (evaluate for client, rather than server) - kSecPolicyRevocationFlags (only valid for a revocation policy) - - @constant kSecPolicyOid Specifies the policy OID (value is a CFStringRef) - @constant kSecPolicyName Specifies a CFStringRef (or CFArrayRef of same) - containing a name which must be matched in the certificate to satisfy - this policy. For SSL/TLS, EAP, and IPSec policies, this specifies the - server name which must match the common name of the certificate. - For S/MIME, this specifies the RFC822 email address. - For Passbook signing, this specifies the pass signer. - @constant kSecPolicyClient Specifies a CFBooleanRef value that indicates - this evaluation should be for a client certificate. If not set (or - false), the policy evaluates the certificate as a server certificate. - @constant kSecPolicyRevocationFlags Specifies a CFNumberRef that holds a - kCFNumberCFIndexType bitmask value. See "Revocation Policy Constants" - for a description of individual bits in this value. - @constant kSecPolicyTeamIdentifier Specifies a CFStringRef containing a - team identifier which must be matched in the certificate to satisfy - this policy. For the Passbook signing policy, this string must match - the Organizational Unit field of the certificate subject. - */ -extern CFTypeRef kSecPolicyOid - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPolicyName - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPolicyClient - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPolicyRevocationFlags - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecPolicyTeamIdentifier - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - - -/*! - @function SecPolicyGetTypeID - @abstract Returns the type identifier of SecPolicy instances. - @result The CFTypeID of SecPolicy instances. -*/ -CFTypeID SecPolicyGetTypeID(void) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -/*! - @function SecPolicyCopyProperties - @abstract Returns a dictionary of this policy's properties. - @param policyRef A policy reference. - @result A properties dictionary. See "Policy Value Constants" for a list - of currently defined property keys. It is the caller's responsibility to - CFRelease this reference when it is no longer needed. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function returns the properties for a policy, as set by the - policy's construction function or by a prior call to SecPolicySetProperties. -*/ -CFDictionaryRef SecPolicyCopyProperties(SecPolicyRef policyRef) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); - -/*! - @function SecPolicyCreateBasicX509 - @abstract Returns a policy object for the default X.509 policy. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -SecPolicyRef SecPolicyCreateBasicX509(void) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @function SecPolicyCreateSSL - @abstract Returns a policy object for evaluating SSL certificate chains. - @param server Passing true for this parameter creates a policy for SSL - server certificates. - @param hostname (Optional) If present, the policy will require the specified - hostname to match the hostname in the leaf certificate. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -SecPolicyRef SecPolicyCreateSSL(Boolean server, CFStringRef hostname) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @enum Revocation Policy Constants - @abstract Predefined constants which allow you to specify how revocation - checking will be performed for a trust evaluation. - @constant kSecRevocationOCSPMethod If this flag is set, perform revocation - checking using OCSP (Online Certificate Status Protocol). - @constant kSecRevocationCRLMethod If this flag is set, perform revocation - checking using the CRL (Certificate Revocation List) method. - @constant kSecRevocationPreferCRL If this flag is set, then CRL revocation - checking will be preferred over OCSP (by default, OCSP is preferred.) - Note that this flag only matters if both revocation methods are specified. - @constant kSecRevocationRequirePositiveResponse If this flag is set, then - the policy will fail unless a verified positive response is obtained. If - the flag is not set, revocation checking is done on a "best attempt" basis, - where failure to reach the server is not considered fatal. - @constant kSecRevocationNetworkAccessDisabled If this flag is set, then - no network access is performed; only locally cached replies are consulted. - @constant kSecRevocationUseAnyAvailableMethod Specifies that either - OCSP or CRL may be used, depending on the method(s) specified in the - certificate and the value of kSecRevocationPreferCRL. - */ -enum { - kSecRevocationOCSPMethod = (1 << 0), - kSecRevocationCRLMethod = (1 << 1), - kSecRevocationPreferCRL = (1 << 2), - kSecRevocationRequirePositiveResponse = (1 << 3), - kSecRevocationNetworkAccessDisabled = (1 << 4), - kSecRevocationUseAnyAvailableMethod = (kSecRevocationOCSPMethod | - kSecRevocationCRLMethod) -}; - -/*! - @function SecPolicyCreateRevocation - @abstract Returns a policy object for checking revocation of certificates. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. - @param revocationFlags Flags to specify revocation checking options. - @discussion Use this function to create a revocation policy with behavior - specified by revocationFlags. See the "Revocation Policy Constants" section - for a description of these flags. Note: it is usually not necessary to - create a revocation policy yourself unless you wish to override default - system behavior (e.g. to force a particular method, or to disable - revocation checking entirely.) -*/ -SecPolicyRef SecPolicyCreateRevocation(CFOptionFlags revocationFlags) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - -/*! - @function SecPolicyCreateWithProperties - @abstract Returns a policy object based on an object identifier for the - policy type. See the "Policy Constants" section for a list of defined - policy object identifiers. - @param policyIdentifier The identifier for the desired policy type. - @param properties (Optional) A properties dictionary. See "Policy Value - Constants" for a list of currently defined property keys. - @result The returned policy reference, or NULL if the policy could not be - created. -*/ -SecPolicyRef SecPolicyCreateWithProperties(CFTypeRef policyIdentifier, - CFDictionaryRef properties) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - - -/* - * Legacy functions (OS X only) - */ -#if TARGET_OS_MAC && !TARGET_OS_IPHONE -#include - -/*! - @enum Policy Value Constants (OS X) - @discussion Predefined property key constants used to get or set values in - a dictionary for a policy instance. - - Some policy values may specify CFBooleanRef key usage constraints: - kSecPolicyKU_DigitalSignature - kSecPolicyKU_NonRepudiation - kSecPolicyKU_KeyEncipherment - kSecPolicyKU_DataEncipherment - kSecPolicyKU_KeyAgreement - kSecPolicyKU_KeyCertSign - kSecPolicyKU_CRLSign - kSecPolicyKU_EncipherOnly - kSecPolicyKU_DecipherOnly - - kSecPolicyKU policy values define certificate-level key purposes, - in contrast to the key-level definitions in SecItem.h - - For example, a key in a certificate might be acceptable to use for - signing a CRL, but not for signing another certificate. In either - case, this key would have the ability to sign (i.e. kSecAttrCanSign - is true), but may only sign for specific purposes allowed by these - policy constants. Similarly, a public key might have the capability - to perform encryption or decryption, but the certificate in which it - resides might have a decipher-only certificate policy. - - These constants correspond to values defined in RFC 5280, section - 4.2.1.3 (Key Usage) which define the purpose of a key contained in a - certificate, in contrast to section 4.1.2.7 which define the uses that - a key is capable of. - - Note: these constants are not available on iOS. Your code should - avoid direct reliance on these values for making policy decisions - and use higher level policies where possible. - - @constant kSecPolicyKU_DigitalSignature Specifies that the certificate must - have a key usage that allows it to be used for signing. - @constant kSecPolicyKU_NonRepudiation Specifies that the certificate must - have a key usage that allows it to be used for non-repudiation. - @constant kSecPolicyKU_KeyEncipherment Specifies that the certificate must - have a key usage that allows it to be used for key encipherment. - @constant kSecPolicyKU_DataEncipherment Specifies that the certificate must - have a key usage that allows it to be used for data encipherment. - @constant kSecPolicyKU_KeyAgreement Specifies that the certificate must - have a key usage that allows it to be used for key agreement. - @constant kSecPolicyKU_KeyCertSign Specifies that the certificate must - have a key usage that allows it to be used for signing certificates. - @constant kSecPolicyKU_CRLSign Specifies that the certificate must - have a key usage that allows it to be used for signing CRLs. - @constant kSecPolicyKU_EncipherOnly Specifies that the certificate must - have a key usage that permits it to be used for encryption only. - @constant kSecPolicyKU_DecipherOnly Specifies that the certificate must - have a key usage that permits it to be used for decryption only. - */ -extern CFTypeRef kSecPolicyKU_DigitalSignature - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyKU_NonRepudiation - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyKU_KeyEncipherment - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyKU_DataEncipherment - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyKU_KeyAgreement - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyKU_KeyCertSign - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyKU_CRLSign - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyKU_EncipherOnly - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyKU_DecipherOnly - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/*! - @function SecPolicyCreateWithOID - @abstract Returns a policy object based on an object identifier for the - policy type. See the "Policy Constants" section for a list of defined - policy object identifiers. - @param policyOID The OID of the desired policy. - @result The returned policy reference, or NULL if the policy could not be - created. - @discussion This function is deprecated in Mac OS X 10.9 and later; - use SecPolicyCreateWithProperties (or a more specific policy creation - function) instead. -*/ -SecPolicyRef SecPolicyCreateWithOID(CFTypeRef policyOID) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecPolicyGetOID - @abstract Returns a policy's object identifier. - @param policyRef A policy reference. - @param oid On return, a pointer to the policy's object identifier. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in Mac OS X 10.7 and later; - use SecPolicyCopyProperties instead. -*/ -OSStatus SecPolicyGetOID(SecPolicyRef policyRef, CSSM_OID *oid) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecPolicyGetValue - @abstract Returns a policy's value. - @param policyRef A policy reference. - @param value On return, a pointer to the policy's value. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in Mac OS X 10.7 and later; - use SecPolicyCopyProperties instead. -*/ -OSStatus SecPolicyGetValue(SecPolicyRef policyRef, CSSM_DATA *value) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecPolicySetValue - @abstract Sets a policy's value. - @param policyRef A policy reference. - @param value The value to be set into the policy object, replacing any - previous value. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in Mac OS X 10.7 and later. Policy - instances should be considered read-only; in cases where your code would - consider changing properties of a policy, it should instead create a new - policy instance with the desired properties. -*/ -OSStatus SecPolicySetValue(SecPolicyRef policyRef, const CSSM_DATA *value) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecPolicySetProperties - @abstract Sets a policy's properties. - @param policyRef A policy reference. - @param properties A properties dictionary. See "Policy Value Constants" - for a list of currently defined property keys. This dictionary replaces the - policy's existing properties, if any. Note that the policy OID (specified - by kSecPolicyOid) is a read-only property of the policy and cannot be set. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in Mac OS X 10.9 and later. Policy - instances should be considered read-only; in cases where your code would - consider changing properties of a policy, it should instead create a new - policy instance with the desired properties. -*/ -OSStatus SecPolicySetProperties(SecPolicyRef policyRef, - CFDictionaryRef properties) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecPolicyGetTPHandle - @abstract Returns the CSSM trust policy handle for the given policy. - @param policyRef A policy reference. - @param tpHandle On return, a pointer to a value of type CSSM_TP_HANDLE. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in Mac OS X 10.7 and later. -*/ -OSStatus SecPolicyGetTPHandle(SecPolicyRef policyRef, CSSM_TP_HANDLE *tpHandle) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - -#endif /* TARGET_OS_MAC && !TARGET_OS_IPHONE */ - - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECPOLICY_H_ */ diff --git a/libsecurity_keychain/lib/SecPolicyPriv.h b/libsecurity_keychain/lib/SecPolicyPriv.h deleted file mode 100644 index cdc6fd8c..00000000 --- a/libsecurity_keychain/lib/SecPolicyPriv.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2003-2013 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/*! - @header SecPolicyPriv - Private part of SecPolicy.h -*/ - -#ifndef _SECURITY_SECPOLICYPRIV_H_ -#define _SECURITY_SECPOLICYPRIV_H_ - -#include -#include - - -#if defined(__cplusplus) -extern "C" { -#endif - -/*! - @enum Policy Constants (Private) - @discussion Predefined constants used to specify a policy. - @constant kSecPolicyAppleMobileStore - @constant kSecPolicyAppleEscrowService - @constant kSecPolicyAppleProfileSigner - @constant kSecPolicyAppleQAProfileSigner - @constant kSecPolicyAppleTestMobileStore - -*/ -extern CFTypeRef kSecPolicyAppleMobileStore - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleEscrowService - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleProfileSigner - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleQAProfileSigner - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleTestMobileStore - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - -/*! - @function SecPolicyCopy - @abstract Returns a copy of a policy reference based on certificate type and OID. - @param certificateType A certificate type. - @param policyOID The OID of the policy you want to find. This is a required parameter. See oidsalg.h to see a list of policy OIDs. - @param policy The returned policy reference. This is a required parameter. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in Mac OS X 10.7 and later; - to obtain a policy reference, use one of the SecPolicyCreate* functions in SecPolicy.h. -*/ -OSStatus SecPolicyCopy(CSSM_CERT_TYPE certificateType, const CSSM_OID *policyOID, SecPolicyRef* policy) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_3, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecPolicyCopyAll - @abstract Returns an array of all known policies based on certificate type. - @param certificateType A certificate type. This is a optional parameter. Pass CSSM_CERT_UNKNOWN if the certificate type is unknown. - @param policies The returned array of policies. This is a required parameter. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in Mac OS X 10.7 and later; - to obtain a policy reference, use one of the SecPolicyCreate* functions in SecPolicy.h. (Note: there is normally - no reason to iterate over multiple disjointed policies, except to provide a way to edit trust settings for each - policy, as is done in certain certificate UI views. In that specific case, your code should call SecPolicyCreateWithOID - for each desired policy from the list of supported OID constants in SecPolicy.h.) -*/ -OSStatus SecPolicyCopyAll(CSSM_CERT_TYPE certificateType, CFArrayRef* policies) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_3, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECPOLICYPRIV_H_ */ diff --git a/libsecurity_keychain/lib/SecRandom.h b/libsecurity_keychain/lib/SecRandom.h deleted file mode 100644 index e97381e3..00000000 --- a/libsecurity_keychain/lib/SecRandom.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2007-2009 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 SecRandom - The functions provided in SecRandom.h implement high-level accessors - to cryptographically secure random numbers. -*/ - -#ifndef _SECURITY_SECRANDOM_H_ -#define _SECURITY_SECRANDOM_H_ - -#include -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -/*! - @typedef SecRandomRef - @abstract Reference to a (psuedo) random number generator. -*/ -typedef const struct __SecRandom * SecRandomRef; - -/* This is a synonym for NULL, if you'd rather use a named constant. This - refers to a cryptographically secure random number generator. */ -extern const SecRandomRef kSecRandomDefault - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - -/*! - @function SecRandomCopyBytes - @abstract Return count random bytes in *bytes, allocated by the caller. - @result Return 0 on success or -1 if something went wrong, check errno - to find out the real error. -*/ -int SecRandomCopyBytes(SecRandomRef rnd, size_t count, uint8_t *bytes) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECRANDOM_H_ */ diff --git a/libsecurity_keychain/lib/SecTrust.h b/libsecurity_keychain/lib/SecTrust.h deleted file mode 100644 index 67f3fb03..00000000 --- a/libsecurity_keychain/lib/SecTrust.h +++ /dev/null @@ -1,686 +0,0 @@ -/* - * Copyright (c) 2002-2010,2012-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@ - */ - -/*! - @header SecTrust - The functions and data types in SecTrust implement trust computation - and allow the caller to apply trust decisions to the evaluation. - */ - -#ifndef _SECURITY_SECTRUST_H_ -#define _SECURITY_SECTRUST_H_ - -#include -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -/*! - @typedef SecTrustResultType - @abstract Specifies the trust result type. - @discussion SecTrustResultType results have two dimensions. They specify - both whether evaluation suceeded and whether this is because of a user - decision. The commonly expected result is kSecTrustResultUnspecified, - which indicates a positive result that wasn't decided by the user. The - common failure is kSecTrustResultRecoverableTrustFailure, which means a - negative result. kSecTrustResultProceed and kSecTrustResultDeny are the - positive and negative result respectively when decided by the user. User - decisions are persisted through the use of SecTrustCopyExceptions() and - SecTrustSetExceptions(). Finally, kSecTrustResultFatalTrustFailure is a - negative result that must not be circumvented. - @constant kSecTrustResultInvalid Indicates an invalid setting or result. - This result usually means that SecTrustEvaluate has not yet been called. - @constant kSecTrustResultProceed Indicates you may proceed. This value - may be returned by the SecTrustEvaluate function or stored as part of - the user trust settings. - @constant kSecTrustResultConfirm Indicates confirmation with the user - is required before proceeding. Important: this value is no longer returned - or supported by SecTrustEvaluate or the SecTrustSettings API starting in - OS X 10.5; its use is deprecated in OS X 10.9 and later, as well as in iOS. - @constant kSecTrustResultDeny Indicates a user-configured deny; do not - proceed. This value may be returned by the SecTrustEvaluate function - or stored as part of the user trust settings. - @constant kSecTrustResultUnspecified Indicates the evaluation succeeded - and the certificate is implicitly trusted, but user intent was not - explicitly specified. This value may be returned by the SecTrustEvaluate - function or stored as part of the user trust settings. - @constant kSecTrustResultRecoverableTrustFailure Indicates a trust policy - failure which can be overridden by the user. This value may be returned - by the SecTrustEvaluate function but not stored as part of the user - trust settings. - @constant kSecTrustResultFatalTrustFailure Indicates a trust failure - which cannot be overridden by the user. This value may be returned by the - SecTrustEvaluate function but not stored as part of the user trust - settings. - @constant kSecTrustResultOtherError Indicates a failure other than that - of trust evaluation. This value may be returned by the SecTrustEvaluate - function but not stored as part of the user trust settings. - */ - -typedef uint32_t SecTrustResultType; -enum { - kSecTrustResultInvalid = 0, - kSecTrustResultProceed = 1, - kSecTrustResultConfirm CF_ENUM_DEPRECATED(10_0, 10_9, NA, NA) = 2, - kSecTrustResultDeny = 3, - kSecTrustResultUnspecified = 4, - kSecTrustResultRecoverableTrustFailure = 5, - kSecTrustResultFatalTrustFailure = 6, - kSecTrustResultOtherError = 7 -}; - -/*! - @typedef SecTrustRef - @abstract CFType used for performing X.509 certificate trust evaluations. - */ -typedef struct __SecTrust *SecTrustRef; - -/*! - @enum Trust Property Constants - @discussion Predefined key constants used to obtain values in a - per-certificate dictionary of trust evaluation results, - as retrieved from a call to SecTrustCopyProperties. - @constant kSecPropertyTypeTitle Specifies a key whose value is a - CFStringRef containing the title (display name) of this certificate. - @constant kSecPropertyTypeError Specifies a key whose value is a - CFStringRef containing the reason for a trust evaluation failure. - */ -extern CFTypeRef kSecPropertyTypeTitle - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPropertyTypeError - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); - -/*! - @enum Trust Result Constants - @discussion Predefined key constants used to obtain values in a - dictionary of trust evaluation results for a certificate chain, - as retrieved from a call to SecTrustCopyResult. - @constant kSecTrustEvaluationDate - This key will be present if a trust evaluation has been performed - and results are available. Its value is a CFDateRef representing - when the evaluation for this trust object took place. - @constant kSecTrustExtendedValidation - This key will be present and have a value of kCFBooleanTrue - if this chain was validated for EV. - @constant kSecTrustOrganizationName - Organization name field of subject of leaf certificate. This - field is meant to be displayed to the user as the validated - name of the company or entity that owns the certificate if the - kSecTrustExtendedValidation key is present. - @constant kSecTrustResultValue - This key will be present if a trust evaluation has been performed. - Its value is a CFNumberRef representing the SecTrustResultType result - for the evaluation. - @constant kSecTrustRevocationChecked - This key will be present iff this chain had its revocation checked. - The value will be a kCFBooleanTrue if revocation checking was - successful and none of the certificates in the chain were revoked. - The value will be kCFBooleanFalse if no current revocation status - could be obtained for one or more certificates in the chain due - to connection problems or timeouts. This is a hint to a client - to retry revocation checking at a later time. - @constant kSecTrustRevocationValidUntilDate - This key will be present iff kSecTrustRevocationChecked has a - value of kCFBooleanTrue. The value will be a CFDateRef representing - the earliest date at which the revocation info for one of the - certificates in this chain might change. - */ -extern CFTypeRef kSecTrustEvaluationDate - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecTrustExtendedValidation - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecTrustOrganizationName - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecTrustResultValue - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecTrustRevocationChecked - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecTrustRevocationValidUntilDate - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - -#ifdef __BLOCKS__ -/*! - @typedef SecTrustCallback - @abstract Delivers the result from an asynchronous trust evaluation. - @param trustRef A reference to the trust object which has been evaluated. - @param trustResult The trust result of the evaluation. Additional status - information can be obtained by calling SecTrustCopyProperties(). - */ -typedef void (^SecTrustCallback)(SecTrustRef trustRef, SecTrustResultType trustResult); -#endif /* __BLOCKS__ */ - - -/*! - @function SecTrustGetTypeID - @abstract Returns the type identifier of SecTrust instances. - @result The CFTypeID of SecTrust instances. - */ -CFTypeID SecTrustGetTypeID(void) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -/*! - @function SecTrustCreateWithCertificates - @abstract Creates a trust object based on the given certificates and - policies. - @param certificates The group of certificates to verify. This can either - be a CFArrayRef of SecCertificateRef objects or a single SecCertificateRef - @param policies An array of one or more policies. You may pass a - SecPolicyRef to represent a single policy. - @param trust On return, a pointer to the trust management reference. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion If multiple policies are passed in, all policies must verify - for the chain to be considered valid. - */ -OSStatus SecTrustCreateWithCertificates(CFTypeRef certificates, - CFTypeRef policies, SecTrustRef *trust) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -/*! - @function SecTrustSetPolicies - @abstract Set the policies for which trust should be verified. - @param trust A trust reference. - @param policies An array of one or more policies. You may pass a - SecPolicyRef to represent a single policy. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function will invalidate the existing trust result, - requiring a fresh evaluation for the newly-set policies. - */ -OSStatus SecTrustSetPolicies(SecTrustRef trust, CFTypeRef policies) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_6_0); - -/*! - @function SecTrustCopyPolicies - @abstract Returns an array of policies used for this evaluation. - @param trust A reference to a trust object. - @param policies On return, an array of policies used by this trust. - Call the CFRelease function to release this reference. - @result A result code. See "Security Error Codes" (SecBase.h). - */ -OSStatus SecTrustCopyPolicies(SecTrustRef trust, CFArrayRef *policies) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_7_0); - -/*! - @function SecTrustSetNetworkFetchAllowed - @abstract Specifies whether a trust evaluation is permitted to fetch missing - intermediate certificates from the network. - @param trust A trust reference. - @param allowFetch If true, and a certificate's issuer is not present in the - trust reference but its network location is known, the evaluation is permitted - to attempt to download it automatically. Pass false to disable network fetch - for this trust evaluation. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion By default, network fetch of missing certificates is enabled if - the trust evaluation includes the SSL policy, otherwise it is disabled. - */ -OSStatus SecTrustSetNetworkFetchAllowed(SecTrustRef trust, - Boolean allowFetch) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - -/*! - @function SecTrustGetNetworkFetchAllowed - @abstract Returns whether a trust evaluation is permitted to fetch missing - intermediate certificates from the network. - @param trust A trust reference. - @param allowFetch On return, the boolean pointed to by this parameter is - set to true if the evaluation is permitted to download missing certificates. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion By default, network fetch of missing certificates is enabled if - the trust evaluation includes the SSL policy, otherwise it is disabled. - */ -OSStatus SecTrustGetNetworkFetchAllowed(SecTrustRef trust, - Boolean *allowFetch) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - -/*! - @function SecTrustSetAnchorCertificates - @abstract Sets the anchor certificates for a given trust. - @param trust A reference to a trust object. - @param anchorCertificates An array of anchor certificates. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Calling this function without also calling - SecTrustSetAnchorCertificatesOnly() will disable trusting any - anchors other than the ones in anchorCertificates. - */ -OSStatus SecTrustSetAnchorCertificates(SecTrustRef trust, - CFArrayRef anchorCertificates) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -/*! - @function SecTrustSetAnchorCertificatesOnly - @abstract Reenables trusting anchor certificates in addition to those - passed in via the SecTrustSetAnchorCertificates API. - @param trust A reference to a trust object. - @param anchorCertificatesOnly If true, disables trusting any anchors other - than the ones passed in via SecTrustSetAnchorCertificates(). If false, - the built in anchor certificates are also trusted. - @result A result code. See "Security Error Codes" (SecBase.h). - */ -OSStatus SecTrustSetAnchorCertificatesOnly(SecTrustRef trust, - Boolean anchorCertificatesOnly) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @function SecTrustCopyCustomAnchorCertificates - @abstract Returns an array of custom anchor certificates used by a given - trust, as set by a prior call to SecTrustSetAnchorCertificates, or NULL if - no custom anchors have been specified. - @param trust A reference to a trust object. - @param anchors On return, an array of custom anchor certificates (roots) - used by this trust, or NULL if no custom anchors have been specified. Call - the CFRelease function to release this reference. - @result A result code. See "Security Error Codes" (SecBase.h). - */ -OSStatus SecTrustCopyCustomAnchorCertificates(SecTrustRef trust, - CFArrayRef *anchors) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_7_0); - -/*! - @function SecTrustSetVerifyDate - @abstract Set the date for which the trust should be verified. - @param trust A reference to a trust object. - @param verifyDate The date for which to verify trust. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function lets you evaluate certificate validity for a - given date (for example, to determine if a signature was valid on the date - it was signed, even if the certificate has since expired.) If this function - is not called, the time at which SecTrustEvaluate() is called is used - implicitly as the verification time. - */ -OSStatus SecTrustSetVerifyDate(SecTrustRef trust, CFDateRef verifyDate) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -/*! - @function SecTrustGetVerifyTime - @abstract Returns the verify time. - @param trust A reference to the trust object being verified. - @result A CFAbsoluteTime value representing the time at which certificates - should be checked for validity. - @discussion This function retrieves the verification time for the given - trust reference, as set by a prior call to SecTrustSetVerifyDate(). If the - verification time has not been set, this function returns a value of 0, - indicating that the current date/time is implicitly used for verification. - */ -CFAbsoluteTime SecTrustGetVerifyTime(SecTrustRef trust) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @function SecTrustEvaluate - @abstract Evaluates a trust reference synchronously. - @param trust A reference to the trust object to evaluate. - @param result A pointer to a result type. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function will completely evaluate trust before returning, - possibly including network access to fetch intermediate certificates or to - perform revocation checking. Since this function can block during those - operations, you should call it from within a function that is placed on a - dispatch queue, or in a separate thread from your application's main - run loop. Alternatively, you can use the SecTrustEvaluateAsync function. - */ -OSStatus SecTrustEvaluate(SecTrustRef trust, SecTrustResultType *result) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -#ifdef __BLOCKS__ -/*! - @function SecTrustEvaluateAsync - @abstract Evaluates a trust reference asynchronously. - @param trust A reference to the trust object to evaluate. - @param queue A dispatch queue on which the result callback should be - executed. Pass NULL to use the current dispatch queue. - @param result A SecTrustCallback block which will be executed when the - trust evaluation is complete. - @result A result code. See "Security Error Codes" (SecBase.h). - */ -OSStatus SecTrustEvaluateAsync(SecTrustRef trust, - dispatch_queue_t queue, SecTrustCallback result) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -#endif - -/*! - @function SecTrustGetTrustResult - @param trust A reference to a trust object. - @param result A pointer to the result from the most recent call to - SecTrustEvaluate for this trust reference. If SecTrustEvaluate has not been - called or trust parameters have changed, the result is kSecTrustResultInvalid. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function replaces SecTrustGetResult for the purpose of - obtaining the current evaluation result of a given trust reference. - */ -OSStatus SecTrustGetTrustResult(SecTrustRef trust, - SecTrustResultType *result) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); - -/*! - @function SecTrustCopyPublicKey - @abstract Return the public key for a leaf certificate after it has - been evaluated. - @param trust A reference to the trust object which has been evaluated. - @result The certificate's public key, or NULL if it the public key could - not be extracted (this can happen with DSA certificate chains if the - parameters in the chain cannot be found). The caller is responsible - for calling CFRelease on the returned key when it is no longer needed. - */ -SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - -/*! - @function SecTrustGetCertificateCount - @abstract Returns the number of certificates in an evaluated certificate - chain. - @param trust A reference to a trust object. - @result The number of certificates in the trust chain, including the anchor. - @discussion Important: if the trust reference has not yet been evaluated, - this function will evaluate it first before returning. If speed is critical, - you may want to call SecTrustGetTrustResult first to make sure that a - result other than kSecTrustResultInvalid is present for the trust object. - */ -CFIndex SecTrustGetCertificateCount(SecTrustRef trust) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - -/*! - @function SecTrustGetCertificateAtIndex - @abstract Returns a certificate from the trust chain. - @param trust Reference to a trust object. - @param ix The index of the requested certificate. Indices run from 0 - (leaf) to the anchor (or last certificate found if no anchor was found). - The leaf cert (index 0) is always present regardless of whether the trust - reference has been evaluated or not. - @result A SecCertificateRef for the requested certificate. - */ -SecCertificateRef SecTrustGetCertificateAtIndex(SecTrustRef trust, CFIndex ix) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - -/*! - @function SecTrustCopyExceptions - @abstract Returns an opaque cookie which will allow future evaluations - of the current certificate to succeed. - @param trust A reference to an evaluated trust object. - @result An opaque cookie which when passed to SecTrustSetExceptions() will - cause a call to SecTrustEvaluate() return kSecTrustResultProceed. This - will happen upon subsequent evaluation of the current certificate unless - some new error starts happening that wasn't being reported when the cookie - was returned from this function (for example, if the certificate expires - then evaluation will start failing again until a new cookie is obtained.) - @discussion Normally this API should only be called once the errors have - been presented to the user and the user decided to trust the current - certificate chain regardless of the errors being presented, for the - current application/server/protocol combination. - */ -CFDataRef SecTrustCopyExceptions(SecTrustRef trust) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); - -/*! - @function SecTrustSetExceptions - @abstract Set a trust cookie to be used for evaluating this certificate chain. - @param trust A reference to a trust object. - @param exceptions An exceptions cookie as returned by a call to - SecTrustCopyExceptions() in the past. - @result Upon calling SecTrustEvaluate(), any failures that where present at the - time the exceptions object was created are ignored, and instead of returning - kSecTrustResultRecoverableTrustFailure, kSecTrustResultProceed will be returned - (if the certificate for which exceptions was created matches the current leaf - certificate). - @result Returns true if the exceptions cookies was valid and matches the current - leaf certificate, false otherwise. This function will invalidate the existing - trust result, requiring a subsequent evaluation for the newly-set exceptions. - Note that this function returning true doesn't mean the caller can skip calling - SecTrustEvaluate, as there may be new errors since the exceptions cookie was - created (for example, a certificate may have subsequently expired.) - @discussion Clients of this interface will need to establish the context of this - exception to later decide when this exception cookie is to be used. - Examples of this context would be the server we are connecting to, the ssid - of the wireless network for which this cert is needed, the account for which - this cert should be considered valid, and so on. - */ -bool SecTrustSetExceptions(SecTrustRef trust, CFDataRef exceptions) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); - -/*! - @function SecTrustCopyProperties - @abstract Return a property array for this trust evaluation. - @param trust A reference to a trust object. If the trust has not been - evaluated, the returned property array will be empty. - @result A property array. It is the caller's responsibility to CFRelease - the returned array when it is no longer needed. - @discussion This function returns an ordered array of CFDictionaryRef - instances for each certificate in the chain. Indices run from 0 (leaf) to - the anchor (or last certificate found if no anchor was found.) See the - "Trust Property Constants" section for a list of currently defined keys. - */ -CFArrayRef SecTrustCopyProperties(SecTrustRef trust) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - -/*! - @function SecTrustCopyResult - @abstract Returns a dictionary containing information about the - evaluated certificate chain for use by clients. - @param trust A reference to a trust object. - @result A dictionary with various fields that can be displayed to the user, - or NULL if no additional info is available or the trust has not yet been - validated. The caller is responsible for calling CFRelease on the value - returned when it is no longer needed. - @discussion Returns a dictionary for the overall trust evaluation. See the - "Trust Result Constants" section for a list of currently defined keys. - */ -CFDictionaryRef SecTrustCopyResult(SecTrustRef trust) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - -/*! - @function SecTrustSetOCSPResponse - @abstract Attach OCSPResponse data to a trust object. - @param trust A reference to a trust object. - @param responseData This may be either a CFData object containing a single - DER-encoded OCSPResponse (per RFC 2560), or a CFArray of these. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Allows the caller to provide OCSPResponse data (which may be - obtained during a TLS/SSL handshake, per RFC 3546) as input to a trust - evaluation. If this data is available, it can obviate the need to contact - an OCSP server for current revocation information. - */ -OSStatus SecTrustSetOCSPResponse(SecTrustRef trust, CFTypeRef responseData) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - - -/* - * Legacy functions (OS X only) - */ -#if TARGET_OS_MAC && !TARGET_OS_IPHONE -#include -#include - -/*! - @typedef SecTrustUserSetting - @abstract Specifies a user-specified trust setting value. - @discussion Deprecated in OS X 10.9. User trust settings are managed by - functions in SecTrustSettings.h (starting with OS X 10.5), and by the - SecTrustCopyExceptions and SecTrustSetExceptions functions (starting with - iOS 4 and OS X 10.9). The latter two functions are recommended for both OS X - and iOS, as they avoid the need to explicitly specify these values. - */ -typedef SecTrustResultType SecTrustUserSetting - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); - -/*! - @typedef SecTrustOptionFlags - @abstract Options for customizing trust evaluation. - @constant kSecTrustOptionAllowExpired Allow expired certificates. - @constant kSecTrustOptionLeafIsCA Allow CA as leaf certificate. - @constant kSecTrustOptionFetchIssuerFromNet Allow network fetch of CA cert. - @constant kSecTrustOptionAllowExpiredRoot Allow expired roots. - @constant kSecTrustOptionRequireRevPerCert Require positive revocation - check per certificate. - @constant kSecTrustOptionUseTrustSettings Use TrustSettings instead of - anchors. - @constant kSecTrustOptionImplicitAnchors Properly self-signed certs are - treated as anchors implicitly. - */ -typedef uint32_t SecTrustOptionFlags; -enum { - kSecTrustOptionAllowExpired = 0x00000001, - kSecTrustOptionLeafIsCA = 0x00000002, - kSecTrustOptionFetchIssuerFromNet = 0x00000004, - kSecTrustOptionAllowExpiredRoot = 0x00000008, - kSecTrustOptionRequireRevPerCert = 0x00000010, - kSecTrustOptionUseTrustSettings = 0x00000020, - kSecTrustOptionImplicitAnchors = 0x00000040 -}; - -/*! - @function SecTrustSetOptions - @abstract Sets optional flags for customizing a trust evaluation. - @param trustRef A trust reference. - @param options Flags to change evaluation behavior for this trust. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is not available on iOS. Use SecTrustSetExceptions - and SecTrustCopyExceptions to modify default trust results, and - SecTrustSetNetworkFetchAllowed to specify whether missing CA certificates - can be fetched from the network. - */ -OSStatus SecTrustSetOptions(SecTrustRef trustRef, SecTrustOptionFlags options) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/*! - @function SecTrustSetParameters - @abstract Sets the action and action data for a trust object. - @param trustRef The reference to the trust to change. - @param action A trust action. - @param actionData A reference to data associated with this action. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in OS X 10.7 and later, where it - was replaced by SecTrustSetOptions, and is not available on iOS. Your code - should use SecTrustSetExceptions and SecTrustCopyExceptions to modify default - trust results, and SecTrustSetNetworkFetchAllowed to specify whether missing - CA certificates can be fetched from the network. - */ -OSStatus SecTrustSetParameters(SecTrustRef trustRef, - CSSM_TP_ACTION action, CFDataRef actionData) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecTrustSetKeychains - @abstract Sets the keychains for a given trust object. - @param trust A reference to a trust object. - @param keychainOrArray A reference to an array of keychains to search, a - single keychain, or NULL to use the default keychain search list. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion By default, the user's keychain search list and the system - anchors keychain are searched for certificates to complete the chain. You - can specify a zero-element array if you do not want any keychains searched. - Note: this function is not applicable to iOS. - */ -OSStatus SecTrustSetKeychains(SecTrustRef trust, CFTypeRef keychainOrArray) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); - -/*! - @function SecTrustGetResult - @abstract Returns detailed information on the outcome of an evaluation. - @param trustRef A reference to a trust object. - @param result A pointer to the result from the call to SecTrustEvaluate. - @param certChain On return, a pointer to the certificate chain used to - validate the input certificate. Call the CFRelease function to release - this pointer. - @param statusChain On return, a pointer to the status of the certificate - chain. Do not attempt to free this pointer; it remains valid until the - trust is destroyed or the next call to SecTrustEvaluate. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in OS X 10.7 and later, - and is not available on iOS. - To get the complete certificate chain, use SecTrustGetCertificateCount and - SecTrustGetCertificateAtIndex. To get detailed status information for each - certificate, use SecTrustCopyProperties. To get the overall trust result - for the evaluation, use SecTrustGetTrustResult. - */ -OSStatus SecTrustGetResult(SecTrustRef trustRef, SecTrustResultType *result, - CFArrayRef *certChain, CSSM_TP_APPLE_EVIDENCE_INFO **statusChain) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecTrustGetCssmResult - @abstract Gets the CSSM trust result. - @param trust A reference to a trust. - @param result On return, a pointer to the CSSM trust result. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in OS X 10.7 and later, - and is not available on iOS. - To get detailed status information for each certificate, use - SecTrustCopyProperties. To get the overall trust result for the evaluation, - use SecTrustGetTrustResult. - */ -OSStatus SecTrustGetCssmResult(SecTrustRef trust, - CSSM_TP_VERIFY_CONTEXT_RESULT_PTR *result) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecTrustGetCssmResultCode - @abstract Gets the result code from the most recent call to SecTrustEvaluate - for the specified trust. - @param trust A reference to a trust. - @param resultCode On return, the result code produced by the most recent - evaluation of the given trust (cssmerr.h). The value of resultCode is - undefined if SecTrustEvaluate has not been called. - @result A result code. See "Security Error Codes" (SecBase.h). Returns - errSecTrustNotAvailable if SecTrustEvaluate has not been called for the - specified trust. - @discussion This function is deprecated in OS X 10.7 and later, - and is not available on iOS. - To get detailed status information for each certificate, use - SecTrustCopyProperties. To get the overall trust result for the evaluation, - use SecTrustGetTrustResult. - */ -OSStatus SecTrustGetCssmResultCode(SecTrustRef trust, OSStatus *resultCode) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecTrustGetTPHandle - @abstract Gets the CSSM trust handle - @param trust A reference to a trust. - @param handle On return, a CSSM trust handle. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in OS X 10.7 and later. - */ -OSStatus SecTrustGetTPHandle(SecTrustRef trust, CSSM_TP_HANDLE *handle) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecTrustCopyAnchorCertificates - @abstract Returns an array of default anchor (root) certificates used by - the system. - @param anchors On return, an array containing the system's default anchors - (roots). Call the CFRelease function to release this pointer. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is not available on iOS, as certificate data - for system-trusted roots is currently unavailable on that platform. - */ -OSStatus SecTrustCopyAnchorCertificates(CFArrayRef *anchors) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); - -#endif /* TARGET_OS_MAC && !TARGET_OS_IPHONE */ - - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECTRUST_H_ */ diff --git a/libsecurity_keychain/lib/SecTrustPriv.h b/libsecurity_keychain/lib/SecTrustPriv.h deleted file mode 100644 index 2244a018..00000000 --- a/libsecurity_keychain/lib/SecTrustPriv.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2003-2010 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 SecTrustPriv - Private part of SecTrust.h -*/ - -#ifndef _SECURITY_SECTRUST_PRIV_H_ -#define _SECURITY_SECTRUST_PRIV_H_ - -#include -#include -#include - - -#if defined(__cplusplus) -extern "C" { -#endif - -/* - unique keychain item attributes for user trust records. -*/ -enum { - kSecTrustCertAttr = 'tcrt', - kSecTrustPolicyAttr = 'tpol', - /* Leopard and later */ - kSecTrustPubKeyAttr = 'tpbk', - kSecTrustSignatureAttr = 'tsig' -}; - -/*! - @function SecTrustGetUserTrust - @abstract Gets the user-specified trust settings of a certificate and policy. - @param certificate A reference to a certificate. - @param policy A reference to a policy. - @param trustSetting On return, a pointer to the user specified trust settings. - @result A result code. See "Security Error Codes" (SecBase.h). - @availability Mac OS X version 10.4. Deprecated in Mac OS X version 10.5. -*/ -OSStatus SecTrustGetUserTrust(SecCertificateRef certificate, SecPolicyRef policy, SecTrustUserSetting *trustSetting) - /*DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER*/; - -/*! - @function SecTrustSetUserTrust - @abstract Sets the user-specified trust settings of a certificate and policy. - @param certificate A reference to a certificate. - @param policy A reference to a policy. - @param trustSetting The user-specified trust settings. - @result A result code. See "Security Error Codes" (SecBase.h). - @availability Mac OS X version 10.4. Deprecated in Mac OS X version 10.5. - @discussion as of Mac OS version 10.5, this will result in a call to - SecTrustSettingsSetTrustSettings(). -*/ -OSStatus SecTrustSetUserTrust(SecCertificateRef certificate, SecPolicyRef policy, SecTrustUserSetting trustSetting) - /*DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER*/; - -/*! - @function SecTrustSetUserTrustLegacy - @abstract Sets the user-specified trust settings of a certificate and policy. - @param certificate A reference to a certificate. - @param policy A reference to a policy. - @param trustSetting The user-specified trust settings. - @result A result code. See "Security Error Codes" (SecBase.h). - - @This is the private version of what used to be SecTrustSetUserTrust(); it operates - on UserTrust entries as that function used to. The current SecTrustSetUserTrust() - function operated on Trust Settings. -*/ -OSStatus SecTrustSetUserTrustLegacy(SecCertificateRef certificate, SecPolicyRef policy, SecTrustUserSetting trustSetting); - -/*! - @function SecTrustGetCSSMAnchorCertificates - @abstract Retrieves the CSSM anchor certificates. - @param cssmAnchors A pointer to an array of anchor certificates. - @param cssmAnchorCount A pointer to the number of certificates in anchors. - @result A result code. See "Security Error Codes" (SecBase.h). - @availability Mac OS X version 10.4. Deprecated in Mac OS X version 10.5. -*/ -OSStatus SecTrustGetCSSMAnchorCertificates(const CSSM_DATA **cssmAnchors, uint32 *cssmAnchorCount) - /*DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER*/; - -/*! - @function SecTrustCopyExtendedResult - @abstract Gets the extended trust result after an evaluation has been performed. - @param trust A trust reference. - @param result On return, result points to a CFDictionaryRef containing extended trust results (if no error occurred). - The caller is responsible for releasing this dictionary with CFRelease when finished with it. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function may only be used after SecTrustEvaluate has been called for the trust reference, otherwise - errSecTrustNotAvailable is returned. If the certificate is not an extended validation certificate, there is - no extended result data and errSecDataNotAvailable is returned. Currently, only one dictionary key is defined - (kSecEVOrganizationName). - - Note: this function will be deprecated in a future release of OS X. Your - code should use SecTrustCopyResult to obtain the trust results dictionary. -*/ -OSStatus SecTrustCopyExtendedResult(SecTrustRef trust, CFDictionaryRef *result) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - - -/*! - @enum Trust Result Constants - @discussion Predefined key constants used to obtain values in a - dictionary of trust evaluation results for a certificate chain, - as retrieved from a call to SecTrustCopyResult. - - @constant kSecTrustResultDetails - This key will be present if a trust evaluation has been performed. - Its value is a CFArrayRef of CFDictionaryRef representing detailed - status info for each certificate in the completed chain. - */ -extern CFTypeRef kSecTrustResultDetails - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_NA); - - -/* - * Preference-related strings for Revocation policies. - */ - -/* - * Preference domain, i.e., the name of a plist in ~/Library/Preferences or in - * /Library/Preferences - */ -#define kSecRevocationDomain "com.apple.security.revocation" - -/* OCSP and CRL style keys, followed by values used for both of them */ -#define kSecRevocationOcspStyle CFSTR("OCSPStyle") -#define kSecRevocationCrlStyle CFSTR("CRLStyle") - #define kSecRevocationOff CFSTR("None") /* default for each one */ - #define kSecRevocationBestAttempt CFSTR("BestAttempt") - #define kSecRevocationRequireIfPresent CFSTR("RequireIfPresent") - #define kSecRevocationRequireForAll CFSTR("RequireForAll") - -/* Which first if both enabled? */ -#define kSecRevocationWhichFirst CFSTR("RevocationFirst") - #define kSecRevocationOcspFirst CFSTR("OCSP") - #define kSecRevocationCrlFirst CFSTR("CRL") - -/* boolean: A "this policy is sufficient per cert" for each */ -#define kSecRevocationOCSPSufficientPerCert CFSTR("OCSPSufficientPerCert") -#define kSecRevocationCRLSufficientPerCert CFSTR("CRLSufficientPerCert") - -/* local OCSP responder URI, value arbitrary string value */ -#define kSecOCSPLocalResponder CFSTR("OCSPLocalResponder") - -/* Extended trust result keys (now in public API) */ -#define kSecEVOrganizationName kSecTrustOrganizationName -#define kSecTrustExpirationDate kSecTrustRevocationValidUntilDate - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECTRUST_PRIV_H_ */ diff --git a/libsecurity_keychain/lib/SecTrustSettings.h b/libsecurity_keychain/lib/SecTrustSettings.h deleted file mode 100644 index 7d11337e..00000000 --- a/libsecurity_keychain/lib/SecTrustSettings.h +++ /dev/null @@ -1,321 +0,0 @@ -/* - * Copyright (c) 2006 Apple Computer, 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@ - */ - -/* - * SecTrustSettings.h - Public interface for manipulation of certificate - * Trust Settings. - */ - -#ifndef _SECURITY_SEC_TRUST_SETTINGS_H_ -#define _SECURITY_SEC_TRUST_SETTINGS_H_ - -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Any certificate (cert) which resides in a keychain can have associated with - * it a set of Trust Settings. Trust Settings specify conditions in which a - * given cert can be trusted or explicitly distrusted. A "trusted" cert is - * either a root (self-signed) cert that, when a cert chain verifies back to that - * root, the entire cert chain is trusted; or a non-root cert that does not need - * to verify to a trusted root cert (which is normally the case when verifying a - * cert chain). An "explicitly distrusted" cert is one which will, when encountered - * during the evaluation of a cert chain, cause immediate and unconditional failure - * of the verify operation. - * - * Trust Settings are configurable by the user; they can apply on three levels - * (called domains): - * - * -- Per-user. - * -- Locally administered, system-wide. Administrator privileges are required - * to make changes to this domain. - * -- System. These Trust Settings are immutable and comprise the set of trusted - * root certificates supplied in Mac OS X. - * - * Per-user Trust Settings override locally administered Trust Settings, which - * in turn override the System Trust Settings. - * - * Each cert's Trust Settings are expressed as a CFArray which includes any - * number (including zero) of CFDictionaries, each of which comprises one set of - * Usage Constraints. Each Usage Constraints dictionary contains zero or one of - * each the following components: - * - * key = kSecTrustSettingsPolicy value = SecPolicyRef - * key = kSecTrustSettingsApplication value = SecTrustedApplicationRef - * key = kSecTrustSettingsPolicyString value = CFString, policy-specific - * key = kSecTrustSettingsKeyUsage value = CFNumber, an SInt32 key usage - * - * A given Usage Constraints dictionary applies to a given cert if *all* of the - * usage constraint components specified in the dictionary match the usage of - * the cert being evaluated; when this occurs, the value of the - * kSecTrustSettingsResult entry in the dictionary, shown below, is the effective - * trust setting for the cert. - * - * key = kSecTrustSettingsResult value = CFNumber, an SInt32 SecTrustSettingsResult - * - * The overall Trust Settings of a given cert are the sum of all such Usage - * Constraints CFDictionaries: Trust Settings for a given usage apply if *any* - * of the CFDictionaries in the cert's Trust Settings array satisfies - * the specified usage. Thus, when a cert has multiple Usage Constraints - * dictionaries in its Trust Settings array, the overall Trust Settings - * for the cert are - * - * (Usage Constraint 0 component 0 AND Usage Constraint 0 component 1 ...) - * -- OR -- - * (Usage Constraint 1 component 0 AND Usage Constraint 1 component 1 ...) - * -- OR -- - * ... - * - * Notes on the various Usage Constraints components: - * - * kSecTrustSettingsPolicy Specifies a cert verification policy, e.g., SSL, - * SMIME, etc. - * kSecTrustSettingsApplication Specifies the application performing the cert - * verification. - * kSecTrustSettingsPolicyString Policy-specific. For the SMIME policy, this is - * an email address. - * For the SSL policy, this is a host name. - * kSecTrustSettingsKeyUsage A bitfield indicating key operations (sign, - * encrypt, etc.) for which this Usage Constraint - * apply. Values are defined below as the - * SecTrustSettingsKeyUsage enum. - * kSecTrustSettingsResult The resulting trust value. If not present this has a - * default of kSecTrustSettingsResultTrustRoot, meaning - * "trust this root cert". Other legal values are: - * kSecTrustSettingsResultTrustAsRoot : trust non-root - * cert as if it were a trusted root. - * kSecTrustSettingsResultDeny : explicitly distrust this - * cert. - * kSecTrustSettingsResultUnspecified : neither trust nor - * distrust; can be used to specify an "Allowed error" - * (see below) without assigning trust to a specific - * cert. - * - * Another optional component in a Usage Constraints dictionary is a CSSM_RETURN - * which, if encountered during certificate verification, is ignored for that - * cert. These "allowed error" values are constrained by Usage Constraints as - * described above; a Usage Constraint dictionary with no constraints but with - * an Allowed Error value causes that error to always be allowed when the cert - * is being evaluated. - * - * The "allowed error" entry in a Usage Constraints dictionary is formatted - * as follows: - * - * key = kSecTrustSettingsAllowedError value = CFNumber, an SInt32 CSSM_RETURN - * - * Note that if kSecTrustSettingsResult value of kSecTrustSettingsResultUnspecified - * is *not* present for a Usage Constraints dictionary with no Usage - * Constraints, the default of kSecTrustSettingsResultTrustRoot is assumed. To - * specify a kSecTrustSettingsAllowedError without explicitly trusting (or - * distrusting) the associated cert, specify kSecTrustSettingsResultUnspecified - * for the kSecTrustSettingsResult component. - * - * Note that an empty Trust Settings array means "always trust this cert, - * with a resulting kSecTrustSettingsResult of kSecTrustSettingsResultTrustRoot". - * An empty Trust Settings array is definitely not the same as *no* Trust - * Settings, which means "this cert must be verified to a known trusted cert". - * - * Note the distinction between kSecTrustSettingsResultTrustRoot and - * kSecTrustSettingsResultTrustAsRoot; the former can only be applied to - * root (self-signed) certs; the latter can only be applied to non-root - * certs. This also means that an empty TrustSettings array for a non-root - * cert is invalid, since the default value for kSecTrustSettingsResult is - * kSecTrustSettingsResultTrustRoot, which is invalid for a non-root cert. - * - * Authentication - * -------------- - * - * When making changes to the per-user Trust Settings, the user will be - * prompted with an alert panel asking for authentication via user name a - * password (or other credentials normally used for login). This means - * that it is not possible to modify per-user Trust Settings when not - * running in a GUI environment (i.e. the user is not logged in via - * Loginwindow). - * - * When making changes to the system-wide Trust Settings, the user will be - * prompted with an alert panel asking for an administrator's name and - * password, unless the calling process is running as root in which case - * no futher authentication is needed. - */ - -/* - * The keys in one Usage Constraints dictionary. - */ -#define kSecTrustSettingsPolicy CFSTR("kSecTrustSettingsPolicy") -#define kSecTrustSettingsApplication CFSTR("kSecTrustSettingsApplication") -#define kSecTrustSettingsPolicyString CFSTR("kSecTrustSettingsPolicyString") -#define kSecTrustSettingsKeyUsage CFSTR("kSecTrustSettingsKeyUsage") -#define kSecTrustSettingsAllowedError CFSTR("kSecTrustSettingsAllowedError") -#define kSecTrustSettingsResult CFSTR("kSecTrustSettingsResult") - -/* - * Key usage bits, the value for Usage Constraints key kSecTrustSettingsKeyUsage. - */ -enum { - /* sign/verify data */ - kSecTrustSettingsKeyUseSignature = 0x00000001, - /* bulk encryption */ - kSecTrustSettingsKeyUseEnDecryptData = 0x00000002, - /* key wrap/unwrap */ - kSecTrustSettingsKeyUseEnDecryptKey = 0x00000004, - /* sign/verify cert */ - kSecTrustSettingsKeyUseSignCert = 0x00000008, - /* sign/verify CRL and OCSP */ - kSecTrustSettingsKeyUseSignRevocation = 0x00000010, - /* key exchange, e.g., Diffie-Hellman */ - kSecTrustSettingsKeyUseKeyExchange = 0x00000020, - /* any usage (the default if this value is not specified) */ - kSecTrustSettingsKeyUseAny = 0xffffffff -}; -typedef uint32 SecTrustSettingsKeyUsage; - -/* - * The effective Trust Setting result. - */ -enum { - kSecTrustSettingsResultInvalid = 0, /* Never valid in a Trust Settings array or - * in an API call. */ - kSecTrustSettingsResultTrustRoot, /* Root cert is explicitly trusted */ - kSecTrustSettingsResultTrustAsRoot, /* Non-root cert is explicitly trusted */ - kSecTrustSettingsResultDeny, /* Cert is explicitly distrusted */ - kSecTrustSettingsResultUnspecified /* Neither trusted nor distrusted; evaluation - * proceeds as usual */ -}; -typedef uint32 SecTrustSettingsResult; - -/* - * Specify user, local administrator, or system domain Trust Settings. - * Note that kSecTrustSettingsDomainSystem settings are read-only, even by - * root. - */ -enum { - kSecTrustSettingsDomainUser = 0, - kSecTrustSettingsDomainAdmin, - kSecTrustSettingsDomainSystem -}; -typedef uint32 SecTrustSettingsDomain; - -/* - * SecCertificateRef value indicating the default Root Certificate Trust Settings - * for a given domain. When evaluating Trust Settings for a root cert in - * a given domain, *and* no matching explicit Trust Settings exists for the - * root cert in questions, *and* default Root Cert Trust Settings exist - * in that domain which matches the evaluation condition, then the - * SecTrustSettingsResult for that default Trust Setting (if not - * kSecTrustSettingsResultUnspecified) will apply. - * - * This can be used e.g. by a system administrator to explicilty distrust all - * of the root certs in the (immutable) system domain for a specific policy. - * - * This const is passed as the 'SecCertificateRef certRef' argument to - * SecTrustSettingsCopyTrustSettings(), SecTrustSettingsSetTrustSettings(), - * and SecTrustSettingsRemoveTrustSettings(), and - * SecTrustSettingsCopyModificationDate(). - */ -#define kSecTrustSettingsDefaultRootCertSetting ((SecCertificateRef)-1) - -/* - * Obtain Trust Settings for specified cert. - * Caller must CFRelease() the returned CFArray. - * Returns errSecItemNotFound if no Trust settings exist for the cert. - */ -OSStatus SecTrustSettingsCopyTrustSettings( - SecCertificateRef certRef, - SecTrustSettingsDomain domain, - CFArrayRef *trustSettings); /* RETURNED */ - -/* - * Specify Trust Settings for specified cert. If specified cert - * already has Trust Settings in the specified domain, they will - * be replaced. - * The trustSettingsDictOrArray parameter is either a CFDictionary, - * a CFArray of them, or NULL. NULL indicates "always trust this - * root cert regardless of usage". - */ -OSStatus SecTrustSettingsSetTrustSettings( - SecCertificateRef certRef, - SecTrustSettingsDomain domain, - CFTypeRef trustSettingsDictOrArray); - -/* - * Delete Trust Settings for specified cert. - * Returns errSecItemNotFound if no Trust settings exist for the cert. - */ -OSStatus SecTrustSettingsRemoveTrustSettings( - SecCertificateRef certRef, - SecTrustSettingsDomain domain); - -/* - * Obtain an array of all certs which have Trust Settings in the - * specified domain. Elements in the returned certArray are - * SecCertificateRefs. - * Caller must CFRelease() the returned array. - * Returns errSecNoTrustSettings if no trust settings exist - * for the specified domain. - */ -OSStatus SecTrustSettingsCopyCertificates( - SecTrustSettingsDomain domain, - CFArrayRef *certArray); - -/* - * Obtain the time at which a specified cert's Trust Settings - * were last modified. Caller must CFRelease the result. - * Returns errSecItemNotFound if no Trust Settings exist for specified - * cert and domain. - */ -OSStatus SecTrustSettingsCopyModificationDate( - SecCertificateRef certRef, - SecTrustSettingsDomain domain, - CFDateRef *modificationDate); /* RETURNED */ - -/* - * Obtain an external, portable representation of the specified - * domain's TrustSettings. Caller must CFRelease the returned data. - * Returns errSecNoTrustSettings if no trust settings exist - * for the specified domain. - */ -OSStatus SecTrustSettingsCreateExternalRepresentation( - SecTrustSettingsDomain domain, - CFDataRef *trustSettings); - -/* - * Import trust settings, obtained via SecTrustSettingsCreateExternalRepresentation, - * into the specified domain. - */ -OSStatus SecTrustSettingsImportExternalRepresentation( - SecTrustSettingsDomain domain, - CFDataRef trustSettings); - -#ifdef __cplusplus -} -#endif - -#endif /* _SECURITY_SEC_TRUST_SETTINGS_H_ */ - diff --git a/libsecurity_keychain/lib/SecTrustSettingsPriv.h b/libsecurity_keychain/lib/SecTrustSettingsPriv.h deleted file mode 100644 index b73ca60b..00000000 --- a/libsecurity_keychain/lib/SecTrustSettingsPriv.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2006 Apple Computer, 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@ - */ - -/* - * SecTrustSettingsPriv.h - TrustSettings SPI functions. - */ - -#ifndef _SEC_TRUST_SETTINGS_PRIV_H_ -#define _SEC_TRUST_SETTINGS_PRIV_H_ - -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Fundamental routine used by TP to ascertain status of one cert. - * - * Returns true in *foundMatchingEntry if a trust setting matching - * specific constraints was found for the cert. Returns true in - * *foundAnyEntry if any entry was found for the cert, even if it - * did not match the specified constraints. The TP uses this to - * optimize for the case where a cert is being evaluated for - * one type of usage, and then later for another type. If - * foundAnyEntry is false, the second evaluation need not occur. - * - * Returns the domain in which a setting was found in *foundDomain. - * - * Allowed errors applying to the specified cert evaluation - * are returned in a mallocd array in *allowedErrors and must - * be freed by caller. - */ -OSStatus SecTrustSettingsEvaluateCert( - CFStringRef certHashStr, - /* parameters describing the current cert evalaution */ - const CSSM_OID *policyOID, - const char *policyString, /* optional */ - uint32 policyStringLen, - SecTrustSettingsKeyUsage keyUsage, /* optional */ - bool isRootCert, /* for checking default setting */ - /* RETURNED values */ - SecTrustSettingsDomain *foundDomain, - CSSM_RETURN **allowedErrors, /* mallocd and RETURNED */ - uint32 *numAllowedErrors, /* RETURNED */ - SecTrustSettingsResult *resultType, /* RETURNED */ - bool *foundMatchingEntry,/* RETURNED */ - bool *foundAnyEntry); /* RETURNED */ - -/* - * Obtain trusted certs which match specified usage. - * Only certs with a SecTrustSettingsResult of - * kSecTrustSettingsResultTrustRoot or - * or kSecTrustSettingsResultTrustAsRoot will be returned. - * - * To be used by SecureTransport for its (hopefully soon-to-be- - * deprecated) SSLSetTrustedRoots() call; I hope nothing else has - * to use this... - * - * Caller must CFRelease the returned CFArrayRef. - */ -OSStatus SecTrustSettingsCopyQualifiedCerts( - const CSSM_OID *policyOID, - const char *policyString, /* optional */ - uint32 policyStringLen, - SecTrustSettingsKeyUsage keyUsage, /* optional */ - CFArrayRef *certArray); /* RETURNED */ - -/* - * Obtain unrestricted root certificates from the specified domain(s). - * Only returns root certificates with no usage constraints. - * Caller must CFRelease the returned CFArrayRef. - */ -OSStatus SecTrustSettingsCopyUnrestrictedRoots( - Boolean userDomain, - Boolean adminDomain, - Boolean systemDomain, - CFArrayRef *certArray); /* RETURNED */ - -/* - * Obtain a string representing a cert's SHA1 digest. This string is - * the key used to look up per-cert trust settings in a TrustSettings record. - */ -CFStringRef SecTrustSettingsCertHashStrFromCert( - SecCertificateRef certRef); - -CFStringRef SecTrustSettingsCertHashStrFromData( - const void *cert, - size_t certLen); - -/* - * Add a cert's TrustSettings to a non-persistent TrustSettings record. - * Primarily intended for use in creating a system TrustSettings record - * (which is itself immutable via this module). - * - * The settingsIn argument is an external representation of a TrustSettings - * record, obtained from this function or from - * SecTrustSettingsCreateExternalRepresentation(). - * If settingsIn is NULL, a new (empty) TrustSettings will be created. - * - * The certRef and trustSettingsDictOrArray arguments are as in - * SecTrustSettingsSetTrustSettings(). May be NULL, when e.g. creating - * a new and empty TrustSettings record. - * - * The external representation is written to the settingOut argument, - * which must eventually be CFReleased by the caller. - */ -OSStatus SecTrustSettingsSetTrustSettingsExternal( - CFDataRef settingsIn, /* optional */ - SecCertificateRef certRef, /* optional */ - CFTypeRef trustSettingsDictOrArray, /* optional */ - CFDataRef *settingsOut); /* RETURNED */ - -#ifdef __cplusplus -} -#endif - -#endif /* _SEC_TRUST_SETTINGS_PRIV_H_ */ - diff --git a/libsecurity_keychain/lib/Security.h b/libsecurity_keychain/lib/Security.h deleted file mode 100644 index c9e35458..00000000 --- a/libsecurity_keychain/lib/Security.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2000-2011 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@ - */ - -/* CDSA */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Security */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Code Signing */ -#include -#include -#include -#include -#include - -/* Authorization */ -#include -#include -#include - -/* CMS */ -#include -#include - -/* Secure Transport */ -#include -#include - -#ifdef __BLOCKS__ -#include -#include -#include -#include -#include -#include -#include -#include -#endif - diff --git a/libsecurity_keychain/lib/generateErrStrings.pl b/libsecurity_keychain/lib/generateErrStrings.pl deleted file mode 100644 index 0382688c..00000000 --- a/libsecurity_keychain/lib/generateErrStrings.pl +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/perl -# -# Copyright (c) 2003-2004 Apple Computer, 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@ -# -# generatorX.pl - create error strings files from the Security header files -# -# Usage: -# perl generatorX.pl input-directory output-directory -# -# Currently supported files are SecBase.h, SecureTransport.h and Authorization.h -# -# perl generatorX.pl `pwd` `pwd` SecBase2.h SecureTransport2.h Authorization.h -# -# Input will be like: -# -# errSSLProtocol = -9800, /* SSL protocol error */ -# errSSLNegotiation = -9801, /* Cipher Suite negotiation failure */ -# -# Output should be like (in Unicode): -# -# /* errSSLProtocol */ -# "-9800" = "SSL protocol error"; -# -# /* errSSLNegotiation */ -# "-9801" = "Cipher Suite negotiation failure"; -# -# Note that the list of errors must be numerically unique across all input files, or the strings file -# will be invalid.Comments that span multiple lines will be ignored, as will lines with no comment. C++ -# style comments are not supported. -# - -use Encode; - -$SOURCEDIR=$ARGV[0]; # directory with error headers -$TARGETDIR=$ARGV[1]; # where to put the output file -@INPUTFILES=@ARGV[2 .. 9999]; # list of input files - -$TABLES="$TARGETDIR/SecErrorMessages.strings"; # error strings - -$tabs = "\t\t\t"; # argument indentation (noncritical) -$warning = "This file was automatically generated. Do not edit on penalty of futility!"; - -# -# Parse error headers and build array of all relevant lines -# - -open(ERR, "cat " . join(" ", @INPUTFILES) . "|") or die "Cannot open error header files"; -$/=undef; # big gulp mode -$_ = ; -@errorlines = m{(?:^\s*)(err[Sec|Authorization|SSL]\w+)(?:\s*=\s*)(-?\d+)(?:\s*,?\s*)(?:/\*\s*)(.*)(?:\*/)(?:$\s*)}gm; -close(ERR); - -$nFull = $#errorlines / 3; - -# -# Now we will generate the error name tables. -# -open(OUT, ">$TABLES") or die "Cannot write $TABLES: $^E"; - -# Print warning comment -$msg = "//\n// Security error code tables.\n// $warning\n//\n"; - -# Print the error messages -while ($errx = shift @errorlines) -{ - $value = shift @errorlines; # or die; - $str = shift @errorlines; # or die; - $str =~ s/\s*$//; # drop trailing white space - if ( $value != 0) # can't output duplicate error codes - { - $msg = $msg . "\n/* $errx */\n\"$value\" = \"$str\";\n"; - } -}; -$msg = $msg . "\n"; -$output = encode("UTF-16", $msg, Encode::FB_PERLQQ); -print OUT "$output"; - -close(OUT); -select(STDOUT); diff --git a/libsecurity_keychain/libDER/Tests/DER_Ticket.h b/libsecurity_keychain/libDER/Tests/DER_Ticket.h deleted file mode 100644 index e8ef10c3..00000000 --- a/libsecurity_keychain/libDER/Tests/DER_Ticket.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * DER_Ticket.h - * libDER - * - * Created by Michael Brouwer on 10/13/09. - * Copyright 2009 Apple Inc. All rights reserved. - * - */ - -#include - - -#define FAST_SET_LOOKUP 1 - -#ifdef FAST_SET_LOOKUP -/* state representing a fast by tag set accessor, the caller needs to provide - a set large enough to hold all */ -typedef struct { - DERTag capacity; /* should be large enough to hold all encountered tags. - otherwise DR_UnexpectedTag will be returned, note - that only one tag per tag number can exist. */ - DERByte *end; - DERByte *byTag[]; /* maxTag element array of pointers to tag + length - of items in set indexed by tagNumber. */ -} DERSet; - -/* Iterates over all the tags in the set to build an index returned in - derSet. */ -DERReturn DERDecodeSetContentInit( - const DERItem *der, /* data to decode */ - DERSet *derSet); /* IN/OUT, to use in DERDecodeSetTag */ - -/* Returns DR_UnexpectedTag if the requested tag is not in derSet, returns - the content of the decoded item in content otherwise. */ -DERReturn DERDecodeSetTag( - DERSet *derSeq, /* data to decode */ - DERTag tag, /* tag in sequence/set we are looking for. */ - DERItem *content); /* RETURNED */ -#endif /* FAST_SET_LOOKUP */ - - -DERReturn DERSetDecodeItemWithTag( - const DERItem *der, /* data to decode */ - DERTag tag, /* tag in sequence/set we are looking for. */ - DERItem *content); /* RETURNED */ - - -/* Application Processor Ticket */ -typedef struct { - DERItem signatureAlgorithm; /* AlgorithmId */ - DERItem body; /* SET OF OCTECT STRING, DER_DEC_SAVE_DER */ - DERItem signature; /* OCTET STRING */ - DERItem certificates; /* SEQUENCE of CERTIFICATE */ -} DERApTicket; - -/* DERItemSpecs to decode into a DERApTicket */ -extern const DERItemSpec DERApTicketItemSpecs[]; -extern const DERSize DERNumApTicketItemSpecs; - -DERReturn DERDecodeApTicket( - const DERItem *contents, - DERApTicket *ticket, /* RETURNED */ - DERSize *numUsedBytes); /* RETURNED */ - - -/* Baseband Ticket */ -typedef struct { - DERItem signatureAlgorithm; /* AlgorithmId */ - DERItem body; /* SET OF OCTECT STRING, DER_DEC_SAVE_DER */ - DERItem signature; /* OCTET STRING */ - DERItem gpuk; /* OCTET STRING */ -} DERBbTicket; - -/* DERItemSpecs to decode into a DERBbTicket */ -extern const DERItemSpec DERBbTicketItemSpecs[]; -extern const DERSize DERNumBbTicketItemSpecs; - -DERReturn DERDecodeBbTicket( - const DERItem *contents, - DERBbTicket *ticket, /* RETURNED */ - DERSize *numUsedBytes); /* RETURNED */ diff --git a/libsecurity_keychain/libDER/config/base.xcconfig b/libsecurity_keychain/libDER/config/base.xcconfig deleted file mode 100644 index 2171d75d..00000000 --- a/libsecurity_keychain/libDER/config/base.xcconfig +++ /dev/null @@ -1,14 +0,0 @@ -CODE_SIGN_IDENTITY = -; -GCC_VERSION = com.apple.compilers.llvm.clang.1_0 -DEBUG_INFORMATION_FORMAT = dwarf-with-dsym -CURRENT_PROJECT_VERSION = $(RC_ProjectSourceVersion) -VERSIONING_SYSTEM = apple-generic; -DEAD_CODE_STRIPPING = YES; - -ARCHS = $(ARCHS_STANDARD_32_64_BIT) - -// Debug symbols should be on obviously -GCC_GENERATE_DEBUGGING_SYMBOLS = YES -COPY_PHASE_STRIP = NO -STRIP_STYLE = debugging -STRIP_INSTALLED_PRODUCT = NO diff --git a/libsecurity_keychain/libDER/libDER.xcodeproj/project.pbxproj b/libsecurity_keychain/libDER/libDER.xcodeproj/project.pbxproj deleted file mode 100644 index bcffddc3..00000000 --- a/libsecurity_keychain/libDER/libDER.xcodeproj/project.pbxproj +++ /dev/null @@ -1,752 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXAggregateTarget section */ - 053BA30F091C00B100A7007A /* World */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 4CD81A6D09BE1FD2000A9641 /* Build configuration list for PBXAggregateTarget "World" */; - buildPhases = ( - ); - dependencies = ( - 053BA317091C017E00A7007A /* PBXTargetDependency */, - 053BA463091FE60E00A7007A /* PBXTargetDependency */, - 058ECC54091FF0000050AA30 /* PBXTargetDependency */, - 058F16680925224F009FA1C5 /* PBXTargetDependency */, - 4C96C8DC113F4174005483E8 /* PBXTargetDependency */, - ); - name = World; - productName = World; - }; -/* End PBXAggregateTarget section */ - -/* Begin PBXBuildFile section */ - 053BA324091C02B700A7007A /* DER_Decode.h in Headers */ = {isa = PBXBuildFile; fileRef = 053BA321091C02B700A7007A /* DER_Decode.h */; }; - 053BA325091C02B700A7007A /* libDER_config.h in Headers */ = {isa = PBXBuildFile; fileRef = 053BA322091C02B700A7007A /* libDER_config.h */; }; - 053BA326091C02B700A7007A /* libDER.h in Headers */ = {isa = PBXBuildFile; fileRef = 053BA323091C02B700A7007A /* libDER.h */; }; - 053BA344091C089B00A7007A /* asn1Types.h in Headers */ = {isa = PBXBuildFile; fileRef = 053BA342091C089B00A7007A /* asn1Types.h */; }; - 053BA345091C089B00A7007A /* DER_Decode.c in Sources */ = {isa = PBXBuildFile; fileRef = 053BA343091C089B00A7007A /* DER_Decode.c */; }; - 053BA399091C258100A7007A /* DER_CertCrl.c in Sources */ = {isa = PBXBuildFile; fileRef = 053BA397091C258100A7007A /* DER_CertCrl.c */; }; - 053BA39A091C258100A7007A /* DER_CertCrl.h in Headers */ = {isa = PBXBuildFile; fileRef = 053BA398091C258100A7007A /* DER_CertCrl.h */; }; - 053BA45D091FE5E700A7007A /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 053BA314091C00BF00A7007A /* libDER.a */; }; - 053BA461091FE60700A7007A /* parseCert.c in Sources */ = {isa = PBXBuildFile; fileRef = 053BA460091FE60700A7007A /* parseCert.c */; }; - 053BA470091FE6C100A7007A /* fileIo.c in Sources */ = {isa = PBXBuildFile; fileRef = 053BA46E091FE6C100A7007A /* fileIo.c */; }; - 053BA471091FE6C100A7007A /* fileIo.h in Headers */ = {isa = PBXBuildFile; fileRef = 053BA46F091FE6C100A7007A /* fileIo.h */; }; - 053BA47D091FE7CC00A7007A /* libDERUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 053BA47B091FE7CC00A7007A /* libDERUtils.h */; }; - 053BA47E091FE7CC00A7007A /* libDERUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 053BA47C091FE7CC00A7007A /* libDERUtils.c */; }; - 0544AEA10940939C00DD6C0B /* DER_Encode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0544AE9F0940939C00DD6C0B /* DER_Encode.h */; }; - 0544AEA20940939C00DD6C0B /* DER_Encode.c in Sources */ = {isa = PBXBuildFile; fileRef = 0544AEA00940939C00DD6C0B /* DER_Encode.c */; }; - 058ECC52091FEFF70050AA30 /* libDERUtils.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 053BA46B091FE63E00A7007A /* libDERUtils.a */; }; - 058ECD350920F5E30050AA30 /* DER_Keys.c in Sources */ = {isa = PBXBuildFile; fileRef = 058ECD330920F5E30050AA30 /* DER_Keys.c */; }; - 058ECD360920F5E30050AA30 /* DER_Keys.h in Headers */ = {isa = PBXBuildFile; fileRef = 058ECD340920F5E30050AA30 /* DER_Keys.h */; }; - 058F15C20922B73F009FA1C5 /* printFields.h in Headers */ = {isa = PBXBuildFile; fileRef = 058F15C00922B73F009FA1C5 /* printFields.h */; }; - 058F15C30922B73F009FA1C5 /* printFields.c in Sources */ = {isa = PBXBuildFile; fileRef = 058F15C10922B73F009FA1C5 /* printFields.c */; }; - 058F163109250D16009FA1C5 /* oids.c in Sources */ = {isa = PBXBuildFile; fileRef = 058F162D09250D0D009FA1C5 /* oids.c */; }; - 058F163209250D17009FA1C5 /* oids.h in Headers */ = {isa = PBXBuildFile; fileRef = 058F162E09250D0D009FA1C5 /* oids.h */; }; - 058F1659092513A7009FA1C5 /* parseCrl.c in Sources */ = {isa = PBXBuildFile; fileRef = 058F1658092513A7009FA1C5 /* parseCrl.c */; }; - 058F16710925230E009FA1C5 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 053BA314091C00BF00A7007A /* libDER.a */; }; - 058F16720925230F009FA1C5 /* libDERUtils.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 053BA46B091FE63E00A7007A /* libDERUtils.a */; }; - 05E0E40709228A5E005F4693 /* DER_Digest.h in Headers */ = {isa = PBXBuildFile; fileRef = 05E0E40509228A5E005F4693 /* DER_Digest.h */; }; - 05E0E40809228A5E005F4693 /* DER_Digest.c in Sources */ = {isa = PBXBuildFile; fileRef = 05E0E40609228A5E005F4693 /* DER_Digest.c */; }; - 4C96C8D6113F4165005483E8 /* DER_Ticket.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C96C8D3113F4165005483E8 /* DER_Ticket.c */; }; - 4C96C8D7113F4165005483E8 /* parseTicket.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C96C8D5113F4165005483E8 /* parseTicket.c */; }; - 4C96C8E2113F4232005483E8 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 053BA314091C00BF00A7007A /* libDER.a */; }; - 4C96C8ED113F42D1005483E8 /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C96C8EC113F42C4005483E8 /* libcrypto.dylib */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 053BA316091C017E00A7007A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 053BA30A091C00A400A7007A /* Project object */; - proxyType = 1; - remoteGlobalIDString = 053BA313091C00BF00A7007A; - remoteInfo = libDER; - }; - 053BA458091FE59900A7007A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 053BA30A091C00A400A7007A /* Project object */; - proxyType = 1; - remoteGlobalIDString = 053BA313091C00BF00A7007A; - remoteInfo = libDER; - }; - 053BA462091FE60E00A7007A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 053BA30A091C00A400A7007A /* Project object */; - proxyType = 1; - remoteGlobalIDString = 053BA444091FE58C00A7007A; - remoteInfo = parseCert; - }; - 058ECC53091FF0000050AA30 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 053BA30A091C00A400A7007A /* Project object */; - proxyType = 1; - remoteGlobalIDString = 053BA46A091FE63E00A7007A; - remoteInfo = libDERUtils; - }; - 058ECC55091FF0090050AA30 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 053BA30A091C00A400A7007A /* Project object */; - proxyType = 1; - remoteGlobalIDString = 053BA46A091FE63E00A7007A; - remoteInfo = libDERUtils; - }; - 058F16670925224F009FA1C5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 053BA30A091C00A400A7007A /* Project object */; - proxyType = 1; - remoteGlobalIDString = 058F16530925135E009FA1C5; - remoteInfo = parseCrl; - }; - 058F1675092523D8009FA1C5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 053BA30A091C00A400A7007A /* Project object */; - proxyType = 1; - remoteGlobalIDString = 053BA313091C00BF00A7007A; - remoteInfo = libDER; - }; - 058F1677092523DD009FA1C5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 053BA30A091C00A400A7007A /* Project object */; - proxyType = 1; - remoteGlobalIDString = 053BA46A091FE63E00A7007A; - remoteInfo = libDERUtils; - }; - 4C96C8DB113F4174005483E8 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 053BA30A091C00A400A7007A /* Project object */; - proxyType = 1; - remoteGlobalIDString = 4C96C8CD113F4132005483E8; - remoteInfo = parseTicket; - }; - 4C96C8E0113F4223005483E8 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 053BA30A091C00A400A7007A /* Project object */; - proxyType = 1; - remoteGlobalIDString = 053BA313091C00BF00A7007A; - remoteInfo = libDER; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 053BA314091C00BF00A7007A /* libDER.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libDER.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 053BA321091C02B700A7007A /* DER_Decode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DER_Decode.h; sourceTree = ""; }; - 053BA322091C02B700A7007A /* libDER_config.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = libDER_config.h; sourceTree = ""; }; - 053BA323091C02B700A7007A /* libDER.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = libDER.h; sourceTree = ""; }; - 053BA342091C089B00A7007A /* asn1Types.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = asn1Types.h; sourceTree = ""; }; - 053BA343091C089B00A7007A /* DER_Decode.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = DER_Decode.c; sourceTree = ""; }; - 053BA397091C258100A7007A /* DER_CertCrl.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = DER_CertCrl.c; sourceTree = ""; }; - 053BA398091C258100A7007A /* DER_CertCrl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DER_CertCrl.h; sourceTree = ""; }; - 053BA445091FE58C00A7007A /* parseCert */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = parseCert; sourceTree = BUILT_PRODUCTS_DIR; }; - 053BA460091FE60700A7007A /* parseCert.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = parseCert.c; sourceTree = ""; }; - 053BA46B091FE63E00A7007A /* libDERUtils.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libDERUtils.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 053BA46E091FE6C100A7007A /* fileIo.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = fileIo.c; sourceTree = ""; }; - 053BA46F091FE6C100A7007A /* fileIo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = fileIo.h; sourceTree = ""; }; - 053BA47B091FE7CC00A7007A /* libDERUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libDERUtils.h; sourceTree = ""; }; - 053BA47C091FE7CC00A7007A /* libDERUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libDERUtils.c; sourceTree = ""; }; - 0544AE9F0940939C00DD6C0B /* DER_Encode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DER_Encode.h; sourceTree = ""; }; - 0544AEA00940939C00DD6C0B /* DER_Encode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DER_Encode.c; sourceTree = ""; }; - 058ECD330920F5E30050AA30 /* DER_Keys.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = DER_Keys.c; sourceTree = ""; }; - 058ECD340920F5E30050AA30 /* DER_Keys.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DER_Keys.h; sourceTree = ""; }; - 058F15C00922B73F009FA1C5 /* printFields.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = printFields.h; sourceTree = ""; }; - 058F15C10922B73F009FA1C5 /* printFields.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = printFields.c; sourceTree = ""; }; - 058F162D09250D0D009FA1C5 /* oids.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = oids.c; sourceTree = ""; }; - 058F162E09250D0D009FA1C5 /* oids.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = oids.h; sourceTree = ""; }; - 058F16540925135E009FA1C5 /* parseCrl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = parseCrl; sourceTree = BUILT_PRODUCTS_DIR; }; - 058F1658092513A7009FA1C5 /* parseCrl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = parseCrl.c; sourceTree = ""; }; - 05E0E40509228A5E005F4693 /* DER_Digest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DER_Digest.h; sourceTree = ""; }; - 05E0E40609228A5E005F4693 /* DER_Digest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DER_Digest.c; sourceTree = ""; }; - 1828EAA014E334E200BE00C2 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; - 1828EAA114E334E200BE00C2 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; - 1828EAA214E334E200BE00C2 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; - 1828EAA314E334E200BE00C2 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; - 4C96C8CE113F4132005483E8 /* parseTicket */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = parseTicket; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C96C8D2113F4165005483E8 /* AppleMobilePersonalizedTicket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppleMobilePersonalizedTicket.h; sourceTree = ""; }; - 4C96C8D3113F4165005483E8 /* DER_Ticket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DER_Ticket.c; sourceTree = ""; }; - 4C96C8D4113F4165005483E8 /* DER_Ticket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DER_Ticket.h; sourceTree = ""; }; - 4C96C8D5113F4165005483E8 /* parseTicket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = parseTicket.c; sourceTree = ""; }; - 4C96C8EC113F42C4005483E8 /* libcrypto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcrypto.dylib; path = /usr/lib/libcrypto.dylib; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 053BA312091C00BF00A7007A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 053BA443091FE58C00A7007A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 058ECC52091FEFF70050AA30 /* libDERUtils.a in Frameworks */, - 053BA45D091FE5E700A7007A /* libDER.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 053BA469091FE63E00A7007A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 058F16520925135E009FA1C5 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 058F16720925230F009FA1C5 /* libDERUtils.a in Frameworks */, - 058F16710925230E009FA1C5 /* libDER.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4C96C8CC113F4132005483E8 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 4C96C8E2113F4232005483E8 /* libDER.a in Frameworks */, - 4C96C8ED113F42D1005483E8 /* libcrypto.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 053BA306091C00A400A7007A = { - isa = PBXGroup; - children = ( - 1828EA9F14E334E200BE00C2 /* config */, - 053BA31E091C029900A7007A /* libDER */, - 053BA466091FE62100A7007A /* libDERUtils */, - 053BA45C091FE5CE00A7007A /* Tests */, - 058ECE5B09211AB20050AA30 /* External Libs */, - 053BA315091C00BF00A7007A /* Products */, - ); - sourceTree = ""; - }; - 053BA315091C00BF00A7007A /* Products */ = { - isa = PBXGroup; - children = ( - 053BA314091C00BF00A7007A /* libDER.a */, - 053BA445091FE58C00A7007A /* parseCert */, - 053BA46B091FE63E00A7007A /* libDERUtils.a */, - 058F16540925135E009FA1C5 /* parseCrl */, - 4C96C8CE113F4132005483E8 /* parseTicket */, - ); - name = Products; - sourceTree = ""; - }; - 053BA31E091C029900A7007A /* libDER */ = { - isa = PBXGroup; - children = ( - 058ECD330920F5E30050AA30 /* DER_Keys.c */, - 058ECD340920F5E30050AA30 /* DER_Keys.h */, - 053BA342091C089B00A7007A /* asn1Types.h */, - 053BA397091C258100A7007A /* DER_CertCrl.c */, - 053BA398091C258100A7007A /* DER_CertCrl.h */, - 053BA343091C089B00A7007A /* DER_Decode.c */, - 053BA321091C02B700A7007A /* DER_Decode.h */, - 0544AEA00940939C00DD6C0B /* DER_Encode.c */, - 0544AE9F0940939C00DD6C0B /* DER_Encode.h */, - 053BA322091C02B700A7007A /* libDER_config.h */, - 053BA323091C02B700A7007A /* libDER.h */, - 05E0E40509228A5E005F4693 /* DER_Digest.h */, - 05E0E40609228A5E005F4693 /* DER_Digest.c */, - 058F162D09250D0D009FA1C5 /* oids.c */, - 058F162E09250D0D009FA1C5 /* oids.h */, - ); - path = libDER; - sourceTree = ""; - }; - 053BA45C091FE5CE00A7007A /* Tests */ = { - isa = PBXGroup; - children = ( - 4C96C8D2113F4165005483E8 /* AppleMobilePersonalizedTicket.h */, - 4C96C8D3113F4165005483E8 /* DER_Ticket.c */, - 4C96C8D4113F4165005483E8 /* DER_Ticket.h */, - 4C96C8D5113F4165005483E8 /* parseTicket.c */, - 053BA460091FE60700A7007A /* parseCert.c */, - 058F1658092513A7009FA1C5 /* parseCrl.c */, - ); - path = Tests; - sourceTree = ""; - }; - 053BA466091FE62100A7007A /* libDERUtils */ = { - isa = PBXGroup; - children = ( - 053BA47B091FE7CC00A7007A /* libDERUtils.h */, - 053BA47C091FE7CC00A7007A /* libDERUtils.c */, - 053BA46E091FE6C100A7007A /* fileIo.c */, - 053BA46F091FE6C100A7007A /* fileIo.h */, - 058F15C00922B73F009FA1C5 /* printFields.h */, - 058F15C10922B73F009FA1C5 /* printFields.c */, - ); - path = libDERUtils; - sourceTree = ""; - }; - 058ECE5B09211AB20050AA30 /* External Libs */ = { - isa = PBXGroup; - children = ( - 4C96C8EC113F42C4005483E8 /* libcrypto.dylib */, - ); - name = "External Libs"; - sourceTree = ""; - }; - 1828EA9F14E334E200BE00C2 /* config */ = { - isa = PBXGroup; - children = ( - 1828EAA014E334E200BE00C2 /* base.xcconfig */, - 1828EAA114E334E200BE00C2 /* debug.xcconfig */, - 1828EAA214E334E200BE00C2 /* lib.xcconfig */, - 1828EAA314E334E200BE00C2 /* release.xcconfig */, - ); - path = config; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 053BA310091C00BF00A7007A /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 053BA324091C02B700A7007A /* DER_Decode.h in Headers */, - 053BA325091C02B700A7007A /* libDER_config.h in Headers */, - 053BA326091C02B700A7007A /* libDER.h in Headers */, - 053BA344091C089B00A7007A /* asn1Types.h in Headers */, - 053BA39A091C258100A7007A /* DER_CertCrl.h in Headers */, - 058ECD360920F5E30050AA30 /* DER_Keys.h in Headers */, - 05E0E40709228A5E005F4693 /* DER_Digest.h in Headers */, - 058F163209250D17009FA1C5 /* oids.h in Headers */, - 0544AEA10940939C00DD6C0B /* DER_Encode.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 053BA467091FE63E00A7007A /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 053BA471091FE6C100A7007A /* fileIo.h in Headers */, - 053BA47D091FE7CC00A7007A /* libDERUtils.h in Headers */, - 058F15C20922B73F009FA1C5 /* printFields.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 053BA313091C00BF00A7007A /* libDER */ = { - isa = PBXNativeTarget; - buildConfigurationList = 4CD81A5D09BE1FD2000A9641 /* Build configuration list for PBXNativeTarget "libDER" */; - buildPhases = ( - 053BA310091C00BF00A7007A /* Headers */, - 053BA311091C00BF00A7007A /* Sources */, - 053BA312091C00BF00A7007A /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libDER; - productName = libDER; - productReference = 053BA314091C00BF00A7007A /* libDER.a */; - productType = "com.apple.product-type.library.static"; - }; - 053BA444091FE58C00A7007A /* parseCert */ = { - isa = PBXNativeTarget; - buildConfigurationList = 4CD81A6509BE1FD2000A9641 /* Build configuration list for PBXNativeTarget "parseCert" */; - buildPhases = ( - 053BA442091FE58C00A7007A /* Sources */, - 053BA443091FE58C00A7007A /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 053BA459091FE59900A7007A /* PBXTargetDependency */, - 058ECC56091FF0090050AA30 /* PBXTargetDependency */, - ); - name = parseCert; - productName = parseCert; - productReference = 053BA445091FE58C00A7007A /* parseCert */; - productType = "com.apple.product-type.tool"; - }; - 053BA46A091FE63E00A7007A /* libDERUtils */ = { - isa = PBXNativeTarget; - buildConfigurationList = 4CD81A6109BE1FD2000A9641 /* Build configuration list for PBXNativeTarget "libDERUtils" */; - buildPhases = ( - 053BA467091FE63E00A7007A /* Headers */, - 053BA468091FE63E00A7007A /* Sources */, - 053BA469091FE63E00A7007A /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libDERUtils; - productName = libDERUtils; - productReference = 053BA46B091FE63E00A7007A /* libDERUtils.a */; - productType = "com.apple.product-type.library.static"; - }; - 058F16530925135E009FA1C5 /* parseCrl */ = { - isa = PBXNativeTarget; - buildConfigurationList = 4CD81A6909BE1FD2000A9641 /* Build configuration list for PBXNativeTarget "parseCrl" */; - buildPhases = ( - 058F16510925135E009FA1C5 /* Sources */, - 058F16520925135E009FA1C5 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 058F1676092523D8009FA1C5 /* PBXTargetDependency */, - 058F1678092523DD009FA1C5 /* PBXTargetDependency */, - ); - name = parseCrl; - productName = parseCrl; - productReference = 058F16540925135E009FA1C5 /* parseCrl */; - productType = "com.apple.product-type.tool"; - }; - 4C96C8CD113F4132005483E8 /* parseTicket */ = { - isa = PBXNativeTarget; - buildConfigurationList = 4C96C8D8113F4165005483E8 /* Build configuration list for PBXNativeTarget "parseTicket" */; - buildPhases = ( - 4C96C8CB113F4132005483E8 /* Sources */, - 4C96C8CC113F4132005483E8 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 4C96C8E1113F4223005483E8 /* PBXTargetDependency */, - ); - name = parseTicket; - productName = parseTicket; - productReference = 4C96C8CE113F4132005483E8 /* parseTicket */; - productType = "com.apple.product-type.tool"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 053BA30A091C00A400A7007A /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0500; - }; - buildConfigurationList = 4CD81A7109BE1FD2000A9641 /* Build configuration list for PBXProject "libDER" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - English, - Japanese, - French, - German, - ); - mainGroup = 053BA306091C00A400A7007A; - productRefGroup = 053BA315091C00BF00A7007A /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 053BA30F091C00B100A7007A /* World */, - 053BA313091C00BF00A7007A /* libDER */, - 053BA444091FE58C00A7007A /* parseCert */, - 053BA46A091FE63E00A7007A /* libDERUtils */, - 058F16530925135E009FA1C5 /* parseCrl */, - 4C96C8CD113F4132005483E8 /* parseTicket */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 053BA311091C00BF00A7007A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 053BA345091C089B00A7007A /* DER_Decode.c in Sources */, - 053BA399091C258100A7007A /* DER_CertCrl.c in Sources */, - 058ECD350920F5E30050AA30 /* DER_Keys.c in Sources */, - 05E0E40809228A5E005F4693 /* DER_Digest.c in Sources */, - 058F163109250D16009FA1C5 /* oids.c in Sources */, - 0544AEA20940939C00DD6C0B /* DER_Encode.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 053BA442091FE58C00A7007A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 053BA461091FE60700A7007A /* parseCert.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 053BA468091FE63E00A7007A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 053BA470091FE6C100A7007A /* fileIo.c in Sources */, - 053BA47E091FE7CC00A7007A /* libDERUtils.c in Sources */, - 058F15C30922B73F009FA1C5 /* printFields.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 058F16510925135E009FA1C5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 058F1659092513A7009FA1C5 /* parseCrl.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4C96C8CB113F4132005483E8 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 4C96C8D6113F4165005483E8 /* DER_Ticket.c in Sources */, - 4C96C8D7113F4165005483E8 /* parseTicket.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 053BA317091C017E00A7007A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 053BA313091C00BF00A7007A /* libDER */; - targetProxy = 053BA316091C017E00A7007A /* PBXContainerItemProxy */; - }; - 053BA459091FE59900A7007A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 053BA313091C00BF00A7007A /* libDER */; - targetProxy = 053BA458091FE59900A7007A /* PBXContainerItemProxy */; - }; - 053BA463091FE60E00A7007A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 053BA444091FE58C00A7007A /* parseCert */; - targetProxy = 053BA462091FE60E00A7007A /* PBXContainerItemProxy */; - }; - 058ECC54091FF0000050AA30 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 053BA46A091FE63E00A7007A /* libDERUtils */; - targetProxy = 058ECC53091FF0000050AA30 /* PBXContainerItemProxy */; - }; - 058ECC56091FF0090050AA30 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 053BA46A091FE63E00A7007A /* libDERUtils */; - targetProxy = 058ECC55091FF0090050AA30 /* PBXContainerItemProxy */; - }; - 058F16680925224F009FA1C5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 058F16530925135E009FA1C5 /* parseCrl */; - targetProxy = 058F16670925224F009FA1C5 /* PBXContainerItemProxy */; - }; - 058F1676092523D8009FA1C5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 053BA313091C00BF00A7007A /* libDER */; - targetProxy = 058F1675092523D8009FA1C5 /* PBXContainerItemProxy */; - }; - 058F1678092523DD009FA1C5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 053BA46A091FE63E00A7007A /* libDERUtils */; - targetProxy = 058F1677092523DD009FA1C5 /* PBXContainerItemProxy */; - }; - 4C96C8DC113F4174005483E8 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 4C96C8CD113F4132005483E8 /* parseTicket */; - targetProxy = 4C96C8DB113F4174005483E8 /* PBXContainerItemProxy */; - }; - 4C96C8E1113F4223005483E8 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 053BA313091C00BF00A7007A /* libDER */; - targetProxy = 4C96C8E0113F4223005483E8 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 4C96C8D0113F4132005483E8 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1828EAA114E334E200BE00C2 /* debug.xcconfig */; - buildSettings = { - }; - name = Debug; - }; - 4C96C8D1113F4132005483E8 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1828EAA314E334E200BE00C2 /* release.xcconfig */; - buildSettings = { - }; - name = Release; - }; - 792E01120CBC0CE3007C00A0 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1828EAA114E334E200BE00C2 /* debug.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Debug; - }; - 792E01130CBC0CE3007C00A0 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1828EAA314E334E200BE00C2 /* release.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Release; - }; - 792E01140CBC0CE3007C00A0 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1828EAA114E334E200BE00C2 /* debug.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Debug; - }; - 792E01150CBC0CE3007C00A0 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1828EAA314E334E200BE00C2 /* release.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Release; - }; - 792E01160CBC0CE3007C00A0 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1828EAA114E334E200BE00C2 /* debug.xcconfig */; - buildSettings = { - }; - name = Debug; - }; - 792E01170CBC0CE3007C00A0 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1828EAA314E334E200BE00C2 /* release.xcconfig */; - buildSettings = { - }; - name = Release; - }; - 792E01180CBC0CE3007C00A0 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1828EAA114E334E200BE00C2 /* debug.xcconfig */; - buildSettings = { - }; - name = Debug; - }; - 792E01190CBC0CE3007C00A0 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1828EAA314E334E200BE00C2 /* release.xcconfig */; - buildSettings = { - }; - name = Release; - }; - 792E011A0CBC0CE3007C00A0 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1828EAA114E334E200BE00C2 /* debug.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Debug; - }; - 792E011B0CBC0CE3007C00A0 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1828EAA314E334E200BE00C2 /* release.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Release; - }; - 792E011C0CBC0CE3007C00A0 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1828EAA214E334E200BE00C2 /* lib.xcconfig */; - buildSettings = { - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - }; - name = Debug; - }; - 792E011D0CBC0CE3007C00A0 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1828EAA214E334E200BE00C2 /* lib.xcconfig */; - buildSettings = { - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 4C96C8D8113F4165005483E8 /* Build configuration list for PBXNativeTarget "parseTicket" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 4C96C8D0113F4132005483E8 /* Debug */, - 4C96C8D1113F4132005483E8 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 4CD81A5D09BE1FD2000A9641 /* Build configuration list for PBXNativeTarget "libDER" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 792E01120CBC0CE3007C00A0 /* Debug */, - 792E01130CBC0CE3007C00A0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 4CD81A6109BE1FD2000A9641 /* Build configuration list for PBXNativeTarget "libDERUtils" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 792E01140CBC0CE3007C00A0 /* Debug */, - 792E01150CBC0CE3007C00A0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 4CD81A6509BE1FD2000A9641 /* Build configuration list for PBXNativeTarget "parseCert" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 792E01160CBC0CE3007C00A0 /* Debug */, - 792E01170CBC0CE3007C00A0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 4CD81A6909BE1FD2000A9641 /* Build configuration list for PBXNativeTarget "parseCrl" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 792E01180CBC0CE3007C00A0 /* Debug */, - 792E01190CBC0CE3007C00A0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 4CD81A6D09BE1FD2000A9641 /* Build configuration list for PBXAggregateTarget "World" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 792E011A0CBC0CE3007C00A0 /* Debug */, - 792E011B0CBC0CE3007C00A0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 4CD81A7109BE1FD2000A9641 /* Build configuration list for PBXProject "libDER" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 792E011C0CBC0CE3007C00A0 /* Debug */, - 792E011D0CBC0CE3007C00A0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 053BA30A091C00A400A7007A /* Project object */; -} diff --git a/libsecurity_keychain/libDER/libDER.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_keychain/libDER/libDER.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 6ace9d59..00000000 --- a/libsecurity_keychain/libDER/libDER.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,39 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 053BA30F091C00B100A7007A - - primary - - - 053BA313091C00BF00A7007A - - primary - - - 053BA444091FE58C00A7007A - - primary - - - 053BA46A091FE63E00A7007A - - primary - - - 058F16530925135E009FA1C5 - - primary - - - 4C96C8CD113F4132005483E8 - - primary - - - - - diff --git a/libsecurity_keychain/libDER/libDER/DER_Digest.h b/libsecurity_keychain/libDER/libDER/DER_Digest.h deleted file mode 100644 index 9dd361ad..00000000 --- a/libsecurity_keychain/libDER/libDER/DER_Digest.h +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (c) 2005-2008,2010 Apple Inc. All Rights Reserved. */ - -/* - * DER_Digest.h - DER encode a DigestInfo - * - * Created Nov. 9 2005 by dmitch - */ - -#ifndef _DER_DIGEST_H_ -#define _DER_DIGEST_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/* - * Create an encoded DigestInfo based on the specified SHA1 digest. - * The incoming digest must be 20 bytes long. - * - * Result is placed in caller's buffer, which must be at least of - * length DER_SHA1_DIGEST_INFO_LEN bytes. - * - * The *resultLen parameter is the available size in the result - * buffer on input, and the actual length of the encoded DigestInfo - * on output. - */ -#define DER_SHA1_DIGEST_LEN 20 -#define DER_SHA1_DIGEST_INFO_LEN 35 - -DERReturn DEREncodeSHA1DigestInfo( - const DERByte *sha1Digest, - DERSize sha1DigestLen, - DERByte *result, /* encoded result RETURNED here */ - DERSize *resultLen); /* IN/OUT */ - -#define DER_SHA256_DIGEST_LEN 32 -#define DER_SHA256_DIGEST_INFO_LEN 51 - -DERReturn DEREncodeSHA256DigestInfo( - const DERByte *sha256Digest, - DERSize sha256DigestLen, - DERByte *result, /* encoded result RETURNED here */ - DERSize *resultLen); /* IN/OUT */ - -/* - * Likewise, create an encoded DIgestInfo for specified MD5 or MD2 digest. - */ -#define DER_MD_DIGEST_LEN 16 -#define DER_MD_DIGEST_INFO_LEN 34 - -typedef enum { - WD_MD2 = 1, - WD_MD5 = 2 -} WhichDigest; - -DERReturn DEREncodeMDDigestInfo( - WhichDigest whichDigest, - const DERByte *mdDigest, - DERSize mdDigestLen, - DERByte *result, /* encoded result RETURNED here */ - DERSize *resultLen); /* IN/OUT */ - -/* max sizes you'll need in the general cases */ -#define DER_MAX_DIGEST_LEN DER_SHA256_DIGEST_LEN -#define DER_MAX_ENCODED_INFO_LEN DER_SHA256_DIGEST_INFO_LEN - -#ifdef __cplusplus -} -#endif - -#endif /* _DER_DIGEST_H_ */ - diff --git a/libsecurity_keychain/libDER/libDER/DER_Encode.h b/libsecurity_keychain/libDER/libDER/DER_Encode.h deleted file mode 100644 index f5728800..00000000 --- a/libsecurity_keychain/libDER/libDER/DER_Encode.h +++ /dev/null @@ -1,103 +0,0 @@ -/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */ - -/* - * DER_Encode.h - DER encoding routines - * - * Created Dec. 2 2005 by dmitch - */ - -#ifndef _DER_ENCCODE_H_ -#define _DER_ENCODE_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/* - * Max size of an encoded item given its length. - * This includes a possible leading zero prepended to a signed integer - * (see DER_ENC_SIGNED_INT below). - */ -#define DER_MAX_ENCODED_SIZE(len) \ - ( 1 + /* tag */ \ - 5 + /* max length */ \ - 1 + /* possible prepended zero */ \ - len) - -/* calculate size of encoded length */ -DERSize DERLengthOfLength( - DERSize length); - -/* encode length */ -DERReturn DEREncodeLength( - DERSize length, - DERByte *buf, /* encoded length goes here */ - DERSize *inOutLen); /* IN/OUT */ - -/* calculate size of encoded length */ -DERSize DERLengthOfItem( - DERTag tag, - DERSize length); - -/* encode item */ -DERReturn DEREncodeItem( - DERTag tag, - DERSize length, - const DERByte *src, - DERByte *derOut, /* encoded item goes here */ - DERSize *inOutLen); /* IN/OUT */ - -/* - * Per-item encode options. - */ - -/* explicit default, no options */ -#define DER_ENC_NO_OPTS 0x0000 - -/* signed integer check: if incoming m.s. bit is 1, prepend a zero */ -#define DER_ENC_SIGNED_INT 0x0100 - -/* DERItem contains fully encoded item - copy, don't encode */ -#define DER_ENC_WRITE_DER 0x0200 - - -/* - * High-level sequence or set encode support. - * - * The outgoing sequence is expressed as an array of DERItemSpecs, each - * of which corresponds to one item in the encoded sequence. - * - * Normally the tag of the encoded item comes from the associated - * DERItemSpec, and the content comes from the DERItem whose address is - * the src arg plus the offset value in the associated DERItemSpec. - * - * If the DER_ENC_WRITE_DER option is true for a given DERItemSpec then - * no per-item encoding is done; the DER - with tag, length, and content - - * is taken en masse from the associated DERItem. - */ -DERReturn DEREncodeSequence( - DERTag topTag, /* ASN1_CONSTR_SEQUENCE, ASN1_CONSTR_SET */ - const void *src, /* generally a ptr to a struct full of - * DERItems */ - DERShort numItems, /* size of itemSpecs[] */ - const DERItemSpec *itemSpecs, - DERByte *derOut, /* encoded data written here */ - DERSize *inOutLen); /* IN/OUT */ - -/* precalculate the length of an encoded sequence. */ -DERSize DERLengthOfEncodedSequence( - DERTag topTag, /* ASN1_CONSTR_SEQUENCE, ASN1_CONSTR_SET */ - const void *src, /* generally a ptr to a struct full of - * DERItems */ - DERShort numItems, /* size of itemSpecs[] */ - const DERItemSpec *itemSpecs); - - -#ifdef __cplusplus -} -#endif - -#endif /* _DER_DECODE_H_ */ - diff --git a/libsecurity_keychain/libDER/libDER/DER_Keys.h b/libsecurity_keychain/libDER/libDER/DER_Keys.h deleted file mode 100644 index 356d52cf..00000000 --- a/libsecurity_keychain/libDER/libDER/DER_Keys.h +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */ - -/* - * DER_Keys.h - support for decoding RSA keys - * - * Created Nov. 8 2005 by dmitch - */ - -#ifndef _DER_KEYS_H_ -#define _DER_KEYS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -/* Algorithm Identifier components */ -typedef struct { - DERItem oid; /* OID */ - DERItem params; /* ASN_ANY, optional, DER_DEC_SAVE_DER */ -} DERAlgorithmId; - -/* DERItemSpecs to decode into a DERAlgorithmId */ -extern const DERItemSpec DERAlgorithmIdItemSpecs[]; -extern const DERSize DERNumAlgorithmIdItemSpecs; - -/* X509 SubjectPublicKeyInfo */ -typedef struct { - DERItem algId; /* sequence, DERAlgorithmId */ - DERItem pubKey; /* BIT STRING */ -} DERSubjPubKeyInfo; - -/* DERItemSpecs to decode into a DERSubjPubKeyInfo */ -extern const DERItemSpec DERSubjPubKeyInfoItemSpecs[]; -extern const DERSize DERNumSubjPubKeyInfoItemSpecs; - -/* - * RSA public key in PKCS1 format; this is inside the BIT_STRING in - * DERSubjPubKeyInfo.pubKey. - */ -typedef struct { - DERItem modulus; /* n - INTEGER */ - DERItem pubExponent; /* e - INTEGER */ -} DERRSAPubKeyPKCS1; - -/* DERItemSpecs to decode/encode into/from a DERRSAPubKeyPKCS1 */ -extern const DERItemSpec DERRSAPubKeyPKCS1ItemSpecs[]; -extern const DERSize DERNumRSAPubKeyPKCS1ItemSpecs; - -/* - * RSA public key in custom (to this library) format, including - * the reciprocal. All fields are integers. - */ -typedef struct { - DERItem modulus; /* n */ - DERItem reciprocal; /* reciprocal of modulus */ - DERItem pubExponent; /* e */ -} DERRSAPubKeyApple; - -/* DERItemSpecs to decode/encode into/from a DERRSAPubKeyApple */ -extern const DERItemSpec DERRSAPubKeyAppleItemSpecs[]; -extern const DERSize DERNumRSAPubKeyAppleItemSpecs; - -/* - * RSA Private key, PKCS1 format, CRT option. - * All fields are integers. - */ -typedef struct { - DERItem p; /* p * q = n */ - DERItem q; - DERItem dp; /* d mod (p-1) */ - DERItem dq; /* d mod (q-1) */ - DERItem qInv; -} DERRSAPrivKeyCRT; - -/* DERItemSpecs to decode into a DERRSAPrivKeyCRT */ -extern const DERItemSpec DERRSAPrivKeyCRTItemSpecs[]; -extern const DERSize DERNumRSAPrivKeyCRTItemSpecs; - -/* Fully formed RSA key pair, for generating a PKCS1 private key */ -typedef struct { - DERItem version; - DERItem n; /* modulus */ - DERItem e; /* public exponent */ - DERItem d; /* private exponent */ - DERItem p; /* n = p*q */ - DERItem q; - DERItem dp; /* d mod (p-1) */ - DERItem dq; /* d mod (q-1) */ - DERItem qInv; /* q^(-1) mod p */ -} DERRSAKeyPair; - -/* DERItemSpecs to encode a DERRSAKeyPair */ -extern const DERItemSpec DERRSAKeyPairItemSpecs[]; -extern const DERSize DERNumRSAKeyPairItemSpecs; - -#ifdef __cplusplus -} -#endif - -#endif /* _DER_KEYS_H_ */ - diff --git a/libsecurity_keychain/libDER/libDER/asn1Types.h b/libsecurity_keychain/libDER/libDER/asn1Types.h deleted file mode 100644 index 1bf25983..00000000 --- a/libsecurity_keychain/libDER/libDER/asn1Types.h +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */ - -/* - * asn1Types.h - ASN.1/DER #defines - strictly hard coded per the real world - * - * Created Nov. 4 2005 by dmitch - */ - -#ifndef _ASN1_TYPES_H_ -#define _ASN1_TYPES_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* copied from libsecurity_asn1 project */ - -#define ASN1_BOOLEAN 0x01 -#define ASN1_INTEGER 0x02 -#define ASN1_BIT_STRING 0x03 -#define ASN1_OCTET_STRING 0x04 -#define ASN1_NULL 0x05 -#define ASN1_OBJECT_ID 0x06 -#define ASN1_OBJECT_DESCRIPTOR 0x07 -/* External type and instance-of type 0x08 */ -#define ASN1_REAL 0x09 -#define ASN1_ENUMERATED 0x0a -#define ASN1_EMBEDDED_PDV 0x0b -#define ASN1_UTF8_STRING 0x0c -/* 0x0d */ -/* 0x0e */ -/* 0x0f */ -#define ASN1_SEQUENCE 0x10 -#define ASN1_SET 0x11 -#define ASN1_NUMERIC_STRING 0x12 -#define ASN1_PRINTABLE_STRING 0x13 -#define ASN1_T61_STRING 0x14 -#define ASN1_VIDEOTEX_STRING 0x15 -#define ASN1_IA5_STRING 0x16 -#define ASN1_UTC_TIME 0x17 -#define ASN1_GENERALIZED_TIME 0x18 -#define ASN1_GRAPHIC_STRING 0x19 -#define ASN1_VISIBLE_STRING 0x1a -#define ASN1_GENERAL_STRING 0x1b -#define ASN1_UNIVERSAL_STRING 0x1c -/* 0x1d */ -#define ASN1_BMP_STRING 0x1e -#define ASN1_HIGH_TAG_NUMBER 0x1f -#define ASN1_TELETEX_STRING ASN1_T61_STRING - -#ifdef DER_MULTIBYTE_TAGS - -#define ASN1_TAG_MASK ((DERTag)~0) -#define ASN1_TAGNUM_MASK ((DERTag)~((DERTag)7 << (sizeof(DERTag) * 8 - 3))) - -#define ASN1_METHOD_MASK ((DERTag)1 << (sizeof(DERTag) * 8 - 3)) -#define ASN1_PRIMITIVE ((DERTag)0 << (sizeof(DERTag) * 8 - 3)) -#define ASN1_CONSTRUCTED ((DERTag)1 << (sizeof(DERTag) * 8 - 3)) - -#define ASN1_CLASS_MASK ((DERTag)3 << (sizeof(DERTag) * 8 - 2)) -#define ASN1_UNIVERSAL ((DERTag)0 << (sizeof(DERTag) * 8 - 2)) -#define ASN1_APPLICATION ((DERTag)1 << (sizeof(DERTag) * 8 - 2)) -#define ASN1_CONTEXT_SPECIFIC ((DERTag)2 << (sizeof(DERTag) * 8 - 2)) -#define ASN1_PRIVATE ((DERTag)3 << (sizeof(DERTag) * 8 - 2)) - -#else /* DER_MULTIBYTE_TAGS */ - -#define ASN1_TAG_MASK 0xff -#define ASN1_TAGNUM_MASK 0x1f -#define ASN1_METHOD_MASK 0x20 -#define ASN1_PRIMITIVE 0x00 -#define ASN1_CONSTRUCTED 0x20 - -#define ASN1_CLASS_MASK 0xc0 -#define ASN1_UNIVERSAL 0x00 -#define ASN1_APPLICATION 0x40 -#define ASN1_CONTEXT_SPECIFIC 0x80 -#define ASN1_PRIVATE 0xc0 - -#endif /* !DER_MULTIBYTE_TAGS */ - -/* sequence and set appear as the following */ -#define ASN1_CONSTR_SEQUENCE (ASN1_CONSTRUCTED | ASN1_SEQUENCE) -#define ASN1_CONSTR_SET (ASN1_CONSTRUCTED | ASN1_SET) - -#ifdef __cplusplus -} -#endif - -#endif /* _ASN1_TYPES_H_ */ - diff --git a/libsecurity_keychain/libDER/libDER/libDER.h b/libsecurity_keychain/libDER/libDER/libDER.h deleted file mode 100644 index 20b606d3..00000000 --- a/libsecurity_keychain/libDER/libDER/libDER.h +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */ - -/* - * libDER.h - main header for libDER, a ROM-capable DER decoding library. - * - * Created Nov. 4 2005 by dmitch - */ - -#ifndef _LIB_DER_H_ -#define _LIB_DER_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -/* - * Error returns generated by this library. - */ -typedef enum { - DR_Success, - DR_EndOfSequence, /* end of sequence or set */ - DR_UnexpectedTag, /* unexpected tag found while decoding */ - DR_DecodeError, /* misc. decoding error (badly formatted DER) */ - DR_Unimplemented, /* function not implemented in this configuration */ - DR_IncompleteSeq, /* incomplete sequence */ - DR_ParamErr, /* incoming parameter error */ - DR_BufOverflow /* buffer overflow */ - /* etc. */ -} DERReturn; - -/* - * Primary representation of a block of memory. - */ -typedef struct { - DERByte *data; - DERSize length; -} DERItem; - -/* - * The structure of a sequence during decode or encode is expressed as - * an array of DERItemSpecs. While decoding or encoding a sequence, - * each item in the sequence corresponds to one DERItemSpec. - */ -typedef struct { - DERSize offset; /* offset of destination DERItem */ - DERTag tag; /* DER tag */ - DERShort options; /* DER_DEC_xxx or DER_ENC_xxx */ -} DERItemSpec; - -/* - * Macro to obtain offset of a DERDecodedInfo within a struct. - * FIXME this is going to need reworking to avoid compiler warnings - * on 64-bit compiles. It'll work OK as long as an offset can't be larger - * than a DERSize, but the cast from a pointer to a DERSize may - * provoke compiler warnings. - */ -#define DER_OFFSET(type, field) ((DERSize)(&((type *)0)->field)) - -#ifdef __cplusplus -} -#endif - -#endif /* _LIB_DER_H_ */ - diff --git a/libsecurity_keychain/libDER/libDER/libDER_config.h b/libsecurity_keychain/libDER/libDER/libDER_config.h deleted file mode 100644 index d4fa21e6..00000000 --- a/libsecurity_keychain/libDER/libDER/libDER_config.h +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */ - -/* - * libDER_config.h - platform dependent #defines and typedefs for libDER - * - * Created Nov. 4 2005 by dmitch - */ - -#ifndef _LIB_DER_CONFIG_H_ -#define _LIB_DER_CONFIG_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Basic data types: unsigned 8-bit integer, unsigned 32-bit integer - */ -typedef uint8_t DERByte; -typedef uint16_t DERShort; -typedef size_t DERSize; - -/* - * Use these #defines of you have memset, memmove, and memcmp; else - * write your own equivalents. - */ - -#define DERMemset(ptr, c, len) memset(ptr, c, len) -#define DERMemmove(dst, src, len) memmove(dst, src, len) -#define DERMemcmp(b1, b2, len) memcmp(b1, b2, len) - - -/*** - *** Compile time options to trim size of the library. - ***/ - -/* enable general DER encode */ -#define DER_ENCODE_ENABLE 1 - -/* enable general DER decode */ -#define DER_DECODE_ENABLE 1 - -#ifndef DER_MULTIBYTE_TAGS -/* enable multibyte tag support. */ -#define DER_MULTIBYTE_TAGS 1 -#endif - -#ifndef DER_TAG_SIZE -/* Iff DER_MULTIBYTE_TAGS is 1 this is the sizeof(DERTag) in bytes. Note that - tags are still encoded and decoded from a minimally encoded DER - represantation. This value determines how big each DERItemSpecs is, we - choose 2 since that makes DERItemSpecs 8 bytes wide. */ -#define DER_TAG_SIZE 2 -#endif - - -/* ---------------------- Do not edit below this line ---------------------- */ - -/* - * Logical representation of a tag (the encoded representation is always in - * the minimal number of bytes). The top 3 bits encode class and method - * The remaining bits encode the tag value. To obtain smaller DERItemSpecs - * sizes, choose the smallest type that fits your needs. Most standard ASN.1 - * usage only needs single byte tags, but ocasionally custom applications - * require a larger tag namespace. - */ -#if DER_MULTIBYTE_TAGS - -#if DER_TAG_SIZE == 1 -typedef uint8_t DERTag; -#elif DER_TAG_SIZE == 2 -typedef uint16_t DERTag; -#elif DER_TAG_SIZE == 4 -typedef uint32_t DERTag; -#elif DER_TAG_SIZE == 8 -typedef uint64_t DERTag; -#else -#error DER_TAG_SIZE invalid -#endif - -#else /* DER_MULTIBYTE_TAGS */ -typedef DERByte DERTag; -#endif /* !DER_MULTIBYTE_TAGS */ - -#ifdef __cplusplus -} -#endif - -#endif /* _LIB_DER_CONFIG_H_ */ diff --git a/libsecurity_keychain/libDER/libDER/oids.h b/libsecurity_keychain/libDER/libDER/oids.h deleted file mode 100644 index e9faf5a6..00000000 --- a/libsecurity_keychain/libDER/libDER/oids.h +++ /dev/null @@ -1,112 +0,0 @@ -/* Copyright (c) 2005-2009 Apple Inc. All Rights Reserved. */ - -/* - * oids.h - declaration of OID consts - * - * Created Nov. 11 2005 by dmitch - */ - -#ifndef _LIB_DER_OIDS_H_ -#define _LIB_DER_OIDS_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Algorithm oids. */ -extern const DERItem - oidRsa, /* PKCS1 RSA encryption, used to identify RSA keys */ - oidMd2Rsa, /* PKCS1 md2withRSAEncryption signature alg */ - oidMd5Rsa, /* PKCS1 md5withRSAEncryption signature alg */ - oidSha1Rsa, /* PKCS1 sha1withRSAEncryption signature alg */ - oidSha256Rsa, /* PKCS1 sha256WithRSAEncryption signature alg */ - oidEcPubKey, /* ECDH or ECDSA public key in a certificate */ - oidSha1Ecdsa, /* ECDSA with SHA1 signature alg */ - oidSha224Ecdsa, /* ECDSA with SHA224 signature alg */ - oidSha256Ecdsa, /* ECDSA with SHA256 signature alg */ - oidSha384Ecdsa, /* ECDSA with SHA384 signature alg */ - oidSha512Ecdsa, /* ECDSA with SHA512 signature alg */ - oidMd2, /* OID_RSA_HASH 2 */ - oidMd4, /* OID_RSA_HASH 4 */ - oidMd5, /* OID_RSA_HASH 5 */ - oidSha1, /* OID_OIW_ALGORITHM 26 */ - oidSha256, /* OID_NIST_HASHALG 1 */ - oidSha384, /* OID_NIST_HASHALG 2 */ - oidSha512, /* OID_NIST_HASHALG 3 */ - oidSha224; /* OID_NIST_HASHALG 4 */ - -/* Standard X.509 Cert and CRL extensions. */ -extern const DERItem - oidSubjectKeyIdentifier, - oidKeyUsage, - oidPrivateKeyUsagePeriod, - oidSubjectAltName, - oidIssuerAltName, - oidBasicConstraints, - oidCrlDistributionPoints, - oidCertificatePolicies, - oidAnyPolicy, - oidPolicyMappings, - oidAuthorityKeyIdentifier, - oidPolicyConstraints, - oidExtendedKeyUsage, - oidAnyExtendedKeyUsage, - oidInhibitAnyPolicy, - oidAuthorityInfoAccess, - oidSubjectInfoAccess, - oidAdOCSP, - oidAdCAIssuer, - oidNetscapeCertType, - oidEntrustVersInfo, - oidMSNTPrincipalName, - /* Policy Qualifier IDs for Internet policy qualifiers. */ - oidQtCps, - oidQtUNotice, - /* X.501 Name IDs. */ - oidCommonName, - oidCountryName, - oidLocalityName, - oidStateOrProvinceName, - oidOrganizationName, - oidOrganizationalUnitName, - oidDescription, - oidEmailAddress, - oidFriendlyName, - oidLocalKeyId, - oidExtendedKeyUsageServerAuth, - oidExtendedKeyUsageClientAuth, - oidExtendedKeyUsageCodeSigning, - oidExtendedKeyUsageEmailProtection, - oidExtendedKeyUsageOCSPSigning, - oidExtendedKeyUsageIPSec, - oidExtendedKeyUsageMicrosoftSGC, - oidExtendedKeyUsageNetscapeSGC, - /* Secure Boot Spec oid */ - oidAppleSecureBootCertSpec, - oidAppleProvisioningProfile, - oidAppleApplicationSigning, - oidAppleInstallerPackagingSigningExternal, - oidAppleExtendedKeyUsageAppleID, - oidAppleExtendedKeyUsageShoebox, - oidAppleExtendedKeyUsageProfileSigning, - oidAppleExtendedKeyUsageQAProfileSigning, - oidAppleIntmMarkerAppleID, - oidAppleIntmMarkerAppleID2, - oidApplePushServiceClient, - oidApplePolicyMobileStore, - oidApplePolicyTestMobileStore, - oidApplePolicyEscrowService, - oidAppleCertExtensionAppleIDRecordValidationSigning, - oidAppleIntmMarkerAppleSystemIntg2; - -/* Compare two decoded OIDs. Returns true iff they are equivalent. */ -bool DEROidCompare(const DERItem *oid1, const DERItem *oid2); - -#ifdef __cplusplus -} -#endif - -#endif /* _LIB_DER_UTILS_H_ */ diff --git a/libsecurity_keychain/libDER/libDERUtils/fileIo.c b/libsecurity_keychain/libDER/libDERUtils/fileIo.c deleted file mode 100644 index fec82702..00000000 --- a/libsecurity_keychain/libDER/libDERUtils/fileIo.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2005-2007,2010 Apple Inc. All Rights Reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "fileIo.h" - -int writeFile( - const char *fileName, - const unsigned char *bytes, - unsigned numBytes) -{ - int rtn; - int fd; - - fd = open(fileName, O_RDWR | O_CREAT | O_TRUNC, 0600); - if(fd <= 0) { - return errno; - } - rtn = (int)write(fd, bytes, (size_t)numBytes); - if(rtn != (int)numBytes) { - if(rtn >= 0) { - fprintf(stderr, "writeFile: short write\n"); - } - rtn = EIO; - } - else { - rtn = 0; - } - close(fd); - return rtn; -} - -/* - * Read entire file. - */ -int readFile( - const char *fileName, - unsigned char **bytes, // mallocd and returned - unsigned *numBytes) // returned -{ - int rtn; - int fd; - char *buf; - struct stat sb; - unsigned size; - - *numBytes = 0; - *bytes = NULL; - fd = open(fileName, O_RDONLY, 0); - if(fd <= 0) { - return errno; - } - rtn = fstat(fd, &sb); - if(rtn) { - goto errOut; - } - size = (unsigned) sb.st_size; - buf = (char *)malloc(size); - if(buf == NULL) { - rtn = ENOMEM; - goto errOut; - } - rtn = (int)read(fd, buf, size); - if(rtn != size) { - if(rtn >= 0) { - fprintf(stderr, "readFile: short read\n"); - } - rtn = EIO; - } - else { - rtn = 0; - *bytes = (unsigned char *)buf; - *numBytes = size; - } -errOut: - close(fd); - return rtn; -} diff --git a/libsecurity_keychain/libDER/libDERUtils/fileIo.h b/libsecurity_keychain/libDER/libDERUtils/fileIo.h deleted file mode 100644 index e215e867..00000000 --- a/libsecurity_keychain/libDER/libDERUtils/fileIo.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2005-2007,2010 Apple Inc. All Rights Reserved. - */ - -#ifndef _DER_FILE_IO_H_ -#define _DER_FILE_IO_H_ - -/* - * Read entire file. - */ -#ifdef __cplusplus -extern "C" { -#endif - -int readFile( - const char *fileName, - unsigned char **bytes, // mallocd and returned - unsigned *numBytes); // returned - -int writeFile( - const char *fileName, - const unsigned char *bytes, - unsigned numBytes); - -#ifdef __cplusplus -} -#endif - -#endif /* _DER_FILE_IO_H_ */ diff --git a/libsecurity_keychain/libDER/libDERUtils/libDERUtils.c b/libsecurity_keychain/libDER/libDERUtils/libDERUtils.c deleted file mode 100644 index 4846505f..00000000 --- a/libsecurity_keychain/libDER/libDERUtils/libDERUtils.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */ - -/* - * libDERUtils.c - support routines for libDER tests & examples - * - * Created Nov. 7 2005 by dmitch - */ - -#include -#include - -const char *DERReturnString( - DERReturn drtn) -{ - static char unknown[128]; - - switch(drtn) { - case DR_Success: return "DR_Success"; - case DR_EndOfSequence: return "DR_EndOfSequence"; - case DR_UnexpectedTag: return "DR_UnexpectedTag"; - case DR_DecodeError: return "DR_DecodeError"; - case DR_Unimplemented: return "DR_Unimplemented"; - case DR_IncompleteSeq: return "DR_IncompleteSeq"; - default: - sprintf(unknown, "Unknown error (%d)", (int)drtn); - return unknown; - } -} - -void DERPerror( - const char *op, - DERReturn drtn) -{ - fprintf(stderr, "*** %s: %s\n", op, DERReturnString(drtn)); -} - diff --git a/libsecurity_keychain/libDER/libDERUtils/libDERUtils.h b/libsecurity_keychain/libDER/libDERUtils/libDERUtils.h deleted file mode 100644 index a053fdbe..00000000 --- a/libsecurity_keychain/libDER/libDERUtils/libDERUtils.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */ - -/* - * libDERUtils.h - support routines for libDER tests & examples - * - * Created Nov. 7 2005 by dmitch - */ - -#ifndef _LIB_DER_UTILS_H_ -#define _LIB_DER_UTILS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -const char *DERReturnString( - DERReturn drtn); - -void DERPerror( - const char *op, - DERReturn rtn); - -#ifdef __cplusplus -} -#endif - -#endif /* _LIB_DER_UTILS_H_ */ diff --git a/libsecurity_keychain/libDER/libDERUtils/printFields.h b/libsecurity_keychain/libDER/libDERUtils/printFields.h deleted file mode 100644 index 9ed0b4a4..00000000 --- a/libsecurity_keychain/libDER/libDERUtils/printFields.h +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */ - -/* - * printFeilds.h - print various DER objects - * - * Created Nov. 9 2005 by dmitch - */ - -#ifndef _PRINT_FIELDS_H_ -#define _PRINT_FIELDS_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -void doIndent(void); -void incrIndent(void); -void decrIndent(void); -void printHex(DERItem *item); -void printBitString(DERItem *item); -void printString(DERItem *item); -void printHeader(const char *label); - -typedef enum { - IT_Leaf, // leaf; always print contents - IT_Branch // branch; print contents iff verbose -} ItemType; - -void printItem( - const char *label, - ItemType itemType, - int verbose, - DERTag tag, // maybe from decoding, maybe the real tag underlying - // an implicitly tagged item - DERItem *item); // content - -void printAlgId( - const DERItem *content, - int verbose); -void printSubjPubKeyInfo( - const DERItem *content, - int verbose); - -/* decode one item and print it */ -void decodePrintItem( - const char *label, - ItemType itemType, - int verbose, - DERItem *derItem); - -#ifdef __cplusplus -} -#endif - -#endif /* _PRINT_FIELDS_H_ */ diff --git a/libsecurity_keychain/libsecurity_keychain.xcodeproj/project.pbxproj b/libsecurity_keychain/libsecurity_keychain.xcodeproj/project.pbxproj deleted file mode 100644 index 2f87ea53..00000000 --- a/libsecurity_keychain/libsecurity_keychain.xcodeproj/project.pbxproj +++ /dev/null @@ -1,1315 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 05012D46060B94A000C044CB /* SecImportExportCrypto.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05012D45060B94A000C044CB /* SecImportExportCrypto.cpp */; }; - 05012D4A060B94B200C044CB /* SecImportExportCrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 05012D49060B94B200C044CB /* SecImportExportCrypto.h */; settings = {ATTRIBUTES = (); }; }; - 051A034805D9A68C00E02A64 /* SecImportExportAgg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 051A034705D9A68C00E02A64 /* SecImportExportAgg.cpp */; }; - 051A035005D9A69900E02A64 /* SecImportExportAgg.h in Headers */ = {isa = PBXBuildFile; fileRef = 051A034F05D9A69900E02A64 /* SecImportExportAgg.h */; settings = {ATTRIBUTES = (); }; }; - 051A053305DAC86400E02A64 /* SecImportExportPem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 051A053205DAC86400E02A64 /* SecImportExportPem.cpp */; }; - 052AF723060A3472003FEB8D /* SecWrappedKeys.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 052AF722060A3472003FEB8D /* SecWrappedKeys.cpp */; }; - 054F90AE05E2860E0013C1D1 /* SecImportExportUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 054F90AD05E2860E0013C1D1 /* SecImportExportUtils.cpp */; }; - 054F90B005E286180013C1D1 /* SecImportExportUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 054F90AF05E286180013C1D1 /* SecImportExportUtils.h */; settings = {ATTRIBUTES = (); }; }; - 055EA6B106AC5C13005079CE /* TrustRevocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 055EA6B006AC5C13005079CE /* TrustRevocation.cpp */; }; - 056CDA3905FD573B00820BC3 /* SecImportExportPkcs8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 056CDA3805FD573B00820BC3 /* SecImportExportPkcs8.cpp */; }; - 056CDA5D05FD5AEB00820BC3 /* SecPkcs8Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 056CDA5C05FD5AEB00820BC3 /* SecPkcs8Templates.h */; }; - 056CDA6505FD5B3400820BC3 /* SecPkcs8Templates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 056CDA6405FD5B3400820BC3 /* SecPkcs8Templates.cpp */; }; - 056CDA8E05FD63C200820BC3 /* SecImportExportPkcs8.h in Headers */ = {isa = PBXBuildFile; fileRef = 056CDA8D05FD63C200820BC3 /* SecImportExportPkcs8.h */; settings = {ATTRIBUTES = (); }; }; - 058AA95A05D93B4300F543ED /* SecExport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 058AA95805D93B4300F543ED /* SecExport.cpp */; }; - 058AA95B05D93B4300F543ED /* SecImportExport.h in Headers */ = {isa = PBXBuildFile; fileRef = 058AA95905D93B4300F543ED /* SecImportExport.h */; settings = {ATTRIBUTES = (); }; }; - 058AA96C05D93CDD00F543ED /* SecImport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 058AA96B05D93CDD00F543ED /* SecImport.cpp */; }; - 058AA9CA05D96FD200F543ED /* SecExternalRep.h in Headers */ = {isa = PBXBuildFile; fileRef = 058AA9C905D96FD200F543ED /* SecExternalRep.h */; settings = {ATTRIBUTES = (); }; }; - 058AA9CE05D96FE600F543ED /* SecExternalRep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 058AA9CD05D96FE600F543ED /* SecExternalRep.cpp */; }; - 058AAA9205D97EAE00F543ED /* SecImportExportPem.h in Headers */ = {isa = PBXBuildFile; fileRef = 058AAA9105D97EAE00F543ED /* SecImportExportPem.h */; settings = {ATTRIBUTES = (); }; }; - 058C797109F56CCB00DB7E98 /* SecTrustSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 058C796F09F56CCB00DB7E98 /* SecTrustSettings.h */; settings = {ATTRIBUTES = (); }; }; - 058C797209F56CCC00DB7E98 /* SecTrustSettingsPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 058C797009F56CCB00DB7E98 /* SecTrustSettingsPriv.h */; settings = {ATTRIBUTES = (); }; }; - 058C797609F56CFB00DB7E98 /* SecTrustSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 058C797509F56CFB00DB7E98 /* SecTrustSettings.cpp */; }; - 058C797C09F56D1400DB7E98 /* TrustSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 058C797709F56D1400DB7E98 /* TrustSettings.cpp */; }; - 058C797D09F56D1400DB7E98 /* TrustSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 058C797809F56D1400DB7E98 /* TrustSettings.h */; settings = {ATTRIBUTES = (); }; }; - 058C797E09F56D1400DB7E98 /* TrustSettingsSchema.h in Headers */ = {isa = PBXBuildFile; fileRef = 058C797909F56D1400DB7E98 /* TrustSettingsSchema.h */; settings = {ATTRIBUTES = (); }; }; - 058C797F09F56D1400DB7E98 /* TrustSettingsUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 058C797A09F56D1400DB7E98 /* TrustSettingsUtils.cpp */; }; - 058C798009F56D1400DB7E98 /* TrustSettingsUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 058C797B09F56D1400DB7E98 /* TrustSettingsUtils.h */; settings = {ATTRIBUTES = (); }; }; - 05A83C380AAF591100906F28 /* SecKeychainItemExtendedAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 05A83C360AAF591100906F28 /* SecKeychainItemExtendedAttributes.h */; settings = {ATTRIBUTES = (); }; }; - 05A83C800AAF5CEA00906F28 /* ExtendedAttribute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05A83C7E0AAF5CEA00906F28 /* ExtendedAttribute.cpp */; }; - 05A83C880AAF5E0A00906F28 /* SecKeychainItemExtendedAttributes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05A83C870AAF5E0A00906F28 /* SecKeychainItemExtendedAttributes.cpp */; }; - 05AE95490AA748570076501C /* SecImportExportOpenSSH.h in Headers */ = {isa = PBXBuildFile; fileRef = 05AE95470AA748570076501C /* SecImportExportOpenSSH.h */; }; - 05AE954A0AA748580076501C /* SecImportExportOpenSSH.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05AE95480AA748570076501C /* SecImportExportOpenSSH.cpp */; }; - 05FB016805E54A3A00A5194C /* SecNetscapeTemplates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05FB016605E54A3A00A5194C /* SecNetscapeTemplates.cpp */; }; - 05FB016905E54A3A00A5194C /* SecNetscapeTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 05FB016705E54A3A00A5194C /* SecNetscapeTemplates.h */; }; - 0CBD509A16C3246D00713B6C /* kc-40-seckey.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CBD509816C3246D00713B6C /* kc-40-seckey.c */; }; - 0CBD509B16C3246D00713B6C /* kc-41-sececkey.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CBD509916C3246D00713B6C /* kc-41-sececkey.c */; }; - 182BB5CD146FF72B000BF1F3 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5297A731112CB13800EAA0C0 /* libDER.a */; }; - 188BB546171DD8B5009D22CE /* si-33-keychain-backup.c in Sources */ = {isa = PBXBuildFile; fileRef = 188BB53F171DD774009D22CE /* si-33-keychain-backup.c */; }; - 1B11967B062F4C1800F3B659 /* SecKeychainSearchPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B11967A062F4C1800F3B659 /* SecKeychainSearchPriv.h */; settings = {ATTRIBUTES = (); }; }; - 30E17F5B062B0A25004208EB /* SecIdentitySearchPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E17F5A062B0A25004208EB /* SecIdentitySearchPriv.h */; settings = {ATTRIBUTES = (); }; }; - 407AC2C0066661620030E07D /* SecPassword.h in Headers */ = {isa = PBXBuildFile; fileRef = 407AC2BE066661620030E07D /* SecPassword.h */; settings = {ATTRIBUTES = (); }; }; - 407AC2C1066661620030E07D /* SecPassword.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 407AC2BF066661620030E07D /* SecPassword.cpp */; }; - 407AC2C5066798420030E07D /* Password.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 407AC2C3066798420030E07D /* Password.cpp */; }; - 4885CFF811C8182D0093ECF6 /* SecRecoveryPassword.c in Sources */ = {isa = PBXBuildFile; fileRef = 4885CFF611C8182D0093ECF6 /* SecRecoveryPassword.c */; }; - 4885CFF911C8182D0093ECF6 /* SecRecoveryPassword.h in Headers */ = {isa = PBXBuildFile; fileRef = 4885CFF711C8182D0093ECF6 /* SecRecoveryPassword.h */; settings = {ATTRIBUTES = (); }; }; - 489C4FCC1202547600A8C58A /* SecRandom.h in Headers */ = {isa = PBXBuildFile; fileRef = 489C4FCB1202547600A8C58A /* SecRandom.h */; settings = {ATTRIBUTES = (); }; }; - 48E66AE3120254D700E878AD /* SecRandom.c in Sources */ = {isa = PBXBuildFile; fileRef = 48E66AE2120254D700E878AD /* SecRandom.c */; }; - 48E66AE5120254FC00E878AD /* SecRandomP.h in Headers */ = {isa = PBXBuildFile; fileRef = 48E66AE4120254FC00E878AD /* SecRandomP.h */; settings = {ATTRIBUTES = (); }; }; - 4C21181B058A75B000014C42 /* SecBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C21181A058A75B000014C42 /* SecBase.cpp */; }; - 4C5719DB12FB5F6800B31F85 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C5719D812FB5F6800B31F85 /* main.c */; }; - 4C86848C058A59430072F261 /* MacOSErrorStrings.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C868429058A55A10072F261 /* MacOSErrorStrings.h */; settings = {ATTRIBUTES = (); }; }; - 4CF00661058A51180060AF78 /* SecBasePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF00660058A51180060AF78 /* SecBasePriv.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F5E0581376700834D11 /* SecKeychain.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B8E052E099D006D0211 /* SecKeychain.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F5F0581376700834D11 /* SecKeychainSearch.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B96052E099D006D0211 /* SecKeychainSearch.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F600581376700834D11 /* SecPolicySearch.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B9C052E099D006D0211 /* SecPolicySearch.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F610581376700834D11 /* SecTrust.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2BA0052E099D006D0211 /* SecTrust.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F620581376700834D11 /* SecKey.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B8C052E099D006D0211 /* SecKey.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F630581376700834D11 /* SecKeychainItem.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B94052E099D006D0211 /* SecKeychainItem.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F640581376700834D11 /* Security.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2BA5052E099D006D0211 /* Security.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F650581376700834D11 /* SecAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B75052E099D006D0211 /* SecAccess.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F660581376700834D11 /* SecPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B99052E099D006D0211 /* SecPolicy.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F670581376700834D11 /* SecIdentitySearch.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B8A052E099D006D0211 /* SecIdentitySearch.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F680581376700834D11 /* SecACL.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B78052E099D006D0211 /* SecACL.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F690581376700834D11 /* SecCertificate.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B7C052E099D006D0211 /* SecCertificate.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F6A0581376700834D11 /* SecBase.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B79052E099D006D0211 /* SecBase.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F6B0581376700834D11 /* SecTrustedApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2BA2052E099D006D0211 /* SecTrustedApplication.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F6C0581376700834D11 /* SecIdentity.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B87052E099D006D0211 /* SecIdentity.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F6E0581377300834D11 /* SecPolicyPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B9A052E099D006D0211 /* SecPolicyPriv.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F6F0581377300834D11 /* SecKeychainItemPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C4A397FA053B21F9000E1B34 /* SecKeychainItemPriv.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F700581377300834D11 /* SecTrustPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2BA4052E099D006D0211 /* SecTrustPriv.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F710581377300834D11 /* SecCertificateRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B81052E099D006D0211 /* SecCertificateRequest.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F720581377300834D11 /* SecAccessPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B76052E099D006D0211 /* SecAccessPriv.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F730581377300834D11 /* SecKeychainPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C4A397A1053B1D50000E1B34 /* SecKeychainPriv.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F740581377300834D11 /* SecIdentityPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B88052E099D006D0211 /* SecIdentityPriv.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F750581377300834D11 /* SecTrustedApplicationPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2BA3052E099D006D0211 /* SecTrustedApplicationPriv.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F760581377300834D11 /* SecCertificatePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B7F052E099D006D0211 /* SecCertificatePriv.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F780581377300834D11 /* SecKeyPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B97052E099D006D0211 /* SecKeyPriv.h */; settings = {ATTRIBUTES = (); }; }; - 4CF36F790581377300834D11 /* SecCertificateBundle.h in Headers */ = {isa = PBXBuildFile; fileRef = C2AA2B7E052E099D006D0211 /* SecCertificateBundle.h */; settings = {ATTRIBUTES = (); }; }; - 4CFDC28506CD9C6A007BEE7E /* DynamicDLDBList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFDC28306CD9C6A007BEE7E /* DynamicDLDBList.cpp */; }; - 52008C6411496BD200E8CA78 /* SecCertificateInternalP.h in Headers */ = {isa = PBXBuildFile; fileRef = 52008C6311496BD200E8CA78 /* SecCertificateInternalP.h */; settings = {ATTRIBUTES = (); }; }; - 521DC57F1125FEE300937BF2 /* SecCertificateP.c in Sources */ = {isa = PBXBuildFile; fileRef = 521DC57D1125FEE300937BF2 /* SecCertificateP.c */; }; - 521DC5801125FEE300937BF2 /* SecCertificateP.h in Headers */ = {isa = PBXBuildFile; fileRef = 521DC57E1125FEE300937BF2 /* SecCertificateP.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 52200F8B14F2B87F00F7F6E7 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA31456E134B716B00133245 /* CoreFoundation.framework */; }; - 5261C28A112F0D570047EF8B /* SecFrameworkP.c in Sources */ = {isa = PBXBuildFile; fileRef = 5261C289112F0D570047EF8B /* SecFrameworkP.c */; }; - 5261C310112F1C560047EF8B /* SecBase64P.c in Sources */ = {isa = PBXBuildFile; fileRef = 5261C30F112F1C560047EF8B /* SecBase64P.c */; }; - 52B609D914F55B6800134209 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52B609D814F55B6800134209 /* Foundation.framework */; }; - 52B609E314F55BFA00134209 /* timestampclient.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B609E214F55BFA00134209 /* timestampclient.m */; }; - 52B60A0714F5CA9600134209 /* main-tsa.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B60A0614F5CA9500134209 /* main-tsa.m */; }; - 52B88DFB11DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52B88DF911DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.cpp */; }; - 52B88DFC11DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B88DFA11DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.h */; settings = {ATTRIBUTES = (); }; }; - 52BA735D112231C70012875E /* CertificateValues.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52BA735B112231C70012875E /* CertificateValues.cpp */; }; - 52BA735E112231C70012875E /* CertificateValues.h in Headers */ = {isa = PBXBuildFile; fileRef = 52BA735C112231C70012875E /* CertificateValues.h */; }; - 52C23EF81135AE5100E079D2 /* SecCertificatePrivP.h in Headers */ = {isa = PBXBuildFile; fileRef = 52C23EF71135AE5100E079D2 /* SecCertificatePrivP.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 52E950CD1509B47000DA6511 /* tsaDERUtilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 52E950CC1509B47000DA6511 /* tsaDERUtilities.c */; }; - 52E950D61509B48D00DA6511 /* tsaDERUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 52E950D51509B48D00DA6511 /* tsaDERUtilities.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 52FB44A91146D769006D3B0A /* SecCertificateOIDs.h in Headers */ = {isa = PBXBuildFile; fileRef = 52FB44A81146D769006D3B0A /* SecCertificateOIDs.h */; settings = {ATTRIBUTES = (); }; }; - AA31456F134B716B00133245 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA31456E134B716B00133245 /* CoreFoundation.framework */; }; - BE296DBF0EAC299C00FD22BE /* SecImportExport.c in Sources */ = {isa = PBXBuildFile; fileRef = BE296DBE0EAC299C00FD22BE /* SecImportExport.c */; }; - BE296DC50EAC2B5600FD22BE /* SecInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = BE296DC40EAC2B5600FD22BE /* SecInternal.h */; }; - BE50AE670F687AB900D28C54 /* TrustAdditions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE50AE650F687AB900D28C54 /* TrustAdditions.cpp */; }; - BE50AE680F687AB900D28C54 /* TrustAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = BE50AE660F687AB900D28C54 /* TrustAdditions.h */; }; - BEA830070EB17344001CA937 /* SecItemConstants.c in Sources */ = {isa = PBXBuildFile; fileRef = BEE897100A62CDD800BF88A5 /* SecItemConstants.c */; }; - BECE5141106B056C0091E644 /* TrustKeychains.h in Headers */ = {isa = PBXBuildFile; fileRef = BECE5140106B056C0091E644 /* TrustKeychains.h */; settings = {ATTRIBUTES = (); }; }; - BEE896E20A61F0BB00BF88A5 /* SecItem.h in Headers */ = {isa = PBXBuildFile; fileRef = BEE896E00A61F0BB00BF88A5 /* SecItem.h */; settings = {ATTRIBUTES = (); }; }; - BEE896E30A61F0BB00BF88A5 /* SecItemPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = BEE896E10A61F0BB00BF88A5 /* SecItemPriv.h */; settings = {ATTRIBUTES = (); }; }; - BEE896E70A61F12300BF88A5 /* SecItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BEE896E60A61F12300BF88A5 /* SecItem.cpp */; }; - C26BA9FF072580AE0049AF3C /* UnlockReferralItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C26BA9FE072580AE0049AF3C /* UnlockReferralItem.cpp */; }; - C2AA2BB4052E099D006D0211 /* Access.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B42052E099D006D0211 /* Access.cpp */; }; - C2AA2BB6052E099D006D0211 /* ACL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B44052E099D006D0211 /* ACL.cpp */; }; - C2AA2BB8052E099D006D0211 /* CCallbackMgr.cp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B46052E099D006D0211 /* CCallbackMgr.cp */; }; - C2AA2BBA052E099D006D0211 /* Certificate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B48052E099D006D0211 /* Certificate.cpp */; }; - C2AA2BBC052E099D006D0211 /* CertificateRequest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B4A052E099D006D0211 /* CertificateRequest.cpp */; }; - C2AA2BBF052E099D006D0211 /* cssmdatetime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B4D052E099D006D0211 /* cssmdatetime.cpp */; }; - C2AA2BC1052E099D006D0211 /* DLDBListCFPref.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B4F052E099D006D0211 /* DLDBListCFPref.cpp */; }; - C2AA2BC7052E099D006D0211 /* Globals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B56052E099D006D0211 /* Globals.cpp */; }; - C2AA2BC9052E099D006D0211 /* Identity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B58052E099D006D0211 /* Identity.cpp */; }; - C2AA2BCB052E099D006D0211 /* IdentityCursor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B5A052E099D006D0211 /* IdentityCursor.cpp */; }; - C2AA2BCD052E099D006D0211 /* Item.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B5C052E099D006D0211 /* Item.cpp */; }; - C2AA2BCF052E099D006D0211 /* KCCursor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B5E052E099D006D0211 /* KCCursor.cpp */; }; - C2AA2BD8052E099D006D0211 /* Keychains.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B67052E099D006D0211 /* Keychains.cpp */; }; - C2AA2BDA052E099D006D0211 /* KeyItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B69052E099D006D0211 /* KeyItem.cpp */; }; - C2AA2BDC052E099D006D0211 /* Policies.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B6B052E099D006D0211 /* Policies.cpp */; }; - C2AA2BDE052E099D006D0211 /* PolicyCursor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B6D052E099D006D0211 /* PolicyCursor.cpp */; }; - C2AA2BE0052E099D006D0211 /* PrimaryKey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B6F052E099D006D0211 /* PrimaryKey.cpp */; }; - C2AA2BE4052E099D006D0211 /* SecAccess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B74052E099D006D0211 /* SecAccess.cpp */; }; - C2AA2BE7052E099D006D0211 /* SecACL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B77052E099D006D0211 /* SecACL.cpp */; }; - C2AA2BEB052E099D006D0211 /* SecCertificate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B7B052E099D006D0211 /* SecCertificate.cpp */; }; - C2AA2BED052E099D006D0211 /* SecCertificateBundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B7D052E099D006D0211 /* SecCertificateBundle.cpp */; }; - C2AA2BF0052E099D006D0211 /* SecCertificateRequest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B80052E099D006D0211 /* SecCertificateRequest.cpp */; }; - C2AA2BF2052E099D006D0211 /* SecCFTypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B82052E099D006D0211 /* SecCFTypes.cpp */; }; - C2AA2BF6052E099D006D0211 /* SecIdentity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B86052E099D006D0211 /* SecIdentity.cpp */; }; - C2AA2BF9052E099D006D0211 /* SecIdentitySearch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B89052E099D006D0211 /* SecIdentitySearch.cpp */; }; - C2AA2BFB052E099D006D0211 /* SecKey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B8B052E099D006D0211 /* SecKey.cpp */; }; - C2AA2BFD052E099D006D0211 /* SecKeychain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B8D052E099D006D0211 /* SecKeychain.cpp */; }; - C2AA2BFF052E099D006D0211 /* SecKeychainAddIToolsPassword.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B8F052E099D006D0211 /* SecKeychainAddIToolsPassword.cpp */; }; - C2AA2C03052E099D006D0211 /* SecKeychainItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B93052E099D006D0211 /* SecKeychainItem.cpp */; }; - C2AA2C05052E099D006D0211 /* SecKeychainSearch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B95052E099D006D0211 /* SecKeychainSearch.cpp */; }; - C2AA2C08052E099D006D0211 /* SecPolicy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B98052E099D006D0211 /* SecPolicy.cpp */; }; - C2AA2C0B052E099D006D0211 /* SecPolicySearch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B9B052E099D006D0211 /* SecPolicySearch.cpp */; }; - C2AA2C0F052E099D006D0211 /* SecTrust.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2B9F052E099D006D0211 /* SecTrust.cpp */; }; - C2AA2C11052E099D006D0211 /* SecTrustedApplication.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2BA1052E099D006D0211 /* SecTrustedApplication.cpp */; }; - C2AA2C1A052E099D006D0211 /* StorageManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2BAA052E099D006D0211 /* StorageManager.cpp */; }; - C2AA2C1C052E099D006D0211 /* Trust.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2BAC052E099D006D0211 /* Trust.cpp */; }; - C2AA2C1E052E099D006D0211 /* TrustedApplication.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2BAE052E099D006D0211 /* TrustedApplication.cpp */; }; - C2AA2C20052E099D006D0211 /* TrustItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2BB0052E099D006D0211 /* TrustItem.cpp */; }; - C2AA2C22052E099D006D0211 /* TrustStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2BB2052E099D006D0211 /* TrustStore.cpp */; }; - C2FD26380731CEFB0027896A /* defaultcreds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2FD26370731CEE60027896A /* defaultcreds.cpp */; }; - C429431E053B2F8B00470431 /* KCUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C429431C053B2F8B00470431 /* KCUtilities.cpp */; }; - D6095E960A94F17C0026C68B /* KCEventNotifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D6E1457B0A632A5A008AA7E8 /* KCEventNotifier.cpp */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 182BB311146F0AE6000BF1F3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 182BB30C146F0AE6000BF1F3 /* libsecurity_utilities.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4CA2A53A0523D32800978A7B; - remoteInfo = libsecurity_utilities; - }; - 182BB340146F106C000BF1F3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 182BB30C146F0AE6000BF1F3 /* libsecurity_utilities.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = C2C9C69D0CECBE8400B3FE07; - remoteInfo = libsecurity_utilitiesDTrace; - }; - 521FBA8B112CB465002BEF54 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 5297A586112B78BB00EAA0C0 /* libDER.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 053BA313091C00BF00A7007A; - remoteInfo = libDER; - }; - 5297A730112CB13800EAA0C0 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 5297A586112B78BB00EAA0C0 /* libDER.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 053BA314091C00BF00A7007A; - remoteInfo = libDER; - }; - 5297A732112CB13800EAA0C0 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 5297A586112B78BB00EAA0C0 /* libDER.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 053BA445091FE58C00A7007A; - remoteInfo = parseCert; - }; - 5297A734112CB13800EAA0C0 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 5297A586112B78BB00EAA0C0 /* libDER.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 053BA46B091FE63E00A7007A; - remoteInfo = libDERUtils; - }; - 5297A736112CB13800EAA0C0 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 5297A586112B78BB00EAA0C0 /* libDER.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 058F16540925135E009FA1C5; - remoteInfo = parseCrl; - }; - 52FB45D411471AD0006D3B0A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 5297A586112B78BB00EAA0C0 /* libDER.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4C96C8CE113F4132005483E8; - remoteInfo = parseTicket; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 05012D45060B94A000C044CB /* SecImportExportCrypto.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecImportExportCrypto.cpp; sourceTree = ""; }; - 05012D49060B94B200C044CB /* SecImportExportCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecImportExportCrypto.h; sourceTree = ""; }; - 051A034705D9A68C00E02A64 /* SecImportExportAgg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecImportExportAgg.cpp; sourceTree = ""; }; - 051A034F05D9A69900E02A64 /* SecImportExportAgg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecImportExportAgg.h; sourceTree = ""; }; - 051A053205DAC86400E02A64 /* SecImportExportPem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecImportExportPem.cpp; sourceTree = ""; }; - 052AF722060A3472003FEB8D /* SecWrappedKeys.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecWrappedKeys.cpp; sourceTree = ""; }; - 054F90AD05E2860E0013C1D1 /* SecImportExportUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecImportExportUtils.cpp; sourceTree = ""; }; - 054F90AF05E286180013C1D1 /* SecImportExportUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecImportExportUtils.h; sourceTree = ""; }; - 055EA6B006AC5C13005079CE /* TrustRevocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrustRevocation.cpp; sourceTree = ""; }; - 056CDA3805FD573B00820BC3 /* SecImportExportPkcs8.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecImportExportPkcs8.cpp; sourceTree = ""; }; - 056CDA5C05FD5AEB00820BC3 /* SecPkcs8Templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecPkcs8Templates.h; sourceTree = ""; }; - 056CDA6405FD5B3400820BC3 /* SecPkcs8Templates.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecPkcs8Templates.cpp; sourceTree = ""; }; - 056CDA8D05FD63C200820BC3 /* SecImportExportPkcs8.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecImportExportPkcs8.h; sourceTree = ""; }; - 058AA95805D93B4300F543ED /* SecExport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecExport.cpp; sourceTree = ""; }; - 058AA95905D93B4300F543ED /* SecImportExport.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecImportExport.h; sourceTree = ""; }; - 058AA96B05D93CDD00F543ED /* SecImport.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 30; path = SecImport.cpp; sourceTree = ""; }; - 058AA9C905D96FD200F543ED /* SecExternalRep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecExternalRep.h; sourceTree = ""; }; - 058AA9CD05D96FE600F543ED /* SecExternalRep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecExternalRep.cpp; sourceTree = ""; }; - 058AAA9105D97EAE00F543ED /* SecImportExportPem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecImportExportPem.h; sourceTree = ""; }; - 058C796F09F56CCB00DB7E98 /* SecTrustSettings.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrustSettings.h; sourceTree = ""; }; - 058C797009F56CCB00DB7E98 /* SecTrustSettingsPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrustSettingsPriv.h; sourceTree = ""; }; - 058C797509F56CFB00DB7E98 /* SecTrustSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecTrustSettings.cpp; sourceTree = ""; }; - 058C797709F56D1400DB7E98 /* TrustSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TrustSettings.cpp; sourceTree = ""; }; - 058C797809F56D1400DB7E98 /* TrustSettings.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TrustSettings.h; sourceTree = ""; }; - 058C797909F56D1400DB7E98 /* TrustSettingsSchema.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TrustSettingsSchema.h; sourceTree = ""; }; - 058C797A09F56D1400DB7E98 /* TrustSettingsUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TrustSettingsUtils.cpp; sourceTree = ""; }; - 058C797B09F56D1400DB7E98 /* TrustSettingsUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TrustSettingsUtils.h; sourceTree = ""; }; - 05A83C360AAF591100906F28 /* SecKeychainItemExtendedAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecKeychainItemExtendedAttributes.h; sourceTree = ""; }; - 05A83C7D0AAF5CEA00906F28 /* ExtendedAttribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExtendedAttribute.h; sourceTree = ""; }; - 05A83C7E0AAF5CEA00906F28 /* ExtendedAttribute.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExtendedAttribute.cpp; sourceTree = ""; }; - 05A83C870AAF5E0A00906F28 /* SecKeychainItemExtendedAttributes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecKeychainItemExtendedAttributes.cpp; sourceTree = ""; }; - 05AE95470AA748570076501C /* SecImportExportOpenSSH.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecImportExportOpenSSH.h; sourceTree = ""; }; - 05AE95480AA748570076501C /* SecImportExportOpenSSH.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecImportExportOpenSSH.cpp; sourceTree = ""; }; - 05FB016605E54A3A00A5194C /* SecNetscapeTemplates.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecNetscapeTemplates.cpp; sourceTree = ""; }; - 05FB016705E54A3A00A5194C /* SecNetscapeTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecNetscapeTemplates.h; sourceTree = ""; }; - 0CBD509716C3242200713B6C /* libsecurity_keychain_regressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurity_keychain_regressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 0CBD509816C3246D00713B6C /* kc-40-seckey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-40-seckey.c"; path = "regressions/kc-40-seckey.c"; sourceTree = ""; }; - 0CBD509916C3246D00713B6C /* kc-41-sececkey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-41-sececkey.c"; path = "regressions/kc-41-sececkey.c"; sourceTree = ""; }; - 0CBD509C16C324B100713B6C /* keychain_regressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = keychain_regressions.h; path = regressions/keychain_regressions.h; sourceTree = ""; }; - 182BB224146F063C000BF1F3 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; - 182BB225146F063C000BF1F3 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; - 182BB226146F063C000BF1F3 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; - 182BB227146F063C000BF1F3 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; - 182BB30C146F0AE6000BF1F3 /* libsecurity_utilities.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_utilities.xcodeproj; path = ../libsecurity_utilities/libsecurity_utilities.xcodeproj; sourceTree = ""; }; - 188BB53F171DD774009D22CE /* si-33-keychain-backup.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = "si-33-keychain-backup.c"; path = "regressions/si-33-keychain-backup.c"; sourceTree = ""; }; - 1B11967A062F4C1800F3B659 /* SecKeychainSearchPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKeychainSearchPriv.h; sourceTree = ""; }; - 30E17F5A062B0A25004208EB /* SecIdentitySearchPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecIdentitySearchPriv.h; path = lib/SecIdentitySearchPriv.h; sourceTree = SOURCE_ROOT; }; - 407AC2BE066661620030E07D /* SecPassword.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecPassword.h; sourceTree = ""; }; - 407AC2BF066661620030E07D /* SecPassword.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecPassword.cpp; sourceTree = ""; }; - 407AC2C2066798420030E07D /* Password.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Password.h; sourceTree = ""; }; - 407AC2C3066798420030E07D /* Password.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Password.cpp; sourceTree = ""; }; - 4885CFF611C8182D0093ECF6 /* SecRecoveryPassword.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecRecoveryPassword.c; sourceTree = ""; }; - 4885CFF711C8182D0093ECF6 /* SecRecoveryPassword.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecRecoveryPassword.h; sourceTree = ""; }; - 489C4FCB1202547600A8C58A /* SecRandom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecRandom.h; sourceTree = ""; }; - 48E66AE2120254D700E878AD /* SecRandom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecRandom.c; sourceTree = ""; }; - 48E66AE4120254FC00E878AD /* SecRandomP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecRandomP.h; sourceTree = ""; }; - 4C21181A058A75B000014C42 /* SecBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecBase.cpp; sourceTree = ""; }; - 4C5719C812FB5E9E00B31F85 /* XPCKeychainSandboxCheck.xpc */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XPCKeychainSandboxCheck.xpc; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C5719CA12FB5E9E00B31F85 /* XPCKeychainSandboxCheck-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "XPCKeychainSandboxCheck-Info.plist"; path = "xpc/XPCKeychainSandboxCheck-Info.plist"; sourceTree = ""; }; - 4C5719D812FB5F6800B31F85 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = main.c; path = xpc/main.c; sourceTree = ""; }; - 4C868429058A55A10072F261 /* MacOSErrorStrings.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MacOSErrorStrings.h; sourceTree = ""; }; - 4CA1FEBE052A3C8100F22E42 /* libsecurity_keychain.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_keychain.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 4CCB00430580089000981D43 /* security_keychain.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = security_keychain.exp; sourceTree = ""; }; - 4CF00660058A51180060AF78 /* SecBasePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecBasePriv.h; sourceTree = ""; }; - 4CFDC28306CD9C6A007BEE7E /* DynamicDLDBList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicDLDBList.cpp; sourceTree = ""; }; - 4CFDC28406CD9C6A007BEE7E /* DynamicDLDBList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DynamicDLDBList.h; sourceTree = ""; }; - 52008C6311496BD200E8CA78 /* SecCertificateInternalP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCertificateInternalP.h; sourceTree = ""; }; - 521DC57D1125FEE300937BF2 /* SecCertificateP.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecCertificateP.c; sourceTree = ""; }; - 521DC57E1125FEE300937BF2 /* SecCertificateP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCertificateP.h; sourceTree = ""; }; - 52200F8F14F2B88000F7F6E7 /* XPCTimeStampingService.xpc */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XPCTimeStampingService.xpc; sourceTree = BUILT_PRODUCTS_DIR; }; - 52200F9B14F2B93700F7F6E7 /* XPCTimeStampingService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "XPCTimeStampingService-Info.plist"; sourceTree = ""; }; - 5261C289112F0D570047EF8B /* SecFrameworkP.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecFrameworkP.c; sourceTree = ""; }; - 5261C2E1112F19BA0047EF8B /* debuggingP.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = debuggingP.c; sourceTree = ""; }; - 5261C30F112F1C560047EF8B /* SecBase64P.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecBase64P.c; sourceTree = ""; }; - 527067DB070246B300C5D30E /* iToolsTrustedApps.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; name = iToolsTrustedApps.plist; path = plist/iToolsTrustedApps.plist; sourceTree = SOURCE_ROOT; }; - 5297A586112B78BB00EAA0C0 /* libDER.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libDER.xcodeproj; path = libDER/libDER.xcodeproj; sourceTree = ""; }; - 52B609D814F55B6800134209 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = ../../../../../../../System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; - 52B609E114F55BFA00134209 /* timestampclient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timestampclient.h; sourceTree = ""; }; - 52B609E214F55BFA00134209 /* timestampclient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = timestampclient.m; sourceTree = ""; }; - 52B60A0614F5CA9500134209 /* main-tsa.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "main-tsa.m"; sourceTree = ""; }; - 52B88DF911DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecFDERecoveryAsymmetricCrypto.cpp; sourceTree = ""; }; - 52B88DFA11DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecFDERecoveryAsymmetricCrypto.h; sourceTree = ""; }; - 52BA735B112231C70012875E /* CertificateValues.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CertificateValues.cpp; sourceTree = ""; }; - 52BA735C112231C70012875E /* CertificateValues.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CertificateValues.h; sourceTree = ""; }; - 52C23EF71135AE5100E079D2 /* SecCertificatePrivP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCertificatePrivP.h; sourceTree = ""; }; - 52E950CC1509B47000DA6511 /* tsaDERUtilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tsaDERUtilities.c; sourceTree = ""; }; - 52E950D51509B48D00DA6511 /* tsaDERUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tsaDERUtilities.h; sourceTree = ""; }; - 52FB42C1113F056D006D3B0A /* debuggingP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debuggingP.h; sourceTree = ""; }; - 52FB44A81146D769006D3B0A /* SecCertificateOIDs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCertificateOIDs.h; sourceTree = ""; }; - AA31456E134B716B00133245 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; - BE296DBE0EAC299C00FD22BE /* SecImportExport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecImportExport.c; sourceTree = ""; }; - BE296DC40EAC2B5600FD22BE /* SecInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecInternal.h; sourceTree = ""; }; - BE50AE650F687AB900D28C54 /* TrustAdditions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrustAdditions.cpp; sourceTree = ""; }; - BE50AE660F687AB900D28C54 /* TrustAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrustAdditions.h; sourceTree = ""; }; - BECE5140106B056C0091E644 /* TrustKeychains.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrustKeychains.h; sourceTree = ""; }; - BEE896E00A61F0BB00BF88A5 /* SecItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecItem.h; sourceTree = ""; }; - BEE896E10A61F0BB00BF88A5 /* SecItemPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecItemPriv.h; sourceTree = ""; }; - BEE896E60A61F12300BF88A5 /* SecItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecItem.cpp; sourceTree = ""; }; - BEE897100A62CDD800BF88A5 /* SecItemConstants.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SecItemConstants.c; sourceTree = ""; }; - C26BA9FE072580AE0049AF3C /* UnlockReferralItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = UnlockReferralItem.cpp; path = lib/UnlockReferralItem.cpp; sourceTree = SOURCE_ROOT; }; - C2975B9B072580DC00AFECAD /* UnlockReferralItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = UnlockReferralItem.h; path = lib/UnlockReferralItem.h; sourceTree = SOURCE_ROOT; }; - C2AA2B42052E099D006D0211 /* Access.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Access.cpp; sourceTree = ""; }; - C2AA2B43052E099D006D0211 /* Access.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Access.h; sourceTree = ""; }; - C2AA2B44052E099D006D0211 /* ACL.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ACL.cpp; sourceTree = ""; }; - C2AA2B45052E099D006D0211 /* ACL.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ACL.h; sourceTree = ""; }; - C2AA2B46052E099D006D0211 /* CCallbackMgr.cp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CCallbackMgr.cp; sourceTree = ""; }; - C2AA2B47052E099D006D0211 /* CCallbackMgr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CCallbackMgr.h; sourceTree = ""; }; - C2AA2B48052E099D006D0211 /* Certificate.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Certificate.cpp; sourceTree = ""; }; - C2AA2B49052E099D006D0211 /* Certificate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Certificate.h; sourceTree = ""; }; - C2AA2B4A052E099D006D0211 /* CertificateRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CertificateRequest.cpp; sourceTree = ""; }; - C2AA2B4B052E099D006D0211 /* CertificateRequest.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CertificateRequest.h; sourceTree = ""; }; - C2AA2B4D052E099D006D0211 /* cssmdatetime.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmdatetime.cpp; sourceTree = ""; }; - C2AA2B4E052E099D006D0211 /* cssmdatetime.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmdatetime.h; sourceTree = ""; }; - C2AA2B4F052E099D006D0211 /* DLDBListCFPref.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DLDBListCFPref.cpp; sourceTree = ""; }; - C2AA2B50052E099D006D0211 /* DLDBListCFPref.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DLDBListCFPref.h; sourceTree = ""; }; - C2AA2B55052E099D006D0211 /* generateErrStrings.pl */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; path = generateErrStrings.pl; sourceTree = ""; }; - C2AA2B56052E099D006D0211 /* Globals.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Globals.cpp; sourceTree = ""; }; - C2AA2B57052E099D006D0211 /* Globals.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Globals.h; sourceTree = ""; }; - C2AA2B58052E099D006D0211 /* Identity.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Identity.cpp; sourceTree = ""; }; - C2AA2B59052E099D006D0211 /* Identity.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Identity.h; sourceTree = ""; }; - C2AA2B5A052E099D006D0211 /* IdentityCursor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = IdentityCursor.cpp; sourceTree = ""; }; - C2AA2B5B052E099D006D0211 /* IdentityCursor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = IdentityCursor.h; sourceTree = ""; }; - C2AA2B5C052E099D006D0211 /* Item.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Item.cpp; sourceTree = ""; }; - C2AA2B5D052E099D006D0211 /* Item.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Item.h; sourceTree = ""; }; - C2AA2B5E052E099D006D0211 /* KCCursor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = KCCursor.cpp; sourceTree = ""; }; - C2AA2B5F052E099D006D0211 /* KCCursor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = KCCursor.h; sourceTree = ""; }; - C2AA2B64052E099D006D0211 /* KCExceptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = KCExceptions.h; sourceTree = ""; }; - C2AA2B67052E099D006D0211 /* Keychains.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Keychains.cpp; sourceTree = ""; }; - C2AA2B68052E099D006D0211 /* Keychains.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Keychains.h; sourceTree = ""; }; - C2AA2B69052E099D006D0211 /* KeyItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = KeyItem.cpp; sourceTree = ""; }; - C2AA2B6A052E099D006D0211 /* KeyItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = KeyItem.h; sourceTree = ""; }; - C2AA2B6B052E099D006D0211 /* Policies.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Policies.cpp; sourceTree = ""; }; - C2AA2B6C052E099D006D0211 /* Policies.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Policies.h; sourceTree = ""; }; - C2AA2B6D052E099D006D0211 /* PolicyCursor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PolicyCursor.cpp; sourceTree = ""; }; - C2AA2B6E052E099D006D0211 /* PolicyCursor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PolicyCursor.h; sourceTree = ""; }; - C2AA2B6F052E099D006D0211 /* PrimaryKey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PrimaryKey.cpp; sourceTree = ""; }; - C2AA2B70052E099D006D0211 /* PrimaryKey.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PrimaryKey.h; sourceTree = ""; }; - C2AA2B74052E099D006D0211 /* SecAccess.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecAccess.cpp; sourceTree = ""; }; - C2AA2B75052E099D006D0211 /* SecAccess.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecAccess.h; sourceTree = ""; }; - C2AA2B76052E099D006D0211 /* SecAccessPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecAccessPriv.h; sourceTree = ""; }; - C2AA2B77052E099D006D0211 /* SecACL.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecACL.cpp; sourceTree = ""; }; - C2AA2B78052E099D006D0211 /* SecACL.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecACL.h; sourceTree = ""; }; - C2AA2B79052E099D006D0211 /* SecBase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecBase.h; sourceTree = ""; }; - C2AA2B7A052E099D006D0211 /* SecBridge.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecBridge.h; sourceTree = ""; }; - C2AA2B7B052E099D006D0211 /* SecCertificate.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecCertificate.cpp; sourceTree = ""; }; - C2AA2B7C052E099D006D0211 /* SecCertificate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCertificate.h; sourceTree = ""; }; - C2AA2B7D052E099D006D0211 /* SecCertificateBundle.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecCertificateBundle.cpp; sourceTree = ""; }; - C2AA2B7E052E099D006D0211 /* SecCertificateBundle.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCertificateBundle.h; sourceTree = ""; }; - C2AA2B7F052E099D006D0211 /* SecCertificatePriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCertificatePriv.h; sourceTree = ""; }; - C2AA2B80052E099D006D0211 /* SecCertificateRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecCertificateRequest.cpp; sourceTree = ""; }; - C2AA2B81052E099D006D0211 /* SecCertificateRequest.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCertificateRequest.h; sourceTree = ""; }; - C2AA2B82052E099D006D0211 /* SecCFTypes.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecCFTypes.cpp; sourceTree = ""; }; - C2AA2B83052E099D006D0211 /* SecCFTypes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCFTypes.h; sourceTree = ""; }; - C2AA2B86052E099D006D0211 /* SecIdentity.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecIdentity.cpp; sourceTree = ""; }; - C2AA2B87052E099D006D0211 /* SecIdentity.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecIdentity.h; sourceTree = ""; }; - C2AA2B88052E099D006D0211 /* SecIdentityPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecIdentityPriv.h; sourceTree = ""; }; - C2AA2B89052E099D006D0211 /* SecIdentitySearch.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecIdentitySearch.cpp; sourceTree = ""; }; - C2AA2B8A052E099D006D0211 /* SecIdentitySearch.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecIdentitySearch.h; sourceTree = ""; }; - C2AA2B8B052E099D006D0211 /* SecKey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecKey.cpp; sourceTree = ""; }; - C2AA2B8C052E099D006D0211 /* SecKey.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKey.h; sourceTree = ""; }; - C2AA2B8D052E099D006D0211 /* SecKeychain.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecKeychain.cpp; sourceTree = ""; }; - C2AA2B8E052E099D006D0211 /* SecKeychain.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKeychain.h; sourceTree = ""; }; - C2AA2B8F052E099D006D0211 /* SecKeychainAddIToolsPassword.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecKeychainAddIToolsPassword.cpp; sourceTree = ""; }; - C2AA2B93052E099D006D0211 /* SecKeychainItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecKeychainItem.cpp; sourceTree = ""; }; - C2AA2B94052E099D006D0211 /* SecKeychainItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKeychainItem.h; sourceTree = ""; }; - C2AA2B95052E099D006D0211 /* SecKeychainSearch.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecKeychainSearch.cpp; sourceTree = ""; }; - C2AA2B96052E099D006D0211 /* SecKeychainSearch.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKeychainSearch.h; sourceTree = ""; }; - C2AA2B97052E099D006D0211 /* SecKeyPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKeyPriv.h; sourceTree = ""; }; - C2AA2B98052E099D006D0211 /* SecPolicy.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecPolicy.cpp; sourceTree = ""; }; - C2AA2B99052E099D006D0211 /* SecPolicy.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecPolicy.h; sourceTree = ""; }; - C2AA2B9A052E099D006D0211 /* SecPolicyPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecPolicyPriv.h; sourceTree = ""; }; - C2AA2B9B052E099D006D0211 /* SecPolicySearch.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecPolicySearch.cpp; sourceTree = ""; }; - C2AA2B9C052E099D006D0211 /* SecPolicySearch.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecPolicySearch.h; sourceTree = ""; }; - C2AA2B9F052E099D006D0211 /* SecTrust.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecTrust.cpp; sourceTree = ""; }; - C2AA2BA0052E099D006D0211 /* SecTrust.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrust.h; sourceTree = ""; }; - C2AA2BA1052E099D006D0211 /* SecTrustedApplication.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecTrustedApplication.cpp; sourceTree = ""; }; - C2AA2BA2052E099D006D0211 /* SecTrustedApplication.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrustedApplication.h; sourceTree = ""; }; - C2AA2BA3052E099D006D0211 /* SecTrustedApplicationPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrustedApplicationPriv.h; sourceTree = ""; }; - C2AA2BA4052E099D006D0211 /* SecTrustPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrustPriv.h; sourceTree = ""; }; - C2AA2BA5052E099D006D0211 /* Security.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Security.h; sourceTree = ""; }; - C2AA2BAA052E099D006D0211 /* StorageManager.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = StorageManager.cpp; sourceTree = ""; }; - C2AA2BAB052E099D006D0211 /* StorageManager.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = StorageManager.h; sourceTree = ""; }; - C2AA2BAC052E099D006D0211 /* Trust.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Trust.cpp; sourceTree = ""; }; - C2AA2BAD052E099D006D0211 /* Trust.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Trust.h; sourceTree = ""; }; - C2AA2BAE052E099D006D0211 /* TrustedApplication.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TrustedApplication.cpp; sourceTree = ""; }; - C2AA2BAF052E099D006D0211 /* TrustedApplication.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TrustedApplication.h; sourceTree = ""; }; - C2AA2BB0052E099D006D0211 /* TrustItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TrustItem.cpp; sourceTree = ""; }; - C2AA2BB1052E099D006D0211 /* TrustItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TrustItem.h; sourceTree = ""; }; - C2AA2BB2052E099D006D0211 /* TrustStore.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TrustStore.cpp; sourceTree = ""; }; - C2AA2BB3052E099D006D0211 /* TrustStore.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TrustStore.h; sourceTree = ""; }; - C2FD262F0731CEB40027896A /* defaultcreds.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = defaultcreds.h; path = lib/defaultcreds.h; sourceTree = SOURCE_ROOT; }; - C2FD26370731CEE60027896A /* defaultcreds.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = defaultcreds.cpp; path = lib/defaultcreds.cpp; sourceTree = SOURCE_ROOT; }; - C429431C053B2F8B00470431 /* KCUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = KCUtilities.cpp; sourceTree = ""; }; - C429431D053B2F8B00470431 /* KCUtilities.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = KCUtilities.h; sourceTree = ""; }; - C4A397A1053B1D50000E1B34 /* SecKeychainPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecKeychainPriv.h; sourceTree = ""; }; - C4A397FA053B21F9000E1B34 /* SecKeychainItemPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecKeychainItemPriv.h; sourceTree = ""; }; - D6E1457B0A632A5A008AA7E8 /* KCEventNotifier.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = KCEventNotifier.cpp; sourceTree = ""; }; - D6E1457C0A632A5A008AA7E8 /* KCEventNotifier.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = KCEventNotifier.h; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 4C5719C612FB5E9E00B31F85 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - AA31456F134B716B00133245 /* CoreFoundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 182BB5CD146FF72B000BF1F3 /* libDER.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 52200F8A14F2B87F00F7F6E7 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 52200F8B14F2B87F00F7F6E7 /* CoreFoundation.framework in Frameworks */, - 52B609D914F55B6800134209 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 05FB014005E5436B00A5194C /* Public API */ = { - isa = PBXGroup; - children = ( - 489C4FCB1202547600A8C58A /* SecRandom.h */, - C2AA2BA5052E099D006D0211 /* Security.h */, - C2AA2B79052E099D006D0211 /* SecBase.h */, - C2AA2B75052E099D006D0211 /* SecAccess.h */, - C2AA2B76052E099D006D0211 /* SecAccessPriv.h */, - C2AA2B78052E099D006D0211 /* SecACL.h */, - 4CF00660058A51180060AF78 /* SecBasePriv.h */, - C2AA2B7C052E099D006D0211 /* SecCertificate.h */, - 52FB44A81146D769006D3B0A /* SecCertificateOIDs.h */, - C2AA2B7E052E099D006D0211 /* SecCertificateBundle.h */, - C2AA2B7F052E099D006D0211 /* SecCertificatePriv.h */, - C2AA2B81052E099D006D0211 /* SecCertificateRequest.h */, - C2AA2B87052E099D006D0211 /* SecIdentity.h */, - C2AA2B88052E099D006D0211 /* SecIdentityPriv.h */, - C2AA2B8A052E099D006D0211 /* SecIdentitySearch.h */, - 30E17F5A062B0A25004208EB /* SecIdentitySearchPriv.h */, - 058AA95905D93B4300F543ED /* SecImportExport.h */, - BEE896E00A61F0BB00BF88A5 /* SecItem.h */, - BEE896E10A61F0BB00BF88A5 /* SecItemPriv.h */, - C2AA2B8C052E099D006D0211 /* SecKey.h */, - C2AA2B97052E099D006D0211 /* SecKeyPriv.h */, - C2AA2B8E052E099D006D0211 /* SecKeychain.h */, - C4A397A1053B1D50000E1B34 /* SecKeychainPriv.h */, - C2AA2B94052E099D006D0211 /* SecKeychainItem.h */, - C4A397FA053B21F9000E1B34 /* SecKeychainItemPriv.h */, - 05A83C360AAF591100906F28 /* SecKeychainItemExtendedAttributes.h */, - C2AA2B96052E099D006D0211 /* SecKeychainSearch.h */, - 1B11967A062F4C1800F3B659 /* SecKeychainSearchPriv.h */, - 407AC2BE066661620030E07D /* SecPassword.h */, - C2AA2B99052E099D006D0211 /* SecPolicy.h */, - C2AA2B9A052E099D006D0211 /* SecPolicyPriv.h */, - C2AA2B9C052E099D006D0211 /* SecPolicySearch.h */, - C2AA2BA0052E099D006D0211 /* SecTrust.h */, - C2AA2BA4052E099D006D0211 /* SecTrustPriv.h */, - 058C796F09F56CCB00DB7E98 /* SecTrustSettings.h */, - 058C797009F56CCB00DB7E98 /* SecTrustSettingsPriv.h */, - C2AA2BA2052E099D006D0211 /* SecTrustedApplication.h */, - C2AA2BA3052E099D006D0211 /* SecTrustedApplicationPriv.h */, - 058C797909F56D1400DB7E98 /* TrustSettingsSchema.h */, - ); - name = "Public API"; - sourceTree = ""; - }; - 05FB014305E5437C00A5194C /* API Bridge */ = { - isa = PBXGroup; - children = ( - C2AA2B74052E099D006D0211 /* SecAccess.cpp */, - C2AA2B77052E099D006D0211 /* SecACL.cpp */, - 4C21181A058A75B000014C42 /* SecBase.cpp */, - C2AA2B7A052E099D006D0211 /* SecBridge.h */, - C2AA2B7B052E099D006D0211 /* SecCertificate.cpp */, - C2AA2B7D052E099D006D0211 /* SecCertificateBundle.cpp */, - C2AA2B80052E099D006D0211 /* SecCertificateRequest.cpp */, - C2AA2B86052E099D006D0211 /* SecIdentity.cpp */, - C2AA2B89052E099D006D0211 /* SecIdentitySearch.cpp */, - BEE897100A62CDD800BF88A5 /* SecItemConstants.c */, - BEE896E60A61F12300BF88A5 /* SecItem.cpp */, - C2AA2B8B052E099D006D0211 /* SecKey.cpp */, - C2AA2B8D052E099D006D0211 /* SecKeychain.cpp */, - C2AA2B93052E099D006D0211 /* SecKeychainItem.cpp */, - 05A83C870AAF5E0A00906F28 /* SecKeychainItemExtendedAttributes.cpp */, - C2AA2B95052E099D006D0211 /* SecKeychainSearch.cpp */, - 407AC2BF066661620030E07D /* SecPassword.cpp */, - C2AA2B98052E099D006D0211 /* SecPolicy.cpp */, - C2AA2B9B052E099D006D0211 /* SecPolicySearch.cpp */, - C2AA2B9F052E099D006D0211 /* SecTrust.cpp */, - C2AA2BA1052E099D006D0211 /* SecTrustedApplication.cpp */, - 058C797509F56CFB00DB7E98 /* SecTrustSettings.cpp */, - ); - name = "API Bridge"; - sourceTree = ""; - }; - 05FB014605E5438300A5194C /* API Classes */ = { - isa = PBXGroup; - children = ( - 48E66AE2120254D700E878AD /* SecRandom.c */, - 52B88DF911DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.cpp */, - 52B88DFA11DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.h */, - 4885CFF611C8182D0093ECF6 /* SecRecoveryPassword.c */, - 4885CFF711C8182D0093ECF6 /* SecRecoveryPassword.h */, - C2AA2B42052E099D006D0211 /* Access.cpp */, - C2AA2B43052E099D006D0211 /* Access.h */, - C2AA2B44052E099D006D0211 /* ACL.cpp */, - C2AA2B45052E099D006D0211 /* ACL.h */, - C2AA2B48052E099D006D0211 /* Certificate.cpp */, - C2AA2B49052E099D006D0211 /* Certificate.h */, - C2AA2B4A052E099D006D0211 /* CertificateRequest.cpp */, - C2AA2B4B052E099D006D0211 /* CertificateRequest.h */, - 52BA735B112231C70012875E /* CertificateValues.cpp */, - 52BA735C112231C70012875E /* CertificateValues.h */, - 05A83C7E0AAF5CEA00906F28 /* ExtendedAttribute.cpp */, - 05A83C7D0AAF5CEA00906F28 /* ExtendedAttribute.h */, - C2AA2B56052E099D006D0211 /* Globals.cpp */, - C2AA2B57052E099D006D0211 /* Globals.h */, - C2AA2B58052E099D006D0211 /* Identity.cpp */, - C2AA2B59052E099D006D0211 /* Identity.h */, - C2AA2B5A052E099D006D0211 /* IdentityCursor.cpp */, - C2AA2B5B052E099D006D0211 /* IdentityCursor.h */, - C2AA2B5C052E099D006D0211 /* Item.cpp */, - C2AA2B5D052E099D006D0211 /* Item.h */, - C2AA2B5E052E099D006D0211 /* KCCursor.cpp */, - C2AA2B5F052E099D006D0211 /* KCCursor.h */, - C2AA2B67052E099D006D0211 /* Keychains.cpp */, - C2AA2B68052E099D006D0211 /* Keychains.h */, - C2AA2B69052E099D006D0211 /* KeyItem.cpp */, - C2AA2B6A052E099D006D0211 /* KeyItem.h */, - 407AC2C3066798420030E07D /* Password.cpp */, - 407AC2C2066798420030E07D /* Password.h */, - C2AA2B6B052E099D006D0211 /* Policies.cpp */, - C2AA2B6C052E099D006D0211 /* Policies.h */, - C2AA2B6D052E099D006D0211 /* PolicyCursor.cpp */, - C2AA2B6E052E099D006D0211 /* PolicyCursor.h */, - C2AA2B82052E099D006D0211 /* SecCFTypes.cpp */, - C2AA2B83052E099D006D0211 /* SecCFTypes.h */, - C2AA2B8F052E099D006D0211 /* SecKeychainAddIToolsPassword.cpp */, - 527067DB070246B300C5D30E /* iToolsTrustedApps.plist */, - C2AA2BAA052E099D006D0211 /* StorageManager.cpp */, - C2AA2BAC052E099D006D0211 /* Trust.cpp */, - C2AA2BAD052E099D006D0211 /* Trust.h */, - 055EA6B006AC5C13005079CE /* TrustRevocation.cpp */, - C2AA2BAE052E099D006D0211 /* TrustedApplication.cpp */, - C2AA2BAF052E099D006D0211 /* TrustedApplication.h */, - 058C797709F56D1400DB7E98 /* TrustSettings.cpp */, - 058C797809F56D1400DB7E98 /* TrustSettings.h */, - BECE5140106B056C0091E644 /* TrustKeychains.h */, - ); - name = "API Classes"; - sourceTree = ""; - }; - 05FB014905E5438C00A5194C /* Internal */ = { - isa = PBXGroup; - children = ( - 48E66AE4120254FC00E878AD /* SecRandomP.h */, - C2AA2B46052E099D006D0211 /* CCallbackMgr.cp */, - C2AA2B47052E099D006D0211 /* CCallbackMgr.h */, - C2AA2B4D052E099D006D0211 /* cssmdatetime.cpp */, - C2AA2B4E052E099D006D0211 /* cssmdatetime.h */, - C2FD26370731CEE60027896A /* defaultcreds.cpp */, - C2FD262F0731CEB40027896A /* defaultcreds.h */, - C2AA2B4F052E099D006D0211 /* DLDBListCFPref.cpp */, - C2AA2B50052E099D006D0211 /* DLDBListCFPref.h */, - 4CFDC28306CD9C6A007BEE7E /* DynamicDLDBList.cpp */, - 4CFDC28406CD9C6A007BEE7E /* DynamicDLDBList.h */, - D6E1457B0A632A5A008AA7E8 /* KCEventNotifier.cpp */, - D6E1457C0A632A5A008AA7E8 /* KCEventNotifier.h */, - C2AA2B64052E099D006D0211 /* KCExceptions.h */, - C429431C053B2F8B00470431 /* KCUtilities.cpp */, - C429431D053B2F8B00470431 /* KCUtilities.h */, - 4C868429058A55A10072F261 /* MacOSErrorStrings.h */, - C2AA2B6F052E099D006D0211 /* PrimaryKey.cpp */, - C2AA2B70052E099D006D0211 /* PrimaryKey.h */, - BE296DC40EAC2B5600FD22BE /* SecInternal.h */, - C2AA2BAB052E099D006D0211 /* StorageManager.h */, - BE50AE650F687AB900D28C54 /* TrustAdditions.cpp */, - BE50AE660F687AB900D28C54 /* TrustAdditions.h */, - C2AA2BB0052E099D006D0211 /* TrustItem.cpp */, - C2AA2BB1052E099D006D0211 /* TrustItem.h */, - C2AA2BB2052E099D006D0211 /* TrustStore.cpp */, - C2AA2BB3052E099D006D0211 /* TrustStore.h */, - C26BA9FE072580AE0049AF3C /* UnlockReferralItem.cpp */, - C2975B9B072580DC00AFECAD /* UnlockReferralItem.h */, - 058C797A09F56D1400DB7E98 /* TrustSettingsUtils.cpp */, - 058C797B09F56D1400DB7E98 /* TrustSettingsUtils.h */, - 52FB42C1113F056D006D3B0A /* debuggingP.h */, - 52C23EF71135AE5100E079D2 /* SecCertificatePrivP.h */, - 5261C30F112F1C560047EF8B /* SecBase64P.c */, - 5261C2E1112F19BA0047EF8B /* debuggingP.c */, - 5261C289112F0D570047EF8B /* SecFrameworkP.c */, - 521DC57D1125FEE300937BF2 /* SecCertificateP.c */, - 521DC57E1125FEE300937BF2 /* SecCertificateP.h */, - 4CCB00430580089000981D43 /* security_keychain.exp */, - 52008C6311496BD200E8CA78 /* SecCertificateInternalP.h */, - C2AA2B55052E099D006D0211 /* generateErrStrings.pl */, - 52E950CC1509B47000DA6511 /* tsaDERUtilities.c */, - 52E950D51509B48D00DA6511 /* tsaDERUtilities.h */, - ); - name = Internal; - sourceTree = ""; - }; - 05FB014C05E5439100A5194C /* Import/Export */ = { - isa = PBXGroup; - children = ( - 058AA95805D93B4300F543ED /* SecExport.cpp */, - 058AA9CD05D96FE600F543ED /* SecExternalRep.cpp */, - 058AA9C905D96FD200F543ED /* SecExternalRep.h */, - 058AA96B05D93CDD00F543ED /* SecImport.cpp */, - BE296DBE0EAC299C00FD22BE /* SecImportExport.c */, - 051A034705D9A68C00E02A64 /* SecImportExportAgg.cpp */, - 051A034F05D9A69900E02A64 /* SecImportExportAgg.h */, - 05012D45060B94A000C044CB /* SecImportExportCrypto.cpp */, - 05012D49060B94B200C044CB /* SecImportExportCrypto.h */, - 05AE95480AA748570076501C /* SecImportExportOpenSSH.cpp */, - 05AE95470AA748570076501C /* SecImportExportOpenSSH.h */, - 051A053205DAC86400E02A64 /* SecImportExportPem.cpp */, - 058AAA9105D97EAE00F543ED /* SecImportExportPem.h */, - 056CDA3805FD573B00820BC3 /* SecImportExportPkcs8.cpp */, - 056CDA8D05FD63C200820BC3 /* SecImportExportPkcs8.h */, - 054F90AD05E2860E0013C1D1 /* SecImportExportUtils.cpp */, - 054F90AF05E286180013C1D1 /* SecImportExportUtils.h */, - 05FB016605E54A3A00A5194C /* SecNetscapeTemplates.cpp */, - 05FB016705E54A3A00A5194C /* SecNetscapeTemplates.h */, - 056CDA6405FD5B3400820BC3 /* SecPkcs8Templates.cpp */, - 056CDA5C05FD5AEB00820BC3 /* SecPkcs8Templates.h */, - 052AF722060A3472003FEB8D /* SecWrappedKeys.cpp */, - ); - name = Import/Export; - sourceTree = ""; - }; - 0CBD4FF916C323E800713B6C /* regressions */ = { - isa = PBXGroup; - children = ( - 0CBD509C16C324B100713B6C /* keychain_regressions.h */, - 0CBD509816C3246D00713B6C /* kc-40-seckey.c */, - 0CBD509916C3246D00713B6C /* kc-41-sececkey.c */, - 188BB53F171DD774009D22CE /* si-33-keychain-backup.c */, - ); - name = regressions; - sourceTree = ""; - }; - 182BB223146F063C000BF1F3 /* config */ = { - isa = PBXGroup; - children = ( - 182BB224146F063C000BF1F3 /* base.xcconfig */, - 182BB225146F063C000BF1F3 /* debug.xcconfig */, - 182BB226146F063C000BF1F3 /* lib.xcconfig */, - 182BB227146F063C000BF1F3 /* release.xcconfig */, - ); - name = config; - path = ../config; - sourceTree = ""; - }; - 182BB30D146F0AE6000BF1F3 /* Products */ = { - isa = PBXGroup; - children = ( - 182BB312146F0AE6000BF1F3 /* libsecurity_utilities.a */, - ); - name = Products; - sourceTree = ""; - }; - 4C5719D712FB5F3300B31F85 /* xpc */ = { - isa = PBXGroup; - children = ( - AA31456E134B716B00133245 /* CoreFoundation.framework */, - 4C5719D812FB5F6800B31F85 /* main.c */, - 4C5719CA12FB5E9E00B31F85 /* XPCKeychainSandboxCheck-Info.plist */, - ); - name = xpc; - sourceTree = ""; - }; - 4CA1FEA7052A3C3800F22E42 = { - isa = PBXGroup; - children = ( - 182BB30C146F0AE6000BF1F3 /* libsecurity_utilities.xcodeproj */, - 5297A586112B78BB00EAA0C0 /* libDER.xcodeproj */, - 0CBD4FF916C323E800713B6C /* regressions */, - C2AA2B41052E099D006D0211 /* lib */, - 182BB223146F063C000BF1F3 /* config */, - 52200F9914F2B93700F7F6E7 /* xpc-tsa */, - 4C5719D712FB5F3300B31F85 /* xpc */, - 4CA1FEBF052A3C8100F22E42 /* Products */, - ); - sourceTree = ""; - }; - 4CA1FEBF052A3C8100F22E42 /* Products */ = { - isa = PBXGroup; - children = ( - 4CA1FEBE052A3C8100F22E42 /* libsecurity_keychain.a */, - 4C5719C812FB5E9E00B31F85 /* XPCKeychainSandboxCheck.xpc */, - 52200F8F14F2B88000F7F6E7 /* XPCTimeStampingService.xpc */, - 0CBD509716C3242200713B6C /* libsecurity_keychain_regressions.a */, - ); - name = Products; - sourceTree = ""; - }; - 52200F9914F2B93700F7F6E7 /* xpc-tsa */ = { - isa = PBXGroup; - children = ( - 52B609D814F55B6800134209 /* Foundation.framework */, - 52200F9B14F2B93700F7F6E7 /* XPCTimeStampingService-Info.plist */, - 52B60A0614F5CA9500134209 /* main-tsa.m */, - 52B609E114F55BFA00134209 /* timestampclient.h */, - 52B609E214F55BFA00134209 /* timestampclient.m */, - ); - path = "xpc-tsa"; - sourceTree = ""; - }; - 5297A72A112CB13800EAA0C0 /* Products */ = { - isa = PBXGroup; - children = ( - 5297A731112CB13800EAA0C0 /* libDER.a */, - 5297A733112CB13800EAA0C0 /* parseCert */, - 5297A735112CB13800EAA0C0 /* libDERUtils.a */, - 5297A737112CB13800EAA0C0 /* parseCrl */, - 52FB45D511471AD0006D3B0A /* parseTicket */, - ); - name = Products; - sourceTree = ""; - }; - C2AA2B41052E099D006D0211 /* lib */ = { - isa = PBXGroup; - children = ( - 05FB014305E5437C00A5194C /* API Bridge */, - 05FB014005E5436B00A5194C /* Public API */, - 05FB014605E5438300A5194C /* API Classes */, - 05FB014905E5438C00A5194C /* Internal */, - 05FB014C05E5439100A5194C /* Import/Export */, - ); - path = lib; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 4CF36F5D0581375900834D11 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 05FB016905E54A3A00A5194C /* SecNetscapeTemplates.h in Headers */, - 056CDA5D05FD5AEB00820BC3 /* SecPkcs8Templates.h in Headers */, - 4CF36F650581376700834D11 /* SecAccess.h in Headers */, - 4CF36F680581376700834D11 /* SecACL.h in Headers */, - 4CF36F6A0581376700834D11 /* SecBase.h in Headers */, - 4CF36F690581376700834D11 /* SecCertificate.h in Headers */, - 4CF36F6C0581376700834D11 /* SecIdentity.h in Headers */, - 4CF36F670581376700834D11 /* SecIdentitySearch.h in Headers */, - BEE896E20A61F0BB00BF88A5 /* SecItem.h in Headers */, - 4CF36F620581376700834D11 /* SecKey.h in Headers */, - 4CF36F5E0581376700834D11 /* SecKeychain.h in Headers */, - 4CF36F630581376700834D11 /* SecKeychainItem.h in Headers */, - 4CF36F5F0581376700834D11 /* SecKeychainSearch.h in Headers */, - 4CF36F660581376700834D11 /* SecPolicy.h in Headers */, - 4CF36F600581376700834D11 /* SecPolicySearch.h in Headers */, - 4CF36F610581376700834D11 /* SecTrust.h in Headers */, - 4CF36F6B0581376700834D11 /* SecTrustedApplication.h in Headers */, - 4CF36F640581376700834D11 /* Security.h in Headers */, - 058AA95B05D93B4300F543ED /* SecImportExport.h in Headers */, - 058C797109F56CCB00DB7E98 /* SecTrustSettings.h in Headers */, - 52FB44A91146D769006D3B0A /* SecCertificateOIDs.h in Headers */, - 489C4FCC1202547600A8C58A /* SecRandom.h in Headers */, - 05AE95490AA748570076501C /* SecImportExportOpenSSH.h in Headers */, - BE296DC50EAC2B5600FD22BE /* SecInternal.h in Headers */, - BE50AE680F687AB900D28C54 /* TrustAdditions.h in Headers */, - 52B88DFC11DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.h in Headers */, - 407AC2C0066661620030E07D /* SecPassword.h in Headers */, - 4C86848C058A59430072F261 /* MacOSErrorStrings.h in Headers */, - 4CF36F720581377300834D11 /* SecAccessPriv.h in Headers */, - 4CF00661058A51180060AF78 /* SecBasePriv.h in Headers */, - 4CF36F790581377300834D11 /* SecCertificateBundle.h in Headers */, - 4CF36F760581377300834D11 /* SecCertificatePriv.h in Headers */, - 4CF36F710581377300834D11 /* SecCertificateRequest.h in Headers */, - 4CF36F740581377300834D11 /* SecIdentityPriv.h in Headers */, - 4CF36F6F0581377300834D11 /* SecKeychainItemPriv.h in Headers */, - 4CF36F730581377300834D11 /* SecKeychainPriv.h in Headers */, - 4CF36F780581377300834D11 /* SecKeyPriv.h in Headers */, - 4CF36F6E0581377300834D11 /* SecPolicyPriv.h in Headers */, - 4CF36F750581377300834D11 /* SecTrustedApplicationPriv.h in Headers */, - 4CF36F700581377300834D11 /* SecTrustPriv.h in Headers */, - 058AA9CA05D96FD200F543ED /* SecExternalRep.h in Headers */, - 058AAA9205D97EAE00F543ED /* SecImportExportPem.h in Headers */, - 051A035005D9A69900E02A64 /* SecImportExportAgg.h in Headers */, - 054F90B005E286180013C1D1 /* SecImportExportUtils.h in Headers */, - 056CDA8E05FD63C200820BC3 /* SecImportExportPkcs8.h in Headers */, - 05012D4A060B94B200C044CB /* SecImportExportCrypto.h in Headers */, - 30E17F5B062B0A25004208EB /* SecIdentitySearchPriv.h in Headers */, - 1B11967B062F4C1800F3B659 /* SecKeychainSearchPriv.h in Headers */, - 058C797209F56CCC00DB7E98 /* SecTrustSettingsPriv.h in Headers */, - 058C797D09F56D1400DB7E98 /* TrustSettings.h in Headers */, - 058C797E09F56D1400DB7E98 /* TrustSettingsSchema.h in Headers */, - 058C798009F56D1400DB7E98 /* TrustSettingsUtils.h in Headers */, - BEE896E30A61F0BB00BF88A5 /* SecItemPriv.h in Headers */, - 05A83C380AAF591100906F28 /* SecKeychainItemExtendedAttributes.h in Headers */, - BECE5141106B056C0091E644 /* TrustKeychains.h in Headers */, - 52008C6411496BD200E8CA78 /* SecCertificateInternalP.h in Headers */, - 4885CFF911C8182D0093ECF6 /* SecRecoveryPassword.h in Headers */, - 48E66AE5120254FC00E878AD /* SecRandomP.h in Headers */, - 52BA735E112231C70012875E /* CertificateValues.h in Headers */, - 521DC5801125FEE300937BF2 /* SecCertificateP.h in Headers */, - 52C23EF81135AE5100E079D2 /* SecCertificatePrivP.h in Headers */, - 52E950D61509B48D00DA6511 /* tsaDERUtilities.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 0CBD500016C3242200713B6C /* libsecurity_keychain_regressions */ = { - isa = PBXNativeTarget; - buildConfigurationList = 0CBD509416C3242200713B6C /* Build configuration list for PBXNativeTarget "libsecurity_keychain_regressions" */; - buildPhases = ( - 0CBD504416C3242200713B6C /* Sources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libsecurity_keychain_regressions; - productName = libsecurity_keychain; - productReference = 0CBD509716C3242200713B6C /* libsecurity_keychain_regressions.a */; - productType = "com.apple.product-type.library.static"; - }; - 4C5719C712FB5E9E00B31F85 /* XPCKeychainSandboxCheck */ = { - isa = PBXNativeTarget; - buildConfigurationList = 4C5719CF12FB5E9F00B31F85 /* Build configuration list for PBXNativeTarget "XPCKeychainSandboxCheck" */; - buildPhases = ( - 4C5719C512FB5E9E00B31F85 /* Sources */, - 4C5719C612FB5E9E00B31F85 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = XPCKeychainSandboxCheck; - productName = XPCKeychainSandboxCheck; - productReference = 4C5719C812FB5E9E00B31F85 /* XPCKeychainSandboxCheck.xpc */; - productType = "com.apple.product-type.application"; - }; - 4CA1FEBD052A3C8100F22E42 /* libsecurity_keychain */ = { - isa = PBXNativeTarget; - buildConfigurationList = C27AD37C0987FCDE001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_keychain" */; - buildPhases = ( - 4CF36F5D0581375900834D11 /* Headers */, - 4CA1FEBA052A3C8100F22E42 /* Sources */, - 4CA1FEBB052A3C8100F22E42 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 182BB341146F106C000BF1F3 /* PBXTargetDependency */, - 521FBA8C112CB465002BEF54 /* PBXTargetDependency */, - ); - name = libsecurity_keychain; - productName = libsecurity_keychain; - productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_keychain.a */; - productType = "com.apple.product-type.library.static"; - }; - 52200F8714F2B87F00F7F6E7 /* XPCTimeStampingService */ = { - isa = PBXNativeTarget; - buildConfigurationList = 52200F8C14F2B87F00F7F6E7 /* Build configuration list for PBXNativeTarget "XPCTimeStampingService" */; - buildPhases = ( - 52200F8814F2B87F00F7F6E7 /* Sources */, - 52200F8A14F2B87F00F7F6E7 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = XPCTimeStampingService; - productName = XPCTimeStampingService; - productReference = 52200F8F14F2B88000F7F6E7 /* XPCTimeStampingService.xpc */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 4CA1FEAB052A3C3800F22E42 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0500; - }; - buildConfigurationList = C27AD3810987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_keychain" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - English, - Japanese, - French, - German, - ); - mainGroup = 4CA1FEA7052A3C3800F22E42; - productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; - projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 5297A72A112CB13800EAA0C0 /* Products */; - ProjectRef = 5297A586112B78BB00EAA0C0 /* libDER.xcodeproj */; - }, - { - ProductGroup = 182BB30D146F0AE6000BF1F3 /* Products */; - ProjectRef = 182BB30C146F0AE6000BF1F3 /* libsecurity_utilities.xcodeproj */; - }, - ); - projectRoot = ""; - targets = ( - 4CA1FEBD052A3C8100F22E42 /* libsecurity_keychain */, - 4C5719C712FB5E9E00B31F85 /* XPCKeychainSandboxCheck */, - 52200F8714F2B87F00F7F6E7 /* XPCTimeStampingService */, - 0CBD500016C3242200713B6C /* libsecurity_keychain_regressions */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXReferenceProxy section */ - 182BB312146F0AE6000BF1F3 /* libsecurity_utilities.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libsecurity_utilities.a; - remoteRef = 182BB311146F0AE6000BF1F3 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 5297A731112CB13800EAA0C0 /* libDER.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libDER.a; - remoteRef = 5297A730112CB13800EAA0C0 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 5297A733112CB13800EAA0C0 /* parseCert */ = { - isa = PBXReferenceProxy; - fileType = "compiled.mach-o.executable"; - path = parseCert; - remoteRef = 5297A732112CB13800EAA0C0 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 5297A735112CB13800EAA0C0 /* libDERUtils.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libDERUtils.a; - remoteRef = 5297A734112CB13800EAA0C0 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 5297A737112CB13800EAA0C0 /* parseCrl */ = { - isa = PBXReferenceProxy; - fileType = "compiled.mach-o.executable"; - path = parseCrl; - remoteRef = 5297A736112CB13800EAA0C0 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 52FB45D511471AD0006D3B0A /* parseTicket */ = { - isa = PBXReferenceProxy; - fileType = "compiled.mach-o.executable"; - path = parseTicket; - remoteRef = 52FB45D411471AD0006D3B0A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - -/* Begin PBXSourcesBuildPhase section */ - 0CBD504416C3242200713B6C /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0CBD509B16C3246D00713B6C /* kc-41-sececkey.c in Sources */, - 188BB546171DD8B5009D22CE /* si-33-keychain-backup.c in Sources */, - 0CBD509A16C3246D00713B6C /* kc-40-seckey.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4C5719C512FB5E9E00B31F85 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 4C5719DB12FB5F6800B31F85 /* main.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4CA1FEBA052A3C8100F22E42 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - C2AA2BB4052E099D006D0211 /* Access.cpp in Sources */, - C2AA2BB6052E099D006D0211 /* ACL.cpp in Sources */, - C2AA2BB8052E099D006D0211 /* CCallbackMgr.cp in Sources */, - C2AA2BBA052E099D006D0211 /* Certificate.cpp in Sources */, - C2AA2BBC052E099D006D0211 /* CertificateRequest.cpp in Sources */, - C2AA2BBF052E099D006D0211 /* cssmdatetime.cpp in Sources */, - C2FD26380731CEFB0027896A /* defaultcreds.cpp in Sources */, - C2AA2BC1052E099D006D0211 /* DLDBListCFPref.cpp in Sources */, - 4CFDC28506CD9C6A007BEE7E /* DynamicDLDBList.cpp in Sources */, - C2AA2BC7052E099D006D0211 /* Globals.cpp in Sources */, - C2AA2BC9052E099D006D0211 /* Identity.cpp in Sources */, - C2AA2BCB052E099D006D0211 /* IdentityCursor.cpp in Sources */, - C2AA2BCD052E099D006D0211 /* Item.cpp in Sources */, - D6095E960A94F17C0026C68B /* KCEventNotifier.cpp in Sources */, - C2AA2BCF052E099D006D0211 /* KCCursor.cpp in Sources */, - C429431E053B2F8B00470431 /* KCUtilities.cpp in Sources */, - C2AA2BD8052E099D006D0211 /* Keychains.cpp in Sources */, - C2AA2BDA052E099D006D0211 /* KeyItem.cpp in Sources */, - 407AC2C5066798420030E07D /* Password.cpp in Sources */, - C2AA2BDC052E099D006D0211 /* Policies.cpp in Sources */, - C2AA2BDE052E099D006D0211 /* PolicyCursor.cpp in Sources */, - C2AA2BE0052E099D006D0211 /* PrimaryKey.cpp in Sources */, - C2AA2BE4052E099D006D0211 /* SecAccess.cpp in Sources */, - C2AA2BE7052E099D006D0211 /* SecACL.cpp in Sources */, - 4C21181B058A75B000014C42 /* SecBase.cpp in Sources */, - C2AA2BEB052E099D006D0211 /* SecCertificate.cpp in Sources */, - C2AA2BED052E099D006D0211 /* SecCertificateBundle.cpp in Sources */, - C2AA2BF0052E099D006D0211 /* SecCertificateRequest.cpp in Sources */, - C2AA2BF2052E099D006D0211 /* SecCFTypes.cpp in Sources */, - C2AA2BF6052E099D006D0211 /* SecIdentity.cpp in Sources */, - C2AA2BF9052E099D006D0211 /* SecIdentitySearch.cpp in Sources */, - C2AA2BFB052E099D006D0211 /* SecKey.cpp in Sources */, - C2AA2BFD052E099D006D0211 /* SecKeychain.cpp in Sources */, - C2AA2BFF052E099D006D0211 /* SecKeychainAddIToolsPassword.cpp in Sources */, - C2AA2C03052E099D006D0211 /* SecKeychainItem.cpp in Sources */, - C2AA2C05052E099D006D0211 /* SecKeychainSearch.cpp in Sources */, - 407AC2C1066661620030E07D /* SecPassword.cpp in Sources */, - C2AA2C08052E099D006D0211 /* SecPolicy.cpp in Sources */, - C2AA2C0B052E099D006D0211 /* SecPolicySearch.cpp in Sources */, - C2AA2C0F052E099D006D0211 /* SecTrust.cpp in Sources */, - C2AA2C11052E099D006D0211 /* SecTrustedApplication.cpp in Sources */, - C2AA2C1A052E099D006D0211 /* StorageManager.cpp in Sources */, - C2AA2C1C052E099D006D0211 /* Trust.cpp in Sources */, - C2AA2C1E052E099D006D0211 /* TrustedApplication.cpp in Sources */, - C2AA2C20052E099D006D0211 /* TrustItem.cpp in Sources */, - C2AA2C22052E099D006D0211 /* TrustStore.cpp in Sources */, - 058AA95A05D93B4300F543ED /* SecExport.cpp in Sources */, - 058AA96C05D93CDD00F543ED /* SecImport.cpp in Sources */, - 058AA9CE05D96FE600F543ED /* SecExternalRep.cpp in Sources */, - 051A034805D9A68C00E02A64 /* SecImportExportAgg.cpp in Sources */, - 051A053305DAC86400E02A64 /* SecImportExportPem.cpp in Sources */, - 054F90AE05E2860E0013C1D1 /* SecImportExportUtils.cpp in Sources */, - 05FB016805E54A3A00A5194C /* SecNetscapeTemplates.cpp in Sources */, - 056CDA3905FD573B00820BC3 /* SecImportExportPkcs8.cpp in Sources */, - 056CDA6505FD5B3400820BC3 /* SecPkcs8Templates.cpp in Sources */, - 052AF723060A3472003FEB8D /* SecWrappedKeys.cpp in Sources */, - 05012D46060B94A000C044CB /* SecImportExportCrypto.cpp in Sources */, - 055EA6B106AC5C13005079CE /* TrustRevocation.cpp in Sources */, - C26BA9FF072580AE0049AF3C /* UnlockReferralItem.cpp in Sources */, - 058C797609F56CFB00DB7E98 /* SecTrustSettings.cpp in Sources */, - 058C797C09F56D1400DB7E98 /* TrustSettings.cpp in Sources */, - 058C797F09F56D1400DB7E98 /* TrustSettingsUtils.cpp in Sources */, - BEE896E70A61F12300BF88A5 /* SecItem.cpp in Sources */, - BEA830070EB17344001CA937 /* SecItemConstants.c in Sources */, - 05AE954A0AA748580076501C /* SecImportExportOpenSSH.cpp in Sources */, - 05A83C800AAF5CEA00906F28 /* ExtendedAttribute.cpp in Sources */, - 05A83C880AAF5E0A00906F28 /* SecKeychainItemExtendedAttributes.cpp in Sources */, - BE296DBF0EAC299C00FD22BE /* SecImportExport.c in Sources */, - BE50AE670F687AB900D28C54 /* TrustAdditions.cpp in Sources */, - 52BA735D112231C70012875E /* CertificateValues.cpp in Sources */, - 521DC57F1125FEE300937BF2 /* SecCertificateP.c in Sources */, - 5261C28A112F0D570047EF8B /* SecFrameworkP.c in Sources */, - 5261C310112F1C560047EF8B /* SecBase64P.c in Sources */, - 4885CFF811C8182D0093ECF6 /* SecRecoveryPassword.c in Sources */, - 52B88DFB11DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.cpp in Sources */, - 48E66AE3120254D700E878AD /* SecRandom.c in Sources */, - 52E950CD1509B47000DA6511 /* tsaDERUtilities.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 52200F8814F2B87F00F7F6E7 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 52B609E314F55BFA00134209 /* timestampclient.m in Sources */, - 52B60A0714F5CA9600134209 /* main-tsa.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 182BB341146F106C000BF1F3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = libsecurity_utilitiesDTrace; - targetProxy = 182BB340146F106C000BF1F3 /* PBXContainerItemProxy */; - }; - 521FBA8C112CB465002BEF54 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = libDER; - targetProxy = 521FBA8B112CB465002BEF54 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 0CBD509516C3242200713B6C /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 182BB225146F063C000BF1F3 /* debug.xcconfig */; - buildSettings = { - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=overloaded-virtual", - ); - }; - name = Debug; - }; - 0CBD509616C3242200713B6C /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 182BB227146F063C000BF1F3 /* release.xcconfig */; - buildSettings = { - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=overloaded-virtual", - ); - }; - name = Release; - }; - 4C5719CB12FB5E9F00B31F85 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 182BB225146F063C000BF1F3 /* debug.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = "-"; - COMBINE_HIDPI_IMAGES = YES; - GCC_MODEL_TUNING = G5; - INFOPLIST_FILE = "xpc/XPCKeychainSandboxCheck-Info.plist"; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; - PRODUCT_NAME = XPCKeychainSandboxCheck; - PROVISIONING_PROFILE = ""; - SKIP_INSTALL = NO; - WRAPPER_EXTENSION = xpc; - }; - name = Debug; - }; - 4C5719CE12FB5E9F00B31F85 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 182BB227146F063C000BF1F3 /* release.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = "-"; - COMBINE_HIDPI_IMAGES = YES; - GCC_MODEL_TUNING = G5; - INFOPLIST_FILE = "xpc/XPCKeychainSandboxCheck-Info.plist"; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; - PRODUCT_NAME = XPCKeychainSandboxCheck; - PROVISIONING_PROFILE = ""; - SKIP_INSTALL = NO; - WRAPPER_EXTENSION = xpc; - }; - name = Release; - }; - 52200F8D14F2B87F00F7F6E7 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 182BB225146F063C000BF1F3 /* debug.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = "-"; - COMBINE_HIDPI_IMAGES = YES; - GCC_MODEL_TUNING = G5; - INFOPLIST_FILE = "xpc-tsa/XPCTimeStampingService-Info.plist"; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; - PRODUCT_NAME = XPCTimeStampingService; - PROVISIONING_PROFILE = ""; - SKIP_INSTALL = NO; - WRAPPER_EXTENSION = xpc; - }; - name = Debug; - }; - 52200F8E14F2B87F00F7F6E7 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 182BB227146F063C000BF1F3 /* release.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = "-"; - COMBINE_HIDPI_IMAGES = YES; - GCC_MODEL_TUNING = G5; - INFOPLIST_FILE = "xpc-tsa/XPCTimeStampingService-Info.plist"; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; - PRODUCT_NAME = XPCTimeStampingService; - PROVISIONING_PROFILE = ""; - SKIP_INSTALL = NO; - WRAPPER_EXTENSION = xpc; - }; - name = Release; - }; - C27AD37D0987FCDE001272E0 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 182BB225146F063C000BF1F3 /* debug.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/libDER", - ); - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=overloaded-virtual", - ); - }; - name = Debug; - }; - C27AD3800987FCDE001272E0 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 182BB227146F063C000BF1F3 /* release.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/libDER", - ); - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=overloaded-virtual", - ); - }; - name = Release; - }; - C27AD3820987FCDE001272E0 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 182BB226146F063C000BF1F3 /* lib.xcconfig */; - buildSettings = { - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - GCC_TREAT_WARNINGS_AS_ERRORS = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - }; - name = Debug; - }; - C27AD3850987FCDE001272E0 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 182BB226146F063C000BF1F3 /* lib.xcconfig */; - buildSettings = { - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - GCC_TREAT_WARNINGS_AS_ERRORS = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 0CBD509416C3242200713B6C /* Build configuration list for PBXNativeTarget "libsecurity_keychain_regressions" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0CBD509516C3242200713B6C /* Debug */, - 0CBD509616C3242200713B6C /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 4C5719CF12FB5E9F00B31F85 /* Build configuration list for PBXNativeTarget "XPCKeychainSandboxCheck" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 4C5719CB12FB5E9F00B31F85 /* Debug */, - 4C5719CE12FB5E9F00B31F85 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 52200F8C14F2B87F00F7F6E7 /* Build configuration list for PBXNativeTarget "XPCTimeStampingService" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 52200F8D14F2B87F00F7F6E7 /* Debug */, - 52200F8E14F2B87F00F7F6E7 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C27AD37C0987FCDE001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_keychain" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C27AD37D0987FCDE001272E0 /* Debug */, - C27AD3800987FCDE001272E0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C27AD3810987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_keychain" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C27AD3820987FCDE001272E0 /* Debug */, - C27AD3850987FCDE001272E0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; -} diff --git a/libsecurity_keychain/libsecurity_keychain.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_keychain/libsecurity_keychain.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 2c7d8fe6..00000000 --- a/libsecurity_keychain/libsecurity_keychain.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,29 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 0CBD500016C3242200713B6C - - primary - - - 4C5719C712FB5E9E00B31F85 - - primary - - - 4CA1FEBD052A3C8100F22E42 - - primary - - - 52200F8714F2B87F00F7F6E7 - - primary - - - - - diff --git a/libsecurity_keychain/regressions/si-33-keychain-backup.c b/libsecurity_keychain/regressions/si-33-keychain-backup.c deleted file mode 100644 index f48d626c..00000000 --- a/libsecurity_keychain/regressions/si-33-keychain-backup.c +++ /dev/null @@ -1,91 +0,0 @@ -// -// si-33-keychain-backup.c -// libsecurity_keychain -// -// Created by Wade Benson on 4/16/13. -// -// - -#include -#include - -#include "keychain_regressions.h" -#include -#include -#include -#include -#include - - -static CFDataRef create_keybag(keybag_handle_t bag_type, CFDataRef password) -{ - keybag_handle_t handle = bad_keybag_handle; - - if (aks_create_bag(NULL, 0, bag_type, &handle) == 0) { - void * keybag = NULL; - int keybag_size = 0; - if (aks_save_bag(handle, &keybag, &keybag_size) == 0) { - return CFDataCreate(kCFAllocatorDefault, keybag, keybag_size); - } - } - - return CFDataCreate(kCFAllocatorDefault, NULL, 0); -} - -/* Test low level keychain migration from device to device interface. */ -static void tests(void) -{ - int v_eighty = 80; - CFNumberRef eighty = CFNumberCreate(NULL, kCFNumberSInt32Type, &v_eighty); - const char *v_data = "test"; - CFDataRef pwdata = CFDataCreate(NULL, (UInt8 *)v_data, strlen(v_data)); - CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); - CFTypeRef result = NULL; - CFDictionaryAddValue(query, kSecClass, kSecClassInternetPassword); - CFDictionaryAddValue(query, kSecAttrServer, CFSTR("members.spamcop.net")); - CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("smith")); - CFDictionaryAddValue(query, kSecAttrPort, eighty); - CFDictionaryAddValue(query, kSecAttrProtocol, kSecAttrProtocolHTTP); - CFDictionaryAddValue(query, kSecAttrAuthenticationType, kSecAttrAuthenticationTypeDefault); - CFDictionaryAddValue(query, kSecValueData, pwdata); - CFDictionaryAddValue(query, kSecAttrSynchronizable, kCFBooleanTrue); - - CFDataRef keybag = NULL, password = NULL; - - keybag = create_keybag(kAppleKeyStoreAsymmetricBackupBag, password); - - SecItemDelete(query); - - // add syncable item - ok_status(SecItemAdd(query, NULL), "add internet password"); - - ok_status(SecItemCopyMatching(query, &result), "find item we are about to destroy"); - if (result) { CFRelease(result); result = NULL; } - - CFDictionaryRef backup = NULL; - - ok_status(_SecKeychainBackupSyncable(keybag, password, NULL, &backup), "export items"); - - ok_status(SecItemDelete(query), "delete item we backed up"); - is_status(SecItemCopyMatching(query, &result), errSecItemNotFound, "find item we are about to destroy"); - if (result) { CFRelease(result); result = NULL; } - - ok_status(_SecKeychainRestoreSyncable(keybag, password, backup), "import items"); - - ok_status(SecItemCopyMatching(query, &result), "find restored item"); - if (result) { CFRelease(result); result = NULL; } - - ok_status(SecItemDelete(query), "delete restored item"); - - if (backup) { CFRelease(backup); } -} - -int si_33_keychain_backup(int argc, char *const *argv) -{ - plan_tests(8); - - - tests(); - - return 0; -} diff --git a/libsecurity_keychain/xpc/main.c b/libsecurity_keychain/xpc/main.c deleted file mode 100644 index 198fd005..00000000 --- a/libsecurity_keychain/xpc/main.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Copyright (c) 2011 Apple Computer, Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct connection_info { - xpc_connection_t peer; - int processed; - int done; -}; - -typedef typeof(SecKeychainCopyDomainSearchList) SecKeychainCopyDomainSearchListType; -SecKeychainCopyDomainSearchListType *SecKeychainCopyDomainSearchListFunctionPointer = NULL; -typedef typeof(SecKeychainGetPath) SecKeychainGetPathType; -SecKeychainGetPathType *SecKeychainGetPathFunctionPointer = NULL; - -// prior to 8723022 we have to do our own idle timeout work -#ifndef XPC_HANDLES_IDLE_TIMEOUT -int current_connections = 0; -// Number of seconds to sit with no clients -#define IDLE_WAIT_TIME 30 -#endif - -xpc_object_t keychain_prefs_path = NULL; -xpc_object_t home = NULL; - -extern xpc_object_t -xpc_create_reply_with_format(xpc_object_t original, const char * format, ...); - -static -xpc_object_t create_keychain_search_list_for(xpc_connection_t peer, SecPreferencesDomain domain) -{ - CFArrayRef keychains = NULL; - pid_t peer_pid = xpc_connection_get_pid(peer); - OSStatus status = SecKeychainCopyDomainSearchListFunctionPointer(domain, &keychains); - if (errSecSuccess != status) { - syslog(LOG_ERR, "Unable to get keychain search list (domain=%d) on behalf of %d, status=0x%lx", domain, peer_pid, (unsigned long)status); - return NULL; - } - - xpc_object_t paths = xpc_array_create(NULL, 0); - CFIndex n_keychains = CFArrayGetCount(keychains); - CFIndex i; - for(i = 0; i < n_keychains; i++) { - char path[MAXPATHLEN]; - - SecKeychainRef keychain = (SecKeychainRef)CFArrayGetValueAtIndex(keychains, i); - UInt32 length = MAXPATHLEN; - OSStatus status = SecKeychainGetPathFunctionPointer(keychain, &length, path); - if (errSecSuccess != status) { - syslog(LOG_ERR, "Unable to get path for keychain#%ld of %ld on behalf of %d, status=0x%lx", i, n_keychains, peer_pid, (unsigned long)status); - continue; - } - xpc_object_t path_as_xpc_string = xpc_string_create(path); - xpc_array_append_value(paths, path_as_xpc_string); - xpc_release(path_as_xpc_string); - } - CFRelease(keychains); - return paths; -} - -static -bool keychain_domain_needs_writes(const char *domain_name) -{ - return (0 == strcmp("kSecPreferencesDomainUser", domain_name) || 0 == strcmp("kSecPreferencesDomainDynamic", domain_name)); -} - -static -void _set_keychain_search_lists_for_domain(xpc_connection_t peer, xpc_object_t all_domains, char *domain_name, SecPreferencesDomain domain_enum) -{ - xpc_object_t keychains_for_domain = create_keychain_search_list_for(peer, domain_enum); - if (keychains_for_domain) { - xpc_dictionary_set_value(all_domains, domain_name, keychains_for_domain); - xpc_release(keychains_for_domain); - } else { - syslog(LOG_ERR, "Can't discover keychain paths for domain %s on behalf of %d", domain_name, xpc_connection_get_pid(peer)); - } -} - -#define SET_KEYCHAIN_SEARCH_LISTS_FOR_DOMAIN(peer, all_domains, domain) _set_keychain_search_lists_for_domain(peer, all_domains, #domain, domain); - -static -xpc_object_t create_keychain_search_lists(xpc_connection_t peer) -{ - xpc_object_t all_domains = xpc_dictionary_create(NULL, NULL, 0); - - SET_KEYCHAIN_SEARCH_LISTS_FOR_DOMAIN(peer, all_domains, kSecPreferencesDomainUser); - SET_KEYCHAIN_SEARCH_LISTS_FOR_DOMAIN(peer, all_domains, kSecPreferencesDomainSystem); - SET_KEYCHAIN_SEARCH_LISTS_FOR_DOMAIN(peer, all_domains, kSecPreferencesDomainCommon); - SET_KEYCHAIN_SEARCH_LISTS_FOR_DOMAIN(peer, all_domains, kSecPreferencesDomainDynamic); - - return all_domains; -} - - -static -xpc_object_t create_keychain_and_lock_paths(xpc_connection_t peer, xpc_object_t keychain_path_dict) -{ - pid_t peer_pid = xpc_connection_get_pid(peer); - char *assembly_queue_label = NULL; - asprintf(&assembly_queue_label, "assembly-for-%d", peer_pid); - if (!assembly_queue_label) { - syslog(LOG_ERR, "Unable to create assembly queue label for %d", peer_pid); - return NULL; - } - dispatch_queue_t assembly_queue = dispatch_queue_create(assembly_queue_label, 0); - free(assembly_queue_label); - if (!assembly_queue) { - syslog(LOG_ERR, "Unable to create assembly queue for %d", peer_pid); - return NULL; - } - xpc_object_t return_paths_dict = xpc_dictionary_create(NULL, NULL, 0); - - xpc_dictionary_apply(keychain_path_dict, ^(const char *keychain_domain, xpc_object_t keychain_path_array) { - xpc_object_t return_paths_array = xpc_array_create(NULL, 0); - dispatch_apply(xpc_array_get_count(keychain_path_array), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t i) { - xpc_object_t path_as_xpc_string = xpc_array_get_value(keychain_path_array, i); - dispatch_sync(assembly_queue, ^{ - xpc_array_append_value(return_paths_array, path_as_xpc_string); - }); - - if (!keychain_domain_needs_writes(keychain_domain)) { - // lock files are only to prevent write-write errors, readers don't hold locks, so they don't need the lock files - return; - } - - // figure out the base and dir - const char* path = xpc_array_get_string(keychain_path_array, i); - char* dir; - char* base; - - char buffer[PATH_MAX]; - strcpy(buffer, path); - - if (path != NULL) { - ptrdiff_t i = strlen(buffer) - 1; - while (i >= 0 && buffer[i] != '/') { - i -= 1; - } - - if (i >= 0) { - // NULL terminate the dir - buffer[i] = 0; - dir = buffer; - base = buffer + i + 1; - } else { - dir = NULL; - base = buffer; - } - } - - if (!(path && dir && base)) { - syslog(LOG_ERR, "Can't get dir or base (likely out of memory) for %s", xpc_array_get_string(keychain_path_array, i)); - return; - } - - // "network style" lock files - path_as_xpc_string = xpc_string_create_with_format("%s/lck~%s", dir, base); - dispatch_sync(assembly_queue, ^{ - xpc_array_append_value(return_paths_array, path_as_xpc_string); - }); - xpc_release(path_as_xpc_string); - - CC_SHA1_CTX sha1Context; - CC_SHA1_Init(&sha1Context); - CC_SHA1_Update(&sha1Context, base, (CC_LONG)strlen(base)); - - unsigned char sha1_result_bytes[CC_SHA1_DIGEST_LENGTH]; - - CC_SHA1_Final(sha1_result_bytes, &sha1Context); - - path_as_xpc_string = xpc_string_create_with_format("%s/.fl%02X%02X%02X%02X", dir, sha1_result_bytes[0], sha1_result_bytes[1], sha1_result_bytes[2], sha1_result_bytes[3]); - dispatch_sync(assembly_queue, ^{ - xpc_array_append_value(return_paths_array, path_as_xpc_string); - }); - }); - xpc_dictionary_set_value(return_paths_dict, keychain_domain, return_paths_array); - xpc_release(return_paths_array); - return (bool)true; - }); - - dispatch_release(assembly_queue); - return return_paths_dict; -} - -static -xpc_object_t create_one_sandbox_extension(xpc_object_t path, uint64_t extension_flags) -{ - char *sandbox_extension = NULL; - int status = sandbox_issue_fs_extension(xpc_string_get_string_ptr(path), extension_flags, &sandbox_extension); - if (0 == status && sandbox_extension) { - xpc_object_t sandbox_extension_as_xpc_string = xpc_string_create(sandbox_extension); - free(sandbox_extension); - return sandbox_extension_as_xpc_string; - } else { - syslog(LOG_ERR, "Can't get sandbox fs extension for %s, status=%d errno=%m ext=%s", xpc_string_get_string_ptr(path), status, sandbox_extension); - } - return NULL; -} - -static -xpc_object_t create_all_sandbox_extensions(xpc_object_t path_dict) -{ - xpc_object_t extensions = xpc_array_create(NULL, 0); - - xpc_object_t sandbox_extension = create_one_sandbox_extension(keychain_prefs_path, FS_EXT_FOR_PATH|FS_EXT_READ); - if (sandbox_extension) { - xpc_array_append_value(extensions, sandbox_extension); - xpc_release(sandbox_extension); - } - - xpc_dictionary_apply(path_dict, ^(const char *keychain_domain, xpc_object_t path_array) { - uint64_t extension_flags = FS_EXT_FOR_PATH|FS_EXT_READ; - if (keychain_domain_needs_writes(keychain_domain)) { - extension_flags = FS_EXT_FOR_PATH|FS_EXT_READ|FS_EXT_WRITE; - } - xpc_array_apply(path_array, ^(size_t index, xpc_object_t path) { - xpc_object_t sandbox_extension = create_one_sandbox_extension(path, extension_flags); - if (sandbox_extension) { - xpc_array_append_value(extensions, sandbox_extension); - xpc_release(sandbox_extension); - } - return (bool)true; - }); - return (bool)true; - }); - - return extensions; -} - -static -void handle_request_event(struct connection_info *info, xpc_object_t event) -{ - xpc_connection_t peer = xpc_dictionary_get_connection(event); - xpc_type_t xtype = xpc_get_type(event); - if (info->done) { - syslog(LOG_ERR, "event %p while done", event); - return; - } - if (xtype == XPC_TYPE_ERROR) { - if (event == XPC_ERROR_TERMINATION_IMMINENT) { - // launchd would like us to die, but we have open transactions. When we finish with them xpc_service_main - // will exit for us, so there is nothing for us to do here. - return; - } - - if (!info->done) { - info->done = true; - xpc_release(info->peer); -#ifndef XPC_HANDLES_IDLE_TIMEOUT - if (0 == __sync_add_and_fetch(¤t_connections, -1)) { - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * IDLE_WAIT_TIME), dispatch_get_main_queue(), ^(void) { - if (0 == current_connections) { - exit(0); - } - }); - } -#endif - } - if (peer == NULL && XPC_ERROR_CONNECTION_INVALID == event && 0 != info->processed) { - // this is a normal shutdown on a connection that has processed at least - // one request. Nothing intresting to log. - return; - } - syslog(LOG_ERR, "listener event error (connection %p): %s", peer, xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION)); - } else if (xtype == XPC_TYPE_DICTIONARY) { - const char *operation = xpc_dictionary_get_string(event, "op"); - if (operation && !strcmp(operation, "GrantKeychainPaths")) { - xpc_object_t keychain_paths = create_keychain_search_lists(peer); - xpc_object_t all_paths = create_keychain_and_lock_paths(peer, keychain_paths); - xpc_object_t sandbox_extensions = NULL; - if (all_paths) { - sandbox_extensions = create_all_sandbox_extensions(all_paths); - } - - xpc_object_t reply = xpc_create_reply_with_format(event, "{keychain-paths: %value, all-paths: %value, extensions: %value, keychain-home: %value}", - keychain_paths, all_paths, sandbox_extensions, home); - xpc_connection_send_message(peer, reply); - xpc_release(reply); - if (keychain_paths) { - xpc_release(keychain_paths); - } - if (all_paths) { - xpc_release(all_paths); - } - if (sandbox_extensions) { - xpc_release(sandbox_extensions); - } - if (INT32_MAX != info->processed) { - info->processed++; - } - } else { - syslog(LOG_ERR, "Unknown op=%s request from pid %d", operation, xpc_connection_get_pid(peer)); - } - } else { - syslog(LOG_ERR, "Unhandled request event=%p type=%p", event, xtype); - } -} - -static -void finalize_connection(void *not_used) -{ -#ifdef XPC_HANDLES_IDLE_TIMEOUT - xpc_transaction_end(); -#endif -} - -static -void handle_connection_event(const xpc_connection_t peer) -{ -#ifndef XPC_HANDLES_IDLE_TIMEOUT - __sync_add_and_fetch(¤t_connections, 1); -#endif - __block struct connection_info info; - info.peer = peer; - info.processed = 0; - info.done = false; - - xpc_connection_set_event_handler(peer, ^(xpc_object_t event) { - handle_request_event(&info, event); - }); - - // unlike dispatch objects xpc objects don't need a context set in order to run a finalizer. (we use our finalizer to - // end the transaction we are about to begin...this keeps xpc from idle exiting us while we have a live connection) - xpc_connection_set_finalizer_f(peer, finalize_connection); -#ifdef XPC_HANDLES_IDLE_TIMEOUT - xpc_transaction_begin(); -#endif - - // enable the peer connection to receive messages - xpc_connection_resume(peer); - xpc_retain(peer); -} - - -static const char* g_path_to_plist = "/Library/Preferences/com.apple.security.plist"; - - - -int main(int argc, const char *argv[]) -{ - char *wait4debugger = getenv("WAIT4DEBUGGER"); - if (wait4debugger && !strcasecmp("YES", wait4debugger)) { - syslog(LOG_ERR, "Waiting for debugger"); - kill(getpid(), SIGSTOP); - } - - // get the home directory - const char* home_dir = getenv("HOME"); - - if (home_dir == NULL || strlen(home_dir) == 0) { - struct passwd* pwd = getpwuid(getuid()); - home_dir = pwd->pw_dir; // look it up in directory services, sort of... - } - - size_t home_dir_length = strlen(home_dir); - size_t path_to_plist_length = strlen(g_path_to_plist); - - size_t total_length = home_dir_length + path_to_plist_length + 1; // compensate for terminating zero - if (total_length > PATH_MAX) { - // someone is spoofing us, just exit - return -1; - } - - // make storage for the real path - char buffer[total_length]; - strlcpy(buffer, home_dir, total_length); - strlcat(buffer, g_path_to_plist, total_length); - keychain_prefs_path = xpc_string_create(buffer); - home = xpc_string_create(home_dir); - - void *security_framework = dlopen("/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY); - if (security_framework) { - SecKeychainCopyDomainSearchListFunctionPointer = dlsym(security_framework, "SecKeychainCopyDomainSearchList"); - if (!SecKeychainCopyDomainSearchListFunctionPointer) { - syslog(LOG_ERR, "Can't lookup SecKeychainCopyDomainSearchList in %p: %s", security_framework, dlerror()); - return EX_OSERR; - } - SecKeychainGetPathFunctionPointer = dlsym(security_framework, "SecKeychainGetPath"); - if (!SecKeychainGetPathFunctionPointer) { - syslog(LOG_ERR, "Can't lookup SecKeychainGetPath in %p: %s", security_framework, dlerror()); - return EX_OSERR; - } - } - - xpc_main(handle_connection_event); - - return EX_OSERR; -} diff --git a/libsecurity_manifest/libsecurity_manifest.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_manifest/libsecurity_manifest.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index ab80c26f..00000000 --- a/libsecurity_manifest/libsecurity_manifest.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SuppressBuildableAutocreation - - D6C8AFAD05DD2430003DB724 - - primary - - - - - diff --git a/libsecurity_mds/lib/MDSSchema.cpp b/libsecurity_mds/lib/MDSSchema.cpp deleted file mode 100644 index 104fb619..00000000 --- a/libsecurity_mds/lib/MDSSchema.cpp +++ /dev/null @@ -1,823 +0,0 @@ -/* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - - -// -// MDSSchema.cpp -// -// Definitions of structures which define the schema, including attributes -// and indexes, for the standard tables that are part of the MDS database. -// - -#include "MDSSchema.h" -#include -#include - -namespace Security -{ - -/* - * There appears to be a bug in AppleDatabase which prevents our assigning - * schema to the meta-tables. - */ -#define DEFINE_META_TABLES 0 - -/* indicates "no MDSNameValuePair table" in a RELATION_INFO declaration. */ -#define NO_NVP NULL - -// -// Schema for the lone table in the Object Directory Database. -// -static const CSSM_DB_ATTRIBUTE_INFO objectAttrs[] = { - DB_ATTRIBUTE(ModuleID, STRING), - DB_ATTRIBUTE(Manifest, BLOB), - DB_ATTRIBUTE(ModuleName, STRING), - DB_ATTRIBUTE(Path, STRING), - DB_ATTRIBUTE(ProductVersion, STRING), - - /* not in the CDSA spec; denotes a plugin which is statically linked to CSSM */ - DB_ATTRIBUTE(BuiltIn, UINT32), -}; - -static const CSSM_DB_INDEX_INFO objectIndex[] = { - UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING) -}; - -const RelationInfo kObjectRelation = - RELATION_INFO(MDS_OBJECT_RECORDTYPE, - objectAttrs, - NO_NVP, // no symbolic names - objectIndex); - -// -// Schema for the various tables in the CDSA Directory Database. -// - -// CSSM Relation. -static const CSSM_DB_ATTRIBUTE_INFO cssmAttrs[] = -{ - DB_ATTRIBUTE(ModuleID, STRING), - DB_ATTRIBUTE(CDSAVersion, STRING), - DB_ATTRIBUTE(Vendor, STRING), - DB_ATTRIBUTE(Desc, STRING), - DB_ATTRIBUTE(NativeServices, UINT32), -}; - -static const MDSNameValuePair *cssmNvp[] = { - NULL, NULL, NULL, NULL, - MDSServiceNames -}; - -static const CSSM_DB_INDEX_INFO cssmIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING) -}; - -// KRMM Relation. -static const CSSM_DB_ATTRIBUTE_INFO krmmAttrs[] = -{ - DB_ATTRIBUTE(CSSMGuid, STRING), - DB_ATTRIBUTE(PolicyType, UINT32), - DB_ATTRIBUTE(PolicyName, STRING), - DB_ATTRIBUTE(PolicyPath, STRING), - DB_ATTRIBUTE(PolicyInfo, BLOB), - DB_ATTRIBUTE(PolicyManifest, BLOB), - /* - * This attribute is not defined in the CDSA spec. It's only here, in the schema, - * to avoid throwing exceptions when searching a DB for any records associated - * with a specified GUID - in all other schemas, a guid is specified as a - * ModuleID. - */ - DB_ATTRIBUTE(ModuleID, STRING), -}; - -static const MDSNameValuePair *krmmNvp[] = { - NULL, MDSKrPolicyTypeNames, NULL, NULL, - NULL, NULL, -}; - -static const CSSM_DB_INDEX_INFO krmmIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(CSSMGuid, STRING), - UNIQUE_INDEX_ATTRIBUTE(PolicyType, UINT32) -}; - -// EMM Relation. -static const CSSM_DB_ATTRIBUTE_INFO emmAttrs[] = -{ - DB_ATTRIBUTE(ModuleID, STRING), - DB_ATTRIBUTE(Manifest, BLOB), - DB_ATTRIBUTE(ModuleName, STRING), - DB_ATTRIBUTE(Path, STRING), - DB_ATTRIBUTE(CDSAVersion, STRING), - DB_ATTRIBUTE(EMMSpecVersion, STRING), - DB_ATTRIBUTE(Desc, STRING), - DB_ATTRIBUTE(PolicyStmt, BLOB), - DB_ATTRIBUTE(EmmVersion, STRING), - DB_ATTRIBUTE(EmmVendor, STRING), - DB_ATTRIBUTE(EmmType, UINT32), // does this need a name/value table? -}; - -static const CSSM_DB_INDEX_INFO emmIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING) -}; - -// Primary EMM Service Provider Relation. -static const CSSM_DB_ATTRIBUTE_INFO emmPrimaryAttrs[] = -{ - DB_ATTRIBUTE(ModuleID, STRING), - DB_ATTRIBUTE(SSID, UINT32), - DB_ATTRIBUTE(ServiceType, UINT32), - DB_ATTRIBUTE(Manifest, BLOB), - DB_ATTRIBUTE(ModuleName, STRING), - DB_ATTRIBUTE(ProductVersion, STRING), - DB_ATTRIBUTE(Vendor, STRING), - DB_ATTRIBUTE(SampleTypes, MULTI_UINT32), - DB_ATTRIBUTE(AclSubjectTypes, MULTI_UINT32), - DB_ATTRIBUTE(AuthTags, MULTI_UINT32), - DB_ATTRIBUTE(EmmSpecVersion, STRING), -}; - -static const MDSNameValuePair *emmPrimaryNvp[] = { - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, MDSSampleTypeNames, - MDSAclSubjectTypeNames, - MDSAclAuthTagNames, - NULL -}; - -static const CSSM_DB_INDEX_INFO emmPrimaryIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), - UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32), - UNIQUE_INDEX_ATTRIBUTE(ServiceType, UINT32) -}; - -// Common Relation. -static const CSSM_DB_ATTRIBUTE_INFO commonAttrs[] = -{ - DB_ATTRIBUTE(ModuleID, STRING), - DB_ATTRIBUTE(Manifest, BLOB), - DB_ATTRIBUTE(ModuleName, STRING), - DB_ATTRIBUTE(Path, STRING), - DB_ATTRIBUTE(CDSAVersion, STRING), - DB_ATTRIBUTE(Desc, STRING), - DB_ATTRIBUTE(DynamicFlag, UINT32), - DB_ATTRIBUTE(MultiThreadFlag, UINT32), - DB_ATTRIBUTE(ServiceMask, UINT32), -}; - -static const MDSNameValuePair *commonNvp[] = { - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - MDSServiceNames -}; - -static const CSSM_DB_INDEX_INFO commonIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING) -}; - -// CSP Primary Relation. -static const CSSM_DB_ATTRIBUTE_INFO cspPrimaryAttrs[] = -{ - DB_ATTRIBUTE(ModuleID, STRING), - DB_ATTRIBUTE(SSID, UINT32), - DB_ATTRIBUTE(Manifest, BLOB), - DB_ATTRIBUTE(ModuleName, STRING), - DB_ATTRIBUTE(ProductVersion, STRING), - DB_ATTRIBUTE(Vendor, STRING), - DB_ATTRIBUTE(CspType, UINT32), - DB_ATTRIBUTE(CspFlags, UINT32), - DB_ATTRIBUTE(CspCustomFlags, UINT32), - DB_ATTRIBUTE(UseeTags, MULTI_UINT32), - DB_ATTRIBUTE(SampleTypes, MULTI_UINT32), - DB_ATTRIBUTE(AclSubjectTypes, MULTI_UINT32), - DB_ATTRIBUTE(AuthTags, MULTI_UINT32), -}; - -static const MDSNameValuePair *cspPrimaryNvp[] = { - NULL, NULL, NULL, NULL, - NULL, NULL, - MDSCspTypeNames, - MDSCspFlagsNames, - NULL, - MDSUseeTagsNames, - MDSSampleTypeNames, - MDSAclSubjectTypeNames, - MDSAclAuthTagNames -}; - -static const CSSM_DB_INDEX_INFO cspPrimaryIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), - UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) -}; - -// CSP Capabilities Relation. -static const CSSM_DB_ATTRIBUTE_INFO cspCapabilitiesAttrs[] = -{ - DB_ATTRIBUTE(ModuleID, STRING), - DB_ATTRIBUTE(SSID, UINT32), - DB_ATTRIBUTE(UseeTag, UINT32), - DB_ATTRIBUTE(ContextType, UINT32), - DB_ATTRIBUTE(AlgType, UINT32), - DB_ATTRIBUTE(GroupId, UINT32), - DB_ATTRIBUTE(AttributeType, UINT32), - DB_ATTRIBUTE(AttributeValue, MULTI_UINT32), - DB_ATTRIBUTE(Description, STRING), -}; -static const MDSNameValuePair *cspCapabilitiesNvp[] = { - NULL, - NULL, - MDSUseeTagsNames, - MDSContextTypeNames, - MDSAlgorithmNames, - NULL, - MDSAttributeTypeNames, - NULL, - NULL -}; - -static const CSSM_DB_INDEX_INFO cspCapabilitiesIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), - UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32), - UNIQUE_INDEX_ATTRIBUTE(UseeTag, UINT32), - UNIQUE_INDEX_ATTRIBUTE(ContextType, UINT32), - UNIQUE_INDEX_ATTRIBUTE(AlgType, UINT32), - UNIQUE_INDEX_ATTRIBUTE(GroupId, UINT32), - UNIQUE_INDEX_ATTRIBUTE(AttributeType, STRING) -}; - -// special case "subschema" for parsing CSPCapabilities. These arrays correspond -// dictionaries within a CSPCapabilities info file; they are not part of -// our DB's schema. They are declared only to streamline the -// MDSAttrParser::parseCspCapabilitiesRecord function. No index info is needed. - -// top-level info, applied to the dictionary for the whole file. -static const CSSM_DB_ATTRIBUTE_INFO kAttributesCSPCapabilitiesDict1[] = -{ - DB_ATTRIBUTE(ModuleID, STRING), - DB_ATTRIBUTE(SSID, UINT32), -}; -const RelationInfo CSPCapabilitiesDict1RelInfo = - RELATION_INFO( - MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE, // actually a don't care - kAttributesCSPCapabilitiesDict1, - NULL, // no NVP needed - NULL); // no index - -// "Capabilities" is an array of dictionaries of these -static const CSSM_DB_ATTRIBUTE_INFO kAttributesCSPCapabilitiesDict2[] = -{ - DB_ATTRIBUTE(AlgType, UINT32), - DB_ATTRIBUTE(ContextType, UINT32), - DB_ATTRIBUTE(UseeTag, UINT32), - DB_ATTRIBUTE(Description, STRING), -}; -static const MDSNameValuePair *CSPCapabilitiesDict2Nvp[] = { - MDSAlgorithmNames, - MDSContextTypeNames, - MDSUseeTagsNames, - NULL -}; -const RelationInfo CSPCapabilitiesDict2RelInfo = - RELATION_INFO( - MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE, // actually a don't care - kAttributesCSPCapabilitiesDict2, - CSPCapabilitiesDict2Nvp, - NULL); // no index - -// Within a Capabilities array, the Attributes array is an array of -// Dictionaries of these. -static const CSSM_DB_ATTRIBUTE_INFO kAttributesCSPCapabilitiesDict3[] = -{ - DB_ATTRIBUTE(AttributeType, UINT32), - DB_ATTRIBUTE(AttributeValue, MULTI_UINT32), -}; -static const MDSNameValuePair *CSPCapabilitiesDict3Nvp[] = { - MDSAttributeTypeNames, - NULL -}; -const RelationInfo CSPCapabilitiesDict3RelInfo = - RELATION_INFO( - MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE, // actually a don't care - kAttributesCSPCapabilitiesDict3, - CSPCapabilitiesDict3Nvp, - NULL); - - - -// CSP Encapsulated Products Relation. -static const CSSM_DB_ATTRIBUTE_INFO cspEncapsulatedAttrs[] = -{ - DB_ATTRIBUTE(ModuleID, STRING), - DB_ATTRIBUTE(SSID, UINT32), - DB_ATTRIBUTE(ProductDesc, STRING), - DB_ATTRIBUTE(ProductVendor, STRING), - DB_ATTRIBUTE(ProductVersion, STRING), - DB_ATTRIBUTE(ProductFlags, UINT32), - DB_ATTRIBUTE(CustomFlags, UINT32), - DB_ATTRIBUTE(StandardDesc, STRING), - DB_ATTRIBUTE(StandardVersion, STRING), - DB_ATTRIBUTE(ReaderDesc, STRING), - DB_ATTRIBUTE(ReaderVendor, STRING), - DB_ATTRIBUTE(ReaderVersion, STRING), - DB_ATTRIBUTE(ReaderFirmwareVersion, STRING), - DB_ATTRIBUTE(ReaderFlags, UINT32), - DB_ATTRIBUTE(ReaderCustomFlags, UINT32), - DB_ATTRIBUTE(ReaderSerialNumber, STRING), -}; - -static const MDSNameValuePair *cspEncapsulatedNvp[] = { - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, MDSCspReaderFlagsNames, NULL, NULL -}; - -static const CSSM_DB_INDEX_INFO cspEncapsulatedIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), - UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) -}; - -// CSP Smartcardinfo Relation. -static const CSSM_DB_ATTRIBUTE_INFO cspSmartCardAttrs[] = -{ - DB_ATTRIBUTE(ModuleID, STRING), - DB_ATTRIBUTE(SSID, UINT32), - DB_ATTRIBUTE(ScDesc, STRING), - DB_ATTRIBUTE(ScVendor, STRING), - DB_ATTRIBUTE(ScVersion, STRING), - DB_ATTRIBUTE(ScFirmwareVersion, STRING), - DB_ATTRIBUTE(ScFlags, UINT32), - DB_ATTRIBUTE(ScCustomFlags, UINT32), - DB_ATTRIBUTE(ScSerialNumber, STRING), -}; -static const MDSNameValuePair *cspSmartCardNvp[] = { - NULL, NULL, NULL, NULL, - NULL, NULL, MDSCspScFlagsNames, NULL, - NULL, -}; - -static const CSSM_DB_INDEX_INFO cspSmartCardIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), - UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32), - UNIQUE_INDEX_ATTRIBUTE(ScDesc, STRING), - UNIQUE_INDEX_ATTRIBUTE(ScVendor, STRING), - UNIQUE_INDEX_ATTRIBUTE(ScVersion, STRING), - UNIQUE_INDEX_ATTRIBUTE(ScFirmwareVersion, STRING), - UNIQUE_INDEX_ATTRIBUTE(ScFlags, UINT32) -}; - -// DL Primary Relation. -static const CSSM_DB_ATTRIBUTE_INFO dlPrimaryAttrs[] = -{ - DB_ATTRIBUTE(ModuleID, STRING), - DB_ATTRIBUTE(SSID, UINT32), - DB_ATTRIBUTE(Manifest, BLOB), - DB_ATTRIBUTE(ModuleName, STRING), - DB_ATTRIBUTE(ProductVersion, STRING), - DB_ATTRIBUTE(Vendor, STRING), - DB_ATTRIBUTE(DLType, UINT32), - DB_ATTRIBUTE(QueryLimitsFlag, UINT32), // a completely bogus attr; see spec - DB_ATTRIBUTE(SampleTypes, MULTI_UINT32), - DB_ATTRIBUTE(AclSubjectTypes, MULTI_UINT32), - DB_ATTRIBUTE(AuthTags, MULTI_UINT32), - DB_ATTRIBUTE(ConjunctiveOps, MULTI_UINT32), - DB_ATTRIBUTE(RelationalOps, MULTI_UINT32), -}; -static const MDSNameValuePair *dlPrimaryNvp[] = { - NULL, NULL, NULL, NULL, - NULL, NULL, MDSDlTypeNames, NULL, - MDSSampleTypeNames, - MDSAclSubjectTypeNames, - MDSAclAuthTagNames, - MDSDbConjunctiveNames, - MDSDbOperatorNames -}; -static const CSSM_DB_INDEX_INFO dlPrimaryIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), - UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) -}; - -// DL Encapsulated Products Relation. -static const CSSM_DB_ATTRIBUTE_INFO dlEncapsulatedAttrs[] = -{ - DB_ATTRIBUTE(ModuleID, STRING), - DB_ATTRIBUTE(SSID, UINT32), - DB_ATTRIBUTE(ProductDesc, STRING), - DB_ATTRIBUTE(ProductVendor, STRING), - DB_ATTRIBUTE(ProductVersion, STRING), - DB_ATTRIBUTE(ProductFlags, UINT32), - DB_ATTRIBUTE(StandardDesc, STRING), - DB_ATTRIBUTE(StandardVersion, STRING), - DB_ATTRIBUTE(Protocol, UINT32), - DB_ATTRIBUTE(RetrievalMode, UINT32), -}; - -static const MDSNameValuePair *dlEncapsulatedNvp[] = { - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - MDSNetProtocolNames, - MDSDbRetrievalModeNames -}; - -static const CSSM_DB_INDEX_INFO dlEncapsulatedIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), - UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) -}; - -// CL Primary Relation. -static const CSSM_DB_ATTRIBUTE_INFO clPrimaryAttrs[] = -{ - DB_ATTRIBUTE(ModuleID, STRING), - DB_ATTRIBUTE(SSID, UINT32), - DB_ATTRIBUTE(Manifest, BLOB), - DB_ATTRIBUTE(ModuleName, STRING), - DB_ATTRIBUTE(ProductVersion, STRING), - DB_ATTRIBUTE(Vendor, STRING), - DB_ATTRIBUTE(CertTypeFormat, UINT32), - DB_ATTRIBUTE(CrlTypeFormat, UINT32), - DB_ATTRIBUTE(CertFieldNames, BLOB), - DB_ATTRIBUTE(BundleTypeFormat, MULTI_UINT32), - DB_ATTRIBUTE(XlationTypeFormat, MULTI_UINT32), - DB_ATTRIBUTE(TemplateFieldNames, BLOB), -}; - -static const MDSNameValuePair *clPrimaryNvp[] = { - NULL, NULL, NULL, NULL, - NULL, NULL, MDSCertTypeNames, MDSCrlTypeNames, - NULL, - MDSCertBundleTypeNames, - MDSCertTypeNames, // translation type - same as cert type - right? - NULL -}; - -static const CSSM_DB_INDEX_INFO clPrimaryIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), - UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) -}; - -// CL Encapsulated Products Relation. -static const CSSM_DB_ATTRIBUTE_INFO clEncapsulatedAttrs[] = -{ - DB_ATTRIBUTE(ModuleID, STRING), - DB_ATTRIBUTE(SSID, UINT32), - DB_ATTRIBUTE(ProductDesc, STRING), - DB_ATTRIBUTE(ProductVendor, STRING), - DB_ATTRIBUTE(ProductVersion, STRING), - DB_ATTRIBUTE(ProductFlags, UINT32), - DB_ATTRIBUTE(StandardDesc, STRING), - DB_ATTRIBUTE(StandardVersion, STRING), -}; - -static const CSSM_DB_INDEX_INFO clEncapsulatedIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), - UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) -}; - -// TP Primary Relation. -static const CSSM_DB_ATTRIBUTE_INFO tpPrimaryAttrs[] = -{ - DB_ATTRIBUTE(ModuleID, STRING), - DB_ATTRIBUTE(SSID, UINT32), - DB_ATTRIBUTE(Manifest, BLOB), - DB_ATTRIBUTE(ModuleName, STRING), - DB_ATTRIBUTE(ProductVersion, STRING), - DB_ATTRIBUTE(Vendor, STRING), - DB_ATTRIBUTE(CertTypeFormat, UINT32), - DB_ATTRIBUTE(SampleTypes, MULTI_UINT32), - DB_ATTRIBUTE(AclSubjectTypes, MULTI_UINT32), - DB_ATTRIBUTE(AuthTags, MULTI_UINT32), -}; - -static const MDSNameValuePair *tpPrimaryNvp[] = { - NULL, NULL, NULL, NULL, - NULL, NULL, - MDSCertTypeNames, - MDSSampleTypeNames, - MDSAclSubjectTypeNames, - MDSAclAuthTagNames, -}; - -static const CSSM_DB_INDEX_INFO tpPrimaryIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), - UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) -}; - -// TP Policy-OIDs Relation. -static const CSSM_DB_ATTRIBUTE_INFO tpPolicyOidsAttrs[] = -{ - DB_ATTRIBUTE(ModuleID, STRING), - DB_ATTRIBUTE(SSID, UINT32), - DB_ATTRIBUTE(OID, BLOB), - DB_ATTRIBUTE(Value, BLOB), -}; - -static const CSSM_DB_INDEX_INFO tpPolicyOidsIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), - UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32), - UNIQUE_INDEX_ATTRIBUTE(OID, BLOB) -}; - -// special case "subschema" for parsing tpPolicyOidsAttrs. These arrays correspond -// dictionaries within a tpPolicyOidsAttrs info file; they are not part of -// our DB's schema. They are declared only to streamline the -// MDSAttrParser::parseTpPolicyOidsRecord function. No index info is needed. - -// top-level info, applied to the dictionary for the whole file. -static const CSSM_DB_ATTRIBUTE_INFO tpPolicyOidsDict1[] = -{ - DB_ATTRIBUTE(ModuleID, STRING), - DB_ATTRIBUTE(SSID, UINT32), -}; -const RelationInfo TpPolicyOidsDict1RelInfo = - RELATION_INFO( - MDS_CDSADIR_TP_OIDS_RECORDTYPE, // actually a don't care - tpPolicyOidsDict1, - NULL, // no NVP needed - NULL); // no index - -// One element of the "Policies" array maps to one of these. -static const CSSM_DB_ATTRIBUTE_INFO tpPolicyOidsDict2[] = -{ - DB_ATTRIBUTE(OID, BLOB), - DB_ATTRIBUTE(Value, BLOB), -}; -const RelationInfo TpPolicyOidsDict2RelInfo = - RELATION_INFO( - MDS_CDSADIR_TP_OIDS_RECORDTYPE, // actually a don't care - tpPolicyOidsDict2, - NULL, // no NVP needed - NULL); // no index - -// TP Encapsulated Products Relation. -static const CSSM_DB_ATTRIBUTE_INFO tpEncapsulatedAttrs[] = -{ - DB_ATTRIBUTE(ModuleID, STRING), - DB_ATTRIBUTE(SSID, UINT32), - DB_ATTRIBUTE(ProductDesc, STRING), - DB_ATTRIBUTE(ProductVendor, STRING), - DB_ATTRIBUTE(ProductVersion, STRING), - DB_ATTRIBUTE(ProductFlags, UINT32), // vendor-specific, right? - DB_ATTRIBUTE(AuthorityRequestType, MULTI_UINT32), - DB_ATTRIBUTE(StandardDesc, STRING), - DB_ATTRIBUTE(StandardVersion, STRING), - DB_ATTRIBUTE(ProtocolDesc, STRING), - DB_ATTRIBUTE(ProtocolFlags, UINT32), - DB_ATTRIBUTE(CertClassName, STRING), - DB_ATTRIBUTE(RootCertificate, BLOB), - DB_ATTRIBUTE(RootCertTypeFormat, UINT32), -}; -static const MDSNameValuePair *tpEncapsulatedNvp[] = { - NULL, NULL, NULL, NULL, - NULL, NULL, MDSTpAuthRequestNames, NULL, - NULL, NULL, NULL, NULL, - NULL, MDSCertTypeNames -}; - -static const CSSM_DB_INDEX_INFO tpEncapsulatedIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), - UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) -}; - -#if DEFINE_META_TABLES -// MDS Schema Relations (meta) Relation. -static const CSSM_DB_ATTRIBUTE_INFO mdsSchemaRelationsAttrs[] = -{ - DB_ATTRIBUTE(RelationID, UINT32), - DB_ATTRIBUTE(RelationName, STRING), -}; - -static const CSSM_DB_INDEX_INFO mdsSchemaRelationsIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(RelationID, UINT32), -}; - -// MDS Schema Attributes (meta) Relation. -static const CSSM_DB_ATTRIBUTE_INFO mdsSchemaAttributesAttrs[] = -{ - DB_ATTRIBUTE(RelationID, UINT32), - DB_ATTRIBUTE(AttributeID, UINT32), - DB_ATTRIBUTE(AttributeNameFormat, UINT32), - DB_ATTRIBUTE(AttributeName, STRING), - DB_ATTRIBUTE(AttributeNameID, BLOB), - DB_ATTRIBUTE(AttributeFormat, UINT32), -}; - -static const CSSM_DB_INDEX_INFO mdsSchemaAttributesIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(RelationID, UINT32), - UNIQUE_INDEX_ATTRIBUTE(AttributeID, UINT32) -}; - -// MDS Schema Indexes (meta) Relation. -static const CSSM_DB_ATTRIBUTE_INFO mdsSchemaIndexesAttrs[] = -{ - DB_ATTRIBUTE(RelationID, UINT32), - DB_ATTRIBUTE(IndexID, UINT32), - DB_ATTRIBUTE(AttributeID, UINT32), - DB_ATTRIBUTE(IndexType, UINT32), - DB_ATTRIBUTE(IndexedDataLocation, UINT32), -}; - -static const CSSM_DB_INDEX_INFO mdsSchemaIndexesIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(RelationID, UINT32), - UNIQUE_INDEX_ATTRIBUTE(IndexID, UINT32) -}; - -#endif /* DEFINE_META_TABLES */ - -// AC Primary Relation. -static const CSSM_DB_ATTRIBUTE_INFO acPrimaryAttrs[] = -{ - DB_ATTRIBUTE(ModuleID, STRING), - DB_ATTRIBUTE(SSID, UINT32), - DB_ATTRIBUTE(Manifest, BLOB), - DB_ATTRIBUTE(ModuleName, STRING), - DB_ATTRIBUTE(ProductVersion, STRING), - DB_ATTRIBUTE(Vendor, STRING), -}; - -static const CSSM_DB_INDEX_INFO acPrimaryIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), - UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) -}; - -// KR Primary Relation. -static const CSSM_DB_ATTRIBUTE_INFO krPrimaryAttrs[] = -{ - DB_ATTRIBUTE(ModuleID, STRING), - DB_ATTRIBUTE(SSID, UINT32), - DB_ATTRIBUTE(Manifest, BLOB), - DB_ATTRIBUTE(ModuleName, STRING), - DB_ATTRIBUTE(CompatCSSMVersion, STRING), - DB_ATTRIBUTE(Version, STRING), - DB_ATTRIBUTE(Vendor, STRING), - DB_ATTRIBUTE(Description, STRING), - DB_ATTRIBUTE(ConfigFileLocation, STRING), -}; - -static const CSSM_DB_INDEX_INFO krPrimaryIndex[] = -{ - UNIQUE_INDEX_ATTRIBUTE(ModuleID, STRING), - UNIQUE_INDEX_ATTRIBUTE(SSID, UINT32) -}; - -// list of all built-in schema for the CDSA Directory DB. -const RelationInfo kMDSRelationInfo[] = -{ - RELATION_INFO(MDS_CDSADIR_CSSM_RECORDTYPE, - cssmAttrs, - cssmNvp, - cssmIndex), - RELATION_INFO(MDS_CDSADIR_KRMM_RECORDTYPE, - krmmAttrs, - krmmNvp, - krmmIndex), - RELATION_INFO(MDS_CDSADIR_EMM_RECORDTYPE, - emmAttrs, - NO_NVP, // FIXME - what is the uint32 EmmType here? - emmIndex), - RELATION_INFO(MDS_CDSADIR_EMM_PRIMARY_RECORDTYPE, - emmPrimaryAttrs, - emmPrimaryNvp, - emmPrimaryIndex), - RELATION_INFO(MDS_CDSADIR_COMMON_RECORDTYPE, - commonAttrs, - commonNvp, - commonIndex), - RELATION_INFO(MDS_CDSADIR_CSP_PRIMARY_RECORDTYPE, - cspPrimaryAttrs, - cspPrimaryNvp, - cspPrimaryIndex), - RELATION_INFO(MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE, - cspCapabilitiesAttrs, - cspCapabilitiesNvp, - cspCapabilitiesIndex), - RELATION_INFO(MDS_CDSADIR_CSP_ENCAPSULATED_PRODUCT_RECORDTYPE, - cspEncapsulatedAttrs, - cspEncapsulatedNvp, - cspEncapsulatedIndex), - RELATION_INFO(MDS_CDSADIR_CSP_SC_INFO_RECORDTYPE, - cspSmartCardAttrs, - cspSmartCardNvp, - cspSmartCardIndex), - RELATION_INFO(MDS_CDSADIR_DL_PRIMARY_RECORDTYPE, - dlPrimaryAttrs, - dlPrimaryNvp, - dlPrimaryIndex), - RELATION_INFO(MDS_CDSADIR_DL_ENCAPSULATED_PRODUCT_RECORDTYPE, - dlEncapsulatedAttrs, - dlEncapsulatedNvp, - dlEncapsulatedIndex), - RELATION_INFO(MDS_CDSADIR_CL_PRIMARY_RECORDTYPE, - clPrimaryAttrs, - clPrimaryNvp, - clPrimaryIndex), - RELATION_INFO(MDS_CDSADIR_CL_ENCAPSULATED_PRODUCT_RECORDTYPE, - clEncapsulatedAttrs, - NO_NVP, // none needed - clEncapsulatedIndex), - RELATION_INFO(MDS_CDSADIR_TP_PRIMARY_RECORDTYPE, - tpPrimaryAttrs, - tpPrimaryNvp, - tpPrimaryIndex), - RELATION_INFO(MDS_CDSADIR_TP_OIDS_RECORDTYPE, - tpPolicyOidsAttrs, - NO_NVP, // none needed - tpPolicyOidsIndex), - RELATION_INFO(MDS_CDSADIR_TP_ENCAPSULATED_PRODUCT_RECORDTYPE, - tpEncapsulatedAttrs, - tpEncapsulatedNvp, - tpEncapsulatedIndex), - #if DEFINE_META_TABLES - RELATION_INFO(MDS_CDSADIR_MDS_SCHEMA_RELATIONS, - mdsSchemaRelationsAttrs, - NO_NVP, - mdsSchemaRelationsIndex), - RELATION_INFO(MDS_CDSADIR_MDS_SCHEMA_ATTRIBUTES, - mdsSchemaAttributesAttrs, - NO_NVP, - mdsSchemaAttributesIndex), - RELATION_INFO(MDS_CDSADIR_MDS_SCHEMA_INDEXES, - mdsSchemaIndexesAttrs, - NO_NVP, - mdsSchemaIndexesIndex), - #endif /* DEFINE_META_TABLES */ - RELATION_INFO(MDS_CDSADIR_AC_PRIMARY_RECORDTYPE, - acPrimaryAttrs, - NO_NVP, // none needed - acPrimaryIndex), - RELATION_INFO(MDS_CDSADIR_KR_PRIMARY_RECORDTYPE, - krPrimaryAttrs, - NO_NVP, // none needed - krPrimaryIndex) -}; - -const unsigned kNumMdsRelations = sizeof(kMDSRelationInfo) / sizeof(RelationInfo); - -// Map a CSSM_DB_RECORDTYPE to a RelationInfo *. -extern const RelationInfo *MDSRecordTypeToRelation( - CSSM_DB_RECORDTYPE recordType) -{ - const RelationInfo *relInfo = kMDSRelationInfo; - unsigned dex; - - for(dex=0; dexDataRecordType == recordType) { - return relInfo; - } - relInfo++; - } - if(recordType == MDS_OBJECT_RECORDTYPE) { - return &kObjectRelation; - } - return NULL; -} - -// same as above, based on record type as string. -extern const RelationInfo *MDSRecordTypeNameToRelation( - const char *recordTypeName) -{ - const RelationInfo *relInfo = kMDSRelationInfo; - unsigned dex; - - for(dex=0; dexrelationName)) { - return relInfo; - } - relInfo++; - } - return NULL; -} - -} // end namespace Security diff --git a/libsecurity_mds/lib/MDSSchema.h b/libsecurity_mds/lib/MDSSchema.h deleted file mode 100644 index 450e0ad3..00000000 --- a/libsecurity_mds/lib/MDSSchema.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - - -// -// MDSSchema.h -// -// Declarations of structures which define the schema, including attributes -// and indexes, for the standard tables that are part of the MDS database. -// - -#ifndef _MDSSCHEMA_H -#define _MDSSCHEMA_H - -#include -#include "MDSAttrStrings.h" - -namespace Security -{ - -// Structure used to store information which is needed to create -// a relation with indexes. The info in one of these structs maps to one -// record type in a CSSM_DBINFO - both record attribute info and index info. -// The nameValues field refers to an array of MDSNameValuePair array pointers -// which are used to convert attribute values from strings to uint32s via -// MDS_StringToUint32. The nameValues array is parallel to the AttributeInfo -// array. -struct RelationInfo { - CSSM_DB_RECORDTYPE DataRecordType; - const char *relationName; - uint32 NumberOfAttributes; - const CSSM_DB_ATTRIBUTE_INFO *AttributeInfo; - const MDSNameValuePair **nameValues; - uint32 NumberOfIndexes; - const CSSM_DB_INDEX_INFO *IndexInfo; -}; - -// Macros used to simplify declarations of attributes and indexes. - -// declare a CSSM_DB_ATTRIBUTE_INFO -#define DB_ATTRIBUTE(name, type) \ - { CSSM_DB_ATTRIBUTE_NAME_AS_STRING, \ - {(char*) #name}, \ - CSSM_DB_ATTRIBUTE_FORMAT_ ## type \ - } - -// declare a CSSM_DB_INDEX_INFO -#define UNIQUE_INDEX_ATTRIBUTE(name, type) \ - { CSSM_DB_INDEX_UNIQUE, \ - CSSM_DB_INDEX_ON_ATTRIBUTE, \ - { CSSM_DB_ATTRIBUTE_NAME_AS_STRING, \ - {(char*) #name}, \ - CSSM_DB_ATTRIBUTE_FORMAT_ ## type \ - } \ - } - -// declare a RelationInfo -#define RELATION_INFO(relationId, attributes, nameValues, indexes) \ - { relationId, \ - #relationId, \ - sizeof(attributes) / sizeof(CSSM_DB_ATTRIBUTE_INFO), \ - attributes, \ - nameValues, \ - sizeof(indexes) / sizeof(CSSM_DB_INDEX_INFO), \ - indexes } - -// Object directory DB - one built-in schema. -extern const RelationInfo kObjectRelation; - -// list of all built-in schema for the CDSA Directory DB. -extern const RelationInfo kMDSRelationInfo[]; -extern const unsigned kNumMdsRelations; // size of kMDSRelationInfo[] - -// special case "subschema" for parsing CSPCapabilities. -extern const RelationInfo CSPCapabilitiesDict1RelInfo; -extern const RelationInfo CSPCapabilitiesDict2RelInfo; -extern const RelationInfo CSPCapabilitiesDict3RelInfo; - -// special case "subschema" for parsing TPPolicyOids. -extern const RelationInfo TpPolicyOidsDict1RelInfo; -extern const RelationInfo TpPolicyOidsDict2RelInfo; - -// Map a CSSM_DB_RECORDTYPE to a RelationInfo *. -extern const RelationInfo *MDSRecordTypeToRelation( - CSSM_DB_RECORDTYPE recordType); - -// same as above, based on record type as string. -extern const RelationInfo *MDSRecordTypeNameToRelation( - const char *recordTypeName); - -} // end namespace Security - -#endif // _MDSSCHEMA_H diff --git a/libsecurity_mds/libsecurity_mds.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_mds/libsecurity_mds.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 988e9b5a..00000000 --- a/libsecurity_mds/libsecurity_mds.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 4CA1FEBD052A3C8100F22E42 - - primary - - - - - diff --git a/libsecurity_ocspd/common/ocspdTypes.h b/libsecurity_ocspd/common/ocspdTypes.h deleted file mode 100644 index c6680e85..00000000 --- a/libsecurity_ocspd/common/ocspdTypes.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2002,2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This 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 OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _OCSPD_TYPES_H_ -#define _OCSPD_TYPES_H_ - -#include -#include - -/* Explicitly enable MIG type checking per Radar 4735696 */ -#undef __MigTypeCheck -#define __MigTypeCheck 1 - -typedef void *Data; - -/* - * Standard bootstrap name and an env var name to override it with (!NDEBUG only) - */ -#define OCSPD_BOOTSTRAP_NAME "com.apple.ocspd" -#define OCSPD_BOOTSTRAP_ENV "OCSPD_SERVER" - -#endif /* _OCSPD_TYPES_H_ */ diff --git a/libsecurity_ocspd/common/ocspdUtils.h b/libsecurity_ocspd/common/ocspdUtils.h deleted file mode 100644 index 56276357..00000000 --- a/libsecurity_ocspd/common/ocspdUtils.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2002,2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This 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 OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * ocspUtils.h - common utilities for OCSPD - */ -#ifndef _OCSPD_UTILS_H_ -#define _OCSPD_UTILS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -/* - * Compare two CSSM_DATAs, return CSSM_TRUE if identical. - */ -CSSM_BOOL ocspdCompareCssmData( - const CSSM_DATA *data1, - const CSSM_DATA *data2); - -/* - * Parse a GeneralizedTime string into a CFAbsoluteTime. Returns NULL_TIME on - * parse error. Fractional parts of a second are discarded. - */ -#define NULL_TIME 0.0 - -CFAbsoluteTime genTimeToCFAbsTime( - const CSSM_DATA *strData); - -/* - * Convert CFAbsoluteTime to generalized time string, GMT format (4 digit year, - * trailing 'Z'). Caller allocated the output which is GENERAL_TIME_STRLEN bytes plus - * a NULL. - */ -#define GENERAL_TIME_STRLEN 15 /* NOT including trailing NULL */ - -void cfAbsTimeToGgenTime( - CFAbsoluteTime absTime, - char *genTime); - -#define OCSPD_MAX_DIGEST_LEN CC_SHA256_DIGEST_LENGTH - -void ocspdSha1( - const void *data, - CC_LONG len, - unsigned char *md); // allocd by caller, CC_SHA1_DIGEST_LENGTH bytes -void ocspdMD5( - const void *data, - CC_LONG len, - unsigned char *md); // allocd by caller, CC_MD5_DIGEST_LENGTH bytes -void ocspdMD4( - const void *data, - CC_LONG len, - unsigned char *md); // allocd by caller, CC_MD4_DIGEST_LENGTH bytes -void ocspdSHA256( - const void *data, - CC_LONG len, - unsigned char *md); // allocd by caller, CC_SHA256_DIGEST_LENGTH bytes - -/* - * How many items in a NULL-terminated array of pointers? - */ -unsigned ocspdArraySize( - const void **array); - -#define CFRELEASE(cf) \ - if(cf != NULL) { \ - CFRelease(cf); \ - } - -#ifdef __cplusplus -} -#endif - -#endif /* _OCSPD_UTILS_H_ */ diff --git a/libsecurity_ocspd/libsecurity_ocspd.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_ocspd/libsecurity_ocspd.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index fb66b79c..00000000 --- a/libsecurity_ocspd/libsecurity_ocspd.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,19 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 051BDB75069B372600F9D07E - - primary - - - 4CA1FEBD052A3C8100F22E42 - - primary - - - - - diff --git a/libsecurity_ocspd/mig/mig.mk b/libsecurity_ocspd/mig/mig.mk deleted file mode 100644 index 755a1d1c..00000000 --- a/libsecurity_ocspd/mig/mig.mk +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright (c) 2003-2004 Apple Computer, 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@ -# -# Makefile to build MIG-generated sources and headers -# -DERIVED_SRC = $(BUILT_PRODUCTS_DIR)/derived_src/security_ocspd - -HDRS = $(DERIVED_SRC)/ocspd.h -SRCS = $(DERIVED_SRC)/ocspd_server.cpp $(DERIVED_SRC)/ocspd_client.cpp - -build: $(HDRS) $(SRCS) - -install: build - -installhdrs: $(HDRS) - -installsrc: - -clean: - rm -f $(HDRS) $(SRCS) - -$(HDRS) $(SRCS): $(PROJECT_DIR)/mig/ocspd.defs - mkdir -p $(DERIVED_SRC) - mig -server $(DERIVED_SRC)/ocspd_server.cpp -user $(DERIVED_SRC)/ocspd_client.cpp \ - -header $(DERIVED_SRC)/ocspd.h $(PROJECT_DIR)/mig/ocspd.defs - diff --git a/libsecurity_pkcs12/lib/pkcs12Templates.h b/libsecurity_pkcs12/lib/pkcs12Templates.h deleted file mode 100644 index 97d72fe3..00000000 --- a/libsecurity_pkcs12/lib/pkcs12Templates.h +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (c) 2003-2004 Apple Computer, 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@ - */ -/* - * pkcs12Templates.h - * - ******************************************************************* - * - * In a probably vain attempt to clarify the structure of a PKCS12 - * PFX, here is a high-level summary. - * - * The top level item in P12 is a PFX. - * - * PFX = { - * int version; - * ContentInfo authSafe; -- from PKCS7 - * MacData mac; -- optional, password integrity version - * } - * - * The authSafe in a PFX has two legal contentTypes in the P12 - * world, CT_Data (password integrity mode) or CT_SignedData - * (public key integrity mode). The current version of this library - * only supports password integrity mode. Thus the integrity of - * the whole authSafe item is protected by a MAC in the PFX. - * - * The authSafe.content field is a BER-encoded AuthenticatedSafe. - * - * AuthenticatedSafe = { - * SEQUENCE OF ContentInfo; - * } - * - * OK. Each ContentInfo in an AuthenticatedSafe can either be type - * CT_Data, CT_EnvData, or CT_EncryptedData. In the latter cases the - * content is decrypted to produce an encoded SafeContents; in the - * former case the content *is* an encoded SafeContents. - * - * A SafeContents is a sequence of SafeBags. - * - * Each SafeBag can be of several types: - * - * BT_KeyBag - * BT_ShroudedKeyBag - * BT_CertBag - * BT_CrlBag - * BT_SecretBag - * BT_SafeContentsBag - * - */ - -#ifndef _PKCS12_TEMPLATES_H_ -#define _PKCS12_TEMPLATES_H_ - -#include -#include /* for NSS_Attribute */ -#include -#include "pkcs7Templates.h" /* will be lib-specific place */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * MacData ::= SEQUENCE { - * mac DigestInfo, - * macSalt OCTET STRING, - * iterations INTEGER DEFAULT 1 - * } - */ -typedef struct { - NSS_P7_DigestInfo mac; - CSSM_DATA macSalt; - CSSM_DATA iterations; // optional -} NSS_P12_MacData; - -extern const SecAsn1Template NSS_P12_MacDataTemplate[]; - -/* - * PFX ::= SEQUENCE { - * version INTEGER {v3(3)}(v3,...), - * authSafe ContentInfo, - * macData MacData OPTIONAL - * } - */ - -/* - * First the top level PFX with unparsed ContentInfo.content. - */ -typedef struct { - CSSM_DATA version; - NSS_P7_RawContentInfo authSafe; - NSS_P12_MacData *macData; -} NSS_P12_RawPFX; - -extern const SecAsn1Template NSS_P12_RawPFXTemplate[]; - -/* - * And a PFX with a decoded ContentInfo.content. - */ -typedef struct { - CSSM_DATA version; - NSS_P7_DecodedContentInfo authSafe; - NSS_P12_MacData *macData; -} NSS_P12_DecodedPFX; - -extern const SecAsn1Template NSS_P12_DecodedPFXTemplate[]; - -/* - * The CSSMOID_PKCS7_Data-style ContentInfo.content of a PFX - * contains an encoded AuthenticatedSafe. - * - * AuthenticatedSafe ::= SEQUENCE OF ContentInfo - * -- Data if unencrypted - * -- EncryptedData if password-encrypted - * -- EnvelopedData if public key-encrypted - */ -typedef struct { - NSS_P7_DecodedContentInfo **info; -} NSS_P12_AuthenticatedSafe; - -extern const SecAsn1Template NSS_P12_AuthenticatedSafeTemplate[]; - -/* - * Individual BagTypes. - * Code on demand. - */ -typedef CSSM_DATA NSS_P12_KeyBag; -typedef NSS_EncryptedPrivateKeyInfo NSS_P12_ShroudedKeyBag; -typedef CSSM_DATA NSS_P12_SecretBag; -typedef CSSM_DATA NSS_P12_SafeContentsBag; - -/* - * CertBag - * - * CertBag ::= SEQUENCE { - * certId BAG-TYPE.&id ({CertTypes}), - * certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId}) - * } - * - * x509Certificate BAG-TYPE ::= - * {OCTET STRING IDENTIFIED BY {certTypes 1}} - * -- DER-encoded X.509 certificate stored in OCTET STRING - * sdsiCertificate BAG-TYPE ::= - * {IA5String IDENTIFIED BY {certTypes 2}} - * -- Base64-encoded SDSI certificate stored in IA5String - */ -typedef enum { - CT_Unknown, // --> ASN_ANY - CT_X509, - CT_SDSI, -} NSS_P12_CertBagType; - -typedef struct { - CSSM_OID bagType; - NSS_P12_CertBagType type; - CSSM_DATA certValue; -} NSS_P12_CertBag; - -extern const SecAsn1Template NSS_P12_CertBagTemplate[]; - -/* - * CRLBag - * - * CRLBag ::= SEQUENCE { - * certId BAG-TYPE.&id ({CertTypes}), - * certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId}) - * } - * - * x509Certificate BAG-TYPE ::= - * {OCTET STRING IDENTIFIED BY {certTypes 1}} - * -- DER-encoded X.509 certificate stored in OCTET STRING - * sdsiCertificate BAG-TYPE ::= - * {IA5String IDENTIFIED BY {certTypes 2}} - * -- Base64-encoded SDSI certificate stored in IA5String - */ -typedef enum { - CRT_Unknown, // --> ASN_ANY - CRT_X509, -} NSS_P12_CrlBagType; - -typedef struct { - CSSM_OID bagType; - NSS_P12_CrlBagType type; - CSSM_DATA crlValue; -} NSS_P12_CrlBag; - -extern const SecAsn1Template NSS_P12_CrlBagTemplate[]; - -/* - * BagId OIDs map to one of these for convenience. Our dynamic - * template chooser drops one of these into NSS_P12_SafeBag.type - * on decode. - */ -typedef enum { - BT_None = 0, - BT_KeyBag, - BT_ShroudedKeyBag, - BT_CertBag, - BT_CrlBag, - BT_SecretBag, - BT_SafeContentsBag -} NSS_P12_SB_Type; - -/* - * The ContentInfo.content values of each element in - * an AuthenticatedSafe map to a sequence of these - either directly - * (contentType CSSMOID_PKCS7_Data, octet string contents are - * the DER encoding of this) or indirectly (encrypted or - * shrouded, the decrypted content is the DER encoding of this). - */ -typedef struct { - CSSM_OID bagId; - NSS_P12_SB_Type type; - union { - NSS_P12_KeyBag *keyBag; - NSS_P12_ShroudedKeyBag *shroudedKeyBag; - NSS_P12_CertBag *certBag; - NSS_P12_CrlBag *crlBag; - NSS_P12_SecretBag *secretBag; - NSS_P12_SafeContentsBag *safeContentsBag; - } bagValue; - NSS_Attribute **bagAttrs; // optional -} NSS_P12_SafeBag; - -extern const SecAsn1Template NSS_P12_SafeBagTemplate[]; - -/* - * SafeContents, the contents of an element in an AuthenticatedSafe. - */ -typedef struct { - NSS_P12_SafeBag **bags; -} -NSS_P12_SafeContents; - -extern const SecAsn1Template NSS_P12_SafeContentsTemplate[]; - -/* - * PKCS12-specific algorithm parameters. - * A DER encoded version of this is the parameters value of - * a CSSM_X509_ALGORITHM_IDENTIFIER used in a - * NSS_P7_EncrContentInfo.encrAlg in P12 password privacy mode. - * - * pkcs-12PbeParams ::= SEQUENCE { - * salt OCTET STRING, - * iterations INTEGER - * } - * - * NOTE the P12 spec does place a limit on the value of iterations. - * I guess we have to assume in actual usage that it's - * restricted to (0..MAX), i.e., uint32-sized. - * - * We're also assuming that it is explicitly an unsigned value, - * so that the value bytes in the encoding of 0xff would be - * (0, 255). - */ -typedef struct { - CSSM_DATA salt; - CSSM_DATA iterations; -} NSS_P12_PBE_Params; - -extern const SecAsn1Template NSS_P12_PBE_ParamsTemplate[]; - -#ifdef __cplusplus -} -#endif - -#endif /* _PKCS12_TEMPLATES_H_ */ - diff --git a/libsecurity_pkcs12/lib/pkcs12Utils.cpp b/libsecurity_pkcs12/lib/pkcs12Utils.cpp deleted file mode 100644 index e2040dcd..00000000 --- a/libsecurity_pkcs12/lib/pkcs12Utils.cpp +++ /dev/null @@ -1,832 +0,0 @@ -/* - * Copyright (c) 2003-2004 Apple Computer, 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@ - */ - -/* - * pkcs12Utils.cpp - */ - -#include "pkcs12Utils.h" -#include -#include "pkcs7Templates.h" -#include "pkcs12Templates.h" -#include "pkcs12Crypto.h" -#include "pkcs12Debug.h" -#include -#include -#include -#include -#include -#include -#include -#include - -/* malloc a NULL-ed array of pointers of size num+1 */ -void **p12NssNullArray( - uint32 num, - SecNssCoder &coder) -{ - unsigned len = (num + 1) * sizeof(void *); - void **p = (void **)coder.malloc(len); - memset(p, 0, len); - return p; -} - -/* CSSM_DATA --> uint32. Returns true if OK. */ -bool p12DataToInt( - const CSSM_DATA &cdata, - uint32 &u) -{ - if((cdata.Length == 0) || (cdata.Data == NULL)) { - /* default/not present */ - u = 0; - return true; - } - CSSM_SIZE len = cdata.Length; - if(len > sizeof(uint32)) { - return false; - } - - uint32 rtn = 0; - uint8 *cp = cdata.Data; - for(uint32 i=0; i CSSM_DATA */ -void p12IntToData( - uint32 num, - CSSM_DATA &cdata, - SecNssCoder &coder) -{ - uint32 len = 0; - - if(num < 0x100) { - len = 1; - } - else if(num < 0x10000) { - len = 2; - } - else if(num < 0x1000000) { - len = 3; - } - else { - len = 4; - } - coder.allocItem(cdata, len); - uint8 *cp = &cdata.Data[len - 1]; - for(unsigned i=0; i>= 8; - } -} - -/* CFDataRef <--> CSSM_DATA */ -CFDataRef p12CssmDataToCf( - const CSSM_DATA &c) -{ - return CFDataCreate(NULL, c.Data, c.Length); -} - -void p12CfDataToCssm( - CFDataRef cf, - CSSM_DATA &c, - SecNssCoder &coder) -{ - coder.allocCopyItem(CFDataGetBytePtr(cf), - CFDataGetLength(cf), c); -} - -/* - * Attempt to convert a CFStringRef, which represents a SafeBag's - * FriendlyName, to a UTF8-encoded CSSM_DATA. The CSSM_DATA and its - * referent are allocated in the specified SecNssCoder's memory. - * No guarantee that this conversion works. If it doesn't we return - * NULL and caller must be prepared to deal with that. - */ -CSSM_DATA_PTR p12StringToUtf8( - CFStringRef cfStr, - SecNssCoder &coder) -{ - if(cfStr == NULL) { - return NULL; - } - CFIndex strLen = CFStringGetLength(cfStr); - if(strLen == 0) { - return NULL; - } - CSSM_DATA_PTR rtn = coder.mallocn(); - coder.allocItem(*rtn, strLen + 1); - if(!CFStringGetCString(cfStr, (char *)rtn->Data,strLen + 1, - kCFStringEncodingUTF8)) { - /* not convertible from native Unicode to UTF8 */ - return NULL; - } - return rtn; -} - -/* - * Enum to string mappper. - * Maybe DEBUG only. - */ -/* - * Each type of attribute has a name/value pair in a table of these: - */ -typedef struct { - unsigned value; - const char *name; -} p12NameValuePair; - -/* declare one entry in a table of p12NameValuePair */ -#define NVP(attr) {attr, #attr} - -/* the NULL entry which terminates all p12NameValuePair tables */ -#define NVP_END {0, NULL} - -static const p12NameValuePair p7CITypeNames[] = -{ - NVP(CT_None), - NVP(CT_Data), - NVP(CT_SignedData), - NVP(CT_EnvData), - NVP(CT_SignedEnvData), - NVP(CT_DigestData), - NVP(CT_EncryptedData), - NVP_END -}; - -static const p12NameValuePair p12BagTypeNames[] = -{ - NVP(BT_None), - NVP(BT_KeyBag), - NVP(BT_ShroudedKeyBag), - NVP(BT_CertBag), - NVP(BT_CrlBag), - NVP(BT_SecretBag), - NVP(BT_SafeContentsBag), - NVP_END -}; - -static const char *typeToStr( - unsigned type, - const p12NameValuePair *table) -{ - while(table->name) { - if(table->value == type) { - return table->name; - } - table++; - } - return "Unknown"; -} - -const char *p12BagTypeStr( - NSS_P12_SB_Type type) -{ - return typeToStr(type, p12BagTypeNames); -} - -const char *p7ContentInfoTypeStr( - NSS_P7_CI_Type type) -{ - return typeToStr(type, p7CITypeNames); -} - -/* - * OIDS for P12 and PKCS5 v1.5 (PBES1) encrypt and decrypt map to the following - * attributes. - */ -typedef struct { - const CSSM_OID *oid; - CSSM_ALGORITHMS keyAlg; // e.g., CSSM_ALGID_DES - CSSM_ALGORITHMS encrAlg; // e.g., CSSM_ALGID_3DES_3KEY_EDE - CSSM_ALGORITHMS pbeHashAlg; // SHA1 or MD5 - uint32 keySizeInBits; - uint32 blockSizeInBytes; // for IV, optional - CSSM_PADDING padding; // CSSM_PADDING_PKCS7, etc. - CSSM_ENCRYPT_MODE mode; // CSSM_ALGMODE_CBCPadIV8, etc. - PKCS_Which pkcs; // PW_PKCS12 (for this module) or PW_PKCS5_v1_5 -} PKCSOidInfo; - -static const PKCSOidInfo pkcsOidInfos[] = { - /* PKCS12 first, the ones this module uses */ - { - &CSSMOID_PKCS12_pbeWithSHAAnd128BitRC4, - CSSM_ALGID_RC4, - CSSM_ALGID_RC4, - CSSM_ALGID_SHA1, - 128, - 0, // RC4 is a stream cipher - CSSM_PADDING_NONE, - CSSM_ALGMODE_NONE, - PW_PKCS12 - }, - { - &CSSMOID_PKCS12_pbeWithSHAAnd40BitRC4, - CSSM_ALGID_RC4, - CSSM_ALGID_RC4, - CSSM_ALGID_SHA1, - 40, - 0, // RC4 is a stream cipher - CSSM_PADDING_NONE, - CSSM_ALGMODE_NONE, - PW_PKCS12 - }, - { - &CSSMOID_PKCS12_pbeWithSHAAnd3Key3DESCBC, - CSSM_ALGID_3DES_3KEY, - CSSM_ALGID_3DES_3KEY_EDE, - CSSM_ALGID_SHA1, - 64 * 3, - 8, - CSSM_PADDING_PKCS7, - CSSM_ALGMODE_CBCPadIV8, - PW_PKCS12 - }, - { - &CSSMOID_PKCS12_pbeWithSHAAnd2Key3DESCBC, - CSSM_ALGID_3DES_2KEY, - CSSM_ALGID_3DES_2KEY_EDE, - CSSM_ALGID_SHA1, - 64 * 2, - 8, - CSSM_PADDING_PKCS7, - CSSM_ALGMODE_CBCPadIV8, - PW_PKCS12 - }, - { - &CSSMOID_PKCS12_pbeWithSHAAnd128BitRC2CBC, - CSSM_ALGID_RC2, - CSSM_ALGID_RC2, - CSSM_ALGID_SHA1, - 128, - 8, - CSSM_PADDING_PKCS7, - CSSM_ALGMODE_CBCPadIV8, - PW_PKCS12 - }, - { - &CSSMOID_PKCS12_pbewithSHAAnd40BitRC2CBC, - CSSM_ALGID_RC2, - CSSM_ALGID_RC2, - CSSM_ALGID_SHA1, - 40, - 8, - CSSM_PADDING_PKCS7, - CSSM_ALGMODE_CBCPadIV8, - PW_PKCS12 - }, - - /* PKCS5 v1.5, used for SecImportExport module */ - { - &CSSMOID_PKCS5_pbeWithMD2AndDES, - CSSM_ALGID_DES, - CSSM_ALGID_DES, - CSSM_ALGID_MD2, - 64, - 8, - CSSM_PADDING_PKCS7, - CSSM_ALGMODE_CBCPadIV8, - PW_PKCS5_v1_5 - }, - { - &CSSMOID_PKCS5_pbeWithMD2AndRC2, - CSSM_ALGID_RC2, - CSSM_ALGID_RC2, - CSSM_ALGID_MD2, - 64, - 8, - CSSM_PADDING_PKCS7, - CSSM_ALGMODE_CBCPadIV8, - PW_PKCS5_v1_5 - }, - { - &CSSMOID_PKCS5_pbeWithMD5AndDES, - CSSM_ALGID_DES, - CSSM_ALGID_DES, - CSSM_ALGID_MD5, - 64, - 8, - CSSM_PADDING_PKCS7, - CSSM_ALGMODE_CBCPadIV8, - PW_PKCS5_v1_5 - }, - { - &CSSMOID_PKCS5_pbeWithMD5AndRC2, - CSSM_ALGID_RC2, - CSSM_ALGID_RC2, - CSSM_ALGID_MD5, - 64, - 8, - CSSM_PADDING_PKCS7, - CSSM_ALGMODE_CBCPadIV8, - PW_PKCS5_v1_5 - }, - { - &CSSMOID_PKCS5_pbeWithSHA1AndDES, - CSSM_ALGID_DES, - CSSM_ALGID_DES, - CSSM_ALGID_SHA1, - 64, - 8, - CSSM_PADDING_PKCS7, - CSSM_ALGMODE_CBCPadIV8, - PW_PKCS5_v1_5 - }, - { - &CSSMOID_PKCS5_pbeWithSHA1AndRC2, - CSSM_ALGID_RC2, - CSSM_ALGID_RC2, - CSSM_ALGID_SHA1, - 64, - 8, - CSSM_PADDING_PKCS7, - CSSM_ALGMODE_CBCPadIV8, - PW_PKCS5_v1_5 - }, - - /* finally one for PKCS5 v2.0, which has its own means of - * cooking up all the parameters */ - { - &CSSMOID_PKCS5_PBES2, - CSSM_ALGID_NONE, - CSSM_ALGID_NONE, - CSSM_ALGID_NONE, - 0, 0, 0, 0, - PW_PKCS5_v2 - } -}; - -#define NUM_PKCS_OID_INFOS (sizeof(pkcsOidInfos) / sizeof(pkcsOidInfos[1])) - -/* map an OID to the components */ -/* returns false if OID not found */ - -/* - * NOTE: as of March 8 2004 this is also used by the SecImportExport - * module...not just PKCS12! - */ -bool pkcsOidToParams( - const CSSM_OID *oid, - CSSM_ALGORITHMS &keyAlg, // e.g., CSSM_ALGID_DES - CSSM_ALGORITHMS &encrAlg, // e.g., CSSM_ALGID_3DES_3KEY_EDE - CSSM_ALGORITHMS &pbeHashAlg, // SHA1 or MD5 - uint32 &keySizeInBits, - uint32 &blockSizeInBytes, // for IV, optional - CSSM_PADDING &padding, // CSSM_PADDING_PKCS7, etc. - CSSM_ENCRYPT_MODE &mode, // CSSM_ALGMODE_CBCPadIV8, etc. - PKCS_Which &pkcs) // PW_PKCS5_v1_5 or PW_PKCS12 -{ - const PKCSOidInfo *info = pkcsOidInfos; - pkcs = PW_None; - - for(unsigned dex=0; dexoid)) { - keyAlg = info->keyAlg; - encrAlg = info->encrAlg; - pbeHashAlg = info->pbeHashAlg; - keySizeInBits = info->keySizeInBits; - blockSizeInBytes = info->blockSizeInBytes; - padding = info->padding; - mode = info->mode; - pkcs = info->pkcs; - return true; - } - info++; - } - return false; -} - -/* - * Verify MAC on an existing PFX. - */ -CSSM_RETURN p12VerifyMac( - const NSS_P12_DecodedPFX &pfx, - CSSM_CSP_HANDLE cspHand, - const CSSM_DATA *pwd, // unicode, double null terminated - const CSSM_KEY *passKey, - SecNssCoder &coder) // for temp mallocs -{ - if(pfx.macData == NULL) { - return CSSMERR_CSP_INVALID_SIGNATURE; - } - NSS_P12_MacData &macData = *pfx.macData; - NSS_P7_DigestInfo &digestInfo = macData.mac; - CSSM_OID &algOid = digestInfo.digestAlgorithm.algorithm; - CSSM_ALGORITHMS macAlg; - if(!cssmOidToAlg(&algOid, &macAlg)) { - return CSSMERR_CSP_INVALID_ALGORITHM; - } - uint32 iterCount = 0; - CSSM_DATA &citer = macData.iterations; - if(!p12DataToInt(citer, iterCount)) { - return CSSMERR_CSP_INVALID_ATTR_ROUNDS; - } - if(iterCount == 0) { - /* optional, default 1 */ - iterCount = 1; - } - - /* - * In classic fashion, the PKCS12 spec now says: - * - * When password integrity mode is used to secure a PFX PDU, - * an SHA-1 HMAC is computed on the BER-encoding of the contents - * of the content field of the authSafe field in the PFX PDU. - * - * So here we go. - */ - CSSM_DATA genMac; - CSSM_RETURN crtn = p12GenMac(cspHand, *pfx.authSafe.content.data, - macAlg, iterCount, macData.macSalt, pwd, passKey, coder, genMac); - if(crtn) { - return crtn; - } - if(nssCompareCssmData(&genMac, &digestInfo.digest)) { - return CSSM_OK; - } - else { - return CSSMERR_CSP_VERIFY_FAILED; - } -} - -/* we generate 8 random bytes of salt */ -#define P12_SALT_LEN 8 - -void p12GenSalt( - CSSM_DATA &salt, - SecNssCoder &coder) -{ - DevRandomGenerator rng; - coder.allocItem(salt, P12_SALT_LEN); - rng.random(salt.Data, P12_SALT_LEN); -} - -/* - * Generate random label string to allow associating an imported private - * key with a cert. - */ -void p12GenLabel( - CSSM_DATA &label, - SecNssCoder &coder) -{ - /* first a random uint32 */ - uint8 d[4]; - DevRandomGenerator rng; - rng.random(d, 4); - CSSM_DATA cd = {4, d}; - uint32 i; - p12DataToInt(cd, i); - - /* sprintf that into a real string */ - coder.allocItem(label, 9); - memset(label.Data, 0, 9); - sprintf((char *)label.Data, "%08X", (unsigned)i); -} - -/* NULL algorithm parameters */ - -static const uint8 nullAlg[2] = {SEC_ASN1_NULL, 0}; - -void p12NullAlgParams( - CSSM_X509_ALGORITHM_IDENTIFIER &algId) -{ - CSSM_DATA &p = algId.parameters; - p.Data = (uint8 *)nullAlg; - p.Length = 2; -} - -/* - * Free memory via specified plugin's app-level allocator - */ -void freeCssmMemory( - CSSM_HANDLE hand, - void *p) -{ - CSSM_API_MEMORY_FUNCS memFuncs; - CSSM_RETURN crtn = CSSM_GetAPIMemoryFunctions(hand, &memFuncs); - if(crtn) { - p12LogCssmError("CSSM_GetAPIMemoryFunctions", crtn); - /* oh well, leak and continue */ - return; - } - memFuncs.free_func(p, memFuncs.AllocRef); -} - -/* - * Find private key by label, modify its Label attr to be the - * hash of the associated public key. - * Also optionally re-sets the key's PrintName attribute; used to reset - * this attr from the random label we create when first unwrap it - * to the friendly name we find later after parsing attributes. - * Detection of a duplicate key when updating the key's attributes - * results in a lookup of the original key and returning it in - * foundKey. - */ -CSSM_RETURN p12SetPubKeyHash( - CSSM_CSP_HANDLE cspHand, // where the key lives - CSSM_DL_DB_HANDLE dlDbHand, // ditto - CSSM_DATA &keyLabel, // for DB lookup - CSSM_DATA_PTR newPrintName, // optional - SecNssCoder &coder, // for mallocing newLabel - CSSM_DATA &newLabel, // RETURNED with label as hash - CSSM_KEY_PTR &foundKey) // RETURNED -{ - CSSM_QUERY query; - CSSM_SELECTION_PREDICATE predicate; - CSSM_DB_UNIQUE_RECORD_PTR record = NULL; - CSSM_RETURN crtn; - CSSM_HANDLE resultHand = 0; - CSSM_DATA keyData = {0, NULL}; - CSSM_CC_HANDLE ccHand = 0; - CSSM_KEY_PTR privKey = NULL; - CSSM_DATA_PTR keyDigest = NULL; - - assert(cspHand != 0); - query.RecordType = CSSM_DL_DB_RECORD_PRIVATE_KEY; - query.Conjunctive = CSSM_DB_NONE; - query.NumSelectionPredicates = 1; - predicate.DbOperator = CSSM_DB_EQUAL; - - predicate.Attribute.Info.AttributeNameFormat = - CSSM_DB_ATTRIBUTE_NAME_AS_STRING; - predicate.Attribute.Info.Label.AttributeName = - (char*) P12_KEY_ATTR_LABEL_AND_HASH; - predicate.Attribute.Info.AttributeFormat = - CSSM_DB_ATTRIBUTE_FORMAT_BLOB; - /* hope this cast is OK */ - predicate.Attribute.Value = &keyLabel; - query.SelectionPredicate = &predicate; - - query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? - query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? - query.QueryFlags = CSSM_QUERY_RETURN_DATA; - - /* build Record attribute with one or two attrs */ - CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; - CSSM_DB_ATTRIBUTE_DATA attr[2]; - attr[0].Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; - attr[0].Info.Label.AttributeName = (char*) P12_KEY_ATTR_LABEL_AND_HASH; - attr[0].Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; - if(newPrintName) { - attr[1].Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; - attr[1].Info.Label.AttributeName = (char*) P12_KEY_ATTR_PRINT_NAME; - attr[1].Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; - } - recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_PRIVATE_KEY; - recordAttrs.NumberOfAttributes = newPrintName ? 2 : 1; - recordAttrs.AttributeData = attr; - - crtn = CSSM_DL_DataGetFirst(dlDbHand, - &query, - &resultHand, - &recordAttrs, - &keyData, // theData - &record); - /* abort only on success */ - if(crtn != CSSM_OK) { - p12LogCssmError("CSSM_DL_DataGetFirst", crtn); - p12ErrorLog("***p12SetPubKeyHash: can't find private key\n"); - return crtn; - } - /* subsequent errors to errOut: */ - if(keyData.Data == NULL) { - p12ErrorLog("***p12SetPubKeyHash: private key lookup failure\n"); - crtn = CSSMERR_CSSM_INTERNAL_ERROR; - goto errOut; - } - privKey = (CSSM_KEY_PTR)keyData.Data; - - /* public key hash via passthrough - works on any key, any CSP/CSPDL.... */ - /* - * Warning! This relies on the current default ACL meaning "allow this - * current app to access this private key" since we created the key. - */ - crtn = CSSM_CSP_CreatePassThroughContext(cspHand, privKey, &ccHand); - if(crtn) { - p12LogCssmError("CSSM_CSP_CreatePassThroughContext", crtn); - goto errOut; - } - crtn = CSSM_CSP_PassThrough(ccHand, - CSSM_APPLECSP_KEYDIGEST, - NULL, - (void **)&keyDigest); - if(crtn) { - p12LogCssmError("CSSM_CSP_PassThrough", crtn); - goto errOut; - } - - /* - * Replace Label attr data with hash. - * NOTE: the module which allocated this attribute data - a DL - - * was loaded and attached by out client layer, not by us. Thus - * we can't use the memory allocator functions *we* used when - * attaching to the CSP - we have to use the ones - * which the client registered with the DL. - */ - freeCssmMemory(dlDbHand.DLHandle, attr[0].Value->Data); - freeCssmMemory(dlDbHand.DLHandle, attr[0].Value); - if(newPrintName) { - freeCssmMemory(dlDbHand.DLHandle, attr[1].Value->Data); - freeCssmMemory(dlDbHand.DLHandle, attr[1].Value); - } - /* modify key attributes */ - attr[0].Value = keyDigest; - if(newPrintName) { - attr[1].Value = newPrintName; - } - crtn = CSSM_DL_DataModify(dlDbHand, - CSSM_DL_DB_RECORD_PRIVATE_KEY, - record, - &recordAttrs, - NULL, // DataToBeModified - CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); - switch(crtn) { - case CSSM_OK: - /* give caller the key's new label */ - coder.allocCopyItem(*keyDigest, newLabel); - break; - default: - p12LogCssmError("CSSM_DL_DataModify", crtn); - break; - case CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA: - { - /* - * Special case: dup private key. The label we just tried to modify is - * the public key hash so we can be confident that this really is a dup. - * Delete it, look up the original, and return the original to caller. - */ - CSSM_RETURN drtn = CSSM_DL_DataDelete(dlDbHand, record); - if(drtn) { - p12LogCssmError("CSSM_DL_DataDelete on dup key", drtn); - crtn = drtn; - break; - } - - /* Free items created in last search */ - CSSM_DL_DataAbortQuery(dlDbHand, resultHand); - resultHand = 0; - CSSM_DL_FreeUniqueRecord(dlDbHand, record); - record = NULL; - - /* lookup by label as public key hash this time */ - predicate.Attribute.Value = keyDigest; - drtn = CSSM_DL_DataGetFirst(dlDbHand, - &query, - &resultHand, - NULL, // no attrs this time - &keyData, - &record); - if(drtn) { - p12LogCssmError("CSSM_DL_DataGetFirst on original key", crtn); - crtn = drtn; - break; - } - foundKey = (CSSM_KEY_PTR)keyData.Data; - /* give caller the key's actual label */ - coder.allocCopyItem(*keyDigest, newLabel); - break; - } - } - -errOut: - /* free resources */ - if(resultHand) { - CSSM_DL_DataAbortQuery(dlDbHand, resultHand); - } - if(record) { - CSSM_DL_FreeUniqueRecord(dlDbHand, record); - } - if(ccHand) { - CSSM_DeleteContext(ccHand); - } - if(privKey) { - /* key created by the CSPDL */ - CSSM_FreeKey(cspHand, NULL, privKey, CSSM_FALSE); - freeCssmMemory(dlDbHand.DLHandle, privKey); - } - if(keyDigest) { - /* mallocd by someone else's CSP */ - freeCssmMemory(cspHand, keyDigest->Data); - freeCssmMemory(cspHand, keyDigest); - } - return crtn; -} - -/* - * Given a context specified via a CSSM_CC_HANDLE, add a new - * CSSM_CONTEXT_ATTRIBUTE to the context as specified by AttributeType, - * AttributeLength, and an untyped pointer. - */ -CSSM_RETURN p12AddContextAttribute(CSSM_CC_HANDLE CCHandle, - uint32 AttributeType, - uint32 AttributeLength, - const void *AttributePtr) -{ - CSSM_CONTEXT_ATTRIBUTE newAttr; - CSSM_RETURN crtn; - - newAttr.AttributeType = AttributeType; - newAttr.AttributeLength = AttributeLength; - newAttr.Attribute.Data = (CSSM_DATA_PTR)AttributePtr; - crtn = CSSM_UpdateContextAttributes(CCHandle, 1, &newAttr); - if(crtn) { - p12LogCssmError("CSSM_UpdateContextAttributes", crtn); - } - return crtn; -} - -/* - * Find private key by specified label, delete it. - */ -CSSM_RETURN p12DeleteKey( - CSSM_DL_DB_HANDLE dlDbHand, - const CSSM_DATA &keyLabel) -{ - CSSM_QUERY query; - CSSM_SELECTION_PREDICATE predicate; - CSSM_DB_UNIQUE_RECORD_PTR record = NULL; - CSSM_RETURN crtn; - CSSM_HANDLE resultHand = 0; - - query.RecordType = CSSM_DL_DB_RECORD_PRIVATE_KEY; - query.Conjunctive = CSSM_DB_NONE; - query.NumSelectionPredicates = 1; - predicate.DbOperator = CSSM_DB_EQUAL; - - predicate.Attribute.Info.AttributeNameFormat = - CSSM_DB_ATTRIBUTE_NAME_AS_STRING; - predicate.Attribute.Info.Label.AttributeName = - (char*) P12_KEY_ATTR_LABEL_AND_HASH; - predicate.Attribute.Info.AttributeFormat = - CSSM_DB_ATTRIBUTE_FORMAT_BLOB; - predicate.Attribute.Value = const_cast(&keyLabel); - - query.SelectionPredicate = &predicate; - query.QueryLimits.TimeLimit = 0; - query.QueryLimits.SizeLimit = 1; - query.QueryFlags = 0; - - crtn = CSSM_DL_DataGetFirst(dlDbHand, - &query, - &resultHand, - NULL, // attrs - don't need 'em - NULL, // theData - don't need it - &record); - /* abort only on success */ - if(crtn) { - p12LogCssmError("CSSM_DL_DataGetFirst", crtn); - p12ErrorLog("***p12DeleteKey: can't find private key\n"); - return crtn; - } - - crtn = CSSM_DL_DataDelete(dlDbHand, record); - if(crtn) { - p12LogCssmError("CSSM_DL_DataDelete", crtn); - p12ErrorLog("***p12DeleteKey: can't delete private key\n"); - } - - CSSM_DL_DataAbortQuery(dlDbHand, resultHand); - CSSM_DL_FreeUniqueRecord(dlDbHand, record); - return crtn; -} - -/* convert App passphrase to array of chars used in P12 PBE */ -void p12ImportPassPhrase( - CFStringRef inPhrase, - SecNssCoder &coder, - CSSM_DATA &outPhrase) -{ - CFDataRef cfData = CFStringCreateExternalRepresentation(NULL, - inPhrase, kCFStringEncodingUTF8, 0); - if(cfData == NULL) { - p12ErrorLog("***p12ImportPassPhrase: can't convert passphrase to UTF8\n"); - MacOSError::throwMe(errSecParam); - } - CFIndex keyLen = CFDataGetLength(cfData); - coder.allocItem(outPhrase, keyLen); - memmove(outPhrase.Data, CFDataGetBytePtr(cfData), keyLen); - CFRelease(cfData); -} diff --git a/libsecurity_pkcs12/lib/pkcs12Utils.h b/libsecurity_pkcs12/lib/pkcs12Utils.h deleted file mode 100644 index 342d7f56..00000000 --- a/libsecurity_pkcs12/lib/pkcs12Utils.h +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2003-2004 Apple Computer, 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@ - */ -/* - * pkcs12Utils.h - */ - -#ifndef _PKCS12_UTILS_H_ -#define _PKCS12_UTILS_H_ - -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* malloc a NULL-ed array of pointers of size num+1 */ -void **p12NssNullArray( - uint32 num, - SecNssCoder &coder); - -/* CSSM_DATA --> uint32. Returns true if OK. */ -bool p12DataToInt( - const CSSM_DATA &cdata, - uint32 &u); - -/* uint32 --> CSSM_DATA */ -void p12IntToData( - uint32 num, - CSSM_DATA &cdata, - SecNssCoder &coder); - -/* CFDataRef <--> CSSM_DATA */ -CFDataRef p12CssmDataToCf( - const CSSM_DATA &c); -void p12CfDataToCssm( - CFDataRef cf, - CSSM_DATA &c, - SecNssCoder &coder); - -CSSM_DATA_PTR p12StringToUtf8( - CFStringRef cfStr, - SecNssCoder &coder); - -const char *p12BagTypeStr( - NSS_P12_SB_Type type); -const char *p7ContentInfoTypeStr( - NSS_P7_CI_Type type); - -/* map an OID to the components */ - -typedef enum { - PW_None, /* not comprehended */ - PW_PKCS5_v1_5, /* PKCS5 v1.5 */ - PW_PKCS5_v2, /* PKCS5 v2.0, not used by this module but parsed here */ - PW_PKCS12 /* PKCS12 */ -} PKCS_Which; - -/* returns false if OID not found */ -bool pkcsOidToParams( - const CSSM_OID *oid, - CSSM_ALGORITHMS &keyAlg, // e.g., CSSM_ALGID_DES - CSSM_ALGORITHMS &encrAlg, // e.g., CSSM_ALGID_3DES_3KEY_EDE - CSSM_ALGORITHMS &pbeHashAlg, // SHA1 or MD5 - uint32 &keySizeInBits, - uint32 &blockSizeInBytes, // for IV, optional - CSSM_PADDING &padding, // CSSM_PADDING_PKCS7, etc. - CSSM_ENCRYPT_MODE &mode, // CSSM_ALGMODE_CBCPadIV8, etc. - PKCS_Which &pkcs); // PW_PKCS5_v1_5 or PW_PKCS12 - -CSSM_RETURN p12VerifyMac( - const NSS_P12_DecodedPFX &pfx, - CSSM_CSP_HANDLE cspHand, - const CSSM_DATA *pwd, // unicode, double null terminated - const CSSM_KEY *passKey, - SecNssCoder &coder);// for temp mallocs - -void p12GenSalt( - CSSM_DATA &salt, - SecNssCoder &coder); - -void p12GenLabel( - CSSM_DATA &label, - SecNssCoder &coder); - -void p12NullAlgParams( - CSSM_X509_ALGORITHM_IDENTIFIER &algId); - -/* - * Free memory via specified plugin's app-level allocator - */ -void freeCssmMemory( - CSSM_HANDLE hand, - void *p); - -/* - * Though it pains me to do this, I must. We "happen to know" the - * names (in string form) of two of a key's attributes. These - * have not been published anywhere, they are hard-coded into - * the script (KeySchema.m4) which generates the KeySchema - * tables. - */ - -/* - * This one is initially the same as the "label" argument passed - * in to the CSP when creating or importing keys; it eventually - * gets munged into the hash of the associated public key ( - * in our case, by p12SetPubKeyHash()). - */ -#define P12_KEY_ATTR_LABEL_AND_HASH "Label" - -/* - * This one is the user-friendly name. - */ -#define P12_KEY_ATTR_PRINT_NAME "PrintName" - -/* - * Find private key by label, modify its Label attr to be the - * hash of the associated public key. - */ -CSSM_RETURN p12SetPubKeyHash( - CSSM_CSP_HANDLE cspHand, // where the key lives - CSSM_DL_DB_HANDLE dlDbHand, // ditto - CSSM_DATA &keyLabel, // for DB lookup - CSSM_DATA_PTR newPrintName, // optional - SecNssCoder &coder, // for mallocing newLabel - CSSM_DATA &newLabel, // RETURNED with label as hash - CSSM_KEY_PTR &foundKey); // RETURNED on dup key detect - -CSSM_RETURN p12AddContextAttribute(CSSM_CC_HANDLE CCHandle, - uint32 AttributeType, - uint32 AttributeLength, - const void *AttributePtr); - -/* - * Find private key by specified label, delete it. - */ -CSSM_RETURN p12DeleteKey( - CSSM_DL_DB_HANDLE dlDbHand, - const CSSM_DATA &keyLabel); - -/* convert App passphrase to array of chars used in P12 PBE */ -void p12ImportPassPhrase( - CFStringRef inPhrase, - SecNssCoder &coder, - CSSM_DATA &outPhrase); - -/* - * Standard error throwMes. - * P12_ENCODE_ERR only occurs on DER-encode which should never fail. - */ -#define P12_DECODE_ERR errSecUnknownFormat -#define P12_ENCODE_ERR errSecInternalComponent -#define P12_THROW_DECODE MacOSError::throwMe(P12_DECODE_ERR) -#define P12_THROW_ENCODE MacOSError::throwMe(P12_ENCODE_ERR) - -#ifdef __cplusplus -} -#endif - -#endif /* _PKCS12_UTILS_H_ */ - diff --git a/libsecurity_pkcs12/lib/pkcs7Templates.h b/libsecurity_pkcs12/lib/pkcs7Templates.h deleted file mode 100644 index 6c9fa763..00000000 --- a/libsecurity_pkcs12/lib/pkcs7Templates.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2003-2004 Apple Computer, 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@ - */ -/* - * pkcs7Templates.h - */ - -#ifndef _PKCS7_TEMPLATES_H_ -#define _PKCS7_TEMPLATES_H_ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * DigestInfo ::= SEQUENCE { - * digestAlgorithm DigestAlgorithmIdentifier, - * digest Digest - * } - * - * Digest ::= OCTET STRING - */ -typedef struct { - CSSM_X509_ALGORITHM_IDENTIFIER digestAlgorithm; - CSSM_DATA digest; -} NSS_P7_DigestInfo; - -extern const SecAsn1Template NSS_P7_DigestInfoTemplate[]; - -/* - * Uninterpreted ContentInfo, with content stripped from its - * EXPLICIT CONTEXT_SPECIFIC wrapper - * - * ContentInfo ::= SEQUENCE { - * contentType ContentType, - * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL - * } - */ -typedef struct { - CSSM_OID contentType; - CSSM_DATA content; -} NSS_P7_RawContentInfo; - -extern const SecAsn1Template NSS_P7_RawContentInfoTemplate[]; - -#pragma mark ---- ContentInfo.content types ----- - -/* - * Expand beyond ASN_ANY/CSSM_DATA as needed - */ -typedef CSSM_DATA NSS_P7_SignedData; -typedef CSSM_DATA NSS_P7_EnvelData; -typedef CSSM_DATA NSS_P7_SignEnvelData; -typedef CSSM_DATA NSS_P7_DigestedData; - -/* EncryptedData */ - -/* - * EncryptedContentInfo ::= SEQUENCE { - * contentType ContentType, - * contentEncryptionAlgorithm - * ContentEncryptionAlgorithmIdentifier, - * encryptedContent - * [0] IMPLICIT EncryptedContent OPTIONAL - * } - * - * EncryptedContent ::= OCTET STRING - */ - -typedef struct { - CSSM_OID contentType; - CSSM_X509_ALGORITHM_IDENTIFIER encrAlg; - CSSM_DATA encrContent; -} NSS_P7_EncrContentInfo; - -/* - * EncryptedData ::= SEQUENCE { - * version Version, - * encryptedContentInfo EncryptedContentInfo - * } - */ -typedef struct { - CSSM_DATA version; - NSS_P7_EncrContentInfo contentInfo; -} NSS_P7_EncryptedData; - -extern const SecAsn1Template NSS_P7_EncrContentInfoTemplate[]; -extern const SecAsn1Template NSS_P7_EncryptedDataTemplate[]; -extern const SecAsn1Template NSS_P7_PtrToEncryptedDataTemplate[]; - -/* the stub templates for unimplemented contentTypes */ -#define NSS_P7_PtrToSignedDataTemplate kSecAsn1PointerToAnyTemplate -#define NSS_P7_PtrToEnvelDataTemplate kSecAsn1PointerToAnyTemplate -#define NSS_P7_PtrToSignEnvelDataTemplate kSecAsn1PointerToAnyTemplate -#define NSS_P7_PtrToDigestedDataTemplate kSecAsn1PointerToAnyTemplate - -#pragma mark ---- decoded ContentInfo ----- - -/* - * For convenience, out dynamic template chooser for ContentInfo.content - * drops one of these into the decoded struct. Thus, higher level - * code doesn't have to grunge around comparing OIDs to figure out - * what's there. - */ -typedef enum { - CT_None = 0, - CT_Data, - CT_SignedData, - CT_EnvData, - CT_SignedEnvData, - CT_DigestData, - CT_EncryptedData -} NSS_P7_CI_Type; - -/* - * Decoded ContentInfo. Decoded via SEC_ASN1_DYNAMIC per contentType. - */ -typedef struct { - CSSM_OID contentType; - NSS_P7_CI_Type type; - union { - CSSM_DATA *data; // CSSMOID_PKCS7_Data - // contents of Octet String - NSS_P7_SignedData *signedData; - // CSSMOID_PKCS7_SignedData - NSS_P7_EnvelData *envData; // CSSMOID_PKCS7_EnvelopedData - NSS_P7_SignEnvelData *signEnvelData; - // CSSMOID_PKCS7_SignedAndEnvelopedData - NSS_P7_DigestedData *digestedData; - // CSSMOID_PKCS7_DigestedData - NSS_P7_EncryptedData *encryptData; - //CSSMOID_PKCS7_EncryptedData - - } content; -} NSS_P7_DecodedContentInfo; - -extern const SecAsn1Template NSS_P7_DecodedContentInfoTemplate[]; - -#ifdef __cplusplus -} -#endif - -#endif /* _PKCS7_TEMPLATES_H_ */ - diff --git a/libsecurity_pkcs12/libsecurity_pkcs12.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_pkcs12/libsecurity_pkcs12.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index ee70f1d0..00000000 --- a/libsecurity_pkcs12/libsecurity_pkcs12.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 0592AC8B0415523C00003D05 - - primary - - - - - diff --git a/libsecurity_sd_cspdl/libsecurity_sd_cspdl.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_sd_cspdl/libsecurity_sd_cspdl.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 988e9b5a..00000000 --- a/libsecurity_sd_cspdl/libsecurity_sd_cspdl.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 4CA1FEBD052A3C8100F22E42 - - primary - - - - - diff --git a/libsecurity_smime/APPLE_LICENSE b/libsecurity_smime/APPLE_LICENSE index 71fe6fd7..fe81a60c 100644 --- a/libsecurity_smime/APPLE_LICENSE +++ b/libsecurity_smime/APPLE_LICENSE @@ -1,335 +1,367 @@ APPLE PUBLIC SOURCE LICENSE -Version 2.0 - August 6, 2003 - -Please read this License carefully before downloading this software. By -downloading or using this software, you are agreeing to be bound by the terms -of this License. If you do not or cannot agree to the terms of this License, -please do not download or use the software. - -Apple Note: In January 2007, Apple changed its corporate name from "Apple -Computer, Inc." to "Apple Inc." This change has been reflected below and -copyright years updated, but no other changes have been made to the APSL 2.0. - -1. General; Definitions. This License applies to any program or other -work which Apple Inc. ("Apple") makes publicly available and which contains a -notice placed by Apple identifying such program or work as "Original Code" and -stating that it is subject to the terms of this Apple Public Source License -version 2.0 ("License"). As used in this License: - -1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is the -grantor of rights, (i) claims of patents that are now or hereafter acquired, -owned by or assigned to Apple and (ii) that cover subject matter contained in -the Original Code, but only to the extent necessary to use, reproduce and/or -distribute the Original Code without infringement; and (b) in the case where -You are the grantor of rights, (i) claims of patents that are now or hereafter -acquired, owned by or assigned to You and (ii) that cover subject matter in -Your Modifications, taken alone or in combination with Original Code. - -1.2 "Contributor" means any person or entity that creates or contributes to -the creation of Modifications. - -1.3 "Covered Code" means the Original Code, Modifications, the combination -of Original Code and any Modifications, and/or any respective portions thereof. - -1.4 "Externally Deploy" means: (a) to sublicense, distribute or otherwise -make Covered Code available, directly or indirectly, to anyone other than You; -and/or (b) to use Covered Code, alone or as part of a Larger Work, in any way -to provide a service, including but not limited to delivery of content, through -electronic communication with a client other than You. - -1.5 "Larger Work" means a work which combines Covered Code or portions +Version 2.0 - August 6, 2003 + +Please read this License carefully before downloading this software. +By downloading or using this software, you are agreeing to be bound by +the terms of this License. If you do not or cannot agree to the terms +of this License, please do not download or use the software. + +1. General; Definitions. This License applies to any program or other +work which Apple Computer, Inc. ("Apple") makes publicly available and +which contains a notice placed by Apple identifying such program or +work as "Original Code" and stating that it is subject to the terms of +this Apple Public Source License version 2.0 ("License"). As used in +this License: + +1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is +the grantor of rights, (i) claims of patents that are now or hereafter +acquired, owned by or assigned to Apple and (ii) that cover subject +matter contained in the Original Code, but only to the extent +necessary to use, reproduce and/or distribute the Original Code +without infringement; and (b) in the case where You are the grantor of +rights, (i) claims of patents that are now or hereafter acquired, +owned by or assigned to You and (ii) that cover subject matter in Your +Modifications, taken alone or in combination with Original Code. + +1.2 "Contributor" means any person or entity that creates or +contributes to the creation of Modifications. + +1.3 "Covered Code" means the Original Code, Modifications, the +combination of Original Code and any Modifications, and/or any +respective portions thereof. + +1.4 "Externally Deploy" means: (a) to sublicense, distribute or +otherwise make Covered Code available, directly or indirectly, to +anyone other than You; and/or (b) to use Covered Code, alone or as +part of a Larger Work, in any way to provide a service, including but +not limited to delivery of content, through electronic communication +with a client other than You. + +1.5 "Larger Work" means a work which combines Covered Code or portions thereof with code not governed by the terms of this License. -1.6 "Modifications" mean any addition to, deletion from, and/or change to, -the substance and/or structure of the Original Code, any previous -Modifications, the combination of Original Code and any previous Modifications, -and/or any respective portions thereof. When code is released as a series of -files, a Modification is: (a) any addition to or deletion from the contents of -a file containing Covered Code; and/or (b) any new file or other representation -of computer program statements that contains any part of Covered Code. - -1.7 "Original Code" means (a) the Source Code of a program or other work as -originally made available by Apple under this License, including the Source -Code of any updates or upgrades to such programs or works made available by -Apple under this License, and that has been expressly identified by Apple as -such in the header file(s) of such work; and (b) the object code compiled from -such Source Code and originally made available by Apple under this License - -1.8 "Source Code" means the human readable form of a program or other work -that is suitable for making modifications to it, including all modules it -contains, plus any associated interface definition files, scripts used to -control compilation and installation of an executable (object code). - -1.9 "You" or "Your" means an individual or a legal entity exercising rights -under this License. For legal entities, "You" or "Your" includes any entity -which controls, is controlled by, or is under common control with, You, where -"control" means (a) the power, direct or indirect, to cause the direction or -management of such entity, whether by contract or otherwise, or (b) ownership -of fifty percent (50%) or more of the outstanding shares or beneficial -ownership of such entity. - -2. Permitted Uses; Conditions & Restrictions. Subject to the terms and -conditions of this License, Apple hereby grants You, effective on the date You -accept this License and download the Original Code, a world-wide, royalty-free, -non-exclusive license, to the extent of Apple's Applicable Patent Rights and -copyrights covering the Original Code, to do the following: - -2.1 Unmodified Code. You may use, reproduce, display, perform, internally -distribute within Your organization, and Externally Deploy verbatim, unmodified -copies of the Original Code, for commercial or non-commercial purposes, -provided that in each instance: - -(a) You must retain and reproduce in all copies of Original Code the -copyright and other proprietary notices and disclaimers of Apple as they appear -in the Original Code, and keep intact all notices in the Original Code that -refer to this License; and - -(b) You must include a copy of this License with every copy of Source Code -of Covered Code and documentation You distribute or Externally Deploy, and You -may not offer or impose any terms on such Source Code that alter or restrict -this License or the recipients' rights hereunder, except as permitted under -Section 6. - -2.2 Modified Code. You may modify Covered Code and use, reproduce, +1.6 "Modifications" mean any addition to, deletion from, and/or change +to, the substance and/or structure of the Original Code, any previous +Modifications, the combination of Original Code and any previous +Modifications, and/or any respective portions thereof. When code is +released as a series of files, a Modification is: (a) any addition to +or deletion from the contents of a file containing Covered Code; +and/or (b) any new file or other representation of computer program +statements that contains any part of Covered Code. + +1.7 "Original Code" means (a) the Source Code of a program or other +work as originally made available by Apple under this License, +including the Source Code of any updates or upgrades to such programs +or works made available by Apple under this License, and that has been +expressly identified by Apple as such in the header file(s) of such +work; and (b) the object code compiled from such Source Code and +originally made available by Apple under this License. + +1.8 "Source Code" means the human readable form of a program or other +work that is suitable for making modifications to it, including all +modules it contains, plus any associated interface definition files, +scripts used to control compilation and installation of an executable +(object code). + +1.9 "You" or "Your" means an individual or a legal entity exercising +rights under this License. For legal entities, "You" or "Your" +includes any entity which controls, is controlled by, or is under +common control with, You, where "control" means (a) the power, direct +or indirect, to cause the direction or management of such entity, +whether by contract or otherwise, or (b) ownership of fifty percent +(50%) or more of the outstanding shares or beneficial ownership of +such entity. + +2. Permitted Uses; Conditions & Restrictions. Subject to the terms +and conditions of this License, Apple hereby grants You, effective on +the date You accept this License and download the Original Code, a +world-wide, royalty-free, non-exclusive license, to the extent of +Apple's Applicable Patent Rights and copyrights covering the Original +Code, to do the following: + +2.1 Unmodified Code. You may use, reproduce, display, perform, +internally distribute within Your organization, and Externally Deploy +verbatim, unmodified copies of the Original Code, for commercial or +non-commercial purposes, provided that in each instance: + +(a) You must retain and reproduce in all copies of Original Code the +copyright and other proprietary notices and disclaimers of Apple as +they appear in the Original Code, and keep intact all notices in the +Original Code that refer to this License; and + +(b) You must include a copy of this License with every copy of Source +Code of Covered Code and documentation You distribute or Externally +Deploy, and You may not offer or impose any terms on such Source Code +that alter or restrict this License or the recipients' rights +hereunder, except as permitted under Section 6. + +2.2 Modified Code. You may modify Covered Code and use, reproduce, display, perform, internally distribute within Your organization, and -Externally Deploy Your Modifications and Covered Code, for commercial or -non-commercial purposes, provided that in each instance You also meet all of -these conditions: - -(a) You must satisfy all the conditions of Section 2.1 with respect to the -Source Code of the Covered Code; - -(b) You must duplicate, to the extent it does not already exist, the notice -in Exhibit A in each file of the Source Code of all Your Modifications, and -cause the modified files to carry prominent notices stating that You changed -the files and the date of any change; and - -(c) If You Externally Deploy Your Modifications, You must make Source Code -of all Your Externally Deployed Modifications either available to those to whom -You have Externally Deployed Your Modifications, or publicly available. Source -Code of Your Externally Deployed Modifications must be released under the terms -set forth in this License, including the license grants set forth in Section 3 -below, for as long as you Externally Deploy the Covered Code or twelve (12) -months from the date of initial External Deployment, whichever is longer. You -should preferably distribute the Source Code of Your Externally Deployed -Modifications electronically (e.g. download from a web site). - -2.3 Distribution of Executable Versions. In addition, if You Externally -Deploy Covered Code (Original Code and/or Modifications) in object code, -executable form only, You must include a prominent notice, in the code itself -as well as in related documentation, stating that Source Code of the Covered -Code is available under the terms of this License with information on how and -where to obtain such Source Code. - -2.4 Third Party Rights. You expressly acknowledge and agree that although -Apple and each Contributor grants the licenses to their respective portions of -the Covered Code set forth herein, no assurances are provided by Apple or any -Contributor that the Covered Code does not infringe the patent or other -intellectual property rights of any other entity. Apple and each Contributor -disclaim any liability to You for claims brought by any other entity based on -infringement of intellectual property rights or otherwise. As a condition to -exercising the rights and licenses granted hereunder, You hereby assume sole -responsibility to secure any other intellectual property rights needed, if any. -For example, if a third party patent license is required to allow You to -distribute the Covered Code, it is Your responsibility to acquire that license -before distributing the Covered Code. - -3. Your Grants. In consideration of, and as a condition to, the licenses -granted to You under this License, You hereby grant to any person or entity -receiving or distributing Covered Code under this License a non-exclusive, -royalty-free, perpetual, irrevocable license, under Your Applicable Patent -Rights and other intellectual property rights (other than patent) owned or -controlled by You, to use, reproduce, display, perform, modify, sublicense, -distribute and Externally Deploy Your Modifications of the same scope and -extent as Apple's licenses under Sections 2.1 and 2.2 above. - -4. Larger Works. You may create a Larger Work by combining Covered Code -with other code not governed by the terms of this License and distribute the -Larger Work as a single product. In each such instance, You must make sure the -requirements of this License are fulfilled for the Covered Code or any portion -thereof. - -5. Limitations on Patent License. Except as expressly stated in Section -2, no other patent rights, express or implied, are granted by Apple herein. -Modifications and/or Larger Works may require additional patent licenses from -Apple which Apple may grant in its sole discretion. - -6. Additional Terms. You may choose to offer, and to charge a fee for, -warranty, support, indemnity or liability obligations and/or other rights -consistent with the scope of the license granted herein ("Additional Terms") to -one or more recipients of Covered Code. However, You may do so only on Your own -behalf and as Your sole responsibility, and not on behalf of Apple or any -Contributor. You must obtain the recipient's agreement that any such Additional -Terms are offered by You alone, and You hereby agree to indemnify, defend and -hold Apple and every Contributor harmless for any liability incurred by or -claims asserted against Apple or such Contributor by reason of any such -Additional Terms. - -7. Versions of the License. Apple may publish revised and/or new versions -of this License from time to time. Each version will be given a distinguishing -version number. Once Original Code has been published under a particular -version of this License, You may continue to use it under the terms of that -version. You may also choose to use such Original Code under the terms of any -subsequent version of this License published by Apple. No one other than Apple -has the right to modify the terms applicable to Covered Code created under this -License. - -8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in -part pre-release, untested, or not fully tested works. The Covered Code may -contain errors that could cause failures or loss of data, and may be incomplete -or contain inaccuracies. You expressly acknowledge and agree that use of the -Covered Code, or any portion thereof, is at Your sole and entire risk. THE -COVERED CODE IS PROVIDED "AS IS" AND WITHOUT WARRANTY, UPGRADES OR SUPPORT OF -ANY KIND AND APPLE AND APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" -FOR THE PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM -ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF MERCHANTABILITY, OF -SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY, OF -QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. APPLE AND EACH -CONTRIBUTOR DOES NOT WARRANT AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE -COVERED CODE, THAT THE FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR -REQUIREMENTS, THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR -ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO ORAL OR -WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE AUTHORIZED -REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. You acknowledge -that the Covered Code is not intended for use in the operation of nuclear -facilities, aircraft navigation, communication systems, or air traffic control -machines in which case the failure of the Covered Code could lead to death, -personal injury, or severe physical or environmental damage. - -9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO -EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, SPECIAL, -INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO THIS LICENSE OR -YOUR USE OR INABILITY TO USE THE COVERED CODE, OR ANY PORTION THEREOF, WHETHER -UNDER A THEORY OF CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE), PRODUCTS -LIABILITY OR OTHERWISE, EVEN IF APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF -THE POSSIBILITY OF SUCH DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL -PURPOSE OF ANY REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF -LIABILITY OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT -APPLY TO YOU. In no event shall Apple's total liability to You for all damages -(other than as may be required by applicable law) under this License exceed the -amount of fifty dollars ($50.00). - -10. Trademarks. This License does not grant any rights to use the -trademarks or trade names "Apple", "Mac", "Mac OS", "QuickTime", "QuickTime -Streaming Server" or any other trademarks, service marks, logos or trade names -belonging to Apple (collectively "Apple Marks") or to any trademark, service -mark, logo or trade name belonging to any Contributor. You agree not to use -any Apple Marks in or as part of the name of products derived from the Original -Code or to endorse or promote products derived from the Original Code other -than as expressly permitted by and in strict compliance at all times with -Apple's third party trademark usage guidelines which are posted at -http://www.apple.com/legal/guidelinesfor3rdparties.html. - -11. Ownership. Subject to the licenses granted under this License, each -Contributor retains all rights, title and interest in and to any Modifications -made by such Contributor. Apple retains all rights, title and interest in and -to the Original Code and any Modifications made by or on behalf of Apple -("Apple Modifications"), and such Apple Modifications will not be automatically -subject to this License. Apple may, at its sole discretion, choose to license -such Apple Modifications under this License, or on different terms from those -contained in this License or may choose not to license them at all. - -12. Termination. - -12.1 Termination. This License and the rights granted hereunder will +Externally Deploy Your Modifications and Covered Code, for commercial +or non-commercial purposes, provided that in each instance You also +meet all of these conditions: + +(a) You must satisfy all the conditions of Section 2.1 with respect to +the Source Code of the Covered Code; + +(b) You must duplicate, to the extent it does not already exist, the +notice in Exhibit A in each file of the Source Code of all Your +Modifications, and cause the modified files to carry prominent notices +stating that You changed the files and the date of any change; and + +(c) If You Externally Deploy Your Modifications, You must make +Source Code of all Your Externally Deployed Modifications either +available to those to whom You have Externally Deployed Your +Modifications, or publicly available. Source Code of Your Externally +Deployed Modifications must be released under the terms set forth in +this License, including the license grants set forth in Section 3 +below, for as long as you Externally Deploy the Covered Code or twelve +(12) months from the date of initial External Deployment, whichever is +longer. You should preferably distribute the Source Code of Your +Externally Deployed Modifications electronically (e.g. download from a +web site). + +2.3 Distribution of Executable Versions. In addition, if You +Externally Deploy Covered Code (Original Code and/or Modifications) in +object code, executable form only, You must include a prominent +notice, in the code itself as well as in related documentation, +stating that Source Code of the Covered Code is available under the +terms of this License with information on how and where to obtain such +Source Code. + +2.4 Third Party Rights. You expressly acknowledge and agree that +although Apple and each Contributor grants the licenses to their +respective portions of the Covered Code set forth herein, no +assurances are provided by Apple or any Contributor that the Covered +Code does not infringe the patent or other intellectual property +rights of any other entity. Apple and each Contributor disclaim any +liability to You for claims brought by any other entity based on +infringement of intellectual property rights or otherwise. As a +condition to exercising the rights and licenses granted hereunder, You +hereby assume sole responsibility to secure any other intellectual +property rights needed, if any. For example, if a third party patent +license is required to allow You to distribute the Covered Code, it is +Your responsibility to acquire that license before distributing the +Covered Code. + +3. Your Grants. In consideration of, and as a condition to, the +licenses granted to You under this License, You hereby grant to any +person or entity receiving or distributing Covered Code under this +License a non-exclusive, royalty-free, perpetual, irrevocable license, +under Your Applicable Patent Rights and other intellectual property +rights (other than patent) owned or controlled by You, to use, +reproduce, display, perform, modify, sublicense, distribute and +Externally Deploy Your Modifications of the same scope and extent as +Apple's licenses under Sections 2.1 and 2.2 above. + +4. Larger Works. You may create a Larger Work by combining Covered +Code with other code not governed by the terms of this License and +distribute the Larger Work as a single product. In each such instance, +You must make sure the requirements of this License are fulfilled for +the Covered Code or any portion thereof. + +5. Limitations on Patent License. Except as expressly stated in +Section 2, no other patent rights, express or implied, are granted by +Apple herein. Modifications and/or Larger Works may require additional +patent licenses from Apple which Apple may grant in its sole +discretion. + +6. Additional Terms. You may choose to offer, and to charge a fee for, +warranty, support, indemnity or liability obligations and/or other +rights consistent with the scope of the license granted herein +("Additional Terms") to one or more recipients of Covered Code. +However, You may do so only on Your own behalf and as Your sole +responsibility, and not on behalf of Apple or any Contributor. You +must obtain the recipient's agreement that any such Additional Terms +are offered by You alone, and You hereby agree to indemnify, defend +and hold Apple and every Contributor harmless for any liability +incurred by or claims asserted against Apple or such Contributor by +reason of any such Additional Terms. + +7. Versions of the License. Apple may publish revised and/or new +versions of this License from time to time. Each version will be given +a distinguishing version number. Once Original Code has been published +under a particular version of this License, You may continue to use it +under the terms of that version. You may also choose to use such +Original Code under the terms of any subsequent version of this +License published by Apple. No one other than Apple has the right to +modify the terms applicable to Covered Code created under this +License. + +8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in +part pre-release, untested, or not fully tested works. The Covered +Code may contain errors that could cause failures or loss of data, and +may be incomplete or contain inaccuracies. You expressly acknowledge +and agree that use of the Covered Code, or any portion thereof, is at +Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND +WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND +APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE +PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM +ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF +MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR +PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD +PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST +INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE +FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS, +THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR +ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO +ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE +AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. +You acknowledge that the Covered Code is not intended for use in the +operation of nuclear facilities, aircraft navigation, communication +systems, or air traffic control machines in which case the failure of +the Covered Code could lead to death, personal injury, or severe +physical or environmental damage. + +9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO +EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING +TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR +ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY, +TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF +APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY +REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF +INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY +TO YOU. In no event shall Apple's total liability to You for all +damages (other than as may be required by applicable law) under this +License exceed the amount of fifty dollars ($50.00). + +10. Trademarks. This License does not grant any rights to use the +trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS", +"QuickTime", "QuickTime Streaming Server" or any other trademarks, +service marks, logos or trade names belonging to Apple (collectively +"Apple Marks") or to any trademark, service mark, logo or trade name +belonging to any Contributor. You agree not to use any Apple Marks in +or as part of the name of products derived from the Original Code or +to endorse or promote products derived from the Original Code other +than as expressly permitted by and in strict compliance at all times +with Apple's third party trademark usage guidelines which are posted +at http://www.apple.com/legal/guidelinesfor3rdparties.html. + +11. Ownership. Subject to the licenses granted under this License, +each Contributor retains all rights, title and interest in and to any +Modifications made by such Contributor. Apple retains all rights, +title and interest in and to the Original Code and any Modifications +made by or on behalf of Apple ("Apple Modifications"), and such Apple +Modifications will not be automatically subject to this License. Apple +may, at its sole discretion, choose to license such Apple +Modifications under this License, or on different terms from those +contained in this License or may choose not to license them at all. + +12. Termination. + +12.1 Termination. This License and the rights granted hereunder will terminate: -(a) automatically without notice from Apple if You fail to comply with any -term(s) of this License and fail to cure such breach within 30 days of becoming -aware of such breach; -(b) immediately in the event of the circumstances described in Section +(a) automatically without notice from Apple if You fail to comply with +any term(s) of this License and fail to cure such breach within 30 +days of becoming aware of such breach; + +(b) immediately in the event of the circumstances described in Section 13.5(b); or -(c) automatically without notice from Apple if You, at any time during the -term of this License, commence an action for patent infringement against Apple; -provided that Apple did not first commence an action for patent infringement -against You in that instance. - -12.2 Effect of Termination. Upon termination, You agree to immediately stop -any further use, reproduction, modification, sublicensing and distribution of -the Covered Code. All sublicenses to the Covered Code which have been properly -granted prior to termination shall survive any termination of this License. -Provisions which, by their nature, should remain in effect beyond the -termination of this License shall survive, including but not limited to -Sections 3, 5, 8, 9, 10, 11, 12.2 and 13. No party will be liable to any other -for compensation, indemnity or damages of any sort solely as a result of -terminating this License in accordance with its terms, and termination of this -License will be without prejudice to any other right or remedy of any party. - -13. Miscellaneous. - -13.1 Government End Users. The Covered Code is a "commercial item" as -defined in FAR 2.101. Government software and technical data rights in the -Covered Code include only those rights customarily provided to the public as -defined in this License. This customary commercial license in technical data -and software is provided in accordance with FAR 12.211 (Technical Data) and -12.212 (Computer Software) and, for Department of Defense purchases, DFAR -252.227-7015 (Technical Data -- Commercial Items) and 227.7202-3 (Rights in -Commercial Computer Software or Computer Software Documentation). Accordingly, -all U.S. Government End Users acquire Covered Code with only those rights set + +(c) automatically without notice from Apple if You, at any time during +the term of this License, commence an action for patent infringement +against Apple; provided that Apple did not first commence +an action for patent infringement against You in that instance. + +12.2 Effect of Termination. Upon termination, You agree to immediately +stop any further use, reproduction, modification, sublicensing and +distribution of the Covered Code. All sublicenses to the Covered Code +which have been properly granted prior to termination shall survive +any termination of this License. Provisions which, by their nature, +should remain in effect beyond the termination of this License shall +survive, including but not limited to Sections 3, 5, 8, 9, 10, 11, +12.2 and 13. No party will be liable to any other for compensation, +indemnity or damages of any sort solely as a result of terminating +this License in accordance with its terms, and termination of this +License will be without prejudice to any other right or remedy of +any party. + +13. Miscellaneous. + +13.1 Government End Users. The Covered Code is a "commercial item" as +defined in FAR 2.101. Government software and technical data rights in +the Covered Code include only those rights customarily provided to the +public as defined in this License. This customary commercial license +in technical data and software is provided in accordance with FAR +12.211 (Technical Data) and 12.212 (Computer Software) and, for +Department of Defense purchases, DFAR 252.227-7015 (Technical Data -- +Commercial Items) and 227.7202-3 (Rights in Commercial Computer +Software or Computer Software Documentation). Accordingly, all U.S. +Government End Users acquire Covered Code with only those rights set forth herein. -13.2 Relationship of Parties. This License will not be construed as -creating an agency, partnership, joint venture or any other form of legal -association between or among You, Apple or any Contributor, and You will not -represent to the contrary, whether expressly, by implication, appearance or -otherwise. - -13.3 Independent Development. Nothing in this License will impair Apple's -right to acquire, license, develop, have others develop for it, market and/or -distribute technology or products that perform the same or similar functions -as, or otherwise compete with, Modifications, Larger Works, technology or -products that You may develop, produce, market or distribute. - -13.4 Waiver; Construction. Failure by Apple or any Contributor to enforce -any provision of this License will not be deemed a waiver of future enforcement -of that or any other provision. Any law or regulation which provides that the -language of a contract shall be construed against the drafter will not apply to -this License. - -13.5 Severability. (a) If for any reason a court of competent jurisdiction -finds any provision of this License, or portion thereof, to be unenforceable, -that provision of the License will be enforced to the maximum extent -permissible so as to effect the economic benefits and intent of the parties, -and the remainder of this License will continue in full force and effect. (b) -Notwithstanding the foregoing, if applicable law prohibits or restricts You -from fully and/or specifically complying with Sections 2 and/or 3 or prevents -the enforceability of either of those Sections, this License will immediately -terminate and You must immediately discontinue any use of the Covered Code and -destroy all copies of it that are in your possession or control. - -13.6 Dispute Resolution. Any litigation or other dispute resolution between -You and Apple relating to this License shall take place in the Northern -District of California, and You and Apple hereby consent to the personal -jurisdiction of, and venue in, the state and federal courts within that -District with respect to this License. The application of the United Nations -Convention on Contracts for the International Sale of Goods is expressly -excluded. - -13.7 Entire Agreement; Governing Law. This License constitutes the entire -agreement between the parties with respect to the subject matter hereof. This -License shall be governed by the laws of the United States and the State of -California, except that body of California law concerning conflicts of law. - -Where You are located in the province of Quebec, Canada, the following clause -applies: The parties hereby confirm that they have requested that this License -and all related documents be drafted in English. Les parties ont exigé que le -présent contrat et tous les documents connexes soient rédigés en anglais. - -EXHIBIT A. - -"Portions Copyright (c) 1999-2007 Apple Inc. All Rights Reserved. - -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. +13.2 Relationship of Parties. This License will not be construed as +creating an agency, partnership, joint venture or any other form of +legal association between or among You, Apple or any Contributor, and +You will not represent to the contrary, whether expressly, by +implication, appearance or otherwise. + +13.3 Independent Development. Nothing in this License will impair +Apple's right to acquire, license, develop, have others develop for +it, market and/or distribute technology or products that perform the +same or similar functions as, or otherwise compete with, +Modifications, Larger Works, technology or products that You may +develop, produce, market or distribute. + +13.4 Waiver; Construction. Failure by Apple or any Contributor to +enforce any provision of this License will not be deemed a waiver of +future enforcement of that or any other provision. Any law or +regulation which provides that the language of a contract shall be +construed against the drafter will not apply to this License. + +13.5 Severability. (a) If for any reason a court of competent +jurisdiction finds any provision of this License, or portion thereof, +to be unenforceable, that provision of the License will be enforced to +the maximum extent permissible so as to effect the economic benefits +and intent of the parties, and the remainder of this License will +continue in full force and effect. (b) Notwithstanding the foregoing, +if applicable law prohibits or restricts You from fully and/or +specifically complying with Sections 2 and/or 3 or prevents the +enforceability of either of those Sections, this License will +immediately terminate and You must immediately discontinue any use of +the Covered Code and destroy all copies of it that are in your +possession or control. + +13.6 Dispute Resolution. Any litigation or other dispute resolution +between You and Apple relating to this License shall take place in the +Northern District of California, and You and Apple hereby consent to +the personal jurisdiction of, and venue in, the state and federal +courts within that District with respect to this License. The +application of the United Nations Convention on Contracts for the +International Sale of Goods is expressly excluded. + +13.7 Entire Agreement; Governing Law. This License constitutes the +entire agreement between the parties with respect to the subject +matter hereof. This License shall be governed by the laws of the +United States and the State of California, except that body of +California law concerning conflicts of law. + +Where You are located in the province of Quebec, Canada, the following +clause applies: The parties hereby confirm that they have requested +that this License and all related documents be drafted in English. Les +parties ont exige que le present contrat et tous les documents +connexes soient rediges en anglais. + +EXHIBIT A. + +"Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights +Reserved. + +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." - +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." diff --git a/libsecurity_smime/Security b/libsecurity_smime/Security new file mode 120000 index 00000000..945c9b46 --- /dev/null +++ b/libsecurity_smime/Security @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/libsecurity_smime/lib/SecAsn1Item.c b/libsecurity_smime/lib/SecAsn1Item.c new file mode 100644 index 00000000..bef79e38 --- /dev/null +++ b/libsecurity_smime/lib/SecAsn1Item.c @@ -0,0 +1,306 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* + * Support routines for SecAsn1Item data structure. + */ + +#include "SecAsn1Item.h" +#include +#include +#include + +SecAsn1Item * +SECITEM_AllocItem(PRArenaPool *arena, SecAsn1Item *item, size_t len) +{ + SecAsn1Item *result = NULL; + void *mark = NULL; + + if (arena != NULL) { + mark = PORT_ArenaMark(arena); + } + + if (item == NULL) { + if (arena != NULL) { + result = PORT_ArenaZAlloc(arena, sizeof(SecAsn1Item)); + } else { + result = PORT_ZAlloc(sizeof(SecAsn1Item)); + } + if (result == NULL) { + goto loser; + } + } else { + PORT_Assert(item->Data == NULL); + result = item; + } + + result->Length = len; + if (len) { + if (arena != NULL) { + result->Data = PORT_ArenaAlloc(arena, len); + } else { + result->Data = PORT_Alloc(len); + } + } + + if (mark) { + PORT_ArenaUnmark(arena, mark); + } + return(result); + +loser: + if ( arena != NULL ) { + if (mark) { + PORT_ArenaRelease(arena, mark); + } + if (item != NULL) { + item->Data = NULL; + item->Length = 0; + } + } else { + if (result != NULL) { + SECITEM_FreeItem(result, (item == NULL) ? PR_TRUE : PR_FALSE); + } + } + return(NULL); +} + +SECStatus +SECITEM_ReallocItem(PRArenaPool *arena, SecAsn1Item *item, size_t oldlen, + size_t newlen) +{ + PORT_Assert(item != NULL); + if (item == NULL) { + /* XXX Set error. But to what? */ + return SECFailure; + } + + /* + * If no old length, degenerate to just plain alloc. + */ + if (oldlen == 0) { + PORT_Assert(item->Data == NULL || item->Length == 0); + if (newlen == 0) { + /* Nothing to do. Weird, but not a failure. */ + return SECSuccess; + } + item->Length = newlen; + if (arena != NULL) { + item->Data = PORT_ArenaAlloc(arena, newlen); + } else { + item->Data = PORT_Alloc(newlen); + } + } else { + if (arena != NULL) { + item->Data = PORT_ArenaGrow(arena, item->Data, oldlen, newlen); + } else { + item->Data = PORT_Realloc(item->Data, newlen); + } + } + + if (item->Data == NULL) { + return SECFailure; + } + + return SECSuccess; +} + +SECComparison +SECITEM_CompareItem(const SecAsn1Item *a, const SecAsn1Item *b) +{ + size_t m; + SECComparison rv; + + m = ( ( a->Length < b->Length ) ? a->Length : b->Length ); + + rv = (SECComparison) PORT_Memcmp(a->Data, b->Data, m); + if (rv) { + return rv; + } + if (a->Length < b->Length) { + return SECLessThan; + } + if (a->Length == b->Length) { + return SECEqual; + } + return SECGreaterThan; +} + +Boolean +SECITEM_ItemsAreEqual(const SecAsn1Item *a, const SecAsn1Item *b) +{ + if (a->Length != b->Length) + return PR_FALSE; + if (!a->Length) + return PR_TRUE; + if (!a->Data || !b->Data) { + /* avoid null pointer crash. */ + return (Boolean)(a->Data == b->Data); + } + return (Boolean)!PORT_Memcmp(a->Data, b->Data, a->Length); +} + +SecAsn1Item * +SECITEM_DupItem(const SecAsn1Item *from) +{ + return SECITEM_ArenaDupItem(NULL, from); +} + +SecAsn1Item * +SECITEM_ArenaDupItem(PRArenaPool *arena, const SecAsn1Item *from) +{ + SecAsn1Item *to; + + if ( from == NULL ) { + return(NULL); + } + + if ( arena != NULL ) { + to = (SecAsn1Item *)PORT_ArenaAlloc(arena, sizeof(SecAsn1Item)); + } else { + to = (SecAsn1Item *)PORT_Alloc(sizeof(SecAsn1Item)); + } + if ( to == NULL ) { + return(NULL); + } + + if ( arena != NULL ) { + to->Data = (unsigned char *)PORT_ArenaAlloc(arena, from->Length); + } else { + to->Data = (unsigned char *)PORT_Alloc(from->Length); + } + if ( to->Data == NULL ) { + PORT_Free(to); + return(NULL); + } + + to->Length = from->Length; + // to->type = from->type; + if ( to->Length ) { + PORT_Memcpy(to->Data, from->Data, to->Length); + } + + return(to); +} + +SECStatus +SECITEM_CopyItem(PRArenaPool *arena, SecAsn1Item *to, const SecAsn1Item *from) +{ + // to->type = from->type; + if (from->Data && from->Length) { + if ( arena ) { + to->Data = (unsigned char*) PORT_ArenaAlloc(arena, from->Length); + } else { + to->Data = (unsigned char*) PORT_Alloc(from->Length); + } + + if (!to->Data) { + return SECFailure; + } + PORT_Memcpy(to->Data, from->Data, from->Length); + to->Length = from->Length; + } else { + to->Data = 0; + to->Length = 0; + } + return SECSuccess; +} + +void +SECITEM_FreeItem(SecAsn1Item *zap, Boolean freeit) +{ + if (zap) { + PORT_Free(zap->Data); + zap->Data = 0; + zap->Length = 0; + if (freeit) { + PORT_Free(zap); + } + } +} + +void +SECITEM_ZfreeItem(SecAsn1Item *zap, Boolean freeit) +{ + if (zap) { + PORT_ZFree(zap->Data, zap->Length); + zap->Data = 0; + zap->Length = 0; + if (freeit) { + PORT_ZFree(zap, sizeof(SecAsn1Item)); + } + } +} + + +/* these reroutines were taken from pkix oid.c, which is supposed to + * replace this file some day */ +/* + * This is the hash function. We simply XOR the encoded form with + * itself in sizeof(PLHashNumber)-byte chunks. Improving this + * routine is left as an excercise for the more mathematically + * inclined student. + */ +PLHashNumber PR_CALLBACK +SECITEM_Hash ( const void *key) +{ + const SecAsn1Item *item = (const SecAsn1Item *)key; + PLHashNumber rv = 0; + + PRUint8 *data = (PRUint8 *)item->Data; + PRUint8 *rvc = (PRUint8 *)&rv; + + size_t i; + + for( i = 0; i < item->Length; i++ ) { + rvc[ i % sizeof(rv) ] ^= *data; + data++; + } + + return rv; +} + +/* + * This is the key-compare function. It simply does a lexical + * comparison on the item data. This does not result in + * quite the same ordering as the "sequence of numbers" order, + * but heck it's only used internally by the hash table anyway. + */ +PRIntn PR_CALLBACK +SECITEM_HashCompare ( const void *k1, const void *k2) +{ + const SecAsn1Item *i1 = (const SecAsn1Item *)k1; + const SecAsn1Item *i2 = (const SecAsn1Item *)k2; + + return SECITEM_ItemsAreEqual(i1,i2); +} diff --git a/libsecurity_smime/lib/SecAsn1Item.h b/libsecurity_smime/lib/SecAsn1Item.h new file mode 100644 index 00000000..69b3aeb3 --- /dev/null +++ b/libsecurity_smime/lib/SecAsn1Item.h @@ -0,0 +1,117 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#ifndef _SECITEM_H_ +#define _SECITEM_H_ +/* + * SecAsn1Item.h - public data structures and prototypes for handling + * SecAsn1Items + */ + +#include +#include +#include "plhash.h" + +SEC_BEGIN_PROTOS + +/* +** Allocate an item. If "arena" is not NULL, then allocate from there, +** otherwise allocate from the heap. If "item" is not NULL, allocate +** only the data for the item, not the item itself. The item structure +** is allocated zero-filled; the data buffer is not zeroed. +** +** The resulting item is returned; NULL if any error occurs. +** +** XXX This probably should take a SecAsn1ItemType, but since that is mostly +** unused and our improved APIs (aka Stan) are looming, I left it out. +*/ +extern SecAsn1Item *SECITEM_AllocItem(PRArenaPool *arena, SecAsn1Item *item, + size_t len); + +/* +** Reallocate the data for the specified "item". If "arena" is not NULL, +** then reallocate from there, otherwise reallocate from the heap. +** In the case where oldlen is 0, the data is allocated (not reallocated). +** In any case, "item" is expected to be a valid SecAsn1Item pointer; +** SECFailure is returned if it is not. If the allocation succeeds, +** SECSuccess is returned. +*/ +extern SECStatus SECITEM_ReallocItem(PRArenaPool *arena, SecAsn1Item *item, + size_t oldlen, size_t newlen); + +/* +** Compare two items returning the difference between them. +*/ +extern SECComparison SECITEM_CompareItem(const SecAsn1Item *a, const SecAsn1Item *b); + +/* +** Compare two items -- if they are the same, return true; otherwise false. +*/ +extern Boolean SECITEM_ItemsAreEqual(const SecAsn1Item *a, const SecAsn1Item *b); + +/* +** Copy "from" to "to" +*/ +extern SECStatus SECITEM_CopyItem(PRArenaPool *arena, SecAsn1Item *to, + const SecAsn1Item *from); + +/* +** Allocate an item and copy "from" into it. +*/ +extern SecAsn1Item *SECITEM_DupItem(const SecAsn1Item *from); + +/* + ** Allocate an item and copy "from" into it. The item itself and the + ** data it points to are both allocated from the arena. If arena is + ** NULL, this function is equivalent to SECITEM_DupItem. + */ +extern SecAsn1Item *SECITEM_ArenaDupItem(PRArenaPool *arena, const SecAsn1Item *from); + +/* +** Free "zap". If freeit is PR_TRUE then "zap" itself is freed. +*/ +extern void SECITEM_FreeItem(SecAsn1Item *zap, Boolean freeit); + +/* +** Zero and then free "zap". If freeit is PR_TRUE then "zap" itself is freed. +*/ +extern void SECITEM_ZfreeItem(SecAsn1Item *zap, Boolean freeit); + +PLHashNumber PR_CALLBACK SECITEM_Hash ( const void *key); + +PRIntn PR_CALLBACK SECITEM_HashCompare ( const void *k1, const void *k2); + + +SEC_END_PROTOS + +#endif /* _SECITEM_H_ */ diff --git a/libsecurity_smime/lib/SecCmsBase.h b/libsecurity_smime/lib/SecCmsBase.h index eed12460..0381c229 100644 --- a/libsecurity_smime/lib/SecCmsBase.h +++ b/libsecurity_smime/lib/SecCmsBase.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2008,2010-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,7 +23,7 @@ /*! @header SecCmsBase.h - @copyright 2004 Apple Computer, Inc. All Rights Reserved. + @Copyright (c) 2004,2008,2010-2011 Apple Inc. All Rights Reserved. @availability 10.4 and later @abstract Interfaces of the CMS implementation. @@ -35,9 +35,12 @@ #ifndef _SECURITY_SECCMSBASE_H_ #define _SECURITY_SECCMSBASE_H_ 1 -#include /* size_t */ #include -#include +#include + +#if !USE_CDSA_CRYPTO +typedef CFTypeRef SecKeychainRef; +#endif #if defined(__cplusplus) extern "C" { @@ -53,13 +56,13 @@ typedef struct SECOidDataStr SECOidData; @typedef @discussion XXX We might want to get rid of this alltogether. */ -typedef CSSM_X509_ALGORITHM_IDENTIFIER SECAlgorithmID; +typedef SecAsn1AlgId SECAlgorithmID; /*! @typedef @discussion XXX This should probably move to SecKey.h */ -typedef SecKeyRef SecSymmetricKeyRef; +typedef void * SecSymmetricKeyRef; /*! @typedef @@ -78,11 +81,6 @@ typedef SecKeyRef SecPrivateKeyRef; */ typedef void(*PK11PasswordFunc)(void); -/*! - @typedef - */ -typedef struct SecArenaPoolStr *SecArenaPoolRef; - /*! @typedef */ @@ -170,10 +168,7 @@ typedef enum { SecCmsVSSignatureAlgorithmUnknown = 6, SecCmsVSSignatureAlgorithmUnsupported = 7, SecCmsVSMalformedSignature = 8, - SecCmsVSProcessingError = 9, - SecCmsVSTimestampMissing = 10, /* A timestamp was expected but was not found. */ - SecCmsVSTimestampInvalid = 11, /* The timestamp was not valid. */ - SecCmsVSTimestampNotTrusted = 12, /* The timestamp signing chain was not trusted. */ + SecCmsVSProcessingError = 9 } SecCmsVerificationStatus; /*! @@ -461,48 +456,11 @@ typedef enum { SEC_OID_AES_192_KEY_WRAP = 198, SEC_OID_AES_256_KEY_WRAP = 199, - /* 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, - - /* 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, - - /* 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_SHA224 = 200, SEC_OID_TOTAL } SECOidTag; -/*! - @function - @abstract Create a new SecArenaPool object. - @param chunksize Size of the chunks the pool will use to allocate its underlying storage. - @param outArena pointer to a SecArenaPoolRef to be created. - @result On success return 0 and outArena will contain a newly created SecArenaPoolRef. - @availability 10.4 and later - @updated 2004-04-23 - */ -OSStatus SecArenaPoolCreate(size_t chunksize, SecArenaPoolRef *outArena); - -/*! - @function - @abstract Free a SecArenaPool object and everything in it. - @param arena The SecArenaPool object to free. - @param zero If this is true the arena's memory will be zero filled before it is freed. - @result arena will no longer be valid and the memory used by it is returned to the malloc heap. - @availability 10.4 and later - @updated 2004-04-23 - */ -void SecArenaPoolFree(SecArenaPoolRef arena, Boolean zero); - #if defined(__cplusplus) } diff --git a/libsecurity_smime/lib/SecCmsContentInfo.h b/libsecurity_smime/lib/SecCmsContentInfo.h index 6987124e..7f5ec6d9 100644 --- a/libsecurity_smime/lib/SecCmsContentInfo.h +++ b/libsecurity_smime/lib/SecCmsContentInfo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2008,2010 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,7 +23,7 @@ /*! @header SecCmsContentInfo.h - @copyright 2004 Apple Computer, Inc. All Rights Reserved. + @Copyright (c) 2004,2008,2010 Apple Inc. All Rights Reserved. @availability 10.4 and later @abstract Interfaces of the CMS implementation. @@ -36,6 +36,7 @@ #define _SECURITY_SECCMSCONTENTINFO_H_ 1 #include +#include #if defined(__cplusplus) @@ -68,7 +69,7 @@ SecCmsContentInfoGetContent(SecCmsContentInfoRef cinfo); @abstract Get pointer to innermost content @discussion This is typically only called by SecCmsMessageGetContent(). */ -extern CSSM_DATA_PTR +extern const SecAsn1Item * SecCmsContentInfoGetInnerContent(SecCmsContentInfoRef cinfo); /*! @@ -83,7 +84,7 @@ SecCmsContentInfoGetContentTypeTag(SecCmsContentInfoRef cinfo); @abstract Find out and return the inner content type. @discussion Caches pointer to lookup result for future reference. */ -extern CSSM_OID * +extern SecAsn1Oid * SecCmsContentInfoGetContentTypeOID(SecCmsContentInfoRef cinfo); /*! @@ -106,16 +107,15 @@ SecCmsContentInfoGetContentEncAlg(SecCmsContentInfoRef cinfo); /*! @function @abstract Set a ContentInfos content to a Data - @param cmsg A Message object to which the cinfo object belongs. @param cinfo A ContentInfo object of which we want set the content. - @param data A pointer to a CSSM_DATA object or NULL if data will be provided during SecCmsEncoderUpdate calls. + @param data A CFDataRef or NULL if data will be provided during SecCmsEncoderUpdate calls. @param detached True if the content is to be deattched from the CMS message rather than included within it. @result A result code. See "SecCmsBase.h" for possible results. - @discussion This function requires a ContentInfo object which can be made by creating a SecCmsMessage object. If the call succeeds the passed in data will be owned by the reciever. The data->Data must have been allocated using the cmsg's SecArenaPool if it is present. + @discussion This function requires a ContentInfo object which can be made by creating a SecCmsMessage object. @availability 10.4 and later */ extern OSStatus -SecCmsContentInfoSetContentData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, CSSM_DATA_PTR data, Boolean detached); +SecCmsContentInfoSetContentData(SecCmsContentInfoRef cinfo, CFDataRef data, Boolean detached); /*! @function @@ -128,7 +128,7 @@ SecCmsContentInfoSetContentData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinf @availability 10.4 and later */ extern OSStatus -SecCmsContentInfoSetContentSignedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsSignedDataRef sigd); +SecCmsContentInfoSetContentSignedData(SecCmsContentInfoRef cinfo, SecCmsSignedDataRef sigd); /*! @function @@ -141,7 +141,7 @@ SecCmsContentInfoSetContentSignedData(SecCmsMessageRef cmsg, SecCmsContentInfoRe @availability 10.4 and later */ extern OSStatus -SecCmsContentInfoSetContentEnvelopedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsEnvelopedDataRef envd); +SecCmsContentInfoSetContentEnvelopedData(SecCmsContentInfoRef cinfo, SecCmsEnvelopedDataRef envd); /*! @function @@ -154,7 +154,7 @@ SecCmsContentInfoSetContentEnvelopedData(SecCmsMessageRef cmsg, SecCmsContentInf @availability 10.4 and later */ extern OSStatus -SecCmsContentInfoSetContentDigestedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsDigestedDataRef digd); +SecCmsContentInfoSetContentDigestedData(SecCmsContentInfoRef cinfo, SecCmsDigestedDataRef digd); /*! @function @@ -167,23 +167,20 @@ SecCmsContentInfoSetContentDigestedData(SecCmsMessageRef cmsg, SecCmsContentInfo @availability 10.4 and later */ extern OSStatus -SecCmsContentInfoSetContentEncryptedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsEncryptedDataRef encd); - -OSStatus -SecCmsContentInfoSetContentOther(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, CSSM_DATA_PTR data, Boolean detached, const CSSM_OID *eContentType); +SecCmsContentInfoSetContentEncryptedData(SecCmsContentInfoRef cinfo, SecCmsEncryptedDataRef encd); /*! @function */ extern OSStatus -SecCmsContentInfoSetContentEncAlg(SecArenaPoolRef pool, SecCmsContentInfoRef cinfo, - SECOidTag bulkalgtag, CSSM_DATA_PTR parameters, int keysize); +SecCmsContentInfoSetContentEncAlg(SecCmsContentInfoRef cinfo, + SECOidTag bulkalgtag, const SecAsn1Item *parameters, int keysize); /*! @function */ extern OSStatus -SecCmsContentInfoSetContentEncAlgID(SecArenaPoolRef pool, SecCmsContentInfoRef cinfo, +SecCmsContentInfoSetContentEncAlgID(SecCmsContentInfoRef cinfo, SECAlgorithmID *algid, int keysize); /*! diff --git a/libsecurity_smime/lib/SecCmsDecoder.h b/libsecurity_smime/lib/SecCmsDecoder.h index cb3d877a..3543346d 100644 --- a/libsecurity_smime/lib/SecCmsDecoder.h +++ b/libsecurity_smime/lib/SecCmsDecoder.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2008,2010,2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,7 +23,7 @@ /*! @header SecCmsDecoder.h - @copyright 2004 Apple Computer, Inc. All Rights Reserved. + @Copyright (c) 2004,2008,2010,2013 Apple Inc. All Rights Reserved. @availability 10.4 and later @abstract Interfaces of the CMS implementation. @@ -47,8 +47,6 @@ extern "C" { /*! @function @abstract Set up decoding of a BER-encoded CMS message. - @param arena An ArenaPool object to use for the resulting message, or NULL if new ArenaPool - should be created. @param cb callback function for delivery of inner content inner content will be stored in the message if cb is NULL. @param cb_arg first argument passed to cb when it is called. @@ -61,13 +59,12 @@ extern "C" { when it is called. @param outDecoder On success will contain a pointer to a newly created SecCmsDecoder. @result A result code. See "SecCmsBase.h" for possible results. - @discussion Create a SecCmsDecoder(). If this function returns noErr, the caller must dispose of the returned outDecoder by calling SecCmsDecoderDestroy() or SecCmsDecoderFinish(). + @discussion Create a SecCmsDecoder(). If this function returns errSecSuccess, the caller must dispose of the returned outDecoder by calling SecCmsDecoderDestroy() or SecCmsDecoderFinish(). @availability 10.4 and later @updated 2004-04-05 */ extern OSStatus -SecCmsDecoderCreate(SecArenaPoolRef arena, - SecCmsContentCallback cb, void *cb_arg, +SecCmsDecoderCreate(SecCmsContentCallback cb, void *cb_arg, PK11PasswordFunc pwfn, void *pwfn_arg, SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg, @@ -113,7 +110,7 @@ SecCmsDecoderFinish(SecCmsDecoderRef decoder, SecCmsMessageRef *outMessage); @abstract Decode a CMS message from BER encoded data. @discussion This function basically does the same as calling SecCmsDecoderStart(), SecCmsDecoderUpdate() and SecCmsDecoderFinish(). - @param DERmessage Pointer to a CSSM_DATA containing the BER encoded cms + @param DERmessage Pointer to a SecAsn1Item containing the BER encoded cms message to decode. @param cb callback function for delivery of inner content inner content will be stored in the message if cb is NULL. @@ -129,7 +126,7 @@ SecCmsDecoderFinish(SecCmsDecoderRef decoder, SecCmsMessageRef *outMessage); @availability 10.4 and later */ extern OSStatus -SecCmsMessageDecode(const CSSM_DATA *encodedMessage, +SecCmsMessageDecode(const SecAsn1Item *encodedMessage, SecCmsContentCallback cb, void *cb_arg, PK11PasswordFunc pwfn, void *pwfn_arg, SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg, diff --git a/libsecurity_smime/lib/SecCmsDigestContext.h b/libsecurity_smime/lib/SecCmsDigestContext.h index 3e8e7986..9b8520b7 100644 --- a/libsecurity_smime/lib/SecCmsDigestContext.h +++ b/libsecurity_smime/lib/SecCmsDigestContext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2008,2010-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,7 +23,7 @@ /*! @header SecCmsDigestContext.h - @copyright 2004 Apple Computer, Inc. All Rights Reserved. + @Copyright (c) 2004,2008,2010-2011 Apple Inc. All Rights Reserved. @availability 10.4 and later @abstract Interfaces of the CMS implementation. @@ -57,7 +57,7 @@ SecCmsDigestContextUpdate(SecCmsDigestContextRef cmsdigcx, const unsigned char * /*! @function - @abstract Cancel digesting operation. + @abstract Cancel digesting operation in progress and destroy it. @discussion Cancel a DigestContext created with @link SecCmsDigestContextStartMultiple SecCmsDigestContextStartMultiple function@/link. */ extern void @@ -65,11 +65,12 @@ SecCmsDigestContextCancel(SecCmsDigestContextRef cmsdigcx); /*! @function - @abstract Finish the digests and put them into an array of CSSM_DATAs (allocated on arena) + @abstract Destroy a SecCmsDigestContextRef. + @discussion Cancel a DigestContext created with @link SecCmsDigestContextStartMultiple SecCmsDigestContextStartMultiple function@/link after it has been used in a @link SecCmsSignedDataSetDigestContext SecCmsSignedDataSetDigestContext function@/link. */ -extern OSStatus -SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, SecArenaPoolRef arena, - CSSM_DATA_PTR **digestsp); +extern void +SecCmsDigestContextDestroy(SecCmsDigestContextRef cmsdigcx); + #if defined(__cplusplus) } diff --git a/libsecurity_smime/lib/SecCmsDigestedData.h b/libsecurity_smime/lib/SecCmsDigestedData.h index 96d59dca..d35d68cb 100644 --- a/libsecurity_smime/lib/SecCmsDigestedData.h +++ b/libsecurity_smime/lib/SecCmsDigestedData.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2008,2010 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,7 +23,7 @@ /*! @header SecCmsDigestedData.h - @copyright 2004 Apple Computer, Inc. All Rights Reserved. + @Copyright (c) 2004,2008,2010 Apple Inc. All Rights Reserved. @availability 10.4 and later @abstract Interfaces of the CMS implementation. diff --git a/libsecurity_smime/lib/SecCmsEncoder.h b/libsecurity_smime/lib/SecCmsEncoder.h index c13d32e5..ae45ad9a 100644 --- a/libsecurity_smime/lib/SecCmsEncoder.h +++ b/libsecurity_smime/lib/SecCmsEncoder.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2008,2010 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,7 +23,7 @@ /*! @header SecCmsEncoder.h - @copyright 2004 Apple Computer, Inc. All Rights Reserved. + @Copyright (c) 2004,2008,2010 Apple Inc. All Rights Reserved. @availability 10.4 and later @abstract CMS message encoding @@ -37,6 +37,7 @@ #define _SECURITY_SECCMSENCODER_H_ 1 #include +#include #if defined(__cplusplus) @@ -48,12 +49,12 @@ extern "C" { /*! @function @abstract Set up encoding of a CMS message. + @param cmsg The SecCmsMessageRef to be encoded. @param outputfn callback function for delivery of BER-encoded output will not be called if NULL. @param outputarg first argument passed to outputfn when it is called. - @param dest If non-NULL, pointer to a CSSM_DATA that will hold the - BER-encoded output. - @param destpoolp Pool to allocate BER-encoded output in. + @param dest If non-NULL, a CFMutableDataRef to which the + BER-encoded output will be appended. @param pwfn callback function for getting token password for enveloped data content with a password recipient. @param pwfn_arg first argument passed to pwfn when it is called. @@ -71,10 +72,9 @@ extern "C" { extern OSStatus SecCmsEncoderCreate(SecCmsMessageRef cmsg, SecCmsContentCallback outputfn, void *outputarg, - CSSM_DATA_PTR dest, SecArenaPoolRef destpoolp, + CFMutableDataRef outBer, PK11PasswordFunc pwfn, void *pwfn_arg, SecCmsGetDecryptKeyCallback encrypt_key_cb, void *encrypt_key_cb_arg, - SECAlgorithmID **detached_digestalgs, CSSM_DATA_PTR *detached_digests, SecCmsEncoderRef *outEncoder); /*! @@ -116,11 +116,16 @@ SecCmsEncoderFinish(SecCmsEncoderRef encoder); /*! @function @abstract BER Encode a CMS message. + @param cmsg The SecCmsMessageRef to be encoded. + @param input The inner content of the message. + @param outBer A CFMutableDataRef to which the + BER-encoded output will be appended. @discussion BER Encode a CMS message, with input being the plaintext message and outBer being the output, stored in arena's pool. */ extern OSStatus -SecCmsMessageEncode(SecCmsMessageRef cmsg, const CSSM_DATA *input, SecArenaPoolRef arena, - CSSM_DATA_PTR outBer); +SecCmsMessageEncode(SecCmsMessageRef cmsg, const SecAsn1Item *input, + CFMutableDataRef outBer); + #if defined(__cplusplus) } diff --git a/libsecurity_smime/lib/SecCmsEncryptedData.h b/libsecurity_smime/lib/SecCmsEncryptedData.h index 27b2b0c4..373907ba 100644 --- a/libsecurity_smime/lib/SecCmsEncryptedData.h +++ b/libsecurity_smime/lib/SecCmsEncryptedData.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2008,2010 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,7 +23,7 @@ /*! @header SecCmsEnvelopedData.h - @copyright 2004 Apple Computer, Inc. All Rights Reserved. + @Copyright (c) 2004,2008,2010 Apple Inc. All Rights Reserved. @availability 10.4 and later @abstract Interfaces of the CMS implementation. diff --git a/libsecurity_smime/lib/SecCmsEnvelopedData.h b/libsecurity_smime/lib/SecCmsEnvelopedData.h index 69aebdbf..abc813c1 100644 --- a/libsecurity_smime/lib/SecCmsEnvelopedData.h +++ b/libsecurity_smime/lib/SecCmsEnvelopedData.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2008,2010 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,7 +23,7 @@ /*! @header SecCmsEnvelopedData.h - @copyright 2004 Apple Computer, Inc. All Rights Reserved. + @Copyright (c) 2004,2008,2010 Apple Inc. All Rights Reserved. @availability 10.4 and later @abstract Interfaces of the CMS implementation. @@ -64,15 +64,6 @@ SecCmsEnvelopedDataDestroy(SecCmsEnvelopedDataRef edp); extern SecCmsContentInfoRef SecCmsEnvelopedDataGetContentInfo(SecCmsEnvelopedDataRef envd); -/*! - @function - @abstract Add a recipientinfo to the enveloped data msg. - @discussion Rip must be created on the same pool as edp - this is not enforced, though. - */ -extern OSStatus -SecCmsEnvelopedDataAddRecipient(SecCmsEnvelopedDataRef edp, SecCmsRecipientInfoRef rip); - - #if defined(__cplusplus) } #endif diff --git a/libsecurity_smime/lib/SecCmsMessage.h b/libsecurity_smime/lib/SecCmsMessage.h index 281146ab..ebdb7579 100644 --- a/libsecurity_smime/lib/SecCmsMessage.h +++ b/libsecurity_smime/lib/SecCmsMessage.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2008,2010 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,7 +23,7 @@ /*! @header SecCmsMessage.h - @copyright 2004 Apple Computer, Inc. All Rights Reserved. + @Copyright (c) 2004,2008,2010 Apple Inc. All Rights Reserved. @availability 10.4 and later @abstract CMS message object interfaces @@ -57,7 +57,7 @@ extern "C" { wrong. */ extern SecCmsMessageRef -SecCmsMessageCreate(SecArenaPoolRef poolp); +SecCmsMessageCreate(void); /*! @function @@ -78,13 +78,6 @@ SecCmsMessageDestroy(SecCmsMessageRef cmsg); extern SecCmsMessageRef SecCmsMessageCopy(SecCmsMessageRef cmsg); -/*! - @function - @abstract Return a pointer to the message's arena pool. - */ -extern SecArenaPoolRef -SecCmsMessageGetArena(SecCmsMessageRef cmsg); - /*! @function @abstract Return a pointer to the top level contentInfo. @@ -98,7 +91,7 @@ SecCmsMessageGetContentInfo(SecCmsMessageRef cmsg); @discussion In the case of those types which are encrypted, this returns the *plain* content. In case of nested contentInfos, this descends and retrieves the innermost content. */ -extern CSSM_DATA_PTR +extern const SecAsn1Item * SecCmsMessageGetContent(SecCmsMessageRef cmsg); /*! @@ -153,8 +146,6 @@ SecCmsMessageIsSigned(SecCmsMessageRef cmsg); extern Boolean SecCmsMessageIsContentEmpty(SecCmsMessageRef cmsg, unsigned int minLen); -extern Boolean -SecCmsMessageContainsTSTInfo(SecCmsMessageRef cmsg); #if defined(__cplusplus) } diff --git a/libsecurity_smime/lib/SecCmsRecipientInfo.h b/libsecurity_smime/lib/SecCmsRecipientInfo.h index d0216d7b..f8ae7415 100644 --- a/libsecurity_smime/lib/SecCmsRecipientInfo.h +++ b/libsecurity_smime/lib/SecCmsRecipientInfo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2008,2010 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,7 +23,7 @@ /*! @header SecCmsRecipientInfo.h - @copyright 2004 Apple Computer, Inc. All Rights Reserved. + @Copyright (c) 2004,2008,2010 Apple Inc. All Rights Reserved. @availability 10.4 and later @abstract Interfaces of the CMS implementation. @@ -50,28 +50,22 @@ extern "C" { the certificate is supposed to have been verified by the caller */ extern SecCmsRecipientInfoRef -SecCmsRecipientInfoCreate(SecCmsMessageRef cmsg, SecCertificateRef cert); +SecCmsRecipientInfoCreate(SecCmsEnvelopedDataRef envd, SecCertificateRef cert); /*! @function */ extern SecCmsRecipientInfoRef -SecCmsRecipientInfoCreateWithSubjKeyID(SecCmsMessageRef cmsg, - CSSM_DATA_PTR subjKeyID, - SecPublicKeyRef pubKey); +SecCmsRecipientInfoCreateWithSubjKeyID(SecCmsEnvelopedDataRef envd, + const SecAsn1Item *subjKeyID, + SecPublicKeyRef pubKey); /*! @function */ extern SecCmsRecipientInfoRef -SecCmsRecipientInfoCreateWithSubjKeyIDFromCert(SecCmsMessageRef cmsg, - SecCertificateRef cert); - -/*! - @function - */ -extern void -SecCmsRecipientInfoDestroy(SecCmsRecipientInfoRef ri); +SecCmsRecipientInfoCreateWithSubjKeyIDFromCert(SecCmsEnvelopedDataRef envd, + SecCertificateRef cert); #if defined(__cplusplus) diff --git a/libsecurity_smime/lib/SecCmsSignedData.h b/libsecurity_smime/lib/SecCmsSignedData.h index 0f0e46cd..08fc62b5 100644 --- a/libsecurity_smime/lib/SecCmsSignedData.h +++ b/libsecurity_smime/lib/SecCmsSignedData.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2008,2010 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,7 +23,7 @@ /*! @header SecCmsSignedData.h - @copyright 2004 Apple Computer, Inc. All Rights Reserved. + @Copyright (c) 2004,2008,2010 Apple Inc. All Rights Reserved. @availability 10.4 and later @abstract Interfaces of the CMS implementation. @@ -38,7 +38,6 @@ #include #include - #if defined(__cplusplus) extern "C" { #endif @@ -160,24 +159,9 @@ SecCmsSignedDataContainsCertsOrCrls(SecCmsSignedDataRef sigd); @function @abstract Retrieve the SignedData's certificate list. */ -extern CSSM_DATA_PTR * +extern SecAsn1Item * * SecCmsSignedDataGetCertificateList(SecCmsSignedDataRef sigd); -/*! - @function - */ -extern OSStatus -SecCmsSignedDataAddSignerInfo(SecCmsSignedDataRef sigd, - SecCmsSignerInfoRef signerinfo); - -/*! - @function - */ -extern OSStatus -SecCmsSignedDataSetDigests(SecCmsSignedDataRef sigd, - SECAlgorithmID **digestalgs, - CSSM_DATA_PTR *digests); - /*! @function @abstract Create a certs-only SignedData. @@ -189,6 +173,17 @@ SecCmsSignedDataSetDigests(SecCmsSignedDataRef sigd, extern SecCmsSignedDataRef SecCmsSignedDataCreateCertsOnly(SecCmsMessageRef cmsg, SecCertificateRef cert, Boolean include_chain); +/*! + @function + @abstract Finalize the digests in digestContext and apply them to sigd. + @param sigd A SecCmsSignedDataRef for which the digests have been calculated + @param digestContext A digestContext created with SecCmsDigestContextStartMultiple. + @result The digest will have been applied to sigd. After this call completes sigd is ready to accept + SecCmsSignedDataVerifySignerInfo() calls. The caller should still destroy digestContext with a SecCmsDigestContextDestroy() call. + + */ +extern OSStatus SecCmsSignedDataSetDigestContext(SecCmsSignedDataRef sigd, + SecCmsDigestContextRef digestContext); #if defined(__cplusplus) } diff --git a/libsecurity_smime/lib/SecCmsSignerInfo.h b/libsecurity_smime/lib/SecCmsSignerInfo.h index 26da7167..98b76f13 100644 --- a/libsecurity_smime/lib/SecCmsSignerInfo.h +++ b/libsecurity_smime/lib/SecCmsSignerInfo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2008,2010,2013 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,7 +23,7 @@ /*! @header SecCmsSignerInfo.h - @copyright 2004 Apple Computer, Inc. All Rights Reserved. + @Copyright (c) 2004,2008,2010,2013 Apple Inc. All Rights Reserved. @availability 10.4 and later @abstract Interfaces of the CMS implementation. @@ -48,20 +48,13 @@ extern "C" { @function */ extern SecCmsSignerInfoRef -SecCmsSignerInfoCreate(SecCmsMessageRef cmsg, SecIdentityRef identity, SECOidTag digestalgtag); +SecCmsSignerInfoCreate(SecCmsSignedDataRef sigd, SecIdentityRef identity, SECOidTag digestalgtag); /*! @function */ extern SecCmsSignerInfoRef -SecCmsSignerInfoCreateWithSubjKeyID(SecCmsMessageRef cmsg, CSSM_DATA_PTR subjKeyID, SecPublicKeyRef pubKey, SecPrivateKeyRef signingKey, SECOidTag digestalgtag); - -/*! - @function - @abstract Destroy a SignerInfo data structure. - */ -extern void -SecCmsSignerInfoDestroy(SecCmsSignerInfoRef si); +SecCmsSignerInfoCreateWithSubjKeyID(SecCmsSignedDataRef sigd, const SecAsn1Item *subjKeyID, SecPublicKeyRef pubKey, SecPrivateKeyRef signingKey, SECOidTag digestalgtag); /*! @function @@ -69,18 +62,6 @@ SecCmsSignerInfoDestroy(SecCmsSignerInfoRef si); extern SecCmsVerificationStatus SecCmsSignerInfoGetVerificationStatus(SecCmsSignerInfoRef signerinfo); -/*! - @function - */ -extern OSStatus -SecCmsSignerInfoVerifyUnAuthAttrs(SecCmsSignerInfoRef signerinfo); - -/*! - @function - */ -extern CSSM_DATA * -SecCmsSignerInfoGetEncDigest(SecCmsSignerInfoRef signerinfo); - /*! @function */ @@ -99,12 +80,6 @@ SecCmsSignerInfoGetDigestAlgTag(SecCmsSignerInfoRef signerinfo); extern CFArrayRef SecCmsSignerInfoGetCertList(SecCmsSignerInfoRef signerinfo); -/*! - @function - */ -extern CFArrayRef -SecCmsSignerInfoGetTimestampCertList(SecCmsSignerInfoRef signerinfo); - /*! @function @abstract Return the signing time, in UTCTime format, of a CMS signerInfo. @@ -115,16 +90,6 @@ SecCmsSignerInfoGetTimestampCertList(SecCmsSignerInfoRef signerinfo); extern OSStatus SecCmsSignerInfoGetSigningTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *stime); -/*! - @function - @abstract Return the timestamp time, in UTCTime format, of a CMS signerInfo. - @param sinfo SignerInfo data for this signer. - @discussion Returns a pointer to XXXX (what?) - @result A return value of NULL is an error. - */ -OSStatus -SecCmsSignerInfoGetTimestampTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *stime); - /*! @function @abstract Return the signing cert of a CMS signerInfo. @@ -140,7 +105,7 @@ SecCmsSignerInfoGetSigningCertificate(SecCmsSignerInfoRef signerinfo, SecKeychai @discussion Returns a CFStringRef containing the common name of the signer. @result A return value of NULL is an error. */ -extern CFStringRef +extern CF_RETURNS_RETAINED CFStringRef SecCmsSignerInfoGetSignerCommonName(SecCmsSignerInfoRef sinfo); /*! @@ -150,7 +115,7 @@ SecCmsSignerInfoGetSignerCommonName(SecCmsSignerInfoRef sinfo); @discussion Returns a CFStringRef containing the name of the signer. @result A return value of NULL is an error. */ -extern CFStringRef +extern CF_RETURNS_RETAINED CFStringRef SecCmsSignerInfoGetSignerEmailAddress(SecCmsSignerInfoRef sinfo); /*! @@ -192,13 +157,6 @@ SecCmsSignerInfoAddSMIMEEncKeyPrefs(SecCmsSignerInfoRef signerinfo, SecCertifica OSStatus SecCmsSignerInfoAddMSSMIMEEncKeyPrefs(SecCmsSignerInfoRef signerinfo, SecCertificateRef cert, SecKeychainRef keychainOrArray); -/*! - @function - @abstract Create a timestamp unsigned attribute with a TimeStampToken. - */ -OSStatus -SecCmsSignerInfoAddTimeStamp(SecCmsSignerInfoRef signerinfo, CSSM_DATA *tstoken); - /*! @function @abstract Countersign a signerinfo. @@ -231,14 +189,6 @@ SecCmsSignerInfoIncludeCerts(SecCmsSignerInfoRef signerinfo, SecCmsCertChainMode extern const char * SecCmsUtilVerificationStatusToString(SecCmsVerificationStatus vs); -/* - * Preference domain and key for the Microsoft ECDSA compatibility flag. - * Default if not present is TRUE, meaning we generate ECDSA-signed messages - * which are compatible with Microsoft Entourage. FALSE means we adhere to - * the spec (RFC 3278 section 2.1.1). - */ -#define kMSCompatibilityDomain "com.apple.security.smime" -#define kMSCompatibilityMode CFSTR("MSCompatibilityMode") #if defined(__cplusplus) } diff --git a/libsecurity_smime/lib/SecSMIME.h b/libsecurity_smime/lib/SecSMIME.h index 92aba648..7083c7cc 100644 --- a/libsecurity_smime/lib/SecSMIME.h +++ b/libsecurity_smime/lib/SecSMIME.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2008,2010 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,7 +23,7 @@ /*! @header SecSMIME.h - @copyright 2004 Apple Computer, Inc. All Rights Reserved. + @Copyright (c) 2004,2008,2010 Apple Inc. All Rights Reserved. @availability 10.4 and later @abstract S/MIME Specific routines. diff --git a/libsecurity_smime/lib/SecSMIMEPriv.h b/libsecurity_smime/lib/SecSMIMEPriv.h index c7b651a1..cc74760a 100644 --- a/libsecurity_smime/lib/SecSMIMEPriv.h +++ b/libsecurity_smime/lib/SecSMIMEPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004,2008,2010-2011 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,7 +23,7 @@ /*! @header SecSMIMEPriv.h - @copyright 2004 Apple Computer, Inc. All Rights Reserved. + @Copyright (c) 2004,2008,2010-2011 Apple Inc. All Rights Reserved. @availability 10.4 and later @abstract Private S/MIME Specific routines. @@ -36,6 +36,7 @@ #define _SECURITY_SECSMIMEPRIV_H_ 1 #include +#include #ifdef __cplusplus extern "C" { @@ -61,7 +62,9 @@ extern "C" { #define SMIME_RC2_CBC_128 (CIPHER_FAMILYID_SMIME | 0003) #define SMIME_DES_CBC_56 (CIPHER_FAMILYID_SMIME | 0011) #define SMIME_DES_EDE3_168 (CIPHER_FAMILYID_SMIME | 0012) -#define SMIME_AES_CBC_128 (CIPHER_FAMILYID_SMIME | 0013) +#define SMIME_AES_CBC_128 (CIPHER_FAMILYID_SMIME | 0013) +#define SMIME_AES_CBC_192 (CIPHER_FAMILYID_SMIME | 0014) +#define SMIME_AES_CBC_256 (CIPHER_FAMILYID_SMIME | 0015) #define SMIME_RC5PAD_64_16_40 (CIPHER_FAMILYID_SMIME | 0021) #define SMIME_RC5PAD_64_16_64 (CIPHER_FAMILYID_SMIME | 0022) #define SMIME_RC5PAD_64_16_128 (CIPHER_FAMILYID_SMIME | 0023) @@ -95,7 +98,7 @@ extern "C" { * SEC_ERROR_XXX (function is being called more times than there * are known/expected ciphers) */ -extern OSStatus SecSMIMEEnableCipher(uint32 which, Boolean on); +extern OSStatus SecSMIMEEnableCipher(unsigned long which, Boolean on); /* * Initialize the local recording of the S/MIME policy. @@ -110,7 +113,7 @@ extern OSStatus SecSMIMEEnableCipher(uint32 which, Boolean on); * - If "on" is non-zero then the named cipher is enabled, otherwise * it is disabled. */ -extern OSStatus SecSMIMEAllowCipher(uint32 which, Boolean on); +extern OSStatus SecSMIMEAllowCipher(unsigned long which, Boolean on); /* * Does the current policy allow S/MIME decryption of this particular @@ -144,23 +147,23 @@ extern Boolean SecSMIMEEncryptionPossible(void); * scans the list of allowed and enabled ciphers and construct a PKCS9-compliant * S/MIME capabilities attribute value. */ -extern OSStatus SecSMIMECreateSMIMECapabilities(SecArenaPoolRef pool, CSSM_DATA_PTR dest, Boolean includeFortezzaCiphers); +extern OSStatus SecSMIMECreateSMIMECapabilities(PLArenaPool *poolp, SecAsn1Item * dest, Boolean includeFortezzaCiphers); /* * SecSMIMECreateSMIMEEncKeyPrefs - create S/MIME encryption key preferences attr value */ -extern OSStatus SecSMIMECreateSMIMEEncKeyPrefs(SecArenaPoolRef pool, CSSM_DATA_PTR dest, SecCertificateRef cert); +extern OSStatus SecSMIMECreateSMIMEEncKeyPrefs(PLArenaPool *poolp, SecAsn1Item * dest, SecCertificateRef cert); /* * SecSMIMECreateMSSMIMEEncKeyPrefs - create S/MIME encryption key preferences attr value using MS oid */ -extern OSStatus SecSMIMECreateMSSMIMEEncKeyPrefs(SecArenaPoolRef pool, CSSM_DATA_PTR dest, SecCertificateRef cert); +extern OSStatus SecSMIMECreateMSSMIMEEncKeyPrefs(PLArenaPool *poolp, SecAsn1Item * dest, SecCertificateRef cert); /* * SecSMIMEGetCertFromEncryptionKeyPreference - find cert marked by EncryptionKeyPreference * attribute */ -extern SecCertificateRef SecSMIMEGetCertFromEncryptionKeyPreference(SecKeychainRef keychainOrArray, CSSM_DATA_PTR DERekp); +extern SecCertificateRef SecSMIMEGetCertFromEncryptionKeyPreference(SecKeychainRef keychainOrArray, SecAsn1Item * DERekp); #ifdef __cplusplus diff --git a/libsecurity_smime/lib/cert.c b/libsecurity_smime/lib/cert.c index 28ea8fd8..8c5dcf56 100644 --- a/libsecurity_smime/lib/cert.c +++ b/libsecurity_smime/lib/cert.c @@ -9,13 +9,10 @@ #include "cert.h" #include "cmstpriv.h" -#include "cmslocal.h" -#include "secitem.h" #include #include #include #include -#include #include #include #include @@ -26,14 +23,7 @@ #include /* for errKCDuplicateItem */ -#include - -#define CERT_DEBUG 0 -#if CERT_DEBUG -#define dprintf(args...) printf(args) -#else -#define dprintf(args...) -#endif +#include /* @@@ Remove this once it's back in the appropriate header. */ static const uint8 X509V1IssuerNameStd[] = {INTEL_X509V3_CERT_R08, 23}; @@ -128,7 +118,7 @@ SecCertificateRef CERT_FindCertByNicknameOrEmailAddr(SecKeychainRef keychainOrAr { SecCertificateRef certificate; OSStatus status=SecCertificateFindByEmail(keychainOrArray,name,&certificate); - return status==noErr?certificate:NULL; + return status==errSecSuccess?certificate:NULL; } SecPublicKeyRef SECKEY_CopyPublicKey(SecPublicKeyRef pubKey) @@ -194,7 +184,7 @@ SecCertificateRef CERT_FindUserCertByUsage(SecKeychainRef keychainOrArray, attrs[1].data = nickname; #else attrs[1].tag = kSecSerialNumberItemAttr; - attrs[1].length = (UInt32)strlen(serialNumber)+1; + attrs[1].length = strlen(serialNumber)+1; attrs[1].data = (uint8 *)serialNumber; #endif SecKeychainAttributeList attrList = { 0, attrs }; @@ -202,12 +192,12 @@ SecCertificateRef CERT_FindUserCertByUsage(SecKeychainRef keychainOrArray, status = SecKeychainSearchCreateFromAttributes(keychainOrArray,itemClass,&attrList,&searchRef); if (status) { - printf("CERT_FindUserCertByUsage: SecKeychainSearchCreateFromAttributes:%d",(int)status); + printf("CERT_FindUserCertByUsage: SecKeychainSearchCreateFromAttributes:%ld",status); return NULL; } status = SecKeychainSearchCopyNext(searchRef,&itemRef); if (status) - printf("CERT_FindUserCertByUsage: SecKeychainSearchCopyNext:%d",(int)status); + printf("CERT_FindUserCertByUsage: SecKeychainSearchCopyNext:%ld",status); CFRelease(searchRef); return (SecCertificateRef)itemRef; } @@ -217,7 +207,7 @@ startNewClass(X509Certificate) CertType, kSecCertTypeItemAttr, "CertType", 0, NULL, UINT32) CertEncoding, kSecCertEncodingItemAttr, "CertEncoding", 0, NULL, UINT32) PrintName, kSecLabelItemAttr, "PrintName", 0, NULL, BLOB) -Alias, kSecAlias, "Alias", 0, NULL, BLOB) +Alias, kSecAliasItemAttr, "Alias", 0, NULL, BLOB) Subject, kSecSubjectItemAttr, "Subject", 0, NULL, BLOB) Issuer, kSecIssuerItemAttr, "Issuer", 0, NULL, BLOB) SerialNumber, kSecSerialNumberItemAttr, "SerialNumber", 0, NULL, BLOB) @@ -234,7 +224,6 @@ CFArrayRef CERT_CertChainFromCert(SecCertificateRef cert, SECCertUsage usage, Bo SecTrustRef trust = NULL; CFArrayRef certChain = NULL; CSSM_TP_APPLE_EVIDENCE_INFO *statusChain; - CFDataRef actionData = NULL; OSStatus status = 0; if (!cert) @@ -252,22 +241,6 @@ CFArrayRef CERT_CertChainFromCert(SecCertificateRef cert, SECCertUsage usage, Bo if (status) goto loser; - /* Tell SecTrust that we don't care if any certs in the chain have expired, - nor do we want to stop when encountering a cert with a trust setting; - we always want to build the full chain. - */ - CSSM_APPLE_TP_ACTION_DATA localActionData = { - CSSM_APPLE_TP_ACTION_VERSION, - CSSM_TP_ACTION_ALLOW_EXPIRED | CSSM_TP_ACTION_ALLOW_EXPIRED_ROOT - }; - actionData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)&localActionData, sizeof(localActionData), kCFAllocatorNull); - if (!actionData) - goto loser; - - status = SecTrustSetParameters(trust, CSSM_TP_ACTION_DEFAULT, actionData); - if (status) - goto loser; - status = SecTrustEvaluate(trust, NULL); if (status) goto loser; @@ -295,8 +268,6 @@ loser: CFRelease(wrappedCert); if (trust) CFRelease(trust); - if (actionData) - CFRelease(actionData); if (certChain && status) { CFRelease(certChain); @@ -360,61 +331,11 @@ SecCertificateRef CERT_FindCertByDERCert(SecKeychainRef keychainOrArray, const S return cert; } -static int compareCssmData( - const CSSM_DATA *d1, - const CSSM_DATA *d2) -{ - if((d1 == NULL) || (d2 == NULL)) { - return 0; - } - if(d1->Length != d2->Length) { - return 0; - } - if(memcmp(d1->Data, d2->Data, d1->Length)) { - return 0; - } - return 1; -} - // Generate a certificate key from the issuer and serialnumber, then look it up in the database. // Return the cert if found. "issuerAndSN" is the issuer and serial number to look for -SecCertificateRef CERT_FindCertByIssuerAndSN (CFTypeRef keychainOrArray, - CSSM_DATA_PTR *rawCerts, PRArenaPool *pl, const SecCmsIssuerAndSN *issuerAndSN) +SecCertificateRef CERT_FindCertByIssuerAndSN (CFTypeRef keychainOrArray, const SecCmsIssuerAndSN *issuerAndSN) { SecCertificateRef certificate; - int numRawCerts = SecCmsArrayCount((void **)rawCerts); - int dex; - OSStatus ortn; - - /* - * First search the rawCerts array. - */ - for(dex=0; dexderIssuer, &issuerAndSN->derIssuer)) { - CFRelease(certificate); - continue; - } - if(!compareCssmData(&isn->serialNumber, &issuerAndSN->serialNumber)) { - CFRelease(certificate); - continue; - } - /* got it */ - dprintf("CERT_FindCertByIssuerAndSN: found cert %p\n", certificate); - return certificate; - } - - /* now search keychain(s) */ OSStatus status = SecCertificateFindByIssuerAndSN(keychainOrArray, &issuerAndSN->derIssuer, &issuerAndSN->serialNumber, &certificate); if (status) @@ -426,41 +347,9 @@ SecCertificateRef CERT_FindCertByIssuerAndSN (CFTypeRef keychainOrArray, return certificate; } -SecCertificateRef CERT_FindCertBySubjectKeyID (CFTypeRef keychainOrArray, - CSSM_DATA_PTR *rawCerts, const SECItem *subjKeyID) +SecCertificateRef CERT_FindCertBySubjectKeyID (CFTypeRef keychainOrArray, const SecAsn1Item *subjKeyID) { SecCertificateRef certificate; - int numRawCerts = SecCmsArrayCount((void **)rawCerts); - int dex; - OSStatus ortn; - SECItem skid; - - /* - * First search the rawCerts array. - */ - for(dex=0; dexdata. -SECStatus CERT_FindSubjectKeyIDExtension (SecCertificateRef cert, SECItem *retItem) +SECStatus CERT_FindSubjectKeyIDExtension (SecCertificateRef cert,SECItem *retItem) +{ + fprintf(stderr, "WARNING: CERT_FindSubjectKeyIDExtension unimplemented\n"); + return SECFailure; +} + +static void * appMalloc (uint32 size, void *allocRef) { + return (malloc (size)); +} + +static void appFree (void *mem_ptr, void *allocRef) { + free (mem_ptr); + return; +} + +static void * appRealloc (void *ptr, uint32 size, void *allocRef) { + return (realloc (ptr, size)); +} + +static void * appCalloc (uint32 num, uint32 size, void *allocRef) { + return (calloc (num, size)); +} + +static CSSM_API_MEMORY_FUNCS memFuncs = { + appMalloc, + appFree, + appRealloc, + appCalloc, + NULL + }; + +// return a valid CL handle +static int InitializeCL (CSSM_CL_HANDLE *clHandle) { - CSSM_DATA_PTR fieldValue = NULL; - OSStatus ortn; - CSSM_X509_EXTENSION *extp; - CE_SubjectKeyID *skid; + CSSM_VERSION version = {2, 0}; + + // load the module + CSSM_RETURN result = CSSM_ModuleLoad (&gGuidAppleX509CL, CSSM_KEY_HIERARCHY_NONE, NULL, NULL); + if (result != 0) + { + return false; + } - ortn = SecCertificateCopyFirstFieldValue(cert, &CSSMOID_SubjectKeyIdentifier, - &fieldValue); - if(ortn || (fieldValue == NULL)) { - /* this cert doesn't have that extension */ - return SECFailure; + result = CSSM_ModuleAttach (&gGuidAppleX509CL, &version, &memFuncs, 0, CSSM_SERVICE_CL, 0, 0, NULL, 0, NULL, clHandle); + if (result != 0) + { + return false; } - extp = (CSSM_X509_EXTENSION *)fieldValue->Data; - skid = (CE_SubjectKeyID *)extp->value.parsedValue; - retItem->Data = (uint8 *)PORT_Alloc(skid->Length); - retItem->Length = skid->Length; - memmove(retItem->Data, skid->Data, retItem->Length); - SecCertificateReleaseFirstFieldValue(cert, &CSSMOID_SubjectKeyIdentifier, - fieldValue); - return SECSuccess; + + return true; +} + +// cleanup a CL handle +static void CloseCL (CSSM_CL_HANDLE clHandle) +{ + CSSM_ModuleDetach (clHandle); + CSSM_ModuleUnload (&gGuidAppleX509CL, NULL, NULL); } // Extract the issuer and serial number from a certificate @@ -549,16 +474,19 @@ SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef ce mark = PORT_ArenaMark(pl); - status = SecCertificateGetCLHandle(cert, &clHandle); - if (status) + if (!InitializeCL (&clHandle)) goto loser; status = SecCertificateGetData(cert, &certData); if (status) goto loser; /* Get the issuer from the cert. */ - result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, - &OID_X509V1IssuerNameStd, &resultsHandle, &numberOfFields, &issuer); + result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, &OID_X509V1IssuerNameStd, &resultsHandle, &numberOfFields, &issuer); + + /* @@@ Remove this once we are sure CSSMOID_X509V1IssuerNameStd is working. */ + /* Fall back on old normalized issuer if the new oid isn't supported yet. */ + if (result) + result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, &CSSMOID_X509V1IssuerName, &resultsHandle, &numberOfFields, &issuer); if (result || numberOfFields < 1) goto loser; @@ -568,8 +496,7 @@ SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef ce /* Get the serialNumber from the cert. */ - result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, - &CSSMOID_X509V1SerialNumber, &resultsHandle, &numberOfFields, &serialNumber); + result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, &CSSMOID_X509V1SerialNumber, &resultsHandle, &numberOfFields, &serialNumber); if (result || numberOfFields < 1) goto loser; result = CSSM_CL_CertAbortQuery(clHandle, resultsHandle); @@ -600,6 +527,8 @@ SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef ce CSSM_CL_FreeFieldValue(clHandle, &CSSMOID_X509V1SerialNumber, serialNumber); CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer); + CloseCL (clHandle); + return certIssuerAndSN; loser: @@ -610,6 +539,8 @@ loser: if (issuer) CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer); + CloseCL (clHandle); + PORT_SetError(SEC_INTERNAL_ONLY); return NULL; } @@ -637,7 +568,7 @@ SECStatus CERT_ImportCerts(SecKeychainRef keychain, SECCertUsage usage, unsigned if (rv) { if (rv == errKCDuplicateItem) - rv = noErr; + rv = errSecSuccess; else { CFRelease(cert); @@ -682,36 +613,16 @@ SECStatus CERT_VerifyCertName(SecCertificateRef cert, const char *hostname) */ SECStatus CERT_VerifyCert(SecKeychainRef keychainOrArray, SecCertificateRef cert, - const CSSM_DATA_PTR *otherCerts, /* intermediates */ CFTypeRef policies, CFAbsoluteTime stime, SecTrustRef *trustRef) { - CFMutableArrayRef certificates = NULL; + CFArrayRef certificates; + const void *certs = cert; SecTrustRef trust = NULL; OSStatus rv; - int numOtherCerts = SecCmsArrayCount((void **)otherCerts); - int dex; - - /* - * Certs to evaluate: first the leaf - our cert - then all the rest we know - * about. It's OK for otherCerts to contain a copy of the leaf. - */ - certificates = CFArrayCreateMutable(NULL, numOtherCerts + 1, &kCFTypeArrayCallBacks); - CFArrayAppendValue(certificates, cert); - for(dex=0; dex +#include "SecCmsBase.h" #include #include #include #include #include "cmstpriv.h" +#include /************************************************************************/ SEC_BEGIN_PROTOS +#if !USE_CDSA_CRYPTO +bool CERT_CheckIssuerAndSerial(SecCertificateRef cert, SecAsn1Item *issuer, SecAsn1Item *serial); +#endif + typedef void CERTVerifyLog; void CERT_NormalizeX509NameNSS(NSS_Name *nssName); @@ -54,7 +59,7 @@ SecCertificateRef CERT_DupCertificate(SecCertificateRef cert); // Generate a certificate chain from a certificate. -CFArrayRef CERT_CertChainFromCert(SecCertificateRef cert, SECCertUsage usage,Boolean includeRoot); +CF_RETURNS_RETAINED CFArrayRef CERT_CertChainFromCert(SecCertificateRef cert, SECCertUsage usage,Boolean includeRoot); CFArrayRef CERT_CertListFromCert(SecCertificateRef cert); @@ -71,43 +76,46 @@ SecCertificateRef CERT_FindCertByEmailAddr(SecKeychainRef keychainOrArray, char // Find a certificate in the database by a DER encoded certificate // "derCert" is the DER encoded certificate -SecCertificateRef CERT_FindCertByDERCert(SecKeychainRef keychainOrArray, const SECItem *derCert); +SecCertificateRef CERT_FindCertByDERCert(SecKeychainRef keychainOrArray, const SecAsn1Item *derCert); // Generate a certificate key from the issuer and serialnumber, then look it up in the database. // Return the cert if found. "issuerAndSN" is the issuer and serial number to look for -SecCertificateRef CERT_FindCertByIssuerAndSN (CFTypeRef keychainOrArray, - CSSM_DATA_PTR *rawCerts, PRArenaPool *pl, const SecCmsIssuerAndSN *issuerAndSN); +SecCertificateRef CERT_FindCertByIssuerAndSN (CFTypeRef keychainOrArray, const SecCmsIssuerAndSN *issuerAndSN); -SecCertificateRef CERT_FindCertBySubjectKeyID (CFTypeRef keychainOrArray, - CSSM_DATA_PTR *rawCerts, const SECItem *subjKeyID); +SecCertificateRef CERT_FindCertBySubjectKeyID (CFTypeRef keychainOrArray, const SecAsn1Item *subjKeyID); SecIdentityRef CERT_FindIdentityByIssuerAndSN (CFTypeRef keychainOrArray, const SecCmsIssuerAndSN *issuerAndSN); +SecCertificateRef CERT_FindCertificateByIssuerAndSN (CFTypeRef keychainOrArray, const SecCmsIssuerAndSN *issuerAndSN); -SecIdentityRef CERT_FindIdentityBySubjectKeyID (CFTypeRef keychainOrArray, const SECItem *subjKeyID); +SecIdentityRef CERT_FindIdentityBySubjectKeyID (CFTypeRef keychainOrArray, const SecAsn1Item *subjKeyID); // find the smime symmetric capabilities profile for a given cert -SECItem *CERT_FindSMimeProfile(SecCertificateRef cert); +SecAsn1Item *CERT_FindSMimeProfile(SecCertificateRef cert); // Return the decoded value of the subjectKeyID extension. The caller should // free up the storage allocated in retItem->data. -SECStatus CERT_FindSubjectKeyIDExtension (SecCertificateRef cert, SECItem *retItem); +SECStatus CERT_FindSubjectKeyIDExtension (SecCertificateRef cert, SecAsn1Item *retItem); // Extract the issuer and serial number from a certificate SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef cert); // import a collection of certs into the temporary or permanent cert database SECStatus CERT_ImportCerts(SecKeychainRef keychain, SECCertUsage usage,unsigned int ncerts, - SECItem **derCerts,SecCertificateRef **retCerts, Boolean keepCerts,Boolean caOnly, char *nickname); + SecAsn1Item **derCerts,SecCertificateRef **retCerts, Boolean keepCerts,Boolean caOnly, char *nickname); -SECStatus CERT_SaveSMimeProfile(SecCertificateRef cert, SECItem *emailProfile,SECItem *profileTime); +SECStatus CERT_SaveSMimeProfile(SecCertificateRef cert, SecAsn1Item *emailProfile,SecAsn1Item *profileTime); // Check the hostname to make sure that it matches the shexp that // is given in the common name of the certificate. SECStatus CERT_VerifyCertName(SecCertificateRef cert, const char *hostname); +#if USE_CDSA_CRYPTO SECStatus CERT_VerifyCert(SecKeychainRef keychainOrArray, SecCertificateRef cert, - const CSSM_DATA_PTR *otherCerts, /* intermediates */ CFTypeRef policies, CFAbsoluteTime stime, SecTrustRef *trustRef); +#else +SECStatus CERT_VerifyCert(SecKeychainRef keychainOrArray, CFArrayRef cert, + CFTypeRef policies, CFAbsoluteTime stime, SecTrustRef *trustRef); +#endif CFTypeRef CERT_PolicyForCertUsage(SECCertUsage certUsage); diff --git a/libsecurity_smime/lib/cmsarray.c b/libsecurity_smime/lib/cmsarray.c index 56984fed..cc1b71a6 100644 --- a/libsecurity_smime/lib/cmsarray.c +++ b/libsecurity_smime/lib/cmsarray.c @@ -38,6 +38,7 @@ #include "cmslocal.h" #include +#include /* * ARRAY FUNCTIONS diff --git a/libsecurity_smime/lib/cmsasn1.c b/libsecurity_smime/lib/cmsasn1.c index 6e8a3eba..e21637e7 100644 --- a/libsecurity_smime/lib/cmsasn1.c +++ b/libsecurity_smime/lib/cmsasn1.c @@ -42,7 +42,7 @@ #include "secoid.h" #include #include - +#include extern const SecAsn1Template nss_cms_set_of_attribute_template[]; @@ -253,10 +253,9 @@ static const SecAsn1Template SecCmsRecipientIdentifierTemplate[] = { { SEC_ASN1_CHOICE, offsetof(SecCmsRecipientIdentifier,identifierType), NULL, sizeof(SecCmsRecipientIdentifier) }, - { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | - SEC_ASN1_XTRN | 0, + { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, offsetof(SecCmsRecipientIdentifier,id.subjectKeyID), - SEC_ASN1_SUB(kSecAsn1PointerToOctetStringTemplate) , + SEC_ASN1_SUB(kSecAsn1OctetStringTemplate) , SecCmsRecipientIDSubjectKeyID }, { SEC_ASN1_POINTER | SEC_ASN1_XTRN, offsetof(SecCmsRecipientIdentifier,id.issuerAndSN), @@ -308,12 +307,11 @@ static const SecAsn1Template SecCmsOriginatorIdentifierOrKeyTemplate[] = { SEC_ASN1_SUB(SecCmsIssuerAndSNTemplate), SecCmsOriginatorIDOrKeyIssuerSN }, { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | - /* this was tag 1 here, 2 for the next; RFC 3852 says they are 0 and 1 */ - SEC_ASN1_XTRN | 0, + SEC_ASN1_XTRN | 1, offsetof(SecCmsOriginatorIdentifierOrKey,id.subjectKeyID), - kSecAsn1OctetStringTemplate, + SEC_ASN1_SUB(kSecAsn1PointerToOctetStringTemplate) , SecCmsOriginatorIDOrKeySubjectKeyID }, - { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, + { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 2, offsetof(SecCmsOriginatorIdentifierOrKey,id.originatorPublicKey), SecCmsOriginatorPublicKeyTemplate, SecCmsOriginatorIDOrKeyOriginatorPublicKey }, @@ -356,7 +354,7 @@ static const SecAsn1Template SecCmsRecipientEncryptedKeyTemplate[] = { SecCmsKeyAgreeRecipientIdentifierTemplate }, { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(SecCmsRecipientEncryptedKey,encKey), - SEC_ASN1_SUB(kSecAsn1OctetStringTemplate) }, + SEC_ASN1_SUB(kSecAsn1BitStringTemplate) }, { 0 } }; @@ -536,9 +534,6 @@ const SecAsn1Template NSS_SMIMEKEAParamTemplateAllParams[] = { { 0 } }; -/*TODO: this should be in some header */ -const SecAsn1Template * -nss_cms_get_kea_template(SecCmsKEATemplateSelector whichTemplate); const SecAsn1Template * nss_cms_get_kea_template(SecCmsKEATemplateSelector whichTemplate) { @@ -579,7 +574,6 @@ nss_cms_choose_content_template(void *src_or_dest, Boolean encoding, const char theTemplate = SEC_ASN1_GET(kSecAsn1PointerToAnyTemplate); break; case SEC_OID_PKCS7_DATA: - case SEC_OID_OTHER: theTemplate = SEC_ASN1_GET(kSecAsn1PointerToOctetStringTemplate); break; case SEC_OID_PKCS7_SIGNED_DATA: diff --git a/libsecurity_smime/lib/cmsattr.c b/libsecurity_smime/lib/cmsattr.c index 6165481b..ba52167b 100644 --- a/libsecurity_smime/lib/cmsattr.c +++ b/libsecurity_smime/lib/cmsattr.c @@ -38,10 +38,13 @@ #include "cmslocal.h" #include "secoid.h" -#include "secitem.h" +#include "SecAsn1Item.h" #include #include +#include + +#include /* * ------------------------------------------------------------------- @@ -61,10 +64,10 @@ * with SecCmsAttributeAddValue. */ SecCmsAttribute * -SecCmsAttributeCreate(PRArenaPool *poolp, SECOidTag oidtag, CSSM_DATA_PTR value, Boolean encoded) +SecCmsAttributeCreate(PRArenaPool *poolp, SECOidTag oidtag, SecAsn1Item * value, Boolean encoded) { SecCmsAttribute *attr; - CSSM_DATA_PTR copiedvalue; + SecAsn1Item * copiedvalue; void *mark; PORT_Assert (poolp != NULL); @@ -83,7 +86,7 @@ SecCmsAttributeCreate(PRArenaPool *poolp, SECOidTag oidtag, CSSM_DATA_PTR value, goto loser; if (value != NULL) { - if ((copiedvalue = SECITEM_AllocItem(poolp, NULL, (unsigned int)value->Length)) == NULL) + if ((copiedvalue = SECITEM_AllocItem(poolp, NULL, value->Length)) == NULL) goto loser; if (SECITEM_CopyItem(poolp, copiedvalue, value) != SECSuccess) @@ -108,9 +111,9 @@ loser: * SecCmsAttributeAddValue - add another value to an attribute */ OSStatus -SecCmsAttributeAddValue(PLArenaPool *poolp, SecCmsAttribute *attr, CSSM_DATA_PTR value) +SecCmsAttributeAddValue(PLArenaPool *poolp, SecCmsAttribute *attr, SecAsn1Item * value) { - CSSM_DATA copiedvalue; + SecAsn1Item copiedvalue; void *mark; PORT_Assert (poolp != NULL); @@ -155,10 +158,10 @@ SecCmsAttributeGetType(SecCmsAttribute *attr) * - Multiple values are *not* expected. * - Empty values are *not* expected. */ -CSSM_DATA_PTR +SecAsn1Item * SecCmsAttributeGetValue(SecCmsAttribute *attr) { - CSSM_DATA_PTR value; + SecAsn1Item * value; if (attr == NULL) return NULL; @@ -178,9 +181,9 @@ SecCmsAttributeGetValue(SecCmsAttribute *attr) * SecCmsAttributeCompareValue - compare the attribute's first value against data */ Boolean -SecCmsAttributeCompareValue(SecCmsAttribute *attr, CSSM_DATA_PTR av) +SecCmsAttributeCompareValue(SecCmsAttribute *attr, SecAsn1Item * av) { - CSSM_DATA_PTR value; + SecAsn1Item * value; if (attr == NULL) return PR_FALSE; @@ -312,8 +315,8 @@ const SecAsn1Template nss_cms_set_of_attribute_template[] = { * and think long and hard about the implications of making it always * do the reordering.) */ -CSSM_DATA_PTR -SecCmsAttributeArrayEncode(PRArenaPool *poolp, SecCmsAttribute ***attrs, CSSM_DATA_PTR dest) +SecAsn1Item * +SecCmsAttributeArrayEncode(PRArenaPool *poolp, SecCmsAttribute ***attrs, SecAsn1Item * dest) { return SEC_ASN1EncodeItem (poolp, dest, (void *)attrs, nss_cms_set_of_attribute_template); } @@ -416,7 +419,7 @@ loser: * SecCmsAttributeArraySetAttr - set an attribute's value in a set of attributes */ OSStatus -SecCmsAttributeArraySetAttr(PLArenaPool *poolp, SecCmsAttribute ***attrs, SECOidTag type, CSSM_DATA_PTR value, Boolean encoded) +SecCmsAttributeArraySetAttr(PLArenaPool *poolp, SecCmsAttribute ***attrs, SECOidTag type, SecAsn1Item * value, Boolean encoded) { SecCmsAttribute *attr; void *mark; diff --git a/libsecurity_smime/lib/cmscinfo.c b/libsecurity_smime/lib/cmscinfo.c index e13acbe8..00e18ded 100644 --- a/libsecurity_smime/lib/cmscinfo.c +++ b/libsecurity_smime/lib/cmscinfo.c @@ -47,16 +47,12 @@ //#include "pk11func.h" #include "secoid.h" -#include "secitem.h" +#include "SecAsn1Item.h" #include -#include +#include -/* - * SecCmsContentInfoCreate - create a content info - * - * version is set in the _Finalize procedures for each content type - */ +#include /* * SecCmsContentInfoDestroy - destroy a CMS contentInfo and all of its sub-pieces. @@ -130,7 +126,6 @@ SecCmsContentInfoGetChildContentInfo(SecCmsContentInfoRef cinfo) ccinfo = &(cinfo->content.encryptedData->contentInfo); break; case SEC_OID_PKCS7_DATA: - case SEC_OID_OTHER: default: break; } @@ -141,18 +136,18 @@ SecCmsContentInfoGetChildContentInfo(SecCmsContentInfoRef cinfo) * SecCmsContentInfoSetContent - set content type & content */ OSStatus -SecCmsContentInfoSetContent(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SECOidTag type, void *ptr) +SecCmsContentInfoSetContent(SecCmsContentInfoRef cinfo, SECOidTag type, void *ptr) { OSStatus rv; cinfo->contentTypeTag = SECOID_FindOIDByTag(type); if (cinfo->contentTypeTag == NULL) - return paramErr; + return errSecParam; /* do not copy the oid, just create a reference */ - rv = SECITEM_CopyItem (cmsg->poolp, &(cinfo->contentType), &(cinfo->contentTypeTag->oid)); + rv = SECITEM_CopyItem (cinfo->cmsg->poolp, &(cinfo->contentType), &(cinfo->contentTypeTag->oid)); if (rv != SECSuccess) - return memFullErr; + return errSecAllocate; cinfo->content.pointer = ptr; @@ -160,14 +155,14 @@ SecCmsContentInfoSetContent(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, S /* as we always have some inner data, * we need to set it to something, just to fool the encoder enough to work on it * and get us into nss_cms_encoder_notify at that point */ - cinfo->rawContent = SECITEM_AllocItem(cmsg->poolp, NULL, 1); + cinfo->rawContent = SECITEM_AllocItem(cinfo->cmsg->poolp, NULL, 1); if (cinfo->rawContent == NULL) { PORT_SetError(SEC_ERROR_NO_MEMORY); - return memFullErr; + return errSecAllocate; } } - return noErr; + return errSecSuccess; } /* @@ -179,71 +174,54 @@ SecCmsContentInfoSetContent(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, S * data != NULL -> take this data */ OSStatus -SecCmsContentInfoSetContentData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, CSSM_DATA_PTR data, Boolean detached) +SecCmsContentInfoSetContentData(SecCmsContentInfoRef cinfo, CFDataRef dataRef, Boolean detached) { - if (SecCmsContentInfoSetContent(cmsg, cinfo, SEC_OID_PKCS7_DATA, (void *)data) != SECSuccess) + SecAsn1Item * data = NULL; + if (dataRef) { + /* @@@ Fixme CFRetain the passed in data rather than + always copying it for performance. */ + data = PORT_ArenaAlloc(cinfo->cmsg->poolp, sizeof(SecAsn1Item)); + data->Length = CFDataGetLength(dataRef); + if (data->Length) { + data->Data = PORT_ArenaAlloc(cinfo->cmsg->poolp, data->Length); + memcpy(data->Data, CFDataGetBytePtr(dataRef), data->Length); + } + else + data->Data = NULL; + } + + if (SecCmsContentInfoSetContent(cinfo, SEC_OID_PKCS7_DATA, (void *)data) != SECSuccess) return PORT_GetError(); cinfo->rawContent = (detached) ? NULL : (data) ? - data : SECITEM_AllocItem(cmsg->poolp, NULL, 1); - return noErr; -} - -OSStatus -SecCmsContentInfoSetContentSignedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsSignedDataRef sigd) -{ - return SecCmsContentInfoSetContent(cmsg, cinfo, SEC_OID_PKCS7_SIGNED_DATA, (void *)sigd); + data : SECITEM_AllocItem(cinfo->cmsg->poolp, NULL, 1); + return errSecSuccess; } OSStatus -SecCmsContentInfoSetContentEnvelopedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsEnvelopedDataRef envd) +SecCmsContentInfoSetContentSignedData(SecCmsContentInfoRef cinfo, SecCmsSignedDataRef sigd) { - return SecCmsContentInfoSetContent(cmsg, cinfo, SEC_OID_PKCS7_ENVELOPED_DATA, (void *)envd); + return SecCmsContentInfoSetContent(cinfo, SEC_OID_PKCS7_SIGNED_DATA, (void *)sigd); } OSStatus -SecCmsContentInfoSetContentDigestedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsDigestedDataRef digd) +SecCmsContentInfoSetContentEnvelopedData(SecCmsContentInfoRef cinfo, SecCmsEnvelopedDataRef envd) { - return SecCmsContentInfoSetContent(cmsg, cinfo, SEC_OID_PKCS7_DIGESTED_DATA, (void *)digd); + return SecCmsContentInfoSetContent(cinfo, SEC_OID_PKCS7_ENVELOPED_DATA, (void *)envd); } OSStatus -SecCmsContentInfoSetContentEncryptedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsEncryptedDataRef encd) +SecCmsContentInfoSetContentDigestedData(SecCmsContentInfoRef cinfo, SecCmsDigestedDataRef digd) { - return SecCmsContentInfoSetContent(cmsg, cinfo, SEC_OID_PKCS7_ENCRYPTED_DATA, (void *)encd); + return SecCmsContentInfoSetContent(cinfo, SEC_OID_PKCS7_DIGESTED_DATA, (void *)digd); } OSStatus -SecCmsContentInfoSetContentOther(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, CSSM_DATA_PTR data, Boolean detached, const CSSM_OID *eContentType) +SecCmsContentInfoSetContentEncryptedData(SecCmsContentInfoRef cinfo, SecCmsEncryptedDataRef encd) { - SECStatus srtn; - SECOidData *tmpOidData; - - /* just like SecCmsContentInfoSetContentData, except override the contentType and - * contentTypeTag. This OID is for encoding... */ - srtn = SECITEM_CopyItem (cmsg->poolp, &(cinfo->contentType), eContentType); - if (srtn != SECSuccess) { - return memFullErr; - } - - /* this serves up a contentTypeTag with an empty OID */ - tmpOidData = SECOID_FindOIDByTag(SEC_OID_OTHER); - /* but that's const: cook up a new one we can write to */ - cinfo->contentTypeTag = (SECOidData *)PORT_ArenaZAlloc(cmsg->poolp, sizeof(SECOidData)); - *cinfo->contentTypeTag = *tmpOidData; - /* now fill in the OID */ - srtn = SECITEM_CopyItem (cmsg->poolp, &(cinfo->contentTypeTag->oid), eContentType); - if (srtn != SECSuccess) { - return memFullErr; - } - cinfo->content.pointer = data; - cinfo->rawContent = (detached) ? - NULL : (data) ? - data : SECITEM_AllocItem(cmsg->poolp, NULL, 1); - return noErr; + return SecCmsContentInfoSetContent(cinfo, SEC_OID_PKCS7_ENCRYPTED_DATA, (void *)encd); } - /* * SecCmsContentInfoGetContent - get pointer to inner content * @@ -254,14 +232,13 @@ SecCmsContentInfoGetContent(SecCmsContentInfoRef cinfo) { SECOidTag tag = (cinfo && cinfo->contentTypeTag) ? cinfo->contentTypeTag->offset - : cinfo->contentType.Data ? SEC_OID_OTHER : SEC_OID_UNKNOWN; + : SEC_OID_UNKNOWN; switch (tag) { case SEC_OID_PKCS7_DATA: case SEC_OID_PKCS7_SIGNED_DATA: case SEC_OID_PKCS7_ENVELOPED_DATA: case SEC_OID_PKCS7_DIGESTED_DATA: case SEC_OID_PKCS7_ENCRYPTED_DATA: - case SEC_OID_OTHER: return cinfo->content.pointer; default: return NULL; @@ -273,38 +250,35 @@ SecCmsContentInfoGetContent(SecCmsContentInfoRef cinfo) * * this is typically only called by SecCmsMessageGetContent() */ -CSSM_DATA_PTR +const SecAsn1Item * SecCmsContentInfoGetInnerContent(SecCmsContentInfoRef cinfo) { + SecCmsContentInfoRef ccinfo; SECOidTag tag; + SecAsn1Item * pItem; - for(;;) { - tag = SecCmsContentInfoGetContentTypeTag(cinfo); - switch (tag) { - case SEC_OID_PKCS7_DATA: - case SEC_OID_OTHER: - /* end of recursion - every message has to have a data cinfo */ - return cinfo->content.data; - case SEC_OID_PKCS7_DIGESTED_DATA: - case SEC_OID_PKCS7_ENCRYPTED_DATA: - case SEC_OID_PKCS7_ENVELOPED_DATA: - case SEC_OID_PKCS7_SIGNED_DATA: - cinfo = SecCmsContentInfoGetChildContentInfo(cinfo); - if (cinfo == NULL) { - return NULL; - } - /* else recurse */ - break; - case SEC_OID_PKCS9_ID_CT_TSTInfo: - /* end of recursion - every message has to have a data cinfo */ - return cinfo->rawContent; - default: - PORT_Assert(0); - return NULL; - } + tag = SecCmsContentInfoGetContentTypeTag(cinfo); + switch (tag) { + case SEC_OID_PKCS7_DATA: + /* end of recursion - every message has to have a data cinfo */ + pItem = cinfo->content.data; + break; + case SEC_OID_PKCS7_DIGESTED_DATA: + case SEC_OID_PKCS7_ENCRYPTED_DATA: + case SEC_OID_PKCS7_ENVELOPED_DATA: + case SEC_OID_PKCS7_SIGNED_DATA: + ccinfo = SecCmsContentInfoGetChildContentInfo(cinfo); + if (ccinfo == NULL) + pItem = NULL; + else + pItem = SecCmsContentInfoGetContent(ccinfo); + break; + default: + PORT_Assert(0); + pItem = NULL; + break; } - /* NOT REACHED */ - return NULL; + return pItem; } /* @@ -318,26 +292,20 @@ SecCmsContentInfoGetContentTypeTag(SecCmsContentInfoRef cinfo) cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType)); if (cinfo->contentTypeTag == NULL) - return SEC_OID_OTHER; // was...SEC_OID_UNKNOWN OK? + return SEC_OID_UNKNOWN; return cinfo->contentTypeTag->offset; } -CSSM_DATA_PTR +SecAsn1Oid * SecCmsContentInfoGetContentTypeOID(SecCmsContentInfoRef cinfo) { if (cinfo->contentTypeTag == NULL) cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType)); - if (cinfo->contentTypeTag == NULL) { - /* if we have an OID but we just don't recognize it, return that */ - if(cinfo->contentType.Data != NULL) { - return &cinfo->contentType; - } - else { - return NULL; - } - } + if (cinfo->contentTypeTag == NULL) + return NULL; + return &(cinfo->contentTypeTag->oid); } @@ -364,10 +332,10 @@ SecCmsContentInfoGetContentEncAlg(SecCmsContentInfoRef cinfo) } OSStatus -SecCmsContentInfoSetContentEncAlg(SecArenaPoolRef pool, SecCmsContentInfoRef cinfo, - SECOidTag bulkalgtag, CSSM_DATA_PTR parameters, int keysize) +SecCmsContentInfoSetContentEncAlg(SecCmsContentInfoRef cinfo, + SECOidTag bulkalgtag, const SecAsn1Item *parameters, int keysize) { - PLArenaPool *poolp = (PLArenaPool *)pool; + PLArenaPool *poolp = cinfo->cmsg->poolp; OSStatus rv; rv = SECOID_SetAlgorithmID(poolp, &(cinfo->contentEncAlg), bulkalgtag, parameters); @@ -378,10 +346,10 @@ SecCmsContentInfoSetContentEncAlg(SecArenaPoolRef pool, SecCmsContentInfoRef cin } OSStatus -SecCmsContentInfoSetContentEncAlgID(SecArenaPoolRef pool, SecCmsContentInfoRef cinfo, +SecCmsContentInfoSetContentEncAlgID(SecCmsContentInfoRef cinfo, SECAlgorithmID *algid, int keysize) { - PLArenaPool *poolp = (PLArenaPool *)pool; + PLArenaPool *poolp = cinfo->cmsg->poolp; OSStatus rv; rv = SECOID_CopyAlgorithmID(poolp, &(cinfo->contentEncAlg), algid); @@ -395,12 +363,18 @@ SecCmsContentInfoSetContentEncAlgID(SecArenaPoolRef pool, SecCmsContentInfoRef c void SecCmsContentInfoSetBulkKey(SecCmsContentInfoRef cinfo, SecSymmetricKeyRef bulkkey) { +#ifdef USE_CDSA_CRYPTO const CSSM_KEY *cssmKey = NULL; - +#endif cinfo->bulkkey = bulkkey; CFRetain(cinfo->bulkkey); +#ifdef USE_CDSA_CRYPTO SecKeyGetCSSMKey(cinfo->bulkkey, &cssmKey); cinfo->keysize = cssmKey ? cssmKey->KeyHeader.LogicalKeySizeInBits : 0; +#else + /* This cast should be always safe, there should be SecSymmetricKeyRef API to get the size anyway */ + cinfo->keysize = (int)CFDataGetLength((CFDataRef)bulkkey) * 8; +#endif } SecSymmetricKeyRef diff --git a/libsecurity_smime/lib/cmscipher.c b/libsecurity_smime/lib/cmscipher.c index 02ec0873..2e149a25 100644 --- a/libsecurity_smime/lib/cmscipher.c +++ b/libsecurity_smime/lib/cmscipher.c @@ -35,16 +35,24 @@ * Encryption/decryption routines for CMS implementation, none of which are exported. * */ +#include #include "cmslocal.h" #include "secoid.h" #include #include +#include + #include +#if USE_CDSA_CRYPTO #include #include #include +#else +#include +#include +#endif /* * ------------------------------------------------------------------- @@ -61,14 +69,14 @@ typedef OSStatus (*nss_cms_cipher_destroy) (void *, Boolean); struct SecCmsCipherContextStr { #if 1 - CSSM_CC_HANDLE cc; /* CSP CONTEXT */ + void * cc; /* CSP CONTEXT */ Boolean encrypt; /* encrypt / decrypt switch */ + int block_size; /* block & pad sizes for cipher */ #else void * cx; /* PK11 cipher context */ nss_cms_cipher_function doit; nss_cms_cipher_destroy destroy; Boolean encrypt; /* encrypt / decrypt switch */ - int block_size; /* block & pad sizes for cipher */ int pad_size; int pending_count; /* pending data (not yet en/decrypted */ unsigned char pending_buf[BLOCK_SIZE];/* because of blocking */ @@ -76,11 +84,11 @@ struct SecCmsCipherContextStr { }; typedef struct sec_rc2cbcParameterStr { - SECItem rc2ParameterVersion; - SECItem iv; + SecAsn1Item rc2ParameterVersion; + SecAsn1Item iv; } sec_rc2cbcParameter; -static const SecAsn1Template sec_rc2cbc_parameter_template[] = { +__unused static const SecAsn1Template sec_rc2cbc_parameter_template[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(sec_rc2cbcParameter) }, { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT, @@ -90,15 +98,17 @@ static const SecAsn1Template sec_rc2cbc_parameter_template[] = { { 0 } }; +// TODO: get rid of this? +#if USE_CDSA_CRYPTO /* ** Convert a der encoded *signed* integer into a machine integral value. ** If an underflow/overflow occurs, sets error code and returns min/max. */ static long -DER_GetInteger(SECItem *it) +DER_GetInteger(SecAsn1Item *it) { long ival = 0; - CSSM_SIZE len = it->Length; + unsigned len = it->Length; unsigned char *cp = it->Data; unsigned long overflow = 0x1ffUL << (((sizeof(ival) - 1) * 8) - 1); unsigned long ofloinit; @@ -125,7 +135,7 @@ DER_GetInteger(SECItem *it) /* S/MIME picked id values to represent differnt keysizes */ /* I do have a formula, but it ain't pretty, and it only works because you * can always match three points to a parabola:) */ -static unsigned char rc2_map(SECItem *version) +static unsigned char rc2_map(SecAsn1Item *version) { long x; @@ -148,6 +158,7 @@ static unsigned long rc2_unmap(unsigned long x) } return 58; } +#endif /* USE_CDSA_CRYPTO */ /* default IV size in bytes */ #define DEFAULT_IV_SIZE 8 @@ -156,29 +167,49 @@ static unsigned long rc2_unmap(unsigned long x) /* max IV size in bytes */ #define MAX_IV_SIZE AES_BLOCK_SIZE +#if !USE_CDSA_CRYPTO +#ifndef kCCKeySizeMaxRC2 +#define kCCKeySizeMaxRC2 16 +#endif +#ifndef kCCBlockSizeRC2 +#define kCCBlockSizeRC2 8 +#endif +#ifndef kCCAlgorithmRC2 +#define kCCAlgorithmRC2 -1 +#endif +#endif + static SecCmsCipherContextRef SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorithmID *algid, Boolean encrypt) { SecCmsCipherContextRef cc; - CSSM_CC_HANDLE ciphercc = 0; SECOidData *oidData; SECOidTag algtag; + OSStatus rv; + uint8_t ivbuf[MAX_IV_SIZE]; + SecAsn1Item initVector = { DEFAULT_IV_SIZE, ivbuf }; +#if USE_CDSA_CRYPTO + CSSM_CC_HANDLE ciphercc = 0; CSSM_ALGORITHMS algorithm; CSSM_PADDING padding = CSSM_PADDING_PKCS7; CSSM_ENCRYPT_MODE mode; CSSM_CSP_HANDLE cspHandle; const CSSM_KEY *cssmKey; - OSStatus rv; - uint8 ivbuf[MAX_IV_SIZE]; - CSSM_DATA initVector = { DEFAULT_IV_SIZE, ivbuf }; - //CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_ALG_PARAMS, sizeof(CSSM_DATA_PTR) }; + //CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_ALG_PARAMS, sizeof(SecAsn1Item *) }; +#else + CCCryptorRef ciphercc = NULL; + CCOptions cipheroptions = kCCOptionPKCS7Padding; + int cipher_blocksize = 0; +#endif +#if USE_CDSA_CRYPTO rv = SecKeyGetCSPHandle(key, &cspHandle); if (rv) goto loser; rv = SecKeyGetCSSMKey(key, &cssmKey); if (rv) goto loser; +#endif // @@@ Add support for PBE based stuff @@ -186,10 +217,11 @@ SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorith if (!oidData) goto loser; algtag = oidData->offset; +#if USE_CDSA_CRYPTO algorithm = oidData->cssmAlgorithm; if (!algorithm) goto loser; - + switch (algtag) { case SEC_OID_RC2_CBC: @@ -228,11 +260,38 @@ SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorith default: goto loser; } +#else + CCAlgorithm alg = -1; + switch (algtag) { + case SEC_OID_DES_CBC: + alg = kCCAlgorithmDES; + cipher_blocksize = kCCBlockSizeDES; + break; + case SEC_OID_DES_EDE3_CBC: + alg = kCCAlgorithm3DES; + cipher_blocksize = kCCBlockSize3DES; + break; + case SEC_OID_RC2_CBC: + alg = kCCAlgorithmRC2; + cipher_blocksize = kCCBlockSizeRC2; + break; + case SEC_OID_AES_128_CBC: + case SEC_OID_AES_192_CBC: + case SEC_OID_AES_256_CBC: + alg = kCCAlgorithmAES128; + cipher_blocksize = kCCBlockSizeAES128; + initVector.Length = AES_BLOCK_SIZE; + break; + default: + goto loser; + } +#endif if (encrypt) { +#if USE_CDSA_CRYPTO CSSM_CC_HANDLE randomcc; - //SECItem *parameters; + //SecAsn1Item *parameters; // Generate random initVector if (CSSM_CSP_CreateRandomGenContext(cspHandle, @@ -245,6 +304,11 @@ SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorith if (CSSM_GenerateRandom(randomcc, &initVector)) goto loser; CSSM_DeleteContext(randomcc); +#else + if (SecRandomCopyBytes(kSecRandomDefault, + initVector.Length, initVector.Data)) + goto loser; +#endif // Put IV into algid.parameters switch (algtag) @@ -268,12 +332,12 @@ SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorith &initVector, kSecAsn1OctetStringTemplate)) goto loser; break; - case SEC_OID_RC2_CBC: +#if USE_CDSA_CRYPTO { sec_rc2cbcParameter rc2 = {}; unsigned long rc2version; - SECItem *newParams; + SecAsn1Item *newParams; rc2.iv = initVector; rc2version = rc2_unmap(cssmKey->KeyHeader.LogicalKeySizeInBits); @@ -287,6 +351,7 @@ SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorith goto loser; break; } +#endif case SEC_OID_RC5_CBC_PAD: default: // @@@ Implement rc5 params stuff. @@ -315,7 +380,7 @@ SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorith case SEC_OID_DES_OFB: case SEC_OID_DES_CFB: { - CSSM_DATA iv = {}; + SecAsn1Item iv = {}; /* Just decode the initVector from an octet string. */ rv = SEC_ASN1DecodeItem(NULL, &iv, kSecAsn1OctetStringTemplate, &(algid->parameters)); if (rv) @@ -329,6 +394,7 @@ SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorith break; } case SEC_OID_RC2_CBC: +#if USE_CDSA_CRYPTO { sec_rc2cbcParameter rc2 = {}; unsigned long ulEffectiveBits; @@ -352,6 +418,7 @@ SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorith goto loser; break; } +#endif case SEC_OID_RC5_CBC_PAD: default: // @@@ Implement rc5 params stuff. @@ -360,6 +427,7 @@ SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorith } } +#if USE_CDSA_CRYPTO if (CSSM_CSP_CreateSymmetricContext(cspHandle, algorithm, mode, @@ -377,6 +445,12 @@ SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorith rv = CSSM_DecryptDataInit(ciphercc); if (rv) goto loser; +#else + if (CCCryptorCreate(encrypt ? kCCEncrypt : kCCDecrypt, + alg, cipheroptions, CFDataGetBytePtr(key), CFDataGetLength(key), + initVector.Data, &ciphercc)) + goto loser; +#endif cc = (SecCmsCipherContextRef)PORT_ZAlloc(sizeof(SecCmsCipherContext)); if (cc == NULL) @@ -384,11 +458,17 @@ SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorith cc->cc = ciphercc; cc->encrypt = encrypt; - +#if !USE_CDSA_CRYPTO + cc->block_size =cipher_blocksize; +#endif return cc; loser: if (ciphercc) +#if USE_CDSA_CRYPTO CSSM_DeleteContext(ciphercc); +#else + CCCryptorRelease(ciphercc); +#endif return NULL; } @@ -409,7 +489,7 @@ SecCmsCipherContextStartDecrypt(SecSymmetricKeyRef key, SECAlgorithmID *algid) SecCmsCipherContextRef cc; void *ciphercx; CK_MECHANISM_TYPE mechanism; - CSSM_DATA_PTR param; + SecAsn1Item * param; PK11SlotInfo *slot; SECOidTag algtag; @@ -418,7 +498,7 @@ SecCmsCipherContextStartDecrypt(SecSymmetricKeyRef key, SECAlgorithmID *algid) /* set param and mechanism */ if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { CK_MECHANISM pbeMech, cryptoMech; - CSSM_DATA_PTR pbeParams; + SecAsn1Item * pbeParams; SEC_PKCS5KeyAndPassword *keyPwd; PORT_Memset(&pbeMech, 0, sizeof(CK_MECHANISM)); @@ -447,7 +527,7 @@ SecCmsCipherContextStartDecrypt(SecSymmetricKeyRef key, SECAlgorithmID *algid) SECITEM_ZfreeItem(pbeParams, PR_TRUE); /* and use it to initialize param & mechanism */ - if ((param = (CSSM_DATA_PTR)PORT_ZAlloc(sizeof(CSSM_DATA))) == NULL) + if ((param = (SecAsn1Item *)PORT_ZAlloc(sizeof(SecAsn1Item))) == NULL) return NULL; param->Data = (unsigned char *)cryptoMech.pParameter; @@ -505,7 +585,7 @@ SecCmsCipherContextStartEncrypt(PRArenaPool *poolp, SecSymmetricKeyRef key, SECA #if 0 SecCmsCipherContextRef cc; void *ciphercx; - CSSM_DATA_PTR param; + SecAsn1Item * param; OSStatus rv; CK_MECHANISM_TYPE mechanism; PK11SlotInfo *slot; @@ -515,7 +595,7 @@ SecCmsCipherContextStartEncrypt(PRArenaPool *poolp, SecSymmetricKeyRef key, SECA /* set param and mechanism */ if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { CK_MECHANISM pbeMech, cryptoMech; - CSSM_DATA_PTR pbeParams; + SecAsn1Item * pbeParams; SEC_PKCS5KeyAndPassword *keyPwd; PORT_Memset(&pbeMech, 0, sizeof(CK_MECHANISM)); @@ -544,7 +624,7 @@ SecCmsCipherContextStartEncrypt(PRArenaPool *poolp, SecSymmetricKeyRef key, SECA SECITEM_ZfreeItem(pbeParams, PR_TRUE); /* and use it to initialize param & mechanism */ - if ((param = (CSSM_DATA_PTR)PORT_ZAlloc(sizeof(CSSM_DATA))) == NULL) + if ((param = (SecAsn1Item *)PORT_ZAlloc(sizeof(SecAsn1Item))) == NULL) return NULL; param->Data = (unsigned char *)cryptoMech.pParameter; @@ -611,13 +691,18 @@ SecCmsCipherContextDestroy(SecCmsCipherContextRef cc) PORT_Assert(cc != NULL); if (cc == NULL) return; +#if USE_CDSA_CRYPTO CSSM_DeleteContext(cc->cc); +#else + CCCryptorRelease(cc->cc); +#endif PORT_Free(cc); } static unsigned int SecCmsCipherContextLength(SecCmsCipherContextRef cc, unsigned int input_len, Boolean final, Boolean encrypt) { +#if USE_CDSA_CRYPTO CSSM_QUERY_SIZE_DATA dataBlockSize[2] = { { input_len, 0 }, { input_len, 0 } }; /* Hack CDSA treats the last block as the final one. So unless we are being asked to report the final size we ask for 2 block and ignore the second (final) one. */ OSStatus rv = CSSM_QuerySize(cc->cc, cc->encrypt, final ? 1 : 2, dataBlockSize); @@ -628,6 +713,9 @@ SecCmsCipherContextLength(SecCmsCipherContextRef cc, unsigned int input_len, Boo } return dataBlockSize[0].SizeOutputBlock; +#else + return ((input_len + cc->block_size - 1) / cc->block_size * cc->block_size) + (final ? cc->block_size : 0); +#endif } /* @@ -651,11 +739,11 @@ SecCmsCipherContextLength(SecCmsCipherContextRef cc, unsigned int input_len, Boo * passed in to the subsequent decrypt operation, as no output bytes * will be stored. */ -size_t -SecCmsCipherContextDecryptLength(SecCmsCipherContextRef cc, size_t input_len, Boolean final) +unsigned int +SecCmsCipherContextDecryptLength(SecCmsCipherContextRef cc, unsigned int input_len, Boolean final) { #if 1 - return SecCmsCipherContextLength(cc, (unsigned int)input_len, final, PR_FALSE); + return SecCmsCipherContextLength(cc, input_len, final, PR_FALSE); #else int blocks, block_size; @@ -713,11 +801,11 @@ SecCmsCipherContextDecryptLength(SecCmsCipherContextRef cc, size_t input_len, Bo * passed in to the subsequent encrypt operation, as no output bytes * will be stored. */ -size_t -SecCmsCipherContextEncryptLength(SecCmsCipherContextRef cc, size_t input_len, Boolean final) +unsigned int +SecCmsCipherContextEncryptLength(SecCmsCipherContextRef cc, unsigned int input_len, Boolean final) { #if 1 - return SecCmsCipherContextLength(cc, (unsigned int)input_len, final, PR_TRUE); + return SecCmsCipherContextLength(cc, input_len, final, PR_TRUE); #else int blocks, block_size; int pad_size; @@ -763,39 +851,47 @@ SecCmsCipherContextEncryptLength(SecCmsCipherContextRef cc, size_t input_len, Bo static OSStatus SecCmsCipherContextCrypt(SecCmsCipherContextRef cc, unsigned char *output, - size_t *output_len_p, size_t max_output_len, - const unsigned char *input, size_t input_len, + unsigned int *output_len_p, unsigned int max_output_len, + const unsigned char *input, unsigned int input_len, Boolean final, Boolean encrypt) { - CSSM_DATA outputBuf = { max_output_len, output }; - CSSM_SIZE bytes_output = 0; + size_t bytes_output = 0; OSStatus rv = 0; if (input_len) { - CSSM_DATA inputBuf = { input_len, (uint8 *)input }; - if (encrypt) - rv = CSSM_EncryptDataUpdate(cc->cc, &inputBuf, 1, &outputBuf, 1, &bytes_output); - else - rv = CSSM_DecryptDataUpdate(cc->cc, &inputBuf, 1, &outputBuf, 1, &bytes_output); +#if USE_CDSA_CRYPTO + SecAsn1Item inputBuf = { input_len, (uint8_t *)input }; + SecAsn1Item outputBuf = { max_output_len, output }; + if (encrypt) + rv = CSSM_EncryptDataUpdate(cc->cc, &inputBuf, 1, &outputBuf, 1, &bytes_output); + else + rv = CSSM_DecryptDataUpdate(cc->cc, &inputBuf, 1, &outputBuf, 1, &bytes_output); +#else + rv = CCCryptorUpdate(cc->cc, input, input_len, output, max_output_len, &bytes_output); +#endif } if (!rv && final) { - CSSM_DATA remainderBuf = { max_output_len - bytes_output, output + bytes_output }; +#if USE_CDSA_CRYPTO + SecAsn1Item remainderBuf = { max_output_len - bytes_output, output + bytes_output }; if (encrypt) rv = CSSM_EncryptDataFinal(cc->cc, &remainderBuf); else rv = CSSM_DecryptDataFinal(cc->cc, &remainderBuf); - bytes_output += remainderBuf.Length; +#else + size_t bytes_output_final = 0; + rv = CCCryptorFinal(cc->cc, output+bytes_output, max_output_len-bytes_output, &bytes_output_final); + bytes_output += bytes_output_final; +#endif } - if (rv) PORT_SetError(SEC_ERROR_BAD_DATA); else if (output_len_p) - *output_len_p = bytes_output; + *output_len_p = (unsigned int)bytes_output; /* This cast is safe since bytes_output can't be bigger than max_output_len */ return rv; } @@ -832,8 +928,8 @@ SecCmsCipherContextCrypt(SecCmsCipherContextRef cc, unsigned char *output, */ OSStatus SecCmsCipherContextDecrypt(SecCmsCipherContextRef cc, unsigned char *output, - size_t *output_len_p, size_t max_output_len, - const unsigned char *input, size_t input_len, + unsigned int *output_len_p, unsigned int max_output_len, + const unsigned char *input, unsigned int input_len, Boolean final) { #if 1 @@ -1050,8 +1146,8 @@ SecCmsCipherContextDecrypt(SecCmsCipherContextRef cc, unsigned char *output, */ OSStatus SecCmsCipherContextEncrypt(SecCmsCipherContextRef cc, unsigned char *output, - size_t *output_len_p, size_t max_output_len, - const unsigned char *input, size_t input_len, + unsigned int *output_len_p, unsigned int max_output_len, + const unsigned char *input, unsigned int input_len, Boolean final) { #if 1 diff --git a/libsecurity_smime/lib/cmsdecode.c b/libsecurity_smime/lib/cmsdecode.c index f9ce1257..29f501c8 100644 --- a/libsecurity_smime/lib/cmsdecode.c +++ b/libsecurity_smime/lib/cmsdecode.c @@ -42,10 +42,14 @@ #include "cmslocal.h" -#include "secitem.h" +#include "SecAsn1Item.h" #include "secoid.h" + #include #include +#include + +#include struct SecCmsDecoderStr { SEC_ASN1DecoderContext * dcx; /* ASN.1 decoder context */ @@ -59,6 +63,8 @@ struct SecCmsDecoderStr { void * cb_arg; }; +/* We use size_t for len in this function because the SEC_ASN1Decoder* layer + uses that for callback function */ static void nss_cms_decoder_update_filter (void *arg, const char *data, size_t len, int depth, SEC_ASN1EncodingPart data_kind); static OSStatus nss_cms_before_data(SecCmsDecoderRef p7dcx); @@ -89,7 +95,7 @@ nss_cms_decoder_notify(void *arg, Boolean before, void *dest, int depth) /* XXX error handling: need to set p7dcx->error */ #ifdef CMSDEBUG - fprintf(stderr, "%6.6s, dest = %p, depth = %d\n", before ? "before" : "after", dest, depth); + fprintf(stderr, "%6.6s, dest = 0x%08x, depth = %d\n", before ? "before" : "after", dest, depth); #endif /* so what are we working on right now? */ @@ -110,7 +116,6 @@ nss_cms_decoder_notify(void *arg, Boolean before, void *dest, int depth) } break; case SEC_OID_PKCS7_DATA: - case SEC_OID_OTHER: /* this can only happen if the outermost cinfo has DATA in it */ /* otherwise, we handle this type implicitely in the inner decoders */ @@ -150,16 +155,16 @@ nss_cms_decoder_notify(void *arg, Boolean before, void *dest, int depth) /* please give me C++ */ switch (p7dcx->type) { case SEC_OID_PKCS7_SIGNED_DATA: - p7dcx->content.signedData->cmsg = p7dcx->cmsg; + p7dcx->content.signedData->contentInfo.cmsg = p7dcx->cmsg; break; case SEC_OID_PKCS7_DIGESTED_DATA: - p7dcx->content.digestedData->cmsg = p7dcx->cmsg; + p7dcx->content.digestedData->contentInfo.cmsg = p7dcx->cmsg; break; case SEC_OID_PKCS7_ENVELOPED_DATA: - p7dcx->content.envelopedData->cmsg = p7dcx->cmsg; + p7dcx->content.envelopedData->contentInfo.cmsg = p7dcx->cmsg; break; case SEC_OID_PKCS7_ENCRYPTED_DATA: - p7dcx->content.encryptedData->cmsg = p7dcx->cmsg; + p7dcx->content.encryptedData->contentInfo.cmsg = p7dcx->cmsg; break; default: PORT_Assert(0); @@ -249,13 +254,8 @@ nss_cms_before_data(SecCmsDecoderRef p7dcx) cinfo = SecCmsContentGetContentInfo(p7dcx->content.pointer, p7dcx->type); childtype = SecCmsContentInfoGetContentTypeTag(cinfo); - - /* special case for SignedData: "unknown" child type maps to SEC_OID_OTHER */ - if((childtype == SEC_OID_UNKNOWN) && (p7dcx->type == SEC_OID_PKCS7_SIGNED_DATA)) { - childtype = SEC_OID_OTHER; - } - - if ((childtype == SEC_OID_PKCS7_DATA) || (childtype == SEC_OID_OTHER)){ + + if (childtype == SEC_OID_PKCS7_DATA) { cinfo->content.data = SECITEM_AllocItem(poolp, NULL, 0); if (cinfo->content.data == NULL) /* set memory error */ @@ -282,9 +282,6 @@ nss_cms_before_data(SecCmsDecoderRef p7dcx) if (childp7dcx->content.pointer == NULL) goto loser; - /* Apple: link the new content to parent ContentInfo */ - cinfo->content.pointer = childp7dcx->content.pointer; - /* start the child decoder */ childp7dcx->dcx = SEC_ASN1DecoderStart(poolp, childp7dcx->content.pointer, template, NULL); if (childp7dcx->dcx == NULL) @@ -324,12 +321,9 @@ loser: static OSStatus nss_cms_after_data(SecCmsDecoderRef p7dcx) { - PLArenaPool *poolp; SecCmsDecoderRef childp7dcx; OSStatus rv = SECFailure; - poolp = p7dcx->cmsg->poolp; - /* Handle last block. This is necessary to flush out the last bytes * of a possibly incomplete block */ nss_cms_decoder_work_data(p7dcx, NULL, 0, PR_TRUE); @@ -421,10 +415,10 @@ nss_cms_decoder_work_data(SecCmsDecoderRef p7dcx, SecCmsContentInfoRef cinfo; unsigned char *buf = NULL; unsigned char *dest; - CSSM_SIZE offset; + size_t offset; OSStatus rv; - CSSM_DATA_PTR storage; - + SecAsn1Item * storage; + /* * We should really have data to process, or we should be trying * to finish/flush the last block. (This is an overly paranoid @@ -433,6 +427,8 @@ nss_cms_decoder_work_data(SecCmsDecoderRef p7dcx, * modifications/development, that is why it is here.) */ PORT_Assert ((data != NULL && len) || final); + /* Debug check for 64 bits cast later */ + PORT_Assert (len <= UINT_MAX); if (!p7dcx->content.pointer) // might be ExContent?? return; @@ -449,11 +445,12 @@ nss_cms_decoder_work_data(SecCmsDecoderRef p7dcx, * sending the data back and they want to know that. */ - CSSM_SIZE outlen = 0; /* length of decrypted data */ - CSSM_SIZE buflen; /* length available for decrypted data */ + unsigned int outlen = 0; /* length of decrypted data */ + unsigned int buflen; /* length available for decrypted data */ /* find out about the length of decrypted data */ - buflen = SecCmsCipherContextDecryptLength(cinfo->ciphcx, len, final); + /* 64 bits cast: Worst case here is we may not decrypt the full CMS blob, if the blob is bigger than 4GB */ + buflen = SecCmsCipherContextDecryptLength(cinfo->ciphcx, (unsigned int)len, final); /* * it might happen that we did not provide enough data for a full @@ -485,13 +482,13 @@ nss_cms_decoder_work_data(SecCmsDecoderRef p7dcx, * keep track of incoming data */ rv = SecCmsCipherContextDecrypt(cinfo->ciphcx, buf, &outlen, buflen, - data, len, final); + data, (unsigned int)len, final); if (rv != SECSuccess) { p7dcx->error = PORT_GetError(); goto loser; } - PORT_Assert (final || outlen == buflen); + //PORT_Assert (final || outlen == buflen); /* swap decrypted data in */ data = buf; @@ -519,11 +516,7 @@ nss_cms_decoder_work_data(SecCmsDecoderRef p7dcx, #if 1 else #endif - switch(SecCmsContentInfoGetContentTypeTag(cinfo)) { - default: - break; - case SEC_OID_PKCS7_DATA: - case SEC_OID_OTHER: + if (SecCmsContentInfoGetContentTypeTag(cinfo) == SEC_OID_PKCS7_DATA) { /* store it in "inner" data item as well */ /* find the DATA item in the encapsulated cinfo and store it there */ storage = cinfo->content.data; @@ -562,6 +555,9 @@ loser: * all data processed by the ASN.1 decoder is also passed through here. * we pass the content bytes (as opposed to length and tag bytes) on to * nss_cms_decoder_work_data(). + * + * len has to be of type size_t because it is a callback to the + * SEC_ASN1Decoder layer */ static void nss_cms_decoder_update_filter (void *arg, const char *data, size_t len, @@ -586,8 +582,7 @@ nss_cms_decoder_update_filter (void *arg, const char *data, size_t len, * SecCmsDecoderCreate - set up decoding of a BER-encoded CMS message */ OSStatus -SecCmsDecoderCreate(SecArenaPoolRef pool, - SecCmsContentCallback cb, void *cb_arg, +SecCmsDecoderCreate(SecCmsContentCallback cb, void *cb_arg, PK11PasswordFunc pwfn, void *pwfn_arg, SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg, SecCmsDecoderRef *outDecoder) @@ -596,12 +591,11 @@ SecCmsDecoderCreate(SecArenaPoolRef pool, SecCmsMessageRef cmsg; OSStatus result; - cmsg = SecCmsMessageCreate(pool); + cmsg = SecCmsMessageCreate(); if (cmsg == NULL) goto loser; - SecCmsMessageSetEncodingParams(cmsg, pwfn, pwfn_arg, decrypt_key_cb, decrypt_key_cb_arg, - NULL, NULL); + SecCmsMessageSetEncodingParams(cmsg, pwfn, pwfn_arg, decrypt_key_cb, decrypt_key_cb_arg); p7dcx = (SecCmsDecoderRef)PORT_ZAlloc(sizeof(struct SecCmsDecoderStr)); if (p7dcx == NULL) { @@ -625,7 +619,7 @@ SecCmsDecoderCreate(SecArenaPoolRef pool, p7dcx->cb_arg = cb_arg; *outDecoder = p7dcx; - return noErr; + return errSecSuccess; loser: result = PORT_GetError(); @@ -689,13 +683,13 @@ SecCmsDecoderFinish(SecCmsDecoderRef p7dcx, SecCmsMessageRef *outMessage) if (p7dcx->dcx == NULL || SEC_ASN1DecoderFinish(p7dcx->dcx) != SECSuccess || nss_cms_after_end(p7dcx) != SECSuccess) { - SecCmsMessageDestroy(cmsg); /* needs to get rid of pool if it's ours */ + SecCmsMessageDestroy(cmsg); result = PORT_GetError(); goto loser; } *outMessage = cmsg; - result = noErr; + result = errSecSuccess; loser: PORT_Free(p7dcx); @@ -703,16 +697,16 @@ loser: } OSStatus -SecCmsMessageDecode(const CSSM_DATA *encodedMessage, +SecCmsMessageDecode(const SecAsn1Item *encodedMessage, SecCmsContentCallback cb, void *cb_arg, PK11PasswordFunc pwfn, void *pwfn_arg, SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg, SecCmsMessageRef *outMessage) { OSStatus result; - SecCmsDecoderRef decoder; + SecCmsDecoderRef decoder = NULL; - result = SecCmsDecoderCreate(NULL, cb, cb_arg, pwfn, pwfn_arg, decrypt_key_cb, decrypt_key_cb_arg, &decoder); + result = SecCmsDecoderCreate(cb, cb_arg, pwfn, pwfn_arg, decrypt_key_cb, decrypt_key_cb_arg, &decoder); if (result) goto loser; result = SecCmsDecoderUpdate(decoder, encodedMessage->Data, encodedMessage->Length); @@ -725,4 +719,3 @@ SecCmsMessageDecode(const CSSM_DATA *encodedMessage, loser: return result; } - diff --git a/libsecurity_smime/lib/cmsdigdata.c b/libsecurity_smime/lib/cmsdigdata.c index 8fb7d5e5..3d2efdad 100644 --- a/libsecurity_smime/lib/cmsdigdata.c +++ b/libsecurity_smime/lib/cmsdigdata.c @@ -42,10 +42,12 @@ #include "cmslocal.h" -#include "secitem.h" +#include "SecAsn1Item.h" #include "secoid.h" + #include #include +#include /* * SecCmsDigestedDataCreate - create a digestedData object (presumably for encoding) @@ -70,7 +72,7 @@ SecCmsDigestedDataCreate(SecCmsMessageRef cmsg, SECAlgorithmID *digestalg) if (digd == NULL) goto loser; - digd->cmsg = cmsg; + digd->contentInfo.cmsg = cmsg; if (SECOID_CopyAlgorithmID (poolp, &(digd->digestAlg), digestalg) != SECSuccess) goto loser; @@ -114,13 +116,13 @@ OSStatus SecCmsDigestedDataEncodeBeforeStart(SecCmsDigestedDataRef digd) { unsigned long version; - CSSM_DATA_PTR dummy; + SecAsn1Item * dummy; version = SEC_CMS_DIGESTED_DATA_VERSION_DATA; if (SecCmsContentInfoGetContentTypeTag(&(digd->contentInfo)) != SEC_OID_PKCS7_DATA) version = SEC_CMS_DIGESTED_DATA_VERSION_ENCAP; - dummy = SEC_ASN1EncodeInteger(digd->cmsg->poolp, &(digd->version), version); + dummy = SEC_ASN1EncodeInteger(digd->contentInfo.cmsg->poolp, &(digd->version), version); return (dummy == NULL) ? SECFailure : SECSuccess; } @@ -157,9 +159,12 @@ SecCmsDigestedDataEncodeAfterData(SecCmsDigestedDataRef digd) OSStatus rv = SECSuccess; /* did we have digest calculation going on? */ if (digd->contentInfo.digcx) { - rv = SecCmsDigestContextFinishSingle(digd->contentInfo.digcx, - (SecArenaPoolRef)digd->cmsg->poolp, &(digd->digest)); - /* error has been set by SecCmsDigestContextFinishSingle */ + SecAsn1Item data; + rv = SecCmsDigestContextFinishSingle(digd->contentInfo.digcx, &data); + if (rv == SECSuccess) + rv = SECITEM_CopyItem(digd->contentInfo.cmsg->poolp, &(digd->digest), &data); + if (rv == SECSuccess) + SecCmsDigestContextDestroy(digd->contentInfo.digcx); digd->contentInfo.digcx = NULL; } @@ -200,9 +205,12 @@ SecCmsDigestedDataDecodeAfterData(SecCmsDigestedDataRef digd) OSStatus rv = SECSuccess; /* did we have digest calculation going on? */ if (digd->contentInfo.digcx) { - rv = SecCmsDigestContextFinishSingle(digd->contentInfo.digcx, - (SecArenaPoolRef)digd->cmsg->poolp, &(digd->cdigest)); - /* error has been set by SecCmsDigestContextFinishSingle */ + SecAsn1Item data; + rv = SecCmsDigestContextFinishSingle(digd->contentInfo.digcx, &data); + if (rv == SECSuccess) + rv = SECITEM_CopyItem(digd->contentInfo.cmsg->poolp, &(digd->digest), &data); + if (rv == SECSuccess) + SecCmsDigestContextDestroy(digd->contentInfo.digcx); digd->contentInfo.digcx = NULL; } diff --git a/libsecurity_smime/lib/cmsdigest.c b/libsecurity_smime/lib/cmsdigest.c index edfe98e2..7e9c6b7f 100644 --- a/libsecurity_smime/lib/cmsdigest.c +++ b/libsecurity_smime/lib/cmsdigest.c @@ -34,22 +34,34 @@ /* * CMS digesting. */ +#include #include "cmslocal.h" -#include "secitem.h" +#include "SecAsn1Item.h" #include "secoid.h" #include -#include +#include -#include +#if USE_CDSA_CRYPTO +#include +#else +#include +#endif +#include "SecCmsDigestContext.h" struct SecCmsDigestContextStr { + PLArenaPool * poolp; Boolean saw_contents; - int digcnt; + int digcnt; +#if USE_CDSA_CRYPTO CSSM_CC_HANDLE * digobjs; +#else + void ** digobjs; +#endif + SECAlgorithmID ** digestalgs; }; /* @@ -59,21 +71,41 @@ struct SecCmsDigestContextStr { SecCmsDigestContextRef SecCmsDigestContextStartMultiple(SECAlgorithmID **digestalgs) { + PLArenaPool *poolp; SecCmsDigestContextRef cmsdigcx; +#if USE_CDSA_CRYPTO CSSM_CC_HANDLE digobj; +#else + void * digobj; +#endif int digcnt; int i; + poolp = PORT_NewArena(1024); + if (poolp == NULL) + goto loser; + digcnt = (digestalgs == NULL) ? 0 : SecCmsArrayCount((void **)digestalgs); - cmsdigcx = (SecCmsDigestContextRef)PORT_Alloc(sizeof(struct SecCmsDigestContextStr)); + cmsdigcx = (SecCmsDigestContextRef)PORT_ArenaAlloc(poolp, sizeof(struct SecCmsDigestContextStr)); if (cmsdigcx == NULL) return NULL; + cmsdigcx->poolp = poolp; if (digcnt > 0) { - cmsdigcx->digobjs = (CSSM_CC_HANDLE *)PORT_Alloc(digcnt * sizeof(CSSM_CC_HANDLE)); +#if USE_CDSA_CRYPTO + cmsdigcx->digobjs = (CSSM_CC_HANDLE *)PORT_ArenaAlloc(poolp, digcnt * sizeof(CSSM_CC_HANDLE)); + if (cmsdigcx->digobjs == NULL) + goto loser; +#else + cmsdigcx->digobjs = (void**)PORT_ArenaAlloc(poolp, digcnt * sizeof(void *)); if (cmsdigcx->digobjs == NULL) goto loser; +#endif + cmsdigcx->digestalgs = (SECAlgorithmID **)PORT_ArenaZAlloc(poolp, + (digcnt + 1) * sizeof(SECAlgorithmID *)); + if (cmsdigcx->digestalgs == NULL) + goto loser; } cmsdigcx->digcnt = 0; @@ -91,17 +123,21 @@ SecCmsDigestContextStartMultiple(SECAlgorithmID **digestalgs) * the particular algorithm may not actually be important, * but we cannot know that until later. */ +#if USE_CDSA_CRYPTO if (digobj) - { - CSSM_RETURN result; - result = CSSM_DigestDataInit(digobj); - if (result != CSSM_OK) - { - goto loser; - } - } - + if (CSSM_DigestDataInit(digobj)) + goto loser; +#endif + cmsdigcx->digobjs[cmsdigcx->digcnt] = digobj; + cmsdigcx->digestalgs[cmsdigcx->digcnt] = PORT_ArenaAlloc(poolp, sizeof(SECAlgorithmID)); + if (SECITEM_CopyItem(poolp, + &(cmsdigcx->digestalgs[cmsdigcx->digcnt]->algorithm), + &(digestalgs[i]->algorithm)) + || SECITEM_CopyItem(poolp, + &(cmsdigcx->digestalgs[cmsdigcx->digcnt]->parameters), + &(digestalgs[i]->parameters))) + goto loser; cmsdigcx->digcnt++; } @@ -110,10 +146,9 @@ SecCmsDigestContextStartMultiple(SECAlgorithmID **digestalgs) return cmsdigcx; loser: - if (cmsdigcx) { - if (cmsdigcx->digobjs) - PORT_Free(cmsdigcx->digobjs); - } + if (poolp) + PORT_FreeArena(poolp, PR_FALSE); + return NULL; } @@ -136,15 +171,35 @@ SecCmsDigestContextStartSingle(SECAlgorithmID *digestalg) void SecCmsDigestContextUpdate(SecCmsDigestContextRef cmsdigcx, const unsigned char *data, size_t len) { - CSSM_DATA dataBuf; + SecAsn1Item dataBuf; int i; dataBuf.Length = len; - dataBuf.Data = (uint8 *)data; + dataBuf.Data = (uint8_t *)data; cmsdigcx->saw_contents = PR_TRUE; - for (i = 0; i < cmsdigcx->digcnt; i++) - if (cmsdigcx->digobjs[i]) + for (i = 0; i < cmsdigcx->digcnt; i++) { + if (cmsdigcx->digobjs[i]) { +#if USE_CDSA_CRYPTO CSSM_DigestDataUpdate(cmsdigcx->digobjs[i], &dataBuf, 1); +#else + /* 64 bits cast: worst case is we truncate the length and we dont hash all the data. + This may cause an invalid CMS blob larger than 4GB to be validated. Unlikely, but + possible security issue. There is no way to return an error here, but a check at + the upper level may happen. */ + assert(len<=UINT32_MAX); /* Debug check. Correct as long as CC_LONG is uint32_t */ + switch (SECOID_GetAlgorithmTag(cmsdigcx->digestalgs[i])) { + case SEC_OID_SHA1: CC_SHA1_Update((CC_SHA1_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; + case SEC_OID_MD5: CC_MD5_Update((CC_MD5_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; + case SEC_OID_SHA224: CC_SHA224_Update((CC_SHA256_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; + case SEC_OID_SHA256: CC_SHA256_Update((CC_SHA256_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; + case SEC_OID_SHA384: CC_SHA384_Update((CC_SHA512_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; + case SEC_OID_SHA512: CC_SHA512_Update((CC_SHA512_CTX *)cmsdigcx->digobjs[i], data, (CC_LONG)len); break; + default: + break; + } +#endif + } + } } /* @@ -157,92 +212,139 @@ SecCmsDigestContextCancel(SecCmsDigestContextRef cmsdigcx) for (i = 0; i < cmsdigcx->digcnt; i++) if (cmsdigcx->digobjs[i]) +#if USE_CDSA_CRYPTO CSSM_DeleteContext(cmsdigcx->digobjs[i]); +#else + free(cmsdigcx->digobjs[i]); +#endif + + PORT_FreeArena(cmsdigcx->poolp, PR_FALSE); } /* - * SecCmsDigestContextFinishMultiple - finish the digests and put them - * into an array of CSSM_DATAs (allocated on poolp) + * SecCmsDigestContextDestroy - delete a digesting operation + */ +void +SecCmsDigestContextDestroy(SecCmsDigestContextRef cmsdigcx) +{ + SecCmsDigestContextCancel(cmsdigcx); +} + +/* + * SecCmsDigestContextFinishMultiple - finish the digests */ OSStatus -SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, SecArenaPoolRef poolp, - CSSM_DATA_PTR **digestsp) +SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, + SECAlgorithmID ***digestalgsp, + SecAsn1Item * **digestsp) { - CSSM_CC_HANDLE digobj; - CSSM_DATA_PTR *digests, digest; +#if USE_CDSA_CRYPTO + CSSM_CC_HANDLE digboj; +#else + void * digobj; +#endif + SecAsn1Item **digests, *digest; + SECAlgorithmID **digestalgs; int i; void *mark; OSStatus rv = SECFailure; + assert(cmsdigcx != NULL); + + /* A message with no contents (just signed attributes) is used within SCEP */ +#if 0 /* no contents? do not update digests */ if (digestsp == NULL || !cmsdigcx->saw_contents) { for (i = 0; i < cmsdigcx->digcnt; i++) if (cmsdigcx->digobjs[i]) +#if USE_CDSA_CRYPTO CSSM_DeleteContext(cmsdigcx->digobjs[i]); +#else + free(cmsdigcx->digobjs[i]); +#endif rv = SECSuccess; if (digestsp) *digestsp = NULL; goto cleanup; } +#endif + + assert(digestsp != NULL); + assert(digestalgsp != NULL); - mark = PORT_ArenaMark ((PLArenaPool *)poolp); + mark = PORT_ArenaMark (cmsdigcx->poolp); - /* allocate digest array & CSSM_DATAs on arena */ - digests = (CSSM_DATA_PTR *)PORT_ArenaAlloc((PLArenaPool *)poolp, (cmsdigcx->digcnt+1) * sizeof(CSSM_DATA_PTR)); - digest = (CSSM_DATA_PTR)PORT_ArenaZAlloc((PLArenaPool *)poolp, cmsdigcx->digcnt * sizeof(CSSM_DATA)); - if (digests == NULL || digest == NULL) { + /* allocate digest array & SecAsn1Items on arena */ + digestalgs = (SECAlgorithmID **)PORT_ArenaZAlloc(cmsdigcx->poolp, (cmsdigcx->digcnt+1) * sizeof(SECAlgorithmID *)); + digests = (SecAsn1Item * *)PORT_ArenaZAlloc(cmsdigcx->poolp, (cmsdigcx->digcnt+1) * sizeof(SecAsn1Item *)); + digest = (SecAsn1Item *)PORT_ArenaZAlloc(cmsdigcx->poolp, cmsdigcx->digcnt * sizeof(SecAsn1Item)); + if (digestalgs == NULL || digests == NULL || digest == NULL) { goto loser; } for (i = 0; i < cmsdigcx->digcnt; i++, digest++) { - digobj = cmsdigcx->digobjs[i]; - CSSM_QUERY_SIZE_DATA dataSize; - rv = CSSM_QuerySize(digobj, CSSM_FALSE, 1, &dataSize); - if (rv != CSSM_OK) - { - goto loser; + + SECOidTag hash_alg = SECOID_GetAlgorithmTag(cmsdigcx->digestalgs[i]); + int diglength = 0; + + switch (hash_alg) { + case SEC_OID_SHA1: diglength = CC_SHA1_DIGEST_LENGTH; break; + case SEC_OID_MD5: diglength = CC_MD5_DIGEST_LENGTH; break; + case SEC_OID_SHA224: diglength = CC_SHA224_DIGEST_LENGTH; break; + case SEC_OID_SHA256: diglength = CC_SHA256_DIGEST_LENGTH; break; + case SEC_OID_SHA384: diglength = CC_SHA384_DIGEST_LENGTH; break; + case SEC_OID_SHA512: diglength = CC_SHA512_DIGEST_LENGTH; break; + default: goto loser; break; } - int diglength = dataSize.SizeOutputBlock; - + digobj = cmsdigcx->digobjs[i]; if (digobj) { - digest->Data = (unsigned char*)PORT_ArenaAlloc((PLArenaPool *)poolp, diglength); + digest->Data = (unsigned char*)PORT_ArenaAlloc(cmsdigcx->poolp, diglength); if (digest->Data == NULL) goto loser; digest->Length = diglength; - rv = CSSM_DigestDataFinal(digobj, digest); - if (rv != CSSM_OK) - { - goto loser; - } - +#if USE_CDSA_CRYPTO + CSSM_DigestDataFinal(digobj, digest); CSSM_DeleteContext(digobj); +#else + switch (hash_alg) { + case SEC_OID_SHA1: CC_SHA1_Final(digest->Data, digobj); break; + case SEC_OID_MD5: CC_MD5_Final(digest->Data, digobj); break; + case SEC_OID_SHA224: CC_SHA224_Final(digest->Data, digobj); break; + case SEC_OID_SHA256: CC_SHA256_Final(digest->Data, digobj); break; + case SEC_OID_SHA384: CC_SHA384_Final(digest->Data, digobj); break; + case SEC_OID_SHA512: CC_SHA512_Final(digest->Data, digobj); break; + default: goto loser; break; + } + + free(digobj); +#endif + digestalgs[i] = cmsdigcx->digestalgs[i]; + digests[i] = digest; } else { digest->Data = NULL; digest->Length = 0; } - - digests[i] = digest; - } + } + digestalgs[i] = NULL; digests[i] = NULL; + *digestalgsp = digestalgs; *digestsp = digests; rv = SECSuccess; loser: if (rv == SECSuccess) - PORT_ArenaUnmark((PLArenaPool *)poolp, mark); + PORT_ArenaUnmark(cmsdigcx->poolp, mark); else - PORT_ArenaRelease((PLArenaPool *)poolp, mark); + PORT_ArenaRelease(cmsdigcx->poolp, mark); -cleanup: - if (cmsdigcx->digcnt > 0) { - PORT_Free(cmsdigcx->digobjs); - } - PORT_Free(cmsdigcx); +/*cleanup:*/ + /* Set things up so SecCmsDigestContextDestroy won't call CSSM_DeleteContext again. */ + cmsdigcx->digcnt = 0; return rv; } @@ -252,29 +354,22 @@ cleanup: * but for one digest. */ OSStatus -SecCmsDigestContextFinishSingle(SecCmsDigestContextRef cmsdigcx, SecArenaPoolRef poolp, - CSSM_DATA_PTR digest) +SecCmsDigestContextFinishSingle(SecCmsDigestContextRef cmsdigcx, + SecAsn1Item * digest) { OSStatus rv = SECFailure; - CSSM_DATA_PTR *dp; - PLArenaPool *arena = NULL; - - if ((arena = PORT_NewArena(1024)) == NULL) - goto loser; + SecAsn1Item * *dp; + SECAlgorithmID **ap; /* get the digests into arena, then copy the first digest into poolp */ - if (SecCmsDigestContextFinishMultiple(cmsdigcx, (SecArenaPoolRef)arena, &dp) != SECSuccess) + if (SecCmsDigestContextFinishMultiple(cmsdigcx, &ap, &dp) != SECSuccess) goto loser; - /* now copy it into poolp */ - if (SECITEM_CopyItem((PLArenaPool *)poolp, digest, dp[0]) != SECSuccess) - goto loser; + /* Return the first element in the digest array. */ + digest = *dp; rv = SECSuccess; loser: - if (arena) - PORT_FreeArena(arena, PR_FALSE); - return rv; } diff --git a/libsecurity_smime/lib/cmsencdata.c b/libsecurity_smime/lib/cmsencdata.c index 895b5085..3e2a2372 100644 --- a/libsecurity_smime/lib/cmsencdata.c +++ b/libsecurity_smime/lib/cmsencdata.c @@ -41,10 +41,12 @@ #include "cmslocal.h" -#include "secitem.h" +#include "SecAsn1Item.h" #include "secoid.h" + #include #include +#include /* * SecCmsEncryptedDataCreate - create an empty encryptedData object. @@ -72,16 +74,19 @@ SecCmsEncryptedDataCreate(SecCmsMessageRef cmsg, SECOidTag algorithm, int keysiz if (encd == NULL) goto loser; - encd->cmsg = cmsg; + encd->contentInfo.cmsg = cmsg; /* version is set in SecCmsEncryptedDataEncodeBeforeStart() */ switch (algorithm) { /* XXX hmmm... hardcoded algorithms? */ + case SEC_OID_AES_128_CBC: + case SEC_OID_AES_192_CBC: + case SEC_OID_AES_256_CBC: case SEC_OID_RC2_CBC: case SEC_OID_DES_EDE3_CBC: case SEC_OID_DES_CBC: - rv = SecCmsContentInfoSetContentEncAlg((SecArenaPoolRef)poolp, &(encd->contentInfo), algorithm, NULL, keysize); + rv = SecCmsContentInfoSetContentEncAlg(&(encd->contentInfo), algorithm, NULL, keysize); break; default: /* Assume password-based-encryption. At least, try that. */ @@ -95,7 +100,7 @@ SecCmsEncryptedDataCreate(SecCmsMessageRef cmsg, SECOidTag algorithm, int keysiz rv = SECFailure; break; } - rv = SecCmsContentInfoSetContentEncAlgID((SecArenaPoolRef)poolp, &(encd->contentInfo), pbe_algid, keysize); + rv = SecCmsContentInfoSetContentEncAlgID(&(encd->contentInfo), pbe_algid, keysize); SECOID_DestroyAlgorithmID (pbe_algid, PR_TRUE); break; } @@ -143,7 +148,7 @@ SecCmsEncryptedDataEncodeBeforeStart(SecCmsEncryptedDataRef encd) { int version; SecSymmetricKeyRef bulkkey = NULL; - CSSM_DATA_PTR dummy; + SecAsn1Item * dummy; SecCmsContentInfoRef cinfo = &(encd->contentInfo); if (SecCmsArrayIsEmpty((void **)encd->unprotectedAttr)) @@ -151,13 +156,13 @@ SecCmsEncryptedDataEncodeBeforeStart(SecCmsEncryptedDataRef encd) else version = SEC_CMS_ENCRYPTED_DATA_VERSION_UPATTR; - dummy = SEC_ASN1EncodeInteger (encd->cmsg->poolp, &(encd->version), version); + dummy = SEC_ASN1EncodeInteger (encd->contentInfo.cmsg->poolp, &(encd->version), version); if (dummy == NULL) return SECFailure; /* now get content encryption key (bulk key) by using our cmsg callback */ - if (encd->cmsg->decrypt_key_cb) - bulkkey = (*encd->cmsg->decrypt_key_cb)(encd->cmsg->decrypt_key_cb_arg, + if (encd->contentInfo.cmsg->decrypt_key_cb) + bulkkey = (*encd->contentInfo.cmsg->decrypt_key_cb)(encd->contentInfo.cmsg->decrypt_key_cb_arg, SecCmsContentInfoGetContentEncAlg(cinfo)); if (bulkkey == NULL) return SECFailure; @@ -192,7 +197,7 @@ SecCmsEncryptedDataEncodeBeforeData(SecCmsEncryptedDataRef encd) /* this may modify algid (with IVs generated in a token). * it is therefore essential that algid is a pointer to the "real" contentEncAlg, * not just to a copy */ - cinfo->ciphcx = SecCmsCipherContextStartEncrypt(encd->cmsg->poolp, bulkkey, algid); + cinfo->ciphcx = SecCmsCipherContextStartEncrypt(encd->contentInfo.cmsg->poolp, bulkkey, algid); CFRelease(bulkkey); if (cinfo->ciphcx == NULL) return SECFailure; @@ -231,10 +236,10 @@ SecCmsEncryptedDataDecodeBeforeData(SecCmsEncryptedDataRef encd) bulkalg = SecCmsContentInfoGetContentEncAlg(cinfo); - if (encd->cmsg->decrypt_key_cb == NULL) /* no callback? no key../ */ + if (encd->contentInfo.cmsg->decrypt_key_cb == NULL) /* no callback? no key../ */ goto loser; - bulkkey = (*encd->cmsg->decrypt_key_cb)(encd->cmsg->decrypt_key_cb_arg, bulkalg); + bulkkey = (*encd->contentInfo.cmsg->decrypt_key_cb)(encd->contentInfo.cmsg->decrypt_key_cb_arg, bulkalg); if (bulkkey == NULL) /* no success finding a bulk key */ goto loser; diff --git a/libsecurity_smime/lib/cmsencode.c b/libsecurity_smime/lib/cmsencode.c index cdc85699..61638f26 100644 --- a/libsecurity_smime/lib/cmsencode.c +++ b/libsecurity_smime/lib/cmsencode.c @@ -43,17 +43,20 @@ #include "cmslocal.h" #include "secoid.h" -#include "secitem.h" +#include "SecAsn1Item.h" #include #include -#include +#include + +#include + +#include struct nss_cms_encoder_output { SecCmsContentCallback outputfn; void *outputarg; - PLArenaPool *destpoolp; - CSSM_DATA_PTR dest; + CFMutableDataRef berData; }; struct SecCmsEncoderStr { @@ -69,8 +72,8 @@ struct SecCmsEncoderStr { static OSStatus nss_cms_before_data(SecCmsEncoderRef p7ecx); static OSStatus nss_cms_after_data(SecCmsEncoderRef p7ecx); -static OSStatus nss_cms_encoder_update(SecCmsEncoderRef p7ecx, const char *data, size_t len); -static OSStatus nss_cms_encoder_work_data(SecCmsEncoderRef p7ecx, CSSM_DATA_PTR dest, +static void nss_cms_encoder_update(void *arg, const char *data, size_t len); +static OSStatus nss_cms_encoder_work_data(SecCmsEncoderRef p7ecx, SecAsn1Item * dest, const unsigned char *data, size_t len, Boolean final, Boolean innermost); @@ -86,13 +89,11 @@ nss_cms_encoder_out(void *arg, const char *buf, size_t len, int depth, SEC_ASN1EncodingPart data_kind) { struct nss_cms_encoder_output *output = (struct nss_cms_encoder_output *)arg; - unsigned char *dest; - CSSM_SIZE offset; #ifdef CMSDEBUG - int i; + size_t i; - fprintf(stderr, "kind = %d, depth = %d, len = %lu\n", data_kind, depth, len); + fprintf(stderr, "kind = %d, depth = %d, len = %d\n", data_kind, depth, len); for (i=0; i < len; i++) { fprintf(stderr, " %02x%s", (unsigned int)buf[i] & 0xff, ((i % 16) == 15) ? "\n" : ""); } @@ -104,26 +105,9 @@ nss_cms_encoder_out(void *arg, const char *buf, size_t len, /* call output callback with DER data */ output->outputfn(output->outputarg, buf, len); - if (output->dest != NULL) { - /* store DER data in CSSM_DATA */ - offset = output->dest->Length; - if (offset == 0) { - dest = (unsigned char *)PORT_ArenaAlloc(output->destpoolp, len); - } else { - dest = (unsigned char *)PORT_ArenaGrow(output->destpoolp, - output->dest->Data, - output->dest->Length, - output->dest->Length + len); - } - if (dest == NULL) - /* oops */ - return; - - output->dest->Data = dest; - output->dest->Length += len; - - /* copy it in */ - PORT_Memcpy(output->dest->Data + offset, buf, len); + if (output->berData != NULL) { + /* store DER data in output->dest */ + CFDataAppendBytes(output->berData, (const UInt8 *)buf, len); } } @@ -142,7 +126,7 @@ nss_cms_encoder_notify(void *arg, Boolean before, void *dest, int depth) Boolean after = !before; PLArenaPool *poolp; SECOidTag childtype; - CSSM_DATA_PTR item; + SecAsn1Item * item; p7ecx = (SecCmsEncoderRef)arg; PORT_Assert(p7ecx != NULL); @@ -151,7 +135,7 @@ nss_cms_encoder_notify(void *arg, Boolean before, void *dest, int depth) poolp = p7ecx->cmsg->poolp; #ifdef CMSDEBUG - fprintf(stderr, "%6.6s, dest = %p, depth = %d\n", before ? "before" : "after", dest, depth); + fprintf(stderr, "%6.6s, dest = 0x%08x, depth = %d\n", before ? "before" : "after", dest, depth); #endif /* @@ -171,7 +155,6 @@ nss_cms_encoder_notify(void *arg, Boolean before, void *dest, int depth) break; case SEC_OID_PKCS7_DATA: - case SEC_OID_OTHER: if (before && dest == &(rootcinfo->rawContent)) { /* just set up encoder to grab from user - no encryption or digesting */ if ((item = rootcinfo->content.data) != NULL) @@ -199,8 +182,7 @@ nss_cms_encoder_notify(void *arg, Boolean before, void *dest, int depth) p7ecx->error = PORT_GetError(); } if (before && dest == &(cinfo->rawContent)) { - if ( ((childtype == SEC_OID_PKCS7_DATA) || (childtype == SEC_OID_OTHER)) && - ((item = cinfo->content.data) != NULL)) + if (childtype == SEC_OID_PKCS7_DATA && (item = cinfo->content.data) != NULL) /* we have data - feed it in */ (void)nss_cms_encoder_work_data(p7ecx, NULL, item->Data, item->Length, PR_TRUE, PR_TRUE); else @@ -280,10 +262,9 @@ nss_cms_before_data(SecCmsEncoderRef p7ecx) childp7ecx->type = childtype; childp7ecx->content = cinfo->content; /* use the non-recursive update function here, of course */ - childp7ecx->output.outputfn = (SecCmsContentCallback)nss_cms_encoder_update; + childp7ecx->output.outputfn = nss_cms_encoder_update; childp7ecx->output.outputarg = p7ecx; - childp7ecx->output.destpoolp = NULL; - childp7ecx->output.dest = NULL; + childp7ecx->output.berData = NULL; childp7ecx->cmsg = p7ecx->cmsg; template = SecCmsUtilGetTemplateByTypeTag(childtype); @@ -305,7 +286,6 @@ nss_cms_before_data(SecCmsEncoderRef p7ecx) rv = SecCmsEncryptedDataEncodeBeforeStart(cinfo->content.encryptedData); break; case SEC_OID_PKCS7_DATA: - case SEC_OID_OTHER: rv = SECSuccess; break; default: @@ -351,7 +331,6 @@ nss_cms_before_data(SecCmsEncoderRef p7ecx) break; case SEC_OID_PKCS7_DATA: - case SEC_OID_OTHER: p7ecx->childp7ecx = NULL; break; default: @@ -391,7 +370,6 @@ nss_cms_after_data(SecCmsEncoderRef p7ecx) rv = SecCmsEncryptedDataEncodeAfterData(p7ecx->content.encryptedData); break; case SEC_OID_PKCS7_DATA: - case SEC_OID_OTHER: /* do nothing */ break; default: @@ -406,9 +384,10 @@ nss_cms_after_data(SecCmsEncoderRef p7ecx) * * (from the user or the next encoding layer) * Here, we need to digest and/or encrypt, then pass it on + * */ static OSStatus -nss_cms_encoder_work_data(SecCmsEncoderRef p7ecx, CSSM_DATA_PTR dest, +nss_cms_encoder_work_data(SecCmsEncoderRef p7ecx, SecAsn1Item * dest, const unsigned char *data, size_t len, Boolean final, Boolean innermost) { @@ -426,6 +405,7 @@ nss_cms_encoder_work_data(SecCmsEncoderRef p7ecx, CSSM_DATA_PTR dest, * modifications/development, that is why it is here.) */ PORT_Assert ((data != NULL && len) || final); + PORT_Assert (len < UINT_MAX); /* overflow check for later cast */ /* we got data (either from the caller, or from a lower level encoder) */ cinfo = SecCmsContentGetContentInfo(p7ecx->content.pointer, p7ecx->type); @@ -436,11 +416,15 @@ nss_cms_encoder_work_data(SecCmsEncoderRef p7ecx, CSSM_DATA_PTR dest, /* Encrypt this chunk. */ if (cinfo->ciphcx != NULL) { - CSSM_SIZE inlen; /* length of data being encrypted */ - CSSM_SIZE outlen; /* length of encrypted data */ - CSSM_SIZE buflen; /* length available for encrypted data */ + unsigned int inlen; /* length of data being encrypted */ + unsigned int outlen; /* length of encrypted data */ + unsigned int buflen; /* length available for encrypted data */ + + /* 64 bits cast: only an issue if unsigned int is smaller than size_t. + Worst case is you will truncate a CMS blob bigger than 4GB when + encrypting */ + inlen = (unsigned int)len; - inlen = len; buflen = SecCmsCipherContextEncryptLength(cinfo->ciphcx, inlen, final); if (buflen == 0) { /* @@ -501,11 +485,13 @@ done: * * no recursion here because we REALLY want to end up at the next higher encoder! */ -static OSStatus -nss_cms_encoder_update(SecCmsEncoderRef p7ecx, const char *data, size_t len) +static void +nss_cms_encoder_update(void *arg, const char *data, size_t len) { /* XXX Error handling needs help. Return what? Do "Finish" on failure? */ - return nss_cms_encoder_work_data (p7ecx, NULL, (const unsigned char *)data, len, PR_FALSE, PR_FALSE); + SecCmsEncoderRef p7ecx = (SecCmsEncoderRef)arg; + + (void)nss_cms_encoder_work_data (p7ecx, NULL, (const unsigned char *)data, len, PR_FALSE, PR_FALSE); } /* @@ -514,7 +500,7 @@ nss_cms_encoder_update(SecCmsEncoderRef p7ecx, const char *data, size_t len) * "cmsg" - message to encode * "outputfn", "outputarg" - callback function for delivery of DER-encoded output * will not be called if NULL. - * "dest" - if non-NULL, pointer to CSSM_DATA that will hold the DER-encoded output + * "dest" - if non-NULL, pointer to SecAsn1Item that will hold the DER-encoded output * "destpoolp" - pool to allocate DER-encoded output in * "pwfn", pwfn_arg" - callback function for getting token password * "decrypt_key_cb", "decrypt_key_cb_arg" - callback function for getting bulk key for encryptedData @@ -523,30 +509,28 @@ nss_cms_encoder_update(SecCmsEncoderRef p7ecx, const char *data, size_t len) OSStatus SecCmsEncoderCreate(SecCmsMessageRef cmsg, SecCmsContentCallback outputfn, void *outputarg, - CSSM_DATA_PTR dest, SecArenaPoolRef destpool, + CFMutableDataRef outBer, PK11PasswordFunc pwfn, void *pwfn_arg, SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg, - SECAlgorithmID **detached_digestalgs, CSSM_DATA_PTR *detached_digests, SecCmsEncoderRef *outEncoder) { SecCmsEncoderRef p7ecx; OSStatus result; SecCmsContentInfoRef cinfo; - SecCmsMessageSetEncodingParams(cmsg, pwfn, pwfn_arg, decrypt_key_cb, decrypt_key_cb_arg, - detached_digestalgs, detached_digests); + SecCmsMessageSetEncodingParams(cmsg, pwfn, pwfn_arg, decrypt_key_cb, decrypt_key_cb_arg); p7ecx = (SecCmsEncoderRef)PORT_ZAlloc(sizeof(struct SecCmsEncoderStr)); if (p7ecx == NULL) { - result = memFullErr; + result = errSecAllocate; goto loser; } p7ecx->cmsg = cmsg; p7ecx->output.outputfn = outputfn; p7ecx->output.outputarg = outputarg; - p7ecx->output.dest = dest; - p7ecx->output.destpoolp = (PLArenaPool *)destpool; + p7ecx->output.berData = outBer; + p7ecx->type = SEC_OID_UNKNOWN; cinfo = SecCmsMessageGetContentInfo(cmsg); @@ -566,7 +550,7 @@ SecCmsEncoderCreate(SecCmsMessageRef cmsg, break; default: /* @@@ We need a better error for unsupported message types. */ - result = paramErr; + result = errSecParam; break; } if (result) @@ -637,11 +621,11 @@ SecCmsEncoderUpdate(SecCmsEncoderRef p7ecx, const void *data, CFIndex len) /* find out about our inner content type - must be data */ cinfo = SecCmsContentGetContentInfo(p7ecx->content.pointer, p7ecx->type); childtype = SecCmsContentInfoGetContentTypeTag(cinfo); - if ((childtype != SEC_OID_PKCS7_DATA) && (childtype != SEC_OID_OTHER)) - return paramErr; /* @@@ Maybe come up with a better error? */ + if (childtype != SEC_OID_PKCS7_DATA) + return errSecParam; /* @@@ Maybe come up with a better error? */ /* and we must not have preset data */ if (cinfo->content.data != NULL) - return paramErr; /* @@@ Maybe come up with a better error? */ + return errSecParam; /* @@@ Maybe come up with a better error? */ /* hand it the data so it can encode it (let DER trickle up the chain) */ result = nss_cms_encoder_work_data(p7ecx, NULL, (const unsigned char *)data, len, PR_FALSE, PR_TRUE); @@ -735,8 +719,7 @@ SecCmsEncoderFinish(SecCmsEncoderRef p7ecx) /* find out about our inner content type - must be data */ cinfo = SecCmsContentGetContentInfo(p7ecx->content.pointer, p7ecx->type); childtype = SecCmsContentInfoGetContentTypeTag(cinfo); - if ( ((childtype == SEC_OID_PKCS7_DATA) || (childtype == SEC_OID_OTHER)) && - (cinfo->content.data == NULL)) { + if (childtype == SEC_OID_PKCS7_DATA && cinfo->content.data == NULL) { SEC_ASN1EncoderClearTakeFromBuf(p7ecx->ecx); /* now that TakeFromBuf is off, this will kick this encoder to finish encoding */ result = SEC_ASN1EncoderUpdate(p7ecx->ecx, NULL, 0); @@ -756,18 +739,18 @@ loser: } OSStatus -SecCmsMessageEncode(SecCmsMessageRef cmsg, const CSSM_DATA *input, SecArenaPoolRef arena, - CSSM_DATA_PTR outBer) +SecCmsMessageEncode(SecCmsMessageRef cmsg, const SecAsn1Item *input, + CFMutableDataRef outBer) { - SecCmsEncoderRef encoder; + SecCmsEncoderRef encoder = NULL; OSStatus result; - if (!cmsg || !outBer || !arena) { - result = paramErr; + if (!cmsg || !outBer) { + result = errSecParam; goto loser; } - result = SecCmsEncoderCreate(cmsg, 0, 0, outBer, arena, 0, 0, 0, 0, 0, 0, &encoder); + result = SecCmsEncoderCreate(cmsg, 0, 0, outBer, 0, 0, 0, 0, &encoder); if (result) goto loser; diff --git a/libsecurity_smime/lib/cmsenvdata.c b/libsecurity_smime/lib/cmsenvdata.c index fad65434..b7ccbdd6 100644 --- a/libsecurity_smime/lib/cmsenvdata.c +++ b/libsecurity_smime/lib/cmsenvdata.c @@ -39,16 +39,22 @@ #include #include +#include #include "cmslocal.h" -#include "secitem.h" +#include "SecAsn1Item.h" #include "secoid.h" #include "cryptohi.h" #include #include +#include + #include +#include + +#include /* * SecCmsEnvelopedDataCreate - create an enveloped data message @@ -69,11 +75,11 @@ SecCmsEnvelopedDataCreate(SecCmsMessageRef cmsg, SECOidTag algorithm, int keysiz if (envd == NULL) goto loser; - envd->cmsg = cmsg; + envd->contentInfo.cmsg = cmsg; /* version is set in SecCmsEnvelopedDataEncodeBeforeStart() */ - rv = SecCmsContentInfoSetContentEncAlg((SecArenaPoolRef)poolp, &(envd->contentInfo), algorithm, NULL, keysize); + rv = SecCmsContentInfoSetContentEncAlg(&(envd->contentInfo), algorithm, NULL, keysize); if (rv != SECSuccess) goto loser; @@ -133,15 +139,15 @@ SecCmsEnvelopedDataAddRecipient(SecCmsEnvelopedDataRef edp, SecCmsRecipientInfoR PR_ASSERT(edp != NULL); PR_ASSERT(rip != NULL); - mark = PORT_ArenaMark(edp->cmsg->poolp); + mark = PORT_ArenaMark(edp->contentInfo.cmsg->poolp); - rv = SecCmsArrayAdd(edp->cmsg->poolp, (void ***)&(edp->recipientInfos), (void *)rip); + rv = SecCmsArrayAdd(edp->contentInfo.cmsg->poolp, (void ***)&(edp->recipientInfos), (void *)rip); if (rv != SECSuccess) { - PORT_ArenaRelease(edp->cmsg->poolp, mark); + PORT_ArenaRelease(edp->contentInfo.cmsg->poolp, mark); return SECFailure; } - PORT_ArenaUnmark (edp->cmsg->poolp, mark); + PORT_ArenaUnmark (edp->contentInfo.cmsg->poolp, mark); return SECSuccess; } @@ -164,19 +170,21 @@ SecCmsEnvelopedDataEncodeBeforeStart(SecCmsEnvelopedDataRef envd) SecCmsRecipientInfoRef *recipientinfos; SecCmsContentInfoRef cinfo; SecSymmetricKeyRef bulkkey = NULL; - CSSM_ALGORITHMS algorithm; +#if USE_CDSA_CRYPTO + SecAsn1AlgId algorithm; +#endif SECOidTag bulkalgtag; //CK_MECHANISM_TYPE type; //PK11SlotInfo *slot; OSStatus rv; - CSSM_DATA_PTR dummy; + SecAsn1Item * dummy; PLArenaPool *poolp; extern const SecAsn1Template SecCmsRecipientInfoTemplate[]; void *mark = NULL; int i; - poolp = envd->cmsg->poolp; cinfo = &(envd->contentInfo); + poolp = cinfo->cmsg->poolp; recipientinfos = envd->recipientInfos; if (recipientinfos == NULL) { @@ -207,12 +215,13 @@ SecCmsEnvelopedDataEncodeBeforeStart(SecCmsEnvelopedDataRef envd) * we cannot do that on our level, so if none is set already, we'll just go * with one of the mandatory algorithms (3DES) */ if ((bulkalgtag = SecCmsContentInfoGetContentEncAlgTag(cinfo)) == SEC_OID_UNKNOWN) { - rv = SecCmsContentInfoSetContentEncAlg((SecArenaPoolRef)poolp, cinfo, SEC_OID_DES_EDE3_CBC, NULL, 168); + rv = SecCmsContentInfoSetContentEncAlg(cinfo, SEC_OID_DES_EDE3_CBC, NULL, 192); if (rv != SECSuccess) goto loser; bulkalgtag = SEC_OID_DES_EDE3_CBC; } +#if USE_CDSA_CRYPTO algorithm = SECOID_FindyCssmAlgorithmByTag(bulkalgtag); if (!algorithm) goto loser; @@ -226,6 +235,14 @@ SecCmsEnvelopedDataEncodeBeforeStart(SecCmsEnvelopedDataRef envd) &bulkkey); if (rv) goto loser; +#else + { + size_t keysize = (cinfo->keysize + 7)/8; + uint8_t key_material[keysize]; + require_noerr(SecRandomCopyBytes(kSecRandomDefault, keysize, key_material), loser); + bulkkey = (SecSymmetricKeyRef)CFDataCreate(kCFAllocatorDefault, key_material, keysize); + } +#endif mark = PORT_ArenaMark(poolp); @@ -286,7 +303,7 @@ SecCmsEnvelopedDataEncodeBeforeData(SecCmsEnvelopedDataRef envd) /* this may modify algid (with IVs generated in a token). * it is essential that algid is a pointer to the contentEncAlg data, not a * pointer to a copy! */ - cinfo->ciphcx = SecCmsCipherContextStartEncrypt(envd->cmsg->poolp, bulkkey, algid); + cinfo->ciphcx = SecCmsCipherContextStartEncrypt(cinfo->cmsg->poolp, bulkkey, algid); CFRelease(bulkkey); if (cinfo->ciphcx == NULL) return SECFailure; @@ -340,11 +357,12 @@ SecCmsEnvelopedDataDecodeBeforeData(SecCmsEnvelopedDataRef envd) if (recipient_list == NULL) goto loser; + cinfo = &(envd->contentInfo); /* what about multiple recipientInfos that match? * especially if, for some reason, we could not produce a bulk key with the first match?! * we could loop & feed partial recipient_list to PK11_FindCertAndKeyByRecipientList... * maybe later... */ - rlIndex = nss_cms_FindCertAndKeyByRecipientList(recipient_list, envd->cmsg->pwfn_arg); + rlIndex = nss_cms_FindCertAndKeyByRecipientList(recipient_list, cinfo->cmsg->pwfn_arg); /* if that fails, then we're not an intended recipient and cannot decrypt */ if (rlIndex < 0) { @@ -363,7 +381,6 @@ SecCmsEnvelopedDataDecodeBeforeData(SecCmsEnvelopedDataRef envd) /* get a pointer to "our" recipientinfo */ ri = envd->recipientInfos[recipient->riIndex]; - cinfo = &(envd->contentInfo); bulkalgtag = SecCmsContentInfoGetContentEncAlgTag(cinfo); if (bulkalgtag == SEC_OID_UNKNOWN) { PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); @@ -374,12 +391,11 @@ SecCmsEnvelopedDataDecodeBeforeData(SecCmsEnvelopedDataRef envd) bulkalgtag); if (bulkkey == NULL) { /* no success finding a bulk key */ - rv = errSecDataNotAvailable; goto loser; } SecCmsContentInfoSetBulkKey(cinfo, bulkkey); - // @@@ See 3401088 for details. We need to CFRelease cinfo->bulkkey before recipient->privkey gets CFReleased. It's created with SecKeyCreateWithCSSMKey which is not safe currently. If the private key's SecKeyRef from which we extracted the CSP gets CFRelease before the builkkey does we crash. We should really fix SecKeyCreateWithCSSMKey which is a huge hack currently. To work around this we add recipient->privkey to the cinfo so it gets when cinfo is destroyed. + // @@@ See 3401088 for details. We need to CFRelease cinfo->bulkkey before recipient->privkey gets CFReleased. It's created with SecKeyCreate which is not safe currently. If the private key's SecKeyRef from which we extracted the CSP gets CFRelease before the builkkey does we crash. We should really fix SecKeyCreate which is a huge hack currently. To work around this we add recipient->privkey to the cinfo so it gets when cinfo is destroyed. CFRetain(recipient->privkey); cinfo->privkey = recipient->privkey; diff --git a/libsecurity_smime/lib/cmslocal.h b/libsecurity_smime/lib/cmslocal.h index abda2456..4c737193 100644 --- a/libsecurity_smime/lib/cmslocal.h +++ b/libsecurity_smime/lib/cmslocal.h @@ -49,6 +49,7 @@ extern const SecAsn1Template SecCmsIssuerAndSNTemplate[]; extern const SecAsn1Template SecCmsContentInfoTemplate[]; +extern const SecAsn1Template *nss_cms_get_kea_template(SecCmsKEATemplateSelector whichTemplate); /************************************************************************/ SEC_BEGIN_PROTOS @@ -88,8 +89,8 @@ SecCmsCipherContextDestroy(SecCmsCipherContextRef cc); * we see the data we do not know how many padding bytes there are * (always between 1 and bsize). */ -extern size_t -SecCmsCipherContextDecryptLength(SecCmsCipherContextRef cc, size_t input_len, Boolean final); +extern unsigned int +SecCmsCipherContextDecryptLength(SecCmsCipherContextRef cc, unsigned int input_len, Boolean final); /* * SecCmsCipherContextEncryptLength - find the output length of the next call to encrypt. @@ -100,8 +101,8 @@ SecCmsCipherContextDecryptLength(SecCmsCipherContextRef cc, size_t input_len, Bo * * Result can be used to perform memory allocations. */ -extern size_t -SecCmsCipherContextEncryptLength(SecCmsCipherContextRef cc, size_t input_len, Boolean final); +extern unsigned int +SecCmsCipherContextEncryptLength(SecCmsCipherContextRef cc, unsigned int input_len, Boolean final); /* * SecCmsCipherContextDecrypt - do the decryption @@ -122,8 +123,8 @@ SecCmsCipherContextEncryptLength(SecCmsCipherContextRef cc, size_t input_len, Bo */ extern OSStatus SecCmsCipherContextDecrypt(SecCmsCipherContextRef cc, unsigned char *output, - size_t *output_len_p, size_t max_output_len, - const unsigned char *input, size_t input_len, + unsigned int *output_len_p, unsigned int max_output_len, + const unsigned char *input, unsigned int input_len, Boolean final); /* @@ -145,8 +146,8 @@ SecCmsCipherContextDecrypt(SecCmsCipherContextRef cc, unsigned char *output, */ extern OSStatus SecCmsCipherContextEncrypt(SecCmsCipherContextRef cc, unsigned char *output, - size_t *output_len_p, size_t max_output_len, - const unsigned char *input, size_t input_len, + unsigned int *output_len_p, unsigned int max_output_len, + const unsigned char *input, unsigned int input_len, Boolean final); /************************************************************************ @@ -162,12 +163,12 @@ SecCmsCipherContextEncrypt(SecCmsCipherContextRef cc, unsigned char *output, extern OSStatus SecCmsUtilEncryptSymKeyRSA(PLArenaPool *poolp, SecCertificateRef cert, SecSymmetricKeyRef key, - CSSM_DATA_PTR encKey); + SecAsn1Item * encKey); extern OSStatus SecCmsUtilEncryptSymKeyRSAPubKey(PLArenaPool *poolp, SecPublicKeyRef publickey, - SecSymmetricKeyRef bulkkey, CSSM_DATA_PTR encKey); + SecSymmetricKeyRef bulkkey, SecAsn1Item * encKey); /* * SecCmsUtilDecryptSymKeyRSA - unwrap a RSA-wrapped symmetric key @@ -177,33 +178,24 @@ SecCmsUtilEncryptSymKeyRSAPubKey(PLArenaPool *poolp, * a hardware token... */ extern SecSymmetricKeyRef -SecCmsUtilDecryptSymKeyRSA(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, SECOidTag bulkalgtag); - -extern OSStatus -SecCmsUtilEncryptSymKeyECDH(PLArenaPool *poolp, SecCertificateRef cert, SecSymmetricKeyRef key, - CSSM_DATA_PTR encKey, CSSM_DATA_PTR ukm, SECAlgorithmID *keyEncAlg, - CSSM_DATA_PTR originatorPubKey); - -extern SecSymmetricKeyRef -SecCmsUtilDecryptSymKeyECDH(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, CSSM_DATA_PTR ukm, - SECAlgorithmID *keyEncAlg, SECOidTag bulkalgtag, CSSM_DATA_PTR pubKey); +SecCmsUtilDecryptSymKeyRSA(SecPrivateKeyRef privkey, SecAsn1Item * encKey, SECOidTag bulkalgtag); #if 0 extern OSStatus SecCmsUtilEncryptSymKeyMISSI(PLArenaPool *poolp, SecCertificateRef cert, SecSymmetricKeyRef key, - SECOidTag symalgtag, CSSM_DATA_PTR encKey, CSSM_DATA_PTR *pparams, void *pwfn_arg); + SECOidTag symalgtag, SecAsn1Item * encKey, SecAsn1Item * *pparams, void *pwfn_arg); extern SecSymmetricKeyRef -SecCmsUtilDecryptSymKeyMISSI(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, +SecCmsUtilDecryptSymKeyMISSI(SecPrivateKeyRef privkey, SecAsn1Item * encKey, SECAlgorithmID *keyEncAlg, SECOidTag bulkalgtag, void *pwfn_arg); extern OSStatus SecCmsUtilEncryptSymKeyESDH(PLArenaPool *poolp, SecCertificateRef cert, SecSymmetricKeyRef key, - CSSM_DATA_PTR encKey, CSSM_DATA_PTR ukm, SECAlgorithmID *keyEncAlg, - CSSM_DATA_PTR originatorPubKey); + SecAsn1Item * encKey, SecAsn1Item * *ukm, SECAlgorithmID *keyEncAlg, + SecAsn1Item * originatorPubKey); extern SecSymmetricKeyRef -SecCmsUtilDecryptSymKeyESDH(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, +SecCmsUtilDecryptSymKeyESDH(SecPrivateKeyRef privkey, SecAsn1Item * encKey, SECAlgorithmID *keyEncAlg, SECOidTag bulkalgtag, void *pwfn_arg); #endif @@ -264,13 +256,13 @@ SecCmsArraySort(void **primary, int (*compare)(void *,void *), void **secondary, * with SecCmsAttributeAddValue. */ extern SecCmsAttribute * -SecCmsAttributeCreate(PRArenaPool *poolp, SECOidTag oidtag, CSSM_DATA_PTR value, Boolean encoded); +SecCmsAttributeCreate(PRArenaPool *poolp, SECOidTag oidtag, SecAsn1Item * value, Boolean encoded); /* * SecCmsAttributeAddValue - add another value to an attribute */ extern OSStatus -SecCmsAttributeAddValue(PLArenaPool *poolp, SecCmsAttribute *attr, CSSM_DATA_PTR value); +SecCmsAttributeAddValue(PLArenaPool *poolp, SecCmsAttribute *attr, SecAsn1Item * value); /* * SecCmsAttributeGetType - return the OID tag @@ -285,14 +277,14 @@ SecCmsAttributeGetType(SecCmsAttribute *attr); * - Multiple values are *not* expected. * - Empty values are *not* expected. */ -extern CSSM_DATA_PTR +extern SecAsn1Item * SecCmsAttributeGetValue(SecCmsAttribute *attr); /* * SecCmsAttributeCompareValue - compare the attribute's first value against data */ extern Boolean -SecCmsAttributeCompareValue(SecCmsAttribute *attr, CSSM_DATA_PTR av); +SecCmsAttributeCompareValue(SecCmsAttribute *attr, SecAsn1Item * av); /* * SecCmsAttributeArrayEncode - encode an Attribute array as SET OF Attributes @@ -303,8 +295,8 @@ SecCmsAttributeCompareValue(SecCmsAttribute *attr, CSSM_DATA_PTR av); * and think long and hard about the implications of making it always * do the reordering.) */ -extern CSSM_DATA_PTR -SecCmsAttributeArrayEncode(PRArenaPool *poolp, SecCmsAttribute ***attrs, CSSM_DATA_PTR dest); +extern SecAsn1Item * +SecCmsAttributeArrayEncode(PRArenaPool *poolp, SecCmsAttribute ***attrs, SecAsn1Item * dest); /* * SecCmsAttributeArrayReorder - sort attribute array by attribute's DER encoding @@ -338,7 +330,7 @@ SecCmsAttributeArrayAddAttr(PLArenaPool *poolp, SecCmsAttribute ***attrs, SecCms * SecCmsAttributeArraySetAttr - set an attribute's value in a set of attributes */ extern OSStatus -SecCmsAttributeArraySetAttr(PLArenaPool *poolp, SecCmsAttribute ***attrs, SECOidTag type, CSSM_DATA_PTR value, Boolean encoded); +SecCmsAttributeArraySetAttr(PLArenaPool *poolp, SecCmsAttribute ***attrs, SECOidTag type, SecAsn1Item * value, Boolean encoded); /************************************************************************/ SEC_END_PROTOS diff --git a/libsecurity_smime/lib/cmsmessage.c b/libsecurity_smime/lib/cmsmessage.c index 816ce4af..d6d9f56c 100644 --- a/libsecurity_smime/lib/cmsmessage.c +++ b/libsecurity_smime/lib/cmsmessage.c @@ -42,11 +42,12 @@ #include "cmslocal.h" -#include "secitem.h" +#include "SecAsn1Item.h" #include "secoid.h" #include #include +#include /* * SecCmsMessageCreate - create a CMS message object @@ -54,41 +55,25 @@ * "poolp" - arena to allocate memory from, or NULL if new arena should be created */ SecCmsMessageRef -SecCmsMessageCreate(SecArenaPoolRef pool) +SecCmsMessageCreate(void) { - PLArenaPool *poolp = (PLArenaPool *)pool; - void *mark = NULL; + PLArenaPool *poolp; SecCmsMessageRef cmsg; - Boolean poolp_is_ours = PR_FALSE; - if (poolp == NULL) { - poolp = PORT_NewArena (1024); /* XXX what is right value? */ - if (poolp == NULL) - return NULL; - poolp_is_ours = PR_TRUE; - } - - if (!poolp_is_ours) - mark = PORT_ArenaMark(poolp); + poolp = PORT_NewArena (1024); /* XXX what is right value? */ + if (poolp == NULL) + return NULL; cmsg = (SecCmsMessageRef)PORT_ArenaZAlloc (poolp, sizeof(SecCmsMessage)); if (cmsg == NULL) { - if (!poolp_is_ours) { - if (mark) { - PORT_ArenaRelease(poolp, mark); - } - } else - PORT_FreeArena(poolp, PR_FALSE); + PORT_FreeArena(poolp, PR_FALSE); return NULL; } cmsg->poolp = poolp; - cmsg->poolp_is_ours = poolp_is_ours; + cmsg->contentInfo.cmsg = cmsg; cmsg->refCount = 1; - if (mark) - PORT_ArenaUnmark(poolp, mark); - return cmsg; } @@ -103,8 +88,7 @@ SecCmsMessageCreate(SecArenaPoolRef pool) void SecCmsMessageSetEncodingParams(SecCmsMessageRef cmsg, PK11PasswordFunc pwfn, void *pwfn_arg, - SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg, - SECAlgorithmID **detached_digestalgs, CSSM_DATA_PTR *detached_digests) + SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg) { #if 0 // @@@ Deal with password stuff. @@ -114,8 +98,6 @@ SecCmsMessageSetEncodingParams(SecCmsMessageRef cmsg, cmsg->pwfn_arg = pwfn_arg; cmsg->decrypt_key_cb = decrypt_key_cb; cmsg->decrypt_key_cb_arg = decrypt_key_cb_arg; - cmsg->detached_digestalgs = detached_digestalgs; - cmsg->detached_digests = detached_digests; } /* @@ -134,9 +116,7 @@ SecCmsMessageDestroy(SecCmsMessageRef cmsg) SecCmsContentInfoDestroy(&(cmsg->contentInfo)); - /* if poolp is not NULL, cmsg is the owner of its arena */ - if (cmsg->poolp_is_ours) - PORT_FreeArena (cmsg->poolp, PR_FALSE); /* XXX clear it? */ + PORT_FreeArena (cmsg->poolp, PR_FALSE); /* XXX clear it? */ } /* @@ -157,15 +137,6 @@ SecCmsMessageCopy(SecCmsMessageRef cmsg) return cmsg; } -/* - * SecCmsMessageGetArena - return a pointer to the message's arena pool - */ -SecArenaPoolRef -SecCmsMessageGetArena(SecCmsMessageRef cmsg) -{ - return (SecArenaPoolRef)cmsg->poolp; -} - /* * SecCmsMessageGetContentInfo - return a pointer to the top level contentInfo */ @@ -180,12 +151,12 @@ SecCmsMessageGetContentInfo(SecCmsMessageRef cmsg) * In the case of those types which are encrypted, this returns the *plain* content. * In case of nested contentInfos, this descends and retrieves the innermost content. */ -CSSM_DATA_PTR +const SecAsn1Item * SecCmsMessageGetContent(SecCmsMessageRef cmsg) { /* this is a shortcut */ SecCmsContentInfoRef cinfo = SecCmsMessageGetContentInfo(cmsg); - CSSM_DATA_PTR pItem = SecCmsContentInfoGetInnerContent(cinfo); + const SecAsn1Item *pItem = SecCmsContentInfoGetInnerContent(cinfo); return pItem; } @@ -307,7 +278,7 @@ SecCmsMessageIsSigned(SecCmsMessageRef cmsg) Boolean SecCmsMessageIsContentEmpty(SecCmsMessageRef cmsg, unsigned int minLen) { - CSSM_DATA_PTR item = NULL; + SecAsn1Item * item = NULL; if (cmsg == NULL) return PR_TRUE; @@ -322,41 +293,3 @@ SecCmsMessageIsContentEmpty(SecCmsMessageRef cmsg, unsigned int minLen) return PR_FALSE; } - -/* - * SecCmsMessageContainsTSTInfo - see if message contains a TimeStamping info block - */ -Boolean -SecCmsMessageContainsTSTInfo(SecCmsMessageRef cmsg) -{ - SecCmsContentInfoRef cinfo; - - /* walk down the chain of contentinfos */ - for (cinfo = &(cmsg->contentInfo); cinfo != NULL; cinfo = SecCmsContentInfoGetChildContentInfo(cinfo)) - { - switch (SecCmsContentInfoGetContentTypeTag(cinfo)) - { - case SEC_OID_PKCS9_ID_CT_TSTInfo: - // TSTInfo is in cinfo->rawContent->Data - return PR_TRUE; - default: - break; - } - } - return PR_FALSE; -} - -void -SecCmsMessageSetTSACallback(SecCmsMessageRef cmsg, SecCmsTSACallback tsaCallback) -{ - if (cmsg) - cmsg->tsaCallback = tsaCallback; -} - -void -SecCmsMessageSetTSAContext(SecCmsMessageRef cmsg, const void *tsaContext) //CFTypeRef -{ - if (cmsg) - cmsg->tsaContext = tsaContext; -} - diff --git a/libsecurity_smime/lib/cmspriv.h b/libsecurity_smime/lib/cmspriv.h index e4222bbd..4dc0b176 100644 --- a/libsecurity_smime/lib/cmspriv.h +++ b/libsecurity_smime/lib/cmspriv.h @@ -39,12 +39,12 @@ #define _CMSPRIV_H_ #include +#include // SEC_BEGIN_PROTOS #include "cmstpriv.h" /************************************************************************/ SEC_BEGIN_PROTOS - /************************************************************************ * cmsutil.c - CMS misc utility functions ************************************************************************/ @@ -62,7 +62,7 @@ SecCmsArraySortByDER(void **objs, const SecAsn1Template *objtemplate, void **obj /* * SecCmsUtilDERCompare - for use with SecCmsArraySort to - * sort arrays of CSSM_DATAs containing DER + * sort arrays of SecAsn1Items containing DER */ extern int SecCmsUtilDERCompare(void *a, void *b); @@ -95,7 +95,11 @@ SecCmsAlgArrayGetIndexByAlgID(SECAlgorithmID **algorithmArray, SECAlgorithmID *a extern int SecCmsAlgArrayGetIndexByAlgTag(SECAlgorithmID **algorithmArray, SECOidTag algtag); +#if USE_CDSA_CRYPTO extern CSSM_CC_HANDLE +#else +extern void * +#endif SecCmsUtilGetHashObjByAlgID(SECAlgorithmID *algid); /* @@ -136,14 +140,7 @@ SecCmsContentGetContentInfo(void *msg, SECOidTag type); extern void SecCmsMessageSetEncodingParams(SecCmsMessageRef cmsg, PK11PasswordFunc pwfn, void *pwfn_arg, - SecCmsGetDecryptKeyCallback encrypt_key_cb, void *encrypt_key_cb_arg, - SECAlgorithmID **detached_digestalgs, CSSM_DATA_PTR *detached_digests); - -extern void -SecCmsMessageSetTSACallback(SecCmsMessageRef cmsg, SecCmsTSACallback tsaCallback); - -extern void -SecCmsMessageSetTSAContext(SecCmsMessageRef cmsg, const void *tsaContext); //CFTypeRef + SecCmsGetDecryptKeyCallback encrypt_key_cb, void *encrypt_key_cb_arg); /************************************************************************ * cmscinfo.c - CMS contentInfo methods @@ -160,7 +157,7 @@ SecCmsContentInfoDestroy(SecCmsContentInfoRef cinfo); * SecCmsContentInfoSetContent - set cinfo's content type & content to CMS object */ extern OSStatus -SecCmsContentInfoSetContent(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SECOidTag type, void *ptr); +SecCmsContentInfoSetContent(SecCmsContentInfoRef cinfo, SECOidTag type, void *ptr); /************************************************************************ @@ -170,20 +167,35 @@ SecCmsContentInfoSetContent(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, S extern OSStatus SecCmsSignedDataSetDigestValue(SecCmsSignedDataRef sigd, SECOidTag digestalgtag, - CSSM_DATA_PTR digestdata); + SecAsn1Item * digestdata); extern OSStatus -SecCmsSignedDataAddDigest(SecArenaPoolRef pool, +SecCmsSignedDataAddDigest(PRArenaPool *poolp, SecCmsSignedDataRef sigd, SECOidTag digestalgtag, - CSSM_DATA_PTR digest); + SecAsn1Item * digest); -extern CSSM_DATA_PTR +extern SecAsn1Item * SecCmsSignedDataGetDigestByAlgTag(SecCmsSignedDataRef sigd, SECOidTag algtag); -extern CSSM_DATA_PTR +extern SecAsn1Item * SecCmsSignedDataGetDigestValue(SecCmsSignedDataRef sigd, SECOidTag digestalgtag); +/*! + @function + */ +extern OSStatus +SecCmsSignedDataAddSignerInfo(SecCmsSignedDataRef sigd, + SecCmsSignerInfoRef signerinfo); + +/*! + @function + */ +extern OSStatus +SecCmsSignedDataSetDigests(SecCmsSignedDataRef sigd, + SECAlgorithmID **digestalgs, + SecAsn1Item * *digests); + /* * SecCmsSignedDataEncodeBeforeStart - do all the necessary things to a SignedData * before start of encoding. @@ -231,12 +243,6 @@ SecCmsSignedDataDecodeAfterData(SecCmsSignedDataRef sigd); extern OSStatus SecCmsSignedDataDecodeAfterEnd(SecCmsSignedDataRef sigd); -/* - * Get SecCmsSignedDataRawCerts - obtain raw certs as a NULL_terminated array - * of pointers. - */ -extern OSStatus SecCmsSignedDataRawCerts(SecCmsSignedDataRef sigd, - CSSM_DATA_PTR **rawCerts); /************************************************************************ * cmssiginfo.c - CMS signerInfo methods @@ -247,7 +253,7 @@ extern OSStatus SecCmsSignedDataRawCerts(SecCmsSignedDataRef sigd, * */ extern OSStatus -SecCmsSignerInfoSign(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR digest, CSSM_DATA_PTR contentType); +SecCmsSignerInfoSign(SecCmsSignerInfoRef signerinfo, SecAsn1Item * digest, SecAsn1Item * contentType); /* * If trustRef is NULL the cert chain is verified and the VerificationStatus is set accordingly. @@ -264,7 +270,7 @@ SecCmsSignerInfoVerifyCertificate(SecCmsSignerInfoRef signerinfo, SecKeychainRef * is done already. */ extern OSStatus -SecCmsSignerInfoVerify(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR digest, CSSM_DATA_PTR contentType); +SecCmsSignerInfoVerify(SecCmsSignerInfoRef signerinfo, SecAsn1Item * digest, SecAsn1Item * contentType); /* * SecCmsSignerInfoAddAuthAttr - add an attribute to the @@ -283,19 +289,26 @@ SecCmsSignerInfoAddUnauthAttr(SecCmsSignerInfoRef signerinfo, SecCmsAttribute *a extern int SecCmsSignerInfoGetVersion(SecCmsSignerInfoRef signerinfo); -/* - * Determine whether Microsoft ECDSA compatibility mode is enabled. - * See comments in SecCmsSignerInfo.h for details. - * Implemented in siginfoUtils.cpp for access to C++ Dictionary class. +/*! + @function + @abstract Destroy a SignerInfo data structure. */ -extern bool -SecCmsMsEcdsaCompatMode(); +extern void +SecCmsSignerInfoDestroy(SecCmsSignerInfoRef si); /************************************************************************ * cmsenvdata.c - CMS envelopedData methods ************************************************************************/ +/*! + @function + @abstract Add a recipientinfo to the enveloped data msg. + @discussion Rip must be created on the same pool as edp - this is not enforced, though. + */ +extern OSStatus +SecCmsEnvelopedDataAddRecipient(SecCmsEnvelopedDataRef edp, SecCmsRecipientInfoRef rip); + /* * SecCmsEnvelopedDataEncodeBeforeStart - prepare this envelopedData for encoding * @@ -350,7 +363,7 @@ SecCmsEnvelopedDataDecodeAfterEnd(SecCmsEnvelopedDataRef envd); extern int SecCmsRecipientInfoGetVersion(SecCmsRecipientInfoRef ri); -extern CSSM_DATA_PTR +extern SecAsn1Item * SecCmsRecipientInfoGetEncryptedKey(SecCmsRecipientInfoRef ri, int subIndex); @@ -364,6 +377,12 @@ extern SecSymmetricKeyRef SecCmsRecipientInfoUnwrapBulkKey(SecCmsRecipientInfoRef ri, int subIndex, SecCertificateRef cert, SecPrivateKeyRef privkey, SECOidTag bulkalgtag); +/*! + @function + */ +extern void +SecCmsRecipientInfoDestroy(SecCmsRecipientInfoRef ri); + /************************************************************************ * cmsencdata.c - CMS encryptedData methods @@ -491,8 +510,29 @@ SecCmsDigestContextStartSingle(SECAlgorithmID *digestalg); * but for one digest. */ extern OSStatus -SecCmsDigestContextFinishSingle(SecCmsDigestContextRef cmsdigcx, SecArenaPoolRef arena, - CSSM_DATA_PTR digest); +SecCmsDigestContextFinishSingle(SecCmsDigestContextRef cmsdigcx, + SecAsn1Item * digest); + +/*! + @function + @abstract Finish the digests being calculated and put them into to parralel + arrays of SecAsn1Items. + @param cmsdigcx A DigestContext object. + @param digestalgsp will contain a to an array of digest algorithms on + success. + @param digestsp A EncryptedData object to set as the content of the cinfo + object. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion This function requires a DigestContext object which can be made + by calling SecCmsDigestContextStartSingle or + SecCmsDigestContextStartMultiple. The returned arrays remain valid + until SecCmsDigestContextDestroy is called. + @availability 10.4 and later + */ +extern OSStatus +SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, + SECAlgorithmID ***digestalgsp, + SecAsn1Item * **digestsp); /************************************************************************/ diff --git a/libsecurity_smime/lib/cmspubkey.c b/libsecurity_smime/lib/cmspubkey.c index 0f4d9f42..fb445d3c 100644 --- a/libsecurity_smime/lib/cmspubkey.c +++ b/libsecurity_smime/lib/cmspubkey.c @@ -37,20 +37,16 @@ #include "cmslocal.h" -#include "secitem.h" +#include "SecAsn1Item.h" #include "secoid.h" #include "cryptohi.h" #include #include -#include +#include + +#include #include -#include -#include -#include -#include -#include -#include /* ====== RSA ======================================================================= */ @@ -63,12 +59,15 @@ OSStatus SecCmsUtilEncryptSymKeyRSA(PLArenaPool *poolp, SecCertificateRef cert, SecSymmetricKeyRef bulkkey, - CSSM_DATA_PTR encKey) + SecAsn1Item * encKey) { OSStatus rv; SecPublicKeyRef publickey; - +#if USE_CDSA_CRYPTO rv = SecCertificateCopyPublicKey(cert,&publickey); +#else + publickey = SecCertificateCopyPublicKey(cert); +#endif if (publickey == NULL) return SECFailure; @@ -80,10 +79,10 @@ SecCmsUtilEncryptSymKeyRSA(PLArenaPool *poolp, SecCertificateRef cert, OSStatus SecCmsUtilEncryptSymKeyRSAPubKey(PLArenaPool *poolp, SecPublicKeyRef publickey, - SecSymmetricKeyRef bulkkey, CSSM_DATA_PTR encKey) + SecSymmetricKeyRef bulkkey, SecAsn1Item * encKey) { OSStatus rv; - unsigned int data_len; + size_t data_len; //KeyType keyType; void *mark = NULL; @@ -100,12 +99,16 @@ SecCmsUtilEncryptSymKeyRSAPubKey(PLArenaPool *poolp, } #endif /* allocate memory for the encrypted key */ +#if USE_CDSA_CRYPTO rv = SecKeyGetStrengthInBits(publickey, NULL, &data_len); if (rv) goto loser; - // Convert length to bytes; data_len >>= 2; +#else + data_len = SecKeyGetSize(publickey, kSecKeyEncryptedDataSize); +#endif + encKey->Data = (unsigned char*)PORT_ArenaAlloc(poolp, data_len); encKey->Length = data_len; if (encKey->Data == NULL) @@ -134,7 +137,7 @@ loser: * a hardware token... */ SecSymmetricKeyRef -SecCmsUtilDecryptSymKeyRSA(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, SECOidTag bulkalgtag) +SecCmsUtilDecryptSymKeyRSA(SecPrivateKeyRef privkey, SecAsn1Item * encKey, SECOidTag bulkalgtag) { /* that's easy */ return WRAP_PubUnwrapSymKey(privkey, encKey, bulkalgtag); @@ -149,12 +152,12 @@ extern const SecAsn1Template NSS_SMIMEKEAParamTemplateAllParams[]; OSStatus SecCmsUtilEncryptSymKeyMISSI(PLArenaPool *poolp, SecCertificateRef cert, SecSymmetricKeyRef bulkkey, - SECOidTag symalgtag, CSSM_DATA_PTR encKey, CSSM_DATA_PTR *pparams, void *pwfn_arg) + SECOidTag symalgtag, SecAsn1Item * encKey, SecAsn1Item * *pparams, void *pwfn_arg) { SECOidTag certalgtag; /* the certificate's encryption algorithm */ SECOidTag encalgtag; /* the algorithm used for key exchange/agreement */ OSStatus rv = SECFailure; - CSSM_DATA_PTR params = NULL; + SecAsn1Item * params = NULL; OSStatus err; SecSymmetricKeyRef tek; SecCertificateRef ourCert; @@ -163,13 +166,15 @@ SecCmsUtilEncryptSymKeyMISSI(PLArenaPool *poolp, SecCertificateRef cert, SecSymm SecCmsKEATemplateSelector whichKEA = SecCmsKEAInvalid; SecCmsSMIMEKEAParameters keaParams; PLArenaPool *arena = NULL; - extern const SecAsn1Template *nss_cms_get_kea_template(SecCmsKEATemplateSelector whichTemplate); const SECAlgorithmID *algid; /* Clear keaParams, since cleanup code checks the lengths */ (void) memset(&keaParams, 0, sizeof(keaParams)); +#if USE_CDSA_CRYPTO SecCertificateGetAlgorithmID(cert,&algid); +#endif + certalgtag = SECOID_GetAlgorithmTag(algid); PORT_Assert(certalgtag == SEC_OID_MISSI_KEA_DSS_OLD || certalgtag == SEC_OID_MISSI_KEA_DSS || @@ -310,7 +315,7 @@ loser: } SecSymmetricKeyRef -SecCmsUtilDecryptSymKeyMISSI(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, SECAlgorithmID *keyEncAlg, SECOidTag bulkalgtag, void *pwfn_arg) +SecCmsUtilDecryptSymKeyMISSI(SecPrivateKeyRef privkey, SecAsn1Item * encKey, SECAlgorithmID *keyEncAlg, SECOidTag bulkalgtag, void *pwfn_arg) { /* fortezza: do a key exchange */ OSStatus err; @@ -395,14 +400,14 @@ loser: OSStatus SecCmsUtilEncryptSymKeyESDH(PLArenaPool *poolp, SecCertificateRef cert, SecSymmetricKeyRef key, - CSSM_DATA_PTR encKey, CSSM_DATA_PTR ukm, SECAlgorithmID *keyEncAlg, - CSSM_DATA_PTR pubKey) + SecAsn1Item * encKey, SecAsn1Item * *ukm, SECAlgorithmID *keyEncAlg, + SecAsn1Item * pubKey) { #if 0 /* not yet done */ SECOidTag certalgtag; /* the certificate's encryption algorithm */ SECOidTag encalgtag; /* the algorithm used for key exchange/agreement */ OSStatus rv; - CSSM_DATA_PTR params = NULL; + SecAsn1Item * params = NULL; int data_len; OSStatus err; SecSymmetricKeyRef tek; @@ -527,7 +532,7 @@ loser: } SecSymmetricKeyRef -SecCmsUtilDecryptSymKeyESDH(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, SECAlgorithmID *keyEncAlg, SECOidTag bulkalgtag, void *pwfn_arg) +SecCmsUtilDecryptSymKeyESDH(SecPrivateKeyRef privkey, SecAsn1Item * encKey, SECAlgorithmID *keyEncAlg, SECOidTag bulkalgtag, void *pwfn_arg) { #if 0 /* not yet done */ OSStatus err; @@ -567,883 +572,4 @@ loser: return NULL; } -#endif /* Fortezza, DIffie-Hellman */ - -#define CFRELEASE(cf) if(cf != NULL) { CFRelease(cf); } - -/* ====== ECDH (Ephemeral-Static Diffie-Hellman) ==================================== */ - -#pragma mark ---- ECDH support functions ---- - -#ifdef NDEBUG -#define CSSM_PERROR(f, r) -#define dprintf(args...) -#else -#define CSSM_PERROR(f, r) cssmPerror(f, r) -#define dprintf(args...) printf(args) #endif - -/* Length of KeyAgreeRecipientInfo.ukm we create */ -#define UKM_LENGTH 8 - -/* KEK algorithm info we generate */ -#define ECDH_KEK_ALG_TAG SEC_OID_DES_EDE3_CBC -#define ECDH_KEK_KEY_CSSM_ALGID CSSM_ALGID_3DES_3KEY -#define ECDH_KEK_ENCR_CSSM_ALGID CSSM_ALGID_3DES_3KEY_EDE -#define ECDH_KEK_KEY_LEN_BYTES 24 -#define ECDH_KEK_IV_LEN_BYTES 8 - -#define CMS_DUMP_BUFS 0 -#if CMS_DUMP_BUFS - -static void dumpBuf( - const char *label, - const CSSM_DATA *cd) -{ - unsigned dex; - - printf("%s:\n ", label); - for(dex=0; dexLength; dex++) { - printf("%02X ", cd->Data[dex]); - if(((dex % 16) == 15) && (dex != (cd->Length - 1))) { - printf("\n "); - } - } - putchar('\n'); -} - -#else -#define dumpBuf(l, d) -#endif /* CMS_DUMP_BUFS */ - -/* - * The ECC-CMS-SharedInfo struct, as defined in RFC 3278 8.2, and the - * template for DER encoding and decoding it. - */ -typedef struct { - SECAlgorithmID algId; /* KEK alg, NULL params */ - CSSM_DATA entityUInfo; /* optional, ukm */ - CSSM_DATA suppPubInfo; /* length of KEK in bits as 4-byte integer */ -} ECC_CMS_SharedInfo; - -static const SecAsn1Template ECC_CMS_SharedInfoTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(ECC_CMS_SharedInfo) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0, - offsetof(ECC_CMS_SharedInfo,entityUInfo), - kSecAsn1OctetStringTemplate }, - { SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 2, - offsetof(ECC_CMS_SharedInfo,suppPubInfo), - kSecAsn1OctetStringTemplate }, - { 0 } -}; - -/* - * Given a context specified via a CSSM_CC_HANDLE, add a new - * CSSM_CONTEXT_ATTRIBUTE to the context as specified by AttributeType, - * AttributeLength, and an untyped pointer. - */ -/* specify either 32-bit integer or a pointer as an added attribute value */ -typedef enum { - CAT_Uint32, - CAT_Ptr -} ContextAttrType; - -static CSSM_RETURN cmsAddContextAttribute( - CSSM_CC_HANDLE CCHandle, - uint32 AttributeType, - uint32 AttributeLength, - ContextAttrType attrType, - /* specify exactly one of these */ - const void *AttributePtr, - uint32 attributeInt) -{ - CSSM_CONTEXT_ATTRIBUTE newAttr; - CSSM_RETURN crtn; - - newAttr.AttributeType = AttributeType; - newAttr.AttributeLength = AttributeLength; - if(attrType == CAT_Uint32) { - newAttr.Attribute.Uint32 = attributeInt; - } - else { - /* this is a union of a bunch of different pointers...*/ - newAttr.Attribute.Data = (CSSM_DATA_PTR)AttributePtr; - } - crtn = CSSM_UpdateContextAttributes(CCHandle, 1, &newAttr); - if(crtn) { - CSSM_PERROR("CSSM_UpdateContextAttributes", crtn); - } - return crtn; -} - -static CSSM_RETURN cmsGenRand( - CSSM_CSP_HANDLE cspHand, - CSSM_SIZE len, - uint8 *randOut) -{ - CSSM_CC_HANDLE ccHand = 0; - CSSM_DATA randData = {len, randOut}; - - CSSM_RETURN crtn = CSSM_CSP_CreateRandomGenContext(cspHand, - CSSM_ALGID_APPLE_YARROW, - NULL, /* seed*/ - len, - &ccHand); - if(crtn) { - CSSM_PERROR("CSSM_CSP_CreateRandomGenContext", crtn); - return crtn; - } - crtn = CSSM_GenerateRandom(ccHand, &randData); - CSSM_DeleteContext(ccHand); - if(crtn) { - CSSM_PERROR("CSSM_GenerateRandom", crtn); - } - return crtn; -} - -/* convert uint32 to big-endian 4 bytes */ -static void int32ToBytes( - uint32_t i, - unsigned char *b) -{ - int dex; - for(dex=3; dex>=0; dex--) { - b[dex] = i; - i >>= 8; - } -} - -/* - * NULL wrap a ref key to raw key in default format. - */ -static OSStatus cmsNullWrapKey( - CSSM_CSP_HANDLE cspHand, - const CSSM_KEY *refKey, - CSSM_KEY_PTR rawKey) -{ - CSSM_DATA descData = {0, 0}; - CSSM_RETURN crtn; - CSSM_CC_HANDLE ccHand; - CSSM_ACCESS_CREDENTIALS creds; - uint32 keyAttr; - - memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); - memset(rawKey, 0, sizeof(CSSM_KEY)); - - crtn = CSSM_CSP_CreateSymmetricContext(cspHand, - CSSM_ALGID_NONE, - CSSM_ALGMODE_NONE, - &creds, - NULL, // unwrappingKey - NULL, // initVector - CSSM_PADDING_NONE, - 0, // Params - &ccHand); - if(crtn) { - CSSM_PERROR("CSSM_CSP_CreateSymmetricContext", crtn); - return crtn; - } - - keyAttr = rawKey->KeyHeader.KeyAttr; - keyAttr &= ~(CSSM_KEYATTR_ALWAYS_SENSITIVE | CSSM_KEYATTR_NEVER_EXTRACTABLE | - CSSM_KEYATTR_MODIFIABLE); - keyAttr |= CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; - crtn = CSSM_WrapKey(ccHand, - &creds, - refKey, - &descData, - rawKey); - if(crtn != CSSM_OK) { - CSSM_PERROR("CSSM_WrapKey", crtn); - } - CSSM_DeleteContext(ccHand); - return crtn; -} - -/* - * Free memory via specified plugin's app-level allocator - */ -static void cmsFreeCssmMemory( - CSSM_HANDLE hand, - void *p) -{ - CSSM_API_MEMORY_FUNCS memFuncs; - CSSM_RETURN crtn = CSSM_GetAPIMemoryFunctions(hand, &memFuncs); - if(crtn) { - return; - } - memFuncs.free_func(p, memFuncs.AllocRef); -} - -/* - * Given an OID tag, return key size and mode. - * NOTE: ciphers with variable key sizes, like RC2, RC4, and RC5 cannot - * be used here because the message does not contain a key size - * indication. - */ -static OSStatus encrAlgInfo( - SECOidTag oidTag, - uint32 *keySizeBits, /* RETURNED */ - CSSM_ENCRYPT_MODE *mode) /* RETURNED */ -{ - *keySizeBits = 64; /* default */ - *mode = CSSM_ALGMODE_CBCPadIV8; /* default */ - - switch(oidTag) { - case SEC_OID_RC2_CBC: - case SEC_OID_RC4: - case SEC_OID_RC5_CBC_PAD: - dprintf("encrAlgInfo: key size unknowable\n"); - return errSecDataNotAvailable; - - case SEC_OID_DES_EDE3_CBC: - *keySizeBits = 192; - break; - case SEC_OID_DES_EDE: - /* Not sure about this; SecCmsCipherContextStart() treats this - * like SEC_OID_DES_EDE3_CBC... */ - case SEC_OID_DES_ECB: - *mode = CSSM_ALGMODE_ECB; - break; - case SEC_OID_DES_CBC: - *mode = CSSM_ALGMODE_CBC; - break; - case SEC_OID_AES_128_CBC: - *keySizeBits = 128; - break; - case SEC_OID_AES_192_CBC: - *keySizeBits = 192; - break; - case SEC_OID_AES_256_CBC: - *keySizeBits = 256; - break; - case SEC_OID_AES_128_ECB: - *keySizeBits = 128; - *mode = CSSM_ALGMODE_ECB; - break; - case SEC_OID_AES_192_ECB: - *keySizeBits = 192; - *mode = CSSM_ALGMODE_ECB; - break; - case SEC_OID_AES_256_ECB: - *keySizeBits = 256; - *mode = CSSM_ALGMODE_ECB; - break; - case SEC_OID_DES_OFB: - *mode = CSSM_ALGMODE_OFB; - break; - case SEC_OID_DES_CFB: - *mode = CSSM_ALGMODE_CFB; - break; - default: - dprintf("encrAlgInfo: unknown alg tag (%d)\n", (int)oidTag); - return errSecDataNotAvailable; - } - return noErr; -} - -#pragma mark ---- ECDH CEK key wrap ---- - -/* - * Encrypt bulk encryption key (a.k.a. content encryption key, CEK) using ECDH - */ -OSStatus -SecCmsUtilEncryptSymKeyECDH( - PLArenaPool *poolp, - SecCertificateRef cert, /* recipient's cert */ - SecSymmetricKeyRef key, /* bulk key */ - /* remaining fields RETURNED */ - CSSM_DATA_PTR encKey, /* encrypted key --> recipientEncryptedKeys[0].EncryptedKey */ - CSSM_DATA_PTR ukm, /* random UKM --> KeyAgreeRecipientInfo.ukm */ - SECAlgorithmID *keyEncAlg, /* alg := dhSinglePass-stdDH-sha1kdf-scheme - * params := another encoded AlgId, with the KEK alg and IV */ - CSSM_DATA_PTR pubKey) /* our pub key as ECPoint --> - * KeyAgreeRecipientInfo.originator.OriginatorPublicKey */ -{ - OSStatus rv = noErr; - CSSM_KEY ourPrivKeyCssm; - CSSM_KEY ourPubKeyCssm; - SecKeyRef theirPubKeyRef = NULL; - CSSM_KEY_PTR theirPubKeyCssm = NULL; - const CSSM_KEY *cekCssmRef = NULL; - uint32 ecdhKeySizeBits; - CSSM_CSP_HANDLE rawCspHand = SecCspHandleForAlgorithm(CSSM_ALGID_ECDH); - CSSM_CC_HANDLE ccHand = 0; - CSSM_RETURN crtn; - CSSM_DATA keyLabel = {8, (uint8 *)"tempKey"}; - SECAlgorithmID kekAlgId; - uint8 iv[ECDH_KEK_IV_LEN_BYTES]; - CSSM_DATA ivData = {ECDH_KEK_IV_LEN_BYTES, iv}; - SECOidData *kekOid; - ECC_CMS_SharedInfo sharedInfo; - CSSM_DATA sharedInfoEnc = {0, NULL}; - uint8 nullData[2] = {SEC_ASN1_NULL, 0}; - uint8 keyLenAsBytes[4]; - CSSM_KEY kekDerive; - CSSM_DATA certData; - CSSM_CL_HANDLE clHand; - CSSM_ACCESS_CREDENTIALS creds; - CSSM_DATA paramData = {0, NULL}; - CSSM_KEY cekCssm; - CSSM_CSP_HANDLE refCspHand; - CSSM_SIZE bytesEncrypted; - CSSM_DATA remData = {0, NULL}; - CSSM_DATA ctext = {0, NULL}; - CSSM_X509_SUBJECT_PUBLIC_KEY_INFO subjPubKey; - - if(rawCspHand == 0) { - return internalComponentErr; - } - - memset(&ourPrivKeyCssm, 0, sizeof(CSSM_KEY)); - memset(&ourPubKeyCssm, 0, sizeof(CSSM_KEY)); - memset(&cekCssm, 0, sizeof(CSSM_KEY)); - memset(&kekDerive, 0, sizeof(kekDerive)); - - encKey->Data = NULL; - encKey->Length = 0; - - /* - * Create our ECDH key pair matching the recipient's key. - * Get the public key in "read-only" OCTET_STRING format, which - * is the ECPoint we put in - * KeyAgreeRecipientInfo.originator.OriginatorPublicKey. - */ - rv = SecCertificateGetData(cert, &certData); - if(rv) { - CSSM_PERROR("SecCertificateGetData", rv); - return rv; - } - rv = SecCertificateGetCLHandle(cert, &clHand); - if(rv) { - CSSM_PERROR("SecCertificateGetCLHandle", rv); - return rv; - } - rv = CSSM_CL_CertGetKeyInfo(clHand, &certData, &theirPubKeyCssm); - if(rv) { - CSSM_PERROR("CSSM_CL_CertGetKeyInfo", rv); - return rv; - } - - /* - * Verify the EC curve of the recipient's public key. It's in the - * public key's AlgId.parameters as an OID. The key we were - * given is in CSSM_X509_SUBJECT_PUBLIC_KEY_INFO form. - */ - memset(&subjPubKey, 0, sizeof(subjPubKey)); - if(SEC_ASN1DecodeItem(poolp, &subjPubKey, kSecAsn1SubjectPublicKeyInfoTemplate, - &theirPubKeyCssm->KeyData)) { - dprintf("SecCmsUtilEncryptSymKeyECDH: error decoding SubjPubKey\n"); - /* oh well, keep going */ - } - else { - if(subjPubKey.algorithm.parameters.Data != NULL) { - CSSM_DATA curveOid; - if(SEC_ASN1DecodeItem(poolp, &curveOid, kSecAsn1ObjectIDTemplate, - &subjPubKey.algorithm.parameters)) { - dprintf("SecCmsUtilEncryptSymKeyECDH: error decoding curveOid\n"); - /* oh well, keep going */ - } - else { - /* We have the curve OID. Any other errors are fatal. */ - SECOidTag oidTag = SECOID_FindOIDTag(&curveOid); - switch(oidTag) { - case SEC_OID_SECP_256_R1: - case SEC_OID_SECP_384_R1: - case SEC_OID_SECP_521_R1: - break; - default: - dprintf("SecCmsUtilEncryptSymKeyECDH: unsupported curveOid\n"); - rv = CSSMERR_CSP_INVALID_KEY; - goto loser; - } - } - } - } - - ecdhKeySizeBits = theirPubKeyCssm->KeyHeader.LogicalKeySizeInBits; - crtn = CSSM_CSP_CreateKeyGenContext(rawCspHand, - CSSM_ALGID_ECDSA, - ecdhKeySizeBits, - NULL, // Seed - NULL, // Salt - NULL, // StartDate - NULL, // EndDate - NULL, // Params - &ccHand); - if(crtn) { - CSSM_PERROR("CSSM_CSP_CreateKeyGenContext", crtn); - rv = crtn; - goto loser; - } - crtn = cmsAddContextAttribute(ccHand, - CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT, - sizeof(uint32), - CAT_Uint32, - NULL, - CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING); - if(crtn) { - CSSM_PERROR("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn); - rv = crtn; - goto loser; - } - - crtn = CSSM_GenerateKeyPair(ccHand, - CSSM_KEYUSE_DERIVE, - CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, - &keyLabel, - &ourPubKeyCssm, - CSSM_KEYUSE_DERIVE, - CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE, - &keyLabel, - NULL, // CredAndAclEntry - &ourPrivKeyCssm); - CSSM_DeleteContext(ccHand); - ccHand = 0; - if(crtn) { - CSSM_PERROR("CSSM_GenerateKeyPair", crtn); - rv = crtn; - goto loser; - } - pubKey->Length = ourPubKeyCssm.KeyData.Length; - pubKey->Data = (uint8 *)PORT_ArenaAlloc(poolp, pubKey->Length); - memmove(pubKey->Data, ourPubKeyCssm.KeyData.Data, pubKey->Length); - dumpBuf("sender's public key", pubKey); - - /* - * Cook up random UKM - */ - ukm->Data = (uint8 *)PORT_ArenaAlloc(poolp, UKM_LENGTH); - ukm->Length = UKM_LENGTH; - crtn = cmsGenRand(rawCspHand, UKM_LENGTH, ukm->Data); - if(crtn) { - goto loser; - } - dumpBuf("sender UKM", ukm); - - /* - * OK, we have to set up a weird SECAlgorithmID. - * algorithm = dhSinglePass-stdDH-sha1kdf-scheme - * params = an encoded SECAlgorithmID representing the KEK algorithm, with - * algorithm = whatever we pick - * parameters = IV as octet string (though I haven't seen that specified - * anywhere; it's how the CEK IV is encoded) - * - * First, the 8-byte random IV, encoded as octet string - */ - crtn = cmsGenRand(rawCspHand, ECDH_KEK_IV_LEN_BYTES, iv); - if(crtn) { - goto loser; - } - dumpBuf("sender IV", &ivData); - - memset(&kekAlgId, 0, sizeof(kekAlgId)); - if (!SEC_ASN1EncodeItem(poolp, &kekAlgId.parameters, - &ivData, kSecAsn1OctetStringTemplate)) { - rv = internalComponentErr; - goto loser; - } - - /* Drop in the KEK OID and encode the whole thing */ - kekOid = SECOID_FindOIDByTag(ECDH_KEK_ALG_TAG); - if(kekOid == NULL) { - dprintf("SecCmsUtilEncryptSymKeyECDH: OID screwup\n"); - rv = internalComponentErr; - goto loser; - } - kekAlgId.algorithm = kekOid->oid; - memset(keyEncAlg, 0, sizeof(*keyEncAlg)); - if (!SEC_ASN1EncodeItem(poolp, &keyEncAlg->parameters, - &kekAlgId, SECOID_AlgorithmIDTemplate)) { - rv = internalComponentErr; - goto loser; - } - kekOid = SECOID_FindOIDByTag(SEC_OID_DH_SINGLE_STD_SHA1KDF); - if(kekOid == NULL) { - dprintf("SecCmsUtilEncryptSymKeyECDH: OID screwup\n"); - rv = internalComponentErr; - goto loser; - } - keyEncAlg->algorithm = kekOid->oid; - - /* - * Now in order to derive the KEK proper, we have to create a - * ECC-CMS-SharedInfo, which does not appear in the message, and DER - * encode that struct, the result of which is used as the - * SharedInfo value in the KEK key derive. - */ - memset(&sharedInfo, 0, sizeof(sharedInfo)); - kekOid = SECOID_FindOIDByTag(ECDH_KEK_ALG_TAG); - sharedInfo.algId.algorithm = kekOid->oid; - sharedInfo.algId.parameters.Data = nullData; - sharedInfo.algId.parameters.Length = 2; - sharedInfo.entityUInfo = *ukm; - int32ToBytes(ECDH_KEK_KEY_LEN_BYTES << 3, keyLenAsBytes); - sharedInfo.suppPubInfo.Length = 4; - sharedInfo.suppPubInfo.Data = keyLenAsBytes; - if (!SEC_ASN1EncodeItem(poolp, &sharedInfoEnc, - &sharedInfo, ECC_CMS_SharedInfoTemplate)) { - rv = internalComponentErr; - goto loser; - } - dumpBuf("sender encoded SharedInfo", &sharedInfoEnc); - - /* - * Since we're using the raw CSP here, we can provide the "other" public - * key as an actual CSSM_KEY. When unwrapping, we won't be able to do that - * since we'll be using our private key obtained from a SecIdentityRef. - */ - memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); - crtn = CSSM_CSP_CreateDeriveKeyContext(rawCspHand, - CSSM_ALGID_ECDH_X963_KDF, - ECDH_KEK_KEY_CSSM_ALGID, // algorithm of the KEK - ECDH_KEK_KEY_LEN_BYTES * 8, - &creds, - &ourPrivKeyCssm, // BaseKey - 0, // IterationCount - &sharedInfoEnc, // Salt - 0, // Seed - &ccHand); - if(crtn) { - CSSM_PERROR("CSSM_CSP_CreateDeriveKeyContext", crtn); - rv = crtn; - goto loser; - } - - /* add recipient's pub key as a context attr */ - crtn = cmsAddContextAttribute(ccHand, - CSSM_ATTRIBUTE_PUBLIC_KEY, - sizeof(CSSM_KEY), - CAT_Ptr, - (void *)theirPubKeyCssm, - 0); - if(crtn) { - rv = crtn; - goto loser; - } - - /* Derive the KEK */ - crtn = CSSM_DeriveKey(ccHand, - ¶mData, - CSSM_KEYUSE_ANY, - CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, - &keyLabel, - NULL, // cread/acl - &kekDerive); - if(crtn) { - CSSM_PERROR("CSSM_DeriveKey", crtn); - rv = crtn; - goto loser; - } - CSSM_DeleteContext(ccHand); - ccHand = 0; - - /* - * Obtain the raw CEK bits. - */ - rv = SecKeyGetCSSMKey(key, &cekCssmRef); - if(rv) { - CSSM_PERROR("SecKeyGetCSSMKey", rv); - goto loser; - } - rv = SecKeyGetCSPHandle(key, &refCspHand); - if(rv) { - CSSM_PERROR("SecKeyGetCSPHandle", rv); - goto loser; - } - rv = cmsNullWrapKey(refCspHand, cekCssmRef, &cekCssm); - if(rv) { - goto loser; - } - - /* - * Finally, encrypt the raw CEK bits with the KEK we just derived - */ - crtn = CSSM_CSP_CreateSymmetricContext(rawCspHand, - ECDH_KEK_ENCR_CSSM_ALGID, - CSSM_ALGMODE_CBCPadIV8, - NULL, // access cred - &kekDerive, - &ivData, // InitVector - CSSM_PADDING_PKCS7, - NULL, // Params - &ccHand); - if(rv) { - CSSM_PERROR("CSSM_CSP_CreateSymmetricContext", rv); - goto loser; - } - rv = CSSM_EncryptData(ccHand, - &cekCssm.KeyData, - 1, - &ctext, - 1, - &bytesEncrypted, - &remData); - if(rv) { - CSSM_PERROR("CSSM_EncryptData", rv); - goto loser; - } - encKey->Data = PORT_ArenaAlloc(poolp, bytesEncrypted); - encKey->Length = bytesEncrypted; - memmove(encKey->Data, ctext.Data, ctext.Length); - if(bytesEncrypted != ctext.Length) { - memmove(encKey->Data + ctext.Length, remData.Data, remData.Length); - } - dumpBuf("sender encKey", encKey); - -loser: - if(ccHand) { - CSSM_DeleteContext(ccHand); - } - CFRELEASE(theirPubKeyRef); - if(ourPubKeyCssm.KeyData.Data) { - CSSM_FreeKey(rawCspHand, NULL, &ourPubKeyCssm, CSSM_FALSE); - } - if(ourPrivKeyCssm.KeyData.Data) { - CSSM_FreeKey(rawCspHand, NULL, &ourPrivKeyCssm, CSSM_FALSE); - } - if(ctext.Data) { - cmsFreeCssmMemory(rawCspHand, ctext.Data); - } - if(remData.Data) { - cmsFreeCssmMemory(rawCspHand, remData.Data); - } - if(cekCssm.KeyData.Data) { - CSSM_FreeKey(refCspHand, NULL, &cekCssm, CSSM_FALSE); - } - if(kekDerive.KeyData.Data) { - CSSM_FreeKey(rawCspHand, NULL, &kekDerive, CSSM_FALSE); - } - if(theirPubKeyCssm) { - /* Allocated by CL */ - cmsFreeCssmMemory(clHand, theirPubKeyCssm->KeyData.Data); - cmsFreeCssmMemory(clHand, theirPubKeyCssm); - } - return rv; -} - -#pragma mark ---- ECDH CEK key unwrap ---- - -SecSymmetricKeyRef -SecCmsUtilDecryptSymKeyECDH( - SecPrivateKeyRef privkey, /* our private key */ - CSSM_DATA_PTR encKey, /* encrypted CEK */ - CSSM_DATA_PTR ukm, /* random UKM from KeyAgreeRecipientInfo.ukm */ - SECAlgorithmID *keyEncAlg, /* alg := dhSinglePass-stdDH-sha1kdf-scheme - * params := another encoded AlgId, with the KEK alg and IV */ - SECOidTag bulkalgtag, /* algorithm of returned key */ - CSSM_DATA_PTR pubKey) /* sender's pub key as ECPoint from - * KeyAgreeRecipientInfo.originator.OriginatorPublicKey */ - -{ - SecSymmetricKeyRef outKey = NULL; - OSStatus rv = noErr; - const CSSM_KEY *ourPrivKeyCssm; - PLArenaPool *pool = NULL; - SECAlgorithmID keyAlgParam; - SECOidData *kekOid = NULL; - CSSM_DATA iv = {0, NULL}; - ECC_CMS_SharedInfo sharedInfo; - CSSM_DATA sharedInfoEnc = {0, NULL}; - uint8 nullData[2] = {SEC_ASN1_NULL, 0}; - uint8 keyLenAsBytes[4]; - CSSM_ENCRYPT_MODE kekMode; - uint32 kekSizeBits; - CSSM_KEY kekDerive; - CSSM_RETURN crtn; - CSSM_ACCESS_CREDENTIALS creds; - CSSM_CSP_HANDLE refCspHand; - CSSM_CC_HANDLE ccHand = 0; - CSSM_DATA keyLabel = {8, (uint8 *)"tempKey"}; - const CSSM_ACCESS_CREDENTIALS *accessCred; - CSSM_KEY wrappedKey; - CSSM_KEY unwrappedKey; - CSSM_ALGORITHMS bulkAlg; - CSSM_DATA descriptiveData = {0, NULL}; - - dumpBuf("receiver encKey", encKey); - - memset(&kekDerive, 0, sizeof(kekDerive)); - - /* our private key in CSSM form */ - rv = SecKeyGetCSSMKey(privkey, &ourPrivKeyCssm); - if(rv) { - CSSM_PERROR("SecKeyGetCSSMKey", rv); - goto loser; - } - - /* - * Decode keyEncAlg.params to get KEK algorithm and IV - */ - pool = PORT_NewArena(1024); - if(pool == NULL) { - goto loser; - } - memset(&keyAlgParam, 0, sizeof(keyAlgParam)); - if(SEC_ASN1DecodeItem(pool, &keyAlgParam, SECOID_AlgorithmIDTemplate, - &keyEncAlg->parameters)) { - dprintf("SecCmsUtilDecryptSymKeyECDH: error decoding keyAlgParams\n"); - goto loser; - } - kekOid = SECOID_FindOID(&keyAlgParam.algorithm); - if(kekOid == NULL) { - dprintf("SecCmsUtilDecryptSymKeyECDH: unknown KEK enc OID\n"); - goto loser; - } - rv = encrAlgInfo(kekOid->offset, &kekSizeBits, &kekMode); - if(rv) { - goto loser; - } - /* IV is OCTET STRING in the alg params */ - if(SEC_ASN1DecodeItem(pool, &iv, kSecAsn1OctetStringTemplate, - &keyAlgParam.parameters)) { - /* - * Not sure here - is it legal to have no IV? I haven't seen this - * addressed in any spec. Maybe we should condition the behavior - * here on the KEK algorithm. - */ - dprintf("SecCmsUtilDecryptSymKeyECDH: no KEK IV\n"); - goto loser; - } - - /* - * Now in order to derive the KEK proper, we have to create a - * ECC-CMS-SharedInfo, which does not appear in the message, and DER - * encode that struct, the result of which is used as the - * SharedInfo value in the KEK key derive. - */ - memset(&sharedInfo, 0, sizeof(sharedInfo)); - sharedInfo.algId.algorithm = kekOid->oid; - sharedInfo.algId.parameters.Data = nullData; - sharedInfo.algId.parameters.Length = 2; - sharedInfo.entityUInfo = *ukm; - int32ToBytes(kekSizeBits, keyLenAsBytes); - sharedInfo.suppPubInfo.Length = 4; - sharedInfo.suppPubInfo.Data = keyLenAsBytes; - if (!SEC_ASN1EncodeItem(pool, &sharedInfoEnc, - &sharedInfo, ECC_CMS_SharedInfoTemplate)) { - rv = internalComponentErr; - goto loser; - } - dumpBuf("receiver encoded SharedInfo", &sharedInfoEnc); - dumpBuf("receiver IV", &iv); - dumpBuf("receiver UKM", ukm); - dumpBuf("sender's public key", pubKey); - - /* - * Using the Sec-layer CSPDL, "other's" public key specified as ECPOint param. Which - * is fortunate because that's what we have... - */ - memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); - rv = SecKeyGetCSPHandle(privkey, &refCspHand); - if(rv) { - CSSM_PERROR("SecKeyGetCSPHandle", rv); - goto loser; - } - rv = SecKeyGetCredentials(privkey, - CSSM_ACL_AUTHORIZATION_DERIVE, - kSecCredentialTypeDefault, - &accessCred); - if (rv) { - CSSM_PERROR("SecKeyGetCredentials", rv); - goto loser; - } - crtn = CSSM_CSP_CreateDeriveKeyContext(refCspHand, - CSSM_ALGID_ECDH_X963_KDF, - kekOid->cssmAlgorithm, // algorithm of the KEK - kekSizeBits, - &creds, - ourPrivKeyCssm, // BaseKey - 0, // IterationCount - &sharedInfoEnc, // Salt - 0, // Seed - &ccHand); - if(crtn) { - CSSM_PERROR("CSSM_CSP_CreateDeriveKeyContext", crtn); - goto loser; - } - crtn = CSSM_DeriveKey(ccHand, - pubKey, // param - CSSM_KEYUSE_ANY, - CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE, - &keyLabel, - NULL, // cred/acl - &kekDerive); - CSSM_DeleteContext(ccHand); - ccHand = 0; - if(crtn) { - CSSM_PERROR("CSSM_DeriveKey", crtn); - goto loser; - } - - /* - * Decrypt the encrypted key bits with the KEK key. - */ - crtn = CSSM_CSP_CreateSymmetricContext(refCspHand, - kekOid->cssmAlgorithm, - kekMode, - NULL, // access cred - &kekDerive, - &iv, // InitVector - /* FIXME is this variable too? */ - CSSM_PADDING_PKCS7, - NULL, // Params - &ccHand); - if(rv) { - CSSM_PERROR("CSSM_CSP_CreateSymmetricContext", rv); - goto loser; - } - - memset(&wrappedKey, 0, sizeof(CSSM_KEY)); - memset(&unwrappedKey, 0, sizeof(CSSM_KEY)); - - bulkAlg = SECOID_FindyCssmAlgorithmByTag(bulkalgtag); - if(bulkAlg == CSSM_ALGID_NONE) { - dprintf("SecCmsUtilDecryptSymKeyECDH: unknown bulk alg\n"); - goto loser; - } - - wrappedKey.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; - wrappedKey.KeyHeader.BlobType = CSSM_KEYBLOB_WRAPPED; - wrappedKey.KeyHeader.Format = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7; - wrappedKey.KeyHeader.AlgorithmId = bulkAlg; - wrappedKey.KeyHeader.KeyClass = CSSM_KEYCLASS_SESSION_KEY; - wrappedKey.KeyHeader.WrapAlgorithmId = kekOid->cssmAlgorithm; - wrappedKey.KeyHeader.WrapMode = CSSM_ALGMODE_NONE; - wrappedKey.KeyData = *encKey; - - crtn = CSSM_UnwrapKey(ccHand, - NULL, /* publicKey */ - &wrappedKey, - CSSM_KEYUSE_DECRYPT, - CSSM_KEYATTR_EXTRACTABLE, - &keyLabel, - NULL, /* rcc */ - &unwrappedKey, - &descriptiveData); - CSSM_DeleteContext(ccHand); - ccHand = 0; - if(crtn) { - CSSM_PERROR("CSSM_UnwrapKey", crtn); - goto loser; - } - rv = SecKeyCreateWithCSSMKey(&unwrappedKey, &outKey); - if (rv) { - CSSM_PERROR("SecKeyCreateWithCSSMKey", rv); - } - -loser: - if(pool != NULL) { - PORT_FreeArena(pool, PR_FALSE); - } - if(kekDerive.KeyData.Data) { - CSSM_FreeKey(refCspHand, NULL, &kekDerive, CSSM_FALSE); - } - if(outKey == NULL) { - PORT_SetError(SEC_ERROR_NO_KEY); - } - return outKey; -} - - - diff --git a/libsecurity_smime/lib/cmsrecinfo.c b/libsecurity_smime/lib/cmsrecinfo.c index dbecfbef..bf3551e6 100644 --- a/libsecurity_smime/lib/cmsrecinfo.c +++ b/libsecurity_smime/lib/cmsrecinfo.c @@ -38,14 +38,18 @@ #include "cmslocal.h" #include "cert.h" -#include "secitem.h" +#include "SecAsn1Item.h" #include "secoid.h" #include #include +#include + #include #include -#include +#include + +#include "SecCmsRecipientInfo.h" static Boolean nss_cmsrecipientinfo_usessubjectkeyid(SecCmsRecipientInfoRef ri) @@ -62,9 +66,9 @@ nss_cmsrecipientinfo_usessubjectkeyid(SecCmsRecipientInfoRef ri) static SecCmsRecipientInfoRef -nss_cmsrecipientinfo_create(SecCmsMessageRef cmsg, SecCmsRecipientIDSelector type, +nss_cmsrecipientinfo_create(SecCmsEnvelopedDataRef envd, SecCmsRecipientIDSelector type, SecCertificateRef cert, SecPublicKeyRef pubKey, - CSSM_DATA_PTR subjKeyID) + const SecAsn1Item *subjKeyID) { SecCmsRecipientInfoRef ri; void *mark; @@ -73,12 +77,14 @@ nss_cmsrecipientinfo_create(SecCmsMessageRef cmsg, SecCmsRecipientIDSelector typ SecCmsRecipientEncryptedKey *rek; SecCmsOriginatorIdentifierOrKey *oiok; unsigned long version; - CSSM_DATA_PTR dummy; + SecAsn1Item * dummy; PLArenaPool *poolp; const SECAlgorithmID *algid; + SECAlgorithmID freeAlgID; + SecCmsRecipientIdentifier *rid; - poolp = cmsg->poolp; + poolp = envd->contentInfo.cmsg->poolp; mark = PORT_ArenaMark(poolp); @@ -86,17 +92,28 @@ nss_cmsrecipientinfo_create(SecCmsMessageRef cmsg, SecCmsRecipientIDSelector typ if (ri == NULL) goto loser; - ri->cmsg = cmsg; + ri->envelopedData = envd; + +#if USE_CDSA_CRYPTO if (type == SecCmsRecipientIDIssuerSN) { - ri->cert = CERT_DupCertificate(cert); - if (ri->cert == NULL) - goto loser; rv = SecCertificateGetAlgorithmID(cert,&algid); } else { PORT_Assert(pubKey); rv = SecKeyGetAlgorithmID(pubKey,&algid); } +#else + ri->cert = CERT_DupCertificate(cert); + if (ri->cert == NULL) + goto loser; + + 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; + freeAlgID.parameters.Length = (size_t)length_data_swapped->parameters.Data; + freeAlgID.parameters.Data = (uint8_t *)length_data_swapped->parameters.Length; + algid = &freeAlgID; +#endif certalgtag = SECOID_GetAlgorithmTag(algid); @@ -111,9 +128,8 @@ nss_cmsrecipientinfo_create(SecCmsMessageRef cmsg, SecCmsRecipientIDSelector typ break; } } else if (type == SecCmsRecipientIDSubjectKeyID){ - SecCmsKeyTransRecipientInfoEx *riExtra; - rid->id.subjectKeyID = PORT_ArenaNew(poolp, CSSM_DATA); + rid->id.subjectKeyID = PORT_ArenaNew(poolp, SecAsn1Item); if (rid->id.subjectKeyID == NULL) { rv = SECFailure; PORT_SetError(SEC_ERROR_NO_MEMORY); @@ -125,6 +141,9 @@ nss_cmsrecipientinfo_create(SecCmsMessageRef cmsg, SecCmsRecipientIDSelector typ PORT_SetError(SEC_ERROR_NO_MEMORY); break; } + +#if 0 + SecCmsKeyTransRecipientInfoEx *riExtra; riExtra = &ri->ri.keyTransRecipientInfoEx; riExtra->version = 0; riExtra->pubKey = SECKEY_CopyPublicKey(pubKey); @@ -133,6 +152,7 @@ nss_cmsrecipientinfo_create(SecCmsMessageRef cmsg, SecCmsRecipientIDSelector typ PORT_SetError(SEC_ERROR_NO_MEMORY); break; } +#endif } else { PORT_SetError(SEC_ERROR_INVALID_ARGS); rv = SECFailure; @@ -201,50 +221,6 @@ nss_cmsrecipientinfo_create(SecCmsMessageRef cmsg, SecCmsRecipientIDSelector typ (void *)rek); break; - - case SEC_OID_EC_PUBLIC_KEY: - /* ephemeral-static ECDH - issuerAndSN, OriginatorPublicKey only */ - PORT_Assert(type != SecCmsRecipientIDSubjectKeyID); - if (type == SecCmsRecipientIDSubjectKeyID) { - rv = SECFailure; - break; - } - /* a key agreement op */ - ri->recipientInfoType = SecCmsRecipientInfoIDKeyAgree; - ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert); - if (ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN == NULL) { - rv = SECFailure; - break; - } - /* we do not support the case where multiple recipients - * share the same KeyAgreeRecipientInfo and have multiple RecipientEncryptedKeys - * in this case, we would need to walk all the recipientInfos, take the - * ones that do KeyAgreement algorithms and join them, algorithm by algorithm - * Then, we'd generate ONE ukm and OriginatorIdentifierOrKey */ - - /* force single recipientEncryptedKey for now */ - if ((rek = SecCmsRecipientEncryptedKeyCreate(poolp)) == NULL) { - rv = SECFailure; - break; - } - - /* hardcoded IssuerSN choice for now */ - rek->recipientIdentifier.identifierType = SecCmsKeyAgreeRecipientIDIssuerSN; - if ((rek->recipientIdentifier.id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert)) == NULL) { - rv = SECFailure; - break; - } - - oiok = &(ri->ri.keyAgreeRecipientInfo.originatorIdentifierOrKey); - - /* see RFC 3278 3.1.1 */ - oiok->identifierType = SecCmsOriginatorIDOrKeyOriginatorPublicKey; - - rv = SecCmsArrayAdd(poolp, (void ***)&ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys, - (void *)rek); - - break; - default: /* other algorithms not supported yet */ /* NOTE that we do not support any KEK algorithm */ @@ -283,6 +259,9 @@ nss_cmsrecipientinfo_create(SecCmsMessageRef cmsg, SecCmsRecipientIDSelector typ } + if (SecCmsEnvelopedDataAddRecipient(envd, ri)) + goto loser; + PORT_ArenaUnmark (poolp, mark); #if 0 if (freeSpki) @@ -307,30 +286,38 @@ loser: * verified by the caller */ SecCmsRecipientInfoRef -SecCmsRecipientInfoCreate(SecCmsMessageRef cmsg, SecCertificateRef cert) +SecCmsRecipientInfoCreate(SecCmsEnvelopedDataRef envd, SecCertificateRef cert) { - return nss_cmsrecipientinfo_create(cmsg, SecCmsRecipientIDIssuerSN, cert, +#if 0 + SecCmsRecipientInfoRef info = SecCmsRecipientInfoCreateWithSubjKeyIDFromCert(envd, cert); + + if (info) + return info; + else +#endif + return nss_cmsrecipientinfo_create(envd, SecCmsRecipientIDIssuerSN, cert, NULL, NULL); } SecCmsRecipientInfoRef -SecCmsRecipientInfoCreateWithSubjKeyID(SecCmsMessageRef cmsg, - CSSM_DATA_PTR subjKeyID, +SecCmsRecipientInfoCreateWithSubjKeyID(SecCmsEnvelopedDataRef envd, + const SecAsn1Item * subjKeyID, SecPublicKeyRef pubKey) { - return nss_cmsrecipientinfo_create(cmsg, SecCmsRecipientIDSubjectKeyID, + return nss_cmsrecipientinfo_create(envd, SecCmsRecipientIDSubjectKeyID, NULL, pubKey, subjKeyID); } +#if USE_CDSA_CRYPTO SecCmsRecipientInfoRef -SecCmsRecipientInfoCreateWithSubjKeyIDFromCert(SecCmsMessageRef cmsg, +SecCmsRecipientInfoCreateWithSubjKeyIDFromCert(SecCmsEnvelopedDataRef envd, SecCertificateRef cert) { SecPublicKeyRef pubKey = NULL; - CSSM_DATA subjKeyID = {0, NULL}; + SecAsn1Item subjKeyID = {0, NULL}; SecCmsRecipientInfoRef retVal = NULL; - if (!cmsg || !cert) { + if (!envd || !cert) { return NULL; } pubKey = CERT_ExtractPublicKey(cert); @@ -341,7 +328,7 @@ SecCmsRecipientInfoCreateWithSubjKeyIDFromCert(SecCmsMessageRef cmsg, subjKeyID.Data == NULL) { goto done; } - retVal = SecCmsRecipientInfoCreateWithSubjKeyID(cmsg, &subjKeyID, pubKey); + retVal = SecCmsRecipientInfoCreateWithSubjKeyID(envd, &subjKeyID, pubKey); done: if (pubKey) SECKEY_DestroyPublicKey(pubKey); @@ -351,6 +338,33 @@ done: return retVal; } +#else +SecCmsRecipientInfoRef +SecCmsRecipientInfoCreateWithSubjKeyIDFromCert(SecCmsEnvelopedDataRef envd, + SecCertificateRef cert) +{ + SecPublicKeyRef pubKey = NULL; + SecAsn1Item subjKeyID = {0, NULL}; + SecCmsRecipientInfoRef retVal = NULL; + CFDataRef subjectKeyIDData = NULL; + + if (!envd || !cert) { + return NULL; + } + subjectKeyIDData = SecCertificateGetSubjectKeyID(cert); + if (!subjectKeyIDData) + goto done; + subjKeyID.Length = + CFDataGetLength(subjectKeyIDData); + subjKeyID.Data = (uint8_t *)CFDataGetBytePtr(subjectKeyIDData); + retVal = nss_cmsrecipientinfo_create(envd, SecCmsRecipientIDSubjectKeyID, + cert, pubKey, &subjKeyID); + +done: + + return retVal; +} +#endif void SecCmsRecipientInfoDestroy(SecCmsRecipientInfoRef ri) @@ -375,7 +389,7 @@ int SecCmsRecipientInfoGetVersion(SecCmsRecipientInfoRef ri) { unsigned long version; - CSSM_DATA_PTR versionitem = NULL; + SecAsn1Item * versionitem = NULL; switch (ri->recipientInfoType) { case SecCmsRecipientInfoIDKeyTrans: @@ -395,17 +409,17 @@ SecCmsRecipientInfoGetVersion(SecCmsRecipientInfoRef ri) if (versionitem == NULL) return 0; - /* always take apart the CSSM_DATA */ + /* always take apart the SecAsn1Item */ if (SEC_ASN1DecodeInteger(versionitem, &version) != SECSuccess) return 0; else return (int)version; } -CSSM_DATA_PTR +SecAsn1Item * SecCmsRecipientInfoGetEncryptedKey(SecCmsRecipientInfoRef ri, int subIndex) { - CSSM_DATA_PTR enckey = NULL; + SecAsn1Item * enckey = NULL; switch (ri->recipientInfoType) { case SecCmsRecipientInfoIDKeyTrans: @@ -451,26 +465,32 @@ SecCmsRecipientInfoWrapBulkKey(SecCmsRecipientInfoRef ri, SecSymmetricKeyRef bul SECOidTag certalgtag; OSStatus rv = SECSuccess; #if 0 - CSSM_DATA_PTR params = NULL; -#endif /* 0 */ + SecAsn1Item * params = NULL; SecCmsRecipientEncryptedKey *rek; SecCmsOriginatorIdentifierOrKey *oiok; +#endif /* 0 */ const SECAlgorithmID *algid; PLArenaPool *poolp; SecCmsKeyTransRecipientInfoEx *extra = NULL; Boolean usesSubjKeyID; - uint8 nullData[2] = {SEC_ASN1_NULL, 0}; - SECItem nullItem; - SecCmsKeyAgreeRecipientInfo *kari; - - poolp = ri->cmsg->poolp; + + poolp = ri->envelopedData->contentInfo.cmsg->poolp; cert = ri->cert; usesSubjKeyID = nss_cmsrecipientinfo_usessubjectkeyid(ri); if (cert) { +#if USE_CDSA_CRYPTO rv = SecCertificateGetAlgorithmID(cert,&algid); if (rv) return SECFailure; - certalgtag = SECOID_GetAlgorithmTag(algid); +#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; + freeAlgID.parameters.Length = (size_t)length_data_swapped->parameters.Data; + freeAlgID.parameters.Data = (uint8_t *)length_data_swapped->parameters.Length; + algid = &freeAlgID; +#endif } else if (usesSubjKeyID) { extra = &ri->ri.keyTransRecipientInfoEx; /* sanity check */ @@ -479,8 +499,10 @@ SecCmsRecipientInfoWrapBulkKey(SecCmsRecipientInfoRef ri, SecSymmetricKeyRef bul PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } +#if USE_CDSA_CRYPTO rv = SecKeyGetAlgorithmID(extra->pubKey,&algid); if (rv) +#endif return SECFailure; certalgtag = SECOID_GetAlgorithmTag(algid); } else { @@ -553,44 +575,6 @@ SecCmsRecipientInfoWrapBulkKey(SecCmsRecipientInfoRef ri, SecSymmetricKeyRef bul break; #endif /* 0 */ - - case SEC_OID_EC_PUBLIC_KEY: - /* These were set up in nss_cmsrecipientinfo_create() */ - kari = &ri->ri.keyAgreeRecipientInfo; - rek = kari->recipientEncryptedKeys[0]; - if (rek == NULL) { - rv = SECFailure; - break; - } - - oiok = &(kari->originatorIdentifierOrKey); - PORT_Assert(oiok->identifierType == SecCmsOriginatorIDOrKeyOriginatorPublicKey); - - /* - * RFC 3278 3.1.1 says this AlgId must contain NULL params which is contrary to - * any other use of the SEC_OID_EC_PUBLIC_KEY OID. So we provide one - * explicitly instead of mucking up the login in SECOID_SetAlgorithmID(). - */ - nullItem.Data = nullData; - nullItem.Length = 2; - if (SECOID_SetAlgorithmID(poolp, &oiok->id.originatorPublicKey.algorithmIdentifier, - SEC_OID_EC_PUBLIC_KEY, &nullItem) != SECSuccess) { - rv = SECFailure; - break; - } - - /* this will generate a key pair, compute the shared secret, */ - /* derive a key and ukm for the keyEncAlg out of it, encrypt the bulk key with */ - /* the keyEncAlg, set encKey, keyEncAlg, publicKey etc. */ - rv = SecCmsUtilEncryptSymKeyECDH(poolp, cert, bulkkey, - &rek->encKey, - &kari->ukm, - &kari->keyEncAlg, - &oiok->id.originatorPublicKey.publicKey); - /* this is a BIT STRING */ - oiok->id.originatorPublicKey.publicKey.Length <<= 3; - break; - default: /* other algorithms not supported yet */ /* NOTE that we do not support any KEK algorithm */ @@ -606,12 +590,6 @@ SecCmsRecipientInfoWrapBulkKey(SecCmsRecipientInfoRef ri, SecSymmetricKeyRef bul return rv; } -#ifdef NDEBUG -#define dprintf(args...) -#else -#define dprintf(args...) printf(args) -#endif - SecSymmetricKeyRef SecCmsRecipientInfoUnwrapBulkKey(SecCmsRecipientInfoRef ri, int subIndex, SecCertificateRef cert, SecPrivateKeyRef privkey, SECOidTag bulkalgtag) @@ -619,7 +597,7 @@ SecCmsRecipientInfoUnwrapBulkKey(SecCmsRecipientInfoRef ri, int subIndex, SecSymmetricKeyRef bulkkey = NULL; SECAlgorithmID *encalg; SECOidTag encalgtag; - CSSM_DATA_PTR enckey; + SecAsn1Item * enckey; int error; ri->cert = CERT_DupCertificate(cert); @@ -664,24 +642,6 @@ SecCmsRecipientInfoUnwrapBulkKey(SecCmsRecipientInfoRef ri, int subIndex, /* the derive operation has to generate the key using the algorithm in RFC2631 */ error = SEC_ERROR_UNSUPPORTED_KEYALG; break; - case SEC_OID_DH_SINGLE_STD_SHA1KDF: - { - /* ephemeral-static ECDH */ - SecCmsKeyAgreeRecipientInfo *kari = &ri->ri.keyAgreeRecipientInfo; - SecCmsOriginatorIdentifierOrKey *oiok = &kari->originatorIdentifierOrKey; - if(oiok->identifierType != SecCmsOriginatorIDOrKeyOriginatorPublicKey) { - dprintf("SEC_OID_EC_PUBLIC_KEY unwrap key: bad oiok.id\n"); - goto loser; - } - SecCmsOriginatorPublicKey *opk = &oiok->id.originatorPublicKey; - /* FIXME - verify opk->algorithmIdentifier here? */ - CSSM_DATA senderPubKey = opk->publicKey; - /* Bit string, convert here */ - senderPubKey.Length = (senderPubKey.Length + 7) >> 3; - CSSM_DATA_PTR ukm = &kari->ukm; - bulkkey = SecCmsUtilDecryptSymKeyECDH(privkey, enckey, ukm, encalg, bulkalgtag, &senderPubKey); - break; - } default: error = SEC_ERROR_UNSUPPORTED_KEYALG; goto loser; diff --git a/libsecurity_smime/lib/cmsreclist.c b/libsecurity_smime/lib/cmsreclist.c index 15f0942d..1b84dd5d 100644 --- a/libsecurity_smime/lib/cmsreclist.c +++ b/libsecurity_smime/lib/cmsreclist.c @@ -34,11 +34,13 @@ #include "cmslocal.h" #include "cert.h" -#include "secitem.h" +#include "SecAsn1Item.h" #include "secoid.h" #include #include +#include + #include static int @@ -190,12 +192,12 @@ nss_cms_FindCertAndKeyByRecipientList(SecCmsRecipient **recipient_list, void *wi SecCertificateRef cert = NULL; SecPrivateKeyRef privKey = NULL; SecIdentityRef identity = NULL; + int ix; CFTypeRef keychainOrArray = NULL; // @@@ The caller should be able to pass this in somehow. - int index; - for (index = 0; recipient_list[index] != NULL; ++index) + for (ix = 0; recipient_list[ix] != NULL; ++ix) { - recipient = recipient_list[index]; + recipient = recipient_list[ix]; switch (recipient->kind) { @@ -211,6 +213,9 @@ nss_cms_FindCertAndKeyByRecipientList(SecCmsRecipient **recipient_list, void *wi break; } + if (!identity) + goto loser; + if (!recipient) goto loser; @@ -223,7 +228,7 @@ nss_cms_FindCertAndKeyByRecipientList(SecCmsRecipient **recipient_list, void *wi recipient->cert = cert; recipient->privkey = privKey; - return index; + return ix; loser: if (identity) diff --git a/libsecurity_smime/lib/cmsreclist.h b/libsecurity_smime/lib/cmsreclist.h index 38d0dc2c..19f9ce23 100644 --- a/libsecurity_smime/lib/cmsreclist.h +++ b/libsecurity_smime/lib/cmsreclist.h @@ -41,7 +41,7 @@ struct SecCmsRecipientStr { enum {RLIssuerSN=0, RLSubjKeyID=1} kind; /* for conversion recipientinfos -> recipientlist */ union { SecCmsIssuerAndSN * issuerAndSN; - CSSM_DATA_PTR subjectKeyID; + SecAsn1Item * subjectKeyID; } id; /* result data (filled out for each recipient that's us) */ diff --git a/libsecurity_smime/lib/cmssigdata.c b/libsecurity_smime/lib/cmssigdata.c index e987374a..6e8e835f 100644 --- a/libsecurity_smime/lib/cmssigdata.c +++ b/libsecurity_smime/lib/cmssigdata.c @@ -44,23 +44,15 @@ #include "cmslocal.h" #include "cert.h" -#include "secitem.h" +#include "SecAsn1Item.h" #include "secoid.h" -#include "tsaTemplates.h" #include #include -#include -#include +#include -#ifndef NDEBUG -#define SIGDATA_DEBUG 1 -#endif - -#if SIGDATA_DEBUG -#define dprintf(args...) printf(args) -#else -#define dprintf(args...) +#if !USE_CDSA_CRYPTO +#include #endif SecCmsSignedDataRef @@ -78,7 +70,7 @@ SecCmsSignedDataCreate(SecCmsMessageRef cmsg) if (sigd == NULL) goto loser; - sigd->cmsg = cmsg; + sigd->contentInfo.cmsg = cmsg; /* signerInfos, certs, certlists, crls are all empty */ /* version is set in SecCmsSignedDataFinalize() */ @@ -128,14 +120,14 @@ SecCmsSignedDataEncodeBeforeStart(SecCmsSignedDataRef sigd) { SecCmsSignerInfoRef signerinfo; SECOidTag digestalgtag; - CSSM_DATA_PTR dummy; + SecAsn1Item * dummy; int version; OSStatus rv; Boolean haveDigests = PR_FALSE; int n, i; PLArenaPool *poolp; - poolp = sigd->cmsg->poolp; + poolp = sigd->contentInfo.cmsg->poolp; /* we assume that we have precomputed digests if there is a list of algorithms, and */ /* a chunk of data for each of those algorithms */ @@ -166,7 +158,6 @@ SecCmsSignedDataEncodeBeforeStart(SecCmsSignedDataRef sigd) /* (we need to know which algorithms we have when the content comes in) */ /* do not overwrite any existing digestAlgorithms (and digest) */ digestalgtag = SecCmsSignerInfoGetDigestAlgTag(signerinfo); - n = SecCmsAlgArrayGetIndexByAlgTag(sigd->digestAlgorithms, digestalgtag); if (n < 0 && haveDigests) { /* oops, there is a digestalg we do not have a digest for */ @@ -174,7 +165,7 @@ SecCmsSignedDataEncodeBeforeStart(SecCmsSignedDataRef sigd) goto loser; } else if (n < 0) { /* add the digestAlgorithm & a NULL digest */ - rv = SecCmsSignedDataAddDigest((SecArenaPoolRef)poolp, sigd, digestalgtag, NULL); + rv = SecCmsSignedDataAddDigest(poolp, sigd, digestalgtag, NULL); if (rv != SECSuccess) goto loser; } else { @@ -211,200 +202,6 @@ SecCmsSignedDataEncodeBeforeData(SecCmsSignedDataRef sigd) return SECSuccess; } -#include -#include "tsaSupport.h" -#include "tsaSupportPriv.h" -#include "tsaTemplates.h" -#include - -extern const SecAsn1Template kSecAsn1TSATSTInfoTemplate; - -OSStatus createTSAMessageImprint(SecCmsSignedDataRef signedData, CSSM_DATA_PTR encDigest, - SecAsn1TSAMessageImprint *messageImprint) -{ - // Calculate hash of encDigest and put in messageImprint.hashedMessage - // We pass in encDigest, since in the verification case, it comes from a different signedData - - OSStatus status = SECFailure; - - require(signedData && messageImprint, xit); - - SECAlgorithmID **digestAlgorithms = SecCmsSignedDataGetDigestAlgs(signedData); - require(digestAlgorithms, xit); - - SecCmsDigestContextRef digcx = SecCmsDigestContextStartMultiple(digestAlgorithms); - require(digcx, xit); - require(encDigest, xit); - - SecCmsSignerInfoRef signerinfo = SecCmsSignedDataGetSignerInfo(signedData, 0); // NB - assume 1 signer only! - messageImprint->hashAlgorithm = signerinfo->digestAlg; - - SecCmsDigestContextUpdate(digcx, encDigest->Data, encDigest->Length); - - require_noerr(SecCmsDigestContextFinishSingle(digcx, (SecArenaPoolRef)signedData->cmsg->poolp, - &messageImprint->hashedMessage), xit); - - status = SECSuccess; -xit: - return status; -} - -#include - -#ifndef NDEBUG -static OSStatus decodeDERUTF8String(const CSSM_DATA_PTR content, char *statusstr, size_t strsz) -{ - // The statusString should use kSecAsn1SequenceOfUTF8StringTemplate, but doesn't - OSStatus status = SECFailure; - SecAsn1CoderRef coder = NULL; - CSSM_DATA statusString; - size_t len = 0; - - require(content && statusstr, xit); - - require_noerr(SecAsn1CoderCreate(&coder), xit); - require_noerr(SecAsn1Decode(coder, content->Data, content->Length, kSecAsn1UTF8StringTemplate, &statusString), xit); - status = 0; - len = (statusString.Length < strsz)?(int)statusString.Length:strsz; - if (statusstr && statusString.Data) - strncpy(statusstr, (const char *)statusString.Data, len); - -xit: - if (coder) - SecAsn1CoderRelease(coder); - return status; -} -#endif - -static OSStatus validateTSAResponseAndAddTimeStamp(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR tsaResponse, - uint64_t expectedNonce) -{ - OSStatus status = SECFailure; - SecAsn1CoderRef coder = NULL; - SecAsn1TimeStampRespDER respDER = {{{0}},}; - SecAsn1TSAPKIStatusInfo *tsastatus = NULL; - int respstatus = -1; -#ifndef NDEBUG - int failinfo = -1; -#endif - - require_action(tsaResponse && tsaResponse->Data && tsaResponse->Length, xit, status = errSecTimestampMissing); - - require_noerr(SecAsn1CoderCreate(&coder), xit); - require_noerr(SecTSAResponseCopyDEREncoding(coder, tsaResponse, &respDER), xit); - -#ifndef NDEBUG - tsaWriteFileX("/tmp/tsa-timeStampToken.der", respDER.timeStampTokenDER.Data, respDER.timeStampTokenDER.Length); -#endif - - tsastatus = (SecAsn1TSAPKIStatusInfo *)&respDER.status; - require_action(tsastatus->status.Data, xit, status = errSecTimestampBadDataFormat); - respstatus = (int)tsaDER_ToInt(&tsastatus->status); - -#ifndef NDEBUG - char buf[80]={0,}; - if (tsastatus->failInfo.Data) // e.g. FI_BadRequest - failinfo = (int)tsaDER_ToInt(&tsastatus->failInfo); - - if (tsastatus->statusString.Data && tsastatus->statusString.Length) - { - OSStatus strrx = decodeDERUTF8String(&tsastatus->statusString, buf, sizeof(buf)); - dprintf("decodeDERUTF8String status: %d\n", (int)strrx); - } - - dprintf("validateTSAResponse: status: %d, failinfo: %d, %s\n", respstatus, failinfo, buf); -#endif - - switch (respstatus) - { - case PKIS_Granted: - case PKIS_GrantedWithMods: // Success - status = noErr; - break; - case PKIS_Rejection: - status = errSecTimestampRejection; - break; - case PKIS_Waiting: - status = errSecTimestampWaiting; - break; - case PKIS_RevocationWarning: - status = errSecTimestampRevocationWarning; - break; - case PKIS_RevocationNotification: - status = errSecTimestampRevocationNotification; - break; - default: - status = errSecTimestampSystemFailure; - break; - } - require_noerr(status, xit); - - // If we succeeded, then we must have a TimeStampToken - - require_action(respDER.timeStampTokenDER.Data && respDER.timeStampTokenDER.Length, xit, status = errSecTimestampBadDataFormat); - - dprintf("timestamp full expected nonce: %lld\n", expectedNonce); - - /* - The bytes in respDER are a full CMS message, which we need to check now for validity. - The code for this is essentially the same code taht is done during a timestamp - verify, except that we also need to check the nonce. - */ - require_noerr(status = decodeTimeStampToken(signerinfo, &respDER.timeStampTokenDER, NULL, expectedNonce), xit); - - status = SecCmsSignerInfoAddTimeStamp(signerinfo, &respDER.timeStampTokenDER); - -xit: - if (coder) - SecAsn1CoderRelease(coder); - return status; -} - -static OSStatus getRandomNonce(uint64_t *nonce) -{ - return nonce ? CCRandomCopyBytes(kCCRandomDevRandom, (void *)nonce, sizeof(*nonce)) : SECFailure; -} - -static OSStatus remapTimestampError(OSStatus inStatus) -{ - /* - Since communicating with the timestamp server is perhaps an unexpected - dependency on the network, map unknown errors into something to indicate - that signing without a timestamp may be a workaround. In particular, the - private CFURL errors (see CFNetworkErrorsPriv.i) - - kCFURLErrorTimedOut = -1001, - kCFURLErrorNotConnectedToInternet = -1009, - - are remapped to errSecTimestampServiceNotAvailable. - */ - - switch (inStatus) - { - case errSecTimestampMissing: - case errSecTimestampInvalid: - case errSecTimestampNotTrusted: - case errSecTimestampServiceNotAvailable: - case errSecTimestampBadAlg: - case errSecTimestampBadRequest: - case errSecTimestampBadDataFormat: - case errSecTimestampTimeNotAvailable: - case errSecTimestampUnacceptedPolicy: - case errSecTimestampUnacceptedExtension: - case errSecTimestampAddInfoNotAvailable: - case errSecTimestampSystemFailure: - case errSecSigningTimeMissing: - case errSecTimestampRejection: - case errSecTimestampWaiting: - case errSecTimestampRevocationWarning: - case errSecTimestampRevocationNotification: - return inStatus; - default: - return errSecTimestampServiceNotAvailable; - } - return errSecTimestampServiceNotAvailable; -} - /* * SecCmsSignedDataEncodeAfterData - do all the necessary things to a SignedData * after all the encapsulated data was passed through the encoder. @@ -423,21 +220,29 @@ SecCmsSignedDataEncodeAfterData(SecCmsSignedDataRef sigd) SECOidTag digestalgtag; OSStatus ret = SECFailure; OSStatus rv; - CSSM_DATA_PTR contentType; - int certcount; + SecAsn1Item * contentType; + CFIndex certcount; int i, ci, n, rci, si; PLArenaPool *poolp; CFArrayRef certlist; extern const SecAsn1Template SecCmsSignerInfoTemplate[]; - poolp = sigd->cmsg->poolp; cinfo = &(sigd->contentInfo); + poolp = cinfo->cmsg->poolp; /* did we have digest calculation going on? */ if (cinfo->digcx) { - rv = SecCmsDigestContextFinishMultiple(cinfo->digcx, (SecArenaPoolRef)poolp, &(sigd->digests)); + SecAsn1Item **digests = NULL; + SECAlgorithmID **digestalgs = NULL; + rv = SecCmsDigestContextFinishMultiple(cinfo->digcx, &digestalgs, &digests); if (rv != SECSuccess) goto loser; /* error has been set by SecCmsDigestContextFinishMultiple */ + if (digestalgs && digests) { + rv = SecCmsSignedDataSetDigests(sigd, digestalgs, digests); + if (rv != SECSuccess) + goto loser; /* error has been set by SecCmsSignedDataSetDigests */ + } + SecCmsDigestContextDestroy(cinfo->digcx); cinfo->digcx = NULL; } @@ -447,7 +252,7 @@ SecCmsSignedDataEncodeAfterData(SecCmsSignedDataRef sigd) /* prepare all the SignerInfos (there may be none) */ for (i=0; i < SecCmsSignedDataSignerInfoCount(sigd); i++) { signerinfo = SecCmsSignedDataGetSignerInfo(sigd, i); - + /* find correct digest for this signerinfo */ digestalgtag = SecCmsSignerInfoGetDigestAlgTag(signerinfo); n = SecCmsAlgArrayGetIndexByAlgTag(sigd->digestAlgorithms, digestalgtag); @@ -476,49 +281,6 @@ SecCmsSignedDataEncodeAfterData(SecCmsSignedDataRef sigd) certcount += CFArrayGetCount(certlist); } - /* Now we can get a timestamp, since we have all the digests */ - - // We force the setting of a callback, since this is the most usual case - if (!sigd->cmsg->tsaCallback) - SecCmsMessageSetTSACallback(sigd->cmsg, (SecCmsTSACallback)SecCmsTSADefaultCallback); - - if (sigd->cmsg->tsaCallback && sigd->cmsg->tsaContext) - { - CSSM_DATA tsaResponse = {0,}; - SecAsn1TSAMessageImprint messageImprint = {{{0},},{0,}}; - // Add nonce support for timestamping client - - uint64_t nonce = 0; - - require_noerr(getRandomNonce(&nonce), tsxit); - dprintf("SecCmsSignedDataSignerInfoCount: %d\n", SecCmsSignedDataSignerInfoCount(sigd)); - - // Calculate hash of encDigest and put in messageImprint.hashedMessage - SecCmsSignerInfoRef signerinfo = SecCmsSignedDataGetSignerInfo(sigd, 0); // NB - assume 1 signer only! - CSSM_DATA *encDigest = SecCmsSignerInfoGetEncDigest(signerinfo); - require_noerr(createTSAMessageImprint(sigd, encDigest, &messageImprint), tsxit); - - // Callback to fire up XPC service to talk to TimeStamping server, etc. - require_noerr(rv =(*sigd->cmsg->tsaCallback)(sigd->cmsg->tsaContext, &messageImprint, - nonce, &tsaResponse), tsxit); - - require_noerr(rv = validateTSAResponseAndAddTimeStamp(signerinfo, &tsaResponse, nonce), tsxit); - - /* - It is likely that every occurrence of "goto loser" in this file should - also do a PORT_SetError. Since it is not clear what might depend on this - behavior, we just do this in the timestamping case. - */ -tsxit: - if (rv) - { - dprintf("Original timestamp error: %d\n", (int)rv); - rv = remapTimestampError(rv); - PORT_SetError(rv); - goto loser; - } - } - /* this is a SET OF, so we need to sort them guys */ rv = SecCmsArraySortByDER((void **)signerinfos, SecCmsSignerInfoTemplate, NULL); if (rv != SECSuccess) @@ -544,7 +306,7 @@ tsxit: * XXX ARGH - this NEEDS to be fixed. need to come up with a decent * SetOfDERcertficates implementation */ - sigd->rawCerts = (CSSM_DATA_PTR *)PORT_ArenaAlloc(poolp, (certcount + 1) * sizeof(CSSM_DATA_PTR)); + sigd->rawCerts = (SecAsn1Item * *)PORT_ArenaAlloc(poolp, (certcount + 1) * sizeof(SecAsn1Item *)); if (sigd->rawCerts == NULL) return SECFailure; @@ -562,18 +324,30 @@ tsxit: for (si = 0; signerinfos[si] != NULL; si++) { signerinfo = signerinfos[si]; for (ci = 0; ci < CFArrayGetCount(signerinfo->certList); ci++) { - sigd->rawCerts[rci] = PORT_ArenaZAlloc(poolp, sizeof(CSSM_DATA)); + sigd->rawCerts[rci] = PORT_ArenaZAlloc(poolp, sizeof(SecAsn1Item)); SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(signerinfo->certList, ci); +#if USE_CDSA_CRYPTO SecCertificateGetData(cert, sigd->rawCerts[rci++]); +#else + SecAsn1Item cert_data = { SecCertificateGetLength(cert), + (uint8_t *)SecCertificateGetBytePtr(cert) }; + *(sigd->rawCerts[rci++]) = cert_data; +#endif } } } if (sigd->certs != NULL) { for (ci = 0; ci < CFArrayGetCount(sigd->certs); ci++) { - sigd->rawCerts[rci] = PORT_ArenaZAlloc(poolp, sizeof(CSSM_DATA)); + sigd->rawCerts[rci] = PORT_ArenaZAlloc(poolp, sizeof(SecAsn1Item)); SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(sigd->certs, ci); - SecCertificateGetData(cert, sigd->rawCerts[rci++]); +#if USE_CDSA_CRYPTO + SecCertificateGetData(cert, sigd->rawCerts[rci++]); +#else + SecAsn1Item cert_data = { SecCertificateGetLength(cert), + (uint8_t *)SecCertificateGetBytePtr(cert) }; + *(sigd->rawCerts[rci++]) = cert_data; +#endif } } @@ -586,16 +360,14 @@ tsxit: ret = SECSuccess; loser: - - dprintf("SecCmsSignedDataEncodeAfterData: ret: %ld, rv: %ld\n", (long)ret, (long)rv); return ret; } OSStatus SecCmsSignedDataDecodeBeforeData(SecCmsSignedDataRef sigd) { - /* set up the digests */ - if (sigd->digestAlgorithms != NULL && sigd->digests == NULL) { + /* set up the digests, if we have digest algorithms, no digests yet, and content is attached */ + if (sigd->digestAlgorithms != NULL && sigd->digests == NULL /* && sigd->contentInfo.content.pointer != NULL*/) { /* if digests are already there, do nothing */ sigd->contentInfo.digcx = SecCmsDigestContextStartMultiple(sigd->digestAlgorithms); if (sigd->contentInfo.digcx == NULL) @@ -611,13 +383,27 @@ SecCmsSignedDataDecodeBeforeData(SecCmsSignedDataRef sigd) OSStatus SecCmsSignedDataDecodeAfterData(SecCmsSignedDataRef sigd) { + OSStatus rv = SECSuccess; + /* did we have digest calculation going on? */ if (sigd->contentInfo.digcx) { - if (SecCmsDigestContextFinishMultiple(sigd->contentInfo.digcx, (SecArenaPoolRef)sigd->cmsg->poolp, &(sigd->digests)) != SECSuccess) - return SECFailure; /* error has been set by SecCmsDigestContextFinishMultiple */ + /* @@@ we should see if data was absent vs. zero length */ + if (sigd->contentInfo.content.data && sigd->contentInfo.content.data->Length) { + SecAsn1Item * *digests = NULL; + SECAlgorithmID **digestalgs = NULL; + rv = SecCmsDigestContextFinishMultiple(sigd->contentInfo.digcx, &digestalgs, &digests); + if (rv != SECSuccess) + goto loser; /* error has been set by SecCmsDigestContextFinishMultiple */ + rv = SecCmsSignedDataSetDigests(sigd, digestalgs, digests); + if (rv != SECSuccess) + goto loser; /* error has been set by SecCmsSignedDataSetDigests */ + } + SecCmsDigestContextDestroy(sigd->contentInfo.digcx); sigd->contentInfo.digcx = NULL; } - return SECSuccess; + +loser: + return rv; } /* @@ -630,14 +416,13 @@ SecCmsSignedDataDecodeAfterEnd(SecCmsSignedDataRef sigd) SecCmsSignerInfoRef *signerinfos; int i; + /* set cmsg for all the signerinfos */ signerinfos = sigd->signerInfos; - /* set cmsg and sigd backpointers for all the signerinfos */ + /* set signedData for all the signerinfos */ if (signerinfos) { - for (i = 0; signerinfos[i] != NULL; i++) { - signerinfos[i]->cmsg = sigd->cmsg; - signerinfos[i]->sigd = sigd; - } + for (i = 0; signerinfos[i] != NULL; i++) + signerinfos[i]->signedData = sigd; } return SECSuccess; @@ -685,7 +470,7 @@ SecCmsSignedDataGetContentInfo(SecCmsSignedDataRef sigd) /* * SecCmsSignedDataGetCertificateList - retrieve the SignedData's certificate list */ -CSSM_DATA_PTR * +SecAsn1Item * * SecCmsSignedDataGetCertificateList(SecCmsSignedDataRef sigd) { return sigd->rawCerts; @@ -695,22 +480,22 @@ OSStatus SecCmsSignedDataImportCerts(SecCmsSignedDataRef sigd, SecKeychainRef keychain, SECCertUsage certusage, Boolean keepcerts) { - int certcount; - OSStatus rv; - int i; - - certcount = SecCmsArrayCount((void **)sigd->rawCerts); + OSStatus rv = -1; +#if USE_CDSA_CRYPTO + int ix, certcount = SecCmsArrayCount((void **)sigd->rawCerts); rv = CERT_ImportCerts(keychain, certusage, certcount, sigd->rawCerts, NULL, keepcerts, PR_FALSE, NULL); - /* XXX CRL handling */ if (sigd->signerInfos != NULL) { /* fill in all signerinfo's certs */ - for (i = 0; sigd->signerInfos[i] != NULL; i++) - (void)SecCmsSignerInfoGetSigningCertificate(sigd->signerInfos[i], keychain); + for (ix = 0; sigd->signerInfos[ix] != NULL; i++) + (void)SecCmsSignerInfoGetSigningCertificate(sigd->signerInfos[ix], keychain); } +#else + // XXX we should only ever import certs for a cert only data blob +#endif return rv; } @@ -720,6 +505,7 @@ SecCmsSignedDataImportCerts(SecCmsSignedDataRef sigd, SecKeychainRef keychain, * of external signatures! */ + /* * SecCmsSignedDataVerifySignerInfo - check the signatures. * @@ -739,8 +525,8 @@ SecCmsSignedDataVerifySignerInfo(SecCmsSignedDataRef sigd, int i, SecCmsSignerInfoRef signerinfo; SecCmsContentInfoRef cinfo; SECOidData *algiddata; - CSSM_DATA_PTR contentType, digest; - OSStatus status, status2; + SecAsn1Item *contentType, *digest; + OSStatus status; cinfo = &(sigd->contentInfo); @@ -751,37 +537,32 @@ SecCmsSignedDataVerifySignerInfo(SecCmsSignedDataRef sigd, int i, /* Find digest and contentType for signerinfo */ algiddata = SecCmsSignerInfoGetDigestAlg(signerinfo); - if (algiddata == NULL) { - return errSecInternalError; // shouldn't have happened, this is likely due to corrupted data + + if (!sigd->digests) { + SECAlgorithmID **digestalgs = SecCmsSignedDataGetDigestAlgs(sigd); + SecCmsDigestContextRef digcx = SecCmsDigestContextStartMultiple(digestalgs); + SecCmsSignedDataSetDigestContext(sigd, digcx); + SecCmsDigestContextDestroy(digcx); } - + digest = SecCmsSignedDataGetDigestByAlgTag(sigd, algiddata->offset); - if(digest == NULL) { - /* - * No digests; this probably had detached content the caller has to - * deal with. - * FIXME: need some error return for this (as well as many - * other places in this library). - */ - return errSecDataNotAvailable; - } + contentType = SecCmsContentInfoGetContentTypeOID(cinfo); /* verify signature */ status = SecCmsSignerInfoVerify(signerinfo, digest, contentType); - - /* Now verify the certificate. We do this even if the signature failed to verify so we can - return a trustRef to the caller for display purposes. */ - status2 = SecCmsSignerInfoVerifyCertificate(signerinfo, keychainOrArray, - policies, trustRef); - dprintf("SecCmsSignedDataVerifySignerInfo: status %d status2 %d\n", (int) status, (int)status2); - /* The error from SecCmsSignerInfoVerify() supercedes error from SecCmsSignerInfoVerifyCertificate(). */ if (status) return status; - return status2; + /* Now verify the certificate. We do this even if the signature failed to verify so we can + return a trustRef to the caller for display purposes. */ + status = SecCmsSignerInfoVerifyCertificate(signerinfo, keychainOrArray, policies, trustRef); + + return status; } +#if USE_CDSA_CRYPTO + /* * SecCmsSignedDataVerifyCertsOnly - verify the certs in a certs-only message */ @@ -812,13 +593,42 @@ SecCmsSignedDataVerifyCertsOnly(SecCmsSignedDataRef sigd, break; } } - rv |= CERT_VerifyCert(keychainOrArray, cert, sigd->rawCerts, - policies, CFAbsoluteTimeGetCurrent(), NULL); + rv |= CERT_VerifyCert(keychainOrArray, cert, policies, CFAbsoluteTimeGetCurrent(), NULL); CFRelease(cert); } return rv; } +#else +OSStatus +SecCmsSignedDataVerifyCertsOnly(SecCmsSignedDataRef sigd, + SecKeychainRef keychainOrArray, + CFTypeRef policies) +{ + OSStatus rv = SECSuccess; + + if (!sigd || !keychainOrArray || !sigd->rawCerts) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + SecAsn1Item **cert_datas = sigd->rawCerts; + SecAsn1Item *cert_data; + while ((cert_data = *cert_datas++) != NULL) { + SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, cert_data->Data, cert_data->Length); + if (cert) { + CFArrayRef certs = CFArrayCreate(kCFAllocatorDefault, (const void **)&cert, 1, NULL); + rv |= CERT_VerifyCert(keychainOrArray, certs, policies, CFAbsoluteTimeGetCurrent(), NULL); + CFRelease(certs); + CFRelease(cert); + } + else + rv |= SECFailure; + } + + return rv; +} +#endif /* * SecCmsSignedDataHasDigests - see if we have digests in place @@ -900,14 +710,14 @@ SecCmsSignedDataContainsCertsOrCrls(SecCmsSignedDataRef sigd) OSStatus SecCmsSignedDataAddSignerInfo(SecCmsSignedDataRef sigd, - SecCmsSignerInfoRef signerinfo) + SecCmsSignerInfoRef signerinfo) { void *mark; OSStatus rv; SECOidTag digestalgtag; PLArenaPool *poolp; - poolp = sigd->cmsg->poolp; + poolp = sigd->contentInfo.cmsg->poolp; mark = PORT_ArenaMark(poolp); @@ -916,8 +726,6 @@ SecCmsSignedDataAddSignerInfo(SecCmsSignedDataRef sigd, if (rv != SECSuccess) goto loser; - signerinfo->sigd = sigd; - /* * add empty digest * Empty because we don't have it yet. Either it gets created during encoding @@ -941,16 +749,30 @@ loser: return SECFailure; } -CSSM_DATA_PTR +SecAsn1Item * SecCmsSignedDataGetDigestByAlgTag(SecCmsSignedDataRef sigd, SECOidTag algtag) { int idx; - if(sigd->digests == NULL) { - return NULL; - } idx = SecCmsAlgArrayGetIndexByAlgTag(sigd->digestAlgorithms, algtag); - return sigd->digests[idx]; + return (idx >= 0)?(sigd->digests)[idx]:NULL; +} + +OSStatus +SecCmsSignedDataSetDigestContext(SecCmsSignedDataRef sigd, + SecCmsDigestContextRef digestContext) +{ + SECAlgorithmID **digestalgs; + SecAsn1Item * *digests; + + if (SecCmsDigestContextFinishMultiple(digestContext, &digestalgs, &digests) != SECSuccess) + goto loser; + if (SecCmsSignedDataSetDigests(sigd, digestalgs, digests) != SECSuccess) + goto loser; + + return 0; +loser: + return PORT_GetError(); } /* @@ -962,7 +784,7 @@ SecCmsSignedDataGetDigestByAlgTag(SecCmsSignedDataRef sigd, SECOidTag algtag) OSStatus SecCmsSignedDataSetDigests(SecCmsSignedDataRef sigd, SECAlgorithmID **digestalgs, - CSSM_DATA_PTR *digests) + SecAsn1Item * *digests) { int cnt, i, idx; @@ -971,21 +793,30 @@ SecCmsSignedDataSetDigests(SecCmsSignedDataRef sigd, return SECFailure; } + /* Since we'll generate a empty digest for content-less messages + whether or not they're detached, we have to avoid overwriting + externally set digest for detached content => return early */ + if (sigd->digests && sigd->digests[0]) + return 0; + /* we assume that the digests array is just not there yet */ +/* PORT_Assert(sigd->digests == NULL); if (sigd->digests != NULL) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } - +*/ /* now allocate one (same size as digestAlgorithms) */ - cnt = SecCmsArrayCount((void **)sigd->digestAlgorithms); - sigd->digests = PORT_ArenaZAlloc(sigd->cmsg->poolp, (cnt + 1) * sizeof(CSSM_DATA_PTR)); if (sigd->digests == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; + cnt = SecCmsArrayCount((void **)sigd->digestAlgorithms); + sigd->digests = PORT_ArenaZAlloc(sigd->contentInfo.cmsg->poolp, (cnt + 1) * sizeof(SecAsn1Item *)); + if (sigd->digests == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + return SECFailure; + } } - + for (i = 0; sigd->digestAlgorithms[i] != NULL; i++) { /* try to find the sigd's i'th digest algorithm in the array we passed in */ idx = SecCmsAlgArrayGetIndexByAlgID(digestalgs, sigd->digestAlgorithms[i]); @@ -995,8 +826,8 @@ SecCmsSignedDataSetDigests(SecCmsSignedDataRef sigd, } /* found it - now set it */ - if ((sigd->digests[i] = SECITEM_AllocItem(sigd->cmsg->poolp, NULL, 0)) == NULL || - SECITEM_CopyItem(sigd->cmsg->poolp, sigd->digests[i], digests[idx]) != SECSuccess) + if ((sigd->digests[i] = SECITEM_AllocItem(sigd->contentInfo.cmsg->poolp, NULL, 0)) == NULL || + SECITEM_CopyItem(sigd->contentInfo.cmsg->poolp, sigd->digests[i], digests[idx]) != SECSuccess) { PORT_SetError(SEC_ERROR_NO_MEMORY); return SECFailure; @@ -1008,20 +839,20 @@ SecCmsSignedDataSetDigests(SecCmsSignedDataRef sigd, OSStatus SecCmsSignedDataSetDigestValue(SecCmsSignedDataRef sigd, SECOidTag digestalgtag, - CSSM_DATA_PTR digestdata) + SecAsn1Item * digestdata) { - CSSM_DATA_PTR digest = NULL; + SecAsn1Item * digest = NULL; PLArenaPool *poolp; void *mark; int n, cnt; - poolp = sigd->cmsg->poolp; + poolp = sigd->contentInfo.cmsg->poolp; mark = PORT_ArenaMark(poolp); if (digestdata) { - digest = (CSSM_DATA_PTR) PORT_ArenaZAlloc(poolp,sizeof(CSSM_DATA)); + digest = (SecAsn1Item *) PORT_ArenaZAlloc(poolp,sizeof(SecAsn1Item)); /* copy digestdata item to arena (in case we have it and are not only making room) */ if (SECITEM_CopyItem(poolp, digest, digestdata) != SECSuccess) @@ -1031,7 +862,7 @@ SecCmsSignedDataSetDigestValue(SecCmsSignedDataRef sigd, /* now allocate one (same size as digestAlgorithms) */ if (sigd->digests == NULL) { cnt = SecCmsArrayCount((void **)sigd->digestAlgorithms); - sigd->digests = PORT_ArenaZAlloc(sigd->cmsg->poolp, (cnt + 1) * sizeof(CSSM_DATA_PTR)); + sigd->digests = PORT_ArenaZAlloc(sigd->contentInfo.cmsg->poolp, (cnt + 1) * sizeof(SecAsn1Item *)); if (sigd->digests == NULL) { PORT_SetError(SEC_ERROR_NO_MEMORY); return SECFailure; @@ -1044,7 +875,7 @@ SecCmsSignedDataSetDigestValue(SecCmsSignedDataRef sigd, /* if not found, add a digest */ if (n < 0) { - if (SecCmsSignedDataAddDigest((SecArenaPoolRef)poolp, sigd, digestalgtag, digest) != SECSuccess) + if (SecCmsSignedDataAddDigest(poolp, sigd, digestalgtag, digest) != SECSuccess) goto loser; } else { /* replace NULL pointer with digest item (and leak previous value) */ @@ -1060,12 +891,11 @@ loser: } OSStatus -SecCmsSignedDataAddDigest(SecArenaPoolRef pool, +SecCmsSignedDataAddDigest(PRArenaPool *poolp, SecCmsSignedDataRef sigd, SECOidTag digestalgtag, - CSSM_DATA_PTR digest) + SecAsn1Item * digest) { - PRArenaPool *poolp = (PRArenaPool *)pool; SECAlgorithmID *digestalg; void *mark; @@ -1093,7 +923,7 @@ loser: return SECFailure; } -CSSM_DATA_PTR +SecAsn1Item * SecCmsSignedDataGetDigestValue(SecCmsSignedDataRef sigd, SECOidTag digestalgtag) { int n; @@ -1155,7 +985,7 @@ SecCmsSignedDataCreateCertsOnly(SecCmsMessageRef cmsg, SecCertificateRef cert, B * "signed" should be id-data (as defined in section 4), and the content * field of the EncapsulatedContentInfo value should be omitted. */ - rv = SecCmsContentInfoSetContentData(cmsg, &(sigd->contentInfo), NULL, PR_TRUE); + rv = SecCmsContentInfoSetContentData(&(sigd->contentInfo), NULL, PR_TRUE); if (rv != SECSuccess) goto loser; @@ -1169,17 +999,6 @@ loser: return NULL; } -/* - * Get SecCmsSignedDataRawCerts - obtain raw certs as a NULL_terminated array - * of pointers. - */ -extern OSStatus SecCmsSignedDataRawCerts(SecCmsSignedDataRef sigd, - CSSM_DATA_PTR **rawCerts) -{ - *rawCerts = sigd->rawCerts; - return noErr; -} - /* TODO: * SecCmsSignerInfoGetReceiptRequest() * SecCmsSignedDataHasReceiptRequest() diff --git a/libsecurity_smime/lib/cmssiginfo.c b/libsecurity_smime/lib/cmssiginfo.c index 4071fe39..41ab2e23 100644 --- a/libsecurity_smime/lib/cmssiginfo.c +++ b/libsecurity_smime/lib/cmssiginfo.c @@ -41,22 +41,25 @@ #include "cmslocal.h" #include "cert.h" -#include "secitem.h" +#include "SecAsn1Item.h" #include "secoid.h" #include "cryptohi.h" #include #include +#include + +#if USE_CDSA_CRYPTO #include +#endif + #include -#include +#include +#include #include +#include #include -#include -#include -#include "tsaSupport.h" -#include "tsaSupportPriv.h" #define HIDIGIT(v) (((v) / 10) + '0') #define LODIGIT(v) (((v) % 10) + '0') @@ -68,29 +71,12 @@ (var) = ((p)[0] - '0') * 10 + ((p)[1] - '0'); \ } -#ifndef NDEBUG -#define SIGINFO_DEBUG 1 -#endif - -#if SIGINFO_DEBUG -#define dprintf(args...) printf(args) -#else -#define dprintf(args...) -#endif - -#if RELEASECOUNTDEBUG -#define dprintfRC(args...) dprintf(args) -#else -#define dprintfRC(args...) -#endif static OSStatus -DER_UTCTimeToCFDate(const CSSM_DATA_PTR utcTime, CFAbsoluteTime *date) +DER_UTCTimeToCFDate(const SecAsn1Item * utcTime, CFAbsoluteTime *date) { - CFGregorianDate gdate; char *string = (char *)utcTime->Data; - long year, month, mday, hour, minute, second, hourOff, minOff; - CFTimeZoneRef timeZone; + int year, month, mday, hour, minute, second, hourOff, minOff; /* Verify time is formatted properly and capture information */ second = 0; @@ -99,7 +85,9 @@ DER_UTCTimeToCFDate(const CSSM_DATA_PTR utcTime, CFAbsoluteTime *date) CAPTURE(year,string+0,loser); if (year < 50) { /* ASSUME that year # is in the 2000's, not the 1900's */ - year += 100; + year += 2000; + } else { + year += 1900; } CAPTURE(month,string+2,loser); if ((month == 0) || (month > 12)) goto loser; @@ -130,24 +118,14 @@ DER_UTCTimeToCFDate(const CSSM_DATA_PTR utcTime, CFAbsoluteTime *date) goto loser; } - gdate.year = (SInt32)(year + 1900); - gdate.month = month; - gdate.day = mday; - gdate.hour = hour; - gdate.minute = minute; - gdate.second = second; - - if (hourOff == 0 && minOff == 0) - timeZone = NULL; /* GMT */ - else - { - timeZone = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, (hourOff * 60 + minOff) * 60); + if (hourOff == 0 && minOff == 0) { + *date = CFAbsoluteTimeForGregorianZuluMoment(year, month, mday, hour, minute, second); + } else { + CFTimeZoneRef tz = CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, (hourOff * 60 + minOff) * 60); + *date = CFAbsoluteTimeForGregorianMoment(tz, year, month, mday, hour, minute, second); + CFReleaseSafe(tz); } - *date = CFGregorianDateGetAbsoluteTime(gdate, timeZone); - if (timeZone) - CFRelease(timeZone); - return SECSuccess; loser: @@ -155,36 +133,44 @@ loser: } static OSStatus -DER_CFDateToUTCTime(CFAbsoluteTime date, CSSM_DATA_PTR utcTime) +DER_CFDateToUTCTime(CFAbsoluteTime date, SecAsn1Item * utcTime) { - CFGregorianDate gdate = CFAbsoluteTimeGetGregorianDate(date, NULL /* GMT */); unsigned char *d; - SInt8 second; utcTime->Length = 13; utcTime->Data = d = PORT_Alloc(13); if (!utcTime->Data) return SECFailure; + int year; + int month; + int day; + int hour; + int minute; + int second; + + if (!CFCalendarDecomposeAbsoluteTime(SecCFCalendarGetZulu(), date, "yMdHms", &year, &month, &day, &hour, &minute, &second)) + return SECFailure; + + /* UTC time does not handle the years before 1950 */ - if (gdate.year < 1950) - return SECFailure; + if (year < 1950) + return SECFailure; /* remove the century since it's added to the year by the CFAbsoluteTimeGetGregorianDate routine, but is not needed for UTC time */ - gdate.year %= 100; - second = gdate.second + 0.5; - - d[0] = HIDIGIT(gdate.year); - d[1] = LODIGIT(gdate.year); - d[2] = HIDIGIT(gdate.month); - d[3] = LODIGIT(gdate.month); - d[4] = HIDIGIT(gdate.day); - d[5] = LODIGIT(gdate.day); - d[6] = HIDIGIT(gdate.hour); - d[7] = LODIGIT(gdate.hour); - d[8] = HIDIGIT(gdate.minute); - d[9] = LODIGIT(gdate.minute); + year %= 100; + + d[0] = HIDIGIT(year); + d[1] = LODIGIT(year); + d[2] = HIDIGIT(month); + d[3] = LODIGIT(month); + d[4] = HIDIGIT(day); + d[5] = LODIGIT(day); + d[6] = HIDIGIT(hour); + d[7] = LODIGIT(hour); + d[8] = HIDIGIT(minute); + d[9] = LODIGIT(minute); d[10] = HIDIGIT(second); d[11] = LODIGIT(second); d[12] = 'Z'; @@ -195,16 +181,16 @@ DER_CFDateToUTCTime(CFAbsoluteTime date, CSSM_DATA_PTR utcTime) * SIGNERINFO */ SecCmsSignerInfoRef -nss_cmssignerinfo_create(SecCmsMessageRef cmsg, SecCmsSignerIDSelector type, SecCertificateRef cert, CSSM_DATA_PTR subjKeyID, SecPublicKeyRef pubKey, SecPrivateKeyRef signingKey, SECOidTag digestalgtag); +nss_cmssignerinfo_create(SecCmsSignedDataRef sigd, SecCmsSignerIDSelector type, SecCertificateRef cert, const SecAsn1Item *subjKeyID, SecPublicKeyRef pubKey, SecPrivateKeyRef signingKey, SECOidTag digestalgtag); SecCmsSignerInfoRef -SecCmsSignerInfoCreateWithSubjKeyID(SecCmsMessageRef cmsg, CSSM_DATA_PTR subjKeyID, SecPublicKeyRef pubKey, SecPrivateKeyRef signingKey, SECOidTag digestalgtag) +SecCmsSignerInfoCreateWithSubjKeyID(SecCmsSignedDataRef sigd, const SecAsn1Item *subjKeyID, SecPublicKeyRef pubKey, SecPrivateKeyRef signingKey, SECOidTag digestalgtag) { - return nss_cmssignerinfo_create(cmsg, SecCmsSignerIDSubjectKeyID, NULL, subjKeyID, pubKey, signingKey, digestalgtag); + return nss_cmssignerinfo_create(sigd, SecCmsSignerIDSubjectKeyID, NULL, subjKeyID, pubKey, signingKey, digestalgtag); } SecCmsSignerInfoRef -SecCmsSignerInfoCreate(SecCmsMessageRef cmsg, SecIdentityRef identity, SECOidTag digestalgtag) +SecCmsSignerInfoCreate(SecCmsSignedDataRef sigd, SecIdentityRef identity, SECOidTag digestalgtag) { SecCmsSignerInfoRef signerInfo = NULL; SecCertificateRef cert = NULL; @@ -215,7 +201,7 @@ SecCmsSignerInfoCreate(SecCmsMessageRef cmsg, SecIdentityRef identity, SECOidTag if (SecIdentityCopyPrivateKey(identity, &signingKey)) goto loser; - signerInfo = nss_cmssignerinfo_create(cmsg, SecCmsSignerIDIssuerSN, cert, NULL, NULL, signingKey, digestalgtag); + signerInfo = nss_cmssignerinfo_create(sigd, SecCmsSignerIDIssuerSN, cert, NULL, NULL, signingKey, digestalgtag); loser: if (cert) @@ -227,14 +213,14 @@ loser: } SecCmsSignerInfoRef -nss_cmssignerinfo_create(SecCmsMessageRef cmsg, SecCmsSignerIDSelector type, SecCertificateRef cert, CSSM_DATA_PTR subjKeyID, SecPublicKeyRef pubKey, SecPrivateKeyRef signingKey, SECOidTag digestalgtag) +nss_cmssignerinfo_create(SecCmsSignedDataRef sigd, SecCmsSignerIDSelector type, SecCertificateRef cert, const SecAsn1Item *subjKeyID, SecPublicKeyRef pubKey, SecPrivateKeyRef signingKey, SECOidTag digestalgtag) { void *mark; SecCmsSignerInfoRef signerinfo; int version; PLArenaPool *poolp; - poolp = cmsg->poolp; + poolp = sigd->contentInfo.cmsg->poolp; mark = PORT_ArenaMark(poolp); @@ -245,7 +231,7 @@ nss_cmssignerinfo_create(SecCmsMessageRef cmsg, SecCmsSignerIDSelector type, Sec } - signerinfo->cmsg = cmsg; + signerinfo->signedData = sigd; switch(type) { case SecCmsSignerIDIssuerSN: @@ -254,15 +240,13 @@ nss_cmssignerinfo_create(SecCmsMessageRef cmsg, SecCmsSignerIDSelector type, Sec goto loser; if ((signerinfo->signerIdentifier.id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert)) == NULL) goto loser; - dprintfRC("nss_cmssignerinfo_create: SecCmsSignerIDIssuerSN: cert.rc %d\n", - (int)CFGetRetainCount(signerinfo->cert)); break; case SecCmsSignerIDSubjectKeyID: signerinfo->signerIdentifier.identifierType = SecCmsSignerIDSubjectKeyID; PORT_Assert(subjKeyID); if (!subjKeyID) goto loser; - signerinfo->signerIdentifier.id.subjectKeyID = PORT_ArenaNew(poolp, CSSM_DATA); + signerinfo->signerIdentifier.id.subjectKeyID = PORT_ArenaNew(poolp, SecAsn1Item); SECITEM_CopyItem(poolp, signerinfo->signerIdentifier.id.subjectKeyID, subjKeyID); signerinfo->pubKey = SECKEY_CopyPublicKey(pubKey); @@ -290,6 +274,9 @@ nss_cmssignerinfo_create(SecCmsMessageRef cmsg, SecCmsSignerIDSelector type, Sec if (SECOID_SetAlgorithmID(poolp, &signerinfo->digestAlg, digestalgtag, NULL) != SECSuccess) goto loser; + if (SecCmsSignedDataAddSignerInfo(sigd, signerinfo)) + goto loser; + PORT_ArenaUnmark(poolp, mark); return signerinfo; @@ -304,55 +291,60 @@ loser: void SecCmsSignerInfoDestroy(SecCmsSignerInfoRef si) { - if (si->cert != NULL) { - dprintfRC("SecCmsSignerInfoDestroy top: certp %p cert.rc %d\n", - si->cert, (int)CFGetRetainCount(si->cert)); + if (si->cert != NULL) CERT_DestroyCertificate(si->cert); - } - if (si->certList != NULL) { - dprintfRC("SecCmsSignerInfoDestroy top: certList.rc %d\n", - (int)CFGetRetainCount(si->certList)); + + if (si->certList != NULL) CFRelease(si->certList); - } - if (si->timestampCertList != NULL) { - dprintfRC("SecCmsSignerInfoDestroy top: timestampCertList.rc %d\n", - (int)CFGetRetainCount(si->timestampCertList)); - CFRelease(si->timestampCertList); - } + /* XXX storage ??? */ } +static SecAsn1AlgId SecCertificateGetPublicKeyAlgorithmID(SecCertificateRef cert) +{ + const DERAlgorithmId *length_data_swapped = SecCertificateGetPublicKeyAlgorithm(cert); + SecAsn1AlgId temp = { + { length_data_swapped->oid.length, length_data_swapped->oid.data }, + { length_data_swapped->params.length, length_data_swapped->params.data } }; + + return temp; +} + /* * SecCmsSignerInfoSign - sign something * */ OSStatus -SecCmsSignerInfoSign(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR digest, CSSM_DATA_PTR contentType) +SecCmsSignerInfoSign(SecCmsSignerInfoRef signerinfo, SecAsn1Item * digest, SecAsn1Item * contentType) { SecCertificateRef cert; SecPrivateKeyRef privkey = NULL; SECOidTag digestalgtag; SECOidTag pubkAlgTag; - CSSM_DATA signature = { 0 }; + SecAsn1Item signature = { 0 }; OSStatus rv; PLArenaPool *poolp, *tmppoolp; - const SECAlgorithmID *algID; - SECAlgorithmID freeAlgID; + const SECAlgorithmID *algID = NULL; //CERTSubjectPublicKeyInfo *spki; PORT_Assert (digest != NULL); - poolp = signerinfo->cmsg->poolp; + poolp = signerinfo->signedData->contentInfo.cmsg->poolp; switch (signerinfo->signerIdentifier.identifierType) { case SecCmsSignerIDIssuerSN: privkey = signerinfo->signingKey; signerinfo->signingKey = NULL; cert = signerinfo->cert; +#if USE_CDSA_CRYPTO if (SecCertificateGetAlgorithmID(cert,&algID)) { PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); goto loser; } +#else + SecAsn1AlgId _algID = SecCertificateGetPublicKeyAlgorithmID(cert); + algID = &_algID; +#endif break; case SecCmsSignerIDSubjectKeyID: privkey = signerinfo->signingKey; @@ -365,28 +357,27 @@ SecCmsSignerInfoSign(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR digest, CSSM_ SECKEY_DestroySubjectPublicKeyInfo(spki); algID = &freeAlgID; #else +#if USE_CDSA_CRYPTO if (SecKeyGetAlgorithmID(signerinfo->pubKey,&algID)) { PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); goto loser; } +#endif +#endif CFRelease(signerinfo->pubKey); signerinfo->pubKey = NULL; -#endif break; default: PORT_SetError(SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE); goto loser; } digestalgtag = SecCmsSignerInfoGetDigestAlgTag(signerinfo); - /* - * XXX I think there should be a cert-level interface for this, - * so that I do not have to know about subjectPublicKeyInfo... - */ pubkAlgTag = SECOID_GetAlgorithmTag(algID); +#if USE_CDSA_CRYPTO if (signerinfo->signerIdentifier.identifierType == SecCmsSignerIDSubjectKeyID) { SECOID_DestroyAlgorithmID(&freeAlgID, PR_FALSE); } - +#endif #if 0 // @@@ Not yet /* Fortezza MISSI have weird signature formats. @@ -396,7 +387,7 @@ SecCmsSignerInfoSign(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR digest, CSSM_ #endif if (signerinfo->authAttr != NULL) { - CSSM_DATA encoded_attrs; + SecAsn1Item encoded_attrs; /* find and fill in the message digest attribute. */ rv = SecCmsAttributeArraySetAttr(poolp, &(signerinfo->authAttr), @@ -438,11 +429,37 @@ SecCmsSignerInfoSign(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR digest, CSSM_ &encoded_attrs) == NULL) goto loser; - rv = SEC_SignData(&signature, encoded_attrs.Data, (int)encoded_attrs.Length, +#if USE_CDSA_CRYPTO + rv = SEC_SignData(&signature, encoded_attrs.Data, encoded_attrs.Length, privkey, digestalgtag, pubkAlgTag); +#else + signature.Length = SecKeyGetSize(privkey, kSecKeySignatureSize); + signature.Data = PORT_ZAlloc(signature.Length); + if (!signature.Data) { + signature.Length = 0; + goto loser; + } + rv = SecKeyDigestAndSign(privkey, &signerinfo->digestAlg, encoded_attrs.Data, encoded_attrs.Length, signature.Data, &signature.Length); + if (rv) { + PORT_ZFree(signature.Data, signature.Length); + signature.Length = 0; + } +#endif + PORT_FreeArena(tmppoolp, PR_FALSE); /* awkward memory management :-( */ } else { - rv = SGN_Digest(privkey, digestalgtag, pubkAlgTag, &signature, digest); + signature.Length = SecKeyGetSize(privkey, kSecKeySignatureSize); + signature.Data = PORT_ZAlloc(signature.Length); + if (!signature.Data) { + signature.Length = 0; + goto loser; + } + rv = SecKeySignDigest(privkey, &signerinfo->digestAlg, digest->Data, digest->Length, + signature.Data, &signature.Length); + if (rv) { + PORT_ZFree(signature.Data, signature.Length); + signature.Length = 0; + } } SECKEY_DestroyPrivateKey(privkey); privkey = NULL; @@ -456,23 +473,6 @@ SecCmsSignerInfoSign(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR digest, CSSM_ SECITEM_FreeItem(&signature, PR_FALSE); - if(pubkAlgTag == SEC_OID_EC_PUBLIC_KEY) { - /* - * RFC 3278 section section 2.1.1 states that the signatureAlgorithm - * field contains the full ecdsa-with-SHA1 OID, not plain old ecPublicKey - * as would appear in other forms of signed datas. However Microsoft doesn't - * do this, it puts ecPublicKey there, and if we put ecdsa-with-SHA1 there, - * MS can't verify - presumably because it takes the digest of the digest - * before feeding it to ECDSA. - * We handle this with a preference; default if it's not there is - * "Microsoft compatibility mode". - */ - if(!SecCmsMsEcdsaCompatMode()) { - pubkAlgTag = SEC_OID_ECDSA_WithSHA1; - } - /* else violating the spec for compatibility */ - } - if (SECOID_SetAlgorithmID(poolp, &(signerinfo->digestEncAlg), pubkAlgTag, NULL) != SECSuccess) goto loser; @@ -484,44 +484,91 @@ loser: SECITEM_FreeItem (&signature, PR_FALSE); if (privkey) SECKEY_DestroyPrivateKey(privkey); - if((algID != NULL) & (algID != &freeAlgID)) { - /* this is dicey - this was actually mallocd by either SecCertificate or - * by SecKey...it all boils down to a free() in the end though. */ - SECOID_DestroyAlgorithmID((SECAlgorithmID *)algID, PR_FALSE); - } return SECFailure; } +#if !USE_CDSA_CRYPTO +static CFArrayRef +SecCmsSignerInfoCopySigningCertificates(SecCmsSignerInfoRef signerinfo) +{ + CFMutableArrayRef certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + SecAsn1Item **cert_datas = signerinfo->signedData->rawCerts; + SecAsn1Item *cert_data; + if (cert_datas) while ((cert_data = *cert_datas) != NULL) { + SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, cert_data->Data, cert_data->Length); + if (cert) { + switch (signerinfo->signerIdentifier.identifierType) { + case SecCmsSignerIDIssuerSN: + if (CERT_CheckIssuerAndSerial(cert, + &(signerinfo->signerIdentifier.id.issuerAndSN->derIssuer), + &(signerinfo->signerIdentifier.id.issuerAndSN->serialNumber))) + CFArrayInsertValueAtIndex(certs, 0, cert); + else + CFArrayAppendValue(certs, cert); + break; + case SecCmsSignerIDSubjectKeyID: + { + CFDataRef cert_keyid = SecCertificateGetSubjectKeyID(cert); + SecAsn1Item *tbf_keyid = signerinfo->signerIdentifier.id.subjectKeyID; + if (tbf_keyid->Length == (size_t)CFDataGetLength(cert_keyid) && + !memcmp(tbf_keyid->Data, CFDataGetBytePtr(cert_keyid), tbf_keyid->Length)) + CFArrayInsertValueAtIndex(certs, 0, cert); + else + CFArrayAppendValue(certs, cert); + break; + } + } + CFReleaseNull(cert); + } + cert_datas++; + } + + if ((CFArrayGetCount(certs) == 0) && + (signerinfo->signerIdentifier.identifierType == SecCmsSignerIDIssuerSN)) + { + SecCertificateRef cert = CERT_FindCertificateByIssuerAndSN(signerinfo->signedData->certs, signerinfo->signerIdentifier.id.issuerAndSN); + if (cert) { + CFArrayAppendValue(certs, cert); + CFRelease(cert); + } + } + return certs; +} +#endif + OSStatus SecCmsSignerInfoVerifyCertificate(SecCmsSignerInfoRef signerinfo, SecKeychainRef keychainOrArray, CFTypeRef policies, SecTrustRef *trustRef) { - SecCertificateRef cert; CFAbsoluteTime stime; OSStatus rv; - CSSM_DATA_PTR *otherCerts; + +#if USE_CDSA_CRYPTO + SecCertificateRef cert; if ((cert = SecCmsSignerInfoGetSigningCertificate(signerinfo, keychainOrArray)) == NULL) { - dprintf("SecCmsSignerInfoVerifyCertificate: no signing cert\n"); +#else + CFArrayRef certs; + + if ((certs = SecCmsSignerInfoCopySigningCertificates(signerinfo)) == NULL) { +#endif signerinfo->verificationStatus = SecCmsVSSigningCertNotFound; return SECFailure; } - /* * Get and convert the signing time; if available, it will be used * both on the cert verification and for importing the sender * email profile. */ - if (SecCmsSignerInfoGetTimestampTime(signerinfo, &stime) != SECSuccess) - if (SecCmsSignerInfoGetSigningTime(signerinfo, &stime) != SECSuccess) - stime = CFAbsoluteTimeGetCurrent(); - rv = SecCmsSignedDataRawCerts(signerinfo->sigd, &otherCerts); - if(rv) { - return rv; - } - rv = CERT_VerifyCert(keychainOrArray, cert, otherCerts, policies, stime, trustRef); - dprintfRC("SecCmsSignerInfoVerifyCertificate after vfy: certp %p cert.rc %d\n", - cert, (int)CFGetRetainCount(cert)); + if (SecCmsSignerInfoGetSigningTime(signerinfo, &stime) != SECSuccess) + stime = CFAbsoluteTimeGetCurrent(); + +#if USE_CDSA_CRYPTO + rv = CERT_VerifyCert(keychainOrArray, cert, policies, stime, trustRef); +#else + rv = CERT_VerifyCert(keychainOrArray, certs, policies, stime, trustRef); + CFRelease(certs); +#endif if (rv || !trustRef) { if (PORT_GetError() == SEC_ERROR_UNTRUSTED_CERT) @@ -531,26 +578,8 @@ SecCmsSignerInfoVerifyCertificate(SecCmsSignerInfoRef signerinfo, SecKeychainRef signerinfo->verificationStatus = SecCmsVSSigningCertNotTrusted; } } - /* FIXME isn't this leaking the cert? */ - dprintf("SecCmsSignerInfoVerifyCertificate: CertVerify rtn %d\n", (int)rv); - return rv; -} -static void debugShowSigningCertificate(SecCmsSignerInfoRef signerinfo) -{ -#if SIGINFO_DEBUG - CFStringRef cn = SecCmsSignerInfoGetSignerCommonName(signerinfo); - if (cn) - { - char *ccn = cfStringToChar(cn); - if (ccn) - { - dprintf("SecCmsSignerInfoVerify: cn: %s\n", ccn); - free(ccn); - } - CFRelease(cn); - } -#endif + return rv; } /* @@ -560,49 +589,39 @@ static void debugShowSigningCertificate(SecCmsSignerInfoRef signerinfo) * is done already. */ OSStatus -SecCmsSignerInfoVerify(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR digest, CSSM_DATA_PTR contentType) +SecCmsSignerInfoVerify(SecCmsSignerInfoRef signerinfo, SecAsn1Item * digest, SecAsn1Item * contentType) { SecPublicKeyRef publickey = NULL; SecCmsAttribute *attr; - CSSM_DATA encoded_attrs; + SecAsn1Item encoded_attrs; SecCertificateRef cert; SecCmsVerificationStatus vs = SecCmsVSUnverified; PLArenaPool *poolp; SECOidTag digestAlgTag, digestEncAlgTag; - + if (signerinfo == NULL) return SECFailure; - + /* SecCmsSignerInfoGetSigningCertificate will fail if 2nd parm is NULL and */ /* cert has not been verified */ if ((cert = SecCmsSignerInfoGetSigningCertificate(signerinfo, NULL)) == NULL) { - dprintf("SecCmsSignerInfoVerify: no signing cert\n"); vs = SecCmsVSSigningCertNotFound; goto loser; } - dprintfRC("SecCmsSignerInfoVerify top: cert %p cert.rc %d\n", cert, (int)CFGetRetainCount(cert)); - - debugShowSigningCertificate(signerinfo); - +#if USE_CDSA_CRYPTO if (SecCertificateCopyPublicKey(cert, &publickey)) { vs = SecCmsVSProcessingError; goto loser; } +#else + publickey = SecCertificateCopyPublicKey(cert); + if (publickey == NULL) + goto loser; +#endif digestAlgTag = SECOID_GetAlgorithmTag(&(signerinfo->digestAlg)); digestEncAlgTag = SECOID_GetAlgorithmTag(&(signerinfo->digestEncAlg)); - - /* - * Gross hack necessitated by RFC 3278 section 2.1.1, which states - * that the signature algorithm (here, digestEncAlg) contains ecdsa_with-SHA1, - * *not* (as in all other algorithms) the raw signature algorithm, e.g. - * pkcs1RSAEncryption. - */ - if(digestEncAlgTag == SEC_OID_ECDSA_WithSHA1) { - digestEncAlgTag = SEC_OID_EC_PUBLIC_KEY; - } - if (!SecCmsArrayIsEmpty((void **)signerinfo->authAttr)) { if (contentType) { /* @@ -661,40 +680,25 @@ SecCmsSignerInfoVerify(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR digest, CSS vs = SecCmsVSProcessingError; goto loser; } - - vs = (VFY_VerifyData (encoded_attrs.Data, (int)encoded_attrs.Length, - publickey, &(signerinfo->encDigest), - digestAlgTag, digestEncAlgTag, - signerinfo->cmsg->pwfn_arg) != SECSuccess) ? SecCmsVSBadSignature : SecCmsVSGoodSignature; - - dprintf("VFY_VerifyData (authenticated attributes): %s\n", - (vs == SecCmsVSGoodSignature)?"SecCmsVSGoodSignature":"SecCmsVSBadSignature"); + if (errSecSuccess == SecKeyDigestAndVerify(publickey, &signerinfo->digestAlg, encoded_attrs.Data, encoded_attrs.Length, signerinfo->encDigest.Data, signerinfo->encDigest.Length)) + vs = SecCmsVSGoodSignature; + else + vs = SecCmsVSBadSignature; PORT_FreeArena(poolp, PR_FALSE); /* awkward memory management :-( */ } else { - CSSM_DATA_PTR sig; + SecAsn1Item * sig; /* No authenticated attributes. The signature is based on the plain message digest. */ sig = &(signerinfo->encDigest); if (sig->Length == 0) goto loser; - vs = (VFY_VerifyDigest(digest, publickey, sig, - digestAlgTag, digestEncAlgTag, - signerinfo->cmsg->pwfn_arg) != SECSuccess) ? SecCmsVSBadSignature : SecCmsVSGoodSignature; - - dprintf("VFY_VerifyData (plain message digest): %s\n", - (vs == SecCmsVSGoodSignature)?"SecCmsVSGoodSignature":"SecCmsVSBadSignature"); - } - - if (!SecCmsArrayIsEmpty((void **)signerinfo->unAuthAttr)) - { - dprintf("found an unAuthAttr\n"); - OSStatus rux = SecCmsSignerInfoVerifyUnAuthAttrs(signerinfo); - dprintf("SecCmsSignerInfoVerifyUnAuthAttrs Status: %ld\n", (long)rux); - if (rux) - goto loser; + if (SecKeyVerifyDigest(publickey, &signerinfo->digestAlg, digest->Data, digest->Length, sig->Data, sig->Length)) + vs = SecCmsVSBadSignature; + else + vs = SecCmsVSGoodSignature; } if (vs == SecCmsVSBadSignature) { @@ -722,10 +726,6 @@ SecCmsSignerInfoVerify(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR digest, CSS CFRelease(publickey); signerinfo->verificationStatus = vs; - dprintfRC("SecCmsSignerInfoVerify end: cerp %p cert.rc %d\n", - cert, (int)CFGetRetainCount(cert)); - - dprintf("verificationStatus: %d\n", vs); return (vs == SecCmsVSGoodSignature) ? SECSuccess : SECFailure; @@ -733,49 +733,12 @@ loser: if (publickey != NULL) SECKEY_DestroyPublicKey (publickey); - dprintf("verificationStatus2: %d\n", vs); signerinfo->verificationStatus = vs; PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE); return SECFailure; } - -OSStatus -SecCmsSignerInfoVerifyUnAuthAttrs(SecCmsSignerInfoRef signerinfo) -{ - /* - unAuthAttr is an array of attributes; we expect to - see just one: the timestamp blob. If we have an unAuthAttr, - but don't see a timestamp, return an error since we have - no other cases where this would be present. - */ - - SecCmsAttribute *attr = NULL; - OSStatus status = SECFailure; - - require(signerinfo, xit); - attr = SecCmsAttributeArrayFindAttrByOidTag(signerinfo->unAuthAttr, - SEC_OID_PKCS9_TIMESTAMP_TOKEN, PR_TRUE); - if (attr == NULL) - { - status = errSecTimestampMissing; - goto xit; - } - - dprintf("found an id-ct-TSTInfo\n"); - // Don't check the nonce in this case - status = decodeTimeStampToken(signerinfo, (attr->values)[0], &signerinfo->encDigest, 0); -xit: - return status; -} - -CSSM_DATA * -SecCmsSignerInfoGetEncDigest(SecCmsSignerInfoRef signerinfo) -{ - return &signerinfo->encDigest; -} - SecCmsVerificationStatus SecCmsSignerInfoGetVerificationStatus(SecCmsSignerInfoRef signerinfo) { @@ -803,27 +766,15 @@ SecCmsSignerInfoGetDigestAlgTag(SecCmsSignerInfoRef signerinfo) CFArrayRef SecCmsSignerInfoGetCertList(SecCmsSignerInfoRef signerinfo) { - dprintfRC("SecCmsSignerInfoGetCertList: certList.rc %d\n", - (int)CFGetRetainCount(signerinfo->certList)); return signerinfo->certList; } -CFArrayRef -SecCmsSignerInfoGetTimestampCertList(SecCmsSignerInfoRef signerinfo) -{ - dprintfRC("SecCmsSignerInfoGetCertList: timestampCertList.rc %d\n", - (int)CFGetRetainCount(signerinfo->timestampCertList)); - return signerinfo->timestampCertList; -} - - - int SecCmsSignerInfoGetVersion(SecCmsSignerInfoRef signerinfo) { unsigned long version; - /* always take apart the CSSM_DATA */ + /* always take apart the SecAsn1Item */ if (SEC_ASN1DecodeInteger(&(signerinfo->version), &version) != SECSuccess) return 0; else @@ -843,10 +794,10 @@ OSStatus SecCmsSignerInfoGetSigningTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *stime) { SecCmsAttribute *attr; - CSSM_DATA_PTR value; + SecAsn1Item * value; if (sinfo == NULL) - return paramErr; + return SECFailure; if (sinfo->signingTime != 0) { *stime = sinfo->signingTime; /* cached copy */ @@ -856,33 +807,13 @@ SecCmsSignerInfoGetSigningTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *stime) attr = SecCmsAttributeArrayFindAttrByOidTag(sinfo->authAttr, SEC_OID_PKCS9_SIGNING_TIME, PR_TRUE); /* XXXX multi-valued attributes NIH */ if (attr == NULL || (value = SecCmsAttributeGetValue(attr)) == NULL) - return errSecSigningTimeMissing; + return SECFailure; if (DER_UTCTimeToCFDate(value, stime) != SECSuccess) - return errSecSigningTimeMissing; + return SECFailure; sinfo->signingTime = *stime; /* make cached copy */ return SECSuccess; } -OSStatus -SecCmsSignerInfoGetTimestampTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *stime) -{ - OSStatus status = paramErr; - - require(sinfo && stime, xit); - - if (sinfo->timestampTime != 0) - { - *stime = sinfo->timestampTime; /* cached copy */ - return noErr; - } - - // A bit heavyweight if haven't already called verify - status = SecCmsSignerInfoVerifyUnAuthAttrs(sinfo); - *stime = sinfo->timestampTime; -xit: - return status; -} - /* * Return the signing cert of a CMS signerInfo. * @@ -891,23 +822,17 @@ xit: SecCertificateRef SecCmsSignerInfoGetSigningCertificate(SecCmsSignerInfoRef signerinfo, SecKeychainRef keychainOrArray) { - SecCertificateRef cert; - SecCmsSignerIdentifier *sid; - OSStatus ortn; - CSSM_DATA_PTR *rawCerts; - - if (signerinfo->cert != NULL) { - dprintfRC("SecCmsSignerInfoGetSigningCertificate top: cert %p cert.rc %d\n", - signerinfo->cert, (int)CFGetRetainCount(signerinfo->cert)); + SecCertificateRef cert = NULL; + + if (signerinfo->cert != NULL) return signerinfo->cert; - } - ortn = SecCmsSignedDataRawCerts(signerinfo->sigd, &rawCerts); - if(ortn) { - return NULL; - } - dprintf("SecCmsSignerInfoGetSigningCertificate: numRawCerts %d\n", - SecCmsArrayCount((void **)rawCerts)); - + + /* @@@ Make sure we search though all the certs in the cms message itself as well, it's silly + to require them to be added to a keychain first. */ + +#if USE_CDSA_CRYPTO + SecCmsSignerIdentifier *sid; + /* * This cert will also need to be freed, but since we save it * in signerinfo for later, we do not want to destroy it when @@ -917,11 +842,10 @@ SecCmsSignerInfoGetSigningCertificate(SecCmsSignerInfoRef signerinfo, SecKeychai sid = &signerinfo->signerIdentifier; switch (sid->identifierType) { case SecCmsSignerIDIssuerSN: - cert = CERT_FindCertByIssuerAndSN(keychainOrArray, rawCerts, signerinfo->cmsg->poolp, - sid->id.issuerAndSN); + cert = CERT_FindCertByIssuerAndSN(keychainOrArray, sid->id.issuerAndSN); break; case SecCmsSignerIDSubjectKeyID: - cert = CERT_FindCertBySubjectKeyID(keychainOrArray, rawCerts, sid->id.subjectKeyID); + cert = CERT_FindCertBySubjectKeyID(keychainOrArray, sid->id.subjectKeyID); break; default: cert = NULL; @@ -930,12 +854,44 @@ SecCmsSignerInfoGetSigningCertificate(SecCmsSignerInfoRef signerinfo, SecKeychai /* cert can be NULL at that point */ signerinfo->cert = cert; /* earmark it */ - dprintfRC("SecCmsSignerInfoGetSigningCertificate end: certp %p cert.rc %d\n", - signerinfo->cert, (int)CFGetRetainCount(signerinfo->cert)); +#else + SecAsn1Item **cert_datas = signerinfo->signedData->rawCerts; + SecAsn1Item *cert_data; + if (cert_datas) while ((cert_data = *cert_datas) != NULL) { + cert = SecCertificateCreateWithBytes(NULL, cert_data->Data, cert_data->Length); + if (cert) { + switch (signerinfo->signerIdentifier.identifierType) { + case SecCmsSignerIDIssuerSN: + if (CERT_CheckIssuerAndSerial(cert, + &(signerinfo->signerIdentifier.id.issuerAndSN->derIssuer), + &(signerinfo->signerIdentifier.id.issuerAndSN->serialNumber))) + signerinfo->cert = cert; + break; + case SecCmsSignerIDSubjectKeyID: { + CFDataRef cert_keyid = SecCertificateGetSubjectKeyID(cert); + SecAsn1Item *tbf_keyid = signerinfo->signerIdentifier.id.subjectKeyID; + if (tbf_keyid->Length == (size_t)CFDataGetLength(cert_keyid) && + !memcmp(tbf_keyid->Data, CFDataGetBytePtr(cert_keyid), tbf_keyid->Length)) + signerinfo->cert = cert; + } + } + if (signerinfo->cert) + break; + CFReleaseNull(cert); + } + cert_datas++; + } + + if (!signerinfo->cert && (signerinfo->signerIdentifier.identifierType == SecCmsSignerIDIssuerSN)) { + cert = CERT_FindCertificateByIssuerAndSN(signerinfo->signedData->certs, signerinfo->signerIdentifier.id.issuerAndSN); + signerinfo->cert = cert; + } +#endif return cert; } + /* * SecCmsSignerInfoGetSignerCommonName - return the common name of the signer * @@ -954,7 +910,17 @@ SecCmsSignerInfoGetSignerCommonName(SecCmsSignerInfoRef sinfo) if ((signercert = SecCmsSignerInfoGetSigningCertificate(sinfo, NULL)) == NULL) return NULL; - SecCertificateCopyCommonName(signercert, &commonName); +#if USE_CDSA_CRYPTO + SecCertificateGetCommonName(signercert, &commonName); +#else + CFArrayRef commonNames = SecCertificateCopyCommonNames(signercert); + if (commonNames) { + /* SecCertificateCopyCommonNames doesn't return empty arrays */ + commonName = (CFStringRef)CFArrayGetValueAtIndex(commonNames, CFArrayGetCount(commonNames) - 1); + CFRetain(commonName); + CFRelease(commonNames); + } +#endif return commonName; } @@ -976,8 +942,18 @@ SecCmsSignerInfoGetSignerEmailAddress(SecCmsSignerInfoRef sinfo) if ((signercert = SecCmsSignerInfoGetSigningCertificate(sinfo, NULL)) == NULL) return NULL; +#if USE_CDSA_CRYPTO SecCertificateGetEmailAddress(signercert, &emailAddress); - +#else + CFArrayRef names = SecCertificateCopyRFC822Names(signercert); + if (names) { + if (CFArrayGetCount(names) > 0) + emailAddress = (CFStringRef)CFArrayGetValueAtIndex(names, 0); + if (emailAddress) + CFRetain(emailAddress); + CFRelease(names); + } +#endif return emailAddress; } @@ -989,7 +965,7 @@ SecCmsSignerInfoGetSignerEmailAddress(SecCmsSignerInfoRef sinfo) OSStatus SecCmsSignerInfoAddAuthAttr(SecCmsSignerInfoRef signerinfo, SecCmsAttribute *attr) { - return SecCmsAttributeArrayAddAttr(signerinfo->cmsg->poolp, &(signerinfo->authAttr), attr); + return SecCmsAttributeArrayAddAttr(signerinfo->signedData->contentInfo.cmsg->poolp, &(signerinfo->authAttr), attr); } /* @@ -999,7 +975,7 @@ SecCmsSignerInfoAddAuthAttr(SecCmsSignerInfoRef signerinfo, SecCmsAttribute *att OSStatus SecCmsSignerInfoAddUnauthAttr(SecCmsSignerInfoRef signerinfo, SecCmsAttribute *attr) { - return SecCmsAttributeArrayAddAttr(signerinfo->cmsg->poolp, &(signerinfo->unAuthAttr), attr); + return SecCmsAttributeArrayAddAttr(signerinfo->signedData->contentInfo.cmsg->poolp, &(signerinfo->unAuthAttr), attr); } /* @@ -1019,11 +995,11 @@ OSStatus SecCmsSignerInfoAddSigningTime(SecCmsSignerInfoRef signerinfo, CFAbsoluteTime t) { SecCmsAttribute *attr; - CSSM_DATA stime; + SecAsn1Item stime; void *mark; PLArenaPool *poolp; - poolp = signerinfo->cmsg->poolp; + poolp = signerinfo->signedData->contentInfo.cmsg->poolp; mark = PORT_ArenaMark(poolp); @@ -1061,11 +1037,11 @@ OSStatus SecCmsSignerInfoAddSMIMECaps(SecCmsSignerInfoRef signerinfo) { SecCmsAttribute *attr; - CSSM_DATA_PTR smimecaps = NULL; + SecAsn1Item * smimecaps = NULL; void *mark; PLArenaPool *poolp; - poolp = signerinfo->cmsg->poolp; + poolp = signerinfo->signedData->contentInfo.cmsg->poolp; mark = PORT_ArenaMark(poolp); @@ -1076,7 +1052,7 @@ SecCmsSignerInfoAddSMIMECaps(SecCmsSignerInfoRef signerinfo) /* create new signing time attribute */ #if 1 // @@@ We don't do Fortezza yet. - if (SecSMIMECreateSMIMECapabilities((SecArenaPoolRef)poolp, smimecaps, PR_FALSE) != SECSuccess) + if (SecSMIMECreateSMIMECapabilities(poolp, smimecaps, PR_FALSE) != SECSuccess) #else if (SecSMIMECreateSMIMECapabilities(poolp, smimecaps, PK11_FortezzaHasKEA(signerinfo->cert)) != SECSuccess) @@ -1107,7 +1083,7 @@ OSStatus SecCmsSignerInfoAddSMIMEEncKeyPrefs(SecCmsSignerInfoRef signerinfo, SecCertificateRef cert, SecKeychainRef keychainOrArray) { SecCmsAttribute *attr; - CSSM_DATA_PTR smimeekp = NULL; + SecAsn1Item * smimeekp = NULL; void *mark; PLArenaPool *poolp; @@ -1123,7 +1099,7 @@ SecCmsSignerInfoAddSMIMEEncKeyPrefs(SecCmsSignerInfoRef signerinfo, SecCertifica CFRelease(policy); #endif - poolp = signerinfo->cmsg->poolp; + poolp = signerinfo->signedData->contentInfo.cmsg->poolp; mark = PORT_ArenaMark(poolp); smimeekp = SECITEM_AllocItem(poolp, NULL, 0); @@ -1131,7 +1107,7 @@ SecCmsSignerInfoAddSMIMEEncKeyPrefs(SecCmsSignerInfoRef signerinfo, SecCertifica goto loser; /* create new signing time attribute */ - if (SecSMIMECreateSMIMEEncKeyPrefs((SecArenaPoolRef)poolp, smimeekp, cert) != SECSuccess) + if (SecSMIMECreateSMIMEEncKeyPrefs(poolp, smimeekp, cert) != SECSuccess) goto loser; if ((attr = SecCmsAttributeCreate(poolp, SEC_OID_SMIME_ENCRYPTION_KEY_PREFERENCE, smimeekp, PR_TRUE)) == NULL) @@ -1159,7 +1135,7 @@ OSStatus SecCmsSignerInfoAddMSSMIMEEncKeyPrefs(SecCmsSignerInfoRef signerinfo, SecCertificateRef cert, SecKeychainRef keychainOrArray) { SecCmsAttribute *attr; - CSSM_DATA_PTR smimeekp = NULL; + SecAsn1Item * smimeekp = NULL; void *mark; PLArenaPool *poolp; @@ -1175,7 +1151,7 @@ SecCmsSignerInfoAddMSSMIMEEncKeyPrefs(SecCmsSignerInfoRef signerinfo, SecCertifi CFRelease(policy); #endif - poolp = signerinfo->cmsg->poolp; + poolp = signerinfo->signedData->contentInfo.cmsg->poolp; mark = PORT_ArenaMark(poolp); smimeekp = SECITEM_AllocItem(poolp, NULL, 0); @@ -1183,7 +1159,7 @@ SecCmsSignerInfoAddMSSMIMEEncKeyPrefs(SecCmsSignerInfoRef signerinfo, SecCertifi goto loser; /* create new signing time attribute */ - if (SecSMIMECreateMSSMIMEEncKeyPrefs((SecArenaPoolRef)poolp, smimeekp, cert) != SECSuccess) + if (SecSMIMECreateMSSMIMEEncKeyPrefs(poolp, smimeekp, cert) != SECSuccess) goto loser; if ((attr = SecCmsAttributeCreate(poolp, SEC_OID_MS_SMIME_ENCRYPTION_KEY_PREFERENCE, smimeekp, PR_TRUE)) == NULL) @@ -1200,60 +1176,6 @@ loser: return SECFailure; } -/* - * SecCmsSignerInfoAddTimeStamp - add time stamp to the - * unauthenticated (i.e. unsigned) attributes of "signerinfo". - * - * This will initially be used for time stamping signed applications - * by using a Time Stamping Authority. It may also be included in outgoing signed - * messages for email (S/MIME), and may be useful in other situations. - * - * This should only be added once; a second call will do nothing. - * - */ - -/* -Countersignature attribute values have ASN.1 type Countersignature: - Countersignature ::= SignerInfo - Countersignature values have the same meaning as SignerInfo values - for ordinary signatures, except that: - 1. The signedAttributes field MUST NOT contain a content-type - attribute; there is no content type for countersignatures. - 2. The signedAttributes field MUST contain a message-digest - attribute if it contains any other attributes. - 3. The input to the message-digesting process is the contents octets - of the DER encoding of the signatureValue field of the SignerInfo - value with which the attribute is associated. -*/ - -/*! - @function - @abstract Create a timestamp unsigned attribute with a TimeStampToken. -*/ - -OSStatus -SecCmsSignerInfoAddTimeStamp(SecCmsSignerInfoRef signerinfo, CSSM_DATA *tstoken) -{ - SecCmsAttribute *attr; - PLArenaPool *poolp = signerinfo->cmsg->poolp; - void *mark = PORT_ArenaMark(poolp); - - // We have already encoded this ourselves, so last param is PR_TRUE - if ((attr = SecCmsAttributeCreate(poolp, SEC_OID_PKCS9_TIMESTAMP_TOKEN, tstoken, PR_TRUE)) == NULL) - goto loser; - - if (SecCmsSignerInfoAddUnauthAttr(signerinfo, attr) != SECSuccess) - goto loser; - - PORT_ArenaUnmark (poolp, mark); - - return SECSuccess; - -loser: - PORT_ArenaRelease (poolp, mark); - return SECFailure; -} - /* * SecCmsSignerInfoAddCounterSignature - countersign a signerinfo * @@ -1282,93 +1204,7 @@ SecCmsSignerInfoAddCounterSignature(SecCmsSignerInfoRef signerinfo, OSStatus SecCmsSignerInfoSaveSMIMEProfile(SecCmsSignerInfoRef signerinfo) { - SecCertificateRef cert = NULL; - CSSM_DATA_PTR profile = NULL; - SecCmsAttribute *attr; - CSSM_DATA_PTR utc_stime = NULL; - CSSM_DATA_PTR ekp; - int save_error; - OSStatus rv; - Boolean must_free_cert = PR_FALSE; - OSStatus status; - SecKeychainRef keychainOrArray; - - status = SecKeychainCopyDefault(&keychainOrArray); - - /* sanity check - see if verification status is ok (unverified does not count...) */ - if (signerinfo->verificationStatus != SecCmsVSGoodSignature) - return SECFailure; - - /* find preferred encryption cert */ - if (!SecCmsArrayIsEmpty((void **)signerinfo->authAttr) && - (attr = SecCmsAttributeArrayFindAttrByOidTag(signerinfo->authAttr, - SEC_OID_SMIME_ENCRYPTION_KEY_PREFERENCE, PR_TRUE)) != NULL) - { /* we have a SMIME_ENCRYPTION_KEY_PREFERENCE attribute! */ - ekp = SecCmsAttributeGetValue(attr); - if (ekp == NULL) - return SECFailure; - - /* we assume that all certs coming with the message have been imported to the */ - /* temporary database */ - cert = SecSMIMEGetCertFromEncryptionKeyPreference(keychainOrArray, ekp); - if (cert == NULL) - return SECFailure; - must_free_cert = PR_TRUE; - } - - if (cert == NULL) { - /* no preferred cert found? - * find the cert the signerinfo is signed with instead */ - CFStringRef emailAddress=NULL; - - cert = SecCmsSignerInfoGetSigningCertificate(signerinfo, keychainOrArray); - if (cert == NULL) - return SECFailure; - if (SecCertificateGetEmailAddress(cert,&emailAddress)) - return SECFailure; - } - - /* verify this cert for encryption (has been verified for signing so far) */ /* don't verify this cert for encryption. It may just be a signing cert. - * that's OK, we can still save the S/MIME profile. The encryption cert - * should have already been saved */ -#ifdef notdef - if (CERT_VerifyCert(keychainOrArray, cert, certUsageEmailRecipient, CFAbsoluteTimeGetCurrent(), NULL) != SECSuccess) { - if (must_free_cert) - CERT_DestroyCertificate(cert); - return SECFailure; - } -#endif - - /* XXX store encryption cert permanently? */ - - /* - * Remember the current error set because we do not care about - * anything set by the functions we are about to call. - */ - save_error = PORT_GetError(); - - if (!SecCmsArrayIsEmpty((void **)signerinfo->authAttr)) { - attr = SecCmsAttributeArrayFindAttrByOidTag(signerinfo->authAttr, - SEC_OID_PKCS9_SMIME_CAPABILITIES, - PR_TRUE); - profile = SecCmsAttributeGetValue(attr); - attr = SecCmsAttributeArrayFindAttrByOidTag(signerinfo->authAttr, - SEC_OID_PKCS9_SIGNING_TIME, - PR_TRUE); - utc_stime = SecCmsAttributeGetValue(attr); - } - - rv = CERT_SaveSMimeProfile (cert, profile, utc_stime); - if (must_free_cert) - CERT_DestroyCertificate(cert); - - /* - * Restore the saved error in case the calls above set a new - * one that we do not actually care about. - */ - PORT_SetError (save_error); - - return rv; + return -4 /*unImp*/; } /* diff --git a/libsecurity_smime/lib/cmstpriv.h b/libsecurity_smime/lib/cmstpriv.h index f2d10f49..e6fc277d 100644 --- a/libsecurity_smime/lib/cmstpriv.h +++ b/libsecurity_smime/lib/cmstpriv.h @@ -101,7 +101,7 @@ typedef struct SecCmsCipherContextStr *SecCmsCipherContextRef; union SecCmsContentUnion { /* either unstructured */ - CSSM_DATA_PTR data; + SecAsn1Item * data; /* or structured data */ SecCmsDigestedDataRef digestedData; SecCmsEncryptedDataRef encryptedData; @@ -112,16 +112,17 @@ union SecCmsContentUnion { }; struct SecCmsContentInfoStr { - CSSM_DATA contentType; + SecAsn1Item contentType; SecCmsContent content; /* --------- local; not part of encoding --------- */ + SecCmsMessageRef cmsg; /* back pointer to message */ SECOidData * contentTypeTag; /* additional info for encryptedData and envelopedData */ /* we waste this space for signedData and digestedData. sue me. */ SECAlgorithmID contentEncAlg; - CSSM_DATA_PTR rawContent; /* encrypted DER, optional */ + SecAsn1Item * rawContent; /* encrypted DER, optional */ /* XXXX bytes not encrypted, but encoded? */ /* --------- local; not part of encoding --------- */ SecSymmetricKeyRef bulkkey; /* bulk encryption key */ @@ -138,32 +139,15 @@ struct SecCmsContentInfoStr { * MESSAGE */ -/*! - @typedef - @discussion Type of function called inside SecCmsSignedDataEncodeAfterData to - fire up XPC service to talk to TimeStamping server, etc. - @param context Typically a CFDictionary with URL, etc. - @param messageImprint a SecAsn1TSAMessageImprint with the algorithm and hash value - @param tstoken The returned TimeStampToken - */ -typedef OSStatus (*SecCmsTSACallback)(const void *context, void *messageImprint, uint64_t nonce, CSSM_DATA *tstoken); - struct SecCmsMessageStr { SecCmsContentInfo contentInfo; /* "outer" cinfo */ /* --------- local; not part of encoding --------- */ PLArenaPool * poolp; - Boolean poolp_is_ours; int refCount; /* properties of the "inner" data */ - SECAlgorithmID ** detached_digestalgs; - CSSM_DATA_PTR * detached_digests; void * pwfn_arg; SecCmsGetDecryptKeyCallback decrypt_key_cb; void * decrypt_key_cb_arg; - - /* Fields for Time Stamping */ - SecCmsTSACallback tsaCallback; - CFTypeRef tsaContext; }; /* ============================================================================= @@ -171,15 +155,15 @@ struct SecCmsMessageStr { */ struct SecCmsSignedDataStr { - CSSM_DATA version; - SECAlgorithmID ** digestAlgorithms; SecCmsContentInfo contentInfo; - CSSM_DATA_PTR * rawCerts; - CSSM_DATA_PTR * rawCrls; + SecAsn1Item version; + SECAlgorithmID ** digestAlgorithms; + SecAsn1Item ** rawCerts; + SecAsn1Item ** rawCrls; SecCmsSignerInfoRef * signerInfos; /* --------- local; not part of encoding --------- */ - SecCmsMessageRef cmsg; /* back pointer to message */ - CSSM_DATA_PTR * digests; + //SecCmsMessageRef cmsg; /* back pointer to message */ + SecAsn1Item ** digests; CFMutableArrayRef certs; }; #define SEC_CMS_SIGNED_DATA_VERSION_BASIC 1 /* what we *create* */ @@ -194,38 +178,34 @@ struct SecCmsSignerIdentifierStr { SecCmsSignerIDSelector identifierType; union { SecCmsIssuerAndSN *issuerAndSN; - CSSM_DATA_PTR subjectKeyID; + SecAsn1Item * subjectKeyID; } id; }; struct SecCmsIssuerAndSNStr { NSS_Name issuer; - CSSM_DATA serialNumber; + SecAsn1Item serialNumber; /* --------- local; not part of encoding --------- */ - CSSM_DATA derIssuer; + SecAsn1Item derIssuer; }; struct SecCmsSignerInfoStr { - CSSM_DATA version; + SecAsn1Item version; SecCmsSignerIdentifier signerIdentifier; SECAlgorithmID digestAlg; SecCmsAttribute ** authAttr; SECAlgorithmID digestEncAlg; - CSSM_DATA encDigest; + SecAsn1Item encDigest; SecCmsAttribute ** unAuthAttr; /* --------- local; not part of encoding --------- */ - SecCmsMessageRef cmsg; /* back pointer to message */ - SecCmsSignedDataRef sigd; /* back pointer to SignedData */ + //SecCmsMessageRef cmsg; /* back pointer to message */ + SecCmsSignedDataRef signedData; /* back pointer to signedData. */ SecCertificateRef cert; CFArrayRef certList; CFAbsoluteTime signingTime; SecCmsVerificationStatus verificationStatus; SecPrivateKeyRef signingKey; /* Used if we're using subjKeyID*/ SecPublicKeyRef pubKey; - CFAbsoluteTime timestampTime; - CFAbsoluteTime tsaLeafNotBefore; /* Start date for Timestamp Authority leaf */ - CFAbsoluteTime tsaLeafNotAfter; /* Expiration date for Timestamp Authority leaf */ - CFMutableArrayRef timestampCertList; }; #define SEC_CMS_SIGNER_INFO_VERSION_ISSUERSN 1 /* what we *create* */ #define SEC_CMS_SIGNER_INFO_VERSION_SUBJKEY 3 /* what we *create* */ @@ -234,20 +214,20 @@ struct SecCmsSignerInfoStr { * ENVELOPED DATA */ struct SecCmsEnvelopedDataStr { - CSSM_DATA version; + SecCmsContentInfo contentInfo; + SecAsn1Item version; SecCmsOriginatorInfo * originatorInfo; /* optional */ SecCmsRecipientInfoRef * recipientInfos; - SecCmsContentInfo contentInfo; SecCmsAttribute ** unprotectedAttr; /* --------- local; not part of encoding --------- */ - SecCmsMessageRef cmsg; /* back pointer to message */ + //SecCmsMessageRef cmsg; /* back pointer to message */ }; #define SEC_CMS_ENVELOPED_DATA_VERSION_REG 0 /* what we *create* */ #define SEC_CMS_ENVELOPED_DATA_VERSION_ADV 2 /* what we *create* */ struct SecCmsOriginatorInfoStr { - CSSM_DATA_PTR * rawCerts; - CSSM_DATA_PTR * rawCrls; + SecAsn1Item ** rawCerts; + SecAsn1Item ** rawCrls; /* --------- local; not part of encoding --------- */ SecCertificateRef * certs; }; @@ -264,16 +244,16 @@ struct SecCmsRecipientIdentifierStr { SecCmsRecipientIDSelector identifierType; union { SecCmsIssuerAndSN *issuerAndSN; - CSSM_DATA_PTR subjectKeyID; + SecAsn1Item * subjectKeyID; } id; }; typedef struct SecCmsRecipientIdentifierStr SecCmsRecipientIdentifier; struct SecCmsKeyTransRecipientInfoStr { - CSSM_DATA version; + SecAsn1Item version; SecCmsRecipientIdentifier recipientIdentifier; SECAlgorithmID keyEncAlg; - CSSM_DATA encKey; + SecAsn1Item encKey; }; typedef struct SecCmsKeyTransRecipientInfoStr SecCmsKeyTransRecipientInfo; @@ -297,7 +277,7 @@ typedef struct SecCmsKeyTransRecipientInfoExStr SecCmsKeyTransRecipientInfoEx; */ struct SecCmsOriginatorPublicKeyStr { SECAlgorithmID algorithmIdentifier; - CSSM_DATA publicKey; /* bit string! */ + SecAsn1Item publicKey; /* bit string! */ }; typedef struct SecCmsOriginatorPublicKeyStr SecCmsOriginatorPublicKey; @@ -310,17 +290,17 @@ typedef enum { struct SecCmsOriginatorIdentifierOrKeyStr { SecCmsOriginatorIDOrKeySelector identifierType; union { - SecCmsIssuerAndSN *issuerAndSN; /* static-static */ - CSSM_DATA subjectKeyID; /* static-static */ + SecCmsIssuerAndSN *issuerAndSN; /* static-static */ + SecAsn1Item * subjectKeyID; /* static-static */ SecCmsOriginatorPublicKey originatorPublicKey; /* ephemeral-static */ } id; }; typedef struct SecCmsOriginatorIdentifierOrKeyStr SecCmsOriginatorIdentifierOrKey; struct SecCmsRecipientKeyIdentifierStr { - CSSM_DATA_PTR subjectKeyIdentifier; - CSSM_DATA_PTR date; /* optional */ - CSSM_DATA_PTR other; /* optional */ + SecAsn1Item * subjectKeyIdentifier; + SecAsn1Item * date; /* optional */ + SecAsn1Item * other; /* optional */ }; typedef struct SecCmsRecipientKeyIdentifierStr SecCmsRecipientKeyIdentifier; @@ -340,14 +320,14 @@ typedef struct SecCmsKeyAgreeRecipientIdentifierStr SecCmsKeyAgreeRecipientIdent struct SecCmsRecipientEncryptedKeyStr { SecCmsKeyAgreeRecipientIdentifier recipientIdentifier; - CSSM_DATA encKey; + SecAsn1Item encKey; }; typedef struct SecCmsRecipientEncryptedKeyStr SecCmsRecipientEncryptedKey; struct SecCmsKeyAgreeRecipientInfoStr { - CSSM_DATA version; + SecAsn1Item version; SecCmsOriginatorIdentifierOrKey originatorIdentifierOrKey; - CSSM_DATA ukm; /* optional */ + SecAsn1Item * ukm; /* optional */ SECAlgorithmID keyEncAlg; SecCmsRecipientEncryptedKey ** recipientEncryptedKeys; }; @@ -359,17 +339,17 @@ typedef struct SecCmsKeyAgreeRecipientInfoStr SecCmsKeyAgreeRecipientInfo; * KEK recipient info */ struct SecCmsKEKIdentifierStr { - CSSM_DATA keyIdentifier; - CSSM_DATA_PTR date; /* optional */ - CSSM_DATA_PTR other; /* optional */ + SecAsn1Item keyIdentifier; + SecAsn1Item * date; /* optional */ + SecAsn1Item * other; /* optional */ }; typedef struct SecCmsKEKIdentifierStr SecCmsKEKIdentifier; struct SecCmsKEKRecipientInfoStr { - CSSM_DATA version; + SecAsn1Item version; SecCmsKEKIdentifier kekIdentifier; SECAlgorithmID keyEncAlg; - CSSM_DATA encKey; + SecAsn1Item encKey; }; typedef struct SecCmsKEKRecipientInfoStr SecCmsKEKRecipientInfo; @@ -416,7 +396,8 @@ struct SecCmsRecipientInfoStr { SecCmsKeyTransRecipientInfoEx keyTransRecipientInfoEx; } ri; /* --------- local; not part of encoding --------- */ - SecCmsMessageRef cmsg; /* back pointer to message */ + //SecCmsMessageRef cmsg; /* back pointer to message */ + SecCmsEnvelopedDataRef envelopedData; /* back pointer to envelopedData */ SecCertificateRef cert; /* recipient's certificate */ }; @@ -424,13 +405,13 @@ struct SecCmsRecipientInfoStr { * DIGESTED DATA */ struct SecCmsDigestedDataStr { - CSSM_DATA version; - SECAlgorithmID digestAlg; SecCmsContentInfo contentInfo; - CSSM_DATA digest; + SecAsn1Item version; + SECAlgorithmID digestAlg; + SecAsn1Item digest; /* --------- local; not part of encoding --------- */ - SecCmsMessageRef cmsg; /* back pointer */ - CSSM_DATA cdigest; /* calculated digest */ + //SecCmsMessageRef cmsg; /* back pointer */ + SecAsn1Item cdigest; /* calculated digest */ }; #define SEC_CMS_DIGESTED_DATA_VERSION_DATA 0 /* what we *create* */ #define SEC_CMS_DIGESTED_DATA_VERSION_ENCAP 2 /* what we *create* */ @@ -439,11 +420,11 @@ struct SecCmsDigestedDataStr { * ENCRYPTED DATA */ struct SecCmsEncryptedDataStr { - CSSM_DATA version; SecCmsContentInfo contentInfo; + SecAsn1Item version; SecCmsAttribute ** unprotectedAttr; /* optional */ /* --------- local; not part of encoding --------- */ - SecCmsMessageRef cmsg; /* back pointer */ + //SecCmsMessageRef cmsg; /* back pointer */ }; #define SEC_CMS_ENCRYPTED_DATA_VERSION 0 /* what we *create* */ #define SEC_CMS_ENCRYPTED_DATA_VERSION_UPATTR 2 /* what we *create* */ @@ -464,13 +445,13 @@ typedef enum { /* ### mwelch - S/MIME KEA parameters. These don't really fit here, but I cannot think of a more appropriate place at this time. */ struct SecCmsSMIMEKEAParametersStr { - CSSM_DATA originatorKEAKey; /* sender KEA key (encrypted?) */ - CSSM_DATA originatorRA; /* random number generated by sender */ - CSSM_DATA nonSkipjackIV; /* init'n vector for SkipjackCBC64 + SecAsn1Item originatorKEAKey; /* sender KEA key (encrypted?) */ + SecAsn1Item originatorRA; /* random number generated by sender */ + SecAsn1Item nonSkipjackIV; /* init'n vector for SkipjackCBC64 decryption of KEA key if Skipjack is not the bulk algorithm used on the message */ - CSSM_DATA bulkKeySize; /* if Skipjack is not the bulk + SecAsn1Item bulkKeySize; /* if Skipjack is not the bulk algorithm used on the message, and the size of the bulk encryption key is not the same as that of @@ -491,8 +472,8 @@ struct SecCmsSMIMEKEAParametersStr { */ struct SecCmsAttributeStr { /* The following fields make up an encoded Attribute: */ - CSSM_DATA type; - CSSM_DATA_PTR * values; /* data may or may not be encoded */ + SecAsn1Item type; + SecAsn1Item ** values; /* data may or may not be encoded */ /* The following fields are not part of an encoded Attribute: */ SECOidData * typeTag; Boolean encoded; /* when true, values are encoded */ diff --git a/libsecurity_smime/lib/cmsutil.c b/libsecurity_smime/lib/cmsutil.c index 020460cf..31117217 100644 --- a/libsecurity_smime/lib/cmsutil.c +++ b/libsecurity_smime/lib/cmsutil.c @@ -37,17 +37,27 @@ #include /* @@@ Remove this when we move the Encoder method. */ #include + #include "cmslocal.h" -#include "secitem.h" +#include "SecAsn1Item.h" #include "secoid.h" #include "cryptohi.h" #include #include +#include + +#if USE_CDSA_CRYPTO #include #include -#include +#include + +#else +#include +#include + +#endif /* @@ -62,7 +72,7 @@ SecCmsArraySortByDER(void **objs, const SecAsn1Template *objtemplate, void **obj { PRArenaPool *poolp; int num_objs; - CSSM_DATA_PTR *enc_objs; + SecAsn1Item **enc_objs; OSStatus rv = SECFailure; int i; @@ -81,7 +91,7 @@ SecCmsArraySortByDER(void **objs, const SecAsn1Template *objtemplate, void **obj * Allocate arrays to hold the individual encodings which we will use * for comparisons and the reordered attributes as they are sorted. */ - enc_objs = (CSSM_DATA_PTR *)PORT_ArenaZAlloc(poolp, (num_objs + 1) * sizeof(CSSM_DATA_PTR)); + enc_objs = (SecAsn1Item **)PORT_ArenaZAlloc(poolp, (num_objs + 1) * sizeof(SecAsn1Item *)); if (enc_objs == NULL) goto loser; @@ -105,14 +115,13 @@ loser: /* * SecCmsUtilDERCompare - for use with SecCmsArraySort to - * sort arrays of CSSM_DATAs containing DER + * sort arrays of SecAsn1Items containing DER */ int SecCmsUtilDERCompare(void *a, void *b) { - CSSM_DATA_PTR der1 = (CSSM_DATA_PTR)a; - CSSM_DATA_PTR der2 = (CSSM_DATA_PTR)b; - int j; + SecAsn1Item * der1 = (SecAsn1Item *)a; + SecAsn1Item * der2 = (SecAsn1Item *)b; /* * Find the lowest (lexigraphically) encoding. One that is @@ -128,12 +137,17 @@ SecCmsUtilDERCompare(void *a, void *b) if (der1->Length != der2->Length) return (der1->Length < der2->Length) ? -1 : 1; +#if 1 + return memcmp(der1->Data, der2->Data, der1->Length); +#else + size_t j; for (j = 0; j < der1->Length; j++) { if (der1->Data[j] == der2->Data[j]) continue; return (der1->Data[j] < der2->Data[j]) ? -1 : 1; } return 0; +#endif } /* @@ -209,12 +223,17 @@ SecCmsAlgArrayGetIndexByAlgTag(SECAlgorithmID **algorithmArray, return i; } +#if USE_CDSA_CRYPTO CSSM_CC_HANDLE +#else +void * +#endif SecCmsUtilGetHashObjByAlgID(SECAlgorithmID *algid) { SECOidData *oidData = SECOID_FindOID(&(algid->algorithm)); if (oidData) { +#if USE_CDSA_CRYPTO CSSM_ALGORITHMS alg = oidData->cssmAlgorithm; if (alg) { @@ -224,6 +243,38 @@ SecCmsUtilGetHashObjByAlgID(SECAlgorithmID *algid) if (!CSSM_CSP_CreateDigestContext(cspHandle, alg, &digobj)) return digobj; } +#else + void *digobj = NULL; + switch (oidData->offset) { + case SEC_OID_SHA1: + digobj = calloc(1, sizeof(CC_SHA1_CTX)); + CC_SHA1_Init(digobj); + break; + case SEC_OID_MD5: + digobj = calloc(1, sizeof(CC_MD5_CTX)); + CC_MD5_Init(digobj); + break; + case SEC_OID_SHA224: + digobj = calloc(1, sizeof(CC_SHA256_CTX)); + CC_SHA224_Init(digobj); + break; + case SEC_OID_SHA256: + digobj = calloc(1, sizeof(CC_SHA256_CTX)); + CC_SHA256_Init(digobj); + break; + case SEC_OID_SHA384: + digobj = calloc(1, sizeof(CC_SHA512_CTX)); + CC_SHA384_Init(digobj); + break; + case SEC_OID_SHA512: + digobj = calloc(1, sizeof(CC_SHA512_CTX)); + CC_SHA512_Init(digobj); + break; + default: + break; + } + return digobj; +#endif } return 0; @@ -263,17 +314,6 @@ SecCmsUtilMakeSignatureAlgorithm(SECOidTag hashalg, SECOidTag encalg) default: return SEC_OID_UNKNOWN; } - case SEC_OID_EC_PUBLIC_KEY: - switch(hashalg) { - /* - * Note this is only used when signing and verifying signed attributes, - * In which case we really do want the combined ECDSA_WithSHA1 alg... - */ - case SEC_OID_SHA1: - return SEC_OID_ECDSA_WithSHA1; - default: - return SEC_OID_UNKNOWN; - } default: break; } @@ -305,7 +345,6 @@ SecCmsUtilGetTemplateByTypeTag(SECOidTag type) break; default: case SEC_OID_PKCS7_DATA: - case SEC_OID_OTHER: template = NULL; break; } @@ -384,29 +423,3 @@ SecCmsUtilVerificationStatusToString(SecCmsVerificationStatus vs) default: return "Unknown"; } } - -OSStatus -SecArenaPoolCreate(size_t chunksize, SecArenaPoolRef *outArena) -{ - OSStatus status; - - if (!outArena) { - status = paramErr; - goto loser; - } - - *outArena = (SecArenaPoolRef)PORT_NewArena(chunksize); - if (*outArena) - status = 0; - else - status = PORT_GetError(); - -loser: - return status; -} - -void -SecArenaPoolFree(SecArenaPoolRef arena, Boolean zero) -{ - PORT_FreeArena((PLArenaPool *)arena, zero); -} diff --git a/libsecurity_smime/lib/crypto-embedded.c b/libsecurity_smime/lib/crypto-embedded.c new file mode 100644 index 00000000..c9dd8e70 --- /dev/null +++ b/libsecurity_smime/lib/crypto-embedded.c @@ -0,0 +1,384 @@ +/* + * crypto-embedded.c + * libsecurity_smime + * + * Created by Conrad Sauerwald on 2/7/08. + * Copyright (c) 2008-2011,2013 Apple Inc. All Rights Reserved. + * + */ + +#include + +#include "cert.h" +#include "cryptohi.h" + +#include "cmstpriv.h" +#include "secoid.h" +#include "cmspriv.h" + +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +SECStatus +CERT_VerifyCert(SecKeychainRef keychainOrArray __unused, CFArrayRef certs, + CFTypeRef policies, CFAbsoluteTime stime, SecTrustRef *trustRef) +{ + SecTrustRef trust = NULL; + OSStatus rv; + + rv = SecTrustCreateWithCertificates(certs, policies, &trust); + if (rv) + goto loser; + + CFDateRef verifyDate = CFDateCreate(NULL, stime); + rv = SecTrustSetVerifyDate(trust, verifyDate); + CFRelease(verifyDate); + if (rv) + goto loser; + + if (trustRef) + { + *trustRef = trust; + } + else + { + SecTrustResultType result; + /* The caller doesn't want a SecTrust object, so let's evaluate it for them. */ + rv = SecTrustEvaluate(trust, &result); + if (rv) + goto loser; + + switch (result) + { + case kSecTrustResultProceed: + case kSecTrustResultUnspecified: + /* TP Verification succeeded and there was either a UserTurst entry + telling us to procceed, or no user trust setting was specified. */ + CFRelease(trust); + break; + default: + PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); + rv = SECFailure; + goto loser; + break; + } + } + + return SECSuccess; +loser: + if (trust) + CFRelease(trust); + + return rv; +} + + +SecCertificateRef CERT_FindUserCertByUsage(SecKeychainRef keychainOrArray, + char *nickname,SECCertUsage usage,Boolean validOnly,void *proto_win) +{ + CFStringRef nickname_cfstr = CFStringCreateWithCString(kCFAllocatorDefault, nickname, kCFStringEncodingUTF8); + const void *keys[] = { kSecClass, kSecAttrLabel }; + const void *values[] = { kSecClassCertificate, nickname_cfstr }; + CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys)/sizeof(*keys), NULL, NULL); + CFTypeRef result = NULL; + SecItemCopyMatching(query, &result); + CFRelease(query); + CFRelease(nickname_cfstr); + return (SecCertificateRef)result; +} + +CF_RETURNS_RETAINED CFArrayRef CERT_CertChainFromCert(SecCertificateRef cert, SECCertUsage usage, Boolean includeRoot) +{ + CFMutableArrayRef certs = NULL; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + CFArrayRef wrappedCert = NULL; + + policy = SecPolicyCreateBasicX509(); + if (!policy) + goto out; + + wrappedCert = CERT_CertListFromCert(cert); + if (SecTrustCreateWithCertificates(wrappedCert, policy, &trust)) + goto out; + + SecTrustResultType result; + if (SecTrustEvaluate(trust, &result)) + goto out; + CFIndex idx, count = SecTrustGetCertificateCount(trust); + certs = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks); + for(idx = 0; idx < count; idx++) + CFArrayAppendValue(certs, SecTrustGetCertificateAtIndex(trust, idx)); + +out: + if (trust) CFRelease(trust); + if (policy) CFRelease(policy); + if (wrappedCert) CFRelease(wrappedCert); + + return certs; +} + +CFArrayRef CERT_CertListFromCert(SecCertificateRef cert) +{ + const void *value = cert; + return cert ? CFArrayCreate(NULL, &value, 1, &kCFTypeArrayCallBacks) : NULL; +} + +CFArrayRef CERT_DupCertList(CFArrayRef oldList) +{ + CFRetain(oldList); + return oldList; +} + +// Extract a public key object from a SubjectPublicKeyInfo +SecPublicKeyRef CERT_ExtractPublicKey(SecCertificateRef cert) +{ + return SecCertificateCopyPublicKey(cert); +} + +// Extract the issuer and serial number from a certificate +SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef cert) +{ + SecCmsIssuerAndSN *certIssuerAndSN; + + void *mark; + mark = PORT_ArenaMark(pl); + CFDataRef serial_data = NULL; + CFDataRef issuer_data = SecCertificateCopyIssuerSequence(cert); + if (!issuer_data) + goto loser; + serial_data = SecCertificateCopySerialNumber(cert); + if (!serial_data) + goto loser; + + SecAsn1Item serialNumber = { CFDataGetLength(serial_data), + (uint8_t *)CFDataGetBytePtr(serial_data) }; + SecAsn1Item issuer = { CFDataGetLength(issuer_data), + (uint8_t *)CFDataGetBytePtr(issuer_data) }; + + /* Allocate the SecCmsIssuerAndSN struct. */ + certIssuerAndSN = (SecCmsIssuerAndSN *)PORT_ArenaZAlloc (pl, sizeof(SecCmsIssuerAndSN)); + if (certIssuerAndSN == NULL) + goto loser; + + /* Copy the issuer. */ + certIssuerAndSN->derIssuer.Data = (uint8_t *) PORT_ArenaAlloc(pl, issuer.Length); + if (!certIssuerAndSN->derIssuer.Data) + goto loser; + PORT_Memcpy(certIssuerAndSN->derIssuer.Data, issuer.Data, issuer.Length); + certIssuerAndSN->derIssuer.Length = issuer.Length; + + /* Copy the serialNumber. */ + certIssuerAndSN->serialNumber.Data = (uint8_t *) PORT_ArenaAlloc(pl, serialNumber.Length); + if (!certIssuerAndSN->serialNumber.Data) + goto loser; + PORT_Memcpy(certIssuerAndSN->serialNumber.Data, serialNumber.Data, serialNumber.Length); + certIssuerAndSN->serialNumber.Length = serialNumber.Length; + + CFRelease(serial_data); + CFRelease(issuer_data); + + PORT_ArenaUnmark(pl, mark); + + return certIssuerAndSN; + +loser: + if (serial_data) + CFRelease(serial_data); + if (issuer_data) + CFRelease(issuer_data); + PORT_ArenaRelease(pl, mark); + PORT_SetError(SEC_INTERNAL_ONLY); + + return NULL; +} + +// find the smime symmetric capabilities profile for a given cert +SecAsn1Item *CERT_FindSMimeProfile(SecCertificateRef cert) +{ + return NULL; +} + +// Generate a certificate key from the issuer and serialnumber, then look it up in the database. +// Return the cert if found. "issuerAndSN" is the issuer and serial number to look for +static CFTypeRef CERT_FindByIssuerAndSN (CFTypeRef keychainOrArray, CFTypeRef class, const SecCmsIssuerAndSN *issuerAndSN) +{ + CFTypeRef ident = NULL; + CFDictionaryRef query = NULL; + CFDataRef issuer = NULL; + CFDataRef serial = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, + issuerAndSN->serialNumber.Data, issuerAndSN->serialNumber.Length, + kCFAllocatorNull); + + DERItem der_issuer = { issuerAndSN->derIssuer.Data, + issuerAndSN->derIssuer.Length }; + DERDecodedInfo content; + require_noerr_quiet(DERDecodeItem(&der_issuer, &content), out); + require_quiet(issuer = createNormalizedX501Name(kCFAllocatorDefault, + &content.content), out); + + if (keychainOrArray && (CFGetTypeID(keychainOrArray) == CFArrayGetTypeID()) && CFEqual(class, kSecClassCertificate)) + { + CFIndex c, count = CFArrayGetCount((CFArrayRef)keychainOrArray); + for (c = 0; c < count; c++) { + SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex((CFArrayRef)keychainOrArray, c); + if (CFEqual(SecCertificateGetNormalizedIssuerContent(cert), issuer)) { + CFDataRef cert_serial = SecCertificateCopySerialNumber(cert); + bool found = CFEqual(cert_serial, serial); + CFRelease(cert_serial); + if (found) { + CFRetain(cert); + ident = cert; + goto out; + } + } + } + } + + 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); + +out: + if (query) + CFRelease(query); + if (issuer) + CFRelease(issuer); + if (serial) + CFRelease(serial); + + return ident; +} + +SecIdentityRef CERT_FindIdentityByIssuerAndSN (CFTypeRef keychainOrArray, const SecCmsIssuerAndSN *issuerAndSN) +{ + return (SecIdentityRef)CERT_FindByIssuerAndSN(keychainOrArray, kSecClassIdentity, issuerAndSN); +} + +SecCertificateRef CERT_FindCertificateByIssuerAndSN (CFTypeRef keychainOrArray, const SecCmsIssuerAndSN *issuerAndSN) +{ + return (SecCertificateRef)CERT_FindByIssuerAndSN(keychainOrArray, kSecClassCertificate, issuerAndSN); +} + +SecIdentityRef CERT_FindIdentityBySubjectKeyID (CFTypeRef keychainOrArray __unused, const SecAsn1Item *subjKeyID) +{ + SecIdentityRef ident = NULL; + CFDictionaryRef query = NULL; + CFDataRef subjectkeyid = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, subjKeyID->Data, subjKeyID->Length, kCFAllocatorNull); + + 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); + +out: + if (query) + CFRelease(query); + if (subjectkeyid) + CFRelease(subjectkeyid); + + return ident; +} + + + +SecPublicKeyRef SECKEY_CopyPublicKey(SecPublicKeyRef pubKey) +{ + CFRetain(pubKey); + return pubKey; +} + +void SECKEY_DestroyPublicKey(SecPublicKeyRef pubKey) +{ + CFRelease(pubKey); +} + +SecPublicKeyRef SECKEY_CopyPrivateKey(SecPublicKeyRef privKey) +{ + CFRetain(privKey); + return privKey; +} + +void SECKEY_DestroyPrivateKey(SecPublicKeyRef privKey) +{ + CFRelease(privKey); +} + +void CERT_DestroyCertificate(SecCertificateRef cert) +{ + CFRelease(cert); +} + +SecCertificateRef CERT_DupCertificate(SecCertificateRef cert) +{ + CFRetain(cert); + return cert; +} + +SECStatus +WRAP_PubWrapSymKey(SecPublicKeyRef publickey, + SecSymmetricKeyRef bulkkey, + SecAsn1Item * encKey) +{ + return SecKeyEncrypt(publickey, kSecPaddingPKCS1, + CFDataGetBytePtr(bulkkey), CFDataGetLength(bulkkey), + encKey->Data, &encKey->Length); +} + +SecSymmetricKeyRef +WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey, const SecAsn1Item *encKey, SECOidTag bulkalgtag) +{ + size_t bulkkey_size = encKey->Length; + uint8_t bulkkey_buffer[bulkkey_size]; + if (SecKeyDecrypt(privkey, kSecPaddingPKCS1, + encKey->Data, encKey->Length, bulkkey_buffer, &bulkkey_size)) + return NULL; + + CFDataRef bulkkey = CFDataCreate(kCFAllocatorDefault, bulkkey_buffer, bulkkey_size); + return (SecSymmetricKeyRef)bulkkey; +} + + +bool +CERT_CheckIssuerAndSerial(SecCertificateRef cert, SecAsn1Item *issuer, SecAsn1Item *serial) +{ + do { + CFDataRef cert_issuer = SecCertificateCopyIssuerSequence(cert); + if (!cert_issuer) + break; + if ((issuer->Length != (size_t)CFDataGetLength(cert_issuer)) || + memcmp(issuer->Data, CFDataGetBytePtr(cert_issuer), issuer->Length)) { + CFRelease(cert_issuer); + break; + } + CFRelease(cert_issuer); + CFDataRef cert_serial = SecCertificateCopySerialNumber(cert); + if (!cert_serial) + break; + if ((serial->Length != (size_t)CFDataGetLength(cert_serial)) || + memcmp(serial->Data, CFDataGetBytePtr(cert_serial), serial->Length)) { + CFRelease(cert_serial); + break; + } + CFRelease(cert_serial); + return true; + } while(0); + return false; +} diff --git a/libsecurity_smime/lib/cryptohi.c b/libsecurity_smime/lib/cryptohi.c index d80963c0..0ef64d99 100644 --- a/libsecurity_smime/lib/cryptohi.c +++ b/libsecurity_smime/lib/cryptohi.c @@ -99,26 +99,8 @@ SECOID_FindyCssmAlgorithmByTag(SECOidTag algTag) return oidData ? oidData->cssmAlgorithm : CSSM_ALGID_NONE; } -static SECStatus SEC_CssmRtnToSECStatus(CSSM_RETURN rv) -{ - CSSM_RETURN crtn = CSSM_ERRCODE(rv); - switch(crtn) { - case CSSM_ERRCODE_USER_CANCELED: - case CSSM_ERRCODE_OPERATION_AUTH_DENIED: - case CSSM_ERRCODE_OBJECT_USE_AUTH_DENIED: - return SEC_ERROR_USER_CANCELLED; - case CSSM_ERRCODE_NO_USER_INTERACTION: - return SEC_ERROR_NO_USER_INTERACTION; - case CSSMERR_CSP_KEY_USAGE_INCORRECT: - return SEC_ERROR_INADEQUATE_KEY_USAGE; - default: - fprintf(stderr, "CSSM_SignData returned: %08X\n", (uint32_t)rv); - return SEC_ERROR_LIBRARY_FAILURE; - } -} - SECStatus -SEC_SignData(SECItem *result, unsigned char *buf, int len, +SEC_SignData(SecAsn1Item *result, unsigned char *buf, int len, SecPrivateKeyRef pk, SECOidTag digAlgTag, SECOidTag sigAlgTag) { const CSSM_ACCESS_CREDENTIALS *accessCred; @@ -126,8 +108,8 @@ SEC_SignData(SECItem *result, unsigned char *buf, int len, CSSM_CC_HANDLE cc = 0; CSSM_CSP_HANDLE csp; OSStatus rv; - CSSM_DATA dataBuf = { (uint32)len, (uint8 *)buf }; - CSSM_DATA sig = {}; + SecAsn1Item dataBuf = { (uint32)len, (uint8_t *)buf }; + SecAsn1Item sig = {}; const CSSM_KEY *key; algorithm = SECOID_FindyCssmAlgorithmByTag(SecCmsUtilMakeSignatureAlgorithm(digAlgTag, sigAlgTag)); @@ -162,7 +144,16 @@ SEC_SignData(SECItem *result, unsigned char *buf, int len, rv = CSSM_SignData(cc, &dataBuf, 1, CSSM_ALGID_NONE, &sig); if (rv) { - SECErrorCodes code = SEC_CssmRtnToSECStatus(rv); + SECErrorCodes code; + if (CSSM_ERRCODE(rv) == CSSM_ERRCODE_USER_CANCELED + || CSSM_ERRCODE(rv) == CSSM_ERRCODE_OPERATION_AUTH_DENIED) + code = SEC_ERROR_USER_CANCELLED; + else if (CSSM_ERRCODE(rv) == CSSM_ERRCODE_NO_USER_INTERACTION + || rv == CSSMERR_CSP_KEY_USAGE_INCORRECT) + code = SEC_ERROR_INADEQUATE_KEY_USAGE; + else + code = SEC_ERROR_LIBRARY_FAILURE; + PORT_SetError(code); goto loser; } @@ -178,14 +169,14 @@ loser: } SECStatus -SGN_Digest(SecPrivateKeyRef pk, SECOidTag digAlgTag, SECOidTag sigAlgTag, SECItem *result, SECItem *digest) +SGN_Digest(SecPrivateKeyRef pk, SECOidTag digAlgTag, SECOidTag sigAlgTag, SecAsn1Item *result, SecAsn1Item *digest) { const CSSM_ACCESS_CREDENTIALS *accessCred; CSSM_ALGORITHMS digalg, sigalg; CSSM_CC_HANDLE cc = 0; CSSM_CSP_HANDLE csp; const CSSM_KEY *key; - CSSM_DATA sig = {}; + SecAsn1Item sig = {}; OSStatus rv; digalg = SECOID_FindyCssmAlgorithmByTag(digAlgTag); @@ -221,7 +212,16 @@ SGN_Digest(SecPrivateKeyRef pk, SECOidTag digAlgTag, SECOidTag sigAlgTag, SECIte rv = CSSM_SignData(cc, digest, 1, digalg, &sig); if (rv) { - SECErrorCodes code = SEC_CssmRtnToSECStatus(rv); + SECErrorCodes code; + if (CSSM_ERRCODE(rv) == CSSM_ERRCODE_USER_CANCELED + || CSSM_ERRCODE(rv) == CSSM_ERRCODE_OPERATION_AUTH_DENIED) + code = SEC_ERROR_USER_CANCELLED; + else if (CSSM_ERRCODE(rv) == CSSM_ERRCODE_NO_USER_INTERACTION + || rv == CSSMERR_CSP_KEY_USAGE_INCORRECT) + code = SEC_ERROR_INADEQUATE_KEY_USAGE; + else + code = SEC_ERROR_LIBRARY_FAILURE; + PORT_SetError(code); goto loser; } @@ -238,7 +238,7 @@ loser: SECStatus VFY_VerifyData(unsigned char *buf, int len, - SecPublicKeyRef pk, SECItem *sig, + SecPublicKeyRef pk, SecAsn1Item *sig, SECOidTag digAlgTag, SECOidTag sigAlgTag, void *wincx) { SECOidTag algTag; @@ -246,7 +246,7 @@ VFY_VerifyData(unsigned char *buf, int len, CSSM_CC_HANDLE cc = 0; CSSM_CSP_HANDLE csp; OSStatus rv = SECFailure; - CSSM_DATA dataBuf = { (uint32)len, (uint8 *)buf }; + SecAsn1Item dataBuf = { (uint32)len, (uint8_t *)buf }; const CSSM_KEY *key; algTag = SecCmsUtilMakeSignatureAlgorithm(digAlgTag, sigAlgTag); @@ -278,8 +278,8 @@ loser: } SECStatus -VFY_VerifyDigest(SECItem *digest, SecPublicKeyRef pk, - SECItem *sig, SECOidTag digAlgTag, SECOidTag sigAlgTag, void *wincx) +VFY_VerifyDigest(SecAsn1Item *digest, SecPublicKeyRef pk, + SecAsn1Item *sig, SECOidTag digAlgTag, SECOidTag sigAlgTag, void *wincx) { CSSM_ALGORITHMS sigalg, digalg; CSSM_CC_HANDLE cc = 0; @@ -318,7 +318,7 @@ loser: SECStatus WRAP_PubWrapSymKey(SecPublicKeyRef publickey, SecSymmetricKeyRef bulkkey, - CSSM_DATA_PTR encKey) + SecAsn1Item * encKey) { CSSM_WRAP_KEY wrappedKey = {}; //CSSM_WRAP_KEY wrappedPk = {} @@ -416,8 +416,8 @@ WRAP_PubWrapSymKey(SecPublicKeyRef publickey, { // @@@ Stick in an empty initVector to work around a csp bug. - CSSM_DATA initVector = {}; - CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_INIT_VECTOR, sizeof(CSSM_DATA_PTR) }; + SecAsn1Item initVector = {}; + CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_INIT_VECTOR, sizeof(SecAsn1Item *) }; contextAttribute.Attribute.Data = &initVector; rv = CSSM_UpdateContextAttributes(cc, 1, &contextAttribute); if (rv) @@ -447,7 +447,7 @@ loser: } SecSymmetricKeyRef -WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, SECOidTag bulkalgtag) +WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey, const SecAsn1Item *encKey, SECOidTag bulkalgtag) { SecSymmetricKeyRef bulkkey = NULL; CSSM_WRAP_KEY wrappedKey = {}; @@ -456,7 +456,7 @@ WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, SECOidTag b const CSSM_KEY *pk; CSSM_KEY unwrappedKey = {}; const CSSM_ACCESS_CREDENTIALS *accessCred; - CSSM_DATA descriptiveData = {}; + SecAsn1Item descriptiveData = {}; CSSM_ALGORITHMS bulkalg; OSStatus rv; @@ -491,8 +491,8 @@ WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, SECOidTag b { // @@@ Stick in an empty initvector to work around a csp bug. - CSSM_DATA initVector = {}; - CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_INIT_VECTOR, sizeof(CSSM_DATA_PTR) }; + SecAsn1Item initVector = {}; + CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_INIT_VECTOR, sizeof(SecAsn1Item *) }; contextAttribute.Attribute.Data = &initVector; rv = CSSM_UpdateContextAttributes(cc, 1, &contextAttribute); if (rv) @@ -520,24 +520,20 @@ WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, SECOidTag b if (rv) { SECErrorCodes code; if (CSSM_ERRCODE(rv) == CSSM_ERRCODE_USER_CANCELED - || CSSM_ERRCODE(rv) == CSSM_ERRCODE_OPERATION_AUTH_DENIED - || CSSM_ERRCODE(rv) == CSSM_ERRCODE_OBJECT_USE_AUTH_DENIED) + || CSSM_ERRCODE(rv) == CSSM_ERRCODE_OPERATION_AUTH_DENIED) code = SEC_ERROR_USER_CANCELLED; else if (CSSM_ERRCODE(rv) == CSSM_ERRCODE_NO_USER_INTERACTION || rv == CSSMERR_CSP_KEY_USAGE_INCORRECT) code = SEC_ERROR_INADEQUATE_KEY_USAGE; else - { - fprintf(stderr, "CSSM_UnwrapKey returned: %08X\n", (uint32_t)rv); code = SEC_ERROR_LIBRARY_FAILURE; - } PORT_SetError(code); goto loser; } // @@@ Export this key from the csp/dl and import it to the standard csp - rv = SecKeyCreateWithCSSMKey(&unwrappedKey, &bulkkey); + rv = SecKeyCreate(&unwrappedKey, &bulkkey); if (rv) goto loser; diff --git a/libsecurity_smime/lib/cryptohi.h b/libsecurity_smime/lib/cryptohi.h index f140c4ca..87f8e129 100644 --- a/libsecurity_smime/lib/cryptohi.h +++ b/libsecurity_smime/lib/cryptohi.h @@ -52,9 +52,10 @@ SEC_BEGIN_PROTOS * most of the rest of the world) just generates 40 bytes of raw data. These * functions convert between formats. */ -//extern SECStatus DSAU_EncodeDerSig(SECItem *dest, SECItem *src); -//extern SECItem *DSAU_DecodeDerSig(SECItem *item); +//extern SECStatus DSAU_EncodeDerSig(SecAsn1Item *dest, SecAsn1Item *src); +//extern SecAsn1Item *DSAU_DecodeDerSig(SecAsn1Item *item); +#if USE_CDSA_CRYPTO /* * Return a csp handle able to deal with algorithm */ @@ -64,7 +65,7 @@ extern CSSM_CSP_HANDLE SecCspHandleForAlgorithm(CSSM_ALGORITHMS algorithm); * Return a CSSM_ALGORITHMS for a given SECOidTag or 0 if there is none */ extern CSSM_ALGORITHMS SECOID_FindyCssmAlgorithmByTag(SECOidTag algTag); - +#endif /****************************************/ /* @@ -81,7 +82,7 @@ extern CSSM_ALGORITHMS SECOID_FindyCssmAlgorithmByTag(SECOidTag algTag); ** "algid" the signature/hash algorithm to sign with ** (must be compatible with the key type). */ -extern SECStatus SEC_SignData(SECItem *result, unsigned char *buf, int len, +extern SECStatus SEC_SignData(SecAsn1Item *result, unsigned char *buf, int len, SecPrivateKeyRef pk, SECOidTag digAlgTag, SECOidTag sigAlgTag); /* @@ -93,7 +94,7 @@ extern SECStatus SEC_SignData(SECItem *result, unsigned char *buf, int len, ** "algtag" The algorithm tag to encode (need for RSA only) */ extern SECStatus SGN_Digest(SecPrivateKeyRef privKey, - SECOidTag digAlgTag, SECOidTag sigAlgTag, SECItem *result, SECItem *digest); + SECOidTag digAlgTag, SECOidTag sigAlgTag, SecAsn1Item *result, SecAsn1Item *digest); /****************************************/ /* @@ -111,8 +112,8 @@ extern SECStatus SGN_Digest(SecPrivateKeyRef privKey, ** "algid" specifies the signing algorithm to use. This must match ** the key type. **/ -extern SECStatus VFY_VerifyDigest(SECItem *dig, SecPublicKeyRef key, - SECItem *sig, SECOidTag digAlgTag, SECOidTag sigAlgTag, void *wincx); +extern SECStatus VFY_VerifyDigest(SecAsn1Item *dig, SecPublicKeyRef key, + SecAsn1Item *sig, SECOidTag digAlgTag, SECOidTag sigAlgTag, void *wincx); /* ** Verify the signature on a block of data. The signature data is an RSA @@ -125,17 +126,17 @@ extern SECStatus VFY_VerifyDigest(SECItem *dig, SecPublicKeyRef key, ** the key type. */ extern SECStatus VFY_VerifyData(unsigned char *buf, int len, - SecPublicKeyRef key, SECItem *sig, + SecPublicKeyRef key, SecAsn1Item *sig, SECOidTag digAlgTag, SECOidTag sigAlgTag, void *wincx); extern SECStatus WRAP_PubWrapSymKey(SecPublicKeyRef publickey, SecSymmetricKeyRef bulkkey, - CSSM_DATA_PTR encKey); + SecAsn1Item * encKey); -extern SecSymmetricKeyRef WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, SECOidTag bulkalgtag); +extern SecSymmetricKeyRef WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey, const SecAsn1Item *encKey, SECOidTag bulkalgtag); SEC_END_PROTOS diff --git a/libsecurity_smime/lib/plhash.c b/libsecurity_smime/lib/plhash.c index e7524460..3da66cbb 100644 --- a/libsecurity_smime/lib/plhash.c +++ b/libsecurity_smime/lib/plhash.c @@ -362,7 +362,7 @@ PL_HashTableRawRemove(PLHashTable *ht, PLHashEntry **hep, PLHashEntry *he) } } -PR_IMPLEMENT(Boolean) +PR_IMPLEMENT(unsigned char) PL_HashTableRemove(PLHashTable *ht, const void *key) { PLHashNumber keyHash; diff --git a/libsecurity_smime/lib/plhash.h b/libsecurity_smime/lib/plhash.h index 1b5aec9c..0affda89 100644 --- a/libsecurity_smime/lib/plhash.h +++ b/libsecurity_smime/lib/plhash.h @@ -39,8 +39,6 @@ */ #include #include -// @@@ for Boolean -#include PR_BEGIN_EXTERN_C @@ -116,7 +114,7 @@ PL_HashTableDestroy(PLHashTable *ht); PR_EXTERN(PLHashEntry *) PL_HashTableAdd(PLHashTable *ht, const void *key, void *value); -PR_EXTERN(Boolean) +PR_EXTERN(unsigned char) PL_HashTableRemove(PLHashTable *ht, const void *key); PR_EXTERN(void *) diff --git a/libsecurity_smime/lib/secalgid.c b/libsecurity_smime/lib/secalgid.c index 623b7f9f..a9e5c3b1 100644 --- a/libsecurity_smime/lib/secalgid.c +++ b/libsecurity_smime/lib/secalgid.c @@ -32,9 +32,10 @@ */ #include "secoid.h" -#include "secitem.h" +#include "SecAsn1Item.h" #include #include +#include const SecAsn1Template SECOID_AlgorithmIDTemplate[] = { { SEC_ASN1_SEQUENCE, @@ -57,7 +58,7 @@ SECOID_GetAlgorithmTag(const SECAlgorithmID *id) SECStatus SECOID_SetAlgorithmID(PRArenaPool *arena, SECAlgorithmID *id, SECOidTag which, - SECItem *params) + const SecAsn1Item *params) { SECOidData *oiddata; Boolean add_null_param; @@ -104,13 +105,10 @@ SECOID_SetAlgorithmID(PRArenaPool *arena, SECAlgorithmID *id, SECOidTag which, * behavior. But I do want for us to notice if the following is * ever true, because I do not think it should be so and probably * signifies an error/bug somewhere. - * This assertion removed Sep 9 2008 by dmitch, we really do need - * to be able to do this for an odd SEC_OID_EC_PUBLIC_KEY case. - * + */ PORT_Assert(!add_null_param || (params->Length == 2 && params->Data[0] == SEC_ASN1_NULL && params->Data[1] == 0)); - */ if (SECITEM_CopyItem(arena, &id->parameters, params)) { return SECFailure; } diff --git a/libsecurity_smime/lib/secoid.c b/libsecurity_smime/lib/secoid.c index 0853144c..5976887b 100644 --- a/libsecurity_smime/lib/secoid.c +++ b/libsecurity_smime/lib/secoid.c @@ -32,11 +32,18 @@ */ #include "secoid.h" -#include "secitem.h" +#include "SecAsn1Item.h" #include "plhash.h" #include +#include + +#if USE_CDSA_CRYPTO #include +#else +#include +#include +#endif #include /* MISSI Mosaic Object ID space */ @@ -122,7 +129,6 @@ #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 @@ -155,21 +161,10 @@ /* { 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 - -/* 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 - #define CONST_OID static const unsigned char +CONST_OID null_oid[] = { }; + CONST_OID md2[] = { DIGEST, 0x02 }; CONST_OID md4[] = { DIGEST, 0x04 }; CONST_OID md5[] = { DIGEST, 0x05 }; @@ -237,10 +232,6 @@ 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 }; @@ -443,41 +434,188 @@ 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 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 }; - -/* a special case: always associated with a caller-specified OID */ -CONST_OID noOid[] = { 0 }; - -#define OI(x) { sizeof x, (uint8 *)x } +#define OI(x) { sizeof x, (uint8_t *)x } #ifndef SECOID_NO_STRINGS +#if USE_CDSA_CRYPTO #define OD(oid,tag,desc,mech,ext) { OI(oid), tag, desc, mech, ext } #else +#define OD(oid,tag,desc,mech,ext) { OI(oid), tag, desc, ext } +#endif +#else #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 mach the SECOidTag enum in secoidt.h! + @@@ We are sticking a enum type in a field of type SecAsn1AlgId, which is + defined as: + typedef struct { + SecAsn1Oid algorithm; + SecAsn1Item parameters; + } SecAsn1AlgId; */ -const static SECOidData oids[] = { - { { 0, NULL }, SEC_OID_UNKNOWN, - "Unknown OID", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION }, +static const SECOidData oids[] = { + OD( null_oid, SEC_OID_UNKNOWN, "Unknown OID", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), OD( md2, SEC_OID_MD2, "MD2", CSSM_ALGID_MD2, INVALID_CERT_EXTENSION ), - OD( md4, SEC_OID_MD4, - "MD4", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( md4, SEC_OID_MD4, "MD4", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), OD( md5, SEC_OID_MD5, "MD5", CSSM_ALGID_MD5, INVALID_CERT_EXTENSION ), OD( sha1, SEC_OID_SHA1, "SHA-1", CSSM_ALGID_SHA1, INVALID_CERT_EXTENSION ), OD( rc2cbc, SEC_OID_RC2_CBC, @@ -745,10 +883,8 @@ const static SECOidData oids[] = { "CRL reason code", CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), OD( x509InvalidDate, SEC_OID_X509_INVALID_DATE, "Invalid Date", CSSM_ALGID_NONE, SUPPORTED_CERT_EXTENSION ), - OD( x500RSAEncryption, SEC_OID_X500_RSA_ENCRYPTION, "X500 RSA Encryption", CSSM_ALGID_RSA, INVALID_CERT_EXTENSION ), - /* added for alg 1485 */ OD( rfc1274Uid, SEC_OID_RFC1274_UID, "RFC1274 User Id", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), @@ -933,11 +1069,9 @@ const static SECOidData oids[] = { OD( netscapeSMimeKEA, SEC_OID_NETSCAPE_SMIME_KEA, "Netscape S/MIME KEA", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), - /* Skipjack OID -- ### mwelch temporary */ OD( skipjackCBC, SEC_OID_FORTEZZA_SKIPJACK, "Skipjack CBC64", CSSM_ALGID_SKIPJACK, INVALID_CERT_EXTENSION ), - /* pkcs12 v2 oids */ OD( pkcs12V2PBEWithSha1And128BitRC4, SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4, @@ -1052,7 +1186,6 @@ const static 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 ), @@ -1061,19 +1194,18 @@ const static SECOidData oids[] = { SEC_OID_MS_SMIME_ENCRYPTION_KEY_PREFERENCE, "Microsoft S/MIME Encryption Key Preference", 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), + 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), OD( pkcs1SHA256WithRSAEncryption, SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION, - "PKCS #1 SHA-256 With RSA Encryption", CSSM_ALGID_SHA256WithRSA, + "PKCS #1 SHA-256 With RSA Encryption", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), OD( pkcs1SHA384WithRSAEncryption, SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION, - "PKCS #1 SHA-384 With RSA Encryption", CSSM_ALGID_SHA384WithRSA, + "PKCS #1 SHA-384 With RSA Encryption", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), OD( pkcs1SHA512WithRSAEncryption, SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION, - "PKCS #1 SHA-512 With RSA Encryption", CSSM_ALGID_SHA512WithRSA, + "PKCS #1 SHA-512 With RSA Encryption", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), OD( aes128_KEY_WRAP, SEC_OID_AES_128_KEY_WRAP, @@ -1082,42 +1214,8 @@ const static SECOidData oids[] = { "AES-192 Key Wrap", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), OD( aes256_KEY_WRAP, SEC_OID_AES_256_KEY_WRAP, "AES-256 Key Wrap", 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_ECDSA, - INVALID_CERT_EXTENSION ), - OD( ecdsaWithSHA1, SEC_OID_ECDSA_WithSHA1, - "SHA-1 With ECDSA", CSSM_ALGID_SHA1WithECDSA, - INVALID_CERT_EXTENSION ), - OD( dhSinglePassStdDHsha1kdf, SEC_OID_DH_SINGLE_STD_SHA1KDF, - "ECDH With SHA1 KDF", CSSM_ALGID_ECDH_X963_KDF, - 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 ), + OD( sha224, SEC_OID_SHA224, "SHA-224", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), }; /* @@ -1125,19 +1223,15 @@ const static SECOidData oids[] = { * and gets modified if the user loads new crypto modules. */ +#if 0 /* disabled since its not used (the only function that could "add" items was disabled before */ + +// TODO: protect this: used multi-threaded static PLHashTable *oid_d_hash = 0; static SECOidData **secoidDynamicTable = NULL; static int secoidDynamicTableSize = 0; static int secoidLastDynamicEntry = 0; static int secoidLastHashEntry = 0; -/* - * A mutex to protect creation and writing of all three hash tables in - * this module, and reading of the dynamic table. - */ -static pthread_mutex_t oid_hash_mutex = PTHREAD_MUTEX_INITIALIZER; - -/* caller holds oid_hash_mutex */ static SECStatus secoid_DynamicRehash(void) { @@ -1174,27 +1268,23 @@ secoid_DynamicRehash(void) /* * Lookup a Dynamic OID. Dynamic OID's still change slowly, so it's * cheaper to rehash the table when it changes than it is to do the loop - * each time. + * each time. Worry: what about thread safety here? Global Static data with + * no locks.... (sigh). */ static SECOidData * -secoid_FindDynamic(const SECItem *key) { +secoid_FindDynamic(const SecAsn1Item *key) { SECOidData *ret = NULL; - - pthread_mutex_lock(&oid_hash_mutex); - /* subsequent errors to loser: */ if (secoidDynamicTable == NULL) { /* PORT_SetError! */ - goto loser; + return NULL; } if (secoidLastHashEntry != secoidLastDynamicEntry) { SECStatus rv = secoid_DynamicRehash(); if ( rv != SECSuccess ) { - goto loser; + return NULL; } } ret = (SECOidData *)PL_HashTableLookup (oid_d_hash, key); -loser: - pthread_mutex_unlock(&oid_hash_mutex); return ret; } @@ -1203,58 +1293,45 @@ static SECOidData * secoid_FindDynamicByTag(SECOidTag tagnum) { int tagNumDiff; - SECOidData *rtn = NULL; - - if (tagnum < SEC_OID_TOTAL) { + + if (secoidDynamicTable == NULL) { return NULL; } - pthread_mutex_lock(&oid_hash_mutex); - /* subsequent errors to loser: */ - - if (secoidDynamicTable == NULL) { - goto loser; + if (tagnum < SEC_OID_TOTAL) { + return NULL; } tagNumDiff = tagnum - SEC_OID_TOTAL; if (tagNumDiff >= secoidLastDynamicEntry) { - goto loser; + return NULL; } - rtn = secoidDynamicTable[tagNumDiff]; -loser: - pthread_mutex_unlock(&oid_hash_mutex); - return rtn; + return(secoidDynamicTable[tagNumDiff]); } -#if 0 +/* + * this routine is definately not thread safe. It is only called out + * of the UI, or at init time. If we want to call it any other time, + * we need to make it thread safe. + */ SECStatus -SECOID_AddEntry(SECItem *oid, char *description, CSSM_ALGORITHMS cssmAlgorithm) { - SECOidData *oiddp; - int last; - int tableSize; - int next; - SECOidData **newTable; +SECOID_AddEntry(SecAsn1Item *oid, char *description, SecAsn1AlgId cssmAlgorithm) { + SECOidData *oiddp = (SECOidData *)PORT_Alloc(sizeof(SECOidData)); + int last = secoidLastDynamicEntry; + int tableSize = secoidDynamicTableSize; + int next = last++; + SECOidData **newTable = secoidDynamicTable; SECOidData **oldTable = NULL; - SECStatus srtn = SECFailure; if (oid == NULL) { return SECFailure; } - pthread_mutex_lock(&oid_hash_mutex); - /* subsequent errors to loser: */ - - oiddp = (SECOidData *)PORT_Alloc(sizeof(SECOidData)); - last = secoidLastDynamicEntry; - tableSize = secoidDynamicTableSize; - next = last++; - newTable = secoidDynamicTable; - /* fill in oid structure */ if (SECITEM_CopyItem(NULL,&oiddp->oid,oid) != SECSuccess) { PORT_Free(oiddp); - goto loser; + return SECFailure; } oiddp->offset = (SECOidTag)(next + SEC_OID_TOTAL); /* may we should just reference the copy passed to us? */ @@ -1270,7 +1347,7 @@ SECOID_AddEntry(SECItem *oid, char *description, CSSM_ALGORITHMS cssmAlgorithm) if (newTable == NULL) { PORT_Free(oiddp->oid.Data); PORT_Free(oiddp); - goto loser; + return SECFailure; } PORT_Memcpy(newTable,oldTable,sizeof(SECOidData *)*oldTableSize); PORT_Free(oldTable); @@ -1279,38 +1356,32 @@ SECOID_AddEntry(SECItem *oid, char *description, CSSM_ALGORITHMS cssmAlgorithm) newTable[next] = oiddp; secoidDynamicTable = newTable; secoidDynamicTableSize = tableSize; - secoidLastDynamicEntry = last; - srtn = SECSuccess; -loser: - pthread_mutex_unlock(&oid_hash_mutex); - return srtn; + secoidLastDynamicEntry= last; + return SECSuccess; } #endif - /* normal static table processing */ -/* creation and writes to these hash tables is protected by oid_hash_mutex */ +/* TODO: MORE GLOBAL DATA */ +static pthread_once_t hash_once = PTHREAD_ONCE_INIT; static PLHashTable *oidhash = NULL; static PLHashTable *oidmechhash = NULL; static PLHashNumber secoid_HashNumber(const void *key) { - intptr_t keyint = (intptr_t)key; - // XXX/gh revisit this - keyint ^= (keyint >> 8); - keyint ^= (keyint << 8); - return (PLHashNumber) keyint; + /* This truncate the hash to the lower 32 bits -- probably safe right ??? */ + return (PLHashNumber)(PRUword)key; } -/* caller holds oid_hash_mutex */ + static SECStatus InitOIDHash(void) { PLHashEntry *entry; const SECOidData *oid; - int i; + size_t ix; oidhash = PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare, PL_CompareValues, NULL, NULL); @@ -1323,10 +1394,10 @@ InitOIDHash(void) return(SECFailure); } - for ( i = 0; i < ( sizeof(oids) / sizeof(SECOidData) ); i++ ) { - oid = &oids[i]; + for ( ix = 0; ix < ( sizeof(oids) / sizeof(SECOidData) ); ix++ ) { + oid = &oids[ix]; - PORT_Assert ( oid->offset == i ); + PORT_Assert ( oid->offset == ix ); entry = PL_HashTableAdd( oidhash, &oid->oid, (void *)oid ); if ( entry == NULL ) { @@ -1335,41 +1406,39 @@ InitOIDHash(void) return(SECFailure); } - if ( oid->cssmAlgorithm != CSSM_ALGID_NONE ) { - intptr_t algorithm = oid->cssmAlgorithm; +#if USE_CDSA_CRYPTO + if ( oid->cssmAlgorithm.algorithm.Length /*CSSM_ALGID_NONE*/ ) { entry = PL_HashTableAdd( oidmechhash, - (void *)algorithm, (void *)oid ); + (void *)&(oid->cssmAlgorithm), (void *)oid ); if ( entry == NULL ) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); PORT_Assert(0); /* This function should never fail. */ return(SECFailure); } } +#endif } - PORT_Assert (i == SEC_OID_TOTAL); + PORT_Assert (ix == SEC_OID_TOTAL); return(SECSuccess); } +static void InitOIDHashOnce() +{ + if (SECSuccess != InitOIDHash()) + abort(); +} + +/* TODO: appears to be the public entry point */ SECOidData * -SECOID_FindOIDByCssmAlgorithm(CSSM_ALGORITHMS cssmAlgorithm) +SECOID_FindOIDByCssmAlgorithm(SecAsn1AlgId cssmAlgorithm) { SECOidData *ret; - int rv; - pthread_mutex_lock(&oid_hash_mutex); - if ( !oidhash ) { - rv = InitOIDHash(); - if ( rv != SECSuccess ) { - pthread_mutex_unlock(&oid_hash_mutex); - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return NULL; - } - } - pthread_mutex_unlock(&oid_hash_mutex); - intptr_t algorithm = cssmAlgorithm; - ret = PL_HashTableLookupConst ( oidmechhash, (void *)algorithm); + pthread_once(&hash_once, InitOIDHashOnce); + + ret = PL_HashTableLookupConst ( oidmechhash, (void *)&cssmAlgorithm); if ( ret == NULL ) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); } @@ -1377,26 +1446,19 @@ SECOID_FindOIDByCssmAlgorithm(CSSM_ALGORITHMS cssmAlgorithm) return (ret); } +/* TODO: appears to be the public entry point */ SECOidData * -SECOID_FindOID(const SECItem *oid) +SECOID_FindOID(const SecAsn1Item *oid) { SECOidData *ret; - int rv; - pthread_mutex_lock(&oid_hash_mutex); - if ( !oidhash ) { - rv = InitOIDHash(); - if ( rv != SECSuccess ) { - pthread_mutex_unlock(&oid_hash_mutex); - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return NULL; - } - } - pthread_mutex_unlock(&oid_hash_mutex); + pthread_once(&hash_once, InitOIDHashOnce); ret = PL_HashTableLookupConst ( oidhash, oid ); if ( ret == NULL ) { +#if 0 ret = secoid_FindDynamic(oid); +#endif if (ret == NULL) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); } @@ -1406,7 +1468,7 @@ SECOID_FindOID(const SECItem *oid) } SECOidTag -SECOID_FindOIDTag(const SECItem *oid) +SECOID_FindOIDTag(const SecAsn1Item *oid) { SECOidData *oiddata; @@ -1421,16 +1483,22 @@ SECOID_FindOIDTag(const SECItem *oid) SECOidData * SECOID_FindOIDByTag(SECOidTag tagnum) { + pthread_once(&hash_once, InitOIDHashOnce); +#if 0 if (tagnum >= SEC_OID_TOTAL) { return secoid_FindDynamicByTag(tagnum); } +#else + if (tagnum >= SEC_OID_TOTAL) + return NULL; +#endif PORT_Assert((unsigned int)tagnum < (sizeof(oids) / sizeof(SECOidData))); return (SECOidData *)(&oids[tagnum]); } -Boolean SECOID_KnownCertExtenOID (const SECItem *extenOid) +Boolean SECOID_KnownCertExtenOID (const SecAsn1Item *extenOid) { SECOidData * oidData; @@ -1449,6 +1517,7 @@ SECOID_FindOIDTagDescription(SECOidTag tagnum) return oidData ? oidData->desc : 0; } +#if 0 /* * free up the oid tables. */ @@ -1457,7 +1526,6 @@ SECOID_Shutdown(void) { int i; - pthread_mutex_lock(&oid_hash_mutex); if (oidhash) { PL_HashTableDestroy(oidhash); oidhash = NULL; @@ -1480,6 +1548,6 @@ SECOID_Shutdown(void) secoidLastDynamicEntry = 0; secoidLastHashEntry = 0; } - pthread_mutex_unlock(&oid_hash_mutex); return SECSuccess; } +#endif diff --git a/libsecurity_smime/lib/secoid.h b/libsecurity_smime/lib/secoid.h index c7088d89..09a091fe 100644 --- a/libsecurity_smime/lib/secoid.h +++ b/libsecurity_smime/lib/secoid.h @@ -53,10 +53,10 @@ SEC_ASN1_CHOOSER_DECLARE(SECOID_AlgorithmIDTemplate) /* * OID handling routines */ -extern SECOidData *SECOID_FindOID(const SECItem *oid); -extern SECOidTag SECOID_FindOIDTag(const SECItem *oid); +extern SECOidData *SECOID_FindOID(const SecAsn1Item *oid); +extern SECOidTag SECOID_FindOIDTag(const SecAsn1Item *oid); extern SECOidData *SECOID_FindOIDByTag(SECOidTag tagnum); -extern SECOidData *SECOID_FindOIDByCssmAlgorithm(CSSM_ALGORITHMS cssmAlgorithm); +extern SECOidData *SECOID_FindOIDByCssmAlgorithm(SecAsn1AlgId cssmAlgorithm); /****************************************/ /* @@ -71,7 +71,7 @@ extern SECOidData *SECOID_FindOIDByCssmAlgorithm(CSSM_ALGORITHMS cssmAlgorithm); ** "params" if not NULL, the parameters to go with the algorithm */ extern SECStatus SECOID_SetAlgorithmID(PRArenaPool *arena, SECAlgorithmID *aid, - SECOidTag tag, SECItem *params); + SECOidTag tag, const SecAsn1Item *params); /* ** Copy the "src" object to "dest". Memory is allocated in "dest" for @@ -101,16 +101,18 @@ extern void SECOID_DestroyAlgorithmID(SECAlgorithmID *aid, Boolean freeit); extern SECComparison SECOID_CompareAlgorithmID(const SECAlgorithmID *a, const SECAlgorithmID *b); -extern Boolean SECOID_KnownCertExtenOID (const SECItem *extenOid); +extern Boolean SECOID_KnownCertExtenOID (const SecAsn1Item *extenOid); /* Given a SEC_OID_* tag, return a string describing it. */ extern const char *SECOID_FindOIDTagDescription(SECOidTag tagnum); +#if 0 /* * free up the oid data structures. */ extern SECStatus SECOID_Shutdown(void); +#endif SEC_END_PROTOS diff --git a/libsecurity_smime/lib/secoidt.h b/libsecurity_smime/lib/secoidt.h index f882ed95..45731dbb 100644 --- a/libsecurity_smime/lib/secoidt.h +++ b/libsecurity_smime/lib/secoidt.h @@ -39,8 +39,6 @@ #include -#include - typedef enum { INVALID_CERT_EXTENSION = 0, UNSUPPORTED_CERT_EXTENSION = 1, @@ -48,10 +46,12 @@ typedef enum { } SECSupportExtenTag; struct SECOidDataStr { - SECItem oid; + SecAsn1Item oid; SECOidTag offset; const char * desc; - CSSM_ALGORITHMS cssmAlgorithm; +#if USE_CDSA_CRYPTO + SecAsn1AlgId cssmAlgorithm; +#endif SECSupportExtenTag supportedExtension; /* only used for x.509 v3 extensions, so that we can print the names of those diff --git a/libsecurity_smime/lib/security_smime.exp b/libsecurity_smime/lib/security_smime.exp index fff9f21c..8290ccdc 100644 --- a/libsecurity_smime/lib/security_smime.exp +++ b/libsecurity_smime/lib/security_smime.exp @@ -1,5 +1,5 @@ # -# Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. +# Copyright (c) 2004,2008,2010 Apple Inc. All Rights Reserved. # # @APPLE_LICENSE_HEADER_START@ # @@ -20,8 +20,6 @@ # # @APPLE_LICENSE_HEADER_END@ # -_SecArenaPoolCreate -_SecArenaPoolFree _SecCmsContentInfoGetBulkKey _SecCmsContentInfoGetBulkKeySize _SecCmsContentInfoGetChildContentInfo @@ -39,12 +37,12 @@ _SecCmsContentInfoSetContentEncAlgID _SecCmsContentInfoSetContentEncryptedData _SecCmsContentInfoSetContentEnvelopedData _SecCmsContentInfoSetContentSignedData -_SecCmsContentInfoSetContentOther _SecCmsDecoderCreate _SecCmsDecoderDestroy _SecCmsDecoderFinish _SecCmsDecoderUpdate _SecCmsDigestContextCancel +_SecCmsDigestContextDestroy _SecCmsDigestContextFinishMultiple _SecCmsDigestContextStartMultiple _SecCmsDigestContextUpdate @@ -58,7 +56,6 @@ _SecCmsEncoderUpdate _SecCmsEncryptedDataCreate _SecCmsEncryptedDataDestroy _SecCmsEncryptedDataGetContentInfo -_SecCmsEnvelopedDataAddRecipient _SecCmsEnvelopedDataCreate _SecCmsEnvelopedDataDestroy _SecCmsEnvelopedDataGetContentInfo @@ -70,30 +67,17 @@ _SecCmsMessageCreate _SecCmsMessageDecode _SecCmsMessageDestroy _SecCmsMessageEncode -_SecCmsMessageGetArena _SecCmsMessageGetContent _SecCmsMessageGetContentInfo _SecCmsMessageIsContentEmpty _SecCmsMessageIsEncrypted _SecCmsMessageIsSigned -_SecCmsMessageContainsTSTInfo -_SecCmsMessageSetTSACallback -_SecCmsMessageSetTSAContext -_SecCmsTSAGetDefaultContext -_SecCmsTSADefaultCallback -_kTSAContextKeyURL -_kTSAContextKeyNoCerts -_kTSADebugContextKeyBadReq -_kTSADebugContextKeyBadNonce -_SecTSAResponseCopyDEREncoding _SecCmsRecipientInfoCreate _SecCmsRecipientInfoCreateWithSubjKeyID _SecCmsRecipientInfoCreateWithSubjKeyIDFromCert -_SecCmsRecipientInfoDestroy _SecCmsSignedDataAddCertChain _SecCmsSignedDataAddCertList _SecCmsSignedDataAddCertificate -_SecCmsSignedDataAddSignerInfo _SecCmsSignedDataContainsCertsOrCrls _SecCmsSignedDataCreate _SecCmsSignedDataCreateCertsOnly @@ -105,7 +89,7 @@ _SecCmsSignedDataGetSignerInfo _SecCmsSignedDataGetSignerInfos _SecCmsSignedDataHasDigests _SecCmsSignedDataImportCerts -_SecCmsSignedDataSetDigests +_SecCmsSignedDataSetDigestContext _SecCmsSignedDataSignerInfoCount _SecCmsSignedDataVerifyCertsOnly _SecCmsSignedDataVerifySignerInfo @@ -116,7 +100,6 @@ _SecCmsSignerInfoAddSMIMEEncKeyPrefs _SecCmsSignerInfoAddSigningTime _SecCmsSignerInfoCreate _SecCmsSignerInfoCreateWithSubjKeyID -_SecCmsSignerInfoDestroy _SecCmsSignerInfoGetCertList _SecCmsSignerInfoGetDigestAlg _SecCmsSignerInfoGetDigestAlgTag @@ -124,9 +107,7 @@ _SecCmsSignerInfoGetSignerCommonName _SecCmsSignerInfoGetSignerEmailAddress _SecCmsSignerInfoGetSigningCertificate _SecCmsSignerInfoGetSigningTime -_SecCmsSignerInfoGetTimestampTime _SecCmsSignerInfoGetVerificationStatus -_SecCmsSignerInfoGetEncDigest _SecCmsSignerInfoIncludeCerts _SecCmsSignerInfoSaveSMIMEProfile _SecCmsUtilVerificationStatusToString diff --git a/libsecurity_smime/lib/smimeutil.c b/libsecurity_smime/lib/smimeutil.c index eacec1a0..e92a43d1 100644 --- a/libsecurity_smime/lib/smimeutil.c +++ b/libsecurity_smime/lib/smimeutil.c @@ -38,7 +38,7 @@ #include "cmslocal.h" #include "secoid.h" -#include "secitem.h" +#include "SecAsn1Item.h" #include "cert.h" #include "SecSMIMEPriv.h" @@ -57,18 +57,18 @@ static unsigned char asn1_int64[] = { SEC_ASN1_INTEGER, 0x01, 0x40 }; static unsigned char asn1_int128[] = { SEC_ASN1_INTEGER, 0x02, 0x00, 0x80 }; /* RC2 algorithm parameters (used in smime_cipher_map) */ -static CSSM_DATA param_int40 = { sizeof(asn1_int40), asn1_int40 }; -static CSSM_DATA param_int64 = { sizeof(asn1_int64), asn1_int64 }; -static CSSM_DATA param_int128 = { sizeof(asn1_int128), asn1_int128 }; +static SecAsn1Item param_int40 = { sizeof(asn1_int40), asn1_int40 }; +static SecAsn1Item param_int64 = { sizeof(asn1_int64), asn1_int64 }; +static SecAsn1Item param_int128 = { sizeof(asn1_int128), asn1_int128 }; /* - * XXX Would like the "parameters" field to be a CSSM_DATA_PTR , but the + * XXX Would like the "parameters" field to be a SecAsn1Item * , but the * encoder is having trouble with optional pointers to an ANY. Maybe * once that is fixed, can change this back... */ typedef struct { - CSSM_DATA capabilityID; - CSSM_DATA parameters; + SecAsn1Item capabilityID; + SecAsn1Item parameters; long cipher; /* optimization */ } NSSSMIMECapability; @@ -101,7 +101,7 @@ typedef struct { union { SecCmsIssuerAndSN *issuerAndSN; SecCmsRecipientKeyIdentifier *recipientKeyID; - CSSM_DATA_PTR subjectKeyID; + SecAsn1Item *subjectKeyID; } id; } NSSSMIMEEncryptionKeyPreference; @@ -130,7 +130,7 @@ static const SecAsn1Template smime_encryptionkeypref_template[] = { typedef struct { unsigned long cipher; SECOidTag algtag; - CSSM_DATA_PTR parms; + SecAsn1Item *parms; Boolean enabled; /* in the user's preferences */ Boolean allowed; /* per export policy */ } smime_cipher_map_entry; @@ -139,12 +139,14 @@ typedef struct { static smime_cipher_map_entry smime_cipher_map[] = { /* cipher algtag parms enabled allowed */ /* ---------------------------------------------------------------------------------- */ - { SMIME_RC2_CBC_40, SEC_OID_RC2_CBC, ¶m_int40, PR_TRUE, PR_TRUE }, - { SMIME_DES_CBC_56, SEC_OID_DES_CBC, NULL, PR_TRUE, PR_TRUE }, - { SMIME_RC2_CBC_64, SEC_OID_RC2_CBC, ¶m_int64, PR_TRUE, PR_TRUE }, - { SMIME_RC2_CBC_128, SEC_OID_RC2_CBC, ¶m_int128, PR_TRUE, PR_TRUE }, + { SMIME_RC2_CBC_40, SEC_OID_RC2_CBC, ¶m_int40, PR_FALSE, PR_FALSE }, + { SMIME_DES_CBC_56, SEC_OID_DES_CBC, NULL, PR_TRUE, PR_FALSE }, + { SMIME_RC2_CBC_64, SEC_OID_RC2_CBC, ¶m_int64, PR_FALSE, PR_FALSE }, + { SMIME_RC2_CBC_128, SEC_OID_RC2_CBC, ¶m_int128, PR_FALSE, PR_FALSE }, { SMIME_DES_EDE3_168, SEC_OID_DES_EDE3_CBC, NULL, PR_TRUE, PR_TRUE }, - { SMIME_AES_CBC_128, SEC_OID_AES_128_CBC, NULL, PR_TRUE, PR_TRUE }, + { SMIME_AES_CBC_128, SEC_OID_AES_128_CBC, NULL, PR_TRUE, PR_TRUE }, + { SMIME_AES_CBC_192, SEC_OID_AES_192_CBC, NULL, PR_TRUE, PR_TRUE }, + { SMIME_AES_CBC_256, SEC_OID_AES_256_CBC, NULL, PR_TRUE, PR_TRUE }, { SMIME_FORTEZZA, SEC_OID_FORTEZZA_SKIPJACK, NULL, PR_TRUE, PR_TRUE } }; static const int smime_cipher_map_count = sizeof(smime_cipher_map) / sizeof(smime_cipher_map_entry); @@ -168,7 +170,7 @@ smime_mapi_by_cipher(unsigned long cipher) * NSS_SMIME_EnableCipher - this function locally records the user's preference */ OSStatus -SecSMIMEEnableCipher(uint32 which, Boolean on) +SecSMIMEEnableCipher(unsigned long which, Boolean on) { unsigned long mask; int mapi; @@ -202,7 +204,7 @@ SecSMIMEEnableCipher(uint32 which, Boolean on) * this function locally records the export policy */ OSStatus -SecSMIMEAllowCipher(uint32 which, Boolean on) +SecSMIMEAllowCipher(unsigned long which, Boolean on) { unsigned long mask; int mapi; @@ -235,14 +237,18 @@ static OSStatus nss_smime_get_cipher_for_alg_and_key(SECAlgorithmID *algid, SecSymmetricKeyRef key, unsigned long *cipher) { SECOidTag algtag; - unsigned int keylen_bits; + CFIndex keylen_bits; unsigned long c; algtag = SECOID_GetAlgorithmTag(algid); switch (algtag) { case SEC_OID_RC2_CBC: +#if USE_CDSA_CRYPTO if (SecKeyGetStrengthInBits(key, algid, &keylen_bits)) return SECFailure; +#else + keylen_bits = CFDataGetLength((CFDataRef)key) * 8; +#endif switch (keylen_bits) { case 40: c = SMIME_RC2_CBC_40; @@ -260,14 +266,20 @@ nss_smime_get_cipher_for_alg_and_key(SECAlgorithmID *algid, SecSymmetricKeyRef k case SEC_OID_DES_CBC: c = SMIME_DES_CBC_56; break; + case SEC_OID_FORTEZZA_SKIPJACK: + c = SMIME_FORTEZZA; + break; case SEC_OID_DES_EDE3_CBC: c = SMIME_DES_EDE3_168; break; case SEC_OID_AES_128_CBC: c = SMIME_AES_CBC_128; break; - case SEC_OID_FORTEZZA_SKIPJACK: - c = SMIME_FORTEZZA; + case SEC_OID_AES_192_CBC: + c = SMIME_AES_CBC_192; + break; + case SEC_OID_AES_256_CBC: + c = SMIME_AES_CBC_256; break; default: return SECFailure; @@ -390,7 +402,7 @@ smime_choose_cipher(SecCertificateRef scert, SecCertificateRef *rcerts) Boolean scert_is_fortezza = (scert == NULL) ? PR_FALSE : PK11_FortezzaHasKEA(scert); #endif - chosen_cipher = SMIME_RC2_CBC_40; /* the default, LCD */ + chosen_cipher = SMIME_DES_CBC_56; /* the default, LCD */ weak_mapi = smime_mapi_by_cipher(chosen_cipher); poolp = PORT_NewArena (1024); /* XXX what is right value? */ @@ -413,7 +425,7 @@ smime_choose_cipher(SecCertificateRef scert, SecCertificateRef *rcerts) /* walk all the recipient's certs */ for (rcount = 0; rcerts[rcount] != NULL; rcount++) { - CSSM_DATA_PTR profile; + SecAsn1Item *profile; NSSSMIMECapability **caps; int pref; @@ -448,7 +460,7 @@ smime_choose_cipher(SecCertificateRef scert, SecCertificateRef *rcerts) /* no profile found - so we can only assume that the user can do * the mandatory algorithms which is RC2-40 (weak crypto) and 3DES (strong crypto) */ SecPublicKeyRef key; - unsigned int pklen_bits; + size_t pklen_bits; /* * if recipient's public key length is > 512, vote for a strong cipher @@ -464,7 +476,11 @@ smime_choose_cipher(SecCertificateRef scert, SecCertificateRef *rcerts) key = CERT_ExtractPublicKey(rcerts[rcount]); pklen_bits = 0; if (key != NULL) { +#if USE_CDSA_CRYPTO SecKeyGetStrengthInBits(key, NULL, &pklen_bits); +#else + pklen_bits = SecKeyGetSize(key, kSecKeyKeySizeInBits); +#endif SECKEY_DestroyPublicKey (key); } @@ -530,7 +546,6 @@ smime_keysize_by_cipher (unsigned long which) keysize = 64; break; case SMIME_RC2_CBC_128: - case SMIME_AES_CBC_128: keysize = 128; break; case SMIME_DES_CBC_56: @@ -585,18 +600,17 @@ SecSMIMEFindBulkAlgForRecipients(SecCertificateRef *rcerts, SECOidTag *bulkalgta * symmetric ciphers, NO signature algorithms or key encipherment algorithms. * * "poolp" - arena pool to create the S/MIME capabilities data on - * "dest" - CSSM_DATA to put the data in + * "dest" - SecAsn1Item to put the data in * "includeFortezzaCiphers" - PR_TRUE if fortezza ciphers should be included */ OSStatus -SecSMIMECreateSMIMECapabilities(SecArenaPoolRef pool, CSSM_DATA_PTR dest, Boolean includeFortezzaCiphers) +SecSMIMECreateSMIMECapabilities(PLArenaPool *poolp, SecAsn1Item *dest, Boolean includeFortezzaCiphers) { - PLArenaPool *poolp = (PLArenaPool *)pool; NSSSMIMECapability *cap; NSSSMIMECapability **smime_capabilities; smime_cipher_map_entry *map; SECOidData *oiddata; - CSSM_DATA_PTR dummy; + SecAsn1Item *dummy; int i, capIndex; /* if we have an old NSSSMIMECapability array, we'll reuse it (has the right size) */ @@ -660,16 +674,15 @@ SecSMIMECreateSMIMECapabilities(SecArenaPoolRef pool, CSSM_DATA_PTR dest, Boolea * SecSMIMECreateSMIMEEncKeyPrefs - create S/MIME encryption key preferences attr value * * "poolp" - arena pool to create the attr value on - * "dest" - CSSM_DATA to put the data in + * "dest" - SecAsn1Item to put the data in * "cert" - certificate that should be marked as preferred encryption key * cert is expected to have been verified for EmailRecipient usage. */ OSStatus -SecSMIMECreateSMIMEEncKeyPrefs(SecArenaPoolRef pool, CSSM_DATA_PTR dest, SecCertificateRef cert) +SecSMIMECreateSMIMEEncKeyPrefs(PLArenaPool *poolp, SecAsn1Item *dest, SecCertificateRef cert) { - PLArenaPool *poolp = (PLArenaPool *)pool; NSSSMIMEEncryptionKeyPreference ekp; - CSSM_DATA_PTR dummy = NULL; + SecAsn1Item *dummy = NULL; PLArenaPool *tmppoolp = NULL; if (cert == NULL) @@ -697,15 +710,14 @@ loser: * SecSMIMECreateSMIMEEncKeyPrefs - create S/MIME encryption key preferences attr value using MS oid * * "poolp" - arena pool to create the attr value on - * "dest" - CSSM_DATA to put the data in + * "dest" - SecAsn1Item to put the data in * "cert" - certificate that should be marked as preferred encryption key * cert is expected to have been verified for EmailRecipient usage. */ OSStatus -SecSMIMECreateMSSMIMEEncKeyPrefs(SecArenaPoolRef pool, CSSM_DATA_PTR dest, SecCertificateRef cert) +SecSMIMECreateMSSMIMEEncKeyPrefs(PLArenaPool *poolp, SecAsn1Item *dest, SecCertificateRef cert) { - PLArenaPool *poolp = (PLArenaPool *)pool; - CSSM_DATA_PTR dummy = NULL; + SecAsn1Item *dummy = NULL; PLArenaPool *tmppoolp = NULL; SecCmsIssuerAndSN *isn; @@ -728,6 +740,7 @@ loser: return (dummy == NULL) ? SECFailure : SECSuccess; } +#if 0 /* * SecSMIMEGetCertFromEncryptionKeyPreference - * find cert marked by EncryptionKeyPreference attribute @@ -739,7 +752,7 @@ loser: * they are assumed to have been imported already. */ SecCertificateRef -SecSMIMEGetCertFromEncryptionKeyPreference(SecKeychainRef keychainOrArray, CSSM_DATA_PTR DERekp) +SecSMIMEGetCertFromEncryptionKeyPreference(SecKeychainRef keychainOrArray, SecAsn1Item *DERekp) { PLArenaPool *tmppoolp = NULL; SecCertificateRef cert = NULL; @@ -756,7 +769,7 @@ SecSMIMEGetCertFromEncryptionKeyPreference(SecKeychainRef keychainOrArray, CSSM_ /* find cert */ switch (ekp.selector) { case NSSSMIMEEncryptionKeyPref_IssuerSN: - cert = CERT_FindCertByIssuerAndSN(keychainOrArray, NULL, NULL, ekp.id.issuerAndSN); + cert = CERT_FindCertByIssuerAndSN(keychainOrArray, ekp.id.issuerAndSN); break; case NSSSMIMEEncryptionKeyPref_RKeyID: case NSSSMIMEEncryptionKeyPref_SubjectKeyID: @@ -770,13 +783,12 @@ loser: return cert; } +#endif #if 0 extern const char __nss_smime_rcsid[]; extern const char __nss_smime_sccsid[]; -#endif -#if 0 /* -- unused */ Boolean NSSSMIME_VersionCheck(const char *importedVersion) { @@ -799,4 +811,5 @@ NSSSMIME_VersionCheck(const char *importedVersion) return NSS_VersionCheck(importedVersion); #endif } -#endif +#endif /* 0 */ + diff --git a/libsecurity_smime/libsecurity_smime.xcodeproj/project.pbxproj b/libsecurity_smime/libsecurity_smime.xcodeproj/project.pbxproj index 3e6d91de..37231950 100644 --- a/libsecurity_smime/libsecurity_smime.xcodeproj/project.pbxproj +++ b/libsecurity_smime/libsecurity_smime.xcodeproj/project.pbxproj @@ -6,26 +6,22 @@ objectVersion = 46; objects = { -/* Begin PBXAggregateTarget section */ - 0540498B0A37699A0035F195 /* Copy Open Source Docs */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 054049900A3769AC0035F195 /* Build configuration list for PBXAggregateTarget "Copy Open Source Docs" */; - buildPhases = ( - 0540498A0A37699A0035F195 /* CopyFiles */, - 054049A10A376A130035F195 /* CopyFiles */, - ); - dependencies = ( - ); - name = "Copy Open Source Docs"; - productName = "Copy Open Source Docs"; - }; -/* End PBXAggregateTarget section */ - /* Begin PBXBuildFile section */ - 0540498E0A3769AC0035F195 /* libsecurity_smime.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0540498C0A3769AC0035F195 /* libsecurity_smime.plist */; }; - 054049990A376A010035F195 /* libsecurity_smime.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0540498D0A3769AC0035F195 /* libsecurity_smime.txt */; }; - 0588CB2A0E7084880069D232 /* siginfoUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0588CB290E7084880069D232 /* siginfoUtils.cpp */; }; + 0C2C8E25164D8F3F00D0B3C9 /* SecSMIME.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7183470637153700230DDE /* SecSMIME.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4C14208F0415845900CA2E66 /* cmsdigdata.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F803E9FC5B00A80181 /* cmsdigdata.c */; }; + 4C21886C0635F4BD00E64E02 /* SecCmsBase.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CCC26030635F1A100CBF0D4 /* SecCmsBase.h */; }; + 4C21886D0635F4BD00E64E02 /* SecCmsContentInfo.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CCC26040635F1A100CBF0D4 /* SecCmsContentInfo.h */; }; + 4C21886E0635F4BD00E64E02 /* SecCmsDecoder.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CCC26050635F1A100CBF0D4 /* SecCmsDecoder.h */; }; + 4C21886F0635F4BD00E64E02 /* SecCmsDigestContext.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CCC26060635F1A100CBF0D4 /* SecCmsDigestContext.h */; }; + 4C2188700635F4BD00E64E02 /* SecCmsDigestedData.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CCC26070635F1A100CBF0D4 /* SecCmsDigestedData.h */; }; + 4C2188710635F4BD00E64E02 /* SecCmsEncoder.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CCC26080635F1A100CBF0D4 /* SecCmsEncoder.h */; }; + 4C2188720635F4BD00E64E02 /* SecCmsEnvelopedData.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CCC26090635F1A100CBF0D4 /* SecCmsEnvelopedData.h */; }; + 4C2188730635F4BD00E64E02 /* SecCmsMessage.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CCC260A0635F1A100CBF0D4 /* SecCmsMessage.h */; }; + 4C2188740635F4BD00E64E02 /* SecCmsRecipientInfo.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CCC260B0635F1A100CBF0D4 /* SecCmsRecipientInfo.h */; }; + 4C2188750635F4BD00E64E02 /* SecCmsSignedData.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CCC260C0635F1A100CBF0D4 /* SecCmsSignedData.h */; }; + 4C2188760635F4BD00E64E02 /* SecCmsSignerInfo.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CCC260D0635F1A100CBF0D4 /* SecCmsSignerInfo.h */; }; + 4C2188810635F4D900E64E02 /* security_smime.exp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C21887E0635F4D300E64E02 /* security_smime.exp */; }; + 4C2188820635F4DD00E64E02 /* security_smime.exp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C21887E0635F4D300E64E02 /* security_smime.exp */; }; 4C27421103E9FC6700A80181 /* cmsarray.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F203E9FC5B00A80181 /* cmsarray.c */; }; 4C27421303E9FC6900A80181 /* cmsasn1.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F303E9FC5B00A80181 /* cmsasn1.c */; }; 4C27421403E9FC6A00A80181 /* cmsattr.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F403E9FC5B00A80181 /* cmsattr.c */; }; @@ -33,32 +29,33 @@ 4C27421703E9FC6D00A80181 /* cmsdecode.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F703E9FC5B00A80181 /* cmsdecode.c */; }; 4C27421B03E9FC7000A80181 /* cmsencode.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741FB03E9FC5B00A80181 /* cmsencode.c */; }; 4C27421D03E9FC7100A80181 /* cmslocal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C2741FD03E9FC5B00A80181 /* cmslocal.h */; }; - 4C27421E03E9FC7200A80181 /* cmsmessage.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741FE03E9FC5B00A80181 /* cmsmessage.c */; }; 4C27422103E9FC7500A80181 /* cmsreclist.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C27420103E9FC5B00A80181 /* cmsreclist.c */; }; 4C27422203E9FC7600A80181 /* cmsreclist.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C27420203E9FC5B00A80181 /* cmsreclist.h */; }; 4C424BE8063F28F600E9831A /* SecSMIMEPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C424BE7063F28F600E9831A /* SecSMIMEPriv.h */; }; 4C6CA861040308C700CA2E66 /* cmssigdata.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C27420303E9FC5B00A80181 /* cmssigdata.c */; }; - 4C7183480637153700230DDE /* SecSMIME.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7183470637153700230DDE /* SecSMIME.h */; settings = {ATTRIBUTES = (); }; }; + 4C7182ED0637119600230DDE /* secoidt.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C8E166E0438EEE700CA2E66 /* secoidt.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C7183480637153700230DDE /* SecSMIME.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7183470637153700230DDE /* SecSMIME.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4C7183560637155B00230DDE /* SecSMIME.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7183470637153700230DDE /* SecSMIME.h */; }; 4C8E166F0438EEE700CA2E66 /* secoid.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C8E166C0438EEE700CA2E66 /* secoid.c */; }; 4C8E16700438EEE700CA2E66 /* secoid.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C8E166D0438EEE700CA2E66 /* secoid.h */; }; 4C8E16740438EF5700CA2E66 /* plhash.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C8E16720438EF5700CA2E66 /* plhash.c */; }; 4C8E16750438EF5700CA2E66 /* plhash.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C8E16730438EF5700CA2E66 /* plhash.h */; }; - 4C8E16790438EFD700CA2E66 /* secitem.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C8E16770438EFD700CA2E66 /* secitem.c */; }; - 4C8E167A0438EFD700CA2E66 /* secitem.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C8E16780438EFD700CA2E66 /* secitem.h */; }; + 4C8E16790438EFD700CA2E66 /* SecAsn1Item.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C8E16770438EFD700CA2E66 /* SecAsn1Item.c */; }; + 4C8E167A0438EFD700CA2E66 /* SecAsn1Item.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C8E16780438EFD700CA2E66 /* SecAsn1Item.h */; }; 4CA51CE00420246F00CA2E66 /* cryptohi.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CA51CDF0420246F00CA2E66 /* cryptohi.h */; }; 4CB42E340421212D00CA2E66 /* cryptohi.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CB42E330421212D00CA2E66 /* cryptohi.c */; }; 4CB6AADA040DA84D00CA2E66 /* secalgid.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CB6AAD9040DA84D00CA2E66 /* secalgid.c */; }; - 4CCC260E0635F1A200CBF0D4 /* SecCmsBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26030635F1A100CBF0D4 /* SecCmsBase.h */; settings = {ATTRIBUTES = (); }; }; - 4CCC260F0635F1A200CBF0D4 /* SecCmsContentInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26040635F1A100CBF0D4 /* SecCmsContentInfo.h */; settings = {ATTRIBUTES = (); }; }; - 4CCC26100635F1A200CBF0D4 /* SecCmsDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26050635F1A100CBF0D4 /* SecCmsDecoder.h */; settings = {ATTRIBUTES = (); }; }; - 4CCC26110635F1A200CBF0D4 /* SecCmsDigestContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26060635F1A100CBF0D4 /* SecCmsDigestContext.h */; settings = {ATTRIBUTES = (); }; }; - 4CCC26120635F1A200CBF0D4 /* SecCmsDigestedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26070635F1A100CBF0D4 /* SecCmsDigestedData.h */; settings = {ATTRIBUTES = (); }; }; - 4CCC26130635F1A200CBF0D4 /* SecCmsEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26080635F1A100CBF0D4 /* SecCmsEncoder.h */; settings = {ATTRIBUTES = (); }; }; - 4CCC26140635F1A200CBF0D4 /* SecCmsEnvelopedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26090635F1A100CBF0D4 /* SecCmsEnvelopedData.h */; settings = {ATTRIBUTES = (); }; }; - 4CCC26150635F1A200CBF0D4 /* SecCmsMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC260A0635F1A100CBF0D4 /* SecCmsMessage.h */; settings = {ATTRIBUTES = (); }; }; - 4CCC26160635F1A200CBF0D4 /* SecCmsRecipientInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC260B0635F1A100CBF0D4 /* SecCmsRecipientInfo.h */; settings = {ATTRIBUTES = (); }; }; - 4CCC26170635F1A200CBF0D4 /* SecCmsSignedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC260C0635F1A100CBF0D4 /* SecCmsSignedData.h */; settings = {ATTRIBUTES = (); }; }; - 4CCC26180635F1A200CBF0D4 /* SecCmsSignerInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC260D0635F1A100CBF0D4 /* SecCmsSignerInfo.h */; settings = {ATTRIBUTES = (); }; }; + 4CCC260E0635F1A200CBF0D4 /* SecCmsBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26030635F1A100CBF0D4 /* SecCmsBase.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4CCC260F0635F1A200CBF0D4 /* SecCmsContentInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26040635F1A100CBF0D4 /* SecCmsContentInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4CCC26100635F1A200CBF0D4 /* SecCmsDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26050635F1A100CBF0D4 /* SecCmsDecoder.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4CCC26110635F1A200CBF0D4 /* SecCmsDigestContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26060635F1A100CBF0D4 /* SecCmsDigestContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4CCC26120635F1A200CBF0D4 /* SecCmsDigestedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26070635F1A100CBF0D4 /* SecCmsDigestedData.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4CCC26130635F1A200CBF0D4 /* SecCmsEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26080635F1A100CBF0D4 /* SecCmsEncoder.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4CCC26140635F1A200CBF0D4 /* SecCmsEnvelopedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC26090635F1A100CBF0D4 /* SecCmsEnvelopedData.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4CCC26150635F1A200CBF0D4 /* SecCmsMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC260A0635F1A100CBF0D4 /* SecCmsMessage.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4CCC26160635F1A200CBF0D4 /* SecCmsRecipientInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC260B0635F1A100CBF0D4 /* SecCmsRecipientInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4CCC26170635F1A200CBF0D4 /* SecCmsSignedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC260C0635F1A100CBF0D4 /* SecCmsSignedData.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4CCC26180635F1A200CBF0D4 /* SecCmsSignerInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCC260D0635F1A100CBF0D4 /* SecCmsSignerInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4CDA0D5E04200AD600CA2E66 /* cmscipher.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F603E9FC5B00A80181 /* cmscipher.c */; }; 4CDA0D6004200AD800CA2E66 /* cmsencdata.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741FA03E9FC5B00A80181 /* cmsencdata.c */; }; 4CDA0D6104200AD800CA2E66 /* cmsdigest.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F903E9FC5B00A80181 /* cmsdigest.c */; }; @@ -69,58 +66,103 @@ 4CDA0D6604200AE000CA2E66 /* cmssiginfo.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C27420403E9FC5B00A80181 /* cmssiginfo.c */; }; 4CDA0D6704200B0F00CA2E66 /* smimeutil.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C27420F03E9FC5B00A80181 /* smimeutil.c */; }; 4CEC5CDF042A721300CA2E66 /* cmspriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CEC5CDE042A721300CA2E66 /* cmspriv.h */; }; - 4CEC5CE1042A722000CA2E66 /* cmstpriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CEC5CE0042A722000CA2E66 /* cmstpriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4CEDC82106371B1700B7E254 /* SecCmsEncryptedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CEDC82006371B1700B7E254 /* SecCmsEncryptedData.h */; settings = {ATTRIBUTES = (); }; }; - 5232A822150AD71A00E6BB48 /* tsaSupportPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 5232A821150AD71A00E6BB48 /* tsaSupportPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 52B609D514F4665700134209 /* tsaTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = 52B609D314F4665700134209 /* tsaTemplates.c */; }; - 52B609D614F4665700134209 /* tsaTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B609D414F4665700134209 /* tsaTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 52D7A24A15092A0600CF48F7 /* tsaSupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 52D7A24915092A0600CF48F7 /* tsaSupport.c */; }; - 52D7A24D15094B8B00CF48F7 /* tsaSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 52D7A24C15092AAD00CF48F7 /* tsaSupport.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4CEC5CE1042A722000CA2E66 /* cmstpriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CEC5CE0042A722000CA2E66 /* cmstpriv.h */; }; + 4CEDC82106371B1700B7E254 /* SecCmsEncryptedData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CEDC82006371B1700B7E254 /* SecCmsEncryptedData.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4CEDC82806371B4000B7E254 /* SecCmsEncryptedData.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CEDC82006371B1700B7E254 /* SecCmsEncryptedData.h */; }; + 79BDD29C0D60C75D000D84D3 /* crypto-embedded.c in Sources */ = {isa = PBXBuildFile; fileRef = 79BDD29B0D60C75D000D84D3 /* crypto-embedded.c */; }; + 79DC32240D4949720039E4BC /* cmsmessage.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741FE03E9FC5B00A80181 /* cmsmessage.c */; }; + 79DC336B0D4E6F170039E4BC /* cmsarray.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F203E9FC5B00A80181 /* cmsarray.c */; }; + 79DC336C0D4E6F170039E4BC /* cmsasn1.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F303E9FC5B00A80181 /* cmsasn1.c */; }; + 79DC336D0D4E6F170039E4BC /* cmsattr.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F403E9FC5B00A80181 /* cmsattr.c */; }; + 79DC336E0D4E6F170039E4BC /* cmscinfo.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F503E9FC5B00A80181 /* cmscinfo.c */; }; + 79DC336F0D4E6F170039E4BC /* cmscipher.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F603E9FC5B00A80181 /* cmscipher.c */; }; + 79DC33700D4E6F170039E4BC /* cmsdecode.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F703E9FC5B00A80181 /* cmsdecode.c */; }; + 79DC33710D4E6F170039E4BC /* cmsdigdata.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F803E9FC5B00A80181 /* cmsdigdata.c */; }; + 79DC33720D4E6F170039E4BC /* cmsdigest.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741F903E9FC5B00A80181 /* cmsdigest.c */; }; + 79DC33730D4E6F170039E4BC /* cmsencdata.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741FA03E9FC5B00A80181 /* cmsencdata.c */; }; + 79DC33740D4E6F170039E4BC /* cmsencode.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741FB03E9FC5B00A80181 /* cmsencode.c */; }; + 79DC33750D4E6F170039E4BC /* cmsenvdata.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741FC03E9FC5B00A80181 /* cmsenvdata.c */; }; + 79DC33760D4E6F170039E4BC /* cmspubkey.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741FF03E9FC5B00A80181 /* cmspubkey.c */; }; + 79DC33770D4E6F170039E4BC /* cmsrecinfo.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C27420003E9FC5B00A80181 /* cmsrecinfo.c */; }; + 79DC33780D4E6F170039E4BC /* cmsreclist.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C27420103E9FC5B00A80181 /* cmsreclist.c */; }; + 79DC33790D4E6F170039E4BC /* cmssigdata.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C27420303E9FC5B00A80181 /* cmssigdata.c */; }; + 79DC337A0D4E6F170039E4BC /* cmssiginfo.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C27420403E9FC5B00A80181 /* cmssiginfo.c */; }; + 79DC337B0D4E6F170039E4BC /* cmsutil.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6D72BC0410298900CA2E66 /* cmsutil.c */; }; + 79DC337D0D4E6F170039E4BC /* plhash.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C8E16720438EF5700CA2E66 /* plhash.c */; }; + 79DC337E0D4E6F170039E4BC /* secalgid.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CB6AAD9040DA84D00CA2E66 /* secalgid.c */; }; + 79DC337F0D4E6F170039E4BC /* SecAsn1Item.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C8E16770438EFD700CA2E66 /* SecAsn1Item.c */; }; + 79DC33800D4E6F170039E4BC /* secoid.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C8E166C0438EEE700CA2E66 /* secoid.c */; }; + 79DC33810D4E6F170039E4BC /* smimeutil.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C27420F03E9FC5B00A80181 /* smimeutil.c */; }; + 79DC33820D4E6F170039E4BC /* cmsmessage.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2741FE03E9FC5B00A80181 /* cmsmessage.c */; }; F64399010420118A01CA2DCC /* cert.h in Headers */ = {isa = PBXBuildFile; fileRef = F64398FF0420118A01CA2DCC /* cert.h */; }; F64399020420118A01CA2DCC /* cert.c in Sources */ = {isa = PBXBuildFile; fileRef = F64399000420118A01CA2DCC /* cert.c */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 0540499A0A376A090035F195 /* PBXContainerItemProxy */ = { + 4C89DFC5056AC87A0002E1CA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C2741E803E9FBAF00A80181 /* Project object */; proxyType = 1; - remoteGlobalIDString = 0540498B0A37699A0035F195; - remoteInfo = "Copy Open Source Docs"; + remoteGlobalIDString = 4C7FAB40056AC7A200FE0C44; + remoteInfo = security_smime; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ - 0540498A0A37699A0035F195 /* CopyFiles */ = { + 4C2188660635F43B00E64E02 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = /usr/local/OpenSourceVersions/; - dstSubfolderSpec = 0; + buildActionMask = 2147483647; + dstPath = SecurityPieces/Exports/Security; + dstSubfolderSpec = 16; files = ( - 0540498E0A3769AC0035F195 /* libsecurity_smime.plist in CopyFiles */, + 4C2188810635F4D900E64E02 /* security_smime.exp in CopyFiles */, ); - runOnlyForDeploymentPostprocessing = 1; + runOnlyForDeploymentPostprocessing = 0; }; - 054049A10A376A130035F195 /* CopyFiles */ = { + 4C2188670635F43E00E64E02 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; - dstPath = /usr/local/OpenSourceLicenses/; + dstPath = /usr/local/SecurityPieces/Exports/Security; dstSubfolderSpec = 0; files = ( - 054049990A376A010035F195 /* libsecurity_smime.txt in CopyFiles */, + 4C2188820635F4DD00E64E02 /* security_smime.exp in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; + 4C2188680635F44100E64E02 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = SecurityPieces/Headers/Security; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C2188690635F44300E64E02 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = SecurityPieces/PrivateHeaders/Security; + dstSubfolderSpec = 16; + files = ( + 4C21886C0635F4BD00E64E02 /* SecCmsBase.h in CopyFiles */, + 4C21886D0635F4BD00E64E02 /* SecCmsContentInfo.h in CopyFiles */, + 4C21886E0635F4BD00E64E02 /* SecCmsDecoder.h in CopyFiles */, + 4C21886F0635F4BD00E64E02 /* SecCmsDigestContext.h in CopyFiles */, + 4C2188700635F4BD00E64E02 /* SecCmsDigestedData.h in CopyFiles */, + 4C2188710635F4BD00E64E02 /* SecCmsEncoder.h in CopyFiles */, + 4CEDC82806371B4000B7E254 /* SecCmsEncryptedData.h in CopyFiles */, + 4C2188720635F4BD00E64E02 /* SecCmsEnvelopedData.h in CopyFiles */, + 4C2188730635F4BD00E64E02 /* SecCmsMessage.h in CopyFiles */, + 4C2188740635F4BD00E64E02 /* SecCmsRecipientInfo.h in CopyFiles */, + 4C2188750635F4BD00E64E02 /* SecCmsSignedData.h in CopyFiles */, + 4C2188760635F4BD00E64E02 /* SecCmsSignerInfo.h in CopyFiles */, + 4C7183560637155B00230DDE /* SecSMIME.h in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 0540498C0A3769AC0035F195 /* libsecurity_smime.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; path = libsecurity_smime.plist; sourceTree = ""; }; - 0540498D0A3769AC0035F195 /* libsecurity_smime.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = libsecurity_smime.txt; sourceTree = ""; }; - 0588CB290E7084880069D232 /* siginfoUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = siginfoUtils.cpp; sourceTree = ""; }; - 182BB39E146F1A68000BF1F3 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; - 182BB39F146F1A68000BF1F3 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; - 182BB3A0146F1A68000BF1F3 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; - 182BB3A1146F1A68000BF1F3 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; 4C21887E0635F4D300E64E02 /* security_smime.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = security_smime.exp; sourceTree = ""; }; 4C2741F203E9FC5B00A80181 /* cmsarray.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmsarray.c; sourceTree = ""; tabWidth = 8; }; 4C2741F303E9FC5B00A80181 /* cmsasn1.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmsasn1.c; sourceTree = ""; tabWidth = 8; }; @@ -145,14 +187,16 @@ 4C424BE7063F28F600E9831A /* SecSMIMEPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecSMIMEPriv.h; sourceTree = ""; }; 4C6D72BC0410298900CA2E66 /* cmsutil.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cmsutil.c; sourceTree = ""; tabWidth = 8; }; 4C7183470637153700230DDE /* SecSMIME.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecSMIME.h; sourceTree = ""; }; - 4C817F8405ED4D7A007975E6 /* libsecurity_smime.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurity_smime.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C7FAB41056AC7A200FE0C44 /* security_smime.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = security_smime.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C817F8405ED4D7A007975E6 /* security_smime */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = security_smime; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C8629041137DB63009EAB5A /* iPhoneFamily.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = iPhoneFamily.xcconfig; path = AppleInternal/XcodeConfig/iPhoneFamily.xcconfig; sourceTree = DEVELOPER_DIR; }; 4C8E166C0438EEE700CA2E66 /* secoid.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = secoid.c; sourceTree = ""; }; 4C8E166D0438EEE700CA2E66 /* secoid.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = secoid.h; sourceTree = ""; }; 4C8E166E0438EEE700CA2E66 /* secoidt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = secoidt.h; sourceTree = ""; }; 4C8E16720438EF5700CA2E66 /* plhash.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = plhash.c; sourceTree = ""; }; 4C8E16730438EF5700CA2E66 /* plhash.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = plhash.h; sourceTree = ""; }; - 4C8E16770438EFD700CA2E66 /* secitem.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = secitem.c; sourceTree = ""; }; - 4C8E16780438EFD700CA2E66 /* secitem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = secitem.h; sourceTree = ""; }; + 4C8E16770438EFD700CA2E66 /* SecAsn1Item.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SecAsn1Item.c; sourceTree = ""; }; + 4C8E16780438EFD700CA2E66 /* SecAsn1Item.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecAsn1Item.h; sourceTree = ""; }; 4CA51CDF0420246F00CA2E66 /* cryptohi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cryptohi.h; sourceTree = ""; tabWidth = 8; }; 4CB42E330421212D00CA2E66 /* cryptohi.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cryptohi.c; sourceTree = ""; tabWidth = 8; }; 4CB6AAD9040DA84D00CA2E66 /* secalgid.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = secalgid.c; sourceTree = ""; }; @@ -170,15 +214,61 @@ 4CEC5CDE042A721300CA2E66 /* cmspriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cmspriv.h; sourceTree = ""; }; 4CEC5CE0042A722000CA2E66 /* cmstpriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cmstpriv.h; sourceTree = ""; }; 4CEDC82006371B1700B7E254 /* SecCmsEncryptedData.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecCmsEncryptedData.h; sourceTree = ""; }; - 5232A821150AD71A00E6BB48 /* tsaSupportPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tsaSupportPriv.h; sourceTree = ""; }; - 52B609D314F4665700134209 /* tsaTemplates.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tsaTemplates.c; sourceTree = ""; }; - 52B609D414F4665700134209 /* tsaTemplates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tsaTemplates.h; sourceTree = ""; }; - 52D7A24915092A0600CF48F7 /* tsaSupport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tsaSupport.c; sourceTree = ""; }; - 52D7A24C15092AAD00CF48F7 /* tsaSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = tsaSupport.h; sourceTree = ""; }; + 79BDD29B0D60C75D000D84D3 /* crypto-embedded.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "crypto-embedded.c"; sourceTree = ""; }; + 79DC33620D4E6EEA0039E4BC /* libCMS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCMS.a; sourceTree = BUILT_PRODUCTS_DIR; }; F64398FF0420118A01CA2DCC /* cert.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cert.h; sourceTree = ""; tabWidth = 8; }; F64399000420118A01CA2DCC /* cert.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cert.c; sourceTree = ""; tabWidth = 8; }; /* End PBXFileReference section */ +/* Begin PBXFrameworkTarget section */ + 4C7FAB40056AC7A200FE0C44 /* security_smime */ = { + isa = PBXFrameworkTarget; + buildConfigurationList = 79DC321C0D49473C0039E4BC /* Build configuration list for PBXFrameworkTarget "security_smime" */; + buildPhases = ( + 4C7FAB3B056AC7A200FE0C44 /* Headers */, + 4C2188660635F43B00E64E02 /* CopyFiles */, + 4C2188670635F43E00E64E02 /* CopyFiles */, + 4C2188680635F44100E64E02 /* CopyFiles */, + 4C2188690635F44300E64E02 /* CopyFiles */, + ); + dependencies = ( + ); + name = security_smime; + productInstallPath = /usr/local/SecurityPieces/Components/Security; + productName = security_smime; + productReference = 4C7FAB41056AC7A200FE0C44 /* security_smime.framework */; + productSettingsXML = " + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + + CFBundleGetInfoString + + CFBundleIconFile + + CFBundleIdentifier + + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + + CFBundlePackageType + FMWK + CFBundleShortVersionString + + CFBundleSignature + ???? + CFBundleVersion + 8 + + +"; + }; +/* End PBXFrameworkTarget section */ + /* Begin PBXFrameworksBuildPhase section */ 4C2741EB03E9FBF700A80181 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; @@ -187,36 +277,21 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 79DC33600D4E6EEA0039E4BC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 054049870A3769830035F195 /* docs */ = { - isa = PBXGroup; - children = ( - 0540498D0A3769AC0035F195 /* libsecurity_smime.txt */, - 0540498C0A3769AC0035F195 /* libsecurity_smime.plist */, - ); - path = docs; - sourceTree = ""; - }; - 182BB39D146F1A68000BF1F3 /* config */ = { - isa = PBXGroup; - children = ( - 182BB39E146F1A68000BF1F3 /* base.xcconfig */, - 182BB39F146F1A68000BF1F3 /* debug.xcconfig */, - 182BB3A0146F1A68000BF1F3 /* lib.xcconfig */, - 182BB3A1146F1A68000BF1F3 /* release.xcconfig */, - ); - name = config; - path = ../config; - sourceTree = ""; - }; 4C2741E403E9FBAF00A80181 = { isa = PBXGroup; children = ( 4C2741F003E9FC2100A80181 /* lib */, - 182BB39D146F1A68000BF1F3 /* config */, - 054049870A3769830035F195 /* docs */, + 4C8629041137DB63009EAB5A /* iPhoneFamily.xcconfig */, 4C2741EF03E9FBF700A80181 /* Products */, ); sourceTree = ""; @@ -224,7 +299,9 @@ 4C2741EF03E9FBF700A80181 /* Products */ = { isa = PBXGroup; children = ( - 4C817F8405ED4D7A007975E6 /* libsecurity_smime.a */, + 4C817F8405ED4D7A007975E6 /* security_smime */, + 4C7FAB41056AC7A200FE0C44 /* security_smime.framework */, + 79DC33620D4E6EEA0039E4BC /* libCMS.a */, ); name = Products; sourceTree = BUILT_PRODUCTS_DIR; @@ -232,12 +309,6 @@ 4C2741F003E9FC2100A80181 /* lib */ = { isa = PBXGroup; children = ( - 5232A821150AD71A00E6BB48 /* tsaSupportPriv.h */, - 52D7A24915092A0600CF48F7 /* tsaSupport.c */, - 52D7A24C15092AAD00CF48F7 /* tsaSupport.h */, - 52B609D314F4665700134209 /* tsaTemplates.c */, - 52B609D414F4665700134209 /* tsaTemplates.h */, - 0588CB290E7084880069D232 /* siginfoUtils.cpp */, F64399000420118A01CA2DCC /* cert.c */, F64398FF0420118A01CA2DCC /* cert.h */, 4C2741F203E9FC5B00A80181 /* cmsarray.c */, @@ -264,6 +335,7 @@ 4C6D72BC0410298900CA2E66 /* cmsutil.c */, 4CB42E330421212D00CA2E66 /* cryptohi.c */, 4CA51CDF0420246F00CA2E66 /* cryptohi.h */, + 79BDD29B0D60C75D000D84D3 /* crypto-embedded.c */, 4C8E16720438EF5700CA2E66 /* plhash.c */, 4C8E16730438EF5700CA2E66 /* plhash.h */, 4CB6AAD9040DA84D00CA2E66 /* secalgid.c */, @@ -279,8 +351,8 @@ 4CCC260B0635F1A100CBF0D4 /* SecCmsRecipientInfo.h */, 4CCC260C0635F1A100CBF0D4 /* SecCmsSignedData.h */, 4CCC260D0635F1A100CBF0D4 /* SecCmsSignerInfo.h */, - 4C8E16770438EFD700CA2E66 /* secitem.c */, - 4C8E16780438EFD700CA2E66 /* secitem.h */, + 4C8E16770438EFD700CA2E66 /* SecAsn1Item.c */, + 4C8E16780438EFD700CA2E66 /* SecAsn1Item.h */, 4C8E166C0438EEE700CA2E66 /* secoid.c */, 4C8E166D0438EEE700CA2E66 /* secoid.h */, 4C8E166E0438EEE700CA2E66 /* secoidt.h */, @@ -295,6 +367,14 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ + 0C2C8E24164D8F2C00D0B3C9 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C2C8E25164D8F3F00D0B3C9 /* SecSMIME.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 4C2741E903E9FBF700A80181 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -318,36 +398,60 @@ 4CCC26160635F1A200CBF0D4 /* SecCmsRecipientInfo.h in Headers */, 4CCC26170635F1A200CBF0D4 /* SecCmsSignedData.h in Headers */, 4CCC26180635F1A200CBF0D4 /* SecCmsSignerInfo.h in Headers */, - 4C7183480637153700230DDE /* SecSMIME.h in Headers */, - 4C8E167A0438EFD700CA2E66 /* secitem.h in Headers */, + 4C8E167A0438EFD700CA2E66 /* SecAsn1Item.h in Headers */, 4C8E16700438EEE700CA2E66 /* secoid.h in Headers */, + 4C7183480637153700230DDE /* SecSMIME.h in Headers */, 4C424BE8063F28F600E9831A /* SecSMIMEPriv.h in Headers */, - 52B609D614F4665700134209 /* tsaTemplates.h in Headers */, - 52D7A24D15094B8B00CF48F7 /* tsaSupport.h in Headers */, - 5232A822150AD71A00E6BB48 /* tsaSupportPriv.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C7FAB3B056AC7A200FE0C44 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C7182ED0637119600230DDE /* secoidt.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ -/* Begin PBXNativeTarget section */ +/* Begin PBXLibraryTarget section */ 4C2741ED03E9FBF700A80181 /* libsecurity_smime */ = { - isa = PBXNativeTarget; - buildConfigurationList = C23B0CD309A298C100B7FCED /* Build configuration list for PBXNativeTarget "libsecurity_smime" */; + isa = PBXLibraryTarget; + buildConfigurationList = 79DC321D0D49473C0039E4BC /* Build configuration list for PBXLibraryTarget "libsecurity_smime" */; buildPhases = ( 4C2741E903E9FBF700A80181 /* Headers */, 4C2741EA03E9FBF700A80181 /* Sources */, 4C2741EB03E9FBF700A80181 /* Frameworks */, - ); - buildRules = ( + 4C681B61056AC6BE00EB41E9 /* ShellScript */, + 4C681B62056AC6C100EB41E9 /* ShellScript */, ); dependencies = ( - 0540499B0A376A090035F195 /* PBXTargetDependency */, + 4C7FAB42056AC7A600FE0C44 /* PBXTargetDependency */, ); name = libsecurity_smime; productInstallPath = /usr/local/lib; productName = libSecurityNssSmime.a; - productReference = 4C817F8405ED4D7A007975E6 /* libsecurity_smime.a */; + productReference = 4C817F8405ED4D7A007975E6 /* security_smime */; + }; +/* End PBXLibraryTarget section */ + +/* Begin PBXNativeTarget section */ + 79DC33610D4E6EEA0039E4BC /* libCMS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 79DC33840D4E6F350039E4BC /* Build configuration list for PBXNativeTarget "libCMS" */; + buildPhases = ( + 0C2C8E24164D8F2C00D0B3C9 /* Headers */, + 79DC335F0D4E6EEA0039E4BC /* Sources */, + 79DC33600D4E6EEA0039E4BC /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libCMS; + productName = cms; + productReference = 79DC33620D4E6EEA0039E4BC /* libCMS.a */; productType = "com.apple.product-type.library.static"; }; /* End PBXNativeTarget section */ @@ -356,9 +460,9 @@ 4C2741E803E9FBAF00A80181 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0420; + LastUpgradeCheck = 0600; }; - buildConfigurationList = C23B0CD909A298C100B7FCED /* Build configuration list for PBXProject "libsecurity_smime" */; + buildConfigurationList = 79DC321B0D49473C0039E4BC /* Build configuration list for PBXProject "libsecurity_smime" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 1; @@ -374,11 +478,33 @@ projectRoot = ""; targets = ( 4C2741ED03E9FBF700A80181 /* libsecurity_smime */, - 0540498B0A37699A0035F195 /* Copy Open Source Docs */, + 4C7FAB40056AC7A200FE0C44 /* security_smime */, + 79DC33610D4E6EEA0039E4BC /* libCMS */, ); }; /* End PBXProject section */ +/* Begin PBXShellScriptBuildPhase section */ + 4C681B61056AC6BE00EB41E9 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "for variant in ${BUILD_VARIANTS}\ndo\n\tpostfix=`echo _${variant} | sed 's/_normal//'`\n\tln -fs \"../../../${PRODUCT_NAME}${postfix}\" ${SYMROOT}/${PRODUCT_NAME}.framework/Versions/A\n\tln -fs \"Versions/Current/${PRODUCT_NAME}${postfix}\" ${SYMROOT}/${PRODUCT_NAME}.framework\ndone"; + }; + 4C681B62056AC6C100EB41E9 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "for variant in ${BUILD_VARIANTS}\ndo\n\tpostfix=`echo _${variant} | sed 's/_normal//'`\n\tcp -p \"${SYMROOT}/${PRODUCT_NAME}${postfix}\" \"${DSTROOT}/usr/local/SecurityPieces/Components/Security/${PRODUCT_NAME}.framework/Versions/A\"\n\tranlib \"${DSTROOT}/usr/local/SecurityPieces/Components/Security/${PRODUCT_NAME}.framework/Versions/A/${PRODUCT_NAME}${postfix}\"\n\tln -fs \"Versions/Current/${PRODUCT_NAME}${postfix}\" \"${DSTROOT}/usr/local/SecurityPieces/Components/Security/${PRODUCT_NAME}.framework\"\ndone"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 4C2741EA03E9FBF700A80181 /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -396,7 +522,6 @@ 4CDA0D6004200AD800CA2E66 /* cmsencdata.c in Sources */, 4C27421B03E9FC7000A80181 /* cmsencode.c in Sources */, 4CDA0D6204200AD900CA2E66 /* cmsenvdata.c in Sources */, - 4C27421E03E9FC7200A80181 /* cmsmessage.c in Sources */, 4CDA0D6304200ADD00CA2E66 /* cmspubkey.c in Sources */, 4CDA0D6404200ADD00CA2E66 /* cmsrecinfo.c in Sources */, 4C27422103E9FC7500A80181 /* cmsreclist.c in Sources */, @@ -406,92 +531,311 @@ 4CB42E340421212D00CA2E66 /* cryptohi.c in Sources */, 4C8E16740438EF5700CA2E66 /* plhash.c in Sources */, 4CB6AADA040DA84D00CA2E66 /* secalgid.c in Sources */, - 4C8E16790438EFD700CA2E66 /* secitem.c in Sources */, + 4C8E16790438EFD700CA2E66 /* SecAsn1Item.c in Sources */, 4C8E166F0438EEE700CA2E66 /* secoid.c in Sources */, 4CDA0D6704200B0F00CA2E66 /* smimeutil.c in Sources */, - 0588CB2A0E7084880069D232 /* siginfoUtils.cpp in Sources */, - 52B609D514F4665700134209 /* tsaTemplates.c in Sources */, - 52D7A24A15092A0600CF48F7 /* tsaSupport.c in Sources */, + 79DC32240D4949720039E4BC /* cmsmessage.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 79DC335F0D4E6EEA0039E4BC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 79DC336B0D4E6F170039E4BC /* cmsarray.c in Sources */, + 79DC336C0D4E6F170039E4BC /* cmsasn1.c in Sources */, + 79DC336D0D4E6F170039E4BC /* cmsattr.c in Sources */, + 79DC336E0D4E6F170039E4BC /* cmscinfo.c in Sources */, + 79DC336F0D4E6F170039E4BC /* cmscipher.c in Sources */, + 79DC33700D4E6F170039E4BC /* cmsdecode.c in Sources */, + 79DC33710D4E6F170039E4BC /* cmsdigdata.c in Sources */, + 79DC33720D4E6F170039E4BC /* cmsdigest.c in Sources */, + 79DC33730D4E6F170039E4BC /* cmsencdata.c in Sources */, + 79DC33740D4E6F170039E4BC /* cmsencode.c in Sources */, + 79DC33750D4E6F170039E4BC /* cmsenvdata.c in Sources */, + 79DC33760D4E6F170039E4BC /* cmspubkey.c in Sources */, + 79DC33770D4E6F170039E4BC /* cmsrecinfo.c in Sources */, + 79DC33780D4E6F170039E4BC /* cmsreclist.c in Sources */, + 79DC33790D4E6F170039E4BC /* cmssigdata.c in Sources */, + 79DC337A0D4E6F170039E4BC /* cmssiginfo.c in Sources */, + 79DC337B0D4E6F170039E4BC /* cmsutil.c in Sources */, + 79DC337D0D4E6F170039E4BC /* plhash.c in Sources */, + 79DC337E0D4E6F170039E4BC /* secalgid.c in Sources */, + 79DC337F0D4E6F170039E4BC /* SecAsn1Item.c in Sources */, + 79DC33800D4E6F170039E4BC /* secoid.c in Sources */, + 79DC33810D4E6F170039E4BC /* smimeutil.c in Sources */, + 79DC33820D4E6F170039E4BC /* cmsmessage.c in Sources */, + 79BDD29C0D60C75D000D84D3 /* crypto-embedded.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 0540499B0A376A090035F195 /* PBXTargetDependency */ = { + 4C7FAB42056AC7A600FE0C44 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 0540498B0A37699A0035F195 /* Copy Open Source Docs */; - targetProxy = 0540499A0A376A090035F195 /* PBXContainerItemProxy */; + target = 4C7FAB40056AC7A200FE0C44 /* security_smime */; + targetProxy = 4C89DFC5056AC87A0002E1CA /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 054049910A3769AC0035F195 /* Debug */ = { + 79BDD2AE0D60CA06000D84D3 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 4C8629041137DB63009EAB5A /* iPhoneFamily.xcconfig */; buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_OPTIMIZATION_LEVEL = 1; + GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_VALUE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CFLAGS = ( + "-fconstant-cfstrings", + "-fno-inline", + ); + SDKROOT = iphoneos.internal; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-unused-parameter", + "-Wno-missing-field-initializers", + ); }; name = Debug; }; - 054049950A3769AC0035F195 /* Release */ = { + 79BDD2AF0D60CA06000D84D3 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + BUILD_VARIANTS = ( + normal, + debug, + profile, + ); + CURRENT_PROJECT_VERSION = 8; + FRAMEWORK_SEARCH_PATHS = ( + /usr/local/SecurityPieces/Frameworks, + /usr/local/SecurityPieces/Components/Security, + ); + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + HEADER_SEARCH_PATHS = ( + "$(BUILT_PRODUCTS_DIR)/SecurityPieces/Headers", + "$(BUILT_PRODUCTS_DIR)/SecurityPieces/PrivateHeaders", + ); + LIBRARY_STYLE = STATIC; + OTHER_ASFLAGS_debug = "$(OTHER_CFLAGS)"; + OTHER_ASFLAGS_normal = "-DNDEBUG $(OTHER_CFLAGS)"; + OTHER_ASFLAGS_profile = "-DNDEBUG $(OTHER_CFLAGS) -pg"; + OTHER_CFLAGS_debug = "$(OTHER_CFLAGS) -O0 -fno-inline"; + OTHER_CFLAGS_normal = "-DNDEBUG $(OTHER_CFLAGS)"; + OTHER_CFLAGS_profile = "-DNDEBUG $(OTHER_CFLAGS) -pg"; + OTHER_CPLUSPLUSFLAGS_debug = "$(OTHER_CFLAGS) -O0 -fno-inline"; + OTHER_CPLUSPLUSFLAGS_normal = "-DNDEBUG $(OTHER_CFLAGS)"; + OTHER_CPLUSPLUSFLAGS_profile = "-DNDEBUG $(OTHER_CFLAGS) -pg"; + OTHER_LDFLAGS_debug = "$(OTHER_LDFLAGS)"; + OTHER_LDFLAGS_normal = "$(OTHER_LDFLAGS)"; + OTHER_LDFLAGS_profile = "$(OTHER_LDFLAGS) -pg"; + PRIVATE_HEADER_DIR = "$(DSTROOT)/usr/local/SecurityPieces/PrivateHeaders/Security"; + PRODUCT_NAME = security_smime; + PUBLIC_HEADER_DIR = "$(DSTROOT)/usr/local/SecurityPieces/Headers/Security"; + VERSIONING_SYSTEM = "apple-generic"; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); }; - name = Release; + name = Debug; + }; + 79BDD2B00D60CA06000D84D3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + FRAMEWORK_VERSION = A; + INSTALL_PATH = /usr/local/SecurityPieces/Components/Security; + PRODUCT_NAME = security_smime; + WRAPPER_EXTENSION = framework; + }; + name = Debug; }; - C23B0CD409A298C100B7FCED /* Debug */ = { + 79BDD2B10D60CA06000D84D3 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 182BB39F146F1A68000BF1F3 /* debug.xcconfig */; buildSettings = { + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/..", + "$(PROJECT_DIR)/../Security/utilities", + "$(PROJECT_DIR)/../Security/sec", + "$(PROJECT_DIR)/../Security/libsecurity_keychain/libDER", + "$(PROJECT_DIR)/../Security/libsecurity_asn1", + "$(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include", + "$(DSTROOT)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include", + ); + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/lib"; + PRODUCT_NAME = CMS; + PUBLIC_HEADERS_FOLDER_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include/Security"; + SKIP_INSTALL = YES; }; name = Debug; }; - C23B0CD809A298C100B7FCED /* Release */ = { + 79BDD2BA0D60CA0A000D84D3 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 182BB3A1146F1A68000BF1F3 /* release.xcconfig */; + baseConfigurationReference = 4C8629041137DB63009EAB5A /* iPhoneFamily.xcconfig */; buildSettings = { + COPY_PHASE_STRIP = YES; + GCC_OPTIMIZATION_LEVEL = s; + GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1"; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_VALUE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CFLAGS = "-fconstant-cfstrings"; + SDKROOT = iphoneos.internal; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + WARNING_CFLAGS = ( + "-Wall", + "-Wextra", + "-Wno-unused-parameter", + "-Wno-missing-field-initializers", + ); }; name = Release; }; - C23B0CDA09A298C100B7FCED /* Debug */ = { + 79BDD2BB0D60CA0A000D84D3 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 182BB3A0146F1A68000BF1F3 /* lib.xcconfig */; buildSettings = { + BUILD_VARIANTS = ( + normal, + debug, + profile, + ); + CURRENT_PROJECT_VERSION = 8; + FRAMEWORK_SEARCH_PATHS = ( + /usr/local/SecurityPieces/Frameworks, + /usr/local/SecurityPieces/Components/Security, + ); + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + HEADER_SEARCH_PATHS = ( + "$(BUILT_PRODUCTS_DIR)/SecurityPieces/Headers", + "$(BUILT_PRODUCTS_DIR)/SecurityPieces/PrivateHeaders", + ); + LIBRARY_STYLE = STATIC; + OTHER_ASFLAGS_debug = "$(OTHER_CFLAGS)"; + OTHER_ASFLAGS_normal = "-DNDEBUG $(OTHER_CFLAGS)"; + OTHER_ASFLAGS_profile = "-DNDEBUG $(OTHER_CFLAGS) -pg"; + OTHER_CFLAGS_debug = "$(OTHER_CFLAGS) -O0 -fno-inline"; + OTHER_CFLAGS_normal = "-DNDEBUG $(OTHER_CFLAGS)"; + OTHER_CFLAGS_profile = "-DNDEBUG $(OTHER_CFLAGS) -pg"; + OTHER_CPLUSPLUSFLAGS_debug = "$(OTHER_CFLAGS) -O0 -fno-inline"; + OTHER_CPLUSPLUSFLAGS_normal = "-DNDEBUG $(OTHER_CFLAGS)"; + OTHER_CPLUSPLUSFLAGS_profile = "-DNDEBUG $(OTHER_CFLAGS) -pg"; + OTHER_LDFLAGS_debug = "$(OTHER_LDFLAGS)"; + OTHER_LDFLAGS_normal = "$(OTHER_LDFLAGS)"; + OTHER_LDFLAGS_profile = "$(OTHER_LDFLAGS) -pg"; + PRIVATE_HEADER_DIR = "$(DSTROOT)/usr/local/SecurityPieces/PrivateHeaders/Security"; + PRODUCT_NAME = security_smime; + PUBLIC_HEADER_DIR = "$(DSTROOT)/usr/local/SecurityPieces/Headers/Security"; + VERSIONING_SYSTEM = "apple-generic"; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); }; - name = Debug; + name = Release; + }; + 79BDD2BC0D60CA0A000D84D3 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + FRAMEWORK_VERSION = A; + INSTALL_PATH = /usr/local/SecurityPieces/Components/Security; + PRODUCT_NAME = security_smime; + WRAPPER_EXTENSION = framework; + }; + name = Release; }; - C23B0CDE09A298C100B7FCED /* Release */ = { + 79BDD2BD0D60CA0A000D84D3 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 182BB3A0146F1A68000BF1F3 /* lib.xcconfig */; buildSettings = { + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/..", + "$(PROJECT_DIR)/../Security/utilities", + "$(PROJECT_DIR)/../Security/sec", + "$(PROJECT_DIR)/../Security/libsecurity_keychain/libDER", + "$(PROJECT_DIR)/../Security/libsecurity_asn1", + "$(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include", + "$(DSTROOT)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include", + ); + INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/lib"; + PRODUCT_NAME = CMS; + PUBLIC_HEADERS_FOLDER_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include/Security"; + SKIP_INSTALL = YES; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 054049900A3769AC0035F195 /* Build configuration list for PBXAggregateTarget "Copy Open Source Docs" */ = { + 79DC321B0D49473C0039E4BC /* Build configuration list for PBXProject "libsecurity_smime" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 79BDD2AE0D60CA06000D84D3 /* Debug */, + 79BDD2BA0D60CA0A000D84D3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 79DC321C0D49473C0039E4BC /* Build configuration list for PBXFrameworkTarget "security_smime" */ = { isa = XCConfigurationList; buildConfigurations = ( - 054049910A3769AC0035F195 /* Debug */, - 054049950A3769AC0035F195 /* Release */, + 79BDD2B00D60CA06000D84D3 /* Debug */, + 79BDD2BC0D60CA0A000D84D3 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - C23B0CD309A298C100B7FCED /* Build configuration list for PBXNativeTarget "libsecurity_smime" */ = { + 79DC321D0D49473C0039E4BC /* Build configuration list for PBXLibraryTarget "libsecurity_smime" */ = { isa = XCConfigurationList; buildConfigurations = ( - C23B0CD409A298C100B7FCED /* Debug */, - C23B0CD809A298C100B7FCED /* Release */, + 79BDD2AF0D60CA06000D84D3 /* Debug */, + 79BDD2BB0D60CA0A000D84D3 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - C23B0CD909A298C100B7FCED /* Build configuration list for PBXProject "libsecurity_smime" */ = { + 79DC33840D4E6F350039E4BC /* Build configuration list for PBXNativeTarget "libCMS" */ = { isa = XCConfigurationList; buildConfigurations = ( - C23B0CDA09A298C100B7FCED /* Debug */, - C23B0CDE09A298C100B7FCED /* Release */, + 79BDD2B10D60CA06000D84D3 /* Debug */, + 79BDD2BD0D60CA0A000D84D3 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/libsecurity_smime/libsecurity_smime.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_smime/libsecurity_smime.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index c1314930..00000000 --- a/libsecurity_smime/libsecurity_smime.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 0540498B0A37699A0035F195 - - primary - - - 4C2741ED03E9FBF700A80181 - - primary - - - AC62F5EF18B4356A00704BBD - - primary - - - - - diff --git a/libsecurity_smime/security_smime b/libsecurity_smime/security_smime new file mode 120000 index 00000000..945c9b46 --- /dev/null +++ b/libsecurity_smime/security_smime @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/libsecurity_ssl/config/base.xcconfig b/libsecurity_ssl/config/base.xcconfig deleted file mode 100644 index 2171d75d..00000000 --- a/libsecurity_ssl/config/base.xcconfig +++ /dev/null @@ -1,14 +0,0 @@ -CODE_SIGN_IDENTITY = -; -GCC_VERSION = com.apple.compilers.llvm.clang.1_0 -DEBUG_INFORMATION_FORMAT = dwarf-with-dsym -CURRENT_PROJECT_VERSION = $(RC_ProjectSourceVersion) -VERSIONING_SYSTEM = apple-generic; -DEAD_CODE_STRIPPING = YES; - -ARCHS = $(ARCHS_STANDARD_32_64_BIT) - -// Debug symbols should be on obviously -GCC_GENERATE_DEBUGGING_SYMBOLS = YES -COPY_PHASE_STRIP = NO -STRIP_STYLE = debugging -STRIP_INSTALLED_PRODUCT = NO diff --git a/libsecurity_ssl/config/lib.xcconfig b/libsecurity_ssl/config/lib.xcconfig deleted file mode 100644 index 2fe95ad5..00000000 --- a/libsecurity_ssl/config/lib.xcconfig +++ /dev/null @@ -1,30 +0,0 @@ -#include "base.xcconfig" - -PRODUCT_NAME = $(TARGET_NAME) -EXECUTABLE_PREFIX = - -CODE_SIGN_IDENTITY = - -HEADER_SEARCH_PATHS[sdk=macosx*] = $(PROJECT_DIR) $(PROJECT_DIR)/../regressions $(PROJECT_DIR)/../include $(BUILT_PRODUCTS_DIR)/derived_src $(PROJECT_DIR)/../utilities $(PROJECT_DIR)/../libsecurity_keychain/ $(PROJECT_DIR)/../libsecurity_keychain/libDER $(BUILT_PRODUCTS_DIR) $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers $(inherited) - -HEADER_SEARCH_PATHS[sdk=iphone*] = $(PROJECT_DIR) $(PROJECT_DIR)/../regressions $(PROJECT_DIR)/../utilities $(PROJECT_DIR)/../libsecurity_asn1 $(PROJECT_DIR)/../libDER $(PROJECT_DIR)/../sec $(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include $(inherited) - -SKIP_INSTALL = YES - -ALWAYS_SEARCH_USER_PATHS = YES - -GCC_C_LANGUAGE_STANDARD = gnu99 - -WARNING_CFLAGS = -Wmost -Wno-four-char-constants -Wno-unknown-pragmas $(inherited) - -GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO - -GCC_SYMBOLS_PRIVATE_EXTERN = NO -GCC_WARN_64_TO_32_BIT_CONVERSION = YES -GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES -GCC_WARN_ABOUT_RETURN_TYPE = YES -GCC_WARN_UNUSED_VARIABLE = YES - -SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator - -GCC_PREPROCESSOR_DEFINITIONS[sdk=iphonesimulator*] = INDIGO=1 $(inherited) diff --git a/libsecurity_ssl/config/tests.xcconfig b/libsecurity_ssl/config/tests.xcconfig deleted file mode 100644 index 551eb22f..00000000 --- a/libsecurity_ssl/config/tests.xcconfig +++ /dev/null @@ -1,25 +0,0 @@ -#include "base.xcconfig" - -PRODUCT_NAME = $(TARGET_NAME) -EXECUTABLE_PREFIX = - -CODE_SIGN_IDENTITY = - -GCC_C_LANGUAGE_STANDARD = gnu99 - -WARNING_CFLAGS = -Wmost -Wno-four-char-constants -Wno-unknown-pragmas $(inherited) - -GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO - -GCC_SYMBOLS_PRIVATE_EXTERN = NO -GCC_WARN_64_TO_32_BIT_CONVERSION = YES -GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES -GCC_WARN_ABOUT_RETURN_TYPE = YES -GCC_WARN_UNUSED_VARIABLE = YES - -SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator - -GCC_PREPROCESSOR_DEFINITIONS[sdk=iphonesimulator*] = INDIGO=1 $(inherited) - -INSTALL_PATH = $(SDKROOT)/usr/local/bin -INSTALL_PATH_ACTUAL[sdk=iphonesimulator*] = /usr/local/bin diff --git a/libsecurity_ssl/lib/ModuleAttacher.c b/libsecurity_ssl/lib/ModuleAttacher.c deleted file mode 100644 index 52b9f091..00000000 --- a/libsecurity_ssl/lib/ModuleAttacher.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2000-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - - -/* - * ModuleAttacher.c - * - * Process-wide class which loads and attaches to {CSP, TP, CL} at most - * once, and detaches and unloads the modules when this code is unloaded. - */ - -#include "ssl.h" -#if USE_CDSA_CRYPTO - -#include "ModuleAttacher.h" -#include "sslDebug.h" -#include "appleCdsa.h" -#include -#include -#include - -#include - -static pthread_mutex_t gAttachLock = PTHREAD_MUTEX_INITIALIZER; -static CSSM_CSP_HANDLE gCSPHandle = CSSM_INVALID_HANDLE; -static CSSM_CL_HANDLE gCLHandle = CSSM_INVALID_HANDLE; -static CSSM_TP_HANDLE gTPHandle = CSSM_INVALID_HANDLE; - -static const CSSM_API_MEMORY_FUNCS CA_memFuncs = { - stAppMalloc, - stAppFree, - stAppRealloc, - stAppCalloc, - NULL -}; -static const CSSM_VERSION cssmVers = {2, 0}; -static const CSSM_GUID testGuid = { 0xFADE, 0, 0, { 1,2,3,4,5,6,7,0 }}; - -static CSSM_HANDLE loadModule( - CSSM_SERVICE_TYPE svcType, // CSSM_SERVICE_CSP, etc. - const CSSM_GUID *guid, - const char *modName) -{ - CSSM_RETURN crtn; - CSSM_HANDLE hand; - - crtn = CSSM_ModuleLoad(guid, - CSSM_KEY_HIERARCHY_NONE, - NULL, // eventHandler - NULL); // AppNotifyCallbackCtx - if(crtn) { - #ifndef NDEBUG - sslErrorLog("loadModule: error (%lu) loading %s\n", - (unsigned long)crtn, modName); - #endif - return CSSM_INVALID_HANDLE; - } - crtn = CSSM_ModuleAttach (guid, - &cssmVers, - &CA_memFuncs, // memFuncs - 0, // SubserviceID - svcType, // SubserviceFlags - 0, // AttachFlags - CSSM_KEY_HIERARCHY_NONE, - NULL, // FunctionTable - 0, // NumFuncTable - NULL, // reserved - &hand); - if(crtn) { - #ifndef NDEBUG - sslErrorLog("loadModule: error (%lu) attaching to %s\n", - (unsigned long)crtn, modName); - #endif - return CSSM_INVALID_HANDLE; - } - return hand; -} - - -static CSSM_RETURN doAttachToModules(void) -{ - CSSM_RETURN crtn; - CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE; - CSSM_HANDLE cspHandle, clHandle, tpHandle; - - /* Check if we got the lock after some other thread did the - initialization. */ - if (gCSPHandle) - return CSSM_OK; - - crtn = CSSM_Init (&cssmVers, - CSSM_PRIVILEGE_SCOPE_NONE, - &testGuid, - CSSM_KEY_HIERARCHY_NONE, - &pvcPolicy, - NULL /* reserved */); - if(crtn != CSSM_OK) { - #ifndef NDEBUG - sslErrorLog("CSSM_Init returned %lu", (unsigned long)crtn); - #endif - return crtn; - } - - cspHandle = loadModule(CSSM_SERVICE_CSP, &gGuidAppleCSP, "AppleCSP"); - if (cspHandle == CSSM_INVALID_HANDLE) - return CSSMERR_CSSM_ADDIN_LOAD_FAILED; - clHandle = loadModule(CSSM_SERVICE_CL, &gGuidAppleX509CL, "AppleCL"); - if (clHandle == CSSM_INVALID_HANDLE) - return CSSMERR_CSSM_ADDIN_LOAD_FAILED; - tpHandle = loadModule(CSSM_SERVICE_TP, &gGuidAppleX509TP, "AppleTP"); - if (tpHandle == CSSM_INVALID_HANDLE) - return CSSMERR_CSSM_ADDIN_LOAD_FAILED; - - gCSPHandle = cspHandle; - gCLHandle = clHandle; - gTPHandle = tpHandle; - - return CSSM_OK; -} - -/* Public C function to load and attach to all three modules. */ -CSSM_RETURN attachToModules( - CSSM_CSP_HANDLE *cspHand, - CSSM_CL_HANDLE *clHand, - CSSM_TP_HANDLE *tpHand) -{ - CSSM_RETURN result; - if (gCSPHandle && gCLHandle && gTPHandle) - result = CSSM_OK; - else - { - pthread_mutex_lock(&gAttachLock); - result = doAttachToModules(); - pthread_mutex_unlock(&gAttachLock); - } - - *cspHand = gCSPHandle; - *clHand = gCLHandle; - *tpHand = gTPHandle; - - return result; -} - -#endif /* USE_CDSA_CRYPTO */ - diff --git a/libsecurity_ssl/lib/SSLRecordInternal.c b/libsecurity_ssl/lib/SSLRecordInternal.c deleted file mode 100644 index d7de1fcb..00000000 --- a/libsecurity_ssl/lib/SSLRecordInternal.c +++ /dev/null @@ -1,706 +0,0 @@ -// -// SSLRecordInternal.c -// Security -// -// Created by Fabrice Gautier on 10/25/11. -// Copyright (c) 2011 Apple, Inc. All rights reserved. -// - -/* THIS FILE CONTAINS KERNEL CODE */ - -#include "sslBuildFlags.h" -#include "SSLRecordInternal.h" -#include "sslDebug.h" -#include "cipherSpecs.h" -#include "symCipher.h" -#include "sslUtils.h" -#include "tls_record.h" - -#include -#include - -#include - -#define DEFAULT_BUFFER_SIZE 4096 - - -/* - * Redirect SSLBuffer-based I/O call to user-supplied I/O. - */ -static -int sslIoRead(SSLBuffer buf, - size_t *actualLength, - struct SSLRecordInternalContext *ctx) -{ - size_t dataLength = buf.length; - int ortn; - - *actualLength = 0; - ortn = (ctx->read)(ctx->ioRef, - buf.data, - &dataLength); - *actualLength = dataLength; - return ortn; -} - -static -int sslIoWrite(SSLBuffer buf, - size_t *actualLength, - struct SSLRecordInternalContext *ctx) -{ - size_t dataLength = buf.length; - int ortn; - - *actualLength = 0; - ortn = (ctx->write)(ctx->ioRef, - buf.data, - &dataLength); - *actualLength = dataLength; - return ortn; -} - - -static int -SSLDisposeCipherSuite(CipherContext *cipher, struct SSLRecordInternalContext *ctx) -{ int err; - - /* symmetric encryption context */ - if(cipher->symCipher) { - if ((err = cipher->symCipher->finish(cipher->cipherCtx)) != 0) { - return err; - } - } - - /* per-record hash/hmac context */ - ctx->sslTslCalls->freeMac(cipher); - - return 0; -} - - - -/* common for sslv3 and tlsv1, except for the computeMac callout */ -int SSLVerifyMac(uint8_t type, - SSLBuffer *data, - uint8_t *compareMAC, - struct SSLRecordInternalContext *ctx) -{ - int err; - uint8_t macData[SSL_MAX_DIGEST_LEN]; - SSLBuffer secret, mac; - - secret.data = ctx->readCipher.macSecret; - secret.length = ctx->readCipher.macRef->hash->digestSize; - mac.data = macData; - mac.length = ctx->readCipher.macRef->hash->digestSize; - - check(ctx->sslTslCalls != NULL); - if ((err = ctx->sslTslCalls->computeMac(type, - *data, - mac, - &ctx->readCipher, - ctx->readCipher.sequenceNum, - ctx)) != 0) - return err; - - if ((memcmp(mac.data, compareMAC, mac.length)) != 0) { - sslErrorLog("SSLVerifyMac: Mac verify failure\n"); - return errSSLRecordProtocol; - } - return 0; -} - -#include "cipherSpecs.h" -#include "symCipher.h" - -static const HashHmacReference *sslCipherSuiteGetHashHmacReference(uint16_t selectedCipher) -{ - HMAC_Algs alg = sslCipherSuiteGetMacAlgorithm(selectedCipher); - - switch (alg) { - case HA_Null: - return &HashHmacNull; - case HA_MD5: - return &HashHmacMD5; - case HA_SHA1: - return &HashHmacSHA1; - case HA_SHA256: - return &HashHmacSHA256; - case HA_SHA384: - return &HashHmacSHA384; - default: - sslErrorLog("Invalid hashAlgorithm %d", alg); - check(0); - return &HashHmacNull; - } -} - -static const SSLSymmetricCipher *sslCipherSuiteGetSymmetricCipher(uint16_t selectedCipher) -{ - - SSL_CipherAlgorithm alg = sslCipherSuiteGetSymmetricCipherAlgorithm(selectedCipher); - switch(alg) { - case SSL_CipherAlgorithmNull: - return &SSLCipherNull; -#if ENABLE_RC2 - case SSL_CipherAlgorithmRC2_128: - return &SSLCipherRC2_128; -#endif -#if ENABLE_RC4 - case SSL_CipherAlgorithmRC4_128: - return &SSLCipherRC4_128; -#endif -#if ENABLE_DES - case SSL_CipherAlgorithmDES_CBC: - return &SSLCipherDES_CBC; -#endif - case SSL_CipherAlgorithm3DES_CBC: - return &SSLCipher3DES_CBC; - case SSL_CipherAlgorithmAES_128_CBC: - return &SSLCipherAES_128_CBC; - case SSL_CipherAlgorithmAES_256_CBC: - return &SSLCipherAES_256_CBC; -#if ENABLE_AES_GCM - case SSL_CipherAlgorithmAES_128_GCM: - return &SSLCipherAES_128_GCM; - case SSL_CipherAlgorithmAES_256_GCM: - return &SSLCipherAES_256_GCM; -#endif - default: - check(0); - return &SSLCipherNull; - } -} - -static void InitCipherSpec(struct SSLRecordInternalContext *ctx, uint16_t selectedCipher) -{ - SSLRecordCipherSpec *dst = &ctx->selectedCipherSpec; - - ctx->selectedCipher = selectedCipher; - dst->cipher = sslCipherSuiteGetSymmetricCipher(selectedCipher); - dst->macAlgorithm = sslCipherSuiteGetHashHmacReference(selectedCipher); -}; - -/* Entry points to Record Layer */ - -static int SSLRecordReadInternal(SSLRecordContextRef ref, SSLRecord *rec) -{ int err; - size_t len, contentLen; - uint8_t *charPtr; - SSLBuffer readData, cipherFragment; - size_t head=5; - int skipit=0; - struct SSLRecordInternalContext *ctx = ref; - - if(ctx->isDTLS) - head+=8; - - if (!ctx->partialReadBuffer.data || ctx->partialReadBuffer.length < head) - { if (ctx->partialReadBuffer.data) - if ((err = SSLFreeBuffer(&ctx->partialReadBuffer)) != 0) - { - return err; - } - if ((err = SSLAllocBuffer(&ctx->partialReadBuffer, - DEFAULT_BUFFER_SIZE)) != 0) - { - return err; - } - } - - if (ctx->negProtocolVersion == SSL_Version_Undetermined) { - if (ctx->amountRead < 1) - { readData.length = 1 - ctx->amountRead; - readData.data = ctx->partialReadBuffer.data + ctx->amountRead; - len = readData.length; - err = sslIoRead(readData, &len, ctx); - if(err != 0) - { if (err == errSSLRecordWouldBlock) { - ctx->amountRead += len; - return err; - } - else { - /* abort */ - err = errSSLRecordClosedAbort; -#if 0 // TODO: revisit this in the transport layer - if((ctx->protocolSide == kSSLClientSide) && - (ctx->amountRead == 0) && - (len == 0)) { - /* - * Detect "server refused to even try to negotiate" - * error, when the server drops the connection before - * sending a single byte. - */ - switch(ctx->state) { - case SSL_HdskStateServerHello: - sslHdskStateDebug("Server dropped initial connection\n"); - err = errSSLConnectionRefused; - break; - default: - break; - } - } -#endif - return err; - } - } - ctx->amountRead += len; - } - } - - if (ctx->amountRead < head) - { readData.length = head - ctx->amountRead; - readData.data = ctx->partialReadBuffer.data + ctx->amountRead; - len = readData.length; - err = sslIoRead(readData, &len, ctx); - if(err != 0) - { - switch(err) { - case errSSLRecordWouldBlock: - ctx->amountRead += len; - break; -#if SSL_ALLOW_UNNOTICED_DISCONNECT - case errSSLClosedGraceful: - /* legal if we're on record boundary and we've gotten past - * the handshake */ - if((ctx->amountRead == 0) && /* nothing pending */ - (len == 0) && /* nothing new */ - (ctx->state == SSL_HdskStateClientReady)) { /* handshake done */ - /* - * This means that the server has disconnected without - * sending a closure alert notice. This is technically - * illegal per the SSL3 spec, but about half of the - * servers out there do it, so we report it as a separate - * error which most clients - including (currently) - * URLAccess - ignore by treating it the same as - * a errSSLClosedGraceful error. Paranoid - * clients can detect it and handle it however they - * want to. - */ - SSLChangeHdskState(ctx, SSL_HdskStateNoNotifyClose); - err = errSSLClosedNoNotify; - break; - } - else { - /* illegal disconnect */ - err = errSSLClosedAbort; - /* and drop thru to default: fatal alert */ - } -#endif /* SSL_ALLOW_UNNOTICED_DISCONNECT */ - default: - break; - } - return err; - } - ctx->amountRead += len; - } - - check(ctx->amountRead >= head); - - charPtr = ctx->partialReadBuffer.data; - rec->contentType = *charPtr++; - if (rec->contentType < SSL_RecordTypeV3_Smallest || - rec->contentType > SSL_RecordTypeV3_Largest) - return errSSLRecordProtocol; - - rec->protocolVersion = (SSLProtocolVersion)SSLDecodeInt(charPtr, 2); - charPtr += 2; - - if(ctx->isDTLS) - { - sslUint64 seqNum; - SSLDecodeUInt64(charPtr, 8, &seqNum); - charPtr += 8; - sslLogRecordIo("Read DTLS Record %016llx (seq is: %016llx)", - seqNum, ctx->readCipher.sequenceNum); - - /* if the epoch of the record is different of current read cipher, just drop it */ - if((seqNum>>48)!=(ctx->readCipher.sequenceNum>>48)) { - skipit=1; - } else { - ctx->readCipher.sequenceNum=seqNum; - } - } - - contentLen = SSLDecodeInt(charPtr, 2); - charPtr += 2; - if (contentLen > (16384 + 2048)) /* Maximum legal length of an - * SSLCipherText payload */ - { - return errSSLRecordRecordOverflow; - } - - if (ctx->partialReadBuffer.length < head + contentLen) - { if ((err = SSLReallocBuffer(&ctx->partialReadBuffer, head + contentLen)) != 0) - { - return err; - } - } - - if (ctx->amountRead < head + contentLen) - { readData.length = head + contentLen - ctx->amountRead; - readData.data = ctx->partialReadBuffer.data + ctx->amountRead; - len = readData.length; - err = sslIoRead(readData, &len, ctx); - if(err != 0) - { if (err == errSSLRecordWouldBlock) - ctx->amountRead += len; - return err; - } - ctx->amountRead += len; - } - - check(ctx->amountRead >= head + contentLen); - - cipherFragment.data = ctx->partialReadBuffer.data + head; - cipherFragment.length = contentLen; - - ctx->amountRead = 0; /* We've used all the data in the cache */ - - /* We dont decrypt if we were told to skip this record */ - if(skipit) { - return errSSLRecordUnexpectedRecord; - } - /* - * Decrypt the payload & check the MAC, modifying the length of the - * buffer to indicate the amount of plaintext data after adjusting - * for the block size and removing the MAC */ - check(ctx->sslTslCalls != NULL); - if ((err = ctx->sslTslCalls->decryptRecord(rec->contentType, - &cipherFragment, ctx)) != 0) - return err; - - /* - * We appear to have sucessfully received a record; increment the - * sequence number - */ - IncrementUInt64(&ctx->readCipher.sequenceNum); - - /* Allocate a buffer to return the plaintext in and return it */ - if ((err = SSLAllocBuffer(&rec->contents, cipherFragment.length)) != 0) - { - return err; - } - memcpy(rec->contents.data, cipherFragment.data, cipherFragment.length); - - - return 0; -} - -static int SSLRecordWriteInternal(SSLRecordContextRef ref, SSLRecord rec) -{ - int err; - struct SSLRecordInternalContext *ctx = ref; - - err=ctx->sslTslCalls->writeRecord(rec, ctx); - - check_noerr(err); - - return err; -} - -/* Record Layer Entry Points */ - -static int -SSLRollbackInternalRecordLayerWriteCipher(SSLRecordContextRef ref) -{ - int err; - struct SSLRecordInternalContext *ctx = ref; - - if ((err = SSLDisposeCipherSuite(&ctx->writePending, ctx)) != 0) - return err; - - ctx->writePending = ctx->writeCipher; - ctx->writeCipher = ctx->prevCipher; - - /* Zero out old data */ - memset(&ctx->prevCipher, 0, sizeof(CipherContext)); - - return 0; -} - -static int -SSLAdvanceInternalRecordLayerWriteCipher(SSLRecordContextRef ref) -{ - int err; - struct SSLRecordInternalContext *ctx = ref; - - if ((err = SSLDisposeCipherSuite(&ctx->prevCipher, ctx)) != 0) - return err; - - ctx->prevCipher = ctx->writeCipher; - ctx->writeCipher = ctx->writePending; - - /* Zero out old data */ - memset(&ctx->writePending, 0, sizeof(CipherContext)); - - return 0; -} - -static int -SSLAdvanceInternalRecordLayerReadCipher(SSLRecordContextRef ref) -{ - struct SSLRecordInternalContext *ctx = ref; - int err; - - if ((err = SSLDisposeCipherSuite(&ctx->readCipher, ctx)) != 0) - return err; - - ctx->readCipher = ctx->readPending; - memset(&ctx->readPending, 0, sizeof(CipherContext)); /* Zero out old data */ - - return 0; -} - -static int -SSLInitInternalRecordLayerPendingCiphers(SSLRecordContextRef ref, uint16_t selectedCipher, bool isServer, SSLBuffer key) -{ int err; - uint8_t *keyDataProgress, *keyPtr, *ivPtr; - CipherContext *serverPending, *clientPending; - - struct SSLRecordInternalContext *ctx = ref; - - InitCipherSpec(ctx, selectedCipher); - - ctx->readPending.macRef = ctx->selectedCipherSpec.macAlgorithm; - ctx->writePending.macRef = ctx->selectedCipherSpec.macAlgorithm; - ctx->readPending.symCipher = ctx->selectedCipherSpec.cipher; - ctx->writePending.symCipher = ctx->selectedCipherSpec.cipher; - /* This need to be reinitialized because the whole thing is zeroed sometimes */ - ctx->readPending.encrypting = 0; - ctx->writePending.encrypting = 1; - - if(ctx->negProtocolVersion == DTLS_Version_1_0) - { - ctx->readPending.sequenceNum = (ctx->readPending.sequenceNum & (0xffffULL<<48)) + (1ULL<<48); - ctx->writePending.sequenceNum = (ctx->writePending.sequenceNum & (0xffffULL<<48)) + (1ULL<<48); - } else { - ctx->writePending.sequenceNum = 0; - ctx->readPending.sequenceNum = 0; - } - - if (isServer) - { serverPending = &ctx->writePending; - clientPending = &ctx->readPending; - } - else - { serverPending = &ctx->readPending; - clientPending = &ctx->writePending; - } - - /* Check the size of the 'key' buffer - */ - if(key.length != ctx->selectedCipherSpec.macAlgorithm->hash->digestSize*2 - + ctx->selectedCipherSpec.cipher->params->keySize*2 - + ctx->selectedCipherSpec.cipher->params->ivSize*2) - { - return errSSLRecordInternal; - } - - keyDataProgress = key.data; - memcpy(clientPending->macSecret, keyDataProgress, - ctx->selectedCipherSpec.macAlgorithm->hash->digestSize); - keyDataProgress += ctx->selectedCipherSpec.macAlgorithm->hash->digestSize; - memcpy(serverPending->macSecret, keyDataProgress, - ctx->selectedCipherSpec.macAlgorithm->hash->digestSize); - keyDataProgress += ctx->selectedCipherSpec.macAlgorithm->hash->digestSize; - - if (ctx->selectedCipherSpec.cipher->params->cipherType == aeadCipherType) - goto skipInit; - - /* init the reusable-per-record MAC contexts */ - err = ctx->sslTslCalls->initMac(clientPending); - if(err) { - goto fail; - } - err = ctx->sslTslCalls->initMac(serverPending); - if(err) { - goto fail; - } - - keyPtr = keyDataProgress; - keyDataProgress += ctx->selectedCipherSpec.cipher->params->keySize; - /* Skip server write key to get to IV */ - ivPtr = keyDataProgress + ctx->selectedCipherSpec.cipher->params->keySize; - if ((err = ctx->selectedCipherSpec.cipher->c.cipher.initialize(clientPending->symCipher->params, clientPending->encrypting, keyPtr, ivPtr, - &clientPending->cipherCtx)) != 0) - goto fail; - keyPtr = keyDataProgress; - keyDataProgress += ctx->selectedCipherSpec.cipher->params->keySize; - /* Skip client write IV to get to server write IV */ - ivPtr = keyDataProgress + ctx->selectedCipherSpec.cipher->params->ivSize; - if ((err = ctx->selectedCipherSpec.cipher->c.cipher.initialize(serverPending->symCipher->params, serverPending->encrypting, keyPtr, ivPtr, - &serverPending->cipherCtx)) != 0) - goto fail; - -skipInit: - /* Ciphers are ready for use */ - ctx->writePending.ready = 1; - ctx->readPending.ready = 1; - - /* Ciphers get swapped by sending or receiving a change cipher spec message */ - err = 0; - -fail: - return err; -} - -static int -SSLSetInternalRecordLayerProtocolVersion(SSLRecordContextRef ref, SSLProtocolVersion negVersion) -{ - struct SSLRecordInternalContext *ctx = ref; - - switch(negVersion) { - case SSL_Version_3_0: - ctx->sslTslCalls = &Ssl3RecordCallouts; - break; - case TLS_Version_1_0: - case TLS_Version_1_1: - case DTLS_Version_1_0: - case TLS_Version_1_2: - ctx->sslTslCalls = &Tls1RecordCallouts; - break; - case SSL_Version_2_0: - case SSL_Version_Undetermined: - default: - return errSSLRecordNegotiation; - } - ctx->negProtocolVersion = negVersion; - - return 0; -} - -static int -SSLRecordFreeInternal(SSLRecordContextRef ref, SSLRecord rec) -{ - return SSLFreeBuffer(&rec.contents); -} - -static int -SSLRecordServiceWriteQueueInternal(SSLRecordContextRef ref) -{ - int err = 0, werr = 0; - size_t written = 0; - SSLBuffer buf; - WaitingRecord *rec; - struct SSLRecordInternalContext *ctx= ref; - - while (!werr && ((rec = ctx->recordWriteQueue) != 0)) - { buf.data = rec->data + rec->sent; - buf.length = rec->length - rec->sent; - werr = sslIoWrite(buf, &written, ctx); - rec->sent += written; - if (rec->sent >= rec->length) - { - check(rec->sent == rec->length); - check(err == 0); - ctx->recordWriteQueue = rec->next; - sslFree(rec); - } - if (err) { - check_noerr(err); - return err; - } - } - - return werr; -} - -/***** Internal Record Layer APIs *****/ - -SSLRecordContextRef -SSLCreateInternalRecordLayer(bool dtls) -{ - struct SSLRecordInternalContext *ctx; - - ctx = sslMalloc(sizeof(struct SSLRecordInternalContext)); - if(ctx==NULL) - return NULL; - - memset(ctx, 0, sizeof(struct SSLRecordInternalContext)); - - ctx->negProtocolVersion = SSL_Version_Undetermined; - - ctx->sslTslCalls = &Ssl3RecordCallouts; - ctx->recordWriteQueue = NULL; - - InitCipherSpec(ctx, TLS_NULL_WITH_NULL_NULL); - - ctx->writeCipher.macRef = ctx->selectedCipherSpec.macAlgorithm; - ctx->readCipher.macRef = ctx->selectedCipherSpec.macAlgorithm; - ctx->readCipher.symCipher = ctx->selectedCipherSpec.cipher; - ctx->writeCipher.symCipher = ctx->selectedCipherSpec.cipher; - ctx->readCipher.encrypting = 0; - ctx->writeCipher.encrypting = 1; - - ctx->isDTLS = dtls; - - return ctx; - -} - -int -SSLSetInternalRecordLayerIOFuncs( - SSLRecordContextRef ref, - SSLIOReadFunc readFunc, - SSLIOWriteFunc writeFunc) -{ - struct SSLRecordInternalContext *ctx = ref; - - ctx->read = readFunc; - ctx->write = writeFunc; - - return 0; -} - -int -SSLSetInternalRecordLayerConnection( - SSLRecordContextRef ref, - SSLIOConnectionRef ioRef) -{ - struct SSLRecordInternalContext *ctx = ref; - - ctx->ioRef = ioRef; - - return 0; -} - -void -SSLDestroyInternalRecordLayer(SSLRecordContextRef ref) -{ - struct SSLRecordInternalContext *ctx = ref; - WaitingRecord *waitRecord, *next; - - /* RecordContext cleanup : */ - SSLFreeBuffer(&ctx->partialReadBuffer); - waitRecord = ctx->recordWriteQueue; - while (waitRecord) - { next = waitRecord->next; - sslFree(waitRecord); - waitRecord = next; - } - - - /* Cleanup cipher structs */ - SSLDisposeCipherSuite(&ctx->readCipher, ctx); - SSLDisposeCipherSuite(&ctx->writeCipher, ctx); - SSLDisposeCipherSuite(&ctx->readPending, ctx); - SSLDisposeCipherSuite(&ctx->writePending, ctx); - SSLDisposeCipherSuite(&ctx->prevCipher, ctx); - - sslFree(ctx); - -} - -struct SSLRecordFuncs SSLRecordLayerInternal = -{ - .read = SSLRecordReadInternal, - .write = SSLRecordWriteInternal, - .initPendingCiphers = SSLInitInternalRecordLayerPendingCiphers, - .advanceWriteCipher = SSLAdvanceInternalRecordLayerWriteCipher, - .advanceReadCipher = SSLAdvanceInternalRecordLayerReadCipher, - .rollbackWriteCipher = SSLRollbackInternalRecordLayerWriteCipher, - .setProtocolVersion = SSLSetInternalRecordLayerProtocolVersion, - .free = SSLRecordFreeInternal, - .serviceWriteQueue = SSLRecordServiceWriteQueueInternal, -}; - diff --git a/libsecurity_ssl/lib/SSLRecordInternal.h b/libsecurity_ssl/lib/SSLRecordInternal.h deleted file mode 100644 index 4e9082c5..00000000 --- a/libsecurity_ssl/lib/SSLRecordInternal.h +++ /dev/null @@ -1,57 +0,0 @@ -// -// SSLRecordInternal.h -// Security -// -// Created by Fabrice Gautier on 10/25/11. -// Copyright (c) 2011 Apple, Inc. All rights reserved. -// - - -/* This header should be kernel compatible */ - -#ifndef _SSLRECORDINTERNAL_H_ -#define _SSLRECORDINTERNAL_H_ 1 - -#include -#include -#include - -#include "sslTypes.h" - -typedef void * SSLIOConnectionRef; - -typedef int -(*SSLIOReadFunc) (SSLIOConnectionRef connection, - void *data, /* owned by - * caller, data - * RETURNED */ - size_t *dataLength); /* IN/OUT */ -typedef int -(*SSLIOWriteFunc) (SSLIOConnectionRef connection, - const void *data, - size_t *dataLength); /* IN/OUT */ - - -/* Record layer creation functions, called from the SSLContext layer */ - -SSLRecordContextRef -SSLCreateInternalRecordLayer(bool dtls); - -int -SSLSetInternalRecordLayerIOFuncs( - SSLRecordContextRef ctx, - SSLIOReadFunc readFunc, - SSLIOWriteFunc writeFunc); - -int -SSLSetInternalRecordLayerConnection( - SSLRecordContextRef ctx, - SSLIOConnectionRef ioRef); - -void -SSLDestroyInternalRecordLayer(SSLRecordContextRef ctx); - - -extern struct SSLRecordFuncs SSLRecordLayerInternal; - -#endif diff --git a/libsecurity_ssl/lib/appleCdsa.c b/libsecurity_ssl/lib/appleCdsa.c deleted file mode 100644 index fb5a1b3b..00000000 --- a/libsecurity_ssl/lib/appleCdsa.c +++ /dev/null @@ -1,2147 +0,0 @@ -/* - * Copyright (c) 2000-2001,2005-2008,2010-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * 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@ - */ - -/* - * appleCdsa.c - CDSA based implementation of sslCrypto.h interfaces. - */ - -#include "ssl.h" -#if USE_CDSA_CRYPTO - -#include "appleCdsa.h" -#include "sslCrypto.h" - -#include "CipherSuite.h" -#include "sslContext.h" -#include "sslMemory.h" -#include "sslUtils.h" -#include "sslDebug.h" -#include "sslBER.h" -#include "ModuleAttacher.h" - -#ifndef _SSL_KEYCHAIN_H_ -#include "sslKeychain.h" -#endif - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -/* X.509 includes, from cssmapi */ -#include /* x.509 function and type defs */ -#include -#include - -// MARK: - -// MARK: Utilities - -/* - * Set up a Raw symmetric key with specified algorithm and key bits. - */ -OSStatus sslSetUpSymmKey( - CSSM_KEY_PTR symKey, - CSSM_ALGORITHMS alg, - CSSM_KEYUSE keyUse, // CSSM_KEYUSE_ENCRYPT, etc. - CSSM_BOOL copyKey, // true: copy keyData false: set by reference - uint8 *keyData, - size_t keyDataLen) // in bytes -{ - OSStatus serr; - CSSM_KEYHEADER *hdr; - - memset(symKey, 0, sizeof(CSSM_KEY)); - if(copyKey) { - serr = stSetUpCssmData(&symKey->KeyData, keyDataLen); - if(serr) { - return serr; - } - memmove(symKey->KeyData.Data, keyData, keyDataLen); - } - else { - symKey->KeyData.Data = keyData; - symKey->KeyData.Length = keyDataLen; - } - - /* set up the header */ - hdr = &symKey->KeyHeader; - hdr->BlobType = CSSM_KEYBLOB_RAW; - hdr->Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; - hdr->AlgorithmId = alg; - hdr->KeyClass = CSSM_KEYCLASS_SESSION_KEY; - hdr->LogicalKeySizeInBits = keyDataLen * 8; - hdr->KeyAttr = CSSM_KEYATTR_MODIFIABLE | CSSM_KEYATTR_EXTRACTABLE; - hdr->KeyUsage = keyUse; - hdr->WrapAlgorithmId = CSSM_ALGID_NONE; - return errSecSuccess; -} - -/* - * Free a CSSM_KEY - its CSP resources, KCItemRef, and the key itself. - */ -OSStatus sslFreeKey( - CSSM_CSP_HANDLE cspHand, - CSSM_KEY_PTR *key, /* so we can null it out */ - #if ST_KC_KEYS_NEED_REF - SecKeychainRef *kcItem) - #else - void *kcItem) - #endif -{ - assert(key != NULL); - - if(*key != NULL) { - if(cspHand != 0) { - CSSM_FreeKey(cspHand, NULL, *key, CSSM_FALSE); - } - stAppFree(*key, NULL); // key mallocd by CL using our callback - *key = NULL; - } - #if ST_KC_KEYS_NEED_REF - if((kcItem != NULL) && (*kcItem != NULL)) { - KCReleaseItem(kcItem); /* does this NULL the referent? */ - *kcItem = NULL; - } - #endif - return errSecSuccess; -} - -/* - * Standard app-level memory functions required by CDSA. - */ -void * stAppMalloc (size_t size, void *allocRef) { - return( malloc(size) ); -} -void stAppFree (void *mem_ptr, void *allocRef) { - free(mem_ptr); - return; -} -void * stAppRealloc (void *ptr, size_t size, void *allocRef) { - return( realloc( ptr, size ) ); -} -void * stAppCalloc (uint32_t num, size_t size, void *allocRef) { - return( calloc( num, size ) ); -} - -/* - * Ensure there's a connection to ctx->cspHand. If there - * already is one, fine. - * Note that as of 12/18/00, we assume we're connected to - * all modules all the time (since we do an attachToAll() in - * SSLNewContext()). - */ -OSStatus attachToCsp(SSLContext *ctx) -{ - assert(ctx != NULL); - if(ctx->cspHand != 0) { - return errSecSuccess; - } - else { - return errSSLModuleAttach; - } -} - -/* - * Connect to TP, CL; reusable. - */ -OSStatus attachToCl(SSLContext *ctx) -{ - assert(ctx != NULL); - if(ctx->clHand != 0) { - return errSecSuccess; - } - else { - return errSSLModuleAttach; - } -} - -OSStatus attachToTp(SSLContext *ctx) -{ - assert(ctx != NULL); - if(ctx->tpHand != 0) { - return errSecSuccess; - } - else { - return errSSLModuleAttach; - } -} - -/* - * Convenience function - attach to CSP, CL, TP. Reusable. - */ -OSStatus attachToAll(SSLContext *ctx) -{ - CSSM_RETURN crtn; - - assert(ctx != NULL); - crtn = attachToModules(&ctx->cspHand, &ctx->clHand, &ctx->tpHand); - if(crtn) { - return errSSLModuleAttach; - } - else { - return errSecSuccess; - } -} - -OSStatus detachFromAll(SSLContext *ctx) -{ - #if 0 - /* No more, attachments are kept on a global basis */ - assert(ctx != NULL); - if(ctx->cspHand != 0) { - CSSM_ModuleDetach(ctx->cspHand); - ctx->cspHand = 0; - } - if(ctx->tpHand != 0) { - CSSM_ModuleDetach(ctx->tpHand); - ctx->tpHand = 0; - } - if(ctx->clHand != 0) { - CSSM_ModuleDetach(ctx->clHand); - ctx->clHand = 0; - } - #endif /* 0 */ - return errSecSuccess; -} - -/* - * Add a CSSM_ATTRIBUTE_RSA_BLINDING attribute to - * specified crypto context. - */ -static CSSM_RETURN sslAddBlindingAttr( - CSSM_CC_HANDLE ccHand) -{ - CSSM_CONTEXT_ATTRIBUTE newAttr; - CSSM_RETURN crtn; - - newAttr.AttributeType = CSSM_ATTRIBUTE_RSA_BLINDING; - newAttr.AttributeLength = sizeof(uint32_t); - newAttr.Attribute.Uint32 = 1; - crtn = CSSM_UpdateContextAttributes(ccHand, 1, &newAttr); - if(crtn) { - stPrintCdsaError("CSSM_UpdateContextAttributes", crtn); - } - return crtn; -} - -/* Get CSP, key in CSSM format from a SecKeyRef */ -static OSStatus sslGetKeyParts( - SecKeyRef keyRef, - const CSSM_KEY **cssmKey, - CSSM_CSP_HANDLE *cspHand) -{ - OSStatus ortn = SecKeyGetCSSMKey(keyRef, cssmKey); - if(ortn) { - sslErrorLog("sslGetKeyParts: SecKeyGetCSSMKey err %d\n", - (int)ortn); - return ortn; - } - ortn = SecKeyGetCSPHandle(keyRef, cspHand); - if(ortn) { - sslErrorLog("sslGetKeyParts: SecKeyGetCSPHandle err %d\n", - (int)ortn); - } - return ortn; -} - -/* Return the first certificate reference from the supplied array - * whose data matches the given certificate, or NULL if none match. - */ - static SecCertificateRef sslGetMatchingCertInArray( - SecCertificateRef certRef, - CFArrayRef certArray) -{ - CSSM_DATA certData; - OSStatus ortn; - int idx, count; - - if(certRef == NULL || certArray == NULL) { - return NULL; - } - ortn = SecCertificateGetData(certRef, &certData); - if(!ortn) { - count = CFArrayGetCount(certArray); - for(idx=0; idxLength = size; - if(size == 0) { - rtn->Data = NULL; - } - else { - rtn->Data = (uint8 *)stAppMalloc(size, NULL); - } - return rtn; -} - -void stFreeCssmData( - CSSM_DATA_PTR data, - CSSM_BOOL freeStruct) -{ - if(data == NULL) { - return; - } - if(data->Data != NULL) { - stAppFree(data->Data, NULL); - data->Data = NULL; - } - data->Length = 0; - if(freeStruct) { - stAppFree(data, NULL); - } -} - -/* - * Ensure that indicated CSSM_DATA_PTR can handle 'length' bytes of data. - * Malloc the Data ptr if necessary. - */ -OSStatus stSetUpCssmData( - CSSM_DATA_PTR data, - size_t length) -{ - assert(data != NULL); - if(data->Length == 0) { - data->Data = (uint8 *)stAppMalloc(length, NULL); - if(data->Data == NULL) { - return errSecAllocate; - } - } - else if(data->Length < length) { - sslErrorLog("stSetUpCssmData: length too small\n"); - return errSecAllocate; - } - data->Length = length; - return errSecSuccess; -} - -/* All signature ops are "raw", with digest step done by us */ -static OSStatus sslKeyToSigAlg( - const CSSM_KEY *cssmKey, - CSSM_ALGORITHMS *sigAlg) /* RETURNED */ - -{ - OSStatus ortn = errSecSuccess; - switch(cssmKey->KeyHeader.AlgorithmId) { - case CSSM_ALGID_RSA: - *sigAlg = CSSM_ALGID_RSA; - break; - case CSSM_ALGID_DSA: - *sigAlg = CSSM_ALGID_DSA; - break; - case CSSM_ALGID_ECDSA: - *sigAlg = CSSM_ALGID_ECDSA; - break; - default: - ortn = errSSLBadConfiguration; - break; - } - return ortn; -} - -// MARK: - -// MARK: Public CSP Functions - -/* - * Raw RSA/DSA sign/verify. - */ -OSStatus sslRawSign( - SSLContext *ctx, - SecKeyRef privKeyRef, - const UInt8 *plainText, - size_t plainTextLen, - UInt8 *sig, // mallocd by caller; RETURNED - size_t sigLen, // available - size_t *actualBytes) // RETURNED -{ - CSSM_CC_HANDLE sigHand = 0; - CSSM_RETURN crtn; - OSStatus serr; - CSSM_DATA sigData; - CSSM_DATA ptextData; - CSSM_CSP_HANDLE cspHand; - const CSSM_KEY *privKey; - const CSSM_ACCESS_CREDENTIALS *creds; - - assert(ctx != NULL); - if((privKeyRef == NULL) || - (plainText == NULL) || - (sig == NULL) || - (actualBytes == NULL)) { - sslErrorLog("sslRsaRawSign: bad arguments\n"); - return errSSLInternal; - } - *actualBytes = 0; - - /* Get CSP, signing key in CSSM format */ - serr = sslGetKeyParts(privKeyRef, &privKey, &cspHand); - if(serr) { - return serr; - } - assert(privKey->KeyHeader.KeyClass == CSSM_KEYCLASS_PRIVATE_KEY); - - CSSM_ALGORITHMS sigAlg; - serr = sslKeyToSigAlg(privKey, &sigAlg); - if(serr) { - return serr; - } - - /* - * Get default creds - * FIXME: per 3420180, this needs to allow app-specified creds via - * an new API - */ - serr = SecKeyGetCredentials(privKeyRef, - CSSM_ACL_AUTHORIZATION_SIGN, - kSecCredentialTypeDefault, - &creds); - if(serr) { - sslErrorLog("sslRawSign: SecKeyGetCredentials err %lu\n", (unsigned long)serr); - return serr; - } - - crtn = CSSM_CSP_CreateSignatureContext(cspHand, - sigAlg, - creds, - privKey, - &sigHand); - if(crtn) { - stPrintCdsaError("CSSM_CSP_CreateSignatureContext (1)", crtn); - return errSSLCrypto; - } - - if((ctx->rsaBlindingEnable) && - (privKey->KeyHeader.AlgorithmId == CSSM_ALGID_RSA)) { - /* - * Turn on RSA blinding to defeat timing attacks - */ - crtn = sslAddBlindingAttr(sigHand); - if(crtn) { - return crtn; - } - } - - ptextData.Data = (uint8 *)plainText; - ptextData.Length = plainTextLen; - - /* caller better get this right, or the SignData will fail */ - sigData.Data = sig; - sigData.Length = sigLen; - - crtn = CSSM_SignData(sigHand, - &ptextData, - 1, - CSSM_ALGID_NONE, // digestAlg for raw sign - &sigData); - if(crtn) { - stPrintCdsaError("CSSM_SignData", crtn); - serr = errSSLCrypto; - } - else { - *actualBytes = sigData.Length; - serr = errSecSuccess; - } - if(sigHand != 0) { - CSSM_DeleteContext(sigHand); - } - return serr; -} - -OSStatus sslRawVerify( - SSLContext *ctx, - const SSLPubKey *sslPubKey, - const UInt8 *plainText, - size_t plainTextLen, - const UInt8 *sig, - size_t sigLen) -{ - CSSM_CC_HANDLE sigHand = 0; - CSSM_RETURN crtn; - OSStatus serr; - CSSM_DATA sigData; - CSSM_DATA ptextData; - const CSSM_KEY *pubKey; - CSSM_CSP_HANDLE cspHand; - - assert(ctx != NULL); - if((sslPubKey == NULL) || - (sslPubKey->key == NULL) || - (sslPubKey->csp == 0) || - (plainText == NULL) || - (sig == NULL)) { - sslErrorLog("sslRawVerify: bad arguments\n"); - return errSSLInternal; - } - - pubKey = &sslPubKey->key; - cspHand = sslPubKey->csp; - - CSSM_ALGORITHMS sigAlg; - serr = sslKeyToSigAlg(pubKey, &sigAlg); - if(serr) { - return serr; - } - crtn = CSSM_CSP_CreateSignatureContext(cspHand, - sigAlg, - NULL, // passPhrase - pubKey, - &sigHand); - if(sigHand == 0) { - stPrintCdsaError("CSSM_CSP_CreateSignatureContext (2)", crtn); - return errSSLCrypto; - } - - ptextData.Data = (uint8 *)plainText; - ptextData.Length = plainTextLen; - sigData.Data = (uint8 *)sig; - sigData.Length = sigLen; - - crtn = CSSM_VerifyData(sigHand, - &ptextData, - 1, - CSSM_ALGID_NONE, // digestAlg - &sigData); - if(crtn) { - stPrintCdsaError("CSSM_VerifyData", crtn); - serr = errSSLCrypto; - } - else { - serr = errSecSuccess; - } - if(sigHand != 0) { - CSSM_DeleteContext(sigHand); - } - return serr; -} - -/* - * Encrypt/Decrypt - */ -OSStatus sslRsaEncrypt( - SSLContext *ctx, - const CSSM_KEY *pubKey, - CSSM_CSP_HANDLE cspHand, - CSSM_PADDING padding, // CSSM_PADDING_PKCS1, CSSM_PADDING_APPLE_SSLv2 - const UInt8 *plainText, - size_t plainTextLen, - UInt8 *cipherText, // mallocd by caller; RETURNED - size_t cipherTextLen, // available - size_t *actualBytes) // RETURNED -{ - CSSM_DATA ctextData = {0, NULL}; - CSSM_DATA ptextData; - CSSM_DATA remData = {0, NULL}; - CSSM_CC_HANDLE cryptHand = 0; - OSStatus serr = errSSLInternal; - CSSM_RETURN crtn; - size_t bytesMoved = 0; - CSSM_ACCESS_CREDENTIALS creds; - - assert(ctx != NULL); - assert(actualBytes != NULL); - *actualBytes = 0; - - if((pubKey == NULL) || (cspHand == 0)) { - sslErrorLog("sslRsaEncrypt: bad pubKey/cspHand\n"); - return errSSLInternal; - } - assert(pubKey->KeyHeader.KeyClass == CSSM_KEYCLASS_PUBLIC_KEY); - - #if RSA_PUB_KEY_USAGE_HACK - ((CSSM_KEY_PTR)pubKey)->KeyHeader.KeyUsage |= CSSM_KEYUSE_ENCRYPT; - #endif - memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); - - crtn = CSSM_CSP_CreateAsymmetricContext(cspHand, - CSSM_ALGID_RSA, - &creds, - pubKey, - padding, - &cryptHand); - if(crtn) { - stPrintCdsaError("CSSM_CSP_CreateAsymmetricContext", crtn); - return errSSLCrypto; - } - ptextData.Data = (uint8 *)plainText; - ptextData.Length = plainTextLen; - - /* - * Have CSP malloc ciphertext - */ - crtn = CSSM_EncryptData(cryptHand, - &ptextData, - 1, - &ctextData, - 1, - &bytesMoved, - &remData); - if(crtn == CSSM_OK) { - /* - * ciphertext in both ctextData and remData; ensure it'll fit - * in caller's buf & copy - */ - if(bytesMoved > cipherTextLen) { - sslErrorLog("sslRsaEncrypt overflow; cipherTextLen %lu bytesMoved %lu\n", - cipherTextLen, bytesMoved); - serr = errSSLCrypto; - } - else { - size_t toMoveCtext; - size_t toMoveRem; - - *actualBytes = bytesMoved; - /* - * Snag valid data from ctextData - its length or bytesMoved, - * whichever is less - */ - if(ctextData.Length > bytesMoved) { - /* everything's in ctext */ - toMoveCtext = bytesMoved; - toMoveRem = 0; - } - else { - /* must be some in remData too */ - toMoveCtext = ctextData.Length; - toMoveRem = bytesMoved - toMoveCtext; // remainder - } - if(toMoveCtext) { - memmove(cipherText, ctextData.Data, toMoveCtext); - } - if(toMoveRem) { - memmove(cipherText + toMoveCtext, remData.Data, - toMoveRem); - } - serr = errSecSuccess; - } - } - else { - stPrintCdsaError("CSSM_EncryptData", crtn); - serr = errSSLCrypto; - } - if(cryptHand != 0) { - CSSM_DeleteContext(cryptHand); - } - - /* free data mallocd by CSP */ - stFreeCssmData(&ctextData, CSSM_FALSE); - stFreeCssmData(&remData, CSSM_FALSE); - return serr; -} - -OSStatus sslRsaDecrypt( - SSLContext *ctx, - SecKeyRef privKeyRef, - CSSM_PADDING padding, // CSSM_PADDING_PKCS1, CSSM_PADDING_APPLE_SSLv2 - const UInt8 *cipherText, - size_t cipherTextLen, - UInt8 *plainText, // mallocd by caller; RETURNED - size_t plainTextLen, // available - size_t *actualBytes) // RETURNED -{ - CSSM_DATA ptextData = {0, NULL}; - CSSM_DATA ctextData; - CSSM_DATA remData = {0, NULL}; - CSSM_CC_HANDLE cryptHand = 0; - OSStatus serr = errSSLInternal; - CSSM_RETURN crtn; - size_t bytesMoved = 0; - CSSM_CSP_HANDLE cspHand; - const CSSM_KEY *privKey; - const CSSM_ACCESS_CREDENTIALS *creds; - - assert(ctx != NULL); - assert(actualBytes != NULL); - *actualBytes = 0; - - if(privKeyRef == NULL) { - sslErrorLog("sslRsaDecrypt: bad privKey\n"); - return errSSLInternal; - } - - /* Get CSP, signing key in CSSM format */ - serr = sslGetKeyParts(privKeyRef, &privKey, &cspHand); - if(serr) { - return serr; - } - assert(privKey->KeyHeader.KeyClass == CSSM_KEYCLASS_PRIVATE_KEY); - - /* - * Get default creds - * FIXME: per 3420180, this needs to allow app-specified creds via - * an new API - */ - serr = SecKeyGetCredentials(privKeyRef, - CSSM_ACL_AUTHORIZATION_DECRYPT, - kSecCredentialTypeDefault, - &creds); - if(serr) { - sslErrorLog("sslRsaDecrypt: SecKeyGetCredentials err %lu\n", (unsigned long)serr); - return serr; - } - crtn = CSSM_CSP_CreateAsymmetricContext(cspHand, - CSSM_ALGID_RSA, - creds, - privKey, - padding, - &cryptHand); - if(crtn) { - stPrintCdsaError("CSSM_CSP_CreateAsymmetricContext", crtn); - return errSSLCrypto; - } - ctextData.Data = (uint8 *)cipherText; - ctextData.Length = cipherTextLen; - - if((ctx->rsaBlindingEnable) && - (privKey->KeyHeader.AlgorithmId == CSSM_ALGID_RSA)) { - /* - * Turn on RSA blinding to defeat timing attacks - */ - crtn = sslAddBlindingAttr(cryptHand); - if(crtn) { - return crtn; - } - } - - /* - * Have CSP malloc plaintext - */ - crtn = CSSM_DecryptData(cryptHand, - &ctextData, - 1, - &ptextData, - 1, - &bytesMoved, - &remData); - if(crtn == CSSM_OK) { - /* - * plaintext in both ptextData and remData; ensure it'll fit - * in caller's buf & copy - */ - if(bytesMoved > plainTextLen) { - sslErrorLog("sslRsaDecrypt overflow; plainTextLen %lu bytesMoved %lu\n", - plainTextLen, bytesMoved); - serr = errSSLCrypto; - } - else { - size_t toMovePtext; - size_t toMoveRem; - - *actualBytes = bytesMoved; - /* - * Snag valid data from ptextData - its length or bytesMoved, - * whichever is less - */ - if(ptextData.Length > bytesMoved) { - /* everything's in ptext */ - toMovePtext = bytesMoved; - toMoveRem = 0; - } - else { - /* must be some in remData too */ - toMovePtext = ptextData.Length; - toMoveRem = bytesMoved - toMovePtext; // remainder - } - if(toMovePtext) { - memmove(plainText, ptextData.Data, toMovePtext); - } - if(toMoveRem) { - memmove(plainText + toMovePtext, remData.Data, - toMoveRem); - } - serr = errSecSuccess; - } - } - else { - stPrintCdsaError("CSSM_DecryptData", crtn); - serr = errSSLCrypto; - } - if(cryptHand != 0) { - CSSM_DeleteContext(cryptHand); - } - - /* free data mallocd by CSP */ - stFreeCssmData(&ptextData, CSSM_FALSE); - stFreeCssmData(&remData, CSSM_FALSE); - return serr; -} - -/* - * Obtain size of key in bytes. - */ -uint32_t sslPrivKeyLengthInBytes(const SSLPrivKey *sslKey) -{ - const CSSM_KEY *cssmKey; - - assert(sslKey != NULL); - assert(sslKey->key != NULL); - err = SecKeyGetCSSMKey(sslKey->key, &cssmKey); - if(err) { - sslErrorLog("sslKeyLengthInBytes: SecKeyGetCSSMKey err %d\n", (int)err); - return 0; - } - - return (((cssmKey->KeyHeader.LogicalKeySizeInBits) + 7) / 8); -} - -/* - * Obtain size of key in bytes. - */ -uint32_t sslPubKeyLengthInBytes(const SSLPubKey *sslKey) -{ - const CSSM_KEY *cssmKey; - - assert(sslKey != NULL); - assert(sslKey->key != NULL); - - return (((sslKey->key.KeyHeader.LogicalKeySizeInBits) + 7) / 8); -} - - -/* - * Obtain maximum size of signature in bytes. A bit of a kludge; we could - * ask the CSP to do this but that would be kind of expensive. - */ -OSStatus sslGetMaxSigSize( - const CSSM_KEY *privKey, - uint32_t *maxSigSize) -{ - OSStatus ortn = errSecSuccess; - assert(privKey != NULL); - assert(privKey->KeyHeader.KeyClass == CSSM_KEYCLASS_PRIVATE_KEY); - switch(privKey->KeyHeader.AlgorithmId) { - case CSSM_ALGID_RSA: - *maxSigSize = sslPrivKeyLengthInBytes(privKey); - break; - case CSSM_ALGID_DSA: - { - /* DSA sig is DER sequence of two 160-bit integers */ - uint32_t sizeOfOneInt; - sizeOfOneInt = (160 / 8) + // the raw contents - 1 + // possible leading zero - 2; // tag + length (assume DER, not BER) - *maxSigSize = (2 * sizeOfOneInt) + 5; - break; - } - default: - ortn = errSSLBadConfiguration; - break; - } - return ortn; -} -/* - * Get raw key bits from an RSA public key. - */ -OSStatus sslGetPubKeyBits( - SSLContext *ctx, - const CSSM_KEY *pubKey, - CSSM_CSP_HANDLE cspHand, - SSLBuffer *modulus, // data mallocd and RETURNED - SSLBuffer *exponent) // data mallocd and RETURNED -{ - CSSM_KEY wrappedKey; - CSSM_BOOL didWrap = CSSM_FALSE; - const CSSM_KEYHEADER *hdr; - SSLBuffer pubKeyBlob; - OSStatus srtn; - - assert(ctx != NULL); - assert(modulus != NULL); - assert(exponent != NULL); - assert(pubKey != NULL); - - hdr = &pubKey->KeyHeader; - if(hdr->KeyClass != CSSM_KEYCLASS_PUBLIC_KEY) { - sslErrorLog("sslGetPubKeyBits: bad keyClass (%ld)\n", (long)hdr->KeyClass); - return errSSLInternal; - } - if(hdr->AlgorithmId != CSSM_ALGID_RSA) { - sslErrorLog("sslGetPubKeyBits: bad AlgorithmId (%ld)\n", (long)hdr->AlgorithmId); - return errSSLInternal; - } - - /* Note currently ALL public keys are raw, obtained from the CL... */ - assert(hdr->BlobType == CSSM_KEYBLOB_RAW); - - /* - * Handle possible reference format - I think it should be in - * blob form since it came from the DL, but conversion is - * simple. - */ - switch(hdr->BlobType) { - case CSSM_KEYBLOB_RAW: - /* easy case */ - CSSM_TO_SSLBUF(&pubKey->KeyData, &pubKeyBlob); - break; - - case CSSM_KEYBLOB_REFERENCE: - - sslErrorLog("sslGetPubKeyBits: bad BlobType (%ld)\n", - (long)hdr->BlobType); - return errSSLInternal; - - #if 0 - /* - * Convert to a blob via "NULL wrap"; no wrapping key, - * ALGID_NONE - */ - srtn = attachToCsp(ctx); - if(srtn) { - return srtn; - } - memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); - crtn = CSSM_CSP_CreateSymmetricContext(ctx->cspHand, - CSSM_ALGID_NONE, - CSSM_ALGMODE_NONE, - &creds, // creds - pubKey, - NULL, // InitVector - CSSM_PADDING_NONE, - 0, // reserved - &ccHand); - if(crtn) { - stPrintCdsaError("sslGetPubKeyBits: CreateSymmetricContext failure", crtn); - return errSSLCrypto; - } - memset(&wrappedKey, 0, sizeof(CSSM_KEY)); - crtn = CSSM_WrapKey(ccHand, - &creds, - pubKey, - NULL, // descriptiveData - &wrappedKey); - CSSM_DeleteContext(ccHand); - if(crtn) { - stPrintCdsaError("CSSM_WrapKey", crtn); - return errSSLCrypto; - } - hdr = &wrappedKey.KeyHeader; - if(hdr->BlobType != CSSM_KEYBLOB_RAW) { - sslErrorLog("sslGetPubKeyBits: bad BlobType (%ld) after WrapKey\n", - hdr->BlobType); - return errSSLCrypto; - } - didWrap = CSSM_TRUE; - CSSM_TO_SSLBUF(&wrappedKey.KeyData, &pubKeyBlob); - break; - #endif /* 0 */ - - default: - sslErrorLog("sslGetPubKeyBits: bad BlobType (%ld)\n", - (long)hdr->BlobType); - return errSSLInternal; - - } /* switch BlobType */ - - assert(hdr->BlobType == CSSM_KEYBLOB_RAW); - srtn = sslDecodeRsaBlob(&pubKeyBlob, modulus, exponent); - if(didWrap) { - CSSM_FreeKey(ctx->cspHand, NULL, &wrappedKey, CSSM_FALSE); - } - return srtn; -} - -/* - * Given raw RSA key bits, cook up a CSSM_KEY_PTR. Used in - * Server-initiated key exchange. - */ -OSStatus sslGetPubKeyFromBits( - SSLContext *ctx, - const SSLBuffer *modulus, - const SSLBuffer *exponent, - CSSM_KEY_PTR *pubKey, // mallocd and RETURNED - CSSM_CSP_HANDLE *cspHand) // RETURNED -{ - CSSM_KEY_PTR key = NULL; - OSStatus serr; - SSLBuffer blob; - CSSM_KEYHEADER_PTR hdr; - CSSM_KEY_SIZE keySize; - CSSM_RETURN crtn; - - assert((ctx != NULL) && (modulus != NULL) && (exponent != NULL)); - assert((pubKey != NULL) && (cspHand != NULL)); - - *pubKey = NULL; - *cspHand = 0; - - serr = attachToCsp(ctx); - if(serr) { - return serr; - } - serr = sslEncodeRsaBlob(modulus, exponent, &blob); - if(serr) { - return serr; - } - - /* the rest is boilerplate, cook up a good-looking public key */ - key = (CSSM_KEY_PTR)sslMalloc(sizeof(CSSM_KEY)); - if(key == NULL) { - return errSecAllocate; - } - memset(key, 0, sizeof(CSSM_KEY)); - hdr = &key->KeyHeader; - - hdr->HeaderVersion = CSSM_KEYHEADER_VERSION; - /* key_ptr->KeyHeader.CspId is unknown (remains 0) */ - hdr->BlobType = CSSM_KEYBLOB_RAW; - hdr->AlgorithmId = CSSM_ALGID_RSA; - hdr->Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1; - hdr->KeyClass = CSSM_KEYCLASS_PUBLIC_KEY; - /* comply with ASA requirements */ - hdr->KeyUsage = CSSM_KEYUSE_VERIFY; - hdr->KeyAttr = CSSM_KEYATTR_EXTRACTABLE; - /* key_ptr->KeyHeader.StartDate is unknown (remains 0) */ - /* key_ptr->KeyHeader.EndDate is unknown (remains 0) */ - hdr->WrapAlgorithmId = CSSM_ALGID_NONE; - hdr->WrapMode = CSSM_ALGMODE_NONE; - - /* blob->data was mallocd by sslEncodeRsaBlob, pass it over to - * actual key */ - SSLBUF_TO_CSSM(&blob, &key->KeyData); - - /* - * Get keySizeInBits. This also serves to validate the key blob - * we just cooked up. - */ - crtn = CSSM_QueryKeySizeInBits(ctx->cspHand, CSSM_INVALID_HANDLE, key, &keySize); - if(crtn) { - stPrintCdsaError("sslGetPubKeyFromBits: QueryKeySizeInBits\n", crtn); - serr = errSSLCrypto; - goto abort; - } - - /* success */ - hdr->LogicalKeySizeInBits = keySize.EffectiveKeySizeInBits; - *pubKey = key; - *cspHand = ctx->cspHand; - return errSecSuccess; - -abort: - /* note this frees the blob */ - sslFreeKey(ctx->cspHand, &key, NULL); - return serr; -} - -#ifdef UNUSED_FUNCTIONS -/* - * NULL-unwrap a raw key to a ref key. Caller must free the returned key. - */ -static OSStatus sslNullUnwrapKey( - CSSM_CSP_HANDLE cspHand, - CSSM_KEY_PTR rawKey, - CSSM_KEY_PTR refKey) -{ - CSSM_DATA descData = {0, 0}; - CSSM_RETURN crtn; - CSSM_CC_HANDLE ccHand; - CSSM_ACCESS_CREDENTIALS creds; - CSSM_DATA labelData = {4, (uint8 *)"none"}; - uint32 keyAttr; - OSStatus ortn = errSecSuccess; - - memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); - memset(refKey, 0, sizeof(CSSM_KEY)); - - crtn = CSSM_CSP_CreateSymmetricContext(cspHand, - CSSM_ALGID_NONE, - CSSM_ALGMODE_NONE, - &creds, - NULL, // unwrappingKey - NULL, // initVector - CSSM_PADDING_NONE, - 0, // Params - &ccHand); - if(crtn) { - stPrintCdsaError("sslNullUnwrapKey: CSSM_CSP_CreateSymmetricContext\n", crtn); - return errSSLCrypto; - } - - keyAttr = rawKey->KeyHeader.KeyAttr; - keyAttr &= ~(CSSM_KEYATTR_ALWAYS_SENSITIVE | CSSM_KEYATTR_NEVER_EXTRACTABLE | - CSSM_KEYATTR_MODIFIABLE); - keyAttr |= CSSM_KEYATTR_RETURN_REF; - if(rawKey->KeyHeader.KeyClass == CSSM_KEYCLASS_PUBLIC_KEY) { - /* CSP policy */ - keyAttr |= CSSM_KEYATTR_EXTRACTABLE; - } - crtn = CSSM_UnwrapKey(ccHand, - NULL, // PublicKey - rawKey, - rawKey->KeyHeader.KeyUsage, - keyAttr, - &labelData, - NULL, // CredAndAclEntry - refKey, - &descData); // required - if(crtn != CSSM_OK) { - stPrintCdsaError("sslNullUnwrapKey: CSSM_UnwrapKey\n", crtn); - ortn = errSSLCrypto; - } - if(CSSM_DeleteContext(ccHand)) { - printf("CSSM_DeleteContext failure\n"); - } - return crtn; -} -#endif - -/* - * NULL-wrap a ref key to a raw key. Caller must free the returned key. - */ -static OSStatus sslNullWrapKey( - CSSM_CSP_HANDLE cspHand, - CSSM_KEY_PTR refKey, - CSSM_KEY_PTR rawKey) -{ - CSSM_DATA descData = {0, 0}; - CSSM_RETURN crtn; - CSSM_CC_HANDLE ccHand; - CSSM_ACCESS_CREDENTIALS creds; - uint32 keyAttr; - OSStatus ortn = errSecSuccess; - - memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); - memset(rawKey, 0, sizeof(CSSM_KEY)); - - crtn = CSSM_CSP_CreateSymmetricContext(cspHand, - CSSM_ALGID_NONE, - CSSM_ALGMODE_NONE, - &creds, - NULL, // unwrappingKey - NULL, // initVector - CSSM_PADDING_NONE, - 0, // Params - &ccHand); - if(crtn) { - stPrintCdsaError("sslNullWrapKey: CSSM_CSP_CreateSymmetricContext\n", crtn); - return errSSLCrypto; - } - - keyAttr = rawKey->KeyHeader.KeyAttr; - keyAttr &= ~(CSSM_KEYATTR_ALWAYS_SENSITIVE | CSSM_KEYATTR_NEVER_EXTRACTABLE | - CSSM_KEYATTR_MODIFIABLE); - keyAttr |= CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; - crtn = CSSM_WrapKey(ccHand, - &creds, - refKey, - &descData, - rawKey); - if(crtn != CSSM_OK) { - stPrintCdsaError("sslNullWrapKey: CSSM_WrapKey\n", crtn); - ortn = errSSLCrypto; - } - if(CSSM_DeleteContext(ccHand)) { - printf("CSSM_DeleteContext failure\n"); - } - return crtn; -} - -// MARK: - -// MARK: Public Certificate Functions - -/* - * Given a DER-encoded cert, obtain its public key as a CSSM_KEY_PTR. - * Caller must CSSM_FreeKey and free the CSSM_KEY_PTR itself. - * - * For now, the returned cspHand is a copy of ctx->cspHand, so it - * doesn't have to be detached later - this may change. - * - * Update: since CSSM_CL_CertGetKeyInfo() doesn't provide a means for - * us to tell the CL what CSP to use, we really have no way of knowing - * what is going on here...we return the process-wide (bare) cspHand, - * which is currently always able to deal with this raw public key. - */ -OSStatus sslPubKeyFromCert( - SSLContext *ctx, - const SSLBuffer *derCert, - SSLPubKey *pubKey) // RETURNED -{ - OSStatus serr; - CSSM_DATA certData; - CSSM_RETURN crtn; - - assert(ctx != NULL); - assert(pubKey != NULL); - - pubKey->key = NULL; - pubKey->cspHand = 0; - - serr = attachToCl(ctx); - if(serr) { - return serr; - } - serr = attachToCsp(ctx); - if(serr) { - return serr; - } - SSLBUF_TO_CSSM(derCert, &certData); - crtn = CSSM_CL_CertGetKeyInfo(ctx->clHand, &certData, &pubKey->key); - if(crtn) { - return errSSLBadCert; - } - else { - pubKey->cspHand = ctx->cspHand; - return errSecSuccess; - } -} - -/* - * Release each element in a CFArray. - */ -static void sslReleaseArray( - CFArrayRef a) -{ - CFIndex num = CFArrayGetCount(a); - CFIndex dex; - for(dex=0; dexpeerSecTrust. Otherwise - * we're just validating our own certs; no host name checking and - * peerSecTrust is transient. - */ - OSStatus sslVerifyCertChain( - SSLContext *ctx, - const SSLCertificate *certChain, - bool arePeerCerts) -{ - uint32_t numCerts; - int i; - OSStatus serr; - SSLCertificate *c = (SSLCertificate *)certChain; - CSSM_RETURN crtn; - CSSM_APPLE_TP_SSL_OPTIONS sslOpts; - CSSM_APPLE_TP_ACTION_DATA tpActionData; - SecPolicyRef policy = NULL; - SecPolicySearchRef policySearch = NULL; - CFDataRef actionData = NULL; - CSSM_DATA sslOptsData; - CFMutableArrayRef anchors = NULL; - SecCertificateRef cert; // only lives in CFArrayRefs - SecTrustResultType secTrustResult; - CFMutableArrayRef kcList = NULL; - SecTrustRef theTrust = NULL; - - if(ctx->peerSecTrust && arePeerCerts) { - /* renegotiate - start with a new SecTrustRef */ - CFRelease(ctx->peerSecTrust); - ctx->peerSecTrust = NULL; - } - - numCerts = SSLGetCertificateChainLength(certChain); - if(numCerts == 0) { - /* nope */ - return errSSLBadCert; - } - - /* - * SSLCertificate chain --> CFArrayRef of SecCertificateRefs. - * TP Cert group has root at the end, opposite of - * SSLCertificate chain. - */ - CFMutableArrayRef certGroup = CFArrayCreateMutable(NULL, numCerts, - &kCFTypeArrayCallBacks); - if(certGroup == NULL) { - return errSecAllocate; - } - /* subsequent errors to errOut: */ - - for(i=numCerts-1; i>=0; i--) { - CSSM_DATA cdata; - SSLBUF_TO_CSSM(&c->derCert, &cdata); - serr = SecCertificateCreateFromData(&cdata, CSSM_CERT_X_509v3, - CSSM_CERT_ENCODING_DER, &cert); - if(serr) { - goto errOut; - } - /* - * Can't set a value at index i when there is an empty element - * at i=1! - */ - secdebug("sslcert", "Adding cert %p", cert); - CFArrayInsertValueAtIndex(certGroup, 0, cert); - c = c->next; - } - - /* - * Cook up an SSL-specific SecPolicyRef. This will persists as part - * of the SecTrustRef object we'll be creating. - */ - serr = SecPolicySearchCreate(CSSM_CERT_X_509v3, - &CSSMOID_APPLE_TP_SSL, - NULL, - &policySearch); - if(serr) { - sslErrorLog("***sslVerifyCertChain: SecPolicySearchCreate rtn %d\n", - (int)serr); - goto errOut; - } - serr = SecPolicySearchCopyNext(policySearch, &policy); - if(serr) { - sslErrorLog("***sslVerifyCertChain: SecPolicySearchCopyNext rtn %d\n", - (int)serr); - goto errOut; - } - sslOpts.Version = CSSM_APPLE_TP_SSL_OPTS_VERSION; - if(arePeerCerts) { - sslOpts.ServerNameLen = ctx->peerDomainNameLen; - sslOpts.ServerName = ctx->peerDomainName; - } - else { - sslOpts.ServerNameLen = 0; - sslOpts.ServerName = NULL; - } - sslOpts.Flags = 0; - if(ctx->protocolSide == kSSLServerSide) { - /* we're evaluating a client cert */ - sslOpts.Flags |= CSSM_APPLE_TP_SSL_CLIENT; - } - sslOptsData.Data = (uint8 *)&sslOpts; - sslOptsData.Length = sizeof(sslOpts); - serr = SecPolicySetValue(policy, &sslOptsData); - if(serr) { - sslErrorLog("***sslVerifyCertChain: SecPolicySetValue rtn %d\n", - (int)serr); - goto errOut; - } - - /* now a SecTrustRef */ - serr = SecTrustCreateWithCertificates(certGroup, policy, &theTrust); - if(serr) { - sslErrorLog("***sslVerifyCertChain: SecTrustCreateWithCertificates " - "rtn %d\n", (int)serr); - goto errOut; - } - - /* anchors - default, or ours? */ - if(ctx->trustedCerts != NULL) { - serr = SecTrustSetAnchorCertificates(theTrust, ctx->trustedCerts); - if(serr) { - sslErrorLog("***sslVerifyCertChain: SecTrustSetAnchorCertificates " - "rtn %d\n", (int)serr); - goto errOut; - } - } - tpActionData.Version = CSSM_APPLE_TP_ACTION_VERSION; - tpActionData.ActionFlags = 0; - if(ctx->allowExpiredCerts) { - tpActionData.ActionFlags |= CSSM_TP_ACTION_ALLOW_EXPIRED; - } - if(ctx->allowExpiredRoots) { - tpActionData.ActionFlags |= CSSM_TP_ACTION_ALLOW_EXPIRED_ROOT; - } - actionData = CFDataCreate(NULL, (UInt8 *)&tpActionData, sizeof(tpActionData)); - - serr = SecTrustSetParameters(theTrust, CSSM_TP_ACTION_DEFAULT, - actionData); - if(serr) { - sslErrorLog("***sslVerifyCertChain: SecTrustSetParameters rtn %d\n", - (int)serr); - goto errOut; - } - - #if 0 - /* Disabled for Radar 3421314 */ - /* - * Avoid searching user keychains for intermediate certs by specifying - * an empty array of keychains - */ - kcList = CFArrayCreateMutable(NULL, 0, NULL); - if(kcList == NULL) { - sslErrorLog("***sslVerifyCertChain: error creating null kcList\n"); - serr = errSecAllocate; - goto errOut; - } - serr = SecTrustSetKeychains(theTrust, kcList); - if(serr) { - sslErrorLog("***sslVerifyCertChain: SecTrustSetKeychains rtn %d\n", - (int)serr); - goto errOut; - } - #endif - - /* - * Save this no matter what if we're evaluating peer certs. - * We do a retain here so we can unconditionally release theTrust - * at the end of this routine in case of previous error or - * !arePeerCerts. - */ - if(arePeerCerts) { - ctx->peerSecTrust = theTrust; - CFRetain(theTrust); - } - - if(!ctx->enableCertVerify) { - /* trivial case, this is caller's responsibility */ - serr = errSecSuccess; - goto errOut; - } - - /* - * If the caller provided a list of trusted leaf certs, check them here - */ - if(ctx->trustedLeafCerts) { - if (sslGetMatchingCertInArray((SecCertificateRef)CFArrayGetValueAtIndex(certGroup, 0), - ctx->trustedLeafCerts)) { - serr = errSecSuccess; - goto errOut; - } - } - - /* - * Here we go; hand it over to SecTrust/TP. - */ - serr = SecTrustEvaluate(theTrust, &secTrustResult); - if(serr) { - sslErrorLog("***sslVerifyCertChain: SecTrustEvaluate rtn %d\n", - (int)serr); - goto errOut; - } - switch(secTrustResult) { - case kSecTrustResultUnspecified: - /* cert chain valid, no special UserTrust assignments */ - case kSecTrustResultProceed: - /* cert chain valid AND user explicitly trusts this */ - crtn = CSSM_OK; - break; - case kSecTrustResultDeny: - case kSecTrustResultConfirm: - /* - * Cert chain may well have verified OK, but user has flagged - * one of these certs as untrustable. - */ - crtn = CSSMERR_TP_NOT_TRUSTED; - break; - default: - { - OSStatus osCrtn; - serr = SecTrustGetCssmResultCode(theTrust, &osCrtn); - if(serr) { - sslErrorLog("***sslVerifyCertChain: SecTrustGetCssmResultCode" - " rtn %d\n", (int)serr); - goto errOut; - } - crtn = osCrtn; - } - } - if(crtn) { - /* get some detailed error info */ - switch(crtn) { - case CSSMERR_TP_INVALID_ANCHOR_CERT: - /* root found but we don't trust it */ - if(ctx->allowAnyRoot) { - serr = errSecSuccess; - sslErrorLog("***Warning: accepting unknown root cert\n"); - } - else { - serr = errSSLUnknownRootCert; - } - break; - case CSSMERR_TP_NOT_TRUSTED: - /* no root, not even in implicit SSL roots */ - if(ctx->allowAnyRoot) { - sslErrorLog("***Warning: accepting unverified cert chain\n"); - serr = errSecSuccess; - } - else { - serr = errSSLNoRootCert; - } - break; - case CSSMERR_TP_CERT_EXPIRED: - assert(!ctx->allowExpiredCerts); - serr = errSSLCertExpired; - break; - case CSSMERR_TP_CERT_NOT_VALID_YET: - serr = errSSLCertNotYetValid; - break; - case CSSMERR_APPLETP_HOSTNAME_MISMATCH: - serr = errSSLHostNameMismatch; - break; - case errSecInvalidTrustSettings: - /* these get passed along unmodified */ - serr = crtn; - break; - default: - stPrintCdsaError("sslVerifyCertChain: SecTrustEvaluate returned", - crtn); - serr = errSSLXCertChainInvalid; - break; - } - } /* SecTrustEvaluate error */ - -errOut: - /* - * Free up resources - certGroup, policy, etc. Note that most of these - * will actually persist as long as the current SSLContext does since - * peerSecTrust holds references to these. - */ - if(policy) { - CFRelease(policy); - } - if(policySearch) { - CFRelease(policySearch); - } - if(actionData) { - CFRelease(actionData); - } - if(anchors) { - sslReleaseArray(anchors); - CFRelease(anchors); - } - if(certGroup) { - sslReleaseArray(certGroup); - CFRelease(certGroup); - } - if(kcList) { - /* empty, no contents to release */ - CFRelease(kcList); - } - if(theTrust) { - CFRelease(theTrust); - } - return serr; -} - -#ifndef NDEBUG -void stPrintCdsaError(const char *op, CSSM_RETURN crtn) -{ - cssmPerror(op, crtn); -} -#endif - -// MARK: - -// MARK: Diffie-Hellman Support - -/* - * Generate a Diffie-Hellman key pair. Algorithm parameters always - * come from the server, so on client side we have the parameters - * as two SSLBuffers. On server side we have the pre-encoded block - * which comes from ServerDhParams. - */ -OSStatus sslDhGenKeyPairClient( - SSLContext *ctx, - const SSLBuffer *prime, - const SSLBuffer *generator, - CSSM_KEY_PTR publicKey, // RETURNED - CSSM_KEY_PTR privateKey) // RETURNED -{ - assert((prime->data != NULL) && (generator->data != NULL)); - if(prime->data && !generator->data) { - return errSSLProtocol; - } - if(!prime->data && generator->data) { - return errSSLProtocol; - } - - SSLBuffer sParam; - OSStatus ortn = sslEncodeDhParams(prime, generator, &sParam); - if(ortn) { - sslErrorLog("***sslDhGenerateKeyPairClient: DH param error\n"); - return ortn; - } - ortn = sslDhGenerateKeyPair(ctx, &sParam, prime->length * 8, publicKey, privateKey); - SSLFreeBuffer(&sParam); - return ortn; -} - -OSStatus sslDhGenerateKeyPair( - SSLContext *ctx, - const SSLBuffer *paramBlob, - uint32_t keySizeInBits, - CSSM_KEY_PTR publicKey, // RETURNED - CSSM_KEY_PTR privateKey) // RETURNED -{ - CSSM_RETURN crtn; - CSSM_CC_HANDLE ccHandle; - CSSM_DATA labelData = {8, (uint8 *)"tempKey"}; - OSStatus ortn = errSecSuccess; - CSSM_DATA cParamBlob; - - assert(ctx != NULL); - assert(ctx->cspHand != 0); - - memset(publicKey, 0, sizeof(CSSM_KEY)); - memset(privateKey, 0, sizeof(CSSM_KEY)); - SSLBUF_TO_CSSM(paramBlob, &cParamBlob); - - crtn = CSSM_CSP_CreateKeyGenContext(ctx->cspHand, - CSSM_ALGID_DH, - keySizeInBits, - NULL, // Seed - NULL, // Salt - NULL, // StartDate - NULL, // EndDate - &cParamBlob, - &ccHandle); - if(crtn) { - stPrintCdsaError("DH CSSM_CSP_CreateKeyGenContext", crtn); - return errSSLCrypto; - } - - crtn = CSSM_GenerateKeyPair(ccHandle, - CSSM_KEYUSE_DERIVE, // only legal use of a Diffie-Hellman key - CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, - &labelData, - publicKey, - /* private key specification */ - CSSM_KEYUSE_DERIVE, - CSSM_KEYATTR_RETURN_REF, - &labelData, // same labels - NULL, // CredAndAclEntry - privateKey); - if(crtn) { - stPrintCdsaError("DH CSSM_GenerateKeyPair", crtn); - ortn = errSSLCrypto; - } - CSSM_DeleteContext(ccHandle); - return ortn; -} - -/* - * Perform Diffie-Hellman key exchange. - * Valid on entry: - * ctx->dhPrivate - * ctx->dhPeerPublic - * - * This generates deriveSizeInBits of key-exchanged data. - */ - -/* the alg isn't important; we just want to be able to cook up lots of bits */ -#define DERIVE_KEY_ALG CSSM_ALGID_RC5 - -OSStatus sslDhKeyExchange( - SSLContext *ctx, - uint32_t deriveSizeInBits, - SSLBuffer *exchanged) -{ - CSSM_RETURN crtn; - CSSM_ACCESS_CREDENTIALS creds; - CSSM_CC_HANDLE ccHandle; - CSSM_DATA labelData = {8, (uint8 *)"tempKey"}; - CSSM_KEY derivedKey; - OSStatus ortn = errSecSuccess; - - assert(ctx != NULL); - assert(ctx->cspHand != 0); - assert(ctx->dhPrivate != NULL); - if(ctx->dhPeerPublic.length == 0) { - /* comes from peer, don't panic */ - sslErrorLog("cdsaDhKeyExchange: null peer public key\n"); - return errSSLProtocol; - } - - memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); - memset(&derivedKey, 0, sizeof(CSSM_KEY)); - - crtn = CSSM_CSP_CreateDeriveKeyContext(ctx->cspHand, - CSSM_ALGID_DH, - DERIVE_KEY_ALG, - deriveSizeInBits, - &creds, - ctx->dhPrivate, // BaseKey - 0, // IterationCount - 0, // Salt - 0, // Seed - &ccHandle); - if(crtn) { - stPrintCdsaError("DH CSSM_CSP_CreateDeriveKeyContext", crtn); - return errSSLCrypto; - } - - /* public key passed in as CSSM_DATA *Param */ - CSSM_DATA theirPubKeyData; - SSLBUF_TO_CSSM(&ctx->dhPeerPublic, &theirPubKeyData); - - crtn = CSSM_DeriveKey(ccHandle, - &theirPubKeyData, - CSSM_KEYUSE_ANY, - CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, - &labelData, - NULL, // cread/acl - &derivedKey); - if(crtn) { - stPrintCdsaError("DH CSSM_DeriveKey", crtn); - ortn = errSSLCrypto; - } - else { - CSSM_TO_SSLBUF(&derivedKey.KeyData, exchanged); - } - CSSM_DeleteContext(ccHandle); - return ortn; -} - -// MARK: - -// MARK: *** ECDSA support *** - -/* specify either 32-bit integer or a pointer as an added attribute value */ -typedef enum { - CAT_Uint32, - CAT_Ptr -} ContextAttrType; - -/* - * Given a context specified via a CSSM_CC_HANDLE, add a new - * CSSM_CONTEXT_ATTRIBUTE to the context as specified by AttributeType, - * AttributeLength, and an untyped pointer. - */ -static CSSM_RETURN sslAddContextAttribute(CSSM_CC_HANDLE CCHandle, - uint32 AttributeType, - uint32 AttributeLength, - ContextAttrType attrType, - /* specify exactly one of these */ - const void *AttributePtr, - uint32 attributeInt) -{ - CSSM_CONTEXT_ATTRIBUTE newAttr; - CSSM_RETURN crtn; - - newAttr.AttributeType = AttributeType; - newAttr.AttributeLength = AttributeLength; - if(attrType == CAT_Uint32) { - newAttr.Attribute.Uint32 = attributeInt; - } - else { - newAttr.Attribute.Data = (CSSM_DATA_PTR)AttributePtr; - } - crtn = CSSM_UpdateContextAttributes(CCHandle, 1, &newAttr); - if(crtn) { - stPrintCdsaError("CSSM_UpdateContextAttributes", crtn); - } - return crtn; -} - -/* - * Generate ECDH key pair with the given SSL_ECDSA_NamedCurve. - * Private key, in ref form, is placed in ctx->ecdhPrivate. - * Public key, in ECPoint form - which can NOT be used as - * a key in any CSP ops - is placed in ecdhExchangePublic. - */ -OSStatus sslEcdhGenerateKeyPair( - SSLContext *ctx, - SSL_ECDSA_NamedCurve namedCurve) -{ - CSSM_RETURN crtn; - CSSM_CC_HANDLE ccHandle = 0; - CSSM_DATA labelData = {8, (uint8 *)"ecdsaKey"}; - OSStatus ortn = errSecSuccess; - CSSM_KEY pubKey; - uint32 keySizeInBits; - - assert(ctx != NULL); - assert(ctx->cspHand != 0); - sslFreeKey(ctx->ecdhPrivCspHand, &ctx->ecdhPrivate, NULL); - SSLFreeBuffer(&ctx->ecdhExchangePublic); - - switch(namedCurve) { - case SSL_Curve_secp256r1: - keySizeInBits = 256; - break; - case SSL_Curve_secp384r1: - keySizeInBits = 384; - break; - case SSL_Curve_secp521r1: - keySizeInBits = 521; - break; - default: - /* should not have gotten this far */ - sslErrorLog("sslEcdhGenerateKeyPair: bad namedCurve (%u)\n", - (unsigned)namedCurve); - return errSSLInternal; - } - - ctx->ecdhPrivate = (CSSM_KEY *)sslMalloc(sizeof(CSSM_KEY)); - - memset(ctx->ecdhPrivate, 0, sizeof(CSSM_KEY)); - memset(&pubKey, 0, sizeof(CSSM_KEY)); - - crtn = CSSM_CSP_CreateKeyGenContext(ctx->cspHand, - CSSM_ALGID_ECDSA, - keySizeInBits, - NULL, // Seed - NULL, // Salt - NULL, // StartDate - NULL, // EndDate - NULL, // Params - &ccHandle); - if(crtn) { - stPrintCdsaError("ECDH CSSM_CSP_CreateKeyGenContext", crtn); - return errSSLCrypto; - } - /* subsequent errors to errOut: */ - - /* - * Here's how we get the raw ECPoint form of a public key - */ - crtn = sslAddContextAttribute(ccHandle, - CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT, - sizeof(uint32), - CAT_Uint32, - NULL, - CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING); - if(crtn) { - ortn = errSSLCrypto; - goto errOut; - } - - crtn = CSSM_GenerateKeyPair(ccHandle, - /* public key specification */ - CSSM_KEYUSE_DERIVE, // only legal use - right? - CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, - &labelData, - &pubKey, - /* private key specification */ - CSSM_KEYUSE_DERIVE, - CSSM_KEYATTR_RETURN_REF, - &labelData, // same labels - NULL, // CredAndAclEntry - ctx->ecdhPrivate); - if(crtn) { - stPrintCdsaError("ECDH CSSM_GenerateKeyPair", crtn); - ortn = errSSLCrypto; - goto errOut; - } - ctx->ecdhPrivCspHand = ctx->cspHand; - - /* - * Take that public key data, drop it into ecdhExchangePublic, - * and free the key. - */ - ortn = SSLCopyBufferFromData(pubKey.KeyData.Data, pubKey.KeyData.Length, - &ctx->ecdhExchangePublic); - CSSM_FreeKey(ctx->cspHand, NULL, &pubKey, CSSM_FALSE); - -errOut: - if(ccHandle != 0) { - CSSM_DeleteContext(ccHandle); - } - return ortn; - -} - -/* - * Perform ECDH key exchange. Obtained key material is the same - * size as our private key. - * - * On entry, ecdhPrivate is our private key. The peer's public key - * is either ctx->ecdhPeerPublic for ECDHE exchange, or - * ctx->peerPubKey for ECDH exchange. - */ -OSStatus sslEcdhKeyExchange( - SSLContext *ctx, - SSLBuffer *exchanged) -{ - CSSM_RETURN crtn; - CSSM_ACCESS_CREDENTIALS creds; - const CSSM_ACCESS_CREDENTIALS *secCreds; - const CSSM_ACCESS_CREDENTIALS *useCreds = &creds; - CSSM_CC_HANDLE ccHandle; - CSSM_DATA labelData = {8, (uint8 *)"tempKey"}; - CSSM_KEY derivedKey; - OSStatus ortn = errSecSuccess; - CSSM_KEY rawKey; - bool useRefKeys = false; - uint32 keyAttr; - SSLBuffer pubKeyBits = {0, NULL}; - - assert(ctx != NULL); - assert(ctx->ecdhPrivCspHand != 0); - assert(ctx->ecdhPrivate != NULL); - - memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); - memset(&derivedKey, 0, sizeof(CSSM_KEY)); - memset(&rawKey, 0, sizeof(CSSM_KEY)); - - /* - * If we're using an actual CSSM_KEY for the peer public key, and its - * cspHand differs from our private key, we do things a bit different - - * our key is in the CSPDL space, and it has a Sec-style ACL for which - * we need creds. Also, the peer public key and the derived key have - * to be in reference form. - */ - switch(ctx->selectedCipherSpec.keyExchangeMethod) { - case SSL_ECDH_ECDSA: - case SSL_ECDH_RSA: - if(ctx->cspHand != ctx->ecdhPrivCspHand) { - useRefKeys = true; - } - break; - default: - break; - } - if(useRefKeys) { - assert(ctx->signingPrivKeyRef != NULL); - ortn = SecKeyGetCredentials(ctx->signingPrivKeyRef, - CSSM_ACL_AUTHORIZATION_DERIVE, - kSecCredentialTypeDefault, - &secCreds); - if(ortn) { - stPrintCdsaError("ECDH SecKeyGetCredentials", ortn); - return ortn; - } - useCreds = secCreds; - } - crtn = CSSM_CSP_CreateDeriveKeyContext(ctx->ecdhPrivCspHand, - CSSM_ALGID_ECDH, - DERIVE_KEY_ALG, - ctx->ecdhPrivate->KeyHeader.LogicalKeySizeInBits, - useCreds, - ctx->ecdhPrivate, // BaseKey - 0, // IterationCount - 0, // Salt - 0, // Seed - &ccHandle); - if(crtn) { - stPrintCdsaError("ECDH CSSM_CSP_CreateDeriveKeyContext", crtn); - return errSSLCrypto; - } - /* subsequent errors to errOut: */ - - CSSM_DATA theirPubKeyData = {0, NULL}; - - switch(ctx->selectedCipherSpec.keyExchangeMethod) { - case SSL_ECDHE_ECDSA: - case SSL_ECDHE_RSA: - /* public key passed in as CSSM_DATA *Param */ - if(ctx->ecdhPeerPublic.length == 0) { - /* comes from peer, don't panic */ - sslErrorLog("sslEcdhKeyExchange: null peer public key\n"); - ortn = errSSLProtocol; - goto errOut; - } - SSLBUF_TO_CSSM(&ctx->ecdhPeerPublic, &theirPubKeyData); - break; - case SSL_ECDH_ECDSA: - case SSL_ECDH_RSA: - /* add pub key as a context attr */ - if(ctx->peerPubKey == NULL) { - sslErrorLog("sslEcdhKeyExchange: no peer key\n"); - ortn = errSSLInternal; - goto errOut; - } - - /* - * If we're using CSPDL, extract the raw public key bits in ECPoint - * form and transmit as CSSM_DATA *Param. - * The securityd can't transmit a public key in a DeriveKey context - * in any form. - */ - if(useRefKeys) { - ortn = sslEcdsaPubKeyBits(ctx->peerPubKey, &pubKeyBits); - if(ortn) { - goto errOut; - } - SSLBUF_TO_CSSM(&pubKeyBits, &theirPubKeyData); - } - else { - crtn = sslAddContextAttribute(ccHandle, - CSSM_ATTRIBUTE_PUBLIC_KEY, - sizeof(CSSM_KEY), - CAT_Ptr, - (void *)ctx->peerPubKey, - 0); - if(crtn) { - stPrintCdsaError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY)", - crtn); - ortn = errSSLInternal; - goto errOut; - } - } - break; - default: - /* shouldn't be here */ - assert(0); - ortn = errSSLInternal; - goto errOut; - } - - if(useRefKeys) { - keyAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; - } - else { - keyAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; - } - crtn = CSSM_DeriveKey(ccHandle, - &theirPubKeyData, - CSSM_KEYUSE_ANY, - keyAttr, - &labelData, - NULL, // cred/acl - &derivedKey); - if(crtn) { - stPrintCdsaError("ECDH CSSM_DeriveKey", crtn); - ortn = errSSLCrypto; - goto errOut; - } - - if(useRefKeys) { - /* - * one more step: NULL-wrap the generated ref key to something we - * can use - */ - ortn = sslNullWrapKey(ctx->ecdhPrivCspHand, &derivedKey, &rawKey); - if(ortn) { - goto errOut; - } - ortn = SSLCopyBufferFromData(rawKey.KeyData.Data, rawKey.KeyData.Length, - exchanged); - } - else { - ortn = SSLCopyBufferFromData(derivedKey.KeyData.Data, - derivedKey.KeyData.Length, exchanged); - } -errOut: - CSSM_DeleteContext(ccHandle); - if(useRefKeys) { - if(pubKeyBits.length) { - SSLFreeBuffer(&pubKeyBits); - } - if(rawKey.KeyData.Length) { - CSSM_FreeKey(ctx->ecdhPrivCspHand, NULL, &rawKey, CSSM_FALSE); - } - } - return ortn; -} - - -/* - * After ciphersuite negotiation is complete, verify that we have - * the capability of actually performing the selected cipher. - * Currently we just verify that we have a cert and private signing - * key, if needed, and that the signing key's algorithm matches the - * expected key exchange method. - * - * This is currently called from FindCipherSpec(), after it sets - * ctx->selectedCipherSuite to a (supposedly) valid value, and from - * sslBuildCipherSuiteArray(), in server mode (pre-negotiation) only. - */ -OSStatus sslVerifySelectedCipher( - SSLContext *ctx, - const SSLCipherSpec *selectedCipherSpec) -{ - if(ctx->protocolSide == kSSLClientSide) { - return errSecSuccess; - } - #if SSL_PAC_SERVER_ENABLE - if((ctx->masterSecretCallback != NULL) && - (ctx->sessionTicket.data != NULL)) { - /* EAP via PAC resumption; we can do it */ - return errSecSuccess; - } - #endif /* SSL_PAC_SERVER_ENABLE */ - - CSSM_ALGORITHMS requireAlg = CSSM_ALGID_NONE; - if(selectedCipherSpec == NULL) { - return errSSLInternal; - } - switch (selectedCipherSpec->keyExchangeMethod) { - case SSL_RSA: - case SSL_RSA_EXPORT: - case SSL_DH_RSA: - case SSL_DH_RSA_EXPORT: - case SSL_DHE_RSA: - case SSL_DHE_RSA_EXPORT: - requireAlg = CSSM_ALGID_RSA; - break; - case SSL_DHE_DSS: - case SSL_DHE_DSS_EXPORT: - case SSL_DH_DSS: - case SSL_DH_DSS_EXPORT: - requireAlg = CSSM_ALGID_DSA; - break; - case SSL_DH_anon: - case SSL_DH_anon_EXPORT: - /* CSSM_ALGID_NONE, no signing key */ - break; - /* - * When SSL_ECDSA_SERVER is true and we support ECDSA on the server side, - * we'll need to add some logic here... - */ - #if SSL_ECDSA_SERVER - #error Work needed in sslVerifySelectedCipher - #endif - - default: - /* needs update per cipherSpecs.c */ - assert(0); - return errSSLInternal; - } - if(requireAlg == CSSM_ALGID_NONE) { - return errSecSuccess; - } - - /* private signing key required */ - if(ctx->signingPrivKeyRef == NULL) { - sslErrorLog("sslVerifySelectedCipher: no signing key\n"); - return errSSLBadConfiguration; - } - { - const CSSM_KEY *cssmKey; - OSStatus ortn = SecKeyGetCSSMKey(ctx->signingPrivKeyRef, &cssmKey); - if(ortn) { - sslErrorLog("sslVerifySelectedCipher: SecKeyGetCSSMKey err %d\n", - (int)ortn); - return ortn; - } - if(cssmKey->KeyHeader.AlgorithmId != requireAlg) { - sslErrorLog("sslVerifySelectedCipher: signing key alg mismatch\n"); - return errSSLBadConfiguration; - } - } - return errSecSuccess; -} - -#endif /* USE_CDSA_CRYPTO */ - diff --git a/libsecurity_ssl/lib/ssl3Callouts.c b/libsecurity_ssl/lib/ssl3Callouts.c deleted file mode 100644 index dc32edfb..00000000 --- a/libsecurity_ssl/lib/ssl3Callouts.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright (c) 2002,2005-2007,2010-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * 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@ - */ - -/* - * ssl3Callouts.c - SSLv3-specific routines for SslTlsCallouts. - */ - -#include "sslMemory.h" -#include "tls_ssl.h" -#include "sslUtils.h" -#include "sslDigests.h" -#include "sslDebug.h" -#include "sslAlertMessage.h" - -#include -#include -#include - -#define LOG_GEN_KEY 0 - -/* - * On input, the following are valid: - * MasterSecret[48] - * ClientHello.random[32] - * ServerHello.random[32] - * - * key_block = - * MD5(master_secret + SHA(`A' + master_secret + - * ServerHello.random + - * ClientHello.random)) + - * MD5(master_secret + SHA(`BB' + master_secret + - * ServerHello.random + - * ClientHello.random)) + - * MD5(master_secret + SHA(`CCC' + master_secret + - * ServerHello.random + - * ClientHello.random)) + [...]; - */ -static OSStatus ssl3GenerateKeyMaterial ( - SSLBuffer key, // caller mallocs and specifies length of - // required key material here - SSLContext *ctx) -{ - OSStatus err; - UInt8 leaderData[10]; /* Max of 10 hashes - * (* 16 bytes/hash = 160 bytes of key) */ - UInt8 shaHashData[20], md5HashData[16]; - SSLBuffer shaContext, md5Context; - UInt8 *keyProgress; - size_t i,j,remaining, satisfied; - SSLBuffer leader, masterSecret, serverRandom, clientRandom, shaHash, md5Hash; - - #if LOG_GEN_KEY - printf("GenerateKey: master "); - for(i=0; imasterSecret[i]); - } - printf("\n"); - #endif - - assert(key.length <= 16 * sizeof(leaderData)); - - leader.data = leaderData; - masterSecret.data = ctx->masterSecret; - masterSecret.length = SSL_MASTER_SECRET_SIZE; - serverRandom.data = ctx->serverRandom; - serverRandom.length = SSL_CLIENT_SRVR_RAND_SIZE; - clientRandom.data = ctx->clientRandom; - clientRandom.length = SSL_CLIENT_SRVR_RAND_SIZE; - shaHash.data = shaHashData; - shaHash.length = 20; - md5Hash.data = md5HashData; - md5Hash.length = 16; - - md5Context.data = 0; - shaContext.data = 0; - if ((err = ReadyHash(&SSLHashMD5, &md5Context)) != 0) - goto fail; - if ((err = ReadyHash(&SSLHashSHA1, &shaContext)) != 0) - goto fail; - - keyProgress = key.data; - remaining = key.length; - - for (i = 0; remaining > 0; ++i) - { for (j = 0; j <= i; j++) - leaderData[j] = 0x41 + i; /* 'A', 'BB', 'CCC', etc. */ - leader.length = i+1; - - if ((err = SSLHashSHA1.update(&shaContext, &leader)) != 0) - goto fail; - if ((err = SSLHashSHA1.update(&shaContext, &masterSecret)) != 0) - goto fail; - if ((err = SSLHashSHA1.update(&shaContext, &serverRandom)) != 0) - goto fail; - if ((err = SSLHashSHA1.update(&shaContext, &clientRandom)) != 0) - goto fail; - if ((err = SSLHashSHA1.final(&shaContext, &shaHash)) != 0) - goto fail; - if ((err = SSLHashMD5.update(&md5Context, &masterSecret)) != 0) - goto fail; - if ((err = SSLHashMD5.update(&md5Context, &shaHash)) != 0) - goto fail; - if ((err = SSLHashMD5.final(&md5Context, &md5Hash)) != 0) - goto fail; - - satisfied = 16; - if (remaining < 16) - satisfied = remaining; - memcpy(keyProgress, md5HashData, satisfied); - remaining -= satisfied; - keyProgress += satisfied; - - if(remaining > 0) { - /* at top of loop, this was done in ReadyHash() */ - if ((err = SSLHashMD5.init(&md5Context)) != 0) - goto fail; - if ((err = SSLHashSHA1.init(&shaContext)) != 0) - goto fail; - } - } - - assert(remaining == 0 && keyProgress == (key.data + key.length)); - err = errSecSuccess; -fail: - SSLFreeBuffer(&md5Context); - SSLFreeBuffer(&shaContext); - - #if LOG_GEN_KEY - printf("GenerateKey: DONE\n"); - #endif - return err; -} - -/* - * On entry: clientRandom, serverRandom, preMasterSecret valid - * On return: masterSecret valid - */ -static OSStatus ssl3GenerateMasterSecret ( - SSLContext *ctx) -{ - OSStatus err; - SSLBuffer shaState, md5State, clientRandom, - serverRandom, shaHash, md5Hash, leader; - UInt8 *masterProgress, shaHashData[20], leaderData[3]; - int i; - - md5State.data = shaState.data = 0; - if ((err = SSLAllocBuffer(&md5State, SSLHashMD5.contextSize))) - goto fail; - if ((err = SSLAllocBuffer(&shaState, SSLHashSHA1.contextSize))) - goto fail; - - clientRandom.data = ctx->clientRandom; - clientRandom.length = SSL_CLIENT_SRVR_RAND_SIZE; - serverRandom.data = ctx->serverRandom; - serverRandom.length = SSL_CLIENT_SRVR_RAND_SIZE; - shaHash.data = shaHashData; - shaHash.length = 20; - - masterProgress = ctx->masterSecret; - - for (i = 1; i <= 3; i++) - { if ((err = SSLHashMD5.init(&md5State)) != 0) - goto fail; - if ((err = SSLHashSHA1.init(&shaState)) != 0) - goto fail; - - leaderData[0] = leaderData[1] = leaderData[2] = 0x40 + i; /* 'A', 'B', etc. */ - leader.data = leaderData; - leader.length = i; - - if ((err = SSLHashSHA1.update(&shaState, &leader)) != 0) - goto fail; - if ((err = SSLHashSHA1.update(&shaState, &ctx->preMasterSecret)) != 0) - goto fail; - if ((err = SSLHashSHA1.update(&shaState, &clientRandom)) != 0) - goto fail; - if ((err = SSLHashSHA1.update(&shaState, &serverRandom)) != 0) - goto fail; - if ((err = SSLHashSHA1.final(&shaState, &shaHash)) != 0) - goto fail; - if ((err = SSLHashMD5.update(&md5State, &ctx->preMasterSecret)) != 0) - goto fail; - if ((err = SSLHashMD5.update(&md5State, &shaHash)) != 0) - goto fail; - md5Hash.data = masterProgress; - md5Hash.length = 16; - if ((err = SSLHashMD5.final(&md5State, &md5Hash)) != 0) - goto fail; - masterProgress += 16; - } - - err = errSecSuccess; -fail: - SSLFreeBuffer(&shaState); - SSLFreeBuffer(&md5State); - return err; -} - -/* common routine to compute a Mac for finished message and cert verify message */ -static OSStatus -ssl3CalculateFinishedMessage( - SSLContext *ctx, - SSLBuffer finished, // mallocd by caller - SSLBuffer shaMsgState, // running total - SSLBuffer md5MsgState, // ditto - UInt32 senderID) // optional, nonzero for finished message -{ - OSStatus err; - SSLBuffer hash, input; - UInt8 sender[4], md5Inner[16], shaInner[20]; - - // assert(finished.length == 36); - - if (senderID != 0) { - SSLEncodeInt(sender, senderID, 4); - input.data = sender; - input.length = 4; - if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0) - goto fail; - if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0) - goto fail; - } - input.data = ctx->masterSecret; - input.length = SSL_MASTER_SECRET_SIZE; - if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0) - goto fail; - if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0) - goto fail; - input.data = (UInt8 *)SSLMACPad1; - input.length = SSLHashMD5.macPadSize; - if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0) - goto fail; - input.length = SSLHashSHA1.macPadSize; - if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0) - goto fail; - hash.data = md5Inner; - hash.length = 16; - if ((err = SSLHashMD5.final(&md5MsgState, &hash)) != 0) - goto fail; - hash.data = shaInner; - hash.length = 20; - if ((err = SSLHashSHA1.final(&shaMsgState, &hash)) != 0) - goto fail; - if ((err = SSLHashMD5.init(&md5MsgState)) != 0) - goto fail; - if ((err = SSLHashSHA1.init(&shaMsgState)) != 0) - goto fail; - input.data = ctx->masterSecret; - input.length = SSL_MASTER_SECRET_SIZE; - if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0) - goto fail; - if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0) - goto fail; - input.data = (UInt8 *)SSLMACPad2; - input.length = SSLHashMD5.macPadSize; - if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0) - goto fail; - input.length = SSLHashSHA1.macPadSize; - if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0) - goto fail; - input.data = md5Inner; - input.length = 16; - if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0) - goto fail; - hash.data = finished.data; - hash.length = 16; - if ((err = SSLHashMD5.final(&md5MsgState, &hash)) != 0) - goto fail; - input.data = shaInner; - input.length = 20; - if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0) - goto fail; - hash.data = finished.data + 16; - hash.length = 20; - if ((err = SSLHashSHA1.final(&shaMsgState, &hash)) != 0) - goto fail; - -fail: - return err; -} - - -static OSStatus ssl3ComputeFinishedMac ( - SSLContext *ctx, - SSLBuffer finished, // output - mallocd by caller - Boolean isServer) // refers to message, not us -{ - OSStatus serr; - SSLBuffer shaMsgState, md5MsgState; - - shaMsgState.data = 0; - md5MsgState.data = 0; - if ((serr = CloneHashState(&SSLHashSHA1, &ctx->shaState, &shaMsgState)) != 0) - goto fail; - if ((serr = CloneHashState(&SSLHashMD5, &ctx->md5State, &md5MsgState)) != 0) - goto fail; - - serr = ssl3CalculateFinishedMessage(ctx, finished, shaMsgState, md5MsgState, - isServer ? SSL_Finished_Sender_Server : SSL_Finished_Sender_Client); - -fail: - SSLFreeBuffer(&shaMsgState); - SSLFreeBuffer(&md5MsgState); - - return serr; -} - -/* TODO: Factor this and ssl3ComputeFinishedMac to share more common code. */ -static OSStatus ssl3ComputeCertVfyMac ( - SSLContext *ctx, - SSLBuffer *finished, // output - mallocd by caller - SSL_HashAlgorithm hash) //unused in this one -{ - OSStatus serr; - SSLBuffer shaMsgState, md5MsgState; - - shaMsgState.data = 0; - md5MsgState.data = 0; - if ((serr = CloneHashState(&SSLHashSHA1, &ctx->shaState, &shaMsgState)) != 0) - goto fail; - if ((serr = CloneHashState(&SSLHashMD5, &ctx->md5State, &md5MsgState)) != 0) - goto fail; - - assert(finished->length >= SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN); - finished->length = SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN; - - serr = ssl3CalculateFinishedMessage(ctx, *finished, shaMsgState, md5MsgState, 0); - -fail: - SSLFreeBuffer(&shaMsgState); - SSLFreeBuffer(&md5MsgState); - - return serr; -} - -const SslTlsCallouts Ssl3Callouts = { - ssl3GenerateKeyMaterial, - ssl3GenerateMasterSecret, - ssl3ComputeFinishedMac, - ssl3ComputeCertVfyMac -}; diff --git a/libsecurity_ssl/lib/ssl3RecordCallouts.c b/libsecurity_ssl/lib/ssl3RecordCallouts.c deleted file mode 100644 index e9604f49..00000000 --- a/libsecurity_ssl/lib/ssl3RecordCallouts.c +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Copyright (c) 2002,2005-2007,2010-2011 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@ - */ - -/* - * ssl3RecordCallouts.c - SSLv3-specific routines for SslTlsCallouts. - */ - -/* THIS FILE CONTAINS KERNEL CODE */ - -#include -#include -#include -#include - -#ifdef KERNEL -#include -#else -#include -#endif - -#include "sslDebug.h" -#include "sslMemory.h" -#include "sslUtils.h" -#include "sslRand.h" - -#include "tls_record.h" - - -/* - * ssl3WriteRecord does not send alerts on failure, out of the assumption/fear - * that this might result in a loop (since sending an alert causes ssl3WriteRecord - * to be called). - * - * As far as I can tell, we can use this same routine for SSLv3 and TLSv1, as long - * as we're not trying to use the "variable length padding" feature of TLSv1. - * OpenSSL doesn't use that feature; for now, neither will we. Thus this routine - * is used for the SslTlsCallouts.writeRecord function for both protocols. - */ -int ssl3WriteRecord( - SSLRecord rec, - struct SSLRecordInternalContext *ctx) -{ - int err; - int padding = 0, i; - WaitingRecord *out = NULL, *queue; - SSLBuffer payload, mac; - uint8_t *charPtr; - uint16_t payloadSize,blockSize = 0; - int head = 5; - - switch(rec.protocolVersion) { - case DTLS_Version_1_0: - head += 8; - case SSL_Version_3_0: - case TLS_Version_1_0: - case TLS_Version_1_1: - case TLS_Version_1_2: - break; - default: - check(0); - return errSSLRecordInternal; - } - check(rec.contents.length <= 16384); - - sslLogRecordIo("type = %02x, ver = %04x, len = %ld, seq = %016llx", - rec.contentType, rec.protocolVersion, rec.contents.length, - ctx->writeCipher.sequenceNum); - - /* Allocate enough room for the transmitted record, which will be: - * 5 bytes of header (13 for DTLS) + - * IV [block cipher and TLS1.1 or DTLS 1.0 only] - * encrypted contents + - * macLength + - * padding [block ciphers only] + - * padding length field (1 byte) [block ciphers only] - */ - payloadSize = (uint16_t) rec.contents.length; - CipherType cipherType = ctx->writeCipher.symCipher->params->cipherType; - const Cipher *cipher = &ctx->writeCipher.symCipher->c.cipher; - const AEADCipher *aead = &ctx->writeCipher.symCipher->c.aead; - blockSize = ctx->writeCipher.symCipher->params->blockSize; - switch (cipherType) { - case blockCipherType: - payloadSize += ctx->writeCipher.macRef->hash->digestSize; - padding = blockSize - (payloadSize % blockSize) - 1; - payloadSize += padding + 1; - /* TLS 1.1, TLS1.2 and DTLS 1.0 have an extra block for IV */ - if(ctx->negProtocolVersion >= TLS_Version_1_1) { - payloadSize += blockSize; - } - break; - case streamCipherType: - payloadSize += ctx->writeCipher.macRef->hash->digestSize; - break; - case aeadCipherType: - /* AES_GCM doesn't need padding. */ - payloadSize += aead->macSize; - break; - default: - check(0); - return errSSLRecordInternal; - } - - out = (WaitingRecord *)sslMalloc(offsetof(WaitingRecord, data) + - head + payloadSize); - out->next = NULL; - out->sent = 0; - out->length = head + payloadSize; - - charPtr = out->data; - *(charPtr++) = rec.contentType; - charPtr = SSLEncodeInt(charPtr, rec.protocolVersion, 2); - - /* DTLS sequence number */ - if(rec.protocolVersion == DTLS_Version_1_0) - charPtr = SSLEncodeUInt64(charPtr,ctx->writeCipher.sequenceNum); - - charPtr = SSLEncodeInt(charPtr, payloadSize, 2); - - /* Also for DTLS */ - if((ctx->negProtocolVersion >= TLS_Version_1_1) && - (cipherType == blockCipherType)) - { - SSLBuffer randomIV; - randomIV.data = charPtr; - randomIV.length = blockSize; - if((err = sslRand(&randomIV)) != 0) - return err; - charPtr += blockSize; - } - if (cipherType == aeadCipherType) { - /* Encode the explicit iv, for AES_GCM we just use the 8 byte - sequenceNum as the explicitIV. - Ideally this needs to be done in the algorithm itself, by an - extra function pointer in AEADCipher. */ - charPtr = SSLEncodeUInt64(charPtr,ctx->writeCipher.sequenceNum); - /* TODO: If we ever add any mode other than GCM this code might have - to be different. */ - /* TODO: Pass 4 byte implicit and 8 byte explicit IV to cipher */ - //err = ctx->writeCipher.symCipher->c.aead.setIV(charPtr, &ctx->writeCipher, ctx); - } - - /* Copy the contents into the output buffer */ - memcpy(charPtr, rec.contents.data, rec.contents.length); - payload.data = charPtr; - payload.length = rec.contents.length; - - charPtr += rec.contents.length; - - /* MAC the data */ - if (cipherType != aeadCipherType) { - /* MAC immediately follows data */ - mac.data = charPtr; - mac.length = ctx->writeCipher.macRef->hash->digestSize; - charPtr += mac.length; - if (mac.length > 0) /* Optimize away null case */ - { - check(ctx->sslTslCalls != NULL); - if ((err = ctx->sslTslCalls->computeMac(rec.contentType, - payload, - mac, - &ctx->writeCipher, - ctx->writeCipher.sequenceNum, - ctx)) != 0) - goto fail; - } - } - - /* For TLS 1.1 and DTLS, we would need to specifiy the IV, but instead - we are clever like this: since the IV is just one block in front, - we encrypt it with the rest of the data. The actual transmitted IV - is the result of the encryption, with whatever internal IV is used. - This method is explained in the TLS 1.1 RFC */ - if(ctx->negProtocolVersion >= TLS_Version_1_1 && - cipherType == blockCipherType) - { - payload.data -= blockSize; - } - - /* Update payload to reflect encrypted data: IV, contents, mac & padding */ - payload.length = payloadSize; - - - switch (cipherType) { - case blockCipherType: - /* Fill in the padding bytes & padding length field with the - * padding value; the protocol only requires the last byte, - * but filling them all in avoids leaking data */ - for (i = 1; i <= padding + 1; ++i) - payload.data[payload.length - i] = padding; - /* DROPTRHOUGH */ - case streamCipherType: - /* Encrypt the data */ - if ((err = cipher->encrypt(payload.data, - payload.data, payload.length, ctx->writeCipher.cipherCtx)) != 0) - goto fail; - break; - case aeadCipherType: - check(0); - break; - default: - check(0); - return errSSLRecordInternal; - } - - /* Enqueue the record to be written from the idle loop */ - if (ctx->recordWriteQueue == 0) - ctx->recordWriteQueue = out; - else - { queue = ctx->recordWriteQueue; - while (queue->next != 0) - queue = queue->next; - queue->next = out; - } - - /* Increment the sequence number */ - IncrementUInt64(&ctx->writeCipher.sequenceNum); - - return 0; - -fail: - /* - * Only for if we fail between when the WaitingRecord is allocated and when - * it is queued - */ - sslFree(out); - return err; -} - -static int ssl3DecryptRecord( - uint8_t type, - SSLBuffer *payload, - struct SSLRecordInternalContext *ctx) -{ - int err; - SSLBuffer content; - - CipherType cipherType = ctx->readCipher.symCipher->params->cipherType; - const Cipher *c = &ctx->readCipher.symCipher->c.cipher; - switch (cipherType) { - case blockCipherType: - if ((payload->length % ctx->readCipher.symCipher->params->blockSize) != 0) - { - return errSSLRecordDecryptionFail; - } - /* DROPTHROUGH */ - case streamCipherType: - /* Decrypt in place */ - err = c->decrypt(payload->data, payload->data, - payload->length, ctx->readCipher.cipherCtx); - break; - case aeadCipherType: - default: - check(0); - return errSSLRecordInternal; - } - if (err != 0) - { - return errSSLRecordDecryptionFail; - } - - /* Locate content within decrypted payload */ - content.data = payload->data; - content.length = payload->length - ctx->readCipher.macRef->hash->digestSize; - if (cipherType == blockCipherType) - { /* padding can't be equal to or more than a block */ - if (payload->data[payload->length - 1] >= ctx->readCipher.symCipher->params->blockSize) - { - sslErrorLog("DecryptSSLRecord: bad padding length (%d)\n", - (unsigned)payload->data[payload->length - 1]); - return errSSLRecordDecryptionFail; - } - content.length -= 1 + payload->data[payload->length - 1]; - /* Remove block size padding */ - } - - /* Verify MAC on payload */ - if (ctx->readCipher.macRef->hash->digestSize > 0) - /* Optimize away MAC for null case */ - if ((err = SSLVerifyMac(type, &content, - payload->data + content.length, ctx)) != 0) - { - return errSSLRecordBadRecordMac; - } - - *payload = content; /* Modify payload buffer to indicate content length */ - - return 0; -} - -/* initialize a per-CipherContext HashHmacContext for use in MACing each record */ -static int ssl3InitMac ( - CipherContext *cipherCtx) // macRef, macSecret valid on entry - // macCtx valid on return -{ - const HashReference *hash; - SSLBuffer *hashCtx; - int serr; - - check(cipherCtx->macRef != NULL); - hash = cipherCtx->macRef->hash; - check(hash != NULL); - - hashCtx = &cipherCtx->macCtx.hashCtx; - if(hashCtx->data != NULL) { - SSLFreeBuffer(hashCtx); - } - serr = SSLAllocBuffer(hashCtx, hash->contextSize); - if(serr) { - return serr; - } - return 0; -} - -static int ssl3FreeMac ( - CipherContext *cipherCtx) -{ - SSLBuffer *hashCtx; - - check(cipherCtx != NULL); - /* this can be called on a completely zeroed out CipherContext... */ - if(cipherCtx->macRef == NULL) { - return 0; - } - hashCtx = &cipherCtx->macCtx.hashCtx; - if(hashCtx->data != NULL) { - sslFree(hashCtx->data); - hashCtx->data = NULL; - } - hashCtx->length = 0; - return 0; -} - -static int ssl3ComputeMac ( - uint8_t type, - SSLBuffer data, - SSLBuffer mac, // caller mallocs data - CipherContext *cipherCtx, // assumes macCtx, macRef - sslUint64 seqNo, - struct SSLRecordInternalContext *ctx) -{ - int err; - uint8_t innerDigestData[SSL_MAX_DIGEST_LEN]; - uint8_t scratchData[11], *charPtr; - SSLBuffer digest, digestCtx, scratch; - SSLBuffer secret; - - const HashReference *hash; - - check(cipherCtx != NULL); - check(cipherCtx->macRef != NULL); - hash = cipherCtx->macRef->hash; - check(hash != NULL); - check(hash->macPadSize <= MAX_MAC_PADDING); - check(hash->digestSize <= SSL_MAX_DIGEST_LEN); - digestCtx = cipherCtx->macCtx.hashCtx; // may be NULL, for null cipher - secret.data = cipherCtx->macSecret; - secret.length = hash->digestSize; - - /* init'd early in SSLNewContext() */ - check(SSLMACPad1[0] == 0x36 && SSLMACPad2[0] == 0x5C); - - /* - * MAC = hash( MAC_write_secret + pad_2 + - * hash( MAC_write_secret + pad_1 + seq_num + type + - * length + content ) - * ) - */ - if ((err = hash->init(&digestCtx)) != 0) - goto exit; - if ((err = hash->update(&digestCtx, &secret)) != 0) /* MAC secret */ - goto exit; - scratch.data = (uint8_t *)SSLMACPad1; - scratch.length = hash->macPadSize; - if ((err = hash->update(&digestCtx, &scratch)) != 0) /* pad1 */ - goto exit; - charPtr = scratchData; - charPtr = SSLEncodeUInt64(charPtr, seqNo); - *charPtr++ = type; - charPtr = SSLEncodeSize(charPtr, data.length, 2); - scratch.data = scratchData; - scratch.length = 11; - check(charPtr = scratchData+11); - if ((err = hash->update(&digestCtx, &scratch)) != 0) - /* sequenceNo, type & length */ - goto exit; - if ((err = hash->update(&digestCtx, &data)) != 0) /* content */ - goto exit; - digest.data = innerDigestData; - digest.length = hash->digestSize; - if ((err = hash->final(&digestCtx, &digest)) != 0) /* figure inner digest */ - goto exit; - - if ((err = hash->init(&digestCtx)) != 0) - goto exit; - if ((err = hash->update(&digestCtx, &secret)) != 0) /* MAC secret */ - goto exit; - scratch.data = (uint8_t *)SSLMACPad2; - scratch.length = hash->macPadSize; - if ((err = hash->update(&digestCtx, &scratch)) != 0) /* pad2 */ - goto exit; - if ((err = hash->update(&digestCtx, &digest)) != 0) /* inner digest */ - goto exit; - if ((err = hash->final(&digestCtx, &mac)) != 0) /* figure the mac */ - goto exit; - - err = 0; /* redundant, I know */ - -exit: - return err; -} - - -const SslRecordCallouts Ssl3RecordCallouts = { - ssl3DecryptRecord, - ssl3WriteRecord, - ssl3InitMac, - ssl3FreeMac, - ssl3ComputeMac, -}; diff --git a/libsecurity_ssl/lib/sslAlertMessage.c b/libsecurity_ssl/lib/sslAlertMessage.c deleted file mode 100644 index 55e3c28e..00000000 --- a/libsecurity_ssl/lib/sslAlertMessage.c +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Copyright (c) 2000-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * 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@ - */ - -/* - * sslAlertMessage.c - SSL3 Alert protocol - */ - -#include "ssl.h" -#include "sslAlertMessage.h" -#include "sslMemory.h" -#include "sslContext.h" -#include "sslSession.h" -#include "sslDebug.h" -#include "sslUtils.h" - -#include - -#ifdef NDEBUG -#define SSLLogAlertMsg(msg,sent) -#else -static void SSLLogAlertMsg(AlertDescription msg, bool sent); -#endif - -static OSStatus SSLEncodeAlert( - SSLRecord *rec, - AlertLevel level, - AlertDescription desc, - SSLContext *ctx); - -/* - * If a peer sends us any kind of a bad cert alert, we may need to adjust - * ctx->clientCertState accordingly. - */ -static void -SSLDetectCertRejected( - SSLContext *ctx, - AlertDescription desc) -{ - if(ctx->protocolSide == kSSLServerSide) { - return; - } - if(ctx->clientCertState != kSSLClientCertSent) { - return; - } - switch(desc) { - case SSL_AlertBadCert: - case SSL_AlertUnsupportedCert: - case SSL_AlertCertRevoked: - case SSL_AlertCertExpired: - case SSL_AlertCertUnknown: - case SSL_AlertUnknownCA: - ctx->clientCertState = kSSLClientCertRejected; - break; - default: - break; - } -} - -OSStatus -SSLProcessAlert(SSLRecord rec, SSLContext *ctx) -{ OSStatus err = errSecSuccess; - AlertLevel level; - AlertDescription desc; - uint8_t *charPtr; - size_t remaining; - - if (rec.contents.length % 2 != 0) - { - err = SSLFatalSessionAlert(SSL_AlertIllegalParam, ctx); - if (!err) { - err = errSSLProtocol; - } - return err; - } - - charPtr = rec.contents.data; - remaining = rec.contents.length; - bool fatal = false; - - while (remaining > 0) - { level = (AlertLevel)*charPtr++; - desc = (AlertDescription)*charPtr++; - sslHdskMsgDebug("alert msg received level %d desc %d", - (int)level, (int)desc); - remaining -= 2; - SSLLogAlertMsg(desc, false); - - if (level == SSL_AlertLevelFatal) { - /* explicit fatal errror */ - fatal = true; - sslErrorLog("***Fatal alert %d received\n", desc); - } - SSLDetectCertRejected(ctx, desc); - - switch (desc) { - /* A number of these are fatal by implication */ - case SSL_AlertUnexpectedMsg: - err = errSSLPeerUnexpectedMsg; - fatal = true; - break; - case SSL_AlertBadRecordMac: - err = errSSLPeerBadRecordMac; - fatal = true; - break; - case SSL_AlertDecryptionFail_RESERVED: - err = errSSLPeerDecryptionFail; - fatal = true; - break; - case SSL_AlertRecordOverflow: - err = errSSLPeerRecordOverflow; - fatal = true; - break; - case SSL_AlertDecompressFail: - err = errSSLPeerDecompressFail; - fatal = true; - break; - case SSL_AlertHandshakeFail: - err = errSSLPeerHandshakeFail; - fatal = true; - break; - case SSL_AlertIllegalParam: - err = errSSLIllegalParam; - fatal = true; - break; - case SSL_AlertBadCert: - err = errSSLPeerBadCert; - break; - case SSL_AlertUnsupportedCert: - err = errSSLPeerUnsupportedCert; - break; - case SSL_AlertCertRevoked: - err = errSSLPeerCertRevoked; - break; - case SSL_AlertCertExpired: - err = errSSLPeerCertExpired; - break; - case SSL_AlertCertUnknown: - err = errSSLPeerCertUnknown; - break; - case SSL_AlertUnknownCA: - err = errSSLPeerUnknownCA; - break; - case SSL_AlertAccessDenied: - err = errSSLPeerAccessDenied; - break; - case SSL_AlertDecodeError: - err = errSSLPeerDecodeError; - break; - case SSL_AlertDecryptError: - err = errSSLPeerDecryptError; - break; - case SSL_AlertExportRestriction_RESERVED: - err = errSSLPeerExportRestriction; - break; - case SSL_AlertProtocolVersion: - err = errSSLPeerProtocolVersion; - break; - case SSL_AlertInsufficientSecurity: - err = errSSLPeerInsufficientSecurity; - break; - case SSL_AlertInternalError: - err = errSSLPeerInternalError; - break; - case SSL_AlertUserCancelled: - err = errSSLPeerUserCancelled; - break; - case SSL_AlertNoRenegotiation: - err = errSSLPeerNoRenegotiation; - break; - /* unusual cases.... */ - case SSL_AlertCloseNotify: - /* the clean "we're done" case */ - SSLClose(ctx); - err = errSecSuccess; - break; - case SSL_AlertNoCert_RESERVED: - if((ctx->state == SSL_HdskStateClientCert) && - (ctx->protocolSide == kSSLServerSide) && - (ctx->clientAuth != kAlwaysAuthenticate)) { - /* - * Tolerate this unless we're configured to - * *require* a client cert. If a client cert is - * required, we'll catch the error at the next - * handshake msg we receive - which will probably - * be a client key exchange msg, which is illegal - * when we're in state SSL_HdskStateClientCert. - * If the client cert is optional, advance to - * state ClientKeyExchange by pretending we - * just got a client cert msg. - */ - if ((err = SSLAdvanceHandshake(SSL_HdskCert, - ctx)) != 0) { - return err; - } - } - break; - case SSL_AlertUnsupportedExtension: - err = errSSLFatalAlert; - fatal = true; - break; - - default: - /* Unknown alert, ignore if not fatal */ - if(level == SSL_AlertLevelFatal) { - err = errSSLFatalAlert; - } - else { - err = errSecSuccess; - } - break; - } - if(fatal) { - /* don't bother processing any more */ - break; - } - } - if(fatal) { - SSLDeleteSessionData(ctx); - } - return err; -} - -OSStatus -SSLSendAlert(AlertLevel level, AlertDescription desc, SSLContext *ctx) -{ SSLRecord rec; - OSStatus err; - - switch(ctx->negProtocolVersion) { - case SSL_Version_Undetermined: - /* Too early in negotiation to send an alert */ - return errSecSuccess; - case SSL_Version_2_0: - /* shouldn't be here */ - assert(0); - return errSSLInternal; - default: - break; - } - if(ctx->sentFatalAlert) { - /* no more alerts allowed */ - return errSecSuccess; - } - if ((err = SSLEncodeAlert(&rec, level, desc, ctx)) != 0) - return err; - SSLLogAlertMsg(desc, true); - if ((err = SSLWriteRecord(rec, ctx)) != 0) - return err; - if ((err = SSLFreeBuffer(&rec.contents))) - return err; - if(desc == SSL_AlertCloseNotify) { - /* no more alerts allowed */ - ctx->sentFatalAlert = true; - } - return errSecSuccess; -} - -static OSStatus -SSLEncodeAlert(SSLRecord *rec, AlertLevel level, AlertDescription desc, SSLContext *ctx) -{ OSStatus err; - - rec->protocolVersion = ctx->negProtocolVersion; - rec->contentType = SSL_RecordTypeAlert; - rec->contents.length = 2; - if ((err = SSLAllocBuffer(&rec->contents, 2))) - return err; - rec->contents.data[0] = level; - rec->contents.data[1] = desc; - - return errSecSuccess; -} - -OSStatus -SSLFatalSessionAlert(AlertDescription desc, SSLContext *ctx) -{ OSStatus err1, err2; - - if(desc != SSL_AlertCloseNotify) { - sslHdskMsgDebug("SSLFatalSessionAlert: desc %d\n", desc); - } - SSLChangeHdskState(ctx, SSL_HdskStateErrorClose); - - if(ctx->negProtocolVersion < TLS_Version_1_0) { - /* translate to SSL3 if necessary */ - switch(desc) { - //case SSL_AlertDecryptionFail_RESERVED: - case SSL_AlertRecordOverflow: - case SSL_AlertAccessDenied: - case SSL_AlertDecodeError: - case SSL_AlertDecryptError: - //case SSL_AlertExportRestriction_RESERVED: - case SSL_AlertProtocolVersion: - case SSL_AlertInsufficientSecurity: - case SSL_AlertUserCancelled: - case SSL_AlertNoRenegotiation: - desc = SSL_AlertHandshakeFail; - break; - case SSL_AlertUnknownCA: - desc = SSL_AlertUnsupportedCert; - break; - case SSL_AlertInternalError: - desc = SSL_AlertCloseNotify; - break; - default: - /* send as is */ - break; - } - } - /* Make session unresumable; I'm not stopping if I get an error, - because I'd like to attempt to send the alert anyway */ - err1 = SSLDeleteSessionData(ctx); - - /* Second, send the alert */ - err2 = SSLSendAlert(SSL_AlertLevelFatal, desc, ctx); - - ctx->sentFatalAlert = true; - - /* If they both returned errors, arbitrarily return the first */ - return err1 != 0 ? err1 : err2; -} - -#ifndef NDEBUG - -/* log alert messages */ - -static char *alertMsgToStr(AlertDescription msg) -{ - static char badStr[100]; - - switch(msg) { - case SSL_AlertCloseNotify: - return "SSL_AlertCloseNotify"; - case SSL_AlertUnexpectedMsg: - return "SSL_AlertUnexpectedMsg"; - case SSL_AlertBadRecordMac: - return "SSL_AlertBadRecordMac"; - case SSL_AlertDecryptionFail_RESERVED: - return "SSL_AlertDecryptionFail"; - case SSL_AlertRecordOverflow: - return "SSL_AlertRecordOverflow"; - case SSL_AlertDecompressFail: - return "SSL_AlertDecompressFail"; - case SSL_AlertHandshakeFail: - return "SSL_AlertHandshakeFail"; - case SSL_AlertNoCert_RESERVED: - return "SSL_AlertNoCert"; - case SSL_AlertBadCert: - return "SSL_AlertBadCert"; - case SSL_AlertUnsupportedCert: - return "SSL_AlertUnsupportedCert"; - case SSL_AlertCertRevoked: - return "SSL_AlertCertRevoked"; - - case SSL_AlertCertExpired: - return "SSL_AlertCertExpired"; - case SSL_AlertCertUnknown: - return "SSL_AlertCertUnknown"; - case SSL_AlertIllegalParam: - return "SSL_AlertIllegalParam"; - case SSL_AlertUnknownCA: - return "SSL_AlertUnknownCA"; - case SSL_AlertAccessDenied: - return "SSL_AlertAccessDenied"; - case SSL_AlertDecodeError: - return "SSL_AlertDecodeError"; - case SSL_AlertDecryptError: - return "SSL_AlertDecryptError"; - - case SSL_AlertExportRestriction_RESERVED: - return "SSL_AlertExportRestriction"; - case SSL_AlertProtocolVersion: - return "SSL_AlertProtocolVersion"; - case SSL_AlertInsufficientSecurity: - return "SSL_AlertInsufficientSecurity"; - case SSL_AlertInternalError: - return "SSL_AlertInternalError"; - case SSL_AlertUserCancelled: - return "SSL_AlertUserCancelled"; - case SSL_AlertNoRenegotiation: - return "SSL_AlertNoRenegotiation"; - - default: - sprintf(badStr, "Unknown state (%d(d)", msg); - return badStr; - } -} - -static void SSLLogAlertMsg(AlertDescription msg, bool sent) -{ - sslHdskMsgDebug("---%s alert msg %s", - alertMsgToStr(msg), (sent ? "sent" : "recv")); -} - -#endif /* NDEBUG */ diff --git a/libsecurity_ssl/lib/sslCert.c b/libsecurity_ssl/lib/sslCert.c deleted file mode 100644 index 4aee2efb..00000000 --- a/libsecurity_ssl/lib/sslCert.c +++ /dev/null @@ -1,788 +0,0 @@ -/* - * Copyright (c) 1999-2001,2005-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * 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@ - */ - -/* - * sslCert.c - certificate request/verify messages - */ - -#include "ssl.h" -#include "sslContext.h" -#include "sslHandshake.h" -#include "sslMemory.h" -#include "sslAlertMessage.h" -#include "sslDebug.h" -#include "sslUtils.h" -#include "sslDigests.h" -#include "sslCrypto.h" - -#include -#include -#include -#include -#include -#include -#include "utilities/SecCFRelease.h" - - -OSStatus -SSLEncodeCertificate(SSLRecord *certificate, SSLContext *ctx) -{ OSStatus err; - size_t totalLength; - UInt8 *charPtr; - CFIndex i, certCount; -#ifdef USE_SSLCERTIFICATE - int j; - SSLCertificate *cert; -#else - CFArrayRef certChain; -#endif - int head; - - /* - * TBD: for client side, match Match DER-encoded acceptable DN list - * (ctx->acceptableDNList) to one of our certs. For now we just send - * what we have since we don't support multiple certs. - * - * Note this can be called with localCert==0 for client side in TLS1+ and DTLS; - * in that case we send an empty cert msg. - */ - assert(ctx->negProtocolVersion >= SSL_Version_3_0); - assert((ctx->localCert != NULL) || (ctx->negProtocolVersion >= TLS_Version_1_0)); - totalLength = 0; - -#ifdef USE_SSLCERTIFICATE - certCount = 0; - cert = ctx->localCert; - while (cert) - { totalLength += 3 + cert->derCert.length; /* 3 for encoded length field */ - ++certCount; - cert = cert->next; - } -#else - certChain = ctx->localCert; - certCount = certChain ? CFArrayGetCount(certChain) : 0; - for (i = 0; i < certCount; ++i) { - SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certChain, i); - totalLength += 3 + SecCertificateGetLength(cert); /* 3 for encoded length field */ - } -#endif - certificate->contentType = SSL_RecordTypeHandshake; - certificate->protocolVersion = ctx->negProtocolVersion; - head = SSLHandshakeHeaderSize(certificate); - if ((err = SSLAllocBuffer(&certificate->contents, totalLength + head + 3))) - return err; - - charPtr = SSLEncodeHandshakeHeader(ctx, certificate, SSL_HdskCert, totalLength+3); - - charPtr = SSLEncodeSize(charPtr, totalLength, 3); /* Vector length */ - -#ifdef USE_SSLCERTIFICATE - /* Root cert is first in the linked list, but has to go last, - * so walk list backwards */ - for (i = 0; i < certCount; ++i) - { cert = ctx->localCert; - for (j = i+1; j < certCount; ++j) - cert = cert->next; - charPtr = SSLEncodeSize(charPtr, cert->derCert.length, 3); - memcpy(charPtr, cert->derCert.data, cert->derCert.length); - charPtr += cert->derCert.length; - } -#else - /* Root cert is last in the array, and has to go last, - * so walk list forwards */ - for (i = 0; i < certCount; ++i) { - SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certChain, i); - CFIndex certLength = SecCertificateGetLength(cert); - charPtr = SSLEncodeSize(charPtr, certLength, 3); - memcpy(charPtr, SecCertificateGetBytePtr(cert), certLength); - charPtr += certLength; - } -#endif - - assert(charPtr == certificate->contents.data + certificate->contents.length); - - if ((ctx->protocolSide == kSSLClientSide) && (ctx->localCert)) { - /* this tells us to send a CertificateVerify msg after the - * client key exchange. We skip the cert vfy if we just - * sent an empty cert msg (i.e., we were asked for a cert - * but we don't have one). */ - ctx->certSent = 1; - assert(ctx->clientCertState == kSSLClientCertRequested); - assert(ctx->certRequested); - ctx->clientCertState = kSSLClientCertSent; - } - if(certCount == 0) { - sslCertDebug("...sending empty cert msg"); - } - return errSecSuccess; -} - -OSStatus -SSLProcessCertificate(SSLBuffer message, SSLContext *ctx) -{ - size_t listLen, certLen; - UInt8 *p; - OSStatus err; - CFMutableArrayRef certChain = NULL; - SecCertificateRef cert; - - p = message.data; - listLen = SSLDecodeInt(p,3); - p += 3; - if (listLen + 3 != message.length) { - sslErrorLog("SSLProcessCertificate: length decode error 1\n"); - return errSSLProtocol; - } - - while (listLen > 0) - { - if (listLen < 3) { - sslErrorLog("SSLProcessCertificate: length decode error 2\n"); - return errSSLProtocol; - } - certLen = SSLDecodeInt(p,3); - p += 3; - if (listLen < certLen + 3) { - sslErrorLog("SSLProcessCertificate: length decode error 3\n"); - return errSSLProtocol; - } - if (!certChain) { - certChain = CFArrayCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeArrayCallBacks); - if (certChain == NULL) { - return errSecAllocate; - } - } - cert = SecCertificateCreateWithBytes(NULL, p, certLen); - #if SSL_DEBUG && !TARGET_OS_IPHONE - { - /* print cert name when debugging; leave disabled otherwise */ - CFStringRef certName = NULL; - OSStatus status = SecCertificateInferLabel(cert, &certName); - char buf[1024]; - if (status || !certName || !CFStringGetCString(certName, buf, 1024-1, kCFStringEncodingUTF8)) { buf[0]=0; } - sslDebugLog("SSLProcessCertificate: err=%d, received \"%s\" (%ld bytes)\n",(int) status, buf, certLen); - CFReleaseSafe(certName); - } - #endif - if (cert == NULL) { - sslErrorLog("SSLProcessCertificate: unable to create cert ref from data\n"); - return errSecAllocate; - } - p += certLen; - /* Insert forwards; root cert will be last in linked list */ - CFArrayAppendValue(certChain, cert); - CFRelease(cert); - listLen -= 3+certLen; - } - assert(p == message.data + message.length && listLen == 0); - - if (ctx->protocolSide == kSSLClientSide && ctx->peerCert && !ctx->allowServerIdentityChange) { - // Do not accept a different server cert during renegotiation unless allowed. - if((certChain!=NULL) && !CFEqual(ctx->peerCert, certChain)) - { - CFRelease(certChain); - sslErrorLog("Illegal server identity change during renegotiation\n"); - return errSSLProtocol; - } - } - - // Replace old cert with new cert. - if (ctx->peerCert) { - sslDebugLog("SSLProcessCertificate: releasing existing cert chain\n"); - CFRelease(ctx->peerCert); - } - - ctx->peerCert = certChain; - - if (!ctx->peerCert) { - /* this *might* be OK... */ - if((ctx->protocolSide == kSSLServerSide) && - (ctx->clientAuth != kAlwaysAuthenticate)) { - /* - * we tried to authenticate, client doesn't have a cert, and - * app doesn't require it. OK. - */ - return errSecSuccess; - } - else { - AlertDescription desc; - if(ctx->negProtocolVersion == SSL_Version_3_0) { - /* this one's for SSL3 only */ - desc = SSL_AlertBadCert; - } - else { - desc = SSL_AlertCertUnknown; - } - SSLFatalSessionAlert(desc, ctx); - return errSSLXCertChainInvalid; - } - } - - - - if((err = sslVerifyCertChain(ctx, ctx->peerCert, true)) != 0) { - AlertDescription desc; - switch(err) { - case errSSLUnknownRootCert: - case errSSLNoRootCert: - desc = SSL_AlertUnknownCA; - break; - case errSSLCertExpired: - case errSSLCertNotYetValid: - desc = SSL_AlertCertExpired; - break; - case errSSLXCertChainInvalid: - default: - desc = SSL_AlertCertUnknown; - break; - } - SSLFatalSessionAlert(desc, ctx); - } - - if (err == errSecSuccess) { - if(ctx->peerPubKey != NULL) { - /* renegotiating - free old key first */ - sslFreePubKey(&ctx->peerPubKey); - } - err = sslCopyPeerPubKey(ctx, &ctx->peerPubKey); - } - - /* Now that cert verification is done, update context state */ - /* (this code was formerly in SSLProcessHandshakeMessage, */ - /* directly after the return from SSLProcessCertificate) */ - if(ctx->protocolSide == kSSLServerSide) { - if(err) { - /* - * Error could be from no cert (when we require one) - * or invalid cert - */ - if(ctx->peerCert != NULL) { - ctx->clientCertState = kSSLClientCertRejected; - } - } else if(ctx->peerCert != NULL) { - /* - * This still might change if cert verify msg - * fails. Note we avoid going to state - * if we get en empty cert message which is - * otherwise valid. - */ - ctx->clientCertState = kSSLClientCertSent; - } - - /* - * Schedule return to the caller to verify the client's identity. - * Note that an error during processing will cause early - * termination of the handshake. - */ - if (ctx->breakOnClientAuth) { - ctx->signalClientAuth = true; - } - } else { - /* - * Schedule return to the caller to verify the server's identity. - * Note that an error during processing will cause early - * termination of the handshake. - */ - if (ctx->breakOnServerAuth) { - ctx->signalServerAuth = true; - } - } - - return err; -} - -OSStatus -SSLEncodeCertificateRequest(SSLRecord *request, SSLContext *ctx) -{ - OSStatus err; - size_t shListLen = 0, dnListLen, msgLen; - UInt8 *charPtr; - DNListElem *dn; - int head; - - assert(ctx->protocolSide == kSSLServerSide); - if (sslVersionIsLikeTls12(ctx)) { - shListLen = 2 + 2 * (ctx->ecdsaEnable ? 5 : 3); //FIXME: 5:3 should not be hardcoded here. - } - - dnListLen = 0; - dn = ctx->acceptableDNList; - while (dn) - { dnListLen += 2 + dn->derDN.length; - dn = dn->next; - } - msgLen = 1 + // number of cert types - 2 + // cert types - shListLen + // SignatureAlgorithms - 2 + // length of DN list - dnListLen; - - request->contentType = SSL_RecordTypeHandshake; - assert(ctx->negProtocolVersion >= SSL_Version_3_0); - - request->protocolVersion = ctx->negProtocolVersion; - head = SSLHandshakeHeaderSize(request); - if ((err = SSLAllocBuffer(&request->contents, msgLen + head))) - return err; - - charPtr = SSLEncodeHandshakeHeader(ctx, request, SSL_HdskCertRequest, msgLen); - - *charPtr++ = 2; /* two cert types */ - *charPtr++ = SSLClientAuth_RSASign; - *charPtr++ = SSLClientAuth_ECDSASign; - - if (shListLen) { - /* Encode the supported_signature_algorithms added in TLS1.2 */ - /* We dont support SHA512 or SHA224 because we didnot implement the digest abstraction for those - and we dont keep a running hash for those. - We dont support SHA384/ECDSA because corecrypto ec does not support it with 256 bits curves */ - charPtr = SSLEncodeSize(charPtr, shListLen - 2, 2); - // *charPtr++ = SSL_HashAlgorithmSHA512; - // *charPtr++ = SSL_SignatureAlgorithmRSA; - *charPtr++ = SSL_HashAlgorithmSHA384; - *charPtr++ = SSL_SignatureAlgorithmRSA; - *charPtr++ = SSL_HashAlgorithmSHA256; - *charPtr++ = SSL_SignatureAlgorithmRSA; - // *charPtr++ = SSL_HashAlgorithmSHA224; - // *charPtr++ = SSL_SignatureAlgorithmRSA; - *charPtr++ = SSL_HashAlgorithmSHA1; - *charPtr++ = SSL_SignatureAlgorithmRSA; - if (ctx->ecdsaEnable) { - // *charPtr++ = SSL_HashAlgorithmSHA512; - // *charPtr++ = SSL_SignatureAlgorithmECDSA; - // *charPtr++ = SSL_HashAlgorithmSHA384; - // *charPtr++ = SSL_SignatureAlgorithmECDSA; - *charPtr++ = SSL_HashAlgorithmSHA256; - *charPtr++ = SSL_SignatureAlgorithmECDSA; - // *charPtr++ = SSL_HashAlgorithmSHA224; - // *charPtr++ = SSL_SignatureAlgorithmECDSA; - *charPtr++ = SSL_HashAlgorithmSHA1; - *charPtr++ = SSL_SignatureAlgorithmECDSA; - } - } - - charPtr = SSLEncodeSize(charPtr, dnListLen, 2); - dn = ctx->acceptableDNList; - while (dn) - { charPtr = SSLEncodeSize(charPtr, dn->derDN.length, 2); - memcpy(charPtr, dn->derDN.data, dn->derDN.length); - charPtr += dn->derDN.length; - dn = dn->next; - } - - assert(charPtr == request->contents.data + request->contents.length); - return errSecSuccess; -} - -#define SSL_ENABLE_ECDSA_SIGN_AUTH 0 -#define SSL_ENABLE_RSA_FIXED_ECDH_AUTH 0 -#define SSL_ENABLE_ECDSA_FIXED_ECDH_AUTH 0 - -OSStatus -SSLProcessCertificateRequest(SSLBuffer message, SSLContext *ctx) -{ - unsigned i; - unsigned typeCount; - unsigned shListLen = 0; - UInt8 *charPtr; - unsigned dnListLen; - unsigned dnLen; - SSLBuffer dnBuf; - DNListElem *dn; - OSStatus err; - - /* - * Cert request only happens in during client authentication. - * We'll send a client cert if we have an appropriate one, but - * we don't do any DNList compare. - */ - unsigned minLen = (sslVersionIsLikeTls12(ctx)) ? 5 : 3; - if (message.length < minLen) { - sslErrorLog("SSLProcessCertificateRequest: length decode error 1\n"); - return errSSLProtocol; - } - charPtr = message.data; - typeCount = *charPtr++; - if (typeCount < 1 || message.length < minLen + typeCount) { - sslErrorLog("SSLProcessCertificateRequest: length decode error 2\n"); - return errSSLProtocol; - } - if(typeCount != 0) { - /* Store server-specified auth types */ - if(ctx->clientAuthTypes != NULL) { - sslFree(ctx->clientAuthTypes); - } - ctx->clientAuthTypes = (SSLClientAuthenticationType *) - sslMalloc(typeCount * sizeof(SSLClientAuthenticationType)); - for(i=0; iclientAuthTypes[i] = (SSLClientAuthenticationType)(*charPtr++); - } - ctx->numAuthTypes = typeCount; - } - - if (sslVersionIsLikeTls12(ctx)) { - /* Parse the supported_signature_algorithms field added in TLS1.2 */ - shListLen = SSLDecodeInt(charPtr, 2); - charPtr += 2; - if (message.length < minLen + typeCount + shListLen) { - sslErrorLog("SSLProcessCertificateRequest: length decode error 3\n"); - return errSSLProtocol; - } - - if (shListLen & 1) { - sslErrorLog("SSLProcessCertificateRequest: signAlg len odd\n"); - return errSSLProtocol; - } - ctx->numServerSigAlgs = shListLen / 2; - if(ctx->serverSigAlgs != NULL) { - sslFree(ctx->serverSigAlgs); - } - ctx->serverSigAlgs = (SSLSignatureAndHashAlgorithm *) - sslMalloc((ctx->numServerSigAlgs) * sizeof(SSLSignatureAndHashAlgorithm)); - for(i=0; inumServerSigAlgs; i++) { - /* TODO: Validate hash and signature fields. */ - ctx->serverSigAlgs[i].hash = *charPtr++; - ctx->serverSigAlgs[i].signature = *charPtr++; - sslLogNegotiateDebug("===Server specifies sigAlg %d %d", - ctx->serverSigAlgs[i].hash, - ctx->serverSigAlgs[i].signature); - } - } - - /* if a client cert is set, it must match a server-specified auth type */ - err = SSLUpdateNegotiatedClientAuthType(ctx); - - /* obtain server's DNList */ - dnListLen = SSLDecodeInt(charPtr, 2); - charPtr += 2; - if (message.length != minLen + typeCount + shListLen + dnListLen) { - sslErrorLog("SSLProcessCertificateRequest: length decode error 3\n"); - return errSSLProtocol; - } - while (dnListLen > 0) - { if (dnListLen < 2) { - sslErrorLog("SSLProcessCertificateRequest: dnListLen error 1\n"); - return errSSLProtocol; - } - dnLen = SSLDecodeInt(charPtr, 2); - charPtr += 2; - if (dnListLen < 2 + dnLen) { - sslErrorLog("SSLProcessCertificateRequest: dnListLen error 2\n"); - return errSSLProtocol; - } - if ((err = SSLAllocBuffer(&dnBuf, sizeof(DNListElem)))) - return err; - dn = (DNListElem*)dnBuf.data; - if ((err = SSLAllocBuffer(&dn->derDN, dnLen))) - { SSLFreeBuffer(&dnBuf); - return err; - } - memcpy(dn->derDN.data, charPtr, dnLen); - charPtr += dnLen; - dn->next = ctx->acceptableDNList; - ctx->acceptableDNList = dn; - dnListLen -= 2 + dnLen; - } - - assert(charPtr == message.data + message.length); - - return errSecSuccess; -} - - -/* TODO: this should be refactored with FindSigAlg in sslKeyExchange.c */ -static -OSStatus FindCertSigAlg(SSLContext *ctx, - SSLSignatureAndHashAlgorithm *alg) -{ - unsigned i; - - assert(ctx->protocolSide == kSSLClientSide); - assert(ctx->negProtocolVersion >= TLS_Version_1_2); - assert(!ctx->isDTLS); - - if((ctx->numServerSigAlgs==0) ||(ctx->serverSigAlgs==NULL)) - return errSSLInternal; - - for(i=0; inumServerSigAlgs; i++) { - alg->hash = ctx->serverSigAlgs[i].hash; - alg->signature = ctx->serverSigAlgs[i].signature; - // We only support RSA cert for our own certs. - if(ctx->serverSigAlgs[i].signature != SSL_SignatureAlgorithmRSA) - continue; - - //Let's only support SHA1 and SHA256. SHA384 does not work with 512 bits RSA keys - // We should actually test against what the client cert can do. - if((alg->hash==SSL_HashAlgorithmSHA1) || (alg->hash==SSL_HashAlgorithmSHA256)) { - return errSecSuccess; - } - } - // We could not find a supported signature and hash algorithm - return errSSLProtocol; -} - -OSStatus -SSLEncodeCertificateVerify(SSLRecord *certVerify, SSLContext *ctx) -{ OSStatus err; - UInt8 hashData[SSL_MAX_DIGEST_LEN]; - SSLBuffer hashDataBuf; - size_t len; - size_t outputLen; - UInt8 *charPtr; - int head; - size_t maxSigLen; - bool isRSA = false; - - certVerify->contents.data = 0; - hashDataBuf.data = hashData; - hashDataBuf.length = SSL_MAX_DIGEST_LEN; - - - assert(ctx->signingPrivKeyRef != NULL); - err = sslGetMaxSigSize(ctx->signingPrivKeyRef, &maxSigLen); - if(err) { - goto fail; - } - - switch(ctx->negAuthType) { - case SSLClientAuth_RSASign: - isRSA = true; - break; -#if SSL_ENABLE_ECDSA_SIGN_AUTH - case SSLClientAuth_ECDSASign: - break; -#endif - default: - /* shouldn't be here */ - assert(0); - return errSSLInternal; - } - - certVerify->contentType = SSL_RecordTypeHandshake; - assert(ctx->negProtocolVersion >= SSL_Version_3_0); - certVerify->protocolVersion = ctx->negProtocolVersion; - head = SSLHandshakeHeaderSize(certVerify); - - outputLen = maxSigLen + head + 2; - - SSLSignatureAndHashAlgorithm sigAlg; - - if (sslVersionIsLikeTls12(ctx)) { - err=FindCertSigAlg(ctx, &sigAlg); - if(err) - goto fail; - outputLen += 2; - } - - assert(ctx->sslTslCalls != NULL); - if ((err = ctx->sslTslCalls->computeCertVfyMac(ctx, &hashDataBuf, sigAlg.hash)) != 0) - goto fail; - - if ((err = SSLAllocBuffer(&certVerify->contents, outputLen)) != 0) - goto fail; - - /* Sign now to get the actual length */ - charPtr = certVerify->contents.data+head; - - if (sslVersionIsLikeTls12(ctx)) - { - *charPtr++ = sigAlg.hash; - *charPtr++ = sigAlg.signature; - - /* We don't support anything but RSA for client side auth yet */ - assert(isRSA); - SecAsn1AlgId algId; - switch (sigAlg.hash) { - case SSL_HashAlgorithmSHA384: - algId.algorithm = CSSMOID_SHA384WithRSA; - break; - case SSL_HashAlgorithmSHA256: - algId.algorithm = CSSMOID_SHA256WithRSA; - break; - case SSL_HashAlgorithmSHA1: - algId.algorithm = CSSMOID_SHA1WithRSA; - break; - default: - sslErrorLog("SSLEncodeCertificateVerify: unsupported signature hash algorithm (%d)\n", - sigAlg.hash); - assert(0); // if you get here, something is wrong in FindCertSigAlg - err=errSSLInternal; - goto fail; - } - - err = sslRsaSign(ctx, - ctx->signingPrivKeyRef, - &algId, - hashData, - hashDataBuf.length, - charPtr+2, - maxSigLen, - &outputLen); - len=outputLen+2+2; - } else { - err = sslRawSign(ctx, - ctx->signingPrivKeyRef, - hashData, // data to sign - hashDataBuf.length, // Data to sign size - charPtr+2, // signature destination - maxSigLen, // we mallocd len+head+2 - &outputLen); - len = outputLen+2; - } - if(err) { - sslErrorLog("SSLEncodeCertificateVerify: unable to sign data (error %d)\n", (int)err); - goto fail; - } - // At this point: - // len = message length - // outputlen = sig length - certVerify->contents.length = len + head; - - /* charPtr point at the len field here */ - charPtr = SSLEncodeSize(charPtr, outputLen, 2); - charPtr = SSLEncodeHandshakeHeader(ctx, certVerify, SSL_HdskCertVerify, len); - - assert(charPtr==(certVerify->contents.data+head)); - - err = errSecSuccess; - -fail: - - return err; -} - -OSStatus -SSLProcessCertificateVerify(SSLBuffer message, SSLContext *ctx) -{ OSStatus err; - UInt8 hashData[SSL_MAX_DIGEST_LEN]; - size_t signatureLen; - SSLBuffer hashDataBuf; - size_t publicModulusLen; - uint8_t *charPtr = message.data; - uint8_t *endCp = charPtr + message.length; - - SSLSignatureAndHashAlgorithm sigAlg; - SecAsn1AlgId algId; - - if (ctx->isDTLS - ? ctx->negProtocolVersion < DTLS_Version_1_0 - : ctx->negProtocolVersion >= TLS_Version_1_2) { - /* Parse the algorithm field added in TLS1.2 */ - if((charPtr+2) > endCp) { - sslErrorLog("SSLProcessCertificateVerify: msg len error 1\n"); - return errSSLProtocol; - } - sigAlg.hash = *charPtr++; - sigAlg.signature = *charPtr++; - - switch (sigAlg.hash) { - case SSL_HashAlgorithmSHA256: - algId.algorithm = CSSMOID_SHA256WithRSA; - if(ctx->selectedCipherSpecParams.macAlg == HA_SHA384) { - sslErrorLog("SSLProcessCertificateVerify: inconsistent hash, HA_SHA384\n"); - return errSSLInternal; - } - break; - case SSL_HashAlgorithmSHA384: - algId.algorithm = CSSMOID_SHA384WithRSA; - if(ctx->selectedCipherSpecParams.macAlg != HA_SHA384) { - sslErrorLog("SSLProcessCertificateVerify: inconsistent hash, %d not HA_SHA384\n", ctx->selectedCipherSpecParams.macAlg); - return errSSLInternal; - } - break; - default: - sslErrorLog("SSLProcessCertificateVerify: unsupported hash %d\n", sigAlg.hash); - return errSSLProtocol; - } - } - - if ((charPtr + 2) > endCp) { - sslErrorLog("SSLProcessCertificateVerify: msg len error\n"); - return errSSLProtocol; - } - - signatureLen = SSLDecodeSize(charPtr, 2); - charPtr += 2; - if ((charPtr + signatureLen) > endCp) { - sslErrorLog("SSLProcessCertificateVerify: sig len error 1\n"); - return errSSLProtocol; - } - - publicModulusLen = sslPubKeyLengthInBytes(ctx->peerPubKey); - - #if 0 - if (signatureLen != publicModulusLen) { - sslErrorLog("SSLProcessCertificateVerify: sig len error 2\n"); - return errSSLProtocol; - } - #endif - if (publicModulusLen == 0) { - sslErrorLog("SSLProcessCertificateVerify: pub key modulus is 0\n"); - } - - hashDataBuf.data = hashData; - hashDataBuf.length = SSL_MAX_DIGEST_LEN; - - assert(ctx->sslTslCalls != NULL); - if ((err = ctx->sslTslCalls->computeCertVfyMac(ctx, &hashDataBuf, sigAlg.hash)) != 0) - goto fail; - - if (sslVersionIsLikeTls12(ctx)) - { - if(sigAlg.signature==SSL_SignatureAlgorithmRSA) { - err = sslRsaVerify(ctx, - ctx->peerPubKey, - &algId, - hashData, - hashDataBuf.length, - charPtr, - signatureLen); - } else { - err = sslRawVerify(ctx, - ctx->peerPubKey, - hashData, - hashDataBuf.length, - charPtr, - signatureLen); - } - } else { - /* sslRawVerify does the decrypt & compare for us in one shot. */ - err = sslRawVerify(ctx, - ctx->peerPubKey, - hashData, // data to verify - hashDataBuf.length, - charPtr, // signature - signatureLen); - } - - if(err) { - SSLFatalSessionAlert(SSL_AlertDecryptError, ctx); - goto fail; - } - err = errSecSuccess; - -fail: - return err; -} diff --git a/libsecurity_ssl/lib/sslChangeCipher.c b/libsecurity_ssl/lib/sslChangeCipher.c deleted file mode 100644 index bd28353e..00000000 --- a/libsecurity_ssl/lib/sslChangeCipher.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 1999-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * 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@ - */ - -/* - * sslChangeCipher.c - support for change cipher spec messages - */ - -#include "sslContext.h" -#include "sslHandshake.h" -#include "sslMemory.h" -#include "sslAlertMessage.h" -#include "sslDebug.h" -#include "sslCipherSpecs.h" - -#include -#include - -OSStatus -SSLEncodeChangeCipherSpec(SSLRecord *rec, SSLContext *ctx) -{ OSStatus err; - - assert(ctx->writePending_ready); - - sslLogNegotiateDebug("===Sending changeCipherSpec msg"); - rec->contentType = SSL_RecordTypeChangeCipher; - assert(ctx->negProtocolVersion >= SSL_Version_3_0); - rec->protocolVersion = ctx->negProtocolVersion; - rec->contents.length = 1; - if ((err = SSLAllocBuffer(&rec->contents, 1))) - return err; - rec->contents.data[0] = 1; - - ctx->messageQueueContainsChangeCipherSpec=true; - - return errSecSuccess; -} - -OSStatus -SSLProcessChangeCipherSpec(SSLRecord rec, SSLContext *ctx) -{ OSStatus err; - - if (rec.contents.length != 1 || rec.contents.data[0] != 1) - { - if(ctx->isDTLS) - return errSSLWouldBlock; - - SSLFatalSessionAlert(SSL_AlertUnexpectedMsg, ctx); - sslErrorLog("***bad changeCipherSpec msg: length %d data 0x%x\n", - (unsigned)rec.contents.length, (unsigned)rec.contents.data[0]); - return errSSLProtocol; - } - - /* - * Handle PAC-style session resumption, client side only. - * In that case, the handshake state was left in either KeyExchange or - * Cert. - */ - if((ctx->protocolSide == kSSLClientSide) && - (ctx->sessionTicket.length != 0) && - ((ctx->state == SSL_HdskStateKeyExchange) || (ctx->state == SSL_HdskStateCert)) && - (ctx->masterSecretCallback != NULL)) { - size_t secretLen = SSL_MASTER_SECRET_SIZE; - sslEapDebug("Client side resuming based on masterSecretCallback"); - ctx->masterSecretCallback(ctx, ctx->masterSecretArg, - ctx->masterSecret, &secretLen); - ctx->sessionMatch = 1; - - /* set up selectedCipherSpec */ - if ((err = FindCipherSpec(ctx)) != 0) { - return err; - } - if((err = SSLInitPendingCiphers(ctx)) != 0) { - SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec); - } - - if (!ctx->readPending_ready || ctx->state != SSL_HdskStateChangeCipherSpec) - { - if(ctx->isDTLS) - return errSSLWouldBlock; - - SSLFatalSessionAlert(SSL_AlertUnexpectedMsg, ctx); - sslErrorLog("***bad changeCipherSpec msg: readPending.ready %d state %d\n", - (unsigned)ctx->readPending_ready, (unsigned)ctx->state); - return errSSLProtocol; - } - - sslLogNegotiateDebug("===Processing changeCipherSpec msg"); - - /* Install new cipher spec on read side */ - if ((err = ctx->recFuncs->advanceReadCipher(ctx->recCtx)) != 0) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - ctx->readCipher_ready = 0; /* Can't send data until Finished is sent */ - SSLChangeHdskState(ctx, SSL_HdskStateFinished); - return errSecSuccess; -} - diff --git a/libsecurity_ssl/lib/sslCipherSpecs.c b/libsecurity_ssl/lib/sslCipherSpecs.c deleted file mode 100644 index ca520365..00000000 --- a/libsecurity_ssl/lib/sslCipherSpecs.c +++ /dev/null @@ -1,661 +0,0 @@ -/* - * Copyright (c) 1999-2001,2005-2011 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@ - */ - -/* - * cipherSpecs.c - SSLCipherSpec declarations - */ - -#include "sslBuildFlags.h" -#include "CipherSuite.h" -#include "sslContext.h" -#include "sslCipherSpecs.h" -#include "sslDebug.h" -#include "sslMemory.h" -#include "sslDebug.h" -#include "sslUtils.h" -#include "sslPriv.h" -#include "sslCrypto.h" - -#include -#include -#include -#include - -#include - - -#define ENABLE_RSA_DES_SHA_NONEXPORT ENABLE_DES -#define ENABLE_RSA_DES_MD5_NONEXPORT ENABLE_DES -#define ENABLE_RSA_DES_SHA_EXPORT ENABLE_DES -#define ENABLE_RSA_RC4_MD5_EXPORT ENABLE_RC4 /* the most common one */ -#define ENABLE_RSA_RC4_MD5_NONEXPORT ENABLE_RC4 -#define ENABLE_RSA_RC4_SHA_NONEXPORT ENABLE_RC4 -#define ENABLE_RSA_RC2_MD5_EXPORT ENABLE_RC2 -#define ENABLE_RSA_RC2_MD5_NONEXPORT ENABLE_RC2 -#define ENABLE_RSA_3DES_SHA ENABLE_3DES -#define ENABLE_RSA_3DES_MD5 ENABLE_3DES - -#define ENABLE_ECDH 1 -#define ENABLE_AES_GCM 0 - -#define ENABLE_PSK 1 - -#if APPLE_DH -#define ENABLE_DH_ANON 1 -#define ENABLE_DH_EPHEM_RSA 1 -#if USE_CDSA_CRYPTO -#define ENABLE_DH_EPHEM_DSA 1 -#else -#define ENABLE_DH_EPHEM_DSA 0 -#endif -#else -#define ENABLE_DH_ANON 0 -#define ENABLE_DH_EPHEM_RSA 0 -#define ENABLE_DH_EPHEM_DSA 0 -#endif /* APPLE_DH */ - -/* - * List of all CipherSpecs we implement. Depending on a context's - * exportable flag, not all of these might be available for use. - */ -/* Order by preference, domestic first */ -static const SSLCipherSuite KnownCipherSuites[] = { -#if ENABLE_AES_GCM - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, -#endif - TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, - TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, - TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, - TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, -#if ENABLE_AES_GCM - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, -#endif - TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, - TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, - TLS_ECDHE_RSA_WITH_RC4_128_SHA, - TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, -#if ENABLE_ECDH -#if ENABLE_AES_GCM - TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, - TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, -#endif - TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, - TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, -#if ENABLE_AES_GCM - TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, - TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, -#endif - TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, - TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, - TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, - TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, - TLS_ECDH_ECDSA_WITH_RC4_128_SHA, - TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, - TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, - TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, - TLS_ECDH_RSA_WITH_RC4_128_SHA, - TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, -#endif -#if ENABLE_AES_GCM - TLS_RSA_WITH_AES_256_GCM_SHA384, - TLS_RSA_WITH_AES_128_GCM_SHA256, -#endif - TLS_RSA_WITH_AES_256_CBC_SHA256, - TLS_RSA_WITH_AES_128_CBC_SHA256, - TLS_RSA_WITH_AES_128_CBC_SHA, - SSL_RSA_WITH_RC4_128_SHA, - SSL_RSA_WITH_RC4_128_MD5, - TLS_RSA_WITH_AES_256_CBC_SHA, - SSL_RSA_WITH_3DES_EDE_CBC_SHA, -#if ENABLE_SSLV2 - SSL_RSA_WITH_3DES_EDE_CBC_MD5, -#endif -#if ENABLE_DES - SSL_RSA_WITH_DES_CBC_SHA, -#endif -#if ENABLE_SSLV2 - SSL_RSA_WITH_DES_CBC_MD5, -#endif -#if ENABLE_RC2 - SSL_RSA_WITH_RC2_CBC_MD5, -#endif -#if ENABLE_AES_GCM -# if ENABLE_DH_EPHEM_DSA - TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, -# endif // ENABLE_DH_EPHEM_DSA - TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, -# if ENABLE_DH_EPHEM_DSA - TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, -# endif // ENABLE_DH_EPHEM_DSA - TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, -#endif // ENABLE_AES_GCM -#if ENABLE_DH_EPHEM_DSA - TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, -#endif - TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, -#if ENABLE_DH_EPHEM_DSA - TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, -#endif - TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, -#if ENABLE_DH_EPHEM_DSA - TLS_DHE_DSS_WITH_AES_128_CBC_SHA, -#endif - TLS_DHE_RSA_WITH_AES_128_CBC_SHA, -#if ENABLE_DH_EPHEM_DSA - TLS_DHE_DSS_WITH_AES_256_CBC_SHA, -#endif - TLS_DHE_RSA_WITH_AES_256_CBC_SHA, - SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, -#if ENABLE_DES - SSL_DHE_RSA_WITH_DES_CBC_SHA, -#endif -#if ENABLE_DH_EPHEM_DSA - SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, -#if ENABLE_DES - SSL_DHE_DSS_WITH_DES_CBC_SHA, -#endif -#endif -#if ENABLE_AES_GCM - TLS_DH_anon_WITH_AES_256_GCM_SHA384, - TLS_DH_anon_WITH_AES_128_GCM_SHA256, -#endif - TLS_DH_anon_WITH_AES_128_CBC_SHA256, - TLS_DH_anon_WITH_AES_256_CBC_SHA256, - TLS_DH_anon_WITH_AES_128_CBC_SHA, - TLS_DH_anon_WITH_AES_256_CBC_SHA, - SSL_DH_anon_WITH_RC4_128_MD5, - SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, -#if ENABLE_DES - SSL_DH_anon_WITH_DES_CBC_SHA, -#endif - TLS_ECDHE_ECDSA_WITH_NULL_SHA, - TLS_ECDHE_RSA_WITH_NULL_SHA, -#if ENABLE_ECDH - TLS_ECDH_ECDSA_WITH_NULL_SHA, - TLS_ECDH_RSA_WITH_NULL_SHA, -#endif - -#if ENABLE_PSK - TLS_PSK_WITH_AES_256_CBC_SHA384, - TLS_PSK_WITH_AES_128_CBC_SHA256, - TLS_PSK_WITH_AES_256_CBC_SHA, - TLS_PSK_WITH_AES_128_CBC_SHA, - TLS_PSK_WITH_RC4_128_SHA, - TLS_PSK_WITH_3DES_EDE_CBC_SHA, - TLS_PSK_WITH_NULL_SHA384, - TLS_PSK_WITH_NULL_SHA256, - TLS_PSK_WITH_NULL_SHA, -#endif - - TLS_RSA_WITH_NULL_SHA256, - SSL_RSA_WITH_NULL_SHA, - SSL_RSA_WITH_NULL_MD5 - -#if 0 - /* We don't support these yet. */ - TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, - TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, - TLS_RSA_WITH_RC4_128_SHA, - TLS_RSA_WITH_3DES_EDE_CBC_SHA, - TLS_RSA_WITH_RC4_128_MD5, - TLS_DH_DSS_WITH_AES_256_GCM_SHA384, - TLS_DH_DSS_WITH_AES_128_GCM_SHA256, - TLS_DH_RSA_WITH_AES_256_GCM_SHA384, - TLS_DH_RSA_WITH_AES_128_GCM_SHA256, - TLS_DH_DSS_WITH_AES_256_CBC_SHA256, - TLS_DH_RSA_WITH_AES_256_CBC_SHA256, - TLS_DH_DSS_WITH_AES_128_CBC_SHA256, - TLS_DH_RSA_WITH_AES_128_CBC_SHA256, - TLS_DH_DSS_WITH_AES_256_CBC_SHA, - TLS_DH_RSA_WITH_AES_256_CBC_SHA, - TLS_DH_DSS_WITH_AES_128_CBC_SHA, - TLS_DH_RSA_WITH_AES_128_CBC_SHA, - TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA, - TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA, - TLS_ECDH_anon_WITH_AES_256_CBC_SHA, - TLS_ECDH_anon_WITH_AES_128_CBC_SHA, - TLS_ECDH_anon_WITH_RC4_128_SHA, - TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, - TLS_ECDH_anon_WITH_NULL_SHA, -#endif -}; - -static const unsigned CipherSuiteCount = array_size(KnownCipherSuites); - - -/* - * Given a valid ctx->validCipherSpecs array, calculate how many of those - * cipherSpecs are *not* SSLv2 only, storing result in - * ctx->numValidNonSSLv2Specs. ClientHello routines need this to set - * up outgoing cipherSpecs arrays correctly. - * - * Also determines if any ECDSA/ECDH ciphers are enabled; we need to know - * that when creating a hello message. - */ -static void sslAnalyzeCipherSpecs(SSLContext *ctx) -{ - unsigned dex; - const SSLCipherSuite *cipherSuite; - -#if ENABLE_SSLV2 - ctx->numValidNonSSLv2Suites = 0; -#endif - cipherSuite = &ctx->validCipherSuites[0]; - ctx->ecdsaEnable = false; - for(dex=0; dexnumValidCipherSuites; dex++, cipherSuite++) { -#if ENABLE_SSLV2 - if(!CIPHER_SPEC_IS_SSLv2(*cipherSuite)) { - ctx->numValidNonSSLv2Suites++; - } -#endif - switch(sslCipherSuiteGetKeyExchangeMethod(*cipherSuite)) { - case SSL_ECDH_ECDSA: - case SSL_ECDHE_ECDSA: - case SSL_ECDH_RSA: - case SSL_ECDHE_RSA: - case SSL_ECDH_anon: - ctx->ecdsaEnable = true; - break; - default: - break; - } - } -} - -/* - * Build ctx->validCipherSpecs as a copy of KnownCipherSpecs, assuming that - * validCipherSpecs is currently not valid (i.e., SSLSetEnabledCiphers() has - * not been called). - */ -OSStatus sslBuildCipherSuiteArray(SSLContext *ctx) -{ - size_t size; - unsigned dex; - - assert(ctx != NULL); - assert(ctx->validCipherSuites == NULL); - - ctx->numValidCipherSuites = CipherSuiteCount; - size = CipherSuiteCount * sizeof(SSLCipherSuite); - ctx->validCipherSuites = (SSLCipherSuite *)sslMalloc(size); - if(ctx->validCipherSuites == NULL) { - ctx->numValidCipherSuites = 0; - return errSecAllocate; - } - - /* - * Trim out inappropriate ciphers: - * -- trim anonymous ciphers if !ctx->anonCipherEnable - * -- trim ECDSA ciphers for server side if appropriate - * -- trim ECDSA ciphers if TLSv1 disable or SSLv2 enabled (since - * we MUST do the Client Hello extensions to make these ciphers - * work reliably) - * -- trim Stream ciphers if DTLSv1 enable - */ - SSLCipherSuite *dst = ctx->validCipherSuites; - const SSLCipherSuite *src = KnownCipherSuites; - - bool trimECDSA = false; - if((ctx->protocolSide == kSSLServerSide) && !SSL_ECDSA_SERVER) { - trimECDSA = true; - } - if(ctx->minProtocolVersion == SSL_Version_2_0 - || ctx->maxProtocolVersion == SSL_Version_3_0) { - /* We trim ECDSA cipher suites if SSL2 is enabled or - The maximum allowed protocol is SSL3. Note that this - won't trim ECDSA cipherspecs for DTLS which should be - the right thing to do here. */ - trimECDSA = true; - } - - /* trim Stream Ciphers for DTLS */ - bool trimRC4 = ctx->isDTLS; - - bool trimDHE = (ctx->protocolSide == kSSLServerSide) && - !ctx->dhParamsEncoded.length; - - for(dex=0; dexnumValidCipherSuites--; - src++; - continue; - } - else { - break; - } - default: - break; - } - if(!ctx->anonCipherEnable) { - /* trim out the anonymous (and null-auth-cipher) ciphers */ - if(mac == HA_Null) { - /* skip this one */ - ctx->numValidCipherSuites--; - src++; - continue; - } - switch(kem) { - case SSL_DH_anon: - case SSL_DH_anon_EXPORT: - case SSL_ECDH_anon: - /* skip this one */ - ctx->numValidCipherSuites--; - src++; - continue; - default: - break; - } - } - if(ctx->falseStartEnabled) { - switch(kem){ - case SSL_ECDHE_ECDSA: - case SSL_ECDHE_RSA: - case SSL_DHE_RSA: - case SSL_DHE_DSS: - /* Ok for false start */ - break; - default: - /* Not ok, skip */ - ctx->numValidCipherSuites--; - src++; - continue; - } - switch(cipher) { - case SSL_CipherAlgorithmAES_128_CBC: - case SSL_CipherAlgorithmAES_128_GCM: - case SSL_CipherAlgorithmAES_256_CBC: - case SSL_CipherAlgorithmAES_256_GCM: - case SSL_CipherAlgorithmRC4_128: - /* Ok for false start */ - break; - default: - /* Not ok, skip*/ - ctx->numValidCipherSuites--; - src++; - continue; - } - } - - /* This will skip the simple DES cipher suites, but not the NULL cipher ones */ - if (keySize == 8) - { - /* skip this one */ - ctx->numValidCipherSuites--; - src++; - continue; - } - - /* Trim PSK ciphersuites, they need to be enabled explicitely */ - if (kem==TLS_PSK) { - ctx->numValidCipherSuites--; - src++; - continue; - } - - if (trimDHE) { - switch(kem) { - case SSL_DHE_DSS: - case SSL_DHE_DSS_EXPORT: - case SSL_DHE_RSA: - case SSL_DHE_RSA_EXPORT: - /* skip this one */ - ctx->numValidCipherSuites--; - src++; - continue; - default: - break; - } - } - - if (trimRC4 && (cipher==SSL_CipherAlgorithmRC4_128)) { - ctx->numValidCipherSuites--; - src++; - continue; - } - - if(cipher==SSL_CipherAlgorithmNull) { - ctx->numValidCipherSuites--; - src++; - continue; - } - - /* This one is good to go */ - *dst++ = *src++; - } - sslAnalyzeCipherSpecs(ctx); - return errSecSuccess; -} - -/* - * Convert an array of SSLCipherSuites (which is always KnownCipherSpecs) - * to an array of SSLCipherSuites. - */ -static OSStatus -cipherSuitesToCipherSuites( - size_t numCipherSuites, - const SSLCipherSuite *cipherSuites, - SSLCipherSuite *ciphers, /* RETURNED */ - size_t *numCiphers) /* IN/OUT */ -{ - if(*numCiphers < numCipherSuites) { - return errSSLBufferOverflow; - } - memcpy(ciphers, cipherSuites, numCipherSuites * sizeof(SSLCipherSuite)); - *numCiphers = numCipherSuites; - return errSecSuccess; -} - -/*** - *** Publically exported functions declared in SecureTransport.h - ***/ - -/* - * Determine number and values of all of the SSLCipherSuites we support. - * Caller allocates output buffer for SSLGetSupportedCiphers() and passes in - * its size in *numCiphers. If supplied buffer is too small, errSSLBufferOverflow - * will be returned. - */ -OSStatus -SSLGetNumberSupportedCiphers (SSLContextRef ctx, - size_t *numCiphers) -{ - if((ctx == NULL) || (numCiphers == NULL)) { - return errSecParam; - } - *numCiphers = CipherSuiteCount; - return errSecSuccess; -} - -OSStatus -SSLGetSupportedCiphers (SSLContextRef ctx, - SSLCipherSuite *ciphers, /* RETURNED */ - size_t *numCiphers) /* IN/OUT */ -{ - if((ctx == NULL) || (ciphers == NULL) || (numCiphers == NULL)) { - return errSecParam; - } - return cipherSuitesToCipherSuites(CipherSuiteCount, - KnownCipherSuites, - ciphers, - numCiphers); -} - -/* - * Specify a (typically) restricted set of SSLCipherSuites to be enabled by - * the current SSLContext. Can only be called when no session is active. Default - * set of enabled SSLCipherSuites is NOT the same as the complete set of supported - * SSLCipherSuites as obtained by SSLGetSupportedCiphers(). - */ -OSStatus -SSLSetEnabledCiphers (SSLContextRef ctx, - const SSLCipherSuite *ciphers, - size_t numCiphers) -{ - size_t size; - size_t foundCiphers=0; - unsigned callerDex; - unsigned tableDex; - - if((ctx == NULL) || (ciphers == NULL) || (numCiphers == 0)) { - return errSecParam; - } - if(sslIsSessionActive(ctx)) { - /* can't do this with an active session */ - return errSecBadReq; - } - size = numCiphers * sizeof(SSLCipherSuite); - ctx->validCipherSuites = (SSLCipherSuite *)sslMalloc(size); - if(ctx->validCipherSuites == NULL) { - ctx->numValidCipherSuites = 0; - return errSecAllocate; - } - - /* - * Run thru caller's specs, keep only the supported ones. - */ - for(callerDex=0; callerDexvalidCipherSuites[foundCiphers] = KnownCipherSuites[tableDex]; - foundCiphers++; - break; - } - } - } - - if(foundCiphers==0) { - /* caller specified only unsupported ciphersuites */ - sslFree(ctx->validCipherSuites); - ctx->validCipherSuites = NULL; - return errSSLBadCipherSuite; - } - - /* success */ - ctx->numValidCipherSuites = foundCiphers; - sslAnalyzeCipherSpecs(ctx); - return errSecSuccess; -} - -/* - * Determine number and values of all of the SSLCipherSuites currently enabled. - * Caller allocates output buffer for SSLGetEnabledCiphers() and passes in - * its size in *numCiphers. If supplied buffer is too small, errSSLBufferOverflow - * will be returned. - */ -OSStatus -SSLGetNumberEnabledCiphers (SSLContextRef ctx, - size_t *numCiphers) -{ - if((ctx == NULL) || (numCiphers == NULL)) { - return errSecParam; - } - if(ctx->validCipherSuites == NULL) { - /* hasn't been set; use default */ - *numCiphers = CipherSuiteCount; - } - else { - /* caller set via SSLSetEnabledCiphers */ - *numCiphers = ctx->numValidCipherSuites; - } - return errSecSuccess; -} - -OSStatus -SSLGetEnabledCiphers (SSLContextRef ctx, - SSLCipherSuite *ciphers, /* RETURNED */ - size_t *numCiphers) /* IN/OUT */ -{ - if((ctx == NULL) || (ciphers == NULL) || (numCiphers == NULL)) { - return errSecParam; - } - if(ctx->validCipherSuites == NULL) { - /* hasn't been set; use default */ - return cipherSuitesToCipherSuites(CipherSuiteCount, - KnownCipherSuites, - ciphers, - numCiphers); - } - else { - /* use the ones specified in SSLSetEnabledCiphers() */ - return cipherSuitesToCipherSuites(ctx->numValidCipherSuites, - ctx->validCipherSuites, - ciphers, - numCiphers); - } -} - -/*** - *** End of publically exported functions declared in SecureTransport.h - ***/ - -void InitCipherSpecParams(SSLContext *ctx) -{ - SSLCipherSpecParams *dst = &ctx->selectedCipherSpecParams; - dst->cipherSpec = ctx->selectedCipher; - dst->macSize = sslCipherSuiteGetMacSize(ctx->selectedCipher); - dst->macAlg = sslCipherSuiteGetMacAlgorithm(ctx->selectedCipher); - dst->keySize = sslCipherSuiteGetSymmetricCipherKeySize(ctx->selectedCipher); - dst->blockSize = sslCipherSuiteGetSymmetricCipherBlockIvSize(ctx->selectedCipher); - dst->ivSize = dst->blockSize; - dst->keyExchangeMethod = sslCipherSuiteGetKeyExchangeMethod(ctx->selectedCipher); -}; - - -OSStatus -FindCipherSpec(SSLContext *ctx) -{ - unsigned i; - - assert(ctx != NULL); - assert(ctx->validCipherSuites != NULL); - - for (i=0; inumValidCipherSuites; i++) - { - if (ctx->validCipherSuites[i] == ctx->selectedCipher) { - InitCipherSpecParams(ctx); - /* Make sure we're configured to handle this cipherSuite. */ - return sslVerifySelectedCipher(ctx); - } - } - /* Not found */ - return errSSLNegotiation; -} diff --git a/libsecurity_ssl/lib/sslContext.h b/libsecurity_ssl/lib/sslContext.h deleted file mode 100644 index a3e13cd9..00000000 --- a/libsecurity_ssl/lib/sslContext.h +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Copyright (c) 1999-2001,2005-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * 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@ - */ - -/* - * sslContext.h - Private SSL typedefs: SSLContext and its components - */ - -#ifndef _SSLCONTEXT_H_ -#define _SSLCONTEXT_H_ 1 - -#include "SecureTransport.h" -#include "sslBuildFlags.h" - -#ifdef USE_CDSA_CRYPTO -#include -#else -#if TARGET_OS_IPHONE -#include -#include -#else -#include "../sec/Security/SecDH.h" // hack to get SecDH. -// typedef struct OpaqueSecDHContext *SecDHContext; -#endif -#include -#endif - -#include -#include - -#include "sslPriv.h" -#include "tls_ssl.h" -#include "sslDigests.h" -#include "sslRecord.h" -#include "cipherSpecs.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct -{ SSLReadFunc read; - SSLWriteFunc write; - SSLConnectionRef ioRef; -} IOContext; - - -#ifdef USE_SSLCERTIFICATE - -/* - * An element in a certificate chain. - */ -typedef struct SSLCertificate -{ - struct SSLCertificate *next; - SSLBuffer derCert; -} SSLCertificate; - -size_t SSLGetCertificateChainLength( - const SSLCertificate *c); -OSStatus sslDeleteCertificateChain( - SSLCertificate *certs, - SSLContext *ctx); - -#endif /* USE_SSLCERTIFICATE */ - - -#include "sslHandshake.h" - -typedef struct WaitingMessage -{ - struct WaitingMessage *next; - SSLRecord rec; -} WaitingMessage; - -typedef struct DNListElem -{ struct DNListElem *next; - SSLBuffer derDN; -} DNListElem; - -#ifdef USE_CDSA_CRYPTO - -/* Public part of asymmetric key. */ -typedef struct SSLPubKey -{ - CSSM_KEY key; - CSSM_CSP_HANDLE csp; /* may not be needed, we figure this - * one out by trial&error, right? */ -} SSLPubKey; - -/* Private part of asymmetric key. */ -typedef struct SSLPrivKey -{ - SecKeyRef key; - -} SSLPrivKey; - -#else /* !USE_CDSA_CRYPTO */ - -#if TARGET_OS_IPHONE -typedef struct __SecKey SSLPubKey; -typedef struct __SecKey SSLPrivKey; -#else -typedef struct OpaqueSecKeyRef SSLPubKey; -typedef struct OpaqueSecKeyRef SSLPrivKey; -#endif -/* - * Convert SSLPrivKey/SSLPubKey types to a platform SecKeyRef - * (currently a no-op) - */ -#define SECKEYREF(sslkey) (sslkey) - -#endif - -typedef struct { - SSLCipherSuite cipherSpec; - KeyExchangeMethod keyExchangeMethod; - uint8_t keySize; /* size in bytes */ - uint8_t ivSize; - uint8_t blockSize; - uint8_t macSize; - HMAC_Algs macAlg; -} SSLCipherSpecParams; - -struct SSLContext -{ - CFRuntimeBase _base; - IOContext ioCtx; - - const struct SSLRecordFuncs *recFuncs; - SSLRecordContextRef recCtx; - - /* - * Prior to successful protocol negotiation, negProtocolVersion - * is SSL_Version_Undetermined. Subsequent to successful - * negotiation, negProtocolVersion contains the actual over-the-wire - * protocol value. - * - * The Boolean versionEnable flags are set by - * SSLSetProtocolVersionEnabled or SSLSetProtocolVersion and - * remain invariant once negotiation has started. If there - * were a large number of these and/or we were adding new - * protocol versions on a regular basis, we'd probably want - * to implement these as a word of flags. For now, in the - * real world, this is the most straightforward implementation. - */ - SSLProtocolVersion negProtocolVersion; /* negotiated */ - SSLProtocolVersion clientReqProtocol; /* requested by client in hello msg */ - SSLProtocolVersion minProtocolVersion; - SSLProtocolVersion maxProtocolVersion; - Boolean isDTLS; /* if this is a Datagram Context */ - SSLProtocolSide protocolSide; /* ConnectionEnd enum { server, client } in rfc5246. */ - - const struct _SslTlsCallouts *sslTslCalls; /* selects between SSLv3, TLSv1 and TLSv1.2 */ - - SSLPrivKey *signingPrivKeyRef; /* our private signing key */ - SSLPubKey *signingPubKey; /* our public signing key */ - - SSLPrivKey *encryptPrivKeyRef; /* our private encrypt key, for - * server-initiated key exchange */ - SSLPubKey *encryptPubKey; /* public version of above */ - - SSLPubKey *peerPubKey; - -#ifdef USE_SSLCERTIFICATE - /* - * Various cert chains. - * For all three, the root is the first in the chain. - */ - SSLCertificate *localCert; - SSLCertificate *encryptCert; - SSLCertificate *peerCert; - CSSM_ALGORITHMS ourSignerAlg; /* algorithm of the signer of localCert */ -#else - /* - * Various cert chains. - * For all three, the root is the last in the chain. - */ - CFArrayRef localCert; - CFArrayRef encryptCert; - CFArrayRef peerCert; - CFIndex ourSignerAlg; /* algorithm of the signer of localCert */ -#endif /* !USE_SSLCERTIFICATE */ - - /* - * The arrays we are given via SSLSetCertificate() and SSLSetEncryptionCertificate(). - * We keep them here, refcounted, solely for the associated getters. - */ - CFArrayRef localCertArray; - CFArrayRef encryptCertArray; - - /* peer certs as SecTrustRef */ - SecTrustRef peerSecTrust; - -#ifdef USE_CDSA_CRYPTO - - /* - * trusted root certs as specified in SSLSetTrustedRoots() - */ - CFArrayRef trustedCerts; - - /* for symmetric cipher and RNG */ - CSSM_CSP_HANDLE cspHand; - - /* session-wide handles for Apple TP, CL */ - CSSM_TP_HANDLE tpHand; - CSSM_CL_HANDLE clHand; -#else - -#ifdef USE_SSLCERTIFICATE - size_t numTrustedCerts; - SSLCertificate *trustedCerts; -#else - CFMutableArrayRef trustedCerts; - Boolean trustedCertsOnly; -#endif /* !USE_SSLCERTIFICATE */ - -#endif /* !USE_CDSA_CRYPTO */ - - /* - * trusted leaf certs as specified in SSLSetTrustedLeafCertificates() - */ - CFArrayRef trustedLeafCerts; - - #if APPLE_DH - SSLBuffer dhPeerPublic; - SSLBuffer dhExchangePublic; - SSLBuffer dhParamsEncoded; /* PKCS3 encoded blob - prime + generator */ -#ifdef USE_CDSA_CRYPTO - CSSM_KEY_PTR dhPrivate; -#else - SecDHContext secDHContext; -#endif /* !USE_CDSA_CRYPTO */ - #endif /* APPLE_DH */ - - /* - * ECDH support - * - * ecdhCurves[] is the set of currently configured curves; the number - * of valid curves is ecdhNumCurves. - */ - SSL_ECDSA_NamedCurve ecdhCurves[SSL_ECDSA_NUM_CURVES]; - unsigned ecdhNumCurves; - - SSLBuffer ecdhPeerPublic; /* peer's public ECDH key as ECPoint */ - SSL_ECDSA_NamedCurve ecdhPeerCurve; /* named curve associated with ecdhPeerPublic or - * peerPubKey */ - SSLBuffer ecdhExchangePublic; /* Our public key as ECPoint */ -#ifdef USE_CDSA_CRYPTO - CSSM_KEY_PTR ecdhPrivate; /* our private key */ - CSSM_CSP_HANDLE ecdhPrivCspHand; -#else - ccec_full_ctx_decl(ccn_sizeof(521), ecdhContext); // Big enough to hold a 521 bit ecdh key pair. -#endif /* !USE_CDSA_CRYPTO */ - - Boolean allowExpiredCerts; - Boolean allowExpiredRoots; - Boolean enableCertVerify; - - SSLBuffer dtlsCookie; /* DTLS ClientHello cookie */ - Boolean cookieVerified; /* Mark if cookie was verified */ - uint16_t hdskMessageSeq; /* Handshake Seq Num to be sent */ - uint32_t hdskMessageRetryCount; /* retry cont for a given flight of messages */ - uint16_t hdskMessageSeqNext; /* Handshake Seq Num to be received */ - SSLHandshakeMsg hdskMessageCurrent; /* Current Handshake Message */ - uint16_t hdskMessageCurrentOfs; /* Offset in current Handshake Message */ - - SSLBuffer sessionID; - - SSLBuffer peerID; - SSLBuffer resumableSession; - - char *peerDomainName; - size_t peerDomainNameLen; - - uint8_t readCipher_ready; - uint8_t writeCipher_ready; - uint8_t readPending_ready; - uint8_t writePending_ready; - uint8_t prevCipher_ready; /* previous write cipher context, used for retransmit */ - - uint16_t selectedCipher; /* currently selected */ - SSLCipherSpecParams selectedCipherSpecParams; /* ditto */ - - SSLCipherSuite *validCipherSuites; /* context's valid suites */ - size_t numValidCipherSuites; /* size of validCipherSuites */ -#if ENABLE_SSLV2 - unsigned numValidNonSSLv2Suites; /* number of entries in validCipherSpecs that - * are *not* SSLv2 only */ -#endif - SSLHandshakeState state; - - /* server-side only */ - SSLAuthenticate clientAuth; /* kNeverAuthenticate, etc. */ - Boolean tryClientAuth; - - /* client and server */ - SSLClientCertificateState clientCertState; - - DNListElem *acceptableDNList; /* client and server */ - CFMutableArrayRef acceptableCAs; /* server only - SecCertificateRefs */ - - bool certRequested; - bool certSent; - bool certReceived; - bool x509Requested; - - uint8_t clientRandom[SSL_CLIENT_SRVR_RAND_SIZE]; - uint8_t serverRandom[SSL_CLIENT_SRVR_RAND_SIZE]; - SSLBuffer preMasterSecret; - uint8_t masterSecret[SSL_MASTER_SECRET_SIZE]; - - /* running digests of all handshake messages */ - SSLBuffer shaState, md5State, sha256State, sha512State; - - SSLBuffer fragmentedMessageCache; - - unsigned ssl2ChallengeLength; - unsigned ssl2ConnectionIDLength; - unsigned sessionMatch; - - /* Queue a full flight of messages */ - WaitingMessage *messageWriteQueue; - Boolean messageQueueContainsChangeCipherSpec; - - /* Transport layer fields */ - SSLBuffer receivedDataBuffer; - size_t receivedDataPos; - - Boolean allowAnyRoot; // don't require known roots - Boolean sentFatalAlert; // this session terminated by fatal alert - Boolean rsaBlindingEnable; - Boolean oneByteRecordEnable; /* enable 1/n-1 data splitting for TLSv1 and SSLv3 */ - Boolean wroteAppData; /* at least one write completed with current writeCipher */ - Boolean allowServerIdentityChange; /* allow server identity change on renegotiation - disallowed by default to avoid triple handshake attack */ - - /* optional session cache timeout (in seconds) override - 0 means default */ - uint32_t sessionCacheTimeout; - - /* optional SessionTicket */ - SSLBuffer sessionTicket; - - /* optional callback to obtain master secret, with its opaque arg */ - SSLInternalMasterSecretFunction masterSecretCallback; - const void *masterSecretArg; - - #if SSL_PAC_SERVER_ENABLE - /* server PAC resume sets serverRandom early to allow for secret acquisition */ - uint8_t serverRandomValid; - #endif - - Boolean anonCipherEnable; - - /* optional switches to enable additional returns from SSLHandshake */ - Boolean breakOnServerAuth; - Boolean breakOnCertRequest; - Boolean breakOnClientAuth; - Boolean signalServerAuth; - Boolean signalCertRequest; - Boolean signalClientAuth; - - /* true iff ECDSA/ECDH ciphers are configured */ - Boolean ecdsaEnable; - - /* List of server-specified client auth types */ - unsigned numAuthTypes; - SSLClientAuthenticationType *clientAuthTypes; - - /* client auth type actually negotiated */ - SSLClientAuthenticationType negAuthType; - - /* List of client-specified supported_signature_algorithms (for key exchange) */ - unsigned numClientSigAlgs; - SSLSignatureAndHashAlgorithm *clientSigAlgs; - /* List of server-specified supported_signature_algorithms (for client cert) */ - unsigned numServerSigAlgs; - SSLSignatureAndHashAlgorithm *serverSigAlgs; - - - /* Timeout for DTLS retransmit */ - CFAbsoluteTime timeout_deadline; - CFAbsoluteTime timeout_duration; - size_t mtu; - - /* RFC 5746: Secure renegotiation */ - Boolean secure_renegotiation; - Boolean secure_renegotiation_received; - SSLBuffer ownVerifyData; - SSLBuffer peerVerifyData; - - /* RFC 4279: TLS PSK */ - SSLBuffer pskSharedSecret; - SSLBuffer pskIdentity; - - /* TLS False Start */ - Boolean falseStartEnabled; //FalseStart enabled (by API call) -}; - -OSStatus SSLUpdateNegotiatedClientAuthType(SSLContextRef ctx); - -Boolean sslIsSessionActive(const SSLContext *ctx); - -static inline bool sslVersionIsLikeTls12(SSLContext *ctx) -{ - check(ctx->negProtocolVersion!=SSL_Version_Undetermined); - return ctx->isDTLS ? ctx->negProtocolVersion > DTLS_Version_1_0 : ctx->negProtocolVersion >= TLS_Version_1_2; -} - -#ifdef __cplusplus -} -#endif - -#endif /* _SSLCONTEXT_H_ */ diff --git a/libsecurity_ssl/lib/sslCrypto.c b/libsecurity_ssl/lib/sslCrypto.c deleted file mode 100644 index b6ad13ef..00000000 --- a/libsecurity_ssl/lib/sslCrypto.c +++ /dev/null @@ -1,1269 +0,0 @@ -/* - * Copyright (c) 2006-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * 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@ - */ - -/* - * sslCrypto.c - interface between SSL and crypto libraries - */ - -#include "sslCrypto.h" - -#include "CipherSuite.h" -#include "ssl.h" -#include "sslContext.h" -#include "sslMemory.h" -#include "sslUtils.h" -#include "sslDebug.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "utilities/SecCFRelease.h" - -#if TARGET_OS_IPHONE -#include -#include -#include -#endif - -#ifndef _SSL_KEYCHAIN_H_ -#include "sslKeychain.h" -#endif - -#if APPLE_DH -#include -#include -#include -#include -#include -#endif - -#include -#include -#include - -#if TARGET_OS_IPHONE -#define CCRNGSTATE ccrng_seckey -#else -/* extern struct ccrng_state *ccDRBGGetRngState(); */ -#include -#define CCRNGSTATE ccDRBGGetRngState() -#endif - - -/* - * Free a pubKey object. - */ -extern OSStatus sslFreePubKey(SSLPubKey **pubKey) -{ - if (pubKey && *pubKey) { - CFReleaseNull(SECKEYREF(*pubKey)); - } - return errSecSuccess; -} - -/* - * Free a privKey object. - */ -extern OSStatus sslFreePrivKey(SSLPrivKey **privKey) -{ - if (privKey && *privKey) { - CFReleaseNull(SECKEYREF(*privKey)); - } - return errSecSuccess; -} - -/* - * Get algorithm id for a SSLPubKey object. - */ -CFIndex sslPubKeyGetAlgorithmID(SSLPubKey *pubKey) -{ -#if TARGET_OS_IPHONE - return SecKeyGetAlgorithmID(SECKEYREF(pubKey)); -#else - return SecKeyGetAlgorithmId(SECKEYREF(pubKey)); -#endif -} - -/* - * Get algorithm id for a SSLPrivKey object. - */ -CFIndex sslPrivKeyGetAlgorithmID(SSLPrivKey *privKey) -{ -#if TARGET_OS_IPHONE - return SecKeyGetAlgorithmID(SECKEYREF(privKey)); -#else - return SecKeyGetAlgorithmId(SECKEYREF(privKey)); -#endif -} - -/* - * Raw RSA/DSA sign/verify. - */ -OSStatus sslRawSign( - SSLContext *ctx, - SSLPrivKey *privKey, - const uint8_t *plainText, - size_t plainTextLen, - uint8_t *sig, // mallocd by caller; RETURNED - size_t sigLen, // available - size_t *actualBytes) // RETURNED -{ -#if 0 - RSAStatus rsaStatus; -#if RSA_SIG_SHARE_GIANT - RSASignBuffer *signBuffer = (RSASignBuffer *)sig; - assert(sigLen >= sizeof(RSASignBuffer)); -#endif - assert(actualBytes != NULL); - - /* @@@ Shouldn't need to init giSigLen according to libgRSA docs. */ - gi_uint16 giSigLen = sigLen; - - rsaStatus = RSA_Sign(&privKey->rsaKey, - RP_PKCS1, - plainText, - plainTextLen, -#if RSA_SIG_SHARE_GIANT - signBuffer, -#else - sig, -#endif - &giSigLen); - *actualBytes = giSigLen; - - return rsaStatus ? rsaStatusToSSL(rsaStatus) : errSecSuccess; -#else - - size_t inOutSigLen = sigLen; - - assert(actualBytes != NULL); - - OSStatus status = SecKeyRawSign(SECKEYREF(privKey), kSecPaddingPKCS1, - plainText, plainTextLen, sig, &inOutSigLen); - - if (status) { - sslErrorLog("sslRawSign: SecKeyRawSign failed (error %d)\n", (int)status); - } - - /* Since the KeyExchange already allocated modulus size bytes we'll - use all of them. SecureTransport has always sent that many bytes, - so we're not going to deviate, to avoid interoperability issues. */ - if (!status && (inOutSigLen < sigLen)) { - size_t offset = sigLen - inOutSigLen; - memmove(sig + offset, sig, inOutSigLen); - memset(sig, 0, offset); - inOutSigLen = sigLen; - } - - - *actualBytes = inOutSigLen; - return status; -#endif -} - -/* TLS 1.2 RSA signature */ -OSStatus sslRsaSign( - SSLContext *ctx, - SSLPrivKey *privKey, - const SecAsn1AlgId *algId, - const uint8_t *plainText, - size_t plainTextLen, - uint8_t *sig, // mallocd by caller; RETURNED - size_t sigLen, // available - size_t *actualBytes) // RETURNED -{ - size_t inOutSigLen = sigLen; - - assert(actualBytes != NULL); - - OSStatus status = SecKeySignDigest(SECKEYREF(privKey), algId, - plainText, plainTextLen, sig, &inOutSigLen); - - if (status) { - sslErrorLog("sslRsaSign: SecKeySignDigest failed (error %d)\n", (int) status); - } - - /* Since the KeyExchange already allocated modulus size bytes we'll - use all of them. SecureTransport has always sent that many bytes, - so we're not going to deviate, to avoid interoperability issues. */ - if (!status && (inOutSigLen < sigLen)) { - size_t offset = sigLen - inOutSigLen; - memmove(sig + offset, sig, inOutSigLen); - memset(sig, 0, offset); - inOutSigLen = sigLen; - } - - *actualBytes = inOutSigLen; - return status; -} - -OSStatus sslRawVerify( - SSLContext *ctx, - SSLPubKey *pubKey, - const uint8_t *plainText, - size_t plainTextLen, - const uint8_t *sig, - size_t sigLen) // available -{ -#if 0 - RSAStatus rsaStatus; - - rsaStatus = RSA_SigVerify(&pubKey->rsaKey, - RP_PKCS1, - plainText, - plainTextLen, - sig, - sigLen); - - return rsaStatus ? rsaStatusToSSL(rsaStatus) : errSecSuccess; -#else - OSStatus status = SecKeyRawVerify(SECKEYREF(pubKey), kSecPaddingPKCS1, - plainText, plainTextLen, sig, sigLen); - - if (status) { - sslErrorLog("sslRawVerify: SecKeyRawVerify failed (error %d)\n", (int) status); - } - - return status; -#endif -} - -/* TLS 1.2 RSA verify */ -OSStatus sslRsaVerify( - SSLContext *ctx, - SSLPubKey *pubKey, - const SecAsn1AlgId *algId, - const uint8_t *plainText, - size_t plainTextLen, - const uint8_t *sig, - size_t sigLen) // available -{ - OSStatus status = SecKeyVerifyDigest(SECKEYREF(pubKey), algId, - plainText, plainTextLen, sig, sigLen); - - if (status) { - sslErrorLog("sslRsaVerify: SecKeyVerifyDigest failed (error %d)\n", (int) status); - } - - return status; -} - -/* - * Encrypt/Decrypt - */ -OSStatus sslRsaEncrypt( - SSLContext *ctx, - SSLPubKey *pubKey, - const uint32_t padding, - const uint8_t *plainText, - size_t plainTextLen, - uint8_t *cipherText, // mallocd by caller; RETURNED - size_t cipherTextLen, // available - size_t *actualBytes) // RETURNED -{ -#if 0 - gi_uint16 giCipherTextLen = cipherTextLen; - RSAStatus rsaStatus; - - assert(actualBytes != NULL); - - rsaStatus = RSA_Encrypt(&pubKey->rsaKey, - RP_PKCS1, - getRandomByte, - plainText, - plainTextLen, - cipherText, - &giCipherTextLen); - *actualBytes = giCipherTextLen; - - return rsaStatus ? rsaStatusToSSL(rsaStatus) : errSecSuccess; -#else - size_t ctlen = cipherTextLen; - - assert(actualBytes != NULL); - -#if RSA_PUB_KEY_USAGE_HACK - /* Force key usage to allow encryption with public key */ - #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) - CSSM_KEY *cssmKey = NULL; - if (SecKeyGetCSSMKey(SECKEYREF(pubKey), (const CSSM_KEY **)&cssmKey)==errSecSuccess && cssmKey) - cssmKey->KeyHeader.KeyUsage |= CSSM_KEYUSE_ENCRYPT; - #endif -#endif - - OSStatus status = SecKeyEncrypt(SECKEYREF(pubKey), padding, - plainText, plainTextLen, cipherText, &ctlen); - - if (status) { - sslErrorLog("sslRsaEncrypt: SecKeyEncrypt failed (error %d)\n", (int)status); - } - - /* Since the KeyExchange already allocated modulus size bytes we'll - use all of them. SecureTransport has always sent that many bytes, - so we're not going to deviate, to avoid interoperability issues. */ - if (!status && (ctlen < cipherTextLen)) { - size_t offset = cipherTextLen - ctlen; - memmove(cipherText + offset, cipherText, ctlen); - memset(cipherText, 0, offset); - ctlen = cipherTextLen; - } - - if (actualBytes) - *actualBytes = ctlen; - - if (status) { - sslErrorLog("***sslRsaEncrypt: error %d\n", (int)status); - } - return status; -#endif -} - -OSStatus sslRsaDecrypt( - SSLContext *ctx, - SSLPrivKey *privKey, - const uint32_t padding, - const uint8_t *cipherText, - size_t cipherTextLen, - uint8_t *plainText, // mallocd by caller; RETURNED - size_t plainTextLen, // available - size_t *actualBytes) // RETURNED -{ -#if 0 - gi_uint16 giPlainTextLen = plainTextLen; - RSAStatus rsaStatus; - - assert(actualBytes != NULL); - - rsaStatus = RSA_Decrypt(&privKey->rsaKey, - RP_PKCS1, - cipherText, - cipherTextLen, - plainText, - &giPlainTextLen); - *actualBytes = giPlainTextLen; - - return rsaStatus ? rsaStatusToSSL(rsaStatus) : errSecSuccess; -#else - size_t ptlen = plainTextLen; - - assert(actualBytes != NULL); - - OSStatus status = SecKeyDecrypt(SECKEYREF(privKey), padding, - cipherText, cipherTextLen, plainText, &ptlen); - *actualBytes = ptlen; - - if (status) { - sslErrorLog("sslRsaDecrypt: SecKeyDecrypt failed (error %d)\n", (int)status); - } - - return status; -#endif -} - -/* - * Obtain size of the modulus of privKey in bytes. - */ -size_t sslPrivKeyLengthInBytes(SSLPrivKey *privKey) -{ -#if 0 - /* Get the length of p + q (which is the size of the modulus) in bits. */ - gi_uint16 bitLen = bitlen(&privKey->rsaKey.p.g) + - bitlen(&privKey->rsaKey.q.g); - /* Convert it to bytes. */ - return (bitLen + 7) / 8; -#else - return SecKeyGetBlockSize(SECKEYREF(privKey)); -#endif -} - -/* - * Obtain size of the modulus of pubKey in bytes. - */ -size_t sslPubKeyLengthInBytes(SSLPubKey *pubKey) -{ -#if 0 - /* Get the length of the modulus in bytes. */ - return giantNumBytes(&pubKey->rsaKey.n.g); -#else - return SecKeyGetBlockSize(SECKEYREF(pubKey)); -#endif -} - - -/* - * Obtain maximum size of signature in bytes. A bit of a kludge; we could - * ask the CSP to do this but that would be kind of expensive. - */ -OSStatus sslGetMaxSigSize( - SSLPrivKey *privKey, - size_t *maxSigSize) -{ - assert(maxSigSize != NULL); - -#if 0 -#if RSA_SIG_SHARE_GIANT - *maxSigSize = sizeof(RSASignBuffer); -#else - *maxSigSize = MAX_PRIME_SIZE_BYTES; -#endif -#else - *maxSigSize = SecKeyGetBlockSize(SECKEYREF(privKey)); -#endif - - return errSecSuccess; -} - -#if 0 -static OSStatus sslGiantToBuffer( - SSLContext *ctx, // Currently unused. - giant g, - SSLBuffer *buffer) -{ - gi_uint8 *chars; - gi_uint16 ioLen; - gi_uint16 zeroCount; - GIReturn giReturn; - OSStatus status; - - ioLen = serializeGiantBytes(g); - status = SSLAllocBuffer(buffer, ioLen); - if (status) - return status; - chars = buffer->data; - - /* Serialize the giant g into chars. */ - giReturn = serializeGiant(g, chars, &ioLen); - if(giReturn) { - SSLFreeBuffer(buffer); - return giReturnToSSL(giReturn); - } - - /* Trim off leading zeroes (but leave one zero if that's all there is). */ - for (zeroCount = 0; zeroCount < (ioLen - 1); ++zeroCount) - if (chars[zeroCount]) - break; - - if (zeroCount > 0) { - buffer->length = ioLen - zeroCount; - memmove(chars, chars + zeroCount, buffer->length); - } - - return status; -} - -/* - * Get raw key bits from an RSA public key. - */ -OSStatus sslGetPubKeyBits( - SSLContext *ctx, // Currently unused. - SSLPubKey *pubKey, - SSLBuffer *modulus, // data mallocd and RETURNED - SSLBuffer *exponent) // data mallocd and RETURNED -{ - OSStatus status; - - status = sslGiantToBuffer(ctx, &pubKey->rsaKey.n.g, modulus); - if(status) - return status; - - status = sslGiantToBuffer(ctx, &pubKey->rsaKey.e.g, exponent); - if(status) { - SSLFreeBuffer(modulus); - return status; - } - - return status; -} -#endif - -/* - * Given raw RSA key bits, cook up a SSLPubKey. Used in - * Server-initiated key exchange. - */ -OSStatus sslGetPubKeyFromBits( - SSLContext *ctx, - const SSLBuffer *modulus, - const SSLBuffer *exponent, - SSLPubKey **pubKey) // mallocd and RETURNED -{ - if (!pubKey) - return errSecParam; -#if 0 - SSLPubKey *key; - RSAStatus rsaStatus; - RSAPubKey apiKey = { - modulus->data, modulus->length, - NULL, 0, - exponent->data, exponent->length - }; - - key = sslMalloc(sizeof(*key)); - rsaStatus = rsaInitPubGKey(&apiKey, &key->rsaKey); - if (rsaStatus) { - sslFree(key); - return rsaStatusToSSL(rsaStatus); - } - - *pubKey = key; - return errSecSuccess; -#else - check(pubKey); - SecRSAPublicKeyParams params = { - modulus->data, modulus->length, - exponent->data, exponent->length - }; -#if SSL_DEBUG - sslDebugLog("Creating RSA pub key from modulus=%p len=%lu exponent=%p len=%lu\n", - modulus->data, modulus->length, - exponent->data, exponent->length); -#endif - SecKeyRef key = SecKeyCreateRSAPublicKey(NULL, (const uint8_t *)¶ms, - sizeof(params), kSecKeyEncodingRSAPublicParams); - if (!key) { - sslErrorLog("sslGetPubKeyFromBits: SecKeyCreateRSAPublicKey failed\n"); - return errSSLCrypto; - } -#if SSL_DEBUG - sslDebugLog("sslGetPubKeyFromBits: RSA pub key block size=%lu\n", SecKeyGetBlockSize(key)); -#endif - *pubKey = (SSLPubKey*)key; - return errSecSuccess; -#endif -} - -// MARK: - -// MARK: Public Certificate Functions - -#ifdef USE_SSLCERTIFICATE - -/* - * Given a SSLCertificate cert, obtain its public key as a SSLPubKey. - * Caller must sslFreePubKey and free the SSLPubKey itself. - */ -OSStatus sslPubKeyFromCert( - SSLContext *ctx, - const SSLCertificate *cert, - SSLPubKey **pubKey) // RETURNED -{ - DERItem der; - DERSignedCertCrl signedCert; - DERTBSCert tbsCert; - DERSubjPubKeyInfo pubKeyInfo; - DERByte numUnused; - DERItem pubKeyPkcs1; - SSLPubKey *key; - DERReturn drtn; - RSAStatus rsaStatus; - - assert(cert); - assert(pubKey != NULL); - - der.data = cert->derCert.data; - der.length = cert->derCert.length; - - /* top level decode */ - drtn = DERParseSequence(&der, DERNumSignedCertCrlItemSpecs, - DERSignedCertCrlItemSpecs, &signedCert, sizeof(signedCert)); - if(drtn) - return errSSLBadCert; - - /* decode the TBSCert - it was saved in full DER form */ - drtn = DERParseSequence(&signedCert.tbs, - DERNumTBSCertItemSpecs, DERTBSCertItemSpecs, - &tbsCert, sizeof(tbsCert)); - if(drtn) - return errSSLBadCert; - - /* sequence we're given: encoded DERSubjPubKeyInfo */ - drtn = DERParseSequenceContent(&tbsCert.subjectPubKey, - DERNumSubjPubKeyInfoItemSpecs, DERSubjPubKeyInfoItemSpecs, - &pubKeyInfo, sizeof(pubKeyInfo)); - if(drtn) - return errSSLBadCert; - - /* @@@ verify that this is an RSA key by decoding the AlgId */ - - /* - * The contents of pubKeyInfo.pubKey is a bit string whose contents - * are a PKCS1 format RSA key. - */ - drtn = DERParseBitString(&pubKeyInfo.pubKey, &pubKeyPkcs1, &numUnused); - if(drtn) - return errSSLBadCert; - -#if TARGET_OS_IPHONE - /* Now we have the public key in pkcs1 format. Let's make a public key - object out of it. */ - key = sslMalloc(sizeof(*key)); - rsaStatus = RSA_DecodePubKey(pubKeyPkcs1.data, pubKeyPkcs1.length, - &key->rsaKey); - if (rsaStatus) { - sslFree(key); - } -#else - SecKeyRef rsaPubKeyRef = SecKeyCreateRSAPublicKey(NULL, - pubKeyPkcs1.data, pubKeyPkcs1.length, - kSecKeyEncodingRSAPublicParams); - rsaStatus = (rsaPubKeyRef) ? 0 : 1; - key = (SSLPubKey*)rsaPubKeyRef; -#endif - if (rsaStatus) { - return rsaStatusToSSL(rsaStatus); - } - - *pubKey = key; - return errSecSuccess; -} - -/* - * Verify a chain of DER-encoded certs. - * First cert in a chain is root; this must also be present - * in ctx->trustedCerts. - * - * If arePeerCerts is true, host name verification is enabled and we - * save the resulting SecTrustRef in ctx->peerSecTrust. Otherwise - * we're just validating our own certs; no host name checking and - * peerSecTrust is transient. - */ - OSStatus sslVerifyCertChain( - SSLContext *ctx, - const SSLCertificate *certChain, - bool arePeerCerts) -{ - OSStatus ortn = errSecSuccess; - - assert(certChain); - - /* No point checking our own certs, our clients can do that. */ - if (!arePeerCerts) - return errSecSuccess; - - CertVerifyReturn cvrtn; - /* @@@ Add real cert checking. */ - if (certChain->next) { - DERItem subject, issuer; - - issuer.data = certChain->derCert.data; - issuer.length = certChain->derCert.length; - subject.data = certChain->next->derCert.data; - subject.length = certChain->next->derCert.length; - cvrtn = certVerify(&subject, &issuer); - if (cvrtn != CVR_Success) - ortn = errSSLBadCert; - } - else - { - sslErrorLog("***sslVerifyCertChain: only one cert in chain\n"); - } - return ortn; -} - -#else /* !USE_SSLCERTIFICATE */ - -OSStatus -sslCreateSecTrust( - SSLContext *ctx, - CFArrayRef certChain, - bool arePeerCerts, - SecTrustRef *pTrust) /* RETURNED */ -{ - OSStatus status = errSecAllocate; - CFStringRef peerDomainName = NULL; - CFTypeRef policies = NULL; - SecTrustRef trust = NULL; - - if (CFArrayGetCount(certChain) == 0) { - status = errSSLBadCert; - goto errOut; - } - - if (arePeerCerts) { - if (ctx->peerDomainNameLen && ctx->peerDomainName) { - CFIndex len = ctx->peerDomainNameLen; - if (ctx->peerDomainName[len - 1] == 0) { - len--; - //secwarning("peerDomainName is zero terminated!"); - } - /* @@@ Double check that this is the correct encoding. */ - require(peerDomainName = CFStringCreateWithBytes(kCFAllocatorDefault, - (const UInt8 *)ctx->peerDomainName, len, - kCFStringEncodingUTF8, false), errOut); - } - } - /* If we are the client, our peer certificates must satisfy the - ssl server policy. */ - bool server = ctx->protocolSide == kSSLClientSide; - require(policies = SecPolicyCreateSSL(server, peerDomainName), errOut); - - require_noerr(status = SecTrustCreateWithCertificates(certChain, policies, - &trust), errOut); - - /* If we have trustedAnchors we set them here. */ - if (ctx->trustedCerts) { - require_noerr(status = SecTrustSetAnchorCertificates(trust, - ctx->trustedCerts), errOut); - require_noerr(status = SecTrustSetAnchorCertificatesOnly(trust, - ctx->trustedCertsOnly), errOut); - } - - status = errSecSuccess; - -errOut: - CFReleaseSafe(peerDomainName); - CFReleaseSafe(policies); - - *pTrust = trust; - - return status; -} - -/* Return the first certificate reference from the supplied array - * whose data matches the given certificate, or NULL if none match. - */ -static -SecCertificateRef -sslGetMatchingCertInArray( - SecCertificateRef certRef, - CFArrayRef certArray) -{ - SecCertificateRef matchedCert = NULL; - - if (certRef == NULL || certArray == NULL) { - return NULL; - } - - CFDataRef certData = SecCertificateCopyData(certRef); - if (certData) { - CFIndex idx, count = CFArrayGetCount(certArray); - for(idx=0; idxtrustedCerts. - * - * If arePeerCerts is true, host name verification is enabled and we - * save the resulting SecTrustRef in ctx->peerSecTrust. Otherwise - * we're just validating our own certs; no host name checking and - * peerSecTrust is transient. - */ -extern OSStatus sslVerifyCertChain( - SSLContext *ctx, - CFArrayRef certChain, - bool arePeerCerts) -{ - OSStatus status; - SecTrustRef trust = NULL; - - assert(certChain); - - if (arePeerCerts) { - /* renegotiate - start with a new SecTrustRef */ - CFReleaseNull(ctx->peerSecTrust); - } - - status = sslCreateSecTrust(ctx, certChain, arePeerCerts, &trust); - - if (!ctx->enableCertVerify) { - /* trivial case, this is caller's responsibility */ - status = errSecSuccess; - goto errOut; - } - - SecTrustResultType secTrustResult; - require_noerr(status = SecTrustEvaluate(trust, &secTrustResult), errOut); - switch (secTrustResult) { - case kSecTrustResultUnspecified: - /* cert chain valid, no special UserTrust assignments */ - case kSecTrustResultProceed: - /* cert chain valid AND user explicitly trusts this */ - status = errSecSuccess; - break; - case kSecTrustResultDeny: - case kSecTrustResultConfirm: - case kSecTrustResultRecoverableTrustFailure: - default: - if(ctx->allowAnyRoot) { - sslErrorLog("***Warning: accepting unverified cert chain\n"); - status = errSecSuccess; - } - else { - /* - * If the caller provided a list of trusted leaf certs, check them here - */ - if(ctx->trustedLeafCerts) { - if (sslGetMatchingCertInArray((SecCertificateRef)CFArrayGetValueAtIndex(certChain, 0), - ctx->trustedLeafCerts)) { - status = errSecSuccess; - goto errOut; - } - } - status = errSSLXCertChainInvalid; - } - /* Do we really need to return things like: - errSSLNoRootCert - errSSLUnknownRootCert - errSSLCertExpired - errSSLCertNotYetValid - errSSLHostNameMismatch - for our client to see what went wrong, or should we just always - return - errSSLXCertChainInvalid - when something is wrong? */ - break; - } - -errOut: - if (arePeerCerts) - ctx->peerSecTrust = trust; - else - CFReleaseSafe(trust); - - return status; -} - -/* - * Given a SecCertificateRef cert, obtain its public key as a SSLPubKey. - * Caller must sslFreePubKey and free the SSLPubKey itself. - */ -extern OSStatus sslCopyPeerPubKey( - SSLContext *ctx, - SSLPubKey **pubKey) -{ - check(pubKey); - check(ctx->peerSecTrust); - - SecKeyRef key = SecTrustCopyPublicKey(ctx->peerSecTrust); - if (!key) { - sslErrorLog("sslCopyPeerPubKey: %s, ctx->peerSecTrust=%p\n", - "SecTrustCopyPublicKey failed", ctx->peerSecTrust); - return errSSLBadCert; - } - *pubKey = (SSLPubKey*)key; - - return errSecSuccess; -} - -#endif /* !USE_SSLCERTIFICATE */ - -#ifndef NDEBUG -void stPrintCdsaError(const char *op, OSStatus crtn) -{ - assert(FALSE); -} -#endif - -/* - * After ciphersuite negotiation is complete, verify that we have - * the capability of actually performing the selected cipher. - * Currently we just verify that we have a cert and private signing - * key, if needed, and that the signing key's algorithm matches the - * expected key exchange method. - * - * This is currently called from FindCipherSpec(), after it sets - * ctx->selectedCipherSpec to a (supposedly) valid value, and from - * sslBuildCipherSpecArray(), in server mode (pre-negotiation) only. - */ -OSStatus sslVerifySelectedCipher(SSLContext *ctx) -{ - if(ctx->protocolSide == kSSLClientSide) { - return errSecSuccess; - } -#if SSL_PAC_SERVER_ENABLE - if((ctx->masterSecretCallback != NULL) && - (ctx->sessionTicket.data != NULL)) { - /* EAP via PAC resumption; we can do it */ - return errSecSuccess; - } -#endif /* SSL_PAC_SERVER_ENABLE */ - - CFIndex requireAlg; - switch (ctx->selectedCipherSpecParams.keyExchangeMethod) { - case SSL_RSA: - case SSL_RSA_EXPORT: - case SSL_DH_RSA: - case SSL_DH_RSA_EXPORT: - case SSL_DHE_RSA: - case SSL_DHE_RSA_EXPORT: - requireAlg = kSecRSAAlgorithmID; - break; - case SSL_DHE_DSS: - case SSL_DHE_DSS_EXPORT: - case SSL_DH_DSS: - case SSL_DH_DSS_EXPORT: - requireAlg = kSecDSAAlgorithmID; - break; - case SSL_DH_anon: - case SSL_DH_anon_EXPORT: - case TLS_PSK: - requireAlg = kSecNullAlgorithmID; /* no signing key */ - break; - /* - * When SSL_ECDSA_SERVER is true and we support ECDSA on the server side, - * we'll need to add some logic here... - */ -#if SSL_ECDSA_SERVER - case SSL_ECDHE_ECDSA: - case SSL_ECDHE_RSA: - case SSL_ECDH_ECDSA: - case SSL_ECDH_RSA: - case SSL_ECDH_anon: - requireAlg = kSecECDSAAlgorithmID; - break; -#endif - - default: - /* needs update per cipherSpecs.c */ - assert(0); - sslErrorLog("sslVerifySelectedCipher: unknown key exchange method\n"); - return errSSLInternal; - } - - if(requireAlg == kSecNullAlgorithmID) { - return errSecSuccess; - } - - /* private signing key required */ - if(ctx->signingPrivKeyRef == NULL) { - sslErrorLog("sslVerifySelectedCipher: no signing key\n"); - return errSSLBadConfiguration; - } - - /* Check the alg of our signing key. */ - CFIndex keyAlg = sslPrivKeyGetAlgorithmID(ctx->signingPrivKeyRef); - if (requireAlg != keyAlg) { - sslErrorLog("sslVerifySelectedCipher: signing key alg mismatch\n"); - return errSSLBadConfiguration; - } - - return errSecSuccess; -} - -#if APPLE_DH - -/* FIXME: This is duplicated in SecDH */ -typedef struct { - DERItem p; - DERItem g; - DERItem l; -} DER_DHParams; - -static const DERItemSpec DER_DHParamsItemSpecs[] = -{ - { DER_OFFSET(DER_DHParams, p), - ASN1_INTEGER, - DER_DEC_NO_OPTS | DER_ENC_SIGNED_INT }, - { DER_OFFSET(DER_DHParams, g), - ASN1_INTEGER, - DER_DEC_NO_OPTS | DER_ENC_SIGNED_INT }, - { DER_OFFSET(DER_DHParams, l), - ASN1_INTEGER, - DER_DEC_OPTIONAL | DER_ENC_SIGNED_INT }, -}; -static const DERSize DER_NumDHParamsItemSpecs = -sizeof(DER_DHParamsItemSpecs) / sizeof(DERItemSpec); - -/* Max encoded size for standard (PKCS3) parameters */ -#define DH_ENCODED_PARAM_SIZE(primeSizeInBytes) \ -DER_MAX_ENCODED_SIZE( \ -DER_MAX_ENCODED_SIZE(primeSizeInBytes) + /* g */ \ -DER_MAX_ENCODED_SIZE(primeSizeInBytes) + /* p */ \ -DER_MAX_ENCODED_SIZE(4)) /* l */ - - -OSStatus sslDecodeDhParams( - const SSLBuffer *blob, /* Input - PKCS-3 encoded */ - SSLBuffer *prime, /* Output - wire format */ - SSLBuffer *generator) /* Output - wire format */ -{ - OSStatus ortn = errSecSuccess; - DERReturn drtn; - DERItem paramItem = {(DERByte *)blob->data, blob->length}; - DER_DHParams decodedParams; - - drtn = DERParseSequence(¶mItem, - DER_NumDHParamsItemSpecs, DER_DHParamsItemSpecs, - &decodedParams, sizeof(decodedParams)); - if(drtn) - return drtn; - - prime->data = decodedParams.p.data; - prime->length = decodedParams.p.length; - - generator->data = decodedParams.g.data; - generator->length = decodedParams.g.length; - - return ortn; -} - - -OSStatus sslEncodeDhParams(SSLBuffer *blob, /* data mallocd and RETURNED PKCS-3 encoded */ - const SSLBuffer *prime, /* Wire format */ - const SSLBuffer *generator) /* Wire format */ -{ - OSStatus ortn = errSecSuccess; - DER_DHParams derParams = - { - .p = { - .length = prime->length, - .data = prime->data, - }, - .g = { - .length = generator->length, - .data = generator->data, - }, - .l = { - .length = 0, - .data = NULL, - } - }; - - DERSize ioLen = DH_ENCODED_PARAM_SIZE(derParams.p.length); - DERByte *der = sslMalloc(ioLen); - // FIXME: What if this fails - we should probably not have a malloc here ? - assert(der); - ortn = (OSStatus)DEREncodeSequence(ASN1_CONSTR_SEQUENCE, - &derParams, - DER_NumDHParamsItemSpecs, DER_DHParamsItemSpecs, - der, - &ioLen); - // This should never fail - - blob->length=ioLen; - blob->data=der; - - return ortn; -} - -OSStatus sslDhCreateKey(SSLContext *ctx) -{ - if (ctx->secDHContext) { - SecDHDestroy(ctx->secDHContext); - ctx->secDHContext = NULL; - } - - /* Server params are set using encoded dh params */ - if (!(ctx->dhParamsEncoded.length && ctx->dhParamsEncoded.data)) - return errSSLInternal; - - if (SecDHCreateFromParameters(ctx->dhParamsEncoded.data, - ctx->dhParamsEncoded.length, &ctx->secDHContext)) - return errSSLCrypto; - - return errSecSuccess; -} - -OSStatus sslDhGenerateKeyPair(SSLContext *ctx) -{ - OSStatus ortn = errSecSuccess; - - require_noerr(ortn = SSLAllocBuffer(&ctx->dhExchangePublic, - SecDHGetMaxKeyLength(ctx->secDHContext)), out); - require_noerr(ortn = SecDHGenerateKeypair(ctx->secDHContext, - ctx->dhExchangePublic.data, &ctx->dhExchangePublic.length), out); - -out: - return ortn; -} - - -OSStatus sslDhKeyExchange(SSLContext *ctx) -{ - OSStatus ortn = errSecSuccess; - - if (ctx == NULL || - ctx->secDHContext == NULL || - ctx->dhPeerPublic.length == 0) { - /* comes from peer, don't panic */ - sslErrorLog("sslDhKeyExchange: null peer public key\n"); - return errSSLProtocol; - } - - require_noerr(ortn = SSLAllocBuffer(&ctx->preMasterSecret, - SecDHGetMaxKeyLength(ctx->secDHContext)), out); - require_noerr(ortn = SecDHComputeKey(ctx->secDHContext, - ctx->dhPeerPublic.data, ctx->dhPeerPublic.length, - ctx->preMasterSecret.data, &ctx->preMasterSecret.length), out); - - return ortn; -out: - sslErrorLog("sslDhKeyExchange: failed to compute key (error %d)\n", (int)ortn); - return ortn; -} - -#endif /* APPLE_DH */ - -/* - * Given an ECDSA key in SecKey format, extract the SSL_ECDSA_NamedCurve - * from its algorithm parameters. - */ -OSStatus sslEcdsaPeerCurve( - SSLPubKey *pubKey, - SSL_ECDSA_NamedCurve *namedCurve) -{ - /* Cast is safe because enums are kept in sync. */ - *namedCurve = (SSL_ECDSA_NamedCurve)SecECKeyGetNamedCurve(SECKEYREF(pubKey)); - if (*namedCurve == kSecECCurveNone) { - sslErrorLog("sslEcdsaPeerCurve: no named curve for public key\n"); - return errSSLProtocol; - } - return errSecSuccess; -} - -/* - * Generate ECDH key pair with the given SSL_ECDSA_NamedCurve. - * Private key, in ref form, is placed in ctx->ecdhPrivate. - * Public key, in ECPoint form - which can NOT be used as - * a key in any CSP ops - is placed in ecdhExchangePublic. - */ -OSStatus sslEcdhGenerateKeyPair( - SSLContext *ctx, - SSL_ECDSA_NamedCurve namedCurve) -{ - OSStatus ortn = errSecSuccess; - - ccec_const_cp_t cp; - switch (namedCurve) { - case SSL_Curve_secp256r1: - cp = ccec_cp_256(); - break; - case SSL_Curve_secp384r1: - cp = ccec_cp_384(); - break; - case SSL_Curve_secp521r1: - cp = ccec_cp_521(); - break; - default: - /* should not have gotten this far */ - sslErrorLog("sslEcdhGenerateKeyPair: bad namedCurve (%u)\n", - (unsigned)namedCurve); - return errSSLInternal; - } - - ccec_generate_key(cp, CCRNGSTATE, ctx->ecdhContext); - size_t pub_size = ccec_export_pub_size(ctx->ecdhContext); - SSLFreeBuffer(&ctx->ecdhExchangePublic); - require_noerr(ortn = SSLAllocBuffer(&ctx->ecdhExchangePublic, - pub_size), errOut); - ccec_export_pub(ctx->ecdhContext, ctx->ecdhExchangePublic.data); - - sslDebugLog("sslEcdhGenerateKeyPair: pub key size=%ld, data=%p\n", - pub_size, ctx->ecdhExchangePublic.data); - -errOut: - return ortn; -} - -/* - * Perform ECDH key exchange. Obtained key material is the same - * size as our private key. - * - * On entry, ecdhPrivate is our private key. The peer's public key - * is either ctx->ecdhPeerPublic for ECDHE exchange, or - * ctx->peerPubKey for ECDH exchange. - */ -OSStatus sslEcdhKeyExchange( - SSLContext *ctx, - SSLBuffer *exchanged) -{ - OSStatus ortn = errSecSuccess; - CFDataRef pubKeyData = NULL; - const unsigned char *pubKeyBits; - unsigned long pubKeyLen; - - switch(ctx->selectedCipherSpecParams.keyExchangeMethod) { - case SSL_ECDHE_ECDSA: - case SSL_ECDHE_RSA: - /* public key passed in as CSSM_DATA *Param */ - if(ctx->ecdhPeerPublic.length == 0) { - /* comes from peer, don't panic */ - sslErrorLog("sslEcdhKeyExchange: null peer public key\n"); - ortn = errSSLProtocol; - goto errOut; - } - pubKeyBits = ctx->ecdhPeerPublic.data; - pubKeyLen = ctx->ecdhPeerPublic.length; - break; - case SSL_ECDH_ECDSA: - case SSL_ECDH_RSA: - /* Use the public key provided by the peer. */ - if(ctx->peerPubKey == NULL) { - sslErrorLog("sslEcdhKeyExchange: no peer key\n"); - ortn = errSSLInternal; - goto errOut; - } - - pubKeyData = SecECKeyCopyPublicBits(SECKEYREF(ctx->peerPubKey)); - if (!pubKeyData) { - sslErrorLog("sslEcdhKeyExchange: SecECKeyCopyPublicBits failed\n"); - ortn = errSSLProtocol; - goto errOut; - } - pubKeyBits = CFDataGetBytePtr(pubKeyData); - pubKeyLen = CFDataGetLength(pubKeyData); - break; - default: - /* shouldn't be here */ - sslErrorLog("sslEcdhKeyExchange: unknown keyExchangeMethod (%d)\n", - ctx->selectedCipherSpecParams.keyExchangeMethod); - assert(0); - ortn = errSSLInternal; - goto errOut; - } - - ccec_const_cp_t cp = ccec_ctx_cp(ctx->ecdhContext); - ccec_pub_ctx_decl(ccn_sizeof(521), pubKey); - ccec_import_pub(cp, pubKeyLen, pubKeyBits, pubKey); - size_t len = 1 + 2 * ccec_ccn_size(cp); - require_noerr(ortn = SSLAllocBuffer(exchanged, len), errOut); - require_noerr(ccec_compute_key(ctx->ecdhContext, pubKey, &exchanged->length, exchanged->data), errOut); - - sslDebugLog("sslEcdhKeyExchange: exchanged key length=%ld, data=%p\n", - exchanged->length, exchanged->data); - -errOut: - CFReleaseSafe(pubKeyData); - return ortn; -} diff --git a/libsecurity_ssl/lib/sslCrypto.h b/libsecurity_ssl/lib/sslCrypto.h deleted file mode 100644 index fc4beaf1..00000000 --- a/libsecurity_ssl/lib/sslCrypto.h +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (c) 2006-2008,2010-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * 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@ - */ - -/* - * sslCrypto.h - interface between SSL and crypto libraries - */ - -#ifndef _SSL_CRYPTO_H_ -#define _SSL_CRYPTO_H_ 1 - -#include "ssl.h" -#include "sslContext.h" -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef NDEBUG -extern void stPrintCdsaError(const char *op, OSStatus crtn); -#else -#define stPrintCdsaError(o, cr) -#endif - -/* - * Free a pubKey object. - */ -extern OSStatus sslFreePubKey(SSLPubKey **pubKey); - -/* - * Free a privKey object. - */ -extern OSStatus sslFreePrivKey(SSLPrivKey **privKey); - -extern CFIndex sslPubKeyGetAlgorithmID(SSLPubKey *pubKey); -extern CFIndex sslPrivKeyGetAlgorithmID(SSLPrivKey *privKey); - -/* - * Create a new SecTrust object and return it. - */ -OSStatus -sslCreateSecTrust( - SSLContext *ctx, - CFArrayRef certChain, - bool arePeerCerts, - SecTrustRef *trust); /* RETURNED */ - - -/* - * Verify a cert chain. - */ -extern OSStatus sslVerifyCertChain( - SSLContext *ctx, -#ifdef USE_SSLCERTIFICATE - const SSLCertificate *certChain, -#else /* !USE_SSLCERTIFICATE */ - CFArrayRef certChain, -#endif /* !USE_SSLCERTIFICATE */ - bool arePeerCerts); - -/* - * Get the peer's public key from the certificate chain. - */ -extern OSStatus sslCopyPeerPubKey( - SSLContext *ctx, - SSLPubKey **pubKey); - - -/* - * Raw RSA/DSA sign/verify. - */ -OSStatus sslRawSign( - SSLContext *ctx, - SSLPrivKey *privKey, - const uint8_t *plainText, - size_t plainTextLen, - uint8_t *sig, // mallocd by caller; RETURNED - size_t sigLen, // available - size_t *actualBytes); // RETURNED - -OSStatus sslRawVerify( - SSLContext *ctx, - SSLPubKey *pubKey, - const uint8_t *plainText, - size_t plainTextLen, - const uint8_t *sig, - size_t sigLen); // available - -/* TLS 1.2 style RSA sign */ -OSStatus sslRsaSign( - SSLContext *ctx, - SSLPrivKey *privKey, - const SecAsn1AlgId *algId, - const uint8_t *plainText, - size_t plainTextLen, - uint8_t *sig, // mallocd by caller; RETURNED - size_t sigLen, // available - size_t *actualBytes); // RETURNED - -/* TLS 1.2 style RSA verify */ -OSStatus sslRsaVerify( - SSLContext *ctx, - SSLPubKey *pubKey, - const SecAsn1AlgId *algId, - const uint8_t *plainText, - size_t plainTextLen, - const uint8_t *sig, - size_t sigLen); // available - -/* - * Encrypt/Decrypt - */ -OSStatus sslRsaEncrypt( - SSLContext *ctx, - SSLPubKey *pubKey, -#ifdef USE_CDSA_CRYPTO - CSSM_CSP_HANDLE cspHand, -#endif - const uint32_t padding, - const uint8_t *plainText, - size_t plainTextLen, - uint8_t *cipherText, // mallocd by caller; RETURNED - size_t cipherTextLen, // available - size_t *actualBytes); // RETURNED -OSStatus sslRsaDecrypt( - SSLContext *ctx, - SSLPrivKey *privKey, - const uint32_t padding, - const uint8_t *cipherText, - size_t cipherTextLen, - uint8_t *plainText, // mallocd by caller; RETURNED - size_t plainTextLen, // available - size_t *actualBytes); // RETURNED - -/* - * Obtain size of key in bytes. - */ -extern size_t sslPrivKeyLengthInBytes( - SSLPrivKey *sslKey); - -extern size_t sslPubKeyLengthInBytes( - SSLPubKey *sslKey); - -/* Obtain max signature size in bytes. */ -extern OSStatus sslGetMaxSigSize( - SSLPrivKey *privKey, - size_t *maxSigSize); - -#if 0 -/* - * Get raw key bits from an RSA public key. - */ -OSStatus sslGetPubKeyBits( - SSLContext *ctx, - SSLPubKey *pubKey, - SSLBuffer *modulus, // data mallocd and RETURNED - SSLBuffer *exponent); // data mallocd and RETURNED -#endif - -/* - * Given raw RSA key bits, cook up a SSLPubKey. Used in - * Server-initiated key exchange. - */ -OSStatus sslGetPubKeyFromBits( - SSLContext *ctx, - const SSLBuffer *modulus, - const SSLBuffer *exponent, - SSLPubKey **pubKey); // mallocd and RETURNED - -OSStatus sslVerifySelectedCipher( - SSLContext *ctx); - -#if APPLE_DH -int sslDhGenerateParams(SSLContext *ctx, uint32_t g, size_t prime_size, - SSLBuffer *params, SSLBuffer *generator, SSLBuffer *prime); - -OSStatus sslDhCreateKey(SSLContext *ctx); -OSStatus sslDhGenerateKeyPair(SSLContext *ctx); -OSStatus sslDhKeyExchange(SSLContext *ctx); - -OSStatus sslDecodeDhParams( - const SSLBuffer *blob, /* Input - PKCS-3 encoded */ - SSLBuffer *prime, /* Output - wire format */ - SSLBuffer *generator); /* Output - wire format */ - -OSStatus sslEncodeDhParams( - SSLBuffer *blob, /* data mallocd and RETURNED - PKCS-3 encoded */ - const SSLBuffer *prime, /* Input - wire format */ - const SSLBuffer *generator); /* Input - wire format */ - -#endif /* APPLE_DH */ - -/* - * Given an ECDSA public key in CSSM format, extract the SSL_ECDSA_NamedCurve - * from its algorithm parameters. - */ -OSStatus sslEcdsaPeerCurve( - SSLPubKey *pubKey, - SSL_ECDSA_NamedCurve *namedCurve); -OSStatus sslEcdhGenerateKeyPair( - SSLContext *ctx, - SSL_ECDSA_NamedCurve namedCurve); -OSStatus sslEcdhKeyExchange( - SSLContext *ctx, - SSLBuffer *exchanged); - -#ifdef __cplusplus -} -#endif - - -#endif /* _SSL_CRYPTO_H_ */ diff --git a/libsecurity_ssl/lib/sslHandshake.c b/libsecurity_ssl/lib/sslHandshake.c deleted file mode 100644 index 6914908e..00000000 --- a/libsecurity_ssl/lib/sslHandshake.c +++ /dev/null @@ -1,1383 +0,0 @@ -/* - * Copyright (c) 1999-2001,2005-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * 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@ - */ - - -/* - * sslHandshake.c - SSL 3.0 handshake state machine. - */ - -#include "sslContext.h" -#include "sslHandshake.h" -#include "sslMemory.h" -#include "sslAlertMessage.h" -#include "sslSession.h" -#include "sslUtils.h" -#include "sslDebug.h" -#include "sslCrypto.h" -#include "sslRand.h" -#include "sslDigests.h" -#include "sslCipherSpecs.h" -#include "cipherSpecs.h" - -#include - -#include -#include -#include -#include - -#define REQUEST_CERT_CORRECT 0 - -#if __LP64__ -#define PRIstatus "d" -#else -#define PRIstatus "ld" -#endif - - -uint8_t * -SSLEncodeHandshakeHeader(SSLContext *ctx, SSLRecord *rec, SSLHandshakeType type, size_t msglen) -{ - uint8_t *charPtr; - - charPtr = rec->contents.data; - *charPtr++ = type; - charPtr = SSLEncodeSize(charPtr, msglen, 3); - - if(rec->protocolVersion == DTLS_Version_1_0) { - charPtr = SSLEncodeInt(charPtr, ctx->hdskMessageSeq, 2); - /* fragmentation -- we encode header as if unfragmented, - actual fragmentation happens at lower layer. */ - charPtr = SSLEncodeInt(charPtr, 0, 3); - charPtr = SSLEncodeSize(charPtr, msglen, 3); - } - - return charPtr; -} - -static OSStatus SSLProcessHandshakeMessage(SSLHandshakeMsg message, SSLContext *ctx); - -static OSStatus -SSLUpdateHandshakeMacs(const SSLBuffer *messageData, SSLContext *ctx) -{ - OSStatus err = errSSLInternal; - bool do_md5 = false; - bool do_sha1 = false; - bool do_sha256 = false; - bool do_sha384 = false; - - //TODO: We can stop updating the unecessary hashes once the CertVerify message is processed in case where we do Client Side Auth, or . - - if(ctx->negProtocolVersion == SSL_Version_Undetermined) - { - // we dont know yet, so we might need MD5 & SHA1 - Server should always call in with known protocol version. - assert(ctx->protocolSide==kSSLClientSide); - do_md5 = do_sha1 = true; - if(ctx->isDTLS - ? ctx->maxProtocolVersion < DTLS_Version_1_0 - : ctx->maxProtocolVersion >= TLS_Version_1_2) - { - // We wil need those too, unless we are sure we wont end up doing TLS 1.2 - do_sha256 = do_sha384 = true; - } - } else { - // we know which version we use at this point - if(sslVersionIsLikeTls12(ctx)) { - do_sha1 = do_sha256 = do_sha384 = true; - } else { - do_md5 = do_sha1 = true; - } - } - - if (do_md5 && - (err = SSLHashMD5.update(&ctx->md5State, messageData)) != 0) - goto done; - if (do_sha1 && - (err = SSLHashSHA1.update(&ctx->shaState, messageData)) != 0) - goto done; - if (do_sha256 && - (err = SSLHashSHA256.update(&ctx->sha256State, messageData)) != 0) - goto done; - if (do_sha384 && - (err = SSLHashSHA384.update(&ctx->sha512State, messageData)) != 0) - goto done; - - sslLogNegotiateDebug("%s protocol: %02X max: %02X cipher: %02X%s%s%s%s", - ctx->protocolSide == kSSLClientSide ? "client" : "server", - ctx->negProtocolVersion, - ctx->maxProtocolVersion, - ctx->selectedCipher, - do_md5 ? " md5" : "", - do_sha1 ? " sha1" : "", - do_sha256 ? " sha256" : "", - do_sha384 ? " sha384" : ""); -done: - return err; -} - -OSStatus -SSLProcessHandshakeRecord(SSLRecord rec, SSLContext *ctx) -{ OSStatus err; - size_t remaining; - UInt8 *p; - UInt8 *startingP; // top of record we're parsing - SSLHandshakeMsg message = {}; - SSLBuffer messageData; - - if (ctx->fragmentedMessageCache.data != 0) - { - size_t origLen = ctx->fragmentedMessageCache.length; - if ((err = SSLReallocBuffer(&ctx->fragmentedMessageCache, - ctx->fragmentedMessageCache.length + rec.contents.length)) != 0) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - memcpy(ctx->fragmentedMessageCache.data + origLen, - rec.contents.data, rec.contents.length); - remaining = ctx->fragmentedMessageCache.length; - p = ctx->fragmentedMessageCache.data; - } - else - { remaining = rec.contents.length; - p = rec.contents.data; - } - startingP = p; - - size_t head = 4; - - while (remaining > 0) - { - if (remaining < head) - break; /* we must have at least a header */ - - messageData.data = p; - message.type = (SSLHandshakeType)*p++; - message.contents.length = SSLDecodeSize(p, 3); - - - p += 3; - - if ((message.contents.length + head) > remaining) - break; - - message.contents.data = p; - p += message.contents.length; - messageData.length = head + message.contents.length; - assert(p == messageData.data + messageData.length); - - /* message fragmentation */ - remaining -= messageData.length; - if ((err = SSLProcessHandshakeMessage(message, ctx)) != 0) - return err; - - if (message.type != SSL_HdskHelloRequest) - - { if ((err = SSLUpdateHandshakeMacs(&messageData, ctx)) != 0) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - } - - if ((err = SSLAdvanceHandshake(message.type, ctx)) != 0) - return err; - } - - if (remaining > 0) /* Fragmented handshake message */ - { /* If there isn't a cache, allocate one */ - if (ctx->fragmentedMessageCache.data == 0) - { if ((err = SSLAllocBuffer(&ctx->fragmentedMessageCache, remaining))) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - } - if (startingP != ctx->fragmentedMessageCache.data) - { memcpy(ctx->fragmentedMessageCache.data, startingP, remaining); - ctx->fragmentedMessageCache.length = remaining; - } - } - else if (ctx->fragmentedMessageCache.data != 0) - { if ((err = SSLFreeBuffer(&ctx->fragmentedMessageCache))) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - } - - return errSecSuccess; -} - -OSStatus -DTLSProcessHandshakeRecord(SSLRecord rec, SSLContext *ctx) -{ OSStatus err = errSecParam; - size_t remaining; - UInt8 *p; - UInt8 *startingP; // top of record we're parsing - - const UInt32 head = 12; - - assert(ctx->isDTLS); - - remaining = rec.contents.length; - p = rec.contents.data; - startingP = p; - - while (remaining > 0) - { - UInt8 msgtype; - UInt32 msglen; - UInt32 msgseq; - UInt32 fraglen; - UInt32 fragofs; - - if (remaining < head) { - /* flush it - record is too small */ - sslErrorLog("DTLSProcessHandshakeRecord: remaining too small (%lu out of %lu)\n", remaining, rec.contents.length); - assert(0); // keep this assert until we find a test case that triggers it - err = errSSLProtocol; - goto flushit; - } - - /* Thats the 12 bytes of header : */ - msgtype = (SSLHandshakeType)*p++; - msglen = SSLDecodeInt(p, 3); p+=3; - msgseq = SSLDecodeInt(p, 2); p+=2; - fragofs = SSLDecodeInt(p, 3); p+=3; - fraglen = SSLDecodeInt(p, 3); p+=3; - - remaining -= head; - - SSLLogHdskMsg(msgtype, 0); - sslHdskMsgDebug("DTLS Hdsk Record: type=%u, len=%u, seq=%u (%u), f_ofs=%u, f_len=%u, remaining=%u", - msgtype, (int)msglen, (int)msgseq, (int)ctx->hdskMessageSeqNext, (int)fragofs, (int)fraglen, (int)remaining); - - if( - ((fraglen+fragofs) > msglen) - || (fraglen > remaining) - || (msgseq!=ctx->hdskMessageSeqNext) - || (fragofs!=ctx->hdskMessageCurrentOfs) - || (fragofs && (msgtype!=ctx->hdskMessageCurrent.type)) - || (fragofs && (msglen != ctx->hdskMessageCurrent.contents.length)) - ) - { - sslErrorLog("DTLSProcessHandshakeRecord: wrong fragment\n"); - // assert(0); // keep this assert until we find a test case that triggers it - // This is a recoverable error, we just drop this fragment. - // TODO: this should probably trigger a retransmit - err = errSecSuccess; - goto flushit; - } - - /* First fragment - allocate */ - if(fragofs==0) { - sslHdskMsgDebug("Allocating hdsk buf for msg type %d", msgtype); - assert(ctx->hdskMessageCurrent.contents.data==NULL); - assert(ctx->hdskMessageCurrent.contents.length==0); - if((err=SSLAllocBuffer(&(ctx->hdskMessageCurrent.contents), msglen))) { - SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - ctx->hdskMessageCurrent.type = msgtype; - } - - /* We have the next fragment, lets save it */ - memcpy(ctx->hdskMessageCurrent.contents.data + ctx->hdskMessageCurrentOfs, p, fraglen); - ctx->hdskMessageCurrentOfs+=fraglen; - p+=fraglen; - remaining-=fraglen; - - /* This was the last fragment, lets process the message */ - if(ctx->hdskMessageCurrentOfs == ctx->hdskMessageCurrent.contents.length) { - err = SSLProcessHandshakeMessage(ctx->hdskMessageCurrent, ctx); - if(err) - goto flushit; - - if ((msgtype != SSL_HdskHelloRequest) && (msgtype != SSL_HdskHelloVerifyRequest)) - { - /* We need to hash a fake header as if no fragmentation */ - uint8_t pseudo_header[head]; - SSLBuffer header; - header.data=pseudo_header; - header.length=head; - - pseudo_header[0]=msgtype; - SSLEncodeInt(pseudo_header+1, msglen, 3); - SSLEncodeInt(pseudo_header+4, msgseq, 2); - SSLEncodeInt(pseudo_header+6, 0, 3); - SSLEncodeInt(pseudo_header+9, msglen, 3); - - if ((err = SSLHashSHA1.update(&ctx->shaState, &header)) != 0 || - (err = SSLHashMD5.update(&ctx->md5State, &header)) != 0) - { - SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - goto flushit; - } - - SSLBuffer *messageData=&ctx->hdskMessageCurrent.contents; - if ((err = SSLHashSHA1.update(&ctx->shaState, messageData)) != 0 || - (err = SSLHashMD5.update(&ctx->md5State, messageData)) != 0) - { - SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - goto flushit; - } - - sslHdskMsgDebug("Hashing %d bytes of msg seq %d\n", (int)messageData->length, (int)msgseq); - } - - sslHdskMsgDebug("processed message of type %d", msgtype); - - if ((err = SSLAdvanceHandshake(msgtype, ctx)) != 0) - { - sslErrorLog("AdvanceHandshake error: %" PRIdOSStatus "\n", err); - goto flushit; - } - - /* Free the buffer for current message, and reset offset */ - SSLFreeBuffer(&(ctx->hdskMessageCurrent.contents)); - ctx->hdskMessageCurrentOfs=0; - - /* If we successfully processed a message, we wait for the next one */ - ctx->hdskMessageSeqNext++; - - } - - sslHdskMsgDebug("remaining = %ld", remaining); - } - - return errSecSuccess; - -flushit: - sslErrorLog("DTLSProcessHandshakeRecord: flusing record (err=%"PRIstatus")\n", err); - - /* This will flush the current handshake message */ - SSLFreeBuffer(&(ctx->hdskMessageCurrent.contents)); - ctx->hdskMessageCurrentOfs=0; - - return err; -} - -OSStatus -DTLSRetransmit(SSLContext *ctx) -{ - sslHdskMsgDebug("DTLSRetransmit in state %s. Last Sent = %d, Last Recv=%d, timeout=%f\n", - hdskStateToStr(ctx->state), ctx->hdskMessageSeq, ctx->hdskMessageSeqNext, ctx->timeout_duration); - - /* Too many retransmits, just give up!! */ - if(ctx->hdskMessageRetryCount>10) - return errSSLConnectionRefused; - - /* go back to previous cipher if retransmitting a flight including changecipherspec */ - if(ctx->messageQueueContainsChangeCipherSpec) { - OSStatus err; - err = ctx->recFuncs->rollbackWriteCipher(ctx->recCtx); - if(err) - return err; - } - - /* set timeout deadline */ - ctx->hdskMessageRetryCount++; - ctx->timeout_deadline = CFAbsoluteTimeGetCurrent()+((1<hdskMessageRetryCount)*ctx->timeout_duration); - - /* Lets resend the last flight */ - return SSLSendFlight(ctx); -} - -static OSStatus -SSLProcessHandshakeMessage(SSLHandshakeMsg message, SSLContext *ctx) -{ OSStatus err; - - err = errSecSuccess; - SSLLogHdskMsg(message.type, 0); - switch (message.type) - { case SSL_HdskHelloRequest: - if (ctx->protocolSide != kSSLClientSide) - goto wrongMessage; - if (message.contents.length > 0) - err = errSSLProtocol; - break; - case SSL_HdskClientHello: - if (ctx->state != SSL_HdskStateServerUninit) - goto wrongMessage; - err = SSLProcessClientHello(message.contents, ctx); - break; - case SSL_HdskServerHello: - if (ctx->state != SSL_HdskStateServerHello) - goto wrongMessage; - err = SSLProcessServerHello(message.contents, ctx); - break; -#if ENABLE_DTLS - case SSL_HdskHelloVerifyRequest: - if (ctx->protocolSide != kSSLClientSide) - goto wrongMessage; - if(ctx->state != SSL_HdskStateServerHello) - goto wrongMessage; - /* TODO: Do we need to check the client state here ? */ - err = SSLProcessServerHelloVerifyRequest(message.contents, ctx); - break; -#endif - case SSL_HdskCert: - if (ctx->state != SSL_HdskStateCert && - ctx->state != SSL_HdskStateClientCert) - goto wrongMessage; - err = SSLProcessCertificate(message.contents, ctx); - /* - * Note that cert evaluation can now be performed asynchronously, - * so SSLProcessCertificate may return errSSLWouldBlock here. - */ - break; - case SSL_HdskCertRequest: - if (((ctx->state != SSL_HdskStateHelloDone) && - (ctx->state != SSL_HdskStateKeyExchange)) - || ctx->certRequested) - goto wrongMessage; - err = SSLProcessCertificateRequest(message.contents, ctx); - if (ctx->breakOnCertRequest) - ctx->signalCertRequest = true; - break; - case SSL_HdskServerKeyExchange: - /* - * Since this message is optional for some key exchange - * mechanisms, and completely at the server's discretion, - * we need to be able to handle this in one of two states... - */ - switch(ctx->state) { - case SSL_HdskStateKeyExchange: /* explicitly waiting for this */ - case SSL_HdskStateHelloDone: - break; - default: - goto wrongMessage; - } - err = SSLProcessServerKeyExchange(message.contents, ctx); - break; - case SSL_HdskServerHelloDone: - if (ctx->state != SSL_HdskStateHelloDone) - goto wrongMessage; - err = SSLProcessServerHelloDone(message.contents, ctx); - break; - case SSL_HdskCertVerify: - if (ctx->state != SSL_HdskStateClientCertVerify) - goto wrongMessage; - err = SSLProcessCertificateVerify(message.contents, ctx); - assert(ctx->protocolSide == kSSLServerSide); - if(err) { - ctx->clientCertState = kSSLClientCertRejected; - } - break; - case SSL_HdskClientKeyExchange: - if (ctx->state != SSL_HdskStateClientKeyExchange) - goto wrongMessage; - err = SSLProcessKeyExchange(message.contents, ctx); - break; - case SSL_HdskFinished: - if (ctx->state != SSL_HdskStateFinished) - goto wrongMessage; - err = SSLProcessFinished(message.contents, ctx); - break; - default: - goto wrongMessage; - break; - } - - if (err && !ctx->sentFatalAlert) - { if (err == errSSLProtocol) - SSLFatalSessionAlert(SSL_AlertIllegalParam, ctx); - else if (err == errSSLNegotiation) - SSLFatalSessionAlert(SSL_AlertHandshakeFail, ctx); - else if (err != errSSLWouldBlock && - err != errSSLServerAuthCompleted /* == errSSLClientAuthCompleted */ && - err != errSSLClientCertRequested) - SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx); - } - return err; - -wrongMessage: - SSLFatalSessionAlert(SSL_AlertUnexpectedMsg, ctx); - return errSSLProtocol; -} - -/* - * Given a server-side SSLContext that's fully restored for a resumed session, - * queue up the remaining outgoing messages to finish the handshake. - */ -static OSStatus -SSLResumeServerSide( - SSLContext *ctx) -{ - OSStatus err; - if ((err = SSLPrepareAndQueueMessage(SSLEncodeServerHello, ctx)) != 0) - return err; - if ((err = SSLInitPendingCiphers(ctx)) != 0) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - if ((err = SSLPrepareAndQueueMessage(SSLEncodeChangeCipherSpec, - ctx)) != 0) - return err; - - if ((err = SSLPrepareAndQueueMessage(SSLEncodeFinishedMessage, - ctx)) != 0) - return err; - - SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec); - - return errSecSuccess; - -} - -OSStatus -SSLAdvanceHandshake(SSLHandshakeType processed, SSLContext *ctx) -{ OSStatus err; - SSLBuffer sessionIdentifier; - - SSLResetFlight(ctx); - - switch (processed) - { -#if ENABLE_DTLS - case SSL_HdskHelloVerifyRequest: - /* Just fall through */ -#endif - case SSL_HdskHelloRequest: - /* - * Reset the client auth state machine in case this is - * a renegotiation. - */ - ctx->certRequested = 0; - ctx->certSent = 0; - ctx->certReceived = 0; - ctx->x509Requested = 0; - ctx->clientCertState = kSSLClientCertNone; - ctx->readCipher_ready = 0; - ctx->writeCipher_ready = 0; - if ((err = SSLPrepareAndQueueMessage(SSLEncodeClientHello, ctx)) != 0) - return err; - SSLChangeHdskState(ctx, SSL_HdskStateServerHello); - break; - case SSL_HdskClientHello: - assert(ctx->protocolSide == kSSLServerSide); - ctx->sessionMatch = 0; - - if((ctx->negProtocolVersion==DTLS_Version_1_0) && (ctx->cookieVerified==false)) - { /* Send Hello Verify Request */ - if((err=SSLPrepareAndQueueMessage(SSLEncodeServerHelloVerifyRequest, ctx)) !=0 ) - return err; - break; - } - - #if SSL_PAC_SERVER_ENABLE - if((ctx->sessionTicket.data != NULL) && - (ctx->masterSecretCallback != NULL)) { - /* - * Client sent us a session ticket and we know how to ask - * the app for master secret. Go for it. - */ - size_t secretLen = SSL_MASTER_SECRET_SIZE; - sslEapDebug("Server side resuming based on masterSecretCallback"); - - /* the master secret callback requires serverRandom, now... */ - if ((err = SSLEncodeRandom(ctx->serverRandom, ctx)) != 0) - return err; - ctx->serverRandomValid = 1; - - ctx->masterSecretCallback(ctx, ctx->masterSecretArg, - ctx->masterSecret, &secretLen); - ctx->sessionMatch = 1; - /* set up selectedCipherSpec */ - if ((err = FindCipherSpec(ctx)) != 0) { - return err; - } - /* queue up remaining messages to finish handshake */ - if((err = SSLResumeServerSide(ctx)) != 0) - return err; - break; - } - #endif /* SSL_PAC_SERVER_ENABLE */ - if (ctx->sessionID.data != 0) - /* If session ID != 0, client is trying to resume */ - { if (ctx->resumableSession.data != 0) - { - SSLProtocolVersion sessionProt; - if ((err = SSLRetrieveSessionID(ctx->resumableSession, - &sessionIdentifier, ctx)) != 0) - return err; - if ((err = SSLRetrieveSessionProtocolVersion(ctx->resumableSession, - &sessionProt, ctx)) != 0) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - if ((sessionIdentifier.length == ctx->sessionID.length) && - (memcmp(sessionIdentifier.data, ctx->sessionID.data, - ctx->sessionID.length) == 0) && - (sessionProt == ctx->negProtocolVersion)) - { /* Everything matches; resume the session */ - sslLogResumSessDebug("===RESUMING SSL3 server-side session"); - if ((err = SSLInstallSessionFromData(ctx->resumableSession, - ctx)) != 0) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - ctx->sessionMatch = 1; - SSLFreeBuffer(&sessionIdentifier); - - /* queue up remaining messages to finish handshake */ - if((err = SSLResumeServerSide(ctx)) != 0) - return err; - break; - } - else { - sslLogResumSessDebug( - "===FAILED TO RESUME SSL3 server-side session"); - } - if ((err = SSLFreeBuffer(&sessionIdentifier)) != 0 || - (err = SSLDeleteSessionData(ctx)) != 0) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - } - if ((err = SSLFreeBuffer(&ctx->sessionID)) != 0) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - } - - /* - * If we get here, we're not resuming; generate a new session ID - * if we know our peer - */ - if (ctx->peerID.data != 0) - { /* Ignore errors; just treat as uncached session */ - assert(ctx->sessionID.data == 0); - err = SSLAllocBuffer(&ctx->sessionID, SSL_SESSION_ID_LEN); - if (err == 0) - { - if((err = sslRand(&ctx->sessionID)) != 0) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - } - } - - if ((err = SSLPrepareAndQueueMessage(SSLEncodeServerHello, ctx)) != 0) - return err; - switch (ctx->selectedCipherSpecParams.keyExchangeMethod) - { case SSL_NULL_auth: - #if APPLE_DH - case SSL_DH_anon: - case SSL_ECDH_anon: - if(ctx->clientAuth == kAlwaysAuthenticate) { - /* app requires this; abort */ - SSLFatalSessionAlert(SSL_AlertHandshakeFail, ctx); - return errSSLNegotiation; - } - ctx->tryClientAuth = false; - /* DH server side needs work */ - break; - #endif /* APPLE_DH */ - case TLS_PSK: - /* skip the cert */ - break; - - case SSL_RSA: - case SSL_DH_DSS: - case SSL_DH_RSA: - case SSL_DHE_DSS: - case SSL_DHE_RSA: - case SSL_ECDH_ECDSA: - case SSL_ECDHE_ECDSA: - case SSL_ECDH_RSA: - case SSL_ECDHE_RSA: - if(ctx->localCert == NULL) { - /* no cert but configured for, and negotiated, a - * ciphersuite which requires one */ - sslErrorLog("SSLAdvanceHandshake: No server key!\n"); - return errSSLBadConfiguration; - } - if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificate, - ctx)) != 0) - return err; - break; - - default: /* everything else */ - sslErrorLog("SSLAdvanceHandshake: Unsupported KEM!\n"); - return errSSLInternal; - } - /* - * At this point we decide whether to send a server key exchange - * method. For Apple servers, I think we'll ALWAYS do this, because - * of key usage restrictions (can't decrypt and sign with the same - * private key), but conceptually in this code, we do it if - * enabled by the presence of encryptPrivKey. - */ - { - bool doServerKeyExch = false; - switch(ctx->selectedCipherSpecParams.keyExchangeMethod) { - case SSL_RSA: - if(ctx->encryptPrivKeyRef != NULL) { - doServerKeyExch = true; - } - break; - case SSL_DH_anon: - case SSL_DHE_RSA: - case SSL_DHE_DSS: - doServerKeyExch = true; - break; - default: /* In all other cases, we don't send a ServerkeyExchange message */ - break; - } - if(doServerKeyExch) { - err = SSLPrepareAndQueueMessage(SSLEncodeServerKeyExchange, ctx); - if(err) { - return err; - } - } - } - if (ctx->tryClientAuth) - { if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificateRequest, - ctx)) != 0) - return err; - ctx->certRequested = 1; - ctx->clientCertState = kSSLClientCertRequested; - } - if ((err = SSLPrepareAndQueueMessage(SSLEncodeServerHelloDone, ctx)) != 0) - return err; - if (ctx->certRequested) { - SSLChangeHdskState(ctx, SSL_HdskStateClientCert); - } - else { - SSLChangeHdskState(ctx, SSL_HdskStateClientKeyExchange); - } - break; - case SSL_HdskServerHello: - ctx->sessionMatch = 0; - if (ctx->resumableSession.data != 0 && ctx->sessionID.data != 0) - { - SSLProtocolVersion sessionProt; - if ((err = SSLRetrieveSessionID(ctx->resumableSession, - &sessionIdentifier, ctx)) != 0) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - if ((err = SSLRetrieveSessionProtocolVersion(ctx->resumableSession, - &sessionProt, ctx)) != 0) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - if ((sessionIdentifier.length == ctx->sessionID.length) && - (memcmp(sessionIdentifier.data, ctx->sessionID.data, - ctx->sessionID.length) == 0) && - (sessionProt == ctx->negProtocolVersion)) - { /* Everything matches; resume the session */ - sslLogResumSessDebug("===RESUMING SSL3 client-side session"); - if ((err = SSLInstallSessionFromData(ctx->resumableSession, - ctx)) != 0 || - (err = SSLInitPendingCiphers(ctx)) != 0 || - (err = SSLFreeBuffer(&sessionIdentifier)) != 0) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - ctx->sessionMatch = 1; - SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec); - break; - } - else { - sslLogResumSessDebug("===FAILED TO RESUME SSL3 client-side " - "session"); - } - if ((err = SSLFreeBuffer(&sessionIdentifier)) != 0) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - } - switch (ctx->selectedCipherSpecParams.keyExchangeMethod) - { - /* these require a key exchange message */ - case SSL_NULL_auth: - case SSL_DH_anon: - SSLChangeHdskState(ctx, SSL_HdskStateKeyExchange); - break; - case SSL_RSA: - case SSL_DH_DSS: - case SSL_DH_RSA: - case SSL_RSA_EXPORT: - case SSL_DHE_DSS: - case SSL_DHE_RSA: - case SSL_Fortezza: - case SSL_ECDH_ECDSA: - case SSL_ECDHE_ECDSA: - case SSL_ECDH_RSA: - case SSL_ECDHE_RSA: - SSLChangeHdskState(ctx, SSL_HdskStateCert); - break; - case TLS_PSK: - SSLChangeHdskState(ctx, SSL_HdskStateHelloDone); - break; - default: - assert("Unknown key exchange method"); - break; - } - break; - case SSL_HdskCert: - if (ctx->state == SSL_HdskStateCert) - switch (ctx->selectedCipherSpecParams.keyExchangeMethod) - { case SSL_RSA: - /* - * I really think the two RSA cases should be - * handled the same here - the server key exchange is - * optional, and is up to the server. - * Note this isn't the same as SSL_SERVER_KEYEXCH_HACK; - * we're a client here. - */ - case SSL_DH_DSS: - case SSL_DH_RSA: - case SSL_ECDH_ECDSA: - case SSL_ECDH_RSA: - SSLChangeHdskState(ctx, SSL_HdskStateHelloDone); - break; - case SSL_DHE_DSS: - case SSL_DHE_RSA: - case SSL_Fortezza: - case SSL_ECDHE_ECDSA: - case SSL_ECDHE_RSA: - SSLChangeHdskState(ctx, SSL_HdskStateKeyExchange); - break; - default: - assert("Unknown or unexpected key exchange method"); - break; - } - else if (ctx->state == SSL_HdskStateClientCert) - { SSLChangeHdskState(ctx, SSL_HdskStateClientKeyExchange); - if (ctx->peerCert != 0) - ctx->certReceived = 1; - } - break; - case SSL_HdskCertRequest: - /* state stays in SSL_HdskStateHelloDone; distinction is in - * ctx->certRequested */ - if (ctx->peerCert == 0) - { SSLFatalSessionAlert(SSL_AlertHandshakeFail, ctx); - return errSSLProtocol; - } - assert(ctx->protocolSide == kSSLClientSide); - ctx->certRequested = 1; - ctx->clientCertState = kSSLClientCertRequested; - break; - case SSL_HdskServerKeyExchange: - SSLChangeHdskState(ctx, SSL_HdskStateHelloDone); - break; - case SSL_HdskServerHelloDone: - /* - * Waiting until server has sent hello done to interrupt and allow - * setting client cert, so we can send certificate, keyexchange and - * cert verify message together - */ - if (ctx->state != SSL_HdskStateClientCert) { - if (ctx->signalServerAuth) { - ctx->signalServerAuth = false; - SSLChangeHdskState(ctx, SSL_HdskStateClientCert); - return errSSLServerAuthCompleted; - } else if (ctx->signalCertRequest) { - ctx->signalCertRequest = false; - SSLChangeHdskState(ctx, SSL_HdskStateClientCert); - return errSSLClientCertRequested; - } else if (ctx->signalClientAuth) { - ctx->signalClientAuth = false; - return errSSLClientAuthCompleted; - } - } - - if (ctx->clientCertState == kSSLClientCertRequested) { - /* - * Server wants a client authentication cert - do - * we have one? - */ - if (ctx->localCert != 0 && ctx->x509Requested) { - if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificate, - ctx)) != 0) { - return err; - } - } - else { - /* response for no cert depends on protocol version */ - if(ctx->negProtocolVersion >= TLS_Version_1_0) { - /* TLS: send empty cert msg */ - if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificate, - ctx)) != 0) { - return err; - } - } - else { - /* SSL3: "no cert" alert */ - if ((err = SSLSendAlert(SSL_AlertLevelWarning, SSL_AlertNoCert_RESERVED, - ctx)) != 0) { - return err; - } - } - } /* no cert to send */ - } /* server requested a cert */ - if ((err = SSLPrepareAndQueueMessage(SSLEncodeKeyExchange, ctx)) != 0) - return err; - assert(ctx->sslTslCalls != NULL); - if ((err = ctx->sslTslCalls->generateMasterSecret(ctx)) != 0 || - (err = SSLInitPendingCiphers(ctx)) != 0) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - memset(ctx->preMasterSecret.data, 0, ctx->preMasterSecret.length); - if ((err = SSLFreeBuffer(&ctx->preMasterSecret))) { - return err; - } - if (ctx->certSent) { - /* Not all client auth mechanisms require a cert verify message */ - switch(ctx->negAuthType) { - case SSLClientAuth_RSASign: - case SSLClientAuth_ECDSASign: - if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificateVerify, - ctx)) != 0) { - return err; - } - break; - default: - break; - } - } - if ((err = SSLPrepareAndQueueMessage(SSLEncodeChangeCipherSpec, - ctx)) != 0) { - return err; - } - if ((err = SSLPrepareAndQueueMessage(SSLEncodeFinishedMessage, ctx)) != 0) - return err; - SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec); - break; - case SSL_HdskCertVerify: - SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec); - break; - case SSL_HdskClientKeyExchange: - assert(ctx->sslTslCalls != NULL); - if ((err = ctx->sslTslCalls->generateMasterSecret(ctx)) != 0 || - (err = SSLInitPendingCiphers(ctx)) != 0) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - memset(ctx->preMasterSecret.data, 0, ctx->preMasterSecret.length); - if ((err = SSLFreeBuffer(&ctx->preMasterSecret))) - return err; - if (ctx->certReceived) { - SSLChangeHdskState(ctx, SSL_HdskStateClientCertVerify); - } - else { - SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec); - } - break; - case SSL_HdskFinished: - /* Handshake is over; enable data transfer on read channel */ - ctx->readCipher_ready = 1; - /* If writePending is set, we haven't yet sent a finished message; - * send it */ - /* Note: If using session resumption, the client will hit this, otherwise the server will */ - if (ctx->writePending_ready != 0) - { if ((err = SSLPrepareAndQueueMessage(SSLEncodeChangeCipherSpec, - ctx)) != 0) - return err; - if ((err = SSLPrepareAndQueueMessage(SSLEncodeFinishedMessage, - ctx)) != 0) - return err; - } - if (ctx->protocolSide == kSSLServerSide) { - SSLChangeHdskState(ctx, SSL_HdskStateServerReady); - } - else { - SSLChangeHdskState(ctx, SSL_HdskStateClientReady); - } - if ((ctx->peerID.data != 0) && (ctx->sessionTicket.data == NULL)) { - /* note we avoid caching session data for PAC-style resumption */ - SSLAddSessionData(ctx); - } - break; - default: - assert(0); - break; - } - - /* We should have a full flight when we reach here, sending it for the first time */ - ctx->hdskMessageRetryCount = 0; - ctx->timeout_deadline = CFAbsoluteTimeGetCurrent() + ctx->timeout_duration; - return SSLSendFlight(ctx); -} - -OSStatus -SSLPrepareAndQueueMessage(EncodeMessageFunc msgFunc, SSLContext *ctx) -{ OSStatus err; - SSLRecord rec = {0, 0, {0, NULL}}; - WaitingMessage *out; - WaitingMessage *queue; - - if ((err = msgFunc(&rec, ctx)) != 0) - { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx); - goto fail; - } - - if (rec.contentType == SSL_RecordTypeHandshake) - { - if ((err = SSLUpdateHandshakeMacs(&rec.contents, ctx)) != 0) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - goto fail; - } - SSLLogHdskMsg((SSLHandshakeType)rec.contents.data[0], 1); - ctx->hdskMessageSeq++; - } - - err=errSSLInternal; - out = (WaitingMessage *)sslMalloc(sizeof(WaitingMessage)); - if(out==NULL) goto fail; - - out->next = NULL; - out->rec = rec; - - queue=ctx->messageWriteQueue; - if (queue == NULL) { - sslHdskMsgDebug("Queuing first message in flight\n"); - ctx->messageWriteQueue = out; - } else { - int n=1; - while (queue->next != 0) { - queue = queue->next; - n++; - } - sslHdskMsgDebug("Queuing message %d in flight\n", n); - queue->next = out; - } - - return errSecSuccess; -fail: - SSLFreeBuffer(&rec.contents); - return err; -} - -static -OSStatus SSLSendMessage(SSLRecord rec, SSLContext *ctx) -{ - OSStatus err; - - - if ((err = SSLWriteRecord(rec, ctx)) != 0) - return err; - if(rec.contentType == SSL_RecordTypeChangeCipher) { - /* Install new cipher spec on write side */ - /* Can't send data until Finished is sent */ - ctx->writeCipher_ready = 0; - ctx->wroteAppData = 0; - - if ((err = ctx->recFuncs->advanceWriteCipher(ctx->recCtx)) != 0) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - - /* pending cipher is invalid now - this is currently used to figure out if we need - to send out the last flight */ - ctx->writePending_ready = 0; - - /* TODO: that should only happen after Finished message is sent. */ - ctx->writeCipher_ready = 1; - } - - return errSecSuccess; -} - -static -OSStatus DTLSSendMessage(SSLRecord rec, SSLContext *ctx) -{ - OSStatus err=errSecSuccess; - - if(rec.contentType != SSL_RecordTypeHandshake) { - sslHdskMsgDebug("Not fragmenting message type=%d len=%d\n", (int)rec.contentType, (int)rec.contents.length); - if ((err = SSLWriteRecord(rec, ctx)) != 0) - return err; - if(rec.contentType == SSL_RecordTypeChangeCipher) { - /* Can't send data until Finished is sent */ - ctx->writeCipher_ready = 0; - ctx->wroteAppData = 0; - - /* Install new cipher spec on write side */ - if ((err = ctx->recFuncs->advanceWriteCipher(ctx->recCtx)) != 0) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - - /* pending cipher is invalid now - this is currently used to figure out if we need - to send out the last flight */ - ctx->writePending_ready = 0; - - /* TODO: that should only happen after Finished message is sent. See */ - ctx->writeCipher_ready = 1; - - } - } else { - /* fragmenting */ - SSLRecord fragrec; - - int msghead = 12; /* size of message header in DTLS */ - size_t fraglen; - size_t len = rec.contents.length-msghead; - UInt32 seq = SSLDecodeInt(rec.contents.data+4, 2); - (void) seq; // Suppress warnings - size_t ofs = 0; - - sslHdskMsgDebug("Fragmenting msg seq %d (rl=%d, ml=%d)", (int)seq, (int)rec.contents.length, - SSLDecodeInt(rec.contents.data+1, 3)); - - - SSLGetDatagramWriteSize(ctx, &fraglen); - fraglen -= msghead; - - fragrec.contentType = rec.contentType; - fragrec.protocolVersion = rec.protocolVersion; - if((err=SSLAllocBuffer(&fragrec.contents, fraglen + msghead))) - return err; - - /* copy the constant part of the header */ - memcpy(fragrec.contents.data,rec.contents.data, 6); - - while(len>fraglen) { - - sslHdskMsgDebug("Fragmenting msg seq %d (o=%d,l=%d)", (int)seq, (int)ofs, (int)fraglen); - - /* fragment offset and fragment length */ - SSLEncodeSize(fragrec.contents.data+6, ofs, 3); - SSLEncodeSize(fragrec.contents.data+9, fraglen, 3); - /* copy the payload */ - memcpy(fragrec.contents.data+msghead, rec.contents.data+msghead+ofs, fraglen); - if ((err = SSLWriteRecord(fragrec, ctx)) != 0) - goto cleanup; - len-=fraglen; - ofs+=fraglen; - } - - sslHdskMsgDebug("Fragmenting msg seq %d - Last Fragment (o=%d,l=%d)", (int)seq, (int)ofs, (int)len); - - /* last fragment */ - /* fragment offset and fragment length */ - SSLEncodeSize(fragrec.contents.data+6, ofs, 3); - SSLEncodeSize(fragrec.contents.data+9, len, 3); - /* copy the payload */ - memcpy(fragrec.contents.data+msghead, rec.contents.data+msghead+ofs, len); - fragrec.contents.length=len+msghead; - err = SSLWriteRecord(fragrec, ctx); - - cleanup: - /* Free the allocated fragment buffer */ - SSLFreeBuffer(&fragrec.contents); - - } - - return err; -} - - -OSStatus SSLResetFlight(SSLContext *ctx) -{ - OSStatus err; - WaitingMessage *queue; - WaitingMessage *next; - int n=0; - - queue=ctx->messageWriteQueue; - ctx->messageQueueContainsChangeCipherSpec=false; - - while(queue) { - n++; - err = SSLFreeBuffer(&queue->rec.contents); - if (err != 0) - goto fail; - next=queue->next; - sslFree(queue); - queue=next; - } - - ctx->messageWriteQueue=NULL; - - return errSecSuccess; -fail: - check_noerr(err); - return err; -} - -OSStatus SSLSendFlight(SSLContext *ctx) -{ - OSStatus err; - WaitingMessage *queue; - int n=0; - - queue=ctx->messageWriteQueue; - - while(queue) { - if (ctx->isDTLS) { - err=DTLSSendMessage(queue->rec, ctx); - } else { - err=SSLSendMessage(queue->rec, ctx); - } - if (err != 0) - goto fail; - queue=queue->next; - n++; - } - - return errSecSuccess; -fail: - check_noerr(err); - return err; -} - -OSStatus -SSL3ReceiveSSL2ClientHello(SSLRecord rec, SSLContext *ctx) -{ OSStatus err; - - if ((err = SSLInitMessageHashes(ctx)) != 0) - return err; - - if ((err = SSLHashSHA1.update(&ctx->shaState, &rec.contents)) != 0 || - (err = SSLHashMD5.update(&ctx->md5State, &rec.contents)) != 0) - { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - return err; - } - - if ((err = SSLAdvanceHandshake(SSL_HdskClientHello, ctx)) != 0) - return err; - - return errSecSuccess; -} - -/* - * Determine max enabled protocol, i.e., the one we try to negotiate for. - * Only returns an error (errSecParam) if NO protocols are enabled, which can - * in fact happen by malicious or ignorant use of SSLSetProtocolVersionEnabled(). - */ -OSStatus sslGetMaxProtVersion( - SSLContext *ctx, - SSLProtocolVersion *version) // RETURNED -{ - /* This check is here until SSLSetProtocolVersionEnabled() is gone .*/ - if (ctx->maxProtocolVersion == SSL_Version_Undetermined) - return errSecBadReq; - - *version = ctx->maxProtocolVersion; - return errSecSuccess; -} - - -/* log changes in handshake state */ -#ifndef NDEBUG -#include - -char *hdskStateToStr(SSLHandshakeState state) -{ - static char badStr[100]; - - switch(state) { - case SSL_HdskStateUninit: - return "Uninit"; - case SSL_HdskStateServerUninit: - return "ServerUninit"; - case SSL_HdskStateClientUninit: - return "ClientUninit"; - case SSL_HdskStateGracefulClose: - return "GracefulClose"; - case SSL_HdskStateErrorClose: - return "ErrorClose"; - case SSL_HdskStateNoNotifyClose: - return "NoNotifyClose"; - case SSL_HdskStateServerHello: - return "ServerHello"; - case SSL_HdskStateKeyExchange: - return "KeyExchange"; - case SSL_HdskStateCert: - return "Cert"; - case SSL_HdskStateHelloDone: - return "HelloDone"; - case SSL_HdskStateClientCert: - return "ClientCert"; - case SSL_HdskStateClientKeyExchange: - return "ClientKeyExchange"; - case SSL_HdskStateClientCertVerify: - return "ClientCertVerify"; - case SSL_HdskStateChangeCipherSpec: - return "ChangeCipherSpec"; - case SSL_HdskStateFinished: - return "Finished"; - case SSL_HdskStateServerReady: - return "SSL_ServerReady"; - case SSL_HdskStateClientReady: - return "SSL_ClientReady"; - default: - sprintf(badStr, "Unknown state (%d(d)", state); - return badStr; - } -} - -/* This is a macro in Release mode */ -void SSLChangeHdskState(SSLContext *ctx, SSLHandshakeState newState) -{ - sslHdskStateDebug("...hdskState = %s", hdskStateToStr(newState)); - ctx->state = newState; -} - -/* log handshake messages */ - -static char *hdskMsgToStr(SSLHandshakeType msg) -{ - static char badStr[100]; - - switch(msg) { - case SSL_HdskHelloRequest: - return "SSL_HdskHelloRequest"; - case SSL_HdskClientHello: - return "SSL_HdskClientHello"; - case SSL_HdskServerHello: - return "SSL_HdskServerHello"; - case SSL_HdskHelloVerifyRequest: - return "SSL_HdskHelloVerifyRequest"; - case SSL_HdskCert: - return "SSL_HdskCert"; - case SSL_HdskServerKeyExchange: - return "SSL_HdskServerKeyExchange"; - case SSL_HdskCertRequest: - return "SSL_HdskCertRequest"; - case SSL_HdskServerHelloDone: - return "SSL_HdskServerHelloDone"; - case SSL_HdskCertVerify: - return "SSL_HdskCertVerify"; - case SSL_HdskClientKeyExchange: - return "SSL_HdskClientKeyExchange"; - case SSL_HdskFinished: - return "SSL_HdskFinished"; - default: - sprintf(badStr, "Unknown msg (%d(d))", msg); - return badStr; - } -} - -void SSLLogHdskMsg(SSLHandshakeType msg, char sent) -{ - sslHdskMsgDebug("---%s handshake msg %s", - hdskMsgToStr(msg), (sent ? "sent" : "recv")); -} - -#endif /* NDEBUG */ - diff --git a/libsecurity_ssl/lib/sslHandshakeFinish.c b/libsecurity_ssl/lib/sslHandshakeFinish.c deleted file mode 100644 index 5a3f3a2f..00000000 --- a/libsecurity_ssl/lib/sslHandshakeFinish.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 1999-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * 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@ - */ - -/* - * sslHandshakeFinish.c - Finished and server hello done messages. - */ - -#include "sslContext.h" -#include "sslHandshake.h" -#include "sslMemory.h" -#include "sslDebug.h" -#include "sslUtils.h" -#include "sslDigests.h" - -#include -#include - -OSStatus -SSLEncodeFinishedMessage(SSLRecord *finished, SSLContext *ctx) -{ OSStatus err; - SSLBuffer finishedMsg; - Boolean isServerMsg; - unsigned finishedSize; - UInt8 *p; - int head; - - /* size and version depend on negotiatedProtocol */ - switch(ctx->negProtocolVersion) { - case SSL_Version_3_0: - finishedSize = 36; - break; - case DTLS_Version_1_0: - case TLS_Version_1_0: - case TLS_Version_1_1: - case TLS_Version_1_2: /* TODO: Support variable finishedSize. */ - finishedSize = 12; - break; - default: - assert(0); - return errSSLInternal; - } - finished->protocolVersion = ctx->negProtocolVersion; - - finished->contentType = SSL_RecordTypeHandshake; - /* msg = type + 3 bytes len + finishedSize */ - head = SSLHandshakeHeaderSize(finished); - if ((err = SSLAllocBuffer(&finished->contents, finishedSize + head)) != 0) - return err; - - p = SSLEncodeHandshakeHeader(ctx, finished, SSL_HdskFinished, finishedSize); - - finishedMsg.data = p; - finishedMsg.length = finishedSize; - - isServerMsg = (ctx->protocolSide == kSSLServerSide) ? true : false; - err = ctx->sslTslCalls->computeFinishedMac(ctx, finishedMsg, isServerMsg); - - if(err) - return err; - - /* Keep this around for secure renegotiation */ - SSLFreeBuffer(&ctx->ownVerifyData); - return SSLCopyBuffer(&finishedMsg, &ctx->ownVerifyData); -} - -OSStatus -SSLProcessFinished(SSLBuffer message, SSLContext *ctx) -{ OSStatus err; - SSLBuffer expectedFinished; - Boolean isServerMsg; - unsigned finishedSize; - - switch(ctx->negProtocolVersion) { - case SSL_Version_3_0: - finishedSize = 36; - break; - case DTLS_Version_1_0: - case TLS_Version_1_0: - case TLS_Version_1_1: - case TLS_Version_1_2: /* TODO: Support variable finishedSize. */ - finishedSize = 12; - break; - default: - assert(0); - return errSSLInternal; - } - if (message.length != finishedSize) { - sslErrorLog("SSLProcessFinished: msg len error 1\n"); - return errSSLProtocol; - } - expectedFinished.data = 0; - if ((err = SSLAllocBuffer(&expectedFinished, finishedSize))) - return err; - isServerMsg = (ctx->protocolSide == kSSLServerSide) ? false : true; - if ((err = ctx->sslTslCalls->computeFinishedMac(ctx, expectedFinished, isServerMsg)) != 0) - goto fail; - - if (memcmp(expectedFinished.data, message.data, finishedSize) != 0) - { - sslErrorLog("SSLProcessFinished: memcmp failure\n"); - err = errSSLProtocol; - goto fail; - } - - /* Keep this around for secure renegotiation */ - SSLFreeBuffer(&ctx->peerVerifyData); - err = SSLCopyBuffer(&expectedFinished, &ctx->peerVerifyData); - -fail: - SSLFreeBuffer(&expectedFinished); - return err; -} - -OSStatus -SSLEncodeServerHelloDone(SSLRecord *helloDone, SSLContext *ctx) -{ OSStatus err; - int head; - - helloDone->contentType = SSL_RecordTypeHandshake; - assert(ctx->negProtocolVersion >= SSL_Version_3_0); - helloDone->protocolVersion = ctx->negProtocolVersion; - head = SSLHandshakeHeaderSize(helloDone); - if ((err = SSLAllocBuffer(&helloDone->contents, head))) - return err; - - SSLEncodeHandshakeHeader(ctx, helloDone, SSL_HdskServerHelloDone, 0); /* Message has 0 length */ - - return errSecSuccess; -} - -OSStatus -SSLProcessServerHelloDone(SSLBuffer message, SSLContext *ctx) -{ assert(ctx->protocolSide == kSSLClientSide); - if (message.length != 0) { - sslErrorLog("SSLProcessServerHelloDone: nonzero msg len\n"); - return errSSLProtocol; - } - return errSecSuccess; -} diff --git a/libsecurity_ssl/lib/sslHandshakeHello.c b/libsecurity_ssl/lib/sslHandshakeHello.c deleted file mode 100644 index 81daee81..00000000 --- a/libsecurity_ssl/lib/sslHandshakeHello.c +++ /dev/null @@ -1,1030 +0,0 @@ -/* - * Copyright (c) 1999-2001,2005-2008,2010-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * 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@ - */ - -/* - * sslHandshakeHello.c - Support for client hello and server hello messages. - */ - -#include "sslContext.h" -#include "sslHandshake.h" -#include "sslMemory.h" -#include "sslSession.h" -#include "sslUtils.h" -#include "sslDebug.h" -#include "sslCrypto.h" -#include "sslRand.h" -#include "sslDigests.h" -#include "sslCipherSpecs.h" - -#include -#include -#include - -#include - -/* - * Given a protocol version sent by peer, determine if we accept that version - * and downgrade if appropriate (which can not be done for the client side). - */ -static -OSStatus sslVerifyProtVersion( - SSLContext *ctx, - SSLProtocolVersion peerVersion, // sent by peer - SSLProtocolVersion *negVersion) // final negotiated version if return success -{ - if ((ctx->isDTLS) - ? peerVersion > ctx->minProtocolVersion - : peerVersion < ctx->minProtocolVersion) { - return errSSLNegotiation; - } - if ((ctx->isDTLS) - ? peerVersion < ctx->maxProtocolVersion - : peerVersion > ctx->maxProtocolVersion) { - if (ctx->protocolSide == kSSLClientSide) { - return errSSLNegotiation; - } - *negVersion = ctx->maxProtocolVersion; - } else { - *negVersion = peerVersion; - } - - return errSecSuccess; -} - - -/* IE treats null session id as valid; two consecutive sessions with NULL ID - * are considered a match. Workaround: when resumable sessions are disabled, - * send a random session ID. */ -#define SSL_IE_NULL_RESUME_BUG 1 -#if SSL_IE_NULL_RESUME_BUG -#define SSL_NULL_ID_LEN 32 /* length of bogus session ID */ -#endif - -OSStatus -SSLEncodeServerHello(SSLRecord *serverHello, SSLContext *ctx) -{ OSStatus err; - UInt8 *charPtr; - int sessionIDLen; - size_t msglen; - int head; - - sessionIDLen = 0; - if (ctx->sessionID.data != 0) - sessionIDLen = (UInt8)ctx->sessionID.length; - #if SSL_IE_NULL_RESUME_BUG - if(sessionIDLen == 0) { - sessionIDLen = SSL_NULL_ID_LEN; - } - #endif /* SSL_IE_NULL_RESUME_BUG */ - - msglen = 38 + sessionIDLen; - - /* this was set to a known quantity in SSLProcessClientHello */ - check(ctx->negProtocolVersion != SSL_Version_Undetermined); - /* should not be here in this case */ - check(ctx->negProtocolVersion != SSL_Version_2_0); - sslLogNegotiateDebug("===SSL3 server: sending version %d_%d", - ctx->negProtocolVersion >> 8, ctx->negProtocolVersion & 0xff); - sslLogNegotiateDebug("...sessionIDLen = %d", sessionIDLen); - serverHello->protocolVersion = ctx->negProtocolVersion; - serverHello->contentType = SSL_RecordTypeHandshake; - head = SSLHandshakeHeaderSize(serverHello); - if ((err = SSLAllocBuffer(&serverHello->contents, msglen + head))) - return err; - - charPtr = SSLEncodeHandshakeHeader(ctx, serverHello, SSL_HdskServerHello, msglen); - - charPtr = SSLEncodeInt(charPtr, serverHello->protocolVersion, 2); - - #if SSL_PAC_SERVER_ENABLE - /* serverRandom might have already been set, in SSLAdvanceHandshake() */ - if(!ctx->serverRandomValid) { - if ((err = SSLEncodeRandom(ctx->serverRandom, ctx)) != 0) { - return err; - } - } - #else - /* This is the normal production code path */ - if ((err = SSLEncodeRandom(ctx->serverRandom, ctx)) != 0) - return err; - #endif /* SSL_PAC_SERVER_ENABLE */ - - memcpy(charPtr, ctx->serverRandom, SSL_CLIENT_SRVR_RAND_SIZE); - - charPtr += SSL_CLIENT_SRVR_RAND_SIZE; - *(charPtr++) = (UInt8)sessionIDLen; - #if SSL_IE_NULL_RESUME_BUG - if(ctx->sessionID.data != NULL) { - /* normal path for enabled resumable session */ - memcpy(charPtr, ctx->sessionID.data, sessionIDLen); - } - else { - /* IE workaround */ - SSLBuffer rb; - rb.data = charPtr; - rb.length = SSL_NULL_ID_LEN; - sslRand(&rb); - } - #else - if (sessionIDLen > 0) - memcpy(charPtr, ctx->sessionID.data, sessionIDLen); - #endif /* SSL_IE_NULL_RESUME_BUG */ - charPtr += sessionIDLen; - charPtr = SSLEncodeInt(charPtr, ctx->selectedCipher, 2); - *(charPtr++) = 0; /* Null compression */ - - sslLogNegotiateDebug("ssl3: server specifying cipherSuite 0x%lx", - (unsigned long)ctx->selectedCipher); - - assert(charPtr == serverHello->contents.data + serverHello->contents.length); - - return errSecSuccess; -} - -OSStatus -SSLEncodeServerHelloVerifyRequest(SSLRecord *helloVerifyRequest, SSLContext *ctx) -{ OSStatus err; - UInt8 *charPtr; - size_t msglen; - int head; - - assert(ctx->protocolSide == kSSLServerSide); - assert(ctx->negProtocolVersion == DTLS_Version_1_0); - assert(ctx->dtlsCookie.length); - - msglen = 3 + ctx->dtlsCookie.length; - - helloVerifyRequest->protocolVersion = DTLS_Version_1_0; - helloVerifyRequest->contentType = SSL_RecordTypeHandshake; - head = SSLHandshakeHeaderSize(helloVerifyRequest); - if ((err = SSLAllocBuffer(&helloVerifyRequest->contents, msglen + head))) - return err; - - charPtr = SSLEncodeHandshakeHeader(ctx, helloVerifyRequest, SSL_HdskHelloVerifyRequest, msglen); - - charPtr = SSLEncodeInt(charPtr, helloVerifyRequest->protocolVersion, 2); - - *charPtr++ = ctx->dtlsCookie.length; - memcpy(charPtr, ctx->dtlsCookie.data, ctx->dtlsCookie.length); - charPtr += ctx->dtlsCookie.length; - - assert(charPtr == (helloVerifyRequest->contents.data + helloVerifyRequest->contents.length)); - - return errSecSuccess; -} - - -OSStatus -SSLProcessServerHelloVerifyRequest(SSLBuffer message, SSLContext *ctx) -{ OSStatus err; - SSLProtocolVersion protocolVersion; - unsigned int cookieLen; - UInt8 *p; - - assert(ctx->protocolSide == kSSLClientSide); - - /* TODO: those length values should not be hardcoded */ - /* 3 bytes at least with empty cookie */ - if (message.length < 3 ) { - sslErrorLog("SSLProcessServerHelloVerifyRequest: msg len error\n"); - return errSSLProtocol; - } - p = message.data; - - protocolVersion = (SSLProtocolVersion)SSLDecodeInt(p, 2); - p += 2; - - /* TODO: Not clear what else to do with protocol version here */ - if(protocolVersion != DTLS_Version_1_0) { - sslErrorLog("SSLProcessServerHelloVerifyRequest: protocol version error\n"); - return errSSLProtocol; - } - - cookieLen = *p++; - sslLogNegotiateDebug("cookieLen = %d, msglen=%d\n", (int)cookieLen, (int)message.length); - /* TODO: hardcoded '15' again */ - if (message.length < (3 + cookieLen)) { - sslErrorLog("SSLProcessServerHelloVerifyRequest: msg len error 2\n"); - return errSSLProtocol; - } - - err = SSLAllocBuffer(&ctx->dtlsCookie, cookieLen); - if (err == 0) - memcpy(ctx->dtlsCookie.data, p, cookieLen); - - return err; -} - -static void -SSLProcessServerHelloExtension_SecureRenegotiation(SSLContext *ctx, UInt16 extLen, UInt8 *p) -{ - if(extLen!= (1 + ctx->ownVerifyData.length + ctx->peerVerifyData.length)) - return; - - if(*p!=ctx->ownVerifyData.length + ctx->ownVerifyData.length) - return; - p++; - - if(memcmp(p, ctx->ownVerifyData.data, ctx->ownVerifyData.length)) - return; - p+=ctx->ownVerifyData.length; - - if(memcmp(p, ctx->peerVerifyData.data, ctx->peerVerifyData.length)) - return; - - ctx->secure_renegotiation_received = true; -} - - -static OSStatus -SSLProcessServerHelloExtensions(SSLContext *ctx, UInt16 extensionsLen, UInt8 *p) -{ - Boolean got_secure_renegotiation = false; - UInt16 remaining; - - if(extensionsLen<2) { - sslErrorLog("SSLProcessHelloExtensions: need a least 2 bytes\n"); - return errSSLProtocol; - } - - remaining = SSLDecodeInt(p, 2); p+=2; - extensionsLen -=2; - - /* remaining = number of bytes remaining to process according to buffer data */ - /* extensionsLen = number of bytes in the buffer */ - - if(remaining>extensionsLen) { - sslErrorLog("SSLProcessHelloExtensions: ext len error 1\n"); - return errSSLProtocol; - } - - if(remainingprotocolSide == kSSLClientSide); - - if (message.length < 38) { - sslErrorLog("SSLProcessServerHello: msg len error\n"); - return errSSLProtocol; - } - p = message.data; - - protocolVersion = (SSLProtocolVersion)SSLDecodeInt(p, 2); - p += 2; - /* FIXME this should probably send appropriate alerts */ - err = sslVerifyProtVersion(ctx, protocolVersion, &negVersion); - if(err) { - return err; - } - ctx->negProtocolVersion = negVersion; - switch(negVersion) { - case SSL_Version_3_0: - ctx->sslTslCalls = &Ssl3Callouts; - break; - case TLS_Version_1_0: - case TLS_Version_1_1: - case DTLS_Version_1_0: - ctx->sslTslCalls = &Tls1Callouts; - break; - case TLS_Version_1_2: - ctx->sslTslCalls = &Tls12Callouts; - break; - default: - return errSSLNegotiation; - } - err = ctx->recFuncs->setProtocolVersion(ctx->recCtx, negVersion); - if(err) { - return err; - } - - sslLogNegotiateDebug("===SSL3 client: negVersion is %d_%d", - (negVersion >> 8) & 0xff, negVersion & 0xff); - - memcpy(ctx->serverRandom, p, 32); - p += 32; - - sessionIDLen = *p++; - if (message.length < (38 + sessionIDLen)) { - sslErrorLog("SSLProcessServerHello: msg len error 2\n"); - return errSSLProtocol; - } - if (sessionIDLen > 0 && ctx->peerID.data != 0) - { /* Don't die on error; just treat it as an uncached session */ - if (ctx->sessionID.data) - SSLFreeBuffer(&ctx->sessionID); - err = SSLAllocBuffer(&ctx->sessionID, sessionIDLen); - if (err == 0) - memcpy(ctx->sessionID.data, p, sessionIDLen); - } - p += sessionIDLen; - - ctx->selectedCipher = (UInt16)SSLDecodeInt(p,2); - sslLogNegotiateDebug("===ssl3: server requests cipherKind %x", - (unsigned)ctx->selectedCipher); - p += 2; - if ((err = FindCipherSpec(ctx)) != 0) { - return err; - } - - if (*p++ != 0) /* Compression */ - return errSecUnimplemented; - - /* Process ServerHello extensions */ - extensionsLen = message.length - (38 + sessionIDLen); - - if(extensionsLen) { - err = SSLProcessServerHelloExtensions(ctx, extensionsLen, p); - if(err) - return err; - } - - /* RFC 5746: Make sure the renegotiation is secure */ - if(ctx->secure_renegotiation && !ctx->secure_renegotiation_received) - return errSSLNegotiation; - - if(ctx->secure_renegotiation_received) - ctx->secure_renegotiation = true; - - - /* - * Note: the server MAY send a SSL_HE_EC_PointFormats extension if - * we've negotiated an ECDSA ciphersuite...but - * a) the provided format list MUST contain SSL_PointFormatUncompressed per - * RFC 4492 5.2; and - * b) The uncompressed format is the only one we support. - * - * Thus we drop a possible incoming SSL_HE_EC_PointFormats extension here. - * IF we ever support other point formats, we have to parse the extension - * to see what the server supports. - */ - return errSecSuccess; -} - -OSStatus -SSLEncodeClientHello(SSLRecord *clientHello, SSLContext *ctx) -{ - size_t length; - unsigned i; - OSStatus err; - unsigned char *p; - SSLBuffer sessionIdentifier = { 0, NULL }; - size_t sessionIDLen; - size_t sessionTicketLen = 0; - size_t serverNameLen = 0; - size_t pointFormatLen = 0; - size_t suppCurveLen = 0; - size_t signatureAlgorithmsLen = 0; - size_t totalExtenLen = 0; - UInt16 numCipherSuites; - int head; - - assert(ctx->protocolSide == kSSLClientSide); - - clientHello->contents.length = 0; - clientHello->contents.data = NULL; - - sessionIDLen = 0; - if (ctx->resumableSession.data != 0) - { if ((err = SSLRetrieveSessionID(ctx->resumableSession, - &sessionIdentifier, ctx)) != 0) - { return err; - } - sessionIDLen = sessionIdentifier.length; - } - - /* - * Since we're not in SSLv2 compatibility mode, only count non-SSLv2 ciphers. - */ -#if ENABLE_SSLV2 - numCipherSuites = ctx->numValidNonSSLv2Specs; -#else - numCipherSuites = ctx->numValidCipherSuites; -#endif - - /* RFC 5746 : add the fake ciphersuite unless we are including the extension */ - if(!ctx->secure_renegotiation) - numCipherSuites+=1; - - length = 39 + 2*numCipherSuites + sessionIDLen; - - /* We always use the max enabled version in the ClientHello.client_version, - even in the renegotiation case. This value is saved in the context so it - can be used in the RSA key exchange */ - err = sslGetMaxProtVersion(ctx, &ctx->clientReqProtocol); - if(err) { - /* we don't have a protocol enabled */ - goto err_exit; - } - - /* RFC 5746: If are starting a new handshake, so we didnt received this yet */ - ctx->secure_renegotiation_received = false; - - /* This is the protocol version used at the record layer, If we already - negotiated the protocol version previously, we should just use that, - otherwise we use the the minimum supported version. - We do not always use the minimum version because some TLS only servers - will reject an SSL 3 version in client_hello. - */ - if(ctx->negProtocolVersion != SSL_Version_Undetermined) { - clientHello->protocolVersion = ctx->negProtocolVersion; - } else { - if(ctx->minProtocolVersionmaxProtocolVersion>=TLS_Version_1_0) - clientHello->protocolVersion = TLS_Version_1_0; - else - clientHello->protocolVersion = ctx->minProtocolVersion; - } - -#if ENABLE_DTLS - if(clientHello->protocolVersion == DTLS_Version_1_0) { - /* extra space for cookie */ - /* TODO: cookie len - 0 for now */ - length += 1 + ctx->dtlsCookie.length; - sslLogNegotiateDebug("==DTLS Hello: len=%lu\n", length); - } - /* Because of the way the version number for DTLS is encoded, - the following code mean that you can use extensions with DTLS... */ -#endif /* ENABLE_DTLS */ - - /* RFC 5746: We add the extension only for renegotiation ClientHello */ - if(ctx->secure_renegotiation) { - totalExtenLen += 2 + /* extension type */ - 2 + /* extension length */ - 1 + /* lenght of renegotiated_conection (client verify data) */ - ctx->ownVerifyData.length; - } - - /* prepare for optional ClientHello extensions */ - if((ctx->clientReqProtocol >= TLS_Version_1_0) && - (ctx->peerDomainName != NULL) && - (ctx->peerDomainNameLen != 0)) { - serverNameLen = 2 + /* extension type */ - 2 + /* 2-byte vector length, extension_data */ - 2 + /* length of server_name_list */ - 1 + /* length of name_type */ - 2 + /* length of HostName */ - ctx->peerDomainNameLen; - totalExtenLen += serverNameLen; - } - if(ctx->sessionTicket.length) { - sessionTicketLen = 2 + /* extension type */ - 2 + /* 2-byte vector length, extension_data */ - ctx->sessionTicket.length; - totalExtenLen += sessionTicketLen; - } - if((ctx->clientReqProtocol >= TLS_Version_1_0) && - (ctx->ecdsaEnable)) { - /* Two more extensions: point format, supported curves */ - pointFormatLen = 2 + /* extension type */ - 2 + /* 2-byte vector length, extension_data */ - 1 + /* length of the ec_point_format_list */ - 1; /* the single format we support */ - suppCurveLen = 2 + /* extension type */ - 2 + /* 2-byte vector length, extension_data */ - 2 + /* length of the elliptic_curve_list */ - (2 * ctx->ecdhNumCurves); /* each curve is 2 bytes */ - totalExtenLen += (pointFormatLen + suppCurveLen); - } - if(ctx->isDTLS - ? ctx->clientReqProtocol < DTLS_Version_1_0 - : ctx->clientReqProtocol >= TLS_Version_1_2) { - signatureAlgorithmsLen = 2 + /* extension type */ - 2 + /* 2-byte vector length, extension_data */ - 2 + /* length of signatureAlgorithms list */ - 2 * (ctx->ecdsaEnable ? 5 : 3); //FIXME: 5:3 should not be hardcoded here. - totalExtenLen += signatureAlgorithmsLen; - } - if(totalExtenLen != 0) { - /* - * Total length extensions have to fit in a 16 bit field... - */ - if(totalExtenLen > 0xffff) { - sslErrorLog("Total extensions length EXCEEDED\n"); - totalExtenLen = 0; - sessionTicketLen = 0; - serverNameLen = 0; - pointFormatLen = 0; - suppCurveLen = 0; - signatureAlgorithmsLen = 0; - } - else { - /* add length of total length plus lengths of extensions */ - length += (totalExtenLen + 2); - } - } - - clientHello->contentType = SSL_RecordTypeHandshake; - head = SSLHandshakeHeaderSize(clientHello); - if ((err = SSLAllocBuffer(&clientHello->contents, length + head))) - goto err_exit; - - p = SSLEncodeHandshakeHeader(ctx, clientHello, SSL_HdskClientHello, length); - - p = SSLEncodeInt(p, ctx->clientReqProtocol, 2); - - sslLogNegotiateDebug("===SSL3 client: proclaiming max protocol " - "%d_%d capable ONLY", - ctx->clientReqProtocol >> 8, ctx->clientReqProtocol & 0xff); - if ((err = SSLEncodeRandom(p, ctx)) != 0) - { goto err_exit; - } - memcpy(ctx->clientRandom, p, SSL_CLIENT_SRVR_RAND_SIZE); - p += 32; - *p++ = sessionIDLen; /* 1 byte vector length */ - if (sessionIDLen > 0) - { memcpy(p, sessionIdentifier.data, sessionIDLen); - } - p += sessionIDLen; -#if ENABLE_DTLS - if (ctx->clientReqProtocol == DTLS_Version_1_0) { - /* TODO: Add the cookie ! Currently: size=0 -> no cookie */ - *p++ = ctx->dtlsCookie.length; - if(ctx->dtlsCookie.length) { - memcpy(p, ctx->dtlsCookie.data, ctx->dtlsCookie.length); - p+=ctx->dtlsCookie.length; - } - sslLogNegotiateDebug("==DTLS Hello: cookie len = %d\n",(int)ctx->dtlsCookie.length); - } -#endif - - - p = SSLEncodeInt(p, 2*numCipherSuites, 2); - /* 2 byte long vector length */ - - /* RFC 5746 : add the fake ciphersuite unless we are including the extension */ - if(!ctx->secure_renegotiation) - p = SSLEncodeInt(p, TLS_EMPTY_RENEGOTIATION_INFO_SCSV, 2); - - for (i = 0; inumValidCipherSuites; ++i) { -#if ENABLE_SSLV2 - if(CIPHER_SUITE_IS_SSLv2(ctx->validCipherSuites[i])) { - continue; - } -#endif - sslLogNegotiateDebug("ssl3EncodeClientHello sending suite %x", - (unsigned)ctx->validCipherSuites[i]); - p = SSLEncodeInt(p, ctx->validCipherSuites[i], 2); - } - *p++ = 1; /* 1 byte long vector */ - *p++ = 0; /* null compression */ - - /* - * Append ClientHello extensions. - */ - if(totalExtenLen != 0) { - /* first, total length of all extensions */ - p = SSLEncodeSize(p, totalExtenLen, 2); - } - if(ctx->secure_renegotiation){ - assert(ctx->ownVerifyData.length<=255); - p = SSLEncodeInt(p, SSL_HE_SecureRenegotation, 2); - p = SSLEncodeSize(p, ctx->ownVerifyData.length+1, 2); - p = SSLEncodeSize(p, ctx->ownVerifyData.length, 1); - memcpy(p, ctx->ownVerifyData.data, ctx->ownVerifyData.length); - p += ctx->ownVerifyData.length; - } - if(sessionTicketLen) { - sslEapDebug("Adding %lu bytes of sessionTicket to ClientHello", - ctx->sessionTicket.length); - p = SSLEncodeInt(p, SSL_HE_SessionTicket, 2); - p = SSLEncodeSize(p, ctx->sessionTicket.length, 2); - memcpy(p, ctx->sessionTicket.data, ctx->sessionTicket.length); - p += ctx->sessionTicket.length; - } - if(serverNameLen) { - sslEapDebug("Specifying ServerNameIndication"); - p = SSLEncodeInt(p, SSL_HE_ServerName, 2); - p = SSLEncodeSize(p, ctx->peerDomainNameLen + 5, 2); - p = SSLEncodeSize(p, ctx->peerDomainNameLen + 3, 2); - p = SSLEncodeInt(p, SSL_NT_HostName, 1); - p = SSLEncodeSize(p, ctx->peerDomainNameLen, 2); - memcpy(p, ctx->peerDomainName, ctx->peerDomainNameLen); - p += ctx->peerDomainNameLen; - } - if(suppCurveLen) { - UInt32 len = 2 * ctx->ecdhNumCurves; - unsigned dex; - p = SSLEncodeInt(p, SSL_HE_EllipticCurves, 2); - p = SSLEncodeSize(p, len+2, 2); /* length of extension data */ - p = SSLEncodeSize(p, len, 2); /* length of elliptic_curve_list */ - for(dex=0; dexecdhNumCurves; dex++) { - sslEcdsaDebug("+++ adding supported curves %u to ClientHello", - (unsigned)ctx->ecdhCurves[dex]); - p = SSLEncodeInt(p, ctx->ecdhCurves[dex], 2); - } - } - if(pointFormatLen) { - sslEcdsaDebug("+++ adding point format to ClientHello"); - p = SSLEncodeInt(p, SSL_HE_EC_PointFormats, 2); - p = SSLEncodeSize(p, 2, 2); /* length of extension data */ - p = SSLEncodeSize(p, 1, 1); /* length of ec_point_format_list */ - p = SSLEncodeInt(p, SSL_PointFormatUncompressed, 1); - } - if (signatureAlgorithmsLen) { - sslEcdsaDebug("+++ adding signature algorithms to ClientHello"); - /* TODO: Don't hardcode this */ - /* We dont support SHA512 or SHA224 because we didnot implement the digest abstraction for those - and we dont keep a running hash for those. - We dont support SHA384/ECDSA because corecrypto ec does not support it with 256 bits curves */ - UInt32 len = 2 * (ctx->ecdsaEnable ? 5 : 3); //FIXME: 5:3 should not be hardcoded here. - p = SSLEncodeInt(p, SSL_HE_SignatureAlgorithms, 2); - p = SSLEncodeSize(p, len+2, 2); /* length of extension data */ - p = SSLEncodeSize(p, len, 2); /* length of extension data */ - // p = SSLEncodeInt(p, SSL_HashAlgorithmSHA512, 1); - // p = SSLEncodeInt(p, SSL_SignatureAlgorithmRSA, 1); - p = SSLEncodeInt(p, SSL_HashAlgorithmSHA384, 1); - p = SSLEncodeInt(p, SSL_SignatureAlgorithmRSA, 1); - p = SSLEncodeInt(p, SSL_HashAlgorithmSHA256, 1); - p = SSLEncodeInt(p, SSL_SignatureAlgorithmRSA, 1); - // p = SSLEncodeInt(p, SSL_HashAlgorithmSHA224, 1); - // p = SSLEncodeInt(p, SSL_SignatureAlgorithmRSA, 1); - p = SSLEncodeInt(p, SSL_HashAlgorithmSHA1, 1); - p = SSLEncodeInt(p, SSL_SignatureAlgorithmRSA, 1); - if (ctx->ecdsaEnable) { - // p = SSLEncodeInt(p, SSL_HashAlgorithmSHA512, 1); - // p = SSLEncodeInt(p, SSL_SignatureAlgorithmECDSA, 1); - // p = SSLEncodeInt(p, SSL_HashAlgorithmSHA384, 1); - // p = SSLEncodeInt(p, SSL_SignatureAlgorithmECDSA, 1); - p = SSLEncodeInt(p, SSL_HashAlgorithmSHA256, 1); - p = SSLEncodeInt(p, SSL_SignatureAlgorithmECDSA, 1); - // p = SSLEncodeInt(p, SSL_HashAlgorithmSHA224, 1); - // p = SSLEncodeInt(p, SSL_SignatureAlgorithmECDSA, 1); - p = SSLEncodeInt(p, SSL_HashAlgorithmSHA1, 1); - p = SSLEncodeInt(p, SSL_SignatureAlgorithmECDSA, 1); - } - } - - sslLogNegotiateDebug("Client Hello : data=%p p=%p len=%08lx\n", clientHello->contents.data, p, (unsigned long)clientHello->contents.length); - - assert(p == clientHello->contents.data + clientHello->contents.length); - - if ((err = SSLInitMessageHashes(ctx)) != 0) - goto err_exit; - -err_exit: - if (err != 0) { - SSLFreeBuffer(&clientHello->contents); - } - SSLFreeBuffer(&sessionIdentifier); - - return err; -} - -OSStatus -SSLProcessClientHello(SSLBuffer message, SSLContext *ctx) -{ OSStatus err; - SSLProtocolVersion negVersion; - UInt16 cipherListLen, cipherCount, desiredSuite, cipherSuite; - UInt8 sessionIDLen, compressionCount; - UInt8 *charPtr; - unsigned i; - UInt8 *eom; /* end of message */ - - if (message.length < 41) { - sslErrorLog("SSLProcessClientHello: msg len error 1\n"); - return errSSLProtocol; - } - charPtr = message.data; - eom = charPtr + message.length; - ctx->clientReqProtocol = (SSLProtocolVersion)SSLDecodeInt(charPtr, 2); - charPtr += 2; - err = sslVerifyProtVersion(ctx, ctx->clientReqProtocol, &negVersion); - if(err) { - sslErrorLog("SSLProcessClientHello: protocol version error %04x - %04x\n", ctx->clientReqProtocol, negVersion); - return err; - } - switch(negVersion) { - case SSL_Version_3_0: - ctx->sslTslCalls = &Ssl3Callouts; - break; - case TLS_Version_1_0: - case TLS_Version_1_1: - case DTLS_Version_1_0: - ctx->sslTslCalls = &Tls1Callouts; - break; - case TLS_Version_1_2: - ctx->sslTslCalls = &Tls12Callouts; - break; - default: - return errSSLNegotiation; - } - ctx->negProtocolVersion = negVersion; - err = ctx->recFuncs->setProtocolVersion(ctx->recCtx, negVersion); - if(err) { - return err; - } - sslLogNegotiateDebug("===SSL3 server: negVersion is %d_%d", - negVersion >> 8, negVersion & 0xff); - - memcpy(ctx->clientRandom, charPtr, SSL_CLIENT_SRVR_RAND_SIZE); - charPtr += 32; - sessionIDLen = *(charPtr++); - if (message.length < (unsigned)(41 + sessionIDLen)) { - sslErrorLog("SSLProcessClientHello: msg len error 2\n"); - return errSSLProtocol; - } - /* FIXME peerID is never set on server side.... */ - if (sessionIDLen > 0 && ctx->peerID.data != 0) - { /* Don't die on error; just treat it as an uncacheable session */ - err = SSLAllocBuffer(&ctx->sessionID, sessionIDLen); - if (err == 0) - memcpy(ctx->sessionID.data, charPtr, sessionIDLen); - } - charPtr += sessionIDLen; - -#if ENABLE_DTLS - /* TODO: actually do something with this cookie */ - if(negVersion==DTLS_Version_1_0) { - UInt8 cookieLen = *charPtr++; - - sslLogNegotiateDebug("cookieLen=%d\n", cookieLen); - - if((ctx->dtlsCookie.length==0) || ((cookieLen==ctx->dtlsCookie.length) && (memcmp(ctx->dtlsCookie.data, charPtr, cookieLen)==0))) - { - ctx->cookieVerified=true; - } else { - ctx->cookieVerified=false; - } - - charPtr+=cookieLen; - } - - /* TODO: if we are about to send a HelloVerifyRequest, we probably dont need to process the cipherspecs */ -#endif - - cipherListLen = (UInt16)SSLDecodeInt(charPtr, 2); - /* Count of cipherSuites, must be even & >= 2 */ - charPtr += 2; - if((charPtr + cipherListLen) > eom) { - sslErrorLog("SSLProcessClientHello: msg len error 5\n"); - return errSSLProtocol; - } - if ((cipherListLen & 1) || - (cipherListLen < 2) || - (message.length < (unsigned)(39 + sessionIDLen + cipherListLen))) { - sslErrorLog("SSLProcessClientHello: msg len error 3\n"); - return errSSLProtocol; - } - cipherCount = cipherListLen/2; - cipherSuite = 0xFFFF; /* No match marker */ - while (cipherSuite == 0xFFFF && cipherCount--) - { desiredSuite = (UInt16)SSLDecodeInt(charPtr, 2); - charPtr += 2; - for (i = 0; i numValidCipherSuites; i++) - { if (ctx->validCipherSuites[i] == desiredSuite) - { cipherSuite = desiredSuite; - break; - } - } - } - - if (cipherSuite == 0xFFFF) - return errSSLNegotiation; - charPtr += 2 * cipherCount; /* Advance past unchecked cipherCounts */ - ctx->selectedCipher = cipherSuite; - /* validate cipher later, after we get possible sessionTicket */ - - compressionCount = *(charPtr++); - if ((compressionCount < 1) || - (message.length < - (unsigned)(38 + sessionIDLen + cipherListLen + compressionCount))) { - sslErrorLog("SSLProcessClientHello: msg len error 4\n"); - return errSSLProtocol; - } - /* Ignore list; we're doing null */ - - /* - * Handle ClientHello extensions. - */ - /* skip compression list */ - charPtr += compressionCount; - if(charPtr < eom) { - ptrdiff_t remLen = eom - charPtr; - UInt32 totalExtensLen; - UInt32 extenType; - UInt32 extenLen; - if(remLen < 6) { - /* - * Not enough for extension type and length, but not an error... - * skip it and proceed. - */ - sslEapDebug("SSLProcessClientHello: too small for any extension"); - goto proceed; - } - totalExtensLen = SSLDecodeInt(charPtr, 2); - charPtr += 2; - if((charPtr + totalExtensLen) > eom) { - sslEapDebug("SSLProcessClientHello: too small for specified total_extension_length"); - goto proceed; - } - while(charPtr < eom) { - extenType = SSLDecodeInt(charPtr, 2); - charPtr += 2; - extenLen = SSLDecodeInt(charPtr, 2); - charPtr += 2; - if((charPtr + extenLen) > eom) { - sslEapDebug("SSLProcessClientHello: too small for specified extension_length"); - break; - } - switch(extenType) { -#if SSL_PAC_SERVER_ENABLE - - case SSL_HE_SessionTicket: - SSLFreeBuffer(&ctx->sessionTicket); - SSLCopyBufferFromData(charPtr, extenLen, &ctx->sessionTicket); - sslEapDebug("Saved %lu bytes of sessionTicket from ClientHello", - (unsigned long)extenLen); - break; -#endif - case SSL_HE_ServerName: - { - /* - * This is for debug only (it's disabled for Deployment builds). - * Someday, I imagine we'll have a getter in the API to get this info. - */ - UInt8 *cp = charPtr; - UInt32 v = SSLDecodeInt(cp, 2); - cp += 2; - sslEapDebug("SSL_HE_ServerName: length of server_name_list %lu", - (unsigned long)v); - v = SSLDecodeInt(cp, 1); - cp++; - sslEapDebug("SSL_HE_ServerName: name_type %lu", (unsigned long)v); - v = SSLDecodeInt(cp, 2); - cp += 2; - sslEapDebug("SSL_HE_ServerName: length of HostName %lu", - (unsigned long)v); - char hostString[v + 1]; - memmove(hostString, cp, v); - hostString[v] = '\0'; - sslEapDebug("SSL_HE_ServerName: ServerName '%s'", hostString); - break; - } - case SSL_HE_SignatureAlgorithms: - { - UInt8 *cp = charPtr; -#ifndef NDEBUG - UInt8 *end = charPtr + extenLen; -#endif - UInt32 sigAlgsSize = SSLDecodeInt(cp, 2); - cp += 2; - - if (extenLen != sigAlgsSize + 2 || extenLen & 1 || sigAlgsSize & 1) { - sslEapDebug("SSL_HE_SignatureAlgorithms: odd length of signature algorithms list %lu %lu", - (unsigned long)extenLen, (unsigned long)sigAlgsSize); - break; - } - - ctx->numClientSigAlgs = sigAlgsSize / 2; - if(ctx->clientSigAlgs != NULL) { - sslFree(ctx->clientSigAlgs); - } - ctx->clientSigAlgs = (SSLSignatureAndHashAlgorithm *) - sslMalloc((ctx->numClientSigAlgs) * sizeof(SSLSignatureAndHashAlgorithm)); - for(i=0; inumClientSigAlgs; i++) { - /* TODO: Validate hash and signature fields. */ - ctx->clientSigAlgs[i].hash = *cp++; - ctx->clientSigAlgs[i].signature = *cp++; - sslLogNegotiateDebug("===Client specifies sigAlg %d %d", - ctx->clientSigAlgs[i].hash, - ctx->clientSigAlgs[i].signature); - } - assert(cp==end); - break; - } - default: - sslEapDebug("SSLProcessClientHello: unknown extenType (%lu)", - (unsigned long)extenType); - break; - } - charPtr += extenLen; - } - } -proceed: - if ((err = FindCipherSpec(ctx)) != 0) { - return err; - } - sslLogNegotiateDebug("ssl3 server: selecting cipherKind 0x%x", (unsigned)ctx->selectedCipher); - if ((err = SSLInitMessageHashes(ctx)) != 0) - return err; - - return errSecSuccess; -} - -static -OSStatus sslTime(uint32_t *tim) -{ - time_t t; - time(&t); - *tim = (uint32_t)t; - return errSecSuccess; -} - -OSStatus -SSLEncodeRandom(unsigned char *p, SSLContext *ctx) -{ SSLBuffer randomData; - OSStatus err; - uint32_t now; - - if ((err = sslTime(&now)) != 0) - return err; - SSLEncodeInt(p, now, 4); - randomData.data = p+4; - randomData.length = 28; - if((err = sslRand(&randomData)) != 0) - return err; - return errSecSuccess; -} - -OSStatus -SSLInitMessageHashes(SSLContext *ctx) -{ OSStatus err; - - if ((err = CloseHash(&SSLHashSHA1, &ctx->shaState)) != 0) - return err; - if ((err = CloseHash(&SSLHashMD5, &ctx->md5State)) != 0) - return err; - if ((err = CloseHash(&SSLHashSHA256, &ctx->sha256State)) != 0) - return err; - if ((err = CloseHash(&SSLHashSHA384, &ctx->sha512State)) != 0) - return err; - if ((err = ReadyHash(&SSLHashSHA1, &ctx->shaState)) != 0) - return err; - if ((err = ReadyHash(&SSLHashMD5, &ctx->md5State)) != 0) - return err; - if ((err = ReadyHash(&SSLHashSHA256, &ctx->sha256State)) != 0) - return err; - if ((err = ReadyHash(&SSLHashSHA384, &ctx->sha512State)) != 0) - return err; - return errSecSuccess; -} diff --git a/libsecurity_ssl/lib/sslKeyExchange.c b/libsecurity_ssl/lib/sslKeyExchange.c deleted file mode 100644 index 4ab3ed8b..00000000 --- a/libsecurity_ssl/lib/sslKeyExchange.c +++ /dev/null @@ -1,1968 +0,0 @@ -/* - * Copyright (c) 1999-2001,2005-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * 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@ - */ - -/* - * sslKeyExchange.c - Support for key exchange and server key exchange - */ - -#include "ssl.h" -#include "sslContext.h" -#include "sslHandshake.h" -#include "sslMemory.h" -#include "sslDebug.h" -#include "sslUtils.h" -#include "sslCrypto.h" -#include "sslRand.h" -#include "sslDigests.h" - -#include -#include - -#include -#include -#include - -#ifdef USE_CDSA_CRYPTO -//#include -//#include -#include -#include -#include "ModuleAttacher.h" -#else -#include -#include -#if APPLE_DH - -#if TARGET_OS_IPHONE -#include -#endif - -static OSStatus SSLGenServerDHParamsAndKey(SSLContext *ctx); -static size_t SSLEncodedDHKeyParamsLen(SSLContext *ctx); -static OSStatus SSLEncodeDHKeyParams(SSLContext *ctx, uint8_t *charPtr); - -#endif /* APPLE_DH */ -#endif /* USE_CDSA_CRYPTO */ - -// MARK: - -// MARK: Forward Static Declarations - -#if APPLE_DH -#if USE_CDSA_CRYPTO -static OSStatus SSLGenServerDHParamsAndKey(SSLContext *ctx); -static OSStatus SSLEncodeDHKeyParams(SSLContext *ctx, uint8_t *charPtr); -#endif -static OSStatus SSLDecodeDHKeyParams(SSLContext *ctx, uint8_t **charPtr, - size_t length); -#endif -static OSStatus SSLDecodeECDHKeyParams(SSLContext *ctx, uint8_t **charPtr, - size_t length); - -#define DH_PARAM_DUMP 0 -#if DH_PARAM_DUMP - -static void dumpBuf(const char *name, SSLBuffer *buf) -{ - printf("%s:\n", name); - uint8_t *cp = buf->data; - uint8_t *endCp = cp + buf->length; - - do { - unsigned i; - for(i=0; i<16; i++) { - printf("%02x ", *cp++); - if(cp == endCp) { - break; - } - } - if(cp == endCp) { - break; - } - printf("\n"); - } while(cp < endCp); - printf("\n"); -} -#else -#define dumpBuf(n, b) -#endif /* DH_PARAM_DUMP */ - -#if APPLE_DH - -// MARK: - -// MARK: Local Diffie-Hellman Parameter Generator - -/* - * Process-wide server-supplied Diffie-Hellman parameters. - * This might be overridden by some API_supplied parameters - * in the future. - */ -struct ServerDhParams -{ - /* these two for sending over the wire */ - SSLBuffer prime; - SSLBuffer generator; - /* this one for sending to the CSP at key gen time */ - SSLBuffer paramBlock; -}; - - -#endif /* APPLE_DH */ - -// MARK: - -// MARK: RSA Key Exchange - -/* - * Client RSA Key Exchange msgs actually start with a two-byte - * length field, contrary to the first version of RFC 2246, dated - * January 1999. See RFC 2246, March 2002, section 7.4.7.1 for - * updated requirements. - */ -#define RSA_CLIENT_KEY_ADD_LENGTH 1 - -static OSStatus -SSLEncodeRSAKeyParams(SSLBuffer *keyParams, SSLPubKey *key, SSLContext *ctx) -{ -#if 0 - SSLBuffer modulus, exponent; - uint8_t *charPtr; - -#ifdef USE_CDSA_CRYPTO - if(err = attachToCsp(ctx)) { - return err; - } - - /* Note currently ALL public keys are raw, obtained from the CL... */ - assert((*key)->KeyHeader.BlobType == CSSM_KEYBLOB_RAW); -#endif /* USE_CDSA_CRYPTO */ - - err = sslGetPubKeyBits(ctx, - key, - &modulus, - &exponent); - if(err) { - SSLFreeBuffer(&modulus); - SSLFreeBuffer(&exponent); - return err; - } - - if ((err = SSLAllocBuffer(keyParams, - modulus.length + exponent.length + 4, ctx)) != 0) { - return err; - } - charPtr = keyParams->data; - charPtr = SSLEncodeInt(charPtr, modulus.length, 2); - memcpy(charPtr, modulus.data, modulus.length); - charPtr += modulus.length; - charPtr = SSLEncodeInt(charPtr, exponent.length, 2); - memcpy(charPtr, exponent.data, exponent.length); - - /* these were mallocd by sslGetPubKeyBits() */ - SSLFreeBuffer(&modulus); - SSLFreeBuffer(&exponent); - return errSecSuccess; -#else - CFDataRef modulus = SecKeyCopyModulus(SECKEYREF(key)); - if (!modulus) { - sslErrorLog("SSLEncodeRSAKeyParams: SecKeyCopyModulus failed\n"); - return errSSLCrypto; - } - CFDataRef exponent = SecKeyCopyExponent(SECKEYREF(key)); - if (!exponent) { - sslErrorLog("SSLEncodeRSAKeyParams: SecKeyCopyExponent failed\n"); - CFRelease(modulus); - return errSSLCrypto; - } - - CFIndex modulusLength = CFDataGetLength(modulus); - CFIndex exponentLength = CFDataGetLength(exponent); - sslDebugLog("SSLEncodeRSAKeyParams: modulus len=%ld, exponent len=%ld\n", - modulusLength, exponentLength); - OSStatus err; - if ((err = SSLAllocBuffer(keyParams, - modulusLength + exponentLength + 4)) != 0) { - CFReleaseSafe(exponent); - CFReleaseSafe(modulus); - return err; - } - uint8_t *charPtr = keyParams->data; - charPtr = SSLEncodeSize(charPtr, modulusLength, 2); - memcpy(charPtr, CFDataGetBytePtr(modulus), modulusLength); - charPtr += modulusLength; - charPtr = SSLEncodeSize(charPtr, exponentLength, 2); - memcpy(charPtr, CFDataGetBytePtr(exponent), exponentLength); - CFRelease(modulus); - CFRelease(exponent); - return errSecSuccess; -#endif -} - -static OSStatus -SSLEncodeRSAPremasterSecret(SSLContext *ctx) -{ SSLBuffer randData; - OSStatus err; - - if ((err = SSLAllocBuffer(&ctx->preMasterSecret, - SSL_RSA_PREMASTER_SECRET_SIZE)) != 0) - return err; - - assert(ctx->negProtocolVersion >= SSL_Version_3_0); - - SSLEncodeInt(ctx->preMasterSecret.data, ctx->clientReqProtocol, 2); - randData.data = ctx->preMasterSecret.data+2; - randData.length = SSL_RSA_PREMASTER_SECRET_SIZE - 2; - if ((err = sslRand(&randData)) != 0) - return err; - return errSecSuccess; -} - -/* - * Generate a server key exchange message signed by our RSA or DSA private key. - */ - -static OSStatus -SSLSignServerKeyExchangeTls12(SSLContext *ctx, SSLSignatureAndHashAlgorithm sigAlg, SSLBuffer exchangeParams, SSLBuffer signature, size_t *actSigLen) -{ - OSStatus err; - SSLBuffer hashOut, hashCtx, clientRandom, serverRandom; - uint8_t hashes[SSL_MAX_DIGEST_LEN]; - SSLBuffer signedHashes; - uint8_t *dataToSign; - size_t dataToSignLen; - const HashReference *hashRef; - SecAsn1AlgId algId; - - signedHashes.data = 0; - hashCtx.data = 0; - - clientRandom.data = ctx->clientRandom; - clientRandom.length = SSL_CLIENT_SRVR_RAND_SIZE; - serverRandom.data = ctx->serverRandom; - serverRandom.length = SSL_CLIENT_SRVR_RAND_SIZE; - - switch (sigAlg.hash) { - case SSL_HashAlgorithmSHA1: - hashRef = &SSLHashSHA1; - algId.algorithm = CSSMOID_SHA1WithRSA; - break; - case SSL_HashAlgorithmSHA256: - hashRef = &SSLHashSHA256; - algId.algorithm = CSSMOID_SHA256WithRSA; - break; - case SSL_HashAlgorithmSHA384: - hashRef = &SSLHashSHA384; - algId.algorithm = CSSMOID_SHA384WithRSA; - break; - default: - sslErrorLog("SSLVerifySignedServerKeyExchangeTls12: unsupported hash %d\n", sigAlg.hash); - return errSSLProtocol; - } - - - dataToSign = hashes; - dataToSignLen = hashRef->digestSize; - hashOut.data = hashes; - hashOut.length = hashRef->digestSize; - - if ((err = ReadyHash(hashRef, &hashCtx)) != 0) - goto fail; - if ((err = hashRef->update(&hashCtx, &clientRandom)) != 0) - goto fail; - if ((err = hashRef->update(&hashCtx, &serverRandom)) != 0) - goto fail; - if ((err = hashRef->update(&hashCtx, &exchangeParams)) != 0) - goto fail; - if ((err = hashRef->final(&hashCtx, &hashOut)) != 0) - goto fail; - - if(sigAlg.signature==SSL_SignatureAlgorithmRSA) { - err = sslRsaSign(ctx, - ctx->signingPrivKeyRef, - &algId, - dataToSign, - dataToSignLen, - signature.data, - signature.length, - actSigLen); - } else { - err = sslRawSign(ctx, - ctx->signingPrivKeyRef, - dataToSign, // one or two hashes - dataToSignLen, - signature.data, - signature.length, - actSigLen); - } - - if(err) { - sslErrorLog("SSLDecodeSignedServerKeyExchangeTls12: sslRawVerify " - "returned %d\n", (int)err); - goto fail; - } - -fail: - SSLFreeBuffer(&signedHashes); - SSLFreeBuffer(&hashCtx); - return err; -} - -static OSStatus -SSLSignServerKeyExchange(SSLContext *ctx, bool isRsa, SSLBuffer exchangeParams, SSLBuffer signature, size_t *actSigLen) -{ - OSStatus err; - uint8_t hashes[SSL_SHA1_DIGEST_LEN + SSL_MD5_DIGEST_LEN]; - SSLBuffer clientRandom,serverRandom,hashCtx, hash; - uint8_t *dataToSign; - size_t dataToSignLen; - - hashCtx.data = 0; - - /* cook up hash(es) for raw sign */ - clientRandom.data = ctx->clientRandom; - clientRandom.length = SSL_CLIENT_SRVR_RAND_SIZE; - serverRandom.data = ctx->serverRandom; - serverRandom.length = SSL_CLIENT_SRVR_RAND_SIZE; - - if(isRsa) { - /* skip this if signing with DSA */ - dataToSign = hashes; - dataToSignLen = SSL_SHA1_DIGEST_LEN + SSL_MD5_DIGEST_LEN; - hash.data = &hashes[0]; - hash.length = SSL_MD5_DIGEST_LEN; - - if ((err = ReadyHash(&SSLHashMD5, &hashCtx)) != 0) - goto fail; - if ((err = SSLHashMD5.update(&hashCtx, &clientRandom)) != 0) - goto fail; - if ((err = SSLHashMD5.update(&hashCtx, &serverRandom)) != 0) - goto fail; - if ((err = SSLHashMD5.update(&hashCtx, &exchangeParams)) != 0) - goto fail; - if ((err = SSLHashMD5.final(&hashCtx, &hash)) != 0) - goto fail; - if ((err = SSLFreeBuffer(&hashCtx)) != 0) - goto fail; - } - else { - /* DSA - just use the SHA1 hash */ - dataToSign = &hashes[SSL_MD5_DIGEST_LEN]; - dataToSignLen = SSL_SHA1_DIGEST_LEN; - } - hash.data = &hashes[SSL_MD5_DIGEST_LEN]; - hash.length = SSL_SHA1_DIGEST_LEN; - if ((err = ReadyHash(&SSLHashSHA1, &hashCtx)) != 0) - goto fail; - if ((err = SSLHashSHA1.update(&hashCtx, &clientRandom)) != 0) - goto fail; - if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0) - goto fail; - if ((err = SSLHashSHA1.update(&hashCtx, &exchangeParams)) != 0) - goto fail; - if ((err = SSLHashSHA1.final(&hashCtx, &hash)) != 0) - goto fail; - if ((err = SSLFreeBuffer(&hashCtx)) != 0) - goto fail; - - - err = sslRawSign(ctx, - ctx->signingPrivKeyRef, - dataToSign, // one or two hashes - dataToSignLen, - signature.data, - signature.length, - actSigLen); - if(err) { - goto fail; - } - -fail: - SSLFreeBuffer(&hashCtx); - - return err; -} - -static -OSStatus FindSigAlg(SSLContext *ctx, - SSLSignatureAndHashAlgorithm *alg) -{ - unsigned i; - - assert(ctx->protocolSide == kSSLServerSide); - assert(ctx->negProtocolVersion >= TLS_Version_1_2); - assert(!ctx->isDTLS); - - if((ctx->numClientSigAlgs==0) ||(ctx->clientSigAlgs==NULL)) - return errSSLInternal; - - //FIXME: Need a better way to select here - for(i=0; inumClientSigAlgs; i++) { - alg->hash = ctx->clientSigAlgs[i].hash; - alg->signature = ctx->clientSigAlgs[i].signature; - //We only support RSA for certs on the server side - but we should test against the cert type - if(ctx->clientSigAlgs[i].signature != SSL_SignatureAlgorithmRSA) - continue; - //Let's only support SHA1 and SHA256. SHA384 does not work with 512 bits keys. - // We should actually test against what the cert can do. - if((alg->hash==SSL_HashAlgorithmSHA1) || (alg->hash==SSL_HashAlgorithmSHA256)) { - return errSecSuccess; - } - } - // We could not find a supported signature and hash algorithm - return errSSLProtocol; -} - -static OSStatus -SSLEncodeSignedServerKeyExchange(SSLRecord *keyExch, SSLContext *ctx) -{ OSStatus err; - uint8_t *charPtr; - size_t outputLen; - bool isRsa = true; - size_t maxSigLen; - size_t actSigLen; - SSLBuffer signature; - int head = 4; - SSLBuffer exchangeParams; - - assert(ctx->protocolSide == kSSLServerSide); - assert(ctx->signingPubKey != NULL); - assert(ctx->negProtocolVersion >= SSL_Version_3_0); - exchangeParams.data = 0; - signature.data = 0; - -#if ENABLE_DTLS - if(ctx->negProtocolVersion == DTLS_Version_1_0) { - head+=8; - } -#endif - - - /* Set up parameter block to hash ==> exchangeParams */ - switch(ctx->selectedCipherSpecParams.keyExchangeMethod) { - case SSL_RSA: - case SSL_RSA_EXPORT: - /* - * Parameter block = encryption public key. - * If app hasn't supplied a separate encryption cert, abort. - */ - if(ctx->encryptPubKey == NULL) { - sslErrorLog("RSAServerKeyExchange: no encrypt cert\n"); - return errSSLBadConfiguration; - } - err = SSLEncodeRSAKeyParams(&exchangeParams, - ctx->encryptPubKey, ctx); - break; - -#if APPLE_DH - - case SSL_DHE_DSS: - case SSL_DHE_DSS_EXPORT: - isRsa = false; - /* and fall through */ - case SSL_DHE_RSA: - case SSL_DHE_RSA_EXPORT: - { - /* - * Parameter block = {prime, generator, public key} - * Obtain D-H parameters (if we don't have them) and a key pair. - */ - err = SSLGenServerDHParamsAndKey(ctx); - if(err) { - return err; - } - size_t len = SSLEncodedDHKeyParamsLen(ctx); - err = SSLAllocBuffer(&exchangeParams, len); - if(err) { - goto fail; - } - err = SSLEncodeDHKeyParams(ctx, exchangeParams.data); - break; - } - -#endif /* APPLE_DH */ - - default: - /* shouldn't be here */ - assert(0); - return errSSLInternal; - } - - SSLSignatureAndHashAlgorithm sigAlg; - - - /* preallocate a buffer for signing */ - err = sslGetMaxSigSize(ctx->signingPrivKeyRef, &maxSigLen); - if(err) { - goto fail; - } - err = SSLAllocBuffer(&signature, maxSigLen); - if(err) { - goto fail; - } - - outputLen = exchangeParams.length + 2; - - if (sslVersionIsLikeTls12(ctx)) - { - err=FindSigAlg(ctx, &sigAlg); - if(err) - goto fail; - - outputLen += 2; - err = SSLSignServerKeyExchangeTls12(ctx, sigAlg, exchangeParams, - signature, &actSigLen); - } else { - err = SSLSignServerKeyExchange(ctx, isRsa, exchangeParams, - signature, &actSigLen); - } - - if(err) - goto fail; - - assert(actSigLen <= maxSigLen); - - outputLen += actSigLen; - - /* package it all up */ - keyExch->protocolVersion = ctx->negProtocolVersion; - keyExch->contentType = SSL_RecordTypeHandshake; - if ((err = SSLAllocBuffer(&keyExch->contents, outputLen+head)) != 0) - goto fail; - - charPtr = SSLEncodeHandshakeHeader(ctx, keyExch, SSL_HdskServerKeyExchange, outputLen); - - memcpy(charPtr, exchangeParams.data, exchangeParams.length); - charPtr += exchangeParams.length; - - if (sslVersionIsLikeTls12(ctx)) - { - *charPtr++=sigAlg.hash; - *charPtr++=sigAlg.signature; - } - - charPtr = SSLEncodeInt(charPtr, actSigLen, 2); - memcpy(charPtr, signature.data, actSigLen); - assert((charPtr + actSigLen) == - (keyExch->contents.data + keyExch->contents.length)); - - err = errSecSuccess; - -fail: - SSLFreeBuffer(&exchangeParams); - SSLFreeBuffer(&signature); - return err; -} - -static OSStatus -SSLVerifySignedServerKeyExchange(SSLContext *ctx, bool isRsa, SSLBuffer signedParams, - uint8_t *signature, UInt16 signatureLen) -{ - OSStatus err; - SSLBuffer hashOut, hashCtx, clientRandom, serverRandom; - uint8_t hashes[SSL_SHA1_DIGEST_LEN + SSL_MD5_DIGEST_LEN]; - SSLBuffer signedHashes; - uint8_t *dataToSign; - size_t dataToSignLen; - - signedHashes.data = 0; - hashCtx.data = 0; - - clientRandom.data = ctx->clientRandom; - clientRandom.length = SSL_CLIENT_SRVR_RAND_SIZE; - serverRandom.data = ctx->serverRandom; - serverRandom.length = SSL_CLIENT_SRVR_RAND_SIZE; - - - if(isRsa) { - /* skip this if signing with DSA */ - dataToSign = hashes; - dataToSignLen = SSL_SHA1_DIGEST_LEN + SSL_MD5_DIGEST_LEN; - hashOut.data = hashes; - hashOut.length = SSL_MD5_DIGEST_LEN; - - if ((err = ReadyHash(&SSLHashMD5, &hashCtx)) != 0) - goto fail; - if ((err = SSLHashMD5.update(&hashCtx, &clientRandom)) != 0) - goto fail; - if ((err = SSLHashMD5.update(&hashCtx, &serverRandom)) != 0) - goto fail; - if ((err = SSLHashMD5.update(&hashCtx, &signedParams)) != 0) - goto fail; - if ((err = SSLHashMD5.final(&hashCtx, &hashOut)) != 0) - goto fail; - } - else { - /* DSA, ECDSA - just use the SHA1 hash */ - dataToSign = &hashes[SSL_MD5_DIGEST_LEN]; - dataToSignLen = SSL_SHA1_DIGEST_LEN; - } - - hashOut.data = hashes + SSL_MD5_DIGEST_LEN; - hashOut.length = SSL_SHA1_DIGEST_LEN; - if ((err = SSLFreeBuffer(&hashCtx)) != 0) - goto fail; - - if ((err = ReadyHash(&SSLHashSHA1, &hashCtx)) != 0) - goto fail; - if ((err = SSLHashSHA1.update(&hashCtx, &clientRandom)) != 0) - goto fail; - if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0) - goto fail; - if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0) - goto fail; - if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0) - goto fail; - - err = sslRawVerify(ctx, - ctx->peerPubKey, - dataToSign, /* plaintext */ - dataToSignLen, /* plaintext length */ - signature, - signatureLen); - if(err) { - sslErrorLog("SSLDecodeSignedServerKeyExchange: sslRawVerify " - "returned %d\n", (int)err); - goto fail; - } - -fail: - SSLFreeBuffer(&signedHashes); - SSLFreeBuffer(&hashCtx); - return err; - -} - -static OSStatus -SSLVerifySignedServerKeyExchangeTls12(SSLContext *ctx, SSLSignatureAndHashAlgorithm sigAlg, SSLBuffer signedParams, - uint8_t *signature, UInt16 signatureLen) -{ - OSStatus err; - SSLBuffer hashOut, hashCtx, clientRandom, serverRandom; - uint8_t hashes[SSL_MAX_DIGEST_LEN]; - SSLBuffer signedHashes; - uint8_t *dataToSign; - size_t dataToSignLen; - const HashReference *hashRef; - SecAsn1AlgId algId; - - signedHashes.data = 0; - hashCtx.data = 0; - - clientRandom.data = ctx->clientRandom; - clientRandom.length = SSL_CLIENT_SRVR_RAND_SIZE; - serverRandom.data = ctx->serverRandom; - serverRandom.length = SSL_CLIENT_SRVR_RAND_SIZE; - - switch (sigAlg.hash) { - case SSL_HashAlgorithmSHA1: - hashRef = &SSLHashSHA1; - algId.algorithm = CSSMOID_SHA1WithRSA; - break; - case SSL_HashAlgorithmSHA256: - hashRef = &SSLHashSHA256; - algId.algorithm = CSSMOID_SHA256WithRSA; - break; - case SSL_HashAlgorithmSHA384: - hashRef = &SSLHashSHA384; - algId.algorithm = CSSMOID_SHA384WithRSA; - break; - default: - sslErrorLog("SSLVerifySignedServerKeyExchangeTls12: unsupported hash %d\n", sigAlg.hash); - return errSSLProtocol; - } - - - dataToSign = hashes; - dataToSignLen = hashRef->digestSize; - hashOut.data = hashes; - hashOut.length = hashRef->digestSize; - - if ((err = ReadyHash(hashRef, &hashCtx)) != 0) - goto fail; - if ((err = hashRef->update(&hashCtx, &clientRandom)) != 0) - goto fail; - if ((err = hashRef->update(&hashCtx, &serverRandom)) != 0) - goto fail; - if ((err = hashRef->update(&hashCtx, &signedParams)) != 0) - goto fail; - if ((err = hashRef->final(&hashCtx, &hashOut)) != 0) - goto fail; - - if(sigAlg.signature==SSL_SignatureAlgorithmRSA) { - err = sslRsaVerify(ctx, - ctx->peerPubKey, - &algId, - dataToSign, - dataToSignLen, - signature, - signatureLen); - } else { - err = sslRawVerify(ctx, - ctx->peerPubKey, - dataToSign, /* plaintext */ - dataToSignLen, /* plaintext length */ - signature, - signatureLen); - } - - if(err) { - sslErrorLog("SSLDecodeSignedServerKeyExchangeTls12: sslRawVerify " - "returned %d\n", (int)err); - goto fail; - } - -fail: - SSLFreeBuffer(&signedHashes); - SSLFreeBuffer(&hashCtx); - return err; - -} - -/* - * Decode and verify a server key exchange message signed by server's - * public key. - */ -static OSStatus -SSLDecodeSignedServerKeyExchange(SSLBuffer message, SSLContext *ctx) -{ - OSStatus err; - UInt16 modulusLen = 0, exponentLen = 0, signatureLen; - uint8_t *modulus = NULL, *exponent = NULL, *signature; - bool isRsa = true; - - assert(ctx->protocolSide == kSSLClientSide); - - if (message.length < 2) { - sslErrorLog("SSLDecodeSignedServerKeyExchange: msg len error 1\n"); - return errSSLProtocol; - } - - /* first extract the key-exchange-method-specific parameters */ - uint8_t *charPtr = message.data; - uint8_t *endCp = charPtr + message.length; - switch(ctx->selectedCipherSpecParams.keyExchangeMethod) { - case SSL_RSA: - case SSL_RSA_EXPORT: - modulusLen = SSLDecodeInt(charPtr, 2); - charPtr += 2; - if((charPtr + modulusLen) > endCp) { - sslErrorLog("signedServerKeyExchange: msg len error 2\n"); - return errSSLProtocol; - } - modulus = charPtr; - charPtr += modulusLen; - - exponentLen = SSLDecodeInt(charPtr, 2); - charPtr += 2; - if((charPtr + exponentLen) > endCp) { - sslErrorLog("signedServerKeyExchange: msg len error 3\n"); - return errSSLProtocol; - } - exponent = charPtr; - charPtr += exponentLen; - break; -#if APPLE_DH - case SSL_DHE_DSS: - case SSL_DHE_DSS_EXPORT: - isRsa = false; - /* and fall through */ - case SSL_DHE_RSA: - case SSL_DHE_RSA_EXPORT: - err = SSLDecodeDHKeyParams(ctx, &charPtr, message.length); - if(err) { - return err; - } - break; - #endif /* APPLE_DH */ - - case SSL_ECDHE_ECDSA: - isRsa = false; - /* and fall through */ - case SSL_ECDHE_RSA: - err = SSLDecodeECDHKeyParams(ctx, &charPtr, message.length); - if(err) { - return err; - } - break; - default: - assert(0); - return errSSLInternal; - } - - /* this is what's hashed */ - SSLBuffer signedParams; - signedParams.data = message.data; - signedParams.length = charPtr - message.data; - - SSLSignatureAndHashAlgorithm sigAlg; - - if (sslVersionIsLikeTls12(ctx)) { - /* Parse the algorithm field added in TLS1.2 */ - if((charPtr + 2) > endCp) { - sslErrorLog("signedServerKeyExchange: msg len error 499\n"); - return errSSLProtocol; - } - sigAlg.hash = *charPtr++; - sigAlg.signature = *charPtr++; - } - - signatureLen = SSLDecodeInt(charPtr, 2); - charPtr += 2; - if((charPtr + signatureLen) != endCp) { - sslErrorLog("signedServerKeyExchange: msg len error 4\n"); - return errSSLProtocol; - } - signature = charPtr; - - if (sslVersionIsLikeTls12(ctx)) - { - err = SSLVerifySignedServerKeyExchangeTls12(ctx, sigAlg, signedParams, - signature, signatureLen); - } else { - err = SSLVerifySignedServerKeyExchange(ctx, isRsa, signedParams, - signature, signatureLen); - } - - if(err) - goto fail; - - /* Signature matches; now replace server key with new key (RSA only) */ - switch(ctx->selectedCipherSpecParams.keyExchangeMethod) { - case SSL_RSA: - case SSL_RSA_EXPORT: - { - SSLBuffer modBuf; - SSLBuffer expBuf; - - /* first free existing peerKey */ - sslFreePubKey(&ctx->peerPubKey); /* no KCItem */ - - /* and cook up a new one from raw bits */ - modBuf.data = modulus; - modBuf.length = modulusLen; - expBuf.data = exponent; - expBuf.length = exponentLen; - err = sslGetPubKeyFromBits(ctx, - &modBuf, - &expBuf, - &ctx->peerPubKey); - break; - } - case SSL_DHE_RSA: - case SSL_DHE_RSA_EXPORT: - case SSL_DHE_DSS: - case SSL_DHE_DSS_EXPORT: - case SSL_ECDHE_ECDSA: - case SSL_ECDHE_RSA: - break; /* handled above */ - default: - assert(0); - } -fail: - return err; -} - -static OSStatus -SSLDecodeRSAKeyExchange(SSLBuffer keyExchange, SSLContext *ctx) -{ OSStatus err; - size_t outputLen, localKeyModulusLen; - SSLProtocolVersion version; - Boolean useEncryptKey = false; - uint8_t *src = NULL; - SSLPrivKey *keyRef = NULL; - - assert(ctx->protocolSide == kSSLServerSide); - if (ctx->encryptPrivKeyRef) { - useEncryptKey = true; - } - if (useEncryptKey) { - keyRef = ctx->encryptPrivKeyRef; - /* FIXME: when 3420180 is implemented, pick appropriate creds here */ - } - else { - keyRef = ctx->signingPrivKeyRef; - /* FIXME: when 3420180 is implemented, pick appropriate creds here */ - } - - localKeyModulusLen = sslPrivKeyLengthInBytes(keyRef); - if (localKeyModulusLen == 0) { - sslErrorLog("SSLDecodeRSAKeyExchange: private key modulus is 0\n"); - return errSSLCrypto; - } - - /* - * We have to tolerate incoming key exchange msgs with and without the - * two-byte "encrypted length" field. - */ - if (keyExchange.length == localKeyModulusLen) { - /* no length encoded */ - src = keyExchange.data; - } - else if((keyExchange.length == (localKeyModulusLen + 2)) && - (ctx->negProtocolVersion >= TLS_Version_1_0)) { - /* TLS only - skip the length bytes */ - src = keyExchange.data + 2; - } - else { - sslErrorLog("SSLDecodeRSAKeyExchange: length error (exp %u got %u)\n", - (unsigned)localKeyModulusLen, (unsigned)keyExchange.length); - return errSSLProtocol; - } - err = SSLAllocBuffer(&ctx->preMasterSecret, SSL_RSA_PREMASTER_SECRET_SIZE); - if(err != 0) { - return err; - } - - /* - * From this point on, to defend against the Bleichenbacher attack - * and its Klima-Pokorny-Rosa variant, any errors we detect are *not* - * reported to the caller or the peer. If we detect any error during - * decryption (e.g., bad PKCS1 padding) or in the testing of the version - * number in the premaster secret, we proceed by generating a random - * premaster secret, with the correct version number, and tell our caller - * that everything is fine. This session will fail as soon as the - * finished messages are sent, since we will be using a bogus premaster - * secret (and hence bogus session and MAC keys). Meanwhile we have - * not provided any side channel information relating to the cause of - * the failure. - * - * See http://eprint.iacr.org/2003/052/ for more info. - */ - err = sslRsaDecrypt(ctx, - keyRef, -#if USE_CDSA_CRYPTO - CSSM_PADDING_PKCS1, -#else - kSecPaddingPKCS1, -#endif - src, - localKeyModulusLen, // ciphertext len - ctx->preMasterSecret.data, - SSL_RSA_PREMASTER_SECRET_SIZE, // plaintext buf available - &outputLen); - - if(err != errSecSuccess) { - /* possible Bleichenbacher attack */ - sslLogNegotiateDebug("SSLDecodeRSAKeyExchange: RSA decrypt fail"); - } - else if(outputLen != SSL_RSA_PREMASTER_SECRET_SIZE) { - sslLogNegotiateDebug("SSLDecodeRSAKeyExchange: premaster secret size error"); - err = errSSLProtocol; // not passed back to caller - } - - if(err == errSecSuccess) { - /* - * Two legal values here - the one we actually negotiated (which is - * technically incorrect but not uncommon), and the one the client - * sent as its preferred version in the client hello msg. - */ - version = (SSLProtocolVersion)SSLDecodeInt(ctx->preMasterSecret.data, 2); - if((version != ctx->negProtocolVersion) && - (version != ctx->clientReqProtocol)) { - /* possible Klima-Pokorny-Rosa attack */ - sslLogNegotiateDebug("SSLDecodeRSAKeyExchange: version error"); - err = errSSLProtocol; - } - } - if(err != errSecSuccess) { - /* - * Obfuscate failures for defense against Bleichenbacher and - * Klima-Pokorny-Rosa attacks. - */ - SSLEncodeInt(ctx->preMasterSecret.data, ctx->negProtocolVersion, 2); - SSLBuffer tmpBuf; - tmpBuf.data = ctx->preMasterSecret.data + 2; - tmpBuf.length = SSL_RSA_PREMASTER_SECRET_SIZE - 2; - /* must ignore failures here */ - sslRand(&tmpBuf); - } - - /* in any case, save premaster secret (good or bogus) and proceed */ - return errSecSuccess; -} - -static OSStatus -SSLEncodeRSAKeyExchange(SSLRecord *keyExchange, SSLContext *ctx) -{ OSStatus err; - size_t outputLen, peerKeyModulusLen; - size_t bufLen; - uint8_t *dst; - bool encodeLen = false; - uint8_t *p; - int head; - size_t msglen; - - assert(ctx->protocolSide == kSSLClientSide); - if ((err = SSLEncodeRSAPremasterSecret(ctx)) != 0) - return err; - - keyExchange->contentType = SSL_RecordTypeHandshake; - assert(ctx->negProtocolVersion >= SSL_Version_3_0); - keyExchange->protocolVersion = ctx->negProtocolVersion; - - peerKeyModulusLen = sslPubKeyLengthInBytes(ctx->peerPubKey); - if (peerKeyModulusLen == 0) { - sslErrorLog("SSLEncodeRSAKeyExchange: peer key modulus is 0\n"); - /* FIXME: we don't return an error here... is this condition ever expected? */ - } -#if SSL_DEBUG - sslDebugLog("SSLEncodeRSAKeyExchange: peer key modulus length = %lu\n", peerKeyModulusLen); -#endif - msglen = peerKeyModulusLen; - #if RSA_CLIENT_KEY_ADD_LENGTH - if(ctx->negProtocolVersion >= TLS_Version_1_0) { - msglen += 2; - encodeLen = true; - } - #endif - head = SSLHandshakeHeaderSize(keyExchange); - bufLen = msglen + head; - if ((err = SSLAllocBuffer(&keyExchange->contents, - bufLen)) != 0) - { - return err; - } - dst = keyExchange->contents.data + head; - if(encodeLen) { - dst += 2; - } - - /* FIXME: can this line be removed? */ - p = keyExchange->contents.data; - - p = SSLEncodeHandshakeHeader(ctx, keyExchange, SSL_HdskClientKeyExchange, msglen); - - if(encodeLen) { - /* the length of the encrypted pre_master_secret */ - SSLEncodeSize(keyExchange->contents.data + head, - peerKeyModulusLen, 2); - } - err = sslRsaEncrypt(ctx, - ctx->peerPubKey, -#if USE_CDSA_CRYPTO - CSSM_PADDING_PKCS1, -#else - kSecPaddingPKCS1, -#endif - ctx->preMasterSecret.data, - SSL_RSA_PREMASTER_SECRET_SIZE, - dst, - peerKeyModulusLen, - &outputLen); - if(err) { - sslErrorLog("SSLEncodeRSAKeyExchange: error %d\n", (int)err); - return err; - } - - assert(outputLen == (encodeLen ? msglen - 2 : msglen)); - - return errSecSuccess; -} - - -#if APPLE_DH - -// MARK: - -// MARK: Diffie-Hellman Key Exchange - -/* - * Diffie-Hellman setup, server side. On successful return, the - * following SSLContext members are valid: - * - * dhParamsPrime - * dhParamsGenerator - * dhPrivate - * dhExchangePublic - */ -static OSStatus -SSLGenServerDHParamsAndKey( - SSLContext *ctx) -{ - OSStatus ortn; - assert(ctx->protocolSide == kSSLServerSide); - - - /* - * Obtain D-H parameters if we don't have them. - */ - if(ctx->dhParamsEncoded.data == NULL) { - /* TODO: Pick appropriate group based on cipher suite */ - ccdh_const_gp_t gp = ccdh_gp_rfc5114_MODP_2048_256(); - cc_size n = ccdh_gp_n(gp); - size_t s = ccdh_gp_prime_size(gp); - uint8_t p[s]; - uint8_t g[s]; - - ccn_write_uint(n, ccdh_gp_prime(gp), s, p); - ccn_write_uint(n, ccdh_gp_g(gp), s, g); - - const SSLBuffer prime = { - .data = p, - .length = s, - }; - const SSLBuffer generator = { - .data = g, - .length = s, - }; - - ortn=sslEncodeDhParams(&ctx->dhParamsEncoded, /* data mallocd and RETURNED PKCS-3 encoded */ - &prime, /* Wire format */ - &generator); /* Wire format */ - - if(ortn) - return ortn; - } - -#if USE_CDSA_CRYPTO - /* generate per-session D-H key pair */ - sslFreeKey(ctx->cspHand, &ctx->dhPrivate, NULL); - SSLFreeBuffer(&ctx->dhExchangePublic); - ctx->dhPrivate = (CSSM_KEY *)sslMalloc(sizeof(CSSM_KEY)); - CSSM_KEY pubKey; - ortn = sslDhGenerateKeyPair(ctx, - &ctx->dhParamsEncoded, - ctx->dhParamsPrime.length * 8, - &pubKey, ctx->dhPrivate); - if(ortn) { - return ortn; - } - CSSM_TO_SSLBUF(&pubKey.KeyData, &ctx->dhExchangePublic); -#else - if (!ctx->secDHContext) { - ortn = sslDhCreateKey(ctx); - if(ortn) - return ortn; - } - return sslDhGenerateKeyPair(ctx); -#endif - return errSecSuccess; -} - -/* - * size of DH param and public key, in wire format - */ -static size_t -SSLEncodedDHKeyParamsLen(SSLContext *ctx) -{ - SSLBuffer prime; - SSLBuffer generator; - - sslDecodeDhParams(&ctx->dhParamsEncoded, &prime, &generator); - - return (2+prime.length+2+generator.length+2+ctx->dhExchangePublic.length); -} - -/* - * Encode DH params and public key, in wire format, in caller-supplied buffer. - */ -static OSStatus -SSLEncodeDHKeyParams( - SSLContext *ctx, - uint8_t *charPtr) -{ - assert(ctx->protocolSide == kSSLServerSide); - assert(ctx->dhParamsEncoded.data != NULL); - assert(ctx->dhExchangePublic.data != NULL); - - SSLBuffer prime; - SSLBuffer generator; - - sslDecodeDhParams(&ctx->dhParamsEncoded, &prime, &generator); - - charPtr = SSLEncodeInt(charPtr, prime.length, 2); - memcpy(charPtr, prime.data, prime.length); - charPtr += prime.length; - - charPtr = SSLEncodeInt(charPtr, generator.length, 2); - memcpy(charPtr, generator.data, - generator.length); - charPtr += generator.length; - - /* TODO: hum.... sounds like this one should be in the SecDHContext */ - charPtr = SSLEncodeInt(charPtr, ctx->dhExchangePublic.length, 2); - memcpy(charPtr, ctx->dhExchangePublic.data, - ctx->dhExchangePublic.length); - - dumpBuf("server prime", &prime); - dumpBuf("server generator", &generator); - dumpBuf("server pub key", &ctx->dhExchangePublic); - - return errSecSuccess; -} - -/* - * Decode DH params and server public key. - */ -static OSStatus -SSLDecodeDHKeyParams( - SSLContext *ctx, - uint8_t **charPtr, // IN/OUT - size_t length) -{ - OSStatus err = errSecSuccess; - SSLBuffer prime; - SSLBuffer generator; - - assert(ctx->protocolSide == kSSLClientSide); - uint8_t *endCp = *charPtr + length; - - /* Allow reuse via renegotiation */ - SSLFreeBuffer(&ctx->dhPeerPublic); - - /* Prime, with a two-byte length */ - UInt32 len = SSLDecodeInt(*charPtr, 2); - (*charPtr) += 2; - if((*charPtr + len) > endCp) { - return errSSLProtocol; - } - - prime.data = *charPtr; - prime.length = len; - - (*charPtr) += len; - - /* Generator, with a two-byte length */ - len = SSLDecodeInt(*charPtr, 2); - (*charPtr) += 2; - if((*charPtr + len) > endCp) { - return errSSLProtocol; - } - - generator.data = *charPtr; - generator.length = len; - - (*charPtr) += len; - - sslEncodeDhParams(&ctx->dhParamsEncoded, &prime, &generator); - - /* peer public key, with a two-byte length */ - len = SSLDecodeInt(*charPtr, 2); - (*charPtr) += 2; - err = SSLAllocBuffer(&ctx->dhPeerPublic, len); - if(err) { - return err; - } - memmove(ctx->dhPeerPublic.data, *charPtr, len); - (*charPtr) += len; - - dumpBuf("client peer pub", &ctx->dhPeerPublic); - // dumpBuf("client prime", &ctx->dhParamsPrime); - // dumpBuf("client generator", &ctx->dhParamsGenerator); - - return err; -} - -/* - * Given the server's Diffie-Hellman parameters, generate our - * own DH key pair, and perform key exchange using the server's - * public key and our private key. The result is the premaster - * secret. - * - * SSLContext members valid on entry: - * dhParamsPrime - * dhParamsGenerator - * dhPeerPublic - * - * SSLContext members valid on successful return: - * dhPrivate - * dhExchangePublic - * preMasterSecret - */ -static OSStatus -SSLGenClientDHKeyAndExchange(SSLContext *ctx) -{ - OSStatus ortn; - -#if USE_CDSA_CRYPTO - - if((ctx->dhParamsPrime.data == NULL) || - (ctx->dhParamsGenerator.data == NULL) || - (ctx->dhPeerPublic.data == NULL)) { - sslErrorLog("SSLGenClientDHKeyAndExchange: incomplete server params\n"); - return errSSLProtocol; - } - - /* generate two keys */ - CSSM_KEY pubKey; - ctx->dhPrivate = (CSSM_KEY *)sslMalloc(sizeof(CSSM_KEY)); - ortn = sslDhGenKeyPairClient(ctx, - &ctx->dhParamsPrime, - &ctx->dhParamsGenerator, - &pubKey, ctx->dhPrivate); - if(ortn) { - sslFree(ctx->dhPrivate); - ctx->dhPrivate = NULL; - return ortn; - } - - /* do the exchange, size of prime */ - ortn = sslDhKeyExchange(ctx, ctx->dhParamsPrime.length * 8, - &ctx->preMasterSecret); - if(ortn) { - return ortn; - } - CSSM_TO_SSLBUF(&pubKey.KeyData, &ctx->dhExchangePublic); -#else - ortn=errSSLProtocol; - require(ctx->dhParamsEncoded.data, out); - require_noerr(ortn = sslDhCreateKey(ctx), out); - require_noerr(ortn = sslDhGenerateKeyPair(ctx), out); - require_noerr(ortn = sslDhKeyExchange(ctx), out); -out: -#endif - return ortn; -} - - -static OSStatus -SSLEncodeDHanonServerKeyExchange(SSLRecord *keyExch, SSLContext *ctx) -{ - OSStatus ortn = errSecSuccess; - int head; - - assert(ctx->negProtocolVersion >= SSL_Version_3_0); - assert(ctx->protocolSide == kSSLServerSide); - - /* - * Obtain D-H parameters (if we don't have them) and a key pair. - */ - ortn = SSLGenServerDHParamsAndKey(ctx); - if(ortn) { - return ortn; - } - - size_t length = SSLEncodedDHKeyParamsLen(ctx); - - keyExch->protocolVersion = ctx->negProtocolVersion; - keyExch->contentType = SSL_RecordTypeHandshake; - head = SSLHandshakeHeaderSize(keyExch); - if ((ortn = SSLAllocBuffer(&keyExch->contents, length+head))) - return ortn; - - uint8_t *charPtr = SSLEncodeHandshakeHeader(ctx, keyExch, SSL_HdskServerKeyExchange, length); - - /* encode prime, generator, our public key */ - return SSLEncodeDHKeyParams(ctx, charPtr); -} - -static OSStatus -SSLDecodeDHanonServerKeyExchange(SSLBuffer message, SSLContext *ctx) -{ - OSStatus err = errSecSuccess; - - assert(ctx->protocolSide == kSSLClientSide); - if (message.length < 6) { - sslErrorLog("SSLDecodeDHanonServerKeyExchange error: msg len %u\n", - (unsigned)message.length); - return errSSLProtocol; - } - uint8_t *charPtr = message.data; - err = SSLDecodeDHKeyParams(ctx, &charPtr, message.length); - if(err == errSecSuccess) { - if((message.data + message.length) != charPtr) { - err = errSSLProtocol; - } - } - return err; -} - -static OSStatus -SSLDecodeDHClientKeyExchange(SSLBuffer keyExchange, SSLContext *ctx) -{ - OSStatus ortn = errSecSuccess; - unsigned int publicLen; - - assert(ctx->protocolSide == kSSLServerSide); - if(ctx->dhParamsEncoded.data == NULL) { - /* should never happen */ - assert(0); - return errSSLInternal; - } - - /* this message simply contains the client's public DH key */ - uint8_t *charPtr = keyExchange.data; - publicLen = SSLDecodeInt(charPtr, 2); - charPtr += 2; - /* TODO : Check the len here ? Will fail in sslDhKeyExchange anyway */ - /* - if((keyExchange.length != publicLen + 2) || - (publicLen > ctx->dhParamsPrime.length)) { - return errSSLProtocol; - } - */ - SSLFreeBuffer(&ctx->dhPeerPublic); // allow reuse via renegotiation - ortn = SSLAllocBuffer(&ctx->dhPeerPublic, publicLen); - if(ortn) { - return ortn; - } - memmove(ctx->dhPeerPublic.data, charPtr, publicLen); - - /* DH Key exchange, result --> premaster secret */ - SSLFreeBuffer(&ctx->preMasterSecret); -#if USE_CDSA_CRYPTO - ortn = sslDhKeyExchange(ctx, ctx->dhParamsPrime.length * 8, - &ctx->preMasterSecret); -#else - ortn = sslDhKeyExchange(ctx); -#endif - dumpBuf("server peer pub", &ctx->dhPeerPublic); - dumpBuf("server premaster", &ctx->preMasterSecret); - return ortn; -} - -static OSStatus -SSLEncodeDHClientKeyExchange(SSLRecord *keyExchange, SSLContext *ctx) -{ OSStatus err; - size_t outputLen; - int head; - - assert(ctx->protocolSide == kSSLClientSide); - assert(ctx->negProtocolVersion >= SSL_Version_3_0); - - keyExchange->contentType = SSL_RecordTypeHandshake; - keyExchange->protocolVersion = ctx->negProtocolVersion; - - if ((err = SSLGenClientDHKeyAndExchange(ctx)) != 0) - return err; - - outputLen = ctx->dhExchangePublic.length + 2; - head = SSLHandshakeHeaderSize(keyExchange); - if ((err = SSLAllocBuffer(&keyExchange->contents,outputLen + head))) - return err; - - uint8_t *charPtr = SSLEncodeHandshakeHeader(ctx, keyExchange, SSL_HdskClientKeyExchange, outputLen); - - charPtr = SSLEncodeSize(charPtr, ctx->dhExchangePublic.length, 2); - memcpy(charPtr, ctx->dhExchangePublic.data, ctx->dhExchangePublic.length); - - dumpBuf("client pub key", &ctx->dhExchangePublic); - dumpBuf("client premaster", &ctx->preMasterSecret); - - return errSecSuccess; -} - -#endif /* APPLE_DH */ - -// MARK: - -// MARK: ECDSA Key Exchange - -/* - * Given the server's ECDH curve params and public key, generate our - * own ECDH key pair, and perform key exchange using the server's - * public key and our private key. The result is the premaster - * secret. - * - * SSLContext members valid on entry: - * if keyExchangeMethod == SSL_ECDHE_ECDSA or SSL_ECDHE_RSA: - * ecdhPeerPublic - * ecdhPeerCurve - * if keyExchangeMethod == SSL_ECDH_ECDSA or SSL_ECDH_RSA: - * peerPubKey, from which we infer ecdhPeerCurve - * - * SSLContext members valid on successful return: - * ecdhPrivate - * ecdhExchangePublic - * preMasterSecret - */ -static OSStatus -SSLGenClientECDHKeyAndExchange(SSLContext *ctx) -{ - OSStatus ortn; - - assert(ctx->protocolSide == kSSLClientSide); - - switch(ctx->selectedCipherSpecParams.keyExchangeMethod) { - case SSL_ECDHE_ECDSA: - case SSL_ECDHE_RSA: - /* Server sent us an ephemeral key with peer curve specified */ - if(ctx->ecdhPeerPublic.data == NULL) { - sslErrorLog("SSLGenClientECDHKeyAndExchange: incomplete server params\n"); - return errSSLProtocol; - } - break; - case SSL_ECDH_ECDSA: - case SSL_ECDH_RSA: - { - /* No server key exchange; we have to get the curve from the key */ - if(ctx->peerPubKey == NULL) { - sslErrorLog("SSLGenClientECDHKeyAndExchange: no peer key\n"); - return errSSLInternal; - } - - /* The peer curve is in the key's CSSM_X509_ALGORITHM_IDENTIFIER... */ - ortn = sslEcdsaPeerCurve(ctx->peerPubKey, &ctx->ecdhPeerCurve); - if(ortn) { - return ortn; - } - sslEcdsaDebug("SSLGenClientECDHKeyAndExchange: derived peerCurve %u", - (unsigned)ctx->ecdhPeerCurve); - break; - } - default: - /* shouldn't be here */ - assert(0); - return errSSLInternal; - } - - /* Generate our (ephemeral) pair, or extract it from our signing identity */ - if((ctx->negAuthType == SSLClientAuth_RSAFixedECDH) || - (ctx->negAuthType == SSLClientAuth_ECDSAFixedECDH)) { - /* - * Client auth with a fixed ECDH key in the cert. Convert private key - * from SecKeyRef to CSSM format. We don't need ecdhExchangePublic - * because the server gets that from our cert. - */ - assert(ctx->signingPrivKeyRef != NULL); -#if USE_CDSA_CRYPTO - //assert(ctx->cspHand != 0); - sslFreeKey(ctx->cspHand, &ctx->ecdhPrivate, NULL); - SSLFreeBuffer(&ctx->ecdhExchangePublic); - ortn = SecKeyGetCSSMKey(ctx->signingPrivKeyRef, (const CSSM_KEY **)&ctx->ecdhPrivate); - if(ortn) { - return ortn; - } - ortn = SecKeyGetCSPHandle(ctx->signingPrivKeyRef, &ctx->ecdhPrivCspHand); - if(ortn) { - sslErrorLog("SSLGenClientECDHKeyAndExchange: SecKeyGetCSPHandle err %d\n", - (int)ortn); - } -#endif - sslEcdsaDebug("+++ Extracted ECDH private key"); - } - else { - /* generate a new pair */ - ortn = sslEcdhGenerateKeyPair(ctx, ctx->ecdhPeerCurve); - if(ortn) { - return ortn; - } -#if USE_CDSA_CRYPTO - sslEcdsaDebug("+++ Generated %u bit (%u byte) ECDH key pair", - (unsigned)ctx->ecdhPrivate->KeyHeader.LogicalKeySizeInBits, - (unsigned)((ctx->ecdhPrivate->KeyHeader.LogicalKeySizeInBits + 7) / 8)); -#endif - } - - - /* do the exchange --> premaster secret */ - ortn = sslEcdhKeyExchange(ctx, &ctx->preMasterSecret); - if(ortn) { - return ortn; - } - return errSecSuccess; -} - - -/* - * Decode ECDH params and server public key. - */ -static OSStatus -SSLDecodeECDHKeyParams( - SSLContext *ctx, - uint8_t **charPtr, // IN/OUT - size_t length) -{ - OSStatus err = errSecSuccess; - - sslEcdsaDebug("+++ Decoding ECDH Server Key Exchange"); - - assert(ctx->protocolSide == kSSLClientSide); - uint8_t *endCp = *charPtr + length; - - /* Allow reuse via renegotiation */ - SSLFreeBuffer(&ctx->ecdhPeerPublic); - - /*** ECParameters - just a curveType and a named curve ***/ - - /* 1-byte curveType, we only allow one type */ - uint8_t curveType = **charPtr; - if(curveType != SSL_CurveTypeNamed) { - sslEcdsaDebug("+++ SSLDecodeECDHKeyParams: Bad curveType (%u)\n", (unsigned)curveType); - return errSSLProtocol; - } - (*charPtr)++; - if(*charPtr > endCp) { - return errSSLProtocol; - } - - /* two-byte curve */ - ctx->ecdhPeerCurve = SSLDecodeInt(*charPtr, 2); - (*charPtr) += 2; - if(*charPtr > endCp) { - return errSSLProtocol; - } - switch(ctx->ecdhPeerCurve) { - case SSL_Curve_secp256r1: - case SSL_Curve_secp384r1: - case SSL_Curve_secp521r1: - break; - default: - sslEcdsaDebug("+++ SSLDecodeECDHKeyParams: Bad curve (%u)\n", - (unsigned)ctx->ecdhPeerCurve); - return errSSLProtocol; - } - - sslEcdsaDebug("+++ SSLDecodeECDHKeyParams: ecdhPeerCurve %u", - (unsigned)ctx->ecdhPeerCurve); - - /*** peer public key as an ECPoint ***/ - - /* - * The spec says the the max length of an ECPoint is 255 bytes, limiting - * this whole mechanism to a max modulus size of 1020 bits, which I find - * hard to believe... - */ - UInt32 len = SSLDecodeInt(*charPtr, 1); - (*charPtr)++; - if((*charPtr + len) > endCp) { - return errSSLProtocol; - } - err = SSLAllocBuffer(&ctx->ecdhPeerPublic, len); - if(err) { - return err; - } - memmove(ctx->ecdhPeerPublic.data, *charPtr, len); - (*charPtr) += len; - - dumpBuf("client peer pub", &ctx->ecdhPeerPublic); - - return err; -} - - -static OSStatus -SSLEncodeECDHClientKeyExchange(SSLRecord *keyExchange, SSLContext *ctx) -{ OSStatus err; - size_t outputLen; - int head; - - assert(ctx->protocolSide == kSSLClientSide); - if ((err = SSLGenClientECDHKeyAndExchange(ctx)) != 0) - return err; - - /* - * Per RFC 4492 5.7, if we're doing ECDSA_fixed_ECDH or RSA_fixed_ECDH - * client auth, we still send this message, but it's empty (because the - * server gets our public key from our cert). - */ - bool emptyMsg = false; - switch(ctx->negAuthType) { - case SSLClientAuth_RSAFixedECDH: - case SSLClientAuth_ECDSAFixedECDH: - emptyMsg = true; - break; - default: - break; - } - if(emptyMsg) { - outputLen = 0; - } - else { - outputLen = ctx->ecdhExchangePublic.length + 1; - } - - keyExchange->contentType = SSL_RecordTypeHandshake; - assert(ctx->negProtocolVersion >= SSL_Version_3_0); - keyExchange->protocolVersion = ctx->negProtocolVersion; - head = SSLHandshakeHeaderSize(keyExchange); - if ((err = SSLAllocBuffer(&keyExchange->contents,outputLen + head))) - return err; - - uint8_t *charPtr = SSLEncodeHandshakeHeader(ctx, keyExchange, SSL_HdskClientKeyExchange, outputLen); - if(emptyMsg) { - sslEcdsaDebug("+++ Sending EMPTY ECDH Client Key Exchange"); - } - else { - /* just a 1-byte length here... */ - charPtr = SSLEncodeSize(charPtr, ctx->ecdhExchangePublic.length, 1); - memcpy(charPtr, ctx->ecdhExchangePublic.data, ctx->ecdhExchangePublic.length); - sslEcdsaDebug("+++ Encoded ECDH Client Key Exchange"); - } - - dumpBuf("client pub key", &ctx->ecdhExchangePublic); - dumpBuf("client premaster", &ctx->preMasterSecret); - return errSecSuccess; -} - - - -static OSStatus -SSLDecodePSKClientKeyExchange(SSLBuffer keyExchange, SSLContext *ctx) -{ - OSStatus ortn = errSecSuccess; - unsigned int identityLen; - - assert(ctx->protocolSide == kSSLServerSide); - - /* this message simply contains the client's PSK identity */ - uint8_t *charPtr = keyExchange.data; - identityLen = SSLDecodeInt(charPtr, 2); - charPtr += 2; - - SSLFreeBuffer(&ctx->pskIdentity); // allow reuse via renegotiation - ortn = SSLAllocBuffer(&ctx->pskIdentity, identityLen); - if(ortn) { - return ortn; - } - memmove(ctx->pskIdentity.data, charPtr, identityLen); - - /* TODO: At this point we know the identity of the PSK client, - we should break out of the handshake, so we can select the appropriate - PreShared secret. As this stands, the preshared secret needs to be known - before the handshake starts. */ - - size_t n=ctx->pskSharedSecret.length; - - if(n==0) return errSSLBadConfiguration; - - if ((ortn = SSLAllocBuffer(&ctx->preMasterSecret, 2*(n+2))) != 0) - return ortn; - - uint8_t *p=ctx->preMasterSecret.data; - - p = SSLEncodeInt(p, n, 2); - memset(p, 0, n); p+=n; - p = SSLEncodeInt(p, n, 2); - memcpy(p, ctx->pskSharedSecret.data, n); - - dumpBuf("server premaster (PSK)", &ctx->preMasterSecret); - - return ortn; -} - - -static OSStatus -SSLEncodePSKClientKeyExchange(SSLRecord *keyExchange, SSLContext *ctx) -{ - OSStatus err; - size_t outputLen; - int head; - - assert(ctx->protocolSide == kSSLClientSide); - - outputLen = ctx->pskIdentity.length+2; - - keyExchange->contentType = SSL_RecordTypeHandshake; - assert(ctx->negProtocolVersion >= SSL_Version_3_0); - keyExchange->protocolVersion = ctx->negProtocolVersion; - head = SSLHandshakeHeaderSize(keyExchange); - if ((err = SSLAllocBuffer(&keyExchange->contents,outputLen + head))) - return err; - - uint8_t *charPtr = SSLEncodeHandshakeHeader(ctx, keyExchange, SSL_HdskClientKeyExchange, outputLen); - - charPtr = SSLEncodeSize(charPtr, ctx->pskIdentity.length, 2); - memcpy(charPtr, ctx->pskIdentity.data, ctx->pskIdentity.length); - - - /* We better have a pskSharedSecret already */ - size_t n=ctx->pskSharedSecret.length; - - if(n==0) return errSSLBadConfiguration; - - if ((err = SSLAllocBuffer(&ctx->preMasterSecret, 2*(n+2))) != 0) - return err; - - uint8_t *p=ctx->preMasterSecret.data; - - p = SSLEncodeInt(p, n, 2); - memset(p, 0, n); p+=n; - p = SSLEncodeInt(p, n, 2); - memcpy(p, ctx->pskSharedSecret.data, n); - - dumpBuf("client premaster (PSK)", &ctx->preMasterSecret); - - return errSecSuccess; -} - - -// MARK: - -// MARK: Public Functions -OSStatus -SSLEncodeServerKeyExchange(SSLRecord *keyExch, SSLContext *ctx) -{ OSStatus err; - - switch (ctx->selectedCipherSpecParams.keyExchangeMethod) - { case SSL_RSA: - case SSL_RSA_EXPORT: - #if APPLE_DH - case SSL_DHE_RSA: - case SSL_DHE_RSA_EXPORT: - case SSL_DHE_DSS: - case SSL_DHE_DSS_EXPORT: - #endif /* APPLE_DH */ - if ((err = SSLEncodeSignedServerKeyExchange(keyExch, ctx)) != 0) - return err; - break; - #if APPLE_DH - case SSL_DH_anon: - case SSL_DH_anon_EXPORT: - if ((err = SSLEncodeDHanonServerKeyExchange(keyExch, ctx)) != 0) - return err; - break; - #endif - default: - return errSecUnimplemented; - } - - return errSecSuccess; -} - -OSStatus -SSLProcessServerKeyExchange(SSLBuffer message, SSLContext *ctx) -{ - OSStatus err; - - switch (ctx->selectedCipherSpecParams.keyExchangeMethod) { - case SSL_RSA: - case SSL_RSA_EXPORT: - #if APPLE_DH - case SSL_DHE_RSA: - case SSL_DHE_RSA_EXPORT: - case SSL_DHE_DSS: - case SSL_DHE_DSS_EXPORT: - #endif - case SSL_ECDHE_ECDSA: - case SSL_ECDHE_RSA: - err = SSLDecodeSignedServerKeyExchange(message, ctx); - break; - #if APPLE_DH - case SSL_DH_anon: - case SSL_DH_anon_EXPORT: - err = SSLDecodeDHanonServerKeyExchange(message, ctx); - break; - #endif - default: - err = errSecUnimplemented; - break; - } - - return err; -} - -OSStatus -SSLEncodeKeyExchange(SSLRecord *keyExchange, SSLContext *ctx) -{ OSStatus err; - - assert(ctx->protocolSide == kSSLClientSide); - - switch (ctx->selectedCipherSpecParams.keyExchangeMethod) { - case SSL_RSA: - case SSL_RSA_EXPORT: - sslDebugLog("SSLEncodeKeyExchange: RSA method\n"); - err = SSLEncodeRSAKeyExchange(keyExchange, ctx); - break; -#if APPLE_DH - case SSL_DHE_RSA: - case SSL_DHE_RSA_EXPORT: - case SSL_DHE_DSS: - case SSL_DHE_DSS_EXPORT: - case SSL_DH_anon: - case SSL_DH_anon_EXPORT: - sslDebugLog("SSLEncodeKeyExchange: DH method\n"); - err = SSLEncodeDHClientKeyExchange(keyExchange, ctx); - break; -#endif - case SSL_ECDH_ECDSA: - case SSL_ECDHE_ECDSA: - case SSL_ECDH_RSA: - case SSL_ECDHE_RSA: - case SSL_ECDH_anon: - sslDebugLog("SSLEncodeKeyExchange: ECDH method\n"); - err = SSLEncodeECDHClientKeyExchange(keyExchange, ctx); - break; - case TLS_PSK: - err = SSLEncodePSKClientKeyExchange(keyExchange, ctx); - break; - default: - sslErrorLog("SSLEncodeKeyExchange: unknown method (%d)\n", - ctx->selectedCipherSpecParams.keyExchangeMethod); - err = errSecUnimplemented; - } - - return err; -} - -OSStatus -SSLProcessKeyExchange(SSLBuffer keyExchange, SSLContext *ctx) -{ OSStatus err; - - switch (ctx->selectedCipherSpecParams.keyExchangeMethod) - { case SSL_RSA: - case SSL_RSA_EXPORT: - if ((err = SSLDecodeRSAKeyExchange(keyExchange, ctx)) != 0) - return err; - break; - #if APPLE_DH - case SSL_DH_anon: - case SSL_DHE_DSS: - case SSL_DHE_DSS_EXPORT: - case SSL_DHE_RSA: - case SSL_DHE_RSA_EXPORT: - case SSL_DH_anon_EXPORT: - sslDebugLog("SSLProcessKeyExchange: processing DH key exchange (%d)\n", - ctx->selectedCipherSpecParams.keyExchangeMethod); - if ((err = SSLDecodeDHClientKeyExchange(keyExchange, ctx)) != 0) - return err; - break; -#endif - case TLS_PSK: - if ((err = SSLDecodePSKClientKeyExchange(keyExchange, ctx)) != 0) - return err; - break; - default: - sslErrorLog("SSLProcessKeyExchange: unknown keyExchangeMethod (%d)\n", - ctx->selectedCipherSpecParams.keyExchangeMethod); - return errSecUnimplemented; - } - - return errSecSuccess; -} - -OSStatus -SSLInitPendingCiphers(SSLContext *ctx) -{ OSStatus err; - SSLBuffer key; - int keyDataLen; - - err = errSecSuccess; - key.data = 0; - - keyDataLen = ctx->selectedCipherSpecParams.macSize + - ctx->selectedCipherSpecParams.keySize + - ctx->selectedCipherSpecParams.ivSize; - keyDataLen *= 2; /* two of everything */ - - if ((err = SSLAllocBuffer(&key, keyDataLen))) - return err; - assert(ctx->sslTslCalls != NULL); - if ((err = ctx->sslTslCalls->generateKeyMaterial(key, ctx)) != 0) - goto fail; - - if((err = ctx->recFuncs->initPendingCiphers(ctx->recCtx, ctx->selectedCipher, (ctx->protocolSide==kSSLServerSide), key)) != 0) - goto fail; - - ctx->writePending_ready = 1; - ctx->readPending_ready = 1; - -fail: - SSLFreeBuffer(&key); - return err; -} diff --git a/libsecurity_ssl/lib/sslKeychain.c b/libsecurity_ssl/lib/sslKeychain.c deleted file mode 100644 index 5e80e622..00000000 --- a/libsecurity_ssl/lib/sslKeychain.c +++ /dev/null @@ -1,489 +0,0 @@ -/* - * Copyright (c) 1999-2001,2005-2008,2010-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * 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@ - */ - -/* - * sslKeychain.c - Apple Keychain routines - */ - -#include "ssl.h" -#include "sslContext.h" -#include "sslMemory.h" - -#include "sslCrypto.h" -#ifdef USE_CDSA_CRYPTO -#include -#else -#include -#include -#include -#include -#include -#endif /* !USE_CDSA_CRYPTO */ -#include "utilities/SecCFRelease.h" - -#include "sslDebug.h" -#include "sslKeychain.h" -#include "sslUtils.h" -#include -#include - -#if TARGET_OS_IPHONE -#include "utilities/SecCFRelease.h" -#endif - -#ifdef USE_SSLCERTIFICATE - -/* - * Given an array of certs (as SecIdentityRefs, specified by caller - * in SSLSetCertificate or SSLSetEncryptionCertificate) and a - * destination SSLCertificate: - * - * -- free destCerts if we have any - * -- Get raw cert data, convert to array of SSLCertificates in *destCert - * -- validate cert chain - * -- get pub, priv keys from certRef[0], store in *pubKey, *privKey - */ - -/* Convert a SecCertificateRef to an SSLCertificate * */ -static OSStatus secCertToSslCert( - SSLContext *ctx, - SecCertificateRef certRef, - SSLCertificate **sslCert) -{ - CSSM_DATA certData; // struct is transient, referent owned by - // Sec layer - OSStatus ortn; - SSLCertificate *thisSslCert = NULL; - - ortn = SecCertificateGetData(certRef, &certData); - if(ortn) { - sslErrorLog("SecCertificateGetData() returned %d\n", (int)ortn); - return ortn; - } - - thisSslCert = (SSLCertificate *)sslMalloc(sizeof(SSLCertificate)); - if(thisSslCert == NULL) { - return errSecAllocate; - } - if(SSLAllocBuffer(&thisSslCert->derCert, certData.Length, - ctx)) { - return errSecAllocate; - } - memcpy(thisSslCert->derCert.data, certData.Data, certData.Length); - thisSslCert->derCert.length = certData.Length; - *sslCert = thisSslCert; - return errSecSuccess; -} - -/* - * Determine the basic signing algorithm, without the digest, component, of - * a cert. The returned algorithm will be RSA, DSA, or ECDSA. - */ -static OSStatus sslCertSignerAlg( - SecCertificateRef certRef, - CSSM_ALGORITHMS *signerAlg) -{ - OSStatus ortn; - CSSM_DATA_PTR fieldPtr; - CSSM_X509_ALGORITHM_IDENTIFIER *algId; - CSSM_ALGORITHMS sigAlg; - - /* - * Extract the full signature algorithm OID - */ - *signerAlg = CSSM_ALGID_NONE; - ortn = SecCertificateCopyFirstFieldValue(certRef, - &CSSMOID_X509V1SignatureAlgorithm, - &fieldPtr); - if(ortn) { - return ortn; - } - if(fieldPtr->Length != sizeof(CSSM_X509_ALGORITHM_IDENTIFIER)) { - sslErrorLog("sslCertSignerAlg() length error\n"); - ortn = errSSLCrypto; - goto errOut; - } - algId = (CSSM_X509_ALGORITHM_IDENTIFIER *)fieldPtr->Data; - if(!cssmOidToAlg(&algId->algorithm, &sigAlg)) { - /* Only way this could happen is if we're given a bad cert */ - sslErrorLog("sslCertSignerAlg() bad sigAlg OID\n"); - ortn = errSecParam; - goto errOut; - } - - /* - * OK we have the full signature algorithm as a CSSM_ALGORITHMS. - * Extract the core signature alg. - */ - switch(sigAlg) { - case CSSM_ALGID_RSA: - case CSSM_ALGID_MD2WithRSA: - case CSSM_ALGID_MD5WithRSA: - case CSSM_ALGID_SHA1WithRSA: - case CSSM_ALGID_SHA224WithRSA: - case CSSM_ALGID_SHA256WithRSA: - case CSSM_ALGID_SHA384WithRSA: - case CSSM_ALGID_SHA512WithRSA: - *signerAlg = CSSM_ALGID_RSA; - break; - case CSSM_ALGID_SHA1WithECDSA: - case CSSM_ALGID_SHA224WithECDSA: - case CSSM_ALGID_SHA256WithECDSA: - case CSSM_ALGID_SHA384WithECDSA: - case CSSM_ALGID_SHA512WithECDSA: - case CSSM_ALGID_ECDSA: - case CSSM_ALGID_ECDSA_SPECIFIED: - *signerAlg = CSSM_ALGID_ECDSA; - break; - case CSSM_ALGID_DSA: - case CSSM_ALGID_SHA1WithDSA: - *signerAlg = CSSM_ALGID_DSA; - break; - default: - sslErrorLog("sslCertSignerAlg() unknown sigAlg\n"); - ortn = errSecParam; - break; - } -errOut: - SecCertificateReleaseFirstFieldValue(certRef, - &CSSMOID_X509V1SignatureAlgorithm, fieldPtr); - return ortn; -} - -OSStatus -parseIncomingCerts( - SSLContext *ctx, - CFArrayRef certs, - SSLCertificate **destCert, /* &ctx->{localCert,encryptCert} */ - CSSM_KEY_PTR *pubKey, /* &ctx->signingPubKey, etc. */ - SecKeyRef *privKeyRef, /* &ctx->signingPrivKeyRef, etc. */ - CSSM_ALGORITHMS *signerAlg) /* optional */ -{ - CFIndex numCerts; - CFIndex cert; - SSLCertificate *certChain = NULL; - SSLCertificate *thisSslCert; - OSStatus ortn; - SecIdentityRef identity; - SecCertificateRef certRef; - SecKeyRef keyRef; - CSSM_DATA certData; - CSSM_CL_HANDLE clHand; // carefully derive from a SecCertificateRef - CSSM_RETURN crtn; - CSSM_KEY_PTR *pubKey; - SecKeyRef *privKeyRef; - - assert(ctx != NULL); - assert(destCert != NULL); /* though its referent may be NULL */ - assert(sslPubKey != NULL); - assert(sslPrivKeyRef != NULL); - - pubKey = &sslPubKey->key; - privKeyRef = &sslPrivKey->key; - - sslDeleteCertificateChain(*destCert, ctx); - *destCert = NULL; - *pubKey = NULL; - *privKeyRef = NULL; - - if(certs == NULL) { - sslErrorLog("parseIncomingCerts: NULL incoming cert array\n"); - return errSSLBadCert; - } - numCerts = CFArrayGetCount(certs); - if(numCerts == 0) { - sslErrorLog("parseIncomingCerts: empty incoming cert array\n"); - return errSSLBadCert; - } - - /* - * Certs[0] is an SecIdentityRef from which we extract subject cert, - * privKeyRef, pubKey. - * - * 1. ensure the first element is a SecIdentityRef. - */ - identity = (SecIdentityRef)CFArrayGetValueAtIndex(certs, 0); - if(identity == NULL) { - sslErrorLog("parseIncomingCerts: bad cert array (1)\n"); - return errSecParam; - } - if(CFGetTypeID(identity) != SecIdentityGetTypeID()) { - sslErrorLog("parseIncomingCerts: bad cert array (2)\n"); - return errSecParam; - } - - /* - * 2. Extract cert, keys and convert to local format. - */ - ortn = SecIdentityCopyCertificate(identity, &certRef); - if(ortn) { - sslErrorLog("parseIncomingCerts: bad cert array (3)\n"); - return ortn; - } - ortn = secCertToSslCert(ctx, certRef, &thisSslCert); - if(ortn) { - sslErrorLog("parseIncomingCerts: bad cert array (4)\n"); - return ortn; - } - /* enqueue onto head of cert chain */ - thisSslCert->next = certChain; - certChain = thisSslCert; - - if(signerAlg != NULL) { - ortn = sslCertSignerAlg(certRef, signerAlg); - if(ortn) { - return ortn; - } - } - - /* fetch private key from identity */ - ortn = SecIdentityCopyPrivateKey(identity, &keyRef); - if(ortn) { - sslErrorLog("parseIncomingCerts: SecIdentityCopyPrivateKey err %d\n", - (int)ortn); - return ortn; - } - *privKeyRef = keyRef; - - /* obtain public key from cert */ - ortn = SecCertificateGetCLHandle(certRef, &clHand); - if(ortn) { - sslErrorLog("parseIncomingCerts: SecCertificateGetCLHandle err %d\n", - (int)ortn); - return ortn; - } - certData.Data = thisSslCert->derCert.data; - certData.Length = thisSslCert->derCert.length; - crtn = CSSM_CL_CertGetKeyInfo(clHand, &certData, pubKey); - if(crtn) { - sslErrorLog("parseIncomingCerts: CSSM_CL_CertGetKeyInfo err\n"); - return (OSStatus)crtn; - } - - /* OK, that's the subject cert. Fetch optional remaining certs. */ - /* - * Convert: CFArray of SecCertificateRefs --> chain of SSLCertificates. - * Incoming certs have root last; SSLCertificate chain has root - * first. - */ - for(cert=1; certnext = certChain; - certChain = thisSslCert; - } - - /* SUCCESS */ - *destCert = certChain; - return errSecSuccess; - - /* free certChain, everything in it, other vars, return ortn */ - sslDeleteCertificateChain(certChain, ctx); - /* FIXME - anything else? */ - return ortn; -} - -#else /* !USE_SSLCERTIFICATE */ - -OSStatus -parseIncomingCerts( - SSLContext *ctx, - CFArrayRef certs, - CFArrayRef *destCertChain, /* &ctx->{localCertChain,encryptCertChain} */ - SSLPubKey **sslPubKey, /* &ctx->signingPubKey, etc. */ - SSLPrivKey **sslPrivKey, /* &ctx->signingPrivKeyRef, etc. */ - CFIndex *signerAlg) /* optional */ -{ - OSStatus ortn; - CFIndex ix, numCerts; - SecIdentityRef identity; - CFMutableArrayRef certChain = NULL; /* Retained */ - SecCertificateRef leafCert = NULL; /* Retained */ - SecKeyRef pubKey = NULL; /* Retained */ - SecKeyRef privKey = NULL; /* Retained */ - SecTrustRef trust = NULL; /* Retained */ - - assert(ctx != NULL); - assert(destCertChain != NULL); /* though its referent may be NULL */ - assert(sslPubKey != NULL); - assert(sslPrivKey != NULL); - - if (certs == NULL) { - sslErrorLog("parseIncomingCerts: NULL incoming cert array\n"); - ortn = errSSLBadCert; - goto errOut; - } - numCerts = CFArrayGetCount(certs); - if (numCerts == 0) { - sslErrorLog("parseIncomingCerts: empty incoming cert array\n"); - ortn = errSSLBadCert; - goto errOut; - } - - /* - * Certs[0] is an SecIdentityRef from which we extract subject cert, - * privKey, pubKey. - * - * 1. ensure the first element is a SecIdentityRef. - */ - identity = (SecIdentityRef)CFArrayGetValueAtIndex(certs, 0); - if (identity == NULL) { - sslErrorLog("parseIncomingCerts: bad cert array (1)\n"); - ortn = errSecParam; - goto errOut; - } - if (CFGetTypeID(identity) != SecIdentityGetTypeID()) { - sslErrorLog("parseIncomingCerts: bad cert array (2)\n"); - ortn = errSecParam; - goto errOut; - } - - /* - * 2. Extract cert, keys and convert to local format. - */ - ortn = SecIdentityCopyCertificate(identity, &leafCert); - if (ortn) { - sslErrorLog("parseIncomingCerts: bad cert array (3)\n"); - goto errOut; - } - - /* Fetch private key from identity */ - ortn = SecIdentityCopyPrivateKey(identity, &privKey); - if (ortn) { - sslErrorLog("parseIncomingCerts: SecIdentityCopyPrivateKey err %d\n", - (int)ortn); - goto errOut; - } - - /* Convert the input array of SecIdentityRef at the start to an array of - all certificates. */ - certChain = CFArrayCreateMutable(kCFAllocatorDefault, numCerts, - &kCFTypeArrayCallBacks); - if (!certChain) { - ortn = errSecAllocate; - goto errOut; - } - CFArrayAppendValue(certChain, leafCert); - for (ix = 1; ix < numCerts; ++ix) { - SecCertificateRef intermediate = - (SecCertificateRef)CFArrayGetValueAtIndex(certs, ix); - if (intermediate == NULL) { - sslErrorLog("parseIncomingCerts: bad cert array (5)\n"); - ortn = errSecParam; - goto errOut; - } - if (CFGetTypeID(intermediate) != SecCertificateGetTypeID()) { - sslErrorLog("parseIncomingCerts: bad cert array (6)\n"); - ortn = errSecParam; - goto errOut; - } - - CFArrayAppendValue(certChain, intermediate); - } - - /* Obtain public key from cert */ -#if TARGET_OS_IPHONE - ortn = SecTrustCreateWithCertificates(certChain, NULL, &trust); -#else - { - SecPolicyRef policy = SecPolicyCreateBasicX509(); - ortn = SecTrustCreateWithCertificates(certChain, policy, &trust); - CFReleaseSafe(policy); - if (!ortn) { - /* We are only interested in getting the public key from the leaf - * cert here, so for best performance, don't try to build a chain - * or search any keychains. - */ - CFArrayRef emptyArray = CFArrayCreate(NULL, NULL, 0, NULL); - (void)SecTrustSetAnchorCertificates(trust, emptyArray); - (void)SecTrustSetKeychains(trust, emptyArray); - CFReleaseSafe(emptyArray); - } - } -#endif - if (ortn) { - sslErrorLog("parseIncomingCerts: SecTrustCreateWithCertificates err %d\n", - (int)ortn); - goto errOut; - } - - -#if !TARGET_OS_IPHONE - /* This is not required on iOS, but still required on osx */ - SecTrustResultType trustResult; - ortn = SecTrustEvaluate(trust, &trustResult); - if (ortn) { - sslErrorLog("parseIncomingCerts: SecTrustEvaluate err %d\n", - (int)ortn); - goto errOut; - } -#endif - - - pubKey = SecTrustCopyPublicKey(trust); - if (!pubKey) { - /* We parsed the private key succesfully but could not get the public key: return an error */ - sslErrorLog("parseIncomingCerts: SecTrustCopyPublicKey failed\n"); - ortn = errSecParam; - goto errOut; - } - - /* SUCCESS */ -errOut: - CFReleaseSafe(trust); - CFReleaseSafe(leafCert); - CFReleaseSafe(*destCertChain); - sslFreePubKey(sslPubKey); - sslFreePrivKey(sslPrivKey); - - if (ortn) { - CFReleaseSafe(certChain); - CFReleaseSafe(pubKey); - CFReleaseSafe(privKey); - - *destCertChain = NULL; - } else { - *destCertChain = certChain; - *sslPubKey = (SSLPubKey*)pubKey; - *sslPrivKey = (SSLPrivKey*)privKey; - } - - return ortn; -} -#endif /* !USE_SSLCERTIFICATE */ diff --git a/libsecurity_ssl/lib/sslKeychain.h b/libsecurity_ssl/lib/sslKeychain.h deleted file mode 100644 index f8041f81..00000000 --- a/libsecurity_ssl/lib/sslKeychain.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 1999-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * 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@ - */ - -/* - * sslKeychain.h - Apple Keychain routines - */ - -#ifndef _SSL_KEYCHAIN_H_ -#define _SSL_KEYCHAIN_H_ - - -#include "sslContext.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef USE_SSLCERTIFICATE -/* - * Given an array of certs (as KCItemRefs) and a destination - * SSLCertificate: - * - * -- free destCerts if we have any - * -- Get raw cert data, convert to array of SSLCertificates in *destCert - * -- get pub, priv keys from certRef[0], store in *pubKey, *privKey - * -- validate cert chain - * - */ -OSStatus -parseIncomingCerts( - SSLContext *ctx, - CFArrayRef certs, - SSLCertificate **destCert, /* &ctx->{localCert,encryptCert} */ - SSLPubKey **pubKey, /* &ctx->signingPubKey, etc. */ - SecKeyRef *privKeyRef, /* &ctx->signingPrivKeyRef, etc. */ - CSSM_ALGORITHMS *signerAlg); /* optionally returned */ -#else - -OSStatus -parseIncomingCerts( - SSLContext *ctx, - CFArrayRef certs, - CFArrayRef *destCertChain, /* &ctx->{localCertChain,encryptCertChain} */ - SSLPubKey **pubKey, /* &ctx->signingPubKey, etc. */ - SSLPrivKey **privKeyRef, /* &ctx->signingPrivKeyRef, etc. */ - CFIndex *signerAlg); /* optional */ - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _SSL_KEYCHAIN_H_ */ diff --git a/libsecurity_ssl/lib/sslRecord.c b/libsecurity_ssl/lib/sslRecord.c deleted file mode 100644 index 35f58180..00000000 --- a/libsecurity_ssl/lib/sslRecord.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 1999-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * 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@ - */ - -/* - * sslRecord.c - Encryption, decryption and MACing of data -*/ - -#include -#include "ssl.h" -#include "sslRecord.h" -#include "sslMemory.h" -#include "sslContext.h" -#include "sslAlertMessage.h" -#include "sslDebug.h" -#include "sslUtils.h" -#include "sslDigests.h" -#include "SSLRecordInternal.h" - -#include -#include - -#include - -/* - * Lots of servers fail to provide closure alerts when they disconnect. - * For now we'll just accept it as long as it occurs on a clean record boundary - * (and the handshake is complete). - */ -#define SSL_ALLOW_UNNOTICED_DISCONNECT 1 - - -static OSStatus errorTranslate(int recordErr) -{ - switch(recordErr) { - case errSecSuccess: - return errSecSuccess; - case errSSLRecordInternal: - return errSSLInternal; - case errSSLRecordWouldBlock: - return errSSLWouldBlock; - case errSSLRecordProtocol: - return errSSLProtocol; - case errSSLRecordNegotiation: - return errSSLNegotiation; - case errSSLRecordClosedAbort: - return errSSLClosedAbort; - case errSSLRecordConnectionRefused: - return errSSLConnectionRefused; - case errSSLRecordDecryptionFail: - return errSSLDecryptionFail; - case errSSLRecordBadRecordMac: - return errSSLBadRecordMac; - case errSSLRecordRecordOverflow: - return errSSLRecordOverflow; - case errSSLRecordUnexpectedRecord: - return errSSLUnexpectedRecord; - default: - sslErrorLog("unknown error code returned in sslErrorTranslate: %d\n", recordErr); - return recordErr; - } -} - -/* SSLWriteRecord - * Attempt to encrypt and queue an SSL record. - */ -OSStatus -SSLWriteRecord(SSLRecord rec, SSLContext *ctx) -{ - OSStatus err; - - err=errorTranslate(ctx->recFuncs->write(ctx->recCtx, rec)); - - switch(err) { - case errSecSuccess: - break; - default: - sslErrorLog("unexpected error code returned in SSLWriteRecord: %d\n", (int)err); - break; - } - - return err; -} - -/* SSLFreeRecord - * Free a record returned by SSLReadRecord. - */ -OSStatus -SSLFreeRecord(SSLRecord rec, SSLContext *ctx) -{ - return ctx->recFuncs->free(ctx->recCtx, rec); -} - -/* SSLReadRecord - * Attempt to read & decrypt an SSL record. - * Record content should be freed using SSLFreeRecord - */ -OSStatus -SSLReadRecord(SSLRecord *rec, SSLContext *ctx) -{ OSStatus err; - - err=errorTranslate(ctx->recFuncs->read(ctx->recCtx, rec)); - - switch(err) { - case errSecSuccess: - case errSSLWouldBlock: - break; - case errSSLUnexpectedRecord: - DTLSRetransmit(ctx); - break; - case errSSLDecryptionFail: - case errSSLBadRecordMac: - /* We never send a Decryption Failed alert, instead we send the BadRecordMac alert */ - /* This is TLS 1.1 compliant - Do it for all protocols versions. */ - /* Except for DTLS where we do not send any alert. */ - if(ctx->isDTLS) { - /* This will ensure we try to read again before returning to the caller - We do NOT want to use errSSLWouldBlock here, as this should only indicate - the IO read callback status */ - err=errSSLUnexpectedRecord; - } else { - SSLFatalSessionAlert(SSL_AlertBadRecordMac, ctx); - } - break; - case errSSLInternal: - SSLFatalSessionAlert(SSL_AlertInternalError, ctx); - break; - case errSSLRecordOverflow: - SSLFatalSessionAlert(SSL_AlertRecordOverflow, ctx); - break; - case errSSLClosedAbort: - case errSSLConnectionRefused: - SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx); - break; - default: - sslErrorLog("unknown error code returned in SSLReadRecord: %d\n", (int)err); - SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx); - break; - } - - return err; -} - -OSStatus SSLServiceWriteQueue(SSLContext *ctx) -{ - return errorTranslate(ctx->recFuncs->serviceWriteQueue(ctx->recCtx)); -} diff --git a/libsecurity_ssl/lib/sslTransport.c b/libsecurity_ssl/lib/sslTransport.c deleted file mode 100644 index 311bedd8..00000000 --- a/libsecurity_ssl/lib/sslTransport.c +++ /dev/null @@ -1,603 +0,0 @@ -/* - * Copyright (c) 1999-2001,2005-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * 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@ - */ - -/* - * sslTransport.c - SSL transport layer - */ - -#include "ssl.h" -#include "sslMemory.h" -#include "sslContext.h" -#include "sslRecord.h" -#include "sslAlertMessage.h" -#include "sslSession.h" -#include "sslDebug.h" -#include "sslCipherSpecs.h" -#include "sslUtils.h" - -#include -#include - -#include - -#ifndef NDEBUG -static inline void sslIoTrace( - const char *op, - size_t req, - size_t moved, - OSStatus stat) -{ - sslLogRecordIo("===%s: req %4lu moved %4lu status %d", - op, req, moved, (int)stat); -} -#else -#define sslIoTrace(op, req, moved, stat) -#endif /* NDEBUG */ - -extern int kSplitDefaultValue; - -static OSStatus SSLProcessProtocolMessage(SSLRecord *rec, SSLContext *ctx); -static OSStatus SSLHandshakeProceed(SSLContext *ctx); -static OSStatus SSLInitConnection(SSLContext *ctx); - -static Boolean isFalseStartAllowed(SSLContext *ctx) -{ - SSL_CipherAlgorithm c=sslCipherSuiteGetSymmetricCipherAlgorithm(ctx->selectedCipher); - KeyExchangeMethod kem=sslCipherSuiteGetKeyExchangeMethod(ctx->selectedCipher); - - - /* Whitelisting allowed ciphers, kem and client auth type */ - return - ( - (c==SSL_CipherAlgorithmAES_128_CBC) || - (c==SSL_CipherAlgorithmAES_128_GCM) || - (c==SSL_CipherAlgorithmAES_256_CBC) || - (c==SSL_CipherAlgorithmAES_256_GCM) || - (c==SSL_CipherAlgorithmRC4_128) - ) && ( - (kem==SSL_ECDHE_ECDSA) || - (kem==SSL_ECDHE_RSA) || - (kem==SSL_DHE_RSA) || - (kem==SSL_DHE_DSS) - ) && ( - (ctx->negAuthType==SSLClientAuthNone) || - (ctx->negAuthType==SSLClientAuth_DSSSign) || - (ctx->negAuthType==SSLClientAuth_RSASign) || - (ctx->negAuthType==SSLClientAuth_ECDSASign) - ); -} - - -OSStatus -SSLWrite( - SSLContext *ctx, - const void * data, - size_t dataLength, - size_t *bytesWritten) /* RETURNED */ -{ - OSStatus err; - SSLRecord rec; - size_t dataLen, processed; - Boolean split; - - sslLogRecordIo("SSLWrite top"); - if((ctx == NULL) || (bytesWritten == NULL)) { - return errSecParam; - } - dataLen = dataLength; - processed = 0; /* Initialize in case we return with errSSLWouldBlock */ - *bytesWritten = 0; - - switch(ctx->state) { - case SSL_HdskStateGracefulClose: - err = errSSLClosedGraceful; - goto abort; - case SSL_HdskStateErrorClose: - err = errSSLClosedAbort; - goto abort; - case SSL_HdskStateServerReady: - case SSL_HdskStateClientReady: - break; - default: - if(ctx->state < SSL_HdskStateServerHello) { - /* not ready for I/O, and handshake not in progress */ - sslIoTrace("SSLWrite", dataLength, 0, errSecBadReq); - return errSecBadReq; - } - /* handshake in progress; will call SSLHandshakeProceed below */ - break; - } - - /* First, we have to wait until the session is ready to send data, - so the encryption keys and such have been established. */ - err = errSecSuccess; - while (!( - (ctx->state==SSL_HdskStateServerReady) || - (ctx->state==SSL_HdskStateClientReady) || - (ctx->writeCipher_ready && ctx->falseStartEnabled && isFalseStartAllowed(ctx)) - )) - { if ((err = SSLHandshakeProceed(ctx)) != 0) - goto exit; - } - - /* Attempt to empty the write queue before queueing more data */ - if ((err = SSLServiceWriteQueue(ctx)) != 0) - goto abort; - - /* Check if we should split the data into 1/n-1 to avoid known-IV issue */ - split = (ctx->oneByteRecordEnable && ctx->negProtocolVersion <= TLS_Version_1_0); - if (split) { - /* Only split if cipher algorithm uses CBC mode */ - SSL_CipherAlgorithm cipherAlg = sslCipherSuiteGetSymmetricCipherAlgorithm(ctx->selectedCipher); - split = (cipherAlg > SSL_CipherAlgorithmRC4_128 && - cipherAlg < SSL_CipherAlgorithmAES_128_GCM); - if (split) { - /* Determine whether we start splitting on second write */ - split = (kSplitDefaultValue == 2 && !ctx->wroteAppData) ? false : true; - } - } - processed = 0; - - /* - * Fragment, package and encrypt the data and queue the resulting data - * for sending - */ - while (dataLen > 0) - { rec.contentType = SSL_RecordTypeAppData; - rec.protocolVersion = ctx->negProtocolVersion; - rec.contents.data = ((uint8_t *)data) + processed; - - if (processed == 0 && split) - rec.contents.length = 1; - else if (dataLen < MAX_RECORD_LENGTH) - rec.contents.length = dataLen; - else - rec.contents.length = MAX_RECORD_LENGTH; - - if ((err = SSLWriteRecord(rec, ctx)) != 0) - goto exit; - processed += rec.contents.length; - dataLen -= rec.contents.length; - ctx->wroteAppData = 1; - } - - /* All the data has been advanced to the write queue */ - *bytesWritten = processed; - if ((err = SSLServiceWriteQueue(ctx)) == 0) { - err = errSecSuccess; - } -exit: - switch(err) { - case errSecSuccess: - case errSSLWouldBlock: - case errSSLUnexpectedRecord: - case errSSLServerAuthCompleted: /* == errSSLClientAuthCompleted */ - case errSSLClientCertRequested: - case errSSLClosedGraceful: - break; - default: - sslErrorLog("SSLWrite: going to state errorClose due to err %d\n", - (int)err); - SSLChangeHdskState(ctx, SSL_HdskStateErrorClose); - break; - } -abort: - sslIoTrace("SSLWrite", dataLength, *bytesWritten, err); - return err; -} - -OSStatus -SSLRead ( - SSLContext *ctx, - void * data, - size_t dataLength, - size_t *processed) /* RETURNED */ -{ - OSStatus err; - uint8_t *charPtr; - size_t bufSize, remaining, count; - SSLRecord rec; - - sslLogRecordIo("SSLRead top"); - if((ctx == NULL) || (data == NULL) || (processed == NULL)) { - return errSecParam; - } - bufSize = dataLength; - *processed = 0; /* Initialize in case we return with errSSLWouldBlock */ - -readRetry: - /* first handle cases in which we know we're finished */ - switch(ctx->state) { - case SSL_HdskStateGracefulClose: - err = errSSLClosedGraceful; - goto abort; - case SSL_HdskStateErrorClose: - err = errSSLClosedAbort; - goto abort; - case SSL_HdskStateNoNotifyClose: - err = errSSLClosedNoNotify; - goto abort; - default: - break; - } - - /* First, we have to wait until the session is ready to receive data, - so the encryption keys and such have been established. */ - err = errSecSuccess; - while (ctx->readCipher_ready == 0) { - if ((err = SSLHandshakeProceed(ctx)) != 0) { - goto exit; - } - } - - /* Attempt to service the write queue */ - if ((err = SSLServiceWriteQueue(ctx)) != 0) { - if (err != errSSLWouldBlock) { - goto exit; - } - err = errSecSuccess; /* Write blocking shouldn't stop attempts to read */ - } - - remaining = bufSize; - charPtr = (uint8_t *)data; - if (ctx->receivedDataBuffer.data) - { count = ctx->receivedDataBuffer.length - ctx->receivedDataPos; - if (count > bufSize) - count = bufSize; - memcpy(data, ctx->receivedDataBuffer.data + ctx->receivedDataPos, count); - remaining -= count; - charPtr += count; - *processed += count; - ctx->receivedDataPos += count; - } - - assert(ctx->receivedDataPos <= ctx->receivedDataBuffer.length); - assert(*processed + remaining == bufSize); - assert(charPtr == ((uint8_t *)data) + *processed); - - if (ctx->receivedDataBuffer.data != 0 && - ctx->receivedDataPos >= ctx->receivedDataBuffer.length) - { SSLFreeBuffer(&ctx->receivedDataBuffer); - ctx->receivedDataBuffer.data = 0; - ctx->receivedDataPos = 0; - } - - /* - * This while statement causes a hang when using nonblocking low-level I/O! - while (remaining > 0 && ctx->state != SSL_HdskStateGracefulClose) - ..what we really have to do is just return as soon as we read one - record. A performance hit in the nonblocking case, but that is - the only way this code can work in both modes... - */ - if (remaining > 0 && ctx->state != SSL_HdskStateGracefulClose) - { assert(ctx->receivedDataBuffer.data == 0); - if ((err = SSLReadRecord(&rec, ctx)) != 0) { - goto exit; - } - if (rec.contentType == SSL_RecordTypeAppData || - rec.contentType == SSL_RecordTypeV2_0) - { if (rec.contents.length <= remaining) - { memcpy(charPtr, rec.contents.data, rec.contents.length); - remaining -= rec.contents.length; - charPtr += rec.contents.length; - *processed += rec.contents.length; - { - if ((err = SSLFreeRecord(rec, ctx))) { - goto exit; - } - } - } - else - { memcpy(charPtr, rec.contents.data, remaining); - charPtr += remaining; - *processed += remaining; - ctx->receivedDataBuffer = rec.contents; - ctx->receivedDataPos = remaining; - remaining = 0; - } - } - else { - if ((err = SSLProcessProtocolMessage(&rec, ctx)) != 0) { - goto exit; - } - if ((err = SSLFreeRecord(rec, ctx))) { - goto exit; - } - } - } - - err = errSecSuccess; - -exit: - /* test for renegotiate: loop until something useful happens */ - if(((err == errSecSuccess) && (*processed == 0) && dataLength) || (err == errSSLUnexpectedRecord)) { - sslLogNegotiateDebug("SSLRead recursion"); - goto readRetry; - } - /* shut down on serious errors */ - switch(err) { - case errSecSuccess: - case errSSLWouldBlock: - case errSSLUnexpectedRecord: - case errSSLServerAuthCompleted: /* == errSSLClientAuthCompleted */ - case errSSLClientCertRequested: - case errSSLClosedGraceful: - case errSSLClosedNoNotify: - break; - default: - sslErrorLog("SSLRead: going to state errorClose due to err %d\n", - (int)err); - SSLChangeHdskState(ctx, SSL_HdskStateErrorClose); - break; - } -abort: - sslIoTrace("SSLRead ", dataLength, *processed, err); - return err; -} - -#if SSL_DEBUG -#include "sslCrypto.h" -#endif - -OSStatus -SSLHandshake(SSLContext *ctx) -{ - OSStatus err; - - if(ctx == NULL) { - return errSecParam; - } - if (ctx->state == SSL_HdskStateGracefulClose) - return errSSLClosedGraceful; - if (ctx->state == SSL_HdskStateErrorClose) - return errSSLClosedAbort; - - #if SSL_ECDSA_HACK - /* Because of Radar 6133465, we have to disable this to allow the sending - of client hello extensions for ECDSA... */ - ctx->versionSsl2Enable = false; - #endif - - if(ctx->validCipherSuites == NULL) { - /* build list of legal cipherSpecs */ - err = sslBuildCipherSuiteArray(ctx); - if(err) { - return err; - } - } - err = errSecSuccess; - - if(ctx->isDTLS) { - if (ctx->timeout_deadlinereadCipher_ready == 0 || ctx->writeCipher_ready == 0) - { - err = SSLHandshakeProceed(ctx); - if((err != 0) && (err != errSSLUnexpectedRecord)) - return err; - } - - /* one more flush at completion of successful handshake */ - if ((err = SSLServiceWriteQueue(ctx)) != 0) { - return err; - } - - return errSecSuccess; -} - - -static OSStatus -SSLHandshakeProceed(SSLContext *ctx) -{ OSStatus err; - SSLRecord rec; - - if (ctx->signalServerAuth) { - ctx->signalServerAuth = false; - return errSSLServerAuthCompleted; - } - if (ctx->signalCertRequest) { - ctx->signalCertRequest = false; - return errSSLClientCertRequested; - } - if (ctx->signalClientAuth) { - ctx->signalClientAuth = false; - return errSSLClientAuthCompleted; - } - - if (ctx->state == SSL_HdskStateUninit) - if ((err = SSLInitConnection(ctx)) != 0) - return err; - - /* This is our cue that we dropped out of the handshake - * to let the client pick an identity, move state back - * to server hello done and continue processing. - */ - if ((ctx->protocolSide == kSSLClientSide) && - (ctx->state == SSL_HdskStateClientCert)) - if ((err = SSLAdvanceHandshake(SSL_HdskServerHelloDone, ctx)) != 0) - return err; - - if ((err = SSLServiceWriteQueue(ctx)) != 0) - return err; - - assert(ctx->readCipher_ready == 0); - if ((err = SSLReadRecord(&rec, ctx)) != 0) - return err; - if ((err = SSLProcessProtocolMessage(&rec, ctx)) != 0) - { - SSLFreeRecord(rec, ctx); - return err; - } - if ((err = SSLFreeRecord(rec, ctx))) - return err; - - return errSecSuccess; -} - -static OSStatus -SSLInitConnection(SSLContext *ctx) -{ OSStatus err = errSecSuccess; - - if (ctx->protocolSide == kSSLClientSide) { - SSLChangeHdskState(ctx, SSL_HdskStateClientUninit); - } - else - { assert(ctx->protocolSide == kSSLServerSide); - SSLChangeHdskState(ctx, SSL_HdskStateServerUninit); - } - - if (ctx->peerID.data != 0) - { SSLGetSessionData(&ctx->resumableSession, ctx); - /* Ignore errors; just treat as uncached session */ - } - - /* - * If we have a cached resumable session, blow it off if it's a version - * which is not currently enabled. - */ - Boolean cachedV3OrTls1 = ctx->isDTLS; - - if (ctx->resumableSession.data != 0) { - SSLProtocolVersion savedVersion; - if ((err = SSLRetrieveSessionProtocolVersion(ctx->resumableSession, - &savedVersion, ctx)) != 0) - return err; - - if (ctx->isDTLS - ? (savedVersion <= ctx->minProtocolVersion && - savedVersion >= ctx->maxProtocolVersion) - : (savedVersion >= ctx->minProtocolVersion && - savedVersion <= ctx->maxProtocolVersion)) { - cachedV3OrTls1 = savedVersion != SSL_Version_2_0; - sslLogResumSessDebug("===attempting to resume session"); - } else { - sslLogResumSessDebug("===Resumable session protocol mismatch"); - SSLFreeBuffer(&ctx->resumableSession); - } - } - - /* - * If we're the client & handshake hasn't yet begun, start it by - * pretending we just received a hello request - */ - if (ctx->state == SSL_HdskStateClientUninit && ctx->writeCipher_ready == 0) - { - assert(ctx->negProtocolVersion == SSL_Version_Undetermined); -#if ENABLE_SSLV2 - if(!cachedV3OrTls1) { - /* SSL2 client hello with possible upgrade */ - err = SSL2AdvanceHandshake(SSL2_MsgKickstart, ctx); - } - else -#endif - { - err = SSLAdvanceHandshake(SSL_HdskHelloRequest, ctx); - } - } - - return err; -} - - -static OSStatus -SSLProcessProtocolMessage(SSLRecord *rec, SSLContext *ctx) -{ OSStatus err; - - switch (rec->contentType) - { case SSL_RecordTypeHandshake: - sslLogRxProtocolDebug("Handshake"); - if(ctx->isDTLS) - err = DTLSProcessHandshakeRecord(*rec, ctx); - else - err = SSLProcessHandshakeRecord(*rec, ctx); - break; - case SSL_RecordTypeAlert: - sslLogRxProtocolDebug("Alert"); - err = SSLProcessAlert(*rec, ctx); - break; - case SSL_RecordTypeChangeCipher: - sslLogRxProtocolDebug("ChangeCipher"); - err = SSLProcessChangeCipherSpec(*rec, ctx); - break; -#if ENABLE_SSLV2 - case SSL_RecordTypeV2_0: - sslLogRxProtocolDebug("RecordTypeV2_0"); - err = SSL2ProcessMessage(rec, ctx); - break; -#endif - default: - sslLogRxProtocolDebug("Bad msg"); - return errSSLProtocol; - } - - return err; -} - -OSStatus -SSLClose(SSLContext *ctx) -{ - OSStatus err = errSecSuccess; - - sslHdskStateDebug("SSLClose"); - if(ctx == NULL) { - return errSecParam; - } - if (ctx->negProtocolVersion >= SSL_Version_3_0) - err = SSLSendAlert(SSL_AlertLevelWarning, SSL_AlertCloseNotify, ctx); - - if (err == 0) - err = SSLServiceWriteQueue(ctx); - - SSLChangeHdskState(ctx, SSL_HdskStateGracefulClose); - if (err == errSecIO) - err = errSecSuccess; /* Ignore errors related to closed streams */ - return err; -} - -/* - * Determine how much data the client can be guaranteed to - * obtain via SSLRead() without blocking or causing any low-level - * read operations to occur. - * - * Implemented here because the relevant info in SSLContext (receivedDataBuffer - * and receivedDataPos) are only used in this file. - */ -OSStatus -SSLGetBufferedReadSize(SSLContextRef ctx, - size_t *bufSize) /* RETURNED */ -{ - if(ctx == NULL) { - return errSecParam; - } - if(ctx->receivedDataBuffer.data == NULL) { - *bufSize = 0; - } - else { - assert(ctx->receivedDataBuffer.length >= ctx->receivedDataPos); - *bufSize = ctx->receivedDataBuffer.length - ctx->receivedDataPos; - } - return errSecSuccess; -} diff --git a/libsecurity_ssl/lib/tls1Callouts.c b/libsecurity_ssl/lib/tls1Callouts.c deleted file mode 100644 index 9c873f76..00000000 --- a/libsecurity_ssl/lib/tls1Callouts.c +++ /dev/null @@ -1,584 +0,0 @@ -/* - * Copyright (c) 2002,2005-2007,2010-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * 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@ - */ - -/* - * tls1Callouts.c - TLSv1-specific routines for SslTlsCallouts. - */ - -#include "SecureTransport.h" - -#include "tls_ssl.h" -#include "sslMemory.h" -#include "sslUtils.h" -#include "sslDigests.h" -#include "sslAlertMessage.h" -#include "sslCrypto.h" -#include "sslDebug.h" -#include "tls_hmac.h" -#include -#include - -#define TLS_ENC_DEBUG 0 -#if TLS_ENC_DEBUG -#define tlsDebug(format, args...) printf(format , ## args) -static void tlsDump(const char *name, void *b, unsigned len) -{ - unsigned char *cp = (unsigned char *)b; - unsigned i, dex; - - printf("%s\n", name); - for(dex=0; dex= outLen - size_t outLen) // desired output size -{ - unsigned char aSubI[TLS_HMAC_MAX_SIZE]; /* A(i) */ - unsigned char digest[TLS_HMAC_MAX_SIZE]; - HMACContextRef hmacCtx; - OSStatus serr; - size_t digestLen = hmac->macSize; - - serr = hmac->alloc(hmac, secret, secretLen, &hmacCtx); - if(serr) { - return serr; - } - - /* A(0) = seed */ - /* A(1) := HMAC_hash(secret, seed) */ - serr = hmac->hmac(hmacCtx, seed, seedLen, aSubI, &digestLen); - if(serr) { - goto fail; - } - assert(digestLen = hmac->macSize); - - /* starting at loopNum 1... */ - for (;;) { - /* - * This loop's chunk = HMAC_hash(secret, A(loopNum) + seed)) - */ - serr = hmac->init(hmacCtx); - if(serr) { - break; - } - serr = hmac->update(hmacCtx, aSubI, digestLen); - if(serr) { - break; - } - serr = hmac->update(hmacCtx, seed, seedLen); - if(serr) { - break; - } - serr = hmac->final(hmacCtx, digest, &digestLen); - if(serr) { - break; - } - assert(digestLen = hmac->macSize); - - if(outLen <= digestLen) { - /* last time, possible partial digest */ - memmove(out, digest, outLen); - break; - } - - memmove(out, digest, digestLen); - out += digestLen; - outLen -= digestLen; - - /* - * A(i) = HMAC_hash(secret, A(i-1)) - * Note there is a possible optimization involving obtaining this - * hmac by cloning the state of hmacCtx above after updating with - * aSubI, and getting the final version of that here. However CDSA - * does not support cloning of a MAC context (only for digest contexts). - */ - serr = hmac->hmac(hmacCtx, aSubI, digestLen, - aSubI, &digestLen); - if(serr) { - break; - } - assert(digestLen = hmac->macSize); - } -fail: - hmac->free(hmacCtx); - memset(aSubI, 0, TLS_HMAC_MAX_SIZE); - memset(digest, 0, TLS_HMAC_MAX_SIZE); - return serr; -} - -/* - * The TLS pseudorandom function, defined in RFC2246, section 5. - * This takes as its input a secret block, a label, and a seed, and produces - * a caller-specified length of pseudorandom data. - * - * Optimization TBD: make label optional, avoid malloc and two copies if it's - * not there, so callers can take advantage of fixed-size seeds. - */ -OSStatus SSLInternal_PRF( - SSLContext *ctx, - const void *vsecret, - size_t secretLen, - const void *label, // optional, NULL implies that seed contains - // the label - size_t labelLen, - const void *seed, - size_t seedLen, - void *vout, // mallocd by caller, length >= outLen - size_t outLen) -{ - OSStatus serr = errSSLInternal; - const unsigned char *S1, *S2; // the two seeds - size_t sLen; // effective length of each seed - unsigned char *labelSeed = NULL; // label + seed, passed to tlsPHash - size_t labelSeedLen; - unsigned char *tmpOut = NULL; // output of P_SHA1 - size_t i; - const unsigned char *secret = (const unsigned char *)vsecret; - - if(label != NULL) { - /* concatenate label and seed */ - labelSeedLen = labelLen + seedLen; - labelSeed = (unsigned char *)sslMalloc(labelSeedLen); - if(labelSeed == NULL) { - return errSecAllocate; - } - memmove(labelSeed, label, labelLen); - memmove(labelSeed + labelLen, seed, seedLen); - } - else { - /* fast track - just use seed as is */ - labelSeed = (unsigned char *)seed; - labelSeedLen = seedLen; - } - - unsigned char *out = (unsigned char *)vout; - if(sslVersionIsLikeTls12(ctx)) { - const HMACReference *mac = &TlsHmacSHA256; - if (ctx->selectedCipherSpecParams.macAlg == HA_SHA384) { - mac = &TlsHmacSHA384; - } - serr = tlsPHash(ctx, mac, secret, secretLen, labelSeed, labelSeedLen, - out, outLen); - if(serr) { - goto fail; - } - } else { - /* two seeds for tlsPHash */ - sLen = secretLen / 2; // for partitioning - S1 = secret; - S2 = &secret[sLen]; - sLen += (secretLen & 1); // secret length odd, increment effective size - - /* temporary output for SHA1, to be XORd with MD5 */ - tmpOut = (unsigned char *)sslMalloc(outLen); - if(tmpOut == NULL) { - serr = errSecAllocate; - goto fail; - } - - serr = tlsPHash(ctx, &TlsHmacMD5, S1, sLen, labelSeed, labelSeedLen, - out, outLen); - if(serr) { - goto fail; - } - serr = tlsPHash(ctx, &TlsHmacSHA1, S2, sLen, labelSeed, labelSeedLen, - tmpOut, outLen); - if(serr) { - goto fail; - } - - /* XOR together to get final result */ - for(i=0; iserverRandom, - SSL_CLIENT_SRVR_RAND_SIZE); - memmove(seedBuf + PLS_KEY_EXPAND_LEN + SSL_CLIENT_SRVR_RAND_SIZE, - ctx->clientRandom, SSL_CLIENT_SRVR_RAND_SIZE); - serr = SSLInternal_PRF(ctx, - ctx->masterSecret, - SSL_MASTER_SECRET_SIZE, - NULL, // no label - 0, - seedBuf, - GKM_SEED_LEN, - key.data, // destination - key.length); - tlsDump("key expansion", key.data, key.length); - return serr; -} - -/* - * On entry: clientRandom, serverRandom, preMasterSecret valid - * On return: masterSecret valid - * - * master_secret = PRF(pre_master_secret, "master secret", - * ClientHello.random + ServerHello.random) - * [0..47]; - */ - -static OSStatus tls1GenerateMasterSecret ( - SSLContext *ctx) -{ - unsigned char randBuf[2 * SSL_CLIENT_SRVR_RAND_SIZE]; - OSStatus serr; - - memmove(randBuf, ctx->clientRandom, SSL_CLIENT_SRVR_RAND_SIZE); - memmove(randBuf + SSL_CLIENT_SRVR_RAND_SIZE, - ctx->serverRandom, SSL_CLIENT_SRVR_RAND_SIZE); - serr = SSLInternal_PRF(ctx, - ctx->preMasterSecret.data, - ctx->preMasterSecret.length, - (const unsigned char *)PLS_MASTER_SECRET, - PLS_MASTER_SECRET_LEN, - randBuf, - 2 * SSL_CLIENT_SRVR_RAND_SIZE, - ctx->masterSecret, // destination - SSL_MASTER_SECRET_SIZE); - tlsDump("master secret", ctx->masterSecret, SSL_MASTER_SECRET_SIZE); - return serr; -} - -/* - * Given digests contexts representing the running total of all handshake messages, - * calculate mac for "finished" message. - * - * verify_data = 12 bytes = - * PRF(master_secret, finished_label, MD5(handshake_messages) + - * SHA-1(handshake_messages)) [0..11]; - */ -static OSStatus tls1ComputeFinishedMac ( - SSLContext *ctx, - SSLBuffer finished, // output - mallocd by caller - Boolean isServer) -{ - unsigned char digests[SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN]; - SSLBuffer digBuf; - char *finLabel; - unsigned finLabelLen; - OSStatus serr; - SSLBuffer shaMsgState, md5MsgState; - - shaMsgState.data = 0; - md5MsgState.data = 0; - if ((serr = CloneHashState(&SSLHashSHA1, &ctx->shaState, &shaMsgState)) != 0) - goto fail; - if ((serr = CloneHashState(&SSLHashMD5, &ctx->md5State, &md5MsgState)) != 0) - goto fail; - - if(isServer) { - finLabel = PLS_SERVER_FINISH; - finLabelLen = PLS_SERVER_FINISH_LEN; - } - else { - finLabel = PLS_CLIENT_FINISH; - finLabelLen = PLS_CLIENT_FINISH_LEN; - } - - /* concatenate two digest results */ - digBuf.data = digests; - digBuf.length = SSL_MD5_DIGEST_LEN; - serr = SSLHashMD5.final(&md5MsgState, &digBuf); - if(serr) { - return serr; - } - digBuf.data += SSL_MD5_DIGEST_LEN; - digBuf.length = SSL_SHA1_DIGEST_LEN; - serr = SSLHashSHA1.final(&shaMsgState, &digBuf); - if(serr) { - return serr; - } - serr = SSLInternal_PRF(ctx, - ctx->masterSecret, - SSL_MASTER_SECRET_SIZE, - (const unsigned char *)finLabel, - finLabelLen, - digests, - SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN, - finished.data, // destination - finished.length); - -fail: - SSLFreeBuffer(&shaMsgState); - SSLFreeBuffer(&md5MsgState); - - return serr; -} - -/* - * Given digests contexts representing the running total of all handshake messages, - * calculate mac for "finished" message. - * - * verify_data = 12 bytes = - * PRF(master_secret, finished_label, SHA256(handshake_messages)) [0..11]; - */ -static OSStatus tls12ComputeFinishedMac ( - SSLContext *ctx, - SSLBuffer finished, // output - mallocd by caller - Boolean isServer) -{ - unsigned char digest[SSL_MAX_DIGEST_LEN]; - SSLBuffer digBuf; - char *finLabel; - unsigned finLabelLen; - OSStatus serr; - SSLBuffer hashState; - const HashReference *hashRef; - const SSLBuffer *ctxHashState; - - /* The PRF used in the finished message is based on the cipherspec */ - if (ctx->selectedCipherSpecParams.macAlg == HA_SHA384) { - hashRef = &SSLHashSHA384; - ctxHashState = &ctx->sha512State; - } else { - hashRef = &SSLHashSHA256; - ctxHashState = &ctx->sha256State; - } - - hashState.data = 0; - if ((serr = CloneHashState(hashRef, ctxHashState, &hashState)) != 0) - goto fail; - if(isServer) { - finLabel = PLS_SERVER_FINISH; - finLabelLen = PLS_SERVER_FINISH_LEN; - } - else { - finLabel = PLS_CLIENT_FINISH; - finLabelLen = PLS_CLIENT_FINISH_LEN; - } - - /* concatenate two digest results */ - digBuf.data = digest; - digBuf.length = hashRef->digestSize; - if ((serr = hashRef->final(&hashState, &digBuf)) != 0) - goto fail; - serr = SSLInternal_PRF(ctx, - ctx->masterSecret, - SSL_MASTER_SECRET_SIZE, - (const unsigned char *)finLabel, - finLabelLen, - digBuf.data, - digBuf.length, - finished.data, // destination - finished.length); -fail: - SSLFreeBuffer(&hashState); - return serr; -} - -/* - * This one is trivial. - * - * mac := MD5(handshake_messages) + SHA(handshake_messages); - * - * I don't know why this one doesn't use an HMAC or the master secret (as SSLv3 - * does). - */ -static OSStatus tls1ComputeCertVfyMac ( - SSLContext *ctx, - SSLBuffer *finished, // output - mallocd by caller - SSL_HashAlgorithm hash) //unused in this one -{ - SSLBuffer digBuf, shaMsgState, md5MsgState; - OSStatus serr; - - shaMsgState.data = 0; - md5MsgState.data = 0; - - if ((serr = CloneHashState(&SSLHashSHA1, &ctx->shaState, &shaMsgState)) != 0) - goto fail; - if ((serr = CloneHashState(&SSLHashMD5, &ctx->md5State, &md5MsgState)) != 0) - goto fail; - - if ((ctx->protocolSide == kSSLServerSide && sslPubKeyGetAlgorithmID(ctx->peerPubKey) == kSecECDSAAlgorithmID) || - (ctx->protocolSide == kSSLClientSide && ctx->negAuthType == SSLClientAuth_ECDSASign)) { - /* Only take SHA1 regardless of TLSv1.0 or TLSv1.1 If we are the server - and our peer signed with an ECDSA key, or if we are the client and - are about to sign with ECDSA. */ - assert(finished->length >= SSL_SHA1_DIGEST_LEN); - digBuf.data = finished->data; - finished->length = SSL_SHA1_DIGEST_LEN; - } else { - /* Put MD5 follow by SHA1 hash in buffer. */ - assert(finished->length >= (SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN)); - digBuf.data = finished->data; - digBuf.length = SSL_MD5_DIGEST_LEN; - if ((serr = SSLHashMD5.final(&md5MsgState, &digBuf)) != 0) - goto fail; - digBuf.data = finished->data + SSL_MD5_DIGEST_LEN; - finished->length = SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN; - } - - digBuf.length = SSL_SHA1_DIGEST_LEN; - serr = SSLHashSHA1.final(&shaMsgState, &digBuf); - -fail: - SSLFreeBuffer(&shaMsgState); - SSLFreeBuffer(&md5MsgState); - - return serr; -} - -static OSStatus tls12ComputeCertVfyMac ( - SSLContext *ctx, - SSLBuffer *finished, // output - mallocd by caller - SSL_HashAlgorithm hash) -{ - const SSLBuffer *ctxHashState; - const HashReference *hashRef; - SSLBuffer hashState; - OSStatus serr; - - hashState.data = 0; - - switch (hash) { - case SSL_HashAlgorithmSHA1: - hashRef = &SSLHashSHA1; - ctxHashState = &ctx->shaState; - break; - case SSL_HashAlgorithmSHA256: - hashRef = &SSLHashSHA256; - ctxHashState = &ctx->sha256State; - break; - case SSL_HashAlgorithmSHA384: - hashRef = &SSLHashSHA384; - ctxHashState = &ctx->sha512State; - break; - default: - return errSSLInternal; - break; - } - - if ((serr = CloneHashState(hashRef, ctxHashState, &hashState)) != 0) - goto fail; - - assert(finished->length >= (hashRef->digestSize)); - finished->length = hashRef->digestSize; - serr = hashRef->final(&hashState, finished); - -fail: - SSLFreeBuffer(&hashState); - - return serr; -} - - -const SslTlsCallouts Tls1Callouts = { - tls1GenerateKeyMaterial, - tls1GenerateMasterSecret, - tls1ComputeFinishedMac, - tls1ComputeCertVfyMac -}; - -const SslTlsCallouts Tls12Callouts = { - tls1GenerateKeyMaterial, - tls1GenerateMasterSecret, - tls12ComputeFinishedMac, - tls12ComputeCertVfyMac -}; diff --git a/libsecurity_ssl/lib/tls1RecordCallouts.c b/libsecurity_ssl/lib/tls1RecordCallouts.c deleted file mode 100644 index a3e2da9d..00000000 --- a/libsecurity_ssl/lib/tls1RecordCallouts.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2002,2005-2007,2010-2011 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@ - */ - -/* - * tls1RecordCallouts.c - TLSv1-specific routines for SslTlsCallouts. - */ - -/* THIS FILE CONTAINS KERNEL CODE */ - -#include "tls_record.h" -#include "sslMemory.h" -#include "sslDebug.h" -#include "sslUtils.h" - -#include -#include - -/* not needed; encrypt/encode is the same for both protocols as long as - * we don't use the "variable length padding" feature. */ -#if 0 -static int tls1WriteRecord( - SSLRecord rec, - SSLContext *ctx) -{ - check(0); - return errSecUnimplemented; -} -#endif - -static int tls1DecryptRecord( - uint8_t type, - SSLBuffer *payload, - struct SSLRecordInternalContext *ctx) -{ - int err; - SSLBuffer content; - - if ((ctx->readCipher.symCipher->params->blockSize > 0) && - ((payload->length % ctx->readCipher.symCipher->params->blockSize) != 0)) { - return errSSLRecordRecordOverflow; - } - - /* Decrypt in place */ - if ((err = ctx->readCipher.symCipher->c.cipher.decrypt(payload->data, - payload->data, payload->length, - ctx->readCipher.cipherCtx)) != 0) - { - return errSSLRecordDecryptionFail; - } - - /* Locate content within decrypted payload */ - - /* TLS 1.1 and DTLS 1.0 block ciphers */ - if((ctx->negProtocolVersion>=TLS_Version_1_1) && (ctx->readCipher.symCipher->params->blockSize>0)) - { - content.data = payload->data + ctx->readCipher.symCipher->params->blockSize; - content.length = payload->length - (ctx->readCipher.macRef->hash->digestSize + ctx->readCipher.symCipher->params->blockSize); - } else { - content.data = payload->data; - content.length = payload->length - ctx->readCipher.macRef->hash->digestSize; - } - - /* Test for underflow - if the record size is smaller than required */ - if(content.length > payload->length) { - return errSSLRecordClosedAbort; - } - - err = 0; - - if (ctx->readCipher.symCipher->params->blockSize > 0) { - /* for TLSv1, padding can be anywhere from 0 to 255 bytes */ - uint8_t padSize = payload->data[payload->length - 1]; - - /* Padding check sequence: - 1. Check that the padding size (last byte in padding) is within bound - 2. Adjust content.length accordingly - 3. Check every padding byte (except last, already checked) - Do not return, just set the error value on failure, - to avoid creating a padding oracle with timing. - */ - if(padSize+1<=content.length) { - uint8_t *padChars; - content.length -= (1 + padSize); - padChars = payload->data + payload->length - (padSize+1); - while(padChars < (payload->data + payload->length - 1)) { - if(*padChars++ != padSize) { - err = errSSLRecordBadRecordMac; - } - } - } else { - err = errSSLRecordBadRecordMac; - } - } - - /* Verify MAC on payload */ - if (ctx->readCipher.macRef->hash->digestSize > 0) - /* Optimize away MAC for null case */ - if (SSLVerifyMac(type, &content, - content.data + content.length, ctx) != 0) - { - err = errSSLRecordBadRecordMac; - } - - *payload = content; /* Modify payload buffer to indicate content length */ - - return err; -} - -/* initialize a per-CipherContext HashHmacContext for use in MACing each record */ -static int tls1InitMac ( - CipherContext *cipherCtx) // macRef, macSecret valid on entry - // macCtx valid on return -{ - const HMACReference *hmac; - int serr; - - check(cipherCtx); - check(cipherCtx->macRef != NULL); - hmac = cipherCtx->macRef->hmac; - check(hmac != NULL); - - if(cipherCtx->macCtx.hmacCtx != NULL) { - hmac->free(cipherCtx->macCtx.hmacCtx); - cipherCtx->macCtx.hmacCtx = NULL; - } - serr = hmac->alloc(hmac, cipherCtx->macSecret, - cipherCtx->macRef->hmac->macSize, &cipherCtx->macCtx.hmacCtx); - - /* mac secret now stored in macCtx.hmacCtx, delete it from cipherCtx */ - memset(cipherCtx->macSecret, 0, sizeof(cipherCtx->macSecret)); - return serr; -} - -static int tls1FreeMac ( - CipherContext *cipherCtx) -{ - /* this can be called on a completely zeroed out CipherContext... */ - if(cipherCtx->macRef == NULL) { - return 0; - } - check(cipherCtx->macRef->hmac != NULL); - - if(cipherCtx->macCtx.hmacCtx != NULL) { - cipherCtx->macRef->hmac->free(cipherCtx->macCtx.hmacCtx); - cipherCtx->macCtx.hmacCtx = NULL; - } - return 0; -} - -/* - * mac = HMAC_hash(MAC_write_secret, seq_num + TLSCompressed.type + - * TLSCompressed.version + TLSCompressed.length + - * TLSCompressed.fragment)); - */ - -/* sequence, type, version, length */ -#define HDR_LENGTH (8 + 1 + 2 + 2) -static int tls1ComputeMac ( - uint8_t type, - SSLBuffer data, - SSLBuffer mac, // caller mallocs data - CipherContext *cipherCtx, // assumes macCtx, macRef - sslUint64 seqNo, - struct SSLRecordInternalContext *ctx) -{ - uint8_t hdr[HDR_LENGTH]; - uint8_t *p; - HMACContextRef hmacCtx; - int serr; - const HMACReference *hmac; - size_t macLength; - - check(cipherCtx != NULL); - check(cipherCtx->macRef != NULL); - hmac = cipherCtx->macRef->hmac; - check(hmac != NULL); - hmacCtx = cipherCtx->macCtx.hmacCtx; // may be NULL, for null cipher - - serr = hmac->init(hmacCtx); - if(serr) { - goto fail; - } - p = SSLEncodeUInt64(hdr, seqNo); - *p++ = type; - *p++ = ctx->negProtocolVersion >> 8; - *p++ = ctx->negProtocolVersion & 0xff; - *p++ = data.length >> 8; - *p = data.length & 0xff; - serr = hmac->update(hmacCtx, hdr, HDR_LENGTH); - if(serr) { - goto fail; - } - serr = hmac->update(hmacCtx, data.data, data.length); - if(serr) { - goto fail; - } - macLength = mac.length; - serr = hmac->final(hmacCtx, mac.data, &macLength); - if(serr) { - goto fail; - } - mac.length = macLength; -fail: - return serr; -} - -const SslRecordCallouts Tls1RecordCallouts = { - tls1DecryptRecord, - ssl3WriteRecord, - tls1InitMac, - tls1FreeMac, - tls1ComputeMac, -}; - diff --git a/libsecurity_ssl/lib/tls_record.h b/libsecurity_ssl/lib/tls_record.h deleted file mode 100644 index eacd8453..00000000 --- a/libsecurity_ssl/lib/tls_record.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2002,2005-2007,2010-2011 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@ - */ - -/* - * tls_record.h - Declarations of record layer callout struct to provide indirect calls to - * SSLv3 and TLS routines. - */ - -#ifndef _TLS_RECORD_H_ -#define _TLS_RECORD_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -// #include "sslRecord.h" - -#include "sslTypes.h" -#include "cryptType.h" -#include "sslMemory.h" -#include "SSLRecordInternal.h" - -struct SSLRecordInternalContext; - -/*** - *** Each of {TLS, SSLv3} implements each of these functions. - ***/ - -/* unpack, decrypt, validate one record */ -typedef int (*decryptRecordFcn) ( - uint8_t type, - SSLBuffer *payload, - struct SSLRecordInternalContext *ctx); - -/* pack, encrypt, mac, queue one outgoing record */ -typedef int (*writeRecordFcn) ( - SSLRecord rec, - struct SSLRecordInternalContext *ctx); - -/* initialize a per-CipherContext HashHmacContext for use in MACing each record */ -typedef int (*initMacFcn) ( - CipherContext *cipherCtx // macRef, macSecret valid on entry - // macCtx valid on return -); - -/* free per-CipherContext HashHmacContext */ -typedef int (*freeMacFcn) ( - CipherContext *cipherCtx); - -/* compute MAC on one record */ -typedef int (*computeMacFcn) ( - uint8_t type, - SSLBuffer data, - SSLBuffer mac, // caller mallocs data - CipherContext *cipherCtx, // assumes macCtx, macRef - sslUint64 seqNo, - struct SSLRecordInternalContext *ctx); - - -typedef struct _SslRecordCallouts { - decryptRecordFcn decryptRecord; - writeRecordFcn writeRecord; - initMacFcn initMac; - freeMacFcn freeMac; - computeMacFcn computeMac; -} SslRecordCallouts; - - -/* From ssl3RecordCallouts.c and tls1RecordCallouts.c */ -extern const SslRecordCallouts Ssl3RecordCallouts; -extern const SslRecordCallouts Tls1RecordCallouts; - -/* one callout routine used in common (for now) */ -int ssl3WriteRecord( - SSLRecord rec, - struct SSLRecordInternalContext *ctx); - - -typedef struct WaitingRecord -{ struct WaitingRecord *next; - size_t sent; - /* - * These two fields replace a dynamically allocated SSLBuffer; - * the payload to write is contained in the variable-length - * array data[]. - */ - size_t length; - uint8_t data[1]; -} WaitingRecord; - -typedef struct { - const HashHmacReference *macAlgorithm; - const SSLSymmetricCipher *cipher; -} SSLRecordCipherSpec; - - - -struct SSLRecordInternalContext -{ - /* I/O */ - SSLIOReadFunc read; - SSLIOWriteFunc write; - SSLIOConnectionRef ioRef; - - /* buffering */ - SSLBuffer partialReadBuffer; - size_t amountRead; - WaitingRecord *recordWriteQueue; - - /* ciphers */ - uint16_t selectedCipher; /* currently selected */ - SSLRecordCipherSpec selectedCipherSpec; /* ditto */ - CipherContext readCipher; - CipherContext writeCipher; - CipherContext readPending; - CipherContext writePending; - CipherContext prevCipher; /* previous write cipher context, used for retransmit */ - - /* protocol */ - bool isDTLS; - SSLProtocolVersion negProtocolVersion; /* negotiated */ - const SslRecordCallouts *sslTslCalls; - -}; - -/* Function called from the ssl3/tls1 callouts */ - -int SSLVerifyMac( - uint8_t type, - SSLBuffer *data, - uint8_t *compareMAC, - struct SSLRecordInternalContext *ctx); - -#ifdef __cplusplus -} -#endif - -#endif /* _TLS_SSL_H_ */ diff --git a/libsecurity_ssl/libsecurity_ssl.xcodeproj/project.pbxproj b/libsecurity_ssl/libsecurity_ssl.xcodeproj/project.pbxproj deleted file mode 100644 index 86bde600..00000000 --- a/libsecurity_ssl/libsecurity_ssl.xcodeproj/project.pbxproj +++ /dev/null @@ -1,1002 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXAggregateTarget section */ - 0C6C633A15D1BD4800BC68CD /* dtlsEcho */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 0C6C633B15D1BD4800BC68CD /* Build configuration list for PBXAggregateTarget "dtlsEcho" */; - buildPhases = ( - ); - dependencies = ( - 0C6C633F15D1BD4D00BC68CD /* PBXTargetDependency */, - 0C6C634115D1BD4E00BC68CD /* PBXTargetDependency */, - ); - name = dtlsEcho; - productName = dtlsEcho; - }; -/* End PBXAggregateTarget section */ - -/* Begin PBXBuildFile section */ - 0C0E0467162C9DF0009F7C71 /* ssl-46-SSLGetSupportedCiphers.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C0E0466162C9DF0009F7C71 /* ssl-46-SSLGetSupportedCiphers.c */; }; - 0C0E046A162CA288009F7C71 /* ssl_regressions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C0E0469162CA288009F7C71 /* ssl_regressions.h */; }; - 0C1C92F315C8AC81007D377B /* cipherSpecs.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CAFF4020534D89900303760 /* cipherSpecs.h */; }; - 0C1C92F415C8AC81007D377B /* sslTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA413C15C75863002AEC4C /* sslTypes.h */; settings = {ATTRIBUTES = (); }; }; - 0C1C92F515C8AC81007D377B /* cryptType.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CAFF4040534D89900303760 /* cryptType.h */; }; - 0C1C930015C8AC81007D377B /* sslMemory.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CAFF4270534D89900303760 /* sslMemory.h */; }; - 0C1C930515C8AC81007D377B /* symCipher.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CAFF4320534D89900303760 /* symCipher.h */; }; - 0C1C930615C8AC81007D377B /* tls_hmac.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CAFF4350534D89900303760 /* tls_hmac.h */; }; - 0C1C930815C8AC81007D377B /* CipherSuite.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CAFF4030534D89900303760 /* CipherSuite.h */; settings = {ATTRIBUTES = (); }; }; - 0C1C931015C8AC81007D377B /* tls_digest.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA413F15C75863002AEC4C /* tls_digest.h */; }; - 0C1C931115C8AC81007D377B /* tls_hashhmac.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA414115C75863002AEC4C /* tls_hashhmac.h */; }; - 0C1C931215C8AC81007D377B /* tls_record.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA414215C75863002AEC4C /* tls_record.h */; }; - 0C1C931615C8AC81007D377B /* cipherSpecs.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4010534D89900303760 /* cipherSpecs.c */; }; - 0C1C932415C8AC81007D377B /* sslMemory.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4260534D89900303760 /* sslMemory.c */; }; - 0C1C932515C8AC81007D377B /* sslNullCipher.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4280534D89900303760 /* sslNullCipher.c */; }; - 0C1C932915C8AC81007D377B /* sslUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF42F0534D89900303760 /* sslUtils.c */; }; - 0C1C932A15C8AC81007D377B /* symCipher.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4310534D89900303760 /* symCipher.c */; }; - 0C1C932C15C8AC81007D377B /* tls_hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4340534D89900303760 /* tls_hmac.c */; }; - 0C1C932E15C8AC81007D377B /* ssl3RecordCallouts.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA413515C75863002AEC4C /* ssl3RecordCallouts.c */; }; - 0C1C933015C8AC81007D377B /* sslRand.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA413815C75863002AEC4C /* sslRand.c */; }; - 0C1C933115C8AC81007D377B /* SSLRecordInternal.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA413A15C75863002AEC4C /* SSLRecordInternal.c */; }; - 0C1C933215C8AC81007D377B /* symCipherParams.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA413D15C75863002AEC4C /* symCipherParams.c */; }; - 0C1C933315C8AC81007D377B /* tls_digest.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA413E15C75863002AEC4C /* tls_digest.c */; }; - 0C1C933415C8AC81007D377B /* tls_hashhmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA414015C75863002AEC4C /* tls_hashhmac.c */; }; - 0C1C933515C8AC81007D377B /* tls1RecordCallouts.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA414315C75863002AEC4C /* tls1RecordCallouts.c */; }; - 0C1C933B15C8AFB8007D377B /* SSLRecordInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA413B15C75863002AEC4C /* SSLRecordInternal.h */; }; - 0C6C633515D1BB4F00BC68CD /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C6C633315D1BB3300BC68CD /* Security.framework */; }; - 0C6C633615D1BB6000BC68CD /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C6C633315D1BB3300BC68CD /* Security.framework */; }; - 0C6C633815D1BB7100BC68CD /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C6C633715D1BB7100BC68CD /* CoreFoundation.framework */; }; - 0C6C633915D1BBAA00BC68CD /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C6C633715D1BB7100BC68CD /* CoreFoundation.framework */; }; - 0C6C634315D1BDCF00BC68CD /* ssl-utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C6C634215D1BDCF00BC68CD /* ssl-utils.c */; }; - 0C6C634515D1BE3900BC68CD /* ssl-utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C6C634415D1BE3900BC68CD /* ssl-utils.h */; }; - 0C6C641F15D5840700BC68CD /* cert-1.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C6C641C15D5840700BC68CD /* cert-1.h */; }; - 0C6C642015D5840700BC68CD /* identity-1.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C6C641D15D5840700BC68CD /* identity-1.h */; }; - 0C6C642115D5840700BC68CD /* privkey-1.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C6C641E15D5840700BC68CD /* privkey-1.h */; }; - 0C6C642315D5938E00BC68CD /* ssl-utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C6C634215D1BDCF00BC68CD /* ssl-utils.c */; }; - 0C6C642415D5939A00BC68CD /* ssl-utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C6C634215D1BDCF00BC68CD /* ssl-utils.c */; }; - 0CADC66716769B7C000A70D4 /* ssl_regressions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CADC66616769B7C000A70D4 /* ssl_regressions.h */; }; - 0CC954F1161A62AE005D3D4A /* ssl-44-crashes.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CC954F0161A62AE005D3D4A /* ssl-44-crashes.c */; }; - 0CCA414515C75863002AEC4C /* ssl3RecordCallouts.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA413515C75863002AEC4C /* ssl3RecordCallouts.c */; }; - 0CCA414615C75863002AEC4C /* sslCipherSpecs.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA413615C75863002AEC4C /* sslCipherSpecs.c */; }; - 0CCA414815C75863002AEC4C /* sslRand.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA413815C75863002AEC4C /* sslRand.c */; }; - 0CCA414A15C75863002AEC4C /* SSLRecordInternal.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA413A15C75863002AEC4C /* SSLRecordInternal.c */; }; - 0CCA414D15C75863002AEC4C /* symCipherParams.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA413D15C75863002AEC4C /* symCipherParams.c */; }; - 0CCA414E15C75863002AEC4C /* tls_digest.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA413E15C75863002AEC4C /* tls_digest.c */; }; - 0CCA415015C75863002AEC4C /* tls_hashhmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA414015C75863002AEC4C /* tls_hashhmac.c */; }; - 0CCA415315C75863002AEC4C /* tls1RecordCallouts.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA414315C75863002AEC4C /* tls1RecordCallouts.c */; }; - 0CCA416F15C89EA3002AEC4C /* ClientCert_ecc_ecc.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA415E15C89EA3002AEC4C /* ClientCert_ecc_ecc.h */; }; - 0CCA417015C89EA3002AEC4C /* ClientCert_ecc_rsa.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA415F15C89EA3002AEC4C /* ClientCert_ecc_rsa.h */; }; - 0CCA417115C89EA3002AEC4C /* ClientCert_rsa_ecc.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA416015C89EA3002AEC4C /* ClientCert_rsa_ecc.h */; }; - 0CCA417215C89EA3002AEC4C /* ClientCert_rsa_rsa.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA416115C89EA3002AEC4C /* ClientCert_rsa_rsa.h */; }; - 0CCA417315C89EA3002AEC4C /* ClientKey_ecc.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA416215C89EA3002AEC4C /* ClientKey_ecc.h */; }; - 0CCA417415C89EA3002AEC4C /* ClientKey_rsa.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA416315C89EA3002AEC4C /* ClientKey_rsa.h */; }; - 0CCA417515C89EA3002AEC4C /* SECG_ecc-secp256r1-client_cert.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA416415C89EA3002AEC4C /* SECG_ecc-secp256r1-client_cert.h */; }; - 0CCA417615C89EA3002AEC4C /* SECG_ecc-secp256r1-client_key.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA416515C89EA3002AEC4C /* SECG_ecc-secp256r1-client_key.h */; }; - 0CCA417715C89EA3002AEC4C /* SECG_ecc_rsa-secp256r1-client_cert.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA416615C89EA3002AEC4C /* SECG_ecc_rsa-secp256r1-client_cert.h */; }; - 0CCA417815C89EA3002AEC4C /* SECG_ecc_rsa-secp256r1-client_key.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CCA416715C89EA3002AEC4C /* SECG_ecc_rsa-secp256r1-client_key.h */; }; - 0CCA417915C89EA3002AEC4C /* ssl-39-echo.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA416815C89EA3002AEC4C /* ssl-39-echo.c */; }; - 0CCA417A15C89EA3002AEC4C /* ssl-40-clientauth.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA416915C89EA3002AEC4C /* ssl-40-clientauth.c */; }; - 0CCA417B15C89EA3002AEC4C /* ssl-41-clientauth.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA416A15C89EA3002AEC4C /* ssl-41-clientauth.c */; }; - 0CCA417C15C89EA3002AEC4C /* ssl-42-ciphers.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA416B15C89EA3002AEC4C /* ssl-42-ciphers.c */; }; - 0CCA417D15C89EA3002AEC4C /* ssl-43-ciphers.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA416C15C89EA3002AEC4C /* ssl-43-ciphers.c */; }; - 0CCA417E15C89EA3002AEC4C /* ssl-45-tls12.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA416D15C89EA3002AEC4C /* ssl-45-tls12.c */; }; - 0CCA42E115C8A3D9002AEC4C /* dtlsEchoClient.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA42C115C8A34E002AEC4C /* dtlsEchoClient.c */; }; - 0CCA42E215C8A3DE002AEC4C /* dtlsEchoServer.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA42C215C8A34E002AEC4C /* dtlsEchoServer.c */; }; - 0CCA42EC15C8A71A002AEC4C /* sslAppUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA42EA15C8A71A002AEC4C /* sslAppUtils.cpp */; }; - 0CCA42ED15C8A71A002AEC4C /* sslAppUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA42EA15C8A71A002AEC4C /* sslAppUtils.cpp */; }; - 0CCF28B8166D5F5000AFA37C /* ssl-47-falsestart.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCF28B7166D5F5000AFA37C /* ssl-47-falsestart.c */; }; - 4CAFF4370534D89900303760 /* appleCdsa.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF3FD0534D89900303760 /* appleCdsa.c */; }; - 4CAFF4390534D89900303760 /* appleSession.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF3FF0534D89900303760 /* appleSession.c */; }; - 4CAFF43B0534D89900303760 /* cipherSpecs.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4010534D89900303760 /* cipherSpecs.c */; }; - 4CAFF43F0534D89900303760 /* ModuleAttacher.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4050534D89900303760 /* ModuleAttacher.c */; }; - 4CAFF44B0534D89900303760 /* ssl3Callouts.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4110534D89900303760 /* ssl3Callouts.c */; }; - 4CAFF44C0534D89900303760 /* sslAlertMessage.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4120534D89900303760 /* sslAlertMessage.c */; }; - 4CAFF44E0534D89900303760 /* sslBER.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4140534D89900303760 /* sslBER.c */; }; - 4CAFF4520534D89900303760 /* sslCert.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4180534D89900303760 /* sslCert.c */; }; - 4CAFF4530534D89900303760 /* sslChangeCipher.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4190534D89900303760 /* sslChangeCipher.c */; }; - 4CAFF4540534D89900303760 /* sslContext.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF41A0534D89900303760 /* sslContext.c */; }; - 4CAFF4570534D89900303760 /* sslDigests.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF41D0534D89900303760 /* sslDigests.c */; }; - 4CAFF4590534D89900303760 /* sslHandshake.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF41F0534D89900303760 /* sslHandshake.c */; }; - 4CAFF45B0534D89900303760 /* sslHandshakeFinish.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4210534D89900303760 /* sslHandshakeFinish.c */; }; - 4CAFF45C0534D89900303760 /* sslHandshakeHello.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4220534D89900303760 /* sslHandshakeHello.c */; }; - 4CAFF45D0534D89900303760 /* sslKeychain.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4230534D89900303760 /* sslKeychain.c */; }; - 4CAFF45F0534D89900303760 /* sslKeyExchange.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4250534D89900303760 /* sslKeyExchange.c */; }; - 4CAFF4600534D89900303760 /* sslMemory.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4260534D89900303760 /* sslMemory.c */; }; - 4CAFF4620534D89900303760 /* sslNullCipher.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4280534D89900303760 /* sslNullCipher.c */; }; - 4CAFF4640534D89900303760 /* sslRecord.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF42A0534D89900303760 /* sslRecord.c */; }; - 4CAFF4660534D89900303760 /* sslSession.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF42C0534D89900303760 /* sslSession.c */; }; - 4CAFF4680534D89900303760 /* sslTransport.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF42E0534D89900303760 /* sslTransport.c */; }; - 4CAFF4690534D89900303760 /* sslUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF42F0534D89900303760 /* sslUtils.c */; }; - 4CAFF46B0534D89900303760 /* symCipher.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4310534D89900303760 /* symCipher.c */; }; - 4CAFF46D0534D89900303760 /* tls1Callouts.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4330534D89900303760 /* tls1Callouts.c */; }; - 4CAFF46E0534D89900303760 /* tls_hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4340534D89900303760 /* tls_hmac.c */; }; - AAB589F216CACE540071FE64 /* ssl-44-crashes.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CC954F0161A62AE005D3D4A /* ssl-44-crashes.c */; }; - BEB382AC14EC84A0003C055B /* sslCrypto.c in Sources */ = {isa = PBXBuildFile; fileRef = BEB382AB14EC84A0003C055B /* sslCrypto.c */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 0C6C633E15D1BD4D00BC68CD /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 0CCA42C815C8A387002AEC4C; - remoteInfo = dtlsEchoClient; - }; - 0C6C634015D1BD4E00BC68CD /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 0CCA42D615C8A395002AEC4C; - remoteInfo = dtlsEchoServer; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 0CCA42C715C8A387002AEC4C /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 0CCA42D515C8A395002AEC4C /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 0C0E0466162C9DF0009F7C71 /* ssl-46-SSLGetSupportedCiphers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-46-SSLGetSupportedCiphers.c"; sourceTree = ""; }; - 0C0E0469162CA288009F7C71 /* ssl_regressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ssl_regressions.h; sourceTree = ""; }; - 0C1C92ED15C8AC52007D377B /* kext.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = kext.xcconfig; sourceTree = ""; }; - 0C1C933A15C8AC81007D377B /* libsecurity_ssl_kext.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurity_ssl_kext.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 0C6C633315D1BB3300BC68CD /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Security.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 0C6C633715D1BB7100BC68CD /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; - 0C6C634215D1BDCF00BC68CD /* ssl-utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-utils.c"; sourceTree = ""; }; - 0C6C634415D1BE3900BC68CD /* ssl-utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ssl-utils.h"; sourceTree = ""; }; - 0C6C641C15D5840700BC68CD /* cert-1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "cert-1.h"; sourceTree = ""; }; - 0C6C641D15D5840700BC68CD /* identity-1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "identity-1.h"; sourceTree = ""; }; - 0C6C641E15D5840700BC68CD /* privkey-1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "privkey-1.h"; sourceTree = ""; }; - 0C85738D15DAB34C0038DFD7 /* tests.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = tests.xcconfig; sourceTree = ""; }; - 0CC954F0161A62AE005D3D4A /* ssl-44-crashes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-44-crashes.c"; sourceTree = ""; }; - 0CCA413415C75863002AEC4C /* SecureTransportPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecureTransportPriv.h; path = ../lib/SecureTransportPriv.h; sourceTree = ""; }; - 0CCA413515C75863002AEC4C /* ssl3RecordCallouts.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ssl3RecordCallouts.c; sourceTree = ""; }; - 0CCA413615C75863002AEC4C /* sslCipherSpecs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sslCipherSpecs.c; sourceTree = ""; }; - 0CCA413715C75863002AEC4C /* sslCipherSpecs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sslCipherSpecs.h; sourceTree = ""; }; - 0CCA413815C75863002AEC4C /* sslRand.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sslRand.c; sourceTree = ""; }; - 0CCA413915C75863002AEC4C /* sslRand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sslRand.h; sourceTree = ""; }; - 0CCA413A15C75863002AEC4C /* SSLRecordInternal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SSLRecordInternal.c; sourceTree = ""; }; - 0CCA413B15C75863002AEC4C /* SSLRecordInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSLRecordInternal.h; sourceTree = ""; }; - 0CCA413C15C75863002AEC4C /* sslTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sslTypes.h; path = ../lib/sslTypes.h; sourceTree = ""; }; - 0CCA413D15C75863002AEC4C /* symCipherParams.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = symCipherParams.c; sourceTree = ""; }; - 0CCA413E15C75863002AEC4C /* tls_digest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tls_digest.c; sourceTree = ""; }; - 0CCA413F15C75863002AEC4C /* tls_digest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tls_digest.h; sourceTree = ""; }; - 0CCA414015C75863002AEC4C /* tls_hashhmac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tls_hashhmac.c; sourceTree = ""; }; - 0CCA414115C75863002AEC4C /* tls_hashhmac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tls_hashhmac.h; sourceTree = ""; }; - 0CCA414215C75863002AEC4C /* tls_record.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tls_record.h; sourceTree = ""; }; - 0CCA414315C75863002AEC4C /* tls1RecordCallouts.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tls1RecordCallouts.c; sourceTree = ""; }; - 0CCA415915C89E8B002AEC4C /* libsecurity_ssl_regressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurity_ssl_regressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 0CCA415E15C89EA3002AEC4C /* ClientCert_ecc_ecc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientCert_ecc_ecc.h; sourceTree = ""; }; - 0CCA415F15C89EA3002AEC4C /* ClientCert_ecc_rsa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientCert_ecc_rsa.h; sourceTree = ""; }; - 0CCA416015C89EA3002AEC4C /* ClientCert_rsa_ecc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientCert_rsa_ecc.h; sourceTree = ""; }; - 0CCA416115C89EA3002AEC4C /* ClientCert_rsa_rsa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientCert_rsa_rsa.h; sourceTree = ""; }; - 0CCA416215C89EA3002AEC4C /* ClientKey_ecc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientKey_ecc.h; sourceTree = ""; }; - 0CCA416315C89EA3002AEC4C /* ClientKey_rsa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientKey_rsa.h; sourceTree = ""; }; - 0CCA416415C89EA3002AEC4C /* SECG_ecc-secp256r1-client_cert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SECG_ecc-secp256r1-client_cert.h"; sourceTree = ""; }; - 0CCA416515C89EA3002AEC4C /* SECG_ecc-secp256r1-client_key.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SECG_ecc-secp256r1-client_key.h"; sourceTree = ""; }; - 0CCA416615C89EA3002AEC4C /* SECG_ecc_rsa-secp256r1-client_cert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SECG_ecc_rsa-secp256r1-client_cert.h"; sourceTree = ""; }; - 0CCA416715C89EA3002AEC4C /* SECG_ecc_rsa-secp256r1-client_key.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SECG_ecc_rsa-secp256r1-client_key.h"; sourceTree = ""; }; - 0CCA416815C89EA3002AEC4C /* ssl-39-echo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-39-echo.c"; sourceTree = ""; }; - 0CCA416915C89EA3002AEC4C /* ssl-40-clientauth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-40-clientauth.c"; sourceTree = ""; }; - 0CCA416A15C89EA3002AEC4C /* ssl-41-clientauth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-41-clientauth.c"; sourceTree = ""; }; - 0CCA416B15C89EA3002AEC4C /* ssl-42-ciphers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-42-ciphers.c"; sourceTree = ""; }; - 0CCA416C15C89EA3002AEC4C /* ssl-43-ciphers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-43-ciphers.c"; sourceTree = ""; }; - 0CCA416D15C89EA3002AEC4C /* ssl-45-tls12.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-45-tls12.c"; sourceTree = ""; }; - 0CCA42C115C8A34E002AEC4C /* dtlsEchoClient.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dtlsEchoClient.c; sourceTree = ""; }; - 0CCA42C215C8A34E002AEC4C /* dtlsEchoServer.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dtlsEchoServer.c; sourceTree = ""; }; - 0CCA42C315C8A34E002AEC4C /* README */ = {isa = PBXFileReference; lastKnownFileType = text; path = README; sourceTree = ""; }; - 0CCA42C915C8A387002AEC4C /* dtlsEchoClient */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dtlsEchoClient; sourceTree = BUILT_PRODUCTS_DIR; }; - 0CCA42D715C8A395002AEC4C /* dtlsEchoServer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dtlsEchoServer; sourceTree = BUILT_PRODUCTS_DIR; }; - 0CCA42EA15C8A71A002AEC4C /* sslAppUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sslAppUtils.cpp; path = sslViewer/sslAppUtils.cpp; sourceTree = SOURCE_ROOT; }; - 0CCA42EB15C8A71A002AEC4C /* sslAppUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sslAppUtils.h; path = sslViewer/sslAppUtils.h; sourceTree = SOURCE_ROOT; }; - 0CCF28B7166D5F5000AFA37C /* ssl-47-falsestart.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-47-falsestart.c"; sourceTree = ""; }; - 4CA1FEBE052A3C8100F22E42 /* libsecurity_ssl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_ssl.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 4CAFF3FD0534D89900303760 /* appleCdsa.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = appleCdsa.c; sourceTree = ""; }; - 4CAFF3FE0534D89900303760 /* appleCdsa.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = appleCdsa.h; sourceTree = ""; }; - 4CAFF3FF0534D89900303760 /* appleSession.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = appleSession.c; sourceTree = ""; }; - 4CAFF4000534D89900303760 /* appleSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = appleSession.h; sourceTree = ""; }; - 4CAFF4010534D89900303760 /* cipherSpecs.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cipherSpecs.c; sourceTree = ""; }; - 4CAFF4020534D89900303760 /* cipherSpecs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cipherSpecs.h; sourceTree = ""; }; - 4CAFF4030534D89900303760 /* CipherSuite.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CipherSuite.h; sourceTree = ""; }; - 4CAFF4040534D89900303760 /* cryptType.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cryptType.h; sourceTree = ""; }; - 4CAFF4050534D89900303760 /* ModuleAttacher.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ModuleAttacher.c; sourceTree = ""; }; - 4CAFF4060534D89900303760 /* ModuleAttacher.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ModuleAttacher.h; sourceTree = ""; }; - 4CAFF4070534D89900303760 /* securetransport++.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = "securetransport++.cpp"; sourceTree = ""; }; - 4CAFF4080534D89900303760 /* securetransport++.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "securetransport++.h"; sourceTree = ""; }; - 4CAFF4090534D89900303760 /* SecureTransport.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecureTransport.h; sourceTree = ""; }; - 4CAFF40B0534D89900303760 /* ssl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ssl.h; sourceTree = ""; }; - 4CAFF4110534D89900303760 /* ssl3Callouts.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ssl3Callouts.c; sourceTree = ""; }; - 4CAFF4120534D89900303760 /* sslAlertMessage.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslAlertMessage.c; sourceTree = ""; }; - 4CAFF4130534D89900303760 /* sslAlertMessage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslAlertMessage.h; sourceTree = ""; }; - 4CAFF4140534D89900303760 /* sslBER.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslBER.c; sourceTree = ""; }; - 4CAFF4150534D89900303760 /* sslBER.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslBER.h; sourceTree = ""; }; - 4CAFF4170534D89900303760 /* sslBuildFlags.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslBuildFlags.h; sourceTree = ""; }; - 4CAFF4180534D89900303760 /* sslCert.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslCert.c; sourceTree = ""; }; - 4CAFF4190534D89900303760 /* sslChangeCipher.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslChangeCipher.c; sourceTree = ""; }; - 4CAFF41A0534D89900303760 /* sslContext.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslContext.c; sourceTree = ""; }; - 4CAFF41B0534D89900303760 /* sslContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslContext.h; sourceTree = ""; }; - 4CAFF41C0534D89900303760 /* sslDebug.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslDebug.h; sourceTree = ""; }; - 4CAFF41D0534D89900303760 /* sslDigests.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslDigests.c; sourceTree = ""; }; - 4CAFF41E0534D89900303760 /* sslDigests.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslDigests.h; sourceTree = ""; }; - 4CAFF41F0534D89900303760 /* sslHandshake.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslHandshake.c; sourceTree = ""; }; - 4CAFF4200534D89900303760 /* sslHandshake.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslHandshake.h; sourceTree = ""; }; - 4CAFF4210534D89900303760 /* sslHandshakeFinish.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslHandshakeFinish.c; sourceTree = ""; }; - 4CAFF4220534D89900303760 /* sslHandshakeHello.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslHandshakeHello.c; sourceTree = ""; }; - 4CAFF4230534D89900303760 /* sslKeychain.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslKeychain.c; sourceTree = ""; }; - 4CAFF4240534D89900303760 /* sslKeychain.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslKeychain.h; sourceTree = ""; }; - 4CAFF4250534D89900303760 /* sslKeyExchange.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslKeyExchange.c; sourceTree = ""; }; - 4CAFF4260534D89900303760 /* sslMemory.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslMemory.c; sourceTree = ""; }; - 4CAFF4270534D89900303760 /* sslMemory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslMemory.h; sourceTree = ""; }; - 4CAFF4280534D89900303760 /* sslNullCipher.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslNullCipher.c; sourceTree = ""; }; - 4CAFF4290534D89900303760 /* sslPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslPriv.h; sourceTree = ""; }; - 4CAFF42A0534D89900303760 /* sslRecord.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslRecord.c; sourceTree = ""; }; - 4CAFF42B0534D89900303760 /* sslRecord.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslRecord.h; sourceTree = ""; }; - 4CAFF42C0534D89900303760 /* sslSession.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslSession.c; sourceTree = ""; }; - 4CAFF42D0534D89900303760 /* sslSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslSession.h; sourceTree = ""; }; - 4CAFF42E0534D89900303760 /* sslTransport.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslTransport.c; sourceTree = ""; }; - 4CAFF42F0534D89900303760 /* sslUtils.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslUtils.c; sourceTree = ""; }; - 4CAFF4300534D89900303760 /* sslUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslUtils.h; sourceTree = ""; }; - 4CAFF4310534D89900303760 /* symCipher.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = symCipher.c; sourceTree = ""; }; - 4CAFF4320534D89900303760 /* symCipher.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = symCipher.h; sourceTree = ""; }; - 4CAFF4330534D89900303760 /* tls1Callouts.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = tls1Callouts.c; sourceTree = ""; }; - 4CAFF4340534D89900303760 /* tls_hmac.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = tls_hmac.c; sourceTree = ""; }; - 4CAFF4350534D89900303760 /* tls_hmac.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tls_hmac.h; sourceTree = ""; }; - 4CAFF4360534D89900303760 /* tls_ssl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tls_ssl.h; sourceTree = ""; }; - 4CCBFE3C057FF16800981D43 /* security_ssl.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = security_ssl.exp; sourceTree = ""; }; - BE6A959C14E3700A00C158E0 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; - BE6A959D14E3700A00C158E0 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; - BE6A959E14E3700A00C158E0 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; - BE6A959F14E3700A00C158E0 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; - BEB382AB14EC84A0003C055B /* sslCrypto.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sslCrypto.c; sourceTree = ""; }; - BEB382AE14EC84AC003C055B /* sslCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sslCrypto.h; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 0C1C933615C8AC81007D377B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0CCA415615C89E8B002AEC4C /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0CCA42C615C8A387002AEC4C /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 0C6C633815D1BB7100BC68CD /* CoreFoundation.framework in Frameworks */, - 0C6C633515D1BB4F00BC68CD /* Security.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0CCA42D415C8A395002AEC4C /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 0C6C633915D1BBAA00BC68CD /* CoreFoundation.framework in Frameworks */, - 0C6C633615D1BB6000BC68CD /* Security.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 050651C7056A83F3008AD683 /* Apple Custom */ = { - isa = PBXGroup; - children = ( - 4CAFF4050534D89900303760 /* ModuleAttacher.c */, - 4CAFF3FD0534D89900303760 /* appleCdsa.c */, - 4CAFF3FF0534D89900303760 /* appleSession.c */, - 4CAFF4230534D89900303760 /* sslKeychain.c */, - ); - name = "Apple Custom"; - sourceTree = ""; - }; - 050651C8056A8404008AD683 /* SSL Core */ = { - isa = PBXGroup; - children = ( - 0CCA413A15C75863002AEC4C /* SSLRecordInternal.c */, - 4CAFF4120534D89900303760 /* sslAlertMessage.c */, - 0CCA413615C75863002AEC4C /* sslCipherSpecs.c */, - 4CAFF41A0534D89900303760 /* sslContext.c */, - 4CAFF42A0534D89900303760 /* sslRecord.c */, - 4CAFF42C0534D89900303760 /* sslSession.c */, - 4CAFF42E0534D89900303760 /* sslTransport.c */, - 4CAFF4110534D89900303760 /* ssl3Callouts.c */, - 0CCA413515C75863002AEC4C /* ssl3RecordCallouts.c */, - 4CAFF4330534D89900303760 /* tls1Callouts.c */, - 0CCA414315C75863002AEC4C /* tls1RecordCallouts.c */, - 050651E4056A86CF008AD683 /* Handshake */, - ); - name = "SSL Core"; - sourceTree = ""; - }; - 050651C9056A840E008AD683 /* Private Headers */ = { - isa = PBXGroup; - children = ( - 0CCA413C15C75863002AEC4C /* sslTypes.h */, - 0CCA413415C75863002AEC4C /* SecureTransportPriv.h */, - ); - name = "Private Headers"; - path = ../Security; - sourceTree = ""; - }; - 050651CA056A8415008AD683 /* Public Headers */ = { - isa = PBXGroup; - children = ( - 4CAFF4030534D89900303760 /* CipherSuite.h */, - 4CAFF4090534D89900303760 /* SecureTransport.h */, - ); - name = "Public Headers"; - path = ../Security; - sourceTree = ""; - }; - 050651CB056A841C008AD683 /* Crypto */ = { - isa = PBXGroup; - children = ( - 4CAFF4010534D89900303760 /* cipherSpecs.c */, - 0CCA413D15C75863002AEC4C /* symCipherParams.c */, - 0CCA413815C75863002AEC4C /* sslRand.c */, - BEB382AB14EC84A0003C055B /* sslCrypto.c */, - 4CAFF41D0534D89900303760 /* sslDigests.c */, - 4CAFF4280534D89900303760 /* sslNullCipher.c */, - 4CAFF4310534D89900303760 /* symCipher.c */, - 0CCA413E15C75863002AEC4C /* tls_digest.c */, - 0CCA414015C75863002AEC4C /* tls_hashhmac.c */, - 4CAFF4340534D89900303760 /* tls_hmac.c */, - ); - name = Crypto; - sourceTree = ""; - }; - 050651CC056A8421008AD683 /* Misc. */ = { - isa = PBXGroup; - children = ( - 4CAFF4140534D89900303760 /* sslBER.c */, - 4CAFF4260534D89900303760 /* sslMemory.c */, - 4CAFF42F0534D89900303760 /* sslUtils.c */, - ); - name = Misc.; - sourceTree = ""; - }; - 050651CD056A8427008AD683 /* C++ Interface */ = { - isa = PBXGroup; - children = ( - 4CAFF4070534D89900303760 /* securetransport++.cpp */, - 4CAFF4080534D89900303760 /* securetransport++.h */, - ); - name = "C++ Interface"; - sourceTree = ""; - }; - 050651E4056A86CF008AD683 /* Handshake */ = { - isa = PBXGroup; - children = ( - 4CAFF4180534D89900303760 /* sslCert.c */, - 4CAFF4190534D89900303760 /* sslChangeCipher.c */, - 4CAFF41F0534D89900303760 /* sslHandshake.c */, - 4CAFF4210534D89900303760 /* sslHandshakeFinish.c */, - 4CAFF4220534D89900303760 /* sslHandshakeHello.c */, - 4CAFF4250534D89900303760 /* sslKeyExchange.c */, - ); - name = Handshake; - sourceTree = ""; - }; - 0CCA415D15C89EA3002AEC4C /* regressions */ = { - isa = PBXGroup; - children = ( - 0C6C641C15D5840700BC68CD /* cert-1.h */, - 0C6C641D15D5840700BC68CD /* identity-1.h */, - 0C6C641E15D5840700BC68CD /* privkey-1.h */, - 0CCA415E15C89EA3002AEC4C /* ClientCert_ecc_ecc.h */, - 0CCA415F15C89EA3002AEC4C /* ClientCert_ecc_rsa.h */, - 0CCA416015C89EA3002AEC4C /* ClientCert_rsa_ecc.h */, - 0CCA416115C89EA3002AEC4C /* ClientCert_rsa_rsa.h */, - 0CCA416215C89EA3002AEC4C /* ClientKey_ecc.h */, - 0CCA416315C89EA3002AEC4C /* ClientKey_rsa.h */, - 0CCA416415C89EA3002AEC4C /* SECG_ecc-secp256r1-client_cert.h */, - 0CCA416515C89EA3002AEC4C /* SECG_ecc-secp256r1-client_key.h */, - 0CCA416615C89EA3002AEC4C /* SECG_ecc_rsa-secp256r1-client_cert.h */, - 0CCA416715C89EA3002AEC4C /* SECG_ecc_rsa-secp256r1-client_key.h */, - 0CCA416815C89EA3002AEC4C /* ssl-39-echo.c */, - 0CCA416915C89EA3002AEC4C /* ssl-40-clientauth.c */, - 0CCA416A15C89EA3002AEC4C /* ssl-41-clientauth.c */, - 0CCA416B15C89EA3002AEC4C /* ssl-42-ciphers.c */, - 0CCA416C15C89EA3002AEC4C /* ssl-43-ciphers.c */, - 0CC954F0161A62AE005D3D4A /* ssl-44-crashes.c */, - 0CCA416D15C89EA3002AEC4C /* ssl-45-tls12.c */, - 0C0E0466162C9DF0009F7C71 /* ssl-46-SSLGetSupportedCiphers.c */, - 0CCF28B7166D5F5000AFA37C /* ssl-47-falsestart.c */, - 0C6C634215D1BDCF00BC68CD /* ssl-utils.c */, - 0C6C634415D1BE3900BC68CD /* ssl-utils.h */, - 0C0E0469162CA288009F7C71 /* ssl_regressions.h */, - ); - path = regressions; - sourceTree = ""; - }; - 0CCA42C015C8A34E002AEC4C /* dtlsEcho */ = { - isa = PBXGroup; - children = ( - 0CCA42EA15C8A71A002AEC4C /* sslAppUtils.cpp */, - 0CCA42EB15C8A71A002AEC4C /* sslAppUtils.h */, - 0CCA42C115C8A34E002AEC4C /* dtlsEchoClient.c */, - 0CCA42C215C8A34E002AEC4C /* dtlsEchoServer.c */, - 0CCA42C315C8A34E002AEC4C /* README */, - ); - path = dtlsEcho; - sourceTree = ""; - }; - 4CA1FEA7052A3C3800F22E42 = { - isa = PBXGroup; - children = ( - 0C6C633715D1BB7100BC68CD /* CoreFoundation.framework */, - 0C6C633315D1BB3300BC68CD /* Security.framework */, - 0CCA42C015C8A34E002AEC4C /* dtlsEcho */, - 0CCA415D15C89EA3002AEC4C /* regressions */, - BE6A959B14E3700A00C158E0 /* config */, - 4CAFF3FC0534D89900303760 /* lib */, - 4CA1FEBF052A3C8100F22E42 /* Products */, - ); - sourceTree = ""; - }; - 4CA1FEBF052A3C8100F22E42 /* Products */ = { - isa = PBXGroup; - children = ( - 4CA1FEBE052A3C8100F22E42 /* libsecurity_ssl.a */, - 0CCA415915C89E8B002AEC4C /* libsecurity_ssl_regressions.a */, - 0CCA42C915C8A387002AEC4C /* dtlsEchoClient */, - 0CCA42D715C8A395002AEC4C /* dtlsEchoServer */, - 0C1C933A15C8AC81007D377B /* libsecurity_ssl_kext.a */, - ); - name = Products; - sourceTree = ""; - }; - 4CAFF3FC0534D89900303760 /* lib */ = { - isa = PBXGroup; - children = ( - 050651C7056A83F3008AD683 /* Apple Custom */, - 050651C8056A8404008AD683 /* SSL Core */, - 050651CA056A8415008AD683 /* Public Headers */, - 050651C9056A840E008AD683 /* Private Headers */, - BE967B0314E9F622002A348A /* Project Headers */, - 050651CB056A841C008AD683 /* Crypto */, - 050651CC056A8421008AD683 /* Misc. */, - 050651CD056A8427008AD683 /* C++ Interface */, - 4CCBFE3C057FF16800981D43 /* security_ssl.exp */, - ); - path = lib; - sourceTree = ""; - }; - BE6A959B14E3700A00C158E0 /* config */ = { - isa = PBXGroup; - children = ( - BE6A959C14E3700A00C158E0 /* base.xcconfig */, - BE6A959D14E3700A00C158E0 /* debug.xcconfig */, - 0C1C92ED15C8AC52007D377B /* kext.xcconfig */, - BE6A959E14E3700A00C158E0 /* lib.xcconfig */, - BE6A959F14E3700A00C158E0 /* release.xcconfig */, - 0C85738D15DAB34C0038DFD7 /* tests.xcconfig */, - ); - path = config; - sourceTree = ""; - }; - BE967B0314E9F622002A348A /* Project Headers */ = { - isa = PBXGroup; - children = ( - 0CCA413715C75863002AEC4C /* sslCipherSpecs.h */, - 0CCA413B15C75863002AEC4C /* SSLRecordInternal.h */, - 0CCA413915C75863002AEC4C /* sslRand.h */, - 0CCA413F15C75863002AEC4C /* tls_digest.h */, - 0CCA414115C75863002AEC4C /* tls_hashhmac.h */, - 0CCA414215C75863002AEC4C /* tls_record.h */, - 4CAFF3FE0534D89900303760 /* appleCdsa.h */, - 4CAFF4000534D89900303760 /* appleSession.h */, - 4CAFF4020534D89900303760 /* cipherSpecs.h */, - 4CAFF4040534D89900303760 /* cryptType.h */, - 4CAFF4060534D89900303760 /* ModuleAttacher.h */, - 4CAFF40B0534D89900303760 /* ssl.h */, - 4CAFF4130534D89900303760 /* sslAlertMessage.h */, - 4CAFF4150534D89900303760 /* sslBER.h */, - 4CAFF4170534D89900303760 /* sslBuildFlags.h */, - 4CAFF41B0534D89900303760 /* sslContext.h */, - BEB382AE14EC84AC003C055B /* sslCrypto.h */, - 4CAFF41C0534D89900303760 /* sslDebug.h */, - 4CAFF41E0534D89900303760 /* sslDigests.h */, - 4CAFF4200534D89900303760 /* sslHandshake.h */, - 4CAFF4240534D89900303760 /* sslKeychain.h */, - 4CAFF4270534D89900303760 /* sslMemory.h */, - 4CAFF4290534D89900303760 /* sslPriv.h */, - 4CAFF42B0534D89900303760 /* sslRecord.h */, - 4CAFF42D0534D89900303760 /* sslSession.h */, - 4CAFF4300534D89900303760 /* sslUtils.h */, - 4CAFF4320534D89900303760 /* symCipher.h */, - 4CAFF4350534D89900303760 /* tls_hmac.h */, - 4CAFF4360534D89900303760 /* tls_ssl.h */, - ); - name = "Project Headers"; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 0C1C92F015C8AC81007D377B /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 0C1C933B15C8AFB8007D377B /* SSLRecordInternal.h in Headers */, - 0C1C92F315C8AC81007D377B /* cipherSpecs.h in Headers */, - 0C1C92F515C8AC81007D377B /* cryptType.h in Headers */, - 0C1C930815C8AC81007D377B /* CipherSuite.h in Headers */, - 0C1C92F415C8AC81007D377B /* sslTypes.h in Headers */, - 0C1C930015C8AC81007D377B /* sslMemory.h in Headers */, - 0C1C930515C8AC81007D377B /* symCipher.h in Headers */, - 0C1C930615C8AC81007D377B /* tls_hmac.h in Headers */, - 0C1C931015C8AC81007D377B /* tls_digest.h in Headers */, - 0C1C931115C8AC81007D377B /* tls_hashhmac.h in Headers */, - 0C1C931215C8AC81007D377B /* tls_record.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0CCA415715C89E8B002AEC4C /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 0CCA416F15C89EA3002AEC4C /* ClientCert_ecc_ecc.h in Headers */, - 0CCA417015C89EA3002AEC4C /* ClientCert_ecc_rsa.h in Headers */, - 0CCA417115C89EA3002AEC4C /* ClientCert_rsa_ecc.h in Headers */, - 0CCA417215C89EA3002AEC4C /* ClientCert_rsa_rsa.h in Headers */, - 0CCA417315C89EA3002AEC4C /* ClientKey_ecc.h in Headers */, - 0CCA417415C89EA3002AEC4C /* ClientKey_rsa.h in Headers */, - 0CCA417515C89EA3002AEC4C /* SECG_ecc-secp256r1-client_cert.h in Headers */, - 0CCA417615C89EA3002AEC4C /* SECG_ecc-secp256r1-client_key.h in Headers */, - 0CCA417715C89EA3002AEC4C /* SECG_ecc_rsa-secp256r1-client_cert.h in Headers */, - 0CCA417815C89EA3002AEC4C /* SECG_ecc_rsa-secp256r1-client_key.h in Headers */, - 0C6C634515D1BE3900BC68CD /* ssl-utils.h in Headers */, - 0C6C641F15D5840700BC68CD /* cert-1.h in Headers */, - 0C6C642015D5840700BC68CD /* identity-1.h in Headers */, - 0C6C642115D5840700BC68CD /* privkey-1.h in Headers */, - 0C0E046A162CA288009F7C71 /* ssl_regressions.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 0C1C92EF15C8AC81007D377B /* libsecurity_ssl_kext */ = { - isa = PBXNativeTarget; - buildConfigurationList = 0C1C933715C8AC81007D377B /* Build configuration list for PBXNativeTarget "libsecurity_ssl_kext" */; - buildPhases = ( - 0C1C92F015C8AC81007D377B /* Headers */, - 0C1C931315C8AC81007D377B /* Sources */, - 0C1C933615C8AC81007D377B /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libsecurity_ssl_kext; - productName = libsecurity_ssl; - productReference = 0C1C933A15C8AC81007D377B /* libsecurity_ssl_kext.a */; - productType = "com.apple.product-type.library.static"; - }; - 0CCA415815C89E8B002AEC4C /* libsecurity_ssl_regressions */ = { - isa = PBXNativeTarget; - buildConfigurationList = 0CCA415A15C89E8B002AEC4C /* Build configuration list for PBXNativeTarget "libsecurity_ssl_regressions" */; - buildPhases = ( - 0CCA415515C89E8B002AEC4C /* Sources */, - 0CCA415615C89E8B002AEC4C /* Frameworks */, - 0CCA415715C89E8B002AEC4C /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libsecurity_ssl_regressions; - productName = libsecurity_ssl_regressions; - productReference = 0CCA415915C89E8B002AEC4C /* libsecurity_ssl_regressions.a */; - productType = "com.apple.product-type.library.static"; - }; - 0CCA42C815C8A387002AEC4C /* dtlsEchoClient */ = { - isa = PBXNativeTarget; - buildConfigurationList = 0CCA42D015C8A387002AEC4C /* Build configuration list for PBXNativeTarget "dtlsEchoClient" */; - buildPhases = ( - 0CCA42C515C8A387002AEC4C /* Sources */, - 0CCA42C615C8A387002AEC4C /* Frameworks */, - 0CCA42C715C8A387002AEC4C /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = dtlsEchoClient; - productName = dtlsEchoClient; - productReference = 0CCA42C915C8A387002AEC4C /* dtlsEchoClient */; - productType = "com.apple.product-type.tool"; - }; - 0CCA42D615C8A395002AEC4C /* dtlsEchoServer */ = { - isa = PBXNativeTarget; - buildConfigurationList = 0CCA42DE15C8A395002AEC4C /* Build configuration list for PBXNativeTarget "dtlsEchoServer" */; - buildPhases = ( - 0CCA42D315C8A395002AEC4C /* Sources */, - 0CCA42D415C8A395002AEC4C /* Frameworks */, - 0CCA42D515C8A395002AEC4C /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = dtlsEchoServer; - productName = dtlsEchoServer; - productReference = 0CCA42D715C8A395002AEC4C /* dtlsEchoServer */; - productType = "com.apple.product-type.tool"; - }; - 4CA1FEBD052A3C8100F22E42 /* libsecurity_ssl */ = { - isa = PBXNativeTarget; - buildConfigurationList = C27AD4000987FCDF001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_ssl" */; - buildPhases = ( - 4CA1FEBA052A3C8100F22E42 /* Sources */, - 4CA1FEBB052A3C8100F22E42 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libsecurity_ssl; - productName = libsecurity_ssl; - productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_ssl.a */; - productType = "com.apple.product-type.library.static"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 4CA1FEAB052A3C3800F22E42 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0500; - }; - buildConfigurationList = C27AD4040987FCDF001272E0 /* Build configuration list for PBXProject "libsecurity_ssl" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - en, - ); - mainGroup = 4CA1FEA7052A3C3800F22E42; - productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 4CA1FEBD052A3C8100F22E42 /* libsecurity_ssl */, - 0C1C92EF15C8AC81007D377B /* libsecurity_ssl_kext */, - 0CCA415815C89E8B002AEC4C /* libsecurity_ssl_regressions */, - 0CCA42C815C8A387002AEC4C /* dtlsEchoClient */, - 0CCA42D615C8A395002AEC4C /* dtlsEchoServer */, - 0C6C633A15D1BD4800BC68CD /* dtlsEcho */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 0C1C931315C8AC81007D377B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0C1C931615C8AC81007D377B /* cipherSpecs.c in Sources */, - 0C1C932415C8AC81007D377B /* sslMemory.c in Sources */, - 0C1C932515C8AC81007D377B /* sslNullCipher.c in Sources */, - 0C1C932915C8AC81007D377B /* sslUtils.c in Sources */, - 0C1C932A15C8AC81007D377B /* symCipher.c in Sources */, - 0C1C932E15C8AC81007D377B /* ssl3RecordCallouts.c in Sources */, - 0C1C933015C8AC81007D377B /* sslRand.c in Sources */, - 0C1C933115C8AC81007D377B /* SSLRecordInternal.c in Sources */, - 0C1C933215C8AC81007D377B /* symCipherParams.c in Sources */, - 0C1C933315C8AC81007D377B /* tls_digest.c in Sources */, - 0C1C932C15C8AC81007D377B /* tls_hmac.c in Sources */, - 0C1C933415C8AC81007D377B /* tls_hashhmac.c in Sources */, - 0C1C933515C8AC81007D377B /* tls1RecordCallouts.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0CCA415515C89E8B002AEC4C /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0CCA417915C89EA3002AEC4C /* ssl-39-echo.c in Sources */, - 0CCA417A15C89EA3002AEC4C /* ssl-40-clientauth.c in Sources */, - 0CCA417B15C89EA3002AEC4C /* ssl-41-clientauth.c in Sources */, - 0CCA417C15C89EA3002AEC4C /* ssl-42-ciphers.c in Sources */, - 0CCA417D15C89EA3002AEC4C /* ssl-43-ciphers.c in Sources */, - AAB589F216CACE540071FE64 /* ssl-44-crashes.c in Sources */, - 0CCA417E15C89EA3002AEC4C /* ssl-45-tls12.c in Sources */, - 0CCF28B8166D5F5000AFA37C /* ssl-47-falsestart.c in Sources */, - 0C6C634315D1BDCF00BC68CD /* ssl-utils.c in Sources */, - 0C0E0467162C9DF0009F7C71 /* ssl-46-SSLGetSupportedCiphers.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0CCA42C515C8A387002AEC4C /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0C6C642315D5938E00BC68CD /* ssl-utils.c in Sources */, - 0CCA42E115C8A3D9002AEC4C /* dtlsEchoClient.c in Sources */, - 0CCA42EC15C8A71A002AEC4C /* sslAppUtils.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0CCA42D315C8A395002AEC4C /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0C6C642415D5939A00BC68CD /* ssl-utils.c in Sources */, - 0CCA42E215C8A3DE002AEC4C /* dtlsEchoServer.c in Sources */, - 0CCA42ED15C8A71A002AEC4C /* sslAppUtils.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4CA1FEBA052A3C8100F22E42 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 4CAFF4370534D89900303760 /* appleCdsa.c in Sources */, - 4CAFF4390534D89900303760 /* appleSession.c in Sources */, - 4CAFF43B0534D89900303760 /* cipherSpecs.c in Sources */, - 4CAFF43F0534D89900303760 /* ModuleAttacher.c in Sources */, - 4CAFF44B0534D89900303760 /* ssl3Callouts.c in Sources */, - 4CAFF44C0534D89900303760 /* sslAlertMessage.c in Sources */, - 4CAFF44E0534D89900303760 /* sslBER.c in Sources */, - 4CAFF4520534D89900303760 /* sslCert.c in Sources */, - 4CAFF4530534D89900303760 /* sslChangeCipher.c in Sources */, - 4CAFF4540534D89900303760 /* sslContext.c in Sources */, - 4CAFF4570534D89900303760 /* sslDigests.c in Sources */, - 4CAFF4590534D89900303760 /* sslHandshake.c in Sources */, - 4CAFF45B0534D89900303760 /* sslHandshakeFinish.c in Sources */, - 4CAFF45C0534D89900303760 /* sslHandshakeHello.c in Sources */, - 4CAFF45D0534D89900303760 /* sslKeychain.c in Sources */, - 4CAFF45F0534D89900303760 /* sslKeyExchange.c in Sources */, - 4CAFF4600534D89900303760 /* sslMemory.c in Sources */, - 4CAFF4620534D89900303760 /* sslNullCipher.c in Sources */, - 4CAFF4640534D89900303760 /* sslRecord.c in Sources */, - 4CAFF4660534D89900303760 /* sslSession.c in Sources */, - 4CAFF4680534D89900303760 /* sslTransport.c in Sources */, - 4CAFF4690534D89900303760 /* sslUtils.c in Sources */, - 4CAFF46B0534D89900303760 /* symCipher.c in Sources */, - 4CAFF46D0534D89900303760 /* tls1Callouts.c in Sources */, - 4CAFF46E0534D89900303760 /* tls_hmac.c in Sources */, - BEB382AC14EC84A0003C055B /* sslCrypto.c in Sources */, - 0CCA414515C75863002AEC4C /* ssl3RecordCallouts.c in Sources */, - 0CCA414615C75863002AEC4C /* sslCipherSpecs.c in Sources */, - 0CCA414815C75863002AEC4C /* sslRand.c in Sources */, - 0CCA414A15C75863002AEC4C /* SSLRecordInternal.c in Sources */, - 0CCA414D15C75863002AEC4C /* symCipherParams.c in Sources */, - 0CCA414E15C75863002AEC4C /* tls_digest.c in Sources */, - 0CCA415015C75863002AEC4C /* tls_hashhmac.c in Sources */, - 0CCA415315C75863002AEC4C /* tls1RecordCallouts.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 0C6C633F15D1BD4D00BC68CD /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 0CCA42C815C8A387002AEC4C /* dtlsEchoClient */; - targetProxy = 0C6C633E15D1BD4D00BC68CD /* PBXContainerItemProxy */; - }; - 0C6C634115D1BD4E00BC68CD /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 0CCA42D615C8A395002AEC4C /* dtlsEchoServer */; - targetProxy = 0C6C634015D1BD4E00BC68CD /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 0C1C933815C8AC81007D377B /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 0C1C92ED15C8AC52007D377B /* kext.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Debug; - }; - 0C1C933915C8AC81007D377B /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 0C1C92ED15C8AC52007D377B /* kext.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Release; - }; - 0C6C633C15D1BD4800BC68CD /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 0C6C633D15D1BD4800BC68CD /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 0CCA415B15C89E8B002AEC4C /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = BE6A959E14E3700A00C158E0 /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Debug; - }; - 0CCA415C15C89E8B002AEC4C /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = BE6A959E14E3700A00C158E0 /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Release; - }; - 0CCA42D115C8A387002AEC4C /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 0C85738D15DAB34C0038DFD7 /* tests.xcconfig */; - buildSettings = { - }; - name = Debug; - }; - 0CCA42D215C8A387002AEC4C /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 0C85738D15DAB34C0038DFD7 /* tests.xcconfig */; - buildSettings = { - }; - name = Release; - }; - 0CCA42DF15C8A395002AEC4C /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 0C85738D15DAB34C0038DFD7 /* tests.xcconfig */; - buildSettings = { - }; - name = Debug; - }; - 0CCA42E015C8A395002AEC4C /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 0C85738D15DAB34C0038DFD7 /* tests.xcconfig */; - buildSettings = { - }; - name = Release; - }; - C27AD4010987FCDF001272E0 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = BE6A959E14E3700A00C158E0 /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Debug; - }; - C27AD4030987FCDF001272E0 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = BE6A959E14E3700A00C158E0 /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Release; - }; - C27AD4050987FCDF001272E0 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = BE6A959D14E3700A00C158E0 /* debug.xcconfig */; - buildSettings = { - }; - name = Debug; - }; - C27AD4070987FCDF001272E0 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = BE6A959F14E3700A00C158E0 /* release.xcconfig */; - buildSettings = { - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 0C1C933715C8AC81007D377B /* Build configuration list for PBXNativeTarget "libsecurity_ssl_kext" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0C1C933815C8AC81007D377B /* Debug */, - 0C1C933915C8AC81007D377B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0C6C633B15D1BD4800BC68CD /* Build configuration list for PBXAggregateTarget "dtlsEcho" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0C6C633C15D1BD4800BC68CD /* Debug */, - 0C6C633D15D1BD4800BC68CD /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0CCA415A15C89E8B002AEC4C /* Build configuration list for PBXNativeTarget "libsecurity_ssl_regressions" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0CCA415B15C89E8B002AEC4C /* Debug */, - 0CCA415C15C89E8B002AEC4C /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0CCA42D015C8A387002AEC4C /* Build configuration list for PBXNativeTarget "dtlsEchoClient" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0CCA42D115C8A387002AEC4C /* Debug */, - 0CCA42D215C8A387002AEC4C /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0CCA42DE15C8A395002AEC4C /* Build configuration list for PBXNativeTarget "dtlsEchoServer" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0CCA42DF15C8A395002AEC4C /* Debug */, - 0CCA42E015C8A395002AEC4C /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C27AD4000987FCDF001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_ssl" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C27AD4010987FCDF001272E0 /* Debug */, - C27AD4030987FCDF001272E0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C27AD4040987FCDF001272E0 /* Build configuration list for PBXProject "libsecurity_ssl" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C27AD4050987FCDF001272E0 /* Debug */, - C27AD4070987FCDF001272E0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; -} diff --git a/libsecurity_ssl/libsecurity_ssl.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_ssl/libsecurity_ssl.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 48b06b64..00000000 --- a/libsecurity_ssl/libsecurity_ssl.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,39 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 0C1C92EF15C8AC81007D377B - - primary - - - 0C6C633A15D1BD4800BC68CD - - primary - - - 0CCA415815C89E8B002AEC4C - - primary - - - 0CCA42C815C8A387002AEC4C - - primary - - - 0CCA42D615C8A395002AEC4C - - primary - - - 4CA1FEBD052A3C8100F22E42 - - primary - - - - - diff --git a/libsecurity_ssl/regressions/ssl-utils.c b/libsecurity_ssl/regressions/ssl-utils.c deleted file mode 100644 index 304f29cb..00000000 --- a/libsecurity_ssl/regressions/ssl-utils.c +++ /dev/null @@ -1,259 +0,0 @@ -// -// ssl-utils.c -// libsecurity_ssl -// -// Created by Fabrice Gautier on 8/7/12. -// -// - -#include -#include - -#include "ssl-utils.h" - -#if TARGET_OS_IPHONE - -#include -#include -#include -#include - -#include "privkey-1.h" -#include "cert-1.h" - -static -CFArrayRef chain_from_der(const unsigned char *pkey_der, size_t pkey_der_len, const unsigned char *cert_der, size_t cert_der_len) -{ - SecKeyRef pkey = NULL; - SecCertificateRef cert = NULL; - SecIdentityRef ident = NULL; - CFArrayRef items = NULL; - - require(pkey = SecKeyCreateRSAPrivateKey(kCFAllocatorDefault, pkey_der, pkey_der_len, kSecKeyEncodingPkcs1), errOut); - require(cert = SecCertificateCreateWithBytes(kCFAllocatorDefault, cert_der, cert_der_len), errOut); - require(ident = SecIdentityCreate(kCFAllocatorDefault, cert, pkey), errOut); - require(items = CFArrayCreate(kCFAllocatorDefault, (const void **)&ident, 1, &kCFTypeArrayCallBacks), errOut); - -errOut: - CFReleaseSafe(pkey); - CFReleaseSafe(cert); - CFReleaseSafe(ident); - return items; -} - -#else - -#include "identity-1.h" -#define P12_PASSWORD "password" - -static -CFArrayRef chain_from_p12(const unsigned char *p12_data, size_t p12_len) -{ - char keychain_path[] = "/tmp/keychain.XXXXXX"; - - SecKeychainRef keychain = NULL; - CFArrayRef list; - CFDataRef data; - - SecExternalFormat format=kSecFormatPKCS12; - SecExternalItemType type=kSecItemTypeAggregate; - SecItemImportExportFlags flags=0; - SecKeyImportExportParameters params = {0,}; - CFArrayRef out = NULL; - - require_noerr(SecKeychainCopyDomainSearchList(kSecPreferencesDomainUser, &list), errOut); - require(mktemp(keychain_path), errOut); - require_noerr(SecKeychainCreate (keychain_path, strlen(P12_PASSWORD), P12_PASSWORD, - FALSE, NULL, &keychain), errOut); - require_noerr(SecKeychainSetDomainSearchList(kSecPreferencesDomainUser, list), errOut); // restores the previous search list - require(data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, p12_data, p12_len, kCFAllocatorNull), errOut); - - - params.passphrase=CFSTR("password"); - params.keyAttributes = CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_SENSITIVE; - - require_noerr(SecKeychainItemImport(data, CFSTR(".p12"), &format, &type, flags, - ¶ms, keychain, &out), errOut); - -errOut: - CFReleaseSafe(keychain); - CFReleaseSafe(list); - - return out; -} - -#endif - -CFArrayRef server_chain(void) -{ -#if TARGET_OS_IPHONE - return chain_from_der(privkey_1_der, privkey_1_der_len, cert_1_der, cert_1_der_len); -#else - return chain_from_p12(identity_1_p12, identity_1_p12_len); -#endif -} - -CFArrayRef client_chain(void) -{ -#if TARGET_OS_IPHONE - return chain_from_der(privkey_1_der, privkey_1_der_len, cert_1_der, cert_1_der_len); -#else - return chain_from_p12(identity_1_p12, identity_1_p12_len); -#endif -} - -const char *ciphersuite_name(SSLCipherSuite cs) -{ - -#define C(x) case x: return #x; - switch (cs) { - - /* TLS 1.2 addenda, RFC 5246 */ - - /* Initial state. */ - C(TLS_NULL_WITH_NULL_NULL) - - /* Server provided RSA certificate for key exchange. */ - C(TLS_RSA_WITH_NULL_MD5) - C(TLS_RSA_WITH_NULL_SHA) - C(TLS_RSA_WITH_RC4_128_MD5) - C(TLS_RSA_WITH_RC4_128_SHA) - C(TLS_RSA_WITH_3DES_EDE_CBC_SHA) - C(TLS_RSA_WITH_AES_128_CBC_SHA) - C(TLS_RSA_WITH_AES_256_CBC_SHA) - C(TLS_RSA_WITH_NULL_SHA256) - C(TLS_RSA_WITH_AES_128_CBC_SHA256) - C(TLS_RSA_WITH_AES_256_CBC_SHA256) - - /* Server-authenticated (and optionally client-authenticated) Diffie-Hellman. */ - C(TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA) - C(TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA) - C(TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA) - C(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) - C(TLS_DH_DSS_WITH_AES_128_CBC_SHA) - C(TLS_DH_RSA_WITH_AES_128_CBC_SHA) - C(TLS_DHE_DSS_WITH_AES_128_CBC_SHA) - C(TLS_DHE_RSA_WITH_AES_128_CBC_SHA) - C(TLS_DH_DSS_WITH_AES_256_CBC_SHA) - C(TLS_DH_RSA_WITH_AES_256_CBC_SHA) - C(TLS_DHE_DSS_WITH_AES_256_CBC_SHA) - C(TLS_DHE_RSA_WITH_AES_256_CBC_SHA) - C(TLS_DH_DSS_WITH_AES_128_CBC_SHA256) - C(TLS_DH_RSA_WITH_AES_128_CBC_SHA256) - C(TLS_DHE_DSS_WITH_AES_128_CBC_SHA256) - C(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) - C(TLS_DH_DSS_WITH_AES_256_CBC_SHA256) - C(TLS_DH_RSA_WITH_AES_256_CBC_SHA256) - C(TLS_DHE_DSS_WITH_AES_256_CBC_SHA256) - C(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) - - /* Completely anonymous Diffie-Hellman */ - C(TLS_DH_anon_WITH_RC4_128_MD5) - C(TLS_DH_anon_WITH_3DES_EDE_CBC_SHA) - C(TLS_DH_anon_WITH_AES_128_CBC_SHA) - C(TLS_DH_anon_WITH_AES_256_CBC_SHA) - C(TLS_DH_anon_WITH_AES_128_CBC_SHA256) - C(TLS_DH_anon_WITH_AES_256_CBC_SHA256) - - /* Addenda from rfc 5288 AES Galois Counter Mode (GCM) Cipher Suites - for TLS. */ - C(TLS_RSA_WITH_AES_128_GCM_SHA256) - C(TLS_RSA_WITH_AES_256_GCM_SHA384) - C(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) - C(TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) - C(TLS_DH_RSA_WITH_AES_128_GCM_SHA256) - C(TLS_DH_RSA_WITH_AES_256_GCM_SHA384) - C(TLS_DHE_DSS_WITH_AES_128_GCM_SHA256) - C(TLS_DHE_DSS_WITH_AES_256_GCM_SHA384) - C(TLS_DH_DSS_WITH_AES_128_GCM_SHA256) - C(TLS_DH_DSS_WITH_AES_256_GCM_SHA384) - C(TLS_DH_anon_WITH_AES_128_GCM_SHA256) - C(TLS_DH_anon_WITH_AES_256_GCM_SHA384) - - /* ECDSA addenda, RFC 4492 */ - C(TLS_ECDH_ECDSA_WITH_NULL_SHA) - C(TLS_ECDH_ECDSA_WITH_RC4_128_SHA) - C(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA) - C(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA) - C(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA) - C(TLS_ECDHE_ECDSA_WITH_NULL_SHA) - C(TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) - C(TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA) - C(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) - C(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) - C(TLS_ECDH_RSA_WITH_NULL_SHA) - C(TLS_ECDH_RSA_WITH_RC4_128_SHA) - C(TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA) - C(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA) - C(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA) - C(TLS_ECDHE_RSA_WITH_NULL_SHA) - C(TLS_ECDHE_RSA_WITH_RC4_128_SHA) - C(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) - C(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) - C(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) - C(TLS_ECDH_anon_WITH_NULL_SHA) - C(TLS_ECDH_anon_WITH_RC4_128_SHA) - C(TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA) - C(TLS_ECDH_anon_WITH_AES_128_CBC_SHA) - C(TLS_ECDH_anon_WITH_AES_256_CBC_SHA) - - /* Addenda from rfc 5289 Elliptic Curve Cipher Suites with - HMAC SHA-256/384. */ - C(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) - C(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384) - C(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256) - C(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384) - C(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) - C(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) - C(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256) - C(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384) - - /* Addenda from rfc 5289 Elliptic Curve Cipher Suites with - SHA-256/384 and AES Galois Counter Mode (GCM) */ - C(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) - C(TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) - C(TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256) - C(TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384) - C(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) - C(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) - C(TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256) - C(TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384) - - /* RFC 5746 - Secure Renegotiation */ - C(TLS_EMPTY_RENEGOTIATION_INFO_SCSV) - - /* - * Tags for SSL 2 cipher kinds which are not specified - * for SSL 3. - */ - C(SSL_RSA_WITH_RC2_CBC_MD5) - C(SSL_RSA_WITH_IDEA_CBC_MD5) - C(SSL_RSA_WITH_DES_CBC_MD5) - C(SSL_RSA_WITH_3DES_EDE_CBC_MD5) - C(SSL_NO_SUCH_CIPHERSUITE) - - C(SSL_RSA_EXPORT_WITH_RC4_40_MD5) - C(SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5) - C(SSL_RSA_WITH_IDEA_CBC_SHA) - C(SSL_RSA_EXPORT_WITH_DES40_CBC_SHA) - C(SSL_RSA_WITH_DES_CBC_SHA) - C(SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA) - C(SSL_DH_DSS_WITH_DES_CBC_SHA) - C(SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA) - C(SSL_DH_RSA_WITH_DES_CBC_SHA) - C(SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA) - C(SSL_DHE_DSS_WITH_DES_CBC_SHA) - C(SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA) - C(SSL_DHE_RSA_WITH_DES_CBC_SHA) - C(SSL_DH_anon_EXPORT_WITH_RC4_40_MD5) - C(SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA) - C(SSL_DH_anon_WITH_DES_CBC_SHA) - C(SSL_FORTEZZA_DMS_WITH_NULL_SHA) - C(SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA) - - - default: - return "Unknown Ciphersuite"; - } - -} diff --git a/libsecurity_ssl/regressions/ssl-utils.h b/libsecurity_ssl/regressions/ssl-utils.h deleted file mode 100644 index cf9a9f3f..00000000 --- a/libsecurity_ssl/regressions/ssl-utils.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// ssl-utils.h -// libsecurity_ssl -// -// Created by Fabrice Gautier on 8/7/12. -// -// - -#ifndef __SSL_UTILS_H__ -#define __SSL_UTILS_H__ - -#include - -#define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) { CFRelease(_cf); } } -#define CFReleaseNull(CF) { CFTypeRef _cf = (CF); if (_cf) { (CF) = NULL; CFRelease(_cf); } } - -CFArrayRef server_chain(void); -CFArrayRef client_chain(void); - -const char *ciphersuite_name(SSLCipherSuite cs); - -#endif diff --git a/libsecurity_ssl/regressions/ssl_regressions.h b/libsecurity_ssl/regressions/ssl_regressions.h deleted file mode 100644 index 5595c093..00000000 --- a/libsecurity_ssl/regressions/ssl_regressions.h +++ /dev/null @@ -1,25 +0,0 @@ -#include - -DISABLED_ONE_TEST(ssl_39_echo) - -#if TARGET_OS_IPHONE - -ONE_TEST(ssl_40_clientauth) -ONE_TEST(ssl_41_clientauth) - -#else - -DISABLED_ONE_TEST(ssl_40_clientauth) -DISABLED_ONE_TEST(ssl_41_clientauth) - -#endif - -ONE_TEST(ssl_42_ciphers) - -OFF_ONE_TEST(ssl_43_ciphers) - -ONE_TEST(ssl_44_crashes) -ONE_TEST(ssl_45_tls12) -ONE_TEST(ssl_46_SSLGetSupportedCiphers) -ONE_TEST(ssl_47_falsestart) - diff --git a/libsecurity_ssl/sslViewer/fileIo.c b/libsecurity_ssl/sslViewer/fileIo.c deleted file mode 100644 index 204fdfe0..00000000 --- a/libsecurity_ssl/sslViewer/fileIo.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2001-2003,2006-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * fileIo.c - simple file read/write utilities - */ - -#include -#include -#include -#include -#include -#include -#include -#include "fileIo.h" - -int writeFile( - const char *fileName, - const unsigned char *bytes, - unsigned numBytes) -{ - int rtn; - int fd; - - fd = open(fileName, O_RDWR | O_CREAT | O_TRUNC, 0600); - if(fd < 0) { - return errno; - } - rtn = lseek(fd, 0, SEEK_SET); - if(rtn < 0) { - return errno; - } - rtn = write(fd, bytes, (size_t)numBytes); - if(rtn != (int)numBytes) { - if(rtn >= 0) { - printf("writeFile: short write\n"); - } - rtn = EIO; - } - else { - rtn = 0; - } - close(fd); - return rtn; -} - -/* - * Read entire file. - */ -int readFile( - const char *fileName, - unsigned char **bytes, // mallocd and returned - unsigned *numBytes) // returned -{ - int rtn; - int fd; - unsigned char *buf; - struct stat sb; - unsigned size; - - *numBytes = 0; - *bytes = NULL; - fd = open(fileName, O_RDONLY, 0); - if(fd < 0) { - return errno; - } - rtn = fstat(fd, &sb); - if(rtn) { - goto errOut; - } - size = sb.st_size; - buf = malloc(size); - if(buf == NULL) { - rtn = ENOMEM; - goto errOut; - } - rtn = lseek(fd, 0, SEEK_SET); - if(rtn < 0) { - goto errOut; - } - rtn = read(fd, buf, (size_t)size); - if(rtn != (int)size) { - if(rtn >= 0) { - printf("readFile: short read\n"); - } - rtn = EIO; - } - else { - rtn = 0; - *bytes = buf; - *numBytes = size; - } -errOut: - close(fd); - return rtn; -} diff --git a/libsecurity_ssl/sslViewer/fileIo.h b/libsecurity_ssl/sslViewer/fileIo.h deleted file mode 100644 index ae55dc3a..00000000 --- a/libsecurity_ssl/sslViewer/fileIo.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2001-2003,2006-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * fileIo.h - simple file read/write utilities - */ - -#ifdef __cplusplus -extern "C" { -#endif - -int readFile( - const char *fileName, - unsigned char **bytes, // mallocd and returned - unsigned *numBytes); // returned - -int writeFile( - const char *fileName, - const unsigned char *bytes, - unsigned numBytes); - -#ifdef __cplusplus -} -#endif diff --git a/libsecurity_ssl/sslViewer/ioSock.c b/libsecurity_ssl/sslViewer/ioSock.c deleted file mode 100644 index dbc18da1..00000000 --- a/libsecurity_ssl/sslViewer/ioSock.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright (c) 2006-2008,2010-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * ioSock.c - socket-based I/O routines for use with Secure Transport - */ - -#include "ioSock.h" -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* debugging for this module */ -#define SSL_OT_DEBUG 1 - -/* log errors to stdout */ -#define SSL_OT_ERRLOG 1 - -/* trace all low-level network I/O */ -#define SSL_OT_IO_TRACE 0 - -/* if SSL_OT_IO_TRACE, only log non-zero length transfers */ -#define SSL_OT_IO_TRACE_NZ 1 - -/* pause after each I/O (only meaningful if SSL_OT_IO_TRACE == 1) */ -#define SSL_OT_IO_PAUSE 0 - -/* print a stream of dots while I/O pending */ -#define SSL_OT_DOT 1 - -/* dump some bytes of each I/O (only meaningful if SSL_OT_IO_TRACE == 1) */ -#define SSL_OT_IO_DUMP 0 -#define SSL_OT_IO_DUMP_SIZE 256 - -/* indicate errSSLWouldBlock with a '.' */ -#define SSL_DISPL_WOULD_BLOCK 0 - -/* general, not-too-verbose debugging */ -#if SSL_OT_DEBUG -#define dprintf(s) printf s -#else -#define dprintf(s) -#endif - -/* errors --> stdout */ -#if SSL_OT_ERRLOG -#define eprintf(s) printf s -#else -#define eprintf(s) -#endif - -/* trace completion of every r/w */ -#if SSL_OT_IO_TRACE -static void tprintf( - const char *str, - UInt32 req, - UInt32 act, - const UInt8 *buf) -{ - #if SSL_OT_IO_TRACE_NZ - if(act == 0) { - return; - } - #endif - printf("%s(%u): moved (%u) bytes\n", str, (unsigned)req, (unsigned)act); - #if SSL_OT_IO_DUMP - { - unsigned i; - - for(i=0; i= (SSL_OT_IO_DUMP_SIZE - 1)) { - break; - } - } - printf("\n"); - } - #endif - #if SSL_OT_IO_PAUSE - { - char instr[20]; - printf("CR to continue: "); - gets(instr); - } - #endif -} - -#else -#define tprintf(str, req, act, buf) -#endif /* SSL_OT_IO_TRACE */ - -/* - * If SSL_OT_DOT, output a '.' every so often while waiting for - * connection. This gives user a chance to do something else with the - * UI. - */ - -#if SSL_OT_DOT - -static time_t lastTime = (time_t)0; -#define TIME_INTERVAL 3 - -static void outputDot() -{ - time_t thisTime = time(0); - - if((thisTime - lastTime) >= TIME_INTERVAL) { - printf("."); fflush(stdout); - lastTime = thisTime; - } -} -#else -#define outputDot() -#endif - - -/* - * One-time only init. - */ -void initSslOt(void) -{ - -} - -/* - * Connect to server. - */ -#define GETHOST_RETRIES 3 - -OSStatus MakeServerConnection( - const char *hostName, - int port, - int nonBlocking, // 0 or 1 - otSocket *socketNo, // RETURNED - PeerSpec *peer) // RETURNED -{ - struct sockaddr_in addr; - struct hostent *ent; - struct in_addr host; - int sock = 0; - - *socketNo = 0; - if (hostName[0] >= '0' && hostName[0] <= '9') - { - host.s_addr = inet_addr(hostName); - } - else { - unsigned dex; - /* seeing a lot of soft failures here that I really don't want to track down */ - for(dex=0; dexh_addr, sizeof(struct in_addr)); - } - sock = socket(AF_INET, SOCK_STREAM, 0); - addr.sin_addr = host; - addr.sin_port = htons((u_short)port); - - addr.sin_family = AF_INET; - if (connect(sock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) != 0) - { printf("connect returned error\n"); - return errSecIO; - } - - if(nonBlocking) { - /* OK to do this after connect? */ - int rtn = fcntl(sock, F_SETFL, O_NONBLOCK); - if(rtn == -1) { - perror("fctnl(O_NONBLOCK)"); - return errSecIO; - } - } - - peer->ipAddr = addr.sin_addr.s_addr; - peer->port = htons((u_short)port); - *socketNo = (otSocket)sock; - return errSecSuccess; -} - -/* - * Set up an otSocket to listen for client connections. Call once, then - * use multiple AcceptClientConnection calls. - */ -OSStatus ListenForClients( - int port, - int nonBlocking, // 0 or 1 - otSocket *socketNo) // RETURNED -{ - struct sockaddr_in addr; - struct hostent *ent; - int len; - int sock; - - sock = socket(AF_INET, SOCK_STREAM, 0); - if(sock < 1) { - perror("socket"); - return errSecIO; - } - - int reuse = 1; - int err = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); - if (err != 0) { - perror("setsockopt"); - return err; - } - - ent = gethostbyname("localhost"); - if (!ent) { - perror("gethostbyname"); - return errSecIO; - } - memcpy(&addr.sin_addr, ent->h_addr, sizeof(struct in_addr)); - - addr.sin_port = htons((u_short)port); - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_family = AF_INET; - len = sizeof(struct sockaddr_in); - if (bind(sock, (struct sockaddr *) &addr, len)) { - int theErr = errno; - perror("bind"); - if(theErr == EADDRINUSE) { - return errSecOpWr; - } - else { - return errSecIO; - } - } - if(nonBlocking) { - int rtn = fcntl(sock, F_SETFL, O_NONBLOCK); - if(rtn == -1) { - perror("fctnl(O_NONBLOCK)"); - return errSecIO; - } - } - - for(;;) { - int rtn = listen(sock, 1); - switch(rtn) { - case 0: - *socketNo = (otSocket)sock; - rtn = errSecSuccess; - break; - case EWOULDBLOCK: - continue; - default: - perror("listen"); - rtn = errSecIO; - break; - } - return rtn; - } - /* NOT REACHED */ - return 0; -} - -/* - * Accept a client connection. - */ - -/* - * Currently we always get back a different peer port number on successive - * connections, no matter what the client is doing. To test for resumable - * session support, force peer port = 0. - */ -#define FORCE_ACCEPT_PEER_PORT_ZERO 1 - -OSStatus AcceptClientConnection( - otSocket listenSock, // obtained from ListenForClients - otSocket *acceptSock, // RETURNED - PeerSpec *peer) // RETURNED -{ - struct sockaddr_in addr; - int sock; - socklen_t len; - - len = sizeof(struct sockaddr_in); - do { - sock = accept((int)listenSock, (struct sockaddr *) &addr, &len); - if (sock < 0) { - if(errno == EAGAIN) { - /* nonblocking, no connection yet */ - continue; - } - else { - perror("accept"); - return errSecIO; - } - } - else { - break; - } - } while(1); - *acceptSock = (otSocket)sock; - peer->ipAddr = addr.sin_addr.s_addr; - #if FORCE_ACCEPT_PEER_PORT_ZERO - peer->port = 0; - #else - peer->port = ntohs(addr.sin_port); - #endif - return errSecSuccess; -} - -/* - * Shut down a connection. - */ -void endpointShutdown( - otSocket sock) -{ - close((int)sock); -} - -/* - * R/W. Called out from SSL. - */ -OSStatus SocketRead( - SSLConnectionRef connection, - void *data, /* owned by - * caller, data - * RETURNED */ - size_t *dataLength) /* IN/OUT */ -{ - UInt32 bytesToGo = *dataLength; - UInt32 initLen = bytesToGo; - UInt8 *currData = (UInt8 *)data; - int sock = (int)((long)connection); - OSStatus rtn = errSecSuccess; - UInt32 bytesRead; - ssize_t rrtn; - - *dataLength = 0; - - for(;;) { - bytesRead = 0; - /* paranoid check, ensure errno is getting written */ - errno = -555; - rrtn = recv(sock, currData, bytesToGo, 0); - if (rrtn <= 0) { - if(rrtn == 0) { - /* closed, EOF */ - rtn = errSSLClosedGraceful; - break; - } - int theErr = errno; - switch(theErr) { - case ENOENT: - /* - * Undocumented but I definitely see this. - * Non-blocking sockets only. Definitely retriable - * just like an EAGAIN. - */ - dprintf(("SocketRead RETRYING on ENOENT, rrtn %d\n", - (int)rrtn)); - /* normal... */ - //rtn = errSSLWouldBlock; - /* ...for temp testing.... */ - rtn = errSecIO; - break; - case ECONNRESET: - /* explicit peer abort */ - rtn = errSSLClosedAbort; - break; - case EAGAIN: - /* nonblocking, no data */ - rtn = errSSLWouldBlock; - break; - default: - dprintf(("SocketRead: read(%u) error %d, rrtn %d\n", - (unsigned)bytesToGo, theErr, (int)rrtn)); - rtn = errSecIO; - break; - } - /* in any case, we're done with this call if rrtn <= 0 */ - break; - } - bytesRead = rrtn; - bytesToGo -= bytesRead; - currData += bytesRead; - - if(bytesToGo == 0) { - /* filled buffer with incoming data, done */ - break; - } - } - *dataLength = initLen - bytesToGo; - tprintf("SocketRead", initLen, *dataLength, (UInt8 *)data); - - #if SSL_OT_DOT || (SSL_OT_DEBUG && !SSL_OT_IO_TRACE) - if((rtn == 0) && (*dataLength == 0)) { - /* keep UI alive */ - outputDot(); - } - #endif - #if SSL_DISPL_WOULD_BLOCK - if(rtn == errSSLWouldBlock) { - printf("."); fflush(stdout); - } - #endif - return rtn; -} - -int oneAtATime = 0; - -OSStatus SocketWrite( - SSLConnectionRef connection, - const void *data, - size_t *dataLength) /* IN/OUT */ -{ - size_t bytesSent = 0; - int sock = (int)((long)connection); - int length; - size_t dataLen = *dataLength; - const UInt8 *dataPtr = (UInt8 *)data; - OSStatus ortn; - - if(oneAtATime && (*dataLength > 1)) { - size_t i; - size_t outLen; - size_t thisMove; - - outLen = 0; - for(i=0; i 0) && - ( (bytesSent += length) < dataLen) ); - - if(length <= 0) { - int theErr = errno; - switch(theErr) { - case EAGAIN: - ortn = errSSLWouldBlock; break; - case EPIPE: - ortn = errSSLClosedAbort; break; - default: - dprintf(("SocketWrite: write(%u) error %d\n", - (unsigned)(dataLen - bytesSent), theErr)); - ortn = errSecIO; - break; - } - } - else { - ortn = errSecSuccess; - } - tprintf("SocketWrite", dataLen, bytesSent, dataPtr); - *dataLength = bytesSent; - return ortn; -} diff --git a/libsecurity_ssl/sslViewer/ioSock.h b/libsecurity_ssl/sslViewer/ioSock.h deleted file mode 100644 index 11486790..00000000 --- a/libsecurity_ssl/sslViewer/ioSock.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2006-2008,2010-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * ioSock.h - socket-based I/O routines for use with Secure Transport - */ - -#ifndef _IO_SOCK_H_ -#define _IO_SOCK_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Opaque reference to an Open Transport connection. - */ -typedef int otSocket; - -/* - * info about a peer returned from MakeServerConnection() and - * AcceptClientConnection(). - */ -typedef struct -{ UInt32 ipAddr; - int port; -} PeerSpec; - -/* - * Ont-time only init. - */ -void initSslOt(void); - -/* - * Connect to server. - */ -extern OSStatus MakeServerConnection( - const char *hostName, - int port, - int nonBlocking, // 0 or 1 - otSocket *socketNo, // RETURNED - PeerSpec *peer); // RETURNED - -/* - * Set up an otSocket to listen for client connections. Call once, then - * use multiple AcceptClientConnection calls. - */ -OSStatus ListenForClients( - int port, - int nonBlocking, // 0 or 1 - otSocket *socketNo); // RETURNED - -/* - * Accept a client connection. Call endpointShutdown() for each successful; - * return from this function. - */ -OSStatus AcceptClientConnection( - otSocket listenSock, // obtained from ListenForClients - otSocket *acceptSock, // RETURNED - PeerSpec *peer); // RETURNED - -/* - * Shut down a connection. - */ -void endpointShutdown( - otSocket socket); - -/* - * R/W. Called out from SSL. - */ -OSStatus SocketRead( - SSLConnectionRef connection, - void *data, /* owned by - * caller, data - * RETURNED */ - size_t *dataLength); /* IN/OUT */ - -OSStatus SocketWrite( - SSLConnectionRef connection, - const void *data, - size_t *dataLength); /* IN/OUT */ - -#ifdef __cplusplus -} -#endif - -#endif /* _IO_SOCK_H_ */ diff --git a/libsecurity_ssl/sslViewer/sslAppUtils.cpp b/libsecurity_ssl/sslViewer/sslAppUtils.cpp deleted file mode 100644 index 7b12af62..00000000 --- a/libsecurity_ssl/sslViewer/sslAppUtils.cpp +++ /dev/null @@ -1,1647 +0,0 @@ -/* - * Copyright (c) 2006-2008,2010-2012 Apple Inc. All Rights Reserved. - */ - -#include "sslAppUtils.h" -#include "fileIo.h" -#include -#include -#include -#include - -#include -#include -#include -#include - -#define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) CFRelease(_cf); } - -const char *sslGetCipherSuiteString(SSLCipherSuite cs) -{ - static char noSuite[40]; - - switch (cs) { - /* TLS cipher suites, RFC 2246 */ - case SSL_NULL_WITH_NULL_NULL: return "TLS_NULL_WITH_NULL_NULL"; - case SSL_RSA_WITH_NULL_MD5: return "TLS_RSA_WITH_NULL_MD5"; - case SSL_RSA_WITH_NULL_SHA: return "TLS_RSA_WITH_NULL_SHA"; - case SSL_RSA_EXPORT_WITH_RC4_40_MD5: return "TLS_RSA_EXPORT_WITH_RC4_40_MD5"; - case SSL_RSA_WITH_RC4_128_MD5: return "TLS_RSA_WITH_RC4_128_MD5"; - case SSL_RSA_WITH_RC4_128_SHA: return "TLS_RSA_WITH_RC4_128_SHA"; - case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: return "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5"; - case SSL_RSA_WITH_IDEA_CBC_SHA: return "TLS_RSA_WITH_IDEA_CBC_SHA"; - case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: return "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA"; - case SSL_RSA_WITH_DES_CBC_SHA: return "TLS_RSA_WITH_DES_CBC_SHA"; - case SSL_RSA_WITH_3DES_EDE_CBC_SHA: return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; - case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: return "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"; - case SSL_DH_DSS_WITH_DES_CBC_SHA: return "TLS_DH_DSS_WITH_DES_CBC_SHA"; - case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA: return "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"; - case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: return "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"; - case SSL_DH_RSA_WITH_DES_CBC_SHA: return "TLS_DH_RSA_WITH_DES_CBC_SHA"; - case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA: return "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"; - case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: return "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"; - case SSL_DHE_DSS_WITH_DES_CBC_SHA: return "TLS_DHE_DSS_WITH_DES_CBC_SHA"; - case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA: return "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; - case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: return "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"; - case SSL_DHE_RSA_WITH_DES_CBC_SHA: return "TLS_DHE_RSA_WITH_DES_CBC_SHA"; - case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: return "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; - case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: return "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5"; - case SSL_DH_anon_WITH_RC4_128_MD5: return "TLS_DH_anon_WITH_RC4_128_MD5"; - case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: return "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA"; - case SSL_DH_anon_WITH_DES_CBC_SHA: return "TLS_DH_anon_WITH_DES_CBC_SHA"; - case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; - - /* SSLv3 Fortezza cipher suites, from NSS */ - case SSL_FORTEZZA_DMS_WITH_NULL_SHA: return "SSL_FORTEZZA_DMS_WITH_NULL_SHA"; - case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA:return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA"; - - /* TLS addenda using AES-CBC, RFC 3268 */ - case TLS_RSA_WITH_AES_128_CBC_SHA: return "TLS_RSA_WITH_AES_128_CBC_SHA"; - case TLS_DH_DSS_WITH_AES_128_CBC_SHA: return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; - case TLS_DH_RSA_WITH_AES_128_CBC_SHA: return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; - case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; - case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; - case TLS_DH_anon_WITH_AES_128_CBC_SHA: return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; - case TLS_RSA_WITH_AES_256_CBC_SHA: return "TLS_RSA_WITH_AES_256_CBC_SHA"; - case TLS_DH_DSS_WITH_AES_256_CBC_SHA: return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; - case TLS_DH_RSA_WITH_AES_256_CBC_SHA: return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; - case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; - case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; - case TLS_DH_anon_WITH_AES_256_CBC_SHA: return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; - - /* ECDSA addenda, RFC 4492 */ - case TLS_ECDH_ECDSA_WITH_NULL_SHA: return "TLS_ECDH_ECDSA_WITH_NULL_SHA"; - case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"; - case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"; - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"; - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"; - case TLS_ECDHE_ECDSA_WITH_NULL_SHA: return "TLS_ECDHE_ECDSA_WITH_NULL_SHA"; - case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"; - case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"; - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"; - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"; - case TLS_ECDH_RSA_WITH_NULL_SHA: return "TLS_ECDH_RSA_WITH_NULL_SHA"; - case TLS_ECDH_RSA_WITH_RC4_128_SHA: return "TLS_ECDH_RSA_WITH_RC4_128_SHA"; - case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"; - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"; - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"; - case TLS_ECDHE_RSA_WITH_NULL_SHA: return "TLS_ECDHE_RSA_WITH_NULL_SHA"; - case TLS_ECDHE_RSA_WITH_RC4_128_SHA: return "TLS_ECDHE_RSA_WITH_RC4_128_SHA"; - case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"; - case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"; - case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"; - case TLS_ECDH_anon_WITH_NULL_SHA: return "TLS_ECDH_anon_WITH_NULL_SHA"; - case TLS_ECDH_anon_WITH_RC4_128_SHA: return "TLS_ECDH_anon_WITH_RC4_128_SHA"; - case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA: return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"; - case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"; - case TLS_ECDH_anon_WITH_AES_256_CBC_SHA: return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"; - - /* TLS 1.2 addenda, RFC 5246 */ - case TLS_RSA_WITH_AES_128_CBC_SHA256: return "TLS_RSA_WITH_AES_128_CBC_SHA256"; - case TLS_RSA_WITH_AES_256_CBC_SHA256: return "TLS_RSA_WITH_AES_256_CBC_SHA256"; - case TLS_DH_DSS_WITH_AES_128_CBC_SHA256: return "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"; - case TLS_DH_RSA_WITH_AES_128_CBC_SHA256: return "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"; - case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"; - case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"; - case TLS_DH_DSS_WITH_AES_256_CBC_SHA256: return "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"; - case TLS_DH_RSA_WITH_AES_256_CBC_SHA256: return "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"; - case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"; - case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"; - case TLS_DH_anon_WITH_AES_128_CBC_SHA256: return "TLS_DH_anon_WITH_AES_128_CBC_SHA256"; - case TLS_DH_anon_WITH_AES_256_CBC_SHA256: return "TLS_DH_anon_WITH_AES_256_CBC_SHA256"; - - /* TLS addenda using AES-GCM, RFC 5288 */ - case TLS_RSA_WITH_AES_128_GCM_SHA256: return "TLS_RSA_WITH_AES_128_GCM_SHA256"; - case TLS_RSA_WITH_AES_256_GCM_SHA384: return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"; - case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"; - case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"; - case TLS_DH_RSA_WITH_AES_128_GCM_SHA256: return "TLS_DH_RSA_WITH_AES_128_GCM_SHA256"; - case TLS_DH_RSA_WITH_AES_256_GCM_SHA384: return "TLS_DH_RSA_WITH_AES_256_GCM_SHA384"; - case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: return "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"; - case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: return "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"; - case TLS_DH_DSS_WITH_AES_128_GCM_SHA256: return "TLS_DH_DSS_WITH_AES_128_GCM_SHA256"; - case TLS_DH_DSS_WITH_AES_256_GCM_SHA384: return "TLS_DH_DSS_WITH_AES_256_GCM_SHA384"; - case TLS_DH_anon_WITH_AES_128_GCM_SHA256: return "TLS_DH_anon_WITH_AES_128_GCM_SHA256"; - case TLS_DH_anon_WITH_AES_256_GCM_SHA384: return "TLS_DH_anon_WITH_AES_256_GCM_SHA384"; - - /* ECDSA addenda, RFC 5289 */ - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"; - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"; - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"; - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"; - case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"; - case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"; - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"; - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"; - case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"; - case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"; - case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"; - case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"; - case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"; - case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"; - case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"; - case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"; - - /* - * Tags for SSL 2 cipher kinds which are not specified for SSL 3. - */ - case SSL_RSA_WITH_RC2_CBC_MD5: return "TLS_RSA_WITH_RC2_CBC_MD5"; - case SSL_RSA_WITH_IDEA_CBC_MD5: return "TLS_RSA_WITH_IDEA_CBC_MD5"; - case SSL_RSA_WITH_DES_CBC_MD5: return "TLS_RSA_WITH_DES_CBC_MD5"; - case SSL_RSA_WITH_3DES_EDE_CBC_MD5: return "TLS_RSA_WITH_3DES_EDE_CBC_MD5"; - case SSL_NO_SUCH_CIPHERSUITE: return "SSL_NO_SUCH_CIPHERSUITE"; - - default: - sprintf(noSuite, "Unknown (0x%04X)", (unsigned)cs); - return noSuite; - } -} - -/* - * Given a SSLProtocolVersion - typically from SSLGetProtocolVersion - - * return a string representation. - */ -const char *sslGetProtocolVersionString(SSLProtocol prot) -{ - static char noProt[20]; - - switch(prot) { - case kSSLProtocolUnknown: return "kSSLProtocolUnknown"; - case kSSLProtocol2: return "kSSLProtocol2"; - case kSSLProtocol3: return "kSSLProtocol3"; - case kSSLProtocol3Only: return "kSSLProtocol3Only"; - case kTLSProtocol1: return "kTLSProtocol1"; - case kTLSProtocol1Only: return "kTLSProtocol1Only"; - case kTLSProtocol11: return "kTLSProtocol11"; - case kTLSProtocol12: return "kTLSProtocol12"; - default: - sprintf(noProt, "Unknown (%d)", (unsigned)prot); - return noProt; - } -} - -/* - * Return string representation of SecureTransport-related OSStatus. - */ -const char *sslGetSSLErrString(OSStatus err) -{ - static char errSecSuccessStr[20]; - - switch(err) { - case errSecSuccess: return "errSecSuccess"; - case errSecAllocate: return "errSecAllocate"; - case errSecParam: return "errSecParam"; - case errSecUnimplemented: return "errSecUnimplemented"; - case errSecIO: return "errSecIO"; - case errSecBadReq: return "errSecBadReq"; - /* SSL errors */ - case errSSLProtocol: return "errSSLProtocol"; - case errSSLNegotiation: return "errSSLNegotiation"; - case errSSLFatalAlert: return "errSSLFatalAlert"; - case errSSLWouldBlock: return "errSSLWouldBlock"; - case errSSLSessionNotFound: return "errSSLSessionNotFound"; - case errSSLClosedGraceful: return "errSSLClosedGraceful"; - case errSSLClosedAbort: return "errSSLClosedAbort"; - case errSSLXCertChainInvalid: return "errSSLXCertChainInvalid"; - case errSSLBadCert: return "errSSLBadCert"; - case errSSLCrypto: return "errSSLCrypto"; - case errSSLInternal: return "errSSLInternal"; - case errSSLModuleAttach: return "errSSLModuleAttach"; - case errSSLUnknownRootCert: return "errSSLUnknownRootCert"; - case errSSLNoRootCert: return "errSSLNoRootCert"; - case errSSLCertExpired: return "errSSLCertExpired"; - case errSSLCertNotYetValid: return "errSSLCertNotYetValid"; - case errSSLClosedNoNotify: return "errSSLClosedNoNotify"; - case errSSLBufferOverflow: return "errSSLBufferOverflow"; - case errSSLBadCipherSuite: return "errSSLBadCipherSuite"; - /* TLS/Panther addenda */ - case errSSLPeerUnexpectedMsg: return "errSSLPeerUnexpectedMsg"; - case errSSLPeerBadRecordMac: return "errSSLPeerBadRecordMac"; - case errSSLPeerDecryptionFail: return "errSSLPeerDecryptionFail"; - case errSSLPeerRecordOverflow: return "errSSLPeerRecordOverflow"; - case errSSLPeerDecompressFail: return "errSSLPeerDecompressFail"; - case errSSLPeerHandshakeFail: return "errSSLPeerHandshakeFail"; - case errSSLPeerBadCert: return "errSSLPeerBadCert"; - case errSSLPeerUnsupportedCert: return "errSSLPeerUnsupportedCert"; - case errSSLPeerCertRevoked: return "errSSLPeerCertRevoked"; - case errSSLPeerCertExpired: return "errSSLPeerCertExpired"; - case errSSLPeerCertUnknown: return "errSSLPeerCertUnknown"; - case errSSLIllegalParam: return "errSSLIllegalParam"; - case errSSLPeerUnknownCA: return "errSSLPeerUnknownCA"; - case errSSLPeerAccessDenied: return "errSSLPeerAccessDenied"; - case errSSLPeerDecodeError: return "errSSLPeerDecodeError"; - case errSSLPeerDecryptError: return "errSSLPeerDecryptError"; - case errSSLPeerExportRestriction: return "errSSLPeerExportRestriction"; - case errSSLPeerProtocolVersion: return "errSSLPeerProtocolVersion"; - case errSSLPeerInsufficientSecurity:return "errSSLPeerInsufficientSecurity"; - case errSSLPeerInternalError: return "errSSLPeerInternalError"; - case errSSLPeerUserCancelled: return "errSSLPeerUserCancelled"; - case errSSLPeerNoRenegotiation: return "errSSLPeerNoRenegotiation"; - case errSSLHostNameMismatch: return "errSSLHostNameMismatch"; - case errSSLConnectionRefused: return "errSSLConnectionRefused"; - case errSSLDecryptionFail: return "errSSLDecryptionFail"; - case errSSLBadRecordMac: return "errSSLBadRecordMac"; - case errSSLRecordOverflow: return "errSSLRecordOverflow"; - case errSSLBadConfiguration: return "errSSLBadConfiguration"; - - /* some from the Sec layer */ - case errSecNotAvailable: return "errSecNotAvailable"; - case errSecDuplicateItem: return "errSecDuplicateItem"; - case errSecItemNotFound: return "errSecItemNotFound"; -#if !TARGET_OS_IPHONE - case errSecReadOnly: return "errSecReadOnly"; - case errSecAuthFailed: return "errSecAuthFailed"; - case errSecNoSuchKeychain: return "errSecNoSuchKeychain"; - case errSecInvalidKeychain: return "errSecInvalidKeychain"; - case errSecNoSuchAttr: return "errSecNoSuchAttr"; - case errSecInvalidItemRef: return "errSecInvalidItemRef"; - case errSecInvalidSearchRef: return "errSecInvalidSearchRef"; - case errSecNoSuchClass: return "errSecNoSuchClass"; - case errSecNoDefaultKeychain: return "errSecNoDefaultKeychain"; - case errSecWrongSecVersion: return "errSecWrongSecVersion"; - case errSecInvalidTrustSettings: return "errSecInvalidTrustSettings"; - case errSecNoTrustSettings: return "errSecNoTrustSettings"; -#endif - default: -#if 0 - if (err < (CSSM_BASE_ERROR + - (CSSM_ERRORCODE_MODULE_EXTENT * 8))) - { - /* assume CSSM error */ - return cssmErrToStr(err); - } - else -#endif - { - sprintf(errSecSuccessStr, "Unknown (%d)", (unsigned)err); - return errSecSuccessStr; - } - } -} - -void printSslErrStr( - const char *op, - OSStatus err) -{ - printf("*** %s: %s\n", op, sslGetSSLErrString(err)); -} - -const char *sslGetClientCertStateString(SSLClientCertificateState state) -{ - static char noState[20]; - - switch(state) { - case kSSLClientCertNone: return "ClientCertNone"; - case kSSLClientCertRequested: return "CertRequested"; - case kSSLClientCertSent: return "ClientCertSent"; - case kSSLClientCertRejected: return "ClientCertRejected"; - default: - sprintf(noState, "Unknown (%d)", (unsigned)state); - return noState; - } - -} - -const char *sslGetClientAuthTypeString(SSLClientAuthenticationType authType) -{ - static char noType[20]; - - switch(authType) { - case SSLClientAuthNone: return "None"; - case SSLClientAuth_RSASign: return "RSASign"; - case SSLClientAuth_DSSSign: return "DSSSign"; - case SSLClientAuth_RSAFixedDH: return "RSAFixedDH"; - case SSLClientAuth_DSS_FixedDH: return "DSS_FixedDH"; - case SSLClientAuth_ECDSASign: return "ECDSASign"; - case SSLClientAuth_RSAFixedECDH: return "RSAFixedECDH"; - case SSLClientAuth_ECDSAFixedECDH: return "ECDSAFixedECDH"; - default: - sprintf(noType, "Unknown (%d)", (unsigned)authType); - return noType; - } -} - -/* - * Convert a keychain name (which may be NULL) into the CFArrayRef required - * by SSLSetCertificate. This is a bare-bones example of this operation, - * since it requires and assumes that there is exactly one SecIdentity - * in the keychain - i.e., there is exactly one matching cert/private key - * pair. A real world server would probably search a keychain for a SecIdentity - * matching some specific criteria. - */ -CFArrayRef getSslCerts( - const char *kcName, // may be NULL, i.e., use default - bool encryptOnly, - bool completeCertChain, - const char *anchorFile, // optional trusted anchor - SecKeychainRef *pKcRef) // RETURNED -{ -#if 0 - SecKeychainRef kcRef = nil; - OSStatus ortn; - - *pKcRef = nil; - - /* pick a keychain */ - if(kcName) { - ortn = SecKeychainOpen(kcName, &kcRef); - if(ortn) { - printf("SecKeychainOpen returned %d.\n", (int)ortn); - printf("Cannot open keychain at %s. Aborting.\n", kcName); - return NULL; - } - } - else { - /* use default keychain */ - ortn = SecKeychainCopyDefault(&kcRef); - if(ortn) { - printf("SecKeychainCopyDefault returned %d; aborting.\n", (int)ortn); - return nil; - } - } - *pKcRef = kcRef; - return sslKcRefToCertArray(kcRef, encryptOnly, completeCertChain, anchorFile); -#elif TARGET_OS_IOS - SecCertificateRef cert = NULL; - SecIdentityRef identity = NULL; - CFMutableArrayRef certificates = NULL, result = NULL; - CFMutableDictionaryRef certQuery = NULL, keyQuery = NULL, keyResult = NULL; - SecTrustRef trust = NULL; - SecKeyRef key = NULL; - CFTypeRef pkdigest = NULL; - - // Find the first private key in the keychain and return both its - // attributes and a ref to it. - require(keyQuery = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut); - CFDictionaryAddValue(keyQuery, kSecClass, kSecClassKey); - CFDictionaryAddValue(keyQuery, kSecAttrKeyClass, kSecAttrKeyClassPrivate); - CFDictionaryAddValue(keyQuery, kSecReturnRef, kCFBooleanTrue); - CFDictionaryAddValue(keyQuery, kSecReturnAttributes, kCFBooleanTrue); - require_noerr(SecItemCopyMatching(keyQuery, (CFTypeRef *)&keyResult), - errOut); - require(key = (SecKeyRef)CFDictionaryGetValue(keyResult, kSecValueRef), - errOut); - require(pkdigest = CFDictionaryGetValue(keyResult, kSecAttrApplicationLabel), - errOut); - - // Find the first certificate that has the same public key hash as the - // returned private key and return it as a ref. - require(certQuery = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut); - CFDictionaryAddValue(certQuery, kSecClass, kSecClassCertificate); - CFDictionaryAddValue(certQuery, kSecAttrPublicKeyHash, pkdigest); - CFDictionaryAddValue(certQuery, kSecReturnRef, kCFBooleanTrue); - require_noerr(SecItemCopyMatching(certQuery, (CFTypeRef *)&cert), errOut); - - // Create an identity from the key and certificate. - require(identity = SecIdentityCreate(NULL, cert, key), errOut); - - // Build a (partial) certificate chain from cert - require(certificates = CFArrayCreateMutable(NULL, 0, - &kCFTypeArrayCallBacks), errOut); - CFArrayAppendValue(certificates, cert); - require_noerr(SecTrustCreateWithCertificates(certificates, NULL, &trust), - errOut); - SecTrustResultType tresult; - require_noerr(SecTrustEvaluate(trust, &tresult), errOut); - - CFIndex certCount, ix; - // We need at least 1 certificate - require(certCount = SecTrustGetCertificateCount(trust), errOut); - - // Build a result where element 0 is the identity and the other elements - // are the certs in the chain starting at the first intermediate up to the - // anchor, if we found one, or as far as we were able to build the chain - // if not. - require(result = CFArrayCreateMutable(NULL, certCount, &kCFTypeArrayCallBacks), - errOut); - - // We are commited to returning a result now, so do not use require below - // this line without setting result to NULL again. - CFArrayAppendValue(result, identity); - for (ix = 1; ix < certCount; ++ix) { - CFArrayAppendValue(result, SecTrustGetCertificateAtIndex(trust, ix)); - } - -errOut: - CFReleaseSafe(trust); - CFReleaseSafe(certificates); - CFReleaseSafe(identity); - CFReleaseSafe(cert); - CFReleaseSafe(certQuery); - CFReleaseSafe(keyResult); - CFReleaseSafe(keyQuery); - - return result; - -#else /* !TARGET_OS_IOS */ - SecIdentityRef identity = NULL; - CFMutableDictionaryRef query = NULL; - CFArrayRef items = NULL; - require(query = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut); - CFDictionaryAddValue(query, kSecClass, kSecClassIdentity); - CFDictionaryAddValue(query, kSecReturnRef, kCFBooleanTrue); - require_noerr(SecItemCopyMatching(query, (CFTypeRef *)&identity), errOut); - - items = CFArrayCreate(kCFAllocatorDefault, - (const void **)&identity, 1, &kCFTypeArrayCallBacks); - -errOut: - CFReleaseSafe(identity); - CFReleaseSafe(query); - - return items; - -#endif - -} - -#if 0 -/* - * Determine if specified SecCertificateRef is a self-signed cert. - * We do this by comparing the subject and issuerr names; no cryptographic - * verification is performed. - * - * Returns true if the cert appears to be a root. - */ -static bool isCertRefRoot( - SecCertificateRef certRef) -{ - bool brtn = false; -#if 0 - /* just search for the two attrs we want */ - UInt32 tags[2] = {kSecSubjectItemAttr, kSecIssuerItemAttr}; - SecKeychainAttributeInfo attrInfo; - attrInfo.count = 2; - attrInfo.tag = tags; - attrInfo.format = NULL; - SecKeychainAttributeList *attrList = NULL; - SecKeychainAttribute *attr1 = NULL; - SecKeychainAttribute *attr2 = NULL; - - OSStatus ortn = SecKeychainItemCopyAttributesAndData( - (SecKeychainItemRef)certRef, - &attrInfo, - NULL, // itemClass - &attrList, - NULL, // length - don't need the data - NULL); // outData - if(ortn) { - cssmPerror("SecKeychainItemCopyAttributesAndData", ortn); - /* may want to be a bit more robust here, but this should - * never happen */ - return false; - } - /* subsequent errors to errOut: */ - - if((attrList == NULL) || (attrList->count != 2)) { - printf("***Unexpected result fetching label attr\n"); - goto errOut; - } - - /* rootness is just byte-for-byte compare of the two names */ - attr1 = &attrList->attr[0]; - attr2 = &attrList->attr[1]; - if(attr1->length == attr2->length) { - if(memcmp(attr1->data, attr2->data, attr1->length) == 0) { - brtn = true; - } - } -errOut: - SecKeychainItemFreeAttributesAndData(attrList, NULL); -#endif - return brtn; -} -#endif - -#if 0 -/* - * Given a SecIdentityRef, do our best to construct a complete, ordered, and - * verified cert chain, returning the result in a CFArrayRef. The result is - * suitable for use when calling SSLSetCertificate(). - */ -OSStatus sslCompleteCertChain( - SecIdentityRef identity, - SecCertificateRef trustedAnchor, // optional additional trusted anchor - bool includeRoot, // include the root in outArray - CFArrayRef *outArray) // created and RETURNED -{ - CFMutableArrayRef certArray; - SecTrustRef secTrust = NULL; - SecPolicyRef policy = NULL; - SecPolicySearchRef policySearch = NULL; - SecTrustResultType secTrustResult; - CSSM_TP_APPLE_EVIDENCE_INFO *dummyEv; // not used - CFArrayRef certChain = NULL; // constructed chain - CFIndex numResCerts; - - certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(certArray, identity); - - /* - * Case 1: identity is a root; we're done. Note that this case - * overrides the includeRoot argument. - */ - SecCertificateRef certRef; - OSStatus ortn = SecIdentityCopyCertificate(identity, &certRef); - if(ortn) { - /* should never happen */ - cssmPerror("SecIdentityCopyCertificate", ortn); - return ortn; - } - bool isRoot = isCertRefRoot(certRef); - if(isRoot) { - *outArray = certArray; - CFRelease(certRef); - return errSecSuccess; - } - - /* - * Now use SecTrust to get a complete cert chain, using all of the - * user's keychains to look for intermediate certs. - * NOTE this does NOT handle root certs which are not in the system - * root cert DB. (The above case, where the identity is a root cert, does.) - */ - CFMutableArrayRef subjCerts = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks); - CFArraySetValueAtIndex(subjCerts, 0, certRef); - - /* the array owns the subject cert ref now */ - CFRelease(certRef); - - /* Get a SecPolicyRef for generic X509 cert chain verification */ - ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3, - &CSSMOID_APPLE_X509_BASIC, - NULL, // value - &policySearch); - if(ortn) { - cssmPerror("SecPolicySearchCreate", ortn); - goto errOut; - } - ortn = SecPolicySearchCopyNext(policySearch, &policy); - if(ortn) { - cssmPerror("SecPolicySearchCopyNext", ortn); - goto errOut; - } - - /* build a SecTrustRef for specified policy and certs */ - ortn = SecTrustCreateWithCertificates(subjCerts, - policy, &secTrust); - if(ortn) { - cssmPerror("SecTrustCreateWithCertificates", ortn); - goto errOut; - } - - if(trustedAnchor) { - /* - * Tell SecTrust to trust this one in addition to the current - * trusted system-wide anchors. - */ - CFMutableArrayRef newAnchors; - CFArrayRef currAnchors; - - ortn = SecTrustCopyAnchorCertificates(&currAnchors); - if(ortn) { - /* should never happen */ - cssmPerror("SecTrustCopyAnchorCertificates", ortn); - goto errOut; - } - newAnchors = CFArrayCreateMutableCopy(NULL, - CFArrayGetCount(currAnchors) + 1, - currAnchors); - CFRelease(currAnchors); - CFArrayAppendValue(newAnchors, trustedAnchor); - ortn = SecTrustSetAnchorCertificates(secTrust, newAnchors); - CFRelease(newAnchors); - if(ortn) { - cssmPerror("SecTrustSetAnchorCertificates", ortn); - goto errOut; - } - } - /* evaluate: GO */ - ortn = SecTrustEvaluate(secTrust, &secTrustResult); - if(ortn) { - cssmPerror("SecTrustEvaluate", ortn); - goto errOut; - } - switch(secTrustResult) { - case kSecTrustResultUnspecified: - /* cert chain valid, no special UserTrust assignments */ - case kSecTrustResultProceed: - /* cert chain valid AND user explicitly trusts this */ - break; - default: - /* - * Cert chain construction failed. - * Just go with the single subject cert we were given. - */ - printf("***Warning: could not construct completed cert chain\n"); - ortn = errSecSuccess; - goto errOut; - } - - /* get resulting constructed cert chain */ - ortn = SecTrustGetResult(secTrust, &secTrustResult, &certChain, &dummyEv); - if(ortn) { - cssmPerror("SecTrustEvaluate", ortn); - goto errOut; - } - - /* - * Copy certs from constructed chain to our result array, skipping - * the leaf (which is already there, as a SecIdentityRef) and possibly - * a root. - */ - numResCerts = CFArrayGetCount(certChain); - if(numResCerts < 2) { - /* - * Can't happen: if subject was a root, we'd already have returned. - * If chain doesn't verify to a root, we'd have bailed after - * SecTrustEvaluate(). - */ - printf("***sslCompleteCertChain screwup: numResCerts %d\n", - (int)numResCerts); - ortn = errSecSuccess; - goto errOut; - } - if(!includeRoot) { - /* skip the last (root) cert) */ - numResCerts--; - } - for(CFIndex dex=1; dexacceptedProts) { - printf(" Allowed SSL versions : %s\n", params->acceptedProts); - } - else { - printf(" Attempted SSL version : %s\n", - sslGetProtocolVersionString(params->tryVersion)); - } - printf(" Result : %s\n", sslGetSSLErrString(params->ortn)); - printf(" Negotiated SSL version : %s\n", - sslGetProtocolVersionString(params->negVersion)); - printf(" Negotiated CipherSuite : %s\n", - sslGetCipherSuiteString(params->negCipher)); - if(params->certState != kSSLClientCertNone) { - printf(" Client Cert State : %s\n", - sslGetClientCertStateString(params->certState)); - } -} -#endif - -/* print a '.' every few seconds to keep UI alive while connecting */ -static CFAbsoluteTime lastTime = (CFAbsoluteTime)0.0; -#define TIME_INTERVAL 3.0 - -void sslOutputDot() -{ - CFAbsoluteTime thisTime = CFAbsoluteTimeGetCurrent(); - - if(lastTime == 0.0) { - /* avoid printing first time thru */ - lastTime = thisTime; - return; - } - if((thisTime - lastTime) >= TIME_INTERVAL) { - printf("."); fflush(stdout); - lastTime = thisTime; - } -} - -#if 0 -/* main server pthread body */ -static void *sslServerThread(void *arg) -{ - SslAppTestParams *testParams = (SslAppTestParams *)arg; - OSStatus status; - - status = sslAppServe(testParams); - pthread_exit((void*)status); - /* NOT REACHED */ - return (void *)status; -} - -/* - * Run one session, with the server in a separate thread. - * On entry, serverParams->port is the port we attempt to run on; - * the server thread may overwrite that with a different port if it's - * unable to open the port we specify. Whatever is left in - * serverParams->port is what's used for the client side. - */ -#define CLIENT_WAIT_SECONDS 1 -int sslRunSession( - SslAppTestParams*serverParams, - SslAppTestParams *clientParams, - const char *testDesc) -{ - pthread_t serverPthread; - OSStatus clientRtn; - void *serverRtn; - - if(testDesc && !clientParams->quiet) { - printf("===== %s =====\n", testDesc); - } - - if(pthread_mutex_init(&serverParams->pthreadMutex, NULL)) { - printf("***Error initializing mutex; aborting.\n"); - return -1; - } - if(pthread_cond_init(&serverParams->pthreadCond, NULL)) { - printf("***Error initializing pthreadCond; aborting.\n"); - return -1; - } - serverParams->serverReady = false; // server sets true - - int result = pthread_create(&serverPthread, NULL, - sslServerThread, serverParams); - if(result) { - printf("***Error starting up server thread; aborting.\n"); - return result; - } - - /* wait for server to set up a socket we can connect to */ - if(pthread_mutex_lock(&serverParams->pthreadMutex)) { - printf("***Error acquiring server lock; aborting.\n"); - return -1; - } - while(!serverParams->serverReady) { - if(pthread_cond_wait(&serverParams->pthreadCond, &serverParams->pthreadMutex)) { - printf("***Error waiting server thread; aborting.\n"); - return -1; - } - } - pthread_mutex_unlock(&serverParams->pthreadMutex); - pthread_cond_destroy(&serverParams->pthreadCond); - pthread_mutex_destroy(&serverParams->pthreadMutex); - - clientParams->port = serverParams->port; - clientRtn = sslAppClient(clientParams); - /* server doesn't shut down its socket until it sees this */ - serverParams->clientDone = 1; - result = pthread_join(serverPthread, &serverRtn); - if(result) { - printf("***pthread_join returned %d, aborting\n", result); - return result; - } - - if(serverParams->verbose) { - sslShowResult("server", serverParams); - } - if(clientParams->verbose) { - sslShowResult("client", clientParams); - } - - /* verify results */ - int ourRtn = 0; - ourRtn += sslVerifyRtn("server", serverParams->expectRtn, serverParams->ortn); - ourRtn += sslVerifyRtn("client", clientParams->expectRtn, clientParams->ortn); - ourRtn += sslVerifyProtVers("server", serverParams->expectVersion, - serverParams->negVersion); - ourRtn += sslVerifyProtVers("client", clientParams->expectVersion, - clientParams->negVersion); - ourRtn += sslVerifyClientCertState("server", serverParams->expectCertState, - serverParams->certState); - ourRtn += sslVerifyClientCertState("client", clientParams->expectCertState, - clientParams->certState); - if(serverParams->ortn == errSecSuccess) { - ourRtn += sslVerifyCipher("server", serverParams->expectCipher, - serverParams->negCipher); - } - if(clientParams->ortn == errSecSuccess) { - ourRtn += sslVerifyCipher("client", clientParams->expectCipher, - clientParams->negCipher); - } - return ourRtn; -} - -/* - * Add all of the roots in a given KC to SSL ctx's trusted anchors. - */ -OSStatus sslAddTrustedRoots( - SSLContextRef ctx, - SecKeychainRef keychain, - bool *foundOne) // RETURNED, true if we found - // at least one root cert -{ - OSStatus ortn; - SecCertificateRef secCert; - SecKeychainSearchRef srch; - - *foundOne = false; - ortn = SecKeychainSearchCreateFromAttributes(keychain, - kSecCertificateItemClass, - NULL, // any attrs - &srch); - if(ortn) { - printSslErrStr("SecKeychainSearchCreateFromAttributes", ortn); - return ortn; - } - - /* - * Only use root certs. Not an error if we don't find any. - */ - do { - ortn = SecKeychainSearchCopyNext(srch, - (SecKeychainItemRef *)&secCert); - if(ortn) { - break; - } - - /* see if it's a root */ - if(!isCertRoot(secCert)) { - continue; - } - - /* Tell Secure Transport to trust this one. */ - ortn = addTrustedSecCert(ctx, secCert, false); - if(ortn) { - /* fatal */ - printSslErrStr("addTrustedSecCert", ortn); - return ortn; - } - CFRelease(secCert); - *foundOne = true; - } while(ortn == errSecSuccess); - CFRelease(srch); - return errSecSuccess; -} - -/* - * Wrapper for sslIdentPicker, with optional trusted anchor specified as a filename. - */ -OSStatus sslIdentityPicker( - SecKeychainRef kcRef, // NULL means use default list - const char *trustedAnchor, // optional additional trusted anchor - bool includeRoot, // true --> root is appended to outArray - // false --> root not included - CFArrayRef *outArray) // created and RETURNED -{ - SecCertificateRef trustedCert = NULL; - OSStatus ortn; - - if(trustedAnchor) { - ortn = sslReadAnchor(trustedAnchor, &trustedCert); - if(ortn) { - printf("***Error reading %s. sslIdentityPicker proceeding with no anchor.\n", - trustedAnchor); - trustedCert = NULL; - } - } - ortn = sslIdentPicker(kcRef, trustedCert, includeRoot, outArray); - if(trustedCert) { - CFRelease(trustedCert); - } - return ortn; -} - -/* - * Given a keychain name, convert it into a full path using the "SSL regression - * test suite algorithm". The Sec layer by default locates root root's keychains - * in different places depending on whether we're actually logged in as root - * or running via e.g. cron, so we force the location of root keychains to - * a hard-coded path. User keychain names we leave alone. - */ -void sslKeychainPath( - const char *kcName, - char *kcPath) // allocd by caller, MAXPATHLEN -{ - if(kcName[0] == '\0') { - kcPath[0] = '\0'; - } - else if(geteuid() == 0) { - /* root */ - sprintf(kcPath, "/Library/Keychains/%s", kcName); - } - else { - /* user, leave alone */ - strcpy(kcPath, kcName); - } -} - -/* Verify presence of required file. Returns nonzero if not found. */ -int sslCheckFile(const char *path) -{ - struct stat sb; - - if(stat(path, &sb)) { - printf("***Can't find file %s.\n", path); - printf(" Try running in the build directory, perhaps after running the\n" - " makeLocalCert script.\n"); - return 1; - } - return 0; -} - -#endif - -/* Stringify a SSL_ECDSA_NamedCurve */ -extern const char *sslCurveString( - SSL_ECDSA_NamedCurve namedCurve) -{ - static char unk[100]; - - switch(namedCurve) { - case SSL_Curve_None: return "Curve_None"; - case SSL_Curve_secp256r1: return "secp256r1"; - case SSL_Curve_secp384r1: return "secp384r1"; - case SSL_Curve_secp521r1: return "secp521r1"; - default: - sprintf(unk, "Unknown <%d>", (int)namedCurve); - return unk; - } -} diff --git a/libsecurity_ssl/sslViewer/sslAppUtils.h b/libsecurity_ssl/sslViewer/sslAppUtils.h deleted file mode 100644 index b5f414f7..00000000 --- a/libsecurity_ssl/sslViewer/sslAppUtils.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2006-2008,2010-2012 Apple Inc. All Rights Reserved. - */ - -#ifndef _SSLS_APP_UTILS_H_ -#define _SSLS_APP_UTILS_H_ 1 - -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct OpaqueSecKeychainRef *SecKeychainRef; - -const char *sslGetCipherSuiteString(SSLCipherSuite cs); -const char *sslGetProtocolVersionString(SSLProtocol prot); -const char *sslGetSSLErrString(OSStatus err); -void printSslErrStr(const char *op, OSStatus err); -const char *sslGetClientCertStateString(SSLClientCertificateState state); -const char *sslGetClientAuthTypeString(SSLClientAuthenticationType authType); - -CFArrayRef getSslCerts( - const char *kcName, // may be NULL, i.e., use default - bool encryptOnly, - bool completeCertChain, - const char *anchorFile, // optional trusted anchor - SecKeychainRef *pKcRef); // RETURNED -OSStatus sslCompleteCertChain( - SecIdentityRef identity, - SecCertificateRef trustedAnchor, // optional additional trusted anchor - bool includeRoot, // include the root in outArray -// const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL - CFArrayRef *outArray); // created and RETURNED -CFArrayRef sslKcRefToCertArray( - SecKeychainRef kcRef, - bool encryptOnly, - bool completeCertChain, -// const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL policy to complete - const char *trustedAnchorFile); - -OSStatus addTrustedSecCert( - SSLContextRef ctx, - SecCertificateRef secCert, - bool replaceAnchors); -OSStatus sslReadAnchor( - const char *anchorFile, - SecCertificateRef *certRef); -OSStatus sslAddTrustedRoot( - SSLContextRef ctx, - const char *anchorFile, - bool replaceAnchors); - -/* - * Assume incoming identity contains a root (e.g., created by - * certtool) and add that cert to ST's trusted anchors. This - * enables ST's verify of the incoming chain to succeed without - * a kludgy "AllowAnyRoot" specification. - */ -OSStatus addIdentityAsTrustedRoot( - SSLContextRef ctx, - CFArrayRef identArray); - -OSStatus sslAddTrustedRoots( - SSLContextRef ctx, - SecKeychainRef keychain, - bool *foundOne); - -void sslOutputDot(); - -/* - * Lists of SSLCipherSuites used in sslSetCipherRestrictions. - */ -extern const SSLCipherSuite suites40[]; -extern const SSLCipherSuite suitesDES[]; -extern const SSLCipherSuite suitesDES40[]; -extern const SSLCipherSuite suites3DES[]; -extern const SSLCipherSuite suitesRC4[]; -extern const SSLCipherSuite suitesRC4_40[]; -extern const SSLCipherSuite suitesRC2[]; -extern const SSLCipherSuite suitesAES128[]; -extern const SSLCipherSuite suitesAES256[]; -extern const SSLCipherSuite suitesDH[]; -extern const SSLCipherSuite suitesDHAnon[]; -extern const SSLCipherSuite suitesDH_RSA[]; -extern const SSLCipherSuite suitesDH_DSS[]; -extern const SSLCipherSuite suites_SHA1[]; -extern const SSLCipherSuite suites_MD5[]; -extern const SSLCipherSuite suites_ECDHE[]; -extern const SSLCipherSuite suites_ECDH[]; - -/* - * Given an SSLContextRef and an array of SSLCipherSuites, terminated by - * SSL_NO_SUCH_CIPHERSUITE, select those SSLCipherSuites which the library - * supports and do a SSLSetEnabledCiphers() specifying those. - */ -OSStatus sslSetEnabledCiphers( - SSLContextRef ctx, - const SSLCipherSuite *ciphers); - -/* - * Specify restricted sets of cipherspecs and protocols. - */ -OSStatus sslSetCipherRestrictions( - SSLContextRef ctx, - char cipherRestrict); - -#ifndef SPHINX -OSStatus sslSetProtocols( - SSLContextRef ctx, - const char *acceptedProts, - SSLProtocol tryVersion); // only used if acceptedProts NULL -#endif - -int sslVerifyRtn( - const char *whichSide, // "client" or "server" - OSStatus expectRtn, - OSStatus gotRtn); -int sslVerifyProtVers( - const char *whichSide, // "client" or "server" - SSLProtocol expectProt, - SSLProtocol gotProt); -int sslVerifyClientCertState( - const char *whichSide, // "client" or "server" - SSLClientCertificateState expectState, - SSLClientCertificateState gotState); -int sslVerifyCipher( - const char *whichSide, // "client" or "server" - SSLCipherSuite expectCipher, - SSLCipherSuite gotCipher); - - -/* - * Wrapper for sslIdentPicker, with optional trusted anchor specified as a filename. - */ -OSStatus sslIdentityPicker( - SecKeychainRef kcRef, // NULL means use default list - const char *trustedAnchor, // optional additional trusted anchor - bool includeRoot, // true --> root is appended to outArray - // false --> root not included -// const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL - CFArrayRef *outArray); // created and RETURNED - -void sslKeychainPath( - const char *kcName, - char *kcPath); // allocd by caller, MAXPATHLEN - -/* Verify presence of required file. Returns nonzero if not found. */ -int sslCheckFile(const char *path); - -/* Stringify a SSL_ECDSA_NamedCurve */ -extern const char *sslCurveString( - SSL_ECDSA_NamedCurve namedCurve); - -#ifdef __cplusplus -} -#endif - -#endif /* _SSLS_APP_UTILS_H_ */ diff --git a/libsecurity_ssl/sslViewer/sslServer.cpp b/libsecurity_ssl/sslViewer/sslServer.cpp deleted file mode 100644 index 0fc0d541..00000000 --- a/libsecurity_ssl/sslViewer/sslServer.cpp +++ /dev/null @@ -1,1062 +0,0 @@ -/* - * Copyright (c) 2008-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * Trivial SSL server example, using SecureTransport / OS X version. - * - * Written by Doug Mitchell. - */ - -#include -#include -#include "sslAppUtils.h" -#include "ioSock.h" -#include "fileIo.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include "printCert.h" - -#if NO_SERVER -#include -#endif - -/* Set true when PR-3074739 is merged to TOT */ -#define SET_DH_PARAMS_ENABLE 1 - -/* true when using SSLCopyPeerCertificates() per Radar 3311892 */ -#define USE_COPY_PEER_CERTS 1 - -/* - * Defaults, overridable by user. - */ -#define SERVER_MESSAGE "HTTP/1.0 200 OK\015\012Content-Type: text/html\015\012\015\012" \ - "SecureTransport Test Server" \ - "

    Secure connection established.

    " \ - "Message from the 'sslServer' sample application.\015\012" \ - "\015\012" - -/* For ease of debugging, pick a non-privileged port */ -#define DEFAULT_PORT 1200 -// #define DEFAULT_PORT 443 - -#define DEFAULT_HOST "localhost" - -#define DEFAULT_KC "certkc" - -static void usage(char **argv) -{ - printf("Usage: %s [option ...]\n", argv[0]); - printf("Options:\n"); - printf(" P=port Port to listen on; default is %d\n", DEFAULT_PORT); - printf(" k=keychain Contains server cert and keys.\n"); - printf(" y=keychain Encryption-only cert and keys.\n"); - printf(" e Allow Expired Certs\n"); - printf(" r Allow any root cert\n"); - printf(" E Allow Expired Roots\n"); - printf(" x Disable Cert Verification\n"); - printf(" f=fileBase Write Peer Certs to fileBase*\n"); - printf(" c Display peer certs\n"); - printf(" d Display received data\n"); - printf(" C=cipherSuite (e=40-bit d=DES D=40-bit DES 3=3DES 4=RC4 $=40-bit RC4\n" - " 2=RC2 a=AES128 A=AES256 h=DH H=Anon DH r=DHE/RSA s=DH/DSS\n" - " n=RSA/NULL\n"); - printf(" 2 SSLv2 only (default is best fit)\n"); - printf(" 3 SSLv3 only (default is best fit)\n"); - printf(" t TLSv1 only (default is best fit)\n"); - printf(" o TLSv1, SSLv3 use kSSLProtocol__X__Only\n"); - printf(" g={prot...} Specify legal protocols; prot = any combo of [23t]\n"); - printf(" T=[nrsj] Verify client cert state = " - "none/requested/sent/rejected\n"); - printf(" R Disable resumable session support\n"); - printf(" i=timeout Session cache timeout\n"); - printf(" u=[nat] Authentication: n=never; a=always; t=try\n"); - printf(" b Non-blocking I/O\n"); - printf(" a fileNmae Add fileName to list of trusted roots\n"); - printf(" A fileName fileName is ONLY trusted root\n"); - printf(" U filename Add filename to acceptable DNList (multiple times OK)\n"); - printf(" D filename Diffie-Hellman parameters from filename\n"); - printf(" z=password Unlock server keychain with password.\n"); - printf(" H Do SecIdentityRef search instead of specific keychain\n"); - printf(" M Complete cert chain (default assumes that our identity is root)\n"); - printf(" 4 Disable anonymous ciphers\n"); - printf(" p Pause after each phase\n"); - printf(" l[=loops] Loop, performing multiple transactions\n"); - printf(" q Quiet/diagnostic mode (site names and errors only)\n"); - printf(" h Help\n"); - exit(1); -} - -/* snag a copy of current connection's peer certs so we can - * examine them later after the connection is closed */ -static OSStatus copyPeerCerts( - SSLContext *ctx, - CFArrayRef *peerCerts) // mallocd & RETURNED -{ - #if USE_COPY_PEER_CERTS - OSStatus ortn = SSLCopyPeerCertificates(ctx, peerCerts); - #else - OSStatus ortn = SSLGetPeerCertificates(ctx, peerCerts); - #endif - if(ortn) { - printf("***Error obtaining peer certs: %s\n", - sslGetSSLErrString(ortn)); - } - return ortn; -} - -/* free the cert array obtained via SSLGetPeerCertificates() */ -static void freePeerCerts( - CFArrayRef peerCerts) -{ - if(peerCerts == NULL) { - return; - } - - #if USE_COPY_PEER_CERTS - - /* Voila! Problem fixed. */ - CFRelease(peerCerts); - return; - - #else - - CFIndex numCerts; - SecCertificateRef certData; - CFIndex i; - - numCerts = CFArrayGetCount(peerCerts); - for(i=0; i", ((unsigned)c) & 0xff); - } - break; - } - - } - printf("\n"); -} - -static void doPause(const char *prompt) { - if(prompt) { - printf("%s. ", prompt); - } - fpurge(stdin); - printf("Continue (n/anything)? "); - char c = getchar(); - if(c == 'n') { - exit(0); - } -} - -/* - * Perform one SSL diagnostic server-side session. Returns nonzero on error. - * Normally no output to stdout except initial "waiting for connection" message, - * unless there is a really screwed up error (i.e., something not directly related - * to the SSL connection). - */ -#define RCV_BUF_SIZE 256 - -static OSStatus sslServe( - otSocket listenSock, - unsigned short portNum, - SSLProtocol tryVersion, // only used if acceptedProts NULL - const char *acceptedProts, - CFArrayRef serverCerts, // required - char *password, // optional - CFArrayRef encryptServerCerts, // optional - bool allowExpired, - bool allowAnyRoot, - bool allowExpiredRoot, - bool disableCertVerify, - char *anchorFile, - bool replaceAnchors, - char cipherRestrict, // '2', 'd'. etc...'\0' for no - // restriction - SSLAuthenticate authenticate, - unsigned char *dhParams, // optional D-H parameters - unsigned dhParamsLen, - CFArrayRef acceptableDNList, // optional - bool resumableEnable, - uint32_t sessionCacheTimeout,// optional - bool disableAnonCiphers, - bool silent, // no stdout - bool pause, - SSLProtocol *negVersion, // RETURNED - SSLCipherSuite *negCipher, // RETURNED - SSLClientCertificateState *certState, // RETURNED - Boolean *sessionWasResumed, // RETURNED - unsigned char *sessionID, // mallocd by caller, RETURNED - size_t *sessionIDLength, // RETURNED - CFArrayRef *peerCerts, // mallocd & RETURNED - char **argv) -{ - otSocket acceptSock; - PeerSpec peerId; - OSStatus ortn; - SSLContextRef ctx = NULL; - size_t length; - uint8_t rcvBuf[RCV_BUF_SIZE]; - const char *outMsg = SERVER_MESSAGE; - - *negVersion = kSSLProtocolUnknown; - *negCipher = SSL_NULL_WITH_NULL_NULL; - *peerCerts = NULL; - - #if IGNORE_SIGPIPE - signal(SIGPIPE, sigpipe); - #endif - - /* first wait for a connection */ - if(!silent) { - printf("Waiting for client connection on port %u...", portNum); - fflush(stdout); - } - ortn = AcceptClientConnection(listenSock, &acceptSock, &peerId); - if(ortn) { - printf("AcceptClientConnection returned %d; aborting\n", (int)ortn); - return ortn; - } - - /* - * Set up a SecureTransport session. - * First the standard calls. - */ - ortn = SSLNewContext(true, &ctx); - if(ortn) { - printSslErrStr("SSLNewContext", ortn); - goto cleanup; - } - ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite); - if(ortn) { - printSslErrStr("SSLSetIOFuncs", ortn); - goto cleanup; - } - ortn = SSLSetConnection(ctx, (SSLConnectionRef)acceptSock); - if(ortn) { - printSslErrStr("SSLSetConnection", ortn); - goto cleanup; - } - - /* have to do these options befor setting server certs */ - if(allowExpired) { - ortn = SSLSetAllowsExpiredCerts(ctx, true); - if(ortn) { - printSslErrStr("SSLSetAllowExpiredCerts", ortn); - goto cleanup; - } - } - if(allowAnyRoot) { - ortn = SSLSetAllowsAnyRoot(ctx, true); - if(ortn) { - printSslErrStr("SSLSetAllowAnyRoot", ortn); - goto cleanup; - } - } - - if(anchorFile) { - ortn = sslAddTrustedRoot(ctx, anchorFile, replaceAnchors); - if(ortn) { - printf("***Error obtaining anchor file %s\n", anchorFile); - goto cleanup; - } - } - if(serverCerts != NULL) { - if(anchorFile == NULL) { - /* no specific anchors, so assume we want to trust this one */ - ortn = addIdentityAsTrustedRoot(ctx, serverCerts); - if(ortn) { - goto cleanup; - } - } - ortn = SSLSetCertificate(ctx, serverCerts); - if(ortn) { - printSslErrStr("SSLSetCertificate", ortn); - goto cleanup; - } - } - if(encryptServerCerts) { - ortn = SSLSetEncryptionCertificate(ctx, encryptServerCerts); - if(ortn) { - printSslErrStr("SSLSetEncryptionCertificate", ortn); - goto cleanup; - } - } - if(allowExpiredRoot) { - ortn = SSLSetAllowsExpiredRoots(ctx, true); - if(ortn) { - printSslErrStr("SSLSetAllowsExpiredRoots", ortn); - goto cleanup; - } - } - if(disableCertVerify) { - ortn = SSLSetEnableCertVerify(ctx, false); - if(ortn) { - printSslErrStr("SSLSetEnableCertVerify", ortn); - goto cleanup; - } - } - - /* - * SecureTransport options. - */ - if(acceptedProts) { - ortn = SSLSetProtocolVersionEnabled(ctx, kSSLProtocolAll, false); - if(ortn) { - printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn); - goto cleanup; - } - for(const char *cp = acceptedProts; *cp; cp++) { - SSLProtocol prot = kSSLProtocolUnknown; - switch(*cp) { - case '2': - prot = kSSLProtocol2; - break; - case '3': - prot = kSSLProtocol3; - break; - case 't': - prot = kTLSProtocol1; - break; - default: - usage(argv); - } - ortn = SSLSetProtocolVersionEnabled(ctx, prot, true); - if(ortn) { - printSslErrStr("SSLSetProtocolVersionEnabled", ortn); - goto cleanup; - } - } - } - else { - ortn = SSLSetProtocolVersion(ctx, tryVersion); - if(ortn) { - printSslErrStr("SSLSetProtocolVersion", ortn); - goto cleanup; - } - } - if(resumableEnable) { - ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec)); - if(ortn) { - printSslErrStr("SSLSetPeerID", ortn); - goto cleanup; - } - } - if(cipherRestrict != '\0') { - ortn = sslSetCipherRestrictions(ctx, cipherRestrict); - if(ortn) { - goto cleanup; - } - } - if(authenticate != kNeverAuthenticate) { - ortn = SSLSetClientSideAuthenticate(ctx, authenticate); - if(ortn) { - printSslErrStr("SSLSetClientSideAuthenticate", ortn); - goto cleanup; - } - } - if(dhParams) { - ortn = SSLSetDiffieHellmanParams(ctx, dhParams, dhParamsLen); - if(ortn) { - printSslErrStr("SSLSetDiffieHellmanParams", ortn); - goto cleanup; - } - } - if(sessionCacheTimeout) { - ortn = SSLSetSessionCacheTimeout(ctx, sessionCacheTimeout); - if(ortn) { - printSslErrStr("SSLSetSessionCacheTimeout", ortn); - goto cleanup; - } - } - if(disableAnonCiphers) { - ortn = SSLSetAllowAnonymousCiphers(ctx, false); - if(ortn) { - printSslErrStr("SSLSetAllowAnonymousCiphers", ortn); - goto cleanup; - } - /* quickie test of the getter */ - Boolean e; - ortn = SSLGetAllowAnonymousCiphers(ctx, &e); - if(ortn) { - printSslErrStr("SSLGetAllowAnonymousCiphers", ortn); - goto cleanup; - } - if(e) { - printf("***SSLGetAllowAnonymousCiphers() returned true; expected false\n"); - ortn = errSecIO; - goto cleanup; - } - } -/* XXX/cs - if(acceptableDNList) { - ortn = SSLSetCertificateAuthorities(ctx, acceptableDNList, TRUE); - if(ortn) { - printSslErrStr("SSLSetCertificateAuthorities", ortn); - goto cleanup; - } - } -*/ - /* end options */ - - if(pause) { - doPause("SSLContext initialized"); - } - - /* Perform SSL/TLS handshake */ - do - { ortn = SSLHandshake(ctx); - if((ortn == errSSLWouldBlock) && !silent) { - /* keep UI responsive */ - sslOutputDot(); - } - } while (ortn == errSSLWouldBlock); - - /* this works even if handshake failed due to cert chain invalid */ - copyPeerCerts(ctx, peerCerts); - - SSLGetClientCertificateState(ctx, certState); - SSLGetNegotiatedCipher(ctx, negCipher); - SSLGetNegotiatedProtocolVersion(ctx, negVersion); - *sessionIDLength = MAX_SESSION_ID_LENGTH; - SSLGetResumableSessionInfo(ctx, sessionWasResumed, sessionID, - sessionIDLength); - - if(!silent) { - printf("\n"); - } - if(ortn) { - goto cleanup; - } - if(pause) { - doPause("SSLContext handshake complete"); - } - - /* wait for one complete line or user says they've had enough */ - while(ortn == errSecSuccess) { - length = sizeof(rcvBuf); - ortn = SSLRead(ctx, rcvBuf, length, &length); - if(length == 0) { - /* keep UI responsive */ - sslOutputDot(); - } - else { - /* print what we have */ - printf("client request: "); - dumpAscii(rcvBuf, length); - } - if(pause) { - /* allow user to bail */ - char resp; - - fpurge(stdin); - printf("\nMore client request (y/anything): "); - resp = getchar(); - if(resp != 'y') { - break; - } - } - - /* poor person's line completion scan */ - for(unsigned i=0; i SSLSetProtocolVersionEnabled - bool quiet = false; - bool resumableEnable = true; - bool pause = false; - char *keyChainName = NULL; - char *encryptKeyChainName = NULL; - int loops = 1; - SSLAuthenticate authenticate = kNeverAuthenticate; - bool nonBlocking = false; - bool allowExpiredRoot = false; - bool disableCertVerify = false; - char *anchorFile = NULL; - bool replaceAnchors = false; - bool vfyCertState = false; - SSLClientCertificateState expectCertState = kSSLClientCertNone; - char *password = NULL; - char *dhParamsFile = NULL; - unsigned char *dhParams = NULL; - unsigned dhParamsLen = 0; - bool doIdSearch = false; - bool completeCertChain = false; - uint32_t sessionCacheTimeout = 0; - bool disableAnonCiphers = false; - CFMutableArrayRef acceptableDNList = NULL; - - for(arg=1; arg loop forever */ - loops = 0; - break; - } - else if(argp[1] != '=') { - usage(argv); - } - loops = atoi(&argp[2]); - break; - default: - usage(argv); - } - } - -#if NO_SERVER -# if DEBUG - securityd_init(); -# endif -#endif - - /* get server cert and optional encryption cert as CFArrayRef */ - if(keyChainName) { - serverCerts = getSslCerts(keyChainName, false, completeCertChain, - anchorFile, &serverKc); - if(serverCerts == nil) { - exit(1); - } - } - else -#if 0 - if(doIdSearch) { - OSStatus ortn = sslIdentityPicker(NULL, anchorFile, true, NULL, &serverCerts); - if(ortn) { - printf("***IdentitySearch failure; aborting.\n"); - exit(1); - } - } - if(password) { - OSStatus ortn = SecKeychainUnlock(serverKc, strlen(password), password, true); - if(ortn) { - printf("SecKeychainUnlock returned %d\n", (int)ortn); - /* oh well */ - } - } - if(encryptKeyChainName) { - encryptCerts = getSslCerts(encryptKeyChainName, true, completeCertChain, - anchorFile, &encryptKc); - if(encryptCerts == nil) { - exit(1); - } - } -#endif - if(protXOnly) { - switch(attemptProt) { - case kTLSProtocol1: - attemptProt = kTLSProtocol1Only; - break; - case kSSLProtocol3: - attemptProt = kSSLProtocol3Only; - break; - default: - break; - } - } -#if 0 - if(dhParamsFile) { - int r = cspReadFile(dhParamsFile, &dhParams, &dhParamsLen); - if(r) { - printf("***Error reading diffie-hellman params from %s; aborting\n", - dhParamsFile); - } - } -#endif - - /* one-time only server port setup */ - err = ListenForClients(portNum, nonBlocking, &listenSock); - if(err) { - printf("ListenForClients returned %d; aborting\n", (int)err); - exit(1); - } - - for(loopNum=1; ; loopNum++) { - err = sslServe(listenSock, - portNum, - attemptProt, - acceptedProts, - serverCerts, - password, - encryptCerts, - allowExpired, - allowAnyRoot, - allowExpiredRoot, - disableCertVerify, - anchorFile, - replaceAnchors, - cipherRestrict, - authenticate, - dhParams, - dhParamsLen, - acceptableDNList, - resumableEnable, - sessionCacheTimeout, - disableAnonCiphers, - quiet, - pause, - &negVersion, - &negCipher, - &certState, - &sessionWasResumed, - sessionID, - &sessionIDLength, - &peerCerts, - argv); - if(err) { - errCount++; - } - if(!quiet) { - SSLProtocol tryProt = attemptProt; - showSSLResult(tryProt, - acceptedProts, - err, - negVersion, - negCipher, - sessionWasResumed, - sessionID, - sessionIDLength, - peerCerts, - displayCerts, - certState, - fileBase ? fullFileBase : NULL); - } - errCount += verifyClientCertState(vfyCertState, expectCertState, - certState); - freePeerCerts(peerCerts); - if(loops && (loopNum == loops)) { - break; - } - }; - - endpointShutdown(listenSock); - - if(serverKc) { - CFRelease(serverKc); - } - if(encryptKc) { - CFRelease(encryptKc); - } - return errCount; - -} - - diff --git a/libsecurity_transform/custom.h b/libsecurity_transform/custom.h deleted file mode 100644 index 11e0dd91..00000000 --- a/libsecurity_transform/custom.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// custom.h -// libsecurity_transform -// -// Created by JOsborne on 2/18/10. -// Copyright 2010 Apple. All rights reserved. -// - -#import - - -@interface custom : SenTestCase { - -} - -@end diff --git a/libsecurity_transform/lib/Digest_block.h b/libsecurity_transform/lib/Digest_block.h deleted file mode 100644 index af04bb7f..00000000 --- a/libsecurity_transform/lib/Digest_block.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Digest_block.h - * libsecurity_transform - * - * Created by JOsborne on 2/20/10. - * Copyright 2010 Apple. All rights reserved. - * - */ - diff --git a/libsecurity_transform/lib/SecExternalSourceTransform.cpp b/libsecurity_transform/lib/SecExternalSourceTransform.cpp deleted file mode 100644 index 6a0b0824..00000000 --- a/libsecurity_transform/lib/SecExternalSourceTransform.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SecExternalSourceTransform.cpp - * libsecurity_transform - * - * Created by J Osborne on 8/17/10. - * Copyright 2010 Apple. All rights reserved. - * - */ - -#include "SecTransform.h" -#include "SecCustomTransform.h" -#include "SecExternalSourceTransform.h" -#include - -CFStringRef external_source_name = CFSTR("com.apple.security.external_source"); - -static SecTransformInstanceBlock SecExternalSourceTransformCreateBlock(CFStringRef name, SecTransformRef newTransform, SecTransformImplementationRef ref) -{ - return Block_copy(^{ - SecTransformCustomSetAttribute(ref, kSecTransformInputAttributeName, kSecTransformMetaAttributeRequired, kCFBooleanFalse); - - SecTransformAttributeRef out = SecTranformCustomGetAttribute(ref, kSecTransformOutputAttributeName, kSecTransformMetaAttributeRef); - - SecTransformSetAttributeAction(ref, kSecTransformActionAttributeNotification, kSecTransformInputAttributeName, ^(SecTransformAttributeRef attribute, CFTypeRef value) { - SecTransformCustomSetAttribute(ref, out, kSecTransformMetaAttributeValue, value); - return (CFTypeRef)NULL; - }); - - return (CFErrorRef)NULL; - }); -} - -SecTransformRef SecExternalSourceTransformCreate(CFErrorRef* error) -{ - static dispatch_once_t once; - dispatch_once(&once, ^{ - SecTransformRegister(external_source_name, SecExternalSourceTransformCreateBlock, error); - }); - - return SecTransformCreate(external_source_name, error); -} \ No newline at end of file diff --git a/libsecurity_transform/lib/SecGroupTransform.cpp b/libsecurity_transform/lib/SecGroupTransform.cpp deleted file mode 100644 index ca782744..00000000 --- a/libsecurity_transform/lib/SecGroupTransform.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * SecGroupTransform.cpp - * libsecurity_transform - * - * Created by ohjelmoija on 3/31/10. - * Copyright 2010 __MyCompanyName__. All rights reserved. - * - */ - -#include "SecGroupTransform.h" -#include "SecTransformInternal.h" -#include "GroupTransform.h" - -SecTransformRef SecGroupTransformFindLastTransform(SecGroupTransformRef groupTransform) -{ - GroupTransform* gt = (GroupTransform*) CoreFoundationHolder::ObjectFromCFType(groupTransform); - return gt->FindLastTransform(); -} - - - -SecTransformRef SecGroupTransformFindMonitor(SecGroupTransformRef groupTransform) -{ - GroupTransform* gt = (GroupTransform*) CoreFoundationHolder::ObjectFromCFType(groupTransform); - return gt->FindMonitor(); -} - - - -bool SecGroupTransformHasMember(SecGroupTransformRef groupTransform, SecTransformRef transform) -{ - GroupTransform* gt = (GroupTransform*) CoreFoundationHolder::ObjectFromCFType(groupTransform); - return gt->HasMember(transform); -} - - diff --git a/libsecurity_transform/lib/misc.h b/libsecurity_transform/lib/misc.h deleted file mode 100644 index 5bee0f84..00000000 --- a/libsecurity_transform/lib/misc.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * misc.h - * libsecurity_transform - * - * Created by JOsborne on 3/19/10. - * Copyright 2010 Apple. All rights reserved. - * - */ - -#ifndef __INCLUDED_TRANSFORMS_MISC_H__ -#define __INCLUDED_TRANSFORMS_MISC_H__ - -#include -#include "SecTransform.h" - -#ifdef __cplusplus -extern "C" { -#endif - - - CFErrorRef fancy_error(CFStringRef domain, CFIndex code, CFStringRef description); - extern void graphviz(FILE *f, SecTransformRef tr); - extern void CFfprintf(FILE *f, const char *format, ...); - CFErrorRef GetNoMemoryError(); - CFErrorRef GetNoMemoryErrorAndRetain(); - void CFSafeRelease(CFTypeRef object); - - // NOTE: the return may or allocate a fair bit more space then it needs. - // Use it for short lived conversions (or strdup the result). - extern char *utf8(CFStringRef s); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/libsecurity_transform/libsecurity_transform.xcodeproj/project.pbxproj b/libsecurity_transform/libsecurity_transform.xcodeproj/project.pbxproj deleted file mode 100644 index 00e4f101..00000000 --- a/libsecurity_transform/libsecurity_transform.xcodeproj/project.pbxproj +++ /dev/null @@ -1,875 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 18C5A961148442000010EF34 /* libsecurity_transform.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CA1FEBE052A3C8100F22E42 /* libsecurity_transform.a */; }; - 18C5A964148443F00010EF34 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18C5A963148443F00010EF34 /* SenTestingKit.framework */; }; - 18C5A9661484440D0010EF34 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18C5A9651484440D0010EF34 /* Foundation.framework */; }; - 4C010B9B121AE9960094CB72 /* speed-test.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4C010B9A121AE9960094CB72 /* speed-test.mm */; }; - 4C010BBB121AECF10094CB72 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D16D6FB114EA1000096BD75 /* Security.framework */; }; - 4C010C52121B00350094CB72 /* SecExternalSourceTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C010C4B121AFCA70094CB72 /* SecExternalSourceTransform.h */; }; - 4C010C53121B00440094CB72 /* SecExternalSourceTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C010C4C121AFCA70094CB72 /* SecExternalSourceTransform.cpp */; }; - 4C0113511468693100E4F866 /* SecMaskGenerationFunctionTransform.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C01134F1468693100E4F866 /* SecMaskGenerationFunctionTransform.c */; }; - 4C0113521468693100E4F866 /* SecMaskGenerationFunctionTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0113501468693100E4F866 /* SecMaskGenerationFunctionTransform.h */; settings = {ATTRIBUTES = (); }; }; - 4C01135C14686F2600E4F866 /* NSData+HexString.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C01135A14686F2600E4F866 /* NSData+HexString.m */; }; - 4C27A37514F2D66C007FCA66 /* libcorecrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C27A37414F2D66C007FCA66 /* libcorecrypto.dylib */; }; - 4C27A37814F2DCB4007FCA66 /* CEncryptDecrypt.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C27A37714F2DCB4007FCA66 /* CEncryptDecrypt.c */; }; - 4C27A38114F2E3A5007FCA66 /* libcorecrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C27A37414F2D66C007FCA66 /* libcorecrypto.dylib */; }; - 4C6E5966116D4E3E00A70E8F /* misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6E5964116D4E3E00A70E8F /* misc.c */; }; - 4C6E5967116D4E3E00A70E8F /* misc.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6E5965116D4E3E00A70E8F /* misc.h */; }; - 4C73822D112DCC4800EA003B /* SecCustomTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C73822B112DCC4800EA003B /* SecCustomTransform.h */; settings = {ATTRIBUTES = (); }; }; - 4C73822E112DCC4800EA003B /* SecCustomTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C73822C112DCC4800EA003B /* SecCustomTransform.cpp */; }; - 4C8174341133031E007F84D6 /* libsecurity_transform.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CA1FEBE052A3C8100F22E42 /* libsecurity_transform.a */; }; - 4CB89E62124D5667004DEC20 /* SecTransformValidator.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CB89E61124D5667004DEC20 /* SecTransformValidator.h */; settings = {ATTRIBUTES = (); }; }; - 4CC4A8B21264D22300075C8F /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D16D6FB114EA1000096BD75 /* Security.framework */; }; - 4CD6A669113F41990094F287 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CD6A668113F41990094F287 /* libz.dylib */; }; - 4CD87F501130A49400A98C5E /* 100-sha2.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CD87F3D1130A34700A98C5E /* 100-sha2.m */; }; - 4CDF6DCC113C4E9E00C64234 /* EncodeDecodeTransforms.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CDF6DC9113C4E9E00C64234 /* EncodeDecodeTransforms.c */; }; - 4CDF6DCD113C4E9E00C64234 /* SecDecodeTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CDF6DCA113C4E9E00C64234 /* SecDecodeTransform.h */; settings = {ATTRIBUTES = (); }; }; - 4CDF6DCE113C4E9E00C64234 /* SecEncodeTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CDF6DCB113C4E9E00C64234 /* SecEncodeTransform.h */; settings = {ATTRIBUTES = (); }; }; - 5D97B3FF114EF1B50033D0F9 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CD6A668113F41990094F287 /* libz.dylib */; }; - 5DCAD5B711F0E099003F2E7A /* SecCollectTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5DCAD5B511F0E099003F2E7A /* SecCollectTransform.cpp */; }; - 5DCAD5B811F0E099003F2E7A /* SecCollectTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DCAD5B611F0E099003F2E7A /* SecCollectTransform.h */; }; - 5DD2E91E114E9044007429E7 /* EncryptTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DD2E91C114E9044007429E7 /* EncryptTransform.h */; }; - 5DD2E91F114E9044007429E7 /* EncryptTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5DD2E91D114E9044007429E7 /* EncryptTransform.cpp */; }; - 5DD2E925114E9094007429E7 /* EncryptTransformUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DD2E923114E9094007429E7 /* EncryptTransformUtilities.h */; }; - 5DD2E926114E9094007429E7 /* EncryptTransformUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5DD2E924114E9094007429E7 /* EncryptTransformUtilities.cpp */; }; - 5DD2E929114E90E2007429E7 /* SecEncryptTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DD2E927114E90E2007429E7 /* SecEncryptTransform.h */; settings = {ATTRIBUTES = (); }; }; - 5DD2E92A114E90E2007429E7 /* SecEncryptTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5DD2E928114E90E2007429E7 /* SecEncryptTransform.cpp */; }; - 5DD2E938114E91CC007429E7 /* SecSignVerifyTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DD2E936114E91CC007429E7 /* SecSignVerifyTransform.h */; settings = {ATTRIBUTES = (); }; }; - 5DD2E939114E91CC007429E7 /* SecSignVerifyTransform.c in Sources */ = {isa = PBXBuildFile; fileRef = 5DD2E937114E91CC007429E7 /* SecSignVerifyTransform.c */; }; - 5DD2E9B5114E986D007429E7 /* custom.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5DD2E96E114E95B1007429E7 /* custom.mm */; }; - AA068646138C420C0059E73E /* SecReadTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA068645138C420C0059E73E /* SecReadTransform.h */; settings = {ATTRIBUTES = (); }; }; - AA068EDF1174AB350002E9E0 /* GroupTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA068EDB1174AB350002E9E0 /* GroupTransform.cpp */; }; - AA068EE01174AB350002E9E0 /* GroupTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA068EDC1174AB350002E9E0 /* GroupTransform.h */; }; - AA068EE11174AB350002E9E0 /* SecGroupTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA068EDD1174AB350002E9E0 /* SecGroupTransform.cpp */; }; - AA068EE21174AB350002E9E0 /* SecGroupTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA068EDE1174AB350002E9E0 /* SecGroupTransform.h */; }; - AA068EEE1174ABB20002E9E0 /* SecTransformInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = AA068EED1174ABB20002E9E0 /* SecTransformInternal.h */; settings = {ATTRIBUTES = (); }; }; - AA957FCB122C571E00181BE1 /* SecTransformReadTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA957FCA122C571E00181BE1 /* SecTransformReadTransform.h */; settings = {ATTRIBUTES = (); }; }; - AA957FD5122C57AF00181BE1 /* SecTransformReadTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA957FD4122C57AF00181BE1 /* SecTransformReadTransform.cpp */; }; - AA9781A91175475500699E38 /* c++utils.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9781A71175475500699E38 /* c++utils.h */; }; - AA9781AA1175475500699E38 /* c++utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9781A81175475500699E38 /* c++utils.cpp */; }; - AA9E1C221117966F00380F0D /* CoreFoundationBasics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C051117966F00380F0D /* CoreFoundationBasics.cpp */; }; - AA9E1C231117966F00380F0D /* CoreFoundationBasics.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C061117966F00380F0D /* CoreFoundationBasics.h */; }; - AA9E1C241117966F00380F0D /* Digest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C071117966F00380F0D /* Digest.cpp */; }; - AA9E1C251117966F00380F0D /* Digest.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C081117966F00380F0D /* Digest.h */; }; - AA9E1C261117966F00380F0D /* LinkedList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C091117966F00380F0D /* LinkedList.cpp */; }; - AA9E1C271117966F00380F0D /* LinkedList.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C0A1117966F00380F0D /* LinkedList.h */; }; - AA9E1C281117966F00380F0D /* Monitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C0B1117966F00380F0D /* Monitor.cpp */; }; - AA9E1C291117966F00380F0D /* Monitor.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C0C1117966F00380F0D /* Monitor.h */; }; - AA9E1C2A1117966F00380F0D /* NullTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C0D1117966F00380F0D /* NullTransform.cpp */; }; - AA9E1C2B1117966F00380F0D /* NullTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C0E1117966F00380F0D /* NullTransform.h */; }; - AA9E1C2C1117966F00380F0D /* SecDigestTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C0F1117966F00380F0D /* SecDigestTransform.cpp */; }; - AA9E1C2D1117966F00380F0D /* SecDigestTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C101117966F00380F0D /* SecDigestTransform.h */; settings = {ATTRIBUTES = (); }; }; - AA9E1C2E1117966F00380F0D /* SecNullTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C111117966F00380F0D /* SecNullTransform.cpp */; }; - AA9E1C2F1117966F00380F0D /* SecNullTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C121117966F00380F0D /* SecNullTransform.h */; settings = {ATTRIBUTES = (); }; }; - AA9E1C301117966F00380F0D /* SecTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C131117966F00380F0D /* SecTransform.cpp */; }; - AA9E1C311117966F00380F0D /* SecTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C141117966F00380F0D /* SecTransform.h */; settings = {ATTRIBUTES = (); }; }; - AA9E1C331117966F00380F0D /* SingleShotSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C161117966F00380F0D /* SingleShotSource.cpp */; }; - AA9E1C341117966F00380F0D /* SingleShotSource.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C171117966F00380F0D /* SingleShotSource.h */; }; - AA9E1C351117966F00380F0D /* Source.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C181117966F00380F0D /* Source.cpp */; }; - AA9E1C361117966F00380F0D /* Source.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C191117966F00380F0D /* Source.h */; }; - AA9E1C371117966F00380F0D /* StreamSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C1A1117966F00380F0D /* StreamSource.cpp */; }; - AA9E1C381117966F00380F0D /* StreamSource.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C1B1117966F00380F0D /* StreamSource.h */; }; - AA9E1C391117966F00380F0D /* Transform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C1C1117966F00380F0D /* Transform.cpp */; }; - AA9E1C3A1117966F00380F0D /* Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C1D1117966F00380F0D /* Transform.h */; }; - AA9E1C3B1117966F00380F0D /* TransformFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C1E1117966F00380F0D /* TransformFactory.cpp */; }; - AA9E1C3C1117966F00380F0D /* TransformFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C1F1117966F00380F0D /* TransformFactory.h */; }; - AA9E1C3D1117966F00380F0D /* Utilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA9E1C201117966F00380F0D /* Utilities.cpp */; }; - AA9E1C3E1117966F00380F0D /* Utilities.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9E1C211117966F00380F0D /* Utilities.h */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 4C010B90121AE9070094CB72 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_transform; - }; - 4C817255112F030F007F84D6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_transform; - }; - 4CD87FFF1131E0F500A98C5E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; - remoteInfo = libsecurity_transform; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 18BBC7391471F6DF00F2B224 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; - 18BBC73A1471F6DF00F2B224 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; - 18BBC73B1471F6DF00F2B224 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; - 18BBC73C1471F6DF00F2B224 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; - 18BBC73D1471F6DF00F2B224 /* security.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = security.xcconfig; sourceTree = ""; }; - 18C5A963148443F00010EF34 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; - 18C5A9651484440D0010EF34 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 4C010B87121AE8DF0094CB72 /* input-speed-test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "input-speed-test"; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C010B99121AE9960094CB72 /* speed-test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "speed-test.h"; path = "misc/speed-test.h"; sourceTree = ""; }; - 4C010B9A121AE9960094CB72 /* speed-test.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "speed-test.mm"; path = "misc/speed-test.mm"; sourceTree = ""; }; - 4C010BBE121AED340094CB72 /* libc++.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libc++.dylib"; path = "usr/lib/libc++.dylib"; sourceTree = SDKROOT; }; - 4C010C4B121AFCA70094CB72 /* SecExternalSourceTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecExternalSourceTransform.h; sourceTree = ""; }; - 4C010C4C121AFCA70094CB72 /* SecExternalSourceTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecExternalSourceTransform.cpp; sourceTree = ""; }; - 4C01134F1468693100E4F866 /* SecMaskGenerationFunctionTransform.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecMaskGenerationFunctionTransform.c; sourceTree = ""; }; - 4C0113501468693100E4F866 /* SecMaskGenerationFunctionTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecMaskGenerationFunctionTransform.h; sourceTree = ""; }; - 4C01135A14686F2600E4F866 /* NSData+HexString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+HexString.m"; sourceTree = ""; }; - 4C01135B14686F2600E4F866 /* NSData+HexString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+HexString.h"; sourceTree = ""; }; - 4C27A37414F2D66C007FCA66 /* libcorecrypto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcorecrypto.dylib; path = usr/lib/system/libcorecrypto.dylib; sourceTree = SDKROOT; }; - 4C27A37714F2DCB4007FCA66 /* CEncryptDecrypt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CEncryptDecrypt.c; sourceTree = ""; }; - 4C6E5964116D4E3E00A70E8F /* misc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = misc.c; sourceTree = ""; }; - 4C6E5965116D4E3E00A70E8F /* misc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = misc.h; sourceTree = ""; }; - 4C73822B112DCC4800EA003B /* SecCustomTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCustomTransform.h; sourceTree = ""; }; - 4C73822C112DCC4800EA003B /* SecCustomTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SecCustomTransform.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; - 4C738257112DF65200EA003B /* unit-tests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "unit-tests.octest"; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C738258112DF65200EA003B /* unit-tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "unit-tests-Info.plist"; sourceTree = ""; }; - 4C738260112DF68900EA003B /* custom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = custom.h; sourceTree = ""; }; - 4CA1FEBE052A3C8100F22E42 /* libsecurity_transform.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_transform.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 4CB89E61124D5667004DEC20 /* SecTransformValidator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTransformValidator.h; sourceTree = ""; }; - 4CBCBEB61130A2D700CC18E9 /* 100-sha2 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "100-sha2"; sourceTree = BUILT_PRODUCTS_DIR; }; - 4CBCBEB81130A2D800CC18E9 /* Info-security_transform.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-security_transform.plist"; sourceTree = ""; }; - 4CD6A668113F41990094F287 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; - 4CD87F3D1130A34700A98C5E /* 100-sha2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "100-sha2.m"; sourceTree = ""; }; - 4CDF6DC9113C4E9E00C64234 /* EncodeDecodeTransforms.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = EncodeDecodeTransforms.c; sourceTree = ""; }; - 4CDF6DCA113C4E9E00C64234 /* SecDecodeTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecDecodeTransform.h; sourceTree = ""; }; - 4CDF6DCB113C4E9E00C64234 /* SecEncodeTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecEncodeTransform.h; sourceTree = ""; }; - 5D16D6FB114EA1000096BD75 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; - 5DCAD5B511F0E099003F2E7A /* SecCollectTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecCollectTransform.cpp; sourceTree = ""; }; - 5DCAD5B611F0E099003F2E7A /* SecCollectTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCollectTransform.h; sourceTree = ""; }; - 5DD2E91C114E9044007429E7 /* EncryptTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = EncryptTransform.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - 5DD2E91D114E9044007429E7 /* EncryptTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = EncryptTransform.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; - 5DD2E923114E9094007429E7 /* EncryptTransformUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EncryptTransformUtilities.h; sourceTree = ""; }; - 5DD2E924114E9094007429E7 /* EncryptTransformUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EncryptTransformUtilities.cpp; sourceTree = ""; }; - 5DD2E927114E90E2007429E7 /* SecEncryptTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecEncryptTransform.h; sourceTree = ""; }; - 5DD2E928114E90E2007429E7 /* SecEncryptTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecEncryptTransform.cpp; sourceTree = ""; }; - 5DD2E936114E91CC007429E7 /* SecSignVerifyTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecSignVerifyTransform.h; sourceTree = ""; }; - 5DD2E937114E91CC007429E7 /* SecSignVerifyTransform.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecSignVerifyTransform.c; sourceTree = ""; }; - 5DD2E96E114E95B1007429E7 /* custom.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = custom.mm; sourceTree = ""; }; - AA068645138C420C0059E73E /* SecReadTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecReadTransform.h; sourceTree = ""; }; - AA068648138C42520059E73E /* SecReadTransform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecReadTransform.h; sourceTree = ""; }; - AA068EDB1174AB350002E9E0 /* GroupTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GroupTransform.cpp; sourceTree = ""; }; - AA068EDC1174AB350002E9E0 /* GroupTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GroupTransform.h; sourceTree = ""; }; - AA068EDD1174AB350002E9E0 /* SecGroupTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecGroupTransform.cpp; sourceTree = ""; }; - AA068EDE1174AB350002E9E0 /* SecGroupTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecGroupTransform.h; sourceTree = ""; }; - AA068EED1174ABB20002E9E0 /* SecTransformInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTransformInternal.h; sourceTree = ""; }; - AA957FCA122C571E00181BE1 /* SecTransformReadTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTransformReadTransform.h; sourceTree = ""; }; - AA957FD4122C57AF00181BE1 /* SecTransformReadTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecTransformReadTransform.cpp; sourceTree = ""; }; - AA9781A71175475500699E38 /* c++utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "c++utils.h"; sourceTree = ""; }; - AA9781A81175475500699E38 /* c++utils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "c++utils.cpp"; sourceTree = ""; }; - AA9E1C051117966F00380F0D /* CoreFoundationBasics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CoreFoundationBasics.cpp; sourceTree = ""; }; - AA9E1C061117966F00380F0D /* CoreFoundationBasics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoreFoundationBasics.h; sourceTree = ""; }; - AA9E1C071117966F00380F0D /* Digest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Digest.cpp; sourceTree = ""; }; - AA9E1C081117966F00380F0D /* Digest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Digest.h; sourceTree = ""; }; - AA9E1C091117966F00380F0D /* LinkedList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LinkedList.cpp; sourceTree = ""; }; - AA9E1C0A1117966F00380F0D /* LinkedList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinkedList.h; sourceTree = ""; }; - AA9E1C0B1117966F00380F0D /* Monitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Monitor.cpp; sourceTree = ""; }; - AA9E1C0C1117966F00380F0D /* Monitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Monitor.h; sourceTree = ""; }; - AA9E1C0D1117966F00380F0D /* NullTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NullTransform.cpp; sourceTree = ""; }; - AA9E1C0E1117966F00380F0D /* NullTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NullTransform.h; sourceTree = ""; }; - AA9E1C0F1117966F00380F0D /* SecDigestTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecDigestTransform.cpp; sourceTree = ""; }; - AA9E1C101117966F00380F0D /* SecDigestTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecDigestTransform.h; sourceTree = ""; }; - AA9E1C111117966F00380F0D /* SecNullTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecNullTransform.cpp; sourceTree = ""; }; - AA9E1C121117966F00380F0D /* SecNullTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecNullTransform.h; sourceTree = ""; }; - AA9E1C131117966F00380F0D /* SecTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecTransform.cpp; sourceTree = ""; }; - AA9E1C141117966F00380F0D /* SecTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTransform.h; sourceTree = ""; }; - AA9E1C161117966F00380F0D /* SingleShotSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SingleShotSource.cpp; sourceTree = ""; }; - AA9E1C171117966F00380F0D /* SingleShotSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SingleShotSource.h; sourceTree = ""; }; - AA9E1C181117966F00380F0D /* Source.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Source.cpp; sourceTree = ""; }; - AA9E1C191117966F00380F0D /* Source.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Source.h; sourceTree = ""; }; - AA9E1C1A1117966F00380F0D /* StreamSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StreamSource.cpp; sourceTree = ""; }; - AA9E1C1B1117966F00380F0D /* StreamSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StreamSource.h; sourceTree = ""; }; - AA9E1C1C1117966F00380F0D /* Transform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = Transform.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; - AA9E1C1D1117966F00380F0D /* Transform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = Transform.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - AA9E1C1E1117966F00380F0D /* TransformFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TransformFactory.cpp; sourceTree = ""; }; - AA9E1C1F1117966F00380F0D /* TransformFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TransformFactory.h; sourceTree = ""; }; - AA9E1C201117966F00380F0D /* Utilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Utilities.cpp; sourceTree = ""; }; - AA9E1C211117966F00380F0D /* Utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utilities.h; sourceTree = ""; }; - AA9E1C9A1117A4A800380F0D /* security_transform.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; name = security_transform.exp; path = lib/security_transform.exp; sourceTree = ""; }; - AA9E1CAD1117A6E000380F0D /* libsecurity_transform_Development.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = libsecurity_transform_Development.xcconfig; sourceTree = ""; }; - AA9E1CAE1117A6F200380F0D /* libsecurity_transform_Deployment.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = libsecurity_transform_Deployment.xcconfig; sourceTree = ""; }; - AA9E1CAF1117A70300380F0D /* libsecurity_transform.Default.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = libsecurity_transform.Default.xcconfig; sourceTree = ""; }; - AA9E1CB01117A78C00380F0D /* security_transform_Development.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = security_transform_Development.xcconfig; sourceTree = ""; }; - AA9E1CB11117A7A300380F0D /* security_transform_Deployment.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = security_transform_Deployment.xcconfig; sourceTree = ""; }; - AA9E1CB21117A7BA00380F0D /* security_transform_Default.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = security_transform_Default.xcconfig; sourceTree = ""; }; - AACAD86B11628E700070BA52 /* libsecurity_transform_core.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = libsecurity_transform_core.xcconfig; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 4C010B85121AE8DF0094CB72 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 4C010BBB121AECF10094CB72 /* Security.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4C738254112DF65200EA003B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 18C5A9661484440D0010EF34 /* Foundation.framework in Frameworks */, - 18C5A964148443F00010EF34 /* SenTestingKit.framework in Frameworks */, - 18C5A961148442000010EF34 /* libsecurity_transform.a in Frameworks */, - 4CD6A669113F41990094F287 /* libz.dylib in Frameworks */, - 4CC4A8B21264D22300075C8F /* Security.framework in Frameworks */, - 4C27A38114F2E3A5007FCA66 /* libcorecrypto.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 4C27A37514F2D66C007FCA66 /* libcorecrypto.dylib in Frameworks */, - 5D97B3FF114EF1B50033D0F9 /* libz.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4CBCBEB41130A2D700CC18E9 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 4C8174341133031E007F84D6 /* libsecurity_transform.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 18BBC7381471F6DF00F2B224 /* config */ = { - isa = PBXGroup; - children = ( - 18BBC7391471F6DF00F2B224 /* base.xcconfig */, - 18BBC73A1471F6DF00F2B224 /* debug.xcconfig */, - 18BBC73B1471F6DF00F2B224 /* lib.xcconfig */, - 18BBC73C1471F6DF00F2B224 /* release.xcconfig */, - 18BBC73D1471F6DF00F2B224 /* security.xcconfig */, - ); - name = config; - path = ../config; - sourceTree = ""; - }; - 4C73825F112DF66700EA003B /* unit-tests */ = { - isa = PBXGroup; - children = ( - 4C01135A14686F2600E4F866 /* NSData+HexString.m */, - 4C01135B14686F2600E4F866 /* NSData+HexString.h */, - 4C738260112DF68900EA003B /* custom.h */, - 5DD2E96E114E95B1007429E7 /* custom.mm */, - ); - name = "unit-tests"; - sourceTree = ""; - }; - 4CA1FEA7052A3C3800F22E42 = { - isa = PBXGroup; - children = ( - 18C5A9651484440D0010EF34 /* Foundation.framework */, - 18C5A963148443F00010EF34 /* SenTestingKit.framework */, - 18BBC7381471F6DF00F2B224 /* config */, - 4C27A37414F2D66C007FCA66 /* libcorecrypto.dylib */, - 4C010BBE121AED340094CB72 /* libc++.dylib */, - 4CD6A668113F41990094F287 /* libz.dylib */, - 4C73825F112DF66700EA003B /* unit-tests */, - 4CBCBEB01130A2AB00CC18E9 /* misc-tests */, - AA9E1CA31117A67D00380F0D /* Configurations */, - AA9E1C9A1117A4A800380F0D /* security_transform.exp */, - 4CAFF3FC0534D89900303760 /* lib */, - 4CA1FEBF052A3C8100F22E42 /* Products */, - 4C738258112DF65200EA003B /* unit-tests-Info.plist */, - 4CBCBEB81130A2D800CC18E9 /* Info-security_transform.plist */, - 5D16D6FB114EA1000096BD75 /* Security.framework */, - ); - sourceTree = ""; - }; - 4CA1FEBF052A3C8100F22E42 /* Products */ = { - isa = PBXGroup; - children = ( - 4CA1FEBE052A3C8100F22E42 /* libsecurity_transform.a */, - 4C738257112DF65200EA003B /* unit-tests.octest */, - 4CBCBEB61130A2D700CC18E9 /* 100-sha2 */, - 4C010B87121AE8DF0094CB72 /* input-speed-test */, - ); - name = Products; - sourceTree = ""; - }; - 4CAFF3FC0534D89900303760 /* lib */ = { - isa = PBXGroup; - children = ( - 4C01134F1468693100E4F866 /* SecMaskGenerationFunctionTransform.c */, - 4C0113501468693100E4F866 /* SecMaskGenerationFunctionTransform.h */, - AA068645138C420C0059E73E /* SecReadTransform.h */, - 5DCAD5B511F0E099003F2E7A /* SecCollectTransform.cpp */, - 5DCAD5B611F0E099003F2E7A /* SecCollectTransform.h */, - AA9781A71175475500699E38 /* c++utils.h */, - AA9781A81175475500699E38 /* c++utils.cpp */, - AA9E1C051117966F00380F0D /* CoreFoundationBasics.cpp */, - AA9E1C061117966F00380F0D /* CoreFoundationBasics.h */, - AA9E1C071117966F00380F0D /* Digest.cpp */, - AA9E1C081117966F00380F0D /* Digest.h */, - 4CDF6DC9113C4E9E00C64234 /* EncodeDecodeTransforms.c */, - 5DD2E91C114E9044007429E7 /* EncryptTransform.h */, - 5DD2E91D114E9044007429E7 /* EncryptTransform.cpp */, - 4C27A37714F2DCB4007FCA66 /* CEncryptDecrypt.c */, - 5DD2E923114E9094007429E7 /* EncryptTransformUtilities.h */, - 5DD2E924114E9094007429E7 /* EncryptTransformUtilities.cpp */, - AA068EDB1174AB350002E9E0 /* GroupTransform.cpp */, - AA068EDC1174AB350002E9E0 /* GroupTransform.h */, - AA9E1C091117966F00380F0D /* LinkedList.cpp */, - AA9E1C0A1117966F00380F0D /* LinkedList.h */, - 4C6E5964116D4E3E00A70E8F /* misc.c */, - 4C6E5965116D4E3E00A70E8F /* misc.h */, - AA9E1C0B1117966F00380F0D /* Monitor.cpp */, - AA9E1C0C1117966F00380F0D /* Monitor.h */, - AA9E1C0D1117966F00380F0D /* NullTransform.cpp */, - AA9E1C0E1117966F00380F0D /* NullTransform.h */, - 4C73822B112DCC4800EA003B /* SecCustomTransform.h */, - 4C73822C112DCC4800EA003B /* SecCustomTransform.cpp */, - 4CDF6DCA113C4E9E00C64234 /* SecDecodeTransform.h */, - AA9E1C0F1117966F00380F0D /* SecDigestTransform.cpp */, - AA9E1C101117966F00380F0D /* SecDigestTransform.h */, - 5DD2E927114E90E2007429E7 /* SecEncryptTransform.h */, - 4CDF6DCB113C4E9E00C64234 /* SecEncodeTransform.h */, - 5DD2E928114E90E2007429E7 /* SecEncryptTransform.cpp */, - AA068EDD1174AB350002E9E0 /* SecGroupTransform.cpp */, - AA068EDE1174AB350002E9E0 /* SecGroupTransform.h */, - AA9E1C111117966F00380F0D /* SecNullTransform.cpp */, - 5DD2E936114E91CC007429E7 /* SecSignVerifyTransform.h */, - 5DD2E937114E91CC007429E7 /* SecSignVerifyTransform.c */, - AA9E1C121117966F00380F0D /* SecNullTransform.h */, - AA9E1C131117966F00380F0D /* SecTransform.cpp */, - AA9E1C141117966F00380F0D /* SecTransform.h */, - AA068EED1174ABB20002E9E0 /* SecTransformInternal.h */, - AA9E1C161117966F00380F0D /* SingleShotSource.cpp */, - AA9E1C171117966F00380F0D /* SingleShotSource.h */, - AA9E1C181117966F00380F0D /* Source.cpp */, - AA9E1C191117966F00380F0D /* Source.h */, - AA9E1C1A1117966F00380F0D /* StreamSource.cpp */, - AA9E1C1B1117966F00380F0D /* StreamSource.h */, - AA9E1C1C1117966F00380F0D /* Transform.cpp */, - AA9E1C1D1117966F00380F0D /* Transform.h */, - AA9E1C1E1117966F00380F0D /* TransformFactory.cpp */, - AA9E1C1F1117966F00380F0D /* TransformFactory.h */, - AA9E1C201117966F00380F0D /* Utilities.cpp */, - AA9E1C211117966F00380F0D /* Utilities.h */, - 4C010C4B121AFCA70094CB72 /* SecExternalSourceTransform.h */, - 4C010C4C121AFCA70094CB72 /* SecExternalSourceTransform.cpp */, - AA957FCA122C571E00181BE1 /* SecTransformReadTransform.h */, - AA957FD4122C57AF00181BE1 /* SecTransformReadTransform.cpp */, - 4CB89E61124D5667004DEC20 /* SecTransformValidator.h */, - AA068648138C42520059E73E /* SecReadTransform.h */, - ); - path = lib; - sourceTree = ""; - }; - 4CBCBEB01130A2AB00CC18E9 /* misc-tests */ = { - isa = PBXGroup; - children = ( - 4CD87F3D1130A34700A98C5E /* 100-sha2.m */, - 4C010B99121AE9960094CB72 /* speed-test.h */, - 4C010B9A121AE9960094CB72 /* speed-test.mm */, - ); - name = "misc-tests"; - sourceTree = ""; - }; - AA9E1CA31117A67D00380F0D /* Configurations */ = { - isa = PBXGroup; - children = ( - AACAD86B11628E700070BA52 /* libsecurity_transform_core.xcconfig */, - AA9E1CAD1117A6E000380F0D /* libsecurity_transform_Development.xcconfig */, - AA9E1CAE1117A6F200380F0D /* libsecurity_transform_Deployment.xcconfig */, - AA9E1CAF1117A70300380F0D /* libsecurity_transform.Default.xcconfig */, - AA9E1CB01117A78C00380F0D /* security_transform_Development.xcconfig */, - AA9E1CB11117A7A300380F0D /* security_transform_Deployment.xcconfig */, - AA9E1CB21117A7BA00380F0D /* security_transform_Default.xcconfig */, - ); - path = Configurations; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 4CA1FEB9052A3C8100F22E42 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - AA9E1C2D1117966F00380F0D /* SecDigestTransform.h in Headers */, - AA068646138C420C0059E73E /* SecReadTransform.h in Headers */, - AA9E1C311117966F00380F0D /* SecTransform.h in Headers */, - 4C73822D112DCC4800EA003B /* SecCustomTransform.h in Headers */, - 4CDF6DCD113C4E9E00C64234 /* SecDecodeTransform.h in Headers */, - 4CDF6DCE113C4E9E00C64234 /* SecEncodeTransform.h in Headers */, - 5DD2E929114E90E2007429E7 /* SecEncryptTransform.h in Headers */, - 5DD2E938114E91CC007429E7 /* SecSignVerifyTransform.h in Headers */, - AA957FCB122C571E00181BE1 /* SecTransformReadTransform.h in Headers */, - AA9E1C231117966F00380F0D /* CoreFoundationBasics.h in Headers */, - AA9E1C251117966F00380F0D /* Digest.h in Headers */, - 4CB89E62124D5667004DEC20 /* SecTransformValidator.h in Headers */, - AA9E1C2F1117966F00380F0D /* SecNullTransform.h in Headers */, - AA068EEE1174ABB20002E9E0 /* SecTransformInternal.h in Headers */, - AA9E1C271117966F00380F0D /* LinkedList.h in Headers */, - AA9E1C291117966F00380F0D /* Monitor.h in Headers */, - AA9E1C2B1117966F00380F0D /* NullTransform.h in Headers */, - AA9E1C341117966F00380F0D /* SingleShotSource.h in Headers */, - AA9E1C361117966F00380F0D /* Source.h in Headers */, - AA9E1C381117966F00380F0D /* StreamSource.h in Headers */, - AA9E1C3A1117966F00380F0D /* Transform.h in Headers */, - AA9E1C3C1117966F00380F0D /* TransformFactory.h in Headers */, - AA9E1C3E1117966F00380F0D /* Utilities.h in Headers */, - 4C0113521468693100E4F866 /* SecMaskGenerationFunctionTransform.h in Headers */, - 5DD2E91E114E9044007429E7 /* EncryptTransform.h in Headers */, - 5DD2E925114E9094007429E7 /* EncryptTransformUtilities.h in Headers */, - 4C6E5967116D4E3E00A70E8F /* misc.h in Headers */, - AA068EE01174AB350002E9E0 /* GroupTransform.h in Headers */, - AA068EE21174AB350002E9E0 /* SecGroupTransform.h in Headers */, - AA9781A91175475500699E38 /* c++utils.h in Headers */, - 5DCAD5B811F0E099003F2E7A /* SecCollectTransform.h in Headers */, - 4C010C52121B00350094CB72 /* SecExternalSourceTransform.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 4C010B86121AE8DF0094CB72 /* input-speed-test */ = { - isa = PBXNativeTarget; - buildConfigurationList = 4C010B97121AE9340094CB72 /* Build configuration list for PBXNativeTarget "input-speed-test" */; - buildPhases = ( - 4C010B84121AE8DF0094CB72 /* Sources */, - 4C010B85121AE8DF0094CB72 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 4C010B91121AE9070094CB72 /* PBXTargetDependency */, - ); - name = "input-speed-test"; - productName = "input-speed-test"; - productReference = 4C010B87121AE8DF0094CB72 /* input-speed-test */; - productType = "com.apple.product-type.tool"; - }; - 4C738256112DF65200EA003B /* unit-tests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 4C73825C112DF65400EA003B /* Build configuration list for PBXNativeTarget "unit-tests" */; - buildPhases = ( - 4C738252112DF65200EA003B /* Resources */, - 4C738253112DF65200EA003B /* Sources */, - 4C738254112DF65200EA003B /* Frameworks */, - 4C738255112DF65200EA003B /* ShellScript */, - ); - buildRules = ( - ); - dependencies = ( - 4C817256112F030F007F84D6 /* PBXTargetDependency */, - ); - name = "unit-tests"; - productName = "unit-tests"; - productReference = 4C738257112DF65200EA003B /* unit-tests.octest */; - productType = "com.apple.product-type.bundle"; - }; - 4CA1FEBD052A3C8100F22E42 /* libsecurity_transform */ = { - isa = PBXNativeTarget; - buildConfigurationList = C27AD4000987FCDF001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_transform" */; - buildPhases = ( - 4CA1FEB9052A3C8100F22E42 /* Headers */, - 4CA1FEBA052A3C8100F22E42 /* Sources */, - 4CA1FEBB052A3C8100F22E42 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libsecurity_transform; - productName = libsecurity_transform; - productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_transform.a */; - productType = "com.apple.product-type.library.static"; - }; - 4CBCBEB51130A2D700CC18E9 /* 100-sha2 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 4CBCBEBC1130A2DB00CC18E9 /* Build configuration list for PBXNativeTarget "100-sha2" */; - buildPhases = ( - 4CBCBEB31130A2D700CC18E9 /* Sources */, - 4CBCBEB41130A2D700CC18E9 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 4CD880001131E0F500A98C5E /* PBXTargetDependency */, - ); - name = "100-sha2"; - productName = "100-sha2"; - productReference = 4CBCBEB61130A2D700CC18E9 /* 100-sha2 */; - productType = "com.apple.product-type.tool"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 4CA1FEAB052A3C3800F22E42 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0500; - }; - buildConfigurationList = C27AD4040987FCDF001272E0 /* Build configuration list for PBXProject "libsecurity_transform" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - English, - Japanese, - French, - German, - ); - mainGroup = 4CA1FEA7052A3C3800F22E42; - productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 4CA1FEBD052A3C8100F22E42 /* libsecurity_transform */, - 4C738256112DF65200EA003B /* unit-tests */, - 4CBCBEB51130A2D700CC18E9 /* 100-sha2 */, - 4C010B86121AE8DF0094CB72 /* input-speed-test */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 4C738252112DF65200EA003B /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 4C738255112DF65200EA003B /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 4C010B84121AE8DF0094CB72 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 4C010B9B121AE9960094CB72 /* speed-test.mm in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4C738253112DF65200EA003B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 5DD2E9B5114E986D007429E7 /* custom.mm in Sources */, - 4C01135C14686F2600E4F866 /* NSData+HexString.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4CA1FEBA052A3C8100F22E42 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - AA9E1C221117966F00380F0D /* CoreFoundationBasics.cpp in Sources */, - AA9E1C241117966F00380F0D /* Digest.cpp in Sources */, - AA9E1C261117966F00380F0D /* LinkedList.cpp in Sources */, - AA9E1C281117966F00380F0D /* Monitor.cpp in Sources */, - AA9E1C2A1117966F00380F0D /* NullTransform.cpp in Sources */, - AA9E1C2C1117966F00380F0D /* SecDigestTransform.cpp in Sources */, - AA9E1C2E1117966F00380F0D /* SecNullTransform.cpp in Sources */, - AA9E1C301117966F00380F0D /* SecTransform.cpp in Sources */, - AA9E1C331117966F00380F0D /* SingleShotSource.cpp in Sources */, - AA9E1C351117966F00380F0D /* Source.cpp in Sources */, - AA9E1C371117966F00380F0D /* StreamSource.cpp in Sources */, - AA9E1C391117966F00380F0D /* Transform.cpp in Sources */, - AA9E1C3B1117966F00380F0D /* TransformFactory.cpp in Sources */, - AA9E1C3D1117966F00380F0D /* Utilities.cpp in Sources */, - 4C73822E112DCC4800EA003B /* SecCustomTransform.cpp in Sources */, - 4CDF6DCC113C4E9E00C64234 /* EncodeDecodeTransforms.c in Sources */, - 5DD2E91F114E9044007429E7 /* EncryptTransform.cpp in Sources */, - 5DD2E926114E9094007429E7 /* EncryptTransformUtilities.cpp in Sources */, - 5DD2E92A114E90E2007429E7 /* SecEncryptTransform.cpp in Sources */, - 5DD2E939114E91CC007429E7 /* SecSignVerifyTransform.c in Sources */, - 4C6E5966116D4E3E00A70E8F /* misc.c in Sources */, - AA068EDF1174AB350002E9E0 /* GroupTransform.cpp in Sources */, - AA068EE11174AB350002E9E0 /* SecGroupTransform.cpp in Sources */, - AA9781AA1175475500699E38 /* c++utils.cpp in Sources */, - 5DCAD5B711F0E099003F2E7A /* SecCollectTransform.cpp in Sources */, - 4C010C53121B00440094CB72 /* SecExternalSourceTransform.cpp in Sources */, - AA957FD5122C57AF00181BE1 /* SecTransformReadTransform.cpp in Sources */, - 4C0113511468693100E4F866 /* SecMaskGenerationFunctionTransform.c in Sources */, - 4C27A37814F2DCB4007FCA66 /* CEncryptDecrypt.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4CBCBEB31130A2D700CC18E9 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 4CD87F501130A49400A98C5E /* 100-sha2.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 4C010B91121AE9070094CB72 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 4CA1FEBD052A3C8100F22E42 /* libsecurity_transform */; - targetProxy = 4C010B90121AE9070094CB72 /* PBXContainerItemProxy */; - }; - 4C817256112F030F007F84D6 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 4CA1FEBD052A3C8100F22E42 /* libsecurity_transform */; - targetProxy = 4C817255112F030F007F84D6 /* PBXContainerItemProxy */; - }; - 4CD880001131E0F500A98C5E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 4CA1FEBD052A3C8100F22E42 /* libsecurity_transform */; - targetProxy = 4CD87FFF1131E0F500A98C5E /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 4C010B89121AE8DF0094CB72 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - COPY_PHASE_STRIP = NO; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; - INSTALL_PATH = /usr/local/bin; - OTHER_LDFLAGS = ( - "-lz", - "-framework", - Foundation, - "-framework", - AppKit, - ); - PRODUCT_NAME = "input-speed-test"; - }; - name = Debug; - }; - 4C010B8B121AE8DF0094CB72 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - GCC_MODEL_TUNING = G5; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; - INSTALL_PATH = /usr/local/bin; - OTHER_LDFLAGS = ( - "-framework", - Foundation, - "-framework", - AppKit, - ); - PRODUCT_NAME = "input-speed-test"; - }; - name = Release; - }; - 4C738259112DF65400EA003B /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18BBC73B1471F6DF00F2B224 /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(DEVELOPER_FRAMEWORKS_DIR)", - ); - INFOPLIST_FILE = "unit-tests-Info.plist"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - /usr/lib/system, - ); - PRODUCT_NAME = "unit-tests"; - WRAPPER_EXTENSION = octest; - }; - name = Debug; - }; - 4C73825B112DF65400EA003B /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18BBC73B1471F6DF00F2B224 /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(DEVELOPER_FRAMEWORKS_DIR)", - ); - INFOPLIST_FILE = "unit-tests-Info.plist"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - /usr/lib/system, - ); - PRODUCT_NAME = "unit-tests"; - WRAPPER_EXTENSION = octest; - }; - name = Release; - }; - 4CBCBEB91130A2DB00CC18E9 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; - INSTALL_PATH = /usr/local/bin; - OTHER_LDFLAGS = ( - "-framework", - Foundation, - "-framework", - AppKit, - "-lstdc++", - ); - PRODUCT_NAME = "100-sha2"; - }; - name = Debug; - }; - 4CBCBEBB1130A2DB00CC18E9 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - GCC_MODEL_TUNING = G5; - GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; - INSTALL_PATH = /usr/local/bin; - OTHER_LDFLAGS = ( - "-framework", - Foundation, - "-framework", - AppKit, - "-lstdc++", - ); - PRODUCT_NAME = "100-sha2"; - }; - name = Release; - }; - C27AD4010987FCDF001272E0 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18BBC73B1471F6DF00F2B224 /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - /usr/lib/system, - ); - OTHER_CFLAGS = ( - "$(inherited)", - "-DCOM_APPLE_SECURITY_SANE_INCLUDES", - ); - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=overloaded-virtual", - ); - }; - name = Debug; - }; - C27AD4030987FCDF001272E0 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18BBC73B1471F6DF00F2B224 /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - /usr/lib/system, - ); - OTHER_CFLAGS = ( - "$(inherited)", - "-DCOM_APPLE_SECURITY_SANE_INCLUDES", - ); - WARNING_CFLAGS = ( - "$(inherited)", - "-Wno-error=overloaded-virtual", - ); - }; - name = Release; - }; - C27AD4050987FCDF001272E0 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18BBC73A1471F6DF00F2B224 /* debug.xcconfig */; - buildSettings = { - }; - name = Debug; - }; - C27AD4070987FCDF001272E0 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18BBC73C1471F6DF00F2B224 /* release.xcconfig */; - buildSettings = { - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 4C010B97121AE9340094CB72 /* Build configuration list for PBXNativeTarget "input-speed-test" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 4C010B89121AE8DF0094CB72 /* Debug */, - 4C010B8B121AE8DF0094CB72 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 4C73825C112DF65400EA003B /* Build configuration list for PBXNativeTarget "unit-tests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 4C738259112DF65400EA003B /* Debug */, - 4C73825B112DF65400EA003B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 4CBCBEBC1130A2DB00CC18E9 /* Build configuration list for PBXNativeTarget "100-sha2" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 4CBCBEB91130A2DB00CC18E9 /* Debug */, - 4CBCBEBB1130A2DB00CC18E9 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C27AD4000987FCDF001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_transform" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C27AD4010987FCDF001272E0 /* Debug */, - C27AD4030987FCDF001272E0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C27AD4040987FCDF001272E0 /* Build configuration list for PBXProject "libsecurity_transform" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C27AD4050987FCDF001272E0 /* Debug */, - C27AD4070987FCDF001272E0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; -} diff --git a/libsecurity_transform/libsecurity_transform.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_transform/libsecurity_transform.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index dee7a39c..00000000 --- a/libsecurity_transform/libsecurity_transform.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,29 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 4C010B86121AE8DF0094CB72 - - primary - - - 4C738256112DF65200EA003B - - primary - - - 4CA1FEBD052A3C8100F22E42 - - primary - - - 4CBCBEB51130A2D700CC18E9 - - primary - - - - - diff --git a/libsecurity_transform/misc/speed-test.h b/libsecurity_transform/misc/speed-test.h deleted file mode 100644 index 7655591c..00000000 --- a/libsecurity_transform/misc/speed-test.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// speed-test.h -// libsecurity_transform -// -// Created by J Osborne on 8/17/10. -// Copyright 2010 Apple. All rights reserved. -// - -#import - - -@interface speed_test : NSObject { - -} - -@end diff --git a/libsecurity_transform/misc/speed-test.mm b/libsecurity_transform/misc/speed-test.mm deleted file mode 100644 index 531a322d..00000000 --- a/libsecurity_transform/misc/speed-test.mm +++ /dev/null @@ -1,92 +0,0 @@ -// -// speed-test.m -// libsecurity_transform -// -// Created by J Osborne on 8/17/10. -// Copyright 2010 Apple. All rights reserved. -// - -#import "speed-test.h" -#include "SecTransform.h" -#include "SecExternalSourceTransform.h" -#include "SecNullTransform.h" -#include - -@implementation speed_test - -@end - -UInt8 zeros[1024]; - -typedef void (^push_block_t)(CFDataRef d); - -void timed_test(NSString *name, float seconds, SecTransformRef tr, push_block_t push) { - __block int num_out = 0; - __block int num_in = 0; - __block int timeout_out = -1; - __block int timeout_in = -1; - volatile __block bool done; - static CFDataRef z = CFDataCreateWithBytesNoCopy(NULL, zeros, sizeof(zeros), NULL); - - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, static_cast(seconds * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ - done = true; - timeout_out = num_out; - timeout_in = num_in; - }); - - dispatch_group_t dg = dispatch_group_create(); - dispatch_group_enter(dg); - - dispatch_queue_t q = dispatch_queue_create("counter", NULL); - - SecTransformExecuteAsync(tr, q, ^(CFTypeRef message, CFErrorRef error, Boolean isFinal) { - if (message) { - num_out++; - } - if (error) { - NSLog(@"Error %@ while running %@", error, name); - } - if (isFinal) { - dispatch_group_leave(dg); - } - }); - - while (!done) { - push(z); - num_in++; - } - push(NULL); - dispatch_group_wait(dg, DISPATCH_TIME_FOREVER); - NSString *m = [NSString stringWithFormat:@"%@ %d in, %d out times in %f seconds, %d stragglers\n", name, timeout_in, timeout_out, seconds, num_out - timeout_out]; - [m writeToFile:@"/dev/stdout" atomically:NO encoding:NSUTF8StringEncoding error:NULL]; -} - -int main(int argc, char *argv[]) { - NSAutoreleasePool *ap = [[NSAutoreleasePool alloc] init]; - float seconds = 5.0; - - { - SecTransformRef x = SecExternalSourceTransformCreate(NULL); - //SecTransformRef t = SecEncodeTransformCreate(kSecBase64Encoding, NULL); - SecTransformRef t = SecNullTransformCreate(); - SecTransformRef g = SecTransformCreateGroupTransform(); - assert(x && t && g); - SecTransformConnectTransforms(x, kSecTransformOutputAttributeName, t, kSecTransformInputAttributeName, g, NULL); - - timed_test(@"external source", seconds, t, ^(CFDataRef d){ - SecExternalSourceSetValue(x, d, NULL); - }); - - } - - // This second test has issues with the stock transform framwork -- it don't think the graph is valid (missing input) - { - //SecTransformRef t = SecEncodeTransformCreate(kSecBase64Encoding, NULL); - SecTransformRef t = SecNullTransformCreate(); - assert(t); - - timed_test(@"set INPUT", seconds, t, ^(CFDataRef d){ - SecTransformSetAttribute(t, kSecTransformInputAttributeName, d, NULL); - }); - } -} \ No newline at end of file diff --git a/libsecurity_utilities/lib/ccaudit.h b/libsecurity_utilities/lib/ccaudit.h deleted file mode 100644 index 9ffa0b34..00000000 --- a/libsecurity_utilities/lib/ccaudit.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - - -#ifndef _H_CCAUDIT -#define _H_CCAUDIT - -#include -#include // audit_token_t -#include // au_tid_t, etc. -#include // AUE_NULL - -namespace Security { -namespace CommonCriteria { - -class AuditToken; - - -/* - * For the most part, we won't have a machine ID to initialize the - * au_tid_t's machine field. There's no machine ID in the audit token, - * for example, since MIG is localhost-only. - */ -class TerminalId: public PodWrapper -{ - public: - TerminalId(); - TerminalId(const TerminalId &t) { set(t); } - TerminalId(const au_tid_t &tid) { set(tid); } - ~TerminalId() { } - - void set(const au_tid_t &tid) { port = tid.port; machine = tid.machine; } -}; - -/* - * audit_token_t provides all the info required for Common Criteria-mandated - * auditing. It's defined in . Its values are filled - * in by the kernel during a Mach RPC and it should be treated as read-only - * thereafter. - */ -class AuditToken { - public: - AuditToken(const audit_token_t &token); - ~AuditToken() { } - - audit_token_t auditToken() const { return mAuditToken; } - uid_t auditId() const { return mAuditId; } - uid_t euid() const { return mEuid; } - gid_t egid() const { return mEgid; } - uid_t ruid() const { return mRuid; } - gid_t rgid() const { return mRgid; } - pid_t pid() const { return mPid; } - au_asid_t sessionId() const { return mSessionId; } - const au_tid_t &terminalId() const { return mTerminalId; } - - private: - audit_token_t mAuditToken; - uid_t mAuditId; - uid_t mEuid; - gid_t mEgid; - uid_t mRuid; - gid_t mRgid; - pid_t mPid; // of client - au_asid_t mSessionId; - TerminalId mTerminalId; -}; - - -/* - * The (new) audit information structure - */ -class AuditInfo : public PodWrapper { -public: - void get(); - void get(au_asid_t session); - void getPid(pid_t pid); - void set(); - void create(uint64_t flags, uid_t auid = AU_DEFAUDITID); - - uid_t uid() const { return this->ai_auid; } - uint64_t flags() const { return this->ai_flags; } - au_asid_t sessionId() const { return this->ai_asid; } - - static AuditInfo current() { AuditInfo info; info.get(); return info; } -}; - - -// XXX/gh 3926739 -// -// NB: Qualify all uses of these names with the namespace (CommonCriteria). -// Existing source code already follows this convention. -enum ExternalErrors -{ - errNone = 0, - errInvalidCredential = 1111, // try to make easier to find in log - errUserCanceled, - errTooManyTries, - errAuthDenied, // "Auth" --> authorization; named to - // avoid conflict with the C symbol - // errAuthorizationDenied already in - // use - errEndOfExternalErrors // sentry/placeholder -}; - - - -class AuditMask -{ - public: - AuditMask(unsigned int s = AUE_NULL, unsigned int f = AUE_NULL) - { - mMask.am_success = s; mMask.am_failure = f; - } - ~AuditMask() { } - const au_mask_t &get(void) const { return mMask; } - - private: - au_mask_t mMask; -}; - - -// audit session state for the current process; only used by Server -class AuditSession -{ - public: - AuditSession(au_id_t auid, au_asid_t sid) - : mAuditId(auid), mSessionId(sid) { } - ~AuditSession() { } - - // set audit info for this process in kernel - void registerSession(void); - - void auditId(au_id_t auid) { mAuditId = auid; } - void eventMask(AuditMask &mask) { mEventMask = mask; } - void terminalId(TerminalId &tid) { mTerminalId = tid; } - void sessionId(au_asid_t sid) { mSessionId = sid; } - - au_id_t auditId(void) { return mAuditId; } - AuditMask &eventMask(void) { return mEventMask; } - TerminalId &terminalId(void) { return mTerminalId; } - au_asid_t sessionId(void) { return mSessionId; } - - private: - au_id_t mAuditId; - AuditMask mEventMask; - TerminalId mTerminalId; - au_asid_t mSessionId; -}; - -// -// For submitting audit records. Not general-purpose: no ability to -// submit arbitrary BSM tokens, for example. However, the SecurityServer -// has only limited auditing requirements under Common Criteria. -// -class AuditRecord -{ - public: - AuditRecord(const AuditToken &auditToken) - : mAuditToken(auditToken) { } - AuditRecord(const audit_token_t &auditToken) - : mAuditToken(auditToken) { } - ~AuditRecord() { } - - // returnCode == 0 --> success; nonzero returnCode --> failure - void submit(const short event_code, const int returnCode, - const char *msg = NULL); - - private: - AuditToken mAuditToken; -}; - -} // end namespace CommonCriteria -} // end namespace Security - -#endif // _H_CCAUDIT diff --git a/libsecurity_utilities/lib/debugging.h b/libsecurity_utilities/lib/debugging.h deleted file mode 100644 index b9f49c12..00000000 --- a/libsecurity_utilities/lib/debugging.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -// -// debugging - non-trivial debug support -// -#ifndef _H_DEBUGGING -#define _H_DEBUGGING - - -#include - -#ifdef __cplusplus - -#include -#include -#include - -namespace Security { -namespace Debug { - - -// -// Debug-dumping functions always exist. They may be stubs depending on build options. -// -bool dumping(const char *scope); -void dump(const char *format, ...) __attribute((format(printf,1,2))); -void dumpData(const void *data, size_t length); -void dumpData(const char *title, const void *data, size_t length); -template inline void dumpData(const Data &obj) -{ dumpData(obj.data(), obj.length()); } -template inline void dumpData(const char *title, const Data &obj) -{ dumpData(title, obj.data(), obj.length()); } - - -// -// The following functions perform runtime recovery of type names. -// This is meant for debugging ONLY. Don't even THINK of depending -// on this for program correctness. For all you know, we may replace -// all those names with "XXX" tomorrow. -// -string makeTypeName(const type_info &info); - -template -string typeName(const Object &obj) -{ - return makeTypeName(typeid(obj)); -} - -template -string typeName() -{ - return makeTypeName(typeid(Object)); -} - - -// -// We are still conditionally emitting debug-dumping code -// -#undef DEBUGGING -#if !defined(NDEBUG) -# define DEBUGGING 1 -# define DEBUGDUMP 1 -#else //NDEBUG -# define DEBUGGING 0 -#endif //NDEBUG - -#if defined(DEBUGDUMP) -# define IFDUMP(code) code -# define IFDUMPING(scope,code) if (Debug::dumping(scope)) code; else /* no */ -#else -# define IFDUMP(code) /* no-op */ -# define IFDUMPING(scope,code) /* no-op */ -#endif - - -// -// We have some very, very old customers who call old debug facilities. -// Dummy them out for now. -// -inline bool debugging(const char *scope) DEPRECATED_ATTRIBUTE; -inline void debug(const char *scope, const char *format, ...) DEPRECATED_ATTRIBUTE; -inline void vdebug(const char *scope, const char *format, va_list args) DEPRECATED_ATTRIBUTE; - -inline bool debugging(const char *scope) { return false; } -inline void debug(const char *scope, const char *format, ...) { } -inline void vdebug(const char *scope, const char *format, va_list args) { } - - - - - -} // end namespace Debug -} // end namespace Security - -// leak debug() into the global namespace because URLAccess et al rely on that -using Security::Debug::debug; - -#else //__cplusplus - -#include - -#endif //__cplusplus - -#include - - -#endif //_H_DEBUGGING diff --git a/libsecurity_utilities/lib/debugging_internal.h b/libsecurity_utilities/lib/debugging_internal.h deleted file mode 100644 index 01996792..00000000 --- a/libsecurity_utilities/lib/debugging_internal.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// debugging_internal.h -// libsecurity_utilities -// -// Created by ohjelmoija on 11/27/12. -// -// - -#ifndef libsecurity_utilities_debugging_internal_h -#define libsecurity_utilities_debugging_internal_h - - -#ifdef __cplusplus -extern "C" -{ -#endif // __cplusplus - -// -// Include DTrace static probe definitions -// -typedef const void *DTException; - -#include - -// -// The debug-log macro is now unconditionally emitted as a DTrace static probe point. -// - -void secdebug_internal(const char* scope, const char* format, ...); - -#define secdebug(scope, format...) secdebug_internal(scope, format) -#define secdebugf(scope, __msg) SECURITY_DEBUG_LOG((char *)(scope), (__msg)) - -// -// The old secdelay() macro is also emitted as a DTrace probe (use destructive actions to handle this). -// Secdelay() should be considered a legacy feature; just put a secdebug at the intended delay point. -// -#define secdelay(file) SECURITY_DEBUG_DELAY((char *)(file)) - - -#ifdef __cplusplus -}; -#endif // __cplusplus - -#endif diff --git a/libsecurity_utilities/lib/utilities.h b/libsecurity_utilities/lib/utilities.h deleted file mode 100644 index 291d6b7f..00000000 --- a/libsecurity_utilities/lib/utilities.h +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (c) 2000-2004 Apple Computer, 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@ - */ - - -/* - * cssm utilities - */ -#ifndef _H_UTILITIES -#define _H_UTILITIES - -#include -#include -#include -#include -#include -#include - -namespace Security -{ - -// -// Elementary debugging support. -// #include for more debugging facilities. -// -#define IFDEBUG(it) IFELSEDEBUG(it,) -#define IFNDEBUG(it) IFELSEDEBUG(,it) - -#if defined(NDEBUG) - -# define safe_cast static_cast -# define safer_cast static_cast - -# define IFELSEDEBUG(d,nd) nd - -#else - -template -inline Derived safer_cast(Base &base) -{ - return dynamic_cast(base); -} - -template -inline Derived safe_cast(Base *base) -{ - if (base == NULL) - return NULL; // okay to cast NULL to NULL - Derived p = dynamic_cast(base); - assert(p); - return p; -} - -# define IFELSEDEBUG(d,nd) d - -#endif //NDEBUG - - -// -// Place this into your class definition if you don't want it to be copyable -// or asignable. This will not prohibit allocation on the stack or in static -// memory, but it will make anything derived from it, and anything containing -// it, fixed-once-created. A proper object, I suppose. -// -#define NOCOPY(Type) \ - private: Type(const Type &) DEPRECATED_IN_MAC_OS_X_VERSION_10_0_AND_LATER; \ - void operator = (const Type &) DEPRECATED_IN_MAC_OS_X_VERSION_10_0_AND_LATER; - - -// -// Helpers for memory pointer validation -// -#define MY_CSSM_ERRCODE_INVALID_POINTER 0x0004 -template -inline T &Required(T *ptr, OSStatus err = MY_CSSM_ERRCODE_INVALID_POINTER) -{ - if (ptr == NULL) - MacOSError::throwMe(err); - return *ptr; -} - -// specialization for void * (just check for non-null; don't return a void & :-) -inline void Required(void *ptr, OSStatus err = MY_CSSM_ERRCODE_INVALID_POINTER) -{ - if (ptr == NULL) - MacOSError::throwMe(err); -} - - -// -// Tools to build POD wrapper classes -// -template -class PodWrapper : public POD { -public: - // pure typecasts - static Wrapper * &overlayVar(POD * &data) - { return reinterpret_cast(data); } - static const Wrapper * &overlayVar(const POD * &data) - { return reinterpret_cast(data); } - - static Wrapper *overlay(POD *data) - { return static_cast(data); } - static const Wrapper *overlay(const POD *data) - { return static_cast(data); } - static Wrapper &overlay(POD &data) - { return static_cast(data); } - static const Wrapper &overlay(const POD &data) - { return static_cast(data); } - - // optional/required forms - static Wrapper &required(POD *data) - { return overlay(Required(data)); } - static const Wrapper &required(const POD *data) - { return overlay(Required(data)); } - static Wrapper *optional(POD *data) - { return overlay(data); } - static const Wrapper *optional(const POD *data) - { return overlay(data); } - - // general helpers for all PodWrappers - void clearPod() - { memset(static_cast(this), 0, sizeof(POD)); } - - void assignPod(const POD &source) - { static_cast(*this) = source; } -}; - - -// -// Template builder support -// -template -struct Nonconst { - typedef T Type; -}; - -template -struct Nonconst { - typedef U Type; -}; - -template -struct Nonconst { - typedef U *Type; -}; - -// cast away pointed-to constness -template -typename Nonconst::Type unconst_cast(T obj) -{ - return const_cast::Type>(obj); -} - -template -typename Nonconst::Type &unconst_ref_cast(T &obj) -{ - return const_cast::Type &>(obj); -} - - -// Help with container of something->pointer cleanup -template -static inline void for_each_delete(In first, In last) -{ - while (first != last) - delete *(first++); -} - -// Help with map of something->pointer cleanup -template -static inline void for_each_map_delete(In first, In last) -{ - while (first != last) - delete (first++)->second; -} - -// versions of copy that project to pair elements -template -inline OutIterator copy_first(InIterator first, InIterator last, OutIterator out) -{ - while (first != last) - *out++ = (first++)->first; - return out; -} - -template -inline OutIterator copy_second(InIterator first, InIterator last, OutIterator out) -{ - while (first != last) - *out++ = (first++)->second; - return out; -} - - -// simple safe re-entry blocker -class RecursionBlock { -public: - RecursionBlock() : mActive(false) { } - ~RecursionBlock() { assert(!mActive); } - -public: - class Once { - public: - Once(RecursionBlock &rb) : block(rb), mActive(false) { } - ~Once() { block.mActive &= !mActive; } - bool operator () () - { if (block.mActive) return true; mActive = block.mActive = true; return false; } - - RecursionBlock █ - - private: - bool mActive; - }; - friend class Once; - -private: - bool mActive; -}; - -// Quick and dirty template for a (temporary) array of something -// Usage example auto_array anArray(20); -template -class auto_array -{ -public: - auto_array() : mArray(NULL) {} - auto_array(size_t inSize) : mArray(new T[inSize]) {} - ~auto_array() { if (mArray) delete[] mArray; } - T &operator[](size_t inIndex) { return mArray[inIndex]; } - void allocate(size_t inSize) { if (mArray) delete[] mArray; mArray = new T[inSize]; } - T *get() { return mArray; } - T *release() { T *anArray = mArray; mArray = NULL; return anArray; } -private: - T *mArray; -}; - -// Template for a vector-like class that takes a c-array as it's -// underlying storage without making a copy. -template -class constVector -{ - NOCOPY(constVector<_Tp>) -public: - typedef _Tp value_type; - typedef const value_type* const_pointer; - typedef const value_type* const_iterator; - typedef const value_type& const_reference; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - - typedef std::reverse_iterator const_reverse_iterator; -public: - const_iterator begin() const { return _M_start; } - const_iterator end() const { return _M_finish; } - - const_reverse_iterator rbegin() const - { return const_reverse_iterator(end()); } - const_reverse_iterator rend() const - { return const_reverse_iterator(begin()); } - - size_type size() const - { return size_type(end() - begin()); } - bool empty() const - { return begin() == end(); } - - const_reference operator[](size_type __n) const { return *(begin() + __n); } - - // "at" will eventually have range checking, once we have the - // infrastructure to be able to throw stl range errors. - const_reference at(size_type n) const { return (*this)[n]; } - - constVector(size_type __n, const _Tp* __value) - : _M_start(__value), _M_finish(__value + __n) - {} - - constVector() : _M_start(NULL), _M_finish(NULL) {} - - void overlay(size_type __n, const _Tp* __value) { - _M_start = __value; - _M_finish = __value + __n; - } - - const_reference front() const { return *begin(); } - const_reference back() const { return *(end() - 1); } -private: - const _Tp *_M_start; - const _Tp *_M_finish; -}; - -char *cached_realpath(const char * file_name, char * resolved_name); - -} // end namespace Security - - -#endif //_H_UTILITIES diff --git a/libsecurity_utilities/libsecurity_utilities.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurity_utilities/libsecurity_utilities.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index a78d8bcc..00000000 --- a/libsecurity_utilities/libsecurity_utilities.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,19 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 4CA2A5390523D32800978A7B - - primary - - - C2C9C69D0CECBE8400B3FE07 - - primary - - - - - diff --git a/libsecurityd/lib/SharedMemoryCommon.h b/libsecurityd/lib/SharedMemoryCommon.h deleted file mode 100644 index d4c40128..00000000 --- a/libsecurityd/lib/SharedMemoryCommon.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __SHARED_MEMORY_COMMON__ -#define __SHARED_MEMORY_COMMON__ - - - -#include - -const unsigned kSegmentSize = 4096; -const unsigned kNumberOfSegments = 8; -const unsigned kSharedMemoryPoolSize = kSegmentSize * kNumberOfSegments; - -const unsigned kBytesWrittenOffset = 0; -const unsigned kBytesWrittenLength = 4; -const unsigned kPoolAvailableForData = kSharedMemoryPoolSize - kBytesWrittenLength; - -typedef u_int32_t SegmentOffsetType; - -#define SECURITY_MESSAGES_NAME "SecurityMessages" - -#endif diff --git a/libsecurityd/lib/transition.cpp b/libsecurityd/lib/transition.cpp deleted file mode 100644 index f4527ff8..00000000 --- a/libsecurityd/lib/transition.cpp +++ /dev/null @@ -1,1066 +0,0 @@ -/* - * Copyright (c) 2000-2008 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@ - */ - - -// -// transition - SecurityServer client library transition code. -// -// These are the functions that implement CssmClient methods in terms of -// MIG IPC client calls, plus their supporting machinery. -// -// WARNING! HERE BE DRAGONS! -// This code involves moderately arcane magic including (but not limited to) -// dancing macros paired off with self-maintaining stack objects. Don't take -// anything for granted! Be very afraid of ALL-CAPS names. Your best bet is -// probably to stick with the existing patterns. -// -// Dragons, the sequel. You just don't go killing of that kind of prose, so -// we'll continue the saga here with a bit of an update. In transitioning -// into securityd there are a couple of steps. The current setup is there -// to allow Security.framework to have 32 and 64 bit clients and either -// big or little endian. Data is packaged up as hand-generated XDR, which -// means it's also in network byte-order. -// -// CSSM_HANDLEs have remained longs in the 64 bit transition to keep the -// optimization option open to allow cssm modules to hand back pointers as -// handles. Since we don't identify the client, handles across ipc will -// remain 32 bit. Handles you see here are passed out by securityd, and -// are clipped and expanded in this layer (high bits always zero). -// -#include "sstransit.h" -#include - -#include -#include -#include - -namespace Security { -namespace SecurityServer { - -using MachPlusPlus::check; -using MachPlusPlus::VMGuard; - -// -// Common database interface -// -void ClientSession::authenticateDb(DbHandle db, CSSM_DB_ACCESS_TYPE type, - const AccessCredentials *cred) -{ - // XXX/cs Leave it up to DatabaseAccessCredentials to rewrite it for now - DatabaseAccessCredentials creds(cred, internalAllocator); - CopyIn copy(creds.value(), reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); - IPC(ucsp_client_authenticateDb(UCSP_ARGS, db, type, copy.data(), copy.length())); -} - - -void ClientSession::releaseDb(DbHandle db) -{ - IPC(ucsp_client_releaseDb(UCSP_ARGS, db)); -} - - -// -// External database interface -// -DbHandle ClientSession::openToken(uint32 ssid, const AccessCredentials *cred, - const char *name) -{ - DbHandle db; - DatabaseAccessCredentials creds(cred, internalAllocator); - CopyIn copycreds(creds.value(), reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); - - IPC(ucsp_client_openToken(UCSP_ARGS, ssid, name ? name : "", copycreds.data(), copycreds.length(), &db)); - - return db; -} - - -RecordHandle ClientSession::insertRecord(DbHandle db, - CSSM_DB_RECORDTYPE recordType, - const CssmDbRecordAttributeData *attributes, - const CssmData *data) -{ - RecordHandle record; - CopyIn db_record_attr_data(attributes, reinterpret_cast(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA)); - - IPC(ucsp_client_insertRecord(UCSP_ARGS, db, recordType, db_record_attr_data.data(), (mach_msg_type_number_t)db_record_attr_data.length(), OPTIONALDATA(data), &record)); - - return record; -} - - -void ClientSession::deleteRecord(DbHandle db, RecordHandle record) -{ - IPC(ucsp_client_deleteRecord(UCSP_ARGS, db, record)); -} - - -void ClientSession::modifyRecord(DbHandle db, RecordHandle &record, - CSSM_DB_RECORDTYPE recordType, - const CssmDbRecordAttributeData *attributes, - const CssmData *data, - CSSM_DB_MODIFY_MODE modifyMode) -{ - CopyIn db_record_attr_data(attributes, reinterpret_cast(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA)); - - IPC(ucsp_client_modifyRecord(UCSP_ARGS, db, &record, recordType, db_record_attr_data.data(), (mach_msg_type_number_t)db_record_attr_data.length(), - data != NULL, OPTIONALDATA(data), modifyMode)); -} - -static -void copy_back_attribute_return_data(CssmDbRecordAttributeData *dest_attrs, CssmDbRecordAttributeData *source_attrs, Allocator &returnAllocator) -{ - assert(dest_attrs->size() == source_attrs->size()); - // global (per-record) fields - dest_attrs->recordType(source_attrs->recordType()); - dest_attrs->semanticInformation(source_attrs->semanticInformation()); - - // transfer data values (but not infos, which we keep in the original vector) - for (uint32 n = 0; n < dest_attrs->size(); n++) - dest_attrs->at(n).copyValues(source_attrs->at(n), returnAllocator); -} - -RecordHandle ClientSession::findFirst(DbHandle db, - const CssmQuery &inQuery, - SearchHandle &hSearch, - CssmDbRecordAttributeData *attributes, - CssmData *data, KeyHandle &hKey) -{ - CopyIn query(&inQuery, reinterpret_cast(xdr_CSSM_QUERY)); - CopyIn in_attr(attributes, reinterpret_cast(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA)); - void *out_attr_data = NULL, *out_data = NULL; - mach_msg_size_t out_attr_length = 0, out_data_length = 0; - RecordHandle ipcHRecord = 0; - - IPC(ucsp_client_findFirst(UCSP_ARGS, db, - query.data(), query.length(), in_attr.data(), in_attr.length(), - &out_attr_data, &out_attr_length, (data != NULL), &out_data, &out_data_length, - &hKey, &hSearch, &ipcHRecord)); - - if (ipcHRecord != 0) - { - CopyOut out_attrs(out_attr_data, out_attr_length, reinterpret_cast(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR), true); - copy_back_attribute_return_data(attributes, reinterpret_cast(out_attrs.data()), returnAllocator); - } - - // decode data from server as cssm_data or cssm_key (get data on keys returns cssm_key in data) - CopyOut possible_key_in_data(out_data, out_data_length, reinterpret_cast(xdr_CSSM_POSSIBLY_KEY_IN_DATA_PTR), true, data); - - return ipcHRecord; -} - - -RecordHandle ClientSession::findNext(SearchHandle hSearch, - CssmDbRecordAttributeData *attributes, - CssmData *data, KeyHandle &hKey) -{ - CopyIn in_attr(attributes, reinterpret_cast(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA)); - void *out_attr_data = NULL, *out_data = NULL; - mach_msg_size_t out_attr_length = 0, out_data_length = 0; - //DataOutput out_data(data, returnAllocator); - RecordHandle ipcHRecord = 0; - - IPC(ucsp_client_findNext(UCSP_ARGS, hSearch, - in_attr.data(), in_attr.length(), &out_attr_data, &out_attr_length, - (data != NULL), &out_data, &out_data_length, &hKey, &ipcHRecord)); - - if (ipcHRecord != 0) - { - CopyOut out_attrs(out_attr_data, out_attr_length, reinterpret_cast(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR), true); - copy_back_attribute_return_data(attributes, reinterpret_cast(out_attrs.data()), returnAllocator); - } - - // decode data from server as cssm_data or cssm_key (get data on keys returns cssm_key in data) - CopyOut possible_key_in_data(out_data, out_data_length, reinterpret_cast(xdr_CSSM_POSSIBLY_KEY_IN_DATA_PTR), true, data); - - return ipcHRecord; -} - - -void ClientSession::findRecordHandle(RecordHandle hRecord, - CssmDbRecordAttributeData *attributes, - CssmData *data, KeyHandle &hKey) -{ - CopyIn in_attr(attributes, reinterpret_cast(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA)); - void *out_attr_data = NULL, *out_data = NULL; - mach_msg_size_t out_attr_length = 0, out_data_length = 0; - IPC(ucsp_client_findRecordHandle(UCSP_ARGS, hRecord, - in_attr.data(), in_attr.length(), &out_attr_data, &out_attr_length, - data != NULL, &out_data, &out_data_length, &hKey)); - - if (hRecord != 0) - { - CopyOut out_attrs(out_attr_data, out_attr_length, reinterpret_cast(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR), true); - copy_back_attribute_return_data(attributes, reinterpret_cast(out_attrs.data()), returnAllocator); - } - - // decode data from server as cssm_data or cssm_key (get data on keys returns cssm_key in data) - CopyOut possible_key_in_data(out_data, out_data_length, reinterpret_cast(xdr_CSSM_POSSIBLY_KEY_IN_DATA_PTR), true, data); -} - - -void ClientSession::releaseSearch(SearchHandle searchHandle) -{ - IPC(ucsp_client_releaseSearch(UCSP_ARGS, searchHandle)); -} - - -void ClientSession::releaseRecord(RecordHandle record) -{ - IPC(ucsp_client_releaseRecord(UCSP_ARGS, record)); -} - -void ClientSession::getDbName(DbHandle db, string &name) -{ - char result[PATH_MAX]; - - IPC(ucsp_client_getDbName(UCSP_ARGS, db, result)); - - name = result; -} - -void ClientSession::setDbName(DbHandle db, const string &name) -{ - IPC(ucsp_client_setDbName(UCSP_ARGS, db, name.c_str())); -} - - -// -// Internal database management -// -DbHandle ClientSession::createDb(const DLDbIdentifier &dbId, - const AccessCredentials *cred, const AclEntryInput *owner, - const DBParameters ¶ms) -{ - DatabaseAccessCredentials creds(cred, internalAllocator); - CopyIn copycreds(creds.value(), reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); - CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); - // XXX/64 make xdr routines translate directly between dldbident and flat rep - DataWalkers::DLDbFlatIdentifier ident(dbId); - CopyIn id(&ident, reinterpret_cast(xdr_DLDbFlatIdentifier)); - DbHandle db; - - IPC(ucsp_client_createDb(UCSP_ARGS, &db, id.data(), id.length(), copycreds.data(), copycreds.length(), proto.data(), proto.length(), params)); - - return db; -} - -DbHandle ClientSession::recodeDbForSync(DbHandle dbToClone, - DbHandle srcDb) -{ - DbHandle newDb; - - IPC(ucsp_client_recodeDbForSync(UCSP_ARGS, dbToClone, srcDb, &newDb)); - - return newDb; -} - -DbHandle ClientSession::authenticateDbsForSync(const CssmData &dbHandleArray, - const CssmData &agentData) -{ - DbHandle newDb; - - IPC(ucsp_client_authenticateDbsForSync(UCSP_ARGS, DATA(dbHandleArray), DATA(agentData), &newDb)); - - return newDb; -} - -void ClientSession::commitDbForSync(DbHandle srcDb, DbHandle cloneDb, - CssmData &blob, Allocator &alloc) -{ - DataOutput outBlob(blob, alloc); - IPC(ucsp_client_commitDbForSync(UCSP_ARGS, srcDb, cloneDb, DATA_OUT(outBlob))); -} - -DbHandle ClientSession::decodeDb(const DLDbIdentifier &dbId, - const AccessCredentials *cred, const CssmData &blob) -{ - // XXX/64 fold into one translation - DatabaseAccessCredentials credentials(cred, internalAllocator); - CopyIn creds(credentials.value(), reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); - // XXX/64 fold into one translation - DataWalkers::DLDbFlatIdentifier ident(dbId); - CopyIn id(&ident, reinterpret_cast(xdr_DLDbFlatIdentifier)); - DbHandle db; - - IPC(ucsp_client_decodeDb(UCSP_ARGS, &db, id.data(), id.length(), creds.data(), creds.length(), DATA(blob))); - - return db; -} - -void ClientSession::encodeDb(DbHandle db, CssmData &blob, Allocator &alloc) -{ - DataOutput outBlob(blob, alloc); - IPC(ucsp_client_encodeDb(UCSP_ARGS, db, DATA_OUT(outBlob))); -} - -void ClientSession::setDbParameters(DbHandle db, const DBParameters ¶ms) -{ - IPC(ucsp_client_setDbParameters(UCSP_ARGS, db, params)); -} - -void ClientSession::getDbParameters(DbHandle db, DBParameters ¶ms) -{ - IPC(ucsp_client_getDbParameters(UCSP_ARGS, db, ¶ms)); -} - -void ClientSession::changePassphrase(DbHandle db, const AccessCredentials *cred) -{ - CopyIn creds(cred, reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); - IPC(ucsp_client_changePassphrase(UCSP_ARGS, db, creds.data(), creds.length())); -} - - -void ClientSession::lock(DbHandle db) -{ - IPC(ucsp_client_authenticateDb(UCSP_ARGS, db, CSSM_DB_ACCESS_RESET, NULL, 0)); -//@@@VIRTUAL IPC(ucsp_client_lockDb(UCSP_ARGS, db)); -} - -void ClientSession::lockAll (bool forSleep) -{ - IPC(ucsp_client_lockAll (UCSP_ARGS, forSleep)); -} - -void ClientSession::unlock(DbHandle db) -{ - IPC(ucsp_client_unlockDb(UCSP_ARGS, db)); -} - -void ClientSession::unlock(DbHandle db, const CssmData &passphrase) -{ - IPC(ucsp_client_unlockDbWithPassphrase(UCSP_ARGS, db, DATA(passphrase))); -} - -void ClientSession::stashDb(DbHandle db) -{ - IPC(ucsp_client_stashDb(UCSP_ARGS, db)); -} - -void ClientSession::stashDbCheck(DbHandle db) -{ - IPC(ucsp_client_stashDbCheck(UCSP_ARGS, db)); -} - -bool ClientSession::isLocked(DbHandle db) -{ - boolean_t locked; - IPC(ucsp_client_isLocked(UCSP_ARGS, db, &locked)); - return locked; -} - -void ClientSession::verifyKeyStorePassphrase(uint32_t retries) -{ - IPC(ucsp_client_verifyKeyStorePassphrase(UCSP_ARGS, retries)); -} - -void ClientSession::resetKeyStorePassphrase(const CssmData &passphrase) -{ - IPC(ucsp_client_resetKeyStorePassphrase(UCSP_ARGS, DATA(passphrase))); -} - -void ClientSession::changeKeyStorePassphrase() -{ - IPC(ucsp_client_changeKeyStorePassphrase(UCSP_ARGS)); -} - -// -// Key control -// -void ClientSession::encodeKey(KeyHandle key, CssmData &blob, - KeyUID *uid, Allocator &alloc) -{ - // Not really used as output - DataOutput oBlob(blob, alloc); - void *uidp; - mach_msg_type_number_t uidLength; - - IPC(ucsp_client_encodeKey(UCSP_ARGS, key, oBlob.data(), oBlob.length(), - (uid != NULL), &uidp, &uidLength)); - - // return key uid if requested - if (uid) { - assert(uidLength == sizeof(KeyUID)); - memcpy(uid, uidp, sizeof(KeyUID)); - } -} - -KeyHandle ClientSession::decodeKey(DbHandle db, const CssmData &blob, CssmKey::Header &header) -{ - KeyHandle key; - void *keyHeaderData; - mach_msg_type_number_t keyHeaderDataLength; - - IPC(ucsp_client_decodeKey(UCSP_ARGS, &key, &keyHeaderData, &keyHeaderDataLength, db, blob.data(), (mach_msg_type_number_t)blob.length())); - - CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast(xdr_CSSM_KEYHEADER_PTR), true); - header = *static_cast(reinterpret_cast(wrappedKeyHeaderXDR.data())); - - return key; -} - -// keychain synchronization -void ClientSession::recodeKey(DbHandle oldDb, KeyHandle key, DbHandle newDb, - CssmData &blob) -{ - DataOutput outBlob(blob, returnAllocator); - IPC(ucsp_client_recodeKey(UCSP_ARGS, oldDb, key, newDb, DATA_OUT(outBlob))); -} - -void ClientSession::releaseKey(KeyHandle key) -{ - IPC(ucsp_client_releaseKey(UCSP_ARGS, key)); -} - - -CssmKeySize ClientSession::queryKeySizeInBits(KeyHandle key) -{ - CssmKeySize length; - IPC(ucsp_client_queryKeySizeInBits(UCSP_ARGS, key, &length)); - return length; -} - - -uint32 ClientSession::getOutputSize(const Context &context, KeyHandle key, - uint32 inputSize, bool encrypt) -{ - CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); - uint32 outputSize; - - IPC(ucsp_client_getOutputSize(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, inputSize, encrypt, &outputSize)); - return outputSize; -} - - -// -// Random number generation. -// This interfaces to the secure RNG inside the SecurityServer; it does not access -// a PRNG in its CSP. If you need a reproducible PRNG, attach a local CSP and use it. -// Note that this function does not allocate a buffer; it always fills the buffer provided. -// -void ClientSession::generateRandom(const Security::Context &context, CssmData &data, Allocator &alloc) -{ - CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); - DataOutput result(data, alloc); - - IPC(ucsp_client_generateRandom(UCSP_ARGS, 0, ctxcopy.data(), ctxcopy.length(), DATA_OUT(result))); -} - - -// -// Signatures and MACs -// -void ClientSession::generateSignature(const Context &context, KeyHandle key, - const CssmData &data, CssmData &signature, Allocator &alloc, CSSM_ALGORITHMS signOnlyAlgorithm) -{ - CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); - DataOutput sig(signature, alloc); - - IPCKEY(ucsp_client_generateSignature(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, signOnlyAlgorithm, - DATA(data), DATA_OUT(sig)), - key, CSSM_ACL_AUTHORIZATION_SIGN); -} - -void ClientSession::verifySignature(const Context &context, KeyHandle key, - const CssmData &data, const CssmData &signature, CSSM_ALGORITHMS verifyOnlyAlgorithm) -{ - CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); - - IPC(ucsp_client_verifySignature(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, verifyOnlyAlgorithm, DATA(data), DATA(signature))); -} - - -void ClientSession::generateMac(const Context &context, KeyHandle key, - const CssmData &data, CssmData &signature, Allocator &alloc) -{ - CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); - DataOutput sig(signature, alloc); - - IPCKEY(ucsp_client_generateMac(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, DATA(data), DATA_OUT(sig)), - key, CSSM_ACL_AUTHORIZATION_MAC); -} - -void ClientSession::verifyMac(const Context &context, KeyHandle key, - const CssmData &data, const CssmData &signature) -{ - CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); - - IPCKEY(ucsp_client_verifyMac(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, - DATA(data), DATA(signature)), - key, CSSM_ACL_AUTHORIZATION_MAC); -} - - -// -// Encryption/Decryption -// - -void ClientSession::encrypt(const Context &context, KeyHandle key, - const CssmData &clear, CssmData &cipher, Allocator &alloc) -{ - CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); - DataOutput cipherOut(cipher, alloc); - IPCKEY(ucsp_client_encrypt(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, DATA(clear), DATA_OUT(cipherOut)), - key, CSSM_ACL_AUTHORIZATION_ENCRYPT); -} - -void ClientSession::decrypt(const Context &context, KeyHandle key, - const CssmData &cipher, CssmData &clear, Allocator &alloc) -{ - CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); - DataOutput clearOut(clear, alloc); - - IPCKEY(ucsp_client_decrypt(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, DATA(cipher), DATA_OUT(clearOut)), - key, CSSM_ACL_AUTHORIZATION_DECRYPT); -} - - -// -// Key generation -// -void ClientSession::generateKey(DbHandle db, const Context &context, uint32 keyUsage, uint32 keyAttr, - const AccessCredentials *cred, const AclEntryInput *owner, - KeyHandle &newKey, CssmKey::Header &newHeader) -{ - CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); - CopyIn creds(cred, reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); - CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); - void *keyHeaderData; - mach_msg_type_number_t keyHeaderDataLength; - - IPC(ucsp_client_generateKey(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), - creds.data(), creds.length(), proto.data(), proto.length(), - keyUsage, keyAttr, &newKey, &keyHeaderData, &keyHeaderDataLength)); - - CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast(xdr_CSSM_KEYHEADER_PTR), true); - newHeader = *static_cast(reinterpret_cast(wrappedKeyHeaderXDR.data())); -} - -void ClientSession::generateKey(DbHandle db, const Context &context, - uint32 pubKeyUsage, uint32 pubKeyAttr, - uint32 privKeyUsage, uint32 privKeyAttr, - const AccessCredentials *cred, const AclEntryInput *owner, - KeyHandle &pubKey, CssmKey::Header &pubHeader, - KeyHandle &privKey, CssmKey::Header &privHeader) -{ - CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); - CopyIn creds(cred, reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); - CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); - void *pubKeyHeaderData, *privKeyHeaderData; - mach_msg_type_number_t pubKeyHeaderDataLength, privKeyHeaderDataLength; - - IPC(ucsp_client_generateKeyPair(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), - creds.data(), creds.length(), proto.data(), proto.length(), - pubKeyUsage, pubKeyAttr, privKeyUsage, privKeyAttr, - &pubKey, &pubKeyHeaderData, &pubKeyHeaderDataLength, - &privKey, &privKeyHeaderData, &privKeyHeaderDataLength)); - - CopyOut wrappedPubKeyHeaderXDR(pubKeyHeaderData, pubKeyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast(xdr_CSSM_KEYHEADER_PTR), true); - pubHeader = *static_cast(reinterpret_cast(wrappedPubKeyHeaderXDR.data())); - CopyOut wrappedPrivKeyHeaderXDR(privKeyHeaderData, privKeyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast(xdr_CSSM_KEYHEADER_PTR), true); - privHeader = *static_cast(reinterpret_cast(wrappedPrivKeyHeaderXDR.data())); - -} - - -// -// Key derivation -// This is a bit strained; the incoming 'param' value may have structure, -// and we use a synthetic CssmDeriveData structure (with ad-hoc walker) to -// handle that. Param also is input/output, which is always a pain (not to mention -// ill-defined by the CDSA standard). -// -// If you're here because an algorithm of yours requires structured parameter -// input, go to security_cdsa_utilities/cssmwalkers.h and add a case to the -// CssmDeriveData walker. -// -void ClientSession::deriveKey(DbHandle db, const Context &context, KeyHandle baseKey, - CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, CssmData ¶m, - const AccessCredentials *cred, const AclEntryInput *owner, - KeyHandle &newKey, CssmKey::Header &newHeader, Allocator &allocator) -{ - CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); - CopyIn creds(cred, reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); - CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); - CSSM_DERIVE_DATA inParamForm = { context.algorithm(), param }; - CopyIn inParam(&inParamForm, reinterpret_cast(xdr_CSSM_DERIVE_DATA)); - - try - { - DataOutput paramOutput(param, allocator); - void *keyHeaderData; - mach_msg_type_number_t keyHeaderDataLength; - - IPCKEY(ucsp_client_deriveKey(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), baseKey, - creds.data(), creds.length(), proto.data(), proto.length(), - inParam.data(), inParam.length(), DATA_OUT(paramOutput), - usage, attrs, &newKey, &keyHeaderData, &keyHeaderDataLength), - baseKey, CSSM_ACL_AUTHORIZATION_DERIVE); - - CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast(xdr_CSSM_KEYHEADER_PTR), true); - newHeader = *static_cast(reinterpret_cast(wrappedKeyHeaderXDR.data())); - } - catch (CssmError& e) - { - // filter out errors for CSSM_ALGID_PKCS5_PBKDF2 - if (context.algorithm() != CSSM_ALGID_PKCS5_PBKDF2 && e.error != CSSMERR_CSP_OUTPUT_LENGTH_ERROR) - { - throw; - } - } -} - - -// -// Digest generation -// -void ClientSession::getKeyDigest(KeyHandle key, CssmData &digest, Allocator &allocator) -{ - DataOutput dig(digest, allocator); - IPC(ucsp_client_getKeyDigest(UCSP_ARGS, key, DATA_OUT(dig))); -} - - -// -// Key wrapping and unwrapping -// -void ClientSession::wrapKey(const Context &context, KeyHandle wrappingKey, - KeyHandle keyToBeWrapped, const AccessCredentials *cred, - const CssmData *descriptiveData, CssmWrappedKey &wrappedKey, Allocator &alloc) -{ - CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); - CopyIn creds(cred, reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); - void *keyData; - mach_msg_type_number_t keyDataLength; - - IPCKEY(ucsp_client_wrapKey(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), wrappingKey, - creds.data(), creds.length(), - keyToBeWrapped, OPTIONALDATA(descriptiveData), - &keyData, &keyDataLength), - keyToBeWrapped, - context.algorithm() == CSSM_ALGID_NONE - ? CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR : CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED); - - CopyOut wrappedKeyXDR(keyData, keyDataLength + sizeof(CSSM_KEY), reinterpret_cast(xdr_CSSM_KEY_PTR), true); - CssmWrappedKey *wrappedKeyIPC = reinterpret_cast(wrappedKeyXDR.data()); - wrappedKey.header() = wrappedKeyIPC->header(); - wrappedKey.keyData() = CssmData(alloc.malloc(wrappedKeyIPC->keyData().length()), wrappedKeyIPC->keyData().length()); - memcpy(wrappedKey.keyData().data(), wrappedKeyIPC->keyData(), wrappedKeyIPC->keyData().length()); -} - -void ClientSession::unwrapKey(DbHandle db, const Context &context, KeyHandle key, - KeyHandle publicKey, const CssmWrappedKey &wrappedKey, - uint32 usage, uint32 attr, - const AccessCredentials *cred, const AclEntryInput *acl, - CssmData &descriptiveData, - KeyHandle &newKey, CssmKey::Header &newHeader, Allocator &alloc) -{ - CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); - DataOutput descriptor(descriptiveData, alloc); - CopyIn creds(cred, reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); - CopyIn proto(acl ? &acl->proto() : NULL, reinterpret_cast(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); - CopyIn wrappedKeyXDR(&wrappedKey, reinterpret_cast(xdr_CSSM_KEY)); - void *keyHeaderData; - mach_msg_type_number_t keyHeaderDataLength; - - IPCKEY(ucsp_client_unwrapKey(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), key, - creds.data(), creds.length(), proto.data(), proto.length(), - publicKey, wrappedKeyXDR.data(), wrappedKeyXDR.length(), usage, attr, DATA_OUT(descriptor), - &newKey, &keyHeaderData, &keyHeaderDataLength), - key, CSSM_ACL_AUTHORIZATION_DECRYPT); - - CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast(xdr_CSSM_KEYHEADER_PTR), true); - newHeader = *static_cast(reinterpret_cast(wrappedKeyHeaderXDR.data())); -} - - -// -// ACL management -// -void ClientSession::getAcl(AclKind kind, GenericHandle key, const char *tag, - uint32 &infoCount, AclEntryInfo * &infoArray, Allocator &alloc) -{ - uint32 count; - void* info; mach_msg_type_number_t infoLength; - IPC(ucsp_client_getAcl(UCSP_ARGS, kind, key, - (tag != NULL), tag ? tag : "", - &count, &info, &infoLength)); - - CSSM_ACL_ENTRY_INFO_ARRAY_PTR aclsArray; - if (!::copyout_chunked(info, infoLength, reinterpret_cast(xdr_CSSM_ACL_ENTRY_INFO_ARRAY_PTR), reinterpret_cast(&aclsArray))) - CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR); - - infoCount = aclsArray->count; - infoArray = reinterpret_cast(aclsArray->acls); - free(aclsArray); -} - -void ClientSession::changeAcl(AclKind kind, GenericHandle key, const AccessCredentials &cred, - const AclEdit &edit) -{ - CopyIn creds(&cred, reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); - //@@@ ignoring callback - CopyIn newEntry(edit.newEntry(), reinterpret_cast(xdr_CSSM_ACL_ENTRY_INPUT)); - - IPCKEY(ucsp_client_changeAcl(UCSP_ARGS, kind, key, creds.data(), creds.length(), - edit.mode(), toIPCHandle(edit.handle()), newEntry.data(), newEntry.length()), - key, CSSM_ACL_AUTHORIZATION_CHANGE_ACL); -} - -void ClientSession::getOwner(AclKind kind, GenericHandle key, AclOwnerPrototype &owner, - Allocator &alloc) -{ - void* proto; mach_msg_type_number_t protoLength; - IPC(ucsp_client_getOwner(UCSP_ARGS, kind, key, &proto, &protoLength)); - - CSSM_ACL_OWNER_PROTOTYPE_PTR tmpOwner; - if (!::copyout_chunked(proto, protoLength, reinterpret_cast(xdr_CSSM_ACL_OWNER_PROTOTYPE_PTR), reinterpret_cast(&tmpOwner))) - CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR); - owner = *static_cast(tmpOwner); - free(tmpOwner); -} - -void ClientSession::changeOwner(AclKind kind, GenericHandle key, - const AccessCredentials &cred, const AclOwnerPrototype &proto) -{ - CopyIn creds(&cred, reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); - CopyIn protos(&proto, reinterpret_cast(xdr_CSSM_ACL_OWNER_PROTOTYPE)); - IPCKEY(ucsp_client_setOwner(UCSP_ARGS, kind, key, creds.data(), creds.length(), protos.data(), protos.length()), - key, CSSM_ACL_AUTHORIZATION_CHANGE_OWNER); -} - - -void ClientSession::getKeyAcl(DbHandle db, const char *tag, - uint32 &count, AclEntryInfo * &info, Allocator &alloc) -{ getAcl(keyAcl, db, tag, count, info, alloc); } - -void ClientSession::changeKeyAcl(DbHandle db, const AccessCredentials &cred, - const AclEdit &edit) -{ changeAcl(keyAcl, db, cred, edit); } - -void ClientSession::getKeyOwner(DbHandle db, AclOwnerPrototype &owner, Allocator &alloc) -{ getOwner(keyAcl, db, owner, alloc); } - -void ClientSession::changeKeyOwner(DbHandle db, const AccessCredentials &cred, - const AclOwnerPrototype &edit) -{ changeOwner(keyAcl, db, cred, edit); } - -void ClientSession::getDbAcl(DbHandle db, const char *tag, - uint32 &count, AclEntryInfo * &info, Allocator &alloc) -{ getAcl(dbAcl, db, tag, count, info, alloc); } - -void ClientSession::changeDbAcl(DbHandle db, const AccessCredentials &cred, - const AclEdit &edit) -{ changeAcl(dbAcl, db, cred, edit); } - -void ClientSession::getDbOwner(DbHandle db, AclOwnerPrototype &owner, Allocator &alloc) -{ getOwner(dbAcl, db, owner, alloc); } - -void ClientSession::changeDbOwner(DbHandle db, const AccessCredentials &cred, - const AclOwnerPrototype &edit) -{ changeOwner(dbAcl, db, cred, edit); } - - -// -// Database key management -// -void ClientSession::extractMasterKey(DbHandle db, const Context &context, DbHandle sourceDb, - uint32 keyUsage, uint32 keyAttr, - const AccessCredentials *cred, const AclEntryInput *owner, - KeyHandle &newKey, CssmKey::Header &newHeader, Allocator &alloc) -{ - CopyIn ctxcopy(&context, reinterpret_cast(xdr_CSSM_CONTEXT)); - CopyIn creds(cred, reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS)); - CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); - void *keyHeaderData; - mach_msg_type_number_t keyHeaderDataLength; - - IPC(ucsp_client_extractMasterKey(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), sourceDb, - creds.data(), creds.length(), proto.data(), proto.length(), - keyUsage, keyAttr, &newKey, &keyHeaderData, &keyHeaderDataLength)); - - CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast(xdr_CSSM_KEYHEADER_PTR), true); - newHeader = *static_cast(reinterpret_cast(wrappedKeyHeaderXDR.data())); -} - - -// -// Authorization subsystem entry -// -void ClientSession::authCreate(const AuthorizationItemSet *rights, - const AuthorizationItemSet *environment, AuthorizationFlags flags, - AuthorizationBlob &result) -{ - void *rightSet = NULL; mach_msg_size_t rightSet_size = 0; - void *environ = NULL; mach_msg_size_t environ_size = 0; - - if ((rights && - !copyin_AuthorizationItemSet(rights, &rightSet, &rightSet_size)) || - (environment && - !copyin_AuthorizationItemSet(environment, &environ, &environ_size))) - CssmError::throwMe(errAuthorizationInternal); - - activate(); - IPCSTART(ucsp_client_authorizationCreate(UCSP_ARGS, - rightSet, rightSet_size, - flags, - environ, environ_size, - &result)); - - free(rightSet); - free(environ); - - if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) - CssmError::throwMe(errAuthorizationInteractionNotAllowed); - IPCEND_CHECK; -} - -void ClientSession::authRelease(const AuthorizationBlob &auth, - AuthorizationFlags flags) -{ - activate(); - IPCSTART(ucsp_client_authorizationRelease(UCSP_ARGS, auth, flags)); - if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) - CssmError::throwMe(errAuthorizationInteractionNotAllowed); - IPCEND_CHECK; -} - -void ClientSession::authCopyRights(const AuthorizationBlob &auth, - const AuthorizationItemSet *rights, const AuthorizationItemSet *environment, - AuthorizationFlags flags, - AuthorizationItemSet **grantedRights) -{ - void *rightSet = NULL; mach_msg_size_t rightSet_size = 0; - void *environ = NULL; mach_msg_size_t environ_size = 0; - void *result = NULL; mach_msg_type_number_t resultLength = 0; - - if ((rights && !copyin_AuthorizationItemSet(rights, &rightSet, &rightSet_size)) || - (environment && !copyin_AuthorizationItemSet(environment, &environ, &environ_size))) - CssmError::throwMe(errAuthorizationInternal); // allocation error probably - - activate(); - IPCSTART(ucsp_client_authorizationCopyRights(UCSP_ARGS, - auth, - rightSet, rightSet_size, - flags | (grantedRights ? 0 : kAuthorizationFlagNoData), - environ, environ_size, - &result, &resultLength)); - - free(rightSet); - free(environ); - - // XXX/cs return error when copyout returns false - if (rcode == CSSM_OK && grantedRights) - copyout_AuthorizationItemSet(result, resultLength, grantedRights); - - if (result) - mig_deallocate(reinterpret_cast(result), resultLength); - if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) - CssmError::throwMe(errAuthorizationInteractionNotAllowed); - IPCEND_CHECK; -} - -void ClientSession::authCopyInfo(const AuthorizationBlob &auth, - const char *tag, - AuthorizationItemSet * &info) -{ - if (tag == NULL) - tag = ""; - else if (tag[0] == '\0') - MacOSError::throwMe(errAuthorizationInvalidTag); - - activate(); - void *result; mach_msg_type_number_t resultLength; - IPCSTART(ucsp_client_authorizationCopyInfo(UCSP_ARGS, auth, tag, &result, &resultLength)); - - // XXX/cs return error when copyout returns false - if (rcode == CSSM_OK) - copyout_AuthorizationItemSet(result, resultLength, &info); - - if (result) - mig_deallocate(reinterpret_cast(result), resultLength); - - if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) - CssmError::throwMe(errAuthorizationInteractionNotAllowed); - IPCEND_CHECK; -} - -void ClientSession::authExternalize(const AuthorizationBlob &auth, - AuthorizationExternalForm &extForm) -{ - activate(); - IPCSTART(ucsp_client_authorizationExternalize(UCSP_ARGS, auth, &extForm)); - if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) - CssmError::throwMe(errAuthorizationInteractionNotAllowed); - IPCEND_CHECK; -} - -void ClientSession::authInternalize(const AuthorizationExternalForm &extForm, - AuthorizationBlob &auth) -{ - activate(); - IPCSTART(ucsp_client_authorizationInternalize(UCSP_ARGS, extForm, &auth)); - if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) - CssmError::throwMe(errAuthorizationInteractionNotAllowed); - IPCEND_CHECK; -} - - -// -// Push user preferences from an app in user space to securityd -// -void ClientSession::setSessionUserPrefs(SecuritySessionId sessionId, uint32_t userPreferencesLength, const void *userPreferences) -{ - IPC(ucsp_client_setSessionUserPrefs(UCSP_ARGS, sessionId, const_cast(userPreferences), userPreferencesLength)); -} - - -void ClientSession::postNotification(NotificationDomain domain, NotificationEvent event, const CssmData &data) -{ - uint32 seq = ++mGlobal().thread().notifySeq; -#if !defined(NDEBUG) - if (getenv("NOTIFYJITTER")) { - // artificially reverse odd/even sequences to test securityd's jitter buffer - seq += 2 * (seq % 2) - 1; - secdebug("notify", "POSTING FAKE SEQUENCE %d NOTIFICATION", seq); - } -#endif //NDEBUG - secdebug("notify", "posting domain 0x%x event %d sequence %d", - domain, event, seq); - IPC(ucsp_client_postNotification(UCSP_ARGS, domain, event, DATA(data), seq)); -} - -// -// authorizationdbGet/Set/Remove -// -void ClientSession::authorizationdbGet(const AuthorizationString rightname, CssmData &rightDefinition, Allocator &alloc) -{ - DataOutput definition(rightDefinition, alloc); - activate(); - IPCSTART(ucsp_client_authorizationdbGet(UCSP_ARGS, rightname, DATA_OUT(definition))); - if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) - CssmError::throwMe(errAuthorizationInteractionNotAllowed); - IPCEND_CHECK; -} - -void ClientSession::authorizationdbSet(const AuthorizationBlob &auth, const AuthorizationString rightname, uint32_t rightDefinitionLength, const void *rightDefinition) -{ - // @@@ DATA_IN in transition.cpp is not const void * - activate(); - IPCSTART(ucsp_client_authorizationdbSet(UCSP_ARGS, auth, rightname, const_cast(rightDefinition), rightDefinitionLength)); - if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) - CssmError::throwMe(errAuthorizationInteractionNotAllowed); - IPCEND_CHECK; -} - -void ClientSession::authorizationdbRemove(const AuthorizationBlob &auth, const AuthorizationString rightname) -{ - activate(); - IPCSTART(ucsp_client_authorizationdbRemove(UCSP_ARGS, auth, rightname)); - if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION) - CssmError::throwMe(errAuthorizationInteractionNotAllowed); - IPCEND_CHECK; -} - - -// -// Miscellaneous administrative calls -// -void ClientSession::addCodeEquivalence(const CssmData &oldHash, const CssmData &newHash, - const char *name, bool forSystem /* = false */) -{ - IPC(ucsp_client_addCodeEquivalence(UCSP_ARGS, DATA(oldHash), DATA(newHash), - name, forSystem)); -} - -void ClientSession::removeCodeEquivalence(const CssmData &hash, const char *name, bool forSystem /* = false */) -{ - IPC(ucsp_client_removeCodeEquivalence(UCSP_ARGS, DATA(hash), name, forSystem)); -} - -void ClientSession::setAlternateSystemRoot(const char *path) -{ - IPC(ucsp_client_setAlternateSystemRoot(UCSP_ARGS, path)); -} - - -// -// Code Signing related -// -void ClientSession::registerHosting(mach_port_t hostingPort, SecCSFlags flags) -{ - IPC(ucsp_client_registerHosting(UCSP_ARGS, hostingPort, flags)); -} - -mach_port_t ClientSession::hostingPort(pid_t pid) -{ - mach_port_t result; - IPC(ucsp_client_hostingPort(UCSP_ARGS, pid, &result)); - return result; -} - -SecGuestRef ClientSession::createGuest(SecGuestRef host, - uint32_t status, const char *path, const CssmData &cdhash, const CssmData &attributes, SecCSFlags flags) -{ - SecGuestRef newGuest; - IPC(ucsp_client_createGuest(UCSP_ARGS, host, status, path, DATA(cdhash), DATA(attributes), flags, &newGuest)); - if (flags & kSecCSDedicatedHost) { - secdebug("ssclient", "setting dedicated guest to 0x%x (was 0x%x)", - mDedicatedGuest, newGuest); - mDedicatedGuest = newGuest; - } - return newGuest; -} - -void ClientSession::setGuestStatus(SecGuestRef guest, uint32 status, const CssmData &attributes) -{ - IPC(ucsp_client_setGuestStatus(UCSP_ARGS, guest, status, DATA(attributes))); -} - -void ClientSession::removeGuest(SecGuestRef host, SecGuestRef guest) -{ - IPC(ucsp_client_removeGuest(UCSP_ARGS, host, guest)); -} - -void ClientSession::selectGuest(SecGuestRef newGuest) -{ - if (mDedicatedGuest) { - secdebug("ssclient", "ignoring selectGuest(0x%x) because dedicated guest=0x%x", - newGuest, mDedicatedGuest); - } else { - secdebug("ssclient", "switching to guest 0x%x", newGuest); - mGlobal().thread().currentGuest = newGuest; - } -} - -SecGuestRef ClientSession::selectedGuest() const -{ - if (mDedicatedGuest) - return mDedicatedGuest; - else - return mGlobal().thread().currentGuest; -} - - -} // end namespace SecurityServer -} // end namespace Security diff --git a/libsecurityd/libsecurityd.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/libsecurityd/libsecurityd.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index c9daec41..00000000 --- a/libsecurityd/libsecurityd.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 4C09A2920557240300FED7A3 - - primary - - - 4C31C2D9055341AA006D00BD - - primary - - - 4CA1FEBD052A3C8100F22E42 - - primary - - - 4CA1FEC8052A44A100F22E42 - - primary - - - C2A788530B7AA65B00CFF85C - - primary - - - - - diff --git a/libsecurityd/mig/mig.mk b/libsecurityd/mig/mig.mk deleted file mode 100644 index 9dabe93f..00000000 --- a/libsecurityd/mig/mig.mk +++ /dev/null @@ -1,61 +0,0 @@ -# -# Copyright (c) 2003-2004,2006-2007 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@ -# -# Makefile to build MIG-generated sources and headers -# -DERIVED_SRC = $(BUILT_PRODUCTS_DIR)/derived_src/securityd_client - -HDRS = $(DERIVED_SRC)/ucsp.h $(DERIVED_SRC)/ucspNotify.h $(DERIVED_SRC)/cshosting.h -SRCS = $(DERIVED_SRC)/ucspServer.cpp $(DERIVED_SRC)/ucspClient.cpp \ - $(DERIVED_SRC)/ucspClientC.c \ - $(DERIVED_SRC)/ucspNotifyReceiver.cpp $(DERIVED_SRC)/ucspNotifySender.cpp \ - $(DERIVED_SRC)/cshostingServer.cpp $(DERIVED_SRC)/cshostingClient.cpp -INCLUDES = $(PROJECT_DIR)/mig/ss_types.defs - -build: $(HDRS) $(SRCS) - -install: build - -installhdrs: $(HDRS) - -installsrc: - -clean: - rm -f $(HDRS) $(SRCS) - -$(DERIVED_SRC)/ucsp.h $(DERIVED_SRC)/ucspServer.cpp $(DERIVED_SRC)/ucspClient.cpp: $(PROJECT_DIR)/mig/ucsp.defs $(INCLUDES) - mkdir -p $(DERIVED_SRC) - mig -server $(DERIVED_SRC)/ucspServer.cpp -user $(DERIVED_SRC)/ucspClient.cpp \ - -header $(DERIVED_SRC)/ucsp.h $(PROJECT_DIR)/mig/ucsp.defs - -$(DERIVED_SRC)/ucspClientC.c: $(DERIVED_SRC)/ucspClient.cpp - cp $(DERIVED_SRC)/ucspClient.cpp $(DERIVED_SRC)/ucspClientC.c - -$(DERIVED_SRC)/ucspNotify.h $(DERIVED_SRC)/ucspNotifyReceiver.cpp $(DERIVED_SRC)/ucspNotifySender.cpp: $(PROJECT_DIR)/mig/ucspNotify.defs $(INCLUDES) - mkdir -p $(DERIVED_SRC) - mig -server $(DERIVED_SRC)/ucspNotifyReceiver.cpp -user $(DERIVED_SRC)/ucspNotifySender.cpp \ - -header $(DERIVED_SRC)/ucspNotify.h $(PROJECT_DIR)/mig/ucspNotify.defs - -$(DERIVED_SRC)/cshosting.h $(DERIVED_SRC)/cshostingServer.cpp $(DERIVED_SRC)/cshostingClient.cpp: $(PROJECT_DIR)/mig/cshosting.defs $(INCLUDES) - mkdir -p $(DERIVED_SRC) - mig -server $(DERIVED_SRC)/cshostingServer.cpp -user $(DERIVED_SRC)/cshostingClient.cpp \ - -header $(DERIVED_SRC)/cshosting.h $(PROJECT_DIR)/mig/cshosting.defs diff --git a/ntlm/NtlmGenerator.c b/ntlm/NtlmGenerator.c new file mode 100644 index 00000000..72db6c48 --- /dev/null +++ b/ntlm/NtlmGenerator.c @@ -0,0 +1,726 @@ +/* + * Copyright (c) 2000-2004,2006-2007,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@ + */ + +/* + * NtlmGenerator.c - NTLM client-side authentication engine. + * + * In the usual absence of documentation from Microsoft, the "inventors" of this + * protocol, this module was written using the superb revers engineering documented + * at + * + * http://davenport.sourceforge.net/ntlm.html#localAuthentication + */ + +#include "NtlmGenerator.h" +#include "ntlmBlobPriv.h" +#include + +#include +#include +#include +#include +#include + +/* + * For debugging using fixed server challenge and client nonce. + */ +#if DEBUG_FIXED_CHALLENGE + +/* these are "test vectors", effectively, from sourceforge */ +/* use pwd SecREt01, host/domain DOMAIN */ +static const unsigned char fixServerChallenge[8] = + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; +static const unsigned char fixClientNonce[8] = + { 0xff, 0xff, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44 }; + +static const unsigned char fixTargetInfo[] = { + 0x02, 0x00, 0x0c, 0x00, 0x44, 0x00, 0x4f, 0x00, + 0x4d, 0x00, 0x41, 0x00, 0x49, 0x00, 0x4e, 0x00, + 0x01, 0x00, 0x0c, 0x00, 0x53, 0x00, 0x45, 0x00, + 0x52, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, + 0x04, 0x00, 0x14, 0x00, 0x64, 0x00, 0x6f, 0x00, + 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, + 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, + 0x03, 0x00, 0x22, 0x00, 0x73, 0x00, 0x65, 0x00, + 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, + 0x2e, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x6d, 0x00, + 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2e, 0x00, + 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; +#endif + +/* app's NtlmGeneratorRef is a pointer to one of these */ +struct NtlmGenerator { + NLTM_Which mWhich; + NLTM_Which mNegotiatedVersion; + uint32_t mSentFlags; /* the flags we sent in first mst */ +}; + +static OSStatus _NtlmGeneratePasswordHashes( + CFAllocatorRef alloc, + NtlmGeneratorRef ntlm, + CFStringRef password, + CFDataRef* ntlmHash, + CFDataRef* lmHash); + +/* + * Validate type 2 message sent by the server; return interesting fields. + * NOTE we do not deal with the Context field here, which is only used + * for local authetication. + */ +static OSStatus ntlmParseServerChallenge( + CFDataRef serverBlob, + uint32_t *serverFlags, /* RETURNED */ + unsigned char *challenge, /* 8 bytes, mallocd by caller, RETURNED */ + unsigned char **targetName, /* mallocd and RETURNED */ + unsigned *targetNameLen, /* RETURNED */ + unsigned char **targetInfo, /* optionally mallocd and RETURNED */ + unsigned *targetInfoLen) /* optionally RETURNED */ +{ + unsigned minLength; + + *targetName = NULL; + *targetNameLen = 0; + *targetInfo = NULL; + *targetInfoLen = 0; + + if(serverBlob == NULL) { + return NTLM_ERR_PARSE_ERR; + } + + minLength = NTLM_SIGNATURE_LEN + + (unsigned)sizeof(uint32_t) + /* msg type */ + NTLM_SIZEOF_SEC_BUF + /* target name */ + (unsigned)sizeof(uint32_t) + /* flags */ + NTLM_CHALLENGE_LEN; + unsigned bufLen = (unsigned)CFDataGetLength(serverBlob); + if(bufLen < minLength) { + dprintf("ntlmParseServerChallenge: bad length\n"); + return NTLM_ERR_PARSE_ERR; + } + + /* do not even think of touching serverBlob after this */ + const unsigned char *cp = CFDataGetBytePtr(serverBlob); + + /* byte 0: signature */ + if(memcmp(cp, NTLM_SIGNATURE, NTLM_SIGNATURE_LEN)) { + dprintf("ntlmParseServerChallenge: signature mismatch\n"); + return NTLM_ERR_PARSE_ERR; + } + + const unsigned char *currCp = cp + NTLM_SIGNATURE_LEN; + + /* byte 8: message type */ + uint32_t msgType = OSReadLittleInt32(currCp, 0); + if(msgType != NTLM_MSG_MARKER_TYPE2) { + dprintf("ntlmParseServerChallenge: bad msg type\n"); + return NTLM_ERR_PARSE_ERR; + } + currCp += sizeof(uint32_t); + + /* byte 12: target name, security buffer */ + const unsigned char *sbData; + uint16_t sbLen; + OSStatus ortn = ntlmParseSecBuffer(currCp, cp, bufLen, &sbData, &sbLen); + if(ortn) { + return ortn; + } + *targetName = (unsigned char *)malloc(sbLen); + *targetNameLen = sbLen; + memmove(*targetName, sbData, sbLen); + currCp += NTLM_SIZEOF_SEC_BUF; + + /* byte 20: flags */ + *serverFlags = OSReadLittleInt32(currCp, 0); + currCp += sizeof(uint32_t); + + /* byte 24: challenge */ + #if DEBUG_FIXED_CHALLENGE + memmove(challenge, fixServerChallenge, NTLM_CHALLENGE_LEN); + #else + memmove(challenge, currCp, NTLM_CHALLENGE_LEN); + #endif + currCp += NTLM_CHALLENGE_LEN; + + /* remaining fields optional */ + const unsigned char *endOfBuf = cp + bufLen; + assert(endOfBuf >= currCp); + if(endOfBuf == currCp) { + return errSecSuccess; + } + + if(endOfBuf < (currCp + NTLM_SIZEOF_SEC_BUF)) { + /* not enough left for even one security buf; ignore */ + return errSecSuccess; + } + + /* byte 32: context: skip */ + currCp += NTLM_SIZEOF_SEC_BUF; + + if(endOfBuf < (currCp + NTLM_SIZEOF_SEC_BUF)) { + /* not enough left for target info security buf; ignore */ + return errSecSuccess; + } + + /* byte 40: target info */ + ortn = ntlmParseSecBuffer(currCp, cp, bufLen, &sbData, &sbLen); + if(ortn) { + free(*targetName); + *targetName = NULL; + return ortn; + } + #if DEBUG_FIXED_CHALLENGE + sbData = fixTargetInfo; + sbLen = sizeof(fixTargetInfo); + #endif /* DEBUG_FIXED_CHALLENGE */ + *targetInfo = (unsigned char *)malloc(sbLen); + *targetInfoLen = sbLen; + memmove(*targetInfo, sbData, sbLen); + return errSecSuccess; +} + +/* + * Create NTLMv2 responses (both NTLM and LM). + */ +static OSStatus ntlmGenerateNtlmV2Response( + /* from app */ + CFStringRef domain, + CFStringRef userName, + CFDataRef ntlmHash, + + /* from server */ + const unsigned char *serverChallenge, + const unsigned char *targetInfo, + unsigned targetInfoLen, + + /* returned */ + unsigned char *lmV2Response, // caller supplied, NTLM_LM_RESPONSE_LEN bytes + unsigned char **ntlmv2Response, // mallocd and RETURNED + unsigned *ntlmV2ResponseLen) // RETURNED +{ + /* Random challenge used in both responses */ + unsigned char challenge[NTLM_CLIENT_NONCE_LEN]; + #if DEBUG_FIXED_CHALLENGE + memmove(challenge, fixClientNonce, NTLM_CLIENT_NONCE_LEN); + #else + ntlmRand(NTLM_CLIENT_NONCE_LEN, challenge); + #endif + + /* NTLM password hash */ + unsigned char ntlmPwdHash[NTLM_DIGEST_LENGTH]; +// ntlmPasswordHash(password, ntlmPwdHash); + memmove(ntlmPwdHash, CFDataGetBytePtr(ntlmHash), sizeof(ntlmPwdHash)); + + /* uppercase(userName | domain) */ + CFMutableStringRef userDomain = CFStringCreateMutableCopy(NULL, 0, userName); + if(domain != NULL) { + CFStringAppend(userDomain, domain); + } + CFStringUppercase(userDomain, NULL); + + /* declare some locals prior to any gotos */ + unsigned char *ucode = NULL; + unsigned ucodeLen; + unsigned char ntlmV2Hash[NTLM_DIGEST_LENGTH]; + unsigned char macText2[NTLM_CHALLENGE_LEN + NTLM_CLIENT_NONCE_LEN]; + unsigned char challengeMac[NTLM_DIGEST_LENGTH]; + unsigned char blobMac[NTLM_DIGEST_LENGTH]; + unsigned char *ntlmv2Resp = NULL; + CFMutableDataRef ntlmV2Blob = NULL; + CFMutableDataRef catBlob = NULL; + unsigned ntlmV2BlobLen; + unsigned char blobSig[4] = {0x01, 0x01, 0x00, 0x00}; + + /* HMAC(passwordHash, uppercase(userName | domain)) */ + ntlmStringToLE(userDomain, &ucode, &ucodeLen); + OSStatus ortn = ntlmHmacMD5(ntlmPwdHash, NTLM_DIGEST_LENGTH, + ucode, ucodeLen, ntlmV2Hash); + if(ortn) { + goto errOut; + } + + /* HMAC(ntlmV2Hash, serverChallenge | clientChallenge) */ + memmove(macText2, serverChallenge, NTLM_CHALLENGE_LEN); + memmove(macText2 + NTLM_CHALLENGE_LEN, challenge, NTLM_CLIENT_NONCE_LEN); + ortn = ntlmHmacMD5(ntlmV2Hash, NTLM_DIGEST_LENGTH, + macText2, NTLM_CHALLENGE_LEN + NTLM_CLIENT_NONCE_LEN, challengeMac); + if(ortn) { + goto errOut; + } + + /* LMv2 response := challengeMac | clientChallenge */ + memmove(lmV2Response, challengeMac, NTLM_DIGEST_LENGTH); + memmove(lmV2Response + NTLM_DIGEST_LENGTH, challenge, NTLM_CLIENT_NONCE_LEN); + + /* Prepare the NTLMv2 'blob' */ + ntlmV2Blob = CFDataCreateMutable(NULL, 0); + + /* 0: 0x01010000 */ + CFDataAppendBytes(ntlmV2Blob, blobSig, 4); + /* 4: reserved, zeroes */ + appendUint32(ntlmV2Blob, 0); + /* 8: Timestamp */ + ntlmAppendTimestamp(ntlmV2Blob); + /* 16: client challenge */ + CFDataAppendBytes(ntlmV2Blob, challenge, NTLM_CLIENT_NONCE_LEN); + /* 24: unknown, zeroes */ + appendUint32(ntlmV2Blob, 0); + /* 28: target info from server */ + CFDataAppendBytes(ntlmV2Blob, targetInfo, targetInfoLen); + /* *: unknown, zeroes */ + appendUint32(ntlmV2Blob, 0); + + /* keep that blob; it'll go directly into the response. Now cook up + * another one, the concatentation of the server challenge with the + * ntlmV2Blob */ + ntlmV2BlobLen = (unsigned)CFDataGetLength(ntlmV2Blob); + catBlob = CFDataCreateMutable(NULL, 0); + CFDataAppendBytes(catBlob, serverChallenge, NTLM_CHALLENGE_LEN); + CFDataAppendBytes(catBlob, CFDataGetBytePtr(ntlmV2Blob), ntlmV2BlobLen); + + /* HMAC(ntlmV2Hash, serverChallenge | blob) */ + ortn = ntlmHmacMD5(ntlmV2Hash, NTLM_DIGEST_LENGTH, + CFDataGetBytePtr(catBlob), (unsigned)CFDataGetLength(catBlob), + blobMac); + if(ortn) { + goto errOut; + } + + /* Finally, NTLMv2 response := (blobMac | ntlmV2Blob) */ + ntlmv2Resp = (unsigned char *)malloc(NTLM_DIGEST_LENGTH + ntlmV2BlobLen); + memmove(ntlmv2Resp, blobMac, NTLM_DIGEST_LENGTH); + memmove(ntlmv2Resp + NTLM_DIGEST_LENGTH, CFDataGetBytePtr(ntlmV2Blob), ntlmV2BlobLen); + *ntlmv2Response = ntlmv2Resp; + *ntlmV2ResponseLen = NTLM_DIGEST_LENGTH + ntlmV2BlobLen; + ortn = errSecSuccess; +errOut: + if(userDomain) { + CFRelease(userDomain); + } + if(ntlmV2Blob) { + CFRelease(ntlmV2Blob); + } + if(catBlob) { + CFRelease(catBlob); + } + CFREE(ucode); + return ortn; +} + +/* + * Create/release NtlmGenerator objects. + */ +OSStatus NtlmGeneratorCreate( + NLTM_Which which, + NtlmGeneratorRef *ntlmGen) /* RETURNED */ +{ + struct NtlmGenerator *gen = + (struct NtlmGenerator *)malloc(sizeof(struct NtlmGenerator)); + if(gen == NULL) { + return errSecAllocate; + } + gen->mWhich = which; + gen->mNegotiatedVersion = 0; /* i.e., unknown */ + gen->mSentFlags = 0; + *ntlmGen = gen; + return errSecSuccess; +} + +void NtlmGeneratorRelease( + NtlmGeneratorRef ntlmGen) +{ + if(ntlmGen == NULL) { + return; + } + free(ntlmGen); +} + +OSStatus NtlmCreateClientRequest( + NtlmGeneratorRef ntlmGen, + CFDataRef *clientRequest) /* RETURNED */ +{ + CFMutableDataRef req = CFDataCreateMutable(NULL, 0); + if(req == NULL) { + return errSecAllocate; + } + /* byte 0: signature, NULL terminated */ + CFDataAppendBytes(req, (UInt8 *)NTLM_SIGNATURE, NTLM_SIGNATURE_LEN); + + /* byte 8: message type */ + appendUint32(req, NTLM_MSG_MARKER_TYPE1); + + /* byte 12: the standard flags we send - we're wide open to all types */ + /* FIXME isn't there a way to tell the server we support NTLMv2? */ + ntlmGen->mSentFlags = NTLM_NegotiateUnicode | + NTLM_NegotiateOEM | + NTLM_RequestTarget | + NTLM_NegotiateNTLM | + NTLM_AlwaysSign; + if(ntlmGen->mWhich & NW_NTLM2) { + ntlmGen->mSentFlags |= NTLM_NegotiateNTLM2Key; + } + appendUint32(req, ntlmGen->mSentFlags); + + /* byte 16: optional supplied domain: not needed */ + CFIndex dex; + appendSecBuf(req, 0, &dex); + + /* byte 24: optional supplied workstation: not needed */ + appendSecBuf(req, 0, &dex); + + *clientRequest = req; + return errSecSuccess; +} + +/* + * The meat & potatoes: given a server type 2 message, cook up a type 3 response. + */ +OSStatus NtlmCreateClientResponse( + NtlmGeneratorRef ntlmGen, + CFDataRef serverBlob, + CFStringRef domain, /* optional */ + CFStringRef userName, + CFStringRef password, + CFDataRef *clientResponse) /* RETURNED */ +{ + CFDataRef ntlmHash = NULL; + CFDataRef lmHash = NULL; + OSStatus result = _NtlmGeneratePasswordHashes(kCFAllocatorDefault, ntlmGen, password, &ntlmHash, &lmHash); + + if (result == errSecSuccess) { + + result = _NtlmCreateClientResponse(ntlmGen, serverBlob, domain, userName, ntlmHash, lmHash, clientResponse); + } + + if (ntlmHash) + CFRelease(ntlmHash); + + if (lmHash) + CFRelease(lmHash); + + return result; +} + +OSStatus _NtlmCreateClientResponse( + NtlmGeneratorRef ntlmGen, + CFDataRef serverBlob, + CFStringRef domain, /* optional */ + CFStringRef userName, + CFDataRef ntlmHash, + CFDataRef lmHash, + CFDataRef *clientResponse) /* RETURNED */ +{ + OSStatus ortn; + uint32_t serverFlags; + unsigned char serverChallenge[NTLM_CHALLENGE_LEN]; + unsigned char *targetName = NULL; + unsigned targetNameLen = 0; + unsigned char *targetInfo = NULL; + unsigned targetInfoLen = 0; + CFIndex lmRespOffset; + unsigned char lmResp[NTLM_LM_RESPONSE_LEN]; + CFIndex ntlmRespOffset; + unsigned char ntlmResp[NTLM_LM_RESPONSE_LEN]; + unsigned char *ntlmResponsePtr = NULL; + unsigned ntlmResponseLen = 0; + unsigned char *domainNameFlat = NULL; + unsigned domainNameFlatLen = 0; + CFIndex domainNameOffset; + unsigned char *userNameFlat = NULL; + unsigned userNameFlatLen = 0; + CFIndex userNameOffset; + unsigned char *workstationName = NULL; + unsigned workstationNameLen = 0; + CFIndex workstationNameOffset; + CFIndex nullDex; + unsigned char pwdHash[NTLM_DIGEST_LENGTH]; + + ortn = ntlmParseServerChallenge(serverBlob, &serverFlags, serverChallenge, + &targetName, &targetNameLen, + &targetInfo, &targetInfoLen); + if(ortn) { + return ortn; + } + /* subsequent errors to errOut: */ + + /* gather negotiated parameters */ + bool lm2Key = (serverFlags & NTLM_NegotiateNTLM2Key) ? true : false; + bool unicode = (serverFlags & NTLM_NegotiateUnicode) ? true : false; + /* any others? */ + + CFMutableDataRef clientBuf = CFDataCreateMutable(NULL, 0); + if(clientBuf == NULL) { + ortn = errSecAllocate; + goto errOut; + } + + if (domain) { + domain = CFStringCreateMutableCopy(NULL, 0, domain); + if (domain) + CFStringUppercase((CFMutableStringRef)domain, NULL); + else { + ortn = errSecAllocate; + goto errOut; + } + } + + /* byte 0: signature, NULL terminated */ + CFDataAppendBytes(clientBuf, (UInt8 *)NTLM_SIGNATURE, NTLM_SIGNATURE_LEN); + + /* byte 8: message type */ + appendUint32(clientBuf, NTLM_MSG_MARKER_TYPE3); + + /* LM and NTLM responses */ + if( (targetInfo != NULL) && // server is NTLMv2 capable + (targetInfoLen != 0) && // ditto + (serverFlags & NTLM_NegotiateTargetInfo) && // ditto + (ntlmGen->mWhich & NW_NTLMv2) ) { // ...and we are + /* + * NTLMv2 + */ + ortn = ntlmGenerateNtlmV2Response(domain, userName, ntlmHash, + serverChallenge, targetInfo, targetInfoLen, + lmResp, &ntlmResponsePtr, &ntlmResponseLen); + if(ortn) { + goto errOut; + } + + /* + * Write security buffers. + * + * byte 12: LM response + * byte 20: NTLM response + */ + appendSecBuf(clientBuf, NTLM_LM_RESPONSE_LEN, &lmRespOffset); + appendSecBuf(clientBuf, ntlmResponseLen, &ntlmRespOffset); + ntlmGen->mNegotiatedVersion = NW_NTLMv2; + } + else { + if(lm2Key && (ntlmGen->mWhich & NW_NTLM2)) { + /* LM response: 8 random bytes, rest zeroes */ + #if DEBUG_FIXED_CHALLENGE + memmove(lmResp, fixClientNonce, NTLM_CLIENT_NONCE_LEN); + #else + ntlmRand(NTLM_CLIENT_NONCE_LEN, lmResp); + #endif + memset(lmResp + NTLM_CLIENT_NONCE_LEN, 0, + NTLM_LM_RESPONSE_LEN - NTLM_CLIENT_NONCE_LEN); + + /* session nonce: server challenge | client nonce */ + unsigned char sessionNonce[NTLM_CHALLENGE_LEN + NTLM_CLIENT_NONCE_LEN]; + memmove(sessionNonce, serverChallenge, NTLM_CHALLENGE_LEN); + memmove(sessionNonce + NTLM_CHALLENGE_LEN, lmResp, NTLM_CLIENT_NONCE_LEN); + + /* NTLM2 session hash: the first 8 bytes of MD5(sessionNonce) */ + unsigned char sessionHash[NTLM_DIGEST_LENGTH]; + md5Hash(sessionNonce, NTLM_CHALLENGE_LEN + NTLM_CLIENT_NONCE_LEN, sessionHash); + + /* standard password hash */ +// ntlmPasswordHash(password, pwdHash); + memmove(pwdHash, CFDataGetBytePtr(ntlmHash), sizeof(pwdHash)); + + /* NTLM response: DES with three different keys */ + ortn = ntlmResponse(pwdHash, sessionHash, ntlmResp); + if(ortn) { + dprintf("***Error on ntlmResponse (3)\n"); + goto errOut; + } + ntlmGen->mNegotiatedVersion = NW_NTLM2; + } + else if(ntlmGen->mWhich & NW_NTLM1) { + /* + * LM response - the old style 2-DES "password hash" applied + * the the server's challenge + */ +// ortn = lmPasswordHash(password, pwdHash); +// if(ortn) { +// dprintf("***Error on lmPasswordHash\n"); +// goto errOut; +// } + memmove(pwdHash, CFDataGetBytePtr(lmHash), sizeof(pwdHash)); + + ortn = ntlmResponse(pwdHash, serverChallenge, lmResp); + if(ortn) { + dprintf("***Error on ntlmResponse (1)\n"); + goto errOut; + } + + /* + * NTLM response: md4 password hash, DES with three different keys + */ +// ntlmPasswordHash(password, pwdHash); + memmove(pwdHash, CFDataGetBytePtr(ntlmHash), sizeof(pwdHash)); + + ortn = ntlmResponse(pwdHash, serverChallenge, ntlmResp); + if(ortn) { + dprintf("***Error on ntlmResponse (2)\n"); + goto errOut; + } + ntlmGen->mNegotiatedVersion = NW_NTLM1; + } + else { + dprintf("***NTLM protocol mismatch\n"); + ortn = NTLM_ERR_PROTOCOL_MISMATCH; + goto errOut; + + } + + /* + * Write security buffers. + * + * byte 12: LM response + * byte 20: NTLM response + */ + appendSecBuf(clientBuf, NTLM_LM_RESPONSE_LEN, &lmRespOffset); + appendSecBuf(clientBuf, NTLM_LM_RESPONSE_LEN, &ntlmRespOffset); + ntlmResponsePtr = ntlmResp; + ntlmResponseLen = NTLM_LM_RESPONSE_LEN; + } /* not NTLMv2 */ + + /* + * convert domain and user as appropriate + * byte 28: domain (server) name + */ + if(domain != NULL) { + ortn = ntlmStringFlatten(domain, unicode, &domainNameFlat, &domainNameFlatLen); + if(ortn) { + dprintf("createClientResponse: error converting domain name\n"); + ortn = NTLM_ERR_PARSE_ERR; + goto errOut; + } + } + appendSecBuf(clientBuf, domainNameFlatLen, &domainNameOffset); + + /* byte 36: user name */ + ortn = ntlmStringFlatten(userName, unicode, &userNameFlat, &userNameFlatLen); + if(ortn) { + dprintf("createClientResponse: error converting user name\n"); + ortn = NTLM_ERR_PARSE_ERR; + goto errOut; + } + appendSecBuf(clientBuf, userNameFlatLen, &userNameOffset); + + /* byte 44: hostname */ + ortn = ntlmHostName(unicode, &workstationName, &workstationNameLen); + if(ortn) { + dprintf("createClientResponse: error getting host name\n"); + goto errOut; + } + appendSecBuf(clientBuf, workstationNameLen, &workstationNameOffset); + + /* byte 52: session key (whatever that is): optional, empty here */ + appendSecBuf(clientBuf, 0, &nullDex); + + /* byte 60: negotiated flags */ + appendUint32(clientBuf, ntlmGen->mSentFlags & serverFlags); + + /* finally, the data associated with the security buffers */ + secBufOffset(clientBuf, lmRespOffset); + CFDataAppendBytes(clientBuf, lmResp, NTLM_LM_RESPONSE_LEN); + + secBufOffset(clientBuf, ntlmRespOffset); + CFDataAppendBytes(clientBuf, ntlmResponsePtr, ntlmResponseLen); + + if(domain != NULL) { + secBufOffset(clientBuf, domainNameOffset); + CFDataAppendBytes(clientBuf, domainNameFlat, domainNameFlatLen); + } + + secBufOffset(clientBuf, userNameOffset); + CFDataAppendBytes(clientBuf, userNameFlat, userNameFlatLen); + + secBufOffset(clientBuf, workstationNameOffset); + CFDataAppendBytes(clientBuf, workstationName, workstationNameLen); + +errOut: + CFREE(targetName); + CFREE(targetInfo); + CFREE(domainNameFlat); + CFREE(userNameFlat); + CFREE(workstationName); + if (domain) CFRelease(domain); + if(ntlmResponsePtr != ntlmResp) { + /* i.e., it was mallocd by ntlmGenerateNtlmV2Response */ + CFREE(ntlmResponsePtr); + } + if(ortn == errSecSuccess) { + *clientResponse = clientBuf; + } + else { + if (clientBuf) + CFRelease(clientBuf); + } + return ortn; +} + +/* replacement for NtlmNegotiatedNtlm2: returns NW_NTLM1Only, NW_NTLM2Only, + * or NW_NTLMv2Only */ +NLTM_Which NtlmGetNegotiatedVersion( + NtlmGeneratorRef ntlmGen) +{ + return ntlmGen->mNegotiatedVersion; +} + +OSStatus _NtlmGeneratePasswordHashes( + CFAllocatorRef alloc, + NtlmGeneratorRef ntlm, + CFStringRef password, + CFDataRef* ntlmHash, + CFDataRef* lmHash) +{ + OSStatus result = errSecSuccess; + unsigned char hash[NTLM_DIGEST_LENGTH]; + + ntlmPasswordHash(password, hash); + + *ntlmHash = CFDataCreate(alloc, hash, sizeof(hash)); + + result = lmPasswordHash(password, hash); + + if (result == errSecSuccess) + *lmHash = CFDataCreate(alloc, hash, sizeof(hash)); + + return result; +} + +OSStatus NtlmGeneratePasswordHashes( + CFAllocatorRef alloc, + CFStringRef password, + CFDataRef* ntlmHash, + CFDataRef* lmHash) +{ + NtlmGeneratorRef ntlm = NULL; + + OSStatus result = NtlmGeneratorCreate(NW_Any, &ntlm); + + if (result == errSecSuccess) { + result = _NtlmGeneratePasswordHashes(alloc, ntlm, password, ntlmHash, lmHash); + } + + if (ntlm) + NtlmGeneratorRelease(ntlm); + + return result; +} + diff --git a/ntlm/NtlmGenerator.h b/ntlm/NtlmGenerator.h new file mode 100644 index 00000000..febce174 --- /dev/null +++ b/ntlm/NtlmGenerator.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2000-2004,2006-2007 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 _NTLM_GENERATOR_H_ +#define _NTLM_GENERATOR_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This interface provides the capability to generate and parse the authentication + * blobs which pass back and forth between a client and a server during NTLM + * authentication. Only the client side is implemented. + * + * All three variants of NTLM authentication are performed: NTLM1, NTLM2, and + * NTLMv2. + * + * In general, to use this stuff for HTTP authentication: + * + * 1. Determine that NTLM authentication is possible. Drop the connection + * to the server if you have a persistent connection open; MS servers + * require a clean unused connection for this negotiation to occur. + * + * 2. Create a NtlmGeneratorRef object, specifying possible restrictions + * on negotiation version. + * + * 3. Create the client authentication blob using NtlmCreateClientRequest() + * and send it to the server, base64 encoded, in a "Authorization: NTLM" + * header line. + * + * 4. The server should send back another 401 status, with its own blob in + * a "WWW-Authenticate: NTLM" header. + * + * 5. Base64 decode that blob and feed it into NtlmCreateClientResponse(), the + * output of which is another blob which you send to the server again in + * a "WWW-Authenticate: NTLM" header. + * + * 6. If you're lucky the server will give a 200 status (or something else useful + * other than 401) and you're done. + * + * 7. Free the NtlmGeneratorRef object with NtlmGeneratorRelease(). + */ + +/* + * Opaque reference to an NTLM blob generator object. + */ +typedef struct NtlmGenerator *NtlmGeneratorRef; + +/* + * Which versions of the protocol are acceptable? + */ +enum { + NW_NTLM1 = 0x00000001, + NW_NTLM2 = 0x00000002, + NW_NTLMv2 = 0x00000004, + + // all variants enabled, preferring NTLMv2, then NTLM2, then NTLM1 + NW_Any = NW_NTLM1 | NW_NTLM2 | NW_NTLMv2 +}; +typedef uint32_t NLTM_Which; + + +/* Create/release NtlmGenerator objects.*/ +OSStatus NtlmGeneratorCreate( + NLTM_Which which, + NtlmGeneratorRef *ntlmGen); /* RETURNED */ + +void NtlmGeneratorRelease( + NtlmGeneratorRef ntlmGen); + +/* create the initial client request */ +OSStatus NtlmCreateClientRequest( + NtlmGeneratorRef ntlmGen, + CFDataRef *clientRequest); /* RETURNED */ + +/* parse server challenge and respond to it */ +OSStatus NtlmCreateClientResponse( + NtlmGeneratorRef ntlmGen, + CFDataRef serverBlob, /* obtained from the server */ + CFStringRef domain, /* server domain, appears to be optional */ + CFStringRef userName, + CFStringRef password, + CFDataRef *clientResponse); /* RETURNED */ + +/* which version did we negotiate? */ +NLTM_Which NtlmGetNegotiatedVersion( + NtlmGeneratorRef ntlmGen); + +OSStatus NtlmGeneratePasswordHashes( + CFAllocatorRef alloc, + CFStringRef password, + CFDataRef* ntlmHash, + CFDataRef* lmHash); + +OSStatus _NtlmCreateClientResponse( + NtlmGeneratorRef ntlmGen, + CFDataRef serverBlob, + CFStringRef domain, /* optional */ + CFStringRef userName, + CFDataRef ntlmHash, + CFDataRef lmHash, + CFDataRef *clientResponse); /* RETURNED */ + +#ifdef __cplusplus +} +#endif + +#endif /* _NTLM_GENERATOR_H_ */ diff --git a/ntlm/ntlmBlobPriv.c b/ntlm/ntlmBlobPriv.c new file mode 100644 index 00000000..f6b221c6 --- /dev/null +++ b/ntlm/ntlmBlobPriv.c @@ -0,0 +1,499 @@ +/* + * Copyright (c) 2000-2004,2006-2008,2010-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * ntlmBlobPriv.c - Private routines used by NtlmGenerator module. + */ + +#include "ntlmBlobPriv.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if DEBUG_FIXED_CHALLENGE +/* Fixed 64-bit timestamp for sourceforge test vectors */ +static unsigned char dbgStamp[] = +{ + 0x00, 0x90, 0xd3, 0x36, 0xb7, 0x34, 0xc3, 0x01 +}; +#endif /* DEBUG_FIXED_CHALLENGE */ + +// MARK: - +// MARK: Encode/Decode Routines + +/* write a 64-bit word, little endian */ +void appendUint64( + CFMutableDataRef buf, + uint64_t word) +{ +#if 1 + unsigned char cb[8]; + OSWriteLittleInt64(cb, 0, word); + CFDataAppendBytes(buf, cb, 8); +#else + /* This is an alternate implementation which may or may not be faster than + the above. */ + CFIndex offset = CFDataGetLength(buf); + UInt8 *bytes = CFDataGetMutableBytePtr(buf); + CFDataIncreaseLength(buf, 8); + OSWriteLittleInt64(bytes, offset, word); +#endif +} + +/* write a 32-bit word, little endian */ +void appendUint32( + CFMutableDataRef buf, + uint32_t word) +{ +#if 1 + unsigned char cb[4]; + OSWriteLittleInt32(cb, 0, word); + CFDataAppendBytes(buf, cb, 4); +#else + /* This is an alternate implementation which may or may not be faster than + the above. */ + CFIndex offset = CFDataGetLength(buf); + UInt8 *bytes = CFDataGetMutableBytePtr(buf); + CFDataIncreaseLength(buf, 4); + OSWriteLittleInt32(bytes, offset, word); +#endif +} + +/* write a 16-bit word, little endian */ +void appendUint16( + CFMutableDataRef buf, + uint16_t word) +{ + unsigned char cb[2]; + OSWriteLittleInt16(cb, 0, word); + CFDataAppendBytes(buf, cb, 2); +} + +/* + * Write a security buffer, providing the index into the CFData at which + * this security buffer's offset is located. Just before the actual data is written, + * go back and update the offset with the start of that data using secBufOffset(). + */ +void appendSecBuf( + CFMutableDataRef buf, + uint16_t len, + CFIndex *offsetIndex) +{ +#if 1 + unsigned char cb[8]; + OSWriteLittleInt16(cb, 0, len); /* buffer length */ + OSWriteLittleInt16(cb, 2, len); /* buffer allocated size */ + OSWriteLittleInt32(cb, 4, 0); /* offset is empty for now */ + CFDataAppendBytes(buf, cb, 8); + *offsetIndex = CFDataGetLength(buf) - 4; /* offset will go here */ +#else + appendUint16(buf, len); /* buffer length */ + appendUint16(buf, len); /* buffer allocated size */ + *offsetIndex = CFDataGetLength(buf); /* offset will go here */ + appendUint32(buf, 0); /* but it's empty for now */ +#endif +} + +/* + * Update a security buffer's offset to be the current end of data in a CFData. + */ +void secBufOffset( + CFMutableDataRef buf, + CFIndex offsetIndex) /* obtained from appendSecBuf() */ +{ + CFIndex currPos = CFDataGetLength(buf); + unsigned char cb[4]; + OSWriteLittleInt32(cb, 0, (uint32_t)currPos); + CFRange range = {offsetIndex, 4}; + CFDataReplaceBytes(buf, range, cb, 4); +} + +/* + * Parse/validate a security buffer. Verifies that supplied offset/length don't go + * past end of avaialble data. Returns ptr to actual data and its length. Returns + * NTLM_ERR_PARSE_ERR on bogus values. + */ +OSStatus ntlmParseSecBuffer( + const unsigned char *cp, /* start of security buffer */ + const unsigned char *bufStart, /* start of whole msg buffer */ + unsigned bufLen, /* # of valid bytes starting at bufStart */ + const unsigned char **data, /* RETURNED, start of actual data */ + uint16_t *dataLen) /* RETURNED, length of actual data */ +{ + assert(cp >= bufStart); + + uint16_t secBufLen = OSReadLittleInt16(cp, 0); + /* skip length we just parsed plus alloc size, which we don't use */ + cp += 4; + uint32_t offset = OSReadLittleInt32(cp, 0); + if((offset + secBufLen) > bufLen) { + dprintf("ntlmParseSecBuffer: buf overflow\n"); + return NTLM_ERR_PARSE_ERR; + } + *data = bufStart + offset; + *dataLen = secBufLen; + return errSecSuccess; +} + +// MARK: - +// MARK: CFString Converters + +/* + * Convert CFString to little-endian unicode. + */ +void ntlmStringToLE( + CFStringRef pwd, + unsigned char **ucode, // mallocd and RETURNED + unsigned *ucodeLen) // RETURNED +{ + CFIndex len = CFStringGetLength(pwd); + unsigned char *data = (unsigned char *)malloc(len * 2); + unsigned char *cp = data; + + CFIndex dex; + for(dex=0; dex> 8; + } + *ucode = data; + *ucodeLen = (unsigned)(len * 2); +} + +/* + * Convert a CFStringRef into a mallocd array of chars suitable for the specified + * encoding. This might return an error if the string can't be converted + * appropriately. + */ +OSStatus ntlmStringFlatten( + CFStringRef str, + bool unicode, + unsigned char **flat, // mallocd and RETURNED + unsigned *flatLen) // RETURNED +{ + if(unicode) { + /* convert to little-endian unicode */ + ntlmStringToLE(str, flat, flatLen); + return errSecSuccess; + } + else { + /* convert to ASCII C string */ + CFIndex strLen = CFStringGetLength(str); + char *cStr = (char *)malloc(strLen + 1); + if(cStr == NULL) { + return errSecAllocate; + } + if(CFStringGetCString(str, cStr, strLen + 1, kCFStringEncodingASCII)) { + *flat = (unsigned char *)cStr; + *flatLen = (unsigned)strLen; + return errSecSuccess; + } + + /* + * Well that didn't work. Try UTF8 - I don't know how a MS would behave if + * this portion of auth (only used for the LM response) didn't work. + */ + dprintf("lmPasswordHash: ASCII password conversion failed; trying UTF8\n"); + free(cStr); + cStr = (char *)malloc(strLen * 4); + if(cStr == NULL) { + return errSecAllocate; + } + if(CFStringCreateExternalRepresentation(NULL, str, kCFStringEncodingUTF8, 0)) { + *flat = (unsigned char *)cStr; + *flatLen = (unsigned)strLen; + return errSecSuccess; + } + dprintf("lmPasswordHash: UTF8 password conversion failed\n"); + free(cStr); + return NTLM_ERR_PARSE_ERR; + } +} + +// MARK: - +// MARK: Machine Dependent Cruft + +/* random number generator */ +void ntlmRand( + unsigned len, + void *buf) /* allocated by caller, random data RETURNED */ +{ + SecRandomCopyBytes(kSecRandomDefault, len, buf); +} + +/* Obtain host name in appropriate encoding */ +OSStatus ntlmHostName( + bool unicode, + unsigned char **flat, // mallocd and RETURNED + unsigned *flatLen) // RETURNED +{ + char hostname[MAXHOSTNAMELEN]; + if(gethostname(hostname, MAXHOSTNAMELEN)) { + #ifndef NDEBUG + perror("gethostname"); + #endif + return errSecInternalComponent; + } + size_t len = strlen(hostname); + if(unicode) { + /* quickie "little endian unicode" conversion */ + *flat = (unsigned char *)malloc(len * 2); + unsigned char *cp = *flat; + size_t dex; + for(dex=0; dex> 1)) & 0xfe; + outKey[2] = ((inKey[1] << 6) | (inKey[2] >> 2)) & 0xfe; + outKey[3] = ((inKey[2] << 5) | (inKey[3] >> 3)) & 0xfe; + outKey[4] = ((inKey[3] << 4) | (inKey[4] >> 4)) & 0xfe; + outKey[5] = ((inKey[4] << 3) | (inKey[5] >> 5)) & 0xfe; + outKey[6] = ((inKey[5] << 2) | (inKey[6] >> 6)) & 0xfe; + outKey[7] = (inKey[6] << 1) & 0xfe; +} + +/* + * single block DES encrypt. + * This would really benefit from a DES implementation in CommonCrypto. + */ +OSStatus ntlmDesCrypt( + const unsigned char *key, // 8 bytes + const unsigned char *inData, // 8 bytes + unsigned char *outData) // 8 bytes +{ + size_t data_moved; + return CCCrypt(kCCEncrypt, kCCAlgorithmDES, 0, key, kCCKeySizeDES, + NULL /*no iv, 1 block*/, inData, 1 * kCCBlockSizeDES, outData, + 1 * kCCBlockSizeDES, &data_moved); +} + +/* + * HMAC/MD5. + */ +OSStatus ntlmHmacMD5( + const unsigned char *key, + unsigned keyLen, + const unsigned char *inData, + unsigned inDataLen, + unsigned char *mac) // caller provided, NTLM_DIGEST_LENGTH +{ + CCHmacContext hmac_md5_context; + + CCHmacInit(&hmac_md5_context, kCCHmacAlgMD5, key, keyLen); + CCHmacUpdate(&hmac_md5_context, inData, inDataLen); + CCHmacFinal(&hmac_md5_context, mac); + + return 0; +} + +// MARK: - +// MARK: LM and NTLM password and digest munging + +/* + * Calculate LM-style password hash. This really only works if the password + * is convertible to ASCII (that is, it will indeed return an error if that + * is not true). + * + * This is the most gawdawful constant I've ever seen in security-related code. + */ +static const unsigned char lmHashPlaintext[] = {'K', 'G', 'S', '!', '@', '#', '$', '%'}; + +OSStatus lmPasswordHash( + CFStringRef pwd, + unsigned char *digest) // caller-supplied, NTLM_DIGEST_LENGTH +{ + /* convert to ASCII */ + unsigned strLen; + unsigned char *cStr; + OSStatus ortn; + ortn = ntlmStringFlatten(pwd, false, &cStr, &strLen); + if(ortn) { + dprintf("lmPasswordHash: ASCII password conversion failed\n"); + return ortn; + } + + /* truncate/pad to 14 bytes and convert to upper case */ + unsigned char pwdFix[NTLM_LM_PASSWORD_LEN]; + unsigned toMove = NTLM_LM_PASSWORD_LEN; + if(strLen < NTLM_LM_PASSWORD_LEN) { + toMove = strLen; + } + memmove(pwdFix, cStr, toMove); + free(cStr); + unsigned dex; + for(dex=0; dex +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef NDEBUG + +#include + +#define dprintf(args...) printf(args) +#else +#define dprintf(args...) +#endif + +/* + * Common error returns. + * + * This one for "I don't understand the server blob". + */ +#define NTLM_ERR_PARSE_ERR errSecParam + +/* + * This one for protocol variant mismatch (e.g., app requires NTLMv2 but server + * doesn't accept that). + */ +#define NTLM_ERR_PROTOCOL_MISMATCH errSecAuthFailed + +/* + * For debugging using fixed pamaters via sourceforge "test vectors". + */ +#define DEBUG_FIXED_CHALLENGE 0 + +/* handy portable NULL-tolerant free() */ +#define CFREE(p) if(p != NULL) { free(p); } + +#define NTLM_SIGNATURE "NTLMSSP" +#define NTLM_SIGNATURE_LEN 8 /* including NULL! */ + +#define NTLM_MSG_MARKER_TYPE1 1 /* first client msg */ +#define NTLM_MSG_MARKER_TYPE2 2 /* server challenge */ +#define NTLM_MSG_MARKER_TYPE3 3 /* client response */ + +/* Size of a security buffer */ +#define NTLM_SIZEOF_SEC_BUF (sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t)) + +/* length of server challenge in bytes */ +#define NTLM_CHALLENGE_LEN 8 + +/* length of client nonce in bytes */ +#define NTLM_CLIENT_NONCE_LEN 8 + +/* length of LM and NTLM responses */ +#define NTLM_LM_RESPONSE_LEN 24 + +/* foreced length of LM-style uppper case password */ +#define NTLM_LM_PASSWORD_LEN 14 + +/* + * Flags - defined here in native endianness; sent over the wire little-endian + */ +#define NTLM_NegotiateUnicode 0x00000001 +#define NTLM_NegotiateOEM 0x00000002 +#define NTLM_RequestTarget 0x00000004 +#define NTLM_Unknown1 0x00000008 +#define NTLM_NegotiateSign 0x00000010 +#define NTLM_NegotiateSeal 0x00000020 +#define NTLM_NegotiateDatagram 0x00000040 +#define NTLM_NegotiateLMKey 0x00000080 +#define NTLM_NegotiateNetware 0x00000100 +#define NTLM_NegotiateNTLM 0x00000200 +#define NTLM_Unknown2 0x00000400 +#define NTLM_Unknown3 0x00000800 +#define NTLM_DomainSupplied 0x00001000 +#define NTLM_WorkstationSupplies 0x00002000 +#define NTLM_LocalCall 0x00004000 +#define NTLM_AlwaysSign 0x00008000 +#define NTLM_TargetTypeDomain 0x00010000 +#define NTLM_TargetTypeServer 0x00020000 +#define NTLM_TargetTypeShare 0x00040000 +#define NTLM_NegotiateNTLM2Key 0x00080000 +#define NTLM_RequestInitResp 0x00100000 +#define NTLM_RequestAcceptResp 0x00200000 +#define NTLM_RequestNonNTSessionKey 0x00400000 +#define NTLM_NegotiateTargetInfo 0x00800000 +#define NTLM_Unknown4 0x01000000 +#define NTLM_Unknown5 0x02000000 +#define NTLM_Unknown6 0x04000000 +#define NTLM_Unknown7 0x08000000 +#define NTLM_Unknown8 0x10000000 +#define NTLM_Negotiate128Bit 0x20000000 +#define NTLM_NegotiateKeyExchange 0x40000000 +#define NTLM_Negotiate56Bit 0x80000000 + + +/* write a 64-bit word, little endian */ +void appendUint64( + CFMutableDataRef buf, + uint64_t word); + +/* write a 32-bit word, little endian */ +void appendUint32( + CFMutableDataRef buf, + uint32_t word); + +/* write a 16-bit word, little endian */ +void appendUint16( + CFMutableDataRef buf, + uint16_t word); + +/* + * Write a security buffer, providing the index into the CFData at which + * this security buffer's offset is located. Just before the actual data is written, + * go back and update the offset with the start of that data using secBufOffset(). + */ +void appendSecBuf( + CFMutableDataRef buf, + uint16_t len, + CFIndex *offsetIndex); + +/* + * Update a security buffer's offset to be the current end of data in a CFData. + */ +void secBufOffset( + CFMutableDataRef buf, + CFIndex offsetIndex); /* obtained from appendSecBuf() */ + +/* + * Parse/validate a security buffer. Verifies that supplied offset/length don't go + * past end of avaialble data. Returns ptr to actual data and its length. Returns + * errSecParam on bogus values. + */ +OSStatus ntlmParseSecBuffer( + const unsigned char *cp, /* start of security buffer */ + const unsigned char *bufStart, /* start of whole msg buffer */ + unsigned bufLen, /* # of valid bytes starting at bufStart */ + const unsigned char **data, /* RETURNED, start of actual data */ + uint16_t *dataLen); /* RETURNED, length of actual data */ + +/* random number generator */ +void ntlmRand( + unsigned len, + void *buf); /* allocated by caller, random data RETURNED */ + +/* Obtain host name in appropriate encoding */ +OSStatus ntlmHostName( + bool unicode, + unsigned char **flat, // mallocd and RETURNED + unsigned *flatLen); // RETURNED + +void ntlmAppendTimestamp( + CFMutableDataRef ntlmV2Blob); + +/* + * Convert CFString to little-endian unicode. + */ +void ntlmStringToLE( + CFStringRef pwd, + unsigned char **ucode, // mallocd and RETURNED + unsigned *ucodeLen); // RETURNED + +/* + * Convert a CFStringRef into a mallocd array of chars suitable for the specified + * encoding. This might return an error if the string can't be converted + * appropriately. + */ +OSStatus ntlmStringFlatten( + CFStringRef str, + bool unicode, + unsigned char **flat, // mallocd and RETURNED + unsigned *flatLen); // RETURNED + +/* MD4 and MD5 hash */ +#define NTLM_DIGEST_LENGTH 16 +void md4Hash( + const unsigned char *data, + unsigned dataLen, + unsigned char *digest); // caller-supplied, NTLM_DIGEST_LENGTH */ +void md5Hash( + const unsigned char *data, + unsigned dataLen, + unsigned char *digest); // caller-supplied, NTLM_DIGEST_LENGTH */ + +/* + * Calculate LM-style password hash. This really only works if the password + * is convertible to ASCII. + */ +OSStatus lmPasswordHash( + CFStringRef pwd, + unsigned char *digest); // caller-supplied, NTLM_DIGEST_LENGTH + +/* + * Calculate NTLM password hash (MD4 on a unicode password). + */ +void ntlmPasswordHash( + CFStringRef pwd, + unsigned char *digest); // caller-supplied, NTLM_DIGEST_LENGTH + +/* + * NTLM response: DES with three different keys. + */ +OSStatus ntlmResponse( + const unsigned char *digest, // NTLM_DIGEST_LENGTH bytes + const unsigned char *challenge, // actually challenge or session hash + unsigned char *ntlmResp); // caller-supplied NTLM_LM_RESPONSE_LEN + +/* DES-related consts */ +#define DES_BLOCK_SIZE 8 +#define DES_RAW_KEY_SIZE 7 +#define DES_KEY_SIZE 8 + +/* + * Given 7 bytes, create 8-byte DES key. Our implementation ignores the + * parity bit (lsb), which simplifies this somewhat. + */ +void ntlmMakeDesKey( + const unsigned char *inKey, // DES_RAW_KEY_SIZE bytes + unsigned char *outKey); // DES_KEY_SIZE bytes + +/* + * single block DES encrypt. + * This would really benefit from a DES implementation in CommonCrypto. + */ +OSStatus ntlmDesCrypt( + const unsigned char *key, // DES_KEY_SIZE bytes + const unsigned char *inData, // DES_BLOCK_SIZE bytes + unsigned char *outData); // DES_BLOCK_SIZE bytes + +/* + * HMAC/MD5. + */ +OSStatus ntlmHmacMD5( + const unsigned char *key, + unsigned keyLen, + const unsigned char *inData, + unsigned inDataLen, + unsigned char *mac); // caller provided, NTLM_DIGEST_LENGTH + +#if NTLM_DUMP +void ntlmPrintFlags( + const char *whereFrom, + uint32_t flags); +#else +#define ntlmPrintFlags(w, f) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _NTLM_BLOB_PRIV_H_ */ diff --git a/refs.txt b/refs.txt new file mode 100644 index 00000000..e69de29b diff --git a/regressions/regressions.xcodeproj/project.pbxproj b/regressions/regressions.xcodeproj/project.pbxproj deleted file mode 100644 index 57814d21..00000000 --- a/regressions/regressions.xcodeproj/project.pbxproj +++ /dev/null @@ -1,341 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 4CC92AB915A3B19D00C6D578 /* testlist_end.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92AB815A3B19D00C6D578 /* testlist_end.h */; settings = {ATTRIBUTES = (); }; }; - 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 */; }; - 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 = (); }; }; - E723A61013DA18C50075AAC1 /* testenv.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C25A6C512271FAF0050C2BD /* testenv.h */; settings = {ATTRIBUTES = (); }; }; - E723A61113DA18C50075AAC1 /* testmore.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C25A6C912271FAF0050C2BD /* testmore.h */; settings = {ATTRIBUTES = (); }; }; - E723A61213DA18C50075AAC1 /* testcert.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C25A6CB12271FAF0050C2BD /* testcert.h */; settings = {ATTRIBUTES = (); }; }; - E723A61313DA18C50075AAC1 /* testpolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = E76CA47B13D8D5CB001B6A11 /* testpolicy.h */; settings = {ATTRIBUTES = (); }; }; - E76CA47913D8D5B4001B6A11 /* testpolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = E76CA47813D8D5B4001B6A11 /* testpolicy.m */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 0C25A68F12271FAF0050C2BD /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; - 0C25A69212271FAF0050C2BD /* Run3.pm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = Run3.pm; sourceTree = ""; }; - 0C25A69312271FAF0050C2BD /* MyHarness.pm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = MyHarness.pm; sourceTree = ""; }; - 0C25A6C012271FAF0050C2BD /* security.pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = security.pl; sourceTree = ""; }; - 0C25A6C312271FAF0050C2BD /* testcpp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testcpp.h; sourceTree = ""; }; - 0C25A6C412271FAF0050C2BD /* testenv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testenv.c; sourceTree = ""; }; - 0C25A6C512271FAF0050C2BD /* testenv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testenv.h; sourceTree = ""; }; - 0C25A6C812271FAF0050C2BD /* testmore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testmore.c; sourceTree = ""; }; - 0C25A6C912271FAF0050C2BD /* testmore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testmore.h; sourceTree = ""; }; - 0C25A6CA12271FAF0050C2BD /* testcert.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testcert.c; sourceTree = ""; }; - 0C25A6CB12271FAF0050C2BD /* testcert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testcert.h; sourceTree = ""; }; - 0C25A6CE12271FAF0050C2BD /* run_tests.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = run_tests.sh; sourceTree = ""; }; - 4CC92AB715A3B19100C6D578 /* testlist_begin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = testlist_begin.h; sourceTree = ""; }; - 4CC92AB815A3B19D00C6D578 /* testlist_end.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testlist_end.h; sourceTree = ""; }; - 4CC92ABB15A3B51100C6D578 /* test_regressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = test_regressions.h; sourceTree = ""; }; - 4CC92B1615A3BD1E00C6D578 /* test-00-test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "test-00-test.c"; sourceTree = ""; }; - E710C6FE133192E900F85568 /* libregressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libregressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; - E76CA47813D8D5B4001B6A11 /* testpolicy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = testpolicy.m; sourceTree = ""; }; - E76CA47B13D8D5CB001B6A11 /* testpolicy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testpolicy.h; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - E710C6FB133192E900F85568 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 05441E5C08A971C700F0EC5A = { - isa = PBXGroup; - children = ( - 0C25A68F12271FAF0050C2BD /* README */, - 0C25A69012271FAF0050C2BD /* inc */, - 0C25A6BF12271FAF0050C2BD /* t */, - 0C25A6C112271FAF0050C2BD /* test */, - E710C6FE133192E900F85568 /* libregressions.a */, - ); - sourceTree = ""; - }; - 0C25A69012271FAF0050C2BD /* inc */ = { - isa = PBXGroup; - children = ( - 0C25A69112271FAF0050C2BD /* IPC */, - 0C25A69312271FAF0050C2BD /* MyHarness.pm */, - ); - path = inc; - sourceTree = ""; - }; - 0C25A69112271FAF0050C2BD /* IPC */ = { - isa = PBXGroup; - children = ( - 0C25A69212271FAF0050C2BD /* Run3.pm */, - ); - path = IPC; - sourceTree = ""; - }; - 0C25A6BF12271FAF0050C2BD /* t */ = { - isa = PBXGroup; - children = ( - 0C25A6C012271FAF0050C2BD /* security.pl */, - ); - path = t; - sourceTree = ""; - }; - 0C25A6C112271FAF0050C2BD /* test */ = { - isa = PBXGroup; - children = ( - 4CC92B1615A3BD1E00C6D578 /* test-00-test.c */, - 4CC92ABB15A3B51100C6D578 /* test_regressions.h */, - 4CC92AB715A3B19100C6D578 /* testlist_begin.h */, - 4CC92AB815A3B19D00C6D578 /* testlist_end.h */, - 0C25A6C312271FAF0050C2BD /* testcpp.h */, - 0C25A6C412271FAF0050C2BD /* testenv.c */, - 0C25A6C512271FAF0050C2BD /* testenv.h */, - 0C25A6C812271FAF0050C2BD /* testmore.c */, - 0C25A6C912271FAF0050C2BD /* testmore.h */, - 0C25A6CA12271FAF0050C2BD /* testcert.c */, - 0C25A6CB12271FAF0050C2BD /* testcert.h */, - E76CA47B13D8D5CB001B6A11 /* testpolicy.h */, - E76CA47813D8D5B4001B6A11 /* testpolicy.m */, - 0C25A6CE12271FAF0050C2BD /* run_tests.sh */, - ); - path = test; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - E710C6FC133192E900F85568 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - E723A61113DA18C50075AAC1 /* testmore.h in Headers */, - 4CC92ABC15A3B51100C6D578 /* test_regressions.h in Headers */, - 4CC92ABD15A3B8FB00C6D578 /* testlist_begin.h in Headers */, - 4CC92AB915A3B19D00C6D578 /* testlist_end.h in Headers */, - E723A61213DA18C50075AAC1 /* testcert.h in Headers */, - E723A60F13DA18C50075AAC1 /* testcpp.h in Headers */, - E723A61013DA18C50075AAC1 /* testenv.h in Headers */, - E723A61313DA18C50075AAC1 /* testpolicy.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - E710C6FD133192E900F85568 /* regressions */ = { - isa = PBXNativeTarget; - buildConfigurationList = E710C703133192E900F85568 /* Build configuration list for PBXNativeTarget "regressions" */; - buildPhases = ( - E710C6FA133192E900F85568 /* Sources */, - E710C6FB133192E900F85568 /* Frameworks */, - E710C6FC133192E900F85568 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = regressions; - productName = regressions; - productReference = E710C6FE133192E900F85568 /* libregressions.a */; - productType = "com.apple.product-type.library.static"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 05441E6008A971C700F0EC5A /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0500; - }; - buildConfigurationList = 4CD81AFC09BE1FD3000A9641 /* Build configuration list for PBXProject "regressions" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - English, - Japanese, - French, - German, - ); - mainGroup = 05441E5C08A971C700F0EC5A; - productRefGroup = 05441E5C08A971C700F0EC5A; - projectDirPath = ""; - projectRoot = ""; - targets = ( - E710C6FD133192E900F85568 /* regressions */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - E710C6FA133192E900F85568 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - E710C7371331938000F85568 /* testenv.c in Sources */, - E710C7381331938000F85568 /* testmore.c in Sources */, - E710C7391331938000F85568 /* testcert.c in Sources */, - E76CA47913D8D5B4001B6A11 /* testpolicy.m in Sources */, - 4CC92B1715A3BD1E00C6D578 /* test-00-test.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 792E01860CBC0E6E007C00A0 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; - "GCC_PREPROCESSOR_DEFINITIONS[sdk=iphoneos*]" = ( - "DEBUG=1", - "NO_SERVER=1", - ); - "GCC_PREPROCESSOR_DEFINITIONS[sdk=iphonesimulator*]" = ( - "DEBUG=1", - "NO_SERVER=1", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; - GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; - GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; - GCC_WARN_MISSING_PARENTHESES = YES; - GCC_WARN_SHADOW = YES; - GCC_WARN_SIGN_COMPARE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = NO; - GCC_WARN_UNKNOWN_PRAGMAS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_LABEL = YES; - GCC_WARN_UNUSED_VALUE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(PROJECT_DIR)/../utilities", - "$(PROJECT_DIR)/../sec", - "$(PROJECT_DIR)/../libDER", - "$(PROJECT_DIR)/..", - "$(PROJECT_DIR)", - "$(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include", - ); - OTHER_CFLAGS = ( - "-fconstant-cfstrings", - "-fno-inline", - ); - "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( - "$(OTHER_LDFLAGS)", - "-framework", - MobileKeyBag, - ); - SKIP_INSTALL = YES; - SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; - WARNING_CFLAGS = ( - "-Wall", - "-Wextra", - "-Wno-unused-parameter", - "-Wno-missing-field-initializers", - ); - }; - name = Debug; - }; - 792E01870CBC0E6E007C00A0 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - COPY_PHASE_STRIP = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_OPTIMIZATION_LEVEL = s; - GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1"; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; - GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; - GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; - GCC_WARN_MISSING_PARENTHESES = YES; - GCC_WARN_SHADOW = YES; - GCC_WARN_SIGN_COMPARE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNKNOWN_PRAGMAS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_LABEL = YES; - GCC_WARN_UNUSED_VALUE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(PROJECT_DIR)/../utilities", - "$(PROJECT_DIR)/../sec", - "$(PROJECT_DIR)/../libDER", - "$(PROJECT_DIR)/..", - "$(PROJECT_DIR)", - "$(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include", - ); - OTHER_CFLAGS = "-fconstant-cfstrings"; - SKIP_INSTALL = YES; - SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; - WARNING_CFLAGS = ( - "-Wall", - "-Wextra", - "-Wno-unused-parameter", - "-Wno-missing-field-initializers", - ); - }; - name = Release; - }; - E710C704133192E900F85568 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - E710C705133192E900F85568 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 4CD81AFC09BE1FD3000A9641 /* Build configuration list for PBXProject "regressions" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 792E01860CBC0E6E007C00A0 /* Debug */, - 792E01870CBC0E6E007C00A0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - E710C703133192E900F85568 /* Build configuration list for PBXNativeTarget "regressions" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - E710C704133192E900F85568 /* Debug */, - E710C705133192E900F85568 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 05441E6008A971C700F0EC5A /* Project object */; -} diff --git a/regressions/t/security.pl b/regressions/t/security.pl deleted file mode 100755 index d0892f0a..00000000 --- a/regressions/t/security.pl +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/perl -w -# -# Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. -# - -my $pid = $$; - -END { - return unless $$ == $pid; - rm_test($_) for @TOCLEAN; -} - -use strict; -use Test::More; -use IPC::Run3; - -sub plan_security { - - unless (1) { - plan skip_all => "security not installed"; - exit; - }; - plan @_; -} - -use Carp; -our @TOCLEAN; -END { - return unless $$ == $pid; - $SIG{__WARN__} = sub { 1 }; - cleanup_test($_) for @TOCLEAN; -} - -our $output = ''; - -sub build_test { - my $xd = "/tmp/test-$pid"; - my $security = 'security'; - $ENV{HOME} = $xd; - push @TOCLEAN, [$xd, $security]; - return ($xd, $security); -} - -sub rm_test { - my ($xd, $security) = @{+shift}; - #rmtree [$xd]; -} - -sub cleanup_test { - return unless $ENV{TEST_VERBOSE}; - my ($xd, $security) = @{+shift}; -} - -sub is_output { - my ($security, $cmd, $arg, $expected, $test) = @_; - $output = ''; - run3([$security, $cmd, @$arg], \undef, \$output, \$output); -# open(STDOUT, ">&STDERR") || die "couldn't dup strerr: $!"; -# open(my $out, '-|', $security, $cmd, @$arg); -# while (<$out>) { $output .= $_; } - - my $cmp = (grep {ref ($_) eq 'Regexp'} @$expected) - ? \&is_deeply_like : \&is_deeply; - @_ = ([sort split (/\r?\n/, $output)], [sort @$expected], $test || join(' ', $cmd, @$arg)); - goto &$cmp; -} - -1; diff --git a/regressions/test/run_tests.sh b/regressions/test/run_tests.sh deleted file mode 100755 index a1ae8cde..00000000 --- a/regressions/test/run_tests.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh - -# run_tests.sh -# Security -# -# Created by Fabrice Gautier on 8/26/10. -# Copyright 2010 Apple, Inc. All rights reserved. - - -# Run a command line tool on the sim or the device - -CMD=SecurityTests.app/SecurityTests - -if [ "${PLATFORM_NAME}" == "iphoneos" ]; then - INSTALL_DIR=/tmp - RSYNC_URL=rsync://root@localhost:10873/root${INSTALL_DIR} -#copy Security Framework and testrunner program to the device, to /tmp -#This will not override the existing security Framework on your device (in /System/Library/Framework) - export RSYNC_PASSWORD=alpine - echo "run_tests.sh:${LINENO}: note: Copying stuff to device" - /usr/bin/rsync -cav ${CONFIGURATION_BUILD_DIR}/Security.framework ${RSYNC_URL} - /usr/bin/rsync -cav ${CONFIGURATION_BUILD_DIR}/SecurityTests.app ${RSYNC_URL} - echo "run_tests.sh:${LINENO}: note: Running the test" - xcrun -sdk "$SDKROOT" PurpleExec --env "DYLD_FRAMEWORK_PATH=${INSTALL_DIR}" --cmd ${INSTALL_DIR}/${CMD} -else - echo "run_tests.sh:${LINENO}: note: Running test on simulator (${BUILT_PRODUCTS_DIR}/${CMD})" - export DYLD_ROOT_PATH="${SDKROOT}" - export DYLD_LIBRARY_PATH="${BUILT_PRODUCTS_DIR}" - export DYLD_FRAMEWORK_PATH="${BUILT_PRODUCTS_DIR}" - ${BUILT_PRODUCTS_DIR}/${CMD} -fi - - diff --git a/regressions/test/testcpp.h b/regressions/test/testcpp.h deleted file mode 100644 index 6149bfdb..00000000 --- a/regressions/test/testcpp.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2005-2007 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@ - * - * testcpp.h - */ - -#ifndef _TESTCPP_H_ -#define _TESTCPP_H_ 1 - -#include "testmore.h" - -#ifdef __cplusplus - -#define no_throw(THIS, TESTNAME) \ -({ \ - bool _this; \ - try { THIS; _this = true; } catch (...) { _this = false; } \ - test_ok(_this, TESTNAME, test_directive, test_reason, \ - __FILE__, __LINE__, \ - "# got: \n" \ - "# expected: \n"); \ -}) -#define does_throw(THIS, TESTNAME) \ -({ \ - bool _this; \ - try { THIS; _this = false; } catch (...) { _this = true; } \ - test_ok(_this, TESTNAME, test_directive, test_reason, \ - __FILE__, __LINE__, \ - "# got: \n" \ - "# expected: \n"); \ -}) -#define is_throw(THIS, CLASS, METHOD, VALUE, TESTNAME) \ -({ \ - bool _this; \ - try \ - { \ - THIS; \ - _this = test_ok(false, TESTNAME, test_directive, test_reason, \ - __FILE__, __LINE__, \ - "# got: \n" \ - "# expected: %s.%s == %s\n", \ - #CLASS, #METHOD, #VALUE); \ - } \ - catch (const CLASS &_exception) \ - { \ - _this = test_ok(_exception.METHOD == (VALUE), TESTNAME, \ - test_directive, test_reason, __FILE__, __LINE__, \ - "# got: %d\n" \ - "# expected: %s.%s == %s\n", \ - _exception.METHOD, #CLASS, #METHOD, #VALUE); \ - } \ - catch (...) \ - { \ - _this = test_ok(false, TESTNAME, test_directive, test_reason, \ - __FILE__, __LINE__, \ - "# got: \n" \ - "# expected: %s.%s == %s\n", \ - #CLASS, #METHOD, #VALUE); \ - } \ - _this; \ -}) -#endif /* __cplusplus */ - -#endif /* !_TESTCPP_H_ */ diff --git a/regressions/test/testenv.c b/regressions/test/testenv.c deleted file mode 100644 index 93482c5d..00000000 --- a/regressions/test/testenv.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (c) 2005-2007,2009-2011 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#include "testmore.h" -#include "testenv.h" - -#include -#include -#include - - -int test_verbose = 0; - -#ifdef NO_SERVER -#include - -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) -{ - char command_buf[256]; - if (strlen(path) + 10 > sizeof(command_buf) || strchr(path, '\'')) - { - fprintf(stderr, "# rmdir_recursive: invalid path: %s", path); - return -1; - } - - sprintf(command_buf, "/bin/rm -rf '%s'", path); - return system(command_buf); -} -#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); -} - -static int tests_run_index(int i, 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]); - } - } - - fprintf(stderr, "TEST: Test Case '%s' started.\n", testlist[i].name); - - run_one_test(&testlist[i], argc, argv); - if(testlist[i].failed_tests) { - fprintf(stderr, "FAIL: Test Case '%s' failed.\n", testlist[i].name); - } else { - fprintf(stderr, "PASS: Test Case '%s' passed. (%lu ms)\n", testlist[i].name, testlist[i].duration); - } - return testlist[i].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_index(i, argc, argv); - optind = curroptind; - } - } - - return failcount; -} - -int -tests_begin(int argc, char * const *argv) -{ - const char *testcase = NULL; - bool initialized = false; - bool print_security_logs = false; - int testix = -1; - int failcount = 0; - int ch; - int loop = 0; - - for (;;) { - while (!testcase && (ch = getopt(argc, argv, "klvws")) != -1) - { - switch (ch) - { -#ifdef NO_SERVER - case 'k': - keep_scratch_dir = true; - break; -#endif - case 's': - print_security_logs = true; - break; - - case 'v': - test_verbose++; - break; - - case 'w': - sleep(100); - break; - case 'l': - loop=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 (print_security_logs) { - add_security_log_hanlder(^(const char *level, CFStringRef scope, const char *function, const char *file, int line, CFStringRef message) { - time_t now = time(NULL); - char *date = ctime(&now); - date[19] = '\0'; - CFStringRef logStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, - CFSTR("%s %@ %s %@\n"), date + 4, - scope ? scope : CFSTR(""), function, message); - CFShow(logStr); - CFReleaseSafe(logStr); - }); - } - - if (testix < 0) { - if (!initialized) { - initialized = true; - tests_init(); - failcount+=tests_run_all(argc, argv); - } - break; - } else { - if (!initialized) { - tests_init(); - initialized = true; - } - optind++; - failcount+=tests_run_index(testix, argc, argv); - testix = -1; - } - } - - printf("Total failcount = %d\n", failcount); - - /* 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/regressions/test/testenv.h b/regressions/test/testenv.h deleted file mode 100644 index 727d42c2..00000000 --- a/regressions/test/testenv.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2005-2007 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.h - */ - -#ifndef _TESTENV_H_ -#define _TESTENV_H_ 1 - -#ifdef __cplusplus -extern "C" { -#endif - -extern int test_verbose; - -int tests_begin(int argc, char * const *argv); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* !_TESTENV_H_ */ diff --git a/regressions/test/testmore.c b/regressions/test/testmore.c deleted file mode 100644 index 0aaf0b3b..00000000 --- a/regressions/test/testmore.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright (c) 2005-2007 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@ - * - * testmore.c - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "testmore.h" -#include "testenv.h" - -static int test_num = 0; -static int test_fails = 0; -static int test_cases = 0; -static const char *test_plan_file; -static int test_plan_line=0; - -const char *test_directive = NULL; -const char *test_reason = NULL; - -static void fprint_string(FILE *file, CFStringRef string) { - UInt8 buf[256]; - CFRange range = { .location = 0 }; - range.length = CFStringGetLength(string); - while (range.length > 0) { - CFIndex bytesUsed = 0; - CFIndex converted = CFStringGetBytes(string, range, kCFStringEncodingUTF8, 0, false, buf, sizeof(buf), &bytesUsed); - fwrite(buf, 1, bytesUsed, file); - range.length -= converted; - range.location += converted; - } -} - -static void cffprint(FILE *file, CFStringRef fmt, ...) CF_FORMAT_FUNCTION(2,0); - -static void cffprint(FILE *file, CFStringRef fmt, ...) { - va_list args; - va_start(args, fmt); - CFStringRef line = CFStringCreateWithFormatAndArguments(NULL, NULL, fmt, args); - va_end(args); - fprint_string(file, line); - CFRelease(line); -} - -void test_skip(const char *reason, int how_many, int unless) -{ - if (unless) - return; - - int done; - for (done = 0; done < how_many; ++done) - test_ok(1, NULL, "skip", reason, __FILE__, __LINE__, NULL); -} - -void test_bail_out(const char *reason, const char *file, unsigned line) -{ - printf("BAIL OUT! (%s at line %u) %s\n", file, line, reason); - fflush(stdout); - exit(255); -} - -void test_plan_skip_all(const char *reason) -{ - if (test_num < test_cases) - { - test_skip(reason, test_cases - test_num, 0); - } -} - -static int test_plan_exit(void) -{ - int status = 0; - fflush(stdout); - - if (!test_num) - { - if (test_cases) - { - fprintf(stderr, "%s:%u: warning: No tests run!\n", test_plan_file, test_plan_line); - status = 255; - } - else - { - fprintf(stderr, "%s:%u: error: Looks like your test died before it could " - "output anything.\n", test_plan_file, test_plan_line); - status = 255; - } - } - else if (test_num < test_cases) - { - fprintf(stderr, "%s:%u: warning: Looks like you planned %d tests but only ran %d.\n", - test_plan_file, test_plan_line, test_cases, test_num); - status = test_fails + test_cases - test_num; - } - else if (test_num > test_cases) - { - fprintf(stderr, "%s:%u: warning: Looks like you planned %d tests but ran %d extra.\n", - test_plan_file, test_plan_line, test_cases, test_num - test_cases); - status = test_fails; - } - else if (test_fails) - { - fprintf(stderr, "%s:%u: error: Looks like you failed %d tests of %d.\n", - test_plan_file, test_plan_line, test_fails, test_cases); - status = test_fails; - } - - fflush(stderr); - - /* reset the test plan */ - test_num = 0; - test_fails = 0; - test_cases = 0; - - return status; -} - -void test_plan_tests(int count, const char *file, unsigned line) -{ -#if 0 - if (atexit(test_plan_exit) < 0) - { - fprintf(stderr, "failed to setup atexit handler: %s\n", - strerror(errno)); - fflush(stderr); - exit(255); - } -#endif - - if (test_cases) - { - fprintf(stderr, - "%s:%u: error: You tried to plan twice!\n", - file, line); - - fflush(stderr); - exit(255); - } - else - { - if (!count) - { - fprintf(stderr, "%s:%u: warning: You said to run 0 tests! You've got to run " - "something.\n", file, line); - fflush(stderr); - exit(255); - } - - test_plan_file=file; - test_plan_line=line; - - test_cases = count; - fprintf(stderr, "%s:%u: note: 1..%d\n", file, line, test_cases); - fflush(stdout); - } -} - -int -test_diag(const char *directive, const char *reason, - const char *file, unsigned line, const char *fmt, ...) -{ - int is_todo = directive && !strcmp(directive, "TODO"); - va_list args; - - va_start(args, fmt); - - if (is_todo) - { - fputs("# ", stdout); - if (fmt) - vprintf(fmt, args); - fputs("\n", stdout); - fflush(stdout); - } - else - { - fflush(stdout); - fputs("# ", stderr); - if (fmt) - vfprintf(stderr, fmt, args); - fputs("\n", stderr); - fflush(stderr); - } - - va_end(args); - - return 1; -} - -int -test_ok(int passed, __attribute((cf_consumed)) CFStringRef description, const char *directive, - const char *reason, const char *file, unsigned line, - const char *fmt, ...) -{ - int is_todo = !passed && directive && !strcmp(directive, "TODO"); - int is_setup = directive && !is_todo && !strcmp(directive, "SETUP"); - - if (is_setup) - { - if (!passed) - { - fflush(stdout); - cffprint(stderr, CFSTR("# SETUP not ok%s%@%s%s\n"), - description ? " - " : "", - description ? description : CFSTR(""), - reason ? " - " : "", - reason ? reason : ""); - } - } - else - { - if (!test_cases) - { - atexit((void(*)(void))test_plan_exit); - fprintf(stderr, "You tried to run a test without a plan! " - "Gotta have a plan. at %s line %u\n", file, line); - fflush(stderr); - exit(255); - } - - ++test_num; - if (test_num > test_cases || (!passed && !is_todo)) - ++test_fails; - - /* We only print this when a test fail, unless verbose is enabled */ - if ((!passed) || (test_verbose > 0)) { - cffprint(stderr, CFSTR("%s:%u: note: %sok %d%s%@%s%s%s%s\n"), - file, line, passed ? "" : "not ", test_num, - description ? " - " : "", - description ? description : CFSTR(""), - directive ? " # " : "", - directive ? directive : "", - reason ? " " : "", - reason ? reason : ""); - } - } - - if (passed) - fflush(stdout); - else - { - va_list args; - - va_start(args, fmt); - - if (is_todo) - { -/* Enable this to output TODO as warning */ -#if 0 - printf("%s:%d: warning: Failed (TODO) test\n", file, line); - if (fmt) - vprintf(fmt, args); -#endif - fflush(stdout); - } - else - { - fflush(stdout); - fprintf(stderr, "%s:%d: error: Failed test\n", file, line); - if (fmt) - vfprintf(stderr, fmt, args); - fflush(stderr); - } - - va_end(args); - } - - if (description) - CFRelease(description); - - return passed; -} - - -const char * -sec_errstr(int err) -{ -#if 1 - static int bufnum = 0; - static char buf[2][20]; - bufnum = bufnum ? 0 : 1; - sprintf(buf[bufnum], "0x%X", err); - return buf[bufnum]; -#else /* !1 */ - if (err >= errSecErrnoBase && err <= errSecErrnoLimit) - return strerror(err - 100000); - -#ifdef MAC_OS_X_VERSION_10_4 - /* AvailabilityMacros.h would only define this if we are on a - Tiger or later machine. */ - extern const char *cssmErrorString(long); - return cssmErrorString(err); -#else /* !defined(MAC_OS_X_VERSION_10_4) */ - extern const char *_ZN8Security15cssmErrorStringEl(long); - return _ZN8Security15cssmErrorStringEl(err); -#endif /* MAC_OS_X_VERSION_10_4 */ -#endif /* !1 */ -} - -/* run one test, described by test, return info in test struct */ -int run_one_test(struct one_test_s *test, int argc, char * const *argv) -{ - struct timeval start, stop; - - if(test->entry==NULL) { - printf("%s:%d: error: wtf?\n", __FILE__, __LINE__); - return -1; - } - - 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); - test->failed_tests=test_fails; - - return test_plan_exit(); - }; diff --git a/regressions/test/testmore.h b/regressions/test/testmore.h deleted file mode 100644 index 515a84e1..00000000 --- a/regressions/test/testmore.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 2005-2007 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@ - * - * testmore.h - */ - -#ifndef _TESTMORE_H_ -#define _TESTMORE_H_ 1 - -#include -#include -#include -#include -#include - -__BEGIN_DECLS - -/* Macros to be used in testlist.h style headers. */ -#define ONE_TEST(x) int x(int argc, char *const *argv); -#define DISABLED_ONE_TEST(x) ONE_TEST(x) -#define OFF_ONE_TEST(x) ONE_TEST(x) - -typedef int (*one_test_entry)(int argc, char *const *argv); - -#define ONE_TEST_ENTRY(x) int x(int argc, char *const *argv) - -struct one_test_s { - char *name; /* test name */ - one_test_entry entry; /* entry point */ - int off; /* off by default */ - int sub_tests; /* number of subtests */ - int failed_tests; /* number of failed tests*/ - unsigned long duration; /* test duration in msecs */ - /* add more later: timing, etc... */ -}; - -extern struct one_test_s testlist[]; - -int run_one_test(struct one_test_s *test, int argc, char * const *argv); - -/* this test harnes rely on shadowing for TODO, SKIP and SETUP blocks */ -#pragma GCC diagnostic ignored "-Wshadow" - -#define test_create_description(TESTNAME, ...) \ - CFStringCreateWithFormat(NULL, NULL, CFSTR(TESTNAME), ## __VA_ARGS__) - -#define ok(THIS, ...) \ -({ \ - bool is_ok = !!(THIS); \ - test_ok(is_ok, test_create_description(__VA_ARGS__), test_directive, \ - test_reason, __FILE__, __LINE__, NULL); \ -}) -#define is(THIS, THAT, ...) \ -({ \ - __typeof__(THIS) _this = (THIS); \ - __typeof__(THAT) _that = (THAT); \ - test_ok((_this == _that), test_create_description(__VA_ARGS__), \ - test_directive, test_reason, __FILE__, __LINE__, \ - "# got: '%d'\n" \ - "# expected: '%d'\n", \ - _this, _that); \ -}) -#define isnt(THIS, THAT, ...) \ - cmp_ok((THIS), !=, (THAT), __VA_ARGS__) -#define diag(MSG, ARGS...) \ - test_diag(test_directive, test_reason, __FILE__, __LINE__, MSG, ## ARGS) -#define cmp_ok(THIS, OP, THAT, ...) \ -({ \ - __typeof__(THIS) _this = (THIS); \ - __typeof__(THAT) _that = (THAT); \ - test_ok((_this OP _that), test_create_description(__VA_ARGS__), \ - test_directive, test_reason, __FILE__, __LINE__, \ - "# '%d'\n" \ - "# " #OP "\n" \ - "# '%d'\n", \ - _this, _that); \ -}) -#define eq_string(THIS, THAT, ...) \ -({ \ - const char *_this = (THIS); \ - const char *_that = (THAT); \ - test_ok(!strcmp(_this, _that), test_create_description(__VA_ARGS__), \ - test_directive, test_reason, __FILE__, __LINE__, \ - "# '%s'\n" \ - "# eq\n" \ - "# '%s'\n", \ - _this, _that); \ -}) -#define eq_stringn(THIS, THISLEN, THAT, THATLEN, ...) \ -({ \ - __typeof__(THISLEN) _thislen = (THISLEN); \ - __typeof__(THATLEN) _thatlen = (THATLEN); \ - const char *_this = (THIS); \ - const char *_that = (THAT); \ - test_ok(_thislen == _thatlen && !strncmp(_this, _that, _thislen), \ - test_create_description(__VA_ARGS__), test_directive, test_reason, \ - __FILE__, __LINE__, \ - "# '%.*s'\n" \ - "# eq\n" \ - "# '%.*s'\n", \ - (int)_thislen, _this, (int)_thatlen, _that); \ -}) -#define like(THIS, REGEXP, ...) like_not_yet_implemented() -#define unlike(THIS, REGEXP, ...) unlike_not_yet_implemented() -#define is_deeply(STRUCT1, STRUCT2, ...) is_deeply_not_yet_implemented() -#define TODO switch(0) default -#define SKIP switch(0) default -#define SETUP switch(0) default -#define todo(REASON) const char *test_directive __attribute__((unused)) = "TODO", \ - *test_reason __attribute__((unused)) = (REASON) -#define skip(WHY, HOW_MANY, UNLESS) if (!(UNLESS)) \ - { test_skip((WHY), (HOW_MANY), 0); break; } -#define setup(REASON) const char *test_directive = "SETUP", \ - *test_reason = (REASON) -#define pass(...) ok(1, __VA_ARGS__) -#define fail(...) ok(0, __VA_ARGS__) -#define BAIL_OUT(WHY) test_bail_out(WHY, __FILE__, __LINE__) -#define plan_skip_all(REASON) test_plan_skip_all(REASON) -#define plan_tests(COUNT) test_plan_tests(COUNT, __FILE__, __LINE__) - -#define ok_status(THIS, ...) \ -({ \ - OSStatus _this = (THIS); \ - test_ok(!_this, test_create_description(__VA_ARGS__), \ - test_directive, test_reason, __FILE__, __LINE__, \ - "# status: %s(%" PRId32 ")\n", \ - sec_errstr(_this), _this); \ -}) -#define is_status(THIS, THAT, ...) \ -({ \ - OSStatus _this = (THIS); \ - OSStatus _that = (THAT); \ - test_ok(_this == _that, test_create_description(__VA_ARGS__), \ - test_directive, test_reason, __FILE__, __LINE__, \ - "# got: %s(%" PRId32 ")\n" \ - "# expected: %s(%" PRId32 ")\n", \ - sec_errstr(_this), _this, sec_errstr(_that), _that); \ -}) -#define ok_unix(THIS, ...) \ -({ \ - int _this = (THIS) < 0 ? errno : 0; \ - test_ok(!_this, test_create_description(__VA_ARGS__), \ - test_directive, test_reason, __FILE__, __LINE__, \ - "# got: %s(%d)\n", \ - strerror(_this), _this); \ -}) -#define is_unix(THIS, THAT, ...) \ -({ \ - int _result = (THIS); \ - int _this = _result < 0 ? errno : 0; \ - int _that = (THAT); \ - _that && _result < 0 \ - ? test_ok(_this == _that, test_create_description(__VA_ARGS__), \ - test_directive, test_reason, __FILE__, __LINE__, \ - "# got: %s(%d)\n" \ - "# expected: %s(%d)\n", \ - strerror(_this), _this, strerror(_that), _that) \ - : test_ok(_this == _that, test_create_description(__VA_ARGS__), \ - test_directive, test_reason, __FILE__, __LINE__, \ - "# got: %d\n" \ - "# expected errno: %s(%d)\n", \ - _result, strerror(_that), _that); \ -}) - - -extern const char *test_directive; -extern const char *test_reason; - -void test_bail_out(const char *reason, const char *file, unsigned line); -int test_diag(const char *directive, const char *reason, - const char *file, unsigned line, const char *fmt, ...); -int test_ok(int passed, __attribute((cf_consumed)) CFStringRef description, const char *directive, - const char *reason, const char *file, unsigned line, const char *fmt, ...); -void test_plan_skip_all(const char *reason); -void test_plan_tests(int count, const char *file, unsigned line); -void test_skip(const char *reason, int how_many, int unless); - -const char *sec_errstr(int err); - -__END_DECLS - -#endif /* !_TESTMORE_H_ */ diff --git a/regressions/test/testpolicy.h b/regressions/test/testpolicy.h deleted file mode 100644 index c7c5c242..00000000 --- a/regressions/test/testpolicy.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// testpolicy.h -// regressions -// -// Created by Mitch Adler on 7/21/11. -// Copyright (c) 2011 Apple Inc. All rights reserved. -// - -#ifndef regressions_testpolicy_h -#define regressions_testpolicy_h - -#include -#include - - -void runCertificateTestForDirectory(SecPolicyRef policy, CFStringRef resourceSubDirectory, CFGregorianDate *date); - - -#endif diff --git a/resources/AppleESCertificates.plist b/resources/AppleESCertificates.plist new file mode 100644 index 0000000000000000000000000000000000000000..e1634ec07cfef8fb8198a8f5688123fe3f08e729 GIT binary patch literal 2086 zcmYc)$jK}&F)+Bq$i&PVFCZ3Bl%GA(VJCPpSE#uNiyHcqWJkGAi;jEvl@3XFjHu-p|F7+LJlxSRtDxKMt%l^CPpr%CPqev1EFV1&U?OmGpkJ8K**u? zVCIbJI?E4S`!Y-RkXz}twT+MTQ$Mc%wrlS}7xT$GCTTUFd7S@u>Z-PNzDYCoJe%MU z9i^Ab^PhcZL*MGe;=iR{#6AGqZd+y02 zDEad4D+`02vR|(M-~A`s^H1gr*1l;X?Mc^~^cPLv>eb-p{PmOcl>Pray6b(f+1jP- z5U)sgwWPf{0ulHiuo z-I8J(93}EiZIZBZv+=$MOPv2yE|~aRM*Ktj)1Hh^=hs;uy?QC4@3&^~zj^oknV1)UNR-JIA&M}gf;y8@$~k|gFIQT?oPM)uNw_e~=6vJ4k5-^f!J zdhW=)Wn65t0~}a{7aaFBzu9_z(@il8@5M{)?y&Jb*eG1nT`8Y_W7n35IV}=T-YSVZ zuC(sB8X6LB?E7f%zBISU0|`erRed{kcBk&%fX&w=uFC&%GVl@jEwpkLpXIOeZB4!-iB((v=5FA=>vi}1 z0}g4KWw&>2I=Dn2-qgRlyK3=mn{Odgoz`ku|6}WUIO$`;^a$yj{ri5q`Dn(-d{Ee? zy;O*EwuYn0^!cAVyfcelS*dRbknPaq-Tjtjk>Gir=+s2hy`OmhJld&nc{_7~<<$pm zH7sXNE^OU0drybo^|dkob$A>40xcD~*UPz0{lzPNX@A3m`MF+S4bvqAmnN%oyt~P+ zdEtuL#OU8%-0T;5E5-7}n3NliiL&P|VB6+8VZ*v5Yxzo9w6!ZfhPNoUtGtOg@{z2Z z{kLLTaKp84ca|NFWV3i%Y1bbh9e|Rvu`0llvkOH}wO`QPDsk1c>g@d_jSt+(zJ5%* zY+jlDxh`5( zEJ44ttF0C9@)X$qc0E>^k@To@hw8iJGNw&RFN0e%>`J$Br@oZg)iQZQ*ZZwfLQneF zU5#1D>czMx|7S$pcb3F=Uym)2cF~Knid?vP!g~mk67pK>tTLvV^6$V{8lw~?$+&Q<|60gLYLZnma7cd-D2Y)9w + + + + VersionNumber + 2014081900 + + diff --git a/resources/Blocked.plist b/resources/Blocked.plist new file mode 100644 index 0000000000000000000000000000000000000000..a3eaf9755ae9c0383e1b7de4852a8b2c8b67dd72 GIT binary patch literal 435 zcmYc)$jK}&F)&y!z|Y9U%)-jX&cVsW&BM#b?=K*d@>{yic8Av|m!_X#wy)FYo|+&wH6)uXgQ;FS_U8ayWJOA(DkVGWI{{Gd*H$ zk)8Bi!@8yM1kZI}pdmPf|J|A5$&>#+rvBJRp_%?-o@;+Mr2cP1t>WV!$)kR_*KCel@!O zV@L+6&Yl?V>=!**^wc2{hj}{Ab?+r4fWnhFQa0|Mzhq)`-1^|Rk0yP-ownAHfrCMc u!H~g&A)cX(p_gF^!)}I43@;fO7{wX&7+o1-7{Gvu5kfNvKxrt&SPTGNw5)Xi literal 0 HcmV?d00001 diff --git a/resources/EVRoots.plist b/resources/EVRoots.plist new file mode 100644 index 0000000000000000000000000000000000000000..d3a23da378c252688ac0f70afb2d223d40b5ee68 GIT binary patch literal 3448 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 literal 0 HcmV?d00001 diff --git a/resources/English.lproj/CloudKeychain.strings b/resources/English.lproj/CloudKeychain.strings new file mode 100644 index 0000000000000000000000000000000000000000..28959b9e33afdd1d47aba534d41c715d79fb0847 GIT binary patch literal 6498 zcmeHLU2juK4E1w=!>%+!3rJ{HwEKz>TUu7C0ClyrLOkB4Ee&nbDoqLf^UI!NW9*wd z_cnYLA)zQYx%1)i*vH47dH>&ixhF*)%b6U=75>fTP~PEL)&bd^%PciQbV~;V<`l-hVZZ7( zQgg0<2z`q@#P`S3`vI)I2Ai+y!)Ms-5v;NYYs_H>T8|z-kWJWP25X$+Z4I{IX9yLS zkZ__lUEpc=1BW7e}CV_}Yu#n*+&OgS#z9`GPkL*ax$J`y2VRhXWtlh2a zHd1C?b#C6-&WAjC0FN?5c`mm1K#afVxzDjTV+rn*m4W3k>QR?>k-TIh*pg*#DSGc> z-$k+?>)5W34z2t8^NOtgFYsx!hQC?dKY`7NCRQdMA?8tw!EM<>535gVxKMlZG~#vD za;y-0&IXj{=M;-mJG)rr(XCdNS0P7-CBKHIR;@&2U#G3{o%6t|8n=DhkI-XS(`rJ; zytibO=C&+(b*2nIw0V*d!>W^>=E)@xQ0K^D{wsQ7wUc3Z?NjD_-tLxBQu$ zl@s_hlv};SoG?->lRZZ0J8f~#cBj9{Kb;u(TO~xkh+Ti~{A__|(2OzXULm(xgl3kb zy}6Sq_%67U9*w!ii_DjKbZEQU=&aii?@kc&Q_WUnVMlgu&FEfk&#SOTWOjEM_8xls zd!BP$o-|t>K|k7pHnV@^Kh_pJ6TQ(k#sklNL{502eQq=+d#$q?9i21S4$cCht-WPk zyNI$A>I8gi(dhR@Zh_?)A-&s^R~qtH#zfdUw`PAWx93$nf6%&iuFMFi^@jfS-Yk9h zV>W5CnA@h_A1n0r*Vh#SM)-muXuVzoq-P2Qw@PKq8aCLF8Q5<} z$PPqTSZ+^w!cIf=o0QOWm9bg#FU{b0m6xpYKgAw+XUp@goxVJ~M;1KC&X_0YoA%vU z+#xf^jByuD8{AR&N8oTs(8xi?TXQxT?mfL*TOA!&@O1}B$f8&QQl>h($ literal 0 HcmV?d00001 diff --git a/resources/English.lproj/OID.strings b/resources/English.lproj/OID.strings new file mode 100644 index 0000000000000000000000000000000000000000..b6e9425b29924035689691fc290283e53abf828b GIT binary patch literal 211564 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 Dr}S)S literal 0 HcmV?d00001 diff --git a/resources/English.lproj/SharedWebCredentials.strings b/resources/English.lproj/SharedWebCredentials.strings new file mode 100644 index 0000000000000000000000000000000000000000..dcf73064ca8754d8f41bfe15bd7ee5a9266342a5 GIT binary patch literal 4982 zcmdT|T~8BH5S?fKfr%zJBpUSr)c7VEOIr<53sS1#sj1yk8vB9l0{Z9GbMAC<_ijs} z0t;rd-QD}KcjnBwGpGCK_qsfl6>-y}DTmULW9dmEU-A1*s?(>Qj3tu+dWVwA8qN$o z1GM&WAKsA4nRGF#kJ+5DlIyF=M2_T_pV!Aq8CHFa(NA!FAavT~+c>vy@_7~SdySLh!g^fE zp``=jHZsuRjhw-r4XnO{qk-!u*zg8z%3;nhWKM9;d5lSlxwab|I9ZH? zv1bD@sLLi|$Vls(i@xuo{WD@#$0)L*g=?M>7CXk1Y#V~j4mb_uySGQ<7WSty<~)wj zpTLWlTV}PbST5on_?39PZyMo>)NllznZK7um=@0NzPpL*3HX_Sp&8hsJNl;iy90D9 zp6||A;lK?GNNb zvN|h;*;U!buHRo8X{*QA!RNJ->)J{fJyHqu?7HjpThD=e#xL0Ns zL9r?t_S8>#jbQuy^0~X1w=Yu>Rq>j&oMG$6`Gu-fy*KT_Ohx}qtx!WQqf!jZ81*VDSrja^DY@X;2zh@pQg^h?T)@d&+-w{5FvHGsO-y4Y(|S zt&#-2be9-h^mgR`@iA}NmybohGb_&K{(KHH?~8SG5eDhCWhvXIWbZhNX~?(pJRnaS zk@8yfZQ$Q4f!TKi`}F$(YXob;5Y{^Uk6O;|2JHTVa~BBO7oHmUJeGTobwn|X($4__prSkHM`!;tsnu$6lFL|hN4{lTVyAF*RXDBJi&9_7bvXBd)uBp=qdLV#SA?auY1u^(>^Hz zh09WG!w$dPxcmP}lTGV3-(h9`vEwdK`1oh7EQPBJRsP&&)l)dnzFE(tl@BOva^5r` zah8EintG$UPE|p-;AgE1K;eYw_7@Xcd)J;aTYR12RO5w*X49pC!bahIZElU+%c_mG z9JxQsPwn&Oz8D4$1~CR*1{a2Ch9ZVeh6N1U8O||0W%$D=%&5fx226|)nt=~WLn%f_ E02pqQJOBUy literal 0 HcmV?d00001 diff --git a/resources/certsIndex.data b/resources/certsIndex.data new file mode 100644 index 0000000000000000000000000000000000000000..39729370f19169ca28c0c0a37217f2af7aaed0ab GIT binary patch literal 5352 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 literal 0 HcmV?d00001 diff --git a/resources/certsTable.data b/resources/certsTable.data new file mode 100644 index 0000000000000000000000000000000000000000..d78d59330c78469ada227bb3b10635240ae1bbfe GIT binary patch literal 242192 zcmeFa1z1#VyEY6A-Q6*C3Ntha(v5%uA|X9=cS*M(tsq?@h?GcoD4o&@BB7v2DWj{L?k3U z)c5kNJam|GqoD>%)}JRJIH(vL;fmp3a1aquP!J%(P%H=rDo7g{l?X{r6G{vrgby&W zv6S@W)HLM4n%q*{P$CEcd@BeWQ^^PB-~{6~bF_!hlHovvpuA8%C?72#4)$|CUQ%o5k%ayc+!h38c3NM>GF{r5xKBE2 zU*mWziB5f~wra`SUkY+)mv_7s`{wF%E$t{uJ}73TPJMoKYUjtx{M{*1*8c7tV&HC* zhHDBr;P|B6c$Hl>zc4wi2csw~QWejx((tu(fqIzz+MVVu?_pfhVpS~VS?nsk($k-) zswpDG_;DQZ@C}CS)vM-hi#U1_3{6j{^1rh@BiSuF4y9Q8m>XFwYaJT08#U^NT0DR? z*)h)=roqxjR@dtjaf6Ezk=Cw-=m~!5Gp2pvgxpD$+3m)$d4*@&O+lY^ZHFl|*J4Tf zmHUewWml-Ah8M$&`bKQBn^a>_`SkL_R^kP6ObtlYwwCgaK$O*7&QEW0&HG}_QR01= zr>8^pL{PHOd^5N8nc~iduhSIL<>M3L6@*;6eii0o#(l%u z&C$i$u{k%-q@y=Hg=F z0CNP(0dq~Q&0!{BC_iv~2o(4M|8YbJ9{h@l5D`z1Q6M1T4+Iy!0S~?b8PHi&2n~FU zi%g14OhXOBeYC^uTb(exTv@r=tnFrpa#1w^4F*&L5#dFUydyoidJf9wyNQPT8hOSW zg^9$J*V7NTBb9SrdAW~H(50w#zpJ%gW!O7lf5Z{hGCb@Nw*+;~WErQXQXpkVvkHwK z`&voGbY(1+oQvsh`DfpCSyC#FuA`j$YwLD53pU*!Bbbh6ZV(C1F<{kfjqW-4%13l$ zHZ`|MU#@i>dB7o7txrgbP);Ed`y@nzx+h4z83|83OW@w8&E*b|A3HUYe=|R;VY%jH zCRwYF-P%Y9etGMytDEt@w>V2buHQyrAsaw4Fq@(vFZ#&&BKpcr+~|nakZiRoe%ewk z40ReLED`@8bdvfUYoZ=r&ZQ@IM3W(zjF+nH^CH9jAK@UfU`Wnvu&Ko)G2zW^(_Z!Q z(R*8XbNf}CQCcuI_i)wg)Pclgi9?L1h4+~Ch4u-v~y9vv1&X*s)ntqd+{Yt#A&`h>9F;87Jkh+nw^MNw5_SL>m zELha7NZsb+S^i_=3Dhci`_wCB)HvAJ^AqSYw&*vIk{ye4l=|Mw#B}ZP&-yXsKexD2 zM}-o3tD)&j)5X9lMwJ!GW-K1Tfbjnqfd4T7|6>6D%?1F_;8O$O^$?p>Ia@VSw5=bv zko0zTy`m9$9FD2r=RpeF(#I2@6KRQ>W16cbaWBJ(Y~XfnYrYw=BE9p$@DnYBA+29% zw2R&@=wpjL%PRGpX~1V7SnO(Bs>wU%MTWGyQhq9e; zbvp#O<2j%+%W^(a1>8jG{J0jrN{`L&kH~j=XS!&ZJxtX{ZC13O771~BFR+C&TGF&M z*Mqd~_bqs~L;t!!S*qxh27x5TB09y_0`jR<_*Tn>&<@O-+!R6hy&CSv>w2U^1XG_j zH6kyWoJdH!q9n^q+!a$p6s0JnlUMT`xwR6+Kp*iv`F7}Z(vwLm8O5r(53Wq_5(2ae zY67oh=8LJibm(;Dyc`f_9hyMR%2S+K%N`1L5=?qbY=Y3%H(kA_X+73< zGAxJ!X2#l4AW`?}2IU#8lTY)3)0aktCk!uPrQW_`H+Reu`2xWI3J?N90q_f8e-1#E zBhT<35qc5u;f!DA0^?WKfKo#!;gklGh)CJQ2_P}9FtCE72h7F69_HW%C4~^fKgA-# zk#cgfvoxV>XxDeX8%9#74I~e~^J%9e!$q(8QYMTZUY&KYf?d6` zfsT@ycQ@y2{4>KGvN{biv!hXdJ|DQTo6~sTRWMClK#KEU5;&FOO3KURnb`e{70dx4&1h#jWN( zdQWNmQVSOG`Gm*cNVXg|?2Paac1b^jqT`AP39$RWNqDzsd^7!&Kdgm4%4tM)W$8+5 z8|M{_^zV@m{i_qnjv14KnjMO|V>&(%$ju!{_1^PXcQW!Ov|Y|e(?i*0RT`$xj#kBR zvM6S0=Oj?$8^b-Gv>U_aHMcr>g5qTaqIt9wU&{0bPqIj*><(LPa349^YOTK88ki!W ziYiJA&ewVXU2Q$n*G52J^Uw4Zge=?kr^fnU_GwlKq3r;;I&O|&Etr{= zgQK0Jr8Ug;%wuPTFrR)?M6@z67dLl%F#M0T#km55rQF@D058YQ`^UjRL=@*cYPq-r zj*mH54d&+Q=wb^#S9W12gcs0nh!7v#)8`d|^728?hmil%*Y{62vGnzJzDq;LRxfeH zzAd8KqJtz_gFWl5fG_%&p6b20X7sp#_n}EdjRRiz7zFA5!IZU5F1g4p8*}gHh`Oa> zP-S7iG2}57w)bG8%V>E6S6%0J%hX@on9wV_7j?Az*y<%?xGw8325VEPgG&fC#AV@4 z-rCrrn>$4_N0u*%7Bbb8jK~vhw(hr-jeBj&Wx`5)10G@7B64E|Sv!O=*AD!aF9qzE z8hs$muDmqbFpwbasmk0NFYGwCHSqN=?S0)V6UJ(*C~O-_-b5-5igP@NF5@D7-|43L zUG}RbhoOj_ALj`!k=>%J(-<|RD6*bM<74a7NI5Lh>emX_kSjh^I>QNRh~!^&^OviM z?lIVpcEa?zdvK#MzUghKki7eszre=dsPe-{PZ)*}#UJLMn2soB-Z6Bk@RD76MO}{Z zjZyKanWL*-8~GW2ek|)eR%eF3E*PuSjD|xgqgT%DG~DaW8v4LmKEi1a)h z)!wTG;Y#R(7;*?(EN&7g_k+5sIXEueBYPvF)ucG?!J7Ht66(X=k0N7_=dvGQu_6hu zS4yV5JA9v^9Z4ZSS=^D?o>J&-7Ru&|~p4Jw{gILqPmfk$EpD zvWyxO7lM7J$S5*uYDzLc!)!#Dr(^JSb#<*XOAFzL3POY+B2a#~@(EoSLjKJA>7U3%akv>3tl zsvcXfAyRwcTge<9bRBVfK?Jd#=$qno`Y!E-+3BZR9u01lwYR6*-hbBZzS`6LgpPQ2 z;ifDzF9pX7fB(B>!W9r-1s4qH7G$oI%7eYp+Cxp}kjgwS=|-(%n!_9>at6UtAYH#% zGCpSUqIod%Fot#GVH(0`rzG-&T>kL<*FGKO-k*J70>kkin)#BlH6OcPUQOo*^U!P- z)0k1_1kQnY4p}I}$6_0cTds>nSSsSQR_9E!v@jaE3I(vNCL-qt41+AP0Um&&PZa$p2 zOz>AF!-CJiI}Pr9zhJ2UcJkk7n2Nxsf#tH+PKPJiDVJ3w^l2A#*z{+zw38cSy-pnj>@=wJ0Nu*A?njo zXq&;kXWjDa@^8YlYp8k&C))=H19y=S#d@s!dcVts?d^Bfht1ePt7g1gtnc#tBD<0&JJel=Hlo8 zOa%_4;$rROc6y}W4kYK`>SpcM+2q>U1RPCUPDM)Y0>x4>0ZyWMX0~ljT)iC~fLNo8 zEzHLnsti$tpALjA_45+Wrh`>FYixf_0xMek*u&hwnkHS@b|&6km1bR)u3eSD$uxoc z?QF6K^PS_1FfTt8$|nSY8+WJ>5WjAn)y9}x+Iq^-3Y6OqJ);^2%31N$2k)Kvek&H0O?#{9g ziqNr(zFcjwJ|KC#RAN`vk2uHMI`$!KI2T8|Q(suesm}em_b4%BgX*Tf?WVv^F1=d! zkYAdSU40!xl19;>s*_EN4N3q}1}E+McZDJ3LdVi1Za>cKEN`NO_v=}G!tQrXD^ij; zRum5vj6!{6MJObx8?-sULaKr`LziBCOcfRZg`pQ~fl%1DdgJb_V}-*g2*%ei z80W2$K)r(0^bSKY7Tal%>8YokGzUT4kD7zAEWQW#FTSA+?vxDr#YKKmkLJjT-nh>N zm{=try1yqdW|6S&SVo#+ZnrdG)xAxFuO1&`QjFdJ6@r|{!G}J--3je zm>+Ejs-^?#;QPF`!;E*^n2n2y$Kum2-C<%lJjxU%**s|7^)^NuFtmI$@rGSu~q8t&vr>7^k zIq;Dg@DV&22xWpWoFWnt)z2AHuCDGbfFq$K3%>5?=mu6e#Tt0B5CZoc&Y}i<@PWYj z@ZWVA9uRy~w9|VBvMnf_LC6RUAX5Znig!(=vapT8I*FTKV=HxvWiO$S>}+D4;Jal% zGrewP;ZL{nib~EKYv8#iW@hXyq?uyfc_h8hDIB=5!phM~&zqiugwc$&XZ6J@6-Un6@s>3+~vli{$?;1OGkw6Mlgo^p7+bFQ%eg%e^X;7ven>OT)1odhuHW zSt3Bpks!OG80PCM={^L|lV!wD`XS%&zDx;N@WUf{nIUc1R6cza@* zKU@R};wPxN1z9mQ6HR+tlYcp#|A=-LKhfDRfvD(pfkWZ|@8mwc#S5PGduBE;xx^I2 z>Qk{g!3Sgt=~S)|zXNg=b|zQoZugm^Ur6|9UA!`g-0$-AE2}JJVPWlJf9hjG!4TRr zD@JxzqiU<5dxXT$%h)BFp0z=0T2kz|5K za=is=Ma2?*`bek;O?NX`4A8_^w2ty82ME{qh>hOgrFhK4t+-lBF5^`?BGlPjHORH9 z@RoAbtWKPp$E!$s%HibrwTsp;TKu9d%Z90sT{Zt-)q2PmZcAqu^0Rfh4 z5QI*f?~)T`lVX46lD~@!>cyviE)QfFyAhEZdgVQB(ya%kl#=tKm7})^eW3uOdkFZ(2#h;WcsQPDN0TGs* zgBv`=!0iBYgGxfKoFWRb5FAl}fa8x(cw{s*jd&sa!eDC$Ge;LEZm_90*ac?64Q2!Q znYEiM*v{I-l$#yO3}HOOBx*J@b}&>#LC>23WJMR{^nrI;|hYCRu}MnY=N!KpIZiluz@ z?naq{jl|lI@XXX6T<-LrvN3-gMjW1^f1g*wQM{+Y0(K zmC$;iFrJwr-Hv;8!I5RSlbqhvLdI!wq77~FjH0+fT>i=X(_Ri5B?xSpj;cq`haToK zVUX54UBK^u@$qT-&F9-_QV7WS5L_zs8v@)AQGRX+2njj<55+l+mFg;#(uYQq^=3qA z(l!K!Q9c(_yHc4^Ac23Yo-p!R(_tSXmf($E?jln5Ffv-ay21~7*E3}-k1oFV*) zGxG<3Jg)z)3i(%@;T3@h0kFdlr$+ySGyhlP44f4HY1IGX>-=H~e+w#q6EwP<9(N-h z@=i0&&&Rvy>isE-l=!cxbbWk&@@8@OESQcYspwhzR$W|o)W1X1zV%?MT4_EH3?@oF zs(CVdOMH9C;WG(AaxnHMiIj4J$9Pjb^K_s%9WL75#s`$LDIdtyAJPrp*1_jVN5;?# zedaJtBf2=5HEQQ==uJ)By)>elbQvbLu^`^^a3zJZ^BF~Fv!Q}ML%H@s{!be zBV>fOhO%^C@5^Y(Bi4uCy@R^E)A)262rG);NZTd#-I)JwABu&3$3J#`DwY2E?mIDW z9>a`LRg&1nj|@Ts4`i_JzY2_xeQKHRsEAH-W4Lvj)6ejM$C_?@w_k_=0qokz2|9oo zM`v-_&wwv9f9?mF2WK4%(YoC_zJGGRr}9MVB8I^0VS=dLsmDmZh%BqG-Iwl{Hb zgPDP407ByEa+(T-(wzc6kRT=f`SB^c{gFR`%0Xn#n1|TU9c1iGTwTGuU=4RuAf*a0 zUTb?37w>z9x;BWor<5?DpH)Pbe47pV6d#NqLe9n3x=GA*g2)v)xcAXUu~DJJnL+ZfAh+lm)r zCucEuk0VxNrzFw-=GBZ!4KW4Q!|{8IlNd`BEYyc|FqK0}8ES-($&nJJyq9yUros&x z#4`4W(1RPKGr~v-!yoKkH;SmGEkZ2iwqI_=b}oG15k{lGjbL~~_UW>5a{_0^V|`>7 zyehUCm&YhzY35>mkPR4r0J_CFE5J4K^}&6$tzZ?-X(PdWtV`u)I5f-wxef-Vxv^|l za*wIO2Z%fk+7AdSD8_m;ylru9P^LXt6_YPbHjCpL9x zVC&>Ud8~K;DnejnWN>t+GtS-asC2H4SgbJ@t^M0C4P=YtH-g`B6-9~8>bSg&+_FQ5(T7gbmkywGl&#m(6Xq;v| zVvau*_6|Rx8BSx?(KD6nC$()>8Z69@vG!&zt5dbRBWa;RDlv>i`FhdL7R|)QgM>XT zfa-N*V0-JcIM?on_ZUMTvV}A8*&uT3xH8umw#Kc}m^_kXx1@sTiKF0ys7VJA32u#%kgZ3MSX$v%8=6A zXdYU>F(}##wdxS_Om6mxJoB!w=CEr5-UVt_@xIhP1&NQyc2Y@pk_LJUcvBj&)gjHP zIaqgA9H{c-kGz`l93Sf%7V-@D&Dxjnd??L*YEx3nZ7Fcady&>U^6jepU{2wB3)YZ_ zs1I)X`tdBQzPKwL!>XdmbJbnz%17K(H7}uHuBPDVy9Ky~Q&BRx}ZkYalN*Py{K`VbXtdAlo<#R);BT0_xqUc3z1;Wp$ZAa68u z$k!n1kgGW=IZELQ=fY{`V)wgn^8B4h!ix!hNhBbUr}D@ROg?jln33UCMChETK*IqV z2RA;4DfrbybL+kbYy0F-na163}JBl4ADk@;>arR3!g zVAbl?EDdg#nb`f3{HMyZH>i#82fhlL-=!09klGL`s! zx%|T(3k@kpfE^@7h=-4`G~o4%QG%FjsZ}HS2_sKFXJ>^Z(b7oQ$(P$&Y^4XRFM*I& zkgm0tObBGUNP?mopfuh1R@bu@^1`|e&>woOYN}VhuN^1ON_yC7zEtY(JlK@I2BI4H zx>gEpFZUyHLrUwcQh3+3fUFrqv_2thxB`;Jn5B0$iC{ zLC?~V0Bu3n^t5($g#*j4PzgLn>jq@0e#Jjv@T8Fk5YKgmQb8!r@Q3in%(M8dj1-vn zjD|o2dHEs2e8Q*MXg(+~6aeZ%;KP5@Rs2(fNQ$&tXy&!mag6sadW_a{UQTyOw>jf* zKto9b+z9BtkNINu)+ATSR3B&6DG>8|^1f!no+no^^2k0AxqPe^HSO1Jx%qgkp5Mq; zbk|&PsH0+-$f~cW|HHGl;@tEL>s&A296H@oJ+Zl&T1&P}b$!Jj4S~jJcJ)dMa;1LjMRSJ5y9=oI70l5LqV_cVdl5w<SHBCAQ4#^tt6 z#7`Ph=mLyRoW-QoF%DsCH3Y-Z*P1L;3zzhiktC11+G^IIl;~_L#+`Is@pth}jb(8@ zVzy|LJ98E8RW*^Ao=`8f(9F{6JQedF45mp~Qu)AjoxdXb8=>00iVsc!St4I7q$?kn zUZ3@l)bZtLe(wOP!U_zF%*1}t;aTzEfzDpt5s`salBi|D{Sm6P+HhVKu6-DffD{H(ma;YG7r|qvMH+@i1BvO)| zZ807D(C!||((2B^c8IB6qxPCfQoi_prOq97#)|ZnWE-A^n1z&U?8doR?8^q)H)|gq zr+s3+s*3w`Ts1EAJv-hvd@ZD~p2L;SJHzkr&XF-35)|@>Z*?ADr-wrl(CUO{9Oj0o z31k6&yg6-uI&02AhoAy28Aym|7eYE$S-=cYD&rFcn7NMgZwZ6Cx5c=BD+u`89WJqOPt1nlm$a}(UIqqyQ-`{Mk&!{+*Z@AjD;-UTunt> zDW5)Y5gApD*GI{OUFj$Iod%mH#<~H6VflB&6{(q##4K;`^RDqgR&E#i2#@Sqa9GgB z@`Xe@`Z+w(bAM1bHG5N0R^gHAk*X4=atEQ%BT4Mep2ZOzocp{fFGRENkLw&@&9AuZ z=Fgoxo7SyzeSMX~xvD{Fzn^+y-@7O6>2bTN+fsEiyATO78|}QDywk_>1~1%bjv)l^ zS8YZVmRzGE1fHrWl(KU&Bmt%0smk6RuM~XHMW4X=h+G(JhxF2%|w{;*T4C zdP3#`Ch7<*q33cI!5xV+XdfTF%itofN^`GF-MMlRh5erHUSpQK_%MzTj_Djrj9D?` zf+eb$pXe;V^rA(zJo5bWd#QLTiat!d?g`nYU#!+R>a}4*w@k)aou-ApXV;hKaNnrS zhh5va{Ft~^^&05CQ8Y^Wr)Y{CV>E01C;*475H|0sJ^x7=X%z0wBPaaC5 zgrOMpp-~uM5wWS>4CpA_l$$jkFN2w6YKFLVlLW(BC_RogI;e%+Bpfc9%fN>uj0-? zX8>x74{%brj|#-kkpcho;~CDQllv4u>bOUb{U^SgUch%CMR(qkhe?D9FU*C(^K;x# z76=m@y0M68&NlwScc5zbLebxORWInQsu%VH-%rsUNVEW6awLe%uZA#k={{n5eA@B%J=^THq)TbyWQaQlAPL zIg#>>rd%c31S;-?VoIPg1r()7d{DAA9EPyUqdeUw7$6bAb8$&FNYl6T3O z^#b{rgVk+|Z;ki*KC*ksSz8<18bv1_XECmdb}&4Js#7=Y)bQ&{f2t@(0+A;m*F5#& z=A#Rg!;y1r#MRRe5Pdg|K81zLYyUM|aM|v07eTaBC`(DU?C5sgbKhjLbj2@NH%S{9 zyR%6|{QGWo@*3g2xgH?7-cpKgo}%ANnXwYsM`t5TZFi-sf`yLeqi?xkj*YlN@l8Ug z1lWVko`$-jLyf?i7AtWgO0$%Bm zZR8EV@=MLde{CfrR24W9W|r# zC8N>qq?S+V(N3`7OwuJve6pxZj|RVCd)-vRW((l^gy2I}?NM6utWka85mjan#eHS0 z8+PigeGhX}jpb+F}yjQ4Lgxb-l_m+-MUe15{{yr;yEttW@(Pj3z zhI_X-bKI?bgtctJ7)6n|rzEoA9QU<9XrDy} zlP$qWe&aF~M<-oMmJfD;!X5pWq(XfCU3gcAh^dAibXQEH`@Nf|lu`20Fx!oqjaOO-&ALlzKDrjoAm-9$HJ@~rhG`O0tD(6q9 zYO8TiDyqxP6bnB@DuORMs1kDXqaHGEjMdXPnt7P(iKQW|Nom?6n~xZl>zUkp=}hB; z5q$t`^!S73p#D|KfBAratK$EN0l|py9&j2kaxfw~a7MsnAtIc&lAD>MAVPw6ARIqj zJ0wI>S~xlJEF$1D5r^j@I z!JA`Tx&KhjQwP>SFirK6SM5ej`m0^f^c{~ePl$RuU06sMRhqbh&`xo>_DoS)J+JiF=?Uj7|J>`fRLx1!OoSXS@MvnTW*D0Fs05N}ltfR= zE+3Czpb1sDyVIWp0x@^bv$(q}z-#o+cnu&h7cd`=V;3D(mFrNP(-;P@@&K}mlBN`t z8^U!;Ww4o599@8Z>VLs7fbBrhfQj9YMkNq74t)A4qX8UND4fzj1b})*z+r_5@WYV| za8`c}|4mmBj0nDX`==`!AmYF~nb1!=nVOK7kBCIJ`0s&j?W`J)<~&bWzm$IDdG~EA zz}_*2V~`m`pJ^}G>X_|gFZ0{djrktF(EW-+4AG)W1;y?G^%(DrLsXsHuRjTY9wx5J zSRZe@!+$xv%9Wy(hzzDCNE`zc|ejtO*BHM{YjC-LZ@Ow-*G6u8y zV3LBE&^nT3;`d_)CWF#3t~UmVe9`R`b4ZAwe0WLNFOX`jVVwr)dB9Xn5T$NFSMKX0JEnuURf;{DRUrl?6F0&_{YXd=@gqP1HF@6GxK}J zRwMz;hS3KFuI+)*VVJnr-}AncJ5YlKCZxH^tjJ|5acm{0yk1*`j1f8Xs#SWfAP+y$ zqfN%pn-W8(F7sI<=53dIGRC6lQu;`0c8fkj#Bkx*{KUkKBV#80j!}nD(saHM&*dcB zDk`+101S=IanTlf+vxbqtjgEaY_l>VG7r4sp&JCO&mZZw9Ft>xz3a~{y}0oXgTA?* zsQZTH9?L^%nRr>PYUgy1WlF+QN;ZUr^!AB^IfMLz#LDLCmxmfN2uSL4AtMCp1=2T6 zME!|)$3y9Q8&3W{Uyg5#c)wP@XuZ1n!K4b$m-w$2m5HYt0F$RK z1{;LsR4<9>e%Ht!;UloDwTHDU0GL3gO7Lt?9(ZLA@a+l%@cipYKw3-Q(FJUB)`{c; z6bb@Z3}C;V_l07@vk5;lWT$n6fLa3?v9rQuVF*7!OHN;Kj`Dj(?7!O${S)D-YGvj6 zIybHV+RK+J%hMvL|4Nfz+3rKu2mJX~P-kI2)8$=f3-8KeSbpK1i8$j+64C=Dw!CeO z{ajM7mluvrGTypYF{BX4kQ;T?(COG=qTFQY5mXiRD;ymTFOMveMIv%@cEyy|MLM7& zwv}FRG-|L7&dbz)r`$}7=rX6`_Wp7}z->C@YL@gj)q150;@Wjn6)e};5TTM5(=$xX zpE;&K(kmIHfA(1m&=&B&XB(T8#M+IDBhQ@70i7_`@r9Sekv!i9-~q zF00rE!qzX4C!6es^gn;G%6P?0q8ORGR(z0}@n&}d%4R}fXL&DHB(1+gj!EQ<@cbu= zC@-#{@x-nq**Ifk`Q+#drW>aj=u3@m>mQs+Q^oXloKfY@V) z_bU(f@}X`nb7aFvK?mqdNlH_GK?woGvQo30vwpI{H;MCUyv!Ph5Oy^gC}&186A6 zXS`HiL63p?*J6+IHf_Gr?_4)o$Occ*y{(-2PHsL%sBd(5lU$%lVK7(l&^F*@h47Vj zs?Hd`nQ0#K?`(Kai$W$l9c0@~1n!Z3*Uh-&VL!E?qy-O8OkIO<-X@wB<>{zggBR&Dnqi4@Y2liYhB(2dAF)z5U)3}W(!LlXX1+x^Sd z%YDcz-%IQdhF-dMr>KZNbJxBH@3*Mx-|p}?wm%QIY2oe0){={>k9l(I7Z;0Z-eqZb z)3S&UI}3=y-{nkAXL4%JT4xhBzN<^fHmbKh4mZHy&n@!TLy(L1Yn3I zuhy|}ft$sjvPFF{I$?NwKa_3_wi)qeq1{sH>8%e{7#ts1HoRJHOK|SivIy84MIqKG z>1QLNq(2sCZXc)#=-74)e|}_c^&#j|@(1bKqZr!PrrRwVmbG@xyW4cO*n()J0YZMo z`u0BCg!0BAQ>@4>Dns{MIxRV@2o?h0Ve?tE65$X#>;}-8;nN<)QZd`x#TC|?AXbj$ zv*hACXFhq`dDxkDt(FrFeTaKiqpIi#Q;sKZYv(lK{rCJEAFeneK=-Zykf{-b4}O1s z5bX=`MfvL&;)|ztUd_?o+V#g;0a!#tQZnG{CT7+S@NTMetNddM2xwn~drqfQPWd-b z;t$})=?l}|IxAg$)x=V+&xm0iahpGJu?@3(YmT_K>x0gd zyn#m~DMV6L^o|-vOfAlGPQ(`PG@{f5vyTIFnK^}mRIcrg2x?}%MDUwT1RM1T=7~XZ zh29i%3a}W<)m23;rKfNy6iE`TO48@^ct6k?ij+6^w4Fe`ht-F46$fS7??E-M^cUjf z3Pnl$hxePGL1uldK**BWV0CjeP6s-C&0(jHVcgP&Tvub%%*_Q#19-Rbd_MItqgbMg_rbNUOnLGYTw-^AukkXPJJ^*`?J8=nQ51i6C_rf~{ss5`OQHO^djA#+ z`MG=ma3DFEQz!d$@eg6B0I$GVxDdV?2rv|Y5C1Q?!++5t5=zuN(qJ#;`_^vcgSL?c z5+&1~ew4MsQeDUG?H#1f4L01j(bINcZK~sDfxu`FVSjO{D#= z&lU#0tDSr=UM)g`=%-DE386moMgR7J^^S7#;o?!zT^98Beu-B0uG5YzrSwR3X|*g; z`pm{k7qZZ#k1>ycy{hNpOmERGN*q^L=VDkTqdOKrn!hAr+#Sj@7i!) zYK2LJdjsZTt!ZuPaIOx&DldP00RFx5QWPS5rUlTS4(N|Pf2zU1azW3XR}c};k11ea zu?-KH3%t4a%;5dKMw}YF|IjV{Z+?IOWLaOB2pLu)^3R!0k))s8)Qe$coHV|hFcqH~ z;J(pYyUsyY*(20mu$)aVv$342L+(o~@ZW71K zU=rLNLFW+TXG99VCOhh+uCu;Gy)@wc>E<+U$5XkaHm-LM$T)owgnXpH+uDkZ#&fZP@k2c`j~X5@rF$xbL^RA4XT0!mH(CV{;A6LKZ4+h*vKXjqug6L z`Vd`+4n&(21E>kMgz;EfTR?!CK?oYqr-%zeqC_T+TN$SeFO9ux+c_L)^HPzV%a?*1 z!c59|o{<9y}kQjx`%VxU|4n25N5-L5L zN*}aTE<@>`2c_K5!>#OiS@}@6bla@IPL)PCUU@T~l#NcW4F7A8hA_6>z_xhjzS+{# zCHh__k+p9m7V>*k1S3~n^KZ)^if=qJGJUx%aqz}Xhm$-rsJe@7Hu-*`(}z-;7Bqsb ziMiJ+Fq}DInbo8ciX_y*-%1 zKQk8Rw z8PFGd22~d;$<}98KXxT4$?m0nRV5+^z^eFE4zh#q$MtL=1CT^AJEJFjKKf~7~4+GvcoM#;ERK71~0Pt5P` zC_*>JF-FF}=bc5$zgk>##4IP$Lkl}h+ArC@{wgh1yfB;+TY&FKr4SjFgc=&SSwe2x z;X5@ubjSyu*l)JsyA*`{wZhOT^iS zuUK$eA1b(^PDhT4vO_|L#zX>5sUE%1QEIZ$zGg|H+#-OsJmH=y z&VzgzFbL@AOr^F}BMtoE;{}t;L!d0j#?dzCSFB5{->%kR-%)3zo3$&YlU;nx=ygs1 z1!*Lp!*Jgi;39s29-E)*F?s1Tn{U=NB%)?^<+Dd!xqs^M&ENI-7dcmeIi4x;X#SKk0Z&9f|MBOTXKePeROn zd!#ilEqo3|2b)YH>e^(;5|nRxd`s~kGJ!Pugcu<;BUTdsTy-u4Hh4jJR8^g-THuEq8lB>5rt8EYpc5Iroq`!M)dY1#n|^9Ja0aIIkn~X z;#$y?8pq=)+}St$6*!ch@0QS0H*X$ggw_g{cPx~S?ct+3ISZWW`2S+0nQKBr>ORSx ztvEpwedVvVGikkiiGK*wsUGS%1#rEtwED|4FloJ?2FAb(=^YT6b8fSoX2~0Ua5V; z6luLKSzd!GrR5Yku7sD4JER(d5@t#DptXn9&VhuAX)dmMx|;1~*ZDSzddEbNoQ~d9 zN?Wj(q+i>BXfY5Q%{-=QUrydS*ysGR-sdGhS(otbAr2=cG2)fLE$N&TG(-Er0hI!| z*vEwLpU&&8Ooo0|b$EIiXgbakqiJX(!BDt|mOh{6T^lTo~| zG{tFkGTa{kODRCl`zk<0v?GDHwq#STdS^6{Q#g842E|Lacl zPu0m?+YtfdUeGVXy$79XGEFbOGzq;^b8b+HD|DqXa7Zl!>68fz$?%Yg)AbBl;kSF0 zQGht{kGQ-;KEJQGs@L8@mMs!FJVw4lyPbEH_0Yt(p>`#YsOE#ol@Ytq)vrf}8#L8f zIRg5*iTztjiQmI8QLe1cV7*mue3c?}oUq0#z%WWDs>T|YSwWJ_J8OcYaMf74EK%Wo zh@QsHwdgzbw{l;-PE)26v}{yd4yh6PpeS07XBkI^_8z%!(*_#xvaRMY+1c09ysjoe zS=txI4Y9%AkN=dix-%I3aVA&!46a@4h13;~HCZUk#0GiXR@aN^Pf; zyX@?Tx+(Wsc4?Iup zG|rl)3y@2&p7C$=a%o4!;~0tyb22H-8N{j+VZRZ|s}|lU-o-I9Md$MA`?XvKsY+)g zGs@r!)5nH7gmer2uibOnZh6PYP`%Muoriu;^>s2TjGumTfK=l+Zv0wOg`r#giKtID zC8a`wH(x{WD_(2RJqJ3KE$8n`mM%G!tp<0NkJ1=kgw|8VGTxWiV16?UYuq%D%jeK9t+SBdfS8*zww*j7!}6y9BQ{`XN@yVsbm8NQrQ(cG9})Dr~3 z^4mdAq#(QURAKSuuxAsM%cS~V?lkv(>~)Jd;(X^jBckxrlw7@f#G9`PxN%Hu`&(0S zG+u6Iu6v*-?qU*e5%CFo^6Exahf4KFA7(sa%Rg=A|B)v!0c2pu%jC4#_QXXq9I4I zD-Uc*5Y;S8W=(Hg2}QRU>k_s}+7~swdogF|jG6G=D5$=H?0m99bao zU<-4#b$5lH*B*ed>Ez`8CKe(vb@&6oUrsm=x}ScMmIQ~%rG zqt)DFr>47!u5{y$#ncaf4E55jY7B4Wjom77}B>4pIHSc&+G@)i{ zZ`4-W7+_G8s-CT_uN%!i6+n5+Enly<`Qd&n|aNHA-xXtzyUy|OYtGwd6C;8&N z=^M9}UJDx16lrMXbaO11#3Vwl0lygCHf{EE=Rsy1TojL%JoTr39oA zl#ni^JEcTQK#*>vL=o;>pued9-kyEWKIfi$pNkLbTyw5D=bGyq;~U=?<9*+BjtjRu zIIOsw93KcVLA9|!K7w(b26b67rn{mKDTEjgFza|72=bEZ2}(nS39N6Tz$tVK*wxd@ zp-6>egtF?a$iVb0>8`jqC+Oim#!5W@GE*+Le8-`f%VwpL&55SBQX}ga3O5W6sU}~B zl;+JGe?$ovtcuII-9UpVo}>P0=K#TTqn#5sD!uv12(+B`GbJIYYqXZ zg8UovzMQ1$Kc$X=c<>+PeSe_!zrTg_3a!ufFQD}~zAx>7p2NRi+WkNEVgKZ}N-1vK zp!MX)Fhnj~mEo0t=iR_3PWX!c{W&evsm6_5(+4=zNBbo`Ea7@&YjlPAB9$?p>eXt? zYh^0WV|?K?wsu8l%#Cr3h73{iCg(oAZ#TZduZp!P)u*NUfNGgO=2qtBQFdG#o7AMJ ziM6uKXv~^}lH5qRl~=dJapgNqml-cT8TGNGW}N%kWrsPGA4>@zS=?McgoD|QtzUvz zn!Qtve*yLKkZk}3Z02BP}ARxh_+Zbf55)syDXULT*rnuq$kK8n)Gl-WsMT&|Bj5X z-JrKfyD9>l8Qn0Sq&piT{{wBrk$(F=8TUKd<{z94$zo=ge<&4ATf7(>itOjh7~Ewlz^=rABx@N3S6Af z&H7KR+w(KRh3}I{dk0N%xC43C@C?JQ&m2ed;4F*g^fefu`ZoDqQlGpCB*HCnCEe#?y(;04YoYh znwx@_x*tWPA8@M%8H}tkd@ROz`)u39`T_*xkSMP5NTfi#bK}atK~ntkumIrw4*=6$ zDHb$f|0RzIoQl1jnUm3XHbrp0_wt1+N5k?x-^&8DHUjHYb{-ZsaK88Y=6~kYe=^qU za1we23q+5LPU25~eA^?w(`AFU%$&vST{BarcsEQyY-A5*ccNdRp@^vUrZYX=Jt>H6 zFRD-OkKPr;v3M5fWTJv59O;9eNRh4m6z=mQjr7k?AwRmVlQgJPDa*U#n`x>+Yqns& zi1b!7aL~C=4#$~%KvA7~H*skm1qoJsdE_He;HxgI_veM4U#&n12czN-&OWm0u+FXB z(0Lm>Qg4$+)hJ z6&xJ?M#6K6e?Wyngt;NHh#YaO5~h4T*9-T{_kU?D5d;;zdPY?X_4M^BBNY$Q??>bA zVDQhhnM~;>w zHF*UVw=9jSGP>?IHf#k9e+Vk_liH}`9p4;6X#)V!x8_oy?5h^gYr9%B(1h9$caG%JqbNE zN4z0^g859D#{vx1kCFuD8R8#a1Vo~tY2C)xXjDrDFA+2WTamxA7iqv=Sii*sVx?vN zZ*!?%hJ$!Qm_7;F{POrfg5TSK5wAE!!FY9Ww#Uc?sGfYQ^orUueUB5Mu~5YTo{jGv z!kSn8!9dFs8^Dkb1ou2wMg(jEh$et?RQo@Ffj^njeCc|!;*B7UssUrOw?VOF>Ml&0wn_`WLTt2y9hUrzE z*b<)m{N=VYlP5A9Yfz5wLu}9>M%DrycfAK9%U8ulf3x{oC6l0@#W14{8KZzLWt;k( zMHvE`Ov&5~_VuQ&(0=mfcxqY{(aUMd`mV|ORvf51 zMbmcs0!&A`H=gjl4YFE7Ps69Hq1E`X%%7II2X&3x<~LLNwGR3tTJI<*&+}q%{5-QD z6YF}>fn)d}9Q~J}acNn(1Pp0-5W3HacWBJH?lcE=3(B-3WF?a7eVEb`8x=qiXnZJ> z-xg4up7nMzWzrMUHhGoPn3*30KBU*F5m)A^LJVy5q9fwM&@8;wRB!D7T`Kd^wSTdlyON8 zeNdM<8bU*MVh!!u6MLoNWGi|^C7G&hQL9;WZsF$WK7*2@j*Z1b!SW#I8I(3iVqsPh zz5xm$7Gl%X#4ruFA*>g3Wz;7w;*_5?%B*VLyIjLL|pLb09Yv@AqfHkzJWb}w*eV-b0@I$r5(`x3FOvYO~G<802BWEx$;0FZxjhQH(D z3u#1<9#FFRmxuayKek?9-u|}<-uLO z1Tfry;qXN0FaZCxKafWP5=meixiXmmaAN5vqqz>UG^~EGrEcnriBD}oq=+Nq{DSus z^IC((KiK^nc_`;UCl5t@Nkw&c%=sC@fejKUeoQZZv-Lq z^35JdS;78fSiQ%N`H$^uyc@avnik?IZSD6EOYm+kKsUhC_LNYqeKOkndKP*+LasC!gRW(%LOmSpRz+PGk%MmH*voIq>_{@Z};fY%VOn3({)NU4=szG1#VtwKG zVRA(or_Yd#H<%5KRe<=z0f;@!uHp|Pz_O&i#UF@(p#X%|-atntBJleg%=*sv038tv zT^T?WUN&U_6knH2=-)^Ik+86T+I2}-tbP@Gfc27CfdRn7dKtfSUfTryXU_d6FIpR; z<~Zs<>t*Fpuy<3DmCxAX7%>rkcIDPV#?+{=s!d6zcN6~Lm%By6mc%zV)OwiX+{0a8{JTjm9$uQ#{&a#3`qJA^ zTgl1l>TYRcg=z$i?2)dnDUgelK|J*dUtc$JPI&A{)xc=|{zPtXzlM&RB>;tX0isn2 zO;-66jCP@q(^y?7-76DxXu8U51r%-lyS4nNM=o0_nWy{|0b%*GhN^3cocvt~@u|6( z{t#*@_!5o7Prch;ejzzILi^7hv>l`+9@#(((v=ql zBM|-=bzC<`_;w{wUg5g<3l56U7ZeO^!{zCb*Ua&6cmK`m*gzn}&907vPo9&I*yC~Y z*Kte?4`tLHmhgsIztfQ}oZD*;AyrZCd{M1`Yx1VNFi9>)MDC3WNd)?wpIMV37PVto zp7V!blaV~N1;zN4Tc{qx77cfMng#Jt5?8unt>#v%nCB9GhA{>C1^na$u`Q1<6vtZ+ zW1rq2Vllihj3ie@EIrS*>m2cHZlc^iThimutsx$y^#Vsv^RlYP#_#OkpDZo zvbP&5Tf948DkKeljZKuUIcz|H9Pr@a*aRAx2WT<|B+5*UOo6%P$NXUe#$p46c(z6k zPWI+zV5A|qM+z+D%*o2h2CSL6FSBnvAfPqslB9|Q9J_#tGQoZsXi3%v{TE#FPc`4Z zB%A1sPha+PINtloPQPzgp75zb?}5^<6s7A>u&(GM)T2pt#~`rM(kQJa65&ceQc6t1wJAv5Cg;Bv$>)<5rt7azKlHJr&0T$1H;wTMk1-`3 zi{kD{=i+2$v|o3Oi>-FWn$uD74h4D%GxqcaW9nT;i6)WxSCBJ@eq%H-ELu8ay-@j8 z%6)dpUqm}^P}x5`eDyVxrVwRZ`~d3?(PWEzjIaeCaf0a!FQm@3DabG$g5(fW;c?zj zWV_F3U5%31%{+2%GK6bll88)_;-?bf+*vF$xZrsG!^Mqw$h&We<>D+8etHCY^(_au z3kul!8;U8&-|E0W7DQ%)n?)SN5CXpAE-i#r&Jw5urT}|F{2bNv9ZZemxp(YN_Al++WpCYk5gd&6ygfoO0ggpc)gemYZDa1YC6;cQh;1xUI ze|EsXZkMmHLvUTbZUo^3VFDa^@7oc;jX-b%zbp`3zZm;v*%;3!>$GaNvvadVhN3zf zs%Z9Um~;i2nhd>0B=0iI?0E<4{;G~?5-01;t*5N_Cq9VPv|!Nr*YjK3d8dt)oVCBr zT`{Hg9$DZf4y3=JHY@#ti_^j67`$A4@i|YT(UkSoF=cQLwa5`^SsNBQ#vnS*OOaT* zQL%+2s!bM2%&&CQy>LS=#Ls2MLupPu*dGZniLD*SD8z6GQdaW3Gog#MAvNew#*|NH zpes&Ko|F8TYd+I98kCrCUXVeFwvNOWXNIWVKBbB|TiPyEt9=V>#N1f@J#ZH_J?EdUF&m$hS z)ZuM!xv3mcKt@)Qt;u++b)|pK#eQY>z|Kwq(-)C1J&^{e4FRo^!2AG10L%|iP#6#q zIBeD# z$vJD@013mHt7bW#!--H_bel>Qu0*g8`+ad=2^>-4;-~ce_l6g3ey;Sg1JmcBDYrLX zo(rf>jB2^h@YxMzVL=eoQD-kTStRvkbyhx^?RCxA1f?3}4oqb4d}cBj^?s13vJXR<_T7fu!4r9yMuep;fUZVV|wC$@er z=z@fmR(~jWt762UqGmKqw=#3E|4qS^VPf!|Ppw=;Mt!Sgoy&34s`zn`mH}oeXt34rLTlok9!^rbqUT2%6;U3yx^=I;$*K=tYY{_}FvOe*djnWPA+t36b zVgO{gqW0Tl+5~O?GAYj)ro^vxea&3ljKl(Q!X*ys-FpgxYpfYAeLbs;u8X6;%+S>y;;qeh&@h4o!6J$ zbv>1Fc5Ui!!Ph%bz|^%RT}k6(PxdORlg}Mgs=LsQ?i(MXZAjPtIu; zQ#N`3Rk83r3Bw?zvQt+6)w5$NtZskYr_I`Dp+oK-;kQ#4W#JJ+I2u0ADRqn{)xPtU z-*Na#$g_zIrG(8G-H7|Xb^fmFDn-fGp-9z(cn5Tgm+5dE(l^KGJqMITvOP^kR$gUy z(zkIoVWF%vn)rHn6(FDp65JZwKcjwBF)ReB?Slv!YW+Y*OVlrLq~yOCn@c^sZ| zn4tPC7Veu>j%cZaJ*XMcOt%&y9|!f5u_@w_#czkVVx_^*|#< zWE#&fp(0j$lrR~Hr|mV|&>bTm0s|~YfuC3aiyLx<#|;Dsm%jC<{me%N0|0hZuK5w5 z|AY`k0A7e9Vqu9px>}hVxnE^~erDQ)#v=MM;^=$;P1;o|{`9tzxbP;fCMT=?qN1_s=~tyEg%neV=|Oa%h_}Zux!LbULD*?$ zO^NIf+)g}ImQ~a4MB`St``Pvr6USR3@6E-%GFShe=UBx}VY_$iiVWzujiG>2)_F`m z^p!1|gG~P}q5GS`UC+=+yR#}|%xK|q>d&`ga|&5Yc*|yAGv~kEeQl}$zG7(L^SkOi zOM}K(Syz`GJbf%sC-Cdl>vRPL5Or?J8eb*R!wfD>p8q>p{n@BP+ z>J0CkE{VR{I6t4i(eIJgpf+7#1s9;5CJBs1p{w!82aLz3Q0R=e&ZP08a^p5vFODL_ zn~<)5dtkCmgP%v{KkSU+0&#$cED{#ezosw(p3!(XffUIPk_J|8uuS9khRFZ&8~A4< zwnjT57sZ-9$lqp&C-m?(78{%_WzM!5W^!kNfBom6R?@7`%s43C*@ia09t@x1(C)lA zzGYuNdcjPiY!Kul)8SeB$(+Pr^{lonT1y&Rxg&Q%JyMxHk9XLtM3M|MHc9N7BPv^q+ZJT_*G=@lA6yr5U;2 zvq_*8Z=V#-5HCf*=^9e^i7UUx-4%p0T}`m`He|!WuqsVAj>?5rwaIT<-hsVo2-7U$ z|8@A;Gh#^IlU&`>+;=Nf{^WdhVlF3$FQg)j+y^L{!yXo(ZaCu$f0cvY3maK>k9ta{ zaGZ>ScfW7)_i=>yk{H66b*+k%N{_^QF#I1?K(2{Fc!a&Di5VF&?>H4pf#IFy)$WOp-{{mx+6-}L{`0u!K-&jn z@rZt@pvSEaR>K+kfsq^%(F(V!NK7D0mXh9kXOJIJ`&u$11uLFCV z8(8qdPF9{k8umK@3_KR1iiy38i?gZGJu?;p(9NrP6hp#Z%*fQ#1DtvK2I0R3nzJXp z-1#fE-s}f!^$!#e55OjKZS@RLO|bptssjE;+~uDl@@7Zl8~dNN*iUZt-poDmm(pA( z3&P6pBo&3^4c=dQAeBkIaU6V0KC5cR;c+)BWI3z=y!_7LX9Z?05ZP)GzPin#Km6GN zuB$(flGpMnM~#d8^Qb_qr5eHK&_SPbnjYd<`^_P>*WhEr_HDF3gGu1M>&=RC0AWtn z6J=$~8HsVTcC3QXu!{RLROIWi*}L#_hyt5>-aX!5%IH<{9vNFHQNkJ#hy_G4JQqzO zpD(@>kcvv%N%(wSkGLiy1BA%)dOytni;Ug?>(&EfQA&0wb!y1CDqaUVLA&y`Ct;92 znQu;KRBR2?n;BL$i|P#Sp1tn419v;>ws!8m(X!T6L2Dq+xQM zd3Z*9XUHYexr$q48rJI*lxyABr{xnbjwj}@`c=?xR4B%3^ux*6ZWw2wZ70gC=b2j>MV6Q;8eK7% zcM$R##lFJfaJ8l_vF2`buT7dBF!*AhL2YCXUcg)8&5*@%GkQjisP0>RFktKRBw*&sZ+3VSak0h{K#vTJU@uK(iSfUQu;BDgE6h!7BiiSD*_ z{Rx6`>j6X8%v@XeJK*jH7P5vJQ0aHFBNa7rFk`_4NWB5;hsQzyZ<4Co-?zJF>Z+GS zkAP5`owMsb7b`o9@7N8bKl4VCgKmS*42?zb?JSA_>&9i3=esnps4xp1h~^vlFbX69 z@VEu=&|e`~Ki_Ai|Mx!eKMSXN&8I%Wiw)IBGVNvW zVu{~_ou8w|RpJ!JxOb0t`yAZ|Gh;bTB=y{orQN*N`HtiZ`C(SBgs^IqnyG`2VpHQ` zn6qwj9|_Lv$%#GpCm)N;!=vxwiVTao+DgwY7WT4SkU%(in-8H=-gxkd_;5^4rs? z6!@WM+T>51iIOI?>p7d{wl|&>ua!C$HJLOc-H>dXo3KY1I8~OUtKM<_p zfK4e2=&?$=>a%(TT_L%>!a% z`PNVXjfH*LX>)lrFyVb`X9N#n7NC9!j9Wm?iv^r=V!OWiUwZ97l{ViDARsabK05Zp z&OmySYE2{rGW}XOk4g-uld1S%V=$^n)MBpev#)L z^##zUeQwW(y6vmK6)1)Ouun_$&Ke49 z>!Bk8}pLy@8j^Yq9)&?(|xLwarc$Q_0Dr$y|r2=h1lT!%vdo89jp%HNdahot--Kr8( zSFqu3jk6OqOldVBNcwvmsERdReITaXVeVi8zIK;l#l-u%(@#V zd-Sv&w8ng6W6Y5(?~$du%hXR`*1tXAnuEBU>;a|=Uw+kTGCcxK0bW(=moEo;J`h-M z2%KVWsvGbtzJ9+UNkui}q3#<;m?Aiw9Y@H3rtmmXOQms`Y%)ym3D?;d(^mJ$h*U#_ zjq%U74TfFJRuwy&nd*^{N~+87@-ZXd7`tz%TW=wb3bpgWf&}CeYBQyw$9$+|YR<)8 zf5vAcu+0-0nH}iqnZQ*JQs79a#8mTHUKH6}dJ>P&BC7*m)NPBArHGe6{;V4D5n6?3 zt04pT071Ua#Yf~1g(QUU>ayag=S)8M-OjwTobmZRmbL3_iCpE;6~v z0nezPn^M7HPxd~t8yWdsWm?9?Tw!>1tH-0T2n|-<+D3yh0fsno{G=X0F#K`RsVDXZ1w96w>Dql&;@;YQIy&ecR+5XBd8)I5kH`Bq0O1|kyPfFz zju@2%i&t!QVK{e(wyiiWTv6^GymnmZvv$sbmgC40yV{)zw^(RflbIY z2Mr|neh9k?Un=N`+S@v~0s+pqwaGW78zd}>pLhRgMFC_9{vyI-p#@Q2MJ=RPhyTJ6 zcJ0v1`T?M(0baoX6nX66oZ$6MP{99`8~xKN=Km{jKte#~20}3d;WhnlEgZikGk>gP z{&y8PXn`SislWjMk01$w-<#JJI07LNK*E1@b3o#9{JjLnw+>*itcKAQ`MQe-GcfLL zotZ3MZ14R)qRb%%epDnd0P6vWCyOhKBZTc=cp6UMg^bj`KTb$U7%7kh02}_+RSkj) z;rSO%Xkr9rQUKN{SC9DGJO&PQf$|MR`ZObrCbN$lOg+q)!0TFb6ZshCH|H`XPK~)d zUCMH>kCl(Yl^`iRnh01=mc=4u#Nc@X-)i?&k?K#qz|kX$Bw}smW-*r3>t2X0|3o45 z$v`trNlzoab@_sC!0EPK$NGBq{RsvK6)HNjNm+O_%PMd59IwdQ{EY@qK%;TlR z8g4OuT#QUmy0a#|A06wcgywOgT*U-E8dr!?7DO2YO6;5J^UhH@@Rdx;+vlnu2`ITk zIzP-K@5>9@C)Onq#%1(PL@Znn7k+#TKwFSDOXwq0b*gd5b%7#MEU>!~NM1^GPeUSv zQivorVj1Ei?r!*@+6}gfiQbVO|8Q~P4)hFKU-b=|1Abio%8#SL`zptKy~p{Wv1b+8 zzx9(W8rZ9QU32Q93M}BS2v|HKA`7V4n^>8Fy9Y&$Yyr64yqD_a4mIi9c-wT;3lA1`im5exrZc(;K!#rvG$n@AuWa@3|hhcmcF z4Jc30S_svb81jdzp-attJDcsUk_N;)_5sHCIvG3gRPk%MqMmTY^&BIOZ!IrB?8!a=#pLDYWY4Np&h4eLk_5$hfLfoEsHCan;HU`BrdOi#O8SJO zooz!OeW5gUMa9EMiGjei@bDBmW7LA5iv65g!vD_y;fgLtj)g3SP5CE(QwT>-N zfJfi^5yJs|#19+_$u~^JUpN#KBe20;wj!E3m@tF1|2h~7Bu^kK3vhq904(DGJk}X( zz81j2b}rjSmmA<@)DMX!Q+rZCJ;VV(kpKcvW_Ezc6QBy@1pJTmo)M{-qUi5ZO~Beg zH=(*tJWej!hyP(w|#Y5h6@%S~O92uk}yzj%7aZ-^4vEAnTIpG$P zw}hZ!v%|NBj6d*Gx|ugq)xIKYvcKTbaCzz33z^uOsI*qZ@Tok6bX~BYLuV9ko$fpc z3r}b#%-Bq4oY!#Oi?6PC+>aBAve2@P1*aBdw&_PC=}|t!vnb+^J9ZRLekPmTtIc)K zn`}~ga5S1Th$k)j^ zn60@kk@3F5bN3^*LZ(L11Q|yLgmS{oC5cHZpO9-gKNoXupzw%Q=c??Y_02`wr{&r8 z)umx|;3%H1>v1(dOOxf1h`wc?CI_WT# zzd2+8S7b*Hu^?i-@=q7jd_yfcLjKXZSp%RnXiO&{J6 z$dPJX?<@Lz zn2AXEn89&jqP-V&vDNMU@1L%Z5L2ilvO1n48W9gc-Djti|0!+Qm3J|J@`twt&G^cO^(yDU!AH|xwX;l zM04E9mqg6%6+}1@Zn_f3u3Ve?uFd;MUX=BJQjPfG_XML-wIa^Eyq@Hia+mRJ$2$7I z?fEU{|C_)Lhrk!>Vf`9>t_(G6g;3nb+asnAnoO)mhXUGg#yx$JX^Xjt3BBEv6Q`^F z$g^qhoAt7$KVwoaGIV>5TNUN!-ZGw|6y&Er)r9;^aht5W1XkAV%k~bjgz51KwT~_h zns}$Kv3`DPTwJXR9@D!L!}KImo<~+cNzo@k zUMmu#pmh@B=Tt6@)Qoj*-7;eE$leOA7Mzxwx(xxEi=9RtBanP9@Bj%rBC2CU7&IaE*}>=Ph=8vKv!%jBAU{mc2&Z$h)s$V5NoPp>c}F73}ruhc3o zBQ|bu5*5&Zaq3=c9F+}6i9e;$~MMeX28rNP# z?QD(8BzM3>L*g*6#w@?x?P!nS#I!xmnmoL(d4I&PL0*3*HTYPUoBzJ_qIJssbsF`$+|yItzpI=dE=3a)w)xKoSi%Rm5ymWXmxmvHepPOm3gVHpiW9mlsQ% zIijxP`w(f1OA`Yk&@%3x%RaB_UNDiyk1ZL^J1)3cBn#HeTRUr;k}ZqO3WK#HH^gowULC)LKckFG4jYadCAmatU+La#d<6eFk)kcBVl9`vO%M94 zeQepg*Oh$Y@Tg&KX@1bZIWEkn0IQ1UCBw_c5u1U7r!?DQ89vIn_DM|mzJvz=TWs_z zL!bNR5~_g^7>4&)Tc2^?+O&I&^>&B*XfG3W_nal5b(A8JS;f;TXAdnzJX$l5UY6{Q ze%7iF6}99%<=rT08t;&d(=-CDdb4KO*%}c&{uKzxKz-5^jKI0R$;=fl2_RT?KQU?- zHr0d@KAnC)^67N#t1@@ZQTY6oKLRs>|CU4e$8i}-WR20ZSltM=PkWP(zU1EPKI<|N z-c?uzljTu zWciDGIbSap;d*#7_qCtTl4;^RdpK6U!io?GeQ!eWM)#-smk_q~Z_kuj_454kSQ1{< z$a4G9fH*EP$yI7=cCZ~Fgy^Rwir9Vi3)DeI^bw-PUu(i>j%;cK45a~l2D?Sn#-@R| zDlcAf#8Q_T+RkvKo;lBJ)`Cg&M{{T{ZHdLbAC>*d=JB4H#f^6;@*e369vF##2rz1q^dM0ZWE1cMip(VGpj>OWw zOx*V-fpjp=CMC$}B%nFG4ZXuO)#|@dKNa{^$E~fOw|W#}FBf&8#7^jBCaY@r?hBj= zu{Jr5(@~_4c*n)&;}jJNBZMg}c1J#&E--bca`zD?s)pb}2>W#q>Qi{QxQO&2^D&V4 z1k0}iO)i>{+;H`|xK<`zl5?)Bp@yYuuv~++DirL+d|E2q3qAN4>2?~w z-7oZ?J@&gx_Rv)*Vk69ZpM@2bY6F7MO)u~6=s0^Z-~|Tg8#81>nN>D+(nI)moI$f` zplmOGeyu0|mV1z+rlNKDNq}_WQU#JR*wf%9BkgM6==EkIKNrlO7pihfByz z6^Oq0!7Kq0rbYimPv;Z*;_ypPnJ;r(5D)}9G#^HvI18|bKF;n{VxE{QW~=jhTAq^e?SX) zv0o(6orN%vD>?Fh#&q>j^-!sks6)hQdoUkXq3@$K4VC!M4sCI$ET?G}dh1Et`UaKG z@?kg@a~W>v#-vSZR*9kzJaWf7W!mymVyc=3B0=DKaT$=q%D&2Dr2~1a2Um6k1>5z@ z0|SX)vmp_=?*;?F&6Qm3)s0L61?0;Gu$d{#Ef799s|AgP`PZ)RL^oGpb8r%horMSZ z8w@rFE8~GTL7eRD+W)T0{3&P|&=A2@eX{a+Y)o$Fe7ieSltj zT0@R2XtZt@I3TSyuT)VfLKg6Ivb1Kr*SXB+_={?YyW|-EC zw&TkcnEn#DJo{0%0+!AGA?NF1EcuIOX=HZU{Px?8iZE)M<*(Aeh!dOQ%&9>}Lb+A< zXA6p0H83|?isGt=({ULAJk~GdTl%rh61Zd@!R^8f_dE%kLGlVHE$64}FuUVkv-8fs zd~_`3$()oEC)ji(p;B(zQ7^5LzVbsj4znc>B^vQs9{t z^2DnU$6n_;LEdyqndu9m&8wg#5Hb-cOT_&ixCAVG%MeY00^WiG#=a>QG-*OWg9181 z0rA&TKLH^G0YSom-1ns-ELhnau!YOG-W<^N2B&?1z9JVZ7ob}AcOu}w+sIFER=iU9 zX1?|!7*nqJUEf>91-JxQ-gC)(vK}z?*l~zzU(ktuqJWn&eZio4TJ2!$CATXfXw`{|L%ZnsXQQ;{crIQfxr8n zOCYX7Nfv|b=a!H5C+2EJWn|q?UIOJ?cFQ@^oYvjHSnk@yhjOV=q_@urM!I>pt5ky6} zQ99;$Q@Do_{-d*>D%{%7xUmY6=R~aN?GE@h{i$b;^2Jaxwbitc#!-|dJ6~jeWcKge zU{&P6OlE3bxY#ETQ{vA2Xs+(Iil&tOR2f-LN(tbFXwH#AMkfkMku5xM!iZnmI8K{> zrdJ?Wn*sI08KP&J9D40^1K-6MBB7s*v?-xLt2)rSDaFI{`A2CAxs}@dl|XdA@BSCw7^6BX8e9<=eFr+i+mkU1jpRCvE<%r{Oz=^h zXRR8HB^utl&{u5wGzs6TZn@i;P1bK9-%9gn?&iyJI+|A)5qR;BQw$Sy$%nM5ll75c z;o`Z7d964%pJx~m#js9CBfoVK@Is)NhP*G)!8^zvnR3*(KxxEQp>=D~Zh}jr2IV>C zGX6vmI)>MtpbpQUVA0d9tC zfSBu>pnu0T{uBaE58N~XeLch@Cjj{5=lSk&FFDq_$GvIDo|OIcOtc1iUG6sgjj(A= zW^*3eMp*ZVbnZ3ST5Dg&yp;~a{IXsDrEnUw49d6LK?f!Iaovx5MQ(Cnr}oqH}Jh5hB>s zV>tnPG& zbZF2*zvgJObb95gRX|F=yXhbKt`^V7mQmqfieOEVF?imA~&q($|Rv55H4j-)@67_s{NMVFUNq z4_(<;KVV;#-|P!wQSw*&3W&I7V8W^_k{~d9KTymR6lT0avPu9%RHWui01={zrJ0kZ znU#yPvj7orzJ& z6;O)=now?naKYDr{%z0YDvg~5sAIAMMa@g-8q4)f(EqHv{gcfn#T89Nmub~OHdYar zq!vzX~?oW#FB8}bFjpByD0X|cF3fl3lqXoYJ#vQ zYuhB%=R*w5tl{b83T_eA$S`x`Dhk59-J7jtZk0n*q?g(Q{?*)CTmD*R!7SDWYH_j@ z%M__W!JbY2`#T1t@P+sB?jbFz6(+ggfXYbTqko}!6^Gy(B9l8leM(;I87XTmB{lh^LpjPV)3`(oY^$PPyl%y!2= z395o!PixRQY-mWr(;@0p3I!zyIk{G$=iraNPsJ|Z=J*hTTR^ia8YpoON%j28hVjc4 zq+QeY0NEO;#=FGIt{kt68i+{>u!A5LHV6{w4y%iuy~N`@;|fi2YKoM0>(^-lgdc|9 znPzWoVM8-;7o}i#MInE;hCh`=71eGG??#S3YG`S+WPvl?q(ItN!4uBCgvQL*f8Lea zp6z{NkOjxuiLU(ujlyeA5si}Z)e+IV3T9kwd3+?2NtN zyyTyZ3my8*cmdXv^18C?`+!{=T-h}Yfb6UP)v&L(21|*5@0~})LJ%M-^vCYY?%+!^1>omkxm9*R*BMy;0o`Q4Cb+vD*!-zA z_}_i)KN(#v%qy~@$NU;=R8FbY9&czD7uFK}%ga9KMAOrzn$BnIZI>ay+Ro50y*AD< zKCcR!#@yuIyq(@6Ob@B-6?T7&FsA!ueOR?M!m9HchET!CK%a3G<8lmAzT)UJ#deyF zqaw=Chp9<~&n@Z%k;hL?m9d!HZjC!Q?8UTT_QCb1E=={YdES5fX{&zUQcOe=YqX^; z?}fhMc}+g-S=B7O7StQ9n~zP7o|?RmMfTCFfb%?fu(A0D`h|Y5fWZaMwpGI^52uss z(0ygOgWgz%dj92Jauq=mipRHg;ZtZEyY6hQ+J)S)Np>+|YqY${vgaP<)_j%`tw$G9 zAQ$_Nnt|aJI2Q%uR}*X)y#Wi{q`g zGmKoc7O1LE%3M4!T01f#>Fg!v6J&WbV0YR*FoZ2Rx3|tyA!D++Y0gg2 z@0v5o5fhXX$ajsjB!-psUa&;4LC@3%c?pmP>u*=6(-eGqUoYgy)!8qBnoMWeLY8QZ zGb1r|G)#XHDAQXaFef_`3(SiM4}&4LK#2S|2fuu!(@G^z#A6W8Ah8qmutnB=d@fng zNiLzQ|J81lxa!zad?X}DC+A^Q`3GA6b4tgslBR~3V&x>6LZzrBEEfDVdAZD);!5lB z1|C(%K2J}-*jXPU|EYjiT2yTq=PU7xC;m%jU)Z@&Y5g7KO1VRrGW;}3Gw@z)686*F zHmD(-T+M+YI~|*z?7#9F0cD_olHZ)bZKSgynAEn}A~^72*u zyF<+L_D^I)zXUhhUUO6bVE1qQqg+fZci5Q#npl|FU##siAsqh(R5k%kN;iCJvKEI7 zOZwaZzt77_{!RJJaMBl5ZF~mg8z&VF51ys_+43q^(#@>C2?nTi(E6z$;}q{58elKR zyR=|sfbJ-Ms50y%+#?ft%=Rf(hQ)vG$)oSs-}lRBBP zzP}_IwTK~hr@6E-NW@t=qVQD#?a+}aA)?$!Lt$|y-SCB<-?Yz0`8J5MHF%nRRL4C? zed`HlJJlk_v4s@TqoT+!n-`ut52One{r3uVr4yJ8U{m;%h2IZWnG8XSzI+n&F2<1e zK)b5S>%}xuEVt`!0Fn9ViG~AbW%C(LsUzhB9jtR=KkX_$V0~Q&Le+*PGG$9 zPw289)u}X3+*nMH!o`N;pysa2bb|sCes)yfn@zB=RXl8g9w;*t09$wEfB<)K&FTEL z`)a))Z{~8}-pPjL2X)n72mI@@ChTBm1jHFY*E)DXa2ac`0pQzfNV@--x9tXC72)YZ zBwzCbi8)yM02l}|Xk!Q%jiHT79y!76+wbj|xt+Q~lMfysNdTFqo{__pv_37f3)#~R zq*}`H(c>)^Mpk3Y3Ad1f&)mIcZ_b?;gLyv5N*QC#z8nwBGT`q~C=-myR>W9}zgyC7 z(7&H&ov6On@~?`wQ=~VHI-U@q99p%z&N}69j@}c*=>vHf@fG$U>CSb2+pLk z0Lr(QD^e`7zuqBfWnoDw43I^m^WFSuX6qVQ zc3%1N=G8JIBWwQra)4m(Af;4|BVGG=0=q>HB4L?AP*Eg+2`of6VWm*o8i=$g#fYwmUSUi;j8?okJh@9#1A z-uT{lp7xrG$ialHd|@r#;hEU6N7F9cSu%a{Q~@V4*(#Xa+XvFNj?q5G)rC3wZCOF5 z3PwszryX0<+%ZeA%ka_2?X<#b=e^otI6jVR9L@4h2>eaF+=@@!SqNWNc2bHbtEZ0^2{#wgQ@E|Cg@PeMNdEN+&C^B_A6mQIG_ zu(r3_w4TWV*K?3M%reG%IzP-k51!CWC=72JvzpMFr~5sKdEAAFCLf#4bl(KEW>Aql z*CkLyBE{?zuD3%{;;xnbY1#hVDi-qRMd@#WsB(ceOX$;PNyw1|Y65tu9b=P+ZNCdd z{pA6F5r`rpfQ_FSPf2?eY6c6hK{gHWR@0joG~=_n388DWh97uNVwk?-ID2~`UiEfT zjzzXMdQFt!Rprxx=_M5p$FXIySjZ{0=Sh?%$Khsub17W?dFS}QPv|CThKLXyWB9N)%K+F;HjqFCv{flNMSz^@A!Xy2uN)+X$R z7_Pp5(YMbe$&kVAv8v$a7M%Cg-(057GA9bEswpqiaqRsyWcGI}706BB{f2n_H!jt2 z@#U|hulqo%x(nz%Co2y(sh}z26p9er1KV2F^Q{&%k6=T7C>kP^7{m6e%a-x@!?ibt z=dSnOpW~?AvBX_lkpGr_7RCr+OArJ z;5;iL14TjZ`Bn+OFGR$FJ%~~J3XRp;_I>Tv(T|r3U1XSdxCk|*zwQr5kRL2I1cCgT zxzpx3;@iJu&$_+--v2{NVDz5a$+&B|+SpvYiKg^9grpF?bjF8fSl$;}LXS2!Y*1=; zQub9wB+oN$3eZW{ zPS?y*2dUn%kN@j3^+(czyPo~A?PaSbczKqv+ zH6^npfX0PZvq#3tpXdADZ}m-#f9+?Mx|jMg(;4eu$j7URG1QlNkDqK5M1THL&0r9f z>(pnohWB94gCmt%0w^5X@c&*$UBoc8p@~Vk5X8j4v$OJ;vP5^T(L)XNkUk-IByj5e zcTPi3Ia)HY&$FB#AIEPnv~x%}BYoEl7RNitjoa3*SCQ16dWmtd?2=j*RS(XiJ}hyfe1V!xW&y-D z^={*v+Q7O++9GBq*TnYyshfT+NZ9TFCa zim9=y6PQZ@=()9ZwF4*h!BG!zO$&hSaTD`k12Z>)fHo@jnDnb>#LaijT3Z4D;C_vw%&& zj(h&akh8&-M*XeEc1w%;CF|#`$yXmK#$V;SEW3?nndA)DUwAY{^|Z_buoS^T(ih=CaE*zCnhhx8qVRw zD&wR-Q|^|{BkTTD{=K*DjlmGwZlS~J*Is#_t+BJh$wpt*{p@v*v&k_xN?PYz)d?n% z{>?8-ca~1HmdtM82zBv%QE!(}2Wf{+zSj?Ldy*c-drw1P$Pe0I`AC+xS2fV3~gWl(XOA z+=B5b?I0Ud%@};o7P}4%4k2QJ2~6|~BxymS{QMQZ@7mSW;O@48aM+QR0J@ciZOJL2&ZtrD~dsZ`Lpp+8kO zXo?0J6PQB5mbQz2O@qy{(|*Dze!A7!oGFY#@jm9qeF*bL$kP6K#|!PxChhZa34`y1 z79qoTXyEotA;ZNOVNG3?TSCxD$@Fck(QHZ(h)VY}@!8v5vz&?cUe4?k|EP3(AJaVZ z2A!m-w~J3Z$l$(uY`z+J$#4qvZfxH6Z>$3G_0PBS6JD;=S%m17%bzNP{r!OO5a-Pb z9+_EOM3PkeCM#`kXKDS5*W22VRLauR*3^Ym#jrii#?Yg^+_=5mxxE}{%eX?5!+q03KgbH`AY|-;9KrI^HtfF+r-zw=r{IZNdd$>;Q;4 zKu~~%6Bq&rtU#SH4-hl|-~Whzw^rFs4>BC&wK79zonYbi&COlD%vd;&cdvDfTf>Tz z2vn%v*LPC4!!pQ*j9z@w(Xa8q-B{_GnSZ)Yuppmf)no8zkg}R=W0NBGimv%QEE?G) z>7LBPKIH8^{^S75EVjJ@gox#} z%QtxO4skqeBhKfgR4|E&{d zp3>R8s5_1y%3>;LLc0G^eBA-yPJ~FEeD|MXG5XCSuMT`txWF}!JCk__*9w!{Yc)3| z`MXHTUmkEr>)aS+pcN!JAxXFCfR@7Tlg)|miqP8@&Y3qT#KkxroD-uwJNqQ$dX)k1 zb?fB_dSXz%N>Y+kQcgvOt_M2Iz8+uyQ27;CTVQU!>wNgqhVB$cBHe77OGN%}_6fLw)tHE2LfVM>eG$}>y6EP&cS#O>$^9in!-5@Ai@ITTz8r4B$* zgb3;j7fN@AX+004JWe9gsdrLuGa(t>{eX{5_stx{Hm4Jm)-dF2SgrPoKl zg4Z^531oToxCi-|`Yu(^6ZYRwe`VhZSBVbQC5U||=uLh)9{M3CA})_#ncXN2f<#qK z#Qc-IL}Wd-I6q<>?kn_+_{7m+P;lSed#9R)@JIM`7MC-QaNCqTR%hR{i@2G8kf5W& zIufAEUAg*PlW6dW^o%dyWT>lY5e~g8#h7^9mi=%is<~w=0PD%iF(-!Ck0Y(H;G@&s<4;aJr(u01$p5GmPRjO+nLQ_Lg;ELZv zx>|-d9)_A@PHub{DEtsswqA2|XuPHl-FPBQ=6%5|uJMswlR?Jm_qDMo1%gi<>2$-n zWO+y0k4`$JGs%)<-YApCIVG9(o_q-r^(JqM`_TxQCpo*!C-lShVe&%>laQArhmq%S z?t>fBnM5y@v2ze#-$aTOft;%FZC;fh(EC(><(Gi{fB$9{z%jg4_?)V3Dax`pk)VG` z@BcoDH#qKR@lxOX!&N*14wGXF=S-5JC_HHgSjPXdzp=?%dL?B%)&nmhGbiV zo2i|RWqX?CpKJvwI58^>AVRd4TayC)CtNr70tiU4a(2RdwO7W`;Y$|=;Ef0&=UhHecXeiA}5lSGdLd;D(qaK00J zM9KH_`)S)!$vC`ZcgKlb$5cw><5jWYxxb*rm3tUg|?Gc7ca#d;B z&ll$T44$Pod4z>@r7`|MlxQ##W-{)ihs7(QA7j%@VQ{FAwA?!B+<(Ldg zp2Ad|a%o$F4}wxnRdw=kp@h!t2)KfFoKiy&)l$`Ii_91XdDUOD!%-E(mqm7=A!zla zCJ-&Fp4N%`TE*LkTFA@5Qgekup;mtyb4nbrcAqk0$x?q%qW{u;O7}SQf?)D(mH#el z?NaDq%7ImST{5;72dBd4gI9XGc*QtxCT1%}aqJ)-SIT}ii~Tm=Uv+QFSmVWVWx;d{ z6H%1dG=VOD)^-!jlf+R+eKk`PqtVP{7_E>lBllJB0C6jRyymS`SLBj+_S(bD37m(! zNB0Xcbh~nv=ryfG5ZW4JsLfbWbm7%pt|Jl#5p#m9hIpR+j5|93y2RvGpBMo8MCw+b zKtY237-wEr#B!&(N#FYWecWB3&|c6qdZ zVn8Cn_}@@@2>#jvx_682#LLVKZqi^fbFj8#GPieQHZyiGHe@z71g9OHrEf@PMLcdc zGC6P=15hP*uHYYPV`At4Tmt;xZ?_-hHS!7hg-RDoXmfgn- z=2geV4}%4^-V@Jxhxs&g zsLv3oos~91dg1cAE{(N0lE0KTE3inl0t11G-<(cZIBz!$JdXqWWOEVB)z(8<7feI=#6afr&!A)M2znwUUVz6k;n*(;B-?A|ZW!gqcgc!9z1SmsE;g{l} z;L#+&!PK&PyECd)L9EP>=-A&$_mz;|(93aX?x1BEg;%D4F?S+_ewGP+7m&r}TX|dn z@(JCy@`!3o1px^Gh5eEZ2kM*6;az10UR>OTcM}u8L&~EndOHV20Y?C!9lz;v07$rR zry=1V_Nv)g0^gJ~*dq}Bg+vaG_28czMJg>VeX}kAa}DqS!J}JmftBYj*TDbQhxVGDN6pu33`o4|t*_4at$Q9VraXT2?Z>lW znl!>u^QX@leUT(9JJ-6Uyi1w;5GRFq(yo#gDoTE+R4uPdq!}!IeL3uV9_Le8<#Z}r z4DZoz874$?MBiF0x|OBUWmtXk#e?1)-%ZN)2^HiJbw`bcB?ZnC!|>u=LdMBbojvL( z%luJfp(8dw(a4l{ZuH{sOPhTKo(sBl^wZCgcHnCE{vbR;>qWs(HmUvMX5=2Yrra3qD0g$C>Z=P+s6_qdk0TZw8(uB@F}F)C{=M}6CQg5O{$Kd~ft{rrzVe8Vc*-rB zyllgm)+-TK@ikrsC*d8qi6~;Bbw=5<6?aG*JhYM4yg#zoRMT82-4NSV*hFiCYcbyy zFF~4aVQvu0L#i}k0f{k?dyD~hytP$C@SwuXPTkzV(?zevHlDMj3Psn(6#47%3x#VFe|0pw$Gv)jI6ZE#QwS}+r_fu1Ac6sI9VX20a0)B z{wz)nJ`|y~FZw=R87bp+FL##E0$!7cq2DzebcozzFW5AUke6ZGH0{%i4fkImwY6b& zGC~{k4X=I6r2iNIAB(HHyYql1imDa`m6lM_U9yoVk7_UWy%}JC{Qy~ay_I)IK;E@( zwqb1HvL=p7Q;7Qo;v2%J0R7{wVf$bBc;`zeE-h`GKsHp_RS6A*r;dks**T z^t7=w_B6G#1aG>5ZTxA&ppj8kw1p+4mG5FsfV<*vi^Vu@Jpa4H-{lnld+zvm0$L== z9I3^^lf8kmn;r465h|;(AJMr0VWm$$z{)j0ez_iY=b%M5qxDOehvx3grdq_dCV>~t zwTxmVM1~a>1zXe_vkIpjz73kt7?;L4EDCcJWsk^Q`Udv`57{LmLBHvVN|U6JoXQos=|``63N=q+@9(q`P_TR~&yG9i*ouP4ZF}Kv1@u1w zL~*y5S|#S)v+Dr2UAB?U7;{NOHbM(N`aevb8wZ$2Q7!eG$aNOsB58M3AAcC5P=2m- z7-5A;8&4M>XIYSCFiw%gJ9IK34AS6tS6Cv^n*|W9iXS?@9}9~s6CV|5yF1&=A22*% zjjZyMl!Rt`rS%rZ{}Ev@mTL)qg~l<8%b?g-GT&MQY~T42-w%hYIquIq$LqE4yO8m@d$l_}URg9uaenYA z@hmT;!>x;VFnVcpeJsWfonSwHL>+dda(lRwCxJBLb<}pSUAi5tD4N7viiRFc+jt5h zCH99#D>dOOb9hFr|MrnU=%*f3u7#GRXsW3>!wx|H!2Fp)x9jakfd5N*D}R5&{sH+n z{k!9Lx}Ybw@jKQ3w)mZ_A&@Sz1&8lAZp<_X;OBAyMP^(#qRj$8>Vfg}ZifHg|A2p| zN%A>;+M-3}+U_U7cXeudDd0wA4@g5ka7Hb1#mYH*%Ro9e5rv94Wch{Wyudw;Mwx1{ zS9f9}P!aE0cvXNP%&YgKyVAKPH6%>>q$!H73Z)BG!q|riF`=Ey%O;YBk{*{WN_(w| zt1|;u=cQGUpcx6Go$#$UJ2Tg%=tP^T6J-Tf!T2b6-2%;f$%6=CBA4kR?^DB+)aX7F zIy3~S7Pn$ONH}D2GkBpZm{i<@+?=caB+|Wh^sR?*L=Xrdf_?K1a-7>Z{hgpGHkq-mdksLfEyX*m58R0)C(KT3|N=ji3noGRFYz zR+ET=gzxyhlU$XL?_ExQPQ%14sSab_q~Z-Fx;6A@kdW6f_n@KSU?Ki&`TxR{I~l~) zbk9uC=}`phS5z{(orjL&U3uAx*B%Gkq>*3HqmyqH)Par*HOF|+SrX|W8pF(l&t2xC zTk(<7stkKmd7F;%V&9Rg+2KiFf1%ssrq z+zfUbL%4EsT!gY2e+cdi$yz0Zh>d6cp-z{i`mB3&aWhWd+=Da4!_w-681T{{(+0i4DG68p)LNS1BJvJn}=s&-~_(;OIm* zULmq`z9c%!t>Srl9q)R={H?$mCP=I&XVK!-rJAAGmq~1@G{WERNTK$7TH-zztBU#tn_7|q6R+v9Ln;$s9YNl_^#E->$npCg z>bF{atUh&4-Jv8BC2Jl#1Gi9iq=U+#veX{KMHAvy3AkG0SrRtW%2x<#%KTN0*KnJ~ zhHCf>`IZSX1wtKc*rqNJKceSKp`|*6RA)Obc z?j(Iw*ZIVuE@B1J|5$ju$S+vgjSO@Q|Coy zp~3@e7vH8yLUX>;C=x<}C?!0uV4gd~3po$9v})W>vdpGQEKD^DI#z0B=%&D#psgvS z!m5&32!Xn$j%W{!Ay&V-Z@#bg&F`IcN}>CLk|PQ!kanJKbn}37PoynQ(wiz*5M$tY zl^xf48Mv$Y$zv?RJMZOHhyWaJ%!1b{@fMq#j|h`Y@Q>&)iy&zK?Bt}TC9V$DLUlfT zM&T^vQ<3S!^m!-ydff$F1r%SVI zy6N5c4G|4XjUONL(rYZIM}<# zrulBM_Oo|?Kyu^1+E2vKdcd2H92N8EiC19YH9GR6ZTqsqimlKM@Zo93MgD`l)<-q$~M3=cP{4IgIkcswB|wv^ig|M zM?VeXpkBO)bsBjEp{erOr(70gSuteut@YPyx||8g$@Dn<>3#7^@VvDEYKU}i>xh63 zXlUV|cI0;jMBt`_$9L?=-{UNkf=Iw-1{xXf7Yy^S#UYZnY3eRmz_$CcW$7iD+6H!KT zqHFGPchbCSt#K+bsn%i|CX+cq%*GpM-MvcZ|8ESmB)`>X&zO+bYyf8 zSpC!dj1-oHdIK-L|sgUY0)!{jPE~E zn=mA)pI{{v>f(l%aS>^xieHDuaW>cYz-QQ84hs{$T9`axgM+UBKoAyZNsV}KpZh%)4BM*ffspNp?M zBE&h?J9VU=P8!p5-(2Rdgi%iPMX=i}QZP?q5|GuYMcX4qd)!AZ779gjSoHjYI$r!GV zJtCi3=ZjmQJsjMdBI>oQ?U6RJ?HV*Tnl(VvEQri#xR-5~`I*qIBFLm%jz_r#^kFwb z7OJee<~JMpC!_b9(Uh$1zh1WAKCRedevJBqs_fMx>$X1`%{$KOucCbjQVL-Xn5d6J zMg}{J9CG7=MT_iFwHfwqXSldoQd|t{Q6Kjoog$`9_%GK#nWAFI%2jiuWIgUe+HbHr zeO*)m_fbD>y00s|pvlU9K^nb}W!$g6zH1^A)kI?>^XOwf3(gl(tE~%iNZQXKwSFY| zeHht~_HipEQ!l>wk+t^@N;(K<^aS3AXRzJZbx#S$#v0)yirHO;<(kP^iAv^<)UhU% z2oV+07l4FQQPnklb`tKKk)*2qfKC*f=3_8gRj3yMUu+GrL2gybDxIZ8OvUCffI14L|#oxEafM3YorseoEpO5waXI7KwVH!eFq5Ye!$dX%Q%u$+p%F6J3G9jv=ryD0=?^^y?_(YbAb-Lt(px-t?x;ZsUI2 zzHg_T1s18_8+GFy#89eHIc64+b?eiWVtajXH!+ys#fW#wIZifoCn{@5Fe`p;x;;9-05Pm#VXKM!e0ohZIOT|wT4=>YM+)CXuHf&`GFF?gT(B~9EhedRZz!rXw6GHBVw73Y&Mpl3Sq2i?sVrP7OM<@t~A01v5$H~c@jqT98W&nal#dLsj zPupablX;&B>SO#@r!^>&^b`K7a|;9LGq(H{Ok3E6{5;*qkFF+HAxw*^@5_4y`m#%I zEa2Ogzaa7`T>V+?01kfsF;nbR6 zq4EY&1KLaE1LodAx&1_!>&Va%oTZ4*QLRceN+1V0>-R6~oLlv)@=D|~&!l_dByc$! zm%22#eYn3hQ?VI*n&C<@uGdQ-A*cx0Ey;1m@Dr2FpzGMJ82kaepl;>smR@XU8WqyVq4x#TEW0lo#E?fxGUBgU_gF_l3T~@`@Md_AcpnNewJ& zbUkcX6fZZpkDnNE4@+`w&>BL~6d0hY-;I;6Bua8jyv$bc$K=I$R@sN-dO+gvju3j| zENN|piIb-P!6 zlsVkm*^l(#Sc_-8sfV6K7JpkQAaqUJ)P29!l8@v4SO(7Nt3>xmbd0Nd*}^s#rzvd* zPS-=XK3n_yfrpn$q4e(VZf#Z!Je#5TA`U7?y%dg5X=s)eb z2??_U&BXv_4!HOM@c9Aky5EMsC%OJV;uHT}WGW{F&XKG^1z+^}GsjFXC@yv_T}Y!~ zt^GCcojM9N!Uk0Brn#(~ok|7VR%+e-&V9 zPjiA;$B)*yOscBb0xg3N3kNfj-WQA8|3y0T*6aQo{5#o45yZjk_J4-mx#MXA0&|mL zB9kpjNa>@(kJVXnZ z*Z6p{d_dR_F`!dxiqp6J%dwJ@lAK4TOFaN8hYOEwNEHObhzL+9DXO0=K%ii?mSY-a z9h`YceX}}8h;Q)CXivg4LmWjfAAzddOMip^RAEz!fI`B_`whC=vpJJDp3&B$ikyd( zLjvO^1fWM_Tz;RY^o+>FMyPh$OLeFp9^Pv~!mi4J0Og4_bcrVjowa}rrOVi~H&iKF z=7ba*{2Etgq8etZU2JhGmp%wWO>y{c)zOK)LE+W6bk%?+Fl=Hr$*|&*7zn~?SHH#w zV#4URabaYjX7BLU&xD4AApN6$5xBFW2Xd=F@nI3MFoC)ZPg56rQWXa#QcqHQCVQq| z7z5A%uRKt+=W6?lFW_h9mYtLBrXLiD`+_4!H$%{W_4DtcL=Xp*`P37>Z&bb`28Vu7pvxAC(5t=(CWR=lK*}HphD>RfFb)W< zCNJN`GKhPgKR!BG%$49JnD?9%g%Ju-D+`0DUz|Jc6 zhtJz(Vlg)Fc?2?p?22p2+`o*t2RvUP753j=JjJLn9>U{ly6;9w1VbRV$zNb@&p6V5 zWy<2vL6`%D_`$%-R`X+$^p!CylJydAOHm@E}(21K$Ctn@npqq@=UC@Dv}9gRN#&@*OhJ9iYp|4 z9&Q-5>_*y(0sE|w!7k?rL-^GhV==vV`|izqpLd2Mo9YGEsD zDmp|Psk=tFNV(nmKyc!t+d%1w)&7}qP9__6_p+z)@LMCU(O}cJs4FUzE`)l-m?}>? z8CCQTrVx_I?#8JxJBY*F zQS6KJfXm2PU}RN)01tYaiGHMAJre(hHWmr8fqhj=6$LpH98zz-ORr=- zaqD=tbszH=kxS{>+_29oAEqF*X`2JSo_@e0RtyQadRP|72@;mUTbFp zh=7k1clw>(#$|EE$Eh7CNv!aey-Jp11)>Folu|V0)RU(u6Nen?ep5BJc#)|j{w51o z9pWE~t?LjyA1lZPZOiUGo5i@k&O?BJNCRG=0EA>v09@eDc=+%7zQKW+07w!R0nnqH zC^r_zEu$Hj*A^he{73ybm?IOQIJ5Kww%U-2JG&SHgqZ54cBY>8HimZgckHjaI19iA z1-=*@7Mv*1T?J4R|Dqm&$3hpgbanxd8SDYpTnB)A(*|gqWxrVoU@@uyyG(5jNgv-Z za{h@>7kB`m)7RL=3F!1SHe>;^@!<22uy|Em9e^rTpi0vY;N~>8Gz34mim8*ECGgNU zOrF306n8HI&LQ6*4xXSuB0%Ee8X7wRpHax!)!7(u4ora>e-VqgE!NK}+`NC;F!J71i(0^E_FqPI_ zrpacwpfHFtz+}Bf8L>>&6#V47oFJtCtCd82WooTt%mh=SH%+dIxX31A3n%*?@b4ES zHOggXBt?=PWO=9hhAg9D1qUq7e}u?G&jeaIpLuPkThHZ-V) zAkMtQgenp0V8g}LCnp96YX|~oGeqam>wc*38WRSk9=ElBYJ-E`35ydwGqHZx0Og}+ zPTUF2l8w1+Q0HjhQa8*DDCB=A5I)!KZ?4_K^DfwY%o&Czh>)8;>)DI?8k00Cdnn>M z_@VdQoDYg(kVKG)ZO-$1IX z*pDbP(>5`rn#Qwg@p)R!1Q~_mpX^T2zWbiYQ3>NjnVv+;XXqB|WSuIl%FIZ9WsDY+ zU&QM5=zc9sa&C?9m-=GSG~EN8Wt(1ing;*Xl1&98dI}oF{dD!$t1J54WcoWDVPg!> zkHgP7y`C^NL}hIE$#JOX6Vya~s$Bkw{}BM7R0cpz{RLVv6o?Cuc4ABz5Qr%N?GN&q zP6&I?AVd!eDjgFUU0GU!QIZj;+X9ft**F&b~f&3}Q+yL3}je*Hb6RlZ~x zkX=Ral__8VTy|g}>WBSThh+pnQfGl}@&8qpe&t|Lb%pNL-RTBtCz9K7fJx zuA}lRm|8;Ld$D3Z)7pAe)3w6L*rLM6#L$-#`MG&0Xz0Y|NOH@qP0q?_E$*qIy9Nj^ z3@gbWFQo27Bt5d-^z9SdAGmAWs;DYz(0PTgT?iqrkF9&t_>X?%?t@fgP-&hk7za5{ zGpWZ)cRKGpzW>=iRvmS*^6Z3hjm7Hi`-eQKB_=IcqcTg8j%6Oz~h9S?jNK{ zmDeM0p#+|{SMaXVC-J2kNI@3I<+;id_)D%{&$D4qePU)#ir+RjU6|fY{ODaiCM(Ks zPHT{{)a?8y_vC9G;q0j9^lASIH$8PJfOZ?>d+#`bz5C<+=SyY$fzP_877GNsh4cOPo)sXitd80f7PGEE&FHSHx_2VfRTAY-iD507#Ej%M)t{A0 z!hQ@O=+F#?qqq6|n5R?;^I71sH(OEzzSb3d^ra_J^5FBRL(K_vI#9a{ickf<*u04T zi#f?zxuR`U4!Q|8e%zuW5wnN`b!fBIv8XOnlatOCrXHIqrhtIWj1twv4F69tA3$;wf~^x>?jG5OK~lrb-K{gQA@#i5M9iSTu8sqSH~uad|Tedmy_Q{2=Z zSyW(y@uR~Sc=t40tyyP7k-VMDUZahKEnXrdu%27L_0upQA`KmJK6q&2MLfgcEgG9HxjT8lbqwOa`lg_`*TJFZV0oS&210@XX95>*JH_NG;AqN;d@h9Z? zf9*DZ=K)mE(mB%;Zzks-y**7&)E`w*JPl^Re`2*ZtDQgadTsF3eWsSFfMa%rFR*2f zIv0B#?W^v0uR8tAkjE-GRR=z{oGpv9ds`grX8DIOk2Px77-oz*m(wSJ|B5cmy97m7VDLh@ub3r$9tM$)?m=8Q9LGA8GeZ4LxQEzd?E}FBr=4_l z0S9#d97x6L@=H|PU^M|QFBt9u&kv`sT?FI#@)|cFFjV{xJFz+_niL)$6O)uL`LL5T zdOW4^>7Y93lX4*R+chL&E=arNm}e_r%5A^zPTXc7{xkr-we}d_=TL)OJ!xIAy%LJZ zQ~Jv3-T_M8JtPx>L=Xn~ndhfid&LU4V1r1Sqs>bi2~s~=G9=VkfZuBiS36l$dJ4I^Gh*A-GbE^4+a?oJ|oD=WdYK>0A z!7GC8zO~EDw2u*sB)YH0Q4@8AY6eU5t6a5tsp^lTL>((8kK&(jPbhCm)P(xLQO;0S zmq|0;#(?}cLH=uhuA21^x-|sPKwh9n>AdOOA)G%It(mEbr4zV2?Pr%7lcf!_u@msR z-EvEy<^klYBK`=T{$y9C8 zS@!B4v#}u!&wlaBLXxhhx+8K+A$c$;Y|J+vyGHTdfte=Sk20>|K|M`Dj#P8H5|>Zo z;S)LS%(;s}FpFk`3yJmPA3=eh3dhjMjx>D2{nAmXO9eOT^?|p3 zjh6P|&R5^g9r-`t($hJg&gR!tqr5|gaXkwVA2+pa`Ae5^!a z$o*S7I-hMyoVKck=dHqDNhpg-;^!MDj8qyAxY!=+kZ4NoB4eK55_Iw!oSuJ|pV6XZ z3vLosKh|74Ug#EO70jISm1>jL8Pk$vp=?gk&>4Z zAJ-YVsXNSQ1p%pw3yZr1qbSDMT_Nx^WHmQQkI&Q(vQClW`Rm@(KJ^HamGM3dPi74- zwj+`G1hW&=P9#BPAg`7O)Ly3C)?X$7?l9!fbvx=^{SVHn$=+FY|5F$PWS}VTW~mG< z4pcc~-?-NRiUATZ`W?Jc7w0K*@6+>=lk+!;NLb0j=bd*k$jjV%dI{CUY zsD~^_kU0ebnkp7oz~i8p9)4PAaB@!Z+4xkYVhUuuf!wEV)ln}5Q8eX;x>Wq{sTT?f zb`?lg*+*jBgtZ-i>LGB3@^=D!Tnj^ks*XEZXFPeCp=v6e4ll)gM*;lh?my~_Kc(Km zc$I)dNdh7Q(`OrmNI{wc+>XeQzZ?CofDxP>^7n@zA%+otnPP6sZ-M)xP!4xQ%*Ay8 zm5>jqC$IBa7Pp*4M4}uLM69j#2{)bEix;p1sJ-*l3IUduG0gJw;`TFP>eqQ3UIh;n zx@UEG)pJcjGy@}zpYgKpuCRzImT|q7_&|mT|MKX*YWI2Q^g+o!Z&>sr&y_-00_)F3jB9!blwu!@ zl6=PA<@wC3x{}^2QmjcaCa?j`Og*??K29=sIX>ST8^~3%^+5FTtQW(VMy71$Z~3*w zyd#NO)l}=r)({3U2G%Md@E&IMm4K6?OP33!vdO2J1-Q)at zF%tpmQ~o3rf0UZviWVP}tCHfsSy{4MK|4FE!~7157s>O7>2(wPH87`*wMUgQ-ej5G zFvlMad-kZ~g^cfd)AU2UuVwnq?)0o!JpSe)K@|Jq<{Vq0&8LxNhREz$C8TmepQcYa z7ThMk=7`jHiou8Ya=K7zPuZXV5I2qc(zDeMx+_s6>G>0x>vig@Mo1SD^;INrrY(|p z4?v>=EQ>FL-Y$htO~natU}fv?{%}xqkQBzyxc|5%vIMsM4Hh0VAyt~|e)+4!4126{ zVaKab`Yr`@Qnm2|Z1LrJvBQn$Z&+WWUa3f&F{ECQ2f08+AW>?9T@)j#!S5l*O7naa@<2Kvt^WaEdMq(tE~;66uBcHJHkk z)`eGu!I&oPjhF0>&;94bAsg>z>jvUX2tH!li4}RTM6SuBIX)2L&VhLM{OR$J*bu$q zjTSw(%}MNcx^|x4$l0=LzOeV{eBUNfk6P7pQ^H#%be2!OONhSom|oUyC#t&@_rJ^V z{sblM+=}see0mg@ZEi%LwJVQdFlhhMK+~{@x?Y(>2mUkYJWnPr{DF}OMFbw&;Rllx zydp`uuc--oUu+BAA`&42N@lfjp}eWc}@QXuv(w|5kjir2yFh%Mh?82l`u~vVYn)O#a=~ zDSC3rEbg%R@a=B%y9(&0*y;Zt;slnh|0_=auNJ3YzG8yG$nw6bK^Z@Rzlr3@lXsK$ zZFESvU-JE>kK1g6v1!G{AP*gN-Y{XK5j-5qw{F!p=f~Z1A}wvg?Lh_UclTz$W@s~4 zC2=ATr*N~0C00_lNo}8(gc|Q_-u3gsx1*XdG91gfY9;oath{`wBaW{9$(j zVNA;CoJkX?6<4^e7ncQOiS1U7Fd(XBL*W)Fw!3sNi*rz6GxqNa64+4`yknMBH2_V{ zbYp9fX@0}M`nh}oa&?wB%<`e^BCDc#$9vSgn%P?>TX`n-#DaKJ=DXv8Dz8TW+2pTn4 zL8cE7z}Kk-Q4@^mePXPDQ9|AMifk;o*^UXX^f1v;Z`9IjLATqTm~>11)v}=hKZ*uGUxr!)EWLHI3pr8JSeY8SF9V801_8#Y^KvI}C4uaz($bKo-+DM8K6*~K{w*eU z12%?^=IKiDIR82#lHTF`SV$_PQ|}8C^_9btr`hQ|Y?_Z|@*-cpw_>~ubzXm?=nV4} zBUC_S49ex4q20d0W^CTiekdfHRRelV{_rtkBDtH7j8MR7_qWHrDvX`w)r-R)U1{v< zP#r7SFPe!SfBb)_`wFnE*5zNiJ5{Vx>Me82UrnRn(lGr!^g!SNMoP$MP#UXc9aLP@Q|Q)`{{ zx;F@wm0A~hP&QXhsIMnWr>!#|C`1c=Cy`LI%8Ka<8EUM)BCH+AO+#9`94cvn{05MU zMb9c=zsLii@C)gwClC1ww2t&R+dl|+$(uf;VBu-AUMA;x|7z3;He)5eRCZ8O9bU_ zkfN8oD{oXpfF7mH@{#<}8FGmGAF7pC70OVU$zJbnBoF$ZH_$GB3xG#Mmrs0cV=57a zri2^+gNK(y*AETF4y`3xp@Nl>Lim8%0{F0}u1Ab-(4%1!OUygXGg|^O5FXOZ&b+`6 zTBz;U-r_2zvksV(usEl=ub7YJ9`31sKC?F1k||vY*F;0J7jlfpe{Z#Q?l2rHI&%po z;u0R`fo2)EAHgoy{RM-iO3Q`|4f_E8Bwvk_29 z5Mcg@7KUoc!5QrZ(!y|Nt=*-WS4csUz1jTmxqJl<)^X8W)|5OaeV{S;B41BxPtSn) zpuVt`3RL2@5Gf^G|D*(_$D0mp(~d)ZHluHvA04G!CeP~OL=v2&ar1eLhN!HsyeVxX zFQ?&3b)jv{H83djT`M*d-;8usAA}9)IV*1fc^JTEGK5ol%Y?<8a}j4|3c`t{>$}_ zEO()zpY@J_Tg`f>-tlJmAF6l!<9`37Wv6>|jyvHeT+T$v4h{~@mbY0TKjj9IEI&nU zUUTwS-rOJr<4V0Ig6|KnsQR3czR{%@6XZwhkfsiIC1dy<H!;DhBllQynF^-|jgb8KOe7@EnFu%xEI`8qywuw}6nMmwZV~r8G$K*6o z9wa>wU#SXb`2h|);@Q;#_5G(El+C_&ZZE|YO)2Aan`$w4>4d?#!UGf>lbyRPiWu_V z2SKsl0^Ucq$h2!g%ER-2#tDr>%G+=_LsnYHhQD`;w)<#I71xt*;kfR;h>50mkdy?&08RSLYIq`FUlHv&bap!(!3G13EtN$jEjJ4 z73oPb|2Elr?jZ`^Y}hxp$h3!q5V-gervBr$nfDNeFij`>ER=`dN<@9G-~aH$f%t12 zH%$BcIj*@nm2YN*IbLt0mI-Xj_i|3oj`0kQ%`&Bxau#v#nZP~vp0uo&t7ZKH-qddU znuN|WO(es|s0pbYjkq_z5%B>|$e;vs`Lc^M14mi#U~zB{96NSlVlk~;(QaBQB%1Yv zUB&gg$`7yzyy3fPn^ajYRD&}8N{+A`2PD)(vR20uxea@0=}$enMEV9j7qijdSho+Y z>a0PgbG=j4RZcq3>)=U~vYlC)!+;Z;!9WAS( zOLo{?#iPtkA5&!s(YG^9x&ybDknuIo(c2yGyz#K%43|K#w4lRY8>8B8yG3ECybRik z(T=h5?NWJeD+*>|-PPlo=NK3yg-?WQIw}t6pH4|)1n-k6(SiE)f+{6SiMDv2RmIJT zEeRv!bbce6x=?7Ck{rcB?qBV%f9~QXOrqo8(-6*`P$ih)D{Q0pa&i6SjNI;{XDz=( zdtE@~OG5N0Ec42pZDRKdsK=rBkDM>dR6{7~6$Be<3gyF#q7%>P-aXf1cr{?$&{*^g zODV7((M#Xe_OjSquYm~74dtSLgVM*oD^YOIrBsw0sb{kRCBTo~$3i$1p<^@OVm=vb zAaqj42POIoH3ElJ_bC@9`xTWx!=8Kl%thp7{(v|=$=hI+3Kz7GDbC%I^hCMMliye> zI!elp$K2&MC*T*Qj>#jd@-oebBWr5(4syvyDK_IY-OXmv+l8K#Sv*zzn47#{eHj7i zMni!+7nA-RQBHGBMhc{PZxzXEHR{Xw>(zM=Ycju1Q*ODsBn@Nz!N)Ikx=v|es@-rM zlLy<%N$05b2shQ03UW7=a|H{pz@K+DC+G zY!GfV#Zxu;VITK{`;{^eMfVM~H8mEQmWY;%r$&)RGuo$p5qJA~s8P$3@YJ&aU(gk> zU9E2IS2MtVRl2ob5h1#uQ??afTGQUOTdy5J+sk}B0xK5GY3nsGx+C5 zBy1!gAN1E`P=O`fn4RAjzxee3vh=6T!9?y9M?Mc?(l!)p8uqG zOS)W-KPTlDYU;S$tC@u{L^rrdO+fUSTrbIAOrwtDSxi&K3D7b;aZLV8o`A!vf{dY9YgY#t&1W7C4&-`bZx>*Fwm3QF!Qz zB2chkecnPT@9;#=cNh7nY5TFga2k^ED77@Q@o|uA7O^^W#f~46kMJ=;UqvYk^#r}e zmZ!z?q7FHd_&@-&T-oKPG0El=y+rP6qn^35Pg`(>%u zT{r1sTq_XUz!WEBH)0?b2U8OGG3KYUY8(9!K4Bb)6C}w+VWt$@>d`4zY=b6%jt)(u#oyilZUWQEnN)t18W|!w0O{lD$>AROyv&+U({k&39S#|3>fr z8N$8GuNHz-#})fvwRAf*`rgSQp8)&l`#)6*U;C`r^{XslN9m9I+Hh9F%eeY^5GM$R zgKB3tCz@&7uqwpqVI0e_mAWg^ zXvp56gyoESo+1W(sPl$IKH{_YsdvClq z-TJWAY{H74eVsT*L2nwK?z|>9FWnk9M*Y4lQq@u_DDmJaIxNc@o6TWpczB)(8M%m2{kDJEZ_cyfDQ? zz59L;9Tsv9O=H;b0vip?3g1OitQIjHSK`Vd0^<3|D!XSSd*`|J^#`6QB2W7Y!KS5d zH8+G2!`LK{a&P5%(tVN|_WL{m6+r~Utl1;;-4d)kU8nTM*K%m#tT1~##(AU~ol_%k zPub2y5GB~vC#18to+QSgtkGJ&vz#q{2rxw*5Us7DMgx>f@K=urVw?=s$yDhoPLd$(TyLiDxOFx?uri$>% zu3YyIK! zvkI^Ga%17fO6?`EFlrvo#ObQ&{qh>$#IbOf9G+C;H|R>6i4`2_xSN!X&pAn#UQ(&` z@brn{Vpz8`TMT@JkM$-DG=NxQ!TK^daK>#JwWzYlC&cJ+G{SA9w)6b>N&(;Q z_$7%8SIu?X9zyGW?!h?gm#fw>Rc<=;TOj^l*m3{<<0dkKFU0?5~{Mw-AU^f!YjKI7e@~95UG7*r|E>o|Q@{e(Cg(c3mxX z)8L!A@*vFokO<`}U?B|iRk*bcnqK^f$#9}nJ6Dq5F!ifx%DX`V!REG_Fg7U0B(?kJ z;Wj0@GqS^S&}6wE#@S-k69!~aAn^Ef9}M;OSQeDOXD)16Us*7o8b5=s6E^C@s6c}? zc;{no2D%vEez}86GoKmnaIio%V~IB>%*D15c0RTag9By|_A2XfksnY}J=2M~M*yQ~ z`mXQoX(M)4QX}T0#;GTR9vS#!15}qm@|29~D6VoDkXQwe3L%ZGJ@knJ0_Hb5Eb8+g z#`|}vV4^q>A=gN}924Og7P5{nzj_x}Zk-qq>1mS@>Vqn6<*@iXhPZ3LbAOW&*5)I@ z2&XelZ=L2ce&N8ZGs)aFQQ?W#SmCKXI>!~O;prypl&vEHKVMg zW^6_n&nAydg$N(P#Dvn(Sy}K9t~q%^*`e)sthEl@pH0`Rd1I{CPz|%)w;J>+#aO6l z4Rgy^96IdCzJYvQ&%PguM z%a&=iX#Ds&HEdW@UNuG1ugBbJh1zoPNamM0NiZGGULqNZ=Ae4~fP++H^{hf|IykJz z7kT2rff@c>=Ph)4xZ53yhrg(rUv<$Rs;55rM`cyq;S%W-Qu(mFdLE;-$kty}4`6>$ z!|B+r8L{^IS$|B!=OJ)6u7NyqfSNU0i-_KTNk~{u{t_+Fz{}%c0(Xc56yfKs#5Ub^+$HKYRv9p=vsB&R{^o) zI$oVeSju4=^d>Er9I}T^BV)DFF}&~T(2@xfj=@d5ZyzyQ?`JtZr4u)3P+Xo__{ht}44b-2P;et*X2kOfL2<37jNyS03Yk&6`FBR4)c# zf5F_=nO^hCtp8p9z_q_?aL3;T^3ZDyQ zy{@1`fV!?so=czJcydoV``PBSu2j%Q+w9fyjtSv`k!kG{yDS}-*ITL5Uu}K()$bV~ z*v#w=jtY81sgkQ=e5moA=y2kf@$PZy5^ybj09{XN!DRlZx;xnG?Q7zy&JW@=HYJ=I z$1kX-KQJ5><2RDnbI2Fq3mPTGe0pfDopTxd1$oYUB?5P0bAV@Z5i19q;X`DlE*5_l z0xUv%-ibX&640mBZ5D=C(HOz>;&SZ%aaC{j zGAh7vBaxsI3KBZkw*%zcdM7b%{B6~E^n@&?T`hQkKl^gF$b4c6s>Z{c%(}f zD;$p2OX7RS2nGB|_fKBwk(9cc^a{@1v}r^n)s=a5IZ&YLFWqk?m)tSSJiFNe>gY#_J9whTkGAU^|X zGG0FgbtKrYn+0Y0QKtARY9?)3^{a=PPs%ybD~Y^6wPs#hV!ePb)^_WUH3Rw}=T;xU zKqMuE{_@B`YIjtEyeu=2-*^+c#l}@}1cM!c0!@3MwF~esP&*3LY%)`WD6jWJV-x-D z{=1QfYi3?R1#q*l-t_Ih&glb6NVx$kj7#%>>bC#n10{{uD`C3(7T_e=S+xzWVG~Tz zpt;wY-y>`QYfgd@+vi?l_n2(Y?$30iU}dnY3DDC73t1e0o+Sq#zUe_bJeqV?k&6m% zx#!Fon7-aG-7~I`gpHUZKpvdtJ++5nRJW~rZxVm$NB6~Idd`jtTA)h~`T|ID8)A*s zQ_SQ65HSeL%1}%)Wm6_$w1V8z6W?RrEM_*Pd+jcq@$SBNT%8g(w0F&1AxmnVWTZ{q zd#dK;Fe_jx#f^XcWUh!R_SNTX=sO`u~08CLbbOJ`ZSBhaCtqiuoq? zs4DW+XIo^6nerBcVD8gT=9d(wEz42|CXdW9G01)+<@JpQ`9}UCNeb6;MG7MYk^qUp z!2th-0P%r%?$k>$-l>-YnrdCQUNbc^Gi0>3WU{?(s%B>7z;vCx&u}wx`wL?KhhbCX zx!Gcn=ZNhH@h#!Yd$vyccFP~Xyp}gU6>Pu@HAfC`=j*YFceq8^b(wjWueWjQnBY+8 z_KITiz^Lb?S_sdSupi02c?jR@}I1D~~#E!fi8$kNI24mPf?EOXtXkMS>Bfs2_HaLukw10cr(=&cD1nL&V7`2XWm z{F9QY3dEi1h2|X1mEg1_AWi_i(G0{gq1bz!xfbfHNAm-_n6KqHsHEgzpNg*T(y4;j zHz*XghRCRfYrSreHsuVTV>fovZMf4vj7*^mwOn}KHC<|nL`3YI&x(xHqMST{QX~pr z?u{ae;Sd8ixq9$LjX}EVjEGrBufp`bMS)(kfH;17pLZU^tSud(Ne=MCkpelQd$OP*pj!@Y*D$p_LXDVcOs6A0fduy5)O_FB#hK>dD>qPHN zlW!6&~&13{pv_9BjTy}SB>`D)kW-xfg;5cH0&SD%g z&r7yVXTxpq5x3L&Xx>La(e-}lEOahTK4)P)y+;G)i#6E2mWH{Bt3+SgfXhoui9ihD zOgX1;_=#i_8>dj4WyP4I;9ene~q_j-%%3(`@H-#pzGoXfWLwGU-0r@hrUFG zZ=e?-=*7+g`~dycZ^)VM4*#cb|4(u`ip#BBtz6sO{nYQRwsHlJsF9CM&t5{yCyvCa z0>khko$pIXgvaxV{4y0s+TY0Pg-eHCc{yjcod|HSW$|_%F=L85#_~V$={^Zb?q4Z2 zpQxV^eu>dJH6;@Aru~2mD_&L=_LyT?-2XX_(bQ)Yxv@Dflv3WexNSV@1)4U_X3E9x zuX;DlQ?!*w8IUa4@enZrM$P+q;2=09m%W}S2!?H%GzFJ*x2dSrM8EZXRTX$2&Xw^K z_`zx5;p6D+HN45l9PatJCR-9(!LV~79Rq(p|A!BfEk@>^n)9C9;7yZUJjU3R_rv2U zqd`&GEuW;UvVd0XWZ=V_6=S1$;B@u}0Q$#Tj1*YxVg#GyA>{i5J&~Sk7wH?{$S)!Z z_g69gHOC1syJdND#mZiZSNFtv^&%sQ%o}bHZa=j|Xb#ae?|&Sh;T{FwJtJ=KXNSf! zK4?=|mre2dh%$2k|1!K__|5pI!H9Fab7;CwOKnzN!v-VX5Sx3>u7{sRiK>Qi*H#z(hkIS_mZgNKsRm6YRc_CpV3mY1$+B-Qo zk_wA36M+bB#SZ89t*WYuzc*T>0FhnqhQ@yI`)(yCuqBXPX=Dg2<~M8Zb#gsWM+2<2 z06!WV`^|!Tclh6%$Un*EGI7e~XGF~xd6|-Jn7Wk#Y@hV`+*}*Kg6hAa5I%g1clG6) z-Dc<^ruCKrYVKTlEU2DlY-E$KL4VA9l(SFjMG~7fQs$ zQ?PUd(yf%w*RuFcnZC=|dSG*vx8PFkP7RmlbTCgbWq!HBd3qiY`|*W`tSa_q<`@I! zk9#~kb5tLX-wSQ!!C}4SU5M^fXaA1#*@y$tx-<{Ihkfh~G%Lq5Cu%E^T`UVx8yUN} zQ#PV4Z0mj>?<6M6S4JPc-pZ!$1W@8}X9eVr57Q6R>YMOs)<91b#6=JtOezE+17AB4 z`t|Aw`8T5J8-2YS@Yh2?zCk`Xe|Lp!i#)Uc+BXk?Eq}LW-!FCA_z`9Vj>m2`gV_n{ z$Ij|0Q7|MBymwT@K(7`B+X&haF(>MvQer4@{7+4TeTELLfv81l_nt#j593!@iC7}d4t`HZ^@zHR4`&VSRjC==GU&$n|zstT+7gu^fu8PWSzKR0K52ooi zePMd{iQUxwq~1{&QfkbYH!2yRZ9))n0$LOU<~;Lni!>58vAmI^tc`&MsTA1K#vSaa zZ|3d@l=^^8%t&R79T|TX0wDv1KwxVp2Qx=!u(g|o8Nd={!OR9?xz#C;eqKb})z;p~ z!NHxB_7?UNr6c|Iw3`YZZV(F#J8(W1^L6qzko>{|RPo#nLB9V_&;H-l;%t7avIK`x zP*v)YE`7{Ak465Z9Z{8CE5zeBeBt!Pl?6ITGblcKOXW0O=zMj3_Tw{m=vM80UX(5+ zx72dAtgoZc7?nuPI3gdFsWHiW#z_bL@=}T~n|z(q%^Sx#oCKh_VhdGd{02E>-U|{G7 zb}%EAFtT(sax}6uGSdex0Q|CdBsH=$2YAFBY%EBDQ*6z_)}(-U=?;{c0hb{)HM>3< zc;kSIGGiM{H?S3OA;({D2e_nGMi$1vk(NMPY$Fqfn->^33+wKq*g{Ix5oh& zy*}_}_BWs9`fk^If$LkEf&mt^U!IEeb+1`#BS%tG8^FK5`KVyhYly_*H_jVipCurM zjKFUuLx7`()W8hzlS!SyCT_q(0kD(nYhK^;=d6V8oIz^Da8pcoa}Fb^w49=XvZ}DW zDjDfDQf~&dF9%y27?A>gJ*gwG!O6jh)W#V2FYrLF>CkRVEUphEb#T%*2dLOcfxBHF zDgWCyE2^kM3S_sLS%UQ~f$IPtPJ&nTR zgY+S2*Da~Od}64U<86Xer`Ax)M_9(pHpR^YY8(uP31j>p8J#p2yIaf8WwI>mOH-cM z7HnnZZ808RoVQ-eaU!6!EG77pA4(H=%RH)6?ey_TmM0nw-ySVni8*yrzckFkj%sSc zO9#W6`1Fo`$cKkwOM;1Dg_*cfuvvg^O}N#sF@Qbheyd**Aiu2C`H~}^22x3upV%id3eoM(KNm~>9sv10V-N-D_PCos3Ni@sTD8Jq zL#e6UR6VnS*Z{K(pmMn>;b-N(GyLyO!0BJn>evkR5&nQl(j`o!X*W1vS8O>fn%LcCVKZjGxtvBgS*(?L3qY*A}odhUPlM zI}8k7){H@cVcF{yI#UMti#m3fn#HpeC$YlzX6K@VD83&y*fT=TARjSuBk11GHV{T8 zER5?6daJ_Ze1tTOGUhM%K;{1alSvxybL^%cF%jqQX+`W12Fp1;3PeskX^{F&oB`u7+r)I>N6Zzp_>`Cgc?(%>L`t#b)rQ;rJxVVZ>B z-u1c!JC;OSm8q!5;|vw24VRyiZ7=1sldv&)9pn^p<;x6|4gDXfPx%lQ6WEpw=2|!> zHc^71MUfRNv)E=8<#5k5DLD@(6tz z9#N18du)_q{?62LdN7$lvdX^8CF<=lIL(n{_`)LlOyMqd6|c|cZiR$x z-{Tq!#z1Mks7Ov3o-y%W_tL%I*qM3YY>fD$E#rt}IHF+;l|E?31pB&v*sT{AaxE?D z7(Vkf;50p2JF9%xCG(AhgBn{kD9*lS18OVGY8j>AWycezk#G@DtyN~v{l1zQGYPcd zA4?1(HC#mn_ak;Qhqld)S{_tUwHDG{90=q%Nw;Tw>N_qZHb`F3lDLY24L>C&Jqe0a zr&_6d!j--mY=}c9O~&1>Z(LlR({Ce4rq>-ZArSF{coc05QNvrKSEvM9>cIwk> zlmt>@0vYF-eS;6aiSj|Vu(|e{9ll#t{|1N1@p2RAF@a8BFvScsC>ptmL*Qhsp4O&K z@Ec#05z$Hq@r%5Y=A?_5B};0TS-3hwxEBZVQ_YV{@QMy#O^g$o7uDRl=(VMze54aLxB+5Y-J}_>VU}8ccScrIN$tr6|bL>QMTs&=M@;$nh7=^ zmiiWS{DrHl4gj-i0)7D9TnCsqX@7@X{TjCha4SO4gKJ%igpK_eYzwwF0#?623Jsaj zZXz21Tm>tqD5a?SyV}Mkx*7i~Z2QJnW&yDRRx2kv&?4;GjJ+NL8*Xb5?*`BR$0qSl zesaV+C9}r|Hsb0w&_OX3tFvdhc+aAWpV~fqYZSq&-#{B-(7g6KbtEGJySbe&>h!Vo z;&uVdiKfSRTX{h0e2Uk&jI9_)oq0%!vb(Ekw$I@V3-KJa;zz2Dp86~U6yN(3p!)^b zp?sgjH1!-rT5^M05BF$^2`^|mkcyqloZdqf?7Nolco&c{y+F7a zMaOS3->CY<65Q9DNTSchL#~g(Q~8*pDXiuEC3`m8$8rXgK810HF>M;o23{?iVs>P0 zl+?krW3#y;7xpRs1P z0}qtBW}wMy?TK>gv*F z3h_gkFUSrdxxYL5(eu}Di#2Uo;H~R?2d^Gl$PQP>-qRA77fL}EX7Zv$QPU_66CGq5=syGPc1$jkGS%J|#vEHAr3wR%m znKyHhxdiUuQrAg1b+^I@c1CYf<|_3EbclvKSHK~|NVVR#ck8qiLO-NkuJeA+ zZsqqFkl*=R`9)@CVQ1xJ;ky2N_o-bY&>D9f*?$xw)Ele=kYpH1MH%UzVh@dteQj3( z%)-}+CjjpJJJbbq^|%fv-L#Md#FzE%@PF{m|0J^oCFN8`QxKR_>+a4a2di~5`-5G| zbrEF+3iUB|HWKxdp1R#Da#ZXMW@v!iYr!m?EEMJ+3t&1}l9rXX z+O_rS@-BcKbWQ#0`>Ck6M=RqzCWfIPagVFs+94jLLvXkt4pe^%+c=j&T5^tU*caMt zxU*=m{2{5rqF$gtt%+5D-u{dp6XNU{9#g76{M*l(%|-6wm`9w|W4EeePi7t^&AT%I~)H1X9p`i&G&KISYySZ2a2_)1869?j$hus zYhXfSm~P|zc&>gJ>J@%{;Ml9BFY$v^%%~6rG1lGhz&8O&02D zp@Y_j?QR^Ik(lo3`3{|Fan1|39k(5YGI$rRYk}#2f`F(2egIji0DjnSJfMrMkcn;Xf(bUEs=(%Hfiym29y8R^hhsI|3{R~BWGb^yY+rKiJZ-9{-%b62M z75$gJoB!XP`oHMkj9a~a0gWrVQnvYm6H|X@+@C|)Q~U|?~ygb&rxKJI61tU~U zp8ZlyJ&Fc|56KWbQaC;!Uyf0CYcPXosrI$CbDJ9S>tePn=`%NHMMHA$?6s}cG~m=;%;{fUy=8C6X=wAndi?r9sQ+T`801KI=vWC#T^On6$b zjyMb&6aw+LQW`Uc*a@%+3C%`eMZb%QYxZ)cbn40yZN)b%Kl8M|MBh4KmkV45) zWXKkU;};2&V{H=Y(qE7ZvdHDRMmzaHEw)kgPJ^S};Yz&xaR`RgV9!@wMo~CvWTPb) z`1a6It*POwIw~2j(s%q`FSIP$3qK=^doRuzH#U#Rt-VH3l0wvPRfH5280yz10zb9K z<>xT-;@Jw{`wW3X-i!n2+LK*RY)7c8*V!wl5N?D8#=^l`dQS=%5#Kgnq>L1j2z9+4 z)I?H~;pK8xYBC55h{Ib|-~R(O`#%uz%TkD!Ng0&q#e)w*&uE(3LDogQzX;P!x$TGx zy|sFqd~HJjL|mz4AL_VsPf#Wi{QHKw*9fkaX5+}xbFAHEY+TX6n z%}u;7#-`G|w9cvUg#GNfZ~5J;AY%LD^som0dNEyvgVc+))P8HaY(w4q*vA!c7*|T~ zQsvaB6k?MxAXS`pv4?vKgoVf3gY&(`&&!(f>se9!-k!l9nXga<=)(1P261D4(in2# zrGF!fu9LF#y;J~9ph)?q<6!sxcTBp5{CiNT(+0A(;gY$~qFS%CC9+U$uAWA=&1Twn zJ$p1C{%m*!MZz+s1}RroRpcHn*1gu5^JYiutImcj!wb&e>`3Em!Lyl64P3UZ!mkAf@70d;X7iwlbq64zqa80;}lyGPj=7>L1-<^ z)ke`zOi|DnF0@oMK>aZ~DMJw2;rOR<_fVOk{B`+V9cn7brxaOU<40a(Po`;FaG%KL zNpybkCq|K#BT<06zj#t~z~h%)<0k4hRc_->^Ab95gYt#o$JUQu_jDDd3AevZGhS=p zD!|sxy|uTmLxV4F^)Dp#-S_3%*tWZ4GKh))bf5v;Ow7p1(ZK+S2dM&aHVYdoQenxT z-0{fRc&ZH7n*p<%^wzErHM$OVG5?Wq@|V+p#z}5+z__owE^q^mI1t;o4F=z2fwOZ1 z!~Yvo`X~Rq6gijuOBfwaHBMk9AI37b4ZHT^irEctM7;EYjbZKsJ>$G$A@YEa6ZtEy zv1q1{<*($lc!u9M6^RJVkK{J{JvEOZC?ianL3l((b7Dpzx%*|4-aYjY8*0>x&Eri5 zAH>tr!x@xA7QRPiiZfGPbN+GtMJUNEXb4j3&&%^8&0KJn~mIVsJ2+Gjr5wo77ptBNaza+0dHRX%?YAuBg1RC-$lHtN3YbNCjs;Ir|z?;NPC$=V3k3#lMr`WBr=0F3G)` zS9OycU()MAB=R{4^HXM+nqmBX`W}4_wMFs|A!>C=QYD6`Q-mBJ#9TEsDR`bF9=d}R zDl*MwWgbOlK`#k>DV`XAK3-e2XwO%kapm)LIaR#wh_`Bp`+gG3$_5$u$tH6*uf2;=94qBw=i-y`$-K8jY9JCxPKA# zyfMcBzzuXw-OSC#1qeRSaQ6m*yBYrf`Jw*F(px+fjD=Mq4%AoGaYsJ92k&3uRq1g& z5o(cdAjyV%CVC~iAr(X^$ySy;*-hx?IH3*qoNU9TU1 z-yp#)+NK)JllVbEzEg`P+DuQ`)J?B7LHI-4u(c~zhqh3VW;c@f{X<3AT(yq_YuqXw zNg3g)`eD>n$DR=$%kMIbMb!Kx*J?B(jE~_x7&%rI2?aliQg*ioNxId#5guzEV1Kjx zA-MRIBz{{&;8l4MOQ3Y3#H9>#l;%LWqa?}K=*D?k81k$MbnQhqg$>KVpw^;-;pNk= zh1!ZaKBeseY!68905ol-xD0HR2F85Z6K-1$n}mKw6fw2#{!?wJ-1#ZPaLrmsq~dxc zN&KswXrYIZ*%Ca=Nh_G=gRiC4L(gB0f>UgaELXb*1e~NVqY4*8x=p6jC9vh0op~v1 zGcb*UO1*c8CVsT6m1$}Y(l5wvc zrL0w@M`|&+_$mX9#%RW}KTe!vU#?-<_K4rAP6H754r0N$^r=RAG)>h_>y+l<<)Hld zy1eRN=CH^h2`WqkZTlQ6nCPGYH(3rC;WgBYqY=j6fRGInC_eQ z*l4N87o?X`u3Pd+(8-sydeKB6q9y~6qE+_#)AwNK)hT$HezTOC0C$&IaeUlN%F!fj ztgF{qj2H5NXa%{3&R8|=3>SaN(j$eo+;;Cz;SX3 zfukNLG`-~fVcg^T5(1YotXzp*1-{6_wBkgb51x7m0oHbqThO^R|Gfz{WKe<1xE`;E zsJB{ZOZ_1*#5 zEx%xl+^t+ZNIJzLA^p%%h!WWS@_?5ifx4Q$O}2EidOWo6lPfklF=Dz^6htP}Oy?32FX;~A=iD_vsK7s!CtB=e6lh#BRUYkwnzJR!|LGS zPN#+Q%$e8gK)!L6H*#%u3*uuJ6eg(HPG=)VCgkZARfuDVS43>>mlTPd|*tX!bC~xZgUftS(^?)6ierpFJz+t>`D|O-j6HV*2Ip}<6SrL`` zNfVBQji}-Rq!e9uB?5Fe=z3*=#-{sy+jTNAt+I+Rsk98K9N3MNgY>4oDl-=k2*ktA zMR#L3-l6-(FaQhve)3O>Z=eS(GYio7m4%b-hTRqL*?%AYUz^uI8HQ!tUfio3E@2{S zP(n5oLM_G zjrp~(SVMeu_5n||j`h|z6qy&wSWKH0QjFvi6o+&z$1uD+!~{+c;xrIzydOz?KJrt} zH&}&wq9F{7v&0oHAQuH6vEjY_cp4vQ-EQY1qKUr)s60 z4&947F-{--X73%C<}djOrQrz=pu*F$##lZwmZ_xdQhp0-gR3w@cdOkbLE?YTIsP;H z`iIS!Fl{%){cz$uxH_~{#no&lO41AOChG}+dZ9oNcdeYC)?qHoR~z`&MCHlvW|*=o z>#x7BNqoUp`%EM!-5=*m@G;w|`(y4)Dn4R*q;pR+lkYDc&ers5jj2A@~ zHW!D8t*=<@*2OMqdywZC^k$aLG&aI zWB=SE0p$Pv=Cs|ww?N$VrW6mT)W5de*Z^P+5K&eRpv%~Q>Nfu*ZQY8`GkDoY=ii18 zMW$}$c5oygh-?%J`1qq26h3{?_flNc3t}V4?ICn4KWB1?apOv;dQfbdsf;O1cx)_` z0BD?(ha4P27%1-^7ymnOK-jQ^363qE;@6jm1tzOt8X?M zlMH=xvc`5%DAO=A@TC8bzrs+nIqxy@sZ_I{c~_Qv z9~S%A@5I3krEOYK)x^{dS zDq%MqrJn5z$iw$ob=Ss@kh5zw2s+W|A|?!FUA74U&3n{-#QOEqebo_Ee-g&UaV-8o zmUbvZxM@pWHXu)^x2Y=sk(n)wdDo8#ES3|ruIkS$0b=wv0}|*P#=__dyBhfgsHo`R zx%>=mPor!;{Iw!A`JJqut#@MHs)xB>qP}~mkw?)r_~tHH$~yD?EUglfGY-?rL@Wp?lYj8QM#lNke@-+}9DA3vpzsj5R z9eD%R&p-O%{Jz{><0yZ?B!6sHv;>kBtevc`*V5};(i@rM02(;4gSdc}=r<%8cZZ<= z;I012hv}csfm)pTaSo4HJ*QVPm!M@x(!=C6Vsa`bGUaR#U$I$fPZ}yN8KmzTG)2ly zeNd5mL9v#fR!>fLzmYSRyhAa~@ACd!k;TQJm7KkIxXuIahO8C<|``6 zqCIU?W|=9erwwmWATy#ja?iTa*CkgpL=#XLo8OuCm%(&jEB$Q*Vi&xw`#Ud*WnsgJH{7G$yQWvpKrNO87#c~(4|GTASfH^bhSkQ!_(USt=SvezqobdO`~`@s($>BuhnJGz{*OSuQi zMWm>_opa)6*)XdR%X}$HRmGpw+XEy3>k^fKu5@@kiZ`hBZ&SE*T79SI*>Uko2b8a4zyzWMKW)I zafHBvLp+pou?L+7Ury8{5YBB0MQ9Tu8@oG&o#YYi+*Yg-`epKi^+rLCP5lU;>p&So z@OTzR@h*@Rd5!GIzB6{X#g6z~&o%l_n9e$koFkq=zVe*&<2P(-!*R?-QhiS!e-EGi zP{~3tDklNV?P?*jQjqmSWnKv*R)5WhX>sgJOC*Pc3+uP0v&azv z8}YN>Mp$ipkj};7j5c$@7v_ezRWWJDZoHLa5@;}OckcjJmWa%WMKD4{9m~Car_8tB zKjruN5-e=l{&RCgu;b_=nGm)BhKHZvj@- z)~*fHARyA+A|Scw?pC^`ySt?%q+3cl1PMXu?nXe65Tpeukq!Zge=cHgw(j@c=Uo3e z=R5y*{d%d4Ime8(9M3(Tx}S$lShSQ7)6sX329hnAX^cL~`uUuXjM}0==X2-DkSK}i0v|5K`*OQW@*~j!Tr(p2$d%aL( zD|!)^J%Zcj+5PRE3oQ1GDOH;{Av`(Ro**ItE4(O1+jEP^IXsQ#XX``@_?#cL-buW$ z^r-~p_C`#+Ve%!JYct^(i7f~Sd}=%l=u$lZmN#GFc|CyVudeZ24G}F-xMQ*Z_NoE< z*(`72xs>uv;wU^atPH@5u(<(pL}Yv+!z;3h5`!Is5CbEKg$3wR0l2x?Ic|7Y(8$C$ zlfbztfW!PcKkc@b1vtdHfJ7BQ)dDdCS{6_N;m_g!?92Sqo{-nok^3-*Zfgm*vqb)t ztpZO5qDF6bx(HSw<6nvz zNZU&1{S`vZWgrqXY#CcbyO0?ku=gg@=Z=Y74JMDh?v*-@D(nFe<13LGJig|3x%97S?A(CsH508 z3DWxWQIrw0+L;db=YESy%1>veQipfpQy8im_%{Nqw;rJFCgKb0|9F(R8di!5e`4%g zmd!QzgZBdWXV;EK*pmgQB99kCvY2vD#14^lsC7$L1;hpi-=*08d_Ll;5pP=*_dI>G zq2*E3qu3)+vIQnFeR)~biA6R~X}pSA*ydMo89kK)UrEMs;O@G|JE`0?!#_nOFfdB9 zo{!ILkAqjci@Dqg`?Drvc`j_BYsEX^P^r_0Ri0XX8(rQW2UNH0X4tS_R-8gxcK(Gc zT&E6+G;Y?zzvg05HKH1AjVFA!v{gGT2T7Xta~bYIWya&b^J^(i1atRfxS4E(?0In7 z#q~l#u@C)wRrPPL_z(ECkUSiMTJ&B^Ne8Ph69xakG?IKhp^k_mhru?-Ml`ws$JFD? zZ!tE*gU`Gf&4)J3upilO$Z+4J#I(t_ss)2fuP~eSL9DalY+hP1N>GTRy#+Qe9+Cf1 z@eP+rL+#hW<{BevKo`P&6Y2H zht86lbg(1`(6DM-9%@yr2LIq^e_L&EMr<%^=Y~ossX5t@!&zs#p~A1DHa7|_DD9gw zEN7T^NB9orDMUe=kE0wzi{NK856N%tP%R_t)R2_wPOUADeCRi*$*) zvLrEaC+BppCS34qWXd?@Qcj2@^`25L?41=1C9m2=Nx6SoYD7etqTh>XUSG`d>g$fT zU!8pA+1YmF^a6$;uqcOINwBKuT-s&uXB=}2TZW5(%~G^Y=4;CA8oH*Bv;k*%W<7O~ zw53)~L^Y1_E1T8b54ItsAqk6#MCaqvmve&P! zjk#kXiFMHiUsW1$FH%chyqvEY@}*qa6J-g0Ru4C8)mR3{Zzj}k14Nk3nNf@kH4Krv zn4$e^m7YJX(vWk%BwVNiwy^w_JuD5_!>rdh?kNYuML3#7e;dcael5{kI1Xe+UAIj| zL`D)aF)??rzO;F7!kf^@*td?}u<3y=cvtx(fZfXl=B+YccGm_*Ko6p;;eXLn{>cii zc;3%~!(bU_WvQ>2x&CVKX`J*@oKI4pijk;sl&R4I+@cnT)FETa^XJ6$yLxFL+5YDN z3v`3T>F4ZkSX|jeC)g73`Pf(8Q6|PDvMkKQKA+ZezkRAPw*Se#J~{fnWpZ_}QxGz- zZf!dK$r~lw>3SFbSZM@=aN_LygrgS4WMA`KR7hJ`AybkwY__Ci(vF2pd7Yg=js zGp0;l&fNE=yrv_OsThtA70e9sD)?-&E+Y1%Td}UPSau9S?X5)C(|wgxqjaht6_vO} zhaG!52w;sh3|^#e3PmtYt+0N3LN*5JK5kTF#5K^n@owWWv}9gp5~RW z{2uoh@2C+iJz+o;u$uUIuym)wN*Mxi9!n<3*}7UiL1V^x7$S2&MY5@#Bd3mi-ZLm5 z5g#jimLXfS@g44QwETeGlOrlqiN5Ykcy6zcblO&U+$NP?XEC;ZrA-L2QAc;p?~L+e=MK&N{q%OFgjqKQgiV`q6ctJfN!H zUmXOXXSW1OOyx$$0l4KtB0z^pYhwqnSOFnJAyN@3aZ({pz^lu`%*k=1F(F~#-zpYn zXr^y%0Ca!^+{+BM4yH`xAkr%rGoHxx88CNM#MTiQXnpXAj!_e!U}F& z!vf?GTn_=4)c^4p^n)b5{iXd@U$UBAWhqx17c@T^q8xMD)2(>KDF1n@6d>wKcoAsU zId`6B1yh_bZoEf$#HHM!;9fbY_l=X+x2$ic{&UQI0ZB+Z=K@%oViNnkUS&QaI154k za^!$bErO?Q1|2o*k!;$K$oF9+*a}nhWHU|p`X~`o1+(_GUpCvn$%QbZ+3db`y^Dlo(|ej^Q{$3(4Nz-Q3As zy$3X3AvDqz|OM zUNJzQcZOe94CBq%0azNBt>OQKhQ+vpQkk`>tcRLvVKOdoE?+)ohyG^8{zm43zbteH z5DS0?#lD2MZ!dT=xL&PS6Vd+z6V|!5gHQ24}4k#-~cQv zJQO50=;njkIsX1Z?HvF5Va=SZt!}Tg8z4g#N^HXqY$5l|_!+&2{}H-$3*(qf7bbPG zH#dUHDj_JQNhli9A$En>OZPCOOFK{S4quU!nAkK!1jwxHPTkLT#{N2_IRRG>aW8Ik zipYd0URXri;W%m{YvdM&VDhnvK_ZOqZOQR**u24RiF6)b)*c_ZQOx?&yYfFy%D)Ti z7R*@p>^l#7v^r3hLK14xow>_aKz72a)voXs!hQ~3gBKV2uqEXCR(;Mt`|bO2SCSP7 z-Zb0DugrIdWZYQYSb5`8C^zKnyYSo_Ny#NO&L4Y0SFflybur625u45An`xHwZyI=g z_E|-AcCX&7Fis|mo-Z7F*}z%p$QyPveeE|F1h9<#3eT7UJj1`z6Mm~W0`j$WOyZgpr(L>(M`n+L}WAoq->3B!A`sz z&-!%yxHv zX>gGJwuAL{UpW~avE99lMQ>p;L}ia$eQ$PpaLYe1J3LMQ-Q{FrW&%5^sbXw~gde2i~QuZS~~&NvSbshHJm;SVfpeqz$T zt1j&SWT@*HJ_(zY&zawc5Dr4`pbL^K&xtVB) z_xTfc;J+`td${G7`)ml5Q}G+>{N_9JxWYUqkOPP_lRc9)kog7*z?gTrv<&sZKQIDo z>DE%ZSxJ}B2V9rQ9QX%_{Bh-For!;Q-CuY3OX?DW>M7KA%IZbV$tRC4QJ)WT9i4{| z>iw^)8Zf2IU|d$0H?_Y*-P8LNA&)CZDGRx{T#~!l+~A}v)O>b|Uehh7u^*xb`%JGI z_R-$qPFr(Fty5qXy_aSG@SgY#W7oVzdpj#Momaw)MjJ{VVp1z?*c)WVJuU7*D-M-A zL9S-chuU(`a_GQsZuc*?hK5+qhNft9$9q>t-veyKi?FX*s#?_*Pm5 zj5pD52;f(j87>?c(D{v8KnTh2aQSD%udye*w7II+MRtWBL;!xkUf~C-tS^12pYc2r z)FwY0l=u?gF9;0s_5FK1!T5K0g7F)kV4#V}$;gSy-NuvaGCt54#5d>ufRx`lrh?dk zaQ!V*0a7miM3w&y@AyyPG9(xl=CBw;@I#@MKpE!cNI`S!a;P>>(9ind4|f+C1>h34 zvmeSQy`AF8QY&#%upihEj*$^MFX)-D2y_*#e`1m-uTwEfXD2#1$q_GX&I{_WFIU_q zlgXN>yQ1i5ZhBE1xvH~Eo;pAr~xIec(TBH>+w#s+Io@u-LNSKkcG+E zy!b1-X|vB4Fp?pzvz2Qpl;-oM4I*gG(gHH|&x>`LDp`YGM6}FTlF`gHCq|F@FOU{4di}4hh!AxvJgX5;@>XjRbua@mm+@ zEj-At+*0u*Q#3vvyZgmzpFcd-F@^!ELl)lNwk3*FA0eOE7qNwrlu;-wW?E9LVW(@h z&c%|Y2ZEkSTzX?AZ7?|Qf~7@ul_HR`W`dJ*j>d8Zy}w&P0!KQ#4KCr%r>S!RUU8v0 z^##>?ygaRhv233?6^k}|zB7Pi&eq{aKs45WDr z9{`8M4O124o(h8!!|hrH$N-7wlI#dAYAee0=Lk%9z9x7yVx%-MHY!!G0=y}&pF`0wD|^o*Z3PNgR1t$rlE76bzKbWY5LwiJz{r*o68FpCuo$C#FIr>+QvQIX=#CIH@T6BJ)Wo1V5i0l=qkU z`jwtBx7IWX1 zzxy)&x}Gj~>z6SR0wF#12QB7~4|&*%>dFyZ`0VbySbHu?2I+LGQt2 zzMm{w^G>{<_2hmZG!@>kKbbS_$~-|5<@9sG_|^R3{zG*wlP!TqiKu==b%@zBnsBsf zc}BA943KO&6#^K=DqqJO^UYJxc3$o>5!(um9=T;i#sJk4VWLe6;b=d6aeqsICc{zQ%v_ z{qVg87pC`d6GXA$s!$D|ZSidt*=?Lv5miR!M1siBj6=Pn8p&oYnFR=*v&O@w39+re zSWlQKd?Em;WSu0pv9v&=5#3tb@fvHeM{NDIc4R95wh@I(E>JtjwravdLEq-}v!I@Z z>Lu1`q2O#QwfDNK5U1v`V(-pCH*~v%R?f(^r(ihOK(;LRYFg&jgiIIZ z%s6bwX8n+BfE)SNW8~z~7B7@)?5MsIoy==d`m(nps9{jdT5Q3FT;ROn9+TGUE+7$^ zfGi|j$pcW|4C=bR85%@Dz z&W<-GGBgJIO}m#rn7~4p3lhxn;Q-n@0GkeA(ENA9(Mp#+J#` zgGJXUw6|6;8%e8^c_GfNGp3@a$M+3Bh1qGZEWtvZ=dQV6aaM&zf` zo~2ii9lGgbk$_M=MXHC2x6wA@DTJPZuK-Z@}z^co32|0z^!5xZy zjN<86ox6Xid%hv~I_ zJYgt1f^UKob+FKO@Hq(=XOb+4U#4??qf=yNyjE7q2DExC;*W9RE0WLpV*uoS)qJ!ArIJ=!dLbsKVV-{UfGv0kCejy(u(+! z^V4)oCjUb37qf8!mxR9Fr>H@cS33=flCd!<_A%H)#z^|{kRzLsV7X34$?HUxA*?_cBaDD@zmI4^T1|9;% zU;aP-0sje>>Yi6QOr;}RE+nmiAoEZFba$L(HX`DAyek zlO=TcB+I<(5PI*2Ki-gqj}L?xaY^?|ax=Ob72zv0M#P{-3riFo<2^#xvC)7CJF<#$ z=9RGQu|O`U(wbq34_|wwI(YJCe=2*aHEpljv^_23Mp9Xje~HbEp~dK?+S(RZzN_(- zDmjBX(Ngms&Q8YZ^A5rkl2THoB{QEd`%jQM0 z%+dy~-vG0zp0xol>}{&TO0{>TQYj1hlJ%e+FaF6wifNVqenjp&18JFg^&%rybm*h1 zh&V%v9Q!L+0vn*eM&f?+g#D=-TR2d<4-s#9t?-yDj9NuxM5CL$xxHImQeA-Z@=r5} z61u9M3Xn$xjRZl%=vi1MGdu}#L@N^ccz|&c!A0A$+bCxjUcmSbrvphjeUu>KB@1tU zu|YP3%bO?WHgH7V9krqnFW;e$>Q5o!iA(IQ|1fM7gcZykuHLUqW^XPCb_s@2fuT(e zdWO%z>rJ1FKQS7j^S-f&&uYT@-PoSXy#bzJPVzLX*yIkrW=TIWU#q8G1kCuv*la@@jx1E9na+_+M4iY(UFid{m*+$sg9dW^fu8y!= z#rNHvPWGpN!Utqt^B`r%9LKiU3kB37EM>@vQ`pjwtY=RC$x`FfvL2z5wqat2R|cpL zfF*8Mc;W=$iPp8hO0)?%Odf)w0&Rqy=G++Z?DiK3j*t5${#Ep@v&IpCTBOQM*BUWA z1`6Qsb|RJ5w**S#o<(M#$(7`f^@82_P3aDfYTVv6sX95Hpu0tU^---F?^xEw~|5o{cebIQY~i^_K$h8r;=^;`cCKxM7$ObW4x%Q z+*}*97y~Bj@po8qtP)FCyS}$NKTQ?aiFh+)aaK#Cf`h7Dj<=nBxKpZKm1q5P-X6y? zJNPHW+&MmzD{?ZVdnxlGEhIdrO?$4+{RXiV5Bb(!P}I~Ct^0`PPZmMq%(0g^4Pim; zAtTzEk!6L2hmq#NaGfV1WP1o{<_vdOQXbwFzZc#w#ad#n(0B|tU{-7*-N0X@--sBD z(lf`m=?Np9hNxp1^J%ktgF51kOi+m9kWJ1IF?JZ{7Z*|JXNE;z2c%LvU+lkO&XUx; zR#Iv~zE!t%lCIxv-9Nz~%R!ftfcm9KJdoEl7Lbtkc(`2*=tgy^kpTIkAg)Y~OtwIl zTaK;2EH}o#Uu2i+2^07(4`66O)Hk6xXvjZ)g8kzsxIcb^|3!!{ZEy*^d$UemNr~@H zi>Y;-BiHFoH)TC&$B{1%XZuvL5x+<)8^`KdW}v4Q>-f{HYrJjwO1}?bNL15ewL2(P zFB5AE_ZpGBOv(U3_M)c;vn&`}dj;|RRotcNekY~l-EFqy=i6gJbxajZGo~&dPqNKJs8;WV$z?#B+#C0T z<`p^eMF^#r?tNN`aV(+&i*$v%Gz#gy$D=$tcIeMgnNx}D(~eB?!F2~-U)dYkfV~lV zjXxNHY%)XwaJ#L?#;{}2ga*HSb$>~11XP>rs!@m-Fsf2YLQISx`YSz!Qq>$Nx_wnx z`?9v5zST{`DN-RvM_WVl%cD1J7N8E`RVB8`n$#Vi38g9vRS^ms7aCmDnXYMw!Fjg{}H9gLeXdxo46VFV+uFl+P?e;9nO%`1M?r}mb`IIGLMDAWfvTW z7Nf}>MF#e^zBzsn3oUsqbs_DQW*^+)LKLk@w0YM5WAjWex6~cm{v-B~Cpxc{dE(St zU9Mz1Mp#}vahN1h_8~nReYkpT;c&Yjpr7+oCa)kM8<*)OV{|jc!(=Q{`S@mF#m`-u zGZA^eLM&5NUp%Luts|#OK(${d-Vg<`9P$le_vsZkw ze_vPnoknGYNCFsN{xY-kVvP`oN_eY?$n`Grl@Q9RB*W6Vew>^ zfY$2B^_SdNQ?>DBr^1!{o4&?m zBk*>LpH}+{G{X5&(W9!vR=UB~GEN~|Mn`*NKH;p7qrh1Dn1(qw;wK}%?Zc(Wd~fl2 znY+lY&aAEg(ad5QL1q@seP|m7NUR{O*Urw}iTX{mfzzXsQ;jsuk5ndCz2tvZ_~6vU zHAC`!o2>JkS2x9}Ri6(I6gRa>LzPfx9%A!+N)w%}fr@sYt(dX@>m$v)9;#jcS)F=8^gA{+WJG`!&Vw(DDSCXeV|#3@0J`)uqAr&pr@;=wG|n*h_YkYdH4&BX$zlb zZu0t|2Y!AUrr6TG%w*$PM(V~7ws9u@k`E`o8Hc}%{cMz>qDI+l+sDC_^h&RuusDR3 z*`P**49)>LOUqik^W@$ z(3(&xWMzr%g7Oxh@Jy<8BD_WTNLRb}wEJEz^KPbBfCMJ={{~2Z0+5VYs~Km#V}W@V z>B`0ddDeZ*@$|n?U;cK&UjZ%fH^c%6{ic?1wYp+FG>=)zmkBJN$ddQhR_8qE&Fk1! zPCzo+D^-`%Q8+D2^q?|sTYA587x{sQ!Qx3qMNqYv_&fjHM9J{n#vN?h6c;*oHa#me zpTz!x7mCZY%jO#eN9^=;uFd+A9}SUeH5E5-OGJdpUzfVRoi*4~=7SIOej| zoO*YP3c|IoACdcLNqm4>M9UDpI7?>k_cBsISy!WU;a(&r=WTnERz{-Ns9(f+n0X}9Aezz#Kyjjeh1MUPe8Ap~piZBar|=GhD0T4K zJP4j%RNN(!W+|Cx95?$kl@qnUi)XkJhuik-?SsYxhbKm*PBfglxYBcj_Anakqs@#- zsjHvsO5>NI9+PEhjMG=%~-%mb5?^3QE`51W!DIsKCMn|U5F;T<qyHDY-*r@Vd7BIsqEV3UO+y7>hoElyZ5xzRbmi7p?7 zD7Ff>I-D+l@TZo2?d13KRqv>;j6`Mm&OsB^SxY>FNsq*b{PDb6vd{_Rtsm`Abmz*j zFa&T3I(uV!`k=p*?-nwx$@I}zer+X7GM|P5zt&sFvU1*{LQMzdlZSVZKCPkzo#+8C zd6D#!Bb1`!NxwX*VPs(ee#vwEz+>I|QhA%4kBI$a_TD6U1fB;%?XS2^Yv9q-p|5!e@#=*YW5c({M!lOwst`7C6K1?i~8GY zx)u4n@%{9EMA2aw>o51@?>ptYxJw-$3)9m)Iq}A8~s5ac;rto)= zRc2wq`<-{8Cjv;07X05B1ieY#D(gR8XF%W>zrPor(L_}GCC7Oxb3qxiw2ts$4(=g( zT{b4>A`@GW;6?R3tczMJ;gj8?=C2zM478qadwY|VHyu}#q4h&Us@mnDz91%G^(8J& z#czk<-GI{nL=3m5%N?{!yCW8~#8>pOTkUzH<=g3r<0=9JJ0w2#Ug2Hlad-XY;VHhs zo`T+#=_z&5aa+!J&)h~{72`YC5w@~>MiE;RwmXZzWrKZvsKrONsk+_kM^5jq{Kl@` zi`>}HF5&k+z))xq-!t>VY@9712Rl6b8RK-uZ$rbS&*%LusRMMne;N4vr|{$Nu}!Z3 zcx+P)Byy!I^8OLqyox8W{wKn#ELUzKAk*p3WG8?$&B63Xz{&UjrVsm1P*vQQi)P;S zElO@i=qJ<+^n=Ui5*QDaVS{f3m;hCI39?cW{V0Tz47z!E5ZFiXi=P^he z{;QAm>xl%0Rk|aza?ZOZuT#GD-q)OpT-d{i#D79x2(|q^C&*;FRp4NvcK^Fy*Dzl^ z(4|D~dGF^}qSSB}<6=eImKIyGx<_b!#GHn#Ci0{Fv5qI8c9Y_ZSo*{*=u4>jWw~G4 zdr>D3Eaf!6=Ezd1ydlSW!u!4warDvDo0%+KrOr$>uC@;nv`ySSs?BYmsZhB~VR>6z znd-SmU_Gpp2|?jLeX+4L{%>Fv{GcGvOfC0<^(AznW5+b_&hLz7F|!4faZi=_z4_RO z*dQ0K+4&fPhlIxOwKsdfv^TFQMCDf=#rgboZLH%i>+ND9lz{4jWJgR5%_t%2ma$cO znH-&g!p|EYrYFXDg^6%l(Y3`m+d2160~q|pCCkQ1bziVYtvtQ=QYUG3dnl*=K&g@D z!;_MCHqWf;hlwFd$Tp6I4E$;*$~x-B<@cC6qagF0)(_mMCRcu#i0q~N^OF{~v+2cr zxVWf+hkz&s{($`83qXFbG1vYXL%6`aP7dQ-k?4F2_5M-jU%ot$Z`3WUkX8i}iCDl= zi-gq>W>Er1ql^7@WWjzF+S)!f*I!NJ&+LDqo*aI1i8zA2>#~YN=j1HiXuV}FLerbK>1*~WXN9TII&(2IoLP= zzwrOMH~uHXGNtDDOkagjE+-eWk|DB|BC6`yj7wtRVpIK|8< ze}3mlEW4sRgPVR*#q3hG74~5j5Lv=-?-39U6RQwTH!G%Jy5aft9z8SSFYG-pjaV-+ zI%wGI;OCD1CL1Y0fY)H*-yXwjrScO|v1Rp(wrc=Or_|hci{@r4j`K*VY%JUlVUd=^ zoUcH(!M@%Os-pNE?p*f{JE9Us%hn-ewPx#Ac&e8vU}G(1mSaSlH(wHT2N0kMd62W` zHSw>yb4=sTMyEv$l#M3~EZ{uTMEmPz?1n zUl6pJpnHp`O5RP6^g^UWdvO7aQ!TE;O+H+F)0KS1lQ$nM&NH22u9$29)lkK z@y$VE6Wt1i0Zkl@8LV7xm9h8*c`xf$kWfEjizYKPLu7P&_lnq$GVzrFkhJ&sm9RS; zhOuTVOy9bf=T_YAPRK#^oFWvN`S7;{)}_qB#F|tU6x4uMm^yT@N0rsn~|1$0B8j8k?F)vfrox@wH7w;53S#p&NI zVQkqm?j`+b>+O-IuB9F&8&6jrYx%Gr`Bf#(BZ{Jn^Yo2-j;bqPzSx%0i=3fH-t~@Q z`*#%`0pGEXh|frYovXn`H#MOnvB)wNg{D;PGJ8(sStmWCd+t+o_i?ha2i86JvfK3^ zFG((_)n)94lFdvRZBOFOeP~JX;c9brHN;YKcz%)-1quInf00n(Wf1niY*>JMOWBms5aej&4z8SYRB#v%QBjB!&j_hZ;Bt-OI+ad zyH`cTyR>h<9)P}MwJB!$axh8KrS(IoQ?i*NBrAE(#sVhN^F|xg@KT4Ard5P-wXtX4 zDj@k}zb>qru7rE9tq7xS#f$gEd}^Y?@xfz#xzaU9d`hO99>~|=y`9?VkiIYBr)h7x zcQUOkov$_Vq}x8#P2?PucE&y2xH<_3sTP|ulI{>L~|KYRY9Q92~ncl*DkL1rM zoU@{8SW8FYJ)b2P?qX9B5%>59JgBZKR1xZjCVxyH6A`u?^3J4t?SgiVw`g*>y#0$= zYRHj0gzD_RO1#z2I-?nbusI}G=5>R9%H)*#LIZ#43OILA&%@>oIGMy+!VV_dG2I3w zbez;AwTC9I`eaP-3=gEzaCbNNXzjx*>$u>hTu-+cUPQx2&@;MvY>70p)hACJJLb{t z4ykQY%Tnq_MVsAWtT~#7TVqJ(SIGNF-hr6MDQQ)HeBt#bP;Ig9Q-GUmoya%IXNMC_ z_pOPWKeAh?Ywc|2;3?xDKo7ete+h5oEgzA5ywG#>>_xtdc&e~5e-3dgJhX;5eNEzC z^;nq-*;d`OG(_T0%y=r6=2a01@nM7{Y&{;J8Qk&)=eO^W#JrNKQg^zgIUv%5QCb|o z*qW?4NPzfJmyn=)lZ7FyI^(?cJ3{B4`Qaly>3G8ITHc^%uF7>*0p~&Y$%y@PqvXbO z67O8{D4H6eH&OMdQnZ^aJ^q=mt>`!pq*H?MJj4Qn<+sjFhobuC^KXUuN7IL8PeZG& zU9G}@VS1;vn7&3P|4exx_U5&*A{y0%SdroHTi~w_iCaE{o8FS;YBHz>vfN*bzSR)E zW4_;0E~TN6>Ovjyv`|ePXY4@nuv&B#L9`k7`7n~tKqvYcgbJ*FkkE7`MLKWCM9)vV zbVj!Xe^T~Y&wJ(=!MV=tFA-jM%@uuERR2`XKU=rA&MG*O?R(%Rz&MtB`Z;@42L=VF z_*`gvsm$R-)Q?4Ym0taaYPf+wop4DivX(c4F{PH097LI$ch=n``iL5$$n1`iGoTVt zPGk>^K|#j`8=!@3pm6HEV2riPEl9P^^THtV?n00()iGUHKzOjW{J>K2VNB{Umm`AO zY!Y0BW*REomo|v}8p20Vh?qmILhpZuvyplEaqbo<$KbKW##vi%ca{y+hXls1ru5$9 z&U3HH+IAB^Ipttn3VpsecMkJ8%PffOheFbK%)$7A)eEib}f%-Hsj zEFOdWY+6;|5c`eZq_V8$D<5y!mUQ^Hb@=8tY{@Et4Y;o>^K~lxtt`z2M>3{&+RZI% zzgXYd-zk)LL3H& z3k5d73|S`h(D<;PHE+Sano;iz;Ny=vPk%UHRddG-j}TYnDqn^a@TFp0`BU!!{?s4; zD*pB87N9CUW&#=*fo&9c3`AiEAmr?51$0WjIf#gXC~6LH*-7;o92sshXQ6@2Ss~KP z%>~>- z6oGYxFUkcoa7p9Iyvku*&;s{5KXk48J3!?FGD7}D$14^jRhDdibqi70 zFT7xpt;C_VTQ%^kTZC!I-Ssi4 zh}BK?@nBW4KzQgl%+jKp^g&?ZLDUJKmHjLF_onM+9yTlm$bQuM(iUWbSft35n*MDC z*jOzTe%iFy#qSLdoghl)L^@FQR80-9%QO34fP7DXN0C3{IT2-2W@!!x4{BSe4&-B1 zCB^NJqkdD-*}+OQ8Vr!F;EQ3XZ);}^EDc)+K_l>DU~sey#J;8Y-5g{z)CZY>uOop0 zns0&VGifs)22%a~L`H!54$RlRx)vDxl7I_PLvP*o_u1f=j)`4H zgn)nmS690QkT(o+ZB{3J>32L67a7*-?1X$szIV}S#Zi6ER(Pp~+cR1?ol74&{w4Q{ zRqz9Z)2C*4gS-rmDs+E#PDnSZHwcJmjuJ!4@ESJV-wGelkgqXQK1NJpL4){`-X`wq zckl!*oJ>0C&cIUsB|z8#xh(ou`7GK1K8Ri612n{f@GoB(NaYqn2q`oD*|tuI{;IqT z9ta1F8AuqY*GK4W6r6!vTp$c`eG2;bQ>_6eg#Q~uY zT6#LMnR@@Q>s0rCq^Y93dL4R>1rPR*a7Q`m&_{cEG3)%sNe@2@jxiu?p9g*#F#a(! z!5j}S8^J^AJjHS7n`;Vh@kM`)iJsaZn_ z4(J4$q^tDe4U?+SQGSRiC=3P>!uUTVT60TeqIo1CQW^Vl>G*4r%#T?@_f1cWDb0y( z>5T175tYn!-Y*`r_1hb$K;?g6)Yd@3P_l&nIVIbzDjo(BDx9++K4Up*Y zJ8FP;1|k#~L>L6wCm*_@n1evSA;sTF+xjq{gu3#+$09B2u!}?7>AD-a-U0M$t)o5Jq;B{YlKSYXWN>7Ja}7nK`WO(=vS#t+LS#0975Paf%U zm92it%lX2F>Rfr=u84`mIs5tvbqs3P)pmR#2*?`imArufc}u$XPu`8hLjO`!?;63m zNHG@<`mJucZ{IEH(-68Tyo!KvIvlUQ`)%2#f1ri3yU&ydGIcJW*hVBBOyRFSlsw*@G?)6>dfqFK!Hb8!w zu)d?YAwb~1yxFZVDITytT+X030M8I~x_mmAI02SxQr~P-t zu7-wKCF>S>IX|pr$vC#x8cnvsC-)>aU7a0fBBW9h)H2;h-wP;|nLKr~pB%k-edZKR6CK%Pf%a_4)ZnonmBf6hkQs6x6SYLjs+7 z4?n+FB7RIPpnTHuoXzoDOu@8vtQssFGJNejBvGzlvdm3C#{zLibE^kV1p{+=<7WXN zm^ijac?2vJbfVZBh#hl2g~s^J_LSRT5d!y(thnkMSpvup-nIOg_Iz1gY$9wtjp2!W zeLqO*m$wJ#<^Li1x%MN#V<3q-I~eHOxR_g68Q(OYLBxQ&TKh~yAaDQ|*y%8DMCx|R z*R7oI>(k2S)_|1iTiXFL2T020`ses}>;He%+y1-t`-xWFO-X_mA&xKX&!>n?8J$A=s>*NH+LjU{anECVk@+c&db6adjPe>GV^!>J zaOAkA38tmkP`U13yie&FG!dAV#vk>C6ILYoLRpH9Q@3pAz$CgV8=?7iVXl{ z3e6F2Fgw0t=UpK-0`qFh1DyU=Je|j$S_}R@F(-^aldG}8>z5j^#qh4|F)U#Hp8YF( z%;?s7RTBHd!G(b&WMp)yZjlNJ-&%)%99349|AU?Yly(9yQ)mpFKTgX#8vt#?!R0po zC^7~Du>n~s0H2=iGRSm$2>PFSi+|F^*6=}5{=t~7q!YX;Q3T%5PW6-KBjUM7k!{Fm z(F(bYCdz^;-=;_&scvT6x7p|F%c`~A^*+`PqSQ|(JX-kv+V_a8lcFCDSzwCN!Mz(Y z5gzAw9G4E{h2lQLaZXn8f~XD$-GF@+b7&=nBoi+h-|n;)m| z47#$4%aV5e+CSH_~xMpZoym2gCIb_vi zJh{y?fcsr@^Nj?nZuen)13|w2KA3-Zhb*%klmD6jcE7*3%AkK>JvyS8yswHK>oUVm zUHg`xrhUh#juh7|{vnkbY=bAweyxJaWDwNsJ!~ANqr#^QcQESTm6771FU1}|KK5S~ z9V-)h&>ZY+dx3iTNO?$i`(%sV(Tjjxtc%RL0;@)LFjXs;PXi(nZjslL*<&|jyXtIi zn;KVgyQ^WSnbjwu?NO<9WOuaKETd_W7|bj8X_Xhf5+)P);oTdlvdQ!4^_3RV&%b;j zzZ(Q$bRO`bgzto#4YXa5r>jIJn}@z6ePSh1Yhss+6$e!8|^ zl4V|-9tE>2l`KQW(`_UOb7H~9CH?S|d({-PL0t^m{8xv)z8;<3XS=*74_7SOt;=b( zq>&psqad2PX6BQi@NBhvj=mnI?m2pfiM&PYHrfDYzwea#aL#nhS|1A2u)ssvhNF z891LiyrT9jH{qy{YNUCLeGbc%$_~?QsS2T3M@mf+mxHsB)I?Oiv=lAu>~c!|f+7Wh zJpnWGT#p}ea)6)-l+xaBW26fAd^+Yr?^t`!x%|4yh94wAa)D&~&Hnl=WNHl-d=eNy zv_S@$dYL*oTA=^V|2*L-7_>QYxy!)#wLO`m#pp>G;%!LvjlNeNmTe}%Xpgi!i+ z(kO)p1HMlNO4YnFKF5eLW`}E$TWCGjyc0sO+Jk+DR@8%un4Y3!2+>XSNevf3y=={x z#Od=fS9@OJJh^6#tW!KAwSfcqzR%j5#mEW6+;S$T1R+w#-_*%32p;WDsT2kPx7$5dt*o4gtMRXVpQ_u&&-F0zDBVztZW4Au459Vy^5R9Q9Z4l9TlAW z8uSV2D9c)&G9Z?~p%(i|AKF@G6v4)8HP4ZInV26IqAYZAFD`-s+w|#`ed-M8C)!uI zg9IQE;77xHtkE9#%l8ISyM;i)VmGcHL=033D_aA7D{z4kQX3a~NBtX@5fTRc6;DFw zR*i*Qldn%+YRQ}+Agc!4lIxN!0T3scz?B0phyQ&K{wM62L|IOX`0#2`F4X(yPMH4# z%Wsk-J2WM=@n|rO+lC((Oicy}X9fu*X*VN6B9q@e^f7+3)=iJz_l8i~4nB(y5j21m zA$K%08ZM7TxFx^Y!SLgBO>sBIYu$?;f za*oQe7y;Y_4aBUKVX)z~u3@E9B&0EK?kL$rfAHXNs(b4<7AD z@j}T@Ml|F8tQT}NtyXvC23W-zn#B&s;QAA=s_kD(3nkQp@>jnK6`-XDd@)^|%Z1jB}s^ z$xb0I@g>Y$yKdYVRxhSdYKOM75!T%c70~ybhU=!hlQte4d!PI=#oas^YPoS zw;o18mSR;R6Xl+p)0tDa5tru?+8b=X?@27e(GG1pk_fb+=}={gA2JOIpgp#Ftu3C0 zTZ?0raSK7Y0S|0_8JEMMT)C%5Xjzf|0U0Yc*cgK`Me1ONZ! z@PDlwLfpYMt1*>pzhlz${Cd4)U9)ndp%tl~e1%$wJC>b9M8hSURx3;v| z{-XXQ1M+^-6z>{;j9Z%k8F57|TOZ>ggH_3WYt{S|^^3C6fT<)`Lk>U{2hu+OOCIu1 z8(c??U_;E9A<1}BW*D*{u~W5Vns_)=**t~rHXcSEhrgwEcjWPN&Uiibu zAB!IMeQKi=iT2q|9SuO9j^;nbFtQ(6V@~CXT&}3aiq(` zCm@wHJ zEftmSM;|*6td_yD+o|Q`b75}gDq`jbU2()50r+=a=MPzE65P(*5%|(aHAR~)HsJWT zu(yZQH7}yqH;N|rxM3xQ%i}wlkcBB~YL;@YHaI`%yMS{|{uhlPC`7Qyl{>8q2HfaW z^;FeNW$>f_hEM-Ge1pY?1GI%$!3>bg+=c@P!%r~)r|0In@CBau^U6Shych!x!gxgZ zQwNHbF?9P`fOSE~_{M+x;DEv((JfU@W-uQI zGZ+>IF7h`!xI_;*(VkD!B)5qWd@3@JhbClCC{rkvwU$Cy;Alh2XslnPZ6ugaEr(G* zgLik@_)wJ*-^2-ZhC9jY%NNTUITODcn49Q|x~Q4ze}RQpU{e|P(KEWafO){1cB6b> zpU2$x-Z-4fy*E87gVpCXl5k_l6L`oRbO-9#Bl7(bsxqadTSE!%leb7wZ7YA^(QG%{ z3La+2+(Tcmw))I3jP<$>O_I__08k}se0R7_REFEK{;UN_&naXA^Q2j|Sm1|U7e|=r zeeBS)L|A3_Hs-a!v_rmOq}p$_ragk{18UO9TX*M$x3G_1^Kg8EI(V`iLvm^kYgm~G z4=-rxhE@08*5qOb8VYI=_yShY9Psu03O6w6c`}LPkl|)TN@%lCRyY!10QJjT^np@+ zg23knR=DPdqhJ%=aEQf4MX&Jz;GRF?xIx7D^{VS9VX={aJqdx6t1*@km-(vW81SJ1 zg%NgO4+r4nzyFFFU~B}$%ijoChgZKEEHoml2ozjpoBL3N)m`)yW?n*K*vz6=i@b

    VPU_h^1v30cZvMGprJ%s#Fyv5E(P^pJ+5NEZms-f+c z0L-_qyxu3u6+(Wqk3UUr5RttRFey6Qsu}#Q&@GhK|L1S;pZ2E)gR)qqYPHkjy~ikgcV;o48pnS4 zRNL#(e@GX{Or?CEis$>CfGPEd-I+8Z@dGK(f^SvD_tOK#R(jg_8sT*E|K z9hC6ot=^NA)lu1vXHI$TR^wZA4+7{BaE_Fhh9*rALyWkw#s)S%dV++-GB&$Y@#pMK z`bbP!zq>#ac6h_8m&ZzzWMfgUw4u6u`D)s|rjt#*wb-Lq_c#Zd20gt?xwY6Mmc*X) z0bMZcl!bUxCZVn^SMSI4_Z8>bJoArge~5`LMb`Y>pI{yV5xN{$@S1xK4GqT%hG>cW z9JK(34kU*#Z5)9)g0@DEcFgw9wl0tbW@~EdXlCnRa#@W1i!u+1h}B;cuY-XeF9}4BbHnHtrxh z0|zJIk)xwCP#Xgo7#W$^IbEH=^zsCd334C68)t}&_2v*=6$0S~FK^yXyuU^F_AJ=92(k?WDfVozZ^l!c zzk5xZuYabm@Bg@!`N8o)!0Go8{zfQpO_T~A#wk1h_9{Aua5(dc13|=unb#w#>BqLb z9xeI0g7fO{W$hCD4OWQ0niHV+ok%LA%3bVGk=2#-9nhR^uqfp_dcq1i*(~9`SWqjz@xU{i^_Eq%b5kQ>Cq08nOhWBNhL>-z3D0ys zeqdevG#p8_D(Q~?xlYrV#}ua9z^G1B#YiDrA}n8UkMdn!R$otS3dL#(tF)Ro$8c8C z)J_qDj_W<(^rbZoiswJ#575undZIJ&S{@Osk@pqvF8TW|R_6uM?ulyZU?mrjPUJ2k zTjcnpKBw#7dm%f#(K^56F~CI`{J@Fp2oeem06DSttGw7p!0O&!;rpLU7=P(U7ZYb? z09qpeY(_?=Okf4uQ!W zKQ{zeRAOZ&WfLnCC7_r6YPY`ve25t3Pkn4aO$^xRfk=Y&QizcKlIwmgmwU4x{eS8v z{|V&t^(Kk*Rve=iC$+z&FG()$o2lr-lfYz_zSh_$4SvT_c#76MAw{@l9?=OpCC^7B z+sUwaY zv;+k+R(-A!!)2l|%*%J*!S0Ri`JM0yJK$)_h5AiL&VZY z+J9x){({iI+w89_TZ0CO3(7q;mBKP~WY1u*lCj(G!A<|;x}lsEHr)V)%xT4etIhgI z_RTRx?wqe`e{W67+S@2Xo_G0PxU&1@8DUx9!Vksra#qM=3-3W0;sx!%RG%79F0sD` zdsuQAdKSV_`m3AFe`W|?zN^G-sH9gr32jK1o=s!F#7FU@$(AJ64)g$#V|MKV_vvEw zn8&!5vlqMvo#d1Ixvbc(z4!S)C`x)TV}6yyoJlqv2pLf}J$|OL=G9F1f@syYv~M2X zzmw&jTY#ZWr(Tnrk&}9(6ai`??|Np>oicaLFx;eZ9JE6ZM74H`XYfn{ukTU|5|rkN zdUbTXHI6{fXhax&VNGK0a6ONr`(|jQX_-X=I{u&Pu*Molg z=TNcrc&Xo+C3Zb|{Tz-%dgE^X@gPm*+<%nfQBeR3G&fMPwE=jr*QN{1*1PfSA6~l) z>!s7h4RD+;)7O`!c6JEq>H6@$e&T;>GHI?~r`aLT*f*zEd6L|!f)}NIwoTrk^wfiC zFe=oDb!UTW=VR8OgV$~AZ`>7&OJ444p=Ev{MN;JjP*Wz(8}zbzP0tTNCJes0lJ{Ov z#)9!8eOA;ErIrbc8pIzLa}y!ZpU)f>ct1PQtzL+Te_SsU9%hWF#-n1+!6k?-wJkqC zWJ;RZf2Ts1i+%V5LLCA0nXA77l=wlY&I)DilXK3wO$E<9a2VkbQn=Y;od$t;0;L){ z!`3ccho<(p;m=H|AIQvMH`eAAc2Na(3ig$lc8Cu)t$2AIpW<~qdQaK=<=)h^fMjY7 zXYhQ2SxEh2gTvO~an>f*=4k>!9<|F9t;}r@@sJOmE7PX!)9=zXO7Jy0X6?fr&UivE zG(*1QOAbHW9em+_PgXD?*IJ51D;N?tEQ z*_v%O1j(UzJJZbO6`nD_=VRFCN-bbnur+8_MB=>{qEuD$cydaq%0+`KS#%NfMUYKD zfI_jNoxNrnmnG9J8`0BOf(tHi+MTmKmXZH`20rJaBiRRSjqS;`+a{hK13oFGALzOH z?LuB_RWVd-lqh1wE755V?_k}Yl833mie@n!7BUz0LK{6*cZLp1R>zZ>sgAsm1Ueio z4)sbRElOdsVS*Y;C7;kwj2xS}amrrd2t<$nFF5k2l)*0$*@@8Lfhs+Scol~_vVQED zkH3PA^_v}Bw(Zp~XdB8=eM7x^V zfWE-!0B3q_$1rQpyHQ}12sfJ#Sa*4)f+DG$ zmGKJuzWp%AG3GtVsI0cT-%dl^(4wkzY-BR9PmGRtU>T?`OEA2E7M_)?6*c8Tr6ANs ze=<>#R5rRaFtI`yf@?2TSg|&)5i}gxfLA)PTA*Q|+(BI3)zmdt1$r34_wq$nYEQ$^ zp>w8loV6;%F9HL(QL3x_C51u7_@#PT?RDp z;R0C$h?|6sdPNici`4TkcO5bW=z1R1FMcW@sRlU#3N{O5`~Z+F;{u`x2;KGSOhDd5 z;y+M&{;B=}i;Z{n27oGIZf)S;ehuE2$PFm_07~zF3cljr$s~~mfW>=q{+f1<>#7pb4NIArVm7VciFcmL` zsq_#Ud&FX5!e9(-*EOdx!)RY=`$yjPK&x{yWwGE%ogYyaTPHzGL9DjjT0N6Pp*y(e zp9;O3^!5kwlNXsQY2)@LXc>y0TeX7}`e;>J$+Oj`idrb|5=vH?SK(F+pU*IKjL9`U zG$x(yf39BrK)%Zik%Tz;LE8vRRF9Xv195BP<8`*P&S>qJ$$-Y!4NBe&NZ&$}qsZbd z9(B(kab>!Wdp=hX8@XpgXMVyfO-+iF_0;n|)A|ZcKMftwOx|)>2Zwvl1De8{dC{r3$e!8>zco@w_yk2GHuHCR*W4`GxK&ULq@YvJn%@%ZA=iF(h%V)DD-D z_DbSc!z?ItB^qR$E!OgpOWN&IrLO!;qT0`lKr)3?E8l(22Y+uG5AV0 z(}1^fZtHMIX!9~G!0mX3sfLQcO?f)&`ZASMlq%BB1< z>5iKUZ+t&O=Q1Oy($p}9ZW>p0%UqxoJKM{iybmKZA=2nl*K`rmCOq|SHQ_QVFE+!!0xvR&L zA8TDq06oZ-6!V|gwgN;VLBh8g_!{>u}?~&-a$3P6CBtjbA=RjFA(|qybLW=bY7{P0tjToY zAk2tVmn7~pDF@v~Sev_ZPw+7rAVKHlw}Pqjps5OHO?krfwbu)8xL1aqtB(ZUByA5K zP%kVk5_pB!%v$xhX~{d3bZZNR!iRl&7+M(JKIi6RVkM2B!1#u(dF(-(bFhY-v#q3V z(-n9C^%3x&%O`)6Qo%h?x!{g_szIK4nuhxjbU3Ux2}^a_A9?2+Ir6J5zG92*?H~G| z9&(wAlkA(qIKg>FgL7w)T`;y|ZR$F?m+qhyypYoBdB)XzAfc_{r}|;!obtoCGO^g( zmYhYLJ^^6^FVUsm7GIwGm(-bbGmr?j3NTccw%At5HI>BugH}=+Qy-%wnEzH z_sz;KHgX1scnFe)yv=oX+OkNgh%zKk%@NI(7hZkX#7KMo9H#I2pp@KP?M3&lL$sJN z?A^5)Et{0iJ-LGE_KQdW10Y-@z-RCWaKP#(4j}!8n?Rl7r&K!vHjJno>#sR2DmLa< zZD&890vb?NZqk~6n>Ttn8Sv)@{$D%kKdt^!9mK9cYH!Q=6CNb=9=~RbJ5cGkdZVku z&=sn%&>9g3Jmyp`&AJS&hYStxPK3`eG*91-J+qSqCwzKS;!+bmTC;ka)|{40Y-N{m zOx=rW)CY!d$Jf$8U+5eAjP>Fg?IZcqJQ5=>lP zXx$Yd&@aN;lyD|q9M6l>te?>wb$cAA_0m;g&xU9wPVqtZsEnvHxoMc|28_Rpw%F}* z5(BG+43Kw4ST#nJb9>lqEsTCHU2dJA=+)}?O$P)00)GlD{%j0J0O$fT)skoQWB}#6@L1Nt!ej{Tc<0W8;0Ip zjgw7o?-nI&PhR*@MjVbQnX07D+{NOz=fYFLayb$Fp{&JP4TbQ-TV*lF~R;c$BCbQys)4{`!`E6Us3PfL0aY6SHGL5Z}3g~lwt+I?{ZVcMpTnlGLbQH zzoz)10ArMF?c5#AADcOWt~cE4LFg#hg!0l#%Hn{J?hGXPAt`+zNos8C;Amoe-J=GJ zO?LH~pC|sA_q_7bC4s@imu)q`zRL!<>Oi|W$7R}+`{yAqCo3SC_5ae%{u7*Z%a=mE z7UY^f`Xp^(d0U!nW1OL+?FXALooMXCSA>-0xZ*QkJBSrkw2EG?a9=Q3t`4u&(@*Cr zGK`siG|<+E={V?f@Z_)DlQX&XsyEYuunD@xF?;Or<8*IrW=L70K_zs0#<1)#ykJz} zj}N!(jo;br5?ekw{OFoY<>Q=R8@!uF^LgTeQ6(rU^@}{>ds@{{0-|`a@E6lx@NJgqw$5kD5e_rS@qX zNtip4gpXsOh%+c6;(g?J5}F@>SKDFY7U^3#fv>)-DX`fmjpuYhDwF;r3b5t#{u$X^`Ivmr za|AM@VrHd+M@mlqr4msRaZnXc8O!Is-k$%QzDyed9cPGl59%v%7MCwU`ol*qjhGoW zOC;4_HS4*QTJJeW1e(*SE0rbH*rsT=5^PMf%q4W5*3TlN0e-m@z%0Cf)mJ9~6#TMa zZrfEakldc2<0$9p@`UZFZn$asFhC|$?}p|7D|JnvdjJ9nDA>$bx|i(#m%5h_M;g*4 z%EtRg+zs%5Zw&qWx8K0OYJBU|)_Ai=6by~?;r1-t{m)<3-dTv>kMKuD`NTdkf!V(W zqfU1BJAJMgeEtS3nVZj>msPKz@+rMX3j)%O#M>QcdcHkubG9Gk-If>Gah^qvYzqh3 zCSd$1pwzRYQ>4MSQf1JesxYI&OYUWyNQu*Z~V}N+1E_`ilX$}M*`{5 zta*sV(9cK>C69wWoqckOjOib`PfPqbn#HTU^>}t?CAO9%!iq6hvBz;dvr%bBZj`#w z1zOEFT95<|O7iw;23huDMqVM+o zSm{&@T{28rN@?`2a7gOp;0=k zWBd=+5!>~wzJL1-{I6O^5Qhj@N4Fgw<-y|+vfUEiX|+V|d4fSs*t_s}N-vLSscXeC znPNP_#u3&as@3bg_7Bp-7rjnES=mcXsduKJZ|4B$P6jv-C1)z&N$*3yOrybxgSO zM`8ef#OtR&qK*P@r9}0)L_v)}?`Sdm_cRNb<_0JM%?Llo4#Q$&h?oHJytDP6l6pYf zBO4%~3xO9%lnx;^UmyP8pXi_V@s2e6RbmMdcQ@FHXr8YoE!xXbFn+=!$Or4DlUGgDTpT*BvqCTPKT*es!jpA* zkqa$fNMUMsEJG681Xf?GoiG`H^&x0oTH?{{pc1Z2H;xXWbg`|)(9l_JGt-8+5R#C3 z{ps*FRH!efL&JB1wKzj>23j9nE2F`#E^qjP4r@efwtBNl`1?i5399!@cfl*$EpK1y zBF?ZyU^(S$aZoBZu37b+b4BMO;jg7J^;>=QCz*N9%#I@9G*7O;6U(gqWwDL*==1$! zi?qz(m#=fk5uTIK47H?nK74QcGc2e9`&RyiYw(wXga{-!0Koxsj)2L1@cKLuLqM!apzl z9h;L3a#cz=V6i;K`P=vWjmywsO`#ZU@B<^xW&~8?`=f0t0}pDl*J9a{{#ZjQ=b<$B zm}8m+w23ZT-E#cU0JDJOP^jm#?NN~?q1-$j4DM=|!TWVROhQ9q!qQ1+T6EuFC@Hk; zi5k==Xyus1zfCTe8HtNwqS5=X`*2Br=(EX#VJ*@=>v+*1;yJdfzc=>$P>tE+i3Rpk zlBur)Mx=uFti}4nZ*FzH-HBSVsyA{--qu$=c+JT|tWBbrL#Dim6@Rg3^W0ma(`j^jUC?_;!v-M+ zZXsReIS;J`h3jT7=jQyZjIJ z`mQtasCYN^`hLzfGB>b-cm$U;2FSn^E-+-U5yXVq0m;70!~dqM{F6l=63IVCWJtq3 zK%nR*gD&~%D2^Z|%~&IS7iYBZW5ruW`8Hv;7`0=p94++u2r|+@!kqjvrYb$O;O2J$ zobGH)HN=M8d&OE01iO0e^;SjdV^%t5jwqyz+ZNxpF<2ME?;MYy^uJo%QOFG8m&~Hn z^6>byXl82=U2G)nuTKjx%LeDmvle9U2|9Te7i25O7f57mkaK=-P}J>d82UYp|< zdCP%}S~y+!5MesG&)OxoR(4%T9C7#JGs`+W+$Tix8GN+Q`>5qJOno`uiB&6;5`)=H zl9vQt>MF>2eB~Rq>A7=qG{{{d+S#XqcG9^a{Oc6DJL{E2|E5~^vP~&O zx9goy3Ms~7Vr(tdVNAqd>y5wj7H-(pH8DZG;2RuzZzI|T^4V}To*rGDr&*%9^xy{) zZdo51ZwUk)(Y8S5dyXa4-tsT=%3J7Py(N#wDV_-(diw%*+>&Z|7q4hMQ+wD)F?^E% zy7;A0UF{Epr?1`=_lele=XoRC^`=QXx7{curJDRIqjCp|pYsF%#F!5F%oqE`UNZv2 z=Hr&|PSFx=OWYSQwT7p1du8nTCALGz=?Y&D`B#|5nm?QJ2oI! zby+{*c!HMV;1WWV;&AqeQ&=1(j)l17m7_Fyv9zSP>M2sbNye(G7d14-15AKG(8Q115&x(VFmz$=n z&qCYmIiAbmue}S23L{n(E~4Pp<=!Ki_{4<9Vy>7|Z<-yW?h+@A2byZl7aqePrqW{p_t%@hS>Ck%suZMg1x!MUJ*|{{>ygj zI}O?B$l!cOz`lcE-{+~m{;9scfj(Bo26g~N)Y#ks=n#kOsK!iAf6UVrl@t8Aa_+K$ zA!`Ttb{WV4-`OFLg@OOrfG=@X$OB*U0XYHi1Y{91iVBK}3;m*InmCxa*cx4? zd92JGoxl>QVyPm5_iu{A-M9gWDBRB*(sKZ=uXj0eS&v;0P>N&IGjY*_T=Vw<%-3+j zvFWKPkQo!SeFxJSk)`xp;FwgAdj0t!-3%aV-$sSB+SIQ?^Z`84cjp{IF&j6NX}d(G z0YrOO`cpQSE60lQ?4x4Lc1Mq1-Z#yKq4wl^nwIZo1>{uTmH3Rrf041&#>;d zm5O1LuwAwfP0jWv4(hU7FUD>e8S&6Kld`Yb6uezV<+4j1 z0gEd z#d(<%fQ(p%P}hMzV2IoP^N<6g;S2WtfAqfp3F!LreT6bI4BYZrp;Tfq-_T%?5zq3y z_A>)FJ}@BJWkEl#cmJM6xvioY=imGJYn9DC)^TLe<3OY(_Ng$L8Px=#e7s+TA1IFA>WBR{^*cs(R=fR*T4T!Hk(Y>BvXKgKA?!r~mo zrL+DU#lqvNw|8`1n*tE0(X1M_5ZYZWgx};~jGb)7;8&am)MvhJA!eN(EB~~xvptI! zQS#{JSlaN5G(_fxIcO{q(mQkGu^gX`-DxkXnK7FeSG1y~P9#y9ttJcEo(b<~EehM6 znM7J2A1k&T)x|Lo!Z8k6=S=PR*gi9vw|M(J(D`SS@DA)-a5LZcFK4ArZW=q`B;g3W zoleZF)1s9P5$GHTUq%pQR}n-iXDWLj>rYq#V1)T!%}TvmV3#-oVeA4W3JNgjI`Dw~ zRgSoYfc#Tk9vK$yH?z5{^4}tRRLm{r_W7)@YBDx1Az#J#X_@BzY4WVrrhPrehaHld z=4&fEoSfeV?(TPFXFh*WM^x;1t8VyXS2<^mMxZNeZ_ZPkBJAzcVyPp`yLXus%Nec3 zn-V&LRdw!diOSuxqzND3lLxClgfK>S}e%HApxWXM6*p=V@WMIi_Yyk>- zTLNDIJKxcX^_P~>pPs*t=RsElOJEKMP;7_P-XYn4Ahd@Za&WS-@oN6}UFe@|x!{7Q zeAN_2`fK`!xyYmY5$;Fxb?)adbz4-?Bov2}0S@NpV?s#7(@|wGNdsY;b1EMd0;}k# zo4-z^?wZ5Wf}V;~FsbJ7E61u*Xpqs)l7R%R)4A#?Q;TiNifM#+m5|onTC6ygG@EFL zH+X$?^Y49wcY44q52C-7;=12T+Vbj=DXEn1*V_mY6bW-C;Y2!=ru>yzY>FL$`DuA? zd|YChv#lzGcSbr8c$S7y=lA&^S}TOMJfmsC_SX=6Cq^{<*;EPJGI>c zHH%H4rbq48F^cT&+VK5dg-cZyia);2?KRuEx3QRd)&d#Yvd^^kN(qCXhM+vZvSn&8 z6&MR*NSB&&x4;O1rW_13>~Bs<+i%O^(t^+>Mg)rHpHJxehQK5U-wJ(LJNbEwhRAQ( zLVN=+L_Q#Ozr?OiGp@SJ#(GO41gJ1D$CVPYuYX9%E#clu$c-;&E`LljoGpDu{L;kb zjR?yWh1DzhJxyHRV*4=$#T9GfgvJT_Z)tv>Bb~zOl+aE*Dj^tE%#YJSaNLtgC`0(< zUn1h&Ic)uiUZ|(+yf-;Vc-072J+|` zhl?xmv6t+b7Lzd6rov-kY(et3F~RwAUQNX(IiqDXEb(t`zL3m+B4#8Ln?J3ON=rH! zrBiYYOi>yaMb{ZM^0Oy->eO{O4`Vr@39%nY{ww+_z77ZCYnPw#HT^|>O8U;~^WXk# zVA>m2^h<;T&|Cd2?{zhU6yPBPdS91mb%>b&0vmvt@LcA>{u5{VCp&0!6d{eiaK;E} za0<*3+AJYpVv0Y?J4tvzIXe>eCA5u=7>@~2WR$7gh9&3Vv@O6-Cw8Wc0;(rh>3+&P zWX^Pt_PMU_`nMmW=O{ShE5)Wzq@e29mJ8R0u1}Ik)aAr9?BD4gJ_$o7W$%a^+Xz*f zc}dDa8mwSXt^Pr$Iq1ct{@@F8p_wsg0xp|5MmtzIlkEfq1|3qvDHY3eQ)6oeLxQue=1yLFf8ug^`4o?Jl6Q0_=Nk%TM@`=hLK645G>pktimia>Z|CIR( z2wwlzT2qg%0UI+j`V<=X>+K}of69FQ?R#!S=+~8U#qogY8a3OVRI9QKP?8eT{sU-K zrv`@7SFfrG_E3Tfh)dbu^(|sU(?t8Lzq(!Zy$2`S(g`m(Zbfms;rPMboEPOr3_3CD zpZYN!%1Ntuh4EzRYB`lqCTGIYd-Gyl?{>v#u9lb=jW=S~C!EG5`TM9~F9|&VS_{g| z5>*{&a2%FD1PfJyoA;&Vy^U@H~AqM6#6|x zG-oxjT%`|OF2;#dHtT{CHaI%El1gE2vR`Ow!UJ3&)_HL;4)hN6UG)!i0e*GKm3_iN zCB%i^v`t8$ep6^k?%}m+5i%;Sl9Pdf6Uf-a0Z{A%{zsd2CaJ8l;0?;c(L~o< zorp5t+kRv36uk|48ROz$0&35K9oiM0ezQntKJz3$b;RQmSyCV<_VY#$HQ>wPiX zoS84~WYlnr&Yxw_H`-g&t@_$^?4uBPFP(z`70HYilXzjSO8cH4FLp>8{0 z?zyk6DCUdoHuIoQrGaE*qC$0h$K?XWz3g4xNuGI>M7-Hk94?YlpBlOZt}M{8pS~e` z=Ei6>VvbE~KTh`YXf(&T@4+dFPQEtjVTLS!<#*nnK7BmcH|DRYi$@UG00bukmIg~A zzyS}Tz!1LYuSEZ~-|p(_%4}z8ZtG&=UVq7BX=gi7=BML z{z{KTnXx^`C3!Jlwp+kO%Mpg+Wf-*no0(pAG~^0DcuXJd>!)BdH#T0%%fAnUi=?2q z%~VI_85GEW^r1EyDX!|U@hzo3f_o^YoZ_JSQ}&Z&srn6JQD3qrlJ|)hJ#Ka7hd3AF zv^1}n3iu)BEYbLB5iDWYOeow779pT(`=ENNdOH;!zYdks=iAH8q&tfB)8fJnQB)tu zLRa_*$8?qGrAiZoaja5XNs;E8MZ?ee zIcmP1Le#ot?VUUpMm}+h1Ilj}pA}k$Dp6c${sCX*ekYV;|BcoHx0dCDSw^+s`!BExsA9eCnhqThBt0 zNe3Tg_K?`VPq2<*E&E}QJXLk-&8EM!{w^3A=w|>p5ENHD2vQ*FmU)HinED#hU#OXD zRF05cgYAzVj9c9h5`YB~qd#Z*{Y%{j&TEMVV1ULiiH7SZ{~fvw|CuYg092VjbQ|Cq zeBq!dU=5+*B*oF=PP}y*R(U^>|42b8AMqrO=9AJO-Z5llYV@Ezzmua~THX`CEIzD$ z{K?f?G`;b;2?sKn$Mm`Yds=IL9p8C-r&_v5Q>n0riZ{%;2+u6pfpo1*{nq*aU_ZYSA34)8=yOud zvsd%pSe=_*#zWokcSBSsQkQjg=JKH;v@J@&nX?S(CC?^CqQ%d6TSH>jep_ zvv+89#GA73CdynU)(UQT>f$P_qF`YF34uW?e6j|{fbb@W*3rZSWaRAN0CfC<42+E( zOn{bNz)gVQppk*KiG!)RgS7#qbD!nsPwB2@-{G;5gn8JwIoR2FxUYG4$k$@xvFhNQJJeMVbOVSOb%*Fx9x3Tkpxq*t? z)gh3s`Cs+x{FBSlIIB9e!1vlk`~&vqi>7kI5N=_D*hiA<_{nrZ;ha_oY|N5|`_ga? z-eO$E_C0l)NRA^D0b&^b&YN7ZeqiWMSvoA;WcXEAeNQK>;hnmizRNg;VUZIKPBzeeQ7=IeioZ#QU z*qPDrDFG8_)96Q6LXbLs;-)xk{1bsd(xA}#y(s?(6OM7Hhu#&e_?mPc$OKg24DK?I zJZNv~(IfP5jomXM_A)wte173_^6BA5!K{=NGEs%jnp!K5_=K(AP_mOG#i9_qI+_&w zM#}>4NYj-u9X_=8Bh6tW9m&Z})&m0#iVI(VeB|LO8qINDdgm{y^D-LM0&#|)B!ObI zpo#NyM(W)QhcXwE8S7O>Q^rUB1LDzr#EXmUBvXh=${G27{I9rKrlwPkSC^*iicXCK zNCa{^5oY`^ELSY=2(+e`ikyTX-P61EsNJw-7~a02#dzUI+Ow5=Sg&(Qhq+`~><`0e z51-{>4;nN@)krmRLT1Lh4E){XAsFXIZqVysPyRfs^leXYXJF& z39#?zQ=GqhO`2~>rY|JX`M=3>{B9uH?{1dhl`99C6~gw@m4j3rf4OqRKU1(*p4x9H z_8UN6x?xX)eC%eTX(!-gBrYP=@^)Ef@1R*8d!Z9cQ@PWOOXS$D!&;jbJb107 zY&)l)o{Lnqv996O#<@F1u)6zr@m;m}7o?dkF^pz>bk`_x4|YAhI7YLOCdr6|*Mf~3 z-3KFn(f*vD>bZDS9ayy_ney>7jTG0Bp$mOBoZob(k?s0m6;~}7`#c_{r2kgQtCO%o zo-F1 z3DUB_SUWq!B85pAwY5>IMZeVLYzjL<{?3?eNPJl6HJ!~$T3+1#B!K!j)1qwB2>faL zC3lG_i#PoDgq6 z+!FUZ?e7WfCgijdU8G!gP$D@q(12lr#6$>VnV*XBqu{Qy(Cj!Ve6TOWpQ^7-gvx_w)HT{NQH==Agx zibzTmu(j?0vGv!h_<9zIuiLNoRdhmjC}=1c+B>h{YWGyce_K0Xj~gZhl*E6|e?-Q{ zRu%BoN9plfNh2m|GTx= zny;iryc#zw@3gKT#V~v2F*QLzq~l_W(_c8IOW`+kiCwbY7{WUn`?MZ?_sf5UU%z3%7k^ zfh%lM8(Yw15M9U4X{sT@!=i~9W2j9RgF(Zp$H3~m(LiouNnWBvbDj{#&i@ApY7;sq z{>jHWEbVAY{M0NGaeQ3LSJAi1D1ySK7^v326yuu>y)&qr2yiE+CuD zl0>TNxXY?6p@^x1_Ch;sa*%+@aj$ZO=0J*q`;*~!PqYr6khBNyPX~6_D*}y{zo0w% zoH;0#t$NR^z#F?g_PN^jjKBte(hck#i%hf0X!r~son*TkiMqr~`qbpFf&8C$gTNab zSC0*S03uJD>I;vrlH{fj6>hO=Dh`}x>*6@iJmlZl-RyaS ziTJ=^Yppb#FO$7(Gg!n_epkS=GYeigv3P?~YilZQFi1(pjibtDsRpCfBijp|VAdAH z>EWlm-L%zlW#b;*IJb1wJ57!yxNU0ivyAyb&Y(Zt7wom*?*ngJineiEn_ujCmh(#| z80^bAL~(~oN3V8l(5HTvw(&xvYO}Q3<6-HtgJ1NSZDU|~`gCN{w)=j~IMEJO=j{$L zm?z9b3Hj-0y9@)9$Kk{m$}4jZY^HNZ-O9ML3XDf^DBIDq*5{CT#u~l!vvd+7LSaUx zRCD)b)$>q>y^Nip+4g2J9t7vXq^FbkyEgCk#Mf~UI_bo)14X1vG48D8;7(%Y zqja%eCWBDi2;UK%^x;UsP@DS(A2oEwC*}^FBq`jTyeGRdY`Jl{b{Oy23t+m;>fE`f zY~*HX@`UU%kXiw-e)@T0)yvZP8LN`ubVX;@#2m? zmO-|b@9uxUAYvb?V+M%Czel@KI#`gJk;~INb#jNPCKMJsCmJd%yz*Ow~ z+MQ;@ddnEKc~IbhYh`Qz-Hj3y)k#HfLZ?OXoxJavZsz`s%#c}xgtPWDBpW)*7Q4`c zL0CSO{o*zc%q@uh5+2uyUw@V#KYln`zyzwOGb4CU- zf{|~<8LHZFe4c=*0y}?&8(fZPevf${xnRT|#xR7ne!7iPomE7X$?2%=O?EKG>UqPn zB~dl1>TL;*{4p$Op3R^6R>*9Z-%_DJQJEYLsICK14WfR46SNW(^dArYCelIt(^dd` zmu1G*51LP#af%_$yzKFC=+M~>r2pF={|(Y}-tOMWhC@Tc=xzM`Hg_*59(DF5i>%ju zRaTGnObq>AkNx_OG~uxKGN-Y&pO88s2nez65qn0ll7HA4u!_L?@m#wf_=v6WjRNDc8~gxkv1UTBvs|RM1rGg}N0NT}OQe&&#V0r@n!723vDNnm zh(>WqGU@|IK4UaW8`m%^5XuZv{g@_2R2|?+1(d2>LdT{_XHx82D7T+sYiCg5%F^8z zuxQB}ugDh5Li_e5*_HIZ9rfwt1lNN5LYYwQYm@pK%((u~ZM3|6xB4Wtlr&ot&vo*q zw;v9-Wfj6Kg(6~++QNRaP0iS+tHWwnNPq7Wl$YrGs<<(Wms#7(e4g?B8n;E}oaWqt z!s4^-tQz{D<6br&Uy~ zrMP}i>Wg9-){7e_ze4My=$aS!s~XhXTtA%)Wq_{!=%k|aT>mwcu<=el{YJTnXx|G{-;R(J zUS-(3LwKCw{sVf);5!GetiGWu9r0;>A_kCN0l;|iE1VYwaGvf8=V4I))D{G(nknA! z<(1X0Q(VZ{NXo*}YQl0%fN%b@+4ROdiR+2)fXA-}P+NZ{w=NS}SN)-v0L~4dHlTb8 zNoHNq$2qTD^nb%8{|U3-!+-8r4{fmtCf^R1O|nNOdt|q1?UxkaI`&XbT)O+dNEsG~ z6=AbeCaYcmO#Fr@JF?PXQfPQZrTb@w5sSTW)0Qm;XvFB@(gB!Rg+rBhrs&;YB=uPs z*myY~@zFl};fdEqP-!?Sc{i$WhY(A)(CA=D$XSnWCk;$YpPG=3Teo#a$h9*cB^q(u zHF}#y`r-C;({6y>>#nt2P0>^9KwHOEZt=VwuJ)cFXVMxggp1df_wY9i^6kCaNYcMc zui};ojHVeJV19?UB{{>a9{?jZ)4fNMqn`Sjo*QLB)*K}sq`jC>X`h8l*y-hr*<(w&s(1(j&bNvy)z z7>%K*jSRTtG9)U5yi1u1tRvH7)BE}-{gx3q2;){O$@A%+Wb@RA(>)+JbtfzRScdd? zW^@=)VxN9;iGo|d+qWDe6=Ss{)~7)w3f`k%5Vz5G1}O&m*%${=&;6{O%GZxa5~BEX z{M}-yGc|AhU~u{X1t&0Di4(pun-^yFIGUZLv0`u|x}zScfsqd07RK_;c5MTFtyZH# zgs`3c^Agz#xIF(1ws%EamiQqh#phOYk)c7k@lt&qvfcX#{dyM2BE_Vnt}NlHOVQ{E zr|=Ym)N`zg-fUAp6Hb(1^4}2qZ-#f>z|%{1E8scnarnAy$B~RImQBDI`QtSerP?Xx ze19m(*?}@fEBL~GBA;D&4Ts2z9IDYugz!mnF{=;^pg_7rI50crx>{Ydh-y%nzG&gs2K&$6Cj|nOKNXj{u{%m`Zr#&lx z>}@~Ch7j#J>aJR#T&K!+;^FZuZv+q9k=fg`zH;Oy#pQGO?y=$seR@4p5-*I*#KK;F zGqy_=Os0kZ$ZJ<==m|Po_`G^6t@4c^QoH;KDPeN15S4nleCXchuk%zxKjzdeAwuA#;^zHG#93n_s%|-Z__VQ@J3(x_6iyUH zS=r-Q<`4BVV73@GhK-_8bn97MEHlcfYa?LCk@p@NOVsfiF2=2M7-7=(#O@YuZ%;i{ zms*vnTr(+HJ$+hM)**gW(3CP!wPqL;-m)w646AS{#DDZn^ZGM_6pI=nDt&glo{jHp z``Q!k-rH|7&pRnUQf=Wz7YjzoQwP?WI#OY;WfmDV6?*%_3fy)JBy#`SvcCrx3o4@Y zYboV}GHh7lqMB2yZYPa&9?=tuHDGAs?_Df4GZ>Jd&Le+h&a}?lzV6zW%~uA?F7NVb zSz8%er`zpYCu&1KRyaNrrCH4K+w;5<2802)UI0(+0B*106~9*(z*C8ze)AQ-m;3|f z5WN{fUZMH#ezWh(8}R!7C%=~nObDrW0Dd;W?*&x3#DtZFMQt7IKuVILKiR!pY#gjS zoZM`z06+umUdSQvKRe)O|G#p3JNohneBee*qo?};J#tj-lm)(uYz}>A;gd${h0KjK8Da} zFB=niT}djbevghHZ{<$v!|cv)1R7?Ic6&-tjk*ecS*o^NM-RS;1*Xc%jY`@`Kj?lu zmfZqh6;Ar?^rCl}>q`>6RS7!-I($JokBEdFY zXiw|Dx>s9ND;aE2WZy+rOkb%d0*|sG0siEG(zU8;eXu?2R&P*Ul2ruvur{~A95=ph zd;LRb1Lu$7kDqAKwfR!)2-rccE$Q!m`lWBdzPbO`++HQNPo@1n$6t0+bpqs~2j7U3 ze2~ACg96$YE)&hE;8f;7#(&A}ymx{&rkE4QD)5a0qQ(8#|bk?sWe9NW$>_8vU+@xA=@mTs{iN!c#?Ye8`mdUTAb? zAZ`+I7oK|6D@tq5@F6ST!V_;!EPmb_YWBq(cC|$=p@csauM|BMH9_I^%RD=z4#td# zS(t?{_I$e^C>>Jsp=W0k?%^n;vQpR4u4;m*osT^AiNp4L6{xM@XkN{ZpovS;Su!rU zOytpdvrTt$3DgyF?qa?nsfiTAl9US{dxBx;Nb-o9hnPV64D9r(Ws!nqyfJJu%Htta z#Q$OME5NGS*0pH_K~hS(n?-lGv>+%Y9n#$$5|Yv=ozfkmbP7@mNF%9$APAxe{Bx}Z zdt>ag@A;qe-*fJLet8h)nq$s6)?$pWzxQ?Y)0>{V5h-o8K4+O+)UBzAfp(bb8OM8= z9Jn~=V0q>$YM>-E{3Z2kkJjh@+x+g$%pUy(VN9Q|K-~1RJAmz`0=3^10G#_;sJwyw zLBN37hyqeC2^hKC7oIsX&J_t4pxp$Z!@UTtqT-M$n>s7n8C#Ld8Cu(U8af+UdO8E3 z-i81Gmx7ry>ji`LRe-_T(AEX$`g8>V#H}n1P3)||TwqXn!fM(+JFQD z`Og=fiy0s=3oy-tI5?nU2Jq$25C5a*{*QXet3DuXk!MkL#PAsm_sZ0~xp8{jl$wDs zOYHaXW1~!%Cj7bE@wq2Dy3RyxvI7E^u4&Ehr0~Bh=Ds;? zOb)9EgAXUm+d~lPL%zE9wT8{p2p2^LcfjNz(!b8AXv%8B;SozsD~iUQZKTa2uUW~e zY|HcP8C)h%u$ulGpAz9mBM0Cq!un&+0oe5b0|r2?5(sDT=ZokFfpBVgfpAJP^0IfO z6{VFZ$fZ32TzCKr{$d@F8-n?6AquS*_KAY4S*kx&g7=n_YEBlo$Rd0flKV~8`_dvnL2p_+~~k<$So|vqk+{1z|))A zS$i1T05<|s@;^Qfj7D#2Wd@A2wsUeaHD`e=Uf?Q2Cqn=;&cqUYD-&qs31D^ro?{6- z5qPqhow=b2Fv!->iX6BcIyZ7dPvDdtbZ*wBwswx5zziz(n<~H1^|~90OzcMEeQU}W&)4}kQ)P> z)wblWhUOl?hXRydf$s@^=EbbUE?q%x%3@<^X$`%Gm0Vs)Rppk3xUvQXxduQ500iP( zAjtk;%ziKiKhTB&2JCmX06vgQU17jLawiu^pAR|kH1J5}^S`X5syex$EAR*i6#(#8 z01N)VoH_vX36Kn&&j}c8Z0~e=wyc+pAu!z)0C#{eQ~nUY;^@9MbfQC@~`O%wRKvMS3Ye4CkXyb_D(Gp^qp9UWnUNzQr~&%16Uuu&v*U`l) zodC}rX6~%DyzsEG&^1QzOHtPhgYmUE3!aGN=m-Z36y%kS*Vj~zCYTiS@V@Ryro_}_ z+*+`SbvQv29aJ_z zxn?Sh$p+hoC>nEABfg_8;d^&yEE&!8TxP>^0TmCRU$Z;>V4H~y0noA_)-2{M#!&i8 zCKpha$?67Pb!Om22PsK%bFz0d2C9=Bt$&pDusxT;g|vx;m~S_-ljF{23E$Qsh>SU* z-UkI#gC7M{PCNw#01Z&T8u!e1)3PMa!w8SghqSi<3UdPUirQK-|MB%Ic{AIu5UQvDQ!gVY#F2G~N; za(ppam|o*0UPXS&iW@KAz+g9J!|rqNJsT7G!7H}Avm$q9pl0G(BTz$G3az6o0(3gd zxnD|Q%bEXjJS@+S0lAh=sB7wS=^jug{G)6;?*&E0!BzLLF$6RiKwJ;Figu2W*5M1t z{i`^5f1HLS`N3Ml&Cbz^T^b|_wGD;-7yva2*)Ig#1=RDODIqZQ+#ga7@K0sAz@iSQ zt_J~a@sNMe8aSZb{sKSfKXlrEQP4SQR(E5jyvE?8%!e>z7eU4ZoBey(hszil^{BY& za<}?s1!`W(k<(%;e+v(Oy%4v;;6o4lc7{OGGMlV!JQQ!X*Uy}4VS$}J2%g)%N}-_- z|C!p$*#!KV4=94J*z-^8{@H>~)3zv@1GMI3w^-2()Tn$ zY0D0tP7OlL5V+|lvOD7I*0fJhgumFtjv`92Rkj2@ve-kDmgjFxMIau>%mOdnU7+V` z3HSzd@EoviyP@m$8c7bg?qsXMz~4Qp9_goj5AwLQZvRDfCqVlgbnTM-!@3iQ9=<3$ z;o{%}7AN4=0L7UXWhei}sr{Ym&2ytllB$UP%wCB3nfAfseZIFC`t!r$8|-C0&T-U9 z?xZML>1l~KZyp$V!xasb9&01G^3UJ<^tGmSAO6nmv8N5o2$Z8o3DcBUV4}voY4rx( zJl2`r`HN_suI1>_Sca(FzLvJr(hULAh#Y`jj(RVE>ipi`&WNQP>!`obOca zJLMnXw5ZKbreJID2n2D)Be_Jzdt+O8+26;gORsm+k-Ph3WkS;8=4%fBtzw#Xp-$(;#0IX^7<1I9=gZNy2Hu=vxLv$VtuyOk`YKB4N}TaCWqGJ zpbAM+x%uwSt_@L>2?nKe2?TL1Lsjq3RTuGjF3fouF9M`CJ-$bDC+2Trx;Xu+m;buz z;|TfOxWm-McGI`q{4(2D2nvB_XLwE1B1CfWBGdPTOQ(O8lqdmL|c?-#EW@3!n+&%!vSqx+j?Yn z-6K~gQ_l5NAF$V(q5Hia*zXzV`yH_jyx+w~kWiIgxnTah-(CNi{SIy;2O^#T#_3Nx z8LEr8z*S}!yiPd8e>vuIjTumi4FoPA#C<<(_J7yB{%)t&4Jke@D_48wE!U0C5bB9r z_EuFG#gQBxx8Att^iIYih5mjFCE=`c9Qlx47(-4?dnu!1bEHP2*uA}{N0Ol(Al<=2 zJ-?nS@+;T)*`f(1;^wIEJp5;@8hO0T@_}pP z3iRr2DUv=C&-WbXBrFUCN3Iv6qO7sRu_-pFJho{7-h zKzg1(XN2h6qp01wfg$qHZXi>5Hs!A=;w503~@2v4KSBgD?4O(2YzE>|uQ9KE?s|@i|`Lk0v@KF4=Wy?`n%*z$RV6 zLDK?al0b|E=#{WHy+}7BF(^L?gtQTg zX$gR#{$Y~>;Y+aEzhHR#-|;s8QM7YBPt~^XOw(#@Sg-yAnuUvO&eM+RV4CkmpJmmi zL+Z$#6GBNbT>9T%F+4!B0oh(BgnNIh&1gm`HRIiVG%3EJ(-+GoDE8f_RaOl3Z1R1A zujvqIFq7HVV{O{#B~m99CFeU2C~Pz`^*RCOww1R!m5sBtUJE<|9d%}u*b@)Xp_>{9 z1jV0+!W55+O0ss2GBsJ7Fe`(yN-SlDkGXF2bYMN*D2h-{vn(F3tqVrV>;0PqE2p!?-VeFEMf zrkB)-y7V99fH+shO-!KC2yuxE&2be6_m5XKG*thHQ&2!^?SPy(!5^nD;uMz|Er19F zP_G2y1dy-5ZrLtl3gHL8Y8m8$v zY@}wdGS-XtGv1}?S7#+_Rf6gSFu30ErFdszRqbv<{qx@GQ7jaS7wr}DCzxKBGvU7} z_6djqECg^g^Z_U!*dOigo^Y-4|I3Vn)Ub&cI-yYQK!r-{Rn z%MOF2H^`-~w0YKxoph~mFOlF8kF+pFPdK~m$x-${Ua%Z!}8PFpAs@Z1}mX;>Kq_$04ARYY!`wfmApXc zlAi;_1)yAOgZ^74@pm$!h;1X!5(!?m^F3qA8DWlnT90bAZ~lUX(hYBn`eX|qmV(IS z_a>qJxjR{*tp=u#6*R&+)cn1$ghi+|1J@65xe|uWDcjr9pZx5 z*BhoXCubc>eA8Ofqd74sPsmu;k$HBE_`By`Hq+oz&7<`Q3%v@wvSubSttN;kkc;S- zHT&Sr98@nJCvy`X1r@)GIl=ghXY za_X$U?6(*bUbKOh9KulK{#7Ft(+EpHY&ajwPMxP$KBGG62_ zkh<+MDC3m{)UG5z>sMj{z3zT)2P3B6(8`FW;CRQ6{JhZ3Mfb8Dj0UKAqaU~L1=ubQ z8n~$h?C*g$F8jG-cNGT{oKgp8{lShK*kNP;Q^)^t1;jisHG%e-oaY%h!2}oJq88}x z1s?zr9?0Q;%N+i$Ub%HG*2!Z2*^1sxArK|Vl5?x0kcPFNLU=D?>TbspL!t1U64$h$ za<3b~=v^SP{Tq3Fc$=C%$u=Y<)gF5TSYs>qCJ=>gVca6?$+({H`y#Vg3-9i2#|n!_ z_8ryDE~)pOI1)xNr7&3+0{4-F*PI1y9Nw{@-S|lUrk|X|n1SWhmcDY|qazB#bgoUr z9{nvHqL$76;h|D4v3pgXW*^=9(pxU;SJ7YPUT1$f z{YZZ{I>vvxJ}yNp)}zzCx4x>Y?mht@JZ99?Yu-FoM4zyOKoQJ1`;yy%;vADR2u_T) zaj@PLimzMBZ@|0gxtqNeV3$hc6l=XQsV$$^u~wXAK9@(=lC8pDhjj=43$?CHjLDaF z%P`jzSK+&Q60Q%zlPx{vb{BK7ZmzXNF@@v8u=djR~~Pe z6mX7)BQHH~Sd+{nXe@ApUBXB}qadl)V4w-NUcGipP1gAZZE3x@%e-gly(rQCmT_?` zY@Jn1)lK&90Y^Malm%}^7g6IaihEt;YF2htC83cj9TU>`o{)dfChcyE$*J;1rA<9p zv1CgjVL5nPTuriiwKcgMIOd>dqPW0nF1p^FQcjGa^3w)`w0%D_eCtze{Q|!$ z?nY;J4ouXti3Nt{uv@wP*ORoHsZIUvx@c(kR@QJCG_Uf=>q!|emOV})FuOs8F6{B% z#%e<2XiTVGQmmXr_2Aa`Sixs0sg_o~?S(}ad33W+zS5P0LYfZEl>|g$?($QrOKtY) z!4GV!dioeqp!)YYnT=*48r<8+uPv-7`eMWV*jqbdB8M+^-#zlP(ir*Gd4!J-(`5r3 z(c5r2c0hMo%NHH?G*|8?+r_KeBt=1%y0Y2 z)G3PE(rbIrj^z~@C6AH5+rAmua^pnyCi;T8nQyg@_=w=jXTi@1#_xAJG+@-SA{hH$ zxevbi@Bo3J=2eA!SjB#PYJJU`A;wq;%(^Pk%8kS)gxO7xtJ14rNOwjsR3xnXQCmJr zeiLxW?^B}9=ROJ7YY8zT;TX$e(%4SZYM=RrIZW6PdGkgLY&~6~`bK@YjZTZjYpRV% zwH(c_y9NGP6QngQ7#Qj<3{OAcxUI}T44^1O#+1b>dmxNF>e4d2Z{`cOr@;K6$54Cf z3t&$zK;<)nTqexV+4i64yp%6W0a4KyBrPm$4FQRKUh{OG4+dT^vjebGAoOC;PH=Wv zkTfI|hbHo0z6K1J{%3>_C=LS~WsoE>0GI-Rt^pPo2RGRCx_tPbHQB#2(b9dLK0X(8 ze`+ErexSOLu*X^*bu(H3z_f%v;;5=J0|V?GIB^2j910oT0xB#;R@{ zeW^1``qhHnWGVfd^QJ`;dE%EIj40VsZKOHFl6PBEnfNS^2ZXqjZ#xW0hE&Po9Wbl= zyAF@Tm^>Ftog18*>B^kIxhEbJ`4#;^ye5}55$09=H`>I>cY=k2iCA^xxNHgU`Qcl3 zo9BWpE4NQDyNZriuo|=cr ziu_A7{}21yRAw$d-QyJI9-~g(b?^;$O3^gfdNgq`*r$=!O$ABpcxL)YzMl9a4de=& z;T1hm#PexOl&Mo&c}F(+0ZGX?D(T_QI;WO|z~;ktk3J<=pZUY8hJeMaui5T0_(Ym1 zyUM~P#M@i^v&eE^j8BouJMwhz>u`j1_i~1mnn}oZ+@VfgS`}G!VUCuZ&=YbeElLbz zP#qn`Yu;&p;rX_9YLHY>X34FJz2rG#->VqgY&}1C7p|4EaA^(w7v=Q%&qUolHl1ov z(NA9Vf6**GY}jT?r(o#it557g*z06D!DWn1Z9*Q*1dD;QKEOtM2DQ@~06Q%cDhJ>Y ze<28!zGRt6C|#Ifs5qEvE_RxRCO}Q0qNNQ`#A$M=#rKa>=bd2y))5dP1OXt5;MM~U zfan{%e*w=4a>xm^ih=$`kNG?MDve-3ApsqRr2?KIVizNzuUwHZgyc$Q34>I~K3hN; z2WhNKYi=kl5$UNfF@b>YV*`9f0p}o2kdL7T*30dZ#kH{<-vcW(&Zlw0_w$cYgO3o$*~sH>IB_w=o> zO3=QBY)ZX9LU7u9f2y1E@W83Us@8YtwJsc!BL7l#Vj_#ggUL5Fv62neIG^U{4!e%R zMMqr@;ydHsM1+mRZq3@vhj*AdBt@dbpFD2W0f44wKAd`Zmu*&j!FxF~M8mX7cAS>^ zPHj*?9ZhcS+VlQeSEO5OSU4e$#_$M>2s}*Wgm4?qg=F>pnr6E$G_&UI*9;B9YD7kh zzUNMpRE}0rX)H*&+H8wYwO3Qts}nD9lgwtjF|x0)9IUR+^evvP`cGap&N}1F#%N}~ ze*Hso%~(#|i@k?Qq(m_!)_I1!O`%SllgUXLR6c=uiUIGkN1M&>B_ik2VSU8I^lFj5 zsaTCLRisM1U*o3HVoY@5I|U-iMQx+Zg#{)~eRRV5^^XS)XCpb?#-%v8 zQH&7c@i3<{=wy!tDVC2mNp#KwNR^;~vR_5ZB_hPja)l_^s6|eZlLq1S$B{$$E<%~n z1S^m&G=2m`i2QMXHy~R+572%8lD!l7>#l^Db0VmCN|{JHMdc29Y=~^;YdF$DT|9^T zZM10Ub+RUUN41XqGWqZXbU*=*kL!mdE`NOT+4Z2KsPD*))Ay8E&8ve?-b#IUQw>=2 zuI)#^>ZpF?ii|8Sn}l|}7)bl*_QO+3G6PfZd+W3{UpQh@RA2Kt+&+w_aQ~9%@$HC( z_JNru$gP0ao%0svopMpb=)L<@I|RNr?-~z8QU^NRt}+BK1;IrG_p#u>U3;Wg3OZ0Zo&yB4Bvs^hS*ZAttJuqpxvFQ zZC2@+iT960*Q=Np1STjS&IUiDv>Q2E>EVBm5GK^wym{Nx#y^$%z#8`WD7i90XY*vt z?vtAZI=2Z`Y2)o|_)#SZ!r3F2yPCOQi{w3yDy}tQWqCK;-{u;rr#0dudVqGcal$$t z>xUf2NHXE88xoXS$#+Hcz5Z8jsrQAm(gAugaD10NYCei)zYTfe%9w|gYha&J1t??ElfnyH-VTRI@pI;A#(f(u;)HN5(f;AQuhfrMof(70gfX#CR1iceb!Efc_#D3lz z43C3+)5XP+MO^_R;n@KT4QTTKfZ-v{Wjr80067PLav$FqIx27xP}$rYypA=Nt^H8V|U6XoT-|PYIQEWH^%QqY9kz zv(0M*&k2k-{E4HMh@*rT&vfp6Fj-CB5KZ+%Lq*|)AyO}-SmINd2)a>LVbbxH*z=*8 zoRS$C0qQ%EXJp8xk3yP=Dx12F(XkE>CcfV2WoBw1P&-}pIxLc_uohHd+c_GQC8gEc zRU_d{I@`G`Jgqc(ovZhQD4v{G9I?M7hHxXI$Y@RC(9{4%hot#T!=pvYK-L!r7W6?) z?ShtGtz&GM~^VTaeFil**At+$vqOl7O4iwNy8qfx#4r2;@k;6Cv|2x7s z!&t(Y0pC_IhQOCI@VXt0E%3i9%nFP(%zfZBC*W1^85bB6;B|4}dKO^36Yx9uPJiCP z8FEMPE0!=ekP%kEc_-k`E|AfN!2Jw?Gc3S$3c%IBf4(K~6!7eLjd5cK;&7ZS;V14zl^&NYymbfkIp4) z6yd3-Z0<^U1<^37SRsL^-OhWT7e7Q8e>>nu>vrv@Eexqg@oFbXP|rcxKczKKQ(fsq zWMkrXk5lw6!ou=Ul)qcr_a($sSLT@@W)@tShqsrUI~UiXyw#-9;O)%hKe)pHo>^}i3+Q30u7X~Ue{ zxr3H}fWfSUEQ{kZot&I($F950^u&u?aH>h;t$u2rfEp@0q&E4_Ap5h*`RqHKVQG00 zsq-(MZ&pmdq%QeY^8C2ukuLw`F2H7k-nVz*=@aR35xm{r`D}d+Mn<7=p;`v38{=fn z^I>*@)vFHp*N+b#^*A@)UwBG&9S&q;7J)hN8vV7(P?V%dZG>??r|q)MG=75#S)V%X z*Dxbz{;T*pFV%|BHVEL?bE@gjFoBo|5;QIX2gF6J;4ppOo+1wykv3p@m>(C0bN$Su z0SaipWZeNNCw$O#aHsYbkNn5`1H)v1jx0lH>yRf9@P_n%*;;#Cs^Gu41Par4kr@XsSbjc$#0A1l z0rARyq=5e4@E-qB(Z-#A*CFJ=OExt}dE028 z@G%6x7Jj9fY#$Cb-t#sd&XL{g(cz3X5ks(O_ir*GmUio%vOP#-5K`UXnsg^CYPOM# zON^1$()aB?9>_!3{E*D60kV4rE6c$-G^>?vVrh7kPC^{6qH7LO%0CNvpgu!QY3POS z%M`-L*Q;Uq-C30|%BbYRJY=(4}=^IY^S=SH$GOSYz>roT1qb`Vcb4k+jjY2y1}9ONG809 zCc+fyqgAU1^2n!#ifv}4_-AcJ_X^E@5caNLu`i9E@Ie^kJXWl~di9v7zbgv9*jIN? zwFEmqdst32e`lfmtKRsYYS%^>&t5nT=4~7YC?kcabFQM=;D^Pw@)qn z4E0vUO;tEP5g;bqC!Qy>pAqrmfa9t|v(Aq2&i@>9_Ij!e{|yVmsOTO4cL8_9UbHRC zJfc30eNLMLV%bQh)#46!P9iwG{;qrV$9OUE2J}*rj%nt>sPh@5$@H%8ZtrV*s#EiyYAHOHk10yeBd#8GIln$My zkK>3OYsiO#Q!YV6acY^K`iD2O z+*VPTq@`p_8_fM+BM`M8y~u7qJ6gYHo+m5ss^=0*bU+)k3pE?h!~mJb3zch}fLyx) zm1_Y1>;B~r4GfT_bV;)PHUH}cek~g5U-Q2L`Q;zTUpWB;TR>8AoRhyo4*%7U`#X1d zy!z&_r|gbPI@LD;wh2|~aBhJftC`ao7>lAscq|fL)hn4wH!TvlYt%;*j0?#%E9TYQ zw-|-@<>XXFP#0uwN7C7JVk)7>-IAPou&AfZQ%5myk6#Soo{sNeZVywj80lM{;0d|? zcv3DIa_aUxwdk8fJF23VdW3$`oxQLzYW-9jj^(v2nkatQFNv!v7-CWTZx3RO*Ai{Z za%)60$}V*8Rc_^IIi} zWQ#H)Q+b^O+THB_8**ux36`gXb5l;<0Ru_%(c3i~h^E0@YilQ3n05DDTiGfx(Yr6) zVIn~G;QeZp{wX(3rg6J6LGu*PNhSEdml#vYFMbOCMQ#L)Lj_g9OHe=`D8N6g?Iyzq9P!x1S-u9y)@)`=S)qCHR$Zrc!Hz zf#Bo)0g`w67E`%Tl2^qH#&{@BM`|1Kr=4^CUN2Opz?IrrSuxX4J7$}Hq|sho<5=HY zD3SlRA8Sc9gYb4;_s)0I*U2vizq6ta(lBx(92vx2cM%ppqaq{hv)&9;M<`fPq*RJ} z*!)VzY0E@I)n@eZ?PJSMp3a9YLLmiKsI=&dk5UZEeS4^rBMk4wMVrN=Jm49MOlJ`} zRC}%Z`Y!$RpuItQFZEEHDcUgm$q#WuB25Erv9{Vh`p%}4x~IACe&Z)_ghi)~9c<#r z9{F{V^U@q$mLuS>+yAu<&Gk=o(f&{M6aItV<3I8fns--*zjl>}Xfz>feU0h%v%os) z!mpH?T?RS5VKicF92q3urq}U(et)(mj(R}cNa#BpY%4Jydjevzt8Gr%b3=SI<&kC9K5rUA`m(r z%C`^0K=xODLdZkx_QEFB>z*$~N*g63W}nXCHirlJ!U|D2P=v7s&KiG%lP;CMJIQ!Q zN~a++Krr4y_#H3xftPiRD|Zq~(cLFauc%6#CxT8moam-3MI@aM%e%wV*44e=dmSq5 zx0?pdM@2jq3X9^u`~9gXWmI;%nQDNe;x?s;ipqe0Ts;GjM+AK47O3Cc2>8ueP<@Jt zwi~T`1uwr$!f$tzj^OUd&znN-l5)L-vVnsS1=WC7c3*BrKliTTajyL^LLA}&0EtDQ zEPx-#D4y$8pi_sPp9{pztquCuJ?ZaMYDr$eYU0qrA#QYs%E0S)?umCEi!Y(4ic#b9 z$8nmyf3Xx)VWb;A`kh+Gux1epOPrX*cDM1_(R^V*bAen>Cdu;`(Z%8-jS1TfM6aXA z;7Q%5{eDszOZyVs`=n`(0sHW*seZpSWR zeM`jRfW+fc|xw4 z6< z)N)}aQ$G)v7j=!hVj_MX5-n-H$t|9H2Ig-ccOyDqT{ov1yYfBkeR-tc66iCp?@15G zG)smQ2xR>cd47!R``DS-p~7b~86=H@Jq}c3T98%x=xn5H^HS3rqmi7f&*q5k48}xu z2opy=in(c3ytPrQ^a>;y%pHvuE!%J(*}RV+QsaET}=2_{{9aH;Ig;ar67#Z zK-5c64uV}|X-qC|Y-nO?1N;KUBf4ekWNPSWYypJAoSZG4UBJabPLTQ@0AuL_?S@?p zBmx*vK!*nJKXVswbpa5>1v>K}rP<(m0-(l#lZ&4lj5!8~0Pq>;;g7`S|3UNqJE2mn z4ztW!a2Wl~V2UMC zwMn@*7dn^YNB@)%a9a1f|Iiqilrh=9LMiU6#%EFlnLAUvzNBjksv z3kWF?fz{Lm`V;KNBL+av0zbfK1J2I^Kfz}&S;ZH=HQA1b_>z~cX!XNTUWuE^#Jr?Y zX3f+A{VLcP6m9Uyp)@vnmO>cPMAgyn>%g<0ACs6r;Brndq z0`o(EKiIVnD7>WpFM$`L{Rv)pQ2~yIc7ag_fhyz$af1cLRWw!rb+EJ9sk6-4wKE%v zR@hl%1)viCfu;pc-dywsGXVU{oDd0v#(Z%jUT=CIHkRtUGN{;hiOzU^+e9dfo|&Z_PTfiY=!>TVbrIyGLuvCv`O8~(*m+9Cb^NWx64Qc=?z#P&}=-dAnP%a zA#bqv6PlNsNm6g%cUvKP*NYeInykb2jPQEMk!8q1YGLsnS7C8|0sMEnP+<*kSA=w{ zuVQ*IT)nKRE>Bj&;GZfT!H-F}wgHvbFh!BM0Ho1x0+BxfE5cr`4jTMs{%E(paU{Qu zbYK1Cq54A5WYT3Bap5_a_bp^37b%_i`OjmEy3g0|gJjqD+FXK-w% zc1-i|=R(u`&6Lq&#A+Fr>s0scLX1KFyKgec7>GNpD^>66#p(zap@W87ef(a1dJ^=! zU&fZa;H#lpGX5He9CCr58oFKX>6Q%QP;%qb($9uMm_;PSZcjhl6}}E zl4kUCfyqJqVF}`<@caC$JVw)lNcVUm>-E_i8ISc39Tuc$GrHE$<7!!568+WgD}V|r zjj|toN}qbwW$Yq)SGMXr{-z4Z2uY}%5C!ZEx^p|@m*QjJOA;v#{21r1x)(bN#A zJ0@2GAP+4dkOCLAD9C8Y>V^RBqoc_MqA4mGmZY7HorxXL`u|6n;yEuBJlYMYCvmyh z_z!^r+4x-G7G`j7$a!Y$G62B8dwzeno!cBZ10zQ4H=P~?ioGFOdD(wWBKGS%S5tN~ z)@PcK{Xs{YJ+EY|8stxI)N%J{Vh){!SNuDUgwXd}#XfxLyEW=)x6@Z5-e}8;&zNY5 zHZ(?>;KhhtlhpFDq4SeUjV#rZxg`un!p z<|7B?GT3#g=n|HfMW?Xxa=UGFy%tmPr^4rULoXrzpM(A1-_j`{zWehKFN(l!TD`j0RDjn(l0)`p72R|nsx-H>BAW_>>*;jY~w52DLl>nyfz(WN^#umze!6ULUhXia9#%ip;qH-u6c&| zHjVfs0RI+&8sL$#s~-5dTX;Mpf}r-5Wqr=Ltq+)i5=-u(h+cGY8nPe_(dKibD$i zBfHpKk{&-+i(H5qoEzr@FWS*Ax+Nf<3y^>ZYzq*O-{Rxs=LT1daPeF^{7;zT-<4E9 z|LT6U_QoI0EH=04uL{NwdMXV z4i9DJ5@k@l70FoG_AZV-ys1s+E6Lk+y0Wu0xa9U8)%bKc=I6ytTz64hgKwTKoYrJ+ zzRg%nq1r02a>HYs87vbd&U-K`<(hrIeoJ$;X4S=OQalcER?l)d5nZzBdr%U8qL;P5whE48&!i87r&RN; zJjOTTGAQJylv(vUps1E`v^SIXM-OhDOz)Jcu_D(fpN^nR+wY`&(_FKesnb%JU1g@Z z-j~7Zu6#88I3tvKKx?09wJ$!BC@{&hvqcr#a_XA4Or*dj?Ki6a`pSS85-@p36Q>~7 z-Z7cO)o7QKy}_oD2RegDm+xEu7%=ViB2-A(XKV1ob!Lf1N3?uYAyP*}dzS=U6PwIc<&g_zAF& zvgp;N9+cegiccbA%pq=mGDmlOOQ|wOdt*DQ(_%S3ix%xcY$g1M`=<0)x@6oJb(*j3 za?aA#`-TZWkIzf;6)*C?;x)m8-GX^Now}u@%m*u+jeYxQY*;;dvsS%u9btg2fU*l~ zb~B})QcwK;Eb1);ofg(CpWgcTXVh8yyrWE#MT4I#+=+bcjAOkro%^ibUcG(j0WTcX zD=rp)?0S`#24AQ`(AGOekkumaVs@SQ__t(j4R zdzfsG(d}R{j@Gsk)_h`zi56S0qNmNaW7osvq@Uz`4;mS4dbmhyVSm$ofdW6{vms*t z^}b=eX>P;t1j(Y{BK8#b^d@CHW_4`qA(ApC>Syd-OlLt-cJ;#4ZYUpG8H>p7YaWtg zU}+==xD?X7x_dv+bf@9N`nxEXNZY+Rl>&XE$HSPYCL_u=ub2jP4h-_?WTPxU`@Onh zKW~47e8P690Jca7d#qSA%S!)QG;22bN_)PX%AYO>yW<^{8mw~8(RQ}5WV!Hjl>!h}6 za42|XOj+Ru_oltro`U{Mq24D?f`fC#i@n{@8q^1rrBsb}G`z=M@QF7Td*l@APZb3S z12ii&KN2PxJ=M-NX+Kof;Oucb?Ivzs)uS0W*nN~1gvGk{^2k~GbRDs=WPRbK!V+)r zbW>!qJ?ZYd$jQp7Yfq{yCm7?rise;&*P;`rg6M?aSjb;{{p65!v+%_xD6f=E>U&}d zC(^Nx0qQ(ZnOOO_crUL>9rnQp&`0Z6a`ygPzZhSbc`biWu$@-F`b=~5$2Q68Ba|T9 zGqYil9sHU*1T-jI`pYjTaO=1B;_aMQ*a8^e#K$czCJS*`AciQ6e$je&i{ufJMkb zS9CUEWe0-ska!FZ<+(Ej?!Nzp1QMu)1VG%_89;Q97z_^iA2<2aQvShuf@XC<{J)$ZFzq5(j!)8!gtYy62GZVe)IAix5jV9W8$SJAyU%hwRlSIuy zGRYf^<~ib9quRB#sS=uV%nc#V9v80VWEy9yIQ>v5e%HLd3&{sH!#QNaL(!ktbAcc6 z*4;0kZ^%gIjfI4abvo?37;!Z-NBEJ(d<2?VuzHh*ZV5MYPRuFIUlqKmkl8`Y_N@+& z*pb_9KuB+GV2L)8h{shIcE%Z(=5)I*D-2`KeSn1wIT-}Y;^^^BW&($?sHvbNNSTkmd~YF=Yu2~+*#`8hP9Ht4uk3Axu<%A z6|n4EXq#hE8y_Bft=WE|GeaYio3xc!7M-UM@mfN+KQ?|^WKE<|t4rhApVJ?SSMZG4 z7hfMy>5eTn3G7E~O!OWOKZ3LGpT7;+#%=J(zaWycjO<8KBEqh=#BWE9o%rTKDc9QU zWqD-Z`^}SgY6^YKRYmJ8wqZGLY;LE+put>V?)2&7-Pe(Rj+C!@GL!3%Dk8Eli{2g+ z^wihs-VzG0CuDSjMa6)x!8X|QWDA(dwLPN+B_Bl2g=^K93D;CGbvL-e?dDG~rG?@$ zIvy@_KGZ`|z*%_q&>82J0@V8qgu4Z(EM*WH*nPx7I0vu06tphC1fUhJ&&;#j!0C4y$`cT>n#}kZu;RN1_fCmW%$o_h8AgmtvIpE$84WJwbQjT{~l2*qHZvF^_6$G(eDoXn!_x8&) z&N=AqP0WBu?VnX_3>P!`1G_te?XcU;qfoKtw6vN5X7}A)|sAvk1mO!IHkXCgk zMkrYZKvsJp+WtZ+k*nHSTN-=(%9H_cd>H@o#x8vlzoB8_yG+8ugvap5vt=Ajftjc) z{*_~SIkpJNKLANhJnPiYW@uaoBO&@es9V#R%6!E73k5WY3UM6m8-kyN=cG_{kmVy7 zUYfx*RHc2PNkI{czOgjN^MFa=nZ-E2nQ#_u?;d{~iCRgZm+zZb+AHtiwd^gEuYA?N zQ-Heg5GhR>504L3U+d7Q*AotLt%bC1FXMADL(ow*?y@cY1F6nfqItezp;AdD6X{oT z^u@Y+PF@H{_!}iv`>eVqwodE<*o`eUSSvm;0cvT2QQ@DJ9+`Ow!EcYJk)-XLsvcyG zxMZ?b?0yK8OgXZA9PZI2870gTsO*%E3>zG-vu1=21^=|53Fk{n0`35Zl``koekizoTX8gr~8P0GF3w@0NtB|S@d zu4f@Vj9_)<9kMDy#&VE~wb0fY+(_L}5&+3}38I=7pf2+V{?SME2RC5K3i-hCK)UN}`_T zN0ILFH$#rxF@jFn%9sI+@@Fg~>*xZFBCihJ56fk#2XeW2UiJ1oNSWR`eqa5HEPHE^Vffb`)%zMn#`={gXMSIH!Bt`8SkOUVJn(vi zUXnfhU@0F#dP4|1AEmo;v_XB}0Jk~B@;-$(nTsJlIlh;*pg4o>QmOXn(8Kgi0}{fm zFRPW)Up)x&rA6f>wZ`VC-!SK%#6{87t#0BXr73z*JQFAbArZ7qwOcX!-PP5LtFoum z+KjN0yZHu#VXH^1jV(;k0v6xxGc}>g^KVPl ztJfHD**im69;Q@&>5AMU;a zF3N4)o9=GOp+jQm?oMeCq`Mm_=>`D-Q5pmUDM3PzmXZ<>P$}sW6cD79?;T=`Zui;e zeBV9iyZ3H4znL}j#+sS+JnR3||Jfc2yqVs|{yrTu_O?omb@UheJsJ!ad*@EK;SYF2 zF7dS^zA$?Wb)(3Rc3B>w{L2Bf1z+T#TJxbNL?Pjczvy@Ja~|4RN<{pXSOky}c~M`F zgo`NdYUAVNXmVM8iinG%VdmuS?q+UcZ*ke!00oy60w67IEbPsH3R+y0AOb1ffFc3% ztIlxd`C;ddF95dMSOWZ*?iN4NvCaw)&rEQBpm5g%>7<`6H=gM||L8fai8fKYZ0);VVQ$ta$^BfL^bgU*-*7=0)$+GF7`4CEZ^TYh z9l1`?n>_furx&{6c&$E)c`8(Y%>CHTs57bnOFc?PYq!pWbU9#Avt02&%T)*F+5w@< z&2@4HMEA~2xn}$7-TaCjb6)Sn)(siMfH?;ZCDW$^6sTqm0-47r-cS!s+z07`#msh| zx!PVsPwgGW@aX3~j)`i!xosL?RApoVJ}7*y?5RiYX~@+Icz#o(tF{922b!ih*!}Je z&KhAK*cHp)8ct0fezahwkL+2aZ91puPL?uCH;M#zbLb%k#`1@g_6>@J?Q^U2x1RdH z-nsnHI4BCo!2un2tn*BZa$lDq>eK%MD$kNAv2PyH-hg#VP8Cd}2oB>P^@LA0oMT9G zFf~AanNu`c;la1fWt+K}9UV@mw#+=-#o~A$q>u=`Q5S9H%RX<#8ham>j#V;Kfqf67 z2Cd=wJZ}Ki3#dE{U-e_V2EmRIZ#9*Hgk3AdYp;Z4e9)oqbn31+EQf&!(`Y)dX5sc{ zzXXgHqnt{R@qS8PGQWufy3IGjA;K5rk>Yk_9beh^nxb>#D8qlyzj7OqrS_zyH@{`* z0lY%vM0{zbAR<901}>`<8WALd-AJa z+F4z|-769=uE{P3mVwA93Yw@m%X$8@tc4pZ$dVPLVFP4304*YIfZhDeiw*RAbO2gK zTG+X}vVx=l*>&`^aJ93rb_K~gn95ypG@+tlU0jL9QO(1|o(0T#`4;S--#U|bAjyfH z7wFV_p78)la{6Nk4*G94-@lXgGGP-(*qsEyR&mtOz<~{>yiB_W$CnbJ`)YV|IYlgL zd1_xiP;YTbohGmM!&BcEt4H)Ipxr}hk`7-TZ)$~$3zIV03@Ge5YNPEBV>T0oH+GYU zpEdTnkEJ+uh<)?5OMqBJ-HcB8_Z0<`q!k|NU~BXn3WgCD6ocpy3woy{Tf~?`@^ttBv#eAv_qOX|0$sX8-gk^;85U@q-^h7X?bJ+ISJxQEbcPP zQEOCl_@>;gs-&>u7BjZRz}H-PT&5y>?>}2bvcthTp^hRRt9W3Ju#U76c6TvsAfRK@ zU|vnTeT{*RV$ES+FV23gq!Q6r`QgZ|is7w7iJY2_xToK@MRzxE$Uu3n z!yF%Gz7b35jufcN#`fL`v?yw#81V|qQB&frer!PNJZ#xxeaMQ9XT7cY5UG?d5%WV- z*62}{_w_e<-lH2ar4bs|5=v@n?&Ku&tP5W$7~PdWJ>8#6ObuFX7U(8a-Fx13l3o#Q z_cjvtUOd8WfiRfqhhvgnqFrG8(sa8%o##<%F#@YSp=gtpsvs0%g%`HOO&cVyIz!VS z-QZ78!9cD7)p@=FInbXO;atAqpn%Mds{($ur9ZzS;F5ZmmHe=1?DDK<+!GL?1U6rw zV*f83PRt-MKO3YRiycUNKUWSks;-`n?PZsJUF}Rd?m~t@^*^L6eT^K9~ zIUE&@>*7}8W@fH{j}4${1F5zHk_u93K{@I;&VBvf{^6yJsItPI^7p24X|cHTm? z&(#+Y)N#iT^2XhEDHvCGFt@OD|=Eid$ghqp1`+ut+XkX!7ef$qC- zTtl-0rY6&$700hIA!r4nNkDKxGvJ^paL_mc954bBYlgr<16R$(R^p&0O$$dLqXyz9 z1=hSB&^FlC0_5p!4m5?fHL-I7*?FD`gPjwk`8eo&pL6o`zIuYQlR3cM;sYEFu#cLt zf;c#MA<_W`X_&HtJVDO(Chm?F4j>;#3r8C^O-T1+;D47tgzWs9mlr&Pye4L5K)N8L z!4NPtNgp8F2dG|f2dOw+xwxd0y*=v{N4-*TJA|LIba3l$zgdRY9cQb1YtTxVW9g@j44%dfcG&IBPP!TPXhNq~as$ zRY68)7oviLg@|%WT-#k6rkfb-RSX&erfH=}Nq$cvYK`FO2}5{aNUh+|40PBT%ffJBT;#9G)i-r zIM|j~KZT(PiYnyw5L12CT@77Ui(6w~CS###-RvL4oESrIh$XdsQmZTOGks4Bek6Pj zi1+|3bp0F;(F1rW;dk-Iv%XQUuPDp^Pkp0)aEM>@jZ$?5>R5mrFNk71?;phgrn}ld z>YDTU5iD+JNBm12r2e;k;D1y<`G$wbHs;++{j7-~anpFd&+>3uZ-+KXN$wNKZW76H z3#jj2w?&8-Wc#SS@HG5x7U6zYwS@yUtCt81e3|gz}15CMoZ^TEqS4 zdP&jAF%!JhJz6DjM=LHi(iHvjuE)#R(9n_BjOsRz|1-i4uKKS?VJAJ%e5cCIUkD^5 zR~qzWj@!DhDYg|V7-V|dJ0$Kj9+lj59DA-7iM@~?cFitWDIX1|Y%RZBbh};NA}zM_ zl?d(gKxPEa<%S24n+twcEFK)Hl+Fdd z0#NQ7Bc*r9npYLinNjh-ZB_kkXQ}^fANYU17(wg>fWyclp)?XxdwdzpHA>e#q`IB> z!ETg45}B&&u~`W0e(LS_&z6Yl49s?bj3E1rRIhDCuRGUh+ONZe9yC&oM^nAaIdR#z z7XjL?+o)X93M>^?f5ngSa;p{o#@k?z*e0VlQ=Vz?I6Y5Y+ox##^OfTW3uYq%=F;@$ zjHk@0g(O&&&-b5JK!&Q$<>)COM-R^TA1oxnS?vS~naW%b+n$^Ex)pwvBa{5>qJ*M?SoBFj*svxbFQNS@{rR>5;VJ(a z`2MC8@kgi!_Jb<7_OMceTCwD+8GBqjop7VSO zCTVlhlT)*?MMUF~yp~LTM$!g0PQ_Hu*j^cN}u+)6Kt&p9mJAeIV zs~Ghs7KUJH5pT^zx`(rYaz(tGTW`IM2|kprVhlKzN)ht0$xqBli!jymXbcLdBJ8uS zcIe34n@|#s!IgOlF$)CR6|O(U$6I?J)mG1EKY!0Y`qaGsHmwf0m4qg5Zfb2t)~}|T z1_>U#!P11XF3h~)C~0L=~gA%3#ou;%^SC-9HS4td%pEU9uXdsZLn@2)@33J*lN zhjGM5`&1?}c*(6OC!NLsouc2u5v^iKJCrCQ4Iv#X*KMX+m*38@Z4ZB}s7SOJ2jMPz zX+Q z7fVbCx7~c^X=eN4p>WK=j%xbSWg8o zSfV!MK^a?V3OjD6^>U9Er?1W(0;&G(zvf>oCyvYJng8|){Eu2r7wAG4pOIhacHYD- zT3A2hqtD2xLiAY9uh5W}t0D$b=800cP5WEY>AjdI0Nvz!fh+KEQ$p~xVn6ztEuC;h+?M)vF>zgn z@nCULfP6LxODIsA$bJ#+L%~J7c=3t~lUF)}3S3}Lpj!evC&vZH3E<4<2ORW}A^899 zs(-ipZ!K!tTp#IDriQXpR<71;>&p;SuF8qMXR8E|;kY(GFE!6G! z=rG3IUZ5;YOHH$YPphsZ1n!HdInRFUT}eq>%i(=Orm;<)BQTc4JB@+EBThG^s>a|6KlK;>X-20*8ij^;Imf~*MExXw`j~0!B)1FOMB<^jUslWv*u&*A}bAb z3ByIMti|TMjbc-S>2{^Z!QzXYsHHuenC8JcOyAJTc;?W`6+1TtQ^%>R^bM+YHr$=j zm~Nc!{y{llfYRjW6i#7?*NXxU;#&tu33FJ(nJ>~VECC;@E2OB;4ftV!M^+pAGhXP6 zU-g2Nlr-Vzjkgh0;7_G!!P{wu?)+>x+uN!>GIu$~#NGIHJ+j44m(OleLgm%1h zO%L_sQ!z)NXPPUl*+5FIMnNA9b9;p|$Ngy=o}J7s6>UAGcY0(wtavN>*rV+WvXF&^ z`Hs^2vc5>0oyCynXibEADTKZHr)3SKYb>FG?uthbD1Tz$SU)sTSnS{- zzc%F*icN9otob-)|F_{73q8D2`b=ox2>%84_o;O_iiDvxWUAx^_ z_&*vimtjBBj__@_PWyfk>s&Nr!Lge!7MuH03Kk<7$|}bNDp>B+8K^O~KCd%22kHWq zF62|H87)Q?il!QSga@qH%6a=&`3%atB6$Gtzo2(U0_dGJFByIj0S+P)dv}nMiJb*V z638-TCkK;4z&;8tzNWPWNJ~RnT~l34L-Uem_p&)1DlXBL^c;Yt*Yyv^n#)9bSX?SC zO%)c%C1h+|-P~C&s|6vH(~vMdgg)gAfbfF>qEmK0E}(7@$f5)M^JhbDUM_w;@c)cY z@pt;C>iAynB9B&BDFT;%PMYqsgBncu+acu~m7a;#8`KIto}vpGwY=W2^(8iU5ov3$ zSuIwO5V@Hstojd(u$eDB_Cq@&49r89jk=-c!uI(@^stT~Fd{067L+C#Y(wM8aFaWi ztTiA6!JGiZJR+YTR^4h6poVl{jejq&uVC!6pulb@oT2f}!dNcX&vjm%!-6;pPW~43 z_4!(z^-hxcon*|Zt?Kz+O88Y`50UI7yPzw4e81X}Qi=9$o)!%WD0<>&y&3LeU6|A% z;doT%v>N_c)VXBIIk7~FTuk*iBhPfv-ZAIZhxtH>qcyhG*Bo&1es`af=5Y(*PiM84 zKPb4+Kli{vaaSv2y8i5z|6zO_h4)O(zF716s#x?Ee`afB&K6GyeB)eQ0Rd*PRE|WB zSh&b#Ha3tK{?jsK`|aYpy7qo0283+K!2mH}{tj*b@aVk|s-b?4lJpc6u6vpwS}qeK zCK&v=nBvnr=4yi|r;T^sQ`&mLsmKa4?(tU&vH%957 z)E1l&47jn2)>+UGj%pBZl{#kMfJcK3Dhy@p&}%Z+aV--ZAt<5&|dD&<5doAJR+=rw40cB170I$tSL{AQe{gTc%e zBw`8!*7dF%E}k2jaTH-_(6&d9`AR7|LahNTV0exP^Z+~{ajtLR1bchbf7LOTms$lN zjh9knM*|qo&y)wOqOue_CU7()a)*lmj936@a8btwi;I5#!i6*Xj2jsRIgu_Z=?k+t zG%OyL4bXkf%tXx2!JGvsMmM)R(-M3Dg8>f!6!_1$O8{DWz-+k~g8x(V_&YgIM=hw% zA;c4;!Zr?g@LhV#C9@*GJE5V6Zw5Ji?F4s^8Ec=fXqJVP4Vno?!?Kd2 zFJ{H6Kg_|qM4nCPn;awGeTjNp;oih=BqE4DdshOVU5fu1=Aj3=BNhlbnZ{u$Y2-Id9S^fzFX{{={Q3TdQGB4_K>i|YA#eP zLmo$Ae$80f*cPdz26~yUy-Ue;q zbKLs!9+2k_*lw}s_FE(%XXqFEI`;|Pt?|$sJ;HRtI_c%_w6As%06KhMk+`3{dG6LG zx7{r+lH>rE>2uLzgD~v_fkj@>)%X7a&;E~E|ML_6@E}|kmqM8Q&rm$jyb#QN<~2BT z_(A&5@?F|_|4pX(7ri4Mjb#M;-p|}t_lo!)P0#|rJd+1=10AsoO6>(2j5-Tdz65{A z_xO)JZOx;~r`bMP^Ob&SWrg9$ZV|&PX$w9D#g4}>s+?P`A|G*&0wi?b%3f}=9~IT_ z93yqz8$M>df7UzVPnjw|L*=WyJ8AEsz)&l80bxX+V`^VVqa9$+HC+AGVQrwmmN4v4 z(+9IUvigO~DD6#O1EU{sqmx7lX@=is=*`{r{!p{bSFvT`92)?m`LgBoeXhv(AaF{@ z-Q<%gjW<)7UIY~QoYWfX3wrDZnZ4yrxQtTh^!i0B))_eax}vPEFgkhhxp-%dm>_+R zQ_k~35&^vFbG|O2k$zSF0#}xzqzXIs*=7zPM4`(M&`wO0{_2U`|m0mC#seZR7LmP_B%LQWD00aIU_2pzZcF#!kXQIN%^)O(ers8 zsUfqWVNpE38ytn{K+_6mkCz;zoP+Lexw94a^uYYuhx)akq#=f|R9OiHW+6U$h5pk+ z`)luNb~e+?^|=t<#XrJD$cPS=7^})luyzPa_^cedq2#Q>@_~l`^))ETB(FoHa5Bl^ zUDrnVR;!~{wKqLsh&1K=fK3*@`0%@fRIk1qjvU;SvcYQF6)@$ST+2cAs z@@$+#!vyZBOwlS7S}7tMS^bOp;hg={EcaX2;4Rq)MVQpTJ7w?GHyySGedV2CRSKdt z*c(qy8{v)tG4L9xt=}>2ev&kNIKAt6yv%j`KJhNfG|Q@;&?5@*g*%3~_J zs_;_kC+`9r`j9|ho{D`vm6COtrk}=T$o=Tae~6Wnqb!zB|Li9Ib$b??=QL(s`;tUH zn9A4-tECYVcUN>>@=F{awLb7`Sin{6ooui}I<%>Va~*4!slWa4^u_VomH-;}UOZ+w zLMXv>vexKkFa2{^p-xgdrmsRp1^3g#x1*!14!Y4SD?f?11V4td7NFw#OuoM46y<)y zw%E2v$4Y$^WYYFpqwgC{fDzqHE|N`3PS$sM$@!6w6CK-;?39kAa|1gb7$7Nv{yT2& z+|tZ~L8G9JTI5&}xo7ehVDu3fa28#uU_|(3&oYBRO3*UvOZIb-9F9K9CRG3mw{e@!Tc( zmABpFPN`LiM`g4uI&8~t*%^3X^f_LASbhULHm{W7*DaTB@Vol~eXxgBsSx9)=*>L(% z-+IM(1g?qKM^^Ric1tTAnss`wXyID> zYgx8dFB2lYZi|yl8GW58Ka7Ty5G+3}B4oJo;r$pUk(_1Kw_u)kD=~Z;8}d@KgZVSt z8on`lwR_kJif=u3zQgP=KHZ{ry@U7ZiNTCdP*!>()d~3lw6yqxZaZj`W=`ubIToRo zjk8So)*~)JYpM@L8+ckV_3;p$0a8F(=eLlo;>|^!E zeVT~(eTUx7m+!>Qp}szH&oLJD>&YoHMiq;pug5|n&HVD5u81N7tcM*@x-8o1sWIRS zP&@Yr0A)0=+!y-!PrPFeSM{?T`#B~9^fSDPxr2@4rM^bRMY>FuyJQVQ#l7}(Hr-{s z0H6-K^c(=}#p005NQ$#a0__3-MGp9W0q!55p)orrCxFu-mi+mU<7^224^QXsp!ypw zTK3c@%zRo0W@=x-407X!ba2oMScEhZLjl=eU5c3d37E#(Lbfod( z1InD9v=E7Oo5@%+I#IT{$a+7Q^pp0lkiJhZ)Y)tgDjL@d)ClWz^u9F#-D~rtx^486 zJ>EMU#oefR!~m>pLi~>k9VP1$G=$$;I$yK~84Y1(L?k^T-`)?@vZq>7)FUWyoUIGP zAxq$7wijgn%HP-fT9PN^_5O2)(9c5sK}p~B(LY7i^AOHttvz^z=s&`|cE9$3F|Cn# z?jW*MLkBxF1zvAdx&CBKMX<;Ib=LpAyi}k@ak$0%YcVOdU2Txm{Xau#V2J!-J~wF^jKF{sLys4F7C@ zABTq0*f`^4i(yIC;T8v5@ozZu16>q!mY;ev1;j19Uhl$GXdFq#FOD~qYX%b18so?Z zxvvUVO<^FgP@`K5Igsw?C^EDlWD(*?EHN)X3M5cD#mp2UJ-~md?(uN+ zfFNo}d4&O~`#yupa!inX>IA*;+L1SS+`ee0M1TYz=Mub-3?y5m!n; zfPxAF{=mTqcYyj^i*x+~5Sv{6&dw6uo?g)~0Qc#SLLWH~M=K!gc&TF$aeuI({%EUo z$zCdFV(;W*;%;i=;|_QPO{{D{XZ)zdV4`yy1{fem-kNQ3*lD)lT*Mb>nS7X_#nrLnYfvNJb}0l^4AJF>oIn;EuqZEuE}P z%z=X(P3%Cx>F09;nfL&2Ii1hV-onwz)d!ftVfwqRG-j{O% zelnmR>($w^{-RsY_9HnOnf({qPDig8V8v9H*!k_~>@)%gy~xGFuJUKsf*Cu zrlA|UdL4QBwZ^(*wLusRC>U>;@+;)kyZ8{lH=`iO4nG|1oxo$yz43cIo zId}`k6g9A3ucb(f(>D)?#!$&gP&`T{L^!+ZJ{{NNew^L@%m_naG;~6?Fgg(?x|?pf zMU8^%OEPskH+?~shGNhTFRZHU);Bxn54oq&Y!PbH7}A`p#27tWU1YHBB%dy6iytqO z@`ort-+NSP*;9o6Z0mM2PaBAyqrU&0Uhf{EIFIsigI17PMv`HOT|gcFZCAfL%E)#% z?=OD>mq^Ks<3ktdM_JU)GK@1I-SIL3C3sMEeT;g4zzBvG>Sh@tMFklK|vOmGy%OwENSKJiA*+xdYlvUXf}b_UnV$8!;d6@)yO6a!O|thEcd(5AE1q~C%bF(~NTg_sj=9^f+C~=x zS7MvYD$!=X)Qh}CbrG|X$+O?p$3&-;>SnqwOpMx^)7Br^ODbBbUb|;CpybfeO#My# zI-KL}0s^nK^jp+}LBt4@X0}s|YR?1?)AtQ3S-!#%A_Qct@`kZ|W^ZJLKImAti{t9# z=if_y*g%0nj?GpSi-;okDAqPLjO#g*NthQgqYXtSt*RPaFJU`BAEL|3@Wb@6VIusL z#`&EdtLxjy&t7NjO430e>DVPascc^59!;>TBMG};;z+-;^7mA34tPBCbXNB_|6 zfGn{Sb+|41)&0gyoyCQoodq!e*g5VW25^7_Bd1FoM28)FqoYS z2xvf5I0q0`-mabLh>-a5d7! z@8(DhaNh9iy`3%?sGB7pH*m0XiQqYGhS8Xbg=teoYy5g0D#}w+kC2R4uD$%yq&Ct& z0#n+CjTZR2WGXq+E{|VB;B6StHlg!QUNB56U@A2J)-?E4mjuIj{A?Fk0(ODvKW`UY zS;S!IZ*%hoH9dUIPc@^1z z(LykBwfHL&;YwBXKVvNXG5ueSgSi^fPS2%bD{|13E>xHBKfEidf}GrzzF-?`1S(kjl`RhvG<$v@CKnOkPh z3!|hfF8Jj^VwYUez*01Sl*ys`gSDo;!({hW7mUW+;q3_hdVUK2T&iH!;{cAdyTUsl z{R7+H@Evv~=9_^qcfRxWfIUc`Yb`WpzbJADWq|jnia~F^r%Ac;7_~a}tD5-KK%Oks zcsF!V$CT_1x{nl}CI`?T?&f7wyKyL_q<(J%YBnMV1q?1+jC2A>s2& zvI)dqDBo-~H@od{8W1;fef-ds-Z*rBZ>xU@^@WMP znv8!IOZMkDGc>{tMCY%Ap{!yd8LOh=4uWMP`FJ;ZyfR@WKV#wAyM8E-EX=j5k$i16 zMSTiOnl~@<&&0{YudMZ|NxA&P+|KvqJmUS>W;Ujbjf!1Ye=S&RD6j<(^e$`sVlRrL zFwDZ=j)MHaZ8wr9Hj=(!Ir6S*SfSZr7RLw6B+TvpO62%y`;sHOfE*Ywzoq_5^SgCf zs#8T{@{c}sPYufl5JK0z3XfNbjl5oz_9VJ<7^>+&b3ScJ->-_E@C-3U!a_m$0DnLX z#uL~w3@_|b0TO^7^=Fg`R=a|j{ytCYqM8T)}z-#!q*vUm%e>5ig+C!mr!Ekq}7mK`&IfDqW7q&|EVSU z?d3Xwru0GcTSe}TqhxD+sIc?a$g&w~IN!~R_P4lB?|-T%HTq~I7=<5}J$BrVBRq;2 z)EN*-wk2v)5o8|;_l~=4*3{j6ez31F)2@D*5Z%A;6LZQ))ks8mhi_)SW8Y%kh)sKj zh*QRb3Z5brxxYaB;%@n5LqySmz~Q-tsSVcr4S0aMvW~q?Kc?aEz0WY);LFD7Y{t-} zWDx$Ttm?N1{Jf;jl==wj$#))s`8zh!0mENd>S8lSAKL2e7H6lti{CVSC7a`#O+s4v ze!=*w;Kpw9`zM|}nDQgYBM2(ka(2gt?(#!Jqo+G!El_HYIuN8BK0R=|^;LFi8@u@S zH>wx92=e2MTYt@zJ@P|~m%lNQeODtSGh~=u{sqJF$I0rAQrpi=FP_;LdEK)Ta*c;-@#|!nEej?Y zjlweM-o*Os=rGI3s?bCLn)nzS(y4ELom1~*l0_JQ+DAqqX0|GamHa7UVxba>)4J{3 z+Za3g2=sU3TADnGMuAu;C9Mtm z(HRBI!@&jS=K_31fRVw;4h(^(XT$&8ME))_remLsP3NPI{l2q-S%r%_vau8cXP%D= z%F+9e_AzP%#9HN=bRGTDh~hV}yaQa`_^62TsZ>FA-S5>OXk!X_M^C|yK~3no`^}i(YN5K9G)1`GIg~skK01sHg{& zAvUV{i*qEV*OHO*cG?>^cbhgQaWe-q<&f2_T6r0<$&cS)7lskJdoSJy!&_J9ov)OB z-;XXCP>%b??z(8<%lRS)PkqVk=IYEUx^O{?fTb_1mJ9^6Ly8ah3Ks{Fhk4pjn~M5nkLcPk%-D;tDC1=8V2c{B@9TlhJho3(dw@j}j!H}-x(DO$JKCvc z&XDTv*W@g*E38$X)a3B8=f~|%z+0(san?~Cy=)tDL`0*zFHUXo!2~5Q& z>6uIncEl)tLM2qFOSf5E_JX;C$`5>lmOp+k-6c+UzqJ}qvuBVg)4}|P{5qv=2)&h- zLjJ-ljt7%`^i$A!C35SD&LVgaFKwoUblyHF83D9nckXWz= z49p)-exvbVuV_5!@q!>n;Yj7XE^lPo9Hq&3Is!9)(s;i;;EKk(B%(|fa6`yeR|MZ0 z{a$&C_V8Vt)7J>|>`!=cb#QSEit)w1as1Wex_dy~97=9x^uF2BdJ})}=zsYP`z6jRIB2#Jd1Yf~yY-rnn7U98|L6ya-a zE&3(JsqeqAH!bm5PU*sTe=;LxMS0*Ck#zl8^uqQA(UM0kW5mi-46%Rp`<{_#Li;<6 zQq9rDU;PDGt=W_6Z70%ZC)ZdDLI+4u>J*R;Gqz3W9wt5awcNO8IISi+>4sSbr;9ud z2Xh}qWW;mkF&25C@ajOm`7md9V)wj?)BZ=LuZN{JAM)+-e3j2ZX0TVnWR zuj=D#csidRP}TL4?YynMhM8?*Vf)ejm0x`O4Fii{igEO)2@luf&23pL+^Sc@*COfZ z(o($x$QPMKeLru1P>xA?&^{*WM?(E6zlw~&RZy2(a6HeHwKs8d1D&CJfO!sZFR_C;&bwl9 z0?Hpqli}p%2T&V0=)c1x{|?wSc_eL_QaRC-&-!?l-f0@A8LNAKGO#5vyY3aKZJ3^> zNv4bzy*D!GysKXGJ_&9?Cfr3_;rbR6vli@Ix%OFpzE59n35iNICJCFAr~n;ew?Oo| z7*YXn#1RGWQt)^ZhU9&7J&uX(+$s-VKS5^xqA}KvCsh|-uorWke&P=#;Wj7Ka9Md$i8Io#&r`E#F`F{sKYHK%BPl zX7X6mgxfRS=JJHHhx8A=LswR)L)9rSl2E#n__uyGv|*xsdh0FO#2fFPod=Aw;SnF; zZeniV95oM9OnpiVN8TgzP4igpWJ}-+KG4Y}A*MzIT7pYkj95&Uw^mAQuRn*g~z?} zj}40oWA(5beS+7UW7n!mQ)m$%D5NqWvQ?AcZi&XMf$<|rsq3s4U~YViQ@?)m&ioKU zxRIf}Z4JL+B-cix7aG#TQ2U|*#p;|pXx_?Obu4|9y<_(Jcjj^!Lvs&DlI8noOz(jj zr%}ho`wu_Tqg;2p*Of_9`l@erHfNVDAx8PQf`?@9noroQ!xt0W$XnU7NhoR$qV--s zEg9P{MlLpPni@BnaeZQpYX}A1qi`ge{}B1#a>R6GIx7s3nxLKXXGBb58ob{{-0*ITjfdS6JKXnnYvUdV}tY_7&fGd#A6%y2S za4(vV^Vvw;7=XVJWOJ2b2pw->zdewPW8qaz(xa^rP}y@yinqC5k31XHG1lST($H zH*Q^&_#gwtDzm~$d5d)j{GmO$B4>~lg)2Z4d4#7aUtUMuZ7uWrqMWx3iT+)V#R56= z9V+z1OeFjkW1*0JSt?qpGDer@w>JrU9@Qorz5*xYpXlE|knf)?TbzN6w5Rw~ebrX%UZ+-*Smi4Ro$&jF%M@KXBUsl}N zu4`PrBS#?S`WPv)r%{%fM$sVWp4%r2uY@hD1fPNyl(Jf;!&Ix8kj~o_T*!Qf{#oL) za>n21iwz=ruQuJ){wAL{^H@@r9USf{mebc#t)DtxuD|_te zI;=eF4|E0E-+1hKAKD*(_7k$Va~9o~<3)}~l?W=6k*PxsLD(hX%L%wKfVvqH74d*H z8f-Q7O*0qPAG$A0sS=g3y?MiLP81VaU5KqPP3}AI8a9IN9FKT(M{P^o^lOExM&j0i zBjVIIF6l>ujbA!6^CG!D`$?E(oY1O=+f6(Z-LXF^2Hqu&!j9R{KPBvuJ6V}Uz@86< z^jUERd?r@seiJjmZ=!gCqXn;iT@W1oN9j0F4F4eHOX*MFklI z2A}-{9w9yv{!2=BVEFI3>EHQ3YNL4c5uby2nt~hV2tcs+eV$_EY4y;iDs&EMi$^3V zQyS;vMF-;eW$UW;|couPsgUl~l9jbNF-$N7#YVjn(^}weZtC z)K-nB`18Gj%a1n%H|Vgr|LAeL<-I9 zkZX~iktGY(6dMz6Io)>@(rf)gBB&X!kXaA)Q+#AI)_iv0Ro(BqWr2}*9t0aM$MYkR z-(2FxlfXTN%Ghr%RvnyIlY3X^^z=Z*pYvfNo~eL`*`V*yhhV`c4gB*RP0UajuLw(V zHJ5RK2!$TxWt2nIqM7IC?nsNQ|`Z`e#JZ8 z;aAL4`j8l>a#m%vQt<0rr)}`Nb5->(;(W!QsJkZkYWw@HijZ$+bD-`>dA_gL+GWBhCq z*`GGX_l0_5mdI-7?OdT*1vfjB!SE@`(^Jat)CM#PUq>7;P2u2mf+rmFIcdEWSv9Z4 z^fL>C*M<>JS2<*wYdAe`7eO1Ow6%>jm(#ZPkfR`jB6Bf%cAS)hHK9O-Z{ipEH3?bo zlGl+mkTj*K2x4(fWkhOhK4RC`y>ZX<)yuTB0el0#CvTe%aBH%0Y`&USrHKd}2AYwO9+SZ+a$b03L{^ucR=gwJU64UH61Nqg`4q~R$)EtZww)WYUV zu(EU@3&2|0gr?2iOo(O(8#8dP9L50YrsEb=m_7dFEBj4a3!MKsZFG4)V)J1SM=&-c zRU;G%yCDl^YuuXMvv^j7_rv$PyKr`uzJUqb+a~z*7oL1v&VAv%>Gr->Lx*K=Xzrcd zDFa~9ke%1! zXj{12oEbys&I%xN=C+fo-6df+DlR*uAefz>pC5F2PKPU;721}kRcA?8tK<6xD z9H4)WWen1UQkPb}KFjp%5L6w!SZf2_lUFX|XBRC?oP zyPSxOF(`~_ETMKFCa0fc`uR68t!JvF+U5OsZ!33$lndECH?0$+6UdQ*w4asP1=ZS|u=x>q3g#W8ZsowB$KmLzvSthuFqNMsRn&5bx1Sm|%7&)QLo$gSX$9QCxKRLald|CFRMQ z)+iI-S!O){&{;RMXkg??)k=35Dj;weTXVc&yuJDwuHw~nA#6N&=iyBLaz6Xa2q~(} zlq*QI{4=~zKBp)uf2p&Vn_}wq8SqQZiXuU+-0uVo0}@T{j)9Z(QiZRj3`R*39-@;= zBv(Q)!wtFT!N60QnGJ;09Je``+Szz~GjJBK|Jvd=)7-}4MnxH;8{~_B&*#O0xm-oS zF%Rv;{h@6dJi=+BKsy;~e$B6OrpRz)$qA3smucrEq>Jkk%9@elpP)(*B@ept&s9p! zG7LUn(X+?3ldn2mAo7cf;WQ}ad{=llA)wWxi*;DMsaHFws5rv};4&~^L(!buQ6RvM zLb||ZWWQ<${wvBsM*fm+0|ggB!^zRY)#Q%`8Ms*IFPuv)2N07wvys>V$|pboIrzEG zT^?7402|MbM9qKk(to$|69^T!GkdqtQ@W*&2zXEAnwkOvS-1t~oQkZTw7`-o$2xJy zj)`06tekA!Z-!~4^6=z`8t8Dqz;0K-aw zZzzvV)i*=WraYF^kpvZLhC4)N+nR!OnV$L&B%Ym?Z>eld^WRqqK?qop7kkwS{Y+EO zl1%vIa7_p$E2z$S3p!?zTGQ`U`9T6XREq1U=Aa362mCI`Br4)y!L#H(XEm`3hc_5Y(5j`EmD^4q;X+T|Wujw2QrG#N)X?Sw(W~_{#ZnRnlE$#NugSVneCAY|EApvr3V7ydz@-Ykh6qK(1cJLPxE7abX)s0 zihI6?hno^FR8+G1(e5TsjZ0@3Zb+z_mG2sKRN_qa3Kp?u;_1PAJl}X{HvfXV77pp& z>O^M7o@EVDDavC_IxfyPByFPs!~$`s#T<^4CpT!b$2q!F^qfm)lpyf{h~FXqTwZbj zd5OG`7xsT7FAAzxvX7Nyfi!IPAN6KeNP-{%+zY-79w1E=lIwr&A_Pj%AVVPY0^-HL zDlh-yrTbbkH4koQ95j(_`D#*xrrrO2#2DR`VkOFRXS!*q==xnE`Ezc=?VLFQ8 zI}2KT$DUakd8-QuR5r{>vbqdwRhDr&Ojb|uo4ti{L_u&|E_*ANHUH^~+FKZVlM#?cKLo{GA8So8TnIqkg^V~lsW>yjy-U%Ox74cyUmyQeJpwn;B=*3Xeo=SVE_kXzi z3V^8Ac3rx=yGwHDZjg|Y?nXjNy1P52LlF>>kPaz9LJ$x{O1cCo2`Q1g22k1VeSXim z_nx>{Mfhf|HM5xc-hSWb0TH4W=Z-zgqTsjopgc&kdxwUpz&c8-TX~Y^q0bnvYO$># zLHmjqgl5OYoe~W9sX|&1=3X(V`DC6_(9GUf%0R$IZ3h#d=3Ko>*Vb8+vd@+!?TJJ+ zy$LL(ncW7%OJyPliI3@}8lz;y?Mb3p9jk))nu}fOlC;}({SaVz^#FSC?qBucSpt1{ z!`Jc(^SiwMh8hiUOM>0de@F~o!%iV%LrXbG{Q#i?R$!?n0TEp}uh_sb3P}ZVH8l#( ztM-g*I|u@C129sYKo8!f9Rx4Au9v^}-u-9X!oNZ+tp$BIZ`~NM+X`ep@?R%xLbJAE zSSTs!Pt_*>vYKhFHXk9H`1)?6S=!T8${1`z9-*gNr^k-W3O4<1pkf8QWe)vgtjfE` zcv`V+HHxRKPg6cIn!MLSl^L{WX7fw89DqP5t$T>a{VFtZMK2$z=bozRzKLrpe)&sA z&0B@@OlnuM2Tq^=O0?T%7w+oE+lj|^;R_~cy+SW|Yxn&(Q-aK95@&~V8j1Muyt_lKVR`H0QL@Silh!HE zMOV>T($E=_-IPt|F7n@+92bS5uyav-^k;i|#^0K{&8Gup+A(X3t2{rK)4c5IOml8# zo_ZwzG=p5$BDKf6&4Xj@YO>iF$aQI6<+}hfa~Of^eFydXzB9k!{M=Ffk#YYc0f{c5#4M&x8;MkwYYa#qsu zIcdWe*SCCc)KF!tY`TRA-n1;#w4xmhFO6WIR^G+Ld@o-5>3~0Ofh$BAIr*6l-?x=+ z51Dc|{L@DPyl@b>2ePQ)#hAYben0f~$0?+}s0{JifD)E84Q$=rG zgj(+%;NHLer1W3CYPz<2O<6cEx7w!lwjz%eHX2jFq=b5KC20pBfw75Ld)FR!P75WhT& z0yyg)aE1$T2jJIH1^#yg&M^g^=jz(4<9C4bz^`ipaSOx=e!nnbfK2lffW3zO2UZyh z@m6Z~Ms3+&)0MOgpAi~eTpFHv)8fX-g%fWI=H{;2;A zeKN2C&a(w|E zn4cGK^?ZekHfmZl94hS`9NJEz{g}s3h6a5wo1pi|F+;z{S*h=dtDHCOqr9M`SjA0~ z*C-stJ$!rt8Ul>Lq}k@4ji|-k@>Vz;PseQrdfmb&*Ts_p?iE0Y^Bk!`pMumUw$5EBaAq#D zXN2dq?>0WTEh& z0r0`iuKaK#KwxC9^y_sUpHf>5;qgsX1FkImxsK2Iqh$Z@tmE?oSkmBjn=2t4Lf$asp2NCfzAlS!`gR*ivZpF42gZn|pY_gyanS7r z)l!r|8Asb0^LL*QnG4W^gi)Bv)5hy?!Z19W1+fF%V-ObPMr=&k$PG^)TFph$r}E{& zjf?d4)9Ii(&sO%X)1d|9cJJs#kH8oM<$s2+)`DOAdl?c}a-vMMc%QrAd~}%?*mh!L z%|07$ZaWl)Sb*dF6vR}nRwRJu95W-1Mj_B%Q~YSXN;!d*!+2e*zY!+M%4&s=&e*jo z&;241XQ!M(?pv7{uIxJ~b`wIwhP0hB_j>b8uQsC&?42yrGgRAob!)s5=qda4;N%Bx z-PWN&_*cGz1W4>}Zu#G2>z8v8zkA33DXTP1xuVLcS!VR?;tcW2-!{!<_3n*3Gg^W80WwcJ@)t%2HD#xM7H!va`?X`{2|owPynf zQR}+~w_{RgytEmJ*hpvJLhy>mZ%NsWt1+bc?OVc-;f_Z=tQnnEpnsx3?Ck7zfS>V- z+zV}q1)&Uyg!w|KR09n?(U0eIrt-Emsu)4;5&G%fu9@fodc6Gyg<}_wFDrF{vZ2={#1XgfarJRWeU)h z7qIn6@h$KtBLB)g)-v6XD&-_XSCydJWG2XwZAm~|%y>i`hBlRn)QoJR0;l>V*WYckAAOh%btnTQOwuKdq5b^B=%?|Ojn|Oy z?jP>1LiibmqE!GiC4reLp%FUJB zLmm+7_V6jrCS4kgQ)`8tHAcU`LNqP9v_RQ+tK-XO_-s{TNU6I*-n8RgE2`=SwD526 zC>qL^#kai>zGpZD7bQYf+VW`Ftoa^3TzwPxA?-^_@cLHei~CsCWY5nGN?xb0*XU_` zwF*C$5-`(wk4!sDtlY8!nfrF+)>s}sA(BHIO2R0j(d1GT_kgFaA|Y>5eOE_W#epYH zW)&pziwgaR`vDwh`oig7@w3xj`YiYpF-YX_PU#PHJ>hQuSecAp(DJA{7IWxuJ(%UW#$Rs|LJs{;OA z*4g#ibq^oeR#9K+B*XQo7lhyNgz{?i?&aF7bv7DAd_pf9qDG&k6)+r7F6^jfc}_E; z4L|#M$U4NB^AiRtb_w-x=t`V-QLeBPwiD;!Gv97Aa)g8Lkp477Ow8(tvx`i2N!|R) zcpE}~Ubo*%+uVNo*)>SBxHR9#3Y+t54rtebo}Y%AG2uMn7WZEA99LoY(eX|Ux~aTR z`RJkgaco_tW;kAu0B5N#6~a+a(+2CjOlD23bOEg3JHfa>ktjQm?fLPk*>oO+<1NH&>t z^aAMauV0?eaqLb85-n%9d=0?aeaGAwdN@(=qPLK8g#=;Rn%?NL4R#1z z9S2mGYB|-&$0|w*qA9W6TYZ~IDEf=TO#`x{yhsCBNKu}Z!qEQKcMiBHe5<)O;_jFq zikw$dTjHX^H0-i;Al?qn4YD=qld zv*yzgkvClM*>Ln!b59FFDT0Ggz)I>*BFTI&>}}O zwLqT{){JtVD)+N%3MBE9h@s$~lvE5k4VhMD-bbT%N50>N$>!vd$2uXhO2Dhj=yWn= znvj(GhCF+{T8OEC9}>Gwcc`Nl$+%^vHp5)4A^%~u!y=t~V$8fL22>sw`jfFF&bza% zu}vXf#zHpJc}$zLvyh_piYqE%{WTR^Qev;)=*CQqF!?;)ZY^3tdWKdw2di4I(L-gx zVUw0-hCSUk?aAXEDj@$_HS&aJEyuki=t6^}@PRecJ1CmHYP$FLr(iTzI*@woK)eZz z%egq5hIsfIuk~vCxgwLk`Q06w zfbwUWX$~i4zEdWm>Fz>>iFG6~bW;|O5$!q_)t4IIC@2KPyL%gFlFila$&#TpDXH6~ z&o4YCdhD(;)Mb{mDMOg^dG-Ea$93NQIViB?KjOjb(Rx38VsY26fq%c<S&++_e*hcI$-)tgb>QIS$?6Oq)w}HB z1$(8xN#vy}r*B$H@%d8TK8wG)GBI|jUKxDQ{MHcGTRG45UWL#nO}}qW9(>S~Os2#T zjmPW8ZwChNM)jz$+b_ub5wKb7)CrphGA#v%tWt%?`Oa@cWtcRO9W*dSVBv+lVo&CK z$X?Vas3zJ;ldP#{owWJ7qnQt4X%oMs;bV^vWN;pbOp_`V7b%AqqGquVEl-K?ovHR9 z2c%}K-tas0m?vZ`J;|cE(?)dnRVP`azTk9A#p0IKx3$a`5p9>VoXNW5e{bHbAUI^a zyUQPvmTGHH+{x7CV(dv~*)n8x4W{Z0pSUshz4yp}cTg zEG7#_Tvc`=njr^vY8CPr<#_5&7jZKZji)#>BJ+1uhQ1JkG|`eOgF+{Q`>D)dvNX_+ zsXuOj+bBzVLX+PSRx6KfBQwN`teL9bKbSdfQ&UtmEshXI?|x*HFJX(!H#qL9!jbf9 zjtN91J3J=NM{Dq8-5{?!#dTQv9F!&*pHPa_6Xt9zZ_P4W=rImAWs`eH#9e>_n+kHc z%_`T-_&&EHvR%_7;r8Ttf9h(DGACN4+b1J-5h9->n*yI|PB^LO& z@eX?Jm5%~7KQ$G!Qdg9pJ3!Av34+{CiS5LPAYZIE^xZp{rrQ^I;<6`4qt{nCtkrQU z;Tf;CfgLw=`M+ws5dsN- zqZwpu&i{Bz49DNQa`^uJT{(Yh`2j~y{Cq$$<8q4Os%G$C|KgfH3CY3rHaUcta&w;HMT4v;ZpX)-rJS~Cx1ke5|HEcb-j!{+bs zPH#eB{`4vYoB5gbI^sc33DgsbSJcY#6T4`S&)9AIRvj|v;SX026g+b6KHm;IZ4B#E z->d4Xcz>Hjw+|O|foglmf@U}9?|!L3f7eJrEyRiS#Q)uw2WMTmUtb&EjS@?5usY5n z37%NYX}Q>Xw0duY4e{X3_(ma9>Q@@$FhwcW;KDAJ{Lyj`YX_$(+j4|mvn1Zt<}MI^ znfrho_p_mi_;;=K1P^7LZPcl_%vtL2vUK!n?&=6sBjX%k%~|FjlyR6FzPRl~AA{xn zTB@e}q5+VF=U4LZ6p)8&9&<#9?;n>S(fedCe!FLYlI=z_i0Y4s9|;9f%F5c#)4|2s z`N!-uGz!9H%de%q$yFOZFy#y|y8)#&up7g{dt>>(`K*7+y7gLp>HF}Zn#+|gh-|Z_ zbwhuFZVOY!WZ|(7o`)FavT?3%uh~M^i-$=U1a{Wc3rwa*GmAWIiSUiGLui|xbFMqfs70b6UbKrh&h-MUL z$r=@|8s6>z{-&1E`eUSY#MvdIY=@7sOQFcPx-XU8AK+Gh zs~>{vP@&LdNe{kCR4f#j zoCxj8Z0l5OlA4Jc-H5t&IH&%0c6H(dB0`$kN(XCYy%b$LU3-NFC|7WdhmjEGK%eYl zh`Ih^_&i(;a}1NZS+qS~>`$KKEjpp0q z&C8RQyd1`W%xYc9tr{S=g8x?i^3IKqNJ*KU6hsU*QAj8_60V+(;Hgw`H5Pt8PIewn zPGB6>9L&SS_oTyHGD8zZyq%=~YU+Yo~nLzmTzzQZI zU;FW@OOcwIhOC)rlI9GJQrvM9)5ShlR4&6fSKf2B59nW>u(haG$%WeSbMH!ll5f-O z*R83Yy)>yPDZn{dmrY@#9aR7!T*DZL0T5X^wA1qn;GCaY(5e})KA1^WSk73REGW7To_r3 z&B>U{S0Cd5`sOV*Cfc`{Y0kE7TVKCoo9J}qGu zz1NPVqll~yl@!uEjkOc(=;+a_b~@MHeep4Z4ZdA2heOMFbnk1%Eu*z(kOR*-pOPRo zCw4*SJJfNVgpF3asiz;v2Ue@)D2i>axMNFK=shE!U{eV4{?6E?-K_jA_Z-@Sh!L%` zkOD8|zGu;6teR$`C)8d>yX7G?%lk}cQ8Weg=@wHUSGRA3iJzuFXNhvOiKW5QH4W^i zgvxu-Cl4h^yl>FMD_ZLpgP!rcw2Kv2@>L4RSMrs7VM6pU$RJiX*hj>{GlaMg+j5Hl`r9$nD?*|YyiqPlCX zj7U>(JD(tEuq@?kdF`ybFg7>(Xvq;_8Y#L}bqA3`hD}Nsbm?Yz;YaPKjOnCGaLH$f5rU;g{djGw`?>Pr zTZ9|0@+6nP1Qz;ZD2u$4H!V{m?hn3zwU6Y2tNp?0df>uMd22d%+crPR;B@Jc_!tFPjtNZSMg-$_qoW;ZRV*2D3 zFNcxt-e{&D&6(!<6*;D=RBzUWf>v~CAM+&KDvbL%bNaL+VpKj)aME)htbKR1FkNi=}i}=UW(+A z-^*K4ATru83qQ_#zQ#lLg)$-C2t9$qRbJDLRKjss;=L1k*db&xe-0~NmE_+^nm=5w zYHoa=pqnmx;?R7VhsZQ93SH#FPKi)ci6YT9kBd`)OG`z-AL!{rZ zlR%7jji-x*jVfc|a5X(4XK%&|rX#%y@j%yHYJ3!bIpJSSPW+-N_<6-22-$y*N&saq zfRXpIkbPPB;sxN~et|~(&%O0ODV&dshNjx2oLT_o!s+M!@R;KF@-uJ|8|HEB>4kg= zWa&e!W=y-cUrJR)K5Az`k#nR>%`{_UT@#OS zNiw|_Rw#G2DN*aE?J8dblv-PAijs_92;vOkMlahSAKh3U}A|eX%{|h%1 zu$?c<;w-PRhcpAcy*yg-%9%6PcBbZ13=yr1*X*rgTAW&CO3>1<8sxv2kMhsaa=q_( zs}#744%0HNGJ zkLMHd^gFE55FvKeTyN;Cat9*qUQN<{Nx?4fulylfTHdvESE{?v-e^zyq;OHgjHowEp#yTWFPMvJq^P8 zOo+*HnYO=Z2Xgi`S9$wNAa9@kLm%|ESjgyCG^9ZoF2jwy%(chX+{c32UcbZ1s8Kxc5s;qoc=+fv;dk-uiHuiE@bO_*96DE z8Uil^VlJR`4FUmdBOG9~c+Q*4|Mb`YQ^J3N7JWN*I)c;H@@*NpuYi(W&L|tszL`ru zB&7}SMu-ah9XdTkNn6TXo8B?#Lu2dsfnBO)^0gxyD)xG2+`akl5H^w*;TGMsL>bR@ZNCb1r;3QetBwjt!3FMW`xm)=P`_3qg6;C%k?m9;4V+7x&Ji-*_3Nu`heVY~-#H~QM zY4P>`YuHEIGT0xgDd|%%kS1van_8u?Z-YeBgeJzvZMFsZmYCkBp*0e(!OQvcGM>15 z45@GF-OecpKueVD_@HNm)09^fOCuwu)8@oi1&nE5WV|y#(?Ke=K5DOmk@ixDC~sB! zTD!JzEL6ZgQu3Wr)%mkZ3#XM zAzF#}+kPdBH!UkPn?@`qr;-pSbI6Di89xyf^YW}LgiIRA5k|l*#DHX}=5TwOidyZJ zc?OT+f$6Xi-_wLnOXR}1LXs|?F-IBxDHYBJsoF-y&El)TP`oKVp*Ir4TcVL*GRhw2 zw$=+1t9nb~W)H>KLCclpj<|a2dy4=VDpz_54^vcTN@LFEK-7z4+DLufI<^>cJ5QQo zRjbYr?!|ktW@xmEV}wc^35?$a@G@Hu(5tHHK#HWwHGT?hJ;kv7L<0hA$)qe$x_0QBB(hta+kHdy#)a`#$A=`;fJi}qoi>r=-l2} z<^0yjrp96vJn92Lat=JhCoS;`-r1p9mgAi$_YW`DyDtZHUEQFShNJ*{UYWF)fb` z+DOTr(ZT2}n^{y`Vjt_-{Ipm3J&6ntiRjzp{xN-BUn^;it$Bj~!E%@0IB&TG+RPIo z2cHP_*Ld~|URJEf0&S>Igdzn!ij~ZQVJHzSWA}pOhV{;0yhRTVc`rf{dL%E*lzq;K zgs8X?c#N41*5F{id$X%KS)h*)`nr!0s0RJj`2__I-_Y37YU}_h_+_F4TU1V0T1iFv zvfl`Bs3hfXQ;4&G09ra;4jvGTsv^*6#HtCdA6c8Q$e1|0SXg^er~_oS+!VKYI4IQk z*nzG!@H4?<^NYKgn^2fr*itA0v^fCmmy?OTg#(2&aILAeIne#h2|WKLh5^NIPxzy6 z5r7(!1K5EaEx>J4e}ki!1H;i<|2%$aBY@E`PQXN5w=e?f`(MldAAjXPIgGXTQ&0vT z)^k{R=<^TK`racGazsA=;Fsm%UBPmK?0c$db}J1kEW^I;wiTwg}4NEpppN>8{LUDXFnyVp{QB#hegWw~H z)|rg~>N4|EEib)6kUZ}_Ukq;BBqfFv_}kHOx$g(l^O{*`Y8XF^ZBB`Dn7e%e{Pc4}9LY1Epo`k#i+^#G8 zx;7qNwzOQ~YWn8P+N&7fpELpi-c)`U*^{-)QSX2S30~yU7c~BF`Bl6C`V4G9sXxaX z?9SAJiZ_7*c4Mqe>1tVt1kg$ML>U((b)KSZmU|kD#ghzR^nT}q<0hXWVf|iNEy(Eg z@^0DtK@xn2&E5`-Ce7*9hrzjY7>@x9wQ-gASq0+9!E1j}tDn>1l|J68 z3?BYc0=w1xZ|@(-^oI5U!bi%>DmT#dNN_!KPod^u>*@jwg*a0vuqv=hvI1?%tYEbQ zjZOdeQ+`3E01S$*E>?hYa`C*>2LLn~pkXfmfQu+UQBuHjhyNA#@FxLXe(9G4vg@9R zV?us;dvKoq;q2_mDb}bEr*kz7+sg+rD|vNP#v(=rgNPSFD8!j}Rfy;!XU0qn2tQ(> zvmiZ|G{7I`N}||s9^zw$qeJv^IyzP1IDVBpYWQdgz)p}2v4q_nrNAYF{htCf*=zEzm-&$KzHG6VWPo};Y$8$zcI3PRw7 z(>wB&#MxKVyQSZqhh3s9B^nE*61r8JiT66-=|S^-P(0ghsK+l*sOEp9kkUYbDL1k= zl%T#dh;gO#sqklv!^NyG#Mp}!{+5OPn?$Pu`vXWi-2usgWb&o+CBww8lTKz%wqP1G zX9rtnXWPpT-0Lm$bCccJKtK1-C79V?t>&fJH<#a8tJnJM|BR*HStit`W4VxYc}-~j zK*z$p)=N(}mX>GUD~*+}UCTH)9WFSp(ap_4UIFSJGF;K7k3`9Wgzg){bs$mAwhn#wk z%?Wr-!7$v(-{oHKuX0ZTBD?ZB@PA-LgA>3eE}6qZ4?29ox5 zDhZ082u6tOPzPb6+0dt_i4l#Gs?7l}G$NzfPlxN>TE&GynNO%_@tr@BEsj2CY|-PR z9AmsQuHm~RpwTjJcOOdY{;G@*LT^yhY;m~oBfAEW=BsL`KqHpJ#Y_+ZL&Lq%e#nOo z8&T34ALer|ESd13ij;_KFp>T0z1Pw|#JD+h2u`ac`>hPek@GgRGpZ0A=cKc@OdtQzb9#=1VQ=MZS?Nt9?zZ z2xSSM2KKJn>E&KZu60>V?(Nf_B(2wZT+2OQkI;}6vaLM4AF%g)CY!eu->=Uve!Jqu z$zyYx$pokdD_}O+@M=C;7ih%pgo1)By!lpvsc&8Xssw%w2Fs{R1Nk8*M+YZ>=*_{N z{hIC;8Jq0#h$k@caFtvBskpE3cYfrX0MduwPP{@Yz056v)dSGe!v{nJ0GjY+PY)0u z084OB53v02x~+fJhLeh(U$?80{mH8*;_VDR8f#_BFtIS&*Od0ClpeU=gtXoUb0RN4 zTOqXtUIu4l|Ee@K_&l`}JMEN_idee{%YfCbs?;GT_BVwjPEGnyYvvMbCnd}u1W=#H zN<5>1tP(h1=sBkw&-(cWzrV637cl5S2>#WE; zxO4N~!F3CZzivHT5cZY*K>^zzuopl9lr4UMzaV2{fTwrBWUpX-aT$dE7@Nc<{&|Hs zK!*x0SIS9U(7Kwg=;c&*Ib z!>8{n0$3W6hFs4h3w>!$m#9#fUZ&zBbG8vGio+#9w4f+re21@HBeAE_V7EwX8O0wV zGu@xwuvLi>4MBN0RNoIh|HkeSjskJy%oaqYs!v6t?F&Back5UP?GTkDOqf&djyzfA zgP!3ZgB({8T^u#6D+;Xg+GgrJtM_soZ)qHqUZk4r_lY@>zH3cx9*tmZ&S`Vf)qEf* z`hNc%(szcPg6+wS3h2>z1L}6a) z=Z7y4SKN(zyUBcd{M~L>z~@=?vSliJ?7zF7aFa-9uv5Mm- zZ`y_vM78g;3GB2ly-y5#r?Lb+?d(4q$4!%vPWt+e1HlixL-^kzu?NBzE>3VS4v;GXiU|PF?IjA$fBFsl zNf;~roEn}$r>qvwBJw55V~T|r`{1`*;uO_*pl)vU4-&Gn9pvJ&lZP+j0rn)Ek9EkP!SWtoEv z>F=apj?)SvNO?*0#LKEL0;f*#F>x{dVhJ9>H^h<(OZ)#4;Nu$5|oL>sy(kvJ0m zmoWa-8~m5Z)i!*3bg{G1x_ioA>cNBrO9;U8mtcQjN07G#bpTf`V<85oU9npT2o@w>MlX6dS;uHc#~W!MU%Du zc7yxdL0j^&;D-dhXtg-}Azv8QSqgH!$-JC&gR4Cqc51#2BNb{Z-<~_O^VHc3p;9eJ zA2{<7T(fy2W76q$JemYU-arwuz@v`WBQ`4-<@|B38&P3ybL!%~n#7~NJyTMuV4<|v zCxoW-&n>9NM}@jq;;PgJmf1(M(tQMM)G~GV#l%D#ukZ<&kv1%jPYObdDgXDUbtB(J-1=3@7M{44TT>3`u zbAge*l64%mgjQ(P4!O5q&zBMIA!|iFmdI}y^S9Pd;HXMNeIx(zwg{9)q}mdZZa+^q zyyj8N5axkGGsqDpweTx{%(-(Qf^VcD2N_ifmGqs;d#s>=Jd5*h{edN4<^?MX!rn!0 zbV+-v7?iJ5x+Ez^>jcH8EUn9bS(B^8SvoZBA9HFUZyd?XfBW|mfq^Fxdg#B1<>;KFI(qUh(99=IlL0#AV@C2 z^9TJY%7eR+@L4KVR|t4CttnZbDBr&yCAwMYYQhg(ZlA(!RBISWCmssG2$>XGcl5r17~u=0`qLmO&oy% zn18rVQb|}{l9mH>8C+cLX<&7^Z-MU|;Ge~T|K#MDmH+8P89P&1W@QcGOK=gu{5Ug9 zNebV%HSp5hLi9$=scPZoV0IbfC|EnYh?<%>TZsOX+KL&U^V=p4z^D#BoW|U^f9Giu z!Q>G<{~>cLoU50W8ZOC({FdQ2>MHE~QN)X{Us>;qKk$6JXm?(&b3c@{L5V7J>mI-T zos?CLZ^*>a?j35__aY}5K1AJVO!Z>NUAW|t7Audq9z zKrC8Lip|q-dOI*T>X%yNFh6(O;LbQqYec8n>~W)HuqfC11RvolubDprEAV7BHYtL6 ze{Z3q+hkh&bx+n28qr%s8^4_M4!Kg zM8JW;udak2TsJ>J@1U_Ue_ns>nQ&aHFo4J&1Pmi`0RUN7?gl_^f4%%4cfWtaGHMzV zT_(gGPlfdVEJBO4eGBFOPBU-0fdB2}vP{fg=7_jeWEkxW6ps4O>avgBI0PifGIQS| zL0a;lql(5yMM0tr-k~52;w62PtOlFA+H_t!0pbza<}UN9r=k0*U#~QXPEA~uDJCrAsTu1>9jH3Ztqer}xLCUN} zCNvPEooq%g`|EEDkKOu*5h03W$_~k|$pT^1CR8mbKCIAD9Z&=dBJ5nODl8+ISPZ40(U@L@e%M^d*)N zqza(e6#lN*kim)y9R>zSLEY49f(wDf`K6+QltE*QSmos^r8tGypui^Z$-tC37?dvn z=bz4b6qx)ZFyVjN76}5{6I8(WP5}cX*+9~8$d`NqCzwc((2xKaD%Xv?8^aA9ZE-DI zmx*@(aS5y?IWBRR9L?|jCdQY6lSA?IFqfvAH>COa>sh* zTdA&#%LZNu2gZ`dcz@UF^E`gs^(ADBi@)m_CJpc0wt_Ps;+9}7@5j$sCAkBe{4&{E zLHQd9kQv<{?o={CoFF;{PL>~&^D^>0&>W72#Gzv>)AlbzKokVE@9u}$`a*jMv&Tb- zKMr7cD3N?tCtH)~D%|QNku3mc9bQaT?S5KfX?H((t994?-5+*H&jw=HwiYzvK7bDc3k80 z%YJ+R{>q326xPTiMs=zUT$Ls3gFG4SH zJ_KNZ0Y3{gHqF&p*IBi{s>Pp$lS|zPz_9@i94|W;hzqRy08V(|FE=MI`|q?}|6Mov zCtog|hO7m*rfIGxrjWjl57~OZPU$H#D?R%JK6mLm}+C%#RM_KhWj6f@fbfD0|nVl z+7F{+!EmM-DVyl-E}tZpu8|79{4{iMpM}e3QPzYcZr?;|z#(70B&AYuYORFJ%Zcx) z_<&Ffrtjz8qL})y{x_V0lft~wXI>&<%xli$NLtU$vj{&Qpu-?UJ%`38G(XU#rHbWZ zuKH?4ie)z%MTRrg6<@SS9XjTP+F~=mzPX9tEJ1AfjCM;pnDSdkpU;@7$m!l|meKR~ z7FWI;kem$629jhyxI=KDVBpALAS5BgZ=&ml{aq#gN}hKsKNf~F3qi~tG+l;y9;;uw zUPt_|$%X#5P1&?%u3N$}e%=YdVgk8pFD@kF)>YI;_O6<1F%2hUe# zoOi=W(G82InSA_FAk1xw0%p6CTu49BTZ0hEbLV|Y&XJMkxob?zB#F!;jf1{}4(u7D ztF0qs3A>0mp8C|KiX&5$=Hl!PXtoJ7PqOqM#5Xnjkq}SY z1fWyCT%Rtg7dxnmE_t!M1JHj7TW4%PWhht>s@|=_%pUR)Tb)^x^nE-bP+Jna$Cc6b z9%BLS95Dn#aJx(4V3XcQ;+2a}P!wWc4K(dbumX_AufTR49!!d<&P6xv*u!Vdx_o;ZPdMF55Y9J}3I zg8q+R;7@{E7V0~QbDLlfCYLh0baJGtREQENv^m5l&)>_xj41V!~Pk9E0pek>UrtFZ1heBRHvW`9v6Lua%V#49L zQ|OISp!u~ErIur!!O%>}w`HGN2!0C@cd3L<_OUwgftIo(648-dXgk?wMvoBs=Jmp< z_i|lHqiccBT~dVV9Xf9vOWF9PG85~B69*^Wl27C!#4>Oq$bJ{F^fC&{*voK>kow4Z zLYj+1Eo=dKh$OjRp``hpX#r*ldBvl;<#Lfb%+v`8uAbWR?7HMN*ybe^TFtkm{f_%e zDB!um^>nTT7u@~+w+i_$q1+ALaPAe=%hKaDI#h_)Jvs=JZTTlr3LzeJOiK&VnVoX+ zOVc}kLNIGvv?B3z-Ab+s@?lkZjn?0iUPg++F z#8wz0U@HF-LUfPr-FDyVN00EkMT#8T`n$sH@9I&y_$DAV^hp>|BU;@hgZuUD*X-gd z+wI7GREq))rqhTfbk0)HAWM3`!M~Cj!~1srj3+hY+)X`gj;-+JV`JqyWJ8BSBIOhA z{M-p@IRnCr;-FN$+Zf-OSw5=1KPA}d!1!waC1mV7-Xe;h!>p{v(^q7-M4s+OrxDn{ zUN5g;f!|2{tira~N|?KSq)uMxulXGUv*w%2c$bI%{REzc3l+cy%Us!ENx%*> zUB@54>m88)jqpQ8;>S=E0t%K4fO86jrxc1N_GVTVK);;R&qxFXUd_bzo`aM5k4ORu z1rwNoaxixQ7qk_u?SQ5^^Pf2rfGZPR0R_)R{R~Hb5pP}@-AgMAeDc>5>z6r`Yp%@y z_8a_@+|E64;L%po-Q!W$3g~h{px7etXCz(a&LpFKp1tzW&q*~OS7KUc#@vf&xWRjd zANQq(Y}b|m#0EQN)7}FYBFly$&Vi@w6$MM<{%xEr3N}KU(Va;nYVI^H+3@y`-&&CM z+?tH`F2;H9$Qyec?Vi4Itl7|cRxl{bR?=C8?1%4!hf)NOLd-YRXId|spIjI&zE|%k z=04GiX7|WJv;Yo_=KHON0sF(VMP}_5f93m3N5(YTG=p?IT!{i> zOM$~xyD(7Wdi5en&+lVJod9D)f{AkaRiD*1j`L)~w%bzM+u`y?^b9eH4|-s@Z;fc^ zFK=B_eFgS`0=sWyMqYbsw`@((T8|v*;61J8X!oYqJNR=eOkgnBQ74D-0eOLh@&)qw z!gy}o ziq*2v*5&iHtu4{YbG{Zbi?<2E-Cx!ju*3NB(1CpJ00!zwp0r5s#3|2hDHYM6v_x`- zX#&g`#$}6OEi9}Ue9;u1?*^6aFz(n52e@ORd;=*08pF@i51Sy2=EDdBJ=hr9{YD2Q zkPgdL^52PcKYFk!nokjPPav`;?)}6IMOv9{wus)^1z73!R-6a3UgvS%zKRGB3$dJc zS>Eu{yI|2P^w*`WPnILt>GF%sz{KJtxJ<@gVi8;||2uE(Pb#Gk6JmjUI7w!mjg-WckLa7MtZ=4&h%d^$ zE*;$cQ)E-@+KUg)ODq8*913L|k7;*uS!Pc1%dnv82?Uqj;FtmoPo);6EnzWY(Jgvn z^QDFPQEPX!bvd@)&!^D&4jpVw+*+=?ujOP26$8 z+mf!KLUwzJhG@+YTbmDe9)I#h;{%BmacNU$%}A|`FaC&x#>k6+$d-3^Alz9Kn{7W$ zQ?22ynp4n)n&qP!j%Eu4>-#gBsiiL@YF)Vkz98?vy8`@R1wjD=b`w~EL4!cRmj=;- zaBsx$i0rH!temV|tlYrR!VerFC=kTow9hZELOE*6?ZVQXIGP8XRhn-kBd#3h=tS?riO0Ps)KjT+52ydVm-Yx5=4buORGwzz!TeRn>Xq z3rVEGkmRkfsN!N8SZR>lA3lQ6l)(!B#r`?Ui#gjjuX|@J$73Q4lS-!p7xzVq?w_X3 zoi)WnEed$JmAZy^eIkP6T9c*Tjd($GpsOVyLpWswILa!Tt@R1{E5!(No5RlJC; z#XlzvL~O18LK6HS%}L`G9`!s-uGKcuD_p%-AB7iqMGaqMdt-cZ&XAa`q*^*8EQL=; z2K;jfKo9I+>46?6@STV{?nl4brBTEYl=HrdjSIeqgNgt8%fQ~!NtYd+{D)6 zhtq(BO#lh5A6Oboth$9@c2-r*?F(254W$yOH5ts?A_wO!-nZzQ zOH5388R}RVzhZ=$_c<1il-1vI^xP1dGNa8qx2gwiI-a>k)!P|cR+05Ku1`F5fQq(6 zRix8;Fh%jLLtZ8J1w+$ievbl>f9$Kc0t}FU^iT2+F2P#;)$m^zQ2!*?fLgzD2yXq7 z>z`%VpV7nL8zcZyE1*Z77hn_R0gLm^<$vLw{HYdE&(ZsR{Xr2-Xc-Eo`P`u5PA@b; zxagzOGohlq-Ofi-?-iFWm_NXPTlvlaDwxhUin!JTmbd+o&P#Kro~M>cHI{d0I)W_4ZHlQRb_g(f&9oIGQi z@$Odqgs}LtGQQCfp0D{B{ZoGF*mOqR(ARskA>*Zzb!q1{7pc@w($m#sHFDRy*c&OU zt@7T8Jt@PXUnb^g(-}Ho@{4&jYD!DWEwzZtp@5}#1ML2G7 zX6_5GJoZz!$}FuA9q`NP4cqk+Bx^=f`8_aYMzYs8dnzmnZNn)4d%)@aI+2XGx?Ns8Ecv@U<8H{VX16yd+_wH$KmC9;r%eC3 zqG`6qVFi1poxX9kR$*52e5pH@ACDF-7G(Zw?G&VW`vv3o*>OGBdfWUYf9;XkcT{m{ z`@9N0v)i17i;GNtyz}J$e*o5Ah@1cb literal 0 HcmV?d00001 diff --git a/sbr b/sbr new file mode 100755 index 00000000..0f77bb12 --- /dev/null +++ b/sbr @@ -0,0 +1,25 @@ +#!/bin/zsh + +if [ $# -lt 1 ]; then + echo 1>&2 "$0: must supply ssh port numbers of devices to update, e.g. 10873, 12873, etc." + echo 1>&2 "$0 10873 12873 15873" + exit 2 +fi + +for port in "$@" +do + echo "Copying roots to port: $item" + RSYNC_PASSWORD=alpine rsync -av /tmp/securitysoscircle.roots.tgz rsync://root@localhost:$port/root/var/mobile/ + RSYNC_PASSWORD=alpine rsync -av ~/bin/sosinstallroot rsync://root@localhost:$port/root/usr/local/bin/sosinstallroot +done + +udids=( 79003b34516ba80b620e3d947e7da96e033bed48 96476595e5d0ef7496e8ff852aedf4725647960b ) + +for U in $udids +do + echo "updating device $U" + PurpleExec --target $U /usr/local/bin/mobile_install rebuild internal + PurpleExec --target $U chmod +x /usr/local/bin/sosinstallroot + PurpleExec --target $U script /var/log/myscript.log /usr/local/bin/sosinstallroot +done + diff --git a/sec/SOSCircle/CKBridge/SOSCloudKeychainClient.c b/sec/SOSCircle/CKBridge/SOSCloudKeychainClient.c deleted file mode 100644 index 303acbfb..00000000 --- a/sec/SOSCircle/CKBridge/SOSCloudKeychainClient.c +++ /dev/null @@ -1,757 +0,0 @@ -/* - * Copyright (c) 2012 Apple Computer, 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@ - */ - -/* - SOSCloudTransport.c - Implementation of the transport layer from CKBridge to SOSAccount/SOSCircle - These are the exported functions from CloudKeychainProxy -*/ - -/* - This XPC service is essentially just a proxy to iCloud KVS, which exists since - the main security code cannot link against Foundation. - - See sendTSARequestWithXPC in tsaSupport.c for how to call the service - - The client of an XPC service does not get connection events, nor does it - need to deal with transactions. -*/ - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "SOSCloudKeychainConstants.h" -#include "SOSCloudKeychainClient.h" - -static CFStringRef sErrorDomain = CFSTR("com.apple.security.sos.transport.error"); - -#define SOSCKCSCOPE "sync" - -// MARK: ---------- SOSCloudTransport ---------- - -/* SOSCloudTransport, a statically initialized transport singleton. */ -static SOSCloudTransportRef sTransport = NULL; - -static SOSCloudTransportRef SOSCloudTransportCreateXPCTransport(void); - -void SOSCloudKeychainSetTransport(SOSCloudTransportRef transport) { - sTransport = transport; -} - -/* Return the singleton cloud transport instance. */ -static SOSCloudTransportRef SOSCloudTransportDefaultTransport(void) -{ - static dispatch_once_t sTransportOnce; - dispatch_once(&sTransportOnce, ^{ - if (!sTransport) - SOSCloudKeychainSetTransport(SOSCloudTransportCreateXPCTransport()); - }); - return sTransport; -} - - -// MARK: ----- utilities ----- - -static CFErrorRef makeError(CFIndex which) -{ - CFDictionaryRef userInfo = NULL; - return CFErrorCreate(kCFAllocatorDefault, sErrorDomain, which, userInfo); -} - -// MARK: ----- DEBUG Utilities ----- - -//------------------------------------------------------------------------------------------------ -// DEBUG only -//------------------------------------------------------------------------------------------------ - -static void describeXPCObject(char *prefix, xpc_object_t object) -{ -//#ifndef NDEBUG - // This is useful for debugging. - if (object) - { - char *desc = xpc_copy_description(object); - secdebug(SOSCKCSCOPE, "%s%s\n", prefix, desc); - free(desc); - } - else - secdebug(SOSCKCSCOPE, "%s\n", prefix); -//#endif -} - -static void describeXPCType(char *prefix, xpc_type_t xtype) -{ - // Add others as necessary, e.g. XPC_TYPE_DOUBLE -#ifndef NDEBUG - // This is useful for debugging. - char msg[256]={0,}; - if (XPC_TYPE_CONNECTION == xtype) - strcpy(msg, "XPC_TYPE_CONNECTION"); - else if (XPC_TYPE_ERROR == xtype) - strcpy(msg, "XPC_TYPE_ERROR"); - else if (XPC_TYPE_DICTIONARY == xtype) - strcpy(msg, "XPC_TYPE_DICTIONARY"); - else - strcpy(msg, ""); - - secdebug(SOSCKCSCOPE, "%s type:%s\n", prefix, msg); -#endif -} - -// MARK: ---------- SOSXPCCloudTransport ---------- - -typedef struct SOSXPCCloudTransport *SOSXPCCloudTransportRef; -struct SOSXPCCloudTransport -{ - struct SOSCloudTransport transport; - xpc_connection_t serviceConnection; - dispatch_queue_t xpc_queue; -}; - -static bool xpc_event_filter(const xpc_connection_t peer, xpc_object_t event, CFErrorRef *error) -{ - // return true if the type is XPC_TYPE_DICTIONARY (and therefore something more to process) - secdebug(SOSCKCSCOPE, "handle_connection_event\n"); - xpc_type_t xtype = xpc_get_type(event); - describeXPCType("handle_xpc_event", xtype); - if (XPC_TYPE_CONNECTION == xtype) - { - secdebug(SOSCKCSCOPE, "handle_xpc_event: XPC_TYPE_CONNECTION (unexpected)"); - // The client of an XPC service does not get connection events - // For now, we log this and keep going - describeXPCObject("handle_xpc_event: XPC_TYPE_CONNECTION, obj : ", event); -#if 0 - if (error) - *error = makeError(kSOSOUnexpectedConnectionEvent); // FIX - assert(true); -#endif - } - else - if (XPC_TYPE_ERROR == xtype) - { -#ifndef NDEBUG - const char *estr = xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION); -#endif - secdebug(SOSCKCSCOPE, "default: xpc error: %s\n", estr); -#if 0 // just log for now - CFStringRef errStr = CFStringCreateWithCString(kCFAllocatorDefault, estr, kCFStringEncodingUTF8); - CFMutableDictionaryRef userInfo = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (errStr) - CFDictionaryAddValue(userInfo, kCFErrorLocalizedDescriptionKey, errStr); - if (error) - *error = CFErrorCreate(kCFAllocatorDefault, sErrorDomain, kSOSOXPCErrorEvent, userInfo); - CFReleaseSafe(errStr); - CFReleaseSafe(userInfo); -#endif - } - else - if (XPC_TYPE_DICTIONARY == xtype) - { - secdebug(SOSCKCSCOPE, "received dictionary event %p\n", event); - return true; - } - else - { - secdebug(SOSCKCSCOPE, "default: unexpected connection event %p\n", event); - describeXPCObject("handle_xpc_event: obj : ", event); - if (error) - *error = makeError(kSOSOUnexpectedXPCEvent); - } - return false; -} - -static bool handle_xpc_event(SOSXPCCloudTransportRef transport, xpc_object_t event) -{ - CFErrorRef localError = NULL; - // See - secerror(">>>>> handle_connection_event via event_handler <<<<<, WTF?"); - bool result = false; - if ((result = xpc_event_filter(transport->serviceConnection, event, &localError))) - { - const char *operation = xpc_dictionary_get_string(event, kMessageKeyOperation); - if (!operation || strcmp(operation, kMessageOperationItemChanged)) // some op we don't care about - { - secdebug(SOSCKCSCOPE, "operation: %s", operation); - return result; - } - - xpc_object_t xrv = xpc_dictionary_get_value(event, kMessageKeyValue); - if (!xrv) - { - secdebug(SOSCKCSCOPE, "xrv null for kMessageKeyValue"); - return result; - } - describeXPCObject("xrv", xrv); - - CFDictionaryRef returnedValues = _CFXPCCreateCFObjectFromXPCObject(xrv); - secdebug(SOSCKCSCOPE, "returnedValues: %@", returnedValues); - - SOSCloudKeychainHandleUpdate(returnedValues); - - CFReleaseNull(returnedValues); - } - CFReleaseSafe(localError); - - return result; -} - -static void SOSXPCCloudTransportInit(SOSXPCCloudTransportRef transport) -{ - secdebug(SOSCKCSCOPE, "initXPCConnection\n"); - - transport->xpc_queue = dispatch_queue_create(xpcServiceName, DISPATCH_QUEUE_SERIAL); - - transport->serviceConnection = xpc_connection_create_mach_service(xpcServiceName, transport->xpc_queue, 0); - - secdebug(SOSCKCSCOPE, "serviceConnection: %p\n", transport->serviceConnection); - - xpc_connection_set_event_handler(transport->serviceConnection, ^(xpc_object_t event) - { - secdebug(SOSCKCSCOPE, "xpc_connection_set_event_handler\n"); - handle_xpc_event(transport, event); - }); - - xpc_connection_resume(transport->serviceConnection); - xpc_retain(transport->serviceConnection); -} - -static void talkWithKVS(SOSXPCCloudTransportRef transport, xpc_object_t message, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - __block CFErrorRef error = NULL; - __block CFTypeRef object = NULL; - - dispatch_block_t callback = ^{ - if (replyBlock) - replyBlock(object, error); - if(object) - CFReleaseNull(object); - if (error) - { - secerror("callback error: %@", error); - CFReleaseNull(error); - } - dispatch_release(processQueue); - }; - - require_action(transport->serviceConnection, xit, error = makeError(kSOSConnectionNotOpen)); - require_action(message, xit, error = makeError(kSOSObjectNotFoundError)); - dispatch_retain(processQueue); - - xpc_connection_send_message_with_reply(transport->serviceConnection, message, transport->xpc_queue, ^(xpc_object_t reply) - { - if (xpc_event_filter(transport->serviceConnection, reply, &error) && reply) - { - describeXPCObject("getValuesFromKVS: reply : ", reply); - if (error) - secerror("Error from xpc_event_filter: %@", error); - xpc_object_t xrv = xpc_dictionary_get_value(reply, kMessageKeyValue); - if (xrv) - { - describeXPCObject("talkWithKVS: xrv: ", xrv); - /* - * The given XPC object must be one that was previously returned by - * _CFXPCCreateXPCMessageWithCFObject(). - */ - object = _CFXPCCreateCFObjectFromXPCObject(xrv); // CF object is retained; release in callback - secnotice("talkwithkvs", "converted CF object: %@", object); - } - else - secerror("missing value reply"); - - xpc_object_t xerror = xpc_dictionary_get_value(reply, kMessageKeyError); - if (xerror) - error = SecCreateCFErrorWithXPCObject(xerror); // use SecCFCreateErrorWithFormat? - } - dispatch_async(processQueue, callback); - }); - return; - -xit: - secerror("talkWithKVS error: %@", error); - if (replyBlock) - dispatch_async(processQueue, callback); - CFReleaseSafe(error); -} - -// MARK: ---------- SOSXPCCloudTransport Client Calls ---------- - -/* Concrete function backend implementations. */ -static void SOSCloudTransportSetItemsChangedBlock(SOSCloudTransportRef transport, - CloudItemsChangedBlock itemsChangedBlock) { - if (transport->itemsChangedBlock != itemsChangedBlock) - { - if (transport->itemsChangedBlock) - Block_release(transport->itemsChangedBlock); - transport->itemsChangedBlock = Block_copy(itemsChangedBlock); - } -} - -/* Virtual function backend implementations. */ -static void SOSCloudTransportPut(SOSCloudTransportRef transport, CFDictionaryRef values, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; - secdebug(SOSCKCSCOPE, "%@", values); - CFErrorRef error = NULL; - xpc_object_t message = NULL; - xpc_object_t xobject = NULL; - require_action(values, xit, error = makeError(kSOSObjectNotFoundError)); - - message = xpc_dictionary_create(NULL, NULL, 0); - xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion); - xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationPUTDictionary); - - xobject = _CFXPCCreateXPCObjectFromCFObject(values); - require_action(xobject, xit, error = makeError(kSOSObjectCantBeConvertedToXPCObject)); - xpc_dictionary_set_value(message, kMessageKeyValue, xobject); - xpc_release(xobject); - - talkWithKVS(xpcTransport, message, processQueue, replyBlock); - xpc_release(message); - return; - -xit: - if (replyBlock) - replyBlock(NULL, error); - CFReleaseSafe(error); -} - -/* Get from KVS */ -static void SOSCloudTransportGet(SOSCloudTransportRef transport, CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; - secdebug(SOSCKCSCOPE, "%@", keysToGet); - CFErrorRef error = NULL; - xpc_object_t xkeysOfInterest = xpc_dictionary_create(NULL, NULL, 0); - xpc_object_t xkeysToGet = keysToGet ? _CFXPCCreateXPCObjectFromCFObject(keysToGet) : xpc_null_create(); - - require_action(xkeysToGet, xit, error = makeError(kSOSObjectNotFoundError)); - - if (keysToGet) // don't add if nulll; will call getall - xpc_dictionary_set_value(xkeysOfInterest, kMessageKeyKeysToGet, xkeysToGet); - - xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); - xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion); - xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationGETv2); - xpc_dictionary_set_value(message, kMessageKeyValue, xkeysOfInterest); - - talkWithKVS(xpcTransport, message, processQueue, replyBlock); - xpc_release(xkeysToGet); - xpc_release(xkeysOfInterest); - xpc_release(message); - return; - -xit: - if(xkeysOfInterest) - xpc_release(xkeysOfInterest); - if(xkeysToGet) - xpc_release(xkeysToGet); - if (replyBlock) - replyBlock(NULL, error); - CFReleaseSafe(error); -} - -static void SOSCloudTransportRegisterKeys(SOSCloudTransportRef transport, CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock, CloudItemsChangedBlock notificationBlock) -{ - SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; - secdebug(SOSCKCSCOPE, "%@", keysToGet); - xpc_object_t xkeysOfInterest = xpc_dictionary_create(NULL, NULL, 0); - xpc_object_t xkeysToRegister = keysToGet ? _CFXPCCreateXPCObjectFromCFObject(keysToGet) : xpc_null_create(); - xpc_dictionary_set_value(xkeysOfInterest, kMessageKeyKeysToGet, xkeysToRegister); - - xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); - xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion); - xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationRegisterKeysAndGet); - xpc_dictionary_set_value(message, kMessageKeyValue, xkeysOfInterest); - - SOSCloudTransportSetItemsChangedBlock(transport, notificationBlock); - talkWithKVS(xpcTransport, message, processQueue, replyBlock); - xpc_release(xkeysOfInterest); - xpc_release(xkeysToRegister); - xpc_release(message); -} - -// -// Handles NULL by seting xpc_null. -static void SecXPCDictionarySetCFObject(xpc_object_t xdict, const char *key, CFTypeRef object) -{ - xpc_object_t xpc_obj = object ? _CFXPCCreateXPCObjectFromCFObject(object) : xpc_null_create(); - xpc_dictionary_set_value(xdict, key, xpc_obj); - xpc_release(xpc_obj); -} - -static bool SOSCloudTransportUpdateKeys(SOSCloudTransportRef transport, - bool getNewKeysOnly, - CFArrayRef alwaysKeys, - CFArrayRef afterFirstUnlockKeys, - CFArrayRef unlockedKeys, - CFErrorRef *error) -{ - __block bool success = true; - dispatch_queue_t processQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - - CloudKeychainReplyBlock replyBlock = ^(CFDictionaryRef returnedValues, CFErrorRef returnedError) - { - if (returnedError) { - success = false; - if (error) { - *error = returnedError; - CFRetain(*error); - } - } - CFReleaseSafe(returnedError); - }; - - SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; - - xpc_object_t xkeysOfInterest = xpc_dictionary_create(NULL, NULL, 0); - xpc_dictionary_set_bool(xkeysOfInterest, kMessageKeyGetNewKeysOnly, getNewKeysOnly); - SecXPCDictionarySetCFObject(xkeysOfInterest, kMessageKeyKeysToGet, alwaysKeys); - SecXPCDictionarySetCFObject(xkeysOfInterest, kMessageKeyKeysRequireFirstUnlock, afterFirstUnlockKeys); - SecXPCDictionarySetCFObject(xkeysOfInterest, kMessageKeyKeysRequiresUnlocked, unlockedKeys); - - xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); - xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion); - xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationRegisterKeysAndGet); - xpc_dictionary_set_value(message, kMessageKeyValue, xkeysOfInterest); - - talkWithKVS(xpcTransport, message, processQueue, replyBlock); - xpc_release(message); - xpc_release(xkeysOfInterest); - - return success; -} - -static void SOSCloudTransportUnregisterKeys(SOSCloudTransportRef transport, CFArrayRef keysToUnregister, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; - secdebug(SOSCKCSCOPE, "%@", keysToUnregister); - xpc_object_t xkeysOfInterest = xpc_dictionary_create(NULL, NULL, 0); - xpc_object_t xkeysToUnregister = keysToUnregister ? _CFXPCCreateXPCObjectFromCFObject(keysToUnregister) : xpc_null_create(); - xpc_dictionary_set_value(xkeysOfInterest, kMessageKeyKeysToGet, xkeysToUnregister); - - xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); - xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion); - xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationUnregisterKeys); - xpc_dictionary_set_value(message, kMessageKeyValue, xkeysOfInterest); - - talkWithKVS(xpcTransport, message, processQueue, replyBlock); - xpc_release(xkeysOfInterest); - xpc_release(xkeysToUnregister); - xpc_release(message); -} - -static void SOSCloudTransportGetAll(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - secdebug(SOSCKCSCOPE, "start"); - SOSCloudTransportGet(transport, NULL, processQueue, replyBlock); -} - -static void SOSCloudTransportSync(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; - secdebug(SOSCKCSCOPE, "start"); - xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); - xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion); - xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationSynchronize); - talkWithKVS(xpcTransport, message, processQueue, replyBlock); - xpc_release(message); -} - -static void SOSCloudTransportSyncAndWait(SOSCloudTransportRef transport, CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; - secdebug(SOSCKCSCOPE, "%@", keysToGet); - xpc_object_t xkeysOfInterest = xpc_dictionary_create(NULL, NULL, 0); - - xpc_object_t xkeysToRegister = keysToGet ? _CFXPCCreateXPCObjectFromCFObject(keysToGet) : xpc_null_create(); - xpc_dictionary_set_value(xkeysOfInterest, kMessageKeyKeysToGet, xkeysToRegister); - xpc_release(xkeysToRegister); - xkeysToRegister = NULL; - - xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); - xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion); - xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationSynchronizeAndWait); - xpc_dictionary_set_value(message, kMessageKeyValue, xkeysOfInterest); - xpc_release(xkeysOfInterest); - xkeysOfInterest = NULL; - - talkWithKVS(xpcTransport, message, processQueue, replyBlock); - xpc_release(message); -} - -static void SOSCloudTransportClearAll(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; - secdebug(SOSCKCSCOPE, "start"); - xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); - xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion); - xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationClearStore); - talkWithKVS(xpcTransport, message, processQueue, replyBlock); - xpc_release(message); -} - -static void SOSCloudTransportRemoveObjectForKey(SOSCloudTransportRef transport, CFStringRef keyToRemove, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; - secdebug(SOSCKCSCOPE, "start"); - CFErrorRef error = NULL; - xpc_object_t message = NULL; - xpc_object_t xkeytoremove = NULL; - - require_action(keyToRemove, xit, error = makeError(kSOSObjectNotFoundError)); - - message = xpc_dictionary_create(NULL, NULL, 0); - xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion); - xpc_dictionary_set_string(message, kMessageKeyOperation, kOperationRemoveObjectForKey); - - xkeytoremove = _CFXPCCreateXPCObjectFromCFObject(keyToRemove); - require_action(xkeytoremove, xit, error = makeError(kSOSObjectCantBeConvertedToXPCObject)); - xpc_dictionary_set_value(message, kMessageKeyKey, xkeytoremove); - xpc_release(xkeytoremove); - - talkWithKVS(xpcTransport, message, processQueue, replyBlock); - xpc_release(message); - return; - -xit: - if(xkeytoremove) - xpc_release(xkeytoremove); - if(message) - xpc_release(message); - if (replyBlock) - replyBlock(NULL, error); - CFReleaseSafe(error); -} - -static void SOSCloudTransportLocalNotification(SOSCloudTransportRef transport, CFStringRef messageToUser, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; - secdebug(SOSCKCSCOPE, "start"); - xpc_object_t xLocalNotificationDict = xpc_dictionary_create(NULL, NULL, 0); - char *headerKey = CFStringToCString(kCFUserNotificationAlertHeaderKey); - char *message = CFStringToCString(messageToUser); - xpc_dictionary_set_string(xLocalNotificationDict, headerKey, message); - - xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0); - xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion); - xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationUILocalNotification); - xpc_dictionary_set_value (xpcmessage, kMessageKeyValue, xLocalNotificationDict); - xpc_release(xLocalNotificationDict); - - talkWithKVS(xpcTransport, xpcmessage, processQueue, replyBlock); - - free(headerKey); - free(message); - xpc_release(xpcmessage); -} - -static void SOSCloudTransportSetParams(SOSCloudTransportRef transport, CFDictionaryRef paramsDict, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - secdebug(SOSCKCSCOPE, "start"); - SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; - - xpc_object_t xParamsDict = paramsDict ? _CFXPCCreateXPCObjectFromCFObject(paramsDict) : xpc_null_create(); - - xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0); - xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion); - xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationSetParams); - xpc_dictionary_set_value (xpcmessage, kMessageKeyValue, xParamsDict); - xpc_release(xParamsDict); - - talkWithKVS(xpcTransport, xpcmessage, processQueue, replyBlock); - - xpc_release(xpcmessage); -} - -static void SOSCloudTransportRequestSyncWithAllPeers(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - secdebug(SOSCKCSCOPE, "start"); - SOSXPCCloudTransportRef xpcTransport = (SOSXPCCloudTransportRef)transport; - - xpc_object_t xpcmessage = xpc_dictionary_create(NULL, NULL, 0); - xpc_dictionary_set_uint64(xpcmessage, kMessageKeyVersion, kCKDXPCVersion); - xpc_dictionary_set_string(xpcmessage, kMessageKeyOperation, kOperationRequestSyncWithAllPeers); - - talkWithKVS(xpcTransport, xpcmessage, processQueue, replyBlock); - - xpc_release(xpcmessage); -} - -static SOSCloudTransportRef SOSCloudTransportCreateXPCTransport(void) -{ - SOSXPCCloudTransportRef st; - st = calloc(1, sizeof(*st)); - st->transport.put = SOSCloudTransportPut; - st->transport.registerKeys = SOSCloudTransportRegisterKeys; - st->transport.updateKeys = SOSCloudTransportUpdateKeys; - st->transport.unregisterKeys = SOSCloudTransportUnregisterKeys; - st->transport.get = SOSCloudTransportGet; - st->transport.getAll = SOSCloudTransportGetAll; - st->transport.synchronize = SOSCloudTransportSync; - st->transport.synchronizeAndWait = SOSCloudTransportSyncAndWait; - st->transport.clearAll = SOSCloudTransportClearAll; - st->transport.removeObjectForKey = SOSCloudTransportRemoveObjectForKey; - st->transport.localNotification = SOSCloudTransportLocalNotification; - st->transport.setParams = SOSCloudTransportSetParams; - st->transport.requestSyncWithAllPeers = SOSCloudTransportRequestSyncWithAllPeers; - SOSXPCCloudTransportInit(st); - return &st->transport; -} - -// MARK: ---------- SOSCloudKeychain concrete client APIs ---------- -void SOSCloudKeychainSetItemsChangedBlock(CloudItemsChangedBlock itemsChangedBlock) -{ - secdebug(SOSCKCSCOPE, "start"); - SOSCloudTransportSetItemsChangedBlock(SOSCloudTransportDefaultTransport(), - itemsChangedBlock); -} - -// MARK: ---------- SOSCloudKeychain virtual client APIs ---------- - -void SOSCloudKeychainPutObjectsInCloud(CFDictionaryRef objects, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); - if (cTransportRef) - cTransportRef->put(cTransportRef, objects, processQueue, replyBlock); -} - -void SOSCloudKeychainRegisterKeysAndGet(CFArrayRef keysToRegister, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock, CloudItemsChangedBlock notificationBlock) -{ - SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); - if (cTransportRef) - cTransportRef->registerKeys(cTransportRef, keysToRegister, processQueue, replyBlock, notificationBlock); -} - -bool SOSCloudKeychainUpdateKeys(bool getNewKeysOnly, - CFArrayRef alwaysKeys, - CFArrayRef afterFirstUnlockKeys, - CFArrayRef unlockedKeys, - CFErrorRef *error) -{ - SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); - if (cTransportRef) - return cTransportRef->updateKeys(cTransportRef, getNewKeysOnly, alwaysKeys, afterFirstUnlockKeys, unlockedKeys, error); - - return false; -} - -void SOSCloudKeychainUnRegisterKeys(CFArrayRef keysToUnregister, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); - if (cTransportRef) - cTransportRef->unregisterKeys(cTransportRef, keysToUnregister, processQueue, replyBlock); -} - -void SOSCloudKeychainHandleUpdate(CFDictionaryRef updates) -{ - SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); - if (cTransportRef->itemsChangedBlock) - ((CloudItemsChangedBlock)cTransportRef->itemsChangedBlock)(updates); -} - -void SOSCloudKeychainGetObjectsFromCloud(CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); - if (cTransportRef) - cTransportRef->get(cTransportRef, keysToGet, processQueue, replyBlock); -} - -void SOSCloudKeychainGetAllObjectsFromCloud(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); - if (cTransportRef) - cTransportRef->getAll(cTransportRef, processQueue, replyBlock); -} - -void SOSCloudKeychainSynchronizeAndWait(CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); - if (cTransportRef) - cTransportRef->synchronizeAndWait(cTransportRef, keysToGet, processQueue, replyBlock); -} - -//DEBUG ONLY -void SOSCloudKeychainSynchronize(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); - if (cTransportRef) - cTransportRef->synchronize(cTransportRef, processQueue, replyBlock); -} - -//DEBUG ONLY -void SOSCloudKeychainClearAll(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); - if (cTransportRef) - cTransportRef->clearAll(cTransportRef, processQueue, replyBlock); -} - -void SOSCloudKeychainRemoveObjectForKey(CFStringRef keyToRemove, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); - if (cTransportRef) - cTransportRef->removeObjectForKey(cTransportRef, keyToRemove, processQueue, replyBlock); -} - -void SOSCloudKeychainUserNotification(CFStringRef messageToUser, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); - if (cTransportRef) - cTransportRef->localNotification(cTransportRef, messageToUser, processQueue, replyBlock); -} - -void SOSCloudKeychainSetParams(CFDictionaryRef paramsDict, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); - if (cTransportRef) - cTransportRef->setParams(cTransportRef, paramsDict, processQueue, replyBlock); -} - -void SOSCloudKeychainRequestSyncWithAllPeers(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - SOSCloudTransportRef cTransportRef = SOSCloudTransportDefaultTransport(); - if (cTransportRef) - cTransportRef->requestSyncWithAllPeers(cTransportRef, processQueue, replyBlock); -} - -void SOSCloudKeychainSetCallbackMethodXPC(void) -{ - // Call this before making any other calls to CloudKeychainProxy - CFDictionaryRef paramsDict = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, - kParamCallbackMethod, kParamCallbackMethodXPC, NULL); - dispatch_queue_t processQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - SOSCloudKeychainSetParams(paramsDict, processQueue, ^(CFDictionaryRef returnedValues, CFErrorRef error) - { - secerror("set params called back"); - }); - CFReleaseSafe(paramsDict); -} diff --git a/sec/SOSCircle/CKBridge/SOSCloudKeychainClient.h b/sec/SOSCircle/CKBridge/SOSCloudKeychainClient.h deleted file mode 100644 index 3d1ae277..00000000 --- a/sec/SOSCircle/CKBridge/SOSCloudKeychainClient.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2012 Apple Computer, 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@ - */ - - -/* - * SOSCloudKeychainClient.h - Implementation of the transport layer from CKBridge to SOSAccount/SOSCircle - */ - -/*! - @header SOSCloudKeychainClient - The functions provided in SOSCloudTransport.h provide an interface - from CKBridge to SOSAccount/SOSCircle - */ - -#ifndef _SOSCLOUDKEYCHAINCLIENT_H_ -#define _SOSCLOUDKEYCHAINCLIENT_H_ - -#include -#include -#include -#include - -__BEGIN_DECLS - - -// MARK: ---------- SOSCloudTransport ---------- - -enum -{ - kSOSObjectMallocFailed = 1, - kAddDuplicateEntry, - kSOSObjectNotFoundError = 1, - kSOSObjectCantBeConvertedToXPCObject, - kSOSOUnexpectedConnectionEvent, - kSOSOXPCErrorEvent, - kSOSOUnexpectedXPCEvent, - kSOSConnectionNotOpen -}; - -typedef void (^CloudItemsChangedBlock)(CFDictionaryRef values); -typedef void (^CloudKeychainReplyBlock)(CFDictionaryRef returnedValues, CFErrorRef error); - -/* SOSCloudTransport protocol. */ -typedef struct SOSCloudTransport *SOSCloudTransportRef; -struct SOSCloudTransport -{ - void (*put)(SOSCloudTransportRef transport, CFDictionaryRef valuesToPut, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); - void (*registerKeys)(SOSCloudTransportRef transport, CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock, CloudItemsChangedBlock notificationBlock); - bool (*updateKeys)(SOSCloudTransportRef transport, bool getNewKeysOnly, CFArrayRef alwaysKeys, CFArrayRef afterFirstUnlockKeys, CFArrayRef unlockedKeys, CFErrorRef *error); - - void (*unregisterKeys)(SOSCloudTransportRef transport, CFArrayRef keysToUnregister, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); - - // Debug calls - void (*get)(SOSCloudTransportRef transport, CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); - void (*getAll)(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); - void (*synchronize)(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); - void (*synchronizeAndWait)(SOSCloudTransportRef transport, CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); - - void (*clearAll)(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); - void (*removeObjectForKey)(SOSCloudTransportRef transport, CFStringRef keyToRemove, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); - void (*localNotification)(SOSCloudTransportRef transport, CFStringRef messageToUser, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); - void (*setParams)(SOSCloudTransportRef transport, CFDictionaryRef paramsDict, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); - void (*requestSyncWithAllPeers)(SOSCloudTransportRef transport, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); - - const void *itemsChangedBlock; -}; - -/* Call this function before calling any other function in this header to provide - an alternate transport, the default transport talks to CloudKeychainProxy via xpc. */ -void SOSCloudKeychainSetTransport(SOSCloudTransportRef transport); - - -/*! - @function SOSCloudKeychainRegisterKeysAndGet - @abstract Register a set of keys-of-interest and optionally return their current values - @param keysToGet An array of CFStringRef keys to get/register - @param processQueue The replyBlock will be called via dispatch_async on this queue - @param replyBlock This will be called via dispatch_async - @discussion The replyBlock will be called asynchronously with the current values of - the registered keys. If an error occured, the error parameter to the replyBlock will - be filled in with an error. The caller should call CFRetain on the returned dictionary. - */ -void SOSCloudKeychainRegisterKeysAndGet(CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock, CloudItemsChangedBlock notificationBlock); -bool SOSCloudKeychainUpdateKeys(bool getNewKeysOnly, - CFArrayRef alwaysKeys, - CFArrayRef afterFirstUnlockKeys, - CFArrayRef unlockedKeys, - CFErrorRef *error); -void SOSCloudKeychainUnRegisterKeys(CFArrayRef keysToUnregister, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); - -void SOSCloudKeychainPutObjectsInCloud(CFDictionaryRef objects, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); - -void SOSCloudKeychainSetItemsChangedBlock(CloudItemsChangedBlock itemsChangedBlock); - -void SOSCloudKeychainUserNotification(CFStringRef messageToUser, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); - -void SOSCloudKeychainHandleUpdate(CFDictionaryRef update); -void SOSCloudKeychainSynchronizeAndWait(CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); - -// Debug only? - -void SOSCloudKeychainGetObjectsFromCloud(CFArrayRef keysToGet, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); -void SOSCloudKeychainSynchronize(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); -void SOSCloudKeychainClearAll(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); -void SOSCloudKeychainRemoveObjectForKey(CFStringRef keyToRemove, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); -void SOSCloudKeychainGetAllObjectsFromCloud(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); - -void SOSCloudKeychainSetParams(CFDictionaryRef paramsDict, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); -void SOSCloudKeychainRequestSyncWithAllPeers(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); - -void SOSCloudKeychainSetCallbackMethodXPC(void); - -__END_DECLS - -#endif /* !_SOSCLOUDKEYCHAINCLIENT_H_ */ - diff --git a/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.h b/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.h deleted file mode 100644 index aad1a9d1..00000000 --- a/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -// -// CKDKVSProxy.h -// ckd-xpc - -#import -#import -#import - -#import - -#import "SOSCloudKeychainConstants.h" -#import "SOSCloudKeychainClient.h" - -#define XPROXYSCOPE "proxy" - -@interface UbiqitousKVSProxy : NSObject -{ - id currentiCloudToken; - CloudItemsChangedBlock itemsChangedCallback; - int callbackMethod; -} -@property (retain, nonatomic) NSString *myID; -@property (retain, nonatomic) NSArray *keysToRead; -@property (retain, nonatomic) NSArray *keysToWrite; -@property (retain, nonatomic) NSArray *keysReadWrite; - -@property (retain, nonatomic) NSSet *alwaysKeys; -@property (retain, nonatomic) NSSet *firstUnlockKeys; -@property (retain, nonatomic) NSSet *unlockedKeys; -@property (retain, nonatomic) NSMutableSet *pendingKeys; -@property (retain, nonatomic) NSMutableSet *shadowPendingKeys; -@property (atomic) bool syncWithPeersPending; -@property (atomic) bool shadowSyncWithPeersPending; -@property (atomic) bool inCallout; -@property (atomic) bool unlockedSinceBoot; -@property (atomic) bool isLocked; -@property (atomic) bool seenKVSStoreChange; - -@property (atomic) dispatch_source_t syncTimer; -@property (atomic) bool syncTimerScheduled; -@property (atomic) dispatch_time_t deadline; -@property (atomic) dispatch_time_t lastSyncTime; - -+ (UbiqitousKVSProxy *) sharedKVSProxy; -- (NSString *)description; -- (id)init; -- (void)streamEvent:(xpc_object_t)notification; -- (void)setItemsChangedBlock:(CloudItemsChangedBlock)itemsChangedBlock; - -- (void)setObject:(id)obj forKey:(id)key; -- (id)get:(id)key; -- (NSDictionary *)getAll; -- (void)requestSynchronization:(bool)force; -- (void)waitForSynchronization:(NSArray *)keys handler:(void (^)(NSDictionary *values, NSError *err))handler; -- (void)clearStore; -- (void)setObjectsFromDictionary:(NSDictionary *)values; -- (void)removeObjectForKey:(NSString *)keyToRemove; -- (void)processAllItems; -- (void)requestSyncWithAllPeers; - -- (NSUbiquitousKeyValueStore *)cloudStore; - -- (NSSet*) keysForCurrentLockState; -- (NSSet*) filterKeySetWithLockState: (NSSet*) startingSet; -- (NSDictionary *)registerKeysAndGet:(BOOL)getNewKeysOnly always:(NSArray *)keysToRegister reqFirstUnlock:(NSArray *)reqFirstUnlock reqUnlocked:(NSArray *)reqUnlocked; - -- (NSDictionary *)localNotification:(NSDictionary *)localNotificationDict outFlags:(int64_t *)outFlags; -- (void)processKeyChangedEvent:(NSDictionary *)keysChangedInCloud; -- (NSMutableDictionary *)copyChangedValues:(NSSet *)keysOfInterest; -- (void)setParams:(NSDictionary *)paramsDict; - -@end diff --git a/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.m b/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.m deleted file mode 100644 index b5947a1f..00000000 --- a/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.m +++ /dev/null @@ -1,869 +0,0 @@ -/* - * Copyright (c) 2012-2013 Apple Computer, Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -// -// CKDKVSProxy.m -// ckd-xpc -// - -#import -#import -#import -#import - -#import -#import -#import -#import - -#import "CKDKVSProxy.h" -#import "CKDPersistentState.h" -#import "CKDUserInteraction.h" - -#import "SOSARCDefines.h" - -#include -#include -#include "SOSCloudKeychainConstants.h" - -#include -#include - -#define SOSCKCSCOPE "sync" - -/* - The total space available in your app’s iCloud key-value storage is 1 MB. - The maximum number of keys you can specify is 1024, and the size limit for - each value associated with a key is 1 MB. So, for example, if you store a - single large value of 1 MB for a single key, that consumes your total - available storage. If you store 1 KB of data for each key, you can use - 1,000 key-value pairs. -*/ - -static const char *kStreamName = "com.apple.notifyd.matching"; - - -static NSString *kKeyAlwaysKeys = @"AlwaysKeys"; -static NSString *kKeyFirstUnlockKeys = @"FirstUnlockKeys"; -static NSString *kKeyUnlockedKeys = @"UnlockedKeys"; -static NSString *kKeyPendingKeys = @"PendingKeys"; -static NSString *kKeyUnsentChangedKeys = @"unsentChangedKeys"; -static NSString *kKeyUnlockNotificationRequested = @"unlockNotificationRequested"; -static NSString *kKeySyncWithPeersPending = @"SyncWithPeersPending"; - -enum -{ - kCallbackMethodSecurityd = 0, - kCallbackMethodXPC = 1, -}; - -static const int64_t kMinSyncDelay = (NSEC_PER_MSEC * 500); -static const int64_t kMaxSyncDelay = (NSEC_PER_SEC * 5); -static const int64_t kMinSyncInterval = (NSEC_PER_SEC * 15); -static const int64_t kSyncTimerLeeway = (NSEC_PER_MSEC * 250); - -@interface NSUbiquitousKeyValueStore (NSUbiquitousKeyValueStore_PrivateZ) -- (void) _synchronizeWithCompletionHandler:(void (^)(NSError *error))completionHandler; - -/* -// SPI For Security -- (void) synchronizeWithCompletionHandler:(void (^)(NSError *error))completionHandler; - */ - -@end - -@implementation UbiqitousKVSProxy - - -- (void)persistState -{ - [SOSPersistentState setRegisteredKeys:[self exportKeyInterests]]; -} - -+ (UbiqitousKVSProxy *) sharedKVSProxy -{ - static UbiqitousKVSProxy *sharedKVSProxy; - if (!sharedKVSProxy) { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - sharedKVSProxy = [[self alloc] init]; - }); - } - return sharedKVSProxy; -} - -- (id)init -{ - if (self = [super init]) - { - secnotice("event", "%@ start", self); - - _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, ^{ - [self timerFired]; - }); - dispatch_resume(_syncTimer); - - [[NSNotificationCenter defaultCenter] - addObserver: self - selector: @selector (iCloudAccountAvailabilityChanged:) - name: NSUbiquityIdentityDidChangeNotification - object: nil]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(cloudChanged:) - name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification - object:nil]; - - [self importKeyInterests: [SOSPersistentState registeredKeys]]; - - // Register for lock state changes - xpc_set_event_stream_handler(kStreamName, dispatch_get_main_queue(), - ^(xpc_object_t notification){ - [self streamEvent:notification]; - }); - - [self updateUnlockedSinceBoot]; - [self updateIsLocked]; - if (!_isLocked) - [self keybagDidUnlock]; - - secdebug(XPROXYSCOPE, "%@ done", self); - } - return self; -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"<%s%s%s%s%s%s%s%s%s>", - _isLocked ? "L" : "U", - _unlockedSinceBoot ? "B" : "-", - _seenKVSStoreChange ? "K" : "-", - _syncTimerScheduled ? "T" : "-", - _syncWithPeersPending ? "s" : "-", - [_pendingKeys count] ? "p" : "-", - _inCallout ? "C" : "-", - _shadowSyncWithPeersPending ? "S" : "-", - [_shadowPendingKeys count] ? "P" : "-"]; -} - -- (void)processAllItems -{ - NSDictionary *allItems = [self getAll]; - if (allItems) - { - secnotice("event", "%@ sending: %@", self, [[allItems allKeys] componentsJoinedByString: @" "]); - [self processKeyChangedEvent:allItems]; - } - else - secdebug(XPROXYSCOPE, "%@ No items in KVS", self); -} - -- (void)setItemsChangedBlock:(CloudItemsChangedBlock)itemsChangedBlock -{ - self->itemsChangedCallback = itemsChangedBlock; -} - -- (void)dealloc -{ - secdebug(XPROXYSCOPE, "%@", self); - [[NSNotificationCenter defaultCenter] removeObserver:self - name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification object:nil]; - - [[NSNotificationCenter defaultCenter] removeObserver:self - name:NSUbiquityIdentityDidChangeNotification object:nil]; -} - -// MARK: ----- Client Interface ----- - -- (void)setObject:(id)obj forKey:(id)key -{ - secdebug("keytrace", "%@ key: %@, obj: %@", self, key, obj); - NSUbiquitousKeyValueStore *store = [self cloudStore]; - if (store) - { - id value = [store objectForKey:key]; - if (value) - secdebug("keytrace", "%@ Current value (before set) for key %@ is: %@", self, key, value); - else - secdebug("keytrace", "%@ No current value for key %@", self, key); - } - else - secdebug("keytrace", "Can't get store"); - - [[self cloudStore] setObject:obj forKey:key]; - [self requestSynchronization:NO]; -} - -- (void)setObjectsFromDictionary:(NSDictionary *)values -{ - secdebug(XPROXYSCOPE, "%@ start: %lu values to put", self, (unsigned long)[values count]); - - NSUbiquitousKeyValueStore *store = [self cloudStore]; - if (store && values) - { - [values enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) - { - if (obj == NULL || obj == [NSNull null]) - [store removeObjectForKey:key]; - else - [store setObject:obj forKey:key]; - }]; - - [self requestSynchronization:NO]; - } - else - secdebug(XPROXYSCOPE, "%@ NULL? store: %@, values: %@", self, store, values); -} - -- (void)requestSynchronization:(bool)force -{ - if (force) - { - secdebug(XPROXYSCOPE, "%@ synchronize (forced)", self); - [[self cloudStore] synchronize]; - } - else - { - secdebug(XPROXYSCOPE, "%@ synchronize (soon)", self); - [[self cloudStore] synchronize]; - } -} - -- (NSUbiquitousKeyValueStore *)cloudStore -{ - NSUbiquitousKeyValueStore *iCloudStore = [NSUbiquitousKeyValueStore defaultStore]; -// secdebug(XPROXYSCOPE, "cloudStore: %@", iCloudStore); - return iCloudStore; -} - -// try to synchronize asap, and invoke the handler on completion to take incoming changes. -- (void)waitForSynchronization:(NSArray *)keys handler:(void (^)(NSDictionary *values, NSError *err))handler -{ - secdebug(XPROXYSCOPE, "%@ synchronize and wait", self); - - if (!keys) - { - NSError *err = [NSError errorWithDomain:(NSString *)NSPOSIXErrorDomain code:(NSInteger)ENOPROTOOPT userInfo:nil]; - handler(@{}, err); - return; - } - - secdebug(XPROXYSCOPE, "%@ Requesting synchronizeWithCompletionHandler", self); - - [[self cloudStore] synchronizeWithCompletionHandler:^(NSError *error) { - [[self cloudStore] synchronize]; // Per olivier in , sync before getting values - - NSDictionary * changedKeys = error ? @{} : [self copyChangedValues:[NSSet setWithArray:keys]]; - - secdebug(XPROXYSCOPE, "%@ Got synchronize completion %@ (error %@)", self, changedKeys, error); - handler(changedKeys, error); - }]; -} - -- (void)dumpStore -{ - NSDictionary *dict = [[self cloudStore] dictionaryRepresentation]; - [dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { - secdebug(XPROXYSCOPE, "%@ Dump: value for key %@ is: %@", self, key, obj); - }]; -} - -- (void)removeObjectForKey:(NSString *)keyToRemove -{ - [[self cloudStore] removeObjectForKey:keyToRemove]; -} - -- (void)clearStore -{ - secdebug(XPROXYSCOPE, "%@ clearStore", self); - NSDictionary *dict = [[self cloudStore] dictionaryRepresentation]; - NSArray *allKeys = [dict allKeys]; - [allKeys enumerateObjectsUsingBlock:^(id key, NSUInteger idx, BOOL *stop) - { - secdebug(XPROXYSCOPE, "%@ Clearing value for key %@", self, key); - [[self cloudStore] removeObjectForKey:(NSString *)key]; - }]; - - [self requestSynchronization:YES]; -} - - -// -// MARK: ----- KVS key lists ----- -// - -- (id)get:(id)key -{ - return [[self cloudStore] objectForKey:key]; -} - -- (NSDictionary *)getAll -{ - return [[self cloudStore] dictionaryRepresentation]; -} - -- (NSDictionary*) exportKeyInterests -{ - return @{ kKeyAlwaysKeys:[_alwaysKeys allObjects], - kKeyFirstUnlockKeys:[_firstUnlockKeys allObjects], - kKeyUnlockedKeys:[_unlockedKeys allObjects], - kKeyPendingKeys:[_pendingKeys allObjects], - kKeySyncWithPeersPending:[NSNumber numberWithBool:_syncWithPeersPending] - }; -} - -- (void) importKeyInterests: (NSDictionary*) interests -{ - _alwaysKeys = [NSSet setWithArray: interests[kKeyAlwaysKeys]]; - _firstUnlockKeys = [NSSet setWithArray: interests[kKeyFirstUnlockKeys]]; - _unlockedKeys = [NSSet setWithArray: interests[kKeyUnlockedKeys]]; - _pendingKeys = [NSMutableSet setWithArray: interests[kKeyPendingKeys]]; - _syncWithPeersPending = [interests[kKeySyncWithPeersPending] boolValue]; -} - -- (NSMutableSet *)copyAllKeys -{ - NSMutableSet *allKeys = [NSMutableSet setWithSet: _alwaysKeys]; - [allKeys unionSet: _firstUnlockKeys]; - [allKeys unionSet: _unlockedKeys]; - return allKeys; -} - -- (NSDictionary *)registerKeysAndGet:(BOOL)getNewKeysOnly always:(NSArray *)keysToRegister reqFirstUnlock:(NSArray *)reqFirstUnlock reqUnlocked:(NSArray *)reqUnlocked -{ - NSMutableSet *allOldKeys = [self copyAllKeys]; - _alwaysKeys = [NSSet setWithArray: keysToRegister]; - _firstUnlockKeys = [NSSet setWithArray: reqFirstUnlock]; - _unlockedKeys = [NSSet setWithArray: reqUnlocked]; - NSMutableSet *allNewKeys = [self copyAllKeys]; - - [_pendingKeys intersectSet:allNewKeys]; - - NSSet* keysToGet = nil; - if (getNewKeysOnly) { - [allNewKeys minusSet:allOldKeys]; - keysToGet = allNewKeys; - } else { - keysToGet = [self keysForCurrentLockState]; - } - - // Mark keysToGet for the current lockState as pending - NSSet *filteredKeys = [self filterKeySetWithLockState:keysToGet]; - [self persistState]; - NSMutableDictionary *returnedValues = [self copyChangedValues: filteredKeys]; - - secnotice("keytrace", "%@ [%s] always: %@ firstUnlock: %@ unlocked: %@ got: %@", self, getNewKeysOnly ? "new only " : "", [keysToRegister componentsJoinedByString: @" "], [reqFirstUnlock componentsJoinedByString: @" "], [reqUnlocked componentsJoinedByString: @" "], [[returnedValues allKeys] componentsJoinedByString: @" "]); - - [self processKeyChangedEvent:returnedValues]; - [returnedValues removeAllObjects]; - - return returnedValues; -} - -- (NSDictionary *)localNotification:(NSDictionary *)localNotificationDict outFlags:(int64_t *)outFlags -{ - __block bool done = false; - __block int64_t returnedFlags = 0; - __block NSDictionary *responses = NULL; - typedef bool (^CKDUserInteractionBlock) (CFDictionaryRef responses); - - CKDUserInteraction *cui = [CKDUserInteraction sharedInstance]; - [cui requestShowNotification:localNotificationDict completion:^ bool (CFDictionaryRef userResponses, int64_t flags) - { - responses = [NSDictionary dictionaryWithDictionary:(__bridge NSDictionary *)userResponses]; - returnedFlags = flags; - secdebug(XPROXYSCOPE, "%@ requestShowNotification: dict: %@, flags: %#llx", self, responses, returnedFlags); - done = true; - return true; - }]; - - // TODO: replace with e.g. dispatch calls to wait, or semaphore - while (!done) - sleep(1); - if (outFlags) - { - secdebug(XPROXYSCOPE, "%@ outFlags: %#llx", self, returnedFlags); - *outFlags = returnedFlags; - } - return responses; -} - -- (void)setParams:(NSDictionary *)paramsDict -{ - secdebug(XPROXYSCOPE, "%@ setParams: %@ ", self, paramsDict); - NSString *cbmethod = [paramsDict objectForKey:(__bridge id)kParamCallbackMethod]; - if (!cbmethod) - return; - - if ([cbmethod isEqualToString:(__bridge NSString *)kParamCallbackMethodSecurityd]) - callbackMethod = kCallbackMethodSecurityd; - else if ([cbmethod isEqualToString:(__bridge NSString *)kParamCallbackMethodXPC]) - callbackMethod = kCallbackMethodXPC; -} - -- (void)saveToUbiquitousStore -{ - [self requestSynchronization:NO]; -} - -// MARK: ----- Event Handling ----- - -- (void)streamEvent:(xpc_object_t)notification -{ -#if (!TARGET_IPHONE_SIMULATOR) - const char *notificationName = xpc_dictionary_get_string(notification, "Notification"); - if (!notificationName) { - } else if (strcmp(notificationName, kUserKeybagStateChangeNotification)==0) { - return [self keybagStateChange]; - } else if (strcmp(notificationName, kCloudKeychainStorechangeChangeNotification)==0) { - return [self kvsStoreChange]; - } else if (strcmp(notificationName, kNotifyTokenForceUpdate)==0) { - // DEBUG -- Possibly remove in future - return [self processAllItems]; - } - const char *eventName = xpc_dictionary_get_string(notification, "XPCEventName"); - char *desc = xpc_copy_description(notification); - secerror("%@ event: %s name: %s desc: %s", self, eventName, notificationName, desc); - if (desc) - free((void *)desc); -#endif -} - -- (void)iCloudAccountAvailabilityChanged:(NSNotification*)notification -{ - /* - Continuing this example, you’d then implement an iCloudAccountAvailabilityChanged: method that would: - - Call the ubiquityIdentityToken method and store its return value. - Compare the new value to the previous value, to find out if the user logged out of their account or - logged in to a different account. If the previously-used account is now unavailable, save the current - state locally as needed, empty your iCloud-related data caches, and refresh all iCloud-related user interface elements. - */ - id previCloudToken = currentiCloudToken; - currentiCloudToken = [[NSFileManager defaultManager] ubiquityIdentityToken]; - if (previCloudToken != currentiCloudToken) - secnotice("event", "%@ iCloud account changed!", self); - else - secnotice("event", "%@ %@", self, notification); -} - -- (void)cloudChanged:(NSNotification*)notification -{ - /* - Posted when the value of one or more keys in the local key-value store - changed due to incoming data pushed from iCloud. This notification is - sent only upon a change received from iCloud; it is not sent when your - app sets a value. - - The user info dictionary can contain the reason for the notification as - well as a list of which values changed, as follows: - - The value of the NSUbiquitousKeyValueStoreChangeReasonKey key, when - present, indicates why the key-value store changed. Its value is one of - the constants in "Change Reason Values." - - The value of the NSUbiquitousKeyValueStoreChangedKeysKey, when present, - is an array of strings, each the name of a key whose value changed. The - notification object is the NSUbiquitousKeyValueStore object whose contents - changed. - - NSUbiquitousKeyValueStoreInitialSyncChange is only posted if there is any - local value that has been overwritten by a distant value. If there is no - conflict between the local and the distant values when doing the initial - sync (e.g. if the cloud has no data stored or the client has not stored - any data yet), you'll never see that notification. - - NSUbiquitousKeyValueStoreInitialSyncChange implies an initial round trip - with server but initial round trip with server does not imply - NSUbiquitousKeyValueStoreInitialSyncChange. - */ - - secdebug(XPROXYSCOPE, "%@ cloudChanged notification: %@", self, notification); - - NSDictionary *userInfo = [notification userInfo]; - NSNumber *reason = [userInfo objectForKey:NSUbiquitousKeyValueStoreChangeReasonKey]; - if (reason) switch ([reason integerValue]) { - case NSUbiquitousKeyValueStoreInitialSyncChange: - case NSUbiquitousKeyValueStoreServerChange: - { - _seenKVSStoreChange = YES; - NSSet *keysChangedInCloud = [NSSet setWithArray:[userInfo objectForKey:NSUbiquitousKeyValueStoreChangedKeysKey]]; - NSSet *keysOfInterestThatChanged = [self filterKeySetWithLockState:keysChangedInCloud]; - NSMutableDictionary *changedValues = [self copyChangedValues:keysOfInterestThatChanged]; - if ([reason integerValue] == NSUbiquitousKeyValueStoreInitialSyncChange) - changedValues[(__bridge NSString*)kSOSKVSInitialSyncKey] = @"true"; - - secnotice("event", "%@ keysChangedInCloud: %@ keysOfInterest: %@", self, [[keysChangedInCloud allObjects] componentsJoinedByString: @" "], [[changedValues allKeys] componentsJoinedByString: @" "]); - if ([changedValues count]) - [self processKeyChangedEvent:changedValues]; - break; - } - case NSUbiquitousKeyValueStoreQuotaViolationChange: - seccritical("%@ event received NSUbiquitousKeyValueStoreQuotaViolationChange", self); - break; - case NSUbiquitousKeyValueStoreAccountChange: - // The primary account changed. We do not get this for password changes on the same account - secnotice("event", "%@ NSUbiquitousKeyValueStoreAccountChange", self); - if ([reason integerValue] == NSUbiquitousKeyValueStoreInitialSyncChange) - { - NSDictionary *changedValues = @{ (__bridge NSString*)kSOSKVSAccountChangedKey: @"true" }; - [self processKeyChangedEvent:changedValues]; - } - break; - } -} - -- (void) calloutWith: (void(^)(NSSet *pending, bool syncWithPeersPending, dispatch_queue_t queue, void(^done)(NSSet *handledKeys, bool handledSyncWithPeers))) callout -{ - // In CKDKVSProxy's serial queue - NSSet *myPending = [_pendingKeys copy]; - bool mySyncWithPeersPending = _syncWithPeersPending; - bool wasLocked = _isLocked; - _inCallout = YES; - _shadowPendingKeys = [NSMutableSet set]; - _shadowSyncWithPeersPending = NO; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - callout(myPending, mySyncWithPeersPending, dispatch_get_main_queue(), ^(NSSet *handledKeys, bool handledSyncWithPeers) { - // In CKDKVSProxy's serial queue - _inCallout = NO; - - // Update SyncWithPeers stuff. - _syncWithPeersPending = (mySyncWithPeersPending && (!handledSyncWithPeers)) || _shadowSyncWithPeersPending; - _shadowSyncWithPeersPending = NO; - if (handledSyncWithPeers) - _lastSyncTime = dispatch_time(DISPATCH_TIME_NOW, 0); - - // Update pendingKeys and handle them - [_pendingKeys minusSet: handledKeys]; - bool hadShadowPendingKeys = [_shadowPendingKeys count]; - NSSet *filteredKeys = [self filterKeySetWithLockState:_shadowPendingKeys]; - _shadowPendingKeys = nil; - - // Write state to disk - [self persistState]; - - // Handle shadow pended stuff - if (_syncWithPeersPending && !_isLocked) - [self scheduleSyncRequestTimer]; - /* We don't want to call processKeyChangedEvent if we failed to - handle pending keys and the device didn't unlock nor receive - any kvs changes while we were in our callout. - Doing so will lead to securityd and CloudKeychainProxy - talking to each other forever in a tight loop if securityd - repeatedly returns an error processing the same message. - Instead we leave any old pending keys until the next event. */ - if (hadShadowPendingKeys || (!_isLocked && wasLocked)) - [self processKeyChangedEvent:[self copyChangedValues:filteredKeys]]; - }); - }); -} - -- (void) doSyncWithAllPeers -{ - [self calloutWith:^(NSSet *pending, bool syncWithPeersPending, dispatch_queue_t queue, void(^done)(NSSet *, bool)) { - CFErrorRef error = NULL; - SyncWithAllPeersReason reason = SOSCCProcessSyncWithAllPeers(&error); - dispatch_async(queue, ^{ - bool handledSyncWithPeers = NO; - if (reason == kSyncWithAllPeersSuccess) { - handledSyncWithPeers = YES; - secnotice("event", "%@ syncWithAllPeers succeeded", self); - } else if (reason == kSyncWithAllPeersLocked) { - secnotice("event", "%@ syncWithAllPeers attempted while locked - waiting for unlock", self); - handledSyncWithPeers = YES; - } else if (reason == kSyncWithAllPeersOtherFail) { - // Pretend we handled syncWithPeers, by pushing out the _lastSyncTime - // This will cause us to wait for kMinSyncInterval seconds before - // retrying, so we don't spam securityd if sync is failing - secerror("%@ syncWithAllPeers %@, rescheduling timer", self, error); - _lastSyncTime = dispatch_time(DISPATCH_TIME_NOW, 0); - } else { - secerror("%@ syncWithAllPeers %@, unknown reason: %d", self, error, reason); - } - - done(nil, handledSyncWithPeers); - CFReleaseSafe(error); - }); - }]; -} - -- (void)timerFired -{ - secnotice("event", "%@ syncWithPeersPending: %d inCallout: %d isLocked: %d", self, _syncWithPeersPending, _inCallout, _isLocked); - _syncTimerScheduled = NO; - if (_syncWithPeersPending && !_inCallout && !_isLocked) - [self doSyncWithAllPeers]; -} - -- (dispatch_time_t) nextSyncTime -{ - dispatch_time_t nextSync = dispatch_time(DISPATCH_TIME_NOW, kMinSyncDelay); - - // Don't sync again unless we waited at least kMinSyncInterval - if (_lastSyncTime) { - dispatch_time_t soonest = dispatch_time(_lastSyncTime, kMinSyncInterval); - if (nextSync < soonest || _deadline < soonest) { - secdebug("timer", "%@ backing off", self); - return soonest; - } - } - - // Don't delay more than kMaxSyncDelay after the first request. - if (nextSync > _deadline) { - secdebug("timer", "%@ hit deadline", self); - return _deadline; - } - - // Bump the timer by kMinSyncDelay - if (_syncTimerScheduled) - secdebug("timer", "%@ bumped timer", self); - else - secdebug("timer", "%@ scheduled timer", self); - - return nextSync; -} - -- (void)scheduleSyncRequestTimer -{ - dispatch_source_set_timer(_syncTimer, [self nextSyncTime], DISPATCH_TIME_FOREVER, kSyncTimerLeeway); - _syncTimerScheduled = YES; -} - -- (void)requestSyncWithAllPeers // secd calling SOSCCSyncWithAllPeers invokes this -{ - secdebug("event", "%@ _syncWithPeersPending: %d _inCallout: %d _shadowSyncWithPeersPending: %d _isLocked: %d", self, _syncWithPeersPending, _inCallout, _shadowSyncWithPeersPending, _isLocked); - - if (!_syncWithPeersPending || (_inCallout && !_shadowSyncWithPeersPending)) - _deadline = dispatch_time(DISPATCH_TIME_NOW, kMaxSyncDelay); - - if (!_syncWithPeersPending) { - _syncWithPeersPending = YES; - [self persistState]; - } - - if (_inCallout) - _shadowSyncWithPeersPending = YES; - - if (!_isLocked) - [self scheduleSyncRequestTimer]; -} - -- (BOOL) updateUnlockedSinceBoot -{ - CFErrorRef aksError = NULL; - if (!SecAKSGetHasBeenUnlocked(&_unlockedSinceBoot, &aksError)) { - secerror("%@ Got error from SecAKSGetHasBeenUnlocked: %@", self, aksError); - CFReleaseSafe(aksError); - return NO; - } - return YES; -} - -- (BOOL) updateIsLocked -{ - CFErrorRef aksError = NULL; - if (!SecAKSGetIsLocked(&_isLocked, &aksError)) { - secerror("%@ Got error querying lock state: %@", self, aksError); - CFReleaseSafe(aksError); - return NO; - } - if (!_isLocked) - _unlockedSinceBoot = YES; - return YES; -} - -- (void) keybagStateChange -{ - BOOL wasLocked = _isLocked; - if ([self updateIsLocked]) { - if (wasLocked == _isLocked) - secdebug("event", "%@ still %s ignoring", self, _isLocked ? "locked" : "unlocked"); - else if (_isLocked) - [self keybagDidLock]; - else - [self keybagDidUnlock]; - } -} - -- (void) keybagDidLock -{ - secnotice("event", "%@", self); -} - -- (void) keybagDidUnlock -{ - secnotice("event", "%@", self); - // First send changed keys to securityd so it can proccess updates - NSSet *filteredKeys = [self filterKeySetWithLockState:nil]; - [self processKeyChangedEvent:[self copyChangedValues:filteredKeys]]; - - // Then, tickle securityd to perform a sync if needed. - if (_syncWithPeersPending && !_syncTimerScheduled) { - [self doSyncWithAllPeers]; - } -} - -- (void) kvsStoreChange { - if (!_seenKVSStoreChange) { - _seenKVSStoreChange = YES; // Only do this once - secnotice("event", "%@ received darwin notification before first NSNotification", self); - // TODO This might not be needed if we always get the NSNotification - // deleived even if we were launched due to a kvsStoreChange - // Send all keys for current lock state to securityd so it can proccess them - NSSet *filteredKeys = [self filterKeySetWithLockState:[self copyAllKeys]]; - [self processKeyChangedEvent:[self copyChangedValues:filteredKeys]]; - } else { - secdebug("event", "%@ ignored, waiting for NSNotification", self); - } -} - -// -// MARK: ----- Key Filtering ----- -// - -- (NSSet*) keysForCurrentLockState -{ - secdebug("keytrace", "%@ Filtering: unlockedSinceBoot: %d\n unlocked: %d\n, _keysOfInterest: %@", self, (int) _unlockedSinceBoot, (int) !_isLocked, [self exportKeyInterests]); - - NSMutableSet *currentStateKeys = [NSMutableSet setWithSet: _alwaysKeys]; - if (_unlockedSinceBoot) - [currentStateKeys unionSet: _firstUnlockKeys]; - - if (!_isLocked) - [currentStateKeys unionSet: _unlockedKeys]; - - return currentStateKeys; -} - -- (NSSet*) filterKeySetWithLockState: (NSSet*) startingSet -{ - NSSet* availableKeys = [self keysForCurrentLockState]; - NSSet *allKeys = [self copyAllKeys]; - if (_inCallout) { - [_shadowPendingKeys unionSet:startingSet]; - [_shadowPendingKeys intersectSet:allKeys]; - } - [_pendingKeys unionSet:startingSet]; - [_pendingKeys intersectSet:allKeys]; - - NSMutableSet *filtered =[_pendingKeys mutableCopy]; - [filtered intersectSet:availableKeys]; - - return filtered; -} - -- (NSMutableDictionary *)copyChangedValues:(NSSet*)keysOfInterest -{ - // Grab values from KVS. - NSUbiquitousKeyValueStore *store = [self cloudStore]; - NSMutableDictionary *changedValues = [NSMutableDictionary dictionaryWithCapacity:0]; - [keysOfInterest enumerateObjectsUsingBlock:^(id obj, BOOL *stop) - { - NSString* key = (NSString*) obj; - id objval = [store objectForKey:key]; - if (!objval) objval = [NSNull null]; - - [changedValues setObject:objval forKey:key]; - secdebug(XPROXYSCOPE, "%@ storeChanged updated value for %@", self, key); - }]; - return changedValues; -} - -/* - During RegisterKeys, separate keys-of-interest into three disjoint sets: - - keys that we always want to be notified about; this means we can get the - value at any time - - keys that require the device to have been unlocked at least once - - keys that require the device to be unlocked now - - Typically, the sets of keys will be: - - - Dk: alwaysKeys - - Ck: firstUnlock - - Ak: unlocked - - The caller is responsible for making sure that the keys in e.g. alwaysKeys are - values that can be handled at any time (that is, not when unlocked) - - Each time we get a notification from ubiquity that keys have changed, we need to - see if anything of interest changed. If we don't care, then done. - - For each key-of-interest that changed, we either notify the client that things - changed, or add it to a pendingNotifications list. If the notification to the - client fails, also add it to the pendingNotifications list. This pending list - should be written to persistent storage and consulted any time we either get an - item changed notification, or get a stream event signalling a change in lock state. - - We can notify the client either through XPC if a connection is set up, or call a - routine in securityd to launch it. - -*/ - -- (void)processKeyChangedEvent:(NSDictionary *)changedValues -{ - NSMutableDictionary* filtered = [NSMutableDictionary dictionary]; - NSMutableArray* nullKeys = [NSMutableArray array]; - // Remove nulls because we don't want them in securityd. - [changedValues enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { - if (obj == [NSNull null]) - [nullKeys addObject:key]; - else - filtered[key] = obj; - }]; - if ([filtered count]) { - [self calloutWith:^(NSSet *pending, bool syncWithPeersPending, dispatch_queue_t queue, void(^done)(NSSet *, bool)) { - CFErrorRef error = NULL; - bool bx = [filtered count] && _SecKeychainSyncUpdate((__bridge CFDictionaryRef)filtered, &error); - // TODO: Make SecKeychainSyncUpdate return handled keys, for now we - // record that we handled everything when _SecKeychainSyncUpdate succeeds. - NSSet* handledKeys = [NSSet setWithArray: bx ? [changedValues allKeys] : nullKeys]; - dispatch_async(queue, ^{ - done(handledKeys, NO); - if (bx) - secnotice("keytrace", "%@ handled: %@ null: %@ pending: %@", self, - [[filtered allKeys] componentsJoinedByString: @" "], - [nullKeys componentsJoinedByString: @" "], - [[_pendingKeys allObjects] componentsJoinedByString: @" "]); - else - secerror("%@ failed: %@ not handled: %@ null: %@ pending: %@", self, error, - [[filtered allKeys] componentsJoinedByString: @" "], - [nullKeys componentsJoinedByString: @" "], - [[_pendingKeys allObjects] componentsJoinedByString: @" "]); - CFReleaseSafe(error); - }); - }]; - } else { - if ([nullKeys count]) - [_pendingKeys minusSet: [NSSet setWithArray: nullKeys]]; - - secnotice("keytrace", "%@ handled: %@ null: %@ pending: %@", self, - [[filtered allKeys] componentsJoinedByString: @" "], - [nullKeys componentsJoinedByString: @" "], - [[_pendingKeys allObjects] componentsJoinedByString: @" "]); - } -} - -@end - diff --git a/sec/SOSCircle/CloudKeychainProxy/cloudkeychainproxy.m b/sec/SOSCircle/CloudKeychainProxy/cloudkeychainproxy.m deleted file mode 100644 index a4a86782..00000000 --- a/sec/SOSCircle/CloudKeychainProxy/cloudkeychainproxy.m +++ /dev/null @@ -1,461 +0,0 @@ -/* - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -// -// main.m -// ckd-xpc -// -// Created by John Hurley on 7/19/12. -// Copyright (c) 2012 John Hurley. All rights reserved. -// - -/* - This XPC service is essentially just a proxy to iCloud KVS, which exists since - the main security code cannot link against Foundation. - - See sendTSARequestWithXPC in tsaSupport.c for how to call the service - - send message to app with xpc_connection_send_message - - For now, build this with: - - ~rc/bin/buildit . --rootsDirectory=/var/tmp -noverify -offline -target CloudKeychainProxy - - and install or upgrade with: - - darwinup install /var/tmp/sec.roots/sec~dst - darwinup upgrade /var/tmp/sec.roots/sec~dst - - You must use darwinup during development to update system caches -*/ - -//------------------------------------------------------------------------------------------------ - -#include - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#include - -#import "SOSCloudKeychainConstants.h" -#import "CKDKVSProxy.h" - -void finalize_connection(void *not_used); -void handle_connection_event(const xpc_connection_t peer); -static void cloudkeychainproxy_peer_dictionary_handler(const xpc_connection_t peer, xpc_object_t event); - -static bool operation_put_dictionary(xpc_object_t event); -static bool operation_get_v2(xpc_object_t event); - -int ckdproxymain(int argc, const char *argv[]); - -static void describeXPCObject(char *prefix, xpc_object_t object) -{ -//#ifndef NDEBUG - // This is useful for debugging. - if (object) - { - char *desc = xpc_copy_description(object); - secdebug(XPROXYSCOPE, "%s%s\n", prefix, desc); - free(desc); - } - else - secdebug(XPROXYSCOPE, "%s\n", prefix); - -//#endif -} - -static void cloudkeychainproxy_peer_dictionary_handler(const xpc_connection_t peer, xpc_object_t event) -{ - bool result = false; - int err = 0; - - require_action_string(xpc_get_type(event) == XPC_TYPE_DICTIONARY, xit, err = -51, "expected XPC_TYPE_DICTIONARY"); - - const char *operation = xpc_dictionary_get_string(event, kMessageKeyOperation); - require_action(operation, xit, result = false); - - // Check protocol version - uint64_t version = xpc_dictionary_get_uint64(event, kMessageKeyVersion); - secdebug(XPROXYSCOPE, "Reply version: %lld\n", version); - require_action(version == kCKDXPCVersion, xit, result = false); - - // Operations - secdebug(XPROXYSCOPE, "Handling %s operation", operation); - - if (operation && !strcmp(operation, kOperationPUTDictionary)) - operation_put_dictionary(event); - else - if (operation && !strcmp(operation, kOperationGETv2)) - operation_get_v2(event); - else - if (operation && !strcmp(operation, kOperationClearStore)) - { - [[UbiqitousKVSProxy sharedKVSProxy] clearStore]; - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - if (replyMessage) // Caller wanted an ACK, so give one - { - xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); - xpc_connection_send_message(peer, replyMessage); - } - } - else if (operation && !strcmp(operation, kOperationRemoveObjectForKey)) - { - const char *keyToRemove = xpc_dictionary_get_string(event, kMessageKeyKey); - [[UbiqitousKVSProxy sharedKVSProxy] removeObjectForKey:[NSString stringWithCString:keyToRemove encoding:NSUTF8StringEncoding]]; - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - if (replyMessage) // Caller wanted an ACK, so give one - { - xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); - xpc_connection_send_message(peer, replyMessage); - } - } - else if (operation && !strcmp(operation, kOperationSynchronize)) - { - [[UbiqitousKVSProxy sharedKVSProxy] requestSynchronization:YES]; - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - if (replyMessage) // Caller wanted an ACK, so give one - { - xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); - xpc_connection_send_message(peer, replyMessage); - } - } - else if (operation && !strcmp(operation, kOperationSynchronizeAndWait)) - { - xpc_object_t xkeysToGetDict = xpc_dictionary_get_value(event, kMessageKeyValue); - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - xpc_object_t xkeys = xpc_dictionary_get_value(xkeysToGetDict, kMessageKeyKeysToGet); - NSArray *keysToGet = (__bridge NSArray *)(_CFXPCCreateCFObjectFromXPCObject(xkeys)); - [[UbiqitousKVSProxy sharedKVSProxy] waitForSynchronization:keysToGet - handler:^(NSDictionary *values, NSError *err) { - if (replyMessage) // Caller wanted an ACK, so give one - { - secdebug("keytrace", "Result from [[UbiqitousKVSProxy sharedKVSProxy] waitForSynchronization:]: %@", err); - xpc_object_t xobject = values ? _CFXPCCreateXPCObjectFromCFObject((__bridge CFTypeRef)(values)) : xpc_null_create(); - xpc_dictionary_set_value(replyMessage, kMessageKeyValue, xobject); - if (err) - { - xpc_object_t xerrobj = SecCreateXPCObjectWithCFError((CFErrorRef)CFBridgingRetain(err)); - xpc_dictionary_set_value(replyMessage, kMessageKeyError, xerrobj); - CFReleaseSafe((__bridge CFTypeRef)(err)); - } - xpc_connection_send_message(peer, replyMessage); - } - }]; - CFReleaseSafe((__bridge CFTypeRef)(keysToGet)); - } - else if (operation && !strcmp(operation, kOperationRegisterKeysAndGet)) - { - xpc_object_t xkeysToRegisterDict = xpc_dictionary_get_value(event, kMessageKeyValue); -// describeXPCObject("xkeysToRegister: ", xkeysToRegisterDict); - // KTR = keysToRegister - bool getNewKeysOnly = xpc_dictionary_get_bool(xkeysToRegisterDict, kMessageKeyGetNewKeysOnly); - xpc_object_t xKTRallkeys = xpc_dictionary_get_value(xkeysToRegisterDict, kMessageKeyKeysToGet); - xpc_object_t xKTRrequiresFirstUnlock = xpc_dictionary_get_value(xkeysToRegisterDict, kMessageKeyKeysRequireFirstUnlock); - xpc_object_t xKTRrequiresUnlock = xpc_dictionary_get_value(xkeysToRegisterDict, kMessageKeyKeysRequiresUnlocked); - - NSArray *KTRallkeys = (__bridge NSArray *)(_CFXPCCreateCFObjectFromXPCObject(xKTRallkeys)); - NSArray *KTRrequiresFirstUnlock = (__bridge NSArray *)(_CFXPCCreateCFObjectFromXPCObject(xKTRrequiresFirstUnlock)); - NSArray *KTRrequiresUnlock = (__bridge NSArray *)(_CFXPCCreateCFObjectFromXPCObject(xKTRrequiresUnlock)); - - id object = [[UbiqitousKVSProxy sharedKVSProxy] registerKeysAndGet:getNewKeysOnly always:KTRallkeys reqFirstUnlock:KTRrequiresFirstUnlock reqUnlocked:KTRrequiresUnlock]; - - CFReleaseSafe((__bridge CFTypeRef)(KTRallkeys)); - CFReleaseSafe((__bridge CFTypeRef)(KTRrequiresFirstUnlock)); - CFReleaseSafe((__bridge CFTypeRef)(KTRrequiresUnlock)); - - secdebug("keytrace", "Result from [[UbiqitousKVSProxy sharedKVSProxy] registerKeysAndGet:]: %@", object); - - xpc_object_t xobject = object ? _CFXPCCreateXPCObjectFromCFObject((__bridge CFTypeRef)(object)) : xpc_null_create(); - - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - xpc_dictionary_set_value(replyMessage, kMessageKeyValue, xobject); - xpc_connection_send_message(peer, replyMessage); - secdebug(XPROXYSCOPE, "RegisterKeysAndGet message sent"); - } - else if (operation && !strcmp(operation, kOperationUILocalNotification)) - { - xpc_object_t xLocalNotificationDict = xpc_dictionary_get_value(event, kMessageKeyValue); -// describeXPCObject("xLocalNotificationDict: ", xLocalNotificationDict); - NSDictionary *localNotificationDict = (__bridge NSDictionary *)(_CFXPCCreateCFObjectFromXPCObject(xLocalNotificationDict)); - int64_t outFlags = 0; - id object = [[UbiqitousKVSProxy sharedKVSProxy] localNotification:localNotificationDict outFlags:&outFlags]; - secdebug(XPROXYSCOPE, "Result from [[UbiqitousKVSProxy sharedKVSProxy] localNotification:]: %@", object); - xpc_object_t xobject = object ? _CFXPCCreateXPCObjectFromCFObject((__bridge CFTypeRef)(object)) : xpc_null_create(); - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - xpc_dictionary_set_int64(xobject, kMessageKeyNotificationFlags, outFlags); - xpc_dictionary_set_value(replyMessage, kMessageKeyValue, xobject); - xpc_connection_send_message(peer, replyMessage); - secdebug(XPROXYSCOPE, "localNotification reply sent"); - CFReleaseSafe((__bridge CFTypeRef)(localNotificationDict)); - } - else if (operation && !strcmp(operation, kOperationSetParams)) - { - xpc_object_t xParamsDict = xpc_dictionary_get_value(event, kMessageKeyValue); - NSDictionary *paramsDict = (__bridge NSDictionary *)(_CFXPCCreateCFObjectFromXPCObject(xParamsDict)); - [[UbiqitousKVSProxy sharedKVSProxy] setParams:paramsDict]; - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - if (replyMessage) // Caller wanted an ACK, so give one - { - xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); - xpc_connection_send_message(peer, replyMessage); - } - secdebug(XPROXYSCOPE, "setParams reply sent"); - CFReleaseSafe((__bridge CFTypeRef)(paramsDict)); - } - else if (operation && !strcmp(operation, kOperationRequestSyncWithAllPeers)) - { - [[UbiqitousKVSProxy sharedKVSProxy] requestSyncWithAllPeers]; - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - if (replyMessage) // Caller wanted an ACK, so give one - { - xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); - xpc_connection_send_message(peer, replyMessage); - } - secdebug(XPROXYSCOPE, "RequestSyncWithAllPeers reply sent"); - } - else - { - char *description = xpc_copy_description(event); - secdebug(XPROXYSCOPE, "Unknown op=%s request from pid %d: %s", operation, xpc_connection_get_pid(peer), description); - free(description); - } - result = true; -xit: - if (!result) - describeXPCObject("handle_operation fail: ", event); -} - -void finalize_connection(void *not_used) -{ - secdebug(XPROXYSCOPE, "finalize_connection"); - [[UbiqitousKVSProxy sharedKVSProxy] requestSynchronization:YES]; - xpc_transaction_end(); -} - -static bool operation_put_dictionary(xpc_object_t event) -{ - // PUT a set of objects into the KVS store. Return false if error - - describeXPCObject("operation_put_dictionary event: ", event); - xpc_object_t xvalue = xpc_dictionary_get_value(event, kMessageKeyValue); - if (!xvalue) - return false; - - CFTypeRef cfvalue = _CFXPCCreateCFObjectFromXPCObject(xvalue); - if (cfvalue && (CFGetTypeID(cfvalue)==CFDictionaryGetTypeID())) - { - [[UbiqitousKVSProxy sharedKVSProxy] setObjectsFromDictionary:(__bridge NSDictionary *)cfvalue]; - CFReleaseSafe(cfvalue); - return true; - } - else{ - describeXPCObject("operation_put_dictionary unable to convert to CF: ", xvalue); - CFReleaseSafe(cfvalue); - } - return false; -} - -static bool operation_get_v2(xpc_object_t event) -{ - // GET a set of objects from the KVS store. Return false if error - describeXPCObject("operation_get_v2 event: ", event); - xpc_connection_t peer = xpc_dictionary_get_remote_connection(event); - describeXPCObject("operation_get_v2: peer: ", peer); - - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - if (!replyMessage) - { - secdebug(XPROXYSCOPE, "can't create replyMessage"); - assert(true); //must have a reply handler - return false; - } - xpc_object_t returnedValues = xpc_dictionary_create(NULL, NULL, 0); - if (!returnedValues) - { - secdebug(XPROXYSCOPE, "can't create returnedValues"); - assert(true); // must have a spot for the returned values - return false; - } - - xpc_object_t xvalue = xpc_dictionary_get_value(event, kMessageKeyValue); - if (!xvalue) - { - secdebug(XPROXYSCOPE, "missing \"value\" key"); - return false; - } - - xpc_object_t xkeystoget = xpc_dictionary_get_value(xvalue, kMessageKeyKeysToGet); - if (xkeystoget) - { - secdebug(XPROXYSCOPE, "got xkeystoget"); - CFTypeRef keystoget = _CFXPCCreateCFObjectFromXPCObject(xkeystoget); - if (!keystoget || (CFGetTypeID(keystoget)!=CFArrayGetTypeID())) // not "getAll", this is an error of some kind - { - secdebug(XPROXYSCOPE, "can't convert keystoget or is not an array"); - CFReleaseSafe(keystoget); - return false; - } - - [(__bridge NSArray *)keystoget enumerateObjectsUsingBlock: ^ (id obj, NSUInteger idx, BOOL *stop) - { - NSString *key = (NSString *)obj; - id object = [[UbiqitousKVSProxy sharedKVSProxy] get:key]; - secdebug(XPROXYSCOPE, "[UbiqitousKVSProxy sharedKVSProxy] get: key: %@, object: %@", key, object); - xpc_object_t xobject = object ? _CFXPCCreateXPCObjectFromCFObject((__bridge CFTypeRef)object) : xpc_null_create(); - xpc_dictionary_set_value(returnedValues, [key UTF8String], xobject); - describeXPCObject("operation_get_v2: value from kvs: ", xobject); - }]; - } - else // get all values from kvs - { - secdebug(XPROXYSCOPE, "get all values from kvs"); - NSDictionary *all = [[UbiqitousKVSProxy sharedKVSProxy] getAll]; - [all enumerateKeysAndObjectsUsingBlock: ^ (id key, id obj, BOOL *stop) - { - xpc_object_t xobject = obj ? _CFXPCCreateXPCObjectFromCFObject((__bridge CFTypeRef)obj) : xpc_null_create(); - xpc_dictionary_set_value(returnedValues, [(NSString *)key UTF8String], xobject); - }]; - } - - xpc_dictionary_set_uint64(replyMessage, kMessageKeyVersion, kCKDXPCVersion); - xpc_dictionary_set_value(replyMessage, kMessageKeyValue, returnedValues); - xpc_connection_send_message(peer, replyMessage); - - return true; -} - -static void initializeProxyObjectWithConnection(const xpc_connection_t connection) -{ - [[UbiqitousKVSProxy sharedKVSProxy] setItemsChangedBlock:^(CFDictionaryRef values) - { - secdebug(XPROXYSCOPE, "UbiqitousKVSProxy called back"); - xpc_object_t xobj = _CFXPCCreateXPCObjectFromCFObject(values); - xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); - xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion); - xpc_dictionary_set_string(message, kMessageKeyOperation, kMessageOperationItemChanged); - xpc_dictionary_set_value(message, kMessageKeyValue, xobj?xobj:xpc_null_create()); - xpc_connection_send_message(connection, message); // Send message; don't wait for a reply - }]; -} - -static void cloudkeychainproxy_peer_event_handler(xpc_connection_t peer, xpc_object_t event) -{ - describeXPCObject("peer: ", peer); - xpc_type_t type = xpc_get_type(event); - if (type == XPC_TYPE_ERROR) { - if (event == XPC_ERROR_CONNECTION_INVALID) { - // The client process on the other end of the connection has either - // crashed or cancelled the connection. After receiving this error, - // the connection is in an invalid state, and you do not need to - // call xpc_connection_cancel(). Just tear down any associated state - // here. - } else if (event == XPC_ERROR_TERMINATION_IMMINENT) { - // Handle per-connection termination cleanup. - } - } else { - assert(type == XPC_TYPE_DICTIONARY); - // Handle the message. - // describeXPCObject("dictionary:", event); - cloudkeychainproxy_peer_dictionary_handler(peer, event); - } -} - -static void cloudkeychainproxy_event_handler(xpc_connection_t peer) -{ - // By defaults, new connections will target the default dispatch - // concurrent queue. - - if (xpc_get_type(peer) != XPC_TYPE_CONNECTION) - { - secdebug(XPROXYSCOPE, "expected XPC_TYPE_CONNECTION"); - return; - } - initializeProxyObjectWithConnection(peer); - xpc_connection_set_event_handler(peer, ^(xpc_object_t event) - { - cloudkeychainproxy_peer_event_handler(peer, event); - }); - - // This will tell the connection to begin listening for events. If you - // have some other initialization that must be done asynchronously, then - // you can defer this call until after that initialization is done. - xpc_connection_resume(peer); -} - -static void diagnostics(int argc, const char *argv[]) -{ - @autoreleasepool - { - NSDictionary *all = [[UbiqitousKVSProxy sharedKVSProxy] getAll]; - NSLog(@"All: %@",all); - } -} - -int ckdproxymain(int argc, const char *argv[]) -{ - secdebug(XPROXYSCOPE, "Starting CloudKeychainProxy"); - char *wait4debugger = getenv("WAIT4DEBUGGER"); - if (wait4debugger && !strcasecmp("YES", wait4debugger)) - { - syslog(LOG_ERR, "Waiting for debugger"); - kill(getpid(), SIGSTOP); - } - - if (argc > 1) { - diagnostics(argc, argv); - return 0; - } - -#if !TARGET_IPHONE_SIMULATOR - xpc_track_activity(); // sets us up for idle timeout handling -#endif - - // DISPATCH_TARGET_QUEUE_DEFAULT - xpc_connection_t listener = xpc_connection_create_mach_service(xpcServiceName, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER); - xpc_connection_set_event_handler(listener, ^(xpc_object_t object){ cloudkeychainproxy_event_handler(object); }); - - [UbiqitousKVSProxy sharedKVSProxy]; - - // It looks to me like there is insufficient locking to allow a request to come in on the XPC connection while doing the initial all items. - // Therefore I'm leaving the XPC connection suspended until that has time to process. - xpc_connection_resume(listener); - - @autoreleasepool - { - secdebug(XPROXYSCOPE, "Starting mainRunLoop"); - NSRunLoop *runLoop = [NSRunLoop mainRunLoop]; - [runLoop run]; - } - - secdebug(XPROXYSCOPE, "Exiting CloudKeychainProxy"); - - return EXIT_FAILURE; -} diff --git a/sec/SOSCircle/CloudKeychainProxy/scripts/sosbuildroot b/sec/SOSCircle/CloudKeychainProxy/scripts/sosbuildroot deleted file mode 100755 index efa31374..00000000 --- a/sec/SOSCircle/CloudKeychainProxy/scripts/sosbuildroot +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/zsh -e - -if [ ! -d "Security.xcodeproj" ]; then - echo "Not in correct directory to build; currently in " `pwd` - exit 2 -fi - -localbase=`basename $PWD` -target=${1-world} -config=${2-Release} -roots=/var/tmp -project=Security - -~rc/bin/buildit . --rootsDirectory=/var/tmp -noverify -project $project -archive -dsymsInDstroot \ - -target $target \ - -configuration $config || { echo 'build failed' ; exit 1; } - -rootsDir=/var/tmp/${project}_${localbase}.roots -buildRoots=$rootsDir/BuildRecords/${project}_install - -roottar=/tmp/security.roots.tgz -symtar=/tmp/security.syms.tgz -srctar=/tmp/security.src.tgz - -cp $rootsDir/Archives/Security_${localbase}_DSTROOT.tar.gz $roottar - -tar -czvf $symtar -C ${buildRoots}/Symbols . &> /dev/null -tar -czvf $srctar -C ${rootsDir}/Sources/${project} . &> /dev/null - -echo "now run" -echo " ~/bin/install_on_devices" diff --git a/sec/SOSCircle/CloudKeychainProxy/scripts/sshauser b/sec/SOSCircle/CloudKeychainProxy/scripts/sshauser deleted file mode 100755 index 81fc6fb5..00000000 --- a/sec/SOSCircle/CloudKeychainProxy/scripts/sshauser +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/expect -- - -proc usage {} { - puts stderr "Usage: sshauser \[ --retry \] port user \[ command ... \]" - exit 22 -} - -if { $argc < 2 } { - usage -} - -set arg 0 -set retry 0 -if { [lindex $argv $arg] == "--retry" } { - set retry 1 - set arg [expr $arg + 1] -} -set offset [lindex $argv $arg] -set arg [expr $arg + 1] -set username [lindex $argv $arg] -set arg [expr $arg + 1] -set command [lrange $argv $arg $argc] - -set password "alpine" -set timeout 60 - -# trap SIGWINCH and pass to spawned process -trap { - set rows [stty rows] - set cols [stty columns] - stty rows $rows columns $cols < $spawn_out(slave,name) -} WINCH - -set continue 1 -while { $continue } { - set continue $retry - spawn ssh -o NoHostAuthenticationForLocalhost=yes -p $offset $username@localhost - while { 1 } { - expect "Are you sure you want to continue connecting (yes/no)" { - send "yes\r" - } "password:" { - send "$password\r" - } "#" { - if { $argc > 2 } { send "$command\r" } - interact - break - } "mobile" { - if { $argc > 2 } { send "$command\r" } - interact - break - } "ssh: connect to host localhost port $offset: Connection refused" { - if { $retry } { - wait - set continue $retry - send_user "conection lost... retrying in 5 seconds.\n" - sleep 5 - } - break - } "ssh_exchange_identification: read: Connection reset by peer" { - if { $retry } { - wait - set continue $retry - send_user "Device rebooting waiting for 15 seconds.\n" - sleep 15 - } - break - } - } -} diff --git a/sec/SOSCircle/Regressions/CKDKeyValueStore.h b/sec/SOSCircle/Regressions/CKDKeyValueStore.h deleted file mode 100644 index 48759223..00000000 --- a/sec/SOSCircle/Regressions/CKDKeyValueStore.h +++ /dev/null @@ -1,78 +0,0 @@ -// -// CKDKeyValueStore.h -// sec -// -// Created by John Hurley on 9/9/12. -// -// - -#import -//#import "CKDKVSProxy.h" -#import "SOSCloudKeychainConstants.h" -#import "SOSCloudKeychainClient.h" - -extern CFStringRef kCKDKVSRemoteStoreID; -extern CFStringRef kCKDAWSRemoteStoreID; - -//--- protocol --- - -@protocol CKDKVSDelegate - -@required - -- (id)objectForKey:(NSString *)aKey; -- (void)setObject:(id)anObject forKey:(NSString *)aKey; -- (void)removeObjectForKey:(NSString *)aKey; - -- (NSDictionary *)dictionaryRepresentation; - -- (BOOL)synchronize; - -@optional -- (BOOL)isLocalKVS; -// DEBUG -- (void)setDictionaryRepresentation:(NSMutableDictionary *)initialValue; -- (void)clearPersistentStores; - -@end - -//--- interface --- - -@interface CKDKeyValueStore : NSObject -{ - BOOL localKVS; - BOOL persistStore; - CloudItemsChangedBlock itemsChangedCallback; -} - -@property (retain) id delegate; -@property (retain) NSString *identifier; -@property (retain) NSString *path; - -- (BOOL)synchronize; -+ (CKDKeyValueStore *)defaultStore:(NSString *)identifier itemsChangedBlock:(CloudItemsChangedBlock)itemsChangedBlock; -- (id)initWithIdentifier:(NSString *)xidentifier itemsChangedBlock:(CloudItemsChangedBlock)itemsChangedBlock; - -+ (CFStringRef)remoteStoreID; - -- (id)initWithItemsChangedBlock:(CloudItemsChangedBlock)itemsChangedBlock; -- (void)cloudChanged:(NSNotification*)notification; - -@end - -@interface CKDKeyValueStoreCollection : NSObject -{ - dispatch_queue_t syncrequestqueue; - NSMutableDictionary *store; -} -@property (retain) NSMutableDictionary *collection; - -+ (id)sharedInstance; -+ (id )defaultStore:(NSString *)identifier itemsChangedBlock:(CloudItemsChangedBlock)itemsChangedBlock; -+ (void)enqueueWrite:(id)anObject forKey:(NSString *)aKey from:(NSString *)identifier; -+ (id)enqueueWithReply:(NSString *)aKey; -+ (BOOL)enqueueSyncWithReply; -+ (void)postItemChangedNotification:(NSString *)keyThatChanged from:(NSString *)identifier; -+ (void)postItemsChangedNotification:(NSArray *)keysThatChanged from:(NSString *)identifier; - -@end diff --git a/sec/SOSCircle/Regressions/SOSTestDataSource.c b/sec/SOSCircle/Regressions/SOSTestDataSource.c deleted file mode 100644 index 1045f804..00000000 --- a/sec/SOSCircle/Regressions/SOSTestDataSource.c +++ /dev/null @@ -1,382 +0,0 @@ -// -// SOSTestDataSource.c -// sec -// -// Created by Michael Brouwer on 9/28/12. -// -// - -#include "SOSTestDataSource.h" - -#include -#include -#include -#include -#include -#include -#include - -static CFStringRef sErrorDomain = CFSTR("com.apple.testdatasource"); - -enum { - kSOSObjectMallocFailed = 1, - kAddDuplicateEntry, - kSOSObjectNotFouncError = 1, -}; - -typedef struct SOSTestDataSource *SOSTestDataSourceRef; - -struct SOSTestDataSource { - struct SOSDataSource ds; - unsigned gm_count; - unsigned cm_count; - unsigned co_count; - CFMutableDictionaryRef database; - uint8_t manifest_digest[SOSDigestSize]; - bool clean; -}; - -typedef struct SOSTestDataSourceFactory *SOSTestDataSourceFactoryRef; - -struct SOSTestDataSourceFactory { - struct SOSDataSourceFactory dsf; - CFMutableDictionaryRef data_sources; -}; - - -/* DataSource protocol. */ -static bool get_manifest_digest(SOSDataSourceRef data_source, uint8_t *out_digest, CFErrorRef *error) { - struct SOSTestDataSource *ds = (struct SOSTestDataSource *)data_source; - if (!ds->clean) { - SOSManifestRef mf = data_source->copy_manifest(data_source, error); - if (mf) { - CFRelease(mf); - } else { - return false; - } - } - memcpy(out_digest, ds->manifest_digest, SOSDigestSize); - ds->gm_count++; - return true; -} - -static SOSManifestRef copy_manifest(SOSDataSourceRef data_source, CFErrorRef *error) { - struct SOSTestDataSource *ds = (struct SOSTestDataSource *)data_source; - ds->cm_count++; - __block struct SOSDigestVector dv = SOSDigestVectorInit; - CFDictionaryForEach(ds->database, ^(const void *key, const void *value) { - SOSDigestVectorAppend(&dv, CFDataGetBytePtr((CFDataRef)key)); - }); - SOSDigestVectorSort(&dv); - SOSManifestRef manifest = SOSManifestCreateWithBytes((const uint8_t *)dv.digest, dv.count * SOSDigestSize, error); - SOSDigestVectorFree(&dv); - ccdigest(ccsha1_di(), SOSManifestGetSize(manifest), SOSManifestGetBytePtr(manifest), ds->manifest_digest); - ds->clean = true; - - return manifest; -} - -static bool foreach_object(SOSDataSourceRef data_source, SOSManifestRef manifest, CFErrorRef *error, bool (^handle_object)(SOSObjectRef object, CFErrorRef *error)) { - struct SOSTestDataSource *ds = (struct SOSTestDataSource *)data_source; - ds->co_count++; - __block bool result = true; - SOSManifestForEach(manifest, ^(CFDataRef key) { - CFDictionaryRef dict = (CFDictionaryRef)CFDictionaryGetValue(ds->database, key); - if (dict) { - result = result && handle_object((SOSObjectRef)dict, error); - } else { - result = false; - if (error) { - // TODO: Collect all missing keys in an array and return an single error at the end with all collected keys - // Collect all errors as chained errors. - CFErrorRef old_error = *error; - *error = NULL; - SecCFCreateErrorWithFormat(kSOSObjectNotFouncError, sErrorDomain, old_error, error, 0, CFSTR("key %@ not in database"), key); - } - } - }); - return result; -} - -static void dispose(SOSDataSourceRef data_source) { - struct SOSTestDataSource *ds = (struct SOSTestDataSource *)data_source; - free(ds); -} - -static SOSObjectRef createWithPropertyList(SOSDataSourceRef ds, CFDictionaryRef plist, CFErrorRef *error) { - return (SOSObjectRef)CFDictionaryCreateCopy(kCFAllocatorDefault, plist); -} - -static CFDataRef SOSObjectCopyDER(SOSObjectRef object, CFErrorRef *error) { - CFDictionaryRef dict = (CFDictionaryRef)object; - size_t size = der_sizeof_plist(dict, error); - CFMutableDataRef data = CFDataCreateMutable(0, size); - if (data) { - CFDataSetLength(data, size); - uint8_t *der = (uint8_t *)CFDataGetMutableBytePtr(data); - uint8_t *der_end = der + size; - der_end = der_encode_plist(dict, error, der, der_end); - assert(der_end == der); - } else if (error && *error == NULL) { - *error = CFErrorCreate(0, sErrorDomain, kSOSObjectMallocFailed, NULL); - } - return data; -} - -static CFDataRef ccdigest_copy_data(const struct ccdigest_info *di, size_t len, - const void *data, CFErrorRef *error) { - CFMutableDataRef digest = CFDataCreateMutable(0, di->output_size); - if (digest) { - CFDataSetLength(digest, di->output_size); - ccdigest(di, len, data, CFDataGetMutableBytePtr(digest)); - } else if (error && *error == NULL) { - *error = CFErrorCreate(0, sErrorDomain, kSOSObjectMallocFailed, NULL); - } - return digest; -} - -static CFDataRef copyDigest(SOSObjectRef object, CFErrorRef *error) { - CFMutableDictionaryRef ocopy = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, (CFDictionaryRef)object); - CFDictionaryRemoveValue(ocopy, kSecClass); - CFDataRef der = SOSObjectCopyDER((SOSObjectRef)ocopy, error); - CFRelease(ocopy); - CFDataRef digest = NULL; - if (der) { - digest = ccdigest_copy_data(ccsha1_di(), CFDataGetLength(der), CFDataGetBytePtr(der), error); - CFRelease(der); - } - return digest; -} - -static CFDataRef copyPrimaryKey(SOSObjectRef object, CFErrorRef *error) { - CFMutableDictionaryRef ocopy = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - CFTypeRef pkNames[] = { - CFSTR("acct"), - CFSTR("agrp"), - CFSTR("svce"), - CFSTR("sync"), - CFSTR("sdmn"), - CFSTR("srvr"), - CFSTR("ptcl"), - CFSTR("atyp"), - CFSTR("port"), - CFSTR("path"), - CFSTR("ctyp"), - CFSTR("issr"), - CFSTR("slnr"), - CFSTR("kcls"), - CFSTR("klbl"), - CFSTR("atag"), - CFSTR("crtr"), - CFSTR("type"), - CFSTR("bsiz"), - CFSTR("esiz"), - CFSTR("sdat"), - CFSTR("edat"), - }; - CFSetRef pkAttrs = CFSetCreate(kCFAllocatorDefault, pkNames, array_size(pkNames), &kCFTypeSetCallBacks); - CFDictionaryForEach((CFDictionaryRef)object, ^(const void *key, const void *value) { - if (CFSetContainsValue(pkAttrs, key)) - CFDictionaryAddValue(ocopy, key, value); - }); - CFRelease(pkAttrs); - CFDataRef der = SOSObjectCopyDER((SOSObjectRef)ocopy, error); - CFRelease(ocopy); - CFDataRef digest = NULL; - if (der) { - digest = ccdigest_copy_data(ccsha1_di(), CFDataGetLength(der), CFDataGetBytePtr(der), error); - CFRelease(der); - } - return digest; -} - -static CFDictionaryRef copyPropertyList(SOSObjectRef object, CFErrorRef *error) { - return (CFDictionaryRef) CFRetain(object); -} - -// Return the newest object -static SOSObjectRef copyMergedObject(SOSObjectRef object1, SOSObjectRef object2, CFErrorRef *error) { - CFDictionaryRef dict1 = (CFDictionaryRef)object1; - CFDictionaryRef dict2 = (CFDictionaryRef)object2; - SOSObjectRef result = NULL; - CFDateRef m1, m2; - m1 = CFDictionaryGetValue(dict1, kSecAttrModificationDate); - m2 = CFDictionaryGetValue(dict2, kSecAttrModificationDate); - switch (CFDateCompare(m1, m2, NULL)) { - case kCFCompareGreaterThan: - result = (SOSObjectRef)dict1; - break; - case kCFCompareLessThan: - result = (SOSObjectRef)dict2; - break; - case kCFCompareEqualTo: - { - // Return the item with the smallest digest. - CFDataRef digest1 = copyDigest(object1, error); - CFDataRef digest2 = copyDigest(object2, error); - if (digest1 && digest2) switch (CFDataCompare(digest1, digest2)) { - case kCFCompareGreaterThan: - case kCFCompareEqualTo: - result = (SOSObjectRef)dict2; - break; - case kCFCompareLessThan: - result = (SOSObjectRef)dict1; - break; - } - CFReleaseSafe(digest2); - CFReleaseSafe(digest1); - break; - } - } - CFRetainSafe(result); - return result; -} - -SOSDataSourceRef SOSTestDataSourceCreate(void) { - SOSTestDataSourceRef ds = calloc(1, sizeof(struct SOSTestDataSource)); - - ds->ds.get_manifest_digest = get_manifest_digest; - ds->ds.copy_manifest = copy_manifest; - ds->ds.foreach_object = foreach_object; - ds->ds.release = dispose; - ds->ds.add = SOSTestDataSourceAddObject; - - ds->ds.createWithPropertyList = createWithPropertyList; - ds->ds.copyDigest = copyDigest; - ds->ds.copyPrimaryKey = copyPrimaryKey; - ds->ds.copyPropertyList = copyPropertyList; - ds->ds.copyMergedObject = copyMergedObject; - - ds->database = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - ds->clean = false; - - return (SOSDataSourceRef)ds; -} - -static CFArrayRef SOSTestDataSourceFactoryCopyNames(SOSDataSourceFactoryRef factory) -{ - SOSTestDataSourceFactoryRef dsf = (SOSTestDataSourceFactoryRef) factory; - CFMutableArrayRef result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - - CFDictionaryForEach(dsf->data_sources, ^(const void*key, const void*value) { CFArrayAppendValue(result, key); }); - - return result; -} - -static SOSDataSourceRef SOSTestDataSourceFactoryCreateDataSource(SOSDataSourceFactoryRef factory, CFStringRef dataSourceName, bool readOnly __unused, CFErrorRef *error) -{ - SOSTestDataSourceFactoryRef dsf = (SOSTestDataSourceFactoryRef) factory; - - return (SOSDataSourceRef) CFDictionaryGetValue(dsf->data_sources, dataSourceName); -} - -static void SOSTestDataSourceFactoryDispose(SOSDataSourceFactoryRef factory) -{ - SOSTestDataSourceFactoryRef dsf = (SOSTestDataSourceFactoryRef) factory; - - CFReleaseNull(dsf->data_sources); - free(dsf); -} - -SOSDataSourceFactoryRef SOSTestDataSourceFactoryCreate() { - SOSTestDataSourceFactoryRef dsf = calloc(1, sizeof(struct SOSTestDataSourceFactory)); - - dsf->dsf.copy_names = SOSTestDataSourceFactoryCopyNames; - dsf->dsf.create_datasource = SOSTestDataSourceFactoryCreateDataSource; - dsf->dsf.release = SOSTestDataSourceFactoryDispose; - dsf->data_sources = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, NULL); - - return &(dsf->dsf); -} - -static void do_nothing(SOSDataSourceRef ds) -{ -} - -void SOSTestDataSourceFactoryAddDataSource(SOSDataSourceFactoryRef factory, CFStringRef name, SOSDataSourceRef ds) -{ - SOSTestDataSourceFactoryRef dsf = (SOSTestDataSourceFactoryRef) factory; - - // TODO This hack sucks. It leaks now. - ds->release = do_nothing; - - CFDictionarySetValue(dsf->data_sources, name, ds); - -} - -SOSMergeResult SOSTestDataSourceAddObject(SOSDataSourceRef data_source, SOSObjectRef object, CFErrorRef *error) { - struct SOSTestDataSource *ds = (struct SOSTestDataSource *)data_source; - bool result = false; - CFDataRef key = copyDigest(object, error); - if (key) { - SOSObjectRef myObject = (SOSObjectRef)CFDictionaryGetValue(ds->database, key); - SOSObjectRef merged = NULL; - if (myObject) { - merged = copyMergedObject(object, myObject, error); - } else { - merged = object; - CFRetain(merged); - } - if (merged) { - result = true; - if (!CFEqualSafe(merged, myObject)) { - CFDictionarySetValue(ds->database, key, merged); - ds->clean = false; - } - CFRelease(merged); - } - CFRelease(key); - } - return result; -} - -bool SOSTestDataSourceDeleteObject(SOSDataSourceRef data_source, CFDataRef key, CFErrorRef *error) { - //struct SOSTestDataSource *ds = (struct SOSTestDataSource *)data_source; - return false; -} - -CFMutableDictionaryRef SOSTestDataSourceGetDatabase(SOSDataSourceRef data_source) { - struct SOSTestDataSource *ds = (struct SOSTestDataSource *)data_source; - return ds->database; -} - -// This works for any datasource, not just the test one, but it's only used in testcases, so it's here for now. -SOSObjectRef SOSDataSourceCreateGenericItemWithData(SOSDataSourceRef ds, CFStringRef account, CFStringRef service, bool is_tomb, CFDataRef data) { -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) - abort(); -#else - int32_t value = 0; - CFNumberRef zero = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value); - value = 1; - CFNumberRef one = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value); - CFAbsoluteTime timestamp = 3700000; - CFDateRef now = CFDateCreate(kCFAllocatorDefault, timestamp); - CFDictionaryRef dict = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, - kSecClass, kSecClassGenericPassword, - kSecAttrSynchronizable, one, - kSecAttrTombstone, is_tomb ? one : zero, - kSecAttrAccount, account, - kSecAttrService, service, - kSecAttrCreationDate, now, - kSecAttrModificationDate, now, - kSecAttrAccessGroup, CFSTR("test"), - kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked, - !is_tomb && data ? kSecValueData : NULL,data, - NULL); - CFRelease(one); - CFRelease(zero); - CFReleaseSafe(now); - CFErrorRef localError = NULL; - SOSObjectRef object = ds->createWithPropertyList(ds, dict, &localError); - if (!object) { - secerror("createWithPropertyList: %@ failed: %@", dict, localError); - CFRelease(localError); - } - CFRelease(dict); - return object; -#endif -} - -SOSObjectRef SOSDataSourceCreateGenericItem(SOSDataSourceRef ds, CFStringRef account, CFStringRef service) { - return SOSDataSourceCreateGenericItemWithData(ds, account, service, false, NULL); -} diff --git a/sec/SOSCircle/Regressions/SOSTestDataSource.h b/sec/SOSCircle/Regressions/SOSTestDataSource.h deleted file mode 100644 index 7c0d0463..00000000 --- a/sec/SOSCircle/Regressions/SOSTestDataSource.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// SOSTestDataSource.h -// sec -// -// Created by Michael Brouwer on 9/28/12. -// -// - -#ifndef _SEC_SOSTestDataSource_H_ -#define _SEC_SOSTestDataSource_H_ - -#include - -// -// MARK: Data Source Functions -// -SOSDataSourceRef SOSTestDataSourceCreate(void); - -CFMutableDictionaryRef SOSTestDataSourceGetDatabase(SOSDataSourceRef data_source); - -SOSMergeResult SOSTestDataSourceAddObject(SOSDataSourceRef data_source, SOSObjectRef object, CFErrorRef *error); -bool SOSTestDataSourceDeleteObject(SOSDataSourceRef data_source, CFDataRef key, CFErrorRef *error); - -// -// MARK: Data Source Factory Functions -// - -SOSDataSourceFactoryRef SOSTestDataSourceFactoryCreate(void); -void SOSTestDataSourceFactoryAddDataSource(SOSDataSourceFactoryRef factory, CFStringRef name, SOSDataSourceRef ds); - -SOSObjectRef SOSDataSourceCreateGenericItemWithData(SOSDataSourceRef ds, CFStringRef account, CFStringRef service, bool is_tomb, CFDataRef data); -SOSObjectRef SOSDataSourceCreateGenericItem(SOSDataSourceRef ds, CFStringRef account, CFStringRef service); - -#endif /* _SEC_SOSTestDataSource_H_ */ diff --git a/sec/SOSCircle/Regressions/SOSTestTransport.c b/sec/SOSCircle/Regressions/SOSTestTransport.c deleted file mode 100644 index a00acfa6..00000000 --- a/sec/SOSCircle/Regressions/SOSTestTransport.c +++ /dev/null @@ -1,48 +0,0 @@ -// -// SOSTestTransport.c -// sec -// -// Created by Michael Brouwer on 10/16/12. -// - -#include "SOSTestTransport.h" - -#include -#include - -struct SOSTestTransport { - struct SOSTransport t; - CFDataRef lastMessage; -}; - - -/* Transport protocol. */ -static bool SOSTestTransportQueue(SOSTransportRef transport, CFDataRef message) { - struct SOSTestTransport *t = (struct SOSTestTransport *)transport; - if (t->lastMessage) { - fail("We already had an unproccessed message"); - CFReleaseNull(t->lastMessage); - } - CFRetain(message); - t->lastMessage = message; - return true; -} - -CFDataRef SOSTestTransportDequeue(SOSTransportRef transport) { - struct SOSTestTransport *t = (struct SOSTestTransport *)transport; - CFDataRef message = t->lastMessage; - t->lastMessage = NULL; - return message; -} - -void SOSTestTransportDispose(SOSTransportRef transport) { - struct SOSTestTransport *t = (struct SOSTestTransport *)transport; - free(t); -} - -SOSTransportRef SOSTestTransportCreate(void) { - struct SOSTestTransport *transport = calloc(1, sizeof(struct SOSTestTransport)); - transport->t.send = SOSTestTransportQueue; - - return (SOSTransportRef)transport; -} diff --git a/sec/SOSCircle/Regressions/SOSTestTransport.h b/sec/SOSCircle/Regressions/SOSTestTransport.h deleted file mode 100644 index 8f828a66..00000000 --- a/sec/SOSCircle/Regressions/SOSTestTransport.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// SOSTestTransport.h -// sec -// -// Created by Michael Brouwer on 10/16/12. -// -// - -#ifndef _SEC_SOSTESTTRANSPORT_H_ -#define _SEC_SOSTESTTRANSPORT_H_ - -#include - -__BEGIN_DECLS - -SOSTransportRef SOSTestTransportCreate(void); - -CFDataRef SOSTestTransportDequeue(SOSTransportRef transport); - -void SOSTestTransportDispose(SOSTransportRef transport); - -__END_DECLS - -#endif /* _SEC_SOSTESTTRANSPORT_H_ */ diff --git a/sec/SOSCircle/Regressions/sc-100-devicecircle.c b/sec/SOSCircle/Regressions/sc-100-devicecircle.c deleted file mode 100644 index 9d92b123..00000000 --- a/sec/SOSCircle/Regressions/sc-100-devicecircle.c +++ /dev/null @@ -1,565 +0,0 @@ -// -// sc-100-devicecircle.c -// sec -// -// Created by John Hurley 10/16/12. -// Copyright 2012 Apple Inc. All rights reserved. -// - -/* - This test is a combination of sc-75, sc_93 and sc_94 that can - be run on two devices. - - The test will look for a circle in kvs - - if none exists, it will create one - - if one exists, it will try to join - - Whenever you confirm a new peer, must start sync - - Test sc-98 can be run before this to clear out kvs -*/ - -// Run on 2 devices: -// /AppleInternal/Applications/SecurityTests.app/SecurityTests sc_100_devicecircle -v -- -i alice -// /AppleInternal/Applications/SecurityTests.app/SecurityTests sc_100_devicecircle -v -- -i bob - -#include -#include - -#include "SOSCircle_regressions.h" - -#include - -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include - - -#include - -#include -#include -#include -#include -#include -#include - -#include "SOSCircle_regressions.h" -#include "SOSRegressionUtilities.h" -#include "SOSTestDataSource.h" -#include "SOSTestTransport.h" -#include "SOSCloudKeychainClient.h" - -#include - -#ifndef SEC_CONST_DECL -#define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); -#endif - -//static dispatch_queue_t wait_queue = NULL; - -#define VALUECFNULLCHECK(msg) if (msg == NULL || CFGetTypeID(msg) == CFNullGetTypeID()) { pass("CFNull message"); return 0; } - -// TODO _SecServerKeychainSyncUpdate - -// MARK: ----- Constants ----- - -static CFStringRef circleKey = CFSTR("Circle"); -//static CFStringRef messageKey = CFSTR("Message"); -static CFStringRef messageFromAliceToBobKey = CFSTR("AliceToBob"); -static CFStringRef messageFromBobToAliceKey = CFSTR("BobToAlice"); - -#if USE_BOB_GO -static CFStringRef messageGoBobGoKey = CFSTR("GoBobGo"); -#endif - -struct SOSKVSTransport { - struct SOSTransport t; - CFStringRef messageKey; -}; - -#include -#include - -static bool kvsTransportSend(CFStringRef key, CFDataRef message) { - __block bool success = true; - __block dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0); - - CFDictionaryRef objects = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, key, message, NULL); - - CFStringRef desc = SOSMessageCopyDescription(message); - pass("kvsTransportSend: %@ %@", key, desc); - CFReleaseSafe(desc); - - SOSCloudKeychainPutObjectsInCloud(objects, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), - ^ (CFDictionaryRef returnedValues, CFErrorRef error) - { - ok(error == NULL, "Error from SOSCloudKeychainPutObjectsInCloud %@:", error); - if (error) - success = false; - dispatch_semaphore_signal(waitSemaphore); - }); - - dispatch_release(waitSemaphore); - - return success; -} - -static void putCircleInCloud(SOSCircleRef circle, dispatch_queue_t work_queue, dispatch_group_t work_group) -{ - CFErrorRef error = NULL; - CFDataRef newCloudCircleEncoded = SOSCircleCopyEncodedData(circle, kCFAllocatorDefault, &error); - ok(newCloudCircleEncoded, "Encoded as: %@ [%@]", newCloudCircleEncoded, error); - - // Send the circle with our application request back to cloud - testPutObjectInCloud(circleKey, newCloudCircleEncoded, &error, work_group, work_queue); - CFReleaseSafe(newCloudCircleEncoded); -} - -static void mutate_inflated_circle(SOSCircleRef newCircle, - dispatch_queue_t work_queue, dispatch_group_t work_group, - void (^action)(SOSCircleRef circle)) -{ -//JCH action(newCircle); - - putCircleInCloud(newCircle, work_queue, work_group); - pass("Put circle in cloud: (%@)", newCircle); -} - -static void mutate_account_circle(SOSAccountRef account, - CFDataRef encodedCircle, - dispatch_queue_t work_queue, dispatch_group_t work_group, - void (^action)(SOSCircleRef circle)) -{ - bool mutated = false; - - CFErrorRef error = NULL; - SKIP: - { - skip("Must be CFData!", 3, encodedCircle && (CFDataGetTypeID() == CFGetTypeID(encodedCircle))); - SOSCircleRef newCircle = SOSCircleCreateFromData(kCFAllocatorDefault, encodedCircle, &error); - ok(newCircle, "Decoded data version of circle: %@", newCircle); - - SOSCircleRef accountCircle = SOSAccountFindCircle(account, SOSCircleGetName(newCircle), NULL); - ok(accountCircle, "Found our circle in account"); - - if (!CFEqual(newCircle, accountCircle)) { - pass("New circle and accountCircle not equal"); - - // JCH JCH - action(newCircle); - - bool updated = SOSAccountUpdateCircle(account, newCircle, &error); - if (updated) { - pass("Updated account with new circle"); - mutated = true; - mutate_inflated_circle(newCircle, work_queue, work_group, action); - } - } - } - pass("mutate_account_circle exit"); -} - -static void SOSCloudKeychainRegisterKeysAndGetWithNotification(CFArrayRef keysToRegister, dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock) -{ - SOSCloudKeychainRegisterKeysAndGet(keysToRegister, processQueue, replyBlock, - ^(CFDictionaryRef dict) { replyBlock(dict, NULL);}); -} - -#define kAlicePeerID CFSTR("alice-peer-id") -#define kBobPeerID CFSTR("bob-peer-id") - -static void runTests(bool Alice, dispatch_queue_t work_queue, dispatch_group_t work_group) -{ - SecKeyRef user_key = NULL; - SecKeyRef public_key = NULL; - CFErrorRef error = NULL; - CFStringRef cflabel = CFSTR("TEST_USERKEY"); - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - - GenerateECPair(256, &public_key, &user_key); - SOSCCRegisterUserCredentials(cflabel, cfpassword, &error); - CFReleaseNull(public_key); - CFReleaseNull(cfpassword); - - SOSDataSourceFactoryRef our_data_source_factory = SOSTestDataSourceFactoryCreate(); - SOSDataSourceRef our_data_source = SOSTestDataSourceCreate(); - SOSTestDataSourceFactoryAddDataSource(our_data_source_factory, circleKey, our_data_source); - - CFDictionaryRef gestalt = SOSCreatePeerGestaltFromName(Alice? kAlicePeerID: kBobPeerID); - - SOSAccountRef our_account = SOSAccountCreate(kCFAllocatorDefault, gestalt, our_data_source_factory, NULL, NULL); - SOSAccountEnsureCircle(our_account, circleKey, NULL); - - SOSFullPeerInfoRef our_full_peer_info = SOSAccountGetMyFullPeerInCircleNamed(our_account, circleKey, &error); - __block SOSPeerInfoRef our_peer_info = SOSFullPeerInfoGetPeerInfo(our_full_peer_info); - CFRetain(our_peer_info); - pass("We are %s (%@)", Alice?"Alice":"Bob", our_peer_info); - - ok(our_peer_info, "Peer Info: %@ [error: %@]", our_peer_info, error); - - /// Setup ck notifications. - - CFArrayRef keysToRegister = NULL; - - CFStringRef message_key; - - if (Alice) - { - keysToRegister = CFArrayCreateForCFTypes(kCFAllocatorDefault, circleKey, messageFromBobToAliceKey, NULL); - message_key = messageFromAliceToBobKey; - } - else - { -#if USE_BOB_GO - keysToRegister = CFArrayCreateForCFTypes(kCFAllocatorDefault, circleKey, messageFromAliceToBobKey, messageGoBobGoKey, NULL); -#else - keysToRegister = CFArrayCreateForCFTypes(kCFAllocatorDefault, circleKey, messageFromAliceToBobKey, NULL); -#endif - message_key = messageFromBobToAliceKey; - } - - SOSPeerSendBlock transport = ^bool (CFDataRef message, CFErrorRef *error) { - kvsTransportSend(message_key, message); - return true; - }; - - - __block CFIndex current = 0; - typedef CFIndex (^TestStateBlock) (CFDictionaryRef returnedValues, CFErrorRef error); - - //------------------------------------------------------------------------ - // ALICE - //------------------------------------------------------------------------ - CFArrayRef aliceWorkToDo = - CFArrayCreateForCFTypes(kCFAllocatorDefault, - ^ CFIndex (CFDictionaryRef returnedValues, CFErrorRef error) - { - /* - We get here as the return from registerkeys. - Here we create a fresh circle, add and accept ourselves - Then we post to the cloud and wait for a Circle changed notification - */ - - (void) returnedValues; (void) error; - - testClearAll(work_queue, work_group); - - CFErrorRef localError = NULL; - -#if USE_BOB_GO - testPutObjectInCloud(messageGoBobGoKey, CFSTR("Go Bob, Go!"), &localError, work_group, work_queue); -#endif - - SOSCircleRef circle = SOSAccountFindCircle(our_account, circleKey, NULL); - CFRetain(circle); - - ok(SOSCircleRequestAdmission(circle, SOSAccountGetPrivateCredential(our_account, &error), our_full_peer_info, &localError), "Requested admission (%@)", our_peer_info); - ok(SOSCircleAcceptRequests(circle, SOSAccountGetPrivateCredential(our_account, &error), our_full_peer_info, &localError), "Accepted self"); - - our_peer_info = SOSFullPeerInfoGetPeerInfo(our_full_peer_info); - - putCircleInCloud(circle, work_queue, work_group); - pass("Put circle in cloud: (%@)", circle); - - CFRelease(circle); - - return +1; - }, - ^ CFIndex (CFDictionaryRef returnedValues, CFErrorRef error) - { - __block CFIndex incrementAmount = 0; // Don't increment unless we find stuff - - /* - When we get here, it should only be because Bob has retrieved - our circle and requested admission to our circle. - If we don't find a circleKey entry, our test setup is wrong. - */ - SKIP: - { - __block CFErrorRef localError = NULL; - CFDataRef value = CFDictionaryGetValue(returnedValues, circleKey); - VALUECFNULLCHECK(value); - skip("cloudCircle NULL!", 5, value); - ok(value, "Found circle"); - - mutate_account_circle(our_account, value, work_queue, work_group, - ^ (SOSCircleRef circle) - { - ok(SOSCircleHasPeer(circle, our_peer_info, &localError), "We're a peer [error: %@]", localError); - CFReleaseNull(localError); - - is(SOSCircleCountPeers(circle), 1, "One peer, woot"); - is(SOSCircleCountApplicants(circle), 1, "One applicant, hope it's BOB"); - - CFErrorRef pkerr; - ok(SOSCircleAcceptRequests(circle, SOSAccountGetPrivateCredential(our_account, &pkerr), our_full_peer_info, &localError), "Accepted peers [error: %@]", localError); - CFReleaseNull(localError); - - ok(SOSCircleSyncWithPeer(our_full_peer_info, circle, our_data_source_factory, transport, kBobPeerID, &localError), "Started sync: [error: %@]", localError); - CFReleaseNull(localError); - - incrementAmount = 1; - }); - - CFReleaseSafe(localError); - } - - return incrementAmount; - }, - ^ (CFDictionaryRef returnedValues, CFErrorRef error) - { - CFErrorRef localError = NULL; - SOSCircleRef circle = SOSAccountFindCircle(our_account, circleKey, NULL); - CFDataRef message = CFDictionaryGetValue(returnedValues, messageFromBobToAliceKey); - VALUECFNULLCHECK(message); - - ok(message, "Saw response to manifest message from Bob"); - ok(SOSCircleHandlePeerMessage(circle, our_full_peer_info, our_data_source_factory, transport, kBobPeerID, message, &localError), "handle message from bob: [error: %@]", localError); - -#if TEST_EMPTY_ADD - // Sync again after adding an empty object - CFDictionaryRef object = CFDictionaryCreate(0, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - ok(SOSTestDataSourceAddObject(our_data_source, object, &error), "add empty object to datasource [error: %@]", error); - - ok(ourEngine = SOSCircleCopyEngine(circle, our_data_source_factory, &localError), "get ourEngine [error: %@]", localError); - - // Start syncing - SOSPeerRef bobPeer = SOSCircleCopyPeer(circle, transport, kBobPeerID, &localError); - ok(bobPeer, "Got bob: [error: %@]", error); - ok(SOSEngineSyncWithPeer(ourEngine, bobPeer, false, &localError), "tell Alice sync with peer Bob"); - SOSPeerDispose(bobPeer); - - CFReleaseNull(localError); -#endif - return 1; - }, -#if TEST_EMPTY_ADD - ^ (CFDictionaryRef returnedValues, CFErrorRef error) - { - CFErrorRef localError = NULL; - SOSCircleRef circle = SOSAccountFindCircle(our_account, circleKey); - CFDataRef message = CFDictionaryGetValue(returnedValues, messageFromBobToAliceKey); - VALUECFNULLCHECK(message); - ok(message, "Saw response to manifest message from Bob - 2"); - ok(SOSCircleHandlePeerMessage(circle, our_data_source_factory, transport, kBobPeerID, message, &localError), "handle message from bob: [error: %@]", localError); - return 1; - }, -#endif - NULL); - - //------------------------------------------------------------------------ - // BOB - //------------------------------------------------------------------------ - - CFArrayRef bobWorkToDo = - CFArrayCreateForCFTypes(kCFAllocatorDefault, - - ^ CFIndex (CFDictionaryRef returnedValues, CFErrorRef error) - { - __block CFIndex incrementAmount = 0; // Don't increment unless we find stuff - __block CFErrorRef localError = NULL; - -#if USE_BOB_GO - CFTypeRef goMessage = CFDictionaryGetValue(returnedValues, messageGoBobGoKey); - if (!goMessage) // We can discard any changes we see here; they are stale - return 0; - - SOSCloudKeychainRemoveObjectForKey(messageGoBobGoKey, work_queue, - ^ (CFDictionaryRef returnedValues, CFErrorRef error) - { - pass("ACK from messageGoBobGoKey"); - }); -#endif - - CFTypeRef value = CFDictionaryGetValue(returnedValues, circleKey); - VALUECFNULLCHECK(value); - - ok(value, "Found circle %@", value); - - mutate_account_circle(our_account, value, work_queue, work_group, - ^ (SOSCircleRef circle) - { - int peerCount = SOSCircleCountPeers(circle); - ok(peerCount == 1, "One peer, hope it's Alice"); - if (peerCount != 1) - printf("NOT One peer, hope it's Alice: saw %d peers\n", peerCount); - ok(SOSCircleCountApplicants(circle) == 0, "No applicants"); - CFErrorRef pkerr; - - ok(SOSCircleRequestAdmission(circle, SOSAccountGetPrivateCredential(our_account, &pkerr), our_full_peer_info, &localError), "Requested admission"); - our_peer_info = SOSFullPeerInfoGetPeerInfo(our_full_peer_info); - - incrementAmount = 1; - }); - - CFReleaseSafe(localError); - - return incrementAmount; - }, - ^ CFIndex (CFDictionaryRef returnedValues, CFErrorRef error) - { - __block CFIndex incrementAmount = 0; // Don't increment unless we find stuff - __block CFErrorRef localError = NULL; - - CFDataRef value = CFDictionaryGetValue(returnedValues, circleKey); - VALUECFNULLCHECK(value); - ok(value, "Found circle"); - - mutate_account_circle(our_account, value, work_queue, work_group, - ^ (SOSCircleRef circle) - { - ok(SOSCircleHasPeer(circle, our_peer_info, &localError), "We're a peer"); - ok(SOSCircleCountPeers(circle) == 2, "Both peers!"); - ok(SOSCircleCountApplicants(circle) == 0, "No applicants!"); - - CFDataRef message; - ok(message = CFDictionaryGetValue(returnedValues, messageFromAliceToBobKey), "got message from alice"); - // VALUECFNULLCHECK(message); - if (message == NULL || CFGetTypeID(message) == CFNullGetTypeID()) { pass("CFNull message"); return; } - ok(SOSCircleHandlePeerMessage(circle, our_full_peer_info, our_data_source_factory, transport, kAlicePeerID, message, &localError), "handle message from alice: %@", localError); - - incrementAmount = 1; - }); - - CFReleaseSafe(localError); - return incrementAmount; - - }, -#if TEST_EMPTY_ADD -/**/ - // this next block would normally be looking at the reply to the initial sync message. - // Since that one was the same we sent out, we won't get a notification for that. - // This block looks at the sync message of the empty object datasource - ^ (CFDictionaryRef returnedValues, CFErrorRef error) - { - CFErrorRef localError = NULL; - SOSCircleRef circle = SOSAccountFindCircle(our_account, circleKey); - CFDataRef message = CFDictionaryGetValue(returnedValues, messageFromBobToAliceKey); - VALUECFNULLCHECK(message); - ok(message, "Saw response to manifest message from Alice 2"); - ok(SOSCircleHandlePeerMessage(circle, our_data_source_factory, transport, kAlicePeerID, message, &localError), "handle message from Alice 2: %@", localError); - return 1; - }, -#endif - - NULL); - - //------------------------------------------------------------------------ - // START - //------------------------------------------------------------------------ - - CFArrayRef ourWork = Alice ? aliceWorkToDo : bobWorkToDo; - - SOSCloudKeychainRegisterKeysAndGetWithNotification(keysToRegister, work_queue, - ^ (CFDictionaryRef returnedValues, CFErrorRef error) - { - pass("Got key changes: %@ [error: %@]", returnedValues, error); - - CFReleaseSafe(error); - - TestStateBlock thingToDo = CFArrayGetValueAtIndex(ourWork, current); - - if (thingToDo) - { - pass("%s stage %d rv: %@ [error: %@]", Alice?"Alice":"Bob", (int)current, returnedValues, error); - current += thingToDo(returnedValues, error); - } - - if (current < 0 || current >= CFArrayGetCount(ourWork)) - dispatch_group_leave(work_group); - }); - - dispatch_group_wait(work_group, DISPATCH_TIME_FOREVER); - - // We probably never get here since the program exits.. - - CFReleaseNull(aliceWorkToDo); - CFReleaseNull(bobWorkToDo); - CFReleaseNull(gestalt); - CFReleaseNull(our_account); - CFReleaseNull(our_peer_info); - CFReleaseNull(user_key); - CFReleaseNull(public_key); // Should be NULL but just in case.. - -#if 0 - - if (Alice) - { - CFDictionaryRef object = CFDictionaryCreate(0, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - ok(SOSTestDataSourceAddObject(our_data_source, object, &error), "add empty object to datasource (error: %@)", error); - CFReleaseNull(error); - CFReleaseNull(object); - - sendManifestDigest(transportX, pqrEngine, our_circle, our_peer_info); - ok(waitForSemaphore(), "Got ACK for manifest with object"); - ok(handleCloudMessage(our_circle, our_data_source, t), "Got ACK for manifest with object"); - } -#endif -} - -// MARK: ----- start of all tests ----- -static void tests(bool Alice) -{ - dispatch_queue_t work_queue = dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - dispatch_group_t work_group = dispatch_group_create(); - - // Queue the work we want to do. - runTests(Alice, work_queue, work_group); - -} - -// define the options table for the command line -static const struct option options[] = -{ - { "verbose", optional_argument, NULL, 'v' }, - { "identity", optional_argument, NULL, 'i' }, - { "clear", optional_argument, NULL, 'C' }, - { } -}; - -static int kAliceTestCount = 22; -static int kBobTestCount = 20; - -int sc_100_devicecircle(int argc, char *const *argv) -{ - char *identity = NULL; -// extern int optind; - extern char *optarg; - int arg, argSlot; - bool Alice = false; - - while (argSlot = -1, (arg = getopt_long(argc, (char * const *)argv, "i:vC", options, &argSlot)) != -1) - switch (arg) - { - case 'i': - identity = (char *)(optarg); - break; - case 'C': // should set up to call testClearAll - break; - default: - secerror("arg: %s", optarg); - break; - } - - if (identity) - { - secerror("We are %s",identity); - if (!strcmp(identity, "alice")) - Alice = true; - } - - plan_tests(Alice?kAliceTestCount:kBobTestCount); - tests(Alice); - - return 0; -} diff --git a/sec/SOSCircle/Regressions/sc-101-accountsync.c b/sec/SOSCircle/Regressions/sc-101-accountsync.c deleted file mode 100644 index d433c628..00000000 --- a/sec/SOSCircle/Regressions/sc-101-accountsync.c +++ /dev/null @@ -1,574 +0,0 @@ -// -// sc-100-devicecircle.c -// sec -// -// Created by John Hurley 10/16/12. -// Copyright 2012 Apple Inc. All rights reserved. -// - -/* - This test is a combination of sc-75, sc_93 and sc_94 that can - be run on two devices. - - The test will look for a circle in kvs - - if none exists, it will create one - - if one exists, it will try to join - - Whenever you confirm a new peer, must start sync - - Test sc-98 can be run before this to clear out kvs -*/ - -// Run on 2 devices: -// /AppleInternal/Applications/SecurityTests.app/SecurityTests sc_101_accountsync -v -- -i alice -// /AppleInternal/Applications/SecurityTests.app/SecurityTests sc_101_accountsync -v -- -i bob - -#include -#include - -#include "SOSCircle_regressions.h" - -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include "SOSCircle_regressions.h" -#include "SOSRegressionUtilities.h" -#include "SOSTestDataSource.h" -#include "SOSTestTransport.h" -#include "SOSCloudKeychainClient.h" - -#include - -#ifndef SEC_CONST_DECL -#define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); -#endif - -//static dispatch_queue_t wait_queue = NULL; - -#define VALUECFNULLCHECK(msg) if (msg == NULL || CFGetTypeID(msg) == CFNullGetTypeID()) { pass("CFNull message"); return 0; } - -// TODO _SecServerKeychainSyncUpdate - -// MARK: ----- Constants ----- - -static CFStringRef circleKey = CFSTR("Circle"); - -struct SOSKVSTransport { - struct SOSTransport t; - CFStringRef messageKey; -}; - -#include -#include - -static void putCircleInCloud(SOSCircleRef circle, dispatch_queue_t work_queue, dispatch_group_t work_group) -{ - CFErrorRef error = NULL; - CFDataRef newCloudCircleEncoded = SOSCircleCopyEncodedData(circle, kCFAllocatorDefault, &error); - ok(newCloudCircleEncoded, "Encoded as: %@ [%@]", newCloudCircleEncoded, error); - - // Send the circle with our application request back to cloud - testPutObjectInCloud(circleKey, newCloudCircleEncoded, &error, work_group, work_queue); - CFReleaseSafe(newCloudCircleEncoded); -} - - -// artifacts of test harness : , dispatch_queue_t work_queue, dispatch_group_t work_group) -bool SOSAccountEstablishCircle(SOSAccountRef account, CFStringRef circleName, CFErrorRef *error, dispatch_queue_t work_queue, dispatch_group_t work_group); - -bool SOSAccountEstablishCircle(SOSAccountRef account, CFStringRef circleName, CFErrorRef *error, dispatch_queue_t work_queue, dispatch_group_t work_group) -{ - CFErrorRef localError = NULL; - SOSCircleRef circle = SOSAccountEnsureCircle(account, circleName, NULL); - CFRetain(circle); - SecKeyRef user_privkey = SOSAccountGetPrivateCredential(account, &localError); - - SOSFullPeerInfoRef our_full_peer_info = SOSAccountGetMyFullPeerInCircleNamed(account, circleName, &localError); - SOSPeerInfoRef our_peer_info = SOSFullPeerInfoGetPeerInfo(our_full_peer_info); - CFRetain(our_peer_info); - - SecKeyRef device_key = SOSFullPeerInfoCopyDeviceKey(our_full_peer_info, &localError); - ok(device_key, "Retrieved device_key from full peer info (Error: %@)", localError); - CFReleaseNull(device_key); - CFReleaseNull(localError); - ok(SOSCircleRequestAdmission(circle, user_privkey, our_full_peer_info, &localError), "Requested admission (%@)", our_peer_info); - ok(SOSCircleAcceptRequests(circle, user_privkey, our_full_peer_info, &localError), "Accepted self"); - - putCircleInCloud(circle, work_queue, work_group); - pass("Put (new) circle in cloud: (%@)", circle); - -#if 0 - - - SOSCircleRef oldCircle = SOSAccountFindCircle(account, SOSCircleGetName(circle)); - - if (!oldCircle) - return false; // Can't update one we don't have. - // TODO: Ensure we don't let circles get replayed. - - CFDictionarySetValue(account->circles, SOSCircleGetName(circle), circle); - -//---- - SOSCircleRef circle = SOSAccountFindCircle(our_account, circleKey); - CFRetain(circle); - - ok(SOSCircleRequestAdmission(circle, our_full_peer_info, user_key, &localError), "Requested admission (%@)", our_peer_info); - ok(SOSCircleAcceptRequests(circle, our_full_peer_info, user_key, &localError), "Accepted self"); - - putCircleInCloud(circle, work_queue, work_group); - -//----- -#endif - return true; -} - - -static void runTests(bool Alice, dispatch_queue_t work_queue, dispatch_group_t work_group) -{ - CFStringRef our_name = Alice ? CFSTR("Alice") : CFSTR("Bob"); - CFDictionaryRef our_gestalt = SOSCreatePeerGestaltFromName(our_name); - - dispatch_queue_t global_queue = dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - - CFErrorRef error = NULL; - - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - - CFDataRef parameters = SOSUserKeyCreateGenerateParameters(&error); - ok(parameters, "No parameters!"); - ok(error == NULL, "Error: (%@)", error); - CFReleaseNull(error); - - SecKeyRef user_privkey = SOSUserKeygen(cfpassword, parameters, &error); - CFReleaseNull(parameters); - CFReleaseNull(cfpassword); - - dispatch_semaphore_t start_semaphore = dispatch_semaphore_create(0); - - CFStringRef sBobReady = CFSTR("Bob-Ready"); - CFStringRef sAliceReady = CFSTR("Alice-Ready"); - __block CFDataRef foundNonce = NULL; - if (Alice) { - const CFIndex nonceByteCount = 10; - CFMutableDataRef nonce = CFDataCreateMutable(kCFAllocatorDefault, nonceByteCount); - CFDataSetLength(nonce, nonceByteCount); - SecRandomCopyBytes(kSecRandomDefault, CFDataGetLength(nonce), CFDataGetMutableBytePtr(nonce)); - - CloudItemsChangedBlock notification_block = ^ (CFDictionaryRef returnedValues) - { - CFTypeRef bobReadyValue = CFDictionaryGetValue(returnedValues, sBobReady); - if (isData(bobReadyValue) && CFEqual(bobReadyValue, nonce)) { - CFDictionaryRef changes = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, sAliceReady, kCFNull, sBobReady, kCFNull, NULL); - - SOSCloudKeychainPutObjectsInCloud(changes, global_queue, NULL); - - pass("signalling"); - dispatch_semaphore_signal(start_semaphore); - CFReleaseSafe(changes); - } - CFReleaseSafe(error); - }; - - CloudKeychainReplyBlock reply_block = ^ (CFDictionaryRef returnedValues, CFErrorRef error) - { - notification_block(returnedValues); - }; - - pass("Clearing"); - - testClearAll(global_queue, work_group); - - CFArrayRef bobKey = CFArrayCreateForCFTypes(kCFAllocatorDefault, sBobReady, NULL); - SOSCloudKeychainRegisterKeysAndGet(bobKey, work_queue, reply_block, notification_block); - - CFStringRef description = SOSInterestListCopyDescription(bobKey); - pass("%@", description); - - CFReleaseNull(description); - CFReleaseNull(bobKey); - - CFDictionaryRef changes = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, sAliceReady, nonce, NULL); - SOSCloudKeychainPutObjectsInCloud(changes, global_queue, NULL); - - description = SOSChangesCopyDescription(changes, true); - pass("%@", description); - CFReleaseNull(description); - - CFReleaseNull(changes); - } else { - CloudItemsChangedBlock notification_block = ^ (CFDictionaryRef returnedValues) - { - CFTypeRef aliceReadyValue = CFDictionaryGetValue(returnedValues, sAliceReady); - if (isData(aliceReadyValue)) { - foundNonce = (CFDataRef) aliceReadyValue; - CFRetain(foundNonce); - - pass("signalling found: %@", foundNonce); - dispatch_semaphore_signal(start_semaphore); - } - CFReleaseSafe(error); - }; - - CloudKeychainReplyBlock reply_block = ^ (CFDictionaryRef returnedValues, CFErrorRef error) - { - notification_block(returnedValues); - }; - - CFArrayRef aliceKey = CFArrayCreateForCFTypes(kCFAllocatorDefault, sAliceReady, NULL); - SOSCloudKeychainRegisterKeysAndGet(aliceKey, work_queue, reply_block, notification_block); - - CFStringRef description = SOSInterestListCopyDescription(aliceKey); - pass("%@", description); - CFReleaseNull(description); - - CFReleaseSafe(aliceKey); - } - - pass("Waiting"); - dispatch_semaphore_wait(start_semaphore, DISPATCH_TIME_FOREVER); - pass("Moving on"); - - - __block CFArrayRef ourWork = NULL; - __block CFIndex current = 0; - __block SOSAccountRef our_account = NULL; - typedef CFIndex (^TestStateBlock) (SOSAccountRef account, CFErrorRef error); - - SOSDataSourceFactoryRef our_data_source_factory = SOSTestDataSourceFactoryCreate(); - SOSDataSourceRef our_data_source = SOSTestDataSourceCreate(); - SOSTestDataSourceFactoryAddDataSource(our_data_source_factory, circleKey, our_data_source); - - CloudItemsChangedBlock notification_block = ^ (CFDictionaryRef returnedValues) - { - CFStringRef changesString = SOSChangesCopyDescription(returnedValues, false); - pass("Got: %@", changesString); - CFReleaseNull(changesString); - - CFErrorRef error = NULL; - - SOSAccountHandleUpdates(our_account, returnedValues, &error); - - TestStateBlock thingToDo = CFArrayGetValueAtIndex(ourWork, current); - - if (thingToDo) - { - pass("%@ stage %d rv: %@ [error: %@]", our_name, (int)current, returnedValues, error); - current += thingToDo(our_account, error); - } - - if (current < 0 || current >= CFArrayGetCount(ourWork)) - dispatch_group_leave(work_group); - - CFReleaseSafe(error); - }; - - CloudKeychainReplyBlock reply_block = ^ (CFDictionaryRef returnedValues, CFErrorRef error) - { - pass("Reply block"); - notification_block(returnedValues); - }; - - __block bool initialConnection = !Alice; - SOSAccountKeyInterestBlock updateKVSKeys = ^(bool getNewKeysOnly, CFArrayRef alwaysKeys, CFArrayRef afterFirstUnlockKeys, CFArrayRef unlockedKeys) { - CFMutableArrayRef keys = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, alwaysKeys); - CFArrayAppendArray(keys, afterFirstUnlockKeys, CFRangeMake(0, CFArrayGetCount(afterFirstUnlockKeys))); - CFArrayAppendArray(keys, unlockedKeys, CFRangeMake(0, CFArrayGetCount(unlockedKeys))); - - CFStringRef description = SOSInterestListCopyDescription(keys); - - pass("%@", description); - - CFReleaseNull(description); - - SOSCloudKeychainRegisterKeysAndGet(keys, work_queue, - initialConnection ? reply_block : NULL, notification_block); - - CFReleaseSafe(keys); - initialConnection = false; - }; - - SOSAccountDataUpdateBlock updateKVS = ^ bool (CFDictionaryRef changes, CFErrorRef *error) { - CFStringRef changesString = SOSChangesCopyDescription(changes, true); - pass("Pushing: %@", changesString); - CFReleaseNull(changesString); - - SOSCloudKeychainPutObjectsInCloud(changes, global_queue, - ^ (CFDictionaryRef returnedValues, CFErrorRef error) - { - if (error) { - fail("testPutObjectInCloud returned: %@", error); - CFRelease(error); - } - }); - return true; - }; - - - our_account = SOSAccountCreate(kCFAllocatorDefault, our_gestalt, our_data_source_factory, updateKVSKeys, updateKVS); - - SOSFullPeerInfoRef our_full_peer_info = SOSAccountGetMyFullPeerInCircleNamed(our_account, circleKey, &error); - SOSPeerInfoRef our_peer_info = SOSFullPeerInfoGetPeerInfo(our_full_peer_info); - CFRetain(our_peer_info); - - SOSAccountAddChangeBlock(our_account, ^(SOSCircleRef circle, - CFArrayRef peer_additions, CFArrayRef peer_removals, - CFArrayRef applicant_additions, CFArrayRef applicant_removals) { - // Should initiate syncing here! - bool joined = CFArrayContainsValue(peer_additions, CFRangeMake(0, CFArrayGetCount(peer_additions)), our_peer_info); - - pass("Peers Changed [%s] (Add: %@, Remove: %@)", joined ? "*** I'm in ***" : "Not including me.", peer_additions, peer_removals); - - if (joined) { - SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer_info) - { - CFErrorRef error = NULL; - - if (!CFEqual(peer_info, our_peer_info)) { - ok(SOSAccountSyncWithPeer(our_account, circle, peer_info, NULL, &error), - "Initiated sync with %@: [Error %@]", peer_info, error); - } - }); - } - }); - - ok(our_peer_info, "Peer Info: %@ [error: %@]", our_peer_info, error); - - //__block SOSEngineRef ourEngine; - - SOSObjectRef firstObject = SOSDataSourceCreateGenericItem(our_data_source, CFSTR("1234"), CFSTR("service")); - - //------------------------------------------------------------------------ - // ALICE - //------------------------------------------------------------------------ - CFArrayRef aliceWorkToDo = - CFArrayCreateForCFTypes(kCFAllocatorDefault, - ^ CFIndex (SOSAccountRef account, CFErrorRef error) - { - /* - When we get here, it should only be because Bob has retrieved - our circle and requested admission to our circle. - If we don't find a circleKey entry, our test setup is wrong. - */ - CFErrorRef modifyError = NULL; - SOSAccountModifyCircle(account, circleKey, &modifyError, ^(SOSCircleRef circle) { - CFErrorRef localError = NULL; - - ok(SOSCircleHasPeer(circle, our_peer_info, &localError), "We're a peer [Error: %@]", localError); - is(SOSCircleCountPeers(circle), 1, "One peer, woot"); - is(SOSCircleCountApplicants(circle), 1, "One applicant, hope it's BOB"); - - ok(SOSCircleAcceptRequests(circle, user_privkey, our_full_peer_info, &localError), "Accepted peers (%@) [Error: %@]", circle, localError); - - CFReleaseSafe(localError); - }); - CFReleaseSafe(modifyError); - - return +1; - }, - ^ CFIndex (SOSAccountRef account, CFErrorRef error) - { - // He should be telling us about him and we should be responding. - - CFMutableDictionaryRef ourDatabase = SOSTestDataSourceGetDatabase(our_data_source); - - is(CFDictionaryGetCount(ourDatabase), 0, "Database empty, we're synced"); - - pass("1"); - return +1; - }, - ^ CFIndex (SOSAccountRef account, CFErrorRef error) - { - CFMutableDictionaryRef ourDatabase = SOSTestDataSourceGetDatabase(our_data_source); - - is(CFDictionaryGetCount(ourDatabase), 1, "One element!"); - - return +1; - }, - NULL); - - //------------------------------------------------------------------------ - // BOB - //------------------------------------------------------------------------ - - CFArrayRef bobWorkToDo = - CFArrayCreateForCFTypes(kCFAllocatorDefault, - ^ CFIndex (SOSAccountRef account, CFErrorRef error) - { - __block CFIndex increment = 0; - CFErrorRef modifyError = NULL; - SOSAccountModifyCircle(account, circleKey, &modifyError, ^(SOSCircleRef circle) { - CFErrorRef localError = NULL; - - if (SOSCircleCountPeers(circle) == 1) { - is(SOSCircleCountApplicants(circle), 0, "No applicants"); - ok(SOSCircleRequestAdmission(circle, user_privkey, our_full_peer_info, &localError), "Requested admission (%@) [Error: %@]", circle, localError); - increment = +1; - } - - CFReleaseSafe(localError); - }); - CFReleaseSafe(modifyError); - return increment; - }, - ^ CFIndex (SOSAccountRef account, CFErrorRef error) - { - CFErrorRef modifyError = NULL; - SOSAccountModifyCircle(account, circleKey, &modifyError, ^(SOSCircleRef circle) { - CFErrorRef localError = NULL; - - ok(SOSCircleHasPeer(circle, our_peer_info, &localError), "We're a peer (%@) [Error: %@]", circle, localError); - is(SOSCircleCountPeers(circle), 2, "One peer, hope it's Alice"); - is(SOSCircleCountApplicants(circle), 0, "No applicants"); - - CFReleaseSafe(localError); - }); - CFReleaseSafe(modifyError); - - return +1; - }, - ^ CFIndex (SOSAccountRef account, CFErrorRef error) - { - CFErrorRef localError = NULL; - CFMutableDictionaryRef ourDatabase = SOSTestDataSourceGetDatabase(our_data_source); - is(CFDictionaryGetCount(ourDatabase), 0, "Database empty, we're synced"); - - SOSTestDataSourceAddObject(our_data_source, firstObject, &localError); - CFReleaseNull(localError); - - SOSAccountSyncWithAllPeers(account, &localError); - CFReleaseNull(localError); - - pass("1"); - return +1; - }, - ^ CFIndex (SOSAccountRef account, CFErrorRef error) - { - pass("2"); - - CFMutableDictionaryRef ourDatabase = SOSTestDataSourceGetDatabase(our_data_source); - is(CFDictionaryGetCount(ourDatabase), 1, "Still one element!"); - - return +1; - }, - NULL); - - //------------------------------------------------------------------------ - // START - //------------------------------------------------------------------------ - - ourWork = Alice ? aliceWorkToDo : bobWorkToDo; - - if (Alice) { - /* - Here we create a fresh circle, add and accept ourselves - Then we post to the cloud and wait for a Circle changed notification - */ - - CFErrorRef modifyError = NULL; - SOSAccountModifyCircle(our_account, circleKey, &modifyError, ^(SOSCircleRef circle) { - CFErrorRef localError = NULL; - - ok(SOSCircleRequestAdmission(circle, user_privkey, our_full_peer_info, &localError), "Requested admission (%@) [error: %@]", our_peer_info, localError); - ok(SOSCircleAcceptRequests(circle, user_privkey, our_full_peer_info, &localError), "Accepted self [Error: %@]", localError); - - CFReleaseSafe(localError); - }); - CFReleaseSafe(modifyError); - - } else { - // Tell alice we're set to go: - if (foundNonce) { - CFDictionaryRef changes = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, sBobReady, foundNonce, NULL); - SOSCloudKeychainPutObjectsInCloud(changes, global_queue, NULL); - CFReleaseSafe(changes); - } else { - fail("No none found to start the handshake"); - } - } - dispatch_group_wait(work_group, DISPATCH_TIME_FOREVER); - - // We probably never get here since the program exits.. - - CFReleaseNull(aliceWorkToDo); - CFReleaseNull(bobWorkToDo); - CFReleaseNull(our_peer_info); - CFReleaseNull(foundNonce); - -} - -// MARK: ----- start of all tests ----- -static void tests(bool Alice) -{ - dispatch_queue_t work_queue = dispatch_queue_create("NotificationQueue", DISPATCH_QUEUE_SERIAL); //; - dispatch_group_t work_group = dispatch_group_create(); - - // Prep the group for exitting the whole shebang. - runTests(Alice, work_queue, work_group); -} - -// define the options table for the command line -static const struct option options[] = -{ - { "verbose", optional_argument, NULL, 'v' }, - { "identity", optional_argument, NULL, 'i' }, - { "clear", optional_argument, NULL, 'C' }, - { } -}; - -static int kAliceTestCount = 32; -static int kBobTestCount = 30; - -int sc_101_accountsync(int argc, char *const *argv) -{ - char *identity = NULL; - extern char *optarg; - int arg, argSlot; - bool Alice = false; - - while (argSlot = -1, (arg = getopt_long(argc, (char * const *)argv, "i:vC", options, &argSlot)) != -1) - switch (arg) - { - case 'i': - identity = (char *)(optarg); - break; - case 'C': // should set up to call testClearAll - break; - default: - secerror("arg: %s", optarg); - break; - } - - if (identity) - { - secerror("We are %s",identity); - if (!strcmp(identity, "alice")) - Alice = true; - } - - plan_tests(Alice?kAliceTestCount:kBobTestCount); - tests(Alice); - - return 0; -} diff --git a/sec/SOSCircle/Regressions/sc-102-cfusernotification.c b/sec/SOSCircle/Regressions/sc-102-cfusernotification.c deleted file mode 100644 index 85ae8c91..00000000 --- a/sec/SOSCircle/Regressions/sc-102-cfusernotification.c +++ /dev/null @@ -1,100 +0,0 @@ -// -// sc-102-xx -// sec -// -// Created by John Hurley 10/16/12. -// Copyright 2012 Apple Inc. All rights reserved. -// - -/* - This test is a simple test of SOSCloudKeychainUserNotification to show - an OK/Cancel dialog to the user and get the response. Run with: - - /AppleInternal/Applications/SecurityTests.app/SecurityTests sc_102_cfusernotification -v - -*/ - -#include -#include -#include - -#include -#include - -#include "SOSCircle_regressions.h" -#include "SOSCloudKeychainClient.h" -#include "SOSCloudKeychainConstants.h" - -#if TARGET_OS_EMBEDDED && !TARGET_IPHONE_SIMULATOR -#include -#endif - -static void tests(void) -{ -// CFStringRef messageToUser = CFSTR("OK to sync with world?"); -// CFStringRef messageToUser = CFSTR("Allow “Emily‘s iPad to use your iCloud Keychain?"); -#if !TARGET_IPHONE_SIMULATOR -#if TARGET_OS_EMBEDDED - CFStringRef our_peer_id = (CFStringRef)MGCopyAnswer(kMGQUserAssignedDeviceName, NULL); -#else - CFStringRef our_peer_id = CFSTR("🔥💩"); -#endif -#else - CFStringRef our_peer_id = CFSTR("Emily‘s iPad"); -#endif - - CFStringRef messageToUser = CFStringCreateWithFormat(kCFAllocatorDefault, 0, CFSTR("Allow “%@” to use your iCloud Keychain?"), our_peer_id); - dispatch_queue_t processQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - dispatch_group_t work_group = dispatch_group_create(); - - // Prep the group for exitting the whole shebang. - dispatch_group_enter(work_group); - dispatch_group_notify(work_group, processQueue, ^ - { - printf("Exiting via dispatch_group_notify; all work done\n"); - CFRunLoopStop(CFRunLoopGetMain()); - // exit(0); - }); - - SOSCloudKeychainUserNotification(messageToUser, processQueue, ^ (CFDictionaryRef returnedValues, CFErrorRef error) - { - uint64_t flags = 0; - pass("Reply from SOSCloudKeychainUserNotification: %@", returnedValues); - CFStringRef nfkey = CFStringCreateWithCString(kCFAllocatorDefault, kMessageKeyNotificationFlags, kCFStringEncodingUTF8); - CFTypeRef cfflags = returnedValues ? CFDictionaryGetValue(returnedValues, nfkey) : NULL; - if (cfflags && (CFGetTypeID(cfflags) == CFNumberGetTypeID())) - CFNumberGetValue(cfflags, kCFNumberSInt64Type, &flags); - CFReleaseSafe(nfkey); - - // flags is not actually a mask - if (flags == kCFUserNotificationDefaultResponse) - pass("OK button pressed"); - else - if (flags == kCFUserNotificationCancelResponse) - pass("Cancel button pressed"); - else - if (flags == kCFUserNotificationAlternateResponse) - pass("Alternate button pressed"); - else - pass("Flags: %#llx", flags); - - ok(error == NULL, "SOSCloudKeychainPutObjectsInCloud [error: %@:]", error); - dispatch_group_leave(work_group); - }); - - pass("Dialog is up for device \"%@\"", our_peer_id); - printf("Dialog is up\n"); - dispatch_group_wait(work_group, DISPATCH_TIME_FOREVER); - CFRunLoopRun(); // Wait for it... - pass("Exit from run loop"); -} - -static int kUNTestCount = 5; - -int sc_102_cfusernotification(int argc, char *const *argv) -{ - plan_tests(kUNTestCount); - tests(); - - return 0; -} diff --git a/sec/SOSCircle/Regressions/sc-120-cloudcircle.c b/sec/SOSCircle/Regressions/sc-120-cloudcircle.c deleted file mode 100644 index 30d2c841..00000000 --- a/sec/SOSCircle/Regressions/sc-120-cloudcircle.c +++ /dev/null @@ -1,391 +0,0 @@ -/* - * sc-01-create.c - * - * Created by Mitch Adler on 1/25/121. - * Copyright 2012 Apple Inc. All rights reserved. - * - */ - -// /AppleInternal/Applications/SecurityTests.app/SecurityTests sc_120_cloudcircle -v -- -i alice -// /AppleInternal/Applications/SecurityTests.app/SecurityTests sc_120_cloudcircle -v -- -i bob - -#include -#include -#include -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) -#include -#endif - -#include -#include -#include -#include -#include -#include "SOSTestDataSource.h" -#include - -#include - -#include -#include - -#include - -#include -#include -#include - -#include - -#include "SOSRegressionUtilities.h" - -#include "SOSCircle_regressions.h" -#include "SecureObjectSync/Imported/SOSCloudCircleServer.h" - -#ifdef NO_SERVER -#if TARGET_OS_EMBEDDED || TARGET_IPHONE_SIMULATOR -#include -#else -#warning "NO_SERVER doesn't really work on OSX" -#endif -#endif - -static CFStringRef kCircleName = CFSTR("Global Circle"); - -static CFStringRef sAliceReady = CFSTR("Alice-Ready"); -static CFStringRef sBobReady = CFSTR("Bob-Ready"); - -static void SOSCloudKeychainClearAllSync() -{ - dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0); - SOSCloudKeychainClearAll(dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), - ^(CFDictionaryRef returnedValues __unused, CFErrorRef error) - { - CFReleaseSafe(error); - dispatch_semaphore_signal(waitSemaphore); - }); - dispatch_semaphore_wait(waitSemaphore, DISPATCH_TIME_FOREVER); - dispatch_release(waitSemaphore); -} - -static void ClearAndSynchronize() -{ - dispatch_queue_t global_queue = dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - dispatch_semaphore_t bob_ready_semaphore = dispatch_semaphore_create(0); - - const CFIndex nonceByteCount = 10; - CFMutableDataRef nonce = CFDataCreateMutable(kCFAllocatorDefault, nonceByteCount); - CFDataSetLength(nonce, nonceByteCount); - SecRandomCopyBytes(kSecRandomDefault, CFDataGetLength(nonce), CFDataGetMutableBytePtr(nonce)); - - dispatch_queue_t notification_queue = dispatch_queue_create("sync notification queue", DISPATCH_QUEUE_SERIAL); - - CloudItemsChangedBlock notification_block = ^ (CFDictionaryRef returnedValues) - { - CFRetain(returnedValues); - dispatch_async(notification_queue, ^{ - CFTypeRef bobReadyValue = CFDictionaryGetValue(returnedValues, sBobReady); - if (isData(bobReadyValue) && CFEqual(bobReadyValue, nonce)) { - SOSCloudKeychainClearAllSync(); - - pass("signalling"); - dispatch_semaphore_signal(bob_ready_semaphore); - } else { - pass("Ignoring change: %@", returnedValues); - } - CFReleaseSafe(returnedValues); - }); - }; - - CloudKeychainReplyBlock reply_block = ^ (CFDictionaryRef returnedValues, CFErrorRef error) - { - if (CFDictionaryGetCount(returnedValues) != 0) - notification_block(returnedValues); - }; - - pass("Clearing"); - SOSCloudKeychainClearAllSync(); - - CFArrayRef bobKey = CFArrayCreateForCFTypes(kCFAllocatorDefault, sBobReady, NULL); - SOSCloudKeychainRegisterKeysAndGet(bobKey, global_queue, reply_block, notification_block); - - CFStringRef description = SOSInterestListCopyDescription(bobKey); - pass("%@", description); - - CFReleaseNull(description); - CFReleaseNull(bobKey); - - CFDictionaryRef changes = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, sAliceReady, nonce, NULL); - SOSCloudKeychainPutObjectsInCloud(changes, global_queue, NULL); - - description = SOSChangesCopyDescription(changes, true); - pass("%@", description); - CFReleaseNull(description); - - pass("Waiting"); - dispatch_semaphore_wait(bob_ready_semaphore, DISPATCH_TIME_FOREVER); - dispatch_release(bob_ready_semaphore); - - pass("Continuing"); - - CFErrorRef error = NULL; - CFArrayRef no_keys = CFArrayCreateForCFTypes(kCFAllocatorDefault, NULL); - SOSCloudKeychainUpdateKeys(false, no_keys, no_keys, no_keys, &error); - - SOSCloudKeychainSetItemsChangedBlock(NULL); - CFReleaseSafe(no_keys); - CFReleaseSafe(error); - - - CFReleaseNull(changes); -} - -static void WaitForSynchronization() -{ - dispatch_queue_t global_queue = dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - dispatch_semaphore_t alice_ready_semaphore = dispatch_semaphore_create(0); - dispatch_queue_t notification_queue = dispatch_queue_create("sync notification queue", DISPATCH_QUEUE_SERIAL); - - __block CFDataRef foundNonce = NULL; - CloudItemsChangedBlock notification_block = ^ (CFDictionaryRef returnedValues) - { - CFRetain(returnedValues); - dispatch_async(notification_queue, ^{ - CFTypeRef aliceReadyValue = CFDictionaryGetValue(returnedValues, sAliceReady); - if (isData(aliceReadyValue)) { - foundNonce = (CFDataRef) aliceReadyValue; - CFRetain(foundNonce); - pass("signalling for: %@", foundNonce); - - dispatch_semaphore_signal(alice_ready_semaphore); - } - CFReleaseSafe(returnedValues); - }); - }; - - CloudKeychainReplyBlock reply_block = ^ (CFDictionaryRef returnedValues, CFErrorRef error) - { - if (CFDictionaryGetCount(returnedValues) != 0) - notification_block(returnedValues); - }; - - CFArrayRef aliceKey = CFArrayCreateForCFTypes(kCFAllocatorDefault, sAliceReady, NULL); - SOSCloudKeychainRegisterKeysAndGet(aliceKey, global_queue, reply_block, notification_block); - - CFStringRef description = SOSInterestListCopyDescription(aliceKey); - pass("%@", description); - CFReleaseNull(description); - - pass("Waiting"); - dispatch_semaphore_wait(alice_ready_semaphore, DISPATCH_TIME_FOREVER); - dispatch_release(alice_ready_semaphore); - pass("Continuing"); - - CFDictionaryRef changes = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, sBobReady, foundNonce, NULL); - SOSCloudKeychainPutObjectsInCloud(changes, global_queue, NULL); - CFReleaseSafe(changes); - - CFReleaseSafe(foundNonce); - CFReleaseSafe(aliceKey); -} - -static CFStringRef circleKey = CFSTR("Circle"); - -#ifdef NO_SERVER -static SOSDataSourceRef SetupTestFactory() -{ - static SOSDataSourceRef our_data_source; - - our_data_source = SOSTestDataSourceCreate(); - - SOSKeychainAccountSetFactoryForAccount(^ { - SOSDataSourceFactoryRef our_data_source_factory = SOSTestDataSourceFactoryCreate(); - SOSTestDataSourceFactoryAddDataSource(our_data_source_factory, circleKey, our_data_source); - return our_data_source_factory; - }); - - return our_data_source; -} -#endif - -static void PurgeAndReload() -{ -#if 0 - CFErrorRef error = NULL; - ok(SOSKeychainSaveAccountDataAndPurge(&error), "Purged"); - CFReleaseNull(error); - - ok(SOSKeychainAccountGetSharedAccount(), "Got Shared: %@", SOSKeychainAccountGetSharedAccount()); -#endif -} - -#ifndef NO_SERVER -#define SOSKeychainAccountGetSharedAccount() NULL -#endif - -#define kAliceTestCount 100 -static void AliceTests() -{ - plan_tests(kAliceTestCount); - - dispatch_semaphore_t notification_signal = dispatch_semaphore_create(0); - int token; - notify_register_dispatch(kSOSCCCircleChangedNotification, &token, - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), - ^(int token) { - dispatch_semaphore_signal(notification_signal); - }); - - SOSCloudKeychainSetCallbackMethodXPC(); // call this first - ClearAndSynchronize(); - -#ifdef NO_SERVER - SOSDataSourceRef our_test_data_source = SetupTestFactory(); -#endif - CFErrorRef error = NULL; - - ok(SOSCCResetToOffering(&error), "Reset: %@ [%@]", SOSKeychainAccountGetSharedAccount(), error); - CFReleaseNull(error); - - PurgeAndReload(); - - CFArrayRef applicants = NULL; - do { - dispatch_semaphore_wait(notification_signal, DISPATCH_TIME_FOREVER); - applicants = SOSCCCopyApplicantPeerInfo(&error); - CFReleaseNull(error); - } while (CFArrayGetCount(applicants) == 0); - pass("Waited long enough"); - - is(CFArrayGetCount(applicants), 1, "Bob should be applying"); - CFReleaseNull(error); - - ok(SOSCCAcceptApplicants(applicants, &error), "Accepted all applicants: %@", error); - CFReleaseNull(error); - CFReleaseSafe(applicants); - - PurgeAndReload(); - - sleep(180); - pass("Waited long enough again"); - -#ifdef NO_SERVER - CFDictionaryRef data = SOSTestDataSourceGetDatabase(our_test_data_source); - is(CFDictionaryGetCount(data), 1, "Should have gotten bob's one"); -#endif -} - -#define kBobTestCount 100 -static void BobTests() -{ - plan_tests(kBobTestCount); - - dispatch_semaphore_t notification_signal = dispatch_semaphore_create(0); - int token; - notify_register_dispatch(kSOSCCCircleChangedNotification, &token, - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), - ^(int token) { - dispatch_semaphore_signal(notification_signal); - }); - - SOSCloudKeychainSetCallbackMethodXPC(); // call this first - WaitForSynchronization(); - -#ifdef NO_SERVER - SOSDataSourceRef our_test_data_source = SetupTestFactory(); -#endif - - CFErrorRef error = NULL; - -#ifdef NO_SERVER - SOSObjectRef firstObject = SOSDataSourceCreateGenericItem(our_test_data_source, CFSTR("1234"), CFSTR("service")); - SOSTestDataSourceAddObject(our_test_data_source, firstObject, &error); -#endif - - CFReleaseNull(error); - - is(SOSCCThisDeviceIsInCircle(&error), kSOSCCCircleAbsent, "Shouldn't be a circle: %@", error); - CFReleaseNull(error); - - PurgeAndReload(); - - CFArrayRef peers = NULL; - do { - dispatch_semaphore_wait(notification_signal, DISPATCH_TIME_FOREVER); - peers = SOSCCCopyPeerPeerInfo(&error); - CFReleaseNull(error); - } while (CFArrayGetCount(peers) == 0); - - pass("Peer arrived: %@", SOSKeychainAccountGetSharedAccount()); - - is(CFArrayGetCount(peers), 1, "Only Alice should be there"); - CFReleaseSafe(peers); - - ok(SOSCCRequestToJoinCircle(&error), "Join circles: %@ [%@]", SOSKeychainAccountGetSharedAccount(), error); - CFReleaseNull(error); - - PurgeAndReload(); - - do { - dispatch_semaphore_wait(notification_signal, DISPATCH_TIME_FOREVER); - - } while (SOSCCThisDeviceIsInCircle(&error) != kSOSCCInCircle); - pass("Was admitted: %@ [%@]", SOSKeychainAccountGetSharedAccount(), error); - CFReleaseNull(error); - - is(SOSCCThisDeviceIsInCircle(&error), kSOSCCInCircle, "Should be in circle: %@", error); - CFReleaseNull(error); - - PurgeAndReload(); - - // Sync - sleep(120); - pass("Waited long enough again: %@", SOSKeychainAccountGetSharedAccount()); - -#ifdef NO_SERVER - CFDictionaryRef data = SOSTestDataSourceGetDatabase(our_test_data_source); - is(CFDictionaryGetCount(data), 1, "Only have one"); -#endif -} - - -static const struct option options[] = -{ - { "identity", optional_argument, NULL, 'i' }, - { } -}; - - -int sc_120_cloudcircle(int argc, char *const *argv) -{ - char *identity = NULL; - extern char *optarg; - int arg, argSlot; - - bool isAlice = false; - - while (argSlot = -1, (arg = getopt_long(argc, (char * const *)argv, "i:vC", options, &argSlot)) != -1) - switch (arg) - { - case 'i': - identity = (char *)(optarg); - break; - default: - fail("arg: %s", optarg); - break; - } - - if (identity) - { - if (!strcmp(identity, "alice")) - isAlice = true; - } - - if (isAlice) - AliceTests(); - else - BobTests(); - - return 0; - -} diff --git a/sec/SOSCircle/Regressions/sc-30-peerinfo.c b/sec/SOSCircle/Regressions/sc-30-peerinfo.c deleted file mode 100644 index 380d62c3..00000000 --- a/sec/SOSCircle/Regressions/sc-30-peerinfo.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * sc-30-peerinfo.c - * - * Created by Mitch Adler on 1/25/121. - * Copyright 2012 Apple Inc. All rights reserved. - * - */ - - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include - -#include -#include - -#include "SOSCircle_regressions.h" - -#include "SOSRegressionUtilities.h" - -#if TARGET_OS_IPHONE -#include -#endif - -static int kTestTestCount = 11; -static void tests(void) -{ - SecKeyRef signingKey = NULL; - SOSFullPeerInfoRef fpi = SOSCreateFullPeerInfoFromName(CFSTR("Test Peer"), &signingKey, NULL); - SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(fpi); - CFRetainSafe(pi); - - ok(NULL != pi, "info creation"); - - uint8_t buffer[4096]; - - const uint8_t *buffer_p = SOSPeerInfoEncodeToDER(pi, NULL, buffer, buffer + sizeof(buffer)); - - ok(buffer_p != NULL, "encode"); - - SOSPeerInfoRef pi2 = SOSPeerInfoCreateFromDER(NULL, NULL, &buffer_p, buffer + sizeof(buffer)); - - SKIP: - { - skip("Decode failed", 1, ok(NULL != pi2, "Decode")); - ok(CFEqual(pi, pi2), "Decode matches"); - } - - buffer_p = SOSFullPeerInfoEncodeToDER(fpi, NULL, buffer, buffer + sizeof(buffer)); - - ok(buffer_p != NULL, "Full peer encode"); - - SOSFullPeerInfoRef fpi2 = SOSFullPeerInfoCreateFromDER(kCFAllocatorDefault, NULL, &buffer_p, buffer + sizeof(buffer)); - - SKIP: - { - skip("Full Peer Decode failed", 1, ok(fpi2, "Full peer inflated")); - - ok(CFEqual(fpi, fpi2), "Full peer inflate matches"); - } - - -// Application ticket time. - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - CFErrorRef error = NULL; - - CFDataRef parameters = SOSUserKeyCreateGenerateParameters(&error); - ok(parameters, "No parameters!"); - ok(error == NULL, "Error: (%@)", error); - CFReleaseNull(error); - - SecKeyRef user_privkey = SOSUserKeygen(cfpassword, parameters, &error); - CFReleaseSafe(cfpassword); - CFReleaseNull(parameters); - SecKeyRef user_pubkey = SecKeyCreatePublicFromPrivate(user_privkey); - - ok(SOSFullPeerInfoPromoteToApplication(fpi, user_privkey, &error), "Promote to Application"); - ok(SOSPeerInfoApplicationVerify(SOSFullPeerInfoGetPeerInfo(fpi), user_pubkey, &error), "Promote to Application"); - - - CFReleaseNull(user_privkey); - CFReleaseNull(user_pubkey); - - CFReleaseNull(signingKey); - CFReleaseNull(pi); - CFReleaseNull(pi2); - CFReleaseNull(fpi); - CFReleaseNull(fpi2); -} - -int sc_30_peerinfo(int argc, char *const *argv) -{ - plan_tests(kTestTestCount); - - tests(); - - return 0; -} diff --git a/sec/SOSCircle/Regressions/sc-40-circle.c b/sec/SOSCircle/Regressions/sc-40-circle.c deleted file mode 100644 index 6a33b230..00000000 --- a/sec/SOSCircle/Regressions/sc-40-circle.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * sc-01-create.c - * - * Created by Mitch Adler on 1/25/121. - * Copyright 2012 Apple Inc. All rights reserved. - * - */ - - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include - -#include - -#include "SOSCircle_regressions.h" - -#include "SOSRegressionUtilities.h" - -static int kTestTestCount = 17; -static void tests(void) -{ - SOSCircleRef circle = SOSCircleCreate(NULL, CFSTR("TEST DOMAIN"), NULL); - - ok(NULL != circle, "Circle creation"); - - ok(0 == SOSCircleCountPeers(circle), "Zero peers"); - - //SecKeyRef publicKey = NULL; - SecKeyRef dev_a_key = NULL; - SecKeyRef dev_b_key = NULL; - CFErrorRef error = NULL; - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - - if(cfpassword == NULL) printf("WTF\n"); - - CFDataRef parameters = SOSUserKeyCreateGenerateParameters(&error); - ok(parameters, "No parameters!"); - ok(error == NULL, "Error: (%@)", error); - CFReleaseNull(error); - - SecKeyRef user_privkey = SOSUserKeygen(cfpassword, parameters, &error); - CFReleaseNull(parameters); - - SOSFullPeerInfoRef peer_a_full_info = SOSCreateFullPeerInfoFromName(CFSTR("Peer A"), &dev_a_key, NULL); - - SOSFullPeerInfoRef peer_b_full_info = SOSCreateFullPeerInfoFromName(CFSTR("Peer B"), &dev_b_key, NULL); - - ok(SOSCircleRequestAdmission(circle, user_privkey, peer_a_full_info, NULL)); - ok(SOSCircleRequestAdmission(circle, user_privkey, peer_a_full_info, NULL)); - ok(SOSCircleRequestAdmission(circle, user_privkey, peer_a_full_info, NULL)); - - ok(SOSCircleAcceptRequest(circle, user_privkey, peer_a_full_info, SOSFullPeerInfoGetPeerInfo(peer_a_full_info), NULL)); - - ok(!SOSCircleRequestAdmission(circle, user_privkey, peer_a_full_info, NULL)); - ok(SOSCircleRequestAdmission(circle, user_privkey, peer_b_full_info, NULL)); - - ok(SOSCircleCountPeers(circle) == 1, "Peer count"); - - size_t size = SOSCircleGetDEREncodedSize(circle, &error); - uint8_t buffer[size]; - uint8_t* start = SOSCircleEncodeToDER(circle, &error, buffer, buffer + sizeof(buffer)); - - ok(start, "successful encoding"); - ok(start == buffer, "Used whole buffer"); - - const uint8_t *der = buffer; - SOSCircleRef inflated = SOSCircleCreateFromDER(NULL, &error, &der, buffer + sizeof(buffer)); - - ok(inflated, "inflated"); - ok(CFEqualSafe(inflated, circle), "Compares"); - - - ok(SOSCircleRemovePeer(circle, user_privkey, peer_a_full_info, SOSFullPeerInfoGetPeerInfo(peer_a_full_info), NULL)); - ok(SOSCircleCountPeers(circle) == 0, "Peer count"); - - CFReleaseNull(dev_a_key); - CFReleaseNull(cfpassword); -} - -int sc_40_circle(int argc, char *const *argv) -{ - plan_tests(kTestTestCount); - - tests(); - - return 0; -} diff --git a/sec/SOSCircle/Regressions/sc-41-cloudcircle.c b/sec/SOSCircle/Regressions/sc-41-cloudcircle.c deleted file mode 100644 index 1a5d5df8..00000000 --- a/sec/SOSCircle/Regressions/sc-41-cloudcircle.c +++ /dev/null @@ -1,48 +0,0 @@ -// -// sc-41-cloudcircle.c -// sec -// -// Created by Mitch Adler on 12/13/12. -// -// - -#include "SOSCircle_regressions.h" - -#include "SOSRegressionUtilities.h" - -#include -#include - -static const int kSOSCCTestCount = 6; // # of "ok"s in "tests" below -static int kTestTestCount = kSOSCCTestCount; -static void tests(void) -{ - CFErrorRef error = NULL; - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - - ok(SOSCCSetUserCredentials(CFSTR("foo1"), cfpassword, &error), "Added Creds (%@)", error); - CFReleaseNull(error); - CFReleaseNull(cfpassword); - - ok(SOSCCThisDeviceIsInCircle(&error) == kSOSCCCircleAbsent, "Circle Absent (%@)", error); - CFReleaseNull(error); - ok(SOSCCResetToOffering(&error), "SOSCCOfferPotentialCircle (%@)", error); - CFReleaseNull(error); - - ok(SOSCCThisDeviceIsInCircle(&error) == kSOSCCInCircle, "Circle Absent (%@)", error); - CFReleaseNull(error); - ok(SOSCCRemoveThisDeviceFromCircle(&error), "Leaving (%@)", error); - CFReleaseNull(error); - - ok(SOSCCThisDeviceIsInCircle(&error) == kSOSCCCircleAbsent, "Circle Absent (%@)", error); - CFReleaseNull(error); -} - -int sc_41_cloudcircle(int argc, char *const *argv) -{ - plan_tests(kTestTestCount); - - tests(); - - return 0; -} diff --git a/sec/SOSCircle/Regressions/sc-60-peer.c b/sec/SOSCircle/Regressions/sc-60-peer.c deleted file mode 100644 index 5adcb78c..00000000 --- a/sec/SOSCircle/Regressions/sc-60-peer.c +++ /dev/null @@ -1,147 +0,0 @@ -// -// sc-60-peer.c -// sec -// -// Created by Michael Brouwer on 8/2/12. -// Copyright 2012 Apple Inc. All rights reserved. -// - -#include - -#include "SOSCircle_regressions.h" - -#include - -#include - -#include - -#include - -static int kTestTestCount = 13; - -struct SOSTestTransport { - struct SOSTransport t; - unsigned t_msg_count; - uint8_t digest[CCSHA256_OUTPUT_SIZE]; -}; - - -static void tests(void) -{ - const unsigned kSOSPeerVersion = 0; - - CFErrorRef error = NULL; - SOSPeerRef peer; - - /* Create peer test. */ - CFStringRef peer_id = CFSTR("peer 60"); - - __block unsigned msg_count = 0; - uint8_t msg_digest_buffer[CCSHA256_OUTPUT_SIZE]; - uint8_t *msg_digest = msg_digest_buffer; - - SOSPeerSendBlock sendBlock = ^bool (CFDataRef message, CFErrorRef *error) { - size_t msglen = CFDataGetLength(message); - const uint8_t *msg = CFDataGetBytePtr(message); - const struct ccdigest_info *sha256 = ccsha256_di(); - if (msg_count++ == 0) { - /* message n=0 */ - ccdigest(sha256, msglen, msg, msg_digest); - } else { - /* message n=n+1 */ - ccdigest_di_decl(sha256, sha256_ctx); - ccdigest_init(sha256, sha256_ctx); - ccdigest_update(sha256, sha256_ctx, sizeof(msg_digest_buffer), msg_digest); - ccdigest_update(sha256, sha256_ctx, msglen, msg); - ccdigest_final(sha256, sha256_ctx, msg_digest); - } - size_t encmaxlen = SecBase64Encode(msg, msglen, NULL, 0); - CFMutableDataRef encoded = CFDataCreateMutable(NULL, encmaxlen); - CFDataSetLength(encoded, encmaxlen); - SecBase64Result rc; - char *enc = (char *)CFDataGetMutableBytePtr(encoded); -#ifndef NDEBUG - size_t enclen = -#endif - SecBase64Encode2(msg, msglen, - enc, - encmaxlen, kSecB64_F_LINE_LEN_USE_PARAM, - 64, &rc); - assert(enclen < INT32_MAX); - -// printf("=== BEGIN SOSMESSAGE ===\n%.*s\n=== END SOSMESSAGE ===\n", (int)enclen, enc); - - CFRelease(encoded); - return true; - }; - - - ok(peer = SOSPeerCreateSimple(peer_id, kSOSPeerVersion, &error, sendBlock), - "create peer: %@", error); - CFReleaseNull(error); - - /* Send a test message. */ - is((int)msg_count, 0, "no message sent yet"); - size_t msglen = 10; - uint8_t msg[msglen]; - memcpy(msg, "0123456789", msglen); - CFDataRef message = CFDataCreate(NULL, msg, msglen); - ok(SOSPeerSendMessage(peer, message, &error), - "send message to peer: %@", error); - CFReleaseNull(error); - is((int)msg_count, 1, "We sent %d/1 messages", msg_count); - CFRelease(message); - - /* Check the peer's version. */ - is(SOSPeerGetVersion(peer), kSOSPeerVersion, "version is correct"); - - /* Get the peer's manifest. */ - SOSManifestRef manifest = SOSPeerCopyManifest(peer, &error); - ok(manifest == NULL, "No manifest yet for this peer: %@", error); - CFReleaseNull(error); - CFReleaseNull(manifest); - - /* Get the peer's manifest digest. */ - CFDataRef digest = SOSPeerCopyManifestDigest(peer, &error); - ok(digest == NULL, "No digest yet for this peer's manifest: %@", error); - CFReleaseNull(error); - CFReleaseNull(digest); - - ok(manifest = SOSManifestCreateWithBytes(NULL, 0, &error), "Create empty manifest: %@", error); - CFReleaseNull(error); - ok(SOSPeerSetManifest(peer, manifest, &error), "Set empty manifest on peer: %@", error); - CFReleaseNull(error); - - /* Get the peer's empty manifest digest. */ - digest = SOSPeerCopyManifestDigest(peer, &error); - ok(digest, "Got a digest: %@ this peer's manifest: %@", digest, error); - CFReleaseNull(error); - - /* Clean up. */ - SOSPeerDispose(peer); - - SOSPeerRef reinflated_peer = NULL; - ok(reinflated_peer = SOSPeerCreateSimple(peer_id, kSOSPeerVersion, &error, sendBlock), - "create peer: %@", error); - CFReleaseNull(error); - - CFDataRef digestAfterReinflate = SOSPeerCopyManifestDigest(reinflated_peer, &error); - ok(digest != NULL, "Got NULL after reinflate (%@)", error); - ok(CFEqual(digest, digestAfterReinflate), "Compare digest after reinflate, before: %@ after: %@", digest, digestAfterReinflate); - CFReleaseNull(error); - - SOSPeerDispose(reinflated_peer); - - CFReleaseNull(digestAfterReinflate); - CFReleaseNull(digest); -} - -int sc_60_peer(int argc, char *const *argv) -{ - plan_tests(kTestTestCount); - - tests(); - - return 0; -} diff --git a/sec/SOSCircle/Regressions/sc-75-circle-engine.c b/sec/SOSCircle/Regressions/sc-75-circle-engine.c deleted file mode 100644 index e0c3f5c0..00000000 --- a/sec/SOSCircle/Regressions/sc-75-circle-engine.c +++ /dev/null @@ -1,223 +0,0 @@ -// -// sc-75-circle-engine.c -// sec -// -// Created by Michael Brouwer on 9/24/12. -// Copyright 2012 Apple Inc. All rights reserved. -// - -#include -#include - -#include "SOSCircle_regressions.h" - -#include - -#include - -#include - -#include - -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include - -#include "SOSCircle_regressions.h" -#include "SOSRegressionUtilities.h" -#include "SOSTestDataSource.h" - -#ifndef SEC_CONST_DECL -#define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); -#endif - -#include - - -// MARK: ----- Constants ----- - -static CFStringRef circleKey = CFSTR("Circle"); - -static int kTestTestCount = 22; - -static void tests() -{ - CFErrorRef error = NULL; - - CFStringRef aliceID = CFSTR("Alice"); - CFStringRef bobID = CFSTR("Bob"); // not really remote, just another client on same machine - - SecKeyRef alice_key = NULL; - SecKeyRef bob_key = NULL; - - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - - CFDataRef parameters = SOSUserKeyCreateGenerateParameters(&error); - ok(parameters, "No parameters!"); - ok(error == NULL, "Error: (%@)", error); - CFReleaseNull(error); - - SecKeyRef user_privkey = SOSUserKeygen(cfpassword, parameters, &error); - CFReleaseNull(parameters); - CFReleaseSafe(cfpassword); - - CFStringRef circleName = CFSTR("Woot Circle"); - - SOSFullPeerInfoRef alice_full_peer_info = SOSCreateFullPeerInfoFromName(aliceID, &alice_key, &error); - SOSPeerInfoRef alice_peer_info = SOSFullPeerInfoGetPeerInfo(alice_full_peer_info); - - SOSFullPeerInfoRef bob_full_peer_info = SOSCreateFullPeerInfoFromName(bobID, &bob_key, &error); - SOSPeerInfoRef bob_peer_info = SOSFullPeerInfoGetPeerInfo(bob_full_peer_info); - - SOSCircleRef aliceCircle = SOSCircleCreate(kCFAllocatorDefault, circleName, &error); - - ok(SOSCircleRequestAdmission(aliceCircle, user_privkey, alice_full_peer_info, &error)); - ok(SOSCircleAcceptRequests(aliceCircle, user_privkey, alice_full_peer_info, NULL)); - ok(SOSCircleRequestAdmission(aliceCircle, user_privkey, bob_full_peer_info, &error), "requested admission"); - ok(SOSCircleAcceptRequests(aliceCircle, user_privkey, bob_full_peer_info, &error), "accepted them all!"); - - alice_peer_info = SOSFullPeerInfoGetPeerInfo(alice_full_peer_info); - bob_peer_info = SOSFullPeerInfoGetPeerInfo(bob_full_peer_info); - - CFDataRef aliceCircleEncoded; - ok(aliceCircleEncoded = SOSCircleCopyEncodedData(aliceCircle, kCFAllocatorDefault, &error), "encode alice circle: %@", error); - CFReleaseNull(error); - SOSCircleRef bobCircle; - ok(bobCircle = SOSCircleCreateFromData(0, aliceCircleEncoded, &error), "decode bobCircle: %@", error); - CFReleaseNull(aliceCircleEncoded); - CFReleaseNull(error); - - /* Transport. */ - __block CFDataRef queued_message = NULL; - - SOSPeerSendBlock enqueueMessage = ^bool (CFDataRef message, CFErrorRef *error) { - if (queued_message) - fail("We already had an unproccessed message"); - - queued_message = (CFDataRef) CFRetain(message); - return true; - }; - - CFDataRef (^dequeueMessage)() = ^CFDataRef () { - CFDataRef result = queued_message; - queued_message = NULL; - - return result; - }; - - /* DataSource */ - SOSDataSourceRef aliceDs = SOSTestDataSourceCreate(); - SOSDataSourceRef bobDs = SOSTestDataSourceCreate(); - - SOSDataSourceFactoryRef aliceDsf = SOSTestDataSourceFactoryCreate(); - SOSTestDataSourceFactoryAddDataSource(aliceDsf, circleName, aliceDs); - - SOSDataSourceFactoryRef bobDsf = SOSTestDataSourceFactoryCreate(); - SOSTestDataSourceFactoryAddDataSource(bobDsf, circleName, bobDs); - - /* Test passing peer messages to the engine. */ - CFDataRef message; - - CFStringRef bob_peer_id = SOSPeerInfoGetPeerID(bob_peer_info); - - /* Hand an empty message to the engine for handeling. */ - message = CFDataCreate(NULL, NULL, 0); - is(SOSCircleHandlePeerMessage(aliceCircle, alice_full_peer_info, aliceDsf, enqueueMessage, bob_peer_id, message, &error), false, - "empty message rejected, %@", error); - - CFReleaseNull(error); - CFReleaseNull(message); - - ok(SOSCircleSyncWithPeer(alice_full_peer_info, aliceCircle, aliceDsf, enqueueMessage, bob_peer_id, &error), "Start sync [error %@]", error); - CFReleaseNull(error); - - ok(message = dequeueMessage(), "Alice sent message"); - CFStringRef alice_peer_id = SOSPeerInfoGetPeerID(alice_peer_info); - is(SOSCircleHandlePeerMessage(bobCircle, bob_full_peer_info, bobDsf, enqueueMessage, alice_peer_id, message, &error), true, - "Bob accepted message: %@", error); - CFReleaseNull(message); - -#if 1 - CFStringRef desc = NULL; - ok(message = dequeueMessage(), "we got a message from Bob %@", desc = SOSMessageCopyDescription(message)); - ok(SOSCircleHandlePeerMessage(aliceCircle, alice_full_peer_info, aliceDsf, enqueueMessage, bob_peer_id, message, &error), - "Alice accepted message: %@", error); - CFReleaseNull(message); - CFReleaseNull(desc); - - ok(message = dequeueMessage(), "we got a reply from Alice %@", desc = SOSMessageCopyDescription(message)); - ok(SOSCircleHandlePeerMessage(bobCircle, bob_full_peer_info, bobDsf, enqueueMessage, alice_peer_id, message, &error), - "Bob accepted message: %@", error); - CFReleaseNull(message); - CFReleaseNull(desc); -#endif - -#if 0 - message = dequeueMessage(); - ok(NULL == message, "we got no message from Bob %@", desc = SOSMessageCopyDescription(message)); - - SOSObjectRef object = SOSDataSourceCreateGenericItem(aliceDs, CFSTR("75_circle_engine_account"), CFSTR("test service")); - ok(SOSTestDataSourceAddObject(aliceDs, object, &error), "add empty object to datasource: %@", error); - CFReleaseNull(error); - CFReleaseNull(object); - - ok(SOSCircleSyncWithPeer(alice_full_peer_info, aliceCircle, aliceDsf, enqueueMessage, bob_peer_id, &error), "Restart sync [error %@]", error); - CFReleaseNull(error); - - ok(message = dequeueMessage(), "Alice started again %@", desc = SOSMessageCopyDescription(message)); - is(SOSCircleHandlePeerMessage(bobCircle, bob_full_peer_info, bobDsf, enqueueMessage, alice_peer_id, message, &error), true, - "bob accepted %@: %@", SOSMessageCopyDescription(message), error); - CFReleaseNull(error); - CFReleaseNull(message); -#endif - -#if 1 - bool alice = true; - int max_loops = 50; - while (max_loops-- && NULL != (message = dequeueMessage())) { - if (alice) { - ok(SOSCircleHandlePeerMessage(aliceCircle, alice_full_peer_info, aliceDsf, enqueueMessage, bob_peer_id, message, &error), - "alice accepted %@: %@", desc = SOSMessageCopyDescription(message), error); - } else { - ok(SOSCircleHandlePeerMessage(bobCircle, bob_full_peer_info, bobDsf, enqueueMessage, alice_peer_id, message, &error), - "bob accepted %@: %@", desc = SOSMessageCopyDescription(message), error); - } - alice = !alice; - CFRelease(message); - CFReleaseNull(desc); - } -#endif - - CFReleaseNull(aliceCircle); - CFReleaseNull(bobCircle); - - CFReleaseNull(alice_peer_info); - CFReleaseNull(bob_peer_info); - - CFReleaseNull(alice_key); - CFReleaseNull(bob_key); - aliceDsf->release(aliceDsf); - bobDsf->release(bobDsf); -} - -// MARK: ----- start of all tests ----- - -int sc_75_circle_engine(int argc, char *const *argv) -{ - plan_tests(kTestTestCount); - - tests(); - - return 0; -} diff --git a/sec/SOSCircle/SOSARCDefines.h b/sec/SOSCircle/SOSARCDefines.h deleted file mode 100644 index 50c0475c..00000000 --- a/sec/SOSCircle/SOSARCDefines.h +++ /dev/null @@ -1,49 +0,0 @@ -// -// SOSARCDefines.h -// sec -// -// Created by John Hurley on 11/2/12. -// -// - -#ifndef sec_SOSARCDefines_h -#define sec_SOSARCDefines_h - -#ifndef __has_feature -#define __has_feature(x) 0 -#endif -#ifndef __has_extension -#define __has_extension __has_feature // Compatibility with pre-3.0 compilers. -#endif - -#if __has_feature(objc_arc) && __clang_major__ >= 3 -#define ARC_ENABLED 1 -#endif // __has_feature(objc_arc) - -#if !ARC_ENABLED || !defined(__clang__) || __clang_major__ < 3 - -#ifndef __bridge -#define __bridge -#endif -#ifndef __bridge_retained -#define __bridge_retained -#endif -#ifndef __bridge_transfer -#define __bridge_transfer -#endif -#ifndef __autoreleasing -#define __autoreleasing -#endif -#ifndef __strong -#define __strong -#endif -#ifndef __weak -#define __weak -#endif -#ifndef __unsafe_unretained -#define __unsafe_unretained -#endif - -#endif // __clang_major__ < 3 - -#endif diff --git a/sec/SOSCircle/SecureObjectSync/Imported/SOSCloudCircleServer.h b/sec/SOSCircle/SecureObjectSync/Imported/SOSCloudCircleServer.h deleted file mode 120000 index 55a3e263..00000000 --- a/sec/SOSCircle/SecureObjectSync/Imported/SOSCloudCircleServer.h +++ /dev/null @@ -1 +0,0 @@ -./../../securityd/SOSCloudCircleServer.h \ No newline at end of file diff --git a/sec/SOSCircle/SecureObjectSync/Imported/SecItemServer.h b/sec/SOSCircle/SecureObjectSync/Imported/SecItemServer.h deleted file mode 120000 index a3cf6ee6..00000000 --- a/sec/SOSCircle/SecureObjectSync/Imported/SecItemServer.h +++ /dev/null @@ -1 +0,0 @@ -./../../securityd/SecItemServer.h \ No newline at end of file diff --git a/sec/SOSCircle/SecureObjectSync/Imported/SecuritydXPC.h b/sec/SOSCircle/SecureObjectSync/Imported/SecuritydXPC.h deleted file mode 120000 index bc4863a9..00000000 --- a/sec/SOSCircle/SecureObjectSync/Imported/SecuritydXPC.h +++ /dev/null @@ -1 +0,0 @@ -./../../Security/SecuritydXPC.h \ No newline at end of file diff --git a/sec/SOSCircle/SecureObjectSync/Imported/securityd_client.h b/sec/SOSCircle/SecureObjectSync/Imported/securityd_client.h deleted file mode 120000 index f9660090..00000000 --- a/sec/SOSCircle/SecureObjectSync/Imported/securityd_client.h +++ /dev/null @@ -1 +0,0 @@ -./../../ipc/securityd_client.h \ No newline at end of file diff --git a/sec/SOSCircle/SecureObjectSync/Imported/spi.h b/sec/SOSCircle/SecureObjectSync/Imported/spi.h deleted file mode 120000 index b59d7977..00000000 --- a/sec/SOSCircle/SecureObjectSync/Imported/spi.h +++ /dev/null @@ -1 +0,0 @@ -./../../securityd/spi.h \ No newline at end of file diff --git a/sec/SOSCircle/SecureObjectSync/SOSAccount.c b/sec/SOSCircle/SecureObjectSync/SOSAccount.c deleted file mode 100644 index 198a3904..00000000 --- a/sec/SOSCircle/SecureObjectSync/SOSAccount.c +++ /dev/null @@ -1,3191 +0,0 @@ -/* - * Created by Michael Brouwer on 6/22/12. - * Copyright 2012 Apple Inc. All Rights Reserved. - */ - -/* - * SOSAccount.c - Implementation of the secure object syncing account. - * An account contains a SOSCircle for each protection domain synced. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include - -#include -#include // For SecError - -#include -#include - -#include - -static CFStringRef kicloud_identity_name = CFSTR("Cloud Identity"); - -// -// Forward statics. -// - -static bool SOSAccountHandleUpdateCircle(SOSAccountRef account, SOSCircleRef newCircle, bool writeUpdate, bool initialSync, CFErrorRef *error); - -// -// DER Encoding utilities -// - -// -// Encodes data or a zero length data -// -static size_t der_sizeof_data_or_null(CFDataRef data, CFErrorRef* error) -{ - if (data) { - return der_sizeof_data(data, error); - } else { - return der_sizeof_null(kCFNull, error); - } -} - -static uint8_t* der_encode_data_or_null(CFDataRef data, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) -{ - if (data) { - return der_encode_data(data, error, der, der_end); - } else { - return der_encode_null(kCFNull, error, der, der_end); - } -} - - -static const uint8_t* der_decode_data_or_null(CFAllocatorRef allocator, CFDataRef* data, - CFErrorRef* error, - const uint8_t* der, const uint8_t* der_end) -{ - CFTypeRef value = NULL; - der = der_decode_plist(allocator, 0, &value, error, der, der_end); - if (value && CFGetTypeID(value) != CFDataGetTypeID()) { - CFReleaseNull(value); - } - if (data) { - *data = value; - } - return der; -} - - -// -// Mark: public_bytes encode/decode -// - -static size_t der_sizeof_public_bytes(SecKeyRef publicKey, CFErrorRef* error) -{ - CFDataRef publicData = NULL; - - if (publicKey) - SecKeyCopyPublicBytes(publicKey, &publicData); - - size_t size = der_sizeof_data_or_null(publicData, error); - - CFReleaseNull(publicData); - - return size; -} - -static uint8_t* der_encode_public_bytes(SecKeyRef publicKey, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) -{ - CFDataRef publicData = NULL; - - if (publicKey) - SecKeyCopyPublicBytes(publicKey, &publicData); - - uint8_t *result = der_encode_data_or_null(publicData, error, der, der_end); - - CFReleaseNull(publicData); - - return result; -} - -static const uint8_t* der_decode_public_bytes(CFAllocatorRef allocator, CFIndex algorithmID, SecKeyRef* publicKey, CFErrorRef* error, const uint8_t* der, const uint8_t* der_end) -{ - CFDataRef dataFound = NULL; - der = der_decode_data_or_null(allocator, &dataFound, error, der, der_end); - - if (der && dataFound && publicKey) { - *publicKey = SecKeyCreateFromPublicData(allocator, algorithmID, dataFound); - } - CFReleaseNull(dataFound); - - return der; -} - - -// -// Cloud Paramters encode/decode -// - -static size_t der_sizeof_cloud_parameters(SecKeyRef publicKey, CFDataRef paramters, CFErrorRef* error) -{ - size_t public_key_size = der_sizeof_public_bytes(publicKey, error); - size_t parameters_size = der_sizeof_data_or_null(paramters, error); - - return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, public_key_size + parameters_size); -} - -static uint8_t* der_encode_cloud_parameters(SecKeyRef publicKey, CFDataRef paramters, CFErrorRef* error, - const uint8_t* der, uint8_t* der_end) -{ - uint8_t* original_der_end = der_end; - - return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, original_der_end, der, - der_encode_public_bytes(publicKey, error, der, - der_encode_data_or_null(paramters, error, der, der_end))); -} - -static const uint8_t* der_decode_cloud_parameters(CFAllocatorRef allocator, - CFIndex algorithmID, SecKeyRef* publicKey, - CFDataRef *parameters, - CFErrorRef* error, - const uint8_t* der, const uint8_t* der_end) -{ - const uint8_t *sequence_end; - der = ccder_decode_sequence_tl(&sequence_end, der, der_end); - der = der_decode_public_bytes(allocator, algorithmID, publicKey, error, der, sequence_end); - der = der_decode_data_or_null(allocator, parameters, error, der, sequence_end); - - return der; -} - - -// -// bool encoding/decoding -// - - -static const uint8_t* ccder_decode_bool(bool* boolean, const uint8_t* der, const uint8_t *der_end) -{ - if (NULL == der) - return NULL; - - size_t payload_size = 0; - const uint8_t *payload = ccder_decode_tl(CCDER_BOOLEAN, &payload_size, der, der_end); - - if (NULL == payload || (der_end - payload) < 1 || payload_size != 1) { - return NULL; - } - - if (boolean) - *boolean = (*payload != 0); - - return payload + payload_size; -} - - -static size_t ccder_sizeof_bool(bool value __unused, CFErrorRef *error) -{ - return ccder_sizeof(CCDER_BOOLEAN, 1); -} - - -static uint8_t* ccder_encode_bool(bool value, const uint8_t *der, uint8_t *der_end) -{ - uint8_t value_byte = value; - - return ccder_encode_tl(CCDER_BOOLEAN, 1, der, - ccder_encode_body(1, &value_byte, der, der_end)); -} - -struct __OpaqueSOSAccount { - CFRuntimeBase _base; - - dispatch_queue_t queue; - - CFDictionaryRef gestalt; - - CFMutableDictionaryRef circle_identities; - CFMutableDictionaryRef circles; - CFMutableDictionaryRef retired_peers; - - bool user_public_trusted; - CFDataRef user_key_parameters; - SecKeyRef user_public; - SecKeyRef previous_public; - enum DepartureReason departure_code; - - // Non-persistent data - - SOSDataSourceFactoryRef factory; - SecKeyRef _user_private; - dispatch_source_t user_private_timer; - int lock_notification_token; - - // Live Notification - CFMutableArrayRef change_blocks; - - SOSAccountKeyInterestBlock update_interest_block; - SOSAccountDataUpdateBlock update_block; - SOSAccountMessageProcessedBlock processed_message_block; - - CFMutableDictionaryRef deferred_updates; - - CFMutableDictionaryRef pending_changes; -}; - -CFGiblisWithCompareFor(SOSAccount); - -static inline bool SOSAccountHasLeft(SOSAccountRef account) { - switch(account->departure_code) { - case kSOSWithdrewMembership: /* Fallthrough */ - case kSOSMembershipRevoked: /* Fallthrough */ - case kSOSLeftUntrustedCircle: - return true; - case kSOSNeverAppliedToCircle: /* Fallthrough */ - case kSOSNeverLeftCircle: /* Fallthrough */ - default: - return false; - } -} - -// Private static functions. - -static bool SOSUpdateKeyInterest(SOSAccountRef account, bool getNewKeysOnly, CFErrorRef *error); - -static bool SOSAccountEnsureFactoryCircles(SOSAccountRef a) -{ - bool result = false; - if (a) - { - require(a->factory, xit); - CFArrayRef circle_names = a->factory->copy_names(a->factory); - require(circle_names, xit); - CFArrayForEach(circle_names, ^(const void*name) { - if (isString(name)) - SOSAccountEnsureCircle(a, (CFStringRef)name, NULL); - }); - - CFReleaseNull(circle_names); - result = true; - } -xit: - return result; -} - -static SOSAccountRef SOSAccountCreateBasic(CFAllocatorRef allocator, - CFDictionaryRef gestalt, - SOSDataSourceFactoryRef factory, - SOSAccountKeyInterestBlock interest_block, - SOSAccountDataUpdateBlock update_block) { - SOSAccountRef a = CFTypeAllocate(SOSAccount, struct __OpaqueSOSAccount, allocator); - - a->queue = dispatch_queue_create("Account Queue", DISPATCH_QUEUE_SERIAL); - - a->gestalt = gestalt; - CFRetain(a->gestalt); - - a->circles = CFDictionaryCreateMutableForCFTypes(allocator); - a->circle_identities = CFDictionaryCreateMutableForCFTypes(allocator); - a->retired_peers = CFDictionaryCreateMutableForCFTypes(allocator); - - a->factory = factory; // We adopt the factory. kthanksbai. - - a->change_blocks = CFArrayCreateMutableForCFTypes(allocator); - - a->update_interest_block = Block_copy(interest_block); - a->update_block = Block_copy(update_block); - - a->pending_changes = CFDictionaryCreateMutableForCFTypes(allocator); - a->departure_code = kSOSNeverAppliedToCircle; - - return a; -} - - -static SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircleNamedIfPresent(SOSAccountRef account, CFStringRef name, CFErrorRef *error) { - if (CFDictionaryGetValue(account->circles, name) == NULL) { - SOSCreateErrorWithFormat(kSOSErrorNoCircle, NULL, error, NULL, CFSTR("No circle named '%@'"), name); - return NULL; - } - - return (SOSFullPeerInfoRef) CFDictionaryGetValue(account->circle_identities, name); -} - - -static void SOSAccountForEachKnownCircle(SOSAccountRef account, - void (^handle_incompatible)(CFStringRef name), - void (^handle_no_peer)(SOSCircleRef circle), - void (^handle_peer)(SOSCircleRef circle, SOSFullPeerInfoRef full_peer)) { - CFDictionaryForEach(account->circles, ^(const void *key, const void *value) { - if (isNull(value)) { - if (handle_incompatible) - handle_incompatible((CFStringRef)key); - } else { - SOSCircleRef circle = (SOSCircleRef) value; - CFRetainSafe(circle); - SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircleNamedIfPresent(account, SOSCircleGetName(circle), NULL); - if (!fpi) { - if (handle_no_peer) - handle_no_peer(circle); - } else { - CFRetainSafe(fpi); - if (handle_peer) - handle_peer(circle, fpi); - CFReleaseSafe(fpi); - } - CFReleaseSafe(circle); - } - }); -} - - -bool SOSAccountUpdateGestalt(SOSAccountRef account, CFDictionaryRef new_gestalt) -{ - if (CFEqual(new_gestalt, account->gestalt)) - return false; - - SOSAccountForEachKnownCircle(account, NULL, NULL, ^(SOSCircleRef circle, SOSFullPeerInfoRef full_peer) { - if (SOSFullPeerInfoUpdateGestalt(full_peer, new_gestalt, NULL)) { - SOSAccountModifyCircle(account, SOSCircleGetName(circle), - NULL, ^(SOSCircleRef circle_to_change) { - (void) SOSCircleUpdatePeerInfo(circle_to_change, SOSFullPeerInfoGetPeerInfo(full_peer)); - }); - }; - }); - - CFReleaseNull(account->gestalt); - account->gestalt = new_gestalt; - CFRetain(account->gestalt); - - return true; -} - -SOSAccountRef SOSAccountCreate(CFAllocatorRef allocator, - CFDictionaryRef gestalt, - SOSDataSourceFactoryRef factory, - SOSAccountKeyInterestBlock interest_block, - SOSAccountDataUpdateBlock update_block) { - SOSAccountRef a = SOSAccountCreateBasic(allocator, gestalt, factory, interest_block, update_block); - - SOSAccountEnsureFactoryCircles(a); - - return a; -} - -static void SOSAccountDestroy(CFTypeRef aObj) { - SOSAccountRef a = (SOSAccountRef) aObj; - - if (a->factory) - a->factory->release(a->factory); - - CFReleaseNull(a->gestalt); - CFReleaseNull(a->circle_identities); - CFReleaseNull(a->circles); - CFReleaseNull(a->retired_peers); - - a->user_public_trusted = false; - CFReleaseNull(a->user_public); - CFReleaseNull(a->user_key_parameters); - - SOSAccountPurgePrivateCredential(a); - CFReleaseNull(a->previous_public); - - CFReleaseNull(a->change_blocks); - Block_release(a->update_interest_block); - Block_release(a->update_block); - CFReleaseNull(a->processed_message_block); - CFReleaseNull(a->pending_changes); - CFReleaseNull(a->deferred_updates); - a->departure_code = kSOSNeverAppliedToCircle; - - dispatch_release(a->queue); -} - -static void SOSAccountSetToNew(SOSAccountRef a) { - CFAllocatorRef allocator = CFGetAllocator(a); - CFReleaseNull(a->circle_identities); - CFReleaseNull(a->circles); - CFReleaseNull(a->retired_peers); - - CFReleaseNull(a->user_key_parameters); - CFReleaseNull(a->user_public); - CFReleaseNull(a->previous_public); - CFReleaseNull(a->_user_private); - - CFReleaseNull(a->pending_changes); - CFReleaseNull(a->deferred_updates); - - a->user_public_trusted = false; - a->departure_code = kSOSNeverAppliedToCircle; - a->user_private_timer = 0; - a->lock_notification_token = 0; - - // keeping gestalt; - // keeping factory; - // Live Notification - // change_blocks; - // update_interest_block; - // update_block; - - a->circles = CFDictionaryCreateMutableForCFTypes(allocator); - a->circle_identities = CFDictionaryCreateMutableForCFTypes(allocator); - a->retired_peers = CFDictionaryCreateMutableForCFTypes(allocator); - a->pending_changes = CFDictionaryCreateMutableForCFTypes(allocator); - - SOSAccountEnsureFactoryCircles(a); -} - - -static CFStringRef SOSAccountCopyDescription(CFTypeRef aObj) { - SOSAccountRef a = (SOSAccountRef) aObj; - - return CFStringCreateWithFormat(NULL, NULL, CFSTR(""), a, a->gestalt, a->circles, a->circle_identities); -} - -static Boolean SOSAccountCompare(CFTypeRef lhs, CFTypeRef rhs) -{ - SOSAccountRef laccount = (SOSAccountRef) lhs; - SOSAccountRef raccount = (SOSAccountRef) rhs; - - return CFEqual(laccount->gestalt, raccount->gestalt) - && CFEqual(laccount->circles, raccount->circles) - && CFEqual(laccount->circle_identities, raccount->circle_identities); - // ??? retired_peers -} - -#if OLD_CODERS_SUPPORTED - -// -// MARK: Persistent Encode decode -// -SOSAccountRef SOSAccountCreateFromDER_V1(CFAllocatorRef allocator, - SOSDataSourceFactoryRef factory, - SOSAccountKeyInterestBlock interest_block, - SOSAccountDataUpdateBlock update_block, - CFErrorRef* error, - const uint8_t** der_p, const uint8_t *der_end) -{ - SOSAccountRef account = NULL; - - const uint8_t *sequence_end; - *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); - - { - CFDictionaryRef decoded_gestalt = NULL; - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, - *der_p, der_end); - - if (*der_p == 0) - return NULL; - - account = SOSAccountCreateBasic(allocator, decoded_gestalt, factory, interest_block, update_block); - CFReleaseNull(decoded_gestalt); - } - - CFArrayRef array = NULL; - *der_p = der_decode_array(kCFAllocatorDefault, 0, &array, error, *der_p, sequence_end); - - *der_p = ccder_decode_bool(&account->user_public_trusted, *der_p, sequence_end); - *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->user_public, error, *der_p, sequence_end); - *der_p = der_decode_data_or_null(kCFAllocatorDefault, &account->user_key_parameters, error, *der_p, sequence_end); - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *) &account->retired_peers, error, *der_p, sequence_end); - if (*der_p != sequence_end) - *der_p = NULL; - - __block bool success = true; - - require_quiet(array && *der_p, fail); - - CFArrayForEach(array, ^(const void *value) { - if (success) { - if (isString(value)) { - CFDictionaryAddValue(account->circles, value, kCFNull); - } else { - CFDataRef circleData = NULL; - CFDataRef fullPeerInfoData = NULL; - - if (isData(value)) { - circleData = (CFDataRef) value; - } else if (isArray(value)) { - CFArrayRef pair = (CFArrayRef) value; - - CFTypeRef circleObject = CFArrayGetValueAtIndex(pair, 0); - CFTypeRef fullPeerInfoObject = CFArrayGetValueAtIndex(pair, 1); - - if (CFArrayGetCount(pair) == 2 && isData(circleObject) && isData(fullPeerInfoObject)) { - circleData = (CFDataRef) circleObject; - fullPeerInfoData = (CFDataRef) fullPeerInfoObject; - } - } - - if (circleData) { - SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, circleData, error); - require_action_quiet(circle, fail, success = false); - - CFStringRef circleName = SOSCircleGetName(circle); - CFDictionaryAddValue(account->circles, circleName, circle); - - if (fullPeerInfoData) { - SOSFullPeerInfoRef full_peer = SOSFullPeerInfoCreateFromData(kCFAllocatorDefault, fullPeerInfoData, error); - require_action_quiet(full_peer, fail, success = false); - - CFDictionaryAddValue(account->circle_identities, circleName, full_peer); - CFReleaseNull(full_peer); - } - fail: - CFReleaseNull(circle); - } - } - } - }); - CFReleaseNull(array); - - require_quiet(success, fail); - require_action_quiet(SOSAccountEnsureFactoryCircles(account), fail, - SOSCreateError(kSOSErrorBadFormat, CFSTR("Cannot EnsureFactoryCircles"), (error != NULL) ? *error : NULL, error)); - - return account; - -fail: - // Create a default error if we don't have one: - SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Account DER"), NULL, error); - CFReleaseNull(account); - return NULL; -} - -SOSAccountRef SOSAccountCreateFromDER_V2(CFAllocatorRef allocator, - SOSDataSourceFactoryRef factory, - SOSAccountKeyInterestBlock interest_block, - SOSAccountDataUpdateBlock update_block, - CFErrorRef* error, - const uint8_t** der_p, const uint8_t *der_end) -{ - SOSAccountRef account = NULL; - const uint8_t *dersave = *der_p; - const uint8_t *derend = der_end; - - const uint8_t *sequence_end; - *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); - - { - CFDictionaryRef decoded_gestalt = NULL; - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, - *der_p, der_end); - - if (*der_p == 0) - return NULL; - - account = SOSAccountCreateBasic(allocator, decoded_gestalt, factory, interest_block, update_block); - CFReleaseNull(decoded_gestalt); - } - - CFArrayRef array = NULL; - *der_p = der_decode_array(kCFAllocatorDefault, 0, &array, error, *der_p, sequence_end); - - uint64_t tmp_departure_code = kSOSNeverAppliedToCircle; - *der_p = ccder_decode_uint64(&tmp_departure_code, *der_p, sequence_end); - *der_p = ccder_decode_bool(&account->user_public_trusted, *der_p, sequence_end); - *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->user_public, error, *der_p, sequence_end); - *der_p = der_decode_data_or_null(kCFAllocatorDefault, &account->user_key_parameters, error, *der_p, sequence_end); - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *) &account->retired_peers, error, *der_p, sequence_end); - if (*der_p != sequence_end) - *der_p = NULL; - account->departure_code = (enum DepartureReason) tmp_departure_code; - - __block bool success = true; - - require_quiet(array && *der_p, fail); - - CFArrayForEach(array, ^(const void *value) { - if (success) { - if (isString(value)) { - CFDictionaryAddValue(account->circles, value, kCFNull); - } else { - CFDataRef circleData = NULL; - CFDataRef fullPeerInfoData = NULL; - - if (isData(value)) { - circleData = (CFDataRef) value; - } else if (isArray(value)) { - CFArrayRef pair = (CFArrayRef) value; - - CFTypeRef circleObject = CFArrayGetValueAtIndex(pair, 0); - CFTypeRef fullPeerInfoObject = CFArrayGetValueAtIndex(pair, 1); - - if (CFArrayGetCount(pair) == 2 && isData(circleObject) && isData(fullPeerInfoObject)) { - circleData = (CFDataRef) circleObject; - fullPeerInfoData = (CFDataRef) fullPeerInfoObject; - } - } - - if (circleData) { - SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, circleData, error); - require_action_quiet(circle, fail, success = false); - - CFStringRef circleName = SOSCircleGetName(circle); - CFDictionaryAddValue(account->circles, circleName, circle); - - if (fullPeerInfoData) { - SOSFullPeerInfoRef full_peer = SOSFullPeerInfoCreateFromData(kCFAllocatorDefault, fullPeerInfoData, error); - require_action_quiet(full_peer, fail, success = false); - - CFDictionaryAddValue(account->circle_identities, circleName, full_peer); - } - fail: - CFReleaseNull(circle); - } - } - } - }); - CFReleaseNull(array); - - require_quiet(success, fail); - require_action_quiet(SOSAccountEnsureFactoryCircles(account), fail, - SOSCreateError(kSOSErrorBadFormat, CFSTR("Cannot EnsureFactoryCircles"), (error != NULL) ? *error : NULL, error)); - - return account; - -fail: - // Create a default error if we don't have one: - account->factory = NULL; // give the factory back. - CFReleaseNull(account); - // Try the der inflater from the previous release. - account = SOSAccountCreateFromDER_V1(allocator, factory, interest_block, update_block, error, &dersave, derend); - if(account) account->departure_code = kSOSNeverAppliedToCircle; - return account; -} - -#endif /* OLD_CODERS_SUPPORTED */ - -#define CURRENT_ACCOUNT_PERSISTENT_VERSION 6 - -SOSAccountRef SOSAccountCreateFromDER(CFAllocatorRef allocator, - SOSDataSourceFactoryRef factory, - SOSAccountKeyInterestBlock interest_block, - SOSAccountDataUpdateBlock update_block, - CFErrorRef* error, - const uint8_t** der_p, const uint8_t *der_end) -{ - SOSAccountRef account = NULL; -#if UPGRADE_FROM_PREVIOUS_VERSION - const uint8_t *dersave = *der_p; - const uint8_t *derend = der_end; -#endif - uint64_t version = 0; - - const uint8_t *sequence_end; - *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); - *der_p = ccder_decode_uint64(&version, *der_p, sequence_end); - if(!(*der_p) || version < CURRENT_ACCOUNT_PERSISTENT_VERSION) { -#if UPGRADE_FROM_PREVIOUS_VERSION - return SOSAccountCreateFromDER_V3(allocator, factory, interest_block, update_block, error, &dersave, derend); -#else - return NULL; -#endif - } - - { - CFDictionaryRef decoded_gestalt = NULL; - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, - *der_p, der_end); - - if (*der_p == 0) - return NULL; - - account = SOSAccountCreateBasic(allocator, decoded_gestalt, factory, interest_block, update_block); - CFReleaseNull(decoded_gestalt); - } - - CFArrayRef array = NULL; - *der_p = der_decode_array(kCFAllocatorDefault, 0, &array, error, *der_p, sequence_end); - - uint64_t tmp_departure_code = kSOSNeverAppliedToCircle; - *der_p = ccder_decode_uint64(&tmp_departure_code, *der_p, sequence_end); - *der_p = ccder_decode_bool(&account->user_public_trusted, *der_p, sequence_end); - *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->user_public, error, *der_p, sequence_end); - *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->previous_public, error, *der_p, sequence_end); - *der_p = der_decode_data_or_null(kCFAllocatorDefault, &account->user_key_parameters, error, *der_p, sequence_end); - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *) &account->retired_peers, error, *der_p, sequence_end); - if (*der_p != sequence_end) - *der_p = NULL; - account->departure_code = (enum DepartureReason) tmp_departure_code; - - __block bool success = true; - - require_quiet(array && *der_p, fail); - - CFArrayForEach(array, ^(const void *value) { - if (success) { - if (isString(value)) { - CFDictionaryAddValue(account->circles, value, kCFNull); - } else { - CFDataRef circleData = NULL; - CFDataRef fullPeerInfoData = NULL; - - if (isData(value)) { - circleData = (CFDataRef) value; - } else if (isArray(value)) { - CFArrayRef pair = (CFArrayRef) value; - - CFTypeRef circleObject = CFArrayGetValueAtIndex(pair, 0); - CFTypeRef fullPeerInfoObject = CFArrayGetValueAtIndex(pair, 1); - - if (CFArrayGetCount(pair) == 2 && isData(circleObject) && isData(fullPeerInfoObject)) { - circleData = (CFDataRef) circleObject; - fullPeerInfoData = (CFDataRef) fullPeerInfoObject; - } - } - - if (circleData) { - SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, circleData, error); - require_action_quiet(circle, fail, success = false); - - CFStringRef circleName = SOSCircleGetName(circle); - CFDictionaryAddValue(account->circles, circleName, circle); - - if (fullPeerInfoData) { - SOSFullPeerInfoRef full_peer = SOSFullPeerInfoCreateFromData(kCFAllocatorDefault, fullPeerInfoData, error); - require_action_quiet(full_peer, fail, success = false); - - CFDictionaryAddValue(account->circle_identities, circleName, full_peer); - } - fail: - CFReleaseNull(circle); - } - } - } - }); - CFReleaseNull(array); - - require_quiet(success, fail); - require_action_quiet(SOSAccountEnsureFactoryCircles(account), fail, - SOSCreateError(kSOSErrorBadFormat, CFSTR("Cannot EnsureFactoryCircles"), (error != NULL) ? *error : NULL, error)); - - return account; - -fail: - account->factory = NULL; // give the factory back. - CFReleaseNull(account); - return NULL; -} - - -SOSAccountRef SOSAccountCreateFromDER_V3(CFAllocatorRef allocator, - SOSDataSourceFactoryRef factory, - SOSAccountKeyInterestBlock interest_block, - SOSAccountDataUpdateBlock update_block, - CFErrorRef* error, - const uint8_t** der_p, const uint8_t *der_end) -{ - SOSAccountRef account = NULL; - uint64_t version = 0; - - const uint8_t *sequence_end; - *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); - *der_p = ccder_decode_uint64(&version, *der_p, sequence_end); - if(!(*der_p) || version != 3) { - // In this case we want to silently fail so that an account gets newly created. - return NULL; - } - - { - CFDictionaryRef decoded_gestalt = NULL; - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListImmutable, &decoded_gestalt, error, - *der_p, der_end); - - if (*der_p == 0) - return NULL; - - account = SOSAccountCreateBasic(allocator, decoded_gestalt, factory, interest_block, update_block); - CFReleaseNull(decoded_gestalt); - } - - CFArrayRef array = NULL; - *der_p = der_decode_array(kCFAllocatorDefault, 0, &array, error, *der_p, sequence_end); - - uint64_t tmp_departure_code = kSOSNeverAppliedToCircle; - *der_p = ccder_decode_uint64(&tmp_departure_code, *der_p, sequence_end); - *der_p = ccder_decode_bool(&account->user_public_trusted, *der_p, sequence_end); - *der_p = der_decode_public_bytes(kCFAllocatorDefault, kSecECDSAAlgorithmID, &account->user_public, error, *der_p, sequence_end); - *der_p = der_decode_data_or_null(kCFAllocatorDefault, &account->user_key_parameters, error, *der_p, sequence_end); - *der_p = der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef *) &account->retired_peers, error, *der_p, sequence_end); - if (*der_p != sequence_end) - *der_p = NULL; - account->departure_code = (enum DepartureReason) tmp_departure_code; - - __block bool success = true; - - require_quiet(array && *der_p, fail); - - CFArrayForEach(array, ^(const void *value) { - if (success) { - if (isString(value)) { - CFDictionaryAddValue(account->circles, value, kCFNull); - } else { - CFDataRef circleData = NULL; - CFDataRef fullPeerInfoData = NULL; - - if (isData(value)) { - circleData = (CFDataRef) value; - } else if (isArray(value)) { - CFArrayRef pair = (CFArrayRef) value; - - CFTypeRef circleObject = CFArrayGetValueAtIndex(pair, 0); - CFTypeRef fullPeerInfoObject = CFArrayGetValueAtIndex(pair, 1); - - if (CFArrayGetCount(pair) == 2 && isData(circleObject) && isData(fullPeerInfoObject)) { - circleData = (CFDataRef) circleObject; - fullPeerInfoData = (CFDataRef) fullPeerInfoObject; - } - } - - if (circleData) { - SOSCircleRef circle = SOSCircleCreateFromData(kCFAllocatorDefault, circleData, error); - require_action_quiet(circle, fail, success = false); - - CFStringRef circleName = SOSCircleGetName(circle); - CFDictionaryAddValue(account->circles, circleName, circle); - - if (fullPeerInfoData) { - SOSFullPeerInfoRef full_peer = SOSFullPeerInfoCreateFromData(kCFAllocatorDefault, fullPeerInfoData, error); - require_action_quiet(full_peer, fail, success = false); - - CFDictionaryAddValue(account->circle_identities, circleName, full_peer); - } - fail: - CFReleaseNull(circle); - } - } - } - }); - CFReleaseNull(array); - - require_quiet(success, fail); - require_action_quiet(SOSAccountEnsureFactoryCircles(account), fail, - SOSCreateError(kSOSErrorBadFormat, CFSTR("Cannot EnsureFactoryCircles"), (error != NULL) ? *error : NULL, error)); - - return account; - -fail: - // Create a default error if we don't have one: - account->factory = NULL; // give the factory back. - CFReleaseNull(account); - // Don't try the der inflater from the previous release. - // account = SOSAccountCreateFromDER_V2(allocator, factory, interest_block, update_block, error, &dersave, derend); - if(account) account->departure_code = kSOSNeverAppliedToCircle; - return account; -} - -SOSAccountRef SOSAccountCreateFromData(CFAllocatorRef allocator, CFDataRef circleData, - SOSDataSourceFactoryRef factory, - SOSAccountKeyInterestBlock interest_block, - SOSAccountDataUpdateBlock update_block, - CFErrorRef* error) -{ - size_t size = CFDataGetLength(circleData); - const uint8_t *der = CFDataGetBytePtr(circleData); - SOSAccountRef account = SOSAccountCreateFromDER(allocator, factory, interest_block, update_block, - error, - &der, der + size); - return account; -} - -static CFMutableArrayRef SOSAccountCopyCircleArrayToEncode(SOSAccountRef account) -{ - CFMutableArrayRef arrayToEncode = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - - CFDictionaryForEach(account->circles, ^(const void *key, const void *value) { - if (isNull(value)) { - CFArrayAppendValue(arrayToEncode, key); // Encode the name of the circle that's out of date. - } else { - SOSCircleRef circle = (SOSCircleRef) value; - CFDataRef encodedCircle = SOSCircleCopyEncodedData(circle, kCFAllocatorDefault, NULL); - CFTypeRef arrayEntry = encodedCircle; - CFRetainSafe(arrayEntry); - - SOSFullPeerInfoRef full_peer = (SOSFullPeerInfoRef) CFDictionaryGetValue(account->circle_identities, key); - - if (full_peer) { - CFDataRef encodedPeer = SOSFullPeerInfoCopyEncodedData(full_peer, kCFAllocatorDefault, NULL); - CFTypeRef originalArrayEntry = arrayEntry; - arrayEntry = CFArrayCreateForCFTypes(kCFAllocatorDefault, encodedCircle, encodedPeer, NULL); - - CFReleaseSafe(originalArrayEntry); - CFReleaseNull(encodedPeer); - } - - CFArrayAppendValue(arrayToEncode, arrayEntry); - - CFReleaseSafe(arrayEntry); - CFReleaseNull(encodedCircle); - } - - }); - - return arrayToEncode; -} - -size_t SOSAccountGetDEREncodedSize(SOSAccountRef account, CFErrorRef *error) -{ - size_t sequence_size = 0; - CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); - uint64_t version = CURRENT_ACCOUNT_PERSISTENT_VERSION; - - require_quiet(accumulate_size(&sequence_size, ccder_sizeof_uint64(version)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->gestalt, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_array(arrayToEncode, error)), fail); - require_quiet(accumulate_size(&sequence_size, ccder_sizeof_uint64(account->departure_code)), fail); - require_quiet(accumulate_size(&sequence_size, ccder_sizeof_bool(account->user_public_trusted, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account->user_public, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account->previous_public, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_data_or_null(account->user_key_parameters, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->retired_peers, error)), fail); - - CFReleaseNull(arrayToEncode); - return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, sequence_size); - -fail: - CFReleaseNull(arrayToEncode); - SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error); - return 0; -} - -uint8_t* SOSAccountEncodeToDER(SOSAccountRef account, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) -{ - CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); - uint64_t version = CURRENT_ACCOUNT_PERSISTENT_VERSION; - der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, - ccder_encode_uint64(version, der, - der_encode_dictionary(account->gestalt, error, der, - der_encode_array(arrayToEncode, error, der, - ccder_encode_uint64(account->departure_code, der, - ccder_encode_bool(account->user_public_trusted, der, - der_encode_public_bytes(account->user_public, error, der, - der_encode_public_bytes(account->previous_public, error, der, - der_encode_data_or_null(account->user_key_parameters, error, der, - der_encode_dictionary(account->retired_peers, error, der, der_end)))))))))); - - CFReleaseNull(arrayToEncode); - - return der_end; -} - - - -size_t SOSAccountGetDEREncodedSize_V3(SOSAccountRef account, CFErrorRef *error) -{ - size_t sequence_size = 0; - CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); - uint64_t version = CURRENT_ACCOUNT_PERSISTENT_VERSION; - - require_quiet(accumulate_size(&sequence_size, ccder_sizeof_uint64(version)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->gestalt, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_array(arrayToEncode, error)), fail); - require_quiet(accumulate_size(&sequence_size, ccder_sizeof_uint64(account->departure_code)), fail); - require_quiet(accumulate_size(&sequence_size, ccder_sizeof_bool(account->user_public_trusted, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account->user_public, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_data_or_null(account->user_key_parameters, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->retired_peers, error)), fail); - - CFReleaseNull(arrayToEncode); - return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, sequence_size); - -fail: - CFReleaseNull(arrayToEncode); - SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error); - return 0; -} - -uint8_t* SOSAccountEncodeToDER_V3(SOSAccountRef account, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) -{ - CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); - uint64_t version = 3; - der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, - ccder_encode_uint64(version, der, - der_encode_dictionary(account->gestalt, error, der, - der_encode_array(arrayToEncode, error, der, - ccder_encode_uint64(account->departure_code, der, - ccder_encode_bool(account->user_public_trusted, der, - der_encode_public_bytes(account->user_public, error, der, - der_encode_data_or_null(account->user_key_parameters, error, der, - der_encode_dictionary(account->retired_peers, error, der, der_end))))))))); - - CFReleaseNull(arrayToEncode); - - return der_end; -} - -#if OLD_CODERS_SUPPORTED - -/* Original V2 encoders */ - -size_t SOSAccountGetDEREncodedSize_V2(SOSAccountRef account, CFErrorRef *error) -{ - size_t sequence_size = 0; - CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); - - require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->gestalt, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_array(arrayToEncode, error)), fail); - require_quiet(accumulate_size(&sequence_size, ccder_sizeof_uint64(account->departure_code)), fail); - require_quiet(accumulate_size(&sequence_size, ccder_sizeof_bool(account->user_public_trusted, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account->user_public, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_data_or_null(account->user_key_parameters, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->retired_peers, error)), fail); - - CFReleaseNull(arrayToEncode); - return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, sequence_size); - -fail: - CFReleaseNull(arrayToEncode); - SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error); - return 0; -} - -uint8_t* SOSAccountEncodeToDER_V2(SOSAccountRef account, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) -{ - CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); - - der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, - der_encode_dictionary(account->gestalt, error, der, - der_encode_array(arrayToEncode, error, der, - ccder_encode_uint64(account->departure_code, der, - ccder_encode_bool(account->user_public_trusted, der, - der_encode_public_bytes(account->user_public, error, der, - der_encode_data_or_null(account->user_key_parameters, error, der, - der_encode_dictionary(account->retired_peers, error, der, der_end)))))))); - - CFReleaseNull(arrayToEncode); - - return der_end; -} - - -/* Original V1 encoders */ - - -size_t SOSAccountGetDEREncodedSize_V1(SOSAccountRef account, CFErrorRef *error) -{ - size_t sequence_size = 0; - CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); - - require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->gestalt, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_array(arrayToEncode, error)), fail); - require_quiet(accumulate_size(&sequence_size, ccder_sizeof_bool(account->user_public_trusted, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_public_bytes(account->user_public, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_data_or_null(account->user_key_parameters, error)), fail); - require_quiet(accumulate_size(&sequence_size, der_sizeof_dictionary(account->retired_peers, error)), fail); - - CFReleaseNull(arrayToEncode); - return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, sequence_size); - -fail: - CFReleaseNull(arrayToEncode); - SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error); - return 0; -} - -uint8_t* SOSAccountEncodeToDER_V1(SOSAccountRef account, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) -{ - CFMutableArrayRef arrayToEncode = SOSAccountCopyCircleArrayToEncode(account); - - der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, - der_encode_dictionary(account->gestalt, error, der, - der_encode_array(arrayToEncode, error, der, - ccder_encode_bool(account->user_public_trusted, der, - der_encode_public_bytes(account->user_public, error, der, - der_encode_data_or_null(account->user_key_parameters, error, der, - der_encode_dictionary(account->retired_peers, error, der, der_end))))))); - - CFReleaseNull(arrayToEncode); - - return der_end; -} -#endif /* OLD_CODERS_SUPPORTED */ - -/************************/ - -CFDataRef SOSAccountCopyEncodedData(SOSAccountRef account, CFAllocatorRef allocator, CFErrorRef *error) -{ - size_t size = SOSAccountGetDEREncodedSize(account, error); - if (size == 0) - return NULL; - uint8_t buffer[size]; - uint8_t* start = SOSAccountEncodeToDER(account, error, buffer, buffer + sizeof(buffer)); - CFDataRef result = CFDataCreate(kCFAllocatorDefault, start, size); - return result; -} - -dispatch_queue_t SOSAccountGetQueue(SOSAccountRef account) { - return account->queue; -} - -// -// MARK: User Credential management -// - -void SOSAccountPurgePrivateCredential(SOSAccountRef account) -{ - CFReleaseNull(account->_user_private); - if (account->user_private_timer) { - dispatch_source_cancel(account->user_private_timer); - dispatch_release(account->user_private_timer); - account->user_private_timer = NULL; - xpc_transaction_end(); - } - if (account->lock_notification_token) { - notify_cancel(account->lock_notification_token); - account->lock_notification_token = 0; - } -} - -static void SOSAccountSetPrivateCredential(SOSAccountRef account, SecKeyRef private) { - if (!private) - return SOSAccountPurgePrivateCredential(account); - - CFRetain(private); - CFReleaseSafe(account->_user_private); - account->_user_private = private; - - bool resume_timer = false; - if (!account->user_private_timer) { - xpc_transaction_begin(); - resume_timer = true; - account->user_private_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, account->queue); - dispatch_source_set_event_handler(account->user_private_timer, ^{ - SOSAccountPurgePrivateCredential(account); - }); - - notify_register_dispatch(kUserKeybagStateChangeNotification, &account->lock_notification_token, account->queue, ^(int token) { - bool locked = false; - CFErrorRef lockCheckError = NULL; - - if (!SecAKSGetIsLocked(&locked, &lockCheckError)) { - secerror("Checking for locked after change failed: %@", lockCheckError); - } - - if (locked) { - SOSAccountPurgePrivateCredential(account); - } - }); - } - - // (Re)set the timer's fire time to now + 120 seconds with a 5 second fuzz factor. - dispatch_time_t purgeTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * 60 * NSEC_PER_SEC)); - dispatch_source_set_timer(account->user_private_timer, purgeTime, DISPATCH_TIME_FOREVER, (int64_t)(5 * NSEC_PER_SEC)); - if (resume_timer) - dispatch_resume(account->user_private_timer); -} - -SecKeyRef SOSAccountGetPrivateCredential(SOSAccountRef account, CFErrorRef* error) -{ - if (account->_user_private == NULL) { - SOSCreateError(kSOSErrorPrivateKeyAbsent, CFSTR("Private Key not available - failed to prompt user recently"), NULL, error); - } - return account->_user_private; -} - -static bool SOSAccountHasPublicKey(SOSAccountRef account, CFErrorRef* error) -{ - if (account->user_public == NULL || account->user_public_trusted == false) { - SOSCreateError(kSOSErrorPublicKeyAbsent, CFSTR("Public Key not available - failed to register before call"), NULL, error); - return false; - } - - return true; -} - -static bool SOSAccountIsMyPeerActiveInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error); - -static void SOSAccountGenerationSignatureUpdate(SOSAccountRef account, SecKeyRef privKey) { - SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { - SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircle(account, circle, NULL); - if(SOSCircleHasPeer(circle, SOSFullPeerInfoGetPeerInfo(fpi), NULL) && - !SOSCircleVerify(circle, account->user_public, NULL)) { - SOSAccountModifyCircle(account, SOSCircleGetName(circle), NULL, ^(SOSCircleRef circle) { - SOSFullPeerInfoRef cloud_fpi = SOSCircleGetiCloudFullPeerInfoRef(circle); - require_quiet(cloud_fpi != NULL, gen_sign); - require_quiet(SOSFullPeerInfoUpgradeSignatures(cloud_fpi, privKey, NULL), gen_sign); - if(!SOSCircleUpdatePeerInfo(circle, SOSFullPeerInfoGetPeerInfo(cloud_fpi))) { - } - gen_sign: // finally generation sign this. - SOSCircleGenerationSign(circle, privKey, fpi, NULL); - account->departure_code = kSOSNeverLeftCircle; - }); - } - }); -} - -/* this one is meant to be local - not published over KVS. */ -static void SOSAccountPeerSignatureUpdate(SOSAccountRef account, SecKeyRef privKey) { - SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { - SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircle(account, circle, NULL); - SOSFullPeerInfoUpgradeSignatures(fpi, privKey, NULL); - }); -} - -static void SOSAccountSetPreviousPublic(SOSAccountRef account) { - CFReleaseNull(account->previous_public); - account->previous_public = account->user_public; - CFRetain(account->previous_public); -} - -static void SOSAccountSetTrustedUserPublicKey(SOSAccountRef account, bool public_was_trusted, SecKeyRef privKey) -{ - if (!privKey) return; - SecKeyRef publicKey = SecKeyCreatePublicFromPrivate(privKey); - - if (account->user_public && account->user_public_trusted && CFEqual(publicKey, account->user_public)) return; - - if(public_was_trusted && account->user_public) { - CFReleaseNull(account->previous_public); - account->previous_public = account->user_public; - CFRetain(account->previous_public); - } - - CFReleaseNull(account->user_public); - account->user_public = publicKey; - account->user_public_trusted = true; - - if(!account->previous_public) { - account->previous_public = account->user_public; - CFRetain(account->previous_public); - } - - secnotice("trust", "trusting new public key: %@", account->user_public); -} - -static void SOSAccountProcessDeferredUpdates(SOSAccountRef account) { - CFErrorRef error = NULL; - if (account->deferred_updates && !SOSAccountHandleUpdates(account, account->deferred_updates, &error)) - secerror("Failed to handle updates when setting public key (%@)", error); - - CFReleaseNull(account->deferred_updates); -} - - -bool SOSAccountTryUserCredentials(SOSAccountRef account, CFStringRef user_account __unused, CFDataRef user_password, CFErrorRef *error) -{ - bool success = false; - - if (!SOSAccountHasPublicKey(account, error)) - return false; - - if (account->user_key_parameters) { - SecKeyRef new_key = SOSUserKeygen(user_password, account->user_key_parameters, error); - if (new_key) { - SecKeyRef new_public_key = SecKeyCreatePublicFromPrivate(new_key); - - if (CFEqualSafe(new_public_key, account->user_public)) { - SOSAccountSetPrivateCredential(account, new_key); - success = true; - } else { - SOSCreateError(kSOSErrorWrongPassword, CFSTR("Password passed in incorrect: ▇█████▇▇██"), NULL, error); - } - CFReleaseSafe(new_public_key); - CFReleaseSafe(new_key); - } - } else { - SOSCreateError(kSOSErrorProcessingFailure, CFSTR("Have public key but no parameters??"), NULL, error); - } - - return success; -} - -static bool SOSAccountPublishCloudParameters(SOSAccountRef account, CFErrorRef* error) -{ - bool success = false; - CFMutableDataRef cloudParameters = CFDataCreateMutableWithScratch(kCFAllocatorDefault, - der_sizeof_cloud_parameters(account->user_public, - account->user_key_parameters, - error)); - if (der_encode_cloud_parameters(account->user_public, account->user_key_parameters, error, - CFDataGetMutableBytePtr(cloudParameters), - CFDataGetMutablePastEndPtr(cloudParameters)) != NULL) { - - CFDictionaryRef changes = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, - kSOSKVSKeyParametersKey, cloudParameters, - NULL); - - CFErrorRef changeError = NULL; - if (account->update_block(changes, &changeError)) { - success = true; - } else { - SOSCreateErrorWithFormat(kSOSErrorSendFailure, changeError, error, NULL, - CFSTR("update parameters key failed [%@]"), changes); - } - CFReleaseSafe(changes); - CFReleaseSafe(changeError); - } else { - SOSCreateError(kSOSErrorEncodeFailure, CFSTR("Encoding parameters failed"), NULL, error); - } - - CFReleaseNull(cloudParameters); - - return success; -} - -bool SOSAccountAssertUserCredentials(SOSAccountRef account, CFStringRef user_account __unused, CFDataRef user_password, CFErrorRef *error) -{ - bool public_was_trusted = account->user_public_trusted; - account->user_public_trusted = false; - SecKeyRef user_private = NULL; - - if (account->user_public && account->user_key_parameters) { - // We have an untrusted public key – see if our generation makes the same key: - // if so we trust it and we have the private key. - // if not we still don't trust it. - require_quiet(user_private = SOSUserKeygen(user_password, account->user_key_parameters, error), exit); - SecKeyRef public_candidate = SecKeyCreatePublicFromPrivate(user_private); - if (!CFEqualSafe(account->user_public, public_candidate)) { - secnotice("trust", "Public keys don't match: calculated: %@, expected: %@", - account->user_public, public_candidate); - debugDumpUserParameters(CFSTR("params"), account->user_key_parameters); - CFReleaseNull(user_private); - } else { - SOSAccountPeerSignatureUpdate(account, user_private); - SOSAccountSetTrustedUserPublicKey(account, public_was_trusted, user_private); - } - CFReleaseSafe(public_candidate); - } - - if (!account->user_public_trusted) { - // We may or may not have parameters here. - // In any case we tried using them and they didn't match - // So forget all that and start again, assume we're the first to push anything useful. - - CFReleaseNull(account->user_key_parameters); - account->user_key_parameters = SOSUserKeyCreateGenerateParameters(error); - require_quiet(user_private = SOSUserKeygen(user_password, account->user_key_parameters, error), exit); - - SOSAccountPeerSignatureUpdate(account, user_private); - SOSAccountSetTrustedUserPublicKey(account, public_was_trusted, user_private); - - CFErrorRef publishError = NULL; - if (!SOSAccountPublishCloudParameters(account, &publishError)) - secerror("Failed to publish new cloud parameters: %@", publishError); - CFReleaseSafe(publishError); - } - - SOSAccountProcessDeferredUpdates(account); - SOSAccountGenerationSignatureUpdate(account, user_private); - SOSAccountSetPrivateCredential(account, user_private); -exit: - CFReleaseSafe(user_private); - - return account->user_public_trusted; -} - -// -// MARK: Circle management -// - -int SOSAccountCountCircles(SOSAccountRef a) { - assert(a); - assert(a->circle_identities); - assert(a->circles); - return (int)CFDictionaryGetCount(a->circles); -} - -static SecKeyRef GeneratePermanentFullECKey_internal(int keySize, CFStringRef name, CFTypeRef accessibility, CFBooleanRef sync, CFErrorRef* error) -{ - SecKeyRef full_key = NULL; - - CFNumberRef key_size_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &keySize); - - CFDictionaryRef priv_key_attrs = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, - kSecAttrIsPermanent, kCFBooleanTrue, - NULL); - - CFDictionaryRef keygen_parameters = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, - kSecAttrKeyType, kSecAttrKeyTypeEC, - kSecAttrKeySizeInBits, key_size_num, - kSecPrivateKeyAttrs, priv_key_attrs, - kSecAttrAccessible, accessibility, - kSecAttrAccessGroup, kSOSInternalAccessGroup, - kSecAttrLabel, name, - kSecAttrSynchronizable, sync, - kSecUseTombstones, kCFBooleanTrue, - NULL); - - CFReleaseNull(priv_key_attrs); - - CFReleaseNull(key_size_num); - OSStatus status = SecKeyGeneratePair(keygen_parameters, NULL, &full_key); - CFReleaseNull(keygen_parameters); - - if (status) - secerror("status: %ld", (long)status); - if (status != errSecSuccess && error != NULL && *error == NULL) { - *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus, status, NULL); - } - - return full_key; -} - -static SecKeyRef GeneratePermanentFullECKey(int keySize, CFStringRef name, CFErrorRef* error) { - return GeneratePermanentFullECKey_internal(keySize, name, kSecAttrAccessibleWhenUnlockedThisDeviceOnly, kCFBooleanFalse, error); -} - -static SecKeyRef GeneratePermanentFullECKeyForCloudIdentity(int keySize, CFStringRef name, CFErrorRef* error) { - return GeneratePermanentFullECKey_internal(keySize, name, kSecAttrAccessibleWhenUnlocked, kCFBooleanTrue, error); -} - - -SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircleNamed(SOSAccountRef account, CFStringRef name, CFErrorRef *error) { - if (CFDictionaryGetValue(account->circles, name) == NULL) { - SOSCreateErrorWithFormat(kSOSErrorNoCircle, NULL, error, NULL, CFSTR("No circle named '%@'"), name); - return NULL; - } - SOSFullPeerInfoRef circle_full_peer_info = (SOSFullPeerInfoRef) CFDictionaryGetValue(account->circle_identities, name); - - - if (circle_full_peer_info == NULL) { - CFStringRef keyName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("ID for %@-%@"), SOSPeerGestaltGetName(account->gestalt), name); - SecKeyRef full_key = GeneratePermanentFullECKey(256, keyName, error); - CFReleaseNull(keyName); - - if (full_key) { - circle_full_peer_info = SOSFullPeerInfoCreate(kCFAllocatorDefault, account->gestalt, full_key, error); - - CFReleaseNull(full_key); - - if (!circle_full_peer_info) { - secerror("Can't make FullPeerInfo for %@-%@ (%@) - is AKS ok?", SOSPeerGestaltGetName(account->gestalt), name, error ? (void*)*error : (void*)CFSTR("-")); - return circle_full_peer_info; - } - - CFDictionarySetValue(account->circle_identities, name, circle_full_peer_info); - CFReleaseNull(circle_full_peer_info); - circle_full_peer_info = (SOSFullPeerInfoRef) CFDictionaryGetValue(account->circle_identities, name); - } - else - secerror("No full_key: %@:", error ? *error : NULL); - } - - return circle_full_peer_info; -} - -static bool SOSAccountDestroyCirclePeerInfoNamed(SOSAccountRef account, CFStringRef name, CFErrorRef* error) { - if (CFDictionaryGetValue(account->circles, name) == NULL) { - SOSCreateErrorWithFormat(kSOSErrorNoCircle, NULL, error, NULL, CFSTR("No circle named '%@'"), name); - return false; - } - - SOSFullPeerInfoRef circle_full_peer_info = (SOSFullPeerInfoRef) CFDictionaryGetValue(account->circle_identities, name); - - if (circle_full_peer_info) { - SOSPeerPurgeAllFor(SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(circle_full_peer_info))); - - SOSFullPeerInfoPurgePersistentKey(circle_full_peer_info, NULL); - } - - CFDictionaryRemoveValue(account->circle_identities, name); - - return true; -} - -static bool SOSAccountDestroyCirclePeerInfo(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error) { - return SOSAccountDestroyCirclePeerInfoNamed(account, SOSCircleGetName(circle), error); -} - -SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error) { - return SOSAccountGetMyFullPeerInCircleNamed(account, SOSCircleGetName(circle), error); -} - -SOSPeerInfoRef SOSAccountGetMyPeerInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error) { - SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircleNamed(account, SOSCircleGetName(circle), error); - - return fpi ? SOSFullPeerInfoGetPeerInfo(fpi) : NULL; -} - -SOSPeerInfoRef SOSAccountGetMyPeerInCircleNamed(SOSAccountRef account, CFStringRef name, CFErrorRef *error) -{ - SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircleNamed(account, name, error); - - return fpi ? SOSFullPeerInfoGetPeerInfo(fpi) : NULL; -} - -CFArrayRef SOSAccountCopyAccountIdentityPeerInfos(SOSAccountRef account, CFAllocatorRef allocator, CFErrorRef* error) -{ - CFMutableArrayRef result = CFArrayCreateMutableForCFTypes(allocator); - - CFDictionaryForEach(account->circle_identities, ^(const void *key, const void *value) { - SOSFullPeerInfoRef fpi = (SOSFullPeerInfoRef) value; - - CFArrayAppendValue(result, SOSFullPeerInfoGetPeerInfo(fpi)); - }); - - return result; -} - -bool SOSAccountIsAccountIdentity(SOSAccountRef account, SOSPeerInfoRef peer_info, CFErrorRef *error) -{ - __block bool matches = false; - CFDictionaryForEach(account->circle_identities, ^(const void *key, const void *value) { - if (!matches) { - matches = CFEqual(peer_info, SOSFullPeerInfoGetPeerInfo((SOSFullPeerInfoRef) value)); - } - }); - - return matches; -} - -bool SOSAccountSyncWithAllPeers(SOSAccountRef account, CFErrorRef *error) -{ - __block bool result = true; - SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { - if (!SOSAccountSyncWithAllPeersInCircle(account, circle, error)) - result = false; - }); - - return result; -} - -bool SOSAccountSyncWithAllPeersInCircle(SOSAccountRef account, SOSCircleRef circle, - CFErrorRef *error) -{ - SOSPeerInfoRef my_peer = SOSAccountGetMyPeerInCircle(account, circle, error); - if (!my_peer) - return false; - - __block bool didSync = false; - __block bool result = true; - - if (SOSCircleHasPeer(circle, my_peer, NULL)) { - SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { - if (!CFEqual(SOSPeerInfoGetPeerID(my_peer), SOSPeerInfoGetPeerID(peer))) - { - bool local_didSync = false; - if (!SOSAccountSyncWithPeer(account, circle, peer, &local_didSync, error)) - result = false; - if (!didSync && local_didSync) - { - didSync = true; - } - } - }); - - if (didSync) - { - SetCloudKeychainTraceValueForKey(kCloudKeychainNumberOfTimesSyncedWithPeers, 1); - } - } - - return result; -} - -bool SOSAccountSyncWithPeer(SOSAccountRef account, SOSCircleRef circle, - SOSPeerInfoRef thisPeer, bool* didSendData, CFErrorRef* error) -{ - CFStringRef peer_id = SOSPeerInfoGetPeerID(thisPeer); - CFStringRef peer_write_key = SOSMessageKeyCreateWithAccountAndPeer(account, circle, peer_id); - SOSFullPeerInfoRef myRef = SOSAccountGetMyFullPeerInCircle(account, circle, error); - - __block bool sentData = false; - - - SOSPeerSendBlock writeToKVSKey = ^bool (CFDataRef data, CFErrorRef* error) { - secnotice("account", "writing data of size %ld:", data?CFDataGetLength(data):0); - sentData = (NULL != data); - CFDictionaryRef writeToDo = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, peer_write_key, data, NULL); - bool written = account->update_block(writeToDo, error); - if (account->processed_message_block) - account->processed_message_block(circle, NULL, data); - CFRelease(writeToDo); - return written; - }; - - if (NULL != didSendData) - { - *didSendData = sentData; - } - - bool result = SOSCircleSyncWithPeer(myRef, circle, account->factory, writeToKVSKey, peer_id, error); - CFReleaseNull(peer_write_key); - return result; -} - -static bool SOSAccountIsActivePeerInCircleNamed(SOSAccountRef account, CFStringRef circle_name, CFStringRef peerid, CFErrorRef* error) { - SOSCircleRef circle = SOSAccountFindCircle(account, circle_name, error); - if(!circle) return false; - return SOSCircleHasActivePeerWithID(circle, peerid, error); -} - -static bool SOSAccountIsMyPeerActiveInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error) { - SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircleNamedIfPresent(account, SOSCircleGetName(circle), NULL); - if(!fpi) return false; - return SOSCircleHasActivePeer(circle, SOSFullPeerInfoGetPeerInfo(fpi), error); -} - -bool SOSAccountCleanupAfterPeer(SOSAccountRef account, size_t seconds, SOSCircleRef circle, - SOSPeerInfoRef cleanupPeer, CFErrorRef* error) -{ - if(!SOSAccountIsMyPeerActiveInCircle(account, circle, NULL)) return true; - - CFMutableDictionaryRef keysToWrite = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - - SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef circlePeer) { - CFStringRef from_key = SOSMessageKeyCreateWithCircleAndPeerInfos(circle, cleanupPeer, circlePeer); - CFStringRef to_key = SOSMessageKeyCreateWithCircleAndPeerInfos(circle, circlePeer, cleanupPeer); - - CFDictionaryAddValue(keysToWrite, from_key, kCFNull); - CFDictionaryAddValue(keysToWrite, to_key, kCFNull); - - CFReleaseNull(from_key); - CFReleaseNull(to_key); - }); - - if(SOSPeerInfoRetireRetirementTicket(seconds, cleanupPeer)) { - CFStringRef resignationKey = SOSRetirementKeyCreateWithCircleAndPeer(circle, SOSPeerInfoGetPeerID(cleanupPeer)); - CFDictionarySetValue(keysToWrite, resignationKey, kCFNull); - CFDictionaryRemoveValue(account->retired_peers, resignationKey); - CFReleaseNull(resignationKey); - } - - bool success = account->update_block(keysToWrite, error); - - CFReleaseNull(keysToWrite); - - return success; -} - -bool SOSAccountCleanupRetirementTickets(SOSAccountRef account, size_t seconds, CFErrorRef* error) { - CFMutableDictionaryRef keysToWrite = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - - CFDictionaryRef copyToIterate = CFDictionaryCreateCopy(kCFAllocatorDefault, account->retired_peers); - - CFDictionaryForEach(copyToIterate, ^(const void* resignationKey, const void* value) { - CFStringRef circle_name = NULL; - CFStringRef retiree_peerid = NULL; - SOSPeerInfoRef pi = NULL; - SOSKVSKeyType keytype = SOSKVSKeyGetKeyTypeAndParse(resignationKey, &circle_name, &retiree_peerid, NULL); - require_quiet(keytype == kRetirementKey && circle_name && retiree_peerid && isData(value), forget); - pi = SOSPeerInfoCreateFromData(NULL, error, (CFDataRef) value); - require_quiet(pi && CFEqualSafe(retiree_peerid, SOSPeerInfoGetPeerID(pi)), forget); - - require_quiet(!SOSAccountIsActivePeerInCircleNamed(account, circle_name, retiree_peerid, NULL), keep); - require_quiet(SOSPeerInfoRetireRetirementTicket(seconds, pi), keep); - - // Happy day, it's time and it's a ticket we should eradicate from KVS. - CFDictionarySetValue(keysToWrite, resignationKey, kCFNull); - - forget: - CFDictionaryRemoveValue(account->retired_peers, resignationKey); - keep: - CFReleaseSafe(pi); - CFReleaseSafe(circle_name); - CFReleaseSafe(retiree_peerid); - }); - CFReleaseNull(copyToIterate); - - bool success = true; - if(CFDictionaryGetCount(keysToWrite)) { - success = account->update_block(keysToWrite, error); - } - CFReleaseNull(keysToWrite); - - return success; -} - -bool SOSAccountScanForRetired(SOSAccountRef account, SOSCircleRef circle, CFErrorRef *error) { - SOSCircleForEachRetiredPeer(circle, ^(SOSPeerInfoRef peer) { - CFStringRef key = SOSRetirementKeyCreateWithCircleAndPeer(circle, SOSPeerInfoGetPeerID(peer)); - if(key && !CFDictionaryGetValueIfPresent(account->retired_peers, key, NULL)) { - CFDataRef value = SOSPeerInfoCopyEncodedData(peer, NULL, NULL); - if(value) { - CFDictionarySetValue(account->retired_peers, key, value); - SOSAccountCleanupAfterPeer(account, RETIREMENT_FINALIZATION_SECONDS, circle, peer, error); - } - CFReleaseSafe(value); - } - CFReleaseSafe(key); - }); - return true; -} - -SOSCircleRef SOSAccountCloneCircleWithRetirement(SOSAccountRef account, SOSCircleRef starting_circle, CFErrorRef *error) { - CFStringRef circle_to_mod = SOSCircleGetName(starting_circle); - SOSCircleRef new_circle = SOSCircleCopyCircle(NULL, starting_circle, error); - if(!new_circle) return NULL; - - CFDictionaryForEach(account->retired_peers, ^(const void* resignationKey, const void* value) { - CFStringRef circle_name = NULL; - CFStringRef retiree_peerid = NULL; - - SOSKVSKeyType keytype = SOSKVSKeyGetKeyTypeAndParse(resignationKey, &circle_name, &retiree_peerid, NULL); - if(keytype == kRetirementKey && CFEqualSafe(circle_name, circle_to_mod) && SOSCircleHasPeerWithID(new_circle, retiree_peerid, NULL)) { - if(isData(value)) { - SOSPeerInfoRef pi = SOSPeerInfoCreateFromData(NULL, error, (CFDataRef) value); - SOSCircleUpdatePeerInfo(new_circle, pi); - CFReleaseSafe(pi); - } - } - CFReleaseSafe(circle_name); - CFReleaseSafe(retiree_peerid); - }); - - if(SOSCircleCountPeers(new_circle) == 0) { - SOSCircleResetToEmpty(new_circle, NULL); - } - - return new_circle; -} - - -// -// Circle Finding -// -SOSCircleRef SOSAccountFindCompatibleCircle(SOSAccountRef a, CFStringRef name) -{ - CFTypeRef entry = CFDictionaryGetValue(a->circles, name); - - if (CFGetTypeID(entry) == SOSCircleGetTypeID()) - return (SOSCircleRef) entry; - - return NULL; -} - -SOSCircleRef SOSAccountFindCircle(SOSAccountRef a, CFStringRef name, CFErrorRef *error) -{ - CFTypeRef entry = CFDictionaryGetValue(a->circles, name); - - require_action_quiet(!isNull(entry), fail, - SOSCreateError(kSOSErrorIncompatibleCircle, CFSTR("Incompatible circle in KVS"), NULL, error)); - - require_action_quiet(entry, fail, - SOSCreateError(kSOSErrorNoCircle, CFSTR("No circle found"), NULL, error)); - - - return (SOSCircleRef) entry; - -fail: - return NULL; -} - -SOSCircleRef SOSAccountEnsureCircle(SOSAccountRef a, CFStringRef name, CFErrorRef *error) -{ - CFErrorRef localError = NULL; - - SOSCircleRef circle = SOSAccountFindCircle(a, name, &localError); - - require_action_quiet(circle || !isSOSErrorCoded(localError, kSOSErrorIncompatibleCircle), fail, - if (error) { *error = localError; localError = NULL; }); - - - if (NULL == circle) { - circle = SOSCircleCreate(NULL, name, NULL); - if (circle){ - CFDictionaryAddValue(a->circles, name, circle); - CFRelease(circle); - circle = SOSAccountFindCircle(a, name, &localError); - } - SOSUpdateKeyInterest(a, false, NULL); - } - -fail: - CFReleaseNull(localError); - return circle; -} - - -void SOSAccountAddChangeBlock(SOSAccountRef a, SOSAccountCircleMembershipChangeBlock changeBlock) -{ - CFArrayAppendValue(a->change_blocks, changeBlock); -} - -void SOSAccountRemoveChangeBlock(SOSAccountRef a, SOSAccountCircleMembershipChangeBlock changeBlock) -{ - CFArrayRemoveAllValue(a->change_blocks, changeBlock); -} - -static void DifferenceAndCall(CFArrayRef old_members, CFArrayRef new_members, void (^updatedCircle)(CFArrayRef additions, CFArrayRef removals)) -{ - CFMutableArrayRef additions = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, new_members); - CFMutableArrayRef removals = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, old_members); - - - CFArrayForEach(old_members, ^(const void * value) { - CFArrayRemoveAllValue(additions, value); - }); - - CFArrayForEach(new_members, ^(const void * value) { - CFArrayRemoveAllValue(removals, value); - }); - - updatedCircle(additions, removals); - - CFReleaseSafe(additions); - CFReleaseSafe(removals); -} - -static void SOSAccountNotifyOfChange(SOSAccountRef account, SOSCircleRef oldCircle, SOSCircleRef newCircle) -{ - CFMutableArrayRef old_members = SOSCircleCopyPeers(oldCircle, kCFAllocatorDefault); - CFMutableArrayRef new_members = SOSCircleCopyPeers(newCircle, kCFAllocatorDefault); - - CFMutableArrayRef old_applicants = SOSCircleCopyApplicants(oldCircle, kCFAllocatorDefault); - CFMutableArrayRef new_applicants = SOSCircleCopyApplicants(newCircle, kCFAllocatorDefault); - - DifferenceAndCall(old_members, new_members, ^(CFArrayRef added_members, CFArrayRef removed_members) { - DifferenceAndCall(old_applicants, new_applicants, ^(CFArrayRef added_applicants, CFArrayRef removed_applicants) { - CFArrayForEach(account->change_blocks, ^(const void * notificationBlock) { - ((SOSAccountCircleMembershipChangeBlock) notificationBlock)(newCircle, added_members, removed_members, added_applicants, removed_applicants); - }); - }); - }); - - CFReleaseNull(old_applicants); - CFReleaseNull(new_applicants); - - CFReleaseNull(old_members); - CFReleaseNull(new_members); -} - -void SOSAccountForEachCircle(SOSAccountRef account, void (^process)(SOSCircleRef circle)) -{ - CFDictionaryForEach(account->circles, ^(const void* key, const void* value) { - assert(value); - process((SOSCircleRef)value); - }); -} - -static void AppendCircleKeyName(CFMutableArrayRef array, CFStringRef name) { - CFStringRef circle_key = SOSCircleKeyCreateWithName(name, NULL); - CFArrayAppendValue(array, circle_key); - CFReleaseNull(circle_key); -} - -static inline void AppendCircleInterests(CFMutableArrayRef circle_keys, CFMutableArrayRef retiree_keys, CFMutableArrayRef message_keys, SOSCircleRef circle, SOSFullPeerInfoRef me) { - CFStringRef my_peer_id = NULL; - - if (me) { - SOSPeerInfoRef my_peer = me ? SOSFullPeerInfoGetPeerInfo(me) : NULL; - my_peer_id = SOSPeerInfoGetPeerID(my_peer); - } - - if (circle_keys) { - CFStringRef circleName = SOSCircleGetName(circle); - AppendCircleKeyName(circle_keys, circleName); - } - - SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { - if (!CFEqualSafe(my_peer_id, SOSPeerInfoGetPeerID(peer))) { - CFStringRef peer_name = SOSPeerInfoGetPeerID(peer); - if (retiree_keys) { - CFStringRef retirementKey = SOSRetirementKeyCreateWithCircleAndPeer(circle, peer_name); - CFArrayAppendValue(retiree_keys, retirementKey); - CFReleaseNull(retirementKey); - } - - if (my_peer_id && message_keys) { - CFStringRef messageKey = SOSMessageKeyCreateWithCircleAndPeerNames(circle, peer_name, my_peer_id); - CFArrayAppendValue(message_keys, messageKey); - CFRelease(messageKey); - } - } - }); -} - -static void SOSAccountCopyKeyInterests(SOSAccountRef account, - CFMutableArrayRef alwaysKeys, - CFMutableArrayRef afterFirstUnlockKeys, - CFMutableArrayRef whenUnlockedKeys) -{ - CFArrayAppendValue(afterFirstUnlockKeys, kSOSKVSKeyParametersKey); - - SOSAccountForEachKnownCircle(account, ^(CFStringRef name) { - AppendCircleKeyName(afterFirstUnlockKeys, name); - }, ^(SOSCircleRef circle) { - AppendCircleInterests(afterFirstUnlockKeys, afterFirstUnlockKeys, whenUnlockedKeys, circle, NULL); - }, ^(SOSCircleRef circle, SOSFullPeerInfoRef full_peer) { - bool inCircle = SOSCircleHasPeer(circle, SOSFullPeerInfoGetPeerInfo(full_peer), NULL); - - AppendCircleInterests(afterFirstUnlockKeys, afterFirstUnlockKeys, inCircle ? whenUnlockedKeys : NULL, circle, full_peer); - }); -} - -static bool SOSUpdateKeyInterest(SOSAccountRef account, bool getNewKeysOnly, CFErrorRef *error) -{ - if (account->update_interest_block) { - - CFMutableArrayRef alwaysKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - CFMutableArrayRef afterFirstUnlockKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - CFMutableArrayRef whenUnlockedKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - - SOSAccountCopyKeyInterests(account, alwaysKeys, afterFirstUnlockKeys, whenUnlockedKeys); - - account->update_interest_block(getNewKeysOnly, alwaysKeys, afterFirstUnlockKeys, whenUnlockedKeys); - - CFReleaseNull(alwaysKeys); - CFReleaseNull(afterFirstUnlockKeys); - CFReleaseNull(whenUnlockedKeys); - } - - return true; -} - -static bool SOSAccountSendPendingChanges(SOSAccountRef account, CFErrorRef *error) { - CFErrorRef changeError = NULL; - - if (CFDictionaryGetCount(account->pending_changes) == 0) - return true; - - bool success = account->update_block(account->pending_changes, &changeError); - if (success) { - CFDictionaryRemoveAllValues(account->pending_changes); - } else { - SOSCreateErrorWithFormat(kSOSErrorSendFailure, changeError, error, NULL, - CFSTR("Send changes block failed [%@]"), account->pending_changes); - } - - return success; -} - -static bool SOSAccountAddCircleToPending(SOSAccountRef account, SOSCircleRef circle, CFErrorRef *error) -{ - bool success = false; - CFDataRef circle_data = SOSCircleCopyEncodedData(circle, kCFAllocatorDefault, error); - - if (circle_data) { - CFStringRef circle_key = SOSCircleKeyCreateWithCircle(circle, NULL); - - CFDictionarySetValue(account->pending_changes, circle_key, circle_data); - success = true; - - CFReleaseNull(circle_data); - CFReleaseNull(circle_key); - } - - return success; -} - - -static void SOSAccountRecordRetiredPeerInCircleNamed(SOSAccountRef account, CFStringRef circleName, SOSPeerInfoRef retiree) -{ - // Replace Peer with RetiredPeer, if were a peer. - SOSAccountModifyCircle(account, circleName, NULL, ^(SOSCircleRef circle) { - if (SOSCircleUpdatePeerInfo(circle, retiree)) { - CFErrorRef cleanupError = NULL; - SOSAccountCleanupAfterPeer(account, RETIREMENT_FINALIZATION_SECONDS, circle, retiree, &cleanupError); - secerror("Error cleanup up after peer (%@): %@", retiree, cleanupError); - CFReleaseSafe(cleanupError); - } - }); -} - -static bool sosAccountLeaveCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error) { - SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircle(account, circle, NULL); - if(!fpi) return false; - CFErrorRef localError = NULL; - SOSPeerInfoRef retire_peer = SOSFullPeerInfoPromoteToRetiredAndCopy(fpi, &localError);; - CFStringRef retire_key = SOSRetirementKeyCreateWithCircleAndPeer(circle, SOSPeerInfoGetPeerID(retire_peer)); - CFDataRef retire_value = NULL; - bool retval = false; - bool writeCircle = false; - - // Create a Retirement Ticket and store it in the retired_peers of the account. - require_action_quiet(retire_peer, errout, secerror("Create ticket failed for peer %@: %@", fpi, localError)); - retire_value = SOSPeerInfoCopyEncodedData(retire_peer, NULL, &localError); - require_action_quiet(retire_value, errout, secerror("Failed to encode retirement peer %@: %@", retire_peer, localError)); - - // See if we need to repost the circle we could either be an applicant or a peer already in the circle - if(SOSCircleHasApplicant(circle, retire_peer, NULL)) { - // Remove our application if we have one. - SOSCircleWithdrawRequest(circle, retire_peer, NULL); - writeCircle = true; - } else if (SOSCircleHasPeer(circle, retire_peer, NULL)) { - if (SOSCircleUpdatePeerInfo(circle, retire_peer)) { - CFErrorRef cleanupError = NULL; - SOSAccountCleanupAfterPeer(account, RETIREMENT_FINALIZATION_SECONDS, circle, retire_peer, &cleanupError); - secerror("Error cleanup up after peer (%@): %@", retire_peer, cleanupError); - CFReleaseSafe(cleanupError); - } - writeCircle = true; - } - - // Store the retirement record locally. - CFDictionarySetValue(account->retired_peers, retire_key, retire_value); - - // Write pending change to KVS - CFDictionarySetValue(account->pending_changes, retire_key, retire_value); - - // Kill peer key but don't return error if we can't. - if(!SOSAccountDestroyCirclePeerInfo(account, circle, &localError)) - secerror("Couldn't purge key for peer %@ on retirement: %@", fpi, localError); - - if (writeCircle) { - SOSAccountAddCircleToPending(account, circle, NULL); - } - retval = true; - -errout: - CFReleaseNull(localError); - CFReleaseNull(retire_peer); - CFReleaseNull(retire_key); - CFReleaseNull(retire_value); - return retval; -} - -/* - NSUbiquitousKeyValueStoreInitialSyncChange is only posted if there is any - local value that has been overwritten by a distant value. If there is no - conflict between the local and the distant values when doing the initial - sync (e.g. if the cloud has no data stored or the client has not stored - any data yet), you'll never see that notification. - - NSUbiquitousKeyValueStoreInitialSyncChange implies an initial round trip - with server but initial round trip with server does not imply - NSUbiquitousKeyValueStoreInitialSyncChange. - */ - -// -// MARK: Handle Circle Updates -// - - -static bool SOSAccountHandleUpdateCircle(SOSAccountRef account, SOSCircleRef prospective_circle, bool writeUpdate, bool initialSync, CFErrorRef *error) -{ - bool success = true; - - secnotice("signing", "start: %@", prospective_circle); - if (!account->user_public || !account->user_public_trusted) { - SOSCreateError(kSOSErrorPublicKeyAbsent, CFSTR("Can't handle updates with no trusted public key here"), NULL, error); - return false; - } - - if (!prospective_circle) { - secerror("##### Can't update to a NULL circle ######"); - return false; // Can't update one we don't have. - } - - CFStringRef newCircleName = SOSCircleGetName(prospective_circle); - SOSCircleRef oldCircle = SOSAccountFindCompatibleCircle(account, newCircleName); - SOSFullPeerInfoRef me_full = SOSAccountGetMyFullPeerInCircle(account, oldCircle, NULL); - SOSPeerInfoRef me = SOSFullPeerInfoGetPeerInfo(me_full); - - if (initialSync) - secerror("##### Processing initial sync. Old (local) circle: %@, New (cloud) circle: %@", oldCircle, prospective_circle); - - if (!oldCircle) - return false; // Can't update one we don't have. - - SOSAccountScanForRetired(account, prospective_circle, error); - SOSCircleRef newCircle = SOSAccountCloneCircleWithRetirement(account, prospective_circle, error); - if(!newCircle) return false; - - SOSCircleUpdatePeerInfo(newCircle, me); - - typedef enum { - accept, - countersign, - leave, - revert, - ignore - } circle_action_t; - - circle_action_t circle_action = ignore; - enum DepartureReason leave_reason = kSOSNeverLeftCircle; - - SecKeyRef old_circle_key = NULL; - if(SOSCircleVerify(oldCircle, account->user_public, NULL)) old_circle_key = account->user_public; - else if(account->previous_public && SOSCircleVerify(oldCircle, account->previous_public, NULL)) old_circle_key = account->previous_public; - bool userTrustedOldCircle = (old_circle_key != NULL); - - SOSConcordanceStatus concstat = - SOSCircleConcordanceTrust(oldCircle, newCircle, - old_circle_key, account->user_public, - me, error); - - CFStringRef concStr = NULL; - switch(concstat) { - case kSOSConcordanceTrusted: - circle_action = countersign; - concStr = CFSTR("Trusted"); - break; - case kSOSConcordanceGenOld: - circle_action = userTrustedOldCircle ? revert : ignore; - concStr = CFSTR("Generation Old"); - break; - case kSOSConcordanceBadUserSig: - case kSOSConcordanceBadPeerSig: - circle_action = userTrustedOldCircle ? revert : accept; - concStr = CFSTR("Bad Signature"); - break; - case kSOSConcordanceNoUserSig: - circle_action = userTrustedOldCircle ? revert : accept; - concStr = CFSTR("No User Signature"); - break; - case kSOSConcordanceNoPeerSig: - circle_action = accept; // We might like this one eventually but don't countersign. - concStr = CFSTR("No trusted peer signature"); - secerror("##### No trusted peer signature found, accepting hoping for concordance later %@", newCircle); - break; - case kSOSConcordanceNoPeer: - circle_action = leave; - leave_reason = kSOSLeftUntrustedCircle; - concStr = CFSTR("No trusted peer left"); - break; - case kSOSConcordanceNoUserKey: - secerror("##### No User Public Key Available, this shouldn't ever happen!!!"); - abort(); - break; - default: - secerror("##### Bad Error Return from ConcordanceTrust"); - abort(); - break; - } - - secnotice("signing", "Decided on action %d based on concordance state %d and %s circle.", circle_action, concstat, userTrustedOldCircle ? "trusted" : "untrusted"); - - SOSCircleRef circleToPush = NULL; - - if (circle_action == leave) { - circle_action = ignore; - - if (me && SOSCircleHasPeer(oldCircle, me, NULL)) { - if (sosAccountLeaveCircle(account, newCircle, error)) { - account->departure_code = leave_reason; - circleToPush = newCircle; - circle_action = accept; - me = NULL; - me_full = NULL; - } - } - else { - // We are not in this circle, but we need to update account with it, since we got it from cloud - secnotice("updatecircle", "We are not in this circle, but we need to update account with it"); - circle_action = accept; - } - } - - if (circle_action == countersign) { - if (me && SOSCircleHasPeer(newCircle, me, NULL) && !SOSCircleVerifyPeerSigned(newCircle, me, NULL)) { - CFErrorRef signing_error = NULL; - - if (me_full && SOSCircleConcordanceSign(newCircle, me_full, &signing_error)) { - circleToPush = newCircle; - secnotice("signing", "Concurred with: %@", newCircle); - } else { - secerror("Failed to concurrence sign, error: %@ Old: %@ New: %@", signing_error, oldCircle, newCircle); - } - CFReleaseSafe(signing_error); - } - circle_action = accept; - } - - if (circle_action == accept) { - if (me && SOSCircleHasActivePeer(oldCircle, me, NULL) && !SOSCircleHasPeer(newCircle, me, NULL)) { - // Don't destroy evidence of other code determining reason for leaving. - if(!SOSAccountHasLeft(account)) account->departure_code = kSOSMembershipRevoked; - } - - if (me - && SOSCircleHasActivePeer(oldCircle, me, NULL) - && !(SOSCircleCountPeers(oldCircle) == 1 && SOSCircleHasPeer(oldCircle, me, NULL)) // If it was our offering, don't change ID to avoid ghosts - && !SOSCircleHasPeer(newCircle, me, NULL) && !SOSCircleHasApplicant(newCircle, me, NULL)) { - secnotice("circle", "Purging my peer (ID: %@) for circle '%@'!!!", SOSPeerInfoGetPeerID(me), SOSCircleGetName(oldCircle)); - SOSAccountDestroyCirclePeerInfo(account, oldCircle, NULL); - me = NULL; - me_full = NULL; - } - - if (me && SOSCircleHasRejectedApplicant(newCircle, me, NULL)) { - SOSPeerInfoRef reject = SOSCircleCopyRejectedApplicant(newCircle, me, NULL); - if(CFEqualSafe(reject, me) && SOSPeerInfoApplicationVerify(me, account->user_public, NULL)) { - secnotice("circle", "Rejected, Purging my applicant peer (ID: %@) for circle '%@'", SOSPeerInfoGetPeerID(me), SOSCircleGetName(oldCircle)); - SOSAccountDestroyCirclePeerInfo(account, oldCircle, NULL); - me = NULL; - me_full = NULL; - } else { - SOSCircleRequestReadmission(newCircle, account->user_public, me_full, NULL); - writeUpdate = true; - } - } - - CFRetain(oldCircle); // About to replace the oldCircle - CFDictionarySetValue(account->circles, newCircleName, newCircle); - SOSAccountSetPreviousPublic(account); - - secnotice("signing", "%@, Accepting circle: %@", concStr, newCircle); - - if (me_full && account->user_public_trusted - && SOSCircleHasApplicant(oldCircle, me, NULL) - && SOSCircleCountPeers(newCircle) > 0 - && !SOSCircleHasPeer(newCircle, me, NULL) && !SOSCircleHasApplicant(newCircle, me, NULL)) { - // We weren't rejected (above would have set me to NULL. - // We were applying and we weren't accepted. - // Our application is declared lost, let us reapply. - - if (SOSCircleRequestReadmission(newCircle, account->user_public, me_full, NULL)) - writeUpdate = true; - } - - if (me && SOSCircleHasActivePeer(oldCircle, me, NULL)) { - SOSAccountCleanupRetirementTickets(account, RETIREMENT_FINALIZATION_SECONDS, NULL); - } - - SOSAccountNotifyOfChange(account, oldCircle, newCircle); - - CFReleaseNull(oldCircle); - - if (writeUpdate) - circleToPush = newCircle; - - success = SOSUpdateKeyInterest(account, true, error); - } - - if (circle_action == revert) { - secnotice("signing", "%@, Rejecting: %@ re-publishing %@", concStr, newCircle, oldCircle); - - circleToPush = oldCircle; - } - - - if (circleToPush != NULL) { - success = (success - && SOSAccountAddCircleToPending(account, circleToPush, error) - && SOSAccountSendPendingChanges(account, error)); - } - - CFReleaseSafe(newCircle); - - return success; -} - -static bool SOSAccountUpdateCircleFromRemote(SOSAccountRef account, SOSCircleRef newCircle, bool initialSync, CFErrorRef *error) -{ - return SOSAccountHandleUpdateCircle(account, newCircle, false, initialSync, error); -} - -bool SOSAccountUpdateCircle(SOSAccountRef account, SOSCircleRef newCircle, CFErrorRef *error) -{ - return SOSAccountHandleUpdateCircle(account, newCircle, true, false, error); -} - -bool SOSAccountModifyCircle(SOSAccountRef account, - CFStringRef circleName, - CFErrorRef* error, - void (^action)(SOSCircleRef circle)) -{ - bool success = false; - - SOSCircleRef circle = NULL; - SOSCircleRef accountCircle = SOSAccountFindCircle(account, circleName, error); - require_quiet(accountCircle, fail); - - circle = SOSCircleCopyCircle(kCFAllocatorDefault, accountCircle, error); - require_quiet(circle, fail); - - action(circle); - success = SOSAccountUpdateCircle(account, circle, error); - -fail: - CFReleaseSafe(circle); - return success; -} - -static SOSCircleRef SOSAccountCreateCircleFrom(CFStringRef circleName, CFTypeRef value, CFErrorRef *error) { - if (value && !isData(value) && !isNull(value)) { - CFStringRef description = CFCopyTypeIDDescription(CFGetTypeID(value)); - SOSCreateErrorWithFormat(kSOSErrorUnexpectedType, NULL, error, NULL, - CFSTR("Expected data or NULL got %@"), description); - CFReleaseSafe(description); - return NULL; - } - - SOSCircleRef circle = NULL; - if (!value || isNull(value)) { - circle = SOSCircleCreate(kCFAllocatorDefault, circleName, error); - } else { - circle = SOSCircleCreateFromData(NULL, (CFDataRef) value, error); - if (circle) { - CFStringRef name = SOSCircleGetName(circle); - if (!CFEqualSafe(name, circleName)) { - SOSCreateErrorWithFormat(kSOSErrorNameMismatch, NULL, error, NULL, - CFSTR("Expected circle named %@, got %@"), circleName, name); - CFReleaseNull(circle); - } - } - } - return circle; -} - -static SOSCCStatus SOSCCCircleStatus(SOSCircleRef circle) -{ - if (SOSCircleCountPeers(circle) == 0) - return kSOSCCCircleAbsent; - - return kSOSCCNotInCircle; -} - -static SOSCCStatus SOSCCThisDeviceStatusInCircle(SOSCircleRef circle, SOSPeerInfoRef this_peer) -{ - if (SOSCircleCountPeers(circle) == 0) - return kSOSCCCircleAbsent; - - if (SOSCircleHasPeer(circle, this_peer, NULL)) - return kSOSCCInCircle; - - if (SOSCircleHasApplicant(circle, this_peer, NULL)) - return kSOSCCRequestPending; - - return kSOSCCNotInCircle; -} - -static SOSCCStatus UnionStatus(SOSCCStatus accumulated_status, SOSCCStatus additional_circle_status) -{ - switch (additional_circle_status) { - case kSOSCCInCircle: - return accumulated_status; - case kSOSCCRequestPending: - return (accumulated_status == kSOSCCInCircle) ? - kSOSCCRequestPending : - accumulated_status; - case kSOSCCNotInCircle: - return (accumulated_status == kSOSCCInCircle || - accumulated_status == kSOSCCRequestPending) ? - kSOSCCNotInCircle : - accumulated_status; - case kSOSCCCircleAbsent: - return (accumulated_status == kSOSCCInCircle || - accumulated_status == kSOSCCRequestPending || - accumulated_status == kSOSCCNotInCircle) ? - kSOSCCCircleAbsent : - accumulated_status; - default: - return additional_circle_status; - }; - -} - -SOSCCStatus SOSAccountIsInCircles(SOSAccountRef account, CFErrorRef* error) -{ - if (!SOSAccountHasPublicKey(account, error)) { - return kSOSCCError; - } - - __block bool set_once = false; - __block SOSCCStatus status = kSOSCCInCircle; - - SOSAccountForEachKnownCircle(account, ^(CFStringRef name) { - set_once = true; - status = kSOSCCError; - SOSCreateError(kSOSErrorIncompatibleCircle, CFSTR("Incompatible circle"), NULL, error); - }, ^(SOSCircleRef circle) { - set_once = true; - status = UnionStatus(status, SOSCCCircleStatus(circle)); - }, ^(SOSCircleRef circle, SOSFullPeerInfoRef full_peer) { - set_once = true; - SOSCCStatus circle_status = SOSCCThisDeviceStatusInCircle(circle, SOSFullPeerInfoGetPeerInfo(full_peer)); - status = UnionStatus(status, circle_status); - }); - - if (!set_once) - status = kSOSCCCircleAbsent; - - return status; -} - -static SOSPeerInfoRef GenerateNewCloudIdentityPeerInfo(CFErrorRef *error) { - SecKeyRef cloud_key = GeneratePermanentFullECKeyForCloudIdentity(256, kicloud_identity_name, error); - SOSPeerInfoRef cloud_peer = NULL; - CFDictionaryRef query = NULL; - CFDictionaryRef change = NULL; - CFStringRef new_name = NULL; - - CFDictionaryRef gestalt = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, - kPIUserDefinedDeviceName, CFSTR("iCloud"), - NULL); - require_action_quiet(gestalt, fail, SecError(errSecAllocate, error, CFSTR("Can't allocate gestalt"))); - - cloud_peer = SOSPeerInfoCreateCloudIdentity(kCFAllocatorDefault, gestalt, cloud_key, error); - - require(cloud_peer, fail); - - query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, - kSecClass, kSecClassKey, - kSecAttrSynchronizable,kCFBooleanTrue, - kSecUseTombstones, kCFBooleanTrue, - kSecValueRef, cloud_key, - NULL); - - new_name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, - CFSTR("Cloud Identity - '%@'"), SOSPeerInfoGetPeerID(cloud_peer)); - - change = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, - kSecAttrLabel, new_name, - NULL); - - SecError(SecItemUpdate(query, change), error, CFSTR("Couldn't update name")); - -fail: - CFReleaseNull(new_name); - CFReleaseNull(query); - CFReleaseNull(change); - CFReleaseNull(gestalt); - CFReleaseNull(cloud_key); - - return cloud_peer; -} - -static SOSFullPeerInfoRef CopyCloudKeychainIdentity(SOSPeerInfoRef cloudPeer, CFErrorRef *error) { - return SOSFullPeerInfoCreateCloudIdentity(NULL, cloudPeer, error); -} - -static bool SOSAccountResetThisCircleToOffering(SOSAccountRef account, SOSCircleRef circle, SecKeyRef user_key, CFErrorRef *error) { - SOSFullPeerInfoRef myCirclePeer = SOSAccountGetMyFullPeerInCircle(account, circle, error); - if (!myCirclePeer) - return false; - - SOSAccountModifyCircle(account, SOSCircleGetName(circle), error, ^(SOSCircleRef circle) { - bool result = false; - SOSFullPeerInfoRef cloud_identity = NULL; - CFErrorRef localError = NULL; - - require_quiet(SOSCircleResetToOffering(circle, user_key, myCirclePeer, &localError), err_out); - - { - SOSPeerInfoRef cloud_peer = GenerateNewCloudIdentityPeerInfo(error); - require_quiet(cloud_peer, err_out); - cloud_identity = CopyCloudKeychainIdentity(cloud_peer, error); - require_quiet(cloud_identity, err_out); - } - - account->departure_code = kSOSNeverLeftCircle; - require_quiet(SOSCircleRequestAdmission(circle, user_key, cloud_identity, &localError), err_out); - require_quiet(SOSCircleAcceptRequest(circle, user_key, myCirclePeer, SOSFullPeerInfoGetPeerInfo(cloud_identity), &localError), err_out); - result = true; - SOSAccountPublishCloudParameters(account, 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); - CFReleaseNull(cloud_identity); - }); - - return true; -} - -static bool SOSAccountJoinThisCircle(SOSAccountRef account, SecKeyRef user_key, - SOSCircleRef circle, bool use_cloud_peer, CFErrorRef* error) { - __block bool result = false; - __block SOSFullPeerInfoRef cloud_full_peer = NULL; - - SOSFullPeerInfoRef myCirclePeer = SOSAccountGetMyFullPeerInCircle(account, circle, error); - require_action_quiet(myCirclePeer, fail, - SOSCreateErrorWithFormat(kSOSErrorPeerNotFound, NULL, error, NULL, CFSTR("Can't find/create peer for circle: %@"), circle)); - if (use_cloud_peer) { - cloud_full_peer = SOSCircleGetiCloudFullPeerInfoRef(circle); - } - - if (SOSCircleCountPeers(circle) == 0) { - result = SOSAccountResetThisCircleToOffering(account, circle, user_key, error); - } else { - SOSAccountModifyCircle(account, SOSCircleGetName(circle), error, ^(SOSCircleRef circle) { - result = SOSCircleRequestAdmission(circle, user_key, myCirclePeer, error); - account->departure_code = kSOSNeverLeftCircle; - if(result && cloud_full_peer) { - CFErrorRef localError = NULL; - CFStringRef cloudid = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(cloud_full_peer)); - require_quiet(cloudid, finish); - require_quiet(SOSCircleHasActivePeerWithID(circle, cloudid, &localError), finish); - require_quiet(SOSCircleAcceptRequest(circle, user_key, cloud_full_peer, SOSFullPeerInfoGetPeerInfo(myCirclePeer), &localError), finish); - finish: - if (localError){ - secerror("Failed to join with cloud identity: %@", localError); - CFReleaseNull(localError); - } - } - }); - } - -fail: - CFReleaseNull(cloud_full_peer); - return result; -} - -static bool SOSAccountJoinCircles_internal(SOSAccountRef account, bool use_cloud_identity, CFErrorRef* error) { - SecKeyRef user_key = SOSAccountGetPrivateCredential(account, error); - if (!user_key) - return false; - - __block bool success = true; - - SOSAccountForEachKnownCircle(account, ^(CFStringRef name) { // Incompatible - success = false; - SOSCreateError(kSOSErrorIncompatibleCircle, CFSTR("Incompatible circle"), NULL, error); - }, ^(SOSCircleRef circle) { // No Peer - success = SOSAccountJoinThisCircle(account, user_key, circle, use_cloud_identity, error) && success; - }, ^(SOSCircleRef circle, SOSFullPeerInfoRef full_peer) { // Have Peer - SOSPeerInfoRef myPeer = SOSFullPeerInfoGetPeerInfo(full_peer); - if(SOSCircleHasPeer(circle, myPeer, NULL)) goto already_present; - if(SOSCircleHasApplicant(circle, myPeer, NULL)) goto already_applied; - if(SOSCircleHasRejectedApplicant(circle, myPeer, NULL)) { - SOSCircleRemoveRejectedPeer(circle, myPeer, NULL); - } - - secerror("Resetting my peer (ID: %@) for circle '%@' during application", SOSPeerInfoGetPeerID(myPeer), SOSCircleGetName(circle)); - CFErrorRef localError = NULL; - if (!SOSAccountDestroyCirclePeerInfo(account, circle, &localError)) { - secerror("Failed to destroy peer (%@) during application, error=%@", myPeer, localError); - CFReleaseNull(localError); - } - already_applied: - success = SOSAccountJoinThisCircle(account, user_key, circle, use_cloud_identity, error) && success; - return; - already_present: - success = true; - return; - }); - - if(success) account->departure_code = kSOSNeverLeftCircle; - - return success; -} - -bool SOSAccountJoinCircles(SOSAccountRef account, CFErrorRef* error) { - return SOSAccountJoinCircles_internal(account, false, error); -} - - -bool SOSAccountJoinCirclesAfterRestore(SOSAccountRef account, CFErrorRef* error) { - return SOSAccountJoinCircles_internal(account, true, error); -} - - -bool SOSAccountLeaveCircles(SOSAccountRef account, CFErrorRef* error) -{ - __block bool result = true; - - SOSAccountForEachKnownCircle(account, NULL, NULL, ^(SOSCircleRef circle, SOSFullPeerInfoRef myCirclePeer) { - SOSAccountModifyCircle(account, SOSCircleGetName(circle), error, ^(SOSCircleRef circle) { - result = sosAccountLeaveCircle(account, circle, error); // TODO: What about multiple errors! - }); - }); - - account->departure_code = kSOSWithdrewMembership; - - return SOSAccountSendPendingChanges(account, error) && result; -} - -bool SOSAccountBail(SOSAccountRef account, uint64_t limit_in_seconds, CFErrorRef* error) -{ - dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - dispatch_group_t group = dispatch_group_create(); - __block bool result = false; - - secnotice("circle", "Attempting to leave circle - best effort - in %llu seconds\n", limit_in_seconds); - // Add a task to the group - dispatch_group_async(group, queue, ^{ - SOSAccountForEachKnownCircle(account, NULL, NULL, ^(SOSCircleRef circle, SOSFullPeerInfoRef myCirclePeer) { - SOSAccountModifyCircle(account, SOSCircleGetName(circle), error, ^(SOSCircleRef circle) { - result = sosAccountLeaveCircle(account, circle, error); // TODO: What about multiple errors! - }); - }); - - account->departure_code = kSOSWithdrewMembership; - if(result) result = SOSAccountSendPendingChanges(account, error); - }); - dispatch_time_t milestone = dispatch_time(DISPATCH_TIME_NOW, limit_in_seconds * NSEC_PER_SEC); - - dispatch_group_wait(group, milestone); - dispatch_release(group); - return result; -} - - -static void for_each_applicant_in_each_circle(SOSAccountRef account, CFArrayRef peer_infos, - void (^action)(SOSCircleRef circle, SOSFullPeerInfoRef myCirclePeer, SOSPeerInfoRef peer)) { - SOSAccountForEachKnownCircle(account, NULL, NULL, ^(SOSCircleRef circle, SOSFullPeerInfoRef full_peer) { - SOSPeerInfoRef me = SOSFullPeerInfoGetPeerInfo(full_peer); - CFErrorRef peer_error = NULL; - if (SOSCircleHasPeer(circle, me, &peer_error)) { - CFArrayForEach(peer_infos, ^(const void *value) { - SOSPeerInfoRef peer = (SOSPeerInfoRef) value; - if (SOSCircleHasApplicant(circle, peer, NULL)) { - SOSAccountModifyCircle(account, SOSCircleGetName(circle), NULL, ^(SOSCircleRef circle) { - action(circle, full_peer, peer); - }); - } - }); - } - if (peer_error) - secerror("Got error in SOSCircleHasPeer: %@", peer_error); - CFReleaseSafe(peer_error); // TODO: We should be accumulating errors here. - }); -} - -bool SOSAccountAcceptApplicants(SOSAccountRef account, CFArrayRef applicants, CFErrorRef* error) { - SecKeyRef user_key = SOSAccountGetPrivateCredential(account, error); - if (!user_key) - return false; - - __block bool success = true; - __block int64_t num_peers = 0; - - for_each_applicant_in_each_circle(account, applicants, ^(SOSCircleRef circle, SOSFullPeerInfoRef myCirclePeer, SOSPeerInfoRef peer) { - if (!SOSCircleAcceptRequest(circle, user_key, myCirclePeer, peer, error)) - success = false; - else - num_peers = MAX(num_peers, SOSCircleCountPeers(circle)); - }); - - return success; -} - -bool SOSAccountRejectApplicants(SOSAccountRef account, CFArrayRef applicants, CFErrorRef* error) { - __block bool success = true; - __block int64_t num_peers = 0; - - for_each_applicant_in_each_circle(account, applicants, ^(SOSCircleRef circle, SOSFullPeerInfoRef myCirclePeer, SOSPeerInfoRef peer) { - if (!SOSCircleRejectRequest(circle, myCirclePeer, peer, error)) - success = false; - else - num_peers = MAX(num_peers, SOSCircleCountPeers(circle)); - }); - - return success; -} - -bool SOSAccountResetToOffering(SOSAccountRef account, CFErrorRef* error) { - SecKeyRef user_key = SOSAccountGetPrivateCredential(account, error); - if (!user_key) - return false; - - __block bool result = true; - - SOSAccountForEachKnownCircle(account, ^(CFStringRef name) { - SOSCircleRef circle = SOSCircleCreate(NULL, name, NULL); - if (circle) - CFDictionaryAddValue(account->circles, name, circle); - - SOSAccountResetThisCircleToOffering(account, circle, user_key, error); - }, ^(SOSCircleRef circle) { - SOSAccountResetThisCircleToOffering(account, circle, user_key, error); - }, ^(SOSCircleRef circle, SOSFullPeerInfoRef full_peer) { - SOSAccountResetThisCircleToOffering(account, circle, user_key, error); - }); - - return result; -} - -bool SOSAccountResetToEmpty(SOSAccountRef account, CFErrorRef* error) { - if (!SOSAccountHasPublicKey(account, error)) - return false; - - __block bool result = true; - SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { - SOSAccountModifyCircle(account, SOSCircleGetName(circle), error, ^(SOSCircleRef circle) { - if (!SOSCircleResetToEmpty(circle, error)) - { - secerror("error: %@", *error); - result = false; - } - account->departure_code = kSOSWithdrewMembership; - }); - }); - - return result; -} - -CFArrayRef SOSAccountCopyApplicants(SOSAccountRef account, CFErrorRef *error) { - if (!SOSAccountHasPublicKey(account, error)) - return NULL; - CFMutableArrayRef applicants = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - - SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { - SOSCircleForEachApplicant(circle, ^(SOSPeerInfoRef peer) { - CFArrayAppendValue(applicants, peer); - }); - }); - - return applicants; -} - -CFArrayRef SOSAccountCopyPeers(SOSAccountRef account, CFErrorRef *error) { - if (!SOSAccountHasPublicKey(account, error)) - return NULL; - - CFMutableArrayRef peers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - - SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { - SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { - CFArrayAppendValue(peers, peer); - }); - }); - - return peers; -} - -CFArrayRef SOSAccountCopyActivePeers(SOSAccountRef account, CFErrorRef *error) { - if (!SOSAccountHasPublicKey(account, error)) - return NULL; - - CFMutableArrayRef peers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - - SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { - SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { - CFArrayAppendValue(peers, peer); - }); - }); - - return peers; -} - -CFArrayRef SOSAccountCopyActiveValidPeers(SOSAccountRef account, CFErrorRef *error) { - if (!SOSAccountHasPublicKey(account, error)) - return NULL; - - CFMutableArrayRef peers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - - SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { - SOSCircleForEachActiveValidPeer(circle, account->user_public, ^(SOSPeerInfoRef peer) { - CFArrayAppendValue(peers, peer); - }); - }); - - return peers; -} - - -CFArrayRef SOSAccountCopyConcurringPeers(SOSAccountRef account, CFErrorRef *error) -{ - if (!SOSAccountHasPublicKey(account, error)) - return NULL; - - CFMutableArrayRef concurringPeers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - - SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { - CFMutableArrayRef circleConcurring = SOSCircleCopyConcurringPeers(circle, NULL); - CFArrayAppendArray(concurringPeers, circleConcurring, CFRangeMake(0, CFArrayGetCount(circleConcurring))); - CFReleaseSafe(circleConcurring); - }); - - return concurringPeers; -} - -CFStringRef SOSAccountCopyIncompatibilityInfo(SOSAccountRef account, CFErrorRef* error) -{ - return CFSTR("We're compatible, go away"); -} - -enum DepartureReason SOSAccountGetLastDepartureReason(SOSAccountRef account, CFErrorRef* error) -{ - return account->departure_code; -} - -// -// TODO: Handle '|' and "¬" in other strings. -// -const CFStringRef kSOSKVSKeyParametersKey = CFSTR(">KeyParameters"); -const CFStringRef kSOSKVSInitialSyncKey = CFSTR("^InitialSync"); -const CFStringRef kSOSKVSAccountChangedKey = CFSTR("^AccountChanged"); - -const CFStringRef sWarningPrefix = CFSTR("!"); -const CFStringRef sAncientCirclePrefix = CFSTR("@"); -const CFStringRef sCirclePrefix = CFSTR("o"); -const CFStringRef sRetirementPrefix = CFSTR("-"); -const CFStringRef sCircleSeparator = CFSTR("|"); -const CFStringRef sFromToSeparator = CFSTR(":"); - -static CFStringRef stringEndingIn(CFMutableStringRef in, CFStringRef token) { - if(token == NULL) return CFStringCreateCopy(NULL, in); - CFRange tokenAt = CFStringFind(in, token, 0); - if(tokenAt.location == kCFNotFound) return NULL; - CFStringRef retval = CFStringCreateWithSubstring(NULL, in, CFRangeMake(0, tokenAt.location)); - CFStringDelete(in, CFRangeMake(0, tokenAt.location+1)); - return retval; -} - -SOSKVSKeyType SOSKVSKeyGetKeyTypeAndParse(CFStringRef key, CFStringRef *circle, CFStringRef *from, CFStringRef *to) -{ - SOSKVSKeyType retval = kUnknownKey; - - if(CFStringHasPrefix(key, sCirclePrefix)) retval = kCircleKey; - else if(CFStringHasPrefix(key, sRetirementPrefix)) retval = kRetirementKey; - else if(CFStringHasPrefix(key, kSOSKVSKeyParametersKey)) retval = kParametersKey; - else if(CFStringHasPrefix(key, kSOSKVSInitialSyncKey)) retval = kInitialSyncKey; - else if(CFStringHasPrefix(key, kSOSKVSAccountChangedKey)) retval = kAccountChangedKey; - else retval = kMessageKey; - - switch(retval) { - case kCircleKey: - if (circle) { - CFRange fromRange = CFRangeMake(1, CFStringGetLength(key)-1); - *circle = CFStringCreateWithSubstring(NULL, key, fromRange); - } - break; - case kMessageKey: { - CFStringRef mCircle = NULL; - CFStringRef mFrom = NULL; - CFStringRef mTo = NULL; - CFMutableStringRef keycopy = CFStringCreateMutableCopy(NULL, 128, key); - - if( ((mCircle = stringEndingIn(keycopy, sCircleSeparator)) != NULL) && - ((mFrom = stringEndingIn(keycopy, sFromToSeparator)) != NULL) && - (CFStringGetLength(mFrom) > 0) ) { - mTo = stringEndingIn(keycopy, NULL); - if (circle) *circle = CFStringCreateCopy(NULL, mCircle); - if (from) *from = CFStringCreateCopy(NULL, mFrom); - if (to && mTo) *to = CFStringCreateCopy(NULL, mTo); - } else { - retval = kUnknownKey; - } - CFReleaseNull(mCircle); - CFReleaseNull(mFrom); - CFReleaseNull(mTo); - CFReleaseNull(keycopy); - } - break; - case kRetirementKey: { - CFStringRef mCircle = NULL; - CFStringRef mPeer = NULL; - CFMutableStringRef keycopy = CFStringCreateMutableCopy(NULL, 128, key); - CFStringDelete(keycopy, CFRangeMake(0, 1)); - if( ((mCircle = stringEndingIn(keycopy, sCircleSeparator)) != NULL) && - ((mPeer = stringEndingIn(keycopy, NULL)) != NULL)) { - if (circle) *circle = CFStringCreateCopy(NULL, mCircle); - if (from) *from = CFStringCreateCopy(NULL, mPeer); - } else { - retval = kUnknownKey; - } - // TODO - Update our circle - CFReleaseNull(mCircle); - CFReleaseNull(mPeer); - CFReleaseNull(keycopy); - } - break; - case kAccountChangedKey: - case kParametersKey: - case kInitialSyncKey: - case kUnknownKey: - break; - } - - return retval; -} - - -SOSKVSKeyType SOSKVSKeyGetKeyType(CFStringRef key) -{ - return SOSKVSKeyGetKeyTypeAndParse(key, NULL, NULL, NULL); -} - -CFStringRef SOSCircleKeyCreateWithCircle(SOSCircleRef circle, CFErrorRef *error) -{ - return SOSCircleKeyCreateWithName(SOSCircleGetName(circle), error); -} - - -CFStringRef SOSCircleKeyCreateWithName(CFStringRef circleName, CFErrorRef *error) -{ - return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), sCirclePrefix, circleName); -} - -CFStringRef SOSCircleKeyCopyCircleName(CFStringRef key, CFErrorRef *error) -{ - CFStringRef circleName = NULL; - - if (kCircleKey != SOSKVSKeyGetKeyTypeAndParse(key, &circleName, NULL, NULL)) { - SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find circle name in key '%@'"), key); - - CFReleaseNull(circleName); - } - - return circleName; -} - -CFStringRef SOSMessageKeyCopyCircleName(CFStringRef key, CFErrorRef *error) -{ - CFStringRef circleName = NULL; - - if (SOSKVSKeyGetKeyTypeAndParse(key, &circleName, NULL, NULL) != kMessageKey) { - SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find circle name in key '%@'"), key); - - CFReleaseNull(circleName); - } - return circleName; -} - -CFStringRef SOSMessageKeyCopyFromPeerName(CFStringRef messageKey, CFErrorRef *error) -{ - CFStringRef fromPeer = NULL; - - if (SOSKVSKeyGetKeyTypeAndParse(messageKey, NULL, &fromPeer, NULL) != kMessageKey) { - SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find from peer in key '%@'"), messageKey); - - CFReleaseNull(fromPeer); - } - return fromPeer; -} - -CFStringRef SOSMessageKeyCreateWithCircleAndPeerNames(SOSCircleRef circle, CFStringRef from_peer_name, CFStringRef to_peer_name) -{ - return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@%@"), - SOSCircleGetName(circle), sCircleSeparator, from_peer_name, sFromToSeparator, to_peer_name); -} - -CFStringRef SOSMessageKeyCreateWithCircleAndPeerInfos(SOSCircleRef circle, SOSPeerInfoRef from_peer, SOSPeerInfoRef to_peer) -{ - return SOSMessageKeyCreateWithCircleAndPeerNames(circle, SOSPeerInfoGetPeerID(from_peer), SOSPeerInfoGetPeerID(to_peer)); -} - -CFStringRef SOSMessageKeyCreateWithAccountAndPeer(SOSAccountRef account, SOSCircleRef circle, CFStringRef peer_name) { - // TODO: Handle errors! - CFErrorRef error = NULL; - - SOSFullPeerInfoRef me = SOSAccountGetMyFullPeerInCircle(account, circle, &error); - SOSPeerInfoRef my_pi = SOSFullPeerInfoGetPeerInfo(me); - CFStringRef result = SOSMessageKeyCreateWithCircleAndPeerNames(circle, SOSPeerInfoGetPeerID(my_pi), peer_name); - CFReleaseSafe(error); - return result; -} - -CFStringRef SOSRetirementKeyCreateWithCircleAndPeer(SOSCircleRef circle, CFStringRef retirement_peer_name) -{ - return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@"), - sRetirementPrefix, SOSCircleGetName(circle), sCircleSeparator, retirement_peer_name); -} - - -static SOSPeerCoderStatus SOSAccountHandlePeerMessage(SOSAccountRef account, - CFStringRef circle_id, - CFStringRef peer_name, - CFDataRef message, - SOSAccountSendBlock send_block, - CFErrorRef *error) -{ - bool success = false; - CFStringRef peer_key = NULL; - - SOSCircleRef circle = SOSAccountFindCircle(account, circle_id, error); - require_quiet(circle, fail); - SOSFullPeerInfoRef myFullPeer = SOSAccountGetMyFullPeerInCircle(account, circle, error); - SOSPeerInfoRef myPeer = SOSFullPeerInfoGetPeerInfo(myFullPeer); - require_action_quiet(SOSCircleHasPeer(circle, myPeer, NULL), fail, SOSCreateErrorWithFormat(kSOSErrorNotReady, NULL, error, NULL, CFSTR("Not in circle, can't handle message"))); - - peer_key = SOSMessageKeyCreateWithAccountAndPeer(account, circle, peer_name); - - SOSPeerSendBlock peer_send_block = ^bool (CFDataRef message, CFErrorRef *error) { - return send_block(circle, peer_key, message, error); - }; - - success = SOSCircleHandlePeerMessage(circle, myFullPeer, account->factory, peer_send_block, peer_name, message, error); - -fail: - CFReleaseNull(peer_key); - return success; -} - -bool SOSAccountHandleUpdates(SOSAccountRef account, - CFDictionaryRef updates, - CFErrorRef *error) { - - if(CFDictionaryGetValue(updates, kSOSKVSAccountChangedKey) != NULL) { - SOSAccountSetToNew(account); - } - - CFTypeRef parameters = CFDictionaryGetValue(updates, kSOSKVSKeyParametersKey); - if (isData(parameters)) { - SecKeyRef newKey = NULL; - CFDataRef newParameters = NULL; - const uint8_t *parse_end = der_decode_cloud_parameters(kCFAllocatorDefault, kSecECDSAAlgorithmID, - &newKey, &newParameters, error, - CFDataGetBytePtr(parameters), CFDataGetPastEndPtr(parameters)); - - if (parse_end == CFDataGetPastEndPtr(parameters)) { - if (CFEqualSafe(account->user_public, newKey)) { - secnotice("updates", "Got same public key sent our way. Ignoring."); - } else if (CFEqualSafe(account->previous_public, newKey)) { - secnotice("updates", "Got previous public key repeated. Ignoring."); - } else { - CFReleaseNull(account->user_public); - SOSAccountPurgePrivateCredential(account); - CFReleaseNull(account->user_key_parameters); - - account->user_public_trusted = false; - - account->user_public = newKey; - newKey = NULL; - - account->user_key_parameters = newParameters; - newParameters = NULL; - - secnotice("updates", "Got new parameters for public key: %@", account->user_public); - debugDumpUserParameters(CFSTR("params"), account->user_key_parameters); - } - } - - CFReleaseNull(newKey); - CFReleaseNull(newParameters); - } - - if (!account->user_public_trusted) { - if (!account->deferred_updates) { - account->deferred_updates = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - } - - CFDictionaryForEach(updates, ^(const void *key, const void *value) { - if (!CFEqualSafe(key, kSOSKVSKeyParametersKey) && !CFEqualSafe(key, kSOSKVSAccountChangedKey)) - CFDictionarySetValue(account->deferred_updates, key, value); - }); - secnotice("updates", "No public peer key, deferring updates: %@", updates); - return true; - } - - // Iterate though keys in updates. Perform circle change update. - // Then instantiate circles and engines and peers for all peers that - // are receiving a message in updates. - __block bool is_initial_sync = CFDictionaryContainsKey(updates, kSOSKVSInitialSyncKey); - - CFDictionaryForEach(updates, ^(const void *key, const void *value) { - CFStringRef circle_name = NULL; - CFErrorRef localError = NULL; - SOSCircleRef circle = NULL; - - if (SOSKVSKeyGetKeyTypeAndParse(key, &circle_name, NULL, NULL) == kCircleKey) { - circle = SOSAccountCreateCircleFrom(circle_name, value, &localError); - if (!circle) { - if (isSOSErrorCoded(localError, kSOSErrorIncompatibleCircle)) { - SOSAccountDestroyCirclePeerInfoNamed(account, circle_name, NULL); - CFDictionarySetValue(account->circles, circle_name, kCFNull); - } else { - SOSCreateErrorWithFormat(kSOSErrorNameMismatch, localError, error, NULL, - CFSTR("Bad key for message, no circle '%@'"), key); - goto circle_done; - } - } - - if (!SOSAccountUpdateCircleFromRemote(account, circle, is_initial_sync, &localError)) { - SOSCreateErrorWithFormat(kSOSErrorProcessingFailure, localError, error, NULL, - CFSTR("Error handling circle change '%@'"), key); - secnotice("update", "Error updating circle '%@': %@", key, circle); - goto circle_done; - } - } - circle_done: - CFReleaseSafe(circle_name); - CFReleaseNull(circle); - CFReleaseNull(localError); - }); - - CFDictionaryForEach(updates, ^(const void *key, const void *value) { - CFErrorRef localError = NULL; - CFStringRef circle_name = NULL; - CFStringRef from_name = NULL; - CFStringRef to_name = NULL; - switch (SOSKVSKeyGetKeyTypeAndParse(key, &circle_name, &from_name, &to_name)) { - case kParametersKey: - case kInitialSyncKey: - case kCircleKey: - break; - case kMessageKey: - { - SOSFullPeerInfoRef my_peer = NULL; - - require_action_quiet(isData(value), message_error, SOSCreateErrorWithFormat(kSOSErrorUnexpectedType, localError, error, NULL, CFSTR("Non-Data for message(%@) from '%@'"), value, key)); - require_quiet(my_peer = SOSAccountGetMyFullPeerInCircleNamedIfPresent(account, circle_name, &localError), message_error); - - CFStringRef my_id = SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(my_peer)); - require_quiet(SOSAccountIsActivePeerInCircleNamed(account, circle_name, my_id, &localError), skip); - require_quiet(CFEqual(my_id, to_name), skip); - require_quiet(!CFEqual(my_id, from_name), skip); - - SOSAccountSendBlock cacheInDictionary = ^ bool (SOSCircleRef circle, CFStringRef key, CFDataRef new_message, CFErrorRef* error) { - CFDictionarySetValue(account->pending_changes, key, new_message); - - if (account->processed_message_block) { - account->processed_message_block(circle, value, new_message); - } - - return true; - }; - - if (SOSAccountHandlePeerMessage(account, circle_name, from_name, value, cacheInDictionary, &localError) == kSOSPeerCoderFailure) { - SOSCreateErrorWithFormat(kSOSErrorNameMismatch, localError, error, NULL, - CFSTR("Error handling peer message from '%@'"), key); - localError = NULL; // Released by SOSCreateErrorWithFormat - goto message_error; - } - - message_error: - skip: - break; - } - case kRetirementKey: - if(isData(value)) { - SOSPeerInfoRef pi = SOSPeerInfoCreateFromData(NULL, error, (CFDataRef) value); - if(pi && CFEqual(from_name, SOSPeerInfoGetPeerID(pi)) && SOSPeerInfoInspectRetirementTicket(pi, error)) { - CFDictionarySetValue(account->retired_peers, key, value); - SOSAccountRecordRetiredPeerInCircleNamed(account, circle_name, pi); - } - CFReleaseSafe(pi); - } - break; - - case kAccountChangedKey: // Handled at entry to function to make sure these are processed first. - break; - - case kUnknownKey: - secnotice("updates", "Unknown key '%@', ignoring", key); - break; - - } - - CFReleaseNull(circle_name); - CFReleaseNull(from_name); - CFReleaseNull(to_name); - - if (error && *error) - secerror("Peer message processing error for: %@ -> %@ (%@)", key, value, *error); - if (localError) - secerror("Peer message local processing error for: %@ -> %@ (%@)", key, value, localError); - - CFReleaseNull(localError); - }); - - return SOSAccountSendPendingChanges(account, error); -} - -void SOSAccountSetMessageProcessedBlock(SOSAccountRef account, SOSAccountMessageProcessedBlock processedBlock) -{ - CFRetainSafe(processedBlock); - CFReleaseNull(account->processed_message_block); - account->processed_message_block = processedBlock; -} - -CFStringRef SOSInterestListCopyDescription(CFArrayRef interests) -{ - CFMutableStringRef description = CFStringCreateMutable(kCFAllocatorDefault, 0); - CFStringAppendFormat(description, NULL, CFSTR("")); - - return description; -} diff --git a/sec/SOSCircle/SecureObjectSync/SOSAccount.h b/sec/SOSCircle/SecureObjectSync/SOSAccount.h deleted file mode 100644 index 005975ba..00000000 --- a/sec/SOSCircle/SecureObjectSync/SOSAccount.h +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Created by Michael Brouwer on 6/22/12. - * Copyright 2012 Apple Inc. All Rights Reserved. - */ - -/*! - @header SOSAccount.h - The functions provided in SOSCircle.h provide an interface to a - secure object syncing circle for a single class - */ - -#ifndef _SOSACCOUNT_H_ -#define _SOSACCOUNT_H_ - -#include - -#include -#include -#include -#include - -__BEGIN_DECLS - -#define RETIREMENT_FINALIZATION_SECONDS (24*60*60) - - -/* Forward declarations of SOS types. */ -typedef struct __OpaqueSOSAccount *SOSAccountRef; - -typedef void (^SOSAccountKeyInterestBlock)(bool getNewKeysOnly, CFArrayRef alwaysKeys, CFArrayRef afterFirstUnlockKeys, CFArrayRef unlockedKeys); -typedef bool (^SOSAccountDataUpdateBlock)(CFDictionaryRef keys, CFErrorRef *error); -typedef void (^SOSAccountCircleMembershipChangeBlock)(SOSCircleRef new_circle, - CFArrayRef added_peers, CFArrayRef removed_peers, - CFArrayRef added_applicants, CFArrayRef removed_applicants); - -SOSAccountRef SOSAccountGetShared(void); -SOSAccountRef SOSAccountCreate(CFAllocatorRef allocator, - CFDictionaryRef gestalt, - SOSDataSourceFactoryRef factory, - SOSAccountKeyInterestBlock interest_block, - SOSAccountDataUpdateBlock update_block); - -// -// MARK: Persistent Encode decode -// - -SOSAccountRef SOSAccountCreateFromDER(CFAllocatorRef allocator, SOSDataSourceFactoryRef factory, - SOSAccountKeyInterestBlock interest_block, SOSAccountDataUpdateBlock update_block, - CFErrorRef* error, - const uint8_t** der_p, const uint8_t *der_end); - -SOSAccountRef SOSAccountCreateFromDER_V3(CFAllocatorRef allocator, - SOSDataSourceFactoryRef factory, - SOSAccountKeyInterestBlock interest_block, - SOSAccountDataUpdateBlock update_block, - CFErrorRef* error, - const uint8_t** der_p, const uint8_t *der_end); - -SOSAccountRef SOSAccountCreateFromData(CFAllocatorRef allocator, CFDataRef circleData, - SOSDataSourceFactoryRef factory, - SOSAccountKeyInterestBlock interest_block, SOSAccountDataUpdateBlock update_block, - CFErrorRef* error); - -size_t SOSAccountGetDEREncodedSize(SOSAccountRef cir, CFErrorRef *error); -uint8_t* SOSAccountEncodeToDER(SOSAccountRef cir, CFErrorRef* error, const uint8_t* der, uint8_t* der_end); -size_t SOSAccountGetDEREncodedSize_V3(SOSAccountRef cir, CFErrorRef *error); -uint8_t* SOSAccountEncodeToDER_V3(SOSAccountRef cir, CFErrorRef* error, const uint8_t* der, uint8_t* der_end); -CFDataRef SOSAccountCopyEncodedData(SOSAccountRef circle, CFAllocatorRef allocator, CFErrorRef *error); - - -// -// MARK: Local Peer finding -// -SOSPeerInfoRef SOSAccountGetMyPeerInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error); -SOSPeerInfoRef SOSAccountGetMyPeerInCircleNamed(SOSAccountRef account, CFStringRef circle, CFErrorRef* error); - -SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error); -SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircleNamed(SOSAccountRef account, CFStringRef name, CFErrorRef *error); - -// -// MARK: Credential management -// - -SecKeyRef SOSAccountGetPrivateCredential(SOSAccountRef account, CFErrorRef* error); -void SOSAccountPurgePrivateCredential(SOSAccountRef account); - -bool SOSAccountTryUserCredentials(SOSAccountRef account, - CFStringRef user_account, CFDataRef user_password, - CFErrorRef *error); - -bool SOSAccountAssertUserCredentials(SOSAccountRef account, - CFStringRef user_account, CFDataRef user_password, - CFErrorRef *error); - - -// -// MARK: Circle management -// -int SOSAccountCountCircles(SOSAccountRef a); - -void SOSAccountForEachCircle(SOSAccountRef account, void (^process)(SOSCircleRef circle)); - -SOSCircleRef SOSAccountFindCompatibleCircle(SOSAccountRef a, CFStringRef name); -SOSCircleRef SOSAccountFindCircle(SOSAccountRef a, CFStringRef name, CFErrorRef *error); -SOSCircleRef SOSAccountEnsureCircle(SOSAccountRef a, CFStringRef name, CFErrorRef *error); -bool SOSAccountUpdateCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef *error); - -bool SOSAccountModifyCircle(SOSAccountRef account, - CFStringRef circleName, - CFErrorRef *error, - void (^action)(SOSCircleRef circle)); - - -SOSCCStatus SOSAccountIsInCircles(SOSAccountRef account, CFErrorRef* error); -bool SOSAccountJoinCircles(SOSAccountRef account, CFErrorRef* error); -bool SOSAccountJoinCirclesAfterRestore(SOSAccountRef account, CFErrorRef* error); -bool SOSAccountLeaveCircles(SOSAccountRef account, CFErrorRef* error); -bool SOSAccountBail(SOSAccountRef account, uint64_t limit_in_seconds, CFErrorRef* error); -bool SOSAccountAcceptApplicants(SOSAccountRef account, CFArrayRef applicants, CFErrorRef* error); -bool SOSAccountRejectApplicants(SOSAccountRef account, CFArrayRef applicants, CFErrorRef* error); - -bool SOSAccountResetToOffering(SOSAccountRef account, CFErrorRef* error); -bool SOSAccountResetToEmpty(SOSAccountRef account, CFErrorRef* error); - -CFArrayRef SOSAccountCopyApplicants(SOSAccountRef account, CFErrorRef *error); -CFArrayRef SOSAccountCopyPeers(SOSAccountRef account, CFErrorRef *error); -CFArrayRef SOSAccountCopyActivePeers(SOSAccountRef account, CFErrorRef *error); -CFArrayRef SOSAccountCopyActiveValidPeers(SOSAccountRef account, CFErrorRef *error); -CFArrayRef SOSAccountCopyConcurringPeers(SOSAccountRef account, CFErrorRef *error); - -CFArrayRef SOSAccountCopyAccountIdentityPeerInfos(SOSAccountRef account, CFAllocatorRef allocator, CFErrorRef* error); -bool SOSAccountIsAccountIdentity(SOSAccountRef account, SOSPeerInfoRef peer_info, CFErrorRef *error); - -enum DepartureReason SOSAccountGetLastDepartureReason(SOSAccountRef account, CFErrorRef* error); - -// -// MARK: Change blocks -// -void SOSAccountAddChangeBlock(SOSAccountRef a, SOSAccountCircleMembershipChangeBlock changeBlock); -void SOSAccountRemoveChangeBlock(SOSAccountRef a, SOSAccountCircleMembershipChangeBlock changeBlock); - -// -// MARK: Local device gestalt change. -// -bool SOSAccountUpdateGestalt(SOSAccountRef account, CFDictionaryRef new_gestalt); - -// TODO: ds should be a SOSDataSourceFactoryRef -bool SOSAccountHandleUpdates(SOSAccountRef account, - CFDictionaryRef updates, - CFErrorRef *error); - -bool SOSAccountSyncWithPeer(SOSAccountRef account, SOSCircleRef circle, SOSPeerInfoRef thisPeer, bool* didSendData, CFErrorRef* error); -bool SOSAccountSyncWithAllPeers(SOSAccountRef account, CFErrorRef *error); -bool SOSAccountSyncWithAllPeersInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef *error); - -bool SOSAccountCleanupAfterPeer(SOSAccountRef account, size_t seconds, SOSCircleRef circle, - SOSPeerInfoRef cleanupPeer, CFErrorRef* error); - -bool SOSAccountCleanupRetirementTickets(SOSAccountRef account, size_t seconds, CFErrorRef* error); - -bool SOSAccountScanForRetired(SOSAccountRef account, SOSCircleRef circle, CFErrorRef *error); - -SOSCircleRef SOSAccountCloneCircleWithRetirement(SOSAccountRef account, SOSCircleRef starting_circle, CFErrorRef *error); - -// -// MARK: Version incompatibility Functions -// -CFStringRef SOSAccountCopyIncompatibilityInfo(SOSAccountRef account, CFErrorRef* error); - -// -// MARK: Private functions -// - -dispatch_queue_t SOSAccountGetQueue(SOSAccountRef account); - - -// -// MARK: Private functions for testing -// - - -typedef enum { - kCircleKey, - kMessageKey, - kParametersKey, - kInitialSyncKey, - kRetirementKey, - kAccountChangedKey, - kUnknownKey, -} SOSKVSKeyType; - -extern const CFStringRef kSOSKVSKeyParametersKey; -extern const CFStringRef kSOSKVSInitialSyncKey; -extern const CFStringRef kSOSKVSAccountChangedKey; - -SOSKVSKeyType SOSKVSKeyGetKeyType(CFStringRef key); -SOSKVSKeyType SOSKVSKeyGetKeyTypeAndParse(CFStringRef key, CFStringRef *circle, CFStringRef *from, CFStringRef *to); - -CFStringRef SOSCircleKeyCreateWithCircle(SOSCircleRef circle, CFErrorRef *error); -CFStringRef SOSCircleKeyCreateWithName(CFStringRef name, CFErrorRef *error); -CFStringRef SOSCircleKeyCopyCircleName(CFStringRef key, CFErrorRef *error); - -CFStringRef SOSMessageKeyCopyCircleName(CFStringRef key, CFErrorRef *error); -CFStringRef SOSMessageKeyCopyFromPeerName(CFStringRef messageKey, CFErrorRef *error); -CFStringRef SOSMessageKeyCreateWithCircleAndPeerNames(SOSCircleRef circle, CFStringRef from_peer_name, CFStringRef to_peer_name); -CFStringRef SOSMessageKeyCreateWithCircleAndPeerInfos(SOSCircleRef circle, SOSPeerInfoRef from_peer, SOSPeerInfoRef to_peer); -CFStringRef SOSMessageKeyCreateWithAccountAndPeer(SOSAccountRef account, SOSCircleRef circle, CFStringRef peer_name); - -CFStringRef SOSRetirementKeyCreateWithCircleAndPeer(SOSCircleRef circle, CFStringRef retirement_peer_name); - -typedef void (^SOSAccountMessageProcessedBlock)(SOSCircleRef circle, CFDataRef messageIn, CFDataRef messageOut); -typedef bool (^SOSAccountSendBlock)(SOSCircleRef circle, CFStringRef key, CFDataRef message, CFErrorRef *error); - -void SOSAccountSetMessageProcessedBlock(SOSAccountRef account, SOSAccountMessageProcessedBlock processedBlock); - -// -// MARK: Utility functions -// - -CFStringRef SOSInterestListCopyDescription(CFArrayRef interests); - -__END_DECLS - -#endif /* !_SOSACCOUNT_H_ */ diff --git a/sec/SOSCircle/SecureObjectSync/SOSCircle.c b/sec/SOSCircle/SecureObjectSync/SOSCircle.c deleted file mode 100644 index 1b131fd4..00000000 --- a/sec/SOSCircle/SecureObjectSync/SOSCircle.c +++ /dev/null @@ -1,1172 +0,0 @@ -/* - * Created by Michael Brouwer on 6/22/12. - * Copyright 2012 Apple Inc. All Rights Reserved. - */ - -/* - * SOSCircle.c - Implementation of the secure object syncing transport - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -//#include "ckdUtilities.h" - -#include -#include - -#include -#include -#include - -#include -#include - -enum { - kOnlyCompatibleVersion = 1, // Sometime in the future this name will be improved to reflect history. - - kAlwaysIncompatibleVersion = UINT64_MAX, -}; - -struct __OpaqueSOSCircle { - CFRuntimeBase _base; - - CFStringRef name; - CFNumberRef generation; - CFMutableArrayRef peers; - CFMutableArrayRef applicants; - CFMutableArrayRef rejected_applicants; - - CFMutableDictionaryRef signatures; -}; - -CFGiblisWithCompareFor(SOSCircle); - -// Move the next 2 lines to SOSPeer if we need it. -static void SOSPeerRelease(CFAllocatorRef allocator, const void *value) { - SOSPeerDispose((SOSPeerRef)value); -} - -static const CFDictionaryValueCallBacks dispose_peer_callbacks = { .release = SOSPeerRelease }; - -SOSCircleRef SOSCircleCreate(CFAllocatorRef allocator, CFStringRef name, CFErrorRef *error) { - SOSCircleRef c = CFTypeAllocate(SOSCircle, struct __OpaqueSOSCircle, allocator); - int64_t gen = 1; - - assert(name); - - c->name = CFStringCreateCopy(allocator, name); - c->generation = CFNumberCreate(allocator, kCFNumberSInt64Type, &gen); - c->peers = CFArrayCreateMutableForCFTypes(allocator); - c->applicants = CFArrayCreateMutableForCFTypes(allocator); - c->rejected_applicants = CFArrayCreateMutableForCFTypes(allocator); - c->signatures = CFDictionaryCreateMutableForCFTypes(allocator); - - return c; -} - -static CFNumberRef SOSCircleGenerationCopy(CFNumberRef generation) { - int64_t value; - CFAllocatorRef allocator = CFGetAllocator(generation); - CFNumberGetValue(generation, kCFNumberSInt64Type, &value); - return CFNumberCreate(allocator, kCFNumberSInt64Type, &value); -} - -SOSCircleRef SOSCircleCopyCircle(CFAllocatorRef allocator, SOSCircleRef otherCircle, CFErrorRef *error) -{ - SOSCircleRef c = CFTypeAllocate(SOSCircle, struct __OpaqueSOSCircle, allocator); - - assert(otherCircle); - c->name = CFStringCreateCopy(allocator, otherCircle->name); - c->generation = SOSCircleGenerationCopy(otherCircle->generation); - c->peers = CFArrayCreateMutableCopy(allocator, 0, otherCircle->peers); - c->applicants = CFArrayCreateMutableCopy(allocator, 0, otherCircle->applicants); - c->rejected_applicants = CFArrayCreateMutableCopy(allocator, 0, otherCircle->rejected_applicants); - c->signatures = CFDictionaryCreateMutableCopy(allocator, 0, otherCircle->signatures); - - return c; -} - -static inline -void SOSCircleAssertStable(SOSCircleRef circle) -{ - assert(circle); - assert(circle->name); - assert(circle->generation); - assert(circle->peers); - assert(circle->applicants); - assert(circle->rejected_applicants); - assert(circle->signatures); -} - -static inline -SOSCircleRef SOSCircleConvertAndAssertStable(CFTypeRef circleAsType) -{ - if (CFGetTypeID(circleAsType) != SOSCircleGetTypeID()) - return NULL; - - SOSCircleRef circle = (SOSCircleRef) circleAsType; - - SOSCircleAssertStable(circle); - - return circle; -} - - -static Boolean SOSCircleCompare(CFTypeRef lhs, CFTypeRef rhs) { - if (CFGetTypeID(lhs) != SOSCircleGetTypeID() - || CFGetTypeID(rhs) != SOSCircleGetTypeID()) - return false; - - SOSCircleRef left = SOSCircleConvertAndAssertStable(lhs); - SOSCircleRef right = SOSCircleConvertAndAssertStable(rhs); - - // TODO: we should be doing set equality for peers and applicants. - return NULL != left && NULL != right - && CFEqual(left->generation, right->generation) - && CFEqual(left->peers, right->peers) - && CFEqual(left->applicants, right->applicants) - && CFEqual(left->rejected_applicants, right->rejected_applicants) - && CFEqual(left->signatures, right->signatures); -} - - -static bool SOSCircleDigestArray(const struct ccdigest_info *di, CFMutableArrayRef array, void *hash_result, CFErrorRef *error) -{ - __block bool success = true; - ccdigest_di_decl(di, array_digest); - const void * a_digest = array_digest; - - ccdigest_init(di, array_digest); - CFArraySortValues(array, CFRangeMake(0, CFArrayGetCount(array)), SOSPeerInfoCompareByID, SOSPeerCmpPubKeyHash); - CFArrayForEach(array, ^(const void *peer) { - if (!SOSPeerInfoUpdateDigestWithPublicKeyBytes((SOSPeerInfoRef)peer, di, a_digest, error)) - success = false; - }); - ccdigest_final(di, array_digest, hash_result); - - return success; -} - -static bool SOSCircleHash(const struct ccdigest_info *di, SOSCircleRef circle, void *hash_result, CFErrorRef *error) { - ccdigest_di_decl(di, circle_digest); - ccdigest_init(di, circle_digest); - int64_t gen = SOSCircleGetGenerationSint(circle); - ccdigest_update(di, circle_digest, sizeof(gen), &gen); - - SOSCircleDigestArray(di, circle->peers, hash_result, error); - ccdigest_update(di, circle_digest, di->output_size, hash_result); - ccdigest_final(di, circle_digest, hash_result); - return true; -} - -static bool SOSCircleSetSignature(SOSCircleRef circle, SecKeyRef pubkey, CFDataRef signature, CFErrorRef *error) { - bool result = false; - - CFStringRef pubKeyID = SOSCopyIDOfKey(pubkey, error); - require_quiet(pubKeyID, fail); - CFDictionarySetValue(circle->signatures, pubKeyID, signature); - result = true; - -fail: - CFReleaseSafe(pubKeyID); - return result; -} - -static bool SOSCircleRemoveSignatures(SOSCircleRef circle, CFErrorRef *error) { - CFDictionaryRemoveAllValues(circle->signatures); - return true; -} - -static CFDataRef SOSCircleGetSignature(SOSCircleRef circle, SecKeyRef pubkey, CFErrorRef *error) { - CFStringRef pubKeyID = SOSCopyIDOfKey(pubkey, error); - CFDataRef result = NULL; - require_quiet(pubKeyID, fail); - - CFTypeRef value = (CFDataRef)CFDictionaryGetValue(circle->signatures, pubKeyID); - - if (isData(value)) result = (CFDataRef) value; - -fail: - CFReleaseSafe(pubKeyID); - return result; -} - -bool SOSCircleSign(SOSCircleRef circle, SecKeyRef privKey, CFErrorRef *error) { - if (!privKey) return false; // Really assertion but not always true for now. - CFAllocatorRef allocator = CFGetAllocator(circle); - uint8_t tmp[4096]; - size_t tmplen = 4096; - const struct ccdigest_info *di = ccsha256_di(); - uint8_t hash_result[di->output_size]; - - SOSCircleHash(di, circle, hash_result, error); - OSStatus stat = SecKeyRawSign(privKey, kSecPaddingNone, hash_result, di->output_size, tmp, &tmplen); - if(stat) { - // TODO - Create a CFErrorRef; - secerror("Bad Circle SecKeyRawSign, stat: %ld", (long)stat); - SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Circle SecKeyRawSign"), (error != NULL) ? *error : NULL, error); - return false; - }; - CFDataRef signature = CFDataCreate(allocator, tmp, tmplen); - SecKeyRef publicKey = SecKeyCreatePublicFromPrivate(privKey); - SOSCircleSetSignature(circle, publicKey, signature, error); - CFReleaseNull(publicKey); - CFRelease(signature); - return true; -} - -bool SOSCircleVerifySignatureExists(SOSCircleRef circle, SecKeyRef pubKey, CFErrorRef *error) { - if(!pubKey) { - // TODO ErrorRef - secerror("SOSCircleVerifySignatureExists no pubKey"); - SOSCreateError(kSOSErrorBadFormat, CFSTR("SOSCircleVerifySignatureExists no pubKey"), (error != NULL) ? *error : NULL, error); - return false; - } - CFDataRef signature = SOSCircleGetSignature(circle, pubKey, error); - return NULL != signature; -} - -bool SOSCircleVerify(SOSCircleRef circle, SecKeyRef pubKey, CFErrorRef *error) { - const struct ccdigest_info *di = ccsha256_di(); - uint8_t hash_result[di->output_size]; - - SOSCircleHash(di, circle, hash_result, error); - - CFDataRef signature = SOSCircleGetSignature(circle, pubKey, error); - if(!signature) return false; - - return SecKeyRawVerify(pubKey, kSecPaddingNone, hash_result, di->output_size, - CFDataGetBytePtr(signature), CFDataGetLength(signature)) == errSecSuccess; -} - -bool SOSCircleVerifyPeerSigned(SOSCircleRef circle, SOSPeerInfoRef peer, CFErrorRef *error) { - SecKeyRef pub_key = SOSPeerInfoCopyPubKey(peer); - bool result = SOSCircleVerify(circle, pub_key, error); - CFReleaseSafe(pub_key); - return result; -} - - -static CFIndex CFArrayRemoveAllPassing(CFMutableArrayRef array, bool (^test)(const void *) ){ - CFIndex numberRemoved = 0; - - CFIndex position = 0; - while (position < CFArrayGetCount(array) && !test(CFArrayGetValueAtIndex(array, position))) - ++position; - - while (position < CFArrayGetCount(array)) { - CFArrayRemoveValueAtIndex(array, position); - ++numberRemoved; - while (position < CFArrayGetCount(array) && !test(CFArrayGetValueAtIndex(array, position))) - ++position; - } - - return numberRemoved; -} - -static CFIndex CFArrayRemoveAllWithMatchingID(CFMutableArrayRef array, SOSPeerInfoRef peerInfo) { - CFStringRef peer_id = SOSPeerInfoGetPeerID(peerInfo); - if (!peer_id) return 0; - - return CFArrayRemoveAllPassing(array, ^ bool (const void *element) { - SOSPeerInfoRef peer = (SOSPeerInfoRef) element; - - return CFEqual(peer_id, SOSPeerInfoGetPeerID(peer)); - }); -} - -static void SOSCircleRejectNonValidApplicants(SOSCircleRef circle, SecKeyRef pubkey) { - CFArrayRef applicants = SOSCircleCopyApplicants(circle, NULL); - CFArrayForEach(applicants, ^(const void *value) { - SOSPeerInfoRef pi = (SOSPeerInfoRef) value; - if(!SOSPeerInfoApplicationVerify(pi, pubkey, NULL)) { - CFArrayRemoveAllWithMatchingID(circle->applicants, pi); - CFArrayAppendValue(circle->rejected_applicants, pi); - } - }); -} - -bool SOSCircleGenerationSign(SOSCircleRef circle, SecKeyRef user_approver, SOSFullPeerInfoRef peerinfo, CFErrorRef *error) { - - SecKeyRef ourKey = SOSFullPeerInfoCopyDeviceKey(peerinfo, error); - require_quiet(ourKey, fail); - - SOSCircleRemoveRetired(circle, error); // Prune off retirees since we're signing this one - CFArrayRemoveAllValues(circle->rejected_applicants); // Dump rejects so we clean them up sometime. - SOSCircleRejectNonValidApplicants(circle, SecKeyCreatePublicFromPrivate(user_approver)); - SOSCircleGenerationIncrement(circle); - require_quiet(SOSCircleRemoveSignatures(circle, error), fail); - require_quiet(SOSCircleSign(circle, user_approver, error), fail); - require_quiet(SOSCircleSign(circle, ourKey, error), fail); - - CFReleaseNull(ourKey); - return true; - -fail: - CFReleaseNull(ourKey); - return false; -} - - -bool SOSCircleConcordanceSign(SOSCircleRef circle, SOSFullPeerInfoRef peerinfo, CFErrorRef *error) { - bool success = false; - SecKeyRef ourKey = SOSFullPeerInfoCopyDeviceKey(peerinfo, error); - require_quiet(ourKey, exit); - - success = SOSCircleSign(circle, ourKey, error); - -exit: - CFReleaseNull(ourKey); - return success; -} - -static inline SOSConcordanceStatus CheckPeerStatus(SOSCircleRef circle, SOSPeerInfoRef peer, CFErrorRef *error) { - SOSConcordanceStatus result = kSOSConcordanceNoPeer; - SecKeyRef pubKey = SOSPeerInfoCopyPubKey(peer); - - require_action_quiet(SOSCircleHasActivePeer(circle, peer, error), exit, result = kSOSConcordanceNoPeer); - require_action_quiet(SOSCircleVerifySignatureExists(circle, pubKey, error), exit, result = kSOSConcordanceNoPeerSig); - require_action_quiet(SOSCircleVerify(circle, pubKey, error), exit, result = kSOSConcordanceBadPeerSig); - - result = kSOSConcordanceTrusted; - -exit: - CFReleaseNull(pubKey); - return result; -} - -static inline SOSConcordanceStatus CombineStatus(SOSConcordanceStatus status1, SOSConcordanceStatus status2) -{ - if (status1 == kSOSConcordanceTrusted || status2 == kSOSConcordanceTrusted) - return kSOSConcordanceTrusted; - - if (status1 == kSOSConcordanceBadPeerSig || status2 == kSOSConcordanceBadPeerSig) - return kSOSConcordanceBadPeerSig; - - if (status1 == kSOSConcordanceNoPeerSig || status2 == kSOSConcordanceNoPeerSig) - return kSOSConcordanceNoPeerSig; - - return status1; -} - -static inline bool SOSCircleIsEmpty(SOSCircleRef circle) { - return SOSCircleCountPeers(circle) == 0; -} - -static inline bool SOSCircleIsOffering(SOSCircleRef circle) { - return SOSCircleCountPeers(circle) == 1; -} - -static inline bool SOSCircleIsResignOffering(SOSCircleRef circle, SecKeyRef pubkey) { - return SOSCircleCountActiveValidPeers(circle, pubkey) == 1; -} - -static inline SOSConcordanceStatus GetSignersStatus(SOSCircleRef signers_circle, SOSCircleRef status_circle, - SecKeyRef user_pubKey, SOSPeerInfoRef exclude, CFErrorRef *error) { - CFStringRef excluded_id = exclude ? SOSPeerInfoGetPeerID(exclude) : NULL; - - __block SOSConcordanceStatus status = kSOSConcordanceNoPeer; - SOSCircleForEachActiveValidPeer(signers_circle, user_pubKey, ^(SOSPeerInfoRef peer) { - SOSConcordanceStatus peerStatus = CheckPeerStatus(status_circle, peer, error); - - if (peerStatus == kSOSConcordanceNoPeerSig && - (CFEqualSafe(SOSPeerInfoGetPeerID(peer), excluded_id) || SOSPeerInfoIsCloudIdentity(peer))) - peerStatus = kSOSConcordanceNoPeer; - - status = CombineStatus(status, peerStatus); // TODO: Use multiple error gathering. - }); - - return status; -} - -static inline bool isOlderGeneration(SOSCircleRef current, SOSCircleRef proposed) { - return CFNumberCompare(current->generation, proposed->generation, NULL) == kCFCompareGreaterThan; -} - -bool SOSCircleSharedTrustedPeers(SOSCircleRef current, SOSCircleRef proposed, SOSPeerInfoRef me) { - __block bool retval = false; - SOSCircleForEachPeer(current, ^(SOSPeerInfoRef peer) { - if(!CFEqual(me, peer) && SOSCircleHasPeer(proposed, peer, NULL)) retval = true; - }); - return retval; -} - -static void SOSCircleUpgradePeersByCircle(SOSCircleRef known_circle, SOSCircleRef proposed_circle) { - SOSCircleForEachPeer(known_circle, ^(SOSPeerInfoRef known_peer) { - SOSPeerInfoRef proposed_peer = SOSCircleCopyPeerInfo(proposed_circle, SOSPeerInfoGetPeerID(known_peer), NULL); - if(proposed_peer && CFEqualSafe(proposed_peer, known_peer) != 0) { - SOSCircleUpdatePeerInfo(known_circle, proposed_peer); - } - }); -} - -SOSConcordanceStatus SOSCircleConcordanceTrust(SOSCircleRef known_circle, SOSCircleRef proposed_circle, - SecKeyRef known_pubkey, SecKeyRef user_pubkey, - SOSPeerInfoRef exclude, CFErrorRef *error) { - - if(user_pubkey == NULL) { - SOSCreateError(kSOSErrorPublicKeyAbsent, CFSTR("Concordance with no public key"), NULL, error); - return kSOSConcordanceNoUserKey; //TODO: - needs to return an error - } - - if (SOSCircleIsEmpty(proposed_circle)) { - return kSOSConcordanceTrusted; - } - - if(!SOSCircleVerifySignatureExists(proposed_circle, user_pubkey, error)) { - SOSCreateError(kSOSErrorBadSignature, CFSTR("No public signature"), (error != NULL) ? *error : NULL, error); - return kSOSConcordanceNoUserSig; - } - - if(!SOSCircleVerify(proposed_circle, user_pubkey, error)) { - SOSCreateError(kSOSErrorBadSignature, CFSTR("Bad public signature"), (error != NULL) ? *error : NULL, error); - return kSOSConcordanceBadUserSig; - } - - if (SOSCircleIsEmpty(known_circle) || SOSCircleIsOffering(proposed_circle)) { - return GetSignersStatus(proposed_circle, proposed_circle, user_pubkey, NULL, error); - } - - if(isOlderGeneration(known_circle, proposed_circle)) { - SOSCreateError(kSOSErrorReplay, CFSTR("Bad generation"), NULL, error); - return kSOSConcordanceGenOld; - } - - - if(!SOSCircleVerify(known_circle, user_pubkey, error)) { - SOSCircleUpgradePeersByCircle(known_circle, proposed_circle); - } - - if(known_pubkey == NULL) known_pubkey = user_pubkey; - if(!SOSCircleVerify(known_circle, known_pubkey, error)) known_pubkey = user_pubkey; - return GetSignersStatus(known_circle, proposed_circle, known_pubkey, exclude, error); -} - - -static const uint8_t* der_decode_mutable_dictionary(CFAllocatorRef allocator, CFOptionFlags mutability, - CFMutableDictionaryRef* dictionary, CFErrorRef *error, - const uint8_t* der, const uint8_t *der_end) -{ - CFDictionaryRef theDict; - const uint8_t* result = der_decode_dictionary(allocator, mutability, &theDict, error, der, der_end); - - if (result != NULL) - *dictionary = (CFMutableDictionaryRef)theDict; - - return result; -} - -SOSCircleRef SOSCircleCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error, - const uint8_t** der_p, const uint8_t *der_end) { - SOSCircleRef cir = CFTypeAllocate(SOSCircle, struct __OpaqueSOSCircle, allocator); - - const uint8_t *sequence_end; - - cir->name = NULL; - cir->generation = NULL; - cir->peers = NULL; - cir->applicants = NULL; - cir->rejected_applicants = NULL; - cir->signatures = NULL; - - *der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, *der_p, der_end); - require_action_quiet(sequence_end != NULL, fail, - SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Circle DER"), (error != NULL) ? *error : NULL, error)); - - // Version first. - uint64_t version = 0; - *der_p = ccder_decode_uint64(&version, *der_p, der_end); - - require_action_quiet(version == kOnlyCompatibleVersion, fail, - SOSCreateError(kSOSErrorIncompatibleCircle, CFSTR("Bad Circle Version"), NULL, error)); - - *der_p = der_decode_string(allocator, 0, &cir->name, error, *der_p, sequence_end); - *der_p = der_decode_number(allocator, 0, &cir->generation, error, *der_p, sequence_end); - - cir->peers = SOSPeerInfoArrayCreateFromDER(allocator, error, der_p, sequence_end); - cir->applicants = SOSPeerInfoArrayCreateFromDER(allocator, error, der_p, sequence_end); - cir->rejected_applicants = SOSPeerInfoArrayCreateFromDER(allocator, error, der_p, sequence_end); - - *der_p = der_decode_mutable_dictionary(allocator, kCFPropertyListMutableContainersAndLeaves, - &cir->signatures, error, *der_p, sequence_end); - - require_action_quiet(*der_p == sequence_end, fail, - SOSCreateError(kSOSErrorBadFormat, CFSTR("Bad Circle DER"), (error != NULL) ? *error : NULL, error)); - - return cir; - -fail: - CFReleaseNull(cir); - return NULL; -} - -SOSCircleRef SOSCircleCreateFromData(CFAllocatorRef allocator, CFDataRef circleData, CFErrorRef *error) -{ - size_t size = CFDataGetLength(circleData); - const uint8_t *der = CFDataGetBytePtr(circleData); - SOSCircleRef inflated = SOSCircleCreateFromDER(allocator, error, &der, der + size); - return inflated; -} - -size_t SOSCircleGetDEREncodedSize(SOSCircleRef cir, CFErrorRef *error) { - SOSCircleAssertStable(cir); - size_t total_payload = 0; - - require_quiet(accumulate_size(&total_payload, ccder_sizeof_uint64(kOnlyCompatibleVersion)), fail); - require_quiet(accumulate_size(&total_payload, der_sizeof_string(cir->name, error)), fail); - require_quiet(accumulate_size(&total_payload, der_sizeof_number(cir->generation, error)), fail); - require_quiet(accumulate_size(&total_payload, SOSPeerInfoArrayGetDEREncodedSize(cir->peers, error)), fail); - require_quiet(accumulate_size(&total_payload, SOSPeerInfoArrayGetDEREncodedSize(cir->applicants, error)), fail); - require_quiet(accumulate_size(&total_payload, SOSPeerInfoArrayGetDEREncodedSize(cir->rejected_applicants, error)), fail); - require_quiet(accumulate_size(&total_payload, der_sizeof_dictionary((CFDictionaryRef) cir->signatures, error)), fail); - - return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, total_payload); - -fail: - SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("don't know how to encode"), NULL, error); - return 0; -} - -uint8_t* SOSCircleEncodeToDER(SOSCircleRef cir, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) { - SOSCircleAssertStable(cir); - - return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, - ccder_encode_uint64(kOnlyCompatibleVersion, der, - der_encode_string(cir->name, error, der, - der_encode_number(cir->generation, error, der, - SOSPeerInfoArrayEncodeToDER(cir->peers, error, der, - SOSPeerInfoArrayEncodeToDER(cir->applicants, error, der, - SOSPeerInfoArrayEncodeToDER(cir->rejected_applicants, error, der, - der_encode_dictionary((CFDictionaryRef) cir->signatures, error, der, der_end)))))))); -} - -CFDataRef SOSCircleCreateIncompatibleCircleDER(CFErrorRef* error) -{ - size_t total_payload = 0; - size_t encoded_size = 0; - uint8_t* der = 0; - uint8_t* der_end = 0; - CFMutableDataRef result = NULL; - - require_quiet(accumulate_size(&total_payload, ccder_sizeof_uint64(kAlwaysIncompatibleVersion)), fail); - - encoded_size = ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, total_payload); - - result = CFDataCreateMutableWithScratch(kCFAllocatorDefault, encoded_size); - - der = CFDataGetMutableBytePtr(result); - der_end = der + CFDataGetLength(result); - - der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, - ccder_encode_uint64(kAlwaysIncompatibleVersion, der, der_end)); - -fail: - if (der == NULL || der != der_end) - CFReleaseNull(result); - - return result; -} - - -CFDataRef SOSCircleCopyEncodedData(SOSCircleRef circle, CFAllocatorRef allocator, CFErrorRef *error) -{ - size_t size = SOSCircleGetDEREncodedSize(circle, error); - if (size == 0) - return NULL; - uint8_t buffer[size]; - uint8_t* start = SOSCircleEncodeToDER(circle, error, buffer, buffer + sizeof(buffer)); - CFDataRef result = CFDataCreate(kCFAllocatorDefault, start, size); - return result; -} - -static void SOSCircleDestroy(CFTypeRef aObj) { - SOSCircleRef c = (SOSCircleRef) aObj; - - CFReleaseNull(c->name); - CFReleaseNull(c->generation); - CFReleaseNull(c->peers); - CFReleaseNull(c->applicants); - CFReleaseNull(c->rejected_applicants); - CFReleaseNull(c->signatures); -} - -static CFStringRef SOSCircleCopyDescription(CFTypeRef aObj) { - SOSCircleRef c = (SOSCircleRef) aObj; - - SOSCircleAssertStable(c); - - return CFStringCreateWithFormat(NULL, NULL, - CFSTR(""), - c, c->name, c->peers, c->applicants, c->rejected_applicants, c->signatures); -} - -CFStringRef SOSCircleGetName(SOSCircleRef circle) { - assert(circle); - assert(circle->name); - return circle->name; -} - -const char *SOSCircleGetNameC(SOSCircleRef circle) { - CFStringRef name = SOSCircleGetName(circle); - if (!name) - return strdup(""); - return CFStringToCString(name); -} - -CFNumberRef SOSCircleGetGeneration(SOSCircleRef circle) { - assert(circle); - assert(circle->generation); - return circle->generation; -} - -int64_t SOSCircleGetGenerationSint(SOSCircleRef circle) { - CFNumberRef gen = SOSCircleGetGeneration(circle); - int64_t value; - if(!gen) return 0; - CFNumberGetValue(gen, kCFNumberSInt64Type, &value); - return value; -} - -void SOSCircleGenerationIncrement(SOSCircleRef circle) { - CFAllocatorRef allocator = CFGetAllocator(circle->generation); - int64_t value = SOSCircleGetGenerationSint(circle); - value++; - circle->generation = CFNumberCreate(allocator, kCFNumberSInt64Type, &value); -} - -int SOSCircleCountPeers(SOSCircleRef circle) { - SOSCircleAssertStable(circle); - __block int count = 0; - SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { - ++count; - }); - return count; -} - -int SOSCircleCountActivePeers(SOSCircleRef circle) { - SOSCircleAssertStable(circle); - __block int count = 0; - SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { - ++count; - }); - return count; -} - -int SOSCircleCountActiveValidPeers(SOSCircleRef circle, SecKeyRef pubkey) { - SOSCircleAssertStable(circle); - __block int count = 0; - SOSCircleForEachActiveValidPeer(circle, pubkey, ^(SOSPeerInfoRef peer) { - ++count; - }); - return count; -} - -int SOSCircleCountRetiredPeers(SOSCircleRef circle) { - SOSCircleAssertStable(circle); - __block int count = 0; - SOSCircleForEachRetiredPeer(circle, ^(SOSPeerInfoRef peer) { - ++count; - }); - return count; -} - -int SOSCircleCountApplicants(SOSCircleRef circle) { - SOSCircleAssertStable(circle); - - return (int)CFArrayGetCount(circle->applicants); -} - -bool SOSCircleHasApplicant(SOSCircleRef circle, SOSPeerInfoRef peerInfo, CFErrorRef *error) { - SOSCircleAssertStable(circle); - - return CFArrayHasValueMatching(circle->applicants, ^bool(const void *value) { - return SOSPeerInfoCompareByID(value, peerInfo, NULL) == 0; - }); -} - -CFMutableArrayRef SOSCircleCopyApplicants(SOSCircleRef circle, CFAllocatorRef allocator) { - SOSCircleAssertStable(circle); - - return CFArrayCreateMutableCopy(allocator, 0, circle->applicants); -} - -int SOSCircleCountRejectedApplicants(SOSCircleRef circle) { - SOSCircleAssertStable(circle); - - return (int)CFArrayGetCount(circle->rejected_applicants); -} - -bool SOSCircleHasRejectedApplicant(SOSCircleRef circle, SOSPeerInfoRef peerInfo, CFErrorRef *error) { - SOSCircleAssertStable(circle); - - return CFArrayHasValueMatching(circle->rejected_applicants, ^bool(const void *value) { - return SOSPeerInfoCompareByID(value, peerInfo, NULL) == 0; - }); -} - -SOSPeerInfoRef SOSCircleCopyRejectedApplicant(SOSCircleRef circle, SOSPeerInfoRef peerInfo, CFErrorRef *error) { - SOSCircleAssertStable(circle); - return (SOSPeerInfoRef) CFArrayGetValueMatching(circle->rejected_applicants, ^bool(const void *value) { - return SOSPeerInfoCompareByID(value, peerInfo, NULL) == 0; - }); -} - -CFMutableArrayRef SOSCircleCopyRejectedApplicants(SOSCircleRef circle, CFAllocatorRef allocator) { - SOSCircleAssertStable(circle); - - return CFArrayCreateMutableCopy(allocator, 0, circle->rejected_applicants); -} - - -bool SOSCircleHasPeerWithID(SOSCircleRef circle, CFStringRef peerid, CFErrorRef *error) { - SOSCircleAssertStable(circle); - __block bool found = false; - SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { - if(peerid && peer && CFEqualSafe(peerid, SOSPeerInfoGetPeerID(peer))) found = true; - }); - return found; -} - -bool SOSCircleHasPeer(SOSCircleRef circle, SOSPeerInfoRef peerInfo, CFErrorRef *error) { - return SOSCircleHasPeerWithID(circle, SOSPeerInfoGetPeerID(peerInfo), error); -} - -bool SOSCircleHasActivePeerWithID(SOSCircleRef circle, CFStringRef peerid, CFErrorRef *error) { - SOSCircleAssertStable(circle); - __block bool found = false; - SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { - if(peerid && peer && CFEqualSafe(peerid, SOSPeerInfoGetPeerID(peer))) found = true; - }); - return found; -} - -bool SOSCircleHasActivePeer(SOSCircleRef circle, SOSPeerInfoRef peerInfo, CFErrorRef *error) { - if(!peerInfo) return false; - return SOSCircleHasActivePeerWithID(circle, SOSPeerInfoGetPeerID(peerInfo), error); -} - - - -bool SOSCircleResetToEmpty(SOSCircleRef circle, CFErrorRef *error) { - CFArrayRemoveAllValues(circle->applicants); - CFArrayRemoveAllValues(circle->peers); - CFDictionaryRemoveAllValues(circle->signatures); - - return true; -} - -bool SOSCircleResetToOffering(SOSCircleRef circle, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error){ - - return SOSCircleResetToEmpty(circle, error) - && SOSCircleRequestAdmission(circle, user_privkey, requestor, error) - && SOSCircleAcceptRequest(circle, user_privkey, requestor, SOSFullPeerInfoGetPeerInfo(requestor), error); -} - -CFIndex SOSCircleRemoveRetired(SOSCircleRef circle, CFErrorRef *error) { - CFIndex n = CFArrayRemoveAllPassing(circle->peers, ^ bool (const void *element) { - SOSPeerInfoRef peer = (SOSPeerInfoRef) element; - - return SOSPeerInfoIsRetirementTicket(peer); - }); - - return n; -} - -static bool SOSCircleRecordAdmission(SOSCircleRef circle, SecKeyRef user_pubkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) { - SOSCircleAssertStable(circle); - - bool isPeer = SOSCircleHasPeer(circle, SOSFullPeerInfoGetPeerInfo(requestor), error); - - require_action_quiet(!isPeer, fail, SOSCreateError(kSOSErrorAlreadyPeer, CFSTR("Cannot request admission when already a peer"), NULL, error)); - - CFIndex total = CFArrayRemoveAllWithMatchingID(circle->applicants, SOSFullPeerInfoGetPeerInfo(requestor)); - - (void) total; // Suppress unused warning in release code. - assert(total <= 1); // We should at most be in the list once. - - total = CFArrayRemoveAllWithMatchingID(circle->rejected_applicants, SOSFullPeerInfoGetPeerInfo(requestor)); - - (void) total; // Suppress unused warning in release code. - assert(total <= 1); // We should at most be in the list once. - - - // Refetch the current PeerInfo as the promtion above can change it. - CFArrayAppendValue(circle->applicants, SOSFullPeerInfoGetPeerInfo(requestor)); - - return true; - -fail: - return false; - -} - -bool SOSCircleRequestReadmission(SOSCircleRef circle, SecKeyRef user_pubkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) { - bool success = false; - - SOSPeerInfoRef peer = SOSFullPeerInfoGetPeerInfo(requestor); - require_quiet(SOSPeerInfoApplicationVerify(peer, user_pubkey, error), fail); - success = SOSCircleRecordAdmission(circle, user_pubkey, requestor, error); -fail: - return success; -} - -bool SOSCircleRequestAdmission(SOSCircleRef circle, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) { - bool success = false; - - SecKeyRef user_pubkey = SecKeyCreatePublicFromPrivate(user_privkey); - require_action_quiet(user_pubkey, fail, SOSCreateError(kSOSErrorBadKey, CFSTR("No public key for key"), NULL, error)); - - require(SOSFullPeerInfoPromoteToApplication(requestor, user_privkey, error), fail); - - success = SOSCircleRecordAdmission(circle, user_pubkey, requestor, error); -fail: - CFReleaseNull(user_pubkey); - return success; -} - - -bool SOSCircleUpdatePeerInfo(SOSCircleRef circle, SOSPeerInfoRef replacement_peer_info) { - __block bool replaced = false; - CFStringRef replacement_peer_id = SOSPeerInfoGetPeerID(replacement_peer_info); - - CFMutableArrayModifyValues(circle->peers, ^const void *(const void *value) { - if (CFEqual(replacement_peer_id, SOSPeerInfoGetPeerID((SOSPeerInfoRef) value)) - && !CFEqual(replacement_peer_info, value)) { - replaced = true; - return replacement_peer_info; - } - - return value; - }); - return replaced; -} - -bool SOSCircleRemovePeer(SOSCircleRef circle, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, SOSPeerInfoRef peer_to_remove, CFErrorRef *error) { - SOSPeerInfoRef requestor_peer_info = SOSFullPeerInfoGetPeerInfo(requestor); - - if (SOSCircleHasApplicant(circle, peer_to_remove, error)) { - return SOSCircleRejectRequest(circle, requestor, peer_to_remove, error); - } - - if (!SOSCircleHasPeer(circle, requestor_peer_info, error)) { - SOSCreateError(kSOSErrorAlreadyPeer, CFSTR("Must be peer to remove peer"), NULL, error); - return false; - } - - CFArrayRemoveAllWithMatchingID(circle->peers, peer_to_remove); - - SOSCircleGenerationSign(circle, user_privkey, requestor, error); - - return true; -} - -bool SOSCircleAcceptRequest(SOSCircleRef circle, SecKeyRef user_privkey, SOSFullPeerInfoRef device_approver, SOSPeerInfoRef peerInfo, CFErrorRef *error) { - SOSCircleAssertStable(circle); - - CFIndex total = CFArrayRemoveAllWithMatchingID(circle->applicants, peerInfo); - SecKeyRef publicKey = NULL; - bool result = false; - - require_action_quiet(total != 0, fail, - SOSCreateError(kSOSErrorNotApplicant, CFSTR("Cannot accept non-applicant"), NULL, error)); - - publicKey = SecKeyCreatePublicFromPrivate(user_privkey); - require_quiet(SOSPeerInfoApplicationVerify(peerInfo, publicKey, error), fail); - - assert(total == 1); - - CFArrayAppendValue(circle->peers, peerInfo); - result = SOSCircleGenerationSign(circle, user_privkey, device_approver, error); - secnotice("circle", "Accepted %@", peerInfo); - -fail: - CFReleaseNull(publicKey); - return result; -} - -bool SOSCircleWithdrawRequest(SOSCircleRef circle, SOSPeerInfoRef peerInfo, CFErrorRef *error) { - SOSCircleAssertStable(circle); - -#ifndef NDEBUG - CFIndex total = -#endif - CFArrayRemoveAllWithMatchingID(circle->applicants, peerInfo); - - assert(total <= 1); - - return true; -} - -bool SOSCircleRemoveRejectedPeer(SOSCircleRef circle, SOSPeerInfoRef peerInfo, CFErrorRef *error) { - SOSCircleAssertStable(circle); - -#ifndef NDEBUG - CFIndex total = -#endif - CFArrayRemoveAllWithMatchingID(circle->rejected_applicants, peerInfo); - - assert(total <= 1); - - return true; -} - - -bool SOSCircleRejectRequest(SOSCircleRef circle, SOSFullPeerInfoRef device_rejector, - SOSPeerInfoRef peerInfo, CFErrorRef *error) { - SOSCircleAssertStable(circle); - - if (CFEqual(SOSPeerInfoGetPeerID(peerInfo), SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(device_rejector)))) - return SOSCircleWithdrawRequest(circle, peerInfo, error); - - CFIndex total = CFArrayRemoveAllWithMatchingID(circle->applicants, peerInfo); - - if (total == 0) { - SOSCreateError(kSOSErrorNotApplicant, CFSTR("Cannot reject non-applicant"), NULL, error); - return false; - } - assert(total == 1); - - CFArrayAppendValue(circle->rejected_applicants, peerInfo); - - // TODO: Maybe we sign the rejection with device_rejector. - - return true; -} - -bool SOSCircleAcceptRequests(SOSCircleRef circle, SecKeyRef user_privkey, SOSFullPeerInfoRef device_approver, - CFErrorRef *error) { - // Returns true if we accepted someone and therefore have to post the circle back to KVS - __block bool result = false; - - SOSCircleForEachApplicant(circle, ^(SOSPeerInfoRef peer) { - if (!SOSCircleAcceptRequest(circle, user_privkey, device_approver, peer, error)) - printf("error in SOSCircleAcceptRequest\n"); - else { - secnotice("circle", "Accepted peer: %@", peer); - result = true; - } - }); - - if (result) { - SOSCircleGenerationSign(circle, user_privkey, device_approver, error); - secnotice("circle", "Countersigned accepted requests"); - } - - return result; -} - -bool SOSCirclePeerSigUpdate(SOSCircleRef circle, SecKeyRef userPrivKey, SOSFullPeerInfoRef fpi, - CFErrorRef *error) { - // Returns true if we accepted someone and therefore have to post the circle back to KVS - __block bool result = false; - SecKeyRef userPubKey = SecKeyCreatePublicFromPrivate(userPrivKey); - - // We're going to remove any applicants using a mismatched user key. - SOSCircleForEachApplicant(circle, ^(SOSPeerInfoRef peer) { - if(!SOSPeerInfoApplicationVerify(peer, userPubKey, NULL)) { - if(!SOSCircleRejectRequest(circle, fpi, peer, NULL)) { - // do we care? - } - } - }); - - result = SOSCircleUpdatePeerInfo(circle, SOSFullPeerInfoGetPeerInfo(fpi)); - - if (result) { - SOSCircleGenerationSign(circle, userPrivKey, fpi, error); - secnotice("circle", "Generation signed updated signatures on peerinfo"); - } - - return result; -} - -SOSPeerInfoRef SOSCircleCopyPeerInfo(SOSCircleRef circle, CFStringRef peer_id, CFErrorRef *error) { - __block SOSPeerInfoRef result = NULL; - - CFArrayForEach(circle->peers, ^(const void *value) { - if (result == NULL) { - SOSPeerInfoRef tpi = (SOSPeerInfoRef)value; - if (CFEqual(SOSPeerInfoGetPeerID(tpi), peer_id)) - result = tpi; - } - }); - - CFRetainSafe(result); - return result; -} - - -static inline void SOSCircleForEachPeerMatching(SOSCircleRef circle, - void (^action)(SOSPeerInfoRef peer), - bool (^condition)(SOSPeerInfoRef peer)) { - CFArrayForEach(circle->peers, ^(const void *value) { - SOSPeerInfoRef peer = (SOSPeerInfoRef) value; - if (condition(peer)) - action(peer); - }); -} - -void SOSCircleForEachPeer(SOSCircleRef circle, void (^action)(SOSPeerInfoRef peer)) { - SOSCircleForEachPeerMatching(circle, action, ^bool(SOSPeerInfoRef peer) { - return !SOSPeerInfoIsRetirementTicket(peer) && !SOSPeerInfoIsCloudIdentity(peer); - }); -} - -void SOSCircleForEachRetiredPeer(SOSCircleRef circle, void (^action)(SOSPeerInfoRef peer)) { - SOSCircleForEachPeerMatching(circle, action, ^bool(SOSPeerInfoRef peer) { - return SOSPeerInfoIsRetirementTicket(peer); - }); -} - -void SOSCircleForEachActivePeer(SOSCircleRef circle, void (^action)(SOSPeerInfoRef peer)) { - SOSCircleForEachPeerMatching(circle, action, ^bool(SOSPeerInfoRef peer) { - return true; - }); -} - -void SOSCircleForEachActiveValidPeer(SOSCircleRef circle, SecKeyRef user_public_key, void (^action)(SOSPeerInfoRef peer)) { - SOSCircleForEachPeerMatching(circle, action, ^bool(SOSPeerInfoRef peer) { - return SOSPeerInfoApplicationVerify(peer, user_public_key, NULL); - }); -} - -void SOSCircleForEachApplicant(SOSCircleRef circle, void (^action)(SOSPeerInfoRef peer)) { - CFArrayForEach(circle->applicants, ^(const void*value) { action((SOSPeerInfoRef) value); } ); -} - - -CFMutableArrayRef SOSCircleCopyPeers(SOSCircleRef circle, CFAllocatorRef allocator) { - SOSCircleAssertStable(circle); - - CFMutableArrayRef result = CFArrayCreateMutableForCFTypes(allocator); - - SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { - CFArrayAppendValue(result, peer); - }); - - return result; -} - -CFMutableArrayRef SOSCircleCopyConcurringPeers(SOSCircleRef circle, CFErrorRef* error) { - SOSCircleAssertStable(circle); - - CFMutableArrayRef concurringPeers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - - SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { - CFErrorRef error = NULL; - if (SOSCircleVerifyPeerSigned(circle, peer, &error)) { - CFArrayAppendValue(concurringPeers, peer); - } else if (error != NULL) { - secerror("Error checking concurrence: %@", error); - } - CFReleaseNull(error); - }); - - return concurringPeers; -} - - -// -// Stuff above this line is really SOSCircleInfo below the line is the active SOSCircle functionality -// - -static SOSPeerRef SOSCircleCopyPeer(SOSCircleRef circle, SOSFullPeerInfoRef myRef, SOSPeerSendBlock sendBlock, - CFStringRef peer_id, CFErrorRef *error) { - SOSPeerRef peer = NULL; - SOSPeerInfoRef peer_info = SOSCircleCopyPeerInfo(circle, peer_id, error); - //TODO: if (peer is legit member of us then good otherwise bail) { - //} - if (peer_info) { - peer = SOSPeerCreate(myRef, peer_info, error, sendBlock); - CFReleaseNull(peer_info); - } - return peer; -} - - -static bool SOSCircleDoWithPeer(SOSFullPeerInfoRef myRef, SOSCircleRef circle, SOSDataSourceFactoryRef factory, - SOSPeerSendBlock sendBlock, CFStringRef peer_id, bool readOnly, - CFErrorRef* error, bool (^do_action)(SOSEngineRef engine, SOSPeerRef peer, CFErrorRef *error)) -{ - bool success = false; - SOSEngineRef engine = NULL; - SOSPeerRef peer = NULL; - SOSDataSourceRef ds = NULL; - - peer = SOSCircleCopyPeer(circle, myRef, sendBlock, peer_id, error); - require(peer, exit); - - ds = factory->create_datasource(factory, SOSCircleGetName(circle), readOnly, error); - require(ds, exit); - - engine = SOSEngineCreate(ds, error); // Hand off DS to engine. - ds = NULL; - require(engine, exit); - - success = do_action(engine, peer, error); - -exit: - if (ds) - ds->release(ds); - if (engine) - SOSEngineDispose(engine); - if (peer) - SOSPeerDispose(peer); - - return success; -} - -bool SOSCircleSyncWithPeer(SOSFullPeerInfoRef myRef, SOSCircleRef circle, SOSDataSourceFactoryRef factory, - SOSPeerSendBlock sendBlock, CFStringRef peer_id, - CFErrorRef *error) -{ - return SOSCircleDoWithPeer(myRef, circle, factory, sendBlock, peer_id, true, error, ^bool(SOSEngineRef engine, SOSPeerRef peer, CFErrorRef *error) { - return SOSPeerStartSync(peer, engine, error) != kSOSPeerCoderFailure; - }); -} - -bool SOSCircleHandlePeerMessage(SOSCircleRef circle, SOSFullPeerInfoRef myRef, SOSDataSourceFactoryRef factory, - SOSPeerSendBlock sendBlock, CFStringRef peer_id, - CFDataRef message, CFErrorRef *error) { - return SOSCircleDoWithPeer(myRef, circle, factory, sendBlock, peer_id, false, error, ^bool(SOSEngineRef engine, SOSPeerRef peer, CFErrorRef *error) { - return SOSPeerHandleMessage(peer, engine, message, error) != kSOSPeerCoderFailure; - }); -} - - -SOSFullPeerInfoRef SOSCircleGetiCloudFullPeerInfoRef(SOSCircleRef circle) { - __block SOSFullPeerInfoRef cloud_full_peer = NULL; - SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { - if (SOSPeerInfoIsCloudIdentity(peer)) { - if (cloud_full_peer == NULL) { - CFErrorRef localError = NULL; - cloud_full_peer = SOSFullPeerInfoCreateCloudIdentity(kCFAllocatorDefault, peer, &localError); - - if (localError) { - secerror("Found cloud peer in circle but can't make full peer: %@", localError); - CFReleaseNull(localError); - } - - } else { - secerror("More than one cloud identity found in circle: %@", circle); - } - } - }); - return cloud_full_peer; -} - - - diff --git a/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.c b/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.c deleted file mode 100644 index 2e5c4427..00000000 --- a/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright (c) 2012 Apple Computer, 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@ - */ - -// -// SOSCloudCircle.m -// - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Imported/SecItemServer.h" - -#include -#include -#include -#include - -#include - -#include - -#include -#define MINIMIZE_INCLUDES MINIMIZE_INCLUDES -#include "Imported/securityd_client.h" -#include "Imported/spi.h" - -#include "SOSRegressionUtilities.h" - - -const char * kSOSCCCircleChangedNotification = "com.apple.security.secureobjectsync.circlechanged"; - -#define do_if_registered(sdp, ...) if (gSecurityd && gSecurityd->sdp) { return gSecurityd->sdp(__VA_ARGS__); } - -static bool xpc_dictionary_entry_is_type(xpc_object_t dictionary, const char *key, xpc_type_t type) -{ - xpc_object_t value = xpc_dictionary_get_value(dictionary, key); - - return value && (xpc_get_type(value) == type); -} - -SOSCCStatus SOSCCThisDeviceIsInCircle(CFErrorRef *error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_api(SOSCCStatus, ^{ - SOSCCStatus result = kSOSCCError; - - do_if_registered(soscc_ThisDeviceIsInCircle, error); - - xpc_object_t message = securityd_create_message(kSecXPCOpDeviceInCircle, error); - if (message) { - xpc_object_t response = securityd_message_with_reply_sync(message, error); - - if (response && xpc_dictionary_entry_is_type(response, kSecXPCKeyResult, XPC_TYPE_INT64)) { - result = (SOSCCStatus) xpc_dictionary_get_int64(response, kSecXPCKeyResult); - } else { - result = kSOSCCError; - } - - if (result < 0) { - if (response && securityd_message_no_error(response, error)) - { - char *desc = xpc_copy_description(response); - SecCFCreateErrorWithFormat(0, sSecXPCErrorDomain, NULL, error, NULL, CFSTR("Remote error occurred/no info: %s"), desc); - free((void *)desc); - } - } - if(response) - xpc_release(response); - if(message) - xpc_release(message); - } - - - return result; - }, CFSTR("SOSCCStatus=%d")) -} - -static CFStringRef simple_cfstring_error_request(enum SecXPCOperation op, CFErrorRef* error) -{ - __block CFStringRef result = NULL; - - secdebug("sosops","enter - operation: %d", op); - securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) { - const char *c_string = xpc_dictionary_get_string(response, kSecXPCKeyResult); - - if (c_string) { - result = CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8*)c_string, strlen(c_string), kCFStringEncodingUTF8, false); - } - - return c_string != NULL; - }); - return result; -} - -static bool simple_bool_error_request(enum SecXPCOperation op, CFErrorRef* error) -{ - __block bool result = false; - - secdebug("sosops","enter - operation: %d", op); - securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) { - result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); - return result; - }); - return result; -} - -static int simple_int_error_request(enum SecXPCOperation op, CFErrorRef* error) -{ - __block int result = 0; - - secdebug("sosops","enter - operation: %d", op); - securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) { - int64_t temp_result = xpc_dictionary_get_int64(response, kSecXPCKeyResult); - if ((temp_result >= INT32_MIN) && (temp_result <= INT32_MAX)) { - result = (int)temp_result; - } - return result; - }); - return result; -} - -static CFArrayRef array_of_info_error_request(enum SecXPCOperation op, CFErrorRef* error) -{ - __block CFArrayRef result = NULL; - - secdebug("sosops","enter - operation: %d", op); - securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) { - xpc_object_t encoded_array = xpc_dictionary_get_value(response, kSecXPCKeyResult); - if (response && (NULL != encoded_array)) { - result = CreateArrayOfPeerInfoWithXPCObject(encoded_array, error); - } - return result != NULL; - }); - - return result; -} - -static bool info_array_to_bool_error_request(enum SecXPCOperation op, CFArrayRef peer_infos, CFErrorRef* error) -{ - __block bool result = false; - - secdebug("sosops", "enter - operation: %d", op); - securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { - xpc_object_t encoded_peers = CreateXPCObjectWithArrayOfPeerInfo(peer_infos, error); - if (encoded_peers) - xpc_dictionary_set_value(message, kSecXPCKeyPeerInfos, encoded_peers); - return encoded_peers != NULL; - }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { - result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); - return result; - }); - return result; -} - -static bool uint64_t_to_bool_error_request(enum SecXPCOperation op, - uint64_t number, - CFErrorRef* error) -{ - __block bool result = false; - - securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { - xpc_dictionary_set_uint64(message, kSecXPCLimitInMinutes, number); - return true; - }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { - result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); - return result; - }); - - return result; -} - -bool SOSCCRequestToJoinCircle(CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_RequestToJoinCircle, error); - - return simple_bool_error_request(kSecXPCOpRequestToJoin, error); - }, NULL) -} - -bool SOSCCRequestToJoinCircleAfterRestore(CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_RequestToJoinCircleAfterRestore, error); - - return simple_bool_error_request(kSecXPCOpRequestToJoinAfterRestore, error); - }, NULL) -} - -bool SOSCCResetToOffering(CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_ResetToOffering, error); - - return simple_bool_error_request(kSecXPCOpResetToOffering, error); - }, NULL) -} - -bool SOSCCResetToEmpty(CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_ResetToEmpty, error); - - return simple_bool_error_request(kSecXPCOpResetToEmpty, error); - }, NULL) -} - -bool SOSCCRemoveThisDeviceFromCircle(CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_RemoveThisDeviceFromCircle, error); - - return simple_bool_error_request(kSecXPCOpRemoveThisDeviceFromCircle, error); - }, NULL) -} - -bool SOSCCBailFromCircle_BestEffort(uint64_t limit_in_seconds, CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_BailFromCircle, limit_in_seconds, error); - - return uint64_t_to_bool_error_request(kSecXPCOpBailFromCircle, limit_in_seconds, error); - }, NULL) -} - - -CFArrayRef SOSCCCopyPeerPeerInfo(CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_api(CFArrayRef, ^{ - do_if_registered(soscc_CopyPeerInfo, error); - - return array_of_info_error_request(kSecXPCOpCopyPeerPeerInfo, error); - }, CFSTR("return=%@")); -} - -CFArrayRef SOSCCCopyConcurringPeerPeerInfo(CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_api(CFArrayRef, ^{ - do_if_registered(soscc_CopyConcurringPeerInfo, error); - - return array_of_info_error_request(kSecXPCOpCopyConcurringPeerPeerInfo, error); - }, CFSTR("return=%@")); -} - -CFArrayRef SOSCCCopyApplicantPeerInfo(CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_api(CFArrayRef, ^{ - do_if_registered(soscc_CopyApplicantPeerInfo, error); - - return array_of_info_error_request(kSecXPCOpCopyApplicantPeerInfo, error); - }, CFSTR("return=%@")) -} - -bool SOSCCAcceptApplicants(CFArrayRef applicants, CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_AcceptApplicants, applicants, error); - - return info_array_to_bool_error_request(kSecXPCOpAcceptApplicants, applicants, error); - }, NULL) -} - -bool SOSCCRejectApplicants(CFArrayRef applicants, CFErrorRef *error) -{ - sec_trace_enter_api(CFSTR("applicants=%@"), applicants); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_RejectApplicants, applicants, error); - - return info_array_to_bool_error_request(kSecXPCOpRejectApplicants, applicants, error); - }, NULL) -} - -static bool label_and_password_to_bool_error_request(enum SecXPCOperation op, - CFStringRef user_label, CFDataRef user_password, - CFErrorRef* error) -{ - __block bool result = false; - - securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { - CFStringPerformWithCString(user_label, ^(const char *utf8Str) { - xpc_dictionary_set_string(message, kSecXPCKeyUserLabel, utf8Str); - }); - xpc_dictionary_set_data(message, kSecXPCKeyUserPassword, CFDataGetBytePtr(user_password), CFDataGetLength(user_password)); - return true; - }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { - result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); - return result; - }); - - return result; -} - -bool SOSCCRegisterUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error) -{ - return SOSCCSetUserCredentials(user_label, user_password, error); -} - -bool SOSCCSetUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error) -{ - sec_trace_enter_api(CFSTR("user_label=%@"), user_label); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_SetUserCredentials, user_label, user_password, error); - - return label_and_password_to_bool_error_request(kSecXPCOpSetUserCredentials, user_label, user_password, error); - }, NULL) -} - -bool SOSCCTryUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error) -{ - sec_trace_enter_api(CFSTR("user_label=%@"), user_label); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_TryUserCredentials, user_label, user_password, error); - - return label_and_password_to_bool_error_request(kSecXPCOpTryUserCredentials, user_label, user_password, error); - }, NULL) -} - - -bool SOSCCCanAuthenticate(CFErrorRef* error) { - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_CanAuthenticate, error); - - return simple_bool_error_request(kSecXPCOpCanAuthenticate, error); - }, NULL) -} - -bool SOSCCPurgeUserCredentials(CFErrorRef* error) { - sec_trace_enter_api(NULL); - sec_trace_return_bool_api(^{ - do_if_registered(soscc_PurgeUserCredentials, error); - - return simple_bool_error_request(kSecXPCOpPurgeUserCredentials, error); - }, NULL) -} - -enum DepartureReason SOSCCGetLastDepartureReason(CFErrorRef *error) { - sec_trace_enter_api(NULL); - sec_trace_return_api(enum DepartureReason, ^{ - do_if_registered(soscc_GetLastDepartureReason, error); - - return (enum DepartureReason) simple_int_error_request(kSecXPCOpGetLastDepartureReason, error); - }, NULL) -} - -CFStringRef SOSCCCopyIncompatibilityInfo(CFErrorRef* error) { - sec_trace_enter_api(NULL); - sec_trace_return_api(CFStringRef, ^{ - do_if_registered(soscc_CopyIncompatibilityInfo, error); - - return simple_cfstring_error_request(kSecXPCOpCopyIncompatibilityInfo, error); - }, NULL) -} - -SyncWithAllPeersReason SOSCCProcessSyncWithAllPeers(CFErrorRef* error) -{ - sec_trace_enter_api(NULL); - sec_trace_return_api(SyncWithAllPeersReason, ^{ - do_if_registered(soscc_ProcessSyncWithAllPeers, error); - - return (SyncWithAllPeersReason) simple_int_error_request(kSecXPCOpProcessSyncWithAllPeers, error); - }, NULL) -} - -CFStringRef SOSCCGetStatusDescription(SOSCCStatus status) -{ - switch (status) { - case kSOSCCInCircle: - return CFSTR("InCircle"); - case kSOSCCNotInCircle: - return CFSTR("NotInCircle"); - case kSOSCCRequestPending: - return CFSTR("RequestPending"); - case kSOSCCCircleAbsent: - return CFSTR("CircleAbsent"); - case kSOSCCError: - return CFSTR("InternalError"); - case kSOSCCParamErr: - return CFSTR("ParamError"); - case kSOSCCMemoryErr: - return CFSTR("MemoryError"); - - default: - return CFSTR("WTF? Unknown Status"); - }; -} diff --git a/sec/SOSCircle/SecureObjectSync/SOSCloudCircleInternal.h b/sec/SOSCircle/SecureObjectSync/SOSCloudCircleInternal.h deleted file mode 100644 index 0c32d3fe..00000000 --- a/sec/SOSCircle/SecureObjectSync/SOSCloudCircleInternal.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// SOSCloudCircleInternal.h -// -// Created by Mitch Adler on 11/13/12. -// -// - -#ifndef _SECURITY_SOSCLOUDCIRCLEINTERNAL_H_ -#define _SECURITY_SOSCLOUDCIRCLEINTERNAL_H_ - -#include -#include -#include - -CFArrayRef SOSCCCopyConcurringPeerPeerInfo(CFErrorRef* error); - -bool SOSCCPurgeUserCredentials(CFErrorRef* error); - -CFStringRef SOSCCGetStatusDescription(SOSCCStatus status); -SecKeyRef SOSCCGetUserPrivKey(CFErrorRef *error); -SecKeyRef SOSCCGetUserPubKey(CFErrorRef *error); - -/*! - @function SOSCCProcessSyncWithAllPeers - @abstract Returns the information (string, hopefully URL) that will lead to an explanation of why you have an incompatible circle. - @param error What went wrong if we returned NULL. - */ - -SyncWithAllPeersReason SOSCCProcessSyncWithAllPeers(CFErrorRef* error); - -#endif diff --git a/sec/SOSCircle/SecureObjectSync/SOSCoder.c b/sec/SOSCircle/SecureObjectSync/SOSCoder.c deleted file mode 100644 index 7a9eb8ff..00000000 --- a/sec/SOSCircle/SecureObjectSync/SOSCoder.c +++ /dev/null @@ -1,495 +0,0 @@ -// -// SOSCoder.c -// sec -// -// Created by Richard Murphy on 2/6/13. -// -// -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include "AssertMacros.h" - -struct __OpaqueSOSCoder { - CFStringRef peer_id; - SecOTRSessionRef sessRef; - bool waitingForDataPacket; -}; - -static const char *SOSPeerCoderString(SOSPeerCoderStatus coderStatus) { - switch (coderStatus) { - case kSOSPeerCoderDataReturned: return "DataReturned"; - case kSOSPeerCoderNegotiating: return "Negotiating"; - case kSOSPeerCoderNegotiationCompleted: return "NegotiationCompleted"; - case kSOSPeerCoderFailure: return "Failure"; - case kSOSPeerCoderStaleEvent: return "StaleEvent"; - default: return "StatusUnknown"; - } -} - -static size_t der_sizeof_bool(bool value) { - return ccder_sizeof(CCDER_BOOLEAN, 1); -} - -static uint8_t* der_encode_bool(bool value, const uint8_t *der, uint8_t *der_end) { - uint8_t valueByte = value; - return ccder_encode_tl(CCDER_BOOLEAN, 1, der, - ccder_encode_body(1, &valueByte, der, der_end)); -} - -static const uint8_t* der_decode_bool(bool *value, const uint8_t *der, const uint8_t *der_end) { - size_t payload_size = 0; - - der = ccder_decode_tl(CCDER_BOOLEAN, &payload_size, der, der_end); - - if (payload_size != 1) { - der = NULL; - } - - if (der != NULL) { - *value = (*der != 0); - der++; - } - - return der; -} - -static CFMutableDataRef sessSerialized(SOSCoderRef coder, CFErrorRef *error) { - CFMutableDataRef otr_state = NULL; - - if(!coder || !coder->sessRef) { - SOSCreateErrorWithFormat(kSOSErrorUnexpectedType, NULL, error, 0, CFSTR("No session reference.")); - return NULL; - } - - if ((otr_state = CFDataCreateMutable(NULL, 0)) == NULL) { - SOSCreateErrorWithFormat(kSOSErrorAllocationFailure, NULL, error, 0, CFSTR("Mutable Data allocation failed.")); - return NULL; - } - - if (errSecSuccess != SecOTRSAppendSerialization(coder->sessRef, otr_state)) { - SOSCreateErrorWithFormat(kSOSErrorEncodeFailure, NULL, error, 0, CFSTR("Append Serialization failed.")); - CFReleaseSafe(otr_state); - return NULL; - } - - return otr_state; - -} - -static size_t SOSCoderGetDEREncodedSize(SOSCoderRef coder, CFErrorRef *error) { - size_t encoded_size = 0; - CFMutableDataRef otr_state = sessSerialized(coder, error); - - if (otr_state) { - size_t data_size = der_sizeof_data(otr_state, error); - size_t waiting_size = der_sizeof_bool(coder->waitingForDataPacket); - - if ((data_size != 0) && (waiting_size != 0)) - { - encoded_size = ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, data_size + waiting_size); - } - CFReleaseSafe(otr_state); - } - return encoded_size; -} - -static uint8_t* SOSCoderEncodeToDER(SOSCoderRef coder, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) { - if(!der_end) return NULL; - uint8_t* result = NULL; - CFMutableDataRef otr_state = sessSerialized(coder, error); - - if(otr_state) { - result = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, - der_encode_data(otr_state, error, der, - der_encode_bool(coder->waitingForDataPacket, der, der_end))); - CFReleaseSafe(otr_state); - } - return result; -} - - -CFDataRef SOSCoderCopyDER(SOSCoderRef coder, CFErrorRef* error) { - CFMutableDataRef encoded = NULL; - size_t encoded_size = SOSCoderGetDEREncodedSize(coder, error); - - if (encoded_size > 0) { - encoded = CFDataCreateMutable(NULL, encoded_size); - if (encoded) { - CFDataSetLength(encoded, encoded_size); - uint8_t * der = CFDataGetMutableBytePtr(encoded); - uint8_t * der_end = der + encoded_size; - if (!SOSCoderEncodeToDER(coder, error, der, der_end)) { - CFReleaseNull(encoded); - encoded = NULL; - } - } - } - return encoded; -} - -SOSCoderRef SOSCoderCreateFromData(CFDataRef exportedData, CFErrorRef *error) { - - SOSCoderRef p = calloc(1, sizeof(struct __OpaqueSOSCoder)); - - const uint8_t *der = CFDataGetBytePtr(exportedData); - const uint8_t *der_end = der + CFDataGetLength(exportedData); - - CFDataRef otr_data = NULL; - - ccder_tag tag; - require(ccder_decode_tag(&tag, der, der_end),fail); - - switch (tag) { - case CCDER_OCTET_STRING: - { - der = der_decode_data(kCFAllocatorDefault, 0, &otr_data, error, der, der_end); - p->waitingForDataPacket = false; - } - break; - - case CCDER_CONSTRUCTED_SEQUENCE: - { - const uint8_t *sequence_end = NULL; - der = ccder_decode_sequence_tl(&sequence_end, der, der_end); - - require_action_quiet(sequence_end == der_end, fail, SecCFDERCreateError(kSOSErrorDecodeFailure, CFSTR("Extra data in SOS coder"), NULL, error)); - - der = der_decode_data(kCFAllocatorDefault, 0, &otr_data, error, der, der_end); - der = der_decode_bool(&p->waitingForDataPacket, der, sequence_end); - } - break; - - default: - SecCFDERCreateError(kSOSErrorDecodeFailure, CFSTR("Unsupported SOS Coder DER"), NULL, error); - goto fail; - } - - require(der, fail); - - p->sessRef = SecOTRSessionCreateFromData(NULL, otr_data); - require(p->sessRef, fail); - - CFReleaseSafe(otr_data); - return p; - -fail: - SOSCoderDispose(p); - CFReleaseSafe(otr_data); - return NULL; -} - - -SOSCoderRef SOSCoderCreate(SOSPeerInfoRef peerInfo, SOSFullPeerInfoRef myPeerInfo, CFErrorRef *error) { - CFAllocatorRef allocator = CFGetAllocator(peerInfo); - - SOSCoderRef p = calloc(1, sizeof(struct __OpaqueSOSCoder)); - - SecOTRFullIdentityRef myRef = NULL; - SecOTRPublicIdentityRef peerRef = NULL; - SecKeyRef privateKey = NULL; - SecKeyRef publicKey = NULL; - - if (myPeerInfo && peerInfo) { - privateKey = SOSFullPeerInfoCopyDeviceKey(myPeerInfo, error); - require_quiet(privateKey, errOut); - - myRef = SecOTRFullIdentityCreateFromSecKeyRef(allocator, privateKey, error); - require_quiet(myRef, errOut); - - CFReleaseNull(privateKey); - - publicKey = SOSPeerInfoCopyPubKey(peerInfo); - - peerRef = SecOTRPublicIdentityCreateFromSecKeyRef(allocator, publicKey, error); - require_quiet(peerRef, errOut); - - p->sessRef = SecOTRSessionCreateFromID(allocator, myRef, peerRef); - - require(p->sessRef, errOut); - - p->waitingForDataPacket = false; - - CFReleaseNull(publicKey); - CFReleaseNull(privateKey); - CFReleaseNull(myRef); - CFReleaseNull(peerRef); - } else { - secnotice("coder", "NULL Coder requested, no transport security"); - } - - return p; - -errOut: - secerror("Coder create failed: %@\n", *error); - CFReleaseNull(myRef); - CFReleaseNull(peerRef); - CFReleaseNull(publicKey); - CFReleaseNull(privateKey); - - free(p); - return NULL; -} - -void SOSCoderDispose(SOSCoderRef coder) -{ - CFReleaseNull(coder->sessRef); - - free(coder); -} - -void SOSCoderReset(SOSCoderRef coder) -{ - SecOTRSessionReset(coder->sessRef); - coder->waitingForDataPacket = false; -} - -static bool SOSOTRSAppendStartPacket(SecOTRSessionRef session, CFMutableDataRef appendPacket, CFErrorRef *error) { - OSStatus otrStatus = SecOTRSAppendStartPacket(session, appendPacket); - if (otrStatus != errSecSuccess) { - SOSCreateErrorWithFormat(kSOSErrorEncodeFailure, (error != NULL) ? *error : NULL, error, NULL, CFSTR("append start packet returned: %" PRIdOSStatus), otrStatus); - } - return otrStatus == errSecSuccess; -} - -// Start OTR negotiation if we haven't already done so. -SOSPeerCoderStatus -SOSCoderStart(SOSCoderRef coder, SOSPeerSendBlock sendBlock, CFStringRef clientId, CFErrorRef *error) { - CFMutableStringRef action = CFStringCreateMutable(kCFAllocatorDefault, 0); - CFStringRef beginState = NULL; - SOSPeerCoderStatus result = kSOSPeerCoderFailure; - CFMutableDataRef startPacket = NULL; - - require_action_quiet(coder->sessRef, coderFailure, CFStringAppend(action, CFSTR("*** no otr session ***"))); - beginState = CFCopyDescription(coder->sessRef); - require_action_quiet(!coder->waitingForDataPacket, negotiatingOut, CFStringAppend(action, CFSTR("waiting for peer to send first data packet"))); - require_action_quiet(!SecOTRSGetIsReadyForMessages(coder->sessRef), coderFailure, CFStringAppend(action, CFSTR("otr session ready")); - result = kSOSPeerCoderDataReturned); - require_action_quiet(SecOTRSGetIsIdle(coder->sessRef), negotiatingOut, CFStringAppend(action, CFSTR("otr negotiating already"))); - require_action_quiet(startPacket = CFDataCreateMutable(kCFAllocatorDefault, 0), coderFailure, SOSCreateError(kSOSErrorAllocationFailure, CFSTR("alloc failed"), NULL, error)); - require_quiet(SOSOTRSAppendStartPacket(coder->sessRef, startPacket, error), coderFailure); - require_quiet(sendBlock(startPacket, error), coderFailure); - -negotiatingOut: - result = kSOSPeerCoderNegotiating; -coderFailure: - // Uber state log - if (result == kSOSPeerCoderFailure && error && *error) - CFStringAppendFormat(action, NULL, CFSTR(" %@"), *error); - secnotice("coder", "%@ %@ %s %@ %@ returned %s", clientId, beginState, - SecOTRPacketTypeString(startPacket), action, coder->sessRef, SOSPeerCoderString(result)); - CFReleaseNull(startPacket); - CFReleaseSafe(beginState); - CFRelease(action); - - return result; - -} - -SOSPeerCoderStatus -SOSCoderResendDH(SOSCoderRef coder, SOSPeerSendBlock sendBlock, CFErrorRef *error) { - if(coder->sessRef == NULL) return kSOSPeerCoderDataReturned; - - CFMutableDataRef startPacket = CFDataCreateMutable(kCFAllocatorDefault, 0); - if (SecOTRSAppendRestartPacket(coder->sessRef, startPacket)) { - return kSOSPeerCoderFailure; - } - - secnotice("coder", "Resending OTR Start %@", startPacket); - SOSPeerCoderStatus result = sendBlock(startPacket, error) ? kSOSPeerCoderNegotiating : kSOSPeerCoderFailure; - CFReleaseNull(startPacket); - return result; -} - - -static SOSPeerCoderStatus nullCoder(CFDataRef from, CFMutableDataRef *to) { - *to = CFDataCreateMutableCopy(NULL, CFDataGetLength(from), from); - return kSOSPeerCoderDataReturned; -} - -SOSPeerCoderStatus SOSCoderUnwrap(SOSCoderRef coder, SOSPeerSendBlock send_block, - CFDataRef codedMessage, CFMutableDataRef *message, - CFStringRef clientId, - CFErrorRef *error) { - if(codedMessage == NULL) return kSOSPeerCoderDataReturned; - if(coder->sessRef == NULL) return nullCoder(codedMessage, message); - CFMutableStringRef action = CFStringCreateMutable(kCFAllocatorDefault, 0); - /* This should be the "normal" case. We just use OTR to unwrap the received message. */ - SOSPeerCoderStatus result = kSOSPeerCoderFailure; - - CFStringRef beginState = CFCopyDescription(coder->sessRef); - enum SecOTRSMessageKind kind = SecOTRSGetMessageKind(coder->sessRef, codedMessage); - - switch (kind) { - case kOTRNegotiationPacket: { - if(send_block) { - /* If we're in here we haven't completed negotiating a session. Use SecOTRSProcessPacket() to go through - the negotiation steps and immediately send a reply back if necessary using the sendBlock. This - assumes the sendBlock is still available. - */ - CFMutableDataRef response = CFDataCreateMutable(kCFAllocatorDefault, 0); - OSStatus ppstatus = errSecSuccess; - if (response) { - switch (ppstatus = SecOTRSProcessPacket(coder->sessRef, codedMessage, response)) { - case errSecSuccess: - if (CFDataGetLength(response) > 1) { - CFStringAppendFormat(action, NULL, CFSTR("Sending OTR Response %s"), SecOTRPacketTypeString(response)); - if (send_block(response, error)) { - result = kSOSPeerCoderNegotiating; - if (SecOTRSGetIsReadyForMessages(coder->sessRef)) { - CFStringAppend(action, CFSTR(" begin waiting for data packet")); - coder->waitingForDataPacket = true; - } - } else { - secerror("%@ Coder send Error %@", clientId, (CFTypeRef)error); - result = kSOSPeerCoderFailure; - } - } else if(!SecOTRSGetIsReadyForMessages(coder->sessRef)) { - CFStringAppend(action, CFSTR("stuck?")); - result = kSOSPeerCoderNegotiating; - } else { - CFStringAppend(action, CFSTR("completed negotiation")); - result = kSOSPeerCoderNegotiationCompleted; - coder->waitingForDataPacket = false; - } - break; - case errSecDecode: - CFStringAppend(action, CFSTR("resending dh")); - result = SOSCoderResendDH(coder, send_block, error); - break; - default: - SOSCreateErrorWithFormat(kSOSErrorEncodeFailure, (error != NULL) ? *error : NULL, error, NULL, CFSTR("%@ Cannot negotiate session (%ld)"), clientId, (long)ppstatus); - result = kSOSPeerCoderFailure; - break; - }; - } else { - SOSCreateErrorWithFormat(kSOSErrorAllocationFailure, (error != NULL) ? *error : NULL, error, NULL, CFSTR("%@ Cannot allocate CFData"), clientId); - result = kSOSPeerCoderFailure; - } - - CFReleaseNull(response); - } else { - secerror("%@ Can't send, no send_block!!", clientId); - SOSCreateErrorWithFormat(kSOSErrorEncodeFailure, (error != NULL) ? *error : NULL, error, NULL, CFSTR("%@ Cannot negotiate session"), clientId); - result = kSOSPeerCoderFailure; - } - - break; - } - - case kOTRDataPacket: - if(!SecOTRSGetIsReadyForMessages(coder->sessRef)) { - CFStringAppend(action, CFSTR("not ready, resending DH packet")); - SetCloudKeychainTraceValueForKey(kCloudKeychainNumberOfTimesSyncFailed, 1); - CFStringAppend(action, CFSTR("not ready for data; resending dh")); - result = SOSCoderResendDH(coder, send_block, error); - } else { - if (coder->waitingForDataPacket) { - CFStringAppend(action, CFSTR("got data packet we were waiting for ")); - coder->waitingForDataPacket = false; - } - CFMutableDataRef exposed = CFDataCreateMutable(0, 0); - OSStatus otrResult = SecOTRSVerifyAndExposeMessage(coder->sessRef, codedMessage, exposed); - CFStringAppend(action, CFSTR("verify and expose message")); - if (otrResult) { - if (otrResult == errSecOTRTooOld) { - CFStringAppend(action, CFSTR(" too old")); - result = kSOSPeerCoderStaleEvent; - } else { - SecError(otrResult, error, CFSTR("%@ Cannot expose message: %" PRIdOSStatus), clientId, otrResult); - secerror("%@ Decode OTR Protected Packet: %@", clientId, error ? *error : NULL); - result = kSOSPeerCoderFailure; - } - } else { - CFStringAppend(action, CFSTR("decoded OTR protected packet")); - *message = exposed; - exposed = NULL; - result = kSOSPeerCoderDataReturned; - } - CFReleaseNull(exposed); - } - break; - - default: - secerror("%@ Unknown packet type: %@", clientId, codedMessage); - SOSCreateError(kSOSErrorDecodeFailure, CFSTR("Unknown packet type"), (error != NULL) ? *error : NULL, error); - result = kSOSPeerCoderFailure; - break; - }; - - // Uber state log - if (result == kSOSPeerCoderFailure && error && *error) - CFStringAppendFormat(action, NULL, CFSTR(" %@"), *error); - secnotice("coder", "%@ %@ %s %@ %@ returned %s", clientId, beginState, - SecOTRPacketTypeString(codedMessage), action, coder->sessRef, SOSPeerCoderString(result)); - CFReleaseSafe(beginState); - CFRelease(action); - - return result; -} - - -SOSPeerCoderStatus SOSCoderWrap(SOSCoderRef coder, CFDataRef message, CFMutableDataRef *codedMessage, CFStringRef clientId, CFErrorRef *error) { - CFMutableStringRef action = CFStringCreateMutable(kCFAllocatorDefault, 0); - SOSPeerCoderStatus result = kSOSPeerCoderDataReturned; - CFStringRef beginState = NULL; - CFMutableDataRef encoded = NULL; - OSStatus otrStatus = 0; - - require_action_quiet(coder->sessRef, errOut, - CFStringAppend(action, CFSTR("*** using null coder ***")); - result = nullCoder(message, codedMessage)); - beginState = CFCopyDescription(coder->sessRef); - require_action_quiet(SecOTRSGetIsReadyForMessages(coder->sessRef), errOut, - CFStringAppend(action, CFSTR("not ready")); - result = kSOSPeerCoderNegotiating); - require_action_quiet(!coder->waitingForDataPacket, errOut, - CFStringAppend(action, CFSTR("waiting for peer to send data packet first")); - result = kSOSPeerCoderNegotiating); - require_action_quiet(encoded = CFDataCreateMutable(kCFAllocatorDefault, 0), errOut, - SOSCreateErrorWithFormat(kSOSErrorAllocationFailure, NULL, error, NULL, CFSTR("%@ alloc failed"), clientId); - result = kSOSPeerCoderFailure); - require_noerr_action_quiet(otrStatus = SecOTRSSignAndProtectMessage(coder->sessRef, message, encoded), errOut, - SOSCreateErrorWithFormat(kSOSErrorEncodeFailure, (error != NULL) ? *error : NULL, error, NULL, CFSTR("%@ cannot protect message: %" PRIdOSStatus), clientId, otrStatus); - CFReleaseNull(encoded); - result = kSOSPeerCoderFailure); - *codedMessage = encoded; - -errOut: - // Uber state log - if (result == kSOSPeerCoderFailure && error && *error) - CFStringAppendFormat(action, NULL, CFSTR(" %@"), *error); - secnotice("coder", "%@ %@ %s %@ %@ returned %s", clientId, beginState, - SecOTRPacketTypeString(encoded), action, coder->sessRef, SOSPeerCoderString(result)); - CFReleaseSafe(beginState); - CFRelease(action); - - return result; -} - -bool SOSCoderCanWrap(SOSCoderRef coder) { - return coder->sessRef && SecOTRSGetIsReadyForMessages(coder->sessRef) && !coder->waitingForDataPacket; -} diff --git a/sec/SOSCircle/SecureObjectSync/SOSCoder.h b/sec/SOSCircle/SecureObjectSync/SOSCoder.h deleted file mode 100644 index 28e178ba..00000000 --- a/sec/SOSCircle/SecureObjectSync/SOSCoder.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// SOSCoder.h -// sec -// -// Created by Richard Murphy on 2/6/13. -// -// - -#ifndef sec_SOSCoder_h -#define sec_SOSCoder_h - -#include -#include -#include - -typedef struct __OpaqueSOSCoder *SOSCoderRef; - -SOSCoderRef SOSCoderCreate(SOSPeerInfoRef peerInfo, SOSFullPeerInfoRef myPeerInfo, CFErrorRef *error); -SOSCoderRef SOSCoderCreateFromData(CFDataRef exportedData, CFErrorRef *error); - -void SOSCoderDispose(SOSCoderRef coder); - -CFDataRef SOSCoderCopyDER(SOSCoderRef coder, CFErrorRef* error); - -SOSPeerCoderStatus -SOSCoderStart(SOSCoderRef coder, SOSPeerSendBlock sendBlock, CFStringRef clientId, CFErrorRef *error); - -SOSPeerCoderStatus -SOSCoderResendDH(SOSCoderRef coder, SOSPeerSendBlock sendBlock, CFErrorRef *error); - -void SOSCoderPersistState(CFStringRef peer_id, SOSCoderRef coder); - -SOSPeerCoderStatus SOSCoderUnwrap(SOSCoderRef coder, SOSPeerSendBlock send_block, CFDataRef codedMessage, CFMutableDataRef *message, CFStringRef clientId, CFErrorRef *error); - -SOSPeerCoderStatus SOSCoderWrap(SOSCoderRef coder, CFDataRef message, CFMutableDataRef *codedMessage, CFStringRef clientId, CFErrorRef *error); - -bool SOSCoderCanWrap(SOSCoderRef coder); - -void SOSCoderReset(SOSCoderRef coder); - -#endif diff --git a/sec/SOSCircle/SecureObjectSync/SOSEngine.c b/sec/SOSCircle/SecureObjectSync/SOSEngine.c deleted file mode 100644 index aab5bffb..00000000 --- a/sec/SOSCircle/SecureObjectSync/SOSEngine.c +++ /dev/null @@ -1,932 +0,0 @@ -/* - * Created by Michael Brouwer on 7/17/12. - * Copyright 2012 Apple Inc. All Rights Reserved. - */ - -/* - * SOSEngine.c - Implementation of a secure object syncing engine - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* DataSource helper macros and functions. */ - -// TODO: Change to create with DER. -#define SOSObjectCreateWithPropertyList(dataSource, plist, error) (dataSource->createWithPropertyList(dataSource, plist, error)) - -#define SOSObjectCopyPropertyList(dataSource, object, error) (dataSource->copyPropertyList(object, error)) -#define SOSObjectCopyDigest(dataSource, object, error) (dataSource->copyDigest(object, error)) -#define SOSObjectCopyPrimaryKey(dataSource, object, error) (dataSource->copyPrimaryKey(object, error)) -#define SOSObjectCopyMergedObject(dataSource, object1, object2, error) (dataSource->copyMergedObject(object1, object2, error)) - -#define kSOSMaxObjectPerMessage (500) - -static CFArrayRef SOSDataSourceCopyObjectArray(SOSDataSourceRef data_source, SOSManifestRef manifest, CFErrorRef *error) { - CFMutableArrayRef objects = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks); - - // Delta sync by only sending a max of kSOSMaxObjectPerMessage objects at a time. - SOSManifestRef toSend = NULL; - if (SOSManifestGetCount(manifest) > kSOSMaxObjectPerMessage) { - toSend = SOSManifestCreateWithBytes(SOSManifestGetBytePtr(manifest), kSOSMaxObjectPerMessage * SOSDigestSize, error); - } else { - toSend = manifest; - CFRetain(toSend); - } - - if (!data_source->foreach_object(data_source, toSend, error, ^bool (SOSObjectRef object, CFErrorRef *localError) { - CFDictionaryRef plist = SOSObjectCopyPropertyList(data_source, object, localError); - if (plist) { - CFArrayAppendValue(objects, plist); - CFRelease(plist); - } - return plist; - })) { - CFReleaseNull(objects); - } - CFRetainSafe(toSend); - return objects; -} - -static CFDataRef SOSDataSourceCopyManifestDigest(SOSDataSourceRef ds, CFErrorRef *error) { - CFMutableDataRef manifestDigest = CFDataCreateMutable(0, SOSDigestSize); - CFDataSetLength(manifestDigest, SOSDigestSize); - if (!ds->get_manifest_digest(ds, CFDataGetMutableBytePtr(manifestDigest), error)) - CFReleaseNull(manifestDigest); - - return manifestDigest; -} - -static SOSManifestRef SOSDataSourceCopyManifest(SOSDataSourceRef ds, CFErrorRef *error) { - return ds->copy_manifest(ds, error); -} - -static void SOSDataSourceRelease(SOSDataSourceRef ds) { - ds->release(ds); -} - - -/* SOSEngine implementation. */ - -static CFStringRef sErrorDomain = CFSTR("com.apple.security.sos.engine.error"); - -static bool SOSEngineCreateError(CFIndex errorCode, CFStringRef descriptionString, CFErrorRef previousError, CFErrorRef *newError) { - SecCFCreateError(errorCode, descriptionString, sErrorDomain, previousError, newError); - return true; -} - -struct __OpaqueSOSEngine { - SOSDataSourceRef dataSource; -}; - -SOSEngineRef SOSEngineCreate(SOSDataSourceRef dataSource, CFErrorRef *error) { - SOSEngineRef engine = calloc(1, sizeof(struct __OpaqueSOSEngine)); - engine->dataSource = dataSource; - - return engine; -} - -void SOSEngineDispose(SOSEngineRef engine) { - SOSDataSourceRelease(engine->dataSource); - free(engine); -} - -/* SOSEngine. */ -enum SOSMessageType { - SOSManifestInvalidMessageType = 0, - SOSManifestDigestMessageType = 1, - SOSManifestMessageType = 2, - SOSManifestDeltaAndObjectsMessageType = 3, -}; - -/* H(): SHA1 hash function. - M: Manifest of peer p - MSG: H(M). - - - SOSPeerMessage := SEQUENCE { - messageType INTEGER (manifestDigest, manifest, manifestDeltaAndObjects) - version INTEGER OPTIONAL default v0 - content ANY defined by messageType - } - - ManifestDigest := OCTECT STRING (length 20) - Manifest := OCTECT STRING (length 20 * number of entries) - - - Value := CHOICE { - bool Boolean - number INTEGER - string UTF8String - data OCTECT STRING - date GENERAL TIME - dictionary Object - array Array - } - - KVPair := SEQUENCE { - key UTF8String - value Value - } - - Array := SEQUENCE of Value - Dictionary := SET of KVPair - - Object := SEQUENCE { - [0] conflict OCTECT STRING OPTIONAL - [1] change OCTECT STRING OPTIONAL - object Dictionary - - - ManifestDeltaAndObjects := SEQUENCE { - manfestDigest ManifestDigest - removals Manifest - additions Manifest - addedObjects SEQUENCE of Object - } - - manifestDigest content = OCTECT STRING - manifest content := OCTECT STRING - manifestDeltaAndObjects := SEQUENCE { - manfestDigest ManifestDigest - } - - */ - - -/* ManifestDigest message */ -static size_t der_sizeof_manifest_digest_message(void) { - return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, - (ccder_sizeof_uint64(SOSManifestDigestMessageType) + - ccder_sizeof_raw_octet_string(SOSDigestSize))); -} - -static uint8_t *der_encode_manifest_digest_message(const uint8_t digest[SOSDigestSize], const uint8_t *der, uint8_t *der_end) { - return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, - ccder_encode_uint64(SOSManifestDigestMessageType, der, - ccder_encode_raw_octet_string(SOSDigestSize, digest, der, der_end))); -} - -/* This message is sent to each peer that joins a circle and can also be sent - as a form of ACK to confirm that the local peer is in sync with the peer - this is beig sent to. */ -CFDataRef SOSEngineCreateManifestDigestMessage(SOSEngineRef engine, SOSPeerRef peer, CFErrorRef *error) { - /* TODO: avoid copying the digest here by inlining der_encode_manifest_digest_message(). */ - - uint8_t digest[SOSDigestSize]; - if (!engine->dataSource->get_manifest_digest(engine->dataSource, &digest[0], error)) { - return NULL; - } - - size_t der_size = der_sizeof_manifest_digest_message(); - CFMutableDataRef message = CFDataCreateMutable(NULL, der_size); - if (message == NULL) { - return NULL; - } - CFDataSetLength(message, der_size); - uint8_t *der_end = CFDataGetMutableBytePtr(message); - const uint8_t *der = der_end; - der_end += der_size; - - der_end = der_encode_manifest_digest_message(digest, der, der_end); - assert(der == der_end); - - return message; -} - - -/* Manifest message */ -static size_t der_sizeof_manifest_message(SOSManifestRef manifest) { - return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, - (ccder_sizeof_uint64(SOSManifestMessageType) + - ccder_sizeof_raw_octet_string(SOSManifestGetSize(manifest)))); -} - -static uint8_t *der_encode_manifest_message(SOSManifestRef manifest, const uint8_t *der, uint8_t *der_end) { - return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, - ccder_encode_uint64(SOSManifestMessageType, der, - ccder_encode_raw_octet_string(SOSManifestGetSize(manifest), - SOSManifestGetBytePtr(manifest), der, der_end))); -} - -/* This message is sent in response to a manifestDigest if our manifestDigest - differs from that of the received manifestDigest, or in response to a - manifestAndObjects message if the manifestDigest in the received message - doesn't match our own manifestDigest. */ -CFDataRef SOSEngineCreateManifestMessage(SOSEngineRef engine, SOSPeerRef peer, CFErrorRef *error) { - SOSManifestRef manifest = SOSDataSourceCopyManifest(engine->dataSource, error); - if (!manifest) - return NULL; - - size_t der_size = der_sizeof_manifest_message(manifest); - CFMutableDataRef message = CFDataCreateMutable(NULL, der_size); - CFDataSetLength(message, der_size); - uint8_t *der_end = CFDataGetMutableBytePtr(message); - const uint8_t *der = der_end; - der_end += der_size; - - der_end = der_encode_manifest_message(manifest, der, der_end); - assert(der == der_end); - - return message; -} - - -/* ManifestDeltaAndObjects message */ -static size_t der_sizeof_manifest_and_objects_message(SOSManifestRef removals, SOSManifestRef additions, CFArrayRef objects, CFErrorRef *error) { - size_t objects_size = der_sizeof_plist(objects, error); - if (objects_size == 0) - return objects_size; - - return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, - (ccder_sizeof_uint64(SOSManifestDeltaAndObjectsMessageType) + - ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, - (ccder_sizeof_raw_octet_string(SOSDigestSize) + - ccder_sizeof_raw_octet_string(SOSManifestGetSize(removals)) + - ccder_sizeof_raw_octet_string(SOSManifestGetSize(additions)) + - objects_size)))); -} - -static uint8_t *der_encode_manifest_and_objects_message(CFDataRef digest, SOSManifestRef removals, SOSManifestRef additions, CFArrayRef objects, CFErrorRef *error, const uint8_t *der, uint8_t *der_end) { - assert(CFDataGetLength(digest) == SOSDigestSize); - return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, - ccder_encode_uint64(SOSManifestDeltaAndObjectsMessageType, der, - ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, - ccder_encode_raw_octet_string(SOSDigestSize, CFDataGetBytePtr(digest), der, - ccder_encode_raw_octet_string(SOSManifestGetSize(removals), SOSManifestGetBytePtr(removals), der, - ccder_encode_raw_octet_string(SOSManifestGetSize(additions), SOSManifestGetBytePtr(additions), der, - der_encode_plist(objects, error, der, der_end))))))); -} - -/* This message is sent in response to a local change that needs to be - propagated to our peers or in response to a manifest or manifestDigest - message from a peer that is not in sync with us yet. */ -CFDataRef SOSEngineCreateManifestAndObjectsMessage(SOSEngineRef engine, SOSPeerRef peer, CFErrorRef *error) { - /* Assumptions: - peer has a manifest that corresponds to peers real manifest. - we send everything in our datasource that's not in peers manifest already to peer. - */ - CFMutableDataRef message = NULL; - SOSManifestRef manifest, peerManifest, additions, removals; - -retry: - manifest = SOSDataSourceCopyManifest(engine->dataSource, error); - if (!manifest) - goto errOut4; - - peerManifest = SOSPeerCopyManifest(peer, error); - if (!peerManifest) - goto errOut3; - - if (!SOSManifestDiff(manifest, peerManifest, &additions, &removals, error)) - goto errOut2; - - CFErrorRef localError = NULL; - CFArrayRef objects = SOSDataSourceCopyObjectArray(engine->dataSource, additions, &localError); - if (!objects) { - if(SecErrorGetOSStatus(localError)==errSecDecode) { - secnotice("engine", "Corrupted item found: %@", localError); - CFReleaseNull(manifest); - CFReleaseNull(additions); - CFReleaseNull(removals); - CFReleaseNull(peerManifest); - CFReleaseNull(localError); - goto retry; - } - if(error && *error==NULL) - *error=localError; - else - CFReleaseNull(localError); - goto errOut1; - } - - size_t der_size = der_sizeof_manifest_and_objects_message(removals, additions, objects, error); - if (der_size == 0) - goto errOut0; - - /* TODO: avoid copying the digest here by inlining der_encode_manifest_and_objects_message(). */ - CFDataRef peerDigest = SOSPeerCopyManifestDigest(peer, error); - if (!peerDigest) - goto errOut0; - - message = CFDataCreateMutable(NULL, der_size); - CFDataSetLength(message, der_size); - uint8_t *der_end = CFDataGetMutableBytePtr(message); - const uint8_t *der = der_end; - der_end += der_size; - - der_end = der_encode_manifest_and_objects_message(peerDigest, removals, additions, objects, error, der, der_end); - assert(der == der_end); - if (der_end == NULL) { - CFReleaseNull(message); - goto errOut_; - } - - /* Record the peers new manifest assuming that peer will accept all the - changes we are about to send them. */ - SOSPeerSetManifest(peer, manifest, error); - -errOut_: - CFRelease(peerDigest); -errOut0: - CFRelease(objects); -errOut1: - SOSManifestDispose(removals); - SOSManifestDispose(additions); -errOut2: - SOSManifestDispose(peerManifest); -errOut3: - SOSManifestDispose(manifest); -errOut4: - - return message; -} - -static const uint8_t *der_decode_msg_type(enum SOSMessageType *msg_type, - const uint8_t *der, - const uint8_t *der_end, - CFErrorRef *error) { - const uint8_t *body_end; - der = ccder_decode_sequence_tl(&body_end, der, der_end); - if (!der) - return NULL; - - if (body_end != der_end) { - SOSEngineCreateError(kSOSEngineInvalidMessageError, CFSTR("Trailing garbage at end of message"), NULL, error); - return NULL; - } - - uint64_t msgType; - der = ccder_decode_uint64(&msgType, der, der_end); - if (msgType < 1 || msgType > SOSManifestDeltaAndObjectsMessageType) { - SecCFCreateErrorWithFormat(kSOSEngineInvalidMessageError, sErrorDomain, - NULL, error, NULL, - CFSTR("Bad message type: %llu"), msgType); - return NULL; - } - *msg_type = (enum SOSMessageType)msgType; - return der; -} - -static const uint8_t * -der_decode_manifest_digest(CFDataRef *digest, CFErrorRef *error, - const uint8_t *der, const uint8_t *der_end) { - require_quiet(der, errOut); - size_t len; - der = ccder_decode_tl(CCDER_OCTET_STRING, &len, der, der_end); - require_action_quiet(der, errOut, SOSEngineCreateError(kSOSEngineInvalidMessageError, CFSTR("Failed to find string"), NULL, error)); - require_action_quiet(len == SOSDigestSize, errOut, SOSEngineCreateError(kSOSEngineInvalidMessageError, CFSTR("Invalid digest size"), NULL, error)); - - *digest = CFDataCreate(0, der, len); - require_action_quiet(*digest, errOut, SOSEngineCreateError(kSOSEngineInvalidMessageError, CFSTR("Failed to create digest"), NULL, error)); - - der += len; - require_action_quiet(der, errOut, CFReleaseNull(*digest); SOSEngineCreateError(kSOSEngineInvalidMessageError, CFSTR("Failed to find string"), NULL, error)); - - return der; - -errOut: - return NULL; -} - -static const uint8_t * -der_decode_manifest(SOSManifestRef *manifest, CFErrorRef *error, - const uint8_t *der, const uint8_t *der_end) { - if (!der) - goto errOut; - size_t len; - der = ccder_decode_tl(CCDER_OCTET_STRING, &len, der, der_end); - if (!der) { - SOSEngineCreateError(kSOSEngineInvalidMessageError, CFSTR("Failed to decode manifest"), NULL, error); - goto errOut; - } - if (len % SOSDigestSize != 0) { - SOSEngineCreateError(kSOSEngineInvalidMessageError, CFSTR("manifest not a multiple of digest size"), NULL, error); - goto errOut; - } - *manifest = SOSManifestCreateWithBytes(der, len, error); - if (!*manifest) - goto errOut; - - return der += len; - -errOut: - return NULL; -} - -static const uint8_t * -der_decode_manifest_digest_message(CFDataRef *digest, CFErrorRef *error, - const uint8_t *der, const uint8_t *der_end) { - der = der_decode_manifest_digest(digest, error, der, der_end); - if (der && der != der_end) { - SOSEngineCreateError(kSOSEngineInvalidMessageError, CFSTR("Trailing garbage after digest"), NULL, error); - CFReleaseNull(*digest); - der = NULL; - } - return der; -} - -static const uint8_t * -der_decode_manifest_message(SOSManifestRef *manifest, CFErrorRef *error, - const uint8_t *der, const uint8_t *der_end) { - der = der_decode_manifest(manifest, error, der, der_end); - if (der && der != der_end) { - SOSEngineCreateError(kSOSEngineInvalidMessageError, CFSTR("Trailing garbage after manifest"), NULL, error); - SOSManifestDispose(*manifest); - *manifest = NULL; - der = NULL; - } - return der; -} - -static const uint8_t * -der_decode_manifest_and_objects_message(CFDataRef *peerManifestDigest, - SOSManifestRef *removals, - SOSManifestRef *additions, - CFArrayRef *objects, - CFErrorRef *error, const uint8_t *der, - const uint8_t *der_end) { - const uint8_t *body_end; - der = ccder_decode_sequence_tl(&body_end, der, der_end); - if (!der) { - SOSEngineCreateError(kSOSEngineInvalidMessageError, CFSTR("Failed to decode top level sequence"), NULL, error); - goto errOut; - } - - if (body_end != der_end) { - SOSEngineCreateError(kSOSEngineInvalidMessageError, CFSTR("Trailing garbage at end of message"), NULL, error); - goto errOut; - } - - der = der_decode_manifest_digest(peerManifestDigest, error, der, der_end); - if (!der) - goto errOut; - der = der_decode_manifest(removals, error, der, der_end); - if (!der) - goto errOut1; - der = der_decode_manifest(additions, error, der, der_end); - if (!der) - goto errOut2; - - CFPropertyListRef pl; - der = der_decode_plist(0, 0, &pl, error, der, der_end); - if (!der) - goto errOut3; - - if (der != der_end) { - SOSEngineCreateError(kSOSEngineInvalidMessageError, CFSTR("Trailing garbage at end of message body"), NULL, error); - goto errOut4; - } - - // TODO Check that objects is in fact an array. */ - if (CFArrayGetTypeID() != CFGetTypeID(pl)) { - SOSEngineCreateError(kSOSEngineInvalidMessageError, CFSTR("objects is not an array"), NULL, error); - goto errOut4; - } - *objects = pl; - - return der; - -errOut4: - CFRelease(pl); -errOut3: - CFRelease(additions); -errOut2: - CFRelease(removals); -errOut1: - CFRelease(peerManifestDigest); -errOut: - return NULL; -} - - -#if 0 -enum SOSMessageType SOSMessageGetType(CFDataRef message) { - const uint8_t *der = CFDataGetBytePtr(message); - const uint8_t *der_end = der + CFDataGetLength(message); - enum SOSMessageType msg_type; - der_decode_msg_type(&msg_type, der, der_end, NULL); - if (!der) { - return SOSManifestInvalidMessageType; - } - - return msg_type; -} -#endif - -/* H(): SHA1 hash function. - M: Manifest of peer p - MSG: H(M) */ -static CFDataRef SOSEngineCopyManifestDigestReply(SOSEngineRef engine, - SOSPeerRef peer, - CFDataRef digest, - CFErrorRef *error) { - CFDataRef reply = NULL; - CFDataRef peerDigest = SOSPeerCopyManifestDigest(peer, NULL); - CFDataRef manifestDigest = SOSDataSourceCopyManifestDigest(engine->dataSource, error); - if (manifestDigest) { - if (CFEqual(manifestDigest, digest)) { - /* Our dataSources manifest and that of the peer are equal, we are in sync. */ - if (peerDigest && CFEqual(peerDigest, digest)) { - /* The last known digest we had for peer already matched the digest peer - sent us, so this message is redundant, consider it an ack of our last - message to peer. */ - reply = CFDataCreate(kCFAllocatorDefault, NULL, 0); - } else { - /* Our peer just sent us a manifest digest that matches our own, but the digest - we have for the peer (if any) doesn't match that. Peer must have the same - manifest we do, so record that. */ - SOSManifestRef manifest = SOSDataSourceCopyManifest(engine->dataSource, error); - if (manifest) { - bool ok = SOSPeerSetManifest(peer, manifest, error); - SOSManifestDispose(manifest); - if (ok) { - /* Since we got lucky and happen to have the same digest as our peer, we - send back an ack to ensure our peer ends up knowning our manifest as well. */ - reply = SOSEngineCreateManifestDigestMessage(engine, peer, error); - } - } - } - } else if (peerDigest && CFEqual(peerDigest, digest)) { - /* We know peer's current manifest is correct (the computed digest - matches the passed in one) but peer and our dataSource - are not in sync. Send the deltas to peer. */ - reply = SOSEngineCreateManifestAndObjectsMessage(engine, peer, error); - } else { - /* Our peer has no digest yet, or the manifestDigest peer just sent - us doesn't match the digest of the manifest we think peer has. - We need to get peer to tell us their manifest, to do so we sent - it ours and hope it responds with deltas. */ - reply = SOSEngineCreateManifestMessage(engine, peer, error); - } - CFRelease(manifestDigest); - } - CFReleaseSafe(peerDigest); - return reply; -} - -/* M: Manifest of peer p - MSG: M */ -static CFDataRef SOSEngineCopyManifestReply(SOSEngineRef engine, SOSPeerRef peer, - SOSManifestRef manifest, - CFErrorRef *error) { - CFDataRef reply = NULL; - // Peer just told us what his manifest was. Let's roll with it. - SOSPeerSetManifest(peer, manifest, error); - CFDataRef peerManifestDigest = SOSPeerCopyManifestDigest(peer, error); - if (peerManifestDigest) { - CFDataRef manifestDigest = SOSDataSourceCopyManifestDigest(engine->dataSource, error); - if (manifestDigest) { - if (CFEqual(peerManifestDigest, manifestDigest)) { - /* We're in sync, optionally send peer an ack. */ - reply = SOSEngineCreateManifestDigestMessage(engine, peer, error); - } else { - /* Send peer the objects it is missing from our manifest. */ - reply = SOSEngineCreateManifestAndObjectsMessage(engine, peer, error); - } - CFRelease(manifestDigest); - } - CFRelease(peerManifestDigest); - } - return reply; -} - -static bool SOSEngineProccesObjects(SOSEngineRef engine, - SOSPeerRef peer, - CFDataRef digest, - SOSManifestRef removals, - SOSManifestRef additions, - CFArrayRef objects, - CFErrorRef *error) { - __block bool result = true; - CFArrayForEach(objects, ^(const void *value) { - SOSObjectRef ob = SOSObjectCreateWithPropertyList(engine->dataSource, value, error); - if (ob) { - SOSMergeResult mr = engine->dataSource->add(engine->dataSource, ob, error); - if (!mr) { - result = false; - // assertion failure, duplicate object added during transaction, that wasn't explicitly listed in removal list. - // treat as conflict? - // oa = ds->lookup(pkb); - // ds->choose_between(oa, ob) - // TODO: This is needed is we want to allow conflicts with other circles. - SetCloudKeychainTraceValueForKey(kCloudKeychainNumberOfTimesSyncFailed, 1); - secerror("assertion failure, add failed: %@", - error ? *error : (CFErrorRef)CFSTR("error is null")); - } - CFRelease(ob); - } - }); - return result; -} - -/* H(): SHA1 hash function. - L: Manifest of local peer. - M: Manifest of peer p. - M-L: Manifest of entries in M but not in L - L-M: Manifest of entries in L but not in M - O(M): Objects in manifest M - MSG: H(L) || L-M || M-L || O(M-L) */ -static CFDataRef SOSEngineCopyManifestAndObjectsReply(SOSEngineRef engine, - SOSPeerRef peer, - CFDataRef digest, - SOSManifestRef removals, - SOSManifestRef additions, - CFArrayRef objects, - CFErrorRef *error) { - CFDataRef reply = NULL; - CFMutableDataRef manifestDigest = (CFMutableDataRef)SOSDataSourceCopyManifestDigest(engine->dataSource, error); - if (manifestDigest) { - SOSManifestRef manifest = SOSDataSourceCopyManifest(engine->dataSource, error); - - /* Always proccess the objects after we snapshot our manifest. */ - if (!SOSEngineProccesObjects(engine, peer, digest, removals, additions, objects, error)) { - secerror("peer: %@ SOSEngineProccesObjects(): %@", SOSPeerGetID(peer), *error); - } - - if (CFEqual(manifestDigest, digest)) { - SOSManifestRef peerManifest = NULL; - if (manifest) { - peerManifest = SOSManifestCreateWithPatch(manifest, removals, additions, error); - } - if (peerManifest) { - if (SOSPeerSetManifest(peer, peerManifest, error)) { - /* Now proccess the objects. */ - if (!SOSEngineProccesObjects(engine, peer, digest, removals, additions, objects, error)) { - secerror("peer: %@ SOSEngineProccesObjects(): %@", SOSPeerGetID(peer), *error); - } - - CFDataRef peerDigest = SOSPeerCopyManifestDigest(peer, error); - if (peerDigest) { - /* Depending on whether after proccess objects we still have objects that need to be sent back to peer we respond with our digestManifest or with a manifestAndObjectsMessage. */ - if (engine->dataSource->get_manifest_digest(engine->dataSource, CFDataGetMutableBytePtr(manifestDigest), error)) { - if (CFEqual(manifestDigest, peerDigest)) { - reply = SOSEngineCreateManifestDigestMessage(engine, peer, error); - } else { - reply = SOSEngineCreateManifestAndObjectsMessage(engine, peer, error); - } - } - CFRelease(peerDigest); - } - } - CFRelease(peerManifest); - } else { - secerror("Received peer: %@ sent bad message: %@", SOSPeerGetID(peer), *error); - /* We failed to compute peer's digest, let's tell him ours again and hope for a retransmission. */ - /* TODO: Perhaps this should be sent by the top level whenever an error occurs during parsing. */ - reply = SOSEngineCreateManifestDigestMessage(engine, peer, error); - } - } else { - /* ds->manifestDigest != msg->manigestDigest => We received deltas - against a manifest we don't have respond with our current - manifest to get back in sync. */ - reply = SOSEngineCreateManifestMessage(engine, peer, error); - } - CFReleaseSafe(manifest); - CFRelease(manifestDigest); - } - return reply; -} - -/* Handle incoming message from peer p. Return false if there was an error, true otherwise. */ -bool SOSEngineHandleMessage(SOSEngineRef engine, SOSPeerRef peer, - CFDataRef message, CFErrorRef *error) { - CFDataRef reply = NULL; - SOSManifestRef oldPeerManifest = SOSPeerCopyManifest(peer, NULL); - const uint8_t *der = CFDataGetBytePtr(message); - const uint8_t *der_end = der + CFDataGetLength(message); - enum SOSMessageType msgType; - - der = der_decode_msg_type(&msgType, der, der_end, error); - if (der) switch (msgType) { - case SOSManifestDigestMessageType: - { - CFDataRef digest = NULL; // Make the static analyzer happy by NULL and Release safe - der = der_decode_manifest_digest_message(&digest, error, der, der_end); - if (der) { - reply = SOSEngineCopyManifestDigestReply(engine, peer, digest, error); - } - CFReleaseSafe(digest); - break; - } - case SOSManifestMessageType: - { - SOSManifestRef manifest; - der = der_decode_manifest_message(&manifest, error, der, der_end); - if (der) { - reply = SOSEngineCopyManifestReply(engine, peer, manifest, error); - SOSManifestDispose(manifest); - } - break; - } - case SOSManifestDeltaAndObjectsMessageType: - { - CFDataRef peerManifestDigest; - SOSManifestRef removals; - SOSManifestRef additions; - CFArrayRef objects; - der = der_decode_manifest_and_objects_message(&peerManifestDigest, &removals, &additions, &objects, error, der, der_end); - if (der) { - reply = SOSEngineCopyManifestAndObjectsReply(engine, peer, peerManifestDigest, removals, additions, objects, error); - CFRelease(peerManifestDigest); - SOSManifestDispose(removals); - SOSManifestDispose(additions); - CFRelease(objects); - } - break; - } - default: - SecCFCreateErrorWithFormat(kSOSEngineInvalidMessageError, sErrorDomain, - NULL, error, NULL, CFSTR("Invalid message type %d"), msgType); - break; - } - - bool ok = reply; - if (reply && CFDataGetLength(reply)) { - ok = SOSPeerSendMessage(peer, reply, error); - if (!ok) - SOSPeerSetManifest(peer, oldPeerManifest, NULL); - } - secnotice("engine", "%@", SOSPeerGetID(peer)); - CFReleaseSafe(oldPeerManifest); - CFReleaseSafe(reply); - return ok; -} - -bool SOSEngineSyncWithPeer(SOSEngineRef engine, SOSPeerRef peer, bool force, - CFErrorRef *error) { - CFDataRef reply = NULL; - SOSManifestRef oldPeerManifest = SOSPeerCopyManifest(peer, NULL); - bool ok = true; - require_quiet(SOSPeerCanSendMessage(peer), exit); - CFDataRef peerDigest = SOSPeerCopyManifestDigest(peer, NULL); - CFMutableDataRef manifestDigest = CFDataCreateMutable(0, SOSDigestSize); - CFDataSetLength(manifestDigest, SOSDigestSize); - if (engine->dataSource->get_manifest_digest(engine->dataSource, CFDataGetMutableBytePtr(manifestDigest), error)) { - if (peerDigest) { - if (CFEqual(peerDigest, manifestDigest)) { - /* We are in sync with peer already. */ - if (force) { - /* If we are at the end of the OTR handshake, we have to send - something to our peer no matter what to break the symmmetry. */ - reply = SOSEngineCreateManifestDigestMessage(engine, peer, error); - } else { - reply = CFDataCreate(kCFAllocatorDefault, NULL, 0); - } - } else { - /* We have have a digest for peer's manifest and it doesn't - match our current digest, so send deltas to peer. */ - reply = SOSEngineCreateManifestAndObjectsMessage(engine, peer, error); - } - } else { - /* We have no digest for peer yet, send our manifest digest to peer, - it should respond with it's manifest so we can sync. */ - reply = SOSEngineCreateManifestDigestMessage(engine, peer, error); - } - } - CFRelease(manifestDigest); - CFReleaseSafe(peerDigest); - - ok = ok && reply; - if (ok && CFDataGetLength(reply)) { - ok = SOSPeerSendMessage(peer, reply, error); - if (!ok) - SOSPeerSetManifest(peer, oldPeerManifest, NULL); - } - -exit: - secnotice("engine", "%@", SOSPeerGetID(peer)); - CFReleaseSafe(oldPeerManifest); - CFReleaseSafe(reply); - return ok; -} - -#if 0 -static void appendObject(CFMutableStringRef desc, CFDictionaryRef object) { - __block bool needComma = false; - CFDictionaryForEach(object, ^(const void *key, const void *value) { - if (needComma) - CFStringAppend(desc, CFSTR(",")); - else - needComma = true; - - CFStringAppend(desc, key); - CFStringAppend(desc, CFSTR("=")); - if (CFEqual(CFSTR("data"), key)) { - CFStringAppend(desc, CFSTR("")); - } else if (isData(value)) { - CFStringAppendHexData(desc, value); - } else { - CFStringAppendFormat(desc, 0, CFSTR("%@"), value); - } - }); -} -#endif - -static void appendObjects(CFMutableStringRef desc, CFArrayRef objects) { - __block bool needComma = false; - CFArrayForEach(objects, ^(const void *value) { - if (needComma) - CFStringAppend(desc, CFSTR(",")); - else - needComma = true; - - SecItemServerAppendItemDescription(desc, value); - }); -} - -CFStringRef SOSMessageCopyDescription(CFDataRef message) { - if (!message) - return CFSTR(""); - - CFMutableStringRef desc = CFStringCreateMutable(0, 0); - const uint8_t *der = CFDataGetBytePtr(message); - const uint8_t *der_end = der + CFDataGetLength(message); - enum SOSMessageType msgType; - - CFStringAppend(desc, CFSTR("")); - - return desc; -} diff --git a/sec/SOSCircle/SecureObjectSync/SOSEngine.h b/sec/SOSCircle/SecureObjectSync/SOSEngine.h deleted file mode 100644 index cc63bbf7..00000000 --- a/sec/SOSCircle/SecureObjectSync/SOSEngine.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Created by Michael Brouwer on 7/17/12. - * Copyright 2012 Apple Inc. All Rights Reserved. - */ - -/*! - @header SOSEngine.h - The functions provided in SOSEngine.h provide an interface to a - secure object syncing engine - */ - -#ifndef _SEC_SOSENGINE_H_ -#define _SEC_SOSENGINE_H_ - -#include -#include - -__BEGIN_DECLS - -enum { - kSOSEngineInvalidMessageError = 1, - kSOSEngineInternalError = 2, -}; - -typedef struct __OpaqueSOSEngine *SOSEngineRef; -typedef struct __OpaqueSOSPeer *SOSPeerRef; - -/* SOSDataSource protocol (non opaque). */ -typedef struct SOSDataSource *SOSDataSourceRef; - -typedef struct __OpaqueSOSObject *SOSObjectRef; - -/* Implement this if you want to create a new type of sync client. - Currently we support keychains, but the engine should scale to - entire filesystems. */ -enum SOSMergeResult { - kSOSMergeFailure = 0, // CFErrorRef returned, no error returned in any other case - kSOSMergeLocalObject, // We choose the current object in the dataSource the manifest is still valid. - kSOSMergePeersObject, // We chose the peers object over our own, manifest is now dirty. - kSOSMergeCreatedObject, // *createdObject is returned and should be released -}; -typedef CFIndex SOSMergeResult; - -struct SOSDataSource { - bool (*get_manifest_digest)(SOSDataSourceRef ds, uint8_t *out_digest, CFErrorRef *error); - SOSManifestRef (*copy_manifest)(SOSDataSourceRef ds, CFErrorRef *error); - bool (*foreach_object)(SOSDataSourceRef ds, SOSManifestRef manifest, CFErrorRef *error, bool (^handle_object)(SOSObjectRef object, CFErrorRef *error)); - SOSMergeResult (*add)(SOSDataSourceRef ds, SOSObjectRef object, CFErrorRef *error); - void (*release)(SOSDataSourceRef ds); - - SOSObjectRef (*createWithPropertyList)(SOSDataSourceRef ds, CFDictionaryRef plist, CFErrorRef *error); - CFDataRef (*copyDigest)(SOSObjectRef object, CFErrorRef *error); - CFDataRef (*copyPrimaryKey)(SOSObjectRef object, CFErrorRef *error); - CFDictionaryRef (*copyPropertyList)(SOSObjectRef object, CFErrorRef *error); - SOSObjectRef (*copyMergedObject)(SOSObjectRef object1, SOSObjectRef object2, CFErrorRef *error); - CFDictionaryRef (*backupObject)(SOSObjectRef object, uint64_t handle, CFErrorRef *error); - bool (*restoreObject)(SOSDataSourceRef ds, uint64_t handle, CFDictionaryRef item, CFErrorRef *error); -}; - -// Create a new engine instance for a given datasource. -SOSEngineRef SOSEngineCreate(SOSDataSourceRef dataSource, CFErrorRef *error); - -// Dispose of an engine when it's no longer needed. -void SOSEngineDispose(SOSEngineRef engine); - -// Handle incoming message from a remote peer. -bool SOSEngineHandleMessage(SOSEngineRef engine, SOSPeerRef peer, - CFDataRef message, CFErrorRef *error); - -// Initiate a sync with the providied peer by sending it a message. -bool SOSEngineSyncWithPeer(SOSEngineRef engine, SOSPeerRef peer, bool force, - CFErrorRef *error); - -/* Internal functions exposed for testability. */ -CFDataRef SOSEngineCreateManifestDigestMessage(SOSEngineRef engine, SOSPeerRef peer, CFErrorRef *error); -CFDataRef SOSEngineCreateManifestMessage(SOSEngineRef engine, SOSPeerRef peer, CFErrorRef *error); -CFDataRef SOSEngineCreateManifestAndObjectsMessage(SOSEngineRef engine, SOSPeerRef peer, CFErrorRef *error); - -CFStringRef SOSMessageCopyDescription(CFDataRef message); - -__END_DECLS - -#endif /* !_SEC_SOSENGINE_H_ */ diff --git a/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.h b/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.h deleted file mode 100644 index 87f34efd..00000000 --- a/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.h +++ /dev/null @@ -1,60 +0,0 @@ -// -// SOSFullPeerInfo.h -// sec -// -// Created by Mitch Adler on 10/26/12. -// -// - -#ifndef _SOSFULLPEERINFO_H_ -#define _SOSFULLPEERINFO_H_ - -#include -#include -#include -#include - -__BEGIN_DECLS - -typedef struct __OpaqueSOSFullPeerInfo *SOSFullPeerInfoRef; - -enum { - kSOSFullPeerVersion = 1, -}; - -SOSFullPeerInfoRef SOSFullPeerInfoCreate(CFAllocatorRef allocator, CFDictionaryRef gestalt, SecKeyRef signingKey, CFErrorRef *error); - -SOSFullPeerInfoRef SOSFullPeerInfoCreateCloudIdentity(CFAllocatorRef allocator, SOSPeerInfoRef peer, CFErrorRef* error); - -SOSPeerInfoRef SOSFullPeerInfoGetPeerInfo(SOSFullPeerInfoRef fullPeer); -SecKeyRef SOSFullPeerInfoCopyDeviceKey(SOSFullPeerInfoRef fullPeer, CFErrorRef* error); - -bool SOSFullPeerInfoPurgePersistentKey(SOSFullPeerInfoRef peer, CFErrorRef* error); - -SOSPeerInfoRef SOSFullPeerInfoPromoteToRetiredAndCopy(SOSFullPeerInfoRef peer, CFErrorRef *error); - -bool SOSFullPeerInfoValidate(SOSFullPeerInfoRef peer, CFErrorRef* error); - -bool SOSFullPeerInfoUpdateGestalt(SOSFullPeerInfoRef peer, CFDictionaryRef gestalt, CFErrorRef* error); - -bool SOSFullPeerInfoPromoteToApplication(SOSFullPeerInfoRef fpi, SecKeyRef user_key, CFErrorRef *error); - -bool SOSFullPeerInfoUpgradeSignatures(SOSFullPeerInfoRef fpi, SecKeyRef user_key, CFErrorRef *error); - -// -// DER Import Export -// -SOSFullPeerInfoRef SOSFullPeerInfoCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error, - const uint8_t** der_p, const uint8_t *der_end); - -SOSFullPeerInfoRef SOSFullPeerInfoCreateFromData(CFAllocatorRef allocator, CFDataRef fullPeerData, CFErrorRef *error); - -size_t SOSFullPeerInfoGetDEREncodedSize(SOSFullPeerInfoRef peer, CFErrorRef *error); -uint8_t* SOSFullPeerInfoEncodeToDER(SOSFullPeerInfoRef peer, CFErrorRef* error, - const uint8_t* der, uint8_t* der_end); - -CFDataRef SOSFullPeerInfoCopyEncodedData(SOSFullPeerInfoRef peer, CFAllocatorRef allocator, CFErrorRef *error); - -__END_DECLS - -#endif diff --git a/sec/SOSCircle/SecureObjectSync/SOSInternal.h b/sec/SOSCircle/SecureObjectSync/SOSInternal.h deleted file mode 100644 index 007280d2..00000000 --- a/sec/SOSCircle/SecureObjectSync/SOSInternal.h +++ /dev/null @@ -1,87 +0,0 @@ -// -// SOSInternal.h -// sec -// -// Created by Mitch Adler on 7/18/12. -// -// - -#ifndef _SOSINTERNAL_H_ -#define _SOSINTERNAL_H_ - -#include - -#include - -#include - -#include - -__BEGIN_DECLS - -enum { - // Public errors are first (See SOSCloudCircle) - - kSOSErrorFirstPrivateError = 1024, - - kSOSErrorAllocationFailure = 1024, - kSOSErrorEncodeFailure = 1025, - kSOSErrorNameMismatch = 1026, - kSOSErrorSendFailure = 1027, - kSOSErrorProcessingFailure = 1028, - kSOSErrorDecodeFailure = 1029, - - kSOSErrorAlreadyPeer = 1030, - kSOSErrorNotApplicant = 1031, - kSOSErrorPeerNotFound = 1032, - - kSOSErrorNoKey = 1033, - kSOSErrorBadKey = 1034, - kSOSErrorBadFormat = 1035, - kSOSErrorNoCircleName = 1036, - kSOSErrorNoCircle = 1037, - kSOSErrorBadSignature = 1038, - kSOSErrorReplay = 1039, - - kSOSErrorUnexpectedType = 1040, - - kSOSErrorUnsupported = 1041 -}; - -bool SOSCreateError(CFIndex errorCode, CFStringRef descriptionString, CFErrorRef previousError, CFErrorRef *newError); - -bool SOSCreateErrorWithFormat(CFIndex errorCode, CFErrorRef previousError, CFErrorRef *newError, - CFDictionaryRef formatOptions, CFStringRef formatString, ...) - CF_FORMAT_FUNCTION(5,6); - -bool SOSCreateErrorWithFormatAndArguments(CFIndex errorCode, CFErrorRef previousError, CFErrorRef *newError, - CFDictionaryRef formatOptions, CFStringRef formatString, va_list args) - CF_FORMAT_FUNCTION(5,0); - - -static inline bool isSOSErrorCoded(CFErrorRef error, CFIndex sosErrorCode) { - return CFErrorGetCode(error) == sosErrorCode && CFEqualSafe(CFErrorGetDomain(error), kSOSErrorDomain); -} - - -// -// Utility Functions -// -OSStatus GenerateECPair(int keySize, SecKeyRef* public, SecKeyRef *full); -OSStatus GeneratePermanentECPair(int keySize, SecKeyRef* public, SecKeyRef *full); - -CFStringRef SOSChangesCopyDescription(CFDictionaryRef changes, bool is_sender); - -CFStringRef SOSCopyIDOfKey(SecKeyRef key, CFErrorRef *error); - -// -// Der encoding accumulation -// -static inline bool accumulate_size(size_t *accumulator, size_t size) { - *accumulator += size; - return size != 0; -} - -__END_DECLS - -#endif diff --git a/sec/SOSCircle/SecureObjectSync/SOSPeer.c b/sec/SOSCircle/SecureObjectSync/SOSPeer.c deleted file mode 100644 index 206b0a7a..00000000 --- a/sec/SOSCircle/SecureObjectSync/SOSPeer.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * Created by Michael Brouwer on 6/22/12. - * Copyright 2012 Apple Inc. All Rights Reserved. - */ - -/* - * SOSPeer.c - Implementation of a secure object syncing peer - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include - -#include - -#include - -// -// -// -static CFStringRef sErrorDomain = CFSTR("com.apple.security.sos.peer.error"); - -static CFMutableDictionaryRef sPersistenceCache = NULL; -static CFStringRef peerFile = CFSTR("PeerManifestCache.plist"); - -static CFMutableDictionaryRef SOSPeerGetPersistenceCache(CFStringRef my_id) -{ - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - CFErrorRef localError = NULL; - CFMutableDictionaryRef peerDict = NULL; - CFDataRef dictAsData = SOSItemGet(kSOSPeerDataLabel, &localError); - - if (dictAsData) { - der_decode_dictionary(kCFAllocatorDefault, kCFPropertyListMutableContainers, (CFDictionaryRef*)&peerDict, &localError, - CFDataGetBytePtr(dictAsData), - CFDataGetBytePtr(dictAsData) + CFDataGetLength(dictAsData)); - } - - if (!isDictionary(peerDict)) { - CFReleaseNull(peerDict); - secnotice("peer", "Error finding persisted peer data %@, using empty", localError); - peerDict = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - CFReleaseNull(localError); - } - - if (CFDictionaryGetValue(peerDict, my_id) != NULL) { - CFMutableDictionaryRef mySubDictionary = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - - CFDictionaryForEach(peerDict, ^(const void *key, const void *value) { - if (!isDictionary(value)) { - CFDictionaryAddValue(mySubDictionary, key, value); - }; - }); - - CFDictionaryForEach(mySubDictionary, ^(const void *key, const void *value) { - CFDictionaryRemoveValue(peerDict, key); - }); - - CFDictionaryAddValue(peerDict, my_id, mySubDictionary); - } - sPersistenceCache = peerDict; - }); - - return sPersistenceCache; -} - -static void SOSPeerFlushPersistenceCache() -{ - if (!sPersistenceCache) - return; - - CFErrorRef localError = NULL; - CFIndex size = der_sizeof_dictionary(sPersistenceCache, &localError); - CFMutableDataRef dataToStore = CFDataCreateMutableWithScratch(kCFAllocatorDefault, size); - - if (size == 0) { - secerror("Error calculating size of persistence cache: %@", localError); - goto fail; - } - - uint8_t *der = NULL; - if (CFDataGetBytePtr(dataToStore) != (der = der_encode_dictionary(sPersistenceCache, &localError, - CFDataGetBytePtr(dataToStore), - CFDataGetMutableBytePtr(dataToStore) + CFDataGetLength(dataToStore)))) { - secerror("Error flattening peer cache: %@", localError); - secerror("ERROR flattening peer cache (%@): size=%zd %@ (%p %p)", sPersistenceCache, size, dataToStore, CFDataGetBytePtr(dataToStore), der); - goto fail; -} - - if (!SOSItemUpdateOrAdd(kSOSPeerDataLabel, kSecAttrAccessibleWhenUnlockedThisDeviceOnly, dataToStore, &localError)) { - secerror("Peer cache item save failed: %@", localError); - goto fail; - } - -fail: - CFReleaseNull(localError); - CFReleaseNull(dataToStore); -} - -void SOSPeerPurge(SOSPeerRef peer) { - // TODO: Do we use this or some other end-around for PurgeAll? -} - -void SOSPeerPurgeAllFor(CFStringRef my_id) -{ - if (!my_id) - return; - - CFMutableDictionaryRef persistenceCache = SOSPeerGetPersistenceCache(my_id); - - CFMutableDictionaryRef myPeerIDs = (CFMutableDictionaryRef) CFDictionaryGetValue(persistenceCache, my_id); - if (myPeerIDs) - { - CFRetainSafe(myPeerIDs); - - CFDictionaryRemoveValue(myPeerIDs, my_id); - - if (isDictionary(myPeerIDs)) { - CFDictionaryForEach(myPeerIDs, ^(const void *key, const void *value) { - // TODO: Inflate each and purge its keys. - }); - } - - CFReleaseNull(myPeerIDs); - } -} - -static bool SOSPeerFindDataFor(CFTypeRef *peerData, CFStringRef my_id, CFStringRef peer_id, CFErrorRef *error) -{ - CFDictionaryRef table = (CFDictionaryRef) CFDictionaryGetValue(SOSPeerGetPersistenceCache(my_id), my_id); - - *peerData = isDictionary(table) ? CFDictionaryGetValue(table, peer_id) : NULL; - - return true; -} - -static bool SOSPeerCopyPersistedManifest(SOSManifestRef* manifest, CFStringRef my_id, CFStringRef peer_id, CFErrorRef *error) -{ - CFTypeRef persistedObject = NULL; - - require(SOSPeerFindDataFor(&persistedObject, my_id, peer_id, error), fail); - - CFDataRef persistedData = NULL; - - if (isData(persistedObject)) - persistedData = (CFDataRef)persistedObject; - else if (isArray(persistedObject) && (CFArrayGetCount((CFArrayRef) persistedObject) == 2)) - persistedData = CFArrayGetValueAtIndex((CFArrayRef) persistedObject, 1); - - if (isData(persistedData)) { - SOSManifestRef createdManifest = SOSManifestCreateWithData(persistedData, error); - - require(createdManifest, fail); - - *manifest = createdManifest; -} - - return true; - -fail: - return false; -} - - -static bool SOSPeerCopyCoderData(CFDataRef *data, CFStringRef my_id, CFStringRef peer_id, CFErrorRef *error) -{ - CFTypeRef persistedObject = NULL; - - require(SOSPeerFindDataFor(&persistedObject, my_id, peer_id, error), fail); - - CFDataRef persistedData = NULL; - - if (isArray(persistedObject)) - persistedData = CFArrayGetValueAtIndex((CFArrayRef) persistedObject, 0); - - if (isData(persistedData)) { - CFRetainSafe(persistedData); - *data = persistedData; - } - - return true; - -fail: - return false; -} - - -static void SOSPeerPersistData(CFStringRef my_id, CFStringRef peer_id, SOSManifestRef manifest, CFDataRef coderData) -{ - CFMutableArrayRef data_array = CFArrayCreateMutableForCFTypes(0); - if (coderData) { - CFArrayAppendValue(data_array, coderData); - } else { - CFDataRef nullData = CFDataCreate(kCFAllocatorDefault, NULL, 0); - CFArrayAppendValue(data_array, nullData); - CFReleaseNull(nullData); - } - - if (manifest) { - CFArrayAppendValue(data_array, SOSManifestGetData(manifest)); - } - - CFMutableDictionaryRef mySubDict = (CFMutableDictionaryRef) CFDictionaryGetValue(SOSPeerGetPersistenceCache(my_id), my_id); - - if (mySubDict == NULL) { - mySubDict = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - CFDictionaryAddValue(SOSPeerGetPersistenceCache(my_id), my_id, mySubDict); - } - - CFDictionarySetValue(mySubDict, peer_id, data_array); - - CFReleaseNull(data_array); - - SOSPeerFlushPersistenceCache(); -} - -struct __OpaqueSOSPeer { - SOSPeerSendBlock send_block; - CFStringRef my_id; - CFStringRef peer_id; - CFIndex version; - SOSManifestRef manifest; - CFDataRef manifest_digest; - SOSCoderRef coder; // Currently will be used for OTR stuff. -}; - -static SOSPeerRef SOSPeerCreate_Internal(CFStringRef myPeerID, CFStringRef theirPeerID, CFIndex version, CFErrorRef *error, - SOSPeerSendBlock sendBlock) { - SOSPeerRef p = calloc(1, sizeof(struct __OpaqueSOSPeer)); - p->send_block = sendBlock; - p->peer_id = theirPeerID; - CFRetainSafe(p->peer_id); - - p->version = version; - - p->my_id = myPeerID; - CFRetainSafe(myPeerID); - - require(SOSPeerCopyPersistedManifest(&p->manifest, p->my_id, p->peer_id, error), fail); - - return p; - -fail: - CFReleaseSafe(p->peer_id); - CFReleaseSafe(p->my_id); - free(p); - return NULL; -} - - -SOSPeerRef SOSPeerCreate(SOSFullPeerInfoRef myPeerInfo, SOSPeerInfoRef peerInfo, - CFErrorRef *error, SOSPeerSendBlock sendBlock) { - - if (myPeerInfo == NULL) { - SOSCreateError(kSOSErrorUnsupported, CFSTR("Can't create peer without my peer info!"), NULL, error); - return NULL; - } - if (peerInfo == NULL) { - SOSCreateError(kSOSErrorUnsupported, CFSTR("Can't create peer without their peer info!"), NULL, error); - return NULL; - } - - SOSPeerRef result = NULL; - SOSPeerRef p = SOSPeerCreate_Internal(SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(myPeerInfo)), - SOSPeerInfoGetPeerID(peerInfo), - SOSPeerInfoGetVersion(peerInfo), - error, sendBlock); - - require(p, fail); - - CFDataRef coderData = NULL; - CFErrorRef coderError = NULL; - - if (SOSPeerCopyCoderData(&coderData, p->my_id, p->peer_id, &coderError) - && coderData && CFDataGetLength(coderData) != 0) { - p->coder = SOSCoderCreateFromData(coderData, &coderError); - } - - if (p->coder) { - secnotice("peer", "Old coder for me: %@ to peer: %@", p->my_id, p->peer_id); - } else { - secnotice("peer", "New coder for me: %@ to peer: %@ [Got error: %@]", p->my_id, p->peer_id, coderError); - - p->coder = SOSCoderCreate(peerInfo, myPeerInfo, error); - - if (!p->coder) { - SOSPeerDispose(p); - p = NULL; - } - } - - CFReleaseNull(coderData); - CFReleaseNull(coderError); - - result = p; - p = NULL; - -fail: - CFReleaseNull(p); - return result; -} - -SOSPeerRef SOSPeerCreateSimple(CFStringRef peer_id, CFIndex version, CFErrorRef *error, - SOSPeerSendBlock sendBlock) { - return SOSPeerCreate_Internal(CFSTR("FakeTestID"), peer_id, version, error, sendBlock); -} - -void SOSPeerDispose(SOSPeerRef peer) { - CFErrorRef error = NULL; - CFDataRef coderData = NULL; - if (peer->coder) { - coderData = SOSCoderCopyDER(peer->coder, &error); - if (coderData == NULL) { - secerror("Coder data failed to export (%@), zapping data for me: %@ to peer: %@", error, peer->my_id, peer->peer_id); - } - CFReleaseNull(error); - } - - if (!coderData) { - coderData = CFDataCreate(NULL, NULL, 0); - } - - SOSPeerPersistData(peer->my_id, peer->peer_id, peer->manifest, coderData); - - CFReleaseNull(coderData); - CFReleaseSafe(peer->peer_id); - CFReleaseSafe(peer->my_id); - if (peer->manifest) - SOSManifestDispose(peer->manifest); - CFReleaseSafe(peer->manifest_digest); - if (peer->coder) - SOSCoderDispose(peer->coder); - - free(peer); -} - -SOSPeerCoderStatus SOSPeerHandleMessage(SOSPeerRef peer, SOSEngineRef engine, CFDataRef codedMessage, CFErrorRef *error) { - CFMutableDataRef message = NULL; - SOSPeerCoderStatus coderStatus = kSOSPeerCoderDataReturned; - - if (peer->coder) { - coderStatus = SOSCoderUnwrap(peer->coder, peer->send_block, codedMessage, &message, peer->peer_id, error); - } else { - message = CFDataCreateMutableCopy(kCFAllocatorDefault, 0, codedMessage); - } - - switch(coderStatus) { - case kSOSPeerCoderDataReturned: { - CFStringRef description = SOSMessageCopyDescription(message); - secnotice("peer", "Got message from %@: %@", peer->peer_id, description); - CFReleaseSafe(description); - coderStatus = (SOSEngineHandleMessage(engine, peer, message, error)) ? coderStatus: kSOSPeerCoderFailure; - break; - } - case kSOSPeerCoderNegotiating: // Sent message already in Unwrap. - secnotice("peer", "Negotiating with %@: Got: %@", peer->peer_id, codedMessage); - break; - case kSOSPeerCoderNegotiationCompleted: - if (SOSEngineSyncWithPeer(engine, peer, true, error)) { - secnotice("peer", "Negotiating with %@ completed: %@" , peer->peer_id, codedMessage); - } else { - secerror("Negotiating with %@ completed syncWithPeer: %@ calling syncWithAllPeers" , peer->peer_id, error ? *error : NULL); - // Clearing the manifest forces SOSEngineSyncWithPeer(engine, peer, false, error) to send a message no matter what. - // This is needed because that's what gets called by SOSPeerStartSync, which is what SOSCCSyncWithAllPeers triggers. - SOSPeerSetManifest(peer, NULL, NULL); - SOSCCSyncWithAllPeers(); - coderStatus = kSOSPeerCoderFailure; - } - break; - case kSOSPeerCoderFailure: // Probably restart coder - secnotice("peer", "Failed handling message from %@: Got: %@", peer->peer_id, codedMessage); - SOSCoderReset(peer->coder); - coderStatus = SOSCoderStart(peer->coder, peer->send_block, peer->peer_id, error); - break; - case kSOSPeerCoderStaleEvent: // We received an event we have already processed in the past. - secnotice("peer", "StaleEvent from %@: Got: %@", peer->peer_id, codedMessage); - break; - default: - assert(false); - break; - } - - CFReleaseNull(message); - - return coderStatus; -} - -SOSPeerCoderStatus SOSPeerStartSync(SOSPeerRef peer, SOSEngineRef engine, CFErrorRef *error) { - SOSPeerCoderStatus coderStatus = kSOSPeerCoderDataReturned; - - if (peer->coder) { - coderStatus = SOSCoderStart(peer->coder, peer->send_block, peer->peer_id, error); - } - - switch(coderStatus) { - case kSOSPeerCoderDataReturned: // fallthrough - case kSOSPeerCoderNegotiationCompleted: // fallthrough - coderStatus = (SOSEngineSyncWithPeer(engine, peer, false, error)) ? coderStatus: kSOSPeerCoderFailure; - break; - case kSOSPeerCoderNegotiating: // Sent message already in Unwrap. - secnotice("peer", "Started sync with %@", peer->peer_id); - break; - case kSOSPeerCoderFailure: // Probably restart coder - break; - default: - assert(false); - break; - } - return coderStatus; -} - -bool SOSPeerSendMessage(SOSPeerRef peer, CFDataRef message, CFErrorRef *error) { - CFMutableDataRef codedMessage = NULL; - CFStringRef description = SOSMessageCopyDescription(message); - - SOSPeerCoderStatus coderStatus = kSOSPeerCoderDataReturned; - - if (peer->coder) { - coderStatus = SOSCoderWrap(peer->coder, message, &codedMessage, peer->peer_id, error); - } else { - codedMessage = CFDataCreateMutableCopy(kCFAllocatorDefault, 0, message); - } - bool ok = true; - switch(coderStatus) { - case kSOSPeerCoderDataReturned: - secnotice("peer", "%@ message: %@", peer->peer_id, description); - peer->send_block(codedMessage, error); - break; - case kSOSPeerCoderNegotiating: - secnotice("peer", "%@ coder Negotiating - message not sent", peer->peer_id); - ok = SOSCreateErrorWithFormat(kSOSCCError, NULL, error, NULL, CFSTR("%@ failed to send message peer still negotiating"), peer->peer_id); - break; - default: // includes kSOSPeerCoderFailure - secerror("%@ coder failure - message not sent %@", peer->peer_id, error ? *error : NULL); - ok = false; - break; - } - CFReleaseSafe(description); - return ok; -} - -bool SOSPeerCanSendMessage(SOSPeerRef peer) { - return (!peer->coder || SOSCoderCanWrap(peer->coder)); -} - -CFIndex SOSPeerGetVersion(SOSPeerRef peer) { - return peer->version; -} - -CFStringRef SOSPeerGetID(SOSPeerRef peer) { - return peer->peer_id; -} - -bool SOSPeersEqual(SOSPeerRef peerA, SOSPeerRef peerB) -{ - // Use mainly to see if peerB is actually this device (peerA) - return CFStringCompare(SOSPeerGetID(peerA), SOSPeerGetID(peerB), 0) == kCFCompareEqualTo; -} - -bool SOSPeerSetManifest(SOSPeerRef peer, SOSManifestRef manifest, CFErrorRef *error __unused) { - CFRetainSafe(manifest); - CFReleaseSafe(peer->manifest); - peer->manifest = manifest; - - CFReleaseNull(peer->manifest_digest); - return true; -} - -SOSManifestRef SOSPeerCopyManifest(SOSPeerRef peer, CFErrorRef *error __unused) { - if (!peer->manifest) { - SecCFCreateError(kSOSPeerHasNoManifest, sErrorDomain, CFSTR("failed to find peer manifest - not yet implemented"), NULL, error); - return NULL; - } - - CFRetain(peer->manifest); - return peer->manifest; -} - -CFDataRef SOSPeerCopyManifestDigest(SOSPeerRef peer, CFErrorRef *error) { - if (peer->manifest_digest) { - CFRetain(peer->manifest_digest); - } else { - if (peer->manifest) { - CFMutableDataRef data = CFDataCreateMutable(NULL, CC_SHA1_DIGEST_LENGTH); - if (data) { - CFDataSetLength(data, CC_SHA1_DIGEST_LENGTH); - CCDigest(kCCDigestSHA1, SOSManifestGetBytePtr(peer->manifest), (CC_LONG)SOSManifestGetSize(peer->manifest), CFDataGetMutableBytePtr(data)); - peer->manifest_digest = data; - CFRetain(peer->manifest_digest); - } else { - SecCFCreateError(kSOSPeerDigestFailure, sErrorDomain, CFSTR("failed to create digest"), NULL, error); - } - } else { - SecCFCreateError(kSOSPeerHasNoManifest, sErrorDomain, CFSTR("peer has no manifest, can't create digest"), NULL, error); - } - } - - return peer->manifest_digest; -} diff --git a/sec/SOSCircle/SecureObjectSync/SOSPeer.h b/sec/SOSCircle/SecureObjectSync/SOSPeer.h deleted file mode 100644 index 97c711e1..00000000 --- a/sec/SOSCircle/SecureObjectSync/SOSPeer.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Created by Michael Brouwer on 6/22/12. - * Copyright 2012 Apple Inc. All Rights Reserved. - */ - -/*! - @header SOSPeer - The functions provided in SOSPeer provide an interface to a - secure object syncing peer in a circle - */ - -#ifndef _SOSPEER_H_ -#define _SOSPEER_H_ - -#include -// #include -#include -#include - -__BEGIN_DECLS - -enum { - kSOSPeerHasNoManifest = 1, - kSOSPeerDigestFailure = 2, -}; - -enum { - kSOSPeerCoderDataReturned = 0, - kSOSPeerCoderNegotiating = 1, - kSOSPeerCoderNegotiationCompleted = 2, - kSOSPeerCoderFailure = 3, - kSOSPeerCoderStaleEvent = 4, -}; -typedef uint32_t SOSPeerCoderStatus; - -typedef bool (^SOSPeerSendBlock)(CFDataRef message, CFErrorRef *error); - - -/* Constructor */ -SOSPeerRef SOSPeerCreate(SOSFullPeerInfoRef myPeerInfo, SOSPeerInfoRef peerInfo, CFErrorRef *error, - SOSPeerSendBlock sendBlock); - -// Permanently forgetting stored information (e.g. keys on keychain) -void SOSPeerPurge(SOSPeerRef); -void SOSPeerPurgeAllFor(CFStringRef my_id); - -// Dispose of a peer when it's no longer needed. -void SOSPeerDispose(SOSPeerRef peer); - -SOSPeerCoderStatus SOSPeerStartSync(SOSPeerRef peer, SOSEngineRef engine, CFErrorRef *error); - -// Handle an incoming message and pass it to the engine. -SOSPeerCoderStatus SOSPeerHandleMessage(SOSPeerRef peer, SOSEngineRef engine, CFDataRef message, CFErrorRef *error); - -// Called by engine to send message to our tranport. -bool SOSPeerSendMessage(SOSPeerRef peer, CFDataRef message, CFErrorRef *error); - -// Return true if the peer is ready to transmit data. -bool SOSPeerCanSendMessage(SOSPeerRef peer); - -CFIndex SOSPeerGetVersion(SOSPeerRef peer); - -CFStringRef SOSPeerGetID(SOSPeerRef peer); -bool SOSPeersEqual(SOSPeerRef peerA, SOSPeerRef peerB); - -bool SOSPeerSetManifest(SOSPeerRef peer, SOSManifestRef manifest, CFErrorRef *error); - -SOSManifestRef SOSPeerCopyManifest(SOSPeerRef peer, CFErrorRef *error); -CFDataRef SOSPeerCopyManifestDigest(SOSPeerRef peer, CFErrorRef *error); - -/* For testing, doesn't OTR encode and uses static ID for self */ -SOSPeerRef SOSPeerCreateSimple(CFStringRef peer_id, CFIndex version, CFErrorRef *error, - SOSPeerSendBlock sendBlock); - -__END_DECLS - -#endif /* !_SOSPEER_H_ */ diff --git a/sec/SOSCircle/SecureObjectSync/SOSPeerInfo.h b/sec/SOSCircle/SecureObjectSync/SOSPeerInfo.h deleted file mode 100644 index 50ca02f8..00000000 --- a/sec/SOSCircle/SecureObjectSync/SOSPeerInfo.h +++ /dev/null @@ -1,127 +0,0 @@ -// -// SOSPeerInfo.h -// sec -// -// Created by Mitch Adler on 7/19/12. -// -// - -#ifndef _SOSPEERINFO_H_ -#define _SOSPEERINFO_H_ - -#include -#include -#include -#include -#include - -__BEGIN_DECLS - -typedef struct __OpaqueSOSPeerInfo *SOSPeerInfoRef; - -enum { - kSOSPeerVersion = 1, -}; - - -enum { - SOSPeerCmpPubKeyHash = 0, - SOSPeerCmpName = 1, -}; -typedef uint32_t SOSPeerInfoCmpSelect; - -SOSPeerInfoRef SOSPeerInfoCreate(CFAllocatorRef allocator, CFDictionaryRef gestalt, SecKeyRef signingKey, CFErrorRef* error); - -SOSPeerInfoRef SOSPeerInfoCreateCloudIdentity(CFAllocatorRef allocator, CFDictionaryRef gestalt, SecKeyRef signingKey, CFErrorRef* error); - -SOSPeerInfoRef SOSPeerInfoCreateCopy(CFAllocatorRef allocator, SOSPeerInfoRef toCopy, CFErrorRef* error); -SOSPeerInfoRef SOSPeerInfoCopyWithGestaltUpdate(CFAllocatorRef allocator, SOSPeerInfoRef toCopy, CFDictionaryRef gestalt, SecKeyRef signingKey, CFErrorRef* error); -SOSPeerInfoRef SOSPeerInfoCopyAsApplication(SOSPeerInfoRef pi, SecKeyRef userkey, SecKeyRef peerkey, CFErrorRef *error); - -bool SOSPeerInfoUpdateDigestWithPublicKeyBytes(SOSPeerInfoRef peer, const struct ccdigest_info *di, - ccdigest_ctx_t ctx, CFErrorRef *error); -bool SOSPeerInfoUpdateDigestWithDescription(SOSPeerInfoRef peer, const struct ccdigest_info *di, - ccdigest_ctx_t ctx, CFErrorRef *error); - - -bool SOSPeerInfoApplicationVerify(SOSPeerInfoRef pi, SecKeyRef userkey, CFErrorRef *error); - -CF_RETURNS_RETAINED CFDateRef SOSPeerInfoGetApplicationDate(SOSPeerInfoRef pi); - -// -// DER Import Export -// -SOSPeerInfoRef SOSPeerInfoCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error, - const uint8_t** der_p, const uint8_t *der_end); - -SOSPeerInfoRef SOSPeerInfoCreateFromData(CFAllocatorRef allocator, CFErrorRef* error, - CFDataRef peerinfo_data); - -size_t SOSPeerInfoGetDEREncodedSize(SOSPeerInfoRef peer, CFErrorRef *error); -uint8_t* SOSPeerInfoEncodeToDER(SOSPeerInfoRef peer, CFErrorRef* error, - const uint8_t* der, uint8_t* der_end); - -CFDataRef SOSPeerInfoCopyEncodedData(SOSPeerInfoRef peer, CFAllocatorRef allocator, CFErrorRef *error); - -// -// Gestalt info about the peer. It was fetched by the implementation on the other side. -// probably has what you're looking for.. -// -CFTypeRef SOSPeerInfoLookupGestaltValue(SOSPeerInfoRef pi, CFStringRef key); -CFDictionaryRef SOSPeerInfoCopyPeerGestalt(SOSPeerInfoRef pi); - -// -// Syntactic Sugar for some commone ones, might get deprectated at this level. -// -CFStringRef SOSPeerInfoGetPeerName(SOSPeerInfoRef peer); -CFStringRef SOSPeerInfoGetPeerDeviceType(SOSPeerInfoRef peer); - - -// Stringified ID for this peer, not human readable. -CFStringRef SOSPeerInfoGetPeerID(SOSPeerInfoRef peer); - -CFIndex SOSPeerInfoGetVersion(SOSPeerInfoRef peer); - - - -// -// Peer Info Arrays -// - -CFMutableArrayRef SOSPeerInfoArrayCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error, - const uint8_t** der_p, const uint8_t *der_end); -size_t SOSPeerInfoArrayGetDEREncodedSize(CFArrayRef pia, CFErrorRef *error); -uint8_t* SOSPeerInfoArrayEncodeToDER(CFArrayRef pia, CFErrorRef* error, const uint8_t* der, uint8_t* der_end); - -CFArrayRef CreateArrayOfPeerInfoWithXPCObject(xpc_object_t peerArray, CFErrorRef* error); -xpc_object_t CreateXPCObjectWithArrayOfPeerInfo(CFArrayRef array, CFErrorRef *error); - -// -// Peer Info Gestalt Helpers -// -CFStringRef SOSPeerGestaltGetName(CFDictionaryRef gestalt); - -// These are Mobile Gestalt questions. Not all Gestalt questions are carried. -CFTypeRef SOSPeerGestaltGetAnswer(CFDictionaryRef gestalt, CFStringRef question); - -SecKeyRef SOSPeerInfoCopyPubKey(SOSPeerInfoRef peer); - -CFComparisonResult SOSPeerInfoCompareByID(const void *val1, const void *val2, void *context); - -SOSPeerInfoRef SOSPeerInfoCreateRetirementTicket(CFAllocatorRef allocator, SecKeyRef privKey, SOSPeerInfoRef peer, CFErrorRef *error); - -CFStringRef SOSPeerInfoInspectRetirementTicket(SOSPeerInfoRef pi, CFErrorRef *error); - -bool SOSPeerInfoRetireRetirementTicket(size_t max_days, SOSPeerInfoRef pi); - -CF_RETURNS_RETAINED CFDateRef SOSPeerInfoGetRetirementDate(SOSPeerInfoRef pi); - -bool SOSPeerInfoIsRetirementTicket(SOSPeerInfoRef pi); - -bool SOSPeerInfoIsCloudIdentity(SOSPeerInfoRef pi); - -SOSPeerInfoRef SOSPeerInfoUpgradeSignatures(CFAllocatorRef allocator, SecKeyRef privKey, SecKeyRef perKey, SOSPeerInfoRef peer, CFErrorRef *error); - -__END_DECLS - -#endif diff --git a/sec/SOSCircle/SecureObjectSync/SOSPeerInfoInternal.h b/sec/SOSCircle/SecureObjectSync/SOSPeerInfoInternal.h deleted file mode 100644 index 8ee16501..00000000 --- a/sec/SOSCircle/SecureObjectSync/SOSPeerInfoInternal.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// SOSPeerInfoInternal.h -// sec -// -// Created by Richard Murphy on 6/24/13. -// -// - -#ifndef sec_SOSPeerInfoInternal_h -#define sec_SOSPeerInfoInternal_h - -CFStringRef kPIUserDefinedDeviceName; -CFStringRef kPIDeviceModelName; - - -#endif diff --git a/sec/SOSCircle/SecureObjectSync/SOSTransport.c b/sec/SOSCircle/SecureObjectSync/SOSTransport.c deleted file mode 100644 index 9126a196..00000000 --- a/sec/SOSCircle/SecureObjectSync/SOSTransport.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Created by Michael Brouwer on 2/14/12. - * Copyright 2012 Apple Inc. All Rights Reserved. - */ - -/* - * SOSTransport.c - Implementation of the secure object syncing transport - */ - -#include -#include -#include -#include -#include - -static CFStringRef sErrorDomain = CFSTR("com.apple.security.sos.transport.error"); - -/* SOSDigestVector code. */ - -#define VECTOR_GROW(vector, count, capacity) \ - do { \ - if ((count) > capacity) { \ - capacity = ((capacity) + 16) * 3 / 2; \ - if (capacity < (count)) \ - capacity = (count); \ - vector = realloc((vector), sizeof(*(vector)) * capacity); \ - } \ -} while (0) - -static void SOSDigestVectorEnsureCapacity(struct SOSDigestVector *dv, size_t count) { - VECTOR_GROW(dv->digest, count, dv->capacity); -} - -void SOSDigestVectorReplaceAtIndex(struct SOSDigestVector *dv, size_t ix, const uint8_t *digest) -{ - SOSDigestVectorEnsureCapacity(dv, ix + 1); - memcpy(dv->digest[ix], digest, SOSDigestSize); - dv->is_sorted = false; -} - -static void SOSDigestVectorAppendOrdered(struct SOSDigestVector *dv, const uint8_t *digest) -{ - SOSDigestVectorEnsureCapacity(dv, dv->count + 1); - memcpy(dv->digest[dv->count++], digest, SOSDigestSize); -} - -void SOSDigestVectorAppend(struct SOSDigestVector *dv, const uint8_t *digest) -{ - SOSDigestVectorAppendOrdered(dv, digest); - dv->is_sorted = false; -} - -static int SOSDigestCompare(const void *a, const void *b) -{ - return memcmp(a, b, SOSDigestSize); -} - -void SOSDigestVectorSort(struct SOSDigestVector *dv) -{ - qsort(dv->digest, dv->count, sizeof(*dv->digest), SOSDigestCompare); - dv->is_sorted = true; -} - -bool SOSDigestVectorContains(struct SOSDigestVector *dv, const uint8_t *digest) -{ - return SOSDigestVectorIndexOf(dv, digest) != (size_t)-1; -} - -size_t SOSDigestVectorIndexOf(struct SOSDigestVector *dv, const uint8_t *digest) -{ - if (!dv->is_sorted) - SOSDigestVectorSort(dv); - const void *pos = bsearch(digest, dv->digest, dv->count, sizeof(*dv->digest), SOSDigestCompare); - return pos ? ((size_t)(pos - (void *)dv->digest)) / SOSDigestSize : ((size_t)-1); -} - -void SOSDigestVectorFree(struct SOSDigestVector *dv) -{ - free(dv->digest); - dv->digest = NULL; - dv->count = 0; - dv->capacity = 0; - dv->is_sorted = false; -} - -void SOSDigestVectorApply(struct SOSDigestVector *dv, - void *context, SOSDigestVectorApplyFunc func) -{ - if (!dv->is_sorted) - SOSDigestVectorSort(dv); - - for (size_t ix = 0; ix < dv->count; ++ix) { - func(context, dv->digest[ix]); - } -} - -static void SOSDigestVectorAppendMultiple(struct SOSDigestVector *dv, - size_t count, const uint8_t *digests) { - if (count) { - SOSDigestVectorEnsureCapacity(dv, dv->count + count); - memcpy(dv->digest[dv->count], digests, count * SOSDigestSize); - dv->count += count; - } -} - -void SOSDigestVectorDiff(struct SOSDigestVector *dv1, struct SOSDigestVector *dv2, - struct SOSDigestVector *dv1_2, struct SOSDigestVector *dv2_1) -{ - /* dv1_2 and dv2_1 should be empty to start. */ - assert(dv1_2->count == 0); - assert(dv2_1->count == 0); - - if (!dv1->is_sorted) - SOSDigestVectorSort(dv1); - if (!dv2->is_sorted) - SOSDigestVectorSort(dv2); - - size_t i1 = 0, i2 = 0; - while (i1 < dv1->count && i2 < dv2->count) { - int delta = SOSDigestCompare(dv1->digest[i1], dv2->digest[i2]); - if (delta == 0) { - ++i1, ++i2; - } else if (delta < 0) { - SOSDigestVectorAppendOrdered(dv1_2, dv1->digest[i1++]); - } else { - SOSDigestVectorAppendOrdered(dv2_1, dv2->digest[i2++]); - } - } - SOSDigestVectorAppendMultiple(dv1_2, dv1->count - i1, dv1->digest[i1]); - SOSDigestVectorAppendMultiple(dv2_1, dv2->count - i2, dv2->digest[i2]); - - dv1_2->is_sorted = true; - dv2_1->is_sorted = true; -} - -bool SOSDigestVectorPatch(struct SOSDigestVector *base, struct SOSDigestVector *removals, - struct SOSDigestVector *additions, struct SOSDigestVector *dv, - CFErrorRef *error) -{ - size_t base_ix = 0, removals_ix = 0, additions_ix = 0; - if (!base->is_sorted) - SOSDigestVectorSort(base); - if (!removals->is_sorted) - SOSDigestVectorSort(removals); - if (!additions->is_sorted) - SOSDigestVectorSort(additions); - - assert(dv->count == 0); - SOSDigestVectorEnsureCapacity(dv, base->count - removals->count + additions->count); - dv->is_sorted = true; - - while (base_ix < base->count) { - const uint8_t *d = base->digest[base_ix]; - if (additions_ix < additions->count && SOSDigestCompare(d, additions->digest[additions_ix]) > 0) { - SOSDigestVectorAppendOrdered(dv, additions->digest[additions_ix++]); - } else if (removals_ix < removals->count && SOSDigestCompare(d, removals->digest[removals_ix]) == 0) { - base_ix++; - removals_ix++; - } else { - SOSDigestVectorAppendOrdered(dv, base->digest[base_ix++]); - } - } - - if (removals_ix != removals->count) { - SecCFCreateErrorWithFormat(1, sErrorDomain, NULL, error, NULL, CFSTR("%lu extra removals left"), removals->count - removals_ix); - goto errOut; - } - - while (additions_ix < additions->count) { - if (dv->count > 0 && SOSDigestCompare(dv->digest[dv->count - 1], additions->digest[additions_ix]) >= 0) { - SecCFCreateErrorWithFormat(1, sErrorDomain, NULL, error, NULL, CFSTR("unordered addition (%lu left)"), additions->count - additions_ix); - goto errOut; - } - SOSDigestVectorAppendOrdered(dv, additions->digest[additions_ix++]); - } - - return true; -errOut: - return false; -} - - - -/* SOSManifest implementation. */ -struct __OpaqueSOSManifest { -}; - -SOSManifestRef SOSManifestCreateWithBytes(const uint8_t *bytes, size_t len, - CFErrorRef *error) { - SOSManifestRef manifest = (SOSManifestRef)CFDataCreate(NULL, bytes, (CFIndex)len); - if (!manifest) - SecCFCreateErrorWithFormat(kSOSManifestCreateError, sErrorDomain, NULL, error, NULL, CFSTR("Failed to create manifest")); - - return manifest; -} - -SOSManifestRef SOSManifestCreateWithData(CFDataRef data, CFErrorRef *error) -{ - SOSManifestRef manifest = NULL; - - if (data) - manifest = (SOSManifestRef)CFDataCreateCopy(kCFAllocatorDefault, data); - else - manifest = (SOSManifestRef)CFDataCreate(kCFAllocatorDefault, NULL, 0); - - if (!manifest) - SecCFCreateErrorWithFormat(kSOSManifestCreateError, sErrorDomain, NULL, error, NULL, CFSTR("Failed to create manifest")); - - return manifest; -} - -void SOSManifestDispose(SOSManifestRef m) { - CFRelease(m); -} - -size_t SOSManifestGetSize(SOSManifestRef m) { - return (size_t)CFDataGetLength((CFDataRef)m); -} - -size_t SOSManifestGetCount(SOSManifestRef m) { - return SOSManifestGetSize(m) / SOSDigestSize; -} - -const uint8_t *SOSManifestGetBytePtr(SOSManifestRef m) { - return CFDataGetBytePtr((CFDataRef)m); -} - -CFDataRef SOSManifestGetData(SOSManifestRef m) { - return (CFDataRef)m; -} - - -bool SOSManifestDiff(SOSManifestRef a, SOSManifestRef b, - SOSManifestRef *a_minus_b, SOSManifestRef *b_minus_a, - CFErrorRef *error) { - bool result = true; - struct SOSDigestVector dva = SOSDigestVectorInit, - dvb = SOSDigestVectorInit, - dvab = SOSDigestVectorInit, - dvba = SOSDigestVectorInit; - SOSDigestVectorAppendMultiple(&dva, SOSManifestGetCount(a), SOSManifestGetBytePtr(a)); - SOSDigestVectorAppendMultiple(&dvb, SOSManifestGetCount(b), SOSManifestGetBytePtr(b)); - SOSDigestVectorDiff(&dva, &dvb, &dvab, &dvba); - SOSDigestVectorFree(&dva); - SOSDigestVectorFree(&dvb); - - if (a_minus_b) { - *a_minus_b = SOSManifestCreateWithBytes((const uint8_t *)dvab.digest, dvab.count * SOSDigestSize, error); - if (!*a_minus_b) - result = false; - } - - if (b_minus_a) { - *b_minus_a = SOSManifestCreateWithBytes((const uint8_t *)dvba.digest, dvba.count * SOSDigestSize, error); - if (!*b_minus_a) - result = false; - } - - SOSDigestVectorFree(&dvab); - SOSDigestVectorFree(&dvba); - - return result; -} - -SOSManifestRef SOSManifestCreateWithPatch(SOSManifestRef base, - SOSManifestRef removals, - SOSManifestRef additions, - CFErrorRef *error) { - struct SOSDigestVector dvbase = SOSDigestVectorInit, - dvresult = SOSDigestVectorInit, - dvremovals = SOSDigestVectorInit, - dvadditions = SOSDigestVectorInit; - dvbase.is_sorted = dvresult.is_sorted = dvremovals.is_sorted = dvadditions.is_sorted = true; - SOSDigestVectorAppendMultiple(&dvbase, SOSManifestGetCount(base), SOSManifestGetBytePtr(base)); - SOSDigestVectorAppendMultiple(&dvremovals, SOSManifestGetCount(removals), SOSManifestGetBytePtr(removals)); - SOSDigestVectorAppendMultiple(&dvadditions, SOSManifestGetCount(additions), SOSManifestGetBytePtr(additions)); - SOSManifestRef result; - if (SOSDigestVectorPatch(&dvbase, &dvremovals, &dvadditions, &dvresult, error)) { - result = SOSManifestCreateWithBytes((const uint8_t *)dvresult.digest, dvresult.count * SOSDigestSize, error); - } else { - result = NULL; - } - SOSDigestVectorFree(&dvbase); - SOSDigestVectorFree(&dvresult); - SOSDigestVectorFree(&dvremovals); - SOSDigestVectorFree(&dvadditions); - return result; -} - -void SOSManifestForEach(SOSManifestRef m, void(^block)(CFDataRef e)) { - CFDataRef e; - const uint8_t *p, *q; - for (p = SOSManifestGetBytePtr(m), q = p + SOSManifestGetSize(m); - p + SOSDigestSize <= q; p += SOSDigestSize) { - e = CFDataCreateWithBytesNoCopy(0, p, SOSDigestSize, kCFAllocatorNull); - if (e) { - block(e); - CFRelease(e); - } - } -} - -CFStringRef SOSManifestCopyDescription(SOSManifestRef m) { - CFMutableStringRef desc = CFStringCreateMutable(0, 0); - CFStringAppend(desc, CFSTR("")); - - return desc; -} - -#if 0 -SOSObjectRef SOSManifestGetObject(SOSManifestRef m, SOSObjectID k) { - return NULL; -} - -void SOSManifestPutObject(SOSManifestRef m, SOSObjectID k, SOSObjectRef v) { - -} - - -SOSManifestRef SOSManifestCreateSparse(void *get_ctx, SOSManifestGetF get_f) { - return NULL; -} -#endif diff --git a/sec/SOSCircle/SecureObjectSync/SOSTransport.h b/sec/SOSCircle/SecureObjectSync/SOSTransport.h deleted file mode 100644 index 7cbe8ac8..00000000 --- a/sec/SOSCircle/SecureObjectSync/SOSTransport.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Created by Michael Brouwer on 2/14/12. - * Copyright 2012 Apple Inc. All Rights Reserved. - */ - -/*! - @header SOSTransport - The functions provided in SOSTransport.h provide an interface to the - secure object syncing transport - */ - -#ifndef _SOSTRANSPORT_H_ -#define _SOSTRANSPORT_H_ - -#include -#include -#include - -__BEGIN_DECLS - -enum { - kSOSManifestUnsortedError = 1, - kSOSManifestCreateError = 2, -}; - - -/* SOSTransport. */ - -/* SOSTransport protocol (not opaque). */ -typedef struct SOSTransport *SOSTransportRef; - -struct SOSTransport { - bool (*send)(SOSTransportRef transport, CFDataRef message); -}; - -/* Return the singleton cloud transport instance. */ -SOSTransportRef SOSTransportCopyCloudTransport(void); - -#define SOSDigestSize ((size_t)CCSHA1_OUTPUT_SIZE) - -#define SOSDigestVectorInit { .digest = NULL, .count = 0, .capacity = 0, .is_sorted = false } - -struct SOSDigestVector { - uint8_t (*digest)[SOSDigestSize]; - size_t count; - size_t capacity; - bool is_sorted; -}; - -/* SOSDigestVector. */ -void SOSDigestVectorAppend(struct SOSDigestVector *dv, const uint8_t *digest); -void SOSDigestVectorSort(struct SOSDigestVector *dv); -size_t SOSDigestVectorIndexOf(struct SOSDigestVector *dv, const uint8_t *digest); -bool SOSDigestVectorContains(struct SOSDigestVector *dv, const uint8_t *digest); -void SOSDigestVectorReplaceAtIndex(struct SOSDigestVector *dv, size_t ix, const uint8_t *digest); -void SOSDigestVectorFree(struct SOSDigestVector *dv); - -typedef void (*SOSDigestVectorApplyFunc)(void *context, const uint8_t digest[SOSDigestSize]); -void SOSDigestVectorApply(struct SOSDigestVector *dv, - void *context, SOSDigestVectorApplyFunc func); -void SOSDigestVectorDiff(struct SOSDigestVector *dv1, struct SOSDigestVector *dv2, - struct SOSDigestVector *dv1_2, struct SOSDigestVector *dv2_1); -bool SOSDigestVectorPatch(struct SOSDigestVector *base, struct SOSDigestVector *removals, - struct SOSDigestVector *additions, struct SOSDigestVector *dv, - CFErrorRef *error); - -/* SOSObject. */ - -/* Forward declarations of SOS types. */ -typedef struct __OpaqueSOSObjectID *SOSObjectID; -typedef struct __OpaqueSOSManifest *SOSManifestRef; - -/* SOSManifest. */ -SOSManifestRef SOSManifestCreateWithBytes(const uint8_t *bytes, size_t len, - CFErrorRef *error); -SOSManifestRef SOSManifestCreateWithData(CFDataRef data, CFErrorRef *error); -void SOSManifestDispose(SOSManifestRef m); -size_t SOSManifestGetSize(SOSManifestRef m); -size_t SOSManifestGetCount(SOSManifestRef m); -const uint8_t *SOSManifestGetBytePtr(SOSManifestRef m); -CFDataRef SOSManifestGetData(SOSManifestRef m); -bool SOSManifestDiff(SOSManifestRef a, SOSManifestRef b, - SOSManifestRef *a_minus_b, SOSManifestRef *b_minus_a, - CFErrorRef *error); -SOSManifestRef SOSManifestCreateWithPatch(SOSManifestRef base, - SOSManifestRef removals, - SOSManifestRef additions, - CFErrorRef *error); -void SOSManifestForEach(SOSManifestRef m, void(^block)(CFDataRef e)); - -CFStringRef SOSManifestCopyDescription(SOSManifestRef m); - -#if 0 -SOSObjectRef SOSManifestGetObject(SOSManifestRef m, SOSObjectID k); -void SOSManifestPutObject(SOSManifestRef m, SOSObjectID k, SOSObjectRef v); - -typedef SOSObjectRef(*SOSManifestGetF)(void *get_ctx, SOSObjectID k); -SOSManifestRef SOSManifestCreateSparse(void *get_ctx, SOSManifestGetF get_f); -#endif - -__END_DECLS - -#endif /* !_SOSTRANSPORT_H_ */ diff --git a/sec/SOSCircle/SecureObjectSync/SOSUserKey.c b/sec/SOSCircle/SecureObjectSync/SOSUserKey.c deleted file mode 100644 index d3109c65..00000000 --- a/sec/SOSCircle/SecureObjectSync/SOSUserKey.c +++ /dev/null @@ -1,80 +0,0 @@ -// -// SOSUserKey.c -// sec -// -// Created by Richard Murphy on 2/13/13. -// -// - -#include -#include -#include -#include -#include -#include - -#if 0 -#include - -#define UK_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); - -UK_CONST_DECL (ukSalt, "salt"); -UK_CONST_DECL (ukIteration, "iteration"); - -static const size_t saltlen = 16; -static const unsigned long iterations = 10240; - -static dispatch_once_t keyParmStoreInit; -static CFMutableDictionaryRef keyParmStorage = NULL; -static void SOSKeyParmStore(CFStringRef user_label, CFDictionaryRef parmData) { - dispatch_once(&keyParmStoreInit, ^{ - keyParmStorage = CFDictionaryCreateMutable(kCFAllocatorDefault, 50, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - }); - CFDictionaryAddValue(keyParmStorage, user_label, parmData); -} - -static CFDictionaryRef SOSKeyParmRetrieve(CFStringRef user_label) { - if(keyParmStorage && CFDictionaryContainsKey(keyParmStorage, user_label)) { - CFDictionaryRef parmData = CFDictionaryGetValue(keyParmStorage, user_label); - CFRetain(parmData); - return parmData; - } -/* - const void *keys[] = { ukSalt, ukIteration }; - const void *values[] = { cfsalt, cfiteration }; - CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys)/sizeof(*keys), NULL, NULL); - CFDictionaryRef retval = CFDictionaryCreate( -*/ - return NULL; -} - - -static void -SOSUserKeyGenParmPersist(CFStringRef user_label) -{ -} - -static void -SOSUserKeyGenParmRetrieve(CFStringRef user_label) -{ -} -#endif - -bool -SOSUserKeyGenerate(int keysize, CFStringRef user_label, CFDataRef user_password, SecKeyRef *user_pubkey, SecKeyRef *user_privkey) -{ -#if 0 - ccec_const_cp_t cp = ccec_get_cp(keysize); - ccec_full_ctx_decl_cp(cp, full_key); - struct ccrng_pbkdf2_prng_state pbkdf2_prng; - uint8_t salt[saltlen]; - if(CCRandomCopyBytes(kCCRandomDefault, salt, sizeof(salt)) != kCCSuccess) return false; - uint8_t password_bytes = CFDataGetBytePtr(user_password); - size_t password_length = CFDataGetLength(user_password); - ccrng_pbkdf2_prng_init(&pbkdf2_prng, 72, password_length, password_bytes, sizeof(salt), salt, iterations); - struct ccrng_state *rng = (struct ccrng_state *)&pbkdf2_prng; - ccec_generate_key(cp, rng, full_key); -#endif - - return true; -} diff --git a/sec/SOSCircle/SecureObjectSync/SOSUserKey.h b/sec/SOSCircle/SecureObjectSync/SOSUserKey.h deleted file mode 100644 index 3064876c..00000000 --- a/sec/SOSCircle/SecureObjectSync/SOSUserKey.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// SOSUserKey.h -// sec -// -// Created by Richard Murphy on 2/13/13. -// -// - -#ifndef sec_SOSUserKey_h -#define sec_SOSUserKey_h - -#include - -bool -SOSUserKeyGenerate(int keysize, CFStringRef user_label, CFDataRef user_password, SecKeyRef *user_pubkey, SecKeyRef *user_privkey); - - -#endif diff --git a/sec/SOSCircle/SecureObjectSync/SOSUserKeygen.h b/sec/SOSCircle/SecureObjectSync/SOSUserKeygen.h deleted file mode 100644 index 0a166ee5..00000000 --- a/sec/SOSCircle/SecureObjectSync/SOSUserKeygen.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// SOSUserKeygen.h -// sec -// -// Created by Richard Murphy on 2/21/13. -// -// - -#ifndef sec_SOSUserKeygen_h -#define sec_SOSUserKeygen_h -#include -#include - -CFDataRef SOSUserKeyCreateGenerateParameters(CFErrorRef *error); -SecKeyRef SOSUserKeygen(CFDataRef password, CFDataRef parameters, CFErrorRef *error); - -void debugDumpUserParameters(CFStringRef message, CFDataRef parameters); - -#endif diff --git a/sec/SOSCircle/Tool/SOSCommands.h b/sec/SOSCircle/Tool/SOSCommands.h deleted file mode 100644 index cdc8bf07..00000000 --- a/sec/SOSCircle/Tool/SOSCommands.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// SOSCommands.h -// sec -// -// Created by Mitch Adler on 1/9/13. -// -// - -#include - -SECURITY_COMMAND("sync", keychain_sync, - "[options]\n" - " -e Enable Keychain Syncing (join/create circle)\n" - " -d Disable Keychain Syncing\n" - " -a Accept all applicants\n" - " -r Reject all applicants\n" - " -i Info\n" - " -k Pend all registered kvs keys\n" - " -s Schedule sync with all peers\n" - " -R Reset\n" - " -O ResetToOffering\n" - " -C Clear all values from KVS\n" - " -P [label:]password Set password (optionally for a given label) for sync\n" - " -D [itemName] Dump contents of KVS\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" - " -U Purge private key material cache\n" - " -D [itemName] Dump contents of KVS\n" - " -W itemNames sync and dump\n", - " -X [limit] Best effort bail from circle in limit seconds\n" - "Keychain Syncing controls." ) - diff --git a/sec/SOSCircle/Tool/keychain_sync.c b/sec/SOSCircle/Tool/keychain_sync.c deleted file mode 100644 index 6e3c7c88..00000000 --- a/sec/SOSCircle/Tool/keychain_sync.c +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Copyright (c) 2003-2007,2009-2010 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - * - * keychain_add.c - */ - - -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include - -#include - -#include - -#include -#include - -#include -#include - -#include "SOSCommands.h" - -#define printmsg(format, ...) _printcfmsg(stdout, format, __VA_ARGS__) -#define printerr(format, ...) _printcfmsg(stderr, format, __VA_ARGS__) - -static void _printcfmsg(FILE *ff, CFStringRef format, ...) -{ - va_list args; - va_start(args, format); - CFStringRef message = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, format, args); - va_end(args); - CFStringPerformWithCString(message, ^(const char *utf8String) { fprintf(ff, utf8String, ""); }); - CFRelease(message); -} - -static bool clearAllKVS(CFErrorRef *error) -{ - __block bool result = false; - const uint64_t maxTimeToWaitInSeconds = 30ull * NSEC_PER_SEC; - dispatch_queue_t processQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0); - dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds); - - SOSCloudKeychainClearAll(processQueue, ^(CFDictionaryRef returnedValues, CFErrorRef cerror) - { - result = (cerror != NULL); - dispatch_semaphore_signal(waitSemaphore); - }); - - dispatch_semaphore_wait(waitSemaphore, finishTime); - dispatch_release(waitSemaphore); - - return result; -} - -static const char *getSOSCCStatusDescription(SOSCCStatus ccstatus) -{ - switch (ccstatus) - { - case kSOSCCInCircle: return "In Circle"; - case kSOSCCNotInCircle: return "Not in Circle"; - case kSOSCCRequestPending: return "Request pending"; - case kSOSCCCircleAbsent: return "Circle absent"; - case kSOSCCError: return "Circle error"; - - default: - return ""; - break; - } -} - -static void dumpCircleInfo() -{ - CFErrorRef error = NULL; - CFArrayRef applicantPeerInfos = NULL; - CFArrayRef peerInfos = NULL; - - SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(&error); - printerr(CFSTR("ccstatus: %s (%d), error: %@\n"), getSOSCCStatusDescription(ccstatus), ccstatus, error); - - if(ccstatus == kSOSCCError) { - printerr(CFSTR("End of Dump - unable to proceed due to ccstatus -\n\t%s\n"), getSOSCCStatusDescription(ccstatus)); - return; - } - - // Now look at current applicants - applicantPeerInfos = SOSCCCopyApplicantPeerInfo(&error); - if (applicantPeerInfos) - { - printerr(CFSTR("Applicants: %ld, error: %@\n"), (long)CFArrayGetCount(applicantPeerInfos), error); - CFArrayForEach(applicantPeerInfos, ^(const void *value) { - SOSPeerInfoRef peer = (SOSPeerInfoRef)value; - CFStringRef peerName = SOSPeerInfoGetPeerName(peer); - printerr(CFSTR("Applicant: %@ (%@)\n"), peerName, peer); - }); - } - else - printerr(CFSTR("No applicants, error: %@\n"), error); - - - peerInfos = SOSCCCopyPeerPeerInfo(&error); - if (peerInfos) - { - printerr(CFSTR("Peers: %ld, error: %@\n"), (long)CFArrayGetCount(peerInfos), error); - CFArrayForEach(peerInfos, ^(const void *value) { - SOSPeerInfoRef peer = (SOSPeerInfoRef)value; - CFStringRef peerName = SOSPeerInfoGetPeerName(peer); - printerr(CFSTR("Peer: %@ (%@)\n"), peerName, peer); - }); - } - else - printerr(CFSTR("No peers, error: %@\n"), error); - - peerInfos = SOSCCCopyConcurringPeerPeerInfo(&error); - if (peerInfos) - { - printerr(CFSTR("Concurring Peers: %ld, error: %@\n"), (long)CFArrayGetCount(peerInfos), error); - CFArrayForEach(peerInfos, ^(const void *value) { - SOSPeerInfoRef peer = (SOSPeerInfoRef)value; - CFStringRef peerName = SOSPeerInfoGetPeerName(peer); - printerr(CFSTR("Concurr: %@ (%@)\n"), peerName, peer); - }); - } - else - printerr(CFSTR("No concurring peers, error: %@\n"), error); -} - -static bool requestToJoinCircle(CFErrorRef *error) -{ - // Set the visual state of switch based on membership in circle - bool hadError = false; - SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(error); - - switch (ccstatus) - { - case kSOSCCCircleAbsent: - hadError = !SOSCCResetToOffering(error); - break; - case kSOSCCNotInCircle: - hadError = !SOSCCRequestToJoinCircle(error); - break; - default: - printerr(CFSTR("Request to join circle with bad status: %@ (%d)\n"), SOSCCGetStatusDescription(ccstatus), ccstatus); - break; - } - return hadError; -} - -static bool setPassword(char *labelAndPassword, CFErrorRef *err) -{ - char *last = NULL; - char *token0 = strtok_r(labelAndPassword, ":", &last); - char *token1 = strtok_r(NULL, "", &last); - CFStringRef label = token1 ? CFStringCreateWithCString(NULL, token0, kCFStringEncodingUTF8) : CFSTR("security command line tool"); - char *password_token = token1 ? token1 : token0; - password_token = password_token ? password_token : ""; - CFDataRef password = CFDataCreate(NULL, (const UInt8*) password_token, strlen(password_token)); - bool returned = !SOSCCSetUserCredentials(label, password, err); - CFRelease(label); - CFRelease(password); - return returned; -} - -static bool tryPassword(char *labelAndPassword, CFErrorRef *err) -{ - char *last = NULL; - char *token0 = strtok_r(labelAndPassword, ":", &last); - char *token1 = strtok_r(NULL, "", &last); - CFStringRef label = token1 ? CFStringCreateWithCString(NULL, token0, kCFStringEncodingUTF8) : CFSTR("security command line tool"); - char *password_token = token1 ? token1 : token0; - password_token = password_token ? password_token : ""; - CFDataRef password = CFDataCreate(NULL, (const UInt8*) password_token, strlen(password_token)); - bool returned = !SOSCCTryUserCredentials(label, password, err); - CFRelease(label); - CFRelease(password); - return returned; -} - -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) - { - secerror("SOSCloudKeychainGetObjectsFromCloud returned: %@", returnedValues); - object = returnedValues; - if (object) - CFRetain(object); - if (error) - { - secerror("SOSCloudKeychainGetObjectsFromCloud returned error: %@", error); - // CFRelease(*error); - } - dispatch_group_leave(dgroup); - secerror("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 void displayCircles(CFTypeRef objects) -{ - // SOSCCCopyApplicantPeerInfo doesn't display all info, e.g. in the case where we are not in circle - CFDictionaryForEach(objects, ^(const void *key, const void *value) { - if (SOSKVSKeyGetKeyType(key) == kCircleKey) - { - CFErrorRef localError = NULL; - if (isData(value)) - { - SOSCircleRef circle = SOSCircleCreateFromData(NULL, (CFDataRef) value, &localError); - printmsg(CFSTR("circle: %@ %@"), key, circle); - CFReleaseSafe(circle); - } - else - printmsg(CFSTR("non-circle: %@ %@"), key, value); - } - }); -} - -static bool dumpKVS(char *itemName, CFErrorRef *err) -{ - CFArrayRef keysToGet = NULL; - if (itemName) - { - CFStringRef itemStr = CFStringCreateWithCString(kCFAllocatorDefault, itemName, kCFStringEncodingUTF8); - printf("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); - printmsg(CFSTR(" : %@\n"), objects); - if (objects) - displayCircles(objects); - printf("\n"); - return false; -} - -static bool syncAndWait(char *itemName, CFErrorRef *err) -{ - CFArrayRef keysToGet = NULL; - __block CFTypeRef objects = NULL; - if (!itemName) - { - fprintf(stderr, "No item keys supplied\n"); - return false; - } - - CFStringRef itemStr = CFStringCreateWithCString(kCFAllocatorDefault, itemName, kCFStringEncodingUTF8); - printf("Retrieving %s from KVS\n", itemName); - keysToGet = CFArrayCreateForCFTypes(kCFAllocatorDefault, itemStr, NULL); - CFReleaseSafe(itemStr); - - dispatch_queue_t generalq = dispatch_queue_create("general", DISPATCH_QUEUE_SERIAL); - - 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); - - CloudKeychainReplyBlock replyBlock = ^ (CFDictionaryRef returnedValues, CFErrorRef error) - { - secerror("SOSCloudKeychainSynchronizeAndWait returned: %@", returnedValues); - if (error) - secerror("SOSCloudKeychainSynchronizeAndWait returned error: %@", error); - objects = returnedValues; - if (objects) - CFRetain(objects); - secerror("SOSCloudKeychainGetObjectsFromCloud block exit: %@", objects); - dispatch_semaphore_signal(waitSemaphore); - }; - - SOSCloudKeychainSynchronizeAndWait(keysToGet, generalq, replyBlock); - - dispatch_semaphore_wait(waitSemaphore, finishTime); - dispatch_release(waitSemaphore); - - CFReleaseSafe(keysToGet); - printmsg(CFSTR(" : %@\n"), objects); - if (objects) - displayCircles(objects); - printf("\n"); - return false; -} - -// enable, disable, accept, reject, status, Reset, Clear -int -keychain_sync(int argc, char * const *argv) -{ - /* - " -e Enable Keychain Syncing (join/create circle)\n" - " -d Disable Keychain Syncing\n" - " -a Accept all applicants\n" - " -r Reject all applicants\n" - " -i Info\n" - " -k Pend all registered kvs keys\n" - " -s Schedule sync with all peers\n" - " -R Reset\n" - " -O ResetToOffering\n" - " -C Clear all values from KVS\n" - " -P [label:]password Set password (optionally for a given label) for sync\n" - " -D [itemName] Dump contents of KVS\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" - " -U Purge private key material cache\n" - " -D [itemName] Dump contents of KVS\n" - " -W itemNames sync and dump\n" - " -X [limit] Best effort bail from circle in limit seconds\n" - */ - int ch, result = 0; - CFErrorRef error = NULL; - bool hadError = false; - - while ((ch = getopt(argc, argv, "edakrisROChP:T:DW:UX:")) != -1) - { - switch (ch) - { - case 'e': - printf("Keychain syncing is being turned ON\n"); - hadError = requestToJoinCircle(&error); - break; - case 'd': - printf("Keychain syncing is being turned OFF\n"); - hadError = !SOSCCRemoveThisDeviceFromCircle(&error); - break; - case 'a': - { - CFArrayRef applicants = SOSCCCopyApplicantPeerInfo(NULL); - if (applicants) - { - hadError = !SOSCCAcceptApplicants(applicants, &error); - CFRelease(applicants); - } - else - fprintf(stderr, "No applicants to accept\n"); - } - break; - case 'r': - { - CFArrayRef applicants = SOSCCCopyApplicantPeerInfo(NULL); - if (applicants) - { - hadError = !SOSCCRejectApplicants(applicants, &error); - CFRelease(applicants); - } - else - fprintf(stderr, "No applicants to reject\n"); - } - break; - case 'i': - dumpCircleInfo(); - break; - case 'k': - notify_post("com.apple.security.cloudkeychain.forceupdate"); - break; - case 's': - //SOSCloudKeychainRequestSyncWithAllPeers(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); - break; - case 'R': - hadError = !SOSCCResetToEmpty(&error); - break; - case 'O': - hadError = !SOSCCResetToOffering(&error); - break; - case 'C': - hadError = clearAllKVS(&error); - break; - case 'P': - hadError = setPassword(optarg, &error); - break; - case 'T': - hadError = tryPassword(optarg, &error); - break; - case 'X': - { - uint64_t limit = strtoul(optarg, NULL, 10); - hadError = !SOSCCBailFromCircle_BestEffort(limit, &error); - } - break; - case 'U': - hadError = !SOSCCPurgeUserCredentials(&error); - break; - case 'D': - hadError = dumpKVS(optarg, &error); - break; - case 'W': - hadError = syncAndWait(optarg, &error); - break; - case '?': - default: - return 2; /* Return 2 triggers usage message. */ - } - } - - argc -= optind; - argv += optind; - -// if (argc == 0) -// return 2; - - if (hadError) - printerr(CFSTR("Error: %@\n"), error); - - // sec_perror("SecItemAdd", result); - - return result; -} diff --git a/sec/SOSCircle/osxshim.c b/sec/SOSCircle/osxshim.c deleted file mode 100644 index 2468f080..00000000 --- a/sec/SOSCircle/osxshim.c +++ /dev/null @@ -1,30 +0,0 @@ -// -// osxshim.c -// sec -// -// Created by J Osborne on 12/4/12. -// -// - -#include - -typedef void *SOSDataSourceFactoryRef; -typedef void *SOSAccountRef; - -// XXX Need to plumb these from security to secd. If we can. - -typedef SOSDataSourceFactoryRef (^AccountDataSourceFactoryBlock)(); - -bool SOSKeychainAccountSetFactoryForAccount(AccountDataSourceFactoryBlock factory); - -bool SOSKeychainAccountSetFactoryForAccount(AccountDataSourceFactoryBlock factory) -{ - return false; -} - -SOSAccountRef SOSKeychainAccountGetSharedAccount(void); - -SOSAccountRef SOSKeychainAccountGetSharedAccount(void) -{ - return (void*)0; -} diff --git a/sec/Security/AppleBaselineEscrowCertificates.h b/sec/Security/AppleBaselineEscrowCertificates.h deleted file mode 100644 index 4a999b13..00000000 --- a/sec/Security/AppleBaselineEscrowCertificates.h +++ /dev/null @@ -1,94 +0,0 @@ -// -// AppleBaselineEscrowCertificates.h -// sec -// -// Created by Jim Murphy on 6/25/13. -// -// - -#ifndef sec_AppleBaselineEscrowCertificates_h -#define sec_AppleBaselineEscrowCertificates_h - -struct RootRecord -{ - size_t _length; - UInt8* _bytes; -}; - -/* ========================================================================== - Production Escrow Certificates - ========================================================================== */ - - -static const UInt8 kBaseLineEscrowRootGM[] = { - 0x30, 0x82, 0x03, 0xd0, 0x30, 0x82, 0x02, 0xb8, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x64, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, - 0x79, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x03, 0x31, 0x30, 0x30, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, - 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 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, 0x33, - 0x30, 0x38, 0x30, 0x32, 0x32, 0x33, 0x32, 0x34, 0x34, 0x34, 0x5a, 0x17, 0x0d, 0x32, 0x33, 0x30, - 0x38, 0x30, 0x32, 0x32, 0x33, 0x32, 0x34, 0x34, 0x34, 0x5a, 0x30, 0x79, 0x31, 0x0c, 0x30, 0x0a, - 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x03, 0x31, 0x30, 0x30, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, - 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, - 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x26, 0x30, 0x24, - 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 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, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, - 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd0, 0xa3, 0xf4, 0x56, 0x7d, 0x3f, 0x46, 0x31, 0xd2, 0x56, - 0xa0, 0xdf, 0x42, 0xa0, 0x29, 0x83, 0x1e, 0xb9, 0x82, 0xb5, 0xa5, 0xff, 0x3e, 0xde, 0xb5, 0x0f, - 0x4a, 0x8a, 0x28, 0x60, 0xcf, 0x75, 0xb4, 0xa0, 0x70, 0x7c, 0xf5, 0xe2, 0x94, 0xf3, 0x22, 0x02, - 0xc8, 0x81, 0xce, 0x34, 0xc7, 0x66, 0x6a, 0x18, 0xaa, 0xb4, 0xfd, 0x6d, 0xb0, 0x0b, 0xdd, 0x4a, - 0xdd, 0xcf, 0xe0, 0x08, 0x1b, 0x1c, 0xa6, 0xdb, 0xba, 0xb2, 0xc1, 0xa4, 0x10, 0x5f, 0x35, 0x4f, - 0x8b, 0x8b, 0x7a, 0xa3, 0xdb, 0x3c, 0xf6, 0x54, 0x95, 0x42, 0xad, 0x2a, 0x3b, 0xfe, 0x06, 0x8c, - 0xe1, 0x92, 0xf1, 0x60, 0x97, 0x58, 0x1b, 0xd9, 0x8f, 0xbe, 0xfb, 0x46, 0x4c, 0x29, 0x5c, 0x1c, - 0xf0, 0x20, 0xb6, 0x2b, 0xa5, 0x12, 0x09, 0x9b, 0x28, 0x41, 0x34, 0x97, 0x9f, 0xf3, 0x88, 0x4b, - 0x69, 0x72, 0xea, 0x3a, 0x27, 0xb0, 0x50, 0x1d, 0x88, 0x29, 0x0d, 0xbb, 0xed, 0x04, 0xa2, 0x11, - 0xcf, 0x0c, 0x5b, 0x65, 0x61, 0x35, 0xbd, 0xf2, 0x0d, 0xfc, 0xe2, 0xb9, 0x20, 0xd3, 0xb7, 0x03, - 0x70, 0x39, 0xd5, 0xe0, 0x86, 0x7c, 0x04, 0xcc, 0xc9, 0xa1, 0x85, 0xb4, 0x9b, 0xbc, 0x88, 0x4e, - 0xd7, 0xad, 0x5c, 0xff, 0x2c, 0x0d, 0x80, 0x8e, 0x51, 0x39, 0x20, 0x8b, 0xaf, 0x1e, 0x46, 0x95, - 0xfa, 0x0d, 0x1b, 0xd2, 0xbf, 0x80, 0xe0, 0x9f, 0x6d, 0x4a, 0xf5, 0x31, 0x67, 0x18, 0x11, 0xa5, - 0x63, 0x27, 0x08, 0xee, 0xd9, 0x07, 0x29, 0xd0, 0xd4, 0x36, 0x91, 0x5b, 0xfb, 0x4a, 0x0b, 0x07, - 0xd1, 0x0d, 0x79, 0x16, 0x6e, 0x16, 0x02, 0x23, 0x80, 0xc6, 0x15, 0x07, 0x6d, 0xa0, 0x06, 0xb6, - 0x45, 0x90, 0xb0, 0xae, 0xa4, 0xad, 0x0e, 0x75, 0x04, 0x2b, 0x2b, 0x78, 0xf1, 0x57, 0x84, 0x23, - 0x87, 0x24, 0xec, 0x58, 0xc4, 0xf1, 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, 0x01, 0x06, - 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xfd, 0x78, 0x96, 0x53, 0x80, - 0xd6, 0xf6, 0xdc, 0xa6, 0xc3, 0x59, 0x06, 0x38, 0xed, 0x79, 0x3e, 0x8f, 0x50, 0x1b, 0x50, 0x30, - 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xfd, 0x78, 0x96, 0x53, - 0x80, 0xd6, 0xf6, 0xdc, 0xa6, 0xc3, 0x59, 0x06, 0x38, 0xed, 0x79, 0x3e, 0x8f, 0x50, 0x1b, 0x50, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, - 0x82, 0x01, 0x01, 0x00, 0x71, 0x15, 0xca, 0x87, 0xd0, 0x2d, 0xb5, 0x18, 0xd5, 0x35, 0x7a, 0xcd, - 0xdf, 0x62, 0x28, 0xf0, 0x0b, 0x63, 0x4d, 0x4e, 0x02, 0xba, 0x3d, 0xb8, 0xb4, 0x37, 0xea, 0xb0, - 0x93, 0x93, 0xab, 0x1c, 0xfd, 0x9f, 0xe8, 0x72, 0xbf, 0xf3, 0xdb, 0xe6, 0xad, 0x16, 0xfe, 0x71, - 0x61, 0xa8, 0x5a, 0xd0, 0x58, 0x0f, 0x65, 0x7a, 0x57, 0x7a, 0xe0, 0x34, 0x80, 0x8e, 0xbb, 0x41, - 0x01, 0xe7, 0xb0, 0x3b, 0xf7, 0x2b, 0x3a, 0x6d, 0x44, 0x2a, 0x3a, 0x04, 0x52, 0xfa, 0x2b, 0x7b, - 0x3b, 0x21, 0xdd, 0x0c, 0x70, 0x3d, 0xfb, 0x45, 0xc6, 0x79, 0x68, 0x62, 0xe2, 0x89, 0xb8, 0x25, - 0xee, 0x63, 0x76, 0x02, 0xb2, 0x22, 0xe9, 0x53, 0x85, 0x68, 0x3e, 0x75, 0xb6, 0x0b, 0x65, 0xe9, - 0x1c, 0xba, 0x84, 0x93, 0xb0, 0x8a, 0xef, 0xb5, 0x1a, 0x12, 0xe4, 0x8f, 0xae, 0xd5, 0x5c, 0xa1, - 0x05, 0x4a, 0x01, 0xbc, 0x6f, 0xf9, 0x58, 0x5e, 0xf7, 0x04, 0x61, 0xee, 0xf5, 0xc6, 0xa0, 0x1b, - 0x44, 0x2e, 0x5a, 0x3a, 0x59, 0xa1, 0xb3, 0xb0, 0xf4, 0xb6, 0xcb, 0xe0, 0x6c, 0x2b, 0x59, 0x8a, - 0xfb, 0x6a, 0xe0, 0xa2, 0x57, 0x09, 0x79, 0xc1, 0xdd, 0xfb, 0x84, 0x86, 0xeb, 0x66, 0x29, 0x73, - 0xae, 0xbf, 0x58, 0xae, 0x47, 0x4d, 0x48, 0x37, 0xd6, 0xb1, 0x8c, 0x5f, 0x26, 0x5f, 0xb5, 0x26, - 0x07, 0x0b, 0x85, 0xb7, 0x36, 0x37, 0x14, 0xcf, 0x5e, 0x55, 0xa5, 0x3c, 0xf3, 0x1e, 0x79, 0x50, - 0xbb, 0x85, 0x3b, 0xb2, 0x94, 0x68, 0xb0, 0x25, 0x4f, 0x75, 0xec, 0xf0, 0xf9, 0xc0, 0x5a, 0x2d, - 0xe5, 0xed, 0x67, 0xcd, 0x88, 0x55, 0xa0, 0x42, 0xde, 0x78, 0xbc, 0xfe, 0x30, 0xb1, 0x62, 0x2d, - 0xe1, 0xfd, 0xec, 0x75, 0x03, 0xa6, 0x1f, 0x7c, 0xc4, 0x3a, 0x4a, 0x59, 0xfe, 0x77, 0xc3, 0x99, - 0x96, 0x87, 0x44, 0xc3, -}; - - -static struct RootRecord kBaseLineEscrowRootRecord = {sizeof(kBaseLineEscrowRootGM), (UInt8*)kBaseLineEscrowRootGM}; -static struct RootRecord* kBaseLineEscrowRoots[] = {&kBaseLineEscrowRootRecord}; -static const int kNumberOfBaseLineEscrowRoots = (int)(sizeof(kBaseLineEscrowRoots)/sizeof(kBaseLineEscrowRoots[0])); - - -#endif diff --git a/sec/Security/Regressions/Security_regressions.h b/sec/Security/Regressions/Security_regressions.h deleted file mode 100644 index d6c3dc51..00000000 --- a/sec/Security/Regressions/Security_regressions.h +++ /dev/null @@ -1,75 +0,0 @@ -/* To add a test: - 1) add it here - 2) Add it as command line argument for SecurityTest.app in the Release and Debug schemes - */ -#include - -ONE_TEST(pbkdf2_00_hmac_sha1) -ONE_TEST(spbkdf_00_hmac_sha1) - -ONE_TEST(si_00_find_nothing) -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_14_dateparse) -ONE_TEST(si_15_certificate) -ONE_TEST(si_16_ec_certificate) -ONE_TEST(si_20_sectrust_activation) -ONE_TEST(si_20_sectrust) -ONE_TEST(si_21_sectrust_asr) -ONE_TEST(si_22_sectrust_iap) -ONE_TEST(si_23_sectrust_ocsp) -ONE_TEST(si_24_sectrust_itms) -ONE_TEST(si_24_sectrust_nist) -ONE_TEST(si_24_sectrust_otatasking) -ONE_TEST(si_24_sectrust_mobileasset) -ONE_TEST(si_24_sectrust_diginotar) -ONE_TEST(si_24_sectrust_appleid) -ONE_TEST(si_24_sectrust_digicert_malaysia) -ONE_TEST(si_24_sectrust_shoebox) -ONE_TEST(si_25_sectrust_ipsec_eap) -ONE_TEST(si_26_applicationsigning) -ONE_TEST(si_27_sectrust_exceptions) -ONE_TEST(si_28_sectrustsettings) -ONE_TEST(si_29_sectrust_codesigning) -DISABLED_ONE_TEST(si_30_keychain_upgrade) //obsolete, needs updating -ONE_TEST(si_31_keychain_bad) -ONE_TEST(si_31_keychain_unreadable) -ONE_TEST(si_33_keychain_backup) -ONE_TEST(si_40_seckey) -ONE_TEST(si_40_seckey_custom) -ONE_TEST(si_41_sececkey) -ONE_TEST(si_42_identity) -ONE_TEST(si_43_persistent) -ONE_TEST(si_50_secrandom) -ONE_TEST(si_60_cms) -DISABLED_ONE_TEST(si_61_pkcs12) -ONE_TEST(si_62_csr) -ONE_TEST(si_63_scep) -ONE_TEST(si_64_ossl_cms) -ONE_TEST(si_65_cms_cert_policy) -ONE_TEST(si_66_smime) -ONE_TEST(si_67_sectrust_blacklist) -ONE_TEST(si_68_secmatchissuer) -ONE_TEST(si_69_keydesc) -ONE_TEST(si_70_sectrust_unified) -ONE_TEST(si_71_mobile_store_policy) -ONE_TEST(si_72_syncableitems) -ONE_TEST(si_73_secpasswordgenerate) -#if TARGET_OS_IPHONE -ONE_TEST(si_74_OTA_PKI_Signer) -ONE_TEST(si_75_AppleIDRecordSigning) -#else -DISABLED_ONE_TEST(si_74_OTA_PKI_Signer) -DISABLED_ONE_TEST(si_75_AppleIDRecordSigning) -#endif - -ONE_TEST(vmdh_40) -ONE_TEST(vmdh_41_example) -ONE_TEST(vmdh_42_example2) - -ONE_TEST(otr_00_identity) -ONE_TEST(otr_30_negotiation) -ONE_TEST(otr_otrdh) -ONE_TEST(otr_packetdata) diff --git a/sec/Security/Regressions/otr/otr-otrdh.c b/sec/Security/Regressions/otr/otr-otrdh.c deleted file mode 100644 index 0c8cacc5..00000000 --- a/sec/Security/Regressions/otr/otr-otrdh.c +++ /dev/null @@ -1,45 +0,0 @@ -// -// otr-otrdh.c -// OTR -// -// Created by Mitch Adler on 7/22/11. -// Copyright (c) 2011 Apple Inc. All rights reserved. -// - -#include "Security_regressions.h" - -#include -#include - -int otr_otrdh(int argc, char *const * argv) -{ - plan_tests(4); - - SecOTRFullDHKeyRef aliceFull = SecOTRFullDHKCreate(kCFAllocatorDefault); - SecOTRPublicDHKeyRef alicePublic = SecOTRPublicDHKCreateFromFullKey(kCFAllocatorDefault, aliceFull); - - SecOTRFullDHKeyRef bobFull = SecOTRFullDHKCreate(kCFAllocatorDefault); - SecOTRPublicDHKeyRef bobPublic = SecOTRPublicDHKCreateFromFullKey(kCFAllocatorDefault, bobFull); - - uint8_t aliceMessageKeys[2][kOTRMessageKeyBytes]; - uint8_t aliceMacKeys[2][kOTRMessageMacKeyBytes]; - - SecOTRDHKGenerateOTRKeys(aliceFull, bobPublic, - aliceMessageKeys[0], aliceMacKeys[0], - aliceMessageKeys[1], aliceMacKeys[1]); - - uint8_t bobMessageKeys[2][kOTRMessageKeyBytes]; - uint8_t bobMacKeys[2][kOTRMessageMacKeyBytes]; - - SecOTRDHKGenerateOTRKeys(bobFull, alicePublic, - bobMessageKeys[0], bobMacKeys[0], - bobMessageKeys[1], bobMacKeys[1]); - - - ok(0 == memcmp(aliceMessageKeys[0], bobMessageKeys[1], sizeof(aliceMessageKeys[0])), "Mac Keys don't match!!"); - ok(0 == memcmp(aliceMessageKeys[1], bobMessageKeys[0], sizeof(aliceMessageKeys[1])), "Mac Keys don't match!!"); - ok(0 == memcmp(aliceMacKeys[0], bobMacKeys[1], sizeof(aliceMacKeys[0])), "Mac Keys don't match!!"); - ok(0 == memcmp(aliceMacKeys[1], bobMacKeys[0], sizeof(aliceMacKeys[1])), "Mac Keys don't match!!"); - - return 0; -} diff --git a/sec/Security/Regressions/otr/otr-packetdata.c b/sec/Security/Regressions/otr/otr-packetdata.c deleted file mode 100644 index 4e6d22f5..00000000 --- a/sec/Security/Regressions/otr/otr-packetdata.c +++ /dev/null @@ -1,185 +0,0 @@ -// -// otr-packetdata.c -// OTR -// -// Created by Mitch Adler on 7/22/11. -// Copyright (c) 2011 Apple Inc. All rights reserved. -// - -#include -#include "SecOTRPacketData.h" - -#include - -#include "security_regressions.h" - -static bool CFDataMatches(CFDataRef data, size_t amount, const uint8_t* bytes) -{ - if ((size_t) CFDataGetLength(data) != amount) - return false; - - return 0 == memcmp(CFDataGetBytePtr(data), bytes, amount); - -} - - -static void testAppendShort() -{ - CFMutableDataRef result = CFDataCreateMutable(kCFAllocatorDefault, 0); - - const uint8_t firstResult[] = { 1, 2 }; - AppendShort(result, 0x0102); - ok(CFDataMatches(result, sizeof(firstResult), firstResult), "Didn't insert correctly"); - - const uint8_t secondResult[] = { 1, 2, 3, 4}; - AppendShort(result, 0x0304); - ok(CFDataMatches(result, sizeof(secondResult), secondResult), "Didn't append!"); - - CFRelease(result); - - result = CFDataCreateMutable(kCFAllocatorDefault, 0); - - const uint8_t thirdResult[] = { 0, 0 }; - AppendShort(result, 0x0); - ok(CFDataMatches(result, sizeof(thirdResult), thirdResult), "Didn't insert zero"); - - CFRelease(result); - - result = CFDataCreateMutable(kCFAllocatorDefault, 0); - - const uint8_t fourthResult[] = { 0xFF, 0xFF}; - AppendShort(result, 0xFFFF); - ok(CFDataMatches(result, sizeof(thirdResult), fourthResult), "Didn't insert 0xFFFFFFFF"); - - CFRelease(result); -} - -static void testAppendLong() -{ - CFMutableDataRef result = CFDataCreateMutable(kCFAllocatorDefault, 0); - - const uint8_t firstResult[] = { 1, 2, 3, 4 }; - AppendLong(result, 0x01020304); - ok(CFDataMatches(result, sizeof(firstResult), firstResult), "Didn't insert correctly"); - - const uint8_t secondResult[] = { 1, 2, 3, 4, 5, 6, 7, 8}; - AppendLong(result, 0x05060708); - ok(CFDataMatches(result, sizeof(secondResult), secondResult), "Didn't append!"); - - CFRelease(result); - - result = CFDataCreateMutable(kCFAllocatorDefault, 0); - - const uint8_t thirdResult[] = { 0, 0, 0, 0 }; - AppendLong(result, 0x0); - ok(CFDataMatches(result, sizeof(thirdResult), thirdResult), "Didn't insert zero"); - - CFRelease(result); - - result = CFDataCreateMutable(kCFAllocatorDefault, 0); - - const uint8_t fourthResult[] = { 0xFF, 0xFF, 0xFF, 0xFF }; - AppendLong(result, 0xFFFFFFFF); - ok(CFDataMatches(result, sizeof(thirdResult), fourthResult), "Didn't insert 0xFFFFFFFF"); - - CFRelease(result); -} - -static void testAppendData() -{ - CFMutableDataRef result = CFDataCreateMutable(kCFAllocatorDefault, 0); - - const uint8_t firstResult[] = { 0, 0, 0, 4, 1, 2, 3, 4 }; - AppendDATA(result, sizeof(firstResult) - 4, firstResult + 4); - ok(CFDataMatches(result, sizeof(firstResult), firstResult), "Didn't insert correctly"); - - const uint8_t secondResult[] = { 0, 0, 0, 4, 1, 2, 3, 4, 0, 0, 0, 1, 0 }; - AppendDATA(result, sizeof(secondResult) - 12, secondResult + 12); - ok(CFDataMatches(result, sizeof(secondResult), secondResult), "Didn't append!"); - - CFRelease(result); - - result = CFDataCreateMutable(kCFAllocatorDefault, 0); - - const uint8_t thirdResult[] = { 0, 0, 0, 2, 0, 0 }; - AppendDATA(result, sizeof(thirdResult) - 4, thirdResult + 4); - ok(CFDataMatches(result, sizeof(thirdResult), thirdResult), "Didn't insert correctly"); - - CFRelease(result); - - result = CFDataCreateMutable(kCFAllocatorDefault, 0); - - const uint8_t fourthResult[] = { 0, 0, 0, 5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - AppendDATA(result, sizeof(fourthResult) - 4, fourthResult + 4); - ok(CFDataMatches(result, sizeof(fourthResult), fourthResult), "Didn't insert correctly"); - - CFRelease(result); -} - - -static void testAppendMPI() -{ - const size_t kUnitBufferN = 1024; - cc_unit unitBuffer[1024]; - - CFMutableDataRef result = CFDataCreateMutable(kCFAllocatorDefault, 0); - - const uint8_t firstResult[] = { 0, 0, 0, 2, 1, 2 }; - ccn_read_uint(kUnitBufferN, unitBuffer, sizeof(firstResult) - 4, firstResult + 4); - AppendMPI(result, kUnitBufferN, unitBuffer); - - ok(CFDataMatches(result, sizeof(firstResult), firstResult), "Didn't insert zero"); - - const uint8_t secondResult[] = { 0, 0, 0, 2, 1, 2, 0, 0, 0, 3, 5, 6, 7 }; - ccn_read_uint(kUnitBufferN, unitBuffer, sizeof(secondResult) - 10, secondResult + 10); - AppendMPI(result, kUnitBufferN, unitBuffer); - - ok(CFDataMatches(result, sizeof(secondResult), secondResult), "Didn't append zero"); - - CFRelease(result); - - result = CFDataCreateMutable(kCFAllocatorDefault, 0); - - const uint8_t thirdResult[] = { 0, 0, 0, 1, 1 }; - ccn_read_uint(kUnitBufferN, unitBuffer, sizeof(thirdResult) - 4, thirdResult + 4); - AppendMPI(result, kUnitBufferN, unitBuffer); - - ok(CFDataMatches(result, sizeof(thirdResult), thirdResult), "Didn't insert zero"); - - CFRelease(result); - - result = CFDataCreateMutable(kCFAllocatorDefault, 0); - - const uint8_t fourthResult[] = { 0, 0, 0, 7, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }; - ccn_read_uint(kUnitBufferN, unitBuffer, sizeof(fourthResult) - 4, fourthResult + 4); - AppendMPI(result, kUnitBufferN, unitBuffer); - - ok(CFDataMatches(result, sizeof(fourthResult), fourthResult), "Didn't insert zero"); - - CFRelease(result); - - result = CFDataCreateMutable(kCFAllocatorDefault, 0); - - const uint8_t paddedData[] = { 0, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA }; - const uint8_t shortenedResult[] = { 0, 0, 0, 5, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA }; - ccn_read_uint(kUnitBufferN, unitBuffer, sizeof(paddedData), paddedData); - AppendMPI(result, kUnitBufferN, unitBuffer); - - ok(CFDataMatches(result, sizeof(shortenedResult), shortenedResult), "Didn't insert zero"); - - CFRelease(result); - -} - -int otr_packetdata(int argc, char *const * argv) -{ - plan_tests(17); - - testAppendShort(); - testAppendLong(); - testAppendData(); - testAppendMPI(); - - return 0; -} - diff --git a/sec/Security/Regressions/secitem/si-20-sectrust.c b/sec/Security/Regressions/secitem/si-20-sectrust.c deleted file mode 100644 index 8e42f544..00000000 --- a/sec/Security/Regressions/secitem/si-20-sectrust.c +++ /dev/null @@ -1,861 +0,0 @@ -/* - * Copyright (c) 2006-2010,2012 Apple Inc. All Rights Reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Security_regressions.h" - -/* - subject= /C=US/ST=California/L=Cupertino/O=Apple Computer, Inc./OU=Apple Internet Services/OU=Terms of use at www.verisign.com/rpa (c)00/CN=store.apple.com - issuer= /O=VeriSign Trust Network/OU=VeriSign, Inc./OU=VeriSign International Server CA - Class 3/OU=www.verisign.com/CPS Incorp.by Ref. LIABILITY LTD.(c)97 VeriSign - serial=4450E623F57E734FF85C1DEEFB976C86 -*/ -static const uint8_t _c0[] = { - 0x30, 0x82, 0x04, 0x82, 0x30, 0x82, 0x03, 0xeb, - 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x44, - 0x50, 0xe6, 0x23, 0xf5, 0x7e, 0x73, 0x4f, 0xf8, - 0x5c, 0x1d, 0xee, 0xfb, 0x97, 0x6c, 0x86, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, - 0xba, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, - 0x04, 0x0a, 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, 0x17, 0x30, 0x15, 0x06, 0x03, - 0x55, 0x04, 0x0b, 0x13, 0x0e, 0x56, 0x65, 0x72, - 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, - 0x6e, 0x63, 0x2e, 0x31, 0x33, 0x30, 0x31, 0x06, - 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65, - 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x20, 0x43, 0x41, 0x20, 0x2d, - 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, - 0x31, 0x49, 0x30, 0x47, 0x06, 0x03, 0x55, 0x04, - 0x0b, 0x13, 0x40, 0x77, 0x77, 0x77, 0x2e, 0x76, - 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, 0x20, - 0x49, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x62, - 0x79, 0x20, 0x52, 0x65, 0x66, 0x2e, 0x20, 0x4c, - 0x49, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, - 0x20, 0x4c, 0x54, 0x44, 0x2e, 0x28, 0x63, 0x29, - 0x39, 0x37, 0x20, 0x56, 0x65, 0x72, 0x69, 0x53, - 0x69, 0x67, 0x6e, 0x30, 0x1e, 0x17, 0x0d, 0x30, - 0x35, 0x30, 0x33, 0x30, 0x32, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x37, - 0x30, 0x34, 0x30, 0x31, 0x32, 0x33, 0x35, 0x39, - 0x35, 0x39, 0x5a, 0x30, 0x81, 0xc6, 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, 0x14, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, - 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x1d, 0x30, 0x1b, - 0x06, 0x03, 0x55, 0x04, 0x0a, 0x14, 0x14, 0x41, - 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x6f, 0x6d, - 0x70, 0x75, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x49, - 0x6e, 0x63, 0x2e, 0x31, 0x20, 0x30, 0x1e, 0x06, - 0x03, 0x55, 0x04, 0x0b, 0x14, 0x17, 0x41, 0x70, - 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x20, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x31, 0x33, 0x30, - 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x14, 0x2a, - 0x54, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, - 0x20, 0x75, 0x73, 0x65, 0x20, 0x61, 0x74, 0x20, - 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65, 0x72, 0x69, - 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x72, 0x70, 0x61, 0x20, 0x28, 0x63, 0x29, - 0x30, 0x30, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x14, 0x0f, 0x73, 0x74, 0x6f, - 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, - 0x2e, 0x63, 0x6f, 0x6d, 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, 0xbf, 0x8f, 0x59, 0x14, 0xbb, 0x91, 0xa4, - 0xe6, 0x3e, 0x75, 0xf8, 0x38, 0x36, 0xfe, 0xcd, - 0x9e, 0x5d, 0x3f, 0x14, 0x62, 0xfc, 0xe7, 0x48, - 0x5f, 0x7e, 0x6b, 0x6e, 0x87, 0xd2, 0x31, 0x6e, - 0x9d, 0x19, 0x92, 0x6f, 0xe3, 0xbc, 0x7e, 0x48, - 0xb1, 0x2f, 0x9d, 0x70, 0x2c, 0x11, 0xdf, 0x35, - 0xd1, 0xee, 0xd2, 0xd5, 0x37, 0x92, 0x4e, 0x06, - 0x66, 0xb3, 0xc9, 0x9c, 0x99, 0xec, 0x09, 0xc6, - 0xc4, 0xd6, 0xe6, 0x62, 0xb7, 0x97, 0x24, 0xd8, - 0x38, 0x40, 0xf1, 0xa0, 0x1c, 0x0f, 0xf2, 0x3d, - 0xaf, 0x4a, 0x93, 0xba, 0x11, 0xad, 0x67, 0xc4, - 0x4b, 0x1d, 0x74, 0x33, 0x7c, 0xb9, 0x6b, 0x2d, - 0xc5, 0x9b, 0x6a, 0xd2, 0xf2, 0x28, 0x08, 0x05, - 0x18, 0x7d, 0xf0, 0xde, 0x28, 0x61, 0xf1, 0x81, - 0xd5, 0x56, 0x4f, 0x20, 0x6e, 0xf3, 0x34, 0x89, - 0x67, 0xd3, 0xa7, 0x09, 0xda, 0xc7, 0x89, 0x4d, - 0xe1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, - 0x01, 0x79, 0x30, 0x82, 0x01, 0x75, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, - 0x00, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, - 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x46, - 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x3f, 0x30, - 0x3d, 0x30, 0x3b, 0xa0, 0x39, 0xa0, 0x37, 0x86, - 0x35, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, - 0x63, 0x72, 0x6c, 0x2e, 0x76, 0x65, 0x72, 0x69, - 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x33, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x44, - 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3d, 0x30, - 0x3b, 0x30, 0x39, 0x06, 0x0b, 0x60, 0x86, 0x48, - 0x01, 0x86, 0xf8, 0x45, 0x01, 0x07, 0x17, 0x03, - 0x30, 0x2a, 0x30, 0x28, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1c, - 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, - 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65, 0x72, 0x69, - 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x72, 0x70, 0x61, 0x30, 0x28, 0x06, 0x03, - 0x55, 0x1d, 0x25, 0x04, 0x21, 0x30, 0x1f, 0x06, - 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, - 0x04, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, - 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x34, - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x01, 0x01, 0x04, 0x28, 0x30, 0x26, 0x30, 0x24, - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, - 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, - 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x6d, 0x06, 0x08, - 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x0c, - 0x04, 0x61, 0x30, 0x5f, 0xa1, 0x5d, 0xa0, 0x5b, - 0x30, 0x59, 0x30, 0x57, 0x30, 0x55, 0x16, 0x09, - 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, 0x69, - 0x66, 0x30, 0x21, 0x30, 0x1f, 0x30, 0x07, 0x06, - 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x04, 0x14, - 0x8f, 0xe5, 0xd3, 0x1a, 0x86, 0xac, 0x8d, 0x8e, - 0x6b, 0xc3, 0xcf, 0x80, 0x6a, 0xd4, 0x48, 0x18, - 0x2c, 0x7b, 0x19, 0x2e, 0x30, 0x25, 0x16, 0x23, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6c, - 0x6f, 0x67, 0x6f, 0x2e, 0x76, 0x65, 0x72, 0x69, - 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x76, 0x73, 0x6c, 0x6f, 0x67, 0x6f, 0x2e, - 0x67, 0x69, 0x66, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, - 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x01, 0x5e, - 0x47, 0x3c, 0x5f, 0x38, 0x4f, 0x4d, 0x64, 0xf1, - 0x33, 0x13, 0xd3, 0xcf, 0x80, 0xf9, 0x88, 0x93, - 0xba, 0x44, 0x7b, 0xf0, 0xbd, 0x60, 0x96, 0x39, - 0xa8, 0xc5, 0x76, 0x18, 0x01, 0xa7, 0x03, 0x53, - 0x8b, 0x92, 0xda, 0x97, 0xaa, 0x85, 0xc7, 0xb7, - 0x7d, 0x58, 0x83, 0x68, 0x4a, 0xd9, 0x54, 0x78, - 0x7f, 0xa0, 0xe9, 0x8f, 0xc5, 0xb4, 0x3a, 0xb7, - 0x3c, 0xa1, 0x70, 0x40, 0xac, 0xc2, 0xc6, 0x5b, - 0xbd, 0x70, 0x90, 0xb9, 0xc6, 0x7d, 0x7e, 0x49, - 0xe4, 0xbd, 0xc1, 0x5d, 0x1a, 0x0f, 0x9e, 0x0a, - 0x93, 0xfd, 0xc7, 0x7a, 0x8b, 0x9c, 0x61, 0x61, - 0x34, 0x02, 0xcc, 0x68, 0xdd, 0x2b, 0x29, 0xbc, - 0x83, 0x8d, 0x7a, 0x8b, 0x22, 0xb9, 0x1e, 0x79, - 0x3a, 0x5a, 0xc6, 0xda, 0xb3, 0xaf, 0xaf, 0x0b, - 0x41, 0x16, 0xda, 0xd2, 0x8e, 0xcd, 0xc1, 0xc0, - 0x43, 0xfc, 0xb3, 0x10, 0xb7, 0x27 -}; - -static const uint8_t _c0_serial[] = { - 0x44, 0x50, 0xE6, 0x23, 0xF5, 0x7E, 0x73, 0x4F, - 0xF8, 0x5C, 0x1D, 0xEE, 0xFB, 0x97, 0x6C, 0x86 -}; - -/* - subject= /O=VeriSign Trust Network/OU=VeriSign, Inc./OU=VeriSign International Server CA - Class 3/OU=www.verisign.com/CPS Incorp.by Ref. LIABILITY LTD.(c)97 VeriSign - issuer= /C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority - serial=254B8A853842CCE358F8C5DDAE226EA4 -*/ -static const uint8_t _c1[] = { - 0x30, 0x82, 0x03, 0x83, 0x30, 0x82, 0x02, 0xec, - 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x25, - 0x4b, 0x8a, 0x85, 0x38, 0x42, 0xcc, 0xe3, 0x58, - 0xf8, 0xc5, 0xdd, 0xae, 0x22, 0x6e, 0xa4, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x5f, - 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, 0x37, - 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, - 0x2e, 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, 0x30, - 0x1e, 0x17, 0x0d, 0x39, 0x37, 0x30, 0x34, 0x31, - 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, - 0x17, 0x0d, 0x31, 0x31, 0x31, 0x30, 0x32, 0x34, - 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, - 0x81, 0xba, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, - 0x55, 0x04, 0x0a, 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, 0x17, 0x30, 0x15, 0x06, - 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0e, 0x56, 0x65, - 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, - 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x33, 0x30, 0x31, - 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, - 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x20, 0x43, 0x41, 0x20, - 0x2d, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, - 0x33, 0x31, 0x49, 0x30, 0x47, 0x06, 0x03, 0x55, - 0x04, 0x0b, 0x13, 0x40, 0x77, 0x77, 0x77, 0x2e, - 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, - 0x20, 0x49, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x62, 0x79, 0x20, 0x52, 0x65, 0x66, 0x2e, 0x20, - 0x4c, 0x49, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, - 0x59, 0x20, 0x4c, 0x54, 0x44, 0x2e, 0x28, 0x63, - 0x29, 0x39, 0x37, 0x20, 0x56, 0x65, 0x72, 0x69, - 0x53, 0x69, 0x67, 0x6e, 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, 0xd8, 0x82, 0x80, 0xe8, 0xd6, 0x19, 0x02, - 0x7d, 0x1f, 0x85, 0x18, 0x39, 0x25, 0xa2, 0x65, - 0x2b, 0xe1, 0xbf, 0xd4, 0x05, 0xd3, 0xbc, 0xe6, - 0x36, 0x3b, 0xaa, 0xf0, 0x4c, 0x6c, 0x5b, 0xb6, - 0xe7, 0xaa, 0x3c, 0x73, 0x45, 0x55, 0xb2, 0xf1, - 0xbd, 0xea, 0x97, 0x42, 0xed, 0x9a, 0x34, 0x0a, - 0x15, 0xd4, 0xa9, 0x5c, 0xf5, 0x40, 0x25, 0xdd, - 0xd9, 0x07, 0xc1, 0x32, 0xb2, 0x75, 0x6c, 0xc4, - 0xca, 0xbb, 0xa3, 0xfe, 0x56, 0x27, 0x71, 0x43, - 0xaa, 0x63, 0xf5, 0x30, 0x3e, 0x93, 0x28, 0xe5, - 0xfa, 0xf1, 0x09, 0x3b, 0xf3, 0xb7, 0x4d, 0x4e, - 0x39, 0xf7, 0x5c, 0x49, 0x5a, 0xb8, 0xc1, 0x1d, - 0xd3, 0xb2, 0x8a, 0xfe, 0x70, 0x30, 0x95, 0x42, - 0xcb, 0xfe, 0x2b, 0x51, 0x8b, 0x5a, 0x3c, 0x3a, - 0xf9, 0x22, 0x4f, 0x90, 0xb2, 0x02, 0xa7, 0x53, - 0x9c, 0x4f, 0x34, 0xe7, 0xab, 0x04, 0xb2, 0x7b, - 0x6f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, - 0xe3, 0x30, 0x81, 0xe0, 0x30, 0x0f, 0x06, 0x03, - 0x55, 0x1d, 0x13, 0x04, 0x08, 0x30, 0x06, 0x01, - 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x44, 0x06, - 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3d, 0x30, 0x3b, - 0x30, 0x39, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, - 0x86, 0xf8, 0x45, 0x01, 0x07, 0x01, 0x01, 0x30, - 0x2a, 0x30, 0x28, 0x06, 0x08, 0x2b, 0x06, 0x01, - 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1c, 0x68, - 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, - 0x77, 0x77, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, - 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x43, 0x50, 0x53, 0x30, 0x34, 0x06, 0x03, 0x55, - 0x1d, 0x25, 0x04, 0x2d, 0x30, 0x2b, 0x06, 0x08, - 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x03, 0x02, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, - 0x86, 0xf8, 0x42, 0x04, 0x01, 0x06, 0x0a, 0x60, - 0x86, 0x48, 0x01, 0x86, 0xf8, 0x45, 0x01, 0x08, - 0x01, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, - 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x11, - 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, - 0x42, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x01, - 0x06, 0x30, 0x31, 0x06, 0x03, 0x55, 0x1d, 0x1f, - 0x04, 0x2a, 0x30, 0x28, 0x30, 0x26, 0xa0, 0x24, - 0xa0, 0x22, 0x86, 0x20, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x76, - 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x63, 0x61, 0x33, - 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x08, - 0x01, 0xec, 0xe4, 0x68, 0x94, 0x03, 0x42, 0xf1, - 0x73, 0xf1, 0x23, 0xa2, 0x3a, 0xde, 0xe9, 0xf1, - 0xda, 0xc6, 0x54, 0xc4, 0x23, 0x3e, 0x86, 0xea, - 0xcf, 0x6a, 0x3a, 0x33, 0xab, 0xea, 0x9c, 0x04, - 0x14, 0x07, 0x36, 0x06, 0x0b, 0xf9, 0x88, 0x6f, - 0xd5, 0x13, 0xee, 0x29, 0x2b, 0xc3, 0xe4, 0x72, - 0x8d, 0x44, 0xed, 0xd1, 0xac, 0x20, 0x09, 0x2d, - 0xe1, 0xf6, 0xe1, 0x19, 0x05, 0x38, 0xb0, 0x3d, - 0x0f, 0x9f, 0x7f, 0xf8, 0x9e, 0x02, 0xdc, 0x86, - 0x02, 0x86, 0x61, 0x4e, 0x26, 0x5f, 0x5e, 0x9f, - 0x92, 0x1e, 0x0c, 0x24, 0xa4, 0xf5, 0xd0, 0x70, - 0x13, 0xcf, 0x26, 0xc3, 0x43, 0x3d, 0x49, 0x1d, - 0x9e, 0x82, 0x2e, 0x52, 0x5f, 0xbc, 0x3e, 0xc6, - 0x66, 0x29, 0x01, 0x8e, 0x4e, 0x92, 0x2c, 0xbc, - 0x46, 0x75, 0x03, 0x82, 0xac, 0x73, 0xe9, 0xd9, - 0x7e, 0x0b, 0x67, 0xef, 0x54, 0x52, 0x1a -}; - - -/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc/OU=Internet Operations/CN=xedge2.apple.com - issuer :/C=US/O=Entrust.net/OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Secure Server Certification Authority */ -const uint8_t xedge2_certificate[1385]={ -0x30,0x82,0x05,0x65,0x30,0x82,0x04,0xCE,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x46, -0x9C,0xDF,0x96,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05, -0x05,0x00,0x30,0x81,0xC3,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, -0x55,0x53,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x13,0x0B,0x45,0x6E,0x74, -0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x31,0x3B,0x30,0x39,0x06,0x03,0x55,0x04, -0x0B,0x13,0x32,0x77,0x77,0x77,0x2E,0x65,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E, -0x65,0x74,0x2F,0x43,0x50,0x53,0x20,0x69,0x6E,0x63,0x6F,0x72,0x70,0x2E,0x20,0x62, -0x79,0x20,0x72,0x65,0x66,0x2E,0x20,0x28,0x6C,0x69,0x6D,0x69,0x74,0x73,0x20,0x6C, -0x69,0x61,0x62,0x2E,0x29,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x0B,0x13,0x1C, -0x28,0x63,0x29,0x20,0x31,0x39,0x39,0x39,0x20,0x45,0x6E,0x74,0x72,0x75,0x73,0x74, -0x2E,0x6E,0x65,0x74,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65,0x64,0x31,0x3A,0x30,0x38, -0x06,0x03,0x55,0x04,0x03,0x13,0x31,0x45,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E, -0x65,0x74,0x20,0x53,0x65,0x63,0x75,0x72,0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72, -0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, -0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x1E,0x17,0x0D,0x30,0x38,0x30,0x31, -0x32,0x39,0x31,0x38,0x33,0x33,0x31,0x33,0x5A,0x17,0x0D,0x31,0x30,0x30,0x31,0x32, -0x38,0x31,0x39,0x30,0x33,0x31,0x32,0x5A,0x30,0x81,0x83,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,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x0A,0x13,0x09,0x41,0x70,0x70,0x6C, -0x65,0x20,0x49,0x6E,0x63,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04,0x0B,0x13,0x13, -0x49,0x6E,0x74,0x65,0x72,0x6E,0x65,0x74,0x20,0x4F,0x70,0x65,0x72,0x61,0x74,0x69, -0x6F,0x6E,0x73,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x03,0x13,0x10,0x78,0x65, -0x64,0x67,0x65,0x32,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,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,0xC7,0xF3,0xA1,0x0E,0x0E, -0xA4,0xDF,0xC5,0x3F,0x24,0x87,0xC3,0x6E,0xE7,0xD0,0x7C,0x2B,0x5A,0x1C,0xF3,0x67, -0x6C,0x6B,0x56,0x0A,0x95,0xC9,0xE5,0x13,0x28,0x6E,0x16,0x9D,0x4F,0xB1,0x76,0xFB, -0x7D,0x42,0x5B,0x2A,0x7C,0xCC,0x97,0x75,0xAA,0xA6,0xA9,0xDE,0xB2,0xEC,0xEF,0xE2, -0xAB,0x40,0xAE,0x9A,0x23,0xF0,0x6A,0x10,0xB3,0x75,0x27,0xF0,0xF4,0x7D,0x08,0x67, -0x8F,0xCE,0x41,0x24,0x74,0xAA,0x37,0xB6,0xC1,0x32,0x61,0xCF,0x7D,0x1C,0x21,0xCD, -0xCF,0x7C,0x9E,0xE2,0x48,0x03,0x7E,0x78,0xB3,0x86,0x3D,0x06,0x6B,0x39,0xEC,0xC8, -0x73,0x68,0xDB,0xE7,0x5B,0x97,0xF4,0xF9,0xA3,0xE7,0xFB,0x81,0x2E,0x4D,0x0B,0x3F, -0xA9,0xCA,0xDE,0x32,0x26,0xF3,0xF0,0x97,0x72,0x65,0xAB,0x02,0x03,0x01,0x00,0x01, -0xA3,0x82,0x02,0xA2,0x30,0x82,0x02,0x9E,0x30,0x0B,0x06,0x03,0x55,0x1D,0x0F,0x04, -0x04,0x03,0x02,0x05,0xA0,0x30,0x2B,0x06,0x03,0x55,0x1D,0x10,0x04,0x24,0x30,0x22, -0x80,0x0F,0x32,0x30,0x30,0x38,0x30,0x31,0x32,0x39,0x31,0x38,0x33,0x33,0x31,0x33, -0x5A,0x81,0x0F,0x32,0x30,0x31,0x30,0x30,0x31,0x32,0x38,0x31,0x39,0x30,0x33,0x31, -0x32,0x5A,0x30,0x11,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x01,0x04, -0x04,0x03,0x02,0x06,0x40,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A, -0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x82,0x01,0x68,0x06,0x03, -0x55,0x1D,0x20,0x04,0x82,0x01,0x5F,0x30,0x82,0x01,0x5B,0x30,0x82,0x01,0x57,0x06, -0x09,0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x4B,0x02,0x30,0x82,0x01,0x48,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,0x65,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E, -0x65,0x74,0x2F,0x63,0x70,0x73,0x30,0x82,0x01,0x1C,0x06,0x08,0x2B,0x06,0x01,0x05, -0x05,0x07,0x02,0x02,0x30,0x82,0x01,0x0E,0x1A,0x82,0x01,0x0A,0x54,0x68,0x65,0x20, -0x45,0x6E,0x74,0x72,0x75,0x73,0x74,0x20,0x53,0x53,0x4C,0x20,0x57,0x65,0x62,0x20, -0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61, -0x74,0x69,0x6F,0x6E,0x20,0x50,0x72,0x61,0x63,0x74,0x69,0x63,0x65,0x20,0x53,0x74, -0x61,0x74,0x65,0x6D,0x65,0x6E,0x74,0x20,0x28,0x43,0x50,0x53,0x29,0x20,0x61,0x76, -0x61,0x69,0x6C,0x61,0x62,0x6C,0x65,0x20,0x61,0x74,0x20,0x77,0x77,0x77,0x2E,0x65, -0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x2F,0x63,0x70,0x73,0x20,0x20, -0x69,0x73,0x20,0x68,0x65,0x72,0x65,0x62,0x79,0x20,0x69,0x6E,0x63,0x6F,0x72,0x70, -0x6F,0x72,0x61,0x74,0x65,0x64,0x20,0x69,0x6E,0x74,0x6F,0x20,0x79,0x6F,0x75,0x72, -0x20,0x75,0x73,0x65,0x20,0x6F,0x72,0x20,0x72,0x65,0x6C,0x69,0x61,0x6E,0x63,0x65, -0x20,0x6F,0x6E,0x20,0x74,0x68,0x69,0x73,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69, -0x63,0x61,0x74,0x65,0x2E,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x43,0x50,0x53,0x20, -0x63,0x6F,0x6E,0x74,0x61,0x69,0x6E,0x73,0x20,0x6C,0x69,0x6D,0x69,0x74,0x61,0x74, -0x69,0x6F,0x6E,0x73,0x20,0x6F,0x6E,0x20,0x77,0x61,0x72,0x72,0x61,0x6E,0x74,0x69, -0x65,0x73,0x20,0x61,0x6E,0x64,0x20,0x6C,0x69,0x61,0x62,0x69,0x6C,0x69,0x74,0x69, -0x65,0x73,0x2E,0x20,0x43,0x6F,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x28,0x63, -0x29,0x20,0x32,0x30,0x30,0x32,0x20,0x45,0x6E,0x74,0x72,0x75,0x73,0x74,0x20,0x4C, -0x69,0x6D,0x69,0x74,0x65,0x64,0x30,0x33,0x06,0x03,0x55,0x1D,0x1F,0x04,0x2C,0x30, -0x2A,0x30,0x28,0xA0,0x26,0xA0,0x24,0x86,0x22,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, -0x63,0x72,0x6C,0x2E,0x65,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x2F, -0x73,0x65,0x72,0x76,0x65,0x72,0x31,0x2E,0x63,0x72,0x6C,0x30,0x33,0x06,0x08,0x2B, -0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x27,0x30,0x25,0x30,0x23,0x06,0x08,0x2B, -0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x17,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, -0x6F,0x63,0x73,0x70,0x2E,0x65,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74, -0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xF0,0x17,0x62, -0x13,0x55,0x3D,0xB3,0xFF,0x0A,0x00,0x6B,0xFB,0x50,0x84,0x97,0xF3,0xED,0x62,0xD0, -0x1A,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x2D,0xEF,0xD9,0xAF, -0x1A,0x89,0x40,0x53,0x75,0x48,0x26,0x59,0x2F,0xEC,0x11,0x18,0xC0,0xD1,0x7A,0x34, -0x30,0x09,0x06,0x03,0x55,0x1D,0x13,0x04,0x02,0x30,0x00,0x30,0x19,0x06,0x09,0x2A, -0x86,0x48,0x86,0xF6,0x7D,0x07,0x41,0x00,0x04,0x0C,0x30,0x0A,0x1B,0x04,0x56,0x37, -0x2E,0x31,0x03,0x02,0x03,0x28,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, -0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0x77,0x33,0x2A,0x69,0x45,0x5A,0xB2, -0xF5,0x74,0xF7,0xDF,0xC7,0x08,0x85,0x86,0x88,0x98,0x41,0x7F,0x57,0x49,0x01,0xBA, -0x13,0x21,0x40,0xD0,0x0A,0x5C,0xA7,0x37,0xDF,0xB3,0x7E,0xF8,0xED,0x04,0x63,0xC3, -0xE8,0x0F,0xA0,0xE5,0xC4,0x4F,0x3A,0x90,0xE4,0x87,0x5F,0xEC,0xDB,0x65,0x8B,0x6E, -0x88,0x6E,0x6E,0xE4,0xBC,0x6A,0x7E,0x37,0x47,0x04,0xFF,0x09,0xC6,0x70,0xE1,0x65, -0x8F,0xE3,0xE9,0x60,0xEB,0xE8,0x8E,0x29,0xAE,0xF9,0x81,0xCA,0x9A,0x97,0x3C,0x6F, -0x7C,0xFA,0xA8,0x49,0xB4,0x33,0x76,0x9C,0x65,0x92,0x12,0xF6,0x7F,0x6A,0x62,0x84, -0x29,0x5F,0x14,0x26,0x6E,0x07,0x6F,0x5C,0xB5,0x7C,0x21,0x64,0x7C,0xD9,0x93,0xF4, -0x9C,0xC8,0xE7,0xEC,0xC6,0xAC,0x13,0xC4,0xF0 -}; - - -/* subject:/CN=garthc2.apple.com/O=Apple Inc./OU=DTS/ST=California/C=US/L=Cupertino/emailAddress=gcummings@apple.com - issuer :/CN=garthc2.apple.com/O=Apple Inc./OU=DTS/ST=California/C=US/L=Cupertino/emailAddress=gcummings@apple.com */ -const uint8_t garthc2_certificate[730]={ -0x30,0x82,0x02,0xD6,0x30,0x82,0x02,0x3F,0xA0,0x03,0x02,0x01,0x02,0x02,0x01,0x01, -0x30,0x0B,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x30,0x81,0x99, -0x31,0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x03,0x0C,0x11,0x67,0x61,0x72,0x74,0x68, -0x63,0x32,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x31,0x13,0x30,0x11, -0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63, -0x2E,0x31,0x0C,0x30,0x0A,0x06,0x03,0x55,0x04,0x0B,0x0C,0x03,0x44,0x54,0x53,0x31, -0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F, -0x72,0x6E,0x69,0x61,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, -0x53,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65, -0x72,0x74,0x69,0x6E,0x6F,0x31,0x22,0x30,0x20,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, -0x0D,0x01,0x09,0x01,0x16,0x13,0x67,0x63,0x75,0x6D,0x6D,0x69,0x6E,0x67,0x73,0x40, -0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x1E,0x17,0x0D,0x30,0x39,0x30, -0x37,0x31,0x36,0x32,0x32,0x34,0x39,0x31,0x30,0x5A,0x17,0x0D,0x31,0x30,0x30,0x37, -0x31,0x36,0x32,0x32,0x34,0x39,0x31,0x30,0x5A,0x30,0x81,0x99,0x31,0x1A,0x30,0x18, -0x06,0x03,0x55,0x04,0x03,0x0C,0x11,0x67,0x61,0x72,0x74,0x68,0x63,0x32,0x2E,0x61, -0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, -0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0C,0x30, -0x0A,0x06,0x03,0x55,0x04,0x0B,0x0C,0x03,0x44,0x54,0x53,0x31,0x13,0x30,0x11,0x06, -0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61, -0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x12,0x30, -0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E, -0x6F,0x31,0x22,0x30,0x20,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x01, -0x16,0x13,0x67,0x63,0x75,0x6D,0x6D,0x69,0x6E,0x67,0x73,0x40,0x61,0x70,0x70,0x6C, -0x65,0x2E,0x63,0x6F,0x6D,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,0xCF,0x30,0xD9,0x9D,0x9C,0xD5,0x6F,0xCB,0xB1,0xD1,0xC2,0x73,0xE2,0xB4, -0x06,0xC3,0x16,0x6D,0x0E,0x68,0x40,0x5E,0x92,0xFC,0xD9,0x14,0xD2,0x5E,0x21,0x50, -0x66,0x41,0x96,0x3A,0x76,0x26,0xF6,0x6C,0x3C,0xA2,0xD4,0x84,0x91,0x09,0x2E,0x23, -0x2D,0x07,0x38,0x48,0x58,0x31,0xE5,0x00,0x08,0xB1,0x6C,0x5D,0x39,0x50,0x30,0xF7, -0x68,0x12,0x99,0xB5,0x4C,0x86,0x1E,0xA5,0xF4,0x0C,0xCB,0xCB,0x25,0xB0,0x7C,0x6A, -0xFE,0x28,0xD4,0x34,0xA5,0xD2,0x94,0x5E,0xBE,0x5F,0xC1,0x61,0xAE,0xB5,0xD2,0xD2, -0x18,0x34,0x07,0x02,0xA8,0x56,0xAC,0x55,0x4D,0x87,0x56,0x8A,0xBA,0x1B,0x17,0x26, -0x11,0x9B,0xF8,0x88,0xD1,0x4F,0x94,0x03,0x01,0xCC,0x01,0xE7,0x0B,0x9B,0x14,0x43, -0x25,0xFB,0x02,0x03,0x01,0x00,0x01,0xA3,0x2E,0x30,0x2C,0x30,0x0B,0x06,0x03,0x55, -0x1D,0x0F,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,0x02,0x06,0x08,0x2B, -0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, -0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0x9D,0x8A,0x8A,0x9F,0xA5,0x36, -0xA2,0xE6,0x1D,0xA9,0xF1,0x10,0xDF,0xC8,0xFC,0x1A,0x2B,0xA0,0x01,0x07,0x58,0xA4, -0xD0,0x41,0xE1,0x32,0xD8,0xA9,0x84,0x9E,0xF3,0xE2,0xDE,0x48,0xD3,0x03,0xD7,0xC9, -0x40,0x58,0x5A,0x91,0x85,0x70,0xF6,0xC7,0x34,0x90,0x3C,0x1B,0x06,0x8F,0x0C,0xEE, -0xDD,0x79,0x14,0x42,0x72,0x4F,0x41,0xF9,0xB0,0xEC,0x04,0x9F,0xD6,0x75,0x68,0x06, -0xA0,0xEA,0x11,0x0C,0xE9,0x16,0x2F,0x9E,0x23,0xFA,0x5D,0xC2,0x02,0x92,0x2A,0xDD, -0xE8,0xBD,0xA1,0x8F,0x33,0x96,0x84,0xFA,0xFD,0x3C,0x70,0xD4,0x9D,0x43,0xA4,0xA0, -0xE9,0xF4,0x49,0xB2,0xF4,0xCB,0x9F,0x43,0x87,0x04,0x8D,0xD0,0xEA,0xAC,0x21,0x24, -0x2C,0x4C,0x36,0x5C,0x34,0x8C,0x61,0xA4,0xF4,0xB8, -}; - -const uint8_t prt_forest_fi_certificate[1797] = { - 0x30, 0x82, 0x07, 0x01, 0x30, 0x82, 0x05, 0xe9, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x11, 0x00, 0xfa, 0x69, 0x1a, 0xa7, 0xbf, 0x1b, 0x93, 0xbe, - 0x97, 0x11, 0xb0, 0xfe, 0xfc, 0xa8, 0x8d, 0x8c, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, - 0x39, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x46, 0x49, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x06, 0x53, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x31, 0x19, 0x30, 0x17, 0x06, - 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x53, 0x6f, 0x6e, 0x65, 0x72, 0x61, - 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x32, 0x20, 0x43, 0x41, 0x30, 0x1e, - 0x17, 0x0d, 0x31, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x39, 0x33, 0x39, - 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x31, 0x31, 0x33, 0x30, 0x30, - 0x39, 0x33, 0x39, 0x33, 0x33, 0x5a, 0x30, 0x57, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x46, 0x49, 0x31, 0x16, 0x30, - 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0d, 0x50, 0x52, 0x54, 0x2d, - 0x46, 0x6f, 0x72, 0x65, 0x73, 0x74, 0x20, 0x4f, 0x79, 0x31, 0x16, 0x30, - 0x14, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x0d, 0x54, 0x69, 0x65, 0x74, - 0x6f, 0x68, 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x74, 0x6f, 0x31, 0x18, 0x30, - 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x2a, 0x2e, 0x70, 0x72, - 0x74, 0x2d, 0x66, 0x6f, 0x72, 0x65, 0x73, 0x74, 0x2e, 0x66, 0x69, 0x30, - 0x82, 0x04, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x04, 0x0f, 0x00, 0x30, - 0x82, 0x04, 0x0a, 0x02, 0x82, 0x04, 0x01, 0x00, 0xbc, 0x62, 0x25, 0x57, - 0xbc, 0x71, 0xb8, 0xa9, 0x5b, 0x0e, 0x04, 0xbc, 0xc4, 0x0e, 0xf1, 0x0e, - 0x1f, 0x20, 0xd2, 0xf4, 0x4f, 0x23, 0xfe, 0x14, 0x54, 0x34, 0x81, 0xd3, - 0x5b, 0xdd, 0x74, 0xed, 0xa1, 0xbe, 0x91, 0x99, 0x9d, 0x02, 0xb9, 0x36, - 0x70, 0x43, 0x5d, 0x73, 0xa6, 0xe5, 0x70, 0x7b, 0x0e, 0x0c, 0x3f, 0x33, - 0xbb, 0x71, 0xd6, 0xd4, 0x22, 0xb0, 0xeb, 0xf5, 0x6e, 0x07, 0x7c, 0xe7, - 0xc7, 0xd1, 0x20, 0x64, 0x72, 0x4e, 0xae, 0x5e, 0xae, 0xaf, 0x08, 0xfb, - 0x7d, 0x6d, 0xdb, 0x69, 0x5a, 0x31, 0x73, 0x7d, 0xbd, 0x53, 0xcb, 0x04, - 0x69, 0x6d, 0x74, 0x56, 0x6c, 0xbc, 0x84, 0xa6, 0x01, 0x39, 0x37, 0x0c, - 0xb9, 0x5c, 0x2e, 0x78, 0x50, 0x3a, 0x8d, 0x1f, 0xa2, 0x33, 0xf1, 0xd2, - 0xc2, 0x87, 0x51, 0xf4, 0x92, 0xc3, 0xa7, 0xaa, 0xc8, 0x36, 0x51, 0x1c, - 0xfb, 0x77, 0xbf, 0xcf, 0x24, 0x11, 0xfe, 0xf4, 0x11, 0x2f, 0x5c, 0xdf, - 0x26, 0xf6, 0xb9, 0x15, 0xc1, 0x46, 0x75, 0x83, 0x40, 0x77, 0xa4, 0x83, - 0x74, 0xce, 0xc0, 0x29, 0x31, 0xd3, 0xd8, 0x68, 0xfa, 0x2e, 0xcc, 0x15, - 0x2c, 0x59, 0x5c, 0xa7, 0x96, 0x65, 0x8f, 0x34, 0x87, 0x29, 0x22, 0x1d, - 0xde, 0x65, 0xc7, 0x1c, 0x5c, 0xd8, 0x33, 0x22, 0xf7, 0x93, 0xd9, 0xcd, - 0x96, 0x76, 0x22, 0xab, 0x75, 0x18, 0x04, 0xe7, 0x65, 0x2a, 0xeb, 0x42, - 0x75, 0x17, 0x13, 0x12, 0x00, 0xe3, 0xf4, 0xd9, 0xde, 0xd1, 0x9f, 0x1c, - 0x61, 0xee, 0xf6, 0xb9, 0xf9, 0x50, 0xb3, 0x1b, 0x79, 0x77, 0x38, 0x3c, - 0x6a, 0xcc, 0xa0, 0x1d, 0xe4, 0xd7, 0x43, 0xca, 0x8b, 0x22, 0xbf, 0x77, - 0x33, 0xea, 0xaa, 0x01, 0xcf, 0x1e, 0xd0, 0x0d, 0x04, 0x2b, 0xec, 0x42, - 0x7b, 0xec, 0x53, 0xed, 0xc7, 0x4f, 0x0c, 0xac, 0x29, 0xb7, 0x8b, 0x92, - 0x14, 0x3f, 0x9b, 0xc6, 0xd8, 0xa1, 0x30, 0x4d, 0x5a, 0x07, 0x0e, 0x1e, - 0x80, 0x5f, 0x38, 0x66, 0x4d, 0xc1, 0xad, 0x2f, 0xee, 0xae, 0x94, 0x50, - 0x8e, 0x38, 0x2a, 0x00, 0x80, 0xe2, 0xc4, 0x43, 0x2e, 0xd5, 0xcd, 0xca, - 0x3f, 0x3d, 0xcb, 0x35, 0x13, 0x96, 0xd2, 0xdc, 0x0e, 0xe7, 0x45, 0x57, - 0x4b, 0x8f, 0xee, 0xa1, 0xce, 0xe6, 0x57, 0x52, 0xcd, 0xd0, 0x82, 0xca, - 0x3b, 0x87, 0xf4, 0x22, 0xff, 0x81, 0x4b, 0xf5, 0xa3, 0xda, 0xc5, 0xb6, - 0x67, 0xb8, 0xf4, 0xaf, 0xff, 0x8d, 0x4e, 0x80, 0xb5, 0x22, 0x80, 0x3c, - 0x70, 0xe4, 0xa0, 0xae, 0xdc, 0xcf, 0x44, 0xff, 0x00, 0x98, 0x3f, 0x19, - 0x7b, 0x4c, 0x3d, 0xd8, 0xa5, 0xd8, 0xe0, 0x05, 0x73, 0x54, 0x06, 0x0c, - 0x4d, 0x50, 0xf8, 0xd8, 0x85, 0x0b, 0xa8, 0x49, 0xaa, 0x97, 0x87, 0x3b, - 0x32, 0xe8, 0x58, 0x22, 0xee, 0x34, 0x1c, 0x9f, 0xe3, 0x18, 0xba, 0x93, - 0x43, 0xea, 0xb7, 0x78, 0x35, 0xa2, 0xb5, 0x1e, 0x19, 0x16, 0x3b, 0xb3, - 0xf5, 0x12, 0xe8, 0x26, 0x62, 0x2d, 0xd7, 0x45, 0xc3, 0xa4, 0x4b, 0xda, - 0x38, 0x48, 0x00, 0x3f, 0x68, 0x62, 0xa2, 0x83, 0x9d, 0x32, 0x76, 0x27, - 0x40, 0x5d, 0x0e, 0x75, 0xb1, 0x08, 0xdb, 0x58, 0xfa, 0x20, 0x62, 0xf1, - 0x3f, 0xbd, 0x86, 0x2f, 0x7c, 0x07, 0x01, 0x14, 0x1d, 0x19, 0x61, 0xee, - 0x0a, 0x85, 0xbf, 0xc7, 0x4f, 0x4a, 0x06, 0xc0, 0xaf, 0x44, 0x5d, 0x6f, - 0xc3, 0x53, 0x23, 0xcb, 0xdf, 0x40, 0x7a, 0x18, 0xa1, 0x34, 0x80, 0x18, - 0x86, 0xfe, 0xe3, 0x87, 0xce, 0x30, 0x53, 0x33, 0x1c, 0x45, 0x4a, 0xb4, - 0xe1, 0x8c, 0x9b, 0x4b, 0xf5, 0x2c, 0x7c, 0x13, 0x56, 0x37, 0x8a, 0x94, - 0x24, 0xdb, 0x3a, 0x4b, 0x80, 0xb1, 0x26, 0x57, 0x5a, 0x75, 0x1c, 0x44, - 0xc5, 0xf7, 0x67, 0xb4, 0x61, 0x87, 0xe8, 0x2e, 0xd9, 0xe1, 0xb9, 0x45, - 0xcc, 0xdc, 0xdf, 0x3b, 0x8c, 0xce, 0xd0, 0x46, 0x6b, 0x87, 0xb5, 0xa9, - 0xfe, 0x35, 0x87, 0xe0, 0xca, 0xc6, 0x7d, 0xc8, 0x86, 0xc2, 0xfe, 0x89, - 0xec, 0xa9, 0x86, 0x33, 0x81, 0xdc, 0x41, 0xb3, 0xe7, 0xc4, 0x82, 0x3a, - 0x81, 0x05, 0xbd, 0x8b, 0x92, 0xb2, 0x6a, 0x2c, 0x3c, 0xca, 0xd0, 0x22, - 0xff, 0xc8, 0x8f, 0xf0, 0x5f, 0x0e, 0xfb, 0x0b, 0x36, 0x64, 0x6a, 0x12, - 0x77, 0x2d, 0x8a, 0x38, 0xde, 0x7d, 0xed, 0xc9, 0xa7, 0xc1, 0x85, 0x41, - 0xa2, 0x7b, 0xa5, 0xdc, 0x30, 0x96, 0xda, 0xf8, 0xb3, 0xc8, 0x21, 0x56, - 0x3c, 0xdb, 0xe4, 0x8c, 0xb0, 0xfb, 0xec, 0x0e, 0x58, 0x49, 0x3c, 0x75, - 0x3c, 0xc2, 0x41, 0xbd, 0xc0, 0x81, 0x37, 0xc7, 0x69, 0x5a, 0x41, 0x86, - 0x18, 0xe9, 0x41, 0x7f, 0xba, 0xff, 0xc3, 0x52, 0x56, 0xf9, 0x7c, 0x60, - 0x14, 0xf9, 0x66, 0x4c, 0x60, 0xb6, 0x3e, 0x23, 0xcd, 0xd1, 0x2d, 0x4f, - 0x43, 0x97, 0xea, 0xa3, 0x37, 0xa4, 0x2a, 0xa7, 0x81, 0x49, 0x90, 0xe3, - 0xb6, 0x12, 0x1b, 0xac, 0x78, 0x57, 0x20, 0x51, 0xb4, 0x16, 0x5e, 0x58, - 0x61, 0x0f, 0x1e, 0x35, 0xbc, 0x3f, 0x44, 0xc2, 0x85, 0xa5, 0x61, 0x8a, - 0x0a, 0x7c, 0x2e, 0xb0, 0x11, 0x12, 0xc6, 0xc0, 0xc8, 0xcb, 0xd8, 0x13, - 0xc3, 0x58, 0xf1, 0xcd, 0x06, 0x5f, 0x90, 0xa5, 0xd7, 0x74, 0xbc, 0x1a, - 0x9c, 0xdc, 0xab, 0xde, 0xea, 0x36, 0x67, 0x41, 0x4f, 0x62, 0x86, 0xc6, - 0xfe, 0x63, 0x14, 0x83, 0x11, 0xab, 0xfb, 0x61, 0x38, 0x11, 0xce, 0x01, - 0xe8, 0xee, 0x3a, 0x21, 0xbc, 0xaa, 0x4b, 0xb0, 0x8f, 0x2f, 0xcf, 0x58, - 0xe6, 0x55, 0x61, 0x38, 0xa7, 0xc3, 0xaa, 0x3b, 0xb0, 0x8c, 0xf4, 0x82, - 0xa0, 0x96, 0xc4, 0x13, 0x4a, 0xc0, 0xc8, 0x93, 0xb7, 0x3d, 0x28, 0x05, - 0xb9, 0xc8, 0x4c, 0xe8, 0x57, 0xda, 0x56, 0x8b, 0xda, 0x27, 0xab, 0xbf, - 0x7e, 0x66, 0x43, 0xdc, 0x57, 0x09, 0xdc, 0x88, 0x8e, 0xfb, 0xa7, 0x63, - 0x41, 0xfb, 0xf1, 0x67, 0xb5, 0xe1, 0x84, 0x5d, 0x1d, 0xe3, 0xb4, 0xc6, - 0x40, 0x97, 0xf8, 0x4d, 0xfc, 0x00, 0xcd, 0x56, 0xc2, 0xab, 0xff, 0x49, - 0x93, 0xff, 0x46, 0x56, 0x9b, 0xee, 0x6d, 0xa0, 0x5d, 0xf4, 0x78, 0x36, - 0x0e, 0xf6, 0xc9, 0x9c, 0x79, 0x89, 0xf9, 0x9c, 0xa7, 0x3e, 0xa0, 0x8d, - 0x62, 0x7c, 0xdc, 0x83, 0x0a, 0xfc, 0x46, 0x96, 0x31, 0xd3, 0x56, 0xc6, - 0xea, 0x7f, 0x1d, 0xaa, 0x49, 0xd1, 0x8b, 0x54, 0xa2, 0x6e, 0x59, 0x8c, - 0x2a, 0xec, 0x3a, 0xd7, 0xda, 0xd2, 0xc1, 0xfc, 0x1d, 0x78, 0x55, 0xce, - 0xd8, 0x0c, 0x1d, 0x7e, 0x99, 0xf8, 0x5e, 0x3c, 0x2d, 0xec, 0x63, 0xe2, - 0xda, 0xa1, 0x68, 0x6f, 0x28, 0x2e, 0xb4, 0xef, 0x07, 0xc4, 0xa8, 0x65, - 0xc7, 0xfd, 0x6b, 0x0f, 0x83, 0x23, 0xf8, 0xc2, 0xc9, 0x55, 0xfa, 0xa4, - 0xa8, 0x6a, 0xab, 0x12, 0xf4, 0x89, 0x42, 0x26, 0x72, 0xd1, 0x82, 0x2f, - 0x62, 0x14, 0xb6, 0x04, 0x23, 0x20, 0xb6, 0xd4, 0xef, 0x59, 0x8a, 0x40, - 0x43, 0xd7, 0x72, 0xe0, 0x5b, 0x0c, 0xb0, 0x73, 0x6f, 0x6a, 0x87, 0xc1, - 0x82, 0x50, 0x20, 0xdb, 0xaa, 0xf8, 0x8d, 0x70, 0xb6, 0x39, 0x46, 0xe0, - 0x68, 0xc4, 0xab, 0xea, 0xd1, 0x31, 0xad, 0xf7, 0x05, 0xfb, 0x3a, 0x3c, - 0x2e, 0x66, 0x4f, 0xc6, 0x0d, 0xf9, 0xb8, 0x29, 0xec, 0xdc, 0xfc, 0x81, - 0x56, 0x2b, 0xb0, 0xad, 0xd2, 0x12, 0x8f, 0x69, 0x70, 0x18, 0x27, 0x16, - 0xf9, 0xf0, 0x40, 0x93, 0xef, 0x6b, 0x95, 0x96, 0xcd, 0x5f, 0xe9, 0x5a, - 0x7b, 0xad, 0x7f, 0x98, 0xa7, 0x6a, 0xe5, 0x17, 0xeb, 0xc3, 0xdd, 0xc9, - 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xe5, 0x30, 0x81, 0xe2, 0x30, - 0x13, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x0c, 0x30, 0x0a, 0x80, 0x08, - 0x4a, 0xa0, 0xaa, 0x58, 0x84, 0xd3, 0x5e, 0x3c, 0x30, 0x19, 0x06, 0x03, - 0x55, 0x1d, 0x20, 0x04, 0x12, 0x30, 0x10, 0x30, 0x0e, 0x06, 0x0c, 0x2b, - 0x06, 0x01, 0x04, 0x01, 0x82, 0x0f, 0x02, 0x03, 0x01, 0x01, 0x02, 0x30, - 0x72, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x6b, 0x30, 0x69, 0x30, 0x67, - 0xa0, 0x65, 0xa0, 0x63, 0x86, 0x61, 0x6c, 0x64, 0x61, 0x70, 0x3a, 0x2f, - 0x2f, 0x31, 0x39, 0x34, 0x2e, 0x32, 0x35, 0x32, 0x2e, 0x31, 0x32, 0x34, - 0x2e, 0x32, 0x34, 0x31, 0x3a, 0x33, 0x38, 0x39, 0x2f, 0x63, 0x6e, 0x3d, - 0x53, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x25, 0x32, 0x30, 0x43, 0x6c, 0x61, - 0x73, 0x73, 0x32, 0x25, 0x32, 0x30, 0x43, 0x41, 0x2c, 0x6f, 0x3d, 0x53, - 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x2c, 0x63, 0x3d, 0x46, 0x49, 0x3f, 0x63, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x72, 0x65, - 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6c, 0x69, 0x73, 0x74, - 0x3b, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 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, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, - 0x14, 0x85, 0xc2, 0x31, 0x35, 0x4f, 0x93, 0x92, 0x9d, 0x8a, 0xbc, 0x32, - 0x7d, 0x1b, 0xf0, 0xaa, 0x96, 0xb1, 0x03, 0x86, 0x71, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, - 0x03, 0x82, 0x01, 0x01, 0x00, 0x00, 0x9e, 0x75, 0x2b, 0x95, 0x6a, 0x96, - 0x12, 0x24, 0xd5, 0x04, 0x6c, 0x34, 0x0a, 0x58, 0x5a, 0x7d, 0x59, 0xb9, - 0x03, 0x23, 0x13, 0xc3, 0xf5, 0x24, 0x57, 0x33, 0x8d, 0xca, 0x5f, 0xd8, - 0x26, 0xff, 0x64, 0x46, 0x13, 0x40, 0xe5, 0x04, 0xb2, 0xba, 0x92, 0xa5, - 0xa6, 0xa3, 0xd9, 0x2b, 0xff, 0x05, 0xef, 0xce, 0x3c, 0x28, 0xe8, 0x1b, - 0xa3, 0x10, 0x8a, 0xdd, 0x3d, 0x3a, 0x0a, 0xe1, 0x07, 0x3c, 0xb4, 0xf6, - 0xbb, 0xeb, 0xb5, 0xf2, 0x05, 0xe8, 0xd7, 0x16, 0x3e, 0xe5, 0x15, 0x49, - 0xdf, 0x8d, 0x34, 0xb8, 0x1b, 0xd4, 0xf2, 0x65, 0xa0, 0x70, 0x80, 0xd0, - 0xbf, 0xa5, 0x74, 0x5d, 0xfb, 0xd4, 0x52, 0x3b, 0x54, 0xca, 0x32, 0xba, - 0xf7, 0xe3, 0x90, 0xa5, 0xa8, 0xad, 0xd0, 0xe5, 0x5d, 0x18, 0x18, 0x87, - 0x60, 0xb0, 0xf3, 0xf9, 0x62, 0x20, 0x77, 0xaa, 0x0f, 0xdd, 0x16, 0x4c, - 0x01, 0x3a, 0xb1, 0x1f, 0x85, 0x7e, 0x01, 0x04, 0x5f, 0xf1, 0x37, 0x36, - 0xe3, 0x3a, 0xc1, 0xa3, 0x7c, 0x33, 0xca, 0xce, 0x0b, 0xb9, 0x34, 0xe2, - 0xe1, 0xe6, 0xed, 0x24, 0xc1, 0xc3, 0xc7, 0x74, 0x8f, 0x22, 0x2c, 0x6e, - 0xcb, 0x5c, 0x7a, 0x61, 0x99, 0xde, 0xea, 0x13, 0xe1, 0xa8, 0xa1, 0x94, - 0xd0, 0x85, 0x65, 0x65, 0xed, 0x97, 0x14, 0x6e, 0x97, 0xc9, 0xcf, 0x34, - 0x7c, 0xf2, 0x68, 0xeb, 0xc2, 0x7d, 0x03, 0x53, 0xf5, 0xdb, 0xa1, 0x11, - 0x8d, 0xda, 0xcc, 0x26, 0x13, 0xaa, 0x43, 0x76, 0x04, 0x9b, 0x85, 0x89, - 0xc3, 0x29, 0xd8, 0xb5, 0x54, 0x81, 0x09, 0xf5, 0x18, 0x52, 0xa5, 0x38, - 0x4a, 0x00, 0xc6, 0x1d, 0x4d, 0x5a, 0x15, 0xa0, 0xfd, 0xf7, 0x58, 0x27, - 0xcd, 0x6b, 0x56, 0x6b, 0xee, 0x7d, 0x73, 0xd3, 0xfd, 0x6c, 0xb6, 0xb1, - 0x3b, 0xbd, 0xbf, 0x5b, 0x4a, 0x6c, 0xd3, 0x1c, 0x47 -}; - - -/* Test basic add delete update copy matching stuff. */ -static void tests(void) -{ - SecTrustRef trust; - SecCertificateRef cert0, cert1; - isnt(cert0 = SecCertificateCreateWithBytes(NULL, _c0, sizeof(_c0)), - NULL, "create cert0"); - isnt(cert1 = SecCertificateCreateWithBytes(NULL, _c1, sizeof(_c1)), - NULL, "create cert1"); - const void *v_certs[] = { - cert0, - cert1 - }; - SecPolicyRef policy = SecPolicyCreateSSL(false, NULL); - CFArrayRef certs = CFArrayCreate(NULL, v_certs, - array_size(v_certs), NULL); - - /* SecTrustCreateWithCertificates using single cert. */ - ok_status(SecTrustCreateWithCertificates(cert0, policy, &trust), - "create trust with single cert0"); - is(SecTrustGetCertificateCount(trust), 1, "cert count is 1"); - is(SecTrustGetCertificateAtIndex(trust, 0), cert0, "cert 0 is leaf"); - CFReleaseNull(trust); - - /* SecTrustCreateWithCertificates failures. */ - is_status(SecTrustCreateWithCertificates(kCFBooleanTrue, policy, &trust), - errSecParam, "create trust with boolean instead of cert"); - is_status(SecTrustCreateWithCertificates(cert0, kCFBooleanTrue, &trust), - errSecParam, "create trust with boolean instead of policy"); - - /* SecTrustCreateWithCertificates using array of certs. */ - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust"); - /* NOTE: prior to -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "Security_regressions.h" - -#ifdef NO_SERVER -static void ensureKeychainExists(void) { - CFDictionaryRef query = CFDictionaryCreate(0, &kSecClass, &kSecClassInternetPassword, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFTypeRef results = NULL; - is_status(SecItemCopyMatching(query, &results), errSecItemNotFound, "expected nothing got %@", results); - CFReleaseNull(query); - CFReleaseNull(results); -} -#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) -{ -#ifndef NO_SERVER - plan_skip_all("No testing against server."); -#else - const char *home_dir = getenv("HOME"); - char keychain_dir[1000]; - char keychain_name[1000]; - sprintf(keychain_dir, "%s/Library/Keychains", home_dir); - sprintf(keychain_name, "%s/keychain-2-debug.db", keychain_dir); - - ensureKeychainExists(); - int fd; - ok_unix(fd = open(keychain_name, O_RDWR | O_CREAT | O_TRUNC, 0644), - "create keychain file '%s'", keychain_name); - ok_unix(fchmod(fd, 0), " keychain file '%s'", keychain_name); - ok_unix(close(fd), "close keychain file '%s'", keychain_name); - - kc_dbhandle_reset(); - - int v_eighty = 80; - CFNumberRef eighty = CFNumberCreate(NULL, kCFNumberSInt32Type, &v_eighty); - 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("members.spamcop.net")); - CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("smith")); - CFDictionaryAddValue(query, kSecAttrPort, eighty); - CFDictionaryAddValue(query, kSecAttrProtocol, kSecAttrProtocolHTTP); - CFDictionaryAddValue(query, kSecAttrAuthenticationType, kSecAttrAuthenticationTypeDefault); - CFDictionaryAddValue(query, kSecValueData, pwdata); - ok_status(SecItemAdd(query, NULL), "add internet password"); - is_status(SecItemAdd(query, NULL), errSecDuplicateItem, - "add internet password again"); - - ok_status(SecItemCopyMatching(query, NULL), "Found the item we added"); - - ok_status(SecItemDelete(query),"Deleted the item we added"); - - CFReleaseSafe(eighty); - CFReleaseSafe(pwdata); - CFReleaseSafe(query); -#endif -} - -int si_31_keychain_unreadable(int argc, char *const *argv) -{ - plan_tests(8); - tests(); - - return 0; -} diff --git a/sec/Security/Regressions/secitem/si-33-keychain-backup.c b/sec/Security/Regressions/secitem/si-33-keychain-backup.c deleted file mode 100644 index dddb3d10..00000000 --- a/sec/Security/Regressions/secitem/si-33-keychain-backup.c +++ /dev/null @@ -1,481 +0,0 @@ -/* - * si-33-keychain-backup.c - * Security - * - * Created by Michael Brouwer on 1/30/10. - * Copyright 2010 Apple Inc. All rights reserved. - * - */ - -#include - -#if TARGET_OS_EMBEDDED && !TARGET_IPHONE_SIMULATOR -#define USE_KEYSTORE 1 -#else /* No AppleKeyStore.kext on this OS. */ -#define USE_KEYSTORE 0 -#endif - - -#include -#include -#include -#include -#include -#include - -#if USE_KEYSTORE -#include -#include -#endif - -#include -#include -#include -#include -#include - -#include "Security_regressions.h" - -struct test_persistent_s { - CFTypeRef persist[2]; - CFDictionaryRef query; - CFDictionaryRef query1; - CFDictionaryRef query2; - CFMutableDictionaryRef query3; - CFMutableDictionaryRef query4; -}; - -static void test_persistent(struct test_persistent_s *p) -{ - int v_eighty = 80; - 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, - kSecReturnPersistentRef, - kSecValueData - }; - const void *values[] = { - kSecClassInternetPassword, - CFSTR("zuigt.nl"), - CFSTR("frtnbf"), - eighty, - CFSTR("http"), - CFSTR("dflt"), - kCFBooleanTrue, - pwdata - }; - CFDictionaryRef item = CFDictionaryCreate(NULL, keys, values, - array_size(keys), &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - p->persist[0] = NULL; - ok_status(SecItemAdd(item, &p->persist[0]), "add internet password"); - CFTypeRef results = NULL; - CFTypeRef results2 = NULL; - SKIP: { - skip("no persistent ref", 3, ok(p->persist[0], "got back persistent ref")); - - /* Create a dict with all attrs except the data. */ - keys[(array_size(keys)) - 2] = kSecReturnAttributes; - p->query = CFDictionaryCreate(NULL, keys, values, - (array_size(keys)) - 1, &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - ok_status(SecItemCopyMatching(p->query, &results), "find internet password by attr"); - - const void *keys_persist[] = { - kSecReturnAttributes, - kSecValuePersistentRef - }; - const void *values_persist[] = { - kCFBooleanTrue, - p->persist[0] - }; - p->query2 = CFDictionaryCreate(NULL, keys_persist, values_persist, - (array_size(keys_persist)), &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - ok_status(SecItemCopyMatching(p->query2, &results2), "find internet password by persistent ref"); - ok(CFEqual(results, results2 ? results2 : CFSTR("")), "same item (attributes)"); - - CFReleaseNull(results); - CFReleaseNull(results2); - } - ok_status(SecItemDelete(p->query), "delete internet password"); - - ok_status(!SecItemCopyMatching(p->query, &results), - "don't find internet password by attributes"); - ok(!results, "no results"); - - /* clean up left over from aborted run */ - if (results) { - CFDictionaryRef cleanup = CFDictionaryCreate(NULL, &kSecValuePersistentRef, - &results, 1, &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - SecItemDelete(cleanup); - CFRelease(results); - CFRelease(cleanup); - } - - ok_status(!SecItemCopyMatching(p->query2, &results2), - "don't find internet password by persistent ref anymore"); - ok(!results2, "no results"); - - CFReleaseNull(p->persist[0]); - - /* Add a new item and get it's persitant ref. */ - ok_status(SecItemAdd(item, &p->persist[0]), "add internet password"); - p->persist[1] = NULL; - CFMutableDictionaryRef item2 = CFDictionaryCreateMutableCopy(NULL, 0, item); - CFDictionarySetValue(item2, kSecAttrAccount, CFSTR("johndoe-bu")); - ok_status(SecItemAdd(item2, &p->persist[1]), "add second internet password"); - is(CFGetTypeID(p->persist[0]), CFDataGetTypeID(), "result is a CFData"); - p->query3 = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - CFDictionaryAddValue(p->query3, kSecValuePersistentRef, p->persist[0]); - CFMutableDictionaryRef update = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); - CFDictionaryAddValue(update, kSecAttrServer, CFSTR("zuigt.com")); - ok_status(SecItemUpdate(p->query3, update), "update via persitant ref"); - - /* Verify that the update really worked. */ - CFDictionaryAddValue(p->query3, kSecReturnAttributes, kCFBooleanTrue); - ok_status(SecItemCopyMatching(p->query3, &results2), "find updated internet password by persistent ref"); - CFStringRef server = CFDictionaryGetValue(results2, kSecAttrServer); - ok(CFEqual(server, CFSTR("zuigt.com")), "verify attribute was modified by update"); - CFReleaseNull(results2); - CFDictionaryRemoveValue(p->query3, kSecReturnAttributes); - - /* Verify that item2 wasn't affected by the update. */ - p->query4 = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - CFDictionaryAddValue(p->query4, kSecValuePersistentRef, p->persist[1]); - CFDictionaryAddValue(p->query4, kSecReturnAttributes, kCFBooleanTrue); - ok_status(SecItemCopyMatching(p->query4, &results2), "find non updated internet password by persistent ref"); - server = CFDictionaryGetValue(results2, kSecAttrServer); - ok(CFEqual(server, CFSTR("zuigt.nl")), "verify second items attribute was not modified by update"); - CFReleaseNull(results2); - - /* Delete the item via persitant ref. */ - ok_status(SecItemDelete(p->query3), "delete via persitant ref"); - is_status(SecItemCopyMatching(p->query3, &results2), errSecItemNotFound, - "don't find deleted internet password by persistent ref"); - CFReleaseNull(results2); - ok_status(SecItemCopyMatching(p->query4, &results2), - "find non deleted internet password by persistent ref"); - CFReleaseNull(results2); - - CFRelease(update); - CFReleaseNull(item); - CFReleaseNull(item2); - CFReleaseNull(eighty); - CFReleaseNull(pwdata); -} - -static void test_persistent2(struct test_persistent_s *p) -{ - CFTypeRef results = NULL; - CFTypeRef results2 = NULL; - - ok_status(!SecItemCopyMatching(p->query, &results), - "don't find internet password by attributes"); - ok(!results, "no results"); - - ok_status(!SecItemCopyMatching(p->query2, &results2), - "don't find internet password by persistent ref anymore"); - ok(!results2, "no results"); - - SKIP:{ - ok_status(SecItemCopyMatching(p->query4, &results2), "find non updated internet password by persistent ref"); - skip("non updated internet password by persistent ref NOT FOUND!", 2, results2); - ok(results2, "non updated internet password not found"); - CFStringRef server = CFDictionaryGetValue(results2, kSecAttrServer); - ok(CFEqual(server, CFSTR("zuigt.nl")), "verify second items attribute was not modified by update"); - CFReleaseNull(results2); - } - - is_status(SecItemCopyMatching(p->query3, &results2), errSecItemNotFound, - "don't find deleted internet password by persistent ref"); - CFReleaseNull(results2); - ok_status(SecItemCopyMatching(p->query4, &results2), - "find non deleted internet password by persistent ref"); - CFReleaseNull(results2); - - ok_status(SecItemDelete(p->query4),"Deleted internet password by persistent ref"); - - CFRelease(p->query); - CFRelease(p->query2); - CFRelease(p->query3); - CFRelease(p->query4); - CFReleaseNull(p->persist[0]); - CFReleaseNull(p->persist[1]); -} - -static CFMutableDictionaryRef test_create_lockdown_identity_query(void) { - CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); - CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword); - CFDictionaryAddValue(query, kSecAttrAccessGroup, CFSTR("lockdown-identities")); - return query; -} - -static CFMutableDictionaryRef test_create_managedconfiguration_query(void) { - CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); - CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword); - CFDictionaryAddValue(query, kSecAttrService, CFSTR("com.apple.managedconfiguration")); - CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("Public")); - CFDictionaryAddValue(query, kSecAttrAccessGroup, CFSTR("apple")); - return query; -} - -static void test_add_lockdown_identity_items(void) { - CFMutableDictionaryRef query = test_create_lockdown_identity_query(); - const char *v_data = "lockdown identity data (which should be a cert + key)"; - CFDataRef pwdata = CFDataCreate(NULL, (UInt8 *)v_data, strlen(v_data)); - CFDictionaryAddValue(query, kSecValueData, pwdata); - ok_status(SecItemAdd(query, NULL), "test_add_lockdown_identity_items"); - CFReleaseSafe(pwdata); - CFReleaseSafe(query); -} - -static void test_remove_lockdown_identity_items(void) { - CFMutableDictionaryRef query = test_create_lockdown_identity_query(); - ok_status(SecItemDelete(query), "test_remove_lockdown_identity_items"); - CFReleaseSafe(query); -} - -static void test_no_find_lockdown_identity_item(void) { - CFMutableDictionaryRef query = test_create_lockdown_identity_query(); - is_status(SecItemCopyMatching(query, NULL), errSecItemNotFound, - "test_no_find_lockdown_identity_item"); - CFReleaseSafe(query); -} - -static void test_add_managedconfiguration_item(void) { - CFMutableDictionaryRef query = test_create_managedconfiguration_query(); - const char *v_data = "public managedconfiguration password history data"; - CFDataRef pwdata = CFDataCreate(NULL, (UInt8 *)v_data, strlen(v_data)); - CFDictionaryAddValue(query, kSecValueData, pwdata); - ok_status(SecItemAdd(query, NULL), "test_add_managedconfiguration_item"); - CFReleaseSafe(pwdata); - CFReleaseSafe(query); -} - -static void test_find_managedconfiguration_item(void) { - CFMutableDictionaryRef query = test_create_managedconfiguration_query(); - ok_status(SecItemCopyMatching(query, NULL), "test_find_managedconfiguration_item"); - ok_status(SecItemDelete(query), "test_find_managedconfiguration_item (deleted)"); - CFReleaseSafe(query); -} - -#if USE_KEYSTORE -static io_connect_t connect_to_keystore(void) -{ - io_registry_entry_t apple_key_bag_service; - kern_return_t result; - io_connect_t keystore = MACH_PORT_NULL; - - apple_key_bag_service = IOServiceGetMatchingService(kIOMasterPortDefault, - IOServiceMatching(kAppleKeyStoreServiceName)); - - if (apple_key_bag_service == IO_OBJECT_NULL) { - fprintf(stderr, "Failed to get service.\n"); - return keystore; - } - - result = IOServiceOpen(apple_key_bag_service, mach_task_self(), 0, &keystore); - if (KERN_SUCCESS != result) - fprintf(stderr, "Failed to open keystore\n"); - - if (keystore != MACH_PORT_NULL) { - IOReturn kernResult = IOConnectCallMethod(keystore, - kAppleKeyStoreUserClientOpen, NULL, 0, NULL, 0, NULL, NULL, - NULL, NULL); - if (kernResult) { - fprintf(stderr, "Failed to open AppleKeyStore: %x\n", kernResult); - } - } - return keystore; -} - -static CFDataRef create_keybag(keybag_handle_t bag_type, CFDataRef password) -{ - uint64_t inputs[] = { bag_type }; - uint64_t outputs[] = {0}; - uint32_t num_inputs = array_size(inputs); - uint32_t num_outputs = array_size(outputs); - IOReturn kernResult; - - io_connect_t keystore; - - unsigned char keybagdata[4096]; //Is that big enough? - size_t keybagsize=sizeof(keybagdata); - - keystore=connect_to_keystore(); - - kernResult = IOConnectCallMethod(keystore, - kAppleKeyStoreKeyBagCreate, - inputs, num_inputs, NULL, 0, - outputs, &num_outputs, NULL, 0); - - if (kernResult) { - fprintf(stderr, "kAppleKeyStoreKeyBagCreate: 0x%x\n", kernResult); - return NULL; - } - - /* Copy out keybag */ - inputs[0]=outputs[0]; - num_inputs=1; - - kernResult = IOConnectCallMethod(keystore, - kAppleKeyStoreKeyBagCopy, - inputs, num_inputs, NULL, 0, - NULL, 0, keybagdata, &keybagsize); - - if (kernResult) { - fprintf(stderr, "kAppleKeyStoreKeyBagCopy: 0x%x\n", kernResult); - return NULL; - } - - return CFDataCreate(kCFAllocatorDefault, keybagdata, keybagsize); -} -#endif - -/* Test low level keychain migration from device to device interface. */ -static void tests(void) -{ - int v_eighty = 80; - CFNumberRef eighty = CFNumberCreate(NULL, kCFNumberSInt32Type, &v_eighty); - 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("members.spamcop.net")); - CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("smith")); - CFDictionaryAddValue(query, kSecAttrPort, eighty); - CFDictionaryAddValue(query, kSecAttrProtocol, kSecAttrProtocolHTTP); - CFDictionaryAddValue(query, kSecAttrAuthenticationType, kSecAttrAuthenticationTypeDefault); - CFDictionaryAddValue(query, kSecValueData, pwdata); - ok_status(SecItemAdd(query, NULL), "add internet password"); - is_status(SecItemAdd(query, NULL), errSecDuplicateItem, - "add internet password again"); - - ok_status(SecItemCopyMatching(query, NULL), "Found the item we added"); - - struct test_persistent_s p = {}; - test_persistent(&p); - - CFDataRef backup = NULL, keybag = NULL, password = NULL; - - test_add_lockdown_identity_items(); - -#if USE_KEYSTORE - keybag = create_keybag(kAppleKeyStoreBackupBag, password); -#else - keybag = CFDataCreate(kCFAllocatorDefault, NULL, 0); -#endif - - ok(backup = _SecKeychainCopyBackup(keybag, password), - "_SecKeychainCopyBackup"); - - test_add_managedconfiguration_item(); - test_remove_lockdown_identity_items(); - - ok_status(_SecKeychainRestoreBackup(backup, keybag, password), - "_SecKeychainRestoreBackup"); - CFReleaseSafe(backup); - - test_no_find_lockdown_identity_item(); - test_find_managedconfiguration_item(); - - ok_status(SecItemCopyMatching(query, NULL), - "Found the item we added after restore"); - - test_persistent2(&p); - -#if USE_KEYSTORE - CFReleaseNull(keybag); - keybag = create_keybag(kAppleKeyStoreOTABackupBag, password); -#endif - - ok(backup = _SecKeychainCopyBackup(keybag, password), - "_SecKeychainCopyBackup"); - ok_status(_SecKeychainRestoreBackup(backup, keybag, password), - "_SecKeychainRestoreBackup"); - ok_status(SecItemCopyMatching(query, NULL), - "Found the item we added after restore"); - CFReleaseNull(backup); - - CFDictionaryAddValue(query, kSecUseTombstones, kCFBooleanTrue); - - ok_status(SecItemDelete(query), "Deleted item we added"); - -#if USE_KEYSTORE - CFReleaseNull(keybag); - keybag = create_keybag(kAppleKeyStoreOTABackupBag /* use truthiness bag once it's there */, password); -#endif - - // add syncable item - CFDictionaryAddValue(query, kSecAttrSynchronizable, kCFBooleanTrue); - ok_status(SecItemAdd(query, NULL), "add internet password"); - - // and non-syncable item - test_add_managedconfiguration_item(); - - CFDictionaryRef syncableBackup = NULL; - - ok_status(_SecKeychainBackupSyncable(keybag, password, NULL, &syncableBackup), "export items"); - - // TODO: add item, call SecServerCopyTruthInTheCloud again - - // CFShow(syncableBackup); - - // find and delete - ok_status(SecItemCopyMatching(query, NULL), "find item we are about to destroy"); - - ok_status(SecItemDelete(query), "delete item we backed up"); - - // ensure we added a tombstone - CFDictionaryAddValue(query, kSecAttrTombstone, kCFBooleanTrue); - ok_status(SecItemCopyMatching(query, NULL), "find tombstone for item we deleted"); - CFDictionaryRemoveValue(query, kSecAttrTombstone); - - test_find_managedconfiguration_item(); - - // TODO: add a different new item - delete what's not in the syncableBackup? - - // Do another backup after some changes - CFDictionaryRef scratch = NULL; - ok_status(_SecKeychainBackupSyncable(keybag, password, syncableBackup, &scratch), "export items after changes"); - CFReleaseNull(scratch); - - ok_status(_SecKeychainRestoreSyncable(keybag, password, syncableBackup), "import items"); - - // non-syncable item should (still) be gone -> add should work - test_add_managedconfiguration_item(); - test_find_managedconfiguration_item(); - - // syncable item should have not been restored, because the tombstone was newer than the item in the backup -> copy matching should fail - is_status(errSecItemNotFound, SecItemCopyMatching(query, NULL), - "find restored item"); - is_status(errSecItemNotFound, SecItemDelete(query), "delete restored item"); - - CFReleaseSafe(syncableBackup); - CFReleaseSafe(keybag); - CFReleaseSafe(eighty); - CFReleaseSafe(pwdata); - CFReleaseSafe(query); -} - -int si_33_keychain_backup(int argc, char *const *argv) -{ - plan_tests(62); - - - tests(); - - return 0; -} diff --git a/sec/Security/Regressions/secitem/si-40-seckey-custom.c b/sec/Security/Regressions/secitem/si-40-seckey-custom.c deleted file mode 100644 index 9a228518..00000000 --- a/sec/Security/Regressions/secitem/si-40-seckey-custom.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * si-40-seckey.c - * Security - * - * Created by Michael Brouwer on 1/29/07. - * Copyright (c) 2007-2008,2010 Apple Inc. All Rights Reserved. - * - */ - -#include -#include - -#include "Security_regressions.h" - -#define CFReleaseNull(CF) { CFTypeRef _cf = (CF); if (_cf) { (CF) = NULL; CFRelease(_cf); } } - -static SecKeyRef customKey; -static SecKeyRef initedCustomKey; - -static OSStatus CustomKeyInit(SecKeyRef key, const uint8_t *key_data, - CFIndex key_len, SecKeyEncoding encoding) -{ - ok(key, "CustomKeyInit"); - is(key->key, NULL, "key->key is NULL"); - initedCustomKey = key; - return errSecSuccess; -} - -static void CustomKeyDestroy(SecKeyRef key) -{ - is(customKey, key, "CustomKeyDestroy"); -} - -static OSStatus CustomKeyRawSign(SecKeyRef key, SecPadding padding, - const uint8_t *dataToSign, size_t dataToSignLen, - uint8_t *sig, size_t *sigLen) -{ - is(customKey, key, "CustomKeyRawSign"); - return errSecSuccess; -} - -static OSStatus CustomKeyRawVerify( - SecKeyRef key, SecPadding padding, const uint8_t *signedData, - size_t signedDataLen, const uint8_t *sig, size_t sigLen) -{ - is(customKey, key, "CustomKeyRawVerify"); - return errSecSuccess; -} - -static OSStatus CustomKeyEncrypt(SecKeyRef key, SecPadding padding, - const uint8_t *plainText, size_t plainTextLen, - uint8_t *cipherText, size_t *cipherTextLen) -{ - is(customKey, key, "CustomKeyEncrypt"); - return errSecSuccess; -} - -static OSStatus CustomKeyDecrypt(SecKeyRef key, SecPadding padding, - const uint8_t *cipherText, size_t cipherTextLen, - uint8_t *plainText, size_t *plainTextLen) -{ - is(customKey, key, "CustomKeyDecrypt"); - return errSecSuccess; -} - -static OSStatus CustomKeyCompute(SecKeyRef key, - const uint8_t *pub_key, size_t pub_key_len, - uint8_t *computed_key, size_t *computed_key_len) -{ - is(customKey, key, "CustomKeyCompute"); - return errSecSuccess; -} - -static size_t CustomKeyBlockSize(SecKeyRef key) -{ - is(customKey, key, "CustomKeyBlockSize"); - return 42; -} - -static CFDictionaryRef CustomKeyCopyAttributeDictionary(SecKeyRef key) -{ - is(customKey, key, "CustomKeyCopyAttributeDictionary"); - CFDictionaryRef dict = CFDictionaryCreate(kCFAllocatorDefault, NULL, NULL, - 0, NULL, NULL); - return dict; -} - -SecKeyDescriptor kCustomKeyDescriptor = { - kSecKeyDescriptorVersion, - "CustomKey", - 0, /* extraBytes */ - CustomKeyInit, - CustomKeyDestroy, - CustomKeyRawSign, - CustomKeyRawVerify, - CustomKeyEncrypt, - CustomKeyDecrypt, - CustomKeyCompute, - CustomKeyBlockSize, - CustomKeyCopyAttributeDictionary, -}; - -/* Test basic add delete update copy matching stuff. */ -static void tests(void) -{ - const uint8_t *keyData = (const uint8_t *)"abc"; - CFIndex keyDataLength = 3; - SecKeyEncoding encoding = kSecKeyEncodingRaw; - ok(customKey = SecKeyCreate(kCFAllocatorDefault, - &kCustomKeyDescriptor, keyData, keyDataLength, encoding), - "create custom key"); - is(customKey, initedCustomKey, "CustomKeyInit got the right key"); - - SecPadding padding = kSecPaddingPKCS1; - const uint8_t *src = NULL; - size_t srcLen = 3; - uint8_t *dst = NULL; - size_t dstLen = 3; - - ok_status(SecKeyDecrypt(customKey, padding, src, srcLen, dst, &dstLen), - "SecKeyDecrypt"); - ok_status(SecKeyEncrypt(customKey, padding, src, srcLen, dst, &dstLen), - "SecKeyEncrypt"); - ok_status(SecKeyRawSign(customKey, padding, src, srcLen, dst, &dstLen), - "SecKeyRawSign"); - ok_status(SecKeyRawVerify(customKey, padding, src, srcLen, dst, dstLen), - "SecKeyRawVerify"); - is(SecKeyGetSize(customKey, kSecKeyKeySizeInBits), (size_t)42*8, "SecKeyGetSize"); - - CFDictionaryRef attrDict = NULL; - ok(attrDict = SecKeyCopyAttributeDictionary(customKey), - "SecKeyCopyAttributeDictionary"); - CFReleaseNull(attrDict); - - //ok(SecKeyGeneratePair(customKey, ), "SecKeyGeneratePair"); - ok(SecKeyGetTypeID() != 0, "SecKeyGetTypeID works"); - - if (customKey) { - CFRelease(customKey); - customKey = NULL; - } -} - -int si_40_seckey_custom(int argc, char *const *argv) -{ - plan_tests(18); - - - tests(); - - return 0; -} diff --git a/sec/Security/Regressions/secitem/si-41-sececkey.c b/sec/Security/Regressions/secitem/si-41-sececkey.c deleted file mode 100644 index cf407cbb..00000000 --- a/sec/Security/Regressions/secitem/si-41-sececkey.c +++ /dev/null @@ -1,283 +0,0 @@ -// -// si-41-sececkey.c -// regressions -// -// Created by Mitch Adler on 5/20/11. -// Copyright 2011 Apple Inc. All rights reserved. -// - -/* - * si-40-seckey.c - * Security - * - * Created by Michael Brouwer on 1/29/07. - * Copyright (c) 2007-2009 Apple Inc. All Rights Reserved. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Security_regressions.h" - -#define CFReleaseNull(CF) { CFTypeRef _cf = (CF); if (_cf) { (CF) = NULL; CFRelease(_cf); } } - - -static void testdigestandsignalg(SecKeyRef privKey, SecKeyRef pubKey, const SecAsn1AlgId *algId) { - uint8_t dataToDigest[256] = {0,}; - size_t dataToDigestLen = sizeof(dataToDigest); - size_t sigLen = SecKeyGetSize(privKey, kSecKeySignatureSize); - uint8_t sig[sigLen]; - - DERItem oid; - oid.length = algId->algorithm.Length; - oid.data = algId->algorithm.Data; - - /* Get the oid in decimal for display purposes. */ - CFStringRef oidStr = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, &oid); - char oidBuf[40]; - CFStringGetCString(oidStr, oidBuf, sizeof(oidBuf), kCFStringEncodingUTF8); - CFRelease(oidStr); - -SKIP: { - OSStatus status; - - /* Time to sign. */ - ok_status(status = SecKeyDigestAndSign(privKey, algId, dataToDigest, dataToDigestLen, - sig, &sigLen), - "digest and sign %s with %ld bit RSA key", oidBuf, sigLen * 8); - - skip("SecKeyDigestAndSign failed", 3, status == errSecSuccess); - - /* Verify the signature we just made. */ - ok_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen, - sig, sigLen), "digest and verify"); - /* Invalidate the signature. */ - sig[0] ^= 0xff; - is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen, - sig, sigLen), errSSLCrypto, "digest and verify bad sig"); - sig[0] ^= 0xff; - dataToDigest[0] ^= 0xff; - is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen, - sig, sigLen), errSSLCrypto, "digest and verify bad digest"); -} -} - -static void testdigestandsign(SecKeyRef privKey, SecKeyRef pubKey) { - static const SecAsn1Oid *oids[] = { - &CSSMOID_ECDSA_WithSHA1, -#if 0 - &CSSMOID_ECDSA_WithSHA224, - &CSSMOID_ECDSA_WithSHA256, - &CSSMOID_ECDSA_WithSHA384, - &CSSMOID_ECDSA_WithSHA512, -#endif - }; - - uint32_t ix; - SecAsn1AlgId algId = {}; - for (ix = 0; ix < array_size(oids); ++ix) { - if (oids[ix]) { - algId.algorithm = *oids[ix]; - } else { - algId.algorithm.Length = 0; - algId.algorithm.Data = NULL; - } - - testdigestandsignalg(privKey, pubKey, &algId); - } -} - -static void testkeygen(size_t keySizeInBits) { - SecKeyRef pubKey = NULL, privKey = NULL; - size_t keySizeInBytes = (keySizeInBits + 7) / 8; - CFNumberRef kzib; - int32_t keysz32 = (int32_t)keySizeInBits; - - kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); - CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); - CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeEC); - CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib); - - OSStatus status; - ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), - "Generate %ld bit (%ld byte) EC keypair", keySizeInBits, - keySizeInBytes); - CFRelease(kzib); - CFRelease(kgp); - -SKIP: { - skip("keygen failed", 8, status == errSecSuccess); - ok(pubKey, "pubkey returned"); - ok(privKey, "privKey returned"); - is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok"); - is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok"); - - /* Sign something. */ - uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, }; - uint8_t sig[8+2*keySizeInBytes]; - size_t sigLen = sizeof(sig); - ok_status(SecKeyRawSign(privKey, kSecPaddingNone, - something, sizeof(something), sig, &sigLen), "sign something"); - ok_status(SecKeyRawVerify(pubKey, kSecPaddingNone, - something, sizeof(something), sig, sigLen), "verify sig on something"); - - testdigestandsign(privKey, pubKey); - - const void *privkeys[] = { - kSecValueRef - }; - const void *privvalues[] = { - privKey - }; - CFDictionaryRef privitem = CFDictionaryCreate(NULL, privkeys, privvalues, - array_size(privkeys), NULL, NULL); - ok_status(SecItemAdd(privitem, NULL), "add private key"); - ok_status(SecItemDelete(privitem), "delete public key"); - CFReleaseNull(privitem); - - const void *pubkeys[] = { - kSecValueRef - }; - const void *pubvalues[] = { - pubKey - }; - CFDictionaryRef pubitem = CFDictionaryCreate(NULL, pubkeys, pubvalues, - array_size(pubkeys), NULL, NULL); - ok_status(SecItemAdd(pubitem, NULL), "add public key"); - ok_status(SecItemDelete(pubitem), "delete public key"); - CFReleaseNull(pubitem); - - /* Cleanup. */ - CFReleaseNull(pubKey); - CFReleaseNull(privKey); -} -} - - -static void testkeygen2(size_t keySizeInBits) { - SecKeyRef pubKey = NULL, privKey = NULL; - size_t keySizeInBytes = (keySizeInBits + 7) / 8; - CFNumberRef kzib; - int32_t keysz32 = (int32_t)keySizeInBits; - - CFUUIDRef ourUUID = CFUUIDCreate(kCFAllocatorDefault); - CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, ourUUID); - CFMutableStringRef publicName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString); - CFMutableStringRef privateName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString); - - CFReleaseNull(ourUUID); - CFReleaseNull(uuidString); - - CFStringAppend(publicName, CFSTR("-Public-41")); - CFStringAppend(privateName, CFSTR("-Private-41")); - - CFMutableDictionaryRef pubd = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); - CFMutableDictionaryRef privd = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); - CFDictionaryAddValue(pubd, kSecAttrLabel, publicName); - CFDictionaryAddValue(privd, kSecAttrLabel, privateName); - - kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); - CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); - CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeEC); - CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib); - CFDictionaryAddValue(kgp, kSecAttrIsPermanent, kCFBooleanTrue); - CFDictionaryAddValue(kgp, kSecPublicKeyAttrs, pubd); - CFDictionaryAddValue(kgp, kSecPrivateKeyAttrs, privd); - - OSStatus status; - ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), - "Generate %ld bit (%ld byte) persistent RSA keypair", - keySizeInBits, keySizeInBytes); - CFRelease(kzib); - CFRelease(kgp); - -SKIP: { - skip("keygen failed", 8, status == errSecSuccess); - ok(pubKey, "pubkey returned"); - ok(privKey, "privKey returned"); - is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok"); - is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok"); - - SecKeyRef pubKey2, privKey2; - CFDictionaryAddValue(pubd, kSecClass, kSecClassKey); - CFDictionaryAddValue(pubd, kSecReturnRef, kCFBooleanTrue); - CFDictionaryAddValue(privd, kSecClass, kSecClassKey); - CFDictionaryAddValue(privd, kSecReturnRef, kCFBooleanTrue); - CFDictionaryAddValue(privd, kSecAttrCanSign, kCFBooleanTrue); - ok_status(SecItemCopyMatching(pubd, (CFTypeRef *)&pubKey2), - "retrieve pub key by label"); - ok(pubKey2, "got valid object"); - ok_status(SecItemCopyMatching(privd, (CFTypeRef *)&privKey2), - "retrieve priv key by label and kSecAttrCanSign"); - ok(privKey2, "got valid object"); - - /* Sign something. */ - uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, }; - size_t sigLen = SecKeyGetSize(privKey2, kSecKeySignatureSize); - uint8_t sig[sigLen]; - ok_status(SecKeyRawSign(privKey2, kSecPaddingPKCS1, - something, sizeof(something), sig, &sigLen), "sign something"); - ok_status(SecKeyRawVerify(pubKey2, kSecPaddingPKCS1, - something, sizeof(something), sig, sigLen), "verify sig on something"); - - /* Cleanup. */ - CFReleaseNull(pubKey2); - CFReleaseNull(privKey2); -} - - /* delete from keychain - note: do it before releasing publicName and privateName - because pubd and privd have no retain/release callbacks */ - ok_status(SecItemDelete(pubd), "delete generated pub key"); - ok_status(SecItemDelete(privd), "delete generated priv key"); - - /* Cleanup. */ - CFReleaseNull(pubKey); - CFReleaseNull(privKey); - - CFReleaseNull(publicName); - CFReleaseNull(privateName); - - CFRelease(pubd); - CFRelease(privd); -} - - -/* Test basic add delete update copy matching stuff. */ -static void tests(void) -{ - testkeygen(192); - testkeygen(224); - testkeygen(256); - testkeygen(384); - testkeygen(521); - - testkeygen2(192); - testkeygen2(224); - testkeygen2(256); - testkeygen2(384); - testkeygen2(521); - -} - -int si_41_sececkey(int argc, char *const *argv) -{ - plan_tests(140); - - tests(); - - return 0; -} diff --git a/sec/Security/Regressions/secitem/si-50-secrandom.c b/sec/Security/Regressions/secitem/si-50-secrandom.c deleted file mode 100644 index 5b5616ac..00000000 --- a/sec/Security/Regressions/secitem/si-50-secrandom.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * si-50-secrandom.c - * Security - * - * Created by Michael Brouwer on 5/8/07 - * Copyright (c) 2007-2008,2010 Apple Inc. All Rights Reserved. - * - */ - -#include -#include -#include -#include - -#include "Security_regressions.h" - -/* Test basic add delete update copy matching stuff. */ -static void tests(void) -{ - UInt8 bytes[4096] = {}; - CFIndex size = 42; - UInt8 *p = bytes + 23; - ok_status(SecRandomCopyBytes(kSecRandomDefault, size, p), "generate some random bytes"); -} - -int si_50_secrandom(int argc, char *const *argv) -{ - plan_tests(1); - - - tests(); - - return 0; -} diff --git a/sec/Security/Regressions/secitem/si-67-sectrust-blacklist.c b/sec/Security/Regressions/secitem/si-67-sectrust-blacklist.c deleted file mode 100644 index 2fff2701..00000000 --- a/sec/Security/Regressions/secitem/si-67-sectrust-blacklist.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * si-67-sectrust-blacklist.c - * regressions - * - * Created by Conrad Sauerwald on 3/24/11. - * Copyright 2011 Apple Inc. All rights reserved. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "si-67-sectrust-blacklist/Global Trustee.cer.h" -#include "si-67-sectrust-blacklist/login.yahoo.com.1.cer.h" -#include "si-67-sectrust-blacklist/UTN-USERFirst-Hardware.cer.h" -#include "si-67-sectrust-blacklist/login.yahoo.com.2.cer.h" -#include "si-67-sectrust-blacklist/addons.mozilla.org.cer.h" -#include "si-67-sectrust-blacklist/login.yahoo.com.cer.h" -#include "si-67-sectrust-blacklist/login.live.com.cer.h" -#include "si-67-sectrust-blacklist/mail.google.com.cer.h" -#include "si-67-sectrust-blacklist/login.skype.com.cer.h" -#include "si-67-sectrust-blacklist/www.google.com.cer.h" - -#include "Security_regressions.h" - -static void validate_one_cert(uint8_t *data, size_t len, int chain_length, SecTrustResultType trust_result) -{ - SecTrustRef trust; - SecCertificateRef cert; - SecPolicyRef policy = SecPolicyCreateSSL(false, NULL); - CFArrayRef certs; - - isnt(cert = SecCertificateCreateWithBytes(NULL, data, len), - NULL, "create cert"); - certs = CFArrayCreate(NULL, (const void **)&cert, 1, NULL); - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), - "create trust with single cert"); - //CFDateRef date = CFDateCreate(NULL, 1301008576); - //ok_status(SecTrustSetVerifyDate(trust, date), "set date"); - //CFRelease(date); - - SecTrustResultType trustResult; - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); - is(SecTrustGetCertificateCount(trust), chain_length, "cert count"); - is_status(trustResult, trust_result, "correct trustResult"); - CFRelease(trust); - CFRelease(policy); - CFRelease(certs); - CFRelease(cert); -} - -static void tests(void) -{ - validate_one_cert(Global_Trustee_cer, sizeof(Global_Trustee_cer), 3, kSecTrustResultFatalTrustFailure); - validate_one_cert(login_yahoo_com_1_cer, sizeof(login_yahoo_com_1_cer), 3, kSecTrustResultFatalTrustFailure); - /* this is the root, which isn't ok for ssl and fails here, but at the - same time it proves that kSecTrustResultFatalTrustFailure isn't - returned for policy failures that aren't blacklisting */ - validate_one_cert(login_yahoo_com_2_cer, sizeof(login_yahoo_com_2_cer), 3, kSecTrustResultFatalTrustFailure); - validate_one_cert(addons_mozilla_org_cer, sizeof(addons_mozilla_org_cer), 3, kSecTrustResultFatalTrustFailure); - validate_one_cert(login_yahoo_com_cer, sizeof(login_yahoo_com_cer), 3, kSecTrustResultFatalTrustFailure); - validate_one_cert(login_live_com_cer, sizeof(login_live_com_cer), 3, kSecTrustResultFatalTrustFailure); - validate_one_cert(mail_google_com_cer, sizeof(mail_google_com_cer), 3, kSecTrustResultFatalTrustFailure); - validate_one_cert(login_skype_com_cer, sizeof(login_skype_com_cer), 3, kSecTrustResultFatalTrustFailure); - validate_one_cert(www_google_com_cer, sizeof(www_google_com_cer), 3, kSecTrustResultFatalTrustFailure); -} - -int si_67_sectrust_blacklist(int argc, char *const *argv) -{ - plan_tests(45); - - tests(); - - return 0; -} diff --git a/sec/Security/Regressions/secitem/si-70-sectrust-unified.c b/sec/Security/Regressions/secitem/si-70-sectrust-unified.c deleted file mode 100644 index f191988c..00000000 --- a/sec/Security/Regressions/secitem/si-70-sectrust-unified.c +++ /dev/null @@ -1,250 +0,0 @@ - -// -// si-70-sectrust-unified.c -// regressions -// -// Created by Ken McLeod on 2/4/13. -// -// -#include -#include -#include -#include -#include - -#include "Security_regressions.h" -#include - -/* This is a minimal test case to ensure that the functionality of - * TLF: SecTrust Unification is present - * and working. Needs to be expanded and split up into separate - * test case files in the future. - */ - -/* SecPolicy: new in 7.0 */ -//CFDictionaryRef SecPolicyCopyProperties(SecPolicyRef policyRef) -//OSStatus SecTrustSetPolicies(SecTrustRef trust, CFTypeRef policies) /* (this was SPI in 6.0) */ -//SecPolicyRef SecPolicyCreateRevocation(CFIndex revocationFlags) -//SecPolicyRef SecPolicyCreateWithProperties(CFTypeRef policyIdentifier, CFDictionaryRef properties) - -/* SecTrust new in 7.0 */ -//OSStatus SecTrustCopyPolicies(SecTrustRef trust, CFArrayRef *policies) -//OSStatus SecTrustSetNetworkFetchAllowed(SecTrustRef trust, Boolean allowFetch) -//OSStatus SecTrustGetNetworkFetchAllowed(SecTrustRef trust, Boolean *allowFetch) -//OSStatus SecTrustCopyCustomAnchorCertificates(SecTrustRef trust, CFArrayRef *anchors) -//CFDictionaryRef SecTrustCopyResult(SecTrustRef trust) -//OSStatus SecTrustSetOCSPResponse(SecTrustRef trust, CFTypeRef responseData) - - -/* subject:/C=US/ST=California/L=Cupertino/O=Apple Inc/OU=Internet Operations/CN=xedge2.apple.com - issuer :/C=US/O=Entrust.net/OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Secure Server Certification Authority */ -const uint8_t xedge2_cert[1385]={ -0x30,0x82,0x05,0x65,0x30,0x82,0x04,0xCE,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x46, -0x9C,0xDF,0x96,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05, -0x05,0x00,0x30,0x81,0xC3,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, -0x55,0x53,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x13,0x0B,0x45,0x6E,0x74, -0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x31,0x3B,0x30,0x39,0x06,0x03,0x55,0x04, -0x0B,0x13,0x32,0x77,0x77,0x77,0x2E,0x65,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E, -0x65,0x74,0x2F,0x43,0x50,0x53,0x20,0x69,0x6E,0x63,0x6F,0x72,0x70,0x2E,0x20,0x62, -0x79,0x20,0x72,0x65,0x66,0x2E,0x20,0x28,0x6C,0x69,0x6D,0x69,0x74,0x73,0x20,0x6C, -0x69,0x61,0x62,0x2E,0x29,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x0B,0x13,0x1C, -0x28,0x63,0x29,0x20,0x31,0x39,0x39,0x39,0x20,0x45,0x6E,0x74,0x72,0x75,0x73,0x74, -0x2E,0x6E,0x65,0x74,0x20,0x4C,0x69,0x6D,0x69,0x74,0x65,0x64,0x31,0x3A,0x30,0x38, -0x06,0x03,0x55,0x04,0x03,0x13,0x31,0x45,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E, -0x65,0x74,0x20,0x53,0x65,0x63,0x75,0x72,0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72, -0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, -0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x30,0x1E,0x17,0x0D,0x30,0x38,0x30,0x31, -0x32,0x39,0x31,0x38,0x33,0x33,0x31,0x33,0x5A,0x17,0x0D,0x31,0x30,0x30,0x31,0x32, -0x38,0x31,0x39,0x30,0x33,0x31,0x32,0x5A,0x30,0x81,0x83,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,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x0A,0x13,0x09,0x41,0x70,0x70,0x6C, -0x65,0x20,0x49,0x6E,0x63,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04,0x0B,0x13,0x13, -0x49,0x6E,0x74,0x65,0x72,0x6E,0x65,0x74,0x20,0x4F,0x70,0x65,0x72,0x61,0x74,0x69, -0x6F,0x6E,0x73,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x03,0x13,0x10,0x78,0x65, -0x64,0x67,0x65,0x32,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,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,0xC7,0xF3,0xA1,0x0E,0x0E, -0xA4,0xDF,0xC5,0x3F,0x24,0x87,0xC3,0x6E,0xE7,0xD0,0x7C,0x2B,0x5A,0x1C,0xF3,0x67, -0x6C,0x6B,0x56,0x0A,0x95,0xC9,0xE5,0x13,0x28,0x6E,0x16,0x9D,0x4F,0xB1,0x76,0xFB, -0x7D,0x42,0x5B,0x2A,0x7C,0xCC,0x97,0x75,0xAA,0xA6,0xA9,0xDE,0xB2,0xEC,0xEF,0xE2, -0xAB,0x40,0xAE,0x9A,0x23,0xF0,0x6A,0x10,0xB3,0x75,0x27,0xF0,0xF4,0x7D,0x08,0x67, -0x8F,0xCE,0x41,0x24,0x74,0xAA,0x37,0xB6,0xC1,0x32,0x61,0xCF,0x7D,0x1C,0x21,0xCD, -0xCF,0x7C,0x9E,0xE2,0x48,0x03,0x7E,0x78,0xB3,0x86,0x3D,0x06,0x6B,0x39,0xEC,0xC8, -0x73,0x68,0xDB,0xE7,0x5B,0x97,0xF4,0xF9,0xA3,0xE7,0xFB,0x81,0x2E,0x4D,0x0B,0x3F, -0xA9,0xCA,0xDE,0x32,0x26,0xF3,0xF0,0x97,0x72,0x65,0xAB,0x02,0x03,0x01,0x00,0x01, -0xA3,0x82,0x02,0xA2,0x30,0x82,0x02,0x9E,0x30,0x0B,0x06,0x03,0x55,0x1D,0x0F,0x04, -0x04,0x03,0x02,0x05,0xA0,0x30,0x2B,0x06,0x03,0x55,0x1D,0x10,0x04,0x24,0x30,0x22, -0x80,0x0F,0x32,0x30,0x30,0x38,0x30,0x31,0x32,0x39,0x31,0x38,0x33,0x33,0x31,0x33, -0x5A,0x81,0x0F,0x32,0x30,0x31,0x30,0x30,0x31,0x32,0x38,0x31,0x39,0x30,0x33,0x31, -0x32,0x5A,0x30,0x11,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x01,0x04, -0x04,0x03,0x02,0x06,0x40,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A, -0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x82,0x01,0x68,0x06,0x03, -0x55,0x1D,0x20,0x04,0x82,0x01,0x5F,0x30,0x82,0x01,0x5B,0x30,0x82,0x01,0x57,0x06, -0x09,0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x4B,0x02,0x30,0x82,0x01,0x48,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,0x65,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E, -0x65,0x74,0x2F,0x63,0x70,0x73,0x30,0x82,0x01,0x1C,0x06,0x08,0x2B,0x06,0x01,0x05, -0x05,0x07,0x02,0x02,0x30,0x82,0x01,0x0E,0x1A,0x82,0x01,0x0A,0x54,0x68,0x65,0x20, -0x45,0x6E,0x74,0x72,0x75,0x73,0x74,0x20,0x53,0x53,0x4C,0x20,0x57,0x65,0x62,0x20, -0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61, -0x74,0x69,0x6F,0x6E,0x20,0x50,0x72,0x61,0x63,0x74,0x69,0x63,0x65,0x20,0x53,0x74, -0x61,0x74,0x65,0x6D,0x65,0x6E,0x74,0x20,0x28,0x43,0x50,0x53,0x29,0x20,0x61,0x76, -0x61,0x69,0x6C,0x61,0x62,0x6C,0x65,0x20,0x61,0x74,0x20,0x77,0x77,0x77,0x2E,0x65, -0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x2F,0x63,0x70,0x73,0x20,0x20, -0x69,0x73,0x20,0x68,0x65,0x72,0x65,0x62,0x79,0x20,0x69,0x6E,0x63,0x6F,0x72,0x70, -0x6F,0x72,0x61,0x74,0x65,0x64,0x20,0x69,0x6E,0x74,0x6F,0x20,0x79,0x6F,0x75,0x72, -0x20,0x75,0x73,0x65,0x20,0x6F,0x72,0x20,0x72,0x65,0x6C,0x69,0x61,0x6E,0x63,0x65, -0x20,0x6F,0x6E,0x20,0x74,0x68,0x69,0x73,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69, -0x63,0x61,0x74,0x65,0x2E,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x43,0x50,0x53,0x20, -0x63,0x6F,0x6E,0x74,0x61,0x69,0x6E,0x73,0x20,0x6C,0x69,0x6D,0x69,0x74,0x61,0x74, -0x69,0x6F,0x6E,0x73,0x20,0x6F,0x6E,0x20,0x77,0x61,0x72,0x72,0x61,0x6E,0x74,0x69, -0x65,0x73,0x20,0x61,0x6E,0x64,0x20,0x6C,0x69,0x61,0x62,0x69,0x6C,0x69,0x74,0x69, -0x65,0x73,0x2E,0x20,0x43,0x6F,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x28,0x63, -0x29,0x20,0x32,0x30,0x30,0x32,0x20,0x45,0x6E,0x74,0x72,0x75,0x73,0x74,0x20,0x4C, -0x69,0x6D,0x69,0x74,0x65,0x64,0x30,0x33,0x06,0x03,0x55,0x1D,0x1F,0x04,0x2C,0x30, -0x2A,0x30,0x28,0xA0,0x26,0xA0,0x24,0x86,0x22,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, -0x63,0x72,0x6C,0x2E,0x65,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74,0x2F, -0x73,0x65,0x72,0x76,0x65,0x72,0x31,0x2E,0x63,0x72,0x6C,0x30,0x33,0x06,0x08,0x2B, -0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x27,0x30,0x25,0x30,0x23,0x06,0x08,0x2B, -0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x17,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, -0x6F,0x63,0x73,0x70,0x2E,0x65,0x6E,0x74,0x72,0x75,0x73,0x74,0x2E,0x6E,0x65,0x74, -0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xF0,0x17,0x62, -0x13,0x55,0x3D,0xB3,0xFF,0x0A,0x00,0x6B,0xFB,0x50,0x84,0x97,0xF3,0xED,0x62,0xD0, -0x1A,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x2D,0xEF,0xD9,0xAF, -0x1A,0x89,0x40,0x53,0x75,0x48,0x26,0x59,0x2F,0xEC,0x11,0x18,0xC0,0xD1,0x7A,0x34, -0x30,0x09,0x06,0x03,0x55,0x1D,0x13,0x04,0x02,0x30,0x00,0x30,0x19,0x06,0x09,0x2A, -0x86,0x48,0x86,0xF6,0x7D,0x07,0x41,0x00,0x04,0x0C,0x30,0x0A,0x1B,0x04,0x56,0x37, -0x2E,0x31,0x03,0x02,0x03,0x28,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, -0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0x77,0x33,0x2A,0x69,0x45,0x5A,0xB2, -0xF5,0x74,0xF7,0xDF,0xC7,0x08,0x85,0x86,0x88,0x98,0x41,0x7F,0x57,0x49,0x01,0xBA, -0x13,0x21,0x40,0xD0,0x0A,0x5C,0xA7,0x37,0xDF,0xB3,0x7E,0xF8,0xED,0x04,0x63,0xC3, -0xE8,0x0F,0xA0,0xE5,0xC4,0x4F,0x3A,0x90,0xE4,0x87,0x5F,0xEC,0xDB,0x65,0x8B,0x6E, -0x88,0x6E,0x6E,0xE4,0xBC,0x6A,0x7E,0x37,0x47,0x04,0xFF,0x09,0xC6,0x70,0xE1,0x65, -0x8F,0xE3,0xE9,0x60,0xEB,0xE8,0x8E,0x29,0xAE,0xF9,0x81,0xCA,0x9A,0x97,0x3C,0x6F, -0x7C,0xFA,0xA8,0x49,0xB4,0x33,0x76,0x9C,0x65,0x92,0x12,0xF6,0x7F,0x6A,0x62,0x84, -0x29,0x5F,0x14,0x26,0x6E,0x07,0x6F,0x5C,0xB5,0x7C,0x21,0x64,0x7C,0xD9,0x93,0xF4, -0x9C,0xC8,0xE7,0xEC,0xC6,0xAC,0x13,0xC4,0xF0 -}; - - -static void tests(void) -{ - SecTrustResultType trustResult; - SecTrustRef trust = NULL; - SecPolicyRef policy = NULL; - CFArrayRef certs = NULL; - CFDateRef date = NULL; - - const void *cert_xedge2; - isnt(cert_xedge2 = SecCertificateCreateWithBytes(NULL, xedge2_cert, - sizeof(xedge2_cert)), NULL, "create cert_xedge2"); - certs = CFArrayCreate(NULL, &cert_xedge2, 1, NULL); - - bool server = true; - policy = SecPolicyCreateSSL(server, CFSTR("xedge.apple.com")); // deliberate hostname mismatch - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), - "create trust for ssl server xedge.apple.com"); - CFReleaseSafe(certs); - date = CFDateCreate(NULL, 252288000.0); /* Jan 1st 2009 */ - ok_status(SecTrustSetVerifyDate(trust, date), "set trust date to Jan 1st 2009"); - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate xedge trust"); - is_status(trustResult, kSecTrustResultRecoverableTrustFailure, - "trust is kSecTrustResultRecoverableTrustFailure (hostname mismatch)"); - - /* Test SecPolicyCreateRevocation */ - { - /* FIXME need to do more than just call the function, but it's a start */ - SecPolicyRef revocation = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod); - isnt(revocation, NULL, "create revocation policy"); - CFReleaseSafe(revocation); - } - - /* Test SecTrustCopyPolicies */ - { - CFArrayRef policies = NULL; - ok_status(SecTrustCopyPolicies(trust, &policies), "copy policies"); - is((policies && (CFArrayGetCount(policies) > 0)), true, "non-empty policies"); - CFReleaseSafe(policies); - } - - /* Test SecTrustSetNetworkFetchAllowed */ - { - Boolean curAllow, allow; - ok_status(SecTrustGetNetworkFetchAllowed(trust, &curAllow)); - allow = !curAllow; /* flip it and see if the setting sticks */ - ok_status(SecTrustSetNetworkFetchAllowed(trust, allow)); - ok_status(SecTrustGetNetworkFetchAllowed(trust, &curAllow)); - is((allow == curAllow), true, "network fetch toggle"); - } - - /* Test setting OCSP response data */ - { - CFDataRef resp = (CFDataRef) CFDataCreateMutable(NULL, 0); - /* FIXME: use actual OCSPResponse DER blob */ - CFDataIncreaseLength((CFMutableDataRef)resp, 64); /* arbitrary length, zero-filled data */ - - is_status(SecTrustSetOCSPResponse(NULL, resp), errSecParam, "SecTrustSetOCSPResponse param 1 check OK"); - is_status(SecTrustSetOCSPResponse(trust, NULL), errSecSuccess, "SecTrustSetOCSPResponse param 2 check OK"); - is_status(SecTrustSetOCSPResponse(trust, resp), errSecSuccess, "SecTrustSetOCSPResponse OK"); - CFReleaseSafe(resp); - } - - /* Test creation of a policy via SecPolicyCreateWithProperties */ - CFReleaseNull(policy); - { - const void *keys[] = { kSecPolicyName, kSecPolicyClient }; - const void *values[] = { CFSTR("xedge2.apple.com"), kCFBooleanFalse }; - CFDictionaryRef properties = CFDictionaryCreate(NULL, keys, values, - array_size(keys), - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - policy = SecPolicyCreateWithProperties(kSecPolicyAppleSSL, properties); - isnt(policy, NULL, "SecPolicyCreateWithProperties"); - CFReleaseSafe(properties); - } - - /* Test introspection of a policy's properties via SecPolicyCopyProperties */ - { - CFDictionaryRef properties = NULL; - isnt(properties = SecPolicyCopyProperties(policy), NULL, "copy policy properties"); - CFTypeRef value = NULL; - is(CFDictionaryGetValueIfPresent(properties, kSecPolicyName, (const void **)&value) && - kCFCompareEqualTo == CFStringCompare((CFStringRef)value, CFSTR("xedge2.apple.com"), 0), - true, "has policy name"); - is(CFDictionaryGetValueIfPresent(properties, kSecPolicyOid, (const void **)&value) && - CFEqual(value, kSecPolicyAppleSSL) , true, "has SSL policy"); - CFReleaseSafe(properties); - } - /* Test setting new policy on a trust via SecTrustSetPolicies */ - ok_status(SecTrustSetPolicies(trust, policy)); - /* Evaluation should now succeed, since our new policy has the correct hostname */ - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate xedge2 trust"); - is_status(trustResult, kSecTrustResultUnspecified, - "trust is kSecTrustResultUnspecified"); - - /* Make sure we can get the results */ - { - CFDictionaryRef results = NULL; - SecTrustResultType anotherResult = kSecTrustResultInvalid; - ok_status(SecTrustGetTrustResult(trust, &anotherResult), "get trust result"); - is_status(trustResult, anotherResult, "trust is kSecTrustResultUnspecified"); - - isnt(results = SecTrustCopyResult(trust), NULL, "copy trust results"); - CFReleaseSafe(results); - } - - CFReleaseSafe(trust); - CFReleaseSafe(policy); - CFReleaseSafe(date); - CFReleaseSafe(cert_xedge2); -} - -int si_70_sectrust_unified(int argc, char *const *argv) -{ - plan_tests(25); - tests(); - - return 0; -} diff --git a/sec/Security/Regressions/secitem/si-71-mobile-store-policy.c b/sec/Security/Regressions/secitem/si-71-mobile-store-policy.c deleted file mode 100644 index 729a06ff..00000000 --- a/sec/Security/Regressions/secitem/si-71-mobile-store-policy.c +++ /dev/null @@ -1,424 +0,0 @@ -/* - * si-70-mobile-store-policy.c - * Security - * - * Created by James Murphy on 05/15/13. - * Copyright (c) 2013 Apple Inc. All Rights Reserved. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Security_regressions.h" - -#if defined(NO_SERVER) && NO_SERVER == 1 - -static const uint8_t kDemoContentSigningCert[] = { - 0x30, 0x82, 0x04, 0x1a, 0x30, 0x82, 0x03, 0x02, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x47, - 0x62, 0x58, 0xaa, 0x2c, 0xdd, 0x90, 0xc1, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x87, 0x31, 0x3b, 0x30, 0x39, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x0c, 0x32, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, - 0x20, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x32, 0x20, 0x43, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, - 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, - 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, - 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, - 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x36, 0x30, 0x34, 0x32, 0x31, 0x34, 0x37, 0x31, 0x37, - 0x5a, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x36, 0x30, 0x33, 0x32, 0x31, 0x34, 0x37, 0x31, 0x37, 0x5a, - 0x30, 0x53, 0x31, 0x1d, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x14, 0x44, 0x65, 0x6d, - 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, - 0x67, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x07, 0x43, 0x6f, 0x72, 0x65, - 0x20, 0x4f, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, - 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 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, 0xaf, 0x2a, 0xac, 0x4b, 0x91, 0x1e, 0x4d, 0x9f, 0x1d, 0x23, - 0xf3, 0xff, 0x1c, 0xbe, 0x87, 0xbe, 0x3e, 0x2a, 0x0f, 0x35, 0xf4, 0xad, 0x80, 0x01, 0xc3, 0xf6, - 0x6b, 0x12, 0xc4, 0xfa, 0x0f, 0xf5, 0xbc, 0xc0, 0x79, 0x76, 0xad, 0x77, 0xb1, 0x8d, 0xdc, 0xe7, - 0xa0, 0x8a, 0xe0, 0x6a, 0xa3, 0xdb, 0x24, 0xb6, 0x0b, 0xa5, 0x29, 0x13, 0xe0, 0xd4, 0x96, 0xc7, - 0x1e, 0xee, 0x9b, 0x56, 0x63, 0xdd, 0xab, 0x9b, 0x4e, 0x7d, 0x09, 0xa7, 0x3f, 0xf9, 0xec, 0x96, - 0xcb, 0x88, 0x62, 0x91, 0xfe, 0xb8, 0x10, 0xe4, 0x40, 0x10, 0xb5, 0x34, 0x8a, 0x8e, 0x9a, 0x28, - 0x16, 0xc3, 0x8e, 0x06, 0xda, 0x32, 0x04, 0x64, 0x60, 0x3b, 0xae, 0x70, 0x24, 0xb0, 0xcc, 0x6c, - 0x76, 0x69, 0xb3, 0x52, 0x8f, 0x9c, 0x7a, 0xfb, 0x68, 0x55, 0x88, 0x2f, 0xd8, 0x18, 0xe0, 0x51, - 0x43, 0xdb, 0x91, 0x9f, 0x10, 0xcf, 0xd8, 0x93, 0x6e, 0x5d, 0xef, 0x90, 0xac, 0x47, 0x56, 0xf7, - 0x32, 0xd3, 0xf0, 0xb4, 0x9d, 0x68, 0x94, 0xdd, 0x4f, 0xf9, 0x5a, 0xb4, 0x9a, 0x81, 0xf8, 0xef, - 0xae, 0xd8, 0x27, 0x4d, 0xec, 0xc5, 0x7d, 0xc2, 0xfe, 0x80, 0x23, 0x4d, 0x13, 0xc9, 0x90, 0x5a, - 0x91, 0x86, 0x30, 0x42, 0x7d, 0x38, 0xda, 0x17, 0xa8, 0x46, 0x3e, 0x76, 0x8c, 0xca, 0x5e, 0x20, - 0x1d, 0x3b, 0x85, 0xda, 0x87, 0x9d, 0xf1, 0xc7, 0x1d, 0x3c, 0x13, 0x4a, 0x56, 0xd4, 0x23, 0x52, - 0x96, 0x6b, 0xb8, 0x99, 0x79, 0x03, 0x88, 0xbd, 0xf0, 0xf2, 0x28, 0x79, 0x1b, 0xe7, 0x8e, 0xfc, - 0xd0, 0x30, 0xf3, 0x0b, 0x3e, 0x15, 0xff, 0x20, 0x5c, 0x42, 0x67, 0x7e, 0x0e, 0x52, 0x86, 0x50, - 0xa0, 0x36, 0xb8, 0xc3, 0xee, 0x3d, 0xd8, 0xd6, 0x77, 0x15, 0xb7, 0x8f, 0xed, 0xf6, 0x42, 0xe4, - 0xfc, 0x52, 0xf6, 0x45, 0x67, 0x41, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xbc, 0x30, 0x81, - 0xb9, 0x30, 0x3e, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x32, 0x30, - 0x30, 0x30, 0x2e, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x22, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x30, 0x34, 0x2d, 0x61, 0x73, 0x69, 0x30, - 0x32, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x55, 0xac, 0xda, 0x4b, - 0xad, 0xf1, 0xe8, 0xe4, 0x2f, 0x72, 0xc2, 0x02, 0x2b, 0xaa, 0x01, 0x23, 0x9c, 0x96, 0x86, 0xdb, - 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, 0x12, 0x75, 0x7c, 0x47, 0x92, - 0xfd, 0x83, 0xe3, 0xbe, 0x2e, 0xfc, 0x59, 0x7f, 0x67, 0x43, 0x81, 0x35, 0x10, 0x45, 0xec, 0x30, - 0x19, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x01, 0x01, 0xff, 0x04, 0x0f, 0x30, 0x0d, 0x30, 0x0b, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, 0x0c, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, - 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x27, 0x50, - 0xf8, 0x85, 0xe0, 0x6a, 0xf6, 0x74, 0x26, 0xcb, 0x5a, 0x23, 0xef, 0xd8, 0x32, 0xa0, 0x87, 0xf0, - 0x01, 0x29, 0x1c, 0x64, 0x84, 0x9e, 0xc6, 0x3b, 0xd7, 0x9e, 0x40, 0x8b, 0x0a, 0x8c, 0x9d, 0xd5, - 0x9b, 0x77, 0xc6, 0x5c, 0xe6, 0x52, 0xfb, 0x5b, 0x41, 0x2b, 0xbb, 0x8c, 0x24, 0xd5, 0xaf, 0xa1, - 0xab, 0x2b, 0xda, 0x3e, 0x11, 0x6b, 0x51, 0xe5, 0xc8, 0xb9, 0xf7, 0x1b, 0x0c, 0x89, 0x6e, 0x29, - 0x1a, 0x88, 0x24, 0xf9, 0x03, 0x2d, 0x46, 0x14, 0x07, 0xff, 0x3f, 0xd2, 0x2b, 0x87, 0x9b, 0xdb, - 0x5c, 0x06, 0x4a, 0x20, 0x4d, 0xf6, 0x33, 0xb1, 0x06, 0x93, 0x87, 0x27, 0x5c, 0x93, 0xca, 0xf6, - 0x81, 0x79, 0x71, 0x82, 0x1b, 0x88, 0x1d, 0x5a, 0x67, 0xc6, 0x2c, 0xd7, 0x68, 0x69, 0xbb, 0x07, - 0x1d, 0x12, 0xae, 0x78, 0x4c, 0xfa, 0x4e, 0xc5, 0x80, 0x5c, 0x2d, 0xd4, 0xb0, 0xcf, 0x71, 0x64, - 0x9e, 0xf8, 0xf3, 0x99, 0xd4, 0xd9, 0xdb, 0xbf, 0xd7, 0xb8, 0x97, 0x24, 0x3f, 0x34, 0x19, 0x52, - 0x73, 0xac, 0xca, 0x31, 0xac, 0x0d, 0xb5, 0x72, 0x11, 0x2d, 0x03, 0x7b, 0xce, 0xf6, 0x1e, 0x84, - 0x09, 0x3b, 0x47, 0xa0, 0x6a, 0xd6, 0x54, 0x60, 0x6d, 0x76, 0x6d, 0x02, 0xbb, 0xa8, 0x69, 0xa8, - 0x58, 0xb5, 0xe2, 0x34, 0xdb, 0x8d, 0xb2, 0x96, 0x17, 0x47, 0x6d, 0xbc, 0xe9, 0xc6, 0xc9, 0xae, - 0xc0, 0x54, 0xcf, 0x98, 0xc9, 0xea, 0x92, 0x69, 0x7f, 0x92, 0x82, 0x19, 0x63, 0x45, 0x5b, 0xeb, - 0x85, 0x0b, 0xaa, 0x7e, 0x4a, 0x77, 0xb4, 0xf9, 0x45, 0xe8, 0x0e, 0x1e, 0x1f, 0xab, 0x1c, 0x86, - 0x59, 0xa8, 0x82, 0x1e, 0x73, 0x86, 0x44, 0xfc, 0x67, 0x2a, 0x71, 0xeb, 0xb9, 0x9e, 0xd0, 0x28, - 0xd7, 0xb1, 0xef, 0xa3, 0x8c, 0x0d, 0x18, 0xd4, 0x8c, 0x1c, 0xb3, 0x0e, 0xba, 0x30 -}; - -static const uint8_t kTestDemoContentSigningCert[] = { - 0x30, 0x82, 0x04, 0x20, 0x30, 0x82, 0x03, 0x08, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x75, - 0x93, 0x8a, 0xaa, 0xe6, 0x6e, 0x3c, 0x5a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x87, 0x31, 0x3b, 0x30, 0x39, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x0c, 0x32, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, - 0x20, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x32, 0x20, 0x43, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, - 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x13, - 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, - 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, - 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x36, 0x30, 0x34, 0x30, 0x30, 0x30, 0x32, 0x35, 0x32, - 0x5a, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x36, 0x30, 0x33, 0x30, 0x30, 0x30, 0x32, 0x35, 0x32, 0x5a, - 0x30, 0x58, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x19, 0x54, 0x65, 0x73, - 0x74, 0x20, 0x44, 0x65, 0x6d, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x53, - 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, - 0x07, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x4f, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, - 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 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, 0xac, 0xc5, 0x87, 0x0d, 0x3b, - 0x14, 0xba, 0x87, 0x63, 0x3d, 0xc9, 0x8d, 0xc1, 0x3a, 0xa9, 0x71, 0x14, 0x30, 0x6b, 0x64, 0x58, - 0x35, 0xb2, 0xff, 0xcf, 0xe1, 0xe1, 0x5c, 0xa8, 0x5d, 0x99, 0xed, 0x11, 0x53, 0xf5, 0x6f, 0x92, - 0x39, 0x28, 0x5a, 0x0f, 0x76, 0x86, 0x40, 0x44, 0x6a, 0x7b, 0x23, 0x05, 0x50, 0xfd, 0x1b, 0x29, - 0xd9, 0x83, 0xfe, 0x0b, 0x65, 0xc6, 0x35, 0x8c, 0x69, 0x4e, 0x93, 0xa3, 0x32, 0x74, 0x18, 0xd4, - 0x06, 0xaf, 0xe5, 0x74, 0xb9, 0x63, 0x89, 0x41, 0x25, 0x2f, 0x15, 0xb6, 0x71, 0x45, 0x02, 0x5e, - 0x71, 0x11, 0xec, 0xea, 0xb8, 0x3a, 0x3d, 0xf2, 0x87, 0x2b, 0x71, 0xb8, 0x7e, 0xc8, 0xc7, 0x06, - 0x12, 0x87, 0x21, 0x61, 0x2f, 0xeb, 0x33, 0x44, 0xe1, 0x3e, 0xa7, 0x77, 0x6a, 0xfe, 0x5d, 0xee, - 0x4c, 0x77, 0x57, 0x74, 0xf7, 0x64, 0x2b, 0x6f, 0x12, 0x1b, 0x0e, 0xec, 0x49, 0x41, 0x81, 0x93, - 0x6b, 0xf9, 0x3b, 0x4e, 0x83, 0x53, 0xd7, 0x05, 0xe0, 0x29, 0x78, 0xf2, 0xd3, 0xe5, 0x81, 0x6f, - 0x47, 0xd1, 0xc8, 0xae, 0xb3, 0x22, 0xa9, 0x29, 0x61, 0xe2, 0x36, 0x26, 0xb9, 0x0d, 0x9d, 0x23, - 0x90, 0x45, 0x8b, 0x42, 0xbc, 0x8b, 0x60, 0xd5, 0xd2, 0x56, 0xc6, 0x09, 0xfd, 0x45, 0xff, 0x8c, - 0x54, 0x69, 0x74, 0x81, 0x90, 0x7a, 0x31, 0x6f, 0xf0, 0x16, 0x4c, 0xef, 0x1c, 0xa9, 0x97, 0xc9, - 0x4e, 0xfe, 0x7d, 0x87, 0x7a, 0x47, 0x3f, 0xa5, 0xc8, 0x20, 0xd3, 0x4a, 0xe2, 0xf3, 0xf6, 0x3a, - 0xf1, 0xef, 0x24, 0x5e, 0x35, 0xc8, 0xdf, 0x7b, 0x12, 0xda, 0xcc, 0xef, 0xbb, 0xf2, 0xfa, 0x28, - 0xf6, 0x38, 0x57, 0xcf, 0x41, 0xd6, 0x43, 0x21, 0x62, 0xc6, 0xa3, 0x3f, 0xf5, 0xd1, 0x86, 0x41, - 0x42, 0xb6, 0x69, 0xca, 0xb0, 0x8a, 0xba, 0xba, 0xbe, 0x97, 0x85, 0x02, 0x03, 0x01, 0x00, 0x01, - 0xa3, 0x81, 0xbd, 0x30, 0x81, 0xba, 0x30, 0x3e, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x01, 0x01, 0x04, 0x32, 0x30, 0x30, 0x30, 0x2e, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x30, 0x01, 0x86, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, - 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x30, 0x34, - 0x2d, 0x61, 0x73, 0x69, 0x30, 0x33, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, - 0x14, 0x0a, 0x8f, 0x13, 0x24, 0x0d, 0xc4, 0xe4, 0xe7, 0x97, 0x65, 0x35, 0xc8, 0x19, 0x91, 0x38, - 0x28, 0xce, 0x9b, 0x50, 0xdb, 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, - 0x12, 0x75, 0x7c, 0x47, 0x92, 0xfd, 0x83, 0xe3, 0xbe, 0x2e, 0xfc, 0x59, 0x7f, 0x67, 0x43, 0x81, - 0x35, 0x10, 0x45, 0xec, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x01, 0x01, 0xff, 0x04, 0x10, - 0x30, 0x0e, 0x30, 0x0c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x05, 0x0c, 0x01, - 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, - 0x82, 0x01, 0x01, 0x00, 0x59, 0x19, 0xdd, 0x6c, 0xf5, 0xb6, 0xf9, 0x93, 0x69, 0xe5, 0xcd, 0x64, - 0x5c, 0x4c, 0xaa, 0xd8, 0x86, 0x44, 0x6b, 0xca, 0x48, 0x6f, 0x2b, 0x15, 0x8f, 0xef, 0x1a, 0x5c, - 0xc9, 0xb2, 0x5b, 0x51, 0xee, 0xae, 0xf8, 0xeb, 0x7e, 0x05, 0x4a, 0xa1, 0x27, 0xd3, 0x15, 0x41, - 0xa1, 0x2c, 0x7e, 0x81, 0x96, 0xa8, 0xba, 0x8d, 0x1c, 0xc0, 0x0a, 0xce, 0xfd, 0x4b, 0xbc, 0x56, - 0x80, 0xe8, 0xf1, 0x04, 0x05, 0xd9, 0x17, 0x3d, 0x29, 0x6d, 0x99, 0xf5, 0xcc, 0x3a, 0x80, 0x7c, - 0x03, 0xb0, 0x8a, 0x4e, 0x2c, 0xdb, 0x24, 0x42, 0xa7, 0xa6, 0x8b, 0x2e, 0xff, 0x9c, 0xec, 0xce, - 0xe0, 0x0f, 0xd3, 0x5c, 0x0a, 0xed, 0x35, 0x14, 0xd0, 0x33, 0x76, 0xe0, 0x46, 0x09, 0x35, 0x54, - 0x40, 0x9b, 0x56, 0x8a, 0x45, 0x17, 0xa7, 0x50, 0x95, 0x5c, 0x9f, 0x5e, 0x95, 0x26, 0x89, 0xfe, - 0x79, 0xc6, 0x01, 0x3b, 0xf9, 0x64, 0x83, 0x28, 0x2b, 0x2d, 0x24, 0xbd, 0xb8, 0x4a, 0xca, 0x9a, - 0xba, 0x59, 0x5f, 0x72, 0xdd, 0x90, 0xcc, 0x4c, 0xed, 0x49, 0xf6, 0x11, 0x10, 0x7c, 0x34, 0x86, - 0x3f, 0x3e, 0x9a, 0xc0, 0xe6, 0xda, 0xf0, 0x6d, 0xb0, 0xd2, 0xf0, 0x46, 0x1e, 0x33, 0x53, 0x4a, - 0x5c, 0xd3, 0xdc, 0x9b, 0x74, 0x3d, 0x3e, 0x85, 0x9c, 0x19, 0xca, 0xb5, 0x26, 0xd5, 0xda, 0x22, - 0x7d, 0x52, 0xe6, 0x8c, 0x95, 0xd8, 0x30, 0x61, 0xf5, 0x3e, 0x05, 0x40, 0xe5, 0xd0, 0xcb, 0x91, - 0x28, 0x17, 0x4c, 0xf3, 0xf8, 0x06, 0x4c, 0x71, 0x80, 0xe0, 0x7c, 0x11, 0x7b, 0x00, 0xed, 0xe6, - 0x93, 0x8c, 0x12, 0x9e, 0xcc, 0x65, 0x5a, 0xb6, 0x61, 0x21, 0xe0, 0x0f, 0x3a, 0x8e, 0xcf, 0x12, - 0xea, 0x16, 0xbb, 0x91, 0x7e, 0x6c, 0x11, 0xb2, 0x29, 0x8a, 0x41, 0x46, 0xc3, 0xae, 0xd9, 0xf7, - 0x15, 0xe8, 0xaa, 0x86 -}; - -static const uint8_t kMobileIntermediate[] = { - 0x30, 0x82, 0x04, 0x13, 0x30, 0x82, 0x02, 0xfb, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x60, - 0x25, 0x4e, 0x56, 0x81, 0x16, 0xcf, 0xf1, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x62, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, - 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, - 0x55, 0x04, 0x0b, 0x13, 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, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0d, 0x41, 0x70, 0x70, - 0x6c, 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, - 0x30, 0x39, 0x31, 0x33, 0x32, 0x32, 0x33, 0x35, 0x33, 0x37, 0x5a, 0x17, 0x0d, 0x32, 0x37, 0x30, - 0x39, 0x31, 0x33, 0x32, 0x32, 0x33, 0x35, 0x33, 0x37, 0x5a, 0x30, 0x81, 0x87, 0x31, 0x3b, 0x30, - 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x32, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x53, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, - 0x55, 0x04, 0x0b, 0x0c, 0x1d, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x74, 0x79, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x41, 0x70, 0x70, - 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x55, 0x53, 0x30, 0x82, 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, 0x9e, 0x48, 0xf6, 0x8f, 0xab, 0x1b, 0x89, 0xa5, 0x9f, 0x34, 0x47, - 0xb6, 0x38, 0x30, 0xa7, 0xb0, 0x62, 0xa4, 0x99, 0x84, 0x2a, 0x74, 0x4b, 0x47, 0x5b, 0x66, 0x35, - 0x69, 0xfe, 0x97, 0x01, 0x64, 0x18, 0x9d, 0x0a, 0xf8, 0xd7, 0x33, 0x2a, 0x64, 0xd8, 0xbc, 0x03, - 0x4f, 0xcd, 0x4d, 0x80, 0x90, 0xd2, 0xc3, 0xc5, 0xd1, 0x8c, 0xc1, 0x73, 0xf6, 0x5a, 0x50, 0x70, - 0xcd, 0xe0, 0x94, 0x35, 0x82, 0xc4, 0x59, 0xca, 0xba, 0xa9, 0x94, 0xbd, 0x88, 0x36, 0x7a, 0x32, - 0xdf, 0x08, 0x29, 0xe0, 0x9c, 0x19, 0x1c, 0x68, 0x02, 0x60, 0x87, 0xfc, 0x2e, 0x8a, 0x3c, 0x37, - 0x4d, 0x7c, 0x81, 0xbb, 0x6c, 0x6f, 0x72, 0x45, 0xf5, 0xb3, 0x96, 0x66, 0x5e, 0xab, 0x97, 0x54, - 0x50, 0x03, 0xc0, 0x41, 0xfc, 0xb5, 0xa8, 0xf7, 0x78, 0xde, 0x4c, 0x9a, 0x67, 0xf4, 0x4d, 0x27, - 0x54, 0x9e, 0xc8, 0x75, 0xea, 0x8c, 0x76, 0xc1, 0xb5, 0x79, 0xe3, 0x60, 0xce, 0x98, 0x21, 0x38, - 0x7b, 0x9a, 0x53, 0xe8, 0x57, 0x69, 0x13, 0xf0, 0xf0, 0x86, 0x91, 0x2e, 0xad, 0x75, 0xb9, 0x53, - 0x4a, 0x30, 0xf6, 0x6d, 0x96, 0x8e, 0x5e, 0xe7, 0xe9, 0xa5, 0x16, 0xe7, 0xb4, 0x5b, 0xe7, 0xe9, - 0x6e, 0x4f, 0xe7, 0x38, 0xda, 0x53, 0x39, 0x60, 0x0e, 0xfd, 0xd0, 0x0b, 0x19, 0x52, 0x5d, 0x79, - 0x3a, 0x5d, 0x7b, 0x0d, 0x19, 0x91, 0x72, 0x94, 0x0e, 0x03, 0xa6, 0x14, 0xca, 0xdd, 0x7a, 0x27, - 0xed, 0x22, 0x21, 0xeb, 0x67, 0x01, 0xc0, 0x98, 0x4f, 0xf7, 0x78, 0x81, 0x34, 0xfb, 0x08, 0x48, - 0xb6, 0xec, 0xa4, 0xdb, 0x60, 0xd3, 0x9d, 0xa7, 0x46, 0x6c, 0x50, 0xa6, 0x14, 0x4a, 0x30, 0xee, - 0x77, 0x87, 0x64, 0xb6, 0xb2, 0xb4, 0x92, 0xfc, 0x45, 0xb3, 0x80, 0x59, 0xbd, 0x85, 0x9c, 0x2f, - 0xd1, 0xd7, 0x59, 0xe3, 0x0f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa6, 0x30, 0x81, 0xa3, - 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x12, 0x75, 0x7c, 0x47, 0x92, - 0xfd, 0x83, 0xe3, 0xbe, 0x2e, 0xfc, 0x59, 0x7f, 0x67, 0x43, 0x81, 0x35, 0x10, 0x45, 0xec, 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, 0x2b, 0xd0, 0x69, - 0x47, 0x94, 0x76, 0x09, 0xfe, 0xf4, 0x6b, 0x8d, 0x2e, 0x40, 0xa6, 0xf7, 0x47, 0x4d, 0x7f, 0x08, - 0x5e, 0x30, 0x2e, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x27, 0x30, 0x25, 0x30, 0x23, 0xa0, 0x21, - 0xa0, 0x1f, 0x86, 0x1d, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x61, - 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 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, 0x0a, 0x04, - 0x02, 0x05, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, - 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xaa, 0x3d, 0x38, 0x8a, 0x96, 0x9b, 0xc7, 0x94, 0x97, - 0x3d, 0x3e, 0x5b, 0x1f, 0x09, 0x43, 0xe1, 0x1a, 0x6e, 0x6a, 0x4d, 0xd6, 0x38, 0xbb, 0x8a, 0x6d, - 0x00, 0xc9, 0x93, 0xdc, 0x3e, 0xa2, 0xc3, 0x2a, 0x97, 0xc1, 0x4f, 0x07, 0xa0, 0xa3, 0x14, 0x6c, - 0xd9, 0x0b, 0x9a, 0xcd, 0xb1, 0xcf, 0x7c, 0xc0, 0x67, 0x75, 0x12, 0xee, 0x2e, 0xb0, 0x28, 0x17, - 0x18, 0x7e, 0x73, 0x3d, 0xb4, 0x04, 0x91, 0x39, 0x7c, 0x37, 0xfb, 0xbd, 0x34, 0x01, 0xa0, 0xde, - 0x77, 0xa7, 0x5b, 0xb6, 0x47, 0x8e, 0x73, 0x3a, 0x8f, 0x7b, 0x63, 0x58, 0xc4, 0xa3, 0x6d, 0x19, - 0x4d, 0x9d, 0x9e, 0xd6, 0x3e, 0xbe, 0x18, 0x53, 0xe9, 0x30, 0x4d, 0xd2, 0xad, 0xef, 0x4b, 0xf6, - 0xa4, 0x84, 0xcf, 0x25, 0xfc, 0xea, 0x0d, 0x33, 0x58, 0x51, 0x00, 0xe2, 0x4b, 0xfe, 0x74, 0xd9, - 0x47, 0x13, 0x9e, 0xa7, 0xd7, 0x37, 0x6a, 0xea, 0x27, 0x0c, 0x6c, 0x7e, 0x8a, 0x93, 0xee, 0x60, - 0x10, 0x30, 0x1b, 0xf5, 0x59, 0x2a, 0x14, 0x4f, 0xd8, 0x7f, 0xe7, 0xb0, 0xe6, 0x3d, 0xfe, 0x72, - 0xe0, 0xc8, 0x52, 0x21, 0x15, 0x37, 0x18, 0x59, 0xd4, 0x7c, 0x5c, 0x8d, 0x55, 0x0b, 0x9b, 0xfb, - 0x3a, 0x75, 0x0f, 0xf6, 0x06, 0x29, 0xb6, 0xc2, 0x7f, 0x8d, 0x95, 0xce, 0x68, 0x77, 0x73, 0xae, - 0xde, 0x81, 0xfa, 0xce, 0x09, 0x72, 0xb1, 0x6c, 0xce, 0xe4, 0x94, 0x9e, 0x85, 0xf8, 0xdc, 0xba, - 0xc4, 0x5f, 0x77, 0xe9, 0x9e, 0x03, 0x99, 0x34, 0x8d, 0xcc, 0xdc, 0x9f, 0x56, 0x98, 0xed, 0x28, - 0xed, 0x06, 0x56, 0x80, 0xea, 0x52, 0x3a, 0x95, 0xc4, 0x64, 0x8f, 0x0c, 0xd9, 0x57, 0xbd, 0xc2, - 0xa9, 0x8d, 0xa0, 0x3a, 0xe2, 0x6c, 0x5a, 0x2a, 0x7b, 0xda, 0xf6, 0x81, 0x1a, 0x03, 0x17, 0x6b, - 0x0c, 0x0c, 0xda, 0xbd, 0x8e, 0x23, 0x06 - -}; - -// Escrow Service Key F98EB04C6AA62F4022709406305387C61415DDD770A24039C1415F24BF918803 -static const uint8_t kEscrowLeafCert[] = { - 0x30, 0x82, 0x04, 0x07, 0x30, 0x82, 0x02, 0xef, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x05, 0x00, - 0x9b, 0x6e, 0xef, 0x8d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x0b, 0x05, 0x00, 0x30, 0x79, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x03, - 0x31, 0x30, 0x30, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, - 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 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, 0x33, 0x30, 0x38, 0x30, 0x32, 0x32, 0x33, 0x32, 0x34, 0x34, 0x38, 0x5a, 0x17, - 0x0d, 0x31, 0x35, 0x30, 0x38, 0x30, 0x32, 0x32, 0x33, 0x32, 0x34, 0x34, 0x38, 0x5a, 0x30, 0x81, - 0x9b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, - 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x02, 0x43, 0x41, 0x31, 0x13, 0x30, 0x11, 0x06, - 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, - 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x03, 0x45, 0x54, 0x53, 0x31, 0x5c, - 0x30, 0x5a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x53, 0x45, 0x73, 0x63, 0x72, 0x6f, 0x77, 0x20, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x39, 0x42, 0x36, 0x45, - 0x45, 0x46, 0x38, 0x44, 0x37, 0x42, 0x33, 0x43, 0x34, 0x39, 0x31, 0x32, 0x46, 0x35, 0x35, 0x35, - 0x32, 0x32, 0x32, 0x32, 0x42, 0x42, 0x34, 0x31, 0x44, 0x38, 0x34, 0x43, 0x43, 0x31, 0x39, 0x43, - 0x33, 0x35, 0x37, 0x37, 0x32, 0x35, 0x41, 0x36, 0x43, 0x35, 0x46, 0x34, 0x45, 0x35, 0x43, 0x43, - 0x36, 0x30, 0x37, 0x41, 0x32, 0x44, 0x37, 0x32, 0x31, 0x35, 0x41, 0x43, 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, 0xc7, 0x51, - 0xf1, 0x3f, 0x9a, 0x5d, 0xd7, 0xc1, 0x03, 0x42, 0x30, 0x84, 0xdb, 0xbc, 0x6c, 0x00, 0x6c, 0xcc, - 0x57, 0x97, 0xaf, 0xfe, 0x9e, 0xa0, 0x06, 0x9f, 0xe8, 0xa9, 0x59, 0xe1, 0xf8, 0xed, 0x23, 0x05, - 0x57, 0xe3, 0xd8, 0xdf, 0xf8, 0x31, 0x80, 0x8b, 0x31, 0x08, 0x2a, 0xc3, 0x7b, 0x16, 0xba, 0x27, - 0x84, 0x4e, 0xbb, 0x55, 0x5b, 0xd2, 0xda, 0x2d, 0xea, 0xda, 0x5c, 0xf0, 0x21, 0x58, 0x63, 0x74, - 0xa9, 0x90, 0x99, 0xbe, 0x87, 0x19, 0x7d, 0x87, 0xfc, 0xcb, 0xb6, 0xc9, 0x39, 0x51, 0x6a, 0xa7, - 0x81, 0x05, 0x50, 0x2d, 0xa2, 0x10, 0x6d, 0x58, 0xa5, 0x62, 0x29, 0x53, 0xce, 0xa6, 0x53, 0xad, - 0x3f, 0x50, 0xda, 0x1a, 0x1e, 0x2c, 0xe3, 0xae, 0x24, 0x88, 0xa5, 0x4c, 0xa3, 0x3a, 0xe1, 0xc6, - 0xa9, 0xcf, 0xb5, 0x53, 0x30, 0xbf, 0x7b, 0xea, 0x77, 0x21, 0x24, 0xfd, 0x91, 0x4c, 0x6f, 0x60, - 0x9f, 0x78, 0xf9, 0xed, 0x84, 0xe5, 0xee, 0xab, 0x07, 0xc5, 0x34, 0xa9, 0xe2, 0x0a, 0xf5, 0xf5, - 0xfa, 0x66, 0x75, 0xc8, 0x3e, 0x9c, 0xdd, 0xea, 0x60, 0xf0, 0x83, 0x03, 0x19, 0x08, 0xa4, 0x85, - 0xb0, 0xf3, 0xb1, 0xf1, 0x7a, 0x3d, 0xb4, 0xc8, 0xdd, 0x25, 0x5a, 0x1b, 0xf5, 0xa0, 0x78, 0xf9, - 0xbb, 0x08, 0x27, 0x6f, 0xa9, 0xf9, 0x17, 0xe8, 0xcb, 0x01, 0xa3, 0x5a, 0xd0, 0x67, 0xfb, 0xb7, - 0xef, 0xb7, 0x5c, 0x20, 0x94, 0x17, 0x5d, 0x46, 0xbd, 0xd2, 0xfe, 0xb6, 0x68, 0x88, 0x9f, 0xa6, - 0x0b, 0x97, 0x0f, 0x2e, 0x10, 0x23, 0x52, 0x9e, 0x69, 0x8b, 0xf4, 0x80, 0x83, 0x0e, 0x5b, 0x04, - 0xfc, 0x4e, 0xa1, 0x32, 0x44, 0x8a, 0x63, 0x3e, 0x3b, 0x0b, 0x70, 0x15, 0xd4, 0x17, 0xc1, 0xbe, - 0xbb, 0x01, 0x37, 0xe8, 0xfb, 0x58, 0x8b, 0x3d, 0xec, 0xc4, 0x47, 0x82, 0xe5, 0x02, 0x03, 0x01, - 0x00, 0x01, 0xa3, 0x73, 0x30, 0x71, 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, 0x20, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb7, - 0x34, 0x54, 0x7b, 0x16, 0x2a, 0x38, 0x22, 0xd5, 0x79, 0x7b, 0xbf, 0x5c, 0x62, 0x16, 0x59, 0xc5, - 0x53, 0x9f, 0xac, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, - 0xfd, 0x78, 0x96, 0x53, 0x80, 0xd6, 0xf6, 0xdc, 0xa6, 0xc3, 0x59, 0x06, 0x38, 0xed, 0x79, 0x3e, - 0x8f, 0x50, 0x1b, 0x50, 0x30, 0x11, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x06, - 0x17, 0x01, 0x04, 0x03, 0x02, 0x01, 0x0a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x01, 0x41, 0x68, 0xd9, 0xd5, - 0xb5, 0xbe, 0x2d, 0xa1, 0xe7, 0x52, 0x28, 0x2c, 0x4f, 0xe7, 0x43, 0x39, 0x4d, 0x1f, 0xeb, 0x09, - 0xd9, 0xc7, 0xca, 0x6f, 0x63, 0x60, 0x7f, 0x7c, 0xb5, 0x7c, 0x5e, 0x4b, 0xab, 0xd5, 0x8b, 0x34, - 0x5b, 0x50, 0xda, 0x3e, 0x37, 0xa8, 0x26, 0xf5, 0xdb, 0x76, 0xc4, 0x4a, 0x48, 0x09, 0xcf, 0x04, - 0x0a, 0x17, 0x6c, 0x8d, 0x3c, 0x6e, 0x1e, 0x41, 0xfc, 0xef, 0x45, 0xbd, 0x72, 0x59, 0x5e, 0x10, - 0x61, 0x4e, 0xad, 0x0e, 0xe4, 0x76, 0x3c, 0xf7, 0x87, 0xef, 0x54, 0xdd, 0x61, 0xe9, 0x91, 0x0f, - 0x7e, 0x52, 0xd6, 0x9e, 0x02, 0xd7, 0xb6, 0xcc, 0xa4, 0x9e, 0x7d, 0xba, 0x5f, 0xb4, 0x40, 0xc9, - 0xe6, 0x95, 0x61, 0xae, 0xb9, 0x89, 0xba, 0x25, 0x1b, 0xb6, 0xde, 0x08, 0x7f, 0x88, 0xef, 0x7c, - 0x59, 0x4d, 0x73, 0xc7, 0xf5, 0x07, 0x94, 0x13, 0x7b, 0xfc, 0x9f, 0x75, 0x0d, 0x1a, 0x69, 0xf0, - 0x51, 0x36, 0x1e, 0x46, 0x76, 0xc8, 0x27, 0x4e, 0x65, 0x58, 0x66, 0x41, 0x5e, 0x9d, 0xfe, 0xf1, - 0x10, 0xd5, 0x3c, 0x5b, 0xea, 0xcd, 0x96, 0x37, 0x4d, 0x76, 0x88, 0x60, 0xfb, 0x3f, 0xb2, 0x7a, - 0x00, 0xb4, 0xe0, 0xb6, 0xb9, 0x76, 0x6e, 0x02, 0xb6, 0xf7, 0x8d, 0x8b, 0x3a, 0x5c, 0xde, 0x4e, - 0xb9, 0xa4, 0x05, 0xc6, 0x14, 0xa6, 0x3f, 0x6c, 0xbd, 0xfd, 0xee, 0x0b, 0xf5, 0x5c, 0x27, 0x56, - 0xc5, 0x48, 0x55, 0x78, 0x72, 0xdc, 0xca, 0x95, 0xb7, 0x02, 0xb2, 0xdc, 0x4e, 0xbd, 0xe2, 0x78, - 0x87, 0xcc, 0xb5, 0xb0, 0x7c, 0x22, 0x52, 0xc1, 0xb0, 0x5a, 0x09, 0x9d, 0xb6, 0xbe, 0xe7, 0x4b, - 0xa2, 0x0e, 0x20, 0x43, 0x28, 0x77, 0x88, 0x1f, 0xd6, 0xa4, 0xb9, 0x56, 0xd0, 0xd0, 0xa6, 0x0f, - 0xa3, 0xef, 0x2e, 0xb7, 0x1d, 0x40, 0x61, 0xf8, 0xb9, 0x17, 0x4c, -}; - - -#if 0 -static inline void test_mobile(void) -{ - SecCertificateRef aCert = NULL; - SecCertificateRef intermediateCert = NULL; - SecCertificateRef rootCert = NULL; - SecTrustResultType trustResult = kSecTrustResultUnspecified; - SecPolicyRef policy = NULL; - CFArrayRef certs = NULL; - SecTrustRef trust = NULL; - - isnt(aCert = SecCertificateCreateWithBytes(NULL, kDemoContentSigningCert, sizeof(kDemoContentSigningCert)), - NULL, "create aCert from kDemoContentSigningCert"); - - isnt(intermediateCert = SecCertificateCreateWithBytes(NULL, kMobileIntermediate, sizeof(kMobileIntermediate)), - NULL, "create intermediate from kMobileIntermediate"); - - SecCertificateRef refs[] = {aCert, intermediateCert}; - certs = CFArrayCreate(NULL, (const void **)refs, 2, NULL); - - isnt(policy = SecPolicyCreateMobileStoreSigner(), - NULL, "create mobile policy"); - - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), - "create trust for mobile store test cert"); - - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate mobile store trust"); - - is_status(trustResult, kSecTrustResultUnspecified, - "trust is kSecTrustResultRecoverableTrustFailure"); - - CFReleaseSafe(trust); - CFReleaseSafe(policy); - CFReleaseSafe(aCert); - - isnt(aCert = SecCertificateCreateWithBytes(NULL, kTestDemoContentSigningCert, sizeof(kTestDemoContentSigningCert)), - NULL, "create aCert from kDemoContentSigningCert"); - - isnt(policy = SecPolicyCreateTestMobileStoreSigner(), - NULL, "create Test mobile policy"); - - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), - "create trust for mobile store test cert"); - - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate test mobile store trust"); - - is_status(trustResult, kSecTrustResultUnspecified, - "trust is kSecTrustResultRecoverableTrustFailure"); - - CFReleaseSafe(trust); - CFReleaseSafe(policy); - CFReleaseSafe(aCert); - CFReleaseSafe(certs); - CFReleaseSafe(intermediateCert); - CFReleaseSafe(rootCert); - -} -#endif // 0 - -static void test_escrow_with_anchor_roots(CFArrayRef anchors) -{ - SecCertificateRef escrowLeafCert = NULL; - SecTrustResultType trustResult = kSecTrustResultUnspecified; - SecPolicyRef policy = NULL; - CFArrayRef certs = NULL; - SecTrustRef trust = NULL; - - isnt(escrowLeafCert = SecCertificateCreateWithBytes(NULL, kEscrowLeafCert, sizeof(kEscrowLeafCert)), - NULL, "could not create aCert from kEscrowLeafCert"); - - certs = CFArrayCreate(NULL, (const void **)&escrowLeafCert, 1, NULL); - - isnt(policy = SecPolicyCreateEscrowServiceSigner(), - NULL, "could not create Escrow policy for GM Escrow Leaf cert"); - - ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), - "coult not create trust for escrow service test GM Escrow Leaf cert"); - - SecTrustSetAnchorCertificates(trust, anchors); - - ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate escrow service trust for GM Escrow Leaf cert"); - - is_status(trustResult, kSecTrustResultUnspecified, - "trust is not kSecTrustResultUnspecified for GM Escrow Leaf cert"); - - CFReleaseSafe(trust); - CFReleaseSafe(policy); - CFReleaseSafe(certs); - CFReleaseSafe(escrowLeafCert); - -} - -static inline void test_escrow() -{ - CFArrayRef anchors = NULL; - isnt(anchors = SecCertificateCopyEscrowRoots(kSecCertificateProductionEscrowRoot), NULL, "unable to get production anchors"); - test_escrow_with_anchor_roots(anchors); - CFReleaseSafe(anchors); -} - -static void tests(void) -{ - test_escrow(); -} - -#endif /* defined(NO_SERVER) && NO_SERVER == 1 */ - -int si_71_mobile_store_policy(int argc, char *const *argv) -{ -#if defined(NO_SERVER) && NO_SERVER == 1 - - plan_tests(21); - - tests(); -#endif - return 0; -} diff --git a/sec/Security/SecBase.h b/sec/Security/SecBase.h deleted file mode 100644 index 05418207..00000000 --- a/sec/Security/SecBase.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2000-2009,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@ - */ - -/*! - @header SecBase - SecBase contains common declarations for the Security functions. -*/ - -#ifndef _SECURITY_SECBASE_H_ -#define _SECURITY_SECBASE_H_ - -#include -#include - -#if defined(__clang__) -#define SEC_DEPRECATED_ATTRIBUTE DEPRECATED_ATTRIBUTE -#else -#define SEC_DEPRECATED_ATTRIBUTE -#endif - -__BEGIN_DECLS - -/*! - @typedef SecCertificateRef - @abstract CFType representing a X.509 certificate. - See SecCertificate.h for details. -*/ -typedef struct __SecCertificate *SecCertificateRef; - -/*! - @typedef SecIdentityRef - @abstract CFType representing an identity, which contains - a SecKeyRef and an associated SecCertificateRef. See - SecIdentity.h for details. -*/ -typedef struct __SecIdentity *SecIdentityRef; - -/*! - @typedef SecKeyRef - @abstract CFType representing a cryptographic key. See - SecKey.h for details. -*/ -typedef struct __SecKey *SecKeyRef; - -/*! - @typedef SecPolicyRef - @abstract CFType representing a X.509 certificate trust policy. - See SecPolicy.h for details. -*/ -typedef struct __SecPolicy *SecPolicyRef; - -/*********************************************** - *** OSStatus values unique to Security APIs *** - ***********************************************/ - -/* - Note: the comments that appear after these errors are used to create - SecErrorMessages.strings. The comments must not be multi-line, and - should be in a form meaningful to an end user. If a different or - additional comment is needed, it can be put in the header doc format, - or on a line that does not start with errZZZ. -*/ - -enum -{ - errSecSuccess = 0, /* No error. */ - errSecUnimplemented = -4, /* Function or operation not implemented. */ - errSecIO = -36, /*I/O error (bummers)*/ - errSecOpWr = -49, /*file already open with with write permission*/ - errSecParam = -50, /* One or more parameters passed to a function where not valid. */ - errSecAllocate = -108, /* Failed to allocate memory. */ - errSecUserCanceled = -128, /* User canceled the operation. */ - errSecBadReq = -909, /* Bad parameter or invalid state for operation. */ - errSecInternalComponent = -2070, - errSecNotAvailable = -25291, /* No keychain is available. You may need to restart your computer. */ - errSecDuplicateItem = -25299, /* The specified item already exists in the keychain. */ - errSecItemNotFound = -25300, /* The specified item could not be found in the keychain. */ - errSecInteractionNotAllowed = -25308, /* User interaction is not allowed. */ - errSecDecode = -26275, /* Unable to decode the provided data. */ - errSecAuthFailed = -25293, /* The user name or passphrase you entered is not correct. */ -}; - -__END_DECLS - -#endif /* !_SECURITY_SECBASE_H_ */ diff --git a/sec/Security/SecBasePriv.h b/sec/Security/SecBasePriv.h deleted file mode 100644 index 5fc4a24c..00000000 --- a/sec/Security/SecBasePriv.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2008-2009 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 SecBasePriv - SecBasePriv contains private error codes from the Security framework. -*/ - -#ifndef _SECURITY_SECBASEPRIV_H_ -#define _SECURITY_SECBASEPRIV_H_ - -#include - -__BEGIN_DECLS - -/******************************************************* - *** Private OSStatus values unique to Security APIs *** - *******************************************************/ - -/* - Note: the comments that appear after these errors are used to create SecErrorMessages.strings. - The comments must not be multi-line, and should be in a form meaningful to an end user. If - a different or additional comment is needed, it can be put in the header doc format, or on a - line that does not start with errZZZ. -*/ - -enum -{ - errSecReadOnly = -25292, /* This keychain cannot be modified. */ - errSecNoSuchKeychain = -25294, /* The specified keychain could not be found. */ - errSecInvalidKeychain = -25295, /* The specified keychain is not a valid keychain file. */ - errSecDuplicateKeychain = -25296, /* A keychain with the same name already exists. */ - errSecDuplicateCallback = -25297, /* The specified callback function is already installed. */ - errSecInvalidCallback = -25298, /* The specified callback function is not valid. */ - errSecBufferTooSmall = -25301, /* There is not enough memory available to use the specified item. */ - errSecDataTooLarge = -25302, /* This item contains information which is too large or in a format that cannot be displayed. */ - errSecNoSuchAttr = errSecParam, // -25303, /* The specified attribute does not exist. */ - errSecInvalidItemRef = -25304, /* The specified item is no longer valid. It may have been deleted from the keychain. */ - errSecInvalidSearchRef = -25305, /* Unable to search the current keychain. */ - errSecNoSuchClass = errSecParam, // -25306, /* The specified item does not appear to be a valid keychain item. */ - errSecNoDefaultKeychain = -25307, /* A default keychain could not be found. */ - errSecReadOnlyAttr = -25309, /* The specified attribute could not be modified. */ - errSecWrongSecVersion = -25310, /* This keychain was created by a different version of the system software and cannot be opened. */ - errSecKeySizeNotAllowed = errSecParam, // -25311, /* This item specifies a key size which is too large. */ - errSecNoStorageModule = -25312, /* A required component (data storage module) could not be loaded. You may need to restart your computer. */ - errSecNoCertificateModule = -25313, /* A required component (certificate module) could not be loaded. You may need to restart your computer. */ - errSecNoPolicyModule = -25314, /* A required component (policy module) could not be loaded. You may need to restart your computer. */ - errSecInteractionRequired = -25315, /* User interaction is required, but is currently not allowed. */ - errSecDataNotAvailable = -25316, /* The contents of this item cannot be retrieved. */ - errSecDataNotModifiable = -25317, /* The contents of this item cannot be modified. */ - errSecCreateChainFailed = -25318, /* One or more certificates required to validate this certificate cannot be found. */ - errSecACLNotSimple = -25240, /* The specified access control list is not in standard (simple) form. */ - errSecInvalidTrustSetting = -25242, /* The specified trust setting is invalid. */ - errSecNoAccessForItem = -25243, /* The specified item has no access control. */ - errSecInvalidOwnerEdit = -25244, /* Invalid attempt to change the owner of this item. */ - errSecInvalidPrefsDomain = -25319, /* The specified preferences domain is not valid. */ - errSecTrustNotAvailable = -25245, /* No trust results are available. */ - errSecUnsupportedFormat = -25256, /* Import/Export format unsupported. */ - errSecUnknownFormat = -25257, /* Unknown format in import. */ - errSecKeyIsSensitive = -25258, /* Key material must be wrapped for export. */ - errSecMultiplePrivKeys = -25259, /* An attempt was made to import multiple private keys. */ - errSecPassphraseRequired = -25260, /* Passphrase is required for import/export. */ - errSecInvalidPasswordRef = -25261, /* The password reference was invalid. */ - errSecInvalidTrustSettings = -25262, /* The Trust Settings record was corrupted. */ - errSecNoTrustSettings = -25263, /* No Trust Settings were found. */ - errSecPkcs12VerifyFailure = -25264, /* MAC verification failed during PKCS12 import. */ - errSecInvalidCertificate = errSecDecode, // -26265, /* This certificate could not be decoded. */ - errSecNotSigner = -26267, /* A certificate was not signed by its proposed parent. */ - errSecPolicyDenied = -26270, /* The certificate chain was not trusted due to a policy not accepting it. */ - errSecInvalidKey = errSecDecode, // -26274, /* The provided key material was not valid. */ - errSecInternal = -26276, /* An internal error occured in the Security framework. */ - errSecUnsupportedAlgorithm = errSecUnimplemented, // -26268, /* An unsupported algorithm was encountered. */ - errSecUnsupportedOperation = errSecUnimplemented, // -26271, /* The operation you requested is not supported by this key. */ - errSecUnsupportedPadding = errSecParam, // -26273, /* The padding you requested is not supported. */ - errSecItemInvalidKey = errSecParam, // -34000, /* A string key in dictionary is not one of the supported keys. */ - errSecItemInvalidKeyType = errSecParam, // -34001, /* A key in a dictionary is neither a CFStringRef nor a CFNumberRef. */ - errSecItemInvalidValue = errSecParam, // -34002, /* A value in a dictionary is an invalid (or unsupported) CF type. */ - errSecItemClassMissing = errSecParam, // -34003, /* No kSecItemClass key was specified in a dictionary. */ - errSecItemMatchUnsupported = errSecParam, // -34004, /* The caller passed one or more kSecMatch keys to a function which does not support matches. */ - errSecUseItemListUnsupported = errSecParam, // -34005, /* The caller passed in a kSecUseItemList key to a function which does not support it. */ - errSecUseKeychainUnsupported = errSecParam, // -34006, /* The caller passed in a kSecUseKeychain key to a function which does not support it. */ - errSecUseKeychainListUnsupported = errSecParam, // -34007, /* The caller passed in a kSecUseKeychainList key to a function which does not support it. */ - errSecReturnDataUnsupported = errSecParam, // -34008, /* The caller passed in a kSecReturnData key to a function which does not support it. */ - errSecReturnAttributesUnsupported = errSecParam, // -34009, /* The caller passed in a kSecReturnAttributes key to a function which does not support it. */ - errSecReturnRefUnsupported = errSecParam, // -34010, /* The caller passed in a kSecReturnRef key to a function which does not support it. */ - errSecReturnPersitentRefUnsupported = errSecParam, // -34010, /* The caller passed in a kSecReturnPersistentRef key to a function which does not support it. */ - errSecValueRefUnsupported = errSecParam, // -34012, /* The caller passed in a kSecValueRef key to a function which does not support it. */ - errSecValuePersistentRefUnsupported = errSecParam, // -34013, /* The caller passed in a kSecValuePersistentRef key to a function which does not support it. */ - errSecReturnMissingPointer = errSecParam, // -34014, /* The caller passed asked for something to be returned but did not pass in a result pointer. */ - errSecMatchLimitUnsupported = errSecParam, // -34015, /* The caller passed in a kSecMatchLimit key to a call which does not support limits. */ - errSecItemIllegalQuery = errSecParam, // -34016, /* The caller passed in a query which contained too many keys. */ - errSecWaitForCallback = -34017, /* This operation is incomplete, until the callback is invoked (not an error). */ - errSecMissingEntitlement = -34018, /* Internal error when a required entitlement isn't present. */ - errSecUpgradePending = -34019, /* Error returned if keychain database needs a schema migration but the device is locked, clients should wait for a device unlock notification and retry the command. */ - - errSecMPSignatureInvalid = -25327, /* Signature invalid on MP message */ - errSecOTRTooOld = -25328, /* Message is too old to use */ - errSecOTRIDTooNew = -25329, /* Key ID is too new to use! Message from the future? */ - -}; - - -__END_DECLS - -#endif /* !_SECURITY_SECBASEPRIV_H_ */ diff --git a/sec/Security/SecCMS.c b/sec/Security/SecCMS.c deleted file mode 100644 index 7e790043..00000000 --- a/sec/Security/SecCMS.c +++ /dev/null @@ -1,696 +0,0 @@ -/* - * Copyright (c) 2008-2010 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@ - * - */ - -/* - * signed_data.c - * Security - * - * Created by Conrad Sauerwald on 2/11/08. - * - */ -#include - -#include -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) -#define ENABLE_CMS 0 -#else -#define ENABLE_CMS 1 -#endif - -#if ENABLE_CMS -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include "SecCMS.h" -#include - - -#include -#include -#include -#include -#include -#include - -CFTypeRef kSecCMSBulkEncryptionAlgorithm = CFSTR("kSecCMSBulkEncryptionAlgorithm"); -CFTypeRef kSecCMSSignDigest = CFSTR("kSecCMSSignDigest"); -CFTypeRef kSecCMSSignDetached = CFSTR("kSecCMSSignDetached"); -CFTypeRef kSecCMSSignHashAlgorithm = CFSTR("kSecCMSSignHashAlgorithm"); -CFTypeRef kSecCMSEncryptionAlgorithmDESCBC = CFSTR("kSecCMSEncryptionAlgorithmDESCBC"); -CFTypeRef kSecCMSEncryptionAlgorithmAESCBC = CFSTR("kSecCMSEncryptionAlgorithmAESCBC"); -CFTypeRef kSecCMSHashingAlgorithmMD5 = CFSTR("kSecCMSHashingAlgorithmMD5"); -CFTypeRef kSecCMSCertChainMode = CFSTR("kSecCMSCertChainMode"); -CFTypeRef kSecCMSCertChainModeNone = CFSTR("0"); -CFTypeRef kSecCMSAdditionalCerts = CFSTR("kSecCMSAdditionalCerts"); -CFTypeRef kSecCMSSignedAttributes = CFSTR("kSecCMSSignedAttributes"); -CFTypeRef kSecCMSSignDate = CFSTR("kSecCMSSignDate"); -CFTypeRef kSecCMSAllCerts = CFSTR("kSecCMSAllCerts"); - -OSStatus SecCMSCreateEnvelopedData(CFTypeRef recipient_or_cfarray_thereof, - CFDictionaryRef params, CFDataRef data, CFMutableDataRef enveloped_data) -{ - SecCmsMessageRef cmsg = NULL; - SecCmsContentInfoRef cinfo; - SecCmsEnvelopedDataRef envd = NULL; - SECOidTag algorithmTag = SEC_OID_DES_EDE3_CBC; - int keySize = 192; - OSStatus status = errSecParam; - - if (params) { - CFStringRef algorithm_name = CFDictionaryGetValue(params, kSecCMSBulkEncryptionAlgorithm); - if (algorithm_name) { - if (CFEqual(kSecCMSEncryptionAlgorithmDESCBC, algorithm_name)) { - algorithmTag = SEC_OID_DES_CBC; - keySize = 64; - } else if (CFEqual(kSecCMSEncryptionAlgorithmAESCBC, algorithm_name)) { - algorithmTag = SEC_OID_AES_128_CBC; - keySize = 128; - } - } - } - - require(cmsg = SecCmsMessageCreate(), out); - require(envd = SecCmsEnvelopedDataCreate(cmsg, algorithmTag, keySize), out); - require(cinfo = SecCmsMessageGetContentInfo(cmsg), out); - require_noerr(SecCmsContentInfoSetContentEnvelopedData(cinfo, envd), out); - require(cinfo = SecCmsEnvelopedDataGetContentInfo(envd), out); - require_noerr(SecCmsContentInfoSetContentData(cinfo, NULL, false), out); - // == wrapper of: require(SECSuccess == SecCmsContentInfoSetContent(cinfo, SEC_OID_PKCS7_DATA, NULL), out); - - if (CFGetTypeID(recipient_or_cfarray_thereof) == CFArrayGetTypeID()) { - CFIndex dex, numCerts = CFArrayGetCount(recipient_or_cfarray_thereof); - for(dex=0; dexrecipientInfos; - while (!used_recipient && *rinfo) { - used_recipient = (*rinfo)->cert; - rinfo++; - } - require_quiet(2 == SecCmsMessageContentLevelCount(cmsg), out); - require_quiet(cinfo = SecCmsMessageContentLevel(cmsg, 1), out); - require_quiet(SecCmsContentInfoGetContentTypeTag(cinfo) == SEC_OID_PKCS7_DATA, out); - const SecAsn1Item *content = SecCmsMessageGetContent(cmsg); - if (content) - CFDataAppendBytes(data, content->Data, content->Length); - if (recipient) { - CFRetainSafe(used_recipient); - *recipient = used_recipient; - } - status = errSecSuccess; -out: - if (cmsg) SecCmsMessageDestroy(cmsg); - return status; -} - -static SecCmsAttribute * -make_attr(PLArenaPool *poolp, SecAsn1Item *type, SecAsn1Item *value, bool encoded) -{ - SecAsn1Item * copiedvalue; - SecCmsAttribute *attr = (SecCmsAttribute *)PORT_ArenaZAlloc(poolp, sizeof(SecCmsAttribute)); - if (attr == NULL) - goto loser; - - if (SECITEM_CopyItem(poolp, &(attr->type), type) != SECSuccess) - goto loser; - - if (value != NULL) { - if ((copiedvalue = SECITEM_AllocItem(poolp, NULL, value->Length)) == NULL) - goto loser; - - if (SECITEM_CopyItem(poolp, copiedvalue, value) != SECSuccess) - goto loser; - - SecCmsArrayAdd(poolp, (void ***)&(attr->values), (void *)copiedvalue); - } - - attr->encoded = encoded; - -loser: - return attr; -} - -static void -signerinfo_add_auth_attr(SecCmsSignerInfoRef signerinfo, /*SECOidTag oidtag*/ - SecAsn1Item *oid, SecAsn1Item *value, bool encoded) -{ - PLArenaPool *poolp = signerinfo->signedData->contentInfo.cmsg->poolp; - PORT_Assert (poolp != NULL); - void *mark = PORT_ArenaMark (poolp); - - SecCmsAttribute *attr = make_attr(poolp, oid, value, encoded); - if (!attr || SecCmsAttributeArrayAddAttr(poolp, &(signerinfo->authAttr), attr) != SECSuccess) - goto loser; - - PORT_ArenaUnmark (poolp, mark); - return; - -loser: - PORT_Assert (mark != NULL); - PORT_ArenaRelease (poolp, mark); - return; -} - -static void sign_all_attributes(const void *key, const void *value, void *context) -{ - SecAsn1Item oid = { CFDataGetLength(key), (uint8_t*)CFDataGetBytePtr(key) }, - oid_value = { CFDataGetLength(value), (uint8_t*)CFDataGetBytePtr(value) }; - - signerinfo_add_auth_attr((SecCmsSignerInfoRef)context, &oid, &oid_value, true); -} - -#if 0 -static void enveloped_data_add_unprotected_attr(SecCmsEnvelopedDataRef envd, - SecAsn1Item *oid, SecAsn1Item *value, bool encoded) -{ - PLArenaPool *poolp = envd->contentInfo.cmsg->poolp; - PORT_Assert (poolp != NULL); - void *mark = PORT_ArenaMark (poolp); - SecCmsAttribute *attr = make_attr(poolp, oid, value, encoded); - - if (!attr || SecCmsAttributeArrayAddAttr( - poolp, - &(envd->unprotectedAttr), attr) != SECSuccess) - goto loser; - - PORT_ArenaUnmark (poolp, mark); - return; - -loser: - PORT_Assert (mark != NULL); - PORT_ArenaRelease (poolp, mark); - return; - -} -#endif - -static OSStatus SecCMSSignDataOrDigestAndAttributes(SecIdentityRef identity, - CFDataRef data, bool detached, bool data_is_digest, SECOidTag sign_algorithm, - CFMutableDataRef signed_data, CFDictionaryRef signed_attributes, SecCmsCertChainMode chainMode, CFArrayRef additional_certs) -{ - SecCmsMessageRef cmsg = NULL; - SecCmsContentInfoRef cinfo; - SecCmsSignedDataRef sigd = NULL; - SecCmsSignerInfoRef signerinfo; - OSStatus status = errSecParam; - - require(!data_is_digest || detached /* if digest, must be detached */, out); - - require(cmsg = SecCmsMessageCreate(), out); - require(sigd = SecCmsSignedDataCreate(cmsg), out); - require(cinfo = SecCmsMessageGetContentInfo(cmsg), out); - require_noerr(SecCmsContentInfoSetContentSignedData(cinfo, sigd), out); - require(cinfo = SecCmsSignedDataGetContentInfo(sigd), out); - require_noerr(SecCmsContentInfoSetContentData(cinfo, NULL, detached), out); - require(signerinfo = SecCmsSignerInfoCreate(sigd, identity, sign_algorithm), out); - if (additional_certs) - require_noerr(SecCmsSignedDataAddCertList(sigd, additional_certs), out); - require_noerr(SecCmsSignerInfoIncludeCerts(signerinfo, chainMode, certUsageAnyCA), out); - require_noerr(SecCmsSignerInfoAddSigningTime(signerinfo, CFAbsoluteTimeGetCurrent()), out); - - if (signed_attributes) - CFDictionaryApplyFunction(signed_attributes, sign_all_attributes, signerinfo); - - SecAsn1Item input = {}; - if (data) { - input.Length = CFDataGetLength(data); - input.Data = (uint8_t*)CFDataGetBytePtr(data); - } - if (data_is_digest) { - require_noerr(SecCmsSignedDataSetDigestValue(sigd, sign_algorithm, &input), out); - require_noerr(SecCmsMessageEncode(cmsg, NULL, signed_data), out); - } - else - require_noerr(SecCmsMessageEncode(cmsg, (data && input.Length) ? &input : NULL, signed_data), out); - - status = errSecSuccess; -out: - if (cmsg) SecCmsMessageDestroy(cmsg); - return status; -} - -OSStatus SecCMSSignDataAndAttributes(SecIdentityRef identity, CFDataRef data, bool detached, - CFMutableDataRef signed_data, CFDictionaryRef signed_attributes) -{ - return SecCMSSignDataOrDigestAndAttributes(identity, data, detached, false, SEC_OID_SHA1, - signed_data, signed_attributes, SecCmsCMCertChain, NULL); -} - -OSStatus SecCMSSignDigestAndAttributes(SecIdentityRef identity, CFDataRef digest, - CFMutableDataRef signed_data, CFDictionaryRef signed_attributes) -{ - return SecCMSSignDataOrDigestAndAttributes(identity, digest, true, true, SEC_OID_SHA1, - signed_data, signed_attributes, SecCmsCMCertChain, NULL); -} - - -OSStatus SecCMSCreateSignedData(SecIdentityRef identity, CFDataRef data, - CFDictionaryRef parameters, CFDictionaryRef signed_attributes, - CFMutableDataRef signed_data) -{ - bool is_digest = false, is_detached = false; - CFStringRef algorithm_name = NULL; - SecCmsCertChainMode chain_mode = SecCmsCMCertChain; - CFArrayRef additional_certs = NULL; - - if (parameters) { - is_digest = CFDictionaryGetValueIfPresent(parameters, - kSecCMSSignDigest, NULL); - is_detached = CFDictionaryGetValueIfPresent(parameters, - kSecCMSSignDetached, NULL); - algorithm_name = CFDictionaryGetValue(parameters, - kSecCMSSignHashAlgorithm); - - CFTypeRef chain_mode_param = CFDictionaryGetValue(parameters, kSecCMSCertChainMode); - if (chain_mode_param && (CFGetTypeID(chain_mode_param) == CFStringGetTypeID())) - chain_mode = CFStringGetIntValue(chain_mode_param); - - CFTypeRef additional_certs_param = CFDictionaryGetValue(parameters, kSecCMSAdditionalCerts); - if (additional_certs_param && (CFGetTypeID(additional_certs_param) == CFArrayGetTypeID())) - additional_certs = (CFArrayRef)additional_certs_param; - } - - SECOidTag algorithm = SEC_OID_SHA1; - if (algorithm_name) { - if (CFEqual(kSecCMSHashingAlgorithmMD5, algorithm_name)) { - algorithm = SEC_OID_MD5; - } else { - algorithm = SEC_OID_UNKNOWN; - } - - } - - return SecCMSSignDataOrDigestAndAttributes(identity, data, - is_detached, is_digest, algorithm, - signed_data, signed_attributes, chain_mode, additional_certs); -} - - -static CFMutableArrayRef copy_signed_attribute_values(SecCmsAttribute *attr) -{ - CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - SecAsn1Item **item = attr->values; - if (item) while (*item) { - CFDataRef asn1data = CFDataCreate(kCFAllocatorDefault, (*item)->Data, (*item)->Length); - if (asn1data) { - CFArrayAppendValue(array, asn1data); - CFRelease(asn1data); - } - item++; - } - return array; -} - -static OSStatus SecCMSVerifySignedData_internal(CFDataRef message, CFDataRef detached_contents, - CFTypeRef policy, SecTrustRef *trustref, CFArrayRef additional_certs, - CFDataRef *attached_contents, CFDictionaryRef *signed_attributes) -{ - SecCmsMessageRef cmsg = NULL; - SecCmsContentInfoRef cinfo; - SecCmsSignedDataRef sigd = NULL; - OSStatus status = errSecParam; - - SecAsn1Item encoded_message = { CFDataGetLength(message), (uint8_t*)CFDataGetBytePtr(message) }; - require_noerr_action_quiet(SecCmsMessageDecode(&encoded_message, NULL, NULL, NULL, NULL, NULL, NULL, &cmsg), - out, status = errSecDecode); - /* expected to be a signed data message at the top level */ - require_quiet(cinfo = SecCmsMessageContentLevel(cmsg, 0), out); - require_quiet(SecCmsContentInfoGetContentTypeTag(cinfo) == SEC_OID_PKCS7_SIGNED_DATA, out); - require_quiet(sigd = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(cinfo), out); - - if (detached_contents) - { - require_quiet(!SecCmsSignedDataHasDigests(sigd), out); - SECAlgorithmID **digestalgs = SecCmsSignedDataGetDigestAlgs(sigd); - SecCmsDigestContextRef digcx = SecCmsDigestContextStartMultiple(digestalgs); - SecCmsDigestContextUpdate(digcx, CFDataGetBytePtr(detached_contents), CFDataGetLength(detached_contents)); - SecCmsSignedDataSetDigestContext(sigd, digcx); - SecCmsDigestContextDestroy(digcx); - } - - if (additional_certs) - require_noerr_quiet(SecCmsSignedDataAddCertList(sigd, additional_certs), out); - - if (policy) { /* if no policy is given skip verification */ - /* find out about signers */ - int nsigners = SecCmsSignedDataSignerInfoCount(sigd); - require_quiet(nsigners == 1, out); - require_noerr_action_quiet(SecCmsSignedDataVerifySignerInfo(sigd, 0, NULL, policy, trustref), - out, status = errSecAuthFailed); - } - - #if 0 - if (nsigners > 1) - trustrefs = CFArrayCreateMutable(kCFAllocatorDefault, nsigners, &kCFTypeArrayCallBacks); - - int j; - for (j = 0; j < nsigners; j++) - { - SecTrustRef trustRef; - require_noerr_action_quiet(SecCmsSignedDataVerifySignerInfo(sigd, j, NULL, policy, &trustRef), - out, status = errSecAuthFailed); - if ((j == 0) && (nsigners == 1)) - *trustref_or_cfarray_thereof = trustRef; - else { - CFArrayAppendValue(trustrefs, trustRef); - CFRelease(trustRef); - } - } - *trustref_or_cfarray_thereof = trustrefs; - trustrefs = NULL; -#endif - - status = errSecSuccess; - - if (attached_contents) { - const SecAsn1Item *content = SecCmsMessageGetContent(cmsg); - if (content) - *attached_contents = CFDataCreate(kCFAllocatorDefault, content->Data, content->Length); - else - *attached_contents = NULL; - } - - if (signed_attributes) { - CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, - 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - require_quiet(attrs, out); - SecCmsAttribute **signed_attrs = sigd->signerInfos[0]->authAttr; - if (signed_attrs) while (*signed_attrs) { - CFDataRef type = CFDataCreate(kCFAllocatorDefault, (*signed_attrs)->type.Data, (*signed_attrs)->type.Length); - if (type) { - CFMutableArrayRef attr = copy_signed_attribute_values(*signed_attrs); - if (attr) { - CFMutableArrayRef existing_attrs = (CFMutableArrayRef)CFDictionaryGetValue(attrs, type); - if (existing_attrs) { - CFIndex count = CFArrayGetCount(attr); - if (count) - CFArrayAppendArray(existing_attrs, attr, CFRangeMake(0, count)); - } else - CFDictionarySetValue(attrs, type, attr); - CFRelease(attr); - } - CFRelease(type); - } - signed_attrs++; - } - CFMutableArrayRef certs = NULL; - - SecAsn1Item **cert_datas = SecCmsSignedDataGetCertificateList(sigd); - certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - SecAsn1Item *cert_data; - if (cert_datas) while ((cert_data = *cert_datas) != NULL) { - SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, cert_data->Data, cert_data->Length); - if (cert) { - CFArrayAppendValue(certs, cert); - CFRelease(cert); - } - cert_datas++; - } - - CFDictionaryAddValue(attrs, kSecCMSAllCerts, certs); - - /* Add "cooked" values separately */ - CFAbsoluteTime signing_time; - if (errSecSuccess == SecCmsSignerInfoGetSigningTime(sigd->signerInfos[0], &signing_time)) { - CFDateRef signing_date = CFDateCreate(kCFAllocatorDefault, signing_time); - if (signing_date){ - CFDictionarySetValue(attrs, kSecCMSSignDate, signing_date); - CFReleaseSafe(signing_date); - } - } - - *signed_attributes = attrs; - } - - -out: - if (cmsg) SecCmsMessageDestroy(cmsg); - return status; -} - -OSStatus SecCMSVerifyCopyDataAndAttributes(CFDataRef message, CFDataRef detached_contents, - CFTypeRef policy, SecTrustRef *trustref, - CFDataRef *attached_contents, CFDictionaryRef *signed_attributes) -{ - OSStatus status = SecCMSVerifySignedData_internal(message, detached_contents, policy, trustref, NULL, attached_contents, signed_attributes); - - return status; -} - -OSStatus SecCMSVerifySignedData(CFDataRef message, CFDataRef detached_contents, - CFTypeRef policy, SecTrustRef *trustref, CFArrayRef additional_certificates, - CFDataRef *attached_contents, CFDictionaryRef *message_attributes) -{ - CFDictionaryRef signed_attributes = NULL; - OSStatus status = SecCMSVerifySignedData_internal(message, detached_contents, policy, trustref, additional_certificates, attached_contents, &signed_attributes); - if (!status && signed_attributes && message_attributes) { - *message_attributes = CFDictionaryCreate(kCFAllocatorDefault, &kSecCMSSignedAttributes, (const void **)&signed_attributes, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - } - CFReleaseSafe(signed_attributes); - - return status; -} - -OSStatus SecCMSVerify(CFDataRef message, CFDataRef detached_contents, - CFTypeRef policy, SecTrustRef *trustref, - CFDataRef *attached_contents) { - return SecCMSVerifySignedData_internal(message, detached_contents, policy, trustref, NULL, attached_contents, NULL); -} - -CFArrayRef SecCMSCertificatesOnlyMessageCopyCertificates(CFDataRef message) { - SecCmsMessageRef cmsg = NULL; - SecCmsContentInfoRef cinfo; - SecCmsSignedDataRef sigd = NULL; - CFMutableArrayRef certs = NULL; - - SecAsn1Item encoded_message = { CFDataGetLength(message), (uint8_t*)CFDataGetBytePtr(message) }; - require_noerr_quiet(SecCmsMessageDecode(&encoded_message, NULL, NULL, NULL, NULL, NULL, NULL, &cmsg), out); - /* expected to be a signed data message at the top level */ - require(cinfo = SecCmsMessageContentLevel(cmsg, 0), out); - require(SecCmsContentInfoGetContentTypeTag(cinfo) == SEC_OID_PKCS7_SIGNED_DATA, out); - require(sigd = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(cinfo), out); - - /* find out about signers */ - int nsigners = SecCmsSignedDataSignerInfoCount(sigd); - require(nsigners == 0, out); - - SecAsn1Item **cert_datas = SecCmsSignedDataGetCertificateList(sigd); - certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - SecAsn1Item *cert_data; - if (cert_datas) while ((cert_data = *cert_datas) != NULL) { - SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, cert_data->Data, cert_data->Length); - if (cert) { - CFArrayAppendValue(certs, cert); - CFRelease(cert); - } - cert_datas++; - } - -out: - if (cmsg) - SecCmsMessageDestroy(cmsg); - - return certs; -} - - -extern const SecAsn1Template SecCmsMessageTemplate[]; - -CFDataRef SecCMSCreateCertificatesOnlyMessage(CFTypeRef cert_or_array_thereof) { - OSStatus status = errSecParam; - SecCmsMessageRef cmsg = NULL; - SecCmsContentInfoRef cinfo; - SecCmsSignedDataRef sigd = NULL; - CFMutableDataRef cert_only_signed_data = NULL; - CFArrayRef cert_array = NULL; - CFIndex cert_array_count = 0; - SecCertificateRef cert = NULL; - - require(cert_or_array_thereof, out); - - require(cmsg = SecCmsMessageCreate(), out); - require(sigd = SecCmsSignedDataCreate(cmsg), out); - require_noerr(SecCmsContentInfoSetContentData(&(sigd->contentInfo), NULL, PR_TRUE), out); - require(cinfo = SecCmsMessageGetContentInfo(cmsg), out); - require_noerr(SecCmsContentInfoSetContentSignedData(cinfo, sigd), out); - long version = SEC_CMS_SIGNED_DATA_VERSION_BASIC; - require(SEC_ASN1EncodeInteger(cmsg->poolp, &(sigd->version), version), out); - - if (CFGetTypeID(cert_or_array_thereof) == SecCertificateGetTypeID()) { - cert_array = CFArrayCreate(kCFAllocatorDefault, &cert_or_array_thereof, 1, &kCFTypeArrayCallBacks); - } else if (CFGetTypeID(cert_or_array_thereof) == CFArrayGetTypeID()) { - cert_array = CFArrayCreateCopy(kCFAllocatorDefault, (CFArrayRef)cert_or_array_thereof); - } - - require(cert_array, out); - cert_array_count = CFArrayGetCount(cert_array); - require(cert_array_count > 0, out); - - sigd->rawCerts = (SecAsn1Item * *)PORT_ArenaAlloc(cmsg->poolp, (cert_array_count + 1) * sizeof(SecAsn1Item *)); - require(sigd->rawCerts, out); - CFIndex ix; - for (ix = 0; ix < cert_array_count; ix++) { - cert = (SecCertificateRef)CFArrayGetValueAtIndex(cert_array, ix); - require(cert, out); - - sigd->rawCerts[ix] = PORT_ArenaZAlloc(cmsg->poolp, sizeof(SecAsn1Item)); - SecAsn1Item cert_data = { SecCertificateGetLength(cert), - (uint8_t *)SecCertificateGetBytePtr(cert) }; - *(sigd->rawCerts[ix]) = cert_data; - } - sigd->rawCerts[ix] = NULL; - - /* this is a SET OF, so we need to sort them guys - we have the DER already, though */ - if (cert_array_count > 1) - SecCmsArraySort((void **)sigd->rawCerts, SecCmsUtilDERCompare, NULL, NULL); - - cert_only_signed_data = CFDataCreateMutable(kCFAllocatorDefault, 0); - SecAsn1Item cert_only_signed_data_item = {}; - require_quiet(SEC_ASN1EncodeItem(cmsg->poolp, &cert_only_signed_data_item, - cmsg, SecCmsMessageTemplate), out); - CFDataAppendBytes(cert_only_signed_data, cert_only_signed_data_item.Data, - cert_only_signed_data_item.Length); - - status = errSecSuccess; -out: - CFReleaseSafe(cert_array); - if (status) CFReleaseSafe(cert_only_signed_data); - if (cmsg) SecCmsMessageDestroy(cmsg); - return cert_only_signed_data; -} - -CFDataRef SecCMSCreateCertificatesOnlyMessageIAP(SecCertificateRef cert) -{ - static const uint8_t header[] = { - 0x30, 0x82, 0x03, 0x6d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, - 0x82, 0x03, 0x5e, 0x30, 0x82, 0x03, 0x5a, 0x02, - 0x01, 0x01, 0x31, 0x00, 0x30, 0x0b, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, - 0x01, 0xa0, 0x82, 0x03, 0x40 - }; - - static const uint8_t trailer[] = { - 0xa1, 0x00, 0x31, 0x00 - }; - - CFMutableDataRef message = NULL; - CFDataRef certdata; - const uint8_t *certbytes; - CFIndex certlen; - uint8_t *messagebytes; - uint16_t messagelen; - - certdata = SecCertificateCopyData(cert); - require(certdata, out); - - certbytes = CFDataGetBytePtr(certdata); - certlen = CFDataGetLength(certdata); - require(certlen > UINT8_MAX, out); - require(certlen < UINT16_MAX, out); - - message = CFDataCreateMutable(kCFAllocatorDefault, 0); - require(message, out); - - CFDataAppendBytes(message, header, sizeof(header)); - CFDataAppendBytes(message, certbytes, certlen); - CFDataAppendBytes(message, trailer, sizeof(trailer)); - - messagebytes = CFDataGetMutableBytePtr(message); - messagelen = CFDataGetLength(message); - - messagelen -= 4; - messagebytes[2] = messagelen >> 8; - messagebytes[3] = messagelen & 0xFF; - - messagelen -= 15; - messagebytes[17] = messagelen >> 8; - messagebytes[18] = messagelen & 0xFF; - - messagelen -= 4; - messagebytes[21] = messagelen >> 8; - messagebytes[22] = messagelen & 0xFF; - - messagelen -= 26; - messagebytes[43] = messagelen >> 8; - messagebytes[44] = messagelen & 0xFF; - -out: - CFReleaseSafe(certdata); - return message; -} - -#endif /* ENABLE_CMS */ - diff --git a/sec/Security/SecCMS.h b/sec/Security/SecCMS.h deleted file mode 100644 index 8b0586cd..00000000 --- a/sec/Security/SecCMS.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (c) 2008-2010 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 SecCMS -*/ - -#include -#include -#include -#include - -#ifndef _SECURITY_SECCMS_H_ -#define _SECURITY_SECCMS_H_ - -__BEGIN_DECLS - -extern const void * kSecCMSBulkEncryptionAlgorithm; -extern const void * kSecCMSSignDigest; -extern const void * kSecCMSSignDetached; -extern const void * kSecCMSSignHashAlgorithm; -extern const void * kSecCMSCertChainMode; -extern const void * kSecCMSAdditionalCerts; -extern const void * kSecCMSSignedAttributes; -extern const void * kSecCMSSignDate; -extern const void * kSecCMSAllCerts; - -extern const void * kSecCMSEncryptionAlgorithmDESCBC; -extern const void * kSecCMSEncryptionAlgorithmAESCBC; -extern const void * kSecCMSHashingAlgorithmMD5; -extern const void * kSecCMSCertChainModeNone; - -/*! - @function SecCMSVerifyCopyDataAndAttributes - @abstract verify a signed data cms blob. - @param message the cms message to be parsed - @param detached_contents to pass detached contents (optional) - @param policy specifies policy or array thereof should be used (optional). - if none is passed the blob will **not** be verified and only - the attached contents will be returned. - @param trustref (output/optional) if specified, the trust chain built during - verification will not be evaluated but returned to the caller to do so. - @param attached_contents (output/optional) return a copy of the attached - contents. - @param signed_attributes (output/optional) return a copy of the signed - attributes as a CFDictionary from oids (CFData) to values - (CFArray of CFData). - @result A result code. See "Security Error Codes" (SecBase.h). - errSecDecode not a CMS message we can parse, - errSecAuthFailed bad signature, or untrusted signer if caller doesn't - ask for trustref, - errSecParam garbage in, garbage out. -*/ -OSStatus SecCMSVerifyCopyDataAndAttributes(CFDataRef message, CFDataRef detached_contents, - CFTypeRef policy, SecTrustRef *trustref, - CFDataRef *attached_contents, CFDictionaryRef *signed_attributes); - -/*! - @function SecCMSVerify - @abstract same as SecCMSVerifyCopyDataAndAttributes, for binary compatibility. -*/ -OSStatus SecCMSVerify(CFDataRef message, CFDataRef detached_contents, - CFTypeRef policy, SecTrustRef *trustref, CFDataRef *attached_contents); - - -/* Return an array of certificates contained in message, if message is of the - type SignedData and has no signers, return NULL otherwise. Not that if - the message is properly formed but has no certificates an empty array will - be returned. */ -CFArrayRef SecCMSCertificatesOnlyMessageCopyCertificates(CFDataRef message); - -/* Create a degenerate PKCS#7 containing a cert or a CFArray of certs. */ -CFDataRef SecCMSCreateCertificatesOnlyMessage(CFTypeRef cert_or_array_thereof); -CFDataRef SecCMSCreateCertificatesOnlyMessageIAP(SecCertificateRef cert); - -/*! - @function SecCMSSignDataAndAttributes - @abstract create a signed data cms blob. - @param identity signer - @param data message to be signed - @param detached sign detached or not - @param signed_data (output) return signed message. - @param signed_attributes (input/optional) signed attributes to insert - as a CFDictionary from oids (CFData) to value (CFData). - @result A result code. See "Security Error Codes" (SecBase.h). - errSecParam garbage in, garbage out. -*/ -OSStatus SecCMSSignDataAndAttributes(SecIdentityRef identity, CFDataRef data, - bool detached, CFMutableDataRef signed_data, CFDictionaryRef signed_attributes); - -/*! - @function SecCMSSignDigestAndAttributes - @abstract create a detached signed data cms blob for a SHA-1 hash. - @param identity signer - @param digest SHA-1 digest of message to be signed - @param signed_data (output) return signed message. - @param signed_attributes (input/optional) signed attributes to insert - as a CFDictionary from oids (CFData) to value (CFData). - @result A result code. See "Security Error Codes" (SecBase.h). - errSecParam garbage in, garbage out. -*/ -OSStatus SecCMSSignDigestAndAttributes(SecIdentityRef identity, CFDataRef digest, - CFMutableDataRef signed_data, CFDictionaryRef signed_attributes); - -/*! - @function SecCMSCreateSignedData - @abstract create a signed data cms blob. - @param identity signer - @param data SHA-1 digest or message to be signed - @param parameters (input/optional) specify algorithm, detached, digest - @param signed_attributes (input/optional) signed attributes to insert - as a CFDictionary from oids (CFData) to value (CFData). - @param signed_data (output) return signed message. - @result A result code. See "Security Error Codes" (SecBase.h). - errSecParam garbage in, garbage out. -*/ -OSStatus SecCMSCreateSignedData(SecIdentityRef identity, CFDataRef data, - CFDictionaryRef parameters, CFDictionaryRef signed_attributes, - CFMutableDataRef signed_data); - -/*! - @function SecCMSCreateEnvelopedData - @abstract create a enveloped cms blob for recipients - @param recipients SecCertificateRef for each recipient - @param params CFDictionaryRef with encryption parameters - @param data Data to be encrypted - @param enveloped_data (output) return enveloped message. - @result A result code. See "Security Error Codes" (SecBase.h). - errSecParam garbage in, garbage out. -*/ -OSStatus SecCMSCreateEnvelopedData(CFTypeRef recipient_or_cfarray_thereof, - CFDictionaryRef params, CFDataRef data, CFMutableDataRef enveloped_data); - - -/*! - @function SecCMSDecryptEnvelopedData - @abstract open an enveloped cms blob. expects recipients identity in keychain. - @param message Eveloped message - @param data (output) return decrypted message. - @param recipient (output/optional) return addressed recipient - @result A result code. See "Security Error Codes" (SecBase.h). - errSecParam garbage in, garbage out. -*/ -OSStatus SecCMSDecryptEnvelopedData(CFDataRef message, - CFMutableDataRef data, SecCertificateRef *recipient); - -OSStatus SecCMSVerifySignedData(CFDataRef message, CFDataRef detached_contents, - CFTypeRef policy, SecTrustRef *trustref, CFArrayRef additional_certificates, - CFDataRef *attached_contents, CFDictionaryRef *message_attributes); - -__END_DECLS - -#endif /* !_SECURITY_SECCMS_H_ */ diff --git a/sec/Security/SecCertificate.h b/sec/Security/SecCertificate.h deleted file mode 100644 index 74a683f2..00000000 --- a/sec/Security/SecCertificate.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2006-2009 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 SecCertificate - The functions provided in SecCertificate.h implement and manage a - particular type of keychain item that represents a X.509 public key - certificate. You can store a certificate in a keychain, but a - certificate can also be a transient object. - - You can use a certificate as a keychain item in most functions. -*/ - -#ifndef _SECURITY_SECCERTIFICATE_H_ -#define _SECURITY_SECCERTIFICATE_H_ - -#include -#include - -__BEGIN_DECLS - -/*! - @function SecCertificateGetTypeID - @abstract Returns the type identifier of SecCertificate instances. - @result The CFTypeID of SecCertificate instances. -*/ -CFTypeID SecCertificateGetTypeID(void) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -/*! - @function SecCertificateCreateWithData - @abstract Create a certificate given it's DER representation as a CFData. - @param allocator CFAllocator to allocate the certificate with. - @param certificate DER encoded X.509 certificate. - @result Return NULL if the passed-in data is not a valid DER-encoded - X.509 certificate, return a SecCertificateRef otherwise. -*/ -SecCertificateRef SecCertificateCreateWithData(CFAllocatorRef allocator, - CFDataRef data) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @function SecCertificateCopyData - @abstract Return the DER representation of an X.509 certificate. - @param certificate SecCertificate object created with - SecCertificateCreateWithData(). - @result DER encoded X.509 certificate. -*/ -CFDataRef SecCertificateCopyData(SecCertificateRef certificate) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @function SecCertificateCopySubjectSummary - @abstract Return a simple string which hopefully represents a human - understandable summary. - @param certificate SecCertificate object created with - SecCertificateCreateWithData(). - @discussion All the data in this string comes from the certificate itself - and thus it's in whatever language the certificate itself is in. - @result A CFStringRef which the caller should CFRelease() once it's no - longer needed. -*/ -CFStringRef SecCertificateCopySubjectSummary(SecCertificateRef certificate) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -__END_DECLS - -#endif /* !_SECURITY_SECCERTIFICATE_H_ */ diff --git a/sec/Security/SecCertificatePriv.h b/sec/Security/SecCertificatePriv.h deleted file mode 100644 index 77674ea7..00000000 --- a/sec/Security/SecCertificatePriv.h +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 2006-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * 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 SecCertificatePriv - The functions provided in SecCertificatePriv.h implement and manage a particular - type of keychain item that represents a certificate. You can store a - certificate in a keychain, but a certificate can also be a transient - object. - - You can use a certificate as a keychain item in most functions. - Certificates are able to compute their parent certificates, and much more. -*/ - -#ifndef _SECURITY_SECCERTIFICATEPRIV_H_ -#define _SECURITY_SECCERTIFICATEPRIV_H_ - -#include -#include -#include -#include -#include -#include -#include -#include - -__BEGIN_DECLS - -typedef uint32_t SecKeyUsage; -enum { - kSecKeyUsageUnspecified = 0, - kSecKeyUsageDigitalSignature = 1 << 0, - kSecKeyUsageNonRepudiation = 1 << 1, - kSecKeyUsageContentCommitment= 1 << 1, - kSecKeyUsageKeyEncipherment = 1 << 2, - kSecKeyUsageDataEncipherment = 1 << 3, - kSecKeyUsageKeyAgreement = 1 << 4, - kSecKeyUsageKeyCertSign = 1 << 5, - kSecKeyUsageCRLSign = 1 << 6, - kSecKeyUsageEncipherOnly = 1 << 7, - kSecKeyUsageDecipherOnly = 1 << 8, - kSecKeyUsageCritical = 1 << 31, - kSecKeyUsageAll = 0x7FFFFFFF -}; - -typedef uint32_t SecCertificateEscrowRootType; -enum { - kSecCertificateBaselineEscrowRoot = 0, - kSecCertificateProductionEscrowRoot = 1, -}; - -/* The names of the files that contain the escrow certificates */ -extern CFTypeRef kSecCertificateProductionEscrowKey; -extern CFTypeRef kSecCertificateEscrowFileName; - - -/* Return a certificate for the DER representation of this certificate. - Return NULL if the passed-in data is not a valid DER-encoded X.509 - certificate. */ -SecCertificateRef SecCertificateCreateWithBytes(CFAllocatorRef allocator, - const UInt8 *bytes, CFIndex length); - -/* Return the length of the DER representation of this certificate. */ -CFIndex SecCertificateGetLength(SecCertificateRef certificate); - -/* Return the bytes of the DER representation of this certificate. */ -const UInt8 *SecCertificateGetBytePtr(SecCertificateRef certificate); - -// MARK: - -// MARK: Certificate Accessors - -CFDataRef SecCertificateGetSHA1Digest(SecCertificateRef certificate); - -CFDataRef SecCertificateCopyIssuerSHA1Digest(SecCertificateRef certificate); - -CFDataRef SecCertificateCopyPublicKeySHA1Digest(SecCertificateRef certificate); - -/*! - @function SecCertificateCopyIssuerSummary - @abstract Return a simple string which hopefully represents a human understandable issuer. - @param certificate SecCertificate object created with SecCertificateCreateWithData(). - @discussion All the data in this string comes from the certificate itself - and thus it's in whatever language the certificate itself is in. - @result A CFStringRef which the caller should CFRelease() once it's no longer needed. -*/ -CFStringRef SecCertificateCopyIssuerSummary(SecCertificateRef certificate); - -/*! - @function SecCertificateCopyProperties - @abstract Return a property array for this trust certificate. - @param certificate A reference to the certificate to evaluate. - @result A property array. It is the caller's responsability to CFRelease - the returned array when it is no longer needed. - See SecTrustCopySummaryPropertiesAtIndex on how to intepret this array. - Unlike that function call this function returns a detailed description - of the certificate in question. -*/ -CFArrayRef SecCertificateCopyProperties(SecCertificateRef certificate); - -CFMutableArrayRef SecCertificateCopySummaryProperties( - SecCertificateRef certificate, CFAbsoluteTime verifyTime); - -/* Return the content of a DER-encoded integer (without the tag and length - fields) for this certificate's serial number. The caller must CFRelease - the value returned. */ -CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate); - -/* Return an array of CFStringRefs representing the ip addresses in the - certificate if any. */ -CFArrayRef SecCertificateCopyIPAddresses(SecCertificateRef certificate); - -/* Return an array of CFStringRefs representing the dns addresses in the - certificate if any. */ -CFArrayRef SecCertificateCopyDNSNames(SecCertificateRef certificate); - -/* Return an array of CFStringRefs representing the email addresses in the - certificate if any. */ -CFArrayRef SecCertificateCopyRFC822Names(SecCertificateRef certificate); - -/* Return an array of CFStringRefs representing the common names in the - certificates subject if any. */ -CFArrayRef SecCertificateCopyCommonNames(SecCertificateRef certificate); - -/* Return an array of CFStringRefs representing the organization in the - certificate's subject if any. */ -CFArrayRef SecCertificateCopyOrganization(SecCertificateRef certificate); - -/* Return an array of CFStringRefs representing the organizational unit in the - certificate's subject if any. */ -CFArrayRef SecCertificateCopyOrganizationalUnit(SecCertificateRef certificate); - -/* Return an array of CFStringRefs representing the NTPrincipalNames in the - certificate if any. */ -CFArrayRef SecCertificateCopyNTPrincipalNames(SecCertificateRef certificate); - -/* Return a string formatted according to RFC 2253 representing the complete - subject of certificate. */ -CFStringRef SecCertificateCopySubjectString(SecCertificateRef certificate); - -/* Return a string with the company name of an ev leaf certificate. */ -CFStringRef SecCertificateCopyCompanyName(SecCertificateRef certificate); - -/* X.509 Certificate Version: 1, 2 or 3. */ -CFIndex SecCertificateVersion(SecCertificateRef certificate); -CFAbsoluteTime SecCertificateNotValidBefore(SecCertificateRef certificate); -CFAbsoluteTime SecCertificateNotValidAfter(SecCertificateRef certificate); - -/* Return true iff certificate is self signed and has a basic constraints - extension indicating that it's a certificate authority. */ -bool SecCertificateIsSelfSignedCA(SecCertificateRef certificate); - -SecKeyUsage SecCertificateGetKeyUsage(SecCertificateRef certificate); - -/* Returns an array of CFDataRefs for all extended key usage oids or NULL */ -CFArrayRef SecCertificateCopyExtendedKeyUsage(SecCertificateRef certificate); - -/* Returns a certificate from a pem blob */ -SecCertificateRef SecCertificateCreateWithPEM(CFAllocatorRef allocator, - CFDataRef pem_certificate); - -/* Append certificate to xpc_certificates. */ -bool SecCertificateAppendToXPCArray(SecCertificateRef certificate, xpc_object_t xpc_certificates, CFErrorRef *error); - -/* Decode certificate from xpc_certificates[index] as encoded by SecCertificateAppendToXPCArray(). */ -SecCertificateRef SecCertificateCreateWithXPCArrayAtIndex(xpc_object_t xpc_certificates, size_t index, CFErrorRef *error); - -/* Retrieve the array of valid Escrow certificates for a given root type */ -CFArrayRef SecCertificateCopyEscrowRoots(SecCertificateEscrowRootType escrowRootType); - -/* Return an xpc_array of data from an array of SecCertificateRefs. */ -xpc_object_t SecCertificateArrayCopyXPCArray(CFArrayRef certificates, CFErrorRef *error); - -/* Return an array of SecCertificateRefs from a xpc_object array of datas. */ -CFArrayRef SecCertificateXPCArrayCopyArray(xpc_object_t xpc_certificates, CFErrorRef *error); - -__END_DECLS - -#endif /* !_SECURITY_SECCERTIFICATEPRIV_H_ */ diff --git a/sec/Security/SecCertificateRequest.h b/sec/Security/SecCertificateRequest.h deleted file mode 100644 index 62bf9d14..00000000 --- a/sec/Security/SecCertificateRequest.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2008-2009 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 SecCertificateRequest -*/ - -#ifndef _SECURITY_SECCERTIFICATEREQUEST_H_ -#define _SECURITY_SECCERTIFICATEREQUEST_H_ - -#include -#include - -__BEGIN_DECLS - -extern const void * kSecOidCommonName; -extern const void * kSecOidCountryName; -extern const void * kSecOidStateProvinceName; -extern const void * kSecOidLocalityName; -extern const void * kSecOidOrganization; -extern const void * kSecOidOrganizationalUnit; - -extern const unsigned char SecASN1PrintableString; -extern const unsigned char SecASN1UTF8String; - -/* - Parameter keys for certificate request generation: - @param kSecCSRChallengePassword CFStringRef - conversion to PrintableString or UTF8String needs to be possible. - @param kSecCertificateKeyUsage CFNumberRef - with key usage mask using kSecKeyUsage constants. - @param kSecSubjectAltName CFArrayRef of CFStringRef or CFDataRef - either dnsName or emailAddress (if contains @) or - ipAddress, ipv4 (4) or ipv6 (16) bytes - @param kSecCSRBasicContraintsPathLen CFNumberRef - if set will include basic constraints and mark it as - a CA cert. If 0 <= number < 256, specifies path length, otherwise - path length will be omitted. Basic contraints will always be - marked critical. - @param kSecCertificateExtensions CFDictionaryRef - if set all keys (strings with oids in dotted notation) will be added - as extensions with accompanying value in binary (CFDataRef) or - appropriate string (CFStringRef) type (based on used character set). -*/ -extern const void * kSecCSRChallengePassword; -extern const void * kSecSubjectAltName; -extern const void * kSecCertificateKeyUsage; -extern const void * kSecCSRBasicContraintsPathLen; -extern const void * kSecCertificateExtensions; - -typedef struct { - const void *oid; /* kSecOid constant or CFDataRef with oid */ - unsigned char type; /* currently only SecASN1PrintableString */ - CFTypeRef value; /* CFStringRef -> ASCII, UTF8, CFDataRef -> binary */ -} SecATV; - -typedef SecATV *SecRDN; - -/* - @function SecGenerateCertificateRequest - @abstract Return a newly generated CSR for subject and keypair. - @param subject RDNs in the subject - @param num Number of RDNs - @param publicKey Public key - @param privateKey Private key - @discussion only handles RSA keypairs and uses a SHA-1 PKCS1 signature - @result On success, a newly allocated CSR, otherwise NULL - -Example for subject: - SecATV cn[] = { { kSecOidCommonName, SecASN1PrintableString, CFSTR("test") }, {} }; - SecATV c[] = { { kSecOidCountryName, SecASN1PrintableString, CFSTR("US") }, {} }; - SecATV o[] = { { kSecOidOrganization, SecASN1PrintableString, CFSTR("Apple Inc.") }, {} }; - SecRDN atvs[] = { cn, c, o, NULL }; -*/ -CFDataRef SecGenerateCertificateRequestWithParameters(SecRDN *subject, - CFDictionaryRef parameters, SecKeyRef publicKey, SecKeyRef privateKey) CF_RETURNS_RETAINED; - -CFDataRef SecGenerateCertificateRequest(CFArrayRef subject, - CFDictionaryRef parameters, SecKeyRef publicKey, SecKeyRef privateKey) CF_RETURNS_RETAINED; - -/* - @function SecVerifyCertificateRequest - @abstract validate a CSR and return contained information to certify - @param publicKey (optional/out) SecKeyRef public key to certify - @param challenge (optional/out) CFStringRef enclosed challenge - @param subject (optional/out) encoded subject RDNs - @param extensions (optional/out) encoded extensions -*/ -bool SecVerifyCertificateRequest(CFDataRef csr, SecKeyRef *publicKey, - CFStringRef *challenge, CFDataRef *subject, CFDataRef *extensions); - -SecCertificateRef -SecGenerateSelfSignedCertificate(CFArrayRef subject, CFDictionaryRef parameters, - SecKeyRef publicKey, SecKeyRef privateKey); - -SecCertificateRef -SecIdentitySignCertificate(SecIdentityRef issuer, CFDataRef serialno, - SecKeyRef publicKey, CFTypeRef subject, CFTypeRef extensions); - - -/* PRIVATE */ - -CFDataRef -SecGenerateCertificateRequestSubject(SecCertificateRef ca_certificate, CFArrayRef subject); - -__END_DECLS - -#endif /* _SECURITY_SECCERTIFICATEREQUEST_H_ */ diff --git a/sec/Security/SecDH.c b/sec/Security/SecDH.c deleted file mode 100644 index e33bb2c5..00000000 --- a/sec/Security/SecDH.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (c) 2007-2008,2010 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@ - */ - -/* - * SecDH.c - Implement the crypto required for a Diffie-Hellman key exchange. - */ - -#include "SecDH.h" -#include -#include -#include -#include -#include -#include -#include "utilities/debugging.h" -#include -#include -#include -#include -#include - -#ifdef DEBUG -#define DH_DEBUG 1 -#endif - -static inline ccdh_gp_t SecDH_gp(SecDHContext dh) -{ - void *p = dh; - ccdh_gp_t gp = { .gp = p }; - return gp; -} - -static inline ccdh_full_ctx_t SecDH_priv(SecDHContext dh) -{ - void *p = dh; - cczp_t zp = { .u = p }; - cc_size s = ccn_sizeof_n(cczp_n(zp)); - ccdh_full_ctx_t priv = { .hdr = (struct ccdh_ctx_header *)(p+ccdh_gp_size(s)) }; - return priv; -} - -static inline size_t SecDH_context_size(size_t p_len) -{ - cc_size n = ccn_nof_size(p_len); - cc_size real_p_len = ccn_sizeof_n(n); - size_t context_size = ccdh_gp_size(real_p_len)+ccdh_full_ctx_size(real_p_len); - return context_size; -} - -/* Shared static functions. */ - -static OSStatus -der2OSStatus(DERReturn derReturn) -{ - switch(derReturn) - { - case DR_Success: return errSecSuccess; - case DR_EndOfSequence: return errSecDecode; - case DR_UnexpectedTag: return errSecDecode; - case DR_DecodeError: return errSecDecode; - case DR_Unimplemented: return errSecUnimplemented; - case DR_IncompleteSeq: return errSecDecode; - case DR_ParamErr: return errSecParam; - case DR_BufOverflow: return errSecBufferTooSmall; - default: return errSecInternal; - } -} - -static int dhRngCallback(struct ccrng_state *rng, unsigned long outlen, void *out) -{ - return SecRandomCopyBytes(kSecRandomDefault, outlen, out); -} - -static struct ccrng_state dhrng = { - .generate = dhRngCallback -}; - -OSStatus SecDHCreate(uint32_t g, const uint8_t *p, size_t p_len, - uint32_t l, const uint8_t *recip, size_t recip_len, SecDHContext *pdh) -{ - cc_size n = ccn_nof_size(p_len); - size_t context_size = SecDH_context_size(p_len); - void *context = malloc(context_size); - bzero(context, context_size); - - ccdh_gp_t gp; - gp.gp = context; - - CCDH_GP_N(gp) = n; - CCDH_GP_L(gp) = l; - - if(ccn_read_uint(n, CCDH_GP_PRIME(gp), p_len, p)) - goto errOut; - if(recip) { - if(ccn_read_uint(n+1, CCDH_GP_RECIP(gp), recip_len, recip)) - goto errOut; - gp.zp.zp->mod_prime = cczp_mod; - } else { - cczp_init(gp.zp); - }; - ccn_seti(n, CCDH_GP_G(gp), g); - - *pdh = (SecDHContext) context; - - return errSecSuccess; - -errOut: - SecDHDestroy(context); - *pdh = NULL; - return errSecInternal; - -} - -/* this used to be in libgDH */ -/* - * Support for encoding and decoding DH parameter blocks. - * Apple form encodes the reciprocal of the prime p. - */ -/* PKCS3, Openssl compatible */ -typedef struct { - DERItem p; - DERItem g; - DERItem l; - DERItem recip; /* Only used in Apple Custom blocks. */ -} DER_DHParams; - -static const DERItemSpec DER_DHParamsItemSpecs[] = -{ - { DER_OFFSET(DER_DHParams, p), - ASN1_INTEGER, - DER_DEC_NO_OPTS | DER_ENC_SIGNED_INT }, - { DER_OFFSET(DER_DHParams, g), - ASN1_INTEGER, - DER_DEC_NO_OPTS | DER_ENC_SIGNED_INT }, - { DER_OFFSET(DER_DHParams, l), - ASN1_INTEGER, - DER_DEC_OPTIONAL | DER_ENC_SIGNED_INT }, - /* Not part of PKCS3 per-se, but we add it on just for kicks. Since - it's optional we will automatically decode any apple specific - params, but we won't add this section unless the caller asks - us to. */ - { DER_OFFSET(DER_DHParams, recip), - ASN1_PRIVATE | ASN1_PRIMITIVE | 0, - DER_DEC_OPTIONAL | DER_ENC_SIGNED_INT }, -}; -static const DERSize DER_NumDHParamsItemSpecs = -sizeof(DER_DHParamsItemSpecs) / sizeof(DERItemSpec); - - -OSStatus SecDHCreateFromParameters(const uint8_t *params, - size_t params_len, SecDHContext *pdh) -{ - DERReturn drtn; - DERItem paramItem = {(DERByte *)params, params_len}; - DER_DHParams decodedParams; - uint32_t l; - - drtn = DERParseSequence(¶mItem, - DER_NumDHParamsItemSpecs, DER_DHParamsItemSpecs, - &decodedParams, sizeof(decodedParams)); - if(drtn) - return drtn; - - drtn = DERParseInteger(&decodedParams.l, &l); - if(drtn) - return drtn; - cc_size n = ccn_nof_size(decodedParams.p.length); - cc_size p_len = ccn_sizeof_n(n); - size_t context_size = ccdh_gp_size(p_len)+ccdh_full_ctx_size(p_len); - void *context = malloc(context_size); - if(context==NULL) - return errSecAllocate; - - bzero(context, context_size); - - ccdh_gp_t gp; - gp.gp = context; - - CCDH_GP_N(gp) = n; - CCDH_GP_L(gp) = l; - - if(ccn_read_uint(n, CCDH_GP_PRIME(gp), decodedParams.p.length, decodedParams.p.data)) - goto errOut; - if(decodedParams.recip.length) { - if(ccn_read_uint(n+1, CCDH_GP_RECIP(gp), decodedParams.recip.length, decodedParams.recip.data)) - goto errOut; - gp.zp.zp->mod_prime = cczp_mod; - } else { - cczp_init(gp.zp); - }; - - if(ccn_read_uint(n, CCDH_GP_G(gp), decodedParams.g.length, decodedParams.g.data)) - goto errOut; - - *pdh = (SecDHContext) context; - return errSecSuccess; - -errOut: - SecDHDestroy(context); - *pdh = NULL; - return errSecInvalidKey; -} - -OSStatus SecDHCreateFromAlgorithmId(const uint8_t *alg, size_t alg_len, - SecDHContext *pdh) { - DERAlgorithmId algorithmId; - DERItem algId; - - algId.data = (uint8_t *)alg; - algId.length = alg_len; - - DERReturn drtn = DERParseSequence(&algId, - DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs, - &algorithmId, sizeof(algorithmId)); - if (drtn != DR_Success) - return der2OSStatus(drtn); - - return SecDHCreateFromParameters(algorithmId.params.data, - algorithmId.params.length, pdh); -} - -size_t SecDHGetMaxKeyLength(SecDHContext dh) { - cczp_const_t zp; - zp.u = (cc_unit *)dh; - - return ccn_sizeof_n(cczp_n(zp)); -} - - -OSStatus SecDHGenerateKeypair(SecDHContext dh, uint8_t *pub_key, - size_t *pub_key_len) -{ - int result; - ccdh_gp_t gp = SecDH_gp(dh); - ccdh_full_ctx_t priv = SecDH_priv(dh); - - if((result = ccdh_generate_key(gp, &dhrng, priv))) - return result; - - /* output y as a big endian byte buffer */ - size_t ylen = ccn_write_uint_size(ccdh_gp_n(gp), ccdh_ctx_y(priv)); - if(*pub_key_len < ylen) - return errSecBufferTooSmall; - ccn_write_uint(ccdh_gp_n(gp),ccdh_ctx_y(priv), ylen, pub_key); - *pub_key_len = ylen; - - return errSecSuccess; -} - -OSStatus SecDHComputeKey(SecDHContext dh, - const uint8_t *pub_key, size_t pub_key_len, - uint8_t *computed_key, size_t *computed_key_len) -{ - ccdh_gp_t gp = SecDH_gp(dh); - ccdh_full_ctx_t priv = SecDH_priv(dh); - ccdh_pub_ctx_decl_gp(gp, pub); - cc_size n = ccdh_gp_n(gp); - cc_unit r[n]; - - if(ccdh_import_pub(gp, pub_key_len, pub_key, pub)) - return errSecInvalidKey; - - if(ccdh_compute_key(priv, pub, r)) - return errSecInvalidKey; - - ccn_write_uint(n, r, *computed_key_len, computed_key); - size_t out_size = ccn_write_uint_size(n, r); - if(out_size < *computed_key_len) - *computed_key_len=out_size; - - return errSecSuccess; -} - -void SecDHDestroy(SecDHContext dh) { - /* Zero out key material. */ - ccdh_gp_t gp = SecDH_gp(dh); - cc_size p_len = ccn_sizeof_n(ccdh_gp_n(gp)); - size_t context_size = SecDH_context_size(p_len); - - bzero(dh, context_size); - free(dh); -} diff --git a/sec/Security/SecECKey.c b/sec/Security/SecECKey.c deleted file mode 100644 index a574a9f4..00000000 --- a/sec/Security/SecECKey.c +++ /dev/null @@ -1,665 +0,0 @@ -/* - * Copyright (c) 2010,2011 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@ - */ - -/* - * SecECKey.c - CoreFoundation based rsa key object - */ - -#include "SecECKey.h" - -#include -#include -#include -#include -#include /* For error codes. */ -#include /* For error codes. */ -#include -#include -#include -#include -#include -#include -#include -#include "SecItemPriv.h" -#include -#include -#include -#include -#include -#include - -#define kMaximumECKeySize 521 - -static CFIndex SecECKeyGetAlgorithmID(SecKeyRef key) { - return kSecECDSAAlgorithmID; -} - - -/* - * - * Public Key - * - */ - -/* Public key static functions. */ -static void SecECPublicKeyDestroy(SecKeyRef key) { - /* Zero out the public key */ - ccec_pub_ctx_t pubkey; - pubkey.pub = key->key; - if (ccec_ctx_cp(pubkey).zp) - cc_zero(ccec_pub_ctx_size(ccn_sizeof_n(ccec_ctx_n(pubkey))), pubkey.pub); -} - -static ccec_const_cp_t getCPForPublicSize(CFIndex encoded_length) -{ - size_t keysize = ccec_x963_import_pub_size(encoded_length); - if(ccec_keysize_is_supported(keysize)) { - return ccec_get_cp(keysize); - } - ccec_const_cp_t nullCP = { .zp = NULL }; - return nullCP; -} - -static ccec_const_cp_t getCPForPrivateSize(CFIndex encoded_length) -{ - size_t keysize = ccec_x963_import_priv_size(encoded_length); - if(ccec_keysize_is_supported(keysize)) { - return ccec_get_cp(keysize); - } - ccec_const_cp_t nullCP = { .zp = NULL }; - return nullCP; -} - -static ccoid_t ccoid_secp192r1 = CC_EC_OID_SECP192R1; -static ccoid_t ccoid_secp256r1 = CC_EC_OID_SECP256R1; -static ccoid_t ccoid_secp224r1 = CC_EC_OID_SECP224R1; -static ccoid_t ccoid_secp384r1 = CC_EC_OID_SECP384R1; -static ccoid_t ccoid_secp521r1 = CC_EC_OID_SECP521R1; - -static ccec_const_cp_t ccec_cp_for_oid(ccoid_t oid) -{ - if (oid.oid) { - if (ccoid_equal(oid, ccoid_secp192r1)) { - return ccec_cp_192(); - } else if (ccoid_equal(oid, ccoid_secp256r1)) { - return ccec_cp_256(); - } else if (ccoid_equal(oid, ccoid_secp224r1)) { - return ccec_cp_224(); - } else if (ccoid_equal(oid, ccoid_secp384r1)) { - return ccec_cp_384(); - } else if (ccoid_equal(oid, ccoid_secp521r1)) { - return ccec_cp_521(); - } - } - return (ccec_const_cp_t){NULL}; -} - -static OSStatus SecECPublicKeyInit(SecKeyRef key, - const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) { - ccec_pub_ctx_t pubkey; - pubkey.pub = key->key; - OSStatus err = errSecParam; - - switch (encoding) { - case kSecDERKeyEncoding: - { - const SecDERKey *derKey = (const SecDERKey *)keyData; - if (keyDataLength != sizeof(SecDERKey)) { - err = errSecDecode; - break; - } - - ccec_const_cp_t cp = getCPForPublicSize(derKey->keyLength); - - /* TODO: Parse and use real params from passed in derKey->algId.params */ - err = (ccec_import_pub(cp, derKey->keyLength, derKey->key, pubkey) - ? errSecDecode : errSecSuccess); - break; - } - case kSecKeyEncodingBytes: - { - ccec_const_cp_t cp = getCPForPublicSize(keyDataLength); - err = (ccec_import_pub(cp, keyDataLength, keyData, pubkey) - ? errSecDecode : errSecSuccess); - break; - } - case kSecExtractPublicFromPrivate: - { - ccec_full_ctx_t fullKey; - fullKey._full = (ccec_full_ctx *) keyData; - - cc_size fullKeyN = ccec_ctx_n(fullKey); - require(fullKeyN <= ccn_nof(kMaximumECKeySize), errOut); - memcpy(pubkey._pub, fullKey.pub, ccec_pub_ctx_size(ccn_sizeof_n(fullKeyN))); - err = errSecSuccess; - break; - } - case kSecKeyEncodingApplePkcs1: - default: - err = errSecParam; - break; - } - -errOut: - return err; -} - -static OSStatus SecECPublicKeyRawVerify(SecKeyRef key, SecPadding padding, - const uint8_t *signedData, size_t signedDataLen, - const uint8_t *sig, size_t sigLen) { - int err = errSSLCrypto; // TODO: Should be errSecNotSigner; - ccec_pub_ctx_t pubkey; - pubkey.pub = key->key; - bool valid = 0; - - if (ccec_verify(pubkey, signedDataLen, signedData, sigLen, sig, &valid)) - err = errSSLCrypto; // TODO: This seems weird. Shouldn't be SSL error - if (valid) - err = errSecSuccess; - - return err; -} - -static OSStatus SecECPublicKeyRawEncrypt(SecKeyRef key, SecPadding padding, - const uint8_t *plainText, size_t plainTextLen, - uint8_t *cipherText, size_t *cipherTextLen) { - ccec_pub_ctx_t pubkey; - pubkey.pub = key->key; - int err = errSecUnimplemented; - -#if 0 - require_noerr(err = ccec_wrap_key(pubkey, &ccsha256_di, - plainTextLen, plainText, cipherText), errOut); - -errOut: -#endif - return err; -} - -static size_t SecECPublicKeyBlockSize(SecKeyRef key) { - /* Get key size in octets */ - ccec_pub_ctx_t pubkey; - pubkey.pub = key->key; - return ccec_ctx_size(pubkey); -} - -/* Encode the public key and return it in a newly allocated CFDataRef. */ -static CFDataRef SecECPublicKeyExport(CFAllocatorRef allocator, - ccec_pub_ctx_t pubkey) { - size_t pub_size = ccec_export_pub_size(pubkey); - CFMutableDataRef blob = CFDataCreateMutable(allocator, pub_size); - if (blob) { - CFDataSetLength(blob, pub_size); - ccec_export_pub(pubkey, CFDataGetMutableBytePtr(blob)); - } - - return blob; -} - -static OSStatus SecECPublicKeyCopyPublicOctets(SecKeyRef key, CFDataRef *serailziation) -{ - ccec_pub_ctx_t pubkey; - pubkey.pub = key->key; - - CFAllocatorRef allocator = CFGetAllocator(key); - *serailziation = SecECPublicKeyExport(allocator, pubkey); - - if (NULL == *serailziation) - return errSecDecode; - else - return errSecSuccess; -} - -static CFDictionaryRef SecECPublicKeyCopyAttributeDictionary(SecKeyRef key) { - return SecKeyGeneratePublicAttributeDictionary(key, kSecAttrKeyTypeEC); -} - -static CFStringRef SecECPublicKeyCopyKeyDescription(SecKeyRef key) -{ - ccec_pub_ctx_t ecPubkey; - CFStringRef keyDescription = NULL; - size_t xlen, ylen, ix; - CFMutableStringRef xString = NULL; - CFMutableStringRef yString = NULL; - - ecPubkey.pub = key->key; - - //curve - long curveType = (long)SecECKeyGetNamedCurve(key); - char* curve= NULL; - - switch (curveType) - { - case 23: - curve = "kSecECCurveSecp256r1"; - break; - case 24: - curve = "kSecECCurveSecp384r1"; - break; - case 25: - curve = "kSecECCurveSecp521r1"; - break; - case -1: - curve = "kSecECCurveNone"; - break; - default: - curve = "kSecECCurveNone"; - break; - } - - uint8_t *xunit = (uint8_t*)ccec_ctx_x(ecPubkey); - require_quiet( NULL != xunit, fail); - xlen = (size_t)strlen((char*)xunit); - - - xString = CFStringCreateMutable(kCFAllocatorDefault, xlen * 2); - require_quiet( NULL != xString, fail); - - for (ix = 0; ix < xlen; ++ix) - { - CFStringAppendFormat(xString, NULL, CFSTR("%02X"), xunit[ix]); - } - - uint8_t *yunit = (uint8_t*)ccec_ctx_y(ecPubkey); - require_quiet( NULL != yunit, fail); - ylen = (size_t)strlen((char*)yunit); - - yString = CFStringCreateMutable(kCFAllocatorDefault, ylen*2); - require_quiet( NULL != yString, fail); - - for(ix = 0; ix < ylen; ++ix) - { - CFStringAppendFormat(yString, NULL, CFSTR("%02X"), yunit[ix]); - } - - keyDescription = CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR( ""), curve, (long)SecKeyGetAlgorithmID(key), key->key_class->name, key->key_class->version, (8*SecKeyGetBlockSize(key)), yString, xString, key); - -fail: - CFReleaseSafe(xString); - CFReleaseSafe(yString); - if(!keyDescription) - keyDescription = CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR(""), curve,(long)SecKeyGetAlgorithmID(key), key->key_class->name, key->key_class->version, (8*SecKeyGetBlockSize(key)), key); - - return keyDescription; -} - -SecKeyDescriptor kSecECPublicKeyDescriptor = { - kSecKeyDescriptorVersion, - "ECPublicKey", - ccec_pub_ctx_size(ccn_sizeof(kMaximumECKeySize)), /* extraBytes */ - SecECPublicKeyInit, - SecECPublicKeyDestroy, - NULL, /* SecKeyRawSignMethod */ - SecECPublicKeyRawVerify, - SecECPublicKeyRawEncrypt, - NULL, /* SecKeyDecryptMethod */ - NULL, /* SecKeyComputeMethod */ - SecECPublicKeyBlockSize, - SecECPublicKeyCopyAttributeDictionary, - SecECPublicKeyCopyKeyDescription, - SecECKeyGetAlgorithmID, - SecECPublicKeyCopyPublicOctets, -}; - -/* Public Key API functions. */ -SecKeyRef SecKeyCreateECPublicKey(CFAllocatorRef allocator, - const uint8_t *keyData, CFIndex keyDataLength, - SecKeyEncoding encoding) { - return SecKeyCreate(allocator, &kSecECPublicKeyDescriptor, keyData, - keyDataLength, encoding); -} - - - -/* - * - * Private Key - * - */ - -/* Private key static functions. */ -static void SecECPrivateKeyDestroy(SecKeyRef key) { - /* Zero out the public key */ - ccec_full_ctx_t fullkey; - fullkey.hdr = key->key; - if (ccec_ctx_cp(fullkey).zp) - cc_zero(ccec_full_ctx_size(ccn_sizeof_n(ccec_ctx_n(fullkey))), fullkey.hdr); -} - - -static OSStatus SecECPrivateKeyInit(SecKeyRef key, - const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) { - ccec_full_ctx_t fullkey; - fullkey.hdr = key->key; - OSStatus err = errSecParam; - - switch (encoding) { - case kSecKeyEncodingPkcs1: - { - /* TODO: DER import size (and thus cp), pub.x, pub.y and k. */ - //err = ecc_import(keyData, keyDataLength, fullkey); - - /* DER != PKCS#1, but we'll go along with it */ - ccoid_t oid; - size_t n; - ccec_const_cp_t cp; - - require_noerr(ccec_der_import_priv_keytype(keyDataLength, keyData, &oid, &n), abort); - cp = ccec_cp_for_oid(oid); - if (cp.zp == NULL) { - cp = ccec_curve_for_length_lookup(n * 8 /* bytes -> bits */, - ccec_cp_192(), ccec_cp_224(), ccec_cp_256(), ccec_cp_384(), ccec_cp_521(), NULL); - } - require_action(cp.zp != NULL, abort, err = errSecDecode); - ccec_ctx_init(cp, fullkey); - - require_noerr(ccec_der_import_priv(cp, keyDataLength, keyData, fullkey), abort); - err = errSecSuccess; - break; - } - case kSecKeyEncodingBytes: - { - ccec_const_cp_t cp = getCPForPrivateSize(keyDataLength); - require(cp.zp != NULL, abort); - - ccec_ctx_init(cp, fullkey); - size_t pubSize = ccec_export_pub_size(fullkey); - - require(pubSize < (size_t) keyDataLength, abort); - require_noerr_action(ccec_import_pub(cp, pubSize, keyData, fullkey), - abort, - err = errSecDecode); - - - keyData += pubSize; - keyDataLength -= pubSize; - - cc_unit *k = ccec_ctx_k(fullkey); - require_noerr_action(ccn_read_uint(ccec_ctx_n(fullkey), k, keyDataLength, keyData), - abort, - err = errSecDecode); - - err = errSecSuccess; - break; - - } - case kSecGenerateKey: - { - CFDictionaryRef parameters = (CFDictionaryRef) keyData; - - CFTypeRef ksize = CFDictionaryGetValue(parameters, kSecAttrKeySizeInBits); - CFIndex keyLengthInBits = getIntValue(ksize); - - ccec_const_cp_t cp = ccec_get_cp(keyLengthInBits); - - if (!cp.zp) { - secwarning("Invalid or missing key size in: %@", parameters); - return errSecKeySizeNotAllowed; - } - - if (!ccec_generate_key(cp, ccrng_seckey, fullkey)) - err = errSecSuccess; - break; - } - - default: - break; - } -abort: - return err; -} - -static OSStatus SecECPrivateKeyRawSign(SecKeyRef key, SecPadding padding, - const uint8_t *dataToSign, size_t dataToSignLen, - uint8_t *sig, size_t *sigLen) { - ccec_full_ctx_t fullkey; - fullkey.hdr = key->key; - int err;; - check(sigLen); - - require_noerr(err = ccec_sign(fullkey, dataToSignLen, dataToSign, - sigLen, sig, ccrng_seckey), errOut); -errOut: - - return err; -} - -#if 0 -static const struct ccdigest_info * -ccdigest_lookup_by_oid(unsigned long oid_size, const void *oid) { - static const struct ccdigest_info *dis[] = { - &ccsha1_di, - &ccsha224_di, - &ccsha256_di, - &ccsha384_di, - &ccsha512_di - }; - size_t i; - for (i = 0; i < array_size(dis); ++i) { - if (oid_size == dis[i]->oid_size && !memcmp(dis[i]->oid, oid, oid_size)) - return dis[i]; - } - return NULL; -} -#endif - -static OSStatus SecECPrivateKeyRawDecrypt(SecKeyRef key, SecPadding padding, - const uint8_t *cipherText, size_t cipherTextLen, - uint8_t *plainText, size_t *plainTextLen) { - ccec_full_ctx_t fullkey; - fullkey.hdr = key->key; - int err = errSecUnimplemented; - -#if 0 - err = ccec_unwrap_key(fullkey, ccrng_seckey, ccdigest_lookup_by_oid, - cipherTextLen, cipherText, plainTextLen, plainText); -#endif - - return err; -} - -static size_t SecECPrivateKeyBlockSize(SecKeyRef key) { - ccec_full_ctx_t fullkey; - fullkey.hdr = key->key; - /* Get key size in octets */ - return ccec_ctx_size(fullkey); -} - -static OSStatus SecECPrivateKeyCopyPublicOctets(SecKeyRef key, CFDataRef *serailziation) -{ - ccec_full_ctx_t fullkey; - fullkey.hdr = key->key; - - CFAllocatorRef allocator = CFGetAllocator(key); - *serailziation = SecECPublicKeyExport(allocator, fullkey); - - if (NULL == *serailziation) - return errSecDecode; - else - return errSecSuccess; -} - -static CFDataRef SecECPPrivateKeyExport(CFAllocatorRef allocator, - ccec_full_ctx_t fullkey) { - size_t prime_size = ccec_cp_prime_size(ccec_ctx_cp(fullkey)); - size_t key_size = ccec_export_pub_size(fullkey) + prime_size; - CFMutableDataRef blob = CFDataCreateMutable(allocator, key_size); - if (blob) { - CFDataSetLength(blob, key_size); - ccec_export_pub(fullkey, CFDataGetMutableBytePtr(blob)); - UInt8 *dest = CFDataGetMutableBytePtr(blob) + ccec_export_pub_size(fullkey); - const cc_unit *k = ccec_ctx_k(fullkey); - ccn_write_uint_padded(ccec_ctx_n(fullkey), k, prime_size, dest); - } - - return blob; -} - - -static CFDictionaryRef SecECPrivateKeyCopyAttributeDictionary(SecKeyRef key) { - CFDictionaryRef dict = NULL; - CFAllocatorRef allocator = CFGetAllocator(key); - - ccec_full_ctx_t fullkey; - fullkey.hdr = key->key; - - CFDataRef fullKeyBlob = NULL; - - /* Export the full ec key pair. */ - require(fullKeyBlob = SecECPPrivateKeyExport(allocator, fullkey), errOut); - - dict = SecKeyGeneratePrivateAttributeDictionary(key, kSecAttrKeyTypeEC, fullKeyBlob); - -errOut: - CFReleaseSafe(fullKeyBlob); - - return dict; -} -static CFStringRef SecECPrivateKeyCopyKeyDescription(SecKeyRef key) { - - //curve - long curveType = (long)SecECKeyGetNamedCurve(key); - char* curve= NULL; - - switch (curveType) - { - case 23: - curve = "kSecECCurveSecp256r1"; - break; - case 24: - curve = "kSecECCurveSecp384r1"; - break; - case 25: - curve = "kSecECCurveSecp521r1"; - break; - case -1: - curve = "kSecECCurveNone"; - break; - default: - curve = "kSecECCurveNone"; - break; - } - - return CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR( ""), curve, (long)SecKeyGetAlgorithmID(key), key->key_class->name, key->key_class->version, (8*SecKeyGetBlockSize(key)), key); - -} - -SecKeyDescriptor kSecECPrivateKeyDescriptor = { - kSecKeyDescriptorVersion, - "ECPrivateKey", - ccec_full_ctx_size(ccn_sizeof(kMaximumECKeySize)), /* extraBytes */ - SecECPrivateKeyInit, - SecECPrivateKeyDestroy, - SecECPrivateKeyRawSign, - NULL, /* SecKeyRawVerifyMethod */ - NULL, /* SecKeyEncryptMethod */ - SecECPrivateKeyRawDecrypt, - NULL, /* SecKeyComputeMethod */ - SecECPrivateKeyBlockSize, - SecECPrivateKeyCopyAttributeDictionary, - SecECPrivateKeyCopyKeyDescription, - SecECKeyGetAlgorithmID, - SecECPrivateKeyCopyPublicOctets, -}; - -/* Private Key API functions. */ -SecKeyRef SecKeyCreateECPrivateKey(CFAllocatorRef allocator, - const uint8_t *keyData, CFIndex keyDataLength, - SecKeyEncoding encoding) { - return SecKeyCreate(allocator, &kSecECPrivateKeyDescriptor, keyData, - keyDataLength, encoding); -} - - -OSStatus SecECKeyGeneratePair(CFDictionaryRef parameters, - SecKeyRef *publicKey, SecKeyRef *privateKey) { - OSStatus status = errSecParam; - - CFAllocatorRef allocator = NULL; /* @@@ get from parameters. */ - SecKeyRef pubKey = NULL; - - SecKeyRef privKey = SecKeyCreate(allocator, &kSecECPrivateKeyDescriptor, - (const void*) parameters, 0, kSecGenerateKey); - - require(privKey, errOut); - - /* Create SecKeyRef's from the pkcs1 encoded keys. */ - pubKey = SecKeyCreate(allocator, &kSecECPublicKeyDescriptor, - privKey->key, 0, kSecExtractPublicFromPrivate); - - require(pubKey, errOut); - - if (publicKey) { - *publicKey = pubKey; - pubKey = NULL; - } - if (privateKey) { - *privateKey = privKey; - privKey = NULL; - } - - status = errSecSuccess; - -errOut: - CFReleaseSafe(pubKey); - CFReleaseSafe(privKey); - - return status; -} - - -/* It's debatable whether this belongs here or in the ssl code since the - curve values come from a tls related rfc4492. */ -SecECNamedCurve SecECKeyGetNamedCurve(SecKeyRef key) { - if (key->key_class != &kSecECPublicKeyDescriptor && - key->key_class != &kSecECPrivateKeyDescriptor) - return kSecECCurveNone; - - ccec_pub_ctx_t pubkey; - pubkey.pub = key->key; - switch (ccec_ctx_size(pubkey)) { -#if 0 - case 24: - return kSecECCurveSecp192r1; - case 28: - return kSecECCurveSecp224r1; -#endif - case 32: - return kSecECCurveSecp256r1; - case 48: - return kSecECCurveSecp384r1; - case 66: - return kSecECCurveSecp521r1; - } - return kSecECCurveNone; -} - -CFDataRef SecECKeyCopyPublicBits(SecKeyRef key) { - if (key->key_class != &kSecECPublicKeyDescriptor && - key->key_class != &kSecECPrivateKeyDescriptor) - return NULL; - - ccec_pub_ctx_t pubkey; - pubkey.pub = key->key; - return SecECPublicKeyExport(CFGetAllocator(key), pubkey); -} diff --git a/sec/Security/SecIdentity.c b/sec/Security/SecIdentity.c deleted file mode 100644 index 7efb22dd..00000000 --- a/sec/Security/SecIdentity.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2002-2004,2007-2008,2010 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@ - */ - -/* - * SecIdentity.c - CoreFoundation based object containing a - * private key, certificate tuple. - */ - - -#include - -#include -#include -#include -#include -#include -#include "SecIdentityPriv.h" -#include - -struct __SecIdentity { - CFRuntimeBase _base; - - SecCertificateRef _certificate; - SecKeyRef _privateKey; -}; - - -/* CFRuntime regsitration data. */ -static pthread_once_t kSecIdentityRegisterClass = PTHREAD_ONCE_INIT; -static CFTypeID kSecIdentityTypeID = _kCFRuntimeNotATypeID; - -/* Forward declartions of static functions. */ -static CFStringRef SecIdentityCopyDescription(CFTypeRef cf); -static void SecIdentityDestroy(CFTypeRef cf); - -/* Static functions. */ -static CFStringRef SecIdentityCopyDescription(CFTypeRef cf) { - SecIdentityRef identity = (SecIdentityRef)cf; - return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, - CFSTR(""), identity); -} - -static void SecIdentityDestroy(CFTypeRef cf) { - SecIdentityRef identity = (SecIdentityRef)cf; - CFReleaseSafe(identity->_certificate); - CFReleaseSafe(identity->_privateKey); -} - -static Boolean SecIdentityEqual(CFTypeRef cf1, CFTypeRef cf2) { - SecIdentityRef identity1 = (SecIdentityRef)cf1; - SecIdentityRef identity2 = (SecIdentityRef)cf2; - if (identity1 == identity2) - return true; - if (!identity2) - return false; - return CFEqual(identity1->_certificate, identity2->_certificate) && - CFEqual(identity1->_privateKey, identity2->_privateKey); -} - -/* Hash of identity is hash of certificate plus hash of key. */ -static CFHashCode SecIdentityHash(CFTypeRef cf) { - SecIdentityRef identity = (SecIdentityRef)cf; - return CFHash(identity->_certificate) + CFHash(identity->_privateKey); -} - -static void SecIdentityRegisterClass(void) { - static const CFRuntimeClass kSecIdentityClass = { - 0, /* version */ - "SecIdentity", /* class name */ - NULL, /* init */ - NULL, /* copy */ - SecIdentityDestroy, /* dealloc */ - SecIdentityEqual, /* equal */ - SecIdentityHash, /* hash */ - NULL, /* copyFormattingDesc */ - SecIdentityCopyDescription /* copyDebugDesc */ - }; - - kSecIdentityTypeID = _CFRuntimeRegisterClass(&kSecIdentityClass); -} - - -/* Public API functions. */ -CFTypeID SecIdentityGetTypeID(void) { - pthread_once(&kSecIdentityRegisterClass, SecIdentityRegisterClass); - return kSecIdentityTypeID; -} - -OSStatus SecIdentityCopyCertificate(SecIdentityRef identity, - SecCertificateRef *certificateRef) { - *certificateRef = identity->_certificate; - CFRetain(*certificateRef); - return 0; -} - -OSStatus SecIdentityCopyPrivateKey(SecIdentityRef identity, - SecKeyRef *privateKeyRef) { - *privateKeyRef = identity->_privateKey; - CFRetain(*privateKeyRef); - return 0; -} - -SecIdentityRef SecIdentityCreate(CFAllocatorRef allocator, - SecCertificateRef certificate, SecKeyRef privateKey) { - CFIndex size = sizeof(struct __SecIdentity); - SecIdentityRef result = (SecIdentityRef)_CFRuntimeCreateInstance( - allocator, SecIdentityGetTypeID(), size - sizeof(CFRuntimeBase), 0); - if (result) { - CFRetain(certificate); - CFRetain(privateKey); - result->_certificate = certificate; - result->_privateKey = privateKey; - } - return result; -} - diff --git a/sec/Security/SecIdentity.h b/sec/Security/SecIdentity.h deleted file mode 100644 index e999401f..00000000 --- a/sec/Security/SecIdentity.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2002-2004,2007-2009 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 SecIdentity - The functions provided in SecIdentity.h implement a convenient way to - match private keys with certificates. -*/ - -#ifndef _SECURITY_SECIDENTITY_H_ -#define _SECURITY_SECIDENTITY_H_ - -#include -#include - -__BEGIN_DECLS - -/*! - @function SecIdentityGetTypeID - @abstract Returns the type identifier of SecIdentity instances. - @result The CFTypeID of SecIdentity instances. -*/ -CFTypeID SecIdentityGetTypeID(void) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -/*! - @function SecIdentityCopyCertificate - @abstract Returns a reference to a certificate for the given identity - reference. - @param identityRef An identity reference. - @param certificateRef On return, a pointer to the found certificate - reference. - @result A result code. See "Security Error Codes" (SecBase.h). -*/ -OSStatus SecIdentityCopyCertificate( - SecIdentityRef identityRef, - SecCertificateRef *certificateRef) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -/*! - @function SecIdentityCopyPrivateKey - @abstract Returns the private key associated with an identity. - @param identityRef An identity reference. - @param privateKeyRef On return, a pointer to the private key for the given - identity. The private key must be of class type kSecAppleKeyItemClass. - @result A result code. See "Security Error Codes" (SecBase.h). -*/ -OSStatus SecIdentityCopyPrivateKey( - SecIdentityRef identityRef, - SecKeyRef *privateKeyRef) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -__END_DECLS - -#endif /* !_SECURITY_SECIDENTITY_H_ */ diff --git a/sec/Security/SecIdentityPriv.h b/sec/Security/SecIdentityPriv.h deleted file mode 100644 index 57dfd1b6..00000000 --- a/sec/Security/SecIdentityPriv.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2007-2008,2010 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 SecIdentityPriv - The functions provided in SecIdentityPriv.h implement a convenient way to - match private keys with certificates. -*/ - -#ifndef _SECURITY_SECIDENTITYPRIV_H_ -#define _SECURITY_SECIDENTITYPRIV_H_ - -#include -#include - -__BEGIN_DECLS - -/*! @function SecIdentityCreate. - @abstract create a new identity object from the passed-in certificate - and private key. - @discussion this function will most likely become private SPI soon. -*/ -SecIdentityRef SecIdentityCreate(CFAllocatorRef allocator, - SecCertificateRef certificate, SecKeyRef privateKey); - -__END_DECLS - -#endif /* !_SECURITY_SECIDENTITYPRIV_H_ */ diff --git a/sec/Security/SecImportExport.c b/sec/Security/SecImportExport.c deleted file mode 100644 index aebc2e54..00000000 --- a/sec/Security/SecImportExport.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2007-2008 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "p12import.h" -#include "SecImportExport.h" - -CFStringRef kSecImportExportPassphrase = CFSTR("passphrase"); -CFStringRef kSecImportItemLabel = CFSTR("label"); -CFStringRef kSecImportItemKeyID = CFSTR("keyid"); -CFStringRef kSecImportItemTrust = CFSTR("trust"); -CFStringRef kSecImportItemCertChain = CFSTR("chain"); -CFStringRef kSecImportItemIdentity = CFSTR("identity"); - - -static void collect_certs(const void *key, const void *value, void *context) -{ - if (!CFDictionaryContainsKey(value, CFSTR("key"))) { - CFDataRef cert_bytes = CFDictionaryGetValue(value, CFSTR("cert")); - if (!cert_bytes) - return; - SecCertificateRef cert = - SecCertificateCreateWithData(kCFAllocatorDefault, cert_bytes); - if (!cert) - return; - CFMutableArrayRef cert_array = (CFMutableArrayRef)context; - CFArrayAppendValue(cert_array, cert); - CFRelease(cert); - } -} - -typedef struct { - CFMutableArrayRef identities; - CFArrayRef certs; -} build_trust_chains_context; - -static void build_trust_chains(const void *key, const void *value, - void *context) -{ - CFMutableDictionaryRef identity_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, - 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - SecKeyRef private_key = NULL; - SecCertificateRef cert = NULL; - SecIdentityRef identity = NULL; - SecPolicyRef policy = NULL; - CFMutableArrayRef cert_chain = NULL, eval_chain = NULL; - SecTrustRef trust = NULL; - build_trust_chains_context * a_build_trust_chains_context = (build_trust_chains_context*)context; - - CFDataRef key_bytes = CFDictionaryGetValue(value, CFSTR("key")); - require(key_bytes, out); - CFDataRef cert_bytes = CFDictionaryGetValue(value, CFSTR("cert")); - require(cert_bytes, out); - CFDataRef algoid_bytes = CFDictionaryGetValue(value, CFSTR("algid")); - - - DERItem algorithm = { (DERByte *)CFDataGetBytePtr(algoid_bytes), CFDataGetLength(algoid_bytes) }; - if (DEROidCompare(&oidEcPubKey, &algorithm)) { - require (private_key = SecKeyCreateECPrivateKey(kCFAllocatorDefault, - CFDataGetBytePtr(key_bytes), CFDataGetLength(key_bytes), - kSecKeyEncodingPkcs1), out); - } else if (DEROidCompare(&oidRsa, &algorithm)) { - require (private_key = SecKeyCreateRSAPrivateKey(kCFAllocatorDefault, - CFDataGetBytePtr(key_bytes), CFDataGetLength(key_bytes), - kSecKeyEncodingPkcs1), out); - } else { - goto out; - } - - require(cert = SecCertificateCreateWithData(kCFAllocatorDefault, cert_bytes), out); - require(identity = SecIdentityCreate(kCFAllocatorDefault, cert, private_key), out); - CFDictionarySetValue(identity_dict, kSecImportItemIdentity, identity); - - eval_chain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - require(eval_chain, out); - CFArrayAppendValue(eval_chain, cert); - CFRange all_certs = { 0, CFArrayGetCount(a_build_trust_chains_context->certs) }; - CFArrayAppendArray(eval_chain, a_build_trust_chains_context->certs, all_certs); - require(policy = SecPolicyCreateBasicX509(), out); - SecTrustResultType result; - SecTrustCreateWithCertificates(eval_chain, policy, &trust); - require(trust, out); - SecTrustEvaluate(trust, &result); - CFDictionarySetValue(identity_dict, kSecImportItemTrust, trust); - - require(cert_chain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks), out); - CFIndex cert_chain_length = SecTrustGetCertificateCount(trust); - int i; - for (i = 0; i < cert_chain_length; i++) - CFArrayAppendValue(cert_chain, SecTrustGetCertificateAtIndex(trust, i)); - CFDictionarySetValue(identity_dict, kSecImportItemCertChain, cert_chain); - - CFArrayAppendValue(a_build_trust_chains_context->identities, identity_dict); -out: - CFReleaseSafe(identity_dict); - CFReleaseSafe(identity); - CFReleaseSafe(private_key); - CFReleaseSafe(cert); - CFReleaseSafe(policy); - CFReleaseSafe(cert_chain); - CFReleaseSafe(eval_chain); - CFReleaseSafe(trust); -} - -OSStatus SecPKCS12Import(CFDataRef pkcs12_data, CFDictionaryRef options, CFArrayRef *items) -{ - pkcs12_context context = {}; - SecAsn1CoderCreate(&context.coder); - if (options) - context.passphrase = CFDictionaryGetValue(options, kSecImportExportPassphrase); - context.items = CFDictionaryCreateMutable(kCFAllocatorDefault, - 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - int status = p12decode(&context, pkcs12_data); - if (!status) { - CFMutableArrayRef certs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFDictionaryApplyFunction(context.items, collect_certs, certs); - - CFMutableArrayRef identities = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - build_trust_chains_context a_build_trust_chains_context = { identities, certs }; - CFDictionaryApplyFunction(context.items, build_trust_chains, &a_build_trust_chains_context); - CFReleaseSafe(certs); - - /* ignoring certs that weren't picked up as part of the certchain for found keys */ - - *items = identities; - } - - CFReleaseSafe(context.items); - SecAsn1CoderRelease(context.coder); - - switch (status) { - case p12_noErr: return errSecSuccess; - case p12_passwordErr: return errSecAuthFailed; - case p12_decodeErr: return errSecDecode; - default: return errSecInternal; - }; - return errSecSuccess; -} - diff --git a/sec/Security/SecImportExport.h b/sec/Security/SecImportExport.h deleted file mode 100644 index dc127a97..00000000 --- a/sec/Security/SecImportExport.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2007-2009 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 SecImportExport - contains import/export functionality for keys and certificates. -*/ - -#ifndef _SECURITY_SECIMPORTEXPORT_H_ -#define _SECURITY_SECIMPORTEXPORT_H_ - -#include -#include -#include -#include - -__BEGIN_DECLS - -/*! - @enum Import/Export options - @discussion Predefined key constants used to pass in arguments to the - import/export functions - @constant kSecImportExportPassphrase Specifies a passphrase represented by - a CFStringRef to be used to encrypt/decrypt. -*/ -extern CFStringRef kSecImportExportPassphrase - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @enum Import/Export item description - @discussion Predefined key constants used to pass back a CFArray with a - CFDictionary per item. - - @constant kSecImportItemLabel a CFStringRef representing the item label. - This implementation specific identifier cannot be expected to have - any format. - @constant kSecImportItemKeyID a CFDataRef representing the key id. Often - the SHA-1 digest of the public key. - @constant kSecImportItemIdentity a SecIdentityRef representing the identity. - @constant kSecImportItemTrust a SecTrustRef set up with all relevant - certificates. Not guaranteed to succesfully evaluate. - @constant kSecImportItemCertChain a CFArrayRef holding all relevant - certificates for this item's identity -*/ -extern CFStringRef kSecImportItemLabel - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFStringRef kSecImportItemKeyID - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFStringRef kSecImportItemTrust - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFStringRef kSecImportItemCertChain - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFStringRef kSecImportItemIdentity - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @function SecPKCS12Import - @abstract return contents of a PKCS#12 formatted blob. - @param pkcs12_data PKCS#12 formatted data - @param options Dictionary containing options for decode. A - kSecImportExportPassphrase is required at a minimum. Only password- - based PKCS#12 blobs are currently supported. - @param items Array containing a dictionary for every item extracted. See - kSecImportItem constants. - @result errSecSuccess in case of success. errSecDecode means either the - blob can't be read or it is malformed. errSecAuthFailed means an - incorrect password was passed, or data in the container got damaged. -*/ -OSStatus SecPKCS12Import(CFDataRef pkcs12_data, CFDictionaryRef options, - CFArrayRef *items) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -__END_DECLS - -#endif /* !_SECURITY_SECIMPORTEXPORT_H_ */ diff --git a/sec/Security/SecInternal.h b/sec/Security/SecInternal.h deleted file mode 100644 index 2d89ba63..00000000 --- a/sec/Security/SecInternal.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2007,2009-2010 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 SecInternal - SecInternal defines common internal constants macros and SPI functions. -*/ - -#ifndef _SECURITY_SECINTERNAL_H_ -#define _SECURITY_SECINTERNAL_H_ - -#include -#include -#include - -#include "utilities/SecCFRelease.h" - -__BEGIN_DECLS - -#define DICT_DECLARE(MAXVALUES) \ - CFIndex numValues = 0, maxValues = (MAXVALUES); \ - const void *keys[maxValues]; \ - const void *values[maxValues]; - -#define DICT_ADDPAIR(KEY,VALUE) do { \ - if (numValues < maxValues) { \ - keys[numValues] = (KEY); \ - values[numValues] = (VALUE); \ - numValues++; \ - } else \ - assert(false); \ -} while(0) - -#define DICT_CREATE(ALLOCATOR) CFDictionaryCreate((ALLOCATOR), keys, values, \ - numValues, NULL, &kCFTypeDictionaryValueCallBacks) - -/* Non valid CFTimeInterval or CFAbsoluteTime. */ -#define NULL_TIME 0.0 - - -static inline CFIndex getIntValue(CFTypeRef cf) { - if (cf) { - if (CFGetTypeID(cf) == CFNumberGetTypeID()) { - CFIndex value; - CFNumberGetValue(cf, kCFNumberCFIndexType, &value); - return value; - } else if (CFGetTypeID(cf) == CFStringGetTypeID()) { - return CFStringGetIntValue(cf); - } - } - return -1; -} - -__END_DECLS - -#endif /* !_SECURITY_SECINTERNAL_H_ */ diff --git a/sec/Security/SecItem.h b/sec/Security/SecItem.h deleted file mode 100644 index 0afcc9ed..00000000 --- a/sec/Security/SecItem.h +++ /dev/null @@ -1,973 +0,0 @@ -/* - * Copyright (c) 2006-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@ - */ - -/*! - @header SecItem - SecItem defines CoreFoundation-based constants and functions for - access to Security items (certificates, keys, identities, and - passwords.) -*/ - -#ifndef _SECURITY_SECITEM_H_ -#define _SECURITY_SECITEM_H_ - -#include -#include -#include - -__BEGIN_DECLS - -/*! - @enum Class Key Constant - @discussion Predefined key constant used to get or set item class values in - a dictionary. Its value is one of the constants defined in the Value - Constants for kSecClass. - @constant kSecClass Specifies a dictionary key whose value is the item's - class code. You use this key to get or set a value of type CFTypeRef - that contains the item class code. -*/ -extern CFTypeRef kSecClass - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @enum Class Value Constants - @discussion Predefined item class constants used to get or set values in - a dictionary. The kSecClass constant is the key and its value is one - of the constants defined here. - @constant kSecClassGenericPassword Specifies generic password items. - @constant kSecClassInternetPassword Specifies Internet password items. - @constant kSecClassCertificate Specifies certificate items. - @constant kSecClassKey Specifies key items. - @constant kSecClassIdentity Specifies identity items. -*/ -extern CFTypeRef kSecClassGenericPassword - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); -extern CFTypeRef kSecClassInternetPassword - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecClassCertificate - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); -extern CFTypeRef kSecClassKey - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); -extern CFTypeRef kSecClassIdentity - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - - -/*! - @enum Attribute Key Constants - @discussion Predefined item attribute keys used to get or set values in a - dictionary. Not all attributes apply to each item class. The table - below lists the currently defined attributes for each item class: - - kSecClassGenericPassword item attributes: - kSecAttrAccessible - kSecAttrAccessGroup - kSecAttrCreationDate - kSecAttrModificationDate - kSecAttrDescription - kSecAttrComment - kSecAttrCreator - kSecAttrType - kSecAttrLabel - kSecAttrIsInvisible - kSecAttrIsNegative - kSecAttrAccount - kSecAttrService - kSecAttrGeneric - - kSecClassInternetPassword item attributes: - kSecAttrAccessible - kSecAttrAccessGroup - kSecAttrCreationDate - kSecAttrModificationDate - kSecAttrDescription - kSecAttrComment - kSecAttrCreator - kSecAttrType - kSecAttrLabel - kSecAttrIsInvisible - kSecAttrIsNegative - kSecAttrAccount - kSecAttrSecurityDomain - kSecAttrServer - kSecAttrProtocol - kSecAttrAuthenticationType - kSecAttrPort - kSecAttrPath - - kSecClassCertificate item attributes: - kSecAttrAccessible - kSecAttrAccessGroup - kSecAttrCertificateType - kSecAttrCertificateEncoding - kSecAttrLabel - kSecAttrSubject - kSecAttrIssuer - kSecAttrSerialNumber - kSecAttrSubjectKeyID - kSecAttrPublicKeyHash - - kSecClassKey item attributes: - kSecAttrAccessible - kSecAttrAccessGroup - kSecAttrKeyClass - kSecAttrLabel - kSecAttrApplicationLabel - kSecAttrIsPermanent - kSecAttrApplicationTag - kSecAttrKeyType - kSecAttrKeySizeInBits - kSecAttrEffectiveKeySize - kSecAttrCanEncrypt - kSecAttrCanDecrypt - kSecAttrCanDerive - kSecAttrCanSign - kSecAttrCanVerify - kSecAttrCanWrap - kSecAttrCanUnwrap - - kSecClassIdentity item attributes: - Since an identity is the combination of a private key and a - certificate, this class shares attributes of both kSecClassKey and - kSecClassCertificate. - - @constant kSecAttrAccessible Specifies a dictionary key whose value - indicates when your application needs access to an item's data. You - should choose the most restrictive option that meets your application's - needs to allow the system to protect that item in the best way possible. - See the "kSecAttrAccessible Value Constants" section for a list of - values which can be specified. - IMPORTANT: This attribute is currently not supported for OS X keychain - items, unless the kSecAttrSynchronizable attribute is also present. If - both attributes are specified on either OS X or iOS, the value for the - kSecAttrAccessible key may only be one whose name does not end with - "ThisDeviceOnly", as those cannot sync to another device. - - @constant kSecAttrAccessGroup Specifies a dictionary key whose value is - a CFStringRef indicating which access group a item is in. The access - groups that a particular application has membership in are determined by - two entitlements for that application. The application-identifier - entitlement contains the application's single access group, unless - there is a keychain-access-groups entitlement present. The latter - has as its value a list of access groups; the first item in this list - is the default access group. Unless a specific access group is provided - as the value of kSecAttrAccessGroup when SecItemAdd is called, new items - are created in the application's default access group. Specifying this - attribute in SecItemCopyMatching, SecItemUpdate, or SecItemDelete calls - limits the search to the specified access group (of which the calling - application must be a member to obtain matching results.) To share - keychain items between multiple applications, each application must have - a common group listed in its keychain-access-groups entitlement, and each - must specify this shared access group name as the value for the - kSecAttrAccessGroup key in the dictionary passed to SecItem functions. - - @constant kSecAttrSynchronizable Specifies a dictionary key whose value is - a CFBooleanRef indicating whether the item in question can be synchronized. - To add a new item which can be synced to other devices, or to obtain - synchronizable results from a query, supply this key with a value of - kCFBooleanTrue. If the key is not supplied, or has a value of - kCFBooleanFalse, then no synchronizable items will be added or returned. - A predefined value, kSecAttrSynchronizableAny, may be provided instead of - kCFBooleanTrue if both synchronizable and non-synchronizable results are - desired. - - IMPORTANT: Specifying the kSecAttrSynchronizable key has several caveats: - - - Updating or deleting items using the kSecAttrSynchronizable key will - affect all copies of the item, not just the one on your local device. - Be sure that it makes sense to use the same password on all devices - before deciding to make a password synchronizable. - - Only password items can currently be synchronized. Keychain syncing - is not supported for certificates or cryptographic keys. - - Items stored or obtained using the kSecAttrSynchronizable key cannot - specify SecAccessRef-based access control with kSecAttrAccess. If a - password is intended to be shared between multiple applications, the - kSecAttrAccessGroup key must be specified, and each application - using this password must have a 'keychain-access-groups' entitlement - with the specified access group value. - - Items stored or obtained using the kSecAttrSynchronizable key may - not also specify a kSecAttrAccessible value which is incompatible - with syncing (namely, those whose names end with "ThisDeviceOnly".) - - Items stored or obtained using the kSecAttrSynchronizable key cannot - be specified by reference. You must pass kSecReturnAttributes and/or - kSecReturnData to retrieve results; kSecReturnRef is currently not - supported for synchronizable items. - - Persistent references to synchronizable items should be avoided; - while they may work locally, they cannot be moved between devices, - and may not resolve if the item is modified on some other device. - - When specifying a query that uses the kSecAttrSynchronizable key, - search keys are limited to the item's class and attributes. - The only search constant which may be used is kSecMatchLimit; other - constants using the kSecMatch prefix are not supported at this time. - - @constant kSecAttrSynchronizableAny Specifies that both synchronizable and - non-synchronizable results should be returned from this query. This may be - used as a value for the kSecAttrSynchronizable dictionary key in a call to - SecItemCopyMatching, SecItemUpdate, or SecItemDelete. - - @constant kSecAttrCreationDate (read-only) Specifies a dictionary key whose - value is the item's creation date. You use this key to get a value - of type CFDateRef that represents the date the item was created. - @constant kSecAttrModificationDate (read-only) Specifies a dictionary key - whose value is the item's modification date. You use this key to get - a value of type CFDateRef that represents the last time the item was - updated. - @constant kSecAttrDescription Specifies a dictionary key whose value is - the item's description attribute. You use this key to set or get a - value of type CFStringRef that represents a user-visible string - describing this particular kind of item (e.g., "disk image password"). - @constant kSecAttrComment Specifies a dictionary key whose value is the - item's comment attribute. You use this key to set or get a value of - type CFStringRef containing the user-editable comment for this item. - @constant kSecAttrCreator Specifies a dictionary key whose value is the - item's creator attribute. You use this key to set or get a value of - type CFNumberRef that represents the item's creator. This number is - the unsigned integer representation of a four-character code (e.g., - 'aCrt'). - @constant kSecAttrType Specifies a dictionary key whose value is the item's - type attribute. You use this key to set or get a value of type - CFNumberRef that represents the item's type. This number is the - unsigned integer representation of a four-character code (e.g., - 'aTyp'). - @constant kSecAttrLabel Specifies a dictionary key whose value is the - item's label attribute. You use this key to set or get a value of - type CFStringRef containing the user-visible label for this item. - @constant kSecAttrIsInvisible Specifies a dictionary key whose value is the - item's invisible attribute. You use this key to set or get a value - of type CFBooleanRef that indicates whether the item is invisible - (i.e., should not be displayed.) - @constant kSecAttrIsNegative Specifies a dictionary key whose value is the - item's negative attribute. You use this key to set or get a value of - type CFBooleanRef that indicates whether there is a valid password - associated with this keychain item. This is useful if your application - doesn't want a password for some particular service to be stored in - the keychain, but prefers that it always be entered by the user. - @constant kSecAttrAccount Specifies a dictionary key whose value is the - item's account attribute. You use this key to set or get a CFStringRef - that contains an account name. (Items of class - kSecClassGenericPassword, kSecClassInternetPassword have this - attribute.) - @constant kSecAttrService Specifies a dictionary key whose value is the - item's service attribute. You use this key to set or get a CFStringRef - that represents the service associated with this item. (Items of class - kSecClassGenericPassword have this attribute.) - @constant kSecAttrGeneric Specifies a dictionary key whose value is the - item's generic attribute. You use this key to set or get a value of - CFDataRef that contains a user-defined attribute. (Items of class - kSecClassGenericPassword have this attribute.) - @constant kSecAttrSecurityDomain Specifies a dictionary key whose value - is the item's security domain attribute. You use this key to set or - get a CFStringRef value that represents the Internet security domain. - (Items of class kSecClassInternetPassword have this attribute.) - @constant kSecAttrServer Specifies a dictionary key whose value is the - item's server attribute. You use this key to set or get a value of - type CFStringRef that contains the server's domain name or IP address. - (Items of class kSecClassInternetPassword have this attribute.) - @constant kSecAttrProtocol Specifies a dictionary key whose value is the - item's protocol attribute. You use this key to set or get a value of - type CFNumberRef that denotes the protocol for this item (see the - SecProtocolType enum in SecKeychainItem.h). (Items of class - kSecClassInternetPassword have this attribute.) - @constant kSecAttrAuthenticationType Specifies a dictionary key whose value - is the item's authentication type attribute. You use this key to set - or get a value of type CFNumberRef that denotes the authentication - scheme for this item (see the kSecAttrAuthenticationType value - constants below). - @constant kSecAttrPort Specifies a dictionary key whose value is the item's - port attribute. You use this key to set or get a CFNumberRef value - that represents an Internet port number. (Items of class - kSecClassInternetPassword have this attribute.) - @constant kSecAttrPath Specifies a dictionary key whose value is the item's - path attribute, typically this is the path component of the URL. You use - this key to set or get a CFStringRef value that represents a path. (Items - of class kSecClassInternetPassword have this attribute.) - @constant kSecAttrSubject (read-only) Specifies a dictionary key whose - value is the item's subject. You use this key to get a value of type - CFDataRef that contains the X.500 subject name of a certificate. - (Items of class kSecClassCertificate have this attribute.) - @constant kSecAttrIssuer (read-only) Specifies a dictionary key whose value - is the item's issuer. You use this key to get a value of type - CFDataRef that contains the X.500 issuer name of a certificate. (Items - of class kSecClassCertificate have this attribute.) - @constant kSecAttrSerialNumber (read-only) Specifies a dictionary key whose - value is the item's serial number. You use this key to get a value - of type CFDataRef that contains the serial number data of a - certificate. (Items of class kSecClassCertificate have this - attribute.) - @constant kSecAttrSubjectKeyID (read-only) Specifies a dictionary key whose - value is the item's subject key ID. You use this key to get a value - of type CFDataRef that contains the subject key ID of a certificate. - (Items of class kSecClassCertificate have this attribute.) - @constant kSecAttrPublicKeyHash (read-only) Specifies a dictionary key - whose value is the item's public key hash. You use this key to get a - value of type CFDataRef that contains the hash of a certificate's - public key. (Items of class kSecClassCertificate have this attribute.) - @constant kSecAttrCertificateType (read-only) Specifies a dictionary key - whose value is the item's certificate type. You use this key to get - a value of type CFNumberRef that denotes the certificate type - (Currently only the value of this attribute must be equal to the - version of the X509 certificate. So 1 for v1 2 for v2 and 3 for v3 - certificates). Only items of class kSecClassCertificate have this - attribute. - @constant kSecAttrCertificateEncoding (read-only) Specifies a dictionary - key whose value is the item's certificate encoding. You use this key - to get a value of type CFNumberRef that denotes the certificate - encoding (Currently only the value 3 meaning - kSecAttrCertificateEncodingDER is supported). Only items of class - kSecClassCertificate have this attribute. - @constant kSecAttrKeyClass (read only) Specifies a dictionary key whose - value is one of kSecAttrKeyClassPublic, kSecAttrKeyClassPrivate or - kSecAttrKeyClassSymmetric. - @constant kSecAttrApplicationLabel Specifies a dictionary key whose value - is the key's application label attribute. This is different from the - kSecAttrLabel (which is intended to be human-readable). This attribute - is used to look up a key programmatically; in particular, for keys of - class kSecAttrKeyClassPublic and kSecAttrKeyClassPrivate, the value of - this attribute is the hash of the public key. - @constant kSecAttrIsPermanent Specifies a dictionary key whose value is a - CFBooleanRef indicating whether the key in question will be stored - permanently. - @constant kSecAttrApplicationTag Specifies a dictionary key whose value is a - CFDataRef containing private tag data. - @constant kSecAttrKeyType Specifies a dictionary key whose value is a - CFNumberRef indicating the algorithm associated with this key - (Currently only the value 42 is supported, alternatively you can use - kSecAttrKeyTypeRSA). - @constant kSecAttrKeySizeInBits Specifies a dictionary key whose value - is a CFNumberRef indicating the number of bits in this key. - @constant kSecAttrEffectiveKeySize Specifies a dictionary key whose value - is a CFNumberRef indicating the effective number of bits in this key. - For example, a DES key has a kSecAttrKeySizeInBits of 64, but a - kSecAttrEffectiveKeySize of 56 bits. - @constant kSecAttrCanEncrypt Specifies a dictionary key whole value is a - CFBooleanRef indicating whether the key in question can be used to - encrypt data. - @constant kSecAttrCanDecrypt Specifies a dictionary key whose value is a - CFBooleanRef indicating whether the key in question can be used to - decrypt data. - @constant kSecAttrCanDerive Specifies a dictionary key whole value is a - CFBooleanRef indicating whether the key in question can be used to - derive another key. - @constant kSecAttrCanSign Specifies a dictionary key whole value is a - CFBooleanRef indicating whether the key in question can be used to - create a digital signature. - @constant kSecAttrCanVerify Specifies a dictionary key whole value is a - CFBooleanRef indicating whether the key in question can be used to - verify a digital signature. - @constant kSecAttrCanWrap Specifies a dictionary key whole value is a - CFBooleanRef indicating whether the key in question can be used to - wrap another key. - @constant kSecAttrCanUnwrap Specifies a dictionary key whole value is a - CFBooleanRef indicating whether the key in question can be used to - unwrap another key. -*/ -extern CFTypeRef kSecAttrAccessible - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); -extern CFTypeRef kSecAttrAccessGroup - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_3_0); -extern CFTypeRef kSecAttrSynchronizable - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecAttrSynchronizableAny - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecAttrCreationDate - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrModificationDate - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrDescription - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrComment - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrCreator - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrType - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrLabel - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrIsInvisible - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrIsNegative - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrAccount - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrService - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrGeneric - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrSecurityDomain - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrServer - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocol - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrAuthenticationType - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrPort - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrPath - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrSubject - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrIssuer - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrSerialNumber - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrSubjectKeyID - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrPublicKeyHash - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrCertificateType - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrCertificateEncoding - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrKeyClass - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrApplicationLabel - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrIsPermanent - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrApplicationTag - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrKeyType - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrKeySizeInBits - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrEffectiveKeySize - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrCanEncrypt - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrCanDecrypt - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrCanDerive - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrCanSign - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrCanVerify - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrCanWrap - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrCanUnwrap - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @enum kSecAttrAccessible Value Constants - @discussion Predefined item attribute constants used to get or set values - in a dictionary. The kSecAttrAccessible constant is the key and its - value is one of the constants defined here. - When asking SecItemCopyMatching to return the item's data, the error - errSecInteractionNotAllowed will be returned if the item's data is not - available until a device unlock occurs. - @constant kSecAttrAccessibleWhenUnlocked Item data can only be accessed - while the device is unlocked. This is recommended for items that only - need be accesible while the application is in the foreground. Items - with this attribute will migrate to a new device when using encrypted - backups. - @constant kSecAttrAccessibleAfterFirstUnlock Item data can only be - accessed once the device has been unlocked after a restart. This is - recommended for items that need to be accesible by background - applications. Items with this attribute will migrate to a new device - when using encrypted backups. - @constant kSecAttrAccessibleAlways Item data can always be accessed - regardless of the lock state of the device. This is not recommended - for anything except system use. Items with this attribute will migrate - to a new device when using encrypted backups. - @constant kSecAttrAccessibleWhenUnlockedThisDeviceOnly Item data can only - be accessed while the device is unlocked. This is recommended for items - that only need be accesible while the application is in the foreground. - Items with this attribute will never migrate to a new device, so after - a backup is restored to a new device, these items will be missing. - @constant kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly Item data can - only be accessed once the device has been unlocked after a restart. - This is recommended for items that need to be accessible by background - applications. Items with this attribute will never migrate to a new - device, so after a backup is restored to a new device these items will - be missing. - @constant kSecAttrAccessibleAlwaysThisDeviceOnly Item data can always - be accessed regardless of the lock state of the device. This option - is not recommended for anything except system use. Items with this - attribute will never migrate to a new device, so after a backup is - restored to a new device, these items will be missing. -*/ -extern CFTypeRef kSecAttrAccessibleWhenUnlocked - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); -extern CFTypeRef kSecAttrAccessibleAfterFirstUnlock - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); -extern CFTypeRef kSecAttrAccessibleAlways - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); -extern CFTypeRef kSecAttrAccessibleWhenUnlockedThisDeviceOnly - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); -extern CFTypeRef kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); -extern CFTypeRef kSecAttrAccessibleAlwaysThisDeviceOnly - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); - -/*! - @enum kSecAttrProtocol Value Constants - @discussion Predefined item attribute constants used to get or set values - in a dictionary. The kSecAttrProtocol constant is the key and its - value is one of the constants defined here. - @constant kSecAttrProtocolFTP. - @constant kSecAttrProtocolFTPAccount. - @constant kSecAttrProtocolHTTP. - @constant kSecAttrProtocolIRC. - @constant kSecAttrProtocolNNTP. - @constant kSecAttrProtocolPOP3. - @constant kSecAttrProtocolSMTP. - @constant kSecAttrProtocolSOCKS. - @constant kSecAttrProtocolIMAP. - @constant kSecAttrProtocolLDAP. - @constant kSecAttrProtocolAppleTalk. - @constant kSecAttrProtocolAFP. - @constant kSecAttrProtocolTelnet. - @constant kSecAttrProtocolSSH. - @constant kSecAttrProtocolFTPS. - @constant kSecAttrProtocolHTTPS. - @constant kSecAttrProtocolHTTPProxy. - @constant kSecAttrProtocolHTTPSProxy. - @constant kSecAttrProtocolFTPProxy. - @constant kSecAttrProtocolSMB. - @constant kSecAttrProtocolRTSP. - @constant kSecAttrProtocolRTSPProxy. - @constant kSecAttrProtocolDAAP. - @constant kSecAttrProtocolEPPC. - @constant kSecAttrProtocolIPP. - @constant kSecAttrProtocolNNTPS. - @constant kSecAttrProtocolLDAPS. - @constant kSecAttrProtocolTelnetS. - @constant kSecAttrProtocolIMAPS. - @constant kSecAttrProtocolIRCS. - @constant kSecAttrProtocolPOP3S. -*/ -extern CFTypeRef kSecAttrProtocolFTP - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolFTPAccount - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolHTTP - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolIRC - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolNNTP - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolPOP3 - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolSMTP - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolSOCKS - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolIMAP - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolLDAP - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolAppleTalk - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolAFP - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolTelnet - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolSSH - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolFTPS - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolHTTPS - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolHTTPProxy - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolHTTPSProxy - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolFTPProxy - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolSMB - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolRTSP - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolRTSPProxy - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolDAAP - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolEPPC - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolIPP - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolNNTPS - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolLDAPS - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolTelnetS - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolIMAPS - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolIRCS - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrProtocolPOP3S - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @enum kSecAttrAuthenticationType Value Constants - @discussion Predefined item attribute constants used to get or set values - in a dictionary. The kSecAttrAuthenticationType constant is the key - and its value is one of the constants defined here. - @constant kSecAttrAuthenticationTypeNTLM. - @constant kSecAttrAuthenticationTypeMSN. - @constant kSecAttrAuthenticationTypeDPA. - @constant kSecAttrAuthenticationTypeRPA. - @constant kSecAttrAuthenticationTypeHTTPBasic. - @constant kSecAttrAuthenticationTypeHTTPDigest. - @constant kSecAttrAuthenticationTypeHTMLForm. - @constant kSecAttrAuthenticationTypeDefault. -*/ -extern CFTypeRef kSecAttrAuthenticationTypeNTLM - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrAuthenticationTypeMSN - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrAuthenticationTypeDPA - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrAuthenticationTypeRPA - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrAuthenticationTypeHTTPBasic - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrAuthenticationTypeHTTPDigest - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrAuthenticationTypeHTMLForm - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecAttrAuthenticationTypeDefault - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @enum kSecAttrKeyClass Value Constants - @discussion Predefined item attribute constants used to get or set values - in a dictionary. The kSecAttrKeyClass constant is the key - and its value is one of the constants defined here. - @constant kSecAttrKeyClassPublic. - @constant kSecAttrKeyClassPrivate. - @constant kSecAttrKeyClassSymmetric. -*/ -extern CFTypeRef kSecAttrKeyClassPublic - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); -extern CFTypeRef kSecAttrKeyClassPrivate - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); -extern CFTypeRef kSecAttrKeyClassSymmetric - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - -/*! - @enum kSecAttrKeyType Value Constants - @discussion Predefined item attribute constants used to get or set values - in a dictionary. The kSecAttrKeyType constant is the key - and its value is one of the constants defined here. - @constant kSecAttrKeyTypeRSA. - @constant kSecAttrKeyTypeEC. -*/ -extern CFTypeRef kSecAttrKeyTypeRSA - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); -extern CFTypeRef kSecAttrKeyTypeEC - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); - -/*! - @enum Search Constants - @discussion Predefined search constants used to set values in a query - dictionary. You can specify a combination of search attributes and - item attributes when looking for matching items with the - SecItemCopyMatching function. - @constant kSecMatchPolicy Specifies a dictionary key whose value is a - SecPolicyRef. If provided, returned certificates or identities must - verify with this policy. - @constant kSecMatchIssuers Specifies a dictionary key whose value is a - CFArray of X.500 names (of type CFDataRef). If provided, returned - certificates or identities will be limited to those whose - certificate chain contains one of the issuers provided in this list. - @constant kSecMatchEmailAddressIfPresent Specifies a dictionary key whose - value is a CFStringRef containing an RFC822 email address. If - provided, returned certificates or identities will be limited to those - that contain the address, or do not contain any email address. - @constant kSecMatchSubjectContains Specifies a dictionary key whose value - is a CFStringRef. If provided, returned certificates or identities - will be limited to those containing this string in the subject. - @constant kSecMatchCaseInsensitive Specifies a dictionary key whose value - is a CFBooleanRef. If this value is kCFBooleanFalse, or is not - provided, then case-sensitive string matching is performed. - @constant kSecMatchTrustedOnly Specifies a dictionary key whose value is - a CFBooleanRef. If provided with a value of kCFBooleanTrue, only - certificates which can be verified back to a trusted anchor will be - returned. If this value is kCFBooleanFalse, or is not provided, then - both trusted and untrusted certificates may be returned. - @constant kSecMatchValidOnDate Specifies a dictionary key whose value is - of type CFDateRef. If provided, returned keys, certificates or - identities will be limited to those which are valid for the given date. - Pass a value of kCFNull to indicate the current date. - @constant kSecMatchLimit Specifies a dictionary key whose value is a - CFNumberRef. If provided, this value specifies the maximum number of - results to return. If not provided, results are limited to the first - item found. Predefined values are provided for a single item - (kSecMatchLimitOne) and all matching items (kSecMatchLimitAll). - @constant kSecMatchLimitOne Specifies that results are limited to the first - item found; used as a value for the kSecMatchLimit dictionary key. - @constant kSecMatchLimitAll Specifies that an unlimited number of results - may be returned; used as a value for the kSecMatchLimit dictionary - key. -*/ -extern CFTypeRef kSecMatchPolicy - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecMatchItemList - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecMatchSearchList - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecMatchIssuers - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecMatchEmailAddressIfPresent - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecMatchSubjectContains - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecMatchCaseInsensitive - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecMatchTrustedOnly - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecMatchValidOnDate - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecMatchLimit - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecMatchLimitOne - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecMatchLimitAll - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - - -/*! - @enum Return Type Key Constants - @discussion Predefined return type keys used to set values in a dictionary. - You use these keys to specify the type of results which should be - returned by the SecItemCopyMatching or SecItemAdd function. You can - specify zero or more of these return types. If more than one of these - result types is specified, the result is returned as a CFDictionaryRef - whose keys are the result types and values are the requested data. - @constant kSecReturnData Specifies a dictionary key whose value is of type - CFBooleanRef. A value of kCFBooleanTrue indicates that the data of - an item (CFDataRef) should be returned. For keys and password - items, data is secret (encrypted) and may require the user to enter - a password for access. - @constant kSecReturnAttributes Specifies a dictionary key whose value is - of type CFBooleanRef. A value of kCFBooleanTrue indicates that the - (non-encrypted) attributes of an item (CFDictionaryRef) should be - returned. - @constant kSecReturnRef Specifies a dictionary key whose value is a - CFBooleanRef. A value of kCFBooleanTrue indicates that a reference - should be returned. Depending on the item class requested, the - returned reference(s) may be of type SecKeychainItemRef, SecKeyRef, - SecCertificateRef, or SecIdentityRef. - @constant kSecReturnPersistentRef Specifies a dictionary key whose value - is of type CFBooleanRef. A value of kCFBooleanTrue indicates that a - persistent reference to an item (CFDataRef) should be returned. -*/ -extern CFTypeRef kSecReturnData - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecReturnAttributes - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecReturnRef - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecReturnPersistentRef - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - - -/*! - @enum Value Type Key Constants - @discussion Predefined value type keys used to pass values in a dictionary. - You can specify zero or more of these types depending on the function - you are calling. For SecItemCopyMatching or SecItemAdd these are - used as keys in the results dictionary. - @constant kSecValueData Specifies a dictionary key whose value is of type - CFDataRef. For keys and password items, data is secret (encrypted) - and may require the user to enter a password for access. - @constant kSecValueRef Specifies a dictionary key whose value, depending - on the item class requested, is of type SecKeychainItemRef, SecKeyRef, - SecCertificateRef, or SecIdentityRef. - @constant kSecValuePersistentRef Specifies a dictionary key whose value - is of type CFDataRef. The bytes in this CFDataRef can be stored by - the caller and used on a subsequent invocation of the application (or - even a different application) to retrieve the item referenced by it. -*/ -extern CFTypeRef kSecValueData - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecValueRef - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); -extern CFTypeRef kSecValuePersistentRef - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - - -/*! - @enum Other Constants - @discussion Predefined constants used to set values in a dictionary. - @constant kSecUseItemList Specifies a dictionary key whose value is a - CFArray of items. If provided, this array is treated as the set of - all possible items to search, or add if the API being called is - SecItemAdd. The items in this array may be of type SecKeyRef, - SecCertificateRef, SecIdentityRef, or CFDataRef (for a persistent - item reference.) The items in the array must all be of the same - type. When this attribute is provided, no keychains are searched. -*/ -extern CFTypeRef kSecUseItemList - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @function SecItemCopyMatching - @abstract Returns one or more items which match a search query. - @param query A dictionary containing an item class specification and - optional attributes for controlling the search. See the "Keychain - Search Attributes" section for a description of currently defined - search attributes. - @param result On return, a CFTypeRef reference to the found item(s). The - exact type of the result is based on the search attributes supplied - in the query, as discussed below. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Attributes defining a search are specified by adding key/value - pairs to the query dictionary. - - A typical query consists of: - - * a kSecClass key, whose value is a constant from the Class - Constants section that specifies the class of item(s) to be searched - * one or more keys from the "Attribute Key Constants" section, whose value - is the attribute data to be matched - * one or more keys from the "Search Constants" section, whose value is - used to further refine the search - * a key from the "Return Type Key Constants" section, specifying the type of - results desired - - Result types are specified as follows: - - * To obtain the data of a matching item (CFDataRef), specify - kSecReturnData with a value of kCFBooleanTrue. - * To obtain the attributes of a matching item (CFDictionaryRef), specify - kSecReturnAttributes with a value of kCFBooleanTrue. - * To obtain a reference to a matching item (SecKeychainItemRef, - SecKeyRef, SecCertificateRef, or SecIdentityRef), specify kSecReturnRef - with a value of kCFBooleanTrue. - * To obtain a persistent reference to a matching item (CFDataRef), - specify kSecReturnPersistentRef with a value of kCFBooleanTrue. Note - that unlike normal references, a persistent reference may be stored - on disk or passed between processes. - * If more than one of these result types is specified, the result is - returned as a CFDictionaryRef containing all the requested data. - * If a result type is not specified, no results are returned. - - By default, this function returns only the first match found. To obtain - more than one matching item at a time, specify kSecMatchLimit with a value - greater than 1. The result will be a CFArrayRef containing up to that - number of matching items; the items' types are described above. - - To filter a provided list of items down to those matching the query, - specify a kSecMatchItemList whose value is a CFArray of SecKeychainItemRef, - SecKeyRef, SecCertificateRef, or SecIdentityRef items. The objects in the - provided array must be of the same type. - - To convert from a persistent item reference to a normal item reference, - specify a kSecValuePersistentRef whose value a CFDataRef (the persistent - reference), and a kSecReturnRef whose value is kCFBooleanTrue. -*/ -OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @function SecItemAdd - @abstract Add one or more items to a keychain. - @param attributes A dictionary containing an item class specification and - optional entries specifying the item's attribute values. See the - "Attribute Key Constants" section for a description of currently defined - attributes. - @param result On return, a CFTypeRef reference to the newly added item(s). - The exact type of the result is based on the values supplied - in attributes, as discussed below. Pass NULL if this result is not - required. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Attributes defining an item are specified by adding key/value - pairs to the attributes dictionary. To add multiple items to a keychain - at once use the kSecUseItemList key with an array of items as its value. - This is currently only supported for non password items. - - Result types are specified as follows: - - * To obtain the data of the added item (CFDataRef), specify - kSecReturnData with a value of kCFBooleanTrue. - * To obtain all the attributes of the added item (CFDictionaryRef), - specify kSecReturnAttributes with a value of kCFBooleanTrue. - * To obtain a reference to the added item (SecKeychainItemRef, SecKeyRef, - SecCertificateRef, or SecIdentityRef), specify kSecReturnRef with a - value of kCFBooleanTrue. - * To obtain a persistent reference to the added item (CFDataRef), specify - kSecReturnPersistentRef with a value of kCFBooleanTrue. Note that - unlike normal references, a persistent reference may be stored on disk - or passed between processes. - * If more than one of these result types is specified, the result is - returned as a CFDictionaryRef containing all the requested data. - * If a result type is not specified, no results are returned. -*/ -OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @function SecItemUpdate - @abstract Modify zero or more items which match a search query. - @param query A dictionary containing an item class specification and - optional attributes for controlling the search. See the "Attribute - Constants" and "Search Constants" sections for a description of - currently defined search attributes. - @param attributesToUpdate A dictionary containing one or more attributes - whose values should be set to the ones specified. Only real keychain - attributes are permitted in this dictionary (no "meta" attributes are - allowed.) See the "Attribute Key Constants" section for a description of - currently defined value attributes. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Attributes defining a search are specified by adding key/value - pairs to the query dictionary. -*/ -OSStatus SecItemUpdate(CFDictionaryRef query, - CFDictionaryRef attributesToUpdate) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @function SecItemDelete - @abstract Delete zero or more items which match a search query. - @param query A dictionary containing an item class specification and - optional attributes for controlling the search. See the "Attribute - Constants" and "Search Constants" sections for a description of - currently defined search attributes. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Attributes defining a search are specified by adding key/value - pairs to the query dictionary. - - By default, this function deletes all items matching the specified query. - You can change this behavior by specifying one of the follow keys: - - * To delete an item identified by a transient reference, specify - kSecValueRef with a reference returned by using the kSecReturnRef - key in a previous call to SecItemCopyMatching or SecItemAdd. - * To delete an item identified by a persistent reference, specify - kSecValuePersistentRef with a persistent reference returned by - using the kSecReturnPersistentRef key to SecItemCopyMatching or - SecItemAdd. - * To delete multiple items specify kSecMatchItemList with an array - of references. - * If more than one of these result keys is specified, the behavior is - undefined. -*/ -OSStatus SecItemDelete(CFDictionaryRef query) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -__END_DECLS - -#endif /* !_SECURITY_SECITEM_H_ */ diff --git a/sec/Security/SecItemConstants.c b/sec/Security/SecItemConstants.c deleted file mode 100644 index 8e0fec3b..00000000 --- a/sec/Security/SecItemConstants.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2006-2008,2010-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@ - */ - -#define __CONSTANT_CFSTRINGS__ 1 -#include - -/* String constant declarations */ - -#define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); - -/* Class Key Constant */ -SEC_CONST_DECL (kSecClass, "class"); - -/* Class Value Constants */ -SEC_CONST_DECL (kSecClassGenericPassword, "genp"); -SEC_CONST_DECL (kSecClassInternetPassword, "inet"); -SEC_CONST_DECL (kSecClassAppleSharePassword, "apls"); -SEC_CONST_DECL (kSecClassCertificate, "cert"); -SEC_CONST_DECL (kSecClassKey, "keys"); -SEC_CONST_DECL (kSecClassIdentity, "idnt"); - -/* Attribute Key Constants */ -SEC_CONST_DECL (kSecAttrAccessible, "pdmn"); -SEC_CONST_DECL (kSecAttrAccessGroup, "agrp"); -SEC_CONST_DECL (kSecAttrCreationDate, "cdat"); -SEC_CONST_DECL (kSecAttrModificationDate, "mdat"); -SEC_CONST_DECL (kSecAttrDescription, "desc"); -SEC_CONST_DECL (kSecAttrComment, "icmt"); -SEC_CONST_DECL (kSecAttrCreator, "crtr"); -SEC_CONST_DECL (kSecAttrType, "type"); -SEC_CONST_DECL (kSecAttrLabel, "labl"); -SEC_CONST_DECL (kSecAttrIsInvisible, "invi"); -SEC_CONST_DECL (kSecAttrIsNegative, "nega"); -SEC_CONST_DECL (kSecAttrAccount, "acct"); -SEC_CONST_DECL (kSecAttrService, "svce"); -SEC_CONST_DECL (kSecAttrGeneric, "gena"); -SEC_CONST_DECL (kSecAttrSecurityDomain, "sdmn"); -SEC_CONST_DECL (kSecAttrServer, "srvr"); -SEC_CONST_DECL (kSecAttrProtocol, "ptcl"); -SEC_CONST_DECL (kSecAttrAuthenticationType, "atyp"); -SEC_CONST_DECL (kSecAttrPort, "port"); -SEC_CONST_DECL (kSecAttrPath, "path"); -SEC_CONST_DECL (kSecAttrVolume, "volm"); -SEC_CONST_DECL (kSecAttrAddress, "addr"); -SEC_CONST_DECL (kSecAttrAFPServerSignature, "afps"); -SEC_CONST_DECL (kSecAttrAlias, "alis"); -SEC_CONST_DECL (kSecAttrSubject, "subj"); -SEC_CONST_DECL (kSecAttrIssuer, "issr"); -SEC_CONST_DECL (kSecAttrSerialNumber, "slnr"); -SEC_CONST_DECL (kSecAttrSubjectKeyID, "skid"); -SEC_CONST_DECL (kSecAttrPublicKeyHash, "pkhh"); -SEC_CONST_DECL (kSecAttrCertificateType, "ctyp"); -SEC_CONST_DECL (kSecAttrCertificateEncoding, "cenc"); -SEC_CONST_DECL (kSecAttrKeyClass, "kcls"); -SEC_CONST_DECL (kSecAttrApplicationLabel, "klbl"); -SEC_CONST_DECL (kSecAttrIsPermanent, "perm"); -SEC_CONST_DECL (kSecAttrIsPrivate, "priv"); -SEC_CONST_DECL (kSecAttrIsModifiable, "modi"); -SEC_CONST_DECL (kSecAttrApplicationTag, "atag"); -SEC_CONST_DECL (kSecAttrKeyCreator, "crtr"); -SEC_CONST_DECL (kSecAttrKeyType, "type"); -SEC_CONST_DECL (kSecAttrKeySizeInBits, "bsiz"); -SEC_CONST_DECL (kSecAttrEffectiveKeySize, "esiz"); -SEC_CONST_DECL (kSecAttrStartDate, "sdat"); -SEC_CONST_DECL (kSecAttrEndDate, "edat"); -SEC_CONST_DECL (kSecAttrIsSensitive, "sens"); -SEC_CONST_DECL (kSecAttrWasAlwaysSensitive, "asen"); -SEC_CONST_DECL (kSecAttrIsExtractable, "extr"); -SEC_CONST_DECL (kSecAttrWasNeverExtractable, "next"); -SEC_CONST_DECL (kSecAttrCanEncrypt, "encr"); -SEC_CONST_DECL (kSecAttrCanDecrypt, "decr"); -SEC_CONST_DECL (kSecAttrCanDerive, "drve"); -SEC_CONST_DECL (kSecAttrCanSign, "sign"); -SEC_CONST_DECL (kSecAttrCanVerify, "vrfy"); -SEC_CONST_DECL (kSecAttrCanSignRecover, "snrc"); -SEC_CONST_DECL (kSecAttrCanVerifyRecover, "vyrc"); -SEC_CONST_DECL (kSecAttrCanWrap, "wrap"); -SEC_CONST_DECL (kSecAttrCanUnwrap, "unwp"); -/* Attribute Constants (Private) */ -SEC_CONST_DECL (kSecAttrScriptCode, "scrp"); -SEC_CONST_DECL (kSecAttrHasCustomIcon, "cusi"); -SEC_CONST_DECL (kSecAttrCRLType, "crlt"); -SEC_CONST_DECL (kSecAttrCRLEncoding, "crle"); -SEC_CONST_DECL (kSecAttrSynchronizable, "sync"); -SEC_CONST_DECL (kSecAttrSynchronizableAny, "syna"); -SEC_CONST_DECL (kSecAttrTombstone, "tomb"); - -/* Search Constants */ -SEC_CONST_DECL (kSecMatchPolicy, "m_Policy"); -SEC_CONST_DECL (kSecMatchItemList, "m_ItemList"); -SEC_CONST_DECL (kSecMatchSearchList, "m_SearchList"); -SEC_CONST_DECL (kSecMatchIssuers, "m_Issuers"); -SEC_CONST_DECL (kSecMatchEmailAddressIfPresent, "m_EmailAddressIfPresent"); -SEC_CONST_DECL (kSecMatchSubjectContains, "m_SubjectContains"); -SEC_CONST_DECL (kSecMatchCaseInsensitive, "m_CaseInsensitive"); -SEC_CONST_DECL (kSecMatchTrustedOnly, "m_TrustedOnly"); -SEC_CONST_DECL (kSecMatchValidOnDate, "m_ValidOnDate"); -SEC_CONST_DECL (kSecMatchLimit, "m_Limit"); -/* Could just use kCFBooleanTrue and kCFBooleanFalse for these 2. */ -SEC_CONST_DECL (kSecMatchLimitOne, "m_LimitOne"); -SEC_CONST_DECL (kSecMatchLimitAll, "m_LimitAll"); - -/* Return Type Key Constants */ -SEC_CONST_DECL (kSecReturnData, "r_Data"); -SEC_CONST_DECL (kSecReturnAttributes, "r_Attributes"); -SEC_CONST_DECL (kSecReturnRef, "r_Ref"); -SEC_CONST_DECL (kSecReturnPersistentRef, "r_PersistentRef"); - -/* Value Type Key Constants */ -SEC_CONST_DECL (kSecValueData, "v_Data"); -SEC_CONST_DECL (kSecValueRef, "v_Ref"); -SEC_CONST_DECL (kSecValuePersistentRef, "v_PersistentRef"); - -/* Other Constants */ -SEC_CONST_DECL (kSecUseItemList, "u_ItemList"); -SEC_CONST_DECL (kSecUseTombstones, "u_Tomb"); -#if defined(MULTIPLE_KEYCHAINS) -/* Other Constants (Private) */ -SEC_CONST_DECL (kSecUseKeychain, "u_Keychain"); -SEC_CONST_DECL (kSecUseKeychainList, "u_KeychainList"); -#endif /* !defined(MULTIPLE_KEYCHAINS) */ - -/* kSecAttrAccessible Value Constants. */ -SEC_CONST_DECL (kSecAttrAccessibleWhenUnlocked, "ak"); -SEC_CONST_DECL (kSecAttrAccessibleAfterFirstUnlock, "ck"); -SEC_CONST_DECL (kSecAttrAccessibleAlways, "dk"); -SEC_CONST_DECL (kSecAttrAccessibleWhenUnlockedThisDeviceOnly, "aku"); -SEC_CONST_DECL (kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, "cku"); -SEC_CONST_DECL (kSecAttrAccessibleAlwaysThisDeviceOnly, "dku"); - -/* kSecAttrProtocol Value Constants. */ -SEC_CONST_DECL (kSecAttrProtocolFTP, "ftp "); -SEC_CONST_DECL (kSecAttrProtocolFTPAccount, "ftpa"); -SEC_CONST_DECL (kSecAttrProtocolHTTP, "http"); -SEC_CONST_DECL (kSecAttrProtocolIRC, "irc "); -SEC_CONST_DECL (kSecAttrProtocolNNTP, "nntp"); -SEC_CONST_DECL (kSecAttrProtocolPOP3, "pop3"); -SEC_CONST_DECL (kSecAttrProtocolSMTP, "smtp"); -SEC_CONST_DECL (kSecAttrProtocolSOCKS, "sox "); -SEC_CONST_DECL (kSecAttrProtocolIMAP, "imap"); -SEC_CONST_DECL (kSecAttrProtocolLDAP, "ldap"); -SEC_CONST_DECL (kSecAttrProtocolAppleTalk, "atlk"); -SEC_CONST_DECL (kSecAttrProtocolAFP, "afp "); -SEC_CONST_DECL (kSecAttrProtocolTelnet, "teln"); -SEC_CONST_DECL (kSecAttrProtocolSSH, "ssh "); -SEC_CONST_DECL (kSecAttrProtocolFTPS, "ftps"); -SEC_CONST_DECL (kSecAttrProtocolHTTPS, "htps"); -SEC_CONST_DECL (kSecAttrProtocolHTTPProxy, "htpx"); -SEC_CONST_DECL (kSecAttrProtocolHTTPSProxy, "htsx"); -SEC_CONST_DECL (kSecAttrProtocolFTPProxy, "ftpx"); -SEC_CONST_DECL (kSecAttrProtocolSMB, "smb "); -SEC_CONST_DECL (kSecAttrProtocolRTSP, "rtsp"); -SEC_CONST_DECL (kSecAttrProtocolRTSPProxy, "rtsx"); -SEC_CONST_DECL (kSecAttrProtocolDAAP, "daap"); -SEC_CONST_DECL (kSecAttrProtocolEPPC, "eppc"); -SEC_CONST_DECL (kSecAttrProtocolIPP, "ipp "); -SEC_CONST_DECL (kSecAttrProtocolNNTPS, "ntps"); -SEC_CONST_DECL (kSecAttrProtocolLDAPS, "ldps"); -SEC_CONST_DECL (kSecAttrProtocolTelnetS, "tels"); -SEC_CONST_DECL (kSecAttrProtocolIMAPS, "imps"); -SEC_CONST_DECL (kSecAttrProtocolIRCS, "ircs"); -SEC_CONST_DECL (kSecAttrProtocolPOP3S, "pops"); - -/* kSecAttrAuthenticationType Value Constants. */ -SEC_CONST_DECL (kSecAttrAuthenticationTypeNTLM, "ntlm"); -SEC_CONST_DECL (kSecAttrAuthenticationTypeMSN, "msna"); -SEC_CONST_DECL (kSecAttrAuthenticationTypeDPA, "dpaa"); -SEC_CONST_DECL (kSecAttrAuthenticationTypeRPA, "rpaa"); -SEC_CONST_DECL (kSecAttrAuthenticationTypeHTTPBasic, "http"); -SEC_CONST_DECL (kSecAttrAuthenticationTypeHTTPDigest, "httd"); -SEC_CONST_DECL (kSecAttrAuthenticationTypeHTMLForm, "form"); -SEC_CONST_DECL (kSecAttrAuthenticationTypeDefault, "dflt"); - -/* kSecAttrKeyClass Value Constants. Based on - CSSM_KEYCLASS_PUBLIC_KEY = 0, - CSSM_KEYCLASS_PRIVATE_KEY = 1, - CSSM_KEYCLASS_SESSION_KEY = 2, - */ -SEC_CONST_DECL (kSecAttrKeyClassPublic, "0"); -SEC_CONST_DECL (kSecAttrKeyClassPrivate, "1"); -SEC_CONST_DECL (kSecAttrKeyClassSymmetric, "2"); - -/* kSecAttrKeyType Value Constants. Based on CSSM_ALGORITHMS. */ -SEC_CONST_DECL (kSecAttrKeyTypeRSA, "42"); -SEC_CONST_DECL (kSecAttrKeyTypeEC, "73"); /* rdar://10755886 */ - -/* Constants used by SecKeyGeneratePair() - in SecKey.h. Never used in - any SecItem apis directly. */ -SEC_CONST_DECL (kSecPrivateKeyAttrs, "private"); -SEC_CONST_DECL (kSecPublicKeyAttrs, "public"); - -/* Constants used by SecPassword - in SecPasswordStrength */ -SEC_CONST_DECL (kSecPasswordMaxLength, "PasswordMaxLength"); -SEC_CONST_DECL (kSecPasswordMinLength, "PasswordMaxLength"); -SEC_CONST_DECL (kSecPasswordAllowedCharacters, "PasswordAllowedCharacters"); -SEC_CONST_DECL (kSecPasswordRequiredCharacters, "PasswordRequiredCharacters"); diff --git a/sec/Security/SecItemPriv.h b/sec/Security/SecItemPriv.h deleted file mode 100644 index 51472bc8..00000000 --- a/sec/Security/SecItemPriv.h +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (c) 2006-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@ - */ - -/*! - @header SecItemPriv - SecItemPriv defines private constants and SPI functions for access to - Security items (certificates, identities, keys, and keychain items.) -*/ - -#ifndef _SECURITY_SECITEMPRIV_H_ -#define _SECURITY_SECITEMPRIV_H_ - -#include -#include - -__BEGIN_DECLS - -/*! - @enum Class Value Constants (Private) - @discussion Predefined item class constants used to get or set values in - a dictionary. The kSecClass constant is the key and its value is one - of the constants defined here. - @constant kSecClassAppleSharePassword Specifies AppleShare password items. -*/ -extern CFTypeRef kSecClassAppleSharePassword; - - -/*! - @enum Attribute Key Constants (Private) - @discussion Predefined item attribute keys used to get or set values in a - dictionary. Not all attributes apply to each item class. The table - below lists the currently defined attributes for each item class: - - kSecClassGenericPassword item attributes: - kSecAttrAccessGroup - kSecAttrCreationDate - kSecAttrModificationDate - kSecAttrDescription - kSecAttrComment - kSecAttrCreator - kSecAttrType - kSecAttrScriptCode (private) - kSecAttrLabel - kSecAttrAlias (private) - kSecAttrIsInvisible - kSecAttrIsNegative - kSecAttrHasCustomIcon (private) - kSecAttrProtected (private) - kSecAttrAccount - kSecAttrService - kSecAttrGeneric - - kSecClassInternetPassword item attributes: - kSecAttrAccessGroup - kSecAttrCreationDate - kSecAttrModificationDate - kSecAttrDescription - kSecAttrComment - kSecAttrCreator - kSecAttrType - kSecAttrScriptCode (private) - kSecAttrLabel - kSecAttrAlias (private) - kSecAttrIsInvisible - kSecAttrIsNegative - kSecAttrHasCustomIcon (private) - kSecAttrProtected (private) - kSecAttrAccount - kSecAttrSecurityDomain - kSecAttrServer - kSecAttrProtocol - kSecAttrAuthenticationType - kSecAttrPort - kSecAttrPath - - kSecClassAppleSharePassword item attributes: - kSecAttrAccessGroup - kSecAttrCreationDate - kSecAttrModificationDate - kSecAttrDescription - kSecAttrComment - kSecAttrCreator - kSecAttrType - kSecAttrScriptCode (private) - kSecAttrLabel - kSecAttrAlias (private) - kSecAttrIsInvisible - kSecAttrIsNegative - kSecAttrHasCustomIcon (private) - kSecAttrProtected (private) - kSecAttrAccount - kSecAttrVolume - kSecAttrAddress - kSecAttrAFPServerSignature - - kSecClassCertificate item attributes: - kSecAttrAccessGroup - kSecAttrCertificateType - kSecAttrCertificateEncoding - kSecAttrLabel - kSecAttrAlias (private) - kSecAttrSubject - kSecAttrIssuer - kSecAttrSerialNumber - kSecAttrSubjectKeyID - kSecAttrPublicKeyHash - - kSecClassKey item attributes: - kSecAttrAccessGroup - kSecAttrKeyClass - kSecAttrLabel - kSecAttrAlias (private) - kSecAttrApplicationLabel - kSecAttrIsPermanent - kSecAttrIsPrivate (private) - kSecAttrIsModifiable (private) - kSecAttrApplicationTag - kSecAttrKeyCreator (private) - kSecAttrKeyType - kSecAttrKeySizeInBits - kSecAttrEffectiveKeySize - kSecAttrStartDate (private) - kSecAttrEndDate (private) - kSecAttrIsSensitive (private) - kSecAttrWasAlwaysSensitive (private) - kSecAttrIsExtractable (private) - kSecAttrWasNeverExtractable (private) - kSecAttrCanEncrypt - kSecAttrCanDecrypt - kSecAttrCanDerive - kSecAttrCanSign - kSecAttrCanVerify - kSecAttrCanSignRecover (private) - kSecAttrCanVerifyRecover (private) - kSecAttrCanWrap - kSecAttrCanUnwrap - - kSecClassIdentity item attributes: - Since an identity is the combination of a private key and a - certificate, this class shares attributes of both kSecClassKey and - kSecClassCertificate. - - @constant kSecAttrScriptCode Specifies a dictionary key whose value is the - item's script code attribute. You use this tag to set or get a value - of type CFNumberRef that represents a script code for this item's - strings. (Note: use of this attribute is deprecated; string attributes - should always be stored in UTF-8 encoding. This is currently private - for use by syncing; new code should not ever access this attribute.) - @constant kSecAttrAlias Specifies a dictionary key whose value is the - item's alias. You use this key to get or set a value of type CFDataRef - which represents an alias. For certificate items, the alias is either - a single email address, an array of email addresses, or the common - name of the certificate if it does not contain any email address. - (Items of class kSecClassCertificate have this attribute.) - @constant kSecAttrHasCustomIcon Specifies a dictionary key whose value is the - item's custom icon attribute. You use this tag to set or get a value - of type CFBooleanRef that indicates whether the item should have an - application-specific icon. (Note: use of this attribute is deprecated; - custom item icons are not supported in Mac OS X. This is currently - private for use by syncing; new code should not use this attribute.) - @constant kSecAttrVolume Specifies a dictionary key whose value is the - item's volume attribute. You use this key to set or get a CFStringRef - value that represents an AppleShare volume name. (Items of class - kSecClassAppleSharePassword have this attribute.) - @constant kSecAttrAddress Specifies a dictionary key whose value is the - item's address attribute. You use this key to set or get a CFStringRef - value that contains the AppleTalk zone name, or the IP or domain name - that represents the server address. (Items of class - kSecClassAppleSharePassword have this attribute.) - @constant kSecAttrAFPServerSignature Specifies a dictionary key whose value - is the item's AFP server signature attribute. You use this key to set - or get a CFDataRef value containing 16 bytes that represents the - server's signature block. (Items of class kSecClassAppleSharePassword - have this attribute.) - @constant kSecAttrCRLType (read-only) Specifies a dictionary key whose - value is the item's certificate revocation list type. You use this - key to get a value of type CFNumberRef that denotes the CRL type (see - the CSSM_CRL_TYPE enum in cssmtype.h). (Items of class - kSecClassCertificate have this attribute.) - @constant kSecAttrCRLEncoding (read-only) Specifies a dictionary key whose - value is the item's certificate revocation list encoding. You use - this key to get a value of type CFNumberRef that denotes the CRL - encoding (see the CSSM_CRL_ENCODING enum in cssmtype.h). (Items of - class kSecClassCertificate have this attribute.) - @constant kSecAttrKeyCreator Specifies a dictionary key whose value is a - CFDataRef containing a CSSM_GUID structure representing the module ID of - the CSP that owns this key. - @constant kSecAttrIsPrivate Specifies a dictionary key whose value is a - CFBooleanRef indicating whether the raw key material of the key in - question is private. - @constant kSecAttrIsModifiable Specifies a dictionary key whose value is a - CFBooleanRef indicating whether any of the attributes of this key are - modifiable. - @constant kSecAttrStartDate Specifies a dictionary key whose value is a - CFDateRef indicating the earliest date on which this key may be used. - If kSecAttrStartDate is not present, the restriction does not apply. - @constant kSecAttrEndDate Specifies a dictionary key whose value is a - CFDateRef indicating the last date on which this key may be used. - If kSecAttrEndDate is not present, the restriction does not apply. - @constant kSecAttrIsSensitive Specifies a dictionary key whose value - is a CFBooleanRef indicating whether the key in question must be wrapped - with an algorithm other than CSSM_ALGID_NONE. - @constant kSecAttrWasAlwaysSensitive Specifies a dictionary key whose value - is a CFBooleanRef indicating that the key in question has always been - marked as sensitive. - @constant kSecAttrIsExtractable Specifies a dictionary key whose value - is a CFBooleanRef indicating whether the key in question may be wrapped. - @constant kSecAttrWasNeverExtractable Specifies a dictionary key whose value - is a CFBooleanRef indicating that the key in question has never been - marked as extractable. - @constant kSecAttrCanSignRecover Specifies a dictionary key whole value is a - CFBooleanRef indicating whether the key in question can be used to - perform sign recovery. - @constant kSecAttrCanVerifyRecover Specifies a dictionary key whole value is - a CFBooleanRef indicating whether the key in question can be used to - perform verify recovery. - @constant kSecAttrTombstone Specifies a dictionary key whose value is - a CFBooleanRef indicating that the item in question is a tombstone. -*/ -extern CFTypeRef kSecAttrScriptCode; -extern CFTypeRef kSecAttrAlias; -extern CFTypeRef kSecAttrHasCustomIcon; -extern CFTypeRef kSecAttrVolume; -extern CFTypeRef kSecAttrAddress; -extern CFTypeRef kSecAttrAFPServerSignature; -extern CFTypeRef kSecAttrCRLType; -extern CFTypeRef kSecAttrCRLEncoding; -extern CFTypeRef kSecAttrKeyCreator; -extern CFTypeRef kSecAttrIsPrivate; -extern CFTypeRef kSecAttrIsModifiable; -extern CFTypeRef kSecAttrStartDate; -extern CFTypeRef kSecAttrEndDate; -extern CFTypeRef kSecAttrIsSensitive; -extern CFTypeRef kSecAttrWasAlwaysSensitive; -extern CFTypeRef kSecAttrIsExtractable; -extern CFTypeRef kSecAttrWasNeverExtractable; -extern CFTypeRef kSecAttrCanSignRecover; -extern CFTypeRef kSecAttrCanVerifyRecover; -extern CFTypeRef kSecAttrTombstone; - -/*! - @enum Other Constants (Private) - @discussion Predefined constants used to set values in a dictionary. - @constant kSecUseTombstones Specifies a dictionary key whose value is a - CFBooleanRef if present this overrides the default behaviour for when - we make tombstones. The default being we create tombstones for - synchronizable items unless we are explicitly deleting or updating a - tombstone. Setting this to false when calling SecItemDelete or - SecItemUpdate will ensure no tombstones are created. Setting it to - true will ensure we create tombstones even when deleting or updating non - synchronizable items. - @constant kSecUseKeychain Specifies a dictionary key whose value is a - keychain reference. You use this key to specify a value of type - SecKeychainRef that indicates the keychain to which SecItemAdd - will add the provided item(s). - @constant kSecUseKeychainList Specifies a dictionary key whose value is - either an array of keychains to search (CFArrayRef), or a single - keychain (SecKeychainRef). If not provided, the user's default - keychain list is searched. kSecUseKeychainList is ignored if an - explicit kSecUseItemList is also provided. This key can be used - for the SecItemCopyMatching, SecItemUpdate and SecItemDelete calls. -*/ -extern CFTypeRef kSecUseTombstones - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -#if defined(MULTIPLE_KEYCHAINS) -extern CFTypeRef kSecUseKeychain; -extern CFTypeRef kSecUseKeychainList; -#endif /* !defined(MULTIPLE_KEYCHAINS) */ - - -/*! - @function SecItemCopyDisplayNames - @abstract Returns an array containing unique display names for each of the - certificates, keys, identities, or passwords in the provided items - array. - @param items An array containing items of type SecKeychainItemRef, - SecKeyRef, SecCertificateRef, or SecIdentityRef. All items in the - array should be of the same type. - @param displayNames On return, an array of CFString references containing - unique names for the supplied items. You are responsible for releasing - this array reference by calling the CFRelease function. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Use this function to obtain item names which are suitable for - display in a menu or list view. The returned names are guaranteed to - be unique across the set of provided items. -*/ -OSStatus SecItemCopyDisplayNames(CFArrayRef items, CFArrayRef *displayNames); - -/*! - @function SecItemDeleteAll - @abstract Removes all items from the keychain and added root certificates - from the trust store. - @result A result code. See "Security Error Codes" (SecBase.h). -*/ -OSStatus SecItemDeleteAll(void); - -/* - Ensure the escrow keybag has been used to unlock the system keybag before - calling either of these APIs. - The password argument is optional, passing NULL implies no backup password - was set. We're assuming there will always be a backup keybag, except in - the OTA case where the loaded OTA backup bag will be used. - */ -CFDataRef _SecKeychainCopyBackup(CFDataRef backupKeybag, CFDataRef password); -CFDataRef _SecKeychainCopyOTABackup(void); -OSStatus _SecKeychainRestoreBackup(CFDataRef backup, CFDataRef backupKeybag, - CFDataRef password); - -OSStatus _SecKeychainBackupSyncable(CFDataRef keybag, CFDataRef password, CFDictionaryRef backup_in, CFDictionaryRef *backup_out); -OSStatus _SecKeychainRestoreSyncable(CFDataRef keybag, CFDataRef password, CFDictionaryRef backup_in); - -/* Called by clients to push sync circle and message changes to us. - Requires caller to have the kSecEntitlementKeychainSyncUpdates entitlement. */ -bool _SecKeychainSyncUpdate(CFDictionaryRef updates, CFErrorRef *error); - -/* Returns an OSStatus value for the given CFErrorRef, returns errSecInternal if the domain of the providied error is not recognized. Passing NULL returns errSecSuccess (0). */ -OSStatus SecErrorGetOSStatus(CFErrorRef error); - -__END_DECLS - -#endif /* !_SECURITY_SECITEMPRIV_H_ */ diff --git a/sec/Security/SecKey.h b/sec/Security/SecKey.h deleted file mode 100644 index 74c08f46..00000000 --- a/sec/Security/SecKey.h +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (c) 2006-2009,2011 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 SecKey - The functions provided in SecKey.h implement and manage a particular - type of keychain item that represents a key. A key can be stored in a - keychain, but a key can also be a transient object. - - You can use a key as a keychain item in most functions. -*/ - -#ifndef _SECURITY_SECKEY_H_ -#define _SECURITY_SECKEY_H_ - -#include -#include -#include - -__BEGIN_DECLS - -/* Padding Types (iPhone OS 2.0 and later only). */ -typedef uint32_t SecPadding; -enum -{ - kSecPaddingNone = 0, - kSecPaddingPKCS1 = 1, - kSecPaddingOAEP = 2, - - /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is an MD2 - hash; standard ASN.1 padding will be done, as well as PKCS1 padding - of the underlying RSA operation. */ - kSecPaddingPKCS1MD2 = 0x8000, /* Unsupported as of iOS 5.0 */ - - /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is an MD5 - hash; standard ASN.1 padding will be done, as well as PKCS1 padding - of the underlying RSA operation. */ - kSecPaddingPKCS1MD5 = 0x8001, /* Unsupported as of iOS 5.0 */ - - /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is a SHA1 - hash; standard ASN.1 padding will be done, as well as PKCS1 padding - of the underlying RSA operation. */ - kSecPaddingPKCS1SHA1 = 0x8002, - - /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is a SHA224 - hash; standard ASN.1 padding will be done, as well as PKCS1 padding - of the underlying RSA operation. */ - kSecPaddingPKCS1SHA224 = 0x8003, - - /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is a SHA256 - hash; standard ASN.1 padding will be done, as well as PKCS1 padding - of the underlying RSA operation. */ - kSecPaddingPKCS1SHA256 = 0x8004, - - /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is a SHA384 - hash; standard ASN.1 padding will be done, as well as PKCS1 padding - of the underlying RSA operation. */ - kSecPaddingPKCS1SHA384 = 0x8005, - - /* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is a SHA512 - hash; standard ASN.1 padding will be done, as well as PKCS1 padding - of the underlying RSA operation. */ - kSecPaddingPKCS1SHA512 = 0x8006, -}; - - -/*! - @function SecKeyGetTypeID - @abstract Returns the type identifier of SecKey instances. - @result The CFTypeID of SecKey instances. -*/ -CFTypeID SecKeyGetTypeID(void) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -/*! - @enum Dictionary key constants for SecKeyGeneratePair API. - @discussion Predefined key constants used to get or set values - in a dictionary. - @constant kSecPrivateKeyAttrs The value for this key is a CFDictionaryRef - containing attributes specific for the private key to be generated. - @constant kSecPublicKeyAttrs The value for this key is a CFDictionaryRef - containing attributes specific for the public key to be generated. -*/ -extern CFTypeRef kSecPrivateKeyAttrs - __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_2_0); -extern CFTypeRef kSecPublicKeyAttrs - __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_2_0); - -/*! - @function SecKeyGeneratePair - @abstract Generate a private/public keypair. - @param parameters A dictionary containing one or more key-value pairs. - See the discussion sections below for a complete overview of options. - @param publicKey On return, a SecKeyRef reference to the public key. - @param privateKey On return, a SecKeyRef reference to the private key. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion In order to generate a keypair the parameters dictionary must - at least contain the following keys: - - * kSecAttrKeyType with a value being kSecAttrKeyTypeRSA or any other - kSecAttrKeyType defined in SecItem.h - * kSecAttrKeySizeInBits with a value being a CFNumberRef or CFStringRef - containing the requested key size in bits. Example sizes for RSA - keys are: 512, 768, 1024, 2048. - - The values below may be set either in the top-level dictionary or in a - dictionary that is the value of the kSecPrivateKeyAttrs or - kSecPublicKeyAttrs key in the top-level dictionary. Setting these - attributes explicitly will override the defaults below. See SecItem.h - for detailed information on these attributes including the types of - the values. - - * kSecAttrLabel default NULL - * kSecAttrIsPermanent if this key is present and has a Boolean - value of true, the key or key pair will be added to the default - keychain. - * kSecAttrApplicationTag default NULL - * kSecAttrEffectiveKeySize default NULL same as kSecAttrKeySizeInBits - * kSecAttrCanEncrypt default false for private keys, true for public keys - * kSecAttrCanDecrypt default true for private keys, false for public keys - * kSecAttrCanDerive default true - * kSecAttrCanSign default true for private keys, false for public keys - * kSecAttrCanVerify default false for private keys, true for public keys - * kSecAttrCanWrap default false for private keys, true for public keys - * kSecAttrCanUnwrap default true for private keys, false for public keys - -*/ -OSStatus SecKeyGeneratePair(CFDictionaryRef parameters, SecKeyRef *publicKey, - SecKeyRef *privateKey) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - - -/*! - @function SecKeyRawSign - @abstract Given a private key and data to sign, generate a digital - signature. - @param key Private key with which to sign. - @param padding See Padding Types above, typically kSecPaddingPKCS1SHA1. - @param dataToSign The data to be signed, typically the digest of the - actual data. - @param dataToSignLen Length of dataToSign in bytes. - @param sig Pointer to buffer in which the signature will be returned. - @param sigLen IN/OUT maximum length of sig buffer on input, actualy - length of sig on output. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion If the padding argument is kSecPaddingPKCS1, PKCS1 padding - will be performed prior to signing. If this argument is kSecPaddingNone, - the incoming data will be signed "as is". - - When PKCS1 padding is performed, the maximum length of data that can - be signed is the value returned by SecKeyGetBlockSize() - 11. - - NOTE: The behavior this function with kSecPaddingNone is undefined if the - first byte of dataToSign is zero; there is no way to verify leading zeroes - as they are discarded during the calculation. - - If you want to generate a proper PKCS1 style signature with DER encoding - of the digest type - and the dataToSign is a SHA1 digest - use - kSecPaddingPKCS1SHA1. - */ -OSStatus SecKeyRawSign( - SecKeyRef key, - SecPadding padding, - const uint8_t *dataToSign, - size_t dataToSignLen, - uint8_t *sig, - size_t *sigLen) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - - -/*! - @function SecKeyRawVerify - @abstract Given a public key, data which has been signed, and a signature, - verify the signature. - @param key Public key with which to verify the signature. - @param padding See Padding Types above, typically kSecPaddingPKCS1SHA1. - @param signedData The data over which sig is being verified, typically - the digest of the actual data. - @param signedDataLen Length of signedData in bytes. - @param sig Pointer to the signature to verify. - @param sigLen Length of sig in bytes. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion If the padding argument is kSecPaddingPKCS1, PKCS1 padding - will be checked during verification. If this argument is kSecPaddingNone, - the incoming data will be compared directly to sig. - - If you are verifying a proper PKCS1-style signature, with DER encoding - of the digest type - and the signedData is a SHA1 digest - use - kSecPaddingPKCS1SHA1. - */ -OSStatus SecKeyRawVerify( - SecKeyRef key, - SecPadding padding, - const uint8_t *signedData, - size_t signedDataLen, - const uint8_t *sig, - size_t sigLen) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - - -/*! - @function SecKeyEncrypt - @abstract Encrypt a block of plaintext. - @param key Public key with which to encrypt the data. - @param padding See Padding Types above, typically kSecPaddingPKCS1. - @param plainText The data to encrypt. - @param plainTextLen Length of plainText in bytes, this must be less - or equal to the value returned by SecKeyGetBlockSize(). - @param cipherText Pointer to the output buffer. - @param cipherTextLen On input, specifies how much space is available at - cipherText; on return, it is the actual number of cipherText bytes written. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion If the padding argument is kSecPaddingPKCS1, PKCS1 padding - will be performed prior to encryption. If this argument is kSecPaddingNone, - the incoming data will be encrypted "as is". - - When PKCS1 padding is performed, the maximum length of data that can - be encrypted is the value returned by SecKeyGetBlockSize() - 11. - - When memory usage is a critical issue, note that the input buffer - (plainText) can be the same as the output buffer (cipherText). - */ -OSStatus SecKeyEncrypt( - SecKeyRef key, - SecPadding padding, - const uint8_t *plainText, - size_t plainTextLen, - uint8_t *cipherText, - size_t *cipherTextLen) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - - -/*! - @function SecKeyDecrypt - @abstract Decrypt a block of ciphertext. - @param key Private key with which to decrypt the data. - @param padding See Padding Types above, typically kSecPaddingPKCS1. - @param cipherText The data to decrypt. - @param cipherTextLen Length of cipherText in bytes, this must be less - or equal to the value returned by SecKeyGetBlockSize(). - @param plainText Pointer to the output buffer. - @param plainTextLen On input, specifies how much space is available at - plainText; on return, it is the actual number of plainText bytes written. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion If the padding argument is kSecPaddingPKCS1, PKCS1 padding - will be removed after decryption. If this argument is kSecPaddingNone, - the decrypted data will be returned "as is". - - When memory usage is a critical issue, note that the input buffer - (plainText) can be the same as the output buffer (cipherText). - */ -OSStatus SecKeyDecrypt( - SecKeyRef key, /* Private key */ - SecPadding padding, /* kSecPaddingNone, - kSecPaddingPKCS1, - kSecPaddingOAEP */ - const uint8_t *cipherText, - size_t cipherTextLen, /* length of cipherText */ - uint8_t *plainText, - size_t *plainTextLen) /* IN/OUT */ - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - -/*! - @function SecKeyGetBlockSize - @abstract Decrypt a block of ciphertext. - @param key The key for which the block length is requested. - @result The block length of the key in bytes. - @discussion If for example key is an RSA key the value returned by - this function is the size of the modulus. - */ -size_t SecKeyGetBlockSize(SecKeyRef key) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - - -__END_DECLS - -#endif /* !_SECURITY_SECKEY_H_ */ diff --git a/sec/Security/SecKeyPriv.h b/sec/Security/SecKeyPriv.h deleted file mode 100644 index 02ffebfe..00000000 --- a/sec/Security/SecKeyPriv.h +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (c) 2006-2010 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 SecKeyPriv - The functions provided in SecKeyPriv.h implement and manage a particular - type of keychain item that represents a key. A key can be stored in a - keychain, but a key can also be a transient object. - - You can use a key as a keychain item in most functions. -*/ - -#ifndef _SECURITY_SECKEYPRIV_H_ -#define _SECURITY_SECKEYPRIV_H_ - -#include -#include -#include -#include - -__BEGIN_DECLS - -typedef struct __SecDERKey { - uint8_t *oid; - CFIndex oidLength; - - uint8_t *parameters; - CFIndex parametersLength; - - /* Contents of BIT STRING in DER Encoding */ - uint8_t *key; - CFIndex keyLength; -} SecDERKey; - - -typedef uint32_t SecKeyEncoding; -enum { - /* Typically only used for symmetric keys. */ - kSecKeyEncodingRaw = 0, - - /* RSA keys are DER-encoded according to PKCS1. */ - kSecKeyEncodingPkcs1 = 1, - - /* RSA keys are DER-encoded according to PKCS1 with Apple Extensions. */ - kSecKeyEncodingApplePkcs1 = 2, - - /* RSA public key in SecRSAPublicKeyParams format. keyData is a pointer - to a SecRSAPublicKeyParams and keyDataLength is - sizeof(SecRSAPublicKeyParams). */ - kSecKeyEncodingRSAPublicParams = 3, - - /* RSA public key in SecRSAPublicKeyParams format. keyData is a pointer - to a SecRSAPublicKeyParams and keyDataLength is - sizeof(SecRSAPublicKeyParams). */ - kSecDERKeyEncoding = 4, - - /* Internal "encodings to send other data" */ - kSecGenerateKey = 5, - kSecExtractPublicFromPrivate = 6, - - /* Encoding came from SecKeyCopyPublicBytes for a public key, - or internally from a private key */ - kSecKeyEncodingBytes = 7, - - /* Handing in a private key from corecrypto directly. */ - kSecKeyCoreCrypto = 8, - -}; - -typedef OSStatus (*SecKeyInitMethod)(SecKeyRef, const uint8_t *, CFIndex, - SecKeyEncoding); -typedef void (*SecKeyDestroyMethod)(SecKeyRef); -typedef OSStatus (*SecKeyRawSignMethod)(SecKeyRef key, SecPadding padding, - const uint8_t *dataToSign, size_t dataToSignLen, - uint8_t *sig, size_t *sigLen); -typedef OSStatus (*SecKeyRawVerifyMethod)( - SecKeyRef key, SecPadding padding, const uint8_t *signedData, - size_t signedDataLen, const uint8_t *sig, size_t sigLen); -typedef OSStatus (*SecKeyEncryptMethod)(SecKeyRef key, SecPadding padding, - const uint8_t *plainText, size_t plainTextLen, - uint8_t *cipherText, size_t *cipherTextLen); -typedef OSStatus (*SecKeyDecryptMethod)(SecKeyRef key, SecPadding padding, - const uint8_t *cipherText, size_t cipherTextLen, - uint8_t *plainText, size_t *plainTextLen); -typedef OSStatus (*SecKeyComputeMethod)(SecKeyRef key, - const uint8_t *pub_key, size_t pub_key_len, - uint8_t *computed_key, size_t *computed_key_len); -typedef size_t (*SecKeyBlockSizeMethod)(SecKeyRef key); -typedef CFDictionaryRef (*SecKeyCopyDictionaryMethod)(SecKeyRef key); -typedef CFIndex (*SecKeyGetAlgorithmIDMethod)(SecKeyRef key); -typedef OSStatus (*SecKeyCopyPublicBytesMethod)(SecKeyRef key, CFDataRef *serailziation); -typedef CFStringRef (*SecKeyDescribeMethod)(SecKeyRef key); - -#define kSecKeyDescriptorVersion (2) - -typedef struct __SecKeyDescriptor { - /* Version of this SecKeyDescriptor. Must be kSecKeyDescriptorVersion. */ - uint32_t version; - - /* Name of this key class for use by SecKeyShow(). */ - const char *name; - - /* If nonzero, SecKeyCreate will allocate this many bytes for the key - field in the SecKeyRef it creates. If zero key is NULL and the - implementor can choose to dynamically allocate it in the init - function and free it in the destroy function. */ - uint32_t extraBytes; - - /* Called by SecKeyCreate(). */ - SecKeyInitMethod init; - /* Called by destructor (final CFRelease() or gc if using). */ - SecKeyDestroyMethod destroy; - /* Called by SecKeyRawSign(). */ - SecKeyRawSignMethod rawSign; - /* Called by SecKeyRawVerify(). */ - SecKeyRawVerifyMethod rawVerify; - /* Called by SecKeyEncrypt(). */ - SecKeyEncryptMethod encrypt; - /* Called by SecKeyDecrypt(). */ - SecKeyDecryptMethod decrypt; - /* Reserved for future use. */ - SecKeyComputeMethod compute; - /* Called by SecKeyGetBlockSize(). */ - SecKeyBlockSizeMethod blockSize; - /* Called by SecKeyCopyAttributeDictionary(), which is private. */ - SecKeyCopyDictionaryMethod copyDictionary; - /* Called by SecKeyDescribeMethod(). */ - SecKeyDescribeMethod describe; -#if kSecKeyDescriptorVersion > 0 - /* Called by SecKeyCopyAttributeDictionary(), which is private. */ - SecKeyGetAlgorithmIDMethod getAlgorithmID; -#endif -#if kSecKeyDescriptorVersion > 1 - SecKeyCopyPublicBytesMethod copyPublic; -#endif -} SecKeyDescriptor; - -struct __SecKey { - CFRuntimeBase _base; - - const SecKeyDescriptor *key_class; - - /* The actual key handled by class. */ - void *key; -}; - -/*! - @function SecKeyCreate - @abstract Given a private key and data to sign, generate a digital signature. - @param allocator allocator to use when allocating this key instance. - @param key_class pointer to a SecKeyDescriptor. - @param keyData The second argument to the init() function in the key_class. - @param keyDataLength The third argument to the init() function in the key_class. - @param encoding The fourth argument to the init() function in the key_class. - @result A newly allocated SecKeyRef. - */ -SecKeyRef SecKeyCreate(CFAllocatorRef allocator, - const SecKeyDescriptor *key_class, const uint8_t *keyData, - CFIndex keyDataLength, SecKeyEncoding encoding); - -/* Create a public key from an oid, params and keyData all in DER format. */ -SecKeyRef SecKeyCreatePublicFromDER(CFAllocatorRef allocator, - const SecAsn1Oid *oid1, const SecAsn1Item *params, - const SecAsn1Item *keyData); - -/* Create public key from private key */ -SecKeyRef SecKeyCreatePublicFromPrivate(SecKeyRef privateKey); -SecKeyRef SecKeyCopyMatchingPrivateKey(SecKeyRef publicKey, CFErrorRef *error); -CFDataRef SecKeyCreatePersistentRefToMatchingPrivateKey(SecKeyRef publicKey, CFErrorRef *error); - -/* Return an attribute dictionary used to store this item in a keychain. */ -CFDictionaryRef SecKeyCopyAttributeDictionary(SecKeyRef key); - -/* Return a key from an attribute dictionary that was used to store this item - in a keychain. */ -SecKeyRef SecKeyCreateFromAttributeDictionary(CFDictionaryRef refAttributes); - -OSStatus SecKeyDigestAndVerify( - SecKeyRef key, /* Public key */ - const SecAsn1AlgId *algId, /* algorithm oid/params */ - const uint8_t *dataToDigest, /* signature over this data */ - size_t dataToDigestLen,/* length of dataToDigest */ - const uint8_t *sig, /* signature to verify */ - size_t sigLen); /* length of sig */ - -OSStatus SecKeyDigestAndSign( - SecKeyRef key, /* Private key */ - const SecAsn1AlgId *algId, /* algorithm oid/params */ - const uint8_t *dataToDigest, /* signature over this data */ - size_t dataToDigestLen,/* length of dataToDigest */ - uint8_t *sig, /* signature, RETURNED */ - size_t *sigLen); /* IN/OUT */ - -OSStatus SecKeyVerifyDigest( - SecKeyRef key, /* Private key */ - const SecAsn1AlgId *algId, /* algorithm oid/params */ - const uint8_t *digestData, /* signature over this digest */ - size_t digestDataLen,/* length of dataToDigest */ - const uint8_t *sig, /* signature to verify */ - size_t sigLen); /* length of sig */ - -OSStatus SecKeySignDigest( - SecKeyRef key, /* Private key */ - const SecAsn1AlgId *algId, /* algorithm oid/params */ - const uint8_t *digestData, /* signature over this digest */ - size_t digestDataLen,/* length of digestData */ - uint8_t *sig, /* signature, RETURNED */ - size_t *sigLen); /* IN/OUT */ - -OSStatus SecKeyCopyPublicBytes(SecKeyRef key, CFDataRef* serializedPublic); -SecKeyRef SecKeyCreateFromPublicBytes(CFAllocatorRef allocator, CFIndex algorithmID, const uint8_t *keyData, CFIndex keyDataLength); -SecKeyRef SecKeyCreateFromPublicData(CFAllocatorRef allocator, CFIndex algorithmID, CFDataRef serialized); - -CF_RETURNS_RETAINED -CFDictionaryRef SecKeyGeneratePrivateAttributeDictionary(SecKeyRef key, - CFTypeRef keyType, - CFDataRef privateBlob); -CF_RETURNS_RETAINED -CFDictionaryRef SecKeyGeneratePublicAttributeDictionary(SecKeyRef key, CFTypeRef keyType); - -enum { - kSecNullAlgorithmID = 0, - kSecRSAAlgorithmID = 1, - kSecDSAAlgorithmID = 2, /* unsupported, just here for reference. */ - kSecECDSAAlgorithmID = 3, -}; - -CFIndex SecKeyGetAlgorithmID(SecKeyRef key); - -typedef enum { - kSecKeyKeySizeInBits = 0, - kSecKeySignatureSize = 1, - kSecKeyEncryptedDataSize = 2, - // More might belong here, but we aren't settled on how - // to take into account padding and/or digest types. -} SecKeySize; - -/*! - @function SecKeyGetSize - @abstract Returns a size in bytes. - @param key The key for which the block length is requested. - @param whichSize The size that you want evaluated. - @result The block length of the key in bytes. - @discussion If for example key is an RSA key the value returned by - this function is the size of the modulus. - */ -size_t SecKeyGetSize(SecKeyRef key, SecKeySize whichSize) -__OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_5_0); - - -/*! - @function SecKeyLookupPersistentRef - @abstract Looks up a SecKeyRef via persistent ref. - @param persistentRef The persistent ref data for looking up. - @param lookedUpData retained SecKeyRef for the found object. - @result Errors when using SecItemFind for the persistent ref. - */ -OSStatus SecKeyFindWithPersistentRef(CFDataRef persistentRef, SecKeyRef* lookedUpData) -__OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - -/*! - @function SecKeyCopyPersistentRef - @abstract Gets a persistent reference for a key. - @param key Key to make a persistent ref for. - @param persistentRef Allocated data representing the persistent ref. - @result Errors when using SecItemFind for the persistent ref. - */ -OSStatus SecKeyCopyPersistentRef(SecKeyRef key, CFDataRef* persistentRef) -__OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - - - -__END_DECLS - -#endif /* !_SECURITY_SECKEYPRIV_H_ */ diff --git a/sec/Security/SecOTR.h b/sec/Security/SecOTR.h deleted file mode 100644 index 59373388..00000000 --- a/sec/Security/SecOTR.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * SecOTR.h - * libsecurity_libSecOTR - * - * Created by Mitch Adler on 2/2/11. - * Copyright 2011 Apple Inc. All rights reserved. - * - */ - -#ifndef _SECOTR_H_ -#define _SECOTR_H_ - -/* - * Message Protection interfaces -*/ - -#include -#include -#include -#include - -#include - -__BEGIN_DECLS - -/*! - @typedef - @abstract Full identity (public and private) for Message Protection - @discussion Abstracts what kind of crypto is going on beyond it being public/priate -*/ -typedef struct _SecOTRFullIdentity* SecOTRFullIdentityRef; - -/*! - @typedef - @abstract Public identity for Message Protection message validation and encryption to send - @discussion Abstracts what kind of crypto is going on beyond it being public/priate - */ -typedef struct _SecOTRPublicIdentity* SecOTRPublicIdentityRef; - -/* - * Full identity functions - */ -SecOTRFullIdentityRef SecOTRFullIdentityCreate(CFAllocatorRef allocator, CFErrorRef *error); - -SecOTRFullIdentityRef SecOTRFullIdentityCreateFromSecKeyRef(CFAllocatorRef allocator, SecKeyRef privateKey, - CFErrorRef *error); -SecOTRFullIdentityRef SecOTRFullIdentityCreateFromData(CFAllocatorRef allocator, CFDataRef serializedData, CFErrorRef *error); - -SecOTRFullIdentityRef SecOTRFullIdentityCreateFromBytes(CFAllocatorRef allocator, const uint8_t**bytes, size_t *size, CFErrorRef *error); - -bool SecOTRFIPurgeFromKeychain(SecOTRFullIdentityRef thisID, CFErrorRef *error); - -bool SecOTRFIAppendSerialization(SecOTRFullIdentityRef fullID, CFMutableDataRef serializeInto, CFErrorRef *error); - - -bool SecOTRFIPurgeAllFromKeychain(CFErrorRef *error); - - -/* - * Public identity functions - */ -SecOTRPublicIdentityRef SecOTRPublicIdentityCopyFromPrivate(CFAllocatorRef allocator, SecOTRFullIdentityRef fullID, CFErrorRef *error); - -SecOTRPublicIdentityRef SecOTRPublicIdentityCreateFromSecKeyRef(CFAllocatorRef allocator, SecKeyRef publicKey, - CFErrorRef *error); - -SecOTRPublicIdentityRef SecOTRPublicIdentityCreateFromData(CFAllocatorRef allocator, CFDataRef serializedData, CFErrorRef *error); -SecOTRPublicIdentityRef SecOTRPublicIdentityCreateFromBytes(CFAllocatorRef allocator, const uint8_t**bytes, size_t * size, CFErrorRef *error); - -bool SecOTRPIAppendSerialization(SecOTRPublicIdentityRef publicID, CFMutableDataRef serializeInto, CFErrorRef *error); - -void SecOTRAdvertiseHashes(bool advertise); - -__END_DECLS - -#endif diff --git a/sec/Security/SecOTRDHKey.c b/sec/Security/SecOTRDHKey.c deleted file mode 100644 index 7f6aa754..00000000 --- a/sec/Security/SecOTRDHKey.c +++ /dev/null @@ -1,309 +0,0 @@ -// -// SecOTRDHKey.c -// libsecurity_libSecOTR -// -// Created by Mitch Adler on 3/2/11. -// Copyright 2011 Apple Inc. All rights reserved. -// -#include "SecOTRDHKey.h" -#include - -#include "SecOTRMath.h" -#include "SecOTRPacketData.h" - -#include -#include -#include -#include - -#include - -#ifdef USECOMMONCRYPTO -#include -#endif - -#define kECKeySize 256 - -struct _SecOTRFullDHKey { - CFRuntimeBase _base; - - ccec_full_ctx_decl(ccn_sizeof(kECKeySize), _key); - uint8_t keyHash[CCSHA1_OUTPUT_SIZE]; - -}; - -CFGiblisFor(SecOTRFullDHKey); - -static size_t AppendECPublicKeyAsDATA(CFMutableDataRef data, ccec_pub_ctx_t public_key) -{ - size_t size = ccec_export_pub_size(public_key); - - AppendLong(data, (uint32_t)size); /* cast: no overflow, pub size always fit in 32 bits */ - ccec_export_pub(public_key, CFDataIncreaseLengthAndGetMutableBytes(data, (CFIndex)size)); - - return size; -} - - -static CF_RETURNS_RETAINED CFStringRef SecOTRFullDHKeyCopyDescription(CFTypeRef cf) -{ - SecOTRFullDHKeyRef session = (SecOTRFullDHKeyRef)cf; - return CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR(""), session); -} - -static void SecOTRFullDHKeyDestroy(CFTypeRef cf) -{ - SecOTRFullDHKeyRef fullKey = (SecOTRFullDHKeyRef)cf; - - bzero(fullKey->_key, sizeof(fullKey->_key)); -} - -SecOTRFullDHKeyRef SecOTRFullDHKCreate(CFAllocatorRef allocator) -{ - SecOTRFullDHKeyRef newFDHK = CFTypeAllocate(SecOTRFullDHKey, struct _SecOTRFullDHKey, allocator); - - SecFDHKNewKey(newFDHK); - - return newFDHK; -} - -SecOTRFullDHKeyRef SecOTRFullDHKCreateFromBytes(CFAllocatorRef allocator, const uint8_t**bytes, size_t*size) -{ - SecOTRFullDHKeyRef newFDHK = CFTypeAllocate(SecOTRFullDHKey, struct _SecOTRFullDHKey, allocator); - - ccec_ctx_init(ccec_cp_256(), newFDHK->_key); - - uint32_t publicKeySize; - require_noerr(ReadLong(bytes, size, &publicKeySize), fail); - - require(publicKeySize <= *size, fail); - require_noerr(ccec_import_pub(ccec_cp_256(), publicKeySize, *bytes, newFDHK->_key), fail); - ccdigest(ccsha1_di(), publicKeySize, *bytes, newFDHK->keyHash); - - *size -= publicKeySize; - *bytes += publicKeySize; - - require_noerr(ReadMPI(bytes, size, ccec_ctx_n(newFDHK->_key), ccec_ctx_k(newFDHK->_key)), fail); - - return newFDHK; - -fail: - CFReleaseNull(newFDHK); - return NULL; -} - -void SecFDHKNewKey(SecOTRFullDHKeyRef fullKey) -{ - struct ccrng_state *rng=ccDRBGGetRngState(); - -#if defined(CCECDH_AVAILABLE) - ccecdh_generate_key(ccec_cp_256(), rng, fullKey->_key); -#else - ccec_generate_key(ccec_cp_256(), rng, fullKey->_key); -#endif - - size_t size = ccec_export_pub_size(fullKey->_key); - uint8_t publicKey[size]; - - ccec_export_pub(fullKey->_key, publicKey); - ccdigest(ccsha1_di(), size, publicKey, fullKey->keyHash); -} - -void SecFDHKAppendSerialization(SecOTRFullDHKeyRef fullKey, CFMutableDataRef appendTo) -{ - AppendECPublicKeyAsDATA(appendTo, fullKey->_key); - AppendMPI(appendTo, ccec_ctx_n(fullKey->_key), ccec_ctx_k(fullKey->_key)); -} - - -void SecFDHKAppendPublicSerialization(SecOTRFullDHKeyRef fullKey, CFMutableDataRef appendTo) -{ - if(ccec_ctx_bitlen(fullKey->_key) != kECKeySize) return; - AppendECPublicKeyAsDATA(appendTo, fullKey->_key); -} - - -uint8_t* SecFDHKGetHash(SecOTRFullDHKeyRef fullKey) -{ - return fullKey->keyHash; -} - - - - -// -// -// -struct _SecOTRPublicDHKey { - CFRuntimeBase _base; - - ccec_pub_ctx_decl(ccn_sizeof(kECKeySize), _key); - uint8_t keyHash[CCSHA1_OUTPUT_SIZE]; - -}; - -CFGiblisFor(SecOTRPublicDHKey); - -static CF_RETURNS_RETAINED CFStringRef SecOTRPublicDHKeyCopyDescription(CFTypeRef cf) { - SecOTRPublicDHKeyRef session = (SecOTRPublicDHKeyRef)cf; - return CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR(""), session); -} - -static void SecOTRPublicDHKeyDestroy(CFTypeRef cf) { - SecOTRPublicDHKeyRef pubKey = (SecOTRPublicDHKeyRef)cf; - (void) pubKey; -} - -static void ccec_copy_public(ccec_pub_ctx_t source, ccec_pub_ctx_t dest) -{ - ccec_ctx_cp(dest) = ccec_ctx_cp(source); - // TODO: +1?! - ccn_set(3*ccec_ctx_n(source), (cc_unit*) ccec_ctx_point(dest)._p, (cc_unit*) ccec_ctx_point(source)._p); -} - -SecOTRPublicDHKeyRef SecOTRPublicDHKCreateFromFullKey(CFAllocatorRef allocator, SecOTRFullDHKeyRef full) -{ - SecOTRPublicDHKeyRef newPDHK = CFTypeAllocate(SecOTRPublicDHKey, struct _SecOTRPublicDHKey, allocator); - - ccec_copy_public(full->_key, newPDHK->_key); - memcpy(newPDHK->keyHash, full->keyHash, CCSHA1_OUTPUT_SIZE); - - return newPDHK; -} - -SecOTRPublicDHKeyRef SecOTRPublicDHKCreateFromSerialization(CFAllocatorRef allocator, const uint8_t** bytes, size_t *size) -{ - SecOTRPublicDHKeyRef newPDHK = CFTypeAllocate(SecOTRPublicDHKey, struct _SecOTRPublicDHKey, allocator); - - uint32_t publicKeySize; - require_noerr(ReadLong(bytes, size, &publicKeySize), fail); - - require(publicKeySize <= *size, fail); - - require_noerr(ccec_import_pub(ccec_cp_256(), publicKeySize, *bytes, newPDHK->_key), fail); - ccdigest(ccsha1_di(), publicKeySize, *bytes, newPDHK->keyHash); - - *size -= publicKeySize; - *bytes += publicKeySize; - - return newPDHK; -fail: - CFReleaseNull(newPDHK); - return NULL; -} - -SecOTRPublicDHKeyRef SecOTRPublicDHKCreateFromBytes(CFAllocatorRef allocator, const uint8_t** bytes, size_t *size) -{ - SecOTRPublicDHKeyRef newPDHK = CFTypeAllocate(SecOTRPublicDHKey, struct _SecOTRPublicDHKey, allocator); - - require_noerr(ccec_import_pub(ccec_cp_256(), *size, *bytes, newPDHK->_key), fail); - ccdigest(ccsha1_di(), *size, *bytes, newPDHK->keyHash); - - return newPDHK; -fail: - CFReleaseNull(newPDHK); - return NULL; -} - -void SecPDHKAppendSerialization(SecOTRPublicDHKeyRef pubKey, CFMutableDataRef appendTo) -{ - AppendECPublicKeyAsDATA(appendTo, pubKey->_key); -} - - -uint8_t* SecPDHKGetHash(SecOTRPublicDHKeyRef pubKey) -{ - return pubKey->keyHash; -} - - -void SecPDHKeyGenerateS(SecOTRFullDHKeyRef myKey, SecOTRPublicDHKeyRef theirKey, cc_unit* s) -{ - ccn_zero(kExponentiationUnits, s); - - size_t keyLen = ccn_sizeof_n(kExponentiationUnits); - ccec_compute_key(myKey->_key, theirKey->_key, &keyLen, (uint8_t*)s); -} - -static int ccec_cmp(ccec_pub_ctx_t l, ccec_pub_ctx_t r) -{ - size_t lsize = ccec_export_pub_size(l); - size_t rsize = ccec_export_pub_size(r); - - int result = 0; - - if (lsize == rsize) { - uint8_t lpub[lsize]; - uint8_t rpub[rsize]; - - ccec_export_pub(l, lpub); - ccec_export_pub(r, rpub); - - result = memcmp(lpub, rpub, lsize); - } else { - result = rsize < lsize ? -1 : 1; - } - - return result; -} - -bool SecDHKIsGreater(SecOTRFullDHKeyRef myKey, SecOTRPublicDHKeyRef theirKey) -{ - return ccec_cmp(myKey->_key, theirKey->_key) > 0; -} - -static void DeriveKeys(CFDataRef dataToHash, - uint8_t* messageKey, - uint8_t* macKey) -{ - if (messageKey == NULL && macKey == NULL) - return; - - uint8_t hashedSharedKey[CCSHA1_OUTPUT_SIZE]; - -#ifdef USECOMMONCRYPTO - (void) CCDigest(kCCDigestSHA1, CFDataGetBytePtr(dataToHash), (uint32_t)CFDataGetLength(dataToHash), hashedSharedKey); -#else - ccdigest(ccsha1_di(), CFDataGetLength(dataToHash), CFDataGetBytePtr(dataToHash), hashedSharedKey); -#endif - - if (messageKey) - memcpy(messageKey, hashedSharedKey, kOTRMessageKeyBytes); - - if (macKey) { -#ifdef USECOMMONCRYPTO - (void) CCDigest(kCCDigestSHA1, messageKey, kOTRMessageKeyBytes, macKey); -#else - ccdigest(ccsha1_di(), kOTRMessageKeyBytes, messageKey, macKey); -#endif - } - - bzero(hashedSharedKey, sizeof(hashedSharedKey)); -} - -void SecOTRDHKGenerateOTRKeys(SecOTRFullDHKeyRef myKey, SecOTRPublicDHKeyRef theirKey, - uint8_t* sendMessageKey, uint8_t* sendMacKey, - uint8_t* receiveMessageKey, uint8_t* receiveMacKey) -{ - CFMutableDataRef dataToHash = CFDataCreateMutable(kCFAllocatorDefault, 0); - - { - cc_unit s[kExponentiationUnits]; - - SecPDHKeyGenerateS(myKey, theirKey, s); - AppendByte(dataToHash, SecDHKIsGreater(myKey, theirKey) ? 0x01 : 0x02); - AppendMPI(dataToHash, kExponentiationUnits, s); - - ccn_zero(kExponentiationUnits, s); - } - - DeriveKeys(dataToHash, receiveMessageKey, receiveMacKey); - - uint8_t *messageTypeByte = CFDataGetMutableBytePtr(dataToHash); - - *messageTypeByte ^= 0x03; // Invert the bits since it's either 1 or 2. - - DeriveKeys(dataToHash, sendMessageKey, sendMacKey); - - CFReleaseNull(dataToHash); -} diff --git a/sec/Security/SecOTRDHKey.h b/sec/Security/SecOTRDHKey.h deleted file mode 100644 index 70594f18..00000000 --- a/sec/Security/SecOTRDHKey.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// SecOTRDHKey.h -// libsecurity_libSecOTR -// -// Created by Mitch Adler on 3/2/11. -// Copyright 2011 Apple Inc. All rights reserved. -// -#ifndef _SECOTRDHKEY_H_ -#define _SECOTRDHKEY_H_ - -#include -#include -#include - -__BEGIN_DECLS - -typedef struct _SecOTRFullDHKey* SecOTRFullDHKeyRef; -typedef struct _SecOTRPublicDHKey* SecOTRPublicDHKeyRef; - -SecOTRFullDHKeyRef SecOTRFullDHKCreate(CFAllocatorRef allocator); -SecOTRFullDHKeyRef SecOTRFullDHKCreateFromBytes(CFAllocatorRef allocator, const uint8_t**bytes, size_t*size); - -void SecFDHKNewKey(SecOTRFullDHKeyRef key); -void SecFDHKAppendSerialization(SecOTRFullDHKeyRef fullKey, CFMutableDataRef appendTo); -void SecFDHKAppendPublicSerialization(SecOTRFullDHKeyRef fullKey, CFMutableDataRef appendTo); -uint8_t* SecFDHKGetHash(SecOTRFullDHKeyRef pubKey); - - -SecOTRPublicDHKeyRef SecOTRPublicDHKCreateFromFullKey(CFAllocatorRef allocator, SecOTRFullDHKeyRef full); -SecOTRPublicDHKeyRef SecOTRPublicDHKCreateFromSerialization(CFAllocatorRef allocator, const uint8_t**bytes, size_t*size); -SecOTRPublicDHKeyRef SecOTRPublicDHKCreateFromBytes(CFAllocatorRef allocator, const uint8_t** bytes, size_t *size); - -void SecPDHKAppendSerialization(SecOTRPublicDHKeyRef pubKey, CFMutableDataRef appendTo); -uint8_t* SecPDHKGetHash(SecOTRPublicDHKeyRef pubKey); - -void SecPDHKeyGenerateS(SecOTRFullDHKeyRef myKey, SecOTRPublicDHKeyRef theirKey, cc_unit* s); - -bool SecDHKIsGreater(SecOTRFullDHKeyRef myKey, SecOTRPublicDHKeyRef theirKey); - -void SecOTRDHKGenerateOTRKeys(SecOTRFullDHKeyRef myKey, SecOTRPublicDHKeyRef theirKey, - uint8_t* sendMessageKey, uint8_t* sendMacKey, - uint8_t* receiveMessageKey, uint8_t* receiveMacKey); - -__END_DECLS - -#endif diff --git a/sec/Security/SecOTRErrors.h b/sec/Security/SecOTRErrors.h deleted file mode 100644 index c5cea300..00000000 --- a/sec/Security/SecOTRErrors.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// SecOTRErrors.h -// libsecurity_libSecOTR -// -// Created by Keith Henrickson on 4/30/12. -// -// - -#ifndef messsageProtection_SecMessageProtectionErrors_h -#define messsageProtection_SecMessageProtectionErrors_h - -static const CFIndex kSecOTRErrorFailedToEncrypt = -1; -static const CFIndex kSecOTRErrorFailedToDecrypt = -2; -static const CFIndex kSecOTRErrorFailedToVerify = -3; -static const CFIndex kSecOTRErrorFailedToSign = -4; -static const CFIndex kSecOTRErrorSignatureDidNotMatch = -5; -static const CFIndex kSecOTRErrorFailedSelfTest = -6; -static const CFIndex kSecOTRErrorParameterError = -7; -static const CFIndex kSecOTRErrorUnknownFormat = -8; -static const CFIndex kSecOTRErrorCreatePublicIdentity = -9; -static const CFIndex kSecOTRErrorCreatePublicBytes = -10; - -// Errors 100-199 reserved for errors being genrated by workarounds/known issues failing -static const CFIndex kSecOTRErrorSignatureTooLarge = -100; -static const CFIndex kSecOTRErrorSignatureDidNotRecreate = -101; - -#endif diff --git a/sec/Security/SecOTRMath.h b/sec/Security/SecOTRMath.h deleted file mode 100644 index 936e1069..00000000 --- a/sec/Security/SecOTRMath.h +++ /dev/null @@ -1,65 +0,0 @@ -// -// OTRMath.h -// libsecurity_libSecOTR -// -// Created by Mitch Adler on 1/28/11. -// Copyright 2011 Apple Inc. All rights reserved. -// - -#ifndef _SECOTRMATH_H_ -#define _SECOTRMATH_H_ - -#include - -#include -#include -#include - -#define kOTRAuthKeyBytes 16 -#define kOTRAuthMACKeyBytes 32 - -#define kOTRMessageKeyBytes 16 -#define kOTRMessageMacKeyBytes 20 - -#define kExponentiationBits 1536 -#define kExponentiationUnits ccn_nof(kExponentiationBits) -#define kExponentiationBytes ((kExponentiationBits+7)/8) - -#define kSHA256HMAC160Bits 160 -#define kSHA256HMAC160Bytes (kSHA256HMAC160Bits/8) - -// Result and exponent are expected to be kExponentiationUnits big. -void OTRExponentiate(cc_unit* res, const cc_unit* base, const cc_unit* exponent); -void OTRGroupExponentiate(cc_unit* result, const cc_unit* exponent); - -OSStatus GetRandomBytesInLSBs(size_t bytesOfRandomness, size_t n, cc_unit* place); -OSStatus FillWithRandomBytes(size_t n, cc_unit* place); - -typedef enum { - kSSID = 0x00, - kCs = 0x01, - kM1 = 0x02, - kM2 = 0x03, - kM1Prime = 0x04, - kM2Prime = 0x05 -} KeyType; - - -void DeriveOTR256BitsFromS(KeyType whichKey, size_t sSize, const cc_unit* s, size_t keySize, uint8_t* key); -void DeriveOTR128BitPairFromS(KeyType whichHalf, size_t sSize, const cc_unit* s, - size_t firstKeySize, uint8_t* firstKey, - size_t secondKeySize, uint8_t* secondKey); -void DeriveOTR64BitsFromS(KeyType whichKey, size_t sSize, const cc_unit* s, - size_t firstKeySize, uint8_t* firstKey); - - -void AES_CTR_HighHalf_Transform(size_t keySize, const uint8_t* key, - uint64_t highHalf, - size_t howMuch, const uint8_t* from, - uint8_t* to); - -void AES_CTR_IV0_Transform(size_t keySize, const uint8_t* key, - size_t howMuch, const uint8_t* from, - uint8_t* to); - -#endif diff --git a/sec/Security/SecOTRMathPrivate.h b/sec/Security/SecOTRMathPrivate.h deleted file mode 100644 index 5084e5e3..00000000 --- a/sec/Security/SecOTRMathPrivate.h +++ /dev/null @@ -1,121 +0,0 @@ -// -// OTRMathPrivate.h -// libsecurity_libSecOTR -// -// Created by Mitch Adler on 1/28/11. -// Copyright 2011 Apple Inc. All rights reserved. -// - -#ifndef _OTRMATHPRIVATE_H_ -#define _OTRMATHPRIVATE_H_ - -#include - -static const cc_unit kOTRGeneratorValue = 2; - -#define kOTRDHGroupUnits ccn_nof_size(sizeof(kOTRDHGroup)) -static const uint8_t kOTRDHGroup[] = { - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, - 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, - 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, - 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, - 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, - 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, - 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, - 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, - 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, - 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, - 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, - 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, - 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, - 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, - 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, - 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, - 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, - 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, - 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, - 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, - 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, - 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, - 0xCA, 0x23, 0x73, 0x27, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF -}; - -#define kOTRDHGroupRecipUnits ccn_nof_size(sizeof(kOTRDHGroup_Recip)) -static const uint8_t kOTRDHGroup_Recip[] = { - 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x36, 0xF0, 0x25, - 0x5D, 0xDE, 0x97, 0x3D, - 0xCB, 0x47, 0x03, 0xCE, - 0x7E, 0x2E, 0x81, 0x51, - 0x97, 0xA6, 0xDB, 0x0F, - 0x58, 0x84, 0x48, 0xB6, - 0x11, 0x64, 0xCF, 0xCA, - 0xC5, 0xF1, 0x87, 0x2E, - 0x51, 0xB1, 0xF9, 0xFB, - 0xB5, 0xBF, 0x16, 0xFB, - 0xE7, 0x96, 0x89, 0xFC, - 0x09, 0x03, 0xA8, 0x01, - 0xE3, 0xD4, 0x80, 0x2F, - 0xB8, 0xD3, 0x29, 0x55, - 0x0D, 0xC8, 0xC9, 0xD3, - 0xD9, 0x22, 0xEE, 0xCE, - 0x9A, 0x54, 0x75, 0xDB, - 0x33, 0xDB, 0x7B, 0x83, - 0xBB, 0x5C, 0x0E, 0x13, - 0xD1, 0x68, 0x04, 0x9B, - 0xBC, 0x86, 0xC5, 0x81, - 0x76, 0x47, 0xB0, 0x88, - 0xD1, 0x7A, 0xA5, 0xCC, - 0x40, 0xE0, 0x20, 0x35, - 0x58, 0x8E, 0xDB, 0x2D, - 0xE1, 0x89, 0x93, 0x41, - 0x37, 0x19, 0xFC, 0x25, - 0x8D, 0x79, 0xBC, 0x21, - 0x7A, 0xC4, 0xB8, 0x73, - 0x9C, 0xBE, 0xA0, 0x38, - 0xAA, 0xA8, 0x8D, 0x0D, - 0x2F, 0x78, 0xA7, 0x7A, - 0x8A, 0x6F, 0xC7, 0xFA, - 0xA8, 0xB2, 0xBD, 0xCA, - 0x9B, 0xE7, 0x50, 0x2D, - 0x2F, 0x5F, 0x6A, 0x7B, - 0x65, 0xF5, 0xE4, 0xF0, - 0x7A, 0xB8, 0xB2, 0x86, - 0xE4, 0x11, 0x15, 0xF0, - 0x24, 0xA6, 0xE9, 0x76, - 0xBD, 0x2B, 0xCE, 0x3E, - 0x51, 0x90, 0xB8, 0x91, - 0xAB, 0xBF, 0x23, 0x31, - 0xE9, 0xC9, 0x42, 0x97, - 0x73, 0xF1, 0x15, 0xD2, - 0x7D, 0x32, 0xC6, 0x95, - 0xE0 -}; - -#endif diff --git a/sec/Security/SecOTRPacketData.c b/sec/Security/SecOTRPacketData.c deleted file mode 100644 index 577ee059..00000000 --- a/sec/Security/SecOTRPacketData.c +++ /dev/null @@ -1,10 +0,0 @@ -// -// SecOTRPacketData.c -// libsecurity_libSecOTR -// -// Created by Mitch Adler on 2/26/11. -// Copyright 2011 Apple Inc. All rights reserved. -// - -#include "SecOTRPacketData.h" - diff --git a/sec/Security/SecOTRPackets.h b/sec/Security/SecOTRPackets.h deleted file mode 100644 index 09a81ad4..00000000 --- a/sec/Security/SecOTRPackets.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// SecOTRPackets.h -// libsecurity_libSecOTR -// -// Created by Mitch Adler on 2/23/11. -// Copyright 2011 Apple Inc. All rights reserved. -// - -#include - -#include - -#ifndef _SECOTRPACKETS_H_ -#define _SECOTRPACKETS_H_ - -void SecOTRAppendDHMessage(SecOTRSessionRef session, CFMutableDataRef appendTo); -void SecOTRAppendDHKeyMessage(SecOTRSessionRef session, CFMutableDataRef appendTo); -void SecOTRAppendRevealSignatureMessage(SecOTRSessionRef session, CFMutableDataRef appendTo); -void SecOTRAppendSignatureMessage(SecOTRSessionRef session, CFMutableDataRef appendTo); - -typedef enum { - kDHMessage = 0x02, - kDataMessage = 0x03, - kDHKeyMessage = 0x0A, - kRevealSignatureMessage = 0x11, - kSignatureMessage = 0x12, - - kInvalidMessage = 0xFF -} OTRMessageType; - -#endif diff --git a/sec/Security/SecOTRSession.c b/sec/Security/SecOTRSession.c deleted file mode 100644 index 75dd6c64..00000000 --- a/sec/Security/SecOTRSession.c +++ /dev/null @@ -1,777 +0,0 @@ -// -// SecOTRSession.c -// libsecurity_libSecOTR -// -// Created by Mitch Adler on 2/22/11. -// Copyright 2011 Apple Inc. All rights reserved. -// - -#include "SecOTRSession.h" - -#include "SecOTRMath.h" -#include "SecOTRDHKey.h" -#include "SecOTRSessionPriv.h" -#include "SecOTRPackets.h" -#include "SecOTRPacketData.h" - -#include - -#include -#include - -#include -#include -#include - -#include - -#ifdef USECOMMONCRYPTO -#include -#endif - -#include -#include -#include - -#include -#include - -#include - -#include "utilities/comparison.h" - -CFGiblisFor(SecOTRSession); - -static OTRMessageType SecOTRSGetMessageType(CFDataRef message) -{ - OTRMessageType type = kInvalidMessage; - - CFMutableDataRef decodedBytes = CFDataCreateMutable(kCFAllocatorDefault, 0); - SecOTRGetIncomingBytes(message, decodedBytes); - - const uint8_t *bytes = CFDataGetBytePtr(decodedBytes); - size_t size = CFDataGetLength(decodedBytes); - - require_noerr(ReadHeader(&bytes, &size, &type), fail); - -fail: - CFReleaseNull(decodedBytes); - - return type; -} - -const char *SecOTRPacketTypeString(CFDataRef message) -{ - if (!message) return "NoMessage"; - switch (SecOTRSGetMessageType(message)) { - case kDHMessage: return "DHMessage (0x02)"; - case kDataMessage: return "DataMessage (0x03)"; - case kDHKeyMessage: return "DHKeyMessage (0x0A)"; - case kRevealSignatureMessage: return "RevealSignatureMessage (0x11)"; - case kSignatureMessage: return "SignatureMessage (0x12)"; - case kInvalidMessage: return "InvalidMessage (0xFF)"; - default: return "UnknownMessage"; - } -} - -static const char *SecOTRAuthStateString(SecOTRAuthState authState) -{ - switch (authState) { - case kIdle: return "Idle"; - case kAwaitingDHKey: return "AwaitingDHKey"; - case kAwaitingRevealSignature: return "AwaitingRevealSignature"; - case kAwaitingSignature: return "AwaitingSignature"; - case kDone: return "Done"; - default: return "InvalidState"; - } -} - -static CF_RETURNS_RETAINED CFStringRef SecOTRSessionCopyDescription(CFTypeRef cf) { - SecOTRSessionRef session = (SecOTRSessionRef)cf; - return CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR("<%s %s%s%s%s %d:%d %s%s>"), - SecOTRAuthStateString(session->_state), - session->_me ? "F" : "-", - session->_them ? "P" : "-", - session->_receivedDHMessage ? "D" : "-", - session->_receivedDHKeyMessage ? "K" : "-", - session->_keyID, - session->_theirKeyID, - session->_theirPreviousKey ? "P" : "-", - session->_theirKey ? "T" : "-"); -} - -static void SecOTRSessionDestroy(CFTypeRef cf) { - SecOTRSessionRef session = (SecOTRSessionRef)cf; - - CFReleaseNull(session->_receivedDHMessage); - CFReleaseNull(session->_receivedDHKeyMessage); - - CFReleaseNull(session->_me); - CFReleaseNull(session->_myKey); - CFReleaseNull(session->_myNextKey); - - CFReleaseNull(session->_them); - CFReleaseNull(session->_theirKey); - CFReleaseNull(session->_theirPreviousKey); - - CFReleaseNull(session->_macKeysToExpose); - - dispatch_release(session->_queue); -} - -static void SecOTRSessionResetInternal(SecOTRSessionRef session) -{ - session->_state = kIdle; - - CFReleaseNull(session->_receivedDHMessage); - CFReleaseNull(session->_receivedDHKeyMessage); - - session->_keyID = 0; - CFReleaseNull(session->_myKey); - CFReleaseNull(session->_myNextKey); - //session->_myNextKey = SecOTRFullDHKCreate(kCFAllocatorDefault); - session->_theirKeyID = 0; - CFReleaseNull(session->_theirKey); - CFReleaseNull(session->_theirPreviousKey); - CFReleaseNull(session->_macKeysToExpose); - session->_macKeysToExpose = CFDataCreateMutable(kCFAllocatorDefault, 0); - - bzero(session->_keyCache, sizeof(session->_keyCache)); -} - -void SecOTRSessionReset(SecOTRSessionRef session) -{ - dispatch_sync_f(session->_queue, session, (dispatch_function_t) SecOTRSessionResetInternal); -} - - -SecOTRSessionRef SecOTRSessionCreateFromID(CFAllocatorRef allocator, - SecOTRFullIdentityRef myID, - SecOTRPublicIdentityRef theirID) -{ - SecOTRSessionRef newID = CFTypeAllocate(SecOTRSession, struct _SecOTRSession, allocator); - - newID->_queue = dispatch_queue_create("OTRSession", DISPATCH_QUEUE_SERIAL); - - newID->_me = myID; - newID->_them = theirID; - newID->_receivedDHMessage = NULL; - newID->_receivedDHKeyMessage = NULL; - newID->_myKey = NULL; - newID->_myNextKey = NULL; - newID->_theirKey = NULL; - newID->_theirPreviousKey = NULL; - newID->_macKeysToExpose = NULL; - newID->_textOutput = false; - - SecOTRSessionResetInternal(newID); - - CFRetain(newID->_me); - CFRetain(newID->_them); - - return newID; -} - -SecOTRSessionRef SecOTRSessionCreateFromIDAndFlags(CFAllocatorRef allocator, - SecOTRFullIdentityRef myID, - SecOTRPublicIdentityRef theirID, - uint32_t flags) -{ - SecOTRSessionRef newID = SecOTRSessionCreateFromID(allocator, myID, theirID); - if (flags & kSecOTRSendTextMessages) { - newID->_textOutput = true; - } - return newID; -} - -static uint64_t constant_zero = 0; - -static void SecOTRSFindKeysForMessage(SecOTRSessionRef session, - SecOTRFullDHKeyRef myKey, - SecOTRPublicDHKeyRef theirKey, - bool sending, - uint8_t** messageKey, uint8_t** macKey, uint64_t **counter) -{ - SecOTRCacheElement* emptyKeys = NULL; - SecOTRCacheElement* cachedKeys = NULL; - - if ((NULL == myKey) || (NULL == theirKey)) { - if (messageKey) - *messageKey = NULL; - if (macKey) - *macKey = NULL; - if (counter) - *counter = &constant_zero; - - return; - } - - for(int i = 0; i < kOTRKeyCacheSize; ++i) - { - if (0 == constant_memcmp(session->_keyCache[i]._fullKeyHash, SecFDHKGetHash(myKey), CCSHA1_OUTPUT_SIZE) - && (0 == constant_memcmp(session->_keyCache[i]._publicKeyHash, SecPDHKGetHash(theirKey), CCSHA1_OUTPUT_SIZE))) { - cachedKeys = &session->_keyCache[i]; - break; - } - - if (emptyKeys == NULL - && session->_keyCache[i]._fullKey == NULL) { - emptyKeys = &session->_keyCache[i]; - } - } - - if (cachedKeys == NULL) { - if (emptyKeys == NULL) { - syslog(LOG_ERR, "SecOTRSession key cache was full. Should never happen, spooky.\n"); - emptyKeys = &session->_keyCache[0]; - } - - // Fill in the entry. - emptyKeys->_fullKey = myKey; - memcpy(emptyKeys->_fullKeyHash, SecFDHKGetHash(myKey), CCSHA1_OUTPUT_SIZE); - emptyKeys->_publicKey = theirKey; - memcpy(emptyKeys->_publicKeyHash, SecPDHKGetHash(theirKey), CCSHA1_OUTPUT_SIZE); - - emptyKeys->_counter = 0; - emptyKeys->_theirCounter = 0; - - SecOTRDHKGenerateOTRKeys(emptyKeys->_fullKey, emptyKeys->_publicKey, - emptyKeys->_sendEncryptionKey, emptyKeys->_sendMacKey, - emptyKeys->_receiveEncryptionKey, emptyKeys->_receiveMacKey); - - cachedKeys = emptyKeys; - } - - if (messageKey) - *messageKey = sending ? cachedKeys->_sendEncryptionKey : cachedKeys->_receiveEncryptionKey; - if (macKey) - *macKey = sending ? cachedKeys->_sendMacKey : cachedKeys->_receiveMacKey; - if (counter) - *counter = sending ? &cachedKeys->_counter : &cachedKeys->_theirCounter; -} - -SecOTRSessionRef SecOTRSessionCreateFromData(CFAllocatorRef allocator, CFDataRef data) -{ - if (data == NULL) - return NULL; - - SecOTRSessionRef result = NULL; - SecOTRSessionRef session = CFTypeAllocate(SecOTRSession, struct _SecOTRSession, allocator); - - const uint8_t *bytes = CFDataGetBytePtr(data); - size_t size = (size_t)CFDataGetLength(data); - - session->_queue = dispatch_queue_create("OTRSession", DISPATCH_QUEUE_SERIAL); - - session->_me = NULL; - session->_them = NULL; - session->_myKey = NULL; - session->_myNextKey = NULL; - session->_theirKey = NULL; - session->_theirPreviousKey = NULL; - session->_receivedDHMessage = NULL; - session->_receivedDHKeyMessage = NULL; - bzero(session->_keyCache, sizeof(session->_keyCache)); - - uint8_t version; - require_noerr(ReadByte(&bytes, &size, &version), fail); - require(version <= 3, fail); - - require_noerr(ReadLong(&bytes, &size, &session->_state), fail); - session->_me = SecOTRFullIdentityCreateFromBytes(kCFAllocatorDefault, &bytes, &size, NULL); - require(session->_me != NULL, fail); - session->_them = SecOTRPublicIdentityCreateFromBytes(kCFAllocatorDefault, &bytes, &size, NULL); - require(session->_them != NULL, fail); - - require(size > sizeof(session->_r), fail); - memcpy(session->_r, bytes, sizeof(session->_r)); - bytes += sizeof(session->_r); - size -= sizeof(session->_r); - - { - uint8_t hasMessage = false; - ReadByte(&bytes, &size, &hasMessage); - if (hasMessage) { - session->_receivedDHMessage = CFDataCreateMutableFromOTRDATA(kCFAllocatorDefault, &bytes, &size); - } - } - - if (version >= 2) { - uint8_t hasMessage = false; - ReadByte(&bytes, &size, &hasMessage); - if (hasMessage) { - session->_receivedDHKeyMessage = CFDataCreateMutableFromOTRDATA(kCFAllocatorDefault, &bytes, &size); - } - } - - if (version < 3) { - uint8_t ready; - require_noerr(ReadByte(&bytes, &size, &ready), fail); - if (ready && session->_state == kIdle) - session->_state = kDone; - } - - require_noerr(ReadLong(&bytes, &size, &session->_keyID), fail); - if (session->_keyID > 0) { - session->_myKey = SecOTRFullDHKCreateFromBytes(kCFAllocatorDefault, &bytes, &size); - require(session->_myKey != NULL, fail); - session->_myNextKey = SecOTRFullDHKCreateFromBytes(kCFAllocatorDefault, &bytes, &size); - require(session->_myNextKey != NULL, fail); - } - - require_noerr(ReadLong(&bytes, &size, &session->_theirKeyID), fail); - if (session->_theirKeyID > 0) { - if (session->_theirKeyID > 1) { - session->_theirPreviousKey = SecOTRPublicDHKCreateFromSerialization(kCFAllocatorDefault, &bytes, &size); - require(session->_theirPreviousKey != NULL, fail); - } - session->_theirKey = SecOTRPublicDHKCreateFromSerialization(kCFAllocatorDefault, &bytes, &size); - require(session->_theirKey != NULL, fail); - } - - uint64_t *counter; - SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirKey, false, NULL, NULL, &counter); - require_noerr(ReadLongLong(&bytes, &size, counter), fail); - SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirKey, true, NULL, NULL, &counter); - require_noerr(ReadLongLong(&bytes, &size, counter), fail); - SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirPreviousKey, false, NULL, NULL, &counter); - require_noerr(ReadLongLong(&bytes, &size, counter), fail); - SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirPreviousKey, true, NULL, NULL, &counter); - require_noerr(ReadLongLong(&bytes, &size, counter), fail); - SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirKey, false, NULL, NULL, &counter); - require_noerr(ReadLongLong(&bytes, &size, counter), fail); - SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirKey, true, NULL, NULL, &counter); - require_noerr(ReadLongLong(&bytes, &size, counter), fail); - SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirPreviousKey, false, NULL, NULL, &counter); - require_noerr(ReadLongLong(&bytes, &size, counter), fail); - SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirPreviousKey, true, NULL, NULL, &counter); - require_noerr(ReadLongLong(&bytes, &size, counter), fail); - - session->_macKeysToExpose = CFDataCreateMutableFromOTRDATA(kCFAllocatorDefault, &bytes, &size); - require(session->_macKeysToExpose != NULL, fail); - - uint8_t textMode; - require_noerr(ReadByte(&bytes, &size, &textMode), fail); - session->_textOutput = (textMode != 0); - - result = session; - session = NULL; - -fail: - CFReleaseNull(session); - return result; -} - - -OSStatus SecOTRSAppendSerialization(SecOTRSessionRef session, CFMutableDataRef serializeInto) -{ - __block OSStatus result = errSecParam; - - require(session, abort); - require(serializeInto, abort); - - CFIndex start = CFDataGetLength(serializeInto); - - dispatch_sync(session->_queue, ^{ - const uint8_t version = 3; - - CFDataAppendBytes(serializeInto, &version, sizeof(version)); - - AppendLong(serializeInto, session->_state); - - result = (SecOTRFIAppendSerialization(session->_me, serializeInto, NULL)) ? errSecSuccess : errSecParam; - - if (result == errSecSuccess) { - result = (SecOTRPIAppendSerialization(session->_them, serializeInto, NULL)) ? errSecSuccess : errSecParam; - } - - if (result == errSecSuccess) { - CFDataAppendBytes(serializeInto, session->_r, sizeof(session->_r)); - - if (session->_receivedDHMessage == NULL) { - AppendByte(serializeInto, 0); - } else { - AppendByte(serializeInto, 1); - AppendCFDataAsDATA(serializeInto, session->_receivedDHMessage); - } - - if (session->_receivedDHKeyMessage == NULL) { - AppendByte(serializeInto, 0); - } else { - AppendByte(serializeInto, 1); - AppendCFDataAsDATA(serializeInto, session->_receivedDHKeyMessage); - } - - AppendLong(serializeInto, session->_keyID); - if (session->_keyID > 0) { - SecFDHKAppendSerialization(session->_myKey, serializeInto); - SecFDHKAppendSerialization(session->_myNextKey, serializeInto); - } - - AppendLong(serializeInto, session->_theirKeyID); - if (session->_theirKeyID > 0) { - if (session->_theirKeyID > 1) { - SecPDHKAppendSerialization(session->_theirPreviousKey, serializeInto); - } - SecPDHKAppendSerialization(session->_theirKey, serializeInto); - } - - uint64_t *counter; - SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirKey, false, NULL, NULL, &counter); - AppendLongLong(serializeInto, *counter); - SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirKey, true, NULL, NULL, &counter); - AppendLongLong(serializeInto, *counter); - SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirPreviousKey, false, NULL, NULL, &counter); - AppendLongLong(serializeInto, *counter); - SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirPreviousKey, true, NULL, NULL, &counter); - AppendLongLong(serializeInto, *counter); - SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirKey, false, NULL, NULL, &counter); - AppendLongLong(serializeInto, *counter); - SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirKey, true, NULL, NULL, &counter); - AppendLongLong(serializeInto, *counter); - SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirPreviousKey, false, NULL, NULL, &counter); - AppendLongLong(serializeInto, *counter); - SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirPreviousKey, true, NULL, NULL, &counter); - AppendLongLong(serializeInto, *counter); - - AppendCFDataAsDATA(serializeInto, session->_macKeysToExpose); - - AppendByte(serializeInto, session->_textOutput ? 1 : 0); - } - }); - - if (result != errSecSuccess) - CFDataSetLength(serializeInto, start); - -abort: - return result; -} - - -bool SecOTRSGetIsReadyForMessages(SecOTRSessionRef session) -{ - __block bool result; - - dispatch_sync(session->_queue, ^{ result = session->_state == kDone; }); - - return result; -} - -bool SecOTRSGetIsIdle(SecOTRSessionRef session) -{ - __block bool result; - - dispatch_sync(session->_queue, ^{ result = session->_state == kIdle; }); - - return result; -} - -static void SecOTRSExpireCachedKeysForFullKey(SecOTRSessionRef session, SecOTRFullDHKeyRef myKey) -{ - for(int i = 0; i < kOTRKeyCacheSize; ++i) - { - if (0 == constant_memcmp(session->_keyCache[i]._fullKeyHash, SecFDHKGetHash(myKey), CCSHA1_OUTPUT_SIZE)) { - CFDataAppendBytes(session->_macKeysToExpose, session->_keyCache[i]._receiveMacKey, sizeof(session->_keyCache[i]._receiveMacKey)); - - bzero(&session->_keyCache[i], sizeof(session->_keyCache[i])); - } - } -} - -static void SecOTRSExpireCachedKeysForPublicKey(SecOTRSessionRef session, SecOTRPublicDHKeyRef theirKey) -{ - for(int i = 0; i < kOTRKeyCacheSize; ++i) - { - if (0 == constant_memcmp(session->_keyCache[i]._publicKeyHash, SecPDHKGetHash(theirKey), CCSHA1_OUTPUT_SIZE)) { - CFDataAppendBytes(session->_macKeysToExpose, session->_keyCache[i]._receiveMacKey, sizeof(session->_keyCache[i]._receiveMacKey)); - - bzero(&session->_keyCache[i], sizeof(session->_keyCache[i])); - } - } -} - -static void SecOTRSPrecalculateForPair(SecOTRSessionRef session, - SecOTRFullDHKeyRef myKey, - SecOTRPublicDHKeyRef theirKey) -{ - if (myKey == NULL || theirKey == NULL) - return; - - SecOTRSFindKeysForMessage(session, myKey, theirKey, true, NULL, NULL, NULL); - SecOTRSFindKeysForMessage(session, myKey, theirKey, false, NULL, NULL, NULL); -} - -static void SecOTRSPrecalculateKeysInternal(SecOTRSessionRef session) -{ - SecOTRSPrecalculateForPair(session, session->_myKey, session->_theirKey); - SecOTRSPrecalculateForPair(session, session->_myNextKey, session->_theirKey); - SecOTRSPrecalculateForPair(session, session->_myKey, session->_theirPreviousKey); - SecOTRSPrecalculateForPair(session, session->_myNextKey, session->_theirPreviousKey); -} - -void SecOTRSPrecalculateKeys(SecOTRSessionRef session) -{ - dispatch_sync_f(session->_queue, session, (dispatch_function_t) SecOTRSPrecalculateKeysInternal); -} - -enum SecOTRSMessageKind SecOTRSGetMessageKind(SecOTRSessionRef session, CFDataRef message) -{ - enum SecOTRSMessageKind kind = kOTRUnknownPacket; - - CFMutableDataRef decodedBytes = CFDataCreateMutable(kCFAllocatorDefault, 0); - SecOTRGetIncomingBytes(message, decodedBytes); - - const uint8_t *bytes = CFDataGetBytePtr(decodedBytes); - size_t size = CFDataGetLength(decodedBytes); - - OTRMessageType type; - require_noerr(ReadHeader(&bytes, &size, &type), fail); - - kind = (type == kDataMessage) ? kOTRDataPacket : kOTRNegotiationPacket; - -fail: - CFReleaseNull(decodedBytes); - - return kind; -} - -OSStatus SecOTRSSignAndProtectMessage(SecOTRSessionRef session, - CFDataRef sourceMessage, - CFMutableDataRef protectedMessage) -{ - __block OSStatus result = errSecParam; - - require(session, abort); - require(sourceMessage, abort); - require(protectedMessage, abort); - - dispatch_sync(session->_queue, ^{ - if (session->_myKey == NULL || - session->_theirKey == NULL) { - return; - } - - CFMutableDataRef destinationMessage; - if (session->_textOutput) { - destinationMessage = CFDataCreateMutable(kCFAllocatorDefault, 0); - } else { - destinationMessage = protectedMessage; - } - - uint8_t *messageKey; - uint8_t *macKey; - uint64_t *counter; - - CFIndex start = CFDataGetLength(destinationMessage); - - SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirKey, - true, - &messageKey, &macKey, &counter); - - AppendHeader(destinationMessage, kDataMessage); - AppendByte(destinationMessage, 0); // Flags, all zero - - AppendLong(destinationMessage, session->_keyID); - AppendLong(destinationMessage, session->_theirKeyID); - SecFDHKAppendPublicSerialization(session->_myNextKey, destinationMessage); - AppendLongLong(destinationMessage, ++*counter); - - CFIndex sourceSize = CFDataGetLength(sourceMessage); - assert(((unsigned long)sourceSize)<=UINT32_MAX); /* this is correct as long as CFIndex is a signed long */ - AppendLong(destinationMessage, (uint32_t)sourceSize); - uint8_t* encryptedDataPointer = CFDataIncreaseLengthAndGetMutableBytes(destinationMessage, sourceSize); - AES_CTR_HighHalf_Transform(kOTRMessageKeyBytes, messageKey, - *counter, - (size_t)sourceSize, CFDataGetBytePtr(sourceMessage), - encryptedDataPointer); - - CFIndex macedContentsSize = CFDataGetLength(destinationMessage) - start; - CFIndex macSize = CCSHA1_OUTPUT_SIZE; - uint8_t* macDataPointer = CFDataIncreaseLengthAndGetMutableBytes(destinationMessage, macSize); - -#ifdef USECOMMONCRYPTO - CCHmac(kCCHmacAlgSHA1, - macKey, kOTRMessageMacKeyBytes, - CFDataGetBytePtr(destinationMessage) + start, (size_t)macedContentsSize, - macDataPointer); -#else - cchmac(ccsha1_di(), - kOTRMessageMacKeyBytes, macKey, - macedContentsSize, CFDataGetBytePtr(destinationMessage) + start, - macDataPointer); -#endif - - CFDataAppend(destinationMessage, session->_macKeysToExpose); - - CFDataSetLength(session->_macKeysToExpose, 0); - - if (session->_textOutput) { - SecOTRPrepareOutgoingBytes(destinationMessage, protectedMessage); - CFReleaseSafe(destinationMessage); - } - - result = errSecSuccess; - }); - -abort: - return result; -} - -OSStatus SecOTRSVerifyAndExposeMessage(SecOTRSessionRef session, - CFDataRef incomingMessage, - CFMutableDataRef exposedMessageContents) -{ - __block SecOTRPublicDHKeyRef newKey = NULL; - __block OSStatus result = errSecParam; - - - require(session, abort); - require(incomingMessage, abort); - require(exposedMessageContents, abort); - - dispatch_sync(session->_queue, ^{ - const uint8_t* bytes; - size_t size; - CFMutableDataRef decodedBytes = CFDataCreateMutable(kCFAllocatorDefault, 0); - SecOTRGetIncomingBytes(incomingMessage, decodedBytes); - - bytes = CFDataGetBytePtr(decodedBytes); - size = CFDataGetLength(decodedBytes); - - const uint8_t* macDataStart = bytes; - - uint32_t theirID; - uint32_t myID; - - if ((result = ReadAndVerifyHeader(&bytes, &size, kDataMessage))){ - CFReleaseSafe(decodedBytes); - return; - } - - if (size <= 0) { result = errSecDecode; CFReleaseSafe(decodedBytes); return; } - - if ((result = ReadAndVerifyByte(&bytes, &size, 0))) { CFReleaseSafe(decodedBytes); return;} // No flags - - if ((result = ReadLong(&bytes, &size, &theirID))){ CFReleaseSafe(decodedBytes); return; } - - if (theirID != session->_theirKeyID && - (session->_theirPreviousKey == NULL || theirID != (session->_theirKeyID - 1))) - { - result = ((theirID + 1) < session->_theirKeyID) ? errSecOTRTooOld : errSecOTRIDTooNew; - CFReleaseSafe(decodedBytes); - return; - }; - - if ((result = ReadLong(&bytes, &size, &myID))){ CFReleaseSafe(decodedBytes); return; } - if (myID != session->_keyID && myID != (session->_keyID + 1)) - { - result = (myID < session->_keyID) ? errSecOTRTooOld : errSecOTRIDTooNew; - CFReleaseSafe(decodedBytes); - return; - }; - - - // Choose appripriate keys for message: - { - uint8_t *messageKey; - uint8_t *macKey; - uint64_t *theirCounter; - - SecOTRFullDHKeyRef myKeyForMessage = (myID == session->_keyID) ? session->_myKey : session->_myNextKey; - SecOTRPublicDHKeyRef theirKeyForMessage = (theirID == session->_theirKeyID) ? session->_theirKey : session->_theirPreviousKey; - - SecOTRSFindKeysForMessage(session, myKeyForMessage, theirKeyForMessage, false, - &messageKey, &macKey, &theirCounter); - - size_t nextKeyMPISize; - const uint8_t* nextKeyMPIBytes; - if ((result = SizeAndSkipMPI(&bytes, &size, &nextKeyMPIBytes, &nextKeyMPISize))){ CFReleaseSafe(decodedBytes); return;} - - uint64_t counter; - if ((result = ReadLongLong(&bytes, &size, &counter))) { CFReleaseSafe(decodedBytes); return; } - - if (counter <= *theirCounter) { result = errSecOTRTooOld; CFReleaseSafe(decodedBytes); return; }; - - size_t messageSize; - const uint8_t* messageStart; - if ((result = SizeAndSkipDATA(&bytes, &size, &messageStart, &messageSize))) { CFReleaseSafe(decodedBytes); return; } - - size_t macDataSize = (bytes - macDataStart) ? (size_t)(bytes - macDataStart) : 0; - uint8_t mac[CCSHA1_OUTPUT_SIZE]; - if (sizeof(mac) > size) { result = errSecDecode; CFReleaseSafe(decodedBytes); return; } - -#ifdef USECOMMONCRYPTO - CCHmac(kCCHmacAlgSHA1, - macKey, kOTRMessageMacKeyBytes, - macDataStart, macDataSize, - mac); -#else - cchmac(ccsha1_di(), - kOTRMessageMacKeyBytes, macKey, - macDataSize, macDataStart, - mac); -#endif - - if (0 != constant_memcmp(mac, bytes, sizeof(mac))) { result = errSecAuthFailed; CFReleaseSafe(decodedBytes); return; } - //if (messageSize > 65535) { result = errSecDataTooLarge; CFReleaseSafe(decodedBytes); return; } - uint8_t* dataSpace = CFDataIncreaseLengthAndGetMutableBytes(exposedMessageContents, (CFIndex)messageSize); - - - AES_CTR_HighHalf_Transform(kOTRMessageKeyBytes, messageKey, - counter, - messageSize, messageStart, - dataSpace); - - // Everything is good, accept the meta data. - *theirCounter = counter; - - newKey = SecOTRPublicDHKCreateFromBytes(kCFAllocatorDefault, &nextKeyMPIBytes, &nextKeyMPISize); - } - - SecOTRSPrecalculateKeysInternal(session); - - bool acceptTheirNewKey = newKey != NULL && theirID == session->_theirKeyID; - - if (acceptTheirNewKey) { - if (session->_theirPreviousKey) { - SecOTRSExpireCachedKeysForPublicKey(session, session->_theirPreviousKey); - } - - CFReleaseNull(session->_theirPreviousKey); - session->_theirPreviousKey = session->_theirKey; - session->_theirKey = newKey; - - session->_theirKeyID += 1; - - newKey = NULL; - } - - if (myID == (session->_keyID + 1)) { - SecOTRSExpireCachedKeysForFullKey(session, session->_myKey); - - // Swap the keys so we know the current key. - { - SecOTRFullDHKeyRef oldKey = session->_myKey; - session->_myKey = session->_myNextKey; - session->_myNextKey = oldKey; - } - - // Derive a new next key by regenerating over the old key. - SecFDHKNewKey(session->_myNextKey); - - session->_keyID = myID; - } - CFReleaseSafe(decodedBytes); - }); - -abort: - CFReleaseNull(newKey); - return result; -} - - -OSStatus SecOTRSEndSession(SecOTRSessionRef session, - CFMutableDataRef messageToSend) -{ - return errSecUnimplemented; -} diff --git a/sec/Security/SecOTRSession.h b/sec/Security/SecOTRSession.h deleted file mode 100644 index cd06a6ee..00000000 --- a/sec/Security/SecOTRSession.h +++ /dev/null @@ -1,112 +0,0 @@ -// -// SecOTRSession.h -// libsecurity_libSecOTR -// -// Created by Mitch Adler on 2/22/11. -// Copyright 2011 Apple Inc. All rights reserved. -// - -#ifndef _SECOTRSESSION_H_ -#define _SECOTRSESSION_H_ - -#include -#include - -#include - -__BEGIN_DECLS - -// MARK: MessageTypes - -enum SecOTRSMessageKind { - kOTRNegotiationPacket, - kOTRDataPacket, - kOTRUnknownPacket -}; - -// MARK: OTR Session - -enum SecOTRCreateFlags { - kSecOTRSendTextMessages = 1, // OTR messages will be encoded as Base-64 with header/footer per the standard, not just given back in binary -}; - -/*! - @typedef - @abstract OTRSessions encapsulate a commuincaiton between to parties using the - otr protocol. - @discussion Sessions start with IDs. One end sends a start packet (created with AppendStartPacket). - Both sides process packets they exchange on the negotiation channel. - */ -typedef struct _SecOTRSession* SecOTRSessionRef; - -SecOTRSessionRef SecOTRSessionCreateFromID(CFAllocatorRef allocator, - SecOTRFullIdentityRef myID, - SecOTRPublicIdentityRef theirID); - -SecOTRSessionRef SecOTRSessionCreateFromIDAndFlags(CFAllocatorRef allocator, - SecOTRFullIdentityRef myID, - SecOTRPublicIdentityRef theirID, - uint32_t flags); - -SecOTRSessionRef SecOTRSessionCreateFromData(CFAllocatorRef allocator, CFDataRef data); - - void SecOTRSessionReset(SecOTRSessionRef session); -OSStatus SecOTRSAppendSerialization(SecOTRSessionRef publicID, CFMutableDataRef serializeInto); - -OSStatus SecOTRSAppendStartPacket(SecOTRSessionRef session, CFMutableDataRef appendInitiatePacket); - -OSStatus SecOTRSAppendRestartPacket(SecOTRSessionRef session, CFMutableDataRef appendPacket); - -OSStatus SecOTRSProcessPacket(SecOTRSessionRef session, - CFDataRef incomingPacket, - CFMutableDataRef negotiationResponse); - -OSStatus SecOTRSEndSession(SecOTRSessionRef session, - CFMutableDataRef messageToSend); - - -bool SecOTRSGetIsReadyForMessages(SecOTRSessionRef session); -bool SecOTRSGetIsIdle(SecOTRSessionRef session); - -enum SecOTRSMessageKind SecOTRSGetMessageKind(SecOTRSessionRef session, CFDataRef incomingPacket); - -/*! - @function - @abstract Precalculates keys for current key sets to save time when sending or receiving. - @param session OTRSession receiving message - */ -void SecOTRSPrecalculateKeys(SecOTRSessionRef session); - -/*! - @function - @abstract Encrypts and Signs a message with OTR credentials. - @param session OTRSession receiving message - @param incomingMessage Cleartext message to protect - @param protectedMessage Data to append the encoded protected message to - @result OSStatus errSecAuthFailed -> bad signature, no data appended. - */ - -OSStatus SecOTRSSignAndProtectMessage(SecOTRSessionRef session, - CFDataRef sourceMessage, - CFMutableDataRef protectedMessage); - -/*! - @function - @abstract Verifies and exposes a message sent via OTR - @param session OTRSession receiving message - @param incomingMessage Encoded message - @param exposedMessageContents Data to append the exposed message to - @result OSStatus errSecAuthFailed -> bad signature, no data appended. - */ - -OSStatus SecOTRSVerifyAndExposeMessage(SecOTRSessionRef session, - CFDataRef incomingMessage, - CFMutableDataRef exposedMessageContents); - - - -const char *SecOTRPacketTypeString(CFDataRef message); - -__END_DECLS - -#endif diff --git a/sec/Security/SecOTRSessionPriv.h b/sec/Security/SecOTRSessionPriv.h deleted file mode 100644 index cf738c4f..00000000 --- a/sec/Security/SecOTRSessionPriv.h +++ /dev/null @@ -1,92 +0,0 @@ -// -// SecOTRSessionPriv.h -// libsecurity_libSecOTR -// -// Created by Mitch Adler on 2/23/11. -// Copyright 2011 Apple Inc. All rights reserved. -// - -#ifndef _SECOTRSESSIONPRIV_H_ -#define _SECOTRSESSIONPRIV_H_ - -#include -#include - -#include -#include -#include -#include - -#include - -#include - -#include -#include - -__BEGIN_DECLS - -typedef enum { - kIdle, - kAwaitingDHKey, - kAwaitingRevealSignature, - kAwaitingSignature, - kDone -} SecOTRAuthState; - -struct _SecOTRCacheElement { - SecOTRFullDHKeyRef _fullKey; - uint8_t _fullKeyHash[CCSHA1_OUTPUT_SIZE]; - SecOTRPublicDHKeyRef _publicKey; - uint8_t _publicKeyHash[CCSHA1_OUTPUT_SIZE]; - - uint8_t _sendMacKey[kOTRMessageMacKeyBytes]; - uint8_t _sendEncryptionKey[kOTRMessageKeyBytes]; - - uint8_t _receiveMacKey[kOTRMessageMacKeyBytes]; - uint8_t _receiveEncryptionKey[kOTRMessageKeyBytes]; - - uint64_t _counter; - uint64_t _theirCounter; - -}; -typedef struct _SecOTRCacheElement SecOTRCacheElement; - -#define kOTRKeyCacheSize 4 - -struct _SecOTRSession { - CFRuntimeBase _base; - - SecOTRAuthState _state; - - SecOTRFullIdentityRef _me; - SecOTRPublicIdentityRef _them; - - uint8_t _r[kOTRAuthKeyBytes]; - - CFDataRef _receivedDHMessage; - CFDataRef _receivedDHKeyMessage; - - uint32_t _keyID; - SecOTRFullDHKeyRef _myKey; - SecOTRFullDHKeyRef _myNextKey; - - uint32_t _theirKeyID; - SecOTRPublicDHKeyRef _theirPreviousKey; - SecOTRPublicDHKeyRef _theirKey; - - CFMutableDataRef _macKeysToExpose; - - dispatch_queue_t _queue; - - SecOTRCacheElement _keyCache[kOTRKeyCacheSize]; - - bool _textOutput; -}; - -void SecOTRGetIncomingBytes(CFDataRef incomingMessage, CFMutableDataRef decodedBytes); -void SecOTRPrepareOutgoingBytes(CFMutableDataRef destinationMessage, CFMutableDataRef protectedMessage); - -__END_DECLS - -#endif diff --git a/sec/Security/SecOnOSX.h b/sec/Security/SecOnOSX.h deleted file mode 100644 index 1bc01bd4..00000000 --- a/sec/Security/SecOnOSX.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// SecOnOSX.h -// messsageProtection -// -// Created by Keith on 10/21/11. -// Copyright (c) 2011 __MyCompanyName__. All rights reserved. -// - -#ifndef _SECONOSX_H_ -#define _SECONOSX_H_ - -#include - -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) - -#include - -#define SecKeyCreateFromPublicData _SecKeyCreateFromPublicData - -#if 0 -SecKeyRef SecKeyCreateFromPublicData(CFAllocatorRef allocator, CFIndex algorithmID, CFDataRef serialized); -#endif - -#endif /* TARGET_OS_MAC */ - -#endif /* _SECONOSX_H_ */ - - diff --git a/sec/Security/SecPolicy.h b/sec/Security/SecPolicy.h deleted file mode 100644 index ccb1717f..00000000 --- a/sec/Security/SecPolicy.h +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (c) 2002-2010,2012-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@ - */ - -/*! - @header SecPolicy - The functions provided in SecPolicy.h provide an interface to various - X.509 certificate trust policies. -*/ - -#ifndef _SECURITY_SECPOLICY_H_ -#define _SECURITY_SECPOLICY_H_ - -#include -#include -#include - -__BEGIN_DECLS - -/*! - @enum Policy Constants - @discussion Predefined constants used to specify a policy. - @constant kSecPolicyAppleX509Basic - @constant kSecPolicyAppleSSL - @constant kSecPolicyAppleSMIME - @constant kSecPolicyAppleEAP - @constant kSecPolicyAppleIPsec - @constant kSecPolicyApplePKINITClient - @constant kSecPolicyApplePKINITServer - @constant kSecPolicyAppleCodeSigning - @constant kSecPolicyMacAppStoreReceipt - @constant kSecPolicyAppleIDValidation - @constant kSecPolicyAppleTimeStamping - @constant kSecPolicyAppleRevocation -*/ -extern CFTypeRef kSecPolicyAppleX509Basic - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleSSL - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleSMIME - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleEAP - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleIPsec - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPolicyApplePKINITClient - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyApplePKINITServer - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyAppleCodeSigning - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPolicyMacAppStoreReceipt - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyAppleIDValidation - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleTimeStamping - __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleRevocation - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - -/*! - @enum Policy Value Constants - @abstract Predefined property key constants used to get or set values in - a dictionary for a policy instance. - @discussion - All policies will have the following read-only value: - kSecPolicyOid (the policy object identifier) - - Additional policy values which your code can optionally set: - kSecPolicyName (name which must be matched) - kSecPolicyClient (evaluate for client, rather than server) - kSecPolicyRevocationFlags (only valid for a revocation policy) - - @constant kSecPolicyOid Specifies the policy OID (value is a CFStringRef) - @constant kSecPolicyName Specifies a CFStringRef (or CFArrayRef of same) - containing a name which must be matched in the certificate to satisfy - this policy. For SSL/TLS, EAP, and IPSec policies, this specifies the - server name which must match the common name of the certificate. - For S/MIME, this specifies the RFC822 email address. - @constant kSecPolicyClient Specifies a CFBooleanRef value that indicates - this evaluation should be for a client certificate. If not set (or - false), the policy evaluates the certificate as a server certificate. - @constant kSecPolicyRevocationFlags Specifies a CFNumberRef that holds a - kCFNumberCFIndexType bitmask value. See "Revocation Policy Constants" - for a description of individual bits in this value. - */ -extern CFTypeRef kSecPolicyOid - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPolicyName - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPolicyClient - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPolicyRevocationFlags - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - - -/*! - @function SecPolicyGetTypeID - @abstract Returns the type identifier of SecPolicy instances. - @result The CFTypeID of SecPolicy instances. -*/ -CFTypeID SecPolicyGetTypeID(void) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -/*! - @function SecPolicyCopyProperties - @abstract Returns a dictionary of this policy's properties. - @param policyRef A policy reference. - @result A properties dictionary. See "Policy Value Constants" for a list - of currently defined property keys. It is the caller's responsibility to - CFRelease this reference when it is no longer needed. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function returns the properties for a policy, as set by the - policy's construction function or by a prior call to SecPolicySetProperties. -*/ -CFDictionaryRef SecPolicyCopyProperties(SecPolicyRef policyRef) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); - -/*! - @function SecPolicyCreateBasicX509 - @abstract Returns a policy object for the default X.509 policy. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -SecPolicyRef SecPolicyCreateBasicX509(void) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @function SecPolicyCreateSSL - @abstract Returns a policy object for evaluating SSL certificate chains. - @param server Passing true for this parameter creates a policy for SSL - server certificates. - @param hostname (Optional) If present, the policy will require the specified - hostname to match the hostname in the leaf certificate. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -SecPolicyRef SecPolicyCreateSSL(Boolean server, CFStringRef hostname) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @enum Revocation Policy Constants - @abstract Predefined constants which allow you to specify how revocation - checking will be performed for a trust evaluation. - @constant kSecRevocationOCSPMethod If this flag is set, perform revocation - checking using OCSP (Online Certificate Status Protocol). - @constant kSecRevocationCRLMethod If this flag is set, perform revocation - checking using the CRL (Certificate Revocation List) method. - @constant kSecRevocationPreferCRL If this flag is set, then CRL revocation - checking will be preferred over OCSP (by default, OCSP is preferred.) - Note that this flag only matters if both revocation methods are specified. - @constant kSecRevocationRequirePositiveResponse If this flag is set, then - the policy will fail unless a verified positive response is obtained. If - the flag is not set, revocation checking is done on a "best attempt" basis, - where failure to reach the server is not considered fatal. - @constant kSecRevocationNetworkAccessDisabled If this flag is set, then - no network access is performed; only locally cached replies are consulted. - @constant kSecRevocationUseAnyAvailableMethod Specifies that either - OCSP or CRL may be used, depending on the method(s) specified in the - certificate and the value of kSecRevocationPreferCRL. - */ -enum { - kSecRevocationOCSPMethod = (1 << 0), - kSecRevocationCRLMethod = (1 << 1), - kSecRevocationPreferCRL = (1 << 2), - kSecRevocationRequirePositiveResponse = (1 << 3), - kSecRevocationNetworkAccessDisabled = (1 << 4), - kSecRevocationUseAnyAvailableMethod = (kSecRevocationOCSPMethod | - kSecRevocationCRLMethod) -}; - -/*! - @function SecPolicyCreateRevocation - @abstract Returns a policy object for checking revocation of certificates. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. - @param revocationFlags Flags to specify revocation checking options. - @discussion Use this function to create a revocation policy with behavior - specified by revocationFlags. See the "Revocation Policy Constants" section - for a description of these flags. Note: it is usually not necessary to - create a revocation policy yourself unless you wish to override default - system behavior (e.g. to force a particular method, or to disable - revocation checking entirely.) -*/ -SecPolicyRef SecPolicyCreateRevocation(CFOptionFlags revocationFlags) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - -/*! - @function SecPolicyCreateWithProperties - @abstract Returns a policy object based on an object identifier for the - policy type. See the "Policy Constants" section for a list of defined - policy object identifiers. - @param policyIdentifier The identifier for the desired policy type. - @param properties (Optional) A properties dictionary. See "Policy Value - Constants" for a list of currently defined property keys. - @result The returned policy reference, or NULL if the policy could not be - created. -*/ -SecPolicyRef SecPolicyCreateWithProperties(CFTypeRef policyIdentifier, - CFDictionaryRef properties) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - - -/* - * Legacy functions (OS X only) - */ -#if TARGET_OS_MAC && !TARGET_OS_IPHONE -#include - -/*! - @enum Policy Value Constants (OS X) - @discussion Predefined property key constants used to get or set values in - a dictionary for a policy instance. - - Some policy values may specify CFBooleanRef key usage constraints: - kSecPolicyKU_DigitalSignature - kSecPolicyKU_NonRepudiation - kSecPolicyKU_KeyEncipherment - kSecPolicyKU_DataEncipherment - kSecPolicyKU_KeyAgreement - kSecPolicyKU_KeyCertSign - kSecPolicyKU_CRLSign - kSecPolicyKU_EncipherOnly - kSecPolicyKU_DecipherOnly - - kSecPolicyKU policy values define certificate-level key purposes, - in contrast to the key-level definitions in SecItem.h - - For example, a key in a certificate might be acceptable to use for - signing a CRL, but not for signing another certificate. In either - case, this key would have the ability to sign (i.e. kSecAttrCanSign - is true), but may only sign for specific purposes allowed by these - policy constants. Similarly, a public key might have the capability - to perform encryption or decryption, but the certificate in which it - resides might have a decipher-only certificate policy. - - These constants correspond to values defined in RFC 5280, section - 4.2.1.3 (Key Usage) which define the purpose of a key contained in a - certificate, in contrast to section 4.1.2.7 which define the uses that - a key is capable of. - - Note: these constants are not available on iOS. Your code should - avoid direct reliance on these values for making policy decisions - and use higher level policies where possible. - - @constant kSecPolicyKU_DigitalSignature Specifies that the certificate must - have a key usage that allows it to be used for signing. - @constant kSecPolicyKU_NonRepudiation Specifies that the certificate must - have a key usage that allows it to be used for non-repudiation. - @constant kSecPolicyKU_KeyEncipherment Specifies that the certificate must - have a key usage that allows it to be used for key encipherment. - @constant kSecPolicyKU_DataEncipherment Specifies that the certificate must - have a key usage that allows it to be used for data encipherment. - @constant kSecPolicyKU_KeyAgreement Specifies that the certificate must - have a key usage that allows it to be used for key agreement. - @constant kSecPolicyKU_KeyCertSign Specifies that the certificate must - have a key usage that allows it to be used for signing certificates. - @constant kSecPolicyKU_CRLSign Specifies that the certificate must - have a key usage that allows it to be used for signing CRLs. - @constant kSecPolicyKU_EncipherOnly Specifies that the certificate must - have a key usage that permits it to be used for encryption only. - @constant kSecPolicyKU_DecipherOnly Specifies that the certificate must - have a key usage that permits it to be used for decryption only. - */ -extern CFTypeRef kSecPolicyKU_DigitalSignature - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyKU_NonRepudiation - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyKU_KeyEncipherment - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyKU_DataEncipherment - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyKU_KeyAgreement - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyKU_KeyCertSign - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyKU_CRLSign - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyKU_EncipherOnly - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); -extern CFTypeRef kSecPolicyKU_DecipherOnly - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/*! - @function SecPolicyCreateWithOID - @abstract Returns a policy object based on an object identifier for the - policy type. See the "Policy Constants" section for a list of defined - policy object identifiers. - @param policyOID The OID of the desired policy. - @result The returned policy reference, or NULL if the policy could not be - created. - @discussion This function is deprecated in Mac OS X 10.9 and later; - use SecPolicyCreateWithProperties (or a more specific policy creation - function) instead. -*/ -SecPolicyRef SecPolicyCreateWithOID(CFTypeRef policyOID) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecPolicyGetOID - @abstract Returns a policy's object identifier. - @param policyRef A policy reference. - @param oid On return, a pointer to the policy's object identifier. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in Mac OS X 10.7 and later; - use SecPolicyCopyProperties instead. -*/ -OSStatus SecPolicyGetOID(SecPolicyRef policyRef, CSSM_OID *oid) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecPolicyGetValue - @abstract Returns a policy's value. - @param policyRef A policy reference. - @param value On return, a pointer to the policy's value. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in Mac OS X 10.7 and later; - use SecPolicyCopyProperties instead. -*/ -OSStatus SecPolicyGetValue(SecPolicyRef policyRef, CSSM_DATA *value) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecPolicySetValue - @abstract Sets a policy's value. - @param policyRef A policy reference. - @param value The value to be set into the policy object, replacing any - previous value. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in Mac OS X 10.7 and later. Policy - instances should be considered read-only; in cases where your code would - consider changing properties of a policy, it should instead create a new - policy instance with the desired properties. -*/ -OSStatus SecPolicySetValue(SecPolicyRef policyRef, const CSSM_DATA *value) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecPolicySetProperties - @abstract Sets a policy's properties. - @param policyRef A policy reference. - @param properties A properties dictionary. See "Policy Value Constants" - for a list of currently defined property keys. This dictionary replaces the - policy's existing properties, if any. Note that the policy OID (specified - by kSecPolicyOid) is a read-only property of the policy and cannot be set. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in Mac OS X 10.9 and later. Policy - instances should be considered read-only; in cases where your code would - consider changing properties of a policy, it should instead create a new - policy instance with the desired properties. -*/ -OSStatus SecPolicySetProperties(SecPolicyRef policyRef, - CFDictionaryRef properties) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecPolicyGetTPHandle - @abstract Returns the CSSM trust policy handle for the given policy. - @param policyRef A policy reference. - @param tpHandle On return, a pointer to a value of type CSSM_TP_HANDLE. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in Mac OS X 10.7 and later. -*/ -OSStatus SecPolicyGetTPHandle(SecPolicyRef policyRef, CSSM_TP_HANDLE *tpHandle) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - -#endif /* TARGET_OS_MAC && !TARGET_OS_IPHONE */ - - -__END_DECLS - -#endif /* !_SECURITY_SECPOLICY_H_ */ diff --git a/sec/Security/SecPolicyPriv.h b/sec/Security/SecPolicyPriv.h deleted file mode 100644 index 306b3364..00000000 --- a/sec/Security/SecPolicyPriv.h +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Copyright (c) 2007-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@ - */ - -/*! - @header SecPolicyPriv - The functions provided in SecPolicyPriv provide an interface to various - X.509 certificate trust policies. -*/ - -#ifndef _SECURITY_SECPOLICYPRIV_H_ -#define _SECURITY_SECPOLICYPRIV_H_ - -#include -#include -#include -#include - -__BEGIN_DECLS - -/*! - @enum Policy Constants (Private) - @discussion Predefined constants used to specify a policy. - @constant kSecPolicyApplePassbookSigning - @constant kSecPolicyAppleMobileStore - @constant kSecPolicyAppleTestMobileStore - @constant kSecPolicyAppleEscrowService - @constant kSecPolicyAppleProfileSigner - @constant kSecPolicyAppleQAProfileSigner - @constant kSecPolicyAppleOTAPKISigner - @constant kSecPolicyAppleTestOTAPKISigner - -*/ -extern CFTypeRef kSecPolicyApplePassbookSigning - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleMobileStore - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleTestMobileStore - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleEscrowService - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleProfileSigner - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleQAProfileSigner - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -#if TARGET_OS_IPHONE -extern CFTypeRef kSecPolicyAppleOTAPKISigner - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleTestOTAPKISigner - __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_7_0); -extern CFTypeRef kSecPolicyAppleIDValidationRecordSigningPolicy - __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_7_0); -#endif - - -/*! - @enum Policy Value Constants - @abstract Predefined property key constants used to get or set values in - a dictionary for a policy instance. - @constant kSecPolicyTeamIdentifier Specifies a CFStringRef containing a - team identifier which must be matched in the certificate to satisfy - this policy. For the Passbook signing policy, this string must match - the Organizational Unit field of the certificate subject. -*/ -extern CFTypeRef kSecPolicyTeamIdentifier - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - -/*! - @function SecPolicyCreateiPhoneActivation - @abstract Returns a policy object for verifying iPhone Activation - certificate chains. - @discussion This policy is like the Basic X.509 policy with the additional - requirements that the chain must contain exactly three certificates, the - anchor is the Apple Inc. CA, and the subject of the first intermediate - certificate has "Apple iPhone Certification Authority" as its only - Common Name entry. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -SecPolicyRef SecPolicyCreateiPhoneActivation(void); - -/*! - @function SecPolicyCreateiPhoneDeviceCertificate - @abstract Returns a policy object for verifying iPhone Device certificate - chains. - @discussion This policy is like the Basic X.509 policy with the additional - requirements that the chain must contain exactly four certificates, the - anchor is the Apple Inc. CA, and the subject of the first intermediate - certificate has "Apple iPhone Device CA" as its only Common Name entry. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -SecPolicyRef SecPolicyCreateiPhoneDeviceCertificate(void); - -/*! - @function SecPolicyCreateFactoryDeviceCertificate - @abstract Returns a policy object for verifying Factory Device certificate - chains. - @discussion This policy is like the Basic X.509 policy with the additional - requirements that the chain must be anchored to the factory device certificate - issuer. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -SecPolicyRef SecPolicyCreateFactoryDeviceCertificate(void); - -/*! - @function SecPolicyCreateiAP - @abstract Returns a policy object for verifying iAP certificate chains. - @discussion This policy is like the Basic X.509 policy with these - additional requirements: - * The leaf's NotValidBefore should be greater than 5/31/06 midnight GMT. - * The Common Name of the leaf begins with the characters "IPA_". - * No validity checking is performed for any of the certificates. - The intended use of this policy is that the caller pass in the - intermediates for iAP1 and iAP2 to SecTrustSetAnchorCertificates(). - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -SecPolicyRef SecPolicyCreateiAP(void); - -/*! - @function SecPolicyCreateiTunesStoreURLBag - @abstract Returns a policy object for verifying iTunes Store URL bag - certificates. - @discussion This policy is like the Basic X.509 policy with these - additional requirements: - * The leaf's Organization is Apple Inc. - * The Common Name of the leaf is "iTunes Store URL Bag". - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -SecPolicyRef SecPolicyCreateiTunesStoreURLBag(void); - -/*! - @function SecPolicyCreateEAP - @abstract Returns a policy object for verifying for 802.1x/EAP certificates. - @param server Passing true for this parameter create a policy for EAP - server certificates. - @param trustedServerNames Optional; if present, the hostname in the leaf - certificate must be in the trustedServerNames list. Note that contrary - to all other policies the trustedServerNames list entries can have wildcards - whilst the certificate cannot. This matches the existing deployments. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -SecPolicyRef SecPolicyCreateEAP(Boolean server, CFArrayRef trustedServerNames); - -/*! - @function SecPolicyCreateIPSec - @abstract Returns a policy object for evaluating IPSec certificate chains. - @param server Passing true for this parameter create a policy for IPSec - server certificates. - @param hostname Optional; if present, the policy will require the specified - hostname or ip address to match the hostname in the leaf certificate. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -SecPolicyRef SecPolicyCreateIPSec(Boolean server, CFStringRef hostname); - -/*! - @function SecPolicyCreateiPhoneApplicationSigning - @abstract Returns a policy object for evaluating signed application - signatures. This is for apps signed directly by the app store. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -SecPolicyRef SecPolicyCreateiPhoneApplicationSigning(void); - -/*! - @function SecPolicyCreateiPhoneProfileApplicationSigning - @abstract Returns a policy object for evaluating signed application - signatures. This is meant for certificates inside a UPP or regular - profile. Currently it only checks for experation of the leaf and - revocation status. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -SecPolicyRef SecPolicyCreateiPhoneProfileApplicationSigning(void); - -/*! - @function SecPolicyCreateiPhoneProvisioningProfileSigning - @abstract Returns a policy object for evaluating provisioning profile signatures. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -SecPolicyRef SecPolicyCreateiPhoneProvisioningProfileSigning(void); - -/*! - @function SecPolicyCreateOCSPSigner - @abstract Returns a policy object for evaluating ocsp response signers. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -SecPolicyRef SecPolicyCreateOCSPSigner(void); - - -enum { - kSecSignSMIMEUsage = (1 << 0), - kSecKeyEncryptSMIMEUsage = (1 << 1), - kSecDataEncryptSMIMEUsage = (1 << 2), - kSecKeyExchangeDecryptSMIMEUsage = (1 << 3), - kSecKeyExchangeEncryptSMIMEUsage = (1 << 4), - kSecKeyExchangeBothSMIMEUsage = (1 << 5), - kSecAnyEncryptSMIME = kSecKeyEncryptSMIMEUsage | kSecDataEncryptSMIMEUsage | - kSecKeyExchangeDecryptSMIMEUsage | kSecKeyExchangeEncryptSMIMEUsage -}; - -/*! - @function SecPolicyCreateSMIME - @abstract Returns a policy object for evaluating S/MIME certificate chains. - @param smimeUsage Pass the bitwise or of one or more kSecXXXSMIMEUsage - flags, to indicated the intended usage of this certificate. A certificate which allows - @param email Optional; if present, the policy will require the specified - email to match the email in the leaf certificate. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -SecPolicyRef SecPolicyCreateSMIME(CFIndex smimeUsage, CFStringRef email); - -/*! - @function SecPolicyCreateCodeSigning - @abstract Returns a policy object for evaluating code signing certificate chains. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ -SecPolicyRef SecPolicyCreateCodeSigning(void); - -/*! - @function SecPolicyCreateLockdownPairing - @abstract basic x509 policy for checking lockdown pairing certificate chains. - It explicitly allows for empty subjects -*/ -SecPolicyRef SecPolicyCreateLockdownPairing(void); - -/*! - @function SecPolicyCreateURLBag - @abstract check for private CA, eku codesigning and certificate policy that - pertains to signing of URL bags. - */ -SecPolicyRef SecPolicyCreateURLBag(void); - -/*! - @function SecPolicyCreateOTATasking - @abstract check for 3 long chain through Apple Certification Policy with common name - "OTA Task Signing". - */ -SecPolicyRef SecPolicyCreateOTATasking(void); - -/*! - @function SecPolicyCreateMobileAsset - @abstract check for 3 long chain through Apple Certification Policy with common name - "Asset Manifest Signing". - */ -SecPolicyRef SecPolicyCreateMobileAsset(void); - -/*! - @function SecPolicyCreateAppleIDAuthorityPolicy - @abstract check for an Apple ID identity per marker in the leaf and marker in the intermediate, rooted in the Apple CA. - */ -SecPolicyRef SecPolicyCreateAppleIDAuthorityPolicy(void); - -/*! - @function SecPolicyCreatePassbookCardSigner - @abstract check rooted in the Apple CA, eku shoebox, marker shoebox and name matching - @param cardIssuer Required; must match name in marker extension. - @param teamIdentifier Optional; if present, the policy will require the specified - team ID to match the organizationalUnit field in the leaf certificate's subject. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. - */ -SecPolicyRef SecPolicyCreatePassbookCardSigner(CFStringRef cardIssuer, - CFStringRef teamIdentifier); - -/*! - @function SecPolicyCreateShoeboxCardSigner - @abstract Deprecated; use SecPolicyCreatePassbookCardSigner instead - */ -SecPolicyRef SecPolicyCreateShoeboxCardSigner(CFStringRef cardIssuer); - -/*! - @function SecPolicyCreateMobileStoreSigner - @abstract Check for key usage of digital signature, - check for 3 long chain through Apple System Integration 2 Certification Authority - with a certificate policy OID of 1.2.840.113635.100.5.12 that roots to the - Apple root - */ -SecPolicyRef SecPolicyCreateMobileStoreSigner(void); - -/*! - @function SecPolicyCreateTestMobileStoreSigner - @abstract Check for key usage of digital signature, - check for 3 long chain through Apple System Integration 2 Certification Authority - with a certificate policy OID of 1.2.840.113635.100.5.12.1 that roots to the - Apple root - */ -SecPolicyRef SecPolicyCreateTestMobileStoreSigner(void); - -/*! - @function SecPolicyCreateEscrowServiceSigner - @abstract Check for key usage of digital signature, has a leaf marker OID of - 1.2.840.113635.100.6.23.1 and roots to the Test Escrow Root - */ -SecPolicyRef SecPolicyCreateEscrowServiceSigner(void); - -/*! - @function SecPolicyCopyEscrowRootCertificate - @abstract Return back the Root certificate for the Escrow service -*/ -SecCertificateRef SecPolicyCopyEscrowRootCertificate(void); - -/*! - @function SecPolicyCreateConfigurationProfileSigner - @abstract Check for key usage of digital signature, has a EKU OID of - 1.2.840.113635.100.4.16 and - roots to Apple Application Integration 2 Certification Authority -*/ -SecPolicyRef SecPolicyCreateConfigurationProfileSigner(void); - -/*! - @function SecPolicyCreateQAConfigurationProfileSigner - @abstract Check for key usage of digital signature, has a EKU OID of - 1.2.840.113635.100.4.17 and - roots to Apple Application Integration 2 Certification Authority -*/ -SecPolicyRef SecPolicyCreateQAConfigurationProfileSigner(void); - -#if TARGET_OS_IPHONE -/*! - @function SecPolicyCreateOTAPKISigner - @abstract Check for key usage of digital signature, and - roots to Apple PKI Settings Root Certification Authority -*/ -SecPolicyRef SecPolicyCreateOTAPKISigner(void); - -/*! - @function SecPolicyCreateTestOTAPKISigner - @abstract Check for key usage of digital signature, and - roots to Apple PKI Settings Root - TESTING -*/ -SecPolicyRef SecPolicyCreateTestOTAPKISigner(void); - -/*! - @function SecPolicyCreateAppleIDValidationRecordSigningPolicy - @abstract Check for leaf certificate contains the - appleIDValidationRecordSigning (1 2 840 113635 100 6 25), and - intermediate certificate contains - appleCertificateExtensionApplicationIntegrationIntermediate - (1 2 840 113635 100 6 2 3) and - appleCertificateExtensionSystemIntegration2Intermediate - (1 2 840 113635 100 6 2 10) and roots to the Apple root -*/ -SecPolicyRef SecPolicyCreateAppleIDValidationRecordSigningPolicy(void); - -#endif - -__END_DECLS - -#endif /* !_SECURITY_SECPOLICYPRIV_H_ */ diff --git a/sec/Security/SecRandom.h b/sec/Security/SecRandom.h deleted file mode 100644 index 9afe53a1..00000000 --- a/sec/Security/SecRandom.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2007-2009 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 SecRandom - The functions provided in SecRandom.h implement high-level accessors - to cryptographically secure random numbers. -*/ - -#ifndef _SECURITY_SECRANDOM_H_ -#define _SECURITY_SECRANDOM_H_ - -#include -#include -#include - -__BEGIN_DECLS - -/*! - @typedef SecRandomRef - @abstract Reference to a (psuedo) random number generator. -*/ -typedef const struct __SecRandom * SecRandomRef; - -/* This is a synonym for NULL, if you'd rather use a named constant. This - refers to a cryptographically secure random number generator. */ -extern const SecRandomRef kSecRandomDefault - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - -/*! - @function SecRandomCopyBytes - @abstract Return count random bytes in *bytes, allocated by the caller. - @result Return 0 on success or -1 if something went wrong, check errno - to find out the real error. -*/ -int SecRandomCopyBytes(SecRandomRef rnd, size_t count, uint8_t *bytes) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - -__END_DECLS - -#endif /* !_SECURITY_SECRANDOM_H_ */ diff --git a/sec/Security/SecTrust.h b/sec/Security/SecTrust.h deleted file mode 100644 index 2a114907..00000000 --- a/sec/Security/SecTrust.h +++ /dev/null @@ -1,681 +0,0 @@ -/* - * Copyright (c) 2002-2010,2012-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@ - */ - -/*! - @header SecTrust - The functions and data types in SecTrust implement trust computation - and allow the caller to apply trust decisions to the evaluation. - */ - -#ifndef _SECURITY_SECTRUST_H_ -#define _SECURITY_SECTRUST_H_ - -#include -#include -#include - -__BEGIN_DECLS - -/*! - @typedef SecTrustResultType - @abstract Specifies the trust result type. - @discussion SecTrustResultType results have two dimensions. They specify - both whether evaluation suceeded and whether this is because of a user - decision. The commonly expected result is kSecTrustResultUnspecified, - which indicates a positive result that wasn't decided by the user. The - common failure is kSecTrustResultRecoverableTrustFailure, which means a - negative result. kSecTrustResultProceed and kSecTrustResultDeny are the - positive and negative result respectively when decided by the user. User - decisions are persisted through the use of SecTrustCopyExceptions() and - SecTrustSetExceptions(). Finally, kSecTrustResultFatalTrustFailure is a - negative result that must not be circumvented. - @constant kSecTrustResultInvalid Indicates an invalid setting or result. - This result usually means that SecTrustEvaluate has not yet been called. - @constant kSecTrustResultProceed Indicates you may proceed. This value - may be returned by the SecTrustEvaluate function or stored as part of - the user trust settings. - @constant kSecTrustResultConfirm Indicates confirmation with the user - is required before proceeding. Important: this value is no longer returned - or supported by SecTrustEvaluate or the SecTrustSettings API starting in - OS X 10.5; its use is deprecated in OS X 10.9 and later, as well as in iOS. - @constant kSecTrustResultDeny Indicates a user-configured deny; do not - proceed. This value may be returned by the SecTrustEvaluate function - or stored as part of the user trust settings. - @constant kSecTrustResultUnspecified Indicates the evaluation succeeded - and the certificate is implicitly trusted, but user intent was not - explicitly specified. This value may be returned by the SecTrustEvaluate - function or stored as part of the user trust settings. - @constant kSecTrustResultRecoverableTrustFailure Indicates a trust policy - failure which can be overridden by the user. This value may be returned - by the SecTrustEvaluate function but not stored as part of the user - trust settings. - @constant kSecTrustResultFatalTrustFailure Indicates a trust failure - which cannot be overridden by the user. This value may be returned by the - SecTrustEvaluate function but not stored as part of the user trust - settings. - @constant kSecTrustResultOtherError Indicates a failure other than that - of trust evaluation. This value may be returned by the SecTrustEvaluate - function but not stored as part of the user trust settings. - */ -typedef uint32_t SecTrustResultType; -enum { - kSecTrustResultInvalid = 0, - kSecTrustResultProceed = 1, - kSecTrustResultConfirm SEC_DEPRECATED_ATTRIBUTE = 2, - kSecTrustResultDeny = 3, - kSecTrustResultUnspecified = 4, - kSecTrustResultRecoverableTrustFailure = 5, - kSecTrustResultFatalTrustFailure = 6, - kSecTrustResultOtherError = 7 -}; - -/*! - @typedef SecTrustRef - @abstract CFType used for performing X.509 certificate trust evaluations. - */ -typedef struct __SecTrust *SecTrustRef; - -/*! - @enum Trust Property Constants - @discussion Predefined key constants used to obtain values in a - per-certificate dictionary of trust evaluation results, - as retrieved from a call to SecTrustCopyProperties. - @constant kSecPropertyTypeTitle Specifies a key whose value is a - CFStringRef containing the title (display name) of this certificate. - @constant kSecPropertyTypeError Specifies a key whose value is a - CFStringRef containing the reason for a trust evaluation failure. - */ -extern CFTypeRef kSecPropertyTypeTitle - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -extern CFTypeRef kSecPropertyTypeError - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); - -/*! - @enum Trust Result Constants - @discussion Predefined key constants used to obtain values in a - dictionary of trust evaluation results for a certificate chain, - as retrieved from a call to SecTrustCopyResult. - @constant kSecTrustEvaluationDate - This key will be present if a trust evaluation has been performed - and results are available. Its value is a CFDateRef representing - when the evaluation for this trust object took place. - @constant kSecTrustExtendedValidation - This key will be present and have a value of kCFBooleanTrue - if this chain was validated for EV. - @constant kSecTrustOrganizationName - Organization name field of subject of leaf certificate. This - field is meant to be displayed to the user as the validated - name of the company or entity that owns the certificate if the - kSecTrustExtendedValidation key is present. - @constant kSecTrustResultValue - This key will be present if a trust evaluation has been performed. - Its value is a CFNumberRef representing the SecTrustResultType result - for the evaluation. - @constant kSecTrustRevocationChecked - This key will be present iff this chain had its revocation checked. - The value will be a kCFBooleanTrue if revocation checking was - successful and none of the certificates in the chain were revoked. - The value will be kCFBooleanFalse if no current revocation status - could be obtained for one or more certificates in the chain due - to connection problems or timeouts. This is a hint to a client - to retry revocation checking at a later time. - @constant kSecTrustRevocationValidUntilDate - This key will be present iff kSecTrustRevocationChecked has a - value of kCFBooleanTrue. The value will be a CFDateRef representing - the earliest date at which the revocation info for one of the - certificates in this chain might change. - */ -extern CFTypeRef kSecTrustEvaluationDate - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecTrustExtendedValidation - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecTrustOrganizationName - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecTrustResultValue - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecTrustRevocationChecked - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -extern CFTypeRef kSecTrustRevocationValidUntilDate - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - -#ifdef __BLOCKS__ -/*! - @typedef SecTrustCallback - @abstract Delivers the result from an asynchronous trust evaluation. - @param trustRef A reference to the trust object which has been evaluated. - @param trustResult The trust result of the evaluation. Additional status - information can be obtained by calling SecTrustCopyProperties(). - */ -typedef void (^SecTrustCallback)(SecTrustRef trustRef, SecTrustResultType trustResult); -#endif /* __BLOCKS__ */ - - -/*! - @function SecTrustGetTypeID - @abstract Returns the type identifier of SecTrust instances. - @result The CFTypeID of SecTrust instances. - */ -CFTypeID SecTrustGetTypeID(void) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -/*! - @function SecTrustCreateWithCertificates - @abstract Creates a trust object based on the given certificates and - policies. - @param certificates The group of certificates to verify. This can either - be a CFArrayRef of SecCertificateRef objects or a single SecCertificateRef - @param policies An array of one or more policies. You may pass a - SecPolicyRef to represent a single policy. - @param trust On return, a pointer to the trust management reference. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion If multiple policies are passed in, all policies must verify - for the chain to be considered valid. - */ -OSStatus SecTrustCreateWithCertificates(CFTypeRef certificates, - CFTypeRef policies, SecTrustRef *trust) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -/*! - @function SecTrustSetPolicies - @abstract Set the policies for which trust should be verified. - @param trust A trust reference. - @param policies An array of one or more policies. You may pass a - SecPolicyRef to represent a single policy. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function will invalidate the existing trust result, - requiring a fresh evaluation for the newly-set policies. - */ -OSStatus SecTrustSetPolicies(SecTrustRef trust, CFTypeRef policies) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_6_0); - -/*! - @function SecTrustCopyPolicies - @abstract Returns an array of policies used for this evaluation. - @param trust A reference to a trust object. - @param policies On return, an array of policies used by this trust. - Call the CFRelease function to release this reference. - @result A result code. See "Security Error Codes" (SecBase.h). - */ -OSStatus SecTrustCopyPolicies(SecTrustRef trust, CFArrayRef *policies) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_7_0); - -/*! - @function SecTrustSetNetworkFetchAllowed - @abstract Specifies whether a trust evaluation is permitted to fetch missing - intermediate certificates from the network. - @param trust A trust reference. - @param allowFetch If true, and a certificate's issuer is not present in the - trust reference but its network location is known, the evaluation is permitted - to attempt to download it automatically. Pass false to disable network fetch - for this trust evaluation. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion By default, network fetch of missing certificates is enabled if - the trust evaluation includes the SSL policy, otherwise it is disabled. - */ -OSStatus SecTrustSetNetworkFetchAllowed(SecTrustRef trust, - Boolean allowFetch) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - -/*! - @function SecTrustGetNetworkFetchAllowed - @abstract Returns whether a trust evaluation is permitted to fetch missing - intermediate certificates from the network. - @param trust A trust reference. - @param allowFetch On return, the boolean pointed to by this parameter is - set to true if the evaluation is permitted to download missing certificates. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion By default, network fetch of missing certificates is enabled if - the trust evaluation includes the SSL policy, otherwise it is disabled. - */ -OSStatus SecTrustGetNetworkFetchAllowed(SecTrustRef trust, - Boolean *allowFetch) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - -/*! - @function SecTrustSetAnchorCertificates - @abstract Sets the anchor certificates for a given trust. - @param trust A reference to a trust object. - @param anchorCertificates An array of anchor certificates. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Calling this function without also calling - SecTrustSetAnchorCertificatesOnly() will disable trusting any - anchors other than the ones in anchorCertificates. - */ -OSStatus SecTrustSetAnchorCertificates(SecTrustRef trust, - CFArrayRef anchorCertificates) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -/*! - @function SecTrustSetAnchorCertificatesOnly - @abstract Reenables trusting anchor certificates in addition to those - passed in via the SecTrustSetAnchorCertificates API. - @param trust A reference to a trust object. - @param anchorCertificatesOnly If true, disables trusting any anchors other - than the ones passed in via SecTrustSetAnchorCertificates(). If false, - the built in anchor certificates are also trusted. - @result A result code. See "Security Error Codes" (SecBase.h). - */ -OSStatus SecTrustSetAnchorCertificatesOnly(SecTrustRef trust, - Boolean anchorCertificatesOnly) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @function SecTrustCopyCustomAnchorCertificates - @abstract Returns an array of custom anchor certificates used by a given - trust, as set by a prior call to SecTrustSetAnchorCertificates, or NULL if - no custom anchors have been specified. - @param trust A reference to a trust object. - @param anchors On return, an array of custom anchor certificates (roots) - used by this trust, or NULL if no custom anchors have been specified. Call - the CFRelease function to release this reference. - @result A result code. See "Security Error Codes" (SecBase.h). - */ -OSStatus SecTrustCopyCustomAnchorCertificates(SecTrustRef trust, - CFArrayRef *anchors) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_7_0); - -/*! - @function SecTrustSetVerifyDate - @abstract Set the date for which the trust should be verified. - @param trust A reference to a trust object. - @param verifyDate The date for which to verify trust. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function lets you evaluate certificate validity for a - given date (for example, to determine if a signature was valid on the date - it was signed, even if the certificate has since expired.) If this function - is not called, the time at which SecTrustEvaluate() is called is used - implicitly as the verification time. - */ -OSStatus SecTrustSetVerifyDate(SecTrustRef trust, CFDateRef verifyDate) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -/*! - @function SecTrustGetVerifyTime - @abstract Returns the verify time. - @param trust A reference to the trust object being verified. - @result A CFAbsoluteTime value representing the time at which certificates - should be checked for validity. - @discussion This function retrieves the verification time for the given - trust reference, as set by a prior call to SecTrustSetVerifyDate(). If the - verification time has not been set, this function returns a value of 0, - indicating that the current date/time is implicitly used for verification. - */ -CFAbsoluteTime SecTrustGetVerifyTime(SecTrustRef trust) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); - -/*! - @function SecTrustEvaluate - @abstract Evaluates a trust reference synchronously. - @param trust A reference to the trust object to evaluate. - @param result A pointer to a result type. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function will completely evaluate trust before returning, - possibly including network access to fetch intermediate certificates or to - perform revocation checking. Since this function can block during those - operations, you should call it from within a function that is placed on a - dispatch queue, or in a separate thread from your application's main - run loop. Alternatively, you can use the SecTrustEvaluateAsync function. - */ -OSStatus SecTrustEvaluate(SecTrustRef trust, SecTrustResultType *result) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); - -#ifdef __BLOCKS__ -/*! - @function SecTrustEvaluateAsync - @abstract Evaluates a trust reference asynchronously. - @param trust A reference to the trust object to evaluate. - @param queue A dispatch queue on which the result callback should be - executed. Pass NULL to use the current dispatch queue. - @param result A SecTrustCallback block which will be executed when the - trust evaluation is complete. - @result A result code. See "Security Error Codes" (SecBase.h). - */ -OSStatus SecTrustEvaluateAsync(SecTrustRef trust, - dispatch_queue_t queue, SecTrustCallback result) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); -#endif - -/*! - @function SecTrustGetTrustResult - @param trust A reference to a trust object. - @param result A pointer to the result from the most recent call to - SecTrustEvaluate for this trust reference. If SecTrustEvaluate has not been - called or trust parameters have changed, the result is kSecTrustResultInvalid. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function replaces SecTrustGetResult for the purpose of - obtaining the current evaluation result of a given trust reference. - */ -OSStatus SecTrustGetTrustResult(SecTrustRef trust, - SecTrustResultType *result) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); - -/*! - @function SecTrustCopyPublicKey - @abstract Return the public key for a leaf certificate after it has - been evaluated. - @param trust A reference to the trust object which has been evaluated. - @result The certificate's public key, or NULL if it the public key could - not be extracted (this can happen with DSA certificate chains if the - parameters in the chain cannot be found). The caller is responsible - for calling CFRelease on the returned key when it is no longer needed. - */ -SecKeyRef SecTrustCopyPublicKey(SecTrustRef trust) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - -/*! - @function SecTrustGetCertificateCount - @abstract Returns the number of certificates in an evaluated certificate - chain. - @param trust A reference to a trust object. - @result The number of certificates in the trust chain, including the anchor. - @discussion Important: if the trust reference has not yet been evaluated, - this function will evaluate it first before returning. If speed is critical, - you may want to call SecTrustGetTrustResult first to make sure that a - result other than kSecTrustResultInvalid is present for the trust object. - */ -CFIndex SecTrustGetCertificateCount(SecTrustRef trust) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - -/*! - @function SecTrustGetCertificateAtIndex - @abstract Returns a certificate from the trust chain. - @param trust Reference to a trust object. - @param ix The index of the requested certificate. Indices run from 0 - (leaf) to the anchor (or last certificate found if no anchor was found). - The leaf cert (index 0) is always present regardless of whether the trust - reference has been evaluated or not. - @result A SecCertificateRef for the requested certificate. - */ -SecCertificateRef SecTrustGetCertificateAtIndex(SecTrustRef trust, CFIndex ix) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - -/*! - @function SecTrustCopyExceptions - @abstract Returns an opaque cookie which will allow future evaluations - of the current certificate to succeed. - @param trust A reference to an evaluated trust object. - @result An opaque cookie which when passed to SecTrustSetExceptions() will - cause a call to SecTrustEvaluate() return kSecTrustResultProceed. This - will happen upon subsequent evaluation of the current certificate unless - some new error starts happening that wasn't being reported when the cookie - was returned from this function (for example, if the certificate expires - then evaluation will start failing again until a new cookie is obtained.) - @discussion Normally this API should only be called once the errors have - been presented to the user and the user decided to trust the current - certificate chain regardless of the errors being presented, for the - current application/server/protocol combination. - */ -CFDataRef SecTrustCopyExceptions(SecTrustRef trust) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); - -/*! - @function SecTrustSetExceptions - @abstract Set a trust cookie to be used for evaluating this certificate chain. - @param trust A reference to a trust object. - @param exceptions An exceptions cookie as returned by a call to - SecTrustCopyExceptions() in the past. - @result Upon calling SecTrustEvaluate(), any failures that where present at the - time the exceptions object was created are ignored, and instead of returning - kSecTrustResultRecoverableTrustFailure, kSecTrustResultProceed will be returned - (if the certificate for which exceptions was created matches the current leaf - certificate). - @result Returns true if the exceptions cookies was valid and matches the current - leaf certificate, false otherwise. This function will invalidate the existing - trust result, requiring a subsequent evaluation for the newly-set exceptions. - Note that this function returning true doesn't mean the caller can skip calling - SecTrustEvaluate, as there may be new errors since the exceptions cookie was - created (for example, a certificate may have subsequently expired.) - @discussion Clients of this interface will need to establish the context of this - exception to later decide when this exception cookie is to be used. - Examples of this context would be the server we are connecting to, the ssid - of the wireless network for which this cert is needed, the account for which - this cert should be considered valid, and so on. - */ -bool SecTrustSetExceptions(SecTrustRef trust, CFDataRef exceptions) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); - -/*! - @function SecTrustCopyProperties - @abstract Return a property array for this trust evaluation. - @param trust A reference to a trust object. If the trust has not been - evaluated, the returned property array will be empty. - @result A property array. It is the caller's responsibility to CFRelease - the returned array when it is no longer needed. - @discussion This function returns an ordered array of CFDictionaryRef - instances for each certificate in the chain. Indices run from 0 (leaf) to - the anchor (or last certificate found if no anchor was found.) See the - "Trust Property Constants" section for a list of currently defined keys. - */ -CFArrayRef SecTrustCopyProperties(SecTrustRef trust) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); - -/*! - @function SecTrustCopyResult - @abstract Returns a dictionary containing information about the - evaluated certificate chain for use by clients. - @param trust A reference to a trust object. - @result A dictionary with various fields that can be displayed to the user, - or NULL if no additional info is available or the trust has not yet been - validated. The caller is responsible for calling CFRelease on the value - returned when it is no longer needed. - @discussion Returns a dictionary for the overall trust evaluation. See the - "Trust Result Constants" section for a list of currently defined keys. - */ -CFDictionaryRef SecTrustCopyResult(SecTrustRef trust) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - -/*! - @function SecTrustSetOCSPResponse - @abstract Attach OCSPResponse data to a trust object. - @param trust A reference to a trust object. - @param responseData This may be either a CFData object containing a single - DER-encoded OCSPResponse (per RFC 2560), or a CFArray of these. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion Allows the caller to provide OCSPResponse data (which may be - obtained during a TLS/SSL handshake, per RFC 3546) as input to a trust - evaluation. If this data is available, it can obviate the need to contact - an OCSP server for current revocation information. - */ -OSStatus SecTrustSetOCSPResponse(SecTrustRef trust, CFTypeRef responseData) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - - -/* - * Legacy functions (OS X only) - */ -#if TARGET_OS_MAC && !TARGET_OS_IPHONE -#include -#include - -/*! - @typedef SecTrustUserSetting - @abstract Specifies a user-specified trust setting value. - @discussion Deprecated in OS X 10.9. User trust settings are managed by - functions in SecTrustSettings.h (starting with OS X 10.5), and by the - SecTrustCopyExceptions and SecTrustSetExceptions functions (starting with - iOS 4 and OS X 10.9). The latter two functions are recommended for both OS X - and iOS, as they avoid the need to explicitly specify these values. - */ -typedef SecTrustResultType SecTrustUserSetting - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); - -/*! - @typedef SecTrustOptionFlags - @abstract Options for customizing trust evaluation. - @constant kSecTrustOptionAllowExpired Allow expired certificates. - @constant kSecTrustOptionLeafIsCA Allow CA as leaf certificate. - @constant kSecTrustOptionFetchIssuerFromNet Allow network fetch of CA cert. - @constant kSecTrustOptionAllowExpiredRoot Allow expired roots. - @constant kSecTrustOptionRequireRevPerCert Require positive revocation - check per certificate. - @constant kSecTrustOptionUseTrustSettings Use TrustSettings instead of - anchors. - @constant kSecTrustOptionImplicitAnchors Properly self-signed certs are - treated as anchors implicitly. - */ -typedef uint32_t SecTrustOptionFlags; -enum { - kSecTrustOptionAllowExpired = 0x00000001, - kSecTrustOptionLeafIsCA = 0x00000002, - kSecTrustOptionFetchIssuerFromNet = 0x00000004, - kSecTrustOptionAllowExpiredRoot = 0x00000008, - kSecTrustOptionRequireRevPerCert = 0x00000010, - kSecTrustOptionUseTrustSettings = 0x00000020, - kSecTrustOptionImplicitAnchors = 0x00000040 -}; - -/*! - @function SecTrustSetOptions - @abstract Sets optional flags for customizing a trust evaluation. - @param trustRef A trust reference. - @param options Flags to change evaluation behavior for this trust. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is not available on iOS. Use SecTrustSetExceptions - and SecTrustCopyExceptions to modify default trust results, and - SecTrustSetNetworkFetchAllowed to specify whether missing CA certificates - can be fetched from the network. - */ -OSStatus SecTrustSetOptions(SecTrustRef trustRef, SecTrustOptionFlags options) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/*! - @function SecTrustSetParameters - @abstract Sets the action and action data for a trust object. - @param trustRef The reference to the trust to change. - @param action A trust action. - @param actionData A reference to data associated with this action. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in OS X 10.7 and later, where it - was replaced by SecTrustSetOptions, and is not available on iOS. Your code - should use SecTrustSetExceptions and SecTrustCopyExceptions to modify default - trust results, and SecTrustSetNetworkFetchAllowed to specify whether missing - CA certificates can be fetched from the network. - */ -OSStatus SecTrustSetParameters(SecTrustRef trustRef, - CSSM_TP_ACTION action, CFDataRef actionData) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecTrustSetKeychains - @abstract Sets the keychains for a given trust object. - @param trust A reference to a trust object. - @param keychainOrArray A reference to an array of keychains to search, a - single keychain, or NULL to use the default keychain search list. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion By default, the user's keychain search list and the system - anchors keychain are searched for certificates to complete the chain. You - can specify a zero-element array if you do not want any keychains searched. - Note: this function is not applicable to iOS. - */ -OSStatus SecTrustSetKeychains(SecTrustRef trust, CFTypeRef keychainOrArray) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); - -/*! - @function SecTrustGetResult - @abstract Returns detailed information on the outcome of an evaluation. - @param trustRef A reference to a trust object. - @param result A pointer to the result from the call to SecTrustEvaluate. - @param certChain On return, a pointer to the certificate chain used to - validate the input certificate. Call the CFRelease function to release - this pointer. - @param statusChain On return, a pointer to the status of the certificate - chain. Do not attempt to free this pointer; it remains valid until the - trust is destroyed or the next call to SecTrustEvaluate. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in OS X 10.7 and later, - and is not available on iOS. - To get the complete certificate chain, use SecTrustGetCertificateCount and - SecTrustGetCertificateAtIndex. To get detailed status information for each - certificate, use SecTrustCopyProperties. To get the overall trust result - for the evaluation, use SecTrustGetTrustResult. - */ -OSStatus SecTrustGetResult(SecTrustRef trustRef, SecTrustResultType *result, - CFArrayRef *certChain, CSSM_TP_APPLE_EVIDENCE_INFO **statusChain) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecTrustGetCssmResult - @abstract Gets the CSSM trust result. - @param trust A reference to a trust. - @param result On return, a pointer to the CSSM trust result. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in OS X 10.7 and later, - and is not available on iOS. - To get detailed status information for each certificate, use - SecTrustCopyProperties. To get the overall trust result for the evaluation, - use SecTrustGetTrustResult. - */ -OSStatus SecTrustGetCssmResult(SecTrustRef trust, - CSSM_TP_VERIFY_CONTEXT_RESULT_PTR *result) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecTrustGetCssmResultCode - @abstract Gets the result code from the most recent call to SecTrustEvaluate - for the specified trust. - @param trust A reference to a trust. - @param resultCode On return, the result code produced by the most recent - evaluation of the given trust (cssmerr.h). The value of resultCode is - undefined if SecTrustEvaluate has not been called. - @result A result code. See "Security Error Codes" (SecBase.h). Returns - errSecTrustNotAvailable if SecTrustEvaluate has not been called for the - specified trust. - @discussion This function is deprecated in OS X 10.7 and later, - and is not available on iOS. - To get detailed status information for each certificate, use - SecTrustCopyProperties. To get the overall trust result for the evaluation, - use SecTrustGetTrustResult. - */ -OSStatus SecTrustGetCssmResultCode(SecTrustRef trust, OSStatus *resultCode) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecTrustGetTPHandle - @abstract Gets the CSSM trust handle - @param trust A reference to a trust. - @param handle On return, a CSSM trust handle. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is deprecated in OS X 10.7 and later. - */ -OSStatus SecTrustGetTPHandle(SecTrustRef trust, CSSM_TP_HANDLE *handle) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); - -/*! - @function SecTrustCopyAnchorCertificates - @abstract Returns an array of default anchor (root) certificates used by - the system. - @param anchors On return, an array containing the system's default anchors - (roots). Call the CFRelease function to release this pointer. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function is not available on iOS, as certificate data - for system-trusted roots is currently unavailable on that platform. - */ -OSStatus SecTrustCopyAnchorCertificates(CFArrayRef *anchors) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); - -#endif /* TARGET_OS_MAC && !TARGET_OS_IPHONE */ - - -__END_DECLS - -#endif /* !_SECURITY_SECTRUST_H_ */ diff --git a/sec/Security/SecTrustPriv.h b/sec/Security/SecTrustPriv.h deleted file mode 100644 index dfc74709..00000000 --- a/sec/Security/SecTrustPriv.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2008-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@ - */ - -/*! - @header SecTrustPriv - The functions and data types in SecTrustPriv implement trust computation - and allow the user to apply trust decisions to the trust configuration. -*/ - -#ifndef _SECURITY_SECTRUSTPRIV_H_ -#define _SECURITY_SECTRUSTPRIV_H_ - -#include -#include -#include - -__BEGIN_DECLS - -typedef enum { - useNetworkDefault, // default policy: network fetch enabled only for SSL - useNetworkDisabled, // explicitly disable network use for any policy - useNetworkEnabled // explicitly enable network use for any policy -} SecNetworkPolicy; - -/* Constants used as keys in property lists. See - SecTrustCopySummaryPropertiesAtIndex for more information. */ -extern CFTypeRef kSecPropertyKeyType; -extern CFTypeRef kSecPropertyKeyLabel; -extern CFTypeRef kSecPropertyKeyLocalizedLabel; -extern CFTypeRef kSecPropertyKeyValue; - -extern CFTypeRef kSecPropertyTypeWarning; -extern CFTypeRef kSecPropertyTypeSuccess; -extern CFTypeRef kSecPropertyTypeSection; -extern CFTypeRef kSecPropertyTypeData; -extern CFTypeRef kSecPropertyTypeString; -extern CFTypeRef kSecPropertyTypeURL; -extern CFTypeRef kSecPropertyTypeDate; - -/* Constants used as keys in the dictionary returned by SecTrustCopyInfo. */ -extern CFTypeRef kSecTrustInfoExtendedValidationKey; -extern CFTypeRef kSecTrustInfoCompanyNameKey; -extern CFTypeRef kSecTrustInfoRevocationKey; -extern CFTypeRef kSecTrustInfoRevocationValidUntilKey; - -/*! - @function SecTrustCopySummaryPropertiesAtIndex - @abstract Return a property array for the certificate. - @param trust A reference to the trust object to evaluate. - @param ix The index of the requested certificate. Indices run from 0 - (leaf) to the anchor (or last certificate found if no anchor was found). - @result A property array. It is the caller's responsibility to CFRelease - the returned array when it is no longer needed. This function returns a - short summary description of the certificate in question. The property - at index 0 of the array might also include general information about the - entire chain's validity in the context of this trust evaluation. - - @discussion Returns a property array for this trust certificate. A property - array is an array of CFDictionaryRefs. Each dictionary (we call it a - property for short) has the following keys: - - kSecPropertyKeyType This key's value determines how this property - should be displayed. Its associated value is one of the - following: - kSecPropertyTypeWarning - The kSecPropertyKeyLocalizedLabel and kSecPropertyKeyLabel keys are not - set. The kSecPropertyKeyValue is a CFStringRef which should - be displayed in yellow with a warning triangle. - kSecPropertyTypeError - The kSecPropertyKeyLocalizedLabel and kSecPropertyKeyLabel keys are not - set. The kSecPropertyKeyValue is a CFStringRef which should - be displayed in red with an error X. - kSecPropertyTypeSuccess - The kSecPropertyKeyLocalizedLabel and kSecPropertyKeyLabel keys are not - set. The kSecPropertyKeyValue is a CFStringRef which should - be displayed in green with a checkmark in front of it. - kSecPropertyTypeTitle - The kSecPropertyKeyLocalizedLabel and kSecPropertyKeyLabel keys are not - set. The kSecPropertyKeyValue is a CFStringRef which should - be displayed in a larger bold font. - kSecPropertyTypeSection - The optional kSecPropertyKeyLocalizedLabel is a CFStringRef with the name - of the next section to display. The value of the - kSecPropertyKeyValue key is a CFArrayRef which is a property - array as defined here. - kSecPropertyTypeData - The optional kSecPropertyKeyLocalizedLabel is a CFStringRef containing - the localized label for the value for the kSecPropertyKeyValue. - The type of this value is a CFDataRef. Its contents should be - displayed as: "bytes length_of_data : hexdump_of_data". Ideally - the UI will only show one line of hex dump data and have a - disclosure arrow to see the remainder. - kSecPropertyTypeString - The optional kSecPropertyKeyLocalizedLabel is a CFStringRef containing - the localized label for the value for the kSecPropertyKeyValue. - The type of this value is a CFStringRef. It's contents should be - displayed in the normal font. - kSecPropertyTypeURL - The optional kSecPropertyKeyLocalizedLabel is a CFStringRef containing - the localized label for the value for the kSecPropertyKeyValue. - The type of this value is a CFURLRef. It's contents should be - displayed as a hyperlink. - kSecPropertyTypeDate - The optional kSecPropertyKeyLocalizedLabel is a CFStringRef containing - the localized label for the value for the kSecPropertyKeyValue. - The type of this value is a CFDateRef. It's contents should be - displayed in human readable form (probably in the current - timezone). - kSecPropertyKeyLocalizedLabel - Human readable localized label for a given property. - kSecPropertyKeyValue - See description of kSecPropertyKeyType to determine what the value - for this key is. - kSecPropertyKeyLabel - Non localized key (label) for this value. This is only - present for properties with fixed label names. - @param certificate A reference to the certificate to evaluate. - @result A property array. It is the caller's responsability to CFRelease - the returned array when it is no longer needed. -*/ -CFArrayRef SecTrustCopySummaryPropertiesAtIndex(SecTrustRef trust, CFIndex ix); - -/*! - @function SecTrustCopyDetailedPropertiesAtIndex - @abstract Return a property array for the certificate. - @param trust A reference to the trust object to evaluate. - @param ix The index of the requested certificate. Indices run from 0 - (leaf) to the anchor (or last certificate found if no anchor was found). - @result A property array. It is the caller's responsibility to CFRelease - the returned array when it is no longer needed. - See SecTrustCopySummaryPropertiesAtIndex on how to intepret this array. - Unlike that function call this function returns a detailed description - of the certificate in question. -*/ -CFArrayRef SecTrustCopyDetailedPropertiesAtIndex(SecTrustRef trust, CFIndex ix); - -/*! - @function SecTrustCopyProperties - @abstract Return a property array for this trust evaluation. - @param trust A reference to the trust object to evaluate. - @result A property array. It is the caller's responsibility to CFRelease - the returned array when it is no longer needed. See - SecTrustCopySummaryPropertiesAtIndex for a detailed description of this array. - Unlike that function, this function returns a short text string suitable for - display in a sheet explaining to the user why this certificate chain is - not trusted for this operation. This function may return NULL if the - certificate chain was trusted. -*/ -CFArrayRef SecTrustCopyProperties(SecTrustRef trust); - -/*! - @function SecTrustCopyInfo - @abstract Return a dictionary with additional information about the - evaluated certificate chain for use by clients. - @param trust A reference to an evaluated trust object. - @discussion Returns a dictionary for this trust evaluation. This - dictionary may have the following keys: - - kSecTrustInfoExtendedValidationKey this key will be present and have - a value of kCFBooleanTrue if this chain was validated for EV. - kSecTrustInfoCompanyNameKey Company name field of subject of leaf - certificate, this field is meant to be displayed to the user - if the kSecTrustInfoExtendedValidationKey is present. - kSecTrustInfoRevocationKey this key will be present iff this chain - had its revocation checked. The value will be a kCFBooleanTrue - if revocation checking was successful and none of the - certificates in the chain were revoked. - The value will be kCFBooleanFalse if no current revocation status - could be obtained for one or more certificates in the chain due - to connection problems or timeouts etc. This is a hint to a - client to retry revocation checking at a later time. - kSecTrustInfoRevocationValidUntilKey this key will be present iff - kSecTrustInfoRevocationKey has a value of kCFBooleanTrue. - The value will be a CFDateRef representing the earliest date at - which the revocation info for one of the certificates in this chain - might change. - - @result A dictionary with various fields that can be displayed to the user, - or NULL if no additional info is available or the trust has not yet been - validated. The caller is responsible for calling CFRelease on the value - returned when it is no longer needed. -*/ -CFDictionaryRef SecTrustCopyInfo(SecTrustRef trust); - -/* For debugging purposes. */ -CFArrayRef SecTrustGetDetails(SecTrustRef trust); - -/* For debugging purposes. */ -CFStringRef SecTrustCopyFailureDescription(SecTrustRef trust); - -/*! - @function SecTrustSetPolicies - @abstract Set the trust policies against which the trust should be verified. - @param trust A reference to a trust object. - @param policies An array of one or more policies. You may pass a - SecPolicyRef to represent a single policy. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function does not invalidate the trust, but should do so in the future. -*/ -OSStatus SecTrustSetPolicies(SecTrustRef trust, CFTypeRef policies) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_6_0); - -OSStatus SecTrustGetOTAPKIAssetVersionNumber(int* versionNumber); - -OSStatus SecTrustOTAPKIGetUpdatedAsset(int* didUpdateAsset); - -__END_DECLS - -#endif /* !_SECURITY_SECTRUSTPRIV_H_ */ diff --git a/sec/Security/SecTrustSettings.h b/sec/Security/SecTrustSettings.h deleted file mode 100644 index d4e68f0b..00000000 --- a/sec/Security/SecTrustSettings.h +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) 2007 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 SecTrustSettings - The functions and data types in SecTrustSettings implement a way to - set and retrive trustability of certificates. -*/ - -#ifndef _SECURITY_SECTRUSTSETTINGS_H_ -#define _SECURITY_SECTRUSTSETTINGS_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Any certificate (cert) which resides in a keychain can have associated with - * it a set of Trust Settings. Trust Settings specify conditions in which a - * given cert can be trusted or explicitly distrusted. A "trusted" cert is - * either a root (self-signed) cert that, when a cert chain verifies back to that - * root, the entire cert chain is trusted; or a non-root cert that does not need - * to verify to a trusted root cert (which is normally the case when verifying a - * cert chain). An "explicitly distrusted" cert is one which will, when encountered - * during the evaluation of a cert chain, cause immediate and unconditional failure - * of the verify operation. - * - * Trust Settings are configurable by the user; they can apply on three levels - * (called domains): - * - * -- Per-user. - * -- Locally administered, system-wide. Administrator privileges are required - * to make changes to this domain. - * -- System. These Trust Settings are immutable and comprise the set of trusted - * root certificates supplied in Mac OS X. - * - * Per-user Trust Settings override locally administered Trust Settings, which - * in turn override the System Trust Settings. - * - * Each cert's Trust Settings are expressed as a CFArray which includes any - * number (including zero) of CFDictionaries, each of which comprises one set of - * Usage Constraints. Each Usage Constraints dictionary contains zero or one of - * each the following components: - * - * key = kSecTrustSettingsPolicy value = SecPolicyRef - * key = kSecTrustSettingsApplication value = SecTrustedApplicationRef - * key = kSecTrustSettingsPolicyString value = CFString, policy-specific - * key = kSecTrustSettingsKeyUsage value = CFNumber, an SInt32 key usage - * - * A given Usage Constraints dictionary applies to a given cert if *all* of the - * usage constraint components specified in the dictionary match the usage of - * the cert being evaluated; when this occurs, the value of the - * kSecTrustSettingsResult entry in the dictionary, shown below, is the effective - * trust setting for the cert. - * - * key = kSecTrustSettingsResult value = CFNumber, an SInt32 SecTrustSettingsResult - * - * The overall Trust Settings of a given cert are the sum of all such Usage - * Constraints CFDictionaries: Trust Settings for a given usage apply if *any* - * of the CFDictionaries in the cert's Trust Settings array satisfies - * the specified usage. Thus, when a cert has multiple Usage Constraints - * dictionaries in its Trust Settings array, the overall Trust Settings - * for the cert are - * - * (Usage Constraint 0 component 0 AND Usage Constraint 0 component 1 ...) - * -- OR -- - * (Usage Constraint 1 component 0 AND Usage Constraint 1 component 1 ...) - * -- OR -- - * ... - * - * Notes on the various Usage Constraints components: - * - * kSecTrustSettingsPolicy Specifies a cert verification policy, e.g., SSL, - * SMIME, etc. - * kSecTrustSettingsApplication Specifies the application performing the cert - * verification. - * kSecTrustSettingsPolicyString Policy-specific. For the SMIME policy, this is - * an email address. - * For the SSL policy, this is a host name. - * kSecTrustSettingsKeyUsage A bitfield indicating key operations (sign, - * encrypt, etc.) for which this Usage Constraint - * apply. Values are defined below as the - * SecTrustSettingsKeyUsage enum. - * kSecTrustSettingsResult The resulting trust value. If not present this has a - * default of kSecTrustSettingsResultTrustRoot, meaning - * "trust this root cert". Other legal values are: - * kSecTrustSettingsResultTrustAsRoot : trust non-root - * cert as if it were a trusted root. - * kSecTrustSettingsResultDeny : explicitly distrust this - * cert. - * kSecTrustSettingsResultUnspecified : neither trust nor - * distrust; can be used to specify an "Allowed error" - * (see below) without assigning trust to a specific - * cert. - * - * Another optional component in a Usage Constraints dictionary is a CSSM_RETURN - * which, if encountered during certificate verification, is ignored for that - * cert. These "allowed error" values are constrained by Usage Constraints as - * described above; a Usage Constraint dictionary with no constraints but with - * an Allowed Error value causes that error to always be allowed when the cert - * is being evaluated. - * - * The "allowed error" entry in a Usage Constraints dictionary is formatted - * as follows: - * - * key = kSecTrustSettingsAllowedError value = CFNumber, an SInt32 CSSM_RETURN - * - * Note that if kSecTrustSettingsResult value of kSecTrustSettingsResultUnspecified - * is *not* present for a Usage Constraints dictionary with no Usage - * Constraints, the default of kSecTrustSettingsResultTrustRoot is assumed. To - * specify a kSecTrustSettingsAllowedError without explicitly trusting (or - * distrusting) the associated cert, specify kSecTrustSettingsResultUnspecified - * for the kSecTrustSettingsResult component. - * - * Note that an empty Trust Settings array means "always trust this cert, - * with a resulting kSecTrustSettingsResult of kSecTrustSettingsResultTrustRoot". - * An empty Trust Settings array is definitely not the same as *no* Trust - * Settings, which means "this cert must be verified to a known trusted cert". - * - * Note the distinction between kSecTrustSettingsResultTrustRoot and - * kSecTrustSettingsResultTrustAsRoot; the former can only be applied to - * root (self-signed) certs; the latter can only be applied to non-root - * certs. This also means that an empty TrustSettings array for a non-root - * cert is invalid, since the default value for kSecTrustSettingsResult is - * kSecTrustSettingsResultTrustRoot, which is invalid for a non-root cert. - * - * Authentication - * -------------- - * - * When making changes to the per-user Trust Settings, the user will be - * prompted with an alert panel asking for authentication via user name a - * password (or other credentials normally used for login). This means - * that it is not possible to modify per-user Trust Settings when not - * running in a GUI environment (i.e. the user is not logged in via - * Loginwindow). - * - * When making changes to the system-wide Trust Settings, the user will be - * prompted with an alert panel asking for an administrator's name and - * password, unless the calling process is running as root in which case - * no futher authentication is needed. - */ - -/* - * The keys in one Usage Constraints dictionary. - */ -#define kSecTrustSettingsPolicy CFSTR("kSecTrustSettingsPolicy") -#define kSecTrustSettingsApplication CFSTR("kSecTrustSettingsApplication") -#define kSecTrustSettingsPolicyString CFSTR("kSecTrustSettingsPolicyString") -#define kSecTrustSettingsKeyUsage CFSTR("kSecTrustSettingsKeyUsage") -#define kSecTrustSettingsAllowedError CFSTR("kSecTrustSettingsAllowedError") -#define kSecTrustSettingsResult CFSTR("kSecTrustSettingsResult") - -/* - * Key usage bits, the value for Usage Constraints key kSecTrustSettingsKeyUsage. - */ -enum { - /* sign/verify data */ - kSecTrustSettingsKeyUseSignature = 0x00000001, - /* bulk encryption */ - kSecTrustSettingsKeyUseEnDecryptData = 0x00000002, - /* key wrap/unwrap */ - kSecTrustSettingsKeyUseEnDecryptKey = 0x00000004, - /* sign/verify cert */ - kSecTrustSettingsKeyUseSignCert = 0x00000008, - /* sign/verify CRL and OCSP */ - kSecTrustSettingsKeyUseSignRevocation = 0x00000010, - /* key exchange, e.g., Diffie-Hellman */ - kSecTrustSettingsKeyUseKeyExchange = 0x00000020, - /* any usage (the default if this value is not specified) */ - kSecTrustSettingsKeyUseAny = 0xffffffff -}; -typedef uint32_t SecTrustSettingsKeyUsage; - -/*! - @enum SecTrustSettingsResult - @abstract Result of a trust settings evaluation. -*/ -enum { - kSecTrustSettingsResultInvalid = 0, /* Never valid in a Trust Settings array or - * in an API call. */ - kSecTrustSettingsResultTrustRoot, /* Root cert is explicitly trusted */ - kSecTrustSettingsResultTrustAsRoot, /* Non-root cert is explicitly trusted */ - kSecTrustSettingsResultDeny, /* Cert is explicitly distrusted */ - kSecTrustSettingsResultUnspecified /* Neither trusted nor distrusted; evaluation - * proceeds as usual */ -}; -typedef uint32_t SecTrustSettingsResult; - -/* - * Specify user, local administrator, or system domain Trust Properties. - * Note that kSecTrustSettingsDomainSystem settings are read-only, even by - * root. - */ -enum { - kSecTrustSettingsDomainUser = 0, - kSecTrustSettingsDomainAdmin, - kSecTrustSettingsDomainSystem -}; -typedef uint32_t SecTrustSettingsDomain; - -/* - * SecCertificateRef value indicating the default Root Certificate Trust Settings - * for a given domain. When evaluating Trust Settings for a root cert in - * a given domain, *and* no matching explicit Trust Settings exists for the - * root cert in questions, *and* default Root Cert Trust Settings exist - * in that domain which matches the evaluation condition, then the - * SecTrustSettingsResult for that default Trust Setting (if not - * kSecTrustSettingsResultUnspecified) will apply. - * - * This can be used e.g. by a system administrator to explicilty distrust all - * of the root certs in the (immutable) system domain for a specific policy. - * - * This const is passed as the 'SecCertificateRef certRef' argument to - * SecTrustSettingsCopyTrustSettings(), SecTrustSettingsSetTrustSettings(), - * and SecTrustSettingsRemoveTrustSettings(), and - * SecTrustSettingsCopyModificationDate(). - */ -#define kSecTrustSettingsDefaultRootCertSetting ((SecCertificateRef)-1) - -#ifdef __cplusplus -} -#endif - -#endif /* _SECURITY_SECTRUSTSETTINGS_H_ */ diff --git a/sec/Security/SecTrustSettingsPriv.h b/sec/Security/SecTrustSettingsPriv.h deleted file mode 100644 index 16ad1bb3..00000000 --- a/sec/Security/SecTrustSettingsPriv.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2007-2008,2010 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@ - */ - -/* - * SecTrustSettingsPriv.h - TrustSettings SPI functions. - */ - -#ifndef _SECURITY_SECTRUSTSETTINGSPRIV_H_ -#define _SECURITY_SECTRUSTSETTINGSPRIV_H_ - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * A TrustSettings Record contains the XML encoding of a CFDictionary. This dictionary - * currently contains two name/value pairs: - * - * key = kTrustRecordVersion, value = SInt32 version number - * key = kTrustRecordTrustList, value = CFDictionary - * - * Each key/value pair of the CFDictionary associated with key kTrustRecordTrustList - * consists of: - * -- key = the ASCII representation (with alpha characters in upper case) of the - * cert's SHA1 digest. - * -- value = a CFDictionary representing one cert. - * - * Key/value pairs in the per-cert dictionary are as follows: - * - * -- key = kTrustRecordIssuer, value = non-normalized issuer as CFData - * -- key = kTrustRecordSerialNumber, value = serial number as CFData - * -- key = kTrustRecordModDate, value = CFDateRef of the last modification - date of the per-cert entry. - * -- key = kTrustRecordTrustSettings, value = array of dictionaries. The - * dictionaries are as described in the API in SecUserTrust.h - * although we store the values differently (see below). - * As written to disk, this key/value is always present although - * the usageConstraints array may be empty. - * - * A usageConstraints dictionary is like so (all elements are optional). These key - * strings are defined in SecUserTrust.h. - * - * key = kSecTrustSettingsPolicy value = policy OID as CFData - * key = kSecTrustSettingsApplication value = application path as CFString - * key = kSecTrustSettingsPolicyString value = CFString, policy-specific - * key = kSecTrustSettingsAllowedError value = CFNumber, an SInt32 CSSM_RETURN - * key = kSecTrustSettingsResult value = CFNumber, an SInt32 SecTrustSettingsResult - * key = kSecTrustSettingsKeyUsage value = CFNumber, an SInt32 key usage - * key = kSecTrustSettingsModifyDate value = CFDate, last modification - */ - -/* - * Keys in the top-level dictionary - */ -#define kTrustRecordVersion CFSTR("trustVersion") -#define kTrustRecordTrustList CFSTR("trustList") - -/* - * Keys in the per-cert dictionary in the TrustedRootList record. - */ -/* value = non-normalized issuer as CFData */ -#define kTrustRecordIssuer CFSTR("issuerName") - -/* value = serial number as CFData */ -#define kTrustRecordSerialNumber CFSTR("serialNumber") - -/* value = CFDateRef representation of modification date */ -#define kTrustRecordModDate CFSTR("modDate") - -/* - * value = array of CFDictionaries as used in public API - * Not present for a cert which has no usage Constraints (i.e. - * "wide open" unrestricted, kSecTrustSettingsResultTrustRoot as - * the default SecTrustSettingsResult). - */ -#define kTrustRecordTrustSettings CFSTR("trustSettings") - -/* - * Version of the top-level dictionary. - */ -enum { - kSecTrustRecordVersionInvalid = 0, /* should never be seen on disk */ - kSecTrustRecordVersionCurrent = 1 -}; - -/* - * Key for the (optional) default entry in a TrustSettings record. This - * appears in place of the cert's hash string, and corresponds to - * kSecTrustSettingsDefaultRootCertSetting at the public API. - * If you change this, make sure it has characters other than those - * appearing in a normal cert hash string (0..9 and A..F). - */ -#define kSecTrustRecordDefaultRootCert CFSTR("kSecTrustRecordDefaultRootCert") - -/* - * The location of the system root keychain and its associated TrustSettings. - * These are immutable; this module never modifies either of them. - */ -#define SYSTEM_ROOT_STORE_PATH "/System/Library/Keychains/SystemRootCertificates.keychain" -#define SYSTEM_TRUST_SETTINGS_PATH "/System/Library/Keychains/SystemTrustSettings.plist" - -/* - * The local admin cert store. - */ -#define ADMIN_CERT_STORE_PATH "/Library/Keychains/System.keychain" - -/* - * Per-user and local admin TrustSettings are stored in this directory. - * Per-user settings are of the form .plist. - */ -#define TRUST_SETTINGS_PATH "/Library/Trust Settings" -#define ADMIN_TRUST_SETTINGS "Admin.plist" - -/* - * Additional values for the SecTrustSettingsDomain enum. - */ -enum { - /* - * This indicates a TrustSettings that exists only in memory; it - * can't be written to disk. - */ - kSecTrustSettingsDomainMemory = 100 -}; - -typedef struct __SecTrustSettings *SecTrustSettingsRef; - -CFTypeID SecTrustSettingsGetTypeID(void); -OSStatus SecTrustSettingsCreateFromExternal(SecTrustSettingsDomain domain, - CFDataRef external, SecTrustSettingsRef *ts); -SecTrustSettingsRef SecTrustSettingsCreate(SecTrustSettingsDomain domain, - bool create, bool trim); -CFDataRef SecTrustSettingsCopyExternal(SecTrustSettingsRef ts); -void SecTrustSettingsSet(SecCertificateRef certRef, - CFTypeRef trustSettingsDictOrArray); - -/* - * Fundamental routine used to ascertain status of one cert. - * - * Returns true in *foundMatchingEntry if a trust setting matching - * specific constraints was found for the cert. Returns true in - * *foundAnyEntry if any entry was found for the cert, even if it - * did not match the specified constraints. The TP uses this to - * optimize for the case where a cert is being evaluated for - * one type of usage, and then later for another type. If - * foundAnyEntry is false, the second evaluation need not occur. - * - * Returns the domain in which a setting was found in *foundDomain. - * - * Allowed errors applying to the specified cert evaluation - * are returned in a mallocd array in *allowedErrors and must - * be freed by caller. - */ -OSStatus SecTrustSettingsEvaluateCertificate( - SecCertificateRef certificate, - SecPolicyRef policy, - SecTrustSettingsKeyUsage keyUsage, /* optional */ - bool isSelfSignedCert, /* for checking default setting */ - /* RETURNED values */ - SecTrustSettingsDomain *foundDomain, - CFArrayRef *allowedErrors, /* RETURNED */ - SecTrustSettingsResult *resultType, /* RETURNED */ - bool *foundMatchingEntry,/* RETURNED */ - bool *foundAnyEntry); /* RETURNED */ - -/* - * Add a cert's TrustSettings to a non-persistent TrustSettings record. - * Primarily intended for use in creating a system TrustSettings record - * (which is itself immutable via this module). - * - * The settingsIn argument is an external representation of a TrustSettings - * record, obtianed from this function or from - * SecTrustSettingsCreateExternalRepresentation(). - * If settingsIn is NULL, a new (empty) TrustSettings will be created. - * - * The certRef and trustSettingsDictOrArray arguments are as in - * SecTrustSettingsSetTrustSettings(). May be NULL, when e.g. creating - * a new and empty TrustSettings record. - * - * The external representation is written to the settingOut argument, - * which must eventually be CFReleased by the caller. - */ -OSStatus SecTrustSettingsSetTrustSettingsExternal( - CFDataRef settingsIn, /* optional */ - SecCertificateRef certRef, /* optional */ - CFTypeRef trustSettingsDictOrArray, /* optional */ - CFDataRef *settingsOut); /* RETURNED */ - -#ifdef __cplusplus -} -#endif - -#endif /* _SECURITY_SECTRUSTSETTINGSPRIV_H_ */ - diff --git a/sec/Security/Security.h b/sec/Security/Security.h deleted file mode 100644 index 25962d92..00000000 --- a/sec/Security/Security.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2007-2008 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - diff --git a/sec/Security/SecuritydXPC.h b/sec/Security/SecuritydXPC.h deleted file mode 100644 index 1d87ddfd..00000000 --- a/sec/Security/SecuritydXPC.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// SecuritydXPC.h -// sec -// -// Created by Mitch Adler on 11/16/12. -// -// - -#include -#include - -#ifndef _UTILITIES_SECURITYDXPC_H_ -#define _UTILITIES_SECURITYDXPC_H_ - -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 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); - -bool SecXPCDictionarySetString(xpc_object_t message, const char *key, CFStringRef string, CFErrorRef *error); - -CFTypeRef SecXPCDictionaryCopyPList(xpc_object_t message, const char *key, CFErrorRef *error); -bool SecXPCDictionaryCopyPListOptional(xpc_object_t message, const char *key, CFTypeRef *pobject, CFErrorRef *error); - -CFArrayRef SecXPCDictionaryCopyArray(xpc_object_t message, const char *key, CFErrorRef *error); -bool SecXPCDictionaryCopyArrayOptional(xpc_object_t message, const char *key, CFArrayRef *parray, CFErrorRef *error); - -CFDataRef SecXPCDictionaryCopyData(xpc_object_t message, const char *key, CFErrorRef *error); -bool SecXPCDictionaryCopyDataOptional(xpc_object_t message, const char *key, CFDataRef *pdata, CFErrorRef *error); - -CFDictionaryRef SecXPCDictionaryCopyDictionary(xpc_object_t message, const char *key, CFErrorRef *error); - -CFStringRef SecXPCDictionaryCopyString(xpc_object_t message, const char *key, CFErrorRef *error); -bool SecXPCDictionaryCopyDictionaryOptional(xpc_object_t message, const char *key, CFDictionaryRef *pdictionary, CFErrorRef *error); - - -#endif diff --git a/sec/Security/Tool/codesign.c b/sec/Security/Tool/codesign.c deleted file mode 100644 index 38e90a5c..00000000 --- a/sec/Security/Tool/codesign.c +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright (c) 2008,2010 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include -#if TARGET_OS_EMBEDDED - -#include "SecurityCommands.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Magic numbers used by Code Signing - */ -enum { - CSMAGIC_REQUIREMENT = 0xfade0c00, /* single Requirement blob */ - CSMAGIC_REQUIREMENTS = 0xfade0c01, /* Requirements vector (internal requirements) */ - CSMAGIC_CODEDIRECTORY = 0xfade0c02, /* CodeDirectory blob */ - CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0, /* embedded form of signature data */ - CSMAGIC_DETACHED_SIGNATURE = 0xfade0cc1, /* multi-arch collection of embedded signatures */ - - CSSLOT_CODEDIRECTORY = 0, /* slot index for CodeDirectory */ -}; - - -/* - * Structure of an embedded-signature SuperBlob - */ -typedef struct __BlobIndex { - uint32_t type; /* type of entry */ - uint32_t offset; /* offset of entry */ -} CS_BlobIndex; - -typedef struct __SuperBlob { - uint32_t magic; /* magic number */ - uint32_t length; /* total length of SuperBlob */ - uint32_t count; /* number of index entries following */ - CS_BlobIndex index[]; /* (count) entries */ - /* followed by Blobs in no particular order as indicated by offsets in index */ -} CS_SuperBlob; - - -/* - * C form of a CodeDirectory. - */ -typedef struct __CodeDirectory { - uint32_t magic; /* magic number (CSMAGIC_CODEDIRECTORY) */ - uint32_t length; /* total length of CodeDirectory blob */ - uint32_t version; /* compatibility version */ - uint32_t flags; /* setup and mode flags */ - uint32_t hashOffset; /* offset of hash slot element at index zero */ - uint32_t identOffset; /* offset of identifier string */ - uint32_t nSpecialSlots; /* number of special hash slots */ - uint32_t nCodeSlots; /* number of ordinary (code) hash slots */ - uint32_t codeLimit; /* limit to main image signature range */ - uint8_t hashSize; /* size of each hash in bytes */ - uint8_t hashType; /* type of hash (cdHashType* constants) */ - uint8_t spare1; /* unused (must be zero) */ - uint8_t pageSize; /* log2(page size in bytes); 0 => infinite */ - uint32_t spare2; /* unused (must be zero) */ - /* followed by dynamic content as located by offset fields above */ -} CS_CodeDirectory; - - - //assert(page < ntohl(cd->nCodeSlots)); - //return base + ntohl(cd->hashOffset) + page * 20; - -#if 0 -static void debug_data(uint8_t *data, size_t length) -{ - uint32_t i, j; - for (i = 0; i < length; i+=16) { - fprintf(stderr, "%p ", (void*)(data+i)); - for (j = 0; (j < 16) && (j+i < length); j++) { - uint8_t byte = *(uint8_t*)(data+i+j); - fprintf(stderr, "%.02x %c|", byte, isprint(byte) ? byte : '?'); - } - fprintf(stderr, "\n"); - } -} - -static void write_data(const char *path, uint8_t *data, size_t length) -{ - int fd = open(path, O_RDWR|O_TRUNC|O_CREAT, 0644); - require(fd>0, out); - write(fd, data, length); - close(fd); -out: - return; -} -#endif - -static void fprint_digest(FILE *file, unsigned char *digest, size_t length) { - size_t ix; - for (ix = 0; ix < length; ++ix) { - fprintf(file, "%02x", digest[ix]); - } -} - -static CFMutableDictionaryRef lc_code_sig(uint8_t *lc_code_signature, size_t lc_code_signature_len) -{ - CFMutableDictionaryRef code_signature = - CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - require(code_signature, out); - - CS_SuperBlob *sb = (CS_SuperBlob*)lc_code_signature; - require(ntohl(sb->magic) == CSMAGIC_EMBEDDED_SIGNATURE, out); - uint32_t count; - for (count = 0; count < ntohl(sb->count); count++) { - //uint32_t type = ntohl(sb->index[count].type); - uint32_t offset = ntohl(sb->index[count].offset); - uint8_t *bytes = lc_code_signature + offset; - //fprintf(stderr, "blob[%d]: (type: 0x%.08x, offset: %p)\n", count, type, (void*)offset); - uint32_t magic = ntohl(*(uint32_t*)bytes); - uint32_t length = ntohl(*(uint32_t*)(bytes+4)); - //fprintf(stderr, " magic: 0x%.08x length: %d\n", magic, length); - switch(magic) { - case 0xfade0c01: //write_data("requirements", bytes, length); - break; - case 0xfade0c02: //write_data("codedir", bytes, length); - { - const CS_CodeDirectory *cd = (const CS_CodeDirectory *)bytes; - CFDataRef codedir = CFDataCreate(kCFAllocatorDefault, bytes, length); - require(codedir, out); - CFDictionarySetValue(code_signature, CFSTR("CodeDirectory"), codedir); - CFRelease(codedir); - require_string(ntohl(cd->version) >= 0x20001, out, "incompatible version"); - require_string(ntohl(cd->version) <= 0x2F000, out, "incompatible version"); - require_string(cd->hashSize == 20, out, "unexpected hash size"); - require_string(cd->hashType == 1, out, "unexpected hash type"); - - uint32_t hash_offset = ntohl(cd->hashOffset); - uint32_t entitlement_slot = 5; - - if (ntohl(cd->nSpecialSlots) >= entitlement_slot) { - CFDataRef message = CFDataCreate(kCFAllocatorDefault, bytes+hash_offset-entitlement_slot*cd->hashSize, cd->hashSize); - require(message, out); - CFDictionarySetValue(code_signature, CFSTR("EntitlementsCDHash"), message); - CFRelease(message); - } else - fprintf(stderr, "no entitlements slot yet\n"); - } - break; - case 0xfade0b01: //write_data("signed", lc_code_signature, bytes-lc_code_signature); - if (length != 8) { - CFDataRef message = CFDataCreate(kCFAllocatorDefault, bytes+8, length-8); - require(message, out); - CFDictionarySetValue(code_signature, CFSTR("SignedData"), message); - CFRelease(message); - } - break; - case 0xfade7171: - { - unsigned char digest[CC_SHA1_DIGEST_LENGTH]; - CCDigest(kCCDigestSHA1, bytes, length, digest); - - CFDataRef message = CFDataCreate(kCFAllocatorDefault, digest, sizeof(digest)); - require(message, out); - CFDictionarySetValue(code_signature, CFSTR("EntitlementsHash"), message); - CFRelease(message); - message = CFDataCreate(kCFAllocatorDefault, bytes+8, length-8); - require(message, out); - CFDictionarySetValue(code_signature, CFSTR("Entitlements"), message); - CFRelease(message); - break; - } - default: - fprintf(stderr, "Skipping block with magic: 0x%x\n", magic); - break; - } - } - return code_signature; -out: - if (code_signature) CFRelease(code_signature); - return NULL; -} - -static FILE * -open_bundle(const char * path, const char * mode) -{ - char full_path[1024] = {}; - CFStringRef path_cfstring = NULL; - CFURLRef path_url = NULL; - CFBundleRef bundle = NULL; - - path_cfstring = CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path); - require_quiet(path_cfstring, out); - path_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path_cfstring, kCFURLPOSIXPathStyle, true); - require_quiet(path_url, out); - bundle = CFBundleCreate(kCFAllocatorDefault, path_url); - require_quiet(bundle, out); - CFURLRef exec = CFBundleCopyExecutableURL(bundle); - require(exec, out); - require(CFURLGetFileSystemRepresentation(exec, true, (uint8_t*)full_path, sizeof(full_path)), out); -out: - if (path_cfstring) CFRelease(path_cfstring); - if (path_url) CFRelease(path_url); - if (bundle) CFRelease(bundle); - - return fopen(full_path, "r"); -} - -static CFMutableDictionaryRef load_code_signature(FILE *binary, size_t slice_offset) -{ - bool signature_found = false; - CFMutableDictionaryRef result = NULL; - struct load_command lc; - do { - require(1 == fread(&lc, sizeof(lc), 1, binary), out); - if (lc.cmd == LC_CODE_SIGNATURE) { - struct { uint32_t offset; uint32_t size; } sig; - require(1 == fread(&sig, sizeof(sig), 1, binary), out); - require_noerr(fseek(binary, slice_offset+sig.offset, SEEK_SET), out); - size_t length = sig.size; - uint8_t *data = malloc(length); - require(length && data, out); - require(1 == fread(data, length, 1, binary), out); - signature_found = true; - result = lc_code_sig(data, length); - free(data); - break; - } - require_noerr(fseek(binary, lc.cmdsize-sizeof(lc), SEEK_CUR), out); - } while(lc.cmd || lc.cmdsize); /* count lc */ -out: - if (!signature_found) - fprintf(stderr, "No LC_CODE_SIGNATURE segment found\n"); - return result; -} - -static CFArrayRef load_code_signatures(const char *path) -{ - bool fully_parsed_binary = false; - CFMutableDictionaryRef result = NULL; - CFMutableArrayRef results = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - - FILE *binary = open_bundle(path, "r"); - if (!binary) binary = fopen(path, "r"); - require(binary, out); - - struct mach_header header; - require(1 == fread(&header, sizeof(header), 1, binary), out); - if ((header.magic == MH_MAGIC) || (header.magic == MH_MAGIC_64)) { - if (header.magic == MH_MAGIC_64) - fseek(binary, sizeof(struct mach_header_64) - sizeof(struct mach_header), SEEK_CUR); - result = load_code_signature(binary, 0 /*non fat*/); - require(result, out); - CFStringRef type = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("CPU type: (%d,%d)"), header.cputype, header.cpusubtype); - CFDictionarySetValue(result, CFSTR("ARCH"), type); - CFRelease(type); - CFArrayAppendValue(results, result); - } - else - { - struct fat_header fat; - require(!fseek(binary, 0L, SEEK_SET), out); - require(1 == fread(&fat, sizeof(fat), 1, binary), out); - require(ntohl(fat.magic) == FAT_MAGIC, out); - uint32_t slice, slices = ntohl(fat.nfat_arch); - struct fat_arch *archs = calloc(slices, sizeof(struct fat_arch)); - require(slices == fread(archs, sizeof(struct fat_arch), slices, binary), out); - for (slice = 0; slice < slices; slice++) { - uint32_t slice_offset = ntohl(archs[slice].offset); - require(!fseek(binary, slice_offset, SEEK_SET), out); - require(1 == fread(&header, sizeof(header), 1, binary), out); - require((header.magic == MH_MAGIC) || (header.magic == MH_MAGIC_64), out); - if (header.magic == MH_MAGIC_64) - fseek(binary, sizeof(struct mach_header_64) - sizeof(struct mach_header), SEEK_CUR); - result = load_code_signature(binary, slice_offset); - require(result, out); - CFStringRef type = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("CPU type: (%d,%d)"), header.cputype, header.cpusubtype); - CFDictionarySetValue(result, CFSTR("ARCH"), type); - CFRelease(type); - CFArrayAppendValue(results, result); - CFRelease(result); - } - } - fully_parsed_binary = true; -out: - if (!fully_parsed_binary) { - if (results) { - CFRelease(results); - results = NULL; - } - } - if (binary) - fclose(binary); - return results; -} - - -extern int codesign_util(int argc, char * const *argv) -{ - int result = 1, verbose = 0; - char ch; - - while ((ch = getopt(argc, argv, "v")) != -1) - { - switch (ch) - { - case 'v': - verbose++; - break; - default: - return 2; /* Trigger usage message. */ - } - } - - argc -= optind; - argv += optind; - - if (argc != 1) - return 2; /* Trigger usage message. */ - - CFArrayRef sigs = load_code_signatures(argv[0]); - require(sigs, out); - - if (verbose >= 2) - CFShow(sigs); - - CFIndex i, count = CFArrayGetCount(sigs); - - for (i = 0; i < count; i++) { - CFDictionaryRef signature = CFArrayGetValueAtIndex(sigs, i); - - CFDataRef code_dir = CFDictionaryGetValue(signature, CFSTR("CodeDirectory")); - const CS_CodeDirectory *cd = (CS_CodeDirectory *)CFDataGetBytePtr(code_dir); - - CFDataRef signed_data = CFDictionaryGetValue(signature, CFSTR("SignedData")); - - CFDataRef entitlements = CFDictionaryGetValue(signature, CFSTR("Entitlements")); - CFDataRef entitlements_cd_hash = CFDictionaryGetValue(signature, CFSTR("EntitlementsCDHash")); - CFDataRef entitlements_hash = CFDictionaryGetValue(signature, CFSTR("EntitlementsHash")); - - CFStringRef arch = CFDictionaryGetValue(signature, CFSTR("ARCH")); - - CFShow(arch); - - SecPolicyRef policy = SecPolicyCreateiPhoneApplicationSigning(); - - if (signed_data) { - if (SecCMSVerify(signed_data, code_dir, policy, NULL, NULL)) { - fprintf(stderr, "Failed to verify signature\n"); - result = -1; - } else - fprintf(stderr, "Signature ok\n"); - - } else - fprintf(stderr, "Ad-hoc signed binary\n"); - - if (entitlements_cd_hash) { - if (entitlements_hash && entitlements_cd_hash && CFEqual(entitlements_hash, entitlements_cd_hash)) - fprintf(stderr, "Entitlements ok\n"); - else - fprintf(stderr, "Entitlements modified\n"); - } - - if (verbose >= 2) { - fprintf(stderr, "magic: 0x%x length: %u(%lu)\n", ntohl(cd->magic), ntohl(cd->length), CFDataGetLength(code_dir)); - fprintf(stderr, "code directory version/flags: 0x%x/0x%x special/code hash slots: %u/%u\n" - "codelimit: %u hash size/type: %u/%u hash/ident offset: %u/%u\n", - ntohl(cd->version), ntohl(cd->flags), ntohl(cd->nSpecialSlots), ntohl(cd->nCodeSlots), - ntohl(cd->codeLimit), cd->hashSize, cd->hashType, ntohl(cd->hashOffset), ntohl(cd->identOffset)); - fprintf(stderr, "ident: '%s'\n", CFDataGetBytePtr(code_dir) + ntohl(cd->identOffset)); - - uint32_t ix; - uint8_t *hashes = (uint8_t *)CFDataGetBytePtr(code_dir) + ntohl(cd->hashOffset); - for (ix = 0; ix < ntohl(cd->nSpecialSlots); ++ix) { - fprint_digest(stderr, hashes, cd->hashSize); - fprintf(stderr, "\n"); - hashes += cd->hashSize; - } - } - - if (verbose >= 1) { - if (entitlements) - fprintf(stderr, "Entitlements\n%.*s", (int)CFDataGetLength(entitlements)-8, CFDataGetBytePtr(entitlements)+8); - } - - if (verbose >= 2) { - if (entitlements_hash) { - fprintf(stderr, "digest: "); - fprint_digest(stderr, (uint8_t *)CFDataGetBytePtr(entitlements_hash), CC_SHA1_DIGEST_LENGTH); - fprintf(stderr, "\n"); - } - } - } - - CFRelease(sigs); - - return result; -out: - return -1; -} - -#endif // TARGET_OS_EMBEDDED diff --git a/sec/Security/Tool/keychain_add.c b/sec/Security/Tool/keychain_add.c deleted file mode 100644 index b605e2b4..00000000 --- a/sec/Security/Tool/keychain_add.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2003-2007,2009-2010 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 -#if TARGET_OS_EMBEDDED - -#include "Securitycommands.h" - -#include "security.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -static int -do_add_certificates(const char *keychainName, bool trustSettings, - int argc, char * const *argv) -{ - int ix, result = 0; - OSStatus status; - - CFMutableDictionaryRef attributes = - CFDictionaryCreateMutable(NULL, 0, NULL, NULL); - CFDictionarySetValue(attributes, kSecClass, kSecClassCertificate); - - for (ix = 0; ix < argc; ++ix) { - CFDataRef data = copyFileContents(argv[ix]); - if (data) { - SecCertificateRef cert = SecCertificateCreateWithData( - kCFAllocatorDefault, data); - if (!cert) { - cert = SecCertificateCreateWithPEM(kCFAllocatorDefault, data); - } - CFRelease(data); - if (cert) { - if (trustSettings) { - SecTrustStoreSetTrustSettings( - SecTrustStoreForDomain(kSecTrustStoreDomainUser), - cert, NULL); - } else { - CFDictionarySetValue(attributes, kSecValueRef, cert); - status = SecItemAdd(attributes, NULL); - CFRelease(cert); - if (status) { - fprintf(stderr, "file %s: SecItemAdd %s", - argv[ix], sec_errstr(status)); - result = 1; - } - } - } else { - result = 1; - fprintf(stderr, "file %s: does not contain a valid certificate", - argv[ix]); - } - } else { - result = 1; - } - } - - return result; -} - - -int -keychain_add_certificates(int argc, char * const *argv) -{ - int ch, result = 0; - const char *keychainName = NULL; - bool trustSettings = false; - while ((ch = getopt(argc, argv, "hk:t")) != -1) - { - switch (ch) - { - case 'k': - keychainName = optarg; - if (*keychainName == '\0') - return 2; - break; - case 't': - trustSettings = true; - break; - case '?': - default: - return 2; /* Return 2 triggers usage message. */ - } - } - - argc -= optind; - argv += optind; - - if (argc == 0) - return 2; - - result = do_add_certificates(keychainName, trustSettings, argc, argv); - - return result; -} - -#endif // TARGET_OS_EMBEDDED diff --git a/sec/Security/Tool/keychain_find.c b/sec/Security/Tool/keychain_find.c deleted file mode 100644 index 2b248ccd..00000000 --- a/sec/Security/Tool/keychain_find.c +++ /dev/null @@ -1,572 +0,0 @@ -// -// -// -// - - - -#include - -#include - -#include -#include - -#include - -#include "SecurityCommands.h" - -// -// Craptastic hacks. - -typedef uint32_t SecProtocolType; -typedef uint32_t SecAuthenticationType; - -/* Parse a string of the form attr=value,attr=value,attr=value */ -static void -keychain_query_parse_string(CFMutableDictionaryRef q, CFStringRef s) { - bool inkey = true; - bool escaped = false; - CFStringRef key = NULL; - CFMutableStringRef str = CFStringCreateMutable(0, 0); - CFRange rng = { .location = 0, .length = CFStringGetLength(s) }; - CFCharacterSetRef cs_key = CFCharacterSetCreateWithCharactersInString(0, CFSTR("=\\")); - CFCharacterSetRef cs_value = CFCharacterSetCreateWithCharactersInString(0, CFSTR(",\\")); - while (rng.length) { - CFRange r; - CFStringRef sub; - bool complete = false; - if (escaped) { - r.location = rng.location; - r.length = 1; - sub = CFStringCreateWithSubstring(0, s, r); - escaped = false; - } else if (CFStringFindCharacterFromSet(s, inkey ? cs_key : cs_value, rng, 0, &r)) { - if (CFStringGetCharacterAtIndex(s, r.location) == '\\') { - escaped = true; - } else { - complete = true; - } - CFIndex next = r.location + 1; - r.length = r.location - rng.location; - r.location = rng.location; - sub = CFStringCreateWithSubstring(0, s, r); - rng.length -= next - rng.location; - rng.location = next; - } else { - sub = CFStringCreateWithSubstring(0, s, rng); - rng.location += rng.length; - rng.length = 0; - complete = true; - } - CFStringAppend(str, sub); - CFRelease(sub); - if (complete) { - CFStringRef value = CFStringCreateCopy(0, str); - CFStringReplaceAll(str, CFSTR("")); - if (inkey) { - key = value; - } else { - CFDictionarySetValue(q, key, value); - CFReleaseNull(value); - CFReleaseNull(key); - } - inkey = !inkey; - } - } - if (key) { - /* Dangeling key value is true?. */ - CFDictionarySetValue(q, key, kCFBooleanTrue); - CFRelease(key); - } - - CFRelease(str); - CFReleaseSafe(cs_key); - CFReleaseSafe(cs_value); -} - -static void -keychain_query_parse_cstring(CFMutableDictionaryRef q, const char *query) { - CFStringRef s; - s = CFStringCreateWithCStringNoCopy(0, query, kCFStringEncodingUTF8, kCFAllocatorNull); - keychain_query_parse_string(q, s); - CFRelease(s); -} - -static CFMutableDictionaryRef -keychain_create_query_from_string(const char *query) { - CFMutableDictionaryRef q; - - q = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - keychain_query_parse_cstring(q, query); - return q; -} - -static void add_key(const void *key, const void *value, void *context) { - CFArrayAppendValue(context, key); -} - -static void display_item(const void *v_item, void *context) { - CFDictionaryRef item = (CFDictionaryRef)v_item; - CFIndex dict_count, key_ix, key_count; - CFMutableArrayRef keys = NULL; - CFIndex maxWidth = 10; /* Maybe precompute this or grab from context? */ - - dict_count = CFDictionaryGetCount(item); - keys = CFArrayCreateMutable(kCFAllocatorDefault, dict_count, - &kCFTypeArrayCallBacks); - CFDictionaryApplyFunction(item, add_key, keys); - key_count = CFArrayGetCount(keys); - CFArraySortValues(keys, CFRangeMake(0, key_count), - (CFComparatorFunction)CFStringCompare, 0); - - for (key_ix = 0; key_ix < key_count; ++key_ix) { - CFStringRef key = (CFStringRef)CFArrayGetValueAtIndex(keys, key_ix); - CFTypeRef value = CFDictionaryGetValue(item, key); - CFMutableStringRef line = CFStringCreateMutable(NULL, 0); - - CFStringAppend(line, key); - CFIndex jx; - for (jx = CFStringGetLength(key); - jx < maxWidth; ++jx) { - CFStringAppend(line, CFSTR(" ")); - } - CFStringAppend(line, CFSTR(" : ")); - if (CFStringGetTypeID() == CFGetTypeID(value)) { - CFStringAppend(line, (CFStringRef)value); - } else if (CFNumberGetTypeID() == CFGetTypeID(value)) { - CFNumberRef v_n = (CFNumberRef)value; - CFStringAppendFormat(line, NULL, CFSTR("%@"), v_n); - } else if (CFDateGetTypeID() == CFGetTypeID(value)) { - CFDateRef v_d = (CFDateRef)value; - CFStringAppendFormat(line, NULL, CFSTR("%@"), v_d); - } else if (CFDataGetTypeID() == CFGetTypeID(value)) { - CFDataRef v_d = (CFDataRef)value; - CFStringRef v_s = CFStringCreateFromExternalRepresentation( - kCFAllocatorDefault, v_d, kCFStringEncodingUTF8); - if (v_s) { - CFStringAppend(line, CFSTR("/")); - CFStringAppend(line, v_s); - CFStringAppend(line, CFSTR("/ ")); - CFRelease(v_s); - } - const uint8_t *bytes = CFDataGetBytePtr(v_d); - CFIndex len = CFDataGetLength(v_d); - for (jx = 0; jx < len; ++jx) { - CFStringAppendFormat(line, NULL, CFSTR("%.02X"), bytes[jx]); - } - } else { - CFStringAppendFormat(line, NULL, CFSTR("%@"), value); - } - - CFStringWriteToFileWithNewline(line, stdout); - - CFRelease(line); - } - CFRelease(keys); - - CFStringWriteToFileWithNewline(CFSTR("===="), stdout); - - //CFShow(item); -} - - -static void display_results(CFTypeRef results) { - if (CFGetTypeID(results) == CFArrayGetTypeID()) { - CFArrayRef r_a = (CFArrayRef)results; - CFArrayApplyFunction(r_a, CFRangeMake(0, CFArrayGetCount(r_a)), - display_item, NULL); - } else if (CFGetTypeID(results) == CFArrayGetTypeID()) { - display_item(results, NULL); - } else { - fprintf(stderr, "SecItemCopyMatching returned unexpected results:"); - CFShow(results); - } -} - -static OSStatus do_find_or_delete(CFDictionaryRef query, bool do_delete) { - OSStatus result; - if (do_delete) { - result = SecItemDelete(query); - if (result) { - sec_perror("SecItemDelete", result); - } - } else { - CFTypeRef results = NULL; - result = SecItemCopyMatching(query, &results); - if (result) { - sec_perror("SecItemCopyMatching", result); - } else { - display_results(results); - } - CFReleaseSafe(results); - } - return result; -} - -static int -do_keychain_find_or_delete_internet_password(Boolean do_delete, - const char *serverName, const char *securityDomain, - const char *accountName, const char *path, UInt16 port, - SecProtocolType protocol, SecAuthenticationType authenticationType, - Boolean get_password) - { - OSStatus result; - CFDictionaryRef query = NULL; - const void *keys[11], *values[11]; - CFIndex ix = 0; - - keys[ix] = kSecClass; - values[ix++] = kSecClassInternetPassword; - if (serverName) { - keys[ix] = kSecAttrServer; - values[ix++] = CFStringCreateWithCStringNoCopy(NULL, serverName, - kCFStringEncodingUTF8, kCFAllocatorNull); - } - if (securityDomain) { - keys[ix] = kSecAttrSecurityDomain; - values[ix++] = CFStringCreateWithCStringNoCopy(NULL, securityDomain, - kCFStringEncodingUTF8, kCFAllocatorNull); - } - if (accountName) { - keys[ix] = kSecAttrAccount; - values[ix++] = CFStringCreateWithCStringNoCopy(NULL, accountName, - kCFStringEncodingUTF8, kCFAllocatorNull); - } - if (path) { - keys[ix] = kSecAttrPath; - values[ix++] = CFStringCreateWithCStringNoCopy(NULL, path, - kCFStringEncodingUTF8, kCFAllocatorNull); - } - if (port != 0) { - keys[ix] = kSecAttrPort; - values[ix++] = CFNumberCreate(NULL, kCFNumberSInt16Type, &port); - } - if (protocol != 0) { - /* Protocol is a 4 char code, perhaps we should use a string rep - instead. */ - keys[ix] = kSecAttrProtocol; - values[ix++] = CFNumberCreate(NULL, kCFNumberSInt32Type, &protocol); - } - if (authenticationType != 0) { - keys[ix] = kSecAttrAuthenticationType; - values[ix++] = CFNumberCreate(NULL, kCFNumberSInt32Type, - &authenticationType); - } - if (get_password) { - /* Only ask for the data if so required. */ - keys[ix] = kSecReturnData; - values[ix++] = kCFBooleanTrue; - } - keys[ix] = kSecReturnAttributes; - values[ix++] = kCFBooleanTrue; - if (!do_delete) { - /* If we aren't deleting ask for all items. */ - keys[ix] = kSecMatchLimit; - values[ix++] = kSecMatchLimitAll; - } - - query = CFDictionaryCreate(NULL, keys, values, ix, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - result = do_find_or_delete(query, do_delete); - CFReleaseSafe(query); - - return result; -} - -static int -parse_fourcharcode(const char *name, uint32_t *code) -{ - /* @@@ Check for errors. */ - char *p = (char *)code; - strncpy(p, name, 4); - return 0; -} - -static int -keychain_find_or_delete_internet_password(Boolean do_delete, int argc, char * const *argv) -{ - char *serverName = NULL, *securityDomain = NULL, *accountName = NULL, *path = NULL; - UInt16 port = 0; - SecProtocolType protocol = 0; - SecAuthenticationType authenticationType = 0; - int ch, result = 0; - Boolean get_password = FALSE; - - while ((ch = getopt(argc, argv, "a:d:hgp:P:r:s:t:")) != -1) - { - switch (ch) - { - case 'a': - accountName = optarg; - break; - case 'd': - securityDomain = optarg; - break; - case 'g': - if (do_delete) - return 2; - get_password = TRUE; - break; - case 'p': - path = optarg; - break; - case 'P': - port = atoi(optarg); - break; - case 'r': - result = parse_fourcharcode(optarg, &protocol); - if (result) - goto loser; - break; - case 's': - serverName = optarg; - break; - case 't': - result = parse_fourcharcode(optarg, &authenticationType); - if (result) - goto loser; - break; - case '?': - default: - return 2; /* @@@ Return 2 triggers usage message. */ - } - } - - argc -= optind; - argv += optind; - - result = do_keychain_find_or_delete_internet_password(do_delete, serverName, securityDomain, - accountName, path, port, protocol,authenticationType, get_password); - - -loser: - - return result; -} - -int -keychain_find_internet_password(int argc, char * const *argv) { - return keychain_find_or_delete_internet_password(0, argc, argv); -} - -int -keychain_delete_internet_password(int argc, char * const *argv) { - return keychain_find_or_delete_internet_password(1, argc, argv); -} - -static int -do_keychain_find_or_delete_generic_password(Boolean do_delete, - const char *serviceName, const char *accountName, - Boolean get_password) - { - OSStatus result; - CFDictionaryRef query = NULL; - const void *keys[6], *values[6]; - CFIndex ix = 0; - - keys[ix] = kSecClass; - values[ix++] = kSecClassGenericPassword; - if (serviceName) { - keys[ix] = kSecAttrService; - values[ix++] = CFStringCreateWithCStringNoCopy(NULL, serviceName, - kCFStringEncodingUTF8, kCFAllocatorNull); - } - if (accountName) { - keys[ix] = kSecAttrAccount; - values[ix++] = CFStringCreateWithCStringNoCopy(NULL, accountName, - kCFStringEncodingUTF8, kCFAllocatorNull); - } - if (get_password) { - /* Only ask for the data if so required. */ - keys[ix] = kSecReturnData; - values[ix++] = kCFBooleanTrue; - } - keys[ix] = kSecReturnAttributes; - values[ix++] = kCFBooleanTrue; - if (!do_delete) { - /* If we aren't deleting ask for all items. */ - keys[ix] = kSecMatchLimit; - values[ix++] = kSecMatchLimitAll; - } - - query = CFDictionaryCreate(NULL, keys, values, ix, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - result = do_find_or_delete(query, do_delete); - - CFReleaseSafe(query); - - return result; -} - -int keychain_item(int argc, char * const *argv) { - int ch, result = 0; - CFMutableDictionaryRef query, update = NULL; - bool get_password = false; - bool do_delete = false; - bool do_add = false; - bool verbose = false; - int limit = 0; - - query = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - while ((ch = getopt(argc, argv, "ad:Df:gq:u:vl:")) != -1) - { - switch (ch) - { - case 'a': - do_add = true; - break; - case 'D': - do_delete = true; - break; - case 'd': - { - CFStringRef data = CFStringCreateWithCString(0, optarg, kCFStringEncodingUTF8); - if (data) { - CFDictionarySetValue(update ? update : query, kSecValueData, data); - CFRelease(data); - } else { - result = 1; - goto out; - } - break; - } - case 'f': - { - CFDataRef data = copyFileContents(optarg); - CFDictionarySetValue(update ? update : query, kSecValueData, data); - CFRelease(data); - break; - } - case 'g': - get_password = true; - break; - case 'q': - keychain_query_parse_cstring(query, optarg); - break; - case 'u': - if (!update) - update = keychain_create_query_from_string(optarg); - else - keychain_query_parse_cstring(update, optarg); - break; - case 'v': - verbose = true; - break; - case 'l': - limit = atoi(optarg); - break; - case '?': - default: - /* Return 2 triggers usage message. */ - result = 2; - goto out; - } - } - - if (((do_add || do_delete) && (get_password || update)) || !query) { - result = 2; - goto out; - } - - argc -= optind; - argv += optind; - - int ix; - for (ix = 0; ix < argc; ++ix) { - keychain_query_parse_cstring(query, argv[ix]); - } - - if (!update && !do_add && !do_delete) { - CFDictionarySetValue(query, kSecReturnAttributes, kCFBooleanTrue); - if(limit) { - CFNumberRef cfLimit = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &limit); - CFDictionarySetValue(query, kSecMatchLimit, cfLimit); - CFReleaseSafe(cfLimit); - } else { - CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll); - } - if (get_password) - CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue); - } - - if (verbose) - CFShow(query); - - OSStatus error; - if (do_add) { - error = SecItemAdd(query, NULL); - if (error) { - sec_perror("SecItemAdd", error); - result = 1; - } - } else if (update) { - error = SecItemUpdate(query, update); - if (error) { - sec_perror("SecItemUpdate", error); - result = 1; - } - } else if (do_delete) { - error = SecItemDelete(query); - if (error) { - sec_perror("SecItemDelete", error); - result = 1; - } - } else { - do_find_or_delete(query, do_delete); - } - -out: - CFReleaseSafe(query); - CFReleaseSafe(update); - return result; -} - -static int -keychain_find_or_delete_generic_password(Boolean do_delete, - int argc, char * const *argv) -{ - char *serviceName = NULL, *accountName = NULL; - int ch, result = 0; - Boolean get_password = FALSE; - - while ((ch = getopt(argc, argv, "a:s:g")) != -1) - { - switch (ch) - { - case 'a': - accountName = optarg; - break; - case 'g': - if (do_delete) - return 2; - get_password = TRUE; - break; - case 's': - serviceName = optarg; - break; - case '?': - default: - return 2; /* @@@ Return 2 triggers usage message. */ - } - } - - argc -= optind; - argv += optind; - - result = do_keychain_find_or_delete_generic_password(do_delete, - serviceName, accountName, get_password); - - return result; -} - -int -keychain_find_generic_password(int argc, char * const *argv) { - return keychain_find_or_delete_generic_password(0, argc, argv); -} - -int -keychain_delete_generic_password(int argc, char * const *argv) { - return keychain_find_or_delete_generic_password(1, argc, argv); -} diff --git a/sec/Security/certextensions.h b/sec/Security/certextensions.h deleted file mode 100644 index 30dc1b63..00000000 --- a/sec/Security/certextensions.h +++ /dev/null @@ -1,546 +0,0 @@ -/* - * Copyright (c) 2000-2009 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@ - * - * CertExtensions.h -- X.509 Cert Extensions as C structs - */ - -#ifndef _CERT_EXTENSIONS_H_ -#define _CERT_EXTENSIONS_H_ - -#include -#include -//#include - -/*** - *** Structs for declaring extension-specific data. - ***/ - -/* - * GeneralName, used in AuthorityKeyID, SubjectAltName, and - * IssuerAltName. - * - * For now, we just provide explicit support for the types which are - * represented as IA5Strings, OIDs, and octet strings. Constructed types - * such as EDIPartyName and x400Address are not explicitly handled - * right now and must be encoded and decoded by the caller. (See exception - * for Name and OtherName, below). In those cases the SecCEGeneralName.name.Data field - * represents the BER contents octets; SecCEGeneralName.name.Length is the - * length of the contents; the tag of the field is not needed - the BER - * encoding uses context-specific implicit tagging. The berEncoded field - * is set to true in these case. Simple types have berEncoded = false. - * - * In the case of a GeneralName in the form of a Name, we parse the Name - * into a CSSM_X509_NAME and place a pointer to the CSSM_X509_NAME in the - * SecCEGeneralName.name.Data field. SecCEGeneralName.name.Length is set to - * sizeof(CSSM_X509_NAME). In this case berEncoded is false. - * - * In the case of a GeneralName in the form of a OtherName, we parse the fields - * into a SecCEOtherName and place a pointer to the SecCEOtherName in the - * SecCEGeneralName.name.Data field. SecCEGeneralName.name.Length is set to - * sizeof(SecCEOtherName). In this case berEncoded is false. - * - * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName - * - * GeneralName ::= CHOICE { - * otherName [0] OtherName - * rfc822Name [1] IA5String, - * dNSName [2] IA5String, - * x400Address [3] ORAddress, - * directoryName [4] Name, - * ediPartyName [5] EDIPartyName, - * uniformResourceIdentifier [6] IA5String, - * iPAddress [7] OCTET STRING, - * registeredID [8] OBJECT IDENTIFIER} - * - * OtherName ::= SEQUENCE { - * type-id OBJECT IDENTIFIER, - * value [0] EXPLICIT ANY DEFINED BY type-id } - * - * EDIPartyName ::= SEQUENCE { - * nameAssigner [0] DirectoryString OPTIONAL, - * partyName [1] DirectoryString } - */ -typedef enum { - GNT_OtherName = 0, - GNT_RFC822Name, - GNT_DNSName, - GNT_X400Address, - GNT_DirectoryName, - GNT_EdiPartyName, - GNT_URI, - GNT_IPAddress, - GNT_RegisteredID -} SecCEGeneralNameType; - -typedef struct { - DERItem typeId; - DERItem value; // unparsed, BER-encoded -} SecCEOtherName; - -typedef struct { - SecCEGeneralNameType nameType; // GNT_RFC822Name, etc. - bool berEncoded; - DERItem name; -} SecCEGeneralName; - -typedef struct { - uint32_t numNames; - SecCEGeneralName *generalName; -} SecCEGeneralNames; - -/* - * id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } - * - * AuthorityKeyIdentifier ::= SEQUENCE { - * keyIdentifier [0] KeyIdentifier OPTIONAL, - * authorityCertIssuer [1] GeneralNames OPTIONAL, - * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } - * - * KeyIdentifier ::= OCTET STRING - * - * CSSM OID = CSSMOID_AuthorityKeyIdentifier - */ -typedef struct { - bool keyIdentifierPresent; - DERItem keyIdentifier; - bool generalNamesPresent; - SecCEGeneralNames *generalNames; - bool serialNumberPresent; - DERItem serialNumber; -} SecCEAuthorityKeyID; - -/* - * id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } - * SubjectKeyIdentifier ::= KeyIdentifier - * - * CSSM OID = CSSMOID_SubjectKeyIdentifier - */ -typedef DERItem SecCESubjectKeyID; - -/* - * id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } - * - * KeyUsage ::= BIT STRING { - * digitalSignature (0), - * nonRepudiation (1), - * keyEncipherment (2), - * dataEncipherment (3), - * keyAgreement (4), - * keyCertSign (5), - * cRLSign (6), - * encipherOnly (7), - * decipherOnly (8) } - * - * CSSM OID = CSSMOID_KeyUsage - * - */ -typedef uint16_t SecCEKeyUsage; - -#define SecCEKU_DigitalSignature 0x8000 -#define SecCEKU_NonRepudiation 0x4000 -#define SecCEKU_KeyEncipherment 0x2000 -#define SecCEKU_DataEncipherment 0x1000 -#define SecCEKU_KeyAgreement 0x0800 -#define SecCEKU_KeyCertSign 0x0400 -#define SecCEKU_CRLSign 0x0200 -#define SecCEKU_EncipherOnly 0x0100 -#define SecCEKU_DecipherOnly 0x0080 - -/* - * id-ce-cRLReason OBJECT IDENTIFIER ::= { id-ce 21 } - * - * -- reasonCode ::= { CRLReason } - * - * CRLReason ::= ENUMERATED { - * unspecified (0), - * keyCompromise (1), - * cACompromise (2), - * affiliationChanged (3), - * superseded (4), - * cessationOfOperation (5), - * certificateHold (6), - * removeFromCRL (8) } - * - * CSSM OID = CSSMOID_CrlReason - * - */ -typedef uint32_t SecCECrlReason; - -#define SecCECR_Unspecified 0 -#define SecCECR_KeyCompromise 1 -#define SecCECR_CACompromise 2 -#define SecCECR_AffiliationChanged 3 -#define SecCECR_Superseded 4 -#define SecCECR_CessationOfOperation 5 -#define SecCECR_CertificateHold 6 -#define SecCECR_RemoveFromCRL 8 - -/* - * id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } - * - * SubjectAltName ::= GeneralNames - * - * CSSM OID = CSSMOID_SubjectAltName - * - * GeneralNames defined above. - */ - -/* - * id-ce-extKeyUsage OBJECT IDENTIFIER ::= {id-ce 37} - * - * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId* - * - * KeyPurposeId ::= OBJECT IDENTIFIER - * - * CSSM OID = CSSMOID_ExtendedKeyUsage - */ -typedef struct { - uint32_t numPurposes; - DERItem *purposes; // in Intel pre-encoded format -} SecCEExtendedKeyUsage; - -/* - * id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } - * - * BasicConstraints ::= SEQUENCE { - * cA BOOLEAN DEFAULT FALSE, - * pathLenConstraint INTEGER (0..MAX) OPTIONAL } - * - * CSSM OID = CSSMOID_BasicConstraints - */ -typedef struct { - bool present; - bool critical; - bool isCA; - bool pathLenConstraintPresent; - uint32_t pathLenConstraint; -} SecCEBasicConstraints; - -typedef struct { - bool present; - bool critical; - bool requireExplicitPolicyPresent; - uint32_t requireExplicitPolicy; - bool inhibitPolicyMappingPresent; - uint32_t inhibitPolicyMapping; -} SecCEPolicyConstraints; - -/* - * id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } - * - * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation - * - * PolicyInformation ::= SEQUENCE { - * policyIdentifier CertPolicyId, - * policyQualifiers SEQUENCE SIZE (1..MAX) OF - * PolicyQualifierInfo OPTIONAL } - * - * CertPolicyId ::= OBJECT IDENTIFIER - * - * PolicyQualifierInfo ::= SEQUENCE { - * policyQualifierId PolicyQualifierId, - * qualifier ANY DEFINED BY policyQualifierId } - * - * -- policyQualifierIds for Internet policy qualifiers - * - * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } - * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } - * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } - * - * PolicyQualifierId ::= - * OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) - * - * Qualifier ::= CHOICE { - * cPSuri CPSuri, - * userNotice UserNotice } - * - * CPSuri ::= IA5String - * - * UserNotice ::= SEQUENCE { - * noticeRef NoticeReference OPTIONAL, - * explicitText DisplayText OPTIONAL} - * - * NoticeReference ::= SEQUENCE { - * organization DisplayText, - * noticeNumbers SEQUENCE OF INTEGER } - * - * DisplayText ::= CHOICE { - * visibleString VisibleString (SIZE (1..200)), - * bmpString BMPString (SIZE (1..200)), - * utf8String UTF8String (SIZE (1..200)) } - * - * CSSM OID = CSSMOID_CertificatePolicies - * - * We only support down to the level of Qualifier, and then only the CPSuri - * choice. UserNotice is transmitted to and from this library as a raw - * CSSM_DATA containing the BER-encoded UserNotice sequence. - */ -#if 0 -typedef struct { - DERItem policyQualifierId; // CSSMOID_QT_CPS, CSSMOID_QT_UNOTICE - DERItem qualifier; // CSSMOID_QT_CPS: IA5String contents - // CSSMOID_QT_UNOTICE : Sequence contents -} SecCEPolicyQualifierInfo; -#endif - -typedef struct { - DERItem policyIdentifier; - DERItem policyQualifiers; -} SecCEPolicyInformation; - -typedef struct { - bool present; - bool critical; - size_t numPolicies; // size of *policies; - SecCEPolicyInformation *policies; -} SecCECertificatePolicies; - -typedef struct { - DERItem issuerDomainPolicy; - DERItem subjectDomainPolicy; -} SecCEPolicyMapping; - -/* - PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { - issuerDomainPolicy CertPolicyId, - subjectDomainPolicy CertPolicyId } -*/ -typedef struct { - bool present; - bool critical; - uint32_t numMappings; // size of *mappings; - SecCEPolicyMapping *mappings; -} SecCEPolicyMappings; - -#if 0 -typedef struct { - bool present; - bool critical; - uint32_t skipCerts; -} SecCEInhibitAnyPolicy; - -/* - * netscape-cert-type, a bit string. - * - * CSSM OID = CSSMOID_NetscapeCertType - * - * Bit fields defined in oidsattr.h: SecCENCT_SSL_Client, etc. - */ -typedef uint16_t SecCENetscapeCertType; - -/* - * CRLDistributionPoints. - * - * id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } - * - * cRLDistributionPoints ::= { - * CRLDistPointsSyntax } - * - * CRLDistPointsSyntax ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint - * - * NOTE: RFC 2459 claims that the tag for the optional DistributionPointName - * is IMPLICIT as shown here, but in practice it is EXPLICIT. It has to be - - * because the underlying type also uses an implicit tag for distinguish - * between CHOICEs. - * - * DistributionPoint ::= SEQUENCE { - * distributionPoint [0] DistributionPointName OPTIONAL, - * reasons [1] ReasonFlags OPTIONAL, - * cRLIssuer [2] GeneralNames OPTIONAL } - * - * DistributionPointName ::= CHOICE { - * fullName [0] GeneralNames, - * nameRelativeToCRLIssuer [1] RelativeDistinguishedName } - * - * ReasonFlags ::= BIT STRING { - * unused (0), - * keyCompromise (1), - * cACompromise (2), - * affiliationChanged (3), - * superseded (4), - * cessationOfOperation (5), - * certificateHold (6) } - * - * CSSM OID = CSSMOID_CrlDistributionPoints - */ - -/* - * Note that this looks similar to SecCECrlReason, but that's an enum and this - * is an OR-able bit string. - */ -typedef uint8_t SecCECrlDistReasonFlags; - -#define SecCECD_Unspecified 0x80 -#define SecCECD_KeyCompromise 0x40 -#define SecCECD_CACompromise 0x20 -#define SecCECD_AffiliationChanged 0x10 -#define SecCECD_Superseded 0x08 -#define SecCECD_CessationOfOperation 0x04 -#define SecCECD_CertificateHold 0x02 - -typedef enum { - SecCECDNT_FullName, - SecCECDNT_NameRelativeToCrlIssuer -} SecCECrlDistributionPointNameType; - -typedef struct { - SecCECrlDistributionPointNameType nameType; - union { - SecCEGeneralNames *fullName; - CSSM_X509_RDN_PTR rdn; - } dpn; -} SecCEDistributionPointName; - -/* - * The top-level CRLDistributionPoint. - * All fields are optional; NULL pointers indicate absence. - */ -typedef struct { - SecCEDistributionPointName *distPointName; - bool reasonsPresent; - SecCECrlDistReasonFlags reasons; - SecCEGeneralNames *crlIssuer; -} SecCECRLDistributionPoint; - -typedef struct { - uint32_t numDistPoints; - SecCECRLDistributionPoint *distPoints; -} SecCECRLDistPointsSyntax; - -/* - * Authority Information Access and Subject Information Access. - * - * CSSM OID = CSSMOID_AuthorityInfoAccess - * CSSM OID = CSSMOID_SubjectInfoAccess - * - * SubjAuthInfoAccessSyntax ::= - * SEQUENCE SIZE (1..MAX) OF AccessDescription - * - * AccessDescription ::= SEQUENCE { - * accessMethod OBJECT IDENTIFIER, - * accessLocation GeneralName } - */ -typedef struct { - DERItem accessMethod; - SecCEGeneralName accessLocation; -} SecCEAccessDescription; - -typedef struct { - uint32_t numAccessDescriptions; - SecCEAccessDescription *accessDescriptions; -} SecCEAuthorityInfoAccess; - -/*** CRL extensions ***/ - -/* - * cRLNumber, an integer. - * - * CSSM OID = CSSMOID_CrlNumber - */ -typedef uint32_t SecCECrlNumber; - -/* - * deltaCRLIndicator, an integer. - * - * CSSM OID = CSSMOID_DeltaCrlIndicator - */ -typedef uint32_t SecCEDeltaCrl; - -/* - * IssuingDistributionPoint - * - * id-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-ce 28 } - * - * issuingDistributionPoint ::= SEQUENCE { - * distributionPoint [0] DistributionPointName OPTIONAL, - * onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE, - * onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE, - * onlySomeReasons [3] ReasonFlags OPTIONAL, - * indirectCRL [4] BOOLEAN DEFAULT FALSE } - * - * CSSM OID = CSSMOID_IssuingDistributionPoint - */ -typedef struct { - SecCEDistributionPointName *distPointName; // optional - bool onlyUserCertsPresent; - bool onlyUserCerts; - bool onlyCACertsPresent; - bool onlyCACerts; - bool onlySomeReasonsPresent; - SecCECrlDistReasonFlags onlySomeReasons; - bool indirectCrlPresent; - bool indirectCrl; -} SecCEIssuingDistributionPoint; - -/* - * An enumerated list identifying one of the above per-extension - * structs. - */ -typedef enum { - DT_AuthorityKeyID, // SecCEAuthorityKeyID - DT_SubjectKeyID, // SecCESubjectKeyID - DT_KeyUsage, // SecCEKeyUsage - DT_SubjectAltName, // implies SecCEGeneralName - DT_IssuerAltName, // implies SecCEGeneralName - DT_ExtendedKeyUsage, // SecCEExtendedKeyUsage - DT_BasicConstraints, // SecCEBasicConstraints - DT_CertPolicies, // SecCECertPolicies - DT_NetscapeCertType, // SecCENetscapeCertType - DT_CrlNumber, // SecCECrlNumber - DT_DeltaCrl, // SecCEDeltaCrl - DT_CrlReason, // SecCECrlReason - DT_CrlDistributionPoints, // SecCECRLDistPointsSyntax - DT_IssuingDistributionPoint,// SecCEIssuingDistributionPoint - DT_AuthorityInfoAccess, // SecCEAuthorityInfoAccess - DT_Other // unknown, raw data as a CSSM_DATA -} SecCEDataType; - -/* - * One unified representation of all the cert adn CRL extensions we know about. - */ -typedef union { - SecCEAuthorityKeyID authorityKeyID; - SecCESubjectKeyID subjectKeyID; - SecCEKeyUsage keyUsage; - SecCEGeneralNames subjectAltName; - SecCEGeneralNames issuerAltName; - SecCEExtendedKeyUsage extendedKeyUsage; - SecCEBasicConstraints basicConstraints; - SecCECertPolicies certPolicies; - SecCENetscapeCertType netscapeCertType; - SecCECrlNumber crlNumber; - SecCEDeltaCrl deltaCrl; - SecCECrlReason crlReason; - SecCECRLDistPointsSyntax crlDistPoints; - SecCEIssuingDistributionPoint issuingDistPoint; - SecCEAuthorityInfoAccess authorityInfoAccess; - DERItem rawData; // unknown, not decoded -} SecCEData; - -typedef struct { - SecCEDataType type; - SecCEData extension; - bool critical; -} SecCEDataAndType; -#endif /* 0 */ - -#endif /* _CERT_EXTENSIONS_H_ */ diff --git a/sec/Security/cssmapple.h b/sec/Security/cssmapple.h deleted file mode 100644 index 183bac78..00000000 --- a/sec/Security/cssmapple.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2000-2004 Apple Computer, 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@ - * - * cssmapple.h -- CSSM features specific to Apple's Implementation - */ - -#ifndef _CSSMAPPLE_H_ -#define _CSSMAPPLE_H_ 1 - - -#ifdef __cplusplus -extern "C" { -#endif - -/* First, an array of bits indicating various status of the cert. */ -typedef uint32 CSSM_TP_APPLE_CERT_STATUS; -enum -{ - CSSM_CERT_STATUS_EXPIRED = 0x00000001, - CSSM_CERT_STATUS_NOT_VALID_YET = 0x00000002, - CSSM_CERT_STATUS_IS_IN_INPUT_CERTS = 0x00000004, - CSSM_CERT_STATUS_IS_IN_ANCHORS = 0x00000008, - CSSM_CERT_STATUS_IS_ROOT = 0x00000010, - CSSM_CERT_STATUS_IS_FROM_NET = 0x00000020, - /* settings found in per-user Trust Settings */ - CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_USER = 0x00000040, - /* settings found in Admin Trust Settings */ - CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_ADMIN = 0x00000080, - /* settings found in System Trust Settings */ - CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_SYSTEM = 0x00000100, - /* Trust Settings result = Trust */ - CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST = 0x00000200, - /* Trust Settings result = Deny */ - CSSM_CERT_STATUS_TRUST_SETTINGS_DENY = 0x00000400, - /* Per-cert error ignored due to Trust Settings */ - CSSM_CERT_STATUS_TRUST_SETTINGS_IGNORED_ERROR = 0x00000800 -}; - -typedef struct { - CSSM_TP_APPLE_CERT_STATUS StatusBits; - uint32 NumStatusCodes; - CSSM_RETURN *StatusCodes; - - /* index into raw cert group or AnchorCerts depending on IS_IN_ANCHORS */ - uint32 Index; - - /* nonzero if cert came from a DLDB */ - CSSM_DL_DB_HANDLE DlDbHandle; - CSSM_DB_UNIQUE_RECORD_PTR UniqueRecord; -} CSSM_TP_APPLE_EVIDENCE_INFO; - - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif /* _CSSMAPPLE_H_ */ diff --git a/sec/Security/keychain_find.h b/sec/Security/keychain_find.h deleted file mode 100644 index e1dcc0ff..00000000 --- a/sec/Security/keychain_find.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2003-2007 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_find.h - */ - -#ifndef _KEYCHAIN_FINDINTERNETPASSWORD_H_ -#define _KEYCHAIN_FINDINTERNETPASSWORD_H_ 1 - -#ifdef __cplusplus -extern "C" { -#endif - -extern int keychain_item(int argc, char * const *argv); - -extern int keychain_find_internet_password(int argc, char * const *argv); - -extern int keychain_find_generic_password(int argc, char * const *argv); - -extern int keychain_find_certificate(int argc, char * const *argv); - -extern int keychain_delete_internet_password(int argc, char * const *argv); - -extern int keychain_delete_generic_password(int argc, char * const *argv); - -extern int keychain_dump(int argc, char * const *argv); - -extern int keychain_show_certificates(int argc, char * const *argv); - -#ifdef __cplusplus -} -#endif - -#endif /* _KEYCHAIN_FINDINTERNETPASSWORD_H_ */ diff --git a/sec/Security/pbkdf2.c b/sec/Security/pbkdf2.c deleted file mode 100644 index 0600ad3e..00000000 --- a/sec/Security/pbkdf2.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - - -/* - File: pbkdf2.c - Contains: Apple Data Security Services PKCS #5 PBKDF2 function definition. - Copyright: (C) 1999 by Apple Computer, Inc., all rights reserved - Written by: Michael Brouwer -*/ -#include "pbkdf2.h" -#include -/* Will write hLen bytes into dataPtr according to PKCS #5 2.0 spec. - See: http://www.rsa.com/rsalabs/node.asp?id=2127 for details. - tempBuffer is a pointer to at least MAX (hLen, saltLen + 4) + hLen bytes. */ -static void -F (PRF prf, size_t hLen, - const void *passwordPtr, size_t passwordLen, - const void *saltPtr, size_t saltLen, - size_t iterationCount, - uint32_t blockNumber, - void *dataPtr, - void *tempBuffer) -{ - uint8_t *inBlock, *outBlock, *resultBlockPtr; - size_t iteration; - outBlock = (uint8_t*)tempBuffer; - inBlock = outBlock + hLen; - /* Set up inBlock to contain Salt || INT (blockNumber). */ - memcpy (inBlock, saltPtr, saltLen); - - inBlock[saltLen + 0] = (uint8_t)(blockNumber >> 24); - inBlock[saltLen + 1] = (uint8_t)(blockNumber >> 16); - inBlock[saltLen + 2] = (uint8_t)(blockNumber >> 8); - inBlock[saltLen + 3] = (uint8_t)(blockNumber); - - /* Caculate U1 (result goes to outBlock) and copy it to resultBlockPtr. */ - resultBlockPtr = (uint8_t*)dataPtr; - prf (passwordPtr, passwordLen, inBlock, saltLen + 4, outBlock); - memcpy (resultBlockPtr, outBlock, hLen); - /* Calculate U2 though UiterationCount. */ - for (iteration = 2; iteration <= iterationCount; iteration++) - { - uint8_t *tempBlock; - uint32_t byte; - /* Swap inBlock and outBlock pointers. */ - tempBlock = inBlock; - inBlock = outBlock; - outBlock = tempBlock; - /* Now inBlock conatins Uiteration-1. Calculate Uiteration into outBlock. */ - prf (passwordPtr, passwordLen, inBlock, hLen, outBlock); - /* Xor data in dataPtr (U1 \xor U2 \xor ... \xor Uiteration-1) with - outBlock (Uiteration). */ - for (byte = 0; byte < hLen; byte++) - resultBlockPtr[byte] ^= outBlock[byte]; - } -} -void pbkdf2 (PRF prf, size_t hLen, - const void *passwordPtr, size_t passwordLen, - const void *saltPtr, size_t saltLen, - size_t iterationCount, - void *dkPtr, size_t dkLen, - void *tempBuffer) -{ - size_t completeBlocks = dkLen / hLen; - size_t partialBlockSize = dkLen % hLen; - uint32_t blockNumber; - uint8_t *dataPtr = (uint8_t*)dkPtr; - uint8_t *blkBuffer = (uint8_t*)tempBuffer; - - /* This check make sure that the following loops ends, in case where dk_len is 64 bits, and very large. - This will cause the derived key to be the maximum size supported by pbkdf2 (4GB * size of the hash) - rather than the actual requested size.*/ - completeBlocks=completeBlocks & UINT32_MAX; - - /* First calculate all the complete hLen sized blocks required. */ - for (blockNumber = 1; blockNumber <= completeBlocks; blockNumber++) - { - F (prf, hLen, passwordPtr, passwordLen, saltPtr, saltLen, - iterationCount, blockNumber, dataPtr, blkBuffer + hLen); - dataPtr += hLen; - } - /* Finally if the requested output size was not an even multiple of hLen, calculate - the final block and copy the first partialBlockSize bytes of it to the output. */ - if (partialBlockSize > 0) - { - F (prf, hLen, passwordPtr, passwordLen, saltPtr, saltLen, - iterationCount, blockNumber, blkBuffer, blkBuffer + hLen); - memcpy (dataPtr, blkBuffer, partialBlockSize); - } -} diff --git a/sec/Security/pbkdf2.h b/sec/Security/pbkdf2.h deleted file mode 100644 index df556fdb..00000000 --- a/sec/Security/pbkdf2.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ -#include -#include -#include - -/* - File: pbkdf2.h - Contains: Apple Data Security Services PKCS #5 PBKDF2 function declaration. - Copyright: (C) 1999 by Apple Computer, Inc., all rights reserved - Written by: Michael Brouwer -*/ - -#ifndef __PBKDF2__ -#define __PBKDF2__ - -__BEGIN_DECLS - -/* This function should generate a pseudo random octect stream - of hLen bytes long (The value hLen is specified as an argument to pbkdf2 - and should be constant for any given prf function.) which is output in the buffer - pointed to by randomPtr (the caller of this function is responsible for allocation - of the buffer). - The inputs to the pseudo random function are the first keyLen octets pointed - to by keyPtr and the first textLen octets pointed to by textPtr. - Both keyLen and textLen can have any nonzero value. - A good prf would be a HMAC-SHA-1 algorithm where the keyPtr octets serve as - HMAC's "key" and the textPtr octets serve as HMAC's "text". */ -typedef void (*PRF)(const uint8_t *keyPtr, size_t keyLen, - const uint8_t *textPtr, size_t textLen, - uint8_t *randomPtr); - -/* This function implements the PBKDF2 key derrivation algorithm described in - http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-5.html - The output is a derived key of dkLen bytes which is written to the buffer - pointed to by dkPtr. - The caller should ensure dkPtr is at least dkLen bytes long. - The Key is derived from passwordPtr (which is passwordLen bytes long) and from - saltPtr (which is saltLen bytes long). The algorithm used is desacribed in - PKCS #5 version 2.0 and iterationCount iterations are performed. - The argument prf is a pointer to a psuedo random number generator declared above. - It should write exactly hLen bytes into its output buffer each time it is called. - The argument tempBuffer should point to a buffer MAX (hLen, saltLen + 4) + 2 * hLen - bytes long. This buffer is used during the calculation for intermediate results. - Security Considerations: - The argument saltPtr should be a pointer to a buffer of at least 8 random bytes - (64 bits). Thus saltLen should be >= 8. - For each session a new salt should be generated. - The value of iterationCount should be at least 1000 (one thousand). - A good prf would be a HMAC-SHA-1 algorithm where the password serves as - HMAC's "key" and the data serves as HMAC's "text". */ -void pbkdf2 (PRF prf, size_t hLen, - const void *passwordPtr, size_t passwordLen, - const void *saltPtr, size_t saltLen, - size_t iterationCount, - void *dkPtr, size_t dkLen, - void *tempBuffer); - - -#ifdef __cplusplus -} -#endif - -#endif /* __PBKDF2__ */ diff --git a/sec/Security/vmdh.c b/sec/Security/vmdh.c deleted file mode 100644 index 65763233..00000000 --- a/sec/Security/vmdh.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * vmdh.c - * Security - * - * Created by Michael Brouwer on 11/7/06. - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. - * - */ - -/*! - @header vmdh - The functions provided in vmdh.h implement the crypto exchange required - for a Diffie-Hellman voicemail exchange. -*/ - - -#include "vmdh.h" -#include -#include -#include -#include -#include - -vmdh_t vmdh_create(uint32_t g, const uint8_t *p, size_t p_len, - const uint8_t *recip, size_t recip_len) { - SecDHContext dh; - if (SecDHCreate(g, p, p_len, 0/*l*/, recip, recip_len, &dh)) - return NULL; - return (vmdh_t)dh; -} - -bool vmdh_generate_key(vmdh_t vmdh, uint8_t *pub_key, size_t *pub_key_len) { - return !SecDHGenerateKeypair((SecDHContext)vmdh, pub_key, pub_key_len); -} - -bool vmdh_encrypt_password(vmdh_t vmdh, - const uint8_t *pub_key, size_t pub_key_len, - const uint8_t *pw, size_t pw_len, uint8_t *encpw, size_t *encpw_len) { - uint8_t aes_key[kCCKeySizeAES128]; - size_t aes_key_len = kCCKeySizeAES128; - - if (SecDHComputeKey((SecDHContext)vmdh, pub_key, pub_key_len, - aes_key, &aes_key_len)) { - return false; - } - - /* Use the first 16 bytes in aes_key as an AES key. */ - if (CCCrypt(kCCEncrypt, kCCAlgorithmAES128, - kCCOptionPKCS7Padding, aes_key, kCCKeySizeAES128, NULL, - pw, pw_len, encpw, *encpw_len, encpw_len)) { - return false; - } - - /* Zero out key material. */ - bzero(aes_key, kCCKeySizeAES128); - - return true; -} - -void vmdh_destroy(vmdh_t vmdh) { - return SecDHDestroy((SecDHContext)vmdh); -} diff --git a/sec/Security/vmdh.h b/sec/Security/vmdh.h deleted file mode 100644 index 9b588391..00000000 --- a/sec/Security/vmdh.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * vmdh.h - * Security - * - * Created by Michael Brouwer on 11/7/06. - * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. - * - */ - -/*! - @header vmdh - The functions provided in vmdh.h implement the crypto exchange required - for a Diffie-Hellman voicemail exchange. -*/ - -#ifndef _SECURITY_VMDH_H_ -#define _SECURITY_VMDH_H_ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct vmdh *vmdh_t; - -/* Return a newly allocated vmdh object given g, p and the recip of p recip. - The recip and recip_len parameters are constant for a given p. They are - optional although providing them improves performance. - The caller should call vmdh_destroy once the returned handle is no longer - needed. */ -vmdh_t vmdh_create(uint32_t g, const uint8_t *p, size_t p_len, - const uint8_t *recip, size_t recip_len); - -/* Generate a dh private/public keypair and return the public key in pub_key. - on input *pub_key_len is the number of bytes available in pub_key, on output - pub_key_len is the number of bytes actually in pub_key. Returns true on - success and false on failure. */ -bool vmdh_generate_key(vmdh_t vmdh, uint8_t *pub_key, size_t *pub_key_len); - -/* Given the length of a password return the size of the encrypted password. */ -#define vmdh_encpw_len(PWLEN) (((PWLEN) & ~0xf) + 16) - -/* Given a vmdh handle and the other parties public key pub_key (of - pub_key_len bytes long), encrypt the password given by pw of pw_len bytes - long and return it in encpw. On input *enc_pw contains the number of bytes - available in encpw, on output *encpw will contain the actual length of - encpw. */ -bool vmdh_encrypt_password(vmdh_t vmdh, - const uint8_t *pub_key, size_t pub_key_len, - const uint8_t *pw, size_t pw_len, uint8_t *encpw, size_t *encpw_len); - -/* Destroy a vmdh object created with vmdh_create(). */ -void vmdh_destroy(vmdh_t vmdh); - -#ifdef __cplusplus -} -#endif - -#endif /* _SECURITY_VMDH_H_ */ diff --git a/sec/SecurityTool/builtin_commands.h b/sec/SecurityTool/builtin_commands.h deleted file mode 100644 index 4973481c..00000000 --- a/sec/SecurityTool/builtin_commands.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// builtin_commands.h -// sec -// -// Created by Mitch Adler on 1/9/13. -// -// - -#include "SecurityTool/security_tool_commands.h" - -SECURITY_COMMAND("help", help, - "[command ...]", - "Show all commands. Or show usage for a command.") - -SECURITY_COMMAND("digest", command_digest, - "algo file(s)...\n" - "Where algo is one of:\n" - " sha1\n" - " sha256\n" - " sha512\n", - "Calculate a digest over the given file(s).") diff --git a/sec/SecurityTool/digest_calc.c b/sec/SecurityTool/digest_calc.c deleted file mode 100644 index 85710a34..00000000 --- a/sec/SecurityTool/digest_calc.c +++ /dev/null @@ -1,78 +0,0 @@ -// -// digest_calc.c -// Digest calculation command for SecurityTool -// -// Created by John Kelley on 4/27/11. -// Copyright 2011 Apple, Inc. All rights reserved. -// - -#include "builtin_commands.h" - -#include -#include - -#include - -#include -#include - -extern int command_digest(int argc, char * const *argv) -{ - int result = 1; - uint8_t *data = NULL; - size_t data_len; - const struct ccdigest_info *di; - unsigned char *digest = NULL; - unsigned long i,j; - - if (argc < 3) - return 2; /* Return 2 triggers usage message. */ - - if (strcasecmp("sha1", argv[1]) == 0) - { - //printf("Calculating sha1\n"); - di = ccsha1_di(); - } - else if (strcasecmp("sha256", argv[1]) == 0) - { - //printf("Calculating sha256\n"); - di = ccsha256_di(); - } - else if (strcasecmp("sha512", argv[1]) == 0) - { - //printf("Calculating sha256\n"); - di = ccsha512_di(); - } - else - return 2; /* Return 2 triggers usage message. */ - - digest = malloc(di->output_size); - if (!digest) - goto exit; - - for (i = 2; i < (unsigned int)argc; ++i) - { - printf("%s(%s)= ", argv[1], argv[i]); - if (read_file( argv[i], &data, &data_len) != 0 || !data) - { - printf("error reading file\n"); - continue; - } - ccdigest(di, data_len, data, digest); - - for (j = 0; j < di->output_size; j++) - printf("%02x", digest[j]); - printf("\n"); - free(data); - data = NULL; - } - result = 0; - -exit: - if(data) - free(data); - if (digest) - free(digest); - - return result; -} diff --git a/sec/SecurityTool/leaks.c b/sec/SecurityTool/leaks.c deleted file mode 100644 index 957ce9dd..00000000 --- a/sec/SecurityTool/leaks.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2003-2004,2006-2007 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@ - * - * leaks.c - */ - -#include "leaks.h" - -#include -#include -#include -#include -#include -#include - -int -leaks(int argc, char *const *argv) -{ - int result = 1; - pid_t child; - pid_t parent = getpid(); - - child = fork(); - switch (child) - { - case -1: - /* Fork failed we're hosed. */ - fprintf(stderr, "fork: %s", strerror(errno)); - break; - case 0: - { - /* child. */ - char **argvec = (char **)malloc((argc + 2) * sizeof(char *)); - char pidstr[8]; - int ix; - - sprintf(pidstr, "%d", parent); - argvec[0] = "/usr/bin/leaks"; - for (ix = 1; ix < argc; ++ix) - argvec[ix] = argv[ix]; - argvec[ix] = pidstr; - argvec[ix + 1] = NULL; - - execv(argvec[0], argvec); - fprintf(stderr, "exec: %s", strerror(errno)); - _exit(1); - break; - } - default: - { - /* Parent. */ - int status = 0; - for (;;) - { - /* Wait for the child to exit. */ - pid_t waited_pid = waitpid(child, &status, 0); - if (waited_pid == -1) - { - int error = errno; - /* Keep going if we get interupted but bail out on any - other error. */ - if (error == EINTR) - continue; - - fprintf(stderr, "waitpid %d: %s", status, strerror(errno)); - break; - } - - if (WIFEXITED(status)) - { - if (WEXITSTATUS(status)) - { - /* Force usage message. */ - result = 2; - fprintf(stderr, "leaks exited: %d", result); - } - break; - } - else if (WIFSIGNALED(status)) - { - fprintf(stderr, "leaks terminated by signal: %d", WTERMSIG(status)); - break; - } - } - break; - } - } - - return result; -} diff --git a/sec/SecurityTool/leaks.h b/sec/SecurityTool/leaks.h deleted file mode 100644 index df6ac716..00000000 --- a/sec/SecurityTool/leaks.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2003-2004,2006-2007 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@ - * - * leaks.h - */ - -#ifndef _LEAKS_H_ -#define _LEAKS_H_ - -#include - -__BEGIN_DECLS - -int leaks(int argc, char *const *argv); - -__END_DECLS - -#endif /* _LEAKS_H_ */ diff --git a/sec/SecurityTool/tool_errors.h b/sec/SecurityTool/tool_errors.h deleted file mode 100644 index 7b6ee3c5..00000000 --- a/sec/SecurityTool/tool_errors.h +++ /dev/null @@ -1,60 +0,0 @@ -// -// tool_errors.h -// sec -// -// Created by Mitch Adler on 1/9/13. -// -// - -// -// These functions should be deprectaed! -// Try to find a better way instead of using them. -// - -#ifndef _TOOL_ERRORS_H_ -#define _TOOL_ERRORS_H_ - -#include -#include -#include "SecurityTool/SecurityTool.h" - -static inline const char * -sec_errstr(int err) -{ - const char *errString; - static char buffer[12]; - - sprintf(buffer, "%d", err); - errString = buffer; -#if 0 - if (IS_SEC_ERROR(err)) - errString = SECErrorString(err); - else - errString = cssmErrorString(err); -#endif - return errString; -} - -static inline void -sec_error(const char *msg, ...) -{ - va_list args; - - fprintf(stderr, "%s: ", prog_name); - - va_start(args, msg); - vfprintf(stderr, msg, args); - va_end(args); - - fprintf(stderr, "\n"); -} - -static inline void -sec_perror(const char *msg, int err) -{ - sec_error("%s: %s", msg, sec_errstr(err)); -} - - - -#endif diff --git a/sec/config/base.xcconfig b/sec/config/base.xcconfig deleted file mode 100644 index 7e8251af..00000000 --- a/sec/config/base.xcconfig +++ /dev/null @@ -1,47 +0,0 @@ -CODE_SIGN_IDENTITY = - -GCC_VERSION = com.apple.compilers.llvm.clang.1_0 -DEBUG_INFORMATION_FORMAT = dwarf-with-dsym -CURRENT_PROJECT_VERSION = $(RC_ProjectSourceVersion) -VERSIONING_SYSTEM = apple-generic -DEAD_CODE_STRIPPING = YES - -ARCHS = $(ARCHS_STANDARD_32_64_BIT) - -GCC_WARN_CHECK_SWITCH_STATEMENTS = YES -GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO // should be YES at some point -CLANG_WARN_EMPTY_BODY = YES -GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES -GCC_WARN_SHADOW = NO // should be yes -CLANG_WARN_CONSTANT_CONVERSION = YES -GCC_WARN_64_TO_32_BIT_CONVERSION = YES -CLANG_WARN_ENUM_CONVERSION = YES -CLANG_WARN_INT_CONVERSION = NO// should be yes -CLANG_WARN_IMPLICIT_SIGN_CONVERSION = NO // should be yes -GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES -GCC_WARN_ABOUT_RETURN_TYPE = YES -GCC_WARN_MISSING_PARENTHESES = YES -GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = NO // should be yes -GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES -GCC_WARN_ABOUT_MISSING_NEWLINE = YES -//WARNING_CFLAGS -GCC_WARN_ABOUT_POINTER_SIGNEDNESS = YES -GCC_WARN_SIGN_COMPARE = YES -CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = NO // should be yes -GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES -GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES -GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES -GCC_WARN_UNINITIALIZED_AUTOS = YES -GCC_WARN_UNKNOWN_PRAGMAS = YES -GCC_WARN_UNUSED_FUNCTION = YES -GCC_WARN_UNUSED_LABEL = YES -GCC_WARN_UNUSED_PARAMETER = NO // should be yes -GCC_WARN_UNUSED_VALUE = YES -GCC_WARN_UNUSED_VARIABLE = YES - -// No executables are made in sec, it can't know how -// Therefore we shouldn't strip anyting -// if somehow we decide to, the default is debuggable. - -COPY_PHASE_STRIP = NO -STRIP_STYLE = debugging -STRIP_INSTALLED_PRODUCT = NO diff --git a/sec/config/lib.xcconfig b/sec/config/lib.xcconfig deleted file mode 100644 index d77f9142..00000000 --- a/sec/config/lib.xcconfig +++ /dev/null @@ -1,32 +0,0 @@ -PRODUCT_NAME = $(TARGET_NAME) -EXECUTABLE_PREFIX = - -CODE_SIGN_IDENTITY = - -INDIGO_INSTALL_PATH_PREFIX[sdk=iphonesimulator*] = $(SDKROOT) - -HEADER_SEARCH_PATHS = $(inherited) $(PROJECT_DIR) $(PROJECT_DIR)/../utilities $(PROJECT_DIR)/ipc $(PROJECT_DIR)/../sectask $(PROJECT_DIR)/../libsecurity_asn1 $(PROJECT_DIR)/../libsecurity_ssl $(PROJECT_DIR)/../libsecurity_smime $(PROJECT_DIR)/../regressions $(PROJECT_DIR)/SOSCircle $(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include - -HEADER_SEARCH_PATHS[sdk=macosx*] = $(inherited) $(PROJECT_DIR)/../libsecurity_keychain/libDER $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers - -HEADER_SEARCH_PATHS[sdk=iphone*] = $(inherited) $(PROJECT_DIR)/../libDER - -FRAMEWORK_SEARCH_PATHS[sdk=macosx*] = $(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks - -COPY_PHASE_STRIP = NO -SKIP_INSTALL = YES -COPY_PHASE_STRIP = NO - -ALWAYS_SEARCH_USER_PATHS = YES - -GCC_C_LANGUAGE_STANDARD = gnu99 - -HEADERMAP_INCLUDES_FRAMEWORK_ENTRIES_FOR_ALL_PRODUCT_TYPES = NO - -WARNING_CFLAGS = $(inherited) -Wmost -Wno-four-char-constants -Wno-unknown-pragmas - -GCC_SYMBOLS_PRIVATE_EXTERN = NO - -SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator - -GCC_PREPROCESSOR_DEFINITIONS[sdk=iphonesimulator*] = $(inherited) INDIGO=1 diff --git a/sec/ipc/com.apple.secd.plist b/sec/ipc/com.apple.secd.plist deleted file mode 100644 index ce7496f8..00000000 --- a/sec/ipc/com.apple.secd.plist +++ /dev/null @@ -1,47 +0,0 @@ - - - - - LimitLoadToSessionType - Background - POSIXSpawnType - Interactive - LaunchEvents - - com.apple.notifyd.matching - - com.apple.security.cloudkeychainproxy.kvstorechange3 - - Notification - com.apple.security.cloudkeychainproxy.kvstorechange3 - - - - Label - com.apple.secd - MachServices - - com.apple.secd - - com.apple.securityd.xpc - - - OnDemand - - ProgramArguments - - /usr/libexec/secd - - ServiceIPC - - Umask - 54 - EnvironmentVariables - - DEBUGSCOPE - none - WAIT4DEBUGGER - NO - - - diff --git a/sec/ipc/com.apple.securityd.plist b/sec/ipc/com.apple.securityd.plist deleted file mode 100644 index 91c21620..00000000 --- a/sec/ipc/com.apple.securityd.plist +++ /dev/null @@ -1,38 +0,0 @@ - - - - - EnableTransactions - - EnvironmentVariables - - DEBUGSCOPE - none - WAIT4DEBUGGER - NO - - GroupName - _securityd - Label - com.apple.securityd - MachServices - - com.apple.securityd - - - OnDemand - - ProgramArguments - - /usr/libexec/securityd - - ServiceIPC - - Umask - 54 - UserName - _securityd - POSIXSpawnType - Interactive - - diff --git a/sec/ipc/securityd_client.h b/sec/ipc/securityd_client.h deleted file mode 100755 index 216dd06a..00000000 --- a/sec/ipc/securityd_client.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2007-2009,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@ - */ -#ifndef _SECURITYD_CLIENT_H_ -#define _SECURITYD_CLIENT_H_ - -#include - -# include -#ifndef MINIMIZE_INCLUDES -# include -# include -#else -typedef struct __SecTrustStore *SecTrustStoreRef; -# ifndef _SECURITY_SECCERTIFICATE_H_ -typedef struct __SecCertificate *SecCertificateRef; -# endif // _SECURITY_SECCERTIFICATE_H_ -# ifndef _SECURITY_SECCERTIFICATEPATH_H_ -typedef struct SecCertificatePath *SecCertificatePathRef; -# endif // _SECURITY_SECCERTIFICATEPATH_H_ -#endif // MINIMIZE_INCLUDES - -#include -#include -#include - -#include - -#include -#include - -// TODO: This should be in client of XPC code locations... -#if SECITEM_SHIM_OSX -#define kSecuritydXPCServiceName "com.apple.securityd.xpc" -#else -#define kSecuritydXPCServiceName "com.apple.securityd" -#endif // *** END SECITEM_SHIM_OSX *** - -// -// MARK: XPC Information. -// - -extern CFStringRef sSecXPCErrorDomain; - -extern const char *kSecXPCKeyOperation; -extern const char *kSecXPCKeyResult; -extern const char *kSecXPCKeyError; -extern const char *kSecXPCKeyPeerInfos; -extern const char *kSecXPCKeyUserLabel; -extern const char *kSecXPCKeyBackup; -extern const char *kSecXPCKeyKeybag; -extern const char *kSecXPCKeyUserPassword; - -// -// MARK: Dispatch macros -// - -#define SECURITYD_XPC(sdp, wrapper, ...) ((gSecurityd && gSecurityd->sdp) ? gSecurityd->sdp(__VA_ARGS__) : wrapper(sdp ## _id, __VA_ARGS__)) - -// -// MARK: Object to XPC format conversion. -// - - -// -// MARK: XPC Interfaces -// - -extern const char *kSecXPCKeyOperation; -extern const char *kSecXPCKeyResult; -extern const char *kSecXPCKeyError; -extern const char *kSecXPCKeyPeerInfos; -extern const char *kSecXPCKeyUserLabel; -extern const char *kSecXPCKeyUserPassword; -extern const char *kSecXPCLimitInMinutes; -extern const char *kSecXPCKeyQuery; -extern const char *kSecXPCKeyAttributesToUpdate; -extern const char *kSecXPCKeyDomain; -extern const char *kSecXPCKeyDigest; -extern const char *kSecXPCKeyCertificate; -extern const char *kSecXPCKeySettings; - -// -// MARK: Mach port request IDs -// -enum SecXPCOperation { - sec_item_add_id, - sec_item_copy_matching_id, - sec_item_update_id, - sec_item_delete_id, - // trust_store_for_domain -- NOT an ipc - sec_trust_store_contains_id, - sec_trust_store_set_trust_settings_id, - sec_trust_store_remove_certificate_id, - // remove_all -- NOT an ipc - sec_delete_all_id, - sec_trust_evaluate_id, - sec_keychain_backup_id, - sec_keychain_restore_id, - sec_keychain_sync_update_id, - sec_keychain_backup_syncable_id, - sec_keychain_restore_syncable_id, - sec_ota_pki_asset_version_id, - kSecXPCOpOTAPKIGetNewAsset, - kSecXPCOpOTAGetEscrowCertificates, - kSecXPCOpProcessUnlockNotification, - kSecXPCOpProcessSyncWithAllPeers, - // any process using an operation below here is required to have entitlement keychain-cloud-circle - kSecXPCOpTryUserCredentials, - kSecXPCOpSetUserCredentials, - kSecXPCOpCanAuthenticate, - kSecXPCOpPurgeUserCredentials, - kSecXPCOpDeviceInCircle, - kSecXPCOpRequestToJoin, - kSecXPCOpRequestToJoinAfterRestore, - kSecXPCOpResetToOffering, - kSecXPCOpResetToEmpty, - kSecXPCOpRemoveThisDeviceFromCircle, - kSecXPCOpBailFromCircle, - kSecXPCOpAcceptApplicants, - kSecXPCOpRejectApplicants, - kSecXPCOpCopyApplicantPeerInfo, - kSecXPCOpCopyPeerPeerInfo, - kSecXPCOpCopyConcurringPeerPeerInfo, - kSecXPCOpGetLastDepartureReason, - kSecXPCOpCopyIncompatibilityInfo -}; - - - -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); - SecTrustStoreRef (*sec_trust_store_for_domain)(CFStringRef domainName, CFErrorRef* error); // TODO: remove, has no msg id - bool (*sec_trust_store_contains)(SecTrustStoreRef ts, CFDataRef digest, bool *contains, CFErrorRef* error); - bool (*sec_trust_store_set_trust_settings)(SecTrustStoreRef ts, SecCertificateRef certificate, CFTypeRef trustSettingsDictOrArray, CFErrorRef* error); - bool (*sec_trust_store_remove_certificate)(SecTrustStoreRef ts, CFDataRef digest, CFErrorRef* error); - 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, 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); - bool (*sec_keychain_sync_update)(CFDictionaryRef update, 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); - int (*sec_ota_pki_asset_version)(CFErrorRef* error); - bool (*soscc_TryUserCredentials)(CFStringRef user_label, CFDataRef user_password, CFErrorRef *error); - bool (*soscc_SetUserCredentials)(CFStringRef user_label, CFDataRef user_password, CFErrorRef *error); - bool (*soscc_CanAuthenticate)(CFErrorRef *error); - bool (*soscc_PurgeUserCredentials)(CFErrorRef *error); - SOSCCStatus (*soscc_ThisDeviceIsInCircle)(CFErrorRef* error); - bool (*soscc_RequestToJoinCircle)(CFErrorRef* error); - bool (*soscc_RequestToJoinCircleAfterRestore)(CFErrorRef* error); - bool (*soscc_ResetToOffering)(CFErrorRef* error); - bool (*soscc_ResetToEmpty)(CFErrorRef* error); - bool (*soscc_RemoveThisDeviceFromCircle)(CFErrorRef* error); - bool (*soscc_BailFromCircle)(uint64_t limit_in_seconds, CFErrorRef* error); - bool (*soscc_AcceptApplicants)(CFArrayRef applicants, CFErrorRef* error); - bool (*soscc_RejectApplicants)(CFArrayRef applicants, CFErrorRef* error); - CFArrayRef (*soscc_CopyApplicantPeerInfo)(CFErrorRef* error); - CFArrayRef (*soscc_CopyPeerInfo)(CFErrorRef* error); - CFArrayRef (*soscc_CopyConcurringPeerInfo)(CFErrorRef* error); - CFStringRef (*soscc_CopyIncompatibilityInfo)(CFErrorRef* error); - enum DepartureReason (*soscc_GetLastDepartureReason)(CFErrorRef* error); - CFArrayRef (*ota_CopyEscrowCertificates)(CFErrorRef* error); - int (*sec_ota_pki_get_new_asset)(CFErrorRef* error); - SyncWithAllPeersReason (*soscc_ProcessSyncWithAllPeers)(CFErrorRef* error); -}; - -extern struct securityd *gSecurityd; - -CFArrayRef SecAccessGroupsGetCurrent(void); - -// TODO Rename me -CFStringRef SOSCCGetOperationDescription(enum SecXPCOperation op); -xpc_object_t securityd_message_with_reply_sync(xpc_object_t message, CFErrorRef *error); -xpc_object_t securityd_create_message(enum SecXPCOperation op, CFErrorRef *error); -bool securityd_message_no_error(xpc_object_t message, CFErrorRef *error); - - -bool securityd_send_sync_and_do(enum SecXPCOperation op, CFErrorRef *error, - bool (^add_to_message)(xpc_object_t message, CFErrorRef* error), - bool (^handle_response)(xpc_object_t response, CFErrorRef* error)); - -// For testing only, never call this in a threaded program! -void SecServerSetMachServiceName(const char *name); - -#endif /* _SECURITYD_CLIENT_H_ */ diff --git a/sec/ipc/server.c b/sec/ipc/server.c deleted file mode 100644 index 8e03f3c9..00000000 --- a/sec/ipc/server.c +++ /dev/null @@ -1,769 +0,0 @@ -/* - * Copyright (c) 2007-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 -#include - -#include -#include - -#include -#include -#include /* For SecItemDeleteAll */ -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "securityd_client.h" - -#include -#include -#include -#include -#include - -#include -#include -#include - -// TODO: Make this include work on both platforms. -#if TARGET_OS_EMBEDDED -#include -#else -#define kSecEntitlementKeychainSyncUpdates CFSTR("keychain-sync-updates") -#define kSecEntitlementKeychainCloudCircle CFSTR("keychain-cloud-circle") -/* defines from */ -/* defines from */ -#if TARGET_OS_EMBEDDED -#define kSecEntitlementApplicationIdentifier CFSTR("application-identifier") -#else -#define kSecEntitlementApplicationIdentifier CFSTR("com.apple.application-identifier") -#endif -#define kSecEntitlementGetTaskAllow CFSTR("get-task-allow") -#define kSecEntitlementKeychainAccessGroups CFSTR("keychain-access-groups") -#define kSecEntitlementModifyAnchorCertificates CFSTR("modify-anchor-certificates") -#define kSecEntitlementDebugApplications CFSTR("com.apple.springboard.debugapplications") -#define kSecEntitlementOpenSensitiveURL CFSTR("com.apple.springboard.opensensitiveurl") -#define kSecEntitlementWipeDevice CFSTR("com.apple.springboard.wipedevice") -#define kSecEntitlementRemoteNotificationConfigure CFSTR("com.apple.remotenotification.configure") -#define kSecEntitlementMigrateKeychain CFSTR("migrate-keychain") -#define kSecEntitlementRestoreKeychain CFSTR("restore-keychain") -#define kSecEntitlementSyncKeychain CFSTR("sync-keychain") -#endif - -#include - -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -// For SecError -#include - -#include - - -#if TARGET_IPHONE_SIMULATOR -#define CHECK_ENTITLEMENTS 0 -#else -#define CHECK_ENTITLEMENTS 1 -#endif - -#if CHECK_ENTITLEMENTS -static CFStringRef SecTaskCopyStringForEntitlement(SecTaskRef task, - CFStringRef entitlement) -{ - CFStringRef value = (CFStringRef)SecTaskCopyValueForEntitlement(task, - entitlement, NULL); - if (value && CFGetTypeID(value) != CFStringGetTypeID()) { - CFRelease(value); - value = NULL; - } - - return value; -} - -static CFArrayRef SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task, - CFStringRef entitlement) -{ - CFArrayRef value = (CFArrayRef)SecTaskCopyValueForEntitlement(task, - entitlement, NULL); - if (value) { - if (CFGetTypeID(value) == CFArrayGetTypeID()) { - CFIndex ix, count = CFArrayGetCount(value); - for (ix = 0; ix < count; ++ix) { - CFStringRef string = (CFStringRef)CFArrayGetValueAtIndex(value, ix); - if (CFGetTypeID(string) != CFStringGetTypeID()) { - CFRelease(value); - value = NULL; - break; - } - } - } else { - CFRelease(value); - value = NULL; - } - } - - return value; -} - -#endif /* CHECK_ENTITLEMENTS */ - -static CFArrayRef SecTaskCopyAccessGroups(SecTaskRef task) { -#if CHECK_ENTITLEMENTS - CFStringRef appID = SecTaskCopyStringForEntitlement(task, - kSecEntitlementApplicationIdentifier); - CFArrayRef groups = SecTaskCopyArrayOfStringsForEntitlement(task, - kSecEntitlementKeychainAccessGroups); - if (appID) { - if (groups) { - CFMutableArrayRef nGroups = CFArrayCreateMutableCopy( - CFGetAllocator(groups), CFArrayGetCount(groups) + 1, groups); - CFArrayAppendValue(nGroups, appID); - CFRelease(groups); - groups = nGroups; - } else { - groups = CFArrayCreate(CFGetAllocator(task), - (const void **)&appID, 1, &kCFTypeArrayCallBacks); - } - CFRelease(appID); - } -#else - CFArrayRef groups = SecAccessGroupsGetCurrent(); - if (groups) - CFRetain(groups); -#endif - return groups; -} - -static bool SecTaskGetBooleanValueForEntitlement(SecTaskRef task, - CFStringRef entitlement) { -#if CHECK_ENTITLEMENTS - CFStringRef canModify = (CFStringRef)SecTaskCopyValueForEntitlement(task, - entitlement, NULL); - if (!canModify) - return false; - CFTypeID canModifyType = CFGetTypeID(canModify); - bool ok = (CFBooleanGetTypeID() == canModifyType) && CFBooleanGetValue((CFBooleanRef)canModify); - CFRelease(canModify); - return ok; -#else - return true; -#endif /* !CHECK_ENTITLEMENTS */ -} - -static void with_label_and_password(xpc_object_t message, void (^action)(CFStringRef label, CFDataRef password)) { - const char *label_utf8 = xpc_dictionary_get_string(message, kSecXPCKeyUserLabel); - - size_t password_length = 0; - const void *password_data = xpc_dictionary_get_data(message, kSecXPCKeyUserPassword, &password_length); - - CFDataRef user_password = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, password_data, password_length, kCFAllocatorNull); - CFStringRef user_label = CFStringCreateWithCString(kCFAllocatorDefault, label_utf8, kCFStringEncodingUTF8); - - action(user_label, user_password); - - CFReleaseNull(user_password); - CFReleaseNull(user_label); -} - -static bool SecXPCDictionarySetChainOptional(xpc_object_t message, const char *key, SecCertificatePathRef path, CFErrorRef *error) { - if (!path) - return true; - xpc_object_t xpc_chain = SecCertificatePathCopyXPCArray(path, error); - if (!xpc_chain) - return false; - - xpc_dictionary_set_value(message, key, xpc_chain); - xpc_release(xpc_chain); - return true; -} - -static SecCertificateRef SecXPCDictionaryCopyCertificate(xpc_object_t message, const char *key, CFErrorRef *error) { - size_t length = 0; - const void *bytes = xpc_dictionary_get_data(message, key, &length); - if (bytes) { - SecCertificateRef certificate = SecCertificateCreateWithBytes(kCFAllocatorDefault, bytes, length); - if (certificate) - return certificate; - SecError(errSecDecode, error, CFSTR("object for key %s failed to create certificate from data"), key); - } else { - SecError(errSecParam, error, CFSTR("object for key %s missing"), key); - } - return NULL; -} - -static bool SecXPCDictionaryCopyCertificates(xpc_object_t message, const char *key, CFArrayRef *certificates, CFErrorRef *error) { - xpc_object_t xpc_certificates = xpc_dictionary_get_value(message, key); - if (!xpc_certificates) - return SecError(errSecAllocate, error, CFSTR("no certs for key %s"), key); - *certificates = SecCertificateXPCArrayCopyArray(xpc_certificates, error); - return *certificates; -} - -static bool SecXPCDictionaryCopyCertificatesOptional(xpc_object_t message, const char *key, CFArrayRef *certificates, CFErrorRef *error) { - xpc_object_t xpc_certificates = xpc_dictionary_get_value(message, key); - if (!xpc_certificates) { - *certificates = NULL; - return true; - } - *certificates = SecCertificateXPCArrayCopyArray(xpc_certificates, error); - return *certificates; -} - -static bool SecXPCDictionaryCopyPoliciesOptional(xpc_object_t message, const char *key, CFArrayRef *policies, CFErrorRef *error) { - xpc_object_t xpc_policies = xpc_dictionary_get_value(message, key); - if (!xpc_policies) { - if (policies) - *policies = NULL; - return true; - } - *policies = SecPolicyXPCArrayCopyArray(xpc_policies, error); - return *policies != NULL; -} - -static SecTrustStoreRef SecXPCDictionaryGetTrustStore(xpc_object_t message, const char *key, CFErrorRef *error) { - SecTrustStoreRef ts = NULL; - CFStringRef domain = SecXPCDictionaryCopyString(message, key, error); - if (domain) { - ts = SecTrustStoreForDomainName(domain, error); - CFRelease(domain); - } - return ts; -} - -static bool SecXPCDictionaryGetDouble(xpc_object_t message, const char *key, double *pvalue, CFErrorRef *error) { - *pvalue = xpc_dictionary_get_double(message, key); - if (*pvalue == NAN) { - return SecError(errSecParam, error, CFSTR("object for key %s bad double"), key); - } - return true; -} - -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; - CFArrayRef accessGroups = NULL; - - secdebug("serverxpc", "entering"); - if (type == XPC_TYPE_DICTIONARY) { - // TODO: Find out what we're dispatching. - replyMessage = xpc_dictionary_create_reply(event); - - uint64_t operation = xpc_dictionary_get_uint64(event, kSecXPCKeyOperation); - secdebug("serverxpc", "operation: %@ (%" PRIu64 ")", SOSCCGetOperationDescription((enum SecXPCOperation)operation), operation); - - bool hasEntitlement; -#if 1 // CHECK_ENTITLEMENTS - audit_token_t auditToken = {}; - xpc_connection_get_audit_token(connection, &auditToken); - clientTask = SecTaskCreateWithAuditToken(kCFAllocatorDefault, auditToken); - accessGroups = SecTaskCopyAccessGroups(clientTask); - - // operations before kSecXPCOpTryUserCredentials don't need this entitlement. - hasEntitlement = (operation < kSecXPCOpTryUserCredentials) || - (clientTask && SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementKeychainCloudCircle)); -#else - clientTask = NULL; - hasEntitlement = true; -#endif - - // Per Disable the entitlement check for "keychain-cloud-circle" - // we disable entitlement enforcement. However, we still log so we know who needs the entitlement - - if (!hasEntitlement) { - CFErrorRef entitlementError = NULL; - SecError(errSecMissingEntitlement, &entitlementError, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation)operation), clientTask, kSecEntitlementKeychainCloudCircle); - secnotice("serverxpc", "MissingEntitlement: %@", entitlementError); - CFReleaseSafe(entitlementError); - } - - if (true) { - switch (operation) - { - case sec_item_add_id: - { - CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); - if (query) { - CFTypeRef result = NULL; - if (_SecItemAdd(query, accessGroups, &result, &error) && result) { - SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); - CFRelease(result); - } - CFRelease(query); - } - break; - } - case sec_item_copy_matching_id: - { - CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); - if (query) { - CFTypeRef result = NULL; - if (_SecItemCopyMatching(query, accessGroups, &result, &error) && result) { - SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); - CFRelease(result); - } - CFRelease(query); - } - break; - } - case sec_item_update_id: - { - CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); - if (query) { - CFDictionaryRef attributesToUpdate = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyAttributesToUpdate, &error); - if (attributesToUpdate) { - bool result = _SecItemUpdate(query, attributesToUpdate, accessGroups, &error); - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); - CFRelease(attributesToUpdate); - } - CFRelease(query); - } - break; - } - case sec_item_delete_id: - { - CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); - if (query) { - bool result = _SecItemDelete(query, accessGroups, &error); - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); - CFRelease(query); - } - break; - } - case sec_trust_store_contains_id: - { - SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error); - if (ts) { - CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, &error); - if (digest) { - bool contains; - if (SecTrustStoreContainsCertificateWithDigest(ts, digest, &contains, &error)) - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, contains); - CFRelease(digest); - } - } - break; - } - case sec_trust_store_set_trust_settings_id: - { - SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error); - if (ts) { - SecCertificateRef certificate = SecXPCDictionaryCopyCertificate(event, kSecXPCKeyCertificate, &error); - if (certificate) { - CFTypeRef trustSettingsDictOrArray = NULL; - if (SecXPCDictionaryCopyPListOptional(event, kSecXPCKeySettings, &trustSettingsDictOrArray, &error)) { - bool result = _SecTrustStoreSetTrustSettings(ts, certificate, trustSettingsDictOrArray, &error); - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); - CFReleaseSafe(trustSettingsDictOrArray); - } - CFRelease(certificate); - } - } - break; - } - case sec_trust_store_remove_certificate_id: - { - SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error); - if (ts) { - CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, &error); - if (digest) { - bool result = SecTrustStoreRemoveCertificateWithDigest(ts, digest, &error); - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); - CFRelease(digest); - } - } - break; - } - case sec_delete_all_id: - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, _SecItemDeleteAll(&error)); - break; - case sec_trust_evaluate_id: - { - CFArrayRef certificates = NULL, anchors = NULL, policies = NULL; - bool anchorsOnly = xpc_dictionary_get_bool(event, kSecTrustAnchorsOnlyKey); - double verifyTime; - if (SecXPCDictionaryCopyCertificates(event, kSecTrustCertificatesKey, &certificates, &error) && - SecXPCDictionaryCopyCertificatesOptional(event, kSecTrustAnchorsKey, &anchors, &error) && - SecXPCDictionaryCopyPoliciesOptional(event, kSecTrustPoliciesKey, &policies, &error) && - 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); - - // Clear replyMessage so we don't send a synchronous reply. - xpc_object_t asyncReply = replyMessage; - replyMessage = NULL; - - SecTrustServerEvaluateBlock(certificates, anchors, anchorsOnly, policies, verifyTime, accessGroups, ^(SecTrustResultType tr, CFArrayRef details, CFDictionaryRef info, SecCertificatePathRef chain, CFErrorRef replyError) { - // Send back reply now - if (replyError) { - CFRetain(replyError); - } else { - xpc_dictionary_set_int64(asyncReply, kSecTrustResultKey, tr); - SecXPCDictionarySetPListOptional(asyncReply, kSecTrustDetailsKey, details, &replyError) && - SecXPCDictionarySetPListOptional(asyncReply, kSecTrustInfoKey, info, &replyError) && - SecXPCDictionarySetChainOptional(asyncReply, kSecTrustChainKey, chain, &replyError); - } - if (replyError) { - secdebug("ipc", "%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyError); - xpc_object_t xpcReplyError = SecCreateXPCObjectWithCFError(replyError); - if (xpcReplyError) { - xpc_dictionary_set_value(asyncReply, kSecXPCKeyError, xpcReplyError); - xpc_release(xpcReplyError); - } - CFRelease(replyError); - } else { - secdebug("ipc", "%@ %@ reponding %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), asyncReply); - } - - xpc_connection_send_message(connection, asyncReply); - xpc_release(asyncReply); - xpc_release(connection); - CFReleaseSafe(clientTask); - }); - } - CFReleaseSafe(policies); - CFReleaseSafe(anchors); - CFReleaseSafe(certificates); - break; - } - case sec_keychain_backup_id: - { - CFDataRef keybag = NULL, passcode = NULL; - if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyKeybag, &keybag, &error)) { - if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) { - CFDataRef backup = _SecServerKeychainBackup(keybag, passcode, &error); - if (backup) { - SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, backup, &error); - CFRelease(backup); - } - CFReleaseSafe(passcode); - } - CFReleaseSafe(keybag); - } - break; - } - case sec_keychain_restore_id: - { - CFDataRef 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); - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); - CFReleaseSafe(passcode); - } - CFRelease(keybag); - } - CFRelease(backup); - } - break; - } - case sec_keychain_sync_update_id: - { - CFDictionaryRef updates = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); - if (updates) { - bool result = _SecServerKeychainSyncUpdate(updates, &error); - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); - CFRelease(updates); - } - break; - } - case sec_keychain_backup_syncable_id: - { - CFDictionaryRef oldbackup = NULL; - if (SecXPCDictionaryCopyDictionaryOptional(event, kSecXPCKeyBackup, &oldbackup, &error)) { - CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error); - if (keybag) { - CFDataRef passcode = NULL; - if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) { - CFDictionaryRef newbackup = _SecServerBackupSyncable(oldbackup, keybag, passcode, &error); - if (newbackup) { - SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, newbackup, &error); - CFRelease(newbackup); - } - CFReleaseSafe(passcode); - } - CFRelease(keybag); - } - CFReleaseSafe(oldbackup); - } - break; - } - case sec_keychain_restore_syncable_id: - { - CFDictionaryRef backup = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyBackup, &error); - if (backup) { - CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error); - if (keybag) { - CFDataRef passcode = NULL; - if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) { - bool result = _SecServerRestoreSyncable(backup, keybag, passcode, &error); - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); - CFReleaseSafe(passcode); - } - CFRelease(keybag); - } - CFRelease(backup); - } - break; - } - case sec_ota_pki_asset_version_id: - xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, - SecOTAPKIGetCurrentAssetVersion(&error)); - break; - case kSecXPCOpTryUserCredentials: - with_label_and_password(event, ^(CFStringRef label, CFDataRef password) { - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, - SOSCCTryUserCredentials_Server(label, password, &error)); - }); - break; - case kSecXPCOpSetUserCredentials: - with_label_and_password(event, ^(CFStringRef label, CFDataRef password) { - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, - SOSCCSetUserCredentials_Server(label, password, &error)); - }); - break; - case kSecXPCOpCanAuthenticate: - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, - SOSCCCanAuthenticate_Server(&error)); - break; - case kSecXPCOpPurgeUserCredentials: - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, - SOSCCPurgeUserCredentials_Server(&error)); - break; - case kSecXPCOpDeviceInCircle: - xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, - SOSCCThisDeviceIsInCircle_Server(&error)); - break; - case kSecXPCOpRequestToJoin: - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, - SOSCCRequestToJoinCircle_Server(&error)); - break; - case kSecXPCOpRequestToJoinAfterRestore: - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, - SOSCCRequestToJoinCircleAfterRestore_Server(&error)); - break; - case kSecXPCOpResetToOffering: - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, - SOSCCResetToOffering_Server(&error)); - break; - case kSecXPCOpResetToEmpty: - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, - SOSCCResetToEmpty_Server(&error)); - break; - case kSecXPCOpRemoveThisDeviceFromCircle: - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, - SOSCCRemoveThisDeviceFromCircle_Server(&error)); - break; - case kSecXPCOpBailFromCircle: - { - uint64_t limit_in_seconds = xpc_dictionary_get_uint64(event, kSecXPCLimitInMinutes); - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, - SOSCCBailFromCircle_Server(limit_in_seconds, &error)); - } - break; - case kSecXPCOpAcceptApplicants: - { - xpc_object_t xapplicants = xpc_dictionary_get_value(event, kSecXPCKeyPeerInfos); - CFArrayRef applicants = CreateArrayOfPeerInfoWithXPCObject(xapplicants, &error); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants)); - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, - (applicants && SOSCCAcceptApplicants_Server(applicants, &error))); - CFReleaseSafe(applicants); - } - break; - case kSecXPCOpRejectApplicants: - { - xpc_object_t xapplicants = xpc_dictionary_get_value(event, kSecXPCKeyPeerInfos); - CFArrayRef applicants = CreateArrayOfPeerInfoWithXPCObject(xapplicants, &error); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants)); - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, - (applicants && SOSCCRejectApplicants_Server(applicants, &error))); - CFReleaseSafe(applicants); - } - break; - case kSecXPCOpCopyApplicantPeerInfo: - { - CFArrayRef array = SOSCCCopyApplicantPeerInfo_Server(&error); - if (array) { - xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error); - xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); - xpc_release(xpc_array); - } - CFReleaseNull(array); - } - break; - case kSecXPCOpCopyPeerPeerInfo: - { - CFArrayRef array = SOSCCCopyPeerPeerInfo_Server(&error); - if (array) { - xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error); - xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); - xpc_release(xpc_array); - } - CFReleaseNull(array); - } - break; - case kSecXPCOpCopyConcurringPeerPeerInfo: - { - CFArrayRef array = SOSCCCopyConcurringPeerPeerInfo_Server(&error); - if (array) { - xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error); - xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); - xpc_release(xpc_array); - } - CFReleaseNull(array); - } - break; - case kSecXPCOpGetLastDepartureReason: - xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, - SOSCCGetLastDepartureReason_Server(&error)); - break; - case kSecXPCOpProcessSyncWithAllPeers: - xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, - SOSCCProcessSyncWithAllPeers_Server(&error)); - break; - case kSecXPCOpCopyIncompatibilityInfo: - xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, - SOSCCCopyIncompatibilityInfo_Server(&error)); - break; - case kSecXPCOpOTAGetEscrowCertificates: - { - CFArrayRef array = SecOTAPKICopyCurrentEscrowCertificates(&error); - if (array) { - xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array); - xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); - xpc_release(xpc_array); - } - CFReleaseNull(array); - } - break; - case kSecXPCOpOTAPKIGetNewAsset: - xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, - SecOTAPKISignalNewAsset(&error)); - break; - default: - break; - } - } - - if (error) - { - if(SecErrorGetOSStatus(error) == errSecItemNotFound) - secdebug("ipc", "%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error); - else - secerror("%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error); - - xpcError = SecCreateXPCObjectWithCFError(error); - xpc_dictionary_set_value(replyMessage, kSecXPCKeyError, xpcError); - } else if (replyMessage) { - secdebug("ipc", "%@ %@ reponding %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyMessage); - } - } else { - SecCFCreateErrorWithFormatAndArguments(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, &error, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event); - secerror("%@: returning error: %@", clientTask, error); - xpcError = SecCreateXPCObjectWithCFError(error); - replyMessage = xpc_create_reply_with_format(event, "{%string: %value}", kSecXPCKeyError, xpcError); - } - - if (replyMessage) { - xpc_connection_send_message(connection, replyMessage); - xpc_release(replyMessage); - } - if (xpcError) - xpc_release(xpcError); - CFReleaseSafe(error); - CFReleaseSafe(accessGroups); - CFReleaseSafe(clientTask); -} - -static void securityd_xpc_init() -{ - secdebug("serverxpc", "start"); - - xpc_track_activity(); - xpc_connection_t listener = xpc_connection_create_mach_service(kSecuritydXPCServiceName, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER); - if (!listener) { - seccritical("security failed to register xpc listener, exiting"); - abort(); - } - - xpc_connection_set_event_handler(listener, ^(xpc_object_t connection) { - if (xpc_get_type(connection) == XPC_TYPE_CONNECTION) { - xpc_connection_set_event_handler(connection, ^(xpc_object_t event) { - if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) { - xpc_retain(connection); - xpc_retain(event); - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - securityd_xpc_dictionary_handler(connection, event); - xpc_release(event); - xpc_release(connection); - }); - } - }); - xpc_connection_resume(connection); - } - }); - xpc_connection_resume(listener); -} - -int main(int argc, char *argv[]) -{ - char *wait4debugger = getenv("WAIT4DEBUGGER"); - if (wait4debugger && !strcasecmp("YES", wait4debugger)) { - seccritical("SIGSTOPing self, awaiting debugger"); - kill(getpid(), SIGSTOP); - asl_log(NULL, NULL, ASL_LEVEL_CRIT, - "Again, for good luck (or bad debuggers)"); - kill(getpid(), SIGSTOP); - } - - securityd_init_server(); - securityd_xpc_init(); - dispatch_main(); - return 0; -} - -/* vi:set ts=4 sw=4 et: */ diff --git a/sec/sec.xcodeproj/project.pbxproj b/sec/sec.xcodeproj/project.pbxproj deleted file mode 100644 index 54ea7da1..00000000 --- a/sec/sec.xcodeproj/project.pbxproj +++ /dev/null @@ -1,2504 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 0C062B1F175E784B00806CFE /* secd-30-keychain-upgrade.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C062B1C175E784B00806CFE /* secd-30-keychain-upgrade.c */; }; - 0C062B20175E784B00806CFE /* secd-31-keychain-bad.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C062B1D175E784B00806CFE /* secd-31-keychain-bad.c */; }; - 0C062B21175E784B00806CFE /* secd-31-keychain-unreadable.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C062B1E175E784B00806CFE /* secd-31-keychain-unreadable.c */; }; - 0C0BDB611756882A00BC1A7E /* secd_regressions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C0BDB601756882A00BC1A7E /* secd_regressions.h */; }; - 0C0BDB63175688DA00BC1A7E /* secd-01-items.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C0BDB62175688DA00BC1A7E /* secd-01-items.c */; }; - 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 */; }; - 0CBF93FA177B7CFC001E5658 /* brighton_keychain_2_db.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CBF93F7177B7CFC001E5658 /* brighton_keychain_2_db.h */; }; - 0CBF93FC177BA9D9001E5658 /* secd-05-corrupted-items.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CBF93FB177BA9D9001E5658 /* secd-05-corrupted-items.c */; }; - 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 */; }; - 18AD566714CB70A8008233F2 /* SecItem.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD563714CB6EB9008233F2 /* SecItem.c */; }; - 18D4043914CE1FE400A2BE4E /* p12import.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD561614CB6EB9008233F2 /* p12import.c */; }; - 18D4043A14CE1FE400A2BE4E /* p12pbegen.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD561814CB6EB9008233F2 /* p12pbegen.c */; }; - 18D4043B14CE1FE400A2BE4E /* pbkdf2.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD561A14CB6EB9008233F2 /* pbkdf2.c */; }; - 18D4043C14CE1FE400A2BE4E /* SecBase64.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD561D14CB6EB9008233F2 /* SecBase64.c */; }; - 18D4043D14CE1FE400A2BE4E /* SecCertificate.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD562014CB6EB9008233F2 /* SecCertificate.c */; }; - 18D4043E14CE1FE400A2BE4E /* SecCertificatePath.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD562314CB6EB9008233F2 /* SecCertificatePath.c */; }; - 18D4043F14CE1FE400A2BE4E /* SecCertificateRequest.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD562614CB6EB9008233F2 /* SecCertificateRequest.c */; }; - 18D4044014CE1FE400A2BE4E /* SecCMS.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD562814CB6EB9008233F2 /* SecCMS.c */; }; - 18D4044114CE1FE400A2BE4E /* SecDH.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD562A14CB6EB9008233F2 /* SecDH.c */; }; - 18D4044214CE1FE400A2BE4E /* SecECKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD562C14CB6EB9008233F2 /* SecECKey.c */; }; - 18D4044314CE1FE400A2BE4E /* SecFramework.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD562E14CB6EB9008233F2 /* SecFramework.c */; }; - 18D4044414CE1FE400A2BE4E /* SecIdentity.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD563114CB6EB9008233F2 /* SecIdentity.c */; }; - 18D4044514CE1FE400A2BE4E /* SecImportExport.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD563414CB6EB9008233F2 /* SecImportExport.c */; }; - 18D4044614CE1FE400A2BE4E /* SecItem.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD563714CB6EB9008233F2 /* SecItem.c */; }; - 18D4044714CE1FE400A2BE4E /* SecItemConstants.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD563914CB6EB9008233F2 /* SecItemConstants.c */; }; - 18D4044814CE1FE400A2BE4E /* SecKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD563C14CB6EB9008233F2 /* SecKey.c */; }; - 18D4044914CE1FE400A2BE4E /* SecPBKDF.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD564014CB6EB9008233F2 /* SecPBKDF.c */; }; - 18D4044A14CE1FE400A2BE4E /* SecPolicy.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD564214CB6EB9008233F2 /* SecPolicy.c */; }; - 18D4044B14CE1FE400A2BE4E /* SecRSAKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD564714CB6EB9008233F2 /* SecRSAKey.c */; }; - 18D4044C14CE1FE400A2BE4E /* SecSCEP.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD564A14CB6EB9008233F2 /* SecSCEP.c */; }; - 18D4044D14CE1FE400A2BE4E /* SecTrust.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD564C14CB6EB9008233F2 /* SecTrust.c */; }; - 18D4044E14CE1FE400A2BE4E /* SecTrustSettings.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD564F14CB6EB9008233F2 /* SecTrustSettings.c */; }; - 18D4044F14CE1FE400A2BE4E /* SecTrustStore.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD565214CB6EB9008233F2 /* SecTrustStore.c */; }; - 18D4045014CE1FE400A2BE4E /* vmdh.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD565514CB6EB9008233F2 /* vmdh.c */; }; - 18D4056614CE53DD00A2BE4E /* asynchttp.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD567D14CB865E008233F2 /* asynchttp.c */; }; - 18D4056814CE53DD00A2BE4E /* policytree.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD568214CB865E008233F2 /* policytree.c */; }; - 18D4056914CE53DD00A2BE4E /* SecCAIssuerCache.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD568414CB865E008233F2 /* SecCAIssuerCache.c */; }; - 18D4056A14CE53DD00A2BE4E /* SecCAIssuerRequest.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD568614CB865E008233F2 /* SecCAIssuerRequest.c */; }; - 18D4056B14CE53DD00A2BE4E /* SecItemServer.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD568814CB865E008233F2 /* SecItemServer.c */; }; - 18D4056C14CE53DD00A2BE4E /* SecOCSPCache.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD565914CB6F79008233F2 /* SecOCSPCache.c */; }; - 18D4056D14CE53DD00A2BE4E /* SecOCSPRequest.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD565B14CB6F79008233F2 /* SecOCSPRequest.c */; }; - 18D4056E14CE53DD00A2BE4E /* SecOCSPResponse.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD565D14CB6F79008233F2 /* SecOCSPResponse.c */; }; - 18D4056F14CE53DD00A2BE4E /* SecPolicyServer.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD565F14CB6F79008233F2 /* SecPolicyServer.c */; }; - 18D4057014CE53DD00A2BE4E /* SecTrustServer.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD566114CB6F79008233F2 /* SecTrustServer.c */; }; - 18D4057114CE53DD00A2BE4E /* SecTrustStoreServer.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD566314CB6F79008233F2 /* SecTrustStoreServer.c */; }; - 18D4057214CE547400A2BE4E /* spi.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD566514CB6F79008233F2 /* spi.c */; }; - 4802A59616D711060059E5B9 /* SOSUserKeygen.c in Sources */ = {isa = PBXBuildFile; fileRef = 4802A59516D711060059E5B9 /* SOSUserKeygen.c */; }; - 4802A59816D7156D0059E5B9 /* SOSUserKeygen.h in Headers */ = {isa = PBXBuildFile; fileRef = 4802A59716D711190059E5B9 /* SOSUserKeygen.h */; settings = {ATTRIBUTES = (); }; }; - 486C6C691795F9D600387075 /* secd-61-account-leave-not-in-kansas-anymore.c in Sources */ = {isa = PBXBuildFile; fileRef = 486C6C671795F20E00387075 /* secd-61-account-leave-not-in-kansas-anymore.c */; }; - 4882C517177521AE0095D04B /* secd-58-password-change.c in Sources */ = {isa = PBXBuildFile; fileRef = 4882C516177521AE0095D04B /* secd-58-password-change.c */; }; - 488902EC16C2F88400F119FF /* SOSCoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 488902EB16C2F88400F119FF /* SOSCoder.c */; }; - 4898223A17BDB277003BEF32 /* secd-52-account-changed.c in Sources */ = {isa = PBXBuildFile; fileRef = 4898223917BDB277003BEF32 /* secd-52-account-changed.c */; }; - 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 */; }; - 48F32D7E1777AFA3001B84BA /* secd-59-account-cleanup.c in Sources */ = {isa = PBXBuildFile; fileRef = 48F32D7D1777AFA3001B84BA /* secd-59-account-cleanup.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 */; }; - 4A5CCA5715ACEFD400702357 /* SecOTRPacketData.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A97168B158FDEB800D439B7 /* SecOTRPacketData.c */; }; - 4A5CCA5815ACEFD400702357 /* SecOTRPackets.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A97168D158FDEB800D439B7 /* SecOTRPackets.c */; }; - 4A5CCA5915ACEFD400702357 /* SecOTRPublicIdentity.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A97168F158FDEB800D439B7 /* SecOTRPublicIdentity.c */; }; - 4A5CCA5A15ACEFD400702357 /* SecOTRSession.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971690158FDEB800D439B7 /* SecOTRSession.c */; }; - 4A5CCA5B15ACEFD400702357 /* SecOTRSessionAKE.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971692158FDEB800D439B7 /* SecOTRSessionAKE.c */; }; - 4A5CCA5C15ACEFD400702357 /* SecOTRUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971694158FDEB800D439B7 /* SecOTRUtils.c */; }; - 4A971695158FDEB800D439B7 /* SecOTR.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A971682158FDEB800D439B7 /* SecOTR.h */; }; - 4A971696158FDEB800D439B7 /* SecOTRDHKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971683158FDEB800D439B7 /* SecOTRDHKey.c */; }; - 4A971697158FDEB800D439B7 /* SecOTRDHKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A971684158FDEB800D439B7 /* SecOTRDHKey.h */; }; - 4A971698158FDEB800D439B7 /* SecOTRErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A971685158FDEB800D439B7 /* SecOTRErrors.h */; }; - 4A971699158FDEB800D439B7 /* SecOTRFullIdentity.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971686158FDEB800D439B7 /* SecOTRFullIdentity.c */; }; - 4A97169A158FDEB800D439B7 /* SecOTRIdentityPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A971687158FDEB800D439B7 /* SecOTRIdentityPriv.h */; }; - 4A97169B158FDEB800D439B7 /* SecOTRMath.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971688158FDEB800D439B7 /* SecOTRMath.c */; }; - 4A97169C158FDEB800D439B7 /* SecOTRMath.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A971689158FDEB800D439B7 /* SecOTRMath.h */; }; - 4A97169D158FDEB800D439B7 /* SecOTRMathPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A97168A158FDEB800D439B7 /* SecOTRMathPrivate.h */; }; - 4A97169E158FDEB800D439B7 /* SecOTRPacketData.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A97168B158FDEB800D439B7 /* SecOTRPacketData.c */; }; - 4A97169F158FDEB800D439B7 /* SecOTRPacketData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A97168C158FDEB800D439B7 /* SecOTRPacketData.h */; }; - 4A9716A0158FDEB800D439B7 /* SecOTRPackets.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A97168D158FDEB800D439B7 /* SecOTRPackets.c */; }; - 4A9716A1158FDEB800D439B7 /* SecOTRPackets.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A97168E158FDEB800D439B7 /* SecOTRPackets.h */; }; - 4A9716A2158FDEB800D439B7 /* SecOTRPublicIdentity.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A97168F158FDEB800D439B7 /* SecOTRPublicIdentity.c */; }; - 4A9716A3158FDEB800D439B7 /* SecOTRSession.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971690158FDEB800D439B7 /* SecOTRSession.c */; }; - 4A9716A4158FDEB800D439B7 /* SecOTRSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A971691158FDEB800D439B7 /* SecOTRSession.h */; }; - 4A9716A5158FDEB800D439B7 /* SecOTRSessionAKE.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971692158FDEB800D439B7 /* SecOTRSessionAKE.c */; }; - 4A9716A6158FDEB800D439B7 /* SecOTRSessionPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A971693158FDEB800D439B7 /* SecOTRSessionPriv.h */; }; - 4A9716A7158FDEB800D439B7 /* SecOTRUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971694158FDEB800D439B7 /* SecOTRUtils.c */; }; - 4AD6F6F21651C86200DB4CE6 /* libSecureObjectSync.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E702E75614E1F3EA00CDE635 /* libSecureObjectSync.a */; }; - 4C143CDE164D8EF5003035A3 /* sd-70-engine.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C143CDD164D8EF5003035A3 /* sd-70-engine.c */; }; - 4C1C452714EB27F50018B1D9 /* SOSTransport.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C1C452614EB27F50018B1D9 /* SOSTransport.c */; }; - 4C1C452A14EB28260018B1D9 /* SOSTransport.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C1C452914EB28260018B1D9 /* SOSTransport.h */; settings = {ATTRIBUTES = (); }; }; - 4C2C8C3D17AB374700C24C13 /* si-12-item-stress.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2C8C3C17AB374700C24C13 /* si-12-item-stress.c */; }; - 4C3CE9E7176005A700B521C2 /* SecuritydXPC.c in Sources */ = {isa = PBXBuildFile; fileRef = E7B01B8816572579000485F1 /* SecuritydXPC.c */; }; - 4C3CE9E8176005B500B521C2 /* SecuritydXPC.c in Sources */ = {isa = PBXBuildFile; fileRef = E7B01B8816572579000485F1 /* SecuritydXPC.c */; }; - 4C4EBD541610D7D8007D06A5 /* sc-75-circle-engine.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C4EBD531610D7D8007D06A5 /* sc-75-circle-engine.c */; }; - 4C5F2E38162DF76A00AF8346 /* SOSTestTransport.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C5F2E36162DE87F00AF8346 /* SOSTestTransport.c */; }; - 4C6ED19515CB0E44004379B7 /* sc-70-engine.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6ED19415CB0E43004379B7 /* sc-70-engine.c */; }; - 4C6ED19615CB0E72004379B7 /* sc-30-peerinfo.c in Sources */ = {isa = PBXBuildFile; fileRef = E777C72815B9C9F0004044A8 /* sc-30-peerinfo.c */; }; - 4C6ED19715CB0E72004379B7 /* sc-60-peer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6ED19115CB0E26004379B7 /* sc-60-peer.c */; }; - 4C8940DB166EA8CF00241770 /* osxshim.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C8940DA166EA8CF00241770 /* osxshim.c */; }; - 4C8D8627177A71E80019A804 /* SOSCloudCircle.c in Sources */ = {isa = PBXBuildFile; fileRef = E7217B1715F80E0F00D26031 /* SOSCloudCircle.c */; }; - 4C8D8628177A71FB0019A804 /* SecPasswordGenerate.c in Sources */ = {isa = PBXBuildFile; fileRef = CDC765C01729A72800721712 /* SecPasswordGenerate.c */; }; - 4C9DC91A15B602760036D941 /* SOSEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9DC91915B602760036D941 /* SOSEngine.h */; settings = {ATTRIBUTES = (); }; }; - 4C9DC91D15B602910036D941 /* SOSEngine.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C9DC91C15B602910036D941 /* SOSEngine.c */; }; - 4CB8A83816164B7700B52EC7 /* SOSTestDataSource.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CB8A83716164B7700B52EC7 /* SOSTestDataSource.c */; }; - 4CC07E26171E252300DCB6CE /* SOSCloudCircle.c in Sources */ = {isa = PBXBuildFile; fileRef = E7217B1715F80E0F00D26031 /* SOSCloudCircle.c */; }; - 4CC929B315A3957800C6D578 /* SOSAccount.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC929AD15A3957800C6D578 /* SOSAccount.c */; }; - 4CC929B415A3957800C6D578 /* SOSAccount.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC929AE15A3957800C6D578 /* SOSAccount.h */; settings = {ATTRIBUTES = (); }; }; - 4CC929B515A3957800C6D578 /* SOSCircle.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC929AF15A3957800C6D578 /* SOSCircle.c */; }; - 4CC929B615A3957800C6D578 /* SOSCircle.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC929B015A3957800C6D578 /* SOSCircle.h */; settings = {ATTRIBUTES = (); }; }; - 4CC929B715A3957800C6D578 /* SOSPeer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC929B115A3957800C6D578 /* SOSPeer.c */; }; - 4CC929B815A3957800C6D578 /* SOSPeer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC929B215A3957800C6D578 /* SOSPeer.h */; settings = {ATTRIBUTES = (); }; }; - 4CC92A5F15A3ABD400C6D578 /* pbkdf2-00-hmac-sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A0F15A3ABD400C6D578 /* pbkdf2-00-hmac-sha1.c */; }; - 4CC92A6015A3ABD400C6D578 /* spbkdf-00-hmac-sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1015A3ABD400C6D578 /* spbkdf-00-hmac-sha1.c */; }; - 4CC92A6115A3ABD400C6D578 /* otr-00-identity.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1215A3ABD400C6D578 /* otr-00-identity.c */; }; - 4CC92A6215A3ABD400C6D578 /* otr-30-negotiation.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1315A3ABD400C6D578 /* otr-30-negotiation.c */; }; - 4CC92A6315A3ABD400C6D578 /* otr-otrdh.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1415A3ABD400C6D578 /* otr-otrdh.c */; }; - 4CC92A6415A3ABD400C6D578 /* otr-packetdata.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1515A3ABD400C6D578 /* otr-packetdata.c */; }; - 4CC92A6515A3ABD400C6D578 /* si-00-find-nothing.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1715A3ABD400C6D578 /* si-00-find-nothing.c */; }; - 4CC92A6615A3ABD400C6D578 /* si-05-add.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1815A3ABD400C6D578 /* si-05-add.c */; }; - 4CC92A6715A3ABD400C6D578 /* si-10-find-internet.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1915A3ABD400C6D578 /* si-10-find-internet.c */; }; - 4CC92A6815A3ABD400C6D578 /* si-11-update-data.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1A15A3ABD400C6D578 /* si-11-update-data.c */; }; - 4CC92A6915A3ABD400C6D578 /* si-14-dateparse.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1B15A3ABD400C6D578 /* si-14-dateparse.c */; }; - 4CC92A6A15A3ABD400C6D578 /* si-15-certificate.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1C15A3ABD400C6D578 /* si-15-certificate.c */; }; - 4CC92A6B15A3ABD400C6D578 /* si-16-ec-certificate.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1D15A3ABD400C6D578 /* si-16-ec-certificate.c */; }; - 4CC92A6C15A3ABD400C6D578 /* si-20-sectrust-activation.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1E15A3ABD400C6D578 /* si-20-sectrust-activation.c */; }; - 4CC92A6D15A3ABD400C6D578 /* si-20-sectrust.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A1F15A3ABD400C6D578 /* si-20-sectrust.c */; }; - 4CC92A6E15A3ABD400C6D578 /* si-21-sectrust-asr.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2015A3ABD400C6D578 /* si-21-sectrust-asr.c */; }; - 4CC92A6F15A3ABD400C6D578 /* si-22-sectrust-iap.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2115A3ABD400C6D578 /* si-22-sectrust-iap.c */; }; - 4CC92A7015A3ABD400C6D578 /* si-23-sectrust-ocsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2215A3ABD400C6D578 /* si-23-sectrust-ocsp.c */; }; - 4CC92A7115A3ABD400C6D578 /* si-24-sectrust-appleid.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2315A3ABD400C6D578 /* si-24-sectrust-appleid.c */; }; - 4CC92A7215A3ABD400C6D578 /* si-24-sectrust-digicert-malaysia.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2415A3ABD400C6D578 /* si-24-sectrust-digicert-malaysia.c */; }; - 4CC92A7315A3ABD400C6D578 /* si-24-sectrust-diginotar.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2515A3ABD400C6D578 /* si-24-sectrust-diginotar.c */; }; - 4CC92A7415A3ABD400C6D578 /* si-24-sectrust-itms.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2615A3ABD400C6D578 /* si-24-sectrust-itms.c */; }; - 4CC92A7515A3ABD400C6D578 /* si-24-sectrust-mobileasset.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2715A3ABD400C6D578 /* si-24-sectrust-mobileasset.c */; }; - 4CC92A7615A3ABD400C6D578 /* si-24-sectrust-nist.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2815A3ABD400C6D578 /* si-24-sectrust-nist.c */; }; - 4CC92A7715A3ABD400C6D578 /* si-24-sectrust-otatasking.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2915A3ABD400C6D578 /* si-24-sectrust-otatasking.c */; }; - 4CC92A7815A3ABD400C6D578 /* si-24-sectrust-shoebox.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2A15A3ABD400C6D578 /* si-24-sectrust-shoebox.c */; }; - 4CC92A7915A3ABD400C6D578 /* si-25-sectrust-ipsec-eap.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2B15A3ABD400C6D578 /* si-25-sectrust-ipsec-eap.c */; }; - 4CC92A7A15A3ABD400C6D578 /* si-26-applicationsigning.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2C15A3ABD400C6D578 /* si-26-applicationsigning.c */; }; - 4CC92A7B15A3ABD400C6D578 /* si-27-sectrust-exceptions.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2D15A3ABD400C6D578 /* si-27-sectrust-exceptions.c */; }; - 4CC92A7C15A3ABD400C6D578 /* si-28-sectrustsettings.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2E15A3ABD400C6D578 /* si-28-sectrustsettings.c */; }; - 4CC92A7D15A3ABD400C6D578 /* si-29-sectrust-codesigning.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A2F15A3ABD400C6D578 /* si-29-sectrust-codesigning.c */; }; - 4CC92A7E15A3ABD400C6D578 /* si-30-keychain-upgrade.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3015A3ABD400C6D578 /* si-30-keychain-upgrade.c */; }; - 4CC92A7F15A3ABD400C6D578 /* si-31-keychain-bad.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3115A3ABD400C6D578 /* si-31-keychain-bad.c */; }; - 4CC92A8015A3ABD400C6D578 /* si-31-keychain-unreadable.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3215A3ABD400C6D578 /* si-31-keychain-unreadable.c */; }; - 4CC92A8215A3ABD400C6D578 /* si-33-keychain-backup.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3415A3ABD400C6D578 /* si-33-keychain-backup.c */; }; - 4CC92A8315A3ABD400C6D578 /* si-40-seckey-custom.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3515A3ABD400C6D578 /* si-40-seckey-custom.c */; }; - 4CC92A8415A3ABD400C6D578 /* si-40-seckey.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3615A3ABD400C6D578 /* si-40-seckey.c */; }; - 4CC92A8515A3ABD400C6D578 /* si-41-sececkey.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3715A3ABD400C6D578 /* si-41-sececkey.c */; }; - 4CC92A8615A3ABD400C6D578 /* si-42-identity.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3815A3ABD400C6D578 /* si-42-identity.c */; }; - 4CC92A8715A3ABD400C6D578 /* si-43-persistent.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3915A3ABD400C6D578 /* si-43-persistent.c */; }; - 4CC92A8815A3ABD400C6D578 /* si-50-secrandom.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3A15A3ABD400C6D578 /* si-50-secrandom.c */; }; - 4CC92A8915A3ABD400C6D578 /* si-60-cms.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3B15A3ABD400C6D578 /* si-60-cms.c */; }; - 4CC92A8A15A3ABD400C6D578 /* si-61-pkcs12.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3C15A3ABD400C6D578 /* si-61-pkcs12.c */; }; - 4CC92A8B15A3ABD400C6D578 /* si-62-csr.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A3D15A3ABD400C6D578 /* si-62-csr.c */; }; - 4CC92A8C15A3ABD400C6D578 /* getcacert-mdes.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A3F15A3ABD400C6D578 /* getcacert-mdes.h */; }; - 4CC92A8D15A3ABD400C6D578 /* getcacert-mdesqa.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A4015A3ABD400C6D578 /* getcacert-mdesqa.h */; }; - 4CC92A8E15A3ABD400C6D578 /* si-63-scep.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A4115A3ABD400C6D578 /* si-63-scep.c */; }; - 4CC92A8F15A3ABD400C6D578 /* si-63-scep.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A4215A3ABD400C6D578 /* si-63-scep.h */; }; - 4CC92A9015A3ABD400C6D578 /* attached_no_data_signed_data.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A4415A3ABD400C6D578 /* attached_no_data_signed_data.h */; }; - 4CC92A9115A3ABD400C6D578 /* attached_signed_data.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A4515A3ABD400C6D578 /* attached_signed_data.h */; }; - 4CC92A9215A3ABD400C6D578 /* detached_content.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A4615A3ABD400C6D578 /* detached_content.h */; }; - 4CC92A9315A3ABD400C6D578 /* detached_signed_data.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A4715A3ABD400C6D578 /* detached_signed_data.h */; }; - 4CC92A9415A3ABD400C6D578 /* privkey.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A4815A3ABD400C6D578 /* privkey.h */; }; - 4CC92A9515A3ABD400C6D578 /* signer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A4915A3ABD400C6D578 /* signer.h */; }; - 4CC92A9615A3ABD400C6D578 /* si-64-ossl-cms.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A4A15A3ABD400C6D578 /* si-64-ossl-cms.c */; }; - 4CC92A9715A3ABD400C6D578 /* si-65-cms-cert-policy.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A4B15A3ABD400C6D578 /* si-65-cms-cert-policy.c */; }; - 4CC92A9815A3ABD400C6D578 /* signed-receipt.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A4D15A3ABD400C6D578 /* signed-receipt.h */; }; - 4CC92A9915A3ABD400C6D578 /* si-66-smime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A4E15A3ABD400C6D578 /* si-66-smime.c */; }; - 4CC92A9A15A3ABD400C6D578 /* Global Trustee.cer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A5015A3ABD400C6D578 /* Global Trustee.cer.h */; }; - 4CC92A9B15A3ABD400C6D578 /* UTN-USERFirst-Hardware.cer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A5115A3ABD400C6D578 /* UTN-USERFirst-Hardware.cer.h */; }; - 4CC92A9C15A3ABD400C6D578 /* addons.mozilla.org.cer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A5215A3ABD400C6D578 /* addons.mozilla.org.cer.h */; }; - 4CC92A9D15A3ABD400C6D578 /* login.live.com.cer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A5315A3ABD400C6D578 /* login.live.com.cer.h */; }; - 4CC92A9E15A3ABD400C6D578 /* login.skype.com.cer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A5415A3ABD400C6D578 /* login.skype.com.cer.h */; }; - 4CC92A9F15A3ABD400C6D578 /* login.yahoo.com.1.cer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A5515A3ABD400C6D578 /* login.yahoo.com.1.cer.h */; }; - 4CC92AA015A3ABD400C6D578 /* login.yahoo.com.2.cer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A5615A3ABD400C6D578 /* login.yahoo.com.2.cer.h */; }; - 4CC92AA115A3ABD400C6D578 /* login.yahoo.com.cer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A5715A3ABD400C6D578 /* login.yahoo.com.cer.h */; }; - 4CC92AA215A3ABD400C6D578 /* mail.google.com.cer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A5815A3ABD400C6D578 /* mail.google.com.cer.h */; }; - 4CC92AA315A3ABD400C6D578 /* www.google.com.cer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92A5915A3ABD400C6D578 /* www.google.com.cer.h */; }; - 4CC92AA415A3ABD400C6D578 /* si-67-sectrust-blacklist.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A5A15A3ABD400C6D578 /* si-67-sectrust-blacklist.c */; }; - 4CC92AA515A3ABD400C6D578 /* vmdh-40.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A5C15A3ABD400C6D578 /* vmdh-40.c */; }; - 4CC92AA615A3ABD400C6D578 /* vmdh-41-example.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A5D15A3ABD400C6D578 /* vmdh-41-example.c */; }; - 4CC92AA715A3ABD400C6D578 /* vmdh-42-example2.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92A5E15A3ABD400C6D578 /* vmdh-42-example2.c */; }; - 4CC92AC015A3BC4300C6D578 /* Security_regressions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92AB015A3AD0000C6D578 /* Security_regressions.h */; }; - 4CC92AC115A3BC4D00C6D578 /* SOSCircle_regressions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92AAF15A3ACE600C6D578 /* SOSCircle_regressions.h */; }; - 4CC92AF915A3BC6B00C6D578 /* sd-10-policytree.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92AAC15A3AC4600C6D578 /* sd-10-policytree.c */; }; - 4CC92B1515A3BCA500C6D578 /* securityd_regressions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92AAE15A3ACCE00C6D578 /* securityd_regressions.h */; }; - 4CD1897D169F835400BC96B8 /* print_cert.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CD1897B169F835400BC96B8 /* print_cert.c */; }; - 5214701B16977D7700DF0DB3 /* cloudkeychainproxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 521C0BB315FA5E3F00604B61 /* cloudkeychainproxy.m */; }; - 521C0A7615F908AF00604B61 /* sc-90-ckdclient.c in Sources */ = {isa = PBXBuildFile; fileRef = 521C0A7315F908A700604B61 /* sc-90-ckdclient.c */; }; - 521C0C8715FEB03300604B61 /* sc-120-cloudcircle.c in Sources */ = {isa = PBXBuildFile; fileRef = 521C0C8615FEB03300604B61 /* sc-120-cloudcircle.c */; }; - 521C0CD615FF9B3300604B61 /* SOSRegressionUtilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 521C0CD515FF9B3300604B61 /* SOSRegressionUtilities.c */; }; - 521C0CDD15FFA05100604B61 /* CKDKeyValueStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 521C0CD915FFA05000604B61 /* CKDKeyValueStore.h */; }; - 521C68601614A6E100E31C3E /* SOSCloudKeychainClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 521C685D1614A6E100E31C3E /* SOSCloudKeychainClient.h */; settings = {ATTRIBUTES = (); }; }; - 521C691F16164B9900E31C3E /* sc-95-ckd2client.c in Sources */ = {isa = PBXBuildFile; fileRef = 521C691E16164B9900E31C3E /* sc-95-ckd2client.c */; }; - 522B0ED21648809300A4675D /* sc-103-syncupdate.c in Sources */ = {isa = PBXBuildFile; fileRef = 522B0ED11648809300A4675D /* sc-103-syncupdate.c */; }; - 5253946116608F6800BA9687 /* sc-51-persistentEC.c in Sources */ = {isa = PBXBuildFile; fileRef = 5253946016608F6800BA9687 /* sc-51-persistentEC.c */; }; - 525394AE1660A30000BA9687 /* SecDbItem.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C4B15931655ED9000734590 /* SecDbItem.c */; }; - 52840281163F2B060035F320 /* sc-102-cfusernotification.c in Sources */ = {isa = PBXBuildFile; fileRef = 52840280163F2B060035F320 /* sc-102-cfusernotification.c */; }; - 528402AE164446410035F320 /* CKDKVSProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 521C0BB015FA5E3F00604B61 /* CKDKVSProxy.m */; }; - 528402AF164446410035F320 /* CKDPersistentState.m in Sources */ = {isa = PBXBuildFile; fileRef = 521C0BB215FA5E3F00604B61 /* CKDPersistentState.m */; }; - 528402B1164446410035F320 /* CKDUserInteraction.m in Sources */ = {isa = PBXBuildFile; fileRef = 52840292164050C80035F320 /* CKDUserInteraction.m */; }; - 528402B2164447610035F320 /* SOSCloudKeychainConstants.c in Sources */ = {isa = PBXBuildFile; fileRef = E7217B2515F8131A00D26031 /* SOSCloudKeychainConstants.c */; }; - 52AF7083163D9AA20092A7ED /* sc-101-accountsync.c in Sources */ = {isa = PBXBuildFile; fileRef = 52AF7082163D9AA20092A7ED /* sc-101-accountsync.c */; }; - 52D0F028169CA72800F07D79 /* SecOnOSX.h in Headers */ = {isa = PBXBuildFile; fileRef = 52D0F026169CA72800F07D79 /* SecOnOSX.h */; }; - 52DEE9E2162DC8F1002F3BCD /* sc-100-devicecircle.c in Sources */ = {isa = PBXBuildFile; fileRef = 52DEE9E1162DC8F1002F3BCD /* sc-100-devicecircle.c */; }; - 52EAF4BE163C52EB00803D0F /* SOSCloudKeychainClient.c in Sources */ = {isa = PBXBuildFile; fileRef = 521C685C1614A6E100E31C3E /* SOSCloudKeychainClient.c */; }; - 5DE4A7BD17441CCD0036339E /* si-71-mobile-store-policy.c in Sources */ = {isa = PBXBuildFile; fileRef = 5DE4A7BC17441CCD0036339E /* si-71-mobile-store-policy.c */; }; - 7249E1CB16C01E5F003D7268 /* OTATrustUtilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E2DC0616BC47C800E7B236 /* OTATrustUtilities.c */; }; - 7255A46C1783333D006A8B9A /* si-74-OTAPKISigner.c in Sources */ = {isa = PBXBuildFile; fileRef = 7255A46B1783333D006A8B9A /* si-74-OTAPKISigner.c */; }; - 7255F91417A973D5004A9F38 /* si-75-AppleIDRecordSigning.c in Sources */ = {isa = PBXBuildFile; fileRef = 7255F91317A973D5004A9F38 /* si-75-AppleIDRecordSigning.c */; }; - BE62D7601747FF3E001EAA9D /* si-72-syncableitems.c in Sources */ = {isa = PBXBuildFile; fileRef = BE62D75F1747FF3E001EAA9D /* si-72-syncableitems.c */; }; - BE62D7621747FF51001EAA9D /* si-70-sectrust-unified.c in Sources */ = {isa = PBXBuildFile; fileRef = BE62D7611747FF51001EAA9D /* si-70-sectrust-unified.c */; }; - BEFE994E14F2E17200356A97 /* SecDH.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD562A14CB6EB9008233F2 /* SecDH.c */; }; - CD3FD10716C3064B00A83BB6 /* SecuritydXPC.c in Sources */ = {isa = PBXBuildFile; fileRef = E7B01B8816572579000485F1 /* SecuritydXPC.c */; }; - CDC765C21729A72800721712 /* SecPasswordGenerate.c in Sources */ = {isa = PBXBuildFile; fileRef = CDC765C01729A72800721712 /* SecPasswordGenerate.c */; }; - CDC765C41729A72800721712 /* SecPasswordGenerate.h in Headers */ = {isa = PBXBuildFile; fileRef = CDC765C11729A72800721712 /* SecPasswordGenerate.h */; }; - CDD565A2173193AC00B6B074 /* si-73-secpasswordgenerate.c in Sources */ = {isa = PBXBuildFile; fileRef = CDD565A1173193AC00B6B074 /* si-73-secpasswordgenerate.c */; }; - E703811514E1FEEF007CB458 /* SOSCloudCircle.h in Headers */ = {isa = PBXBuildFile; fileRef = E703811114E1FEE4007CB458 /* SOSCloudCircle.h */; }; - E71049F3169E023B00DB0045 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 521C0B9815FA5C4A00604B61 /* Foundation.framework */; }; - E7104A01169E036E00DB0045 /* SecurityTool.c in Sources */ = {isa = PBXBuildFile; fileRef = E71049FF169E036E00DB0045 /* SecurityTool.c */; }; - E7104A18169E216E00DB0045 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 521C0B9815FA5C4A00604B61 /* Foundation.framework */; }; - E7217B2715F8131A00D26031 /* SOSCloudKeychainConstants.c in Sources */ = {isa = PBXBuildFile; fileRef = E7217B2515F8131A00D26031 /* SOSCloudKeychainConstants.c */; }; - E7217B2815F8131A00D26031 /* SOSCloudKeychainConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = E7217B2615F8131A00D26031 /* SOSCloudKeychainConstants.h */; settings = {ATTRIBUTES = (); }; }; - E748744515A61AF800624935 /* si-68-secmatchissuer.c in Sources */ = {isa = PBXBuildFile; fileRef = E748744415A61AF800624935 /* si-68-secmatchissuer.c */; }; - E763D6231624E2670038477D /* sc-20-keynames.c in Sources */ = {isa = PBXBuildFile; fileRef = E763D6221624E2670038477D /* sc-20-keynames.c */; }; - E777C6B115B4DDF2004044A8 /* sc-40-circle.c in Sources */ = {isa = PBXBuildFile; fileRef = E777C6B015B4DDF2004044A8 /* sc-40-circle.c */; }; - E777C71C15B73F59004044A8 /* SOSInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = E777C71B15B73F59004044A8 /* SOSInternal.h */; settings = {ATTRIBUTES = (); }; }; - 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 */; settings = {ATTRIBUTES = (); }; }; - E790C10A169E4FD200E0C0C9 /* digest_calc.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C109169E4FD200E0C0C9 /* digest_calc.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 */; }; - E790C143169E5C6200E0C0C9 /* keychain_add.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C138169E5C6200E0C0C9 /* keychain_add.c */; }; - E790C144169E5C6200E0C0C9 /* keychain_find.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C139169E5C6200E0C0C9 /* keychain_find.c */; }; - E790C145169E5C6200E0C0C9 /* pkcs12_util.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C13A169E5C6200E0C0C9 /* pkcs12_util.c */; }; - E790C147169E5C6200E0C0C9 /* scep.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C13D169E5C6200E0C0C9 /* scep.c */; }; - E790C148169E5C6200E0C0C9 /* show_certificates.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C13F169E5C6200E0C0C9 /* show_certificates.c */; }; - E790C149169E5C6200E0C0C9 /* spc.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C140169E5C6200E0C0C9 /* spc.c */; }; - E79277E3163B110A0096F3E2 /* SOSFullPeerInfo.c in Sources */ = {isa = PBXBuildFile; fileRef = E79277E1163B110A0096F3E2 /* SOSFullPeerInfo.c */; }; - E79277E4163B110A0096F3E2 /* SOSFullPeerInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = E79277E2163B110A0096F3E2 /* SOSFullPeerInfo.h */; settings = {ATTRIBUTES = (); }; }; - E79D62BB176798FD005A9743 /* secd-50-account.c in Sources */ = {isa = PBXBuildFile; fileRef = E79D62B9176798BF005A9743 /* secd-50-account.c */; }; - E79D62BC176799DB005A9743 /* SOSRegressionUtilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 521C0CD515FF9B3300604B61 /* SOSRegressionUtilities.c */; }; - E79D62BD176799EE005A9743 /* SOSTestDataSource.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CB8A83716164B7700B52EC7 /* SOSTestDataSource.c */; }; - E79D62C01767A5BC005A9743 /* SecdTestKeychainUtilities.c in Sources */ = {isa = PBXBuildFile; fileRef = E79D62BE1767A547005A9743 /* SecdTestKeychainUtilities.c */; }; - E7A10FAC1771246A00C4602F /* secd-55-account-circle.c in Sources */ = {isa = PBXBuildFile; fileRef = E7A10FAB1771246A00C4602F /* secd-55-account-circle.c */; }; - E7A10FAE1771249C00C4602F /* secd-57-account-leave.c in Sources */ = {isa = PBXBuildFile; fileRef = E7A10FAD1771249C00C4602F /* secd-57-account-leave.c */; }; - E7B01B5B16532507000485F1 /* SOSCloudCircleInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = E7B01B5A16532507000485F1 /* SOSCloudCircleInternal.h */; settings = {ATTRIBUTES = (); }; }; - E7B01B691655DF20000485F1 /* SOSCloudCircleServer.c in Sources */ = {isa = PBXBuildFile; fileRef = E7B01B671655CCA6000485F1 /* SOSCloudCircleServer.c */; }; - E7BE10A7167AB32300D2A178 /* sc-41-cloudcircle.c in Sources */ = {isa = PBXBuildFile; fileRef = E7BE10A5167AB2BF00D2A178 /* sc-41-cloudcircle.c */; }; - E7CA197A17179EC20065299C /* si-69-keydesc.c in Sources */ = {isa = PBXBuildFile; fileRef = CDA7729616B899F10069434D /* si-69-keydesc.c */; }; - E7F0D3EA177BBE35001ACBC1 /* secd-55-account-incompatibility.c in Sources */ = {isa = PBXBuildFile; fileRef = E7F0D3E9177BBE35001ACBC1 /* secd-55-account-incompatibility.c */; }; - E7F18555177A44E000177B23 /* secd-60-account-cloud-identity.c in Sources */ = {isa = PBXBuildFile; fileRef = E7F18554177A44E000177B23 /* secd-60-account-cloud-identity.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 */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 5284029E164445760035F320 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "include/${PRODUCT_NAME}"; - dstSubfolderSpec = 16; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E71049F0169E023B00DB0045 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "include/${PRODUCT_NAME}"; - dstSubfolderSpec = 16; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E7104A19169E216E00DB0045 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "include/${PRODUCT_NAME}"; - dstSubfolderSpec = 16; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E7FEFB88169E363300E18152 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = "include/${PRODUCT_NAME}"; - dstSubfolderSpec = 16; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 0C062B1C175E784B00806CFE /* secd-30-keychain-upgrade.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-30-keychain-upgrade.c"; sourceTree = ""; }; - 0C062B1D175E784B00806CFE /* secd-31-keychain-bad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-31-keychain-bad.c"; sourceTree = ""; }; - 0C062B1E175E784B00806CFE /* secd-31-keychain-unreadable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-31-keychain-unreadable.c"; sourceTree = ""; }; - 0C0BDB5F175687EC00BC1A7E /* libsecdRegressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecdRegressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 0C0BDB601756882A00BC1A7E /* secd_regressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = secd_regressions.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - 0C0BDB62175688DA00BC1A7E /* secd-01-items.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-01-items.c"; sourceTree = ""; }; - 0C664AE7175951270092D3D9 /* secd-02-upgrade-while-locked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = "secd-02-upgrade-while-locked.c"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.c; }; - 0CBF93F5177B7CFC001E5658 /* secd-03-corrupted-items.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-03-corrupted-items.c"; sourceTree = ""; }; - 0CBF93F6177B7CFC001E5658 /* secd-04-corrupted-items.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-04-corrupted-items.c"; sourceTree = ""; }; - 0CBF93F7177B7CFC001E5658 /* brighton_keychain_2_db.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = brighton_keychain_2_db.h; sourceTree = ""; }; - 0CBF93FB177BA9D9001E5658 /* secd-05-corrupted-items.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-05-corrupted-items.c"; sourceTree = ""; }; - 0CE7ABDE171383E30088968F /* keychain_backup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keychain_backup.c; sourceTree = ""; }; - 18270C9714CF1AAD00B05E7F /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; - 18270C9814CF1AAD00B05E7F /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; - 18270C9914CF1AAD00B05E7F /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; - 18270C9A14CF1AAD00B05E7F /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; - 18270F5514CF651900B05E7F /* libsecipc_client.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecipc_client.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 186CDD0F14CA116C00AF9171 /* libSecItemShimOSX.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSecItemShimOSX.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 18AD560614CB6E7A008233F2 /* client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = client.c; sourceTree = ""; }; - 18AD560714CB6E7A008233F2 /* com.apple.securityd.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.securityd.plist; sourceTree = ""; }; - 18AD560814CB6E7A008233F2 /* securityd_client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = securityd_client.h; sourceTree = ""; }; - 18AD560D14CB6E7A008233F2 /* server.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = server.c; sourceTree = ""; }; - 18AD561514CB6EB9008233F2 /* certextensions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = certextensions.h; sourceTree = ""; }; - 18AD561614CB6EB9008233F2 /* p12import.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = p12import.c; sourceTree = ""; }; - 18AD561714CB6EB9008233F2 /* p12import.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = p12import.h; sourceTree = ""; }; - 18AD561814CB6EB9008233F2 /* p12pbegen.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = p12pbegen.c; sourceTree = ""; }; - 18AD561914CB6EB9008233F2 /* p12pbegen.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = p12pbegen.h; sourceTree = ""; }; - 18AD561A14CB6EB9008233F2 /* pbkdf2.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = pbkdf2.c; sourceTree = ""; }; - 18AD561B14CB6EB9008233F2 /* pbkdf2.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = pbkdf2.h; sourceTree = ""; }; - 18AD561C14CB6EB9008233F2 /* SecBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecBase.h; sourceTree = ""; }; - 18AD561D14CB6EB9008233F2 /* SecBase64.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecBase64.c; sourceTree = ""; }; - 18AD561E14CB6EB9008233F2 /* SecBase64.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecBase64.h; sourceTree = ""; }; - 18AD561F14CB6EB9008233F2 /* SecBasePriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecBasePriv.h; sourceTree = ""; }; - 18AD562014CB6EB9008233F2 /* SecCertificate.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecCertificate.c; sourceTree = ""; }; - 18AD562114CB6EB9008233F2 /* SecCertificate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecCertificate.h; sourceTree = ""; }; - 18AD562214CB6EB9008233F2 /* SecCertificateInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecCertificateInternal.h; sourceTree = ""; }; - 18AD562314CB6EB9008233F2 /* SecCertificatePath.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecCertificatePath.c; sourceTree = ""; }; - 18AD562414CB6EB9008233F2 /* SecCertificatePath.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecCertificatePath.h; sourceTree = ""; }; - 18AD562514CB6EB9008233F2 /* SecCertificatePriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecCertificatePriv.h; sourceTree = ""; }; - 18AD562614CB6EB9008233F2 /* SecCertificateRequest.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecCertificateRequest.c; sourceTree = ""; }; - 18AD562714CB6EB9008233F2 /* SecCertificateRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecCertificateRequest.h; sourceTree = ""; }; - 18AD562814CB6EB9008233F2 /* SecCMS.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecCMS.c; sourceTree = ""; }; - 18AD562914CB6EB9008233F2 /* SecCMS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecCMS.h; sourceTree = ""; }; - 18AD562A14CB6EB9008233F2 /* SecDH.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecDH.c; sourceTree = ""; }; - 18AD562B14CB6EB9008233F2 /* SecDH.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecDH.h; sourceTree = ""; }; - 18AD562C14CB6EB9008233F2 /* SecECKey.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecECKey.c; sourceTree = ""; }; - 18AD562D14CB6EB9008233F2 /* SecECKey.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecECKey.h; sourceTree = ""; }; - 18AD562E14CB6EB9008233F2 /* SecFramework.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecFramework.c; sourceTree = ""; }; - 18AD562F14CB6EB9008233F2 /* SecFramework.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecFramework.h; sourceTree = ""; }; - 18AD563014CB6EB9008233F2 /* SecFrameworkStrings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecFrameworkStrings.h; sourceTree = ""; }; - 18AD563114CB6EB9008233F2 /* SecIdentity.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecIdentity.c; sourceTree = ""; }; - 18AD563214CB6EB9008233F2 /* SecIdentity.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecIdentity.h; sourceTree = ""; }; - 18AD563314CB6EB9008233F2 /* SecIdentityPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecIdentityPriv.h; sourceTree = ""; }; - 18AD563414CB6EB9008233F2 /* SecImportExport.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecImportExport.c; sourceTree = ""; }; - 18AD563514CB6EB9008233F2 /* SecImportExport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecImportExport.h; sourceTree = ""; }; - 18AD563614CB6EB9008233F2 /* SecInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecInternal.h; sourceTree = ""; }; - 18AD563714CB6EB9008233F2 /* SecItem.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecItem.c; sourceTree = ""; }; - 18AD563814CB6EB9008233F2 /* SecItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecItem.h; sourceTree = ""; }; - 18AD563914CB6EB9008233F2 /* SecItemConstants.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecItemConstants.c; sourceTree = ""; }; - 18AD563A14CB6EB9008233F2 /* SecItemInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecItemInternal.h; sourceTree = ""; }; - 18AD563B14CB6EB9008233F2 /* SecItemPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecItemPriv.h; sourceTree = ""; }; - 18AD563C14CB6EB9008233F2 /* SecKey.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecKey.c; sourceTree = ""; }; - 18AD563D14CB6EB9008233F2 /* SecKey.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecKey.h; sourceTree = ""; }; - 18AD563E14CB6EB9008233F2 /* SecKeyInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecKeyInternal.h; sourceTree = ""; }; - 18AD563F14CB6EB9008233F2 /* SecKeyPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecKeyPriv.h; sourceTree = ""; }; - 18AD564014CB6EB9008233F2 /* SecPBKDF.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecPBKDF.c; sourceTree = ""; }; - 18AD564114CB6EB9008233F2 /* SecPBKDF.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecPBKDF.h; sourceTree = ""; }; - 18AD564214CB6EB9008233F2 /* SecPolicy.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecPolicy.c; sourceTree = ""; }; - 18AD564314CB6EB9008233F2 /* SecPolicy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecPolicy.h; sourceTree = ""; }; - 18AD564414CB6EB9008233F2 /* SecPolicyInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecPolicyInternal.h; sourceTree = ""; }; - 18AD564514CB6EB9008233F2 /* SecPolicyPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecPolicyPriv.h; sourceTree = ""; }; - 18AD564614CB6EB9008233F2 /* SecRandom.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecRandom.h; sourceTree = ""; }; - 18AD564714CB6EB9008233F2 /* SecRSAKey.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecRSAKey.c; sourceTree = ""; }; - 18AD564814CB6EB9008233F2 /* SecRSAKey.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecRSAKey.h; sourceTree = ""; }; - 18AD564914CB6EB9008233F2 /* SecRSAKeyPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecRSAKeyPriv.h; sourceTree = ""; }; - 18AD564A14CB6EB9008233F2 /* SecSCEP.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecSCEP.c; sourceTree = ""; }; - 18AD564B14CB6EB9008233F2 /* SecSCEP.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecSCEP.h; sourceTree = ""; }; - 18AD564C14CB6EB9008233F2 /* SecTrust.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecTrust.c; sourceTree = ""; }; - 18AD564D14CB6EB9008233F2 /* SecTrust.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecTrust.h; sourceTree = ""; }; - 18AD564E14CB6EB9008233F2 /* SecTrustPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecTrustPriv.h; sourceTree = ""; }; - 18AD564F14CB6EB9008233F2 /* SecTrustSettings.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecTrustSettings.c; sourceTree = ""; }; - 18AD565014CB6EB9008233F2 /* SecTrustSettings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecTrustSettings.h; sourceTree = ""; }; - 18AD565114CB6EB9008233F2 /* SecTrustSettingsPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecTrustSettingsPriv.h; sourceTree = ""; }; - 18AD565214CB6EB9008233F2 /* SecTrustStore.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecTrustStore.c; sourceTree = ""; }; - 18AD565314CB6EB9008233F2 /* SecTrustStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecTrustStore.h; sourceTree = ""; }; - 18AD565414CB6EB9008233F2 /* Security.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Security.h; sourceTree = ""; }; - 18AD565514CB6EB9008233F2 /* vmdh.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = vmdh.c; sourceTree = ""; }; - 18AD565614CB6EB9008233F2 /* vmdh.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = vmdh.h; sourceTree = ""; }; - 18AD565814CB6F79008233F2 /* SecItemServer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecItemServer.h; sourceTree = ""; }; - 18AD565914CB6F79008233F2 /* SecOCSPCache.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecOCSPCache.c; sourceTree = ""; }; - 18AD565A14CB6F79008233F2 /* SecOCSPCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecOCSPCache.h; sourceTree = ""; }; - 18AD565B14CB6F79008233F2 /* SecOCSPRequest.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecOCSPRequest.c; sourceTree = ""; }; - 18AD565C14CB6F79008233F2 /* SecOCSPRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecOCSPRequest.h; sourceTree = ""; }; - 18AD565D14CB6F79008233F2 /* SecOCSPResponse.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecOCSPResponse.c; sourceTree = ""; }; - 18AD565E14CB6F79008233F2 /* SecOCSPResponse.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecOCSPResponse.h; sourceTree = ""; }; - 18AD565F14CB6F79008233F2 /* SecPolicyServer.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecPolicyServer.c; sourceTree = ""; }; - 18AD566014CB6F79008233F2 /* SecPolicyServer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecPolicyServer.h; sourceTree = ""; }; - 18AD566114CB6F79008233F2 /* SecTrustServer.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecTrustServer.c; sourceTree = ""; }; - 18AD566214CB6F79008233F2 /* SecTrustServer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecTrustServer.h; sourceTree = ""; }; - 18AD566314CB6F79008233F2 /* SecTrustStoreServer.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecTrustStoreServer.c; sourceTree = ""; }; - 18AD566414CB6F79008233F2 /* SecTrustStoreServer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecTrustStoreServer.h; sourceTree = ""; }; - 18AD566514CB6F79008233F2 /* spi.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = spi.c; sourceTree = ""; }; - 18AD566614CB6F79008233F2 /* spi.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = spi.h; sourceTree = ""; }; - 18AD567D14CB865E008233F2 /* asynchttp.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = asynchttp.c; sourceTree = ""; }; - 18AD567E14CB865E008233F2 /* asynchttp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = asynchttp.h; sourceTree = ""; }; - 18AD567F14CB865E008233F2 /* entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = ""; }; - 18AD568214CB865E008233F2 /* policytree.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = policytree.c; sourceTree = ""; }; - 18AD568314CB865E008233F2 /* policytree.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = policytree.h; sourceTree = ""; }; - 18AD568414CB865E008233F2 /* SecCAIssuerCache.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecCAIssuerCache.c; sourceTree = ""; }; - 18AD568514CB865E008233F2 /* SecCAIssuerCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecCAIssuerCache.h; sourceTree = ""; }; - 18AD568614CB865E008233F2 /* SecCAIssuerRequest.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecCAIssuerRequest.c; sourceTree = ""; }; - 18AD568714CB865E008233F2 /* SecCAIssuerRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecCAIssuerRequest.h; sourceTree = ""; }; - 18AD568814CB865E008233F2 /* SecItemServer.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = SecItemServer.c; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.c; }; - 18D4043514CE0CF300A2BE4E /* libsecurity.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurity.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 18D4056214CE53C200A2BE4E /* libsecurityd.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurityd.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 4802A59516D711060059E5B9 /* SOSUserKeygen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSUserKeygen.c; sourceTree = ""; }; - 4802A59716D711190059E5B9 /* SOSUserKeygen.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSUserKeygen.h; sourceTree = ""; }; - 485835871779013E0050F074 /* SOSPeerInfoInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSPeerInfoInternal.h; sourceTree = ""; }; - 486C6C671795F20E00387075 /* secd-61-account-leave-not-in-kansas-anymore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-61-account-leave-not-in-kansas-anymore.c"; sourceTree = ""; }; - 4882C516177521AE0095D04B /* secd-58-password-change.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-58-password-change.c"; sourceTree = ""; }; - 488902EB16C2F88400F119FF /* SOSCoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSCoder.c; sourceTree = ""; }; - 488902ED16C2F89700F119FF /* SOSCoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSCoder.h; sourceTree = ""; }; - 4898223917BDB277003BEF32 /* secd-52-account-changed.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-52-account-changed.c"; sourceTree = ""; }; - 48CE733D1731C49A004C2946 /* sc-130-resignationticket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-130-resignationticket.c"; sourceTree = ""; }; - 48E928C4179DD05500A7F755 /* secd-51-account-inflate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-51-account-inflate.c"; sourceTree = ""; }; - 48F32D7D1777AFA3001B84BA /* secd-59-account-cleanup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-59-account-cleanup.c"; sourceTree = ""; }; - 4A5CCA4F15ACEFA500702357 /* libSecOtrOSX.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSecOtrOSX.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 4A824B03158FF07000F932C0 /* libSecurityRegressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSecurityRegressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 4A971682158FDEB800D439B7 /* SecOTR.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOTR.h; sourceTree = ""; }; - 4A971683158FDEB800D439B7 /* SecOTRDHKey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SecOTRDHKey.c; path = ../../../SecOTRDHKey.c; sourceTree = ""; }; - 4A971684158FDEB800D439B7 /* SecOTRDHKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOTRDHKey.h; sourceTree = ""; }; - 4A971685158FDEB800D439B7 /* SecOTRErrors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOTRErrors.h; sourceTree = ""; }; - 4A971686158FDEB800D439B7 /* SecOTRFullIdentity.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecOTRFullIdentity.c; sourceTree = ""; }; - 4A971687158FDEB800D439B7 /* SecOTRIdentityPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOTRIdentityPriv.h; sourceTree = ""; }; - 4A971688158FDEB800D439B7 /* SecOTRMath.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecOTRMath.c; sourceTree = ""; }; - 4A971689158FDEB800D439B7 /* SecOTRMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOTRMath.h; sourceTree = ""; }; - 4A97168A158FDEB800D439B7 /* SecOTRMathPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOTRMathPrivate.h; sourceTree = ""; }; - 4A97168B158FDEB800D439B7 /* SecOTRPacketData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecOTRPacketData.c; sourceTree = ""; }; - 4A97168C158FDEB800D439B7 /* SecOTRPacketData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOTRPacketData.h; sourceTree = ""; }; - 4A97168D158FDEB800D439B7 /* SecOTRPackets.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecOTRPackets.c; sourceTree = ""; }; - 4A97168E158FDEB800D439B7 /* SecOTRPackets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOTRPackets.h; sourceTree = ""; }; - 4A97168F158FDEB800D439B7 /* SecOTRPublicIdentity.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecOTRPublicIdentity.c; sourceTree = ""; }; - 4A971690158FDEB800D439B7 /* SecOTRSession.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecOTRSession.c; sourceTree = ""; }; - 4A971691158FDEB800D439B7 /* SecOTRSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOTRSession.h; sourceTree = ""; }; - 4A971692158FDEB800D439B7 /* SecOTRSessionAKE.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecOTRSessionAKE.c; sourceTree = ""; }; - 4A971693158FDEB800D439B7 /* SecOTRSessionPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOTRSessionPriv.h; sourceTree = ""; }; - 4A971694158FDEB800D439B7 /* SecOTRUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecOTRUtils.c; sourceTree = ""; }; - 4C143CDD164D8EF5003035A3 /* sd-70-engine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sd-70-engine.c"; sourceTree = ""; }; - 4C1C452614EB27F50018B1D9 /* SOSTransport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSTransport.c; sourceTree = ""; }; - 4C1C452914EB28260018B1D9 /* SOSTransport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransport.h; sourceTree = ""; }; - 4C2C8C3C17AB374700C24C13 /* si-12-item-stress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-12-item-stress.c"; sourceTree = ""; }; - 4C4B15931655ED9000734590 /* SecDbItem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecDbItem.c; sourceTree = ""; }; - 4C4B15951655EDA700734590 /* SecDbItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecDbItem.h; sourceTree = ""; }; - 4C4EBD531610D7D8007D06A5 /* sc-75-circle-engine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-75-circle-engine.c"; sourceTree = ""; }; - 4C5EA365164C791400A136B8 /* lib-arc-only.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "lib-arc-only.xcconfig"; sourceTree = ""; }; - 4C5F2E35162DE84E00AF8346 /* SOSTestTransport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSTestTransport.h; sourceTree = ""; }; - 4C5F2E36162DE87F00AF8346 /* SOSTestTransport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSTestTransport.c; sourceTree = ""; }; - 4C6ED19115CB0E26004379B7 /* sc-60-peer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-60-peer.c"; sourceTree = ""; }; - 4C6ED19415CB0E43004379B7 /* sc-70-engine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-70-engine.c"; sourceTree = ""; }; - 4C8940DA166EA8CF00241770 /* osxshim.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = osxshim.c; sourceTree = ""; }; - 4C9DC91915B602760036D941 /* SOSEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSEngine.h; sourceTree = ""; }; - 4C9DC91C15B602910036D941 /* SOSEngine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSEngine.c; sourceTree = ""; }; - 4CB8A83716164B7700B52EC7 /* SOSTestDataSource.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSTestDataSource.c; sourceTree = ""; }; - 4CB8A83916164B8C00B52EC7 /* SOSTestDataSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSTestDataSource.h; sourceTree = ""; }; - 4CC929AD15A3957800C6D578 /* SOSAccount.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccount.c; sourceTree = ""; }; - 4CC929AE15A3957800C6D578 /* SOSAccount.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSAccount.h; sourceTree = ""; }; - 4CC929AF15A3957800C6D578 /* SOSCircle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSCircle.c; sourceTree = ""; }; - 4CC929B015A3957800C6D578 /* SOSCircle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSCircle.h; sourceTree = ""; }; - 4CC929B115A3957800C6D578 /* SOSPeer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSPeer.c; sourceTree = ""; }; - 4CC929B215A3957800C6D578 /* SOSPeer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSPeer.h; sourceTree = ""; }; - 4CC92A0F15A3ABD400C6D578 /* pbkdf2-00-hmac-sha1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "pbkdf2-00-hmac-sha1.c"; sourceTree = ""; }; - 4CC92A1015A3ABD400C6D578 /* spbkdf-00-hmac-sha1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "spbkdf-00-hmac-sha1.c"; sourceTree = ""; }; - 4CC92A1215A3ABD400C6D578 /* otr-00-identity.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "otr-00-identity.c"; sourceTree = ""; }; - 4CC92A1315A3ABD400C6D578 /* otr-30-negotiation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "otr-30-negotiation.c"; sourceTree = ""; }; - 4CC92A1415A3ABD400C6D578 /* otr-otrdh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "otr-otrdh.c"; sourceTree = ""; }; - 4CC92A1515A3ABD400C6D578 /* otr-packetdata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "otr-packetdata.c"; sourceTree = ""; }; - 4CC92A1715A3ABD400C6D578 /* si-00-find-nothing.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-00-find-nothing.c"; sourceTree = ""; }; - 4CC92A1815A3ABD400C6D578 /* si-05-add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-05-add.c"; sourceTree = ""; }; - 4CC92A1915A3ABD400C6D578 /* si-10-find-internet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-10-find-internet.c"; sourceTree = ""; }; - 4CC92A1A15A3ABD400C6D578 /* si-11-update-data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-11-update-data.c"; sourceTree = ""; }; - 4CC92A1B15A3ABD400C6D578 /* si-14-dateparse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-14-dateparse.c"; sourceTree = ""; }; - 4CC92A1C15A3ABD400C6D578 /* si-15-certificate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-15-certificate.c"; sourceTree = ""; }; - 4CC92A1D15A3ABD400C6D578 /* si-16-ec-certificate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-16-ec-certificate.c"; sourceTree = ""; }; - 4CC92A1E15A3ABD400C6D578 /* si-20-sectrust-activation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-20-sectrust-activation.c"; sourceTree = ""; }; - 4CC92A1F15A3ABD400C6D578 /* si-20-sectrust.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-20-sectrust.c"; sourceTree = ""; }; - 4CC92A2015A3ABD400C6D578 /* si-21-sectrust-asr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-21-sectrust-asr.c"; sourceTree = ""; }; - 4CC92A2115A3ABD400C6D578 /* si-22-sectrust-iap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-22-sectrust-iap.c"; sourceTree = ""; }; - 4CC92A2215A3ABD400C6D578 /* si-23-sectrust-ocsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-23-sectrust-ocsp.c"; sourceTree = ""; }; - 4CC92A2315A3ABD400C6D578 /* si-24-sectrust-appleid.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-appleid.c"; sourceTree = ""; }; - 4CC92A2415A3ABD400C6D578 /* si-24-sectrust-digicert-malaysia.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-digicert-malaysia.c"; sourceTree = ""; }; - 4CC92A2515A3ABD400C6D578 /* si-24-sectrust-diginotar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-diginotar.c"; sourceTree = ""; }; - 4CC92A2615A3ABD400C6D578 /* si-24-sectrust-itms.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-itms.c"; sourceTree = ""; }; - 4CC92A2715A3ABD400C6D578 /* si-24-sectrust-mobileasset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-mobileasset.c"; sourceTree = ""; }; - 4CC92A2815A3ABD400C6D578 /* si-24-sectrust-nist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-nist.c"; sourceTree = ""; }; - 4CC92A2915A3ABD400C6D578 /* si-24-sectrust-otatasking.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-otatasking.c"; sourceTree = ""; }; - 4CC92A2A15A3ABD400C6D578 /* si-24-sectrust-shoebox.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-shoebox.c"; sourceTree = ""; }; - 4CC92A2B15A3ABD400C6D578 /* si-25-sectrust-ipsec-eap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-25-sectrust-ipsec-eap.c"; sourceTree = ""; }; - 4CC92A2C15A3ABD400C6D578 /* si-26-applicationsigning.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-26-applicationsigning.c"; sourceTree = ""; }; - 4CC92A2D15A3ABD400C6D578 /* si-27-sectrust-exceptions.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-27-sectrust-exceptions.c"; sourceTree = ""; }; - 4CC92A2E15A3ABD400C6D578 /* si-28-sectrustsettings.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-28-sectrustsettings.c"; sourceTree = ""; }; - 4CC92A2F15A3ABD400C6D578 /* si-29-sectrust-codesigning.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-29-sectrust-codesigning.c"; sourceTree = ""; }; - 4CC92A3015A3ABD400C6D578 /* si-30-keychain-upgrade.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-30-keychain-upgrade.c"; sourceTree = ""; }; - 4CC92A3115A3ABD400C6D578 /* si-31-keychain-bad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-31-keychain-bad.c"; sourceTree = ""; }; - 4CC92A3215A3ABD400C6D578 /* si-31-keychain-unreadable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-31-keychain-unreadable.c"; sourceTree = ""; }; - 4CC92A3415A3ABD400C6D578 /* si-33-keychain-backup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-33-keychain-backup.c"; sourceTree = ""; }; - 4CC92A3515A3ABD400C6D578 /* si-40-seckey-custom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-40-seckey-custom.c"; sourceTree = ""; }; - 4CC92A3615A3ABD400C6D578 /* si-40-seckey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-40-seckey.c"; sourceTree = ""; }; - 4CC92A3715A3ABD400C6D578 /* si-41-sececkey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-41-sececkey.c"; sourceTree = ""; }; - 4CC92A3815A3ABD400C6D578 /* si-42-identity.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-42-identity.c"; sourceTree = ""; }; - 4CC92A3915A3ABD400C6D578 /* si-43-persistent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-43-persistent.c"; sourceTree = ""; }; - 4CC92A3A15A3ABD400C6D578 /* si-50-secrandom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-50-secrandom.c"; sourceTree = ""; }; - 4CC92A3B15A3ABD400C6D578 /* si-60-cms.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-60-cms.c"; sourceTree = ""; }; - 4CC92A3C15A3ABD400C6D578 /* si-61-pkcs12.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-61-pkcs12.c"; sourceTree = ""; }; - 4CC92A3D15A3ABD400C6D578 /* si-62-csr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-62-csr.c"; sourceTree = ""; }; - 4CC92A3F15A3ABD400C6D578 /* getcacert-mdes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "getcacert-mdes.h"; sourceTree = ""; }; - 4CC92A4015A3ABD400C6D578 /* getcacert-mdesqa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "getcacert-mdesqa.h"; sourceTree = ""; }; - 4CC92A4115A3ABD400C6D578 /* si-63-scep.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-63-scep.c"; sourceTree = ""; }; - 4CC92A4215A3ABD400C6D578 /* si-63-scep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "si-63-scep.h"; sourceTree = ""; }; - 4CC92A4415A3ABD400C6D578 /* attached_no_data_signed_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = attached_no_data_signed_data.h; sourceTree = ""; }; - 4CC92A4515A3ABD400C6D578 /* attached_signed_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = attached_signed_data.h; sourceTree = ""; }; - 4CC92A4615A3ABD400C6D578 /* detached_content.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = detached_content.h; sourceTree = ""; }; - 4CC92A4715A3ABD400C6D578 /* detached_signed_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = detached_signed_data.h; sourceTree = ""; }; - 4CC92A4815A3ABD400C6D578 /* privkey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = privkey.h; sourceTree = ""; }; - 4CC92A4915A3ABD400C6D578 /* signer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = signer.h; sourceTree = ""; }; - 4CC92A4A15A3ABD400C6D578 /* si-64-ossl-cms.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-64-ossl-cms.c"; sourceTree = ""; }; - 4CC92A4B15A3ABD400C6D578 /* si-65-cms-cert-policy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-65-cms-cert-policy.c"; sourceTree = ""; }; - 4CC92A4D15A3ABD400C6D578 /* signed-receipt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "signed-receipt.h"; sourceTree = ""; }; - 4CC92A4E15A3ABD400C6D578 /* si-66-smime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-66-smime.c"; sourceTree = ""; }; - 4CC92A5015A3ABD400C6D578 /* Global Trustee.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Global Trustee.cer.h"; sourceTree = ""; }; - 4CC92A5115A3ABD400C6D578 /* UTN-USERFirst-Hardware.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UTN-USERFirst-Hardware.cer.h"; sourceTree = ""; }; - 4CC92A5215A3ABD400C6D578 /* addons.mozilla.org.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = addons.mozilla.org.cer.h; sourceTree = ""; }; - 4CC92A5315A3ABD400C6D578 /* login.live.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.live.com.cer.h; sourceTree = ""; }; - 4CC92A5415A3ABD400C6D578 /* login.skype.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.skype.com.cer.h; sourceTree = ""; }; - 4CC92A5515A3ABD400C6D578 /* login.yahoo.com.1.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.yahoo.com.1.cer.h; sourceTree = ""; }; - 4CC92A5615A3ABD400C6D578 /* login.yahoo.com.2.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.yahoo.com.2.cer.h; sourceTree = ""; }; - 4CC92A5715A3ABD400C6D578 /* login.yahoo.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.yahoo.com.cer.h; sourceTree = ""; }; - 4CC92A5815A3ABD400C6D578 /* mail.google.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mail.google.com.cer.h; sourceTree = ""; }; - 4CC92A5915A3ABD400C6D578 /* www.google.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = www.google.com.cer.h; sourceTree = ""; }; - 4CC92A5A15A3ABD400C6D578 /* si-67-sectrust-blacklist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-67-sectrust-blacklist.c"; sourceTree = ""; }; - 4CC92A5C15A3ABD400C6D578 /* vmdh-40.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "vmdh-40.c"; sourceTree = ""; }; - 4CC92A5D15A3ABD400C6D578 /* vmdh-41-example.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "vmdh-41-example.c"; sourceTree = ""; }; - 4CC92A5E15A3ABD400C6D578 /* vmdh-42-example2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "vmdh-42-example2.c"; sourceTree = ""; }; - 4CC92AAC15A3AC4600C6D578 /* sd-10-policytree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sd-10-policytree.c"; sourceTree = ""; }; - 4CC92AAE15A3ACCE00C6D578 /* securityd_regressions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = securityd_regressions.h; sourceTree = ""; }; - 4CC92AAF15A3ACE600C6D578 /* SOSCircle_regressions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSCircle_regressions.h; sourceTree = ""; }; - 4CC92AB015A3AD0000C6D578 /* Security_regressions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Security_regressions.h; path = Regressions/Security_regressions.h; sourceTree = ""; }; - 4CC92B1415A3BC6B00C6D578 /* libsecuritydRegressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecuritydRegressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 4CD1897B169F835400BC96B8 /* print_cert.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = print_cert.c; sourceTree = ""; }; - 4CD1897C169F835400BC96B8 /* print_cert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = print_cert.h; sourceTree = ""; }; - 521C0A7315F908A700604B61 /* sc-90-ckdclient.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-90-ckdclient.c"; sourceTree = ""; }; - 521C0B9815FA5C4A00604B61 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 521C0BA615FA5D7400604B61 /* cloudkeychain.entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = cloudkeychain.entitlements.plist; path = SOSCircle/CloudKeychainProxy/cloudkeychain.entitlements.plist; sourceTree = SOURCE_ROOT; }; - 521C0BAD15FA5DA800604B61 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = InfoPlist.strings; sourceTree = ""; }; - 521C0BAF15FA5E3F00604B61 /* CKDKVSProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = CKDKVSProxy.h; path = SOSCircle/CloudKeychainProxy/CKDKVSProxy.h; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - 521C0BB015FA5E3F00604B61 /* CKDKVSProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CKDKVSProxy.m; path = SOSCircle/CloudKeychainProxy/CKDKVSProxy.m; sourceTree = SOURCE_ROOT; }; - 521C0BB115FA5E3F00604B61 /* CKDPersistentState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CKDPersistentState.h; path = SOSCircle/CloudKeychainProxy/CKDPersistentState.h; sourceTree = SOURCE_ROOT; }; - 521C0BB215FA5E3F00604B61 /* CKDPersistentState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CKDPersistentState.m; path = SOSCircle/CloudKeychainProxy/CKDPersistentState.m; sourceTree = SOURCE_ROOT; }; - 521C0BB315FA5E3F00604B61 /* cloudkeychainproxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = cloudkeychainproxy.m; path = SOSCircle/CloudKeychainProxy/cloudkeychainproxy.m; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; - 521C0C8615FEB03300604B61 /* sc-120-cloudcircle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-120-cloudcircle.c"; sourceTree = ""; }; - 521C0CD515FF9B3300604B61 /* SOSRegressionUtilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSRegressionUtilities.c; sourceTree = ""; }; - 521C0CD815FF9B4B00604B61 /* SOSRegressionUtilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSRegressionUtilities.h; sourceTree = ""; }; - 521C0CD915FFA05000604B61 /* CKDKeyValueStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = CKDKeyValueStore.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - 521C0CDA15FFA05000604B61 /* CKDKeyValueStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKDKeyValueStore.m; sourceTree = ""; }; - 521C685C1614A6E100E31C3E /* SOSCloudKeychainClient.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = SOSCloudKeychainClient.c; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.c; }; - 521C685D1614A6E100E31C3E /* SOSCloudKeychainClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = SOSCloudKeychainClient.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - 521C691E16164B9900E31C3E /* sc-95-ckd2client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-95-ckd2client.c"; sourceTree = ""; }; - 522B0ED11648809300A4675D /* sc-103-syncupdate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-103-syncupdate.c"; sourceTree = ""; }; - 522B0ED31649A68E00A4675D /* MobileKeyBag.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileKeyBag.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.Internal.sdk/System/Library/PrivateFrameworks/MobileKeyBag.framework; sourceTree = DEVELOPER_DIR; }; - 5253946016608F6800BA9687 /* sc-51-persistentEC.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-51-persistentEC.c"; sourceTree = ""; }; - 526CBA5116079FB4008DF7C8 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = "../../build/Products/Debug-iphoneos/Security.framework"; sourceTree = ""; }; - 5272501916838BB20029AADD /* CloudKeychainProxy.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = CloudKeychainProxy.1; sourceTree = ""; }; - 52840280163F2B060035F320 /* sc-102-cfusernotification.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-102-cfusernotification.c"; sourceTree = ""; }; - 52840291164050C80035F320 /* CKDUserInteraction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CKDUserInteraction.h; path = SOSCircle/CloudKeychainProxy/CKDUserInteraction.h; sourceTree = SOURCE_ROOT; }; - 52840292164050C80035F320 /* CKDUserInteraction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CKDUserInteraction.m; path = SOSCircle/CloudKeychainProxy/CKDUserInteraction.m; sourceTree = SOURCE_ROOT; }; - 528402A0164445760035F320 /* libCloudKeychainProxy.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCloudKeychainProxy.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 52849FC2164498C9005CDF23 /* SOSARCDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSARCDefines.h; path = SOSCircle/SOSARCDefines.h; sourceTree = SOURCE_ROOT; }; - 52AF7082163D9AA20092A7ED /* sc-101-accountsync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-101-accountsync.c"; sourceTree = ""; }; - 52C3D18E169A53150091D9D3 /* ckdmain.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ckdmain.m; path = SOSCircle/CloudKeychainProxy/ckdmain.m; sourceTree = SOURCE_ROOT; }; - 52D0F026169CA72800F07D79 /* SecOnOSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOnOSX.h; sourceTree = ""; }; - 52DD7069160CD40B0027A346 /* libutilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libutilities.a; path = ../../build/Release/libutilities.a; sourceTree = ""; }; - 52DEE9E1162DC8F1002F3BCD /* sc-100-devicecircle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-100-devicecircle.c"; sourceTree = ""; }; - 5DE4A7BC17441CCD0036339E /* si-71-mobile-store-policy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-71-mobile-store-policy.c"; sourceTree = ""; }; - 724D7363177A13A500FA10A1 /* AppleBaselineEscrowCertificates.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppleBaselineEscrowCertificates.h; sourceTree = ""; }; - 7255A46B1783333D006A8B9A /* si-74-OTAPKISigner.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-74-OTAPKISigner.c"; sourceTree = ""; }; - 7255F91317A973D5004A9F38 /* si-75-AppleIDRecordSigning.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-75-AppleIDRecordSigning.c"; sourceTree = ""; }; - 72E2DC0616BC47C800E7B236 /* OTATrustUtilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = OTATrustUtilities.c; sourceTree = ""; }; - 72E2DC0716BC47C800E7B236 /* OTATrustUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OTATrustUtilities.h; sourceTree = ""; }; - BE62D75F1747FF3E001EAA9D /* si-72-syncableitems.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-72-syncableitems.c"; sourceTree = ""; }; - BE62D7611747FF51001EAA9D /* si-70-sectrust-unified.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-70-sectrust-unified.c"; sourceTree = ""; }; - CDA7729616B899F10069434D /* si-69-keydesc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-69-keydesc.c"; sourceTree = ""; }; - CDC765C01729A72800721712 /* SecPasswordGenerate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecPasswordGenerate.c; sourceTree = ""; }; - CDC765C11729A72800721712 /* SecPasswordGenerate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecPasswordGenerate.h; sourceTree = ""; }; - CDD565A1173193AC00B6B074 /* si-73-secpasswordgenerate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-73-secpasswordgenerate.c"; sourceTree = ""; }; - E702E75614E1F3EA00CDE635 /* libSecureObjectSync.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSecureObjectSync.a; sourceTree = BUILT_PRODUCTS_DIR; }; - E702E77814E1F48800CDE635 /* libSOSRegressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSOSRegressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; - E703811114E1FEE4007CB458 /* SOSCloudCircle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSCloudCircle.h; sourceTree = ""; }; - E71049F2169E023B00DB0045 /* libSecurityTool.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSecurityTool.a; sourceTree = BUILT_PRODUCTS_DIR; }; - E71049FE169E036E00DB0045 /* security.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = security.1; sourceTree = ""; }; - E71049FF169E036E00DB0045 /* SecurityTool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecurityTool.c; sourceTree = ""; }; - E7104A00169E036E00DB0045 /* SecurityTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecurityTool.h; sourceTree = ""; }; - E7104A0D169E1C1600DB0045 /* tool_errors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tool_errors.h; sourceTree = ""; }; - E7104A1D169E216E00DB0045 /* libSecurityCommands.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSecurityCommands.a; sourceTree = BUILT_PRODUCTS_DIR; }; - E7217B1715F80E0F00D26031 /* SOSCloudCircle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = SOSCloudCircle.c; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.c; }; - E7217B2515F8131A00D26031 /* SOSCloudKeychainConstants.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = SOSCloudKeychainConstants.c; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.c; }; - E7217B2615F8131A00D26031 /* SOSCloudKeychainConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSCloudKeychainConstants.h; sourceTree = ""; }; - E7295C6714E3571A007FBB20 /* Empty.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = Empty.c; sourceTree = ""; }; - E748744415A61AF800624935 /* si-68-secmatchissuer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-68-secmatchissuer.c"; sourceTree = ""; }; - E763D6221624E2670038477D /* sc-20-keynames.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-20-keynames.c"; sourceTree = ""; }; - E777C6B015B4DDF2004044A8 /* sc-40-circle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-40-circle.c"; sourceTree = ""; }; - E777C71B15B73F59004044A8 /* SOSInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSInternal.h; sourceTree = ""; }; - E777C71D15B73F9E004044A8 /* SOSInternal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSInternal.c; sourceTree = ""; }; - E777C72415B87528004044A8 /* SOSPeerInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSPeerInfo.h; sourceTree = ""; }; - E777C72515B87544004044A8 /* SOSPeerInfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSPeerInfo.c; sourceTree = ""; }; - E777C72815B9C9F0004044A8 /* sc-30-peerinfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-30-peerinfo.c"; sourceTree = ""; }; - E790C0F4169E3D7200E0C0C9 /* SOSCommands.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSCommands.h; sourceTree = ""; }; - E790C108169E4E7900E0C0C9 /* builtin_commands.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = builtin_commands.h; sourceTree = ""; }; - E790C109169E4FD200E0C0C9 /* digest_calc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = digest_calc.c; sourceTree = ""; }; - E790C10E169E53DF00E0C0C9 /* leaks.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = leaks.c; sourceTree = ""; }; - E790C10F169E53DF00E0C0C9 /* leaks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = leaks.h; sourceTree = ""; }; - E790C136169E5C6200E0C0C9 /* add_internet_password.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = add_internet_password.c; sourceTree = ""; }; - E790C137169E5C6200E0C0C9 /* codesign.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = codesign.c; sourceTree = ""; }; - E790C138169E5C6200E0C0C9 /* keychain_add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keychain_add.c; sourceTree = ""; }; - E790C139169E5C6200E0C0C9 /* keychain_find.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keychain_find.c; sourceTree = ""; }; - E790C13A169E5C6200E0C0C9 /* pkcs12_util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkcs12_util.c; sourceTree = ""; }; - E790C13D169E5C6200E0C0C9 /* scep.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scep.c; sourceTree = ""; }; - E790C13E169E5C6200E0C0C9 /* SecurityCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecurityCommands.h; sourceTree = ""; }; - E790C13F169E5C6200E0C0C9 /* show_certificates.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = show_certificates.c; sourceTree = ""; }; - E790C140169E5C6200E0C0C9 /* spc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = spc.c; sourceTree = ""; }; - E79277E1163B110A0096F3E2 /* SOSFullPeerInfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSFullPeerInfo.c; sourceTree = ""; }; - E79277E2163B110A0096F3E2 /* SOSFullPeerInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSFullPeerInfo.h; sourceTree = ""; }; - E79D62B9176798BF005A9743 /* secd-50-account.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = "secd-50-account.c"; path = "securityd/Regressions/secd-50-account.c"; sourceTree = SOURCE_ROOT; }; - E79D62BE1767A547005A9743 /* SecdTestKeychainUtilities.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecdTestKeychainUtilities.c; sourceTree = ""; }; - E79D62BF1767A55F005A9743 /* SecdTestKeychainUtilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecdTestKeychainUtilities.h; sourceTree = ""; }; - E7A10FAA1771245D00C4602F /* SOSAccountTesting.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSAccountTesting.h; sourceTree = ""; }; - E7A10FAB1771246A00C4602F /* secd-55-account-circle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-55-account-circle.c"; sourceTree = ""; }; - E7A10FAD1771249C00C4602F /* secd-57-account-leave.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-57-account-leave.c"; sourceTree = ""; }; - E7B00701170B58BD00B27966 /* SecExports.exp-in */ = {isa = PBXFileReference; lastKnownFileType = text; path = "SecExports.exp-in"; sourceTree = ""; }; - E7B00702170B5FE100B27966 /* SOSExports.exp-in */ = {isa = PBXFileReference; lastKnownFileType = text; path = "SOSExports.exp-in"; sourceTree = ""; }; - E7B01B5A16532507000485F1 /* SOSCloudCircleInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = SOSCloudCircleInternal.h; sourceTree = ""; }; - E7B01B661655CC99000485F1 /* SOSCloudCircleServer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSCloudCircleServer.h; sourceTree = ""; }; - E7B01B671655CCA6000485F1 /* SOSCloudCircleServer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSCloudCircleServer.c; sourceTree = ""; }; - E7B01B8816572579000485F1 /* SecuritydXPC.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecuritydXPC.c; sourceTree = ""; }; - E7B01B8A1657259F000485F1 /* SecuritydXPC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecuritydXPC.h; sourceTree = ""; }; - E7BE10A5167AB2BF00D2A178 /* sc-41-cloudcircle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-41-cloudcircle.c"; sourceTree = ""; }; - E7F0D3E9177BBE35001ACBC1 /* secd-55-account-incompatibility.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-55-account-incompatibility.c"; sourceTree = ""; }; - E7F18554177A44E000177B23 /* secd-60-account-cloud-identity.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-60-account-cloud-identity.c"; sourceTree = ""; }; - E7F18556177A502900177B23 /* secd-56-account-apply.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-56-account-apply.c"; sourceTree = ""; }; - E7FEFB8C169E363300E18152 /* libSOSCommands.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSOSCommands.a; sourceTree = BUILT_PRODUCTS_DIR; }; - E7FEFB90169E36D800E18152 /* keychain_sync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keychain_sync.c; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 0C0BDB59175687EC00BC1A7E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 18270F5214CF651900B05E7F /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 186CDD0C14CA116C00AF9171 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 18D4043214CE0CF300A2BE4E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 18D4055F14CE53C200A2BE4E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4A5CCA4C15ACEFA500702357 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4A824AFE158FF07000F932C0 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4CC92AFA15A3BC6B00C6D578 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 5284029D164445760035F320 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E702E74F14E1F3EA00CDE635 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E702E77114E1F48800CDE635 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 4AD6F6F21651C86200DB4CE6 /* libSecureObjectSync.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E71049EF169E023B00DB0045 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - E71049F3169E023B00DB0045 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E7104A17169E216E00DB0045 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - E7104A18169E216E00DB0045 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E7FEFB86169E363300E18152 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - E7FEFB87169E363300E18152 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 18270C9614CF1AAD00B05E7F /* config */ = { - isa = PBXGroup; - children = ( - 18270C9714CF1AAD00B05E7F /* base.xcconfig */, - 18270C9814CF1AAD00B05E7F /* debug.xcconfig */, - 4C5EA365164C791400A136B8 /* lib-arc-only.xcconfig */, - 18270C9914CF1AAD00B05E7F /* lib.xcconfig */, - 18270C9A14CF1AAD00B05E7F /* release.xcconfig */, - ); - path = config; - sourceTree = ""; - }; - 186CDD0414CA116C00AF9171 = { - isa = PBXGroup; - children = ( - 18270C9614CF1AAD00B05E7F /* config */, - 18AD565714CB6ECD008233F2 /* securityd */, - 186CDD1F14CA126D00AF9171 /* ipc */, - E7AC69CE14E1F78400CB09C1 /* SOSCircle */, - 186CDD3014CA159600AF9171 /* Security */, - E71049F4169E023B00DB0045 /* SecurityTool */, - 521C0B9715FA5C4900604B61 /* Frameworks */, - 186CDD1014CA116C00AF9171 /* Products */, - ); - sourceTree = ""; - }; - 186CDD1014CA116C00AF9171 /* Products */ = { - isa = PBXGroup; - children = ( - 186CDD0F14CA116C00AF9171 /* libSecItemShimOSX.a */, - 18D4043514CE0CF300A2BE4E /* libsecurity.a */, - 18D4056214CE53C200A2BE4E /* libsecurityd.a */, - 18270F5514CF651900B05E7F /* libsecipc_client.a */, - E702E75614E1F3EA00CDE635 /* libSecureObjectSync.a */, - E702E77814E1F48800CDE635 /* libSOSRegressions.a */, - 4A824B03158FF07000F932C0 /* libSecurityRegressions.a */, - 4CC92B1415A3BC6B00C6D578 /* libsecuritydRegressions.a */, - 4A5CCA4F15ACEFA500702357 /* libSecOtrOSX.a */, - 528402A0164445760035F320 /* libCloudKeychainProxy.a */, - E71049F2169E023B00DB0045 /* libSecurityTool.a */, - E7104A1D169E216E00DB0045 /* libSecurityCommands.a */, - E7FEFB8C169E363300E18152 /* libSOSCommands.a */, - 0C0BDB5F175687EC00BC1A7E /* libsecdRegressions.a */, - ); - name = Products; - sourceTree = ""; - }; - 186CDD1F14CA126D00AF9171 /* ipc */ = { - isa = PBXGroup; - children = ( - 18AD560614CB6E7A008233F2 /* client.c */, - 18AD560714CB6E7A008233F2 /* com.apple.securityd.plist */, - 18AD560814CB6E7A008233F2 /* securityd_client.h */, - 18AD560D14CB6E7A008233F2 /* server.c */, - ); - path = ipc; - sourceTree = ""; - }; - 186CDD3014CA159600AF9171 /* Security */ = { - isa = PBXGroup; - children = ( - E7104A0F169E1F0800DB0045 /* Tool */, - 4A824AFA158FF05900F932C0 /* Regressions */, - 52D0F026169CA72800F07D79 /* SecOnOSX.h */, - 4A971682158FDEB800D439B7 /* SecOTR.h */, - 4A971684158FDEB800D439B7 /* SecOTRDHKey.h */, - 4A971685158FDEB800D439B7 /* SecOTRErrors.h */, - 4A971686158FDEB800D439B7 /* SecOTRFullIdentity.c */, - 4A971687158FDEB800D439B7 /* SecOTRIdentityPriv.h */, - 4A971688158FDEB800D439B7 /* SecOTRMath.c */, - 4A971689158FDEB800D439B7 /* SecOTRMath.h */, - 4A97168A158FDEB800D439B7 /* SecOTRMathPrivate.h */, - 4A97168B158FDEB800D439B7 /* SecOTRPacketData.c */, - 4A97168C158FDEB800D439B7 /* SecOTRPacketData.h */, - 4A97168D158FDEB800D439B7 /* SecOTRPackets.c */, - 4A97168E158FDEB800D439B7 /* SecOTRPackets.h */, - 4A97168F158FDEB800D439B7 /* SecOTRPublicIdentity.c */, - 4A971690158FDEB800D439B7 /* SecOTRSession.c */, - 4A971691158FDEB800D439B7 /* SecOTRSession.h */, - 4A971692158FDEB800D439B7 /* SecOTRSessionAKE.c */, - 4A971693158FDEB800D439B7 /* SecOTRSessionPriv.h */, - 4A971694158FDEB800D439B7 /* SecOTRUtils.c */, - 18AD561514CB6EB9008233F2 /* certextensions.h */, - 18AD561614CB6EB9008233F2 /* p12import.c */, - 18AD561714CB6EB9008233F2 /* p12import.h */, - 18AD561814CB6EB9008233F2 /* p12pbegen.c */, - 18AD561914CB6EB9008233F2 /* p12pbegen.h */, - 18AD561A14CB6EB9008233F2 /* pbkdf2.c */, - 18AD561B14CB6EB9008233F2 /* pbkdf2.h */, - 18AD561C14CB6EB9008233F2 /* SecBase.h */, - 18AD561D14CB6EB9008233F2 /* SecBase64.c */, - 18AD561E14CB6EB9008233F2 /* SecBase64.h */, - 18AD561F14CB6EB9008233F2 /* SecBasePriv.h */, - 18AD562114CB6EB9008233F2 /* SecCertificate.h */, - 18AD562214CB6EB9008233F2 /* SecCertificateInternal.h */, - 18AD562314CB6EB9008233F2 /* SecCertificatePath.c */, - 18AD562414CB6EB9008233F2 /* SecCertificatePath.h */, - 18AD562514CB6EB9008233F2 /* SecCertificatePriv.h */, - 18AD562614CB6EB9008233F2 /* SecCertificateRequest.c */, - 18AD562714CB6EB9008233F2 /* SecCertificateRequest.h */, - 18AD562814CB6EB9008233F2 /* SecCMS.c */, - 18AD562914CB6EB9008233F2 /* SecCMS.h */, - 18AD562A14CB6EB9008233F2 /* SecDH.c */, - 18AD562B14CB6EB9008233F2 /* SecDH.h */, - 18AD562C14CB6EB9008233F2 /* SecECKey.c */, - 18AD562D14CB6EB9008233F2 /* SecECKey.h */, - 18AD562E14CB6EB9008233F2 /* SecFramework.c */, - 18AD562014CB6EB9008233F2 /* SecCertificate.c */, - 18AD562F14CB6EB9008233F2 /* SecFramework.h */, - 18AD563014CB6EB9008233F2 /* SecFrameworkStrings.h */, - 18AD563114CB6EB9008233F2 /* SecIdentity.c */, - 18AD563214CB6EB9008233F2 /* SecIdentity.h */, - 18AD563314CB6EB9008233F2 /* SecIdentityPriv.h */, - 18AD563414CB6EB9008233F2 /* SecImportExport.c */, - 18AD563514CB6EB9008233F2 /* SecImportExport.h */, - 18AD563614CB6EB9008233F2 /* SecInternal.h */, - 18AD563714CB6EB9008233F2 /* SecItem.c */, - 18AD563814CB6EB9008233F2 /* SecItem.h */, - 18AD563914CB6EB9008233F2 /* SecItemConstants.c */, - 18AD563A14CB6EB9008233F2 /* SecItemInternal.h */, - 18AD563B14CB6EB9008233F2 /* SecItemPriv.h */, - 18AD563C14CB6EB9008233F2 /* SecKey.c */, - 18AD563D14CB6EB9008233F2 /* SecKey.h */, - 18AD563E14CB6EB9008233F2 /* SecKeyInternal.h */, - 18AD563F14CB6EB9008233F2 /* SecKeyPriv.h */, - CDC765C01729A72800721712 /* SecPasswordGenerate.c */, - CDC765C11729A72800721712 /* SecPasswordGenerate.h */, - 18AD564014CB6EB9008233F2 /* SecPBKDF.c */, - 18AD564114CB6EB9008233F2 /* SecPBKDF.h */, - 18AD564214CB6EB9008233F2 /* SecPolicy.c */, - 18AD564314CB6EB9008233F2 /* SecPolicy.h */, - 18AD564414CB6EB9008233F2 /* SecPolicyInternal.h */, - 18AD564514CB6EB9008233F2 /* SecPolicyPriv.h */, - 18AD564614CB6EB9008233F2 /* SecRandom.h */, - 18AD564714CB6EB9008233F2 /* SecRSAKey.c */, - 18AD564814CB6EB9008233F2 /* SecRSAKey.h */, - 18AD564914CB6EB9008233F2 /* SecRSAKeyPriv.h */, - 18AD564A14CB6EB9008233F2 /* SecSCEP.c */, - 18AD564B14CB6EB9008233F2 /* SecSCEP.h */, - 18AD564C14CB6EB9008233F2 /* SecTrust.c */, - 18AD564D14CB6EB9008233F2 /* SecTrust.h */, - 18AD564E14CB6EB9008233F2 /* SecTrustPriv.h */, - 18AD564F14CB6EB9008233F2 /* SecTrustSettings.c */, - 18AD565014CB6EB9008233F2 /* SecTrustSettings.h */, - 18AD565114CB6EB9008233F2 /* SecTrustSettingsPriv.h */, - 18AD565214CB6EB9008233F2 /* SecTrustStore.c */, - 18AD565314CB6EB9008233F2 /* SecTrustStore.h */, - 18AD565414CB6EB9008233F2 /* Security.h */, - 18AD565514CB6EB9008233F2 /* vmdh.c */, - 18AD565614CB6EB9008233F2 /* vmdh.h */, - E7B01B8816572579000485F1 /* SecuritydXPC.c */, - E7B01B8A1657259F000485F1 /* SecuritydXPC.h */, - E7B00701170B58BD00B27966 /* SecExports.exp-in */, - 724D7363177A13A500FA10A1 /* AppleBaselineEscrowCertificates.h */, - ); - path = Security; - sourceTree = ""; - }; - 18AD565714CB6ECD008233F2 /* securityd */ = { - isa = PBXGroup; - children = ( - 4CC92AAB15A3AC4600C6D578 /* Regressions */, - 18AD567D14CB865E008233F2 /* asynchttp.c */, - 18AD567E14CB865E008233F2 /* asynchttp.h */, - 18AD567F14CB865E008233F2 /* entitlements.plist */, - 72E2DC0616BC47C800E7B236 /* OTATrustUtilities.c */, - 72E2DC0716BC47C800E7B236 /* OTATrustUtilities.h */, - 18AD568214CB865E008233F2 /* policytree.c */, - 18AD568314CB865E008233F2 /* policytree.h */, - 18AD568414CB865E008233F2 /* SecCAIssuerCache.c */, - 18AD568514CB865E008233F2 /* SecCAIssuerCache.h */, - 18AD568614CB865E008233F2 /* SecCAIssuerRequest.c */, - 18AD568714CB865E008233F2 /* SecCAIssuerRequest.h */, - 4C4B15931655ED9000734590 /* SecDbItem.c */, - 4C4B15951655EDA700734590 /* SecDbItem.h */, - 18AD568814CB865E008233F2 /* SecItemServer.c */, - 18AD565814CB6F79008233F2 /* SecItemServer.h */, - 18AD565914CB6F79008233F2 /* SecOCSPCache.c */, - 18AD565A14CB6F79008233F2 /* SecOCSPCache.h */, - 18AD565B14CB6F79008233F2 /* SecOCSPRequest.c */, - 18AD565C14CB6F79008233F2 /* SecOCSPRequest.h */, - 18AD565D14CB6F79008233F2 /* SecOCSPResponse.c */, - 18AD565E14CB6F79008233F2 /* SecOCSPResponse.h */, - 18AD565F14CB6F79008233F2 /* SecPolicyServer.c */, - 18AD566014CB6F79008233F2 /* SecPolicyServer.h */, - 18AD566114CB6F79008233F2 /* SecTrustServer.c */, - 18AD566214CB6F79008233F2 /* SecTrustServer.h */, - 18AD566314CB6F79008233F2 /* SecTrustStoreServer.c */, - 18AD566414CB6F79008233F2 /* SecTrustStoreServer.h */, - E7B01B671655CCA6000485F1 /* SOSCloudCircleServer.c */, - E7B01B661655CC99000485F1 /* SOSCloudCircleServer.h */, - 18AD566514CB6F79008233F2 /* spi.c */, - 18AD566614CB6F79008233F2 /* spi.h */, - ); - path = securityd; - sourceTree = ""; - }; - 4A824AFA158FF05900F932C0 /* Regressions */ = { - isa = PBXGroup; - children = ( - 4CC92AB015A3AD0000C6D578 /* Security_regressions.h */, - 4CC92A0E15A3ABD400C6D578 /* crypto */, - 4CC92A1115A3ABD400C6D578 /* otr */, - 4CC92A1615A3ABD400C6D578 /* secitem */, - 4CC92A5B15A3ABD400C6D578 /* vmdh */, - ); - name = Regressions; - sourceTree = ""; - }; - 4CC92A0E15A3ABD400C6D578 /* crypto */ = { - isa = PBXGroup; - children = ( - 4CC92A0F15A3ABD400C6D578 /* pbkdf2-00-hmac-sha1.c */, - 4CC92A1015A3ABD400C6D578 /* spbkdf-00-hmac-sha1.c */, - ); - name = crypto; - path = Regressions/crypto; - sourceTree = ""; - }; - 4CC92A1115A3ABD400C6D578 /* otr */ = { - isa = PBXGroup; - children = ( - 4CC92A1215A3ABD400C6D578 /* otr-00-identity.c */, - 4CC92A1315A3ABD400C6D578 /* otr-30-negotiation.c */, - 4CC92A1415A3ABD400C6D578 /* otr-otrdh.c */, - 4CC92A1515A3ABD400C6D578 /* otr-packetdata.c */, - ); - name = otr; - path = Regressions/otr; - sourceTree = ""; - }; - 4CC92A1615A3ABD400C6D578 /* secitem */ = { - isa = PBXGroup; - children = ( - 4CC92A1715A3ABD400C6D578 /* si-00-find-nothing.c */, - 4CC92A1815A3ABD400C6D578 /* si-05-add.c */, - 4CC92A1915A3ABD400C6D578 /* si-10-find-internet.c */, - 4CC92A1A15A3ABD400C6D578 /* si-11-update-data.c */, - 4C2C8C3C17AB374700C24C13 /* si-12-item-stress.c */, - 4CC92A1B15A3ABD400C6D578 /* si-14-dateparse.c */, - 4CC92A1C15A3ABD400C6D578 /* si-15-certificate.c */, - 4CC92A1D15A3ABD400C6D578 /* si-16-ec-certificate.c */, - 4CC92A1E15A3ABD400C6D578 /* si-20-sectrust-activation.c */, - 4CC92A1F15A3ABD400C6D578 /* si-20-sectrust.c */, - 4CC92A2015A3ABD400C6D578 /* si-21-sectrust-asr.c */, - 4CC92A2115A3ABD400C6D578 /* si-22-sectrust-iap.c */, - 4CC92A2215A3ABD400C6D578 /* si-23-sectrust-ocsp.c */, - 4CC92A2315A3ABD400C6D578 /* si-24-sectrust-appleid.c */, - 4CC92A2415A3ABD400C6D578 /* si-24-sectrust-digicert-malaysia.c */, - 4CC92A2515A3ABD400C6D578 /* si-24-sectrust-diginotar.c */, - 4CC92A2615A3ABD400C6D578 /* si-24-sectrust-itms.c */, - 4CC92A2715A3ABD400C6D578 /* si-24-sectrust-mobileasset.c */, - 4CC92A2815A3ABD400C6D578 /* si-24-sectrust-nist.c */, - 4CC92A2915A3ABD400C6D578 /* si-24-sectrust-otatasking.c */, - 4CC92A2A15A3ABD400C6D578 /* si-24-sectrust-shoebox.c */, - 4CC92A2B15A3ABD400C6D578 /* si-25-sectrust-ipsec-eap.c */, - 4CC92A2C15A3ABD400C6D578 /* si-26-applicationsigning.c */, - 4CC92A2D15A3ABD400C6D578 /* si-27-sectrust-exceptions.c */, - 4CC92A2E15A3ABD400C6D578 /* si-28-sectrustsettings.c */, - 4CC92A2F15A3ABD400C6D578 /* si-29-sectrust-codesigning.c */, - 4CC92A3015A3ABD400C6D578 /* si-30-keychain-upgrade.c */, - 4CC92A3115A3ABD400C6D578 /* si-31-keychain-bad.c */, - 4CC92A3215A3ABD400C6D578 /* si-31-keychain-unreadable.c */, - 4CC92A3415A3ABD400C6D578 /* si-33-keychain-backup.c */, - 4CC92A3515A3ABD400C6D578 /* si-40-seckey-custom.c */, - 4CC92A3615A3ABD400C6D578 /* si-40-seckey.c */, - 4CC92A3715A3ABD400C6D578 /* si-41-sececkey.c */, - 4CC92A3815A3ABD400C6D578 /* si-42-identity.c */, - 4CC92A3915A3ABD400C6D578 /* si-43-persistent.c */, - 4CC92A3A15A3ABD400C6D578 /* si-50-secrandom.c */, - 4CC92A3B15A3ABD400C6D578 /* si-60-cms.c */, - 4CC92A3C15A3ABD400C6D578 /* si-61-pkcs12.c */, - 4CC92A3D15A3ABD400C6D578 /* si-62-csr.c */, - 4CC92A3E15A3ABD400C6D578 /* si-63-scep */, - 4CC92A4115A3ABD400C6D578 /* si-63-scep.c */, - 4CC92A4215A3ABD400C6D578 /* si-63-scep.h */, - 4CC92A4315A3ABD400C6D578 /* si-64-ossl-cms */, - 4CC92A4A15A3ABD400C6D578 /* si-64-ossl-cms.c */, - 4CC92A4B15A3ABD400C6D578 /* si-65-cms-cert-policy.c */, - 4CC92A4C15A3ABD400C6D578 /* si-66-smime */, - 4CC92A4E15A3ABD400C6D578 /* si-66-smime.c */, - 4CC92A4F15A3ABD400C6D578 /* si-67-sectrust-blacklist */, - 4CC92A5A15A3ABD400C6D578 /* si-67-sectrust-blacklist.c */, - E748744415A61AF800624935 /* si-68-secmatchissuer.c */, - CDA7729616B899F10069434D /* si-69-keydesc.c */, - BE62D7611747FF51001EAA9D /* si-70-sectrust-unified.c */, - 5DE4A7BC17441CCD0036339E /* si-71-mobile-store-policy.c */, - BE62D75F1747FF3E001EAA9D /* si-72-syncableitems.c */, - CDD565A1173193AC00B6B074 /* si-73-secpasswordgenerate.c */, - 7255A46B1783333D006A8B9A /* si-74-OTAPKISigner.c */, - 7255F91317A973D5004A9F38 /* si-75-AppleIDRecordSigning.c */, - ); - name = secitem; - path = Regressions/secitem; - sourceTree = ""; - }; - 4CC92A3E15A3ABD400C6D578 /* si-63-scep */ = { - isa = PBXGroup; - children = ( - 4CC92A3F15A3ABD400C6D578 /* getcacert-mdes.h */, - 4CC92A4015A3ABD400C6D578 /* getcacert-mdesqa.h */, - ); - path = "si-63-scep"; - sourceTree = ""; - }; - 4CC92A4315A3ABD400C6D578 /* si-64-ossl-cms */ = { - isa = PBXGroup; - children = ( - 4CC92A4415A3ABD400C6D578 /* attached_no_data_signed_data.h */, - 4CC92A4515A3ABD400C6D578 /* attached_signed_data.h */, - 4CC92A4615A3ABD400C6D578 /* detached_content.h */, - 4CC92A4715A3ABD400C6D578 /* detached_signed_data.h */, - 4CC92A4815A3ABD400C6D578 /* privkey.h */, - 4CC92A4915A3ABD400C6D578 /* signer.h */, - ); - path = "si-64-ossl-cms"; - sourceTree = ""; - }; - 4CC92A4C15A3ABD400C6D578 /* si-66-smime */ = { - isa = PBXGroup; - children = ( - 4CC92A4D15A3ABD400C6D578 /* signed-receipt.h */, - ); - path = "si-66-smime"; - sourceTree = ""; - }; - 4CC92A4F15A3ABD400C6D578 /* si-67-sectrust-blacklist */ = { - isa = PBXGroup; - children = ( - 4A971683158FDEB800D439B7 /* SecOTRDHKey.c */, - 4CC92A5015A3ABD400C6D578 /* Global Trustee.cer.h */, - 4CC92A5115A3ABD400C6D578 /* UTN-USERFirst-Hardware.cer.h */, - 4CC92A5215A3ABD400C6D578 /* addons.mozilla.org.cer.h */, - 4CC92A5315A3ABD400C6D578 /* login.live.com.cer.h */, - 4CC92A5415A3ABD400C6D578 /* login.skype.com.cer.h */, - 4CC92A5515A3ABD400C6D578 /* login.yahoo.com.1.cer.h */, - 4CC92A5615A3ABD400C6D578 /* login.yahoo.com.2.cer.h */, - 4CC92A5715A3ABD400C6D578 /* login.yahoo.com.cer.h */, - 4CC92A5815A3ABD400C6D578 /* mail.google.com.cer.h */, - 4CC92A5915A3ABD400C6D578 /* www.google.com.cer.h */, - ); - path = "si-67-sectrust-blacklist"; - sourceTree = ""; - }; - 4CC92A5B15A3ABD400C6D578 /* vmdh */ = { - isa = PBXGroup; - children = ( - 4CC92A5C15A3ABD400C6D578 /* vmdh-40.c */, - 4CC92A5D15A3ABD400C6D578 /* vmdh-41-example.c */, - 4CC92A5E15A3ABD400C6D578 /* vmdh-42-example2.c */, - ); - name = vmdh; - path = Regressions/vmdh; - sourceTree = ""; - }; - 4CC92AAB15A3AC4600C6D578 /* Regressions */ = { - isa = PBXGroup; - children = ( - 0CBF93F5177B7CFC001E5658 /* secd-03-corrupted-items.c */, - 0CBF93F6177B7CFC001E5658 /* secd-04-corrupted-items.c */, - 0CBF93FB177BA9D9001E5658 /* secd-05-corrupted-items.c */, - 0CBF93F7177B7CFC001E5658 /* brighton_keychain_2_db.h */, - 4CC92AAE15A3ACCE00C6D578 /* securityd_regressions.h */, - 4CC92AAC15A3AC4600C6D578 /* sd-10-policytree.c */, - 4C143CDD164D8EF5003035A3 /* sd-70-engine.c */, - 0C0BDB601756882A00BC1A7E /* secd_regressions.h */, - 0C0BDB62175688DA00BC1A7E /* secd-01-items.c */, - 0C664AE7175951270092D3D9 /* secd-02-upgrade-while-locked.c */, - 0C062B1C175E784B00806CFE /* secd-30-keychain-upgrade.c */, - 0C062B1D175E784B00806CFE /* secd-31-keychain-bad.c */, - 0C062B1E175E784B00806CFE /* secd-31-keychain-unreadable.c */, - E79D62B9176798BF005A9743 /* secd-50-account.c */, - 48E928C4179DD05500A7F755 /* secd-51-account-inflate.c */, - 4898223917BDB277003BEF32 /* secd-52-account-changed.c */, - E7A10FAB1771246A00C4602F /* secd-55-account-circle.c */, - E7F0D3E9177BBE35001ACBC1 /* secd-55-account-incompatibility.c */, - E7F18556177A502900177B23 /* secd-56-account-apply.c */, - E7A10FAD1771249C00C4602F /* secd-57-account-leave.c */, - 4882C516177521AE0095D04B /* secd-58-password-change.c */, - 48F32D7D1777AFA3001B84BA /* secd-59-account-cleanup.c */, - E7F18554177A44E000177B23 /* secd-60-account-cloud-identity.c */, - 486C6C671795F20E00387075 /* secd-61-account-leave-not-in-kansas-anymore.c */, - E7A10FAA1771245D00C4602F /* SOSAccountTesting.h */, - E79D62BE1767A547005A9743 /* SecdTestKeychainUtilities.c */, - E79D62BF1767A55F005A9743 /* SecdTestKeychainUtilities.h */, - ); - path = Regressions; - sourceTree = ""; - }; - 521C0B9715FA5C4900604B61 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 52DD7069160CD40B0027A346 /* libutilities.a */, - 526CBA5116079FB4008DF7C8 /* Security.framework */, - 521C0B9815FA5C4A00604B61 /* Foundation.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 521C0B9B15FA5C4A00604B61 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 521C0BAB15FA5DA800604B61 /* en.lproj */ = { - isa = PBXGroup; - children = ( - 521C0BAC15FA5DA800604B61 /* InfoPlist.strings */, - ); - name = en.lproj; - path = SOSCircle/CloudKeychainProxy/en.lproj; - sourceTree = SOURCE_ROOT; - }; - 5272501416838BB20029AADD /* CloudKeychainProxy */ = { - isa = PBXGroup; - children = ( - 52C3D18E169A53150091D9D3 /* ckdmain.m */, - 521C0BB315FA5E3F00604B61 /* cloudkeychainproxy.m */, - 521C0BAF15FA5E3F00604B61 /* CKDKVSProxy.h */, - 521C0BB015FA5E3F00604B61 /* CKDKVSProxy.m */, - 521C0BB115FA5E3F00604B61 /* CKDPersistentState.h */, - 521C0BB215FA5E3F00604B61 /* CKDPersistentState.m */, - 52840291164050C80035F320 /* CKDUserInteraction.h */, - 52840292164050C80035F320 /* CKDUserInteraction.m */, - 521C0B9B15FA5C4A00604B61 /* Supporting Files */, - 522B0ED31649A68E00A4675D /* MobileKeyBag.framework */, - 521C0BAB15FA5DA800604B61 /* en.lproj */, - 521C0BA615FA5D7400604B61 /* cloudkeychain.entitlements.plist */, - 5272501916838BB20029AADD /* CloudKeychainProxy.1 */, - 5272501716838BB20029AADD /* Supporting Files */, - ); - name = CloudKeychainProxy; - path = ../CloudKeychainProxy; - sourceTree = ""; - }; - 5272501716838BB20029AADD /* Supporting Files */ = { - isa = PBXGroup; - children = ( - ); - name = "Supporting Files"; - sourceTree = ""; - }; - E71049F4169E023B00DB0045 /* SecurityTool */ = { - isa = PBXGroup; - children = ( - E790C108169E4E7900E0C0C9 /* builtin_commands.h */, - E790C109169E4FD200E0C0C9 /* digest_calc.c */, - E790C10E169E53DF00E0C0C9 /* leaks.c */, - E790C10F169E53DF00E0C0C9 /* leaks.h */, - 4CD1897B169F835400BC96B8 /* print_cert.c */, - 4CD1897C169F835400BC96B8 /* print_cert.h */, - E71049FE169E036E00DB0045 /* security.1 */, - E71049FF169E036E00DB0045 /* SecurityTool.c */, - E7104A00169E036E00DB0045 /* SecurityTool.h */, - E7104A0D169E1C1600DB0045 /* tool_errors.h */, - ); - path = SecurityTool; - sourceTree = ""; - }; - E7104A0F169E1F0800DB0045 /* Tool */ = { - isa = PBXGroup; - children = ( - E790C136169E5C6200E0C0C9 /* add_internet_password.c */, - E790C137169E5C6200E0C0C9 /* codesign.c */, - E790C138169E5C6200E0C0C9 /* keychain_add.c */, - E790C139169E5C6200E0C0C9 /* keychain_find.c */, - 0CE7ABDE171383E30088968F /* keychain_backup.c */, - E790C13A169E5C6200E0C0C9 /* pkcs12_util.c */, - E790C13D169E5C6200E0C0C9 /* scep.c */, - E790C13E169E5C6200E0C0C9 /* SecurityCommands.h */, - E790C13F169E5C6200E0C0C9 /* show_certificates.c */, - E790C140169E5C6200E0C0C9 /* spc.c */, - ); - path = Tool; - sourceTree = ""; - }; - E7217B2015F8126700D26031 /* CKBridge */ = { - isa = PBXGroup; - children = ( - 521C685C1614A6E100E31C3E /* SOSCloudKeychainClient.c */, - 521C685D1614A6E100E31C3E /* SOSCloudKeychainClient.h */, - E7217B2515F8131A00D26031 /* SOSCloudKeychainConstants.c */, - E7217B2615F8131A00D26031 /* SOSCloudKeychainConstants.h */, - 52849FC2164498C9005CDF23 /* SOSARCDefines.h */, - ); - path = CKBridge; - sourceTree = ""; - }; - E7295C6614E356FE007FBB20 /* Hacks */ = { - isa = PBXGroup; - children = ( - E7295C6714E3571A007FBB20 /* Empty.c */, - 4C8940DA166EA8CF00241770 /* osxshim.c */, - ); - name = Hacks; - sourceTree = ""; - }; - E7AC69CE14E1F78400CB09C1 /* SOSCircle */ = { - isa = PBXGroup; - children = ( - E7FEFB81169E362100E18152 /* Tool */, - E7295C6614E356FE007FBB20 /* Hacks */, - E7AC69CF14E1F78400CB09C1 /* Regressions */, - E7AC69D114E1F78400CB09C1 /* SecureObjectSync */, - 5272501416838BB20029AADD /* CloudKeychainProxy */, - E7217B2015F8126700D26031 /* CKBridge */, - ); - path = SOSCircle; - sourceTree = ""; - }; - E7AC69CF14E1F78400CB09C1 /* Regressions */ = { - isa = PBXGroup; - children = ( - 4CC92AAF15A3ACE600C6D578 /* SOSCircle_regressions.h */, - E763D6221624E2670038477D /* sc-20-keynames.c */, - E777C72815B9C9F0004044A8 /* sc-30-peerinfo.c */, - E777C6B015B4DDF2004044A8 /* sc-40-circle.c */, - E7BE10A5167AB2BF00D2A178 /* sc-41-cloudcircle.c */, - 5253946016608F6800BA9687 /* sc-51-persistentEC.c */, - 4C6ED19115CB0E26004379B7 /* sc-60-peer.c */, - 4C6ED19415CB0E43004379B7 /* sc-70-engine.c */, - 4C4EBD531610D7D8007D06A5 /* sc-75-circle-engine.c */, - 521C0A7315F908A700604B61 /* sc-90-ckdclient.c */, - 521C691E16164B9900E31C3E /* sc-95-ckd2client.c */, - 52DEE9E1162DC8F1002F3BCD /* sc-100-devicecircle.c */, - 52AF7082163D9AA20092A7ED /* sc-101-accountsync.c */, - 52840280163F2B060035F320 /* sc-102-cfusernotification.c */, - 522B0ED11648809300A4675D /* sc-103-syncupdate.c */, - 521C0C8615FEB03300604B61 /* sc-120-cloudcircle.c */, - 48CE733D1731C49A004C2946 /* sc-130-resignationticket.c */, - 521C0CD515FF9B3300604B61 /* SOSRegressionUtilities.c */, - 521C0CD815FF9B4B00604B61 /* SOSRegressionUtilities.h */, - 521C0CD915FFA05000604B61 /* CKDKeyValueStore.h */, - 521C0CDA15FFA05000604B61 /* CKDKeyValueStore.m */, - 4CB8A83716164B7700B52EC7 /* SOSTestDataSource.c */, - 4CB8A83916164B8C00B52EC7 /* SOSTestDataSource.h */, - 4C5F2E36162DE87F00AF8346 /* SOSTestTransport.c */, - 4C5F2E35162DE84E00AF8346 /* SOSTestTransport.h */, - ); - path = Regressions; - sourceTree = ""; - }; - E7AC69D114E1F78400CB09C1 /* SecureObjectSync */ = { - isa = PBXGroup; - children = ( - 4CC929AD15A3957800C6D578 /* SOSAccount.c */, - 4CC929AE15A3957800C6D578 /* SOSAccount.h */, - 4CC929AF15A3957800C6D578 /* SOSCircle.c */, - 4CC929B015A3957800C6D578 /* SOSCircle.h */, - E777C71D15B73F9E004044A8 /* SOSInternal.c */, - E777C71B15B73F59004044A8 /* SOSInternal.h */, - E703811114E1FEE4007CB458 /* SOSCloudCircle.h */, - E7B01B5A16532507000485F1 /* SOSCloudCircleInternal.h */, - E7217B1715F80E0F00D26031 /* SOSCloudCircle.c */, - 4C9DC91C15B602910036D941 /* SOSEngine.c */, - 4C9DC91915B602760036D941 /* SOSEngine.h */, - 4CC929B115A3957800C6D578 /* SOSPeer.c */, - 4CC929B215A3957800C6D578 /* SOSPeer.h */, - E79277E1163B110A0096F3E2 /* SOSFullPeerInfo.c */, - E79277E2163B110A0096F3E2 /* SOSFullPeerInfo.h */, - E777C72515B87544004044A8 /* SOSPeerInfo.c */, - E777C72415B87528004044A8 /* SOSPeerInfo.h */, - 485835871779013E0050F074 /* SOSPeerInfoInternal.h */, - 4C1C452614EB27F50018B1D9 /* SOSTransport.c */, - 4C1C452914EB28260018B1D9 /* SOSTransport.h */, - 488902EB16C2F88400F119FF /* SOSCoder.c */, - 488902ED16C2F89700F119FF /* SOSCoder.h */, - 4802A59516D711060059E5B9 /* SOSUserKeygen.c */, - 4802A59716D711190059E5B9 /* SOSUserKeygen.h */, - E7B00702170B5FE100B27966 /* SOSExports.exp-in */, - ); - path = SecureObjectSync; - sourceTree = ""; - }; - E7FEFB81169E362100E18152 /* Tool */ = { - isa = PBXGroup; - children = ( - E790C0F4169E3D7200E0C0C9 /* SOSCommands.h */, - E7FEFB90169E36D800E18152 /* keychain_sync.c */, - ); - path = Tool; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 0C0BDB5A175687EC00BC1A7E /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 0CBF93FA177B7CFC001E5658 /* brighton_keychain_2_db.h in Headers */, - 0C0BDB611756882A00BC1A7E /* secd_regressions.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 18270F5314CF651900B05E7F /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 186CDD0D14CA116C00AF9171 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 18AD560F14CB6E7A008233F2 /* securityd_client.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 18D4043314CE0CF300A2BE4E /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - CDC765C41729A72800721712 /* SecPasswordGenerate.h in Headers */, - 4A971695158FDEB800D439B7 /* SecOTR.h in Headers */, - 4A971697158FDEB800D439B7 /* SecOTRDHKey.h in Headers */, - 4A971698158FDEB800D439B7 /* SecOTRErrors.h in Headers */, - 4A97169A158FDEB800D439B7 /* SecOTRIdentityPriv.h in Headers */, - 4A97169C158FDEB800D439B7 /* SecOTRMath.h in Headers */, - 4A97169D158FDEB800D439B7 /* SecOTRMathPrivate.h in Headers */, - 4A97169F158FDEB800D439B7 /* SecOTRPacketData.h in Headers */, - 4A9716A1158FDEB800D439B7 /* SecOTRPackets.h in Headers */, - 4A9716A4158FDEB800D439B7 /* SecOTRSession.h in Headers */, - 4A9716A6158FDEB800D439B7 /* SecOTRSessionPriv.h in Headers */, - 52D0F028169CA72800F07D79 /* SecOnOSX.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 18D4056014CE53C200A2BE4E /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4A5CCA4D15ACEFA500702357 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4A824AFF158FF07000F932C0 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 4CC92AC015A3BC4300C6D578 /* Security_regressions.h in Headers */, - 4CC92A8C15A3ABD400C6D578 /* getcacert-mdes.h in Headers */, - 4CC92A8D15A3ABD400C6D578 /* getcacert-mdesqa.h in Headers */, - 4CC92A8F15A3ABD400C6D578 /* si-63-scep.h in Headers */, - 4CC92A9015A3ABD400C6D578 /* attached_no_data_signed_data.h in Headers */, - 4CC92A9115A3ABD400C6D578 /* attached_signed_data.h in Headers */, - 4CC92A9215A3ABD400C6D578 /* detached_content.h in Headers */, - 4CC92A9315A3ABD400C6D578 /* detached_signed_data.h in Headers */, - 4CC92A9415A3ABD400C6D578 /* privkey.h in Headers */, - 4CC92A9515A3ABD400C6D578 /* signer.h in Headers */, - 4CC92A9815A3ABD400C6D578 /* signed-receipt.h in Headers */, - 4CC92A9A15A3ABD400C6D578 /* Global Trustee.cer.h in Headers */, - 4CC92A9B15A3ABD400C6D578 /* UTN-USERFirst-Hardware.cer.h in Headers */, - 4CC92A9C15A3ABD400C6D578 /* addons.mozilla.org.cer.h in Headers */, - 4CC92A9D15A3ABD400C6D578 /* login.live.com.cer.h in Headers */, - 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 */, - 4CC92AA115A3ABD400C6D578 /* login.yahoo.com.cer.h in Headers */, - 4CC92AA215A3ABD400C6D578 /* mail.google.com.cer.h in Headers */, - 4CC92AA315A3ABD400C6D578 /* www.google.com.cer.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4CC92AFB15A3BC6B00C6D578 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 4CC92B1515A3BCA500C6D578 /* securityd_regressions.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E702E75014E1F3EA00CDE635 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - E703811514E1FEEF007CB458 /* SOSCloudCircle.h in Headers */, - 4C1C452A14EB28260018B1D9 /* SOSTransport.h in Headers */, - 4CC929B415A3957800C6D578 /* SOSAccount.h in Headers */, - 4CC929B615A3957800C6D578 /* SOSCircle.h in Headers */, - 4CC929B815A3957800C6D578 /* SOSPeer.h in Headers */, - 4C9DC91A15B602760036D941 /* SOSEngine.h in Headers */, - E777C71C15B73F59004044A8 /* SOSInternal.h in Headers */, - 4802A59816D7156D0059E5B9 /* SOSUserKeygen.h in Headers */, - E777C72715B882E5004044A8 /* SOSPeerInfo.h in Headers */, - E7217B2815F8131A00D26031 /* SOSCloudKeychainConstants.h in Headers */, - 521C68601614A6E100E31C3E /* SOSCloudKeychainClient.h in Headers */, - E79277E4163B110A0096F3E2 /* SOSFullPeerInfo.h in Headers */, - E7B01B5B16532507000485F1 /* SOSCloudCircleInternal.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E702E77214E1F48800CDE635 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 4CC92AC115A3BC4D00C6D578 /* SOSCircle_regressions.h in Headers */, - 521C0CDD15FFA05100604B61 /* CKDKeyValueStore.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 0C0BDB55175687EC00BC1A7E /* libsecdRegressions */ = { - isa = PBXNativeTarget; - buildConfigurationList = 0C0BDB5C175687EC00BC1A7E /* Build configuration list for PBXNativeTarget "libsecdRegressions" */; - buildPhases = ( - 0C0BDB56175687EC00BC1A7E /* Sources */, - 0C0BDB59175687EC00BC1A7E /* Frameworks */, - 0C0BDB5A175687EC00BC1A7E /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libsecdRegressions; - productName = security; - productReference = 0C0BDB5F175687EC00BC1A7E /* libsecdRegressions.a */; - productType = "com.apple.product-type.library.static"; - }; - 18270F5414CF651900B05E7F /* libsecipc_client */ = { - isa = PBXNativeTarget; - buildConfigurationList = 18270F5614CF651900B05E7F /* Build configuration list for PBXNativeTarget "libsecipc_client" */; - buildPhases = ( - 18270F5114CF651900B05E7F /* Sources */, - 18270F5214CF651900B05E7F /* Frameworks */, - 18270F5314CF651900B05E7F /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libsecipc_client; - productName = libsecipc_client; - productReference = 18270F5514CF651900B05E7F /* libsecipc_client.a */; - productType = "com.apple.product-type.library.static"; - }; - 186CDD0E14CA116C00AF9171 /* libSecItemShimOSX */ = { - isa = PBXNativeTarget; - buildConfigurationList = 186CDD1314CA116C00AF9171 /* Build configuration list for PBXNativeTarget "libSecItemShimOSX" */; - buildPhases = ( - 186CDD0B14CA116C00AF9171 /* Sources */, - 186CDD0C14CA116C00AF9171 /* Frameworks */, - 186CDD0D14CA116C00AF9171 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libSecItemShimOSX; - productName = sec; - productReference = 186CDD0F14CA116C00AF9171 /* libSecItemShimOSX.a */; - productType = "com.apple.product-type.library.static"; - }; - 18D4043414CE0CF300A2BE4E /* libsecurity */ = { - isa = PBXNativeTarget; - buildConfigurationList = 18D4043614CE0CF300A2BE4E /* Build configuration list for PBXNativeTarget "libsecurity" */; - buildPhases = ( - 18D4043114CE0CF300A2BE4E /* Sources */, - 18D4043214CE0CF300A2BE4E /* Frameworks */, - 18D4043314CE0CF300A2BE4E /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libsecurity; - productName = security; - productReference = 18D4043514CE0CF300A2BE4E /* libsecurity.a */; - productType = "com.apple.product-type.library.static"; - }; - 18D4056114CE53C200A2BE4E /* libsecurityd */ = { - isa = PBXNativeTarget; - buildConfigurationList = 18D4056314CE53C200A2BE4E /* Build configuration list for PBXNativeTarget "libsecurityd" */; - buildPhases = ( - 18D4055E14CE53C200A2BE4E /* Sources */, - 18D4055F14CE53C200A2BE4E /* Frameworks */, - 18D4056014CE53C200A2BE4E /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libsecurityd; - productName = securityd; - productReference = 18D4056214CE53C200A2BE4E /* libsecurityd.a */; - productType = "com.apple.product-type.library.static"; - }; - 4A5CCA4E15ACEFA500702357 /* libSecOtrOSX */ = { - isa = PBXNativeTarget; - buildConfigurationList = 4A5CCA5215ACEFA500702357 /* Build configuration list for PBXNativeTarget "libSecOtrOSX" */; - buildPhases = ( - 4A5CCA4B15ACEFA500702357 /* Sources */, - 4A5CCA4C15ACEFA500702357 /* Frameworks */, - 4A5CCA4D15ACEFA500702357 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libSecOtrOSX; - productName = libSecOtrOSX; - productReference = 4A5CCA4F15ACEFA500702357 /* libSecOtrOSX.a */; - productType = "com.apple.product-type.library.static"; - }; - 4A824AFB158FF07000F932C0 /* libSecurityRegressions */ = { - isa = PBXNativeTarget; - buildConfigurationList = 4A824B00158FF07000F932C0 /* Build configuration list for PBXNativeTarget "libSecurityRegressions" */; - buildPhases = ( - 4A824AFC158FF07000F932C0 /* Sources */, - 4A824AFE158FF07000F932C0 /* Frameworks */, - 4A824AFF158FF07000F932C0 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libSecurityRegressions; - productName = security; - productReference = 4A824B03158FF07000F932C0 /* libSecurityRegressions.a */; - productType = "com.apple.product-type.library.static"; - }; - 4CC92AC215A3BC6B00C6D578 /* libsecuritydRegressions */ = { - isa = PBXNativeTarget; - buildConfigurationList = 4CC92B1115A3BC6B00C6D578 /* Build configuration list for PBXNativeTarget "libsecuritydRegressions" */; - buildPhases = ( - 4CC92AC315A3BC6B00C6D578 /* Sources */, - 4CC92AFA15A3BC6B00C6D578 /* Frameworks */, - 4CC92AFB15A3BC6B00C6D578 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libsecuritydRegressions; - productName = security; - productReference = 4CC92B1415A3BC6B00C6D578 /* libsecuritydRegressions.a */; - productType = "com.apple.product-type.library.static"; - }; - 5284029F164445760035F320 /* libCloudKeychainProxy */ = { - isa = PBXNativeTarget; - buildConfigurationList = 528402A9164445760035F320 /* Build configuration list for PBXNativeTarget "libCloudKeychainProxy" */; - buildPhases = ( - 5284029C164445760035F320 /* Sources */, - 5284029D164445760035F320 /* Frameworks */, - 5284029E164445760035F320 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libCloudKeychainProxy; - productName = libCloudKeychainProxy; - productReference = 528402A0164445760035F320 /* libCloudKeychainProxy.a */; - productType = "com.apple.product-type.library.static"; - }; - E702E73514E1F3EA00CDE635 /* libSecureObjectSync */ = { - isa = PBXNativeTarget; - buildConfigurationList = E702E75314E1F3EA00CDE635 /* Build configuration list for PBXNativeTarget "libSecureObjectSync" */; - buildPhases = ( - E702E73614E1F3EA00CDE635 /* Sources */, - E702E74F14E1F3EA00CDE635 /* Frameworks */, - E702E75014E1F3EA00CDE635 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libSecureObjectSync; - productName = security; - productReference = E702E75614E1F3EA00CDE635 /* libSecureObjectSync.a */; - productType = "com.apple.product-type.library.static"; - }; - E702E75714E1F48800CDE635 /* libSOSRegressions */ = { - isa = PBXNativeTarget; - buildConfigurationList = E702E77514E1F48800CDE635 /* Build configuration list for PBXNativeTarget "libSOSRegressions" */; - buildPhases = ( - E702E75814E1F48800CDE635 /* Sources */, - E702E77114E1F48800CDE635 /* Frameworks */, - E702E77214E1F48800CDE635 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libSOSRegressions; - productName = security; - productReference = E702E77814E1F48800CDE635 /* libSOSRegressions.a */; - productType = "com.apple.product-type.library.static"; - }; - E71049F1169E023B00DB0045 /* libSecurityTool */ = { - isa = PBXNativeTarget; - buildConfigurationList = E71049FD169E023B00DB0045 /* Build configuration list for PBXNativeTarget "libSecurityTool" */; - buildPhases = ( - E71049EE169E023B00DB0045 /* Sources */, - E71049EF169E023B00DB0045 /* Frameworks */, - E71049F0169E023B00DB0045 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libSecurityTool; - productName = SecurityTool; - productReference = E71049F2169E023B00DB0045 /* libSecurityTool.a */; - productType = "com.apple.product-type.library.static"; - }; - E7104A12169E216E00DB0045 /* libSecurityCommands */ = { - isa = PBXNativeTarget; - buildConfigurationList = E7104A1A169E216E00DB0045 /* Build configuration list for PBXNativeTarget "libSecurityCommands" */; - buildPhases = ( - E7104A13169E216E00DB0045 /* Sources */, - E7104A17169E216E00DB0045 /* Frameworks */, - E7104A19169E216E00DB0045 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libSecurityCommands; - productName = SecurityTool; - productReference = E7104A1D169E216E00DB0045 /* libSecurityCommands.a */; - productType = "com.apple.product-type.library.static"; - }; - E7FEFB82169E363300E18152 /* libSOSCommands */ = { - isa = PBXNativeTarget; - buildConfigurationList = E7FEFB89169E363300E18152 /* Build configuration list for PBXNativeTarget "libSOSCommands" */; - buildPhases = ( - E7FEFB83169E363300E18152 /* Sources */, - E7FEFB86169E363300E18152 /* Frameworks */, - E7FEFB88169E363300E18152 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libSOSCommands; - productName = SecurityTool; - productReference = E7FEFB8C169E363300E18152 /* libSOSCommands.a */; - productType = "com.apple.product-type.library.static"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 186CDD0614CA116C00AF9171 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0500; - }; - buildConfigurationList = 186CDD0914CA116C00AF9171 /* Build configuration list for PBXProject "sec" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 186CDD0414CA116C00AF9171; - productRefGroup = 186CDD1014CA116C00AF9171 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 18D4043414CE0CF300A2BE4E /* libsecurity */, - 18D4056114CE53C200A2BE4E /* libsecurityd */, - 186CDD0E14CA116C00AF9171 /* libSecItemShimOSX */, - 18270F5414CF651900B05E7F /* libsecipc_client */, - E702E73514E1F3EA00CDE635 /* libSecureObjectSync */, - E702E75714E1F48800CDE635 /* libSOSRegressions */, - 4A824AFB158FF07000F932C0 /* libSecurityRegressions */, - 4CC92AC215A3BC6B00C6D578 /* libsecuritydRegressions */, - 4A5CCA4E15ACEFA500702357 /* libSecOtrOSX */, - 5284029F164445760035F320 /* libCloudKeychainProxy */, - E71049F1169E023B00DB0045 /* libSecurityTool */, - E7104A12169E216E00DB0045 /* libSecurityCommands */, - E7FEFB82169E363300E18152 /* libSOSCommands */, - 0C0BDB55175687EC00BC1A7E /* libsecdRegressions */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 0C0BDB56175687EC00BC1A7E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - E7F0D3EA177BBE35001ACBC1 /* secd-55-account-incompatibility.c in Sources */, - 0C0BDB63175688DA00BC1A7E /* secd-01-items.c in Sources */, - 4882C517177521AE0095D04B /* secd-58-password-change.c in Sources */, - E7A10FAE1771249C00C4602F /* secd-57-account-leave.c in Sources */, - E7F18555177A44E000177B23 /* secd-60-account-cloud-identity.c in Sources */, - E7F18557177A502900177B23 /* secd-56-account-apply.c in Sources */, - 0C664AE8175951270092D3D9 /* secd-02-upgrade-while-locked.c in Sources */, - 0CBF93F8177B7CFC001E5658 /* secd-03-corrupted-items.c in Sources */, - 0CBF93FC177BA9D9001E5658 /* secd-05-corrupted-items.c in Sources */, - 0CBF93F9177B7CFC001E5658 /* secd-04-corrupted-items.c in Sources */, - 4898223A17BDB277003BEF32 /* secd-52-account-changed.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 */, - E79D62BB176798FD005A9743 /* secd-50-account.c in Sources */, - 48E928C5179DD05500A7F755 /* secd-51-account-inflate.c in Sources */, - 486C6C691795F9D600387075 /* secd-61-account-leave-not-in-kansas-anymore.c in Sources */, - E79D62BD176799EE005A9743 /* SOSTestDataSource.c in Sources */, - E79D62BC176799DB005A9743 /* SOSRegressionUtilities.c in Sources */, - E7A10FAC1771246A00C4602F /* secd-55-account-circle.c in Sources */, - E79D62C01767A5BC005A9743 /* SecdTestKeychainUtilities.c in Sources */, - 48F32D7E1777AFA3001B84BA /* secd-59-account-cleanup.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 18270F5114CF651900B05E7F /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 18270F5914CF654400B05E7F /* client.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 186CDD0B14CA116C00AF9171 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 18AD566714CB70A8008233F2 /* SecItem.c in Sources */, - BEFE994E14F2E17200356A97 /* SecDH.c in Sources */, - 4C8D8627177A71E80019A804 /* SOSCloudCircle.c in Sources */, - 4C3CE9E7176005A700B521C2 /* SecuritydXPC.c in Sources */, - 4C8940DB166EA8CF00241770 /* osxshim.c in Sources */, - 4C8D8628177A71FB0019A804 /* SecPasswordGenerate.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 18D4043114CE0CF300A2BE4E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 18D4043914CE1FE400A2BE4E /* p12import.c in Sources */, - 18D4043A14CE1FE400A2BE4E /* p12pbegen.c in Sources */, - 18D4043B14CE1FE400A2BE4E /* pbkdf2.c in Sources */, - 18D4043C14CE1FE400A2BE4E /* SecBase64.c in Sources */, - 18D4043D14CE1FE400A2BE4E /* SecCertificate.c in Sources */, - 18D4043E14CE1FE400A2BE4E /* SecCertificatePath.c in Sources */, - 18D4043F14CE1FE400A2BE4E /* SecCertificateRequest.c in Sources */, - 18D4044014CE1FE400A2BE4E /* SecCMS.c in Sources */, - 18D4044114CE1FE400A2BE4E /* SecDH.c in Sources */, - 18D4044214CE1FE400A2BE4E /* SecECKey.c in Sources */, - 18D4044314CE1FE400A2BE4E /* SecFramework.c in Sources */, - 18D4044414CE1FE400A2BE4E /* SecIdentity.c in Sources */, - 18D4044514CE1FE400A2BE4E /* SecImportExport.c in Sources */, - 18D4044614CE1FE400A2BE4E /* SecItem.c in Sources */, - 18D4044714CE1FE400A2BE4E /* SecItemConstants.c in Sources */, - 18D4044814CE1FE400A2BE4E /* SecKey.c in Sources */, - 18D4044914CE1FE400A2BE4E /* SecPBKDF.c in Sources */, - 18D4044A14CE1FE400A2BE4E /* SecPolicy.c in Sources */, - 4CC07E26171E252300DCB6CE /* SOSCloudCircle.c in Sources */, - 18D4044B14CE1FE400A2BE4E /* SecRSAKey.c in Sources */, - 18D4044C14CE1FE400A2BE4E /* SecSCEP.c in Sources */, - 18D4044D14CE1FE400A2BE4E /* SecTrust.c in Sources */, - 18D4044E14CE1FE400A2BE4E /* SecTrustSettings.c in Sources */, - CDC765C21729A72800721712 /* SecPasswordGenerate.c in Sources */, - 18D4044F14CE1FE400A2BE4E /* SecTrustStore.c in Sources */, - 18D4045014CE1FE400A2BE4E /* vmdh.c in Sources */, - 4A971696158FDEB800D439B7 /* SecOTRDHKey.c in Sources */, - 4A971699158FDEB800D439B7 /* SecOTRFullIdentity.c in Sources */, - 4A97169B158FDEB800D439B7 /* SecOTRMath.c in Sources */, - 4A97169E158FDEB800D439B7 /* SecOTRPacketData.c in Sources */, - 4A9716A0158FDEB800D439B7 /* SecOTRPackets.c in Sources */, - 4A9716A2158FDEB800D439B7 /* SecOTRPublicIdentity.c in Sources */, - 4A9716A3158FDEB800D439B7 /* SecOTRSession.c in Sources */, - 4A9716A5158FDEB800D439B7 /* SecOTRSessionAKE.c in Sources */, - 4A9716A7158FDEB800D439B7 /* SecOTRUtils.c in Sources */, - CD3FD10716C3064B00A83BB6 /* SecuritydXPC.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 18D4055E14CE53C200A2BE4E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7249E1CB16C01E5F003D7268 /* OTATrustUtilities.c in Sources */, - 18D4056614CE53DD00A2BE4E /* asynchttp.c in Sources */, - 18D4056814CE53DD00A2BE4E /* policytree.c in Sources */, - 18D4056914CE53DD00A2BE4E /* SecCAIssuerCache.c in Sources */, - 18D4056A14CE53DD00A2BE4E /* SecCAIssuerRequest.c in Sources */, - 18D4056B14CE53DD00A2BE4E /* SecItemServer.c in Sources */, - 4C3CE9E8176005B500B521C2 /* SecuritydXPC.c in Sources */, - 18D4056C14CE53DD00A2BE4E /* SecOCSPCache.c in Sources */, - 18D4056D14CE53DD00A2BE4E /* SecOCSPRequest.c in Sources */, - 18D4056E14CE53DD00A2BE4E /* SecOCSPResponse.c in Sources */, - 18D4056F14CE53DD00A2BE4E /* SecPolicyServer.c in Sources */, - 18D4057014CE53DD00A2BE4E /* SecTrustServer.c in Sources */, - 18D4057114CE53DD00A2BE4E /* SecTrustStoreServer.c in Sources */, - 18D4057214CE547400A2BE4E /* spi.c in Sources */, - E7B01B691655DF20000485F1 /* SOSCloudCircleServer.c in Sources */, - 525394AE1660A30000BA9687 /* SecDbItem.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4A5CCA4B15ACEFA500702357 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 4A5CCA5415ACEFD400702357 /* SecOTRDHKey.c in Sources */, - 4A5CCA5515ACEFD400702357 /* SecOTRFullIdentity.c in Sources */, - 4A5CCA5615ACEFD400702357 /* SecOTRMath.c in Sources */, - 4A5CCA5715ACEFD400702357 /* SecOTRPacketData.c in Sources */, - 4A5CCA5815ACEFD400702357 /* SecOTRPackets.c in Sources */, - 4A5CCA5915ACEFD400702357 /* SecOTRPublicIdentity.c in Sources */, - 4A5CCA5A15ACEFD400702357 /* SecOTRSession.c in Sources */, - 4A5CCA5B15ACEFD400702357 /* SecOTRSessionAKE.c in Sources */, - 4A5CCA5C15ACEFD400702357 /* SecOTRUtils.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4A824AFC158FF07000F932C0 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 4CC92A5F15A3ABD400C6D578 /* pbkdf2-00-hmac-sha1.c in Sources */, - 4CC92A6015A3ABD400C6D578 /* spbkdf-00-hmac-sha1.c in Sources */, - 4CC92A6115A3ABD400C6D578 /* otr-00-identity.c in Sources */, - 4CC92A6215A3ABD400C6D578 /* otr-30-negotiation.c in Sources */, - 4CC92A6315A3ABD400C6D578 /* otr-otrdh.c in Sources */, - 4CC92A6415A3ABD400C6D578 /* otr-packetdata.c in Sources */, - 4CC92A6515A3ABD400C6D578 /* si-00-find-nothing.c in Sources */, - 4CC92A6615A3ABD400C6D578 /* si-05-add.c in Sources */, - 4CC92A6715A3ABD400C6D578 /* si-10-find-internet.c in Sources */, - 4CC92A6815A3ABD400C6D578 /* si-11-update-data.c in Sources */, - 4CC92A6915A3ABD400C6D578 /* si-14-dateparse.c in Sources */, - 4CC92A6A15A3ABD400C6D578 /* si-15-certificate.c in Sources */, - 4CC92A6B15A3ABD400C6D578 /* si-16-ec-certificate.c in Sources */, - 4CC92A6C15A3ABD400C6D578 /* si-20-sectrust-activation.c in Sources */, - 4CC92A6D15A3ABD400C6D578 /* si-20-sectrust.c in Sources */, - BE62D7601747FF3E001EAA9D /* si-72-syncableitems.c in Sources */, - 4CC92A6E15A3ABD400C6D578 /* si-21-sectrust-asr.c in Sources */, - 4CC92A6F15A3ABD400C6D578 /* si-22-sectrust-iap.c in Sources */, - 4CC92A7015A3ABD400C6D578 /* si-23-sectrust-ocsp.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 */, - 4CC92A7415A3ABD400C6D578 /* si-24-sectrust-itms.c in Sources */, - 4CC92A7515A3ABD400C6D578 /* si-24-sectrust-mobileasset.c in Sources */, - 4CC92A7615A3ABD400C6D578 /* si-24-sectrust-nist.c in Sources */, - 4CC92A7715A3ABD400C6D578 /* si-24-sectrust-otatasking.c in Sources */, - 4CC92A7815A3ABD400C6D578 /* si-24-sectrust-shoebox.c in Sources */, - 4CC92A7915A3ABD400C6D578 /* si-25-sectrust-ipsec-eap.c in Sources */, - 4CC92A7A15A3ABD400C6D578 /* si-26-applicationsigning.c in Sources */, - 4CC92A7B15A3ABD400C6D578 /* si-27-sectrust-exceptions.c in Sources */, - 4CC92A7C15A3ABD400C6D578 /* si-28-sectrustsettings.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 */, - 4CC92A7F15A3ABD400C6D578 /* si-31-keychain-bad.c in Sources */, - 4CC92A8015A3ABD400C6D578 /* si-31-keychain-unreadable.c in Sources */, - 4CC92A8215A3ABD400C6D578 /* si-33-keychain-backup.c in Sources */, - 4CC92A8315A3ABD400C6D578 /* si-40-seckey-custom.c in Sources */, - E7CA197A17179EC20065299C /* si-69-keydesc.c in Sources */, - BE62D7621747FF51001EAA9D /* si-70-sectrust-unified.c in Sources */, - 4CC92A8415A3ABD400C6D578 /* si-40-seckey.c in Sources */, - 4CC92A8515A3ABD400C6D578 /* si-41-sececkey.c in Sources */, - 4CC92A8615A3ABD400C6D578 /* si-42-identity.c in Sources */, - 4CC92A8715A3ABD400C6D578 /* si-43-persistent.c in Sources */, - 4CC92A8815A3ABD400C6D578 /* si-50-secrandom.c in Sources */, - 4CC92A8915A3ABD400C6D578 /* si-60-cms.c in Sources */, - 5DE4A7BD17441CCD0036339E /* si-71-mobile-store-policy.c in Sources */, - CDD565A2173193AC00B6B074 /* si-73-secpasswordgenerate.c in Sources */, - 4CC92A8A15A3ABD400C6D578 /* si-61-pkcs12.c in Sources */, - 4CC92A8B15A3ABD400C6D578 /* si-62-csr.c in Sources */, - 4CC92A8E15A3ABD400C6D578 /* si-63-scep.c in Sources */, - 4CC92A9615A3ABD400C6D578 /* si-64-ossl-cms.c in Sources */, - 7255A46C1783333D006A8B9A /* si-74-OTAPKISigner.c in Sources */, - 7255F91417A973D5004A9F38 /* si-75-AppleIDRecordSigning.c in Sources */, - 4CC92A9715A3ABD400C6D578 /* si-65-cms-cert-policy.c in Sources */, - 4CC92A9915A3ABD400C6D578 /* si-66-smime.c in Sources */, - 4CC92AA415A3ABD400C6D578 /* si-67-sectrust-blacklist.c in Sources */, - 4CC92AA515A3ABD400C6D578 /* vmdh-40.c in Sources */, - 4CC92AA615A3ABD400C6D578 /* vmdh-41-example.c in Sources */, - 4CC92AA715A3ABD400C6D578 /* vmdh-42-example2.c in Sources */, - E748744515A61AF800624935 /* si-68-secmatchissuer.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 4CC92AC315A3BC6B00C6D578 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 4CC92AF915A3BC6B00C6D578 /* sd-10-policytree.c in Sources */, - 4C143CDE164D8EF5003035A3 /* sd-70-engine.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 5284029C164445760035F320 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 5214701B16977D7700DF0DB3 /* cloudkeychainproxy.m in Sources */, - 528402AE164446410035F320 /* CKDKVSProxy.m in Sources */, - 528402AF164446410035F320 /* CKDPersistentState.m in Sources */, - 528402B1164446410035F320 /* CKDUserInteraction.m in Sources */, - 528402B2164447610035F320 /* SOSCloudKeychainConstants.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E702E73614E1F3EA00CDE635 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 4C1C452714EB27F50018B1D9 /* SOSTransport.c in Sources */, - 4802A59616D711060059E5B9 /* SOSUserKeygen.c in Sources */, - 4CC929B315A3957800C6D578 /* SOSAccount.c in Sources */, - 4CC929B515A3957800C6D578 /* SOSCircle.c in Sources */, - 4CC929B715A3957800C6D578 /* SOSPeer.c in Sources */, - 4C9DC91D15B602910036D941 /* SOSEngine.c in Sources */, - E777C71E15B73F9E004044A8 /* SOSInternal.c in Sources */, - E777C72615B87545004044A8 /* SOSPeerInfo.c in Sources */, - E7217B2715F8131A00D26031 /* SOSCloudKeychainConstants.c in Sources */, - E79277E3163B110A0096F3E2 /* SOSFullPeerInfo.c in Sources */, - 52EAF4BE163C52EB00803D0F /* SOSCloudKeychainClient.c in Sources */, - 488902EC16C2F88400F119FF /* SOSCoder.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E702E75814E1F48800CDE635 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 4C6ED19615CB0E72004379B7 /* sc-30-peerinfo.c in Sources */, - E777C6B115B4DDF2004044A8 /* sc-40-circle.c in Sources */, - 4C6ED19715CB0E72004379B7 /* sc-60-peer.c in Sources */, - 4C6ED19515CB0E44004379B7 /* sc-70-engine.c in Sources */, - 521C0A7615F908AF00604B61 /* sc-90-ckdclient.c in Sources */, - 521C0C8715FEB03300604B61 /* sc-120-cloudcircle.c in Sources */, - 521C0CD615FF9B3300604B61 /* SOSRegressionUtilities.c in Sources */, - 48CE733E1731C49A004C2946 /* sc-130-resignationticket.c in Sources */, - 4C4EBD541610D7D8007D06A5 /* sc-75-circle-engine.c in Sources */, - 4CB8A83816164B7700B52EC7 /* SOSTestDataSource.c in Sources */, - 521C691F16164B9900E31C3E /* sc-95-ckd2client.c in Sources */, - 4C5F2E38162DF76A00AF8346 /* SOSTestTransport.c in Sources */, - E763D6231624E2670038477D /* sc-20-keynames.c in Sources */, - 52DEE9E2162DC8F1002F3BCD /* sc-100-devicecircle.c in Sources */, - 52AF7083163D9AA20092A7ED /* sc-101-accountsync.c in Sources */, - 52840281163F2B060035F320 /* sc-102-cfusernotification.c in Sources */, - 522B0ED21648809300A4675D /* sc-103-syncupdate.c in Sources */, - 5253946116608F6800BA9687 /* sc-51-persistentEC.c in Sources */, - E7BE10A7167AB32300D2A178 /* sc-41-cloudcircle.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E71049EE169E023B00DB0045 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0CE7ABDF171383E30088968F /* keychain_backup.c in Sources */, - E7104A01169E036E00DB0045 /* SecurityTool.c in Sources */, - E790C10A169E4FD200E0C0C9 /* digest_calc.c in Sources */, - E790C110169E53DF00E0C0C9 /* leaks.c in Sources */, - 4CD1897D169F835400BC96B8 /* print_cert.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E7104A13169E216E00DB0045 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - E790C141169E5C6200E0C0C9 /* add_internet_password.c in Sources */, - E790C142169E5C6200E0C0C9 /* codesign.c in Sources */, - E790C143169E5C6200E0C0C9 /* keychain_add.c in Sources */, - E790C144169E5C6200E0C0C9 /* keychain_find.c in Sources */, - E790C145169E5C6200E0C0C9 /* pkcs12_util.c in Sources */, - E790C147169E5C6200E0C0C9 /* scep.c in Sources */, - E790C148169E5C6200E0C0C9 /* show_certificates.c in Sources */, - E790C149169E5C6200E0C0C9 /* spc.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E7FEFB83169E363300E18152 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - E7FEFB91169E36D800E18152 /* keychain_sync.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 521C0BAC15FA5DA800604B61 /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 521C0BAD15FA5DA800604B61 /* en */, - ); - name = InfoPlist.strings; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 0C0BDB5D175687EC00BC1A7E /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Debug; - }; - 0C0BDB5E175687EC00BC1A7E /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Release; - }; - 18270F5714CF651900B05E7F /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - "GCC_PREPROCESSOR_DEFINITIONS[sdk=macosx*]" = ( - "$(inherited)", - "SECITEM_SHIM_OSX=1", - ); - }; - name = Debug; - }; - 18270F5814CF651900B05E7F /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - "GCC_PREPROCESSOR_DEFINITIONS[sdk=macosx*]" = ( - "$(inherited)", - "SECITEM_SHIM_OSX=1", - ); - }; - name = Release; - }; - 186CDD1114CA116C00AF9171 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9814CF1AAD00B05E7F /* debug.xcconfig */; - buildSettings = { - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - }; - name = Debug; - }; - 186CDD1214CA116C00AF9171 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9A14CF1AAD00B05E7F /* release.xcconfig */; - buildSettings = { - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - }; - name = Release; - }; - 186CDD1414CA116C00AF9171 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "$(inherited)", - "SECITEM_SHIM_OSX=1", - ); - SECITEM_SHIM_OSX = 1; - }; - name = Debug; - }; - 186CDD1514CA116C00AF9171 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "$(inherited)", - "SECITEM_SHIM_OSX=1", - ); - SECITEM_SHIM_OSX = 1; - }; - name = Release; - }; - 18D4043714CE0CF300A2BE4E /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - CLANG_WARN_CONSTANT_CONVERSION = NO; - CLANG_WARN_ENUM_CONVERSION = NO; - CLANG_WARN_INT_CONVERSION = NO; - COMBINE_HIDPI_IMAGES = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = NO; - }; - name = Debug; - }; - 18D4043814CE0CF300A2BE4E /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - CLANG_WARN_CONSTANT_CONVERSION = NO; - CLANG_WARN_ENUM_CONVERSION = NO; - CLANG_WARN_INT_CONVERSION = NO; - COMBINE_HIDPI_IMAGES = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = NO; - }; - name = Release; - }; - 18D4056414CE53C200A2BE4E /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - "GCC_PREPROCESSOR_DEFINITIONS[sdk=macosx*]" = ( - "$(inherited)", - "SECITEM_SHIM_OSX=1", - ); - }; - name = Debug; - }; - 18D4056514CE53C200A2BE4E /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - "GCC_PREPROCESSOR_DEFINITIONS[sdk=macosx*]" = ( - "$(inherited)", - "SECITEM_SHIM_OSX=1", - ); - }; - name = Release; - }; - 4A5CCA5015ACEFA500702357 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COMBINE_HIDPI_IMAGES = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - }; - name = Debug; - }; - 4A5CCA5115ACEFA500702357 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COMBINE_HIDPI_IMAGES = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - }; - name = Release; - }; - 4A824B01158FF07000F932C0 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Debug; - }; - 4A824B02158FF07000F932C0 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Release; - }; - 4CC92B1215A3BC6B00C6D578 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Debug; - }; - 4CC92B1315A3BC6B00C6D578 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Release; - }; - 528402AA164445760035F320 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 4C5EA365164C791400A136B8 /* lib-arc-only.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Debug; - }; - 528402AB164445760035F320 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 4C5EA365164C791400A136B8 /* lib-arc-only.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Release; - }; - E702E75414E1F3EA00CDE635 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Debug; - }; - E702E75514E1F3EA00CDE635 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Release; - }; - E702E77614E1F48800CDE635 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Debug; - }; - E702E77714E1F48800CDE635 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Release; - }; - E71049FB169E023B00DB0045 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Debug; - }; - E71049FC169E023B00DB0045 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Release; - }; - E7104A1B169E216E00DB0045 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Debug; - }; - E7104A1C169E216E00DB0045 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Release; - }; - E7FEFB8A169E363300E18152 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Debug; - }; - E7FEFB8B169E363300E18152 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18270C9914CF1AAD00B05E7F /* lib.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 0C0BDB5C175687EC00BC1A7E /* Build configuration list for PBXNativeTarget "libsecdRegressions" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0C0BDB5D175687EC00BC1A7E /* Debug */, - 0C0BDB5E175687EC00BC1A7E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 18270F5614CF651900B05E7F /* Build configuration list for PBXNativeTarget "libsecipc_client" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 18270F5714CF651900B05E7F /* Debug */, - 18270F5814CF651900B05E7F /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 186CDD0914CA116C00AF9171 /* Build configuration list for PBXProject "sec" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 186CDD1114CA116C00AF9171 /* Debug */, - 186CDD1214CA116C00AF9171 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 186CDD1314CA116C00AF9171 /* Build configuration list for PBXNativeTarget "libSecItemShimOSX" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 186CDD1414CA116C00AF9171 /* Debug */, - 186CDD1514CA116C00AF9171 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 18D4043614CE0CF300A2BE4E /* Build configuration list for PBXNativeTarget "libsecurity" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 18D4043714CE0CF300A2BE4E /* Debug */, - 18D4043814CE0CF300A2BE4E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 18D4056314CE53C200A2BE4E /* Build configuration list for PBXNativeTarget "libsecurityd" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 18D4056414CE53C200A2BE4E /* Debug */, - 18D4056514CE53C200A2BE4E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 4A5CCA5215ACEFA500702357 /* Build configuration list for PBXNativeTarget "libSecOtrOSX" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 4A5CCA5015ACEFA500702357 /* Debug */, - 4A5CCA5115ACEFA500702357 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 4A824B00158FF07000F932C0 /* Build configuration list for PBXNativeTarget "libSecurityRegressions" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 4A824B01158FF07000F932C0 /* Debug */, - 4A824B02158FF07000F932C0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 4CC92B1115A3BC6B00C6D578 /* Build configuration list for PBXNativeTarget "libsecuritydRegressions" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 4CC92B1215A3BC6B00C6D578 /* Debug */, - 4CC92B1315A3BC6B00C6D578 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 528402A9164445760035F320 /* Build configuration list for PBXNativeTarget "libCloudKeychainProxy" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 528402AA164445760035F320 /* Debug */, - 528402AB164445760035F320 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - E702E75314E1F3EA00CDE635 /* Build configuration list for PBXNativeTarget "libSecureObjectSync" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - E702E75414E1F3EA00CDE635 /* Debug */, - E702E75514E1F3EA00CDE635 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - E702E77514E1F48800CDE635 /* Build configuration list for PBXNativeTarget "libSOSRegressions" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - E702E77614E1F48800CDE635 /* Debug */, - E702E77714E1F48800CDE635 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - E71049FD169E023B00DB0045 /* Build configuration list for PBXNativeTarget "libSecurityTool" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - E71049FB169E023B00DB0045 /* Debug */, - E71049FC169E023B00DB0045 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - E7104A1A169E216E00DB0045 /* Build configuration list for PBXNativeTarget "libSecurityCommands" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - E7104A1B169E216E00DB0045 /* Debug */, - E7104A1C169E216E00DB0045 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - E7FEFB89169E363300E18152 /* Build configuration list for PBXNativeTarget "libSOSCommands" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - E7FEFB8A169E363300E18152 /* Debug */, - E7FEFB8B169E363300E18152 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 186CDD0614CA116C00AF9171 /* Project object */; -} diff --git a/sec/sec.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist b/sec/sec.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index c028ee75..00000000 --- a/sec/sec.xcodeproj/xcuserdata/jkauth.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,89 +0,0 @@ - - - - - SuppressBuildableAutocreation - - 0C0BDB55175687EC00BC1A7E - - primary - - - 18270F5414CF651900B05E7F - - primary - - - 186CDD0E14CA116C00AF9171 - - primary - - - 18D4043414CE0CF300A2BE4E - - primary - - - 18D4056114CE53C200A2BE4E - - primary - - - 4A5CCA4E15ACEFA500702357 - - primary - - - 4A824AFB158FF07000F932C0 - - primary - - - 4CC92AC215A3BC6B00C6D578 - - primary - - - 5284029F164445760035F320 - - primary - - - BEF963FE18B4171200813FA3 - - primary - - - E702E73514E1F3EA00CDE635 - - primary - - - E702E75714E1F48800CDE635 - - primary - - - E71049F1169E023B00DB0045 - - primary - - - E7104A12169E216E00DB0045 - - primary - - - E76079971951FD2800F69731 - - primary - - - E7FEFB82169E363300E18152 - - primary - - - - - diff --git a/sec/securityd/Regressions/SOSAccountTesting.h b/sec/securityd/Regressions/SOSAccountTesting.h deleted file mode 100644 index 00c1ec1f..00000000 --- a/sec/securityd/Regressions/SOSAccountTesting.h +++ /dev/null @@ -1,254 +0,0 @@ -// -// SOSAccountTesting.h -// sec -// -// Created by Mitch Adler on 6/18/13. -// -// - -#ifndef SEC_SOSAccountTesting_h -#define SEC_SOSAccountTesting_h - -#include -#include - -// -// Account comparison -// - -#define kAccountsAgreeTestMin 9 -#define kAccountsAgreeTestPerPeer 1 -#define accountsAgree(x) (kAccountsAgreeTestMin + kAccountsAgreeTestPerPeer * (x)) - -static void unretired_peers_is_subset(const char* label, CFArrayRef peers, CFArrayRef allowed_peers) -{ - CFArrayForEach(peers, ^(const void *value) { - SOSPeerInfoRef pi = (SOSPeerInfoRef) value; - CFErrorRef leftError = NULL; - CFErrorRef rightError = NULL; - - ok(SOSPeerInfoIsRetirementTicket(pi) || SOSPeerInfoIsCloudIdentity(pi) || CFArrayContainsValue(allowed_peers, CFRangeMake(0, CFArrayGetCount(allowed_peers)), pi), "Peer is allowed (%s) Peer: %@, Allowed %@", label, pi, allowed_peers); - - CFReleaseNull(leftError); - CFReleaseNull(rightError); - }); -} - -static void accounts_agree_internal(char *label, SOSAccountRef left, SOSAccountRef right, bool check_peers) -{ - CFErrorRef error = NULL; - { - CFArrayRef leftPeers = SOSAccountCopyActivePeers(left, &error); - ok(leftPeers, "Left peers (%@) - %s", error, label); - CFReleaseNull(error); - - CFArrayRef rightPeers = SOSAccountCopyActivePeers(right, &error); - ok(rightPeers, "Right peers (%@) - %s", error, label); - CFReleaseNull(error); - - ok(CFEqual(leftPeers, rightPeers), "Matching peers (%s) Left: %@, Right: %@", label, leftPeers, rightPeers); - - if (check_peers) { - CFMutableArrayRef allowed_identities = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - - CFArrayRef leftIdentities = SOSAccountCopyAccountIdentityPeerInfos(left, kCFAllocatorDefault, &error); - ok(leftIdentities, "Get identities (%@)", error); - CFReleaseNull(error); - - CFArrayAppendArray(allowed_identities, leftIdentities, CFRangeMake(0, CFArrayGetCount(leftIdentities))); - - CFReleaseNull(leftIdentities); - - CFArrayRef rightIdentities = SOSAccountCopyAccountIdentityPeerInfos(right, kCFAllocatorDefault, &error); - ok(rightIdentities, "Get identities (%@)", error); - CFReleaseNull(error); - - CFArrayAppendArray(allowed_identities, rightIdentities, CFRangeMake(0, CFArrayGetCount(rightIdentities))); - - CFReleaseNull(rightIdentities); - - unretired_peers_is_subset(label, leftPeers, allowed_identities); - } - - CFReleaseNull(leftPeers); - CFReleaseNull(rightPeers); - } - { - CFArrayRef leftConcurringPeers = SOSAccountCopyConcurringPeers(left, &error); - ok(leftConcurringPeers, "Left peers (%@) - %s", error, label); - - CFArrayRef rightConcurringPeers = SOSAccountCopyConcurringPeers(right, &error); - ok(rightConcurringPeers, "Right peers (%@) - %s", error, label); - - ok(CFEqual(leftConcurringPeers, rightConcurringPeers), "Matching concurring peers Left: %@, Right: %@", leftConcurringPeers, rightConcurringPeers); - - CFReleaseNull(leftConcurringPeers); - CFReleaseNull(rightConcurringPeers); - } - { - CFArrayRef leftApplicants = SOSAccountCopyApplicants(left, &error); - ok(leftApplicants, "Left Applicants (%@) - %s", error, label); - - CFArrayRef rightApplicants = SOSAccountCopyApplicants(right, &error); - ok(rightApplicants, "Left Applicants (%@) - %s", error, label); - - ok(CFEqual(leftApplicants, rightApplicants), "Matching applicants (%s) Left: %@, Right: %@", label, leftApplicants, rightApplicants); - - CFReleaseNull(leftApplicants); - CFReleaseNull(rightApplicants); - } -} - -static inline void accounts_agree(char *label, SOSAccountRef left, SOSAccountRef right) -{ - accounts_agree_internal(label, left, right, true); -} - - -// -// Change handling -// - -static CFMutableDictionaryRef ExtractPendingChanges(CFMutableDictionaryRef changes) -{ - CFMutableDictionaryRef extracted = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, changes); - - CFDictionaryRemoveAllValues(changes); - - return extracted; -} - -#define kFeedChangesToMultieTestCountPer 1 -static inline void FeedChangesToMulti(CFMutableDictionaryRef changes, ...) -{ - CFDictionaryRef changes_to_send = ExtractPendingChanges(changes); - - SOSAccountRef account; - - secerror("Change block: %@", changes_to_send); - - CFErrorRef error = NULL; - va_list argp; - va_start(argp, changes); - while((account = va_arg(argp, SOSAccountRef)) != NULL) { - ok(SOSAccountHandleUpdates(account, changes_to_send, &error), "SOSAccountHandleUpdates failed (%@)", error); - CFReleaseNull(error); - } -} - -static inline void InjectChangeToMulti(CFStringRef changeKey, CFStringRef changeValue, ...) -{ - CFMutableDictionaryRef changes_to_send = CFDictionaryCreateMutable(NULL, 1, NULL, NULL); - CFDictionaryAddValue(changes_to_send, changeKey, changeValue); - - SOSAccountRef account; - - secerror("Change block: %@", changes_to_send); - - CFErrorRef error = NULL; - va_list argp; - va_start(argp, changeValue); - while((account = va_arg(argp, SOSAccountRef)) != NULL) { - ok(SOSAccountHandleUpdates(account, changes_to_send, &error), "SOSAccountHandleUpdates failed (%@)", error); - CFReleaseNull(error); - } - CFReleaseNull(changes_to_send); -} - - - -#define kFeedChangesToTestCount 1 -static inline void FeedChangesTo(CFMutableDictionaryRef changes, SOSAccountRef account) -{ - CFDictionaryRef changes_to_send = ExtractPendingChanges(changes); - - secerror("Change block: %@", changes_to_send); - - CFErrorRef error = NULL; - ok(SOSAccountHandleUpdates(account, changes_to_send, &error), "SOSAccountHandleUpdates failed (%@)", error); - CFReleaseNull(error); - CFReleaseNull(changes_to_send); -} - - -static SOSAccountRef CreateAccountForLocalChanges(CFMutableDictionaryRef changes, CFStringRef name, CFStringRef data_source_name) -{ - SOSAccountKeyInterestBlock interest_block = ^(bool getNewKeysOnly, CFArrayRef alwaysKeys, CFArrayRef afterFirstUnlockKeys, CFArrayRef unlockedKeys) {}; - SOSAccountDataUpdateBlock update_block = ^ bool (CFDictionaryRef keys, CFErrorRef *error) { - CFDictionaryForEach(keys, ^(const void *key, const void *value) { - CFDictionarySetValue(changes, key, value); - }); - return true; - }; - - SOSDataSourceFactoryRef factory = SOSTestDataSourceFactoryCreate(); - SOSTestDataSourceFactoryAddDataSource(factory, data_source_name, SOSTestDataSourceCreate()); - - CFDictionaryRef gestalt = SOSCreatePeerGestaltFromName(name); - - SOSAccountRef result = SOSAccountCreate(kCFAllocatorDefault, gestalt, factory, interest_block, update_block); - - CFReleaseNull(gestalt); - - return result; -} - - -static inline int countPeers(SOSAccountRef account) { - CFErrorRef error = NULL; - CFArrayRef peers; - - peers = SOSAccountCopyPeers(account, &error); - int retval = (int) CFArrayGetCount(peers); - CFReleaseNull(error); - CFReleaseNull(peers); - return retval; -} - -static inline int countActivePeers(SOSAccountRef account) { - CFErrorRef error = NULL; - CFArrayRef peers; - - peers = SOSAccountCopyActivePeers(account, &error); - int retval = (int) CFArrayGetCount(peers); - CFReleaseNull(error); - CFReleaseNull(peers); - return retval; -} - -static inline int countActiveValidPeers(SOSAccountRef account) { - CFErrorRef error = NULL; - CFArrayRef peers; - - peers = SOSAccountCopyActiveValidPeers(account, &error); - int retval = (int) CFArrayGetCount(peers); - CFReleaseNull(error); - CFReleaseNull(peers); - return retval; -} - -static inline int countApplicants(SOSAccountRef account) { - CFErrorRef error = NULL; - CFArrayRef applicants = SOSAccountCopyApplicants(account, &error); - int retval = 0; - - if(applicants) retval = (int)CFArrayGetCount(applicants); - CFReleaseNull(error); - CFReleaseNull(applicants); - return retval; -} - - -static inline void showActiveValidPeers(SOSAccountRef account) { - CFErrorRef error = NULL; - CFArrayRef peers; - - peers = SOSAccountCopyActiveValidPeers(account, &error); - CFArrayForEach(peers, ^(const void *value) { - SOSPeerInfoRef pi = (SOSPeerInfoRef) value; - ok(0, "Active Valid Peer %@", pi); - }); - CFReleaseNull(peers); -} - -#endif diff --git a/sec/securityd/Regressions/SecdTestKeychainUtilities.c b/sec/securityd/Regressions/SecdTestKeychainUtilities.c deleted file mode 100644 index 07a9c0c4..00000000 --- a/sec/securityd/Regressions/SecdTestKeychainUtilities.c +++ /dev/null @@ -1,45 +0,0 @@ -// -// SecdKeychainUtilities.c -// sec -// -// Created by Mitch Adler on 6/11/13. -// -// - -#include "SecdTestKeychainUtilities.h" - -#include -#include -#include - -#include - -//#include -#include -#include -#include - -void kc_dbhandle_reset(void); - -void secd_test_setup_temp_keychain(const char* test_prefix, dispatch_block_t do_before_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); - - CFStringPerformWithCString(keychain_dir, ^(const char *keychain_dir_string) { - ok_unix(mkpath_np(keychain_dir_string, 0755), "Create temp dir"); - - printf("Created temporary directory %s\n", keychain_dir_string); - }); - - - /* set custom keychain dir, reset db */ - CFStringPerformWithCString(tmp_dir, ^(const char *tmp_dir_string) { - SetCustomHomeURL(tmp_dir_string); - }); - - if(do_before_reset) - do_before_reset(); - - kc_dbhandle_reset(); -} diff --git a/sec/securityd/Regressions/SecdTestKeychainUtilities.h b/sec/securityd/Regressions/SecdTestKeychainUtilities.h deleted file mode 100644 index a95da553..00000000 --- a/sec/securityd/Regressions/SecdTestKeychainUtilities.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// SecdTestKeychainUtilities.h -// sec -// -// Created by Mitch Adler on 6/11/13. -// -// - -#ifndef _SECDTESTKEYCHAINUTILITIES_ -#define _SECDTESTKEYCHAINUTILITIES_ - -#include - -#define kSecdTestSetupTestCount 1 -void secd_test_setup_temp_keychain(const char* test_prefix, dispatch_block_t do_before_reset); - -#endif diff --git a/sec/securityd/Regressions/brighton_keychain_2_db.h b/sec/securityd/Regressions/brighton_keychain_2_db.h deleted file mode 100644 index c994675f..00000000 --- a/sec/securityd/Regressions/brighton_keychain_2_db.h +++ /dev/null @@ -1,10586 +0,0 @@ -unsigned char brighton_keychain_2_db[] = { - 0x53, 0x51, 0x4c, 0x69, 0x74, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, - 0x74, 0x20, 0x33, 0x00, 0x10, 0x00, 0x01, 0x01, 0x00, 0x40, 0x20, 0x20, - 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, - 0x00, 0x2d, 0xe2, 0x25, 0x0d, 0x0f, 0xfc, 0x00, 0x17, 0x04, 0x99, 0x00, - 0x0e, 0x72, 0x0f, 0xd3, 0x0e, 0x20, 0x0b, 0xed, 0x0d, 0xf7, 0x0a, 0x89, - 0x0b, 0xc4, 0x07, 0xa8, 0x0a, 0x60, 0x07, 0x64, 0x07, 0x2d, 0x06, 0xf6, - 0x06, 0xbf, 0x06, 0x88, 0x06, 0x51, 0x06, 0x1a, 0x05, 0xe3, 0x05, 0xac, - 0x05, 0x75, 0x05, 0x3e, 0x05, 0x07, 0x04, 0xd0, 0x04, 0x99, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x35, 0x17, 0x06, 0x17, 0x17, 0x15, 0x01, 0x4d, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x69, 0x75, 0x6e, 0x77, 0x70, 0x6b, 0x65, 0x79, 0x73, 0x18, - 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x49, 0x4e, 0x44, 0x45, 0x58, - 0x20, 0x69, 0x75, 0x6e, 0x77, 0x70, 0x20, 0x4f, 0x4e, 0x20, 0x6b, 0x65, - 0x79, 0x73, 0x28, 0x75, 0x6e, 0x77, 0x70, 0x29, 0x35, 0x16, 0x06, 0x17, - 0x17, 0x15, 0x01, 0x4d, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x69, 0x77, 0x72, - 0x61, 0x70, 0x6b, 0x65, 0x79, 0x73, 0x17, 0x43, 0x52, 0x45, 0x41, 0x54, - 0x45, 0x20, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x20, 0x69, 0x77, 0x72, 0x61, - 0x70, 0x20, 0x4f, 0x4e, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x77, 0x72, - 0x61, 0x70, 0x29, 0x35, 0x15, 0x06, 0x17, 0x17, 0x15, 0x01, 0x4d, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x69, 0x76, 0x72, 0x66, 0x79, 0x6b, 0x65, 0x79, - 0x73, 0x16, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x49, 0x4e, 0x44, - 0x45, 0x58, 0x20, 0x69, 0x76, 0x72, 0x66, 0x79, 0x20, 0x4f, 0x4e, 0x20, - 0x6b, 0x65, 0x79, 0x73, 0x28, 0x76, 0x72, 0x66, 0x79, 0x29, 0x35, 0x14, - 0x06, 0x17, 0x17, 0x15, 0x01, 0x4d, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x69, - 0x73, 0x69, 0x67, 0x6e, 0x6b, 0x65, 0x79, 0x73, 0x15, 0x43, 0x52, 0x45, - 0x41, 0x54, 0x45, 0x20, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x20, 0x69, 0x73, - 0x69, 0x67, 0x6e, 0x20, 0x4f, 0x4e, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x28, - 0x73, 0x69, 0x67, 0x6e, 0x29, 0x35, 0x13, 0x06, 0x17, 0x17, 0x15, 0x01, - 0x4d, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x69, 0x64, 0x72, 0x76, 0x65, 0x6b, - 0x65, 0x79, 0x73, 0x14, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x49, - 0x4e, 0x44, 0x45, 0x58, 0x20, 0x69, 0x64, 0x72, 0x76, 0x65, 0x20, 0x4f, - 0x4e, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x64, 0x72, 0x76, 0x65, 0x29, - 0x35, 0x12, 0x06, 0x17, 0x17, 0x15, 0x01, 0x4d, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x69, 0x64, 0x65, 0x63, 0x72, 0x6b, 0x65, 0x79, 0x73, 0x13, 0x43, - 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x20, - 0x69, 0x64, 0x65, 0x63, 0x72, 0x20, 0x4f, 0x4e, 0x20, 0x6b, 0x65, 0x79, - 0x73, 0x28, 0x64, 0x65, 0x63, 0x72, 0x29, 0x35, 0x11, 0x06, 0x17, 0x17, - 0x15, 0x01, 0x4d, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x69, 0x65, 0x6e, 0x63, - 0x72, 0x6b, 0x65, 0x79, 0x73, 0x12, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, - 0x20, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x20, 0x69, 0x65, 0x6e, 0x63, 0x72, - 0x20, 0x4f, 0x4e, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x65, 0x6e, 0x63, - 0x72, 0x29, 0x35, 0x10, 0x06, 0x17, 0x17, 0x15, 0x01, 0x4d, 0x69, 0x6e, - 0x64, 0x65, 0x78, 0x69, 0x6b, 0x6c, 0x62, 0x6c, 0x6b, 0x65, 0x79, 0x73, - 0x11, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x49, 0x4e, 0x44, 0x45, - 0x58, 0x20, 0x69, 0x6b, 0x6c, 0x62, 0x6c, 0x20, 0x4f, 0x4e, 0x20, 0x6b, - 0x65, 0x79, 0x73, 0x28, 0x6b, 0x6c, 0x62, 0x6c, 0x29, 0x35, 0x0f, 0x06, - 0x17, 0x17, 0x15, 0x01, 0x4d, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x69, 0x6b, - 0x63, 0x6c, 0x73, 0x6b, 0x65, 0x79, 0x73, 0x10, 0x43, 0x52, 0x45, 0x41, - 0x54, 0x45, 0x20, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x20, 0x69, 0x6b, 0x63, - 0x6c, 0x73, 0x20, 0x4f, 0x4e, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x6b, - 0x63, 0x6c, 0x73, 0x29, 0x35, 0x0e, 0x06, 0x17, 0x17, 0x15, 0x01, 0x4d, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x69, 0x70, 0x6b, 0x68, 0x68, 0x63, 0x65, - 0x72, 0x74, 0x0f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x49, 0x4e, - 0x44, 0x45, 0x58, 0x20, 0x69, 0x70, 0x6b, 0x68, 0x68, 0x20, 0x4f, 0x4e, - 0x20, 0x63, 0x65, 0x72, 0x74, 0x28, 0x70, 0x6b, 0x68, 0x68, 0x29, 0x35, - 0x0d, 0x06, 0x17, 0x17, 0x15, 0x01, 0x4d, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x69, 0x73, 0x6b, 0x69, 0x64, 0x63, 0x65, 0x72, 0x74, 0x0e, 0x43, 0x52, - 0x45, 0x41, 0x54, 0x45, 0x20, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x20, 0x69, - 0x73, 0x6b, 0x69, 0x64, 0x20, 0x4f, 0x4e, 0x20, 0x63, 0x65, 0x72, 0x74, - 0x28, 0x73, 0x6b, 0x69, 0x64, 0x29, 0x35, 0x0c, 0x06, 0x17, 0x17, 0x15, - 0x01, 0x4d, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x69, 0x73, 0x75, 0x62, 0x6a, - 0x63, 0x65, 0x72, 0x74, 0x0d, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, - 0x49, 0x4e, 0x44, 0x45, 0x58, 0x20, 0x69, 0x73, 0x75, 0x62, 0x6a, 0x20, - 0x4f, 0x4e, 0x20, 0x63, 0x65, 0x72, 0x74, 0x28, 0x73, 0x75, 0x62, 0x6a, - 0x29, 0x35, 0x0b, 0x06, 0x17, 0x17, 0x15, 0x01, 0x4d, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x69, 0x61, 0x6c, 0x69, 0x73, 0x63, 0x65, 0x72, 0x74, 0x0c, - 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x49, 0x4e, 0x44, 0x45, 0x58, - 0x20, 0x69, 0x61, 0x6c, 0x69, 0x73, 0x20, 0x4f, 0x4e, 0x20, 0x63, 0x65, - 0x72, 0x74, 0x28, 0x61, 0x6c, 0x69, 0x73, 0x29, 0x42, 0x0a, 0x06, 0x17, - 0x1d, 0x1d, 0x01, 0x59, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x74, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x0b, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x54, 0x41, 0x42, - 0x4c, 0x45, 0x20, 0x74, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x28, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x4e, 0x54, 0x45, - 0x47, 0x45, 0x52, 0x29, 0x85, 0x35, 0x08, 0x07, 0x17, 0x15, 0x15, 0x01, - 0x8a, 0x4d, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x6b, 0x65, 0x79, 0x73, 0x6b, - 0x65, 0x79, 0x73, 0x09, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x54, - 0x41, 0x42, 0x4c, 0x45, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x72, 0x6f, - 0x77, 0x69, 0x64, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x20, - 0x50, 0x52, 0x49, 0x4d, 0x41, 0x52, 0x59, 0x20, 0x4b, 0x45, 0x59, 0x20, - 0x41, 0x55, 0x54, 0x4f, 0x49, 0x4e, 0x43, 0x52, 0x45, 0x4d, 0x45, 0x4e, - 0x54, 0x2c, 0x63, 0x64, 0x61, 0x74, 0x20, 0x52, 0x45, 0x41, 0x4c, 0x2c, - 0x6d, 0x64, 0x61, 0x74, 0x20, 0x52, 0x45, 0x41, 0x4c, 0x2c, 0x6b, 0x63, - 0x6c, 0x73, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x20, 0x4e, - 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, - 0x55, 0x4c, 0x54, 0x20, 0x30, 0x2c, 0x6c, 0x61, 0x62, 0x6c, 0x20, 0x42, - 0x4c, 0x4f, 0x42, 0x2c, 0x61, 0x6c, 0x69, 0x73, 0x20, 0x42, 0x4c, 0x4f, - 0x42, 0x2c, 0x70, 0x65, 0x72, 0x6d, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, - 0x45, 0x52, 0x2c, 0x70, 0x72, 0x69, 0x76, 0x20, 0x49, 0x4e, 0x54, 0x45, - 0x47, 0x45, 0x52, 0x2c, 0x6d, 0x6f, 0x64, 0x69, 0x20, 0x49, 0x4e, 0x54, - 0x45, 0x47, 0x45, 0x52, 0x2c, 0x6b, 0x6c, 0x62, 0x6c, 0x20, 0x42, 0x4c, - 0x4f, 0x42, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, - 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x27, 0x27, 0x2c, 0x61, - 0x74, 0x61, 0x67, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x20, 0x4e, 0x4f, 0x54, - 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, - 0x54, 0x20, 0x27, 0x27, 0x2c, 0x63, 0x72, 0x74, 0x72, 0x20, 0x49, 0x4e, - 0x54, 0x45, 0x47, 0x45, 0x52, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, - 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x30, - 0x2c, 0x74, 0x79, 0x70, 0x65, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, - 0x52, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, - 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x30, 0x2c, 0x62, 0x73, 0x69, - 0x7a, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x20, 0x4e, 0x4f, - 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, - 0x4c, 0x54, 0x20, 0x30, 0x2c, 0x65, 0x73, 0x69, 0x7a, 0x20, 0x49, 0x4e, - 0x54, 0x45, 0x47, 0x45, 0x52, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, - 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x30, - 0x2c, 0x73, 0x64, 0x61, 0x74, 0x20, 0x52, 0x45, 0x41, 0x4c, 0x20, 0x4e, - 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, - 0x55, 0x4c, 0x54, 0x20, 0x30, 0x2c, 0x65, 0x64, 0x61, 0x74, 0x20, 0x52, - 0x45, 0x41, 0x4c, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, - 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x30, 0x2c, 0x73, - 0x65, 0x6e, 0x73, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, - 0x61, 0x73, 0x65, 0x6e, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, - 0x2c, 0x65, 0x78, 0x74, 0x72, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, - 0x52, 0x2c, 0x6e, 0x65, 0x78, 0x74, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, - 0x45, 0x52, 0x2c, 0x65, 0x6e, 0x63, 0x72, 0x20, 0x49, 0x4e, 0x54, 0x45, - 0x47, 0x45, 0x52, 0x2c, 0x64, 0x65, 0x63, 0x72, 0x20, 0x49, 0x4e, 0x54, - 0x45, 0x47, 0x45, 0x52, 0x2c, 0x64, 0x72, 0x76, 0x65, 0x20, 0x49, 0x4e, - 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x73, 0x69, 0x67, 0x6e, 0x20, 0x49, - 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x76, 0x72, 0x66, 0x79, 0x20, - 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x73, 0x6e, 0x72, 0x63, - 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x76, 0x79, 0x72, - 0x63, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x77, 0x72, - 0x61, 0x70, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x75, - 0x6e, 0x77, 0x70, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, - 0x64, 0x61, 0x74, 0x61, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x61, 0x67, - 0x72, 0x70, 0x20, 0x54, 0x45, 0x58, 0x54, 0x2c, 0x70, 0x64, 0x6d, 0x6e, - 0x20, 0x54, 0x45, 0x58, 0x54, 0x2c, 0x55, 0x4e, 0x49, 0x51, 0x55, 0x45, - 0x28, 0x6b, 0x63, 0x6c, 0x73, 0x2c, 0x6b, 0x6c, 0x62, 0x6c, 0x2c, 0x61, - 0x74, 0x61, 0x67, 0x2c, 0x63, 0x72, 0x74, 0x72, 0x2c, 0x74, 0x79, 0x70, - 0x65, 0x2c, 0x62, 0x73, 0x69, 0x7a, 0x2c, 0x65, 0x73, 0x69, 0x7a, 0x2c, - 0x73, 0x64, 0x61, 0x74, 0x2c, 0x65, 0x64, 0x61, 0x74, 0x2c, 0x61, 0x67, - 0x72, 0x70, 0x29, 0x29, 0x27, 0x09, 0x06, 0x17, 0x3b, 0x15, 0x01, 0x00, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x73, 0x71, 0x6c, 0x69, 0x74, 0x65, 0x5f, - 0x61, 0x75, 0x74, 0x6f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x6b, 0x65, - 0x79, 0x73, 0x5f, 0x31, 0x6b, 0x65, 0x79, 0x73, 0x0a, 0x82, 0x38, 0x06, - 0x07, 0x17, 0x15, 0x15, 0x01, 0x84, 0x53, 0x74, 0x61, 0x62, 0x6c, 0x65, - 0x63, 0x65, 0x72, 0x74, 0x63, 0x65, 0x72, 0x74, 0x07, 0x43, 0x52, 0x45, - 0x41, 0x54, 0x45, 0x20, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x20, 0x63, 0x65, - 0x72, 0x74, 0x28, 0x72, 0x6f, 0x77, 0x69, 0x64, 0x20, 0x49, 0x4e, 0x54, - 0x45, 0x47, 0x45, 0x52, 0x20, 0x50, 0x52, 0x49, 0x4d, 0x41, 0x52, 0x59, - 0x20, 0x4b, 0x45, 0x59, 0x20, 0x41, 0x55, 0x54, 0x4f, 0x49, 0x4e, 0x43, - 0x52, 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x2c, 0x63, 0x64, 0x61, 0x74, 0x20, - 0x52, 0x45, 0x41, 0x4c, 0x2c, 0x6d, 0x64, 0x61, 0x74, 0x20, 0x52, 0x45, - 0x41, 0x4c, 0x2c, 0x63, 0x74, 0x79, 0x70, 0x20, 0x49, 0x4e, 0x54, 0x45, - 0x47, 0x45, 0x52, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, - 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x30, 0x2c, 0x63, - 0x65, 0x6e, 0x63, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, - 0x6c, 0x61, 0x62, 0x6c, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x61, 0x6c, - 0x69, 0x73, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x73, 0x75, 0x62, 0x6a, - 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x69, 0x73, 0x73, 0x72, 0x20, 0x42, - 0x4c, 0x4f, 0x42, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, - 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x27, 0x27, 0x2c, - 0x73, 0x6c, 0x6e, 0x72, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x20, 0x4e, 0x4f, - 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, - 0x4c, 0x54, 0x20, 0x27, 0x27, 0x2c, 0x73, 0x6b, 0x69, 0x64, 0x20, 0x42, - 0x4c, 0x4f, 0x42, 0x2c, 0x70, 0x6b, 0x68, 0x68, 0x20, 0x42, 0x4c, 0x4f, - 0x42, 0x2c, 0x64, 0x61, 0x74, 0x61, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, - 0x61, 0x67, 0x72, 0x70, 0x20, 0x54, 0x45, 0x58, 0x54, 0x2c, 0x70, 0x64, - 0x6d, 0x6e, 0x20, 0x54, 0x45, 0x58, 0x54, 0x2c, 0x55, 0x4e, 0x49, 0x51, - 0x55, 0x45, 0x28, 0x63, 0x74, 0x79, 0x70, 0x2c, 0x69, 0x73, 0x73, 0x72, - 0x2c, 0x73, 0x6c, 0x6e, 0x72, 0x2c, 0x61, 0x67, 0x72, 0x70, 0x29, 0x29, - 0x27, 0x07, 0x06, 0x17, 0x3b, 0x15, 0x01, 0x00, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x73, 0x71, 0x6c, 0x69, 0x74, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x6f, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x31, - 0x63, 0x65, 0x72, 0x74, 0x08, 0x84, 0x07, 0x04, 0x07, 0x17, 0x15, 0x15, - 0x01, 0x87, 0x71, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x69, 0x6e, 0x65, 0x74, - 0x69, 0x6e, 0x65, 0x74, 0x05, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, - 0x54, 0x41, 0x42, 0x4c, 0x45, 0x20, 0x69, 0x6e, 0x65, 0x74, 0x28, 0x72, - 0x6f, 0x77, 0x69, 0x64, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, - 0x20, 0x50, 0x52, 0x49, 0x4d, 0x41, 0x52, 0x59, 0x20, 0x4b, 0x45, 0x59, - 0x20, 0x41, 0x55, 0x54, 0x4f, 0x49, 0x4e, 0x43, 0x52, 0x45, 0x4d, 0x45, - 0x4e, 0x54, 0x2c, 0x63, 0x64, 0x61, 0x74, 0x20, 0x52, 0x45, 0x41, 0x4c, - 0x2c, 0x6d, 0x64, 0x61, 0x74, 0x20, 0x52, 0x45, 0x41, 0x4c, 0x2c, 0x64, - 0x65, 0x73, 0x63, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x69, 0x63, 0x6d, - 0x74, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x63, 0x72, 0x74, 0x72, 0x20, - 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x74, 0x79, 0x70, 0x65, - 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x73, 0x63, 0x72, - 0x70, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x6c, 0x61, - 0x62, 0x6c, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x61, 0x6c, 0x69, 0x73, - 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x69, 0x6e, 0x76, 0x69, 0x20, 0x49, - 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x6e, 0x65, 0x67, 0x61, 0x20, - 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x63, 0x75, 0x73, 0x69, - 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x70, 0x72, 0x6f, - 0x74, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x61, 0x63, 0x63, 0x74, 0x20, - 0x42, 0x4c, 0x4f, 0x42, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, - 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x27, 0x27, - 0x2c, 0x73, 0x64, 0x6d, 0x6e, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x20, 0x4e, - 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, - 0x55, 0x4c, 0x54, 0x20, 0x27, 0x27, 0x2c, 0x73, 0x72, 0x76, 0x72, 0x20, - 0x42, 0x4c, 0x4f, 0x42, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, - 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x27, 0x27, - 0x2c, 0x70, 0x74, 0x63, 0x6c, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, - 0x52, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, - 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x30, 0x2c, 0x61, 0x74, 0x79, - 0x70, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, - 0x55, 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, - 0x27, 0x27, 0x2c, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x49, 0x4e, 0x54, 0x45, - 0x47, 0x45, 0x52, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, - 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x30, 0x2c, 0x70, - 0x61, 0x74, 0x68, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x20, 0x4e, 0x4f, 0x54, - 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, - 0x54, 0x20, 0x27, 0x27, 0x2c, 0x64, 0x61, 0x74, 0x61, 0x20, 0x42, 0x4c, - 0x4f, 0x42, 0x2c, 0x61, 0x67, 0x72, 0x70, 0x20, 0x54, 0x45, 0x58, 0x54, - 0x2c, 0x70, 0x64, 0x6d, 0x6e, 0x20, 0x54, 0x45, 0x58, 0x54, 0x2c, 0x55, - 0x4e, 0x49, 0x51, 0x55, 0x45, 0x28, 0x61, 0x63, 0x63, 0x74, 0x2c, 0x73, - 0x64, 0x6d, 0x6e, 0x2c, 0x73, 0x72, 0x76, 0x72, 0x2c, 0x70, 0x74, 0x63, - 0x6c, 0x2c, 0x61, 0x74, 0x79, 0x70, 0x2c, 0x70, 0x6f, 0x72, 0x74, 0x2c, - 0x70, 0x61, 0x74, 0x68, 0x2c, 0x61, 0x67, 0x72, 0x70, 0x29, 0x29, 0x27, - 0x05, 0x06, 0x17, 0x3b, 0x15, 0x01, 0x00, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x73, 0x71, 0x6c, 0x69, 0x74, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x69, 0x6e, 0x65, 0x74, 0x5f, 0x31, 0x69, - 0x6e, 0x65, 0x74, 0x06, 0x50, 0x03, 0x06, 0x17, 0x2b, 0x2b, 0x01, 0x59, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x71, 0x6c, 0x69, 0x74, 0x65, 0x5f, - 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x71, 0x6c, 0x69, - 0x74, 0x65, 0x5f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x04, - 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x54, 0x41, 0x42, 0x4c, 0x45, - 0x20, 0x73, 0x71, 0x6c, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x65, 0x71, 0x75, - 0x65, 0x6e, 0x63, 0x65, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x73, 0x65, - 0x71, 0x29, 0x82, 0x5e, 0x01, 0x07, 0x17, 0x15, 0x15, 0x01, 0x85, 0x1f, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x67, 0x65, 0x6e, 0x70, 0x67, 0x65, 0x6e, - 0x70, 0x02, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x20, 0x54, 0x41, 0x42, - 0x4c, 0x45, 0x20, 0x67, 0x65, 0x6e, 0x70, 0x28, 0x72, 0x6f, 0x77, 0x69, - 0x64, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x20, 0x50, 0x52, - 0x49, 0x4d, 0x41, 0x52, 0x59, 0x20, 0x4b, 0x45, 0x59, 0x20, 0x41, 0x55, - 0x54, 0x4f, 0x49, 0x4e, 0x43, 0x52, 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x2c, - 0x63, 0x64, 0x61, 0x74, 0x20, 0x52, 0x45, 0x41, 0x4c, 0x2c, 0x6d, 0x64, - 0x61, 0x74, 0x20, 0x52, 0x45, 0x41, 0x4c, 0x2c, 0x64, 0x65, 0x73, 0x63, - 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x69, 0x63, 0x6d, 0x74, 0x20, 0x42, - 0x4c, 0x4f, 0x42, 0x2c, 0x63, 0x72, 0x74, 0x72, 0x20, 0x49, 0x4e, 0x54, - 0x45, 0x47, 0x45, 0x52, 0x2c, 0x74, 0x79, 0x70, 0x65, 0x20, 0x49, 0x4e, - 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x73, 0x63, 0x72, 0x70, 0x20, 0x49, - 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x6c, 0x61, 0x62, 0x6c, 0x20, - 0x42, 0x4c, 0x4f, 0x42, 0x2c, 0x61, 0x6c, 0x69, 0x73, 0x20, 0x42, 0x4c, - 0x4f, 0x42, 0x2c, 0x69, 0x6e, 0x76, 0x69, 0x20, 0x49, 0x4e, 0x54, 0x45, - 0x47, 0x45, 0x52, 0x2c, 0x6e, 0x65, 0x67, 0x61, 0x20, 0x49, 0x4e, 0x54, - 0x45, 0x47, 0x45, 0x52, 0x2c, 0x63, 0x75, 0x73, 0x69, 0x20, 0x49, 0x4e, - 0x54, 0x45, 0x47, 0x45, 0x52, 0x2c, 0x70, 0x72, 0x6f, 0x74, 0x20, 0x42, - 0x4c, 0x4f, 0x42, 0x2c, 0x61, 0x63, 0x63, 0x74, 0x20, 0x42, 0x4c, 0x4f, - 0x42, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, - 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x27, 0x27, 0x2c, 0x73, 0x76, - 0x63, 0x65, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x20, 0x4e, 0x4f, 0x54, 0x20, - 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, - 0x20, 0x27, 0x27, 0x2c, 0x67, 0x65, 0x6e, 0x61, 0x20, 0x42, 0x4c, 0x4f, - 0x42, 0x2c, 0x64, 0x61, 0x74, 0x61, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x2c, - 0x61, 0x67, 0x72, 0x70, 0x20, 0x54, 0x45, 0x58, 0x54, 0x2c, 0x70, 0x64, - 0x6d, 0x6e, 0x20, 0x54, 0x45, 0x58, 0x54, 0x2c, 0x55, 0x4e, 0x49, 0x51, - 0x55, 0x45, 0x28, 0x61, 0x63, 0x63, 0x74, 0x2c, 0x73, 0x76, 0x63, 0x65, - 0x2c, 0x61, 0x67, 0x72, 0x70, 0x29, 0x29, 0x27, 0x02, 0x06, 0x17, 0x3b, - 0x15, 0x01, 0x00, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x73, 0x71, 0x6c, 0x69, - 0x74, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x5f, 0x67, 0x65, 0x6e, 0x70, 0x5f, 0x31, 0x67, 0x65, 0x6e, 0x70, 0x03, - 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x01, 0x0f, 0xfb, 0x00, - 0x00, 0x00, 0x00, 0x1a, 0x0f, 0xfb, 0x0f, 0xf6, 0x04, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x55, 0x07, - 0x16, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x34, 0x34, 0x00, 0x88, 0x0a, 0x17, 0x13, 0x41, 0xb7, - 0x59, 0x5c, 0x7e, 0xdf, 0xaa, 0x7a, 0x41, 0xb7, 0x59, 0x5c, 0x7e, 0xdf, - 0xaa, 0x7a, 0x0b, 0x66, 0x7c, 0x18, 0x9e, 0x44, 0x49, 0x2d, 0x40, 0x62, - 0x95, 0x22, 0xa7, 0xe3, 0x08, 0x19, 0x26, 0x0f, 0xd6, 0x6d, 0x3a, 0xdc, - 0x09, 0xb3, 0xcd, 0x3d, 0x7c, 0x47, 0x10, 0xf5, 0x62, 0xa0, 0x5b, 0xd8, - 0x50, 0xe7, 0x56, 0xcb, 0xa1, 0xb8, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x64, 0x0f, 0xc5, 0x21, 0x02, 0x15, - 0x7c, 0xa5, 0xb2, 0x07, 0xf2, 0xee, 0xe7, 0xeb, 0x55, 0xb1, 0x73, 0x0b, - 0xc7, 0x85, 0xd2, 0x16, 0x2f, 0x68, 0x13, 0x3e, 0x6a, 0x6b, 0x3a, 0x3d, - 0xbd, 0x3d, 0xd9, 0xc4, 0x98, 0x92, 0xea, 0x5a, 0xf1, 0xf3, 0x69, 0x0e, - 0x20, 0x7b, 0x97, 0xca, 0xe6, 0x21, 0x45, 0x98, 0xcf, 0x92, 0x04, 0xf5, - 0xc9, 0x46, 0x27, 0xd4, 0x4f, 0x83, 0x2c, 0x3b, 0xbb, 0x83, 0x22, 0xa3, - 0x3c, 0x4e, 0x8e, 0x37, 0x6e, 0xe1, 0x6f, 0x80, 0x83, 0x0f, 0x19, 0xed, - 0x17, 0xdb, 0xd1, 0x96, 0xb9, 0x33, 0xe6, 0x25, 0x50, 0x4f, 0x40, 0x36, - 0xbf, 0x42, 0x46, 0xfc, 0x1c, 0x4a, 0x84, 0x9a, 0xb5, 0xcb, 0xe1, 0xee, - 0x4c, 0x84, 0xde, 0x41, 0x9f, 0x69, 0x3d, 0x9c, 0xe5, 0x38, 0x68, 0xb1, - 0x9c, 0x59, 0xd6, 0xcf, 0xcd, 0x76, 0xc3, 0xa7, 0x99, 0xf2, 0xe5, 0x8d, - 0x3b, 0x02, 0xcc, 0x1a, 0xed, 0x52, 0xd6, 0xef, 0x8f, 0xb2, 0xba, 0x11, - 0x39, 0xa5, 0x82, 0x12, 0x04, 0x2b, 0x03, 0xda, 0x41, 0x8c, 0x9e, 0xe1, - 0xc0, 0x8d, 0xdb, 0xff, 0x46, 0xce, 0xa9, 0xf3, 0x70, 0xf0, 0x5a, 0xd9, - 0x5e, 0xc1, 0xa3, 0xca, 0xd4, 0x02, 0x2a, 0xce, 0x49, 0x55, 0x61, 0x5d, - 0x22, 0xbf, 0xf6, 0x5a, 0xe6, 0xe4, 0xb4, 0x7a, 0xe2, 0x47, 0x24, 0x72, - 0xba, 0x8b, 0xd2, 0x39, 0x49, 0xf2, 0xa0, 0xda, 0xe6, 0xb6, 0xe1, 0x79, - 0xdc, 0x0d, 0x73, 0x1b, 0xe6, 0x40, 0xe4, 0xda, 0x74, 0x7c, 0xa4, 0x81, - 0x4b, 0x79, 0x8c, 0x23, 0x8d, 0xd5, 0x9d, 0xe0, 0x01, 0xe2, 0x88, 0xa8, - 0x3f, 0x09, 0xec, 0xf3, 0xa8, 0xd5, 0x8b, 0xe2, 0xef, 0x0e, 0x0c, 0x42, - 0x37, 0xc0, 0x2a, 0x7d, 0x25, 0x56, 0xc4, 0x28, 0xc3, 0x70, 0x73, 0xe7, - 0x14, 0xd0, 0xa8, 0x1e, 0x2a, 0xd7, 0xd6, 0x85, 0x0f, 0x4b, 0x94, 0x8d, - 0xa3, 0xb2, 0xee, 0x83, 0x36, 0x0a, 0x59, 0x4b, 0x8a, 0xc3, 0xf8, 0xd1, - 0x64, 0xb4, 0x07, 0x7c, 0x3d, 0x98, 0xaf, 0x7c, 0xd2, 0xed, 0x2a, 0xa2, - 0x91, 0xf4, 0x32, 0xa8, 0xf1, 0x67, 0x0a, 0x34, 0x75, 0x88, 0x4e, 0x69, - 0x78, 0xca, 0xa4, 0x0c, 0xf8, 0x40, 0x9f, 0x86, 0xd9, 0x16, 0x56, 0x67, - 0x74, 0xd4, 0x33, 0x9e, 0xb7, 0xef, 0xa6, 0xdf, 0x32, 0xb2, 0x24, 0x20, - 0xe7, 0xe9, 0x80, 0xdf, 0x7b, 0xa3, 0x49, 0x04, 0xd7, 0x3f, 0x9f, 0xbe, - 0xa6, 0x2d, 0xd0, 0xec, 0xed, 0x04, 0x76, 0xc9, 0x38, 0x0b, 0x2c, 0x02, - 0xcc, 0xd0, 0x98, 0x02, 0x73, 0x96, 0x6b, 0x8b, 0xcb, 0x2b, 0x57, 0x2d, - 0xab, 0x0d, 0x5e, 0x97, 0xb8, 0xd9, 0x81, 0xa6, 0x09, 0x7c, 0x6a, 0x6a, - 0xbe, 0xed, 0x44, 0xe1, 0x87, 0x2a, 0xbd, 0xad, 0x61, 0xfa, 0xdc, 0x76, - 0xaa, 0xa5, 0xfd, 0x40, 0xee, 0x9f, 0xf1, 0xc6, 0x74, 0xe9, 0xba, 0xc1, - 0xaf, 0xf1, 0x5d, 0x16, 0x06, 0x27, 0x60, 0x2b, 0x96, 0x9d, 0x0d, 0xc1, - 0x7c, 0xc3, 0x7b, 0xfd, 0x33, 0xc2, 0xa6, 0x7c, 0xbc, 0xc3, 0x1c, 0xef, - 0x9d, 0xf4, 0xe2, 0x8c, 0x2d, 0xe3, 0x01, 0xc1, 0x95, 0x24, 0x66, 0x15, - 0x1a, 0xa1, 0xa0, 0x61, 0x28, 0x8f, 0x44, 0x77, 0x80, 0xfc, 0x11, 0xce, - 0xad, 0xe1, 0xf1, 0xe9, 0x80, 0x55, 0x6d, 0x77, 0x5d, 0xf7, 0x2a, 0xf8, - 0x15, 0x42, 0xdd, 0xf6, 0x62, 0xac, 0x68, 0x8f, 0xaa, 0x85, 0xd8, 0xfa, - 0xc6, 0x21, 0xe9, 0xa8, 0xa2, 0x1e, 0xe3, 0xd4, 0x32, 0x3e, 0xee, 0xec, - 0x96, 0x54, 0xe1, 0xb1, 0x8f, 0x64, 0x59, 0xc6, 0x49, 0x01, 0x3c, 0xc0, - 0x17, 0xa9, 0xf5, 0xf2, 0x6f, 0x8a, 0xec, 0x9b, 0x66, 0xa7, 0x1d, 0x98, - 0xff, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x64, 0x6b, 0x75, 0x84, 0x07, 0x06, - 0x16, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x34, 0x34, 0x34, 0x86, 0x46, 0x17, 0x13, 0x41, 0xb7, - 0x59, 0x5c, 0x54, 0xdd, 0xc7, 0x58, 0x41, 0xb7, 0x59, 0x5c, 0x54, 0xdd, - 0xc7, 0x58, 0x8e, 0xc3, 0x7e, 0x3a, 0x0f, 0x3a, 0x3a, 0x7e, 0x0e, 0x1e, - 0x69, 0x08, 0x28, 0x2f, 0x21, 0x1c, 0x2a, 0x13, 0xa3, 0x59, 0xe5, 0x0e, - 0x4d, 0x78, 0x41, 0x89, 0x33, 0xa3, 0x28, 0x6d, 0xb9, 0x0a, 0x0b, 0x36, - 0x7b, 0xf9, 0xc7, 0xb9, 0x71, 0xe5, 0x1c, 0x32, 0x04, 0xe7, 0x79, 0xe1, - 0xe0, 0x05, 0x0b, 0xa0, 0xe7, 0xb9, 0xe1, 0x92, 0xbb, 0xa8, 0xae, 0xca, - 0xff, 0x1c, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, - 0x00, 0x00, 0x99, 0x02, 0x2d, 0xc5, 0xee, 0x94, 0x76, 0x6c, 0x0a, 0xe2, - 0xa1, 0xb1, 0x7a, 0x6d, 0x0c, 0xbf, 0x9d, 0xa2, 0x60, 0xdc, 0xb9, 0xf4, - 0xf9, 0x4e, 0x6f, 0x61, 0x37, 0x18, 0x86, 0xbf, 0xef, 0xe9, 0x55, 0x9e, - 0x44, 0x75, 0x32, 0x4c, 0x20, 0x82, 0xb5, 0x3d, 0x42, 0x72, 0x35, 0x69, - 0xba, 0x22, 0x95, 0x0c, 0xec, 0x46, 0xe8, 0x5b, 0x62, 0xe2, 0x07, 0xd4, - 0x80, 0x99, 0xc1, 0x83, 0x12, 0x3f, 0xcc, 0xd4, 0xf6, 0xcd, 0xc2, 0xb2, - 0xcd, 0x4d, 0x94, 0x4c, 0xab, 0x05, 0x48, 0x0c, 0x09, 0xe1, 0x82, 0x1a, - 0x6c, 0x0a, 0xf5, 0x16, 0x06, 0x57, 0x23, 0x9e, 0x18, 0xe8, 0xd9, 0xbb, - 0x4a, 0x8a, 0xcd, 0x69, 0xed, 0xc3, 0xae, 0x71, 0xe8, 0x8f, 0xeb, 0xb5, - 0x76, 0x50, 0xca, 0xb5, 0x69, 0x05, 0xdc, 0x93, 0x5b, 0x49, 0xed, 0xa3, - 0xf8, 0x25, 0xfe, 0x6a, 0x83, 0x6f, 0x16, 0x1e, 0xef, 0x5b, 0xfd, 0x24, - 0x7f, 0x9f, 0x66, 0xf1, 0x65, 0x8c, 0x38, 0x43, 0xd1, 0xbc, 0x13, 0x14, - 0x45, 0x75, 0x66, 0x3b, 0xd7, 0xe1, 0x7a, 0xde, 0xb1, 0xf6, 0x27, 0xd6, - 0x3e, 0xf6, 0x44, 0x7d, 0xf3, 0x3e, 0xd2, 0x95, 0x49, 0xe5, 0x31, 0x6f, - 0x38, 0x95, 0xd0, 0x78, 0xc8, 0xca, 0x68, 0xaf, 0xec, 0xab, 0x1e, 0xcf, - 0x0c, 0xff, 0x3e, 0xc4, 0x12, 0x3e, 0x48, 0xb4, 0x7e, 0x70, 0xc6, 0xa0, - 0x9b, 0xf8, 0x80, 0x30, 0x75, 0x25, 0x1a, 0xf1, 0xdf, 0x3a, 0x37, 0xa1, - 0xac, 0x43, 0x5b, 0xa0, 0xae, 0x9b, 0x91, 0xb3, 0x4a, 0xfa, 0x5f, 0x4b, - 0xf1, 0xba, 0xcd, 0x41, 0x92, 0x38, 0x6a, 0x8d, 0x69, 0x9e, 0xd3, 0x09, - 0xaa, 0x4c, 0xb2, 0x60, 0xcf, 0xff, 0x37, 0xed, 0xa0, 0x39, 0x36, 0x03, - 0x1a, 0x6a, 0xb7, 0xed, 0xce, 0xc8, 0x4e, 0x46, 0xb1, 0x82, 0xfb, 0xe1, - 0x46, 0x2d, 0x12, 0xf4, 0x8a, 0x6c, 0x38, 0x5c, 0x6b, 0xaa, 0x05, 0xf1, - 0xc0, 0xf2, 0x14, 0x8d, 0x3e, 0xdc, 0xec, 0x04, 0x0c, 0x94, 0xe3, 0xbf, - 0x3b, 0x7b, 0x3f, 0xa2, 0x88, 0x98, 0xe6, 0x0c, 0x5f, 0x23, 0x6d, 0x0b, - 0x6f, 0x8e, 0xe9, 0xce, 0xc0, 0xe2, 0x3e, 0xc7, 0xcd, 0xa0, 0x7b, 0xda, - 0xf1, 0x26, 0xfd, 0x3d, 0xc6, 0xe7, 0xe8, 0xed, 0x9d, 0xeb, 0x74, 0xc5, - 0x14, 0x5c, 0xee, 0xcd, 0x4d, 0xc4, 0x4e, 0x1b, 0x2d, 0x09, 0xf4, 0x7b, - 0xdb, 0xf6, 0x96, 0x17, 0x17, 0xd1, 0x16, 0xd5, 0xea, 0xaf, 0x4f, 0x7b, - 0xc2, 0x1e, 0x0f, 0xe1, 0x2c, 0xd8, 0x26, 0xe1, 0xcc, 0x66, 0x64, 0xd1, - 0x3f, 0xd9, 0x16, 0x99, 0x0c, 0xb1, 0x11, 0xc2, 0x13, 0xe5, 0xab, 0x99, - 0x2a, 0x6f, 0x09, 0x37, 0xc5, 0x7c, 0x8e, 0xb8, 0x04, 0x73, 0x3b, 0x0b, - 0x58, 0x87, 0x10, 0x33, 0x1f, 0x5d, 0xea, 0xe9, 0xcd, 0x4e, 0x5b, 0x33, - 0x88, 0xc2, 0x9c, 0x01, 0x1a, 0xe6, 0x92, 0x57, 0xf9, 0xa8, 0x7d, 0x03, - 0x76, 0x79, 0x4e, 0x1e, 0x25, 0xe8, 0xae, 0x61, 0x70, 0x70, 0x6c, 0x65, - 0x64, 0x6b, 0x75, 0x83, 0x0b, 0x05, 0x16, 0x00, 0x07, 0x07, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x34, 0x00, - 0x84, 0x3c, 0x29, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x53, 0x32, 0x4a, 0x6b, - 0x41, 0xb7, 0x59, 0x5c, 0x53, 0x32, 0x4a, 0x6b, 0x65, 0x6d, 0xb0, 0x14, - 0x83, 0xdf, 0x17, 0xb6, 0x73, 0x59, 0x09, 0xd6, 0x8a, 0xed, 0x02, 0x13, - 0x5a, 0x8b, 0xd4, 0x99, 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, - 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, - 0xaa, 0xa7, 0xbf, 0x94, 0x09, 0x4f, 0x35, 0x59, 0x31, 0xba, 0xaa, 0x89, - 0x4f, 0xfa, 0x26, 0x41, 0x66, 0x87, 0x1b, 0x60, 0x02, 0x00, 0x00, 0x00, - 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xdc, 0x97, 0xef, 0xa5, - 0xc0, 0xbc, 0x15, 0x38, 0x95, 0x35, 0x74, 0x61, 0x34, 0x68, 0xb9, 0x5c, - 0xef, 0x21, 0xad, 0xeb, 0xc9, 0x50, 0x73, 0xed, 0x31, 0x38, 0x33, 0x44, - 0x03, 0x44, 0x16, 0xaf, 0xa2, 0xba, 0x34, 0x58, 0x3f, 0x49, 0xaf, 0x93, - 0xf8, 0xe4, 0x6e, 0x6f, 0x7f, 0x23, 0x05, 0x46, 0x75, 0x49, 0xdf, 0x84, - 0xad, 0x64, 0x83, 0x11, 0x43, 0xd9, 0x80, 0x11, 0x93, 0x6d, 0xcf, 0xb4, - 0x72, 0x42, 0xc2, 0x5a, 0x78, 0x57, 0x37, 0x2d, 0x9e, 0x9a, 0x3e, 0x30, - 0x9b, 0x72, 0x7b, 0xfa, 0x1d, 0x9e, 0x2d, 0x53, 0x16, 0x85, 0x91, 0x3c, - 0xe9, 0xf1, 0x39, 0x60, 0x1d, 0x9e, 0xc6, 0xee, 0xb1, 0xdc, 0xb1, 0x0d, - 0xb8, 0x23, 0x68, 0xbf, 0xe5, 0x08, 0xc4, 0xac, 0x31, 0x4e, 0x2d, 0x0f, - 0x1f, 0xe1, 0xb3, 0xfe, 0xd2, 0x31, 0x4a, 0x52, 0x3e, 0x03, 0xe1, 0x1a, - 0x66, 0x58, 0x8b, 0x56, 0x99, 0x55, 0x7f, 0x6f, 0x5a, 0xa9, 0x8f, 0xcf, - 0xb3, 0x03, 0x96, 0x79, 0xb0, 0x6c, 0x67, 0x60, 0x35, 0xce, 0x8d, 0xc6, - 0x1c, 0x70, 0x05, 0xa4, 0x5e, 0x4f, 0x83, 0x4f, 0x1a, 0x98, 0x88, 0xdd, - 0x5a, 0x5d, 0xb3, 0x9b, 0xf6, 0xb2, 0xa3, 0x2e, 0x1c, 0x41, 0x81, 0x97, - 0xef, 0x16, 0xb3, 0x8e, 0xbe, 0x09, 0x08, 0x3d, 0x47, 0xaa, 0x2b, 0x90, - 0x61, 0xc7, 0x67, 0xcb, 0x0d, 0xa5, 0x7a, 0x58, 0x4d, 0xa7, 0x9f, 0xd4, - 0x21, 0xf2, 0x47, 0x65, 0x3b, 0x9e, 0x3b, 0xa4, 0xb4, 0x15, 0x05, 0x10, - 0xee, 0x90, 0xe5, 0xd9, 0x2e, 0xa0, 0xfe, 0x85, 0x9c, 0xad, 0x37, 0x71, - 0x51, 0xba, 0x0e, 0x91, 0x48, 0x3e, 0x54, 0xa0, 0x10, 0x1b, 0xc7, 0xff, - 0x4b, 0xd2, 0x24, 0xf8, 0x37, 0xd9, 0xc3, 0x17, 0x12, 0x05, 0x28, 0xbe, - 0xeb, 0xf5, 0xa3, 0x5a, 0x93, 0x7b, 0x9e, 0x59, 0xb2, 0x63, 0xbc, 0x71, - 0x61, 0x6a, 0x5a, 0x6c, 0xbd, 0xae, 0xeb, 0xff, 0x2a, 0x53, 0xf3, 0x44, - 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x61, 0x70, - 0x73, 0x64, 0x64, 0x6b, 0x75, 0x00, 0x00, 0x01, 0x87, 0x00, 0x07, 0x07, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, - 0x34, 0x34, 0x84, 0x40, 0x17, 0x13, 0x41, 0xb7, 0x59, 0x51, 0x13, 0x75, - 0xf7, 0x83, 0x41, 0xb7, 0x59, 0x51, 0x13, 0x75, 0xf7, 0x83, 0x8e, 0xc3, - 0x7e, 0x3a, 0x0f, 0x3a, 0x3a, 0x7e, 0x0e, 0x1e, 0x69, 0x08, 0x28, 0x2f, - 0x21, 0x1c, 0x2a, 0x13, 0xa3, 0x59, 0xe5, 0x0e, 0x4d, 0x78, 0x41, 0x89, - 0x33, 0xa3, 0x28, 0x6d, 0xb9, 0x0a, 0x0b, 0x36, 0x7b, 0xf9, 0xc7, 0xb9, - 0x71, 0xe5, 0xce, 0x65, 0x7a, 0x52, 0xa0, 0x52, 0xa3, 0xaa, 0xf5, 0x34, - 0xec, 0xfb, 0xf7, 0xcb, 0xdd, 0xe4, 0xee, 0x33, 0x4c, 0x10, 0x02, 0x00, - 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xc9, 0xa4, - 0xb0, 0xbb, 0x30, 0xa3, 0x3d, 0x27, 0x05, 0x4f, 0x4c, 0x5e, 0x1f, 0x82, - 0x66, 0x8e, 0x02, 0x48, 0x36, 0x3c, 0x6b, 0xa3, 0x16, 0x82, 0x0c, 0x12, - 0x58, 0xe2, 0xb6, 0x5f, 0xe3, 0x0a, 0x20, 0xfd, 0xad, 0xa0, 0xc7, 0x99, - 0x65, 0x78, 0xfe, 0x99, 0xa5, 0xac, 0x48, 0x47, 0x0e, 0x2d, 0xc3, 0x76, - 0x76, 0xcb, 0xca, 0x9b, 0xb7, 0xe5, 0x3b, 0x4a, 0xca, 0x8a, 0xb6, 0x6f, - 0x22, 0x08, 0xcb, 0xb4, 0xc6, 0xf6, 0xba, 0x30, 0x52, 0x57, 0x1b, 0x09, - 0xc8, 0x9a, 0x3e, 0xde, 0x73, 0x81, 0xde, 0xb7, 0xc2, 0x2d, 0x46, 0xc9, - 0x52, 0x9f, 0x4b, 0xef, 0x2c, 0x2f, 0x5c, 0xa3, 0x10, 0x98, 0x0d, 0x57, - 0x0b, 0x4c, 0xc5, 0xeb, 0x49, 0x49, 0x7f, 0xae, 0xc3, 0x45, 0xbe, 0x0a, - 0x7d, 0x37, 0x94, 0xc4, 0xfe, 0x53, 0xdf, 0x10, 0x55, 0x98, 0xf9, 0x68, - 0x2a, 0xf7, 0x42, 0x48, 0x6b, 0xa7, 0x5b, 0x3d, 0xa3, 0x9f, 0xed, 0xf2, - 0x70, 0xcb, 0x64, 0x74, 0xa8, 0xfa, 0xdc, 0xe4, 0x5e, 0x90, 0x6f, 0x79, - 0x18, 0x19, 0xc8, 0xbf, 0xf3, 0x78, 0xd9, 0x35, 0x07, 0x42, 0x5f, 0xc6, - 0x04, 0x09, 0x62, 0x1f, 0xa4, 0xe2, 0x67, 0x06, 0x46, 0x47, 0xac, 0x53, - 0x7d, 0x0e, 0xbb, 0xd7, 0xbd, 0x51, 0x00, 0x60, 0x44, 0xa9, 0x47, 0x60, - 0xd5, 0x7f, 0xc4, 0x45, 0xdb, 0xd5, 0x42, 0xbe, 0x8e, 0x5d, 0x89, 0xbd, - 0xb4, 0xe7, 0x6e, 0xdf, 0xcc, 0x21, 0x10, 0x2c, 0x8d, 0xe8, 0x6e, 0x2c, - 0xb8, 0x72, 0x0e, 0x86, 0xe9, 0xd4, 0x08, 0x93, 0xf3, 0xb3, 0x2a, 0x00, - 0xa0, 0xe2, 0x1f, 0xc4, 0x09, 0x3b, 0x75, 0x81, 0x99, 0x17, 0x5b, 0x78, - 0x27, 0x32, 0x6d, 0x0b, 0x29, 0x31, 0x51, 0x70, 0x50, 0x95, 0x0c, 0x94, - 0x90, 0xba, 0x18, 0x17, 0x44, 0x6b, 0xd8, 0x50, 0x58, 0xe8, 0xe2, 0xff, - 0x80, 0xb9, 0x44, 0xfe, 0x1b, 0x8f, 0xdf, 0xa1, 0x91, 0xeb, 0x57, 0x86, - 0xd0, 0x61, 0x1a, 0x09, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x64, 0x6b, 0x75, - 0x84, 0x43, 0x02, 0x16, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x34, 0x00, 0x87, 0x66, 0x17, - 0x13, 0x41, 0xb7, 0x59, 0x50, 0xd8, 0x37, 0x6c, 0x27, 0x41, 0xb7, 0x59, - 0x50, 0xd8, 0x37, 0x6c, 0x27, 0x77, 0xac, 0x86, 0x8b, 0xf9, 0xb8, 0xa0, - 0x50, 0x0b, 0x1f, 0xb3, 0x50, 0x55, 0xe2, 0x63, 0x81, 0xf6, 0x85, 0xbc, - 0xeb, 0x06, 0x98, 0x7e, 0x8b, 0x09, 0xd8, 0x2e, 0xbe, 0x8c, 0x6b, 0x51, - 0x5c, 0x08, 0x13, 0x58, 0xb4, 0x2e, 0x41, 0xcb, 0x34, 0x02, 0x00, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xf6, 0xbc, 0x81, - 0x5b, 0x23, 0x66, 0x44, 0x13, 0x27, 0xcf, 0x98, 0xc2, 0xc0, 0x31, 0x38, - 0x98, 0xec, 0x01, 0x84, 0xbb, 0x38, 0xb1, 0x79, 0xd7, 0x91, 0x66, 0x5a, - 0x56, 0x22, 0x62, 0x6f, 0xb8, 0xf0, 0x68, 0x00, 0xe7, 0x1a, 0x7a, 0x93, - 0xfc, 0xa8, 0xd4, 0xd9, 0xaf, 0x21, 0x17, 0x71, 0xf3, 0x0c, 0xd6, 0x22, - 0x2f, 0xb0, 0xb7, 0xc3, 0x1e, 0x07, 0xe7, 0x53, 0x34, 0xc9, 0x17, 0x9d, - 0xe8, 0xd3, 0x07, 0x78, 0xe7, 0x74, 0xcd, 0xf0, 0xdd, 0x88, 0x0d, 0x30, - 0x9b, 0x3c, 0x78, 0xfb, 0x43, 0xb7, 0x4f, 0x79, 0xd1, 0x83, 0xcd, 0x56, - 0x60, 0xe7, 0x7e, 0x8d, 0xba, 0x61, 0x9d, 0x4f, 0xf2, 0x71, 0x9b, 0xbd, - 0x11, 0xfc, 0x82, 0x8f, 0xc2, 0x9b, 0x32, 0xb7, 0x4d, 0x5d, 0x93, 0x87, - 0x11, 0x7d, 0xbf, 0x3a, 0x06, 0x11, 0x15, 0xf5, 0x97, 0xf4, 0x03, 0x24, - 0x6a, 0xfb, 0x5e, 0x27, 0x2b, 0xb5, 0xac, 0x20, 0x84, 0xe8, 0x8d, 0x67, - 0xa9, 0xf5, 0x41, 0x8a, 0xbd, 0xea, 0x51, 0x91, 0x30, 0xd7, 0xf2, 0x81, - 0x12, 0xbc, 0x24, 0x61, 0x25, 0x58, 0x9e, 0x4a, 0x4c, 0x89, 0xa4, 0x19, - 0xf1, 0x12, 0xe2, 0x33, 0xf1, 0x37, 0x1f, 0x0f, 0xa0, 0x42, 0xa1, 0x0e, - 0xa2, 0xc4, 0x06, 0xb0, 0xba, 0x61, 0xef, 0xc5, 0x6b, 0x46, 0x33, 0x62, - 0x50, 0xe0, 0xe4, 0x2e, 0x74, 0x20, 0xf4, 0x54, 0xbb, 0xed, 0xa0, 0x73, - 0x51, 0xa5, 0xc6, 0x55, 0x90, 0x61, 0xe9, 0x9c, 0x76, 0x72, 0x21, 0xa9, - 0x19, 0x1a, 0xbd, 0xcf, 0x61, 0x29, 0x8a, 0xef, 0xdd, 0xe0, 0xc6, 0x0a, - 0xf0, 0xd8, 0x50, 0xb9, 0xe9, 0x92, 0x7d, 0xf3, 0xce, 0x7e, 0x9e, 0xcf, - 0x32, 0x92, 0xc7, 0x49, 0x59, 0x23, 0xb5, 0x4e, 0xf2, 0x71, 0xf0, 0xda, - 0xb3, 0x80, 0xe3, 0xb6, 0x7a, 0xe4, 0x14, 0x80, 0x25, 0x3e, 0xd0, 0x89, - 0x13, 0xf4, 0x70, 0x96, 0xee, 0xbe, 0xef, 0x31, 0x61, 0xa1, 0x8d, 0xf7, - 0x9a, 0x5c, 0x92, 0x0a, 0x9b, 0x1f, 0x8c, 0x5e, 0x3d, 0x37, 0x24, 0xc2, - 0x8d, 0x21, 0xe9, 0x47, 0x2e, 0x03, 0xee, 0x32, 0xbf, 0x46, 0xc7, 0x2c, - 0x6e, 0x7a, 0x81, 0x9e, 0x14, 0xb8, 0xbe, 0xdb, 0x22, 0x4f, 0xf1, 0x8d, - 0x47, 0x41, 0x84, 0xc9, 0xeb, 0x4f, 0xe9, 0xf4, 0xad, 0xc4, 0xbe, 0xf8, - 0x28, 0xcb, 0xe6, 0x16, 0xa8, 0x6b, 0xaf, 0xd5, 0x0a, 0x6d, 0x06, 0x59, - 0x4f, 0x7d, 0x53, 0xa6, 0x4e, 0x90, 0xa0, 0x23, 0x1b, 0x92, 0xf0, 0xe8, - 0xef, 0xed, 0x0d, 0xa7, 0x64, 0x01, 0x83, 0x4a, 0x3b, 0x2d, 0x18, 0x90, - 0x1d, 0x19, 0x1d, 0xa2, 0x98, 0xe9, 0xb5, 0xe4, 0x4a, 0x73, 0xcf, 0xdf, - 0x0c, 0x09, 0xd5, 0xf4, 0xd3, 0xd9, 0x12, 0x7c, 0xbb, 0x81, 0x51, 0x26, - 0x2a, 0xcb, 0xa7, 0xc9, 0x6a, 0xe9, 0xfb, 0x1d, 0xca, 0x43, 0xf1, 0xbe, - 0xfb, 0xc3, 0x6f, 0xb6, 0xa1, 0x0c, 0x42, 0x32, 0x18, 0x24, 0x63, 0xf9, - 0xa0, 0x7e, 0x71, 0x8c, 0xa5, 0x16, 0x16, 0x5a, 0x5e, 0x15, 0x5d, 0x6d, - 0x4b, 0x74, 0x5b, 0xde, 0x21, 0xd5, 0xe0, 0x11, 0xa6, 0x91, 0xc3, 0xb2, - 0xd7, 0x38, 0x70, 0xa2, 0x18, 0x29, 0x1b, 0xdc, 0x83, 0x3e, 0x37, 0x45, - 0xc4, 0x1b, 0x61, 0x98, 0x06, 0x12, 0x3e, 0xc0, 0xda, 0x1a, 0xc9, 0x18, - 0x9c, 0x50, 0x0e, 0xc5, 0xe1, 0xa7, 0x4d, 0x05, 0xc6, 0x99, 0x31, 0xab, - 0x17, 0x30, 0xb9, 0xb0, 0x01, 0x1f, 0x93, 0xd9, 0x76, 0xd4, 0x67, 0x0b, - 0xea, 0x7b, 0x2b, 0x0b, 0x42, 0x97, 0x40, 0x07, 0x94, 0x08, 0x61, 0x70, - 0x70, 0x6c, 0x65, 0x64, 0x6b, 0x75, 0x84, 0x3f, 0x01, 0x16, 0x00, 0x07, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x34, 0x34, 0x00, 0x87, 0x5e, 0x17, 0x13, 0x41, 0xb7, 0x59, 0x50, 0xd8, - 0x33, 0x2b, 0x24, 0x41, 0xb7, 0x59, 0x50, 0xd8, 0x33, 0x2b, 0x24, 0x83, - 0xad, 0xb6, 0xae, 0x9f, 0x27, 0xa5, 0x45, 0x30, 0xb3, 0x67, 0xc8, 0x32, - 0x58, 0x95, 0x85, 0x06, 0xeb, 0xc1, 0xf4, 0x06, 0x98, 0x7e, 0x8b, 0x09, - 0xd8, 0x2e, 0xbe, 0x8c, 0x6b, 0x51, 0x5c, 0x08, 0x13, 0x58, 0xb4, 0x2e, - 0x41, 0xcb, 0x34, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, - 0x00, 0x00, 0x00, 0x99, 0xb4, 0x79, 0xc1, 0x37, 0xc1, 0xe1, 0x5c, 0x49, - 0xa0, 0xe1, 0xf3, 0x17, 0xb8, 0x9c, 0x69, 0xe6, 0xba, 0xdc, 0xe7, 0x78, - 0xb2, 0x5d, 0xd6, 0x95, 0xbe, 0xb2, 0xda, 0x91, 0xd3, 0x9b, 0xf2, 0xd4, - 0xe3, 0x95, 0x3c, 0x53, 0x8d, 0x0e, 0x68, 0xe9, 0x02, 0xb3, 0xed, 0xeb, - 0x95, 0xdd, 0x11, 0xb2, 0x64, 0x69, 0x8a, 0xfe, 0x03, 0x05, 0xd5, 0x04, - 0x9b, 0xac, 0x8a, 0xb6, 0x98, 0x29, 0x56, 0x2e, 0xd3, 0xea, 0x4e, 0x84, - 0xee, 0x23, 0x44, 0x03, 0x12, 0x9d, 0x9c, 0x9c, 0x9f, 0x11, 0x62, 0xf0, - 0x86, 0x36, 0x52, 0x15, 0x0f, 0x27, 0x93, 0xdb, 0xde, 0x13, 0xc9, 0x94, - 0x93, 0xe4, 0xa4, 0x6f, 0x58, 0x9d, 0x58, 0x9f, 0x15, 0xba, 0x5f, 0x4c, - 0xf3, 0x9a, 0x90, 0xc0, 0xcb, 0x60, 0xce, 0x9b, 0x56, 0x0c, 0xfe, 0x5b, - 0xd2, 0x4e, 0x0e, 0x82, 0xe6, 0x4c, 0x62, 0x57, 0x08, 0x6e, 0x5d, 0x54, - 0x7b, 0x28, 0xbb, 0x88, 0xdc, 0xec, 0xaa, 0xd1, 0x6e, 0xd3, 0x94, 0x20, - 0x3e, 0x35, 0x81, 0x52, 0xf6, 0xe9, 0xee, 0x42, 0x89, 0xe9, 0xea, 0x61, - 0x2c, 0xd8, 0xdc, 0xe3, 0x82, 0xf7, 0xf0, 0xc0, 0xf6, 0xf9, 0xb7, 0xef, - 0x49, 0xc7, 0x8d, 0x6c, 0x8a, 0x6d, 0x6e, 0xbc, 0x2d, 0xc0, 0xb1, 0xec, - 0x0c, 0xdd, 0xe5, 0xbe, 0x65, 0x3f, 0x69, 0x81, 0xcf, 0xe8, 0xd8, 0xf3, - 0x57, 0x8e, 0xba, 0x73, 0x7f, 0xb0, 0x4e, 0x65, 0xa2, 0xa5, 0xa5, 0xbb, - 0x7b, 0xae, 0xaa, 0x88, 0x06, 0x4f, 0x2c, 0x43, 0xb9, 0x4c, 0x17, 0xa1, - 0x24, 0xfb, 0xe1, 0x90, 0x50, 0xdb, 0xcc, 0xd9, 0xe5, 0x7b, 0x09, 0xaf, - 0x5c, 0x5a, 0x4f, 0xb2, 0x2b, 0x30, 0x53, 0x0f, 0xd3, 0xe2, 0xbd, 0xcd, - 0xf7, 0xa3, 0x19, 0xdc, 0xba, 0xee, 0xd1, 0x49, 0xbc, 0xa6, 0xde, 0x1b, - 0xe6, 0xd3, 0xaf, 0xdd, 0x61, 0xf6, 0xfd, 0xef, 0xb7, 0xda, 0x9d, 0x93, - 0x45, 0x0a, 0xa2, 0xa8, 0x1a, 0xe5, 0x16, 0xb1, 0xaf, 0x20, 0x00, 0x86, - 0x6b, 0x66, 0x42, 0x97, 0x4e, 0x3a, 0xea, 0x0d, 0x33, 0xb2, 0x93, 0x87, - 0x9c, 0xd1, 0x6a, 0x20, 0xbc, 0xc9, 0x7d, 0x46, 0xb9, 0x0a, 0x26, 0x9a, - 0x09, 0x81, 0xc8, 0x6d, 0x9b, 0x63, 0xa5, 0x1f, 0x63, 0x72, 0x6c, 0xa8, - 0x65, 0x65, 0xa2, 0x8a, 0x81, 0x4d, 0x54, 0xd4, 0xa3, 0xc4, 0x86, 0x48, - 0x31, 0x5c, 0x4e, 0x15, 0xf3, 0x48, 0x30, 0xbc, 0x17, 0xac, 0x0b, 0x85, - 0x8f, 0x44, 0x62, 0xf4, 0x57, 0xc7, 0xbd, 0x18, 0xcf, 0xf5, 0xd8, 0xa9, - 0x2d, 0xf5, 0x57, 0xaf, 0x42, 0x09, 0xf7, 0x5b, 0x25, 0x56, 0xa1, 0x04, - 0x0c, 0xf7, 0xa7, 0xc9, 0x2d, 0xd7, 0x84, 0x78, 0x86, 0x82, 0x2d, 0xd3, - 0xaa, 0xd2, 0xbf, 0x77, 0xc0, 0x34, 0x7b, 0xdb, 0x7e, 0x4d, 0xde, 0x63, - 0x8f, 0xcc, 0xb6, 0x6d, 0x01, 0x80, 0x68, 0x51, 0x3e, 0x8f, 0x2a, 0x7c, - 0x0e, 0xaa, 0xc2, 0xbf, 0x77, 0x12, 0x06, 0x88, 0xdf, 0x3f, 0x6c, 0x7d, - 0x69, 0x05, 0x57, 0x71, 0xeb, 0xe7, 0xf3, 0xcb, 0x32, 0x4d, 0x33, 0x54, - 0x8a, 0x2a, 0x1b, 0xb5, 0x6e, 0xb6, 0xa4, 0x64, 0xcd, 0x34, 0x5c, 0xa9, - 0x3d, 0x92, 0xc8, 0x38, 0xbb, 0x84, 0xed, 0xde, 0xe4, 0xa2, 0xe1, 0x68, - 0x2f, 0xcb, 0x4b, 0x3c, 0x76, 0xb2, 0x3b, 0x84, 0x5f, 0x6b, 0x46, 0x72, - 0x2f, 0x7f, 0xf0, 0x6f, 0x6b, 0x7b, 0xd3, 0xc5, 0x4b, 0x20, 0x2b, 0xae, - 0x48, 0x7e, 0xcb, 0x22, 0x38, 0x44, 0x1f, 0x43, 0x1c, 0x55, 0x00, 0x00, - 0x00, 0x05, 0x0d, 0x00, 0x00, 0x00, 0x19, 0x07, 0x0a, 0x00, 0x00, 0x00, - 0x0a, 0x0d, 0xf1, 0x00, 0x0e, 0x8c, 0x0e, 0xf4, 0x0e, 0xc0, 0x0e, 0x24, - 0x0f, 0x99, 0x0e, 0x58, 0x0f, 0xcd, 0x0f, 0x65, 0x0d, 0xf1, 0x0f, 0x28, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x32, 0x05, 0x34, 0x34, 0x15, 0x01, 0xda, 0x39, 0xa3, 0xee, 0x5e, - 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, - 0xd8, 0x07, 0x09, 0xa9, 0x4a, 0x8f, 0xe5, 0xcc, 0xb1, 0x9b, 0xa6, 0x1c, - 0x4c, 0x08, 0x73, 0xd3, 0x91, 0xe9, 0x87, 0x98, 0x2f, 0xbb, 0xd3, 0x74, - 0x65, 0x73, 0x74, 0x11, 0x33, 0x05, 0x34, 0x34, 0x17, 0x01, 0x59, 0x27, - 0x33, 0x2f, 0x22, 0x90, 0x8f, 0xdf, 0x8f, 0x07, 0xfa, 0xa9, 0xeb, 0x8d, - 0x26, 0x20, 0xc7, 0xc6, 0x2a, 0x20, 0x3a, 0xdc, 0x09, 0xb3, 0xcd, 0x3d, - 0x7c, 0x47, 0x10, 0xf5, 0x62, 0xa0, 0x5b, 0xd8, 0x50, 0xe7, 0x56, 0xcb, - 0xa1, 0xb8, 0x69, 0x63, 0x68, 0x61, 0x74, 0x0d, 0x33, 0x05, 0x34, 0x34, - 0x17, 0x01, 0x7f, 0xda, 0x6a, 0xa0, 0x63, 0xf3, 0xfc, 0x5a, 0x86, 0x5c, - 0xa8, 0xf7, 0xa6, 0x9b, 0x5d, 0x69, 0x07, 0x3b, 0x91, 0x55, 0x72, 0x29, - 0x9c, 0x30, 0x4b, 0x50, 0xee, 0xe7, 0xb0, 0xc7, 0x1b, 0x05, 0x97, 0x70, - 0xac, 0x8e, 0x43, 0x5d, 0x69, 0x39, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x12, - 0x33, 0x05, 0x34, 0x34, 0x17, 0x01, 0x05, 0xc5, 0x64, 0xf0, 0xff, 0xc1, - 0x0a, 0xf4, 0x42, 0x83, 0x33, 0x33, 0x5d, 0x04, 0x75, 0x9c, 0x85, 0x9a, - 0x74, 0x0a, 0x3a, 0xdc, 0x09, 0xb3, 0xcd, 0x3d, 0x7c, 0x47, 0x10, 0xf5, - 0x62, 0xa0, 0x5b, 0xd8, 0x50, 0xe7, 0x56, 0xcb, 0xa1, 0xb8, 0x61, 0x70, - 0x70, 0x6c, 0x65, 0x09, 0x33, 0x05, 0x34, 0x34, 0x17, 0x01, 0x51, 0x96, - 0x74, 0xbb, 0x0c, 0xef, 0x0c, 0xf3, 0x24, 0x61, 0xd2, 0x2c, 0xba, 0x9a, - 0xa9, 0xc8, 0x0e, 0x22, 0xff, 0x0b, 0x3a, 0xdc, 0x09, 0xb3, 0xcd, 0x3d, - 0x7c, 0x47, 0x10, 0xf5, 0x62, 0xa0, 0x5b, 0xd8, 0x50, 0xe7, 0x56, 0xcb, - 0xa1, 0xb8, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x08, 0x33, 0x05, 0x34, 0x34, - 0x17, 0x01, 0x0b, 0x66, 0x7c, 0x18, 0x9e, 0x44, 0x49, 0x2d, 0x40, 0x62, - 0x95, 0x22, 0xa7, 0xe3, 0x08, 0x19, 0x26, 0x0f, 0xd6, 0x6d, 0x3a, 0xdc, - 0x09, 0xb3, 0xcd, 0x3d, 0x7c, 0x47, 0x10, 0xf5, 0x62, 0xa0, 0x5b, 0xd8, - 0x50, 0xe7, 0x56, 0xcb, 0xa1, 0xb8, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x07, - 0x3c, 0x05, 0x34, 0x34, 0x29, 0x01, 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, - 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, - 0x07, 0x09, 0xaa, 0xa7, 0xbf, 0x94, 0x09, 0x4f, 0x35, 0x59, 0x31, 0xba, - 0xaa, 0x89, 0x4f, 0xfa, 0x26, 0x41, 0x66, 0x87, 0x1b, 0x60, 0x63, 0x6f, - 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x73, 0x64, - 0x05, 0x33, 0x05, 0x34, 0x34, 0x17, 0x01, 0x8e, 0xc3, 0x7e, 0x3a, 0x0f, - 0x3a, 0x3a, 0x7e, 0x0e, 0x1e, 0x69, 0x08, 0x28, 0x2f, 0x21, 0x1c, 0x2a, - 0x13, 0xa3, 0x59, 0xe5, 0x0e, 0x4d, 0x78, 0x41, 0x89, 0x33, 0xa3, 0x28, - 0x6d, 0xb9, 0x0a, 0x0b, 0x36, 0x7b, 0xf9, 0xc7, 0xb9, 0x71, 0xe5, 0x61, - 0x70, 0x70, 0x6c, 0x65, 0x06, 0x33, 0x05, 0x34, 0x34, 0x17, 0x01, 0x77, - 0xac, 0x86, 0x8b, 0xf9, 0xb8, 0xa0, 0x50, 0x0b, 0x1f, 0xb3, 0x50, 0x55, - 0xe2, 0x63, 0x81, 0xf6, 0x85, 0xbc, 0xeb, 0x06, 0x98, 0x7e, 0x8b, 0x09, - 0xd8, 0x2e, 0xbe, 0x8c, 0x6b, 0x51, 0x5c, 0x08, 0x13, 0x58, 0xb4, 0x2e, - 0x41, 0xcb, 0x34, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x02, 0x32, 0x05, 0x34, - 0x34, 0x17, 0x09, 0x83, 0xad, 0xb6, 0xae, 0x9f, 0x27, 0xa5, 0x45, 0x30, - 0xb3, 0x67, 0xc8, 0x32, 0x58, 0x95, 0x85, 0x06, 0xeb, 0xc1, 0xf4, 0x06, - 0x98, 0x7e, 0x8b, 0x09, 0xd8, 0x2e, 0xbe, 0x8c, 0x6b, 0x51, 0x5c, 0x08, - 0x13, 0x58, 0xb4, 0x2e, 0x41, 0xcb, 0x34, 0x61, 0x70, 0x70, 0x6c, 0x65, - 0x0d, 0x0f, 0xe4, 0x00, 0x03, 0x0f, 0xda, 0x00, 0x0f, 0xf6, 0x0f, 0xda, - 0x0f, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x08, 0x02, 0x03, 0x15, 0x01, 0x63, 0x65, 0x72, 0x74, 0x02, - 0x00, 0x00, 0x00, 0x08, 0x09, 0x6b, 0x65, 0x79, 0x08, 0x03, 0x03, 0x15, - 0x01, 0x6b, 0x65, 0x79, 0x73, 0x06, 0x08, 0x01, 0x03, 0x15, 0x01, 0x67, - 0x65, 0x6e, 0x70, 0x12, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0d, 0x00, 0x00, 0x00, 0x02, 0x03, 0xfb, 0x00, 0x09, 0xed, 0x03, 0xfb, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, - 0x6f, 0x02, 0x11, 0x00, 0x07, 0x07, 0x01, 0x01, 0x34, 0x00, 0x34, 0x34, - 0x34, 0x34, 0x34, 0x95, 0x12, 0x29, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x4b, - 0x9d, 0x7a, 0x35, 0x41, 0xb7, 0x59, 0x5c, 0x4b, 0x9d, 0x7a, 0x35, 0x03, - 0x03, 0x37, 0xee, 0x5a, 0x85, 0xe1, 0xcb, 0xdd, 0xc8, 0xce, 0x07, 0x77, - 0xee, 0x01, 0x3f, 0x96, 0x7b, 0x33, 0x30, 0x3a, 0xcd, 0x7e, 0x0b, 0xaa, - 0xec, 0xd2, 0x3c, 0x92, 0x58, 0xd7, 0xfd, 0x92, 0x3c, 0xf8, 0x03, 0x3e, - 0x70, 0x20, 0x84, 0xa7, 0x17, 0x2c, 0xf0, 0xfa, 0xf2, 0x6b, 0xa9, 0x12, - 0x4e, 0x73, 0x93, 0x45, 0x6c, 0x2f, 0x97, 0x33, 0x72, 0xa1, 0x3b, 0x0d, - 0x66, 0x6e, 0x37, 0x4b, 0xba, 0xaa, 0x65, 0x68, 0x18, 0x44, 0x35, 0x5b, - 0x9a, 0x6f, 0xf1, 0x3c, 0x2b, 0x18, 0x1f, 0xda, 0x4c, 0xda, 0xde, 0x08, - 0x82, 0x7d, 0xfa, 0x5c, 0xf3, 0x42, 0xb1, 0x04, 0x84, 0xf4, 0xba, 0xe3, - 0x73, 0xe9, 0x35, 0x6f, 0xbb, 0x64, 0x14, 0x5e, 0x86, 0xb3, 0x7b, 0x2d, - 0x6c, 0xa9, 0xc0, 0xcf, 0xd8, 0x43, 0x7e, 0x59, 0x45, 0xac, 0xff, 0x92, - 0x4b, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, - 0x00, 0xc4, 0xe8, 0xe5, 0xde, 0xeb, 0xd1, 0xbc, 0xae, 0x0f, 0x47, 0x6a, - 0xc0, 0xb4, 0xf8, 0x7a, 0xdc, 0xc1, 0x10, 0xb0, 0x90, 0xf2, 0x29, 0x16, - 0x8f, 0x90, 0xeb, 0x31, 0x83, 0x9b, 0x33, 0x91, 0x26, 0x16, 0x4c, 0xce, - 0xfe, 0x98, 0x25, 0x0d, 0xed, 0xe6, 0x9f, 0xc3, 0x91, 0xac, 0xbb, 0xf8, - 0xc0, 0xca, 0x25, 0x42, 0xd4, 0x5d, 0xfe, 0x1b, 0x4d, 0x60, 0x7f, 0x01, - 0xee, 0x5f, 0x16, 0xbd, 0xb8, 0xe7, 0xdc, 0xe1, 0x75, 0xf9, 0x1a, 0xc7, - 0x4f, 0xc5, 0xf1, 0x44, 0x46, 0xfe, 0xdd, 0x91, 0xf8, 0x25, 0xed, 0xbc, - 0x1a, 0xf1, 0x34, 0x71, 0x05, 0x4e, 0x13, 0xb9, 0x21, 0xbf, 0x04, 0x6d, - 0x1e, 0x0f, 0xe6, 0x63, 0x19, 0x0b, 0x77, 0xef, 0xf1, 0x24, 0xf4, 0x55, - 0xf3, 0x71, 0x53, 0x13, 0x8b, 0xbb, 0xd5, 0xdb, 0x3e, 0xcb, 0xc5, 0x3a, - 0x9a, 0xe9, 0x55, 0xa1, 0x75, 0xa1, 0x98, 0x40, 0x80, 0x3b, 0x1e, 0xe1, - 0xbc, 0x44, 0x59, 0xb9, 0xf2, 0x6b, 0xa9, 0x0d, 0x13, 0x0c, 0xd2, 0xb2, - 0x99, 0xbf, 0x1f, 0xa9, 0x86, 0x5b, 0x2b, 0x63, 0x65, 0x28, 0x2f, 0x11, - 0x96, 0x2b, 0xa1, 0x9d, 0x32, 0x5e, 0x55, 0xa1, 0xdf, 0x90, 0x3b, 0x5e, - 0x4e, 0xdd, 0x3f, 0x6f, 0x10, 0xb6, 0x7c, 0xad, 0x92, 0xeb, 0x9f, 0x72, - 0xe4, 0x37, 0x83, 0x59, 0x4b, 0x6c, 0x62, 0x2e, 0xf1, 0x11, 0x5a, 0x75, - 0x86, 0x5b, 0xe4, 0x79, 0x86, 0xca, 0xdb, 0xd8, 0x11, 0xf4, 0x5f, 0x65, - 0x8f, 0x7f, 0x66, 0xc4, 0xe0, 0x35, 0x97, 0x15, 0xe3, 0x13, 0x97, 0xa9, - 0x23, 0x20, 0xce, 0xfe, 0x1a, 0x3a, 0x3f, 0xce, 0xa3, 0x88, 0x36, 0xfa, - 0x58, 0xb2, 0x35, 0x9a, 0x07, 0x69, 0xcd, 0xc7, 0xc7, 0xf4, 0x93, 0x0d, - 0x11, 0x3f, 0xec, 0x74, 0x88, 0x55, 0xfc, 0x12, 0x08, 0x0d, 0xc1, 0xd1, - 0x1f, 0xf6, 0xdd, 0xff, 0xea, 0x75, 0x40, 0x21, 0x06, 0xf2, 0x8a, 0x6c, - 0x2e, 0xc4, 0x84, 0x5d, 0x67, 0x90, 0x29, 0x95, 0xed, 0x6e, 0x55, 0x19, - 0x12, 0xb0, 0x11, 0x41, 0x2e, 0x2b, 0xe0, 0xbb, 0xe4, 0x90, 0x8e, 0xa3, - 0x9f, 0x1c, 0x3d, 0xa0, 0xd1, 0x5c, 0xa3, 0x01, 0xf3, 0x0f, 0x09, 0x64, - 0x7c, 0x12, 0xbc, 0x43, 0x2a, 0x24, 0x32, 0x8c, 0x63, 0x6c, 0x4d, 0x91, - 0xff, 0xe8, 0x0c, 0xc3, 0x54, 0xa8, 0x9b, 0x01, 0x99, 0x56, 0xc3, 0x1c, - 0xe1, 0x8e, 0x18, 0xfb, 0xb7, 0xfe, 0x27, 0x8c, 0x83, 0x3b, 0x07, 0x5b, - 0x93, 0x35, 0xaa, 0xef, 0xda, 0xb5, 0x50, 0x29, 0x92, 0x64, 0x18, 0x5d, - 0x2d, 0x25, 0x13, 0x68, 0x11, 0x37, 0xa7, 0x9e, 0xb1, 0x82, 0xe5, 0x10, - 0x6c, 0x2e, 0x44, 0x23, 0x04, 0x88, 0x47, 0xf0, 0x8e, 0xbc, 0xb2, 0xda, - 0xe2, 0x58, 0x8e, 0x4a, 0xc9, 0x93, 0x28, 0x7a, 0x32, 0x8c, 0x3d, 0x9b, - 0x49, 0x45, 0xcd, 0x13, 0x15, 0x13, 0xef, 0xaa, 0x71, 0x76, 0x08, 0x31, - 0xdf, 0xf2, 0xce, 0xae, 0xc5, 0xf7, 0x01, 0xd4, 0x59, 0x76, 0x88, 0xa3, - 0x8b, 0xfc, 0x3a, 0x24, 0xb6, 0x98, 0x44, 0x51, 0x87, 0xff, 0x14, 0xa7, - 0xb0, 0x47, 0x15, 0xc0, 0x35, 0x9a, 0xb8, 0xf1, 0xff, 0xa8, 0x84, 0x5b, - 0x4e, 0x59, 0x02, 0x65, 0xbf, 0x6f, 0xd5, 0x4d, 0xa0, 0xdb, 0x50, 0x13, - 0x7f, 0x1f, 0x86, 0x3a, 0x7a, 0x6b, 0xfb, 0xf2, 0xb6, 0xa6, 0x3d, 0xac, - 0x97, 0x86, 0xbf, 0x29, 0xdb, 0xb6, 0x99, 0xe8, 0x22, 0xce, 0xea, 0x43, - 0x38, 0xab, 0xfa, 0x64, 0x6c, 0xcc, 0x45, 0x7a, 0xc0, 0x9f, 0x50, 0x7b, - 0x1f, 0x25, 0x33, 0xe6, 0xfc, 0x9f, 0xcc, 0xfb, 0xbb, 0x50, 0x33, 0x31, - 0xe8, 0x62, 0x33, 0x43, 0x7e, 0x8d, 0x82, 0x38, 0x0c, 0x2c, 0x6e, 0x57, - 0x5f, 0x08, 0x31, 0x96, 0x48, 0x02, 0xbb, 0x95, 0x9a, 0xea, 0xd4, 0xcd, - 0x54, 0x49, 0x65, 0x51, 0xf6, 0xc9, 0x39, 0x39, 0xab, 0xe3, 0x92, 0xc2, - 0x71, 0xbb, 0xb1, 0x25, 0x12, 0x96, 0x45, 0xb8, 0x14, 0x34, 0x82, 0x94, - 0x9f, 0xbd, 0xc7, 0xf7, 0x07, 0x4f, 0x7d, 0xb5, 0xa2, 0xe2, 0xd5, 0x91, - 0xbf, 0x9b, 0xde, 0x3d, 0xa2, 0xfe, 0x25, 0x76, 0x5e, 0xac, 0xde, 0xf1, - 0x5f, 0x00, 0xe5, 0x9f, 0x6f, 0x3d, 0xdd, 0xbc, 0x7f, 0xfd, 0x92, 0x52, - 0x56, 0x53, 0x5a, 0x04, 0xca, 0xdc, 0x23, 0x76, 0xe4, 0xc4, 0xeb, 0x00, - 0x5e, 0x3e, 0x71, 0xb9, 0x7c, 0x54, 0x81, 0x4d, 0x6e, 0xb3, 0x09, 0x39, - 0x6f, 0x67, 0x0e, 0xc6, 0x95, 0xdf, 0x03, 0xcc, 0x7e, 0x0b, 0x7c, 0x31, - 0x16, 0xbe, 0x4b, 0xfc, 0x0f, 0x17, 0xb4, 0x7a, 0x9c, 0x44, 0x36, 0x5a, - 0xaf, 0x42, 0x69, 0x40, 0x58, 0xe7, 0xa4, 0x07, 0x5b, 0xe5, 0xd6, 0x35, - 0xe5, 0x4a, 0xde, 0x35, 0x29, 0xc5, 0x69, 0x00, 0x47, 0xfa, 0x3d, 0x54, - 0xbc, 0x1f, 0xa5, 0x58, 0x86, 0xbf, 0xaa, 0x5d, 0x94, 0x60, 0x3b, 0x81, - 0x11, 0xa0, 0xa0, 0x19, 0xf3, 0x7a, 0xfd, 0x69, 0x5f, 0xac, 0xf6, 0x41, - 0xfd, 0x73, 0xff, 0x99, 0x2a, 0x41, 0xee, 0xda, 0x7f, 0xfe, 0x80, 0xcb, - 0x20, 0x9e, 0x8f, 0xdc, 0x6c, 0x3f, 0x71, 0xed, 0x07, 0xc5, 0xd9, 0x4f, - 0x32, 0x9e, 0xe5, 0x0b, 0x63, 0x70, 0x66, 0x2b, 0x42, 0x5d, 0xa3, 0xfa, - 0x81, 0x6a, 0x47, 0x40, 0xa6, 0xed, 0x8c, 0x7d, 0x71, 0x61, 0x74, 0xd3, - 0x40, 0x24, 0x1f, 0x2c, 0x4a, 0x89, 0xd3, 0xbb, 0xb8, 0x14, 0x6b, 0x8f, - 0xb2, 0x3d, 0x16, 0x99, 0xf5, 0x7f, 0x0a, 0x2e, 0x79, 0x6b, 0xb6, 0xe8, - 0x8f, 0xb3, 0x42, 0x67, 0x93, 0x59, 0xe8, 0x69, 0x66, 0x9e, 0x6d, 0x06, - 0x11, 0x5d, 0xfd, 0x0f, 0x19, 0x43, 0x9f, 0x5b, 0x82, 0xbc, 0x5f, 0x79, - 0xeb, 0x4f, 0x7f, 0xcc, 0xfa, 0x8e, 0xe5, 0xe6, 0xe4, 0x01, 0xf7, 0xa0, - 0x7a, 0xb8, 0xe6, 0xb6, 0x08, 0x19, 0x80, 0x30, 0xa4, 0x2f, 0x84, 0xd2, - 0x5e, 0xce, 0xde, 0x59, 0x26, 0xf6, 0x19, 0x19, 0x42, 0x13, 0x0e, 0xcb, - 0x3f, 0xfb, 0x22, 0xbb, 0x61, 0xc6, 0xf8, 0xc9, 0x68, 0x77, 0x60, 0x30, - 0x85, 0x34, 0x2a, 0x30, 0x3c, 0x09, 0xd9, 0x2f, 0xf7, 0x15, 0xdc, 0x50, - 0xc5, 0x05, 0x18, 0x12, 0x2c, 0x8b, 0x55, 0xad, 0x3e, 0x2a, 0xf9, 0x1f, - 0x77, 0xa3, 0xc6, 0x34, 0x47, 0x86, 0x7d, 0x85, 0x11, 0x1c, 0x04, 0x0c, - 0x4a, 0xae, 0xc0, 0x49, 0xba, 0x46, 0xa9, 0x75, 0xd5, 0x86, 0x1b, 0xa0, - 0x18, 0x63, 0xfe, 0x9c, 0x23, 0x6c, 0xb3, 0xfe, 0x06, 0x06, 0x6f, 0xdf, - 0x8b, 0x5b, 0x59, 0x2b, 0xd4, 0x97, 0x50, 0x1b, 0x79, 0x64, 0x57, 0xbe, - 0x62, 0x46, 0xda, 0x38, 0xf3, 0x06, 0x3c, 0xec, 0x3e, 0xcf, 0x14, 0x24, - 0xc6, 0x33, 0xf6, 0x08, 0x0e, 0xe9, 0xb1, 0xbc, 0x29, 0x37, 0x13, 0x96, - 0x79, 0x2a, 0x32, 0x8e, 0x93, 0xed, 0x97, 0xcf, 0x7e, 0x72, 0xb6, 0x60, - 0x6c, 0x68, 0x2a, 0xf2, 0xbf, 0xd2, 0xe0, 0x2b, 0x76, 0xd3, 0x88, 0x24, - 0xf7, 0xfc, 0xed, 0xf9, 0x59, 0xff, 0xd1, 0xd5, 0xf4, 0x69, 0x00, 0xd2, - 0xbd, 0xfc, 0xcb, 0x1e, 0x8b, 0x51, 0x7a, 0xd5, 0x46, 0x6e, 0x11, 0x33, - 0xf8, 0xee, 0xbd, 0xb5, 0x64, 0x8b, 0xf6, 0x31, 0xd4, 0x7f, 0xda, 0x2b, - 0xf0, 0x52, 0x92, 0xaa, 0xee, 0x4e, 0x2e, 0xea, 0xdd, 0x42, 0x14, 0x51, - 0xff, 0xc0, 0xb2, 0x6e, 0xc2, 0x77, 0x7a, 0x9d, 0xce, 0x74, 0xaa, 0xe9, - 0x46, 0x67, 0x40, 0x08, 0xfe, 0xf5, 0xc0, 0xd0, 0x33, 0x2b, 0x7a, 0x07, - 0xb0, 0x37, 0x22, 0x96, 0x0c, 0xe1, 0xe2, 0x97, 0x96, 0x1b, 0xcf, 0xfc, - 0xd3, 0x4a, 0x8f, 0x6e, 0x99, 0xc1, 0xb0, 0x43, 0xb7, 0x96, 0xd4, 0xab, - 0xe6, 0x8b, 0x90, 0x98, 0x8a, 0xed, 0x0f, 0xe1, 0x77, 0x20, 0x87, 0x39, - 0x66, 0x56, 0xfa, 0xa1, 0x58, 0xd1, 0x8a, 0x0e, 0x59, 0xc0, 0x21, 0xf7, - 0x14, 0x10, 0xe3, 0xbb, 0x2f, 0xcd, 0x09, 0xc2, 0x44, 0x04, 0x27, 0x3f, - 0x68, 0xec, 0xc2, 0xd0, 0x04, 0xb5, 0x0b, 0x14, 0x8f, 0xcf, 0x04, 0xc1, - 0x94, 0x65, 0xc2, 0xbc, 0x8f, 0x9c, 0x79, 0x0b, 0xe2, 0xd6, 0x5b, 0xe9, - 0x90, 0xa5, 0x0b, 0x8c, 0xa7, 0x27, 0xc5, 0x6d, 0x89, 0x62, 0x30, 0x3d, - 0x5b, 0x7a, 0xd4, 0xee, 0x33, 0x1c, 0x42, 0x09, 0x64, 0x95, 0x64, 0x25, - 0x79, 0x63, 0x5a, 0x10, 0x79, 0x5d, 0xb4, 0x86, 0x19, 0x84, 0x84, 0x61, - 0x43, 0x1d, 0x46, 0xef, 0xd5, 0x81, 0xc0, 0xe7, 0x3f, 0x64, 0xf1, 0xf0, - 0x36, 0x1b, 0x1f, 0xdf, 0xba, 0x7e, 0x6a, 0x8b, 0xdb, 0xc2, 0x48, 0xe3, - 0x07, 0x12, 0x9e, 0xc1, 0x9c, 0x85, 0xd0, 0xa5, 0x5e, 0xda, 0x88, 0x43, - 0xb3, 0xed, 0xbb, 0xd3, 0xdf, 0x8e, 0x6f, 0x13, 0x51, 0x52, 0x50, 0x73, - 0x97, 0xc1, 0xd0, 0xb7, 0xd7, 0x82, 0x31, 0xfd, 0xc2, 0x96, 0xc3, 0x37, - 0xd4, 0x1c, 0xfd, 0x90, 0x47, 0x1c, 0x7e, 0xc6, 0xb0, 0x0d, 0x6f, 0x96, - 0x65, 0x6b, 0x9d, 0xbd, 0x59, 0x13, 0xca, 0x32, 0xc3, 0x29, 0x39, 0xdc, - 0x6c, 0x26, 0x15, 0xc8, 0x83, 0xa8, 0x5d, 0x9d, 0x1d, 0x30, 0x64, 0x65, - 0x05, 0x48, 0xce, 0xaa, 0x69, 0xf7, 0x42, 0xa6, 0x1f, 0x9d, 0xcb, 0xc9, - 0x5b, 0xe7, 0x69, 0xcf, 0x29, 0xd1, 0xa5, 0xcf, 0x55, 0x79, 0xff, 0x6c, - 0xfa, 0xac, 0xb8, 0xec, 0x33, 0x61, 0xc1, 0x33, 0x5c, 0xef, 0x0f, 0x92, - 0x93, 0x4a, 0x83, 0x79, 0x48, 0x21, 0xba, 0xf7, 0xcb, 0x01, 0x63, 0x84, - 0x22, 0xc6, 0xec, 0x8c, 0x66, 0x8d, 0x97, 0x42, 0x56, 0x75, 0x73, 0x61, - 0xcb, 0xfa, 0xd4, 0x20, 0x66, 0xce, 0x6a, 0x81, 0x78, 0xa6, 0xc8, 0x72, - 0xeb, 0x15, 0x25, 0xb2, 0x06, 0xc0, 0xb2, 0xab, 0x18, 0x66, 0x4e, 0x5e, - 0x73, 0x21, 0x55, 0xd6, 0xe3, 0x60, 0x81, 0x56, 0x85, 0x1f, 0x5a, 0xce, - 0xff, 0xc0, 0x6a, 0xd3, 0x18, 0xdd, 0xfd, 0xaa, 0x73, 0x42, 0xb1, 0xd5, - 0x62, 0xda, 0x2e, 0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, - 0x65, 0x2e, 0x61, 0x70, 0x73, 0x64, 0x64, 0x6b, 0x75, 0x8c, 0x10, 0x01, - 0x11, 0x00, 0x07, 0x07, 0x01, 0x01, 0x34, 0x00, 0x34, 0x34, 0x34, 0x34, - 0x34, 0x95, 0x4a, 0x33, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x4b, 0x83, 0xb6, - 0x03, 0x41, 0xb7, 0x59, 0x5c, 0x4b, 0x83, 0xb6, 0x03, 0x03, 0x03, 0xb1, - 0x0a, 0x33, 0x78, 0x48, 0x21, 0xea, 0x97, 0x6e, 0xb7, 0xc7, 0x2e, 0xdb, - 0x0f, 0x9b, 0x01, 0xd0, 0x22, 0x6d, 0xbb, 0x7e, 0x0b, 0xaa, 0xec, 0xd2, - 0x3c, 0x92, 0x58, 0xd7, 0xfd, 0x92, 0x3c, 0xf8, 0x03, 0x3e, 0x70, 0x20, - 0x84, 0xa7, 0x17, 0x2c, 0xf0, 0xfa, 0xf2, 0x6b, 0xa9, 0x12, 0x4e, 0x73, - 0x93, 0x45, 0x6c, 0x2f, 0x97, 0x33, 0x72, 0xa1, 0x3b, 0x0d, 0x66, 0x6e, - 0x37, 0x4b, 0xba, 0xaa, 0x65, 0x68, 0x18, 0x44, 0x35, 0x5b, 0x9a, 0x6f, - 0xf1, 0x3c, 0x2b, 0x18, 0x1f, 0xda, 0x4c, 0xda, 0xde, 0x08, 0x82, 0x7d, - 0xfa, 0x5c, 0xf3, 0x42, 0xb1, 0x04, 0x84, 0xf4, 0xba, 0xe3, 0x73, 0xe9, - 0x35, 0x6f, 0xbb, 0x64, 0x14, 0x5e, 0x86, 0xb3, 0x7b, 0x2d, 0x6c, 0xa9, - 0xc0, 0xcf, 0xd8, 0x43, 0x7e, 0x59, 0x45, 0xac, 0xff, 0x92, 0x4b, 0x02, - 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x15, - 0x67, 0xb2, 0x55, 0xfa, 0x3d, 0xce, 0x31, 0x23, 0xdf, 0x93, 0xad, 0x9c, - 0x09, 0x8d, 0xbc, 0x7e, 0xb3, 0x84, 0x6c, 0x0a, 0x52, 0x6e, 0xab, 0x7d, - 0x13, 0x86, 0xcc, 0xbe, 0xf3, 0x30, 0x0b, 0x08, 0xf8, 0xa1, 0xcf, 0x62, - 0x7a, 0x7e, 0xaf, 0xd7, 0x55, 0x51, 0x92, 0x16, 0x1d, 0x3e, 0x5e, 0x37, - 0x86, 0xf2, 0xea, 0x51, 0xee, 0x6a, 0xe3, 0xa6, 0xe1, 0xc5, 0xce, 0x5f, - 0x86, 0x3e, 0x5a, 0x3d, 0x6d, 0x31, 0xf9, 0x10, 0xe3, 0xd6, 0x77, 0x76, - 0x33, 0x03, 0xfc, 0x2a, 0x0c, 0x45, 0x5c, 0x29, 0xa8, 0x9f, 0x96, 0x45, - 0xd5, 0xae, 0x9f, 0x21, 0x9a, 0x1a, 0x6d, 0x85, 0x4f, 0x3d, 0x35, 0x85, - 0xf1, 0x6a, 0x11, 0xf3, 0x54, 0x3e, 0x96, 0x4c, 0xbf, 0xa6, 0x01, 0xd4, - 0xc8, 0x67, 0xc1, 0x94, 0x16, 0x19, 0x39, 0x42, 0x28, 0xc9, 0x5b, 0x88, - 0x09, 0xbf, 0xba, 0xf2, 0x9b, 0x4f, 0x13, 0x73, 0x8b, 0x2c, 0x98, 0x07, - 0x70, 0xa7, 0x27, 0xae, 0x02, 0xa3, 0x63, 0x11, 0x5b, 0x1b, 0x8c, 0x85, - 0x8e, 0x0f, 0xde, 0xf9, 0x0b, 0x8f, 0x06, 0xfd, 0xab, 0x03, 0x34, 0x52, - 0x23, 0x52, 0x2e, 0xf1, 0xa8, 0x30, 0x89, 0xe8, 0xdc, 0x8f, 0xe4, 0x9f, - 0xd3, 0xa1, 0x09, 0x33, 0x5b, 0x07, 0xc8, 0x9c, 0x49, 0x47, 0x37, 0x53, - 0x35, 0xc5, 0x1e, 0x78, 0x9f, 0xc7, 0x65, 0x94, 0xf6, 0xb9, 0xcf, 0xcc, - 0xee, 0xfc, 0x73, 0x40, 0x42, 0xb8, 0x37, 0x12, 0xfd, 0x34, 0xea, 0xdd, - 0x89, 0x01, 0x51, 0xfe, 0xde, 0xb6, 0xb6, 0x1e, 0x40, 0x39, 0x12, 0xf8, - 0xdd, 0x5c, 0x96, 0xb6, 0x1b, 0x21, 0x08, 0xaf, 0x6e, 0x62, 0xbb, 0x3c, - 0x65, 0xd1, 0xa9, 0x15, 0xb0, 0xf6, 0x1b, 0xbb, 0xac, 0x26, 0xa5, 0x82, - 0xc6, 0x43, 0xa0, 0x88, 0xf1, 0x64, 0x64, 0x01, 0xd9, 0xa9, 0x5e, 0xf0, - 0x73, 0x52, 0xfb, 0xc9, 0x27, 0x81, 0x0e, 0xce, 0x8e, 0x4c, 0xc8, 0x3d, - 0xef, 0xe2, 0xdc, 0xe3, 0xe9, 0x23, 0x3c, 0x47, 0x93, 0xcb, 0x18, 0xe6, - 0x11, 0xe2, 0x40, 0xd7, 0x73, 0x18, 0x6b, 0xbd, 0x77, 0x56, 0x6e, 0x6c, - 0xe8, 0x25, 0xe7, 0xef, 0x12, 0xc7, 0x8f, 0x38, 0x80, 0x0e, 0xd1, 0x97, - 0x71, 0xef, 0xfa, 0x78, 0xac, 0x3d, 0x55, 0x45, 0x83, 0x45, 0x62, 0xb0, - 0x9a, 0xbf, 0x45, 0xd5, 0xbe, 0x45, 0x8a, 0xa2, 0x21, 0x88, 0xb9, 0xd0, - 0x3e, 0x59, 0xbb, 0x68, 0x77, 0xb7, 0x29, 0x65, 0x4a, 0x8d, 0xf4, 0x1d, - 0xf1, 0xd1, 0x00, 0x92, 0x2d, 0xcb, 0x6b, 0xaa, 0x9d, 0x1d, 0x0f, 0xf1, - 0x45, 0x0b, 0x13, 0x47, 0x2b, 0x47, 0x00, 0x30, 0x72, 0x0c, 0xa8, 0xb2, - 0xcb, 0x5b, 0xcd, 0xee, 0x30, 0x8d, 0xdb, 0x62, 0xd1, 0xb5, 0x5f, 0xe1, - 0x3e, 0xf8, 0x96, 0x09, 0x1e, 0x82, 0x2e, 0xf1, 0x8c, 0x20, 0x52, 0x33, - 0x2e, 0x42, 0x5c, 0x64, 0x39, 0xa2, 0x7b, 0x84, 0x2f, 0xff, 0x02, 0x24, - 0xdd, 0x40, 0x23, 0x9c, 0xec, 0xf0, 0xe9, 0x8f, 0x37, 0x15, 0xfd, 0xca, - 0xa5, 0xa6, 0x30, 0x1f, 0x4f, 0xa6, 0xf1, 0x05, 0xd8, 0x2f, 0x0b, 0xbf, - 0xa4, 0x3a, 0x9f, 0x57, 0x31, 0xb3, 0x9d, 0x64, 0xa5, 0xc9, 0x13, 0x64, - 0x7f, 0xb2, 0xe9, 0x38, 0x55, 0xe2, 0xd7, 0x6f, 0xad, 0xe5, 0x77, 0xf9, - 0xbe, 0x17, 0xcc, 0xec, 0xfb, 0xe4, 0xd1, 0x13, 0xa3, 0x20, 0x6e, 0xa6, - 0x64, 0x4e, 0xda, 0xa8, 0x86, 0xfc, 0xc8, 0x29, 0xb9, 0x47, 0xc1, 0xf0, - 0xe1, 0xc9, 0x62, 0x1d, 0x6a, 0x64, 0x8e, 0x1b, 0x76, 0x6a, 0x49, 0x22, - 0xeb, 0xfc, 0x33, 0xbc, 0x27, 0x8c, 0x84, 0x40, 0xe9, 0x3f, 0x46, 0x11, - 0x52, 0xf7, 0xe1, 0xbe, 0xbb, 0x48, 0x31, 0x28, 0x12, 0x62, 0x4a, 0x88, - 0x46, 0xf2, 0x4c, 0x1b, 0x03, 0xa6, 0x6f, 0xd3, 0x58, 0x35, 0x47, 0x24, - 0x53, 0x61, 0xc2, 0xa3, 0x6b, 0xc2, 0x6b, 0x73, 0x96, 0x2b, 0xd0, 0xd9, - 0x7d, 0x8e, 0xf1, 0x1a, 0x24, 0xfd, 0x34, 0x97, 0x02, 0xde, 0x0e, 0x79, - 0x29, 0xd2, 0x61, 0x2b, 0xca, 0x09, 0xea, 0xf2, 0xda, 0x17, 0x07, 0x8e, - 0x39, 0xc5, 0xee, 0x52, 0x76, 0x36, 0xce, 0x40, 0xee, 0xfa, 0x03, 0x40, - 0x9b, 0x91, 0xf6, 0x5e, 0x82, 0x46, 0x3e, 0x91, 0x13, 0xf2, 0x4e, 0x49, - 0x1d, 0x61, 0xf2, 0x6a, 0xcd, 0x5f, 0x06, 0xf0, 0xde, 0x9d, 0x5c, 0x8d, - 0xf5, 0xf6, 0xe5, 0x20, 0x1f, 0x1e, 0xd3, 0x37, 0x6f, 0x4a, 0xf5, 0x9e, - 0x93, 0x25, 0x27, 0xcc, 0x41, 0x53, 0x0c, 0xc7, 0x6b, 0x23, 0x42, 0xe0, - 0x3e, 0xe0, 0xb0, 0x06, 0x64, 0xc2, 0xf2, 0x6b, 0x45, 0x49, 0x25, 0x16, - 0x39, 0x9b, 0x67, 0xf8, 0xa0, 0x2f, 0x38, 0x48, 0x97, 0xd2, 0x59, 0x16, - 0x5b, 0x86, 0x10, 0xdd, 0x92, 0xa2, 0x26, 0x67, 0x46, 0xd8, 0x5f, 0x1a, - 0xe7, 0x16, 0x9f, 0x8e, 0xb5, 0x04, 0x4d, 0x1b, 0x14, 0xaf, 0x3e, 0xf6, - 0xf3, 0x2e, 0x9f, 0xb0, 0x9f, 0x93, 0x2a, 0x9e, 0xae, 0x2f, 0xeb, 0x23, - 0xf8, 0x34, 0xb4, 0x39, 0x0a, 0xbb, 0x58, 0x5a, 0x43, 0x1e, 0xf0, 0x33, - 0x2e, 0x78, 0x62, 0x69, 0xd6, 0x31, 0x01, 0xc2, 0xc9, 0x7e, 0xcd, 0x8f, - 0x2e, 0xab, 0x2d, 0x46, 0x5a, 0xfe, 0xdb, 0x44, 0x2f, 0x83, 0xbf, 0xd2, - 0x1a, 0x77, 0xd4, 0x1c, 0x9d, 0x6a, 0x72, 0xc1, 0xcd, 0x6c, 0x3a, 0x18, - 0xa7, 0x83, 0x71, 0x4a, 0x2b, 0x25, 0x79, 0xea, 0x34, 0x14, 0x7c, 0xe0, - 0xbf, 0xbc, 0x53, 0xf7, 0xa0, 0x5f, 0x70, 0xa8, 0x4e, 0x7d, 0xec, 0x82, - 0x16, 0x1d, 0xa5, 0x1f, 0x4c, 0xc6, 0xe7, 0xc3, 0x81, 0x9f, 0x1b, 0xd3, - 0x13, 0x5b, 0x22, 0x26, 0x1f, 0xc1, 0x63, 0xb0, 0xe7, 0x42, 0xc6, 0x74, - 0x3b, 0xb4, 0xbf, 0xa8, 0xb9, 0xf6, 0xaa, 0x67, 0x59, 0x96, 0x2d, 0xc1, - 0xd0, 0xf4, 0xe8, 0x84, 0xc7, 0x5e, 0xae, 0xca, 0xe8, 0x45, 0x68, 0xa8, - 0xd4, 0x87, 0x2f, 0x81, 0x08, 0x63, 0xd0, 0xb0, 0x5d, 0x04, 0x4d, 0x6a, - 0x72, 0xc4, 0x11, 0xc2, 0x05, 0x32, 0x20, 0xd6, 0x32, 0x44, 0x1d, 0xae, - 0xc9, 0x5d, 0x27, 0x67, 0xeb, 0xed, 0x63, 0xf6, 0x45, 0x25, 0xb8, 0x4c, - 0xf7, 0x63, 0xed, 0x18, 0x02, 0x0b, 0x53, 0x8d, 0x43, 0x45, 0x2f, 0x94, - 0x2f, 0x0f, 0xe9, 0x40, 0x41, 0x10, 0x57, 0x4f, 0x90, 0x29, 0x5b, 0x6e, - 0x8b, 0x72, 0x35, 0x25, 0xf9, 0x8c, 0xf1, 0x82, 0x3a, 0xa6, 0xcc, 0x8a, - 0xed, 0x3d, 0xfe, 0x85, 0xd7, 0xd9, 0x53, 0x42, 0x14, 0x34, 0x38, 0xef, - 0x1a, 0x8a, 0xbd, 0xd2, 0x17, 0x14, 0xac, 0x3e, 0xd8, 0x14, 0x26, 0xe7, - 0xc5, 0xdf, 0xd7, 0xad, 0x5c, 0xc9, 0x23, 0x46, 0x3d, 0xdb, 0xbd, 0xa0, - 0xc9, 0x12, 0x13, 0x9b, 0x45, 0x66, 0x6a, 0x96, 0xc3, 0x8b, 0xc5, 0x0a, - 0xc7, 0x38, 0x2f, 0x98, 0x4a, 0x32, 0x96, 0xbe, 0x14, 0xf7, 0x8b, 0x8d, - 0x45, 0x64, 0xf9, 0x94, 0x53, 0x1a, 0x00, 0x12, 0x9c, 0xc1, 0x0b, 0x7b, - 0x05, 0x3f, 0xaf, 0xc1, 0x79, 0x7f, 0x75, 0x54, 0xec, 0xc3, 0x1d, 0xd9, - 0xb5, 0x27, 0xed, 0xd9, 0x21, 0xfa, 0x42, 0xe5, 0x53, 0x40, 0xe5, 0x3a, - 0x51, 0x78, 0x8a, 0xe2, 0x80, 0xac, 0x5b, 0xff, 0xfd, 0x11, 0x4a, 0x58, - 0xc1, 0xb4, 0x4d, 0xdc, 0xc4, 0xa3, 0x4c, 0x57, 0x3d, 0x77, 0xb2, 0x98, - 0xdc, 0x9f, 0x7d, 0x97, 0x85, 0xd0, 0x16, 0x2a, 0x63, 0x2c, 0x79, 0x1a, - 0xce, 0xcf, 0x0c, 0x3b, 0x24, 0x2a, 0x39, 0x9f, 0x06, 0x1a, 0xc6, 0x49, - 0xf3, 0x86, 0xd4, 0x8d, 0x65, 0x77, 0x02, 0xc6, 0x35, 0x38, 0x97, 0x23, - 0x85, 0x7c, 0x6f, 0x5c, 0x0e, 0x78, 0xdd, 0xe7, 0x48, 0x40, 0xe5, 0x22, - 0xae, 0xef, 0x81, 0x02, 0xec, 0xc7, 0x0f, 0x12, 0x0f, 0x46, 0xd3, 0x7e, - 0x45, 0x17, 0xf7, 0xbe, 0x33, 0x84, 0x20, 0x08, 0xab, 0xdb, 0xa0, 0x01, - 0xcc, 0x8a, 0x0e, 0xfb, 0x81, 0x53, 0x44, 0x48, 0x07, 0xd5, 0x3e, 0xd2, - 0xcd, 0x3e, 0x6d, 0x00, 0x5d, 0x59, 0xeb, 0x15, 0x38, 0xb2, 0x49, 0x0e, - 0x85, 0x52, 0x93, 0x92, 0xd6, 0x27, 0x1f, 0x8f, 0x58, 0x54, 0x08, 0xc1, - 0x15, 0x66, 0x0a, 0x71, 0x6f, 0xe9, 0xf1, 0x5c, 0x3e, 0xcf, 0x9e, 0xde, - 0x1f, 0xdc, 0x79, 0xe9, 0xc1, 0x38, 0xa5, 0x3f, 0xe3, 0x60, 0x53, 0x0f, - 0xe6, 0xb3, 0x18, 0x67, 0x92, 0xff, 0x02, 0xa3, 0x20, 0x99, 0xda, 0xb2, - 0xa3, 0xa5, 0x72, 0x48, 0x1f, 0x76, 0x3e, 0xa2, 0x78, 0x37, 0xc2, 0xbf, - 0x00, 0x93, 0xdc, 0xa4, 0x96, 0xd1, 0xc8, 0xe9, 0xf1, 0xd2, 0xc7, 0x68, - 0x47, 0xdc, 0x36, 0x1c, 0x13, 0x34, 0xbd, 0xd9, 0x36, 0x9b, 0x70, 0x1a, - 0x56, 0x27, 0xd2, 0x7e, 0xe6, 0xd3, 0x74, 0x84, 0x24, 0x78, 0x68, 0xad, - 0x4c, 0x5e, 0xb9, 0xf2, 0x63, 0x80, 0x58, 0xc2, 0x93, 0xef, 0x7e, 0xf1, - 0xf7, 0x46, 0x4f, 0x89, 0xd3, 0x09, 0x07, 0x2c, 0x83, 0x44, 0x57, 0x7c, - 0x6d, 0x38, 0x27, 0x63, 0x22, 0x28, 0x55, 0xf5, 0x3e, 0xcb, 0x4d, 0x4f, - 0x4d, 0x82, 0x27, 0x96, 0x2d, 0xe9, 0x72, 0xeb, 0x86, 0x3a, 0x90, 0xa6, - 0xc4, 0x09, 0x6d, 0xbc, 0x13, 0x64, 0x58, 0x1e, 0xfc, 0xee, 0xee, 0x00, - 0x25, 0x92, 0x8d, 0x0b, 0x16, 0xf2, 0xd1, 0xd3, 0x2a, 0xb6, 0x00, 0xa3, - 0x4c, 0x58, 0xf9, 0x0b, 0x78, 0x9b, 0xc5, 0x11, 0xba, 0xa9, 0x36, 0xd7, - 0x74, 0xdd, 0x49, 0x30, 0x6d, 0x54, 0x6f, 0xb2, 0x0f, 0xf3, 0x7c, 0xc8, - 0x57, 0x55, 0x8e, 0x19, 0x09, 0x62, 0xaf, 0x34, 0x2e, 0x01, 0x65, 0xe3, - 0x15, 0x2c, 0xd6, 0x5f, 0x62, 0x50, 0xbf, 0xe9, 0xf6, 0x4a, 0xa8, 0x14, - 0x15, 0xe1, 0x22, 0xdc, 0x6d, 0x5e, 0x8b, 0x02, 0x86, 0x3d, 0xea, 0xcf, - 0x62, 0x9c, 0x70, 0xb1, 0x9e, 0x2e, 0x40, 0x62, 0x2d, 0x0d, 0x91, 0xac, - 0xaf, 0xcd, 0x3b, 0xa1, 0xf1, 0xfe, 0xaf, 0x16, 0xd4, 0xa3, 0xe5, 0x76, - 0xd9, 0x0e, 0x3e, 0x15, 0x59, 0x5d, 0x01, 0xc7, 0xf7, 0x57, 0xdb, 0x29, - 0x18, 0x03, 0x61, 0x00, 0xc5, 0x4b, 0xb1, 0x16, 0x3a, 0x9e, 0xa5, 0xc5, - 0x87, 0x88, 0x42, 0xda, 0xcd, 0x87, 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, - 0x77, 0x6e, 0x2d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, - 0x73, 0x64, 0x6b, 0x75, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x0f, 0x7e, 0x00, - 0x0f, 0x7e, 0x0f, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x06, - 0x01, 0x34, 0x34, 0x29, 0x01, 0x03, 0x2c, 0xf0, 0xfa, 0xf2, 0x6b, 0xa9, - 0x12, 0x4e, 0x73, 0x93, 0x45, 0x6c, 0x2f, 0x97, 0x33, 0x72, 0xa1, 0x3b, - 0x0d, 0x66, 0x6e, 0x37, 0x4b, 0xba, 0xaa, 0x65, 0x68, 0x18, 0x44, 0x35, - 0x5b, 0x9a, 0x6f, 0xf1, 0x3c, 0x2b, 0x18, 0x1f, 0xda, 0x4c, 0x63, 0x6f, - 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x73, 0x64, - 0x02, 0x42, 0x06, 0x01, 0x34, 0x34, 0x33, 0x09, 0x03, 0x2c, 0xf0, 0xfa, - 0xf2, 0x6b, 0xa9, 0x12, 0x4e, 0x73, 0x93, 0x45, 0x6c, 0x2f, 0x97, 0x33, - 0x72, 0xa1, 0x3b, 0x0d, 0x66, 0x6e, 0x37, 0x4b, 0xba, 0xaa, 0x65, 0x68, - 0x18, 0x44, 0x35, 0x5b, 0x9a, 0x6f, 0xf1, 0x3c, 0x2b, 0x18, 0x1f, 0xda, - 0x4c, 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x2d, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x05, 0x00, 0x00, 0x00, - 0x01, 0x0f, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0f, 0xfb, 0x00, 0x51, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x61, 0x04, 0x23, 0x00, 0x07, 0x07, - 0x09, 0x34, 0x00, 0x09, 0x09, 0x09, 0x34, 0x34, 0x08, 0x01, 0x02, 0x02, - 0x08, 0x08, 0x08, 0x08, 0x09, 0x08, 0x08, 0x09, 0x09, 0x09, 0x08, 0x08, - 0x08, 0x08, 0x09, 0x89, 0x56, 0x17, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x83, - 0x2b, 0xa8, 0x0d, 0x41, 0xb7, 0x59, 0x5c, 0x83, 0x2b, 0xa8, 0x0d, 0xdf, - 0xb4, 0xb1, 0x32, 0xb5, 0x0f, 0xc0, 0x25, 0xc5, 0x8d, 0xd9, 0x08, 0xc5, - 0x28, 0x81, 0xd3, 0x73, 0x52, 0xf9, 0x26, 0x9b, 0x66, 0x83, 0xaf, 0x24, - 0x40, 0x8e, 0xa7, 0xd6, 0x76, 0x12, 0x4a, 0x40, 0x61, 0xb5, 0x6a, 0xbc, - 0x33, 0xef, 0x01, 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, - 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0x2b, - 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, - 0x28, 0x00, 0x00, 0x00, 0x4e, 0x6b, 0x19, 0x54, 0xf5, 0xf0, 0xaf, 0x61, - 0xfa, 0x1e, 0x1f, 0x1f, 0x5e, 0x17, 0xd3, 0x8e, 0x04, 0x4b, 0xfa, 0x8d, - 0x34, 0x55, 0x45, 0x92, 0xd5, 0xd0, 0xb8, 0x8e, 0x56, 0xe9, 0x39, 0x37, - 0x8e, 0x7d, 0x7e, 0x88, 0x56, 0x30, 0x48, 0x61, 0xb4, 0xed, 0x1e, 0x15, - 0x64, 0xfc, 0xa8, 0xb1, 0x02, 0xbb, 0x9c, 0x14, 0xe9, 0xd1, 0xe0, 0xcf, - 0x40, 0x41, 0x46, 0x5d, 0xb0, 0xda, 0xba, 0x8c, 0x3a, 0x41, 0x12, 0x91, - 0xeb, 0x13, 0xdf, 0x2c, 0x6e, 0x25, 0x75, 0xb3, 0x92, 0xff, 0xb0, 0xa9, - 0xa5, 0xef, 0x3a, 0x4c, 0x6b, 0x54, 0x55, 0x0e, 0x7e, 0x93, 0x16, 0x7f, - 0xe6, 0x22, 0x22, 0x51, 0xe2, 0x22, 0xa4, 0x35, 0x33, 0xec, 0xdc, 0xa8, - 0x73, 0x64, 0x59, 0xc1, 0x4d, 0xad, 0xa0, 0x56, 0xbf, 0xad, 0x45, 0x64, - 0xda, 0xb0, 0x08, 0x4a, 0x82, 0xfc, 0x0d, 0x21, 0xb7, 0x8b, 0x59, 0x90, - 0xac, 0xb2, 0x08, 0x1b, 0x50, 0x82, 0x0c, 0x87, 0xd6, 0x48, 0x5c, 0xdd, - 0x6b, 0x02, 0x7f, 0xab, 0x3e, 0xdc, 0x25, 0x1f, 0x53, 0x49, 0xb5, 0x6d, - 0x0f, 0x0c, 0xbe, 0xae, 0x1d, 0xab, 0x8b, 0x13, 0x9d, 0xd7, 0x6c, 0x91, - 0xaa, 0x90, 0xe8, 0x63, 0x06, 0x6d, 0xa8, 0xf0, 0xea, 0x21, 0xf6, 0xa8, - 0xfd, 0x15, 0x6d, 0x78, 0x66, 0x42, 0xae, 0x4c, 0xa7, 0x7a, 0x85, 0x15, - 0x7d, 0xf9, 0xed, 0x92, 0x1c, 0xde, 0x7c, 0x71, 0xd0, 0x6b, 0x25, 0x24, - 0x22, 0x6b, 0xe4, 0x5e, 0x60, 0xda, 0xbd, 0x95, 0x32, 0x21, 0xe8, 0xb1, - 0xcb, 0x07, 0x1b, 0x08, 0xf5, 0x49, 0x4f, 0x60, 0x8c, 0xe8, 0xb0, 0x71, - 0x2a, 0x8b, 0x91, 0x17, 0x16, 0x93, 0x39, 0x49, 0x8d, 0x47, 0x1f, 0xe8, - 0x2b, 0x12, 0xa6, 0x4f, 0xa1, 0x77, 0x37, 0xe7, 0x39, 0x68, 0x5c, 0x68, - 0x2b, 0xad, 0xa8, 0x3c, 0xa0, 0x8a, 0xf5, 0xb7, 0x51, 0x9f, 0x2d, 0x85, - 0x1a, 0x99, 0x02, 0x4c, 0x84, 0x5f, 0x4d, 0xe6, 0x55, 0x64, 0xd7, 0x5b, - 0x00, 0x48, 0xde, 0xf2, 0x77, 0x39, 0x6e, 0x7b, 0x0e, 0x97, 0x81, 0xd2, - 0x8a, 0x1b, 0x20, 0x30, 0x60, 0xbe, 0x94, 0xf0, 0x09, 0x34, 0xfe, 0x64, - 0xbb, 0xbb, 0xcb, 0x97, 0x91, 0x43, 0x6d, 0x57, 0x45, 0x7d, 0xc5, 0x43, - 0x5a, 0x78, 0x0d, 0xd8, 0xb9, 0xf5, 0x43, 0x13, 0x21, 0xd6, 0x31, 0x6e, - 0x21, 0x9a, 0x3f, 0x8f, 0xe2, 0x57, 0x32, 0xdb, 0x50, 0x61, 0x45, 0x9f, - 0xb9, 0x7b, 0x73, 0x10, 0xb9, 0xd0, 0x66, 0xaf, 0xa0, 0x3a, 0x77, 0x93, - 0x9b, 0xd3, 0x32, 0xb0, 0xda, 0x01, 0x17, 0x90, 0x1a, 0xa5, 0x9f, 0x2b, - 0x9f, 0x8f, 0x93, 0x6e, 0x4d, 0x69, 0x40, 0xec, 0x56, 0x76, 0x61, 0x2d, - 0xcd, 0xdf, 0xc5, 0xfe, 0x9e, 0x26, 0x2f, 0x78, 0x78, 0xab, 0x5a, 0x32, - 0xa6, 0xe9, 0x7a, 0x85, 0x15, 0xc6, 0x2f, 0x10, 0x37, 0x35, 0xf6, 0xfa, - 0xc0, 0xdd, 0xb0, 0xa9, 0xa1, 0x0d, 0x22, 0xc1, 0xab, 0xc8, 0x8c, 0x2a, - 0x77, 0x0b, 0xd3, 0x52, 0xdb, 0x53, 0x33, 0x78, 0xf3, 0xf6, 0x33, 0x5d, - 0x9f, 0xb7, 0xb6, 0x46, 0xf6, 0x79, 0x9e, 0x08, 0x16, 0xd8, 0x48, 0xcf, - 0x70, 0x4d, 0x00, 0x36, 0x30, 0xdb, 0xb3, 0x76, 0xa5, 0x16, 0x78, 0xf8, - 0xaf, 0x71, 0x6b, 0x50, 0x92, 0xfc, 0x52, 0xd6, 0x2c, 0xee, 0xa8, 0xb0, - 0xbe, 0x89, 0x18, 0xc0, 0x7a, 0x72, 0xa5, 0x36, 0x31, 0x7b, 0x86, 0xca, - 0xc0, 0xe4, 0x08, 0x17, 0x1d, 0x6e, 0xe5, 0x4c, 0x82, 0x86, 0x3e, 0x8c, - 0x60, 0xf7, 0x04, 0x8f, 0x2c, 0x64, 0x3d, 0x2e, 0x23, 0x22, 0x10, 0x8e, - 0x88, 0x45, 0xcd, 0x18, 0xd6, 0xba, 0x4c, 0x40, 0x1e, 0x31, 0xfb, 0xbf, - 0xda, 0xe7, 0xae, 0x87, 0x72, 0x81, 0xb2, 0x69, 0x97, 0xe3, 0x2c, 0x5e, - 0xbb, 0x26, 0x1b, 0xe2, 0x83, 0xf3, 0x90, 0x37, 0x0d, 0xb1, 0xa2, 0x58, - 0x88, 0x63, 0xe7, 0x6e, 0x4a, 0xbd, 0x76, 0x90, 0x73, 0x65, 0x85, 0x96, - 0xcc, 0x2d, 0xb7, 0x51, 0x0d, 0xa7, 0x8a, 0xe2, 0x8c, 0x47, 0xb9, 0x44, - 0x09, 0xc3, 0x8f, 0x24, 0x65, 0x79, 0xf0, 0xd0, 0xc3, 0xa5, 0x1f, 0xc3, - 0xca, 0xd7, 0x57, 0xac, 0x1c, 0xcf, 0xa9, 0xfc, 0x81, 0x12, 0x53, 0x0b, - 0xe5, 0x9d, 0x38, 0x29, 0x14, 0xd6, 0xf5, 0x17, 0x06, 0xfb, 0xc2, 0x9d, - 0x25, 0x10, 0xf9, 0xde, 0x4b, 0x33, 0x0d, 0xf1, 0xdd, 0xf5, 0xbc, 0xa8, - 0x2b, 0xdc, 0xdb, 0x51, 0x7d, 0x69, 0x63, 0x68, 0x61, 0x74, 0x64, 0x6b, - 0x75, 0x85, 0x41, 0x03, 0x23, 0x00, 0x07, 0x07, 0x08, 0x34, 0x00, 0x09, - 0x09, 0x09, 0x34, 0x34, 0x08, 0x01, 0x02, 0x02, 0x08, 0x08, 0x08, 0x08, - 0x09, 0x08, 0x08, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x09, 0x89, - 0x16, 0x17, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x83, 0x25, 0xab, 0x8f, 0x41, - 0xb7, 0x59, 0x5c, 0x83, 0x25, 0xab, 0x8f, 0xdf, 0xb4, 0xb1, 0x32, 0xb5, - 0x0f, 0xc0, 0x25, 0xc5, 0x8d, 0xd9, 0x08, 0xc5, 0x28, 0x81, 0xd3, 0x73, - 0x52, 0xf9, 0x26, 0x9b, 0x66, 0x83, 0xaf, 0x24, 0x40, 0x8e, 0xa7, 0xd6, - 0x76, 0x12, 0x4a, 0x40, 0x61, 0xb5, 0x6a, 0xbc, 0x33, 0xef, 0x01, 0xda, - 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, - 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0x2b, 0x01, 0x00, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, - 0xe3, 0xb5, 0xfb, 0x0d, 0xa0, 0x75, 0xd1, 0xa9, 0x33, 0x31, 0xc6, 0x84, - 0xba, 0x58, 0x50, 0xb0, 0x71, 0x32, 0x4f, 0x72, 0x88, 0x46, 0x71, 0x06, - 0xb3, 0x82, 0x5e, 0x30, 0xfd, 0xc8, 0x5b, 0xc8, 0xf3, 0x24, 0x92, 0xe0, - 0xce, 0x8b, 0xf7, 0x50, 0x20, 0xc3, 0xeb, 0x1b, 0xf4, 0xef, 0x4f, 0xfa, - 0x28, 0x4d, 0x02, 0x4d, 0x7c, 0x46, 0xf1, 0x91, 0x89, 0xde, 0xc6, 0xfa, - 0x79, 0xc5, 0xbd, 0x17, 0xa1, 0xc6, 0x1d, 0x8c, 0xd4, 0x57, 0xa6, 0x58, - 0x66, 0xce, 0xe5, 0xb0, 0x8b, 0x54, 0xef, 0x3b, 0x24, 0x9b, 0xa4, 0xc4, - 0x6a, 0xa9, 0xf3, 0x1b, 0x73, 0x37, 0x10, 0xc0, 0xe1, 0xcb, 0xc8, 0x90, - 0x14, 0x88, 0x97, 0x25, 0x8b, 0x7c, 0xa2, 0x66, 0x36, 0x89, 0x55, 0x8d, - 0x68, 0xe7, 0x55, 0x20, 0x10, 0x68, 0x14, 0x2f, 0x05, 0x3b, 0xe3, 0x81, - 0x08, 0xfe, 0x54, 0x7d, 0xa5, 0x51, 0x2a, 0x39, 0x86, 0x11, 0xce, 0x26, - 0x8d, 0xe1, 0xec, 0x30, 0x3f, 0xf9, 0xa3, 0x3d, 0x43, 0x6c, 0xad, 0x23, - 0x54, 0x20, 0x7d, 0x60, 0xa5, 0x42, 0xbd, 0x3d, 0x22, 0xc8, 0x95, 0x9b, - 0xab, 0x5b, 0xf7, 0xc1, 0x11, 0xfb, 0xf1, 0x70, 0xa2, 0x43, 0xcb, 0x53, - 0x8c, 0x18, 0x0d, 0x8a, 0xb2, 0xa5, 0xbd, 0x87, 0x2b, 0x8b, 0xdf, 0x79, - 0x96, 0x29, 0x20, 0x8e, 0x34, 0x4a, 0x45, 0x96, 0x33, 0x8d, 0xa8, 0xb0, - 0x47, 0x26, 0x4f, 0x8b, 0xad, 0xb5, 0xa7, 0x2d, 0x15, 0x58, 0x92, 0x7b, - 0x4b, 0x53, 0xa9, 0x5e, 0x51, 0x39, 0x9c, 0xbd, 0x7e, 0x8f, 0x7f, 0x9f, - 0xb7, 0x38, 0xcd, 0x7e, 0xff, 0x7d, 0x73, 0x1f, 0xab, 0x3a, 0x61, 0xaa, - 0xde, 0x73, 0x28, 0xb2, 0x6f, 0x1e, 0xc9, 0x5e, 0x59, 0x71, 0x6b, 0xe8, - 0x6d, 0x63, 0xf3, 0x9e, 0xdf, 0x52, 0x86, 0x60, 0x1c, 0xbd, 0xc7, 0xeb, - 0xaf, 0x82, 0x83, 0xaa, 0x68, 0xa6, 0x71, 0x7a, 0xe8, 0xd3, 0xd4, 0xc8, - 0xe7, 0x9a, 0xcc, 0x3c, 0xc2, 0xdf, 0x0c, 0x42, 0xe8, 0xae, 0xc7, 0xd8, - 0x1f, 0x66, 0x0a, 0x57, 0x09, 0x14, 0x02, 0x74, 0x9a, 0x7a, 0x07, 0xb3, - 0x19, 0x87, 0x8d, 0xa9, 0x45, 0x25, 0x26, 0x48, 0xb3, 0x20, 0x3c, 0xf7, - 0x5a, 0x1c, 0xae, 0xc7, 0x06, 0x9e, 0x1a, 0x0a, 0x23, 0xf3, 0x39, 0x25, - 0x2c, 0x91, 0x7c, 0x5e, 0x87, 0xe7, 0x55, 0xc4, 0x69, 0xf3, 0x3e, 0xeb, - 0xc5, 0x44, 0xa8, 0xe3, 0xec, 0xc1, 0xfe, 0x70, 0xbf, 0xdd, 0xbb, 0xf0, - 0x22, 0xe1, 0x19, 0xa1, 0x6d, 0x7a, 0x9a, 0xa3, 0x36, 0x90, 0xbc, 0x1a, - 0xa7, 0x37, 0xf8, 0xcf, 0xdc, 0x9e, 0x23, 0x17, 0x42, 0xd5, 0xa0, 0xd3, - 0x36, 0xb0, 0xb1, 0xf5, 0x1a, 0x95, 0xbc, 0xe8, 0x0f, 0xb4, 0x58, 0x76, - 0x40, 0x74, 0xd0, 0x21, 0xaf, 0xae, 0xc6, 0xb4, 0x84, 0xd7, 0xfc, 0x70, - 0x6a, 0x8f, 0x41, 0x57, 0x2b, 0x8e, 0xbc, 0x6b, 0x21, 0x65, 0xcc, 0xa0, - 0x8e, 0xb9, 0x0b, 0x46, 0xef, 0xb3, 0x56, 0xec, 0x8a, 0xd6, 0x4d, 0xdd, - 0x97, 0xbd, 0xdd, 0x65, 0xbf, 0x26, 0xab, 0xba, 0x0d, 0xd1, 0x22, 0x7e, - 0xb6, 0x8a, 0xb4, 0x92, 0xc9, 0xa6, 0x48, 0xd4, 0x64, 0x17, 0xc6, 0xb5, - 0xb9, 0xce, 0x45, 0x6d, 0xf4, 0xd9, 0x3d, 0xa0, 0xb3, 0x86, 0x67, 0x19, - 0xad, 0xd8, 0x32, 0x2b, 0xf7, 0xab, 0x90, 0xee, 0x91, 0x8f, 0x73, 0xe4, - 0xc0, 0x29, 0xde, 0x45, 0x8a, 0xfb, 0xca, 0x74, 0x3b, 0x50, 0xf1, 0x34, - 0x40, 0x36, 0x25, 0x8a, 0xe0, 0xf9, 0x7f, 0x55, 0xc5, 0x59, 0x89, 0xbb, - 0x43, 0x03, 0xa3, 0xdd, 0x8c, 0x83, 0x03, 0xc6, 0xef, 0x60, 0x02, 0xc5, - 0xd8, 0x29, 0x3f, 0x2f, 0x56, 0xba, 0x8b, 0x97, 0x0a, 0xc4, 0xf3, 0x07, - 0x3f, 0xca, 0x0f, 0xdf, 0xb9, 0x5d, 0x59, 0x42, 0x36, 0x02, 0xf7, 0x0f, - 0x03, 0xc8, 0xf2, 0xb7, 0xd8, 0x64, 0xcd, 0x1e, 0xe4, 0xe1, 0xa0, 0xbd, - 0x0f, 0x70, 0xfb, 0xcf, 0x77, 0x77, 0xef, 0x9d, 0xdd, 0xc1, 0x61, 0xab, - 0x3c, 0xdb, 0xe4, 0x35, 0x11, 0xab, 0xde, 0x40, 0x7d, 0x51, 0xba, 0xb1, - 0x7d, 0x13, 0xf1, 0x58, 0x03, 0xca, 0xae, 0x12, 0x4a, 0xa3, 0xb6, 0xed, - 0xd7, 0x18, 0x1c, 0xb6, 0xd8, 0x69, 0x63, 0x68, 0x61, 0x74, 0x64, 0x6b, - 0x75, 0x89, 0x70, 0x02, 0x23, 0x00, 0x07, 0x07, 0x09, 0x34, 0x00, 0x09, - 0x09, 0x09, 0x34, 0x34, 0x08, 0x01, 0x02, 0x02, 0x08, 0x08, 0x08, 0x08, - 0x09, 0x08, 0x08, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x09, 0x91, - 0x62, 0x29, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x4b, 0xa2, 0xb8, 0x84, 0x41, - 0xb7, 0x59, 0x5c, 0x4b, 0xa2, 0xb8, 0x84, 0x37, 0xee, 0x5a, 0x85, 0xe1, - 0xcb, 0xdd, 0xc8, 0xce, 0x07, 0x77, 0xee, 0x01, 0x3f, 0x96, 0x7b, 0x33, - 0x30, 0x3a, 0xcd, 0x64, 0x14, 0x5e, 0x86, 0xb3, 0x7b, 0x2d, 0x6c, 0xa9, - 0xc0, 0xcf, 0xd8, 0x43, 0x7e, 0x59, 0x45, 0xac, 0xff, 0x92, 0x4b, 0xda, - 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, - 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0x2a, 0x04, 0x00, 0x04, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, - 0xfa, 0x4b, 0x92, 0xea, 0x4b, 0xef, 0xde, 0x03, 0xd5, 0xe2, 0xee, 0xe5, - 0x67, 0xd4, 0x99, 0x63, 0x37, 0x68, 0x91, 0xbc, 0x4f, 0xbc, 0x41, 0xe9, - 0x01, 0xc5, 0x4d, 0x59, 0x2a, 0x9b, 0x42, 0x60, 0x07, 0x7e, 0xc2, 0xbc, - 0x62, 0xcc, 0xbc, 0xa7, 0xf1, 0xe4, 0x20, 0x5f, 0xe3, 0xe8, 0x9f, 0x16, - 0x7a, 0x77, 0xd2, 0xb7, 0xad, 0x98, 0xc3, 0xb4, 0x99, 0xdb, 0x36, 0x1a, - 0xe4, 0xf0, 0xfc, 0xe1, 0xc8, 0x2f, 0x8c, 0xcf, 0x6f, 0x97, 0x48, 0x09, - 0x4a, 0xae, 0xc7, 0xf9, 0xfb, 0xb7, 0x5f, 0x64, 0x6a, 0x79, 0xa1, 0x27, - 0xeb, 0x59, 0x7d, 0x0a, 0xd3, 0x56, 0x27, 0x1d, 0x56, 0xd3, 0x62, 0x1e, - 0x7f, 0xb5, 0x0f, 0x50, 0x9c, 0x4d, 0x1d, 0xd5, 0x53, 0xcb, 0x08, 0x07, - 0x56, 0x93, 0x9e, 0x4f, 0xb2, 0xd0, 0x12, 0xc7, 0x50, 0xcf, 0x99, 0xac, - 0x24, 0xdb, 0x94, 0xab, 0x08, 0x89, 0x60, 0x2f, 0x6c, 0xd0, 0xc2, 0x2e, - 0x6d, 0x08, 0xe0, 0xf9, 0xfc, 0x7e, 0x5b, 0x54, 0x92, 0xaa, 0x01, 0xfd, - 0xf6, 0x49, 0xb1, 0xfc, 0xd4, 0x51, 0x83, 0x73, 0xaf, 0xac, 0x38, 0x78, - 0x8e, 0x9b, 0x42, 0x4e, 0x83, 0xbb, 0x9d, 0xd7, 0x5c, 0xdb, 0x73, 0xd3, - 0x3d, 0x2c, 0xe2, 0x4c, 0x57, 0xa4, 0xfa, 0xdf, 0x53, 0x44, 0x29, 0x71, - 0x22, 0xb6, 0x89, 0x84, 0x80, 0xca, 0xcb, 0x7c, 0x5f, 0x15, 0x19, 0x4b, - 0x06, 0x28, 0x5d, 0x4a, 0x9b, 0xc8, 0x59, 0xa7, 0x9e, 0xa2, 0xba, 0x32, - 0x5d, 0xf2, 0xcb, 0xa9, 0xc6, 0xba, 0x09, 0xee, 0xd2, 0x00, 0x32, 0x53, - 0x8b, 0x39, 0xff, 0xc4, 0x63, 0xac, 0xbc, 0x1c, 0x15, 0xb8, 0x79, 0xc2, - 0xe3, 0xda, 0x8d, 0xb2, 0x95, 0x8d, 0x3c, 0x10, 0xec, 0x93, 0x03, 0xc1, - 0x07, 0x84, 0x47, 0xf3, 0xeb, 0xe3, 0x10, 0x33, 0xa1, 0x2e, 0xc6, 0x48, - 0x44, 0x2c, 0x38, 0x36, 0xe1, 0x68, 0x3c, 0xe8, 0x0d, 0x5c, 0x8a, 0xdc, - 0x1f, 0xe8, 0x3b, 0xb2, 0x0f, 0xea, 0x27, 0x18, 0x7a, 0x7f, 0x82, 0x6a, - 0x96, 0xfa, 0x63, 0xd3, 0x5c, 0xbf, 0xf6, 0x1d, 0x9e, 0xf2, 0xd9, 0x83, - 0x3b, 0xf0, 0x1b, 0x29, 0x49, 0x8d, 0xb3, 0xdc, 0x60, 0x47, 0x9d, 0x2b, - 0xac, 0xd6, 0x6e, 0x59, 0xb3, 0x09, 0x0d, 0xa7, 0xfb, 0x0e, 0x43, 0x56, - 0xa3, 0x80, 0x2c, 0x9f, 0xc1, 0xe8, 0xd2, 0xef, 0x05, 0xc5, 0x25, 0x4c, - 0x5b, 0x67, 0x1a, 0x54, 0x0b, 0x55, 0x83, 0x3d, 0xfb, 0x38, 0x0e, 0xd2, - 0xc0, 0x1a, 0xcd, 0x9f, 0x81, 0x3e, 0x6d, 0x7f, 0xe4, 0x3f, 0x34, 0x0c, - 0xdc, 0x99, 0x5a, 0x77, 0xd4, 0xe4, 0xff, 0x4a, 0x7b, 0x8a, 0x95, 0xe4, - 0x46, 0x3d, 0x7b, 0xc4, 0x0e, 0xdd, 0xc7, 0x2d, 0xf4, 0xfa, 0x5e, 0x50, - 0xae, 0x9c, 0xca, 0x64, 0x97, 0xad, 0x03, 0x30, 0x3e, 0x05, 0xc4, 0x33, - 0x1e, 0x2c, 0x03, 0x2b, 0x06, 0x2c, 0x79, 0x13, 0xae, 0x1b, 0x65, 0xf1, - 0x1f, 0xb9, 0xe4, 0x8a, 0x06, 0x96, 0xea, 0xc4, 0x6e, 0x17, 0x19, 0x03, - 0x54, 0xe8, 0x39, 0xe7, 0xeb, 0x7b, 0xbc, 0x25, 0xd6, 0x55, 0x6c, 0x76, - 0x5f, 0xf7, 0xd2, 0x0e, 0x54, 0x46, 0x9f, 0x5d, 0xa4, 0x3d, 0xac, 0xa1, - 0x19, 0x7b, 0x7c, 0x5a, 0x44, 0x54, 0x65, 0x5d, 0x43, 0x26, 0x5f, 0x47, - 0x63, 0x2b, 0x00, 0xe3, 0xb4, 0xe9, 0x70, 0x8c, 0x31, 0x50, 0x7c, 0x37, - 0x01, 0x43, 0x6c, 0x29, 0xc3, 0xae, 0x59, 0xb7, 0x0b, 0xb9, 0x9a, 0x72, - 0x69, 0xe0, 0xd1, 0xb0, 0x47, 0x53, 0xf0, 0xb8, 0x8b, 0xc8, 0x80, 0x3c, - 0x58, 0xfa, 0x34, 0xf2, 0x44, 0x27, 0xb7, 0xfc, 0x44, 0x73, 0xfb, 0xe5, - 0xe1, 0x8b, 0xdb, 0x2b, 0xc5, 0x73, 0x97, 0x25, 0xb3, 0xef, 0x16, 0xfd, - 0xba, 0x08, 0x3d, 0x15, 0x2a, 0x03, 0xb5, 0x4d, 0x2a, 0x8c, 0xf5, 0x53, - 0x11, 0x97, 0x3c, 0x35, 0x66, 0x1d, 0x59, 0xc8, 0xc9, 0x79, 0x48, 0x6d, - 0x19, 0x4f, 0xa7, 0x07, 0x25, 0x4d, 0xb2, 0xfc, 0x1e, 0xbc, 0x9a, 0x0c, - 0x6e, 0x46, 0x2b, 0x58, 0x45, 0xbe, 0xe7, 0x8e, 0x09, 0xa5, 0xa0, 0xd3, - 0x5a, 0xf5, 0x6e, 0x92, 0x7b, 0x5b, 0x21, 0x07, 0xab, 0xf3, 0x57, 0xd6, - 0x93, 0x4b, 0x56, 0x3b, 0x9c, 0x3c, 0x4b, 0x85, 0xb0, 0x62, 0x18, 0x3e, - 0x7c, 0xc5, 0x25, 0xe2, 0xf2, 0xfc, 0xa3, 0xca, 0x88, 0xd6, 0xb2, 0x01, - 0x11, 0xcd, 0x93, 0x9a, 0x76, 0x84, 0xc2, 0x2d, 0x07, 0xd3, 0xbb, 0xac, - 0x99, 0xde, 0x29, 0x00, 0xf7, 0x3d, 0x06, 0xea, 0xdc, 0x88, 0xfd, 0xc6, - 0x6e, 0xf5, 0x55, 0x64, 0x73, 0x4e, 0x3b, 0xa9, 0x24, 0x44, 0x63, 0x1c, - 0x50, 0x29, 0x66, 0xc4, 0x74, 0x70, 0xcb, 0xd8, 0x57, 0x0c, 0x60, 0x50, - 0x6d, 0x64, 0x64, 0xd1, 0x53, 0xef, 0x62, 0xef, 0x61, 0xf4, 0xe2, 0xfe, - 0x4c, 0xaa, 0x9f, 0xe9, 0x81, 0x01, 0xe1, 0x97, 0xaa, 0xc0, 0x06, 0xbf, - 0x40, 0x19, 0x64, 0x24, 0x6e, 0x80, 0x73, 0x00, 0x5c, 0x86, 0x3e, 0xc2, - 0xcf, 0x8c, 0x09, 0xc0, 0xfa, 0x4a, 0xb3, 0x3a, 0x0d, 0x81, 0x1d, 0x49, - 0x58, 0x09, 0xe8, 0x31, 0x0e, 0xd7, 0x60, 0x8d, 0x9d, 0xfe, 0x9f, 0x35, - 0xf7, 0x8d, 0xa1, 0x12, 0x04, 0xb2, 0x47, 0xac, 0x31, 0x92, 0x03, 0x0a, - 0x10, 0x50, 0xb7, 0x86, 0x3d, 0xcd, 0x15, 0x8f, 0x25, 0x93, 0x24, 0x7a, - 0x5f, 0xa0, 0x3c, 0x41, 0xaa, 0xb2, 0x96, 0xce, 0xd3, 0x0c, 0xe9, 0x55, - 0x66, 0x37, 0x5c, 0xf3, 0x02, 0x3c, 0xa1, 0x09, 0xa4, 0x9e, 0x90, 0xc9, - 0x82, 0xab, 0xd4, 0x04, 0x2e, 0x8b, 0xb4, 0x8d, 0x5b, 0xcc, 0x19, 0x5a, - 0xfe, 0x86, 0x9c, 0x6c, 0x56, 0x09, 0x86, 0x36, 0xef, 0xe8, 0x1f, 0x3a, - 0xbc, 0xda, 0x4c, 0x68, 0xac, 0xa2, 0x1b, 0xd1, 0x23, 0x75, 0x28, 0xed, - 0x9f, 0x84, 0x2e, 0x40, 0x57, 0x5f, 0x0a, 0x85, 0xe4, 0x77, 0x59, 0x53, - 0x12, 0x32, 0xd6, 0x3c, 0x1b, 0xaf, 0x95, 0xa1, 0x1c, 0x14, 0x1a, 0x42, - 0x7d, 0xc7, 0x7b, 0x21, 0xd1, 0x4e, 0xb9, 0x29, 0x85, 0xef, 0xa2, 0x61, - 0x1c, 0xe5, 0x16, 0x44, 0xbe, 0xfb, 0xa3, 0x21, 0x4f, 0x94, 0x70, 0xff, - 0x5c, 0xc2, 0x1d, 0x0b, 0x39, 0x36, 0x84, 0x0e, 0x61, 0xe2, 0x1c, 0x63, - 0x74, 0xe0, 0x30, 0x01, 0xbe, 0x39, 0x0f, 0x6f, 0xe6, 0x29, 0xad, 0xd8, - 0x8c, 0xdd, 0x8b, 0x24, 0x38, 0x6f, 0x67, 0x8a, 0x2d, 0x82, 0x1e, 0x8e, - 0x45, 0xcb, 0xec, 0x2d, 0xe3, 0xb4, 0x03, 0x8e, 0x46, 0x2e, 0x01, 0xb0, - 0xca, 0x4f, 0xe0, 0x2c, 0x52, 0xd3, 0x4c, 0xdd, 0xd6, 0x62, 0xf3, 0x38, - 0x3f, 0x3c, 0xc1, 0x58, 0xaa, 0x87, 0x3d, 0x4f, 0xb2, 0xb1, 0x54, 0x65, - 0xdc, 0x1c, 0xc8, 0x16, 0x88, 0x15, 0x53, 0xb0, 0x4e, 0x77, 0xae, 0xe0, - 0x34, 0x18, 0x36, 0x34, 0x31, 0x74, 0x4c, 0x79, 0x0f, 0x2b, 0x1a, 0x11, - 0x06, 0x06, 0xaa, 0x60, 0x31, 0x6e, 0x65, 0x9e, 0x1b, 0xb0, 0x61, 0xd6, - 0x90, 0xd1, 0x1d, 0x4c, 0x36, 0xfe, 0xec, 0x26, 0xcc, 0xba, 0xce, 0xd7, - 0xe7, 0x0c, 0x53, 0x90, 0xe8, 0xce, 0xce, 0xed, 0x58, 0x37, 0x37, 0x3f, - 0x40, 0x39, 0xeb, 0x8c, 0xfb, 0x7d, 0x93, 0xa2, 0x26, 0x4e, 0xbf, 0x49, - 0xe7, 0x95, 0xc0, 0x12, 0x6a, 0xec, 0xfb, 0xbe, 0x00, 0x62, 0xb9, 0xc9, - 0x0d, 0x5a, 0x37, 0xf9, 0xae, 0x84, 0x95, 0x89, 0x20, 0x47, 0x48, 0xf6, - 0xf8, 0x73, 0x92, 0x5f, 0xe1, 0x4a, 0xb4, 0x9e, 0xd8, 0x75, 0xf3, 0x38, - 0x48, 0xe1, 0x29, 0x95, 0x0d, 0x74, 0x6b, 0x98, 0x96, 0x6e, 0xc9, 0x3f, - 0xfc, 0x44, 0x91, 0x4d, 0xf4, 0x4c, 0xb7, 0x38, 0xd7, 0xec, 0xbf, 0xf6, - 0x78, 0x05, 0x7d, 0x1b, 0xe5, 0x68, 0x8a, 0xbc, 0x6a, 0x6a, 0x29, 0xb6, - 0xc6, 0x9a, 0x8d, 0x7a, 0x0e, 0x00, 0x80, 0x73, 0xf5, 0x88, 0x5d, 0x2a, - 0xa2, 0x60, 0x98, 0x1e, 0xf5, 0x06, 0x3b, 0xef, 0xa9, 0x46, 0x6b, 0x89, - 0x24, 0xb0, 0xf4, 0x34, 0x42, 0x15, 0x87, 0xd3, 0xc9, 0x36, 0xe0, 0x52, - 0x5f, 0x57, 0x8e, 0x65, 0x5c, 0x7f, 0x7c, 0xf2, 0x66, 0xd8, 0xd1, 0xbf, - 0x13, 0x95, 0x65, 0xb0, 0x7a, 0xa0, 0xbb, 0xee, 0xc9, 0x20, 0xff, 0x26, - 0xda, 0xa0, 0x61, 0x65, 0xd5, 0x3c, 0xdf, 0xb5, 0xf0, 0xd2, 0x02, 0x4f, - 0x97, 0x65, 0x48, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, - 0x2e, 0x61, 0x70, 0x73, 0x64, 0x64, 0x6b, 0x75, 0x8a, 0x11, 0x01, 0x23, - 0x00, 0x07, 0x07, 0x09, 0x34, 0x00, 0x09, 0x09, 0x09, 0x34, 0x34, 0x08, - 0x01, 0x02, 0x02, 0x08, 0x08, 0x08, 0x08, 0x09, 0x08, 0x08, 0x09, 0x09, - 0x09, 0x08, 0x08, 0x08, 0x08, 0x09, 0x92, 0x1a, 0x33, 0x13, 0x41, 0xb7, - 0x59, 0x5c, 0x4b, 0x89, 0xf6, 0xba, 0x41, 0xb7, 0x59, 0x5c, 0x4b, 0x89, - 0xf6, 0xba, 0xb1, 0x0a, 0x33, 0x78, 0x48, 0x21, 0xea, 0x97, 0x6e, 0xb7, - 0xc7, 0x2e, 0xdb, 0x0f, 0x9b, 0x01, 0xd0, 0x22, 0x6d, 0xbb, 0x64, 0x14, - 0x5e, 0x86, 0xb3, 0x7b, 0x2d, 0x6c, 0xa9, 0xc0, 0xcf, 0xd8, 0x43, 0x7e, - 0x59, 0x45, 0xac, 0xff, 0x92, 0x4b, 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, - 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, - 0x07, 0x09, 0x2a, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, - 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x12, 0x83, 0x28, 0x8c, 0xcd, - 0x78, 0x8c, 0x1b, 0x02, 0xa2, 0x38, 0xa7, 0x25, 0xc1, 0x25, 0x59, 0xcd, - 0x36, 0xb2, 0x21, 0xa1, 0x91, 0xd0, 0xc3, 0x54, 0x89, 0x64, 0xa8, 0x3d, - 0x07, 0xcb, 0x8f, 0xf7, 0xa6, 0x55, 0xc2, 0x96, 0xf6, 0x35, 0xc1, 0x67, - 0xdf, 0x2f, 0x1f, 0xda, 0xa8, 0xf8, 0x8c, 0xc9, 0xa7, 0x5e, 0x7f, 0x1f, - 0xa8, 0xd3, 0x38, 0x57, 0xa2, 0xf4, 0x57, 0x32, 0x17, 0xe3, 0x06, 0xe3, - 0xb6, 0x56, 0x60, 0x6e, 0xbe, 0x12, 0x60, 0x00, 0xfd, 0xa8, 0x4c, 0x3f, - 0x2b, 0x54, 0x9c, 0xfb, 0x87, 0x8b, 0xfa, 0x9e, 0xb8, 0xb2, 0x80, 0x36, - 0xf1, 0x5b, 0xcd, 0x9d, 0x74, 0xa1, 0x7b, 0xbf, 0xf6, 0x4c, 0x64, 0x58, - 0x67, 0x8b, 0x68, 0x05, 0x15, 0x7e, 0x4b, 0x54, 0xe9, 0x84, 0x59, 0x70, - 0x42, 0x80, 0x67, 0x6c, 0x45, 0x62, 0x12, 0x03, 0x27, 0x2b, 0x32, 0xdc, - 0x78, 0x85, 0x3d, 0x74, 0x28, 0x89, 0x5c, 0x33, 0x15, 0x79, 0x63, 0x1f, - 0xd7, 0x26, 0xbf, 0x5d, 0xf6, 0xb1, 0xb7, 0x9e, 0x37, 0x86, 0xd8, 0xf6, - 0xf9, 0xc3, 0x66, 0x90, 0x50, 0x5a, 0x0e, 0xeb, 0xcc, 0xe0, 0xf2, 0x19, - 0xbb, 0xd7, 0x6a, 0xe4, 0xea, 0x87, 0xf9, 0x17, 0x20, 0x88, 0xf6, 0xc0, - 0xc7, 0xb7, 0x55, 0x25, 0xef, 0x15, 0xec, 0xc5, 0x80, 0x52, 0x9a, 0x92, - 0xdb, 0x32, 0xf3, 0xc2, 0xa2, 0x55, 0xd6, 0xd9, 0x5b, 0xe6, 0xb1, 0x95, - 0x18, 0x2b, 0xf8, 0x94, 0x21, 0x56, 0x29, 0x30, 0xf3, 0x61, 0x39, 0x22, - 0x03, 0x86, 0xce, 0x81, 0x6d, 0x9e, 0xdb, 0x5b, 0x49, 0xdb, 0x2c, 0x1d, - 0x0d, 0x45, 0xa9, 0xb3, 0x1c, 0x1a, 0x43, 0x36, 0x1d, 0xd2, 0x76, 0x28, - 0x27, 0xe0, 0xd3, 0x19, 0x56, 0xd3, 0x52, 0xb2, 0xa0, 0x9c, 0xda, 0xb7, - 0xac, 0x4d, 0xb1, 0x98, 0x22, 0xa5, 0x86, 0x5d, 0x79, 0x6a, 0x69, 0x06, - 0xd7, 0x07, 0xe7, 0x44, 0x55, 0x6c, 0xc7, 0xd0, 0x8a, 0x2b, 0xa1, 0x45, - 0xc6, 0xbf, 0xf3, 0x21, 0x2e, 0x41, 0x5c, 0x84, 0xa2, 0x77, 0x46, 0x65, - 0x80, 0x75, 0xba, 0x49, 0xd6, 0xd7, 0x73, 0xeb, 0x35, 0x2c, 0x46, 0x58, - 0xc4, 0x1d, 0x2f, 0x6b, 0xe6, 0x6c, 0xa7, 0x5f, 0x95, 0x0c, 0xbc, 0x60, - 0x00, 0x3d, 0xa9, 0x0a, 0xd6, 0x0a, 0x66, 0x59, 0xc0, 0x9b, 0x49, 0x5b, - 0x4c, 0x73, 0xf5, 0x9e, 0x6d, 0x38, 0xdd, 0x0f, 0x25, 0xe4, 0x35, 0x84, - 0x34, 0x25, 0xfe, 0x71, 0x35, 0x78, 0xa7, 0x5b, 0xc1, 0x7a, 0xab, 0xd7, - 0xeb, 0x2f, 0x54, 0x93, 0x94, 0x49, 0x8a, 0x1e, 0x04, 0xe6, 0xfc, 0xd7, - 0xe3, 0xa2, 0x41, 0x25, 0x5a, 0xa5, 0x46, 0x59, 0x85, 0xfb, 0x21, 0xc7, - 0x02, 0x48, 0x79, 0xd4, 0xef, 0xc4, 0x03, 0xc2, 0x0a, 0x4b, 0x42, 0x1c, - 0x73, 0x35, 0xcd, 0x21, 0x8b, 0xd5, 0xfc, 0xa3, 0xdc, 0xbb, 0x4b, 0xa3, - 0x45, 0x04, 0x73, 0xa1, 0xdb, 0x3a, 0x97, 0x0e, 0xc7, 0x1c, 0xe2, 0x67, - 0x04, 0xd4, 0x49, 0x68, 0x0e, 0x05, 0xcb, 0x52, 0xd4, 0x37, 0x75, 0xd8, - 0x2a, 0x17, 0xd3, 0x7a, 0x93, 0x96, 0x46, 0xfb, 0x07, 0x6d, 0x3b, 0x92, - 0x60, 0xf4, 0x35, 0x94, 0x3b, 0xbd, 0x2e, 0xf6, 0x0b, 0x18, 0xd5, 0x0d, - 0x1b, 0xe1, 0xd3, 0x14, 0xc1, 0x84, 0xd7, 0x67, 0xd7, 0x96, 0x2d, 0xa9, - 0xab, 0x59, 0x70, 0x43, 0x7b, 0xea, 0x25, 0xa3, 0x05, 0x1c, 0x45, 0xf6, - 0x34, 0x51, 0x8e, 0xaf, 0x46, 0x33, 0x90, 0x68, 0x28, 0x4f, 0x38, 0x5b, - 0xbb, 0x69, 0xee, 0xbb, 0x0a, 0x4c, 0x76, 0x1c, 0x3d, 0xfd, 0xea, 0x1f, - 0x77, 0x9e, 0xd4, 0xa1, 0xeb, 0x74, 0x16, 0x60, 0x20, 0xe9, 0x44, 0xc1, - 0x90, 0x2c, 0x7b, 0x77, 0x6f, 0x70, 0xe3, 0x62, 0x0f, 0xc3, 0x20, 0xf6, - 0xce, 0xc3, 0xa6, 0x0e, 0x9c, 0x6d, 0xa3, 0xa0, 0x21, 0x1c, 0x28, 0x7f, - 0x44, 0xd7, 0xa9, 0x87, 0x62, 0x91, 0x4d, 0x2a, 0x93, 0xe2, 0xc7, 0x94, - 0x0c, 0x75, 0x1d, 0xf6, 0xc7, 0xf8, 0x36, 0x09, 0xa8, 0x23, 0xa3, 0x80, - 0x52, 0x2d, 0xe7, 0x0b, 0x44, 0x5d, 0x4b, 0xf5, 0xdc, 0x57, 0xa3, 0x02, - 0x40, 0x89, 0xdc, 0x40, 0xf7, 0x5c, 0xad, 0xea, 0x5c, 0x1a, 0x59, 0xfc, - 0xb8, 0xaf, 0xcb, 0x71, 0xe0, 0x08, 0xdc, 0x80, 0x08, 0x8a, 0x32, 0x85, - 0x46, 0xa9, 0x9a, 0x17, 0x6b, 0x25, 0x9c, 0xfe, 0x7d, 0x90, 0x22, 0x6e, - 0x7b, 0x01, 0x24, 0x17, 0xf6, 0xa7, 0x70, 0x93, 0x03, 0x60, 0xc2, 0x0d, - 0x7b, 0x3b, 0xe8, 0x5b, 0x02, 0xb0, 0x6d, 0x00, 0x62, 0x97, 0x1b, 0x84, - 0x86, 0x27, 0x72, 0x2d, 0x90, 0xee, 0xdc, 0xb6, 0xb8, 0xa5, 0x58, 0x73, - 0x29, 0x9b, 0x06, 0x99, 0xda, 0x4f, 0x12, 0x0c, 0x74, 0x0a, 0xc1, 0x1b, - 0x34, 0x20, 0xfa, 0x6d, 0x01, 0xd2, 0x1b, 0xf2, 0x0f, 0xe3, 0xfe, 0x34, - 0x2d, 0x44, 0x4f, 0xa3, 0x6a, 0xab, 0xaa, 0x7e, 0x1c, 0x35, 0xef, 0xfe, - 0xa0, 0xc1, 0x8a, 0xeb, 0x77, 0x80, 0xd6, 0x57, 0x20, 0x2e, 0x2b, 0xeb, - 0x67, 0xa0, 0x82, 0x86, 0xc8, 0x0e, 0x70, 0x76, 0x74, 0x52, 0x3e, 0x67, - 0x96, 0xf0, 0x48, 0x3f, 0x9b, 0xdc, 0x5f, 0x36, 0xd9, 0xae, 0x3a, 0xcb, - 0x57, 0x5d, 0xe0, 0x7c, 0x03, 0xa9, 0xe8, 0x88, 0x13, 0x6a, 0x70, 0x94, - 0x4b, 0xf5, 0x92, 0x8f, 0xc0, 0x34, 0x49, 0x3f, 0xf7, 0xe1, 0x59, 0xc4, - 0xf2, 0xae, 0x7a, 0x88, 0x58, 0x39, 0x74, 0x39, 0x6d, 0xaf, 0x7a, 0xec, - 0xaf, 0x44, 0x0e, 0x11, 0x7d, 0xa8, 0x3c, 0x50, 0x5b, 0x64, 0x8d, 0x8a, - 0x21, 0x59, 0xc6, 0x8c, 0x6c, 0xce, 0x05, 0xad, 0x1c, 0x2f, 0x5e, 0x4a, - 0xa3, 0x2a, 0x46, 0x3a, 0xaa, 0x12, 0x7e, 0xcc, 0x82, 0xb6, 0x62, 0xba, - 0xe6, 0x1a, 0x52, 0xc6, 0xe3, 0x96, 0x71, 0xf6, 0x81, 0x21, 0x46, 0xd0, - 0x3f, 0x5d, 0xa1, 0x37, 0x8b, 0xf5, 0xc7, 0x8c, 0x28, 0xf0, 0x2e, 0xe8, - 0x44, 0x25, 0x48, 0x27, 0x8e, 0x2f, 0x65, 0x83, 0xed, 0xf5, 0xb6, 0x9f, - 0x02, 0xa7, 0x1b, 0x1e, 0x90, 0x01, 0x55, 0x88, 0xe5, 0xdf, 0x0e, 0x7e, - 0x16, 0x66, 0xa1, 0xc6, 0x07, 0xf6, 0xb5, 0x84, 0x8d, 0x60, 0x6b, 0xe2, - 0xad, 0xbd, 0x18, 0x39, 0xe5, 0xd2, 0xd9, 0xe0, 0xab, 0xc2, 0xac, 0x2f, - 0x36, 0x24, 0x03, 0x69, 0x4c, 0xf9, 0xf3, 0x67, 0x8f, 0xf6, 0x8b, 0xde, - 0xf9, 0x7c, 0x14, 0xfa, 0x97, 0xc3, 0xe5, 0xc1, 0x7d, 0xcf, 0x16, 0x24, - 0x26, 0xda, 0xde, 0x5c, 0x70, 0x96, 0x90, 0xd9, 0x06, 0x2f, 0xf9, 0x61, - 0xa3, 0x47, 0x19, 0x50, 0x5e, 0xe2, 0xb6, 0x74, 0x5e, 0x55, 0xe6, 0x89, - 0xaa, 0xde, 0x19, 0x27, 0x26, 0x47, 0x95, 0x7b, 0xf0, 0x09, 0x21, 0xa9, - 0xf3, 0xf2, 0xf0, 0xbc, 0x1a, 0xa2, 0x25, 0x77, 0x3f, 0x8a, 0x57, 0x20, - 0xfc, 0x48, 0x45, 0xd8, 0x8b, 0xcb, 0x33, 0x04, 0x10, 0x1d, 0xc6, 0x4b, - 0x4c, 0xe4, 0x92, 0x1f, 0xef, 0x27, 0x5e, 0xd5, 0xac, 0xab, 0xcc, 0x69, - 0xbe, 0xd6, 0x35, 0x0e, 0x0d, 0x96, 0x99, 0x3b, 0x67, 0x8d, 0x33, 0xa0, - 0xe3, 0x16, 0xcc, 0x4a, 0x29, 0x80, 0xc8, 0x47, 0xd1, 0x0c, 0xb1, 0xa0, - 0xc1, 0xbe, 0xcc, 0x16, 0xab, 0xf7, 0xee, 0x8a, 0x77, 0xef, 0xca, 0x08, - 0x82, 0x0a, 0x9e, 0x11, 0xcf, 0x3c, 0xbb, 0x1b, 0x44, 0x96, 0xd1, 0x5e, - 0x65, 0xf9, 0xe7, 0xc7, 0xa1, 0x94, 0x42, 0xa9, 0x0e, 0x36, 0x9a, 0x5b, - 0x7f, 0xf0, 0x91, 0x95, 0xeb, 0xd1, 0xb6, 0x1d, 0x18, 0x44, 0x93, 0xa4, - 0xc1, 0x31, 0x97, 0x07, 0x09, 0x9b, 0x50, 0xae, 0xf3, 0x74, 0x7f, 0xbe, - 0x0d, 0xc2, 0xc3, 0x11, 0x8f, 0xa1, 0xea, 0x1f, 0x4e, 0x84, 0x94, 0x18, - 0x7e, 0x7c, 0xbd, 0xe6, 0xc9, 0x78, 0x0e, 0x39, 0x1e, 0x1a, 0x71, 0xc4, - 0xbc, 0x5c, 0x99, 0x76, 0xf7, 0x26, 0x66, 0x9c, 0x8f, 0xd4, 0xad, 0xa9, - 0x6e, 0x96, 0xb9, 0x54, 0x5b, 0xae, 0xa2, 0x0d, 0x94, 0xa8, 0x5a, 0x34, - 0xc3, 0xdb, 0x52, 0x59, 0x3f, 0xdd, 0x53, 0x72, 0xfc, 0xf6, 0x1d, 0x3c, - 0xe0, 0x1f, 0x4a, 0xee, 0xf5, 0x74, 0xa5, 0x95, 0x7a, 0x5d, 0x75, 0xbd, - 0x27, 0x4a, 0x49, 0x18, 0xcf, 0xf0, 0xe5, 0x32, 0x4f, 0x1b, 0xa0, 0xeb, - 0x00, 0x19, 0x21, 0xbd, 0xf7, 0xf5, 0x4b, 0x47, 0x1d, 0x3b, 0x8b, 0xe6, - 0xca, 0xdc, 0xb6, 0x52, 0x41, 0xa7, 0xab, 0x68, 0xb3, 0xfb, 0x8f, 0x40, - 0xc3, 0x59, 0xd9, 0x2d, 0x13, 0x3a, 0x99, 0x93, 0x9f, 0xa6, 0x90, 0xdd, - 0x65, 0x17, 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x2d, 0x69, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x00, 0x00, 0x00, 0x1d, 0x04, - 0x0a, 0x00, 0x00, 0x00, 0x06, 0x0e, 0x6a, 0x00, 0x0f, 0x2a, 0x0e, 0xaa, - 0x0f, 0x6a, 0x0f, 0xb3, 0x0e, 0xea, 0x0e, 0x6a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x0c, 0x09, 0x34, 0x34, 0x08, - 0x01, 0x02, 0x02, 0x08, 0x08, 0x17, 0x01, 0xfc, 0x9b, 0xff, 0x1a, 0xfd, - 0x18, 0x88, 0xb2, 0x23, 0xc4, 0x27, 0xcd, 0xff, 0x6d, 0xed, 0x99, 0xdb, - 0x40, 0x1d, 0x5c, 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, - 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0x2a, - 0x05, 0x00, 0x05, 0x00, 0x69, 0x63, 0x68, 0x61, 0x74, 0x06, 0x3f, 0x0c, - 0x08, 0x34, 0x34, 0x08, 0x01, 0x02, 0x02, 0x08, 0x08, 0x17, 0x01, 0xfc, - 0x9b, 0xff, 0x1a, 0xfd, 0x18, 0x88, 0xb2, 0x23, 0xc4, 0x27, 0xcd, 0xff, - 0x6d, 0xed, 0x99, 0xdb, 0x40, 0x1d, 0x5c, 0xda, 0x39, 0xa3, 0xee, 0x5e, - 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, - 0xd8, 0x07, 0x09, 0x2a, 0x05, 0x00, 0x05, 0x00, 0x69, 0x63, 0x68, 0x61, - 0x74, 0x05, 0x3f, 0x0c, 0x09, 0x34, 0x34, 0x08, 0x01, 0x02, 0x02, 0x08, - 0x08, 0x17, 0x01, 0x9b, 0x66, 0x83, 0xaf, 0x24, 0x40, 0x8e, 0xa7, 0xd6, - 0x76, 0x12, 0x4a, 0x40, 0x61, 0xb5, 0x6a, 0xbc, 0x33, 0xef, 0x01, 0xda, - 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, - 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0x2b, 0x01, 0x00, 0x01, 0x00, - 0x69, 0x63, 0x68, 0x61, 0x74, 0x04, 0x3f, 0x0c, 0x08, 0x34, 0x34, 0x08, - 0x01, 0x02, 0x02, 0x08, 0x08, 0x17, 0x01, 0x9b, 0x66, 0x83, 0xaf, 0x24, - 0x40, 0x8e, 0xa7, 0xd6, 0x76, 0x12, 0x4a, 0x40, 0x61, 0xb5, 0x6a, 0xbc, - 0x33, 0xef, 0x01, 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, - 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0x2b, - 0x01, 0x00, 0x01, 0x00, 0x69, 0x63, 0x68, 0x61, 0x74, 0x03, 0x48, 0x0c, - 0x09, 0x34, 0x34, 0x08, 0x01, 0x02, 0x02, 0x08, 0x08, 0x29, 0x01, 0x64, - 0x14, 0x5e, 0x86, 0xb3, 0x7b, 0x2d, 0x6c, 0xa9, 0xc0, 0xcf, 0xd8, 0x43, - 0x7e, 0x59, 0x45, 0xac, 0xff, 0x92, 0x4b, 0xda, 0x39, 0xa3, 0xee, 0x5e, - 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, - 0xd8, 0x07, 0x09, 0x2a, 0x04, 0x00, 0x04, 0x00, 0x63, 0x6f, 0x6d, 0x2e, - 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x73, 0x64, 0x02, 0x4c, - 0x0c, 0x09, 0x34, 0x34, 0x08, 0x01, 0x02, 0x02, 0x08, 0x08, 0x33, 0x09, - 0x64, 0x14, 0x5e, 0x86, 0xb3, 0x7b, 0x2d, 0x6c, 0xa9, 0xc0, 0xcf, 0xd8, - 0x43, 0x7e, 0x59, 0x45, 0xac, 0xff, 0x92, 0x4b, 0xda, 0x39, 0xa3, 0xee, - 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, - 0xaf, 0xd8, 0x07, 0x09, 0x2a, 0x04, 0x00, 0x04, 0x00, 0x6c, 0x6f, 0x63, - 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x2d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x69, 0x65, 0x73, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x0f, 0xfb, 0x00, - 0x0f, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 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, 0x01, 0x02, 0x01, 0x05, 0x0a, 0x00, 0x00, 0x00, - 0x02, 0x0f, 0xf7, 0x00, 0x0f, 0xfc, 0x0f, 0xf7, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x01, 0x02, 0x03, 0x03, 0x00, 0x09, - 0x0a, 0x00, 0x00, 0x00, 0x02, 0x0f, 0xcf, 0x00, 0x0f, 0xe8, 0x0f, 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, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x03, 0x34, 0x01, 0x7e, 0x0b, 0xaa, 0xec, 0xd2, - 0x3c, 0x92, 0x58, 0xd7, 0xfd, 0x92, 0x3c, 0xf8, 0x03, 0x3e, 0x70, 0x20, - 0x84, 0xa7, 0x17, 0x02, 0x17, 0x03, 0x34, 0x09, 0x7e, 0x0b, 0xaa, 0xec, - 0xd2, 0x3c, 0x92, 0x58, 0xd7, 0xfd, 0x92, 0x3c, 0xf8, 0x03, 0x3e, 0x70, - 0x20, 0x84, 0xa7, 0x17, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x0f, 0xcf, 0x00, - 0x0f, 0xe8, 0x0f, 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, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x03, 0x34, 0x01, 0xda, - 0xde, 0x08, 0x82, 0x7d, 0xfa, 0x5c, 0xf3, 0x42, 0xb1, 0x04, 0x84, 0xf4, - 0xba, 0xe3, 0x73, 0xe9, 0x35, 0x6f, 0xbb, 0x02, 0x17, 0x03, 0x34, 0x09, - 0xda, 0xde, 0x08, 0x82, 0x7d, 0xfa, 0x5c, 0xf3, 0x42, 0xb1, 0x04, 0x84, - 0xf4, 0xba, 0xe3, 0x73, 0xe9, 0x35, 0x6f, 0xbb, 0x0a, 0x00, 0x00, 0x00, - 0x02, 0x0f, 0xcf, 0x00, 0x0f, 0xe8, 0x0f, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x03, 0x34, 0x01, 0x64, 0x14, 0x5e, 0x86, 0xb3, 0x7b, 0x2d, 0x6c, 0xa9, - 0xc0, 0xcf, 0xd8, 0x43, 0x7e, 0x59, 0x45, 0xac, 0xff, 0x92, 0x4b, 0x02, - 0x17, 0x03, 0x34, 0x09, 0x64, 0x14, 0x5e, 0x86, 0xb3, 0x7b, 0x2d, 0x6c, - 0xa9, 0xc0, 0xcf, 0xd8, 0x43, 0x7e, 0x59, 0x45, 0xac, 0xff, 0x92, 0x4b, - 0x0a, 0x00, 0x00, 0x00, 0x06, 0x0f, 0xe3, 0x00, 0x0f, 0xf2, 0x0f, 0xe8, - 0x0f, 0xfc, 0x0f, 0xf7, 0x0f, 0xed, 0x0f, 0xe3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x09, 0x01, 0x06, 0x04, 0x03, 0x08, 0x01, 0x05, 0x04, 0x03, 0x09, - 0x01, 0x04, 0x04, 0x03, 0x08, 0x01, 0x03, 0x04, 0x03, 0x09, 0x01, 0x02, - 0x03, 0x03, 0x09, 0x09, 0x0a, 0x00, 0x00, 0x00, 0x06, 0x0f, 0x6b, 0x00, - 0x0f, 0xe8, 0x0f, 0xcf, 0x0f, 0xb6, 0x0f, 0x9d, 0x0f, 0x84, 0x0f, 0x6b, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x03, 0x34, 0x01, 0xfc, 0x9b, 0xff, 0x1a, 0xfd, - 0x18, 0x88, 0xb2, 0x23, 0xc4, 0x27, 0xcd, 0xff, 0x6d, 0xed, 0x99, 0xdb, - 0x40, 0x1d, 0x5c, 0x06, 0x18, 0x03, 0x34, 0x01, 0xfc, 0x9b, 0xff, 0x1a, - 0xfd, 0x18, 0x88, 0xb2, 0x23, 0xc4, 0x27, 0xcd, 0xff, 0x6d, 0xed, 0x99, - 0xdb, 0x40, 0x1d, 0x5c, 0x05, 0x18, 0x03, 0x34, 0x01, 0x9b, 0x66, 0x83, - 0xaf, 0x24, 0x40, 0x8e, 0xa7, 0xd6, 0x76, 0x12, 0x4a, 0x40, 0x61, 0xb5, - 0x6a, 0xbc, 0x33, 0xef, 0x01, 0x04, 0x18, 0x03, 0x34, 0x01, 0x9b, 0x66, - 0x83, 0xaf, 0x24, 0x40, 0x8e, 0xa7, 0xd6, 0x76, 0x12, 0x4a, 0x40, 0x61, - 0xb5, 0x6a, 0xbc, 0x33, 0xef, 0x01, 0x03, 0x18, 0x03, 0x34, 0x01, 0x64, - 0x14, 0x5e, 0x86, 0xb3, 0x7b, 0x2d, 0x6c, 0xa9, 0xc0, 0xcf, 0xd8, 0x43, - 0x7e, 0x59, 0x45, 0xac, 0xff, 0x92, 0x4b, 0x02, 0x17, 0x03, 0x34, 0x09, - 0x64, 0x14, 0x5e, 0x86, 0xb3, 0x7b, 0x2d, 0x6c, 0xa9, 0xc0, 0xcf, 0xd8, - 0x43, 0x7e, 0x59, 0x45, 0xac, 0xff, 0x92, 0x4b, 0x0a, 0x00, 0x00, 0x00, - 0x06, 0x0f, 0xe3, 0x00, 0x0f, 0xfc, 0x0f, 0xf7, 0x0f, 0xf2, 0x0f, 0xed, - 0x0f, 0xe8, 0x0f, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x08, 0x01, 0x06, - 0x04, 0x03, 0x08, 0x01, 0x05, 0x04, 0x03, 0x08, 0x01, 0x04, 0x04, 0x03, - 0x08, 0x01, 0x03, 0x04, 0x03, 0x08, 0x01, 0x02, 0x03, 0x03, 0x08, 0x09, - 0x0a, 0x00, 0x00, 0x00, 0x06, 0x0f, 0xe3, 0x00, 0x0f, 0xfc, 0x0f, 0xf7, - 0x0f, 0xf2, 0x0f, 0xed, 0x0f, 0xe8, 0x0f, 0xe3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x09, 0x01, 0x06, 0x04, 0x03, 0x09, 0x01, 0x05, 0x04, 0x03, 0x09, - 0x01, 0x04, 0x04, 0x03, 0x09, 0x01, 0x03, 0x04, 0x03, 0x09, 0x01, 0x02, - 0x03, 0x03, 0x09, 0x09, 0x0a, 0x00, 0x00, 0x00, 0x06, 0x0f, 0xe3, 0x00, - 0x0f, 0xfc, 0x0f, 0xf7, 0x0f, 0xf2, 0x0f, 0xed, 0x0f, 0xe8, 0x0f, 0xe3, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x09, 0x01, 0x06, 0x04, 0x03, 0x09, 0x01, - 0x05, 0x04, 0x03, 0x09, 0x01, 0x04, 0x04, 0x03, 0x09, 0x01, 0x03, 0x04, - 0x03, 0x09, 0x01, 0x02, 0x03, 0x03, 0x09, 0x09, 0x0a, 0x00, 0x00, 0x00, - 0x06, 0x0f, 0xe3, 0x00, 0x0f, 0xfc, 0x0f, 0xf7, 0x0f, 0xf2, 0x0f, 0xed, - 0x0f, 0xe8, 0x0f, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x09, 0x01, 0x06, - 0x04, 0x03, 0x09, 0x01, 0x05, 0x04, 0x03, 0x09, 0x01, 0x04, 0x04, 0x03, - 0x09, 0x01, 0x03, 0x04, 0x03, 0x09, 0x01, 0x02, 0x03, 0x03, 0x09, 0x09, - 0x0a, 0x00, 0x00, 0x00, 0x06, 0x0f, 0xe3, 0x00, 0x0f, 0xfc, 0x0f, 0xf7, - 0x0f, 0xf2, 0x0f, 0xed, 0x0f, 0xe8, 0x0f, 0xe3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x08, 0x01, 0x06, 0x04, 0x03, 0x08, 0x01, 0x05, 0x04, 0x03, 0x08, - 0x01, 0x04, 0x04, 0x03, 0x08, 0x01, 0x03, 0x04, 0x03, 0x08, 0x01, 0x02, - 0x03, 0x03, 0x08, 0x09, 0x0a, 0x00, 0x00, 0x00, 0x06, 0x0f, 0xe3, 0x00, - 0x0f, 0xfc, 0x0f, 0xf7, 0x0f, 0xf2, 0x0f, 0xed, 0x0f, 0xe8, 0x0f, 0xe3, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x08, 0x01, 0x06, 0x04, 0x03, 0x08, 0x01, - 0x05, 0x04, 0x03, 0x08, 0x01, 0x04, 0x04, 0x03, 0x08, 0x01, 0x03, 0x04, - 0x03, 0x08, 0x01, 0x02, 0x03, 0x03, 0x08, 0x09, 0x0a, 0x00, 0x00, 0x00, - 0x06, 0x0f, 0xe3, 0x00, 0x0f, 0xfc, 0x0f, 0xf7, 0x0f, 0xf2, 0x0f, 0xed, - 0x0f, 0xe8, 0x0f, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x09, 0x01, 0x06, - 0x04, 0x03, 0x09, 0x01, 0x05, 0x04, 0x03, 0x09, 0x01, 0x04, 0x04, 0x03, - 0x09, 0x01, 0x03, 0x04, 0x03, 0x09, 0x01, 0x02, 0x03, 0x03, 0x09, 0x09, - 0x0d, 0x00, 0x00, 0x00, 0x05, 0x05, 0x88, 0x00, 0x05, 0x88, 0x07, 0xca, - 0x0a, 0x10, 0x0b, 0x9e, 0x0d, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x55, 0x07, 0x16, 0x00, 0x07, 0x07, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, - 0x34, 0x00, 0x88, 0x0a, 0x17, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x7e, 0xdf, - 0xaa, 0x7a, 0x41, 0xb7, 0x59, 0x5c, 0x7e, 0xdf, 0xaa, 0x7a, 0x0b, 0x66, - 0x7c, 0x18, 0x9e, 0x44, 0x49, 0x2d, 0x40, 0x62, 0x95, 0x22, 0xa7, 0xe3, - 0x08, 0x19, 0x26, 0x0f, 0xd6, 0x6d, 0x3a, 0xdc, 0x09, 0xb3, 0xcd, 0x3d, - 0x7c, 0x47, 0x10, 0xf5, 0x62, 0xa0, 0x5b, 0xd8, 0x50, 0xe7, 0x56, 0xcb, - 0xa1, 0xb8, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, - 0x00, 0x00, 0x64, 0x0f, 0xc5, 0x21, 0x02, 0x15, 0x7c, 0xa5, 0xb2, 0x07, - 0xf2, 0xee, 0xe7, 0xeb, 0x55, 0xb1, 0x73, 0x0b, 0xc7, 0x85, 0xd2, 0x16, - 0x2f, 0x68, 0x13, 0x3e, 0x6a, 0x6b, 0x3a, 0x3d, 0xbd, 0x3d, 0xd9, 0xc4, - 0x98, 0x92, 0xea, 0x5a, 0xf1, 0xf3, 0x69, 0x0e, 0x20, 0x7b, 0x97, 0xca, - 0xe6, 0x21, 0x45, 0x98, 0xcf, 0x92, 0x04, 0xf5, 0xc9, 0x46, 0x27, 0xd4, - 0x4f, 0x83, 0x2c, 0x3b, 0xbb, 0x83, 0x22, 0xa3, 0x3c, 0x4e, 0x8e, 0x37, - 0x6e, 0xe1, 0x6f, 0x80, 0x83, 0x0f, 0x19, 0xed, 0x17, 0xdb, 0xd1, 0x96, - 0xb9, 0x33, 0xe6, 0x25, 0x50, 0x4f, 0x40, 0x36, 0xbf, 0x42, 0x46, 0xfc, - 0x1c, 0x4a, 0x84, 0x9a, 0xb5, 0xcb, 0xe1, 0xee, 0x4c, 0x84, 0xde, 0x41, - 0x9f, 0x69, 0x3d, 0x9c, 0xe5, 0x38, 0x68, 0xb1, 0x9c, 0x59, 0xd6, 0xcf, - 0xcd, 0x76, 0xc3, 0xa7, 0x99, 0xf2, 0xe5, 0x8d, 0x3b, 0x02, 0xcc, 0x1a, - 0xed, 0x52, 0xd6, 0xef, 0x8f, 0xb2, 0xba, 0x11, 0x39, 0xa5, 0x82, 0x12, - 0x04, 0x2b, 0x03, 0xda, 0x41, 0x8c, 0x9e, 0xe1, 0xc0, 0x8d, 0xdb, 0xff, - 0x46, 0xce, 0xa9, 0xf3, 0x70, 0xf0, 0x5a, 0xd9, 0x5e, 0xc1, 0xa3, 0xca, - 0xd4, 0x02, 0x2a, 0xce, 0x49, 0x55, 0x61, 0x5d, 0x22, 0xbf, 0xf6, 0x5a, - 0xe6, 0xe4, 0xb4, 0x7a, 0xe2, 0x47, 0x24, 0x72, 0xba, 0x8b, 0xd2, 0x39, - 0x49, 0xf2, 0xa0, 0xda, 0xe6, 0xb6, 0xe1, 0x79, 0xdc, 0x0d, 0x73, 0x1b, - 0xe6, 0x40, 0xe4, 0xda, 0x74, 0x7c, 0xa4, 0x81, 0x4b, 0x79, 0x8c, 0x23, - 0x8d, 0xd5, 0x9d, 0xe0, 0x01, 0xe2, 0x88, 0xa8, 0x3f, 0x09, 0xec, 0xf3, - 0xa8, 0xd5, 0x8b, 0xe2, 0xef, 0x0e, 0x0c, 0x42, 0x37, 0xc0, 0x2a, 0x7d, - 0x25, 0x56, 0xc4, 0x28, 0xc3, 0x70, 0x73, 0xe7, 0x14, 0xd0, 0xa8, 0x1e, - 0x2a, 0xd7, 0xd6, 0x85, 0x0f, 0x4b, 0x94, 0x8d, 0xa3, 0xb2, 0xee, 0x83, - 0x36, 0x0a, 0x59, 0x4b, 0x8a, 0xc3, 0xf8, 0xd1, 0x64, 0xb4, 0x07, 0x7c, - 0x3d, 0x98, 0xaf, 0x7c, 0xd2, 0xed, 0x2a, 0xa2, 0x91, 0xf4, 0x32, 0xa8, - 0xf1, 0x67, 0x0a, 0x34, 0x75, 0x88, 0x4e, 0x69, 0x78, 0xca, 0xa4, 0x0c, - 0x84, 0x3f, 0x01, 0x16, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x34, 0x00, 0x87, 0x5e, 0x17, - 0x13, 0x41, 0xb7, 0x59, 0x50, 0xd8, 0x33, 0x2b, 0x24, 0x41, 0xb7, 0x59, - 0x50, 0xd8, 0x33, 0x2b, 0x24, 0x83, 0xad, 0xb6, 0xae, 0x9f, 0x27, 0xa5, - 0x45, 0x30, 0xb3, 0x67, 0xc8, 0x32, 0x58, 0x95, 0x85, 0x06, 0xeb, 0xc1, - 0xf4, 0x06, 0x98, 0x7e, 0x8b, 0x09, 0xd8, 0x2e, 0xbe, 0x8c, 0x6b, 0x51, - 0x5c, 0x08, 0x13, 0x58, 0xb4, 0x2e, 0x41, 0xcb, 0x34, 0x02, 0x00, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x99, 0xb4, 0x79, - 0xc1, 0x37, 0xc1, 0xe1, 0x5c, 0x49, 0xa0, 0xe1, 0xf3, 0x17, 0xb8, 0x9c, - 0x69, 0xe6, 0xba, 0xdc, 0xe7, 0x78, 0xb2, 0x5d, 0xd6, 0x95, 0xbe, 0xb2, - 0xda, 0x91, 0xd3, 0x9b, 0xf2, 0xd4, 0xe3, 0x95, 0x3c, 0x53, 0x8d, 0x0e, - 0x68, 0xe9, 0x02, 0xb3, 0xed, 0xeb, 0x95, 0xdd, 0x11, 0xb2, 0x64, 0x69, - 0x8a, 0xfe, 0x03, 0x05, 0xd5, 0x04, 0x9b, 0xac, 0x8a, 0xb6, 0x98, 0x29, - 0x56, 0x2e, 0xd3, 0xea, 0x4e, 0x84, 0xee, 0x23, 0x44, 0x03, 0x12, 0x9d, - 0x9c, 0x9c, 0x9f, 0x11, 0x62, 0xf0, 0x86, 0x36, 0x52, 0x15, 0x0f, 0x27, - 0x93, 0xdb, 0xde, 0x13, 0xc9, 0x94, 0x93, 0xe4, 0xa4, 0x6f, 0x58, 0x9d, - 0x58, 0x9f, 0x15, 0xba, 0x5f, 0x4c, 0xf3, 0x9a, 0x90, 0xc0, 0xcb, 0x60, - 0xce, 0x9b, 0x56, 0x0c, 0xfe, 0x5b, 0xd2, 0x4e, 0x0e, 0x82, 0xe6, 0x4c, - 0x62, 0x57, 0x08, 0x6e, 0x5d, 0x54, 0x7b, 0x28, 0xbb, 0x88, 0xdc, 0xec, - 0xaa, 0xd1, 0x6e, 0xd3, 0x94, 0x20, 0x3e, 0x35, 0x81, 0x52, 0xf6, 0xe9, - 0xee, 0x42, 0x89, 0xe9, 0xea, 0x61, 0x2c, 0xd8, 0xdc, 0xe3, 0x82, 0xf7, - 0xf0, 0xc0, 0xf6, 0xf9, 0xb7, 0xef, 0x49, 0xc7, 0x8d, 0x6c, 0x8a, 0x6d, - 0x6e, 0xbc, 0x2d, 0xc0, 0xb1, 0xec, 0x0c, 0xdd, 0xe5, 0xbe, 0x65, 0x3f, - 0x69, 0x81, 0xcf, 0xe8, 0xd8, 0xf3, 0x57, 0x8e, 0xba, 0x73, 0x7f, 0xb0, - 0x4e, 0x65, 0xa2, 0xa5, 0xa5, 0xbb, 0x7b, 0xae, 0xaa, 0x88, 0x06, 0x4f, - 0x2c, 0x43, 0xb9, 0x4c, 0x17, 0xa1, 0x24, 0xfb, 0xe1, 0x90, 0x50, 0xdb, - 0xcc, 0xd9, 0xe5, 0x7b, 0x09, 0xaf, 0x5c, 0x5a, 0x4f, 0xb2, 0x2b, 0x30, - 0x53, 0x0f, 0xd3, 0xe2, 0xbd, 0xcd, 0xf7, 0xa3, 0x19, 0xdc, 0xba, 0xee, - 0xd1, 0x49, 0xbc, 0xa6, 0xde, 0x1b, 0xe6, 0xd3, 0xaf, 0xdd, 0x61, 0xf6, - 0xfd, 0xef, 0xb7, 0xda, 0x9d, 0x93, 0x45, 0x0a, 0xa2, 0xa8, 0x1a, 0xe5, - 0x16, 0xb1, 0xaf, 0x20, 0x00, 0x86, 0x6b, 0x66, 0x42, 0x97, 0x4e, 0x3a, - 0xea, 0x0d, 0x33, 0xb2, 0x93, 0x87, 0x9c, 0xd1, 0x6a, 0x20, 0xbc, 0xc9, - 0x7d, 0x46, 0xb9, 0x0a, 0x26, 0x9a, 0x09, 0x81, 0xc8, 0x6d, 0x9b, 0x63, - 0xa5, 0x1f, 0x63, 0x72, 0x6c, 0xa8, 0x65, 0x65, 0xa2, 0x8a, 0x81, 0x4d, - 0x54, 0xd4, 0xa3, 0xc4, 0x86, 0x48, 0x31, 0x5c, 0x4e, 0x15, 0xf3, 0x48, - 0x30, 0xbc, 0x17, 0xac, 0x0b, 0x85, 0x8f, 0x44, 0x62, 0xf4, 0x57, 0xc7, - 0xbd, 0x18, 0xcf, 0xf5, 0xd8, 0xa9, 0x2d, 0xf5, 0x57, 0xaf, 0x42, 0x09, - 0xf7, 0x5b, 0x25, 0x56, 0xa1, 0x04, 0x0c, 0xf7, 0xa7, 0xc9, 0x2d, 0xd7, - 0x84, 0x78, 0x86, 0x82, 0x2d, 0xd3, 0xaa, 0xd2, 0xbf, 0x77, 0xc0, 0x34, - 0x7b, 0xdb, 0x7e, 0x4d, 0xde, 0x63, 0x8f, 0xcc, 0xb6, 0x6d, 0x01, 0x80, - 0x68, 0x51, 0x3e, 0x8f, 0x2a, 0x7c, 0x0e, 0xaa, 0xc2, 0xbf, 0x77, 0x12, - 0x06, 0x88, 0xdf, 0x3f, 0x6c, 0x7d, 0x69, 0x05, 0x57, 0x71, 0xeb, 0xe7, - 0xf3, 0xcb, 0x32, 0x4d, 0x33, 0x54, 0x8a, 0x2a, 0x1b, 0xb5, 0x6e, 0xb6, - 0xa4, 0x64, 0xcd, 0x34, 0x5c, 0xa9, 0x3d, 0x92, 0xc8, 0x38, 0xbb, 0x84, - 0xed, 0xde, 0xe4, 0xa2, 0xe1, 0x68, 0x2f, 0xcb, 0x4b, 0x3c, 0x76, 0xb2, - 0x3b, 0x84, 0x5f, 0x6b, 0x46, 0x72, 0x2f, 0x7f, 0xf0, 0x6f, 0x6b, 0x7b, - 0xd3, 0xc5, 0x4b, 0x20, 0x2b, 0xae, 0x48, 0x7e, 0xcb, 0x22, 0x38, 0x44, - 0x1f, 0x43, 0x1c, 0x55, 0x85, 0xe0, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x64, - 0x6b, 0x75, 0x84, 0x43, 0x02, 0x16, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x34, 0x00, 0x87, - 0x66, 0x17, 0x13, 0x41, 0xb7, 0x59, 0x50, 0xd8, 0x37, 0x6c, 0x27, 0x41, - 0xb7, 0x59, 0x50, 0xd8, 0x37, 0x6c, 0x27, 0x77, 0xac, 0x86, 0x8b, 0xf9, - 0xb8, 0xa0, 0x50, 0x0b, 0x1f, 0xb3, 0x50, 0x55, 0xe2, 0x63, 0x81, 0xf6, - 0x85, 0xbc, 0xeb, 0x06, 0x98, 0x7e, 0x8b, 0x09, 0xd8, 0x2e, 0xbe, 0x8c, - 0x6b, 0x51, 0x5c, 0x08, 0x13, 0x58, 0xb4, 0x2e, 0x41, 0xcb, 0x34, 0x02, - 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xf6, - 0xbc, 0x81, 0x5b, 0x23, 0x66, 0x44, 0x13, 0x27, 0xcf, 0x98, 0xc2, 0xc0, - 0x31, 0x38, 0x98, 0xec, 0x01, 0x84, 0xbb, 0x38, 0xb1, 0x79, 0xd7, 0x91, - 0x66, 0x5a, 0x56, 0x22, 0x62, 0x6f, 0xb8, 0xf0, 0x68, 0x00, 0xe7, 0x1a, - 0x7a, 0x93, 0xfc, 0xa8, 0xd4, 0xd9, 0xaf, 0x21, 0x17, 0x71, 0xf3, 0x0c, - 0xd6, 0x22, 0x2f, 0xb0, 0xb7, 0xc3, 0x1e, 0x07, 0xe7, 0x53, 0x34, 0xc9, - 0x17, 0x9d, 0xe8, 0xd3, 0x07, 0x78, 0xe7, 0x74, 0xcd, 0xf0, 0xdd, 0x88, - 0x0d, 0x30, 0x9b, 0x3c, 0x78, 0xfb, 0x43, 0xb7, 0x4f, 0x79, 0xd1, 0x83, - 0xcd, 0x56, 0x60, 0xe7, 0x7e, 0x8d, 0xba, 0x61, 0x9d, 0x4f, 0xf2, 0x71, - 0x9b, 0xbd, 0x11, 0xfc, 0x82, 0x8f, 0xc2, 0x9b, 0x32, 0xb7, 0x4d, 0x5d, - 0x93, 0x87, 0x11, 0x7d, 0xbf, 0x3a, 0x06, 0x11, 0x15, 0xf5, 0x97, 0xf4, - 0x03, 0x24, 0x6a, 0xfb, 0x5e, 0x27, 0x2b, 0xb5, 0xac, 0x20, 0x84, 0xe8, - 0x8d, 0x67, 0xa9, 0xf5, 0x41, 0x8a, 0xbd, 0xea, 0x51, 0x91, 0x30, 0xd7, - 0xf2, 0x81, 0x12, 0xbc, 0x24, 0x61, 0x25, 0x58, 0x9e, 0x4a, 0x4c, 0x89, - 0xa4, 0x19, 0xf1, 0x12, 0xe2, 0x33, 0xf1, 0x37, 0x1f, 0x0f, 0xa0, 0x42, - 0xa1, 0x0e, 0xa2, 0xc4, 0x06, 0xb0, 0xba, 0x61, 0xef, 0xc5, 0x6b, 0x46, - 0x33, 0x62, 0x50, 0xe0, 0xe4, 0x2e, 0x74, 0x20, 0xf4, 0x54, 0xbb, 0xed, - 0xa0, 0x73, 0x51, 0xa5, 0xc6, 0x55, 0x90, 0x61, 0xe9, 0x9c, 0x76, 0x72, - 0x21, 0xa9, 0x19, 0x1a, 0xbd, 0xcf, 0x61, 0x29, 0x8a, 0xef, 0xdd, 0xe0, - 0xc6, 0x0a, 0xf0, 0xd8, 0x50, 0xb9, 0xe9, 0x92, 0x7d, 0xf3, 0xce, 0x7e, - 0x9e, 0xcf, 0x32, 0x92, 0xc7, 0x49, 0x59, 0x23, 0xb5, 0x4e, 0xf2, 0x71, - 0xf0, 0xda, 0xb3, 0x80, 0xe3, 0xb6, 0x7a, 0xe4, 0x14, 0x80, 0x25, 0x3e, - 0xd0, 0x89, 0x13, 0xf4, 0x70, 0x96, 0xee, 0xbe, 0xef, 0x31, 0x61, 0xa1, - 0x8d, 0xf7, 0x9a, 0x5c, 0x92, 0x0a, 0x9b, 0x1f, 0x8c, 0x5e, 0x3d, 0x37, - 0x24, 0xc2, 0x8d, 0x21, 0xe9, 0x47, 0x2e, 0x03, 0xee, 0x32, 0xbf, 0x46, - 0xc7, 0x2c, 0x6e, 0x7a, 0x81, 0x9e, 0x14, 0xb8, 0xbe, 0xdb, 0x22, 0x4f, - 0xf1, 0x8d, 0x47, 0x41, 0x84, 0xc9, 0xeb, 0x4f, 0xe9, 0xf4, 0xad, 0xc4, - 0xbe, 0xf8, 0x28, 0xcb, 0xe6, 0x16, 0xa8, 0x6b, 0xaf, 0xd5, 0x0a, 0x6d, - 0x06, 0x59, 0x4f, 0x7d, 0x53, 0xa6, 0x4e, 0x90, 0xa0, 0x23, 0x1b, 0x92, - 0xf0, 0xe8, 0xef, 0xed, 0x0d, 0xa7, 0x64, 0x01, 0x83, 0x4a, 0x3b, 0x2d, - 0x18, 0x90, 0x1d, 0x19, 0x1d, 0xa2, 0x98, 0xe9, 0xb5, 0xe4, 0x4a, 0x73, - 0xcf, 0xdf, 0x0c, 0x09, 0xd5, 0xf4, 0xd3, 0xd9, 0x12, 0x7c, 0xbb, 0x81, - 0x51, 0x26, 0x2a, 0xcb, 0xa7, 0xc9, 0x6a, 0xe9, 0xfb, 0x1d, 0xca, 0x43, - 0xf1, 0xbe, 0xfb, 0xc3, 0x6f, 0xb6, 0xa1, 0x0c, 0x42, 0x32, 0x18, 0x24, - 0x63, 0xf9, 0xa0, 0x7e, 0x71, 0x8c, 0xa5, 0x16, 0x16, 0x5a, 0x5e, 0x15, - 0x5d, 0x6d, 0x4b, 0x74, 0x5b, 0xde, 0x21, 0xd5, 0xe0, 0x11, 0xa6, 0x91, - 0xc3, 0xb2, 0xd7, 0x38, 0x70, 0xa2, 0x18, 0x29, 0x1b, 0xdc, 0x83, 0x3e, - 0x37, 0x45, 0xc4, 0x1b, 0x61, 0x98, 0x06, 0x12, 0x3e, 0xc0, 0xda, 0x1a, - 0xc9, 0x18, 0x9c, 0x50, 0x0e, 0xc5, 0xe1, 0xa7, 0x4d, 0x05, 0xc6, 0x99, - 0x31, 0xab, 0x17, 0x30, 0xb9, 0xb0, 0x01, 0x1f, 0x93, 0xd9, 0x76, 0xd4, - 0x67, 0x0b, 0xea, 0x7b, 0x2b, 0x0b, 0x42, 0x97, 0x40, 0x07, 0x94, 0x08, - 0x61, 0x70, 0x70, 0x6c, 0x65, 0x64, 0x6b, 0x75, 0x83, 0x0b, 0x05, 0x16, - 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x34, 0x34, 0x00, 0x84, 0x3c, 0x29, 0x13, 0x41, 0xb7, 0x59, - 0x5c, 0x53, 0x32, 0x4a, 0x6b, 0x41, 0xb7, 0x59, 0x5c, 0x53, 0x32, 0x4a, - 0x6b, 0x65, 0x6d, 0xb0, 0x14, 0x83, 0xdf, 0x17, 0xb6, 0x73, 0x59, 0x09, - 0xd6, 0x8a, 0xed, 0x02, 0x13, 0x5a, 0x8b, 0xd4, 0x99, 0xda, 0x39, 0xa3, - 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, - 0x90, 0xaf, 0xd8, 0x07, 0x09, 0xaa, 0xa7, 0xbf, 0x94, 0x09, 0x4f, 0x35, - 0x59, 0x31, 0xba, 0xaa, 0x89, 0x4f, 0xfa, 0x26, 0x41, 0x66, 0x87, 0x1b, - 0x60, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, - 0x00, 0xdc, 0x97, 0xef, 0xa5, 0xc0, 0xbc, 0x15, 0x38, 0x95, 0x35, 0x74, - 0x61, 0x34, 0x68, 0xb9, 0x5c, 0xef, 0x21, 0xad, 0xeb, 0xc9, 0x50, 0x73, - 0xed, 0x31, 0x38, 0x33, 0x44, 0x03, 0x44, 0x16, 0xaf, 0xa2, 0xba, 0x34, - 0x58, 0x3f, 0x49, 0xaf, 0x93, 0xf8, 0xe4, 0x6e, 0x6f, 0x7f, 0x23, 0x05, - 0x46, 0x75, 0x49, 0xdf, 0x84, 0xad, 0x64, 0x83, 0x11, 0x43, 0xd9, 0x80, - 0x11, 0x93, 0x6d, 0xcf, 0xb4, 0x72, 0x42, 0xc2, 0x5a, 0x78, 0x57, 0x37, - 0x2d, 0x9e, 0x9a, 0x3e, 0x30, 0x9b, 0x72, 0x7b, 0xfa, 0x1d, 0x9e, 0x2d, - 0x53, 0x16, 0x85, 0x91, 0x3c, 0xe9, 0xf1, 0x39, 0x60, 0x1d, 0x9e, 0xc6, - 0xee, 0xb1, 0xdc, 0xb1, 0x0d, 0xb8, 0x23, 0x68, 0xbf, 0xe5, 0x08, 0xc4, - 0xac, 0x31, 0x4e, 0x2d, 0x0f, 0x1f, 0xe1, 0xb3, 0xfe, 0xd2, 0x31, 0x4a, - 0x52, 0x3e, 0x03, 0xe1, 0x1a, 0x66, 0x58, 0x8b, 0x56, 0x99, 0x55, 0x7f, - 0x6f, 0x5a, 0xa9, 0x8f, 0xcf, 0xb3, 0x03, 0x96, 0x79, 0xb0, 0x6c, 0x67, - 0x60, 0x35, 0xce, 0x8d, 0xc6, 0x1c, 0x70, 0x05, 0xa4, 0x5e, 0x4f, 0x83, - 0x4f, 0x1a, 0x98, 0x88, 0xdd, 0x5a, 0x5d, 0xb3, 0x9b, 0xf6, 0xb2, 0xa3, - 0x2e, 0x1c, 0x41, 0x81, 0x97, 0xef, 0x16, 0xb3, 0x8e, 0xbe, 0x09, 0x08, - 0x3d, 0x47, 0xaa, 0x2b, 0x90, 0x61, 0xc7, 0x67, 0xcb, 0x0d, 0xa5, 0x7a, - 0x58, 0x4d, 0xa7, 0x9f, 0xd4, 0x21, 0xf2, 0x47, 0x65, 0x3b, 0x9e, 0x3b, - 0xa4, 0xb4, 0x15, 0x05, 0x10, 0xee, 0x90, 0xe5, 0xd9, 0x2e, 0xa0, 0xfe, - 0x85, 0x9c, 0xad, 0x37, 0x71, 0x51, 0xba, 0x0e, 0x91, 0x48, 0x3e, 0x54, - 0xa0, 0x10, 0x1b, 0xc7, 0xff, 0x4b, 0xd2, 0x24, 0xf8, 0x37, 0xd9, 0xc3, - 0x17, 0x12, 0x05, 0x28, 0xbe, 0xeb, 0xf5, 0xa3, 0x5a, 0x93, 0x7b, 0x9e, - 0x59, 0xb2, 0x63, 0xbc, 0x71, 0x61, 0x6a, 0x5a, 0x6c, 0xbd, 0xae, 0xeb, - 0xff, 0x2a, 0x53, 0xf3, 0x44, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, - 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x73, 0x64, 0x64, 0x6b, 0x75, 0x84, 0x07, - 0x06, 0x16, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x34, 0x34, 0x34, 0x86, 0x46, 0x17, 0x13, 0x41, - 0xb7, 0x59, 0x5c, 0x54, 0xdd, 0xc7, 0x58, 0x41, 0xb7, 0x59, 0x5c, 0x54, - 0xdd, 0xc7, 0x58, 0x8e, 0xc3, 0x7e, 0x3a, 0x0f, 0x3a, 0x3a, 0x7e, 0x0e, - 0x1e, 0x69, 0x08, 0x28, 0x2f, 0x21, 0x1c, 0x2a, 0x13, 0xa3, 0x59, 0xe5, - 0x0e, 0x4d, 0x78, 0x41, 0x89, 0x33, 0xa3, 0x28, 0x6d, 0xb9, 0x0a, 0x0b, - 0x36, 0x7b, 0xf9, 0xc7, 0xb9, 0x71, 0xe5, 0x1c, 0x32, 0x04, 0xe7, 0x79, - 0xe1, 0xe0, 0x05, 0x0b, 0xa0, 0xe7, 0xb9, 0xe1, 0x92, 0xbb, 0xa8, 0xae, - 0xca, 0xff, 0x1c, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, - 0x00, 0x00, 0x00, 0x99, 0x02, 0x2d, 0xc5, 0xee, 0x94, 0x76, 0x6c, 0x0a, - 0xe2, 0xa1, 0xb1, 0x7a, 0x6d, 0x0c, 0xbf, 0x9d, 0xa2, 0x60, 0xdc, 0xb9, - 0xf4, 0xf9, 0x4e, 0x6f, 0x61, 0x37, 0x18, 0x86, 0xbf, 0xef, 0xe9, 0x55, - 0x9e, 0x44, 0x75, 0x32, 0x4c, 0x20, 0x82, 0xb5, 0x3d, 0x42, 0x72, 0x35, - 0x69, 0xba, 0x22, 0x95, 0x0c, 0xec, 0x46, 0xe8, 0x5b, 0x62, 0xe2, 0x07, - 0xd4, 0x80, 0x99, 0xc1, 0x83, 0x12, 0x3f, 0xcc, 0xd4, 0xf6, 0xcd, 0xc2, - 0xb2, 0xcd, 0x4d, 0x94, 0x4c, 0xab, 0x05, 0x48, 0x0c, 0x09, 0xe1, 0x82, - 0x1a, 0x6c, 0x0a, 0xf5, 0x16, 0x06, 0x57, 0x23, 0x9e, 0x18, 0xe8, 0xd9, - 0xbb, 0x4a, 0x8a, 0xcd, 0x69, 0xed, 0xc3, 0xae, 0x71, 0xe8, 0x8f, 0xeb, - 0xb5, 0x76, 0x50, 0xca, 0xb5, 0x69, 0x05, 0xdc, 0x93, 0x5b, 0x49, 0xed, - 0xa3, 0xf8, 0x25, 0xfe, 0x6a, 0x83, 0x6f, 0x16, 0x1e, 0xef, 0x5b, 0xfd, - 0x24, 0x7f, 0x9f, 0x66, 0xf1, 0x65, 0x8c, 0x38, 0x43, 0xd1, 0xbc, 0x13, - 0x14, 0x45, 0x75, 0x66, 0x3b, 0xd7, 0xe1, 0x7a, 0xde, 0xb1, 0xf6, 0x27, - 0xd6, 0x3e, 0xf6, 0x44, 0x7d, 0xf3, 0x3e, 0xd2, 0x95, 0x49, 0xe5, 0x31, - 0x6f, 0x38, 0x95, 0xd0, 0x78, 0xc8, 0xca, 0x68, 0xaf, 0xec, 0xab, 0x1e, - 0xcf, 0x0c, 0xff, 0x3e, 0xc4, 0x12, 0x3e, 0x48, 0xb4, 0x7e, 0x70, 0xc6, - 0xa0, 0x9b, 0xf8, 0x80, 0x30, 0x75, 0x25, 0x1a, 0xf1, 0xdf, 0x3a, 0x37, - 0xa1, 0xac, 0x43, 0x5b, 0xa0, 0xae, 0x9b, 0x91, 0xb3, 0x4a, 0xfa, 0x5f, - 0x4b, 0xf1, 0xba, 0xcd, 0x41, 0x92, 0x38, 0x6a, 0x8d, 0x69, 0x9e, 0xd3, - 0x09, 0xaa, 0x4c, 0xb2, 0x60, 0xcf, 0xff, 0x37, 0xed, 0xa0, 0x39, 0x36, - 0x03, 0x1a, 0x6a, 0xb7, 0xed, 0xce, 0xc8, 0x4e, 0x46, 0xb1, 0x82, 0xfb, - 0xe1, 0x46, 0x2d, 0x12, 0xf4, 0x8a, 0x6c, 0x38, 0x5c, 0x6b, 0xaa, 0x05, - 0xf1, 0xc0, 0xf2, 0x14, 0x8d, 0x3e, 0xdc, 0xec, 0x04, 0x0c, 0x94, 0xe3, - 0xbf, 0x3b, 0x7b, 0x3f, 0xa2, 0x88, 0x98, 0xe6, 0x0c, 0x5f, 0x23, 0x6d, - 0x0b, 0x6f, 0x8e, 0xe9, 0xce, 0xc0, 0xe2, 0x3e, 0xc7, 0xcd, 0xa0, 0x7b, - 0xda, 0xf1, 0x26, 0xfd, 0x3d, 0xc6, 0xe7, 0xe8, 0xed, 0x9d, 0xeb, 0x74, - 0xc5, 0x14, 0x5c, 0xee, 0xcd, 0x4d, 0xc4, 0x4e, 0x1b, 0x2d, 0x09, 0xf4, - 0x7b, 0xdb, 0xf6, 0x96, 0x17, 0x17, 0xd1, 0x16, 0xd5, 0xea, 0xaf, 0x4f, - 0x7b, 0xc2, 0x1e, 0x0f, 0xe1, 0x2c, 0xd8, 0x26, 0xe1, 0xcc, 0x66, 0x64, - 0xd1, 0x3f, 0xd9, 0x16, 0x99, 0x0c, 0xb1, 0x11, 0xc2, 0x13, 0xe5, 0xab, - 0x99, 0x2a, 0x6f, 0x09, 0x37, 0xc5, 0x7c, 0x8e, 0xb8, 0x04, 0x73, 0x3b, - 0x0b, 0x58, 0x87, 0x10, 0x33, 0x1f, 0x5d, 0xea, 0xe9, 0xcd, 0x4e, 0x5b, - 0x33, 0x88, 0xc2, 0x9c, 0x01, 0x1a, 0xe6, 0x92, 0x57, 0xf9, 0xa8, 0x7d, - 0x03, 0x76, 0x79, 0x4e, 0x1e, 0x25, 0xe8, 0xae, 0x61, 0x70, 0x70, 0x6c, - 0x65, 0x64, 0x6b, 0x75, 0x84, 0x55, 0x07, 0x16, 0x00, 0x07, 0x07, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x34, - 0x00, 0x88, 0x0a, 0x17, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x7e, 0xdf, 0xaa, - 0x7a, 0x41, 0xb7, 0x59, 0x5c, 0x7e, 0xdf, 0xaa, 0x7a, 0x0b, 0x66, 0x7c, - 0x18, 0x9e, 0x44, 0x49, 0x2d, 0x40, 0x62, 0x95, 0x22, 0xa7, 0xe3, 0x08, - 0x19, 0x26, 0x0f, 0xd6, 0x6d, 0x3a, 0xdc, 0x09, 0xb3, 0xcd, 0x3d, 0x7c, - 0x47, 0x10, 0xf5, 0x62, 0xa0, 0x5b, 0xd8, 0x50, 0xe7, 0x56, 0xcb, 0xa1, - 0xb8, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, - 0x00, 0x64, 0x0f, 0xc5, 0x21, 0x02, 0x15, 0x7c, 0xa5, 0xb2, 0x07, 0xf2, - 0xee, 0xe7, 0xeb, 0x55, 0xb1, 0x73, 0x0b, 0xc7, 0x85, 0xd2, 0x16, 0x2f, - 0x68, 0x13, 0x3e, 0x6a, 0x6b, 0x3a, 0x3d, 0xbd, 0x3d, 0xd9, 0xc4, 0x98, - 0x92, 0xea, 0x5a, 0xf1, 0xf3, 0x69, 0x0e, 0x20, 0x7b, 0x97, 0xca, 0xe6, - 0x21, 0x45, 0x98, 0xcf, 0x92, 0x04, 0xf5, 0xc9, 0x46, 0x27, 0xd4, 0x4f, - 0x83, 0x2c, 0x3b, 0xbb, 0x83, 0x22, 0xa3, 0x3c, 0x4e, 0x8e, 0x37, 0x6e, - 0xe1, 0x6f, 0x80, 0x83, 0x0f, 0x19, 0xed, 0x17, 0xdb, 0xd1, 0x96, 0xb9, - 0x33, 0xe6, 0x25, 0x50, 0x4f, 0x40, 0x36, 0xbf, 0x42, 0x46, 0xfc, 0x1c, - 0x4a, 0x84, 0x9a, 0xb5, 0xcb, 0xe1, 0xee, 0x4c, 0x84, 0xde, 0x41, 0x9f, - 0x69, 0x3d, 0x9c, 0xe5, 0x38, 0x68, 0xb1, 0x9c, 0x59, 0xd6, 0xcf, 0xcd, - 0x76, 0xc3, 0xa7, 0x99, 0xf2, 0xe5, 0x8d, 0x3b, 0x02, 0xcc, 0x1a, 0xed, - 0x52, 0xd6, 0xef, 0x8f, 0xb2, 0xba, 0x11, 0x39, 0xa5, 0x82, 0x12, 0x04, - 0x2b, 0x03, 0xda, 0x41, 0x8c, 0x9e, 0xe1, 0xc0, 0x8d, 0xdb, 0xff, 0x46, - 0xce, 0xa9, 0xf3, 0x70, 0xf0, 0x5a, 0xd9, 0x5e, 0xc1, 0xa3, 0xca, 0xd4, - 0x02, 0x2a, 0xce, 0x49, 0x55, 0x61, 0x5d, 0x22, 0xbf, 0xf6, 0x5a, 0xe6, - 0xe4, 0xb4, 0x7a, 0xe2, 0x47, 0x24, 0x72, 0xba, 0x8b, 0xd2, 0x39, 0x49, - 0xf2, 0xa0, 0xda, 0xe6, 0xb6, 0xe1, 0x79, 0xdc, 0x0d, 0x73, 0x1b, 0xe6, - 0x40, 0xe4, 0xda, 0x74, 0x7c, 0xa4, 0x81, 0x4b, 0x79, 0x8c, 0x23, 0x8d, - 0xd5, 0x9d, 0xe0, 0x01, 0xe2, 0x88, 0xa8, 0x3f, 0x09, 0xec, 0xf3, 0xa8, - 0xd5, 0x8b, 0xe2, 0xef, 0x0e, 0x0c, 0x42, 0x37, 0xc0, 0x2a, 0x7d, 0x25, - 0x56, 0xc4, 0x28, 0xc3, 0x70, 0x73, 0xe7, 0x14, 0xd0, 0xa8, 0x1e, 0x2a, - 0xd7, 0xd6, 0x85, 0x0f, 0x4b, 0x94, 0x8d, 0xa3, 0xb2, 0xee, 0x83, 0x36, - 0x0a, 0x59, 0x4b, 0x8a, 0xc3, 0xf8, 0xd1, 0x64, 0xb4, 0x07, 0x7c, 0x3d, - 0x98, 0xaf, 0x7c, 0xd2, 0xed, 0x2a, 0xa2, 0x91, 0xf4, 0x32, 0xa8, 0xf1, - 0x67, 0x0a, 0x34, 0x75, 0x88, 0x4e, 0x69, 0x78, 0xca, 0xa4, 0x0c, 0xf8, - 0x40, 0x9f, 0x86, 0xd9, 0x16, 0x56, 0x67, 0x74, 0xd4, 0x33, 0x9e, 0xb7, - 0xef, 0xa6, 0xdf, 0x32, 0xb2, 0x24, 0x20, 0xe7, 0xe9, 0x80, 0xdf, 0x7b, - 0xa3, 0x49, 0x04, 0xd7, 0x3f, 0x9f, 0xbe, 0xa6, 0x2d, 0xd0, 0xec, 0xed, - 0x04, 0x76, 0xc9, 0x38, 0x0b, 0x2c, 0x02, 0xcc, 0xd0, 0x98, 0x02, 0x73, - 0x96, 0x6b, 0x8b, 0xcb, 0x2b, 0x57, 0x2d, 0xab, 0x0d, 0x5e, 0x97, 0xb8, - 0xd9, 0x81, 0xa6, 0x09, 0x7c, 0x6a, 0x6a, 0xbe, 0xed, 0x44, 0xe1, 0x87, - 0x2a, 0xbd, 0xad, 0x61, 0xfa, 0xdc, 0x76, 0xaa, 0xa5, 0xfd, 0x40, 0xee, - 0x9f, 0xf1, 0xc6, 0x74, 0xe9, 0xba, 0xc1, 0xaf, 0xf1, 0x5d, 0x16, 0x06, - 0x27, 0x60, 0x2b, 0x96, 0x9d, 0x0d, 0xc1, 0x7c, 0xc3, 0x7b, 0xfd, 0x33, - 0xc2, 0xa6, 0x7c, 0xbc, 0xc3, 0x1c, 0xef, 0x9d, 0xf4, 0xe2, 0x8c, 0x2d, - 0xe3, 0x01, 0xc1, 0x95, 0x24, 0x66, 0x15, 0x1a, 0xa1, 0xa0, 0x61, 0x28, - 0x8f, 0x44, 0x77, 0x80, 0xfc, 0x11, 0xce, 0xad, 0xe1, 0xf1, 0xe9, 0x80, - 0x55, 0x6d, 0x77, 0x5d, 0xf7, 0x2a, 0xf8, 0x15, 0x42, 0xdd, 0xf6, 0x62, - 0xac, 0x68, 0x8f, 0xaa, 0x85, 0xd8, 0xfa, 0xc6, 0x21, 0xe9, 0xa8, 0xa2, - 0x1e, 0xe3, 0xd4, 0x32, 0x3e, 0xee, 0xec, 0x96, 0x54, 0xe1, 0xb1, 0x8f, - 0x64, 0x59, 0xc6, 0x49, 0x01, 0x3c, 0xc0, 0x17, 0xa9, 0xf5, 0xf2, 0x6f, - 0x8a, 0xec, 0x9b, 0x66, 0xa7, 0x1d, 0x98, 0xff, 0x61, 0x70, 0x70, 0x6c, - 0x65, 0x64, 0x6b, 0x75, 0x0d, 0x00, 0x00, 0x00, 0x05, 0x04, 0x3a, 0x00, - 0x07, 0x4c, 0x0d, 0x3f, 0x0e, 0xa9, 0x04, 0x3a, 0x05, 0x5c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x1f, 0x11, 0x16, 0x00, 0x07, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x34, 0x34, 0x00, 0x83, 0x22, 0x15, 0x11, 0x41, 0xb7, 0x59, 0x5c, 0xf4, - 0x84, 0x43, 0x4e, 0x41, 0xb7, 0x59, 0x5c, 0xf4, 0x84, 0x43, 0x4e, 0xda, - 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, - 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0xa9, 0x4a, 0x8f, 0xe5, 0xcc, - 0xb1, 0x9b, 0xa6, 0x1c, 0x4c, 0x08, 0x73, 0xd3, 0x91, 0xe9, 0x87, 0x98, - 0x2f, 0xbb, 0xd3, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x28, - 0x00, 0x00, 0x00, 0x72, 0xbd, 0xda, 0xaa, 0x55, 0x31, 0xcc, 0x9a, 0xfc, - 0x33, 0x30, 0x52, 0x07, 0x40, 0x54, 0xcb, 0x27, 0x4e, 0xb7, 0x9f, 0x96, - 0xb8, 0xcb, 0xdc, 0x88, 0x3c, 0x09, 0xd1, 0x96, 0xe2, 0x79, 0x54, 0x21, - 0x46, 0xca, 0x50, 0xa2, 0x46, 0xda, 0x44, 0x2e, 0x3b, 0x4b, 0x18, 0xb7, - 0x5a, 0x17, 0xe6, 0x4f, 0x06, 0xde, 0xec, 0x05, 0x9c, 0xec, 0x8e, 0xb5, - 0xd1, 0xb3, 0xe3, 0x0a, 0x3f, 0x44, 0x9c, 0xa5, 0x30, 0x0a, 0x83, 0x66, - 0x82, 0x89, 0xcf, 0x1b, 0xb8, 0xb8, 0xb2, 0x18, 0x54, 0xcf, 0x4d, 0x85, - 0x93, 0x97, 0x75, 0x54, 0x06, 0x23, 0x05, 0xe8, 0xff, 0x42, 0x33, 0x7f, - 0xdf, 0x26, 0xa0, 0x1e, 0xd3, 0xe2, 0x7b, 0xb7, 0xe2, 0x70, 0x88, 0x82, - 0xba, 0x3e, 0x38, 0xaa, 0x95, 0xee, 0xf7, 0x4f, 0x81, 0xbe, 0xf4, 0xfe, - 0x8f, 0x42, 0xb8, 0x94, 0x25, 0xe3, 0x3a, 0x4b, 0xe1, 0x15, 0xe2, 0xe1, - 0xe6, 0x8b, 0xda, 0x49, 0x9a, 0xb1, 0x47, 0xa4, 0x9c, 0xac, 0x35, 0xb8, - 0xa2, 0xb3, 0xc2, 0x5f, 0x2b, 0x87, 0x11, 0xd7, 0x57, 0x47, 0x05, 0x89, - 0x05, 0x86, 0xfa, 0x97, 0xa7, 0x97, 0x46, 0xcf, 0xaa, 0xa8, 0x94, 0x2c, - 0xde, 0xa3, 0xde, 0xb1, 0x92, 0x20, 0xbd, 0x7d, 0x90, 0xd2, 0xa7, 0x21, - 0x26, 0x6f, 0x2b, 0x6e, 0xd3, 0xd9, 0x1a, 0xea, 0x57, 0x04, 0x94, 0x1c, - 0x73, 0x0e, 0x74, 0x65, 0x73, 0x74, 0x61, 0x6b, 0xe1, 0x06, 0x12, 0x17, - 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x34, 0x34, 0x00, 0x81, 0xc0, 0x6a, 0x17, 0x13, 0x41, 0xb7, - 0x59, 0x5c, 0xfe, 0x44, 0x71, 0x3f, 0x41, 0xb7, 0x59, 0x5c, 0xfe, 0x44, - 0x71, 0x3f, 0x7f, 0xda, 0x6a, 0xa0, 0x63, 0xf3, 0xfc, 0x5a, 0x86, 0x5c, - 0xa8, 0xf7, 0xa6, 0x9b, 0x5d, 0x69, 0x07, 0x3b, 0x91, 0x55, 0x72, 0x29, - 0x9c, 0x30, 0x4b, 0x50, 0xee, 0xe7, 0xb0, 0xc7, 0x1b, 0x05, 0x97, 0x70, - 0xac, 0x8e, 0x43, 0x5d, 0x69, 0x39, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x38, 0xbe, 0xad, 0xda, 0xa8, 0x8a, - 0x50, 0x50, 0xa2, 0x05, 0x34, 0x4f, 0x7d, 0x48, 0x22, 0x81, 0x07, 0x45, - 0x81, 0x36, 0x06, 0x10, 0x48, 0xd5, 0xe0, 0xb8, 0x50, 0xbd, 0x5c, 0xe8, - 0x5d, 0x51, 0x93, 0x3c, 0xfa, 0xeb, 0x83, 0x4d, 0x00, 0xa1, 0x9d, 0x8a, - 0x39, 0x91, 0xac, 0x08, 0x70, 0x37, 0x9a, 0x2d, 0x33, 0xdf, 0xfa, 0x44, - 0xed, 0x61, 0x62, 0x10, 0x2c, 0x22, 0x27, 0x44, 0xa8, 0x19, 0xc3, 0x4f, - 0xd4, 0xb6, 0x7a, 0x6c, 0xf3, 0xb2, 0x4f, 0xf4, 0x06, 0x16, 0x5e, 0xc6, - 0x08, 0x61, 0xd5, 0x6b, 0xaf, 0x9d, 0x1e, 0x1f, 0x9c, 0xed, 0x30, 0xda, - 0x7a, 0xf1, 0xa3, 0x24, 0x26, 0xf5, 0xc9, 0xd6, 0xea, 0xdc, 0x1b, 0x4b, - 0xf6, 0x62, 0x78, 0xa6, 0x64, 0x6c, 0xd4, 0xbf, 0x30, 0x29, 0x36, 0x18, - 0x7c, 0x55, 0x1e, 0x12, 0xbe, 0x30, 0xc9, 0x51, 0x4c, 0x18, 0x83, 0x39, - 0x8d, 0xa2, 0xbc, 0x8a, 0x6f, 0x96, 0x1b, 0x69, 0xbf, 0x99, 0x29, 0x58, - 0x7b, 0xd2, 0x9d, 0x50, 0x32, 0x91, 0x31, 0xd2, 0x25, 0xcc, 0x19, 0xab, - 0x51, 0x6a, 0xc8, 0x5b, 0xd9, 0xf3, 0x64, 0x36, 0xf8, 0xbc, 0x73, 0x23, - 0x07, 0x04, 0x93, 0xd9, 0xbc, 0xd4, 0xb8, 0x7b, 0xd3, 0x58, 0x68, 0x2c, - 0x2b, 0x67, 0xae, 0x57, 0x39, 0x6b, 0xb0, 0xf5, 0x62, 0xe5, 0xec, 0xbe, - 0x42, 0x97, 0x9f, 0xec, 0x9c, 0x43, 0x7c, 0xba, 0xab, 0xad, 0xed, 0xd9, - 0xa0, 0xbc, 0xf4, 0x98, 0x03, 0xca, 0xbe, 0xd8, 0xa3, 0x79, 0x4c, 0xdb, - 0x3d, 0x22, 0x15, 0x71, 0xc9, 0x37, 0x92, 0x9b, 0x05, 0x54, 0x72, 0xe2, - 0x41, 0xd7, 0xd8, 0xb2, 0x4f, 0xcf, 0x56, 0xf3, 0x46, 0x4c, 0x39, 0x5d, - 0x49, 0xdf, 0xae, 0x52, 0xb2, 0x8f, 0xf0, 0x9a, 0xae, 0xe0, 0x00, 0xf4, - 0xd0, 0xd0, 0xa3, 0x8d, 0xf4, 0xba, 0x57, 0xe5, 0x0d, 0xa2, 0x0e, 0xcc, - 0xa3, 0xb9, 0xd0, 0x78, 0x24, 0x3e, 0xdb, 0xdb, 0x4b, 0xc8, 0x60, 0xbb, - 0x71, 0xb8, 0xc6, 0xfe, 0xb0, 0x67, 0x5b, 0x86, 0x09, 0x6c, 0xd0, 0x3e, - 0x6e, 0x0a, 0x82, 0x93, 0xcf, 0xdb, 0x9a, 0x72, 0x5c, 0x41, 0x8f, 0xa5, - 0xfd, 0x44, 0x17, 0xe0, 0x5f, 0x85, 0x9c, 0xb5, 0x71, 0xe4, 0x67, 0x94, - 0x88, 0xdf, 0xfe, 0xad, 0x4e, 0x5e, 0x67, 0x41, 0x49, 0xc3, 0xda, 0x1a, - 0x25, 0xcc, 0x8c, 0xaf, 0xb5, 0xf9, 0xb6, 0x37, 0x2f, 0xe9, 0x73, 0x1d, - 0x71, 0xaf, 0x2a, 0x7d, 0x95, 0xef, 0x8a, 0xe0, 0x0f, 0x0a, 0x73, 0x95, - 0x88, 0x33, 0xe2, 0xe0, 0x88, 0x2b, 0x44, 0x60, 0x51, 0x27, 0xfa, 0x90, - 0xfc, 0x5a, 0x35, 0x54, 0x19, 0x9c, 0xb4, 0x60, 0x2b, 0xd8, 0x4c, 0xf9, - 0x2d, 0xba, 0x88, 0x12, 0xa6, 0xfc, 0x0c, 0x22, 0xfd, 0x27, 0x9e, 0x98, - 0x02, 0xf8, 0x06, 0x70, 0x51, 0x66, 0xa0, 0x1e, 0xb1, 0x6e, 0xe1, 0x90, - 0x86, 0x55, 0xa2, 0x84, 0x92, 0xd6, 0xe4, 0x59, 0x00, 0x00, 0x00, 0x1c, - 0x8b, 0x70, 0x08, 0x16, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x34, 0x00, 0x96, 0x40, 0x17, - 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x7e, 0xe2, 0xe0, 0xc1, 0x41, 0xb7, 0x59, - 0x5c, 0x7e, 0xe2, 0xe0, 0xc1, 0x51, 0x96, 0x74, 0xbb, 0x0c, 0xef, 0x0c, - 0xf3, 0x24, 0x61, 0xd2, 0x2c, 0xba, 0x9a, 0xa9, 0xc8, 0x0e, 0x22, 0xff, - 0x0b, 0x3a, 0xdc, 0x09, 0xb3, 0xcd, 0x3d, 0x7c, 0x47, 0x10, 0xf5, 0x62, - 0xa0, 0x5b, 0xd8, 0x50, 0xe7, 0x56, 0xcb, 0xa1, 0xb8, 0x02, 0x00, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x4e, 0xcb, 0x84, - 0x35, 0xce, 0xed, 0x00, 0x0f, 0x0d, 0x8f, 0xce, 0xe6, 0x43, 0xc4, 0x14, - 0x6f, 0x42, 0xd5, 0x97, 0xdf, 0xa6, 0x31, 0x52, 0xa2, 0xb2, 0xc4, 0x38, - 0xf2, 0x2e, 0xb2, 0x5e, 0x73, 0x6d, 0xeb, 0x60, 0xa9, 0x70, 0x32, 0xad, - 0x98, 0x3a, 0x23, 0x00, 0x86, 0x4c, 0x75, 0x26, 0x22, 0x28, 0x8f, 0x1a, - 0x96, 0x60, 0x8a, 0x61, 0xa2, 0xc5, 0x0b, 0x5a, 0xf6, 0x7b, 0x3a, 0xb0, - 0x42, 0x02, 0x3a, 0x5f, 0x4c, 0x14, 0xdd, 0x52, 0x6a, 0xff, 0x08, 0x5f, - 0x7e, 0xef, 0x9a, 0x98, 0x0e, 0x06, 0x38, 0x24, 0x6d, 0x4c, 0xa6, 0x29, - 0xeb, 0x44, 0xa8, 0x35, 0x7d, 0x0f, 0x2f, 0x8c, 0x83, 0x5b, 0xc4, 0x43, - 0x5f, 0x9c, 0x33, 0x7f, 0xc0, 0x97, 0x17, 0xed, 0xcb, 0x95, 0xed, 0xa4, - 0xe4, 0x29, 0xdd, 0x62, 0xff, 0x3a, 0x07, 0x91, 0x92, 0xa9, 0xc2, 0x19, - 0xc3, 0xaa, 0xa3, 0xcb, 0xcc, 0x64, 0xf2, 0x00, 0xb8, 0xc9, 0x17, 0x3d, - 0x00, 0x24, 0xb2, 0xaf, 0x0e, 0x6c, 0xd5, 0x64, 0x84, 0x7d, 0x60, 0x19, - 0xad, 0xa6, 0x79, 0x05, 0x88, 0xf7, 0x72, 0x5a, 0xa4, 0x6b, 0x51, 0x77, - 0xb2, 0x28, 0x93, 0xcb, 0xbe, 0x74, 0x70, 0x10, 0x09, 0x00, 0x5f, 0x2d, - 0xe5, 0xf8, 0x9d, 0x90, 0x00, 0x2b, 0xa3, 0xbb, 0x32, 0x6c, 0x2d, 0x9e, - 0x72, 0x25, 0x18, 0x92, 0xec, 0xbf, 0x97, 0x49, 0xc7, 0x4c, 0xee, 0x90, - 0x5d, 0x6d, 0xdc, 0xa4, 0x4f, 0x4c, 0x88, 0x6c, 0x81, 0x9f, 0xcf, 0xd1, - 0x89, 0x29, 0x3d, 0x61, 0x38, 0x33, 0x89, 0x4a, 0x81, 0xd2, 0x0c, 0xc8, - 0xdc, 0x09, 0xb2, 0x6a, 0xa7, 0x16, 0x42, 0x9f, 0xa3, 0x9d, 0x85, 0x02, - 0xb4, 0xb8, 0xd4, 0xae, 0x63, 0xef, 0x50, 0x78, 0x43, 0x3b, 0x20, 0x7c, - 0x87, 0xac, 0xcb, 0x0b, 0x96, 0x1c, 0x8e, 0x1f, 0xc4, 0x84, 0x20, 0xe1, - 0x3c, 0xe3, 0x0a, 0x28, 0xfb, 0x4b, 0xa3, 0x19, 0x7c, 0xc7, 0x37, 0xf0, - 0x29, 0x47, 0x9d, 0xaf, 0xf4, 0xf1, 0xf6, 0x3c, 0x32, 0xae, 0x5b, 0x37, - 0xc5, 0x77, 0x90, 0xf5, 0x59, 0x8b, 0x85, 0x95, 0xee, 0xdf, 0xa7, 0x2e, - 0x4b, 0x5b, 0xf3, 0x0c, 0xe3, 0xc5, 0xe6, 0x6a, 0x85, 0xfb, 0xe2, 0x4a, - 0x5a, 0xb8, 0x06, 0xcc, 0x22, 0x3d, 0x21, 0x76, 0x04, 0xca, 0x5f, 0x61, - 0x18, 0x4f, 0x35, 0x11, 0x20, 0xe9, 0xc1, 0x72, 0x3d, 0x45, 0x58, 0x60, - 0x8b, 0x8e, 0x3d, 0x3d, 0x21, 0xf8, 0xb3, 0xa3, 0x02, 0x57, 0x06, 0xbd, - 0xff, 0xe0, 0x65, 0x35, 0x3a, 0xba, 0xe8, 0xa8, 0x96, 0x6f, 0x6c, 0x67, - 0xeb, 0xd6, 0xf4, 0xdc, 0xf6, 0x26, 0x52, 0xcd, 0xed, 0xc1, 0x73, 0x12, - 0xdb, 0x86, 0xef, 0x36, 0x87, 0x22, 0xc4, 0xfd, 0xaf, 0xc7, 0x35, 0x90, - 0x38, 0xe5, 0xb2, 0x4a, 0x8a, 0xca, 0xcc, 0x1a, 0xd5, 0x82, 0x10, 0xba, - 0xe7, 0x60, 0xb2, 0x0d, 0x6b, 0xb5, 0xbd, 0x9e, 0x6e, 0xd0, 0xe0, 0x36, - 0xd8, 0x0a, 0x09, 0x24, 0x87, 0xcd, 0xc2, 0x94, 0x10, 0x14, 0xc4, 0x15, - 0xc2, 0xf7, 0x37, 0x22, 0x78, 0x6c, 0x88, 0x75, 0x3a, 0x08, 0xdc, 0x81, - 0x58, 0xe6, 0x3a, 0x4b, 0x7a, 0x6b, 0xe8, 0x27, 0x5d, 0x5d, 0xea, 0x6d, - 0x1a, 0xbb, 0x50, 0x8b, 0xa5, 0x7c, 0x1d, 0xd2, 0xd8, 0x86, 0xf3, 0xa7, - 0xd7, 0xd7, 0x82, 0x61, 0x14, 0x7a, 0x4e, 0x32, 0xf3, 0x74, 0x38, 0x09, - 0x9b, 0xeb, 0x7c, 0x55, 0x53, 0x9e, 0x39, 0xec, 0xe1, 0xf0, 0xae, 0x7d, - 0xbe, 0x9a, 0x1d, 0x87, 0xab, 0x97, 0xc2, 0xa6, 0x05, 0xb7, 0xc2, 0x86, - 0x2d, 0xc8, 0x1e, 0x02, 0x0a, 0xa8, 0xaa, 0x4f, 0xb5, 0x70, 0x92, 0x97, - 0x75, 0x7a, 0x3c, 0xe0, 0xd3, 0x2c, 0x87, 0xf6, 0x53, 0x4f, 0x98, 0x69, - 0x2f, 0xb3, 0xa6, 0xeb, 0xb6, 0xfd, 0xf5, 0x07, 0x6d, 0x8c, 0x9d, 0xf7, - 0x70, 0x60, 0xe9, 0x34, 0x66, 0x9b, 0x54, 0x37, 0x20, 0xe2, 0x03, 0xb5, - 0x81, 0xff, 0xa1, 0x52, 0x72, 0x27, 0xae, 0x71, 0xe3, 0x4a, 0xf8, 0xda, - 0xa9, 0x8d, 0xb6, 0x2c, 0x88, 0xa2, 0xa4, 0xf3, 0x01, 0xdc, 0x16, 0x28, - 0xe2, 0xb3, 0x6d, 0x94, 0xa8, 0x17, 0xc7, 0x19, 0x35, 0x57, 0x75, 0x31, - 0x7b, 0x1e, 0x92, 0x44, 0xa3, 0xf4, 0xed, 0x84, 0x9c, 0x3e, 0xae, 0x71, - 0xfe, 0x12, 0x40, 0x76, 0x85, 0xa4, 0x98, 0x0b, 0x07, 0x48, 0x91, 0x22, - 0xff, 0x80, 0x07, 0x51, 0x5a, 0x67, 0x19, 0xa8, 0xf5, 0x11, 0x1b, 0x3a, - 0x2e, 0xae, 0x27, 0x6e, 0x26, 0x0e, 0xb0, 0x3c, 0x3b, 0xaf, 0xc0, 0x31, - 0xf6, 0x76, 0x95, 0x89, 0x66, 0xe5, 0x6d, 0x92, 0x12, 0xc8, 0x96, 0xc6, - 0x42, 0x33, 0x66, 0xb1, 0x3c, 0x9b, 0x45, 0xc8, 0xa2, 0x50, 0x37, 0xeb, - 0x7e, 0xf6, 0x67, 0x9e, 0xda, 0x28, 0x1b, 0x8f, 0x6d, 0xd4, 0x47, 0x71, - 0x6a, 0xa6, 0xd9, 0x0c, 0x3c, 0x49, 0xa8, 0xa5, 0x2a, 0x60, 0x88, 0xd0, - 0x44, 0x8f, 0xb0, 0xb8, 0x28, 0x8b, 0x84, 0xce, 0xdd, 0x05, 0x02, 0x22, - 0xab, 0x7c, 0x7a, 0xfe, 0x5a, 0x6c, 0x60, 0x7e, 0x63, 0x17, 0xc6, 0x8b, - 0xaa, 0x28, 0xf4, 0xa1, 0x59, 0x17, 0x93, 0x8e, 0xfc, 0x20, 0x7a, 0xd2, - 0x6d, 0x60, 0x53, 0x2f, 0xd3, 0x97, 0xaa, 0xc4, 0xc3, 0x1b, 0x81, 0x43, - 0xdd, 0x0b, 0xc2, 0x18, 0x31, 0x05, 0xb3, 0xce, 0xea, 0x46, 0x4a, 0x90, - 0xdb, 0x9f, 0x1e, 0x5b, 0xfd, 0x17, 0x6f, 0x84, 0x0d, 0x05, 0x4b, 0x4b, - 0xcb, 0x63, 0x6c, 0x15, 0x47, 0xcf, 0x8b, 0x77, 0x5d, 0xb7, 0x3a, 0x0e, - 0xe1, 0xc5, 0xd6, 0x4b, 0x8a, 0x81, 0x04, 0x18, 0x4f, 0x2e, 0x25, 0x1d, - 0x3b, 0x45, 0x00, 0xc0, 0xd9, 0x44, 0x23, 0xf0, 0x99, 0xf1, 0xe8, 0xc6, - 0xdc, 0x96, 0x38, 0xde, 0xa9, 0x85, 0x4a, 0x5c, 0x7b, 0x5d, 0xaf, 0x35, - 0xc8, 0x6d, 0xbe, 0x89, 0xd2, 0x2a, 0x5c, 0xec, 0xab, 0xe3, 0x8e, 0x69, - 0x19, 0x54, 0xb0, 0x61, 0xad, 0xfd, 0x0b, 0x68, 0x07, 0x2f, 0xe6, 0x13, - 0xa6, 0x83, 0xc1, 0x23, 0x45, 0x54, 0x9e, 0x19, 0xe0, 0xeb, 0x1b, 0x04, - 0xd4, 0xd9, 0x86, 0x6d, 0x38, 0xe4, 0x5b, 0x63, 0xbb, 0xb5, 0xb6, 0xd5, - 0xc5, 0x6e, 0xb1, 0xa5, 0xaf, 0x16, 0x6e, 0x8e, 0xbe, 0xb2, 0xc4, 0x2a, - 0xa8, 0x2d, 0x41, 0x5e, 0xd4, 0xc9, 0x28, 0x67, 0x65, 0x65, 0x98, 0x4c, - 0x0c, 0xd8, 0x40, 0x79, 0x59, 0x42, 0x77, 0xf3, 0x06, 0x81, 0x06, 0x43, - 0xfb, 0x97, 0xbf, 0x28, 0x41, 0xdc, 0xb5, 0x54, 0xb8, 0xdf, 0x9d, 0xc1, - 0x9d, 0xba, 0x4f, 0x11, 0x2a, 0x4e, 0xca, 0xf9, 0xc4, 0xcb, 0xfc, 0xeb, - 0xc1, 0x2a, 0x87, 0x75, 0x5c, 0x6f, 0xcb, 0x75, 0x36, 0xc2, 0x5e, 0xce, - 0x7a, 0x59, 0x6e, 0x7c, 0x6f, 0xe8, 0x3c, 0xa6, 0x7b, 0xe7, 0x36, 0x4d, - 0xfa, 0xad, 0xac, 0xbd, 0x61, 0xa3, 0x36, 0x53, 0xc4, 0x3d, 0xc5, 0xf5, - 0x46, 0x3a, 0x97, 0x5b, 0x66, 0x0a, 0x84, 0xa2, 0x31, 0xf0, 0xdc, 0xc3, - 0x30, 0xdc, 0x52, 0x93, 0x73, 0xab, 0x2b, 0x7e, 0x61, 0xb1, 0x35, 0xa2, - 0xff, 0x8a, 0x31, 0xf8, 0xfe, 0x0f, 0x22, 0x27, 0xba, 0xe2, 0x9e, 0xd3, - 0xfe, 0x7c, 0x2e, 0xe0, 0x94, 0x45, 0xc5, 0x2b, 0xd6, 0xaa, 0xb5, 0x74, - 0xd0, 0x5a, 0x5b, 0x61, 0x24, 0x69, 0x42, 0x8d, 0x5f, 0xe4, 0x3c, 0xe2, - 0xad, 0x15, 0x2b, 0x87, 0xbe, 0xec, 0xf0, 0x2e, 0x61, 0xb6, 0xc4, 0xe1, - 0xc6, 0x57, 0x9a, 0x5d, 0xc7, 0x35, 0x31, 0x6f, 0xb0, 0x14, 0xcc, 0x59, - 0xfc, 0x8a, 0x88, 0x08, 0xcb, 0x20, 0xdd, 0xc3, 0xc7, 0xa4, 0xdc, 0x9c, - 0x1f, 0x1b, 0x89, 0x28, 0x55, 0xab, 0x36, 0x9c, 0xae, 0x64, 0xb2, 0x7e, - 0x7f, 0x92, 0xb5, 0x79, 0x44, 0x0b, 0x2e, 0x0c, 0x3c, 0xc5, 0xd8, 0xd2, - 0x12, 0x15, 0xb9, 0x5e, 0x76, 0x40, 0xc5, 0xf5, 0x6f, 0x33, 0x41, 0xdf, - 0x83, 0x99, 0x91, 0x9b, 0xc1, 0x72, 0xf6, 0xbe, 0x87, 0xeb, 0x25, 0x82, - 0x49, 0x61, 0x44, 0xc1, 0x0f, 0x79, 0xd3, 0xae, 0x4d, 0x8d, 0xa0, 0xa5, - 0x40, 0x5f, 0xf2, 0x65, 0x94, 0xc3, 0x66, 0x18, 0xa1, 0x3c, 0x3b, 0x50, - 0x4b, 0xc9, 0xc0, 0x55, 0xb6, 0xf6, 0x69, 0xc2, 0x08, 0x10, 0x5f, 0xd7, - 0x7a, 0x62, 0xfb, 0x30, 0xf2, 0xdd, 0x25, 0x45, 0xfb, 0x8c, 0xaa, 0x56, - 0x89, 0xa5, 0xc8, 0x4a, 0xfc, 0x34, 0x57, 0x5a, 0x1c, 0x7b, 0x5b, 0xbd, - 0x7d, 0xfe, 0x43, 0xcb, 0xec, 0x3a, 0xdf, 0x59, 0x46, 0xd4, 0x01, 0xe3, - 0xee, 0xdf, 0x7e, 0xab, 0xc4, 0x55, 0x03, 0xdb, 0x7a, 0x3c, 0x56, 0x84, - 0xec, 0x39, 0x7c, 0xab, 0xd6, 0x64, 0x3b, 0x6e, 0xda, 0xa5, 0x1a, 0x48, - 0x13, 0x31, 0x3f, 0xe2, 0xaf, 0xee, 0x15, 0x74, 0xa6, 0x9d, 0x26, 0x6b, - 0xb4, 0x7d, 0x4d, 0xb2, 0x3e, 0xbe, 0x80, 0xdd, 0x81, 0xad, 0x81, 0x3a, - 0xa8, 0x27, 0x25, 0x13, 0xfc, 0x0e, 0xe6, 0x87, 0xdb, 0xf5, 0x08, 0x50, - 0x7a, 0x2c, 0x06, 0x66, 0x87, 0x07, 0xae, 0x14, 0xa8, 0xe2, 0x49, 0x6b, - 0x5f, 0x03, 0x89, 0x07, 0x8e, 0x1a, 0xa1, 0x5e, 0xa3, 0x9f, 0x1f, 0x1f, - 0xb1, 0x22, 0x14, 0x38, 0x9a, 0xc7, 0x4a, 0x7f, 0xd9, 0xb7, 0xd9, 0xbd, - 0xb5, 0x33, 0xa7, 0x97, 0xbb, 0x24, 0x5c, 0xb0, 0xee, 0x1a, 0xe3, 0x2d, - 0xf1, 0x0d, 0x33, 0x6e, 0x77, 0x02, 0x38, 0x35, 0x7d, 0x0f, 0x4a, 0xfb, - 0x12, 0x10, 0xee, 0x1e, 0xf8, 0x33, 0xa8, 0x19, 0xdb, 0xf1, 0xb3, 0x31, - 0x4b, 0x7b, 0xee, 0x3d, 0x0c, 0x71, 0x3a, 0x7c, 0xb7, 0xbc, 0x5e, 0x44, - 0x97, 0x99, 0xb8, 0x56, 0xee, 0x8a, 0xac, 0x72, 0x12, 0x38, 0xac, 0xe9, - 0x8d, 0x35, 0x05, 0x0a, 0x47, 0x27, 0xea, 0xd9, 0xbe, 0x21, 0xaa, 0xd5, - 0xb3, 0x57, 0x44, 0x15, 0xf9, 0xe7, 0x0d, 0x0d, 0x63, 0xc5, 0xa8, 0xe6, - 0x74, 0x9d, 0x52, 0xf4, 0xdd, 0x04, 0x1b, 0xea, 0x82, 0xe9, 0x5d, 0xca, - 0x43, 0xa5, 0x60, 0x6b, 0x16, 0xee, 0x1b, 0xe0, 0xc2, 0x28, 0x75, 0xad, - 0xb5, 0x87, 0xf2, 0xd2, 0x53, 0x32, 0x00, 0xa7, 0xe6, 0x15, 0xd0, 0x93, - 0x0d, 0x1f, 0x67, 0x56, 0xea, 0xaf, 0x98, 0xe4, 0x87, 0x04, 0x71, 0xfe, - 0xf9, 0x2e, 0xd0, 0x2d, 0x1f, 0x70, 0xa9, 0xee, 0x53, 0xec, 0xdb, 0xc7, - 0x3b, 0x3e, 0x42, 0x7e, 0xf3, 0x07, 0xdd, 0x6e, 0x3f, 0xca, 0x69, 0xcc, - 0xe3, 0x9b, 0x9b, 0xd6, 0xfd, 0xd2, 0x44, 0x27, 0xd5, 0xd0, 0x64, 0x2f, - 0xe8, 0x72, 0x26, 0x3c, 0xaf, 0x49, 0xcb, 0xb6, 0x69, 0xae, 0x95, 0xc1, - 0x24, 0x33, 0xc3, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x64, 0x6b, 0x75, 0x82, - 0x67, 0x09, 0x16, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x34, 0x00, 0x84, 0x2e, 0x17, 0x13, - 0x41, 0xb7, 0x59, 0x5c, 0x7e, 0xe7, 0x05, 0xea, 0x41, 0xb7, 0x59, 0x5c, - 0x7e, 0xe7, 0x05, 0xea, 0x05, 0xc5, 0x64, 0xf0, 0xff, 0xc1, 0x0a, 0xf4, - 0x42, 0x83, 0x33, 0x33, 0x5d, 0x04, 0x75, 0x9c, 0x85, 0x9a, 0x74, 0x0a, - 0x3a, 0xdc, 0x09, 0xb3, 0xcd, 0x3d, 0x7c, 0x47, 0x10, 0xf5, 0x62, 0xa0, - 0x5b, 0xd8, 0x50, 0xe7, 0x56, 0xcb, 0xa1, 0xb8, 0x02, 0x00, 0x00, 0x00, - 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x10, 0x8e, 0xb4, 0xf5, - 0x90, 0xc1, 0x32, 0x90, 0x6a, 0xe5, 0x04, 0x8f, 0xcf, 0xc2, 0xed, 0xf7, - 0x79, 0x17, 0xfc, 0x2e, 0x73, 0xd6, 0xaa, 0xea, 0xfe, 0xb5, 0x0d, 0x3f, - 0x72, 0xf1, 0x5a, 0x24, 0x01, 0xcd, 0xda, 0x13, 0xc1, 0x2b, 0x8f, 0xa9, - 0x10, 0xf2, 0x28, 0xa0, 0x07, 0xbd, 0xc8, 0x20, 0x8c, 0x85, 0x74, 0x3c, - 0xcb, 0x87, 0xbd, 0x9f, 0x3f, 0xf0, 0xd8, 0x56, 0x35, 0x47, 0x97, 0x13, - 0xc9, 0x22, 0x59, 0x2b, 0x71, 0x3f, 0x46, 0x44, 0xf1, 0x3d, 0x3f, 0xc8, - 0x44, 0x43, 0x4d, 0x5c, 0x56, 0x92, 0x3a, 0x3b, 0x00, 0xb0, 0xc1, 0x42, - 0x91, 0xf8, 0xa5, 0x17, 0x42, 0xa8, 0x6a, 0x4d, 0x1e, 0xfd, 0x6f, 0x05, - 0xfb, 0x89, 0x38, 0x46, 0x67, 0x9f, 0x6d, 0xe5, 0x3b, 0xd5, 0xb1, 0xcc, - 0x8b, 0xa9, 0x67, 0x6f, 0x67, 0x1b, 0x5d, 0x7c, 0xe0, 0x0f, 0xd4, 0xdf, - 0x6e, 0xd1, 0x4a, 0xbb, 0x53, 0x57, 0x47, 0xe8, 0x0c, 0xe7, 0x64, 0x54, - 0x4f, 0x57, 0xb6, 0x8e, 0xce, 0xb3, 0x88, 0x70, 0x36, 0x06, 0x0f, 0xdc, - 0xa8, 0x1d, 0xda, 0x06, 0x2b, 0x03, 0xbb, 0xa4, 0x9d, 0x70, 0xb2, 0x04, - 0xa3, 0xfd, 0x9d, 0x8b, 0x6f, 0x89, 0x74, 0x3a, 0xff, 0xf5, 0x2f, 0x30, - 0x34, 0xb1, 0x6b, 0x21, 0xe3, 0xe9, 0x3a, 0xe0, 0x87, 0x17, 0xf5, 0xb4, - 0x81, 0xf2, 0x8f, 0x5e, 0x86, 0xf1, 0x69, 0x5e, 0x99, 0x20, 0x4c, 0x13, - 0xf6, 0x45, 0x46, 0x54, 0x8a, 0x96, 0xfb, 0x83, 0xee, 0xd3, 0x18, 0xd3, - 0x75, 0xa0, 0x6f, 0x32, 0x71, 0xde, 0x4c, 0x92, 0x22, 0x06, 0xca, 0xd0, - 0x9e, 0x1b, 0x32, 0xb5, 0xc9, 0x6c, 0x7e, 0x5f, 0xd1, 0x34, 0xfa, 0xb6, - 0x70, 0x8c, 0x7d, 0xcd, 0x68, 0x86, 0xd0, 0xb6, 0x97, 0x6d, 0x78, 0x96, - 0x48, 0x96, 0xe5, 0x28, 0x28, 0x87, 0xe1, 0xa6, 0xcc, 0x7f, 0x9c, 0x44, - 0x2e, 0xa4, 0x86, 0xef, 0xa9, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x64, 0x6b, - 0x75, 0x82, 0x54, 0x0d, 0x16, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x34, 0x00, 0x84, 0x08, - 0x17, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x83, 0xe0, 0x01, 0x3f, 0x41, 0xb7, - 0x59, 0x5c, 0x83, 0xe0, 0x01, 0x3f, 0x59, 0x27, 0x33, 0x2f, 0x22, 0x90, - 0x8f, 0xdf, 0x8f, 0x07, 0xfa, 0xa9, 0xeb, 0x8d, 0x26, 0x20, 0xc7, 0xc6, - 0x2a, 0x20, 0x3a, 0xdc, 0x09, 0xb3, 0xcd, 0x3d, 0x7c, 0x47, 0x10, 0xf5, - 0x62, 0xa0, 0x5b, 0xd8, 0x50, 0xe7, 0x56, 0xcb, 0xa1, 0xb8, 0x02, 0x00, - 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xa1, 0x9c, - 0xa0, 0x45, 0x5c, 0x35, 0x23, 0x76, 0xa8, 0xd0, 0x2d, 0x3f, 0xa5, 0x6d, - 0x7a, 0x4d, 0xe6, 0xc5, 0x95, 0x1d, 0xea, 0xcf, 0xd5, 0x75, 0x93, 0x57, - 0x57, 0xc1, 0x28, 0xc0, 0xb2, 0x8f, 0x42, 0x7f, 0x45, 0xd2, 0x6c, 0xc3, - 0xec, 0xe7, 0x48, 0x15, 0xf5, 0xb1, 0x10, 0xf3, 0xbc, 0x0e, 0x78, 0xef, - 0x2f, 0x15, 0x65, 0x7d, 0xe4, 0x09, 0xb7, 0x34, 0x5b, 0x66, 0x24, 0x0c, - 0x93, 0x63, 0xd8, 0xdc, 0xfd, 0x47, 0x1c, 0xeb, 0x4a, 0xd3, 0x86, 0x57, - 0x49, 0xb7, 0x8e, 0x15, 0x47, 0xa1, 0x61, 0xd8, 0x0a, 0x07, 0xb0, 0x97, - 0x08, 0x48, 0x99, 0x2b, 0x88, 0xcf, 0xe5, 0xe8, 0xd3, 0xda, 0xc2, 0xae, - 0x50, 0xd6, 0xbb, 0x64, 0xbf, 0x7a, 0x1f, 0xc8, 0xbe, 0x29, 0x6e, 0x8d, - 0xf1, 0x18, 0x7c, 0xf7, 0x13, 0x78, 0xf6, 0x23, 0x35, 0x9b, 0xf8, 0xf3, - 0x42, 0x4a, 0x5d, 0xef, 0x7d, 0x20, 0x62, 0x2e, 0xa6, 0xb5, 0xce, 0x94, - 0x0a, 0xfd, 0x8b, 0xf9, 0x12, 0xea, 0x53, 0x13, 0x45, 0x9d, 0xdd, 0x66, - 0x7d, 0x42, 0xb2, 0x3f, 0x65, 0xc4, 0x0d, 0xf8, 0x6d, 0xda, 0x0e, 0xe6, - 0x45, 0x35, 0xd4, 0x90, 0xc3, 0x9b, 0x8b, 0xb4, 0x39, 0xf1, 0x4f, 0x70, - 0x4a, 0x7f, 0x51, 0x1d, 0x3d, 0x80, 0x95, 0x4b, 0xd2, 0xb0, 0xd7, 0xb7, - 0xfe, 0xa8, 0x40, 0x38, 0x95, 0x48, 0x27, 0xf8, 0x23, 0xb9, 0xb0, 0xfe, - 0x58, 0x3a, 0x8e, 0x1a, 0x53, 0xf3, 0xa4, 0x59, 0xf9, 0xba, 0x9d, 0x9d, - 0x24, 0x8b, 0xe6, 0x39, 0xc1, 0xaf, 0x86, 0xdc, 0xf7, 0x27, 0x0d, 0x0b, - 0x85, 0xc4, 0x9d, 0x25, 0xb8, 0x81, 0xd4, 0x5d, 0xc2, 0x6a, 0xe4, 0x96, - 0x42, 0x87, 0xaa, 0x67, 0x17, 0xe1, 0x23, 0xa1, 0x32, 0x62, 0xa2, 0x65, - 0x69, 0x63, 0x68, 0x61, 0x74, 0x64, 0x6b, 0x75, 0x00, 0x00, 0x00, 0x1f, - 0x7d, 0x89, 0x47, 0x47, 0xf5, 0xb7, 0xed, 0xb4, 0x95, 0xd6, 0x75, 0x78, - 0xeb, 0x1d, 0x4e, 0xa4, 0x3c, 0x47, 0x73, 0x5e, 0x8d, 0xd2, 0xd4, 0x7c, - 0xc6, 0x32, 0x4b, 0x5d, 0xc7, 0x78, 0xa2, 0xc7, 0xbd, 0xca, 0x06, 0x92, - 0xf9, 0xba, 0x4d, 0x7d, 0xe3, 0xe0, 0xf8, 0x0a, 0xec, 0x73, 0x88, 0xb6, - 0xab, 0x6d, 0x37, 0x6d, 0x37, 0xd2, 0xa5, 0x3d, 0xa8, 0xd0, 0x47, 0x7b, - 0xa1, 0x58, 0xf7, 0x07, 0x73, 0x23, 0x49, 0xfb, 0xa0, 0x7e, 0xae, 0x30, - 0x88, 0x4c, 0x2b, 0x75, 0x91, 0xd7, 0xe3, 0x5d, 0x80, 0x06, 0x12, 0xcc, - 0xb4, 0xe9, 0xdc, 0xc6, 0x01, 0x48, 0x91, 0x2a, 0x38, 0x93, 0x26, 0xee, - 0x01, 0x8a, 0xad, 0xdb, 0x02, 0xdc, 0x54, 0x5a, 0x08, 0x18, 0xf8, 0xe1, - 0xc2, 0x63, 0x80, 0x13, 0xd4, 0x4c, 0x06, 0xf0, 0x1d, 0x60, 0x66, 0x75, - 0x25, 0x43, 0xb9, 0xa1, 0x2b, 0xc7, 0x54, 0x81, 0x91, 0x2d, 0x66, 0xb2, - 0x74, 0xe7, 0x90, 0x8e, 0xd4, 0x03, 0xca, 0xef, 0x9a, 0x13, 0xfe, 0x40, - 0xf8, 0x42, 0x77, 0x52, 0x5b, 0xae, 0x22, 0xd0, 0x6b, 0xb6, 0x77, 0x41, - 0xff, 0x96, 0x80, 0xbc, 0x8f, 0xfa, 0xa1, 0xb6, 0xe4, 0xf1, 0x93, 0x1d, - 0x91, 0x96, 0x7b, 0x84, 0xc7, 0x60, 0x7e, 0x80, 0x98, 0xcd, 0x7b, 0x12, - 0x11, 0x41, 0x90, 0x33, 0x96, 0xc0, 0xeb, 0x6b, 0x9f, 0xb4, 0x1a, 0x2c, - 0x46, 0x80, 0xf0, 0x56, 0xe2, 0x4b, 0x32, 0x3c, 0x6a, 0xa1, 0x94, 0xca, - 0x46, 0xb4, 0x06, 0x63, 0x85, 0xcf, 0x62, 0x20, 0x79, 0xf2, 0x03, 0x97, - 0xa0, 0xa0, 0x44, 0x7b, 0x8e, 0x39, 0x16, 0xca, 0xe0, 0xb2, 0x04, 0x79, - 0xf8, 0x55, 0xf7, 0xe6, 0x3c, 0x3f, 0x67, 0x2f, 0x2b, 0x75, 0x39, 0x55, - 0x12, 0xd5, 0x85, 0xd4, 0x22, 0x37, 0xb6, 0x8c, 0x40, 0x47, 0x51, 0x11, - 0x88, 0xa1, 0xfa, 0x8f, 0x2d, 0x43, 0x41, 0x0a, 0x58, 0xe3, 0x38, 0x94, - 0xa0, 0xe1, 0xda, 0x1e, 0x7b, 0x07, 0x74, 0xc5, 0xe4, 0xd1, 0xb7, 0x3f, - 0xed, 0x46, 0x1e, 0x35, 0x84, 0x7c, 0x58, 0x3d, 0xc3, 0x99, 0x9f, 0x3f, - 0x0e, 0x30, 0x4f, 0xd5, 0xf4, 0x5d, 0x09, 0xef, 0x01, 0xe3, 0xa3, 0xbc, - 0x17, 0x74, 0xa4, 0x28, 0x5f, 0xab, 0xe5, 0x71, 0x66, 0x34, 0x2e, 0x29, - 0x2a, 0x24, 0xbb, 0x6d, 0x41, 0x16, 0x76, 0x86, 0x15, 0x67, 0xb5, 0x07, - 0x60, 0x13, 0xd2, 0x11, 0xa6, 0x90, 0x22, 0xc4, 0x17, 0x76, 0x38, 0x3a, - 0xaf, 0x51, 0xee, 0x4c, 0x9b, 0xfa, 0x84, 0x25, 0xd9, 0x6d, 0xd3, 0x8d, - 0x3e, 0xb2, 0x95, 0xd7, 0x8a, 0x83, 0x19, 0xaf, 0x7a, 0x2f, 0x6b, 0x87, - 0x36, 0x9e, 0xa3, 0x48, 0xdd, 0x8e, 0xe0, 0xdc, 0x40, 0xf3, 0xb7, 0xb4, - 0x3f, 0x95, 0x70, 0x5b, 0x67, 0xf7, 0xa1, 0xe9, 0x91, 0x7a, 0x94, 0xd1, - 0x81, 0xcc, 0xeb, 0x55, 0xb7, 0xc6, 0xd9, 0x0d, 0x59, 0x4a, 0x9f, 0x37, - 0x06, 0x6a, 0xda, 0x4e, 0xd3, 0xef, 0x35, 0x18, 0xa3, 0x90, 0x19, 0x72, - 0x2e, 0xcd, 0x03, 0x61, 0xf7, 0xb2, 0x0f, 0x69, 0x50, 0x47, 0x2f, 0xb3, - 0x10, 0x4a, 0xb1, 0x5d, 0xe8, 0x5a, 0x36, 0x07, 0xd6, 0x95, 0x03, 0x17, - 0x50, 0x1f, 0xa2, 0x58, 0x01, 0x0d, 0xfc, 0x8d, 0xcc, 0xf2, 0x6c, 0x4d, - 0x2f, 0x58, 0x02, 0xb6, 0x5e, 0x7c, 0x6f, 0x47, 0x3e, 0x13, 0x62, 0x33, - 0xc3, 0x7f, 0x64, 0x88, 0x30, 0x45, 0x5a, 0x6a, 0x8f, 0x49, 0x9a, 0xd1, - 0x6e, 0xf4, 0x3a, 0x3a, 0x9b, 0x50, 0x50, 0x8b, 0x59, 0x36, 0xbc, 0x0c, - 0x2c, 0x73, 0xec, 0x21, 0x0c, 0x95, 0xca, 0x32, 0x28, 0x07, 0x85, 0x91, - 0x0a, 0x90, 0xfe, 0x5a, 0x9d, 0x11, 0x09, 0xa2, 0x38, 0x9b, 0x0f, 0x22, - 0xc1, 0x44, 0x09, 0xca, 0x50, 0xe0, 0x4e, 0x01, 0x24, 0xef, 0x8a, 0x58, - 0xa5, 0x56, 0x69, 0x9b, 0x2e, 0x72, 0xf5, 0xb2, 0xbe, 0xa3, 0xca, 0x84, - 0x36, 0x36, 0x84, 0xb0, 0x88, 0x88, 0x74, 0x60, 0xc3, 0xf2, 0x6b, 0x19, - 0x44, 0xb6, 0x8b, 0x02, 0x38, 0x7d, 0x6e, 0x26, 0x89, 0x37, 0xae, 0xc5, - 0x67, 0x9c, 0x4e, 0x5b, 0xeb, 0x68, 0xc1, 0x3a, 0xb9, 0x10, 0xad, 0x10, - 0x00, 0x1f, 0x6a, 0x9a, 0xfe, 0x6a, 0x7e, 0x03, 0xcc, 0x7d, 0x0d, 0x37, - 0xea, 0x91, 0xfa, 0xf4, 0xdb, 0x22, 0x9b, 0x91, 0x70, 0x07, 0x6d, 0xa8, - 0xd6, 0x95, 0x49, 0x66, 0xd6, 0xbc, 0xd1, 0x57, 0x6e, 0xa5, 0x1c, 0x96, - 0x16, 0xaf, 0x94, 0xa5, 0x00, 0x06, 0x38, 0x55, 0xe9, 0xdc, 0xb8, 0x38, - 0x66, 0x26, 0x2d, 0xac, 0x1a, 0xff, 0x95, 0x52, 0xa3, 0x97, 0x58, 0xd9, - 0xe9, 0x35, 0x54, 0x3d, 0x6a, 0xae, 0xe6, 0xcd, 0x00, 0xbe, 0x68, 0x83, - 0x05, 0x5a, 0x65, 0xb8, 0x8c, 0x94, 0x87, 0x6c, 0x27, 0x82, 0x7b, 0x4a, - 0x48, 0x1e, 0x6e, 0x42, 0xc1, 0xe5, 0xd8, 0x25, 0x9b, 0x8a, 0xe4, 0x2b, - 0x85, 0x6f, 0x40, 0x75, 0x65, 0x9e, 0xc5, 0x03, 0xd1, 0x14, 0x82, 0x91, - 0x15, 0x59, 0x66, 0x48, 0x13, 0xfe, 0xd3, 0x17, 0x1e, 0xff, 0xec, 0x58, - 0x43, 0xb5, 0xb9, 0xbf, 0xad, 0x33, 0xb2, 0x91, 0xe2, 0xb5, 0x3b, 0x57, - 0xd6, 0xb1, 0x55, 0x6c, 0xa2, 0xac, 0x7f, 0x5e, 0x9b, 0x28, 0xa7, 0x98, - 0x44, 0x46, 0x1d, 0x30, 0x16, 0x2f, 0xa5, 0x35, 0x85, 0x68, 0xaa, 0x92, - 0x0f, 0x51, 0xb3, 0x88, 0x42, 0xf3, 0x8d, 0xa0, 0x06, 0x8f, 0x91, 0xcf, - 0xf4, 0x8f, 0xbc, 0x95, 0xb1, 0x57, 0xa5, 0x61, 0xd9, 0x1e, 0x40, 0x29, - 0x79, 0x63, 0x84, 0xfd, 0xf5, 0x93, 0xd4, 0x5b, 0xb9, 0xdf, 0x5d, 0x56, - 0xc5, 0xfb, 0xcb, 0xee, 0x1f, 0x3b, 0x9c, 0x02, 0x0c, 0x7d, 0x7f, 0xbb, - 0x81, 0x8d, 0xbb, 0xa5, 0x83, 0x5c, 0x4f, 0xf1, 0x08, 0xf8, 0x18, 0x87, - 0xab, 0x74, 0x5c, 0xa7, 0x57, 0xa8, 0xcf, 0xf4, 0x2f, 0xcc, 0xd2, 0xcc, - 0x5b, 0x99, 0x00, 0xbc, 0xe5, 0x06, 0x42, 0x24, 0xc9, 0xf0, 0x23, 0x45, - 0x60, 0xf1, 0x34, 0xb0, 0x99, 0xb4, 0x24, 0x94, 0x71, 0x76, 0x16, 0x32, - 0x2d, 0xb5, 0x98, 0x38, 0x9e, 0x02, 0xe4, 0x1b, 0xc9, 0x3f, 0x20, 0xa3, - 0x94, 0xc2, 0x4c, 0xff, 0x81, 0x95, 0x05, 0xd5, 0x8c, 0x13, 0xd2, 0xb8, - 0x54, 0xf5, 0x55, 0xff, 0x4a, 0xfa, 0xd0, 0x93, 0xa7, 0x49, 0x5f, 0x43, - 0x6d, 0x23, 0x3e, 0x5f, 0x37, 0xb1, 0x05, 0xb1, 0xc7, 0x99, 0xb5, 0xab, - 0xbe, 0x04, 0x65, 0xef, 0xb0, 0x79, 0x62, 0x47, 0xbc, 0x7b, 0x57, 0x74, - 0xea, 0xac, 0x2d, 0x45, 0xfc, 0x65, 0x26, 0x3d, 0xf7, 0x91, 0x0e, 0xbd, - 0x78, 0x78, 0x72, 0x6b, 0x8a, 0xfe, 0x8d, 0x6e, 0x03, 0x6d, 0x0c, 0x3a, - 0x52, 0xb5, 0xc4, 0x9c, 0x7d, 0x82, 0xdd, 0x52, 0x75, 0xb7, 0xe3, 0xe3, - 0xff, 0xfc, 0x31, 0xa9, 0xc6, 0xd7, 0xa4, 0x1d, 0x05, 0xde, 0x8b, 0x82, - 0x1d, 0x7d, 0xd0, 0xb3, 0x25, 0xcc, 0x45, 0xce, 0x8e, 0x4c, 0x2b, 0xca, - 0x60, 0x15, 0x6c, 0xba, 0x5d, 0x6b, 0x41, 0x22, 0x62, 0x05, 0xef, 0x55, - 0x04, 0x84, 0x2e, 0x14, 0xe6, 0x5e, 0x23, 0x83, 0x82, 0x39, 0xbe, 0x79, - 0xd1, 0x29, 0xe3, 0xac, 0x54, 0x63, 0x03, 0xf9, 0xa0, 0xb7, 0xb7, 0xd4, - 0x37, 0xdc, 0x91, 0xfc, 0x1e, 0x96, 0xe9, 0xcc, 0x66, 0x6b, 0xa4, 0x67, - 0xb8, 0xc8, 0xed, 0x69, 0x4f, 0x08, 0xa2, 0xaf, 0x34, 0x3b, 0xcb, 0x70, - 0xf2, 0x8c, 0xae, 0xc9, 0x2e, 0x96, 0xe3, 0x47, 0x31, 0x36, 0x13, 0x62, - 0xc8, 0xcc, 0x18, 0x7f, 0x48, 0xea, 0x2e, 0xf4, 0x87, 0x09, 0xa2, 0x68, - 0x19, 0xf7, 0x30, 0x8b, 0x72, 0x65, 0xa6, 0x9f, 0xf3, 0x96, 0x22, 0x68, - 0x59, 0x72, 0x69, 0x2f, 0xdd, 0x88, 0x4c, 0x04, 0xd2, 0xb9, 0x71, 0x0c, - 0xd7, 0x2d, 0xd7, 0xef, 0xce, 0x33, 0x7f, 0x5a, 0xe7, 0x80, 0xba, 0x85, - 0xc0, 0xd3, 0x83, 0x27, 0xe9, 0x11, 0x40, 0x67, 0xb7, 0xf7, 0x8f, 0x8e, - 0x8f, 0x93, 0x7d, 0xfb, 0x04, 0x0f, 0x1e, 0x6d, 0xd7, 0xa9, 0xc6, 0x53, - 0x29, 0x58, 0x55, 0xe5, 0x2d, 0xe1, 0x05, 0xe3, 0x00, 0x3b, 0x6f, 0xb9, - 0xdd, 0x5f, 0x42, 0x47, 0x0a, 0x79, 0x43, 0xef, 0x84, 0x47, 0x6d, 0x37, - 0xba, 0x37, 0xb3, 0xef, 0xae, 0x0b, 0xc9, 0x45, 0x32, 0x1a, 0x9a, 0x94, - 0x3f, 0xb8, 0xc7, 0x72, 0xd8, 0x90, 0xb1, 0x61, 0x62, 0xe0, 0x0f, 0xd1, - 0xef, 0x94, 0x04, 0x2f, 0xff, 0xd6, 0x7e, 0x14, 0x81, 0xb8, 0x62, 0xcc, - 0x4e, 0x76, 0x0a, 0xc6, 0x1f, 0x58, 0x51, 0xa1, 0x14, 0xe8, 0xde, 0x2f, - 0xe6, 0x2e, 0xb2, 0xe2, 0xda, 0x24, 0x47, 0xe1, 0xcf, 0x26, 0x2a, 0xfc, - 0xb1, 0xbf, 0xae, 0x1a, 0xb0, 0x4d, 0x3d, 0x97, 0x4d, 0x18, 0xfb, 0x0d, - 0x00, 0x64, 0x40, 0x75, 0x6a, 0x78, 0x3a, 0x60, 0xda, 0x54, 0x06, 0x92, - 0xb6, 0xa9, 0x1c, 0x36, 0xeb, 0x26, 0x46, 0x10, 0x0d, 0x5d, 0x3e, 0x13, - 0xca, 0x7e, 0xb1, 0xbb, 0xa7, 0x37, 0x71, 0x7c, 0x09, 0xd4, 0x5d, 0xd4, - 0x59, 0xb0, 0x46, 0x37, 0x06, 0x2a, 0xdb, 0xd3, 0x0c, 0x26, 0x0a, 0x9d, - 0x18, 0x65, 0x8a, 0xb4, 0xf1, 0x1b, 0xfd, 0x50, 0x32, 0x6a, 0xa9, 0x2f, - 0x0c, 0x46, 0x1f, 0x9b, 0x50, 0x86, 0xf1, 0x91, 0xf0, 0xe0, 0xc2, 0x8d, - 0x84, 0x8e, 0xfe, 0x6d, 0x1e, 0x6e, 0xd4, 0x93, 0xf1, 0x56, 0x4b, 0x3b, - 0x20, 0x10, 0x1f, 0x6a, 0xc5, 0xf3, 0x8c, 0x2f, 0x88, 0x32, 0x28, 0xbe, - 0x05, 0x9a, 0x1b, 0x7d, 0x1b, 0xaa, 0x2d, 0xa5, 0xe4, 0x82, 0xd0, 0xf3, - 0x65, 0x5a, 0xd5, 0xa5, 0x3e, 0xdd, 0xee, 0x98, 0x03, 0xf4, 0x63, 0x6e, - 0xe5, 0x60, 0x35, 0x54, 0xf9, 0xf8, 0x5c, 0x8c, 0x02, 0x5f, 0xa5, 0xf3, - 0xb2, 0xf8, 0x47, 0xce, 0x74, 0xbc, 0xf5, 0xcc, 0x1e, 0x0f, 0x8b, 0x6f, - 0x1f, 0xd3, 0x11, 0x2d, 0x10, 0x40, 0x5d, 0xb2, 0x45, 0x6f, 0xd3, 0xc3, - 0x44, 0xc5, 0x74, 0xab, 0x29, 0x2f, 0x4c, 0x7e, 0xc8, 0x57, 0xcb, 0xaf, - 0x0b, 0x44, 0x12, 0xa2, 0x1d, 0x3b, 0x1c, 0xfa, 0xf5, 0xd3, 0xe6, 0x75, - 0x4e, 0xc7, 0x04, 0x99, 0xd8, 0x32, 0x14, 0x83, 0xda, 0x35, 0xf0, 0xfa, - 0x67, 0x15, 0x8d, 0xab, 0xa9, 0x30, 0x12, 0xd0, 0x4a, 0xb6, 0x09, 0x20, - 0x89, 0x19, 0xee, 0x60, 0x4b, 0x97, 0xd2, 0x38, 0x2a, 0x57, 0x36, 0x22, - 0xe9, 0x02, 0x2f, 0x2d, 0x30, 0x93, 0x88, 0x14, 0x99, 0xa3, 0x31, 0x93, - 0x2a, 0x33, 0x58, 0xae, 0xe6, 0xe6, 0xcc, 0x89, 0x02, 0x95, 0x52, 0xe3, - 0x60, 0xed, 0xd5, 0x9d, 0xac, 0x7f, 0x1f, 0x35, 0x54, 0xd6, 0x89, 0x8e, - 0xed, 0x13, 0x7f, 0xe6, 0xce, 0xba, 0xe7, 0x00, 0x30, 0x7f, 0x46, 0x25, - 0xdc, 0xb3, 0x22, 0xac, 0xef, 0x54, 0xef, 0x17, 0xf8, 0xdc, 0xc4, 0x12, - 0xdb, 0x40, 0xe8, 0x20, 0x7a, 0x1b, 0x5a, 0x6b, 0x37, 0x8d, 0x46, 0xfd, - 0x26, 0xa5, 0x1f, 0x24, 0xb3, 0xaa, 0xe4, 0xb6, 0x1c, 0x93, 0xd9, 0x77, - 0xc2, 0x66, 0xf7, 0x0a, 0xf8, 0xca, 0xa1, 0xfb, 0xa6, 0x78, 0x9c, 0xc3, - 0x7f, 0x40, 0x63, 0x9a, 0x98, 0x52, 0x23, 0xb2, 0x51, 0x0f, 0xab, 0xf2, - 0xa0, 0x41, 0x87, 0x79, 0x18, 0x2e, 0x50, 0x8a, 0x6a, 0x99, 0xc7, 0xef, - 0x0c, 0x33, 0xee, 0xf2, 0x76, 0x26, 0x40, 0x4b, 0xb7, 0x75, 0xb0, 0x8c, - 0x99, 0x8c, 0x96, 0x8a, 0xc3, 0xb6, 0xfd, 0xa2, 0x62, 0x49, 0x29, 0x8c, - 0xc4, 0xfe, 0xc8, 0xe9, 0x89, 0xeb, 0xc7, 0x59, 0x08, 0x99, 0xd3, 0x73, - 0xea, 0x64, 0x50, 0x9d, 0x09, 0x36, 0xe3, 0x85, 0xc4, 0xac, 0x3e, 0x87, - 0x11, 0x5d, 0xf4, 0x5b, 0x21, 0x91, 0xf6, 0x34, 0xfb, 0x08, 0x15, 0xd2, - 0xe1, 0xcb, 0x8c, 0x72, 0xca, 0x88, 0xd6, 0xb1, 0x65, 0xd4, 0xd7, 0x6e, - 0x10, 0x7b, 0x15, 0x0f, 0x41, 0xd7, 0x12, 0x49, 0xcc, 0x8d, 0x39, 0x13, - 0x9c, 0x22, 0x1d, 0x15, 0x43, 0xc1, 0x8a, 0x6f, 0xf3, 0x1d, 0x46, 0x74, - 0xb3, 0x1f, 0xa4, 0xbd, 0x17, 0x20, 0x69, 0x57, 0x53, 0x2c, 0x6a, 0xec, - 0x29, 0xac, 0x02, 0xb1, 0x47, 0x83, 0xf0, 0x2f, 0xc9, 0x20, 0xcc, 0x14, - 0xf0, 0xe4, 0x4f, 0x43, 0xe1, 0x98, 0x3d, 0xbd, 0x2c, 0x48, 0x7f, 0xd5, - 0xd6, 0x33, 0x98, 0xd2, 0x9d, 0xa8, 0xe0, 0xb1, 0x85, 0xe0, 0x14, 0x96, - 0xec, 0xde, 0x18, 0xc4, 0xe9, 0x8f, 0x67, 0x24, 0x48, 0x6c, 0xf9, 0xaf, - 0xfb, 0x89, 0xd1, 0x35, 0xc9, 0x0d, 0xe9, 0x22, 0x08, 0xef, 0x8b, 0x27, - 0x9d, 0x18, 0xa1, 0x19, 0x7d, 0x20, 0xd1, 0xc1, 0x1b, 0x99, 0x59, 0xea, - 0xba, 0xae, 0xe4, 0x09, 0xd4, 0xb6, 0x23, 0x08, 0x5f, 0x0c, 0x0b, 0x49, - 0x69, 0x8a, 0x36, 0x02, 0xf5, 0x32, 0x3e, 0xfb, 0xb4, 0xdb, 0x45, 0x9d, - 0x19, 0x9d, 0x4b, 0xcf, 0xee, 0xa7, 0xbc, 0x5a, 0x06, 0x4e, 0x43, 0x52, - 0xd3, 0xd2, 0x4a, 0x0e, 0x21, 0x08, 0xd6, 0xc0, 0x93, 0x7d, 0xe8, 0xff, - 0x04, 0xd4, 0xef, 0xe8, 0x0d, 0xd1, 0xe7, 0x74, 0xf2, 0x56, 0x66, 0x51, - 0x4c, 0x79, 0xf4, 0x12, 0x9f, 0xf4, 0xd2, 0x61, 0x12, 0x60, 0xc2, 0xfb, - 0x98, 0x5c, 0xed, 0x73, 0x13, 0x06, 0xa7, 0xce, 0x86, 0xea, 0x65, 0x26, - 0xc0, 0xfc, 0xe6, 0xc1, 0xdb, 0xe0, 0xcc, 0x13, 0xd3, 0x63, 0x5f, 0x2d, - 0xfb, 0x5a, 0x95, 0x9e, 0x27, 0x05, 0x3d, 0xd0, 0x1b, 0xaf, 0x29, 0x79, - 0x70, 0x69, 0x12, 0xc7, 0xe6, 0xc2, 0x57, 0x40, 0x31, 0xcb, 0x50, 0xd4, - 0xfe, 0xf3, 0xb1, 0x3e, 0x79, 0xdb, 0xcf, 0xdd, 0x9a, 0x86, 0x2a, 0x58, - 0xb3, 0x51, 0xe6, 0x74, 0x9f, 0x1e, 0xbd, 0xb1, 0x57, 0xd8, 0xa9, 0xe8, - 0xbf, 0x5e, 0x15, 0xcf, 0x2c, 0x4b, 0x00, 0x88, 0x8d, 0x10, 0x15, 0x25, - 0xeb, 0x36, 0xe6, 0x4b, 0x9c, 0xe5, 0x82, 0x26, 0x6e, 0x61, 0xb3, 0x69, - 0xf4, 0x4c, 0x21, 0x15, 0x64, 0x36, 0x0c, 0x8e, 0x77, 0xc1, 0x89, 0xd5, - 0xfd, 0xb0, 0x81, 0x7c, 0x90, 0x7d, 0xdf, 0xd3, 0xe5, 0xc9, 0xd8, 0x4f, - 0xc5, 0x85, 0x12, 0xb7, 0x02, 0x63, 0xb7, 0x24, 0x2c, 0xeb, 0xb5, 0x89, - 0x59, 0x44, 0x2b, 0xa3, 0x8e, 0xfd, 0x42, 0x48, 0x57, 0x57, 0x17, 0x71, - 0xec, 0xe0, 0x0e, 0x72, 0xfc, 0x6c, 0xa2, 0xa5, 0xfb, 0xd3, 0x17, 0xb7, - 0x1a, 0x19, 0xe4, 0x93, 0x22, 0x4d, 0xde, 0x22, 0x4f, 0xb8, 0x42, 0x3a, - 0x06, 0xa7, 0x35, 0x20, 0x57, 0xc4, 0xe6, 0x0c, 0x7f, 0xae, 0x59, 0xfe, - 0xe6, 0xe7, 0x17, 0x0c, 0xec, 0x33, 0x4d, 0x6e, 0x0a, 0xd8, 0x6e, 0xe2, - 0x27, 0x39, 0x3e, 0x32, 0x1b, 0xf8, 0x9d, 0xd5, 0xdb, 0x38, 0xee, 0xe6, - 0x58, 0xbf, 0xfa, 0x05, 0xc0, 0x7e, 0xf1, 0x70, 0x43, 0x8d, 0xc5, 0x5f, - 0xd1, 0xb8, 0x5f, 0xe2, 0xb4, 0xd7, 0x81, 0xd7, 0x04, 0x8d, 0x06, 0x99, - 0x7f, 0x0b, 0x87, 0xea, 0xe3, 0x9a, 0x51, 0xd4, 0xd4, 0x47, 0xeb, 0x29, - 0x98, 0x56, 0xa7, 0x2f, 0x07, 0xa3, 0x04, 0x88, 0xe9, 0x13, 0x4f, 0xac, - 0x0f, 0x29, 0xda, 0xc7, 0x53, 0x2c, 0x9d, 0x00, 0x7a, 0x9e, 0x7a, 0x74, - 0xac, 0xce, 0xf2, 0xfa, 0xe6, 0xd5, 0xa2, 0x0c, 0xab, 0x80, 0xa9, 0x9f, - 0x46, 0x39, 0xe6, 0x8c, 0xc8, 0xf3, 0x90, 0xca, 0x9e, 0xb6, 0xdd, 0x0c, - 0xf9, 0xe6, 0x8c, 0x83, 0x46, 0xb0, 0x12, 0xe3, 0x47, 0xba, 0x12, 0x7b, - 0xf5, 0xb7, 0xe6, 0x49, 0x8c, 0x78, 0x45, 0xc2, 0xa3, 0x7a, 0xdf, 0x47, - 0xa9, 0x80, 0x41, 0x03, 0x29, 0x7f, 0xeb, 0xa1, 0xa8, 0x4b, 0x4f, 0xa8, - 0x41, 0x57, 0xb9, 0xfe, 0x06, 0xa9, 0xce, 0xbc, 0x27, 0x81, 0xed, 0x1b, - 0xab, 0x19, 0x4a, 0xbf, 0x6b, 0xe0, 0xef, 0x58, 0xfb, 0xfa, 0xe3, 0xa1, - 0x85, 0x02, 0x0d, 0x57, 0x9b, 0x04, 0x2b, 0xc0, 0x8e, 0x21, 0x73, 0xdc, - 0x34, 0x21, 0x63, 0x1d, 0xaf, 0xd8, 0xe0, 0x42, 0xaa, 0x45, 0xe9, 0x3c, - 0x44, 0xc5, 0x22, 0x77, 0xc0, 0xe5, 0xa5, 0xf7, 0xa4, 0x83, 0x66, 0xad, - 0xc7, 0x4a, 0x32, 0xc6, 0x7e, 0xca, 0x8f, 0x35, 0xa7, 0x88, 0x64, 0x56, - 0x45, 0x25, 0xec, 0xfa, 0x85, 0x61, 0x34, 0x0d, 0x83, 0x92, 0x1e, 0xf0, - 0x58, 0x4c, 0x47, 0x93, 0xe5, 0x17, 0xaa, 0xe8, 0x22, 0x53, 0xa6, 0x9e, - 0x3d, 0xb1, 0x47, 0x25, 0x09, 0x93, 0x93, 0x9d, 0x08, 0x31, 0x5b, 0xdc, - 0x07, 0x1f, 0x82, 0xbc, 0x88, 0x31, 0xbd, 0xc3, 0xa6, 0x4d, 0x2a, 0xed, - 0xf9, 0xc2, 0x76, 0x1e, 0xa1, 0xfd, 0xca, 0x7e, 0xcd, 0x62, 0x83, 0x06, - 0xca, 0xf3, 0x13, 0xcd, 0x25, 0xa1, 0x45, 0x0c, 0x3a, 0xc3, 0xb1, 0x3b, - 0xf5, 0xa1, 0x12, 0x1e, 0x90, 0xff, 0xf6, 0x56, 0x06, 0x7b, 0x14, 0xb7, - 0x37, 0x5c, 0x7a, 0xe9, 0x7e, 0xca, 0x33, 0x05, 0xc0, 0x7c, 0xa7, 0xcd, - 0xb2, 0x11, 0x2a, 0x0c, 0xe7, 0x2b, 0x36, 0x11, 0x5f, 0xa6, 0xba, 0xc5, - 0x56, 0x6f, 0x7c, 0xb7, 0x8c, 0xee, 0x54, 0xa0, 0x8c, 0x59, 0x85, 0x22, - 0x98, 0xad, 0xbb, 0x93, 0x66, 0x23, 0xfa, 0x00, 0x81, 0x88, 0xb0, 0x0a, - 0x1d, 0xfb, 0x66, 0xa2, 0x14, 0x88, 0x2a, 0x4e, 0x41, 0xb4, 0x89, 0x91, - 0x6d, 0x73, 0x5a, 0x3c, 0x4f, 0xc9, 0xd3, 0xa3, 0x08, 0x10, 0xe0, 0xb2, - 0xc2, 0xda, 0xa1, 0x23, 0x91, 0x40, 0x92, 0x51, 0xa0, 0xf4, 0x92, 0x01, - 0xb1, 0xa7, 0xd1, 0x80, 0x1d, 0xf0, 0x30, 0x29, 0xed, 0x0b, 0xec, 0x80, - 0x02, 0x09, 0x4e, 0x8d, 0x3f, 0xdf, 0x7a, 0x53, 0xcf, 0xed, 0xad, 0x6c, - 0x1b, 0x9c, 0x6a, 0x25, 0xff, 0xc3, 0xd7, 0xe9, 0x99, 0xf8, 0xa6, 0x8d, - 0x3f, 0x4a, 0x17, 0xf1, 0xe4, 0x54, 0x2b, 0x55, 0x67, 0x4a, 0xd2, 0xee, - 0x29, 0x53, 0x44, 0x71, 0x87, 0x6c, 0x98, 0xef, 0x8f, 0x23, 0x06, 0xf5, - 0x56, 0x9d, 0x12, 0x1f, 0x9c, 0xe5, 0x22, 0x51, 0x6e, 0x5b, 0x41, 0x7e, - 0x89, 0x6f, 0x40, 0x4b, 0xd6, 0x81, 0xd1, 0x7f, 0x63, 0xd1, 0x3f, 0xa1, - 0x60, 0xe2, 0xe4, 0x01, 0x7b, 0x76, 0x86, 0xf5, 0x13, 0x4f, 0xa2, 0x50, - 0xaf, 0xc8, 0x74, 0xe3, 0x2f, 0x7a, 0xd0, 0x81, 0x3e, 0xcf, 0xfa, 0x31, - 0xeb, 0xc0, 0xc3, 0x07, 0xc7, 0xe8, 0xb2, 0x9a, 0x51, 0xb9, 0xf7, 0x98, - 0x55, 0x90, 0xce, 0xdd, 0x60, 0xac, 0xc9, 0x08, 0x5e, 0xe8, 0xae, 0xad, - 0x22, 0xed, 0x73, 0x29, 0xa1, 0x5f, 0x43, 0x27, 0x2f, 0xb9, 0x38, 0x78, - 0x9d, 0x32, 0x1f, 0xff, 0xe0, 0xf7, 0x77, 0x37, 0xdf, 0xd1, 0xcb, 0xf7, - 0x50, 0xcd, 0x4a, 0xe9, 0xdd, 0x21, 0x50, 0xa0, 0xf2, 0x7f, 0x73, 0x31, - 0xae, 0xfb, 0x6e, 0xb7, 0x99, 0x1a, 0x43, 0x16, 0x5a, 0x17, 0x3a, 0x77, - 0xf1, 0xc3, 0xa8, 0x33, 0xde, 0xc6, 0x5b, 0xe8, 0x59, 0x53, 0x19, 0xf9, - 0x7f, 0xc5, 0x20, 0x56, 0xfc, 0x99, 0x19, 0x38, 0x77, 0x92, 0xe4, 0x7c, - 0xf3, 0x96, 0xac, 0x22, 0x87, 0x16, 0x5d, 0x43, 0x43, 0x65, 0x4e, 0x46, - 0x45, 0x44, 0x2d, 0x3f, 0x7f, 0x9d, 0xf0, 0x0c, 0x0e, 0x5b, 0xf7, 0x5b, - 0x31, 0x71, 0xcd, 0x27, 0x5b, 0xa3, 0x4a, 0x7a, 0xef, 0x28, 0x1c, 0x9a, - 0x98, 0x26, 0x95, 0xda, 0x35, 0x8d, 0x0d, 0xce, 0x04, 0xa2, 0xed, 0x8a, - 0xbb, 0x46, 0xf7, 0xca, 0x2b, 0x92, 0xd7, 0x8d, 0xae, 0x1b, 0xf1, 0xe4, - 0x9d, 0x67, 0x5b, 0x03, 0x57, 0xd1, 0xf6, 0x1e, 0x8f, 0x03, 0x7d, 0x8d, - 0xb8, 0x4a, 0x74, 0x99, 0x0f, 0x76, 0x3d, 0xe7, 0xb3, 0x4f, 0xdb, 0x9f, - 0x5c, 0xa7, 0x1b, 0x23, 0xa7, 0x99, 0x48, 0x34, 0x65, 0x46, 0x32, 0x83, - 0xc8, 0xcb, 0xee, 0xb3, 0xab, 0xe8, 0x99, 0xc9, 0x8a, 0x50, 0x34, 0x15, - 0x13, 0x52, 0xda, 0x12, 0xbd, 0x20, 0x21, 0x41, 0x57, 0x2a, 0xa0, 0x2c, - 0xba, 0x6c, 0xa9, 0xed, 0xcb, 0x03, 0xc9, 0x10, 0x26, 0x9d, 0x31, 0x52, - 0xf2, 0x66, 0x88, 0x2e, 0x51, 0x80, 0x76, 0xc9, 0xce, 0xfb, 0x8a, 0x4a, - 0x10, 0x8c, 0x83, 0x34, 0xe9, 0x02, 0xfc, 0x4e, 0xfe, 0xaa, 0x6c, 0xd6, - 0xcc, 0x81, 0x5d, 0x45, 0xc8, 0xa6, 0xa0, 0x3a, 0xef, 0xa4, 0xc5, 0xf1, - 0xba, 0x32, 0x93, 0x12, 0x2b, 0x59, 0x68, 0x19, 0x21, 0xe8, 0xd2, 0x8f, - 0x1d, 0x38, 0xd3, 0x56, 0x54, 0x38, 0x1d, 0xbb, 0xa0, 0x69, 0xe4, 0x82, - 0xfc, 0x21, 0x55, 0xee, 0xf8, 0x84, 0x7b, 0xab, 0x5e, 0x83, 0x42, 0x7e, - 0x18, 0xab, 0x3b, 0x1b, 0xea, 0x0e, 0xa0, 0xbd, 0x74, 0x33, 0x6d, 0x8a, - 0xe6, 0x7f, 0xe9, 0x78, 0xcf, 0xc9, 0xfd, 0xb6, 0x95, 0x90, 0x0e, 0x76, - 0x1a, 0xce, 0xb5, 0x72, 0x3f, 0x48, 0xa2, 0xcc, 0x6b, 0xf6, 0x6e, 0x72, - 0xef, 0x0c, 0x5f, 0x1b, 0xb4, 0x61, 0x5d, 0xf2, 0xc3, 0x9f, 0x09, 0x5b, - 0x60, 0xd8, 0xfd, 0xb0, 0x12, 0xe3, 0xc3, 0xeb, 0x4a, 0x5b, 0x26, 0xf8, - 0x5c, 0xfe, 0xd8, 0x93, 0xf1, 0xc8, 0x38, 0x29, 0x2c, 0xfe, 0x76, 0xf8, - 0xf5, 0x7b, 0x1b, 0x48, 0x6e, 0x27, 0xc3, 0xc8, 0xba, 0x23, 0xa8, 0x23, - 0xa3, 0xae, 0x48, 0x24, 0x83, 0x13, 0x6c, 0xbb, 0xfe, 0x7c, 0x36, 0xf7, - 0x7e, 0xe6, 0x1b, 0xd8, 0x86, 0x39, 0xc1, 0x84, 0x89, 0x2d, 0x0e, 0x80, - 0x3f, 0xb9, 0x5f, 0x25, 0x05, 0x85, 0xfa, 0x34, 0x23, 0xb9, 0xfa, 0xa2, - 0x2b, 0xaa, 0x40, 0x6d, 0xd3, 0x9b, 0xc9, 0x6a, 0xf7, 0xe8, 0x60, 0x2b, - 0x38, 0xe2, 0x79, 0xc9, 0x37, 0x62, 0x7d, 0xe0, 0x7a, 0xb5, 0xc6, 0x1f, - 0x80, 0xb1, 0xba, 0x4a, 0xdc, 0x65, 0x99, 0x0d, 0xe4, 0xae, 0x7f, 0x79, - 0x27, 0x93, 0xe6, 0x89, 0xbf, 0xb6, 0xeb, 0x8b, 0x1d, 0xfc, 0xb2, 0x8f, - 0x41, 0x0d, 0x0d, 0xa6, 0x20, 0x8f, 0x14, 0xf7, 0x33, 0x0c, 0xbb, 0x79, - 0xa4, 0xf3, 0x03, 0x23, 0xe9, 0xa3, 0x0a, 0x8b, 0xc2, 0xa6, 0xe3, 0xd3, - 0xaf, 0x11, 0xd3, 0x00, 0xfe, 0x84, 0x36, 0x8e, 0x51, 0x62, 0x00, 0x8a, - 0xaf, 0x45, 0x34, 0xc7, 0x96, 0xc1, 0x48, 0x5f, 0xd7, 0xc4, 0xa1, 0x2e, - 0xf6, 0x86, 0x0e, 0x74, 0xfd, 0x0f, 0x2d, 0x70, 0x9a, 0x83, 0xa6, 0x47, - 0x91, 0x50, 0x9e, 0xf7, 0xbe, 0x00, 0xce, 0xe1, 0xe0, 0x93, 0x47, 0x0f, - 0x3c, 0x2b, 0x1b, 0x68, 0x34, 0x07, 0xc4, 0x28, 0x8f, 0x66, 0xb9, 0xb6, - 0xad, 0xfc, 0x53, 0x42, 0xbb, 0x21, 0x00, 0x35, 0xe7, 0x74, 0xd8, 0x36, - 0x66, 0x7c, 0x54, 0xc2, 0x59, 0xe4, 0x11, 0x52, 0x8f, 0xdb, 0xb5, 0x46, - 0xe6, 0xb3, 0x16, 0x6a, 0xf5, 0x79, 0x51, 0x11, 0x56, 0x13, 0xa9, 0xfe, - 0x39, 0xe7, 0xfe, 0x27, 0x86, 0x05, 0x2a, 0xde, 0x90, 0x43, 0xa3, 0x84, - 0x41, 0x78, 0x24, 0xfb, 0xe3, 0x4f, 0x42, 0xc1, 0x56, 0x65, 0x45, 0xab, - 0x8d, 0x69, 0x42, 0x6d, 0x44, 0x22, 0x19, 0x50, 0x43, 0x73, 0x52, 0x34, - 0xdd, 0xb9, 0xcf, 0x78, 0xe7, 0x81, 0xa7, 0x3a, 0x51, 0xe3, 0x9e, 0xc4, - 0x38, 0xa3, 0x03, 0x2c, 0xe6, 0x45, 0x67, 0x70, 0xc7, 0xc5, 0x4c, 0x50, - 0xf7, 0x68, 0x52, 0x7f, 0x08, 0x94, 0x78, 0xd7, 0xb8, 0x8c, 0xb2, 0x56, - 0x45, 0x90, 0x65, 0xd3, 0x55, 0x1c, 0x20, 0x9c, 0x3c, 0x54, 0x96, 0xf3, - 0x45, 0x42, 0x9b, 0x1b, 0x20, 0xab, 0xc7, 0x1e, 0x73, 0x85, 0x6d, 0x03, - 0x0e, 0xc7, 0x17, 0xc5, 0xf6, 0x02, 0x10, 0x3b, 0x54, 0x2c, 0x17, 0x5c, - 0x08, 0xa2, 0xd6, 0x2e, 0xcc, 0x18, 0x9b, 0x71, 0x60, 0xba, 0xdb, 0xae, - 0x18, 0x54, 0x57, 0xd0, 0x30, 0xda, 0xe9, 0x15, 0x5f, 0x90, 0x43, 0x52, - 0xd9, 0xf5, 0xb6, 0x4e, 0x5b, 0x83, 0x83, 0xaa, 0xc0, 0x16, 0xe2, 0xa9, - 0x5f, 0x31, 0x30, 0x79, 0x87, 0x9d, 0x0c, 0xd8, 0xf2, 0xdb, 0x4e, 0x3e, - 0xe6, 0xd9, 0xc9, 0x17, 0xb7, 0x11, 0x8d, 0x9c, 0x72, 0x17, 0x45, 0xde, - 0x2b, 0x6a, 0xc7, 0x60, 0x79, 0x3f, 0xbe, 0xf8, 0xdd, 0x47, 0x07, 0x66, - 0x24, 0xe3, 0xa6, 0x00, 0x91, 0xa2, 0x6f, 0x6d, 0xbf, 0x76, 0x0c, 0x18, - 0xe0, 0x87, 0xe1, 0xb8, 0x0e, 0x75, 0x18, 0xa2, 0x46, 0x62, 0x9a, 0x20, - 0x85, 0x5e, 0x8b, 0xb4, 0xfe, 0xd2, 0x24, 0x4b, 0x6b, 0x2c, 0x53, 0x3e, - 0xba, 0xb3, 0x28, 0x6b, 0x29, 0x81, 0x6a, 0x74, 0xc8, 0xb6, 0x92, 0x13, - 0x77, 0x2b, 0xe7, 0xad, 0x1f, 0x20, 0x41, 0x0c, 0xdd, 0xb4, 0xa7, 0xa2, - 0xb8, 0x88, 0x2e, 0xb3, 0x12, 0xec, 0xfb, 0x36, 0x7a, 0xea, 0x77, 0xb3, - 0x22, 0xb4, 0x52, 0xd0, 0x97, 0x41, 0xae, 0xc1, 0xb2, 0x04, 0xd0, 0x7f, - 0x88, 0x23, 0x66, 0x50, 0x21, 0xee, 0xb5, 0x89, 0xcd, 0xeb, 0xe4, 0x46, - 0xed, 0x7b, 0x89, 0x4a, 0xb9, 0xc2, 0xa6, 0x33, 0x13, 0xdd, 0xc3, 0x96, - 0x16, 0xd5, 0xe0, 0x70, 0xfb, 0x13, 0xb8, 0xa3, 0x64, 0x86, 0x18, 0x2e, - 0xb6, 0x0f, 0x86, 0x2c, 0x1f, 0xda, 0x82, 0xb0, 0x79, 0x9c, 0x73, 0xa9, - 0x7e, 0x7b, 0xe9, 0x49, 0x84, 0x08, 0x53, 0x14, 0x31, 0x77, 0xdc, 0xa1, - 0x65, 0xd5, 0xaa, 0xb2, 0x99, 0xa6, 0x85, 0x30, 0x45, 0x95, 0x06, 0x31, - 0xc3, 0xd2, 0xb2, 0x5e, 0xcd, 0x8d, 0x4a, 0x24, 0x66, 0xfb, 0x97, 0x02, - 0xf0, 0xca, 0x1c, 0x5c, 0x79, 0x28, 0xa1, 0x97, 0x47, 0xac, 0xba, 0x85, - 0x05, 0x79, 0x1c, 0x06, 0x2c, 0xdf, 0x1f, 0xcf, 0xca, 0xd4, 0xa8, 0x31, - 0xa6, 0x76, 0x8d, 0x3d, 0x3e, 0xd6, 0xba, 0xf9, 0xe6, 0xb1, 0xae, 0x49, - 0xca, 0x4c, 0x5b, 0xb3, 0x58, 0xee, 0x44, 0xec, 0xa9, 0x82, 0x73, 0xa3, - 0xe3, 0x1e, 0xd0, 0xc0, 0x28, 0x15, 0x6a, 0x7a, 0x1f, 0x5b, 0xc1, 0xc6, - 0x14, 0x17, 0x15, 0x2f, 0x15, 0xd5, 0xcb, 0xb0, 0x4a, 0x58, 0x56, 0x5a, - 0xa5, 0xac, 0x82, 0x89, 0x22, 0x2d, 0xe0, 0x0c, 0x89, 0xab, 0x05, 0x82, - 0x29, 0x73, 0x03, 0xc9, 0xcc, 0x03, 0x8e, 0x4e, 0x81, 0x75, 0x16, 0x2e, - 0x7f, 0xe4, 0x41, 0x3f, 0x6b, 0x49, 0xfa, 0xb4, 0x15, 0xd0, 0x71, 0xea, - 0x53, 0xf0, 0xa3, 0x40, 0x0e, 0x63, 0x8e, 0x31, 0x30, 0x02, 0x6d, 0x35, - 0x47, 0x65, 0x84, 0x72, 0x12, 0xd3, 0x78, 0x6e, 0x35, 0xba, 0x32, 0x41, - 0x62, 0x26, 0x61, 0x33, 0x39, 0x89, 0xc2, 0xc3, 0x58, 0x09, 0x2a, 0x32, - 0x44, 0xaf, 0xd8, 0xe9, 0x16, 0x41, 0x08, 0xbf, 0x6f, 0x20, 0x0d, 0x9f, - 0xc8, 0xdd, 0x5a, 0xdf, 0xc7, 0xec, 0xcc, 0x81, 0x57, 0x12, 0xa1, 0x9a, - 0x5e, 0xe2, 0x68, 0x2d, 0xa9, 0x6b, 0xd8, 0x7f, 0x36, 0x5f, 0xe1, 0x43, - 0xca, 0xbc, 0x7e, 0x8c, 0x74, 0x11, 0xd4, 0xf4, 0x20, 0xa5, 0xf8, 0x28, - 0x3b, 0x7d, 0x24, 0xe6, 0x3c, 0x46, 0xd8, 0x46, 0x4d, 0xea, 0x84, 0x16, - 0x7b, 0xf7, 0xb9, 0x9b, 0x7f, 0xf6, 0x1d, 0x53, 0x6f, 0x32, 0x02, 0x74, - 0xd3, 0x12, 0x62, 0x92, 0x0c, 0x53, 0xa2, 0xbf, 0x16, 0x4e, 0xde, 0x1d, - 0xe5, 0xe4, 0x9f, 0x75, 0xe4, 0xac, 0xa0, 0x71, 0x54, 0x45, 0x37, 0xfc, - 0x3b, 0x1a, 0x40, 0x99, 0x1e, 0x4a, 0x66, 0xe3, 0x1e, 0x47, 0x18, 0xe1, - 0xa6, 0x66, 0x26, 0x90, 0x31, 0xc6, 0x89, 0xb1, 0x0e, 0x98, 0x3d, 0x1e, - 0xb8, 0x47, 0x8a, 0xb5, 0xd1, 0x4c, 0xee, 0x25, 0x2c, 0x1f, 0x29, 0x30, - 0xd6, 0x57, 0x9a, 0xb7, 0x66, 0x6c, 0x92, 0x13, 0xa8, 0x49, 0xdd, 0x59, - 0xc4, 0xc3, 0xe0, 0x44, 0x2e, 0xeb, 0x4e, 0x2e, 0x39, 0x4f, 0x37, 0x63, - 0xf9, 0xbe, 0x7d, 0x39, 0x53, 0x0b, 0x8b, 0x6b, 0x40, 0x6a, 0x6f, 0x21, - 0x3a, 0xea, 0x15, 0xc9, 0xc3, 0x19, 0x58, 0x50, 0x27, 0x5f, 0xd0, 0x33, - 0x55, 0x68, 0xad, 0xe3, 0xf2, 0x84, 0x97, 0x0b, 0x7f, 0x39, 0xeb, 0xad, - 0x25, 0x6b, 0xa4, 0xbe, 0x77, 0x5d, 0xcc, 0x25, 0xda, 0x50, 0xbf, 0xbb, - 0xfc, 0x03, 0xd1, 0x54, 0xfb, 0x21, 0x5c, 0x7f, 0x35, 0x7f, 0x4b, 0x76, - 0x2e, 0x46, 0x5c, 0x6d, 0xc0, 0x40, 0xbc, 0x08, 0x54, 0xab, 0x27, 0xfd, - 0xaf, 0x2c, 0xff, 0x4e, 0x14, 0xe2, 0xa9, 0xa4, 0xba, 0xa0, 0x34, 0x47, - 0xbd, 0x7a, 0x81, 0x7c, 0xd1, 0xe4, 0xe3, 0xa3, 0x20, 0x33, 0xa3, 0x64, - 0x9a, 0x78, 0x0c, 0xc2, 0x3a, 0x55, 0xdb, 0x98, 0x35, 0x2d, 0x39, 0x04, - 0x2d, 0xf3, 0x22, 0xdf, 0x2e, 0x9c, 0x7c, 0x57, 0x53, 0xf3, 0x9d, 0xd3, - 0x1e, 0xcf, 0xf9, 0x15, 0xd4, 0x5b, 0x1f, 0xac, 0x56, 0x47, 0xb7, 0x36, - 0x4e, 0x5c, 0x88, 0x0c, 0x01, 0xf5, 0x7c, 0xc7, 0xe0, 0x20, 0xea, 0xcc, - 0xe7, 0x6e, 0x41, 0xab, 0xcc, 0xa6, 0x2b, 0x8a, 0x99, 0xe5, 0x01, 0x47, - 0xf5, 0xb7, 0xbf, 0x98, 0x73, 0x89, 0x44, 0xa9, 0xa1, 0x75, 0x6f, 0xfb, - 0x0b, 0x64, 0x55, 0xca, 0xb4, 0x75, 0xbf, 0xc3, 0x55, 0xce, 0x87, 0x50, - 0xce, 0x0b, 0xf7, 0x7c, 0x24, 0x19, 0xe4, 0xe9, 0x97, 0x29, 0x86, 0x5f, - 0x8a, 0x16, 0x97, 0xf7, 0x87, 0x5a, 0x41, 0x7b, 0x38, 0x13, 0x70, 0x62, - 0x0f, 0xf0, 0xad, 0xe9, 0xd7, 0xf9, 0x7f, 0x62, 0xda, 0x77, 0x2a, 0x60, - 0x8d, 0xd2, 0x85, 0x5c, 0x6b, 0xc4, 0x43, 0xa7, 0x30, 0x27, 0x2d, 0x18, - 0x79, 0x52, 0x94, 0x76, 0xd8, 0xea, 0xb2, 0xb7, 0x2d, 0x86, 0xbb, 0xef, - 0xf7, 0x54, 0x17, 0x1b, 0xec, 0x1d, 0x9a, 0x7f, 0xa9, 0xb7, 0x35, 0x15, - 0xb1, 0xdf, 0x61, 0xd9, 0x76, 0x7c, 0x2d, 0x4a, 0x59, 0xf5, 0xf6, 0x5e, - 0xde, 0xfe, 0x3a, 0x27, 0x8d, 0x33, 0xa9, 0x72, 0xfc, 0x7e, 0xa9, 0xf5, - 0xdd, 0x72, 0xe9, 0x2c, 0x0d, 0xd3, 0x89, 0x89, 0x54, 0xc0, 0x9e, 0xd2, - 0x61, 0x68, 0xc5, 0x7b, 0xd1, 0x91, 0xd0, 0x55, 0xaa, 0x69, 0xb5, 0x19, - 0x0f, 0x83, 0x37, 0xbb, 0x72, 0x90, 0xb9, 0x7f, 0x47, 0xd8, 0xc4, 0xf0, - 0x29, 0x9d, 0x96, 0xe8, 0x32, 0x70, 0x64, 0x85, 0xc4, 0xa0, 0xfb, 0x53, - 0x9a, 0x45, 0xe6, 0x94, 0xcb, 0x6d, 0x09, 0x8a, 0xe2, 0x9d, 0xf7, 0x35, - 0xa7, 0x43, 0xbb, 0x46, 0x9d, 0x18, 0x37, 0x58, 0x14, 0x5b, 0xc5, 0x1c, - 0x35, 0x57, 0xf5, 0x30, 0x60, 0x8d, 0x3b, 0xba, 0xab, 0x90, 0x3f, 0x22, - 0xa1, 0x2a, 0xff, 0xae, 0xa4, 0xe4, 0x95, 0xa9, 0x43, 0x89, 0x12, 0x2d, - 0xf0, 0xe0, 0x70, 0x25, 0x1c, 0x90, 0xd7, 0x70, 0x1b, 0xbe, 0x82, 0xad, - 0x26, 0x59, 0x01, 0x05, 0x2c, 0x8e, 0xf4, 0x74, 0x50, 0xa0, 0x83, 0xbe, - 0x76, 0x05, 0x41, 0x55, 0xf8, 0x12, 0x3e, 0x0c, 0x11, 0xf6, 0x59, 0x9c, - 0x23, 0xc3, 0x13, 0x41, 0xee, 0xd3, 0x0d, 0xa6, 0x00, 0x5c, 0x11, 0x12, - 0x00, 0x00, 0x00, 0x1b, 0x99, 0x90, 0xef, 0x9c, 0x6b, 0x48, 0x2f, 0x5d, - 0xe2, 0x75, 0x64, 0x30, 0x6e, 0x94, 0x88, 0xcd, 0xc7, 0xb1, 0x7d, 0xd2, - 0xc6, 0xc6, 0x44, 0xab, 0x2d, 0xff, 0x54, 0x7b, 0x29, 0x79, 0x07, 0xd6, - 0xd2, 0x68, 0x7c, 0x74, 0xcd, 0x27, 0x28, 0x1c, 0x58, 0x5c, 0xd9, 0x4e, - 0xbd, 0xee, 0xc0, 0x02, 0xe7, 0x71, 0x41, 0xc9, 0x31, 0x14, 0x6b, 0x68, - 0x2f, 0xb9, 0xfb, 0xf5, 0x49, 0x17, 0x23, 0x35, 0x8d, 0x3e, 0x7b, 0x5a, - 0x21, 0x21, 0x3a, 0x71, 0x00, 0x14, 0xb1, 0x84, 0x71, 0x13, 0x3d, 0xf2, - 0xb3, 0xad, 0x9c, 0xff, 0xe9, 0xd3, 0x19, 0x7c, 0x67, 0x5c, 0x7c, 0x5d, - 0x0b, 0xb9, 0x4e, 0xfc, 0x2a, 0x9d, 0x19, 0x37, 0x80, 0xe6, 0xbe, 0xef, - 0x5d, 0xb6, 0xf9, 0x90, 0x5d, 0xdf, 0x25, 0x93, 0x98, 0x04, 0x0a, 0x46, - 0xce, 0xd8, 0xe3, 0x92, 0xd1, 0x8e, 0x90, 0xf6, 0xce, 0xe8, 0x6f, 0x58, - 0x8c, 0xe0, 0x4c, 0x44, 0x61, 0x8d, 0x84, 0xe8, 0xc7, 0xc9, 0xa6, 0x80, - 0xdf, 0x96, 0x8d, 0x22, 0x2d, 0x86, 0x38, 0x19, 0x0f, 0x36, 0x1c, 0xbb, - 0x5c, 0xa1, 0xa1, 0xb3, 0xb0, 0xc6, 0xbf, 0xf1, 0x41, 0x9b, 0x3f, 0xf6, - 0x5c, 0x1f, 0x96, 0xc5, 0xce, 0x8f, 0x8a, 0xd5, 0xcc, 0xc5, 0xc4, 0x14, - 0xce, 0xe0, 0xea, 0x87, 0x7a, 0x30, 0xac, 0x17, 0xf6, 0xc8, 0x4a, 0x17, - 0xb2, 0x2d, 0xf8, 0x46, 0xf9, 0x5c, 0xad, 0x02, 0xc7, 0x4a, 0x19, 0x33, - 0xe1, 0x7e, 0x39, 0x06, 0xe7, 0x88, 0x1a, 0x3b, 0xc7, 0x4b, 0xb7, 0x0f, - 0x05, 0x34, 0x06, 0xae, 0x6d, 0x92, 0x5b, 0xea, 0x22, 0x17, 0x6c, 0xad, - 0x65, 0x86, 0x68, 0xba, 0x4e, 0x38, 0xf5, 0x3a, 0xeb, 0xe4, 0x81, 0x2a, - 0xff, 0x22, 0x33, 0x73, 0x85, 0xeb, 0x11, 0x78, 0x98, 0xcb, 0x4d, 0xc9, - 0xbf, 0x4f, 0x24, 0x8e, 0x6b, 0xf7, 0x44, 0x7b, 0xbf, 0xf2, 0xa9, 0x4e, - 0x08, 0xcd, 0xfc, 0xb7, 0xfc, 0xd9, 0xb8, 0x19, 0xf5, 0x80, 0xd1, 0xce, - 0x45, 0x06, 0x9b, 0xc8, 0x4c, 0xd8, 0xd1, 0x19, 0xd7, 0x9b, 0xc8, 0x67, - 0x11, 0x04, 0x86, 0x69, 0xae, 0x5d, 0xd5, 0xa2, 0xb3, 0xe5, 0x64, 0x50, - 0x2b, 0x9c, 0x18, 0xf5, 0xef, 0x65, 0x90, 0xdc, 0xb9, 0x7a, 0x67, 0x1d, - 0x62, 0xf3, 0x17, 0xbf, 0x1d, 0x67, 0xaf, 0xb3, 0x0c, 0xe4, 0xda, 0x27, - 0x06, 0xa3, 0x34, 0xe6, 0x8f, 0x43, 0xd1, 0x20, 0x17, 0x44, 0x44, 0x10, - 0x93, 0x91, 0x61, 0x43, 0xb7, 0x75, 0x9f, 0x1e, 0x91, 0x0b, 0xa0, 0x5e, - 0x49, 0x02, 0xba, 0x5d, 0xbc, 0xde, 0x6c, 0xb5, 0xbb, 0x26, 0x87, 0x68, - 0x03, 0x94, 0xe1, 0x05, 0xd1, 0xfc, 0xba, 0x48, 0xc7, 0x87, 0x86, 0xef, - 0xe9, 0x54, 0x0a, 0xaf, 0xd1, 0x7b, 0x0a, 0xd4, 0xf5, 0x07, 0xe6, 0x1f, - 0x60, 0xec, 0x82, 0x2c, 0xc5, 0x93, 0xc3, 0x60, 0xee, 0x78, 0x85, 0x28, - 0xa5, 0x08, 0x9f, 0x36, 0x47, 0x9c, 0xb2, 0x8e, 0x0a, 0x90, 0xf2, 0xa2, - 0xd0, 0x13, 0x3e, 0xfa, 0x40, 0x46, 0x6e, 0x97, 0x92, 0xea, 0x56, 0x60, - 0xe3, 0x95, 0xa1, 0x35, 0x3c, 0x26, 0xe2, 0x4d, 0x35, 0x92, 0x5e, 0xe4, - 0xbd, 0x4c, 0xea, 0x8e, 0xbf, 0x81, 0xd6, 0xe8, 0xa2, 0x37, 0x70, 0x3b, - 0x3c, 0xc4, 0x8d, 0x05, 0x16, 0x9a, 0x3a, 0x34, 0x47, 0x99, 0xd7, 0x49, - 0xc7, 0x9a, 0x34, 0x1c, 0x7f, 0xbf, 0xce, 0x56, 0x7e, 0x64, 0xaa, 0xba, - 0xc6, 0xfc, 0xe7, 0x3e, 0x62, 0x7f, 0xa6, 0x38, 0xdd, 0x3a, 0x95, 0x80, - 0xd4, 0xf8, 0x49, 0x58, 0xe7, 0x02, 0x4e, 0xa0, 0x08, 0x74, 0x71, 0x19, - 0x79, 0x75, 0x41, 0x95, 0x88, 0xc8, 0xe1, 0xe4, 0x9d, 0x19, 0x7c, 0x06, - 0x03, 0x0d, 0x27, 0x36, 0x5d, 0x2b, 0xbc, 0xa6, 0xb6, 0x22, 0x94, 0x12, - 0x17, 0xa2, 0xa2, 0x1e, 0x07, 0x60, 0x0e, 0x8d, 0x53, 0x60, 0x41, 0x7b, - 0x92, 0xfb, 0x13, 0x74, 0x1c, 0x6c, 0x1a, 0xd3, 0x7d, 0xda, 0xe1, 0x1c, - 0x16, 0xb9, 0xf9, 0xd2, 0x39, 0x36, 0xc0, 0xbb, 0x49, 0x00, 0xd4, 0x8d, - 0x7a, 0x59, 0x41, 0x9c, 0x2f, 0x09, 0x3b, 0x63, 0x1c, 0x82, 0x15, 0xe3, - 0x36, 0x62, 0x37, 0x07, 0x3b, 0x6e, 0x7c, 0x8d, 0x6c, 0x7b, 0x2b, 0xa0, - 0xa8, 0xd2, 0xe1, 0x24, 0x58, 0x3d, 0xb2, 0xf2, 0x3f, 0xf8, 0x86, 0x44, - 0x09, 0xe7, 0xab, 0x5f, 0x34, 0xa8, 0x37, 0xda, 0x2d, 0xd8, 0xae, 0x01, - 0x88, 0x0d, 0x43, 0x38, 0x35, 0x7d, 0xb5, 0xe7, 0x6e, 0x79, 0x0d, 0xe9, - 0xe9, 0x25, 0xf8, 0xdb, 0xfd, 0x3b, 0xd9, 0x73, 0x77, 0x55, 0x45, 0xc3, - 0x22, 0xf5, 0x43, 0x22, 0x4f, 0x47, 0xbf, 0x78, 0xfb, 0x34, 0xd1, 0xee, - 0xd0, 0xcc, 0x3a, 0xa5, 0xa4, 0xe5, 0x78, 0xe9, 0xd6, 0x55, 0xe0, 0x15, - 0x86, 0x4b, 0x58, 0x9d, 0x62, 0x2f, 0x29, 0x62, 0xd8, 0xdf, 0x96, 0x80, - 0x05, 0x1a, 0x9d, 0xc1, 0x0d, 0xb9, 0xd1, 0x44, 0x29, 0x6f, 0xe0, 0x86, - 0x25, 0xde, 0x7f, 0x78, 0x6f, 0xe0, 0x9c, 0xdf, 0x14, 0xdd, 0x89, 0x3e, - 0x44, 0xf4, 0xe0, 0x4c, 0x20, 0x58, 0xbb, 0x55, 0xf5, 0x4e, 0x96, 0xaa, - 0x82, 0x74, 0x2d, 0xbd, 0xc2, 0xad, 0x7f, 0xc3, 0xed, 0x8b, 0xd5, 0x98, - 0xf7, 0xad, 0x5a, 0xc4, 0x90, 0x14, 0xb2, 0xa8, 0xf4, 0x81, 0xc4, 0xaf, - 0x6c, 0x05, 0xfe, 0xee, 0x04, 0x3c, 0x51, 0xbd, 0x75, 0xd7, 0x32, 0xf5, - 0x7e, 0x45, 0x19, 0x39, 0x19, 0x28, 0x45, 0x9a, 0xc7, 0xcf, 0x82, 0x7d, - 0x56, 0xac, 0x68, 0xdb, 0xde, 0x89, 0x9d, 0x72, 0x1a, 0x46, 0xea, 0xb0, - 0xc3, 0xbc, 0x6f, 0x0d, 0x4b, 0x41, 0x3b, 0x38, 0xb3, 0xc7, 0xcb, 0x04, - 0xbe, 0xf3, 0x4c, 0x3b, 0x74, 0xa9, 0x2a, 0xe4, 0xe3, 0x2f, 0xc7, 0x8c, - 0x90, 0x30, 0x67, 0xcb, 0xb1, 0x1f, 0xbf, 0xc0, 0xad, 0x37, 0x74, 0x80, - 0xa9, 0x04, 0x7c, 0xc8, 0x57, 0x33, 0x83, 0x5b, 0x8c, 0xe6, 0xfc, 0xd5, - 0xa4, 0xf3, 0x9b, 0x6b, 0x2d, 0xdc, 0x64, 0x2b, 0x83, 0xe7, 0xdc, 0xb4, - 0x48, 0x8d, 0x11, 0x65, 0x22, 0xb5, 0xb5, 0x54, 0xec, 0x26, 0xdc, 0x1f, - 0x96, 0xbc, 0x68, 0x87, 0x67, 0xed, 0x1c, 0x41, 0xd3, 0xd8, 0x4f, 0xe2, - 0xc8, 0x43, 0xbb, 0x22, 0xd9, 0xa1, 0x39, 0xe1, 0x72, 0xdb, 0x75, 0x81, - 0x58, 0x74, 0x89, 0xb9, 0x58, 0x8b, 0x0f, 0x8a, 0xa0, 0x6a, 0x9e, 0x70, - 0x6b, 0x3b, 0x01, 0x2f, 0x2b, 0xf4, 0x00, 0xb8, 0x1c, 0xf9, 0x34, 0xa4, - 0x30, 0x80, 0x80, 0x4a, 0x0e, 0xcc, 0x52, 0x4e, 0xc7, 0xc1, 0x01, 0xfd, - 0x73, 0x22, 0x26, 0x33, 0x68, 0xfe, 0x01, 0x1d, 0xe1, 0xf0, 0x04, 0x66, - 0xfd, 0xcc, 0x77, 0xe5, 0xa1, 0x4b, 0xbe, 0x0e, 0xde, 0x95, 0x74, 0x72, - 0xbf, 0xbb, 0xa2, 0x5c, 0x08, 0x5d, 0x13, 0xcb, 0xcb, 0xd7, 0xa6, 0x34, - 0x61, 0x53, 0x0b, 0x3e, 0xb1, 0xe0, 0xb5, 0xd3, 0xaf, 0xe9, 0x07, 0x67, - 0x4c, 0x1a, 0x5b, 0x64, 0x68, 0xac, 0x94, 0x6f, 0xc4, 0xdb, 0x0f, 0x84, - 0x52, 0x88, 0x4b, 0x1e, 0xe5, 0xf1, 0x05, 0x70, 0x94, 0xee, 0xc1, 0x62, - 0xfd, 0x6f, 0x41, 0x2a, 0x1f, 0xda, 0xbe, 0x9f, 0xfb, 0x87, 0xf0, 0x96, - 0x8d, 0xa0, 0x60, 0x74, 0x7d, 0x53, 0x6e, 0x2e, 0x2d, 0x42, 0x49, 0x3d, - 0x9a, 0xae, 0xbc, 0x1b, 0x76, 0xa0, 0xc7, 0xaf, 0x4b, 0xb9, 0x18, 0x6f, - 0x4b, 0xe8, 0xbc, 0x56, 0x7b, 0x57, 0x60, 0xd1, 0xd3, 0x0c, 0x4d, 0xe0, - 0xe2, 0x3d, 0xcc, 0x82, 0x36, 0x78, 0xa2, 0x53, 0xe8, 0xe8, 0xf6, 0x13, - 0xa6, 0xc1, 0x1f, 0x0c, 0x9f, 0x5b, 0x0c, 0xf9, 0x89, 0x8e, 0xae, 0x70, - 0x51, 0xd0, 0x1f, 0x7b, 0xab, 0x69, 0xda, 0xb9, 0x56, 0x4d, 0x2d, 0x93, - 0x18, 0xa4, 0x40, 0x55, 0x95, 0xdf, 0x58, 0xca, 0xbd, 0x36, 0x89, 0x07, - 0x58, 0x11, 0xa6, 0x22, 0xf8, 0x83, 0x1c, 0x8e, 0xe7, 0xa9, 0xc7, 0xd3, - 0xdc, 0x5e, 0x54, 0x35, 0xd6, 0xf1, 0xe4, 0x41, 0x98, 0xa4, 0x16, 0x67, - 0x73, 0x56, 0xdd, 0x69, 0x6d, 0xaa, 0x3f, 0xb8, 0xad, 0xfa, 0xd7, 0xce, - 0xee, 0x65, 0xc5, 0x10, 0xe8, 0x39, 0x1d, 0xff, 0x57, 0x1a, 0x85, 0x43, - 0x77, 0x3f, 0xb1, 0xe1, 0x21, 0x81, 0xa6, 0x8e, 0xd8, 0x49, 0xec, 0xe8, - 0x44, 0x0c, 0x4c, 0x44, 0x8f, 0x8d, 0x78, 0x45, 0xcc, 0x81, 0xed, 0x17, - 0xd1, 0xac, 0x54, 0x3c, 0x58, 0xa4, 0x8e, 0x65, 0xd0, 0xd8, 0x94, 0xc9, - 0xd7, 0x8d, 0x46, 0x5d, 0xc1, 0x3c, 0xb6, 0xb9, 0x0d, 0x88, 0xdf, 0x2c, - 0xb8, 0x51, 0x6d, 0x30, 0x87, 0x76, 0x27, 0x0a, 0xd7, 0xfe, 0x0a, 0x2b, - 0x2d, 0xdc, 0xd1, 0xd2, 0xfd, 0x72, 0xcd, 0x0f, 0x1b, 0xb7, 0xb6, 0x0d, - 0xbd, 0xe0, 0x10, 0x60, 0xec, 0xfd, 0xe1, 0x18, 0x0d, 0x88, 0x48, 0x34, - 0xec, 0xf6, 0x7f, 0x4a, 0x24, 0xce, 0xa9, 0x8d, 0x45, 0x4e, 0xde, 0xcc, - 0x5e, 0xfc, 0x48, 0xf8, 0x7e, 0xa8, 0x0a, 0x9c, 0x5b, 0xad, 0x3c, 0x5e, - 0x5d, 0x3e, 0x33, 0x89, 0xec, 0x88, 0x58, 0xa9, 0xca, 0xa6, 0xe7, 0x59, - 0x5a, 0x8e, 0xfb, 0x21, 0x43, 0x8a, 0x45, 0x49, 0x0f, 0x91, 0xb8, 0xf8, - 0x60, 0x5b, 0x35, 0x44, 0xd7, 0x0d, 0x68, 0x9f, 0x47, 0x6f, 0xbf, 0x3d, - 0xa1, 0x6f, 0xd7, 0xfc, 0xef, 0xbd, 0x9b, 0x84, 0xce, 0x79, 0xbd, 0xf9, - 0x59, 0x4d, 0x46, 0x6e, 0xde, 0x49, 0xdd, 0xde, 0xb8, 0x27, 0x33, 0xf9, - 0xdb, 0x33, 0xdb, 0xea, 0x42, 0x30, 0xff, 0x96, 0x72, 0x5b, 0x55, 0xb6, - 0xa3, 0xa9, 0x15, 0xb3, 0xbd, 0x31, 0xb6, 0x7c, 0x4e, 0xc8, 0xec, 0x5a, - 0x2a, 0x53, 0xe9, 0xa8, 0x25, 0x26, 0x75, 0xeb, 0xce, 0xd5, 0x27, 0x6e, - 0x85, 0xe2, 0x01, 0x0b, 0xd6, 0x1b, 0x09, 0xe8, 0x0a, 0x11, 0xf3, 0x2d, - 0x94, 0xcf, 0xab, 0x03, 0xb9, 0x83, 0x8a, 0x6f, 0x3b, 0x05, 0x98, 0xb4, - 0x72, 0x3b, 0xba, 0x90, 0xbd, 0x23, 0x07, 0x8b, 0xf8, 0xd9, 0x26, 0x13, - 0x74, 0xe3, 0x1c, 0x85, 0xec, 0x8f, 0x43, 0x29, 0xa8, 0x17, 0x6d, 0xb7, - 0x00, 0xda, 0xd1, 0x34, 0x1d, 0x1c, 0xd2, 0xc3, 0xe6, 0xd7, 0x11, 0x51, - 0x79, 0x1b, 0x73, 0x00, 0x51, 0xd0, 0xe7, 0x92, 0xe1, 0x11, 0x5d, 0x9b, - 0x5c, 0x11, 0x88, 0x4c, 0xfa, 0x02, 0x82, 0x78, 0x86, 0xed, 0x65, 0x08, - 0x4f, 0x1c, 0xcb, 0x8c, 0x78, 0x59, 0x65, 0xea, 0x97, 0x8c, 0xe6, 0x52, - 0xe1, 0x3f, 0xdd, 0xbb, 0x20, 0xe6, 0x7c, 0xf9, 0xc7, 0xf8, 0xb9, 0xe6, - 0x74, 0xa0, 0xa5, 0xcb, 0xe9, 0x89, 0xb9, 0xff, 0x88, 0xa3, 0xb8, 0x7b, - 0x60, 0x8d, 0xb0, 0xca, 0x50, 0xe8, 0xc0, 0x80, 0xc1, 0x68, 0x27, 0xef, - 0x48, 0xe7, 0x00, 0x22, 0x52, 0xb4, 0x2e, 0x30, 0x97, 0x96, 0xde, 0xb3, - 0xd0, 0xa1, 0x8b, 0x6a, 0x31, 0x6a, 0xc4, 0x52, 0xef, 0xba, 0x74, 0x57, - 0xf1, 0xc6, 0x19, 0x37, 0x0b, 0x22, 0xa0, 0x23, 0xb9, 0xe0, 0x26, 0x0c, - 0x23, 0xa3, 0xb8, 0x4c, 0x71, 0x7b, 0x45, 0xa4, 0xe8, 0xfd, 0x94, 0xfc, - 0x96, 0x47, 0xba, 0x0f, 0xaa, 0x67, 0x90, 0xa3, 0x2d, 0x95, 0x70, 0xd2, - 0xa3, 0xfa, 0x7b, 0x49, 0x03, 0x45, 0x44, 0x45, 0x8a, 0x38, 0x2a, 0x04, - 0x1b, 0x9a, 0xa3, 0xbd, 0xc6, 0xa9, 0xcf, 0x4f, 0x88, 0x41, 0x98, 0x0c, - 0x2a, 0x5e, 0x22, 0x60, 0x01, 0xf3, 0x78, 0x98, 0xf4, 0x13, 0xc9, 0x27, - 0x80, 0x6e, 0xee, 0x4f, 0xa0, 0xf2, 0xbe, 0x8f, 0x83, 0x69, 0x52, 0xc4, - 0xf8, 0x82, 0x36, 0xd6, 0xe4, 0x91, 0xd9, 0x62, 0xa4, 0x09, 0xa1, 0xbd, - 0xff, 0xec, 0x96, 0x74, 0x0d, 0x6f, 0x17, 0xf9, 0xb7, 0xe3, 0xe4, 0x16, - 0x7f, 0x03, 0xd7, 0x27, 0x7f, 0xaa, 0x94, 0x27, 0x61, 0x3a, 0x3c, 0x0a, - 0x92, 0x82, 0x93, 0x6a, 0xed, 0x55, 0x12, 0xac, 0xe4, 0x89, 0xc2, 0x25, - 0x36, 0x50, 0x63, 0x68, 0x49, 0xb7, 0x5f, 0x44, 0x95, 0xe8, 0x41, 0x09, - 0x6f, 0xdf, 0x66, 0x0c, 0xde, 0x6f, 0xba, 0x7a, 0x0f, 0x9e, 0x87, 0x43, - 0x62, 0x99, 0x9b, 0x97, 0xe7, 0xb1, 0x46, 0x2d, 0xa2, 0x10, 0x57, 0x92, - 0x5a, 0xbe, 0xec, 0xc1, 0x24, 0x91, 0x94, 0x80, 0x1c, 0xea, 0x0f, 0xc7, - 0xfe, 0x02, 0x4d, 0x99, 0x88, 0x1b, 0xc1, 0xaa, 0xce, 0x4d, 0x6a, 0xc7, - 0xe0, 0x93, 0x4b, 0x35, 0x71, 0x49, 0x81, 0x6b, 0x98, 0x54, 0x17, 0x6d, - 0xf5, 0xbc, 0xc2, 0xc3, 0xb8, 0x5b, 0x00, 0xfd, 0xec, 0x50, 0x50, 0x6e, - 0xb6, 0xe7, 0xdc, 0x6c, 0x2b, 0x4b, 0x77, 0x73, 0xeb, 0xee, 0xc1, 0xc3, - 0xe1, 0xee, 0xc1, 0xc6, 0xc9, 0xce, 0xad, 0x6b, 0x8f, 0x40, 0x95, 0xb3, - 0x41, 0xb9, 0x86, 0xf8, 0x6a, 0x9a, 0x59, 0x7e, 0xc8, 0xb3, 0x26, 0xa0, - 0x55, 0x6e, 0x41, 0x90, 0xff, 0xf2, 0x69, 0x01, 0x70, 0x61, 0x81, 0x6a, - 0x61, 0x14, 0x78, 0x8c, 0x31, 0xbc, 0xc4, 0x51, 0x81, 0x4e, 0x12, 0x54, - 0xef, 0xd8, 0x85, 0x07, 0x92, 0xa4, 0x02, 0xae, 0x54, 0x80, 0x70, 0x94, - 0x26, 0x49, 0x8a, 0xa2, 0x3e, 0x63, 0x6f, 0x3a, 0xa5, 0xbe, 0x71, 0x02, - 0x22, 0x99, 0xf0, 0x98, 0xe8, 0x8f, 0xc5, 0x58, 0x1e, 0xcd, 0x2b, 0xe8, - 0xf5, 0xa0, 0x2c, 0xd0, 0x21, 0x87, 0x3a, 0x38, 0x28, 0x0d, 0x87, 0x1f, - 0x0f, 0x3e, 0xfb, 0xd6, 0xd3, 0x12, 0x86, 0x66, 0x25, 0x02, 0x6c, 0x08, - 0x54, 0x10, 0xfb, 0x29, 0x8f, 0x7f, 0xe5, 0x96, 0xa8, 0x56, 0xba, 0x72, - 0x71, 0x36, 0xdd, 0xc6, 0x81, 0xe2, 0x1f, 0x7a, 0xd4, 0x8d, 0xdc, 0xea, - 0xe6, 0xff, 0x2f, 0xb5, 0xea, 0x44, 0xea, 0x88, 0x69, 0x80, 0x2e, 0x49, - 0x4d, 0x84, 0x6f, 0xa1, 0x7a, 0xed, 0x05, 0x55, 0x73, 0x42, 0x56, 0xe4, - 0xa6, 0x9f, 0x65, 0x32, 0x46, 0x32, 0xb3, 0x97, 0x87, 0x74, 0x7a, 0xd3, - 0xdd, 0xcf, 0x9f, 0x01, 0x96, 0x37, 0xf2, 0xd1, 0xeb, 0x45, 0x4a, 0x23, - 0xb5, 0x33, 0x6c, 0xa5, 0x7b, 0x98, 0x65, 0xd2, 0xe1, 0x78, 0xf9, 0x44, - 0x03, 0x3b, 0x29, 0xa8, 0xf2, 0x45, 0xb2, 0x96, 0x3e, 0xac, 0x09, 0x24, - 0x76, 0x48, 0xb9, 0x75, 0x87, 0xba, 0x2c, 0x4e, 0x33, 0x67, 0xdf, 0xdc, - 0x70, 0x3b, 0xc3, 0x1f, 0xbb, 0xd9, 0x36, 0xf8, 0x19, 0x2e, 0xeb, 0x42, - 0xe5, 0x6b, 0xaa, 0x85, 0x3f, 0xeb, 0xac, 0x51, 0x78, 0xdb, 0x62, 0x9e, - 0x2a, 0x5f, 0x1e, 0xb2, 0x72, 0xa7, 0xdd, 0x25, 0xb0, 0x6b, 0xcb, 0xc5, - 0xb5, 0xe3, 0x88, 0x1c, 0xcd, 0xfa, 0xa8, 0x6e, 0x2a, 0x0e, 0xa0, 0x79, - 0x7a, 0x04, 0x1f, 0xed, 0x3d, 0xc2, 0x65, 0xaf, 0x0b, 0xaa, 0xb2, 0xec, - 0x73, 0x6e, 0x0f, 0xd4, 0x21, 0xd8, 0x29, 0x39, 0x10, 0x53, 0x2c, 0xf8, - 0x31, 0xaf, 0x5f, 0x4b, 0x81, 0xff, 0xb2, 0x6f, 0x96, 0x41, 0xcf, 0x25, - 0x0f, 0x03, 0x13, 0x05, 0x72, 0x7f, 0x75, 0x5c, 0x31, 0x09, 0x72, 0x90, - 0x65, 0x01, 0x43, 0x4b, 0xef, 0x55, 0x91, 0xd3, 0x75, 0x85, 0x44, 0x78, - 0xe9, 0x4c, 0xb0, 0x9b, 0x68, 0xdd, 0xf2, 0x2d, 0x4a, 0x96, 0x21, 0xb6, - 0x2c, 0x2f, 0x86, 0x76, 0x6f, 0xc5, 0x1f, 0x30, 0x6c, 0xc4, 0xf8, 0x12, - 0x8d, 0x0a, 0x1d, 0x76, 0xe7, 0x79, 0xac, 0x85, 0xd4, 0x2f, 0xfc, 0x2c, - 0x9b, 0x54, 0x2b, 0xdc, 0xf7, 0xad, 0x4a, 0x64, 0x03, 0x40, 0xb4, 0xaa, - 0x21, 0x5f, 0x47, 0x55, 0xf2, 0xfd, 0x9d, 0xe2, 0x14, 0x2e, 0x68, 0x84, - 0xef, 0x98, 0x8e, 0xcd, 0xe3, 0x04, 0x52, 0xd1, 0xc2, 0x6c, 0x3b, 0xc3, - 0x2c, 0x49, 0xc4, 0x53, 0x6c, 0xcb, 0x7e, 0xb5, 0x8a, 0xce, 0x18, 0x02, - 0x34, 0x3c, 0xcb, 0xa4, 0xd6, 0xd8, 0xc9, 0xea, 0xa0, 0x19, 0x08, 0x52, - 0x3a, 0x76, 0x49, 0xc5, 0x6c, 0xb3, 0xbf, 0x23, 0x4d, 0x17, 0x18, 0xa4, - 0x27, 0xea, 0x2c, 0x89, 0xc0, 0x77, 0xe5, 0x5c, 0xab, 0x78, 0xdc, 0x17, - 0x29, 0x7a, 0xde, 0x43, 0x4b, 0x40, 0x06, 0x5d, 0x57, 0xa4, 0xf4, 0xe9, - 0xf0, 0xc3, 0xfe, 0x75, 0x71, 0xb3, 0x57, 0x5d, 0x02, 0x84, 0x1e, 0x35, - 0x9c, 0x2b, 0x97, 0x4b, 0x73, 0x8b, 0xaf, 0x7c, 0x1f, 0xae, 0x2b, 0xb2, - 0x85, 0x3b, 0x00, 0xe6, 0xa6, 0x3f, 0x93, 0x8a, 0xfb, 0x47, 0x71, 0x47, - 0xcb, 0xfd, 0x34, 0xd9, 0xf0, 0xbd, 0x7d, 0x85, 0x02, 0x9b, 0x90, 0x88, - 0x7f, 0x6e, 0x97, 0xce, 0x1a, 0x9f, 0x61, 0x19, 0x59, 0x81, 0x05, 0xfb, - 0xb8, 0xbc, 0x3c, 0x19, 0x1c, 0x1a, 0x5b, 0x60, 0xe0, 0x24, 0xcc, 0x52, - 0xb7, 0x49, 0x9e, 0xb6, 0x08, 0xd5, 0x0e, 0x69, 0xfe, 0xc0, 0x92, 0x74, - 0x73, 0x72, 0x93, 0x32, 0xe7, 0xe6, 0xe9, 0x8f, 0xb2, 0xb4, 0x86, 0x47, - 0x67, 0x67, 0xff, 0xc5, 0x2f, 0x25, 0x54, 0x36, 0x50, 0xeb, 0xf4, 0x34, - 0x91, 0x83, 0xde, 0x05, 0xd7, 0xc6, 0xc8, 0xce, 0xf8, 0xe0, 0xbb, 0xc7, - 0x27, 0x24, 0x65, 0x60, 0x21, 0x47, 0x0d, 0x4e, 0x2c, 0x03, 0xad, 0x14, - 0x0b, 0xe3, 0x0f, 0xe3, 0x50, 0xef, 0x06, 0x63, 0x22, 0xb0, 0x51, 0xff, - 0x72, 0x6d, 0x03, 0xaf, 0x76, 0xf6, 0x0f, 0x06, 0xa1, 0x84, 0x53, 0xa2, - 0x79, 0xe1, 0x68, 0x1c, 0xe7, 0x57, 0x09, 0xf3, 0xff, 0x64, 0x6a, 0x33, - 0x81, 0x8a, 0x84, 0x80, 0xd0, 0x85, 0x84, 0x99, 0x75, 0xc6, 0x2e, 0xae, - 0xe0, 0x6d, 0x49, 0xaa, 0xbd, 0x0e, 0x8d, 0xb9, 0x88, 0xb7, 0x52, 0x55, - 0x00, 0xaf, 0xcb, 0x68, 0xb4, 0x53, 0x25, 0x8d, 0x58, 0xc3, 0xcf, 0x94, - 0x1f, 0x80, 0x8a, 0xda, 0x1f, 0x70, 0xe2, 0x19, 0x6d, 0xdd, 0x1d, 0xac, - 0xab, 0xf8, 0xef, 0x0f, 0x43, 0xe0, 0x91, 0xd7, 0x7c, 0xed, 0xb4, 0x8f, - 0x2f, 0x2a, 0xa6, 0x36, 0x18, 0x86, 0xd7, 0xcc, 0xd1, 0xde, 0xda, 0x0d, - 0x0c, 0xde, 0xae, 0x9f, 0xbc, 0x49, 0xf7, 0x07, 0x82, 0xbe, 0x6e, 0xd0, - 0x2b, 0xb1, 0xd4, 0xfa, 0x1a, 0xfe, 0xcc, 0x57, 0x97, 0x2f, 0x4d, 0x12, - 0xf0, 0xba, 0xa0, 0x3f, 0x7f, 0xb4, 0xfe, 0xb8, 0x0f, 0xb3, 0xc5, 0x03, - 0xdc, 0x77, 0x98, 0x95, 0xc6, 0x0b, 0x7b, 0x6f, 0xad, 0xae, 0x9d, 0xb4, - 0xf0, 0x0d, 0xa2, 0xa1, 0xa8, 0x83, 0x62, 0xc7, 0x31, 0x27, 0x9c, 0x52, - 0x36, 0x06, 0x13, 0x52, 0x0e, 0xd6, 0x30, 0x41, 0xc4, 0x38, 0x29, 0x1d, - 0x39, 0x7c, 0x23, 0x32, 0x45, 0xcc, 0x79, 0xca, 0xa5, 0x9a, 0x62, 0x6e, - 0x00, 0x02, 0xc9, 0xb9, 0xd3, 0x84, 0x02, 0x5d, 0xe3, 0x69, 0x5c, 0x8e, - 0xbe, 0x55, 0xf4, 0x96, 0xdf, 0xcb, 0x8b, 0x52, 0xa1, 0x4e, 0x9c, 0x38, - 0x56, 0xa1, 0xd7, 0x82, 0x4a, 0x6a, 0xd3, 0x19, 0xa6, 0x74, 0x80, 0x04, - 0x6d, 0xc5, 0x7e, 0xd6, 0xda, 0x91, 0x5e, 0x2c, 0x81, 0x3b, 0x0c, 0x6a, - 0xc6, 0xe8, 0x40, 0xb7, 0x9c, 0x2a, 0x4f, 0xb3, 0x87, 0x46, 0xc5, 0x4b, - 0x81, 0x87, 0xbe, 0x93, 0x5a, 0x9c, 0xc8, 0xdc, 0x97, 0x93, 0xff, 0x06, - 0x36, 0x8e, 0xa6, 0x24, 0x03, 0x10, 0x17, 0xf9, 0x20, 0xed, 0x75, 0xef, - 0xed, 0xcf, 0x28, 0x1b, 0x7b, 0x64, 0x00, 0x7c, 0x78, 0x10, 0x84, 0xa2, - 0x96, 0x4b, 0x04, 0x42, 0x57, 0x76, 0xaa, 0x2b, 0x7d, 0x7c, 0xc4, 0x85, - 0x83, 0xef, 0x04, 0xdd, 0x6a, 0x68, 0x5e, 0xe3, 0xba, 0xb4, 0x08, 0xe0, - 0x8a, 0xdc, 0x32, 0x53, 0x1a, 0x4b, 0x06, 0x06, 0x8c, 0x12, 0xb9, 0xf7, - 0xd2, 0xf6, 0x5d, 0x12, 0x7b, 0x1b, 0xb9, 0xcf, 0x0d, 0x8c, 0xfe, 0xb2, - 0x4b, 0xfb, 0xaf, 0x0c, 0xf6, 0x1a, 0x89, 0xe1, 0xdb, 0xa0, 0x92, 0x3b, - 0xb0, 0x15, 0xaf, 0x76, 0xe5, 0x22, 0x5f, 0x93, 0x0f, 0x08, 0x33, 0xa6, - 0xe0, 0x52, 0x00, 0x49, 0x7d, 0xf2, 0xd0, 0xdd, 0xe0, 0xb5, 0xbb, 0x07, - 0x78, 0x2f, 0xd3, 0x17, 0xe0, 0xce, 0xd1, 0x60, 0xef, 0x26, 0x27, 0x68, - 0x81, 0x7e, 0x23, 0xa2, 0xcf, 0x93, 0x12, 0xc6, 0x44, 0x1b, 0xaf, 0x47, - 0x8b, 0x26, 0x47, 0xba, 0x95, 0x7c, 0x2f, 0xc0, 0xff, 0xc6, 0xdc, 0xe8, - 0x1f, 0x2c, 0x35, 0xa1, 0x4b, 0xdc, 0x16, 0x1a, 0xbf, 0x78, 0x05, 0xbc, - 0xb2, 0x1d, 0x69, 0x75, 0x74, 0x6e, 0x32, 0x05, 0x4e, 0x20, 0x6e, 0x1f, - 0xaf, 0x11, 0xf2, 0x37, 0x41, 0x0a, 0x7b, 0xfd, 0x28, 0x9f, 0xa4, 0x47, - 0xfc, 0x25, 0xf5, 0x1c, 0xd5, 0x62, 0xde, 0x84, 0xcb, 0xf9, 0x52, 0xe2, - 0xdd, 0x26, 0x3f, 0x8e, 0x8c, 0xd4, 0xba, 0x54, 0x34, 0xbf, 0x9b, 0xff, - 0x9e, 0x05, 0x2f, 0x9c, 0x98, 0xce, 0xa6, 0x4e, 0x36, 0xde, 0x96, 0x81, - 0x30, 0x05, 0x75, 0x07, 0xdd, 0xa0, 0x74, 0x4f, 0x39, 0x60, 0xcb, 0x5e, - 0x26, 0x2e, 0xbb, 0x00, 0xaf, 0xf7, 0x3b, 0xd9, 0xb1, 0x70, 0x4f, 0xa4, - 0x31, 0x45, 0x06, 0x63, 0x61, 0x03, 0x45, 0x27, 0xe3, 0x66, 0xf7, 0x9f, - 0x15, 0x5b, 0x22, 0x45, 0xb7, 0x6d, 0xe8, 0xb2, 0x67, 0x35, 0x8e, 0x72, - 0x02, 0x76, 0xf4, 0xb4, 0x63, 0x4a, 0x7c, 0xd7, 0xd1, 0x00, 0x6c, 0x93, - 0xfc, 0x63, 0x53, 0x20, 0x40, 0x59, 0xbb, 0x2e, 0xad, 0x26, 0x9c, 0xff, - 0x63, 0xbf, 0xb8, 0x7c, 0x2c, 0x87, 0xb8, 0x5d, 0x07, 0xeb, 0x6d, 0x40, - 0x04, 0x8d, 0x48, 0xc2, 0x92, 0x67, 0x47, 0x16, 0x95, 0x9f, 0x31, 0x93, - 0x3e, 0x09, 0x92, 0x7f, 0xcf, 0xaf, 0x10, 0xec, 0x39, 0xff, 0xd7, 0xb7, - 0xee, 0x8f, 0x86, 0x4e, 0x02, 0x83, 0x04, 0x76, 0x9f, 0x32, 0xf5, 0xa6, - 0xc4, 0xeb, 0xc0, 0x7a, 0xa3, 0x9c, 0x77, 0xd0, 0xb8, 0x9e, 0xf7, 0xad, - 0x51, 0x69, 0xf0, 0x1b, 0xf6, 0x57, 0xde, 0x1e, 0x2b, 0x24, 0xa6, 0x15, - 0x20, 0xba, 0xde, 0xe5, 0xfb, 0x62, 0x60, 0x9c, 0x3e, 0x94, 0xa1, 0x6a, - 0x16, 0x02, 0xa2, 0xc0, 0xc7, 0xe9, 0x21, 0x33, 0x5b, 0xf2, 0x18, 0xbc, - 0x6b, 0x11, 0x13, 0x0a, 0xaa, 0x71, 0x4e, 0xd0, 0x6a, 0x17, 0x91, 0x65, - 0xfd, 0x5f, 0x5e, 0x93, 0xba, 0x9f, 0x70, 0xfa, 0x91, 0xc2, 0x74, 0xf2, - 0xbb, 0xe0, 0x47, 0xf5, 0x7c, 0x0a, 0x91, 0x3c, 0x08, 0x13, 0x74, 0x3f, - 0x63, 0xd6, 0x9c, 0xc6, 0xf6, 0x04, 0x7f, 0xd7, 0x5b, 0xa9, 0x8c, 0x74, - 0x0a, 0x57, 0x45, 0x32, 0x5e, 0x31, 0xf9, 0xa2, 0x68, 0xed, 0xc5, 0xba, - 0x08, 0xf5, 0x41, 0x83, 0x98, 0x65, 0x47, 0x9a, 0x86, 0x87, 0x75, 0x64, - 0xa6, 0xd2, 0x6c, 0xfe, 0x0b, 0xdd, 0x17, 0xb0, 0x4e, 0xbe, 0x09, 0xdb, - 0xe7, 0x2f, 0x5e, 0xd4, 0x2b, 0x2d, 0x2d, 0x26, 0x63, 0xd2, 0xeb, 0x64, - 0x79, 0xd2, 0x55, 0x4f, 0xf1, 0x45, 0x89, 0xc2, 0xf9, 0x38, 0x96, 0xab, - 0xba, 0x5a, 0xfb, 0x42, 0x06, 0xb9, 0xe6, 0x9d, 0x16, 0xaf, 0x79, 0x45, - 0xf7, 0xe7, 0xe6, 0x2e, 0xec, 0x1b, 0x69, 0xe6, 0xbf, 0x54, 0x88, 0x2c, - 0xea, 0xd2, 0x0c, 0xc6, 0x96, 0xfe, 0xc9, 0x5a, 0x5b, 0x16, 0xd8, 0x9a, - 0x13, 0x77, 0x43, 0x37, 0x88, 0xe8, 0x6a, 0x82, 0x06, 0xe4, 0x5d, 0x0a, - 0x50, 0xd9, 0xff, 0xd0, 0x62, 0xcd, 0x8c, 0xcf, 0x86, 0x47, 0xd4, 0xba, - 0x7b, 0xec, 0x4d, 0x78, 0xa5, 0xff, 0x67, 0x2f, 0xf8, 0x70, 0xf4, 0x42, - 0x4b, 0xce, 0xa3, 0xef, 0x25, 0x4c, 0x92, 0x3d, 0x7e, 0x10, 0xfb, 0x03, - 0x97, 0x0a, 0xfe, 0xf4, 0xd3, 0x73, 0x64, 0x00, 0xa1, 0x5e, 0x68, 0xdb, - 0x5f, 0x7a, 0xff, 0x2e, 0x9f, 0xe2, 0x75, 0xd4, 0xf9, 0xa4, 0x49, 0xf0, - 0xe9, 0x5b, 0xe2, 0x37, 0x3b, 0x0c, 0xa9, 0x0c, 0x77, 0x3b, 0x7a, 0x64, - 0xe4, 0x7a, 0x9f, 0x10, 0x9d, 0x18, 0x25, 0x92, 0xd0, 0xcf, 0x6d, 0x1c, - 0xdd, 0xc4, 0xd5, 0x51, 0x6c, 0x52, 0x92, 0x62, 0x57, 0xaa, 0x50, 0x44, - 0xdd, 0xc9, 0xef, 0x8d, 0x28, 0x8a, 0x8b, 0x9c, 0x2c, 0xf6, 0x8d, 0x42, - 0xa2, 0x83, 0xf9, 0xc8, 0xc6, 0x65, 0x0b, 0x6b, 0xd5, 0x5f, 0x76, 0x5e, - 0x76, 0xc1, 0x6f, 0x00, 0x2c, 0xc5, 0x8d, 0x27, 0x7b, 0x28, 0xf0, 0xa3, - 0x0d, 0x5d, 0x1e, 0xa9, 0x6e, 0xe6, 0x4c, 0xc0, 0x12, 0x22, 0x77, 0x0f, - 0x9e, 0x73, 0xba, 0x83, 0x41, 0xbf, 0x8f, 0x0d, 0x7c, 0x27, 0x65, 0x85, - 0x76, 0x88, 0xf4, 0xf1, 0x65, 0x33, 0x55, 0x27, 0x18, 0xcb, 0x1d, 0xd0, - 0xc8, 0xf7, 0x2d, 0x53, 0x94, 0x1f, 0x2a, 0xfa, 0xdd, 0x48, 0xf7, 0x9a, - 0x25, 0xf4, 0xba, 0x8c, 0x16, 0xd3, 0xfa, 0xec, 0x7f, 0x67, 0x28, 0x61, - 0x44, 0x0a, 0x55, 0xaf, 0x9e, 0xd1, 0x51, 0x69, 0x9d, 0x22, 0x3b, 0xf5, - 0x17, 0x23, 0x4c, 0xb9, 0x79, 0xcc, 0xac, 0x6e, 0xc0, 0x3e, 0x81, 0xa6, - 0x4e, 0xec, 0x98, 0x18, 0x6f, 0xf1, 0x05, 0x68, 0xd5, 0x9c, 0x43, 0x1c, - 0x17, 0xbc, 0x34, 0x9d, 0xa5, 0x9f, 0x87, 0x53, 0x0d, 0xdf, 0xf7, 0xa1, - 0xb2, 0xab, 0x5d, 0x0e, 0xc6, 0xb7, 0x7a, 0x0d, 0xe5, 0x35, 0xfc, 0xab, - 0xea, 0x40, 0xfb, 0xd5, 0xc6, 0xc0, 0x4c, 0xfc, 0x28, 0x5c, 0xc0, 0x0a, - 0x4d, 0xac, 0x1e, 0xb0, 0xb3, 0x63, 0xdd, 0x9d, 0x48, 0x87, 0xee, 0x2d, - 0xb3, 0x63, 0xbf, 0x9c, 0x21, 0xe2, 0x5c, 0xd6, 0x03, 0x79, 0x25, 0x00, - 0x98, 0xf8, 0xf6, 0xb5, 0x4c, 0x6f, 0xfb, 0x16, 0x09, 0xbc, 0x64, 0x10, - 0x78, 0xb7, 0x57, 0x26, 0x40, 0x0c, 0xf1, 0x09, 0xcc, 0x93, 0xc1, 0x52, - 0xf4, 0x74, 0xf6, 0x96, 0xb6, 0x97, 0x73, 0xcd, 0x1a, 0xb4, 0x4d, 0xac, - 0x4f, 0xfd, 0x76, 0x0a, 0xc1, 0xc0, 0xd7, 0x94, 0xe4, 0x89, 0xd5, 0xc6, - 0x37, 0xe1, 0xf8, 0x47, 0x20, 0x78, 0xc8, 0xf9, 0xe9, 0xdf, 0xaa, 0xe9, - 0x53, 0x51, 0x0c, 0xc5, 0xac, 0xea, 0x6c, 0xd4, 0x4d, 0x2e, 0x4d, 0x78, - 0x36, 0x00, 0x36, 0x5b, 0xce, 0xca, 0x92, 0xea, 0xb9, 0x90, 0x7e, 0x15, - 0xc2, 0xe2, 0xa9, 0xff, 0x53, 0xa5, 0x91, 0x0f, 0x26, 0x79, 0x72, 0x8e, - 0x69, 0xd9, 0xde, 0xdf, 0x41, 0x85, 0x5a, 0x9b, 0xbe, 0xb7, 0xf7, 0x0f, - 0x0c, 0x24, 0x55, 0xc9, 0x64, 0x85, 0x69, 0xa5, 0x09, 0x92, 0x25, 0x47, - 0x0a, 0x47, 0x49, 0x3d, 0x16, 0x2d, 0xe1, 0x44, 0xf9, 0x3a, 0x0a, 0x82, - 0xcf, 0x3a, 0xf4, 0x1f, 0x18, 0xc4, 0xba, 0x5c, 0x4a, 0xdb, 0xe8, 0xf3, - 0xbb, 0xa4, 0x71, 0x96, 0x6f, 0x5a, 0x77, 0x53, 0x74, 0xf9, 0x40, 0xbc, - 0xae, 0x54, 0xf5, 0x02, 0xae, 0xd1, 0x5f, 0x08, 0xf6, 0x44, 0x65, 0x70, - 0xc2, 0x97, 0x34, 0x10, 0x9a, 0x74, 0x6c, 0x4f, 0x22, 0xa1, 0x50, 0xdf, - 0x17, 0xec, 0x82, 0xed, 0x1d, 0xca, 0x19, 0xdd, 0x67, 0x56, 0x77, 0x3f, - 0x3d, 0x91, 0x19, 0x0e, 0xbb, 0x3b, 0x71, 0x4c, 0xfc, 0x48, 0x60, 0x49, - 0xb2, 0x40, 0x80, 0xbf, 0xc6, 0x71, 0xdf, 0x58, 0x59, 0x73, 0x68, 0x4e, - 0xdb, 0x63, 0xc8, 0xd8, 0x37, 0x97, 0x6a, 0x0a, 0x2a, 0x46, 0xbf, 0xd6, - 0xab, 0x38, 0xaf, 0xf6, 0x42, 0xe6, 0x82, 0x49, 0x3b, 0x6a, 0x0a, 0x43, - 0x04, 0x59, 0xd3, 0x29, 0xf5, 0xd7, 0xef, 0x9e, 0x81, 0x57, 0x3e, 0xa9, - 0x65, 0xa2, 0x20, 0xfd, 0xa3, 0xdc, 0x1e, 0xc3, 0xde, 0xcc, 0x7d, 0xc0, - 0x93, 0xb9, 0x60, 0x56, 0x52, 0x13, 0x51, 0x98, 0xac, 0x60, 0xc2, 0x5f, - 0x84, 0xe9, 0xd6, 0xaa, 0xc6, 0x3c, 0x50, 0x99, 0x98, 0xf5, 0x6e, 0xd7, - 0x7c, 0xe1, 0x08, 0x80, 0x24, 0x76, 0xd0, 0xcc, 0x3a, 0xbd, 0x31, 0x18, - 0x40, 0x7f, 0x79, 0x66, 0xf4, 0x74, 0xb5, 0x83, 0xb3, 0xe2, 0xcc, 0xbc, - 0x49, 0x67, 0x5f, 0x3a, 0x1f, 0xd2, 0x4f, 0x79, 0xf6, 0x38, 0x67, 0xf6, - 0x02, 0x55, 0x21, 0x64, 0xf2, 0x93, 0x5e, 0xbb, 0x3d, 0xa7, 0x5a, 0xc6, - 0xa7, 0x90, 0xd6, 0x46, 0x71, 0x13, 0xb0, 0xa3, 0x47, 0xfe, 0xd5, 0xe0, - 0x17, 0xbd, 0xdc, 0x35, 0x72, 0x68, 0x4e, 0xa0, 0x96, 0xc2, 0xbc, 0x78, - 0x5b, 0xb1, 0x4f, 0x34, 0x26, 0xdc, 0x0f, 0x84, 0x58, 0x6e, 0x7d, 0xb1, - 0x54, 0xc2, 0x9d, 0xac, 0x2c, 0xde, 0xf5, 0xf8, 0x72, 0x43, 0x15, 0x5c, - 0x52, 0x48, 0x0c, 0x67, 0x39, 0x25, 0x8c, 0x3f, 0x49, 0xd2, 0x8b, 0x51, - 0x43, 0xe8, 0x2f, 0x3c, 0x16, 0xdc, 0x48, 0x0b, 0x76, 0xee, 0xd9, 0xb7, - 0x8e, 0x2e, 0x99, 0xbb, 0xa5, 0xda, 0xdd, 0xfe, 0x99, 0x47, 0xf1, 0x22, - 0x53, 0xfc, 0x2e, 0xaa, 0xf7, 0xcf, 0x7b, 0x13, 0x1b, 0x08, 0x18, 0x3a, - 0x6b, 0xe4, 0x66, 0x8a, 0x3e, 0x77, 0xbd, 0x14, 0xb0, 0x90, 0x60, 0xaa, - 0x97, 0x65, 0x1a, 0xd5, 0x0e, 0xea, 0x12, 0xa5, 0x05, 0x87, 0x78, 0x0f, - 0xf4, 0x05, 0xd5, 0x8c, 0x2e, 0x14, 0x26, 0x80, 0x01, 0x7d, 0x06, 0x79, - 0x37, 0x63, 0x70, 0xb1, 0x57, 0x2b, 0x62, 0x2a, 0xe8, 0x76, 0x48, 0x46, - 0x79, 0xea, 0x4a, 0x7a, 0x35, 0xf2, 0xcb, 0x10, 0x7a, 0x3b, 0x62, 0x04, - 0x34, 0x76, 0xe0, 0xf7, 0x9c, 0x1d, 0x73, 0x89, 0x90, 0xf2, 0xc5, 0x79, - 0x7c, 0x15, 0xa0, 0x7f, 0x99, 0x5f, 0xb8, 0x73, 0x62, 0x75, 0x6b, 0x0f, - 0xbe, 0xf1, 0x34, 0x5f, 0x28, 0x14, 0x18, 0x71, 0xe9, 0xde, 0xb7, 0x28, - 0x00, 0x65, 0xa2, 0x08, 0x57, 0xdd, 0x5e, 0x14, 0xa9, 0xc5, 0x0b, 0xb1, - 0x92, 0xa8, 0x20, 0xb2, 0xbd, 0x42, 0x77, 0xf5, 0xb0, 0xa0, 0x00, 0xbe, - 0xa7, 0x82, 0xd0, 0x6a, 0xc8, 0xa9, 0x57, 0xfa, 0x07, 0x3a, 0x97, 0x69, - 0x60, 0xe8, 0xd1, 0x94, 0x0d, 0xa5, 0x7d, 0x74, 0x7f, 0x50, 0xc6, 0x50, - 0x9b, 0x05, 0x41, 0x8d, 0x08, 0x2b, 0x2b, 0x01, 0x37, 0xd0, 0xee, 0x4d, - 0xca, 0x15, 0x70, 0xca, 0x75, 0x4a, 0xc2, 0x54, 0x10, 0xc0, 0x80, 0x27, - 0xe1, 0xcd, 0x52, 0xec, 0x06, 0xb5, 0x73, 0xf4, 0xc2, 0x0b, 0xea, 0x79, - 0xe6, 0x30, 0x5d, 0x41, 0x07, 0x4c, 0x8a, 0xae, 0x03, 0xb0, 0x9b, 0xc2, - 0x5d, 0xf2, 0x43, 0x3f, 0x5e, 0xb7, 0x53, 0x36, 0xc3, 0x81, 0xf6, 0xe5, - 0xd9, 0x35, 0x69, 0x04, 0xe0, 0x36, 0xb8, 0xeb, 0x71, 0x58, 0x71, 0x6f, - 0x47, 0x17, 0xf2, 0x16, 0xe2, 0x09, 0xc7, 0xc2, 0x35, 0xa4, 0x4d, 0xfe, - 0x1a, 0xd2, 0x28, 0x06, 0x34, 0xb3, 0x0f, 0x33, 0xf0, 0xd6, 0x18, 0xf4, - 0x6d, 0x54, 0xb2, 0xbd, 0x88, 0x17, 0x02, 0x40, 0x11, 0x21, 0x59, 0x8b, - 0x62, 0xcb, 0x87, 0xad, 0x0f, 0xc0, 0x08, 0x14, 0x29, 0xf9, 0x5c, 0x3e, - 0xfc, 0xe4, 0x95, 0x1c, 0x9b, 0x60, 0x94, 0xcb, 0x83, 0xb4, 0x1c, 0x1b, - 0xbd, 0xfd, 0x55, 0x88, 0xbf, 0xa6, 0xa5, 0x94, 0xc2, 0xb3, 0x76, 0x5a, - 0x9b, 0xd4, 0xc1, 0xe1, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x51, 0x00, - 0x0a, 0xec, 0x05, 0xf9, 0x03, 0x35, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x85, 0x61, 0x04, 0x23, 0x00, 0x07, 0x07, 0x09, 0x34, 0x00, 0x09, - 0x09, 0x09, 0x34, 0x34, 0x08, 0x01, 0x02, 0x02, 0x08, 0x08, 0x08, 0x08, - 0x09, 0x08, 0x08, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x09, 0x89, - 0x56, 0x17, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x83, 0x2b, 0xa8, 0x0d, 0x41, - 0xb7, 0x59, 0x5c, 0x83, 0x2b, 0xa8, 0x0d, 0xdf, 0xb4, 0xb1, 0x32, 0xb5, - 0x0f, 0xc0, 0x25, 0xc5, 0x8d, 0xd9, 0x08, 0xc5, 0x28, 0x81, 0xd3, 0x73, - 0x52, 0xf9, 0x26, 0x9b, 0x66, 0x83, 0xaf, 0x24, 0x40, 0x8e, 0xa7, 0xd6, - 0x76, 0x12, 0x4a, 0x40, 0x61, 0xb5, 0x6a, 0xbc, 0x33, 0xef, 0x01, 0xda, - 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, - 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0x2b, 0x01, 0x00, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, - 0x4e, 0x6b, 0x19, 0x54, 0xf5, 0xf0, 0xaf, 0x61, 0xfa, 0x1e, 0x1f, 0x1f, - 0x5e, 0x17, 0xd3, 0x8e, 0x04, 0x4b, 0xfa, 0x8d, 0x34, 0x55, 0x45, 0x92, - 0xd5, 0xd0, 0xb8, 0x8e, 0x56, 0xe9, 0x39, 0x37, 0x8e, 0x7d, 0x7e, 0x88, - 0x56, 0x30, 0x48, 0x61, 0xb4, 0xed, 0x1e, 0x15, 0x64, 0xfc, 0xa8, 0xb1, - 0x02, 0xbb, 0x9c, 0x14, 0xe9, 0xd1, 0xe0, 0xcf, 0x40, 0x41, 0x46, 0x5d, - 0xb0, 0xda, 0xba, 0x8c, 0x3a, 0x41, 0x12, 0x91, 0xeb, 0x13, 0xdf, 0x2c, - 0x6e, 0x25, 0x75, 0xb3, 0x92, 0xff, 0xb0, 0xa9, 0xa5, 0xef, 0x3a, 0x4c, - 0x6b, 0x54, 0x55, 0x0e, 0x7e, 0x93, 0x16, 0x7f, 0xe6, 0x22, 0x22, 0x51, - 0xe2, 0x22, 0xa4, 0x35, 0x33, 0xec, 0xdc, 0xa8, 0x73, 0x64, 0x59, 0xc1, - 0x4d, 0xad, 0xa0, 0x56, 0xbf, 0xad, 0x45, 0x64, 0xda, 0xb0, 0x08, 0x4a, - 0x82, 0xfc, 0x0d, 0x21, 0xb7, 0x8b, 0x59, 0x90, 0xac, 0xb2, 0x08, 0x1b, - 0x50, 0x82, 0x0c, 0x87, 0xd6, 0x48, 0x5c, 0xdd, 0x6b, 0x02, 0x7f, 0xab, - 0x3e, 0xdc, 0x25, 0x1f, 0x53, 0x49, 0xb5, 0x6d, 0x0f, 0x0c, 0xbe, 0xae, - 0x1d, 0xab, 0x8b, 0x13, 0x9d, 0xd7, 0x6c, 0x91, 0xaa, 0x90, 0xe8, 0x63, - 0x06, 0x6d, 0xa8, 0xf0, 0xea, 0x21, 0xf6, 0xa8, 0xfd, 0x15, 0x6d, 0x78, - 0x66, 0x42, 0xae, 0x4c, 0xa7, 0x7a, 0x85, 0x15, 0x7d, 0xf9, 0xed, 0x92, - 0x1c, 0xde, 0x7c, 0x71, 0xd0, 0x6b, 0x25, 0x24, 0x22, 0x6b, 0xe4, 0x5e, - 0x60, 0xda, 0xbd, 0x95, 0x32, 0x21, 0xe8, 0xb1, 0xcb, 0x07, 0x1b, 0x08, - 0xf5, 0x49, 0x4f, 0x60, 0x8c, 0xe8, 0xb0, 0x71, 0x2a, 0x8b, 0x91, 0x17, - 0x16, 0x93, 0x39, 0x49, 0x8d, 0x47, 0x1f, 0xe8, 0x2b, 0x12, 0xa6, 0x4f, - 0xa1, 0x77, 0x37, 0xe7, 0x39, 0x68, 0x5c, 0x68, 0x2b, 0xad, 0xa8, 0x3c, - 0xa0, 0x8a, 0xf5, 0xb7, 0x51, 0x9f, 0x2d, 0x85, 0x1a, 0x99, 0x02, 0x4c, - 0x84, 0x5f, 0x4d, 0xe6, 0x55, 0x64, 0xd7, 0x5b, 0x00, 0x48, 0xde, 0xf2, - 0x77, 0x39, 0x6e, 0x7b, 0x0e, 0x97, 0x81, 0xd2, 0x8a, 0x1b, 0x20, 0x30, - 0x60, 0xbe, 0x94, 0xf0, 0x09, 0x34, 0xfe, 0x64, 0xbb, 0xbb, 0xcb, 0x97, - 0x91, 0x43, 0x6d, 0x57, 0x45, 0x7d, 0xc5, 0x43, 0x5a, 0x78, 0x0d, 0xd8, - 0xb9, 0xf5, 0x43, 0x13, 0x21, 0xd6, 0x31, 0x6e, 0x21, 0x9a, 0x3f, 0x8f, - 0xe2, 0x57, 0x32, 0xdb, 0x50, 0x61, 0x45, 0x9f, 0xb9, 0x7b, 0x73, 0x10, - 0xb9, 0xd0, 0x66, 0xaf, 0xa0, 0x3a, 0x77, 0x93, 0x9b, 0xd3, 0x32, 0xb0, - 0xda, 0x01, 0x17, 0x90, 0x1a, 0xa5, 0x9f, 0x2b, 0x9f, 0x8f, 0x93, 0x6e, - 0x4d, 0x69, 0x40, 0xec, 0x56, 0x76, 0x61, 0x2d, 0xcd, 0xdf, 0xc5, 0xfe, - 0x9e, 0x26, 0x2f, 0x78, 0x78, 0xab, 0x5a, 0x32, 0xa6, 0xe9, 0x7a, 0x85, - 0x15, 0xc6, 0x2f, 0x10, 0x37, 0x35, 0xf6, 0xfa, 0xc0, 0xdd, 0xb0, 0xa9, - 0xa1, 0x0d, 0x22, 0xc1, 0xab, 0xc8, 0x8c, 0x2a, 0x77, 0x0b, 0xd3, 0x52, - 0xdb, 0x53, 0x33, 0x78, 0xf3, 0xf6, 0x33, 0x5d, 0x9f, 0xb7, 0xb6, 0x46, - 0xf6, 0x79, 0x9e, 0x08, 0x16, 0xd8, 0x48, 0xcf, 0x70, 0x4d, 0x00, 0x36, - 0x30, 0xdb, 0xb3, 0x76, 0xa5, 0x16, 0x78, 0xf8, 0xaf, 0x71, 0x6b, 0x50, - 0x92, 0xfc, 0x52, 0xd6, 0x2c, 0xee, 0xa8, 0xb0, 0xbe, 0x89, 0x18, 0xc0, - 0x7a, 0x72, 0xa5, 0x36, 0x31, 0x7b, 0x86, 0xca, 0xc0, 0xe4, 0x08, 0x17, - 0x1d, 0x6e, 0xe5, 0x4c, 0x82, 0x86, 0x3e, 0x8c, 0x60, 0xf7, 0x04, 0x8f, - 0x2c, 0x64, 0x3d, 0x2e, 0x23, 0x22, 0x10, 0x8e, 0x88, 0x45, 0xcd, 0x18, - 0xd6, 0xba, 0x4c, 0x40, 0x1e, 0x31, 0xfb, 0xbf, 0xda, 0xe7, 0xae, 0x87, - 0x72, 0x81, 0xb2, 0x69, 0x97, 0xe3, 0x2c, 0x5e, 0xbb, 0x26, 0x1b, 0xe2, - 0x83, 0xf3, 0x90, 0x37, 0x0d, 0xb1, 0xa2, 0x58, 0x88, 0x63, 0xe7, 0x6e, - 0x4a, 0xbd, 0x76, 0x90, 0x73, 0x65, 0x85, 0x96, 0xcc, 0x2d, 0xb7, 0x51, - 0x0d, 0xa7, 0x8a, 0xe2, 0x8c, 0x47, 0xb9, 0x44, 0x09, 0xc3, 0x8f, 0x24, - 0x65, 0x79, 0xf0, 0xd0, 0xc3, 0xa5, 0x1f, 0xc3, 0xca, 0xd7, 0x57, 0xac, - 0x1c, 0xcf, 0xa9, 0xfc, 0x81, 0x12, 0x53, 0x0b, 0xe5, 0x9d, 0x38, 0x29, - 0x14, 0xd6, 0xf5, 0x17, 0x06, 0xfb, 0xc2, 0x9d, 0x25, 0x10, 0xf9, 0xde, - 0x4b, 0x33, 0x0d, 0xf1, 0xdd, 0xf5, 0xbc, 0xa8, 0x2b, 0xdc, 0xdb, 0x51, - 0x7d, 0x69, 0x63, 0x68, 0x61, 0x74, 0x64, 0x6b, 0x75, 0x85, 0x41, 0x03, - 0x23, 0x00, 0x07, 0x07, 0x08, 0x34, 0x00, 0x09, 0x09, 0x09, 0x34, 0x34, - 0x08, 0x01, 0x02, 0x02, 0x08, 0x08, 0x08, 0x08, 0x09, 0x08, 0x08, 0x09, - 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x09, 0x89, 0x16, 0x17, 0x13, 0x41, - 0xb7, 0x59, 0x5c, 0x83, 0x25, 0xab, 0x8f, 0x41, 0xb7, 0x59, 0x5c, 0x83, - 0x25, 0xab, 0x8f, 0xdf, 0xb4, 0xb1, 0x32, 0xb5, 0x0f, 0xc0, 0x25, 0xc5, - 0x8d, 0xd9, 0x08, 0xc5, 0x28, 0x81, 0xd3, 0x73, 0x52, 0xf9, 0x26, 0x9b, - 0x66, 0x83, 0xaf, 0x24, 0x40, 0x8e, 0xa7, 0xd6, 0x76, 0x12, 0x4a, 0x40, - 0x61, 0xb5, 0x6a, 0xbc, 0x33, 0xef, 0x01, 0xda, 0x39, 0xa3, 0xee, 0x5e, - 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, - 0xd8, 0x07, 0x09, 0x2b, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xe3, 0xb5, 0xfb, 0x0d, - 0xa0, 0x75, 0xd1, 0xa9, 0x33, 0x31, 0xc6, 0x84, 0xba, 0x58, 0x50, 0xb0, - 0x71, 0x32, 0x4f, 0x72, 0x88, 0x46, 0x71, 0x06, 0xb3, 0x82, 0x5e, 0x30, - 0xfd, 0xc8, 0x5b, 0xc8, 0xf3, 0x24, 0x92, 0xe0, 0xce, 0x8b, 0xf7, 0x50, - 0x20, 0xc3, 0xeb, 0x1b, 0xf4, 0xef, 0x4f, 0xfa, 0x28, 0x4d, 0x02, 0x4d, - 0x7c, 0x46, 0xf1, 0x91, 0x89, 0xde, 0xc6, 0xfa, 0x79, 0xc5, 0xbd, 0x17, - 0xa1, 0xc6, 0x1d, 0x8c, 0xd4, 0x57, 0xa6, 0x58, 0x66, 0xce, 0xe5, 0xb0, - 0x8b, 0x54, 0xef, 0x3b, 0x24, 0x9b, 0xa4, 0xc4, 0x6a, 0xa9, 0xf3, 0x1b, - 0x73, 0x37, 0x10, 0xc0, 0xe1, 0xcb, 0xc8, 0x90, 0x14, 0x88, 0x97, 0x25, - 0x8b, 0x7c, 0xa2, 0x66, 0x36, 0x89, 0x55, 0x8d, 0x68, 0xe7, 0x55, 0x20, - 0x10, 0x68, 0x14, 0x2f, 0x05, 0x3b, 0xe3, 0x81, 0x08, 0xfe, 0x54, 0x7d, - 0xa5, 0x51, 0x2a, 0x39, 0x86, 0x11, 0xce, 0x26, 0x8d, 0xe1, 0xec, 0x30, - 0x3f, 0xf9, 0xa3, 0x3d, 0x43, 0x6c, 0xad, 0x23, 0x54, 0x20, 0x7d, 0x60, - 0xa5, 0x42, 0xbd, 0x3d, 0x22, 0xc8, 0x95, 0x9b, 0xab, 0x5b, 0xf7, 0xc1, - 0x11, 0xfb, 0xf1, 0x70, 0xa2, 0x43, 0xcb, 0x53, 0x8c, 0x18, 0x0d, 0x8a, - 0xb2, 0xa5, 0xbd, 0x87, 0x2b, 0x8b, 0xdf, 0x79, 0x96, 0x29, 0x20, 0x8e, - 0x34, 0x4a, 0x45, 0x96, 0x33, 0x8d, 0xa8, 0xb0, 0x47, 0x26, 0x4f, 0x8b, - 0xad, 0xb5, 0xa7, 0x2d, 0x15, 0x58, 0x92, 0x7b, 0x4b, 0x53, 0xa9, 0x5e, - 0x51, 0x39, 0x9c, 0xbd, 0x7e, 0x8f, 0x7f, 0x9f, 0xb7, 0x38, 0xcd, 0x7e, - 0xff, 0x7d, 0x73, 0x1f, 0xab, 0x3a, 0x61, 0xaa, 0xde, 0x73, 0x28, 0xb2, - 0x6f, 0x1e, 0xc9, 0x5e, 0x59, 0x71, 0x6b, 0xe8, 0x6d, 0x63, 0xf3, 0x9e, - 0xdf, 0x52, 0x86, 0x60, 0x1c, 0xbd, 0xc7, 0xeb, 0xaf, 0x82, 0x83, 0xaa, - 0x68, 0xa6, 0x71, 0x7a, 0xe8, 0xd3, 0xd4, 0xc8, 0xe7, 0x9a, 0xcc, 0x3c, - 0xc2, 0xdf, 0x0c, 0x42, 0xe8, 0xae, 0xc7, 0xd8, 0x1f, 0x66, 0x0a, 0x57, - 0x09, 0x14, 0x02, 0x74, 0x9a, 0x7a, 0x07, 0xb3, 0x19, 0x87, 0x8d, 0xa9, - 0x45, 0x25, 0x26, 0x48, 0xb3, 0x20, 0x3c, 0xf7, 0x5a, 0x1c, 0xae, 0xc7, - 0x06, 0x9e, 0x1a, 0x0a, 0x23, 0xf3, 0x39, 0x25, 0x2c, 0x91, 0x7c, 0x5e, - 0x87, 0xe7, 0x55, 0xc4, 0x69, 0xf3, 0x3e, 0xeb, 0xc5, 0x44, 0xa8, 0xe3, - 0xec, 0xc1, 0xfe, 0x70, 0xbf, 0xdd, 0xbb, 0xf0, 0x22, 0xe1, 0x19, 0xa1, - 0x6d, 0x7a, 0x9a, 0xa3, 0x36, 0x90, 0xbc, 0x1a, 0xa7, 0x37, 0xf8, 0xcf, - 0xdc, 0x9e, 0x23, 0x17, 0x42, 0xd5, 0xa0, 0xd3, 0x36, 0xb0, 0xb1, 0xf5, - 0x1a, 0x95, 0xbc, 0xe8, 0x0f, 0xb4, 0x58, 0x76, 0x40, 0x74, 0xd0, 0x21, - 0xaf, 0xae, 0xc6, 0xb4, 0x84, 0xd7, 0xfc, 0x70, 0x6a, 0x8f, 0x41, 0x57, - 0x2b, 0x8e, 0xbc, 0x6b, 0x21, 0x65, 0xcc, 0xa0, 0x8e, 0xb9, 0x0b, 0x46, - 0xef, 0xb3, 0x56, 0xec, 0x8a, 0xd6, 0x4d, 0xdd, 0x97, 0xbd, 0xdd, 0x65, - 0xbf, 0x26, 0xab, 0xba, 0x0d, 0xd1, 0x22, 0x7e, 0xb6, 0x8a, 0xb4, 0x92, - 0xc9, 0xa6, 0x48, 0xd4, 0x64, 0x17, 0xc6, 0xb5, 0xb9, 0xce, 0x45, 0x6d, - 0xf4, 0xd9, 0x3d, 0xa0, 0xb3, 0x86, 0x67, 0x19, 0xad, 0xd8, 0x32, 0x2b, - 0xf7, 0xab, 0x90, 0xee, 0x91, 0x8f, 0x73, 0xe4, 0xc0, 0x29, 0xde, 0x45, - 0x8a, 0xfb, 0xca, 0x74, 0x3b, 0x50, 0xf1, 0x34, 0x40, 0x36, 0x25, 0x8a, - 0xe0, 0xf9, 0x7f, 0x55, 0xc5, 0x59, 0x89, 0xbb, 0x43, 0x03, 0xa3, 0xdd, - 0x8c, 0x83, 0x03, 0xc6, 0xef, 0x60, 0x02, 0xc5, 0xd8, 0x29, 0x3f, 0x2f, - 0x56, 0xba, 0x8b, 0x97, 0x0a, 0xc4, 0xf3, 0x07, 0x3f, 0xca, 0x0f, 0xdf, - 0xb9, 0x5d, 0x59, 0x42, 0x36, 0x02, 0xf7, 0x0f, 0x03, 0xc8, 0xf2, 0xb7, - 0xd8, 0x64, 0xcd, 0x1e, 0xe4, 0xe1, 0xa0, 0xbd, 0x0f, 0x70, 0xfb, 0xcf, - 0x77, 0x77, 0xef, 0x9d, 0xdd, 0xc1, 0x61, 0xab, 0x3c, 0xdb, 0xe4, 0x35, - 0x11, 0xab, 0xde, 0x40, 0x7d, 0x51, 0xba, 0xb1, 0x7d, 0x13, 0xf1, 0x58, - 0x03, 0xca, 0xae, 0x12, 0x4a, 0xa3, 0xb6, 0xed, 0xd7, 0x18, 0x1c, 0xb6, - 0xd8, 0x69, 0x63, 0x68, 0x61, 0x74, 0x64, 0x6b, 0x75, 0x89, 0x70, 0x02, - 0x23, 0x00, 0x07, 0x07, 0x09, 0x34, 0x00, 0x09, 0x09, 0x09, 0x34, 0x34, - 0x08, 0x01, 0x02, 0x02, 0x08, 0x08, 0x08, 0x08, 0x09, 0x08, 0x08, 0x09, - 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x09, 0x91, 0x62, 0x29, 0x13, 0x41, - 0xb7, 0x59, 0x5c, 0x4b, 0xa2, 0xb8, 0x84, 0x41, 0xb7, 0x59, 0x5c, 0x4b, - 0xa2, 0xb8, 0x84, 0x37, 0xee, 0x5a, 0x85, 0xe1, 0xcb, 0xdd, 0xc8, 0xce, - 0x07, 0x77, 0xee, 0x01, 0x3f, 0x96, 0x7b, 0x33, 0x30, 0x3a, 0xcd, 0x64, - 0x14, 0x5e, 0x86, 0xb3, 0x7b, 0x2d, 0x6c, 0xa9, 0xc0, 0xcf, 0xd8, 0x43, - 0x7e, 0x59, 0x45, 0xac, 0xff, 0x92, 0x4b, 0xda, 0x39, 0xa3, 0xee, 0x5e, - 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, - 0xd8, 0x07, 0x09, 0x2a, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xfa, 0x4b, 0x92, 0xea, - 0x4b, 0xef, 0xde, 0x03, 0xd5, 0xe2, 0xee, 0xe5, 0x67, 0xd4, 0x99, 0x63, - 0x37, 0x68, 0x91, 0xbc, 0x4f, 0xbc, 0x41, 0xe9, 0x01, 0xc5, 0x4d, 0x59, - 0x2a, 0x9b, 0x42, 0x60, 0x07, 0x7e, 0xc2, 0xbc, 0x62, 0xcc, 0xbc, 0xa7, - 0xf1, 0xe4, 0x20, 0x5f, 0xe3, 0xe8, 0x9f, 0x16, 0x7a, 0x77, 0xd2, 0xb7, - 0xad, 0x98, 0xc3, 0xb4, 0x99, 0xdb, 0x36, 0x1a, 0xe4, 0xf0, 0xfc, 0xe1, - 0xc8, 0x2f, 0x8c, 0xcf, 0x6f, 0x97, 0x48, 0x09, 0x4a, 0xae, 0xc7, 0xf9, - 0xfb, 0xb7, 0x5f, 0x64, 0x6a, 0x79, 0xa1, 0x27, 0xeb, 0x59, 0x7d, 0x0a, - 0xd3, 0x56, 0x27, 0x1d, 0x56, 0xd3, 0x62, 0x1e, 0x7f, 0xb5, 0x0f, 0x50, - 0x9c, 0x4d, 0x1d, 0xd5, 0x53, 0xcb, 0x08, 0x07, 0x56, 0x93, 0x9e, 0x4f, - 0xb2, 0xd0, 0x12, 0xc7, 0x50, 0xcf, 0x99, 0xac, 0x24, 0xdb, 0x94, 0xab, - 0x08, 0x89, 0x60, 0x2f, 0x6c, 0xd0, 0xc2, 0x2e, 0x6d, 0x08, 0xe0, 0xf9, - 0xfc, 0x7e, 0x5b, 0x54, 0x92, 0xaa, 0x01, 0xfd, 0xf6, 0x49, 0xb1, 0xfc, - 0xd4, 0x51, 0x83, 0x73, 0xaf, 0xac, 0x38, 0x78, 0x8e, 0x9b, 0x42, 0x4e, - 0x83, 0xbb, 0x9d, 0xd7, 0x5c, 0xdb, 0x73, 0xd3, 0x3d, 0x2c, 0xe2, 0x4c, - 0x57, 0xa4, 0xfa, 0xdf, 0x53, 0x44, 0x29, 0x71, 0x22, 0xb6, 0x89, 0x84, - 0x80, 0xca, 0xcb, 0x7c, 0x5f, 0x15, 0x19, 0x4b, 0x06, 0x28, 0x5d, 0x4a, - 0x9b, 0xc8, 0x59, 0xa7, 0x9e, 0xa2, 0xba, 0x32, 0x5d, 0xf2, 0xcb, 0xa9, - 0xc6, 0xba, 0x09, 0xee, 0xd2, 0x00, 0x32, 0x53, 0x8b, 0x39, 0xff, 0xc4, - 0x63, 0xac, 0xbc, 0x1c, 0x15, 0xb8, 0x79, 0xc2, 0xe3, 0xda, 0x8d, 0xb2, - 0x95, 0x8d, 0x3c, 0x10, 0xec, 0x93, 0x03, 0xc1, 0x07, 0x84, 0x47, 0xf3, - 0xeb, 0xe3, 0x10, 0x33, 0xa1, 0x2e, 0xc6, 0x48, 0x44, 0x2c, 0x38, 0x36, - 0xe1, 0x68, 0x3c, 0xe8, 0x0d, 0x5c, 0x8a, 0xdc, 0x1f, 0xe8, 0x3b, 0xb2, - 0x0f, 0xea, 0x27, 0x18, 0x7a, 0x7f, 0x82, 0x6a, 0x96, 0xfa, 0x63, 0xd3, - 0x5c, 0xbf, 0xf6, 0x1d, 0x9e, 0xf2, 0xd9, 0x83, 0x3b, 0xf0, 0x1b, 0x29, - 0x49, 0x8d, 0xb3, 0xdc, 0x60, 0x47, 0x9d, 0x2b, 0xac, 0xd6, 0x6e, 0x59, - 0xb3, 0x09, 0x0d, 0xa7, 0xfb, 0x0e, 0x43, 0x56, 0xa3, 0x80, 0x2c, 0x9f, - 0xc1, 0xe8, 0xd2, 0xef, 0x05, 0xc5, 0x25, 0x4c, 0x5b, 0x67, 0x1a, 0x54, - 0x0b, 0x55, 0x83, 0x3d, 0xfb, 0x38, 0x0e, 0xd2, 0xc0, 0x1a, 0xcd, 0x9f, - 0x81, 0x3e, 0x6d, 0x7f, 0xe4, 0x3f, 0x34, 0x0c, 0xdc, 0x99, 0x5a, 0x77, - 0xd4, 0xe4, 0xff, 0x4a, 0x7b, 0x8a, 0x95, 0xe4, 0x46, 0x3d, 0x7b, 0xc4, - 0x0e, 0xdd, 0xc7, 0x2d, 0xf4, 0xfa, 0x5e, 0x50, 0xae, 0x9c, 0xca, 0x64, - 0x97, 0xad, 0x03, 0x30, 0x3e, 0x05, 0xc4, 0x33, 0x1e, 0x2c, 0x03, 0x2b, - 0x06, 0x2c, 0x79, 0x13, 0xae, 0x1b, 0x65, 0xf1, 0x1f, 0xb9, 0xe4, 0x8a, - 0x06, 0x96, 0xea, 0xc4, 0x6e, 0x17, 0x19, 0x03, 0x54, 0xe8, 0x39, 0xe7, - 0xeb, 0x7b, 0xbc, 0x25, 0xd6, 0x55, 0x6c, 0x76, 0x5f, 0xf7, 0xd2, 0x0e, - 0x54, 0x46, 0x9f, 0x5d, 0xa4, 0x3d, 0xac, 0xa1, 0x19, 0x7b, 0x7c, 0x5a, - 0x44, 0x54, 0x65, 0x5d, 0x43, 0x26, 0x5f, 0x47, 0x63, 0x2b, 0x00, 0xe3, - 0xb4, 0xe9, 0x70, 0x8c, 0x31, 0x50, 0x7c, 0x37, 0x01, 0x43, 0x6c, 0x29, - 0xc3, 0xae, 0x59, 0xb7, 0x0b, 0xb9, 0x9a, 0x72, 0x69, 0xe0, 0xd1, 0xb0, - 0x47, 0x53, 0xf0, 0xb8, 0x8b, 0xc8, 0x80, 0x3c, 0x58, 0xfa, 0x34, 0xf2, - 0x44, 0x27, 0xb7, 0xfc, 0x44, 0x73, 0xfb, 0xe5, 0xe1, 0x8b, 0xdb, 0x2b, - 0xc5, 0x73, 0x97, 0x25, 0xb3, 0xef, 0x16, 0xfd, 0xba, 0x08, 0x3d, 0x15, - 0x2a, 0x03, 0xb5, 0x4d, 0x2a, 0x8c, 0xf5, 0x53, 0x11, 0x97, 0x3c, 0x35, - 0x66, 0x1d, 0x59, 0xc8, 0xc9, 0x79, 0x48, 0x6d, 0x19, 0x4f, 0xa7, 0x07, - 0x25, 0x4d, 0xb2, 0xfc, 0x1e, 0xbc, 0x9a, 0x0c, 0x6e, 0x46, 0x2b, 0x58, - 0x45, 0xbe, 0xe7, 0x8e, 0x09, 0xa5, 0xa0, 0xd3, 0x5a, 0xf5, 0x6e, 0x92, - 0x7b, 0x5b, 0x21, 0x07, 0xab, 0xf3, 0x57, 0xd6, 0x93, 0x4b, 0x56, 0x3b, - 0x9c, 0x3c, 0x4b, 0x85, 0xb0, 0x62, 0x18, 0x3e, 0x7c, 0xc5, 0x25, 0xe2, - 0xf2, 0xfc, 0xa3, 0xca, 0x88, 0xd6, 0xb2, 0x01, 0x11, 0xcd, 0x93, 0x9a, - 0x76, 0x84, 0xc2, 0x2d, 0x07, 0xd3, 0xbb, 0xac, 0x99, 0xde, 0x29, 0x00, - 0xf7, 0x3d, 0x06, 0xea, 0xdc, 0x88, 0xfd, 0xc6, 0x6e, 0xf5, 0x55, 0x64, - 0x73, 0x4e, 0x3b, 0xa9, 0x24, 0x44, 0x63, 0x1c, 0x50, 0x29, 0x66, 0xc4, - 0x74, 0x70, 0xcb, 0xd8, 0x57, 0x0c, 0x60, 0x50, 0x6d, 0x64, 0x64, 0xd1, - 0x53, 0xef, 0x62, 0xef, 0x61, 0xf4, 0xe2, 0xfe, 0x4c, 0xaa, 0x9f, 0xe9, - 0x81, 0x01, 0xe1, 0x97, 0xaa, 0xc0, 0x06, 0xbf, 0x40, 0x19, 0x64, 0x24, - 0x6e, 0x80, 0x73, 0x00, 0x5c, 0x86, 0x3e, 0xc2, 0xcf, 0x8c, 0x09, 0xc0, - 0xfa, 0x4a, 0xb3, 0x3a, 0x0d, 0x81, 0x1d, 0x49, 0x58, 0x09, 0xe8, 0x31, - 0x0e, 0xd7, 0x60, 0x8d, 0x9d, 0xfe, 0x9f, 0x35, 0xf7, 0x8d, 0xa1, 0x12, - 0x04, 0xb2, 0x47, 0xac, 0x31, 0x92, 0x03, 0x0a, 0x10, 0x50, 0xb7, 0x86, - 0x3d, 0xcd, 0x15, 0x8f, 0x25, 0x93, 0x24, 0x7a, 0x5f, 0xa0, 0x3c, 0x41, - 0xaa, 0xb2, 0x96, 0xce, 0xd3, 0x0c, 0xe9, 0x55, 0x66, 0x37, 0x5c, 0xf3, - 0x02, 0x3c, 0xa1, 0x09, 0xa4, 0x9e, 0x90, 0xc9, 0x82, 0xab, 0xd4, 0x04, - 0x2e, 0x8b, 0xb4, 0x8d, 0x5b, 0xcc, 0x19, 0x5a, 0xfe, 0x86, 0x9c, 0x6c, - 0x56, 0x09, 0x86, 0x36, 0xef, 0xe8, 0x1f, 0x3a, 0xbc, 0xda, 0x4c, 0x68, - 0xac, 0xa2, 0x1b, 0xd1, 0x23, 0x75, 0x28, 0xed, 0x9f, 0x84, 0x2e, 0x40, - 0x57, 0x5f, 0x0a, 0x85, 0xe4, 0x77, 0x59, 0x53, 0x12, 0x32, 0xd6, 0x3c, - 0x1b, 0xaf, 0x95, 0xa1, 0x1c, 0x14, 0x1a, 0x42, 0x7d, 0xc7, 0x7b, 0x21, - 0xd1, 0x4e, 0xb9, 0x29, 0x85, 0xef, 0xa2, 0x61, 0x1c, 0xe5, 0x16, 0x44, - 0xbe, 0xfb, 0xa3, 0x21, 0x4f, 0x94, 0x70, 0xff, 0x5c, 0xc2, 0x1d, 0x0b, - 0x39, 0x36, 0x84, 0x0e, 0x61, 0xe2, 0x1c, 0x63, 0x74, 0xe0, 0x30, 0x01, - 0xbe, 0x39, 0x0f, 0x6f, 0xe6, 0x29, 0xad, 0xd8, 0x8c, 0xdd, 0x8b, 0x24, - 0x38, 0x6f, 0x67, 0x8a, 0x2d, 0x82, 0x1e, 0x8e, 0x45, 0xcb, 0xec, 0x2d, - 0xe3, 0xb4, 0x03, 0x8e, 0x46, 0x2e, 0x01, 0xb0, 0xca, 0x4f, 0xe0, 0x2c, - 0x52, 0xd3, 0x4c, 0xdd, 0xd6, 0x62, 0xf3, 0x38, 0x3f, 0x3c, 0xc1, 0x58, - 0xaa, 0x87, 0x3d, 0x4f, 0xb2, 0xb1, 0x54, 0x65, 0xdc, 0x1c, 0xc8, 0x16, - 0x88, 0x15, 0x53, 0xb0, 0x4e, 0x77, 0xae, 0xe0, 0x34, 0x18, 0x36, 0x34, - 0x31, 0x74, 0x4c, 0x79, 0x0f, 0x2b, 0x1a, 0x11, 0x06, 0x06, 0xaa, 0x60, - 0x31, 0x6e, 0x65, 0x9e, 0x1b, 0xb0, 0x61, 0xd6, 0x90, 0xd1, 0x1d, 0x4c, - 0x36, 0xfe, 0xec, 0x26, 0xcc, 0xba, 0xce, 0xd7, 0xe7, 0x0c, 0x53, 0x90, - 0xe8, 0xce, 0xce, 0xed, 0x58, 0x37, 0x37, 0x3f, 0x40, 0x39, 0xeb, 0x8c, - 0xfb, 0x7d, 0x93, 0xa2, 0x26, 0x4e, 0xbf, 0x49, 0xe7, 0x95, 0xc0, 0x12, - 0x6a, 0xec, 0xfb, 0xbe, 0x00, 0x62, 0xb9, 0xc9, 0x0d, 0x5a, 0x37, 0xf9, - 0xae, 0x84, 0x95, 0x89, 0x20, 0x47, 0x48, 0xf6, 0xf8, 0x73, 0x92, 0x5f, - 0xe1, 0x4a, 0xb4, 0x9e, 0xd8, 0x75, 0xf3, 0x38, 0x48, 0xe1, 0x29, 0x95, - 0x0d, 0x74, 0x6b, 0x98, 0x96, 0x6e, 0xc9, 0x3f, 0xfc, 0x44, 0x91, 0x4d, - 0xf4, 0x4c, 0xb7, 0x38, 0xd7, 0xec, 0xbf, 0xf6, 0x78, 0x05, 0x7d, 0x1b, - 0xe5, 0x68, 0x8a, 0xbc, 0x6a, 0x6a, 0x29, 0xb6, 0xc6, 0x9a, 0x8d, 0x7a, - 0x0e, 0x00, 0x80, 0x73, 0xf5, 0x88, 0x5d, 0x2a, 0xa2, 0x60, 0x98, 0x1e, - 0xf5, 0x06, 0x3b, 0xef, 0xa9, 0x46, 0x6b, 0x89, 0x24, 0xb0, 0xf4, 0x34, - 0x42, 0x15, 0x87, 0xd3, 0xc9, 0x36, 0xe0, 0x52, 0x5f, 0x57, 0x8e, 0x65, - 0x5c, 0x7f, 0x7c, 0xf2, 0x66, 0xd8, 0xd1, 0xbf, 0x13, 0x95, 0x65, 0xb0, - 0x7a, 0xa0, 0xbb, 0xee, 0xc9, 0x20, 0xff, 0x26, 0xda, 0xa0, 0x61, 0x65, - 0xd5, 0x3c, 0xdf, 0xb5, 0xf0, 0xd2, 0x02, 0x4f, 0x97, 0x65, 0x48, 0x63, - 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x73, - 0x64, 0x64, 0x6b, 0x75, 0x8a, 0x11, 0x01, 0x23, 0x00, 0x07, 0x07, 0x09, - 0x34, 0x00, 0x09, 0x09, 0x09, 0x34, 0x34, 0x08, 0x01, 0x02, 0x02, 0x08, - 0x08, 0x08, 0x08, 0x09, 0x08, 0x08, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, - 0x08, 0x09, 0x92, 0x1a, 0x33, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x4b, 0x89, - 0xf6, 0xba, 0x41, 0xb7, 0x59, 0x5c, 0x4b, 0x89, 0xf6, 0xba, 0xb1, 0x0a, - 0x33, 0x78, 0x48, 0x21, 0xea, 0x97, 0x6e, 0xb7, 0xc7, 0x2e, 0xdb, 0x0f, - 0x9b, 0x01, 0xd0, 0x22, 0x6d, 0xbb, 0x64, 0x14, 0x5e, 0x86, 0xb3, 0x7b, - 0x2d, 0x6c, 0xa9, 0xc0, 0xcf, 0xd8, 0x43, 0x7e, 0x59, 0x45, 0xac, 0xff, - 0x92, 0x4b, 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, - 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0x2a, 0x04, - 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, - 0x00, 0x00, 0x00, 0x12, 0x83, 0x28, 0x8c, 0xcd, 0x78, 0x8c, 0x1b, 0x02, - 0xa2, 0x38, 0xa7, 0x25, 0xc1, 0x25, 0x59, 0xcd, 0x36, 0xb2, 0x21, 0xa1, - 0x91, 0xd0, 0xc3, 0x54, 0x89, 0x64, 0xa8, 0x3d, 0x07, 0xcb, 0x8f, 0xf7, - 0xa6, 0x55, 0xc2, 0x96, 0xf6, 0x35, 0xc1, 0x67, 0xdf, 0x2f, 0x1f, 0xda, - 0xa8, 0xf8, 0x8c, 0xc9, 0xa7, 0x5e, 0x7f, 0x1f, 0xa8, 0xd3, 0x38, 0x57, - 0xa2, 0xf4, 0x57, 0x32, 0x17, 0xe3, 0x06, 0xe3, 0xb6, 0x56, 0x60, 0x6e, - 0xbe, 0x12, 0x60, 0x00, 0xfd, 0xa8, 0x4c, 0x3f, 0x2b, 0x54, 0x9c, 0xfb, - 0x87, 0x8b, 0xfa, 0x9e, 0xb8, 0xb2, 0x80, 0x36, 0xf1, 0x5b, 0xcd, 0x9d, - 0x74, 0xa1, 0x7b, 0xbf, 0xf6, 0x4c, 0x64, 0x58, 0x67, 0x8b, 0x68, 0x05, - 0x15, 0x7e, 0x4b, 0x54, 0xe9, 0x84, 0x59, 0x70, 0x42, 0x80, 0x67, 0x6c, - 0x45, 0x62, 0x12, 0x03, 0x27, 0x2b, 0x32, 0xdc, 0x78, 0x85, 0x3d, 0x74, - 0x28, 0x89, 0x5c, 0x33, 0x15, 0x79, 0x63, 0x1f, 0xd7, 0x26, 0xbf, 0x5d, - 0xf6, 0xb1, 0xb7, 0x9e, 0x37, 0x86, 0xd8, 0xf6, 0xf9, 0xc3, 0x66, 0x90, - 0x50, 0x5a, 0x0e, 0xeb, 0xcc, 0xe0, 0xf2, 0x19, 0xbb, 0xd7, 0x6a, 0xe4, - 0xea, 0x87, 0xf9, 0x17, 0x20, 0x88, 0xf6, 0xc0, 0xc7, 0xb7, 0x55, 0x25, - 0xef, 0x15, 0xec, 0xc5, 0x80, 0x52, 0x9a, 0x92, 0xdb, 0x32, 0xf3, 0xc2, - 0xa2, 0x55, 0xd6, 0xd9, 0x5b, 0xe6, 0xb1, 0x95, 0x18, 0x2b, 0xf8, 0x94, - 0x21, 0x56, 0x29, 0x30, 0xf3, 0x61, 0x39, 0x22, 0x03, 0x86, 0xce, 0x81, - 0x6d, 0x9e, 0xdb, 0x5b, 0x49, 0xdb, 0x2c, 0x1d, 0x0d, 0x45, 0xa9, 0xb3, - 0x1c, 0x1a, 0x43, 0x36, 0x1d, 0xd2, 0x76, 0x28, 0x27, 0xe0, 0xd3, 0x19, - 0x56, 0xd3, 0x52, 0xb2, 0xa0, 0x9c, 0xda, 0xb7, 0xac, 0x4d, 0xb1, 0x98, - 0x22, 0xa5, 0x86, 0x5d, 0x79, 0x6a, 0x69, 0x06, 0xd7, 0x07, 0xe7, 0x44, - 0x55, 0x6c, 0xc7, 0xd0, 0x8a, 0x2b, 0xa1, 0x45, 0xc6, 0xbf, 0xf3, 0x21, - 0x2e, 0x41, 0x5c, 0x84, 0xa2, 0x77, 0x46, 0x65, 0x80, 0x75, 0xba, 0x49, - 0xd6, 0xd7, 0x73, 0xeb, 0x35, 0x2c, 0x46, 0x58, 0xc4, 0x1d, 0x2f, 0x6b, - 0xe6, 0x6c, 0xa7, 0x5f, 0x95, 0x0c, 0xbc, 0x60, 0x00, 0x3d, 0xa9, 0x0a, - 0xd6, 0x0a, 0x66, 0x59, 0xc0, 0x9b, 0x49, 0x5b, 0x4c, 0x73, 0xf5, 0x9e, - 0x6d, 0x38, 0xdd, 0x0f, 0x25, 0xe4, 0x35, 0x84, 0x34, 0x25, 0xfe, 0x71, - 0x35, 0x78, 0xa7, 0x5b, 0xc1, 0x7a, 0xab, 0xd7, 0xeb, 0x2f, 0x54, 0x93, - 0x94, 0x49, 0x8a, 0x1e, 0x04, 0xe6, 0xfc, 0xd7, 0xe3, 0xa2, 0x41, 0x25, - 0x5a, 0xa5, 0x46, 0x59, 0x85, 0xfb, 0x21, 0xc7, 0x02, 0x48, 0x79, 0xd4, - 0xef, 0xc4, 0x03, 0xc2, 0x0a, 0x4b, 0x42, 0x1c, 0x73, 0x35, 0xcd, 0x21, - 0x8b, 0xd5, 0xfc, 0xa3, 0xdc, 0xbb, 0x4b, 0xa3, 0x45, 0x04, 0x73, 0xa1, - 0xdb, 0x3a, 0x97, 0x0e, 0xc7, 0x1c, 0xe2, 0x67, 0x04, 0xd4, 0x49, 0x68, - 0x0e, 0x05, 0xcb, 0x52, 0xd4, 0x37, 0x75, 0xd8, 0x2a, 0x17, 0xd3, 0x7a, - 0x93, 0x96, 0x46, 0xfb, 0x07, 0x6d, 0x3b, 0x92, 0x60, 0xf4, 0x35, 0x94, - 0x3b, 0xbd, 0x2e, 0xf6, 0x0b, 0x18, 0xd5, 0x0d, 0x1b, 0xe1, 0xd3, 0x14, - 0xc1, 0x84, 0xd7, 0x67, 0xd7, 0x96, 0x2d, 0xa9, 0xab, 0x59, 0x70, 0x43, - 0x7b, 0xea, 0x25, 0xa3, 0x05, 0x1c, 0x45, 0xf6, 0x34, 0x51, 0x8e, 0xaf, - 0x46, 0x33, 0x90, 0x68, 0x28, 0x4f, 0x38, 0x5b, 0xbb, 0x69, 0xee, 0xbb, - 0x0a, 0x4c, 0x76, 0x1c, 0x3d, 0xfd, 0xea, 0x1f, 0x77, 0x9e, 0xd4, 0xa1, - 0xeb, 0x74, 0x16, 0x60, 0x20, 0xe9, 0x44, 0xc1, 0x90, 0x2c, 0x7b, 0x77, - 0x6f, 0x70, 0xe3, 0x62, 0x0f, 0xc3, 0x20, 0xf6, 0xce, 0xc3, 0xa6, 0x0e, - 0x9c, 0x6d, 0xa3, 0xa0, 0x21, 0x1c, 0x28, 0x7f, 0x44, 0xd7, 0xa9, 0x87, - 0x62, 0x91, 0x4d, 0x2a, 0x93, 0xe2, 0xc7, 0x94, 0x0c, 0x75, 0x1d, 0xf6, - 0xc7, 0xf8, 0x36, 0x09, 0xa8, 0x23, 0xa3, 0x80, 0x52, 0x2d, 0xe7, 0x0b, - 0x44, 0x5d, 0x4b, 0xf5, 0xdc, 0x57, 0xa3, 0x02, 0x40, 0x89, 0xdc, 0x40, - 0xf7, 0x5c, 0xad, 0xea, 0x5c, 0x1a, 0x59, 0xfc, 0xb8, 0xaf, 0xcb, 0x71, - 0xe0, 0x08, 0xdc, 0x80, 0x08, 0x8a, 0x32, 0x85, 0x46, 0xa9, 0x9a, 0x17, - 0x6b, 0x25, 0x9c, 0xfe, 0x7d, 0x90, 0x22, 0x6e, 0x7b, 0x01, 0x24, 0x17, - 0xf6, 0xa7, 0x70, 0x93, 0x03, 0x60, 0xc2, 0x0d, 0x7b, 0x3b, 0xe8, 0x5b, - 0x02, 0xb0, 0x6d, 0x00, 0x62, 0x97, 0x1b, 0x84, 0x86, 0x27, 0x72, 0x2d, - 0x90, 0xee, 0xdc, 0xb6, 0xb8, 0xa5, 0x58, 0x73, 0x29, 0x9b, 0x06, 0x99, - 0xda, 0x4f, 0x12, 0x0c, 0x74, 0x0a, 0xc1, 0x1b, 0x34, 0x20, 0xfa, 0x6d, - 0x01, 0xd2, 0x1b, 0xf2, 0x0f, 0xe3, 0xfe, 0x34, 0x2d, 0x44, 0x4f, 0xa3, - 0x6a, 0xab, 0xaa, 0x7e, 0x1c, 0x35, 0xef, 0xfe, 0xa0, 0xc1, 0x8a, 0xeb, - 0x77, 0x80, 0xd6, 0x57, 0x20, 0x2e, 0x2b, 0xeb, 0x67, 0xa0, 0x82, 0x86, - 0xc8, 0x0e, 0x70, 0x76, 0x74, 0x52, 0x3e, 0x67, 0x96, 0xf0, 0x48, 0x3f, - 0x9b, 0xdc, 0x5f, 0x36, 0xd9, 0xae, 0x3a, 0xcb, 0x57, 0x5d, 0xe0, 0x7c, - 0x03, 0xa9, 0xe8, 0x88, 0x13, 0x6a, 0x70, 0x94, 0x4b, 0xf5, 0x92, 0x8f, - 0xc0, 0x34, 0x49, 0x3f, 0xf7, 0xe1, 0x59, 0xc4, 0xf2, 0xae, 0x7a, 0x88, - 0x58, 0x39, 0x74, 0x39, 0x6d, 0xaf, 0x7a, 0xec, 0xaf, 0x44, 0x0e, 0x11, - 0x7d, 0xa8, 0x3c, 0x50, 0x5b, 0x64, 0x8d, 0x8a, 0x21, 0x59, 0xc6, 0x8c, - 0x6c, 0xce, 0x05, 0xad, 0x1c, 0x2f, 0x5e, 0x4a, 0xa3, 0x2a, 0x46, 0x3a, - 0xaa, 0x12, 0x7e, 0xcc, 0x82, 0xb6, 0x62, 0xba, 0xe6, 0x1a, 0x52, 0xc6, - 0xe3, 0x96, 0x71, 0xf6, 0x81, 0x21, 0x46, 0xd0, 0x3f, 0x5d, 0xa1, 0x37, - 0x8b, 0xf5, 0xc7, 0x8c, 0x28, 0xf0, 0x2e, 0xe8, 0x44, 0x25, 0x48, 0x27, - 0x8e, 0x2f, 0x65, 0x83, 0xed, 0xf5, 0xb6, 0x9f, 0x02, 0xa7, 0x1b, 0x1e, - 0x90, 0x01, 0x55, 0x88, 0xe5, 0xdf, 0x0e, 0x7e, 0x16, 0x66, 0xa1, 0xc6, - 0x07, 0xf6, 0xb5, 0x84, 0x8d, 0x60, 0x6b, 0xe2, 0xad, 0xbd, 0x18, 0x39, - 0xe5, 0xd2, 0xd9, 0xe0, 0xab, 0xc2, 0xac, 0x2f, 0x36, 0x24, 0x03, 0x69, - 0x4c, 0xf9, 0xf3, 0x67, 0x8f, 0xf6, 0x8b, 0xde, 0xf9, 0x7c, 0x14, 0xfa, - 0x97, 0xc3, 0xe5, 0xc1, 0x7d, 0xcf, 0x16, 0x24, 0x26, 0xda, 0xde, 0x5c, - 0x70, 0x96, 0x90, 0xd9, 0x06, 0x2f, 0xf9, 0x61, 0xa3, 0x47, 0x19, 0x50, - 0x5e, 0xe2, 0xb6, 0x74, 0x5e, 0x55, 0xe6, 0x89, 0xaa, 0xde, 0x19, 0x27, - 0x26, 0x47, 0x95, 0x7b, 0xf0, 0x09, 0x21, 0xa9, 0xf3, 0xf2, 0xf0, 0xbc, - 0x1a, 0xa2, 0x25, 0x77, 0x3f, 0x8a, 0x57, 0x20, 0xfc, 0x48, 0x45, 0xd8, - 0x8b, 0xcb, 0x33, 0x04, 0x10, 0x1d, 0xc6, 0x4b, 0x4c, 0xe4, 0x92, 0x1f, - 0xef, 0x27, 0x5e, 0xd5, 0xac, 0xab, 0xcc, 0x69, 0xbe, 0xd6, 0x35, 0x0e, - 0x0d, 0x96, 0x99, 0x3b, 0x67, 0x8d, 0x33, 0xa0, 0xe3, 0x16, 0xcc, 0x4a, - 0x29, 0x80, 0xc8, 0x47, 0xd1, 0x0c, 0xb1, 0xa0, 0xc1, 0xbe, 0xcc, 0x16, - 0xab, 0xf7, 0xee, 0x8a, 0x77, 0xef, 0xca, 0x08, 0x82, 0x0a, 0x9e, 0x11, - 0xcf, 0x3c, 0xbb, 0x1b, 0x44, 0x96, 0xd1, 0x5e, 0x65, 0xf9, 0xe7, 0xc7, - 0xa1, 0x94, 0x42, 0xa9, 0x0e, 0x36, 0x9a, 0x5b, 0x7f, 0xf0, 0x91, 0x95, - 0xeb, 0xd1, 0xb6, 0x1d, 0x18, 0x44, 0x93, 0xa4, 0xc1, 0x31, 0x97, 0x07, - 0x09, 0x9b, 0x50, 0xae, 0xf3, 0x74, 0x7f, 0xbe, 0x0d, 0xc2, 0xc3, 0x11, - 0x8f, 0xa1, 0xea, 0x1f, 0x4e, 0x84, 0x94, 0x18, 0x7e, 0x7c, 0xbd, 0xe6, - 0xc9, 0x78, 0x0e, 0x39, 0x1e, 0x1a, 0x71, 0xc4, 0xbc, 0x5c, 0x99, 0x76, - 0xf7, 0x26, 0x66, 0x9c, 0x8f, 0xd4, 0xad, 0xa9, 0x6e, 0x96, 0xb9, 0x54, - 0x5b, 0xae, 0xa2, 0x0d, 0x94, 0xa8, 0x5a, 0x34, 0xc3, 0xdb, 0x52, 0x59, - 0x3f, 0xdd, 0x53, 0x72, 0xfc, 0xf6, 0x1d, 0x3c, 0xe0, 0x1f, 0x4a, 0xee, - 0xf5, 0x74, 0xa5, 0x95, 0x7a, 0x5d, 0x75, 0xbd, 0x27, 0x4a, 0x49, 0x18, - 0xcf, 0xf0, 0xe5, 0x32, 0x4f, 0x1b, 0xa0, 0xeb, 0x00, 0x19, 0x21, 0xbd, - 0xf7, 0xf5, 0x4b, 0x47, 0x1d, 0x3b, 0x8b, 0xe6, 0xca, 0xdc, 0xb6, 0x52, - 0x41, 0xa7, 0xab, 0x68, 0xb3, 0xfb, 0x8f, 0x40, 0xc3, 0x59, 0xd9, 0x2d, - 0x13, 0x3a, 0x99, 0x93, 0x9f, 0xa6, 0x90, 0xdd, 0x65, 0x17, 0x6c, 0x6f, - 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x2d, 0x69, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x69, 0x65, 0x73, 0x64, 0x6b, 0x75, 0x0d, 0x00, 0x00, 0x00, - 0x02, 0x07, 0x57, 0x00, 0x0c, 0xce, 0x07, 0x57, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x8a, 0x74, 0x06, 0x23, 0x00, 0x07, 0x07, 0x09, 0x34, - 0x00, 0x09, 0x09, 0x09, 0x34, 0x34, 0x08, 0x01, 0x02, 0x02, 0x08, 0x08, - 0x08, 0x08, 0x09, 0x08, 0x08, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, - 0x09, 0x93, 0x7c, 0x17, 0x13, 0x41, 0xb7, 0x59, 0x5c, 0x83, 0xd8, 0xc4, - 0xac, 0x41, 0xb7, 0x59, 0x5c, 0x83, 0xd8, 0xc4, 0xac, 0xdb, 0x80, 0x31, - 0x14, 0x76, 0xc0, 0x68, 0x81, 0x87, 0xa3, 0xfd, 0xf3, 0xa2, 0xd6, 0x51, - 0xa9, 0xbf, 0x9e, 0x90, 0x88, 0xfc, 0x9b, 0xff, 0x1a, 0xfd, 0x18, 0x88, - 0xb2, 0x23, 0xc4, 0x27, 0xcd, 0xff, 0x6d, 0xed, 0x99, 0xdb, 0x40, 0x1d, - 0x5c, 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, - 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0x2a, 0x05, 0x00, - 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, - 0x00, 0x00, 0x08, 0xd8, 0x16, 0x86, 0x7c, 0x84, 0xb6, 0xc0, 0xb3, 0x50, - 0x2d, 0x2a, 0x95, 0x72, 0x8c, 0x1b, 0x64, 0xd9, 0xce, 0xbb, 0x9c, 0xc8, - 0xc6, 0x63, 0x5a, 0xd5, 0x38, 0x7c, 0x27, 0x74, 0xaa, 0x87, 0x88, 0x30, - 0xf3, 0x87, 0x6a, 0x7d, 0x11, 0xc7, 0x6a, 0xf8, 0x5a, 0x6c, 0xd9, 0xaf, - 0xae, 0xb7, 0x3e, 0x35, 0x89, 0x91, 0x11, 0xe7, 0x44, 0x9c, 0xc1, 0xa1, - 0x18, 0x0e, 0x78, 0x20, 0xfe, 0x4a, 0xf9, 0x47, 0x3a, 0xf4, 0x23, 0x28, - 0x3c, 0x45, 0xa2, 0x22, 0xe8, 0x63, 0x71, 0x92, 0xc8, 0xfd, 0x85, 0xf8, - 0x03, 0x28, 0x38, 0xb6, 0x09, 0x66, 0x5b, 0x56, 0xc8, 0xa6, 0x52, 0x03, - 0xea, 0xbf, 0xb5, 0x6f, 0xaf, 0x68, 0xdc, 0xb6, 0x9c, 0xa2, 0x16, 0xa5, - 0x33, 0x1a, 0xb7, 0x13, 0x15, 0x1d, 0x52, 0x29, 0x54, 0x51, 0xc4, 0x3e, - 0xa0, 0x03, 0xf9, 0x73, 0xa9, 0x3e, 0xf6, 0x45, 0xd8, 0xf2, 0x1e, 0xa9, - 0x40, 0x14, 0xc4, 0x5f, 0xbc, 0xce, 0x6f, 0xb5, 0xa2, 0x93, 0x7b, 0xf2, - 0x7c, 0xfa, 0xa5, 0x82, 0x97, 0x64, 0x77, 0x2e, 0x6d, 0x8f, 0x00, 0x71, - 0x64, 0xed, 0xc9, 0x51, 0x61, 0x69, 0x8f, 0x2a, 0xf4, 0x80, 0xd2, 0x24, - 0x6c, 0xc3, 0x53, 0x9f, 0xca, 0x72, 0x9d, 0x22, 0x54, 0x27, 0xd5, 0xba, - 0xae, 0x53, 0xb4, 0x7e, 0xae, 0xa9, 0xe1, 0x48, 0x67, 0xf5, 0x7b, 0xd7, - 0x7e, 0x36, 0x6f, 0xd1, 0xf8, 0x40, 0x8a, 0x9b, 0x07, 0x80, 0x2c, 0x17, - 0x6c, 0x42, 0x2f, 0x7b, 0x8b, 0x98, 0xc4, 0x20, 0xaf, 0x5b, 0x25, 0x73, - 0xb5, 0x5b, 0xa3, 0x4d, 0xe6, 0xeb, 0x66, 0x21, 0x91, 0x9d, 0x85, 0xa3, - 0x8b, 0xfa, 0x40, 0x2d, 0x0b, 0x20, 0x66, 0x47, 0x70, 0x83, 0xe3, 0x02, - 0x0f, 0xc2, 0x56, 0xd6, 0x49, 0x83, 0x3d, 0xad, 0x16, 0x1f, 0x55, 0x33, - 0xcf, 0x79, 0x6d, 0x8d, 0xb1, 0xf7, 0x5d, 0x08, 0x10, 0xd8, 0xe2, 0x0e, - 0xe7, 0xa1, 0x74, 0xdb, 0xef, 0x19, 0xc0, 0xe7, 0xf3, 0xb7, 0x73, 0xf8, - 0x4d, 0x78, 0x98, 0xf0, 0x64, 0xc3, 0xc5, 0x99, 0xb7, 0xf6, 0x07, 0xd4, - 0xae, 0x17, 0xe4, 0xee, 0xd9, 0x35, 0x53, 0xb6, 0x2d, 0xb5, 0xa0, 0xc4, - 0x50, 0x48, 0x3e, 0x16, 0x18, 0xea, 0x20, 0x34, 0x9c, 0xeb, 0xeb, 0xef, - 0xee, 0xb8, 0xf4, 0x32, 0xb1, 0xda, 0x32, 0x35, 0x4e, 0x47, 0x1a, 0x4e, - 0xad, 0x46, 0x53, 0xe6, 0xce, 0x22, 0x7e, 0xe3, 0xf3, 0xbc, 0x34, 0x77, - 0xb0, 0x53, 0x21, 0x81, 0x19, 0x42, 0xb7, 0x1d, 0x0d, 0x81, 0x0f, 0x29, - 0xea, 0x2f, 0x3d, 0xba, 0x40, 0x0c, 0xea, 0x2e, 0xaf, 0x20, 0x88, 0x96, - 0x88, 0xc2, 0xea, 0x3b, 0xec, 0x58, 0x4f, 0x16, 0x66, 0xec, 0x9c, 0xe3, - 0xc8, 0x77, 0x6b, 0xfe, 0xc5, 0xeb, 0x5f, 0xab, 0xbc, 0xc2, 0x6b, 0x03, - 0xdb, 0xbc, 0x0e, 0xd6, 0xd2, 0x8d, 0x3e, 0xd8, 0x63, 0xe7, 0x13, 0xa9, - 0xc3, 0x98, 0xfa, 0xf6, 0xbd, 0xe9, 0x53, 0x33, 0x83, 0x26, 0x2b, 0x78, - 0xa4, 0x91, 0xb5, 0x5b, 0x39, 0xcf, 0x1d, 0x26, 0xc4, 0x05, 0xbe, 0xeb, - 0x8b, 0xa4, 0xee, 0xcd, 0xe0, 0x76, 0xac, 0x41, 0xdf, 0x85, 0x05, 0x60, - 0xe3, 0xc2, 0x5e, 0x57, 0x73, 0x00, 0x48, 0xa2, 0x3f, 0x3c, 0xd2, 0x3c, - 0x78, 0x8e, 0x20, 0xa2, 0xbd, 0xc6, 0xb6, 0x09, 0xdb, 0xdd, 0xf5, 0x39, - 0x8b, 0x5f, 0x2d, 0x13, 0xb9, 0x18, 0x3c, 0x43, 0x55, 0xcc, 0xf6, 0x87, - 0x97, 0xbe, 0x82, 0x03, 0x18, 0xa2, 0xb0, 0xf5, 0x05, 0xec, 0xe3, 0x64, - 0x43, 0x67, 0xef, 0xf7, 0x3c, 0x23, 0xde, 0x2a, 0xa7, 0xff, 0xee, 0xc1, - 0x95, 0x3d, 0xc8, 0x99, 0xea, 0xb7, 0x73, 0x2a, 0x89, 0xc8, 0x1b, 0x2e, - 0x47, 0x25, 0xae, 0x2a, 0x40, 0x77, 0x87, 0x6d, 0xea, 0xa9, 0x71, 0x49, - 0xa0, 0x11, 0xe5, 0x89, 0x0e, 0xd8, 0x01, 0x10, 0xe2, 0x6f, 0xea, 0xb2, - 0xbf, 0x6d, 0x2b, 0x03, 0x92, 0x28, 0x2a, 0xe8, 0x21, 0x70, 0x55, 0x48, - 0xe5, 0x9f, 0xf4, 0xea, 0x37, 0x69, 0x22, 0xb9, 0x3f, 0x48, 0x06, 0xd1, - 0x97, 0x6e, 0x72, 0x13, 0x4b, 0x20, 0xb5, 0x55, 0x64, 0x5c, 0xfc, 0x0b, - 0xec, 0xf9, 0x6f, 0x0d, 0xfa, 0x2d, 0xa4, 0xf9, 0x6a, 0x98, 0x5f, 0xd2, - 0x17, 0x31, 0xbf, 0x86, 0xc4, 0xd8, 0x21, 0x0a, 0x51, 0x62, 0xf1, 0x30, - 0x72, 0xef, 0x39, 0xb5, 0x05, 0x6b, 0xc9, 0x15, 0x1f, 0xbd, 0xb5, 0xfc, - 0xe5, 0x0b, 0x35, 0x13, 0x9b, 0xc5, 0x48, 0x3e, 0xf1, 0x1f, 0x7a, 0x1d, - 0x7f, 0xcb, 0x61, 0xba, 0x58, 0xbb, 0x74, 0xc2, 0x1b, 0xd9, 0xc0, 0x45, - 0x45, 0xe9, 0xbf, 0x3b, 0x56, 0x14, 0x9c, 0xd7, 0xaa, 0xcd, 0x77, 0xc4, - 0x32, 0x6c, 0x7e, 0x5d, 0xc0, 0x1c, 0xde, 0xad, 0xbb, 0xe4, 0x46, 0xca, - 0x6c, 0x13, 0x08, 0x58, 0x07, 0xd6, 0xa7, 0xc5, 0xa1, 0x90, 0xc6, 0x93, - 0x4d, 0xbd, 0xc4, 0xd7, 0x75, 0x02, 0x16, 0x47, 0x38, 0x33, 0x92, 0x11, - 0xb9, 0x6a, 0x85, 0xc4, 0x97, 0x7d, 0xdc, 0x54, 0x31, 0x07, 0xf9, 0xcd, - 0xeb, 0x09, 0x85, 0xae, 0x14, 0x6d, 0x2c, 0xb0, 0xfa, 0xa3, 0x49, 0x26, - 0xb6, 0x98, 0x69, 0xb1, 0x85, 0x52, 0x02, 0x0d, 0x3a, 0x8d, 0x40, 0x3b, - 0x83, 0x05, 0x66, 0x5c, 0xe3, 0xb1, 0x51, 0xe4, 0xc9, 0x59, 0x74, 0x0a, - 0x8a, 0xbb, 0xcb, 0x95, 0xde, 0x81, 0xa4, 0x92, 0x09, 0x63, 0x9d, 0xef, - 0x27, 0xf4, 0xe1, 0x66, 0xf6, 0x4f, 0xe9, 0x6d, 0xce, 0x8d, 0xcb, 0x91, - 0x55, 0xd7, 0xf9, 0xba, 0x49, 0xf2, 0x27, 0x0c, 0x15, 0x68, 0x21, 0x42, - 0x2d, 0x69, 0xe2, 0x0d, 0xee, 0x69, 0x55, 0x68, 0xc3, 0xb5, 0x8d, 0xd7, - 0x37, 0x32, 0xda, 0x6f, 0x78, 0x2b, 0xc8, 0xf9, 0x30, 0x3b, 0xd1, 0xe5, - 0xa5, 0x4c, 0xcb, 0xfe, 0xeb, 0x6f, 0x5d, 0x3c, 0x99, 0xfb, 0x33, 0xc1, - 0x8e, 0xac, 0x48, 0x70, 0x8c, 0x30, 0x85, 0xe1, 0x30, 0x69, 0xde, 0x82, - 0x82, 0x18, 0xe2, 0xc5, 0x6b, 0xb7, 0x1d, 0xdb, 0xce, 0x09, 0x4d, 0x9a, - 0x8e, 0x93, 0x89, 0x46, 0x5f, 0x8c, 0xe9, 0xf5, 0x4c, 0xa1, 0x62, 0xd9, - 0x22, 0x4c, 0xad, 0xbe, 0x77, 0x5c, 0x4f, 0x34, 0xc0, 0x64, 0x23, 0x0d, - 0x9d, 0xed, 0x3e, 0x70, 0x9b, 0x5f, 0x65, 0x84, 0x98, 0x63, 0x1a, 0x0b, - 0xd9, 0x7c, 0xb0, 0x95, 0xee, 0x6a, 0x9a, 0x5c, 0xc3, 0x76, 0x7c, 0x18, - 0x75, 0xba, 0x86, 0xca, 0x43, 0xa5, 0xb5, 0xe1, 0x0b, 0x26, 0xc0, 0xfb, - 0xd6, 0x3a, 0x23, 0x9f, 0xfb, 0xba, 0x68, 0xa3, 0x9b, 0xc0, 0xe5, 0x21, - 0xe3, 0x77, 0x75, 0x84, 0x40, 0x1d, 0x9b, 0xc9, 0xf2, 0x25, 0x6c, 0xba, - 0x6c, 0x8c, 0xb2, 0x2e, 0xec, 0xce, 0x90, 0xb1, 0x4a, 0x90, 0x24, 0xf3, - 0x34, 0x9d, 0xc3, 0x62, 0xb2, 0x11, 0x02, 0xd1, 0xf5, 0x67, 0x95, 0x48, - 0x45, 0x04, 0xe1, 0xd4, 0xb3, 0xdd, 0x1e, 0x00, 0x35, 0x84, 0x7c, 0x41, - 0xea, 0xf9, 0x50, 0xd3, 0x82, 0x14, 0x7d, 0xe7, 0x72, 0xe2, 0xb4, 0x9e, - 0xfc, 0xe7, 0x2e, 0xf7, 0x06, 0xb4, 0x29, 0xfe, 0x7e, 0x72, 0x6a, 0xe1, - 0xde, 0xa8, 0xfa, 0xd9, 0xde, 0xf4, 0xdd, 0xce, 0xff, 0xdb, 0xdc, 0x09, - 0x31, 0x14, 0x1d, 0x09, 0x53, 0xb5, 0x3f, 0x2c, 0x66, 0x74, 0xa8, 0x66, - 0xaa, 0xa2, 0x3d, 0x32, 0x61, 0xed, 0x43, 0xa5, 0x69, 0xf8, 0x6b, 0x0d, - 0x16, 0xe4, 0x67, 0xf5, 0x62, 0xaa, 0x76, 0xac, 0x01, 0x3f, 0x5f, 0x44, - 0x29, 0x34, 0x95, 0x0c, 0x1a, 0x07, 0x96, 0x6b, 0xf4, 0x60, 0x96, 0x5b, - 0xe2, 0x53, 0x2a, 0x87, 0x02, 0xc6, 0xf4, 0x01, 0xf3, 0x7a, 0xdb, 0x82, - 0x5f, 0xc3, 0x85, 0xd4, 0x1a, 0x9b, 0x63, 0xc4, 0x60, 0xb7, 0x82, 0x3c, - 0x9c, 0x70, 0x6f, 0x62, 0x72, 0x10, 0x13, 0xe2, 0xf5, 0x7b, 0x06, 0x41, - 0x48, 0xc7, 0x63, 0xa0, 0xb9, 0xde, 0x56, 0x96, 0x0f, 0x0d, 0x67, 0xd9, - 0x0e, 0x8a, 0x94, 0x3f, 0xca, 0x2f, 0x94, 0x19, 0xff, 0x47, 0xad, 0x59, - 0x3b, 0x9b, 0xb4, 0xc5, 0x4b, 0x51, 0x0d, 0x18, 0x74, 0xc9, 0x53, 0x34, - 0xf0, 0x6c, 0x58, 0x51, 0xbe, 0x4b, 0xfe, 0x24, 0x37, 0xd2, 0x0b, 0x4d, - 0xfa, 0x54, 0xfd, 0x92, 0xc4, 0x25, 0xb3, 0xe8, 0xe2, 0xb5, 0xda, 0xd1, - 0xd1, 0x44, 0x82, 0xb9, 0x2b, 0xb7, 0x03, 0xd9, 0xca, 0x78, 0x71, 0x9c, - 0xc6, 0x8f, 0xb6, 0x59, 0x37, 0xbd, 0x15, 0x02, 0x5e, 0xfb, 0xf5, 0x8c, - 0x7c, 0x46, 0x8e, 0xe2, 0xc8, 0xed, 0xf9, 0x96, 0xdb, 0xa8, 0xbe, 0xe5, - 0x09, 0x70, 0x3f, 0xf4, 0xfb, 0xbf, 0xf4, 0xf5, 0xe1, 0xd4, 0x5e, 0xda, - 0x60, 0x8f, 0x9d, 0xff, 0x94, 0x00, 0xa2, 0xe6, 0x40, 0xd2, 0x47, 0xdb, - 0x2d, 0x0e, 0x82, 0x7c, 0x7f, 0xab, 0x94, 0x2b, 0xc2, 0x6b, 0x46, 0x4d, - 0x55, 0x44, 0x7b, 0xb9, 0x2e, 0x68, 0x89, 0xbb, 0xc0, 0x69, 0x44, 0x77, - 0xa1, 0x41, 0xf8, 0x3b, 0x3f, 0xe5, 0xfb, 0x3c, 0x12, 0x0f, 0x59, 0x78, - 0x6a, 0x52, 0x6e, 0xe1, 0x2a, 0xf7, 0xab, 0xcd, 0xc8, 0xb2, 0x5d, 0x8d, - 0x1c, 0xf6, 0x24, 0xae, 0xb3, 0xda, 0x8a, 0xa7, 0x75, 0x3b, 0x58, 0x77, - 0x08, 0x72, 0xa9, 0x06, 0x0c, 0x7e, 0x4d, 0xad, 0x52, 0x42, 0xc5, 0x9d, - 0x32, 0x10, 0x49, 0xbb, 0xe1, 0x32, 0xc6, 0xb6, 0x2a, 0x68, 0xd3, 0x8d, - 0xba, 0x9e, 0x69, 0x63, 0x68, 0x61, 0x74, 0x64, 0x6b, 0x75, 0x86, 0x2f, - 0x05, 0x23, 0x00, 0x07, 0x07, 0x08, 0x34, 0x00, 0x09, 0x09, 0x09, 0x34, - 0x34, 0x08, 0x01, 0x02, 0x02, 0x08, 0x08, 0x08, 0x08, 0x09, 0x08, 0x08, - 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x09, 0x8a, 0x72, 0x17, 0x13, - 0x41, 0xb7, 0x59, 0x5c, 0x83, 0xd3, 0xa8, 0x82, 0x41, 0xb7, 0x59, 0x5c, - 0x83, 0xd3, 0xa8, 0x82, 0xdb, 0x80, 0x31, 0x14, 0x76, 0xc0, 0x68, 0x81, - 0x87, 0xa3, 0xfd, 0xf3, 0xa2, 0xd6, 0x51, 0xa9, 0xbf, 0x9e, 0x90, 0x88, - 0xfc, 0x9b, 0xff, 0x1a, 0xfd, 0x18, 0x88, 0xb2, 0x23, 0xc4, 0x27, 0xcd, - 0xff, 0x6d, 0xed, 0x99, 0xdb, 0x40, 0x1d, 0x5c, 0xda, 0x39, 0xa3, 0xee, - 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, - 0xaf, 0xd8, 0x07, 0x09, 0x2a, 0x05, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x38, 0xe1, 0x14, - 0x34, 0xc4, 0xb0, 0x8c, 0x51, 0x96, 0xb8, 0x94, 0xef, 0xe7, 0xf0, 0x5b, - 0x0e, 0x91, 0xf7, 0x07, 0x87, 0x90, 0x3f, 0x8d, 0x5f, 0xf6, 0x59, 0x69, - 0x11, 0x87, 0xdb, 0xaa, 0xdb, 0x60, 0x19, 0xe3, 0x42, 0xdd, 0xd2, 0x2e, - 0xbf, 0xc3, 0x0d, 0x32, 0x66, 0x01, 0xb9, 0xde, 0xce, 0xb5, 0x23, 0xa4, - 0x8e, 0x40, 0x6f, 0xe6, 0xa9, 0xea, 0xc6, 0x1e, 0x64, 0xc9, 0x57, 0x83, - 0x42, 0x36, 0x52, 0x9b, 0xa5, 0x29, 0x32, 0x5f, 0xe9, 0xc2, 0xe3, 0x2d, - 0x5b, 0x00, 0x7b, 0x3e, 0xad, 0xd4, 0x78, 0x7f, 0xfa, 0x02, 0x30, 0xb0, - 0x02, 0xfd, 0xd2, 0xbc, 0xa5, 0xe8, 0x0b, 0x4f, 0x96, 0x16, 0x79, 0x43, - 0x1a, 0xc1, 0x6d, 0xb5, 0xcf, 0x11, 0x35, 0x58, 0x61, 0x08, 0x64, 0x23, - 0xa3, 0x07, 0x76, 0xdb, 0x4d, 0x7d, 0x0e, 0xe0, 0x43, 0x7d, 0xc9, 0x3d, - 0x5e, 0xf4, 0x05, 0x0d, 0xb2, 0xbe, 0x23, 0x13, 0x19, 0x5f, 0x2a, 0xe9, - 0x10, 0xe7, 0x69, 0xed, 0x95, 0x7b, 0x66, 0xb3, 0xe5, 0xa5, 0x8b, 0x6f, - 0xe7, 0xa8, 0x2c, 0xab, 0xed, 0xd1, 0x12, 0xcf, 0xfb, 0xc7, 0x9a, 0xa5, - 0xf0, 0xe9, 0x2a, 0x98, 0x38, 0x96, 0x6a, 0xbb, 0x8d, 0xf2, 0xbf, 0x08, - 0x7f, 0xa7, 0x52, 0xd6, 0x12, 0x3b, 0x00, 0x47, 0xfe, 0xf3, 0x35, 0x63, - 0xf8, 0xc0, 0xec, 0xcf, 0x47, 0x72, 0x45, 0x81, 0x77, 0x4f, 0x23, 0x89, - 0x57, 0x15, 0x3c, 0xd7, 0xf9, 0x51, 0x14, 0xbd, 0x2a, 0x3d, 0xf4, 0x3d, - 0x83, 0xc1, 0xd0, 0x58, 0x07, 0x65, 0x5e, 0xe9, 0x23, 0x9a, 0xb9, 0x76, - 0xd1, 0xe1, 0x5f, 0xfd, 0x7c, 0xfe, 0x31, 0xad, 0xcd, 0xd6, 0x03, 0xb9, - 0x37, 0xe0, 0xae, 0x49, 0x85, 0x6b, 0x3c, 0x03, 0x97, 0x29, 0x99, 0x7c, - 0x1d, 0x36, 0x1a, 0xdd, 0xda, 0x47, 0xa1, 0x38, 0x21, 0xfa, 0x91, 0x4a, - 0x8d, 0xe7, 0x26, 0x9d, 0xaa, 0x44, 0xf7, 0x91, 0x25, 0xca, 0xa8, 0x84, - 0x77, 0x58, 0x2a, 0x50, 0xd6, 0xa4, 0xab, 0x69, 0xd3, 0xd4, 0xac, 0x1e, - 0x08, 0xfc, 0xa2, 0xbd, 0xab, 0x27, 0x72, 0xa4, 0x5a, 0x40, 0x76, 0x15, - 0x24, 0x0e, 0x50, 0x5a, 0x6f, 0x5d, 0x00, 0x75, 0x6c, 0x75, 0x75, 0xbb, - 0x13, 0x85, 0x0e, 0xcf, 0x27, 0x28, 0x94, 0x41, 0x64, 0xf0, 0x76, 0x97, - 0xbb, 0x58, 0x20, 0x12, 0x46, 0xa9, 0xf5, 0x23, 0xc2, 0x6b, 0xf6, 0x9b, - 0xd1, 0x20, 0xc5, 0x98, 0xa5, 0xdb, 0x77, 0xd9, 0x2a, 0xe7, 0xd8, 0x06, - 0xfc, 0x5d, 0xca, 0x85, 0xd8, 0x6e, 0x44, 0xf0, 0x4a, 0x32, 0x37, 0x66, - 0xbf, 0xde, 0x0a, 0x4c, 0xd8, 0xd8, 0xeb, 0x96, 0x0f, 0x6a, 0x37, 0x16, - 0x09, 0x63, 0x48, 0x8d, 0x31, 0xe8, 0x7c, 0xa6, 0x5b, 0xf0, 0xd3, 0x51, - 0xad, 0x5b, 0x12, 0xd5, 0x42, 0x86, 0xbd, 0x46, 0x7c, 0x62, 0x9c, 0x92, - 0x10, 0xeb, 0xdd, 0x5f, 0xc4, 0x16, 0xcc, 0x2d, 0xe1, 0xce, 0x42, 0xb0, - 0x80, 0x26, 0xcf, 0x49, 0x11, 0x0e, 0x4b, 0xe3, 0x63, 0xb4, 0x6f, 0x84, - 0x9b, 0x4d, 0xaf, 0x67, 0x56, 0x5f, 0x51, 0xff, 0xc9, 0xbd, 0xd5, 0xe4, - 0x7d, 0x96, 0x2c, 0x64, 0xe8, 0xa2, 0x42, 0x95, 0x2f, 0xf9, 0xb3, 0xa5, - 0x3c, 0xb2, 0x33, 0xa9, 0x4a, 0x03, 0xfe, 0x2c, 0x56, 0x00, 0xaa, 0xc6, - 0x5b, 0xea, 0x89, 0x0e, 0xa7, 0xae, 0xa0, 0x92, 0x7c, 0x04, 0xe5, 0x91, - 0xf4, 0x91, 0x8e, 0x77, 0xc0, 0x74, 0xd9, 0x85, 0xd6, 0x4f, 0x13, 0x11, - 0xc4, 0xd7, 0xeb, 0xd6, 0xfa, 0xbd, 0x70, 0x09, 0xb2, 0xa5, 0x77, 0x8d, - 0xbe, 0x23, 0x0b, 0xb3, 0x4c, 0xd6, 0x2f, 0xd0, 0x37, 0x62, 0x60, 0x88, - 0xd1, 0xbd, 0xec, 0x1c, 0x98, 0xbb, 0xd4, 0x9b, 0xa8, 0x50, 0x1e, 0xa4, - 0xb3, 0xe1, 0x1f, 0xe2, 0x49, 0x5b, 0x09, 0xc8, 0x3c, 0xb4, 0x38, 0xaf, - 0x5c, 0xec, 0xf8, 0x5d, 0xa1, 0xe1, 0xbf, 0xad, 0x5a, 0x33, 0xc8, 0x65, - 0x6a, 0x21, 0x10, 0x94, 0x70, 0x5c, 0x16, 0xd2, 0x5a, 0xfd, 0x52, 0x13, - 0xb8, 0xb7, 0xdb, 0xc2, 0x26, 0x7f, 0x24, 0xb2, 0xc3, 0x19, 0x19, 0x7c, - 0x7c, 0x5e, 0x70, 0x8a, 0x99, 0x74, 0x27, 0x3e, 0x5a, 0xb3, 0x17, 0x10, - 0xd8, 0x8a, 0x3e, 0xc2, 0x7e, 0x99, 0x67, 0x74, 0xe3, 0x65, 0x32, 0x18, - 0x90, 0x66, 0x7f, 0xe1, 0x74, 0x7d, 0xe7, 0xb8, 0xd1, 0xe2, 0xd3, 0x29, - 0xf1, 0xf2, 0x5d, 0xf1, 0x05, 0xca, 0x11, 0x7b, 0xf7, 0x32, 0xdf, 0x68, - 0x37, 0x84, 0xce, 0x00, 0x16, 0x5f, 0x9d, 0x9a, 0x5e, 0x04, 0xe0, 0xb1, - 0xa8, 0x39, 0x08, 0xfe, 0x75, 0xcc, 0x6b, 0x7c, 0x99, 0x28, 0x8d, 0x4c, - 0x50, 0x81, 0x0a, 0x4a, 0xba, 0x72, 0xbe, 0x90, 0x96, 0xcc, 0xac, 0x36, - 0x11, 0x5e, 0x9f, 0xe3, 0xc8, 0x97, 0x8b, 0x86, 0x87, 0x05, 0x68, 0x59, - 0x4d, 0xfa, 0xf7, 0xb8, 0x83, 0x0b, 0x42, 0xbd, 0xba, 0x63, 0x64, 0x3f, - 0xd6, 0xba, 0x66, 0x65, 0xbb, 0x1c, 0x69, 0x5d, 0xab, 0x22, 0x73, 0xd9, - 0xbc, 0x86, 0x0d, 0x06, 0x69, 0x63, 0x68, 0x61, 0x74, 0x64, 0x6b, 0x75, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x35, 0x1d, 0x3e, 0x1d, 0x24, 0xd4, 0x92, - 0xad, 0x2d, 0xbe, 0xf7, 0x22, 0xa4, 0x69, 0xce, 0x73, 0xef, 0xfc, 0x8d, - 0xfa, 0x05, 0xac, 0xfe, 0xf0, 0xa4, 0xe5, 0xb1, 0x82, 0x82, 0x42, 0xbd, - 0xaf, 0xba, 0xb2, 0x56, 0xf3, 0x3f, 0x14, 0x2c, 0xc6, 0xf5, 0x78, 0xb1, - 0x7f, 0x9e, 0xa5, 0xfb, 0x83, 0x3c, 0x1a, 0xdf, 0x4f, 0x79, 0x59, 0x61, - 0xed, 0xa5, 0x9a, 0x9b, 0x35, 0x8e, 0x10, 0x15, 0xb2, 0x49, 0x4d, 0x07, - 0x88, 0x4f, 0xc6, 0xb2, 0x3e, 0xca, 0x64, 0xae, 0xa3, 0x70, 0x5b, 0x2b, - 0xad, 0x74, 0x05, 0x2b, 0xc7, 0xcb, 0xff, 0x0e, 0x65, 0x85, 0xcc, 0xf3, - 0x4c, 0x85, 0x59, 0xa8, 0x34, 0x86, 0x92, 0xa5, 0xef, 0x3c, 0xdd, 0x52, - 0x13, 0x96, 0x52, 0x18, 0x3b, 0xd2, 0xaf, 0xab, 0x00, 0x17, 0x32, 0x82, - 0x71, 0xee, 0x90, 0x05, 0x81, 0x57, 0x52, 0x4f, 0x24, 0xff, 0xb3, 0xe6, - 0x3b, 0x94, 0xa3, 0x90, 0x7f, 0xd0, 0x26, 0xb0, 0x8b, 0x3e, 0xad, 0x36, - 0x5f, 0xb7, 0x28, 0x67, 0xac, 0xed, 0x35, 0xce, 0x51, 0xee, 0x78, 0xd5, - 0x99, 0x36, 0xea, 0x49, 0x22, 0x60, 0xc0, 0x75, 0x30, 0x7e, 0x96, 0x9d, - 0x60, 0x6e, 0x6a, 0xfb, 0x82, 0xb7, 0xa6, 0x41, 0xdf, 0x0c, 0x36, 0x9d, - 0xd2, 0xf7, 0xb7, 0xd1, 0x89, 0x95, 0x07, 0xac, 0x41, 0xa4, 0x60, 0x0a, - 0x6e, 0x4f, 0x41, 0xc3, 0x26, 0xed, 0xa0, 0x48, 0x91, 0xdd, 0xff, 0xc2, - 0xe9, 0x65, 0x2f, 0x76, 0x53, 0x05, 0xc3, 0x6f, 0x6a, 0x51, 0x27, 0xf8, - 0x55, 0xdf, 0xd7, 0xc3, 0x13, 0x25, 0x2d, 0x6b, 0xf1, 0x99, 0xd2, 0xda, - 0x9a, 0xed, 0x6d, 0x4f, 0xd0, 0x40, 0x73, 0xc2, 0x35, 0xeb, 0x8d, 0xa7, - 0x0f, 0x78, 0xc7, 0x43, 0x04, 0x53, 0x8d, 0x20, 0x6d, 0xb4, 0xd1, 0x18, - 0xf8, 0xd9, 0x5e, 0x92, 0x98, 0x0a, 0xa1, 0x16, 0xe8, 0x9f, 0x5a, 0x2a, - 0x2a, 0x89, 0x50, 0xda, 0xa3, 0xd6, 0xb1, 0xea, 0x50, 0x0c, 0x84, 0x7a, - 0xd9, 0xd8, 0x10, 0x75, 0x9d, 0x04, 0x3e, 0x4a, 0x5a, 0x8d, 0x9f, 0xf4, - 0xf9, 0xc4, 0x11, 0x6b, 0x76, 0x80, 0xf0, 0x56, 0x28, 0x13, 0xe3, 0x05, - 0x6b, 0x78, 0x23, 0x79, 0x88, 0x16, 0x51, 0x0c, 0x9b, 0xde, 0x4e, 0x90, - 0xd0, 0x2c, 0x53, 0x1c, 0x70, 0x41, 0xe7, 0xad, 0x73, 0xa3, 0xed, 0xc2, - 0x91, 0xc2, 0xb3, 0x3e, 0x99, 0xf2, 0x57, 0xf9, 0x7d, 0xc7, 0xc9, 0xe5, - 0x3e, 0xe2, 0x0b, 0x4b, 0xb6, 0xee, 0x29, 0x5b, 0xc9, 0xc5, 0xa6, 0x70, - 0x77, 0xe5, 0xbc, 0x43, 0x9e, 0xa2, 0x01, 0x22, 0x32, 0xb5, 0xdd, 0x1f, - 0x35, 0xd5, 0x3c, 0xdc, 0x7a, 0x4e, 0x85, 0x5f, 0xe2, 0x8f, 0x48, 0x28, - 0x70, 0x46, 0x89, 0x38, 0x5f, 0x72, 0x00, 0x65, 0x96, 0xfd, 0xc4, 0x36, - 0x01, 0xd6, 0x64, 0x70, 0xcc, 0xda, 0xd0, 0xc1, 0xee, 0x5b, 0x5a, 0xde, - 0x27, 0x1e, 0x35, 0xda, 0xae, 0x3c, 0xaf, 0xd3, 0x1c, 0x1a, 0x57, 0x24, - 0x0a, 0xf0, 0x79, 0xf0, 0xc1, 0xd7, 0x04, 0xcb, 0x21, 0xb2, 0xf4, 0x1e, - 0x1a, 0xa8, 0xc7, 0x89, 0xca, 0x1e, 0x68, 0x55, 0x71, 0x96, 0x68, 0x16, - 0x19, 0xb9, 0x9c, 0x96, 0xfa, 0xab, 0x34, 0xbb, 0xe0, 0x21, 0xb1, 0xae, - 0xb5, 0x8d, 0xf2, 0xd6, 0xce, 0x69, 0xc4, 0x58, 0x3f, 0x3c, 0xec, 0x28, - 0xcd, 0x9f, 0xfa, 0x97, 0xb3, 0xb0, 0xa4, 0x80, 0x7b, 0x07, 0x51, 0x0b, - 0x01, 0x23, 0x09, 0xcc, 0x7d, 0x94, 0x5d, 0xb4, 0xe9, 0x81, 0x5c, 0x3a, - 0x6b, 0xc4, 0x52, 0xc1, 0x86, 0xcc, 0xdf, 0x24, 0xcb, 0x3e, 0xbe, 0xc7, - 0xeb, 0xd7, 0xe0, 0x3a, 0xfc, 0xa1, 0x4d, 0x17, 0x8b, 0x41, 0x82, 0xeb, - 0x79, 0x2b, 0x87, 0x4d, 0xea, 0x27, 0xfb, 0x9e, 0x03, 0x75, 0xfc, 0x29, - 0x05, 0x4e, 0x76, 0xf3, 0x0f, 0x6d, 0xf2, 0x0f, 0xf6, 0x33, 0x58, 0x58, - 0xce, 0x67, 0xe7, 0x18, 0x97, 0x3a, 0x21, 0x4c, 0xaf, 0x64, 0x55, 0xd9, - 0x84, 0x53, 0xfd, 0x8b, 0x84, 0xad, 0x1a, 0xa5, 0x1c, 0x22, 0xac, 0xa5, - 0x21, 0xfb, 0xa2, 0x26, 0x69, 0x85, 0x24, 0xa3, 0x50, 0x24, 0x62, 0xe2, - 0xf8, 0x6c, 0x45, 0x97, 0xf6, 0xca, 0xe3, 0xbb, 0xb3, 0x02, 0x73, 0x7d, - 0x8b, 0x86, 0x69, 0xe6, 0x3a, 0x0c, 0x38, 0xa1, 0x85, 0xf5, 0xc8, 0xe6, - 0xbf, 0xce, 0x67, 0xeb, 0x68, 0xea, 0xe1, 0x05, 0x28, 0x48, 0xa6, 0xd5, - 0x2a, 0x35, 0xb5, 0x81, 0xaf, 0x3c, 0x47, 0xbb, 0x10, 0x4a, 0xc1, 0x29, - 0x9b, 0xa3, 0x16, 0x2b, 0x34, 0x18, 0x44, 0x2a, 0x1d, 0x43, 0x57, 0x1b, - 0x14, 0xea, 0x25, 0xbf, 0x1c, 0x95, 0x3e, 0x1e, 0x0d, 0x65, 0x50, 0x5a, - 0xe1, 0xd7, 0x14, 0x3f, 0xbb, 0xe2, 0xdd, 0x6f, 0x53, 0x5f, 0xd3, 0xc2, - 0x68, 0xa6, 0x14, 0xb2, 0x70, 0x36, 0x60, 0x99, 0x9d, 0x12, 0x9f, 0xee, - 0xcd, 0x99, 0x50, 0xbd, 0x41, 0x6f, 0x1b, 0xd4, 0x0d, 0x3b, 0xde, 0x00, - 0x20, 0xfd, 0x4c, 0x49, 0x80, 0x2e, 0x99, 0x4e, 0x23, 0xa8, 0x50, 0x14, - 0x42, 0x80, 0xb1, 0x4b, 0xe1, 0x97, 0x01, 0x1f, 0x8f, 0xf8, 0x05, 0x15, - 0xe6, 0x0e, 0x92, 0xdb, 0x10, 0xa2, 0x24, 0xf7, 0x4f, 0xc2, 0xf2, 0xe5, - 0xd8, 0xbc, 0xcc, 0x43, 0x10, 0xa0, 0x94, 0xff, 0x75, 0xee, 0xc2, 0x35, - 0x62, 0x2d, 0x9c, 0xe1, 0xd0, 0x0c, 0x02, 0x5b, 0xf0, 0x78, 0x32, 0xfe, - 0xf2, 0xf8, 0xdf, 0xd6, 0x7a, 0xdc, 0xc5, 0x82, 0xcd, 0xd4, 0x46, 0xd4, - 0x80, 0x99, 0xd6, 0x68, 0xb0, 0x60, 0xb2, 0x27, 0xdf, 0xbb, 0x41, 0x7f, - 0x49, 0x53, 0x93, 0x25, 0x05, 0x9a, 0xce, 0xc0, 0xd6, 0xc6, 0x46, 0xff, - 0xd7, 0xaa, 0x2d, 0xfa, 0x6b, 0x45, 0x09, 0xb0, 0xd2, 0x35, 0xfa, 0x8a, - 0xb4, 0xbb, 0xc2, 0x76, 0xe9, 0xd1, 0x91, 0x18, 0xde, 0x65, 0xd7, 0x81, - 0xa5, 0xbd, 0xd8, 0xf9, 0x89, 0xc6, 0x6f, 0xd9, 0xd3, 0xe4, 0x03, 0x4f, - 0x83, 0xf2, 0xd4, 0xd7, 0x41, 0x74, 0x5e, 0xe3, 0xcc, 0x8b, 0xf2, 0x22, - 0xb3, 0x89, 0xbc, 0xd5, 0x42, 0x43, 0x06, 0x76, 0xee, 0x0e, 0x79, 0x05, - 0xbd, 0xb2, 0x1e, 0xf6, 0x76, 0x12, 0x30, 0x2b, 0xd1, 0x9c, 0xe0, 0xd4, - 0xc9, 0x44, 0x09, 0x0a, 0xed, 0xae, 0x16, 0xdc, 0x9a, 0x26, 0xf4, 0xbb, - 0x37, 0xec, 0xc8, 0xa3, 0x7b, 0x12, 0x09, 0xcf, 0x17, 0x5c, 0x17, 0x74, - 0x0a, 0xa7, 0x71, 0x7c, 0xb0, 0x88, 0x15, 0xac, 0x98, 0xea, 0xfb, 0x3d, - 0x73, 0x3b, 0x46, 0xe9, 0xb0, 0x29, 0x73, 0xac, 0xe9, 0xdd, 0x1d, 0x8e, - 0xff, 0x79, 0xb9, 0x87, 0xf6, 0x07, 0x24, 0x49, 0xbf, 0xf6, 0x97, 0x71, - 0xbc, 0x5d, 0x14, 0x3f, 0x0f, 0x81, 0x6f, 0xcb, 0x49, 0x09, 0x51, 0x9e, - 0x4f, 0x24, 0x19, 0x7a, 0x00, 0x22, 0x9a, 0xa0, 0x52, 0xe3, 0x5b, 0x4a, - 0x9d, 0xe5, 0xb0, 0x96, 0xfc, 0x40, 0x15, 0xeb, 0x48, 0x1c, 0x4f, 0x25, - 0x64, 0xe9, 0x79, 0xbf, 0xb5, 0xef, 0x5f, 0xc3, 0x29, 0xbe, 0x7c, 0x6e, - 0x14, 0xe5, 0xe4, 0x36, 0xeb, 0x66, 0x27, 0x07, 0xbc, 0x2d, 0x1c, 0x2e, - 0x71, 0x51, 0x67, 0x60, 0x4d, 0xfc, 0x6c, 0x74, 0x8f, 0xc7, 0x84, 0x3e, - 0xe3, 0x8a, 0xfb, 0x34, 0xe3, 0x8e, 0x84, 0x5c, 0xdd, 0xc9, 0x0c, 0x3a, - 0xf4, 0x8c, 0xac, 0x40, 0xb0, 0x6b, 0x08, 0xe7, 0x4e, 0xa3, 0x92, 0xe3, - 0x57, 0xfc, 0x25, 0x08, 0x82, 0xd5, 0xf6, 0x35, 0x35, 0x41, 0x6a, 0xd9, - 0xf6, 0x78, 0x81, 0xca, 0x81, 0xe7, 0x5b, 0x58, 0x15, 0x5c, 0x57, 0x6e, - 0x5e, 0xe1, 0x65, 0xe5, 0xfc, 0xb1, 0xe9, 0x1a, 0x97, 0x9d, 0x86, 0xb9, - 0xb1, 0xa1, 0xb0, 0xbd, 0x3e, 0xb8, 0x0d, 0xc6, 0x33, 0x7e, 0xb5, 0x47, - 0xcc, 0x0a, 0x29, 0xcb, 0xf9, 0xaa, 0xff, 0x14, 0x33, 0x01, 0xd0, 0x3d, - 0x12, 0xb6, 0xc9, 0x33, 0x5d, 0xa8, 0x99, 0x30, 0x38, 0x38, 0xe3, 0x35, - 0x5a, 0x36, 0xf9, 0xca, 0xaf, 0x1d, 0xfe, 0x8c, 0x6a, 0xb7, 0xce, 0x67, - 0x0c, 0x6d, 0xc2, 0x29, 0xcd, 0x9e, 0x32, 0x46, 0xe8, 0xf4, 0x23, 0xa3, - 0xf3, 0xff, 0xf5, 0x74, 0xa6, 0xeb, 0xbd, 0xc3, 0x3e, 0xe2, 0x14, 0xd9, - 0xa5, 0xe8, 0x0e, 0xf6, 0x6f, 0xbd, 0xc3, 0x08, 0x56, 0x0a, 0xf0, 0x8a, - 0x14, 0xa1, 0xd6, 0x2d, 0xaf, 0xf7, 0x03, 0xff, 0xdc, 0x1c, 0x85, 0xdb, - 0xc9, 0x10, 0x33, 0xa2, 0x8d, 0x46, 0x69, 0x51, 0x70, 0x59, 0xc9, 0x4d, - 0x38, 0xb2, 0x69, 0x0e, 0xa8, 0xf4, 0xef, 0xdf, 0xb6, 0x34, 0xcf, 0x3d, - 0xec, 0xe8, 0x37, 0xea, 0xb3, 0x8e, 0x70, 0xb6, 0xf8, 0x5a, 0xa5, 0x13, - 0xde, 0x4c, 0x18, 0x6d, 0x04, 0xc5, 0xfd, 0xa4, 0x28, 0x15, 0x1b, 0x49, - 0xb3, 0x39, 0xfe, 0x9b, 0x54, 0xc1, 0x1e, 0x7f, 0x86, 0xe8, 0x3c, 0xe7, - 0xd5, 0x55, 0xa8, 0x89, 0xe1, 0xf4, 0xb5, 0x94, 0x0b, 0xff, 0xa8, 0xc2, - 0x56, 0xaa, 0xba, 0x6d, 0xb9, 0xc7, 0x54, 0xea, 0xbb, 0x1a, 0x17, 0x2a, - 0x3e, 0xae, 0x10, 0x2b, 0x89, 0xa8, 0x5d, 0xb1, 0x13, 0x46, 0xb1, 0x1c, - 0x6c, 0x7c, 0x58, 0x27, 0xc6, 0xf8, 0xfb, 0x9b, 0xca, 0x6b, 0x12, 0xd4, - 0x14, 0xbf, 0x3b, 0xb8, 0xea, 0xa7, 0xfa, 0x76, 0x55, 0x16, 0x0b, 0x2c, - 0xbb, 0x94, 0xd1, 0x12, 0x47, 0x0f, 0x3f, 0x89, 0xf4, 0xc2, 0xc3, 0x8d, - 0x03, 0x11, 0x0c, 0xe8, 0xe3, 0x96, 0x8f, 0x89, 0x25, 0x90, 0xa5, 0xe1, - 0xf4, 0x20, 0xf4, 0xfc, 0x24, 0xfe, 0xf0, 0x28, 0x11, 0x2a, 0x74, 0x10, - 0x9e, 0x20, 0x79, 0x11, 0xd4, 0x8b, 0x4b, 0x26, 0x75, 0x4f, 0x82, 0xd8, - 0x17, 0x64, 0xdf, 0x21, 0x73, 0x85, 0xa7, 0x57, 0x35, 0x8d, 0x67, 0x37, - 0x4a, 0x9a, 0xfe, 0x87, 0xa7, 0x45, 0x87, 0x51, 0xf3, 0x19, 0x3b, 0x1a, - 0xd4, 0x39, 0x37, 0x45, 0x99, 0xe9, 0x71, 0x96, 0x8b, 0x3e, 0xd8, 0xa6, - 0x8e, 0xc7, 0xf5, 0x62, 0x14, 0x1c, 0x8c, 0x4c, 0xfa, 0x60, 0x48, 0x35, - 0xb1, 0xba, 0xcd, 0xf5, 0xba, 0xf5, 0x67, 0xb6, 0xa2, 0x38, 0xf9, 0xd2, - 0xa3, 0xde, 0xbc, 0xfb, 0x58, 0xb2, 0xd2, 0x3d, 0x10, 0x63, 0x12, 0xed, - 0x23, 0xfd, 0xab, 0x65, 0x18, 0x6d, 0x94, 0x61, 0x06, 0xaa, 0x0b, 0xcc, - 0x3c, 0xd2, 0x91, 0xc9, 0x1b, 0x1e, 0x66, 0x38, 0x26, 0x0b, 0x0a, 0xb8, - 0x15, 0x88, 0xaf, 0x93, 0x03, 0x41, 0x2f, 0x0c, 0x2b, 0x68, 0x94, 0x1f, - 0xa7, 0x8d, 0xed, 0x3d, 0xa1, 0xca, 0x53, 0x93, 0xf8, 0x81, 0x95, 0x07, - 0xc5, 0x92, 0xf0, 0xa4, 0x74, 0x76, 0x1b, 0x14, 0x6e, 0xe6, 0x2f, 0x71, - 0x43, 0x8e, 0x79, 0x4c, 0x91, 0x71, 0xd7, 0x1e, 0x63, 0x94, 0xbd, 0xba, - 0x40, 0xb2, 0x86, 0x95, 0x90, 0x8c, 0xad, 0x22, 0x65, 0xfa, 0x65, 0x4c, - 0x65, 0xc4, 0x78, 0x7c, 0xef, 0x7a, 0x46, 0x25, 0xad, 0xac, 0xfc, 0x9c, - 0x6f, 0x24, 0xdf, 0xe4, 0xfe, 0x5f, 0x67, 0x31, 0x4e, 0xb9, 0x2a, 0xdb, - 0xfd, 0xfc, 0x9b, 0x99, 0xe4, 0xc3, 0x7b, 0x61, 0x04, 0x76, 0x0f, 0x4d, - 0x21, 0xcb, 0x27, 0xd9, 0x6d, 0x62, 0x42, 0x4f, 0x6c, 0xd8, 0x0a, 0xbc, - 0xa9, 0xbb, 0xc6, 0x61, 0x4b, 0xc3, 0xec, 0x82, 0x8b, 0xcc, 0x7b, 0x55, - 0xdd, 0xaa, 0xc1, 0x9e, 0x93, 0xd8, 0x77, 0xae, 0x34, 0x83, 0xbc, 0x90, - 0x85, 0x73, 0x4f, 0xba, 0x55, 0xa6, 0x66, 0x31, 0xe3, 0x8b, 0x11, 0x6b, - 0xce, 0xdf, 0x6a, 0xa3, 0x6e, 0xca, 0xe5, 0x65, 0x77, 0xd6, 0x08, 0x22, - 0x20, 0x20, 0x44, 0x04, 0xc7, 0x2a, 0x46, 0x4f, 0x17, 0xc7, 0xf6, 0x6f, - 0x45, 0x6a, 0xd3, 0xfc, 0xce, 0xa0, 0x9c, 0x43, 0xe3, 0x68, 0x83, 0x9b, - 0x70, 0x7f, 0x74, 0x1e, 0x8f, 0x9b, 0x61, 0x2d, 0x7f, 0x1f, 0x45, 0xd1, - 0xef, 0x92, 0xfb, 0x5f, 0xfa, 0x7a, 0x7f, 0x20, 0x0d, 0x86, 0xc6, 0x6f, - 0x5d, 0x8a, 0x0a, 0xd2, 0xb7, 0xe6, 0x82, 0xc9, 0x66, 0xb7, 0x54, 0x20, - 0x80, 0x19, 0xc9, 0x09, 0x10, 0x7e, 0x81, 0x92, 0x93, 0xab, 0x4e, 0xc9, - 0x49, 0x2d, 0xf4, 0xef, 0x5d, 0x08, 0x37, 0x6e, 0x0c, 0xfa, 0xfc, 0xd3, - 0xe0, 0xc4, 0x43, 0x04, 0x15, 0x47, 0x51, 0x9b, 0xc3, 0x9b, 0x6b, 0x80, - 0x03, 0xc6, 0x8b, 0x9a, 0x0d, 0x3c, 0xf1, 0x49, 0x0b, 0xd6, 0x39, 0x36, - 0x42, 0xd4, 0x81, 0xb2, 0x63, 0xe0, 0xa0, 0x8a, 0x34, 0xc0, 0x8a, 0xd0, - 0x67, 0xed, 0x3f, 0xed, 0x5f, 0x46, 0xa6, 0x04, 0x6b, 0x07, 0x81, 0xaa, - 0xc6, 0xc5, 0x0f, 0x17, 0x82, 0x28, 0xe9, 0xc7, 0xcd, 0xe5, 0xfc, 0xc3, - 0xb6, 0x45, 0xce, 0xe9, 0xd5, 0xe6, 0xe1, 0xc3, 0x92, 0x88, 0xe3, 0x22, - 0x3d, 0x63, 0x99, 0x47, 0x00, 0x3c, 0x21, 0x71, 0x02, 0x84, 0xd5, 0xb0, - 0x05, 0x9d, 0x19, 0x71, 0x5c, 0x9c, 0xea, 0x21, 0x64, 0x59, 0x0c, 0xa2, - 0x33, 0xdd, 0xcb, 0xcc, 0x5d, 0xcf, 0xd3, 0xc5, 0xc5, 0x38, 0xfc, 0xe1, - 0x9d, 0xd7, 0xff, 0xe4, 0x13, 0x76, 0x9d, 0xe7, 0xa5, 0xa1, 0x76, 0xc5, - 0xd3, 0xa6, 0xfa, 0x62, 0x5e, 0xb0, 0xf9, 0x8c, 0x1d, 0x8a, 0x75, 0x7f, - 0xef, 0x5b, 0x73, 0x76, 0xb6, 0x0a, 0x0e, 0xca, 0x34, 0x77, 0x7c, 0x42, - 0xcb, 0xe3, 0x62, 0x34, 0xda, 0xf2, 0x5a, 0x83, 0x37, 0xdd, 0xba, 0x06, - 0x4c, 0xa6, 0xf2, 0x80, 0x87, 0xfe, 0x61, 0x0b, 0xa3, 0x27, 0x84, 0x28, - 0x80, 0x81, 0x9a, 0x07, 0x4f, 0x77, 0xbf, 0x56, 0x7c, 0xe9, 0x24, 0xdc, - 0xa0, 0xe7, 0x1c, 0x0a, 0x32, 0x67, 0x22, 0x64, 0x47, 0x1c, 0x41, 0x06, - 0xac, 0x0a, 0x1f, 0x34, 0xa2, 0x08, 0xd9, 0x94, 0x02, 0x91, 0x79, 0x73, - 0x1e, 0x86, 0xd2, 0x21, 0x71, 0x02, 0x8d, 0xf3, 0xef, 0x9f, 0x17, 0xac, - 0xe2, 0x74, 0xec, 0x11, 0xbb, 0xe4, 0x62, 0xfc, 0x17, 0x38, 0x7d, 0x57, - 0x21, 0x0d, 0x5a, 0x4e, 0x8d, 0xa5, 0x8b, 0xc6, 0x44, 0xd9, 0xfb, 0x42, - 0xd5, 0x0b, 0x18, 0xdd, 0xf1, 0x7d, 0xca, 0x3b, 0x02, 0x00, 0x23, 0x38, - 0xd6, 0xa9, 0xb8, 0x4b, 0x1f, 0x7a, 0xe8, 0x55, 0x4a, 0xb3, 0xaf, 0xf8, - 0x0a, 0x57, 0xe5, 0xd7, 0xff, 0xee, 0x2b, 0xbc, 0xb5, 0x1f, 0xb5, 0xf1, - 0x43, 0xd0, 0x6f, 0xcf, 0xf1, 0x4e, 0x22, 0xe0, 0x01, 0x79, 0xc1, 0xbd, - 0x1e, 0xdb, 0x48, 0xb6, 0x9c, 0x26, 0xc2, 0xa9, 0x91, 0xee, 0x89, 0x1b, - 0xd5, 0x23, 0x08, 0x8c, 0x62, 0xc9, 0x86, 0x3e, 0x33, 0x6a, 0xb9, 0x7f, - 0x63, 0x51, 0x28, 0xab, 0xba, 0x60, 0x2c, 0x12, 0xcf, 0x66, 0x43, 0x38, - 0x0d, 0xc5, 0x3b, 0x2f, 0xf0, 0x70, 0x9c, 0xeb, 0x39, 0xe0, 0x8f, 0xcd, - 0x4c, 0x73, 0x1c, 0x70, 0x01, 0xfa, 0x78, 0xd3, 0x16, 0x1a, 0xae, 0x27, - 0x2d, 0x02, 0xdc, 0xdb, 0xba, 0x4b, 0xed, 0xae, 0x61, 0x1f, 0x55, 0x77, - 0xf5, 0xff, 0x88, 0xdb, 0x8b, 0xfc, 0x18, 0xc4, 0x9b, 0x41, 0xf1, 0x0e, - 0x6f, 0x6e, 0xc6, 0x77, 0x05, 0x8c, 0x6a, 0x7d, 0xbd, 0x69, 0xb8, 0x26, - 0x68, 0xd1, 0x55, 0x93, 0x9b, 0x4c, 0x66, 0xd6, 0xcf, 0xb4, 0x33, 0x5e, - 0x6a, 0xc1, 0x96, 0xca, 0xe6, 0x8b, 0x2d, 0xdf, 0xd6, 0x1d, 0xa6, 0x67, - 0xfc, 0x26, 0x96, 0xfc, 0xfa, 0xcd, 0x65, 0x77, 0x43, 0x44, 0x10, 0x01, - 0x08, 0x93, 0xa6, 0xb2, 0x1a, 0x27, 0x9c, 0x50, 0xde, 0xc0, 0xcf, 0xba, - 0x8d, 0x35, 0x6c, 0x57, 0x5b, 0x0e, 0x11, 0x7c, 0x89, 0x74, 0xca, 0x7e, - 0xf5, 0x08, 0xaf, 0xe4, 0x9f, 0x78, 0x14, 0x8d, 0x2e, 0x1f, 0x47, 0x0a, - 0x18, 0x26, 0xb0, 0x7d, 0xce, 0x36, 0x63, 0x30, 0xa5, 0x63, 0x5e, 0x10, - 0x98, 0xf9, 0xe2, 0x57, 0xe2, 0x0c, 0x17, 0x34, 0xfd, 0x4c, 0x35, 0xe5, - 0x44, 0xbf, 0xf1, 0xa1, 0x9f, 0x07, 0x4c, 0x5f, 0xb1, 0xff, 0x57, 0xd3, - 0xf9, 0xe8, 0xd6, 0x76, 0xae, 0xda, 0xd0, 0xd8, 0x49, 0x44, 0x65, 0x76, - 0xd1, 0xa3, 0x1b, 0xe5, 0x5e, 0x86, 0x12, 0xd2, 0x77, 0x6c, 0x19, 0xfa, - 0x32, 0x9b, 0xe6, 0xf8, 0x6d, 0xc8, 0x87, 0x52, 0xad, 0x80, 0xcd, 0xbd, - 0x83, 0xa7, 0x94, 0x68, 0x39, 0x01, 0x32, 0xa4, 0x91, 0x20, 0xe9, 0xb8, - 0xcc, 0x49, 0x8a, 0xad, 0x9f, 0x59, 0x11, 0x2a, 0x8a, 0x8c, 0xaa, 0x54, - 0x82, 0x58, 0x97, 0xc9, 0x4e, 0x2e, 0x99, 0xa0, 0xc6, 0x29, 0xc3, 0x3b, - 0x61, 0x51, 0xf8, 0x65, 0xa5, 0x76, 0x33, 0xf5, 0xa4, 0x5d, 0x3e, 0x3f, - 0xdc, 0xfc, 0x4d, 0xa9, 0x78, 0x16, 0x29, 0x61, 0x5f, 0x2b, 0x1d, 0x82, - 0x61, 0x8e, 0x5e, 0xb6, 0x10, 0xfc, 0x6c, 0x07, 0x9d, 0xe8, 0x34, 0x5d, - 0xe0, 0xad, 0x81, 0x19, 0x4c, 0x32, 0x9b, 0x1c, 0x5d, 0xae, 0xe6, 0x4e, - 0xaf, 0xba, 0xf3, 0x0d, 0x54, 0x7a, 0x9f, 0x84, 0x5b, 0xc0, 0x6c, 0xba, - 0x21, 0x14, 0x19, 0x57, 0x09, 0x63, 0x48, 0x92, 0xdb, 0x8b, 0x02, 0xff, - 0xf9, 0x3b, 0xd5, 0xe7, 0xa1, 0x97, 0x57, 0x88, 0x95, 0xc9, 0xf7, 0x99, - 0xc8, 0xab, 0x28, 0x6f, 0x89, 0x06, 0xde, 0x54, 0x2e, 0xe5, 0xeb, 0x51, - 0x0f, 0x36, 0xfd, 0xcf, 0x37, 0x43, 0x67, 0x21, 0xd8, 0xeb, 0xa4, 0xeb, - 0x5d, 0xf4, 0x64, 0xd5, 0xb7, 0x1d, 0xf6, 0xea, 0x0a, 0xe9, 0x75, 0x77, - 0xe5, 0x4e, 0xa4, 0x28, 0xdc, 0xc4, 0x09, 0xce, 0xf0, 0x66, 0x8f, 0x8c, - 0xa0, 0x28, 0x81, 0xc5, 0x87, 0x00, 0x61, 0x6b, 0xd3, 0x15, 0x3b, 0x81, - 0x9b, 0x72, 0xc5, 0xfc, 0x04, 0x22, 0x4c, 0x29, 0xfa, 0x42, 0x41, 0x0b, - 0x7c, 0xe5, 0xd9, 0xf6, 0xcd, 0x0d, 0xd5, 0x98, 0x05, 0x3c, 0x5e, 0x4c, - 0x0d, 0x4d, 0x1b, 0x8c, 0x8e, 0xb2, 0x13, 0xa9, 0xf7, 0x46, 0x38, 0xa1, - 0x52, 0x20, 0x67, 0x96, 0xa9, 0x50, 0x33, 0x7f, 0xb3, 0x00, 0x21, 0x3e, - 0x4e, 0x47, 0xd9, 0x9c, 0x53, 0x8d, 0xf7, 0xb6, 0xfa, 0x45, 0x19, 0x57, - 0x56, 0xfa, 0x4e, 0x75, 0x07, 0x9f, 0xe4, 0x5e, 0x13, 0xa9, 0x2b, 0xd7, - 0x70, 0x3b, 0xca, 0x2b, 0xd4, 0x65, 0xb1, 0xbc, 0xb6, 0xc0, 0xbc, 0xfa, - 0x58, 0x3a, 0x09, 0x9e, 0x4e, 0x8c, 0x08, 0xd0, 0x3c, 0xd1, 0xb0, 0x1c, - 0xd2, 0x60, 0xdd, 0x4e, 0xaf, 0xef, 0x62, 0x97, 0x01, 0x80, 0xb8, 0xab, - 0x22, 0x74, 0x2e, 0x0f, 0xd2, 0x34, 0x1b, 0x88, 0x86, 0x9a, 0xa1, 0x5f, - 0xf1, 0x2a, 0x4b, 0x90, 0xd4, 0x1c, 0x68, 0x7a, 0xb0, 0xb8, 0x6a, 0x2c, - 0xeb, 0x80, 0xdf, 0x6d, 0x4c, 0xf6, 0x43, 0x0e, 0x52, 0x91, 0x89, 0x10, - 0x6d, 0x71, 0xec, 0x03, 0xe9, 0x27, 0x2a, 0xa6, 0x31, 0xbb, 0xaa, 0x39, - 0x40, 0xef, 0x97, 0xe3, 0xec, 0x88, 0xb8, 0x47, 0x98, 0x4e, 0xc6, 0xf7, - 0xa3, 0x98, 0x6d, 0xc7, 0x1c, 0x12, 0x55, 0xf2, 0x4f, 0x8e, 0x61, 0xad, - 0x68, 0xb3, 0xf2, 0xf2, 0x1f, 0x20, 0x85, 0xba, 0x9f, 0x8a, 0x7d, 0x91, - 0xe2, 0x3f, 0xf7, 0xa6, 0x7f, 0x3f, 0xee, 0x09, 0x47, 0xf9, 0x7f, 0x68, - 0xcf, 0x83, 0xaf, 0x01, 0xda, 0x33, 0x0b, 0x88, 0xf0, 0xf7, 0xcb, 0x7a, - 0xa5, 0x92, 0x42, 0x0f, 0xd6, 0xc8, 0x25, 0xc1, 0xff, 0x8e, 0x32, 0xc0, - 0xbc, 0x72, 0x92, 0xc9, 0xf4, 0xf5, 0xfa, 0x15, 0x9b, 0x00, 0x46, 0x25, - 0x6e, 0x24, 0xf6, 0x10, 0x95, 0xea, 0x1c, 0xb0, 0x96, 0x0e, 0x8f, 0xb5, - 0x70, 0x68, 0xa7, 0x8f, 0x60, 0x23, 0xc7, 0xeb, 0x26, 0x09, 0xc9, 0x45, - 0x6a, 0xdc, 0x6e, 0xde, 0x82, 0x0f, 0xac, 0xea, 0x22, 0x5d, 0x47, 0x26, - 0xee, 0x9a, 0x6e, 0x0a, 0x42, 0xf2, 0xda, 0x18, 0x3c, 0x7d, 0xd8, 0x68, - 0x7e, 0x4a, 0x4c, 0xbd, 0xb0, 0x00, 0x73, 0x2c, 0x5c, 0x33, 0xf8, 0xb3, - 0x3e, 0x5c, 0xc7, 0x3b, 0xf4, 0x8d, 0xee, 0xee, 0x83, 0x21, 0x5c, 0x42, - 0x24, 0xb3, 0x13, 0xb3, 0x28, 0x1b, 0x85, 0xf5, 0xaa, 0x1c, 0xf9, 0xd8, - 0x90, 0x91, 0xaf, 0x98, 0x40, 0x7c, 0xce, 0x8c, 0x12, 0x5c, 0x68, 0x86, - 0xd4, 0x55, 0xd8, 0x80, 0x93, 0x01, 0x64, 0x34, 0x98, 0x8b, 0x9a, 0x7a, - 0x85, 0x62, 0xc0, 0x76, 0x92, 0xa3, 0x98, 0x11, 0x13, 0x60, 0xc3, 0x72, - 0xb4, 0xb1, 0x8b, 0xf4, 0xf8, 0xc6, 0x23, 0xf6, 0xe6, 0x98, 0x5a, 0xde, - 0x48, 0xff, 0x86, 0x28, 0x41, 0x6c, 0xcb, 0xc7, 0x70, 0x90, 0x17, 0xb9, - 0x61, 0x0f, 0x26, 0x2f, 0x8f, 0xb9, 0x56, 0x49, 0x79, 0x09, 0x88, 0xf2, - 0x3e, 0xff, 0x06, 0x90, 0xb5, 0x78, 0x8e, 0xb1, 0xac, 0x89, 0xe8, 0x8b, - 0x26, 0x4b, 0x6e, 0x7c, 0xbd, 0x54, 0x76, 0xdb, 0x6f, 0x78, 0xfc, 0xdd, - 0x9d, 0x31, 0x17, 0x15, 0xb7, 0x65, 0xc7, 0x9f, 0x55, 0x76, 0x5e, 0xa0, - 0xb9, 0x8e, 0xd9, 0xa1, 0x93, 0x23, 0x6c, 0x18, 0x47, 0x31, 0xee, 0x73, - 0x77, 0xa1, 0x44, 0xb2, 0x53, 0xd8, 0xd6, 0x82, 0x07, 0x0e, 0x1b, 0x86, - 0x2d, 0xb0, 0xe2, 0x22, 0x9f, 0xac, 0xb6, 0xb7, 0x88, 0xa0, 0x03, 0x07, - 0xe6, 0xbd, 0x45, 0x4d, 0x50, 0xec, 0xce, 0x4d, 0xe9, 0x43, 0x90, 0x8e, - 0xaf, 0xdf, 0xc0, 0x4d, 0xe8, 0x3d, 0xfe, 0xb8, 0x34, 0x2b, 0x81, 0xbf, - 0x02, 0x50, 0x87, 0x40, 0xaa, 0x70, 0x43, 0xc8, 0xda, 0x8e, 0xc0, 0xa6, - 0x7a, 0xab, 0xe7, 0x5a, 0x4d, 0xf2, 0x44, 0x9d, 0xbd, 0x7e, 0x76, 0x63, - 0xd8, 0x00, 0x45, 0xb2, 0x1e, 0x20, 0xb7, 0x96, 0x08, 0xb9, 0x4c, 0x06, - 0x81, 0x43, 0x26, 0xd4, 0x5b, 0x90, 0x3c, 0x39, 0xc3, 0x3b, 0xee, 0x27, - 0x7a, 0x4e, 0x1d, 0x5f, 0x9e, 0xeb, 0xe1, 0x2f, 0x10, 0xf0, 0xd9, 0x2e, - 0x61, 0x8a, 0x67, 0xca, 0xbb, 0xbf, 0x17, 0xe3, 0xf6, 0x58, 0xaa, 0xeb, - 0x5f, 0xd7, 0xda, 0xfb, 0x81, 0x63, 0x0e, 0xe0, 0xac, 0x93, 0xe8, 0x1b, - 0x11, 0x3a, 0x1f, 0x51, 0x26, 0x99, 0xea, 0xf3, 0x73, 0x99, 0x2a, 0xd0, - 0xaf, 0x76, 0xd1, 0xda, 0xcc, 0xfe, 0xce, 0x82, 0x69, 0x6d, 0xe4, 0xc3, - 0x44, 0xa6, 0x7a, 0x8e, 0xda, 0x44, 0xdf, 0x07, 0xaf, 0xf0, 0x6d, 0x33, - 0x90, 0x8a, 0xc4, 0x8c, 0x68, 0xa6, 0x86, 0xa8, 0x59, 0x00, 0x62, 0x36, - 0x0c, 0x55, 0x7d, 0x63, 0xd2, 0xea, 0x3a, 0x2b, 0x6a, 0x5b, 0x76, 0x9d, - 0xab, 0x26, 0xb6, 0x25, 0xe7, 0x95, 0x42, 0x54, 0x11, 0xf5, 0x05, 0x33, - 0x7f, 0x6e, 0x8a, 0xa0, 0x4c, 0x25, 0x63, 0x3f, 0x13, 0xfe, 0x81, 0x54, - 0x7b, 0x86, 0x45, 0x9b, 0xba, 0x6b, 0x34, 0x4a, 0x1e, 0xeb, 0x92, 0x67, - 0x9e, 0x13, 0x30, 0xc1, 0x3c, 0xfd, 0xe1, 0xe8, 0xbe, 0xe2, 0x5c, 0x93, - 0xf5, 0xd9, 0xf6, 0x9d, 0x42, 0x88, 0x59, 0x2f, 0x76, 0x77, 0x6a, 0x4a, - 0x4c, 0x8e, 0xed, 0x0e, 0x49, 0x7e, 0xdc, 0x08, 0xef, 0x84, 0x74, 0x1e, - 0x27, 0x37, 0x53, 0xd4, 0x7e, 0xbf, 0xac, 0x32, 0x94, 0x00, 0x06, 0xf4, - 0x57, 0x0f, 0xa6, 0xe7, 0xa6, 0x70, 0x25, 0x3a, 0x2e, 0x8d, 0x83, 0xa0, - 0x1c, 0xa8, 0x08, 0x2c, 0xbd, 0x14, 0x71, 0xad, 0x57, 0xd1, 0xb1, 0xed, - 0x49, 0x91, 0x1f, 0x72, 0xe8, 0xab, 0x46, 0x83, 0x89, 0xb8, 0x16, 0xe4, - 0xf5, 0x7f, 0x73, 0x1f, 0x44, 0x01, 0xc9, 0x88, 0x9c, 0xdc, 0x65, 0xb4, - 0x44, 0xbd, 0x47, 0x8b, 0x52, 0x48, 0x5c, 0x30, 0xf9, 0x73, 0xa0, 0x8c, - 0x72, 0xa3, 0x4c, 0x93, 0x0f, 0xb1, 0xda, 0x0b, 0x8c, 0x02, 0xb4, 0x07, - 0x06, 0xda, 0x78, 0xed, 0x7a, 0x4c, 0x4a, 0xb2, 0x21, 0xee, 0x23, 0xe8, - 0x56, 0x4c, 0x6d, 0x03, 0xa0, 0x71, 0x2c, 0xdf, 0x6a, 0xc4, 0x68, 0xa4, - 0xf0, 0x18, 0x49, 0xcd, 0x7e, 0x66, 0xef, 0x62, 0x1e, 0xe7, 0x23, 0x3b, - 0x87, 0x19, 0x54, 0x12, 0x67, 0x63, 0xb7, 0x5f, 0xa6, 0xd2, 0x26, 0xed, - 0x33, 0x09, 0xfe, 0x58, 0xae, 0x78, 0x48, 0x03, 0x17, 0x00, 0x01, 0x7f, - 0x70, 0xe2, 0xde, 0xc0, 0x1d, 0x4c, 0x32, 0x66, 0xec, 0xe0, 0x8f, 0x00, - 0x3e, 0xf3, 0x57, 0x77, 0xe3, 0x9b, 0x8d, 0x70, 0xac, 0x3c, 0x36, 0x0e, - 0x7b, 0x67, 0xc6, 0x1d, 0xc5, 0x64, 0x9c, 0x0a, 0xfb, 0xdb, 0x40, 0xf9, - 0x85, 0x42, 0x1a, 0x01, 0x4b, 0x86, 0xb2, 0x60, 0xc3, 0xc6, 0x69, 0x48, - 0xff, 0x22, 0xf8, 0xcb, 0xc2, 0x4a, 0xb2, 0x36, 0x62, 0xdb, 0xaa, 0x1f, - 0xe5, 0xdc, 0x2c, 0xa5, 0x2c, 0x33, 0x42, 0xf0, 0xe3, 0x9b, 0x48, 0xa7, - 0x50, 0xaa, 0x0f, 0x3e, 0x6c, 0xfb, 0xed, 0x4b, 0xbd, 0xd1, 0x1b, 0x5d, - 0x96, 0xa2, 0x9c, 0x1a, 0xe3, 0xb6, 0x32, 0xf0, 0xcb, 0x08, 0x60, 0xdf, - 0x48, 0xde, 0x04, 0x62, 0xfc, 0x01, 0x30, 0x29, 0x9e, 0x39, 0x4a, 0x0c, - 0x4f, 0x79, 0x3b, 0xc9, 0xce, 0xd8, 0xc4, 0xee, 0xcc, 0xdc, 0x63, 0x50, - 0xe5, 0xa4, 0x6c, 0x95, 0x66, 0xc0, 0x47, 0x0f, 0xbe, 0xa2, 0x02, 0x6d, - 0xcd, 0x32, 0xc3, 0x14, 0x0e, 0x95, 0x21, 0xbc, 0x61, 0xee, 0x25, 0x65, - 0xfc, 0x4c, 0x23, 0xe0, 0xa5, 0x0a, 0x65, 0xc0, 0xe3, 0xe8, 0x56, 0x10, - 0xb3, 0xb1, 0x6a, 0xd1, 0xd3, 0x71, 0xb2, 0xb5, 0x90, 0x74, 0x32, 0x24, - 0xe5, 0xa7, 0x04, 0x37, 0xde, 0x71, 0xef, 0x08, 0x4c, 0x1c, 0x80, 0x6b, - 0x99, 0x17, 0x47, 0x72, 0x44, 0x31, 0x22, 0xd9, 0xce, 0xff, 0x61, 0x2d, - 0x72, 0xe0, 0xbd, 0x48, 0x3e, 0xfd, 0x5a, 0xc5, 0x7b, 0x16, 0x96, 0xbd, - 0x47, 0x60, 0x6d, 0xa1, 0x6a, 0x34, 0xe9, 0xaa, 0xd5, 0xfe, 0x09, 0x1d, - 0xfa, 0x94, 0xb8, 0xc0, 0x63, 0xa9, 0x1d, 0x8a, 0x27, 0x7b, 0xf0, 0xd2, - 0xe7, 0x3e, 0x5e, 0x6e, 0x6a, 0x8e, 0xe3, 0x4b, 0xa8, 0x0c, 0xac, 0xc4, - 0x50, 0x1c, 0xa0, 0xfc, 0x48, 0x42, 0x53, 0x54, 0x08, 0x64, 0xae, 0x9f, - 0x19, 0xd6, 0xd3, 0xc9, 0x55, 0x0e, 0x72, 0x18, 0x53, 0xef, 0x02, 0xd1, - 0x14, 0x81, 0xa9, 0xa8, 0xb6, 0xf5, 0x93, 0x56, 0xcb, 0xd0, 0x63, 0xbc, - 0xb9, 0xfd, 0x77, 0xa4, 0x1d, 0x3f, 0x29, 0xba, 0x97, 0xb5, 0xed, 0x7c, - 0xe5, 0x35, 0xe5, 0x74, 0x6b, 0x08, 0xe8, 0x3f, 0x6d, 0xc4, 0x70, 0x06, - 0x3b, 0xd1, 0x92, 0xcc, 0xab, 0x7a, 0x22, 0x13, 0x96, 0x41, 0xfc, 0x92, - 0x81, 0xb7, 0x39, 0xdf, 0x68, 0xaa, 0x77, 0x21, 0x87, 0xff, 0x78, 0x83, - 0xf5, 0xca, 0x8b, 0x08, 0xa9, 0xcd, 0xc0, 0xa0, 0xb8, 0x7c, 0x52, 0x93, - 0xec, 0x93, 0x5c, 0xe6, 0xd9, 0xc9, 0x49, 0x94, 0x60, 0xac, 0x1c, 0x9e, - 0x1e, 0x19, 0xac, 0xc3, 0xfa, 0x3f, 0xe0, 0x36, 0x1d, 0x99, 0x8f, 0xea, - 0xc7, 0xe6, 0x1e, 0x0b, 0x7f, 0x02, 0x73, 0x3c, 0xda, 0x49, 0x68, 0x44, - 0x91, 0x76, 0x3c, 0x4d, 0x53, 0xfc, 0xda, 0x99, 0x8d, 0x13, 0xcf, 0xd3, - 0x88, 0xbb, 0xdf, 0x3f, 0xab, 0x42, 0x08, 0x9b, 0xeb, 0x1f, 0x93, 0x09, - 0x59, 0x39, 0x21, 0x2c, 0x91, 0xe5, 0xef, 0x97, 0xf7, 0x8c, 0x56, 0x34, - 0x66, 0x94, 0x05, 0x18, 0x1b, 0x50, 0x41, 0xf3, 0xa6, 0xca, 0x82, 0xdf, - 0xa3, 0x8e, 0xa9, 0x3f, 0x6d, 0xa0, 0xfb, 0x74, 0x2b, 0x35, 0x2c, 0x02, - 0xc3, 0xd3, 0xba, 0x21, 0x0e, 0xef, 0x23, 0x35, 0x06, 0xcd, 0xc7, 0x5e, - 0x44, 0x6f, 0xa5, 0x5d, 0xee, 0x9a, 0x42, 0x54, 0x47, 0x78, 0xbe, 0x47, - 0x9e, 0x17, 0x56, 0x94, 0xf7, 0xb2, 0x6c, 0x97, 0x45, 0x16, 0xea, 0xa0, - 0xe4, 0xb4, 0x84, 0xf0, 0xda, 0xb6, 0x3a, 0xb6, 0xee, 0x1d, 0x5f, 0x87, - 0x0d, 0xa4, 0x13, 0x19, 0xa3, 0x4b, 0x27, 0x4c, 0xec, 0x9e, 0x66, 0x2b, - 0x6f, 0x91, 0x85, 0x22, 0xee, 0x2e, 0x55, 0xa2, 0xe5, 0x52, 0x09, 0x78, - 0x05, 0x39, 0x32, 0x27, 0xda, 0x7c, 0xe2, 0xcc, 0x78, 0x40, 0xfc, 0x11, - 0xab, 0x95, 0xbc, 0xb6, 0x3f, 0x26, 0x90, 0x15, 0xcb, 0x59, 0xd5, 0x10, - 0x36, 0xeb, 0x03, 0x25, 0x8e, 0x46, 0xcf, 0x63, 0x1d, 0x34, 0x76, 0xda, - 0x61, 0xef, 0xfd, 0x86, 0x66, 0x7a, 0x23, 0x9a, 0xff, 0xcb, 0xe1, 0x61, - 0xc7, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x64, 0x6b, 0x75, 0xd3, 0x13, 0xc6, - 0x7f, 0x6c, 0x2b, 0xef, 0x9b, 0xbf, 0x66, 0x14, 0xe8, 0x6f, 0xb2, 0xaf, - 0xf4, 0x61, 0x91, 0x3f, 0x7b, 0xf7, 0x9b, 0xb5, 0x34, 0x6b, 0x8f, 0xca, - 0xcf, 0x32, 0x6c, 0xe0, 0xb4, 0xea, 0x51, 0xff, 0x01, 0x8b, 0xd7, 0x80, - 0x95, 0x46, 0xb9, 0xbc, 0xe3, 0x92, 0x52, 0x3b, 0xec, 0x63, 0xc3, 0x6e, - 0x34, 0xef, 0xc7, 0xb1, 0x52, 0x41, 0x87, 0x21, 0xa5, 0xf1, 0xe5, 0x37, - 0xc5, 0x7c, 0x9d, 0xa3, 0x14, 0xb8, 0xee, 0x35, 0x63, 0xed, 0x00, 0xce, - 0x91, 0xf8, 0xc7, 0x88, 0x41, 0xf6, 0xbf, 0x5a, 0x6c, 0x73, 0xca, 0x0b, - 0x1a, 0xde, 0x7e, 0x49, 0x7c, 0xc1, 0xe8, 0xeb, 0xe3, 0xba, 0xf2, 0x8a, - 0x98, 0xce, 0x19, 0x98, 0xdb, 0x62, 0x03, 0x15, 0x08, 0x33, 0x83, 0x77, - 0x3f, 0x7c, 0xc8, 0x27, 0xef, 0x2d, 0x4b, 0x4b, 0x7f, 0x80, 0xfc, 0x12, - 0x41, 0x4b, 0x89, 0x88, 0x32, 0x19, 0xaa, 0xf4, 0xff, 0x39, 0x61, 0xc9, - 0x06, 0xfd, 0x78, 0x79, 0xc0, 0x52, 0x7e, 0xe6, 0x79, 0x7d, 0x50, 0x43, - 0xb3, 0xf2, 0x86, 0xb2, 0xf3, 0x38, 0x35, 0x72, 0xbf, 0xb7, 0x35, 0x45, - 0x34, 0xb3, 0x05, 0x67, 0x3e, 0xb7, 0x71, 0x5e, 0x55, 0x36, 0xc7, 0xbf, - 0x3b, 0x6d, 0xc3, 0xf9, 0x9c, 0x94, 0x4f, 0x63, 0x3e, 0x34, 0x44, 0x9e, - 0x5f, 0x2b, 0x65, 0xc2, 0xeb, 0x5b, 0x5c, 0x61, 0x20, 0x6a, 0x3e, 0xb5, - 0x38, 0xf0, 0x5b, 0xde, 0x45, 0xa7, 0x1f, 0xa7, 0xad, 0xd0, 0xb5, 0x0d, - 0x2d, 0x15, 0x9f, 0x7c, 0x62, 0x7a, 0xf1, 0x2a, 0xb8, 0x6c, 0xeb, 0x0f, - 0xd5, 0x84, 0xa9, 0xfa, 0x5f, 0xc6, 0x39, 0x66, 0xd7, 0xaa, 0x8c, 0x4b, - 0xbe, 0xaf, 0x26, 0xc1, 0x7b, 0xbb, 0xbb, 0x45, 0xa9, 0x58, 0xb7, 0x62, - 0x6b, 0x96, 0x3a, 0xe9, 0xb0, 0x87, 0x1b, 0x5d, 0x8b, 0x77, 0xe0, 0xcc, - 0x9c, 0xad, 0x3b, 0xfb, 0xe9, 0x53, 0x85, 0x1c, 0xae, 0xf8, 0x70, 0x06, - 0x66, 0x88, 0x30, 0x12, 0x44, 0xa5, 0x31, 0xd8, 0x23, 0xdc, 0x4f, 0x80, - 0x36, 0x02, 0x9c, 0x9e, 0x36, 0x09, 0x70, 0xd5, 0xa4, 0x41, 0xa6, 0x48, - 0xfd, 0xd3, 0x39, 0x19, 0xa0, 0x43, 0x7e, 0x8d, 0xe9, 0x41, 0x3b, 0x1b, - 0x58, 0x6b, 0xb0, 0xe2, 0x28, 0x21, 0x21, 0xe3, 0x6d, 0xa1, 0x84, 0x29, - 0x1e, 0xcf, 0x5f, 0xeb, 0x81, 0xf9, 0xc6, 0x07, 0x09, 0xc9, 0xe1, 0x6d, - 0x53, 0x47, 0x59, 0xf7, 0x14, 0x23, 0x5d, 0x39, 0x12, 0x4b, 0xbe, 0x7e, - 0x28, 0xb9, 0x9c, 0x23 -}; -unsigned int brighton_keychain_2_db_len = 126976; - diff --git a/sec/securityd/Regressions/sd-70-engine.c b/sec/securityd/Regressions/sd-70-engine.c deleted file mode 100644 index eb9463c6..00000000 --- a/sec/securityd/Regressions/sd-70-engine.c +++ /dev/null @@ -1,383 +0,0 @@ -// -// sd-70-engine.c -// sec -// -// Created by Michael Brouwer on 11/9/12. -// Copyright 2012 Apple Inc. All rights reserved. -// -// - -// Test syncing between SecItemDataSource and SOSTestDataSource - -#include -#include - -#include "securityd_regressions.h" - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include "SOSTestDataSource.h" -#include "SOSTestTransport.h" - -#include - -static int kTestTestCount = 74; - -// TODO: Make this shared. -static CFStringRef SOSMessageCopyDigestHex(CFDataRef message) { - uint8_t digest[CCSHA1_OUTPUT_SIZE]; - ccdigest(ccsha1_di(), CFDataGetLength(message), CFDataGetBytePtr(message), digest); - CFMutableStringRef hex = CFStringCreateMutable(0, 2 * sizeof(digest)); - for (unsigned int ix = 0; ix < sizeof(digest); ++ix) { - CFStringAppendFormat(hex, 0, CFSTR("%02X"), digest[ix]); - } - return hex; -} - -static void testsync(const char *name, const char *test_directive, const char *test_reason, void (^aliceInit)(SOSDataSourceRef ds), void (^bobInit)(SOSDataSourceRef ds), CFStringRef msg, ...) { - CFErrorRef error = NULL; - - /* Setup Alice and Bob's dataSources. */ - SOSDataSourceFactoryRef aliceDataSourceFactory = SecItemDataSourceFactoryCreateDefault(); - SOSDataSourceRef aliceDataSource = NULL; - CFArrayRef ds_names = aliceDataSourceFactory->copy_names(aliceDataSourceFactory); - if (ds_names && CFArrayGetCount(ds_names) > 0) { - CFStringRef name = CFArrayGetValueAtIndex(ds_names, 0); - ok (aliceDataSource = aliceDataSourceFactory->create_datasource(aliceDataSourceFactory, name, false, &error), "create datasource \"%@\" [error: %@]", name, error); - CFReleaseNull(error); - } - CFReleaseNull(ds_names); - - SOSDataSourceRef bobDataSource = SOSTestDataSourceCreate(); - - /* Setup Alice engine and peer for Alice to talk to Bob */ - SOSEngineRef aliceEngine; - ok(aliceEngine = SOSEngineCreate(aliceDataSource, &error), "create alice engine: %@", error); - CFReleaseNull(error); - CFStringRef bobID = CFStringCreateWithFormat(kCFAllocatorDefault, 0, CFSTR("Bob-%s"), name); - - __block CFDataRef queued_message = NULL; - - SOSPeerSendBlock enqueueMessage = ^bool (CFDataRef message, CFErrorRef *error) { - if (queued_message) - fail("We already had an unproccessed message"); - - queued_message = (CFDataRef) CFRetain(message); - return true; - }; - - CFDataRef (^dequeueMessage)() = ^CFDataRef () { - CFDataRef result = queued_message; - queued_message = NULL; - - return result; - }; - - SOSPeerRef bobPeer; - ok(bobPeer = SOSPeerCreateSimple(bobID, kSOSPeerVersion, &error, enqueueMessage), - "create peer: %@", error); - - /* Setup Bob engine and peer for Bob to talk to Alice */ - SOSEngineRef bobEngine; - ok(bobEngine = SOSEngineCreate(bobDataSource, &error), "create bob engine: %@", error); - CFReleaseNull(error); - CFStringRef aliceID = CFStringCreateWithFormat(kCFAllocatorDefault, 0, CFSTR("Alice-%s"), name); - - SOSPeerRef alicePeer; - ok(alicePeer = SOSPeerCreateSimple(aliceID, kSOSPeerVersion, &error, enqueueMessage), - "create peer: %@", error); - CFReleaseNull(error); - - /* Now call provided setup blocks to populate the dataSources with - interesting stuff. */ - aliceInit(aliceDataSource); - bobInit(bobDataSource); - - /* Start syncing by making alice send the first message. */ - ok(SOSEngineSyncWithPeer(aliceEngine, bobPeer, false, &error), "tell Alice sync with peer Bob"); - CFDataRef message; - - va_list msgs; - va_start(msgs, msg); - - int msg_index = 0; - bool alice = false; - for (;;) { - message = dequeueMessage(); - msg_index++; - /* We are expecting a message and msg is it's digest. */ - if (message) { - CFStringRef messageDesc = SOSMessageCopyDescription(message); - CFStringRef messageDigestStr = SOSMessageCopyDigestHex(message); - if (msg) { - bool handeled = SOSEngineHandleMessage(alice ? aliceEngine : bobEngine, alice ? bobPeer : alicePeer, message, &error); - if (!CFEqual(messageDigestStr, msg)) { - if (handeled) { - fail("%s %s received message [%d] digest %@ != %@ %@", name, alice ? "Alice" : "Bob", msg_index, messageDigestStr, msg, messageDesc); - } else { - fail("%s %s failed to handle message [%d] digest %@ != %@ %@: %@", name, alice ? "Alice" : "Bob", msg_index, messageDigestStr, msg, messageDesc, error); - CFReleaseNull(error); - } - } else if (handeled) { - pass("%s %s handled message [%d] %@", name, alice ? "Alice" : "Bob", msg_index, messageDesc); - } else { - fail("%s %s failed to handle message [%d] %@: %@", name, alice ? "Alice" : "Bob", msg_index, messageDesc, error); - CFReleaseNull(error); - } - } else { - fail("%s %s sent extra message [%d] with digest %@: %@", name, alice ? "Bob" : "Alice", msg_index, messageDigestStr, messageDesc); - } - CFRelease(messageDigestStr); - CFRelease(messageDesc); - CFRelease(message); - } else { - if (msg) { - fail("%s %s expected message [%d] with digest %@, none received", name, alice ? "Alice" : "Bob", msg_index, msg); - } - } - - if (msg) { - alice = !alice; - msg = va_arg(msgs, CFStringRef); - } else - break; - } - - va_end(msgs); - - SOSEngineDispose(aliceEngine); // Also disposes aliceDataSource - SOSPeerDispose(alicePeer); - CFReleaseSafe(aliceID); - - SOSEngineDispose(bobEngine); // Also disposes bobDataSource - SOSPeerDispose(bobPeer); - CFReleaseSafe(bobID); - - aliceDataSourceFactory->release(aliceDataSourceFactory); -} - - -static SOSObjectRef SOSDataSourceCopyObject(SOSDataSourceRef ds, SOSObjectRef match, CFErrorRef *error) -{ - __block SOSObjectRef result = NULL; - - CFDataRef digest = ds->copyDigest(match, error); - SOSManifestRef manifest = NULL; - - require(digest, exit); - - manifest = SOSManifestCreateWithData(digest, error); - - ds->foreach_object(ds, manifest, error, ^ bool (SOSObjectRef object, CFErrorRef *error) { - if (result == NULL) { - result = object; - CFRetainSafe(result); - } - - return true; - }); - -exit: - CFReleaseNull(manifest); - CFReleaseNull(digest); - return result; -} - -static void synctests(void) { -#if 0 - // TODO: Adding items gives us non predictable creation and mod dates so - // the message hashes can't be precomputed. - CFDictionaryRef item = CFDictionaryCreateForCFTypes - (0, - kSecClass, kSecClassGenericPassword, - kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked, - kSecAttrSynchronizable, kCFBooleanTrue, - kSecAttrService, CFSTR("service"), - kSecAttrAccount, CFSTR("account"), - NULL); - SecItemAdd(item, NULL); - CFReleaseSafe(item); -#endif - -SKIP: - { - -#ifdef NO_SERVER - // Careful with this in !NO_SERVER, it'll destroy debug keychains. - WithPathInKeychainDirectory(CFSTR("keychain-2-debug.db"), ^(const char *keychain_path) { - unlink(keychain_path); - }); - - // Don't ever do this in !NO_SERVER, it'll destroy real keychains. - WithPathInKeychainDirectory(CFSTR("keychain-2.db"), ^(const char *keychain_path) { - unlink(keychain_path); - }); - - void kc_dbhandle_reset(void); - kc_dbhandle_reset(); -#else - skip("Keychain not reset", kTestTestCount, false); -#endif - - // Sync between 2 empty dataSources - testsync("sd_70_engine", test_directive, test_reason, - ^ (SOSDataSourceRef dataSource) {}, - ^ (SOSDataSourceRef dataSource) {}, - CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), - CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), - CFSTR("2AF312E092D67308A0083DFFBF2B6B754B967864"), - NULL); - - // Sync a dataSource with one object to an empty dataSource - testsync("sd_70_engine-alice1", test_directive, test_reason, - ^ (SOSDataSourceRef dataSource) { - CFErrorRef error = NULL; - SOSObjectRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); - // TODO: Needs to be a SecDBItemRef for the SecItemDataSource... - ok(dataSource->add(dataSource, object, &error), "dataSource added object %@", error); - CFReleaseSafe(object); - CFReleaseNull(error); - }, - ^ (SOSDataSourceRef dataSource) {}, - CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), - CFSTR("147B6C509908CC4A9FC4263973A842104A64CE01"), - CFSTR("019B494F3C06B48BB02C280AF1E19AD861A7003C"), - CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), - NULL); - - // Sync a dataSource with one object to another dataSource with the same object - testsync("sd_70_engine-alice1bob1", test_directive, test_reason, - ^ (SOSDataSourceRef dataSource) { -#if 0 - CFErrorRef error = NULL; - // TODO: Needs to be a SecDBItemRef for the SecItemDataSource... - CFDictionaryRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); - ok(dataSource->add(dataSource, object, &error), "dataSource added object %@", error); - CFReleaseSafe(object); - CFReleaseNull(error); -#endif - }, - ^ (SOSDataSourceRef dataSource) { - CFErrorRef error = NULL; - SOSObjectRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); - ok(dataSource->add(dataSource, object, &error), "dataSource added object %@", error); - CFReleaseSafe(object); - CFReleaseNull(error); - }, - CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), - CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), - CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), - NULL); - - // Sync a dataSource with one object to another dataSource with the same object - testsync("sd_70_engine-alice1bob2", test_directive, test_reason, - ^ (SOSDataSourceRef dataSource) { -#if 0 - CFErrorRef error = NULL; - // TODO: Needs to be a SecDBItemRef for the SecItemDataSource... - SOSObjectRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); - ok(dataSource->add(dataSource, object, &error), "dataSource added object %@", error); - CFReleaseSafe(object); - CFReleaseNull(error); -#endif - }, - ^ (SOSDataSourceRef dataSource) { - CFErrorRef error = NULL; - SOSObjectRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); - ok(dataSource->add(dataSource, object, &error), "dataSource added object %@", error); - CFReleaseSafe(object); - object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("account1"), CFSTR("service1")); - ok(dataSource->add(dataSource, object, &error), "dataSource added object %@", error); - CFReleaseSafe(object); - CFReleaseNull(error); - }, - CFSTR("ADAA3ACE75ED516CB91893413EE9CC9ED04CA47B"), - CFSTR("D4049A1063CFBF7CAF8424E13DE3CE926FF5856C"), - CFSTR("9624EA855BBED6B668868BB723443E804D04F6A1"), - CFSTR("063E097CCD4FEB7F3610ED12B3DA828467314846"), - CFSTR("D1B3944E3084425F41B2C2EA0BE82170E10AA37D"), - NULL); - - // Sync a dataSource with a tombstone object to another dataSource with the same object - TODO: { - todo(" Test case in sd-70-engine fails due to need for RowID"); - testsync("sd_70_engine-update", test_directive, test_reason, - ^ (SOSDataSourceRef dataSource) { - CFErrorRef error = NULL; - const char *password = "password1"; - CFDataRef data = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)password, strlen(password)); - // TODO: Needs to be a SecDBItemRef for the SecItemDataSource... - SOSObjectRef object_to_find = SOSDataSourceCreateGenericItemWithData(dataSource, CFSTR("test_account"), CFSTR("test service"), true, NULL); - SOSObjectRef object = SOSDataSourceCopyObject(dataSource, object_to_find, &error); - SOSObjectRef old_object = NULL; - SKIP: { - skip("no object", 1, ok(object, "Finding object %@, error: %@", object_to_find, error)); - CFReleaseNull(data); - // TODO: Needs to be a SecDBItemRef for the SecItemDataSource... - old_object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); - ok(dataSource->add(dataSource, object, &error), "dataSource update object %@", error); - } - CFReleaseSafe(data); - CFReleaseSafe(old_object); - CFReleaseSafe(object); - CFReleaseNull(error); - }, - ^ (SOSDataSourceRef dataSource) { - CFErrorRef error = NULL; - SOSObjectRef object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("test_account"), CFSTR("test service")); - ok(dataSource->add(dataSource, object, &error), "dataSource added object %@", error); - CFReleaseSafe(object); - object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("account1"), CFSTR("service1")); - ok(dataSource->add(dataSource, object, &error), "dataSource added object %@", error); - CFReleaseSafe(object); - CFReleaseNull(error); - }, - CFSTR("5D07A221A152D6D6C5F1919189F259A7278A08C5"), - CFSTR("D4049A1063CFBF7CAF8424E13DE3CE926FF5856C"), - CFSTR("137FD34E9BF11B4BA0620E8EBFAB8576BCCCF294"), - CFSTR("5D07A221A152D6D6C5F1919189F259A7278A08C5"), - NULL); - } - - // Sync a dataSource with one object to another dataSource with the same object - testsync("sd_70_engine-foreign-add", test_directive, test_reason, - ^ (SOSDataSourceRef dataSource) { - }, - ^ (SOSDataSourceRef dataSource) { - CFErrorRef error = NULL; - const char *password = "password1"; - CFDataRef data = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)password, strlen(password)); - SOSObjectRef object = SOSDataSourceCreateGenericItemWithData(dataSource, CFSTR("test_account"), CFSTR("test service"), false, data); - CFReleaseSafe(data); - ok(dataSource->add(dataSource, object, &error), "dataSource added object %@", error); - CFReleaseSafe(object); - CFReleaseNull(error); - object = SOSDataSourceCreateGenericItem(dataSource, CFSTR("account1"), CFSTR("service1")); - ok(dataSource->add(dataSource, object, &error), "dataSource added object %@", error); - CFReleaseSafe(object); - CFReleaseNull(error); - }, - CFSTR("D1B3944E3084425F41B2C2EA0BE82170E10AA37D"), - CFSTR("607EEF976943FD781CFD2B3850E6DC7979AA61EF"), - CFSTR("28434CD1B90CC205460557CAC03D7F12067F2329"), - CFSTR("D1B3944E3084425F41B2C2EA0BE82170E10AA37D"), - NULL); - } -} - -int sd_70_engine(int argc, char *const *argv) -{ - plan_tests(kTestTestCount); - - synctests(); - - return 0; -} diff --git a/sec/securityd/Regressions/secd-31-keychain-unreadable.c b/sec/securityd/Regressions/secd-31-keychain-unreadable.c deleted file mode 100644 index 95b2f9df..00000000 --- a/sec/securityd/Regressions/secd-31-keychain-unreadable.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * secd-31-keychain-unreadable.c - * Security - * - * Created by Michael Brouwer on 5/23/08. - * Copyright (c) 2008-2010,2013 Apple Inc. All Rights Reserved. - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "secd_regressions.h" - -#include - -#include "SecdTestKeychainUtilities.h" - - -/* Create an empty keychain file that can't be read or written and make sure - securityd can deal with it. */ -static void tests(void) -{ - /* custom keychain dir */ - secd_test_setup_temp_keychain("secd_31_keychain_unreadable", ^{ - CFStringRef keychain_path_cf = __SecKeychainCopyPath(); - - CFStringPerformWithCString(keychain_path_cf, ^(const char *keychain_path) { - int fd; - ok_unix(fd = open(keychain_path, O_RDWR | O_CREAT | O_TRUNC, 0644), - "create keychain file '%s'", keychain_path); - ok_unix(fchmod(fd, 0), " keychain file '%s'", keychain_path); - ok_unix(close(fd), "close keychain file '%s'", keychain_path); - - }); - - CFReleaseSafe(keychain_path_cf); - }); - - int v_eighty = 80; - CFNumberRef eighty = CFNumberCreate(NULL, kCFNumberSInt32Type, &v_eighty); - 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("members.spamcop.net")); - CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("smith")); - CFDictionaryAddValue(query, kSecAttrPort, eighty); - CFDictionaryAddValue(query, kSecAttrProtocol, kSecAttrProtocolHTTP); - CFDictionaryAddValue(query, kSecAttrAuthenticationType, kSecAttrAuthenticationTypeDefault); - CFDictionaryAddValue(query, kSecValueData, pwdata); - ok_status(SecItemAdd(query, NULL), "add internet password"); - is_status(SecItemAdd(query, NULL), errSecDuplicateItem, - "add internet password again"); - - ok_status(SecItemCopyMatching(query, NULL), "Found the item we added"); - - ok_status(SecItemDelete(query),"Deleted the item we added"); - - CFReleaseSafe(eighty); - CFReleaseSafe(pwdata); - CFReleaseSafe(query); -} - -int secd_31_keychain_unreadable(int argc, char *const *argv) -{ - plan_tests(7 + kSecdTestSetupTestCount); - tests(); - - return 0; -} diff --git a/sec/securityd/Regressions/secd-50-account.c b/sec/securityd/Regressions/secd-50-account.c deleted file mode 100644 index d9216eed..00000000 --- a/sec/securityd/Regressions/secd-50-account.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * secd_50_account.c - * - * Created by Mitch Adler on 1/25/121. - * Copyright 2012 Apple Inc. All rights reserved. - * - */ - - -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include "secd_regressions.h" -#include "SOSTestDataSource.h" - -#include "SOSRegressionUtilities.h" -#include - -#include - -#include "SecdTestKeychainUtilities.h" - -static int kTestTestCount = 10 + kSecdTestSetupTestCount; -static void tests(void) -{ - secd_test_setup_temp_keychain("secd_50_account", ^{ - }); - - CFErrorRef error = NULL; - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - CFStringRef cfaccount = CFSTR("test@test.org"); - - SOSAccountKeyInterestBlock interest_block = ^(bool getNewKeysOnly, CFArrayRef alwaysKeys, CFArrayRef afterFirstUnlockKeys, CFArrayRef unlockedKeys) {}; - SOSAccountDataUpdateBlock update_block = ^ bool (CFDictionaryRef keys, CFErrorRef *error) {return true;}; - - SOSDataSourceFactoryRef test_factory = SOSTestDataSourceFactoryCreate(); - SOSDataSourceRef test_source = SOSTestDataSourceCreate(); - SOSTestDataSourceFactoryAddDataSource(test_factory, CFSTR("TestType"), test_source); - - CFDictionaryRef gestalt = SOSCreatePeerGestaltFromName(CFSTR("Test Device")); - SOSAccountRef account = SOSAccountCreate(kCFAllocatorDefault, gestalt, test_factory, interest_block, update_block); - ok(SOSAccountAssertUserCredentials(account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - CFReleaseNull(cfpassword); - - ok(NULL != account, "Created"); - - ok(1 == SOSAccountCountCircles(account), "Has one circle"); - - size_t size = SOSAccountGetDEREncodedSize(account, &error); - CFReleaseNull(error); - uint8_t buffer[size]; - uint8_t* start = SOSAccountEncodeToDER(account, &error, buffer, buffer + sizeof(buffer)); - CFReleaseNull(error); - - ok(start, "successful encoding"); - ok(start == buffer, "Used whole buffer"); - - const uint8_t *der = buffer; - SOSAccountRef inflated = SOSAccountCreateFromDER(kCFAllocatorDefault, test_factory, interest_block, update_block, - &error, &der, buffer + sizeof(buffer)); - - ok(inflated, "inflated"); - ok(CFEqual(inflated, account), "Compares"); - - CFDictionaryRef new_gestalt = SOSCreatePeerGestaltFromName(CFSTR("New Device")); - - ok(SOSAccountResetToOffering(account, &error), "Reset to Offering (%@)", error); - CFReleaseNull(error); - - is(SOSAccountIsInCircles(account, &error), kSOSCCInCircle, "Was in Circle (%@)", error); - CFReleaseNull(error); - - SOSAccountUpdateGestalt(account, new_gestalt); - - is(SOSAccountIsInCircles(account, &error), kSOSCCInCircle, "Still in Circle (%@)", error); - CFReleaseNull(error); - - CFReleaseNull(gestalt); - CFReleaseNull(new_gestalt); - CFReleaseNull(account); -} - -int secd_50_account(int argc, char *const *argv) -{ - plan_tests(kTestTestCount); - - tests(); - - return 0; -} diff --git a/sec/securityd/Regressions/secd-52-account-changed.c b/sec/securityd/Regressions/secd-52-account-changed.c deleted file mode 100644 index 8972233f..00000000 --- a/sec/securityd/Regressions/secd-52-account-changed.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * secd_52_account_changed.c - * - * Created by Richard Murphy on 09152013. - * Copyright 2013 Apple Inc. All rights reserved. - * - */ - - -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include "secd_regressions.h" -#include "SOSTestDataSource.h" - -#include "SOSRegressionUtilities.h" -#include - -#include - -#include "SecdTestKeychainUtilities.h" -#include "SOSAccountTesting.h" - - -static int kTestTestCount = 133; - - -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(changes, CFSTR("Alice"), CFSTR("TestSource")); - SOSAccountRef bob_account = CreateAccountForLocalChanges(changes, CFSTR("Bob"), CFSTR("TestSource")); - SOSAccountRef carol_account = CreateAccountForLocalChanges(changes, CFSTR("Carol"), CFSTR("TestSource")); - - ok(SOSAccountAssertUserCredentials(bob_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - - // Bob wins writing at this point, feed the changes back to alice. - - FeedChangesToMulti(changes, alice_account, carol_account, NULL); - - ok(SOSAccountAssertUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - ok(SOSAccountAssertUserCredentials(carol_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - CFReleaseNull(cfpassword); - - /* ==================== Three Accounts setup =============================================*/ - - ok(SOSAccountResetToOffering(alice_account, &error), "Reset to offering (%@)", error); - CFReleaseNull(error); - - FeedChangesToMulti(changes, bob_account, carol_account, NULL); - - ok(SOSAccountJoinCircles(bob_account, &error), "Bob Applies (%@)", error); - CFReleaseNull(error); - - FeedChangesToMulti(changes, alice_account, carol_account, bob_account, NULL); - - ok(SOSAccountJoinCircles(carol_account, &error), "Carol Applies (%@)", error); - CFReleaseNull(error); - - FeedChangesToMulti(changes, alice_account, carol_account, bob_account, NULL); - - { - CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); - - ok(applicants && CFArrayGetCount(applicants) == 2, "See two applicants %@ (%@)", applicants, error); - ok(SOSAccountAcceptApplicants(alice_account, applicants, &error), "Alice accepts (%@)", error); - CFReleaseNull(error); - CFReleaseNull(applicants); - } - - FeedChangesToMulti(changes, bob_account, NULL); // let bob concurr - FeedChangesToMulti(changes, alice_account, carol_account, NULL); // let carol concurr - FeedChangesToMulti(changes, alice_account, bob_account, carol_account, NULL); // all synced - FeedChangesToMulti(changes, alice_account, bob_account, carol_account, NULL); // all synced - FeedChangesToMulti(changes, alice_account, bob_account, carol_account, NULL); // all synced - - ok(CFDictionaryGetCount(changes) == 0, "We converged. (%@)", changes); - - accounts_agree_internal("bob&alice pair", bob_account, alice_account, false); - accounts_agree_internal("bob&carol pair", bob_account, carol_account, false); - /* ==================== Three Accounts in circle =============================================*/ - InjectChangeToMulti(CFSTR("^AccountChanged"), CFSTR("none"), alice_account, bob_account, carol_account, NULL); - - is(SOSAccountIsInCircles(alice_account, &error), kSOSCCError, "Account reset - no user keys - error"); - is(SOSAccountIsInCircles(bob_account, &error), kSOSCCError, "Account reset - no user keys - error"); - is(SOSAccountIsInCircles(carol_account, &error), kSOSCCError, "Account reset - no user keys - error"); - - CFDataRef cfpassword2 = CFDataCreate(NULL, (uint8_t *) "ooFooFooF", 10); - CFStringRef cfaccount2 = CFSTR("test2@test.org"); - - ok(SOSAccountAssertUserCredentials(alice_account, cfaccount2, cfpassword2, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - - is(SOSAccountIsInCircles(alice_account, &error), kSOSCCCircleAbsent, "Account reset - circle is absent"); - is(SOSAccountIsInCircles(bob_account, &error), kSOSCCError, "Account reset - no user keys - error"); - FeedChangesToMulti(changes, bob_account, carol_account, NULL); - - ok(SOSAccountAssertUserCredentials(bob_account, cfaccount2, cfpassword2, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - - ok(SOSAccountAssertUserCredentials(carol_account, cfaccount2, cfpassword2, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - - is(SOSAccountIsInCircles(bob_account, &error), kSOSCCCircleAbsent, "Account reset - circle is absent"); - is(SOSAccountIsInCircles(carol_account, &error), kSOSCCCircleAbsent, "Account reset - circle is absent"); - // Now everyone is playing the same account. - - /* ==================== Three Accounts setup =============================================*/ - - ok(SOSAccountResetToOffering(alice_account, &error), "Reset to offering (%@)", error); - CFReleaseNull(error); - is(countActivePeers(alice_account), 2, "2 peers - alice and icloud"); - - FeedChangesToMulti(changes, bob_account, carol_account, NULL); - is(SOSAccountIsInCircles(alice_account, &error), kSOSCCInCircle, "Alice is in circle"); - is(SOSAccountIsInCircles(bob_account, &error), kSOSCCNotInCircle, "Bob is not in circle"); - is(SOSAccountIsInCircles(carol_account, &error), kSOSCCNotInCircle, "Carol is not in circle"); - - ok(SOSAccountJoinCircles(bob_account, &error), "Bob Applies (%@)", error); - CFReleaseNull(error); - - FeedChangesToMulti(changes, alice_account, carol_account, bob_account, NULL); - is(SOSAccountIsInCircles(bob_account, &error), kSOSCCRequestPending, "Bob has a pending request"); - - ok(SOSAccountJoinCircles(carol_account, &error), "Carol Applies (%@)", error); - CFReleaseNull(error); - - FeedChangesToMulti(changes, alice_account, carol_account, bob_account, NULL); - is(SOSAccountIsInCircles(carol_account, &error), kSOSCCRequestPending, "Carol has a pending request"); - - { - CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); - - ok(applicants && CFArrayGetCount(applicants) == 2, "See two applicants %@ (%@)", applicants, error); - ok(SOSAccountAcceptApplicants(alice_account, applicants, &error), "Alice accepts (%@)", error); - CFReleaseNull(error); - CFReleaseNull(applicants); - is(countActivePeers(alice_account), 4, "4 peers - alice, bob, carol, and icloud"); - } - - FeedChangesToMulti(changes, bob_account, NULL); // let bob concurr - is(SOSAccountIsInCircles(bob_account, &error), kSOSCCInCircle, "Bob is in circle"); - FeedChangesToMulti(changes, alice_account, carol_account, NULL); // let carol concurr - is(SOSAccountIsInCircles(carol_account, &error), kSOSCCInCircle, "Carol is in circle"); - FeedChangesToMulti(changes, alice_account, bob_account, carol_account, NULL); // all synced - FeedChangesToMulti(changes, alice_account, bob_account, carol_account, NULL); // all synced - FeedChangesToMulti(changes, alice_account, bob_account, carol_account, NULL); // all synced - - ok(CFDictionaryGetCount(changes) == 0, "We converged. (%@)", changes); - - accounts_agree_internal("bob&alice pair", bob_account, alice_account, false); - accounts_agree_internal("bob&carol pair", bob_account, carol_account, false); - -} - - -int secd_52_account_changed(int argc, char *const *argv) -{ - plan_tests(kTestTestCount); - - tests(); - - return 0; -} diff --git a/sec/securityd/Regressions/secd-55-account-circle.c b/sec/securityd/Regressions/secd-55-account-circle.c deleted file mode 100644 index 271a8f15..00000000 --- a/sec/securityd/Regressions/secd-55-account-circle.c +++ /dev/null @@ -1,300 +0,0 @@ -// -// secd-55-account-circle.c -// sec -// -// Created by Mitch Adler on 1/25/12. -// -// - - - -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include - -#include "secd_regressions.h" -#include "SOSTestDataSource.h" - -#include "SOSRegressionUtilities.h" -#include -#include - -#include - -#include "SOSAccountTesting.h" - - -static int kTestTestCount = 202; - -static void tests(void) -{ - CFErrorRef error = NULL; - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - CFDataRef cfwrong_password = CFDataCreate(NULL, (uint8_t *) "NotFooFooFoo", 10); - CFStringRef cfaccount = CFSTR("test@test.org"); - - CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - - SOSAccountRef alice_account = CreateAccountForLocalChanges(changes, CFSTR("Alice"), CFSTR("TestSource")); - SOSAccountRef bob_account = CreateAccountForLocalChanges(changes, CFSTR("Bob"), CFSTR("TestSource")); - SOSAccountRef carol_account = CreateAccountForLocalChanges(changes, CFSTR("Carol"), CFSTR("TestSource")); - - ok(SOSAccountAssertUserCredentials(bob_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - - // Bob wins writing at this point, feed the changes back to alice. - - FeedChangesToMulti(changes, alice_account, carol_account, NULL); - - ok(SOSAccountAssertUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - ok(SOSAccountTryUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential trying (%@)", error); - CFReleaseNull(error); - ok(!SOSAccountTryUserCredentials(alice_account, cfaccount, cfwrong_password, &error), "Credential failing (%@)", error); - CFReleaseNull(cfwrong_password); - is(error ? CFErrorGetCode(error) : 0, kSOSErrorWrongPassword, "Expected SOSErrorWrongPassword"); - CFReleaseNull(error); - - ok(SOSAccountResetToOffering(alice_account, &error), "Reset to offering (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, bob_account); - - ok(SOSAccountJoinCircles(bob_account, &error), "Bob Applies (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, alice_account); - - { - 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); - } - - - FeedChangesTo(changes, bob_account); // Bob sees he's accepted - - FeedChangesTo(changes, alice_account); // Alice sees bob-concurring - - ok(CFDictionaryGetCount(changes) == 0, "We converged. (%@)", changes); - - accounts_agree("bob&alice pair", bob_account, alice_account); - - CFArrayRef peers = SOSAccountCopyPeers(alice_account, &error); - ok(peers && CFArrayGetCount(peers) == 2, "See two peers %@ (%@)", peers, error); - CFReleaseNull(peers); - - CFDictionaryRef alice_new_gestalt = SOSCreatePeerGestaltFromName(CFSTR("Alice, but different")); - - ok(SOSAccountUpdateGestalt(alice_account, alice_new_gestalt), "Update gestalt %@ (%@)", alice_account, error); - CFReleaseNull(alice_new_gestalt); - - FeedChangesTo(changes, bob_account); // Bob sees alice change her name. - - FeedChangesTo(changes, alice_account); // Alice sees the fallout. - - accounts_agree("Alice's name changed", bob_account, alice_account); - - ok(SOSAccountLeaveCircles(alice_account, &error), "Alice Leaves (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, bob_account); // Bob sees alice bail. - - FeedChangesTo(changes, alice_account); // Alice sees the fallout. - - accounts_agree("Alice bails", bob_account, alice_account); - - peers = SOSAccountCopyPeers(alice_account, &error); - ok(peers && CFArrayGetCount(peers) == 1, "See one peer %@ (%@)", peers, error); - CFReleaseNull(peers); - - ok(SOSAccountJoinCircles(alice_account, &error), "Alice re-applies (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, bob_account); - - - { - CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); - - ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); - ok(SOSAccountAcceptApplicants(bob_account, applicants, &error), "Bob accepts (%@)", error); - CFReleaseNull(error); - CFReleaseNull(applicants); - } - - FeedChangesTo(changes, alice_account); // Alice sees bob accepting - - FeedChangesTo(changes, bob_account); // Bob sees Alice concurring - - accounts_agree("Alice accepts' Bob", bob_account, alice_account); - - ok(SOSAccountLeaveCircles(alice_account, &error), "Alice Leaves (%@)", error); - CFReleaseNull(error); - ok(SOSAccountJoinCircles(alice_account, &error), "Alice re-applies (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, bob_account); // Bob sees Alice leaving and rejoining - FeedChangesTo(changes, alice_account); // Alice sees bob concurring - - { - CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); - - ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); - ok(SOSAccountAcceptApplicants(bob_account, applicants, &error), "Bob accepts (%@)", error); - CFReleaseNull(error); - CFReleaseNull(applicants); - } - - FeedChangesTo(changes, alice_account); // Alice sees bob accepting - - FeedChangesTo(changes, bob_account); // Bob sees Alice concurring - - accounts_agree("Bob accepts Alice", bob_account, alice_account); - - // As of PR-13917727/PR-13906870 this no longer works (by "design"), in favor of making another more common - // failure (apply/OSX-psudo-reject/re-apply) work. Write races might be "fixed better" with affirmitave rejection. -#if 0 - - // - // Write race emulation. - // - // - - ok(SOSAccountLeaveCircles(alice_account, &error), "Alice Leaves (%@)", error); - CFReleaseNull(error); - FeedChangesTo(changes, bob_account); // Bob sees Alice leaving and rejoining - FeedChangesTo(changes, alice_account); // Alice sees bob concurring - - accounts_agree("Alice leaves & returns", bob_account, alice_account); - - ok(SOSAccountJoinCircles(alice_account, &error), "Alice re-applies (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, bob_account); // Bob sees Alice Applying - - { - CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); - - ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); - ok(SOSAccountAcceptApplicants(bob_account, applicants, &error), "Bob accepts (%@)", error); - CFReleaseNull(error); - CFReleaseNull(applicants); - } - - CFMutableDictionaryRef bobAcceptanceChanges = ExtractPendingChanges(changes); - - // Alice re-applies without seeing that she was accepted. - ok(SOSAccountLeaveCircles(alice_account, &error), "Alice Leaves again (%@)", error); - CFReleaseNull(error); - ok(SOSAccountJoinCircles(alice_account, &error), "Alice re-applies (%@)", error); - CFReleaseNull(error); - - CFReleaseSafe(ExtractPendingChanges(changes)); // Alice loses the race to write her changes - bob never sees em. - - FeedChangesTo(&bobAcceptanceChanges, alice_account); // Alice sees bob inviting her in the circle. - - FeedChangesTo(changes, bob_account); // Bob sees Alice Concurring - - // As of PR-13917727/PR-13906870 - accounts_agree("Alice leave, applies back, loses a race and eventually gets in", bob_account, alice_account); -#endif - - // Both in circle. - - // Emulation of - - // We want Alice to leave circle while an Applicant on a full concordance signed circle with old-Alice as an Alum and Bob a peer. - // ZZZ - ok(SOSAccountLeaveCircles(alice_account, &error), "Alice leaves once more (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, bob_account); // Bob sees Alice become an Alum. - FeedChangesTo(changes, alice_account); // Alice sees bob concurring - accounts_agree("Alice and Bob see Alice out of circle", bob_account, alice_account); - - ok(SOSAccountJoinCircles(alice_account, &error), "Alice re-applies (%@)", error); - CFReleaseNull(error); - - ok(SOSAccountLeaveCircles(alice_account, &error), "Alice leaves while applying (%@)", error); - FeedChangesTo(changes, bob_account); // Bob sees Alice become an Alum. - - CFReleaseNull(error); - - is(SOSAccountIsInCircles(alice_account, &error), kSOSCCNotInCircle, "Alice isn't applying any more"); - accounts_agree("Alice leaves & some fancy concordance stuff happens", bob_account, alice_account); - - ok(SOSAccountJoinCircles(alice_account, &error), "Alice re-applies (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, bob_account); // Bob sees Alice reapply. - - { - CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); - - ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); - ok(SOSAccountAcceptApplicants(bob_account, applicants, &error), "Bob accepts (%@)", error); - CFReleaseNull(error); - CFReleaseNull(applicants); - } - - FeedChangesTo(changes, alice_account); // Alice sees bob accepting her - FeedChangesTo(changes, bob_account); // Bob sees Alice concur - - accounts_agree("Alice comes back", bob_account, alice_account); - - // Emulation of - FeedChangesTo(changes, carol_account); - - ok(SOSAccountAssertUserCredentials(carol_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(cfpassword); - ok(SOSAccountJoinCircles(carol_account, &error), "Carol Applies (%@)", error); - CFReleaseNull(error); - CFReleaseSafe(ExtractPendingChanges(changes)); // Alice and Bob loses the race to see Carol's changes. - - ok(SOSAccountResetToOffering(carol_account, &error), "Reset to offering (%@)", error); - CFReleaseNull(error); - FeedChangesTo(changes, bob_account); - accounts_agree("13889901", carol_account, bob_account); - is(SOSAccountGetLastDepartureReason(bob_account, &error), kSOSMembershipRevoked, "Bob affirms he hasn't left."); - - ok(SOSAccountJoinCircles(bob_account, &error), "Bob ReApplies (%@)", error); - FeedChangesTo(changes, carol_account); - { - CFArrayRef applicants = SOSAccountCopyApplicants(carol_account, &error); - - ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); - ok(SOSAccountAcceptApplicants(carol_account, applicants, &error), "Carol accepts (%@)", error); - CFReleaseNull(error); - CFReleaseNull(applicants); - } - FeedChangesTo(changes, bob_account); - FeedChangesTo(changes, carol_account); - accounts_agree("rdar://problem/13889901-II", bob_account, carol_account); - - CFReleaseNull(alice_new_gestalt); - - CFReleaseNull(bob_account); - CFReleaseNull(alice_account); - CFReleaseNull(carol_account); -} - -int secd_55_account_circle(int argc, char *const *argv) -{ - plan_tests(kTestTestCount); - - tests(); - - return 0; -} diff --git a/sec/securityd/Regressions/secd-55-account-incompatibility.c b/sec/securityd/Regressions/secd-55-account-incompatibility.c deleted file mode 100644 index 24694aad..00000000 --- a/sec/securityd/Regressions/secd-55-account-incompatibility.c +++ /dev/null @@ -1,197 +0,0 @@ -// -// secd-55-account-circle.c -// sec -// -// Created by Mitch Adler on 1/25/12. -// -// - - - -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include - -#include "secd_regressions.h" -#include "SOSTestDataSource.h" - -#include "SOSRegressionUtilities.h" -#include -#include - -#include - -#include "SOSAccountTesting.h" - - -static int kTestTestCount = 9; - -static void tests(void) -{ - CFErrorRef error = NULL; - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - CFDataRef cfwrong_password = CFDataCreate(NULL, (uint8_t *) "NotFooFooFoo", 10); - CFStringRef cfaccount = CFSTR("test@test.org"); - CFStringRef data_name = CFSTR("TestSource"); - CFStringRef circle_key_name = SOSCircleKeyCreateWithName(data_name, NULL); - - CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - - SOSAccountRef alice_account = CreateAccountForLocalChanges(changes, CFSTR("Alice"), data_name); - SOSAccountRef bob_account = CreateAccountForLocalChanges(changes, CFSTR("Bob"), data_name); - SOSAccountRef carol_account = CreateAccountForLocalChanges(changes, CFSTR("Carol"), data_name); - - ok(SOSAccountAssertUserCredentials(bob_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - - // Bob wins writing at this point, feed the changes back to alice. - - FeedChangesToMulti(changes, alice_account, carol_account, NULL); - - ok(SOSAccountAssertUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - ok(SOSAccountTryUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential trying (%@)", error); - CFReleaseNull(error); - CFReleaseNull(cfpassword); - - ok(!SOSAccountTryUserCredentials(alice_account, cfaccount, cfwrong_password, &error), "Credential failing (%@)", error); - CFReleaseNull(cfwrong_password); - is(error ? CFErrorGetCode(error) : 0, kSOSErrorWrongPassword, "Expected SOSErrorWrongPassword"); - CFReleaseNull(error); - - CFDataRef incompatibleDER = SOSCircleCreateIncompatibleCircleDER(&error); - - CFDictionarySetValue(changes, circle_key_name, incompatibleDER); - - FeedChangesTo(changes, alice_account); - CFReleaseNull(incompatibleDER); - CFReleaseNull(circle_key_name); - is(SOSAccountIsInCircles(alice_account, &error), kSOSCCError, "Is in circle"); - CFReleaseNull(error); - -#if 0 - ok(SOSAccountResetToOffering(alice_account, &error), "Reset to offering (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, bob_account); - - ok(SOSAccountJoinCircles(bob_account, &error), "Bob Applies (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, alice_account); - - { - 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); - } - - - FeedChangesTo(changes, bob_account); // Bob sees he's accepted - - FeedChangesTo(changes, alice_account); // Alice sees bob-concurring - - ok(CFDictionaryGetCount(changes) == 0, "We converged. (%@)", changes); - - accounts_agree("bob&alice pair", bob_account, alice_account); - - CFArrayRef peers = SOSAccountCopyPeers(alice_account, &error); - ok(peers && CFArrayGetCount(peers) == 2, "See two peers %@ (%@)", peers, error); - CFReleaseNull(peers); - - CFDictionaryRef alice_new_gestalt = SOSCreatePeerGestaltFromName(CFSTR("Alice, but different")); - - ok(SOSAccountUpdateGestalt(alice_account, alice_new_gestalt), "Update gestalt %@ (%@)", alice_account, error); - CFReleaseNull(alice_new_gestalt); - - FeedChangesTo(changes, bob_account); // Bob sees alice change her name. - - FeedChangesTo(changes, alice_account); // Alice sees the fallout. - - accounts_agree("Alice's name changed", bob_account, alice_account); - - ok(SOSAccountLeaveCircles(alice_account, &error), "Alice Leaves (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, bob_account); // Bob sees alice bail. - - FeedChangesTo(changes, alice_account); // Alice sees the fallout. - - accounts_agree("Alice bails", bob_account, alice_account); - - peers = SOSAccountCopyPeers(alice_account, &error); - ok(peers && CFArrayGetCount(peers) == 1, "See one peer %@ (%@)", peers, error); - CFReleaseNull(peers); - - ok(SOSAccountJoinCircles(alice_account, &error), "Alice re-applies (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, bob_account); - - - { - CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); - - ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); - ok(SOSAccountAcceptApplicants(bob_account, applicants, &error), "Bob accepts (%@)", error); - CFReleaseNull(error); - CFReleaseNull(applicants); - } - - FeedChangesTo(changes, alice_account); // Alice sees bob accepting - - FeedChangesTo(changes, bob_account); // Bob sees Alice concurring - - accounts_agree("Alice accepts' Bob", bob_account, alice_account); - - ok(SOSAccountLeaveCircles(alice_account, &error), "Alice Leaves (%@)", error); - CFReleaseNull(error); - ok(SOSAccountJoinCircles(alice_account, &error), "Alice re-applies (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, bob_account); // Bob sees Alice leaving and rejoining - FeedChangesTo(changes, alice_account); // Alice sees bob concurring - - { - CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); - - ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); - ok(SOSAccountAcceptApplicants(bob_account, applicants, &error), "Bob accepts (%@)", error); - CFReleaseNull(error); - CFReleaseNull(applicants); - } - - FeedChangesTo(changes, alice_account); // Alice sees bob accepting - - FeedChangesTo(changes, bob_account); // Bob sees Alice concurring - - accounts_agree("Bob accepts Alice", bob_account, alice_account); - - - CFReleaseNull(alice_new_gestalt); -#endif - - CFReleaseNull(bob_account); - CFReleaseNull(alice_account); - CFReleaseNull(carol_account); -} - -int secd_55_account_incompatibility(int argc, char *const *argv) -{ - plan_tests(kTestTestCount); - - tests(); - - return 0; -} diff --git a/sec/securityd/Regressions/secd-56-account-apply.c b/sec/securityd/Regressions/secd-56-account-apply.c deleted file mode 100644 index 6bc9f4b3..00000000 --- a/sec/securityd/Regressions/secd-56-account-apply.c +++ /dev/null @@ -1,223 +0,0 @@ -// -// sc-60-account-cloud-identity.c -// sec -// -// Created by Mitch Adler on 6/25/13. -// -// - - - -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include - -#include "secd_regressions.h" -#include "SOSTestDataSource.h" - -#include "SOSRegressionUtilities.h" -#include -#include - -#include - -#include "SOSAccountTesting.h" - - -static int kTestTestCount = 97; - -#if 0 -static int countPeers(SOSAccountRef account, bool active) { - CFErrorRef error = NULL; - CFArrayRef peers; - - if(active) peers = SOSAccountCopyActivePeers(account, &error); - else peers = SOSAccountCopyPeers(account, &error); - int retval = (int) CFArrayGetCount(peers); - CFReleaseNull(error); - CFReleaseNull(peers); - return retval; -} -#endif - -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(changes, CFSTR("Alice"), CFSTR("TestSource")); - SOSAccountRef bob_account = CreateAccountForLocalChanges(changes, CFSTR("Bob"), CFSTR("TestSource")); - SOSAccountRef carole_account = CreateAccountForLocalChanges(changes, CFSTR("Carole"), CFSTR("TestSource")); - SOSAccountRef david_account = CreateAccountForLocalChanges(changes, CFSTR("David"), CFSTR("TestSource")); - - ok(SOSAccountAssertUserCredentials(bob_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - - // Bob wins writing at this point, feed the changes back to alice. - - FeedChangesToMulti(changes, alice_account, carole_account, david_account, NULL); - - ok(SOSAccountAssertUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - - ok(SOSAccountAssertUserCredentials(carole_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - - ok(SOSAccountAssertUserCredentials(david_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(cfpassword); - CFReleaseNull(error); - - ok(SOSAccountResetToOffering(alice_account, &error), "Reset to offering (%@)", error); - CFReleaseNull(error); - - // Lost Application Scenario - FeedChangesToMulti(changes, bob_account, carole_account, NULL); - - ok(SOSAccountJoinCircles(bob_account, &error), "Bob Applies (%@)", error); - CFReleaseNull(error); - - ok(SOSAccountJoinCircles(carole_account, &error), "Carole Applies too (%@)", error); - CFReleaseNull(error); - - FeedChangesToMulti(changes, alice_account, bob_account, NULL); - FeedChangesToMulti(changes, alice_account, bob_account, carole_account, NULL); - - accounts_agree("alice and carole agree", alice_account, carole_account); - accounts_agree("alice and bob agree", alice_account, bob_account); - - { - CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); - - ok(applicants && CFArrayGetCount(applicants) == 2, "See two applicants %@ (%@)", applicants, error); - CFReleaseNull(error); - CFReleaseSafe(applicants); - } - - FeedChangesToMulti(changes, bob_account, carole_account, NULL); - FeedChangesToMulti(changes, bob_account, alice_account, carole_account, NULL); - accounts_agree("alice and carole agree", alice_account, carole_account); - ok(CFDictionaryGetCount(changes) == 0, "Nothing left to deal with (%@)", changes); - CFReleaseNull(error); - - { - CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); - ok(applicants && CFArrayGetCount(applicants) == 2, "See two applicants %@ (%@)", applicants, error); - ok(SOSAccountRejectApplicants(alice_account, applicants, &error), "Everyone out the pool"); - CFReleaseNull(error); - CFReleaseSafe(applicants); - } - - FeedChangesToMulti(changes, bob_account, carole_account, NULL); - FeedChangesToMulti(changes, bob_account, alice_account, carole_account, NULL); - accounts_agree("alice and carole agree", alice_account, carole_account); - ok(CFDictionaryGetCount(changes) == 0, "Nothing left to deal with (%@)", changes); - - { - CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); - ok(applicants && CFArrayGetCount(applicants) == 0, "See no applicants %@ (%@)", applicants, error); - CFReleaseNull(error); - CFReleaseSafe(applicants); - } - - ok(SOSAccountJoinCircles(bob_account, &error), "Bob asks again"); - CFReleaseNull(error); - FeedChangesToMulti(changes, bob_account, alice_account, carole_account, NULL); - ok(CFDictionaryGetCount(changes) == 0, "Nothing left to deal with (%@)", changes); - - { - CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); - ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicants %@ (%@)", applicants, error); - CFReleaseNull(error); - ok(SOSAccountAcceptApplicants(alice_account, applicants, &error), "Accept bob into the fold"); - CFReleaseNull(error); - CFReleaseSafe(applicants); - } - - FeedChangesTo(changes, bob_account); // Countersign - FeedChangesToMulti(changes, alice_account, bob_account, carole_account, NULL); // Everyone sees the fallout. - ok(CFDictionaryGetCount(changes) == 0, "Nothing left to deal with (%@)", changes); - -#if 0 - - { - CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); - - ok(applicants && CFArrayGetCount(applicants) == 1, "Bob automatically re-applied %@ (%@)", applicants, error); - ok(SOSAccountAcceptApplicants(alice_account, applicants, &error), "Alice accepts (%@)", error); - CFReleaseNull(error); - CFReleaseNull(applicants); - } - - is(countPeers(alice_account, 0), 3, "Bob is accepted after auto-reapply"); - FeedChangesToMulti(changes, bob_account, carole_account, david_account, NULL); - FeedChangesToMulti(changes, alice_account, bob_account, carole_account, david_account, NULL); - FeedChangesToMulti(changes, alice_account, bob_account, carole_account, david_account, NULL); - accounts_agree("alice and carole agree after bob gets in", alice_account, carole_account); - - // Rejected Application Scenario - ok(SOSAccountJoinCircles(david_account, &error), "Dave Applies (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, alice_account); - SOSAccountPurgePrivateCredential(alice_account); - - { - CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); - - ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); - ok(SOSAccountRejectApplicants(alice_account, applicants, &error), "Alice rejects (%@)", error); - CFReleaseNull(error); - CFReleaseNull(applicants); - } - FeedChangesToMulti(changes, alice_account, bob_account, carole_account, david_account, NULL); - FeedChangesToMulti(changes, alice_account, bob_account, carole_account, david_account, NULL); - FeedChangesToMulti(changes, alice_account, bob_account, carole_account, david_account, NULL); - accounts_agree("alice and carole still agree after david is rejected", alice_account, carole_account); - ok(SOSAccountTryUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - - - - - FeedChangesToMulti(changes, alice_account, carole_account, NULL); // Everyone sees conurring circle - - ok(CFDictionaryGetCount(changes) == 0, "We converged. (%@)", changes); - - accounts_agree("bob&alice pair", bob_account, alice_account); - - ok(SOSAccountJoinCirclesAfterRestore(carole_account, &error), "Carole cloud identiy joins (%@)", error); - CFReleaseNull(error); - - is(countPeers(carole_account, false), 3, "Carole sees 3 valid peers after sliding in"); - - FeedChangesTo(changes, bob_account); - FeedChangesTo(changes, alice_account); - FeedChangesToMulti(changes, bob_account, carole_account, NULL); // Bob and carole see the final result. - - accounts_agree_internal("Carole's in", bob_account, alice_account, false); - accounts_agree_internal("Carole's in - 2", bob_account, carole_account, false); -#endif - CFReleaseNull(bob_account); - CFReleaseNull(alice_account); - CFReleaseNull(carole_account); -} - -int secd_56_account_apply(int argc, char *const *argv) -{ - plan_tests(kTestTestCount); - - tests(); - - return 0; -} diff --git a/sec/securityd/Regressions/secd-57-account-leave.c b/sec/securityd/Regressions/secd-57-account-leave.c deleted file mode 100644 index 747dac27..00000000 --- a/sec/securityd/Regressions/secd-57-account-leave.c +++ /dev/null @@ -1,238 +0,0 @@ -// -// sc-57-account-leave.c -// sec -// -// Created by Mitch Adler on 6/18/13. -// -// - - - -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include - -#include "secd_regressions.h" -#include "SOSTestDataSource.h" - -#include "SOSRegressionUtilities.h" -#include -#include - -#include - -#include "SOSAccountTesting.h" - - -static int kTestTestCount = 158; - -/* -static void trim_retirements_from_circle(SOSAccountRef account) { - SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { - SOSCircleRemoveRetired(circle, NULL); - }); -} - */ - - -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(changes, CFSTR("Alice"), CFSTR("TestSource")); - SOSAccountRef bob_account = CreateAccountForLocalChanges(changes, CFSTR("Bob"), CFSTR("TestSource")); - SOSAccountRef carole_account = CreateAccountForLocalChanges(changes, CFSTR("Carole"), CFSTR("TestSource")); - SOSAccountRef david_account = CreateAccountForLocalChanges(changes, CFSTR("David"), CFSTR("TestSource")); - - ok(SOSAccountAssertUserCredentials(bob_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - - // Bob wins writing at this point, feed the changes back to alice. - - FeedChangesToMulti(changes, alice_account, carole_account, david_account, NULL); - - ok(SOSAccountAssertUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - - ok(SOSAccountAssertUserCredentials(carole_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - - ok(SOSAccountResetToOffering(alice_account, &error), "Reset to offering (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, bob_account); - - ok(SOSAccountJoinCircles(bob_account, &error), "Bob Applies (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, alice_account); - - { - 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); - } - - - FeedChangesTo(changes, bob_account); // Bob sees he's accepted - - FeedChangesTo(changes, alice_account); // Alice sees bob-concurring - - ok(CFDictionaryGetCount(changes) == 0, "We converged. (%@)", changes); - - accounts_agree("bob&alice pair", bob_account, alice_account); - is(SOSAccountGetLastDepartureReason(bob_account, &error), kSOSNeverLeftCircle, "Bob affirms he hasn't left."); - - CFArrayRef peers = SOSAccountCopyPeers(alice_account, &error); - ok(peers && CFArrayGetCount(peers) == 2, "See two peers %@ (%@)", peers, error); - CFReleaseNull(peers); - - SOSAccountPurgePrivateCredential(alice_account); - - ok(SOSAccountLeaveCircles(alice_account, &error), "Alice Leaves (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, bob_account); // Bob sees alice bail. - - FeedChangesTo(changes, alice_account); // Alice sees the fallout. - - accounts_agree("Alice bails", bob_account, alice_account); - - { - CFArrayRef concurring = SOSAccountCopyConcurringPeers(alice_account, &error); - - ok(concurring && CFArrayGetCount(concurring) == 2, "See two concurring %@ (%@)", concurring, error); - CFReleaseNull(error); - CFReleaseNull(concurring); - } - - ok(SOSAccountTryUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - - ok(SOSAccountJoinCircles(alice_account, &error), "Alice re-applies (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, bob_account); // Bob sees alice request. - - is(countActivePeers(bob_account), 3, "Bob sees 2 active peers"); - is(countPeers(bob_account), 1, "Bob sees 1 valid peer"); - - { - CFArrayRef applicants = SOSAccountCopyApplicants(bob_account, &error); - - ok(applicants && CFArrayGetCount(applicants) == 1, "See alice's reapp. %@ (%@)", applicants, error); - ok(SOSAccountAcceptApplicants(bob_account, applicants, &error), "Bob accepts (%@)", error); - CFReleaseNull(error); - CFReleaseNull(applicants); - } - - - is(countActivePeers(bob_account), 3, "Bob sees 3 active peers"); - is(countPeers(bob_account), 2, "Bob sees 2 valid peers"); - - is(countActivePeers(alice_account), 3, "Alice sees 2 active peers"); - is(countPeers(alice_account), 1, "Alice sees 1 valid peers"); - - FeedChangesToMulti(changes, alice_account, carole_account, NULL); // Alice sees bob accepts. - - FeedChangesToMulti(changes, bob_account, carole_account, NULL); // Bob sees Alice concurr. - - accounts_agree("Alice rejoined", bob_account, alice_account); - accounts_agree_internal("Alice rejoined, carole noticed", bob_account, carole_account, false); - - ok(SOSAccountJoinCircles(carole_account, &error), "Carole applies (%@)", error); - CFReleaseNull(error); - - FeedChangesToMulti(changes, bob_account, alice_account, NULL); // Bob and carole see the final result. - - accounts_agree_internal("Carole applied", bob_account, alice_account, false); - accounts_agree_internal("Carole applied - 2", bob_account, carole_account, false); - - { - CFArrayRef applicants = SOSAccountCopyApplicants(bob_account, &error); - - ok(applicants && CFArrayGetCount(applicants) == 1, "See Carole's eapp. %@ (%@)", applicants, error); - ok(SOSAccountAcceptApplicants(bob_account, applicants, &error), "Bob accepts carole (%@)", error); - CFReleaseNull(error); - CFReleaseNull(applicants); - } - - FeedChangesToMulti(changes, alice_account, NULL); // Alice sees the change and countersigns - FeedChangesToMulti(changes, carole_account, NULL); // Carole countersigns her acceptance. - FeedChangesToMulti(changes, bob_account, alice_account, david_account, NULL); // Bob and Alice see carole's counter signature. - // david ends up with a 3 peerinfo member circle. - - accounts_agree_internal("Carole joined", bob_account, alice_account, false); - accounts_agree_internal("Carole joined - 2", bob_account, carole_account, false); - - // Now test lost circle change when two leave simultaneously, needing us to see the retirement tickets - - ok(SOSAccountLeaveCircles(alice_account, &error), "Alice Leaves (%@)", error); - CFReleaseNull(error); - - ok(SOSAccountLeaveCircles(carole_account, &error), "carole Leaves (%@)", error); - CFReleaseNull(error); - - FeedChangesToMulti(changes, bob_account, NULL); // Bob sees both retirements and a circle missing one - - is(countPeers(bob_account), 1, "Bob sees 1 valid peer"); - is(countActivePeers(bob_account), 4, "Bob sees 4 active peers"); - - FeedChangesToMulti(changes, carole_account, alice_account, david_account, NULL); - - is(SOSAccountGetLastDepartureReason(carole_account, &error), kSOSWithdrewMembership, "Carole affirms she left on her own."); - - ok(SOSAccountAssertUserCredentials(david_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - CFReleaseNull(cfpassword); - is(countPeers(david_account), 1, "david sees 1 peers"); - is(countActivePeers(david_account), 4, "david sees 4 active peers"); - - ok(SOSAccountJoinCircles(david_account, &error), "David applies (%@)", error); - CFReleaseNull(error); - is(countPeers(david_account), 1, "david sees 1 peers"); - is(countActivePeers(david_account), 4, "david sees 4 active peers"); - - FeedChangesToMulti(changes, carole_account, alice_account, bob_account, NULL); - - { - CFArrayRef applicants = SOSAccountCopyApplicants(bob_account, &error); - - ok(applicants && CFArrayGetCount(applicants) == 1, "See David's app. %@ (%@)", applicants, error); - ok(SOSAccountAcceptApplicants(bob_account, applicants, &error), "Bob accepts carole (%@)", error); - CFReleaseNull(error); - CFReleaseNull(applicants); - } - - FeedChangesToMulti(changes, carole_account, alice_account, david_account, NULL); - - is(countPeers(bob_account), 2, "Bob sees 2 valid peer"); - is(countActivePeers(bob_account), 3, "Bob sees 3 active peers"); - - CFReleaseNull(bob_account); - CFReleaseNull(alice_account); -} - -int secd_57_account_leave(int argc, char *const *argv) -{ - plan_tests(kTestTestCount); - - tests(); - - return 0; -} diff --git a/sec/securityd/Regressions/secd-58-password-change.c b/sec/securityd/Regressions/secd-58-password-change.c deleted file mode 100644 index 4f1e85f7..00000000 --- a/sec/securityd/Regressions/secd-58-password-change.c +++ /dev/null @@ -1,198 +0,0 @@ -// -// secd-58-password-change.c -// sec -// -// Created by Mitch Adler on 6/18/13. -// -// - - - -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include - -#include "secd_regressions.h" -#include "SOSTestDataSource.h" - -#include "SOSRegressionUtilities.h" -#include -#include - -#include - -#include "SOSAccountTesting.h" - - -static int kTestTestCount = 300; - -static bool AssertCreds(SOSAccountRef account, CFStringRef acct_name, CFDataRef password) { - CFErrorRef error = NULL; - bool retval; - ok((retval = SOSAccountAssertUserCredentials(account, acct_name, password, &error)), "Credential setting (%@)", error); - CFReleaseNull(error); - return retval; -} - -static bool ResetToOffering(SOSAccountRef account) { - CFErrorRef error = NULL; - bool retval; - ok((retval = SOSAccountResetToOffering(account, &error)), "Reset to offering (%@)", error); - CFReleaseNull(error); - return retval; -} - -static bool JoinCircle(SOSAccountRef account) { - CFErrorRef error = NULL; - bool retval; - ok((retval = SOSAccountJoinCircles(account, &error)), "Join Circle (%@)", error); - CFReleaseNull(error); - return retval; -} - -static bool AcceptApplicants(SOSAccountRef account, CFIndex cnt) { - CFErrorRef error = NULL; - bool retval = false; - CFArrayRef applicants = SOSAccountCopyApplicants(account, &error); - - ok((retval = (applicants && CFArrayGetCount(applicants) == cnt)), "See applicants %@ (%@)", applicants, error); - if(retval) ok((retval = SOSAccountAcceptApplicants(account, applicants, &error)), "Accept Applicants (%@)", error); - CFReleaseNull(applicants); - CFReleaseNull(error); - return retval; -} - - -static void tests(void) -{ - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - CFStringRef cfaccount = CFSTR("test@test.org"); - - CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - - SOSAccountRef alice_account = CreateAccountForLocalChanges(changes, CFSTR("Alice"), CFSTR("TestSource")); - SOSAccountRef bob_account = CreateAccountForLocalChanges(changes, CFSTR("Bob"), CFSTR("TestSource")); - SOSAccountRef carol_account = CreateAccountForLocalChanges(changes, CFSTR("Carol"), CFSTR("TestSource")); - - /* Set Initial Credentials and Parameters for the Syncing Circles ---------------------------------------*/ - ok(AssertCreds(bob_account, cfaccount, cfpassword), "Setting credentials for Bob"); - // Bob wins writing at this point, feed the changes back to alice. - FeedChangesToMulti(changes, alice_account, carol_account, NULL); - ok(AssertCreds(alice_account, cfaccount, cfpassword), "Setting credentials for Alice"); - ok(AssertCreds(carol_account, cfaccount, cfpassword), "Setting credentials for Carol"); - CFReleaseNull(cfpassword); - - /* Make Alice First Peer -------------------------------------------------------------------------------*/ - ok(ResetToOffering(alice_account), "Reset to offering - Alice as first peer"); - FeedChangesToMulti(changes, bob_account, carol_account, NULL); - - /* Bob Joins -------------------------------------------------------------------------------------------*/ - ok(JoinCircle(bob_account), "Bob Applies"); - FeedChangesToMulti(changes, alice_account, carol_account, NULL); - - /* Alice Accepts -------------------------------------------------------------------------------------------*/ - ok(AcceptApplicants(alice_account, 1), "Alice Accepts Bob's Application"); - FeedChangesToMulti(changes, bob_account, carol_account, NULL); // Bob sees he's accepted - FeedChangesToMulti(changes, alice_account, carol_account, NULL); // Alice sees bob-concurring - ok(CFDictionaryGetCount(changes) == 0, "We converged. (%@)", changes); - accounts_agree("bob&alice pair", bob_account, alice_account); - - /* Carol Applies -------------------------------------------------------------------------------------------*/ - ok(JoinCircle(carol_account), "Carol Applies"); - FeedChangesToMulti(changes, alice_account, bob_account, NULL); - - is(countPeers(alice_account), 2, "See two peers"); - - - /* Change Password ------------------------------------------------------------------------------------------*/ - CFDataRef cfnewpassword = CFDataCreate(NULL, (uint8_t *) "ooFooFooF", 10); - - ok(AssertCreds(bob_account, cfaccount, cfnewpassword), "Credential resetting for Bob"); - is(countPeers(bob_account), 2, "There are two valid peers - iCloud and Bob"); - is(countActivePeers(bob_account), 3, "There are three active peers - bob, alice, and iCloud"); - is(countActiveValidPeers(bob_account), 2, "There is two active valid peer - Bob and iCloud"); - FeedChangesToMulti(changes, alice_account, carol_account, NULL); - - ok(AssertCreds(alice_account, cfaccount, cfnewpassword), "Credential resetting for Alice"); - is(countPeers(alice_account), 2, "There are two peers - bob and alice"); - is(countActiveValidPeers(alice_account), 3, "There are three active valid peers - alice, bob, and icloud"); - FeedChangesToMulti(changes, bob_account, carol_account, NULL); - FeedChangesToMulti(changes, alice_account, carol_account, NULL); - FeedChangesToMulti(changes, alice_account, bob_account, NULL); - accounts_agree("bob&alice pair", bob_account, alice_account); - is(countPeers(alice_account), 2, "There are two peers - bob and alice"); - is(countActiveValidPeers(alice_account), 3, "There are three active valid peers - alice, bob, and icloud"); - - ok(AssertCreds(carol_account, cfaccount, cfnewpassword), "Credential resetting for Carol"); - FeedChangesToMulti(changes, alice_account, bob_account, NULL); - FeedChangesToMulti(changes, bob_account, carol_account, alice_account, NULL); - FeedChangesToMulti(changes, bob_account, carol_account, alice_account, NULL); - FeedChangesToMulti(changes, bob_account, carol_account, alice_account, NULL); - accounts_agree("bob&alice pair", bob_account, alice_account); - - ok(AcceptApplicants(alice_account, 1), "Alice Accepts Carol's Application"); - FeedChangesToMulti(changes, bob_account, carol_account, NULL); // Carol sees she's accepted - FeedChangesToMulti(changes, alice_account, bob_account, carol_account, NULL); // Alice sees bob-concurring - FeedChangesToMulti(changes, alice_account, bob_account, carol_account, NULL); // Alice sees bob-concurring - FeedChangesToMulti(changes, alice_account, bob_account, carol_account, NULL); // Alice sees bob-concurring - accounts_agree_internal("bob&alice pair", bob_account, alice_account, false); - accounts_agree_internal("bob&carol pair", bob_account, carol_account, false); - accounts_agree_internal("carol&alice pair", alice_account, carol_account, false); - - - /* Change Password 2 ----------------------------------------------------------------------------------------*/ - CFReleaseNull(cfnewpassword); - cfnewpassword = CFDataCreate(NULL, (uint8_t *) "ffoffoffo", 10); - - /* Bob */ - ok(AssertCreds(bob_account, cfaccount, cfnewpassword), "Credential resetting for Bob"); - is(countPeers(bob_account), 3, "There are three peers - Alice, Carol, Bob"); - is(countActivePeers(bob_account), 4, "There are four active peers - bob, alice, carol and iCloud"); - is(countActiveValidPeers(bob_account), 2, "There is two active valid peer - Bob and iCloud"); - FeedChangesToMulti(changes, alice_account, carol_account, NULL); - - /* Alice */ - ok(AssertCreds(alice_account, cfaccount, cfnewpassword), "Credential resetting for Alice"); - is(countPeers(alice_account), 3, "There are three peers - Alice, Carol, Bob"); - is(countActivePeers(alice_account), 4, "There are four active peers - bob, alice, carol and iCloud"); - is(countActiveValidPeers(alice_account), 3, "There are three active valid peers - alice, bob, and icloud"); - FeedChangesToMulti(changes, bob_account, carol_account, NULL); - FeedChangesToMulti(changes, alice_account, bob_account, carol_account, NULL); - FeedChangesToMulti(changes, alice_account, bob_account, carol_account, NULL); - - /* Carol */ - ok(AssertCreds(carol_account, cfaccount, cfnewpassword), "Credential resetting for Carol"); - is(countPeers(carol_account), 3, "There are three peers - Alice, Carol, Bob"); - is(countActivePeers(carol_account), 4, "There are four active peers - bob, alice, carol and iCloud"); - is(countActiveValidPeers(carol_account), 4, "There are three active valid peers - alice, bob, carol, and icloud"); - - FeedChangesToMulti(changes, alice_account, bob_account, NULL); - FeedChangesToMulti(changes, bob_account, carol_account, alice_account, NULL); - FeedChangesToMulti(changes, bob_account, carol_account, alice_account, NULL); - FeedChangesToMulti(changes, bob_account, carol_account, alice_account, NULL); - accounts_agree_internal("bob&alice pair", bob_account, alice_account, false); - - CFReleaseNull(bob_account); - CFReleaseNull(alice_account); - CFReleaseNull(carol_account); - CFReleaseNull(cfnewpassword); - -} - -int secd_58_password_change(int argc, char *const *argv) -{ - plan_tests(kTestTestCount); - - tests(); - - return 0; -} diff --git a/sec/securityd/Regressions/secd-59-account-cleanup.c b/sec/securityd/Regressions/secd-59-account-cleanup.c deleted file mode 100644 index 2c2337b8..00000000 --- a/sec/securityd/Regressions/secd-59-account-cleanup.c +++ /dev/null @@ -1,180 +0,0 @@ -// -// secd-59-account-cleanup.c -// sec -// -// Created by Mitch Adler on 6/18/13. -// -// - - - -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include - -#include "secd_regressions.h" -#include "SOSTestDataSource.h" - -#include "SOSRegressionUtilities.h" -#include -#include - -#include - -#include "SOSAccountTesting.h" - - -static int kTestTestCount = 93; - -static void tests(void) -{ - CFErrorRef error = NULL; - CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); - CFStringRef cfaccount = CFSTR("test@test.org"); - CFStringRef circle_name = CFSTR("TestSource"); - - CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - - SOSAccountRef alice_account = CreateAccountForLocalChanges(changes, CFSTR("Alice"), circle_name); - SOSAccountRef bob_account = CreateAccountForLocalChanges(changes, CFSTR("Bob"), circle_name); - SOSAccountRef carole_account = CreateAccountForLocalChanges(changes, CFSTR("Carole"), circle_name); - - ok(SOSAccountAssertUserCredentials(bob_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - - // Bob wins writing at this point, feed the changes back to alice. - - FeedChangesToMulti(changes, alice_account, carole_account, NULL); - - ok(SOSAccountAssertUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - - ok(SOSAccountAssertUserCredentials(carole_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - ok(SOSAccountResetToOffering(alice_account, &error), "Reset to offering (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, bob_account); - - ok(SOSAccountJoinCircles(bob_account, &error), "Bob Applies (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, alice_account); - - { - 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); - } - - - FeedChangesTo(changes, bob_account); // Bob sees he's accepted - - FeedChangesTo(changes, alice_account); // Alice sees bob-concurring - - ok(CFDictionaryGetCount(changes) == 0, "We converged. (%@)", changes); - - accounts_agree("bob&alice pair", bob_account, alice_account); - - CFArrayRef peers = SOSAccountCopyPeers(alice_account, &error); - ok(peers && CFArrayGetCount(peers) == 2, "See two peers %@ (%@)", peers, error); - CFReleaseNull(peers); - - SOSFullPeerInfoRef fpiAlice = SOSAccountGetMyFullPeerInCircleNamed(alice_account, circle_name, NULL); - CFStringRef alice_id = CFStringCreateCopy(NULL, SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(fpiAlice))); - - ok(SOSAccountLeaveCircles(alice_account, &error), "Alice Leaves (%@)", error); - CFReleaseNull(error); - CFReleaseNull(cfpassword); - - FeedChangesTo(changes, bob_account); // Bob sees alice bail. - - is(CFDictionaryGetCountOfValue(changes, kCFNull),2, "2 Keys Nulled Out"); - - CFDictionaryForEach(changes, ^(const void *key, const void *value) { - if(isNull(value)) { - CFStringRef circle_name = NULL, from_name = NULL, to_name = NULL; - SOSKVSKeyType keytype = SOSKVSKeyGetKeyTypeAndParse(key, &circle_name, &from_name, &to_name); - is(keytype, kMessageKey, "Expect only a message key"); - bool testcmp = CFEqualSafe(alice_id, from_name) || CFEqualSafe(alice_id, to_name); - ok(testcmp, "Alice is from_name(%@) or to_name(%@)", from_name, to_name); - CFReleaseNull(circle_name); - CFReleaseNull(from_name); - CFReleaseNull(to_name); - } - }); - - FeedChangesToMulti(changes, alice_account, carole_account, NULL); - - accounts_agree("Alice bails", bob_account, alice_account); - accounts_agree("Alice bails", bob_account, carole_account); - - SOSAccountCleanupRetirementTickets(bob_account, 0, &error); - is(CFDictionaryGetCountOfValue(changes, kCFNull),0, "0 Keys Nulled Out"); - - ok(SOSAccountJoinCircles(carole_account, &error), "Carole Applies (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, bob_account); - - { - CFArrayRef applicants = SOSAccountCopyApplicants(bob_account, &error); - - ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); - ok(SOSAccountAcceptApplicants(bob_account, applicants, &error), "Bob accepts Carole (%@)", error); - CFReleaseNull(error); - CFReleaseNull(applicants); - } - - // Bob should not yet cleanup Alice's retirment here on his own since it hasn't been long enough - // by default. - is(CFDictionaryGetCountOfValue(changes, kCFNull),0, "0 Keys Nulled Out"); - - FeedChangesTo(changes, carole_account); // Carole sees he's accepted - FeedChangesTo(changes, bob_account); // Bob sees she's all happy. - - accounts_agree("Carole joins", bob_account, carole_account); - - SOSAccountCleanupRetirementTickets(bob_account, 0, &error); - - is(countPeers(bob_account), 2, "Active peers after forced cleanup"); - is(countActivePeers(bob_account), 3, "Inactive peers after forced cleanup"); - - is(CFDictionaryGetCountOfValue(changes, kCFNull), 1, "1 Keys Nulled Out"); - - CFDictionaryForEach(changes, ^(const void *key, const void *value) { - if(isNull(value)) { - CFStringRef circle_name = NULL, retiree = NULL; - SOSKVSKeyType keytype = SOSKVSKeyGetKeyTypeAndParse(key, &circle_name, &retiree, NULL); - is(keytype, kRetirementKey, "Expect only a retirement key"); - ok(CFEqualSafe(alice_id, retiree), "Alice (%@) is retiree (%@)", alice_id, retiree); - CFReleaseNull(circle_name); - CFReleaseNull(retiree); - } - }); - - CFReleaseNull(alice_id); - CFReleaseNull(carole_account); - CFReleaseNull(bob_account); - CFReleaseNull(alice_account); -} - -int secd_59_account_cleanup(int argc, char *const *argv) -{ - plan_tests(kTestTestCount); - - tests(); - - return 0; -} diff --git a/sec/securityd/Regressions/secd-60-account-cloud-identity.c b/sec/securityd/Regressions/secd-60-account-cloud-identity.c deleted file mode 100644 index e808eb8e..00000000 --- a/sec/securityd/Regressions/secd-60-account-cloud-identity.c +++ /dev/null @@ -1,151 +0,0 @@ -// -// sc-60-account-cloud-identity.c -// sec -// -// Created by Mitch Adler on 6/25/13. -// -// - - - -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include - -#include "secd_regressions.h" -#include "SOSTestDataSource.h" - -#include "SOSRegressionUtilities.h" -#include -#include - -#include - -#include "SOSAccountTesting.h" - - -static int kTestTestCount = 95; - - - -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(changes, CFSTR("Alice"), CFSTR("TestSource")); - SOSAccountRef bob_account = CreateAccountForLocalChanges(changes, CFSTR("Bob"), CFSTR("TestSource")); - SOSAccountRef carole_account = CreateAccountForLocalChanges(changes, CFSTR("Carole"), CFSTR("TestSource")); - - ok(SOSAccountAssertUserCredentials(bob_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - - // Bob wins writing at this point, feed the changes back to alice. - - FeedChangesToMulti(changes, alice_account, carole_account, NULL); - - ok(SOSAccountAssertUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - - ok(SOSAccountAssertUserCredentials(carole_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - CFReleaseNull(cfpassword); - ok(SOSAccountResetToOffering(alice_account, &error), "Reset to offering (%@)", error); - CFReleaseNull(error); - - FeedChangesToMulti(changes, bob_account, carole_account, NULL); - - ok(SOSAccountJoinCircles(bob_account, &error), "Bob Applies (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, alice_account); - - { - 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); - } - - - FeedChangesTo(changes, bob_account); // Bob sees he's accepted - - FeedChangesToMulti(changes, alice_account, carole_account, NULL); // Everyone sees conurring circle - - ok(CFDictionaryGetCount(changes) == 0, "We converged. (%@)", changes); - - accounts_agree("bob&alice pair", bob_account, alice_account); - - /*----- normal join after restore -----*/ - - ok(SOSAccountJoinCirclesAfterRestore(carole_account, &error), "Carole cloud identity joins (%@)", error); - CFReleaseNull(error); - - FeedChangesToMulti(changes, bob_account, carole_account, NULL); // Bob and carole see the final result. - FeedChangesToMulti(changes, alice_account, bob_account, carole_account, NULL); // Bob and carole see the final result. - - is(countApplicants(alice_account), 0, "See no applicants"); - - is(countPeers(carole_account), 3, "Carole sees 3 valid peers after sliding in"); - - FeedChangesToMulti(changes, bob_account, carole_account, NULL); // Bob and carole see the final result. - - accounts_agree_internal("Carole's in", bob_account, alice_account, false); - accounts_agree_internal("Carole's in - 2", bob_account, carole_account, false); - - ok(SOSAccountLeaveCircles(carole_account, &error), "Carol Leaves again"); - CFReleaseNull(error); - FeedChangesToMulti(changes, bob_account, alice_account, NULL); - FeedChangesToMulti(changes, alice_account, bob_account, carole_account, NULL); - - /*----- join - join after restore -----*/ - - ok(SOSAccountJoinCircles(carole_account, &error), "Carole normally joins (%@)", error); - CFReleaseNull(error); - FeedChangesTo(changes, alice_account); - - is(countApplicants(alice_account), 1, "See one applicant"); - - ok(SOSAccountJoinCirclesAfterRestore(carole_account, &error), "Carole cloud identity joins (%@)", error); - CFReleaseNull(error); - - FeedChangesToMulti(changes, bob_account, carole_account, NULL); // Bob and carole see the final result. - FeedChangesToMulti(changes, alice_account, bob_account, carole_account, NULL); // Bob and carole see the final result. - - is(countApplicants(alice_account), 0, "See no applicants"); - - is(countPeers(carole_account), 3, "Carole sees 3 valid peers after sliding in"); - - FeedChangesToMulti(changes, bob_account, carole_account, NULL); // Bob and carole see the final result. - - accounts_agree_internal("Carole's in", bob_account, alice_account, false); - accounts_agree_internal("Carole's in - 2", bob_account, carole_account, false); - - - - CFReleaseNull(bob_account); - CFReleaseNull(alice_account); - CFReleaseNull(carole_account); -} - -int secd_60_account_cloud_identity(int argc, char *const *argv) -{ - plan_tests(kTestTestCount); - - tests(); - - return 0; -} diff --git a/sec/securityd/Regressions/secd-61-account-leave-not-in-kansas-anymore.c b/sec/securityd/Regressions/secd-61-account-leave-not-in-kansas-anymore.c deleted file mode 100644 index 5cbeeb54..00000000 --- a/sec/securityd/Regressions/secd-61-account-leave-not-in-kansas-anymore.c +++ /dev/null @@ -1,194 +0,0 @@ -// -// secd-61-account-leave-not-in-kansas-anymore.c -// sec -// -// Created by Richard Murphy on 7/16/13. -// - - -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include - -#include "secd_regressions.h" -#include "SOSTestDataSource.h" - -#include "SOSRegressionUtilities.h" -#include -#include - -#include - -#include "SOSAccountTesting.h" - - -static int kTestTestCount = 102; -#if 0 -static int countPeers(SOSAccountRef account, bool active) { - CFErrorRef error = NULL; - CFArrayRef peers; - - if(active) peers = SOSAccountCopyActivePeers(account, &error); - else peers = SOSAccountCopyPeers(account, &error); - int retval = (int) CFArrayGetCount(peers); - CFReleaseNull(error); - CFReleaseNull(peers); - return retval; -} -#endif -/* - static void trim_retirements_from_circle(SOSAccountRef account) { - SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { - SOSCircleRemoveRetired(circle, NULL); - }); - } - */ -static bool accept_applicants(SOSAccountRef account, int count) { - CFErrorRef error = NULL; - CFArrayRef applicants = SOSAccountCopyApplicants(account, &error); - bool retval = false; - ok(applicants, "Have Applicants"); - if(!applicants) goto errout; - is(CFArrayGetCount(applicants), count, "See applicants %@ (%@)", applicants, error); - if(CFArrayGetCount(applicants) != count) goto errout; - ok(retval = SOSAccountAcceptApplicants(account, applicants, &error), "Account accepts (%@)", error); -errout: - CFReleaseNull(error); - CFReleaseNull(applicants); - 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(changes, CFSTR("Alice"), CFSTR("TestSource")); - SOSAccountRef bob_account = CreateAccountForLocalChanges(changes, CFSTR("Bob"), CFSTR("TestSource")); - SOSAccountRef carole_account = CreateAccountForLocalChanges(changes, CFSTR("Carole"), CFSTR("TestSource")); - SOSAccountRef david_account = CreateAccountForLocalChanges(changes, CFSTR("David"), CFSTR("TestSource")); - - ok(SOSAccountAssertUserCredentials(bob_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - - // Bob wins writing at this point, feed the changes back to alice. - - FeedChangesToMulti(changes, alice_account, carole_account, david_account, NULL); - - ok(SOSAccountAssertUserCredentials(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - - ok(SOSAccountAssertUserCredentials(carole_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - - ok(SOSAccountAssertUserCredentials(david_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); - CFReleaseNull(error); - - ok(SOSAccountResetToOffering(alice_account, &error), "Reset to offering (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, bob_account); - - ok(SOSAccountJoinCircles(bob_account, &error), "Bob Applies (%@)", error); - CFReleaseNull(error); - - FeedChangesTo(changes, alice_account); - - ok(accept_applicants(alice_account, 1), "Alice Accepts Application"); - - FeedChangesToMulti(changes, alice_account, bob_account, carole_account, david_account, NULL); - - FeedChangesToMulti(changes, alice_account, bob_account, carole_account, david_account, NULL); - - ok(CFDictionaryGetCount(changes) == 0, "We converged. (%@)", changes); - - accounts_agree("bob&alice pair", bob_account, alice_account); - is(SOSAccountGetLastDepartureReason(bob_account, &error), kSOSNeverLeftCircle, "Bob affirms he hasn't left."); - - // ============================== Alice and Bob are in the Account. ============================================ - - ok(SOSAccountJoinCircles(carole_account, &error), "Carole Applies (%@)", error); - CFReleaseNull(error); - - FeedChangesToMulti(changes, alice_account, carole_account, david_account, NULL); - - ok(accept_applicants(alice_account, 1), "Alice Accepts Application"); - - // Let everyone concur. - FeedChangesToMulti(changes, alice_account, carole_account, david_account, NULL); - - CFArrayRef peers = SOSAccountCopyPeers(alice_account, &error); - ok(peers && CFArrayGetCount(peers) == 3, "See three peers %@ (%@)", peers, error); - CFReleaseNull(peers); - - - // SOSAccountPurgePrivateCredential(alice_account); - - ok(SOSAccountLeaveCircles(alice_account, &error), "Alice Leaves (%@)", error); - CFReleaseNull(error); - - FeedChangesToMulti(changes, alice_account, carole_account, david_account, NULL); - FeedChangesToMulti(changes, alice_account, carole_account, david_account, NULL); - FeedChangesToMulti(changes, alice_account, carole_account, david_account, NULL); - - ok(SOSAccountJoinCircles(david_account, &error), "David Applies (%@)", error); - CFReleaseNull(error); - - FeedChangesToMulti(changes, alice_account, carole_account, david_account, NULL); - - CFReleaseNull(error); - ok(accept_applicants(carole_account, 1), "Carole Accepts Application"); - - // ============================== We added Carole and David while Bob was in a drawer. Alice has left ============================================ - - // ============================== Bob comes out of the drawer seeing alice left and doesn't recognize the remainder. ============================================ - - FeedChangesToMulti(changes, alice_account, carole_account, david_account, NULL); - FeedChangesToMulti(changes, bob_account, alice_account, carole_account, david_account, NULL); - FeedChangesToMulti(changes, alice_account, carole_account, david_account, bob_account, NULL); - FeedChangesToMulti(changes, alice_account, carole_account, david_account, bob_account, NULL); - FeedChangesToMulti(changes, alice_account, carole_account, david_account, bob_account, NULL); - FeedChangesToMulti(changes, alice_account, carole_account, david_account, bob_account, NULL); - FeedChangesToMulti(changes, alice_account, carole_account, david_account, bob_account, NULL); - - CFReleaseNull(error); - is(SOSAccountIsInCircles(carole_account, &error), kSOSCCInCircle, "Carole still in Circle (%@)", error); - CFReleaseNull(error); - is(SOSAccountIsInCircles(david_account, &error), kSOSCCInCircle, "David still in Circle (%@)", error); - CFReleaseNull(error); - is(SOSAccountIsInCircles(bob_account, &error), kSOSCCNotInCircle, "Bob is not in Circle (%@)", error); - CFReleaseNull(error); - is(SOSAccountGetLastDepartureReason(bob_account, &error), kSOSLeftUntrustedCircle, "Bob affirms he left because he doesn't know anyone."); - CFReleaseNull(error); - is(SOSAccountIsInCircles(alice_account, &error), kSOSCCNotInCircle, "Alice is not in Circle (%@)", error); - CFReleaseNull(error); - is(SOSAccountGetLastDepartureReason(alice_account, &error), kSOSWithdrewMembership, "Alice affirms she left by request."); - CFReleaseNull(error); - - - CFReleaseNull(carole_account); - CFReleaseNull(david_account); - CFReleaseNull(bob_account); - CFReleaseNull(alice_account); -} - -int secd_61_account_leave_not_in_kansas_anymore(int argc, char *const *argv) -{ - plan_tests(kTestTestCount); - - tests(); - - return 0; -} diff --git a/sec/securityd/Regressions/secd_regressions.h b/sec/securityd/Regressions/secd_regressions.h deleted file mode 100644 index 391a06a0..00000000 --- a/sec/securityd/Regressions/secd_regressions.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// secd_regressions.h -// sec -// -// Created by Fabrice Gautier on 5/29/13. -// -// - -#include - -ONE_TEST(secd_01_items) -ONE_TEST(secd_02_upgrade_while_locked) -ONE_TEST(secd_03_corrupted_items) -ONE_TEST(secd_04_corrupted_items) -ONE_TEST(secd_05_corrupted_items) - -DISABLED_ONE_TEST(secd_30_keychain_upgrade) //obsolete, needs updating -ONE_TEST(secd_31_keychain_bad) -ONE_TEST(secd_31_keychain_unreadable) - -ONE_TEST(secd_50_account) -ONE_TEST(secd_51_account_inflate) -ONE_TEST(secd_52_account_changed) -ONE_TEST(secd_55_account_circle) -ONE_TEST(secd_55_account_incompatibility) -ONE_TEST(secd_56_account_apply) -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_61_account_leave_not_in_kansas_anymore) diff --git a/sec/securityd/Regressions/securityd_regressions.h b/sec/securityd/Regressions/securityd_regressions.h deleted file mode 100644 index b1d2a50b..00000000 --- a/sec/securityd/Regressions/securityd_regressions.h +++ /dev/null @@ -1,12 +0,0 @@ -/* To add a test: - 1) add it here - 2) Add it as command line argument for SecurityTest.app in the Release and Debug schemes - */ -#include - -ONE_TEST(sd_10_policytree) -#ifdef NO_SERVER -ONE_TEST(sd_70_engine) -#else -OFF_ONE_TEST(sd_70_engine) -#endif diff --git a/sec/securityd/SOSCloudCircleServer.c b/sec/securityd/SOSCloudCircleServer.c deleted file mode 100644 index b5f8b876..00000000 --- a/sec/securityd/SOSCloudCircleServer.c +++ /dev/null @@ -1,1000 +0,0 @@ -// -// SOSCloudCircleServer.c -// sec -// -// Created by Mitch Adler on 11/15/12. -// -// - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "SOSCloudKeychainClient.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include - -#if TARGET_OS_EMBEDDED || TARGET_IPHONE_SIMULATOR -#include -#else -#include - -// We need authorization, but that doesn't exist -// on sec built for desktop (iOS in a process) -// Define AuthorizationRef here to make SystemConfiguration work -// as if it's on iOS. -typedef const struct AuthorizationOpaqueRef * AuthorizationRef; -#endif - -#define SOSCKCSCOPE "sync" - -#define USE_SYSTEMCONFIGURATION_PRIVATE_HEADERS -#import - -#include - -CloudKeychainReplyBlock log_error = ^(CFDictionaryRef returnedValues __unused, CFErrorRef error) { - if (error) { - secerror("Error putting: %@", error); - CFReleaseSafe(error); - } -}; - -static SOSCCAccountDataSourceFactoryBlock accountDataSourceOverride = NULL; - -bool SOSKeychainAccountSetFactoryForAccount(SOSCCAccountDataSourceFactoryBlock block) -{ - accountDataSourceOverride = Block_copy(block); - - return true; -} - -static void do_with_account(void (^action)(SOSAccountRef account)); - - -// -// Constants -// -CFStringRef kSOSInternalAccessGroup = CFSTR("com.apple.security.sos"); - -CFStringRef kSOSAccountLabel = CFSTR("iCloud Keychain Account Meta-data"); -CFStringRef kSOSPeerDataLabel = CFSTR("iCloud Peer Data Meta-data"); - -static CFStringRef accountFileName = CFSTR("PersistedAccount.plist"); - -static CFDictionaryRef SOSItemCopyQueryForSyncItems(CFStringRef service, bool returnData) -{ - return CFDictionaryCreateForCFTypes(kCFAllocatorDefault, - kSecClass, kSecClassGenericPassword, - kSecAttrService, service, - kSecAttrAccessGroup, kSOSInternalAccessGroup, - kSecReturnData, returnData ? kCFBooleanTrue : kCFBooleanFalse, - NULL); -} - -CFDataRef SOSItemGet(CFStringRef service, CFErrorRef* error) -{ - CFDictionaryRef query = SOSItemCopyQueryForSyncItems(service, true); - - CFDataRef result = NULL; - - OSStatus copyResult = SecItemCopyMatching(query, (CFTypeRef*) &result); - - CFReleaseNull(query); - - if (copyResult != noErr) { - SecError(copyResult, error, CFSTR("Error %@ reading for service '%@'"), result, service); - CFReleaseNull(result); - return NULL; - } - - if (!isData(result)) { - SOSCreateErrorWithFormat(kSOSErrorProcessingFailure, NULL, error, NULL, CFSTR("SecItemCopyMatching returned non-data in '%@'"), service); - return NULL; - } - - return result; -} - -static CFDataRef SOSKeychainCopySavedAccountData() -{ - CFErrorRef error = NULL; - CFDataRef accountData = SOSItemGet(kSOSAccountLabel, &error); - if (!accountData) - secnotice("account", "Failed to load account: %@", error); - CFReleaseNull(error); - - return accountData; -} - - -bool SOSItemUpdateOrAdd(CFStringRef service, CFStringRef accessibility, CFDataRef data, CFErrorRef *error) -{ - CFDictionaryRef query = SOSItemCopyQueryForSyncItems(service, false); - - CFDictionaryRef update = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, - kSecValueData, data, - kSecAttrAccessible, accessibility, - NULL); - OSStatus saveStatus = SecItemUpdate(query, update); - - if (errSecItemNotFound == saveStatus) { - CFMutableDictionaryRef add = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, query); - CFDictionaryForEach(update, ^(const void *key, const void *value) { - CFDictionaryAddValue(add, key, value); - }); - saveStatus = SecItemAdd(add, NULL); - CFReleaseNull(add); - } - - CFReleaseNull(query); - CFReleaseNull(update); - - return SecError(saveStatus, error, CFSTR("Error saving %@ to service '%@'"), data, service); -} - -static CFStringRef accountStatusFileName = CFSTR("accountStatus.plist"); -#include -#include -#include - -static const uint8_t* ccder_decode_bool(bool* boolean, const uint8_t* der, const uint8_t *der_end) -{ - if (NULL == der) - return NULL; - - size_t payload_size = 0; - const uint8_t *payload = ccder_decode_tl(CCDER_BOOLEAN, &payload_size, der, der_end); - - if (NULL == payload || (der_end - payload) < 1 || payload_size != 1) { - return NULL; - } - - if (boolean) - *boolean = (*payload != 0); - - return payload + payload_size; -} - -bool SOSCCCircleIsOn_Artifact(void) { - CFURLRef accountStatusFileURL = SecCopyURLForFileInKeychainDirectory(accountStatusFileName); - CFDataRef accountStatus = (CFDataRef) CFPropertyListReadFromFile(accountStatusFileURL); - CFReleaseSafe(accountStatusFileURL); - bool circle_on = false; - - if (accountStatus && !isData(accountStatus)) { - CFReleaseNull(accountStatus); - } else if(accountStatus) { - size_t size = CFDataGetLength(accountStatus); - const uint8_t *der = CFDataGetBytePtr(accountStatus); - const uint8_t *der_p = der; - - const uint8_t *sequence_end; - der_p = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der_p, der_p + size); - der_p = ccder_decode_bool(&circle_on, der_p, sequence_end); - } else { - - } - return circle_on; -} - - -static size_t ccder_sizeof_bool(bool value __unused, CFErrorRef *error) -{ - return ccder_sizeof(CCDER_BOOLEAN, 1); -} - - -static uint8_t* ccder_encode_bool(bool value, const uint8_t *der, uint8_t *der_end) -{ - uint8_t value_byte = value; - - return ccder_encode_tl(CCDER_BOOLEAN, 1, der, - ccder_encode_body(1, &value_byte, der, der_end)); -} - -static void SOSCCCircleIsOn_SetArtifact(bool account_on) { - static CFDataRef sLastSavedAccountStatus = NULL; - CFErrorRef saveError = NULL; - size_t der_size = ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, ccder_sizeof_bool(account_on, NULL)); - uint8_t der[der_size]; - uint8_t *der_end = der + der_size; - der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, - ccder_encode_bool(account_on, der, der_end)); - - CFDataRef accountStatusAsData = CFDataCreate(kCFAllocatorDefault, der_end, der_size); - - require_quiet(accountStatusAsData, exit); - if (sLastSavedAccountStatus && CFEqual(sLastSavedAccountStatus, accountStatusAsData)) goto exit; - - CFURLRef accountStatusFileURL = SecCopyURLForFileInKeychainDirectory(accountStatusFileName); - CFPropertyListWriteToFile((CFPropertyListRef) accountStatusAsData, accountStatusFileURL); - CFReleaseSafe(accountStatusFileURL); - - CFReleaseNull(sLastSavedAccountStatus); - sLastSavedAccountStatus = accountStatusAsData; - accountStatusAsData = NULL; - -exit: - CFReleaseNull(saveError); - CFReleaseNull(accountStatusAsData); -} - -static void SOSCCCircleIsOn_UpdateArtifact(SOSCCStatus status) -{ - switch (status) { - case kSOSCCCircleAbsent: - case kSOSCCNotInCircle: - SOSCCCircleIsOn_SetArtifact(false); - break; - case kSOSCCInCircle: - case kSOSCCRequestPending: - SOSCCCircleIsOn_SetArtifact(true); - break; - case kSOSCCError: - default: - // do nothing - break; - } -} - -static void SOSKeychainAccountEnsureSaved(SOSAccountRef account) -{ - static CFDataRef sLastSavedAccountData = NULL; - - CFErrorRef saveError = NULL; - SOSCCCircleIsOn_UpdateArtifact(SOSAccountIsInCircles(account, NULL)); - - CFDataRef accountAsData = SOSAccountCopyEncodedData(account, kCFAllocatorDefault, &saveError); - - require_action_quiet(accountAsData, exit, secerror("Failed to transform account into data, error: %@", saveError)); - require_quiet(!CFEqualSafe(sLastSavedAccountData, accountAsData), exit); - - if (!SOSItemUpdateOrAdd(kSOSAccountLabel, kSecAttrAccessibleAlwaysThisDeviceOnly, accountAsData, &saveError)) { - secerror("Can't save account: %@", saveError); - goto exit; - } - - CFReleaseNull(sLastSavedAccountData); - sLastSavedAccountData = accountAsData; - accountAsData = NULL; - -exit: - CFReleaseNull(saveError); - CFReleaseNull(accountAsData); -} - - -/* - Stolen from keychain_sync.c - */ - -static bool clearAllKVS(CFErrorRef *error) -{ - return true; - __block bool result = false; - const uint64_t maxTimeToWaitInSeconds = 30ull * NSEC_PER_SEC; - dispatch_queue_t processQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0); - dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds); - - SOSCloudKeychainClearAll(processQueue, ^(CFDictionaryRef returnedValues, CFErrorRef cerror) - { - result = (cerror != NULL); - dispatch_semaphore_signal(waitSemaphore); - }); - - dispatch_semaphore_wait(waitSemaphore, finishTime); - dispatch_release(waitSemaphore); - - return result; -} - -static SOSAccountRef SOSKeychainAccountCreateSharedAccount(CFDictionaryRef our_gestalt) -{ - SOSAccountKeyInterestBlock updateKVSKeys = ^(bool getNewKeysOnly, CFArrayRef alwaysKeys, CFArrayRef afterFirstUnlockKeys, CFArrayRef unlockedKeys) { - CFErrorRef error = NULL; - - if (!SOSCloudKeychainUpdateKeys(getNewKeysOnly, alwaysKeys, afterFirstUnlockKeys, unlockedKeys, &error)) - { - secerror("Error updating keys: %@", error); - // TODO: propagate error(s) to callers. - } else { - if (CFArrayGetCount(unlockedKeys) == 0) { - secnotice(SOSCKCSCOPE, "Unlocked keys were empty!"); - } - // This leaks 3 CFStringRefs in DEBUG builds. - CFStringRef alwaysKeysDesc = SOSInterestListCopyDescription(alwaysKeys); - CFStringRef afterFirstUnlockKeysDesc = SOSInterestListCopyDescription(afterFirstUnlockKeys); - CFStringRef unlockedKeysDesc = SOSInterestListCopyDescription(unlockedKeys); - secdebug(SOSCKCSCOPE, "Updating interest: always: %@,\nfirstUnlock: %@,\nunlockedKeys: %@", - alwaysKeysDesc, - afterFirstUnlockKeysDesc, - unlockedKeysDesc); - CFReleaseNull(alwaysKeysDesc); - CFReleaseNull(afterFirstUnlockKeysDesc); - CFReleaseNull(unlockedKeysDesc); - } - - CFReleaseNull(error); - }; - - SOSAccountDataUpdateBlock updateKVS = ^ bool (CFDictionaryRef changes, CFErrorRef *error) { - SOSCloudKeychainPutObjectsInCloud(changes, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), log_error); - - CFStringRef changeDescription = SOSChangesCopyDescription(changes, true); - secnotice("account", "Keys Sent: %@", changeDescription); - CFReleaseSafe(changeDescription); - - return true; - }; - - secdebug("account", "Created account"); - - CFDataRef savedAccount = SOSKeychainCopySavedAccountData(); - - // At this point we might have an account structure from keychain that may or may not match the account we're building this for - // murf ZZZ we should probably make sure this is a good thing before using it. - - SOSAccountRef account = NULL; - - if (savedAccount) { - CFErrorRef inflationError = NULL; - SOSDataSourceFactoryRef factory = accountDataSourceOverride ? accountDataSourceOverride() : SecItemDataSourceFactoryCreateDefault(); - - account = SOSAccountCreateFromData(kCFAllocatorDefault, savedAccount, factory, updateKVSKeys, updateKVS, &inflationError); - - if (account) - SOSAccountUpdateGestalt(account, our_gestalt); - else - secerror("Got error inflating account: %@", inflationError); - CFReleaseNull(inflationError); - } - - CFReleaseSafe(savedAccount); - - if (!account) { - // If we get here then we are creating a new accout and so increment the peer count for ourselves. - SOSDataSourceFactoryRef factory = accountDataSourceOverride ? accountDataSourceOverride() : SecItemDataSourceFactoryCreateDefault(); - - account = SOSAccountCreate(kCFAllocatorDefault, our_gestalt, factory, updateKVSKeys, updateKVS); - - if (!account) - secerror("Got NULL creating account"); - } - - return account; -} - -// -// Mark: Gestalt Handling -// - -static CFStringRef CopyModelName(void) -{ - static dispatch_once_t once; - static CFStringRef modelName = NULL; - dispatch_once(&once, ^{ -#if TARGET_OS_EMBEDDED || TARGET_IPHONE_SIMULATOR - modelName = MGCopyAnswer(kMGQDeviceName, NULL); -#else - modelName = ASI_CopyComputerModelName(FALSE); -#endif - if (modelName == NULL) - modelName = CFSTR("Unknown model"); - }); - return CFStringCreateCopy(kCFAllocatorDefault, modelName); -} - -static CFStringRef CopyComputerName(SCDynamicStoreRef store) -{ - CFStringRef deviceName = SCDynamicStoreCopyComputerName(store, NULL); - if (deviceName == NULL) { - deviceName = CFSTR("Unknown name"); - } - return deviceName; -} - -static CFDictionaryRef GatherDeviceGestalt(SCDynamicStoreRef store, CFArrayRef keys, void *context) -{ - CFStringRef modelName = CopyModelName(); - CFStringRef computerName = CopyComputerName(store); - - CFDictionaryRef gestalt = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, - kPIUserDefinedDeviceName, computerName, - kPIDeviceModelName, modelName, - NULL); - CFRelease(modelName); - CFRelease(computerName); - - return gestalt; -} - -static void SOSCCProcessGestaltUpdate(SCDynamicStoreRef store, CFArrayRef keys, void *context) -{ - do_with_account(^(SOSAccountRef account) { - CFDictionaryRef gestalt = GatherDeviceGestalt(store, keys, context); - if (SOSAccountUpdateGestalt(account, gestalt)) { - notify_post(kSOSCCCircleChangedNotification); - } - CFReleaseSafe(gestalt); - }); -} - - -static CFDictionaryRef RegisterForGestaltUpdate(dispatch_queue_t queue, void *info) -{ - SCDynamicStoreContext context = { .info = info }; - SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("com.apple.securityd.cloudcircleserver"), SOSCCProcessGestaltUpdate, &context); - CFStringRef computerKey = SCDynamicStoreKeyCreateComputerName(NULL); - CFArrayRef keys = NULL; - CFDictionaryRef gestalt = NULL; - - if (store == NULL || computerKey == NULL) { - goto done; - } - keys = CFArrayCreate(NULL, (const void **)&computerKey, 1, &kCFTypeArrayCallBacks); - if (keys == NULL) { - goto done; - } - gestalt = GatherDeviceGestalt(store, keys, info); - SCDynamicStoreSetNotificationKeys(store, keys, NULL); - SCDynamicStoreSetDispatchQueue(store, queue); - -done: - if (store) CFRelease(store); - if (computerKey) CFRelease(computerKey); - if (keys) CFRelease(keys); - return gestalt; -} - -static void do_with_account(void (^action)(SOSAccountRef account)); -static void do_with_account_async(void (^action)(SOSAccountRef account)); - -static void do_with_account_dynamic(void (^action)(SOSAccountRef account), bool sync) { - static SOSAccountRef sSharedAccount; - static dispatch_once_t onceToken; - - dispatch_once(&onceToken, ^{ - secdebug(SOSCKCSCOPE, "Account Creation start"); - - CFDictionaryRef gestalt = RegisterForGestaltUpdate(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); - - if (!gestalt) { -#if TARGET_OS_IPHONE && TARGET_IPHONE_SIMULATOR - gestalt = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, NULL); -#else - secerror("Didn't get machine gestalt! This is going to be ugly."); -#endif - } - - sSharedAccount = SOSKeychainAccountCreateSharedAccount(gestalt); - - CFReleaseSafe(gestalt); - - SOSCCSetThisDeviceDefinitelyNotActiveInCircle(SOSAccountIsInCircles(sSharedAccount, NULL)); - - SOSAccountAddChangeBlock(sSharedAccount, ^(SOSCircleRef circle, - CFArrayRef peer_additions, CFArrayRef peer_removals, - CFArrayRef applicant_additions, CFArrayRef applicant_removals) { - CFErrorRef pi_error = NULL; - SOSPeerInfoRef me = SOSAccountGetMyPeerInCircle(sSharedAccount, circle, &pi_error); - if (!me) { - secerror("Error finding me for change: %@", pi_error); - CFReleaseNull(pi_error); - } else { - CFReleaseSafe(pi_error); - - if (CFArrayContainsValue(peer_additions, CFRangeMake(0, CFArrayGetCount(peer_additions)), me)) { - SOSCCSyncWithAllPeers(); - } - } - - if (CFArrayGetCount(peer_additions) != 0 || - CFArrayGetCount(peer_removals) != 0 || - CFArrayGetCount(applicant_additions) != 0 || - CFArrayGetCount(applicant_removals) != 0) { - - SOSCCSetThisDeviceDefinitelyNotActiveInCircle(SOSAccountIsInCircles(sSharedAccount, NULL)); - notify_post(kSOSCCCircleChangedNotification); - } - }); - - SOSCloudKeychainSetItemsChangedBlock(^(CFDictionaryRef changes) { - CFRetainSafe(changes); - do_with_account_async(^(SOSAccountRef account) { - CFStringRef changeDescription = SOSChangesCopyDescription(changes, false); - secdebug(SOSCKCSCOPE, "Received: %@", changeDescription); - CFReleaseSafe(changeDescription); - - CFErrorRef error = NULL; - if (!SOSAccountHandleUpdates(account, changes, &error)) { - secerror("Error handling updates: %@", error); - CFReleaseNull(error); - return; - } - CFReleaseNull(error); - CFReleaseSafe(changes); - }); - }); - - }); - - dispatch_block_t do_action_and_save = ^{ - action(sSharedAccount); - SOSKeychainAccountEnsureSaved(sSharedAccount); - }; - - if (sync) { - dispatch_sync(SOSAccountGetQueue(sSharedAccount), do_action_and_save); - } else { - dispatch_async(SOSAccountGetQueue(sSharedAccount), do_action_and_save); - } -} - -static void do_with_account_async(void (^action)(SOSAccountRef account)) { - do_with_account_dynamic(action, false); -} - -static void do_with_account(void (^action)(SOSAccountRef account)) { - do_with_account_dynamic(action, true); -} - -#if TARGET_IPHONE_SIMULATOR -#define MKBDeviceUnlockedSinceBoot() true -#endif - -static bool do_if_after_first_unlock(CFErrorRef *error, dispatch_block_t action) -{ - bool beenUnlocked = false; - require_quiet(SecAKSGetHasBeenUnlocked(&beenUnlocked, error), fail); - - require_action_quiet(beenUnlocked, fail, - SOSCreateErrorWithFormat(kSOSErrorNotReady, NULL, error, NULL, - CFSTR("Keybag never unlocked, ask after first unlock"))); - - action(); - return true; - -fail: - return false; -} - -static bool do_with_account_if_after_first_unlock(CFErrorRef *error, bool (^action)(SOSAccountRef account, CFErrorRef* error)) -{ - __block bool action_result = false; - - return do_if_after_first_unlock(error, ^{ - do_with_account(^(SOSAccountRef account) { - action_result = action(account, error); - }); - - }) && action_result; -} - -static bool do_with_account_while_unlocked(CFErrorRef *error, bool (^action)(SOSAccountRef account, CFErrorRef* error)) -{ - __block bool action_result = false; - - return SecAKSDoWhileUserBagLocked(error, ^{ - do_with_account(^(SOSAccountRef account) { - action_result = action(account, error); - }); - - }) && action_result; -} - -SOSAccountRef SOSKeychainAccountGetSharedAccount() -{ - __block SOSAccountRef result = NULL; - - do_with_account(^(SOSAccountRef account) { - result = account; - }); - - return result; -} - -// -// Mark: Credential processing -// - - -bool SOSCCTryUserCredentials_Server(CFStringRef user_label, CFDataRef user_password, CFErrorRef *error) -{ - return do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { - return SOSAccountTryUserCredentials(account, user_label, user_password, block_error); - }); -} - - -static bool EnsureFreshParameters(SOSAccountRef account, CFErrorRef *error) { - dispatch_semaphore_t wait_for = dispatch_semaphore_create(0); - dispatch_retain(wait_for); // Both this scope and the block own it. - - CFMutableArrayRef keysToGet = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - CFArrayAppendValue(keysToGet, kSOSKVSKeyParametersKey); - - __block CFDictionaryRef valuesToUpdate = NULL; - __block bool success = false; - - SOSAccountForEachCircle(account, ^(SOSCircleRef circle) { - CFStringRef circle_key = SOSCircleKeyCreateWithName(SOSCircleGetName(circle), NULL); - CFArrayAppendValue(keysToGet, circle_key); - CFReleaseNull(circle_key); - }); - - secnotice("updates", "***** EnsureFreshParameters *****"); - - SOSCloudKeychainSynchronizeAndWait(keysToGet, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(CFDictionaryRef returnedValues, CFErrorRef sync_error) { - - if (sync_error) { - secerror("SOSCloudKeychainSynchronizeAndWait: %@", sync_error); - if (error) { - *error = sync_error; - CFRetainSafe(*error); - } - } else { - secnotice("updates", "SOSCloudKeychainSynchronizeAndWait: results: %@", returnedValues); - valuesToUpdate = returnedValues; - CFRetainSafe(valuesToUpdate); - success = true; - } - - dispatch_semaphore_signal(wait_for); - dispatch_release(wait_for); - }); - - dispatch_semaphore_wait(wait_for, DISPATCH_TIME_FOREVER); - // TODO: Maybe we timeout here... used to dispatch_time(DISPATCH_TIME_NOW, 30ull * NSEC_PER_SEC)); - dispatch_release(wait_for); - - if ((valuesToUpdate) && (account)) { - if (!SOSAccountHandleUpdates(account, valuesToUpdate, error)) { - secerror("Freshness update failed: %@", *error); - - success = false; - } - } - - CFReleaseNull(valuesToUpdate); - CFReleaseNull(keysToGet); - - return success; -} - -static bool EnsureFreshParameters_once(SOSAccountRef account, CFErrorRef *error) { - static dispatch_once_t once; - __block bool retval = false; - dispatch_once(&once, ^{ - retval = EnsureFreshParameters(account, error); - }); - return retval; -} - -bool SOSCCSetUserCredentials_Server(CFStringRef user_label, CFDataRef user_password, CFErrorRef *error) -{ - return do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { - if (!EnsureFreshParameters(account, block_error)) { - secnotice("updates", "EnsureFreshParameters error: %@", *block_error); - return false; - } - if (!SOSAccountAssertUserCredentials(account, user_label, user_password, block_error)) { - secnotice("updates", "EnsureFreshParameters/SOSAccountAssertUserCredentials error: %@", *block_error); - return false; - } - - return true; - }); - -} - -bool SOSCCCanAuthenticate_Server(CFErrorRef *error) -{ - bool result = do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { - return SOSAccountGetPrivateCredential(account, block_error) != NULL; - }); - - if (!result && error && *error && CFErrorGetDomain(*error) == kSOSErrorDomain) { - CFIndex code = CFErrorGetCode(*error); - if (code == kSOSErrorPrivateKeyAbsent || code == kSOSErrorPublicKeyAbsent) { - CFReleaseNull(*error); - } - } - - return result; -} - -bool SOSCCPurgeUserCredentials_Server(CFErrorRef *error) -{ - return do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { - SOSAccountPurgePrivateCredential(account); - return true; - }); -} - - -#if USE_BETTER -static bool sAccountInCircleCache = false; - -static void do_with_not_in_circle_bool_queue(bool start_account, dispatch_block_t action) -{ - static dispatch_queue_t account_start_queue; - static dispatch_queue_t not_in_circle_queue; - static bool account_started = false; - - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - not_in_circle_queue = dispatch_queue_create("nis queue", DISPATCH_QUEUE_SERIAL); - account_start_queue = dispatch_queue_create("init nis queue", DISPATCH_QUEUE_SERIAL);; - account_started = false; - }); - - __block bool done = false; - dispatch_sync(not_in_circle_queue, ^{ - if (account_started) { - done = true; - action(); - } - }); - - if (!done && start_account) { - dispatch_sync(account_start_queue, ^{ - __block bool do_start = false; - dispatch_sync(not_in_circle_queue, ^{ - do_start = !account_started; - account_started = true; - }); - if (do_start) - SOSCCThisDeviceIsInCircle(NULL); // Inflate account. - }); - - dispatch_sync(not_in_circle_queue, action); - } -} -#endif - -bool SOSCCThisDeviceDefinitelyNotActiveInCircle() -{ - return !SOSCCCircleIsOn_Artifact(); -#if USE_BETTER - __block bool result = false; - do_with_not_in_circle_bool_queue(true, ^{ - result = sAccountInCircleCache; - }); - - return result; -#endif -} - -void SOSCCSetThisDeviceDefinitelyNotActiveInCircle(SOSCCStatus currentStatus) -{ - SOSCCCircleIsOn_UpdateArtifact(currentStatus); -#if USE_BETTER - do_with_not_in_circle_bool_queue(false, ^{ - sAccountInCircleCache = notActive; - }); -#endif -} - - -SOSCCStatus SOSCCThisDeviceIsInCircle_Server(CFErrorRef *error) -{ - __block SOSCCStatus status; - - return do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { - EnsureFreshParameters_once(account, NULL); - status = SOSAccountIsInCircles(account, block_error); - return true; - }) ? status : kSOSCCError; -} - -bool SOSCCRequestToJoinCircle_Server(CFErrorRef* error) -{ - return do_with_account_while_unlocked(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { - EnsureFreshParameters_once(account, NULL); - return SOSAccountJoinCircles(account, block_error); - }); -} - -bool SOSCCRequestToJoinCircleAfterRestore_Server(CFErrorRef* error) -{ - return do_with_account_while_unlocked(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { - EnsureFreshParameters_once(account, NULL); - return SOSAccountJoinCirclesAfterRestore(account, block_error); - }); -} - -bool SOSCCResetToOffering_Server(CFErrorRef* error) -{ - return do_with_account_while_unlocked(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { - EnsureFreshParameters_once(account, NULL); - clearAllKVS(NULL); - return SOSAccountResetToOffering(account, block_error); - }); -} - -bool SOSCCResetToEmpty_Server(CFErrorRef* error) -{ - return do_with_account_while_unlocked(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { - return SOSAccountResetToEmpty(account, block_error); - }); -} - -bool SOSCCRemoveThisDeviceFromCircle_Server(CFErrorRef* error) -{ - return do_with_account_while_unlocked(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { - bool result = SOSAccountLeaveCircles(account, block_error); - return result; - }); -} - -bool SOSCCBailFromCircle_Server(uint64_t limit_in_seconds, CFErrorRef* error) -{ - return do_with_account_while_unlocked(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { - return SOSAccountBail(account, limit_in_seconds, block_error); - }); -} - -CFArrayRef SOSCCCopyApplicantPeerInfo_Server(CFErrorRef* error) -{ - __block CFArrayRef result = NULL; - - (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { - EnsureFreshParameters_once(account, NULL); - result = SOSAccountCopyApplicants(account, block_error); - return result != NULL; - }); - - return result; -} - - -bool SOSCCAcceptApplicants_Server(CFArrayRef applicants, CFErrorRef* error) -{ - return do_with_account_while_unlocked(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { - EnsureFreshParameters_once(account, NULL); - return SOSAccountAcceptApplicants(account, applicants, block_error); - }); -} - -bool SOSCCRejectApplicants_Server(CFArrayRef applicants, CFErrorRef* error) -{ - return do_with_account_while_unlocked(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { - EnsureFreshParameters_once(account, NULL); - return SOSAccountRejectApplicants(account, applicants, block_error); - }); -} - -CFArrayRef SOSCCCopyPeerPeerInfo_Server(CFErrorRef* error) -{ - __block CFArrayRef result = NULL; - - (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { - EnsureFreshParameters_once(account, NULL); - result = SOSAccountCopyPeers(account, block_error); - return result != NULL; - }); - - return result; -} - -CFArrayRef SOSCCCopyConcurringPeerPeerInfo_Server(CFErrorRef* error) -{ - __block CFArrayRef result = NULL; - - (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { - EnsureFreshParameters_once(account, NULL); - result = SOSAccountCopyConcurringPeers(account, block_error); - return result != NULL; - }); - - return result; -} - -CFStringRef SOSCCCopyIncompatibilityInfo_Server(CFErrorRef* error) -{ - __block CFStringRef result = NULL; - - (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { - EnsureFreshParameters_once(account, NULL); - result = SOSAccountCopyIncompatibilityInfo(account, block_error); - return result != NULL; - }); - - return result; -} - -enum DepartureReason SOSCCGetLastDepartureReason_Server(CFErrorRef* error) -{ - __block enum DepartureReason result = kSOSDepartureReasonError; - - (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { - EnsureFreshParameters_once(account, NULL); - result = SOSAccountGetLastDepartureReason(account, block_error); - return result != kSOSDepartureReasonError; - }); - - return result; -} - -SyncWithAllPeersReason SOSCCProcessSyncWithAllPeers_Server(CFErrorRef* error) -{ - /* - #define kIOReturnLockedRead iokit_common_err(0x2c3) // device read locked - #define kIOReturnLockedWrite iokit_common_err(0x2c4) // device write locked - */ - __block SyncWithAllPeersReason result = kSyncWithAllPeersSuccess; - CFErrorRef action_error = NULL; - - if (!do_with_account_while_unlocked(&action_error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { - CFErrorRef localError = NULL; - if (!SOSAccountSyncWithAllPeers(account, &localError)) { - secerror("sync with all peers failed: %@", localError); - CFReleaseSafe(localError); - // This isn't a device-locked error, but returning false will - // have CloudKeychainProxy ask us to try sync again after next unlock - result = kSyncWithAllPeersOtherFail; - return false; - } - return true; - })) { - if (action_error) { - if (SecErrorGetOSStatus(action_error) == errSecInteractionNotAllowed) { - secnotice("updates", "SOSAccountSyncWithAllPeers failed because device is locked; letting CloudKeychainProxy know"); - result = kSyncWithAllPeersLocked; // tell CloudKeychainProxy to call us back when device unlocks - CFReleaseNull(action_error); - } else { - secerror("Unexpected error: %@", action_error); - } - - if (error && *error == NULL) { - *error = action_error; - action_error = NULL; - } - - CFReleaseNull(action_error); - } - } - - return result; -} - -void SOSCCSyncWithAllPeers(void) -{ - SOSCloudKeychainRequestSyncWithAllPeers(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); -} - -void SOSCCHandleUpdate(CFDictionaryRef updates) -{ - SOSCloudKeychainHandleUpdate(updates); -} - diff --git a/sec/securityd/SOSCloudCircleServer.h b/sec/securityd/SOSCloudCircleServer.h deleted file mode 100644 index ab1ceb23..00000000 --- a/sec/securityd/SOSCloudCircleServer.h +++ /dev/null @@ -1,85 +0,0 @@ -// -// SOSCloudCircleServer.h -// sec -// -// Created by Mitch Adler on 11/15/12. -// -// - -#ifndef _SECURITY_SOSCLOUDCIRCLESERVER_H_ -#define _SECURITY_SOSCLOUDCIRCLESERVER_H_ - -#include -#include - -// -// MARK: Server versions of our SPI -// -bool SOSCCTryUserCredentials_Server(CFStringRef user_label, CFDataRef user_password, CFErrorRef *error); -bool SOSCCSetUserCredentials_Server(CFStringRef user_label, CFDataRef user_password, CFErrorRef *error); -bool SOSCCCanAuthenticate_Server(CFErrorRef *error); -bool SOSCCPurgeUserCredentials_Server(CFErrorRef *error); - -SOSCCStatus SOSCCThisDeviceIsInCircle_Server(CFErrorRef *error); -bool SOSCCRequestToJoinCircle_Server(CFErrorRef* error); -bool SOSCCRequestToJoinCircleAfterRestore_Server(CFErrorRef* error); -bool SOSCCRemoveThisDeviceFromCircle_Server(CFErrorRef* error); -bool SOSCCBailFromCircle_Server(uint64_t limit_in_seconds, CFErrorRef* error); - -CFArrayRef SOSCCCopyApplicantPeerInfo_Server(CFErrorRef* error); -bool SOSCCRejectApplicants_Server(CFArrayRef applicants, CFErrorRef* error); -bool SOSCCAcceptApplicants_Server(CFArrayRef applicants, CFErrorRef* error); - -CFArrayRef SOSCCCopyPeerPeerInfo_Server(CFErrorRef* error); -CFArrayRef SOSCCCopyConcurringPeerPeerInfo_Server(CFErrorRef* error); - -bool SOSCCResetToOffering_Server(CFErrorRef* error); -bool SOSCCResetToEmpty_Server(CFErrorRef* error); - -CFStringRef SOSCCCopyIncompatibilityInfo_Server(CFErrorRef* error); -enum DepartureReason SOSCCGetLastDepartureReason_Server(CFErrorRef* error); - -SyncWithAllPeersReason SOSCCProcessSyncWithAllPeers_Server(CFErrorRef* error); - -// -// MARK: Internal kicks. -// - -void SOSCCHandleUpdate(CFDictionaryRef updates); - -// Expected to be called when the data source changes. -void SOSCCSyncWithAllPeers(void); - -// Internal careful questioning. -bool SOSCCThisDeviceDefinitelyNotActiveInCircle(void); -void SOSCCSetThisDeviceDefinitelyNotActiveInCircle(SOSCCStatus currentStatus); - -// -// MARK: Internal access to local account for tests. -// -typedef SOSDataSourceFactoryRef (^SOSCCAccountDataSourceFactoryBlock)(); - -SOSAccountRef SOSKeychainAccountGetSharedAccount(void); -bool SOSKeychainAccountSetFactoryForAccount(SOSCCAccountDataSourceFactoryBlock factory); - -// -// MARK: Testing operations, dangerous to call in normal operation. -// -bool SOSKeychainSaveAccountDataAndPurge(CFErrorRef *error); - - -// -// MARK: Constants for where we store persistent information in the keychain -// - -extern CFStringRef kSOSInternalAccessGroup; - -extern CFStringRef kSOSAccountLabel; -extern CFStringRef kSOSPeerDataLabel; - -CFDataRef SOSItemGet(CFStringRef label, CFErrorRef* error); -bool SOSItemUpdateOrAdd(CFStringRef label, CFStringRef accessibility, CFDataRef data, CFErrorRef *error); - -bool SOSCCCircleIsOn_Artifact(void); - -#endif diff --git a/sec/securityd/SecCAIssuerRequest.h b/sec/securityd/SecCAIssuerRequest.h deleted file mode 100644 index 9f6e31dc..00000000 --- a/sec/securityd/SecCAIssuerRequest.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * SecCAIssuerRequest.h - * Security - * - * Created by Michael Brouwer on 9/17/09. - * Copyright (c) 2009-2010 Apple Inc.. All Rights Reserved. - * - */ - -#include -#include -#include - -bool SecCAIssuerCopyParents(SecCertificateRef certificate, - dispatch_queue_t queue, void *context, void (*callback)(void *, CFArrayRef)); diff --git a/sec/securityd/SecDbItem.h b/sec/securityd/SecDbItem.h deleted file mode 100644 index 236ac2b3..00000000 --- a/sec/securityd/SecDbItem.h +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright (c) 2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * 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 SecDbItem - The functions provided in SecDbItem provide an interface to - database items (certificates, keys, identities, and passwords). - */ - -#ifndef _SECURITYD_SECDBITEM_H_ -#define _SECURITYD_SECDBITEM_H_ - -#include -#include -#include // For CCSHA1_OUTPUT_SIZE -#include -#include -#include -#include -#include - -#if TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_IPHONE_SIMULATOR) -#define USE_KEYSTORE 1 -#elif TARGET_OS_EMBEDDED && !TARGET_IPHONE_SIMULATOR -#define USE_KEYSTORE 1 -#else /* no keystore on this platform */ -#define USE_KEYSTORE 0 -#endif - -#if USE_KEYSTORE -#include -#endif /* USE_KEYSTORE */ - -__BEGIN_DECLS - -// TODO: Get this out of this file -#if USE_KEYSTORE -typedef int32_t keyclass_t; -#else - -/* TODO: this needs to be available in the sim! */ -#define kAppleKeyStoreKeyWrap 0 -#define kAppleKeyStoreKeyUnwrap 1 -typedef int32_t keyclass_t; -typedef int32_t key_handle_t; -enum key_classes { - key_class_ak = 6, - key_class_ck, - key_class_dk, - key_class_aku, - key_class_cku, - key_class_dku -}; -#endif /* !USE_KEYSTORE */ - -// MARK SecDbAttrKind, SecDbFlag - -typedef enum { - kSecDbBlobAttr, // CFString or CFData, preserves caller provided type. - kSecDbDataAttr, - kSecDbStringAttr, - kSecDbNumberAttr, - kSecDbDateAttr, - kSecDbCreationDateAttr, - kSecDbModificationDateAttr, - kSecDbSHA1Attr, - kSecDbRowIdAttr, - kSecDbEncryptedDataAttr, - kSecDbPrimaryKeyAttr, - kSecDbSyncAttr, - kSecDbTombAttr, - kSecDbAccessAttr -} SecDbAttrKind; - -enum { - kSecDbPrimaryKeyFlag = (1 << 0), // attr is part of primary key - kSecDbInFlag = (1 << 1), // attr exists in db - kSecDbIndexFlag = (1 << 2), // attr should have a db index - kSecDbSHA1ValueInFlag = (1 << 3), // col in db is sha1 of attr value - kSecDbReturnAttrFlag = (1 << 4), - kSecDbReturnDataFlag = (1 << 5), - kSecDbReturnRefFlag = (1 << 6), - kSecDbInCryptoDataFlag = (1 << 7), - kSecDbInHashFlag = (1 << 8), - kSecDbInBackupFlag = (1 << 9), - kSecDbDefault0Flag = (1 << 10), // default attr value is 0 - kSecDbDefaultEmptyFlag = (1 << 11), // default attr value is "" - kSecDbNotNullFlag = (1 << 12), // attr value can't be null -}; - -#define SecVersionDbFlag(v) ((v & 0xFF) << 8) - -#define SecDbFlagGetVersion(flags) ((flags >> 8) & 0xFF) - -#define SECDB_ATTR(var, name, kind, flags) const SecDbAttr var = { CFSTR(name), kSecDb ## kind ## Attr, flags } - -typedef struct SecDbAttr { - CFStringRef name; - SecDbAttrKind kind; - CFOptionFlags flags; -} SecDbAttr; - -typedef struct SecDbClass { - CFStringRef name; - const SecDbAttr *attrs[]; -} SecDbClass; - -typedef struct Pair *SecDbPairRef; -typedef struct Query *SecDbQueryRef; - -/* Return types. */ -typedef uint32_t ReturnTypeMask; -enum -{ - kSecReturnDataMask = 1 << 0, - kSecReturnAttributesMask = 1 << 1, - kSecReturnRefMask = 1 << 2, - kSecReturnPersistentRefMask = 1 << 3, -}; - -/* Constant indicating there is no limit to the number of results to return. */ -enum -{ - kSecMatchUnlimited = kCFNotFound -}; - -typedef struct Pair -{ - const void *key; - const void *value; -} Pair; - -/* Nothing in this struct is retained since all the - values below are extracted from the dictionary passed in by the - caller. */ -typedef struct Query -{ - /* Class of this query. */ - const SecDbClass *q_class; - - /* Dictionary with all attributes and values in clear (to be encrypted). */ - CFMutableDictionaryRef q_item; - - /* q_pairs is an array of Pair structs. Elements with indices - [0, q_attr_end) contain attribute key value pairs. Elements with - indices [q_match_begin, q_match_end) contain match key value pairs. - Thus q_attr_end is the number of attrs in q_pairs and - q_match_begin - q_match_end is the number of matches in q_pairs. */ - CFIndex q_match_begin; - CFIndex q_match_end; - CFIndex q_attr_end; - - CFErrorRef q_error; - ReturnTypeMask q_return_type; - - CFDataRef q_data; - CFTypeRef q_ref; - sqlite_int64 q_row_id; - - 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; - - /* True if query contained a kSecAttrSynchronizable attribute, - * regardless of its actual value. If this is false, then we - * will add an explicit sync=0 to the query. */ - bool q_sync; - - // Set to true if we modified any item as part of executing this query - bool q_changed; - - // Set to true if we modified any synchronizable item as part of executing this query - bool q_sync_changed; - - /* Keybag handle to use for this item. */ - keybag_handle_t q_keybag; - keyclass_t q_keyclass; - //CFStringRef q_keyclass_s; - - // SHA1 digest of DER encoded primary key - CFDataRef q_primary_key_digest; - - CFArrayRef q_match_issuer; - - /* Store all the corrupted rows found during the query */ - CFMutableArrayRef corrupted_rows; - - Pair q_pairs[]; -} Query; - - -#define SecDbForEachAttr(class, attr) for (const SecDbAttr * const* _pattr = (class)->attrs, *attr = *_pattr; attr; attr = *(++_pattr)) - -#define SecDbForEachAttrWithMask(class, attr, flag_mask) SecDbForEachAttr(class, attr) if ((attr->flags & (flag_mask)) == (flag_mask)) - -// MARK: Stuff that needs to move out of SecItemServer.c - -// Move this or do crypto in a block -bool ks_encrypt_data(keybag_handle_t keybag, keyclass_t keyclass, CFDataRef plainText, CFDataRef *pBlob, CFErrorRef *error); -bool ks_decrypt_data(keybag_handle_t keybag, keyclass_t *pkeyclass, CFDataRef blob, CFDataRef *pPlainText, - uint32_t *version_p, CFErrorRef *error); - -CFDataRef kc_copy_sha1(size_t len, const void *data, CFErrorRef *error); -CFDataRef kc_copy_plist_sha1(CFPropertyListRef plist, CFErrorRef *error); -CFDataRef kc_plist_copy_der(CFPropertyListRef plist, CFErrorRef *error); -Query *query_create(const SecDbClass *qclass, CFDictionaryRef query, CFErrorRef *error); -bool query_destroy(Query *q, CFErrorRef *error); - -// MARK: SecDbItem - -typedef struct SecDbItem *SecDbItemRef; - -enum SecDbItemState { - kSecDbItemDirty, // We have no edata (or if we do it's invalid), attributes are the truth - kSecDbItemEncrypted, // Attributes haven't been decrypted yet from edata - kSecDbItemClean, // Attributes and _edata are in sync. - kSecDbItemDecrypting, // Temporary state while we are decrypting so set knows not to blow away the edata. - kSecDbItemEncrypting, // Temporary state while we are encrypting so set knows to move to clean. -}; - -struct SecDbItem { - CFRuntimeBase _base; - const SecDbClass *class; - keyclass_t keyclass; - keybag_handle_t keybag; - //sqlite3_int64 _rowid; - //CFDataRef _primaryKey; - //CFDataRef _sha1; - //CFDataRef _edata; - enum SecDbItemState _edataState; - CFMutableDictionaryRef attributes; -}; - -// TODO: Make this a callback to client -bool SecDbItemDecrypt(SecDbItemRef item, CFDataRef edata, CFErrorRef *error); - -CFTypeID SecDbItemGetTypeID(void); - -static inline size_t SecDbClassAttrCount(const SecDbClass *dbClass) { - size_t n_attrs = 0; - SecDbForEachAttr(dbClass, attr) { n_attrs++; } - return n_attrs; -} - -const SecDbAttr *SecDbClassAttrWithKind(const SecDbClass *class, SecDbAttrKind kind, CFErrorRef *error); - -SecDbItemRef SecDbItemCreateWithAttributes(CFAllocatorRef allocator, const SecDbClass *class, CFDictionaryRef attributes, keybag_handle_t keybag, CFErrorRef *error); - -const SecDbClass *SecDbItemGetClass(SecDbItemRef item); -const keybag_handle_t SecDbItemGetKeybag(SecDbItemRef item); -bool SecDbItemSetKeybag(SecDbItemRef item, keybag_handle_t keybag, CFErrorRef *error); -keyclass_t SecDbItemGetKeyclass(SecDbItemRef item, CFErrorRef *error); -bool SecDbItemSetKeyclass(SecDbItemRef item, keyclass_t keyclass, CFErrorRef *error); - -CFTypeRef SecDbItemGetCachedValueWithName(SecDbItemRef item, CFStringRef name); -CF_RETURNS_NOT_RETAINED CFTypeRef SecDbItemGetValue(SecDbItemRef item, const SecDbAttr *desc, CFErrorRef *error); - -bool SecDbItemSetValue(SecDbItemRef item, const SecDbAttr *desc, CFTypeRef value, CFErrorRef *error); -bool SecDbItemSetValues(SecDbItemRef item, CFDictionaryRef values, CFErrorRef *error); -bool SecDbItemSetValueWithName(SecDbItemRef item, CFStringRef name, CFTypeRef value, CFErrorRef *error); - -sqlite3_int64 SecDbItemGetRowId(SecDbItemRef item, CFErrorRef *error); -bool SecDbItemSetRowId(SecDbItemRef item, sqlite3_int64 rowid, CFErrorRef *error); - -bool SecDbItemIsSyncable(SecDbItemRef item); - -bool SecDbItemSetSyncable(SecDbItemRef item, bool sync, CFErrorRef *error); - -bool SecDbItemIsTombstone(SecDbItemRef item); - -CFMutableDictionaryRef SecDbItemCopyPListWithMask(SecDbItemRef item, CFOptionFlags mask, CFErrorRef *error); - -CFDataRef SecDbItemGetPrimaryKey(SecDbItemRef item, CFErrorRef *error); -CFDataRef SecDbItemGetSHA1(SecDbItemRef item, CFErrorRef *error); - -CFDataRef SecDbItemCopyEncryptedDataToBackup(SecDbItemRef item, uint64_t handle, CFErrorRef *error); - -SecDbItemRef SecDbItemCreateWithStatement(CFAllocatorRef allocator, const SecDbClass *class, sqlite3_stmt *stmt, keybag_handle_t keybag, CFErrorRef *error, bool (^return_attr)(const SecDbAttr *attr)); - -SecDbItemRef SecDbItemCreateWithEncryptedData(CFAllocatorRef allocator, const SecDbClass *class, - CFDataRef edata, keybag_handle_t keybag, CFErrorRef *error); - -SecDbItemRef SecDbItemCreateWithPrimaryKey(CFAllocatorRef allocator, const SecDbClass *class, CFDataRef primary_key); - -#if 0 -SecDbItemRef SecDbItemCreateWithRowId(CFAllocatorRef allocator, const SecDbClass *class, sqlite_int64 row_id, keybag_handle_t keybag, CFErrorRef *error); -#endif - -SecDbItemRef SecDbItemCopyWithUpdates(SecDbItemRef item, CFDictionaryRef updates, CFErrorRef *error); - -SecDbItemRef SecDbItemCopyTombstone(SecDbItemRef item, CFErrorRef *error); - -bool SecDbItemInsertOrReplace(SecDbItemRef item, SecDbConnectionRef dbconn, CFErrorRef *error, void(^duplicate)(SecDbItemRef item, SecDbItemRef *replace)); - -bool SecDbItemInsert(SecDbItemRef item, SecDbConnectionRef dbconn, CFErrorRef *error); - -bool SecDbItemDelete(SecDbItemRef item, SecDbConnectionRef dbconn, bool makeTombstone, CFErrorRef *error); - -// Low level update, just do the update -bool SecDbItemDoUpdate(SecDbItemRef old_item, SecDbItemRef new_item, SecDbConnectionRef dbconn, CFErrorRef *error, bool (^use_attr_in_where)(const SecDbAttr *attr)); - -// High level update, will replace tombstones and create them if needed. -bool SecDbItemUpdate(SecDbItemRef old_item, SecDbItemRef new_item, SecDbConnectionRef dbconn, bool makeTombstone, CFErrorRef *error); - -bool SecDbItemSelect(SecDbQueryRef query, SecDbConnectionRef dbconn, CFErrorRef *error, - bool (^use_attr_in_where)(const SecDbAttr *attr), - bool (^add_where_sql)(CFMutableStringRef sql, bool *needWhere), - bool (^bind_added_where)(sqlite3_stmt *stmt, int col), - void (^handle_row)(SecDbItemRef item, bool *stop)); - -CFStringRef SecDbItemCopySelectSQL(SecDbQueryRef query, - bool (^return_attr)(const SecDbAttr *attr), - bool (^use_attr_in_where)(const SecDbAttr *attr), - bool (^add_where_sql)(CFMutableStringRef sql, bool *needWhere)); -bool SecDbItemSelectBind(SecDbQueryRef query, sqlite3_stmt *stmt, CFErrorRef *error, - bool (^use_attr_in_where)(const SecDbAttr *attr), - bool (^bind_added_where)(sqlite3_stmt *stmt, int col)); - - -// MARK: - -// MARK: SQL Construction helpers -- These should become private in the future - -void SecDbAppendElement(CFMutableStringRef sql, CFStringRef value, bool *needComma); -void SecDbAppendWhereOrAnd(CFMutableStringRef sql, bool *needWhere); -void SecDbAppendWhereOrAndEquals(CFMutableStringRef sql, CFStringRef col, bool *needWhere); - -// MARK: - -// MARK: SecItemDb (a SecDb of SecDbItems) - -typedef struct SecItemDb *SecItemDbRef; -typedef struct SecItemDbConnection *SecItemDbConnectionRef; - -struct SecItemDb { - CFRuntimeBase _base; - SecDbRef db; - CFDictionaryRef classes; // className -> SecItemClass mapping -}; - -struct SecItemDbConnection { - SecDbConnectionRef db; -}; - -SecItemDbRef SecItemDbCreate(SecDbRef db); -SecItemDbRef SecItemDbRegisterClass(SecItemDbRef db, const SecDbClass *class, void(^upgrade)(SecDbItemRef item, uint32_t current_version)); - -SecItemDbConnectionRef SecItemDbAquireConnection(SecItemDbRef db); -void SecItemDbReleaseConnection(SecItemDbRef db, SecItemDbConnectionRef dbconn); - -bool SecItemDbInsert(SecItemDbConnectionRef dbconn, SecDbItemRef item, CFErrorRef *error); - -bool SecItemDbDelete(SecItemDbConnectionRef dbconn, SecDbItemRef item, CFErrorRef *error); - -// Low level update, just do the update -bool SecItemDbDoUpdate(SecItemDbConnectionRef dbconn, SecDbItemRef old_item, SecDbItemRef new_item, CFErrorRef *error, - bool (^use_attr_in_where)(const SecDbAttr *attr)); - -// High level update, will replace tombstones and create them if needed. -bool SecItemDbUpdate(SecItemDbConnectionRef dbconn, SecDbItemRef old_item, SecDbItemRef new_item, CFErrorRef *error); - -bool SecItemDbSelect(SecItemDbConnectionRef dbconn, SecDbQueryRef query, CFErrorRef *error, - bool (^use_attr_in_where)(const SecDbAttr *attr), - bool (^add_where_sql)(CFMutableStringRef sql, bool *needWhere), - bool (^bind_added_where)(sqlite3_stmt *stmt, int col), - void (^handle_row)(SecDbItemRef item, bool *stop)); - -// MARK: type converters. -// TODO: these should be static and private to SecDbItem, or part of the schema - -CFStringRef copyString(CFTypeRef obj); -CFDataRef copyData(CFTypeRef obj); -CFTypeRef copyBlob(CFTypeRef obj); -CFDataRef copySHA1(CFTypeRef obj); -CFTypeRef copyNumber(CFTypeRef obj); -CFDateRef copyDate(CFTypeRef obj); - -__END_DECLS - -#endif /* _SECURITYD_SECDBITEM_H_ */ diff --git a/sec/securityd/SecItemServer.c b/sec/securityd/SecItemServer.c deleted file mode 100644 index c6dec55c..00000000 --- a/sec/securityd/SecItemServer.c +++ /dev/null @@ -1,4446 +0,0 @@ -/* - * Copyright (c) 2006-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@ - */ - -/* - * SecItemServer.c - CoreFoundation-based constants and functions for - access to Security items (certificates, keys, identities, and - passwords.) - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "securityd_client.h" -#include "utilities/sqlutils.h" -#include "utilities/SecIOFormat.h" -#include "utilities/SecFileLocations.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include "OTATrustUtilities.h" - -#if USE_KEYSTORE -#include -#include -#if TARGET_OS_EMBEDDED -#include -#endif -#endif /* USE_KEYSTORE */ - - -/* 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 */ -#if USE_KEYSTORE -#if TARGET_OS_MAC && !TARGET_OS_EMBEDDED -static keybag_handle_t g_keychain_keybag = session_keybag_handle; -#else -static keybag_handle_t g_keychain_keybag = device_keybag_handle; -#endif -#else /* !USE_KEYSTORE */ -static int32_t g_keychain_keybag = 0; /* 0 == device_keybag_handle, constant dictated by AKS */ -#endif /* USE_KEYSTORE */ - -void SecItemServerSetKeychainKeybag(int32_t keybag) -{ - g_keychain_keybag=keybag; -} - -void SecItemServerResetKeychainKeybag(void) -{ -#if USE_KEYSTORE -#if TARGET_OS_MAC && !TARGET_OS_EMBEDDED - g_keychain_keybag = session_keybag_handle; -#else - g_keychain_keybag = device_keybag_handle; -#endif -#else /* !USE_KEYSTORE */ - g_keychain_keybag = 0; /* 0 == device_keybag_handle, constant dictated by AKS */ -#endif /* USE_KEYSTORE */ -} - -/* KEYBAG_NONE is private to security and have special meaning. - They should not collide with AppleKeyStore constants, but are only referenced - in here. - */ -#define KEYBAG_NONE (-1) /* Set q_keybag to KEYBAG_NONE to obtain cleartext data. */ -#define KEYBAG_DEVICE (g_keychain_keybag) /* actual keybag used to encrypt items */ - -/* Changed the name of the keychain changed notification, for testing */ -static const char *g_keychain_changed_notification = kSecServerKeychainChangedNotification; - -void SecItemServerSetKeychainChangedNotification(const char *notification_name) -{ - g_keychain_changed_notification = notification_name; -} - -/* label when certificate data is joined with key data */ -#define CERTIFICATE_DATA_COLUMN_LABEL "certdata" - -#define CURRENT_DB_VERSION 6 - -#define CLOSE_DB 0 - -/* Forward declaration of import export SPIs. */ -enum SecItemFilter { - kSecNoItemFilter, - kSecSysBoundItemFilter, - kSecBackupableItemFilter, -}; - -static CF_RETURNS_RETAINED CFDictionaryRef SecServerExportKeychainPlist(SecDbConnectionRef dbt, - keybag_handle_t src_keybag, keybag_handle_t dest_keybag, - enum SecItemFilter filter, CFErrorRef *error); -static bool SecServerImportKeychainInPlist(SecDbConnectionRef dbt, - keybag_handle_t src_keybag, keybag_handle_t dest_keybag, - CFDictionaryRef keychain, enum SecItemFilter filter, CFErrorRef *error); - -#if USE_KEYSTORE - -static bool hwaes_key_available(void) -{ - keybag_handle_t handle = bad_keybag_handle; - keybag_handle_t special_handle = bad_keybag_handle; -#if TARGET_OS_MAC && !TARGET_OS_EMBEDDED - special_handle = session_keybag_handle; -#elif TARGET_OS_EMBEDDED - special_handle = device_keybag_handle; -#endif - kern_return_t kr = aks_get_system(special_handle, &handle); - if (kr != kIOReturnSuccess) { -#if TARGET_OS_EMBEDDED - /* TODO: Remove this once the kext runs the daemon on demand if - there is no system keybag. */ - int kb_state = MKBGetDeviceLockState(NULL); - asl_log(NULL, NULL, ASL_LEVEL_INFO, "AppleKeyStore lock state: %d", kb_state); -#endif - } - return true; -} - -#else /* !USE_KEYSTORE */ - -static bool hwaes_key_available(void) -{ - return false; -} - -#endif /* USE_KEYSTORE */ - -// MARK - -// MARK Keychain version 6 schema - -#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) (__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) - -#define __FLAGS_ 0 -#define __FLAGS_P kSecDbPrimaryKeyFlag -#define __FLAGS_L kSecDbInFlag -#define __FLAGS_I kSecDbIndexFlag -#define __FLAGS_S kSecDbSHA1ValueInFlag -#define __FLAGS_A kSecDbReturnAttrFlag -#define __FLAGS_D kSecDbReturnDataFlag -#define __FLAGS_R kSecDbReturnRefFlag -#define __FLAGS_C kSecDbInCryptoDataFlag -#define __FLAGS_H kSecDbInHashFlag -#define __FLAGS_B kSecDbInBackupFlag -#define __FLAGS_Z kSecDbDefault0Flag -#define __FLAGS_E kSecDbDefaultEmptyFlag -#define __FLAGS_N kSecDbNotNullFlag - -// ,------------- P : Part of primary key -// / ,------------ L : Stored in local database -// / / ,----------- I : Attribute wants an index in the database -// / / / ,---------- S : SHA1 hashed attribute value in database (implies L) -// / / / / ,--------- A : Returned to client as attribute in queries -// / / / / / ,-------- D : Returned to client as data in queries -// / / / / / / ,------- R : Returned to client as ref/persistant ref in queries -// / / / / / / / ,------ C : Part of encrypted blob -// / / / / / / / / ,----- H : Attribute is part of item SHA1 hash (Implied by C) -// / / / / / / / / / ,---- B : Attribute is part of iTunes/iCloud backup bag -// / / / / / / / / / / ,--- Z : Attribute has a default value of 0 -// / / / / / / / / / / / ,-- E : Attribute has a default value of "" or empty data -// / / / / / / / / / / / / ,- N : Attribute must have a value -// / / / / / / / / / / / / / -// / / / / / / / / / / / / / -// | | | | | | | | | | | | | -// common to all | | | | | | | | | | | | | -SECDB_ATTR(v6rowid, "rowid", RowId, SecDbFlags( ,L, , , , ,R, , ,B, , , )); -SECDB_ATTR(v6cdat, "cdat", CreationDate, SecDbFlags( ,L, , ,A, , ,C,H, , , , )); -SECDB_ATTR(v6mdat, "mdat",ModificationDate,SecDbFlags( ,L, , ,A, , ,C,H, , , , )); -SECDB_ATTR(v6labl, "labl", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , )); -SECDB_ATTR(v6data, "data", EncryptedData, SecDbFlags( ,L, , , , , , , ,B, , , )); -SECDB_ATTR(v6agrp, "agrp", String, SecDbFlags(P,L, , ,A, , ,C,H, , , , )); -SECDB_ATTR(v6pdmn, "pdmn", Access, SecDbFlags( ,L, , ,A, , ,C,H, , , , )); -SECDB_ATTR(v6sync, "sync", Sync, SecDbFlags(P,L,I, ,A, , ,C,H, ,Z, ,N)); -SECDB_ATTR(v6tomb, "tomb", Tomb, SecDbFlags( ,L, , , , , ,C,H, ,Z, ,N)); -SECDB_ATTR(v6sha1, "sha1", SHA1, SecDbFlags( ,L,I, ,A, ,R, , , , , , )); -SECDB_ATTR(v6v_Data, "v_Data", Data, SecDbFlags( , , , , ,D, ,C,H, , , , )); -SECDB_ATTR(v6v_pk, "v_pk", PrimaryKey, SecDbFlags( , , , , , , , , , , , , )); -// genp and inet and keys | | | | | | | | | | | | | -SECDB_ATTR(v6crtr, "crtr", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , )); -SECDB_ATTR(v6alis, "alis", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , )); -// genp and inet | | | | | | | | | | | | | -SECDB_ATTR(v6desc, "desc", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , )); -SECDB_ATTR(v6icmt, "icmt", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , )); -SECDB_ATTR(v6type, "type", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , )); -SECDB_ATTR(v6invi, "invi", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , )); -SECDB_ATTR(v6nega, "nega", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , )); -SECDB_ATTR(v6cusi, "cusi", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , )); -SECDB_ATTR(v6prot, "prot", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , )); -SECDB_ATTR(v6scrp, "scrp", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , )); -SECDB_ATTR(v6acct, "acct", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N)); -// genp only | | | | | | | | | | | | | -SECDB_ATTR(v6svce, "svce", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N)); -SECDB_ATTR(v6gena, "gena", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , )); -// inet only | | | | | | | | | | | | | -SECDB_ATTR(v6sdmn, "sdmn", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N)); -SECDB_ATTR(v6srvr, "srvr", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N)); -SECDB_ATTR(v6ptcl, "ptcl", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N)); -SECDB_ATTR(v6atyp, "atyp", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N)); -SECDB_ATTR(v6port, "port", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N)); -SECDB_ATTR(v6path, "path", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N)); -// cert only | | | | | | | | | | | | | -SECDB_ATTR(v6ctyp, "ctyp", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N)); -SECDB_ATTR(v6cenc, "cenc", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , )); -SECDB_ATTR(v6subj, "subj", Data, SecDbFlags( ,L,I,S,A, , ,C,H, , , , )); -SECDB_ATTR(v6issr, "issr", Data, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N)); -SECDB_ATTR(v6slnr, "slnr", Data, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N)); -SECDB_ATTR(v6skid, "skid", Data, SecDbFlags( ,L,I,S,A, , ,C,H, , , , )); -SECDB_ATTR(v6pkhh, "pkhh", Data, SecDbFlags( ,L,I, ,A, , ,C,H, , , , )); -// cert attributes that share names with common ones but have different flags -SECDB_ATTR(v6certalis, "alis", Blob, SecDbFlags( ,L,I,S,A, , ,C,H, , , , )); -// keys only | | | | | | | | | | | | | -SECDB_ATTR(v6kcls, "kcls", Number, SecDbFlags(P,L,I,S,A, , ,C,H, ,Z, ,N)); -SECDB_ATTR(v6perm, "perm", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , )); -SECDB_ATTR(v6priv, "priv", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , )); -SECDB_ATTR(v6modi, "modi", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , )); -SECDB_ATTR(v6klbl, "klbl", Data, SecDbFlags(P,L,I, ,A, , ,C,H, , ,E,N)); -SECDB_ATTR(v6atag, "atag", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N)); -SECDB_ATTR(v6bsiz, "bsiz", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N)); -SECDB_ATTR(v6esiz, "esiz", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N)); -SECDB_ATTR(v6sdat, "sdat", Date, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N)); -SECDB_ATTR(v6edat, "edat", Date, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N)); -SECDB_ATTR(v6sens, "sens", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , )); -SECDB_ATTR(v6asen, "asen", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , )); -SECDB_ATTR(v6extr, "extr", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , )); -SECDB_ATTR(v6next, "next", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , )); -SECDB_ATTR(v6encr, "encr", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , )); -SECDB_ATTR(v6decr, "decr", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , )); -SECDB_ATTR(v6drve, "drve", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , )); -SECDB_ATTR(v6sign, "sign", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , )); -SECDB_ATTR(v6vrfy, "vrfy", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , )); -SECDB_ATTR(v6snrc, "snrc", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , )); -SECDB_ATTR(v6vyrc, "vyrc", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , )); -SECDB_ATTR(v6wrap, "wrap", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , )); -SECDB_ATTR(v6unwp, "unwp", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , )); -// 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)); -SECDB_ATTR(v6keycrtr, "crtr", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N)); - -static const SecDbClass genp_class = { - .name = CFSTR("genp"), - .attrs = { - &v6rowid, - &v6cdat, - &v6mdat, - &v6desc, - &v6icmt, - &v6crtr, - &v6type, - &v6scrp, - &v6labl, - &v6alis, - &v6invi, - &v6nega, - &v6cusi, - &v6prot, - &v6acct, - &v6svce, - &v6gena, - &v6data, - &v6agrp, - &v6pdmn, - &v6sync, - &v6tomb, - &v6sha1, - &v6v_Data, - &v6v_pk, - NULL - }, -}; - -static const SecDbClass inet_class = { - .name = CFSTR("inet"), - .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, - &v6v_Data, - &v6v_pk, - 0 - }, -}; - -static const SecDbClass cert_class = { - .name = CFSTR("cert"), - .attrs = { - &v6rowid, - &v6cdat, - &v6mdat, - &v6ctyp, - &v6cenc, - &v6labl, - &v6certalis, - &v6subj, - &v6issr, - &v6slnr, - &v6skid, - &v6pkhh, - &v6data, - &v6agrp, - &v6pdmn, - &v6sync, - &v6tomb, - &v6sha1, - &v6v_Data, - &v6v_pk, - 0 - }, -}; - -static const SecDbClass keys_class = { - .name = CFSTR("keys"), - .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, - &v6v_Data, - &v6v_pk, - 0 - } -}; - -/* An identity which is really a cert + a key, so all cert and keys attrs are - allowed. */ -static const SecDbClass identity_class = { - .name = CFSTR("idnt"), - .attrs = { - 0 - }, -}; - -static const SecDbAttr *SecDbAttrWithKey(const SecDbClass *c, - CFTypeRef key, - CFErrorRef *error) { - /* Special case: identites can have all attributes of either cert - or keys. */ - if (c == &identity_class) { - const SecDbAttr *desc; - if (!(desc = SecDbAttrWithKey(&cert_class, key, 0))) - desc = SecDbAttrWithKey(&keys_class, key, error); - return desc; - } - - if (isString(key)) { - SecDbForEachAttr(c, a) { - if (CFEqual(a->name, key)) - return a; - } - } - - SecError(errSecNoSuchAttr, error, CFSTR("attribute %@ not found in class %@"), key, c->name); - - return NULL; -} - -static bool kc_transaction(SecDbConnectionRef dbt, CFErrorRef *error, bool(^perform)()) { - __block bool ok = true; - return ok && SecDbTransaction(dbt, kSecDbExclusiveTransactionType, error, ^(bool *commit) { - ok = *commit = perform(); - }); -} - -static CFStringRef SecDbGetKindSQL(SecDbAttrKind kind) { - switch (kind) { - case kSecDbBlobAttr: - case kSecDbDataAttr: - case kSecDbSHA1Attr: - case kSecDbPrimaryKeyAttr: - case kSecDbEncryptedDataAttr: - return CFSTR("BLOB"); - case kSecDbAccessAttr: - case kSecDbStringAttr: - return CFSTR("TEXT"); - case kSecDbNumberAttr: - case kSecDbSyncAttr: - case kSecDbTombAttr: - return CFSTR("INTEGER"); - case kSecDbDateAttr: - case kSecDbCreationDateAttr: - case kSecDbModificationDateAttr: - return CFSTR("REAL"); - case kSecDbRowIdAttr: - return CFSTR("INTEGER PRIMARY KEY AUTOINCREMENT"); - } -} - -static void SecDbAppendUnqiue(CFMutableStringRef sql, CFStringRef value, bool *haveUnique) { - assert(haveUnique); - if (!*haveUnique) - CFStringAppend(sql, CFSTR("UNIQUE(")); - - SecDbAppendElement(sql, value, haveUnique); -} - -static void SecDbAppendCreateTableWithClass(CFMutableStringRef sql, const SecDbClass *c) { - CFStringAppendFormat(sql, 0, CFSTR("CREATE TABLE %@("), c->name); - SecDbForEachAttrWithMask(c,desc,kSecDbInFlag) { - CFStringAppendFormat(sql, 0, CFSTR("%@ %@"), desc->name, SecDbGetKindSQL(desc->kind)); - if (desc->flags & kSecDbNotNullFlag) - CFStringAppend(sql, CFSTR(" NOT NULL")); - if (desc->flags & kSecDbDefault0Flag) - CFStringAppend(sql, CFSTR(" DEFAULT 0")); - if (desc->flags & kSecDbDefaultEmptyFlag) - CFStringAppend(sql, CFSTR(" DEFAULT ''")); - CFStringAppend(sql, CFSTR(",")); - } - - bool haveUnique = false; - SecDbForEachAttrWithMask(c,desc,kSecDbPrimaryKeyFlag | kSecDbInFlag) { - SecDbAppendUnqiue(sql, desc->name, &haveUnique); - } - if (haveUnique) - CFStringAppend(sql, CFSTR(")")); - - CFStringAppend(sql, CFSTR(");")); -} - -static const char * const s3dl_upgrade_sql[] = { - /* 0 */ - "", - - /* 1 */ - /* Create indices. */ - "CREATE INDEX igsha ON genp(sha1);" - "CREATE INDEX iisha ON inet(sha1);" - "CREATE INDEX icsha ON cert(sha1);" - "CREATE INDEX iksha ON keys(sha1);" - "CREATE INDEX ialis ON cert(alis);" - "CREATE INDEX isubj ON cert(subj);" - "CREATE INDEX iskid ON cert(skid);" - "CREATE INDEX ipkhh ON cert(pkhh);" - "CREATE INDEX ikcls ON keys(kcls);" - "CREATE INDEX iklbl ON keys(klbl);" - "CREATE INDEX iencr ON keys(encr);" - "CREATE INDEX idecr ON keys(decr);" - "CREATE INDEX idrve ON keys(drve);" - "CREATE INDEX isign ON keys(sign);" - "CREATE INDEX ivrfy ON keys(vrfy);" - "CREATE INDEX iwrap ON keys(wrap);" - "CREATE INDEX iunwp ON keys(unwp);", - - /* 2 */ - "", - - /* 3 */ - /* Rename version 2 or version 3 tables and drop version table since - step 0 creates it. */ - "ALTER TABLE genp RENAME TO ogenp;" - "ALTER TABLE inet RENAME TO oinet;" - "ALTER TABLE cert RENAME TO ocert;" - "ALTER TABLE keys RENAME TO okeys;" - "DROP TABLE tversion;", - - /* 4 */ - "", - - /* 5 */ - "", - - /* 6 */ - "", - - /* 7 */ - /* Move data from version 5 tables to new ones and drop old ones. */ - "INSERT INTO genp (rowid,cdat,mdat,desc,icmt,crtr,type,scrp,labl,alis,invi,nega,cusi,prot,acct,svce,gena,data,agrp,pdmn) SELECT rowid,cdat,mdat,desc,icmt,crtr,type,scrp,labl,alis,invi,nega,cusi,prot,acct,svce,gena,data,agrp,pdmn from ogenp;" - "INSERT INTO inet (rowid,cdat,mdat,desc,icmt,crtr,type,scrp,labl,alis,invi,nega,cusi,prot,acct,sdmn,srvr,ptcl,atyp,port,path,data,agrp,pdmn) SELECT rowid,cdat,mdat,desc,icmt,crtr,type,scrp,labl,alis,invi,nega,cusi,prot,acct,sdmn,srvr,ptcl,atyp,port,path,data,agrp,pdmn from oinet;" - "INSERT INTO cert (rowid,cdat,mdat,ctyp,cenc,labl,alis,subj,issr,slnr,skid,pkhh,data,agrp,pdmn) SELECT rowid,cdat,mdat,ctyp,cenc,labl,alis,subj,issr,slnr,skid,pkhh,data,agrp,pdmn from ocert;" - "INSERT INTO keys (rowid,cdat,mdat,kcls,labl,alis,perm,priv,modi,klbl,atag,crtr,type,bsiz,esiz,sdat,edat,sens,asen,extr,next,encr,decr,drve,sign,vrfy,snrc,vyrc,wrap,unwp,data,agrp,pdmn) SELECT rowid,cdat,mdat,kcls,labl,alis,perm,priv,modi,klbl,atag,crtr,type,bsiz,esiz,sdat,edat,sens,asen,extr,next,encr,decr,drve,sign,vrfy,snrc,vyrc,wrap,unwp,data,agrp,pdmn from okeys;" - "DROP TABLE ogenp;" - "DROP TABLE oinet;" - "DROP TABLE ocert;" - "DROP TABLE okeys;" - "CREATE INDEX igsha ON genp(sha1);" - "CREATE INDEX iisha ON inet(sha1);" - "CREATE INDEX icsha ON cert(sha1);" - "CREATE INDEX iksha ON keys(sha1);", -}; - -struct sql_stages { - int pre; - int main; - int post; - bool init_pdmn; // If true do a full export followed by an import of the entire database so all items are re-encoded. -}; - -/* On disk database format version upgrade scripts. - If pre is 0, version is unsupported and db is considered corrupt for having that version. - First entry creates the current db, each susequent entry upgrade to current from the version - represented by the index of the slot. Each script is either -1 (disabled) of the number of - the script in the main table. - {pre,main,post, reencode} */ -static struct sql_stages s3dl_upgrade_script[] = { - { -1, 0, 1, false },/* 0->current: Create version 6 database. */ - {}, /* 1->current: Upgrade to version 6 from version 1 (LittleBear) -- Unsupported. */ - {}, /* 2->current: Upgrade to version 6 from version 2 (BigBearBeta) -- Unsupported */ - {}, /* 3->current: Upgrade to version 6 from version 3 (Apex) -- Unsupported */ - {}, /* 4->current: Upgrade to version 6 from version 4 (Telluride) -- Unsupported */ - { 3, 0, 7, true }, /* 5->current: Upgrade to version 6 from version 5 (TellurideGM). */ -}; - -static bool sql_run_script(SecDbConnectionRef dbt, int number, CFErrorRef *error) -{ - /* Script -1 == skip this step. */ - if (number < 0) - return true; - - /* If we are attempting to run a script we don't have, fail. */ - if ((size_t)number >= array_size(s3dl_upgrade_sql)) - return SecDbError(SQLITE_CORRUPT, error, CFSTR("script %d exceeds maximum %d"), - number, (int)(array_size(s3dl_upgrade_sql))); - __block bool ok = true; - if (number == 0) { - CFMutableStringRef sql = CFStringCreateMutable(0, 0); - SecDbAppendCreateTableWithClass(sql, &genp_class); - SecDbAppendCreateTableWithClass(sql, &inet_class); - SecDbAppendCreateTableWithClass(sql, &cert_class); - SecDbAppendCreateTableWithClass(sql, &keys_class); - CFStringAppend(sql, CFSTR("CREATE TABLE tversion(version INTEGER);INSERT INTO tversion(version) VALUES(6);")); - CFStringPerformWithCString(sql, ^(const char *sql_string) { - ok = SecDbErrorWithDb(sqlite3_exec(SecDbHandle(dbt), sql_string, NULL, NULL, NULL), - SecDbHandle(dbt), error, CFSTR("sqlite3_exec: %s"), sql_string); - }); - CFReleaseSafe(sql); - } else { - ok = SecDbErrorWithDb(sqlite3_exec(SecDbHandle(dbt), s3dl_upgrade_sql[number], NULL, NULL, NULL), - SecDbHandle(dbt), error, CFSTR("sqlite3_exec: %s"), s3dl_upgrade_sql[number]); - } - return ok; -} - -/* Return the current database version in *version. Returns a - SQLITE error. */ -static bool s3dl_dbt_get_version(SecDbConnectionRef dbt, int *version, CFErrorRef *error) -{ - CFStringRef sql = CFSTR("SELECT version FROM tversion LIMIT 1"); - return SecDbWithSQL(dbt, sql, error, ^(sqlite3_stmt *stmt) { - __block bool found_version = false; - bool step_ok = SecDbForEach(stmt, error, ^(int row_index __unused) { - if (!found_version) { - *version = sqlite3_column_int(stmt, 0); - found_version = true; - } - return found_version; - }); - if (!found_version) { - /* We have a tversion table but we didn't find a single version - value, now what? I suppose we pretend the db is corrupted - since this isn't supposed to ever happen. */ - step_ok = SecDbError(SQLITE_CORRUPT, error, CFSTR("Failed to read version: database corrupt")); - secwarning("SELECT version step: %@", error ? *error : NULL); - } - return step_ok; - }); -} - -static bool s3dl_dbt_upgrade_from_version(SecDbConnectionRef dbt, int version, CFErrorRef *error) -{ - /* We need to go from db version to CURRENT_DB_VERSION, let's do so. */ - __block bool ok = true; - /* O, guess we're done already. */ - if (version == CURRENT_DB_VERSION) - return ok; - - if (ok && version < 6) { - // Pre v6 keychains need to have WAL enabled, since SecDb only - // does this at db creation time. - // NOTE: This has to be run outside of a transaction. - ok = (SecDbExec(dbt, CFSTR("PRAGMA auto_vacuum = FULL"), error) && - SecDbExec(dbt, CFSTR("PRAGMA journal_mode = WAL"), error)); - } - - // Start a transaction to do the upgrade within - if (ok) { ok = SecDbTransaction(dbt, kSecDbExclusiveTransactionType, error, ^(bool *commit) { - // Be conservative and get the version again once we start a transaction. - int cur_version = version; - s3dl_dbt_get_version(dbt, &cur_version, NULL); - - /* If we are attempting to upgrade to a version greater than what we have - an upgrade script for, fail. */ - if (ok && (cur_version < 0 || - (size_t)cur_version >= array_size(s3dl_upgrade_script))) { - ok = SecDbError(SQLITE_CORRUPT, error, CFSTR("no upgrade script for version: %d"), cur_version); - secerror("no upgrade script for version %d", cur_version); - } - - struct sql_stages *script; - if (ok) { - script = &s3dl_upgrade_script[cur_version]; - if (script->pre == 0) - ok = SecDbError(SQLITE_CORRUPT, error, CFSTR("unsupported db version %d"), cur_version); - } - if (ok) - ok = sql_run_script(dbt, script->pre, error); - if (ok) - ok = sql_run_script(dbt, script->main, error); - if (ok) - ok = sql_run_script(dbt, script->post, error); - if (ok && script->init_pdmn) { - CFErrorRef localError = NULL; - CFDictionaryRef backup = SecServerExportKeychainPlist(dbt, - KEYBAG_DEVICE, KEYBAG_NONE, kSecNoItemFilter, &localError); - if (backup) { - if (localError) { - secerror("Ignoring export error: %@ during upgrade export", localError); - CFReleaseNull(localError); - } - ok = SecServerImportKeychainInPlist(dbt, KEYBAG_NONE, - KEYBAG_DEVICE, backup, kSecNoItemFilter, &localError); - CFRelease(backup); - } else { - ok = false; - - if (localError && CFErrorGetCode(localError) == errSecInteractionNotAllowed) { - SecError(errSecUpgradePending, error, - CFSTR("unable to complete upgrade due to device lock state")); - secerror("unable to complete upgrade due to device lock state"); - } else { - secerror("unable to complete upgrade for unknown reason, marking DB as corrupt: %@", localError); - SecDbCorrupt(dbt); - } - } - - if (localError) { - if (error && !*error) - *error = localError; - else - CFRelease(localError); - } - } else if (!ok) { - secerror("unable to complete upgrade scripts, marking DB as corrupt: %@", error ? *error : NULL); - SecDbCorrupt(dbt); - } - *commit = ok; - }); } else { - secerror("unable to complete upgrade scripts, marking DB as corrupt: %@", error ? *error : NULL); - SecDbCorrupt(dbt); - } - - return ok; -} - - -/* This function is called if the db doesn't have the proper version. We - start an exclusive transaction and recheck the version, and then perform - the upgrade within that transaction. */ -static bool s3dl_dbt_upgrade(SecDbConnectionRef dbt, CFErrorRef *error) -{ - // Already in a transaction - //return kc_transaction(dbt, error, ^{ - int version = 0; // Upgrade from version 0 == create new db - s3dl_dbt_get_version(dbt, &version, NULL); - return s3dl_dbt_upgrade_from_version(dbt, version, error); - //}); -} - -const uint32_t v0KeyWrapOverHead = 8; - -/* Wrap takes a 128 - 256 bit key as input and returns output of - inputsize + 64 bits. - In bytes this means that a - 16 byte (128 bit) key returns a 24 byte wrapped key - 24 byte (192 bit) key returns a 32 byte wrapped key - 32 byte (256 bit) key returns a 40 byte wrapped key */ -static bool ks_crypt(uint32_t selector, keybag_handle_t keybag, - keyclass_t keyclass, uint32_t textLength, const uint8_t *source, uint8_t *dest, size_t *dest_len, CFErrorRef *error) { -#if USE_KEYSTORE - kern_return_t kernResult = kIOReturnBadArgument; - - if (selector == kAppleKeyStoreKeyWrap) { - kernResult = aks_wrap_key(source, textLength, keyclass, keybag, dest, (int*)dest_len); - } else if (selector == kAppleKeyStoreKeyUnwrap) { - kernResult = aks_unwrap_key(source, textLength, keyclass, keybag, dest, (int*)dest_len); - } - - if (kernResult != KERN_SUCCESS) { - if ((kernResult == kIOReturnNotPermitted) || (kernResult == kIOReturnNotPrivileged)) { - /* Access to item attempted while keychain is locked. */ - return SecError(errSecInteractionNotAllowed, error, CFSTR("ks_crypt: %x failed to %s item (class %"PRId32", bag: %"PRId32") Access to item attempted while keychain is locked."), - kernResult, (selector == kAppleKeyStoreKeyWrap ? "wrap" : "unwrap"), keyclass, keybag); - } else if (kernResult == kIOReturnError) { - /* Item can't be decrypted on this device, ever, so drop the item. */ - return SecError(errSecDecode, error, CFSTR("ks_crypt: %x failed to %s item (class %"PRId32", bag: %"PRId32") Item can't be decrypted on this device, ever, so drop the item."), - kernResult, (selector == kAppleKeyStoreKeyWrap ? "wrap" : "unwrap"), keyclass, keybag); - } else { - return SecError(errSecNotAvailable, error, CFSTR("ks_crypt: %x failed to %s item (class %"PRId32", bag: %"PRId32")"), - kernResult, (selector == kAppleKeyStoreKeyWrap ? "wrap" : "unwrap"), keyclass, keybag); - } - } - return true; -#else /* !USE_KEYSTORE */ - if (selector == kAppleKeyStoreKeyWrap) { - /* The no encryption case. */ - if (*dest_len >= textLength + 8) { - memcpy(dest, source, textLength); - memset(dest + textLength, 8, 8); - *dest_len = textLength + 8; - } else - return SecError(errSecNotAvailable, error, CFSTR("ks_crypt: failed to wrap item (class %"PRId32")"), keyclass); - } else if (selector == kAppleKeyStoreKeyUnwrap) { - if (*dest_len + 8 >= textLength) { - memcpy(dest, source, textLength - 8); - *dest_len = textLength - 8; - } else - return SecError(errSecNotAvailable, error, CFSTR("ks_crypt: failed to unwrap item (class %"PRId32")"), keyclass); - } - return true; -#endif /* USE_KEYSTORE */ -} - - -CFDataRef kc_plist_copy_der(CFPropertyListRef plist, CFErrorRef *error) { - size_t len = der_sizeof_plist(plist, error); - CFMutableDataRef encoded = CFDataCreateMutable(0, len); - CFDataSetLength(encoded, len); - uint8_t *der_end = CFDataGetMutableBytePtr(encoded); - const uint8_t *der = der_end; - der_end += len; - der_end = der_encode_plist(plist, error, der, der_end); - if (!der_end) { - CFReleaseNull(encoded); - } else { - assert(!der_end || der_end == der); - } - return encoded; -} - -static CFDataRef kc_copy_digest(const struct ccdigest_info *di, size_t len, - const void *data, CFErrorRef *error) { - CFMutableDataRef digest = CFDataCreateMutable(0, di->output_size); - CFDataSetLength(digest, di->output_size); - ccdigest(di, len, data, CFDataGetMutableBytePtr(digest)); - return digest; -} - -CFDataRef kc_copy_sha1(size_t len, const void *data, CFErrorRef *error) { - return kc_copy_digest(ccsha1_di(), len, data, error); -} - -CFDataRef kc_copy_plist_sha1(CFPropertyListRef plist, CFErrorRef *error) { - CFDataRef der = kc_plist_copy_der(plist, error); - CFDataRef digest = NULL; - if (der) { - digest = kc_copy_sha1(CFDataGetLength(der), CFDataGetBytePtr(der), error); - CFRelease(der); - } - return digest; -} - -/* Given plainText create and return a CFDataRef containing: - BULK_KEY = RandomKey() - version || keyclass || KeyStore_WRAP(keyclass, BULK_KEY) || - AES(BULK_KEY, NULL_IV, plainText || padding) - */ -bool ks_encrypt_data(keybag_handle_t keybag, - keyclass_t keyclass, CFDataRef plainText, CFDataRef *pBlob, CFErrorRef *error) { - CFMutableDataRef blob = NULL; - bool ok = true; - //check(keybag >= 0); - - /* Precalculate output blob length. */ - const uint32_t bulkKeySize = 32; /* Use 256 bit AES key for bulkKey. */ - const uint32_t maxKeyWrapOverHead = 8 + 32; - uint8_t bulkKey[bulkKeySize]; - uint8_t bulkKeyWrapped[bulkKeySize + maxKeyWrapOverHead]; - size_t bulkKeyWrappedSize = sizeof(bulkKeyWrapped); - uint32_t key_wrapped_size; - - if (!plainText || CFGetTypeID(plainText) != CFDataGetTypeID() - || keyclass == 0) { - ok = SecError(errSecParam, error, CFSTR("ks_encrypt_data: invalid plain text")); - goto out; - } - - size_t ptLen = CFDataGetLength(plainText); - size_t ctLen = ptLen; - size_t tagLen = 16; - uint32_t version = 3; - - if (SecRandomCopyBytes(kSecRandomDefault, bulkKeySize, bulkKey)) { - ok = SecError(errSecAllocate, error, CFSTR("ks_encrypt_data: SecRandomCopyBytes failed")); - goto out; - } - - /* Now that we're done using the bulkKey, in place encrypt it. */ - require_quiet(ok = ks_crypt(kAppleKeyStoreKeyWrap, keybag, keyclass, - bulkKeySize, bulkKey, bulkKeyWrapped, - &bulkKeyWrappedSize, error), out); - key_wrapped_size = (uint32_t)bulkKeyWrappedSize; - - size_t blobLen = sizeof(version) + sizeof(keyclass) + - sizeof(key_wrapped_size) + key_wrapped_size + ctLen + tagLen; - - require_quiet(blob = CFDataCreateMutable(NULL, blobLen), out); - CFDataSetLength(blob, blobLen); - UInt8 *cursor = CFDataGetMutableBytePtr(blob); - - *((uint32_t *)cursor) = version; - cursor += sizeof(version); - - *((keyclass_t *)cursor) = keyclass; - cursor += sizeof(keyclass); - - *((uint32_t *)cursor) = key_wrapped_size; - cursor += sizeof(key_wrapped_size); - - memcpy(cursor, bulkKeyWrapped, key_wrapped_size); - cursor += key_wrapped_size; - - /* Encrypt the plainText with the bulkKey. */ - CCCryptorStatus ccerr = CCCryptorGCM(kCCEncrypt, kCCAlgorithmAES128, - bulkKey, bulkKeySize, - NULL, 0, /* iv */ - NULL, 0, /* auth data */ - CFDataGetBytePtr(plainText), ptLen, - cursor, - cursor + ctLen, &tagLen); - if (ccerr) { - ok = SecError(errSecInternal, error, CFSTR("ks_encrypt_data: CCCryptorGCM failed: %d"), ccerr); - goto out; - } - if (tagLen != 16) { - ok = SecError(errSecInternal, error, CFSTR("ks_encrypt_data: CCCryptorGCM expected: 16 got: %ld byte tag"), tagLen); - goto out; - } - -out: - memset(bulkKey, 0, sizeof(bulkKey)); - if (!ok) { - CFReleaseSafe(blob); - } else { - *pBlob = blob; - } - return ok; -} - -/* Given cipherText containing: - version || keyclass || KeyStore_WRAP(keyclass, BULK_KEY) || - AES(BULK_KEY, NULL_IV, plainText || padding) - return the plainText. */ -bool ks_decrypt_data(keybag_handle_t keybag, - keyclass_t *pkeyclass, CFDataRef blob, CFDataRef *pPlainText, - uint32_t *version_p, CFErrorRef *error) { - const uint32_t bulkKeySize = 32; /* Use 256 bit AES key for bulkKey. */ - uint8_t bulkKey[bulkKeySize]; - size_t bulkKeyCapacity = sizeof(bulkKey); - bool ok = true; - - CFMutableDataRef plainText = NULL; -#if USE_KEYSTORE -#if TARGET_OS_IPHONE - check(keybag >= 0); -#else - check((keybag >= 0) || (keybag == session_keybag_handle)); -#endif -#endif - - if (!blob) { - ok = SecError(errSecParam, error, CFSTR("ks_decrypt_data: invalid blob")); - goto out; - } - - size_t blobLen = CFDataGetLength(blob); - const uint8_t *cursor = CFDataGetBytePtr(blob); - uint32_t version; - keyclass_t keyclass; - uint32_t wrapped_key_size; - - /* Check for underflow, ensuring we have at least one full AES block left. */ - if (blobLen < sizeof(version) + sizeof(keyclass) + - bulkKeySize + v0KeyWrapOverHead + 16) { - ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: Check for underflow")); - goto out; - } - - version = *((uint32_t *)cursor); - cursor += sizeof(version); - - keyclass = *((keyclass_t *)cursor); - if (pkeyclass) - *pkeyclass = keyclass; - cursor += sizeof(keyclass); - - size_t minimum_blob_len = sizeof(version) + sizeof(keyclass) + 16; - size_t ctLen = blobLen - sizeof(version) - sizeof(keyclass); - size_t tagLen = 0; - switch (version) { - case 0: - wrapped_key_size = bulkKeySize + v0KeyWrapOverHead; - break; - case 2: - /* DROPTHROUGH */ - /* v2 and v3 have the same crypto, just different dictionary encodings. */ - case 3: - tagLen = 16; - minimum_blob_len -= 16; // Remove PKCS7 padding block requirement - ctLen -= tagLen; // Remove tagLen from ctLen - /* DROPTHROUGH */ - case 1: - wrapped_key_size = *((uint32_t *)cursor); - cursor += sizeof(wrapped_key_size); - minimum_blob_len += sizeof(wrapped_key_size); - ctLen -= sizeof(wrapped_key_size); - break; - default: - ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: invalid version %d"), version); - goto out; - } - - /* Validate key wrap length against total length */ - require(blobLen - minimum_blob_len - tagLen >= wrapped_key_size, out); - ctLen -= wrapped_key_size; - if (version < 2 && (ctLen & 0xF) != 0) { - ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: invalid version")); - goto out; - } - - /* Now unwrap the bulk key using a key in the keybag. */ - require_quiet(ok = ks_crypt(kAppleKeyStoreKeyUnwrap, keybag, - keyclass, wrapped_key_size, cursor, bulkKey, &bulkKeyCapacity, error), out); - cursor += wrapped_key_size; - - plainText = CFDataCreateMutable(NULL, ctLen); - if (!plainText) { - ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: failed to allocate data for plain text")); - goto out; - } - CFDataSetLength(plainText, ctLen); - - /* Decrypt the cipherText with the bulkKey. */ - CCCryptorStatus ccerr; - if (tagLen) { - uint8_t tag[tagLen]; - ccerr = CCCryptorGCM(kCCDecrypt, kCCAlgorithmAES128, - bulkKey, bulkKeySize, - NULL, 0, /* iv */ - NULL, 0, /* auth data */ - cursor, ctLen, - CFDataGetMutableBytePtr(plainText), - tag, &tagLen); - if (ccerr) { - /* TODO: Should this be errSecDecode once AppleKeyStore correctly - identifies uuid unwrap failures? */ - /* errSecInteractionNotAllowed; */ - ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: CCCryptorGCM failed: %d"), ccerr); - goto out; - } - if (tagLen != 16) { - ok = SecError(errSecInternal, error, CFSTR("ks_decrypt_data: CCCryptorGCM expected: 16 got: %ld byte tag"), tagLen); - goto out; - } - cursor += ctLen; - if (memcmp(tag, cursor, tagLen)) { - ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: CCCryptorGCM computed tag not same as tag in blob")); - goto out; - } - } else { - size_t ptLen; - ccerr = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, - bulkKey, bulkKeySize, NULL, cursor, ctLen, - CFDataGetMutableBytePtr(plainText), ctLen, &ptLen); - if (ccerr) { - /* TODO: Should this be errSecDecode once AppleKeyStore correctly - identifies uuid unwrap failures? */ - /* errSecInteractionNotAllowed; */ - ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: CCCrypt failed: %d"), ccerr); - goto out; - } - CFDataSetLength(plainText, ptLen); - } - if (version_p) *version_p = version; -out: - memset(bulkKey, 0, bulkKeySize); - if (!ok) { - CFReleaseSafe(plainText); - } else { - *pPlainText = plainText; - } - return ok; -} - -static bool use_hwaes() { - static bool use_hwaes; - static dispatch_once_t check_once; - dispatch_once(&check_once, ^{ - use_hwaes = hwaes_key_available(); - if (use_hwaes) { - asl_log(NULL, NULL, ASL_LEVEL_INFO, "using hwaes key"); - } else { - asl_log(NULL, NULL, ASL_LEVEL_ERR, "unable to access hwaes key"); - } - }); - return use_hwaes; -} - -/* Upper limit for number of keys in a QUERY dictionary. */ -#define QUERY_KEY_LIMIT_BASE (128) -#ifdef NO_SERVER -#define QUERY_KEY_LIMIT (31 + QUERY_KEY_LIMIT_BASE) -#else -#define QUERY_KEY_LIMIT QUERY_KEY_LIMIT_BASE -#endif - -/* Inline accessors to attr and match values in a query. */ -static inline CFIndex query_attr_count(const Query *q) -{ - return q->q_attr_end; -} - -static inline Pair query_attr_at(const Query *q, CFIndex ix) -{ - return q->q_pairs[ix]; -} - -static inline CFIndex query_match_count(const Query *q) -{ - return q->q_match_end - q->q_match_begin; -} - -static inline Pair query_match_at(const Query *q, CFIndex ix) -{ - return q->q_pairs[q->q_match_begin + ix]; -} - -/* Private routines used to parse a query. */ - -/* Sets q_keyclass based on value. */ -static void query_parse_keyclass(const void *value, Query *q) { - if (!isString(value)) { - SecError(errSecParam, &q->q_error, CFSTR("accessible attribute %@ not a string"), value); - return; - } else if (CFEqual(value, kSecAttrAccessibleWhenUnlocked)) { - q->q_keyclass = key_class_ak; - } else if (CFEqual(value, kSecAttrAccessibleAfterFirstUnlock)) { - q->q_keyclass = key_class_ck; - } else if (CFEqual(value, kSecAttrAccessibleAlways)) { - q->q_keyclass = key_class_dk; - } else if (CFEqual(value, kSecAttrAccessibleWhenUnlockedThisDeviceOnly)) { - q->q_keyclass = key_class_aku; - } else if (CFEqual(value, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly)) { - q->q_keyclass = key_class_cku; - } else if (CFEqual(value, kSecAttrAccessibleAlwaysThisDeviceOnly)) { - q->q_keyclass = key_class_dku; - } else { - SecError(errSecParam, &q->q_error, CFSTR("accessible attribute %@ unknown"), value); - return; - } - //q->q_keyclass_s = value; -} - -static const SecDbClass *kc_class_with_name(CFStringRef name) { - if (isString(name)) { -#if 0 - // TODO Iterate kc_db_classes and look for name == class->name. - // Or get clever and switch on first letter of class name and compare to verify - static const void *kc_db_classes[] = { - &genp_class, - &inet_class, - &cert_class, - &keys_class, - &identity_class - }; -#endif - if (CFEqual(name, kSecClassGenericPassword)) - return &genp_class; - else if (CFEqual(name, kSecClassInternetPassword)) - return &inet_class; - else if (CFEqual(name, kSecClassCertificate)) - return &cert_class; - else if (CFEqual(name, kSecClassKey)) - return &keys_class; - else if (CFEqual(name, kSecClassIdentity)) - return &identity_class; - } - return NULL; -} - -/* AUDIT[securityd](done): - key (ok) is a caller provided, string or number of length 4. - value (ok) is a caller provided, non NULL CFTypeRef. - */ -static void query_add_attribute_with_desc(const SecDbAttr *desc, const void *value, Query *q) -{ - if (CFEqual(desc->name, kSecAttrSynchronizable)) { - q->q_sync = true; - if (CFEqual(value, kSecAttrSynchronizableAny)) - return; /* skip the attribute so it isn't part of the search */ - } - - CFTypeRef attr = NULL; - switch (desc->kind) { - case kSecDbDataAttr: - attr = copyData(value); - break; - case kSecDbBlobAttr: - attr = copyBlob(value); - break; - case kSecDbDateAttr: - case kSecDbCreationDateAttr: - case kSecDbModificationDateAttr: - attr = copyDate(value); - break; - case kSecDbNumberAttr: - case kSecDbSyncAttr: - case kSecDbTombAttr: - attr = copyNumber(value); - break; - case kSecDbAccessAttr: - case kSecDbStringAttr: - attr = copyString(value); - break; - case kSecDbSHA1Attr: - attr = copySHA1(value); - break; - case kSecDbRowIdAttr: - case kSecDbPrimaryKeyAttr: - case kSecDbEncryptedDataAttr: - break; - } - - if (!attr) { - SecError(errSecItemInvalidValue, &q->q_error, CFSTR("attribute %@: value: %@ failed to convert"), desc->name, value); - return; - } - - /* Store plaintext attr data in q_item unless it's a kSecDbSHA1Attr. */ - if (q->q_item && desc->kind != kSecDbSHA1Attr) { - CFDictionarySetValue(q->q_item, desc->name, attr); - } - - if (CFEqual(desc->name, kSecAttrAccessible)) { - query_parse_keyclass(attr, q); - } - - /* Convert attr to (sha1) digest if requested. */ - if (desc->flags & kSecDbSHA1ValueInFlag) { - CFDataRef data = copyData(attr); - CFRelease(attr); - if (!data) { - SecError(errSecInternal, &q->q_error, CFSTR("failed to get attribute %@ data"), desc->name); - return; - } - - CFMutableDataRef digest = CFDataCreateMutable(0, CC_SHA1_DIGEST_LENGTH); - CFDataSetLength(digest, CC_SHA1_DIGEST_LENGTH); - /* 64 bits cast: worst case is we generate the wrong hash */ - assert((unsigned long)CFDataGetLength(data)q_pairs[q->q_attr_end].key = desc->name; - q->q_pairs[q->q_attr_end++].value = attr; -} - -static void query_add_attribute(const void *key, const void *value, Query *q) -{ - const SecDbAttr *desc = SecDbAttrWithKey(q->q_class, key, &q->q_error); - if (desc) - query_add_attribute_with_desc(desc, value, q); -} - -/* First remove key from q->q_pairs if it's present, then add the attribute again. */ -static void query_set_attribute_with_desc(const SecDbAttr *desc, const void *value, Query *q) { - if (CFDictionaryContainsKey(q->q_item, desc->name)) { - CFIndex ix; - for (ix = 0; ix < q->q_attr_end; ++ix) { - if (CFEqual(desc->name, q->q_pairs[ix].key)) { - CFReleaseSafe(q->q_pairs[ix].value); - --q->q_attr_end; - for (; ix < q->q_attr_end; ++ix) { - q->q_pairs[ix] = q->q_pairs[ix + 1]; - } - CFDictionaryRemoveValue(q->q_item, desc->name); - break; - } - } - } - query_add_attribute_with_desc(desc, value, q); -} - -/* AUDIT[securityd](done): - key (ok) is a caller provided, string starting with 'm'. - value (ok) is a caller provided, non NULL CFTypeRef. - */ -static void query_add_match(const void *key, const void *value, Query *q) -{ - /* Record the match key, value in q_pairs. */ - --(q->q_match_begin); - q->q_pairs[q->q_match_begin].key = key; - q->q_pairs[q->q_match_begin].value = value; - - if (CFEqual(kSecMatchLimit, key)) { - /* Figure out what the value for kSecMatchLimit is if specified. */ - if (CFGetTypeID(value) == CFNumberGetTypeID()) { - if (!CFNumberGetValue(value, kCFNumberCFIndexType, &q->q_limit)) - SecError(errSecItemInvalidValue, &q->q_error, CFSTR("failed to convert match limit %@ to CFIndex"), value); - } else if (CFEqual(kSecMatchLimitAll, value)) { - q->q_limit = kSecMatchUnlimited; - } else if (CFEqual(kSecMatchLimitOne, value)) { - q->q_limit = 1; - } else { - SecError(errSecItemInvalidValue, &q->q_error, CFSTR("unsupported match limit %@"), value); - } - } else if (CFEqual(kSecMatchIssuers, key) && - (CFGetTypeID(value) == CFArrayGetTypeID())) - { - CFMutableArrayRef canonical_issuers = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - if (canonical_issuers) { - CFIndex i, count = CFArrayGetCount(value); - for (i = 0; i < count; i++) { - CFTypeRef issuer_data = CFArrayGetValueAtIndex(value, i); - CFDataRef issuer_canonical = NULL; - if (CFDataGetTypeID() == CFGetTypeID(issuer_data)) - issuer_canonical = SecDistinguishedNameCopyNormalizedContent((CFDataRef)issuer_data); - if (issuer_canonical) { - CFArrayAppendValue(canonical_issuers, issuer_canonical); - CFRelease(issuer_canonical); - } - } - - if (CFArrayGetCount(canonical_issuers) > 0) { - q->q_match_issuer = canonical_issuers; - } else - CFRelease(canonical_issuers); - } - } -} - -static bool query_set_class(Query *q, CFStringRef c_name, CFErrorRef *error) { - const SecDbClass *value; - if (c_name && CFGetTypeID(c_name) == CFStringGetTypeID() && - (value = kc_class_with_name(c_name)) && - (q->q_class == 0 || q->q_class == value)) { - q->q_class = value; - return true; - } - - if (error && !*error) - SecError((c_name ? errSecNoSuchClass : errSecItemClassMissing), error, CFSTR("can find class named: %@"), c_name); - - - return false; -} - -static const SecDbClass *query_get_class(CFDictionaryRef query, CFErrorRef *error) { - CFStringRef c_name = NULL; - const void *value = CFDictionaryGetValue(query, kSecClass); - if (isString(value)) { - c_name = value; - } else { - value = CFDictionaryGetValue(query, kSecValuePersistentRef); - if (isData(value)) { - CFDataRef pref = value; - _SecItemParsePersistentRef(pref, &c_name, 0); - } - } - - if (c_name && (value = kc_class_with_name(c_name))) { - return value; - } else { - if (c_name) - SecError(errSecNoSuchClass, error, CFSTR("can't find class named: %@"), c_name); - else - SecError(errSecItemClassMissing, error, CFSTR("query missing class name")); - return NULL; - } -} - -/* AUDIT[securityd](done): - key (ok) is a caller provided, string starting with 'c'. - value (ok) is a caller provided, non NULL CFTypeRef. - */ -static void query_add_class(const void *key, const void *value, Query *q) -{ - if (CFEqual(key, kSecClass)) { - query_set_class(q, value, &q->q_error); - } else { - SecError(errSecItemInvalidKey, &q->q_error, CFSTR("add_class: key %@ is not %@"), key, kSecClass); - } -} - -/* AUDIT[securityd](done): - key (ok) is a caller provided, string starting with 'r'. - value (ok) is a caller provided, non NULL CFTypeRef. - */ -static void query_add_return(const void *key, const void *value, Query *q) -{ - ReturnTypeMask mask; - if (CFGetTypeID(value) != CFBooleanGetTypeID()) { - SecError(errSecItemInvalidValue, &q->q_error, CFSTR("add_return: value %@ is not CFBoolean"), value); - return; - } - - int set_it = CFEqual(value, kCFBooleanTrue); - - if (CFEqual(key, kSecReturnData)) - mask = kSecReturnDataMask; - else if (CFEqual(key, kSecReturnAttributes)) - mask = kSecReturnAttributesMask; - else if (CFEqual(key, kSecReturnRef)) - mask = kSecReturnRefMask; - else if (CFEqual(key, kSecReturnPersistentRef)) - mask = kSecReturnPersistentRefMask; - else { - SecError(errSecItemInvalidKey, &q->q_error, CFSTR("add_return: unknown key %@"), key); - return; - } - - if ((q->q_return_type & mask) && !set_it) { - /* Clear out this bit (it's set so xor with the mask will clear it). */ - q->q_return_type ^= mask; - } else if (!(q->q_return_type & mask) && set_it) { - /* Set this bit. */ - q->q_return_type |= mask; - } -} - -/* AUDIT[securityd](done): - key (ok) is a caller provided, string starting with 'u'. - value (ok since q_use_item_list is unused) is a caller provided, non - NULL CFTypeRef. - */ -static void query_add_use(const void *key, const void *value, Query *q) -{ - if (CFEqual(key, kSecUseItemList)) { - /* TODO: Add sanity checking when we start using this. */ - q->q_use_item_list = value; - } else if (CFEqual(key, kSecUseTombstones)) { - if (CFGetTypeID(value) == CFBooleanGetTypeID()) { - q->q_use_tomb = value; - } else if (CFGetTypeID(value) == CFNumberGetTypeID()) { - q->q_use_tomb = CFBooleanGetValue(value) ? kCFBooleanTrue : kCFBooleanFalse; - } else if (CFGetTypeID(value) == CFStringGetTypeID()) { - q->q_use_tomb = CFStringGetIntValue(value) ? kCFBooleanTrue : kCFBooleanFalse; - } else { - SecError(errSecItemInvalidValue, &q->q_error, CFSTR("add_use: value %@ for key %@ is neither CFBoolean nor CFNumber"), 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) */ - } else { - SecError(errSecItemInvalidKey, &q->q_error, CFSTR("add_use: unknown key %@"), key); - return; - } -} - -static void query_set_data(const void *value, Query *q) { - if (!isData(value)) { - SecError(errSecItemInvalidValue, &q->q_error, CFSTR("set_data: value %@ is not type data"), value); - } else { - q->q_data = value; - if (q->q_item) - CFDictionarySetValue(q->q_item, kSecValueData, value); - } -} - -/* AUDIT[securityd](done): - key (ok) is a caller provided, string starting with 'u'. - value (ok) is a caller provided, non NULL CFTypeRef. - */ -static void query_add_value(const void *key, const void *value, Query *q) -{ - if (CFEqual(key, kSecValueData)) { - query_set_data(value, q); -#ifdef NO_SERVER - } else if (CFEqual(key, kSecValueRef)) { - q->q_ref = value; - /* TODO: Add value type sanity checking. */ -#endif - } else if (CFEqual(key, kSecValuePersistentRef)) { - CFStringRef c_name; - if (_SecItemParsePersistentRef(value, &c_name, &q->q_row_id)) - query_set_class(q, c_name, &q->q_error); - else - SecError(errSecItemInvalidValue, &q->q_error, CFSTR("add_value: value %@ is not a valid persitent ref"), value); - } else { - SecError(errSecItemInvalidKey, &q->q_error, CFSTR("add_value: unknown key %@"), key); - return; - } -} - -/* AUDIT[securityd](done): - key (ok) is a caller provided, unchecked. - value (ok) is a caller provided, unchecked. - */ -static void query_update_applier(const void *key, const void *value, - void *context) -{ - Query *q = (Query *)context; - /* If something went wrong there is no point processing any more args. */ - if (q->q_error) - return; - - /* Make sure we have a string key. */ - if (!isString(key)) { - SecError(errSecItemInvalidKeyType, &q->q_error, CFSTR("update_applier: unknown key type %@"), key); - return; - } - - if (!value) { - SecError(errSecItemInvalidValue, &q->q_error, CFSTR("update_applier: key %@ has NULL value"), key); - return; - } - - if (CFEqual(key, kSecValueData)) { - query_set_data(value, q); - } else { - query_add_attribute(key, value, q); - } -} - -/* AUDIT[securityd](done): - key (ok) is a caller provided, unchecked. - value (ok) is a caller provided, unchecked. - */ -static void query_applier(const void *key, const void *value, void *context) -{ - Query *q = (Query *)context; - /* If something went wrong there is no point processing any more args. */ - if (q->q_error) - return; - - /* Make sure we have a key. */ - if (!key) { - SecError(errSecItemInvalidKeyType, &q->q_error, CFSTR("applier: NULL key")); - return; - } - - /* Make sure we have a value. */ - if (!value) { - SecError(errSecItemInvalidValue, &q->q_error, CFSTR("applier: key %@ has NULL value"), key); - return; - } - - /* Figure out what type of key we are dealing with. */ - CFTypeID key_id = CFGetTypeID(key); - if (key_id == CFStringGetTypeID()) { - CFIndex key_len = CFStringGetLength(key); - /* String keys can be different things. The subtype is determined by: - length 4 strings are all attributes. Otherwise the first char - determines the type: - c: class must be kSecClass - m: match like kSecMatchPolicy - r: return like kSecReturnData - u: use keys - v: value - */ - if (key_len == 4) { - /* attributes */ - query_add_attribute(key, value, q); - } else if (key_len > 1) { - UniChar k_first_char = CFStringGetCharacterAtIndex(key, 0); - switch (k_first_char) - { - case 'c': /* class */ - query_add_class(key, value, q); - break; - case 'm': /* match */ - query_add_match(key, value, q); - break; - case 'r': /* return */ - query_add_return(key, value, q); - break; - case 'u': /* use */ - query_add_use(key, value, q); - break; - case 'v': /* value */ - query_add_value(key, value, q); - break; - default: - SecError(errSecItemInvalidKey, &q->q_error, CFSTR("applier: key %@ invalid"), key); - break; - } - } else { - SecError(errSecItemInvalidKey, &q->q_error, CFSTR("applier: key %@ invalid length"), key); - } - } else if (key_id == CFNumberGetTypeID()) { - /* Numeric keys are always (extended) attributes. */ - /* TODO: Why is this here? query_add_attribute() doesn't take numbers. */ - query_add_attribute(key, value, q); - } else { - /* We only support string and number type keys. */ - SecError(errSecItemInvalidKeyType, &q->q_error, CFSTR("applier: key %@ neither string nor number"), key); - } -} - -static CFStringRef query_infer_keyclass(Query *q, CFStringRef agrp) { - /* apsd and lockdown are always dku. */ - if (CFEqual(agrp, CFSTR("com.apple.apsd")) - || CFEqual(agrp, CFSTR("lockdown-identities"))) { - return kSecAttrAccessibleAlwaysThisDeviceOnly; - } - /* All other certs or in the apple agrp is dk. */ - if (q->q_class == &cert_class) { - /* third party certs are always dk. */ - return kSecAttrAccessibleAlways; - } - /* The rest defaults to ak. */ - return kSecAttrAccessibleWhenUnlocked; -} - -static void query_ensure_keyclass(Query *q, CFStringRef agrp) { - if (q->q_keyclass == 0) { - CFStringRef accessible = query_infer_keyclass(q, agrp); - query_add_attribute(kSecAttrAccessible, accessible, q); - } -} - -static bool query_error(Query *q, CFErrorRef *error) { - if (q->q_error) { - CFErrorRef tmp = q->q_error; - q->q_error = NULL; - if (error && !*error) { - *error = tmp; - } else { - CFRelease(tmp); - } - return false; - } - return true; -} - -bool query_destroy(Query *q, CFErrorRef *error) { - bool ok = query_error(q, error); - CFIndex ix, attr_count = query_attr_count(q); - for (ix = 0; ix < attr_count; ++ix) { - CFReleaseSafe(query_attr_at(q, ix).value); - } - CFReleaseSafe(q->q_item); - CFReleaseSafe(q->q_primary_key_digest); - CFReleaseSafe(q->q_match_issuer); - - free(q); - return ok; -} - -static void SecKeychainChanged(bool syncWithPeers) { - uint32_t result = notify_post(g_keychain_changed_notification); - if (syncWithPeers) - SOSCCSyncWithAllPeers(); - if (result == NOTIFY_STATUS_OK) - secnotice("item", "Sent %s%s", syncWithPeers ? "SyncWithAllPeers and " : "", g_keychain_changed_notification); - else - secerror("%snotify_post %s returned: %" PRIu32, syncWithPeers ? "Sent SyncWithAllPeers, " : "", g_keychain_changed_notification, result); -} - -static bool query_notify_and_destroy(Query *q, bool ok, CFErrorRef *error) { - if (ok && !q->q_error && q->q_sync_changed) { - SecKeychainChanged(true); - } - return query_destroy(q, error) && ok; -} - -/* Allocate and initialize a Query object for query. */ -Query *query_create(const SecDbClass *qclass, CFDictionaryRef query, - CFErrorRef *error) -{ - if (!qclass) { - if (error && !*error) - SecError(errSecItemClassMissing, error, CFSTR("Missing class")); - return NULL; - } - - /* 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. */ - CFIndex key_count = SecDbClassAttrCount(qclass); - if (key_count == 0) { - // Identities claim to have 0 attributes, but they really support any keys or cert attribute. - key_count = SecDbClassAttrCount(&cert_class) + SecDbClassAttrCount(&keys_class); - } - - if (query) { - key_count += CFDictionaryGetCount(query); - SecDbForEachAttr(qclass, attr) { - if (CFDictionaryContainsKey(query, attr->name)) - --key_count; - } - } - - if (key_count > QUERY_KEY_LIMIT) { - if (error && !*error) - { - secerror("key_count: %ld, QUERY_KEY_LIMIT: %d", (long)key_count, QUERY_KEY_LIMIT); - SecError(errSecItemIllegalQuery, error, CFSTR("Past query key limit")); - } - return NULL; - } - - Query *q = calloc(1, sizeof(Query) + sizeof(Pair) * key_count); - if (q == NULL) { - if (error && !*error) - SecError(errSecAllocate, error, CFSTR("Out of memory")); - return NULL; - } - - q->q_keybag = KEYBAG_DEVICE; - q->q_class = qclass; - q->q_match_begin = q->q_match_end = key_count; - q->q_item = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - return q; -} - -/* Parse query for a Query object q. */ -static bool query_parse_with_applier(Query *q, CFDictionaryRef query, - CFDictionaryApplierFunction applier, - CFErrorRef *error) { - CFDictionaryApplyFunction(query, applier, q); - return query_error(q, error); -} - -/* Parse query for a Query object q. */ -static bool query_parse(Query *q, CFDictionaryRef query, - CFErrorRef *error) { - return query_parse_with_applier(q, query, query_applier, error); -} - -/* Parse query for a Query object q. */ -static bool query_update_parse(Query *q, CFDictionaryRef update, - CFErrorRef *error) { - return query_parse_with_applier(q, update, query_update_applier, error); -} - -static Query *query_create_with_limit(CFDictionaryRef query, CFIndex limit, - CFErrorRef *error) { - Query *q; - q = query_create(query_get_class(query, error), query, error); - if (q) { - q->q_limit = limit; - if (!query_parse(q, query, error)) { - query_destroy(q, error); - return NULL; - } - if (!q->q_sync && !q->q_row_id) { - /* query did not specify a kSecAttrSynchronizable attribute, - * and did not contain a persistent reference. */ - query_add_attribute(kSecAttrSynchronizable, kCFBooleanFalse, q); - } - } - return q; -} - - -//TODO: Move this to SecDbItemRef - -/* Make sure all attributes that are marked as not_null have a value. If - force_date is false, only set mdat and cdat if they aren't already set. */ -static void -query_pre_add(Query *q, bool force_date) { - CFDateRef now = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); - SecDbForEachAttrWithMask(q->q_class, desc, kSecDbInFlag) { - if (desc->kind == kSecDbCreationDateAttr || - desc->kind == kSecDbModificationDateAttr) { - if (force_date) { - query_set_attribute_with_desc(desc, now, q); - } else if (!CFDictionaryContainsKey(q->q_item, desc->name)) { - query_add_attribute_with_desc(desc, now, q); - } - } else if ((desc->flags & kSecDbNotNullFlag) && - !CFDictionaryContainsKey(q->q_item, desc->name)) { - CFTypeRef value = NULL; - if (desc->flags & kSecDbDefault0Flag) { - if (desc->kind == kSecDbDateAttr) - value = CFDateCreate(kCFAllocatorDefault, 0.0); - else { - SInt32 vzero = 0; - value = CFNumberCreate(0, kCFNumberSInt32Type, &vzero); - } - } else if (desc->flags & kSecDbDefaultEmptyFlag) { - if (desc->kind == kSecDbDataAttr) - value = CFDataCreate(kCFAllocatorDefault, NULL, 0); - else { - value = CFSTR(""); - CFRetain(value); - } - } - if (value) { - /* Safe to use query_add_attribute here since the attr wasn't - set yet. */ - query_add_attribute_with_desc(desc, value, q); - CFRelease(value); - } - } - } - CFReleaseSafe(now); -} - -//TODO: Move this to SecDbItemRef - -/* Update modification_date if needed. */ -static void -query_pre_update(Query *q) { - SecDbForEachAttr(q->q_class, desc) { - if (desc->kind == kSecDbModificationDateAttr) { - CFDateRef now = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); - query_set_attribute_with_desc(desc, now, q); - CFReleaseSafe(now); - } - } -} - -/* AUDIT[securityd](done): - accessGroup (ok) is a caller provided, non NULL CFTypeRef. - - Return true iff accessGroup is allowable according to accessGroups. - */ -static bool accessGroupsAllows(CFArrayRef accessGroups, - CFStringRef accessGroup) { - /* NULL accessGroups is wildcard. */ - if (!accessGroups) - return true; - /* Make sure we have a string. */ - if (!isString(accessGroup)) - return false; - - /* Having the special accessGroup "*" allows access to all accessGroups. */ - CFRange range = { 0, CFArrayGetCount(accessGroups) }; - if (range.length && - (CFArrayContainsValue(accessGroups, range, accessGroup) || - CFArrayContainsValue(accessGroups, range, CFSTR("*")))) - return true; - - return false; -} - -static bool itemInAccessGroup(CFDictionaryRef item, CFArrayRef accessGroups) { - return accessGroupsAllows(accessGroups, - CFDictionaryGetValue(item, kSecAttrAccessGroup)); -} - -static void s3dl_merge_into_dict(const void *key, const void *value, void *context) { - CFDictionarySetValue(context, key, value); -} - -/* Return whatever the caller requested based on the value of q->q_return_type. - keys and values must be 3 larger than attr_count in size to accomadate the - optional data, class and persistent ref results. This is so we can use - the CFDictionaryCreate() api here rather than appending to a - mutable dictionary. */ -static CFTypeRef handle_result(Query *q, CFMutableDictionaryRef item, - sqlite_int64 rowid) { - CFTypeRef a_result; - CFDataRef data; - data = CFDictionaryGetValue(item, kSecValueData); - if (q->q_return_type == 0) { - /* Caller isn't interested in any results at all. */ - a_result = kCFNull; - } else if (q->q_return_type == kSecReturnDataMask) { - if (data) { - a_result = data; - CFRetain(a_result); - } else { - a_result = CFDataCreate(kCFAllocatorDefault, NULL, 0); - } - } else if (q->q_return_type == kSecReturnPersistentRefMask) { - a_result = _SecItemMakePersistentRef(q->q_class->name, rowid); - } else { - /* We need to return more than one value. */ - if (q->q_return_type & kSecReturnRefMask) { - CFDictionarySetValue(item, kSecClass, q->q_class->name); - } else if ((q->q_return_type & kSecReturnAttributesMask)) { - if (!(q->q_return_type & kSecReturnDataMask)) { - CFDictionaryRemoveValue(item, kSecValueData); - } - } else { - if (data) - CFRetain(data); - CFDictionaryRemoveAllValues(item); - if ((q->q_return_type & kSecReturnDataMask) && data) { - CFDictionarySetValue(item, kSecValueData, data); - CFRelease(data); - } - } - if (q->q_return_type & kSecReturnPersistentRefMask) { - CFDataRef pref = _SecItemMakePersistentRef(q->q_class->name, rowid); - CFDictionarySetValue(item, kSecValuePersistentRef, pref); - CFRelease(pref); - } - - a_result = item; - CFRetain(item); - } - - return a_result; -} - -static CFDataRef SecDbItemMakePersistentRef(SecDbItemRef item, CFErrorRef *error) { - sqlite3_int64 row_id = SecDbItemGetRowId(item, error); - if (row_id) - return _SecItemMakePersistentRef(SecDbItemGetClass(item)->name, row_id); - return NULL; -} - -static CFTypeRef SecDbItemCopyResult(SecDbItemRef item, ReturnTypeMask return_type, CFErrorRef *error) { - CFTypeRef a_result; - - if (return_type == 0) { - /* Caller isn't interested in any results at all. */ - a_result = kCFNull; - } else if (return_type == kSecReturnDataMask) { - a_result = SecDbItemGetCachedValueWithName(item, kSecValueData); - if (a_result) { - CFRetainSafe(a_result); - } else { - a_result = CFDataCreate(kCFAllocatorDefault, NULL, 0); - } - } else if (return_type == kSecReturnPersistentRefMask) { - a_result = SecDbItemMakePersistentRef(item, error); - } else { - CFMutableDictionaryRef dict = CFDictionaryCreateMutableForCFTypes(CFGetAllocator(item)); - /* We need to return more than one value. */ - if (return_type & kSecReturnRefMask) { - CFDictionarySetValue(dict, kSecClass, SecDbItemGetClass(item)->name); - } - CFOptionFlags mask = (((return_type & kSecReturnDataMask || return_type & kSecReturnRefMask) ? kSecDbReturnDataFlag : 0) | - ((return_type & kSecReturnAttributesMask || return_type & kSecReturnRefMask) ? kSecDbReturnAttrFlag : 0)); - SecDbForEachAttr(SecDbItemGetClass(item), desc) { - if ((desc->flags & mask) != 0) { - CFTypeRef value = SecDbItemGetValue(item, desc, error); - if (value && !CFEqual(kCFNull, value)) { - CFDictionarySetValue(dict, desc->name, value); - } else if (value == NULL) { - CFReleaseNull(dict); - break; - } - } - } - if (return_type & kSecReturnPersistentRefMask) { - CFDataRef pref = SecDbItemMakePersistentRef(item, error); - CFDictionarySetValue(dict, kSecValuePersistentRef, pref); - CFRelease(pref); - } - - a_result = dict; - } - - return a_result; -} - - -// MARK: - -// MARK: Forward declarations - -static CFMutableDictionaryRef -s3dl_item_from_col(sqlite3_stmt *stmt, Query *q, int col, - CFArrayRef accessGroups, keyclass_t *keyclass, CFErrorRef *error); - -/* AUDIT[securityd](done): - attributes (ok) is a caller provided dictionary, only its cf type has - been checked. - */ -static bool -s3dl_query_add(SecDbConnectionRef dbt, Query *q, CFTypeRef *result, CFErrorRef *error) -{ - if (query_match_count(q) != 0) - return errSecItemMatchUnsupported; - - /* Add requires a class to be specified unless we are adding a ref. */ - if (q->q_use_item_list) - return errSecUseItemListUnsupported; - - /* Actual work here. */ - SecDbItemRef item = SecDbItemCreateWithAttributes(kCFAllocatorDefault, q->q_class, q->q_item, KEYBAG_DEVICE, error); - if (!item) - return false; - - bool ok = true; - if (q->q_data) - ok = SecDbItemSetValueWithName(item, CFSTR("v_Data"), q->q_data, error); - if (q->q_row_id) - ok = SecDbItemSetRowId(item, q->q_row_id, error); - - if (ok) - ok = SecDbItemInsert(item, dbt, error); - if (ok) { - if (result && q->q_return_type) { - *result = SecDbItemCopyResult(item, q->q_return_type, error); - } - } - if (!ok && error && *error) { - if (CFEqual(CFErrorGetDomain(*error), kSecDbErrorDomain) && CFErrorGetCode(*error) == SQLITE_CONSTRAINT) { - CFReleaseNull(*error); - SecError(errSecDuplicateItem, error, CFSTR("duplicate item %@"), item); - } - } - - if (ok) { - q->q_changed = true; - if (SecDbItemIsSyncable(item)) - q->q_sync_changed = true; - } - - secdebug("dbitem", "inserting item %@%s%@", item, ok ? "" : "failed: ", ok || error == NULL ? (CFErrorRef)CFSTR("") : *error); - - CFRelease(item); - - return ok; -} - -typedef void (*s3dl_handle_row)(sqlite3_stmt *stmt, void *context); - -/* Return a (mutable) dictionary if plist is a dictionary, return NULL and set error otherwise. Does nothing if plist is already NULL. */ -static CFMutableDictionaryRef dictionaryFromPlist(CFPropertyListRef plist, CFErrorRef *error) { - if (plist && !isDictionary(plist)) { - CFStringRef typeName = CFCopyTypeIDDescription(CFGetTypeID((CFTypeRef)plist)); - SecError(errSecDecode, error, CFSTR("plist is a %@, expecting a dictionary"), typeName); - CFReleaseSafe(typeName); - CFReleaseNull(plist); - } - return (CFMutableDictionaryRef)plist; -} - -static CFMutableDictionaryRef s3dl_item_v2_decode(CFDataRef plain, CFErrorRef *error) { - CFPropertyListRef item; - item = CFPropertyListCreateWithData(0, plain, kCFPropertyListMutableContainers, NULL, error); - return dictionaryFromPlist(item, error); -} - -static CFMutableDictionaryRef s3dl_item_v3_decode(CFDataRef plain, CFErrorRef *error) { - CFPropertyListRef item = NULL; - const uint8_t *der = CFDataGetBytePtr(plain); - const uint8_t *der_end = der + CFDataGetLength(plain); - der = der_decode_plist(0, kCFPropertyListMutableContainers, &item, error, der, der_end); - if (der && der != der_end) { - SecCFCreateError(errSecDecode, kSecErrorDomain, CFSTR("trailing garbage at end of decrypted item"), NULL, error); - CFReleaseNull(item); - } - return dictionaryFromPlist(item, error); -} - -static CFMutableDictionaryRef -s3dl_item_from_data(CFDataRef edata, Query *q, CFArrayRef accessGroups, keyclass_t *keyclass, CFErrorRef *error) { - CFMutableDictionaryRef item = NULL; - CFDataRef plain = NULL; - - /* Decrypt and decode the item and check the decoded attributes against the query. */ - uint32_t version; - require_quiet((ks_decrypt_data(q->q_keybag, keyclass, edata, &plain, &version, error)), out); - if (version < 2) { - goto out; - } - - if (version < 3) { - item = s3dl_item_v2_decode(plain, error); - } else { - item = s3dl_item_v3_decode(plain, error); - } - - if (!item && plain) { - secerror("decode v%d failed: %@ [item: %@]", version, error ? *error : NULL, plain); - } - if (item && !itemInAccessGroup(item, accessGroups)) { - secerror("items accessGroup %@ not in %@", - CFDictionaryGetValue(item, kSecAttrAccessGroup), - accessGroups); - CFReleaseNull(item); - } - /* TODO: Validate keyclass attribute. */ - -out: - CFReleaseSafe(plain); - return item; -} - -static CFDataRef -s3dl_copy_data_from_col(sqlite3_stmt *stmt, int col, CFErrorRef *error) { - return CFDataCreateWithBytesNoCopy(0, sqlite3_column_blob(stmt, col), - sqlite3_column_bytes(stmt, col), - kCFAllocatorNull); -} - -static CFMutableDictionaryRef -s3dl_item_from_col(sqlite3_stmt *stmt, Query *q, int col, - CFArrayRef accessGroups, keyclass_t *keyclass, CFErrorRef *error) { - CFMutableDictionaryRef item = NULL; - CFDataRef edata = NULL; - require(edata = s3dl_copy_data_from_col(stmt, col, error), out); - item = s3dl_item_from_data(edata, q, accessGroups, keyclass, error); - -out: - CFReleaseSafe(edata); - return item; -} - -struct s3dl_query_ctx { - Query *q; - CFArrayRef accessGroups; - CFTypeRef result; - int found; -}; - -static bool match_item(Query *q, CFArrayRef accessGroups, CFDictionaryRef item); - -static void s3dl_query_row(sqlite3_stmt *stmt, void *context) { - struct s3dl_query_ctx *c = context; - Query *q = c->q; - - CFMutableDictionaryRef item = s3dl_item_from_col(stmt, q, 1, - c->accessGroups, NULL, &q->q_error); - sqlite_int64 rowid = sqlite3_column_int64(stmt, 0); - if (!item) { - secerror("decode %@,rowid=%" PRId64 " failed (%ld): %@", q->q_class->name, rowid, CFErrorGetCode(q->q_error), q->q_error); - // errSecDecode means the tiem is corrupted, stash it for delete. - if(CFErrorGetCode(q->q_error)==errSecDecode) - { - secerror("We should attempt to delete this row (%lld)", rowid); - - { - CFDataRef edata = s3dl_copy_data_from_col(stmt, 1, NULL); - CFMutableStringRef edatastring = CFStringCreateMutable(kCFAllocatorDefault, 0); - if(edatastring) { - CFStringAppendEncryptedData(edatastring, edata); - secnotice("item", "corrupted edata=%@", edatastring); - } - CFReleaseSafe(edata); - CFReleaseSafe(edatastring); - } - - if(q->corrupted_rows==NULL) { - q->corrupted_rows=CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - } - - if(q->corrupted_rows==NULL) { - secerror("Could not create a mutable array to store corrupted row! No memory ?"); - } else { - long long row=rowid; - CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberLongLongType, &row); - if(number==NULL) { - secerror("Could not create a CFNumber to store corrupted row! No memory ?"); - } else { - CFArrayAppendValue(q->corrupted_rows, number); - CFReleaseNull(number); - /* Hide this error, this will just pretend the item didnt exist at all */ - CFReleaseNull(q->q_error); - } - } - } - // q->q_error will be released appropriately by a call to query_error - return; - } - - if (q->q_class == &identity_class) { - // TODO: Use col 2 for key rowid and use both rowids in persistent ref. - CFMutableDictionaryRef key = s3dl_item_from_col(stmt, q, 3, - c->accessGroups, NULL, &q->q_error); - - /* TODO : if there is a errSecDecode error here, we should cleanup */ - if (!key) - goto out; - - CFDataRef certData = CFDictionaryGetValue(item, kSecValueData); - if (certData) { - CFDictionarySetValue(key, CFSTR(CERTIFICATE_DATA_COLUMN_LABEL), - certData); - CFDictionaryRemoveValue(item, kSecValueData); - } - CFDictionaryApplyFunction(item, s3dl_merge_into_dict, key); - CFRelease(item); - item = key; - } - - if (!match_item(q, c->accessGroups, item)) - goto out; - - CFTypeRef a_result = handle_result(q, item, rowid); - if (a_result) { - if (a_result == kCFNull) { - /* Caller wasn't interested in a result, but we still - count this row as found. */ - } else if (q->q_limit == 1) { - c->result = a_result; - } else { - CFArrayAppendValue((CFMutableArrayRef)c->result, a_result); - CFRelease(a_result); - } - c->found++; - } - -out: - CFRelease(item); -} - -static void -SecDbAppendWhereROWID(CFMutableStringRef sql, - CFStringRef col, sqlite_int64 row_id, - bool *needWhere) { - if (row_id > 0) { - SecDbAppendWhereOrAnd(sql, needWhere); - CFStringAppendFormat(sql, NULL, CFSTR("%@=%lld"), col, row_id); - } -} - -static void -SecDbAppendWhereAttrs(CFMutableStringRef sql, const Query *q, bool *needWhere) { - CFIndex ix, attr_count = query_attr_count(q); - for (ix = 0; ix < attr_count; ++ix) { - SecDbAppendWhereOrAndEquals(sql, query_attr_at(q, ix).key, needWhere); - } -} - -static void -SecDbAppendWhereAccessGroups(CFMutableStringRef sql, - CFStringRef col, - CFArrayRef accessGroups, - bool *needWhere) { - CFIndex ix, ag_count; - if (!accessGroups || 0 == (ag_count = CFArrayGetCount(accessGroups))) { - return; - } - - SecDbAppendWhereOrAnd(sql, needWhere); - CFStringAppend(sql, col); - CFStringAppend(sql, CFSTR(" IN (?")); - for (ix = 1; ix < ag_count; ++ix) { - CFStringAppend(sql, CFSTR(",?")); - } - CFStringAppend(sql, CFSTR(")")); -} - -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); - SecDbAppendWhereAccessGroups(sql, CFSTR("agrp"), accessGroups, &needWhere); -} - -static void SecDbAppendLimit(CFMutableStringRef sql, CFIndex limit) { - if (limit != kSecMatchUnlimited) - CFStringAppendFormat(sql, NULL, CFSTR(" LIMIT %" PRIdCFIndex), limit); -} - -static CFStringRef s3dl_select_sql(Query *q, CFArrayRef accessGroups) { - CFMutableStringRef sql = CFStringCreateMutable(NULL, 0); - if (q->q_class == &identity_class) { - CFStringAppendFormat(sql, NULL, CFSTR("SELECT crowid, " - CERTIFICATE_DATA_COLUMN_LABEL ", rowid,data FROM " - "(SELECT cert.rowid AS crowid, cert.labl AS labl," - " cert.issr AS issr, cert.slnr AS slnr, cert.skid AS skid," - " keys.*,cert.data AS " CERTIFICATE_DATA_COLUMN_LABEL - " FROM keys, cert" - " WHERE keys.priv == 1 AND cert.pkhh == keys.klbl")); - SecDbAppendWhereAccessGroups(sql, CFSTR("cert.agrp"), accessGroups, 0); - /* The next 3 SecDbAppendWhere calls are in the same order as in - SecDbAppendWhereClause(). This makes sqlBindWhereClause() work, - as long as we do an extra sqlBindAccessGroups first. */ - SecDbAppendWhereROWID(sql, CFSTR("crowid"), q->q_row_id, 0); - CFStringAppend(sql, CFSTR(")")); - bool needWhere = true; - SecDbAppendWhereAttrs(sql, q, &needWhere); - SecDbAppendWhereAccessGroups(sql, CFSTR("agrp"), accessGroups, &needWhere); - } else { - CFStringAppend(sql, CFSTR("SELECT rowid, data FROM ")); - CFStringAppend(sql, q->q_class->name); - SecDbAppendWhereClause(sql, q, accessGroups); - } - SecDbAppendLimit(sql, q->q_limit); - - return sql; -} - -static bool sqlBindAccessGroups(sqlite3_stmt *stmt, CFArrayRef accessGroups, - int *pParam, CFErrorRef *error) { - bool result = true; - int param = *pParam; - CFIndex ix, count = accessGroups ? CFArrayGetCount(accessGroups) : 0; - for (ix = 0; ix < count; ++ix) { - result = SecDbBindObject(stmt, param++, - CFArrayGetValueAtIndex(accessGroups, ix), - error); - if (!result) - break; - } - *pParam = param; - return result; -} - -static bool sqlBindWhereClause(sqlite3_stmt *stmt, const Query *q, - CFArrayRef accessGroups, int *pParam, CFErrorRef *error) { - bool result = true; - int param = *pParam; - CFIndex ix, attr_count = query_attr_count(q); - for (ix = 0; ix < attr_count; ++ix) { - result = SecDbBindObject(stmt, param++, query_attr_at(q, ix).value, error); - if (!result) - break; - } - - /* Bind the access group to the sql. */ - if (result) { - result = sqlBindAccessGroups(stmt, accessGroups, ¶m, error); - } - - *pParam = param; - return result; -} - -static bool SecDbItemQuery(SecDbQueryRef query, CFArrayRef accessGroups, SecDbConnectionRef dbconn, CFErrorRef *error, - void (^handle_row)(SecDbItemRef item, bool *stop)) { - __block bool ok = true; - /* Sanity check the query. */ - if (query->q_ref) - return SecError(errSecValueRefUnsupported, error, CFSTR("value ref not supported by queries")); - - bool (^return_attr)(const SecDbAttr *attr) = ^bool (const SecDbAttr * attr) { - return attr->kind == kSecDbRowIdAttr || attr->kind == kSecDbEncryptedDataAttr; - }; - - CFStringRef sql = s3dl_select_sql(query, accessGroups); - ok = sql; - if (sql) { - ok &= SecDbPrepare(dbconn, sql, error, ^(sqlite3_stmt *stmt) { - /* Bind the values being searched for to the SELECT statement. */ - int param = 1; - if (query->q_class == &identity_class) { - /* Bind the access groups to cert.agrp. */ - ok &= sqlBindAccessGroups(stmt, accessGroups, ¶m, error); - } - if (ok) - ok &= sqlBindWhereClause(stmt, query, accessGroups, ¶m, error); - if (ok) { - SecDbStep(dbconn, stmt, error, ^(bool *stop) { - SecDbItemRef item = SecDbItemCreateWithStatement(kCFAllocatorDefault, query->q_class, stmt, query->q_keybag, error, return_attr); - if (item) { - if (match_item(query, accessGroups, item->attributes)) - handle_row(item, stop); - CFRelease(item); - } else { - secerror("failed to create item from stmt: %@", error ? *error : (CFErrorRef)"no error"); - if (error) { - CFReleaseNull(*error); - } - //*stop = true; - //ok = false; - } - }); - } - }); - CFRelease(sql); - } - - return ok; -} - -static bool -s3dl_query(SecDbConnectionRef dbt, s3dl_handle_row handle_row, - void *context, CFErrorRef *error) -{ - struct s3dl_query_ctx *c = context; - Query *q = c->q; - CFArrayRef accessGroups = c->accessGroups; - - /* Sanity check the query. */ - if (q->q_ref) - return SecError(errSecValueRefUnsupported, error, CFSTR("value ref not supported by queries")); - - /* Actual work here. */ - if (q->q_limit == 1) { - c->result = NULL; - } else { - c->result = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - } - CFStringRef sql = s3dl_select_sql(q, accessGroups); - bool ok = SecDbWithSQL(dbt, sql, error, ^(sqlite3_stmt *stmt) { - bool sql_ok = true; - /* Bind the values being searched for to the SELECT statement. */ - int param = 1; - if (q->q_class == &identity_class) { - /* Bind the access groups to cert.agrp. */ - sql_ok = sqlBindAccessGroups(stmt, accessGroups, ¶m, error); - } - if (sql_ok) - sql_ok = sqlBindWhereClause(stmt, q, accessGroups, ¶m, error); - if (sql_ok) { - SecDbForEach(stmt, error, ^bool (int row_index) { - handle_row(stmt, context); - return (!q->q_error) && (q->q_limit == kSecMatchUnlimited || c->found < q->q_limit); - }); - } - return sql_ok; - }); - - CFRelease(sql); - - // First get the error from the query, since errSecDuplicateItem from an - // update query should superceed the errSecItemNotFound below. - if (!query_error(q, error)) - ok = false; - if (ok && c->found == 0) - ok = SecError(errSecItemNotFound, error, CFSTR("no matching items found")); - - return ok; -} - -#if 0 -/* Gross hack to recover from item corruption */ -static void -s3dl_cleanup_corrupted(SecDbConnectionRef dbt, Query *q, CFErrorRef *error) -{ - - if(q->corrupted_rows==NULL) - return; - - __security_simulatecrash(CFSTR("Corrupted items found in keychain")); - - if (q->q_class == &identity_class) { - /* TODO: how to cleanup in that case */ - secerror("Cleaning up corrupted identities is not implemented yet"); - goto out; - } - - CFArrayForEach(q->corrupted_rows, ^(const void *value) { - CFMutableStringRef sql=CFStringCreateMutable(kCFAllocatorDefault, 0); - - if(sql==NULL) { - secerror("Could not allocate CFString for sql, out of memory ?"); - } else { - CFStringAppend(sql, CFSTR("DELETE FROM ")); - CFStringAppend(sql, q->q_class->name); - CFStringAppendFormat(sql, NULL, CFSTR(" WHERE rowid=%@"), value); - - secerror("Attempting cleanup with %@", sql); - - if(!SecDbExec(dbt, sql, error)) { - secerror("Cleanup Failed using %@, error: %@", sql, error?NULL:*error); - } else { - secerror("Cleanup Succeeded using %@", sql); - } - - CFReleaseSafe(sql); - } - }); - -out: - CFReleaseNull(q->corrupted_rows); -} -#endif - -static bool -s3dl_copy_matching(SecDbConnectionRef dbt, Query *q, CFTypeRef *result, - CFArrayRef accessGroups, CFErrorRef *error) -{ - struct s3dl_query_ctx ctx = { - .q = q, .accessGroups = accessGroups, - }; - if (q->q_row_id && query_attr_count(q)) - return SecError(errSecItemIllegalQuery, error, - CFSTR("attributes to query illegal; both row_id and other attributes can't be searched at the same time")); - - // Only copy things that aren't tombstones unless the client explicitly asks otherwise. - if (!CFDictionaryContainsKey(q->q_item, kSecAttrTombstone)) - query_add_attribute(kSecAttrTombstone, kCFBooleanFalse, q); - bool ok = s3dl_query(dbt, s3dl_query_row, &ctx, error); - if (ok && result) - *result = ctx.result; - else - CFReleaseSafe(ctx.result); - - // s3dl_cleanup_corrupted(dbt, q, error); - - return ok; -} - -/* AUDIT[securityd](done): - attributesToUpdate (ok) is a caller provided dictionary, - only its cf types have been checked. - */ -static bool -s3dl_query_update(SecDbConnectionRef dbt, Query *q, - CFDictionaryRef attributesToUpdate, CFArrayRef accessGroups, CFErrorRef *error) -{ - /* Sanity check the query. */ - if (query_match_count(q) != 0) - return SecError(errSecItemMatchUnsupported, error, CFSTR("match not supported in attributes to update")); - if (q->q_ref) - return SecError(errSecValueRefUnsupported, error, CFSTR("value ref not supported in attributes to update")); - if (q->q_row_id && query_attr_count(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); - if (u == NULL) return false; - require_action_quiet(query_update_parse(u, attributesToUpdate, error), errOut, result = false); - query_pre_update(u); - result &= SecDbTransaction(dbt, kSecDbExclusiveTransactionType, error, ^(bool *commit) { - // Make sure we only update real items, not tombstones, unless the client explicitly asks otherwise. - if (!CFDictionaryContainsKey(q->q_item, kSecAttrTombstone)) - query_add_attribute(kSecAttrTombstone, kCFBooleanFalse, q); - result &= SecDbItemQuery(q, accessGroups, dbt, error, ^(SecDbItemRef item, bool *stop) { - //We always need to know the error here. - CFErrorRef localError = NULL; - SecDbItemRef new_item = SecDbItemCopyWithUpdates(item, u->q_item, &localError); - if(SecErrorGetOSStatus(localError)==errSecDecode) { - // We just ignore this, and treat as if item is not found - secerror("Trying to update to a corrupted item"); - CFReleaseSafe(localError); - return; - } - - if (error && *error == NULL) { - *error = localError; - localError = NULL; - } - CFReleaseSafe(localError); - - result = new_item; - if (new_item) { - bool item_is_sync = SecDbItemIsSyncable(item); - bool makeTombstone = q->q_use_tomb ? CFBooleanGetValue(q->q_use_tomb) : (item_is_sync && !SecDbItemIsTombstone(item)); - result = SecDbItemUpdate(item, new_item, dbt, makeTombstone, error); - if (result) { - q->q_changed = true; - if (item_is_sync || SecDbItemIsSyncable(new_item)) - q->q_sync_changed = true; - } - CFRelease(new_item); - } - if (!result) - *stop = true; - }); - if (!result) - *commit = false; - }); - if (result && !q->q_changed) - result = SecError(errSecItemNotFound, error, CFSTR("No items updated")); -errOut: - if (!query_destroy(u, error)) - result = false; - return result; -} - -static bool -s3dl_query_delete(SecDbConnectionRef dbt, Query *q, CFArrayRef accessGroups, CFErrorRef *error) -{ - __block bool ok = true; - // Only delete things that aren't tombstones, unless the client explicitly asks otherwise. - if (!CFDictionaryContainsKey(q->q_item, kSecAttrTombstone)) - query_add_attribute(kSecAttrTombstone, kCFBooleanFalse, q); - ok &= SecDbItemSelect(q, dbt, error, ^bool(const SecDbAttr *attr) { - return false; - },^bool(CFMutableStringRef sql, bool *needWhere) { - SecDbAppendWhereClause(sql, q, accessGroups); - return true; - },^bool(sqlite3_stmt * stmt, int col) { - return sqlBindWhereClause(stmt, q, accessGroups, &col, error); - }, ^(SecDbItemRef item, bool *stop) { - bool item_is_sync = SecDbItemIsSyncable(item); - bool makeTombstone = q->q_use_tomb ? CFBooleanGetValue(q->q_use_tomb) : (item_is_sync && !SecDbItemIsTombstone(item)); - ok = SecDbItemDelete(item, dbt, makeTombstone, error); - if (ok) { - q->q_changed = true; - if (item_is_sync) - q->q_sync_changed = true; - } - }); - if (ok && !q->q_changed) { - ok = SecError(errSecItemNotFound, error, CFSTR("Delete failed to delete anything")); - } - return ok; -} - -/* 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) { - CFStringRef agrp = CFDictionaryGetValue(item, kSecAttrAccessGroup); - if (!isString(agrp)) - return false; - - if (CFEqual(agrp, CFSTR("lockdown-identities"))) { - secdebug("backup", "found sys_bound item: %@", item); - return true; - } - - if (CFEqual(agrp, CFSTR("apple")) && class == &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")))) { - secdebug("backup", "found sys_bound item: %@", item); - return true; - } - } - secdebug("backup", "found non sys_bound item: %@", item); - return false; -} - -/* Delete all items from the current keychain. If this is not an in - place upgrade we don't delete items in the 'lockdown-identities' - access group, this ensures that an import or restore of a backup - will never overwrite an existing activation record. */ -static bool SecServerDeleteAll(SecDbConnectionRef dbt, CFErrorRef *error) { - return kc_transaction(dbt, error, ^{ - bool ok = (SecDbExec(dbt, CFSTR("DELETE from genp;"), error) && - SecDbExec(dbt, CFSTR("DELETE from inet;"), error) && - SecDbExec(dbt, CFSTR("DELETE from cert;"), error) && - SecDbExec(dbt, CFSTR("DELETE from keys;"), error)); - return ok; - }); -} - -struct s3dl_export_row_ctx { - struct s3dl_query_ctx qc; - keybag_handle_t dest_keybag; - enum SecItemFilter filter; - SecDbConnectionRef dbt; -}; - -static void s3dl_export_row(sqlite3_stmt *stmt, void *context) { - struct s3dl_export_row_ctx *c = context; - Query *q = c->qc.q; - keyclass_t keyclass = 0; - CFErrorRef localError = NULL; - - sqlite_int64 rowid = sqlite3_column_int64(stmt, 0); - CFMutableDictionaryRef item = s3dl_item_from_col(stmt, q, 1, c->qc.accessGroups, &keyclass, &localError); - - if (item) { - /* Only export sysbound items is 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) { - /* Re-encode the item. */ - secdebug("item", "export rowid %llu item: %@", rowid, item); - /* The code below could be moved into handle_row. */ - CFDataRef pref = _SecItemMakePersistentRef(q->q_class->name, rowid); - if (pref) { - if (c->dest_keybag != KEYBAG_NONE) { - /* Encode and encrypt the item to the specified keybag. */ - CFDataRef plain = kc_plist_copy_der(item, &q->q_error); - CFDictionaryRemoveAllValues(item); - if (plain) { - CFDataRef edata = NULL; - if (ks_encrypt_data(c->dest_keybag, keyclass, plain, &edata, &q->q_error)) { - CFDictionarySetValue(item, kSecValueData, edata); - CFReleaseSafe(edata); - } else { - seccritical("ks_encrypt_data %@,rowid=%" PRId64 ": failed: %@", q->q_class->name, rowid, q->q_error); - CFReleaseNull(q->q_error); - } - CFRelease(plain); - } - } - if (CFDictionaryGetCount(item)) { - CFDictionarySetValue(item, kSecValuePersistentRef, pref); - CFArrayAppendValue((CFMutableArrayRef)c->qc.result, item); - c->qc.found++; - } - CFReleaseSafe(pref); - } - } - CFRelease(item); - } else { - /* This happens a lot when trying to migrate keychain before first unlock, so only a notice */ - /* If the error is "corrupted item" then we just ignore it, otherwise we save it in the query */ - secnotice("item","Could not export item for rowid %llu: %@", rowid, localError); - if(SecErrorGetOSStatus(localError)==errSecDecode) { - CFReleaseNull(localError); - } else { - CFReleaseSafe(q->q_error); - q->q_error=localError; - } - } -} - -static CF_RETURNS_RETAINED CFDictionaryRef SecServerExportKeychainPlist(SecDbConnectionRef dbt, - keybag_handle_t src_keybag, keybag_handle_t dest_keybag, - enum SecItemFilter filter, CFErrorRef *error) { - CFMutableDictionaryRef keychain; - keychain = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (!keychain) { - if (error && !*error) - SecError(errSecAllocate, error, CFSTR("Can't create keychain dictionary")); - goto errOut; - } - unsigned class_ix; - Query q = { .q_keybag = src_keybag }; - q.q_return_type = kSecReturnDataMask | kSecReturnAttributesMask | \ - kSecReturnPersistentRefMask; - q.q_limit = kSecMatchUnlimited; - - /* Get rid of this duplicate. */ - const SecDbClass *SecDbClasses[] = { - &genp_class, - &inet_class, - &cert_class, - &keys_class - }; - - for (class_ix = 0; class_ix < array_size(SecDbClasses); - ++class_ix) { - q.q_class = SecDbClasses[class_ix]; - struct s3dl_export_row_ctx ctx = { - .qc = { .q = &q, }, - .dest_keybag = dest_keybag, .filter = filter, - .dbt = dbt, - }; - - secnotice("item", "exporting class '%@'", q.q_class->name); - - CFErrorRef localError = NULL; - if (s3dl_query(dbt, s3dl_export_row, &ctx, &localError)) { - if (CFArrayGetCount(ctx.qc.result)) - CFDictionaryAddValue(keychain, q.q_class->name, ctx.qc.result); - - } else { - OSStatus status = (OSStatus)CFErrorGetCode(localError); - if (status == errSecItemNotFound) { - CFRelease(localError); - } else { - secerror("Export failed: %@", localError); - if (error) { - CFReleaseSafe(*error); - *error = localError; - } else { - CFRelease(localError); - } - CFReleaseNull(keychain); - break; - } - } - CFReleaseNull(ctx.qc.result); - } -errOut: - return keychain; -} - -static CF_RETURNS_RETAINED CFDataRef SecServerExportKeychain(SecDbConnectionRef dbt, - 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, - src_keybag, dest_keybag, kSecBackupableItemFilter, - error); - if (keychain) { - data_out = CFPropertyListCreateData(kCFAllocatorDefault, keychain, - kCFPropertyListBinaryFormat_v1_0, - 0, error); - CFRelease(keychain); - } - - return data_out; -} - -struct SecServerImportClassState { - SecDbConnectionRef dbt; - CFErrorRef error; - keybag_handle_t src_keybag; - keybag_handle_t dest_keybag; - enum SecItemFilter filter; -}; - -struct SecServerImportItemState { - const SecDbClass *class; - struct SecServerImportClassState *s; -}; - -/* Infer accessibility and access group for pre-v2 (iOS4.x and earlier) items - being imported from a backup. */ -static bool SecDbItemImportMigrate(SecDbItemRef item, CFErrorRef *error) { - bool ok = true; - CFStringRef agrp = SecDbItemGetCachedValueWithName(item, kSecAttrAccessGroup); - CFStringRef accessible = SecDbItemGetCachedValueWithName(item, kSecAttrAccessible); - - if (!isString(agrp) || !isString(accessible)) - return ok; - if (SecDbItemGetClass(item) == &genp_class && CFEqual(accessible, kSecAttrAccessibleAlways)) { - CFStringRef svce = SecDbItemGetCachedValueWithName(item, kSecAttrService); - if (!isString(svce)) return ok; - if (CFEqual(agrp, CFSTR("apple"))) { - if (CFEqual(svce, CFSTR("AirPort"))) { - ok = SecDbItemSetValueWithName(item, kSecAttrAccessible, kSecAttrAccessibleAfterFirstUnlock, error); - } else if (CFEqual(svce, CFSTR("com.apple.airplay.password"))) { - ok = SecDbItemSetValueWithName(item, kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked, error); - } else if (CFEqual(svce, CFSTR("YouTube"))) { - ok = (SecDbItemSetValueWithName(item, kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked, error) && - SecDbItemSetValueWithName(item, kSecAttrAccessGroup, CFSTR("com.apple.youtube.credentials"), error)); - } else { - CFStringRef desc = SecDbItemGetCachedValueWithName(item, kSecAttrDescription); - if (!isString(desc)) return ok; - if (CFEqual(desc, CFSTR("IPSec Shared Secret")) || CFEqual(desc, CFSTR("PPP Password"))) { - ok = SecDbItemSetValueWithName(item, kSecAttrAccessible, kSecAttrAccessibleAfterFirstUnlock, error); - } - } - } - } else if (SecDbItemGetClass(item) == &inet_class && CFEqual(accessible, kSecAttrAccessibleAlways)) { - if (CFEqual(agrp, CFSTR("PrintKitAccessGroup"))) { - ok = SecDbItemSetValueWithName(item, kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked, error); - } else if (CFEqual(agrp, CFSTR("apple"))) { - CFTypeRef ptcl = SecDbItemGetCachedValueWithName(item, kSecAttrProtocol); - bool is_proxy = false; - if (isNumber(ptcl)) { - SInt32 iptcl; - CFNumberGetValue(ptcl, kCFNumberSInt32Type, &iptcl); - is_proxy = (iptcl == FOUR_CHAR_CODE('htpx') || - iptcl == FOUR_CHAR_CODE('htsx') || - iptcl == FOUR_CHAR_CODE('ftpx') || - iptcl == FOUR_CHAR_CODE('rtsx') || - iptcl == FOUR_CHAR_CODE('xpth') || - iptcl == FOUR_CHAR_CODE('xsth') || - iptcl == FOUR_CHAR_CODE('xptf') || - iptcl == FOUR_CHAR_CODE('xstr')); - } else if (isString(ptcl)) { - is_proxy = (CFEqual(ptcl, kSecAttrProtocolHTTPProxy) || - CFEqual(ptcl, kSecAttrProtocolHTTPSProxy) || - CFEqual(ptcl, kSecAttrProtocolRTSPProxy) || - CFEqual(ptcl, kSecAttrProtocolFTPProxy)); - } - if (is_proxy) - ok = SecDbItemSetValueWithName(item, kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked, error); - } - } - return ok; -} - -bool SecDbItemDecrypt(SecDbItemRef item, CFDataRef edata, CFErrorRef *error) { - bool ok = true; - CFDataRef pdata = NULL; - keyclass_t keyclass; - uint32_t version; - ok = ks_decrypt_data(SecDbItemGetKeybag(item), &keyclass, edata, &pdata, &version, error); - if (!ok) - return ok; - - if (version < 2) { - /* Old V4 style keychain backup being imported. */ - ok = SecDbItemSetValueWithName(item, CFSTR("v_Data"), pdata, error) && - SecDbItemImportMigrate(item, error); - } else { - CFDictionaryRef dict; - if (version < 3) { - dict = s3dl_item_v2_decode(pdata, error); - } else { - dict = s3dl_item_v3_decode(pdata, error); - } - ok = dict && SecDbItemSetValues(item, dict, error); - CFReleaseSafe(dict); - } - - CFReleaseSafe(pdata); - - keyclass_t my_keyclass = SecDbItemGetKeyclass(item, NULL); - if (!my_keyclass) { - ok = ok && SecDbItemSetKeyclass(item, keyclass, error); - } else { - /* Make sure the keyclass in the dictionary matched what we got - back from decoding the data blob. */ - if (my_keyclass != keyclass) { - ok = SecError(errSecDecode, error, CFSTR("keyclass attribute %d doesn't match keyclass in blob %d"), my_keyclass, keyclass); - } - } - - return ok; -} - -/* Automagically make a item syncable, based on various attributes. */ -static bool SecDbItemInferSyncable(SecDbItemRef item, CFErrorRef *error) -{ - CFStringRef agrp = SecDbItemGetCachedValueWithName(item, kSecAttrAccessGroup); - - if (!isString(agrp)) - return true; - - if (CFEqual(agrp, CFSTR("com.apple.cfnetwork")) && SecDbItemGetClass(item) == &inet_class) { - CFTypeRef srvr = SecDbItemGetCachedValueWithName(item, kSecAttrServer); - CFTypeRef ptcl = SecDbItemGetCachedValueWithName(item, kSecAttrProtocol); - CFTypeRef atyp = SecDbItemGetCachedValueWithName(item, kSecAttrAuthenticationType); - - if (isString(srvr) && isString(ptcl) && isString(atyp)) { - /* This looks like a Mobile Safari Password, make syncable */ - secnotice("item", "Make this item syncable: %@", item); - return SecDbItemSetSyncable(item, true, error); - } - } - - return true; -} - -/* This create a SecDbItem from the item dictionnary that are exported for backups. - Item are stored in the backup as a dictionary containing two keys: - - v_Data: the encrypted data blob - - v_PersistentRef: a persistent Ref. - src_keybag is normally the backup keybag. - dst_keybag is normally the device keybag. -*/ -static SecDbItemRef SecDbItemCreateWithBackupDictionary(CFAllocatorRef allocator, const SecDbClass *dbclass, CFDictionaryRef dict, keybag_handle_t src_keybag, keybag_handle_t dst_keybag, CFErrorRef *error) -{ - CFDataRef edata = CFDictionaryGetValue(dict, CFSTR("v_Data")); - SecDbItemRef item = NULL; - - if (edata) { - item = SecDbItemCreateWithEncryptedData(kCFAllocatorDefault, dbclass, edata, src_keybag, error); - if (item) - if (!SecDbItemSetKeybag(item, dst_keybag, error)) - CFReleaseNull(item); - } else { - SecError(errSecDecode, error, CFSTR("No v_Data in backup dictionary %@"), dict); - } - - return item; -} - -static bool SecDbItemExtractRowIdFromBackupDictionary(SecDbItemRef item, CFDictionaryRef dict, CFErrorRef *error) { - CFDataRef ref = CFDictionaryGetValue(dict, CFSTR("v_PersistentRef")); - if (!ref) - return SecError(errSecDecode, error, CFSTR("No v_PersistentRef in backup dictionary %@"), dict); - - CFStringRef className; - sqlite3_int64 rowid; - if (!_SecItemParsePersistentRef(ref, &className, &rowid)) - return SecError(errSecDecode, error, CFSTR("v_PersistentRef %@ failed to decode"), ref); - - if (!CFEqual(SecDbItemGetClass(item)->name, className)) - return SecError(errSecDecode, error, CFSTR("v_PersistentRef has unexpected class %@"), className); - - return SecDbItemSetRowId(item, rowid, error); -} - -static void SecServerImportItem(const void *value, void *context) { - struct SecServerImportItemState *state = - (struct SecServerImportItemState *)context; - if (state->s->error) - return; - if (!isDictionary(value)) { - SecError(errSecParam, &state->s->error, CFSTR("value %@ is not a dictionary"), value); - return; - } - - CFDictionaryRef dict = (CFDictionaryRef)value; - - secdebug("item", "Import Item : %@", dict); - - /* We don't filter non sys_bound items during import since we know we - 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)) - return; - - SecDbItemRef item; - - /* This is sligthly confusing: - - During upgrade all items are exported with KEYBAG_NONE. - - During restore from backup, existing sys_bound items are exported with KEYBAG_NONE, and are exported as dictionary of attributes. - - Item in the actual backup are export with a real keybag, and are exported as encrypted v_Data and v_PersistentRef - */ - if (state->s->src_keybag == KEYBAG_NONE) { - item = SecDbItemCreateWithAttributes(kCFAllocatorDefault, state->class, dict, state->s->dest_keybag, &state->s->error); - } else { - item = SecDbItemCreateWithBackupDictionary(kCFAllocatorDefault, state->class, dict, state->s->src_keybag, state->s->dest_keybag, &state->s->error); - } - - if (item) { - if(state->s->filter != kSecSysBoundItemFilter) { - SecDbItemExtractRowIdFromBackupDictionary(item, dict, &state->s->error); - } - SecDbItemInferSyncable(item, &state->s->error); - 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. */ - if (state->s->error) { - secwarning("Failed to import an item (%@) of class '%@': %@ - ignoring error.", - item, state->class->name, state->s->error); - CFReleaseNull(state->s->error); - } - - CFReleaseSafe(item); -} - -static void SecServerImportClass(const void *key, const void *value, - void *context) { - struct SecServerImportClassState *state = - (struct SecServerImportClassState *)context; - if (state->error) - return; - if (!isString(key)) { - SecError(errSecParam, &state->error, CFSTR("class name %@ is not a string"), key); - return; - } - const SecDbClass *class = kc_class_with_name(key); - if (!class || class == &identity_class) { - SecError(errSecParam, &state->error, CFSTR("attempt to import an identity")); - return; - } - struct SecServerImportItemState item_state = { - .class = class, .s = state - }; - if (isArray(value)) { - CFArrayRef items = (CFArrayRef)value; - CFArrayApplyFunction(items, CFRangeMake(0, CFArrayGetCount(items)), - SecServerImportItem, &item_state); - } else { - CFDictionaryRef item = (CFDictionaryRef)value; - SecServerImportItem(item, &item_state); - } -} - -static bool SecServerImportKeychainInPlist(SecDbConnectionRef dbt, - keybag_handle_t src_keybag, keybag_handle_t dest_keybag, - CFDictionaryRef keychain, enum SecItemFilter filter, CFErrorRef *error) { - bool ok = true; - - CFDictionaryRef sys_bound = NULL; - 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); - } - - /* Delete everything in the keychain. */ - require(ok = SecServerDeleteAll(dbt, error), errOut); - - struct SecServerImportClassState state = { - .dbt = dbt, - .src_keybag = src_keybag, - .dest_keybag = dest_keybag, - .filter = filter, - }; - /* Import the provided items, preserving rowids. */ - CFDictionaryApplyFunction(keychain, SecServerImportClass, &state); - - if (sys_bound) { - state.src_keybag = KEYBAG_NONE; - /* Import the items we preserved with random rowids. */ - state.filter = kSecSysBoundItemFilter; - CFDictionaryApplyFunction(sys_bound, SecServerImportClass, &state); - CFRelease(sys_bound); - } - if (state.error) { - if (error) { - CFReleaseSafe(*error); - *error = state.error; - } else { - CFRelease(state.error); - } - ok = false; - } - -errOut: - return ok; -} - -static bool SecServerImportKeychain(SecDbConnectionRef dbt, - keybag_handle_t src_keybag, - keybag_handle_t dest_keybag, CFDataRef data, CFErrorRef *error) { - return kc_transaction(dbt, error, ^{ - bool ok = false; - CFDictionaryRef keychain; - keychain = CFPropertyListCreateWithData(kCFAllocatorDefault, data, - kCFPropertyListImmutable, NULL, - error); - if (keychain) { - if (isDictionary(keychain)) { - ok = SecServerImportKeychainInPlist(dbt, src_keybag, - dest_keybag, keychain, - kSecBackupableItemFilter, - error); - } else { - ok = SecError(errSecParam, error, CFSTR("import: keychain is not a dictionary")); - } - CFRelease(keychain); - } - return ok; - }); -} - -static bool ks_open_keybag(CFDataRef keybag, CFDataRef password, keybag_handle_t *handle, CFErrorRef *error) { -#if USE_KEYSTORE - kern_return_t kernResult; - kernResult = aks_load_bag(CFDataGetBytePtr(keybag), (int)CFDataGetLength(keybag), handle); - if (kernResult) - return SecKernError(kernResult, error, CFSTR("aks_load_bag failed: %@"), keybag); - - if (password) { - kernResult = aks_unlock_bag(*handle, CFDataGetBytePtr(password), (int)CFDataGetLength(password)); - if (kernResult) { - aks_unload_bag(*handle); - return SecKernError(kernResult, error, CFSTR("aks_unlock_bag failed")); - } - } - return true; -#else /* !USE_KEYSTORE */ - *handle = KEYBAG_NONE; - return true; -#endif /* USE_KEYSTORE */ -} - -static bool ks_close_keybag(keybag_handle_t keybag, CFErrorRef *error) { -#if USE_KEYSTORE - IOReturn kernResult = aks_unload_bag(keybag); - if (kernResult) { - return SecKernError(kernResult, error, CFSTR("aks_unload_bag failed")); - } -#endif /* USE_KEYSTORE */ - return true; -} - -static CF_RETURNS_RETAINED CFDataRef SecServerKeychainBackup(SecDbConnectionRef dbt, 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 = SecServerExportKeychain(dbt, KEYBAG_DEVICE, backup_keybag, error); - if (!ks_close_keybag(backup_keybag, error)) { - CFReleaseNull(backup); - } - } - return backup; -} - -static bool SecServerKeychainRestore(SecDbConnectionRef dbt, 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 = SecServerImportKeychain(dbt, backup_keybag, KEYBAG_DEVICE, - backup, error); - ok &= ks_close_keybag(backup_keybag, error); - - return ok; -} - - -// MARK - External SPI support code. - -CFStringRef __SecKeychainCopyPath(void) { - CFStringRef kcRelPath = NULL; - if (use_hwaes()) { - kcRelPath = CFSTR("keychain-2.db"); - } else { - kcRelPath = CFSTR("keychain-2-debug.db"); - } - - CFStringRef kcPath = NULL; - CFURLRef kcURL = SecCopyURLForFileInKeychainDirectory(kcRelPath); - if (kcURL) { - kcPath = CFURLCopyFileSystemPath(kcURL, kCFURLPOSIXPathStyle); - CFRelease(kcURL); - } - return kcPath; - -} - -// MARK; - -// MARK: kc_dbhandle init and reset - -static SecDbRef SecKeychainDbCreate(CFStringRef path) { - return SecDbCreate(path, ^bool (SecDbConnectionRef dbconn, bool didCreate, CFErrorRef *localError) { - bool ok; - if (didCreate) - ok = s3dl_dbt_upgrade_from_version(dbconn, 0, localError); - else - ok = s3dl_dbt_upgrade(dbconn, localError); - - if (!ok) - secerror("Upgrade %sfailed: %@", didCreate ? "from v0 " : "", localError ? *localError : NULL); - - return ok; - }); -} - -static SecDbRef _kc_dbhandle = NULL; - -static void kc_dbhandle_init(void) { - SecDbRef oldHandle = _kc_dbhandle; - _kc_dbhandle = NULL; - CFStringRef dbPath = __SecKeychainCopyPath(); - if (dbPath) { - _kc_dbhandle = SecKeychainDbCreate(dbPath); - CFRelease(dbPath); - } - if (oldHandle) { - secerror("replaced %@ with %@", oldHandle, _kc_dbhandle); - CFRelease(oldHandle); - } -} - -static dispatch_once_t _kc_dbhandle_once; - -static SecDbRef kc_dbhandle(void) { - dispatch_once(&_kc_dbhandle_once, ^{ - kc_dbhandle_init(); - }); - return _kc_dbhandle; -} - -/* For whitebox testing only */ -void kc_dbhandle_reset(void); -void kc_dbhandle_reset(void) -{ - __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(); -} - -static SecDbConnectionRef kc_aquire_dbt(bool writeAndRead, CFErrorRef *error) { - return SecDbConnectionAquire(kc_dbhandle(), !writeAndRead, error); -} - -/* Return a per thread dbt handle for the keychain. If create is true create - the database if it does not yet exist. If it is false, just return an - error if it fails to auto-create. */ -static bool kc_with_dbt(bool writeAndRead, CFErrorRef *error, bool (^perform)(SecDbConnectionRef dbt)) -{ - bool ok = false; - SecDbConnectionRef dbt = kc_aquire_dbt(writeAndRead, error); - if (dbt) { - ok = perform(dbt); - SecDbConnectionRelease(dbt); - } - return ok; -} - -static bool -items_matching_issuer_parent(CFArrayRef accessGroups, - CFDataRef issuer, CFArrayRef issuers, int recurse) -{ - Query *q; - CFArrayRef results = NULL; - SecDbConnectionRef dbt = NULL; - CFIndex i, count; - bool found = false; - - if (CFArrayContainsValue(issuers, CFRangeMake(0, CFArrayGetCount(issuers)), issuer)) - return true; - - const void *keys[] = { kSecClass, kSecReturnRef, kSecAttrSubject }; - const void *vals[] = { kSecClassCertificate, kCFBooleanTrue, issuer }; - CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, array_size(keys), NULL, NULL); - - if (!query) - return false; - - CFErrorRef localError = NULL; - q = query_create_with_limit(query, kSecMatchUnlimited, &localError); - CFRelease(query); - if (q) { - if ((dbt = SecDbConnectionAquire(kc_dbhandle(), true, &localError))) { - s3dl_copy_matching(dbt, q, (CFTypeRef*)&results, accessGroups, &localError); - SecDbConnectionRelease(dbt); - } - query_destroy(q, &localError); - } - if (localError) { - secerror("items matching issuer parent: %@", localError); - CFReleaseNull(localError); - return false; - } - - count = CFArrayGetCount(results); - for (i = 0; (i < count) && !found; i++) { - CFDictionaryRef cert_dict = (CFDictionaryRef)CFArrayGetValueAtIndex(results, i); - CFDataRef cert_issuer = CFDictionaryGetValue(cert_dict, kSecAttrIssuer); - if (CFEqual(cert_issuer, issuer)) - continue; - if (recurse-- > 0) - found = items_matching_issuer_parent(accessGroups, cert_issuer, issuers, recurse); - } - CFRelease(results); - - return found; -} - -static bool match_item(Query *q, CFArrayRef accessGroups, CFDictionaryRef item) -{ - if (q->q_match_issuer) { - CFDataRef issuer = CFDictionaryGetValue(item, kSecAttrIssuer); - if (!items_matching_issuer_parent(accessGroups, issuer, q->q_match_issuer, 10 /*max depth*/)) - return false; - } - - /* Add future match checks here. */ - - return true; -} - -/**************************************************************************** - **************** 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 - -/* AUDIT[securityd](done): - query (ok) is a caller provided dictionary, only its cf type has been checked. - */ -static bool -SecItemServerCopyMatching(CFDictionaryRef query, CFTypeRef *result, - CFArrayRef accessGroups, CFErrorRef *error) -{ - CFIndex ag_count; - if (!accessGroups || 0 == (ag_count = CFArrayGetCount(accessGroups))) { - return SecError(errSecMissingEntitlement, error, - CFSTR("client has neither application-identifier nor keychain-access-groups entitlements")); - } - - if (CFArrayContainsValue(accessGroups, CFRangeMake(0, ag_count), CFSTR("*"))) { - /* Having the special accessGroup "*" allows access to all accessGroups. */ - accessGroups = NULL; - } - - bool ok = false; - Query *q = query_create_with_limit(query, 1, error); - if (q) { - CFStringRef agrp = CFDictionaryGetValue(q->q_item, kSecAttrAccessGroup); - if (agrp && accessGroupsAllows(accessGroups, agrp)) { - // TODO: Return an error if agrp is not NULL and accessGroupsAllows() fails above. - const void *val = agrp; - accessGroups = CFArrayCreate(0, &val, 1, &kCFTypeArrayCallBacks); - } else { - CFRetainSafe(accessGroups); - } - - /* Sanity check the query. */ - 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")); - } else if (q->q_return_type != 0 && result == NULL) { - ok = SecError(errSecReturnMissingPointer, error, CFSTR("missing pointer")); - } else if (!q->q_error) { - ok = kc_with_dbt(false, error, ^(SecDbConnectionRef dbt) { - return s3dl_copy_matching(dbt, q, result, accessGroups, error); - }); - } - - CFReleaseSafe(accessGroups); - if (!query_destroy(q, error)) - ok = false; - } - - return ok; -} - -bool -_SecItemCopyMatching(CFDictionaryRef query, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error) { - return SecItemServerCopyMatching(query, result, accessGroups, error); -} - -/* 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) -{ - bool ok = true; - CFIndex ag_count; - if (!accessGroups || 0 == (ag_count = CFArrayGetCount(accessGroups))) - return SecError(errSecMissingEntitlement, error, - CFSTR("client has neither application-identifier nor keychain-access-groups entitlements")); - - Query *q = query_create_with_limit(attributes, 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; - - if (agrp) { - /* The user specified an explicit access group, validate it. */ - if (!accessGroupsAllows(accessGroups, agrp)) - return SecError(errSecNoAccessForItem, error, CFSTR("NoAccessForItem")); - } else { - agrp = (CFStringRef)CFArrayGetValueAtIndex(ag, 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); - } - - query_ensure_keyclass(q, agrp); - - 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) { - ok = kc_with_dbt(true, error, ^(SecDbConnectionRef dbt){ - return kc_transaction(dbt, error, ^{ - query_pre_add(q, true); - return s3dl_query_add(dbt, q, result, error); - }); - }); - } - ok = query_notify_and_destroy(q, ok, error); - } else { - ok = false; - } - return ok; -} - -/* AUDIT[securityd](done): - query (ok) and attributesToUpdate (ok) are a caller provided dictionaries, - only their cf types have been checked. - */ -bool -_SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate, - CFArrayRef accessGroups, CFErrorRef *error) -{ - CFIndex ag_count; - if (!accessGroups || 0 == (ag_count = CFArrayGetCount(accessGroups))) { - return SecError(errSecMissingEntitlement, error, - CFSTR("client has neither application-identifier nor keychain-access-groups entitlements")); - } - - if (CFArrayContainsValue(accessGroups, CFRangeMake(0, ag_count), CFSTR("*"))) { - /* Having the special accessGroup "*" allows access to all accessGroups. */ - accessGroups = NULL; - } - - bool ok = true; - Query *q = query_create_with_limit(query, kSecMatchUnlimited, error); - if (!q) { - ok = false; - } - if (ok) { - /* Sanity check the query. */ - 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. */ - ok = SecError(errSecReturnDataUnsupported, error, CFSTR("return data not supported by update")); - } else if (q->q_return_type & kSecReturnAttributesMask) { - ok = SecError(errSecReturnAttributesUnsupported, error, CFSTR("return attributes not supported by update")); - } else if (q->q_return_type & kSecReturnRefMask) { - ok = SecError(errSecReturnRefUnsupported, error, CFSTR("return ref not supported by update")); - } else if (q->q_return_type & kSecReturnPersistentRefMask) { - ok = SecError(errSecReturnPersitentRefUnsupported, error, CFSTR("return persistent ref not supported by update")); - } else { - /* Access group sanity checking. */ - CFStringRef agrp = (CFStringRef)CFDictionaryGetValue(attributesToUpdate, - kSecAttrAccessGroup); - if (agrp) { - /* The user is attempting to modify the access group column, - validate it to make sure the new value is allowable. */ - if (!accessGroupsAllows(accessGroups, agrp)) { - ok = SecError(errSecNoAccessForItem, error, CFSTR("accessGroup %@ not in %@"), agrp, accessGroups); - } - } - } - } - if (ok) { - if (!q->q_use_tomb && SOSCCThisDeviceDefinitelyNotActiveInCircle()) { - q->q_use_tomb = kCFBooleanFalse; - } - ok = kc_with_dbt(true, error, ^(SecDbConnectionRef dbt) { - return s3dl_query_update(dbt, q, attributesToUpdate, accessGroups, error); - }); - } - if (q) { - ok = query_notify_and_destroy(q, ok, error); - } - return ok; -} - - -/* AUDIT[securityd](done): - query (ok) is a caller provided dictionary, only its cf type has been checked. - */ -bool -_SecItemDelete(CFDictionaryRef query, CFArrayRef accessGroups, CFErrorRef *error) -{ - CFIndex ag_count; - if (!accessGroups || 0 == (ag_count = CFArrayGetCount(accessGroups))) { - return SecError(errSecMissingEntitlement, error, - CFSTR("client has neither application-identifier nor keychain-access-groups entitlements")); - } - - if (CFArrayContainsValue(accessGroups, CFRangeMake(0, ag_count), CFSTR("*"))) { - /* Having the special accessGroup "*" allows access to all accessGroups. */ - accessGroups = NULL; - } - - Query *q = query_create_with_limit(query, kSecMatchUnlimited, error); - bool ok; - if (q) { - /* Sanity check the query. */ - if (q->q_limit != kSecMatchUnlimited) - ok = SecError(errSecMatchLimitUnsupported, error, CFSTR("match limit not supported by delete")); - else if (query_match_count(q) != 0) - ok = SecError(errSecItemMatchUnsupported, error, CFSTR("match not supported by delete")); - 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)) - ok = SecError(errSecItemIllegalQuery, error, CFSTR("rowid and other attributes are mutually exclusive")); - else { - if (!q->q_use_tomb && SOSCCThisDeviceDefinitelyNotActiveInCircle()) { - q->q_use_tomb = kCFBooleanFalse; - } - ok = kc_with_dbt(true, error, ^(SecDbConnectionRef dbt) { - return s3dl_query_delete(dbt, q, accessGroups, error); - }); - } - ok = query_notify_and_destroy(q, ok, error); - } else { - ok = false; - } - return ok; -} - - -/* AUDIT[securityd](done): - No caller provided inputs. - */ -static bool -SecItemServerDeleteAll(CFErrorRef *error) { - return kc_with_dbt(true, error, ^bool (SecDbConnectionRef dbt) { - return (kc_transaction(dbt, error, ^bool { - return (SecDbExec(dbt, CFSTR("DELETE from genp;"), error) && - SecDbExec(dbt, CFSTR("DELETE from inet;"), error) && - SecDbExec(dbt, CFSTR("DELETE from cert;"), error) && - SecDbExec(dbt, CFSTR("DELETE from keys;"), error)); - }) && SecDbExec(dbt, CFSTR("VACUUM;"), error)); - }); -} - -bool -_SecItemDeleteAll(CFErrorRef *error) { - return SecItemServerDeleteAll(error); -} - -CFDataRef -_SecServerKeychainBackup(CFDataRef keybag, CFDataRef passcode, CFErrorRef *error) { - CFDataRef backup; - SecDbConnectionRef dbt = SecDbConnectionAquire(kc_dbhandle(), false, error); - - if (!dbt) - return NULL; - - if (keybag == NULL && passcode == NULL) { -#if USE_KEYSTORE - backup = SecServerExportKeychain(dbt, KEYBAG_DEVICE, backup_keybag_handle, error); -#else /* !USE_KEYSTORE */ - SecError(errSecParam, error, CFSTR("Why are you doing this?")); - backup = NULL; -#endif /* USE_KEYSTORE */ - } else { - backup = SecServerKeychainBackup(dbt, keybag, passcode, error); - } - - SecDbConnectionRelease(dbt); - - return backup; -} - -bool -_SecServerKeychainRestore(CFDataRef backup, 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); - }); - - if (ok) { - SecKeychainChanged(true); - } - - return ok; -} - - -/* - * - * - * SecItemDataSource - * - * - */ -static CFStringRef kSecItemDataSourceErrorDomain = CFSTR("com.apple.secitem.datasource"); - -enum { - kSecObjectMallocFailed = 1, - kSecAddDuplicateEntry, - kSecObjectNotFoundError, - kSOSAccountCreationFailed, -}; - -typedef struct SecItemDataSource *SecItemDataSourceRef; - -struct SecItemDataSource { - struct SOSDataSource ds; - SecDbRef db; - bool readOnly; - SecDbConnectionRef _dbconn; - unsigned gm_count; - unsigned cm_count; - unsigned co_count; - bool dv_loaded; - struct SOSDigestVector dv; - struct SOSDigestVector toadd; - struct SOSDigestVector todel; - SOSManifestRef manifest; - uint8_t manifest_digest[SOSDigestSize]; - bool changed; - bool syncWithPeersWhenDone; -}; - -static SecDbConnectionRef SecItemDataSourceGetConnection(SecItemDataSourceRef ds, CFErrorRef *error) { - if (!ds->_dbconn) { - ds->_dbconn = SecDbConnectionAquire(ds->db, ds->readOnly, error); - if (ds->_dbconn) { - ds->changed = false; - } else { - secerror("SecDbConnectionAquire failed: %@", error ? *error : NULL); - } - } - return ds->_dbconn; -} - -static bool SecItemDataSourceRecordUpdate(SecItemDataSourceRef ds, SecDbItemRef deleted, SecDbItemRef inserted, CFErrorRef *error) { - bool ok = true; - CFDataRef digest; - if (ds->dv_loaded) { - if (inserted) { - ok = digest = SecDbItemGetSHA1(inserted, error); - if (ok) SOSDigestVectorAppend(&ds->toadd, CFDataGetBytePtr(digest)); - } - if (ok && deleted) { - ok = digest = SecDbItemGetSHA1(deleted, error); - if (ok) SOSDigestVectorAppend(&ds->todel, CFDataGetBytePtr(digest)); - } - if (inserted || deleted) { - CFReleaseNull(ds->manifest); - ds->changed = true; - } - - if (!ok) { - ds->dv_loaded = false; - } - } - return ok; -} - -static bool SecItemDataSourceRecordAdd(SecItemDataSourceRef ds, SecDbItemRef inserted, CFErrorRef *error) { - return SecItemDataSourceRecordUpdate(ds, NULL, inserted, error); -} - -static bool SecDbItemSelectSHA1(SecDbQueryRef query, SecDbConnectionRef dbconn, CFErrorRef *error, - bool (^use_attr_in_where)(const SecDbAttr *attr), - bool (^add_where_sql)(CFMutableStringRef sql, bool *needWhere), - bool (^bind_added_where)(sqlite3_stmt *stmt, int col), - void (^row)(sqlite3_stmt *stmt, bool *stop)) { - __block bool ok = true; - bool (^return_attr)(const SecDbAttr *attr) = ^bool (const SecDbAttr * attr) { - return attr->kind == kSecDbSHA1Attr; - }; - CFStringRef sql = SecDbItemCopySelectSQL(query, return_attr, use_attr_in_where, add_where_sql); - if (sql) { - ok &= SecDbPrepare(dbconn, sql, error, ^(sqlite3_stmt *stmt) { - ok = (SecDbItemSelectBind(query, stmt, error, use_attr_in_where, bind_added_where) && - SecDbStep(dbconn, stmt, error, ^(bool *stop){ row(stmt, stop); })); - }); - CFRelease(sql); - } else { - ok = false; - } - return ok; -} - -static bool SecItemDataSourceLoadManifest(SecItemDataSourceRef ds, CFErrorRef *error) { - bool ok = true; - SecDbConnectionRef dbconn; - if (!(dbconn = SecItemDataSourceGetConnection(ds, error))) return false; - - /* Fetch all syncable items. */ - const SecDbClass *synced_classes[] = { - &genp_class, - &inet_class, - &keys_class, - }; - - ds->dv.count = 0; // Empty the digest vectory before we begin - CFErrorRef localError = NULL; - for (size_t class_ix = 0; class_ix < array_size(synced_classes); - ++class_ix) { - Query *q = query_create(synced_classes[class_ix], NULL, &localError); - if (q) { - q->q_return_type = kSecReturnDataMask | kSecReturnAttributesMask; - q->q_limit = kSecMatchUnlimited; - q->q_keybag = KEYBAG_DEVICE; - query_add_attribute(kSecAttrSynchronizable, kCFBooleanTrue, q); - //query_add_attribute(kSecAttrAccessible, ds->name, q); - // Select everything including tombstones that is synchronizable. - if (!SecDbItemSelectSHA1(q, dbconn, &localError, ^bool(const SecDbAttr *attr) { - return attr->kind == kSecDbSyncAttr; - }, NULL, NULL, ^(sqlite3_stmt *stmt, bool *stop) { - const uint8_t *digest = sqlite3_column_blob(stmt, 0); - size_t digestLen = sqlite3_column_bytes(stmt, 0); - if (digestLen != SOSDigestSize) { - secerror("digest %zu bytes", digestLen); - } else { - SOSDigestVectorAppend(&ds->dv, digest); - } - })) { - secerror("SecDbItemSelect failed: %@", localError); - CFReleaseNull(localError); - } - query_destroy(q, &localError); - if (localError) { - secerror("query_destroy failed: %@", localError); - CFReleaseNull(localError); - } - } else if (localError) { - secerror("query_create failed: %@", localError); - CFReleaseNull(localError); - } - } - SOSDigestVectorSort(&ds->dv); - return ok; -} - -static bool SecItemDataSourceEnsureFreshManifest(SecItemDataSourceRef ds, CFErrorRef *error) { - bool ok = true; - if (ds->dv_loaded && (ds->toadd.count || ds->todel.count)) { - CFErrorRef patchError = NULL; - struct SOSDigestVector new_dv = SOSDigestVectorInit; - ok = SOSDigestVectorPatch(&ds->dv, &ds->todel, &ds->toadd, &new_dv, &patchError); - if (!ok) secerror("patch failed %@ manifest: %@ toadd: %@ todel: %@", patchError, &ds->dv, &ds->todel, &ds->toadd); - CFReleaseSafe(patchError); - SOSDigestVectorFree(&ds->dv); - SOSDigestVectorFree(&ds->toadd); - SOSDigestVectorFree(&ds->todel); - ds->dv = new_dv; - } - // If we failed to patch or we haven't loaded yet, force a load from the db. - return (ok && ds->dv_loaded) || (ds->dv_loaded = SecItemDataSourceLoadManifest(ds, error)); -} - -/* DataSource protocol. */ -static bool ds_get_manifest_digest(SOSDataSourceRef data_source, uint8_t *out_digest, CFErrorRef *error) { - struct SecItemDataSource *ds = (struct SecItemDataSource *)data_source; - if (!ds->manifest) { - SOSManifestRef mf = data_source->copy_manifest(data_source, error); - if (mf) { - CFRelease(mf); - } else { - return false; - } - } - memcpy(out_digest, ds->manifest_digest, SOSDigestSize); - ds->gm_count++; - return true; -} - -static SOSManifestRef ds_copy_manifest(SOSDataSourceRef data_source, CFErrorRef *error) { - struct SecItemDataSource *ds = (struct SecItemDataSource *)data_source; - ds->cm_count++; - if (ds->manifest) { - CFRetain(ds->manifest); - return ds->manifest; - } - - if (!SecItemDataSourceEnsureFreshManifest(ds, error)) return NULL; - - ds->manifest = SOSManifestCreateWithBytes((const uint8_t *)ds->dv.digest, ds->dv.count * SOSDigestSize, error); - // TODO move digest - ccdigest(ccsha1_di(), SOSManifestGetSize(ds->manifest), SOSManifestGetBytePtr(ds->manifest), ds->manifest_digest); - - return (SOSManifestRef)CFRetain(ds->manifest); -} - -static bool ds_foreach_object(SOSDataSourceRef data_source, SOSManifestRef manifest, CFErrorRef *error, bool (^handle_object)(SOSObjectRef object, CFErrorRef *error)) { - struct SecItemDataSource *ds = (struct SecItemDataSource *)data_source; - ds->co_count++; - __block bool result = true; - const SecDbAttr *sha1Attr = SecDbClassAttrWithKind(&genp_class, kSecDbSHA1Attr, error); - if (!sha1Attr) return false; - bool (^return_attr)(const SecDbAttr *attr) = ^bool (const SecDbAttr * attr) { - return attr->kind == kSecDbRowIdAttr || attr->kind == kSecDbEncryptedDataAttr; - }; - bool (^use_attr_in_where)(const SecDbAttr *attr) = ^bool (const SecDbAttr * attr) { - return attr->kind == kSecDbSHA1Attr; - }; - const SecDbClass *synced_classes[] = { - &genp_class, - &inet_class, - &keys_class, - }; - Query *select_queries[array_size(synced_classes)]; - CFStringRef select_sql[array_size(synced_classes)]; - sqlite3_stmt *select_stmts[array_size(synced_classes)]; - - __block Query **queries = select_queries; - __block CFStringRef *sqls = select_sql; - __block sqlite3_stmt **stmts = select_stmts; - - SecDbConnectionRef dbconn; - result = dbconn = SecItemDataSourceGetConnection(ds, error); - - // Setup - for (size_t class_ix = 0; class_ix < array_size(synced_classes); ++class_ix) { - result = (result - && (queries[class_ix] = query_create(synced_classes[class_ix], 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))); - } - - if (result) SOSManifestForEach(manifest, ^(CFDataRef key) { - __block bool gotItem = false; - for (size_t class_ix = 0; result && !gotItem && class_ix < array_size(synced_classes); ++class_ix) { - CFDictionarySetValue(queries[class_ix]->q_item, sha1Attr->name, key); - result &= (SecDbItemSelectBind(queries[class_ix], stmts[class_ix], error, use_attr_in_where, NULL) && SecDbStep(dbconn, stmts[class_ix], error, ^(bool *stop) { - SecDbItemRef item = SecDbItemCreateWithStatement(kCFAllocatorDefault, queries[class_ix]->q_class, stmts[class_ix], KEYBAG_DEVICE, error, return_attr); - if (item) { - CFErrorRef localError=NULL; - gotItem = true; - // Stop on errors from handle_object, except decode errors - if(!(result=handle_object((SOSObjectRef)item, &localError))){ - if (SecErrorGetOSStatus(localError) == errSecDecode) { - const uint8_t *p=CFDataGetBytePtr(key); - secnotice("item", "Found corrupted item, removing from manifest key=%02X%02X%02X%02X, item=%@", p[0],p[1],p[2],p[3], item); - /* Removing from Manifest: */ - SOSDigestVectorAppend(&ds->todel, p); - CFReleaseNull(ds->manifest); - } else { - *stop=true; - } - if(error && *error == NULL) { - *error = localError; - localError = NULL; - } - } - CFRelease(item); - CFReleaseSafe(localError); - } - })) && SecDbReset(stmts[class_ix], error); - } - if (!gotItem) { - result = false; - if (error && !*error) { - SecCFCreateErrorWithFormat(kSecObjectNotFoundError, kSecItemDataSourceErrorDomain, NULL, error, 0, CFSTR("key %@ not in database"), key); - } - } - }); - - // Cleanup - for (size_t class_ix = 0; class_ix < array_size(synced_classes); ++class_ix) { - result &= SecDbReleaseCachedStmt(dbconn, sqls[class_ix], stmts[class_ix], error); - CFReleaseSafe(sqls[class_ix]); - result &= query_destroy(queries[class_ix], error); - } - return result; -} - -static void ds_dispose(SOSDataSourceRef data_source) { - struct SecItemDataSource *ds = (struct SecItemDataSource *)data_source; - if (ds->_dbconn) - SecDbConnectionRelease(ds->_dbconn); - if (ds->changed) - SecKeychainChanged(ds->syncWithPeersWhenDone); - CFReleaseSafe(ds->manifest); - SOSDigestVectorFree(&ds->dv); - free(ds); -} - -static SOSObjectRef ds_create_with_property_list(SOSDataSourceRef ds, CFDictionaryRef plist, CFErrorRef *error) { - SecDbItemRef item = NULL; - const SecDbClass *class = NULL; - CFTypeRef cname = CFDictionaryGetValue(plist, kSecClass); - if (cname) { - class = kc_class_with_name(cname); - if (class) { - item = SecDbItemCreateWithAttributes(kCFAllocatorDefault, class, plist, KEYBAG_DEVICE, error); - } else { - SecError(errSecNoSuchClass, error, CFSTR("can find class named: %@"), cname); - } - } else { - SecError(errSecItemClassMissing, error, CFSTR("query missing %@ attribute"), kSecClass); - } - return (SOSObjectRef)item; -} - -static CFDataRef ds_copy_digest(SOSObjectRef object, CFErrorRef *error) { - SecDbItemRef item = (SecDbItemRef) object; - CFDataRef digest = SecDbItemGetSHA1(item, error); - CFRetainSafe(digest); - return digest; -} - -static CFDataRef ds_copy_primary_key(SOSObjectRef object, CFErrorRef *error) { - SecDbItemRef item = (SecDbItemRef) object; - CFDataRef pk = SecDbItemGetPrimaryKey(item, error); - CFRetainSafe(pk); - return pk; -} - -static CFDictionaryRef ds_copy_property_list(SOSObjectRef object, CFErrorRef *error) { - SecDbItemRef item = (SecDbItemRef) object; - CFMutableDictionaryRef plist = SecDbItemCopyPListWithMask(item, kSecDbInCryptoDataFlag, error); - if (plist) - CFDictionaryAddValue(plist, kSecClass, SecDbItemGetClass(item)->name); - return plist; -} - -// Return the newest object -static SOSObjectRef ds_copy_merged_object(SOSObjectRef object1, SOSObjectRef object2, CFErrorRef *error) { - SecDbItemRef item1 = (SecDbItemRef) object1; - SecDbItemRef item2 = (SecDbItemRef) object2; - SOSObjectRef result = NULL; - CFDateRef m1, m2; - const SecDbAttr *desc = SecDbAttrWithKey(SecDbItemGetClass(item1), kSecAttrModificationDate, error); - m1 = SecDbItemGetValue(item1, desc, error); - if (!m1) - return NULL; - m2 = SecDbItemGetValue(item2, desc, error); - if (!m2) - return NULL; - switch (CFDateCompare(m1, m2, NULL)) { - case kCFCompareGreaterThan: - result = (SOSObjectRef)item1; - break; - case kCFCompareLessThan: - result = (SOSObjectRef)item2; - break; - case kCFCompareEqualTo: - { - // Return the item with the smallest digest. - CFDataRef digest1 = ds_copy_digest(object1, error); - CFDataRef digest2 = ds_copy_digest(object2, error); - if (digest1 && digest2) switch (CFDataCompare(digest1, digest2)) { - case kCFCompareGreaterThan: - case kCFCompareEqualTo: - result = (SOSObjectRef)item2; - break; - case kCFCompareLessThan: - result = (SOSObjectRef)item1; - break; - } - CFReleaseSafe(digest2); - CFReleaseSafe(digest1); - break; - } - } - CFRetainSafe(result); - return result; -} - -static SOSMergeResult dsMergeObject(SOSDataSourceRef data_source, SOSObjectRef peersObject, CFErrorRef *error) { - struct SecItemDataSource *ds = (struct SecItemDataSource *)data_source; - SecDbItemRef peersItem = (SecDbItemRef)peersObject; - SecDbConnectionRef dbconn = SecItemDataSourceGetConnection(ds, error); - __block SOSMergeResult mr = kSOSMergeFailure; - __block SecDbItemRef mergedItem = NULL; - __block SecDbItemRef replacedItem = NULL; - if (!peersItem || !dbconn || !SecDbItemSetKeybag(peersItem, KEYBAG_DEVICE, error)) return mr; - if (SecDbItemInsertOrReplace(peersItem, dbconn, error, ^(SecDbItemRef myItem, SecDbItemRef *replace) { - // An item with the same primary key as dbItem already exists in the the database. That item is old_item. - // Let the conflict resolver choose which item to keep. - mergedItem = (SecDbItemRef)ds_copy_merged_object(peersObject, (SOSObjectRef)myItem, error); - if (!mergedItem) return; - if (CFEqual(mergedItem, myItem)) { - // Conflict resolver choose my (local) item - mr = kSOSMergeLocalObject; - } else { - CFRetainSafe(myItem); - replacedItem = myItem; - CFRetainSafe(mergedItem); - *replace = mergedItem; - if (CFEqual(mergedItem, peersItem)) { - // Conflict resolver choose peers item - mr = kSOSMergePeersObject; - } else { - mr = kSOSMergeCreatedObject; - } - } - })) { - if (mr == kSOSMergeFailure) { - mr = kSOSMergePeersObject; - SecItemDataSourceRecordAdd(ds, peersItem, error); - } else if (mr != kSOSMergeLocalObject) { - SecItemDataSourceRecordUpdate(ds, replacedItem, mergedItem, error); - } - } - - if (error && *error && mr != kSOSMergeFailure) - CFReleaseNull(*error); - - CFReleaseSafe(mergedItem); - CFReleaseSafe(replacedItem); - return mr; -} - - -/* - Truthy backup format is a dictionary from sha1 => item. - Each item has class, hash and item data. - - TODO: sha1 is included as binary blob to avoid parsing key. - */ -enum { - kSecBackupIndexHash = 0, - kSecBackupIndexClass, - kSecBackupIndexData, -}; - -static const void *kSecBackupKeys[] = { - [kSecBackupIndexHash] = CFSTR("hash"), - [kSecBackupIndexClass] = CFSTR("class"), - [kSecBackupIndexData] = CFSTR("data"), -}; - -#define kSecBackupHash kSecBackupKeys[kSecBackupIndexHash] -#define kSecBackupClass kSecBackupKeys[kSecBackupIndexClass] -#define kSecBackupData kSecBackupKeys[kSecBackupIndexData] - -static CFDictionaryRef ds_backup_object(SOSObjectRef object, uint64_t handle, CFErrorRef *error) { - const void *values[array_size(kSecBackupKeys)]; - SecDbItemRef item = (SecDbItemRef)object; - CFDictionaryRef backup_item = NULL; - - if ((values[kSecBackupIndexHash] = SecDbItemGetSHA1(item, error))) { - if ((values[kSecBackupIndexData] = SecDbItemCopyEncryptedDataToBackup(item, handle, error))) { - values[kSecBackupIndexClass] = SecDbItemGetClass(item)->name; - backup_item = CFDictionaryCreate(kCFAllocatorDefault, kSecBackupKeys, values, array_size(kSecBackupKeys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFRelease(values[kSecBackupIndexData]); - } - } - - return backup_item; -} - -static bool ds_restore_object(SOSDataSourceRef data_source, uint64_t handle, CFDictionaryRef item, CFErrorRef *error) { - struct SecItemDataSource *ds = (struct SecItemDataSource *)data_source; - SecDbConnectionRef dbconn = SecItemDataSourceGetConnection(ds, error); - if (!dbconn) return false; - - CFStringRef item_class = CFDictionaryGetValue(item, kSecBackupClass); - CFDataRef data = CFDictionaryGetValue(item, kSecBackupData); - const SecDbClass *dbclass = NULL; - - if (!item_class || !data) - return SecError(errSecDecode, error, CFSTR("no class or data in object")); - - dbclass = kc_class_with_name(item_class); - if (!dbclass) - return SecError(errSecDecode, error, CFSTR("no such class %@; update kc_class_with_name "), item_class); - - __block SecDbItemRef dbitem = SecDbItemCreateWithEncryptedData(kCFAllocatorDefault, dbclass, data, (keybag_handle_t)handle, error); - if (!dbitem) - return false; - - __block bool ok = SecDbItemSetKeybag(dbitem, KEYBAG_DEVICE, error); - - if (ok) { - __block SecDbItemRef replaced_item = NULL; - ok &= SecDbItemInsertOrReplace(dbitem, dbconn, error, ^(SecDbItemRef old_item, SecDbItemRef *replace) { - // An item with the same primary key as dbItem already exists in the the database. That item is old_item. - // Let the conflict resolver choose which item to keep. - SecDbItemRef chosen_item = (SecDbItemRef)ds_copy_merged_object((SOSObjectRef)dbitem, (SOSObjectRef)old_item, error); - if (chosen_item) { - if (CFEqual(chosen_item, old_item)) { - // We're keeping the exisiting item, so we don't need to change anything. - CFRelease(chosen_item); - CFReleaseNull(dbitem); - } else { - // We choose a different item than what's in the database already. Let's set dbitem to what - // we are replacing the item in the database with, and set replaced_item to the item we are replacing. - CFRelease(dbitem); // Release the item created via SecDbItemCreateWithEncryptedData - // Record what we put in the database - CFRetain(chosen_item); // retain what we are about to return in *replace, since SecDbItemInsertOrReplace() CFReleases it. - *replace = dbitem = chosen_item; - // Record that we are replaced old_item in replaced_item. - CFRetain(old_item); - replaced_item = old_item; - } - } else { - ok = false; - } - }) - && SecItemDataSourceRecordUpdate(ds, replaced_item, dbitem, error); - CFReleaseSafe(replaced_item); - } - CFReleaseSafe(dbitem); - - return ok; -} - - -static SOSDataSourceRef SecItemDataSourceCreate(SecDbRef db, bool readOnly, bool syncWithPeersWhenDone, CFErrorRef *error) { - __block SecItemDataSourceRef ds = calloc(1, sizeof(struct SecItemDataSource)); - ds->ds.get_manifest_digest = ds_get_manifest_digest; - ds->ds.copy_manifest = ds_copy_manifest; - ds->ds.foreach_object = ds_foreach_object; - ds->ds.release = ds_dispose; - ds->ds.add = dsMergeObject; - - ds->ds.createWithPropertyList = ds_create_with_property_list; - ds->ds.copyDigest = ds_copy_digest; - ds->ds.copyPrimaryKey = ds_copy_primary_key; - ds->ds.copyPropertyList = ds_copy_property_list; - ds->ds.copyMergedObject = ds_copy_merged_object; - ds->ds.backupObject = ds_backup_object; - ds->ds.restoreObject = ds_restore_object; - - ds->syncWithPeersWhenDone = syncWithPeersWhenDone; - ds->db = (SecDbRef)CFRetain(db); - ds->readOnly = readOnly; - - ds->changed = false; - struct SOSDigestVector dv = SOSDigestVectorInit; - ds->dv = dv; - - return (SOSDataSourceRef)ds; -} - -static CFArrayRef SecItemDataSourceFactoryCopyNames(SOSDataSourceFactoryRef factory) -{ - return CFArrayCreateForCFTypes(kCFAllocatorDefault, - kSecAttrAccessibleWhenUnlocked, - //kSecAttrAccessibleAfterFirstUnlock, - //kSecAttrAccessibleAlways, - NULL); -} - -struct SecItemDataSourceFactory { - struct SOSDataSourceFactory factory; - SecDbRef db; -}; - - -static SOSDataSourceRef SecItemDataSourceFactoryCopyDataSource(SOSDataSourceFactoryRef factory, CFStringRef dataSourceName, bool readOnly, CFErrorRef *error) -{ - struct SecItemDataSourceFactory *f = (struct SecItemDataSourceFactory *)factory; - return SecItemDataSourceCreate(f->db, readOnly, false, error); -} - -static void SecItemDataSourceFactoryDispose(SOSDataSourceFactoryRef factory) -{ - struct SecItemDataSourceFactory *f = (struct SecItemDataSourceFactory *)factory; - CFReleaseSafe(f->db); - free(f); -} - -SOSDataSourceFactoryRef SecItemDataSourceFactoryCreate(SecDbRef db) { - struct SecItemDataSourceFactory *dsf = calloc(1, sizeof(struct SecItemDataSourceFactory)); - dsf->factory.copy_names = SecItemDataSourceFactoryCopyNames; - dsf->factory.create_datasource = SecItemDataSourceFactoryCopyDataSource; - dsf->factory.release = SecItemDataSourceFactoryDispose; - CFRetainSafe(db); - dsf->db = db; - - return &dsf->factory; -} - -SOSDataSourceFactoryRef SecItemDataSourceFactoryCreateDefault(void) { - return SecItemDataSourceFactoryCreate(kc_dbhandle()); -} - -void SecItemServerAppendItemDescription(CFMutableStringRef desc, CFDictionaryRef object) { - SOSObjectRef item = ds_create_with_property_list(NULL, object, NULL); - if (item) { - CFStringRef itemDesc = CFCopyDescription(item); - if (itemDesc) { - CFStringAppend(desc, itemDesc); - CFReleaseSafe(itemDesc); - } - CFRelease(item); - } -} - -/* AUDIT[securityd]: - args_in (ok) is a caller provided, CFDictionaryRef. - */ -bool -_SecServerKeychainSyncUpdate(CFDictionaryRef updates, CFErrorRef *error) { - // This never fails, trust us! - CFRetainSafe(updates); - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - SOSCCHandleUpdate(updates); - CFReleaseSafe(updates); - }); - return true; -} - -// -// Truthiness in the cloud backup/restore support. -// - -static CFStringRef SOSCopyItemKey(SOSDataSourceRef ds, SOSObjectRef object, CFErrorRef *error) -{ - CFStringRef item_key = NULL; - CFDataRef digest_data = ds->copyDigest(object, error); - if (digest_data) { - item_key = CFDataCopyHexString(digest_data); - CFRelease(digest_data); - } - return item_key; -} - -static SOSManifestRef SOSCopyManifestFromBackup(CFDictionaryRef backup) -{ - CFMutableDataRef manifest = CFDataCreateMutable(kCFAllocatorDefault, 0); - if (backup) { - CFDictionaryForEach(backup, ^void (const void * key, const void * value) { - if (isDictionary(value)) { - /* converting key back to binary blob is horrible */ - CFDataRef sha1 = CFDictionaryGetValue(value, kSecBackupHash); - if (isData(sha1)) - CFDataAppend(manifest, sha1); - } - }); - } - return (SOSManifestRef)manifest; -} - -static CFDictionaryRef -_SecServerCopyTruthInTheCloud(CFDataRef keybag, CFDataRef password, - CFDictionaryRef backup, CFErrorRef *error) -{ - SOSManifestRef mold = NULL, mnow = NULL, mdelete = NULL, madd = NULL; - CFErrorRef foreachError = NULL; - CFDictionaryRef backup_out = NULL; - keybag_handle_t bag_handle; - if (!ks_open_keybag(keybag, password, &bag_handle, error)) - return NULL; - - CFMutableDictionaryRef backup_new = NULL; - SOSDataSourceRef ds = SecItemDataSourceCreate(kc_dbhandle(), true, false, error); - if (ds) { - backup_new = backup ? CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, backup) : CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - mold = SOSCopyManifestFromBackup(backup); - mnow = ds->copy_manifest(ds, error); - SOSManifestDiff(mold, mnow, &mdelete, &madd, error); - - // Delete everything from the new_backup that is no longer in the datasource according to the datasources manifest. - SOSManifestForEach(mdelete, ^(CFDataRef digest_data) { - CFStringRef deleted_item_key = CFDataCopyHexString(digest_data); - CFDictionaryRemoveValue(backup_new, deleted_item_key); - CFRelease(deleted_item_key); - }); - - if(!ds->foreach_object(ds, madd, &foreachError, ^bool(SOSObjectRef object, CFErrorRef *localError) { - bool ok = true; - CFStringRef key = SOSCopyItemKey(ds, object, localError); - CFTypeRef value = ds->backupObject(object, bag_handle, localError); - - if (!key || !value) { - ok = false; - } else { - CFDictionarySetValue(backup_new, key, value); - } - CFReleaseSafe(key); - CFReleaseSafe(value); - return ok; - })) { - if(!SecErrorGetOSStatus(foreachError)==errSecDecode) { - if(error && *error==NULL) { - *error = foreachError; - foreachError = NULL; - } - goto out; - } - } - - backup_out = backup_new; - backup_new = NULL; - } - -out: - if(ds) - ds->release(ds); - - CFReleaseSafe(foreachError); - CFReleaseSafe(mold); - CFReleaseSafe(mnow); - CFReleaseSafe(madd); - CFReleaseSafe(mdelete); - CFReleaseSafe(backup_new); - - if (!ks_close_keybag(bag_handle, error)) - CFReleaseNull(backup_out); - - return backup_out; -} - -static bool -_SecServerRestoreTruthInTheCloud(CFDataRef keybag, CFDataRef password, CFDictionaryRef backup_in, CFErrorRef *error) { - __block bool ok = true; - keybag_handle_t bag_handle; - if (!ks_open_keybag(keybag, password, &bag_handle, error)) - return false; - - SOSManifestRef mbackup = SOSCopyManifestFromBackup(backup_in); - if (mbackup) { - SOSDataSourceRef ds = SecItemDataSourceCreate(kc_dbhandle(), false, true, error); - if (ds) { - SOSManifestRef mnow = ds->copy_manifest(ds, error); - SOSManifestRef mdelete = NULL, madd = NULL; - SOSManifestDiff(mnow, mbackup, &mdelete, &madd, error); - - // Don't delete everything in datasource not in backup. - - // Add items from the backup - SOSManifestForEach(madd, ^void(CFDataRef e) { - CFDictionaryRef item = NULL; - CFStringRef sha1 = CFDataCopyHexString(e); - if (sha1) { - item = CFDictionaryGetValue(backup_in, sha1); - CFRelease(sha1); - } - if (item) { - CFErrorRef localError = NULL; - if (!ds->restoreObject(ds, bag_handle, item, &localError)) { - if (SecErrorGetOSStatus(localError) == errSecDuplicateItem) { - // Log and ignore duplicate item errors during restore - secnotice("titc", "restore %@ not replacing existing item", item); - } else { - // Propagate the first other error upwards (causing the restore to fail). - secerror("restore %@ failed %@", item, localError); - ok = false; - if (error && !*error) { - *error = localError; - localError = NULL; - } - } - CFReleaseSafe(localError); - } - } - }); - - ds->release(ds); - CFReleaseNull(mdelete); - CFReleaseNull(madd); - CFReleaseNull(mnow); - } else { - ok = false; - } - CFRelease(mbackup); - } - - ok &= ks_close_keybag(bag_handle, error); - - return ok; -} - - -CF_RETURNS_RETAINED CFDictionaryRef -_SecServerBackupSyncable(CFDictionaryRef backup, CFDataRef keybag, CFDataRef password, CFErrorRef *error) { - require_action_quiet(isData(keybag), errOut, SecError(errSecParam, error, CFSTR("keybag %@ not a data"), keybag)); - require_action_quiet(!backup || isDictionary(backup), errOut, SecError(errSecParam, error, CFSTR("backup %@ not a dictionary"), backup)); - require_action_quiet(!password || isData(password), errOut, SecError(errSecParam, error, CFSTR("password %@ not a data"), password)); - - return _SecServerCopyTruthInTheCloud(keybag, password, backup, error); - -errOut: - return NULL; -} - -bool -_SecServerRestoreSyncable(CFDictionaryRef backup, CFDataRef keybag, CFDataRef password, CFErrorRef *error) { - bool ok; - 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"))); - } - - ok = _SecServerRestoreTruthInTheCloud(keybag, password, backup, error); - -errOut: - return ok; -} - - - diff --git a/sec/securityd/SecItemServer.h b/sec/securityd/SecItemServer.h deleted file mode 100644 index 5bb0ba9f..00000000 --- a/sec/securityd/SecItemServer.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2007-2009,2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * 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 SecItemServer - The functions provided in SecItemServer.h provide an interface to - the backed for SecItem APIs in the server. -*/ - -#ifndef _SECURITYD_SECITEMSERVER_H_ -#define _SECURITYD_SECITEMSERVER_H_ - -#include -#include -#include -#include - -__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 _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); -CFDataRef _SecServerKeychainBackup(CFDataRef keybag, CFDataRef passcode, CFErrorRef *error); -bool _SecServerKeychainRestore(CFDataRef backup, CFDataRef keybag, CFDataRef passcode, CFErrorRef *error); -bool _SecServerKeychainSyncUpdate(CFDictionaryRef updates, CFErrorRef *error); -CFDictionaryRef _SecServerBackupSyncable(CFDictionaryRef backup, CFDataRef keybag, CFDataRef password, CFErrorRef *error); -bool _SecServerRestoreSyncable(CFDictionaryRef backup, CFDataRef keybag, CFDataRef password, CFErrorRef *error); - -// Hack to log objects from inside SOS code -void SecItemServerAppendItemDescription(CFMutableStringRef desc, CFDictionaryRef object); - -// These are visible for testing. -SOSDataSourceFactoryRef SecItemDataSourceFactoryCreate(SecDbRef db); -SOSDataSourceFactoryRef SecItemDataSourceFactoryCreateDefault(void); - -/* FIXME: there is a specific type for keybag handle (keybag_handle_t) - but it's not defined for simulator so we just use an int32_t */ -void SecItemServerSetKeychainKeybag(int32_t keybag); -void SecItemServerResetKeychainKeybag(void); - -void SecItemServerSetKeychainChangedNotification(const char *notification_name); - -CFStringRef __SecKeychainCopyPath(void); - -__END_DECLS - -#endif /* _SECURITYD_SECITEMSERVER_H_ */ diff --git a/sec/securityd/entitlements.plist b/sec/securityd/entitlements.plist deleted file mode 100644 index e3248a6c..00000000 --- a/sec/securityd/entitlements.plist +++ /dev/null @@ -1,12 +0,0 @@ - - - - - application-identifier - com.apple.securityd - com.apple.keystore.access-keychain-keys - - com.apple.keystore.lockassertion - - - diff --git a/sec/securityd/spi.c b/sec/securityd/spi.c deleted file mode 100644 index 711dde25..00000000 --- a/sec/securityd/spi.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * spi.c - * Security - * - * Created by Michael Brouwer on 1/28/09. - * Copyright (c) 2009-2010 Apple Inc.. All Rights Reserved. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "securityd_client.h" -#include -#include "utilities/iOSforOSX.h" -#include "utilities/SecFileLocations.h" -#include "OTATrustUtilities.h" - -static struct securityd spi = { - .sec_item_add = _SecItemAdd, - .sec_item_copy_matching = _SecItemCopyMatching, - .sec_item_update = _SecItemUpdate, - .sec_item_delete = _SecItemDelete, - .sec_trust_store_for_domain = SecTrustStoreForDomainName, - .sec_trust_store_contains = SecTrustStoreContainsCertificateWithDigest, - .sec_trust_store_set_trust_settings = _SecTrustStoreSetTrustSettings, - .sec_trust_store_remove_certificate = SecTrustStoreRemoveCertificateWithDigest, - .sec_truststore_remove_all = _SecTrustStoreRemoveAll, - .sec_item_delete_all = _SecItemDeleteAll, - .sec_trust_evaluate = SecTrustServerEvaluate, - .sec_keychain_backup = _SecServerKeychainBackup, - .sec_keychain_restore = _SecServerKeychainRestore, - .sec_keychain_sync_update = _SecServerKeychainSyncUpdate, - .sec_keychain_backup_syncable = _SecServerBackupSyncable, - .sec_keychain_restore_syncable = _SecServerRestoreSyncable, - .sec_ota_pki_asset_version = SecOTAPKIGetCurrentAssetVersion, - .soscc_TryUserCredentials = SOSCCTryUserCredentials_Server, - .soscc_SetUserCredentials = SOSCCSetUserCredentials_Server, - .soscc_CanAuthenticate = SOSCCCanAuthenticate_Server, - .soscc_PurgeUserCredentials = SOSCCPurgeUserCredentials_Server, - .soscc_ThisDeviceIsInCircle = SOSCCThisDeviceIsInCircle_Server, - .soscc_RequestToJoinCircle = SOSCCRequestToJoinCircle_Server, - .soscc_RequestToJoinCircleAfterRestore = SOSCCRequestToJoinCircleAfterRestore_Server, - .soscc_ResetToOffering = SOSCCResetToOffering_Server, - .soscc_ResetToEmpty = SOSCCResetToEmpty_Server, - .soscc_RemoveThisDeviceFromCircle = SOSCCRemoveThisDeviceFromCircle_Server, - .soscc_BailFromCircle = SOSCCBailFromCircle_Server, - .soscc_AcceptApplicants = SOSCCAcceptApplicants_Server, - .soscc_RejectApplicants = SOSCCRejectApplicants_Server, - .soscc_CopyApplicantPeerInfo = SOSCCCopyApplicantPeerInfo_Server, - .soscc_CopyPeerInfo = SOSCCCopyPeerPeerInfo_Server, - .soscc_CopyConcurringPeerInfo = SOSCCCopyConcurringPeerPeerInfo_Server, - .ota_CopyEscrowCertificates = SecOTAPKICopyCurrentEscrowCertificates, - .sec_ota_pki_get_new_asset = SecOTAPKISignalNewAsset, - .soscc_ProcessSyncWithAllPeers = SOSCCProcessSyncWithAllPeers_Server -}; - -void securityd_init_server(void) { - gSecurityd = &spi; - SecPolicyServerInitalize(); -} - -void securityd_init(char* home_path) { - if (home_path) - SetCustomHomeURL(home_path); - - securityd_init_server(); -} diff --git a/sec/securityd/spi.h b/sec/securityd/spi.h deleted file mode 100644 index ceb2bca7..00000000 --- a/sec/securityd/spi.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2009-2010 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 _SECURITYD_SPI_H_ -#define _SECURITYD_SPI_H_ - -#include -#include - -__BEGIN_DECLS - -/* Calling this function initializes the spi interface in the library to call - directly into the backend. It uses home_dir for root of files if specified. */ -void securityd_init(char* home_dir); - -// Don't call this function unless you are really securityd -void securityd_init_server(void); - -__END_DECLS - -#endif /* _SECURITYD_SPI_H_ */ diff --git a/secdtests/main.c b/secdtests/main.c index fb6392e8..ce2c7c92 100644 --- a/secdtests/main.c +++ b/secdtests/main.c @@ -1,16 +1,13 @@ -/* - * main.c - * Security - * - * Created by Fabrice Gautier on 8/7/12. - * Copyright 2012 Apple, Inc. All rights reserved. - * - */ +// +// main.c +// secdtest +// +// Created by Fabrice Gautier on 5/29/13. +// +// #include -#include - -#include "test/testenv.h" +#include #include "testlist.h" #include @@ -19,19 +16,14 @@ #include -int main(int argc, char *argv[]) +int main(int argc, char * const *argv) { - printf("Build date : %s %s\n", __DATE__, __TIME__); - - /* We run this as if we are secd, so we need to initialize this */ securityd_init(NULL); int result = tests_begin(argc, argv); - fflush(stderr); fflush(stdout); - - sleep(1); + fflush(stderr); return result; } diff --git a/secdtests/secdtests-entitlements.plist b/secdtests/secdtests-entitlements.plist new file mode 100644 index 00000000..c910e269 --- /dev/null +++ b/secdtests/secdtests-entitlements.plist @@ -0,0 +1,40 @@ + + + + + keychain-cloud-circle + + com.apple.keystore.access-keychain-keys + + com.apple.keystore.device + + restore-keychain + + migrate-keychain + + modify-anchor-certificates + + com.apple.springboard.wipedevice + + application-identifier + com.apple.security.regressions + keychain-access-groups + + com.apple.security.regressions + lockdown-identities + apple + + com.apple.private.ubiquity-kvstore-access + + com.apple.securityd + + com.apple.developer.ubiquity-kvstore-identifier + com.apple.security.cloudkeychainproxy + com.apple.developer.ubiquity-container-identifiers + + com.apple.security.cloudkeychainproxy + com.apple.security.cloudkeychain + CloudKeychainProxy.xpc + + + diff --git a/secdtests/testlist.h b/secdtests/testlist.h index e4b0f70a..65e1aef4 100644 --- a/secdtests/testlist.h +++ b/secdtests/testlist.h @@ -1,4 +1,2 @@ -/* Don't prevent multiple inclusion of this file. */ -#include -#include -#include +/* Don't preent multiple inclusions of this file */ +#include diff --git a/sectask/SecEntitlements.h b/sectask/SecEntitlements.h new file mode 100644 index 00000000..17fd6142 --- /dev/null +++ b/sectask/SecEntitlements.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2008-2010,2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* This file contains the names of all known entitlements currently + in use on the system. */ + +#ifndef _SECURITY_SECENTITLEMENTS_H_ +#define _SECURITY_SECENTITLEMENTS_H_ + +#include + +__BEGIN_DECLS + +/* Allow other tasks to get this task's name port. This is needed so the app + can be debugged. */ +#define kSecEntitlementGetTaskAllow CFSTR("get-task-allow") + +#if TARGET_OS_IPHONE +/* The identifier of this application, typically the same as the + CFBundleIdentifier. Used as the default access group for any keychain + items this application creates and accesses. */ +#define kSecEntitlementApplicationIdentifier CFSTR("application-identifier") +#else +/* The identifier of this application, for Mac App Store applications. */ +#define kSecEntitlementAppleApplicationIdentifier CFSTR("com.apple.application-identifier") +#define kSecEntitlementApplicationIdentifier kSecEntitlementAppleApplicationIdentifier +#endif + +/* The value should be an array of strings. Each string is the name of an + access group that the application has access to. The + application-identifier is implicitly added to this list. When creating + a new keychain item use the kSecAttrAccessGroup attribute (defined in + ) to specify its access group. If omitted, the + access group defaults to the first access group in this list or the + application-identifier if there is no keychain-access-groups entitlement. */ +#define kSecEntitlementKeychainAccessGroups CFSTR("keychain-access-groups") + +/* The value should be an array of strings. Each string is the name of an + access group that the application has access to. The first of + kSecEntitlementKeychainAccessGroups, + kSecEntitlementApplicationIdentifier or + kSecEntitlementAppleSecurityApplicationGroups to have a value becomes the default + application group for keychain clients that don't specify an explicit one. */ +#define kSecEntitlementAppleSecurityApplicationGroups CFSTR("com.apple.security.application-groups") + +/* Boolean entitlement, if present the application with the entitlement is + allowed to modify the which certificates are trusted as anchors using + the SecTrustStoreSetTrustSettings() and SecTrustStoreRemoveCertificate() + SPIs. */ +#define kSecEntitlementModifyAnchorCertificates CFSTR("modify-anchor-certificates") + +#define kSecEntitlementDebugApplications CFSTR("com.apple.springboard.debugapplications") + +#define kSecEntitlementOpenSensitiveURL CFSTR("com.apple.springboard.opensensitiveurl") + +/* Boolean entitlement, if present allows the application to wipe the keychain + and truststore. */ +#define kSecEntitlementWipeDevice CFSTR("com.apple.springboard.wipedevice") + +#define kSecEntitlementRemoteNotificationConfigure CFSTR("com.apple.remotenotification.configure") + +#define kSecEntitlementMigrateKeychain CFSTR("migrate-keychain") + +#define kSecEntitlementRestoreKeychain CFSTR("restore-keychain") + +/* Entitlement needed to call SecKeychainSyncUpdate SPI. */ +#define kSecEntitlementKeychainSyncUpdates CFSTR("keychain-sync-updates") + +/* Boolean entitlement, if present you get access to the SPIs for keychain sync circle manipulation */ +#define kSecEntitlementKeychainCloudCircle CFSTR("keychain-cloud-circle") + +/* Associated Domains entitlement (contains array of fully-qualified domain names) */ +#define kSecEntitlementAssociatedDomains CFSTR("com.apple.developer.associated-domains") + +/* Entitlement needed to call swcd and swcagent processes. */ +#define kSecEntitlementPrivateAssociatedDomains CFSTR("com.apple.private.associated-domains") + +__END_DECLS + +#endif /* !_SECURITY_SECENTITLEMENTS_H_ */ diff --git a/sectask/SecTask.c b/sectask/SecTask.c new file mode 100644 index 00000000..5932609e --- /dev/null +++ b/sectask/SecTask.c @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2008,2010-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 "SecTask.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define USE_LIBPROC 0 +#if USE_LIBPROC +#include +#else +#include +#endif + +struct __SecTask { + CFRuntimeBase base; + + pid_t pid_self; + audit_token_t token; + + /* Track whether we've loaded entitlements independently since after the + * load, entitlements may legitimately be NULL */ + Boolean entitlementsLoaded; + CFDictionaryRef entitlements; +}; + +static bool check_task(SecTaskRef task) { + return SecTaskGetTypeID() == CFGetTypeID(task); +} + +static void SecTaskFinalize(CFTypeRef cfTask) +{ + SecTaskRef task = (SecTaskRef) cfTask; + + if (task->entitlements != NULL) { + CFRelease(task->entitlements); + task->entitlements = NULL; + } +} + + +// Define PRIdPID (proper printf format string for pid_t) +#define PRIdPID PRId32 + +static CFStringRef SecTaskCopyDebugDescription(CFTypeRef cfTask) +{ + SecTaskRef task = (SecTaskRef) cfTask; + pid_t pid; + if (task->pid_self==-1) { + audit_token_to_au32(task->token, NULL, NULL, NULL, NULL, NULL, &pid, NULL, NULL); + } else { + pid = task->pid_self; + } + +#if USE_LIBPROC +#define MAX_PROCNAME 32 + char task_name[MAX_PROCNAME + 1] = {}; + proc_name(pid, task_name, MAX_PROCNAME); +#else + const char *task_name; + int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; + struct kinfo_proc kp; + size_t len = sizeof(kp); + if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1 || len == 0) + task_name = strerror(errno); + else + task_name = kp.kp_proc.p_comm; +#endif + + return CFStringCreateWithFormat(CFGetAllocator(task), NULL, CFSTR("%s[%" PRIdPID "]"), task_name, pid); +} + +CFGiblisWithFunctions(SecTask, NULL, NULL, SecTaskFinalize, NULL, NULL, NULL, SecTaskCopyDebugDescription, NULL, NULL, NULL) + +static SecTaskRef init_task_ref(CFAllocatorRef allocator) +{ + CFIndex extra = sizeof(struct __SecTask) - sizeof(CFRuntimeBase); + return (SecTaskRef) _CFRuntimeCreateInstance(allocator, SecTaskGetTypeID(), extra, NULL); +} + +SecTaskRef SecTaskCreateFromSelf(CFAllocatorRef allocator) +{ + SecTaskRef task = init_task_ref(allocator); + if (task != NULL) { + + memset(&task->token, 0, sizeof(task->token)); + task->entitlementsLoaded = false; + task->entitlements = NULL; + task->pid_self = getpid(); + } + + return task; +} + +SecTaskRef SecTaskCreateWithAuditToken(CFAllocatorRef allocator, audit_token_t token) +{ + SecTaskRef task = init_task_ref(allocator); + if (task != NULL) { + + memcpy(&task->token, &token, sizeof(token)); + task->entitlementsLoaded = false; + task->entitlements = NULL; + task->pid_self = -1; + } + + return task; +} + +struct csheader { + uint32_t magic; + uint32_t length; +}; + +static int +csops_task(SecTaskRef task, int ops, void *blob, size_t size) +{ + if (task->pid_self==-1) { + pid_t pid; + audit_token_to_au32(task->token, NULL, NULL, NULL, NULL, NULL, &pid, NULL, NULL); + return csops_audittoken(pid, ops, blob, size, &task->token); + } + else + return csops(task->pid_self, ops, blob, size); +} + +/* This may need to be exported at some point */ +CFStringRef +SecTaskCopySigningIdentifier(SecTaskRef task, CFErrorRef *error) +{ + CFStringRef signingId = NULL; + char *data = NULL; + struct csheader header; + uint32_t bufferlen; + int ret; + + ret = csops_task(task, CS_OPS_IDENTITY, &header, sizeof(header)); + if (ret != -1 || errno != ERANGE) + return NULL; + + bufferlen = ntohl(header.length); + /* check for insane values */ + if (bufferlen > 1024 * 1024 || bufferlen < 8) { + ret = EINVAL; + goto out; + } + data = malloc(bufferlen + 1); + if (data == NULL) { + ret = ENOMEM; + goto out; + } + ret = csops_task(task, CS_OPS_IDENTITY, data, bufferlen); + if (ret) { + ret = errno; + goto out; + } + data[bufferlen] = '\0'; + + signingId = CFStringCreateWithCString(NULL, data + 8, kCFStringEncodingUTF8); + + out: + if (data) + free(data); + if (ret && error) + *error = CFErrorCreate(NULL, kCFErrorDomainPOSIX, ret, NULL); + + return signingId; +} + + +static bool SecTaskLoadEntitlements(SecTaskRef task, CFErrorRef *error) +{ + CFMutableDictionaryRef entitlements = NULL; + struct csheader header; + uint8_t *buffer = NULL; + uint32_t bufferlen; + int ret; + + + ret = csops_task(task, CS_OPS_ENTITLEMENTS_BLOB, &header, sizeof(header)); + /* Any other combination means no entitlements */ + if (ret == -1 && errno == ERANGE) { + bufferlen = ntohl(header.length); + /* check for insane values */ + if (bufferlen > 1024 * 1024 || bufferlen < 8) { + ret = EINVAL; + goto out; + } + buffer = malloc(bufferlen); + if (buffer == NULL) { + ret = ENOMEM; + goto out; + } + ret = csops_task(task, CS_OPS_ENTITLEMENTS_BLOB, buffer, bufferlen); + if (ret) { + ret = errno; + goto out; + } + + CFDataRef data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, buffer+8, bufferlen-8, kCFAllocatorNull); + entitlements = (CFMutableDictionaryRef) CFPropertyListCreateWithData(kCFAllocatorDefault, data, kCFPropertyListMutableContainers, NULL, error); + CFRelease(data); + + if((entitlements==NULL) || (CFGetTypeID(entitlements)!=CFDictionaryGetTypeID())){ + ret = EINVAL; + goto out; + } + } + + task->entitlements = entitlements ? CFRetain(entitlements) : NULL; + task->entitlementsLoaded = true; + +out: + if(entitlements) + CFRelease(entitlements); + if(buffer) + free(buffer); + if (ret && error && *error==NULL) + *error = CFErrorCreate(NULL, kCFErrorDomainPOSIX, ret, NULL); + return ret == 0; +} + + +CFTypeRef SecTaskCopyValueForEntitlement(SecTaskRef task, CFStringRef entitlement, CFErrorRef *error) +{ + CFTypeRef value = NULL; + require(check_task(task), out); + + /* Load entitlements if necessary */ + if (task->entitlementsLoaded == false) { + require_quiet(SecTaskLoadEntitlements(task, error), out); + } + + if (task->entitlements != NULL) { + value = CFDictionaryGetValue(task->entitlements, entitlement); + + /* Return something the caller must release */ + if (value != NULL) { + CFRetain(value); + } + } +out: + return value; +} + +CFDictionaryRef SecTaskCopyValuesForEntitlements(SecTaskRef task, CFArrayRef entitlements, CFErrorRef *error) +{ + CFMutableDictionaryRef values = NULL; + require(check_task(task), out); + + /* Load entitlements if necessary */ + if (task->entitlementsLoaded == false) { + SecTaskLoadEntitlements(task, error); + } + + /* Iterate over the passed in entitlements, populating the dictionary + * If entitlements were loaded but none were present, return an empty + * dictionary */ + if (task->entitlementsLoaded == true) { + + CFIndex i, count = CFArrayGetCount(entitlements); + values = CFDictionaryCreateMutable(CFGetAllocator(task), count, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (task->entitlements != NULL) { + for (i = 0; i < count; i++) { + CFStringRef entitlement = CFArrayGetValueAtIndex(entitlements, i); + CFTypeRef value = CFDictionaryGetValue(task->entitlements, entitlement); + if (value != NULL) { + CFDictionarySetValue(values, entitlement, value); + } + } + } + } +out: + return values; +} diff --git a/sectask/SecTask.h b/sectask/SecTask.h new file mode 100644 index 00000000..e98ff382 --- /dev/null +++ b/sectask/SecTask.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2008,2012-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@ + */ + +#ifndef _SECURITY_SECTASK_H_ +#define _SECURITY_SECTASK_H_ + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + @typedef SecTaskRef + @abstract CFType used for representing a task +*/ +typedef struct __SecTask *SecTaskRef; + +/*! + @function SecTaskGetTypeID + @abstract Returns the type ID for CF instances of SecTask. + @result A CFTypeID for SecTask +*/ +CFTypeID SecTaskGetTypeID(void); + +/*! + @function SecTaskCreateWithAuditToken + @abstract Create a SecTask object for the task that sent the mach message + represented by the audit token. + @param token The audit token of a mach message + @result The newly created SecTask object or NULL on error. The caller must + CFRelease the returned object. +*/ +SecTaskRef SecTaskCreateWithAuditToken(CFAllocatorRef allocator, audit_token_t token); + +/*! + @function SecTaskCreateFromSelf + @abstract Create a SecTask object for the current task. + @result The newly created SecTask object or NULL on error. The caller must + CFRelease the returned object. + */ +SecTaskRef SecTaskCreateFromSelf(CFAllocatorRef allocator); + +/*! + @function SecTaskCopyValueForEntitlement + @abstract Returns the value of a single entitlement for the represented + task. + @param task A previously created SecTask object + @param entitlement The name of the entitlement to be fetched + @param error On a NULL return, this may be contain a CFError describing + the problem. This argument may be NULL if the caller is not interested in + detailed errors. + @result The value of the specified entitlement for the process or NULL if + the entitlement value could not be retrieved. The type of the returned + value will depend on the entitlement specified. The caller must release + the returned object. + @discussion A NULL return may indicate an error, or it may indicate that + the entitlement is simply not present. In the latter case, no CFError is + returned. +*/ +CFTypeRef SecTaskCopyValueForEntitlement(SecTaskRef task, CFStringRef entitlement, CFErrorRef *error); + +/*! + @function SecTaskCopyValuesForEntitlements + @abstract Returns the values of multiple entitlements for the represented + task. + @param task A previously created SecTask object + @param entitlements An array of entitlement names to be fetched + @param error On a NULL return, this will contain a CFError describing + the problem. This argument may be NULL if the caller is not interested in + detailed errors. If a requested entitlement is not present for the + returned dictionary, the entitlement is not set on the task. The caller + must CFRelease the returned value +*/ +CFDictionaryRef SecTaskCopyValuesForEntitlements(SecTaskRef task, CFArrayRef entitlements, CFErrorRef *error); + +/*! + @function SecTaskCopySigningIdentifier + @abstract Return the value of the codesigning identifier. + @param task A previously created SecTask object + @param error On a NULL return, this will contain a CFError describing + the problem. This argument may be NULL if the caller is not interested in + detailed errors. The caller must CFRelease the returned value +*/ +CFStringRef SecTaskCopySigningIdentifier(SecTaskRef task, CFErrorRef *error); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SECURITY_SECTASK_H_ */ diff --git a/sectask/regressions/sectask-10-sectask.c b/sectask/regressions/sectask-10-sectask.c new file mode 100644 index 00000000..00bb07f8 --- /dev/null +++ b/sectask/regressions/sectask-10-sectask.c @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2007-2009,2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + + +#include +#include +#include +#include +#include +#include +#include + +#include "utilities/SecCFRelease.h" + +#include "sectask_regressions.h" + +/* IPC stuff: + + This is a hack to get our own audittoken: + We send a simple request with no argument to our mach port. + The mach port callback copy the audittoken to a global. + */ + +#include +#include +#include "sectask_ipc.h" + +static audit_token_t g_self_audittoken = {{0}}; + +kern_return_t sectask_server_request(mach_port_t receiver, + audit_token_t auditToken); +kern_return_t sectask_server_request(mach_port_t receiver, + audit_token_t auditToken) +{ + memcpy(&g_self_audittoken, &auditToken, sizeof(g_self_audittoken)); + + CFRunLoopStop(CFRunLoopGetCurrent()); + + return 0; +} + +extern boolean_t sectask_ipc_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +union max_msg_size_union { + union __RequestUnion__sectask_client_sectask_ipc_subsystem reply; +}; + +static uint8_t reply_buffer[sizeof(union max_msg_size_union) + MAX_TRAILER_SIZE]; + +static void server_callback(CFMachPortRef port, void *msg, CFIndex size, void *info) +{ + mach_msg_header_t *message = (mach_msg_header_t *)msg; + mach_msg_header_t *reply = (mach_msg_header_t *)reply_buffer; + + sectask_ipc_server(message, reply); + +} + +static +void init_self_audittoken(void) +{ + /* create a mach port and an event source */ + CFMachPortRef server_port = CFMachPortCreate (NULL, server_callback, NULL, false); + CFRunLoopSourceRef server_source = CFMachPortCreateRunLoopSource(NULL, server_port, 0/*order*/); + + /* add the source to the current run loop */ + CFRunLoopAddSource(CFRunLoopGetCurrent(), server_source, kCFRunLoopDefaultMode); + CFRelease(server_source); + + /* Send the request */ + sectask_client_request(CFMachPortGetPort(server_port)); + + /* Run the loop to process the message */ + CFRunLoopRun(); + + /* done */ + CFRelease(server_port); + +} + +static +CFStringRef copyProcName(pid_t pid) { + const char *task_name; + int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; + struct kinfo_proc kp; + size_t len = sizeof(kp); + if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1 || len == 0) + task_name = strerror(errno); + else + task_name = kp.kp_proc.p_comm; + return CFStringCreateWithCString(kCFAllocatorDefault, task_name, kCFStringEncodingASCII); +} + +/* Actual test code */ + +int sectask_10_sectask_self(int argc, char *const *argv) +{ + SecTaskRef task=NULL; + CFStringRef appId=NULL; + CFStringRef signingIdentifier=NULL; + plan_tests(6); + + ok(task=SecTaskCreateFromSelf(kCFAllocatorDefault), "SecTaskCreateFromSelf"); + require(task, out); + + /* TODO: remove the todo once xcode signs simulator binaries */ +SKIP: { +#if TARGET_IPHONE_SIMULATOR + todo("no entitlements in the simulator binaries yet, until "); +#endif + ok(appId=SecTaskCopyValueForEntitlement(task, kSecEntitlementApplicationIdentifier, NULL), "SecTaskCopyValueForEntitlement"); + skip("appId is NULL", 1, appId); + ok(CFEqual(appId, CFSTR("com.apple.security.regressions")), "Application Identifier match"); + + ok(signingIdentifier=SecTaskCopySigningIdentifier(task, NULL), "SecTaskCopySigningIdentifier"); + ok(CFEqual(signingIdentifier, CFBundleGetIdentifier(CFBundleGetMainBundle())), "CodeSigning Identifier match"); + } + + pid_t pid = getpid(); + CFStringRef name = copyProcName(pid); + CFStringRef expected = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@[%d]"), name, pid); + CFStringRef desc = CFCopyDescription(task); + ok(CFEqual(desc, expected), "task-description expected: %@ got: %@", expected, desc); + CFReleaseSafe(name); + CFReleaseSafe(desc); + CFReleaseSafe(expected); + +out: + CFReleaseSafe(task); + CFReleaseSafe(appId); + CFReleaseSafe(signingIdentifier); + + return 0; +} + +int sectask_11_sectask_audittoken(int argc, char *const *argv) +{ + SecTaskRef task=NULL; + CFStringRef appId=NULL; + CFStringRef signingIdentifier=NULL; + + plan_tests(6); + + init_self_audittoken(); + + ok(task=SecTaskCreateWithAuditToken(kCFAllocatorDefault, g_self_audittoken), "SecTaskCreateFromAuditToken"); + require(task, out); + + /* TODO: remove the todo once xcode signs simulator binaries */ +SKIP: { +#if TARGET_IPHONE_SIMULATOR + todo("no entitlements in the simulator binaries yet, until "); +#endif + ok(appId=SecTaskCopyValueForEntitlement(task, kSecEntitlementApplicationIdentifier, NULL), "SecTaskCopyValueForEntitlement"); + skip("appId is NULL", 1, appId); + ok(CFEqual(appId, CFSTR("com.apple.security.regressions")), "Application Identifier match"); + ok(signingIdentifier=SecTaskCopySigningIdentifier(task, NULL), "SecTaskCopySigningIdentifier"); + ok(CFEqual(signingIdentifier, CFBundleGetIdentifier(CFBundleGetMainBundle())), "CodeSigning Identifier match"); +} + + pid_t pid = getpid(); + CFStringRef name = copyProcName(pid); + CFStringRef expected = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@[%d]"), name, pid); + CFStringRef desc = CFCopyDescription(task); + ok(CFEqual(desc, expected), "task-description expected: %@ got: %@", expected, desc); + + CFReleaseSafe(name); + CFReleaseSafe(desc); + CFReleaseSafe(expected); + +out: + CFReleaseSafe(task); + CFReleaseSafe(appId); + CFReleaseSafe(signingIdentifier); + + return 0; +} diff --git a/sectask/regressions/sectask_ipc.defs b/sectask/regressions/sectask_ipc.defs new file mode 100644 index 00000000..909f9aee --- /dev/null +++ b/sectask/regressions/sectask_ipc.defs @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2007-2008,2010,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 +#include + +subsystem sectask_ipc 1000; +serverprefix sectask_server_; +userprefix sectask_client_; + + +simpleroutine request(receiver: mach_port_t; + serveraudittoken sourceAudit: audit_token_t); diff --git a/sectask/regressions/sectask_regressions.h b/sectask/regressions/sectask_regressions.h new file mode 100644 index 00000000..0dfb4214 --- /dev/null +++ b/sectask/regressions/sectask_regressions.h @@ -0,0 +1,9 @@ +#include + +#if !TARGET_IPHONE_SIMULATOR +ONE_TEST(sectask_10_sectask_self) +ONE_TEST(sectask_11_sectask_audittoken) +#else +OFF_ONE_TEST(sectask_10_sectask_self) +OFF_ONE_TEST(sectask_11_sectask_audittoken) +#endif diff --git a/sectests/main.c b/sectests/main.c deleted file mode 100644 index 7d2290da..00000000 --- a/sectests/main.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * main.c - * Security - * - * Created by Fabrice Gautier on 8/7/12. - * Copyright 2012 Apple, Inc. All rights reserved. - * - */ - -#include -#include - -#include "test/testenv.h" - -#include "testlist.h" -#include -#include "testlist.h" -#include - -int main(int argc, char *argv[]) -{ - printf("Build date : %s %s\n", __DATE__, __TIME__); - - int result = tests_begin(argc, argv); - - fflush(stderr); - fflush(stdout); - - sleep(1); - - return result; -} diff --git a/sectests/test/testenv.c b/sectests/test/testenv.c deleted file mode 100644 index a9a00c20..00000000 --- a/sectests/test/testenv.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (c) 2005-2007,2009-2011 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 -#include -#include -#include -#include -#include -#include -#include - -#include "testmore.h" -#include "testenv.h" - -int test_verbose = 0; - -#if NO_SERVER -#include - -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) -{ - char command_buf[256]; - if (strlen(path) + 10 > sizeof(command_buf) || strchr(path, '\'')) - { - fprintf(stderr, "# rmdir_recursive: invalid path: %s", path); - return -1; - } - - sprintf(command_buf, "rm -rf '%s'", path); - return system(command_buf); -} -#endif - -static int tests_init(void) { -#if NO_SERVER - char preferences_dir[80]; - char library_dir[70]; - - char *path = getenv("TESTHOME"); - if (path) - setenv("TESTHOME", path, 1); - securityd_init(); - - 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); - return (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")); - -#else - return 0; -#endif -} - -static int -tests_end(void) -{ -#if 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); -} - -static int tests_run_index(int i, 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]); - } - } - - fprintf(stderr, "TEST: Test Case '%s' started.\n", testlist[i].name); - - run_one_test(&testlist[i], argc, argv); - if(testlist[i].failed_tests) { - fprintf(stderr, "FAIL: Test Case '%s' failed.\n", testlist[i].name); - } else { - fprintf(stderr, "PASS: Test Case '%s' passed. (%lu ms)\n", testlist[i].name, testlist[i].duration); - } - return testlist[i].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_index(i, argc, argv); - optind = curroptind; - } - } - - return failcount; -} - -int -tests_begin(int argc, char * const *argv) -{ - const char *testcase = NULL; - bool initialized = false; - int testix = -1; - int failcount = 0; - int ch; - int loop = 0; - - for (;;) { - while (!testcase && (ch = getopt(argc, argv, "klw")) != -1) - { - switch (ch) - { -#ifdef NO_SERVER - case 'k': - keep_scratch_dir = true; - break; -#endif - case 'w': - sleep(100); - break; - case 'l': - loop=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 (testix < 0) { - if (!initialized) { - initialized = true; - tests_init(); - failcount+=tests_run_all(argc, argv); - } - break; - } else { - if (!initialized) { - tests_init(); - initialized = true; - } - optind++; - failcount+=tests_run_index(testix, argc, argv); - testix = -1; - } - } - - printf("Total failcount = %d\n", failcount); - - /* 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/sectests/testlist.h b/sectests/testlist.h deleted file mode 100644 index afd1665e..00000000 --- a/sectests/testlist.h +++ /dev/null @@ -1,3 +0,0 @@ -/* Don't prevent multiple inclusion of this file. */ -#include -#include diff --git a/security2/security2.1 b/security2/security2.1 deleted file mode 100644 index 621b26d3..00000000 --- a/security2/security2.1 +++ /dev/null @@ -1,79 +0,0 @@ -.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. -.\"See Also: -.\"man mdoc.samples for a complete listing of options -.\"man mdoc for the short list of editing options -.\"/usr/share/misc/mdoc.template -.Dd 1/10/13 \" DATE -.Dt security2 1 \" Program name and manual section number -.Os Darwin -.Sh NAME \" Section Header - required - don't modify -.Nm security2, -.\" The following lines are read in generating the apropos(man -k) database. Use only key -.\" words here as the database is built based on the words here and in the .ND line. -.Nm Other_name_for_same_program(), -.Nm Yet another name for the same program. -.\" Use .Nm macro to designate other names for the documented program. -.Nd This line parsed for whatis database. -.Sh SYNOPSIS \" Section Header - required - don't modify -.Nm -.Op Fl abcd \" [-abcd] -.Op Fl a Ar path \" [-a path] -.Op Ar file \" [file] -.Op Ar \" [file ...] -.Ar arg0 \" Underlined argument - use .Ar anywhere to underline -arg2 ... \" Arguments -.Sh DESCRIPTION \" Section Header - required - don't modify -Use the .Nm macro to refer to your program throughout the man page like such: -.Nm -Underlining is accomplished with the .Ar macro like this: -.Ar underlined text . -.Pp \" Inserts a space -A list of items with descriptions: -.Bl -tag -width -indent \" Begins a tagged list -.It item a \" Each item preceded by .It macro -Description of item a -.It item b -Description of item b -.El \" Ends the list -.Pp -A list of flags and their descriptions: -.Bl -tag -width -indent \" Differs from above in tag removed -.It Fl a \"-a flag as a list item -Description of -a flag -.It Fl b -Description of -b flag -.El \" Ends the list -.Pp -.\" .Sh ENVIRONMENT \" May not be needed -.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 -.\" .It Ev ENV_VAR_1 -.\" Description of ENV_VAR_1 -.\" .It Ev ENV_VAR_2 -.\" Description of ENV_VAR_2 -.\" .El -.Sh FILES \" File used or created by the topic of the man page -.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact -.It Pa /usr/share/file_name -FILE_1 description -.It Pa /Users/joeuser/Library/really_long_file_name -FILE_2 description -.El \" Ends the list -.\" .Sh DIAGNOSTICS \" May not be needed -.\" .Bl -diag -.\" .It Diagnostic Tag -.\" Diagnostic informtion here. -.\" .It Diagnostic Tag -.\" Diagnostic informtion here. -.\" .El -.Sh SEE ALSO -.\" List links in ascending order by section, alphabetically within a section. -.\" Please do not reference files that do not exist without filing a bug report -.Xr a 1 , -.Xr b 1 , -.Xr c 1 , -.Xr a 2 , -.Xr b 2 , -.Xr a 3 , -.Xr b 3 -.\" .Sh BUGS \" Document known, unremedied bugs -.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file diff --git a/security2/security_tool_commands.c b/security2/security_tool_commands.c deleted file mode 100644 index c7f3f925..00000000 --- a/security2/security_tool_commands.c +++ /dev/null @@ -1,28 +0,0 @@ -// -// security_tool_commands.c -// Security -// -// Created by J Osborne on 1/10/13. -// -// - -#include -#include -#include "SecurityTool/SecurityTool.h" - -#include "SecurityTool/security_tool_commands.h" - -#include "SecurityTool/builtin_commands.h" -#include "security2/sub_commands.h" - -// Redefine for making them declaraionts. -#include "SecurityTool/security_tool_commands_table.h" - -const command commands[] = -{ -#include "SecurityTool/builtin_commands.h" - -#include "security2/sub_commands.h" - - {} -}; diff --git a/security2/sub_commands.h b/security2/sub_commands.h deleted file mode 100644 index 8ceb3b13..00000000 --- a/security2/sub_commands.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// sub_commands.h -// Security -// -// Created by J Osborne on 1/10/13. -// -// - -// 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" diff --git a/securityd/APPLE_LICENSE b/securityd/APPLE_LICENSE new file mode 100644 index 00000000..fe81a60c --- /dev/null +++ b/securityd/APPLE_LICENSE @@ -0,0 +1,367 @@ +APPLE PUBLIC SOURCE LICENSE +Version 2.0 - August 6, 2003 + +Please read this License carefully before downloading this software. +By downloading or using this software, you are agreeing to be bound by +the terms of this License. If you do not or cannot agree to the terms +of this License, please do not download or use the software. + +1. General; Definitions. This License applies to any program or other +work which Apple Computer, Inc. ("Apple") makes publicly available and +which contains a notice placed by Apple identifying such program or +work as "Original Code" and stating that it is subject to the terms of +this Apple Public Source License version 2.0 ("License"). As used in +this License: + +1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is +the grantor of rights, (i) claims of patents that are now or hereafter +acquired, owned by or assigned to Apple and (ii) that cover subject +matter contained in the Original Code, but only to the extent +necessary to use, reproduce and/or distribute the Original Code +without infringement; and (b) in the case where You are the grantor of +rights, (i) claims of patents that are now or hereafter acquired, +owned by or assigned to You and (ii) that cover subject matter in Your +Modifications, taken alone or in combination with Original Code. + +1.2 "Contributor" means any person or entity that creates or +contributes to the creation of Modifications. + +1.3 "Covered Code" means the Original Code, Modifications, the +combination of Original Code and any Modifications, and/or any +respective portions thereof. + +1.4 "Externally Deploy" means: (a) to sublicense, distribute or +otherwise make Covered Code available, directly or indirectly, to +anyone other than You; and/or (b) to use Covered Code, alone or as +part of a Larger Work, in any way to provide a service, including but +not limited to delivery of content, through electronic communication +with a client other than You. + +1.5 "Larger Work" means a work which combines Covered Code or portions +thereof with code not governed by the terms of this License. + +1.6 "Modifications" mean any addition to, deletion from, and/or change +to, the substance and/or structure of the Original Code, any previous +Modifications, the combination of Original Code and any previous +Modifications, and/or any respective portions thereof. When code is +released as a series of files, a Modification is: (a) any addition to +or deletion from the contents of a file containing Covered Code; +and/or (b) any new file or other representation of computer program +statements that contains any part of Covered Code. + +1.7 "Original Code" means (a) the Source Code of a program or other +work as originally made available by Apple under this License, +including the Source Code of any updates or upgrades to such programs +or works made available by Apple under this License, and that has been +expressly identified by Apple as such in the header file(s) of such +work; and (b) the object code compiled from such Source Code and +originally made available by Apple under this License. + +1.8 "Source Code" means the human readable form of a program or other +work that is suitable for making modifications to it, including all +modules it contains, plus any associated interface definition files, +scripts used to control compilation and installation of an executable +(object code). + +1.9 "You" or "Your" means an individual or a legal entity exercising +rights under this License. For legal entities, "You" or "Your" +includes any entity which controls, is controlled by, or is under +common control with, You, where "control" means (a) the power, direct +or indirect, to cause the direction or management of such entity, +whether by contract or otherwise, or (b) ownership of fifty percent +(50%) or more of the outstanding shares or beneficial ownership of +such entity. + +2. Permitted Uses; Conditions & Restrictions. Subject to the terms +and conditions of this License, Apple hereby grants You, effective on +the date You accept this License and download the Original Code, a +world-wide, royalty-free, non-exclusive license, to the extent of +Apple's Applicable Patent Rights and copyrights covering the Original +Code, to do the following: + +2.1 Unmodified Code. You may use, reproduce, display, perform, +internally distribute within Your organization, and Externally Deploy +verbatim, unmodified copies of the Original Code, for commercial or +non-commercial purposes, provided that in each instance: + +(a) You must retain and reproduce in all copies of Original Code the +copyright and other proprietary notices and disclaimers of Apple as +they appear in the Original Code, and keep intact all notices in the +Original Code that refer to this License; and + +(b) You must include a copy of this License with every copy of Source +Code of Covered Code and documentation You distribute or Externally +Deploy, and You may not offer or impose any terms on such Source Code +that alter or restrict this License or the recipients' rights +hereunder, except as permitted under Section 6. + +2.2 Modified Code. You may modify Covered Code and use, reproduce, +display, perform, internally distribute within Your organization, and +Externally Deploy Your Modifications and Covered Code, for commercial +or non-commercial purposes, provided that in each instance You also +meet all of these conditions: + +(a) You must satisfy all the conditions of Section 2.1 with respect to +the Source Code of the Covered Code; + +(b) You must duplicate, to the extent it does not already exist, the +notice in Exhibit A in each file of the Source Code of all Your +Modifications, and cause the modified files to carry prominent notices +stating that You changed the files and the date of any change; and + +(c) If You Externally Deploy Your Modifications, You must make +Source Code of all Your Externally Deployed Modifications either +available to those to whom You have Externally Deployed Your +Modifications, or publicly available. Source Code of Your Externally +Deployed Modifications must be released under the terms set forth in +this License, including the license grants set forth in Section 3 +below, for as long as you Externally Deploy the Covered Code or twelve +(12) months from the date of initial External Deployment, whichever is +longer. You should preferably distribute the Source Code of Your +Externally Deployed Modifications electronically (e.g. download from a +web site). + +2.3 Distribution of Executable Versions. In addition, if You +Externally Deploy Covered Code (Original Code and/or Modifications) in +object code, executable form only, You must include a prominent +notice, in the code itself as well as in related documentation, +stating that Source Code of the Covered Code is available under the +terms of this License with information on how and where to obtain such +Source Code. + +2.4 Third Party Rights. You expressly acknowledge and agree that +although Apple and each Contributor grants the licenses to their +respective portions of the Covered Code set forth herein, no +assurances are provided by Apple or any Contributor that the Covered +Code does not infringe the patent or other intellectual property +rights of any other entity. Apple and each Contributor disclaim any +liability to You for claims brought by any other entity based on +infringement of intellectual property rights or otherwise. As a +condition to exercising the rights and licenses granted hereunder, You +hereby assume sole responsibility to secure any other intellectual +property rights needed, if any. For example, if a third party patent +license is required to allow You to distribute the Covered Code, it is +Your responsibility to acquire that license before distributing the +Covered Code. + +3. Your Grants. In consideration of, and as a condition to, the +licenses granted to You under this License, You hereby grant to any +person or entity receiving or distributing Covered Code under this +License a non-exclusive, royalty-free, perpetual, irrevocable license, +under Your Applicable Patent Rights and other intellectual property +rights (other than patent) owned or controlled by You, to use, +reproduce, display, perform, modify, sublicense, distribute and +Externally Deploy Your Modifications of the same scope and extent as +Apple's licenses under Sections 2.1 and 2.2 above. + +4. Larger Works. You may create a Larger Work by combining Covered +Code with other code not governed by the terms of this License and +distribute the Larger Work as a single product. In each such instance, +You must make sure the requirements of this License are fulfilled for +the Covered Code or any portion thereof. + +5. Limitations on Patent License. Except as expressly stated in +Section 2, no other patent rights, express or implied, are granted by +Apple herein. Modifications and/or Larger Works may require additional +patent licenses from Apple which Apple may grant in its sole +discretion. + +6. Additional Terms. You may choose to offer, and to charge a fee for, +warranty, support, indemnity or liability obligations and/or other +rights consistent with the scope of the license granted herein +("Additional Terms") to one or more recipients of Covered Code. +However, You may do so only on Your own behalf and as Your sole +responsibility, and not on behalf of Apple or any Contributor. You +must obtain the recipient's agreement that any such Additional Terms +are offered by You alone, and You hereby agree to indemnify, defend +and hold Apple and every Contributor harmless for any liability +incurred by or claims asserted against Apple or such Contributor by +reason of any such Additional Terms. + +7. Versions of the License. Apple may publish revised and/or new +versions of this License from time to time. Each version will be given +a distinguishing version number. Once Original Code has been published +under a particular version of this License, You may continue to use it +under the terms of that version. You may also choose to use such +Original Code under the terms of any subsequent version of this +License published by Apple. No one other than Apple has the right to +modify the terms applicable to Covered Code created under this +License. + +8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in +part pre-release, untested, or not fully tested works. The Covered +Code may contain errors that could cause failures or loss of data, and +may be incomplete or contain inaccuracies. You expressly acknowledge +and agree that use of the Covered Code, or any portion thereof, is at +Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND +WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND +APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE +PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM +ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF +MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR +PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD +PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST +INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE +FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS, +THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR +ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO +ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE +AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. +You acknowledge that the Covered Code is not intended for use in the +operation of nuclear facilities, aircraft navigation, communication +systems, or air traffic control machines in which case the failure of +the Covered Code could lead to death, personal injury, or severe +physical or environmental damage. + +9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO +EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING +TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR +ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY, +TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF +APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY +REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF +INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY +TO YOU. In no event shall Apple's total liability to You for all +damages (other than as may be required by applicable law) under this +License exceed the amount of fifty dollars ($50.00). + +10. Trademarks. This License does not grant any rights to use the +trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS", +"QuickTime", "QuickTime Streaming Server" or any other trademarks, +service marks, logos or trade names belonging to Apple (collectively +"Apple Marks") or to any trademark, service mark, logo or trade name +belonging to any Contributor. You agree not to use any Apple Marks in +or as part of the name of products derived from the Original Code or +to endorse or promote products derived from the Original Code other +than as expressly permitted by and in strict compliance at all times +with Apple's third party trademark usage guidelines which are posted +at http://www.apple.com/legal/guidelinesfor3rdparties.html. + +11. Ownership. Subject to the licenses granted under this License, +each Contributor retains all rights, title and interest in and to any +Modifications made by such Contributor. Apple retains all rights, +title and interest in and to the Original Code and any Modifications +made by or on behalf of Apple ("Apple Modifications"), and such Apple +Modifications will not be automatically subject to this License. Apple +may, at its sole discretion, choose to license such Apple +Modifications under this License, or on different terms from those +contained in this License or may choose not to license them at all. + +12. Termination. + +12.1 Termination. This License and the rights granted hereunder will +terminate: + +(a) automatically without notice from Apple if You fail to comply with +any term(s) of this License and fail to cure such breach within 30 +days of becoming aware of such breach; + +(b) immediately in the event of the circumstances described in Section +13.5(b); or + +(c) automatically without notice from Apple if You, at any time during +the term of this License, commence an action for patent infringement +against Apple; provided that Apple did not first commence +an action for patent infringement against You in that instance. + +12.2 Effect of Termination. Upon termination, You agree to immediately +stop any further use, reproduction, modification, sublicensing and +distribution of the Covered Code. All sublicenses to the Covered Code +which have been properly granted prior to termination shall survive +any termination of this License. Provisions which, by their nature, +should remain in effect beyond the termination of this License shall +survive, including but not limited to Sections 3, 5, 8, 9, 10, 11, +12.2 and 13. No party will be liable to any other for compensation, +indemnity or damages of any sort solely as a result of terminating +this License in accordance with its terms, and termination of this +License will be without prejudice to any other right or remedy of +any party. + +13. Miscellaneous. + +13.1 Government End Users. The Covered Code is a "commercial item" as +defined in FAR 2.101. Government software and technical data rights in +the Covered Code include only those rights customarily provided to the +public as defined in this License. This customary commercial license +in technical data and software is provided in accordance with FAR +12.211 (Technical Data) and 12.212 (Computer Software) and, for +Department of Defense purchases, DFAR 252.227-7015 (Technical Data -- +Commercial Items) and 227.7202-3 (Rights in Commercial Computer +Software or Computer Software Documentation). Accordingly, all U.S. +Government End Users acquire Covered Code with only those rights set +forth herein. + +13.2 Relationship of Parties. This License will not be construed as +creating an agency, partnership, joint venture or any other form of +legal association between or among You, Apple or any Contributor, and +You will not represent to the contrary, whether expressly, by +implication, appearance or otherwise. + +13.3 Independent Development. Nothing in this License will impair +Apple's right to acquire, license, develop, have others develop for +it, market and/or distribute technology or products that perform the +same or similar functions as, or otherwise compete with, +Modifications, Larger Works, technology or products that You may +develop, produce, market or distribute. + +13.4 Waiver; Construction. Failure by Apple or any Contributor to +enforce any provision of this License will not be deemed a waiver of +future enforcement of that or any other provision. Any law or +regulation which provides that the language of a contract shall be +construed against the drafter will not apply to this License. + +13.5 Severability. (a) If for any reason a court of competent +jurisdiction finds any provision of this License, or portion thereof, +to be unenforceable, that provision of the License will be enforced to +the maximum extent permissible so as to effect the economic benefits +and intent of the parties, and the remainder of this License will +continue in full force and effect. (b) Notwithstanding the foregoing, +if applicable law prohibits or restricts You from fully and/or +specifically complying with Sections 2 and/or 3 or prevents the +enforceability of either of those Sections, this License will +immediately terminate and You must immediately discontinue any use of +the Covered Code and destroy all copies of it that are in your +possession or control. + +13.6 Dispute Resolution. Any litigation or other dispute resolution +between You and Apple relating to this License shall take place in the +Northern District of California, and You and Apple hereby consent to +the personal jurisdiction of, and venue in, the state and federal +courts within that District with respect to this License. The +application of the United Nations Convention on Contracts for the +International Sale of Goods is expressly excluded. + +13.7 Entire Agreement; Governing Law. This License constitutes the +entire agreement between the parties with respect to the subject +matter hereof. This License shall be governed by the laws of the +United States and the State of California, except that body of +California law concerning conflicts of law. + +Where You are located in the province of Quebec, Canada, the following +clause applies: The parties hereby confirm that they have requested +that this License and all related documents be drafted in English. Les +parties ont exige que le present contrat et tous les documents +connexes soient rediges en anglais. + +EXHIBIT A. + +"Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights +Reserved. + +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." diff --git a/securityd/config/debug.xcconfig b/securityd/config/debug.xcconfig new file mode 100644 index 00000000..937d1775 --- /dev/null +++ b/securityd/config/debug.xcconfig @@ -0,0 +1,3 @@ +GCC_OPTIMIZATION_LEVEL = 0 +GCC_PREPROCESSOR_DEFINITIONS = DEBUG=1 $(inherited) +COPY_PHASE_STRIP = NO diff --git a/securityd/config/project.xcconfig b/securityd/config/project.xcconfig new file mode 100644 index 00000000..1af4d3ce --- /dev/null +++ b/securityd/config/project.xcconfig @@ -0,0 +1,25 @@ +ARCHS = $(ARCHS_STANDARD_64_BIT) +CODE_SIGN_IDENTITY = -; +GCC_VERSION = com.apple.compilers.llvm.clang.1_0 +DEBUG_INFORMATION_FORMAT = dwarf-with-dsym +SDKROOT = +CURRENT_PROJECT_VERSION = $(RC_ProjectSourceVersion) +VERSIONING_SYSTEM = apple-generic; +DEAD_CODE_STRIPPING = YES; + +FRAMEWORK_SEARCH_PATHS = $(SYSTEM_LIBRARY_DIR)/PrivateFrameworks + +PRODUCT_NAME = $(TARGET_NAME) + +ALWAYS_SEARCH_USER_PATHS = NO + +GCC_C_LANGUAGE_STANDARD = gnu99 + +WARNING_CFLAGS = -Wmost -Wno-four-char-constants -Wno-unknown-pragmas $(inherited) + +GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO + +GCC_WARN_64_TO_32_BIT_CONVERSION = YES +GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES +GCC_WARN_ABOUT_RETURN_TYPE = YES +GCC_WARN_UNUSED_VARIABLE = YES \ No newline at end of file diff --git a/securityd/config/release.xcconfig b/securityd/config/release.xcconfig new file mode 100644 index 00000000..dc5f8761 --- /dev/null +++ b/securityd/config/release.xcconfig @@ -0,0 +1,3 @@ +GCC_PREPROCESSOR_DEFINITIONS = NDEBUG=1 $(inherited) +COPY_PHASE_STRIP = YES + diff --git a/securityd/doc/BLOBFORMAT b/securityd/doc/BLOBFORMAT new file mode 100644 index 00000000..a6f423db --- /dev/null +++ b/securityd/doc/BLOBFORMAT @@ -0,0 +1,63 @@ +Description of SecurityServer blob format. + + +Database blob: + + +Creation (input PASSWORD, PRIVATE_DBB_BYTES, PUBLIC_DBB_BYTES) +Update -- change password (same as creation except use passed in DSK and DEK). + +1. Generate a 20 byte (160 bit) random string called SALT. +2. Derive a 24 byte (192 bit -- 168 bit effective because of odd parity in each octet) 3DES key called MK and 8 bytes IV from PASSWORD and SALT using PBKDF2 with PRF = HMACSHA1 and iteration count = 1000. +3. Generate a 24 byte (192 bit -- 168 bit effective because of parity) 3DES key called DEK. +4. Generate a 20 byte (160 bit SHA1HMAC key called DSK. +5. Let TEMP1 = DSK || DEK || PRIVATE_DBB_BYTES +6. Let TEMP2 = ciphertext of TEMP1 encrypted with MK and IV using 3DES in CBC_IV mode. +7. Let TEMP3 = SALT || LEN(PUBLIC_DBB_BYTES) || PUBLIC_DBB_BYTES || TEMP2 +8. Let SIG = SHA1HMAC(DSK, TEMP3) +9. Let DBB = SIG || TEMP3 +10. Outputs DBB, DSK (for signing) and DEK (for encryption) + + +Decode (input DBB and PASSWORD) + +1. Let SIG = First 20 octets of DBB. +2. Let TEMP3 = Octets 20 though end of DBB. +3. Let SALT = Octets 0 though 20 of TEMP3. +4. Derive a 192 bit (168 bit effective because of parity) 3DES key called MK and 8 bytes IV from PASSWORD and SALT using PKDF2 with PRF = HMACSHA1 and iteration count = 1000. +5. Let LEN_PUBLIC_DBB_BYTES = Octets 20 though 24 of TEMP3. +6. Let PUBLIC_DBB_BYTES = Octets 24 though 24 + LEN_PUBLIC_DBB_BYTES of TEMP3. +7. Let TEMP2 = Octets 24 + LEN_PUBLIC_DBB_BYTES though end of TEMP3. +8. Let TEMP1 = plaintext of TEMP2 decrypted with MK and IV using 3DES in CBC_IV mode with PKCS1 padding. +9. Let DSK = First 20 octets of TEMP1 +10. Verify that SHA1HMAC(DSK, TEMP3) == SIG (using VerifyMac) if fail then password is wrong. +11. Let DEK = Octets 20 though 44 of TEMP1 +12. If DEK does not have odd parity in all octets then DBB is corrupt. +13. Let PRIVATE_DBB_BYTES = Octets 44 though end of TEMP1 +14. Outputs PUBLIC_DBB_BYTES, PRIVATE_DBB_BYTES, DSK, DEK + + + +Key blob: + +Creation (input DSK, DEK, PRIVATE_KEY_BYTES, PUBLIC_KEY_BYTES output KB) +(NOTE PRIVATE_KEY_BYTES contains both the key bits (24 bytes) and the private ACL parts) + +1. Generate a 8 byte random string called IV +2. Encrypt PRIVATE_KEY_BYTES using DEK (3DES) and IV in CBC mode with PKCS1 padding. Call the ciphertext TEMP1 +3. Let TEMP2 = IV || TEMP1. +4. Reverse the order of the octects in TEMP2 call the result TEMP3. +5. Encrypt TEMP3 using DEK with an IV of 0x4adda22c79e82105 in CBC mode with PKCS1 padding call the result TEMP4. +6. Concatenate LEN(PUBLIC_KEY_BYTES) | PUBLIC_KEY_BYTES | TEMP4 and call it TEMP5 +7. Compute the 20 byte SHA1HMAC of TEMP5 using DSK and call it SIG. +8. Concatinate TEMP5 | SIG and call the result KB. + +Decode (input DSK, DEK, KB output PRIVATE_KEY_BYTES, PUBLIC_KEY_BYTES) + +1. Split KB in TEMP5 and SIG (SIG is last 20 bytes) TEMP5 is the rest. +2. Verify the 20 byte SHA1HMAC of TEMP5 using DSK against SIG if if fails the blob is invalid. +3. Split TEMP5 in LEN(PUBLIC_KEY_BYTES) , PUBLIC_KEY_BYTES and TEMP4. +4. Decrypt TEMP4 using DEK with an IV of 0x4adda22c79e82105 in CBC mode with PKCS1 padding call the result TEMP3. +5. Reverse the order of the octects in TEMP3 and call the result TEMP2. +6. Split TEMP2 in IV (first 8 bytes) and TEMP1 (rest). +7. Decrypt TEMP1 using DEK (3DES) and IV in CBC mode with PKCS1 padding. Call the plaintext PRIVATE_KEY_BYTES. diff --git a/securityd/doc/securityd.1 b/securityd/doc/securityd.1 new file mode 100644 index 00000000..b23cae7d --- /dev/null +++ b/securityd/doc/securityd.1 @@ -0,0 +1,36 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. +.\"See Also: +.\"man mdoc.samples for a complete listing of options +.\"man mdoc for the short list of editing options +.Dd Fri Sep 10 2004 \" DATE +.Dt securityd 1 \" Program name and manual section number +.Os Darwin +.Sh NAME \" Section Header - required - don't modify +.Nm securityd +.\" The following lines are read in generating the apropos(man -k) database. Use only key +.\" words here as the database is built based on the words here and in the .ND line. +.\" Use .Nm macro to designate other names for the documented program. +.Nd Security context daemon for Authorization and cryptographic operations +.Sh SYNOPSIS \" Section Header - required - don't modify +.Nm +.Sh DESCRIPTION \" Section Header - required - don't modify +.Nm +maintains security contexts and arbitrates cryptographic operations and Security Authorizations. Access to +keychain items is routed through +.Nm +to enforce access controls and to keep private keys out of +user process address space. Authorization calls also communicate with +.Nm +to enforce rules contained in the +.Pa /etc/authorization +database. All user interaction with +.Nm +is mediated through the +.Nm "Security Agent." +.Pp +This command is not intended to be invoked directly. +.Sh HISTORY +.Nm +was first introduced in Mac OS X version 10.0 (Cheetah) as the "Security Server" and was renamed in 10.4 (Tiger). +.Sh AUTHORS +.An "Perry The Cynic" diff --git a/securityd/dtrace/dtrace.mk b/securityd/dtrace/dtrace.mk new file mode 100644 index 00000000..37b42095 --- /dev/null +++ b/securityd/dtrace/dtrace.mk @@ -0,0 +1,2 @@ +$(DERIVED_SRC)/securityd_dtrace.h: $(SRCROOT)/src/securityd.d + /usr/sbin/dtrace -h -C -s $(SRCROOT)/src/securityd.d -o $(DERIVED_SRC)/securityd_dtrace.h diff --git a/securityd/dtrace/securityd-watch.d b/securityd/dtrace/securityd-watch.d new file mode 100755 index 00000000..aa405871 --- /dev/null +++ b/securityd/dtrace/securityd-watch.d @@ -0,0 +1,415 @@ +#!/usr/sbin/dtrace -q -s + + + +/* + * Tracking state + */ +typedef uint32_t DTPort; +typedef uint64_t DTHandle; + +DTHandle portmap[DTPort]; /* map client reply ports to connections */ + +struct connection { + DTPort replyport; /* reply port for client thread */ + uint32_t client; /* client object for this connection */ +}; +struct connection connection[DTHandle]; /* indexed by connection handle */ + +/* should be a single self struct, but that doesn't work right... */ +self string reqName; /* request name */ +self DTHandle reqConnection; /* associated connection */ +self DTHandle reqClient; /* associated client */ + +struct client { + pid_t pid; /* original client pid */ + DTHandle session; /* session handle */ + string name; /* abbreviated name */ + string path; /* path to client process (regardless of guests) */ + DTPort taskport; /* process task port */ +}; +struct client client[DTHandle]; /* indexed by client handle */ + +struct keychain { + string name; /* keychain path */ +}; +struct keychain keychain[DTHandle]; /* indexed by DbCommon handle */ + + +/* + * Script management + */ +:::BEGIN +{ + /* fake data for unknown processes */ + client[0].pid = 0; + client[0].session = 0; + client[0].name = "*UNKNOWN*"; + client[0].path = "*UNKNOWN*"; + + printf("Ready...\n"); +} + + +/* + * Translate thread id + */ +uint32_t threads[DTHandle]; /* map tids to simple thread numbers */ +uint32_t nextThread; /* next unused thread number */ +self uint32_t mytid; /* translated tid */ + +securityd*::: /!threads[tid]/ { threads[tid] = ++nextThread; } +security_debug*::: /!threads[tid]/ { threads[tid] = ++nextThread; } + +securityd*::: { self->mytid = threads[tid]; } +security_debug*::: { self->mytid = threads[tid]; } + + +/* + * Principal events + */ +securityd*:::installmode +{ + printf("%u SYSTEM INSTALLATION MODE SELECTED\n", timestamp); +} + +securityd*:::initialized +{ + printf("%u COMMENCING SERVICE as %s\n", timestamp, copyinstr(arg0)); +} + + +/* + * Client management + */ +securityd*:::client-connection-new +{ + replymap[arg1] = arg0; + self->reqClient = arg2; + connection[arg0].client = self->reqClient; + self->reqConnection = arg0; + @total["Connections"] = count(); + printf("%u T%d:connection-new(<%x>,port=%d,client=<%x>/%s(%d))\n", + timestamp, self->mytid, arg0, arg1, + arg2, client[arg2].name, client[arg2].pid); +} + +securityd*:::client-connection-release +/connection[arg0].client/ +{ + printf("%u T%d:connection-release(<%x>,client=<%x>/%s(%d))\n", + timestamp, self->mytid, arg0, + connection[arg0].client, + client[connection[arg0].client].name, + client[connection[arg0].client].pid); + replymap[connection[arg0].replyport] = 0; /* clear from port map */ + connection[arg0].replyport = 0; + connection[arg0].client = 0; +} + +securityd*:::client-new +{ + client[arg0].pid = arg1; + client[arg0].session = arg2; + client[arg0].path = copyinstr(arg3); + client[arg0].name = basename(client[arg0].path); + client[arg0].taskport = arg4; + self->reqClient = arg0; + @total["Processes"] = count(); + printf("%u T%d:client-new(<%x>,%s(%d),session=<%x>,task=%d)\n", + timestamp, self->mytid, arg0, + client[arg0].path, client[arg0].pid, + client[arg0].session, client[arg0].taskport); +} + +securityd*:::client-release +{ + printf("%u T%d:client-release(<%x>,%s(%d))\n", + timestamp, self->mytid, arg0, client[arg0].path, arg1); + client[arg0].pid = 0; +} + +securityd*:::client-change_session +{ + printf("%u T%d:client-change_session(<%x>,new session=<%x>)\n", + timestamp, self->mytid, arg0, arg1); + client[arg0].pid = 0; +} + + +/* + * Client requests + */ +uint32_t connections[DTHandle]; +uint32_t nextConnection; +self uint32_t myConnection; + +securityd*:::request-entry +/!connections[arg1]/ +{ connections[arg1] = ++nextConnection; } + +securityd*:::request-entry +{ + self->reqName = copyinstr(arg0); + self->reqConnection = arg1; + self->myConnection = connections[arg1]; + self->reqClient = arg2; + this->client = client[self->reqClient]; +} + +securityd*:::request-entry +/this->client.pid/ +{ + printf("%u T%d:C%d:%s(%d)%s\n", + timestamp, self->mytid, self->myConnection, this->client.name, this->client.pid, self->reqName); + @request[client[self->reqClient].name, self->reqName] = count(); +} + +securityd*:::request-entry +/!this->client.pid/ +{ + printf("%u T%d:C%d:%s\n", + timestamp, self->mytid, self->myConnection, self->reqName); +} + +securityd*:::request-entry +{ + @requests[self->reqName] = count(); + @total["Requests"] = count(); +} + +securityd*:::request-return +/self->reqConnection && arg0 == 0/ +{ + printf("%u T%d:C%d:return\n", + timestamp, self->mytid, self->myConnection); +} + +securityd*:::request-return +/self->reqConnection && arg0 != 0/ +{ + printf("%u T%d:C%d:FAIL(%d)\n", + timestamp, self->mytid, self->myConnection, arg0); +} + +securityd*:::request-return +{ + self->reqConnection = 0; + self->reqClient = 0; +} + + +/* + * Sessions + */ +typedef uint32_t SessionId; + +struct Session { + DTHandle handle; + SessionId sessionid; +}; +struct Session session[SessionId]; + +struct xauditinfo { + uint32_t ai_auid; /* audit user id */ + struct { + unsigned int low; + unsigned int high; + } ai_mask; + struct { + uint32_t dev; + uint32_t type; + uint32_t addr[4]; + } ai_termid; + au_asid_t ai_asid; /* audit session id */ + au_asflgs_t ai_flags; /* audit session flags */ +}; +self struct xauditinfo *ai; + +securityd*:::session-create +{ + session[arg1].handle = arg0; + session[arg1].sessionid = arg1; + self->ai = copyin(arg2, sizeof(struct xauditinfo)); + printf("%u T%d:%s(<%x>,id=%d,uid=%d,flags=%#x)\n", timestamp, self->mytid, probename, + arg0, arg1, self->ai->ai_auid, self->ai->ai_flags); +} + +securityd*:::session-kill +{ + printf("%u T%d:%s(<%x>,id=%d)\n", timestamp, self->mytid, probename, arg0, arg1); +} + +securityd*:::session-destroy +{ + printf("%u T%d:%s(<%x>,id=%d)\n", timestamp, self->mytid, probename, arg0, arg1); +} + +securityd*:::session-notify +{ + printf("%u T%d:%s(<%x>,id=%d,events=0x%x,uid=%d)\n", timestamp, self->mytid, probename, + session[arg0].handle, arg0, arg1, arg2); +} + + +/* + * Keychains + */ +securityd*:::keychain-* +{ + this->path = copyinstr(arg1); + printf("%u T%d:%s(<%x>,%s)\n", timestamp, self->mytid, probename, arg0, this->path); + @keychain[this->path, probename] = count(); +} + + +/* + * Low-level port events + */ +securityd*:::ports-* +{ + printf("%u T%d:%s(%d)\n", timestamp, self->mytid, probename, arg0); +} + + +/* + * Code signing + */ +securityd*:::guest-create +{ + printf("%u T%d:guest-create(<%x>,host=<%x>,guest=<%x>,status=0x%x,flags=0x%x,path=%s)\n", + timestamp, self->mytid, arg0, arg1, arg2, arg3, arg4, copyinstr(arg5)); + @total["Guests"] = count(); +} + +securityd*:::guest-change +{ + printf("%u T%d:guest-change(<%x>,<%x>,status=0x%x)\n", timestamp, self->mytid, arg0, arg1, arg2); +} + +securityd*:::guest-destroy +{ + printf("%u T%d:guest-destroy(<%x>,<%x>)\n", timestamp, self->mytid, arg0, arg1); +} + +securityd*:::host-register, +securityd*:::host-proxy +{ + printf("%u T%d:%s(<%x>,port=%d)\n", timestamp, self->mytid, probename, arg0, arg1); + @total["Hosts"] = count(); +} + +securityd*:::host-unregister +{ + printf("%u T%d:host-unregister(<%x>)\n", timestamp, self->mytid, arg0); +} + + +/* + * Child management + */ +securityd*:::child-* +{ + printf("%u T%d:%s(%d,%d)\n", timestamp, self->mytid, probename, arg0, arg1); +} + + +/* + * Power events + */ +securityd*:::power-* +{ + printf("%u T%d:POWER(%s)\n", timestamp, self->mytid, probename); +} + + +/* + * Authorization + */ +securityd*:::auth-create +{ + printf("%u T%d:%s ref(%#x) session(%#x)\n", timestamp, self->mytid, probename, arg1, arg0); +} + +securityd*:::auth-allow, +securityd*:::auth-deny, +securityd*:::auth-user, +securityd*:::auth-rules, +securityd*:::auth-kofn, +securityd*:::auth-mechrule +{ + printf("%u T%d:%s ref(%#x) rule(%s)\n", timestamp, self->mytid, probename, arg0, copyinstr(arg1)); +} + +securityd*:::auth-mech +{ + printf("%u T%d:%s ref(%#x) (%s)\n", timestamp, self->mytid, probename, arg0, copyinstr(arg1)); +} + +securityd*:::auth-user-allowroot, +securityd*:::auth-user-allowsessionowner +{ + printf("%u T%d:%s ref(%#x)\n", timestamp, self->mytid, probename, arg0); +} + +securityd*:::auth-evalright +{ + printf("%u T%d:%s ref(%#x) %s (%d)\n", timestamp, self->mytid, probename, arg0, copyinstr(arg1), arg2); +} + + +/* + * Miscellanea + */ +securityd*:::entropy-collect +{ + printf("%u T%d:entropy-collect()\n", timestamp, tid); +} + +securityd*:::entropy-seed +{ + printf("%u T%d:entropy-seed(%d)\n", timestamp, self->mytid, arg0); +} + +securityd*:::entropy-save +{ + printf("%u T%d:entropy-save(%s)\n", timestamp, self->mytid, copyinstr(arg0)); +} + +securityd*:::signal-* +{ + printf("%u T%d:%s(%d)\n", timestamp, self->mytid, probename, arg0); +} + + +/* + * Integrate secdebug logs + */ +security_debug*:::log +/execname == "securityd"/ +{ + printf("%u T%d:[%s]%s\n", timestamp, threads[tid], + copyinstr(arg0), copyinstr(arg1)); +} + +security_exception*:::throw-* +/execname == "securityd"/ +{ + printf("%u T%d:EXCEPTION(%p) THROWN %s(%d)\n", timestamp, threads[tid], + arg0, probename, arg1); +} + + +/* + * Wrapup + */ +:::END +{ + printa("%@8u %s\n", @total); + printf("\n Requests:\n"); + printa("%@8u %s\n", @requests); + printf("\n Requests by client:\n"); + printa("%@8u %s:%s\n", @request); + printf("\n Keychains by path and operation:\n"); + printa("%@8u %s(%s)\n", @keychain); +} diff --git a/securityd/etc/CodeEquivalenceCandidates b/securityd/etc/CodeEquivalenceCandidates new file mode 100644 index 00000000..41674bce --- /dev/null +++ b/securityd/etc/CodeEquivalenceCandidates @@ -0,0 +1,74 @@ +/Applications/Address Book.app +/Applications/Internet Connect.app +/Applications/Mail.app +/Applications/Safari.app +/Applications/Server/QTSS Publisher.app +/Applications/Server/Server Admin.app +/Applications/Server/Server Monitor.app +/Applications/Server/Workgroup Manager.app +/Applications/System Preferences.app +/Applications/Utilities/AirPort Admin Utility.app +/Applications/Utilities/Keychain Access.app +/Applications/Utilities/Keychain Access.app/Contents/Resources/Keychain Agent +/Applications/iCal.app +/Applications/iCal.app/Contents/Resources/iCal Helper.app +/Applications/iChat.app +/Applications/iMovie.app +/Applications/iPhoto.app +/Applications/iSync.app +/Applications/iTunes.app +/System/Library/CoreServices/Finder.app +/System/Library/CoreServices/loginwindow.app +/System/Library/CoreServices/MirrorAgent.app +/System/Library/CoreServices/SecurityAgent.app +/System/Library/CoreServices/SecurityAgent.app/Contents/Resources/authorizationhost +/System/Library/CoreServices/SyncServer.app +/System/Library/CoreServices/SyncServer.app/Contents/Resources/safaritool +/System/Library/CoreServices/SystemUIServer.app +/System/Library/CoreServices/dotmacsyncclient +/System/Library/Filesystems/ftp.fs/mount_ftp +/System/Library/Frameworks/ApplicationServices.framework/Frameworks/AE.framework/Versions/A/Support/AEServer +/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/AE.framework/Versions/A/Support/AEServer +/System/Library/Frameworks/ApplicationServices.framework/Versions/Current/Frameworks/AE.framework/Versions/A/Support/AEServer +/System/Library/Frameworks/ApplicationServices.framework/Frameworks/AE.framework/Versions/Current/Support/AEServer +/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/AE.framework/Versions/Current/Support/AEServer +/System/Library/Frameworks/ApplicationServices.framework/Versions/Current/Frameworks/AE.framework/Versions/Current/Support/AEServer +/System/Library/Frameworks/InstantMessage.framework/iChatAgent.app +/System/Library/Frameworks/SecurityFoundation.framework/Resources/dotmacfx.app +/System/Library/Frameworks/SecurityFoundation.framework/Resources/kcSync.app +/System/Library/PreferencePanes/Mac.prefPane +/System/Library/PreferencePanes/Mac.prefPane/Contents/Resources/dotMacPrefTool +/System/Library/PreferencePanes/Mac.prefPane/Contents/Versions/A/Resources/dotMacPrefTool +/System/Library/PreferencePanes/Mac.prefPane/Contents/Versions/Current/Resources/dotMacPrefTool +/System/Library/PrivateFrameworks/Admin.framework/Resources/writeconfig +/System/Library/PrivateFrameworks/Admin.framework/Versions/A/Resources/writeconfig +/System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport +/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport +/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport +/System/Library/PrivateFrameworks/Apple80211.framework/Resources/AirPortNetworkPrefs.bundle/Contents/Resources/AirPortCfgTool +/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/AirPortNetworkPrefs.bundle/Contents/Resources/AirPortCfgTool +/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/AirPortNetworkPrefs.bundle/Contents/Resources/AirPortCfgTool +/System/Library/PrivateFrameworks/DotmacLegacy.framework/Resources/dotMacTranslator +/System/Library/PrivateFrameworks/DotmacLegacy.framework/Versions/A/Resources/dotMacTranslator +/System/Library/PrivateFrameworks/DotmacLegacy.framework/Versions/Current/Resources/dotMacTranslator +/System/Library/PrivateFrameworks/InstantMessage.framework/iChatAgent.app +/System/Library/PrivateFrameworks/DMNotification.framework/Resources/dmnotifyd +/System/Library/PrivateFrameworks/DMNotification.framework/Versions/A/Resources/dmnotifyd +/System/Library/PrivateFrameworks/DMNotification.framework/Versions/Current/Resources/dmnotifyd +/System/Library/PrivateFrameworks/Syndication.framework/Resources/SyndicationAgent.app/Contents/MacOS/SyndicationAgent +/System/Library/PrivateFrameworks/Syndication.framework/Versions/A/Resources/SyndicationAgent.app/Contents/MacOS/SyndicationAgent +/System/Library/PrivateFrameworks/Syndication.framework/Versions/Current/Resources/SyndicationAgent.app/Contents/MacOS/SyndicationAgent +/System/Library/ScriptingAdditions/Keychain Scripting.app +/sbin/mount_smbfs +/sbin/mount_webdav +/usr/bin/certtool +/usr/bin/crlrefresh +/usr/bin/security +/usr/bin/smbutil +/usr/libexec/airportd +/usr/local/bin/cmsutil +/usr/sbin/configd +/usr/sbin/pppd +/usr/sbin/racoon +/usr/sbin/systemkeychain +/usr/sbin/mDNSResponder diff --git a/securityd/etc/com.apple.securityd.plist b/securityd/etc/com.apple.securityd.plist new file mode 100644 index 00000000..1002f4e8 --- /dev/null +++ b/securityd/etc/com.apple.securityd.plist @@ -0,0 +1,31 @@ + + + + + Label + com.apple.securityd + ProgramArguments + + /usr/sbin/securityd + -i + + MachServices + + com.apple.SecurityServer + + ResetAtClose + + + + RunAtLoad + + LaunchOnlyOnce + + BeginTransactionAtShutdown + + EnableTransactions + + POSIXSpawnType + Interactive + + diff --git a/securityd/etc/startup.mk b/securityd/etc/startup.mk new file mode 100644 index 00000000..7147bf7d --- /dev/null +++ b/securityd/etc/startup.mk @@ -0,0 +1,55 @@ +# +# Makefile to install the system-startup code for SecurityServer +# + +# wouldn't it be nice if PBX actually $#@?@! defined those? +# (for future ref: CoreOS Makefiles define many standard path vars) +# Note: CORE_SERVICES_DIR should be absolute path in target environment (don't prefix with DSTROOT) +SYSTEM_LIBRARY_DIR=$(DSTROOT)/System/Library +SYSTEM_CORE_SERVICES_DIR=/System/Library/CoreServices +ETC_DIR=$(DSTROOT)/private/etc +LAUNCH_DIR=$(DSTROOT)/System/Library/LaunchDaemons +#AUTHORIZATION_LOCATION=$(ETC_DIR) +#AUTHORIZATION_PLIST=$(AUTHORIZATION_LOCATION)/authorization +VARDB=$(DSTROOT)/private/var/db +CANDIDATES=$(VARDB)/CodeEquivalenceCandidates + +SRC=$(SRCROOT)/etc + + +# +# The other phases do nothing +# +build: + @echo null build. + +debug: + @echo null debug. + +profile: + @echo null profile. + +# +# Install +# +install: + mkdir -p $(LAUNCH_DIR) + cp $(SRC)/com.apple.securityd.plist $(LAUNCH_DIR) + #mkdir -p $(AUTHORIZATION_LOCATION) + #plutil -lint $(SRC)/authorization.plist + #cp $(SRC)/authorization.plist $(AUTHORIZATION_PLIST) + #chown root:wheel $(AUTHORIZATION_PLIST) + #chmod 644 $(AUTHORIZATION_PLIST) + mkdir -p $(VARDB) + cp $(SRC)/CodeEquivalenceCandidates $(CANDIDATES) + chown root:admin $(CANDIDATES) + chmod 644 $(CANDIDATES) + +installhdrs: + @echo null installhdrs. + +installsrc: + @echo null installsrc. + +clean: + @echo null clean. diff --git a/securityd/libsecurity_agent/Info-security_agent_client.plist b/securityd/libsecurity_agent/Info-security_agent_client.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/securityd/libsecurity_agent/Info-security_agent_client.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/securityd/libsecurity_agent/Info-security_agent_server.plist b/securityd/libsecurity_agent/Info-security_agent_server.plist new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/securityd/libsecurity_agent/Info-security_agent_server.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/securityd/libsecurity_agent/lib/agentclient.cpp b/securityd/libsecurity_agent/lib/agentclient.cpp new file mode 100644 index 00000000..a2f92f31 --- /dev/null +++ b/securityd/libsecurity_agent/lib/agentclient.cpp @@ -0,0 +1,597 @@ +/* + * agentclient.cpp + * SecurityAgent + * + * Copyright (c) 2002,2008,2011-2012 Apple Inc.. All Rights Reserved. + * + */ + + +#include + +/* +For now all the calls into agentclient will be synchronous, with timeouts + +On a timeout, we will return control to the client, but we really need to send the appropriate abort right there and then, otherwise they'll need to call the same method again to check that the reply still isn't there. + +If we receive a reply that is not confirming attempts to abort, we'll process these and return them to the caller. + +Alternatively, there can be an answer that isn't the answer we expected: setError, where the server aborts the transaction. + +We can't support interrupt() with a synchronous interface unless we add some notification that let's the client know that the "server" is dead +*/ + +#include +#include +#include + +#include // for size of replies +#include + +#include +#include +#include +#include +#include + +#include + +using LowLevelMemoryUtilities::increment; +using LowLevelMemoryUtilities::difference; +using Security::DataWalkers::walk; + +using Authorization::AuthItemSet; +using Authorization::AuthItemRef; +using Authorization::AuthValueOverlay; + +#include "agentclient.h" + +namespace SecurityAgent { + +class CheckingReconstituteWalker { +public: + CheckingReconstituteWalker(void *ptr, void *base, size_t size) + : mBase(base), mLimit(increment(base, size)), mOffset(difference(ptr, base)) { } + + template + void operator () (T &obj, size_t size = sizeof(T)) +{ } + + template + void operator () (T * &addr, size_t size = sizeof(T)) +{ + blob(addr, size); +} + +template +void blob(T * &addr, size_t size) +{ + DEBUGWALK("checkreconst:*"); + if (addr) { + if (addr < mBase || increment(addr, size) > mLimit) + MacOSError::throwMe(errAuthorizationInternal); + addr = increment(addr, mOffset); + } +} + +static const bool needsRelinking = true; +static const bool needsSize = false; + +private: +void *mBase; // old base address +void *mLimit; // old last byte address + 1 +off_t mOffset; // relocation offset +}; + +template +void relocate(T *obj, T *base, size_t size) +{ + if (obj) { + CheckingReconstituteWalker w(obj, base, size); + walk(w, base); + } +} + +void Client::check(mach_msg_return_t returnCode) +{ + // first check the Mach IPC return code + switch (returnCode) { + case MACH_MSG_SUCCESS: // peachy + break; + case MIG_SERVER_DIED: // explicit can't-send-it's-dead + CssmError::throwMe(CSSM_ERRCODE_NO_USER_INTERACTION); + default: // some random Mach error + MachPlusPlus::Error::throwMe(returnCode); + } +} + +void Client::checkResult() +{ + // now check the OSStatus return from the server side + switch (result()) { + case kAuthorizationResultAllow: return; + case kAuthorizationResultDeny: + case kAuthorizationResultUserCanceled: CssmError::throwMe(CSSM_ERRCODE_USER_CANCELED); + default: MacOSError::throwMe(errAuthorizationInternal); + } +} + + + +#pragma mark administrative operations + +Client::Client() : mState(init), mTerminateOnSleep(false) +{ + // create reply port + mClientPort.allocate(); //implicit MACH_PORT_RIGHT_RECEIVE + + // register with agentclients + Clients::gClients().insert(this); + + // add this client to the global list so that we can kill it if we have to + StLock _(Clients::gAllClientsMutex()); + Clients::allClients().insert(this); +} + +void +Client::activate(Port serverPort) +{ + if (!serverPort) + MacOSError::throwMe(errAuthorizationInternal); + + secdebug("agentclient", "using server at port %d", serverPort.port()); + mServerPort = serverPort; +} + + +Client::~Client() +{ + teardown(); +} + + +// start/endTransaction calls stand outside the usual client protocol: they +// don't participate in the state-management or multiplexing-by-port tangoes. +// (These calls could take advantage of activate(), but callers would be +// instantiating an entire Client object for the sake of mServerPort.) +// Conversely, SecurityAgent::Client does not cache transaction state. +OSStatus +Client::startTransaction(Port serverPort) +{ + if (!serverPort) + return errAuthorizationInternal; + kern_return_t ret = sa_request_client_txStart(serverPort); + secdebug("agentclient", "Transaction started (port %u)", serverPort.port()); + return ret; +} + +OSStatus +Client::endTransaction(Port serverPort) +{ + if (!serverPort) + return errAuthorizationInternal; + secdebug("agentclient", "Requesting end of transaction (port %u)", serverPort.port()); + return sa_request_client_txEnd(serverPort); +} + +void +Client::setState(PluginState inState) +{ + // validate state transition: might be more useful where change is requested if that implies anything to interpreting what to do. + // Mutex + mState = inState; +} + +void Client::teardown() throw() +{ + // remove this from the global list + { + StLock _(Clients::gAllClientsMutex()); + Clients::allClients().erase(this); + } + + Clients::gClients().remove(this); + + try { + if (mStagePort) + mStagePort.destroy(); + if (mClientPort) + mClientPort.destroy(); + } catch (...) { secdebug("agentclient", "ignoring problems tearing down ports for client %p", this); } +} + + +AuthItemSet +Client::clientHints(SecurityAgent::RequestorType type, std::string &path, pid_t clientPid, uid_t clientUid) +{ + AuthItemSet clientHints; + + clientHints.insert(AuthItemRef(AGENT_HINT_CLIENT_TYPE, AuthValueOverlay(sizeof(type), &type))); + clientHints.insert(AuthItemRef(AGENT_HINT_CLIENT_PATH, AuthValueOverlay(path))); + clientHints.insert(AuthItemRef(AGENT_HINT_CLIENT_PID, AuthValueOverlay(sizeof(clientPid), &clientPid))); + clientHints.insert(AuthItemRef(AGENT_HINT_CLIENT_UID, AuthValueOverlay(sizeof(clientUid), &clientUid))); + + return clientHints; +} + + +#pragma mark request operations + +OSStatus Client::contact(mach_port_t jobId, Bootstrap processBootstrap, mach_port_t userPrefs) +{ + kern_return_t ret = sa_request_client_contact(mServerPort, mClientPort, jobId, processBootstrap, userPrefs); + if (ret) + { + Syslog::error("SecurityAgent::Client::contact(): kern_return error %s", + mach_error_string(ret)); + } + return ret; +} + +OSStatus Client::create(const char *inPluginId, const char *inMechanismId, const SessionId inSessionId) +{ + // securityd is already notified when the agent/authhost dies through SIGCHILD, and we only really care about the stage port, but we will track if dying happens during create with a DPN. If two threads are both in the time between the create message and the didcreate answer and the host dies, one will be stuck - too risky and I will win the lottery before that: Chablis. + { + kern_return_t ret; + mach_port_t old_port = MACH_PORT_NULL; + ret = mach_port_request_notification(mach_task_self(), mServerPort, MACH_NOTIFY_DEAD_NAME, 0, mClientPort, MACH_MSG_TYPE_MAKE_SEND_ONCE, &old_port); + if (!ret && (MACH_PORT_NULL != old_port)) + mach_port_deallocate(mach_task_self(), old_port); + } + + secdebug("agentclient", "asking server at port %d to create %s:%s; replies to %d", mServerPort.port(), inPluginId, inMechanismId, mClientPort.port()); // XXX/cs + kern_return_t ret = sa_request_client_create(mServerPort, mClientPort, inSessionId, inPluginId, inMechanismId); + + if (ret) + return ret; + + // wait for message (either didCreate, reportError) + do + { + // one scenario that could happen here (and only here) is: + // host died before create finished - in which case we'll get a DPN + try { receive(); } catch (...) { setState(dead); } + } + while ((state() != created) && + (state() != dead)); + + // verify that we got didCreate + if (state() == created) + return noErr; + + // and not reportError + if (state() == dead) + return Client::getError(); + + // something we don't deal with + secdebug("agentclient", "we got an error on create"); // XXX/cs + return errAuthorizationInternal; +} + +// client maintains their own copy of the current data +OSStatus Client::invoke() +{ + if ((state() != created) && + (state() != active) && + (state() != interrupting)) + return errAuthorizationInternal; + + AuthorizationValueVector *arguments; + AuthorizationItemSet *hints, *context; + size_t argumentSize, hintSize, contextSize; + + mInHints.copy(hints, hintSize); + mInContext.copy(context, contextSize); + mArguments.copy(&arguments, &argumentSize); + + setState(current); + + check(sa_request_client_invoke(mStagePort.port(), + arguments, argumentSize, arguments, // data, size, offset + hints, hintSize, hints, + context, contextSize, context)); + + receive(); + + free (arguments); + free (hints); + free (context); + + switch(state()) + { + case active: + switch(result()) + { + case kAuthorizationResultUndefined: + MacOSError::throwMe(errAuthorizationInternal); + default: + return noErr; + } + case dead: + return mErrorState; + case current: + return noErr; + default: + break; + } + return errAuthorizationInternal; +} + +OSStatus +Client::deactivate() +{ + // check state is current + if (state() != current) + return errAuthorizationInternal; + + secdebug("agentclient", "deactivating mechanism at request port %d", mStagePort.port()); + + // tell mechanism to deactivate + check(sa_request_client_deactivate(mStagePort.port())); + + setState(deactivating); + + receive(); + + // if failed destroy it + return noErr; +} + +OSStatus +Client::destroy() +{ + if (state() == active || state() == created || state() == current) + { + secdebug("agentclient", "destroying mechanism at request port %d", mStagePort.port()); + // tell mechanism to destroy + if (mStagePort) + sa_request_client_destroy(mStagePort.port()); + + setState(dead); + + return noErr; + } + + return errAuthorizationInternal; +} + +// kill host: do not pass go, do not collect $200 +OSStatus +Client::terminate() +{ + check(sa_request_client_terminate(mServerPort.port())); + + return noErr; +} + +void +Client::receive() +{ + bool gotReply = false; + while (!gotReply) + gotReply = Clients::gClients().receive(); +} + +#pragma mark result operations + +void Client::setResult(const AuthorizationResult inResult, const AuthorizationItemSet *inHints, const AuthorizationItemSet *inContext) +{ + if (state() != current) + return; + // construct AuthItemSet for hints and context (deep copy - previous contents are released) + mOutHints = (*inHints); + mOutContext = (*inContext); + mResult = inResult; + setState(active); +} + +void Client::setError(const OSStatus inMechanismError) +{ + setState(dead); + + mErrorState = inMechanismError; +} + +OSStatus Client::getError() +{ + return mErrorState; +} + +void Client::requestInterrupt() +{ + if (state() != active) + return; + + setState(interrupting); +} + +void Client::didDeactivate() +{ + if (state() != deactivating) + return; + + // check state for deactivating + // change state + setState(active); +} + +void Client::setStagePort(const mach_port_t inStagePort) +{ + mStagePort = Port(inStagePort); + mStagePort.requestNotify(mClientPort, MACH_NOTIFY_DEAD_NAME, 0); +} + + +void Client::didCreate(const mach_port_t inStagePort) +{ + // it can be dead, because the host died, we'll always try to revive it once + if ((state() != init) && (state() != dead)) + return; + + setStagePort(inStagePort); + setState(created); +} + +#pragma mark client instances + +ThreadNexus Clients::gClients; +ModuleNexus > Clients::allClients; + +bool +Clients::compare(const Client * client, mach_port_t instance) +{ + if (client->instance() == instance) return true; + return false; +} + +// throw so the agent client operation is aborted +Client& +Clients::find(mach_port_t instanceReplyPort) const +{ + StLock _(mLock); + for (set::const_iterator foundClient = mClients.begin(); + foundClient != mClients.end(); + foundClient++) + { + Client *client = *foundClient; + if (client->instance() == instanceReplyPort) + return *client; + } + + // can't be receiving for a client we didn't create + MacOSError::throwMe(errAuthorizationInternal); +} + +bool +Clients::receive() +{ + try + { + // maximum known message size (variable sized elements are already forced OOL) + Message in(sizeof(union __ReplyUnion__sa_reply_client_secagentreply_subsystem)); + Message out(sizeof(union __ReplyUnion__sa_reply_client_secagentreply_subsystem)); + + in.receive(mClientPortSet, 0, 0); + + // got the message, now demux it; call secagentreply_server to handle any call + // this is asynchronous, so no reply message, although not apparent + if (!::secagentreply_server(in, out)) + { + // port death notification + if (MACH_NOTIFY_DEAD_NAME == in.msgId()) + { + find(in.remotePort()).setError(errAuthorizationInternal); + return true; + } + return false; + + } + else + return true; + } + catch (Security::MachPlusPlus::Error &e) + { + secdebug("agentclient", "interpret error %ul", e.error); + switch (e.error) { + case MACH_MSG_SUCCESS: // peachy + break; + case MIG_SERVER_DIED: // explicit can't-send-it's-dead + CssmError::throwMe(CSSM_ERRCODE_NO_USER_INTERACTION); + default: // some random Mach error + MachPlusPlus::Error::throwMe(e.error); + } + } + catch (...) + { + MacOSError::throwMe(errAuthorizationInternal); + } + return false; +} + +ModuleNexus Clients::gAllClientsMutex; + +void +Clients::killAllClients() +{ + // grab the lock for the client list -- we need to make sure no one modifies the structure while we are iterating it. + StLock _(gAllClientsMutex()); + + set::iterator clientIterator = allClients().begin(); + while (clientIterator != allClients().end()) + { + set::iterator thisClient = clientIterator++; + if ((*thisClient)->getTerminateOnSleep()) + { + (*thisClient)->terminate(); + } + } +} + + + +} /* end namesapce SecurityAgent */ + +#pragma mark demux requests replies +// external C symbols for the mig message handling code to call into + +#define COPY_IN(type,name) type *name, mach_msg_type_number_t name##Length, type *name##Base + +// callbacks that key off instanceReplyPort to find the right agentclient instance +// to deliver the message to. + +// they make the data readable to the receiver (relocate internal references) + +kern_return_t sa_reply_server_didCreate(mach_port_t instanceReplyPort, mach_port_t instanceRequestPort) +{ + secdebug("agentclient", "got didCreate at port %u; requests go to port %u", instanceReplyPort, instanceRequestPort); + SecurityAgent::Clients::gClients().find(instanceReplyPort).didCreate(instanceRequestPort); + return KERN_SUCCESS; +} + +kern_return_t sa_reply_server_setResult(mach_port_t instanceReplyPort, AuthorizationResult result, + COPY_IN(AuthorizationItemSet,inHints) , + COPY_IN(AuthorizationItemSet,inContext) ) +{ + secdebug("agentclient", "got setResult at port %u; result %u", instanceReplyPort, (unsigned int)result); + + // relink internal references according to current place in memory + try { SecurityAgent::relocate(inHints, inHintsBase, inHintsLength); } + catch (MacOSError &e) { return e.osStatus(); } + catch (...) { return errAuthorizationInternal; } + + try { SecurityAgent::relocate(inContext, inContextBase, inContextLength); } + catch (MacOSError &e) { return e.osStatus(); } + catch (...) { return errAuthorizationInternal; } + + SecurityAgent::Clients::gClients().find(instanceReplyPort).setResult(result, inHints, inContext); + + return KERN_SUCCESS; +} + +kern_return_t sa_reply_server_requestInterrupt(mach_port_t instanceReplyPort) +{ + secdebug("agentclient", "got requestInterrupt at port %u", instanceReplyPort); + SecurityAgent::Clients::gClients().find(instanceReplyPort).requestInterrupt(); + return KERN_SUCCESS; +} + +kern_return_t sa_reply_server_didDeactivate(mach_port_t instanceReplyPort) +{ + secdebug("agentclient", "got didDeactivate at port %u", instanceReplyPort); + SecurityAgent::Clients::gClients().find(instanceReplyPort).didDeactivate(); + return KERN_SUCCESS; +} + +kern_return_t sa_reply_server_reportError(mach_port_t instanceReplyPort, OSStatus status) +{ + secdebug("agentclient", "got reportError at port %u; error is %u", instanceReplyPort, (unsigned int)status); + SecurityAgent::Clients::gClients().find(instanceReplyPort).setError(status); + return KERN_SUCCESS; +} + +kern_return_t sa_reply_server_didStartTx(mach_port_t replyPort, kern_return_t retval) +{ + // no instance ports here: this goes straight to server + secdebug("agentclient", "got didStartTx"); + return retval; +} diff --git a/securityd/libsecurity_agent/lib/agentclient.h b/securityd/libsecurity_agent/lib/agentclient.h new file mode 100644 index 00000000..70f9e00c --- /dev/null +++ b/securityd/libsecurity_agent/lib/agentclient.h @@ -0,0 +1,220 @@ +/* + * agentclient.h + * SecurityAgent + * + * Copyright (c) 2002,2008,2011-2013 Apple Inc.. All Rights Reserved. + * + */ + +#ifndef _H_AGENTCLIENT +#define _H_AGENTCLIENT + +#include +#include +#include +#include + +#include + +#if defined(__cplusplus) + +#include +#include +#include + +namespace SecurityAgent { +#endif /* __cplusplus__ */ + +// Manimum number of failed authentications before +// SecurityAgent dialog is killed. +#define kMaximumAuthorizationTries 10000 + +// Number of failed authentications before a password +// hint is displayed. +#define kAuthorizationTriesBeforeHint 3 + +#define maxPassphraseLength 1024 + +// +// Unified reason codes transmitted to SecurityAgent (and internationalized there) +// +enum Reason { + noReason = 0, // no reason (not used, used as a NULL) + unknownReason, // something else (catch-all internal error) + + // reasons for asking for a new passphrase + newDatabase = 11, // need passphrase for a new database + changePassphrase, // changing passphrase for existing database + + // reasons for retrying an unlock query + invalidPassphrase = 21, // passphrase was wrong + + // reasons for retrying a new passphrase query + passphraseIsNull = 31, // empty passphrase + passphraseTooSimple, // passphrase is not complex enough + passphraseRepeated, // passphrase was used before (must use new one) + passphraseUnacceptable, // passphrase unacceptable for some other reason + oldPassphraseWrong, // the old passphrase given is wrong + + // reasons for retrying an authorization query + userNotInGroup = 41, // authenticated user not in needed group + unacceptableUser, // authenticated user unacceptable for some other reason + + // reasons for canceling a staged query + tooManyTries = 61, // too many failed attempts to get it right + noLongerNeeded, // the queried item is no longer needed + keychainAddFailed, // the requested itemed couldn't be added to the keychain + generalErrorCancel, // something went wrong so we have to give up now + resettingPassword, // The user has indicated that they wish to reset their password + + worldChanged = 101 +}; + +typedef enum { + tool = 'TOOL', + bundle = 'BNDL', + unknown = 'UNKN' +} RequestorType; + +#if defined(__cplusplus) + +using MachPlusPlus::Port; +using MachPlusPlus::PortSet; +using MachPlusPlus::Bootstrap; +using MachPlusPlus::ReceivePort; +using MachPlusPlus::Message; +using Authorization::AuthItemSet; +using Authorization::AuthValueVector; + +class Clients; + +class Client +{ +friend class Clients; + +enum MessageType { requestInterruptMessage, didDeactivateMessage, reportErrorMessage }; + +public: + Client(); + virtual ~Client(); + + static AuthItemSet clientHints(SecurityAgent::RequestorType type, std::string &path, pid_t clientPid, uid_t clientUid); + + static OSStatus startTransaction(Port serverPort); + static OSStatus endTransaction(Port serverPort); + +protected: + void establishServer(); + +public: + void activate(Port serverPort); + + OSStatus contact(mach_port_t jobId, Bootstrap processBootstrap, mach_port_t userPrefs); + OSStatus create(const char *pluginId, const char *mechanismId, const SessionId inSessionId); + void setArguments(const Authorization::AuthValueVector& inArguments) { mArguments = inArguments; } + void setInput(const Authorization::AuthItemSet& inHints, const Authorization::AuthItemSet& inContext) { mInHints = inHints; mInContext = inContext; } + OSStatus invoke(); + OSStatus deactivate(); + OSStatus destroy(); + OSStatus terminate(); + void receive(); + + void didCreate(const mach_port_t inStagePort); + void setResult(const AuthorizationResult inResult, const AuthorizationItemSet *inHints, const AuthorizationItemSet *inContext); + void requestInterrupt(); // setMessageType(requestInterrupt); + void didDeactivate(); // setMessageType(didDeactivate); + + void setError(const OSStatus inMechanismError); // setMessageType(reportError); setError(mechanismError); + OSStatus getError(); + AuthorizationResult result() { return mResult; } + + typedef enum _PluginState { + init, + created, + current, + deactivating, + active, + interrupting, + dead + } PluginState; + PluginState state() { return mState; } + +protected: + void setMessageType(const MessageType inMessageType); + // allow didCreate to set stagePort + void setStagePort(const mach_port_t inStagePort); + // allow server routines to use request port to find instance + + // @@@ implement lessThan operator for set in terms of instance + +protected: + void setup(); + void teardown() throw(); + + Port mServerPort; + Port mStagePort; + Port mClientPort; + + MessageType mMessageType; + + OSStatus mErrorState; + + AuthorizationResult mResult; + AuthValueVector mArguments; + AuthItemSet mInHints; + AuthItemSet mInContext; + AuthItemSet mOutHints; + AuthItemSet mOutContext; + + PluginState mState; + void setState(PluginState mState); + + bool mTerminateOnSleep; + +public: + mach_port_t instance() const { return mClientPort; } +// bool operator == (const Client &other) const { return this->instance() == other.instance(); } + bool operator < (const Client &other) const { return this->instance() < other.instance(); } + + AuthItemSet &inHints() { return mInHints; } + AuthItemSet &inContext() { return mInContext; } + AuthItemSet &outHints() { return mOutHints; } + AuthItemSet &outContext() { return mOutContext; } + + void setTerminateOnSleep(bool terminateOnSleep) {mTerminateOnSleep = terminateOnSleep;} + bool getTerminateOnSleep() {return mTerminateOnSleep;} + +public: + void check(mach_msg_return_t returnCode); + void checkResult(); +}; + +class Clients +{ +friend class Client; + +protected: + set mClients; + PortSet mClientPortSet; +public: + Clients() {} + void create(); // create an agentclient + void insert(Client *agent) { StLock _(mLock); mClients.insert(agent); mClientPortSet += agent->instance(); } + void remove(Client *agent) { StLock _(mLock); mClientPortSet -= agent->instance(); mClients.erase(agent); } + Client &find(const mach_port_t instance) const; + bool receive(); + bool compare(const Client * client, mach_port_t instance); + + mutable Mutex mLock; + static ThreadNexus gClients; + static ModuleNexus gAllClientsMutex; + static ModuleNexus > allClients; + static void killAllClients(); +}; + +} // end namespace Authorization + +#endif /* __cplusplus__ */ + +#endif /* _H_AGENTCLIENT */ + diff --git a/securityd/libsecurity_agent/lib/sa_types.h b/securityd/libsecurity_agent/lib/sa_types.h new file mode 100644 index 00000000..8ccb1362 --- /dev/null +++ b/securityd/libsecurity_agent/lib/sa_types.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2002,2008,2011 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please obtain + * a copy of the License at http://www.apple.com/publicsource and read it before + * using this file. + * + * This 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. + */ + +#ifndef _H_SA_TYPES +#define _H_SA_TYPES + +#define __MigTypeCheck 1 + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif // C++ + +#include + +// force unmangled name +boolean_t secagentreply_server(mach_msg_header_t *, mach_msg_header_t *); + +typedef u_int32_t SessionId; +typedef uint32_t MigBoolean; +typedef uint32_t SATransactionId; + +typedef AuthorizationItemSet AuthorizationItemSetBlob; +typedef AuthorizationItemSet *AuthorizationItemSetPtr; +typedef AuthorizationValueVector AuthorizationValueVectorBlob; +typedef AuthorizationValueVector *AuthorizationValueVectorPtr; + +typedef AuthorizationMechanismId PluginId; +typedef AuthorizationMechanismId MechanismId; + +// pass structured arguments in/out of IPC calls. See "data walkers" for details +#define BLOB(copy) copy, copy.length(), copy +#define BLOB_OUT(copy) ©, ©##Length, ©##Base +#define BLOB_DECL(type,name) type *name, *name##Base; mach_msg_type_number_t name##Length +#define BLOB_FUNC_DECL(type,name) type *name, type *name##Base, mach_msg_type_number_t name##Length + +// +// Customization macros for MIG code +// +/* +#define __AfterSendRpc(id, name) \ + if (msg_result == MACH_MSG_SUCCESS && Out0P->Head.msgh_id == MACH_NOTIFY_DEAD_NAME) \ + return MIG_SERVER_DIED; + +#define UseStaticTemplates 0 +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _H_SA_TYPES */ + diff --git a/securityd/libsecurity_agent/lib/secagent_types.h b/securityd/libsecurity_agent/lib/secagent_types.h new file mode 100644 index 00000000..807e8fcc --- /dev/null +++ b/securityd/libsecurity_agent/lib/secagent_types.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2000-2001,2011 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please obtain + * a copy of the License at http://www.apple.com/publicsource and read it before + * using this file. + * + * This 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. + */ + + +// +// secagent_types - type equivalence declarations for SecurityAgent MIG +// +#include +#include +#include + + +namespace Security +{ + +using namespace SecurityAgent; + +typedef void *Data; + +typedef char *String; +typedef const char *ConstString; +typedef Client::KeychainChoice Choice; +typedef char *Username; +typedef uint32 MigBoolean; + +typedef uint32 AuthorizationResultInt; + + +// +// Customization macros for MIG code +// +#define __AfterSendRpc(id, name) \ + if (msg_result == MACH_MSG_SUCCESS && Out0P->Head.msgh_id == MACH_NOTIFY_DEAD_NAME) \ + return MIG_SERVER_DIED; + +#define UseStaticTemplates 0 + + +} // end namespace Security diff --git a/securityd/libsecurity_agent/lib/utils.c b/securityd/libsecurity_agent/lib/utils.c new file mode 100644 index 00000000..f3d08392 --- /dev/null +++ b/securityd/libsecurity_agent/lib/utils.c @@ -0,0 +1,26 @@ +/* + * utils.h + * libsecurity_agent + * + * Copyright (c) 2010-2011 Apple Inc. All Rights Reserved. + * + */ + + +#include "utils.h" + +unsigned char * +uuid_init_with_sessionid(uuid_t uuid, uint32_t sessionid) +{ + uuid_t tmp = UUID_INITIALIZER_FROM_SESSIONID(sessionid); + + uuid_copy(uuid, tmp); + return &uuid[0]; +} + +const char * +uuid_to_string(const uuid_t uuid, char *buf) +{ + uuid_unparse_lower(uuid, buf); + return buf; +} diff --git a/securityd/libsecurity_agent/lib/utils.h b/securityd/libsecurity_agent/lib/utils.h new file mode 100644 index 00000000..c4bb86fd --- /dev/null +++ b/securityd/libsecurity_agent/lib/utils.h @@ -0,0 +1,26 @@ +/* + * utils.h + * libsecurity_agent + * + * Copyright (c) 2010-2011 Apple Inc. All Rights Reserved. + * + */ + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +#define UUID_INITIALIZER_FROM_SESSIONID(sessionid) \ + { 0,0,0,0, 0,0,0,0, 0,0,0,0, \ + (0xff000000 & (sessionid))>>24, (0x00ff0000 & (sessionid))>>16, \ + (0x0000ff00 & (sessionid))>>8, (0x000000ff & (sessionid)) } + +unsigned char *uuid_init_with_sessionid(uuid_t uuid, uint32_t sessionid); +const char *uuid_to_string(const uuid_t uuid, char *buf); + +#if defined(__cplusplus) +} +#endif diff --git a/securityd/libsecurity_agent/libsecurity_agent.xcodeproj/project.pbxproj b/securityd/libsecurity_agent/libsecurity_agent.xcodeproj/project.pbxproj new file mode 100644 index 00000000..65e10554 --- /dev/null +++ b/securityd/libsecurity_agent/libsecurity_agent.xcodeproj/project.pbxproj @@ -0,0 +1,513 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + 40635B69052E4CBD0009891B /* world */ = { + isa = PBXAggregateTarget; + buildConfigurationList = C27AD23D0987FCDC001272E0 /* Build configuration list for PBXAggregateTarget "world" */; + buildPhases = ( + ); + dependencies = ( + 40635B6F052E4CD00009891B /* PBXTargetDependency */, + 40635B6E052E4CCD0009891B /* PBXTargetDependency */, + ); + name = world; + productName = world; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 18B965C51473155E005A4D2E /* sa_reply.h in Headers */ = {isa = PBXBuildFile; fileRef = 40ACCCCC05DC565700E9F642 /* sa_reply.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18B965C614731564005A4D2E /* utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B3720A1104E343000D2A39 /* utils.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18B965C914731593005A4D2E /* sa_types.h in Headers */ = {isa = PBXBuildFile; fileRef = 40ACCCBD05DC556000E9F642 /* sa_types.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18B965CA14731598005A4D2E /* sa_request.h in Headers */ = {isa = PBXBuildFile; fileRef = 40ACCCCD05DC565700E9F642 /* sa_request.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 409513EC05E6A5780003976E /* agentclient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 409513EA05E6A5780003976E /* agentclient.cpp */; }; + 409513ED05E6A5780003976E /* agentclient.h in Headers */ = {isa = PBXBuildFile; fileRef = 409513EB05E6A5780003976E /* agentclient.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 40ACCCD705DC580800E9F642 /* sa_request_user.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 40ACCCD505DC57E200E9F642 /* sa_request_user.cpp */; }; + 40ACCCD805DC583700E9F642 /* sa_reply_server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 40ACCCD005DC578C00E9F642 /* sa_reply_server.cpp */; }; + 40ACCCDA05DC587C00E9F642 /* sa_request_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 40ACCCD405DC57E200E9F642 /* sa_request_server.c */; }; + 40ACCCDB05DC587C00E9F642 /* sa_reply_user.c in Sources */ = {isa = PBXBuildFile; fileRef = 40ACCCD105DC578C00E9F642 /* sa_reply_user.c */; }; + 72B3720C1104E343000D2A39 /* utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B3720A1104E343000D2A39 /* utils.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 72B3720D1104E343000D2A39 /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B3720B1104E343000D2A39 /* utils.c */; }; + 72B3720F1104E343000D2A39 /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B3720B1104E343000D2A39 /* utils.c */; }; + 72B372321104EB8D000D2A39 /* utils.h in Sources */ = {isa = PBXBuildFile; fileRef = 72B3720A1104E343000D2A39 /* utils.h */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 18B965C71473157C005A4D2E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 40E8FACC052E45D000A3D8D1; + remoteInfo = "generate mig"; + }; + 4C25921905448C1E007AEE03 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4CA1FECF052A450F00F22E42; + remoteInfo = libsecurity_agent_server; + }; + 4C25921C05448C1E007AEE03 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4CA1FEBD052A3C8100F22E42; + remoteInfo = libsecurity_agent_client; + }; + 4C25921D05448C1E007AEE03 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEAB052A3C3800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 40E8FACC052E45D000A3D8D1; + remoteInfo = mig; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 1865FFA41474FB2100FD79DF /* debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 1865FFA51474FB2100FD79DF /* project.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = project.xcconfig; sourceTree = ""; }; + 1865FFA61474FB2100FD79DF /* release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 409513EA05E6A5780003976E /* agentclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = agentclient.cpp; sourceTree = ""; }; + 409513EB05E6A5780003976E /* agentclient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = agentclient.h; sourceTree = ""; }; + 40ACCCBD05DC556000E9F642 /* sa_types.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sa_types.h; sourceTree = ""; }; + 40ACCCC505DC559800E9F642 /* sa_reply.defs */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.mig; path = sa_reply.defs; sourceTree = ""; }; + 40ACCCC605DC559800E9F642 /* sa_request.defs */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.mig; path = sa_request.defs; sourceTree = ""; }; + 40ACCCCC05DC565700E9F642 /* sa_reply.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sa_reply.h; path = derived_src/security_agent_client/sa_reply.h; sourceTree = BUILT_PRODUCTS_DIR; }; + 40ACCCCD05DC565700E9F642 /* sa_request.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sa_request.h; path = derived_src/security_agent_client/sa_request.h; sourceTree = BUILT_PRODUCTS_DIR; }; + 40ACCCD005DC578C00E9F642 /* sa_reply_server.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = sa_reply_server.cpp; path = derived_src/security_agent_client/sa_reply_server.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; + 40ACCCD105DC578C00E9F642 /* sa_reply_user.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = sa_reply_user.c; path = derived_src/security_agent_client/sa_reply_user.c; sourceTree = BUILT_PRODUCTS_DIR; }; + 40ACCCD405DC57E200E9F642 /* sa_request_server.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = sa_request_server.c; path = derived_src/security_agent_client/sa_request_server.c; sourceTree = BUILT_PRODUCTS_DIR; }; + 40ACCCD505DC57E200E9F642 /* sa_request_user.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = sa_request_user.cpp; path = derived_src/security_agent_client/sa_request_user.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C24BF380557273B00C95CD3 /* mig.mk */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = mig.mk; sourceTree = ""; usesTabs = 1; }; + 4CA1FEBE052A3C8100F22E42 /* libsecurity_agent_client.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_agent_client.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CA1FED4052A450F00F22E42 /* libsecurity_agent_server.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_agent_server.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 72B3720A1104E343000D2A39 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = ""; }; + 72B3720B1104E343000D2A39 /* utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = utils.c; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CA1FED2052A450F00F22E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1865FFA31474FB2100FD79DF /* config */ = { + isa = PBXGroup; + children = ( + 1865FFA41474FB2100FD79DF /* debug.xcconfig */, + 1865FFA51474FB2100FD79DF /* project.xcconfig */, + 1865FFA61474FB2100FD79DF /* release.xcconfig */, + ); + name = config; + path = ../config; + sourceTree = ""; + }; + 4C24BF370557273B00C95CD3 /* mig */ = { + isa = PBXGroup; + children = ( + 4C24BF380557273B00C95CD3 /* mig.mk */, + 40ACCCC505DC559800E9F642 /* sa_reply.defs */, + 40ACCCC605DC559800E9F642 /* sa_request.defs */, + ); + path = mig; + sourceTree = ""; + }; + 4C7503520540CEAC00056564 /* lib */ = { + isa = PBXGroup; + children = ( + 409513EA05E6A5780003976E /* agentclient.cpp */, + 409513EB05E6A5780003976E /* agentclient.h */, + 40ACCCBD05DC556000E9F642 /* sa_types.h */, + 72B3720A1104E343000D2A39 /* utils.h */, + 72B3720B1104E343000D2A39 /* utils.c */, + ); + path = lib; + sourceTree = ""; + }; + 4C75036D0540CEDE00056564 /* derived_src */ = { + isa = PBXGroup; + children = ( + 40ACCCCD05DC565700E9F642 /* sa_request.h */, + 40ACCCD405DC57E200E9F642 /* sa_request_server.c */, + 40ACCCD505DC57E200E9F642 /* sa_request_user.cpp */, + 40ACCCCC05DC565700E9F642 /* sa_reply.h */, + 40ACCCD005DC578C00E9F642 /* sa_reply_server.cpp */, + 40ACCCD105DC578C00E9F642 /* sa_reply_user.c */, + ); + path = derived_src; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4CA1FEA7052A3C3800F22E42 = { + isa = PBXGroup; + children = ( + 4C7503520540CEAC00056564 /* lib */, + 1865FFA31474FB2100FD79DF /* config */, + 4C24BF370557273B00C95CD3 /* mig */, + 4C75036D0540CEDE00056564 /* derived_src */, + 4CA1FEBF052A3C8100F22E42 /* Products */, + ); + sourceTree = ""; + }; + 4CA1FEBF052A3C8100F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + 4CA1FEBE052A3C8100F22E42 /* libsecurity_agent_client.a */, + 4CA1FED4052A450F00F22E42 /* libsecurity_agent_server.a */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4CA1FEB9052A3C8100F22E42 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 409513ED05E6A5780003976E /* agentclient.h in Headers */, + 72B3720C1104E343000D2A39 /* utils.h in Headers */, + 18B965CA14731598005A4D2E /* sa_request.h in Headers */, + 18B965C914731593005A4D2E /* sa_types.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CA1FED0052A450F00F22E42 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 18B965C614731564005A4D2E /* utils.h in Headers */, + 18B965C51473155E005A4D2E /* sa_reply.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXLegacyTarget section */ + 40E8FACC052E45D000A3D8D1 /* generate mig */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "-f mig/mig.mk $ACTION"; + buildConfigurationList = C27AD2290987FCDC001272E0 /* Build configuration list for PBXLegacyTarget "generate mig" */; + buildPhases = ( + ); + buildToolPath = /usr/bin/gnumake; + dependencies = ( + ); + name = "generate mig"; + passBuildSettingsInEnvironment = 1; + productName = mig; + }; +/* End PBXLegacyTarget section */ + +/* Begin PBXNativeTarget section */ + 4CA1FEBD052A3C8100F22E42 /* libsecurity_agent_client */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD2390987FCDC001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_agent_client" */; + buildPhases = ( + 4CA1FEB9052A3C8100F22E42 /* Headers */, + 4CA1FEBA052A3C8100F22E42 /* Sources */, + 4CA1FEBB052A3C8100F22E42 /* Frameworks */, + 1865FFDE14751B6E00FD79DF /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 18B965C81473157C005A4D2E /* PBXTargetDependency */, + ); + name = libsecurity_agent_client; + productInstallPath = /usr/local/lib; + productName = libsecurity_agent; + productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_agent_client.a */; + productType = "com.apple.product-type.library.static"; + }; + 4CA1FECF052A450F00F22E42 /* libsecurity_agent_server */ = { + isa = PBXNativeTarget; + buildConfigurationList = C27AD2350987FCDC001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_agent_server" */; + buildPhases = ( + 4CA1FED0052A450F00F22E42 /* Headers */, + 4CA1FED1052A450F00F22E42 /* Sources */, + 4CA1FED2052A450F00F22E42 /* Frameworks */, + 1865FFDF14751B7600FD79DF /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 40C765C3053485EE008AC043 /* PBXTargetDependency */, + ); + name = libsecurity_agent_server; + productName = libsecurity_agent; + productReference = 4CA1FED4052A450F00F22E42 /* libsecurity_agent_server.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA1FEAB052A3C3800F22E42 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0440; + }; + buildConfigurationList = C27AD2450987FCDC001272E0 /* Build configuration list for PBXProject "libsecurity_agent" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 4CA1FEA7052A3C3800F22E42; + productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 40635B69052E4CBD0009891B /* world */, + 4CA1FEBD052A3C8100F22E42 /* libsecurity_agent_client */, + 4CA1FECF052A450F00F22E42 /* libsecurity_agent_server */, + 40E8FACC052E45D000A3D8D1 /* generate mig */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + 1865FFDE14751B6E00FD79DF /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "nmedit -p \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\"\nranlib \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\""; + }; + 1865FFDF14751B7600FD79DF /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "nmedit -p \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\"\nranlib \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\""; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 4CA1FEBA052A3C8100F22E42 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 40ACCCD805DC583700E9F642 /* sa_reply_server.cpp in Sources */, + 40ACCCD705DC580800E9F642 /* sa_request_user.cpp in Sources */, + 409513EC05E6A5780003976E /* agentclient.cpp in Sources */, + 72B3720D1104E343000D2A39 /* utils.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CA1FED1052A450F00F22E42 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 72B372321104EB8D000D2A39 /* utils.h in Sources */, + 40ACCCDA05DC587C00E9F642 /* sa_request_server.c in Sources */, + 40ACCCDB05DC587C00E9F642 /* sa_reply_user.c in Sources */, + 72B3720F1104E343000D2A39 /* utils.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 18B965C81473157C005A4D2E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 40E8FACC052E45D000A3D8D1 /* generate mig */; + targetProxy = 18B965C71473157C005A4D2E /* PBXContainerItemProxy */; + }; + 40635B6E052E4CCD0009891B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4CA1FEBD052A3C8100F22E42 /* libsecurity_agent_client */; + targetProxy = 4C25921C05448C1E007AEE03 /* PBXContainerItemProxy */; + }; + 40635B6F052E4CD00009891B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4CA1FECF052A450F00F22E42 /* libsecurity_agent_server */; + targetProxy = 4C25921905448C1E007AEE03 /* PBXContainerItemProxy */; + }; + 40C765C3053485EE008AC043 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 40E8FACC052E45D000A3D8D1 /* generate mig */; + targetProxy = 4C25921D05448C1E007AEE03 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + C27AD22A0987FCDC001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + C27AD22C0987FCDC001272E0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; + C27AD2360987FCDC001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1865FFA41474FB2100FD79DF /* debug.xcconfig */; + buildSettings = { + EXECUTABLE_PREFIX = ""; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(BUILT_PRODUCTS_DIR)/derived_src", + "$(SRCROOT)", + ); + PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/security_agent_server; + }; + name = Debug; + }; + C27AD2380987FCDC001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1865FFA61474FB2100FD79DF /* release.xcconfig */; + buildSettings = { + EXECUTABLE_PREFIX = ""; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(BUILT_PRODUCTS_DIR)/derived_src", + "$(SRCROOT)", + ); + PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/security_agent_server; + }; + name = Release; + }; + C27AD23A0987FCDC001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1865FFA41474FB2100FD79DF /* debug.xcconfig */; + buildSettings = { + EXECUTABLE_PREFIX = ""; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(BUILT_PRODUCTS_DIR)/derived_src", + "$(SRCROOT)", + ); + PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/security_agent_client; + }; + name = Debug; + }; + C27AD23C0987FCDC001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1865FFA61474FB2100FD79DF /* release.xcconfig */; + buildSettings = { + EXECUTABLE_PREFIX = ""; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(BUILT_PRODUCTS_DIR)/derived_src", + "$(SRCROOT)", + ); + PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/security_agent_client; + }; + name = Release; + }; + C27AD23E0987FCDC001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + C27AD2400987FCDC001272E0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; + C27AD2460987FCDC001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1865FFA51474FB2100FD79DF /* project.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD2480987FCDC001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1865FFA51474FB2100FD79DF /* project.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C27AD2290987FCDC001272E0 /* Build configuration list for PBXLegacyTarget "generate mig" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD22A0987FCDC001272E0 /* Debug */, + C27AD22C0987FCDC001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD2350987FCDC001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_agent_server" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD2360987FCDC001272E0 /* Debug */, + C27AD2380987FCDC001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD2390987FCDC001272E0 /* Build configuration list for PBXNativeTarget "libsecurity_agent_client" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD23A0987FCDC001272E0 /* Debug */, + C27AD23C0987FCDC001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD23D0987FCDC001272E0 /* Build configuration list for PBXAggregateTarget "world" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD23E0987FCDC001272E0 /* Debug */, + C27AD2400987FCDC001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD2450987FCDC001272E0 /* Build configuration list for PBXProject "libsecurity_agent" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD2460987FCDC001272E0 /* Debug */, + C27AD2480987FCDC001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; +} diff --git a/securityd/libsecurity_agent/mig/mig.mk b/securityd/libsecurity_agent/mig/mig.mk new file mode 100644 index 00000000..04fbe932 --- /dev/null +++ b/securityd/libsecurity_agent/mig/mig.mk @@ -0,0 +1,39 @@ +# +# Makefile to build MIG-generated sources and headers +# +DERIVED_SRC = $(BUILT_PRODUCTS_DIR)/derived_src/security_agent_client + +HDRS = $(DERIVED_SRC)/sa_reply.h \ + $(DERIVED_SRC)/sa_request.h + +SRCS = $(DERIVED_SRC)/sa_reply_server.cpp $(DERIVED_SRC)/sa_reply_user.c \ + $(DERIVED_SRC)/sa_request_server.c $(DERIVED_SRC)/sa_request_user.cpp +SDKROOT := $(shell xcrun --show-sdk-path --sdk macosx.internal) + +build: $(HDRS) $(SRCS) + +install: build + +installhdrs: $(HDRS) + +installsrc: + +clean: + rm -f $(HDRS) $(SRCS) + +$(DERIVED_SRC)/sa_request_server.c $(DERIVED_SRC)/sa_request_user.cpp $(DERIVED_SRC)/sa_request.h: $(PROJECT_DIR)/mig/sa_request.defs $(PROJECT_DIR)/lib/sa_types.h + mkdir -p $(DERIVED_SRC) + ln -sF $(DERIVED_SRC) $(BUILT_PRODUCTS_DIR)/derived_src/security_agent_server + xcrun mig -isysroot "$(SDKROOT)" \ + -server $(DERIVED_SRC)/sa_request_server.c \ + -user $(DERIVED_SRC)/sa_request_user.cpp \ + -header $(DERIVED_SRC)/sa_request.h $(PROJECT_DIR)/mig/sa_request.defs + +$(DERIVED_SRC)/sa_reply_server.cpp $(DERIVED_SRC)/sa_reply_user.c $(DERIVED_SRC)/sa_reply.h: $(PROJECT_DIR)/mig/sa_reply.defs $(PROJECT_DIR)/lib/sa_types.h + mkdir -p $(DERIVED_SRC) + xcrun mig -isysroot "$(SDKROOT)" \ + -server $(DERIVED_SRC)/sa_reply_server.cpp \ + -user $(DERIVED_SRC)/sa_reply_user.c \ + -header $(DERIVED_SRC)/sa_reply.h $(PROJECT_DIR)/mig/sa_reply.defs + + diff --git a/securityd/libsecurity_agent/mig/sa_reply.defs b/securityd/libsecurity_agent/mig/sa_reply.defs new file mode 100644 index 00000000..1c70c749 --- /dev/null +++ b/securityd/libsecurity_agent/mig/sa_reply.defs @@ -0,0 +1,54 @@ +// +// sa_reply.defs - SecurityAgent-side Mach RPC interface to Server. +// +#include +#include + +subsystem secagentreply 1200; +serverprefix sa_reply_server_; +userprefix sa_reply_client_; + +import ; + +// +// Data types +// +type OSStatus = int32; +type AuthorizationResult = int32; + +type Data = array [] of char; + +type AuthorizationItemSetBlob = Data + ctype: AuthorizationItemSetPtr; +type AuthorizationItemSetPtr = unsigned32; +type AuthorizationValueVectorBlob = Data + ctype: AuthorizationValueVectorPtr; +type AuthorizationValueVectorPtr = unsigned32; + + +#define BLOB(name,type) name: type##Blob; name##Base: type##Ptr + +// +// Staged SecurityAgent reply protocol +// +simpleroutine didCreate(requestport instanceReplyPort: mach_port_t; + instanceRequestPort: mach_port_make_send_t); // give client send rights to mechanism request port + +simpleroutine setResult(requestport instanceReplyPort: mach_port_t; + status: AuthorizationResult; + BLOB(hintsIn,AuthorizationItemSet); + BLOB(contextIn,AuthorizationItemSet)); + +simpleroutine requestInterrupt(requestport instanceReplyPort: mach_port_t); + +simpleroutine didDeactivate(requestport instanceReplyPort: mach_port_t); + +simpleroutine reportError(requestport instanceReplyPort: mach_port_t; + status: OSStatus); + +simpleroutine didStartTx(clientReplyPort: mach_port_move_send_once_t; + result: kern_return_t); + +// in case we decide to support true synchronous agent client IPCs, this +// keeps sa_reply routine #s at parity with sa_request routine #s +skip; // client: txEnd diff --git a/securityd/libsecurity_agent/mig/sa_request.defs b/securityd/libsecurity_agent/mig/sa_request.defs new file mode 100644 index 00000000..4411b1c3 --- /dev/null +++ b/securityd/libsecurity_agent/mig/sa_request.defs @@ -0,0 +1,70 @@ +// +// sa_request.defs - Client-side Mach RPC interface to SecurityAgent. +// +#include +#include + +subsystem secagentrequest 1100; +serverprefix sa_request_server_; +userprefix sa_request_client_; + +import ; + +// +// Data types +// +type Data = array [] of char; + +type AuthorizationString = c_string[*:1024]; +type AuthorizationItemSetBlob = Data + ctype: AuthorizationItemSetPtr; +type AuthorizationItemSetPtr = unsigned32; +type AuthorizationValueVectorBlob = Data + ctype: AuthorizationValueVectorPtr; +type AuthorizationValueVectorPtr = unsigned32; +type SessionId = unsigned32; +type Choice = struct[2] of unsigned32; + +#define BLOB(name,type) name: type##Blob; name##Base: type##Ptr + +// +// Staged SecurityAgent request protocol +// +simpleroutine create(requestport agentPort: mach_port_t; + instanceReplyPort: mach_port_make_send_t; // give agent send rights for replies + sessionId: SessionId; + pluginId: AuthorizationString; + mechanismId: AuthorizationString); + +simpleroutine invoke(requestport instanceRequestPort: mach_port_t; + BLOB(argumentsIn,AuthorizationValueVector); + BLOB(hintsIn,AuthorizationItemSet); + BLOB(contextIn,AuthorizationItemSet)); + +simpleroutine deactivate(requestport instanceRequestPort: mach_port_t); + +simpleroutine destroy(requestport instanceRequestPort: mach_port_t); + +// +// Tell the SecurityAgent to go away we no longer need you. +// +simpleroutine terminate(requestport agentPort: mach_port_t); + +// +// Support transaction semantics outside the usual client protocol +// (those semantics not defined here) +// +routine txStart(agentPort: mach_port_t; + sreplyport clientReplyPort: mach_port_make_send_once_t); + +simpleroutine txEnd(agentPort: mach_port_t); + +// +// client check-in +// +simpleroutine contact(requestport agentPort: mach_port_t; + clientPort: mach_port_make_send_t; + serveraudittoken sourceAudit: audit_token_t; + jobPort: mach_port_move_send_t; + processBootstrap: mach_port_t; + userPrefs: mach_port_t); diff --git a/securityd/libsecurity_agent/security_agent_client b/securityd/libsecurity_agent/security_agent_client new file mode 120000 index 00000000..945c9b46 --- /dev/null +++ b/securityd/libsecurity_agent/security_agent_client @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/securityd/mig/mig.mk b/securityd/mig/mig.mk new file mode 100644 index 00000000..4f4c7596 --- /dev/null +++ b/securityd/mig/mig.mk @@ -0,0 +1,47 @@ +# +# Copyright (c) 2003-2004,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@ +# +# Makefile to build MIG-generated sources and headers +# +DERIVED_SRC = $(BUILT_PRODUCTS_DIR)/derived_src + +HDRS = $(DERIVED_SRC)/self.h +SRCS = $(DERIVED_SRC)/selfServer.cpp $(DERIVED_SRC)/selfUser.cpp +SDKROOT := $(shell xcrun --show-sdk-path --sdk macosx.internal) + +build: $(HDRS) $(SRCS) + +install: build + +installhdrs: $(HDRS) + +installsrc: + +clean: + rm -f $(HDRS) $(SRCS) + +$(DERIVED_SRC)/self.h $(DERIVED_SRC)/selfServer.cpp $(DERIVED_SRC)/selfUser.cpp: $(SRCROOT)/mig/self.defs + mkdir -p $(DERIVED_SRC) + xcrun mig -isysroot "$(SDKROOT)" \ + -server $(DERIVED_SRC)/selfServer.cpp \ + -user $(DERIVED_SRC)/selfUser.cpp \ + -header $(DERIVED_SRC)/self.h $(SRCROOT)/mig/self.defs diff --git a/securityd/mig/self.defs b/securityd/mig/self.defs new file mode 100644 index 00000000..b2e8f87c --- /dev/null +++ b/securityd/mig/self.defs @@ -0,0 +1,43 @@ +// +// Copyright (c) 2004,2009 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@ +// +// self.defs - Mach RPC interface for messages security sends to itself +// +// Note: Main (ucsp) dispatch starts at 1000; make sure you don't overlap it. +// +#include +#include + +subsystem self 900; +serverprefix self_server_; +userprefix self_client_; + + +// +// Sent to ourselves upon receipt of a signal (so we get out from under +// the dreaded "can't do anything useful in a signal handler" problem). +// +simpleroutine handleSignal(requestport sport: mach_port_make_send_once_t; + in task_port: mach_port_t; in signal_number: int); + +simpleroutine handleSession(requestport sport: mach_port_make_send_once_t; + in task_port: mach_port_t; in events: uint32_t; in ident: uint64_t); diff --git a/securityd/security_agent_client b/securityd/security_agent_client new file mode 120000 index 00000000..e83fc10f --- /dev/null +++ b/securityd/security_agent_client @@ -0,0 +1 @@ +./lib \ No newline at end of file diff --git a/securityd/security_agent_server b/securityd/security_agent_server new file mode 120000 index 00000000..e83fc10f --- /dev/null +++ b/securityd/security_agent_server @@ -0,0 +1 @@ +./lib \ No newline at end of file diff --git a/securityd/securityd.xcodeproj/project.pbxproj b/securityd/securityd.xcodeproj/project.pbxproj new file mode 100644 index 00000000..c769af27 --- /dev/null +++ b/securityd/securityd.xcodeproj/project.pbxproj @@ -0,0 +1,1187 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXAggregateTarget section */ + AA6D4B7A0E6F3A910050206D /* mig */ = { + isa = PBXAggregateTarget; + buildConfigurationList = AA6D4B7F0E6F3AE50050206D /* Build configuration list for PBXAggregateTarget "mig" */; + buildPhases = ( + AA6D4B790E6F3A910050206D /* ShellScript */, + ); + dependencies = ( + ); + name = mig; + productName = mig_native; + }; + AA6D4B810E6F3B210050206D /* startup */ = { + isa = PBXAggregateTarget; + buildConfigurationList = AA6D4B860E6F3B8D0050206D /* Build configuration list for PBXAggregateTarget "startup" */; + buildPhases = ( + AA6D4B800E6F3B210050206D /* ShellScript */, + ); + dependencies = ( + ); + name = startup; + productName = startup_native; + }; + C26CF02C0CD934260094DD9D /* DTrace */ = { + isa = PBXAggregateTarget; + buildConfigurationList = C26CF03B0CD934420094DD9D /* Build configuration list for PBXAggregateTarget "DTrace" */; + buildPhases = ( + C26CF0360CD9343A0094DD9D /* ShellScript */, + ); + dependencies = ( + ); + name = DTrace; + productName = DTrace; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 1865FFB11474FED300FD79DF /* libsecurity_tokend_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1865FFB01474FED300FD79DF /* libsecurity_tokend_client.a */; }; + 1865FFB3147505C800FD79DF /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1865FFB2147505C800FD79DF /* libbsm.dylib */; }; + 1865FFCF1475169A00FD79DF /* libsecurityd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1865FFCE1475169A00FD79DF /* libsecurityd_client.a */; }; + 1865FFDC14751B0600FD79DF /* libobjc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 18B967B514731B78005A4D2E /* libobjc.dylib */; }; + 1865FFE114751C9100FD79DF /* libauto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 18B967B314731B69005A4D2E /* libauto.dylib */; }; + 1865FFEB1475208B00FD79DF /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 18B967B114731B55005A4D2E /* libsqlite3.dylib */; }; + 18B27134148C2C3D0087AE98 /* securityd_dtrace.h in Headers */ = {isa = PBXBuildFile; fileRef = 18B27133148C2C3D0087AE98 /* securityd_dtrace.h */; }; + 18B965CD14731612005A4D2E /* libsecurity_agent_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18B965BD147314BE005A4D2E /* libsecurity_agent_client.a */; }; + 18B965D314731963005A4D2E /* libsecurity_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18B965D214731963005A4D2E /* libsecurity_utilities.a */; }; + 18B965D51473197B005A4D2E /* libsecurity_cdsa_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18B965D41473197B005A4D2E /* libsecurity_cdsa_utilities.a */; }; + 18B965D614731996005A4D2E /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CDD506B0537666500FEC36D /* IOKit.framework */; }; + 18B965D71473199F005A4D2E /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CDD5018053765A900FEC36D /* CoreFoundation.framework */; }; + 18B965D8147319A6005A4D2E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CDD5019053765A900FEC36D /* Security.framework */; }; + 18B965DA147319C8005A4D2E /* libsecurity_cdsa_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18B965D9147319C8005A4D2E /* libsecurity_cdsa_client.a */; }; + 18B965DC147319E5005A4D2E /* libsecurityd_server.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18B965DB147319E5005A4D2E /* libsecurityd_server.a */; }; + 18B965DD147319F6005A4D2E /* PCSC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C276AAD60663E7A400B57276 /* PCSC.framework */; }; + 18CE013F17147A46008C042F /* libsecuritydservice_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18CE013E17147A46008C042F /* libsecuritydservice_client.a */; }; + 4E0BB2B40F79590300BBFEFA /* ccaudit_extensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E0BB2B20F79590300BBFEFA /* ccaudit_extensions.h */; }; + 4E0BB2B50F79590300BBFEFA /* ccaudit_extensions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4E0BB2B30F79590300BBFEFA /* ccaudit_extensions.cpp */; }; + 53002F001818A7C300900564 /* libsecurity_codesigning.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1865FFD0147516CF00FD79DF /* libsecurity_codesigning.a */; }; + AAC707230E6F4335003CC2B2 /* acl_keychain.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264990534866F004B0E72 /* acl_keychain.h */; }; + AAC707240E6F4335003CC2B2 /* acls.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C92649B0534866F004B0E72 /* acls.h */; }; + AAC707250E6F4335003CC2B2 /* agentquery.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C92649D0534866F004B0E72 /* agentquery.h */; }; + AAC707260E6F4335003CC2B2 /* authority.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C92649F0534866F004B0E72 /* authority.h */; }; + AAC707270E6F4335003CC2B2 /* AuthorizationDBPlist.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264A10534866F004B0E72 /* AuthorizationDBPlist.h */; }; + AAC707280E6F4335003CC2B2 /* AuthorizationEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264A30534866F004B0E72 /* AuthorizationEngine.h */; }; + AAC707290E6F4335003CC2B2 /* AuthorizationMechEval.h in Headers */ = {isa = PBXBuildFile; fileRef = 405845660663B2010083E58C /* AuthorizationMechEval.h */; }; + AAC7072A0E6F4335003CC2B2 /* AuthorizationRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264A50534866F004B0E72 /* AuthorizationRule.h */; }; + AAC7072B0E6F4335003CC2B2 /* child.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CB5ACBA06680AE000F359A9 /* child.h */; }; + AAC7072C0E6F4335003CC2B2 /* codesigdb.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264A90534866F004B0E72 /* codesigdb.h */; }; + AAC7072D0E6F4335003CC2B2 /* connection.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264AB0534866F004B0E72 /* connection.h */; }; + AAC7072E0E6F4335003CC2B2 /* database.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B8DBC805E6C3CE00E6E67C /* database.h */; }; + AAC7072F0E6F4335003CC2B2 /* dbcrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264AD0534866F004B0E72 /* dbcrypto.h */; }; + AAC707300E6F4335003CC2B2 /* entropy.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264AF0534866F004B0E72 /* entropy.h */; }; + AAC707310E6F4335003CC2B2 /* kcdatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B8DBCA05E6C3CE00E6E67C /* kcdatabase.h */; }; + AAC707320E6F4335003CC2B2 /* kckey.h in Headers */ = {isa = PBXBuildFile; fileRef = C207646405EAD713004FEEDA /* kckey.h */; }; + AAC707330E6F4335003CC2B2 /* key.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264B60534866F004B0E72 /* key.h */; }; + AAC707340E6F4335003CC2B2 /* localdatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = C20764E505ED250F004FEEDA /* localdatabase.h */; }; + AAC707350E6F4335003CC2B2 /* localkey.h in Headers */ = {isa = PBXBuildFile; fileRef = C20764E705ED250F004FEEDA /* localkey.h */; }; + AAC707360E6F4335003CC2B2 /* notifications.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264B90534866F004B0E72 /* notifications.h */; }; + AAC707370E6F4335003CC2B2 /* pcscmonitor.h in Headers */ = {isa = PBXBuildFile; fileRef = C2FDCABE0663CD5B0013F64C /* pcscmonitor.h */; }; + AAC707380E6F4335003CC2B2 /* process.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264BB0534866F004B0E72 /* process.h */; }; + AAC707390E6F4335003CC2B2 /* reader.h in Headers */ = {isa = PBXBuildFile; fileRef = C2FDCAC00663CD5B0013F64C /* reader.h */; }; + AAC7073A0E6F4335003CC2B2 /* server.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264BF0534866F004B0E72 /* server.h */; }; + AAC7073B0E6F4335003CC2B2 /* session.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C9264C10534866F004B0E72 /* session.h */; }; + AAC7073C0E6F4335003CC2B2 /* structure.h in Headers */ = {isa = PBXBuildFile; fileRef = C28ACF9B05C9940B00447176 /* structure.h */; }; + AAC7073D0E6F4335003CC2B2 /* tempdatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = C20AF37D05F689540055732C /* tempdatabase.h */; }; + AAC7073E0E6F4335003CC2B2 /* token.h in Headers */ = {isa = PBXBuildFile; fileRef = C2FDCAC20663CD5B0013F64C /* token.h */; }; + AAC7073F0E6F4335003CC2B2 /* tokendatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D425F205F3C07400CB11F8 /* tokendatabase.h */; }; + AAC707400E6F4335003CC2B2 /* tokencache.h in Headers */ = {isa = PBXBuildFile; fileRef = C26EA9520688CF34007CE21D /* tokencache.h */; }; + AAC707410E6F4335003CC2B2 /* self.h in Headers */ = {isa = PBXBuildFile; fileRef = C209B3B206ADBE64007B9E6D /* self.h */; }; + AAC707420E6F4335003CC2B2 /* tokend.h in Headers */ = {isa = PBXBuildFile; fileRef = C22A7F8D06AF06D9006087B7 /* tokend.h */; }; + AAC707430E6F4335003CC2B2 /* tokenkey.h in Headers */ = {isa = PBXBuildFile; fileRef = C26D533806C1E70A00062E1E /* tokenkey.h */; }; + AAC707440E6F4335003CC2B2 /* tokenacl.h in Headers */ = {isa = PBXBuildFile; fileRef = C28654B106DBC2A30021E6E5 /* tokenacl.h */; }; + AAC707450E6F4335003CC2B2 /* tokenaccess.h in Headers */ = {isa = PBXBuildFile; fileRef = C2813C800730534A00E243E8 /* tokenaccess.h */; }; + AAC707460E6F4335003CC2B2 /* authhost.h in Headers */ = {isa = PBXBuildFile; fileRef = 40689F840725DCE00021A502 /* authhost.h */; }; + AAC707470E6F4335003CC2B2 /* SharedMemoryServer.h in Headers */ = {isa = PBXBuildFile; fileRef = D6C887EE0A55B6220044DFD2 /* SharedMemoryServer.h */; }; + AAC707480E6F4335003CC2B2 /* csproxy.h in Headers */ = {isa = PBXBuildFile; fileRef = C2BD5FDB0AC47E850057FD3D /* csproxy.h */; }; + AAC707490E6F4335003CC2B2 /* credential.h in Headers */ = {isa = PBXBuildFile; fileRef = 407ACD060AE5B57700A9DA90 /* credential.h */; }; + AAC7074B0E6F4335003CC2B2 /* clientid.h in Headers */ = {isa = PBXBuildFile; fileRef = C22C34530B278EB60009368E /* clientid.h */; }; + AAC7074C0E6F4335003CC2B2 /* dtrace.h in Headers */ = {isa = PBXBuildFile; fileRef = C26CF0880CDFE1180094DD9D /* dtrace.h */; }; + AAC7074D0E6F4352003CC2B2 /* acl_keychain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264980534866F004B0E72 /* acl_keychain.cpp */; }; + AAC7074E0E6F4352003CC2B2 /* acls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C92649A0534866F004B0E72 /* acls.cpp */; }; + AAC7074F0E6F4352003CC2B2 /* agentquery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C92649C0534866F004B0E72 /* agentquery.cpp */; }; + AAC707500E6F4352003CC2B2 /* authority.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C92649E0534866F004B0E72 /* authority.cpp */; }; + AAC707510E6F4352003CC2B2 /* AuthorizationDBPlist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264A00534866F004B0E72 /* AuthorizationDBPlist.cpp */; }; + AAC707520E6F4352003CC2B2 /* AuthorizationEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264A20534866F004B0E72 /* AuthorizationEngine.cpp */; }; + AAC707530E6F4352003CC2B2 /* AuthorizationMechEval.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 405845650663B2010083E58C /* AuthorizationMechEval.cpp */; }; + AAC707540E6F4352003CC2B2 /* AuthorizationRule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264A40534866F004B0E72 /* AuthorizationRule.cpp */; }; + AAC707550E6F4352003CC2B2 /* child.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CB5ACB906680AE000F359A9 /* child.cpp */; }; + AAC707560E6F4352003CC2B2 /* codesigdb.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264A80534866F004B0E72 /* codesigdb.cpp */; }; + AAC707570E6F4352003CC2B2 /* connection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264AA0534866F004B0E72 /* connection.cpp */; }; + AAC707580E6F4352003CC2B2 /* database.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2B8DBC705E6C3CE00E6E67C /* database.cpp */; }; + AAC707590E6F4352003CC2B2 /* dbcrypto.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264AC0534866F004B0E72 /* dbcrypto.cpp */; }; + AAC7075A0E6F4352003CC2B2 /* entropy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264AE0534866F004B0E72 /* entropy.cpp */; }; + AAC7075B0E6F4352003CC2B2 /* kcdatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2B8DBC905E6C3CE00E6E67C /* kcdatabase.cpp */; }; + AAC7075C0E6F4352003CC2B2 /* kckey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C207646305EAD713004FEEDA /* kckey.cpp */; }; + AAC7075D0E6F4352003CC2B2 /* key.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264B50534866F004B0E72 /* key.cpp */; }; + AAC7075E0E6F4352003CC2B2 /* localdatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C20764E405ED250F004FEEDA /* localdatabase.cpp */; }; + AAC7075F0E6F4352003CC2B2 /* localkey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C20764E605ED250F004FEEDA /* localkey.cpp */; }; + AAC707600E6F4352003CC2B2 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264B70534866F004B0E72 /* main.cpp */; }; + AAC707610E6F4352003CC2B2 /* notifications.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264B80534866F004B0E72 /* notifications.cpp */; }; + AAC707620E6F4352003CC2B2 /* pcscmonitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2FDCABD0663CD5B0013F64C /* pcscmonitor.cpp */; }; + AAC707630E6F4352003CC2B2 /* process.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264BA0534866F004B0E72 /* process.cpp */; }; + AAC707640E6F4352003CC2B2 /* reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2FDCABF0663CD5B0013F64C /* reader.cpp */; }; + AAC707650E6F4352003CC2B2 /* server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264BE0534866F004B0E72 /* server.cpp */; }; + AAC707660E6F4352003CC2B2 /* session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264C00534866F004B0E72 /* session.cpp */; }; + AAC707670E6F4352003CC2B2 /* structure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C28ACF9A05C9940B00447176 /* structure.cpp */; }; + AAC707680E6F4352003CC2B2 /* tempdatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C20AF37C05F689540055732C /* tempdatabase.cpp */; }; + AAC707690E6F4352003CC2B2 /* token.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2FDCAC10663CD5B0013F64C /* token.cpp */; }; + AAC7076A0E6F4352003CC2B2 /* tokendatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D425F105F3C07400CB11F8 /* tokendatabase.cpp */; }; + AAC7076B0E6F4352003CC2B2 /* transition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9264C20534866F004B0E72 /* transition.cpp */; }; + AAC7076C0E6F4352003CC2B2 /* tokencache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C26EA9510688CF34007CE21D /* tokencache.cpp */; }; + AAC7076D0E6F4352003CC2B2 /* selfServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C209B3B306ADBE64007B9E6D /* selfServer.cpp */; }; + AAC7076E0E6F4352003CC2B2 /* selfUser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C209B3B406ADBE64007B9E6D /* selfUser.cpp */; }; + AAC7076F0E6F4352003CC2B2 /* tokend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C22A7F8C06AF06D9006087B7 /* tokend.cpp */; }; + AAC707700E6F4352003CC2B2 /* tokenkey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C26D533706C1E70A00062E1E /* tokenkey.cpp */; }; + AAC707710E6F4352003CC2B2 /* tokenacl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C28654B006DBC2A30021E6E5 /* tokenacl.cpp */; }; + AAC707720E6F4352003CC2B2 /* tokenaccess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2813C7F0730534A00E243E8 /* tokenaccess.cpp */; }; + AAC707730E6F4352003CC2B2 /* authhost.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 40689F850725DCE00021A502 /* authhost.cpp */; }; + AAC707740E6F4352003CC2B2 /* SharedMemoryServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D6C887ED0A55B6220044DFD2 /* SharedMemoryServer.cpp */; }; + AAC707750E6F4352003CC2B2 /* csproxy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2BD5FDA0AC47E850057FD3D /* csproxy.cpp */; }; + AAC707760E6F4352003CC2B2 /* credential.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 407ACD070AE5B57700A9DA90 /* credential.cpp */; }; + AAC707780E6F4352003CC2B2 /* clientid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C22C34520B278EB60009368E /* clientid.cpp */; }; + C274C51E0F9E8E0F001ABDA3 /* auditevents.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C274C51C0F9E8E0F001ABDA3 /* auditevents.cpp */; }; + C274C51F0F9E8E0F001ABDA3 /* auditevents.h in Headers */ = {isa = PBXBuildFile; fileRef = C274C51D0F9E8E0F001ABDA3 /* auditevents.h */; }; + ED5130690E7F1259002A3749 /* securityd.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CE1878706FFC5D60079D235 /* securityd.1 */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 1820DFC71714D3F800CA851F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 80C7A77A167FF4FF001533BE /* securityd_service.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 1843240D1714797D00196B52; + remoteInfo = securitydservice_client; + }; + 18B965BC147314BE005A4D2E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18B965B0147314BE005A4D2E /* libsecurity_agent.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; + remoteInfo = libsecurity_agent_client; + }; + 18B965C0147314BE005A4D2E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18B965B0147314BE005A4D2E /* libsecurity_agent.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CA1FED4052A450F00F22E42; + remoteInfo = libsecurity_agent_server; + }; + 18B967B814731BB1005A4D2E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18B965B0147314BE005A4D2E /* libsecurity_agent.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 40635B69052E4CBD0009891B; + remoteInfo = world; + }; + 18CE013D17147A46008C042F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 80C7A77A167FF4FF001533BE /* securityd_service.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 1843240E1714797D00196B52; + remoteInfo = securitydservice_client; + }; + 53002F061818A7C400900564 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 80C7A77A167FF4FF001533BE /* securityd_service.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 18F4808E17497521009724DB; + remoteInfo = KeyStoreEvents; + }; + 80C7A78C167FF586001533BE /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 80C7A77A167FF4FF001533BE /* securityd_service.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 189D4635166AC95C001D8533; + remoteInfo = securityd_service; + }; + 80C7A78E167FF586001533BE /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 80C7A77A167FF4FF001533BE /* securityd_service.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 189D465B166C15C1001D8533; + remoteInfo = securitydservicectrl; + }; + 80C7A790167FF9D3001533BE /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 80C7A77A167FF4FF001533BE /* securityd_service.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 189D4634166AC95C001D8533; + remoteInfo = securityd_service; + }; + AA1A9FF80E71EF08003D0309 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEB0052A3C5800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C26CF02C0CD934260094DD9D; + remoteInfo = DTrace; + }; + AA1AA00E0E71F2ED003D0309 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEB0052A3C5800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = AA6D4B810E6F3B210050206D; + remoteInfo = startup; + }; + AA1AA0100E71F2F7003D0309 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4CA1FEB0052A3C5800F22E42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = AA6D4B7A0E6F3A910050206D; + remoteInfo = mig; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + ED51306A0E7F1277002A3749 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + ED5130690E7F1259002A3749 /* securityd.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1865FFA01474FB1100FD79DF /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; + 1865FFA11474FB1100FD79DF /* project.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = project.xcconfig; sourceTree = ""; }; + 1865FFA21474FB1100FD79DF /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; + 1865FFB01474FED300FD79DF /* libsecurity_tokend_client.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_tokend_client.a; path = /usr/local/lib/libsecurity_tokend_client.a; sourceTree = ""; }; + 1865FFB2147505C800FD79DF /* libbsm.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbsm.dylib; path = /usr/lib/libbsm.dylib; sourceTree = ""; }; + 1865FFCE1475169A00FD79DF /* libsecurityd_client.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurityd_client.a; path = /usr/local/lib/libsecurityd_client.a; sourceTree = ""; }; + 1865FFD0147516CF00FD79DF /* libsecurity_codesigning.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_codesigning.a; path = /usr/local/lib/libsecurity_codesigning.a; sourceTree = ""; }; + 18B27133148C2C3D0087AE98 /* securityd_dtrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = securityd_dtrace.h; path = derived_src/securityd_dtrace.h; sourceTree = BUILT_PRODUCTS_DIR; }; + 18B965B0147314BE005A4D2E /* libsecurity_agent.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_agent.xcodeproj; path = libsecurity_agent/libsecurity_agent.xcodeproj; sourceTree = ""; }; + 18B965D214731963005A4D2E /* libsecurity_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_utilities.a; path = /usr/local/lib/libsecurity_utilities.a; sourceTree = ""; }; + 18B965D41473197B005A4D2E /* libsecurity_cdsa_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_cdsa_utilities.a; path = /usr/local/lib/libsecurity_cdsa_utilities.a; sourceTree = ""; }; + 18B965D9147319C8005A4D2E /* libsecurity_cdsa_client.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_cdsa_client.a; path = /usr/local/lib/libsecurity_cdsa_client.a; sourceTree = ""; }; + 18B965DB147319E5005A4D2E /* libsecurityd_server.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurityd_server.a; path = /usr/local/lib/libsecurityd_server.a; sourceTree = ""; }; + 18B967B114731B55005A4D2E /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = /usr/lib/libsqlite3.dylib; sourceTree = ""; }; + 18B967B314731B69005A4D2E /* libauto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libauto.dylib; path = /usr/lib/libauto.dylib; sourceTree = ""; }; + 18B967B514731B78005A4D2E /* libobjc.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libobjc.dylib; path = /usr/lib/libobjc.dylib; sourceTree = ""; }; + 405845650663B2010083E58C /* AuthorizationMechEval.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AuthorizationMechEval.cpp; sourceTree = ""; }; + 405845660663B2010083E58C /* AuthorizationMechEval.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AuthorizationMechEval.h; sourceTree = ""; }; + 40689F840725DCE00021A502 /* authhost.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = authhost.h; sourceTree = ""; }; + 40689F850725DCE00021A502 /* authhost.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = authhost.cpp; sourceTree = ""; }; + 407ACD060AE5B57700A9DA90 /* credential.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = credential.h; sourceTree = ""; }; + 407ACD070AE5B57700A9DA90 /* credential.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = credential.cpp; sourceTree = ""; }; + 4C9264980534866F004B0E72 /* acl_keychain.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = acl_keychain.cpp; sourceTree = ""; }; + 4C9264990534866F004B0E72 /* acl_keychain.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = acl_keychain.h; sourceTree = ""; }; + 4C92649A0534866F004B0E72 /* acls.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = acls.cpp; sourceTree = ""; }; + 4C92649B0534866F004B0E72 /* acls.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = acls.h; sourceTree = ""; }; + 4C92649C0534866F004B0E72 /* agentquery.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = agentquery.cpp; sourceTree = ""; }; + 4C92649D0534866F004B0E72 /* agentquery.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = agentquery.h; sourceTree = ""; }; + 4C92649E0534866F004B0E72 /* authority.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = authority.cpp; sourceTree = ""; }; + 4C92649F0534866F004B0E72 /* authority.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = authority.h; sourceTree = ""; }; + 4C9264A00534866F004B0E72 /* AuthorizationDBPlist.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AuthorizationDBPlist.cpp; sourceTree = ""; }; + 4C9264A10534866F004B0E72 /* AuthorizationDBPlist.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AuthorizationDBPlist.h; sourceTree = ""; }; + 4C9264A20534866F004B0E72 /* AuthorizationEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AuthorizationEngine.cpp; sourceTree = ""; }; + 4C9264A30534866F004B0E72 /* AuthorizationEngine.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AuthorizationEngine.h; sourceTree = ""; }; + 4C9264A40534866F004B0E72 /* AuthorizationRule.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AuthorizationRule.cpp; sourceTree = ""; }; + 4C9264A50534866F004B0E72 /* AuthorizationRule.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AuthorizationRule.h; sourceTree = ""; }; + 4C9264A80534866F004B0E72 /* codesigdb.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = codesigdb.cpp; sourceTree = ""; }; + 4C9264A90534866F004B0E72 /* codesigdb.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = codesigdb.h; sourceTree = ""; }; + 4C9264AA0534866F004B0E72 /* connection.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = connection.cpp; sourceTree = ""; }; + 4C9264AB0534866F004B0E72 /* connection.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = connection.h; sourceTree = ""; }; + 4C9264AC0534866F004B0E72 /* dbcrypto.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = dbcrypto.cpp; sourceTree = ""; }; + 4C9264AD0534866F004B0E72 /* dbcrypto.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = dbcrypto.h; sourceTree = ""; }; + 4C9264AE0534866F004B0E72 /* entropy.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = entropy.cpp; sourceTree = ""; }; + 4C9264AF0534866F004B0E72 /* entropy.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = entropy.h; sourceTree = ""; }; + 4C9264B50534866F004B0E72 /* key.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = key.cpp; sourceTree = ""; }; + 4C9264B60534866F004B0E72 /* key.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = key.h; sourceTree = ""; }; + 4C9264B70534866F004B0E72 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 4C9264B80534866F004B0E72 /* notifications.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = notifications.cpp; sourceTree = ""; }; + 4C9264B90534866F004B0E72 /* notifications.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = notifications.h; sourceTree = ""; }; + 4C9264BA0534866F004B0E72 /* process.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = process.cpp; sourceTree = ""; }; + 4C9264BB0534866F004B0E72 /* process.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = process.h; sourceTree = ""; }; + 4C9264BC0534866F004B0E72 /* securityd.order */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = securityd.order; sourceTree = ""; }; + 4C9264BE0534866F004B0E72 /* server.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = server.cpp; sourceTree = ""; }; + 4C9264BF0534866F004B0E72 /* server.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = server.h; sourceTree = ""; }; + 4C9264C00534866F004B0E72 /* session.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = session.cpp; sourceTree = ""; }; + 4C9264C10534866F004B0E72 /* session.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = session.h; sourceTree = ""; }; + 4C9264C20534866F004B0E72 /* transition.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = transition.cpp; sourceTree = ""; }; + 4CB5ACB906680AE000F359A9 /* child.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = child.cpp; sourceTree = ""; }; + 4CB5ACBA06680AE000F359A9 /* child.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = child.h; sourceTree = ""; }; + 4CD8CCBD055884E0006B3584 /* CodeEquivalenceCandidates */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = CodeEquivalenceCandidates; sourceTree = ""; }; + 4CD8CCC0055884E0006B3584 /* startup.mk */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = startup.mk; sourceTree = ""; }; + 4CDD5018053765A900FEC36D /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; + 4CDD5019053765A900FEC36D /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = ""; }; + 4CDD506B0537666500FEC36D /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = ""; }; + 4CE1878606FFC5D60079D235 /* BLOBFORMAT */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = BLOBFORMAT; sourceTree = ""; }; + 4CE1878706FFC5D60079D235 /* securityd.1 */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.man; path = securityd.1; sourceTree = ""; }; + 4E0BB2B20F79590300BBFEFA /* ccaudit_extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ccaudit_extensions.h; sourceTree = ""; }; + 4E0BB2B30F79590300BBFEFA /* ccaudit_extensions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ccaudit_extensions.cpp; sourceTree = ""; }; + 80C7A77A167FF4FF001533BE /* securityd_service.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = securityd_service.xcodeproj; path = securityd_service/securityd_service.xcodeproj; sourceTree = ""; }; + AA6D4B8A0E6F3BB80050206D /* securityd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = securityd; sourceTree = BUILT_PRODUCTS_DIR; }; + AAA020B10E367BB000A6F842 /* dtrace.mk */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dtrace.mk; path = dtrace/dtrace.mk; sourceTree = ""; }; + C207646305EAD713004FEEDA /* kckey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = kckey.cpp; sourceTree = ""; }; + C207646405EAD713004FEEDA /* kckey.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = kckey.h; sourceTree = ""; }; + C20764E405ED250F004FEEDA /* localdatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = localdatabase.cpp; sourceTree = ""; }; + C20764E505ED250F004FEEDA /* localdatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = localdatabase.h; sourceTree = ""; }; + C20764E605ED250F004FEEDA /* localkey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = localkey.cpp; sourceTree = ""; }; + C20764E705ED250F004FEEDA /* localkey.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = localkey.h; sourceTree = ""; }; + C209B3AD06ADBDB4007B9E6D /* mig.mk */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = mig.mk; sourceTree = ""; }; + C209B3AE06ADBDB4007B9E6D /* self.defs */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.mig; path = self.defs; sourceTree = ""; }; + C209B3B206ADBE64007B9E6D /* self.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = self.h; path = derived_src/self.h; sourceTree = BUILT_PRODUCTS_DIR; }; + C209B3B306ADBE64007B9E6D /* selfServer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = selfServer.cpp; path = derived_src/selfServer.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; + C209B3B406ADBE64007B9E6D /* selfUser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = selfUser.cpp; path = derived_src/selfUser.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; + C20AF37C05F689540055732C /* tempdatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tempdatabase.cpp; sourceTree = ""; }; + C20AF37D05F689540055732C /* tempdatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tempdatabase.h; sourceTree = ""; }; + C22A7F8C06AF06D9006087B7 /* tokend.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tokend.cpp; sourceTree = ""; }; + C22A7F8D06AF06D9006087B7 /* tokend.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tokend.h; sourceTree = ""; }; + C22C34520B278EB60009368E /* clientid.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = clientid.cpp; sourceTree = ""; }; + C22C34530B278EB60009368E /* clientid.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = clientid.h; sourceTree = ""; }; + C26CF0230CD933AE0094DD9D /* securityd.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; name = securityd.d; path = src/securityd.d; sourceTree = ""; }; + C26CF0880CDFE1180094DD9D /* dtrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dtrace.h; path = src/dtrace.h; sourceTree = ""; }; + C26D533706C1E70A00062E1E /* tokenkey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tokenkey.cpp; sourceTree = ""; }; + C26D533806C1E70A00062E1E /* tokenkey.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tokenkey.h; sourceTree = ""; }; + C26EA9510688CF34007CE21D /* tokencache.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tokencache.cpp; sourceTree = ""; }; + C26EA9520688CF34007CE21D /* tokencache.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tokencache.h; sourceTree = ""; }; + C26FB2650BC2C3A300D8EFC8 /* com.apple.securityd.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; path = com.apple.securityd.plist; sourceTree = ""; }; + C274C51C0F9E8E0F001ABDA3 /* auditevents.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = auditevents.cpp; sourceTree = ""; }; + C274C51D0F9E8E0F001ABDA3 /* auditevents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = auditevents.h; sourceTree = ""; }; + C276AAD60663E7A400B57276 /* PCSC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PCSC.framework; path = /System/Library/Frameworks/PCSC.framework; sourceTree = ""; }; + C2813C7F0730534A00E243E8 /* tokenaccess.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tokenaccess.cpp; sourceTree = ""; }; + C2813C800730534A00E243E8 /* tokenaccess.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tokenaccess.h; sourceTree = ""; }; + C28654B006DBC2A30021E6E5 /* tokenacl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tokenacl.cpp; sourceTree = ""; }; + C28654B106DBC2A30021E6E5 /* tokenacl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tokenacl.h; sourceTree = ""; }; + C28ACF9A05C9940B00447176 /* structure.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = structure.cpp; sourceTree = ""; }; + C28ACF9B05C9940B00447176 /* structure.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = structure.h; sourceTree = ""; }; + C2B8DBC705E6C3CE00E6E67C /* database.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = database.cpp; sourceTree = ""; }; + C2B8DBC805E6C3CE00E6E67C /* database.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = database.h; sourceTree = ""; }; + C2B8DBC905E6C3CE00E6E67C /* kcdatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = kcdatabase.cpp; sourceTree = ""; }; + C2B8DBCA05E6C3CE00E6E67C /* kcdatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = kcdatabase.h; sourceTree = ""; }; + C2BD5FDA0AC47E850057FD3D /* csproxy.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = csproxy.cpp; sourceTree = ""; }; + C2BD5FDB0AC47E850057FD3D /* csproxy.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = csproxy.h; sourceTree = ""; }; + C2CB75A90CE26A3600727A2B /* securityd-watch.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; name = "securityd-watch.d"; path = "dtrace/securityd-watch.d"; sourceTree = ""; }; + C2D425F105F3C07400CB11F8 /* tokendatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tokendatabase.cpp; sourceTree = ""; }; + C2D425F205F3C07400CB11F8 /* tokendatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tokendatabase.h; sourceTree = ""; }; + C2FDCABD0663CD5B0013F64C /* pcscmonitor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = pcscmonitor.cpp; sourceTree = ""; }; + C2FDCABE0663CD5B0013F64C /* pcscmonitor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = pcscmonitor.h; sourceTree = ""; }; + C2FDCABF0663CD5B0013F64C /* reader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = reader.cpp; sourceTree = ""; }; + C2FDCAC00663CD5B0013F64C /* reader.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = reader.h; sourceTree = ""; }; + C2FDCAC10663CD5B0013F64C /* token.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = token.cpp; sourceTree = ""; }; + C2FDCAC20663CD5B0013F64C /* token.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = token.h; sourceTree = ""; }; + D6C887ED0A55B6220044DFD2 /* SharedMemoryServer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SharedMemoryServer.cpp; sourceTree = ""; }; + D6C887EE0A55B6220044DFD2 /* SharedMemoryServer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SharedMemoryServer.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + AA6D4B880E6F3BB80050206D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 53002F001818A7C300900564 /* libsecurity_codesigning.a in Frameworks */, + 18CE013F17147A46008C042F /* libsecuritydservice_client.a in Frameworks */, + 1865FFEB1475208B00FD79DF /* libsqlite3.dylib in Frameworks */, + 1865FFE114751C9100FD79DF /* libauto.dylib in Frameworks */, + 1865FFDC14751B0600FD79DF /* libobjc.dylib in Frameworks */, + 18B965CD14731612005A4D2E /* libsecurity_agent_client.a in Frameworks */, + 1865FFCF1475169A00FD79DF /* libsecurityd_client.a in Frameworks */, + 18B965DC147319E5005A4D2E /* libsecurityd_server.a in Frameworks */, + 1865FFB11474FED300FD79DF /* libsecurity_tokend_client.a in Frameworks */, + 18B965D51473197B005A4D2E /* libsecurity_cdsa_utilities.a in Frameworks */, + 18B965DA147319C8005A4D2E /* libsecurity_cdsa_client.a in Frameworks */, + 18B965D314731963005A4D2E /* libsecurity_utilities.a in Frameworks */, + 1865FFB3147505C800FD79DF /* libbsm.dylib in Frameworks */, + 18B965DD147319F6005A4D2E /* PCSC.framework in Frameworks */, + 18B965D8147319A6005A4D2E /* Security.framework in Frameworks */, + 18B965D71473199F005A4D2E /* CoreFoundation.framework in Frameworks */, + 18B965D614731996005A4D2E /* IOKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1865FF9F1474FB1100FD79DF /* config */ = { + isa = PBXGroup; + children = ( + 1865FFA01474FB1100FD79DF /* debug.xcconfig */, + 1865FFA11474FB1100FD79DF /* project.xcconfig */, + 1865FFA21474FB1100FD79DF /* release.xcconfig */, + ); + path = config; + sourceTree = ""; + }; + 18B965B1147314BE005A4D2E /* Products */ = { + isa = PBXGroup; + children = ( + 18B965BD147314BE005A4D2E /* libsecurity_agent_client.a */, + 18B965C1147314BE005A4D2E /* libsecurity_agent_server.a */, + ); + name = Products; + sourceTree = ""; + }; + 4C9264970534866F004B0E72 /* src */ = { + isa = PBXGroup; + children = ( + 4C9264B70534866F004B0E72 /* main.cpp */, + C28AE81406CD7DA100BE0061 /* Core Structure */, + C2C8B29806F8A60F000EBDA2 /* Crypto */, + C28AE81706CD7DC500BE0061 /* Database Types */, + C28AE81A06CD7DE200BE0061 /* Smartcards */, + C28AE82306CD7E0F00BE0061 /* Transit */, + C28AE82606CD7E4700BE0061 /* ACLs */, + C28AE81106CD7D7800BE0061 /* Authorization */, + C22C34510B278E950009368E /* Client Identification */, + C26AC79D0DAED222005BFB40 /* Code Signing */, + C28AE83906CD7EE900BE0061 /* Support */, + ); + path = src; + sourceTree = ""; + }; + 4CA1FEAC052A3C5800F22E42 = { + isa = PBXGroup; + children = ( + 80C7A77A167FF4FF001533BE /* securityd_service.xcodeproj */, + 18B965B0147314BE005A4D2E /* libsecurity_agent.xcodeproj */, + 1865FF9F1474FB1100FD79DF /* config */, + 4C9264970534866F004B0E72 /* src */, + C209B39106ADBB19007B9E6D /* mig */, + C26CF0290CD933D60094DD9D /* DTrace */, + 4CE1878506FFC5D60079D235 /* doc */, + C209B39406ADBB2B007B9E6D /* derived_src */, + C28AE82006CD7DF500BE0061 /* Build Stuff */, + 4CDD50150537658500FEC36D /* Linked Frameworks */, + 4CA1FEB7052A3C6D00F22E42 /* Products */, + 4CD8CCBB055884E0006B3584 /* Other Installs */, + ); + sourceTree = ""; + }; + 4CA1FEB7052A3C6D00F22E42 /* Products */ = { + isa = PBXGroup; + children = ( + AA6D4B8A0E6F3BB80050206D /* securityd */, + ); + name = Products; + sourceTree = ""; + }; + 4CD8CCBB055884E0006B3584 /* Other Installs */ = { + isa = PBXGroup; + children = ( + C26FB2650BC2C3A300D8EFC8 /* com.apple.securityd.plist */, + 4CD8CCBD055884E0006B3584 /* CodeEquivalenceCandidates */, + 4CD8CCC0055884E0006B3584 /* startup.mk */, + ); + name = "Other Installs"; + path = etc; + sourceTree = ""; + }; + 4CDD50150537658500FEC36D /* Linked Frameworks */ = { + isa = PBXGroup; + children = ( + 1865FFD0147516CF00FD79DF /* libsecurity_codesigning.a */, + 1865FFCE1475169A00FD79DF /* libsecurityd_client.a */, + 1865FFB2147505C800FD79DF /* libbsm.dylib */, + 1865FFB01474FED300FD79DF /* libsecurity_tokend_client.a */, + 18B967B514731B78005A4D2E /* libobjc.dylib */, + 18B967B314731B69005A4D2E /* libauto.dylib */, + 18B967B114731B55005A4D2E /* libsqlite3.dylib */, + 18B965DB147319E5005A4D2E /* libsecurityd_server.a */, + 18B965D9147319C8005A4D2E /* libsecurity_cdsa_client.a */, + 18B965D41473197B005A4D2E /* libsecurity_cdsa_utilities.a */, + 18B965D214731963005A4D2E /* libsecurity_utilities.a */, + 4CDD5018053765A900FEC36D /* CoreFoundation.framework */, + 4CDD506B0537666500FEC36D /* IOKit.framework */, + C276AAD60663E7A400B57276 /* PCSC.framework */, + 4CDD5019053765A900FEC36D /* Security.framework */, + ); + name = "Linked Frameworks"; + path = src; + sourceTree = ""; + }; + 4CE1878506FFC5D60079D235 /* doc */ = { + isa = PBXGroup; + children = ( + 4CE1878606FFC5D60079D235 /* BLOBFORMAT */, + 4CE1878706FFC5D60079D235 /* securityd.1 */, + ); + path = doc; + sourceTree = ""; + }; + 80C7A788167FF586001533BE /* Products */ = { + isa = PBXGroup; + children = ( + 80C7A78D167FF586001533BE /* securityd_service */, + 80C7A78F167FF586001533BE /* securitydservicectrl */, + 18CE013E17147A46008C042F /* libsecuritydservice_client.a */, + 53002F071818A7C400900564 /* com.apple.KeyStore.plugin */, + ); + name = Products; + sourceTree = ""; + }; + C209B39106ADBB19007B9E6D /* mig */ = { + isa = PBXGroup; + children = ( + C209B3AD06ADBDB4007B9E6D /* mig.mk */, + C209B3AE06ADBDB4007B9E6D /* self.defs */, + ); + path = mig; + sourceTree = ""; + }; + C209B39406ADBB2B007B9E6D /* derived_src */ = { + isa = PBXGroup; + children = ( + C209B3B206ADBE64007B9E6D /* self.h */, + C209B3B306ADBE64007B9E6D /* selfServer.cpp */, + C209B3B406ADBE64007B9E6D /* selfUser.cpp */, + ); + path = derived_src; + sourceTree = BUILT_PRODUCTS_DIR; + }; + C22C34510B278E950009368E /* Client Identification */ = { + isa = PBXGroup; + children = ( + C22C34530B278EB60009368E /* clientid.h */, + C22C34520B278EB60009368E /* clientid.cpp */, + 4C9264A90534866F004B0E72 /* codesigdb.h */, + 4C9264A80534866F004B0E72 /* codesigdb.cpp */, + ); + name = "Client Identification"; + sourceTree = ""; + }; + C26AC79D0DAED222005BFB40 /* Code Signing */ = { + isa = PBXGroup; + children = ( + C2BD5FDB0AC47E850057FD3D /* csproxy.h */, + C2BD5FDA0AC47E850057FD3D /* csproxy.cpp */, + ); + name = "Code Signing"; + sourceTree = ""; + }; + C26CF0290CD933D60094DD9D /* DTrace */ = { + isa = PBXGroup; + children = ( + 18B27133148C2C3D0087AE98 /* securityd_dtrace.h */, + C26CF0230CD933AE0094DD9D /* securityd.d */, + C26CF0880CDFE1180094DD9D /* dtrace.h */, + C2CB75A90CE26A3600727A2B /* securityd-watch.d */, + AAA020B10E367BB000A6F842 /* dtrace.mk */, + ); + name = DTrace; + sourceTree = ""; + }; + C28AE7FE06CD7CFF00BE0061 /* Token */ = { + isa = PBXGroup; + children = ( + C2D425F205F3C07400CB11F8 /* tokendatabase.h */, + C2D425F105F3C07400CB11F8 /* tokendatabase.cpp */, + C26D533806C1E70A00062E1E /* tokenkey.h */, + C26D533706C1E70A00062E1E /* tokenkey.cpp */, + C2813C800730534A00E243E8 /* tokenaccess.h */, + C2813C7F0730534A00E243E8 /* tokenaccess.cpp */, + ); + name = Token; + sourceTree = ""; + }; + C28AE80106CD7D0E00BE0061 /* Temporary */ = { + isa = PBXGroup; + children = ( + C20AF37D05F689540055732C /* tempdatabase.h */, + C20AF37C05F689540055732C /* tempdatabase.cpp */, + ); + name = Temporary; + sourceTree = ""; + }; + C28AE80406CD7D1D00BE0061 /* Local */ = { + isa = PBXGroup; + children = ( + C20764E505ED250F004FEEDA /* localdatabase.h */, + C20764E405ED250F004FEEDA /* localdatabase.cpp */, + C20764E705ED250F004FEEDA /* localkey.h */, + C20764E605ED250F004FEEDA /* localkey.cpp */, + ); + name = Local; + sourceTree = ""; + }; + C28AE80706CD7D2700BE0061 /* Keychain */ = { + isa = PBXGroup; + children = ( + C2B8DBCA05E6C3CE00E6E67C /* kcdatabase.h */, + C2B8DBC905E6C3CE00E6E67C /* kcdatabase.cpp */, + C207646405EAD713004FEEDA /* kckey.h */, + C207646305EAD713004FEEDA /* kckey.cpp */, + ); + name = Keychain; + sourceTree = ""; + }; + C28AE81106CD7D7800BE0061 /* Authorization */ = { + isa = PBXGroup; + children = ( + 40689F840725DCE00021A502 /* authhost.h */, + 40689F850725DCE00021A502 /* authhost.cpp */, + 4C92649F0534866F004B0E72 /* authority.h */, + 4C92649E0534866F004B0E72 /* authority.cpp */, + 407ACD060AE5B57700A9DA90 /* credential.h */, + 407ACD070AE5B57700A9DA90 /* credential.cpp */, + 4C9264A10534866F004B0E72 /* AuthorizationDBPlist.h */, + 4C9264A00534866F004B0E72 /* AuthorizationDBPlist.cpp */, + 4C9264A30534866F004B0E72 /* AuthorizationEngine.h */, + 4C9264A20534866F004B0E72 /* AuthorizationEngine.cpp */, + 405845660663B2010083E58C /* AuthorizationMechEval.h */, + 405845650663B2010083E58C /* AuthorizationMechEval.cpp */, + 4C9264A50534866F004B0E72 /* AuthorizationRule.h */, + 4C9264A40534866F004B0E72 /* AuthorizationRule.cpp */, + ); + name = Authorization; + sourceTree = ""; + }; + C28AE81406CD7DA100BE0061 /* Core Structure */ = { + isa = PBXGroup; + children = ( + 4C9264AB0534866F004B0E72 /* connection.h */, + 4C9264AA0534866F004B0E72 /* connection.cpp */, + C2B8DBC805E6C3CE00E6E67C /* database.h */, + C2B8DBC705E6C3CE00E6E67C /* database.cpp */, + 4C9264B60534866F004B0E72 /* key.h */, + 4C9264B50534866F004B0E72 /* key.cpp */, + 4C9264BB0534866F004B0E72 /* process.h */, + 4C9264BA0534866F004B0E72 /* process.cpp */, + 4C9264BF0534866F004B0E72 /* server.h */, + 4C9264BE0534866F004B0E72 /* server.cpp */, + 4C9264C10534866F004B0E72 /* session.h */, + 4C9264C00534866F004B0E72 /* session.cpp */, + C28ACF9B05C9940B00447176 /* structure.h */, + C28ACF9A05C9940B00447176 /* structure.cpp */, + ); + name = "Core Structure"; + sourceTree = ""; + }; + C28AE81706CD7DC500BE0061 /* Database Types */ = { + isa = PBXGroup; + children = ( + C28AE80406CD7D1D00BE0061 /* Local */, + C28AE80706CD7D2700BE0061 /* Keychain */, + C28AE80106CD7D0E00BE0061 /* Temporary */, + C28AE7FE06CD7CFF00BE0061 /* Token */, + ); + name = "Database Types"; + sourceTree = ""; + }; + C28AE81A06CD7DE200BE0061 /* Smartcards */ = { + isa = PBXGroup; + children = ( + C2FDCABE0663CD5B0013F64C /* pcscmonitor.h */, + C2FDCABD0663CD5B0013F64C /* pcscmonitor.cpp */, + C2FDCAC00663CD5B0013F64C /* reader.h */, + C2FDCABF0663CD5B0013F64C /* reader.cpp */, + C2FDCAC20663CD5B0013F64C /* token.h */, + C2FDCAC10663CD5B0013F64C /* token.cpp */, + C22A7F8D06AF06D9006087B7 /* tokend.h */, + C22A7F8C06AF06D9006087B7 /* tokend.cpp */, + C26EA9520688CF34007CE21D /* tokencache.h */, + C26EA9510688CF34007CE21D /* tokencache.cpp */, + ); + name = Smartcards; + sourceTree = ""; + }; + C28AE82006CD7DF500BE0061 /* Build Stuff */ = { + isa = PBXGroup; + children = ( + 4C9264BC0534866F004B0E72 /* securityd.order */, + ); + name = "Build Stuff"; + path = src; + sourceTree = ""; + }; + C28AE82306CD7E0F00BE0061 /* Transit */ = { + isa = PBXGroup; + children = ( + 4C9264C20534866F004B0E72 /* transition.cpp */, + ); + name = Transit; + sourceTree = ""; + }; + C28AE82606CD7E4700BE0061 /* ACLs */ = { + isa = PBXGroup; + children = ( + 4C92649B0534866F004B0E72 /* acls.h */, + 4C92649A0534866F004B0E72 /* acls.cpp */, + C28654B106DBC2A30021E6E5 /* tokenacl.h */, + C28654B006DBC2A30021E6E5 /* tokenacl.cpp */, + 4C9264990534866F004B0E72 /* acl_keychain.h */, + 4C9264980534866F004B0E72 /* acl_keychain.cpp */, + ); + name = ACLs; + sourceTree = ""; + }; + C28AE83906CD7EE900BE0061 /* Support */ = { + isa = PBXGroup; + children = ( + 4C92649D0534866F004B0E72 /* agentquery.h */, + 4C92649C0534866F004B0E72 /* agentquery.cpp */, + C274C51D0F9E8E0F001ABDA3 /* auditevents.h */, + C274C51C0F9E8E0F001ABDA3 /* auditevents.cpp */, + 4E0BB2B20F79590300BBFEFA /* ccaudit_extensions.h */, + 4E0BB2B30F79590300BBFEFA /* ccaudit_extensions.cpp */, + 4CB5ACBA06680AE000F359A9 /* child.h */, + 4CB5ACB906680AE000F359A9 /* child.cpp */, + 4C9264AF0534866F004B0E72 /* entropy.h */, + 4C9264AE0534866F004B0E72 /* entropy.cpp */, + 4C9264B90534866F004B0E72 /* notifications.h */, + 4C9264B80534866F004B0E72 /* notifications.cpp */, + D6C887EE0A55B6220044DFD2 /* SharedMemoryServer.h */, + D6C887ED0A55B6220044DFD2 /* SharedMemoryServer.cpp */, + ); + name = Support; + sourceTree = ""; + }; + C2C8B29806F8A60F000EBDA2 /* Crypto */ = { + isa = PBXGroup; + children = ( + 4C9264AD0534866F004B0E72 /* dbcrypto.h */, + 4C9264AC0534866F004B0E72 /* dbcrypto.cpp */, + ); + name = Crypto; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + AAC7077A0E6F437A003CC2B2 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + AAC707230E6F4335003CC2B2 /* acl_keychain.h in Headers */, + AAC707240E6F4335003CC2B2 /* acls.h in Headers */, + AAC707250E6F4335003CC2B2 /* agentquery.h in Headers */, + AAC707260E6F4335003CC2B2 /* authority.h in Headers */, + AAC707270E6F4335003CC2B2 /* AuthorizationDBPlist.h in Headers */, + AAC707280E6F4335003CC2B2 /* AuthorizationEngine.h in Headers */, + AAC707290E6F4335003CC2B2 /* AuthorizationMechEval.h in Headers */, + AAC7072A0E6F4335003CC2B2 /* AuthorizationRule.h in Headers */, + AAC7072B0E6F4335003CC2B2 /* child.h in Headers */, + AAC7072C0E6F4335003CC2B2 /* codesigdb.h in Headers */, + AAC7072D0E6F4335003CC2B2 /* connection.h in Headers */, + AAC7072E0E6F4335003CC2B2 /* database.h in Headers */, + AAC7072F0E6F4335003CC2B2 /* dbcrypto.h in Headers */, + AAC707300E6F4335003CC2B2 /* entropy.h in Headers */, + AAC707310E6F4335003CC2B2 /* kcdatabase.h in Headers */, + AAC707320E6F4335003CC2B2 /* kckey.h in Headers */, + AAC707330E6F4335003CC2B2 /* key.h in Headers */, + AAC707340E6F4335003CC2B2 /* localdatabase.h in Headers */, + AAC707350E6F4335003CC2B2 /* localkey.h in Headers */, + AAC707360E6F4335003CC2B2 /* notifications.h in Headers */, + AAC707370E6F4335003CC2B2 /* pcscmonitor.h in Headers */, + AAC707380E6F4335003CC2B2 /* process.h in Headers */, + AAC707390E6F4335003CC2B2 /* reader.h in Headers */, + AAC7073A0E6F4335003CC2B2 /* server.h in Headers */, + AAC7073B0E6F4335003CC2B2 /* session.h in Headers */, + AAC7073C0E6F4335003CC2B2 /* structure.h in Headers */, + AAC7073D0E6F4335003CC2B2 /* tempdatabase.h in Headers */, + AAC7073E0E6F4335003CC2B2 /* token.h in Headers */, + AAC7073F0E6F4335003CC2B2 /* tokendatabase.h in Headers */, + AAC707400E6F4335003CC2B2 /* tokencache.h in Headers */, + AAC707410E6F4335003CC2B2 /* self.h in Headers */, + AAC707420E6F4335003CC2B2 /* tokend.h in Headers */, + AAC707430E6F4335003CC2B2 /* tokenkey.h in Headers */, + AAC707440E6F4335003CC2B2 /* tokenacl.h in Headers */, + AAC707450E6F4335003CC2B2 /* tokenaccess.h in Headers */, + AAC707460E6F4335003CC2B2 /* authhost.h in Headers */, + AAC707470E6F4335003CC2B2 /* SharedMemoryServer.h in Headers */, + AAC707480E6F4335003CC2B2 /* csproxy.h in Headers */, + AAC707490E6F4335003CC2B2 /* credential.h in Headers */, + AAC7074B0E6F4335003CC2B2 /* clientid.h in Headers */, + AAC7074C0E6F4335003CC2B2 /* dtrace.h in Headers */, + 4E0BB2B40F79590300BBFEFA /* ccaudit_extensions.h in Headers */, + C274C51F0F9E8E0F001ABDA3 /* auditevents.h in Headers */, + 18B27134148C2C3D0087AE98 /* securityd_dtrace.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + AA6D4B890E6F3BB80050206D /* securityd */ = { + isa = PBXNativeTarget; + buildConfigurationList = AA6D4B900E6F3BE80050206D /* Build configuration list for PBXNativeTarget "securityd" */; + buildPhases = ( + AAC7077A0E6F437A003CC2B2 /* Headers */, + AA6D4B870E6F3BB80050206D /* Sources */, + AA6D4B880E6F3BB80050206D /* Frameworks */, + ED51306A0E7F1277002A3749 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + 1820DFC81714D3F800CA851F /* PBXTargetDependency */, + 80C7A791167FF9D3001533BE /* PBXTargetDependency */, + 18B967B914731BB1005A4D2E /* PBXTargetDependency */, + AA1AA00F0E71F2ED003D0309 /* PBXTargetDependency */, + AA1AA0110E71F2F7003D0309 /* PBXTargetDependency */, + AA1A9FF90E71EF08003D0309 /* PBXTargetDependency */, + ); + name = securityd; + productName = securityd_native; + productReference = AA6D4B8A0E6F3BB80050206D /* securityd */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4CA1FEB0052A3C5800F22E42 /* Project object */ = { + isa = PBXProject; + attributes = { + }; + buildConfigurationList = C27AD4AD0987FCF4001272E0 /* Build configuration list for PBXProject "securityd" */; + compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 4CA1FEAC052A3C5800F22E42; + productRefGroup = 4CA1FEB7052A3C6D00F22E42 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 18B965B1147314BE005A4D2E /* Products */; + ProjectRef = 18B965B0147314BE005A4D2E /* libsecurity_agent.xcodeproj */; + }, + { + ProductGroup = 80C7A788167FF586001533BE /* Products */; + ProjectRef = 80C7A77A167FF4FF001533BE /* securityd_service.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + AA6D4B890E6F3BB80050206D /* securityd */, + C26CF02C0CD934260094DD9D /* DTrace */, + AA6D4B7A0E6F3A910050206D /* mig */, + AA6D4B810E6F3B210050206D /* startup */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 18B965BD147314BE005A4D2E /* libsecurity_agent_client.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_agent_client.a; + remoteRef = 18B965BC147314BE005A4D2E /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 18B965C1147314BE005A4D2E /* libsecurity_agent_server.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_agent_server.a; + remoteRef = 18B965C0147314BE005A4D2E /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 18CE013E17147A46008C042F /* libsecuritydservice_client.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecuritydservice_client.a; + remoteRef = 18CE013D17147A46008C042F /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 53002F071818A7C400900564 /* com.apple.KeyStore.plugin */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = com.apple.KeyStore.plugin; + remoteRef = 53002F061818A7C400900564 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 80C7A78D167FF586001533BE /* securityd_service */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = securityd_service; + remoteRef = 80C7A78C167FF586001533BE /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 80C7A78F167FF586001533BE /* securitydservicectrl */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = securitydservicectrl; + remoteRef = 80C7A78E167FF586001533BE /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXShellScriptBuildPhase section */ + AA6D4B790E6F3A910050206D /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if [ -f $SRCROOT/securityd/etc/startup.mk ]; then SRCROOT=$SRCROOT/securityd; fi; make -f $SRCROOT/mig/mig.mk"; + }; + AA6D4B800E6F3B210050206D /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if [ -f $SRCROOT/securityd/etc/startup.mk ]; then SRCROOT=$SRCROOT/securityd; fi; /usr/bin/gnumake -f $SRCROOT/etc/startup.mk $ACTION"; + }; + C26CF0360CD9343A0094DD9D /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/bash; + shellScript = "if [ -f $SRCROOT/securityd/etc/startup.mk ]; then SRCROOT=$SRCROOT/securityd; fi; export DERIVED_SRC=$BUILT_PRODUCTS_DIR/derived_src; mkdir -p $DERIVED_SRC; make -f $SRCROOT/dtrace/dtrace.mk"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + AA6D4B870E6F3BB80050206D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AAC7074D0E6F4352003CC2B2 /* acl_keychain.cpp in Sources */, + AAC7074E0E6F4352003CC2B2 /* acls.cpp in Sources */, + AAC7074F0E6F4352003CC2B2 /* agentquery.cpp in Sources */, + AAC707500E6F4352003CC2B2 /* authority.cpp in Sources */, + AAC707510E6F4352003CC2B2 /* AuthorizationDBPlist.cpp in Sources */, + AAC707520E6F4352003CC2B2 /* AuthorizationEngine.cpp in Sources */, + AAC707530E6F4352003CC2B2 /* AuthorizationMechEval.cpp in Sources */, + AAC707540E6F4352003CC2B2 /* AuthorizationRule.cpp in Sources */, + AAC707550E6F4352003CC2B2 /* child.cpp in Sources */, + AAC707560E6F4352003CC2B2 /* codesigdb.cpp in Sources */, + AAC707570E6F4352003CC2B2 /* connection.cpp in Sources */, + AAC707580E6F4352003CC2B2 /* database.cpp in Sources */, + AAC707590E6F4352003CC2B2 /* dbcrypto.cpp in Sources */, + AAC7075A0E6F4352003CC2B2 /* entropy.cpp in Sources */, + AAC7075B0E6F4352003CC2B2 /* kcdatabase.cpp in Sources */, + AAC7075C0E6F4352003CC2B2 /* kckey.cpp in Sources */, + AAC7075D0E6F4352003CC2B2 /* key.cpp in Sources */, + AAC7075E0E6F4352003CC2B2 /* localdatabase.cpp in Sources */, + AAC7075F0E6F4352003CC2B2 /* localkey.cpp in Sources */, + AAC707600E6F4352003CC2B2 /* main.cpp in Sources */, + AAC707610E6F4352003CC2B2 /* notifications.cpp in Sources */, + AAC707620E6F4352003CC2B2 /* pcscmonitor.cpp in Sources */, + AAC707630E6F4352003CC2B2 /* process.cpp in Sources */, + AAC707640E6F4352003CC2B2 /* reader.cpp in Sources */, + AAC707650E6F4352003CC2B2 /* server.cpp in Sources */, + AAC707660E6F4352003CC2B2 /* session.cpp in Sources */, + AAC707670E6F4352003CC2B2 /* structure.cpp in Sources */, + AAC707680E6F4352003CC2B2 /* tempdatabase.cpp in Sources */, + AAC707690E6F4352003CC2B2 /* token.cpp in Sources */, + AAC7076A0E6F4352003CC2B2 /* tokendatabase.cpp in Sources */, + AAC7076B0E6F4352003CC2B2 /* transition.cpp in Sources */, + AAC7076C0E6F4352003CC2B2 /* tokencache.cpp in Sources */, + AAC7076D0E6F4352003CC2B2 /* selfServer.cpp in Sources */, + AAC7076E0E6F4352003CC2B2 /* selfUser.cpp in Sources */, + AAC7076F0E6F4352003CC2B2 /* tokend.cpp in Sources */, + AAC707700E6F4352003CC2B2 /* tokenkey.cpp in Sources */, + AAC707710E6F4352003CC2B2 /* tokenacl.cpp in Sources */, + AAC707720E6F4352003CC2B2 /* tokenaccess.cpp in Sources */, + AAC707730E6F4352003CC2B2 /* authhost.cpp in Sources */, + AAC707740E6F4352003CC2B2 /* SharedMemoryServer.cpp in Sources */, + AAC707750E6F4352003CC2B2 /* csproxy.cpp in Sources */, + AAC707760E6F4352003CC2B2 /* credential.cpp in Sources */, + AAC707780E6F4352003CC2B2 /* clientid.cpp in Sources */, + 4E0BB2B50F79590300BBFEFA /* ccaudit_extensions.cpp in Sources */, + C274C51E0F9E8E0F001ABDA3 /* auditevents.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 1820DFC81714D3F800CA851F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = securitydservice_client; + targetProxy = 1820DFC71714D3F800CA851F /* PBXContainerItemProxy */; + }; + 18B967B914731BB1005A4D2E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = world; + targetProxy = 18B967B814731BB1005A4D2E /* PBXContainerItemProxy */; + }; + 80C7A791167FF9D3001533BE /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = securityd_service; + targetProxy = 80C7A790167FF9D3001533BE /* PBXContainerItemProxy */; + }; + AA1A9FF90E71EF08003D0309 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C26CF02C0CD934260094DD9D /* DTrace */; + targetProxy = AA1A9FF80E71EF08003D0309 /* PBXContainerItemProxy */; + }; + AA1AA00F0E71F2ED003D0309 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = AA6D4B810E6F3B210050206D /* startup */; + targetProxy = AA1AA00E0E71F2ED003D0309 /* PBXContainerItemProxy */; + }; + AA1AA0110E71F2F7003D0309 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = AA6D4B7A0E6F3A910050206D /* mig */; + targetProxy = AA1AA0100E71F2F7003D0309 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + AA6D4B7B0E6F3A910050206D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + AA6D4B7E0E6F3A910050206D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; + AA6D4B820E6F3B210050206D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + AA6D4B850E6F3B210050206D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; + AA6D4B8C0E6F3BB80050206D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1865FFA01474FB1100FD79DF /* debug.xcconfig */; + buildSettings = { + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(BUILT_PRODUCTS_DIR)/derived_src", + "$(SRCROOT)", + "$(SRCROOT)/securityd", + ); + INSTALL_PATH = /usr/sbin; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/../../../build/Products\"", + "\"$(SRCROOT)/securityd/../../../build/Products\"", + ); + ORDER_FILE = "$(SRCROOT)/securityd/src/securityd.order"; + }; + name = Debug; + }; + AA6D4B8F0E6F3BB80050206D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1865FFA21474FB1100FD79DF /* release.xcconfig */; + buildSettings = { + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(BUILT_PRODUCTS_DIR)/derived_src", + "$(SRCROOT)", + "$(SRCROOT)/securityd", + ); + INSTALL_PATH = /usr/sbin; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/../../../build/Products\"", + "\"$(SRCROOT)/securityd/../../../build/Products\"", + ); + ORDER_FILE = "$(SRCROOT)/securityd/src/securityd.order"; + }; + name = Release; + }; + C26CF02D0CD934260094DD9D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + C26CF0300CD934260094DD9D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; + C27AD4AE0987FCF4001272E0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1865FFA11474FB1100FD79DF /* project.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C27AD4B10987FCF4001272E0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1865FFA11474FB1100FD79DF /* project.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + AA6D4B7F0E6F3AE50050206D /* Build configuration list for PBXAggregateTarget "mig" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AA6D4B7B0E6F3A910050206D /* Debug */, + AA6D4B7E0E6F3A910050206D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + AA6D4B860E6F3B8D0050206D /* Build configuration list for PBXAggregateTarget "startup" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AA6D4B820E6F3B210050206D /* Debug */, + AA6D4B850E6F3B210050206D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + AA6D4B900E6F3BE80050206D /* Build configuration list for PBXNativeTarget "securityd" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AA6D4B8C0E6F3BB80050206D /* Debug */, + AA6D4B8F0E6F3BB80050206D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C26CF03B0CD934420094DD9D /* Build configuration list for PBXAggregateTarget "DTrace" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C26CF02D0CD934260094DD9D /* Debug */, + C26CF0300CD934260094DD9D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C27AD4AD0987FCF4001272E0 /* Build configuration list for PBXProject "securityd" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C27AD4AE0987FCF4001272E0 /* Debug */, + C27AD4B10987FCF4001272E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4CA1FEB0052A3C5800F22E42 /* Project object */; +} diff --git a/securityd/securityd.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/securityd/securityd.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..ff0c9f28 --- /dev/null +++ b/securityd/securityd.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/securityd/securityd_service/KeyStore/AppleKeyStoreEvents.h b/securityd/securityd_service/KeyStore/AppleKeyStoreEvents.h new file mode 100644 index 00000000..a1b72ad7 --- /dev/null +++ b/securityd/securityd_service/KeyStore/AppleKeyStoreEvents.h @@ -0,0 +1,9 @@ +/* Copyright (c) 2013 Apple Inc. All Rights Reserved. */ + +#ifndef __APPLEKEYSTORE_EVENTS_H +#define __APPLEKEYSTORE_EVENTS_H + +#define kAppleKeyStoreLockStatusNotificationID "com.apple.keystore.lockstatus" +#define kAppleKeyStoreFirstUnlockNotificationID "com.apple.keystore.firstunlock" + +#endif // __APPLEKEYSTORE_EVENTS_H diff --git a/securityd/securityd_service/KeyStore/KeyStore-Info.plist b/securityd/securityd_service/KeyStore/KeyStore-Info.plist new file mode 100644 index 00000000..505cb03c --- /dev/null +++ b/securityd/securityd_service/KeyStore/KeyStore-Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.apple.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSHumanReadableCopyright + Copyright © 2013 Apple. All rights reserved. + XPCEventModuleInitializer + init_keystore_events + + diff --git a/securityd/securityd_service/KeyStore/KeyStoreEvents.c b/securityd/securityd_service/KeyStore/KeyStoreEvents.c new file mode 100644 index 00000000..63a749d5 --- /dev/null +++ b/securityd/securityd_service/KeyStore/KeyStoreEvents.c @@ -0,0 +1,54 @@ +/* Copyright (c) 2013 Apple Inc. All Rights Reserved. */ + +#include "AppleKeyStoreEvents.h" + +#include +#include +#include +#include +#include +#include +#include + +static void aksNotificationCallback(void *refcon,io_service_t service, natural_t messageType, void *messageArgument) +{ + if(messageType == kAppleKeyStoreLockStateChangeMessage) { +// syslog(LOG_ERR, "KeyStoreNotifier - %s posting notification: %s\n", __func__, kAppleKeyStoreLockStatusNotificationID); + notify_post(kAppleKeyStoreLockStatusNotificationID); + } else if (messageType == kAppleKeyStoreFirstUnlockMessage) { +// syslog(LOG_ERR, "KeyStoreNotifier - %s posting notification: %s\n", __func__, kAppleKeyStoreFirstUnlockNotificationID); + notify_post(kAppleKeyStoreFirstUnlockNotificationID); + } +} + +static void start(dispatch_queue_t queue) +{ + IOReturn result; + io_service_t aksService = IO_OBJECT_NULL; + IONotificationPortRef aksNotifyPort = IO_OBJECT_NULL; + io_object_t notification = IO_OBJECT_NULL; + + aksService = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching(kAppleKeyStoreServiceName)); + require_action(aksService, cleanup, syslog(LOG_ERR, "KeyStoreNotifier - Can't find %s service", kAppleKeyStoreServiceName)); + + aksNotifyPort = IONotificationPortCreate(kIOMasterPortDefault); + require_action(aksNotifyPort, cleanup, syslog(LOG_ERR, "KeyStoreNotifier - Can't create notification port")); + + IONotificationPortSetDispatchQueue(aksNotifyPort, queue); + + result = IOServiceAddInterestNotification(aksNotifyPort, aksService, kIOGeneralInterest, aksNotificationCallback, NULL, ¬ification); + require_noerr_action(result, cleanup, syslog(LOG_ERR, "KeyStoreNotifier - Can't register for notification: %08x", result)); + return; + +cleanup: + if (aksNotifyPort) IONotificationPortDestroy(aksNotifyPort); + if (notification) IOObjectRelease(notification); + if (aksService) IOObjectRelease(aksService); + return; +} + +void +init_keystore_events(xpc_event_module_t module) +{ + start(xpc_event_module_get_queue(module)); +} diff --git a/securityd/securityd_service/securityd_service.xcodeproj/project.pbxproj b/securityd/securityd_service/securityd_service.xcodeproj/project.pbxproj new file mode 100644 index 00000000..b31f75c4 --- /dev/null +++ b/securityd/securityd_service/securityd_service.xcodeproj/project.pbxproj @@ -0,0 +1,634 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 189D4639166AC95C001D8533 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 189D4638166AC95C001D8533 /* main.c */; }; + 189D4644166BFDCE001D8533 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 189D4643166BFDCE001D8533 /* Security.framework */; }; + 189D4647166C03CD001D8533 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 189D4646166C03CD001D8533 /* CoreFoundation.framework */; }; + 189D4649166C11A6001D8533 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 189D4648166C11A6001D8533 /* IOKit.framework */; }; + 189D465E166C15C1001D8533 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 189D465D166C15C1001D8533 /* main.c */; }; + 189D4667166C1809001D8533 /* com.apple.securityd_service.plist in Copy launchd plist */ = {isa = PBXBuildFile; fileRef = 189D4666166C171B001D8533 /* com.apple.securityd_service.plist */; }; + 189D4668166C19CF001D8533 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 189D4646166C03CD001D8533 /* CoreFoundation.framework */; }; + 18CD2B721714D48900633846 /* securityd_service_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 18CD2B711714D48300633846 /* securityd_service_client.c */; }; + 18CD2B791715CEC800633846 /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18CD2B781715CEC800633846 /* libaks.a */; }; + 18D7BBD2171639F0008F80B3 /* com.apple.securitydservice.sb in Copy sandbox profile */ = {isa = PBXBuildFile; fileRef = 18D7BBD0171638B9008F80B3 /* com.apple.securitydservice.sb */; }; + 18F4808F17497521009724DB /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 189D4646166C03CD001D8533 /* CoreFoundation.framework */; }; + 18F4809D174976DA009724DB /* KeyStoreEvents.c in Sources */ = {isa = PBXBuildFile; fileRef = 18F4809C174976D2009724DB /* KeyStoreEvents.c */; }; + 18F4809E1749774F009724DB /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 189D4648166C11A6001D8533 /* IOKit.framework */; }; + 18F480A217498ADD009724DB /* AppleKeyStoreEvents.h in Headers */ = {isa = PBXBuildFile; fileRef = 18F4809F17498963009724DB /* AppleKeyStoreEvents.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 80C312B6169BA50700DA5DC6 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 189D4643166BFDCE001D8533 /* Security.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 189D4664166C166E001D8533 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 189D462D166AC95C001D8533 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 189D465A166C15C1001D8533; + remoteInfo = securitydservicectrl; + }; + 18F4809A174975FF009724DB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 189D462D166AC95C001D8533 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 18F4808D17497521009724DB; + remoteInfo = KeyStore; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 189D4633166AC95C001D8533 /* Copy launchd plist */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /System/Library/LaunchDaemons; + dstSubfolderSpec = 0; + files = ( + 189D4667166C1809001D8533 /* com.apple.securityd_service.plist in Copy launchd plist */, + ); + name = "Copy launchd plist"; + runOnlyForDeploymentPostprocessing = 1; + }; + 189D4659166C15C1001D8533 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 18D7BBD1171639CE008F80B3 /* Copy sandbox profile */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "$(SYSTEM_LIBRARY_DIR)/Sandbox/Profiles"; + dstSubfolderSpec = 0; + files = ( + 18D7BBD2171639F0008F80B3 /* com.apple.securitydservice.sb in Copy sandbox profile */, + ); + name = "Copy sandbox profile"; + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1843240E1714797D00196B52 /* libsecuritydservice_client.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecuritydservice_client.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 189D4635166AC95C001D8533 /* securityd_service */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = securityd_service; sourceTree = BUILT_PRODUCTS_DIR; }; + 189D4638166AC95C001D8533 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 189D4641166AC9B6001D8533 /* securityd_service.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = securityd_service.h; sourceTree = ""; }; + 189D4642166BD755001D8533 /* service.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = service.entitlements; sourceTree = ""; }; + 189D4643166BFDCE001D8533 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = ""; }; + 189D4646166C03CD001D8533 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; + 189D4648166C11A6001D8533 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = ""; }; + 189D465B166C15C1001D8533 /* securitydservicectrl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = securitydservicectrl; sourceTree = BUILT_PRODUCTS_DIR; }; + 189D465D166C15C1001D8533 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 189D4666166C171B001D8533 /* com.apple.securityd_service.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.securityd_service.plist; sourceTree = ""; }; + 18CD2B711714D48300633846 /* securityd_service_client.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = securityd_service_client.c; path = securityd_service/securityd_service_client.c; sourceTree = ""; }; + 18CD2B731714D4B300633846 /* securityd_service_client.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = securityd_service_client.h; path = securityd_service/securityd_service_client.h; sourceTree = ""; }; + 18CD2B781715CEC800633846 /* libaks.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libaks.a; path = /usr/local/lib/libaks.a; sourceTree = ""; }; + 18D7BBD0171638B9008F80B3 /* com.apple.securitydservice.sb */ = {isa = PBXFileReference; lastKnownFileType = text; path = com.apple.securitydservice.sb; sourceTree = ""; }; + 18F4808E17497521009724DB /* com.apple.KeyStore.plugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = com.apple.KeyStore.plugin; sourceTree = BUILT_PRODUCTS_DIR; }; + 18F4809217497521009724DB /* KeyStore-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "KeyStore-Info.plist"; sourceTree = ""; }; + 18F4809C174976D2009724DB /* KeyStoreEvents.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = KeyStoreEvents.c; sourceTree = ""; }; + 18F4809F17498963009724DB /* AppleKeyStoreEvents.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppleKeyStoreEvents.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1843240B1714797D00196B52 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 189D4632166AC95C001D8533 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 18CD2B791715CEC800633846 /* libaks.a in Frameworks */, + 189D4649166C11A6001D8533 /* IOKit.framework in Frameworks */, + 189D4647166C03CD001D8533 /* CoreFoundation.framework in Frameworks */, + 189D4644166BFDCE001D8533 /* Security.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 189D4658166C15C1001D8533 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 80C312B6169BA50700DA5DC6 /* Security.framework in Frameworks */, + 189D4668166C19CF001D8533 /* CoreFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18F4808B17497521009724DB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 18F4809E1749774F009724DB /* IOKit.framework in Frameworks */, + 18F4808F17497521009724DB /* CoreFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 189D462C166AC95C001D8533 = { + isa = PBXGroup; + children = ( + 189D4637166AC95C001D8533 /* securityd_service */, + 18CD2B3B1714D43C00633846 /* securityd_service_client */, + 189D465C166C15C1001D8533 /* securitydservicectrl */, + 18F4809017497521009724DB /* KeyStore */, + 189D4645166BFDD4001D8533 /* Frameworks */, + 189D4636166AC95C001D8533 /* Products */, + ); + sourceTree = ""; + }; + 189D4636166AC95C001D8533 /* Products */ = { + isa = PBXGroup; + children = ( + 189D4635166AC95C001D8533 /* securityd_service */, + 189D465B166C15C1001D8533 /* securitydservicectrl */, + 1843240E1714797D00196B52 /* libsecuritydservice_client.a */, + 18F4808E17497521009724DB /* com.apple.KeyStore.plugin */, + ); + name = Products; + sourceTree = ""; + }; + 189D4637166AC95C001D8533 /* securityd_service */ = { + isa = PBXGroup; + children = ( + 189D4638166AC95C001D8533 /* main.c */, + 189D4641166AC9B6001D8533 /* securityd_service.h */, + 189D4642166BD755001D8533 /* service.entitlements */, + 189D4666166C171B001D8533 /* com.apple.securityd_service.plist */, + 18D7BBD0171638B9008F80B3 /* com.apple.securitydservice.sb */, + ); + path = securityd_service; + sourceTree = ""; + }; + 189D4645166BFDD4001D8533 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 18CD2B781715CEC800633846 /* libaks.a */, + 189D4648166C11A6001D8533 /* IOKit.framework */, + 189D4646166C03CD001D8533 /* CoreFoundation.framework */, + 189D4643166BFDCE001D8533 /* Security.framework */, + ); + name = Frameworks; + path = /Volumes/Data/wade/src/projects/securityd_service; + sourceTree = ""; + }; + 189D465C166C15C1001D8533 /* securitydservicectrl */ = { + isa = PBXGroup; + children = ( + 189D465D166C15C1001D8533 /* main.c */, + ); + path = securitydservicectrl; + sourceTree = ""; + }; + 18CD2B3B1714D43C00633846 /* securityd_service_client */ = { + isa = PBXGroup; + children = ( + 18CD2B711714D48300633846 /* securityd_service_client.c */, + 18CD2B731714D4B300633846 /* securityd_service_client.h */, + ); + name = securityd_service_client; + sourceTree = ""; + }; + 18F4809017497521009724DB /* KeyStore */ = { + isa = PBXGroup; + children = ( + 18F4809117497521009724DB /* Supporting Files */, + 18F4809C174976D2009724DB /* KeyStoreEvents.c */, + 18F4809F17498963009724DB /* AppleKeyStoreEvents.h */, + ); + path = KeyStore; + sourceTree = ""; + }; + 18F4809117497521009724DB /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 18F4809217497521009724DB /* KeyStore-Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 1843240C1714797D00196B52 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18F480A117498AD8009724DB /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 18F480A217498ADD009724DB /* AppleKeyStoreEvents.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 1843240D1714797D00196B52 /* securitydservice_client */ = { + isa = PBXNativeTarget; + buildConfigurationList = 184324111714797D00196B52 /* Build configuration list for PBXNativeTarget "securitydservice_client" */; + buildPhases = ( + 1843240A1714797D00196B52 /* Sources */, + 1843240B1714797D00196B52 /* Frameworks */, + 1843240C1714797D00196B52 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = securitydservice_client; + productName = securitydservice_client; + productReference = 1843240E1714797D00196B52 /* libsecuritydservice_client.a */; + productType = "com.apple.product-type.library.static"; + }; + 189D4634166AC95C001D8533 /* securityd_service */ = { + isa = PBXNativeTarget; + buildConfigurationList = 189D463E166AC95C001D8533 /* Build configuration list for PBXNativeTarget "securityd_service" */; + buildPhases = ( + 189D4631166AC95C001D8533 /* Sources */, + 189D4632166AC95C001D8533 /* Frameworks */, + 189D4633166AC95C001D8533 /* Copy launchd plist */, + 18D7BBD1171639CE008F80B3 /* Copy sandbox profile */, + ); + buildRules = ( + ); + dependencies = ( + 18F4809B174975FF009724DB /* PBXTargetDependency */, + 189D4665166C166E001D8533 /* PBXTargetDependency */, + ); + name = securityd_service; + productName = securityd_service; + productReference = 189D4635166AC95C001D8533 /* securityd_service */; + productType = "com.apple.product-type.tool"; + }; + 189D465A166C15C1001D8533 /* securitydservicectrl */ = { + isa = PBXNativeTarget; + buildConfigurationList = 189D4661166C15C1001D8533 /* Build configuration list for PBXNativeTarget "securitydservicectrl" */; + buildPhases = ( + 189D4657166C15C1001D8533 /* Sources */, + 189D4658166C15C1001D8533 /* Frameworks */, + 189D4659166C15C1001D8533 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = securitydservicectrl; + productName = securitydservicectrl; + productReference = 189D465B166C15C1001D8533 /* securitydservicectrl */; + productType = "com.apple.product-type.tool"; + }; + 18F4808D17497521009724DB /* KeyStoreEvents */ = { + isa = PBXNativeTarget; + buildConfigurationList = 18F4809917497521009724DB /* Build configuration list for PBXNativeTarget "KeyStoreEvents" */; + buildPhases = ( + 18F4808A17497521009724DB /* Sources */, + 18F4808B17497521009724DB /* Frameworks */, + 18F4808C17497521009724DB /* Resources */, + 18F480A117498AD8009724DB /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = KeyStoreEvents; + productName = KeyStore; + productReference = 18F4808E17497521009724DB /* com.apple.KeyStore.plugin */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 189D462D166AC95C001D8533 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0460; + ORGANIZATIONNAME = Apple; + }; + buildConfigurationList = 189D4630166AC95C001D8533 /* Build configuration list for PBXProject "securityd_service" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 189D462C166AC95C001D8533; + productRefGroup = 189D4636166AC95C001D8533 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 189D4634166AC95C001D8533 /* securityd_service */, + 189D465A166C15C1001D8533 /* securitydservicectrl */, + 1843240D1714797D00196B52 /* securitydservice_client */, + 18F4808D17497521009724DB /* KeyStoreEvents */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 18F4808C17497521009724DB /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1843240A1714797D00196B52 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18CD2B721714D48900633846 /* securityd_service_client.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 189D4631166AC95C001D8533 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 189D4639166AC95C001D8533 /* main.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 189D4657166C15C1001D8533 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 189D465E166C15C1001D8533 /* main.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 18F4808A17497521009724DB /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18F4809D174976DA009724DB /* KeyStoreEvents.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 189D4665166C166E001D8533 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 189D465A166C15C1001D8533 /* securitydservicectrl */; + targetProxy = 189D4664166C166E001D8533 /* PBXContainerItemProxy */; + }; + 18F4809B174975FF009724DB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 18F4808D17497521009724DB /* KeyStoreEvents */; + targetProxy = 18F4809A174975FF009724DB /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 1843240F1714797D00196B52 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_UNDECLARED_SELECTOR = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 184324101714797D00196B52 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + ENABLE_NS_ASSERTIONS = NO; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_UNDECLARED_SELECTOR = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 189D463C166AC95C001D8533 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "RC_BUILDIT_$(RC_BUILDIT)=1", + "DEBUG=1", + "$(inherited)", + ); + GCC_STRICT_ALIASING = YES; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + ONLY_ACTIVE_ARCH = YES; + }; + name = Debug; + }; + 189D463D166AC95C001D8533 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "RC_BUILDIT_$(RC_BUILDIT)=1", + "NDEBUG=1", + ); + GCC_STRICT_ALIASING = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + }; + name = Release; + }; + 189D463F166AC95C001D8533 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = securityd_service/service.entitlements; + INSTALL_PATH = /usr/libexec; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 189D4640166AC95C001D8533 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = securityd_service/service.entitlements; + INSTALL_PATH = /usr/libexec; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 189D4662166C15C1001D8533 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 189D4663166C15C1001D8533 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 18F4809717497521009724DB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = /usr/libexec/UserEventAgent; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + INFOPLIST_FILE = "KeyStore/KeyStore-Info.plist"; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/UserEventPlugins"; + PRODUCT_NAME = com.apple.KeyStore; + PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include; + WRAPPER_EXTENSION = plugin; + }; + name = Debug; + }; + 18F4809817497521009724DB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = /usr/libexec/UserEventAgent; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + INFOPLIST_FILE = "KeyStore/KeyStore-Info.plist"; + INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/UserEventPlugins"; + PRODUCT_NAME = com.apple.KeyStore; + PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include; + WRAPPER_EXTENSION = plugin; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 184324111714797D00196B52 /* Build configuration list for PBXNativeTarget "securitydservice_client" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1843240F1714797D00196B52 /* Debug */, + 184324101714797D00196B52 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 189D4630166AC95C001D8533 /* Build configuration list for PBXProject "securityd_service" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 189D463C166AC95C001D8533 /* Debug */, + 189D463D166AC95C001D8533 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 189D463E166AC95C001D8533 /* Build configuration list for PBXNativeTarget "securityd_service" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 189D463F166AC95C001D8533 /* Debug */, + 189D4640166AC95C001D8533 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 189D4661166C15C1001D8533 /* Build configuration list for PBXNativeTarget "securitydservicectrl" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 189D4662166C15C1001D8533 /* Debug */, + 189D4663166C15C1001D8533 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 18F4809917497521009724DB /* Build configuration list for PBXNativeTarget "KeyStoreEvents" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 18F4809717497521009724DB /* Debug */, + 18F4809817497521009724DB /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 189D462D166AC95C001D8533 /* Project object */; +} diff --git a/securityd/securityd_service/securityd_service/com.apple.securityd_service.plist b/securityd/securityd_service/securityd_service/com.apple.securityd_service.plist new file mode 100644 index 00000000..11f3a12e --- /dev/null +++ b/securityd/securityd_service/securityd_service/com.apple.securityd_service.plist @@ -0,0 +1,17 @@ + + + + + EnableTransactions + + Label + com.apple.securityd_service + Program + /usr/libexec/securityd_service + MachServices + + com.apple.securitydservice + + + + diff --git a/securityd/securityd_service/securityd_service/com.apple.securitydservice.sb b/securityd/securityd_service/securityd_service/com.apple.securitydservice.sb new file mode 100644 index 00000000..32d04705 --- /dev/null +++ b/securityd/securityd_service/securityd_service/com.apple.securitydservice.sb @@ -0,0 +1,31 @@ +(version 1) + +(deny default) + +(import "system.sb") + +(allow file-read*) + +(allow file-read* + (literal "/usr/libexec") + (literal "/usr/libexec/securityd_service") + (literal "/usr/sbin") + (literal "/usr/sbin/securityd")) + +(allow file-read* file-write* + (subpath "/private/var/keybags") + (regex #"/Keychains/") + (subpath "/private/var/db/mds")) + +(allow mach-lookup + (global-name "com.apple.SecurityServer")) + +(allow iokit-open + (iokit-user-client-class "AppleFDEKeyStoreUserClient") + (iokit-user-client-class "AppleKeyStoreUserClient")) + +(allow ipc-posix-shm + (ipc-posix-name "apple.shm.notification_center") + (ipc-posix-name "com.apple.AppleDatabaseChanged")) + +(allow system-audit) diff --git a/securityd/securityd_service/securityd_service/main.c b/securityd/securityd_service/securityd_service/main.c new file mode 100644 index 00000000..9ff33499 --- /dev/null +++ b/securityd/securityd_service/securityd_service/main.c @@ -0,0 +1,1080 @@ +/* Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. */ + +#include "securityd_service.h" +#include "securityd_service_client.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#if DEBUG +#define LOG(...) syslog(LOG_ERR, ##__VA_ARGS__); +#else +#define LOG(...) +#endif + +// exported from libaks.a +kern_return_t aks_register_for_notifications(mach_port_t server_port, uintptr_t message_id); +kern_return_t _aks_stash_create_internal(keybag_handle_t handle, bool stage_key, const void * passcode, int length); +kern_return_t _aks_stash_load_internal(keybag_handle_t handle, bool verify, uint8_t * data, size_t length, keybag_handle_t * handle_out); +kern_return_t _aks_stash_destroy_internal(void); +kern_return_t _aks_stash_commit_internal(void ** data, int * length); + +const char * kb_home_path = "Library/Keychains"; +const char * kb_user_bag = "user.kb"; +const char * kb_stash_bag = "stash.kb"; + +#define HEXBUF_LEN 2048 + +typedef struct { + uid_t uid; + gid_t gid; + char * name; + char * home; +} service_user_record_t; + +typedef enum { + kb_bag_type_user, + kb_bag_type_stash +} kb_bag_type_t; + +static io_connect_t +openiodev(void) +{ + io_registry_entry_t service; + io_connect_t conn; + kern_return_t kr; + + service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching(kAppleFDEKeyStoreServiceName)); + if (service == IO_OBJECT_NULL) + return IO_OBJECT_NULL; + + kr = IOServiceOpen(service, mach_task_self(), 0, &conn); + if (kr != KERN_SUCCESS) + return IO_OBJECT_NULL; + + kr = IOConnectCallMethod(conn, kAppleFDEKeyStoreUserClientOpen, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL); + if (kr != KERN_SUCCESS) { + IOServiceClose(conn); + return IO_OBJECT_NULL; + } + + return conn; +} + +static void +closeiodev(io_connect_t conn) +{ + kern_return_t kr; + kr = IOConnectCallMethod(conn, kAppleFDEKeyStoreUserClientClose, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL); + if (kr != KERN_SUCCESS) + return; + IOServiceClose(conn); +} + +static dispatch_queue_t +_kb_service_get_dispatch_queue() +{ + static dispatch_once_t onceToken = 0; + static dispatch_queue_t connection_queue = NULL; + + dispatch_once(&onceToken, ^{ + connection_queue = dispatch_queue_create("kb-service-queue", DISPATCH_QUEUE_SERIAL); + }); + + return connection_queue; +} + +static service_user_record_t * get_user_record(uid_t uid) +{ + service_user_record_t * ur = NULL; + long bufsize = 0; + if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) == -1) { + bufsize = 4096; + } + char buf[bufsize]; + struct passwd pwbuf, *pw = NULL; + if ((getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0) && pw != NULL) { + ur = calloc(1u, sizeof(service_user_record_t)); + require(ur, done); + ur->uid = pw->pw_uid; + ur->gid = pw->pw_gid; + ur->home = strdup(pw->pw_dir); + ur->name = strdup(pw->pw_name); + } else { + syslog(LOG_ERR, "failed to lookup user record for uid: %d", uid); + } + +done: + return ur; +} + +static void free_user_record(service_user_record_t * ur) +{ + if (ur != NULL) { + if (ur->home) { + free(ur->home); + } + if (ur->name) { + free(ur->name); + } + free(ur); + } +} + +static const char * get_host_uuid() +{ + static uuid_string_t hostuuid = {}; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + struct timespec timeout = {30, 0}; + uuid_t uuid = {}; + if (gethostuuid(uuid, &timeout) == 0) { + uuid_unparse(uuid, hostuuid); + } else { + syslog(LOG_ERR, "failed to get host uuid"); + } + }); + + return hostuuid; +} + +static char * +_kb_copy_bag_filename(service_user_record_t * ur, kb_bag_type_t type) +{ + char * bag_file = NULL; + const char * name = NULL; + + require(ur, done); + switch(type) { + case kb_bag_type_user: + name = kb_user_bag; + break; + case kb_bag_type_stash: + name = kb_stash_bag; + break; + default: + goto done; + } + + bag_file = calloc(1u, PATH_MAX); + require(bag_file, done); + + snprintf(bag_file, PATH_MAX, "%s/%s/%s/%s", ur->home, kb_home_path, get_host_uuid(), name); + +done: + return bag_file; +} + +static bool +_kb_verify_create_path(service_user_record_t * ur) +{ + bool created = false; + struct stat st_info = {}; + char new_path[PATH_MAX] = {}; + char kb_path[PATH_MAX] = {}; + snprintf(kb_path, sizeof(kb_path), "%s/%s/%s", ur->home, kb_home_path, get_host_uuid()); + if (lstat(kb_path, &st_info) == 0) { + if (S_ISDIR(st_info.st_mode)) { + created = true; + } else { + syslog(LOG_ERR, "invalid directory at '%s' moving aside", kb_path); + snprintf(new_path, sizeof(new_path), "%s-invalid", kb_path); + unlink(new_path); + if (rename(kb_path, new_path) != 0) { + syslog(LOG_ERR, "failed to rename file: %s (%s)", kb_path, strerror(errno)); + goto done; + } + } + } + if (!created) { + require_action(mkpath_np(kb_path, 0700) == 0, done, syslog(LOG_ERR, "could not create path: %s (%s)", kb_path, strerror(errno))); + created = true; + } + +done: + return created; +} + +static void +_set_thread_credentials(service_user_record_t * ur) +{ + int rc = pthread_setugid_np(ur->uid, ur->gid); + if (rc) { syslog(LOG_ERR, "failed to set thread credential: %i (%s)", errno, strerror(errno)); } + + rc = initgroups(ur->name, ur->gid); + if (rc) { syslog(LOG_ERR, "failed to initgroups: %i", rc); } +} + +static void +_clear_thread_credentials() +{ + int rc = pthread_setugid_np(KAUTH_UID_NONE, KAUTH_GID_NONE); + if (rc) { syslog(LOG_ERR, "failed to reset thread credential: %i (%s)", errno, strerror(errno)); } +} + +static bool +_kb_bag_exists(service_user_record_t * ur, const char * bag_file) +{ + bool exists = false; + struct stat st_info = {}; + char new_file[PATH_MAX] = {}; + + require(ur, done); + + _set_thread_credentials(ur); + if (lstat(bag_file, &st_info) == 0) { + if (S_ISREG(st_info.st_mode)) { + exists = true; + } else { + syslog(LOG_ERR, "invalid file at '%s' moving aside", bag_file); + snprintf(new_file, sizeof(new_file), "%s-invalid", bag_file); + unlink(new_file); + if (rename(bag_file, new_file) != 0) { + syslog(LOG_ERR, "failed to rename file: %s (%s)", bag_file, strerror(errno)); + } + } + } + +done: + _clear_thread_credentials(); + return exists; +} + +static bool +_kb_save_bag_to_disk(service_user_record_t * ur, const char * bag_file, void * data, size_t length) +{ + bool result = false; + int fd = -1; + + require(bag_file, done); + + _set_thread_credentials(ur); + require(_kb_verify_create_path(ur), done); + + fd = open(bag_file, O_CREAT | O_TRUNC | O_WRONLY | O_NOFOLLOW, 0600); + require_action(fd != -1, done, syslog(LOG_ERR, "could not create file: %s (%s)", bag_file, strerror(errno))); + require_action(write(fd, data, length) != -1, done, syslog(LOG_ERR, "failed to write keybag to disk %s", strerror(errno))); + + result = true; + +done: + if (fd != -1) { close(fd); } + _clear_thread_credentials(); + return result; +} + +static bool +_kb_load_bag_from_disk(service_user_record_t * ur, const char * bag_file, uint8_t ** data, size_t * length) +{ + bool result = false; + int fd = -1; + uint8_t * buf = NULL; + size_t buf_size = 0; + struct stat st_info = {}; + + require(bag_file, done); + + _set_thread_credentials(ur); + require(_kb_verify_create_path(ur), done); + require_quiet(lstat(bag_file, &st_info) == 0, done); + require_action(S_ISREG(st_info.st_mode), done, syslog(LOG_ERR, "failed to load, not a file: %s", bag_file)); + buf_size = (size_t)st_info.st_size; + + fd = open(bag_file, O_RDONLY | O_NOFOLLOW); + require_action(fd != -1, done, syslog(LOG_ERR, "could not open file: %s (%s)", bag_file, strerror(errno))); + + buf = (uint8_t *)calloc(1u, buf_size); + require(buf != NULL, done); + require(read(fd, buf, buf_size) == buf_size, done); + + *data = buf; + *length = buf_size; + buf = NULL; + result = true; + +done: + if (fd != -1) { close(fd); } + if (buf) { free(buf); } + _clear_thread_credentials(); + return result; +} + +static void +_kb_rename_bag_on_disk(service_user_record_t * ur, const char * bag_file) +{ + char new_file[PATH_MAX] = {}; + if (bag_file) { + _set_thread_credentials(ur); + snprintf(new_file, sizeof(new_file), "%s-invalid", bag_file); + unlink(new_file); + rename(bag_file, new_file); + _clear_thread_credentials(); + } +} + +static void +_kb_delete_bag_on_disk(service_user_record_t * ur, const char * bag_file) +{ + if (bag_file) { + _set_thread_credentials(ur); + unlink(bag_file); + _clear_thread_credentials(); + } +} + +static int +_kb_get_session_handle(service_context_t * context, keybag_handle_t * handle_out) +{ + int rc = KB_BagNotLoaded; + keybag_handle_t session_handle = bad_keybag_handle; + require_noerr_quiet(aks_get_system(context->s_uid, &session_handle), done); + + *handle_out = session_handle; + rc = KB_Success; + +done: + return rc; +} + +static void update_keybag_handle(keybag_handle_t handle) +{ + dispatch_sync(_kb_service_get_dispatch_queue(), ^{ + uid_t uid = abs(handle); + uint8_t * buf = NULL; + size_t buf_size = 0; + service_user_record_t * ur = NULL; + char * bag_file = NULL; + + require_noerr(aks_save_bag(handle, (void**)&buf, (int*)&buf_size), done); + require(ur = get_user_record(uid), done); + require(bag_file = _kb_copy_bag_filename(ur, kb_bag_type_user), done); + require(_kb_save_bag_to_disk(ur, bag_file, buf, buf_size), done); + + syslog(LOG_NOTICE, "successfully updated handle %d", handle); + + done: + if (buf) free(buf); + if (ur) free_user_record(ur); + if (bag_file) free(bag_file); + }); +} + +static int +service_kb_create(service_context_t * context, const void * secret, int secret_len) +{ + __block int rc = KB_GeneralError; + + dispatch_sync(_kb_service_get_dispatch_queue(), ^{ + uint8_t * buf = NULL; + size_t buf_size = 0; + keybag_handle_t session_handle = bad_keybag_handle; + service_user_record_t * ur = get_user_record(context->s_uid); + char * bag_file = _kb_copy_bag_filename(ur, kb_bag_type_user); + + require(bag_file, done); + + // check for the existance of the bagfile + require_action(!_kb_bag_exists(ur, bag_file), done, rc = KB_BagExists); + + require_noerr(rc = aks_create_bag(secret, secret_len, kAppleKeyStoreDeviceBag, &session_handle), done); + require_noerr(rc = aks_save_bag(session_handle, (void**)&buf, (int*)&buf_size), done); + require_action(_kb_save_bag_to_disk(ur, bag_file, buf, buf_size), done, rc = KB_BagError); + require_noerr(rc = aks_set_system(session_handle, context->s_uid), done); + aks_unload_bag(session_handle); + require_noerr(rc = _kb_get_session_handle(context, &session_handle), done); + + if (secret && rc == KB_Success) { + aks_unlock_bag(session_handle, secret, secret_len); + } + + done: + if (buf) free(buf); + if (bag_file) { free(bag_file); } + if (ur) free_user_record(ur); + }); + + return rc; +} + +static int +service_kb_load(service_context_t * context) +{ + __block int rc = KB_GeneralError; + + dispatch_sync(_kb_service_get_dispatch_queue(), ^{ + uint8_t * buf = NULL; + size_t buf_size = 0; + keybag_handle_t session_handle = bad_keybag_handle; + service_user_record_t * ur = NULL; + char * bag_file = NULL; + + rc = aks_get_system(context->s_uid, &session_handle); + if (rc == kIOReturnNotFound) { + require_action(ur = get_user_record(context->s_uid), done, rc = KB_GeneralError); + require_action(bag_file = _kb_copy_bag_filename(ur, kb_bag_type_user), done, rc = KB_GeneralError); + require_action_quiet(_kb_load_bag_from_disk(ur, bag_file, &buf, &buf_size), done, rc = KB_BagNotFound); + rc = aks_load_bag(buf, (int)buf_size, &session_handle); + if (rc == kIOReturnNotPermitted) { + syslog(LOG_ERR, "error loading keybag for uid (%i) in session (%i)", context->s_uid, context->s_id); + _kb_rename_bag_on_disk(ur, bag_file); + rc = KB_BagNotFound; + } + require_noerr(rc, done); + require_noerr(rc = aks_set_system(session_handle, context->s_uid), done); + aks_unload_bag(session_handle); + } + require(rc == KB_Success, done); + + done: + if (buf) free(buf); + if (ur) free_user_record(ur); + if (bag_file) free(bag_file); + }); + + return rc; +} + + +static int +service_kb_unlock(service_context_t * context, const void * secret, int secret_len) +{ + int rc = KB_GeneralError; + keybag_handle_t session_handle; + require_noerr(rc = _kb_get_session_handle(context, &session_handle), done); + + rc = aks_unlock_bag(session_handle, secret, secret_len); + +done: + return rc; +} + +static int +service_kb_lock(service_context_t * context) +{ + int rc = KB_GeneralError; + keybag_handle_t session_handle; + require_noerr(rc = _kb_get_session_handle(context, &session_handle), done); + + rc = aks_lock_bag(session_handle); + +done: + return rc; +} + +static int +service_kb_change_secret(service_context_t * context, const void * secret, int secret_len, const void * new_secret, int new_secret_len) +{ + __block int rc = KB_GeneralError; + keybag_handle_t session_handle; + require_noerr(rc = _kb_get_session_handle(context, &session_handle), done); + + dispatch_sync(_kb_service_get_dispatch_queue(), ^{ + uint8_t * buf = NULL; + size_t buf_size = 0; + service_user_record_t * ur = NULL; + char * bag_file = NULL; + + require_noerr(rc = aks_change_secret(session_handle, secret, secret_len, new_secret, new_secret_len, NULL, NULL), done); + require_noerr(rc = aks_save_bag(session_handle, (void**)&buf, (int*)&buf_size), done); + require_action(ur = get_user_record(context->s_uid), done, rc = KB_GeneralError); + require_action(bag_file = _kb_copy_bag_filename(ur, kb_bag_type_user), done, rc = KB_GeneralError); + require_action(_kb_save_bag_to_disk(ur, bag_file, buf, buf_size), done, rc = KB_BagError); + + rc = KB_Success; + + done: + if (buf) free(buf); + if (ur) free_user_record(ur); + if (bag_file) free(bag_file); + return; + }); + +done: + return rc; +} + +static int +service_kb_reset(service_context_t * context, const void * secret, int secret_len) +{ + __block int rc = KB_GeneralError; + service_user_record_t * ur = NULL; + char * bag_file = NULL; + + require_action(ur = get_user_record(context->s_uid), done, rc = KB_GeneralError); + require_action(bag_file = _kb_copy_bag_filename(ur, kb_bag_type_user), done, rc = KB_GeneralError); + + dispatch_sync(_kb_service_get_dispatch_queue(), ^{ + uint8_t * buf = NULL; + size_t buf_size = 0; + keybag_handle_t session_handle = bad_keybag_handle; + + syslog(LOG_ERR, "resetting keybag for uid (%i) in session (%i)", context->s_uid, context->s_id); + _kb_rename_bag_on_disk(ur, bag_file); + + require_noerr(rc = aks_create_bag(secret, secret_len, kAppleKeyStoreDeviceBag, &session_handle), done); + require_noerr(rc = aks_save_bag(session_handle, (void**)&buf, (int*)&buf_size), done); + require_action(_kb_save_bag_to_disk(ur, bag_file, buf, buf_size), done, rc = KB_BagError); + require_noerr(rc = aks_set_system(session_handle, context->s_uid), done); + aks_unload_bag(session_handle); + require_noerr(rc = _kb_get_session_handle(context, &session_handle), done); + + if (secret && rc == KB_Success) { + aks_unlock_bag(session_handle, secret, secret_len); + } + + done: + if (buf) free(buf); + return; + }); + +done: + if (ur) free_user_record(ur); + if (bag_file) free(bag_file); + return rc; +} + +static int +service_kb_is_locked(service_context_t * context, xpc_object_t reply) +{ + int rc = KB_GeneralError; + keybag_state_t state; + keybag_handle_t session_handle; + require_noerr(rc = _kb_get_session_handle(context, &session_handle), done); + + require_noerr(rc = aks_get_lock_state(session_handle, &state), done); + + xpc_dictionary_set_bool(reply, SERVICE_XPC_LOCKED, state & keybag_state_locked); + xpc_dictionary_set_bool(reply, SERVICE_XPC_NO_PIN, state & keybag_state_no_pin); + +done: + return rc; +} + +static int +service_kb_stash_create(service_context_t * context, const void * key, unsigned key_size) +{ + int rc = KB_GeneralError; + char * bag_file = NULL; + keybag_handle_t session_handle; + service_user_record_t * ur = NULL; + void * stashbag = NULL; + unsigned stashbag_size = 0; + __block bool saved = false; + + require(key, done); + require_noerr(rc = _kb_get_session_handle(context, &session_handle), done); + require_action(ur = get_user_record(context->s_uid), done, rc = KB_GeneralError); + require_noerr(rc = _aks_stash_create_internal(session_handle, false, key, key_size), done); + require_noerr(rc = _aks_stash_commit_internal((void**)&stashbag, (int*)&stashbag_size), done); + + require_action(bag_file = _kb_copy_bag_filename(ur, kb_bag_type_stash), done, rc = KB_GeneralError); + + // sync writing the bag to disk + dispatch_sync(_kb_service_get_dispatch_queue(), ^{ + saved = _kb_save_bag_to_disk(ur, bag_file, stashbag, stashbag_size); + }); + require_action(saved, done, rc = KB_BagError); + rc = KB_Success; + +done: + if (stashbag) { free(stashbag); } + if (bag_file) { free(bag_file); } + if (ur) free_user_record(ur); + return rc; +} + +static int +service_kb_stash_load(service_context_t * context, const void * key, unsigned key_size, bool nondestructive) +{ + __block int rc = KB_GeneralError; + char * bag_file = NULL; + keybag_handle_t session_handle; + service_user_record_t * ur = NULL; + __block uint8_t * stashbag = NULL; + __block size_t stashbag_size = 0; + + require(key, done); + require_noerr(rc = _kb_get_session_handle(context, &session_handle), done); + require_action(ur = get_user_record(context->s_uid), done, rc = KB_GeneralError); + require_action(bag_file = _kb_copy_bag_filename(ur, kb_bag_type_stash), done, rc = KB_GeneralError); + + // sync loading the bag from disk + dispatch_sync(_kb_service_get_dispatch_queue(), ^{ + if (!_kb_load_bag_from_disk(ur, bag_file, &stashbag, &stashbag_size)) { + rc = KB_BagError; + } + }); + require_noerr(rc, done); + + require_noerr(rc = _aks_stash_create_internal(session_handle, true, key, key_size), done); + require_noerr(rc = _aks_stash_load_internal(session_handle, false, stashbag, stashbag_size, NULL), done); + rc = KB_Success; + +done: + if (stashbag) { free(stashbag); } + if ((bag_file) && (!nondestructive)) { + _kb_delete_bag_on_disk(ur, bag_file); + free(bag_file); + } + if (ur) free_user_record(ur); + return rc; +} + +// +// Get the keychain master key from the AppleFDEKeyStore. +// Note that this is a one-time call - the master key is +// removed from the keystore after it is returned. +// Requires the entitlement: com.apple.private.securityd.keychain +// +OSStatus service_stash_get_key(service_context_t * context, xpc_object_t event, xpc_object_t reply) +{ + getStashKey_InStruct_t inStruct; + getStashKey_OutStruct_t outStruct; + size_t outSize = sizeof(outStruct); + kern_return_t kr = KERN_INVALID_ARGUMENT; + + io_connect_t conn = openiodev(); + require(conn, done); + inStruct.type = kAppleFDEKeyStoreStash_master; + + kr = IOConnectCallMethod(conn, kAppleFDEKeyStore_getStashKey, + NULL, 0, + &inStruct, sizeof(inStruct), + NULL, NULL, + &outStruct, &outSize); + + if (kr == KERN_SUCCESS) { + xpc_dictionary_set_data(reply, SERVICE_XPC_KEY, outStruct.outBuf.key.key, outStruct.outBuf.key.keysize); + service_kb_stash_load(context, outStruct.outBuf.key.key, outStruct.outBuf.key.keysize, false); + } + +done: + if (conn) + closeiodev(conn); + + return kr; +} + +// +// Stash the keychain master key in the AppleFDEKeyStore and +// flag it as the keychain master key to be added to the +// reboot NVRAM blob. +// This requires two calls to the AKS: the first to store the +// key and get its uuid. The second uses the uuid to flag the +// key for blob inclusion. +// +OSStatus service_stash_set_key(service_context_t * context, xpc_object_t event, xpc_object_t reply) +{ + kern_return_t kr = KERN_INVALID_ARGUMENT; + size_t keydata_len = 0; + size_t len; + + io_connect_t conn = openiodev(); + require(conn, done); + + // Store the key in the keystore and get its uuid + setKeyGetUUID_InStruct_t inStruct1; + uuid_OutStruct_t outStruct1; + + + const uint8_t *keydata = xpc_dictionary_get_data(event, SERVICE_XPC_KEY, &keydata_len); + require(keydata, done); + + memcpy(&inStruct1.inKey.key.key, keydata, keydata_len); + inStruct1.inKey.key.keysize = (cryptosize_t) keydata_len; + len = sizeof(outStruct1); + kr = IOConnectCallMethod(conn, kAppleFDEKeyStore_setKeyGetUUID, + NULL, 0, + &inStruct1, sizeof(inStruct1), + NULL, NULL, + &outStruct1, &len); + require(kr == KERN_SUCCESS, done); + + // Now using the uuid stash it as the master key + setStashKey_InStruct_t inStruct2; + memcpy(&inStruct2.uuid, &outStruct1.uuid, sizeof(outStruct1.uuid)); + inStruct2.type = kAppleFDEKeyStoreStash_master; + + kr = IOConnectCallMethod(conn, kAppleFDEKeyStore_setStashKey, + NULL, 0, + &inStruct2, sizeof(inStruct2), + NULL, NULL, + NULL, NULL); + + if (kr == KERN_SUCCESS) { + service_kb_stash_create(context, keydata, (unsigned)keydata_len); + } +done: + if (conn) + closeiodev(conn); + + return kr; +} + +// +// Load the master stash key +// +OSStatus service_stash_load_key(service_context_t * context, xpc_object_t event, xpc_object_t reply) +{ + kern_return_t kr = KERN_SUCCESS; + size_t keydata_len = 0; + + const uint8_t *keydata = xpc_dictionary_get_data(event, SERVICE_XPC_KEY, &keydata_len); + require(keydata, done); + + kr = service_kb_stash_load(context, keydata, (cryptosize_t) keydata_len, true); +done: + + return kr; +} + +// +// Signal the AppleFDEKeyStore to take the tagged FDE key +// and keychain master key, stash them in an encrypted +// blob structure and write the blob to NVRAM. The random +// encryption key is written to the SMC. +// +#if DEBUG +OSStatus service_stash_blob(xpc_object_t event, xpc_object_t reply) +{ + kern_return_t kr = KERN_INVALID_ARGUMENT; + + io_connect_t conn = openiodev(); + require(conn, done); + + kr = IOConnectCallMethod(conn, kAppleFDEKeyStore_commitStash, + NULL, 0, + NULL, 0, + NULL, NULL, + NULL, NULL); +done: + if (conn) + closeiodev(conn); + + return kr; +} +#endif + +bool peer_has_entitlement(xpc_connection_t peer, const char * entitlement) +{ + bool entitled = false; + + xpc_object_t value = xpc_connection_copy_entitlement_value(peer, entitlement); + if (value && (xpc_get_type(value) == XPC_TYPE_BOOL)) { + entitled = xpc_bool_get_value(value); + } + + if (value) xpc_release(value); + return entitled; +} + +#if DEBUG +static char * +to_hex(char * dst, const void * src, size_t size) +{ + int notleading = 0; + + if ((size * 2) > HEXBUF_LEN) return NULL; + + uint8_t * buf = (uint8_t *)src; + register char *chp = dst; + *dst = '\0'; + if (size != 0) do { + if(notleading || *buf != '\0') { + if(!notleading && (*buf & 0xf0) == 0) { + sprintf(chp, "%.1x", * (unsigned char *) src); + chp += 1; + } + else { + sprintf(chp, "%.2x", * (unsigned char *) src); + chp += 2; + } + notleading = 1; + } + ++src; + } while (--size != 0); + return dst; +} +#endif // DEBUG + +static char * sel_to_char(uint64_t sel) +{ + switch (sel) { + case SERVICE_STASH_SET_KEY: + return "set_key"; + case SERVICE_STASH_GET_KEY: + return "get_key"; + case SERVICE_STASH_BLOB: + return "stash_blob"; + case SERVICE_KB_LOAD: + return "kb_load"; + case SERVICE_KB_UNLOCK: + return "kb_unlock"; + case SERVICE_KB_LOCK: + return "kb_lock"; + case SERVICE_KB_CHANGE_SECRET: + return "kb_change_secret"; + case SERVICE_KB_CREATE: + return "kb_create"; + case SERVICE_KB_IS_LOCKED: + return "kb_is_locked"; + case SERVICE_KB_RESET: + return "kb_reset"; + default: + return "unknown"; + } +} + +static char * err_to_char(int err) +{ + switch (err) { + case KB_Success: + return "success"; + case KB_GeneralError: + return "general error"; + case KB_BagNotFound: + return "bag not found"; + case KB_BagError: + return "bag error"; + case KB_BagNotLoaded: + return "bag not loaded"; + case KB_BagExists: + return "bag exists"; + case KB_InvalidSession: + return "invalid session"; + default: + return ""; + } +} + +void service_peer_event_handler(xpc_connection_t connection, xpc_object_t event) +{ +#if DEBUG + char hexbuf1[HEXBUF_LEN]; + char hexbuf2[HEXBUF_LEN]; +#endif // DEBUG + xpc_type_t type = xpc_get_type(event); + + if (type == XPC_TYPE_ERROR) { + if (event == XPC_ERROR_CONNECTION_INVALID) { + } + } else { + assert(type == XPC_TYPE_DICTIONARY); + + int rc = KB_GeneralError; + uint64_t request = 0; + const uint8_t * secret = NULL, * new_secret = NULL; + size_t secret_len = 0, new_secret_len = 0, data_len = 0; + service_context_t * context = NULL; + const void * data; + + xpc_object_t reply = xpc_dictionary_create_reply(event); + + data = xpc_dictionary_get_data(event, SERVICE_XPC_CONTEXT, &data_len); + require(data, done); + require(data_len == sizeof(service_context_t), done); + context = (service_context_t*)data; + + request = xpc_dictionary_get_uint64(event, SERVICE_XPC_REQUEST); + + require_action(context->s_id != AU_DEFAUDITSID, done, rc = KB_InvalidSession); + require_action(context->s_uid != AU_DEFAUDITID, done, rc = KB_InvalidSession); // we only want to work in actual user sessions. + + switch (request) { + case SERVICE_KB_CREATE: + // if (kb_service_has_entitlement(peer, "com.apple.keystore.device")) { + secret = xpc_dictionary_get_data(event, SERVICE_XPC_SECRET, &secret_len); + rc = service_kb_create(context, secret, (int)secret_len); + // } + break; + case SERVICE_KB_LOAD: + rc = service_kb_load(context); + break; + case SERVICE_KB_UNLOCK: + secret = xpc_dictionary_get_data(event, SERVICE_XPC_SECRET, &secret_len); + rc = service_kb_unlock(context, secret, (int)secret_len); + break; + case SERVICE_KB_LOCK: + rc = service_kb_lock(context); + break; + case SERVICE_KB_CHANGE_SECRET: + secret = xpc_dictionary_get_data(event, SERVICE_XPC_SECRET, &secret_len); + new_secret = xpc_dictionary_get_data(event, SERVICE_XPC_SECRET_NEW, &new_secret_len); + rc = service_kb_change_secret(context, secret, (int)secret_len, new_secret, (int)new_secret_len); + break; + case SERVICE_KB_RESET: + secret = xpc_dictionary_get_data(event, SERVICE_XPC_SECRET, &secret_len); + rc = service_kb_reset(context, secret, (int)secret_len); + break; + case SERVICE_KB_IS_LOCKED: + rc = service_kb_is_locked(context, reply); + break; + case SERVICE_STASH_GET_KEY: + rc = service_stash_get_key(context, event, reply); + break; + case SERVICE_STASH_SET_KEY: + rc = service_stash_set_key(context, event, reply); + break; + case SERVICE_STASH_LOAD_KEY: + rc = service_stash_load_key(context, event, reply); + break; +#if DEBUG + case SERVICE_STASH_BLOB: + rc = service_stash_blob(event, reply); + break; +#endif + default: + LOG("unknown service type"); + break; + } + + done: +#if DEBUG + LOG("selector: %s (%llu), error: %s (%x), '%s' secret_len: %zu, '%s' new_secret_len: %zu, sid: %d, suid: %d", sel_to_char(request), request, err_to_char(rc), rc, to_hex(hexbuf1, secret, secret_len), secret_len, to_hex(hexbuf2, new_secret, new_secret_len), new_secret_len, context ? context->s_id : 0, context ? context->s_uid : 0); +#else + if (rc != 0) { + syslog(LOG_NOTICE, "selector: %s (%llu), error: %s (%x), sid: %d, suid: %d", sel_to_char(request), request, err_to_char(rc), rc, context ? context->s_id : 0, context ? context->s_uid : 0); + } +#endif + xpc_dictionary_set_int64(reply, SERVICE_XPC_RC, rc); + xpc_connection_send_message(connection, reply); + xpc_release(reply); + } +} + +bool check_signature(xpc_connection_t connection) +{ + CFStringRef reqStr = CFSTR("identifier com.apple.securityd and anchor apple"); + SecRequirementRef requirement = NULL; + SecCodeRef codeRef = NULL; + CFMutableDictionaryRef codeDict = NULL; + CFNumberRef codePid = NULL; + pid_t pid = xpc_connection_get_pid(connection); + + OSStatus status = SecRequirementCreateWithString(reqStr, kSecCSDefaultFlags, &requirement); + require_action(status == errSecSuccess, done, LOG("failed to create requirement")); + + codeDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + codePid = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &pid); + CFDictionarySetValue(codeDict, kSecGuestAttributePid, codePid); + status = SecCodeCopyGuestWithAttributes(NULL, codeDict, kSecCSDefaultFlags, &codeRef); + require_action(status == errSecSuccess, done, LOG("failed to get code ref")); + + status = SecCodeCheckValidity(codeRef, kSecCSDefaultFlags, +#if DEBUG || RC_BUILDIT_YES + NULL); +#else + requirement); +#endif + require_action(status == errSecSuccess, done, syslog(LOG_ERR, "pid %d, does not satisfy code requirment (%d)", pid, status)); + +done: + if (codeRef) CFRelease(codeRef); + if (requirement) CFRelease(requirement); + if (codeDict) CFRelease(codeDict); + if (codePid) CFRelease(codePid); + + return (status == errSecSuccess); +} + +static void register_for_notifications() +{ + __block kern_return_t kr; + static mach_port_t mp = MACH_PORT_NULL; + + static dispatch_once_t onceToken = 0; + dispatch_once(&onceToken, ^{ + kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &mp); + if (kr == KERN_SUCCESS) { + dispatch_source_t mach_src = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, mp, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); + dispatch_source_set_event_handler(mach_src, ^{ + mach_msg_return_t mr; + uint8_t buf[sizeof(aks_notification_msg_t) + MAX_TRAILER_SIZE] = {}; + aks_notification_msg_t * msg = (aks_notification_msg_t*)buf; + mr = mach_msg((mach_msg_header_t*)&buf, MACH_RCV_MSG, 0, sizeof(buf), mp, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + if (mr == MACH_MSG_SUCCESS && msg->hdr.msgh_id == AKS_NOTIFICATION_MSGID) { + // ignored for now + } else if (mr == MACH_MSG_SUCCESS && msg->hdr.msgh_id == AKS_NOTIFICATION_WRITE_SYSTEM_KEYBAG) { + syslog(LOG_NOTICE, "request to update handle %d", msg->handle); + update_keybag_handle(msg->handle); + } else { + syslog(LOG_ERR, "mach_msg error: %x", mr); + } + }); + dispatch_resume(mach_src); + } else { + syslog(LOG_NOTICE, "failed to create notification port"); + } + + }); + + kr = aks_register_for_notifications(mp, AKS_NOTIFICATION_WRITE_SYSTEM_KEYBAG); + if (kr == KERN_SUCCESS) { + syslog(LOG_NOTICE, "registered for notifications"); + } else { + syslog(LOG_NOTICE, "failed to register for notifications %d", kr); + } +} + +int main(int argc, const char * argv[]) +{ + char * errorbuf; + if (sandbox_init(SECURITYD_SERVICE_NAME, SANDBOX_NAMED, &errorbuf) != 0) { + syslog(LOG_ERR, "sandbox_init failed %s", errorbuf); + sandbox_free_error(errorbuf); +#ifndef DEBUG + abort(); +#endif + } + + register_for_notifications(); + + xpc_connection_t listener = xpc_connection_create_mach_service(SECURITYD_SERVICE_NAME, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER); + xpc_connection_set_event_handler(listener, ^(xpc_object_t peer) { + // It is safe to cast 'peer' to xpc_connection_t assuming + // we have a correct configuration in our launchd.plist. + + if (xpc_connection_get_euid(peer) != 0) { + xpc_connection_cancel(peer); + return; + } + + if (!check_signature(peer)) { + xpc_connection_cancel(peer); + return; + } + + xpc_connection_set_event_handler(peer, ^(xpc_object_t event) { + vproc_transaction_t transaction = vproc_transaction_begin(NULL); + service_peer_event_handler(peer, event); + vproc_transaction_end(NULL, transaction); + }); + xpc_connection_resume(peer); + }); + xpc_connection_resume(listener); + + dispatch_main(); + exit(EXIT_FAILURE); +} + diff --git a/securityd/securityd_service/securityd_service/securityd_service.h b/securityd/securityd_service/securityd_service/securityd_service.h new file mode 100644 index 00000000..6cba5629 --- /dev/null +++ b/securityd/securityd_service/securityd_service/securityd_service.h @@ -0,0 +1,31 @@ +/* Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. */ + +#ifndef securityd_service_securityd_service_h +#define securityd_service_securityd_service_h + +#define SECURITYD_SERVICE_NAME "com.apple.securitydservice" + +#define SERVICE_XPC_REQUEST "_request" +#define SERVICE_XPC_RC "_rc" +#define SERVICE_XPC_KEY "_key" +#define SERVICE_XPC_SECRET "_secret" +#define SERVICE_XPC_SECRET_NEW "_secret_new" +#define SERVICE_XPC_CONTEXT "_context" +#define SERVICE_XPC_LOCKED "_locked" +#define SERVICE_XPC_NO_PIN "_no_pin" + +enum { + SERVICE_STASH_SET_KEY = 1, + SERVICE_STASH_GET_KEY, + SERVICE_STASH_BLOB, + SERVICE_KB_LOAD, + SERVICE_KB_UNLOCK, + SERVICE_KB_LOCK, + SERVICE_KB_CHANGE_SECRET, + SERVICE_KB_CREATE, + SERVICE_KB_IS_LOCKED, + SERVICE_KB_RESET, + SERVICE_STASH_LOAD_KEY, +}; + +#endif diff --git a/securityd/securityd_service/securityd_service/securityd_service_client.c b/securityd/securityd_service/securityd_service/securityd_service_client.c new file mode 100644 index 00000000..f8a9ab10 --- /dev/null +++ b/securityd/securityd_service/securityd_service/securityd_service_client.c @@ -0,0 +1,237 @@ +/* Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. */ + +#include "securityd_service.h" +#include "securityd_service_client.h" +#include +#include +#include +#include + +static xpc_connection_t +_service_get_connection() +{ + static dispatch_once_t onceToken; + static xpc_connection_t connection = NULL; + + dispatch_once(&onceToken, ^{ + connection = xpc_connection_create_mach_service(SECURITYD_SERVICE_NAME, NULL, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED); + require(connection, done); + + xpc_connection_set_event_handler(connection, ^(xpc_object_t event) { + if (xpc_get_type(event) == XPC_TYPE_ERROR) { + if (event == XPC_ERROR_CONNECTION_INVALID) { + syslog(LOG_ERR, "securityd_service not available"); + } + // XPC_ERROR_CONNECTION_INTERRUPTED + // XPC_ERROR_TERMINATION_IMMINENT + } else { + char * desc = xpc_copy_description(event); + syslog(LOG_ERR, "securityd_service should never get messages on this connection: %s", desc); + free(desc); + } + }); + + xpc_connection_resume(connection); + done: + return; + }); + + return connection; +} + +static int +_service_send_msg(service_context_t *context, xpc_object_t message, xpc_object_t * reply_out) +{ + int rc = KB_GeneralError; + xpc_object_t reply = NULL; + xpc_connection_t conn = NULL; + + require(context, done); + require(message, done); + conn = _service_get_connection(); + require(conn, done); + + xpc_dictionary_set_data(message, SERVICE_XPC_CONTEXT, context, sizeof(service_context_t)); + + reply = xpc_connection_send_message_with_reply_sync(conn, message); + require(reply, done); + require(xpc_get_type(reply) != XPC_TYPE_ERROR, done); + + rc = (int)xpc_dictionary_get_int64(reply, SERVICE_XPC_RC); + + if (reply_out) { + *reply_out = reply; + reply = NULL; + } + +done: + if (reply) xpc_release(reply); + return rc; +} + +int +_service_client_send_secret(service_context_t *context, uint64_t request, const void * secret, int secret_len, const void * new_secret, int new_secret_len) +{ + int rc = KB_GeneralError; + xpc_object_t message = NULL; + + message = xpc_dictionary_create(NULL, NULL, 0); + require_quiet(message, done); + + xpc_dictionary_set_uint64(message, SERVICE_XPC_REQUEST, request); + if (secret) { + xpc_dictionary_set_data(message, SERVICE_XPC_SECRET, secret, secret_len); + } + + if (new_secret) { + xpc_dictionary_set_data(message, SERVICE_XPC_SECRET_NEW, new_secret, new_secret_len); + } + + rc = _service_send_msg(context, message, NULL); + +done: + if (message) xpc_release(message); + return rc; +} + +int +service_client_kb_create(service_context_t *context, const void * secret, int secret_len) +{ + return _service_client_send_secret(context, SERVICE_KB_CREATE, secret, secret_len, NULL, 0); +} + +int +service_client_kb_load(service_context_t *context) +{ + return _service_client_send_secret(context, SERVICE_KB_LOAD, NULL, 0, NULL, 0); + } + +int +service_client_kb_unlock(service_context_t *context, const void * secret, int secret_len) +{ + return _service_client_send_secret(context, SERVICE_KB_UNLOCK, secret, secret_len, NULL, 0); +} + +int +service_client_kb_lock(service_context_t *context) +{ + return _service_client_send_secret(context, SERVICE_KB_LOCK, NULL, 0, NULL, 0); +} + +int +service_client_kb_change_secret(service_context_t *context, const void * secret, int secret_len, const void * new_secret, int new_secret_len) +{ + return _service_client_send_secret(context, SERVICE_KB_CHANGE_SECRET, secret, secret_len, new_secret, new_secret_len); +} + +int +service_client_kb_reset(service_context_t *context, const void * secret, int secret_len) +{ + return _service_client_send_secret(context, SERVICE_KB_RESET, secret, secret_len, NULL, 0); +} + +int service_client_kb_is_locked(service_context_t *context, bool *locked, bool *no_pin) +{ + int rc = KB_GeneralError; + xpc_object_t message = NULL; + xpc_object_t reply = NULL; + + if (locked) *locked = false; + if (no_pin) *no_pin = false; + + message = xpc_dictionary_create(NULL, NULL, 0); + require_quiet(message, done); + + xpc_dictionary_set_uint64(message, SERVICE_XPC_REQUEST, SERVICE_KB_IS_LOCKED); + + rc = _service_send_msg(context, message, &reply); + + if (rc == KB_Success) { + if (locked) { + *locked = xpc_dictionary_get_bool(reply, SERVICE_XPC_LOCKED); + } + if (no_pin) { + *no_pin = xpc_dictionary_get_bool(reply, SERVICE_XPC_NO_PIN); + } + } + +done: + if (message) xpc_release(message); + if (reply) xpc_release(reply); + return rc; +} + +int +service_client_stash_set_key(service_context_t *context, const void * key, int key_len) +{ + int rc = KB_GeneralError; + xpc_object_t message = NULL; + + message = xpc_dictionary_create(NULL, NULL, 0); + require_quiet(message, done); + + xpc_dictionary_set_uint64(message, SERVICE_XPC_REQUEST, SERVICE_STASH_SET_KEY); + + if (key) + xpc_dictionary_set_data(message, SERVICE_XPC_KEY, key, key_len); + + rc = _service_send_msg(context, message, NULL); + +done: + if (message) xpc_release(message); + return rc; +} + +int +service_client_stash_load_key(service_context_t *context, const void * key, int key_len) +{ + int rc = KB_GeneralError; + xpc_object_t message = NULL; + + message = xpc_dictionary_create(NULL, NULL, 0); + require_quiet(message, done); + + xpc_dictionary_set_uint64(message, SERVICE_XPC_REQUEST, SERVICE_STASH_LOAD_KEY); + + if (key) + xpc_dictionary_set_data(message, SERVICE_XPC_KEY, key, key_len); + + rc = _service_send_msg(context, message, NULL); + +done: + if (message) xpc_release(message); + return rc; +} + +int +service_client_stash_get_key(service_context_t *context, void ** key, int * key_len) +{ + int rc = KB_GeneralError; + xpc_object_t message = NULL; + xpc_object_t reply = NULL; + + require(key, done); + require(key_len, done); + + message = xpc_dictionary_create(NULL, NULL, 0); + require_quiet(message, done); + + xpc_dictionary_set_uint64(message, SERVICE_XPC_REQUEST, SERVICE_STASH_GET_KEY); + + rc = _service_send_msg(context, message, &reply); + + if (rc == KB_Success) { + size_t data_len = 0; + const void * data = xpc_dictionary_get_data(reply, SERVICE_XPC_KEY, &data_len); + if (data) { + *key = calloc(1u, data_len); + memcpy(*key, data, data_len); + *key_len = (int)data_len; + } + } + +done: + if (message) xpc_release(message); + if (reply) xpc_release(reply); + return rc; +} diff --git a/securityd/securityd_service/securityd_service/securityd_service_client.h b/securityd/securityd_service/securityd_service/securityd_service_client.h new file mode 100644 index 00000000..d9a5d2df --- /dev/null +++ b/securityd/securityd_service/securityd_service/securityd_service_client.h @@ -0,0 +1,46 @@ +/* Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. */ + +#ifndef __SECURITYD_SERVICE_CLIENT_H +#define __SECURITYD_SERVICE_CLIENT_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#include +#include +#include + +enum { + KB_Success = 0, + KB_GeneralError, + KB_BagNotFound, + KB_BagError, + KB_BagNotLoaded, + KB_BagExists, + KB_InvalidSession +}; + +typedef struct { + au_asid_t s_id; + uid_t s_uid; + audit_token_t procToken; +} service_context_t; + +int service_client_kb_create(service_context_t *context, const void * secret, int secret_len); +int service_client_kb_load(service_context_t *context); +int service_client_kb_unlock(service_context_t *context, const void * secret, int secret_len); +int service_client_kb_lock(service_context_t *context); +int service_client_kb_change_secret(service_context_t *context, const void * secret, int secret_len, const void * new_secret, int new_secret_len); +int service_client_kb_is_locked(service_context_t *context, bool *locked, bool *no_pin); +int service_client_kb_reset(service_context_t *context, const void * secret, int secret_len); + +int service_client_stash_set_key(service_context_t *context, const void * key, int key_len); +int service_client_stash_load_key(service_context_t *context, const void * key, int key_len); +int service_client_stash_get_key(service_context_t *context, void ** key, int * key_len); + +#if defined(__cplusplus) +} +#endif + +#endif // __SECURITYD_SERVICE_CLIENT_H diff --git a/securityd/securityd_service/securityd_service/service.entitlements b/securityd/securityd_service/securityd_service/service.entitlements new file mode 100644 index 00000000..b4ad6417 --- /dev/null +++ b/securityd/securityd_service/securityd_service/service.entitlements @@ -0,0 +1,14 @@ + + + + + com.apple.keystore.stash.access + + com.apple.keystore.device + + com.apple.private.securityd.keychain + + com.apple.private.securityd.stash + + + diff --git a/securityd/securityd_service/securitydservicectrl/main.c b/securityd/securityd_service/securitydservicectrl/main.c new file mode 100644 index 00000000..f8c3752c --- /dev/null +++ b/securityd/securityd_service/securitydservicectrl/main.c @@ -0,0 +1,114 @@ +// +// main.c +// securitydservicectrl +// +// Created by Wade Benson on 12/2/12. +// Copyright (c) 2012 Apple. All rights reserved. +// + +#include "securityd_service.h" + +#include +#include +#include +#include +#include +#include + +static inline char * +hextostr(const uint8_t *buf, size_t len, char *hexbuf) +{ + char *s = hexbuf; + size_t i; + static const char hexdigits[] = "0123456789abcdef"; + for (i = 0; i < len; i++) { + *s++ = hexdigits[buf[i]>>4]; + *s++ = hexdigits[buf[i]&0xf]; + } + *s = '\0'; + return hexbuf; +} + +int main(int argc, const char * argv[]) +{ + uint64_t action = 0; + OSStatus status = noErr; + uint8_t testkey[128] = "\xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef"; + xpc_connection_t connection = xpc_connection_create_mach_service(SECURITYD_SERVICE_NAME, NULL, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED); + + xpc_connection_set_event_handler(connection, ^(xpc_object_t event) { + if (xpc_get_type(event) == XPC_TYPE_ERROR) { + printf("XPC error\n"); + } + }); + xpc_connection_resume(connection); + + if (argc != 2) { + printf("Usage: securityservicectrl < get | set | stash | login | loginstash >\n"); + return 1; + } + + if (strcmp(argv[1], "get") == 0) { + action = SERVICE_STASH_GET_KEY; + printf("Get key\n"); + + } else if (strcmp(argv[1], "set") == 0) { + action = SERVICE_STASH_SET_KEY; + printf("Set key\n"); + + } else if (strcmp(argv[1], "stash") == 0) { + action = SERVICE_STASH_BLOB; + printf("Stash\n"); + + } else if (strcmp(argv[1], "login") == 0) { + printf("SecKeychainLogin() null passwd\n"); + status = SecKeychainLogin((uint32) strlen("test"), "test", 0, NULL); + printf("Returned: %i\n", status); + return status ? 1 : 0; + + } else if (strcmp(argv[1], "loginstash") == 0) { + printf("SecKeychainStash()\n"); + status = SecKeychainStash(); + printf("Returned: %i\n", status); + return status ? 1 : 0; + + } else { + printf("%s not known\n", argv[1]); + return 1; + } + + // Send + xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_uint64(message, SERVICE_XPC_REQUEST, action); + + if (action == SERVICE_STASH_SET_KEY) + xpc_dictionary_set_data(message, SERVICE_XPC_KEY, testkey, 16); + + xpc_object_t reply = xpc_connection_send_message_with_reply_sync(connection, message); + require_action(reply != NULL, done, status = -1); + require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = -1); + + if (action == SERVICE_STASH_GET_KEY) { + size_t len = 0; + const uint8_t *keydata = xpc_dictionary_get_data(reply, SERVICE_XPC_KEY, &len); + if (keydata) { + char buf[sizeof(testkey) + 1]; + printf("\tkey = %s\n", hextostr(keydata, len > sizeof(testkey) ? sizeof(testkey) : len, buf)); + } + } + + status = (OSStatus)xpc_dictionary_get_int64(reply, SERVICE_XPC_RC); + +done: + if (message) + xpc_release(message); + if (reply) + xpc_release(reply); + if (connection) + xpc_release(connection); + + printf("Returned: %i\n", status); + + return status ? 1 : 0; +} + diff --git a/securityd/src/AuthorizationDBPlist.cpp b/securityd/src/AuthorizationDBPlist.cpp new file mode 100644 index 00000000..65a6ffa7 --- /dev/null +++ b/securityd/src/AuthorizationDBPlist.cpp @@ -0,0 +1,416 @@ +/* + * Copyright (c) 2003-2005,2007-2010 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@ + * + * AuthorizationDBPlist.cpp + * Security + * + */ + +#include "AuthorizationDBPlist.h" +#include +#include + +// mLock is held when the database is changed +// mReadWriteLock is held when the file on disk is changed +// during load(), save() and parseConfig() mLock is assumed + +namespace Authorization { + +AuthorizationDBPlist::AuthorizationDBPlist(const char *configFile) : + mFileName(configFile), mLastChecked(DBL_MIN) +{ + memset(&mRulesFileMtimespec, 0, sizeof(mRulesFileMtimespec)); +} + +void AuthorizationDBPlist::sync(CFAbsoluteTime now) +{ + if (mRules.empty()) { + StLock _(mLock); + load(); + } else { + // Don't do anything if we checked the timestamp less than 5 seconds ago + if (mLastChecked > now - 5.0) { + secdebug("authdb", "no sync: last reload %.0f + 5 > %.0f", + mLastChecked, now); + return; + } + + { + struct stat st; + { + StLock _(mReadWriteLock); + if (stat(mFileName.c_str(), &st)) { + Syslog::error("Stating rules file \"%s\": %s", mFileName.c_str(), + strerror(errno)); + return; + } + } + + if (memcmp(&st.st_mtimespec, &mRulesFileMtimespec, sizeof(mRulesFileMtimespec))) { + StLock _(mLock); + load(); + } + } + } +} + +void AuthorizationDBPlist::save() +{ + if (!mConfig) + return; + + StLock _(mReadWriteLock); + + secdebug("authdb", "policy db changed, saving to disk."); + int fd = -1; + string tempFile = mFileName + ","; + + for (;;) { + fd = open(tempFile.c_str(), O_WRONLY|O_CREAT|O_EXCL, 0644); + if (fd == -1) { + if (errno == EEXIST) { + unlink(tempFile.c_str()); + continue; + } + if (errno == EINTR) + continue; + else + break; + } else + break; + } + + if (fd == -1) { + Syslog::error("Saving rules file \"%s\": %s", tempFile.c_str(), + strerror(errno)); + return; + } + + CFDataRef configXML = CFPropertyListCreateXMLData(NULL, mConfig); + if (!configXML) + return; + + CFIndex configSize = CFDataGetLength(configXML); + ssize_t bytesWritten = write(fd, CFDataGetBytePtr(configXML), configSize); + CFRelease(configXML); + + if (bytesWritten != configSize) { + if (bytesWritten == -1) + Syslog::error("Problem writing rules file \"%s\": (errno=%s)", + tempFile.c_str(), strerror(errno)); + else + Syslog::error("Problem writing rules file \"%s\": " + "only wrote %lu out of %ld bytes", + tempFile.c_str(), bytesWritten, configSize); + + close(fd); + unlink(tempFile.c_str()); + } + else + { + if (-1 == fcntl(fd, F_FULLFSYNC, NULL)) + fsync(fd); + + close(fd); + int fd2 = open (mFileName.c_str(), O_RDONLY); + if (rename(tempFile.c_str(), mFileName.c_str())) + { + close(fd2); + unlink(tempFile.c_str()); + } + else + { + /* force a sync to flush the journal */ + int flags = FSCTL_SYNC_WAIT|FSCTL_SYNC_FULLSYNC; + ffsctl(fd2, FSCTL_SYNC_VOLUME, &flags, sizeof(flags)); + close(fd2); + mLastChecked = CFAbsoluteTimeGetCurrent(); // we have the copy that's on disk now, so don't go loading it right away + } + } +} + +void AuthorizationDBPlist::load() +{ + StLock _(mReadWriteLock); + CFDictionaryRef configPlist; + + secdebug("authdb", "(re)loading policy db from disk."); + int fd = open(mFileName.c_str(), O_RDONLY, 0); + if (fd == -1) { + Syslog::error("Problem opening rules file \"%s\": %s", + mFileName.c_str(), strerror(errno)); + return; + } + + struct stat st; + if (fstat(fd, &st)) { + int error = errno; + close(fd); + UnixError::throwMe(error); + } + + mRulesFileMtimespec = st.st_mtimespec; + off_t fileSize = st.st_size; + CFMutableDataRef xmlData = CFDataCreateMutable(NULL, fileSize); + CFDataSetLength(xmlData, fileSize); + void *buffer = CFDataGetMutableBytePtr(xmlData); + ssize_t bytesRead = read(fd, buffer, fileSize); + if (bytesRead != fileSize) { + if (bytesRead == -1) { + Syslog::error("Problem reading rules file \"%s\": %s", + mFileName.c_str(), strerror(errno)); + goto cleanup; + } + Syslog::error("Problem reading rules file \"%s\": " + "only read %ul out of %ul bytes", + bytesRead, fileSize, mFileName.c_str()); + goto cleanup; + } + + CFStringRef errorString; + configPlist = reinterpret_cast(CFPropertyListCreateFromXMLData(NULL, xmlData, kCFPropertyListMutableContainersAndLeaves, &errorString)); + + if (!configPlist) { + char buffer[512]; + const char *error = CFStringGetCStringPtr(errorString, + kCFStringEncodingUTF8); + if (error == NULL) { + if (CFStringGetCString(errorString, buffer, 512, + kCFStringEncodingUTF8)) + error = buffer; + } + + Syslog::error("Parsing rules file \"%s\": %s", + mFileName.c_str(), error); + if (errorString) + CFRelease(errorString); + + goto cleanup; + } + + if (CFGetTypeID(configPlist) != CFDictionaryGetTypeID()) { + + Syslog::error("Rules file \"%s\": is not a dictionary", + mFileName.c_str()); + + goto cleanup; + } + + parseConfig(configPlist); + +cleanup: + if (xmlData) + CFRelease(xmlData); + if (configPlist) + CFRelease(configPlist); + + close(fd); + + // If all went well, we have the copy that's on disk now, so don't go loading it right away + mLastChecked = CFAbsoluteTimeGetCurrent(); +} + +void AuthorizationDBPlist::parseConfig(CFDictionaryRef config) +{ + CFStringRef rightsKey = CFSTR("rights"); + CFStringRef rulesKey = CFSTR("rules"); + CFMutableDictionaryRef newRights = NULL; + CFMutableDictionaryRef newRules = NULL; + + if (!config) + { + Syslog::alert("Failed to parse config, no config"); + MacOSError::throwMe(errAuthorizationInternal); + } + + if (CFDictionaryContainsKey(config, rulesKey)) + newRules = reinterpret_cast(const_cast(CFDictionaryGetValue(config, rulesKey))); + + if (CFDictionaryContainsKey(config, rightsKey)) + newRights = reinterpret_cast(const_cast(CFDictionaryGetValue(config, rightsKey))); + + if (newRules && newRights + && (CFDictionaryGetTypeID() == CFGetTypeID(newRules)) + && (CFDictionaryGetTypeID() == CFGetTypeID(newRights))) + { + mConfigRights = static_cast(newRights); + mConfigRules = static_cast(newRules); + mRules.clear(); + try { + CFDictionaryApplyFunction(newRights, parseRule, this); + } catch (...) { + Syslog::alert("Failed to parse config and apply dictionary function"); + MacOSError::throwMe(errAuthorizationInternal); // XXX/cs invalid rule file + } + mConfig = config; + } + else + { + Syslog::alert("Failed to parse config, invalid rule file"); + MacOSError::throwMe(errAuthorizationInternal); // XXX/cs invalid rule file + } +} + +void AuthorizationDBPlist::parseRule(const void *key, const void *value, void *context) +{ + static_cast(context)->addRight(static_cast(key), static_cast(value)); +} + +void AuthorizationDBPlist::addRight(CFStringRef key, CFDictionaryRef definition) +{ + string keyString = cfString(key); + mRules[keyString] = Rule(keyString, definition, mConfigRules); +} + +bool +AuthorizationDBPlist::validateRule(string inRightName, CFDictionaryRef inRightDefinition) const +{ + if (!mConfigRules || + 0 == CFDictionaryGetCount(mConfigRules)) { + Syslog::error("No rule definitions!"); + MacOSError::throwMe(errAuthorizationInternal); + } + try { + Rule newRule(inRightName, inRightDefinition, mConfigRules); + if (newRule->name() == inRightName) + return true; + } catch (...) { + secdebug("authrule", "invalid definition for rule %s.\n", + inRightName.c_str()); + } + return false; +} + +CFDictionaryRef +AuthorizationDBPlist::getRuleDefinition(string &key) +{ + if (!mConfigRights || + 0 == CFDictionaryGetCount(mConfigRights)) { + Syslog::error("No rule definitions!"); + MacOSError::throwMe(errAuthorizationInternal); + } + CFStringRef cfKey = makeCFString(key); + StLock _(mLock); + if (CFDictionaryContainsKey(mConfigRights, cfKey)) { + CFDictionaryRef definition = reinterpret_cast(const_cast(CFDictionaryGetValue(mConfigRights, cfKey))); + CFRelease(cfKey); + return CFDictionaryCreateCopy(NULL, definition); + } else { + CFRelease(cfKey); + return NULL; + } +} + +bool +AuthorizationDBPlist::existRule(string &ruleName) const +{ + AuthItemRef candidateRule(ruleName.c_str()); + string ruleForCandidate = getRule(candidateRule)->name(); + // same name or covered by wildcard right -> modification. + if ( (ruleName == ruleForCandidate) || + (*(ruleForCandidate.rbegin()) == '.') ) + return true; + + return false; +} + +Rule +AuthorizationDBPlist::getRule(const AuthItemRef &inRight) const +{ + string key(inRight->name()); + // Lock the rulemap + StLock _(mLock); + + secdebug("authdb", "looking up rule %s.", inRight->name()); + if (mRules.empty()) + return Rule(); + + for (;;) { + map::const_iterator rule = mRules.find(key); + + if (rule != mRules.end()) + return (*rule).second; + + // no default rule + assert (key.size()); + + // any reduction of a combination of two chars is futile + if (key.size() > 2) { + // find last dot with exception of possible dot at end + string::size_type index = key.rfind('.', key.size() - 2); + // cut right after found dot, or make it match default rule + key = key.substr(0, index == string::npos ? 0 : index + 1); + } else + key.erase(); + } +} + +void +AuthorizationDBPlist::setRule(const char *inRightName, CFDictionaryRef inRuleDefinition) +{ + // if mConfig is now a reasonable guard + if (!inRuleDefinition || !mConfigRights) + { + Syslog::alert("Failed to set rule, no definition or rights"); + MacOSError::throwMe(errAuthorizationDenied); // ???/gh errAuthorizationInternal instead? + } + + CFRef keyRef(CFStringCreateWithCString(NULL, inRightName, + kCFStringEncodingASCII)); + if (!keyRef) + return; + + { + StLock _(mLock); + secdebug("authdb", "setting up rule %s.", inRightName); + CFDictionarySetValue(mConfigRights, keyRef, inRuleDefinition); + save(); + parseConfig(mConfig); + } +} + +void +AuthorizationDBPlist::removeRule(const char *inRightName) +{ + // if mConfig is now a reasonable guard + if (!mConfigRights) + { + Syslog::alert("Failed to remove rule, no rights"); + MacOSError::throwMe(errAuthorizationDenied); // ???/gh errAuthorizationInternal instead? + } + + CFRef keyRef(CFStringCreateWithCString(NULL, inRightName, + kCFStringEncodingASCII)); + if (!keyRef) + return; + + { + StLock _(mLock); + secdebug("authdb", "removing rule %s.", inRightName); + CFDictionaryRemoveValue(mConfigRights, keyRef); + save(); + parseConfig(mConfig); + } +} + + +} // end namespace Authorization diff --git a/securityd/src/AuthorizationDBPlist.h b/securityd/src/AuthorizationDBPlist.h new file mode 100644 index 00000000..2d8820f6 --- /dev/null +++ b/securityd/src/AuthorizationDBPlist.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2003-2004,2007 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@ + * + * AuthorizationDBPlist.h + * Security + * + */ +#ifndef _H_AUTHORIZATIONDBPLIST +#define _H_AUTHORIZATIONDBPLIST 1 + +#include +#include + +#include +#include "AuthorizationRule.h" + +class AuthorizationDBPlist; // @@@ the ordering sucks here, maybe engine should include all these and other should only include it + +namespace Authorization +{ + +class AuthorizationDBPlist /* : public AuthorizationDB */ +{ +public: + AuthorizationDBPlist(const char *configFile); + + void sync(CFAbsoluteTime now); + bool validateRule(string inRightName, CFDictionaryRef inRightDefinition) const; + CFDictionaryRef getRuleDefinition(string &key); + + bool existRule(string &ruleName) const; + Rule getRule(const AuthItemRef &inRight) const; + + void setRule(const char *inRightName, CFDictionaryRef inRuleDefinition); + void removeRule(const char *inRightName); + +protected: + void load(); + void save(); + +private: + string mFileName; + +private: + enum { kTypeRight, kTypeRule }; + void parseConfig(CFDictionaryRef config); + static void parseRule(const void *key, const void *value, void *context); + void addRight(CFStringRef key, CFDictionaryRef definition); + + CFAbsoluteTime mLastChecked; + struct timespec mRulesFileMtimespec; + + map mRules; + CFRef mConfig; + CFRef mConfigRights; + CFRef mConfigRules; + + mutable Mutex mLock; // rule map lock + mutable Mutex mReadWriteLock; // file operation lock +}; + +}; /* namespace Authorization */ + +#endif /* ! _H_AUTHORIZATIONDBPLIST */ diff --git a/securityd/src/AuthorizationEngine.cpp b/securityd/src/AuthorizationEngine.cpp new file mode 100644 index 00000000..c34507c4 --- /dev/null +++ b/securityd/src/AuthorizationEngine.cpp @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2000-2004,2006-2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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 "AuthorizationEngine.h" +#include +#include +#include + +#include "authority.h" + +#include +#include +#include +#include +#include +#include "server.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include // AUE_ssauth* +#include "ccaudit_extensions.h" + +namespace Authorization { + +using namespace CommonCriteria::Securityd; + + +// +// Errors to be thrown +// +Error::Error(int err) : error(err) +{ +} + +const char *Error::what() const throw() +{ return "Authorization error"; } + +int Error::unixError() const throw() +{ return error; } // @@@ eventually... + +OSStatus Error::osStatus() const throw() +{ return error; } + +void Error::throwMe(int err) { throw Error(err); } + +// +// Engine class +// +Engine::Engine(const char *configFile) : mAuthdb(configFile) +{ +} + +Engine::~Engine() +{ +} + + +/*! + @function AuthorizationEngine::authorize + + @@@. + + @param inRights (input) List of rights being requested for authorization. + @param environment (optional/input) Environment containing information to be used during evaluation. + @param flags (input) Optional flags @@@ see AuthorizationCreate for a description. + @param inCredentials (input) Credentials already held by the caller. + @param outCredentials (output/optional) Credentials obtained, used or refreshed during this call to authorize the requested rights. + @param outRights (output/optional) Subset of inRights which were actually authorized. + + @results Returns errAuthorizationSuccess if all rights requested are authorized, or if the kAuthorizationFlagPartialRights flag was specified. Might return other status values like errAuthorizationDenied, errAuthorizationCanceled or errAuthorizationInteractionNotAllowed +*/ +OSStatus +Engine::authorize(const AuthItemSet &inRights, const AuthItemSet &environment, + AuthorizationFlags flags, const CredentialSet *inCredentials, CredentialSet *outCredentials, + AuthItemSet &outRights, AuthorizationToken &auth) +{ + CredentialSet credentials; + OSStatus status = errAuthorizationSuccess; + SecurityAgent::Reason reason = SecurityAgent::noReason; + + // Get current time of day. + CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); + + // Update rules from database if needed + mAuthdb.sync(now); + + // Check if a credential was passed into the environment and we were asked to extend the rights + if (flags & kAuthorizationFlagExtendRights) + { + string username, password; + bool shared = false; + for (AuthItemSet::iterator item = environment.begin(); item != environment.end(); item ++) + { + if (!strcmp((*item)->name(), kAuthorizationEnvironmentUsername)) + username = (*item)->stringValue(); + else if (!strcmp((*item)->name(), kAuthorizationEnvironmentPassword)) + password = (*item)->stringValue(); + else if (!strcmp((*item)->name(), kAuthorizationEnvironmentShared)) + shared = true; + } + + if (username.length()) + { + // Let's create a credential from the passed in username and password. + Credential newCredential(username, password, shared); + // If it's valid insert it into the credentials list. Normally this is + // only done if it actually authorizes a requested right, but for this + // special case (environment) we do it even when no rights are being requested. + if (newCredential->isValid()) + credentials.insert(newCredential); + } + } + + // generate hints for every authorization + AuthItemSet environmentToClient = environment; + + RightAuthenticationLogger logger(auth.creatorAuditToken(), AUE_ssauthorize); + + // create a vector with the first right first + std::vector tempRights; + for (AuthItemSet::const_iterator it = inRights.begin(); it != inRights.end(); ++it) { + if (inRights.firstItemName != NULL && strcmp((*it)->name(), inRights.firstItemName) == 0) + tempRights.insert(tempRights.begin(), *it); + else + tempRights.push_back(*it); + } + + bool authExtractPassword = false; + std::vector::const_iterator end = tempRights.end(); + for (std::vector::const_iterator it = tempRights.begin(); it != end; ++it) + { + // Get the rule for each right we are trying to obtain. + const Rule &toplevelRule = mAuthdb.getRule(*it); + + if (false == authExtractPassword) + authExtractPassword = toplevelRule->extractPassword(); + + string processName = "unknown"; + string authCreatorName = "unknown"; + { + StLock _(Server::process()); + if (SecCodeRef code = Server::process().currentGuest()) { + CFRef path; + if (!SecCodeCopyPath(code, kSecCSDefaultFlags, &path.aref())) + processName = cfString(path); + } + } + authCreatorName = auth.creatorPath(); + + if (sandbox_check(Server::process().pid(), "authorization-right-obtain", SANDBOX_FILTER_RIGHT_NAME, (*it)->name())) { + Syslog::error("Sandbox denied authorizing right '%s' by client '%s' [%d]", (*it)->name(), processName.c_str(), Server::process().pid()); + return errAuthorizationDenied; + } + if (auth.creatorSandboxed() && sandbox_check(auth.creatorPid(), "authorization-right-obtain", SANDBOX_FILTER_RIGHT_NAME, (*it)->name())) { + Syslog::error("Sandbox denied authorizing right '%s' for authorization created by '%s' [%d]", (*it)->name(), authCreatorName.c_str(), auth.creatorPid()); + return errAuthorizationDenied; + } + + OSStatus result = toplevelRule->evaluate(*it, toplevelRule, environmentToClient, flags, now, inCredentials, credentials, auth, reason, authExtractPassword); + secdebug("autheval", "evaluate rule %s for right %s returned %d.", toplevelRule->name().c_str(), (*it)->name(), int(result)); + SECURITYD_AUTH_EVALRIGHT(&auth, (char *)(*it)->name(), result); + + logger.setRight((*it)->name()); + logger.logAuthorizationResult(processName.c_str(), authCreatorName.c_str(), result); + + if (result == errAuthorizationSuccess) + { + outRights.insert(*it); + Syslog::info("Succeeded authorizing right '%s' by client '%s' [%d] for authorization created by '%s' [%d] (%X,%d)", (*it)->name(), processName.c_str(), Server::process().pid(), authCreatorName.c_str(), auth.creatorPid(), uint32_t(flags), auth.operatesAsLeastPrivileged()); + } + else if (result == errAuthorizationDenied || result == errAuthorizationInteractionNotAllowed) + { + if (result == errAuthorizationDenied) + { + secdebug("autheval", "Failed to authorize right '%s' by client '%s' [%d] for authorization created by '%s' [%d] (%X,%d)", (*it)->name(), processName.c_str(), Server::process().pid(), authCreatorName.c_str(), auth.creatorPid(), uint32_t(flags), auth.operatesAsLeastPrivileged()); + } + + // add creator pid to authorization token + if (!(flags & kAuthorizationFlagPartialRights)) + { + status = result; + break; + } + } + else if (result == errAuthorizationCanceled) + { + status = result; + break; + } + else + { + Syslog::error("Engine::authorize: Rule::evaluate returned %ld returning errAuthorizationInternal", result); + status = errAuthorizationInternal; + break; + } + } + + // purge all uid credentials from the outCredentials for least privileged mode + if (auth.operatesAsLeastPrivileged()) { + CredentialSet::const_iterator current, it = outCredentials->begin(); + while(it != outCredentials->end()) { + current = it++; + if (!(*current)->isRight()) { + outCredentials->erase(current); + } + } + } + + if (outCredentials) + outCredentials->swap(credentials); + + return status; +} + +OSStatus +Engine::verifyModification(string inRightName, bool remove, + const CredentialSet *inCredentials, CredentialSet *outCredentials, AuthorizationToken &auth) +{ + // Validate right + + // meta rights are constructed as follows: + // we don't allow setting of wildcard rights, so you can only be more specific + // note that you should never restrict things with a wildcard right without disallowing + // changes to the entire domain. ie. + // system.privilege. -> never + // config.add.system.privilege. -> never + // config.modify.system.privilege. -> never + // config.delete.system.privilege. -> never + // For now we don't allow any configuration of configuration rules + // config.config. -> never + + string rightnameToCheck; + + // @@@ verify right name is is not NULL or zero length + if (inRightName.length() == 0) + return errAuthorizationDenied; + + // @@@ make sure it isn't a wildcard right by checking trailing "." + if ( *(inRightName.rbegin()) == '.') + return errAuthorizationDenied; + + // @@@ make sure it isn't a configure right by checking it doesn't start with config. + if (inRightName.find(kConfigRight, 0) != string::npos) + { + // special handling of meta right change: + // config.add. config.modify. config.remove. config.{}. + // check for config. (which always starts with config.config.) + rightnameToCheck = string(kConfigRight) + inRightName; + } + else + { + // regular check of rights + bool existingRule = mAuthdb.existRule(inRightName); + if (!remove) + { + if (existingRule) + rightnameToCheck = string(kAuthorizationConfigRightModify) + inRightName; + else + rightnameToCheck = string(kAuthorizationConfigRightAdd) + inRightName; + } + else + { + if (existingRule) + rightnameToCheck = string(kAuthorizationConfigRightRemove) + inRightName; + else + { + secdebug("engine", "rule %s doesn't exist.", inRightName.c_str()); + return errAuthorizationSuccess; // doesn't exist, done + } + } + } + + + AuthItemSet rights, environment, outRights; + rights.insert(AuthItemRef(rightnameToCheck.c_str())); + secdebug("engine", "authorizing %s for db modification.", rightnameToCheck.c_str()); + return authorize(rights, environment, kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights, inCredentials, outCredentials, outRights, auth); +} + +OSStatus +Engine::getRule(string &inRightName, CFDictionaryRef *outRuleDefinition) +{ + // Get current time of day. + CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); + + // Update rules from database if needed + mAuthdb.sync(now); + + CFDictionaryRef definition = mAuthdb.getRuleDefinition(inRightName); + if (definition) + { + if (outRuleDefinition) + *outRuleDefinition = definition; + else + CFRelease(definition); + + return errAuthorizationSuccess; + } + + return errAuthorizationDenied; +} + +OSStatus +Engine::setRule(const char *inRightName, CFDictionaryRef inRuleDefinition, const CredentialSet *inCredentials, CredentialSet *outCredentials, AuthorizationToken &auth) +{ + // Validate rule by constructing it from the passed dictionary + if (!mAuthdb.validateRule(inRightName, inRuleDefinition)) + return errAuthorizationDenied; // @@@ separate error for this? + + OSStatus result = verifyModification(inRightName, false /*setting, not removing*/, inCredentials, outCredentials, auth); + if (result != errAuthorizationSuccess) + return result; + + // set the rule for the right and save the database + mAuthdb.setRule(inRightName, inRuleDefinition); + + return errAuthorizationSuccess; +} + +OSStatus +Engine::removeRule(const char *inRightName, const CredentialSet *inCredentials, CredentialSet *outCredentials, AuthorizationToken &auth) +{ + // Get current time of day. + CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); + + // Update rules from database if needed + mAuthdb.sync(now); + + OSStatus result = verifyModification(inRightName, true /*removing*/, inCredentials, outCredentials, auth); + if (result != errAuthorizationSuccess) + return result; + + // set the rule for the right and save the database + mAuthdb.removeRule(inRightName); + + return errAuthorizationSuccess; +} + +} // end namespace Authorization diff --git a/securityd/src/AuthorizationEngine.h b/securityd/src/AuthorizationEngine.h new file mode 100644 index 00000000..05b93fd3 --- /dev/null +++ b/securityd/src/AuthorizationEngine.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2000-2004,2007 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@ + * + * AuthorizationEngine.h + * Authorization + * + */ +#ifndef _H_AUTHORIZATIONENGINE +#define _H_AUTHORIZATIONENGINE 1 + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "authority.h" + +#include "AuthorizationRule.h" +#include "AuthorizationDBPlist.h" + +namespace Authorization +{ + +class Error : public CommonError { +protected: + Error(int err); +public: + const int error; + virtual int unixError() const throw(); + virtual OSStatus osStatus() const throw(); + virtual const char *what () const throw(); + static void throwMe(int err) __attribute((noreturn)); +}; + + +/* The engine which performs the actual authentication and authorization computations. + + The implementation of a typical call to AuthorizationCreate would look like: + + Get the current shared CredentialSet for this session. + Call authorizedRights() with inRights and the shared CredentialSet. + Compute the difference set between the rights requested and the rights returned from authorizedRights(). + Call credentialIds() with the rights computed above (for which we have no credentials yet). + Call aquireCredentials() for the credentialIds returned from credentialIds() + For each credential returned place it in the session (replacing when needed) if shared() returns true. + The authorization returned to the user should now refer to the credentials in the session and the non shared ones returned by aquireCredentials(). + + When a call to AuthorizationCopyRights() is made, just call authorizedRights() using the union of the session credentials and the credentials tied to the authorization specified. + + When a call to AuthorizationCopyInfo() is made, ask the Credential specified by tag for it info and return it. + + When a call to AuthorizationFree() is made, delete all the non-shared credentials ascociated with the authorization specified. If the kAuthorizationFreeFlagDestroy is set. Also delete the shared credentials ascociated with the authorization specified. + */ +class Engine +{ +public: + Engine(const char *configFile); + ~Engine(); + + OSStatus authorize(const AuthItemSet &inRights, const AuthItemSet &environment, + AuthorizationFlags flags, const CredentialSet *inCredentials, CredentialSet *outCredentials, + AuthItemSet &outRights, AuthorizationToken &auth); + OSStatus getRule(string &inRightName, CFDictionaryRef *outRuleDefinition); + OSStatus setRule(const char *inRightName, CFDictionaryRef inRuleDefinition, const CredentialSet *inCredentials, CredentialSet *outCredentials, AuthorizationToken &auth); + OSStatus removeRule(const char *inRightName, const CredentialSet *inCredentials, CredentialSet *outCredentials, AuthorizationToken &auth); + +private: + OSStatus verifyModification(string inRightName, bool remove, + const CredentialSet *inCredentials, CredentialSet *outCredentials, AuthorizationToken &auth); + + AuthorizationDBPlist mAuthdb; + mutable Mutex mLock; +}; + +}; // namespace Authorization + +#endif /* ! _H_AUTHORIZATIONENGINE */ diff --git a/securityd/src/AuthorizationMechEval.cpp b/securityd/src/AuthorizationMechEval.cpp new file mode 100644 index 00000000..971df40b --- /dev/null +++ b/securityd/src/AuthorizationMechEval.cpp @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2003-2009 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@ + * + * AuthorizationMechEval.cpp + * securityd + * + */ +#include "AuthorizationMechEval.h" +#include +#include +#include "ccaudit_extensions.h" + +namespace Authorization { + +using namespace CommonCriteria::Securityd; + +AgentMechanismRef::AgentMechanismRef(const AuthHostType type, Session &session) : + RefPointer(new QueryInvokeMechanism(type, session)) {} + +// we need the vector of mechanisms +AgentMechanismEvaluator::AgentMechanismEvaluator(uid_t uid, Session& session, const vector& inMechanisms) : + mMechanisms(inMechanisms), mClientUid(uid), mSession(session) +{ + //set up environment +} + +OSStatus +AgentMechanismEvaluator::run(const AuthValueVector &inArguments, const AuthItemSet &inHints, const AuthorizationToken &auth) +{ + AuthMechLogger logger(auth.creatorAuditToken(), AUE_ssauthmech); + string rightName = ""; // for syslog + + // as of 10.6, the first item in inArguments should be the name of the + // requested right, for auditing + try + { + AuthorizationValue val = inArguments.at(0)->value(); + string tmpstr(static_cast(val.data), val.length); + logger.setRight(tmpstr); + rightName.clear(); + rightName = tmpstr; + } + catch (...) { } + + const AuthItemSet &inContext = const_cast(auth).infoSet(); + + // add process specifics to context? + + vector::const_iterator currentMechanism = mMechanisms.begin(); + + AuthorizationResult result = kAuthorizationResultAllow; + + AuthItemSet hints = inHints; + AuthItemSet context = inContext; + // add saved-off sticky context values to context for evaluation + context.insert(mStickyContext.begin(), mStickyContext.end()); + + while ( (result == kAuthorizationResultAllow) && + (currentMechanism != mMechanisms.end()) ) // iterate mechanisms + { + SECURITYD_AUTH_MECH(&auth, (char *)(*currentMechanism).c_str()); + + // set up the audit message + logger.setCurrentMechanism(*currentMechanism); + + // do the real work + ClientMap::iterator iter = mClients.find(*currentMechanism); + if (iter == mClients.end()) + { + string::size_type extPlugin = currentMechanism->find(':'); + if (extPlugin != string::npos) + { + // no whitespace removal + string pluginIn(currentMechanism->substr(0, extPlugin)); + string mechanismIn, authhostIn; + + string::size_type extMechanism = currentMechanism->rfind(','); + AuthHostType hostType = securityAgent; + + if (extMechanism != string::npos) + { + if (extMechanism < extPlugin) + { + string auditMsg = "badly formed mechanism name; ending rule evaluation"; + Syslog::alert("Right '%s', mech '%s': %s", rightName.c_str(), (*currentMechanism).c_str(), auditMsg.c_str()); + logger.logFailure(auditMsg); + return errAuthorizationInternal; + } + + mechanismIn = currentMechanism->substr(extPlugin + 1, extMechanism - extPlugin - 1); + authhostIn = currentMechanism->substr(extMechanism + 1); + if (authhostIn == "privileged") + hostType = privilegedAuthHost; + } + else + mechanismIn = currentMechanism->substr(extPlugin + 1); + + secdebug("AuthEvalMech", "external mechanism %s:%s", pluginIn.c_str(), mechanismIn.c_str()); + + AgentMechanismRef client(hostType, mSession); + client->initialize(pluginIn, mechanismIn, inArguments); + mClients.insert(ClientMap::value_type(*currentMechanism, client)); + } + else if (*currentMechanism == "authinternal") + { + secdebug("AuthEvalMech", "performing authentication"); + result = authinternal(context); + + if (kAuthorizationResultAllow == result) + { + logger.logSuccess(); + } + else // kAuthorizationResultDeny + { + logger.logFailure(); + } + } + else if (*currentMechanism == "push_hints_to_context") + { + secdebug("AuthEvalMech", "evaluate push_hints_to_context"); + logger.logSuccess(); + // doesn't block evaluation, ever + result = kAuthorizationResultAllow; + context = hints; + } + else + { + string auditMsg = "unknown mechanism; ending rule evaluation"; + Syslog::alert("Right '%s', mech '%s': %s", rightName.c_str(), (*currentMechanism).c_str(), auditMsg.c_str()); + logger.logFailure(auditMsg); + return errAuthorizationInternal; + } + } + + iter = mClients.find(*currentMechanism); + if (iter != mClients.end()) + { + try + { + AgentMechanismRef &client = iter->second; + client->run(inArguments, hints, context, &result); + + bool interrupted = false; + while (client->state() == client->current) + { + // check for interruption + vector::const_iterator checkMechanism = mMechanisms.begin(); + while (*checkMechanism != *currentMechanism) { + ClientMap::iterator iter2 = mClients.find(*checkMechanism); + if (iter2->second->state() == iter2->second->interrupting) + { + client->deactivate(); + // nothing can happen until the client mechanism returns control to us + while (client->state() == client->deactivating) + client->receive(); + + string auditMsg = "evaluation interrupted by "; + auditMsg += (iter2->first).c_str(); + auditMsg += "; restarting evaluation there"; + secdebug("AuthEvalMech", "%s", auditMsg.c_str()); + logger.logInterrupt(auditMsg); + + interrupted = true; + hints = iter2->second->inHints(); + context = iter2->second->inContext(); + currentMechanism = checkMechanism; + break; + } + else + checkMechanism++; + } + if (client->state() == client->current) + client->receive(); + } + + if (interrupted) + { + // clear reason for restart from interrupt + uint32_t reason = SecurityAgent::worldChanged; + AuthItemRef retryHint(AGENT_HINT_RETRY_REASON, AuthValueOverlay(sizeof(reason), &reason)); + hints.erase(retryHint); hints.insert(retryHint); // replace + + result = kAuthorizationResultAllow; + continue; + } + else + secdebug("AuthEvalMech", "evaluate(%s) with result: %u.", (iter->first).c_str(), (uint32_t)result); + } + catch (...) { + string auditMsg = "exception during evaluation of "; + auditMsg += (iter->first).c_str(); + secdebug("AuthEvalMech", "%s", auditMsg.c_str()); + logger.logFailure(auditMsg); + result = kAuthorizationResultUndefined; + } + } + + if (result == kAuthorizationResultAllow) + { + logger.logSuccess(); + currentMechanism++; + } + } + + if ((result == kAuthorizationResultUserCanceled) || + (result == kAuthorizationResultAllow)) + { + mHints = hints; + mContext.clear(); + // only make non-sticky context values available externally + AuthItemSet::const_iterator end = context.end(); + for (AuthItemSet::const_iterator it = context.begin(); it != end; ++it) { + const AuthItemRef &item = *it; + if (item->flags() != kAuthorizationContextFlagSticky) + mContext.insert(item); + } + if (result == kAuthorizationResultUserCanceled) + logger.logFailure(NULL, errAuthorizationCanceled); + } + else if (result == kAuthorizationResultDeny) + { + // save off sticky values in context + mStickyContext.clear(); + AuthItemSet::const_iterator end = context.end(); + for (AuthItemSet::const_iterator it = context.begin(); it != end; ++it) { + const AuthItemRef &item = *it; + if (item->flags() == kAuthorizationContextFlagSticky) + mStickyContext.insert(item); + } + logger.logFailure(); + } + + // convert AuthorizationResult to OSStatus + switch(result) + { + case kAuthorizationResultDeny: + return errAuthorizationDenied; + case kAuthorizationResultUserCanceled: + return errAuthorizationCanceled; + case kAuthorizationResultAllow: + return errAuthorizationSuccess; + case kAuthorizationResultUndefined: + return errAuthorizationInternal; + default: + { + Syslog::alert("Right '%s': unexpected error result (%u)", rightName.c_str(), result); + logger.logFailure("unexpected error result", result); + return errAuthorizationInternal; + } + } +} + +AuthorizationResult AgentMechanismEvaluator::authinternal(AuthItemSet &context) +{ + secdebug("AuthEvalMech", "evaluate authinternal"); + do { + AuthItemSet::iterator found = find_if(context.begin(), context.end(), FindAuthItemByRightName(kAuthorizationEnvironmentUsername) ); + if (found == context.end()) + break; + string username(static_cast((*found)->value().data), (*found)->value().length); + secdebug("AuthEvalMech", "found username"); + found = find_if(context.begin(), context.end(), FindAuthItemByRightName(kAuthorizationEnvironmentPassword) ); + if (found == context.end()) + break; + string password(static_cast((*found)->value().data), (*found)->value().length); + secdebug("AuthEvalMech", "found password"); + + Credential newCredential(username, password, true); // create a new shared credential + if (newCredential->isValid()) + return kAuthorizationResultAllow; + + } while (0); + + return kAuthorizationResultDeny; +} + +/* +AuthItemSet & +AgentMechanismEvaluator::commonHints(const AuthorizationToken &auth) +{ + +} +*/ + +} /* namespace Authorization */ diff --git a/securityd/src/AuthorizationMechEval.h b/securityd/src/AuthorizationMechEval.h new file mode 100644 index 00000000..e2b0e5ae --- /dev/null +++ b/securityd/src/AuthorizationMechEval.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2003-2009 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@ + * + * AuthorizationMechEval.h + * securityd + * + */ + +#include +#include +#include +#include "agentquery.h" +#include "AuthorizationRule.h" +#include "authority.h" +#include "session.h" + + +namespace Authorization { + +class AgentMechanismRef : public RefPointer +{ +public: + AgentMechanismRef(const AuthHostType type, Session &session); +}; + +class AgentMechanismEvaluator +{ +public: + AgentMechanismEvaluator(uid_t uid, Session &session, const vector& inMechanisms); + OSStatus run(const AuthValueVector &inArguments, const AuthItemSet &inHints, const AuthorizationToken &auth); + + AuthorizationResult authinternal(AuthItemSet &context); + + AuthItemSet &hints() { return mHints; } + AuthItemSet &context() { return mContext; } + +private: + vector mMechanisms; + typedef map ClientMap; + ClientMap mClients; + + uid_t mClientUid; + Session &mSession; + + AuthItemSet mHints; + AuthItemSet mContext; + AuthItemSet mStickyContext; +}; + +} /* namespace Authorization */ diff --git a/securityd/src/AuthorizationRule.cpp b/securityd/src/AuthorizationRule.cpp new file mode 100644 index 00000000..7bd9f928 --- /dev/null +++ b/securityd/src/AuthorizationRule.cpp @@ -0,0 +1,1117 @@ +/* + * Copyright (c) 2003-2010,2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + * + * AuthorizationRule.cpp + * Security + * + */ + +#include "AuthorizationRule.h" +#include +#include +#include +#include +#include +#include +#include "ccaudit_extensions.h" +#include "authority.h" +#include "server.h" +#include "process.h" +#include "agentquery.h" +#include "AuthorizationMechEval.h" + +#include +#include +#include +#include +#include + +extern "C" { +#include +} + +using namespace CommonCriteria::Securityd; + +// +// Rule class +// +namespace Authorization { + +CFStringRef RuleImpl::kUserGroupID = CFSTR(kAuthorizationRuleParameterGroup); +CFStringRef RuleImpl::kTimeoutID = CFSTR(kAuthorizationRuleParameterCredentialTimeout); +CFStringRef RuleImpl::kSharedID = CFSTR(kAuthorizationRuleParameterCredentialShared); +CFStringRef RuleImpl::kAllowRootID = CFSTR(kAuthorizationRuleParameterAllowRoot); +CFStringRef RuleImpl::kMechanismsID = CFSTR(kAuthorizationRuleParameterMechanisms); +CFStringRef RuleImpl::kSessionOwnerID = CFSTR(kAuthorizationRuleParameterCredentialSessionOwner); +CFStringRef RuleImpl::kKofNID = CFSTR(kAuthorizationRuleParameterKofN); +CFStringRef RuleImpl::kPromptID = CFSTR(kAuthorizationRuleParameterDefaultPrompt); +CFStringRef RuleImpl::kButtonID = CFSTR(kAuthorizationRuleParameterDefaultButton); +CFStringRef RuleImpl::kTriesID = CFSTR("tries"); // XXX/cs move to AuthorizationTagsPriv.h +CFStringRef RuleImpl::kExtractPasswordID = CFSTR(kAuthorizationRuleParameterExtractPassword); + +CFStringRef RuleImpl::kRuleClassID = CFSTR(kAuthorizationRuleClass); +CFStringRef RuleImpl::kRuleAllowID = CFSTR(kAuthorizationRuleClassAllow); +CFStringRef RuleImpl::kRuleDenyID = CFSTR(kAuthorizationRuleClassDeny); +CFStringRef RuleImpl::kRuleUserID = CFSTR(kAuthorizationRuleClassUser); +CFStringRef RuleImpl::kRuleDelegateID = CFSTR(kAuthorizationRightRule); +CFStringRef RuleImpl::kRuleMechanismsID = CFSTR(kAuthorizationRuleClassMechanisms); +CFStringRef RuleImpl::kRuleAuthenticateUserID = CFSTR(kAuthorizationRuleParameterAuthenticateUser); + + +string +RuleImpl::Attribute::getString(CFDictionaryRef config, CFStringRef key, bool required = false, const char *defaultValue = "") +{ + CFTypeRef value = CFDictionaryGetValue(config, key); + if (value && (CFGetTypeID(value) == CFStringGetTypeID())) + { + CFStringRef stringValue = reinterpret_cast(value); + char buffer[512]; + const char *ptr = CFStringGetCStringPtr(stringValue, kCFStringEncodingUTF8); + if (ptr == NULL) + { + if (CFStringGetCString(stringValue, buffer, sizeof(buffer), kCFStringEncodingUTF8)) + ptr = buffer; + else + { + Syslog::alert("Could not convert CFString to C string"); + MacOSError::throwMe(errAuthorizationInternal); + } + } + + return string(ptr); + } + else + if (!required) + return string(defaultValue); + else + { + Syslog::alert("Failed to get rule string"); + MacOSError::throwMe(errAuthorizationInternal); + } +} + +double +RuleImpl::Attribute::getDouble(CFDictionaryRef config, CFStringRef key, bool required = false, double defaultValue = 0.0) +{ + double doubleValue = 0; + + CFTypeRef value = CFDictionaryGetValue(config, key); + if (value && (CFGetTypeID(value) == CFNumberGetTypeID())) + { + CFNumberGetValue(reinterpret_cast(value), kCFNumberDoubleType, &doubleValue); + } + else + if (!required) + return defaultValue; + else + { + Syslog::alert("Failed to get rule double value"); + MacOSError::throwMe(errAuthorizationInternal); + } + + return doubleValue; +} + +bool +RuleImpl::Attribute::getBool(CFDictionaryRef config, CFStringRef key, bool required = false, bool defaultValue = false) +{ + bool boolValue = false; + CFTypeRef value = CFDictionaryGetValue(config, key); + + if (value && (CFGetTypeID(value) == CFBooleanGetTypeID())) + { + boolValue = CFBooleanGetValue(reinterpret_cast(value)); + } + else + if (!required) + return defaultValue; + else + { + Syslog::alert("Failed to get rule bool value"); + MacOSError::throwMe(errAuthorizationInternal); + } + + return boolValue; +} + +vector +RuleImpl::Attribute::getVector(CFDictionaryRef config, CFStringRef key, bool required = false) +{ + vector valueArray; + + CFTypeRef value = CFDictionaryGetValue(config, key); + if (value && (CFGetTypeID(value) == CFArrayGetTypeID())) + { + CFArrayRef evalArray = reinterpret_cast(value); + + CFIndex numItems = CFArrayGetCount(evalArray); + for (CFIndex index=0; index < numItems; index++) + { + CFTypeRef arrayValue = CFArrayGetValueAtIndex(evalArray, index); + if (arrayValue && (CFGetTypeID(arrayValue) == CFStringGetTypeID())) + { + CFStringRef stringValue = reinterpret_cast(arrayValue); + char buffer[512]; + const char *ptr = CFStringGetCStringPtr(stringValue, kCFStringEncodingUTF8); + if (ptr == NULL) + { + if (CFStringGetCString(stringValue, buffer, sizeof(buffer), kCFStringEncodingUTF8)) + ptr = buffer; + else + { + Syslog::alert("Failed to convert CFString to C string for item %u in array", index); + MacOSError::throwMe(errAuthorizationInternal); + } + } + valueArray.push_back(string(ptr)); + } + } + } + else + if (required) + { + Syslog::alert("Value for key either not present or not a CFArray"); + MacOSError::throwMe(errAuthorizationInternal); + } + + return valueArray; +} + + +bool RuleImpl::Attribute::getLocalizedText(CFDictionaryRef config, map &localizedPrompts, CFStringRef dictKey, const char *descriptionKey) +{ + CFIndex numberOfPrompts = 0; + CFDictionaryRef promptsDict; + if (CFDictionaryContainsKey(config, dictKey)) + { + promptsDict = reinterpret_cast(CFDictionaryGetValue(config, dictKey)); + if (promptsDict && (CFGetTypeID(promptsDict) == CFDictionaryGetTypeID())) + numberOfPrompts = CFDictionaryGetCount(promptsDict); + } + if (numberOfPrompts == 0) + return false; + + const void *keys[numberOfPrompts+1]; + const void *values[numberOfPrompts+1]; + CFDictionaryGetKeysAndValues(promptsDict, &keys[0], &values[0]); + + while (numberOfPrompts-- > 0) + { + CFStringRef keyRef = reinterpret_cast(keys[numberOfPrompts]); + CFStringRef valueRef = reinterpret_cast(values[numberOfPrompts]); + if (!keyRef || (CFGetTypeID(keyRef) != CFStringGetTypeID())) { + continue; + } + if (!valueRef || (CFGetTypeID(valueRef) != CFStringGetTypeID())) { + continue; + } + string key = cfString(keyRef); + string value = cfString(valueRef); + localizedPrompts[descriptionKey + key] = value; + } + + return true; +} + + +// default rule +RuleImpl::RuleImpl() : +mType(kUser), mGroupName("admin"), mMaxCredentialAge(300.0), mShared(true), mAllowRoot(false), mSessionOwner(false), mTries(0), mAuthenticateUser(true), mExtractPassword(false) +{ + // XXX/cs read default descriptions from somewhere + // @@@ Default rule is shared admin group with 5 minute timeout +} + +// return rule built from rule definition; throw if invalid. +RuleImpl::RuleImpl(const string &inRightName, CFDictionaryRef cfRight, CFDictionaryRef cfRules) : mRightName(inRightName), mExtractPassword(false) +{ + // @@@ make sure cfRight is non mutable and never used that way + + if (CFGetTypeID(cfRight) != CFDictionaryGetTypeID()) + { + Syslog::alert("Invalid rights set"); + MacOSError::throwMe(errAuthorizationInternal); + } + + mTries = 0; + + string classTag = Attribute::getString(cfRight, kRuleClassID, false, ""); + + if (classTag.length()) + { + if (classTag == kAuthorizationRuleClassAllow) + { + secdebug("authrule", "%s : rule allow", inRightName.c_str()); + mType = kAllow; + } + else if (classTag == kAuthorizationRuleClassDeny) + { + secdebug("authrule", "%s : rule deny", inRightName.c_str()); + mType = kDeny; + } + else if (classTag == kAuthorizationRuleClassUser) + { + mType = kUser; + mGroupName = Attribute::getString(cfRight, kUserGroupID); + // grab other user-in-group attributes + mMaxCredentialAge = Attribute::getDouble(cfRight, kTimeoutID, false, DBL_MAX); + mShared = Attribute::getBool(cfRight, kSharedID); + mAllowRoot = Attribute::getBool(cfRight, kAllowRootID); + mSessionOwner = Attribute::getBool(cfRight, kSessionOwnerID); + // authorization tags can have eval now too + mEvalDef = Attribute::getVector(cfRight, kMechanismsID); + if (mEvalDef.size() == 0 && cfRules /*only rights default see appserver-admin*/) + { + CFDictionaryRef cfRuleDef = reinterpret_cast(CFDictionaryGetValue(cfRules, CFSTR("authenticate"))); + if (cfRuleDef && CFGetTypeID(cfRuleDef) == CFDictionaryGetTypeID()) + mEvalDef = Attribute::getVector(cfRuleDef, kMechanismsID); + } + mTries = int(Attribute::getDouble(cfRight, kTriesID, false, double(kMaximumAuthorizationTries))); + mAuthenticateUser = Attribute::getBool(cfRight, kRuleAuthenticateUserID, false, true); + mExtractPassword = Attribute::getBool(cfRight, kExtractPasswordID, false, false); + + secdebug("authrule", "%s : rule user in group \"%s\" timeout %g%s%s", + inRightName.c_str(), + mGroupName.c_str(), mMaxCredentialAge, mShared ? " shared" : "", + mAllowRoot ? " allow-root" : ""); + + } + else if (classTag == kAuthorizationRuleClassMechanisms) + { + secdebug("authrule", "%s : rule evaluate mechanisms", inRightName.c_str()); + mType = kEvaluateMechanisms; + // mechanisms to evaluate + mEvalDef = Attribute::getVector(cfRight, kMechanismsID, true); + mTries = int(Attribute::getDouble(cfRight, kTriesID, false, 0.0)); // "forever" + mShared = Attribute::getBool(cfRight, kSharedID, false, true); + mExtractPassword = Attribute::getBool(cfRight, kExtractPasswordID, false, false); + } + else if (classTag == kAuthorizationRightRule) + { + assert(cfRules); // rules can't delegate to other rules + secdebug("authrule", "%s : rule delegate rule", inRightName.c_str()); + mType = kRuleDelegation; + + // string or + string ruleDefString = Attribute::getString(cfRight, kRuleDelegateID, false, ""); + if (ruleDefString.length()) + { + CFStringRef ruleDefRef = makeCFString(ruleDefString); + CFDictionaryRef cfRuleDef = reinterpret_cast(CFDictionaryGetValue(cfRules, ruleDefRef)); + if (ruleDefRef) + CFRelease(ruleDefRef); + if (!cfRuleDef || CFGetTypeID(cfRuleDef) != CFDictionaryGetTypeID()) + { + Syslog::alert("'%s' does not name a built-in rule", ruleDefString.c_str()); + MacOSError::throwMe(errAuthorizationInternal); + } + mRuleDef.push_back(Rule(ruleDefString, cfRuleDef, cfRules)); + } + else // array + { + vector ruleDef = Attribute::getVector(cfRight, kRuleDelegateID, true); + for (vector::const_iterator it = ruleDef.begin(); it != ruleDef.end(); it++) + { + CFStringRef ruleNameRef = makeCFString(*it); + CFDictionaryRef cfRuleDef = reinterpret_cast(CFDictionaryGetValue(cfRules, ruleNameRef)); + if (ruleNameRef) + CFRelease(ruleNameRef); + if (!cfRuleDef || (CFGetTypeID(cfRuleDef) != CFDictionaryGetTypeID())) + { + Syslog::alert("Invalid rule '%s'in rule set", it->c_str()); + MacOSError::throwMe(errAuthorizationInternal); + } + mRuleDef.push_back(Rule(*it, cfRuleDef, cfRules)); + } + } + + mKofN = int(Attribute::getDouble(cfRight, kKofNID, false, 0.0)); + if (mKofN) + mType = kKofN; + + } + else + { + secdebug("authrule", "%s : rule class '%s' unknown.", inRightName.c_str(), classTag.c_str()); + Syslog::alert("%s : rule class '%s' unknown", inRightName.c_str(), classTag.c_str()); + MacOSError::throwMe(errAuthorizationInternal); + } + } + else + { + // no class tag means, this is the abbreviated specification from the API + // it _must_ have a definition for "rule" which will be used as a delegate + // it may have a comment (not extracted here) + // it may have a default prompt, or a whole dictionary of languages (not extracted here) + mType = kRuleDelegation; + string ruleName = Attribute::getString(cfRight, kRuleDelegateID, true); + secdebug("authrule", "%s : rule delegate rule (1): %s", inRightName.c_str(), ruleName.c_str()); + CFStringRef ruleNameRef = makeCFString(ruleName); + CFDictionaryRef cfRuleDef = reinterpret_cast(CFDictionaryGetValue(cfRules, ruleNameRef)); + if (ruleNameRef) + CFRelease(ruleNameRef); + if (!cfRuleDef || CFGetTypeID(cfRuleDef) != CFDictionaryGetTypeID()) + { + Syslog::alert("Rule '%s' for right '%s' does not exist or is not properly formed", ruleName.c_str(), inRightName.c_str()); + MacOSError::throwMe(errAuthorizationInternal); + } + mRuleDef.push_back(Rule(ruleName, cfRuleDef, cfRules)); + } + + Attribute::getLocalizedText(cfRight, mLocalizedPrompts, kPromptID, kAuthorizationRuleParameterDescription); + Attribute::getLocalizedText(cfRight, mLocalizedButtons, kButtonID, kAuthorizationRuleParameterButton); +} + +/* +RuleImpl::~Rule() +{ +} +*/ + +void +RuleImpl::setAgentHints(const AuthItemRef &inRight, const Rule &inTopLevelRule, AuthItemSet &environmentToClient, AuthorizationToken &auth) const +{ + string authorizeString(inRight->name()); + environmentToClient.erase(AuthItemRef(AGENT_HINT_AUTHORIZE_RIGHT)); + environmentToClient.insert(AuthItemRef(AGENT_HINT_AUTHORIZE_RIGHT, AuthValueOverlay(authorizeString))); + + pid_t creatorPid = auth.creatorPid(); + environmentToClient.erase(AuthItemRef(AGENT_HINT_CREATOR_PID)); + environmentToClient.insert(AuthItemRef(AGENT_HINT_CREATOR_PID, AuthValueOverlay(sizeof(pid_t), &creatorPid))); + + audit_token_t creatorAuditToken = auth.creatorAuditToken().auditToken(); + environmentToClient.erase(AuthItemRef(AGENT_HINT_CREATOR_AUDIT_TOKEN)); + environmentToClient.insert(AuthItemRef(AGENT_HINT_CREATOR_AUDIT_TOKEN, AuthValueOverlay(sizeof(audit_token_t), &creatorAuditToken))); + + Process &thisProcess = Server::process(); + string bundlePath; + if (SecStaticCodeRef clientCode = auth.creatorCode()) + bundlePath = codePath(clientCode); + AuthItemSet processHints = SecurityAgent::Client::clientHints( + SecurityAgent::bundle, bundlePath, thisProcess.pid(), thisProcess.uid()); + environmentToClient.erase(AuthItemRef(AGENT_HINT_CLIENT_TYPE)); + environmentToClient.erase(AuthItemRef(AGENT_HINT_CLIENT_PATH)); + environmentToClient.erase(AuthItemRef(AGENT_HINT_CLIENT_PID)); + environmentToClient.erase(AuthItemRef(AGENT_HINT_CLIENT_UID)); + environmentToClient.insert(processHints.begin(), processHints.end()); + + map defaultPrompts = inTopLevelRule->localizedPrompts(); + map defaultButtons = inTopLevelRule->localizedButtons(); + + if (defaultPrompts.empty()) + defaultPrompts = localizedPrompts(); + if (defaultButtons.empty()) + defaultButtons = localizedButtons(); + + if (!defaultPrompts.empty()) + { + map::const_iterator it; + for (it = defaultPrompts.begin(); it != defaultPrompts.end(); it++) + { + const string &key = it->first; + const string &value = it->second; + environmentToClient.insert(AuthItemRef(key.c_str(), AuthValueOverlay(value))); + } + } + if (!defaultButtons.empty()) + { + map::const_iterator it; + for (it = defaultButtons.begin(); it != defaultButtons.end(); it++) + { + const string &key = it->first; + const string &value = it->second; + environmentToClient.insert(AuthItemRef(key.c_str(), AuthValueOverlay(value))); + } + } + + // add rulename as a hint + string ruleName = name(); + environmentToClient.erase(AuthItemRef(AGENT_HINT_AUTHORIZE_RULE)); + environmentToClient.insert(AuthItemRef(AGENT_HINT_AUTHORIZE_RULE, AuthValueOverlay(ruleName))); +} + +// If a different evaluation for getting a credential is prescribed, +// we'll run that and validate the credentials from there. +// we fall back on a default configuration from the authenticate rule +OSStatus +RuleImpl::evaluateAuthentication(const AuthItemRef &inRight, const Rule &inRule,AuthItemSet &environmentToClient, AuthorizationFlags flags, CFAbsoluteTime now, const CredentialSet *inCredentials, CredentialSet &credentials, AuthorizationToken &auth, SecurityAgent::Reason &reason, bool savePassword) const +{ + OSStatus status = errAuthorizationDenied; + + Credential hintCredential; + if (errAuthorizationSuccess == evaluateSessionOwner(inRight, inRule, environmentToClient, now, auth, hintCredential, reason)) { + if (hintCredential->name().length()) + environmentToClient.insert(AuthItemRef(AGENT_HINT_SUGGESTED_USER, AuthValueOverlay(hintCredential->name()))); + if (hintCredential->realname().length()) + environmentToClient.insert(AuthItemRef(AGENT_HINT_SUGGESTED_USER_LONG, AuthValueOverlay(hintCredential->realname()))); + } + + if ((mType == kUser) && (mGroupName.length())) + environmentToClient.insert(AuthItemRef(AGENT_HINT_REQUIRE_USER_IN_GROUP, AuthValueOverlay(mGroupName))); + + uint32 tries; + reason = SecurityAgent::noReason; + + Process &cltProc = Server::process(); + // Authorization preserves creator's UID in setuid processes + // (which is nice, but cltUid ends up being unused except by the debug + // message -- AgentMechanismEvaluator ignores it) + uid_t cltUid = (cltProc.uid() != 0) ? cltProc.uid() : auth.creatorUid(); + secdebug("AuthEvalMech", "Mechanism invocation by process %d (UID %d)", cltProc.pid(), cltUid); + + // For auditing within AuthorizationMechEval, pass the right name. + size_t rightNameSize = inRight->name() ? strlen(inRight->name()) : 0; + AuthorizationString rightName = inRight->name() ? inRight->name() : ""; + // @@@ AuthValueRef's ctor ought to take a const void * + AuthValueRef rightValue(rightNameSize, const_cast(rightName)); + AuthValueVector authValueVector; + authValueVector.push_back(rightValue); + + RightAuthenticationLogger rightAuthLogger(auth.creatorAuditToken(), AUE_ssauthint); + rightAuthLogger.setRight(rightName); + + // Just succeed for a continuously active session owner. + if (auth.session().originatorUid() == auth.creatorUid() && auth.session().attributes() & AU_SESSION_FLAG_HAS_AUTHENTICATED) { + secdebug("AuthEvalMech", "We are an active session owner."); + aslmsg m = asl_new(ASL_TYPE_MSG); + asl_set(m, "com.apple.message.domain", "com.apple.securityd.UserActivity"); + asl_set(m, "com.apple.message.signature", "userIsActive"); + asl_set(m, "com.apple.message.signature2", rightName); + asl_set(m, "com.apple.message.result", "failure"); + asl_log(NULL, m, ASL_LEVEL_NOTICE, "We are an active session owner."); + asl_free(m); +// Credential rightCredential(rightName, auth.creatorUid(), mShared); +// credentials.erase(rightCredential); credentials.insert(rightCredential); +// return errAuthorizationSuccess; + } + else { + secdebug("AuthEvalMech", "We are not an active session owner."); + aslmsg m = asl_new(ASL_TYPE_MSG); + asl_set(m, "com.apple.message.domain", "com.apple.securityd.UserActivity"); + asl_set(m, "com.apple.message.signature", "userIsNotActive"); + asl_set(m, "com.apple.message.signature2", rightName); + asl_set(m, "com.apple.message.result", "success"); + asl_log(NULL, m, ASL_LEVEL_NOTICE, "We are not an active session owner."); + asl_free(m); + } + + AgentMechanismEvaluator eval(cltUid, auth.session(), mEvalDef); + + for (tries = 0; tries < mTries; tries++) + { + AuthItemRef retryHint(AGENT_HINT_RETRY_REASON, AuthValueOverlay(sizeof(reason), &reason)); + environmentToClient.erase(retryHint); environmentToClient.insert(retryHint); // replace + AuthItemRef triesHint(AGENT_HINT_TRIES, AuthValueOverlay(sizeof(tries), &tries)); + environmentToClient.erase(triesHint); environmentToClient.insert(triesHint); // replace + + status = eval.run(authValueVector, environmentToClient, auth); + + if ((status == errAuthorizationSuccess) || + (status == errAuthorizationCanceled)) // @@@ can only pass back sideband through context + { + secdebug("AuthEvalMech", "storing new context for authorization"); + auth.setInfoSet(eval.context(), savePassword); + } + + // successfully ran mechanisms to obtain credential + if (status == errAuthorizationSuccess) + { + // deny is the default + status = errAuthorizationDenied; + + CredentialSet newCredentials = makeCredentials(auth); + // clear context after extracting credentials + auth.scrubInfoSet(savePassword); + + for (CredentialSet::const_iterator it = newCredentials.begin(); it != newCredentials.end(); ++it) + { + const Credential& newCredential = *it; + + // @@@ we log the uid a process was running under when it created the authref, which is misleading in the case of loginwindow + if (newCredential->isValid()) { + Syslog::info("UID %u authenticated as user %s (UID %u) for right '%s'", auth.creatorUid(), newCredential->name().c_str(), newCredential->uid(), rightName); + rightAuthLogger.logSuccess(auth.creatorUid(), newCredential->uid(), newCredential->name().c_str()); + } else { + // we can't be sure that the user actually exists so inhibit logging of uid + Syslog::error("UID %u failed to authenticate as user '%s' for right '%s'", auth.creatorUid(), newCredential->name().c_str(), rightName); + rightAuthLogger.logFailure(auth.creatorUid(), newCredential->name().c_str()); + } + + if (!newCredential->isValid()) + { + reason = SecurityAgent::invalidPassphrase; + continue; + } + + // verify that this credential authorizes right + status = evaluateUserCredentialForRight(auth, inRight, inRule, environmentToClient, now, newCredential, true, reason); + + if (status == errAuthorizationSuccess) + { + if (auth.operatesAsLeastPrivileged()) { + Credential rightCredential(rightName, mShared); + credentials.erase(rightCredential); credentials.insert(rightCredential); + if (mShared) + credentials.insert(Credential(rightName, false)); + } + + // whack an equivalent credential, so it gets updated to a later achieved credential which must have been more stringent + credentials.erase(newCredential); credentials.insert(newCredential); + // just got a new credential - if it's shared also add a non-shared one that to stick in the authorizationref local cache + if (mShared) + credentials.insert(Credential(newCredential->uid(), newCredential->name(), newCredential->realname(), false)); + + // use valid credential to set context info + // XXX/cs keeping this for now, such that the uid is passed back + auth.setCredentialInfo(newCredential, savePassword); + secdebug("SSevalMech", "added valid credential for user %s", newCredential->name().c_str()); + // set the sessionHasAuthenticated + if (newCredential->uid() == auth.session().originatorUid()) { + secdebug("AuthEvalMech", "We authenticated as the session owner.\n"); + SessionAttributeBits flags = auth.session().attributes(); + flags |= AU_SESSION_FLAG_HAS_AUTHENTICATED; + auth.session().setAttributes(flags); + } + + status = errAuthorizationSuccess; + break; + } + } + + if (status == errAuthorizationSuccess) + break; + } + else + if ((status == errAuthorizationCanceled) || (status == errAuthorizationInternal)) + { + auth.scrubInfoSet(false); + break; + } + else // last mechanism is now authentication - fail + if (status == errAuthorizationDenied) + reason = SecurityAgent::invalidPassphrase; + } + + // If we fell out of the loop because of too many tries, notify user + if (tries == mTries) + { + reason = SecurityAgent::tooManyTries; + AuthItemRef retryHint (AGENT_HINT_RETRY_REASON, AuthValueOverlay(sizeof(reason), &reason)); + environmentToClient.erase(retryHint); environmentToClient.insert(retryHint); // replace + AuthItemRef triesHint(AGENT_HINT_TRIES, AuthValueOverlay(sizeof(tries), &tries)); + environmentToClient.erase(triesHint); environmentToClient.insert(triesHint); // replace + eval.run(AuthValueVector(), environmentToClient, auth); + // XXX/cs is this still necessary? + auth.scrubInfoSet(false); + + rightAuthLogger.logFailure(NULL, CommonCriteria::errTooManyTries); + } + + return status; +} + +// create externally verified credentials on the basis of +// mechanism-provided information +CredentialSet +RuleImpl::makeCredentials(const AuthorizationToken &auth) const +{ + // fetch context and construct a credential to be tested + const AuthItemSet &context = const_cast(auth).infoSet(); + CredentialSet newCredentials; + + do { + AuthItemSet::const_iterator found = find_if(context.begin(), context.end(), FindAuthItemByRightName(kAuthorizationEnvironmentUsername) ); + if (found == context.end()) + break; + string username = (**found).stringValue(); + secdebug("AuthEvalMech", "found username"); + + const uid_t *uid = NULL; + found = find_if(context.begin(), context.end(), FindAuthItemByRightName("uid") ); + if (found != context.end()) + { + uid = static_cast((**found).value().data); + secdebug("AuthEvalMech", "found uid"); + } + + if (username.length() && uid) + { + // credential is valid because mechanism says so + newCredentials.insert(Credential(*uid, username, "", mShared)); + } + } while(0); + + return newCredentials; +} + +// evaluate whether a good credential of the current session owner would authorize a right +OSStatus +RuleImpl::evaluateSessionOwner(const AuthItemRef &inRight, const Rule &inRule, const AuthItemSet &environment, const CFAbsoluteTime now, const AuthorizationToken &auth, Credential &credential, SecurityAgent::Reason &reason) const +{ + // username hint is taken from the user who created the authorization, unless it's clearly ineligible + // @@@ we have no access to current requester uid here and the process uid is only taken when the authorization is created + // meaning that a process like loginwindow that drops privs later is screwed. + + Credential sessionCredential; + uid_t uid = auth.session().originatorUid(); + Server::active().longTermActivity(); + struct passwd *pw = getpwuid(uid); + if (pw != NULL) { + // avoid hinting a locked account + if ( (pw->pw_passwd == NULL) || + strcmp(pw->pw_passwd, "*") ) { + // Check if username will authorize the request and set username to + // be used as a hint to the user if so + secdebug("AuthEvalMech", "preflight credential from current user, result follows:"); + sessionCredential = Credential(pw->pw_uid, pw->pw_name, pw->pw_gecos, mShared/*ignored*/); + } //fi + endpwent(); + } + OSStatus status = evaluateUserCredentialForRight(auth, inRight, inRule, environment, now, sessionCredential, true, reason); + if (errAuthorizationSuccess == status) + credential = sessionCredential; + + return status; +} + + +OSStatus +RuleImpl::evaluateCredentialForRight(const AuthorizationToken &auth, const AuthItemRef &inRight, const Rule &inRule, const AuthItemSet &environment, CFAbsoluteTime now, const Credential &credential, bool ignoreShared, SecurityAgent::Reason &reason) const +{ + if (auth.operatesAsLeastPrivileged()) { + if (credential->isRight() && credential->isValid() && (inRight->name() == credential->name())) + { + if (!ignoreShared && !mShared && credential->isShared()) + { + // @@@ no proper SA::Reason + reason = SecurityAgent::unknownReason; + secdebug("autheval", "shared credential cannot be used, denying right %s", inRight->name()); + return errAuthorizationDenied; + } else { + return errAuthorizationSuccess; + } + } else { + // @@@ no proper SA::Reason + reason = SecurityAgent::unknownReason; + return errAuthorizationDenied; + } + } else + return evaluateUserCredentialForRight(auth, inRight, inRule, environment, now, credential, false, reason); +} + +// Return errAuthorizationSuccess if this rule allows access based on the specified credential, +// return errAuthorizationDenied otherwise. +OSStatus +RuleImpl::evaluateUserCredentialForRight(const AuthorizationToken &auth, const AuthItemRef &inRight, const Rule &inRule, const AuthItemSet &environment, CFAbsoluteTime now, const Credential &credential, bool ignoreShared, SecurityAgent::Reason &reason) const +{ + assert(mType == kUser); + + // Ideally we'd set the AGENT_HINT_RETRY_REASON hint in this method, but + // evaluateAuthentication() overwrites it before + // AgentMechanismEvaluator::run(). That's what led to passing "reason" + // everywhere, from RuleImpl::evaluate() on down. + + // Get the username from the credential + const char *user = credential->name().c_str(); + + // If the credential is not valid or its age is more than the allowed maximum age + // for a credential, deny. + if (!credential->isValid()) + { + // @@@ it could be the username, not password, was invalid + reason = SecurityAgent::invalidPassphrase; + secdebug("autheval", "credential for user %s is invalid, denying right %s", user, inRight->name()); + return errAuthorizationDenied; + } + + if (now - credential->creationTime() > mMaxCredentialAge) + { + // @@@ no proper SA::Reason + reason = SecurityAgent::unknownReason; + secdebug("autheval", "credential for user %s has expired, denying right %s", user, inRight->name()); + return errAuthorizationDenied; + } + + if (!ignoreShared && !mShared && credential->isShared()) + { + // @@@ no proper SA::Reason + reason = SecurityAgent::unknownReason; + secdebug("autheval", "shared credential for user %s cannot be used, denying right %s", user, inRight->name()); + return errAuthorizationDenied; + } + + // A root (uid == 0) user can do anything + if (credential->uid() == 0) + { + secdebug("autheval", "user %s has uid 0, granting right %s", user, inRight->name()); + return errAuthorizationSuccess; + } + + if (mSessionOwner) + { + Session &session = auth.session(); + uid_t console_user = session.originatorUid(); + + if (credential->uid() == console_user) + { + secdebug("autheval", "user %s is session-owner(uid: %d), granting right %s", user, console_user, inRight->name()); + return errAuthorizationSuccess; + } + // set "reason" in this case? not that a proper SA::Reason exists + } + else + { + // @@@ no proper SA::Reason + reason = SecurityAgent::unknownReason; + secdebug("autheval", "session-owner check failed."); + } + + if (mGroupName.length()) + { + const char *groupname = mGroupName.c_str(); + Server::active().longTermActivity(); + + if (!groupname) + return errAuthorizationDenied; + + do + { + uuid_t group_uuid, user_uuid; + int is_member; + + // @@@ it'd be nice to have SA::Reason codes for the failures + // associated with the pre-check-membership mbr_*() functions, + // but userNotInGroup will do + if (mbr_group_name_to_uuid(groupname, group_uuid)) + break; + + if (mbr_uid_to_uuid(credential->uid(), user_uuid)) + { + struct passwd *pwd; + if (NULL == (pwd = getpwnam(user))) + break; + if (mbr_uid_to_uuid(pwd->pw_uid, user_uuid)) + break; + } + + if (mbr_check_membership(user_uuid, group_uuid, &is_member)) + break; + + if (is_member) + { + secdebug("autheval", "user %s is a member of group %s, granting right %s", + user, groupname, inRight->name()); + return errAuthorizationSuccess; + } + + } + while (0); + + reason = SecurityAgent::userNotInGroup; + secdebug("autheval", "user %s is not a member of group %s, denying right %s", + user, groupname, inRight->name()); + } + else if (mSessionOwner) // rule asks only if user is the session owner + { + reason = SecurityAgent::unacceptableUser; + } + + return errAuthorizationDenied; +} + + + +OSStatus +RuleImpl::evaluateUser(const AuthItemRef &inRight, const Rule &inRule, AuthItemSet &environmentToClient, AuthorizationFlags flags, CFAbsoluteTime now, const CredentialSet *inCredentials, CredentialSet &credentials, AuthorizationToken &auth, SecurityAgent::Reason &reason, bool savePassword) const +{ + // If we got here, this is a kUser type rule, let's start looking for a + // credential that is satisfactory + + // Zeroth -- Here is an extra special saucy ugly hack to allow authorizations + // created by a proccess running as root to automatically get a right. + if (mAllowRoot && auth.creatorUid() == 0) + { + SECURITYD_AUTH_USER_ALLOWROOT(&auth); + + secdebug("autheval", "creator of authorization has uid == 0 granting right %s", + inRight->name()); + return errAuthorizationSuccess; + } + + // if we're not supposed to authenticate evaluate the session-owner against the group + if (!mAuthenticateUser) + { + Credential hintCredential; + OSStatus status = evaluateSessionOwner(inRight, inRule, environmentToClient, now, auth, hintCredential, reason); + + if (!status) + { + SECURITYD_AUTH_USER_ALLOWSESSIONOWNER(&auth); + return errAuthorizationSuccess; + } + + return errAuthorizationDenied; + } + + // First -- go though the credentials we either already used or obtained during this authorize operation. + for (CredentialSet::const_iterator it = credentials.begin(); it != credentials.end(); ++it) + { + // Passed-in user credentials are allowed for least-privileged mode + if (auth.operatesAsLeastPrivileged() && !(*it)->isRight() && (*it)->isValid()) + { + OSStatus status = evaluateUserCredentialForRight(auth, inRight, inRule, environmentToClient, now, *it, false, reason); + if (errAuthorizationSuccess == status) { + Credential rightCredential(inRight->name(), mShared); + credentials.erase(rightCredential); credentials.insert(rightCredential); + if (mShared) + credentials.insert(Credential(inRight->name(), false)); + return status; + } + } + + // if this is least privileged, this will function differently: match credential to requested right + OSStatus status = evaluateCredentialForRight(auth, inRight, inRule, environmentToClient, now, *it, false, reason); + + if (status != errAuthorizationDenied) { + // add credential to authinfo + auth.setCredentialInfo(*it, savePassword); + return status; + } + + } + + // Second -- go though the credentials passed in to this authorize operation by the state management layer. + if (inCredentials) + { + for (CredentialSet::const_iterator it = inCredentials->begin(); it != inCredentials->end(); ++it) + { + // if this is least privileged, this will function differently: match credential to requested right + OSStatus status = evaluateCredentialForRight(auth, inRight, inRule, environmentToClient, now, *it, false, reason); + + if (status == errAuthorizationSuccess) + { + // Add the credential we used to the output set. + // whack an equivalent credential, so it gets updated to a later achieved credential which must have been more stringent + credentials.erase(*it); credentials.insert(*it); + // add credential to authinfo + auth.setCredentialInfo(*it, savePassword); + + return status; + } + else if (status != errAuthorizationDenied) + return status; + } + } + + // Finally -- We didn't find the credential in our passed in credential lists. Obtain a new credential if our flags let us do so. + if (!(flags & kAuthorizationFlagExtendRights)) + return errAuthorizationDenied; + + // authorizations that timeout immediately cannot be preauthorized + if ((flags & kAuthorizationFlagPreAuthorize) && + (mMaxCredentialAge == 0.0)) + { + inRight->setFlags(inRight->flags() | kAuthorizationFlagCanNotPreAuthorize); + return errAuthorizationSuccess; + } + + if (!(flags & kAuthorizationFlagInteractionAllowed)) + return errAuthorizationInteractionNotAllowed; + + setAgentHints(inRight, inRule, environmentToClient, auth); + + return evaluateAuthentication(inRight, inRule, environmentToClient, flags, now, inCredentials, credentials, auth, reason, savePassword); +} + +OSStatus +RuleImpl::evaluateMechanismOnly(const AuthItemRef &inRight, const Rule &inRule, AuthItemSet &environmentToClient, AuthorizationToken &auth, CredentialSet &outCredentials, bool savePassword) const +{ + uint32 tries = 0; + OSStatus status; + + Process &cltProc = Server::process(); + // Authorization preserves creator's UID in setuid processes + uid_t cltUid = (cltProc.uid() != 0) ? cltProc.uid() : auth.creatorUid(); + secdebug("AuthEvalMech", "Mechanism invocation by process %d (UID %d)", cltProc.pid(), cltUid); + + { + AgentMechanismEvaluator eval(cltUid, auth.session(), mEvalDef); + // For auditing within AuthorizationMechEval, pass the right name. + size_t rightNameSize = inRight->name() ? strlen(inRight->name()) : 0; + AuthorizationString rightName = inRight->name() ? inRight->name() : ""; + // @@@ AuthValueRef's ctor ought to take a const void * + AuthValueRef rightValue(rightNameSize, const_cast(rightName)); + AuthValueVector authValueVector; + authValueVector.push_back(rightValue); + + do + { + setAgentHints(inRight, inRule, environmentToClient, auth); + AuthItemRef triesHint(AGENT_HINT_TRIES, AuthValueOverlay(sizeof(tries), &tries)); + environmentToClient.erase(triesHint); environmentToClient.insert(triesHint); // replace + + status = eval.run(authValueVector, environmentToClient, auth); + if ((status == errAuthorizationSuccess) || + (status == errAuthorizationCanceled)) // @@@ can only pass back sideband through context + { + secdebug("AuthEvalMech", "storing new context for authorization"); + auth.setInfoSet(eval.context(), savePassword); + if (status == errAuthorizationSuccess) + { + // (try to) attach the authorizing UID to the least-priv cred + if (auth.operatesAsLeastPrivileged()) + { + outCredentials.insert(Credential(rightName, mShared)); + if (mShared) + outCredentials.insert(Credential(rightName, false)); + + RightAuthenticationLogger logger(auth.creatorAuditToken(), AUE_ssauthint); + logger.setRight(rightName); + + AuthItem *uidItem = eval.context().find(AGENT_CONTEXT_UID); + if (uidItem) + { + uid_t authorizedUid; + memcpy(&authorizedUid, uidItem->value().data, sizeof(authorizedUid)); + secdebug("AuthEvalMech", "generating least-privilege cred for '%s' authorized by UID %u", inRight->name(), authorizedUid); + logger.logLeastPrivilege(authorizedUid, true); + } + else // cltUid is better than nothing + { + secdebug("AuthEvalMech", "generating least-privilege cred for '%s' with process- or auth-UID %u", inRight->name(), cltUid); + logger.logLeastPrivilege(cltUid, false); + } + } + + if (0 == strcmp(rightName, "system.login.console") && NULL == eval.context().find(AGENT_CONTEXT_AUTO_LOGIN)) { + secdebug("AuthEvalMech", "We logged in as the session owner.\n"); + SessionAttributeBits flags = auth.session().attributes(); + flags |= AU_SESSION_FLAG_HAS_AUTHENTICATED; + auth.session().setAttributes(flags); + } + CredentialSet newCredentials = makeCredentials(auth); + outCredentials.insert(newCredentials.begin(), newCredentials.end()); + } + } + + tries++; + } + while ((status == errAuthorizationDenied) // only if we have an expected failure we continue + && ((mTries == 0) // mTries == 0 means we try forever + || ((mTries > 0) // mTries > 0 means we try up to mTries times + && (tries < mTries)))); + } + + // HACK kill all hosts to free pages for low memory systems + // (XXX/gh there should be a #define for this right) + if (name() == "system.login.done") + { + // one case where we don't want to mark the agents as "busy" + QueryInvokeMechanism query(securityAgent, auth.session()); + query.terminateAgent(); + QueryInvokeMechanism query2(privilegedAuthHost, auth.session()); + query2.terminateAgent(); + } + + return status; +} + +OSStatus +RuleImpl::evaluateRules(const AuthItemRef &inRight, const Rule &inRule, AuthItemSet &environmentToClient, AuthorizationFlags flags, CFAbsoluteTime now, const CredentialSet *inCredentials, CredentialSet &credentials, AuthorizationToken &auth, SecurityAgent::Reason &reason, bool savePassword) const +{ + // line up the rules to try + if (!mRuleDef.size()) + return errAuthorizationSuccess; + + uint32_t count = 0; + OSStatus status = errAuthorizationSuccess; + vector::const_iterator it; + + for (it = mRuleDef.begin();it != mRuleDef.end(); it++) + { + // are we at k yet? + if ((mType == kKofN) && (count == mKofN)) + return errAuthorizationSuccess; + + // get a rule and try it + status = (*it)->evaluate(inRight, inRule, environmentToClient, flags, now, inCredentials, credentials, auth, reason, savePassword); + + // if status is cancel/internal error abort + if ((status == errAuthorizationCanceled) || (status == errAuthorizationInternal)) + return status; + + if (status != errAuthorizationSuccess) + { + // continue if we're only looking for k of n + if (mType == kKofN) + continue; + + break; + } + else + count++; + } + + if ((mType == kKofN) && (status == errAuthorizationSuccess) && (count < mKofN)) + status = errAuthorizationDenied; + + return status; // return the last failure +} + + +OSStatus +RuleImpl::evaluate(const AuthItemRef &inRight, const Rule &inRule, AuthItemSet &environmentToClient, AuthorizationFlags flags, CFAbsoluteTime now, const CredentialSet *inCredentials, CredentialSet &credentials, AuthorizationToken &auth, SecurityAgent::Reason &reason, bool savePassword) const +{ + switch (mType) + { + case kAllow: + SECURITYD_AUTH_ALLOW(&auth, (char *)name().c_str()); + return errAuthorizationSuccess; + case kDeny: + SECURITYD_AUTH_DENY(&auth, (char *)name().c_str()); + return errAuthorizationDenied; + case kUser: + SECURITYD_AUTH_USER(&auth, (char *)name().c_str()); + return evaluateUser(inRight, inRule, environmentToClient, flags, now, inCredentials, credentials, auth, reason, savePassword); + case kRuleDelegation: + SECURITYD_AUTH_RULES(&auth, (char *)name().c_str()); + return evaluateRules(inRight, inRule, environmentToClient, flags, now, inCredentials, credentials, auth, reason, savePassword); + case kKofN: + SECURITYD_AUTH_KOFN(&auth, (char *)name().c_str()); + return evaluateRules(inRight, inRule, environmentToClient, flags, now, inCredentials, credentials, auth, reason, savePassword); + case kEvaluateMechanisms: + SECURITYD_AUTH_MECHRULE(&auth, (char *)name().c_str()); + // if we had a SecurityAgent::Reason code for "mechanism denied," + // it would make sense to pass down "reason" + return evaluateMechanismOnly(inRight, inRule, environmentToClient, auth, credentials, savePassword); + default: + Syslog::alert("Unrecognized rule type %d", mType); + MacOSError::throwMe(errAuthorizationInternal); // invalid rule + } +} + +Rule::Rule() : RefPointer(new RuleImpl()) {} +Rule::Rule(const string &inRightName, CFDictionaryRef cfRight, CFDictionaryRef cfRules) : RefPointer(new RuleImpl(inRightName, cfRight, cfRules)) {} + + + +} // end namespace Authorization diff --git a/securityd/src/AuthorizationRule.h b/securityd/src/AuthorizationRule.h new file mode 100644 index 00000000..bd70fa9b --- /dev/null +++ b/securityd/src/AuthorizationRule.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2003-2007,2009-2010 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@ + * + * AuthorizationRule.h + * Security + * + */ + +#ifndef _H_AUTHORIZATIONRULE +#define _H_AUTHORIZATIONRULE 1 + +#include +#include +#include "authority.h" + +namespace Authorization +{ + +class Rule; + +class RuleImpl : public RefCount +{ +public: + RuleImpl(); + RuleImpl(const string &inRightName, CFDictionaryRef cfRight, CFDictionaryRef cfRules); + + OSStatus evaluate(const AuthItemRef &inRight, const Rule &inRule, AuthItemSet &environmentToClient, + AuthorizationFlags flags, CFAbsoluteTime now, + const CredentialSet *inCredentials, CredentialSet &credentials, + AuthorizationToken &auth, SecurityAgent::Reason &reason, bool savePassword) const; + + string name() const { return mRightName; } + bool extractPassword() const { return mExtractPassword; } + +private: +// internal machinery + + // evaluate credential for right + OSStatus evaluateCredentialForRight(const AuthorizationToken &auth, const AuthItemRef &inRight, const Rule &inRule, + const AuthItemSet &environment, CFAbsoluteTime now, const Credential &credential, bool ignoreShared, SecurityAgent::Reason &reason) const; + // evaluate user credential (authentication) for right + OSStatus evaluateUserCredentialForRight(const AuthorizationToken &auth, const AuthItemRef &inRight, const Rule &inRule, const AuthItemSet &environment, CFAbsoluteTime now, const Credential &credential, bool ignoreShared, SecurityAgent::Reason &reason) const; + + OSStatus evaluateRules(const AuthItemRef &inRight, const Rule &inRule, + AuthItemSet &environmentToClient, AuthorizationFlags flags, + CFAbsoluteTime now, const CredentialSet *inCredentials, CredentialSet &credentials, + AuthorizationToken &auth, SecurityAgent::Reason &reason, bool savePassword) const; + + void setAgentHints(const AuthItemRef &inRight, const Rule &inTopLevelRule, AuthItemSet &environmentToClient, AuthorizationToken &auth) const; + + // perform authorization based on running specified mechanisms (see evaluateMechanism) + OSStatus evaluateAuthentication(const AuthItemRef &inRight, const Rule &inRule, AuthItemSet &environmentToClient, AuthorizationFlags flags, CFAbsoluteTime now, const CredentialSet *inCredentials, CredentialSet &credentials, AuthorizationToken &auth, SecurityAgent::Reason &reason, bool savePassword) const; + + OSStatus evaluateUser(const AuthItemRef &inRight, const Rule &inRule, + AuthItemSet &environmentToClient, AuthorizationFlags flags, + CFAbsoluteTime now, const CredentialSet *inCredentials, CredentialSet &credentials, + AuthorizationToken &auth, SecurityAgent::Reason &reason, bool savePassword) const; + + OSStatus evaluateMechanismOnly(const AuthItemRef &inRight, const Rule &inRule, AuthItemSet &environmentToClient, AuthorizationToken &auth, CredentialSet &outCredentials, bool savePassword) const; + + // find username hint based on session owner + OSStatus evaluateSessionOwner(const AuthItemRef &inRight, const Rule &inRule, const AuthItemSet &environment, const CFAbsoluteTime now, const AuthorizationToken &auth, Credential &credential, SecurityAgent::Reason &reason) const; + + CredentialSet makeCredentials(const AuthorizationToken &auth) const; + + map localizedPrompts() const { return mLocalizedPrompts; } + map localizedButtons() const { return mLocalizedButtons; } + + +// parsed attributes +private: + enum Type + { + kDeny, + kAllow, + kUser, + kRuleDelegation, + kKofN, + kEvaluateMechanisms, + } mType; + + string mRightName; + string mGroupName; + CFTimeInterval mMaxCredentialAge; + bool mShared; + bool mAllowRoot; + vector mEvalDef; + bool mSessionOwner; + vector mRuleDef; + uint32_t mKofN; + mutable uint32_t mTries; + bool mExtractPassword; + bool mAuthenticateUser; + map mLocalizedPrompts; + map mLocalizedButtons; + +private: + + class Attribute + { + public: + static bool getBool(CFDictionaryRef config, CFStringRef key, bool required, bool defaultValue); + static double getDouble(CFDictionaryRef config, CFStringRef key, bool required, double defaultValue); + static string getString(CFDictionaryRef config, CFStringRef key, bool required, const char *defaultValue); + static vector getVector(CFDictionaryRef config, CFStringRef key, bool required); + static bool getLocalizedText(CFDictionaryRef config, map &localizedPrompts, CFStringRef dictKey, const char *descriptionKey); + }; + + +// keys + static CFStringRef kUserGroupID; + static CFStringRef kTimeoutID; + static CFStringRef kSharedID; + static CFStringRef kAllowRootID; + static CFStringRef kMechanismsID; + static CFStringRef kSessionOwnerID; + static CFStringRef kKofNID; + static CFStringRef kPromptID; + static CFStringRef kButtonID; + static CFStringRef kTriesID; + static CFStringRef kExtractPasswordID; + + static CFStringRef kRuleClassID; + static CFStringRef kRuleAllowID; + static CFStringRef kRuleDenyID; + static CFStringRef kRuleUserID; + static CFStringRef kRuleDelegateID; + static CFStringRef kRuleMechanismsID; + static CFStringRef kRuleAuthenticateUserID; +}; + +class Rule : public RefPointer +{ +public: + Rule(); + Rule(const string &inRightName, CFDictionaryRef cfRight, CFDictionaryRef cfRules); +}; + +}; /* namespace Authorization */ + +#endif /* ! _H_AUTHORIZATIONRULE */ diff --git a/securityd/src/SharedMemoryServer.cpp b/securityd/src/SharedMemoryServer.cpp new file mode 100644 index 00000000..699542c6 --- /dev/null +++ b/securityd/src/SharedMemoryServer.cpp @@ -0,0 +1,169 @@ +#include "SharedMemoryServer.h" +#include +#include +#include +#include +#include +#include +#include +#include + +static const char* kPrefix = "/private/var/db/mds/messages/se_"; + +SharedMemoryServer::SharedMemoryServer (const char* segmentName, SegmentOffsetType segmentSize) : + mSegmentName (segmentName), mSegmentSize (segmentSize) +{ + mFileName = kPrefix; + mFileName += segmentName; + + // make the mds directory, just in case it doesn't exist + mkdir("/var/db/mds", 1777); + mkdir("/var/db/mds/messages", 0755); + + // make the file name + // clean any old file away + unlink (mFileName.c_str ()); + + // open the file + int segmentDescriptor = open (mFileName.c_str (), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (segmentDescriptor < 0) + { + return; + } + + // set the segment size + ftruncate (segmentDescriptor, segmentSize); + + // map it into memory + mSegment = (u_int8_t*) mmap (NULL, mSegmentSize, PROT_READ | PROT_WRITE, MAP_SHARED, segmentDescriptor, 0); + close (segmentDescriptor); + + if (mSegment == (u_int8_t*) -1) // can't map the memory? + { + mSegment = NULL; + unlink (mFileName.c_str()); + } + + mDataPtr = mDataArea = mSegment + sizeof(SegmentOffsetType); + mDataMax = mSegment + segmentSize;; + + SetProducerOffset (0); +} + + + +SharedMemoryServer::~SharedMemoryServer () +{ + // go away + if (mSegment == NULL) + { + return; + } + + // get out of memory + munmap (mSegment, mSegmentSize); + + // mark the segment for deletion + unlink (mFileName.c_str ()); +} + + + +const SegmentOffsetType + kSegmentLength = 0, + kCRCOffset = kSegmentLength + sizeof(SegmentOffsetType), + kDomainOffset = kCRCOffset + sizeof(SegmentOffsetType), + kEventTypeOffset = kDomainOffset + sizeof(SegmentOffsetType), + kHeaderLength = kEventTypeOffset + sizeof(SegmentOffsetType) - kCRCOffset; + +void SharedMemoryServer::WriteMessage (SegmentOffsetType domain, SegmentOffsetType event, const void *message, SegmentOffsetType messageLength) +{ + // assemble the final message + ssize_t messageSize = kHeaderLength + messageLength; + u_int8_t finalMessage[messageSize]; + SegmentOffsetType *fm = (SegmentOffsetType*) finalMessage; + fm[0] = OSSwapHostToBigInt32(domain); + fm[1] = OSSwapHostToBigInt32(event); + memcpy(&fm[2], message, messageLength); + + SegmentOffsetType crc = CalculateCRC(finalMessage, messageSize); + + // write the length + WriteOffset(messageSize); + + // write the crc + WriteOffset(crc); + + // write the data + WriteData (finalMessage, messageSize); + + // write the data count + SetProducerOffset(mDataPtr - mDataArea); +} + + + +const char* SharedMemoryServer::GetSegmentName () +{ + return mSegmentName.c_str (); +} + + + +size_t SharedMemoryServer::GetSegmentSize () +{ + return mSegmentSize; +} + + + +SegmentOffsetType SharedMemoryServer::GetProducerOffset () +{ + // the data is stored in the buffer in network byte order + u_int32_t pCount = OSSwapBigToHostInt32 (*(u_int32_t*) mSegment); + return OSSwapHostToBigInt32 (pCount); +} + + + +void SharedMemoryServer::SetProducerOffset (SegmentOffsetType producerCount) +{ + *((SegmentOffsetType*) mSegment) = OSSwapHostToBigInt32 (producerCount); +} + + + +void SharedMemoryServer::WriteOffset(SegmentOffsetType offset) +{ + u_int8_t buffer[4]; + *((u_int32_t*) buffer) = OSSwapHostToBigInt32(offset); + WriteData(buffer, 4); +} + + + +void SharedMemoryServer::WriteData(const void* data, SegmentOffsetType length) +{ + // figure out where in the buffer we actually need to write the data + // figure out how many bytes we can write without overflowing the buffer + const u_int8_t* dp = (const u_int8_t*) data; + SegmentOffsetType bytesToEnd = mDataMax - mDataPtr; + + // figure out how many bytes we can write + SegmentOffsetType bytesToWrite = (length <= bytesToEnd) ? length : bytesToEnd; + + // move the first part of the data, making sure to skip the producer pointer + memcpy (mDataPtr, dp, bytesToWrite); + mDataPtr += bytesToWrite; + dp += bytesToWrite; + + // deduct the bytes just written + length -= bytesToWrite; + + if (length != 0) // did we wrap around? + { + mDataPtr = mDataArea; + memcpy (mDataPtr, dp, length); + mDataPtr += length; + } +} diff --git a/securityd/src/SharedMemoryServer.h b/securityd/src/SharedMemoryServer.h new file mode 100644 index 00000000..6e17b35a --- /dev/null +++ b/securityd/src/SharedMemoryServer.h @@ -0,0 +1,39 @@ +#ifndef __SHARED_MEMORY_SERVER__ +#define __SHARED_MEMORY_SERVER__ + + + +#include +#include +#include + +class SharedMemoryServer +{ +protected: + std::string mSegmentName, mFileName; + size_t mSegmentSize; + + u_int8_t* mSegment; + u_int8_t* mDataArea; + u_int8_t* mDataPtr; + u_int8_t* mDataMax; + + void WriteOffset (SegmentOffsetType offset); + void WriteData (const void* data, SegmentOffsetType length); + +public: + SharedMemoryServer (const char* segmentName, SegmentOffsetType segmentSize); + virtual ~SharedMemoryServer (); + + void WriteMessage (SegmentOffsetType domain, SegmentOffsetType event, const void *message, SegmentOffsetType messageLength); + + const char* GetSegmentName (); + size_t GetSegmentSize (); + + SegmentOffsetType GetProducerOffset (); + void SetProducerOffset (SegmentOffsetType producerOffset); +}; + + + +#endif diff --git a/securityd/src/acl_keychain.cpp b/securityd/src/acl_keychain.cpp new file mode 100644 index 00000000..dbc4bcb7 --- /dev/null +++ b/securityd/src/acl_keychain.cpp @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2000-2004,2006-2009,2012-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@ + */ + + +// +// acl_keychain - a subject type for the protected-path +// keychain prompt interaction model. +// +// Arguments in CSSM_LIST form: +// list[1] = CssmData: CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR structure +// list[2] = CssmData: Descriptive String (presented to user in protected dialogs) +// For legacy compatibility, we accept a single-entry form +// list[1] = CssmData: Descriptive String +// which defaults to a particular CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR structure value. +// This is never produced by current code, and is considered purely a legacy feature. +// +// On-disk (flattened) representation: +// In order to accommodate legacy formats nicely, we use the binary-versioning feature +// of the ACL machinery. Version 0 is the legacy format (storing only the description +// string), while Version 1 contains both selector and description. We are now always +// writing version-1 data, but will continue to recognize version-0 data indefinitely +// for really, really old keychain items. +// +#include "acl_keychain.h" +#include "agentquery.h" +#include "acls.h" +#include "connection.h" +#include "database.h" +#include "server.h" +#include +#include +#include +#include + + +#define ACCEPT_LEGACY_FORM 1 + + +// +// The default for the selector structure. +// +CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR KeychainPromptAclSubject::defaultSelector = { + CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION, // version + 0 // flags +}; + + +// +// Validate a credential set against this subject. +// +bool KeychainPromptAclSubject::validate(const AclValidationContext &context, + const TypedList &sample) const +{ + if (SecurityServerEnvironment *env = context.environment()) { + Process &process = Server::process(); + secdebug("kcacl", "Keychain query for process %d (UID %d)", process.pid(), process.uid()); + + // assemble the effective validity mode mask + uint32_t mode = Maker::defaultMode; + const uint16_t &flags = selector.flags; + if (flags & CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED_ACT) + mode = (mode & ~CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED) | (flags & CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED); + if (flags & CSSM_ACL_KEYCHAIN_PROMPT_INVALID_ACT) + mode = (mode & ~CSSM_ACL_KEYCHAIN_PROMPT_INVALID) | (flags & CSSM_ACL_KEYCHAIN_PROMPT_INVALID); + + // determine signed/validity status of client, without reference to any particular Code Requirement + SecCodeRef clientCode = NULL; + OSStatus validation = errSecCSStaticCodeNotFound; + { + StLock _(process); + Server::active().longTermActivity(); + clientCode = process.currentGuest(); + if (clientCode) { + validation = SecCodeCheckValidity(clientCode, kSecCSDefaultFlags, NULL); + } + + switch (validation) + { + 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; + } + } + break; + + case errSecCSUnsigned: + { // client is not signed + if (!(mode & CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED)) { + secdebug("kcacl", "client is unsigned, suppressing prompt"); + return false; + } + } + break; + + case errSecCSSignatureFailed: // client signed but signature is broken + case errSecCSGuestInvalid: // client signed but dynamically invalid + case errSecCSStaticCodeNotFound: // client not on disk (or unreadable) + { + 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()); + return false; + } + Syslog::info("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)); + return false; + } + } + + // At this point, we're committed to try to Pop The Question. Now, how? + + // does the user need to type in the passphrase? + const Database *db = env->database; + bool needPassphrase = db && (selector.flags & CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE); + + // an application (i.e. Keychain Access.app :-) can force this option + if (clientCode && validation == noErr) { + StLock _(process); + CFRef dict; + if (SecCodeCopySigningInformation(clientCode, kSecCSDefaultFlags, &dict.aref()) == noErr) + if (CFDictionaryRef info = CFDictionaryRef(CFDictionaryGetValue(dict, kSecCodeInfoPList))) + needPassphrase |= + (CFDictionaryGetValue(info, CFSTR("SecForcePassphrasePrompt")) != NULL); + } + + // pop The Question + if (db && db->belongsToSystem() && !hasAuthorizedForSystemKeychain()) { + QueryKeychainAuth query; + query.inferHints(Server::process()); + if (query(db ? db->dbName() : NULL, description.c_str(), context.authorization(), NULL) != SecurityAgent::noReason) + return false; + return true; + } else { + QueryKeychainUse query(needPassphrase, db); + query.inferHints(Server::process()); + query.addHint(AGENT_HINT_CLIENT_VALIDITY, &validation, sizeof(validation)); + if (query.queryUser(db ? db->dbName() : NULL, + description.c_str(), context.authorization()) != SecurityAgent::noReason) + return false; + + // process an "always allow..." response + if (query.remember && clientCode) { + StLock _(process); + RefPointer clientXCode = new OSXCodeWrap(clientCode); + RefPointer subject = new CodeSignatureAclSubject(OSXVerifier(clientXCode)); + SecurityServerAcl::addToStandardACL(context, subject); + } + + // finally, return the actual user response + return query.allow; + } + } + return false; // default to deny without prejudice +} + + +// +// Make a copy of this subject in CSSM_LIST form +// +CssmList KeychainPromptAclSubject::toList(Allocator &alloc) const +{ + // always issue new (non-legacy) form + return TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT, + new(alloc) ListElement(alloc, CssmData::wrap(selector)), + new(alloc) ListElement(alloc, description)); +} + +// +// Has the caller recently authorized in such a way as to render unnecessary +// the usual QueryKeychainAuth dialog? (The right is specific to Keychain +// Access' way of editing a system keychain.) +// +bool KeychainPromptAclSubject::hasAuthorizedForSystemKeychain() const +{ + string rightString = "system.keychain.modify"; + return Server::session().isRightAuthorized(rightString, Server::connection(), false/*no UI*/); +} + + + +// +// Create a KeychainPromptAclSubject +// +uint32_t KeychainPromptAclSubject::Maker::defaultMode; + +KeychainPromptAclSubject *KeychainPromptAclSubject::Maker::make(const TypedList &list) const +{ + switch (list.length()) { +#if ACCEPT_LEGACY_FORM + case 2: // legacy case: just description + { + ListElement *params[1]; + crack(list, 1, params, CSSM_LIST_ELEMENT_DATUM); + return new KeychainPromptAclSubject(*params[0], defaultSelector); + } +#endif //ACCEPT_LEGACY_FORM + case 3: // standard case: selector + description + { + ListElement *params[2]; + crack(list, 2, params, CSSM_LIST_ELEMENT_DATUM, CSSM_LIST_ELEMENT_DATUM); + return new KeychainPromptAclSubject(*params[1], + *params[0]->data().interpretedAs(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE)); + } + default: + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + } +} + +KeychainPromptAclSubject *KeychainPromptAclSubject::Maker::make(Version version, + Reader &pub, Reader &) const +{ + CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR selector; + const char *description; + switch (version) { + case pumaVersion: + selector = defaultSelector; + pub(description); + break; + case jaguarVersion: + pub(selector); + selector.version = n2h(selector.version); + selector.flags = n2h(selector.flags); + pub(description); + break; + default: + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + } + return new KeychainPromptAclSubject(description, selector); +} + +KeychainPromptAclSubject::KeychainPromptAclSubject(string descr, + const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR &sel) + : SimpleAclSubject(CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT), + selector(sel), description(descr) +{ + // check selector version + if (selector.version != CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION) + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + + // always use the latest binary version + version(currentVersion); +} + + +// +// Export the subject to a memory blob +// +void KeychainPromptAclSubject::exportBlob(Writer::Counter &pub, Writer::Counter &priv) +{ + if (version() != 0) { + selector.version = h2n (selector.version); + selector.flags = h2n (selector.flags); + pub(selector); + } + + pub.insert(description.size() + 1); +} + +void KeychainPromptAclSubject::exportBlob(Writer &pub, Writer &priv) +{ + if (version() != 0) { + selector.version = h2n (selector.version); + selector.flags = h2n (selector.flags); + pub(selector); + } + pub(description.c_str()); +} + + +#ifdef DEBUGDUMP + +void KeychainPromptAclSubject::debugDump() const +{ + Debug::dump("KeychainPrompt:%s(%s)", + description.c_str(), + (selector.flags & CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE) ? "passphrase" : "standard"); +} + +#endif //DEBUGDUMP diff --git a/securityd/src/acl_keychain.h b/securityd/src/acl_keychain.h new file mode 100644 index 00000000..51e6e85a --- /dev/null +++ b/securityd/src/acl_keychain.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2000-2004,2006-2007,2009 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_keychain - a subject type for the protected-path +// keychain prompt interaction model. +// +#ifndef _ACL_KEYCHAIN +#define _ACL_KEYCHAIN + +#include +#include +#include + + +// +// This is the actual subject implementation class +// +class KeychainPromptAclSubject : public SimpleAclSubject { + static const Version pumaVersion = 0; // 10.0, 10.1 -> default selector (not stored) + 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; + CssmList toList(Allocator &alloc) const; + bool hasAuthorizedForSystemKeychain() const; + + KeychainPromptAclSubject(string description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR &selector); + + void exportBlob(Writer::Counter &pub, Writer::Counter &priv); + void exportBlob(Writer &pub, Writer &priv); + + uint32_t selectorFlags() const { return selector.flags; } + bool selectorFlag(uint32_t flag) const { return selectorFlags() & flag; } + + IFDUMP(void debugDump() const); + +public: + class Maker : public AclSubject::Maker { + friend class KeychainPromptAclSubject; + public: + Maker(uint32_t mode) + : AclSubject::Maker(CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT) { defaultMode = mode; } + KeychainPromptAclSubject *make(const TypedList &list) const; + KeychainPromptAclSubject *make(Version version, Reader &pub, Reader &priv) const; + + private: + static uint32_t defaultMode; + }; + +private: + CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR selector; // selector structure + string description; // description blob (string) + +private: + static CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR defaultSelector; +}; + + +#endif //_ACL_KEYCHAIN diff --git a/securityd/src/acls.cpp b/securityd/src/acls.cpp new file mode 100644 index 00000000..f4df0940 --- /dev/null +++ b/securityd/src/acls.cpp @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2000-2009,2012-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@ + */ + + +// +// acls - securityd ACL implementation +// +#include "acls.h" +#include "connection.h" +#include "server.h" +#include "agentquery.h" +#include "tokendatabase.h" +#include "acl_keychain.h" + +// ACL subjects whose Environments we implement +#include +#include +#include + +#include +#include + +// +// SecurityServerAcl is virtual +// +SecurityServerAcl::~SecurityServerAcl() +{ } + + +// +// The default implementation of the ACL interface simply uses the local ObjectAcl +// data. You can customize this by implementing instantiateAcl() [from ObjectAcl] +// or by overriding these methods as desired. +// Note: While you can completely ignore the ObjectAcl personality if you wish, it's +// usually smarter to adapt it. +// +void SecurityServerAcl::getOwner(AclOwnerPrototype &owner) +{ + StLock _(aclSequence); + ObjectAcl::cssmGetOwner(owner); +} + +void SecurityServerAcl::getAcl(const char *tag, uint32 &count, AclEntryInfo *&acls) +{ + StLock _(aclSequence); + ObjectAcl::cssmGetAcl(tag, count, acls); +} + +void SecurityServerAcl::changeAcl(const AclEdit &edit, const AccessCredentials *cred, + Database *db) +{ + StLock _(aclSequence); + SecurityServerEnvironment env(*this, db); + ObjectAcl::cssmChangeAcl(edit, cred, &env); +} + +void SecurityServerAcl::changeOwner(const AclOwnerPrototype &newOwner, + const AccessCredentials *cred, Database *db) +{ + StLock _(aclSequence); + SecurityServerEnvironment env(*this, db); + ObjectAcl::cssmChangeOwner(newOwner, cred, &env); +} + + +// +// Modified validate() methods to connect all the conduits... +// +void SecurityServerAcl::validate(AclAuthorization auth, const AccessCredentials *cred, Database *db) +{ + SecurityServerEnvironment env(*this, db); + + StLock objectSequence(aclSequence); + StLock processSequence(Server::process().aclSequence); + ObjectAcl::validate(auth, cred, &env); +} + +void SecurityServerAcl::validate(AclAuthorization auth, const Context &context, Database *db) +{ + validate(auth, + context.get(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS), db); +} + + +// +// This helper tries to add the (new) subject given to the ACL +// whose validation is currently proceeding through context. +// This will succeed if the ACL is in standard form, which means +// a ThresholdAclSubject. +// The new subject will be added at the front (so it is checked first +// from now on), and as a side effect we'll notify the client side to +// re-encode the object. +// Returns true if the edit could be done, or false if the ACL wasn't +// standard enough. May throw if the ACL is malformed or otherwise messed up. +// +// This is a self-contained helper that is here merely because it's "about" +// ACLs and has no better home. +// +bool SecurityServerAcl::addToStandardACL(const AclValidationContext &context, AclSubject *subject) +{ + if (SecurityServerEnvironment *env = context.environment()) + if (ThresholdAclSubject *threshold = env->standardSubject(context)) { + unsigned size = threshold->count(); + if (dynamic_cast(threshold->subject(size-1))) { + // looks standard enough + secdebug("acl", "adding new subject %p to from of threshold ACL", subject); + threshold->add(subject, 0); + + // tell the ACL it's been modified + context.acl()->changedAcl(); + + // trigger a special notification code on (otherwise successful) return + Server::connection().overrideReturn(CSSMERR_CSP_APPLE_ADD_APPLICATION_ACL_SUBJECT); + return true; + } + } + secdebug("acl", "ACL is not standard form; cannot edit"); + return false; +} + + +// +// Look at the ACL whose validation is currently proceeding through context. +// If it LOOKS like a plausible version of a legacy "dot mac item" ACL. +// We don't have access to the database attributes of the item up here in the +// securityd sky, so we have to apply a heuristic based on which applications (by path) +// are given access to the item. +// So this is strictly a heuristic. The potential downside is that we may inadvertently +// give access to new .Mac authorized Apple (only) applications when the user only intended +// a limited set of extremely popular Apple (only) applications that just happen to all be +// .Mac authorized today. We can live with that. +// +bool SecurityServerAcl::looksLikeLegacyDotMac(const AclValidationContext &context) +{ + static const char * const prototypicalDotMacPath[] = { + "/Applications/Mail.app", + "/Applications/Safari.app", + "/Applications/iSync.app", + "/Applications/System Preferences.app", + "/Applications/iCal.app", + "/Applications/iChat.app", + "/Applications/iTunes.app", + "/Applications/Address Book.app", + "/Applications/iSync.app", + NULL // sentinel + }; + + static const unsigned threshold = 6; + + if (SecurityServerEnvironment *env = context.environment()) { + if (ThresholdAclSubject *list = env->standardSubject(context)) { + unsigned count = list->count(); + unsigned matches = 0; + for (unsigned n = 0; n < count; ++n) { + if (CodeSignatureAclSubject *app = dynamic_cast(list->subject(n))) { + for (const char * const *p = prototypicalDotMacPath; *p; p++) + if (app->path() == *p) + matches++; + } + } + secdebug("codesign", "matched %d of %zd candididates (threshold=%d)", + matches, sizeof(prototypicalDotMacPath) / sizeof(char *) - 1, threshold); + return matches >= threshold; + } + } + return false; +} + + +// +// External storage interface +// +Adornable &SecurityServerEnvironment::store(const AclSubject *subject) +{ + switch (subject->type()) { + case CSSM_ACL_SUBJECT_TYPE_PREAUTH: + { + if (TokenDatabase *tokenDb = dynamic_cast(database)) + return tokenDb->common().store(); + } + break; + default: + break; + } + CssmError::throwMe(CSSM_ERRCODE_ACL_SUBJECT_TYPE_NOT_SUPPORTED); +} + + +// +// ProcessAclSubject personality: uid/gid/pid come from the active Process object +// +uid_t SecurityServerEnvironment::getuid() const +{ + return Server::process().uid(); +} + +gid_t SecurityServerEnvironment::getgid() const +{ + return Server::process().gid(); +} + +pid_t SecurityServerEnvironment::getpid() const +{ + return Server::process().pid(); +} + + +// +// CodeSignatureAclSubject personality: take code signature from active Process object +// +bool SecurityServerEnvironment::verifyCodeSignature(const OSXVerifier &verifier, + const AclValidationContext &context) +{ + return Server::codeSignatures().verify(Server::process(), verifier, context); +} + + +// +// PromptedAclSubject personality: Get a secret by prompting through SecurityAgent +// +bool SecurityServerEnvironment::getSecret(CssmOwnedData &secret, const CssmData &prompt) const +{ + //@@@ ignoring prompt - not used right now + if (database) { + QueryPIN query(*database); + query.inferHints(Server::process()); + if (!query()) { // success + secret = query.pin(); + return true; + } + } + return false; +} + + +// +// SecretAclSubject personality: externally validate a secret (passphrase etc.) +// Right now, this always goes to the (Token)Database object, because that's where +// the PIN ACL entries are. We could direct this at the ObjectAcl (database or key) +// instead and rely on tokend to perform the PIN mapping, but the generic tokend +// wrappers do not (currently) perform any ACL validation, so every tokend would have +// to re-implement that. Perhaps in the next ACL revamp cycle... +// +bool SecurityServerEnvironment::validateSecret(const SecretAclSubject *me, + const AccessCredentials *cred) +{ + return database && database->validateSecret(me, cred); +} + + +// +// PreAuthenticationAclSubject personality - refer to database (ObjectAcl) +// +ObjectAcl *SecurityServerEnvironment::preAuthSource() +{ + return database ? &database->acl() : NULL; +} + + +// +// Autonomous ACL editing support +// +ThresholdAclSubject *SecurityServerEnvironment::standardSubject(const AclValidationContext &context) +{ + return dynamic_cast(context.subject()); +} + + +// +// The default AclSource denies having an ACL at all +// +AclSource::~AclSource() +{ /* virtual */ } + +SecurityServerAcl &AclSource::acl() +{ + CssmError::throwMe(CSSM_ERRCODE_OBJECT_ACL_NOT_SUPPORTED); +} + +Database *AclSource::relatedDatabase() +{ + return NULL; +} diff --git a/securityd/src/acls.h b/securityd/src/acls.h new file mode 100644 index 00000000..5df4ba25 --- /dev/null +++ b/securityd/src/acls.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2000-2001,2003-2007,2011 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@ + */ + + +// +// acls - securityd ACL implementation +// +// These classes implement securityd's local ACL machine in terms of the generic +// ObjectAcl model. In particular, they define securityd's AclValidationEnvironment, +// which hooks the real-world state into the abstract AclSubject submachines. +// +// Note that these classes are *complete* but *extendable*. The default implementation +// uses unmodified local ObjectAcl state. Subclasses (and certain AclSubjects) may delegate +// validation to outside agents (such as a tokend) and thus act as caching forwarding agents. +// Don't assume. +// +#ifndef _H_ACLS +#define _H_ACLS + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace SecurityServer; + + +class Connection; +class Database; + + +// +// ACL implementation as used by the SecurityServer +// +class SecurityServerAcl : public ObjectAcl { +public: + SecurityServerAcl() : ObjectAcl(Allocator::standard()), aclSequence(Mutex::recursive) { } + virtual ~SecurityServerAcl(); + + // validation calls restated + virtual void validate(AclAuthorization auth, const AccessCredentials *cred, Database *relatedDatabase); + void validate(AclAuthorization auth, const Context &context, Database *relatedDatabase); + + // CSSM layer ACL calls + virtual void getOwner(AclOwnerPrototype &owner); + virtual void getAcl(const char *tag, uint32 &count, AclEntryInfo *&acls); + virtual void changeAcl(const AclEdit &edit, const AccessCredentials *cred, + Database *relatedDatabase); + virtual void changeOwner(const AclOwnerPrototype &newOwner, const AccessCredentials *cred, + Database *relatedDatabase); + + // to be provided by implementations + virtual AclKind aclKind() const = 0; + + // 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); + + // aclSequence is taken to serialize ACL validations to pick up mutual changes + Mutex aclSequence; +}; + + +// +// Our implementation of an ACL validation environment uses information +// derived from a Connection object. It implements context for a fair number +// of subject types (see the inheritance list below). +// +class SecurityServerEnvironment : public virtual AclValidationEnvironment, + public virtual ProcessAclSubject::Environment, + public virtual CodeSignatureAclSubject::Environment, + public virtual SecretAclSubject::Environment, + public virtual PromptedAclSubject::Environment, + public virtual PreAuthorizationAcls::Environment { +public: + SecurityServerEnvironment(SecurityServerAcl &baseAcl, Database *db) + : acl(baseAcl), database(db) { } + + SecurityServerAcl &acl; + Database * const database; + + // personalities + uid_t getuid() const; + gid_t getgid() const; + pid_t getpid() const; + bool verifyCodeSignature(const OSXVerifier &verifier, const AclValidationContext &context); + bool validateSecret(const SecretAclSubject *me, const AccessCredentials *cred); + bool getSecret(CssmOwnedData &secret, const CssmData &prompt) const; + ObjectAcl *preAuthSource(); + Adornable &store(const AclSubject *subject); + + // subject editing + ThresholdAclSubject *standardSubject(const AclValidationContext &context); +}; + + +// +// An abstract source of a SecurityServerAcl. +// There is a default implementation, which throws OBJECT_ACL_NOT_SUPPORTED. +// +class AclSource { +protected: + AclSource() { } + virtual ~AclSource(); + +public: + virtual SecurityServerAcl &acl(); // defaults to "no ACL; throw exception" + virtual Database *relatedDatabase(); // optionally, a Database related to me + + // + // Forward ACL calls, passing some locally obtained stuff along. + // These are virtual so an AclSource can override them. Such overrides + // should enhance/post-process rather than replace functionality. + // + virtual void getOwner(AclOwnerPrototype &owner) + { return acl().getOwner(owner); } + virtual void getAcl(const char *tag, uint32 &count, AclEntryInfo *&acls) + { return acl().getAcl(tag, count, acls); } + virtual void changeAcl(const AclEdit &edit, const AccessCredentials *cred) + { return acl().changeAcl(edit, cred, relatedDatabase()); } + virtual void changeOwner(const AclOwnerPrototype &newOwner, const AccessCredentials *cred) + { return acl().changeOwner(newOwner, cred, relatedDatabase()); } + virtual void validate(AclAuthorization auth, const AccessCredentials *cred) + { acl().validate(auth, cred, relatedDatabase()); } + virtual void validate(AclAuthorization auth, const Context &context) + { acl().validate(auth, context, relatedDatabase()); } +}; + + +#endif //_H_ACLS diff --git a/securityd/src/agentquery.cpp b/securityd/src/agentquery.cpp new file mode 100644 index 00000000..aa797acd --- /dev/null +++ b/securityd/src/agentquery.cpp @@ -0,0 +1,1575 @@ +/* + * Copyright (c) 2000-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@ + */ + +// +// passphrases - canonical code to obtain passphrases +// +#include "agentquery.h" +#include "authority.h" +#include "ccaudit_extensions.h" + +#include +#include +#include +#include +#include +#include +#include // AUE_ssauthint +#include +#include +#include +#include +#include +#include "securityd_service/securityd_service/securityd_service_client.h" + +#define SECURITYAGENT_BOOTSTRAP_NAME_BASE "com.apple.security.agentMain" +#define SECURITYAGENT_STUB_BOOTSTRAP_NAME_BASE "com.apple.security.agentStub" +#define AUTHORIZATIONHOST_BOOTSTRAP_NAME_BASE "com.apple.security.authhost" + +#define AUTH_XPC_ITEM_NAME "_item_name" +#define AUTH_XPC_ITEM_FLAGS "_item_flags" +#define AUTH_XPC_ITEM_VALUE "_item_value" +#define AUTH_XPC_ITEM_TYPE "_item_type" + +#define AUTH_XPC_REQUEST_METHOD_KEY "_agent_request_key" +#define AUTH_XPC_REQUEST_METHOD_CREATE "_agent_request_create" +#define AUTH_XPC_REQUEST_METHOD_INVOKE "_agent_request_invoke" +#define AUTH_XPC_REQUEST_METHOD_DEACTIVATE "_agent_request_deactivate" +#define AUTH_XPC_REQUEST_METHOD_DESTROY "_agent_request_destroy" +#define AUTH_XPC_REPLY_METHOD_KEY "_agent_reply_key" +#define AUTH_XPC_REPLY_METHOD_RESULT "_agent_reply_result" +#define AUTH_XPC_REPLY_METHOD_INTERRUPT "_agent_reply_interrupt" +#define AUTH_XPC_REPLY_METHOD_CREATE "_agent_reply_create" +#define AUTH_XPC_REPLY_METHOD_DEACTIVATE "_agent_reply_deactivate" +#define AUTH_XPC_PLUGIN_NAME "_agent_plugin" +#define AUTH_XPC_MECHANISM_NAME "_agent_mechanism" +#define AUTH_XPC_HINTS_NAME "_agent_hints" +#define AUTH_XPC_CONTEXT_NAME "_agent_context" +#define AUTH_XPC_IMMUTABLE_HINTS_NAME "_agent_immutable_hints" +#define AUTH_XPC_REQUEST_INSTANCE "_agent_instance" +#define AUTH_XPC_REPLY_RESULT_VALUE "_agent_reply_result_value" +#define AUTH_XPC_AUDIT_SESSION_PORT "_agent_audit_session_port" +#define AUTH_XPC_BOOTSTRAP_PORT "_agent_bootstrap_port" +#define AUTH_XPC_SESSION_UUID "_agent_session_uuid" +#define AUTH_XPC_SESSION_PREFS "_agent_session_prefs" +#define AUTH_XPC_SESSION_INPUT_METHOD "_agent_session_inputMethod" + +#define UUID_INITIALIZER_FROM_SESSIONID(sessionid) \ +{ 0,0,0,0, 0,0,0,0, 0,0,0,0, (unsigned char)((0xff000000 & (sessionid))>>24), (unsigned char)((0x00ff0000 & (sessionid))>>16), (unsigned char)((0x0000ff00 & (sessionid))>>8), (unsigned char)((0x000000ff & (sessionid))) } + +// +// NOSA support functions. This is a test mode where the SecurityAgent +// is simulated via stdio in the client. Good for running automated tests +// of client programs. Only available if -DNOSA when compiling. +// +#if defined(NOSA) + +#include + +static void getNoSA(char *buffer, size_t bufferSize, const char *fmt, ...) +{ + // write prompt + va_list args; + va_start(args, fmt); + vfprintf(stdout, fmt, args); + va_end(args); + + // read reply + memset(buffer, 0, bufferSize); + const char *nosa = getenv("NOSA"); + if (!strcmp(nosa, "-")) { + if (fgets(buffer, bufferSize-1, stdin) == NULL) + CssmError::throwMe(CSSM_ERRCODE_NO_USER_INTERACTION); + buffer[strlen(buffer)-1] = '\0'; // remove trailing newline + if (!isatty(fileno(stdin))) + printf("%s\n", buffer); // echo to output if input not terminal + } else { + strncpy(buffer, nosa, bufferSize-1); + printf("%s\n", buffer); + } + if (buffer[0] == '\0') // empty input -> cancellation + CssmError::throwMe(CSSM_ERRCODE_USER_CANCELED); +} + +#endif //NOSA + + +// SecurityAgentConnection + +SecurityAgentConnection::SecurityAgentConnection(const AuthHostType type, Session &session) +: mAuthHostType(type), +mHostInstance(session.authhost(mAuthHostType)), +mConnection(&Server::connection()), +mAuditToken(Server::connection().auditToken()) +{ + // this may take a while + Server::active().longTermActivity(); + secdebug("SecurityAgentConnection", "new SecurityAgentConnection(%p)", this); +} + +SecurityAgentConnection::~SecurityAgentConnection() +{ + secdebug("SecurityAgentConnection", "SecurityAgentConnection(%p) dying", this); + mConnection->useAgent(NULL); +} + +void +SecurityAgentConnection::activate() +{ + secdebug("SecurityAgentConnection", "activate(%p)", this); + + Session &session = mHostInstance->session(); + SessionId targetSessionId = session.sessionId(); + MachPlusPlus::Bootstrap processBootstrap = Server::process().taskPort().bootstrap(); + fileport_t userPrefsFP = MACH_PORT_NULL; + + // send the the userPrefs to SecurityAgent + if (mAuthHostType == securityAgent || mAuthHostType == userAuthHost) { + CFRef userPrefs(mHostInstance->session().copyUserPrefs()); + if (0 != userPrefs) + { + FILE *mbox = NULL; + int fd = 0; + mbox = tmpfile(); + if (NULL != mbox) + { + fd = dup(fileno(mbox)); + fclose(mbox); + if (fd != -1) + { + CFIndex length = CFDataGetLength(userPrefs); + if (write(fd, CFDataGetBytePtr(userPrefs), length) != length) + Syslog::error("could not write userPrefs"); + else + { + if (0 == fileport_makeport(fd, &userPrefsFP)) + secdebug("SecurityAgentConnection", "stashed the userPrefs file descriptor"); + else + Syslog::error("failed to stash the userPrefs file descriptor"); + } + close(fd); + } + } + } + if (MACH_PORT_NULL == userPrefsFP) + { + secdebug("SecurityAgentConnection", "could not read userPrefs"); + } + } + + mConnection->useAgent(this); + try + { + StLock _(*mHostInstance); + + mach_port_t lookupPort = mHostInstance->lookup(targetSessionId); + if (MACH_PORT_NULL == lookupPort) + { + Syslog::error("could not find real service, bailing"); + MacOSError::throwMe(CSSM_ERRCODE_SERVICE_NOT_AVAILABLE); + } + // reset Client contact info + mPort = lookupPort; + SecurityAgent::Client::activate(mPort); + + secdebug("SecurityAgentConnection", "%p activated", this); + } + catch (MacOSError &err) + { + mConnection->useAgent(NULL); // guess not + Syslog::error("SecurityAgentConnection: error activating %s instance %p", + mAuthHostType == privilegedAuthHost + ? "authorizationhost" + : "SecurityAgent", this); + throw; + } + + secdebug("SecurityAgentConnection", "contacting service (%p)", this); + mach_port_name_t jobPort; + if (0 > audit_session_port(session.sessionId(), &jobPort)) + Syslog::error("audit_session_port failed: %m"); + MacOSError::check(SecurityAgent::Client::contact(jobPort, processBootstrap, userPrefsFP)); + secdebug("SecurityAgentConnection", "contact didn't throw (%p)", this); + + if (userPrefsFP != MACH_PORT_NULL) + mach_port_deallocate(mach_task_self(), userPrefsFP); +} + +void +SecurityAgentConnection::reconnect() +{ + // if !mHostInstance throw()? + if (mHostInstance) + { + activate(); + } +} + +void +SecurityAgentConnection::terminate() +{ + activate(); + + // @@@ This happens already in the destructor; presumably we do this to tear things down orderly + mConnection->useAgent(NULL); +} + + +// SecurityAgentConnection + +SecurityAgentXPCConnection::SecurityAgentXPCConnection(const AuthHostType type, Session &session) +: mAuthHostType(type), +mHostInstance(session.authhost(mAuthHostType)), +mSession(session), +mConnection(&Server::connection()), +mAuditToken(Server::connection().auditToken()) +{ + // this may take a while + Server::active().longTermActivity(); + secdebug("SecurityAgentConnection", "new SecurityAgentConnection(%p)", this); + mXPCConnection = NULL; + mXPCStubConnection = NULL; + mNobodyUID = -2; + struct passwd *pw = getpwnam("nobody"); + if (NULL != pw) { + mNobodyUID = pw->pw_uid; + } +} + +SecurityAgentXPCConnection::~SecurityAgentXPCConnection() +{ + secdebug("SecurityAgentConnection", "SecurityAgentConnection(%p) dying", this); + mConnection->useAgent(NULL); + + // If a connection has been established, we need to tear it down. + if (NULL != mXPCConnection) { + // Tearing this down is a multi-step process. First, request a cancellation. + // This is safe even if the connection is already in the cancelled state. + xpc_connection_cancel(mXPCConnection); + + // Then release the XPC connection + xpc_release(mXPCConnection); + mXPCConnection = NULL; + + if (NULL != mXPCStubConnection) { + // We may or may not have one of these + xpc_release(mXPCStubConnection); + mXPCStubConnection = NULL; + } + } +} + +bool SecurityAgentXPCConnection::inDarkWake() +{ + return mSession.server().inDarkWake(); +} + +void +SecurityAgentXPCConnection::activate(bool ignoreUid) +{ + secdebug("SecurityAgentConnection", "activate(%p)", this); + + mConnection->useAgent(this); + if (mXPCConnection != NULL) { + // If we already have an XPC connection, there's nothing to do. + return; + } + try + { + if (mAuthHostType == securityAgent) { + uuid_t sessionUUID = UUID_INITIALIZER_FROM_SESSIONID(mSession.sessionId()); + // Yes, these need to be throws, as we're still in securityd, and thus still have to do flow control with exceptions. + if (!(mSession.attributes() & sessionHasGraphicAccess)) + CssmError::throwMe(CSSM_ERRCODE_NO_USER_INTERACTION); + if (inDarkWake()) + CssmError::throwMe(CSSM_ERRCODE_IN_DARK_WAKE); + uid_t targetUid = mHostInstance->session().originatorUid(); + secdebug("SecurityAgentXPCConnection","Retrieved UID %d for this session", targetUid); + if ((int32_t)targetUid != -1) { + mXPCStubConnection = xpc_connection_create_mach_service(SECURITYAGENT_STUB_BOOTSTRAP_NAME_BASE, NULL, 0); + xpc_connection_set_target_uid(mXPCStubConnection, targetUid); + secdebug("SecurityAgentXPCConnection", "Creating a security agent stub"); + xpc_connection_set_event_handler(mXPCStubConnection, ^(xpc_object_t object){}); // Yes, this is a dummy handler, we never ever care about any responses from the stub. It can die in a fire for all I care. + xpc_connection_resume(mXPCStubConnection); + + xpc_object_t wakeupMessage = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_data(wakeupMessage, AUTH_XPC_SESSION_UUID, sessionUUID, sizeof(uuid_t)); + xpc_object_t responseMessage = xpc_connection_send_message_with_reply_sync(mXPCStubConnection, wakeupMessage); + if (xpc_get_type(responseMessage) == XPC_TYPE_DICTIONARY) { + secdebug("SecurityAgentXPCConnection", "Valid response received from stub"); + } else { + secdebug("SecurityAgentXPCConnection", "Error response received from stub"); + } + xpc_release(wakeupMessage); + xpc_release(responseMessage); + } + + mXPCConnection = xpc_connection_create_mach_service(SECURITYAGENT_BOOTSTRAP_NAME_BASE, NULL,0); + xpc_connection_set_instance(mXPCConnection, sessionUUID); + secdebug("SecurityAgentXPCConnection", "Creating a security agent"); + } else { + mXPCConnection = xpc_connection_create_mach_service(AUTHORIZATIONHOST_BOOTSTRAP_NAME_BASE, NULL, 0); + secdebug("SecurityAgentXPCConnection", "Creating a standard authhost"); + } + + xpc_connection_set_event_handler(mXPCConnection, ^(xpc_object_t object) { + if (xpc_get_type(object) == XPC_TYPE_ERROR) { + secdebug("SecurityAgentXPCConnection", "error during xpc: %s", xpc_dictionary_get_string(object, XPC_ERROR_KEY_DESCRIPTION)); + } + }); + + xpc_connection_resume(mXPCConnection); + + secdebug("SecurityAgentXPCConnection", "%p activated", this); + } + catch (MacOSError &err) + { + mConnection->useAgent(NULL); // guess not + Syslog::error("SecurityAgentConnection: error activating %s instance %p", + mAuthHostType == privilegedAuthHost + ? "authorizationhost" + : "SecurityAgent", this); + throw; + } + + secdebug("SecurityAgentXPCConnection", "contact didn't throw (%p)", this); +} + +void +SecurityAgentXPCConnection::reconnect() +{ +} + +void +SecurityAgentXPCConnection::terminate() +{ + activate(false); + + // @@@ This happens already in the destructor; presumably we do this to tear things down orderly + mConnection->useAgent(NULL); +} + + +using SecurityAgent::Reason; +using namespace Authorization; + +SecurityAgentQuery::SecurityAgentQuery(const AuthHostType type, Session &session) +: SecurityAgentConnection(type, session) +{ + secdebug("SecurityAgentQuery", "new SecurityAgentQuery(%p)", this); +} + +SecurityAgentQuery::~SecurityAgentQuery() +{ + secdebug("SecurityAgentQuery", "SecurityAgentQuery(%p) dying", this); + +#if defined(NOSA) + if (getenv("NOSA")) { + printf(" [query done]\n"); + return; + } +#endif + + if (SecurityAgent::Client::state() != SecurityAgent::Client::dead) + destroy(); +} + +void +SecurityAgentQuery::inferHints(Process &thisProcess) +{ + string guestPath; + { + StLock _(thisProcess); + if (SecCodeRef clientCode = thisProcess.currentGuest()) + guestPath = codePath(clientCode); + } + AuthItemSet processHints = clientHints(SecurityAgent::bundle, guestPath, + thisProcess.pid(), thisProcess.uid()); + mClientHints.insert(processHints.begin(), processHints.end()); +} + +void SecurityAgentQuery::addHint(const char *name, const void *value, UInt32 valueLen, UInt32 flags) +{ + AuthorizationItem item = { name, valueLen, const_cast(value), flags }; + mClientHints.insert(AuthItemRef(item)); +} + + +void +SecurityAgentQuery::readChoice() +{ + allow = false; + remember = false; + + AuthItem *allowAction = outContext().find(AGENT_CONTEXT_ALLOW); + if (allowAction) + { + string allowString; + if (allowAction->getString(allowString) + && (allowString == "YES")) + allow = true; + } + + AuthItem *rememberAction = outContext().find(AGENT_CONTEXT_REMEMBER_ACTION); + if (rememberAction) + { + string rememberString; + if (rememberAction->getString(rememberString) + && (rememberString == "YES")) + remember = true; + } +} + +void +SecurityAgentQuery::disconnect() +{ + SecurityAgent::Client::destroy(); +} + +void +SecurityAgentQuery::terminate() +{ + // you might think these are called in the wrong order, but you'd be wrong + SecurityAgentConnection::terminate(); + SecurityAgent::Client::terminate(); +} + +void +SecurityAgentQuery::create(const char *pluginId, const char *mechanismId, const SessionId inSessionId) +{ + activate(); + OSStatus status = SecurityAgent::Client::create(pluginId, mechanismId, inSessionId); + if (status) + { + secdebug("SecurityAgentQuery", "agent went walkabout, restarting"); + reconnect(); + status = SecurityAgent::Client::create(pluginId, mechanismId, inSessionId); + } + if (status) MacOSError::throwMe(status); +} + +ModuleNexus gAllXPCClientsMutex; +ModuleNexus > allXPCClients; + +void +SecurityAgentXPCQuery::killAllXPCClients() +{ + // grab the lock for the client list -- we need to make sure no one modifies the structure while we are iterating it. + StLock _(gAllXPCClientsMutex()); + + set::iterator clientIterator = allXPCClients().begin(); + while (clientIterator != allXPCClients().end()) + { + set::iterator thisClient = clientIterator++; + if ((*thisClient)->getTerminateOnSleep()) + { + (*thisClient)->terminate(); + } + } +} + + +SecurityAgentXPCQuery::SecurityAgentXPCQuery(const AuthHostType type, Session &session) +: SecurityAgentXPCConnection(type, session), mAgentConnected(false), mTerminateOnSleep(false) +{ + secdebug("SecurityAgentXPCQuery", "new SecurityAgentXPCQuery(%p)", this); +} + +SecurityAgentXPCQuery::~SecurityAgentXPCQuery() +{ + secdebug("SecurityAgentXPCQuery", "SecurityAgentXPCQuery(%p) dying", this); + if (mAgentConnected) { + this->disconnect(); + } +} + +void +SecurityAgentXPCQuery::inferHints(Process &thisProcess) +{ + string guestPath; + if (SecCodeRef clientCode = thisProcess.currentGuest()) + guestPath = codePath(clientCode); + + AuthItemSet clientHints; + SecurityAgent::RequestorType type = SecurityAgent::bundle; + pid_t clientPid = thisProcess.pid(); + uid_t clientUid = thisProcess.uid(); + + clientHints.insert(AuthItemRef(AGENT_HINT_CLIENT_TYPE, AuthValueOverlay(sizeof(type), &type))); + clientHints.insert(AuthItemRef(AGENT_HINT_CLIENT_PATH, AuthValueOverlay(guestPath))); + clientHints.insert(AuthItemRef(AGENT_HINT_CLIENT_PID, AuthValueOverlay(sizeof(clientPid), &clientPid))); + clientHints.insert(AuthItemRef(AGENT_HINT_CLIENT_UID, AuthValueOverlay(sizeof(clientUid), &clientUid))); + + + mClientHints.insert(clientHints.begin(), clientHints.end()); + + bool validSignature = thisProcess.checkAppleSigned(); + AuthItemSet clientImmutableHints; + + clientImmutableHints.insert(AuthItemRef(AGENT_HINT_PROCESS_SIGNED, AuthValueOverlay(sizeof(validSignature), &validSignature))); + + mImmutableHints.insert(clientImmutableHints.begin(), clientImmutableHints.end()); +} + +void SecurityAgentXPCQuery::addHint(const char *name, const void *value, UInt32 valueLen, UInt32 flags) +{ + AuthorizationItem item = { name, valueLen, const_cast(value), flags }; + mClientHints.insert(AuthItemRef(item)); +} + + +void +SecurityAgentXPCQuery::readChoice() +{ + allow = false; + remember = false; + + AuthItem *allowAction = mOutContext.find(AGENT_CONTEXT_ALLOW); + if (allowAction) + { + string allowString; + if (allowAction->getString(allowString) + && (allowString == "YES")) + allow = true; + } + + AuthItem *rememberAction = mOutContext.find(AGENT_CONTEXT_REMEMBER_ACTION); + if (rememberAction) + { + string rememberString; + if (rememberAction->getString(rememberString) + && (rememberString == "YES")) + remember = true; + } +} + +void +SecurityAgentXPCQuery::disconnect() +{ + if (NULL != mXPCConnection) { + xpc_object_t requestObject = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_string(requestObject, AUTH_XPC_REQUEST_METHOD_KEY, AUTH_XPC_REQUEST_METHOD_DESTROY); + xpc_connection_send_message(mXPCConnection, requestObject); + xpc_release(requestObject); + } + + StLock _(gAllXPCClientsMutex()); + allXPCClients().erase(this); +} + +void +SecurityAgentXPCQuery::terminate() +{ + this->disconnect(); +} + +static void xpcArrayToAuthItemSet(AuthItemSet *setToBuild, xpc_object_t input) { + setToBuild->clear(); + + xpc_array_apply(input, ^bool(size_t index, xpc_object_t item) { + const char *name = xpc_dictionary_get_string(item, AUTH_XPC_ITEM_NAME); + + size_t length; + const void *data = xpc_dictionary_get_data(item, AUTH_XPC_ITEM_VALUE, &length); + void *dataCopy = malloc(length); + memcpy(dataCopy, data, length); + + uint64_t flags = xpc_dictionary_get_uint64(item, AUTH_XPC_ITEM_FLAGS); + AuthItemRef nextItem(name, AuthValueOverlay((uint32_t)length, dataCopy), (uint32_t)flags); + setToBuild->insert(nextItem); + memset(dataCopy, 0, length); // The authorization items contain things like passwords, so wiping clean is important. + free(dataCopy); + return true; + }); +} + +void +SecurityAgentXPCQuery::create(const char *pluginId, const char *mechanismId, const SessionId inSessionId) +{ + bool ignoreUid = false; + + do { + activate(ignoreUid); + + mAgentConnected = false; + + xpc_object_t requestObject = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_string(requestObject, AUTH_XPC_REQUEST_METHOD_KEY, AUTH_XPC_REQUEST_METHOD_CREATE); + xpc_dictionary_set_string(requestObject, AUTH_XPC_PLUGIN_NAME, pluginId); + xpc_dictionary_set_string(requestObject, AUTH_XPC_MECHANISM_NAME, mechanismId); + + uid_t targetUid = Server::process().uid(); + bool doSwitchAudit = true; // (ignoreUid) || ((targetUid == 0) || (targetUid == mNobodyUID)); + bool doSwitchBootstrap = true; // (ignoreUid) || ((targetUid == 0) || (targetUid == mNobodyUID)); + + if (doSwitchAudit) { + mach_port_name_t jobPort; + if (0 == audit_session_port(mSession.sessionId(), &jobPort)) { + secdebug("SecurityAgentXPCQuery", "attaching an audit session port because the uid was %d", targetUid); + xpc_dictionary_set_mach_send(requestObject, AUTH_XPC_AUDIT_SESSION_PORT, jobPort); + if (mach_port_mod_refs(mach_task_self(), jobPort, MACH_PORT_RIGHT_SEND, -1) != KERN_SUCCESS) { + secdebug("SecurityAgentXPCQuery", "unable to release send right for audit session, leaking"); + } + } + } + + if (doSwitchBootstrap) { + secdebug("SecurityAgentXPCQuery", "attaching a bootstrap port because the uid was %d", targetUid); + MachPlusPlus::Bootstrap processBootstrap = Server::process().taskPort().bootstrap(); + xpc_dictionary_set_mach_send(requestObject, AUTH_XPC_BOOTSTRAP_PORT, processBootstrap); + } + + xpc_object_t object = xpc_connection_send_message_with_reply_sync(mXPCConnection, requestObject); + if (xpc_get_type(object) == XPC_TYPE_DICTIONARY) { + const char *replyType = xpc_dictionary_get_string(object, AUTH_XPC_REPLY_METHOD_KEY); + if (0 == strcmp(replyType, AUTH_XPC_REPLY_METHOD_CREATE)) { + uint64_t status = xpc_dictionary_get_uint64(object, AUTH_XPC_REPLY_RESULT_VALUE); + if (status == kAuthorizationResultAllow) { + mAgentConnected = true; + } else { + secdebug("SecurityAgentXPCQuery", "plugin create failed in SecurityAgent"); + MacOSError::throwMe(errAuthorizationInternal); + } + } + } else if (xpc_get_type(object) == XPC_TYPE_ERROR) { + if (XPC_ERROR_CONNECTION_INVALID == object) { + // If we get an error before getting the create response, try again without the UID + if (ignoreUid) { + secdebug("SecurityAgentXPCQuery", "failed to establish connection, no retries left"); + xpc_release(object); + MacOSError::throwMe(errAuthorizationInternal); + } else { + secdebug("SecurityAgentXPCQuery", "failed to establish connection, retrying with no UID"); + ignoreUid = true; + xpc_release(mXPCConnection); + mXPCConnection = NULL; + } + } else if (XPC_ERROR_CONNECTION_INTERRUPTED == object) { + // If we get an error before getting the create response, try again + } + } + xpc_release(object); + xpc_release(requestObject); + } while (!mAgentConnected); + + StLock _(gAllXPCClientsMutex()); + allXPCClients().insert(this); +} + +static xpc_object_t authItemSetToXPCArray(AuthItemSet input) { + xpc_object_t outputArray = xpc_array_create(NULL, 0); + for (AuthItemSet::iterator i = input.begin(); i != input.end(); i++) { + AuthItemRef item = *i; + + xpc_object_t xpc_data = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_string(xpc_data, AUTH_XPC_ITEM_NAME, item->name()); + AuthorizationValue value = item->value(); + if (value.data != NULL) { + xpc_dictionary_set_data(xpc_data, AUTH_XPC_ITEM_VALUE, value.data, value.length); + } + xpc_dictionary_set_uint64(xpc_data, AUTH_XPC_ITEM_FLAGS, item->flags()); + xpc_array_append_value(outputArray, xpc_data); + xpc_release(xpc_data); + } + return outputArray; +} + +OSStatus +SecurityAgentXPCQuery::invoke() { + __block OSStatus status = kAuthorizationResultUndefined; + + xpc_object_t hintsArray = authItemSetToXPCArray(mInHints); + xpc_object_t contextArray = authItemSetToXPCArray(mInContext); + xpc_object_t immutableHintsArray = authItemSetToXPCArray(mImmutableHints); + + xpc_object_t requestObject = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_string(requestObject, AUTH_XPC_REQUEST_METHOD_KEY, AUTH_XPC_REQUEST_METHOD_INVOKE); + xpc_dictionary_set_value(requestObject, AUTH_XPC_HINTS_NAME, hintsArray); + xpc_dictionary_set_value(requestObject, AUTH_XPC_CONTEXT_NAME, contextArray); + xpc_dictionary_set_value(requestObject, AUTH_XPC_IMMUTABLE_HINTS_NAME, immutableHintsArray); + + xpc_object_t object = xpc_connection_send_message_with_reply_sync(mXPCConnection, requestObject); + if (xpc_get_type(object) == XPC_TYPE_DICTIONARY) { + const char *replyType = xpc_dictionary_get_string(object, AUTH_XPC_REPLY_METHOD_KEY); + if (0 == strcmp(replyType, AUTH_XPC_REPLY_METHOD_RESULT)) { + xpc_object_t xpcHints = xpc_dictionary_get_value(object, AUTH_XPC_HINTS_NAME); + xpc_object_t xpcContext = xpc_dictionary_get_value(object, AUTH_XPC_CONTEXT_NAME); + AuthItemSet tempHints, tempContext; + xpcArrayToAuthItemSet(&tempHints, xpcHints); + xpcArrayToAuthItemSet(&tempContext, xpcContext); + mOutHints = tempHints; + mOutContext = tempContext; + mLastResult = xpc_dictionary_get_uint64(object, AUTH_XPC_REPLY_RESULT_VALUE); + } + } else if (xpc_get_type(object) == XPC_TYPE_ERROR) { + if (XPC_ERROR_CONNECTION_INVALID == object) { + // If the connection drops, return an "auth undefined" result, because we cannot continue + } else if (XPC_ERROR_CONNECTION_INTERRUPTED == object) { + // If the agent dies, return an "auth undefined" result, because we cannot continue + } + } + xpc_release(object); + + xpc_release(hintsArray); + xpc_release(contextArray); + xpc_release(immutableHintsArray); + xpc_release(requestObject); + + return status; +} + +void SecurityAgentXPCQuery::checkResult() +{ + // now check the OSStatus return from the server side + switch (mLastResult) { + case kAuthorizationResultAllow: return; + case kAuthorizationResultDeny: + case kAuthorizationResultUserCanceled: CssmError::throwMe(CSSM_ERRCODE_USER_CANCELED); + default: MacOSError::throwMe(errAuthorizationInternal); + } +} + +// +// Perform the "rogue app" access query dialog +// +QueryKeychainUse::QueryKeychainUse(bool needPass, const Database *db) + : mPassphraseCheck(NULL) +{ + // if passphrase checking requested, save KeychainDatabase reference + // (will quietly disable check if db isn't a keychain) + if (needPass) + mPassphraseCheck = dynamic_cast(db); + + setTerminateOnSleep(true); +} + +Reason QueryKeychainUse::queryUser (const char *database, const char *description, AclAuthorization action) +{ + Reason reason = SecurityAgent::noReason; + int retryCount = 0; + OSStatus status; + AuthValueVector arguments; + AuthItemSet hints, context; + +#if defined(NOSA) + if (getenv("NOSA")) { + char answer[maxPassphraseLength+10]; + + string applicationPath; + AuthItem *applicationPathItem = mClientHints.find(AGENT_HINT_APPLICATION_PATH); + if (applicationPathItem) + applicationPathItem->getString(applicationPath); + + getNoSA(answer, sizeof(answer), "Allow %s to do %d on %s in %s? [yn][g]%s ", + applicationPath.c_str(), int(action), (description ? description : "[NULL item]"), + (database ? database : "[NULL database]"), + mPassphraseCheck ? ":passphrase" : ""); + // turn passphrase (no ':') into y:passphrase + if (mPassphraseCheck && !strchr(answer, ':')) { + memmove(answer+2, answer, strlen(answer)+1); + memcpy(answer, "y:", 2); + } + + allow = answer[0] == 'y'; + remember = answer[1] == 'g'; + return SecurityAgent::noReason; + } +#endif + + // prepopulate with client hints + hints.insert(mClientHints.begin(), mClientHints.end()); + + // put action/operation (sint32) into hints + hints.insert(AuthItemRef(AGENT_HINT_ACL_TAG, AuthValueOverlay(sizeof(action), static_cast(&action)))); + + // item name into hints + + hints.insert(AuthItemRef(AGENT_HINT_KEYCHAIN_ITEM_NAME, AuthValueOverlay(description ? (uint32_t)strlen(description) : 0, const_cast(description)))); + + // keychain name into hints + hints.insert(AuthItemRef(AGENT_HINT_KEYCHAIN_PATH, AuthValueOverlay(database ? (uint32_t)strlen(database) : 0, const_cast(database)))); + + if (mPassphraseCheck) + { + create("builtin", "confirm-access-password", noSecuritySession); + + CssmAutoData data(Allocator::standard(Allocator::sensitive)); + + do + { + + AuthItemRef triesHint(AGENT_HINT_TRIES, AuthValueOverlay(sizeof(retryCount), &retryCount)); + hints.erase(triesHint); hints.insert(triesHint); // replace + + if (retryCount++ > kMaximumAuthorizationTries) + { + reason = SecurityAgent::tooManyTries; + } + + AuthItemRef retryHint(AGENT_HINT_RETRY_REASON, AuthValueOverlay(sizeof(reason), &reason)); + hints.erase(retryHint); hints.insert(retryHint); // replace + + setInput(hints, context); + status = invoke(); + + if (retryCount > kMaximumAuthorizationTries) + { + return reason; + } + + checkResult(); + + AuthItem *passwordItem = mOutContext.find(kAuthorizationEnvironmentPassword); + if (!passwordItem) + continue; + + passwordItem->getCssmData(data); + } + while ((reason = (const_cast(mPassphraseCheck)->decode(data) ? SecurityAgent::noReason : SecurityAgent::invalidPassphrase))); + } + else + { + create("builtin", "confirm-access", noSecuritySession); + setInput(hints, context); + invoke(); + } + + readChoice(); + + return reason; +} + +// +// Perform code signature ACL access adjustment dialogs +// +bool QueryCodeCheck::operator () (const char *aclPath) +{ + OSStatus status; + AuthValueVector arguments; + AuthItemSet hints, context; + +#if defined(NOSA) + if (getenv("NOSA")) { + char answer[10]; + + string applicationPath; + AuthItem *applicationPathItem = mClientHints.find(AGENT_HINT_APPLICATION_PATH); + if (applicationPathItem) + applicationPathItem->getString(applicationPath); + + getNoSA(answer, sizeof(answer), + "Allow %s to match an ACL for %s [yn][g]? ", + applicationPath.c_str(), aclPath ? aclPath : "(unknown)"); + allow = answer[0] == 'y'; + remember = answer[1] == 'g'; + return; + } +#endif + + // prepopulate with client hints + hints.insert(mClientHints.begin(), mClientHints.end()); + + hints.insert(AuthItemRef(AGENT_HINT_APPLICATION_PATH, AuthValueOverlay((uint32_t)strlen(aclPath), const_cast(aclPath)))); + + create("builtin", "code-identity", noSecuritySession); + + setInput(hints, context); + status = invoke(); + + checkResult(); + +// MacOSError::check(status); + + return kAuthorizationResultAllow == mLastResult; +} + + +// +// Obtain passphrases and submit them to the accept() method until it is accepted +// or we can't get another passphrase. Accept() should consume the passphrase +// if it is accepted. If no passphrase is acceptable, throw out of here. +// +Reason QueryOld::query() +{ + Reason reason = SecurityAgent::noReason; + OSStatus status; + AuthValueVector arguments; + AuthItemSet hints, context; + CssmAutoData passphrase(Allocator::standard(Allocator::sensitive)); + int retryCount = 0; + +#if defined(NOSA) + // return the passphrase + if (getenv("NOSA")) { + char passphrase_[maxPassphraseLength]; + getNoSA(passphrase, maxPassphraseLength, "Unlock %s [ to cancel]: ", database.dbName()); + passphrase.copy(passphrase_, strlen(passphrase_)); + return database.decode(passphrase) ? SecurityAgent::noReason : SecurityAgent::invalidPassphrase; + } +#endif + + // prepopulate with client hints + + const char *keychainPath = database.dbName(); + hints.insert(AuthItemRef(AGENT_HINT_KEYCHAIN_PATH, AuthValueOverlay((uint32_t)strlen(keychainPath), const_cast(keychainPath)))); + + hints.insert(mClientHints.begin(), mClientHints.end()); + + create("builtin", "unlock-keychain", noSecuritySession); + + do + { + AuthItemRef triesHint(AGENT_HINT_TRIES, AuthValueOverlay(sizeof(retryCount), &retryCount)); + hints.erase(triesHint); hints.insert(triesHint); // replace + + ++retryCount; + + if (retryCount > maxTries) + { + reason = SecurityAgent::tooManyTries; + } + + AuthItemRef retryHint(AGENT_HINT_RETRY_REASON, AuthValueOverlay(sizeof(reason), &reason)); + hints.erase(retryHint); hints.insert(retryHint); // replace + + setInput(hints, context); + status = invoke(); + + if (retryCount > maxTries) + { + return reason; + } + + checkResult(); + + AuthItem *passwordItem = mOutContext.find(kAuthorizationEnvironmentPassword); + if (!passwordItem) + continue; + + passwordItem->getCssmData(passphrase); + + } + while ((reason = accept(passphrase))); + + return SecurityAgent::noReason; +} + + +// +// Get existing passphrase (unlock) Query +// +Reason QueryOld::operator () () +{ + return query(); +} + + +// +// End-classes for old secrets +// +Reason QueryUnlock::accept(CssmManagedData &passphrase) +{ + if (safer_cast(database).decode(passphrase)) + return SecurityAgent::noReason; + else + return SecurityAgent::invalidPassphrase; +} + +Reason QueryUnlock::retrievePassword(CssmOwnedData &passphrase) { + CssmAutoData pass(Allocator::standard(Allocator::sensitive)); + + AuthItem *passwordItem = mOutContext.find(kAuthorizationEnvironmentPassword); + if (!passwordItem) + return SecurityAgent::invalidPassphrase; + + passwordItem->getCssmData(pass); + + passphrase = pass; + + return SecurityAgent::noReason; +} + +QueryKeybagPassphrase::QueryKeybagPassphrase(Session & session, int32_t tries) : mSession(session), mContext(), mRetries(tries) +{ + setTerminateOnSleep(true); + mContext = mSession.get_current_service_context(); +} + +Reason QueryKeybagPassphrase::query() +{ + Reason reason = SecurityAgent::noReason; + OSStatus status; + AuthValueVector arguments; + AuthItemSet hints, context; + CssmAutoData passphrase(Allocator::standard(Allocator::sensitive)); + int retryCount = 0; + + // prepopulate with client hints + + const char *keychainPath = "iCloud"; + hints.insert(AuthItemRef(AGENT_HINT_KEYCHAIN_PATH, AuthValueOverlay((uint32_t)strlen(keychainPath), const_cast(keychainPath)))); + + hints.insert(mClientHints.begin(), mClientHints.end()); + + create("builtin", "unlock-keychain", noSecuritySession); + + do + { + if (retryCount > mRetries) + { + return SecurityAgent::tooManyTries; + } + + AuthItemRef triesHint(AGENT_HINT_TRIES, AuthValueOverlay(sizeof(retryCount), &retryCount)); + hints.erase(triesHint); hints.insert(triesHint); // replace + + AuthItemRef retryHint(AGENT_HINT_RETRY_REASON, AuthValueOverlay(sizeof(reason), &reason)); + hints.erase(retryHint); hints.insert(retryHint); // replace + + setInput(hints, context); + status = invoke(); + + checkResult(); + + AuthItem *passwordItem = mOutContext.find(kAuthorizationEnvironmentPassword); + if (!passwordItem) + continue; + + passwordItem->getCssmData(passphrase); + + ++retryCount; + } + while ((reason = accept(passphrase))); + + return SecurityAgent::noReason; +} + +Reason QueryKeybagPassphrase::accept(Security::CssmManagedData & password) +{ + if (service_client_kb_unlock(&mContext, password.data(), (int)password.length()) == 0) { + mSession.keybagSetState(session_keybag_unlocked); + return SecurityAgent::noReason; + } else + return SecurityAgent::invalidPassphrase; +} + +QueryKeybagNewPassphrase::QueryKeybagNewPassphrase(Session & session) : QueryKeybagPassphrase(session) {} + +Reason QueryKeybagNewPassphrase::query(CssmOwnedData &oldPassphrase, CssmOwnedData &passphrase) +{ + CssmAutoData pass(Allocator::standard(Allocator::sensitive)); + CssmAutoData oldPass(Allocator::standard(Allocator::sensitive)); + Reason reason = SecurityAgent::noReason; + OSStatus status; + AuthValueVector arguments; + AuthItemSet hints, context; + int retryCount = 0; + + // prepopulate with client hints + + const char *keychainPath = "iCloud"; + hints.insert(AuthItemRef(AGENT_HINT_KEYCHAIN_PATH, AuthValueOverlay((uint32_t)strlen(keychainPath), const_cast(keychainPath)))); + + const char *showResetString = "YES"; + hints.insert(AuthItemRef(AGENT_HINT_SHOW_RESET, AuthValueOverlay((uint32_t)strlen(showResetString), const_cast(showResetString)))); + + hints.insert(mClientHints.begin(), mClientHints.end()); + + create("builtin", "change-passphrase", noSecuritySession); + + AuthItem *resetPassword = NULL; + do + { + if (retryCount > mRetries) + { + return SecurityAgent::tooManyTries; + } + + AuthItemRef triesHint(AGENT_HINT_TRIES, AuthValueOverlay(sizeof(retryCount), &retryCount)); + hints.erase(triesHint); hints.insert(triesHint); // replace + + AuthItemRef retryHint(AGENT_HINT_RETRY_REASON, AuthValueOverlay(sizeof(reason), &reason)); + hints.erase(retryHint); hints.insert(retryHint); // replace + + setInput(hints, context); + status = invoke(); + + checkResult(); + + resetPassword = mOutContext.find(AGENT_CONTEXT_RESET_PASSWORD); + if (resetPassword != NULL) { + return SecurityAgent::resettingPassword; + } + + AuthItem *oldPasswordItem = mOutContext.find(AGENT_PASSWORD); + if (!oldPasswordItem) + continue; + + oldPasswordItem->getCssmData(oldPass); + + ++retryCount; + } + while ((reason = accept(oldPass))); + + if (reason == SecurityAgent::noReason) { + AuthItem *passwordItem = mOutContext.find(AGENT_CONTEXT_NEW_PASSWORD); + if (!passwordItem) + return SecurityAgent::invalidPassphrase; + + passwordItem->getCssmData(pass); + + oldPassphrase = oldPass; + passphrase = pass; + } + + return SecurityAgent::noReason; +} + +QueryPIN::QueryPIN(Database &db) + : QueryOld(db), mPin(Allocator::standard()) +{ + this->inferHints(Server::process()); +} + + +Reason QueryPIN::accept(CssmManagedData &pin) +{ + // no retries for now + mPin = pin; + return SecurityAgent::noReason; +} + + +// +// Obtain passphrases and submit them to the accept() method until it is accepted +// or we can't get another passphrase. Accept() should consume the passphrase +// if it is accepted. If no passphrase is acceptable, throw out of here. +// +Reason QueryNewPassphrase::query() +{ + Reason reason = initialReason; + CssmAutoData passphrase(Allocator::standard(Allocator::sensitive)); + CssmAutoData oldPassphrase(Allocator::standard(Allocator::sensitive)); + + OSStatus status; + AuthValueVector arguments; + AuthItemSet hints, context; + + int retryCount = 0; + +#if defined(NOSA) + if (getenv("NOSA")) { + char passphrase_[maxPassphraseLength]; + getNoSA(passphrase_, maxPassphraseLength, + "New passphrase for %s (reason %d) [ to cancel]: ", + database.dbName(), reason); + return SecurityAgent::noReason; + } +#endif + + // prepopulate with client hints + hints.insert(mClientHints.begin(), mClientHints.end()); + + // keychain name into hints + hints.insert(AuthItemRef(AGENT_HINT_KEYCHAIN_PATH, AuthValueOverlay(database.dbName()))); + + switch (initialReason) + { + case SecurityAgent::newDatabase: + create("builtin", "new-passphrase", noSecuritySession); + break; + case SecurityAgent::changePassphrase: + create("builtin", "change-passphrase", noSecuritySession); + break; + default: + assert(false); + } + + do + { + AuthItemRef triesHint(AGENT_HINT_TRIES, AuthValueOverlay(sizeof(retryCount), &retryCount)); + hints.erase(triesHint); hints.insert(triesHint); // replace + + if (++retryCount > maxTries) + { + reason = SecurityAgent::tooManyTries; + } + + AuthItemRef retryHint(AGENT_HINT_RETRY_REASON, AuthValueOverlay(sizeof(reason), &reason)); + hints.erase(retryHint); hints.insert(retryHint); // replace + + setInput(hints, context); + status = invoke(); + + if (retryCount > maxTries) + { + return reason; + } + + checkResult(); + + if (SecurityAgent::changePassphrase == initialReason) + { + AuthItem *oldPasswordItem = mOutContext.find(AGENT_PASSWORD); + if (!oldPasswordItem) + continue; + + oldPasswordItem->getCssmData(oldPassphrase); + } + + AuthItem *passwordItem = mOutContext.find(AGENT_CONTEXT_NEW_PASSWORD); + if (!passwordItem) + continue; + + passwordItem->getCssmData(passphrase); + + } + while ((reason = accept(passphrase, (initialReason == SecurityAgent::changePassphrase) ? &oldPassphrase.get() : NULL))); + + return SecurityAgent::noReason; +} + + +// +// Get new passphrase Query +// +Reason QueryNewPassphrase::operator () (CssmOwnedData &oldPassphrase, CssmOwnedData &passphrase) +{ + if (Reason result = query()) + return result; // failed + passphrase = mPassphrase; + oldPassphrase = mOldPassphrase; + return SecurityAgent::noReason; // success +} + +Reason QueryNewPassphrase::accept(CssmManagedData &passphrase, CssmData *oldPassphrase) +{ + //@@@ acceptance criteria are currently hardwired here + //@@@ This validation presumes ASCII - UTF8 might be more lenient + + // if we have an old passphrase, check it + if (oldPassphrase && !safer_cast(database).validatePassphrase(*oldPassphrase)) + return SecurityAgent::oldPassphraseWrong; + + // sanity check the new passphrase (but allow user override) + if (!(mPassphraseValid && passphrase.get() == mPassphrase)) { + mPassphrase = passphrase; + if (oldPassphrase) mOldPassphrase = *oldPassphrase; + mPassphraseValid = true; + if (mPassphrase.length() == 0) + return SecurityAgent::passphraseIsNull; + if (mPassphrase.length() < 6) + return SecurityAgent::passphraseTooSimple; + } + + // accept this + return SecurityAgent::noReason; +} + +// +// Get a passphrase for unspecified use +// +Reason QueryGenericPassphrase::operator () (const CssmData *prompt, bool verify, + string &passphrase) +{ + return query(prompt, verify, passphrase); +} + +Reason QueryGenericPassphrase::query(const CssmData *prompt, bool verify, + string &passphrase) +{ + Reason reason = SecurityAgent::noReason; + OSStatus status; // not really used; remove? + AuthValueVector arguments; + AuthItemSet hints, context; + +#if defined(NOSA) + if (getenv("NOSA")) { + // FIXME 3690984 + return SecurityAgent::noReason; + } +#endif + + hints.insert(mClientHints.begin(), mClientHints.end()); + hints.insert(AuthItemRef(AGENT_HINT_CUSTOM_PROMPT, AuthValueOverlay(prompt ? (UInt32)prompt->length() : 0, prompt ? prompt->data() : NULL))); + // XXX/gh defined by dmitch but no analogous hint in + // AuthorizationTagsPriv.h: + // CSSM_ATTRIBUTE_ALERT_TITLE (optional alert panel title) + + if (false == verify) { // import + create("builtin", "generic-unlock", noSecuritySession); + } else { // verify passphrase (export) + // new-passphrase-generic works with the pre-4 June 2004 agent; + // generic-new-passphrase is required for the new agent + create("builtin", "generic-new-passphrase", noSecuritySession); + } + + AuthItem *passwordItem; + + do { + setInput(hints, context); + status = invoke(); + checkResult(); + passwordItem = mOutContext.find(AGENT_PASSWORD); + + } while (!passwordItem); + + passwordItem->getString(passphrase); + + return reason; +} + + +// +// Get a DB blob's passphrase--keychain synchronization +// +Reason QueryDBBlobSecret::operator () (DbHandle *dbHandleArray, uint8 dbHandleArrayCount, DbHandle *dbHandleAuthenticated) +{ + return query(dbHandleArray, dbHandleArrayCount, dbHandleAuthenticated); +} + +Reason QueryDBBlobSecret::query(DbHandle *dbHandleArray, uint8 dbHandleArrayCount, DbHandle *dbHandleAuthenticated) +{ + Reason reason = SecurityAgent::noReason; + CssmAutoData passphrase(Allocator::standard(Allocator::sensitive)); + OSStatus status; // not really used; remove? + AuthValueVector arguments; + AuthItemSet hints/*NUKEME*/, context; + +#if defined(NOSA) + if (getenv("NOSA")) { + // FIXME akin to 3690984 + return SecurityAgent::noReason; + } +#endif + + hints.insert(mClientHints.begin(), mClientHints.end()); + create("builtin", "generic-unlock-kcblob", noSecuritySession); + + AuthItem *secretItem; + + int retryCount = 0; + + do { + AuthItemRef triesHint(AGENT_HINT_TRIES, AuthValueOverlay(sizeof(retryCount), &retryCount)); + hints.erase(triesHint); hints.insert(triesHint); // replace + + if (++retryCount > maxTries) + { + reason = SecurityAgent::tooManyTries; + } + + AuthItemRef retryHint(AGENT_HINT_RETRY_REASON, AuthValueOverlay(sizeof(reason), &reason)); + hints.erase(retryHint); hints.insert(retryHint); // replace + + setInput(hints, context); + status = invoke(); + checkResult(); + secretItem = mOutContext.find(AGENT_PASSWORD); + if (!secretItem) + continue; + secretItem->getCssmData(passphrase); + + } while ((reason = accept(passphrase, dbHandleArray, dbHandleArrayCount, dbHandleAuthenticated))); + + return reason; +} + +Reason QueryDBBlobSecret::accept(CssmManagedData &passphrase, + DbHandle *dbHandlesToAuthenticate, uint8 dbHandleCount, DbHandle *dbHandleAuthenticated) +{ + DbHandle *currHdl = dbHandlesToAuthenticate; + short index; + Boolean authenticated = false; + for (index=0; index < dbHandleCount && !authenticated; index++) + { + try + { + RefPointer dbToUnlock = Server::keychain(*currHdl); + dbToUnlock->unlockDb(passphrase); + authenticated = true; + *dbHandleAuthenticated = *currHdl; // return the DbHandle that 'passphrase' authenticated with. + } + catch (const CommonError &err) + { + currHdl++; // we failed to authenticate with this one, onto the next one. + } + } + if ( !authenticated ) + return SecurityAgent::invalidPassphrase; + + return SecurityAgent::noReason; +} + +QueryInvokeMechanism::QueryInvokeMechanism(const AuthHostType type, Session &session) : + SecurityAgentQuery(type, session) { } + +void QueryInvokeMechanism::initialize(const string &inPluginId, const string &inMechanismId, const AuthValueVector &inArguments, const SessionId inSessionId) +{ + if (SecurityAgent::Client::init == SecurityAgent::Client::state()) + { + create(inPluginId.c_str(), inMechanismId.c_str(), inSessionId); + mArguments = inArguments; + } +} + +// XXX/cs should return AuthorizationResult +void QueryInvokeMechanism::run(const AuthValueVector &inArguments, AuthItemSet &inHints, AuthItemSet &inContext, AuthorizationResult *outResult) +{ + // prepopulate with client hints + inHints.insert(mClientHints.begin(), mClientHints.end()); + + if (Server::active().inDarkWake()) + CssmError::throwMe(CSSM_ERRCODE_IN_DARK_WAKE); + + setArguments(inArguments); + setInput(inHints, inContext); + MacOSError::check(invoke()); + + if (outResult) *outResult = result(); + + inHints = outHints(); + inContext = outContext(); +} + +void QueryInvokeMechanism::terminateAgent() +{ + terminate(); +} + +// @@@ no pluggable authentication possible! +Reason +QueryKeychainAuth::operator () (const char *database, const char *description, AclAuthorization action, const char *prompt) +{ + Reason reason = SecurityAgent::noReason; + AuthItemSet hints, context; + AuthValueVector arguments; + int retryCount = 0; + string username; + string password; + + using CommonCriteria::Securityd::KeychainAuthLogger; + KeychainAuthLogger logger(mAuditToken, AUE_ssauthint, database, description); + +#if defined(NOSA) + /* XXX/gh probably not complete; stolen verbatim from rogue-app query */ + if (getenv("NOSA")) { + char answer[maxPassphraseLength+10]; + + string applicationPath; + AuthItem *applicationPathItem = mClientHints.find(AGENT_HINT_APPLICATION_PATH); + if (applicationPathItem) + applicationPathItem->getString(applicationPath); + + getNoSA(answer, sizeof(answer), "Allow %s to do %d on %s in %s? [yn][g]%s ", + applicationPath.c_str(), int(action), (description ? description : "[NULL item]"), + (database ? database : "[NULL database]"), + mPassphraseCheck ? ":passphrase" : ""); + // turn passphrase (no ':') into y:passphrase + if (mPassphraseCheck && !strchr(answer, ':')) { + memmove(answer+2, answer, strlen(answer)+1); + memcpy(answer, "y:", 2); + } + + allow = answer[0] == 'y'; + remember = answer[1] == 'g'; + return SecurityAgent::noReason; + } +#endif + + hints.insert(mClientHints.begin(), mClientHints.end()); + + // put action/operation (sint32) into hints + hints.insert(AuthItemRef(AGENT_HINT_ACL_TAG, AuthValueOverlay(sizeof(action), static_cast(&action)))); + + hints.insert(AuthItemRef(AGENT_HINT_CUSTOM_PROMPT, AuthValueOverlay(prompt ? (uint32_t)strlen(prompt) : 0, const_cast(prompt)))); + + // item name into hints + hints.insert(AuthItemRef(AGENT_HINT_KEYCHAIN_ITEM_NAME, AuthValueOverlay(description ? (uint32_t)strlen(description) : 0, const_cast(description)))); + + // keychain name into hints + hints.insert(AuthItemRef(AGENT_HINT_KEYCHAIN_PATH, AuthValueOverlay(database ? (uint32_t)strlen(database) : 0, const_cast(database)))); + + create("builtin", "confirm-access-user-password", noSecuritySession); + + AuthItem *usernameItem; + AuthItem *passwordItem; + + do { + + AuthItemRef triesHint(AGENT_HINT_TRIES, AuthValueOverlay(sizeof(retryCount), &retryCount)); + hints.erase(triesHint); hints.insert(triesHint); // replace + + if (++retryCount > maxTries) + reason = SecurityAgent::tooManyTries; + + if (SecurityAgent::noReason != reason) + { + if (SecurityAgent::tooManyTries == reason) + logger.logFailure(NULL, CommonCriteria::errTooManyTries); + else + logger.logFailure(); + } + + AuthItemRef retryHint(AGENT_HINT_RETRY_REASON, AuthValueOverlay(sizeof(reason), &reason)); + hints.erase(retryHint); hints.insert(retryHint); // replace + + setInput(hints, context); + try + { + invoke(); + checkResult(); + } + catch (...) // user probably clicked "deny" + { + logger.logFailure(); + throw; + } + usernameItem = mOutContext.find(AGENT_USERNAME); + passwordItem = mOutContext.find(AGENT_PASSWORD); + if (!usernameItem || !passwordItem) + continue; + usernameItem->getString(username); + passwordItem->getString(password); + } while ((reason = accept(username, password))); + + if (SecurityAgent::noReason == reason) + logger.logSuccess(); + // else we logged the denial in the loop + + return reason; +} + +Reason +QueryKeychainAuth::accept(string &username, string &passphrase) +{ + const char *user = username.c_str(); + const char *passwd = passphrase.c_str(); + int checkpw_status = checkpw(user, passwd); + + if (checkpw_status != CHECKPW_SUCCESS) + return SecurityAgent::invalidPassphrase; + + return SecurityAgent::noReason; +} + diff --git a/securityd/src/agentquery.h b/securityd/src/agentquery.h new file mode 100644 index 00000000..b0cc1674 --- /dev/null +++ b/securityd/src/agentquery.h @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2000-2005,2007-2010,2012-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@ + */ + + +// +// passphrases - canonical code to obtain passphrases +// +#ifndef _H_AGENTQUERY +#define _H_AGENTQUERY + +#include +#include +#include // some queries do their own authentication +#include +#include "kcdatabase.h" +#include "AuthorizationEngine.h" +#include "authhost.h" +#include "server.h" +#include "session.h" +#include + +using Authorization::AuthItemSet; +using Authorization::AuthValueVector; +using Security::OSXCode; + +// +// base for classes talking to SecurityAgent and authorizationhost +// +class SecurityAgentConnection : public SecurityAgent::Client, +public SecurityAgentConnectionInterface +{ +public: + SecurityAgentConnection(const AuthHostType type = securityAgent, Session &session = Server::session()); + virtual ~SecurityAgentConnection(); + virtual void activate(); + virtual void reconnect(); + virtual void disconnect() { }; + virtual void terminate(); + + AuthHostType hostType() { return mAuthHostType; } + +protected: + AuthHostType mAuthHostType; + RefPointer mHostInstance; + Port mPort; + const RefPointer mConnection; + audit_token_t *mAuditToken; +}; + +// +// base for classes talking to com.apple.security.agent and com.apple.security.authhost +// +class SecurityAgentXPCConnection : public SecurityAgentConnectionInterface +{ +public: + SecurityAgentXPCConnection(const AuthHostType type = securityAgent, Session &session = Server::session()); + virtual ~SecurityAgentXPCConnection(); + virtual void activate(bool ignoreUid); + virtual void reconnect(); + virtual void disconnect() { }; + virtual void terminate(); + + AuthHostType hostType() { return mAuthHostType; } + +protected: + AuthHostType mAuthHostType; + RefPointer mHostInstance; + Session &mSession; + xpc_connection_t mXPCConnection; + xpc_connection_t mXPCStubConnection; + const RefPointer mConnection; + audit_token_t *mAuditToken; + uid_t mNobodyUID; + + bool inDarkWake(); + +}; + +// +// The main SecurityAgent/authorizationhost interaction base class +// +class SecurityAgentQuery : public SecurityAgentConnection +{ +public: + typedef SecurityAgent::Reason Reason; + + SecurityAgentQuery(const AuthHostType type = securityAgent, Session &session = Server::session()); + + + void inferHints(Process &thisProcess); + void addHint(const char *name, const void *value = NULL, UInt32 valueLen = 0, UInt32 flags = 0); + + virtual ~SecurityAgentQuery(); + + virtual void disconnect(); + virtual void terminate(); + void create(const char *pluginId, const char *mechanismId, const SessionId inSessionId); + + void readChoice(); + + bool allow; + bool remember; + +protected: + AuthItemSet mClientHints; +}; + +// +// The main com.apple.security.agent/com.apple.security.authhost interaction base class +// +class SecurityAgentXPCQuery : public SecurityAgentXPCConnection +{ +public: + static void killAllXPCClients(); + + typedef SecurityAgent::Reason Reason; + + SecurityAgentXPCQuery(const AuthHostType type = securityAgent, Session &session = Server::session()); + + + void inferHints(Process &thisProcess); + void addHint(const char *name, const void *value = NULL, UInt32 valueLen = 0, UInt32 flags = 0); + + virtual ~SecurityAgentXPCQuery(); + + virtual void disconnect(); + virtual void terminate(); + void create(const char *pluginId, const char *mechanismId, const SessionId inSessionId); + OSStatus invoke(); + void setTerminateOnSleep(bool terminateOnSleep) {mTerminateOnSleep = terminateOnSleep;} + bool getTerminateOnSleep() {return mTerminateOnSleep;} + void setInput(const AuthItemSet& inHints, const AuthItemSet& inContext) { mInHints = inHints; mInContext = inContext; } + void checkResult(); + + void readChoice(); + + bool allow; + bool remember; + +protected: + AuthItemSet mClientHints; + AuthItemSet mImmutableHints; + AuthItemSet mInHints; + AuthItemSet mInContext; + AuthItemSet mOutHints; + AuthItemSet mOutContext; + bool mAgentConnected; + uint64_t mLastResult; + bool mTerminateOnSleep; +}; + +// +// Specialized for "rogue app" alert queries +// +class QueryKeychainUse : public SecurityAgentXPCQuery { +public: + QueryKeychainUse(bool needPass, const Database *db); + Reason queryUser (const char* database, const char *description, AclAuthorization action); + +private: + const KeychainDatabase *mPassphraseCheck; // NULL to not check passphrase +}; + + +// +// Specialized for code signature adjustment queries +// +class QueryCodeCheck : public SecurityAgentXPCQuery { +public: + bool operator () (const char *aclPath); +}; + + +// +// A query for an existing passphrase +// +class QueryOld : public SecurityAgentXPCQuery { + static const int maxTries = kMaximumAuthorizationTries; +public: + QueryOld(Database &db) : database(db) {setTerminateOnSleep(true);} + + Database &database; + + Reason operator () (); + +protected: + Reason query(); + virtual Reason accept(CssmManagedData &) = 0; +}; + + +class QueryUnlock : public QueryOld { +public: + QueryUnlock(KeychainDatabase &db) : QueryOld(db) { } + Reason retrievePassword(CssmOwnedData &passphrase); + +protected: + Reason accept(CssmManagedData &passphrase); +}; + + +class QueryKeybagPassphrase : public SecurityAgentXPCQuery { +public: + QueryKeybagPassphrase(Session &session, int32_t retries = kMaximumAuthorizationTries); + + Reason query(); + Reason accept(CssmManagedData &passphrase); +protected: + Session &mSession; + service_context_t mContext; + int32_t mRetries; +}; + +class QueryKeybagNewPassphrase : public QueryKeybagPassphrase { +public: + QueryKeybagNewPassphrase(Session &session); + + Reason query(CssmOwnedData &oldPassphrase, CssmOwnedData &passphrase); +}; + +// +// Repurpose QueryUnlock for PIN prompting +// Not very clean - but this stuff is an outdated hack as it is... +// +class QueryPIN : public QueryOld { +public: + QueryPIN(Database &db); + + const CssmData &pin() const { return mPin; } + +protected: + Reason accept(CssmManagedData &pin); + +private: + CssmAutoData mPin; // PIN obtained +}; + + +// +// A query for a new passphrase +// +class QueryNewPassphrase : public SecurityAgentXPCQuery { + static const int maxTries = kMaximumAuthorizationTries; +public: + QueryNewPassphrase(Database &db, Reason reason) : + database(db), initialReason(reason), + mPassphrase(Allocator::standard(Allocator::sensitive)), + mOldPassphrase(Allocator::standard(Allocator::sensitive)), + mPassphraseValid(false) { } + + Database &database; + + Reason operator () (CssmOwnedData &oldPassphrase, CssmOwnedData &passphrase); + +protected: + Reason query(); + virtual Reason accept(CssmManagedData &passphrase, CssmData *oldPassphrase); + +private: + Reason initialReason; + CssmAutoData mPassphrase; + CssmAutoData mOldPassphrase; + bool mPassphraseValid; +}; + + +// +// Generic passphrase query (not associated with a database) +// +class QueryGenericPassphrase : public SecurityAgentXPCQuery { +public: + QueryGenericPassphrase() { } + Reason operator () (const CssmData *prompt, bool verify, + string &passphrase); + +protected: + Reason query(const CssmData *prompt, bool verify, string &passphrase); +}; + + +// +// Generic secret query (not associated with a database) +// +class QueryDBBlobSecret : public SecurityAgentXPCQuery { + static const int maxTries = kMaximumAuthorizationTries; +public: + QueryDBBlobSecret() { } + Reason operator () (DbHandle *dbHandleArray, uint8 dbHandleArrayCount, DbHandle *dbHandleAuthenticated); + +protected: + Reason query(DbHandle *dbHandleArray, uint8 dbHandleArrayCount, DbHandle *dbHandleAuthenticated); + Reason accept(CssmManagedData &passphrase, DbHandle *dbHandlesToAuthenticate, uint8 dbHandleCount, DbHandle *dbHandleAuthenticated); +}; + +class QueryInvokeMechanism : public SecurityAgentQuery, public RefCount { +public: + QueryInvokeMechanism(const AuthHostType type, Session &session); + void initialize(const string &inPluginId, const string &inMechanismId, const AuthValueVector &arguments, const SessionId inSessionId = 0); + void run(const AuthValueVector &inArguments, AuthItemSet &inHints, AuthItemSet &inContext, AuthorizationResult *outResult); + + bool operator () (const string &inPluginId, const string &inMechanismId, const Authorization::AuthValueVector &inArguments, AuthItemSet &inHints, AuthItemSet &inContext, AuthorizationResult *outResult); + void terminateAgent(); + //~QueryInvokeMechanism(); + + AuthValueVector mArguments; +}; + +// hybrid of confirm-access and generic authentication queries, for +// securityd's use; keep the Frankenstein references to yourself +// (the alternative is to ask the user to unlock the system keychain, +// and you don't want that, do you?) +class QueryKeychainAuth : public SecurityAgentXPCQuery { + static const int maxTries = kMaximumAuthorizationTries; +public: + QueryKeychainAuth() { } + // "prompt" can be NULL + Reason operator () (const char *database, const char *description, AclAuthorization action, const char *prompt); + Reason accept(string &username, string &passphrase); +}; + +#endif //_H_AGENTQUERY diff --git a/securityd/src/auditevents.cpp b/securityd/src/auditevents.cpp new file mode 100644 index 00000000..2edfabe2 --- /dev/null +++ b/securityd/src/auditevents.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2009-2010 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@ + */ + + +// +// auditevents - monitor and act upon audit subsystem events +// +#include "auditevents.h" +#include "dtrace.h" +#include +#include "self.h" + +using namespace UnixPlusPlus; +using namespace MachPlusPlus; + + +AuditMonitor::AuditMonitor(Port relay) + : mRelay(relay) +{ +} + +AuditMonitor::~AuditMonitor() +{ +} + + +// +// Endlessly retrieve session events and dispatch them. +// (The current version of MachServer cannot receive FileDesc-based events, +// so we need a monitor thread for this.) +// +void AuditMonitor::action() +{ + au_sdev_handle_t *dev = au_sdev_open(AU_SDEVF_ALLSESSIONS); + int event; + auditinfo_addr_t aia; + + if (NULL == dev) { + Syslog::error("This is bad, man. I've got bad vibes here. Could not open %s: %d", AUDIT_SDEV_PATH, errno); + return; + } + + for (;;) { + if (0 != au_sdev_read_aia(dev, &event, &aia)) { + Syslog::error("au_sdev_read_aia failed: %d\n", errno); + continue; + } + SECURITYD_SESSION_NOTIFY(aia.ai_asid, event, aia.ai_auid); + if (kern_return_t rc = self_client_handleSession(mRelay, mach_task_self(), event, aia.ai_asid)) + Syslog::error("self-send failed (mach error %d)", rc); + } +} diff --git a/securityd/src/auditevents.h b/securityd/src/auditevents.h new file mode 100644 index 00000000..e108f8ed --- /dev/null +++ b/securityd/src/auditevents.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2009-2010 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@ + */ + + +// +// child - track a single child process and its belongings +// +#ifndef _H_AUDITEVENTS +#define _H_AUDITEVENTS + +#include +#include +#include +#include +#include + + +class AuditMonitor : public Thread, public UnixPlusPlus::KQueue { +public: + AuditMonitor(MachPlusPlus::Port relay); + ~AuditMonitor(); + + void action(); + +private: + MachPlusPlus::Port mRelay; +}; + + +#endif //_H_AUDITEVENTS diff --git a/securityd/src/authhost.cpp b/securityd/src/authhost.cpp new file mode 100644 index 00000000..460a26bc --- /dev/null +++ b/securityd/src/authhost.cpp @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2000-2007,2009-2010,2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include "authhost.h" +#include "server.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +static pthread_once_t agent_cred_init = PTHREAD_ONCE_INIT; +static gid_t agent_gid = 92; +static uid_t agent_uid = 92; + +void initialize_agent_creds() +{ + struct passwd *agentUser = getpwnam("securityagent"); + if (agentUser) + { + agent_uid = agentUser->pw_uid; + agent_gid = agentUser->pw_gid; + endpwent(); + } +} + +AuthHostInstance::AuthHostInstance(Session &session, AuthHostType host) : + mHostType(host) +{ + secdebug("authhost", "authhost born (%p)", this); + referent(session); + session.addReference(*this); + if (host == securityAgent) + pthread_once(&agent_cred_init, initialize_agent_creds); +} + +AuthHostInstance::~AuthHostInstance() +{ + secdebug("authhost", "authhost died (%p)", this); +} + +Session &AuthHostInstance::session() const +{ + return referent(); +} + +bool AuthHostInstance::inDarkWake() +{ + return session().server().inDarkWake(); +} + +void +AuthHostInstance::childAction() +{ + // switch to desired session + CommonCriteria::AuditInfo &audit = this->session().auditInfo(); + audit.get(audit.sessionId()); + audit.set(); + //this->session().auditInfo().set(); + + // Setup the environment for the SecurityAgent + unsetenv("USER"); + unsetenv("LOGNAME"); + unsetenv("HOME"); + + // close down any files that might have been open at this point + int maxDescriptors = getdtablesize (); + int i; + + int devnull = open(_PATH_DEVNULL, O_RDWR, 0); + if (devnull >= 0) for (i = 0; i < 3; ++i) + { + dup2(devnull, i); + } + + for (i = 3; i < maxDescriptors; ++i) + { + close (i); + } + + // construct path to SecurityAgent + char agentExecutable[PATH_MAX + 1]; + const char *path = getenv("SECURITYAGENT"); + if (!path) + path = "/System/Library/CoreServices/SecurityAgent.app"; + secdebug("adhoc", "hostType = %d", mHostType); + + if ((mHostType == userAuthHost) || (mHostType == privilegedAuthHost)) + { + snprintf(agentExecutable, sizeof(agentExecutable), "%s/Contents/Resources/authorizationhost", path); + secdebug("AuthHostInstance", "execl(%s)", agentExecutable); + execl(agentExecutable, agentExecutable, NULL); + } + else + { + snprintf(agentExecutable, sizeof(agentExecutable), "%s/Contents/MacOS/SecurityAgent", path); + + pid_t pid = getpid(); + if ((pid <= 0) || + sysctlbyname("vfs.generic.noremotehang", NULL, NULL, &pid, sizeof(pid))) + syslog(LOG_ERR, "Failed to set vfs.generic.noremotehang for pid(%d)", pid); + + setgroups(1, &agent_gid); + setgid(agent_gid); + setuid(agent_uid); + + secdebug("AuthHostInstance", "execl(%s) as user (%d,%d)", agentExecutable, agent_uid, agent_gid); + execl(agentExecutable, agentExecutable, NULL); + } + + secdebug("AuthHostInstance", "execl failed, errno=%d", errno); + // Unconditional suicide follows. + _exit(1); +} + +// @@@ these definitions and the logic in lookup() should move into +// libsecurity_agent +#define SECURITYAGENT_BOOTSTRAP_NAME_BASE "com.apple.SecurityAgent" +#define AUTHORIZATIONHOST_BOOTSTRAP_NAME_BASE "com.apple.authorizationhost" + +mach_port_t +AuthHostInstance::lookup(SessionId jobId) +{ + StLock _(*this); + + mach_port_t pluginhostPort = MACH_PORT_NULL; + kern_return_t result; + const char *serviceName; + /* PR-7483709 const */ uuid_t instanceId = UUID_INITIALIZER_FROM_SESSIONID(jobId); + uuid_string_t s; + + if ((mHostType == securityAgent)) { + if (!(session().attributes() & sessionHasGraphicAccess)) + CssmError::throwMe(CSSM_ERRCODE_NO_USER_INTERACTION); + if (inDarkWake()) + CssmError::throwMe(CSSM_ERRCODE_IN_DARK_WAKE); + } + + if (mHostType == securityAgent) + serviceName = SECURITYAGENT_BOOTSTRAP_NAME_BASE; + else + serviceName = AUTHORIZATIONHOST_BOOTSTRAP_NAME_BASE; + + secdebug("AuthHostInstance", "looking up %s instance %s", serviceName, + uuid_to_string(instanceId, s)); // XXX/gh debugging + if ((result = bootstrap_look_up3(bootstrap_port, serviceName, + &pluginhostPort, 0, instanceId, BOOTSTRAP_SPECIFIC_INSTANCE)) != KERN_SUCCESS) { + + Syslog::error("error %d looking up %s instance %s", result, serviceName, + uuid_to_string(instanceId, s)); + } else + secdebug("AuthHostInstance", "port = %x", (unsigned int)pluginhostPort); + + return pluginhostPort; +} + +Port AuthHostInstance::activate() +{ + StLock _(*this); + if (state() != alive) + { + if ((mHostType == securityAgent)) { + if (!(session().attributes() & sessionHasGraphicAccess)) + CssmError::throwMe(CSSM_ERRCODE_NO_USER_INTERACTION); + if (inDarkWake()) + CssmError::throwMe(CSSM_ERRCODE_IN_DARK_WAKE); + } + + fork(); + switch (ServerChild::state()) { + case Child::alive: + secdebug("AuthHostInstance", "%p (pid %d) has launched", this, pid()); + break; + case Child::dead: + secdebug("AuthHostInstance", "%p (pid %d) failed on startup", this, pid()); + break; + default: + assert(false); + } + } + + if (!ready()) + CssmError::throwMe(CSSM_ERRCODE_NO_USER_INTERACTION); + + return servicePort(); +} diff --git a/securityd/src/authhost.h b/securityd/src/authhost.h new file mode 100644 index 00000000..d422681d --- /dev/null +++ b/securityd/src/authhost.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2004,2009-2010,2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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_AUTHHOST +#define _H_AUTHHOST + +#include + +#include "structure.h" +#include "child.h" + +class Session; + +typedef enum { + privilegedAuthHost, + securityAgent, + userAuthHost +} AuthHostType; + +class AuthHostInstance : public PerSession, public ServerChild { +public: + AuthHostInstance(Session &session, AuthHostType host); + virtual ~AuthHostInstance(); + + Session &session() const; + mach_port_t lookup(SessionId jobId); + Port activate(); + +protected: + void childAction(); + +private: + AuthHostType mHostType; + + bool inDarkWake(); +}; + +#endif /* _H_AUTHHOST */ diff --git a/securityd/src/authority.cpp b/securityd/src/authority.cpp new file mode 100644 index 00000000..5817e517 --- /dev/null +++ b/securityd/src/authority.cpp @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2000-2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + */ + + +// +// authority - authorization manager +// +#include "authority.h" +#include "server.h" +#include "connection.h" +#include "session.h" +#include "process.h" + +#include + +#include // AuditToken + +#include + +using Authorization::AuthItemSet; +using Authorization::AuthItemRef; +using Authorization::AuthValue; +using Authorization::AuthValueOverlay; + +// +// The global dictionary of extant AuthorizationTokens +// +//AuthorizationToken::AuthMap AuthorizationToken::authMap; // set of extant authorizations +//@@@ Workaround ONLY! Don't destruct this map on termination +AuthorizationToken::AuthMap &AuthorizationToken::authMap = *new AuthMap; // set of extant authorizations +Mutex AuthorizationToken::authMapLock; // lock for mAuthorizations (only) + + + +// +// Create an authorization token. +// +AuthorizationToken::AuthorizationToken(Session &ssn, const CredentialSet &base, +const audit_token_t &auditToken, bool operateAsLeastPrivileged) + : mBaseCreds(base), mTransferCount(INT_MAX), + mCreatorPid(Server::process().pid()), + mCreatorAuditToken(auditToken), + mOperatesAsLeastPrivileged(operateAsLeastPrivileged) +{ + mCreatorUid = mCreatorAuditToken.euid(); + mCreatorGid = mCreatorAuditToken.egid(); + + if (sandbox_check(mCreatorPid, "authorization-right-obtain", SANDBOX_CHECK_NO_REPORT) != 0) + mCreatorSandboxed = true; + else + mCreatorSandboxed = false; + + { + Process &thisProcess = Server::process(); + StLock _(thisProcess); + if (SecCodeRef code = thisProcess.currentGuest()) + MacOSError::check(SecCodeCopyStaticCode(code, kSecCSDefaultFlags, &mCreatorCode.aref())); + } + + // link to session + referent(ssn); + + // generate our (random) handle + Server::active().random(mHandle); + + // register handle in the global map + StLock _(authMapLock); + authMap[mHandle] = this; + + // all ready + secdebug("SSauth", "Authorization %p created using %d credentials; owner=%p", + this, int(mBaseCreds.size()), mCreatorCode.get()); +} + +AuthorizationToken::~AuthorizationToken() +{ + // we better be clean + assert(mUsingProcesses.empty()); + + secdebug("SSauth", "Authorization %p destroyed", this); +} + + +Session &AuthorizationToken::session() const +{ + return referent(); +} + + +std::string AuthorizationToken::creatorPath() const +{ + if (mCreatorCode) { + StLock _(mLock); + CFRef path; + if (SecCodeCopyPath(mCreatorCode, kSecCSDefaultFlags, &path.aref()) == noErr) + return cfString(path); + } + return "unknown"; +} + + +// +// Locate an authorization given its blob. +// +AuthorizationToken &AuthorizationToken::find(const AuthorizationBlob &blob) +{ + StLock _(authMapLock); + AuthMap::iterator it = authMap.find(blob); + if (it == authMap.end()) + Authorization::Error::throwMe(errAuthorizationInvalidRef); + return *it->second; +} + + +// +// Handle atomic deletion of AuthorizationToken objects +// +AuthorizationToken::Deleter::Deleter(const AuthorizationBlob &blob) + : lock(authMapLock) +{ + AuthMap::iterator it = authMap.find(blob); + if (it == authMap.end()) + Authorization::Error::throwMe(errAuthorizationInvalidRef); + mAuth = it->second; +} + +void AuthorizationToken::Deleter::remove() +{ + if (mAuth) { + authMap.erase(mAuth->handle()); + mAuth = NULL; + } +} + + +// +// Given a set of credentials, add it to our private credentials and return the result +// +// must hold Session::mCredsLock +CredentialSet AuthorizationToken::effectiveCreds() const +{ + secdebug("SSauth", "Authorization %p grabbing session %p creds %p", + this, &session(), &session().authCredentials()); + CredentialSet result = session().authCredentials(); + for (CredentialSet::const_iterator it = mBaseCreds.begin(); it != mBaseCreds.end(); it++) + if (!(*it)->isShared()) + result.insert(*it); + return result; +} + + +// +// Add more credential dependencies to an authorization +// +// must hold Session::mCredsLock +void AuthorizationToken::mergeCredentials(const CredentialSet &add) +{ + secdebug("SSauth", "Authorization %p merge creds %p", this, &add); + for (CredentialSet::const_iterator it = add.begin(); it != add.end(); it++) { + mBaseCreds.erase(*it); + mBaseCreds.insert(*it); + } + secdebug("SSauth", "Authorization %p merged %d new credentials for %d total", + this, int(add.size()), int(mBaseCreds.size())); +} + + +// +// Register a new process that uses this authorization token. +// This is an idempotent operation. +// +void AuthorizationToken::addProcess(Process &proc) +{ + StLock _(mLock); + mUsingProcesses.insert(&proc); + secdebug("SSauth", "Authorization %p added process %p(%d)", this, &proc, proc.pid()); +} + + +// +// Completely unregister client process. +// It does not matter how often it was registered with addProcess before. +// This returns true if no more processes use this token. Presumably you +// would then want to clean up, though that's up to you. +// +bool AuthorizationToken::endProcess(Process &proc) +{ + StLock _(mLock); + assert(mUsingProcesses.find(&proc) != mUsingProcesses.end()); + mUsingProcesses.erase(&proc); + secdebug("SSauth", "Authorization %p removed process %p(%d)%s", + this, &proc, proc.pid(), mUsingProcesses.empty() ? " FINAL" : ""); + return mUsingProcesses.empty(); +} + + +// +// Check whether internalization/externalization is allowed +// +bool AuthorizationToken::mayExternalize(Process &) const +{ + return mTransferCount > 0; +} + +bool AuthorizationToken::mayInternalize(Process &, bool countIt) +{ + StLock _(mLock); + if (mTransferCount > 0) { + if (countIt) { + mTransferCount--; + secdebug("SSauth", "Authorization %p decrement intcount to %d", this, mTransferCount); + } + return true; + } + return false; +} + +AuthItemSet +AuthorizationToken::infoSet(AuthorizationString tag) +{ + StLock _(mLock); // consider a separate lock + + AuthItemSet tempSet; + + if (tag) + { + AuthItemSet::iterator found = find_if(mInfoSet.begin(), mInfoSet.end(), + Authorization::FindAuthItemByRightName(tag)); + if (found != mInfoSet.end()) + tempSet.insert(AuthItemRef(*found)); + + } + else + tempSet = mInfoSet; + + secdebug("SSauth", "Authorization %p returning copy of context %s%s.", this, tag ? "for tag " : "", tag ? "" : tag); + + return tempSet; +} + +void +AuthorizationToken::setInfoSet(AuthItemSet &newInfoSet, bool savePassword) +{ + StLock _(mLock); // consider a separate lock + secdebug("SSauth", "Authorization %p setting new context", this); + + AuthItemSet::const_iterator end = mInfoSet.end(); + for (AuthItemSet::const_iterator it = mInfoSet.begin(); it != end; ++it) { + const AuthItemRef &item = *it; + if (0 == strcmp(item->name(), "password")) { + mSavedPassword.clear(); + mSavedPassword.insert(item); + } + } + + if (true == savePassword) + newInfoSet.insert(mSavedPassword.begin(), mSavedPassword.end()); + + mInfoSet = newInfoSet; +} + +// This is destructive (non-merging) +void +AuthorizationToken::setCredentialInfo(const Credential &inCred, bool savePassword) +{ + AuthItemSet dstInfoSet; + + uid_t uid = inCred->uid(); + AuthItemRef uidHint("uid", AuthValueOverlay(sizeof(uid), &uid)); + dstInfoSet.insert(uidHint); + + AuthItemRef userHint("username", AuthValueOverlay(inCred->name()), 0); + dstInfoSet.insert(userHint); + + setInfoSet(dstInfoSet, savePassword); +} + +void +AuthorizationToken::clearInfoSet() +{ + AuthItemSet dstInfoSet; + secdebug("SSauth", "Authorization %p clearing context", this); + setInfoSet(dstInfoSet, false); +} + +void +AuthorizationToken::scrubInfoSet(bool savePassword) +{ + AuthItemSet srcInfoSet = infoSet(), dstInfoSet; + AuthItemSet::const_iterator end = srcInfoSet.end(); + for (AuthItemSet::const_iterator it = srcInfoSet.begin(); it != end; ++it) + { + const AuthItemRef &item = *it; + if (item->flags() == kAuthorizationContextFlagExtractable) + dstInfoSet.insert(item); + } + secdebug("SSauth", "Authorization %p scrubbing context", this); + setInfoSet(dstInfoSet, savePassword); +} diff --git a/securityd/src/authority.h b/securityd/src/authority.h new file mode 100644 index 00000000..554bb9d6 --- /dev/null +++ b/securityd/src/authority.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2000-2007,2010-2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + */ + + +// +// authority - authorization manager +// +#ifndef _H_AUTHORITY +#define _H_AUTHORITY + +#include +#include +#include "database.h" +#include "credential.h" +#include + +using Authorization::AuthItemSet; +using Authorization::Credential; +using Authorization::CredentialSet; +using Security::CommonCriteria::AuditToken; + +class Process; +class Session; + +class AuthorizationToken : public PerSession { +public: + AuthorizationToken(Session &ssn, const CredentialSet &base, const audit_token_t &auditToken, bool operateAsLeastPrivileged = false); + ~AuthorizationToken(); + + Session &session() const; + + const AuthorizationBlob &handle() const { return mHandle; } + const CredentialSet &baseCreds() const { return mBaseCreds; } + CredentialSet effectiveCreds() const; + + typedef CredentialSet::iterator iterator; + iterator begin() { return mBaseCreds.begin(); } + iterator end() { return mBaseCreds.end(); } + + // add more credential dependencies + void mergeCredentials(const CredentialSet &more); + + // maintain process-owning links + void addProcess(Process &proc); + bool endProcess(Process &proc); + + // access control for external representations + bool mayExternalize(Process &proc) const; + bool mayInternalize(Process &proc, bool countIt = true); + + uid_t creatorUid() const { return mCreatorUid; } + gid_t creatorGid() const { return mCreatorGid; } + SecStaticCodeRef creatorCode() const { return mCreatorCode; } + std::string creatorPath() const; + pid_t creatorPid() const { return mCreatorPid; } + bool creatorSandboxed() const { return mCreatorSandboxed; } + + const AuditToken &creatorAuditToken() const { return mCreatorAuditToken; } + + AuthItemSet infoSet(AuthorizationString tag = NULL); + void setInfoSet(AuthItemSet &newInfoSet, bool savePassword); + void setCredentialInfo(const Credential &inCred, bool savePassword); + void clearInfoSet(); + void scrubInfoSet(bool savePassword); + bool operatesAsLeastPrivileged() const { return mOperatesAsLeastPrivileged; } + +public: + static AuthorizationToken &find(const AuthorizationBlob &blob); + + class Deleter { + public: + Deleter(const AuthorizationBlob &blob); + + void remove(); + operator AuthorizationToken &() const { return *mAuth; } + + private: + RefPointer mAuth; + StLock lock; + }; + +private: + mutable Mutex mLock; // object lock + AuthorizationBlob mHandle; // official randomized blob marker + CredentialSet mBaseCreds; // credentials we're based on + + unsigned int mTransferCount; // number of internalizations remaining + + typedef set ProcessSet; + ProcessSet mUsingProcesses; // set of process objects using this token + + uid_t mCreatorUid; // Uid of process that created this authorization + gid_t mCreatorGid; // Gid of process that created this authorization + CFCopyRef mCreatorCode; // code reference to creator + pid_t mCreatorPid; // Pid of processs that created this authorization + bool mCreatorSandboxed; // A record of whether or not the creator was Sandboxed + + AuditToken mCreatorAuditToken; // Audit token of the process that created this authorization + + AuthItemSet mInfoSet; // Side band info gathered from evaluations in this session + + bool mOperatesAsLeastPrivileged; + + AuthItemSet mSavedPassword; + +private: + typedef map > AuthMap; + static AuthMap &authMap; // set of extant authorizations + static Mutex authMapLock; // lock for mAuthorizations (only) +}; + +#endif //_H_AUTHORITY diff --git a/securityd/src/ccaudit_extensions.cpp b/securityd/src/ccaudit_extensions.cpp new file mode 100644 index 00000000..2ffcd5ea --- /dev/null +++ b/securityd/src/ccaudit_extensions.cpp @@ -0,0 +1,441 @@ +/* + * ccaudit_extensions.cpp + * securityd + * + * Created by G H on 3/24/09. + * Copyright (c) 2009 Apple Inc. All Rights Reserved. + * + */ + +#include +#include +#include // vsnprintf() +#include // va_start(), et al. +#include +#include // memcpy() +#include // AUE_ssauth* +#include +#include +#include +#include "ccaudit_extensions.h" + +namespace Security +{ + +namespace CommonCriteria +{ + +namespace Securityd +{ + +// +// AuditLogger +// +AuditLogger::AuditLogger(const audit_token_t *srcToken, short auEvent) + : mAuditFd(-1), mEvent(auEvent), mClientInfoSet(false) +{ + setClientInfo(srcToken); +} + +AuditLogger::AuditLogger(const AuditToken &srcToken, short auEvent) + : mAuditFd(-1), mEvent(auEvent), mClientInfoSet(false) +{ + setClientInfo(srcToken); +} + +AuditLogger::~AuditLogger() +{ + close(); +} + +bool +AuditLogger::open() +{ + if (-1 != mAuditFd) + return true; + + // @@@ use audit_get_cond() when it's available + int acond = au_get_state(); + switch (acond) + { + case AUC_NOAUDIT: + return false; + case AUC_AUDITING: + break; + default: + logInternalError("error checking auditing status (%d)", acond); + UnixError::throwMe(acond); // assume it's a Unix error + } + if ((mAuditFd = au_open()) < 0) + { + logInternalError("au_open() failed (%s)", strerror(errno)); + UnixError::throwMe(errno); + } + return true; +} + +void +AuditLogger::close(bool writeLog/* = true*/) +{ + if (-1 != mAuditFd) + { + int keep = writeLog == true ? AU_TO_WRITE : AU_TO_NO_WRITE; + int error = au_close(mAuditFd, keep, mEvent); + mAuditFd = -1; + if (writeLog == true && error < 0) + { + logInternalError("au_close() failed; record not committed"); + UnixError::throwMe(error); + } + } +} + +void +AuditLogger::setClientInfo(const audit_token_t *srcToken) +{ + assert(srcToken); + audit_token_to_au32(*srcToken, &mAuditId, &mEuid, &mEgid, &mRuid, &mRgid, &mPid, &mAuditSessionId, &mOldTerminalId); + + mTerminalId.at_type = AU_IPv4; + mTerminalId.at_addr[0] = mOldTerminalId.machine; + mTerminalId.at_port = mOldTerminalId.port; + + mClientInfoSet = true; +} + +void +AuditLogger::setClientInfo(const AuditToken &srcToken) +{ + mAuditId = srcToken.auditId(); + mEuid = srcToken.euid(); + mEgid = srcToken.egid(); + mRuid = srcToken.ruid(); + mRgid = srcToken.rgid(); + mPid = srcToken.pid(); + mAuditSessionId = srcToken.sessionId(); + memcpy(&mOldTerminalId, &(srcToken.terminalId()), sizeof(mOldTerminalId)); + + mTerminalId.at_type = AU_IPv4; + mTerminalId.at_addr[0] = mOldTerminalId.machine; + mTerminalId.at_port = mOldTerminalId.port; + + mClientInfoSet = true; +} + +void +AuditLogger::writeToken(token_t *token, const char *name) +{ + const char *tokenName = name ? name : ""; + if (NULL == token) + { + logInternalError("Invalid '%s' token", tokenName); + close(); + UnixError::throwMe(EPERM); // per audit_submit() + } + if (au_write(mAuditFd, token) < 0) + { + logInternalError("Error writing '%s' token (%s)", tokenName, strerror(errno)); + close(); + UnixError::throwMe(errno); + } +} + +void +AuditLogger::writeSubject() +{ + assert(mClientInfoSet); + + token_t *token; + + // @@@ terminal ID is not carried in the audit trailer nowadays, but + // this code should be harmless: it replicates the current logic in + // audit_submit() + if (AU_IPv4 == mTerminalId.at_type) + token = au_to_subject32(mAuditId, mEuid, mEgid, mRuid, mRgid, mPid, mAuditSessionId, &mOldTerminalId); + else + token = au_to_subject_ex(mAuditId, mEuid, mEgid, mRuid, mRgid, mPid, mAuditSessionId, &mTerminalId); + writeToken(token, "subject"); +} + +void +AuditLogger::writeReturn(char status, int reterr) +{ + writeToken(au_to_return32(status, reterr), "return"); +} + +void +AuditLogger::logSuccess() +{ + if (false == open()) + return; + writeCommon(); + writeReturn(0, 0); + close(); +} + +void +AuditLogger::logFailure(const char *errMsg, int errcode) +{ + if (false == open()) + return; + writeCommon(); + if (errMsg) + writeToken(au_to_text(errMsg), "evaluation error"); + writeReturn(EPERM, errcode); + close(); +} + +// cribbed from audit_submit() +void +AuditLogger::logInternalError(const char *fmt, ...) +{ + va_list ap; + char text[MAX_AUDITSTRING_LEN]; + + if (fmt != NULL) + { + int error = errno; + va_start(ap, fmt); + (void)vsnprintf(text, MAX_AUDITSTRING_LEN, fmt, ap); + va_end(ap); + syslog(LOG_AUTH | LOG_ERR, "%s", text); + errno = error; + } +} + +// +// KeychainAuthLogger +// +const char *KeychainAuthLogger::sysKCAuthStr = "System keychain authorization"; +const char *KeychainAuthLogger::unknownKCStr = ""; +const char *KeychainAuthLogger::unknownItemStr = ""; + +KeychainAuthLogger::KeychainAuthLogger(const audit_token_t *srcToken, short auEvent) + : AuditLogger(srcToken, auEvent), mDatabase(unknownKCStr), + mItem(unknownItemStr) +{ +} + +KeychainAuthLogger::KeychainAuthLogger(const AuditToken &srcToken, short auEvent) + : AuditLogger(srcToken, auEvent), mDatabase(unknownKCStr), + mItem(unknownItemStr) +{ +} + +KeychainAuthLogger::KeychainAuthLogger(const audit_token_t *srcToken, short auEvent, const char *database, const char *item) + : AuditLogger(srcToken, auEvent) +{ + setDbName(database); + setItemName(item); +} + +KeychainAuthLogger::KeychainAuthLogger(const AuditToken &srcToken, short auEvent, const char *database, const char *item) + : AuditLogger(srcToken, auEvent) +{ + setDbName(database); + setItemName(item); +} + +void +KeychainAuthLogger::setDbName(const char *database) +{ + mDatabase = database ? database : unknownKCStr; +} + +void +KeychainAuthLogger::setItemName(const char *item) +{ + mItem = item ? item : unknownItemStr; +} + +void +KeychainAuthLogger::writeCommon() +{ + writeSubject(); + writeToken(au_to_text(sysKCAuthStr), sysKCAuthStr); + writeToken(au_to_text(mDatabase.c_str()), "keychain"); + writeToken(au_to_text(mItem.c_str()), "keychain item"); +} + + +// +// RightLogger +// +const char *RightLogger::unknownRightStr = ""; + +void +RightLogger::setRight(const string &rightName) +{ + mRight.clear(); + mRight = rightName; +} + +void +RightLogger::setRight(const char *rightName) +{ + if (rightName) // NULL bad for string class and au_to_text() + { + string tmpStr(rightName); // setRight() takes a string& + setRight(tmpStr); + } +} + + +// +// AuthMechLogger +// +const char *AuthMechLogger::unknownMechStr = ""; +const char *AuthMechLogger::mechStr = "mechanism "; + +AuthMechLogger::AuthMechLogger(const AuditToken &srcToken, short auEvent) + : AuditLogger(srcToken, auEvent), RightLogger(), + mEvaluatingMechanism(false), mCurrentMechanism(unknownMechStr) +{ +} + +AuthMechLogger::AuthMechLogger(const audit_token_t *srcToken, short auEvent) + : AuditLogger(srcToken, auEvent), RightLogger(), + mEvaluatingMechanism(false), mCurrentMechanism(unknownMechStr) +{ +} + +void +AuthMechLogger::setCurrentMechanism(const char *mech) +{ + mCurrentMechanism.clear(); + if (NULL == mech) + { + mEvaluatingMechanism = false; + } + else + { + mCurrentMechanism = mech; + mEvaluatingMechanism = true; + } +} + +void +AuthMechLogger::writeCommon() +{ + writeSubject(); + writeToken(au_to_text(mRight.c_str()), "right"); + if (true == mEvaluatingMechanism) + { + string tmpStr = mechStr; // mechStr includes a trailing space + tmpStr += mCurrentMechanism; + writeToken(au_to_text(tmpStr.c_str()), "mechanism"); + } +} + +void +AuthMechLogger::logInterrupt(const char *msg) +{ + if (false == open()) + return; + writeCommon(); + if (msg) + writeToken(au_to_text(msg), "interrupt"); + writeReturn(0, 0); + close(); +} + +// +// RightAuthenticationLogger +// +const char *RightAuthenticationLogger::unknownUserStr = ""; +const char *RightAuthenticationLogger::unknownClientStr = ""; +const char *RightAuthenticationLogger::unknownAuthCreatorStr = ""; +const char *RightAuthenticationLogger::authenticatorStr = "known UID "; +const char *RightAuthenticationLogger::clientStr = "client "; +const char *RightAuthenticationLogger::authCreatorStr = "creator "; +const char *RightAuthenticationLogger::authenticatedAsStr = "authenticated as "; +const char *RightAuthenticationLogger::leastPrivStr = "least-privilege"; + +RightAuthenticationLogger::RightAuthenticationLogger(const AuditToken &srcToken, short auEvent) + : AuditLogger(srcToken, auEvent), RightLogger() +{ +} + +RightAuthenticationLogger::RightAuthenticationLogger(const audit_token_t *srcToken, short auEvent) + : AuditLogger(srcToken, auEvent), RightLogger() +{ +} + +void +RightAuthenticationLogger::writeCommon() +{ + writeSubject(); + writeToken(au_to_text(mRight.c_str()), "right"); +} + +void +RightAuthenticationLogger::logSuccess(uid_t authenticator, uid_t target, const char *targetName) +{ + if (false == open()) + return; + writeCommon(); + + // au_to_arg32() is really meant for auditing syscall arguments; + // we're slightly abusing it to get descriptive strings for free. + writeToken(au_to_arg32(1, authenticatorStr, authenticator), "authenticator"); + string tmpStr(authenticatedAsStr); + // targetName shouldn't be NULL on a successful authentication, but allow + // for programmer screwups + tmpStr += targetName ? targetName : unknownUserStr; + writeToken(au_to_arg32(2, tmpStr.c_str(), target), "target"); + writeReturn(0, 0); + close(); +} + +void +RightAuthenticationLogger::logAuthorizationResult(const char *client, const char *authCreator, int errcode) +{ + if (false == open()) + return; + writeCommon(); + string tmpStr(clientStr); + tmpStr += client ? client : unknownClientStr; + writeToken(au_to_text(tmpStr.c_str()), "Authorization client"); + tmpStr.clear(); + tmpStr = authCreatorStr; + tmpStr += authCreator ? authCreator : unknownAuthCreatorStr; + writeToken(au_to_text(tmpStr.c_str()), "Authorization creator"); + if (errAuthorizationSuccess == errcode) + writeReturn(0, 0); + else + writeReturn(EPERM, errcode); + close(); +} + +void +RightAuthenticationLogger::logLeastPrivilege(uid_t userId, bool isAuthorizingUser) +{ + if (false == open()) + return; + writeCommon(); + writeToken(au_to_text(leastPrivStr), leastPrivStr); + writeReturn(0, 0); + close(); +} + +void +RightAuthenticationLogger::logFailure(uid_t authenticator, const char *targetName) +{ + if (false == open()) + return; + writeCommon(); + writeToken(au_to_arg32(1, authenticatorStr, authenticator), "authenticator"); + if (NULL == targetName) + writeToken(au_to_text(unknownUserStr), "target username"); + else + writeToken(au_to_text(targetName), "target username"); + // @@@ EAUTH more appropriate, but !defined for _POSIX_C_SOURCE + writeReturn(EPERM, errAuthorizationDenied); + close(); +} + +} // namespace Securityd + +} // namespace CommonCriteria + +} // namespace Security diff --git a/securityd/src/ccaudit_extensions.h b/securityd/src/ccaudit_extensions.h new file mode 100644 index 00000000..8b4150b1 --- /dev/null +++ b/securityd/src/ccaudit_extensions.h @@ -0,0 +1,253 @@ +/* + * ccaudit_extensions.h + * securityd + * + * Created by G H on 3/24/09. + * Copyright (c) 2009 Apple Inc. All Rights Reserved. + * + * Extensions to utility classes in Security::CommonCriteria + * (libsecurity_utilities). Not clear that these are useful enough to be + * added there, so for now, they're here. + */ + +#include +#include +#include +#include // AUE_NULL +#include + +// +// Regarding message formats in comments, below: +// +// <> denotes a string with the indicated information +// '' denotes a literal string +// +// Message info is in text tokens unless otherwise indicated. +// + +namespace Security +{ + +namespace CommonCriteria +{ + +namespace Securityd +{ + +// +// Pure virtual class from which audit log writers should be derived. +// The assumption about logging is that a "success" case logs certain +// data about what succeeded, while a "failure" case logs that same data +// plus some indication as to why the failure occurred. +// +// Subclasses minimally need to provide a writeCommon() method. They may +// override logSuccess(); q.v. +// +// An AuditLogger is intended to live no longer than the audit trailer of a +// securityd IPC. +// +// setClientInfo() must be called before logging, or at best, gibberish +// will be logged. +// +// Nomenclature: +// "write" methods only au_write() +// "log" methods open, write, and close the log +// +class AuditLogger +{ +public: + AuditLogger() : mAuditFd(-1), mEvent(AUE_NULL), mClientInfoSet(false) { } + AuditLogger(const audit_token_t *srcToken, short auEvent = AUE_NULL); + AuditLogger(const AuditToken &srcToken, short auEvent = AUE_NULL); + virtual ~AuditLogger(); + + bool open(); // false if auditing disabled; throws on real errors + void close(bool writeLog = true); // throws if writeLog true but au_close() failed + + void setClientInfo(const audit_token_t *srcToken); + void setClientInfo(const AuditToken &srcToken); + void setEvent(short auEvent) { mEvent = auEvent; } + short event() const { return mEvent; } + + // common log-writing activities + void writeToken(token_t *token, const char *name); + void writeSubject(); + void writeReturn(char status, int reterr); + virtual void writeCommon() = 0; // should not open or close log + + // logSuccess() assumes that all the ancillary information you need is + // written by writeCommon(). If that's not true, you can either + // override logSuccess() in your subclass, or use a different method + // altogether. Do not call AuditLogger::logSuccess() from the subclass + // in eiher case. + virtual void logSuccess(); + + virtual void logFailure(const char *errMsg = NULL, int errcode = errAuthorizationDenied); + virtual void logFailure(string &errMsg, int errcode = errAuthorizationDenied) { logFailure(errMsg.c_str(), errcode); } + + // @@@ Extra credit: let callers add arbitrary tokens. Tokens added + // before a log*() call would be appended to the end of writeCommon()'s + // standard set. + +protected: + void logInternalError(const char *fmt, ...); + +private: + int mAuditFd; + short mEvent; + bool mClientInfoSet; // disallow resetting client info + + uid_t mAuditId; + uid_t mEuid; + gid_t mEgid; + uid_t mRuid; + gid_t mRgid; + pid_t mPid; + au_asid_t mAuditSessionId; + au_tid_t mOldTerminalId; // to cache audit_token_to_au32() result + au_tid_addr_t mTerminalId; // @@@ AuditInfo still uses ai_tid_t +}; + +// +// KeychainAuthLogger format: +// 'System keychain authorization' +// +// +// [optional] +// +// For QueryKeychainAuth audit logging +// +class KeychainAuthLogger : public AuditLogger +{ + static const char *sysKCAuthStr; + static const char *unknownKCStr; + static const char *unknownItemStr; + +public: + KeychainAuthLogger() : AuditLogger(), mDatabase(unknownKCStr), mItem(unknownItemStr) { } + KeychainAuthLogger(const audit_token_t *srcToken, short auEvent); + KeychainAuthLogger(const audit_token_t *srcToken, short auEvent, const char *database, const char *item); + KeychainAuthLogger(const AuditToken &srcToken, short auEvent); + KeychainAuthLogger(const AuditToken &srcToken, short auEvent, const char *database, const char *item); + void setDbName(const char *database); + void setItemName(const char *item); + virtual void writeCommon(); + +private: + string mDatabase; + string mItem; +}; + +// +// RightLogger provides basic common data and behavior for rights-based +// logging classes. @@@ "RightLogger" is a lousy name +// +class RightLogger +{ +protected: + static const char *unknownRightStr; + +public: + RightLogger() : mRight(unknownRightStr) { } + virtual ~RightLogger() { } + + void setRight(const string &rightName); + void setRight(const char *rightName); + +protected: + string mRight; +}; + +// +// Basic (per-mechanism) AuthMechLogger format: +// +// [optional] 'mechanism' +// [optional] +// +// e.g.: +// com.foo.bar +// mechanism FooPlugin:SomeMechanism +// unknown mechanism; ending rule evaluation +// +class AuthMechLogger : public AuditLogger, public RightLogger +{ + static const char *unknownMechStr; + static const char *mechStr; + +public: + AuthMechLogger() : AuditLogger(), RightLogger(), mEvaluatingMechanism(false), mCurrentMechanism(unknownMechStr) { } + AuthMechLogger(const AuditToken &srcToken, short auEvent); + AuthMechLogger(const audit_token_t *srcToken, short auEvent); + + void setCurrentMechanism(const char *mech); // pass NULL if not running mechs. + void setCurrentMechanism(const string &mech) { setCurrentMechanism(mech.c_str()); } + virtual void writeCommon(); + + // Authorization mechanism-evaluation interrupts need to be logged since + // they cause evaluation to restart, possibly at a different point in the + // mechanism chain. + void logInterrupt(const char *msg); // NULL msg okay + void logInterrupt(string &msg) { logInterrupt(msg.c_str()); } + +private: + bool mEvaluatingMechanism; + string mCurrentMechanism; +}; + +// +// Basic RightAuthenticationLogger formats: +// +// Per-credential (newly granted during an evaluation): +// +// UID of user performing the authentication [arg32 token] +// UID and username of the successfully authenticated user [arg32 token] +// or: +// +// UID of user performing the authentication [arg32 token] +// Name of the user as whom the first UID was attempting to authenticate +// +// Final (i.e., after all mechanisms) right-granting decision format: +// +// name of process requesting authorization +// name of process that created the Authorization handle +// +// Least-privilege credential-generating event format: +// +// 'least-privilege' +// +// @@@ each format should be its own class +// +class RightAuthenticationLogger : public AuditLogger, public RightLogger +{ + static const char *unknownUserStr; + static const char *unknownClientStr; + static const char *unknownAuthCreatorStr; + static const char *authenticatorStr; + static const char *clientStr; + static const char *authCreatorStr; + static const char *authenticatedAsStr; + static const char *leastPrivStr; + +public: + RightAuthenticationLogger() : AuditLogger(), RightLogger() { } + RightAuthenticationLogger(const AuditToken &srcToken, short auEvent); + RightAuthenticationLogger(const audit_token_t *srcToken, short auEvent); + virtual ~RightAuthenticationLogger() { } + + virtual void writeCommon(); + + virtual void logSuccess() { } // throw? in any case, don't allow the usual logSuccess() to work + // @@@ clean up, consolidate Success and AuthorizationResult + void logSuccess(uid_t authenticator, uid_t target, const char *targetName); + void logAuthorizationResult(const char *client, const char *authCreator, int errcode); + void logLeastPrivilege(uid_t userId, bool isAuthorizingUser); + virtual void logFailure(const char *errMsg, int errcode) { AuditLogger::logFailure(errMsg, errcode); } + void logFailure(uid_t authenticator, const char *targetName); +}; + + +} // namespace Securityd + +} // namespace CommonCriteria + +} // namespace Security diff --git a/securityd/src/child.cpp b/securityd/src/child.cpp new file mode 100644 index 00000000..120bf4cd --- /dev/null +++ b/securityd/src/child.cpp @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2004,2007 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@ + */ + + +// +// child - track a single child process and its belongings +// +#include "child.h" +#include "dtrace.h" +#include + + +// +// We use a static Mutex to coordinate checkin +// +Mutex ServerChild::mCheckinLock; + + +// +// Make and break ServerChildren +// +ServerChild::ServerChild() + : mCheckinCond(mCheckinLock) +{ +} + + +// +// If the ServerChild is destroyed, kill its process, nice or hard. +// +// In case you wonder about the tango below, it's making sure we +// get to "It's dead, Jim" with the minimum number of checkChildren() +// calls while still working correctly if this is the only thread alive. +// +//@@@ We *could* define a "soft shutdown" MIG message to send to all +//@@@ ServerChildren in this situation. +// +ServerChild::~ServerChild() +{ + mServicePort.destroy(); + + if (state() == alive) { + this->kill(SIGTERM); // shoot it once + checkChildren(); // check for quick death + if (state() == alive) { + usleep(300000); // give it some grace + if (state() == alive) { // could have been reaped by another thread + checkChildren(); // check again + if (state() == alive) { // it... just... won't... die... + this->kill(SIGKILL); // take THAT! + checkChildren(); + if (state() == alive) // stuck zombie + abandon(); // leave the body behind + } + } + } + } +} + + +// +// Parent action during fork: wait until ready or dead, then return +// +void ServerChild::parentAction() +{ + // wait for either checkin or (premature) death + secdebug("serverchild", "%p (pid %d) waiting for checkin", this, pid()); + StLock _(mCheckinLock); + while (!ready() && state() == alive) + mCheckinCond.wait(); + + // so what happened? + if (state() == dead) { + // our child died + secdebug("serverchild", "%p (pid %d) died before checking in", this, pid()); + SECURITYD_CHILD_STILLBORN(this->pid()); + } else if (ready()) { + // child has checked in and is ready for service + secdebug("serverchild", "%p (pid %d) ready for service on port %d", + this, pid(), mServicePort.port()); + SECURITYD_CHILD_READY(this->pid()); + } else + assert(false); // how did we ever get here?! +} + + +// +// Death action during fork: release the waiting creator thread, if any +// +void ServerChild::dying() +{ + SECURITYD_CHILD_DYING(this->pid()); + secdebug("serverchild", "%p is dead; resuming parent thread (if any)", this); + mCheckinCond.signal(); +} + + +void ServerChild::checkIn(Port servicePort, pid_t pid) +{ + if (ServerChild *child = Child::find(pid)) { + // Child was alive when last seen. Store service port and signal parent thread + { + StLock _(mCheckinLock); + child->mServicePort = servicePort; + servicePort.modRefs(MACH_PORT_RIGHT_SEND, +1); // retain send right + secdebug("serverchild", "%p (pid %d) checking in; resuming parent thread", + child, pid); + } + SECURITYD_CHILD_CHECKIN(pid, servicePort); + child->mCheckinCond.signal(); + } else { + // Child has died; is wrong kind; or spurious checkin. + // If it was a proper child, death notifications will wake up the parent thread + secdebug("serverchild", "pid %d not in child set; checkin ignored", pid); + SECURITYD_CHILD_CHECKIN(pid, 0); + } +} diff --git a/securityd/src/child.h b/securityd/src/child.h new file mode 100644 index 00000000..587627a7 --- /dev/null +++ b/securityd/src/child.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2004 Apple Computer, 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@ + */ + + +// +// child - track a single child process and its belongings +// +#ifndef _CHILD_H_ +#define _CHILD_H_ 1 + +#include +#include + +using MachPlusPlus::Port; +using MachPlusPlus::TaskPort; + + +// +// ServerChild builds on the generic UNIX Child abstraction. +// The child is expected to engage in a checkin protocol after launch, +// whereby it RPC-calls childCheckIn in securityd and thus authenticates +// and declares readiness to provide service. +// +// @@@ PerWhat are these, if they are at all? +// +class ServerChild : public UnixPlusPlus::Child { +public: + ServerChild(); + ~ServerChild(); + + Port servicePort() const { return mServicePort; } + bool ready() const { return mServicePort; } + +public: + static void checkIn(Port servicePort, pid_t pid); + +protected: + void childAction() = 0; // must be provided by subclass + void parentAction(); // fully implemented + void dying(); // fully implemented + +private: + Port mServicePort; // child's main service port + +private: + typedef map CheckinMap; + static CheckinMap mCheckinMap; + + // The parent side will wait on mCheckinCond until the child checks in + // or fails. During that time ONLY, mCheckinLock protects the entire Child + // object. + static Mutex mCheckinLock; + Condition mCheckinCond; +}; + + +#endif // _CHILD_H_ diff --git a/securityd/src/clientid.cpp b/securityd/src/clientid.cpp new file mode 100644 index 00000000..8c84a05f --- /dev/null +++ b/securityd/src/clientid.cpp @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2006-2009,2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + */ +// +// clientid - track and manage identity of securityd clients +// +#include "clientid.h" +#include "server.h" +#include + + +// +// Constructing a ClientIdentification doesn't do much. +// We're waiting for setup(), which should be called by the child class's +// constructor. +// +ClientIdentification::ClientIdentification() +{ +} + + +// +// Initialize the ClientIdentification. +// This creates a process-level code object for the client. +// +void ClientIdentification::setup(pid_t pid) +{ + StLock _(mLock); + if (OSStatus rc = SecCodeCreateWithPID(pid, kSecCSDefaultFlags, + &mClientProcess.aref())) + secdebug("clientid", "could not get code for process %d: OSStatus=%d", + pid, int32_t(rc)); + mGuests.erase(mGuests.begin(), mGuests.end()); +} + + +// +// Return a SecCodeRef for the client process itself, regardless of +// which guest within it is currently active. +// Think twice before using this. +// +SecCodeRef ClientIdentification::processCode() const +{ + return mClientProcess; +} + + +// +// Return a SecCodeRef for the currently active guest within the client +// process. +// +// We make a fair effort to cache client guest identities without over-growing +// the cache. Note that there's currently no protocol for being notified of +// a guest's death or disappearance (independent from the host process's death), +// so we couldn't track guests live even if we tried. +// +// Note that this consults Server::connection for the currently serviced +// Connection object, so this is not entirely a function of ClientIdentification state. +// +SecCodeRef ClientIdentification::currentGuest() const +{ + if (GuestState *guest = current()) + return guest->code; + else + return mClientProcess; +} + +ClientIdentification::GuestState *ClientIdentification::current() const +{ + // if we have no client identification, we can't find a current guest either + if (!processCode()) + return NULL; + + SecGuestRef guestRef = Server::connection().guestRef(); + + // try to deliver an already-cached entry + { + StLock _(mLock); + GuestMap::iterator it = mGuests.find(guestRef); + if (it != mGuests.end()) + return &it->second; + } + + // okay, make a new one (this may take a while) + CFRef attributes = (guestRef == kSecNoGuest) + ? NULL + : makeCFDictionary(1, kSecGuestAttributeCanonical, CFTempNumber(guestRef).get()); + Server::active().longTermActivity(); + CFRef code; + switch (OSStatus rc = SecCodeCopyGuestWithAttributes(processCode(), + attributes, kSecCSDefaultFlags, &code.aref())) { + case noErr: + break; + case errSecCSUnsigned: // not signed; clearly not a host + case errSecCSNotAHost: // signed but not marked as a (potential) host + code = mClientProcess; + break; + case errSecCSNoSuchCode: // potential host, but... + if (guestRef == kSecNoGuest) { // ... no guests (yet), so return the process + code = mClientProcess; + break; + } + // else fall through // ... the guest we expected to be there isn't + default: + MacOSError::throwMe(rc); + } + StLock _(mLock); + GuestState &slot = mGuests[guestRef]; + if (!slot.code) // if another thread didn't get here first... + slot.code = code; + return &slot; +} + + +// +// Support for the legacy hash identification mechanism. +// The legacy machinery deals exclusively in terms of processes. +// It knows nothing about guests and their identities. +// +string ClientIdentification::getPath() const +{ + assert(mClientProcess); + return codePath(currentGuest()); +} + +const CssmData ClientIdentification::getHash() const +{ + if (GuestState *guest = current()) { + if (!guest->gotHash) { + RefPointer clientCode = new OSXCodeWrap(guest->code); + OSXVerifier::makeLegacyHash(clientCode, guest->legacyHash); + guest->gotHash = true; + } + return CssmData::wrap(guest->legacyHash, SHA1::digestLength); + } else + return CssmData(); +} + +const bool ClientIdentification::checkAppleSigned() const +{ + if (GuestState *guest = current()) { + if (!guest->checkedSignature) { + // This is the clownfish supported way to check for a Mac App Store or B&I signed build + CFStringRef requirementString = CFSTR("(anchor apple) or (anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.9])"); + SecRequirementRef secRequirementRef = NULL; + OSStatus status = SecRequirementCreateWithString(requirementString, kSecCSDefaultFlags, &secRequirementRef); + if (status == errSecSuccess) { + OSStatus status = SecCodeCheckValidity(guest->code, kSecCSDefaultFlags, secRequirementRef); + if (status != errSecSuccess) { + secdebug("SecurityAgentXPCQuery", "code requirement check failed (%d)", (int32_t)status); + } else { + guest->appleSigned = true; + } + guest->checkedSignature = true; + } + CFRelease(secRequirementRef); + } + return guest->appleSigned; + } else + return false; +} + + +// +// Bonus function: get the path out of a SecCodeRef +// +std::string codePath(SecStaticCodeRef code) +{ + CFRef path; + MacOSError::check(SecCodeCopyPath(code, kSecCSDefaultFlags, &path.aref())); + return cfString(path); +} + + +// +// Debug dump support +// +#if defined(DEBUGDUMP) + +static void dumpCode(SecCodeRef code) +{ + CFRef path; + if (OSStatus rc = SecCodeCopyPath(code, kSecCSDefaultFlags, &path.aref())) + Debug::dump("unknown(rc=%d)", int32_t(rc)); + else + Debug::dump("%s", cfString(path).c_str()); +} + +void ClientIdentification::dump() +{ + Debug::dump(" client="); + dumpCode(mClientProcess); + for (GuestMap::const_iterator it = mGuests.begin(); it != mGuests.end(); ++it) { + Debug::dump(" guest(0x%x)=", it->first); + dumpCode(it->second.code); + if (it->second.gotHash) + Debug::dump(" [got hash]"); + } +} + +#endif //DEBUGDUMP diff --git a/securityd/src/clientid.h b/securityd/src/clientid.h new file mode 100644 index 00000000..57d9caf7 --- /dev/null +++ b/securityd/src/clientid.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2000-2004,2006-2007,2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + */ +// +// clientid - track and manage identity of securityd clients +// +#ifndef _H_CLIENTID +#define _H_CLIENTID + +#include "codesigdb.h" +#include +#include +#include + + +// +// A ClientIdentification object is a mix-in class that tracks +// the identity of associated client processes and their sub-entities +// (aka Code Signing Guest objects). +// +class ClientIdentification : public CodeSignatures::Identity { +public: + ClientIdentification(); + + SecCodeRef processCode() const; + SecCodeRef currentGuest() const; + + // CodeSignatures::Identity personality + string getPath() const; + const CssmData getHash() const; + const bool checkAppleSigned() const; + +protected: + void setup(pid_t pid); + +public: + IFDUMP(void dump()); + +private: + CFRef mClientProcess; // process-level client object + + mutable Mutex mLock; // protects everything below + + struct GuestState { + GuestState() : gotHash(false) { } + CFRef code; + mutable bool gotHash; + mutable SHA1::Digest legacyHash; + mutable bool checkedSignature; + mutable bool appleSigned; + }; + typedef std::map GuestMap; + mutable GuestMap mGuests; + + GuestState *current() const; +}; + + +// +// Bonus function +// +std::string codePath(SecStaticCodeRef code); + + +#endif //_H_CLIENTID diff --git a/securityd/src/codesigdb.cpp b/securityd/src/codesigdb.cpp new file mode 100644 index 00000000..c06a7582 --- /dev/null +++ b/securityd/src/codesigdb.cpp @@ -0,0 +1,549 @@ +/* + * Copyright (c) 2003-2009,2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + */ + + +// +// codesigdb - code-hash equivalence database +// +#include "codesigdb.h" +#include "process.h" +#include "server.h" +#include "agentquery.h" +#include +#include +#include + + +// +// A self-constructing database key class. +// Key format is +// where +// single ASCII character type code ('H' for hash links) +// decimal userid of owning user, or 'S' for system entries. Followed by null byte. +// variable length key value (binary). +// +class DbKey : public CssmAutoData { +public: + DbKey(char type, const CssmData &key, bool perUser = false, uid_t user = 0); +}; + +DbKey::DbKey(char type, const CssmData &key, bool perUser, uid_t user) + : CssmAutoData(Allocator::standard()) +{ + using namespace LowLevelMemoryUtilities; + char header[20]; + size_t headerLength; + if (perUser) + headerLength = 1 + sprintf(header, "%c%d", type, user); + else + headerLength = 1 + sprintf(header, "%cS", type); + malloc(headerLength + key.length()); + memcpy(this->data(), header, headerLength); + memcpy(get().at(headerLength), key.data(), key.length()); +} + + +// +// A subclass of Identity made of whole cloth (from a raw CodeSignature ACL information) +// +struct AclIdentity : public CodeSignatures::Identity { + AclIdentity(const CssmData hash, string path) : mHash(hash), mPath(path) { } + + string getPath() const { return mPath; } + const CssmData getHash() const { return mHash; } + +private: + const CssmData mHash; + const string mPath; +}; + + +// +// Construct a CodeSignatures objects +// +CodeSignatures::CodeSignatures(const char *path) +{ + try { + mDb.open(path, O_RDWR | O_CREAT, 0644); + } catch (const CommonError &err) { + try { + mDb.open(path, O_RDONLY, 0644); + Syslog::warning("database %s opened READONLY (R/W failed errno=%d)", path, err.unixError()); + secdebug("codesign", "database %s opened READONLY (R/W failed errno=%d)", path, err.unixError()); + } catch (...) { + Syslog::warning("cannot open %s; using no code equivalents", path); + secdebug("codesign", "unable to open %s; using no code equivalents", path); + } + } + if (mDb) + mDb.flush(); // in case we just created it + IFDUMPING("equiv", debugDump("open")); +} + +CodeSignatures::~CodeSignatures() +{ +} + + +// +// (Re)open the equivalence database. +// This is useful to switch to database in another volume. +// +void CodeSignatures::open(const char *path) +{ + mDb.open(path, O_RDWR | O_CREAT, 0644); + mDb.flush(); + IFDUMPING("equiv", debugDump("reopen")); +} + + +// +// Basic Identity objects +// +CodeSignatures::Identity::Identity() : mState(untried) +{ } + +CodeSignatures::Identity::~Identity() +{ } + +string CodeSignatures::Identity::canonicalName(const string &path) +{ + string::size_type slash = path.rfind('/'); + if (slash == string::npos) // bloody unlikely, but whatever... + return path; + return path.substr(slash+1); +} + + +// +// Find and store database objects (primitive layer) +// +bool CodeSignatures::find(Identity &id, uid_t user) +{ + if (id.mState != Identity::untried) + return id.mState == Identity::valid; + try { + DbKey userKey('H', id.getHash(), true, user); + CssmData linkValue; + if (mDb.get(userKey, linkValue)) { + id.mName = string(linkValue.interpretedAs(), linkValue.length()); + IFDUMPING("equiv", id.debugDump("found/user")); + id.mState = Identity::valid; + return true; + } + DbKey sysKey('H', id.getHash()); + if (mDb.get(sysKey, linkValue)) { + id.mName = string(linkValue.interpretedAs(), linkValue.length()); + IFDUMPING("equiv", id.debugDump("found/system")); + id.mState = Identity::valid; + return true; + } + } catch (...) { + secdebug("codesign", "exception validating identity for %s - marking failed", id.path().c_str()); + id.mState = Identity::invalid; + } + return id.mState == Identity::valid; +} + +void CodeSignatures::makeLink(Identity &id, const string &ident, bool forUser, uid_t user) +{ + DbKey key('H', id.getHash(), forUser, user); + if (!mDb.put(key, StringData(ident))) + UnixError::throwMe(); +} + + +// +// Administrative manipulation calls +// +void CodeSignatures::addLink(const CssmData &oldHash, const CssmData &newHash, + const char *inName, bool forSystem) +{ + string name = Identity::canonicalName(inName); + uid_t user = Server::process().uid(); + if (forSystem && user) // only root user can establish forSystem links + UnixError::throwMe(EACCES); + if (!forSystem) // in fact, for now we don't allow per-user calls at all + UnixError::throwMe(EACCES); + AclIdentity oldCode(oldHash, name); + AclIdentity newCode(newHash, name); + secdebug("codesign", "addlink for name %s", name.c_str()); + StLock _(mDatabaseLock); + if (oldCode) { + if (oldCode.trustedName() != name) { + secdebug("codesign", "addlink does not match existing name %s", + oldCode.trustedName().c_str()); + MacOSError::throwMe(CSSMERR_CSP_VERIFY_FAILED); + } + } else { + makeLink(oldCode, name, !forSystem, user); + } + if (!newCode) + makeLink(newCode, name, !forSystem, user); + mDb.flush(); +} + +void CodeSignatures::removeLink(const CssmData &hash, const char *name, bool forSystem) +{ + AclIdentity code(hash, name); + uid_t user = Server::process().uid(); + if (forSystem && user) // only root user can remove forSystem links + UnixError::throwMe(EACCES); + DbKey key('H', hash, !forSystem, user); + StLock _(mDatabaseLock); + mDb.erase(key); + mDb.flush(); +} + + +// +// Verify signature matches. +// This ends up getting called when a CodeSignatureAclSubject is validated. +// The OSXVerifier describes what we require of the client code; the process represents +// the requesting client; and the context gives us access to the ACL and its environment +// in case we want to, well, creatively rewrite it for some reason. +// +bool CodeSignatures::verify(Process &process, + const OSXVerifier &verifier, const AclValidationContext &context) +{ + secdebug("codesign", "start verify"); + + StLock _(process); + SecCodeRef code = process.currentGuest(); + if (!code) { + secdebug("codesign", "no code base: fail"); + return false; + } + if (SecRequirementRef requirement = verifier.requirement()) { + // If the ACL contains a code signature (requirement), we won't match against unsigned code at all. + // The legacy hash is ignored (it's for use by pre-Leopard systems). + secdebug("codesign", "CS requirement present; ignoring legacy hashes"); + Server::active().longTermActivity(); + switch (OSStatus rc = SecCodeCheckValidity(code, kSecCSDefaultFlags, requirement)) { + case noErr: + secdebug("codesign", "CS verify passed"); + return true; + case errSecCSUnsigned: + secdebug("codesign", "CS verify against unsigned binary failed"); + return false; + default: + secdebug("codesign", "CS verify failed OSStatus=%d", int32_t(rc)); + return false; + } + } + switch (matchSignedClientToLegacyACL(process, code, verifier, context)) { + case noErr: // handled, allow access + return true; + case errSecCSUnsigned: // unsigned client, complete legacy case + secdebug("codesign", "no CS requirement - using legacy hash"); + return verifyLegacy(process, + CssmData::wrap(verifier.legacyHash(), SHA1::digestLength), + verifier.path()); + default: // client unsuitable, reject this match + return false; + } +} + + +// +// See if we can rewrite the ACL from legacy to Code Signing form without losing too much security. +// Returns true if the present validation should succeed (we probably rewrote the ACL). +// Returns false if the present validation shouldn't succeed based on what we did here (we may still +// have rewritten the ACL, in principle). +// +// Note that these checks add nontrivial overhead to ACL processing. We want to eventually phase +// this out, or at least make it an option that doesn't run all the time - perhaps an "extra legacy +// effort" per-client mode bit. +// +static string trim(string s, char delimiter) +{ + string::size_type p = s.rfind(delimiter); + if (p != string::npos) + s = s.substr(p + 1); + return s; +} + +static string trim(string s, char delimiter, string suffix) +{ + s = trim(s, delimiter); + int preLength = s.length() - suffix.length(); + if (preLength > 0 && s.substr(preLength) == suffix) + s = s.substr(0, preLength); + return s; +} + +OSStatus CodeSignatures::matchSignedClientToLegacyACL(Process &process, + SecCodeRef code, const OSXVerifier &verifier, const AclValidationContext &context) +{ + // + // Check whether we seem to be matching a legacy .Mac ACL against a member of the .Mac group + // + if (SecurityServerAcl::looksLikeLegacyDotMac(context)) { + Server::active().longTermActivity(); + CFRef dotmac; + MacOSError::check(SecRequirementCreateGroup(CFSTR("dot-mac"), NULL, kSecCSDefaultFlags, &dotmac.aref())); + if (SecCodeCheckValidity(code, kSecCSDefaultFlags, dotmac) == noErr) { + secdebug("codesign", "client is a dot-mac application; update the ACL accordingly"); + + // create a suitable AclSubject (this is the above-the-API-line way) + CFRef reqdata; + MacOSError::check(SecRequirementCopyData(dotmac, kSecCSDefaultFlags, &reqdata.aref())); + RefPointer subject = new CodeSignatureAclSubject(NULL, "group://dot-mac"); + subject->add((const BlobCore *)CFDataGetBytePtr(reqdata)); + + // add it to the ACL and pass the access check (we just quite literally did it above) + SecurityServerAcl::addToStandardACL(context, subject); + return noErr; + } + } + + // + // Get best names for the ACL (legacy) subject and the (signed) client + // + CFRef info; + MacOSError::check(SecCodeCopySigningInformation(code, kSecCSSigningInformation, &info.aref())); + CFStringRef signingIdentity = CFStringRef(CFDictionaryGetValue(info, kSecCodeInfoIdentifier)); + if (!signingIdentity) // unsigned + return errSecCSUnsigned; + + string bundleName; // client + if (CFDictionaryRef infoList = CFDictionaryRef(CFDictionaryGetValue(info, kSecCodeInfoPList))) + if (CFStringRef name = CFStringRef(CFDictionaryGetValue(infoList, kCFBundleNameKey))) + bundleName = trim(cfString(name), '.'); + if (bundleName.empty()) // fall back to signing identifier + bundleName = trim(cfString(signingIdentity), '.'); + + string aclName = trim(verifier.path(), '/', ".app"); // ACL + + secdebug("codesign", "matching signed client \"%s\" against legacy ACL \"%s\"", + bundleName.c_str(), aclName.c_str()); + + // + // Check whether we're matching a signed APPLE application against a legacy ACL by the same name + // + if (bundleName == aclName) { + const unsigned char reqData[] = { // "anchor apple", version 1 blob, embedded here + 0xfa, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03 + }; + CFRef apple; + MacOSError::check(SecRequirementCreateWithData(CFTempData(reqData, sizeof(reqData)), + kSecCSDefaultFlags, &apple.aref())); + Server::active().longTermActivity(); + switch (OSStatus rc = SecCodeCheckValidity(code, kSecCSDefaultFlags, apple)) { + case noErr: + { + secdebug("codesign", "withstands strict scrutiny; quietly adding new ACL"); + RefPointer wrap = new OSXCodeWrap(code); + RefPointer subject = new CodeSignatureAclSubject(OSXVerifier(wrap)); + SecurityServerAcl::addToStandardACL(context, subject); + return noErr; + } + default: + secdebug("codesign", "validation fails with rc=%d, rejecting", int32_t(rc)); + return rc; + } + secdebug("codesign", "does not withstand strict scrutiny; ask the user"); + QueryCodeCheck query; + query.inferHints(process); + if (!query(verifier.path().c_str())) { + secdebug("codesign", "user declined equivalence: cancel the access"); + CssmError::throwMe(CSSM_ERRCODE_USER_CANCELED); + } + RefPointer wrap = new OSXCodeWrap(code); + RefPointer subject = new CodeSignatureAclSubject(OSXVerifier(wrap)); + SecurityServerAcl::addToStandardACL(context, subject); + return noErr; + } + + // not close enough to even ask - this can't match + return errSecCSReqFailed; +} + + +// +// Perform legacy hash verification. +// This is the pre-Leopard (Tiger, Panther) code path. Here we only have legacy hashes +// (called, confusingly, "signatures"), which we're matching against suitably computed +// "signatures" (hashes) on the requesting application. We consult the CodeEquivalenceDatabase +// in a doomed attempt to track changes made to applications through updates, and issue +// equivalence dialogs to users if we have a name match (but hash mismatch). That's all +// there was before Code Signing; and that's what you'll continue to get if the requesting +// application is unsigned. Until we throw the whole mess out altogether, hopefully by +// the Next Big Cat After Leopard. +// +bool CodeSignatures::verifyLegacy(Process &process, const CssmData &signature, string path) +{ + // First of all, if the signature directly matches the client's code, we're obviously fine + // we don't even need the database for that... + Identity &clientIdentity = process; + try { + if (clientIdentity.getHash() == signature) { + secdebug("codesign", "direct match: pass"); + return true; + } + } catch (...) { + secdebug("codesign", "exception getting client code hash: fail"); + return false; + } + +#if CONSULT_LEGACY_CODE_EQUIVALENCE_DATABASE + + // Ah well. Establish mediator objects for database signature links + AclIdentity aclIdentity(signature, path); + + uid_t user = process.uid(); + { + StLock _(mDatabaseLock); + find(aclIdentity, user); + find(clientIdentity, user); + } + + // if both links exist, we can decide this right now + if (aclIdentity && clientIdentity) { + if (aclIdentity.trustedName() == clientIdentity.trustedName()) { + secdebug("codesign", "app references match: pass"); + return true; + } else { + secdebug("codesign", "client/acl links exist but are unequal: fail"); + return false; + } + } + + // check for name equality + secdebug("codesign", "matching client %s against acl %s", + clientIdentity.name().c_str(), aclIdentity.name().c_str()); + if (aclIdentity.name() != clientIdentity.name()) { + secdebug("codesign", "name/path mismatch: fail"); + return false; + } + + // The names match - we have a possible update. + + // Take the UI lock now to serialize "update rushes". + LongtermStLock uiLocker(mUILock); + + // re-read the database in case some other thread beat us to the update + { + StLock _(mDatabaseLock); + find(aclIdentity, user); + find(clientIdentity, user); + } + if (aclIdentity && clientIdentity) { + if (aclIdentity.trustedName() == clientIdentity.trustedName()) { + secdebug("codesign", "app references match: pass (on the rematch)"); + return true; + } else { + secdebug("codesign", "client/acl links exist but are unequal: fail (on the rematch)"); + return false; + } + } + + // ask the user + QueryCodeCheck query; + query.inferHints(process); + if (!query(aclIdentity.path().c_str())) + { + secdebug("codesign", "user declined equivalence: cancel the access"); + CssmError::throwMe(CSSM_ERRCODE_USER_CANCELED); + } + + // take the database lock back for real + StLock _(mDatabaseLock); + + // user wants us to go ahead and establish trust (if possible) + if (aclIdentity) { + // acl is linked but new client: link the client to this application + makeLink(clientIdentity, aclIdentity.trustedName(), true, user); + mDb.flush(); + secdebug("codesign", "client %s linked to application %s: pass", + clientIdentity.path().c_str(), aclIdentity.trustedName().c_str()); + return true; + } + + if (clientIdentity) { // code link exists, acl link missing + // client is linked but ACL (hash) never seen: link the ACL to this app + makeLink(aclIdentity, clientIdentity.trustedName(), true, user); + mDb.flush(); + secdebug("codesign", "acl %s linked to client %s: pass", + aclIdentity.path().c_str(), clientIdentity.trustedName().c_str()); + return true; + } + + // the De Novo case: no links, must create everything + string ident = clientIdentity.name(); + makeLink(clientIdentity, ident, true, user); + makeLink(aclIdentity, ident, true, user); + mDb.flush(); + secdebug("codesign", "new linkages established: pass"); + return true; + +#else /* ignore Code Equivalence Database */ + + return false; + +#endif +} + + +// +// Debug dumping support +// +#if defined(DEBUGDUMP) + +void CodeSignatures::debugDump(const char *how) const +{ + using namespace Debug; + using namespace LowLevelMemoryUtilities; + if (!how) + how = "dump"; + CssmData key, value; + if (!mDb.first(key, value)) { + dump("CODE EQUIVALENTS DATABASE IS EMPTY (%s)\n", how); + } else { + dump("CODE EQUIVALENTS DATABASE DUMP (%s)\n", how); + do { + const char *header = key.interpretedAs(); + size_t headerLength = strlen(header) + 1; + dump("%s:", header); + dumpData(key.at(headerLength), key.length() - headerLength); + dump(" => "); + dumpData(value); + dump("\n"); + } while (mDb.next(key, value)); + dump("END DUMP\n"); + } +} + +void CodeSignatures::Identity::debugDump(const char *how) const +{ + using namespace Debug; + if (!how) + how = "dump"; + dump("IDENTITY (%s) path=%s", how, getPath().c_str()); + dump(" name=%s hash=", mName.empty() ? "(unset)" : mName.c_str()); + dumpData(getHash()); + dump("\n"); +} + +#endif //DEBUGDUMP diff --git a/securityd/src/codesigdb.h b/securityd/src/codesigdb.h new file mode 100644 index 00000000..02cf40fc --- /dev/null +++ b/securityd/src/codesigdb.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2003-2007 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@ + */ + + +// +// codesigdb - code-hash equivalence database +// +#ifndef _H_CODESIGDB +#define _H_CODESIGDB + +#include "acls.h" +#include +#include +#include + + +class Process; +class CodeSignatures; + + +// +// A CodeSignaturse object represents a database of code-signature equivalencies +// as (previously) expressed by a user and/or the system. +// You'll usually only need one of these. +// +class CodeSignatures { +public: + // + // Identity is an abstract class modeling a code-identity in the database. + // It can represent either an existing or latent code-hash link. + // Subclass must provide path and hash source functions. + // + class Identity { + friend class CodeSignatures; + public: + Identity(); + virtual ~Identity(); + + operator bool () const { return mState == valid; } + std::string path() { return getPath(); } + std::string name() { return canonicalName(path()); } + std::string trustedName() const { return mName; } + + static std::string canonicalName(const std::string &path); + + IFDUMP(void debugDump(const char *how = NULL) const); + + virtual std::string getPath() const = 0; + virtual const CssmData getHash() const = 0; + + private: + enum { untried, valid, invalid } mState; + std::string mName; // link db value (canonical name linked to) + }; + +public: + CodeSignatures(const char *path); + ~CodeSignatures(); + + void open(const char *path); + +public: + bool find(Identity &id, uid_t user); + + void makeLink(Identity &id, const std::string &ident, bool forUser = false, uid_t user = 0); + + void addLink(const CssmData &oldHash, const CssmData &newHash, + const char *name, bool forSystem); + void removeLink(const CssmData &hash, const char *name, bool forSystem); + + IFDUMP(void debugDump(const char *how = NULL) const); + +public: + bool verify(Process &process, const OSXVerifier &verifier, const AclValidationContext &context); + +private: + OSStatus matchSignedClientToLegacyACL(Process &process, SecCodeRef code, + const OSXVerifier &verifier, const AclValidationContext &context); + bool verifyLegacy(Process &process, const CssmData &signature, string path); + +private: + UnixPlusPlus::UnixDb mDb; + + // lock hierarchy: mUILock first, then mDatabaseLock, no back-off + Mutex mDatabaseLock; // controls mDb access + Mutex mUILock; // serializes user interaction +}; + + + +#endif //_H_CODESIGDB diff --git a/securityd/src/connection.cpp b/securityd/src/connection.cpp new file mode 100644 index 00000000..ec973d84 --- /dev/null +++ b/securityd/src/connection.cpp @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2000-2009 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@ + */ + + +// +// connection - manage connections to clients. +// +// Note that Connection objects correspond to client process threads, and are +// thus inherently single-threaded. It is physically impossible for multiple +// requests to come in for the same Connection, unless the client side is +// illegally messing with the IPC protocol (for which we check below). +// It is still necessary to take the object lock for a Connection because there +// are times when we want to manipulate a busy Connection from another securityd +// thread (say, in response to a DPN). +// +#include "connection.h" +#include "key.h" +#include "server.h" +#include "session.h" +#include +#include +#include +#include +#include +#include + + +// +// Construct a Connection object. +// +Connection::Connection(Process &proc, Port rPort) + : mClientPort(rPort), mGuestRef(kSecNoGuest), state(idle), agentWait(NULL) +{ + parent(proc); + + // bump the send-rights count on the reply port so we keep the right after replying + mClientPort.modRefs(MACH_PORT_RIGHT_SEND, +1); + + SECURITYD_CLIENT_CONNECTION_NEW(this, rPort, &proc); +} + + +// +// When a Connection's destructor executes, the connection must already have been +// terminated. All we have to do here is clean up a bit. +// +Connection::~Connection() +{ + SECURITYD_CLIENT_CONNECTION_RELEASE(this); + assert(!agentWait); +} + + +// +// Set the (last known) guest handle for this connection. +// +void Connection::guestRef(SecGuestRef newGuest, SecCSFlags flags) +{ + secdebug("SS", "Connection %p switches to guest 0x%x", this, newGuest); + mGuestRef = newGuest; +} + + +// +// Terminate a Connection normally. +// This is assumed to be properly sequenced, so no thread races are possible. +// +void Connection::terminate() +{ + // cleanly discard port rights + assert(state == idle); + mClientPort.modRefs(MACH_PORT_RIGHT_SEND, -1); // discard surplus send right + assert(mClientPort.getRefs(MACH_PORT_RIGHT_SEND) == 1); // one left for final reply + secdebug("SS", "Connection %p terminated", this); +} + + +// +// Abort a Connection. +// This may be called from thread A while thread B is working a request for the Connection, +// so we must be careful. +// +void Connection::abort(bool keepReplyPort) +{ + StLock _(*this); + if (!keepReplyPort) + mClientPort.destroy(); // dead as a doornail already + switch (state) { + case idle: + secdebug("SS", "Connection %p aborted", this); + break; + case busy: + state = dying; // shoot me soon, please + if (agentWait) + agentWait->disconnect(); + secdebug("SS", "Connection %p abort deferred (busy)", this); + break; + default: + assert(false); // impossible (we hope) + break; + } +} + + +// +// Service request framing. +// These are here so "hanging" connection service threads don't fall +// into the Big Bad Void as Connections and processes drop out from +// under them. +// +void Connection::beginWork(audit_token_t &auditToken) +{ + // assume the audit token will be valid for the Connection's lifetime + // (but no longer) + mAuditToken = &auditToken; + switch (state) { + case idle: + state = busy; + mOverrideReturn = CSSM_OK; // clear override + break; + case busy: + secdebug("SS", "Attempt to re-enter connection %p(port %d)", this, mClientPort.port()); + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); //@@@ some state-error code instead? + default: + assert(false); + } +} + +void Connection::checkWork() +{ + StLock _(*this); + switch (state) { + case busy: + return; + case dying: + agentWait = NULL; // obviously we're not waiting on this + throw this; + default: + assert(false); + } +} + +void Connection::endWork(CSSM_RETURN &rcode) +{ + mAuditToken = NULL; + + switch (state) { + case busy: + if (mOverrideReturn && rcode == CSSM_OK) + rcode = mOverrideReturn; + state = idle; + return; + case dying: + secdebug("SS", "Connection %p abort resuming", this); + return; + default: + assert(false); + return; // placebo + } +} diff --git a/securityd/src/connection.h b/securityd/src/connection.h new file mode 100644 index 00000000..b3409402 --- /dev/null +++ b/securityd/src/connection.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2000-2009 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@ + */ + + +// +// connection - manage connections to clients +// +#ifndef _H_CONNECTION +#define _H_CONNECTION + +#include "process.h" +#include "session.h" +#include "notifications.h" +#include // audit_token_t +#include + +using MachPlusPlus::Port; +using MachPlusPlus::TaskPort; + +class Session; + +// define the minimum interface Connection requires for classes wanting to +// participate in SecurityAgent/authorizationhost IPCs (defined here rather +// than agentquery.h to avoid circularity in headers) +class SecurityAgentConnectionInterface +{ +public: + virtual void disconnect() = 0; +}; + +// +// A Connection object represents an established connection between a client +// and securityd. There is a separate Connection object for each Mach reply port +// that was (ever) used to talk to securityd. In practice, this maps to one reply +// port (and thus one Connection) for each client thread that (ever) talks to securityd. +// +// If a client tricked us into using multiple reply ports from one thread, we'd treat +// them as distinct client threads (which really doesn't much matter to us). The standard +// client library (libsecurityd) won't let you do that. +// +class Connection : public PerConnection, public Listener::JitterBuffer { +public: + Connection(Process &proc, Port rPort); + virtual ~Connection(); + void terminate(); // normal termination + void abort(bool keepReplyPort = false); // abnormal termination + + Port clientPort() const { return mClientPort; } + + // Code Signing guest management - tracks current guest id in client + SecGuestRef guestRef() const { return mGuestRef; } + void guestRef(SecGuestRef newGuest, SecCSFlags flags = 0); + + audit_token_t *auditToken() const { return mAuditToken; } + + // work framing - called as work threads pick up connection work + void beginWork(audit_token_t &auditToken); // I've got it + void checkWork(); // everything still okay? + void endWork(CSSM_RETURN &rcode); // Done with this + + // notify that a SecurityAgent call may hang the active worker thread for a while + void useAgent(SecurityAgentConnectionInterface *client) + { StLock _(*this); agentWait = client; } + + // set an overriding CSSM_RETURN to return instead of success + void overrideReturn(CSSM_RETURN rc) { mOverrideReturn = rc; } + + Process &process() const { return parent(); } + Session &session() const { return process().session(); } + +private: + // peer state: established during connection startup; fixed thereafter + Port mClientPort; // client's Mach reply port + SecGuestRef mGuestRef; // last known Code Signing guest reference for this client thread + audit_token_t *mAuditToken; // in case auditing is required + CSSM_RETURN mOverrideReturn; // override successful return code (only) + + // transient state (altered as we go) + enum State { + idle, // no thread services us + busy, // a thread is busy servicing us + dying // busy and scheduled to die as soon as possible + } state; + SecurityAgentConnectionInterface *agentWait; // SA connection we may be waiting on +}; + + +#endif //_H_CONNECTION diff --git a/securityd/src/credential.cpp b/securityd/src/credential.cpp new file mode 100644 index 00000000..8d14bc6c --- /dev/null +++ b/securityd/src/credential.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2000-2004,2006-2007,2009,2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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 "credential.h" +#include +#include + +#include +extern "C" int checkpw_internal( const struct passwd *pw, const char* password ); +#include "server.h" + +namespace Authorization { + +// default credential: invalid for everything, needed as a default session credential +CredentialImpl::CredentialImpl() : mShared(false), mRight(false), mUid(0), mName(""), mCreationTime(CFAbsoluteTimeGetCurrent()), mValid(false) +{ +} + +// only for testing whether this credential is usable +CredentialImpl::CredentialImpl(const uid_t uid, const string &username, const string &realname, bool shared) : mShared(shared), mRight(false), mUid(uid), mName(username), mRealName(realname), mCreationTime(CFAbsoluteTimeGetCurrent()), mValid(true) +{ +} + +CredentialImpl::CredentialImpl(const string &username, const string &password, bool shared) : mShared(shared), mRight(false), mName(username), mCreationTime(CFAbsoluteTimeGetCurrent()), mValid(false) +{ + Server::active().longTermActivity(); + const char *user = username.c_str(); + struct passwd *pw = getpwnam(user); + + do { + if (!pw) { + syslog(LOG_ERR, "getpwnam() failed for user %s, creating invalid credential", user); + break; + } + + mUid = pw->pw_uid; + mName = pw->pw_name; + mRealName = pw->pw_gecos; + + const char *passwd = password.c_str(); + int checkpw_status = checkpw_internal(pw, passwd); + + if (checkpw_status != CHECKPW_SUCCESS) { + syslog(LOG_ERR, "checkpw() returned %d; failed to authenticate user %s (uid %lu).", checkpw_status, pw->pw_name, pw->pw_uid); + break; + } + + syslog(LOG_INFO, "checkpw() succeeded, creating%s credential for user %s", mShared ? " shared" : "", user); + + mValid = true; + + endpwent(); + } while (0); +} + +// least-privilege + // @@@ arguably we don't care about the UID any more and should not + // require it in this ctor +CredentialImpl::CredentialImpl(const string &right, bool shared) : mShared(shared), mRight(true), mUid(-2), mName(right), mRealName(""), mCreationTime(CFAbsoluteTimeGetCurrent()), mValid(true) +{ +} + +CredentialImpl::~CredentialImpl() +{ +} + +bool +CredentialImpl::operator < (const CredentialImpl &other) const +{ + // all shared creds are placed into mSessionCreds + // all non shared creds are placed into AuthorizationToken + // + // There are 2 types of credentials UID and Right + // UID = Authenticated Identity + // Right = Rights which were previously authenticated by a uid credential + + // Right Credentials are only used during kAuthorizationFlagLeastPrivileged + // operations and should not have a valid uid set + + // this allows shared and none shared co-exist in the same container + // used when processing multiple rights shared vs non-shared during evaluation + if (!mShared && other.mShared) + return true; + if (!other.mShared && mShared) + return false; + + // this allows uids and rights co-exist in the same container + // used when holding onto Rights inside of the AuthorizationToken + if (mRight && !other.mRight) + return true; + if (!mRight && other.mRight) + return false; + + // this is the actual comparision + if (mRight) { + return mName < other.mName; + } else { + return mUid < other.mUid; + } +} + +// Returns true if this CredentialImpl should be shared. +bool +CredentialImpl::isShared() const +{ + return mShared; +} + +// Merge with other +void +CredentialImpl::merge(const CredentialImpl &other) +{ + // try to ensure that the credentials are the same type + assert(mRight == other.mRight); + if (mRight) + assert(mName == other.mName); + else + assert(mUid == other.mUid); + + if (other.mValid && (!mValid || mCreationTime < other.mCreationTime)) + { + mCreationTime = other.mCreationTime; + mValid = true; + } +} + +// The time at which this credential was obtained. +CFAbsoluteTime +CredentialImpl::creationTime() const +{ + return mCreationTime; +} + +// Return true iff this credential is valid. +bool +CredentialImpl::isValid() const +{ + return mValid; +} + +void +CredentialImpl::invalidate() +{ + mValid = false; +} + +// +// Credential class +// +Credential::Credential() : +RefPointer(new CredentialImpl()) +{ +} + +Credential::Credential(CredentialImpl *impl) : +RefPointer(impl) +{ +} + +Credential::Credential(const uid_t uid, const string &username, const string &realname, bool shared) : +RefPointer(new CredentialImpl(uid, username, realname, shared)) +{ +} + +Credential::Credential(const string &username, const string &password, bool shared) : RefPointer(new CredentialImpl(username, password, shared)) +{ +} + +Credential::Credential(const string &right, bool shared) : RefPointer(new CredentialImpl(right, shared)) +{ +} + +Credential::~Credential() +{ +} + +bool +Credential::operator < (const Credential &other) const +{ + if (!*this) + return other; + + if (!other) + return false; + + return (**this) < (*other); +} + +} // end namespace Authorization + + diff --git a/securityd/src/credential.h b/securityd/src/credential.h new file mode 100644 index 00000000..48004763 --- /dev/null +++ b/securityd/src/credential.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2000-2004,2006-2007,2009,2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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_CREDENTIAL +#define _H_CREDENTIAL + +#include +#include +#include + +namespace Authorization { + + // There should be an abstract base class for Credential so we can have + // different kinds, e.g., those associated with smart-card auth, or those + // not requiring authentication as such at all. () + +/* Credentials are less than comparable so they can be put in sets or maps. */ +class CredentialImpl : public RefCount +{ +public: + CredentialImpl(); + CredentialImpl(const uid_t uid, const string &username, const string &realname, bool shared); + CredentialImpl(const string &username, const string &password, bool shared); + CredentialImpl(const string &right, bool shared); + ~CredentialImpl(); + + bool operator < (const CredentialImpl &other) const; + + // Returns true if this credential should be shared. + bool isShared() const; + + // Merge with other + void merge(const CredentialImpl &other); + + // The time at which this credential was obtained. + CFAbsoluteTime creationTime() const; + + // Return true iff this credential is valid. + bool isValid() const; + + // Make this credential invalid. + void invalidate(); + + // We could make Rule a friend but instead we just expose this for now + inline const uid_t uid() const { return mUid; } + inline const string& name() const { return mName; } + inline const string& realname() const { return mRealName; } + inline const bool isRight() const { return mRight; } + +private: + bool mShared; // credential is shared + bool mRight; // is least-privilege credential + + + // Fields below are not used by less-than operator + + // The user that provided his password. + uid_t mUid; + string mName; + string mRealName; + + CFAbsoluteTime mCreationTime; + bool mValid; +}; + +/* Credentials are less than comparable so they can be put in sets or maps. */ +class Credential : public RefPointer +{ +public: + Credential(); + Credential(CredentialImpl *impl); + Credential(const uid_t uid, const string &username, const string &realname, bool shared); + Credential(const string &username, const string &password, bool shared); + Credential(const string &right, bool shared); + ~Credential(); + + bool operator < (const Credential &other) const; +}; + +typedef set CredentialSet; + +} // namespace Authorization + +#endif // _H_CREDENTIAL diff --git a/securityd/src/csproxy.cpp b/securityd/src/csproxy.cpp new file mode 100644 index 00000000..6d293910 --- /dev/null +++ b/securityd/src/csproxy.cpp @@ -0,0 +1,531 @@ +/* + * Copyright (c) 2006-2010 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@ + */ + + +// +// csproxy - Code Signing Hosting Proxy +// +#include "csproxy.h" +#include "server.h" +#include +#include +#include + + +// +// Construct a CodeSigningHost +// +CodeSigningHost::CodeSigningHost() + : mLock(Mutex::recursive), mHostingState(noHosting) +{ +} + + +// +// Cleanup code. +// +CodeSigningHost::~CodeSigningHost() +{ + reset(); +} + + +// +// Reset Code Signing Hosting state. +// This turns hosting off and clears all children. +// +void CodeSigningHost::reset() +{ + StLock _(mLock); + switch (mHostingState) { + case noHosting: + break; // nothing to do + case dynamicHosting: + mHostingPort.destroy(); + mHostingPort = MACH_PORT_NULL; + SECURITYD_HOST_UNREGISTER(DTSELF); + break; + case proxyHosting: + Server::active().remove(*this); // unhook service handler + mHostingPort.destroy(); // destroy receive right + mHostingState = noHosting; + mHostingPort = MACH_PORT_NULL; + mGuests.erase(mGuests.begin(), mGuests.end()); + SECURITYD_HOST_UNREGISTER(DTSELF); + break; + } +} + + +// +// Given a host reference (possibly NULL for the process itself), locate +// its most dedicated guest. This descends a contiguous chain of dedicated +// guests until it find a host that either has no guests, or whose guests +// are not dedicated. +// +CodeSigningHost::Guest *CodeSigningHost::findHost(SecGuestRef hostRef) +{ + Guest *host = findGuest(hostRef, true); + for (;;) { + if (Guest *guest = findGuest(host)) + if (guest->dedicated) { + host = guest; + continue; + } + return host; + } +} + + +// +// Look up guest by guestRef. +// Throws if we don't have a guest by that ref. +// +CodeSigningHost::Guest *CodeSigningHost::findGuest(SecGuestRef guestRef, bool hostOk /* = false */) +{ + GuestMap::iterator it = mGuests.find(guestRef); + if (it == mGuests.end()) + if (hostOk) + return NULL; + else + MacOSError::throwMe(errSecCSNoSuchCode); + assert(it->first == it->second->guestRef()); + return it->second; +} + + +// +// Look up guest by attribute set. +// Returns the host if the attributes can't be found (*loose* interpretation). +// Throws if multiple guests are found (ambiguity). +// Implicitly matches dedicated guests no matter what attributes are requested. +// +CodeSigningHost::Guest *CodeSigningHost::findGuest(Guest *host, const CssmData &attrData) +{ + CFRef attrDict = attrData + ? makeCFDictionaryFrom(attrData.data(), attrData.length()) + : makeCFDictionary(0); + CFDictionary attrs(attrDict, errSecCSInvalidAttributeValues); + + // if a guest handle was provided, start with that - it must be valid or we fail + if (CFNumberRef canonical = attrs.get(kSecGuestAttributeCanonical)) { + // direct lookup by SecGuestRef (canonical guest handle) + SecGuestRef guestRef = cfNumber(canonical); + if (Guest *guest = findGuest(guestRef, true)) // found guest handle + if (guest->isGuestOf(host, loose)) + host = guest; // new starting point + else + MacOSError::throwMe(errSecCSNoSuchCode); // not a guest of given host + else + MacOSError::throwMe(errSecCSNoSuchCode); // not there at all + } + + // now take the rest of the attrs + CFIndex count = CFDictionaryGetCount(attrs); + CFTypeRef keys[count], values[count]; + CFDictionaryGetKeysAndValues(attrs, keys, values); + for (;;) { + Guest *match = NULL; // previous match found + for (GuestMap::const_iterator it = mGuests.begin(); it != mGuests.end(); ++it) + if (it->second->isGuestOf(host, strict)) + if (it->second->matches(count, keys, values)) + if (match) + MacOSError::throwMe(errSecCSMultipleGuests); // ambiguous + else + match = it->second; + if (!match) // nothing found + return host; + else + host = match; // and repeat + } +} + + +// +// Find any guest of a given host. +// This will return a randomly chosen guest of this host if it has any, +// or NULL if it has none (i.e. it is not a host). +// +CodeSigningHost::Guest *CodeSigningHost::findGuest(Guest *host) +{ + for (GuestMap::const_iterator it = mGuests.begin(); it != mGuests.end(); ++it) + if (it->second->isGuestOf(host, strict)) + return it->second; + return NULL; +} + + +// +// Register a hosting API service port where the host will dynamically +// answer hosting queries from interested parties. This switches the process +// to dynamic hosting mode, and is incompatible with proxy hosting. +// +void CodeSigningHost::registerCodeSigning(mach_port_t hostingPort, SecCSFlags flags) +{ + StLock _(mLock); + switch (mHostingState) { + case noHosting: + mHostingPort = hostingPort; + mHostingState = dynamicHosting; + SECURITYD_HOST_REGISTER(DTSELF, mHostingPort); + break; + default: + MacOSError::throwMe(errSecCSHostProtocolContradiction); + } +} + + +// +// Create a guest entry for the given host and prepare to answer for it +// when dynamic hosting queries are received for it. +// This engages proxy hosting mode, and is incompatible with dynamic hosting mode. +// +SecGuestRef CodeSigningHost::createGuest(SecGuestRef hostRef, + uint32_t status, const char *path, + const CssmData &cdhash, const CssmData &attributes, SecCSFlags flags) +{ + StLock _(mLock); + if (path[0] != '/') // relative path (relative to what? :-) + MacOSError::throwMe(errSecCSHostProtocolRelativePath); + if (cdhash.length() > maxUcspHashLength) + MacOSError::throwMe(errSecCSHostProtocolInvalidHash); + + // set up for hosting proxy services if nothing's there yet + switch (mHostingState) { + case noHosting: // first hosting call, this host + // set up proxy hosting + mHostingPort.allocate(); // allocate service port + MachServer::Handler::port(mHostingPort); // put into Handler + MachServer::active().add(*this); // start listening + mHostingState = proxyHosting; // now proxying for this host + SECURITYD_HOST_PROXY(DTSELF, mHostingPort); + break; + case proxyHosting: // already proxying + break; + case dynamicHosting: // in dynamic mode, can't switch + MacOSError::throwMe(errSecCSHostProtocolContradiction); + } + + RefPointer host = findHost(hostRef); + if (RefPointer knownGuest = findGuest(host)) // got a guest already + if (flags & kSecCSDedicatedHost) + MacOSError::throwMe(errSecCSHostProtocolDedicationError); // can't dedicate with other guests + else if (knownGuest->dedicated) + MacOSError::throwMe(errSecCSHostProtocolDedicationError); // other guest is already dedicated + + // create the new guest + RefPointer guest = new Guest; + if (host) + guest->guestPath = host->guestPath; + guest->guestPath.push_back(guest->handle()); + guest->status = status; + guest->path = path; + guest->setAttributes(attributes); + guest->setHash(cdhash, flags & kSecCSGenerateGuestHash); + guest->dedicated = (flags & kSecCSDedicatedHost); + mGuests[guest->guestRef()] = guest; + SECURITYD_GUEST_CREATE(DTSELF, hostRef, guest->guestRef(), guest->status, flags, guest->path.c_str()); + if (SECURITYD_GUEST_CDHASH_ENABLED()) + SECURITYD_GUEST_CDHASH(DTSELF, guest->guestRef(), + (void*)CFDataGetBytePtr(guest->cdhash), CFDataGetLength(guest->cdhash)); + return guest->guestRef(); +} + + +void CodeSigningHost::setGuestStatus(SecGuestRef guestRef, uint32_t status, const CssmData &attributes) +{ + StLock _(mLock); + if (mHostingState != proxyHosting) + MacOSError::throwMe(errSecCSHostProtocolNotProxy); + Guest *guest = findGuest(guestRef); + + // state modification machine + if ((status & ~guest->status) & kSecCodeStatusValid) + MacOSError::throwMe(errSecCSHostProtocolStateError); // can't set + if ((~status & guest->status) & (kSecCodeStatusHard | kSecCodeStatusKill)) + MacOSError::throwMe(errSecCSHostProtocolStateError); // can't clear + guest->status = status; + SECURITYD_GUEST_CHANGE(DTSELF, guestRef, status); + + // replace attributes if requested + if (attributes) + guest->setAttributes(attributes); +} + + +// +// Remove a guest previously introduced via createGuest(). +// +void CodeSigningHost::removeGuest(SecGuestRef hostRef, SecGuestRef guestRef) +{ + StLock _(mLock); + if (mHostingState != proxyHosting) + MacOSError::throwMe(errSecCSHostProtocolNotProxy); + RefPointer host = findHost(hostRef); + RefPointer guest = findGuest(guestRef); + if (guest->dedicated) // can't remove a dedicated guest + MacOSError::throwMe(errSecCSHostProtocolDedicationError); + if (!guest->isGuestOf(host, strict)) + MacOSError::throwMe(errSecCSHostProtocolUnrelated); + for (GuestMap::iterator it = mGuests.begin(); it != mGuests.end(); ++it) + if (it->second->isGuestOf(guest, loose)) { + SECURITYD_GUEST_DESTROY(DTSELF, it->first); + mGuests.erase(it); + } +} + + +// +// The internal Guest object +// +CodeSigningHost::Guest::~Guest() +{ } + +void CodeSigningHost::Guest::setAttributes(const CssmData &attrData) +{ + CFRef guest = makeCFNumber(guestRef()); + if (attrData) { + attributes.take(cfmake("{+%O,%O=%O}", + makeCFDictionaryFrom(attrData.data(), attrData.length()), kSecGuestAttributeCanonical, guest.get())); + } else { + attributes.take(makeCFDictionary(1, kSecGuestAttributeCanonical, guest.get())); + } +} + +CFDataRef CodeSigningHost::Guest::attrData() const +{ + if (!mAttrData) + mAttrData = makeCFData(this->attributes.get()); + return mAttrData; +} + + +void CodeSigningHost::Guest::setHash(const CssmData &given, bool generate) +{ + if (given.length()) // explicitly given + this->cdhash.take(makeCFData(given)); + else if (CFTypeRef hash = CFDictionaryGetValue(this->attributes, kSecGuestAttributeHash)) + if (CFGetTypeID(hash) == CFDataGetTypeID()) + this->cdhash = CFDataRef(hash); + else + MacOSError::throwMe(errSecCSHostProtocolInvalidHash); + else if (generate) { // generate from path (well, try) + CFRef code; + MacOSError::check(SecStaticCodeCreateWithPath(CFTempURL(this->path), kSecCSDefaultFlags, &code.aref())); + CFRef info; + MacOSError::check(SecCodeCopySigningInformation(code, kSecCSDefaultFlags, &info.aref())); + this->cdhash = CFDataRef(CFDictionaryGetValue(info, kSecCodeInfoUnique)); + } +} + + +bool CodeSigningHost::Guest::isGuestOf(Guest *host, GuestCheck check) const +{ + vector hostPath; + if (host) + hostPath = host->guestPath; + if (hostPath.size() <= guestPath.size() + && !memcmp(&hostPath[0], &guestPath[0], sizeof(SecGuestRef) * hostPath.size())) + // hostPath is a prefix of guestPath + switch (check) { + case loose: + return true; + case strict: + return guestPath.size() == hostPath.size() + 1; // immediate guest + } + return false; +} + + +// +// Check to see if a given guest matches the (possibly empty) attribute set provided +// (in broken-open form, for efficiency). A dedicated guest will match all attribute +// specifications, even empty ones. A non-dedicated guest matches if at least one +// attribute value requested matches exactly (in the sense of CFEqual) that given +// by the host for this guest. +// +bool CodeSigningHost::Guest::matches(CFIndex count, CFTypeRef keys[], CFTypeRef values[]) const +{ + if (dedicated) + return true; + for (CFIndex n = 0; n < count; n++) { + CFStringRef key = CFStringRef(keys[n]); + if (CFEqual(key, kSecGuestAttributeCanonical)) // ignore canonical attribute (handled earlier) + continue; + if (CFTypeRef value = CFDictionaryGetValue(attributes, key)) + if (CFEqual(value, values[n])) + return true; + } + return false; +} + + +// +// The MachServer dispatch handler for proxy hosting. +// + +// give MIG handlers access to the object lock +struct CodeSigningHost::Lock : private StLock { + Lock(CodeSigningHost *host) : StLock(host->mLock) { } +}; + + +boolean_t cshosting_server(mach_msg_header_t *, mach_msg_header_t *); + +static ThreadNexus context; + +boolean_t CodeSigningHost::handle(mach_msg_header_t *in, mach_msg_header_t *out) +{ + CodeSigningHost::Lock _(this); + context() = this; + return cshosting_server(in, out); +} + + +// +// Proxy implementation of Code Signing Hosting protocol +// +#define CSH_ARGS mach_port_t servicePort, mach_port_t replyPort, OSStatus *rcode + +#define BEGIN_IPC try { +#define END_IPC *rcode = noErr; } \ + catch (const CommonError &err) { *rcode = err.osStatus(); } \ + catch (...) { *rcode = errSecCSInternalError; } \ + return KERN_SUCCESS; + +#define DATA_IN(base) void *base, mach_msg_type_number_t base##Length +#define DATA_OUT(base) void **base, mach_msg_type_number_t *base##Length +#define DATA(base) CssmData(base, base##Length) + + +// +// Find a guest by arbitrary attribute set. +// +// This returns an array of canonical guest references describing the path +// from the host given to the guest found. If the host itself is returned +// as a guest, this will be an empty array (zero length). +// +// The subhost return argument may in the future return the hosting port for +// a guest who dynamically manages its hosting (thus breaking out of proxy mode), +// but this is not yet implemented. +// +kern_return_t cshosting_server_findGuest(CSH_ARGS, SecGuestRef hostRef, + DATA_IN(attributes), + GuestChain *foundGuest, mach_msg_type_number_t *depth, mach_port_t *subhost) +{ + BEGIN_IPC + + *subhost = MACH_PORT_NULL; // preset no sub-hosting port returned + + Process::Guest *host = context()->findGuest(hostRef, true); + if (Process::Guest *guest = context()->findGuest(host, DATA(attributes))) { + *foundGuest = &guest->guestPath[0]; + *depth = guest->guestPath.size(); + } else { + *foundGuest = NULL; + *depth = 0; + } + END_IPC +} + + +// +// Retrieve the path to a guest specified by canonical reference. +// +kern_return_t cshosting_server_identifyGuest(CSH_ARGS, SecGuestRef guestRef, + char *path, char *hash, uint32_t *hashLength, DATA_OUT(attributes)) +{ + BEGIN_IPC + CodeSigningHost::Guest *guest = context()->findGuest(guestRef); + strncpy(path, guest->path.c_str(), MAXPATHLEN); + + // canonical cdhash + if (guest->cdhash) { + *hashLength = CFDataGetLength(guest->cdhash); + assert(*hashLength <= maxUcspHashLength); + memcpy(hash, CFDataGetBytePtr(guest->cdhash), *hashLength); + } else + *hashLength = 0; // unavailable + + // visible attributes. This proxy returns all attributes set by the host + CFDataRef attrData = guest->attrData(); // (the guest will cache this until it dies) + *attributes = (void *)CFDataGetBytePtr(attrData); // MIG botch (it doesn't need a writable pointer) + *attributesLength = CFDataGetLength(attrData); + + END_IPC +} + + +// +// Retrieve the status word for a guest specified by canonical reference. +// +kern_return_t cshosting_server_guestStatus(CSH_ARGS, SecGuestRef guestRef, uint32_t *status) +{ + BEGIN_IPC + *status = context()->findGuest(guestRef)->status; + END_IPC +} + + +// +// Debug support +// +#if defined(DEBUGDUMP) + +void CodeSigningHost::dump() const +{ + StLock _(mLock); + switch (mHostingState) { + case noHosting: + break; + case dynamicHosting: + Debug::dump(" dynamic host port=%d", mHostingPort.port()); + break; + case proxyHosting: + Debug::dump(" proxy-host port=%d", mHostingPort.port()); + if (!mGuests.empty()) { + Debug::dump(" %d guests={", int(mGuests.size())); + for (GuestMap::const_iterator it = mGuests.begin(); it != mGuests.end(); ++it) { + if (it != mGuests.begin()) + Debug::dump(", "); + it->second->dump(); + } + Debug::dump("}"); + } + break; + } +} + +void CodeSigningHost::Guest::dump() const +{ + Debug::dump("%s[", path.c_str()); + for (vector::const_iterator it = guestPath.begin(); it != guestPath.end(); ++it) { + if (it != guestPath.begin()) + Debug::dump("/"); + Debug::dump("0x%x", *it); + } + Debug::dump("; status=0x%x attrs=%s]", + status, cfString(CFCopyDescription(attributes), true).c_str()); +} + +#endif //DEBUGDUMP diff --git a/securityd/src/csproxy.h b/securityd/src/csproxy.h new file mode 100644 index 00000000..f1869613 --- /dev/null +++ b/securityd/src/csproxy.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2006-2008,2010 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@ + */ + + +// +// csproxy - Code Signing Hosting Proxy +// +#ifndef _H_CSPROXY +#define _H_CSPROXY + +#include +#include +#include +#include +#include +#include +#include +#include + +using MachPlusPlus::Port; +using MachPlusPlus::MachServer; + + +// +// CodeSigningHost is a mix-in for an object representing a primary +// Code Signing host object. It performs two notionally separate functions: +// (1) Register a hosting port. +// (2) Optionally, maintain a guest registry to offload the host's work. +// +class CodeSigningHost : private MachServer::Handler { +public: + CodeSigningHost(); + ~CodeSigningHost(); + void reset(); + + enum HostingState { + noHosting, // is not a host (yet), could go either way + dynamicHosting, // gave us its own hosting port to keep + proxyHosting // we act as a proxy for it + }; + + enum GuestCheck { + strict, // direct guest relationship required + loose // indirect or identity is okay (prefix check) + }; + + struct Guest : public RefCount, public HandleObject { + public: + ~Guest(); + std::vector guestPath; // guest chain to this guest + uint32_t status; // dynamic status + std::string path; // canonical code path + CFRef attributes; // matching attributes set + CFRef cdhash; // hash of CodeDirectory as specified by host + bool dedicated; // host is dedicated (and this is the only guest) + + operator bool() const { return attributes; } // exists + SecGuestRef guestRef() const { return handle(); } + void setAttributes(const CssmData &attrData); + CFDataRef attrData() const; + void setHash(const CssmData &given, bool generate); + + bool isGuestOf(Guest *host, GuestCheck check) const; + bool matches(CFIndex count, CFTypeRef keys[], CFTypeRef values[]) const; + + IFDUMP(void dump() const); + + private: + mutable CFRef mAttrData; // XML form of attributes (must live until guest destruction) + }; + + void registerCodeSigning(mach_port_t hostingPort, SecCSFlags flags); + Port hostingPort() const { return mHostingPort; } + + SecGuestRef createGuest(SecGuestRef guest, + uint32_t status, const char *path, + const CssmData &cdhash, const CssmData &attributes, SecCSFlags flags); + void setGuestStatus(SecGuestRef guest, uint32_t status, const CssmData &attributes); + void removeGuest(SecGuestRef host, SecGuestRef guest); + +public: + IFDUMP(void dump() const); + +public: + // internal use only (public for use by MIG handlers) + Guest *findHost(SecGuestRef hostRef); // find most dedicated guest of this host + Guest *findGuest(Guest *host, const CssmData &attrData); // by host and attributes + Guest *findGuest(SecGuestRef guestRef, bool hostOk = false); // by guest reference + Guest *findGuest(Guest *host); // any guest of this host + + class Lock; + friend class Lock; + +private: + boolean_t handle(mach_msg_header_t *in, mach_msg_header_t *out); + void eraseGuest(Guest *guest); + +private: + mutable Mutex mLock; // protects everything below + + // host port registry + HostingState mHostingState; // status of hosting support + Port mHostingPort; // his or ours or NULL + + // guest map (only used if mHostingState == proxyHosting) + typedef std::map > GuestMap; + GuestMap mGuests; +}; + + +#endif //_H_CSPROXY diff --git a/securityd/src/database.cpp b/securityd/src/database.cpp new file mode 100644 index 00000000..9067ce2e --- /dev/null +++ b/securityd/src/database.cpp @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2000-2008 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@ + */ + + +// +// database - database session management +// +#include "database.h" +#include "agentquery.h" +#include "key.h" +#include "server.h" +#include "session.h" +#include "notifications.h" +#include +#include +#include // for default owner ACLs +#include +#include + +using namespace UnixPlusPlus; + + +// +// DbCommon basics +// +DbCommon::DbCommon(Session &session) +{ + referent(session); +} + +Session &DbCommon::session() const +{ + return referent(); +} + + +// +// Database basics +// +Database::Database(Process &proc) +{ + referent(proc); +} + + +Process& Database::process() const +{ + return referent(); +} + + +// +// Send a keychain-related notification event about this database +// +void DbCommon::notify(NotificationEvent event, const DLDbIdentifier &ident) +{ + // form the data (encoded DLDbIdentifier) + NameValueDictionary nvd; + NameValueDictionary::MakeNameValueDictionaryFromDLDbIdentifier(ident, nvd); + CssmData data; + nvd.Export(data); + + // inject notification into Security event system + Listener::notify(kNotificationDomainDatabase, event, data); + + // clean up + free (data.data()); +} + + +// +// Default behaviors +// +void DbCommon::sleepProcessing() +{ + // nothing +} + +void DbCommon::lockProcessing() +{ + // nothing +} + +bool DbCommon::belongsToSystem() const +{ + return false; +} + + +void Database::releaseKey(Key &key) +{ + kill(key); +} + +void Database::releaseSearch(Search &search) +{ + kill(search); +} + +void Database::releaseRecord(Record &record) +{ + kill(record); +} + +void Database::dbName(const char *name) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + + +// +// Functions that aren't implemented at the Database level but can stay that way +// +void Database::findFirst(const CssmQuery &query, + CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength, + CssmData *data, RefPointer &key, RefPointer &search, RefPointer &record, + CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength) +{ + secdebug("database", "%p calling unimplemented findFirst", this); + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void Database::findNext(Search *search, + CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength, + CssmData *data, RefPointer &key, RefPointer &record, + CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength) +{ + secdebug("database", "%p calling unimplemented findNext", this); + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void Database::findRecordHandle(Record *record, + CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength, + CssmData *data, RefPointer &key, + CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength) +{ + secdebug("database", "%p calling unimplemented findRecordHandle", this); + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void Database::insertRecord(CSSM_DB_RECORDTYPE recordtype, + const CssmDbRecordAttributeData *attributes, mach_msg_type_number_t inAttributesLength, + const CssmData &data, RecordHandle &record) +{ + secdebug("database", "%p calling unimplemented insertRecord", this); + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void Database::modifyRecord(CSSM_DB_RECORDTYPE recordtype, Record *record, + const CssmDbRecordAttributeData *attributes, mach_msg_type_number_t inAttributesLength, + const CssmData *data, CSSM_DB_MODIFY_MODE modifyMode) +{ + secdebug("database", "%p calling unimplemented modifyRecord", this); + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void Database::deleteRecord(Database::Record *record) +{ + secdebug("database", "%p calling unimplemented deleteRecord", this); + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +void Database::authenticate(CSSM_DB_ACCESS_TYPE, const AccessCredentials *) +{ + secdebug("database", "%p calling unimplemented authenticate", this); + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +SecurityServerAcl &Database::acl() +{ + secdebug("database", "%p has no ACL implementation", this); + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + +bool Database::isLocked() +{ + secdebug("database", "%p calling unimplemented isLocked", this); + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + + +// +// SecurityServerAcl personality implementation. +// This is the trivial (type coding) stuff. The hard stuff is virtually mixed in. +// +Database *Database::relatedDatabase() +{ + return this; +} + +AclKind Database::aclKind() const +{ + return dbAcl; +} + + +// +// Remote validation is not, by default, supported +// +bool Database::validateSecret(const AclSubject *, const AccessCredentials *) +{ + return false; +} + + +// +// Implementation of a "system keychain unlock key store" +// +SystemKeychainKey::SystemKeychainKey(const char *path) + : mPath(path), mValid(false) +{ + // explicitly set up a key header for a raw 3DES key + CssmKey::Header &hdr = mKey.header(); + hdr.blobType(CSSM_KEYBLOB_RAW); + hdr.blobFormat(CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING); + hdr.keyClass(CSSM_KEYCLASS_SESSION_KEY); + hdr.algorithm(CSSM_ALGID_3DES_3KEY_EDE); + hdr.KeyAttr = 0; + hdr.KeyUsage = CSSM_KEYUSE_ANY; + mKey = CssmData::wrap(mBlob.masterKey); +} + +SystemKeychainKey::~SystemKeychainKey() +{ +} + +bool SystemKeychainKey::matches(const DbBlob::Signature &signature) +{ + return update() && signature == mBlob.signature; +} + +bool SystemKeychainKey::update() +{ + // if we checked recently, just assume it's okay + if (mValid && mUpdateThreshold > Time::now()) + return mValid; + + // check the file + struct stat st; + if (::stat(mPath.c_str(), &st)) { + // something wrong with the file; can't use it + mUpdateThreshold = Time::now() + Time::Interval(checkDelay); + return mValid = false; + } + if (mValid && Time::Absolute(st.st_mtimespec) == mCachedDate) + return true; + mUpdateThreshold = Time::now() + Time::Interval(checkDelay); + + try { + secdebug("syskc", "reading system unlock record from %s", mPath.c_str()); + AutoFileDesc fd(mPath, O_RDONLY); + if (fd.read(mBlob) != sizeof(mBlob)) + return false; + if (mBlob.isValid()) { + mCachedDate = st.st_mtimespec; + return mValid = true; + } else + return mValid = false; + } catch (...) { + secdebug("syskc", "system unlock record not available"); + return false; + } +} diff --git a/securityd/src/database.h b/securityd/src/database.h new file mode 100644 index 00000000..d065f41b --- /dev/null +++ b/securityd/src/database.h @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2000-2008 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@ + */ + + +// +// database - abstract database management +// +// This file defines database objects that represent different +// way to implement "database with cryptographic operations on its contents". +// The objects here are abstract and need to be implemented to be useful. +// +#ifndef _H_DATABASE +#define _H_DATABASE + +#include "structure.h" +#include "acls.h" +#include "dbcrypto.h" +#include "notifications.h" +#include +#include +#include +#include +#include +#include +#include +#include + + +class Key; +class Connection; +class Process; +class Session; +using MachPlusPlus::MachServer; + + +// +// A Database::DbCommon is the "common core" of all Database objects that +// represent the same client database (on disk, presumably). +// NOTE: DbCommon obeys exterior locking protocol: the caller (always Database) +// must lock it before operating on its non-const members. In practice, +// most Database methods lock down their DbCommon first thing. +// +class DbCommon : public PerSession { +public: + DbCommon(Session &ssn); + + Session &session() const; + + virtual void sleepProcessing(); // generic action on system sleep + virtual void lockProcessing(); // generic action on "lock" requests + + virtual bool belongsToSystem() const; // belongs to system (root) security domain + +protected: + void notify(NotificationEvent event, const DLDbIdentifier &ident); +}; + + +// +// A Database object represents an Apple CSP/DL open database (DL/DB) object. +// It maintains its protected semantic state (including keys) and provides controlled +// access. +// +class Database : public PerProcess, public AclSource { + static const NotificationEvent lockedEvent = kNotificationEventLocked; + static const NotificationEvent unlockedEvent = kNotificationEventUnlocked; + static const NotificationEvent passphraseChangedEvent = kNotificationEventPassphraseChanged; + +protected: + Database(Process &proc); + +public: + Process& process() const; + + virtual bool transient() const = 0; // is transient store (reboot clears) + +public: + // + // A common class for objects that "belong" to a Database and + // don't have parents up the global stack. These will die along with + // the Database when it goes. + // + class Subsidiary : public PerProcess { + public: + Subsidiary(Database &db) { referent(db); } + Database &database() const { return referent(); } + Process &process() const { return database().process(); } + }; + + // + // Cryptographic service calls. + // These must be supported by any type of database. + // + virtual void releaseKey(Key &key); + virtual void queryKeySizeInBits(Key &key, CssmKeySize &result) = 0; + virtual void getOutputSize(const Context &context, Key &key, + uint32 inputSize, bool encrypt, uint32 &result) = 0; + + virtual void generateSignature(const Context &context, Key &key, + CSSM_ALGORITHMS signOnlyAlgorithm, const CssmData &data, CssmData &signature) = 0; + virtual void verifySignature(const Context &context, Key &key, + CSSM_ALGORITHMS verifyOnlyAlgorithm, const CssmData &data, const CssmData &signature) = 0; + virtual void generateMac(const Context &context, Key &key, + const CssmData &data, CssmData &mac) = 0; + virtual void verifyMac(const Context &context, Key &key, + const CssmData &data, const CssmData &mac) = 0; + + virtual void encrypt(const Context &context, Key &key, const CssmData &clear, CssmData &cipher) = 0; + virtual void decrypt(const Context &context, Key &key, const CssmData &cipher, CssmData &clear) = 0; + + virtual void generateKey(const Context &context, + const AccessCredentials *cred, const AclEntryPrototype *owner, + uint32 usage, uint32 attrs, RefPointer &newKey) = 0; + virtual void generateKey(const Context &context, + const AccessCredentials *cred, const AclEntryPrototype *owner, + uint32 pubUsage, uint32 pubAttrs, uint32 privUsage, uint32 privAttrs, + RefPointer &publicKey, RefPointer &privateKey) = 0; + + virtual void wrapKey(const Context &context, const AccessCredentials *cred, + Key *wrappingKey, Key &keyToBeWrapped, + const CssmData &descriptiveData, CssmKey &wrappedKey) = 0; + virtual void unwrapKey(const Context &context, + const AccessCredentials *cred, const AclEntryPrototype *owner, + Key *wrappingKey, Key *publicKey, CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, + const CssmKey wrappedKey, RefPointer &unwrappedKey, CssmData &descriptiveData) = 0; + virtual void deriveKey(const Context &context, Key *key, + const AccessCredentials *cred, const AclEntryPrototype *owner, + CssmData *param, uint32 usage, uint32 attrs, RefPointer &derivedKey) = 0; + + virtual void authenticate(CSSM_DB_ACCESS_TYPE mode, const AccessCredentials *cred); + virtual SecurityServerAcl &acl(); + + virtual bool isLocked(); + +public: + class Search : public Subsidiary { + public: + Search(Database &db) : Subsidiary(db) { } + }; + + class Record : public Subsidiary { + public: + Record(Database &db) : Subsidiary(db) { } + }; + + virtual void findFirst(const CssmQuery &query, + CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength, + CssmData *data, RefPointer &key, RefPointer &search, + RefPointer &record, + CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength); + virtual void findNext(Search *search, + CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength, + CssmData *data, RefPointer &key, RefPointer &record, + CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength); + virtual void findRecordHandle(Record *record, + CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength, + CssmData *data, RefPointer &key, + CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength); + + virtual void insertRecord(CSSM_DB_RECORDTYPE recordtype, + const CssmDbRecordAttributeData *attributes, mach_msg_type_number_t inAttributesLength, + const CssmData &data, RecordHandle &record); + virtual void modifyRecord(CSSM_DB_RECORDTYPE recordtype, Record *record, + const CssmDbRecordAttributeData *attributes, mach_msg_type_number_t inAttributesLength, + const CssmData *data, CSSM_DB_MODIFY_MODE modifyMode); + virtual void deleteRecord(Database::Record *record); + + virtual void releaseSearch(Search &search); + virtual void releaseRecord(Record &record); + +public: + // SecurityServerAcl personality + AclKind aclKind() const; + Database *relatedDatabase(); + + bool belongsToSystem() const { return common().belongsToSystem(); } + +public: + // support ACL remote secret validation (default is no support) + virtual bool validateSecret(const AclSubject *subject, const AccessCredentials *cred); + +public: + static const int maxUnlockTryCount = 3; + +public: + DbCommon& common() const { return parent(); } + virtual const char *dbName() const = 0; + virtual void dbName(const char *name); +}; + + +// +// This class implements a "system keychain unlock record" store +// +class SystemKeychainKey { +public: + SystemKeychainKey(const char *path); + ~SystemKeychainKey(); + + bool matches(const DbBlob::Signature &signature); + CssmKey &key() { return mKey; } + +private: + std::string mPath; // path to file + CssmKey mKey; // proper CssmKey with data in mBlob + + bool mValid; // mBlob was validly read from mPath + UnlockBlob mBlob; // contents of mPath as last read + + Time::Absolute mCachedDate; // modify date of file when last read + Time::Absolute mUpdateThreshold; // cutoff threshold for checking again + + static const int checkDelay = 1; // seconds minimum delay between update checks + + bool update(); +}; + +#endif //_H_DATABASE diff --git a/securityd/src/dbcrypto.cpp b/securityd/src/dbcrypto.cpp new file mode 100644 index 00000000..22180f63 --- /dev/null +++ b/securityd/src/dbcrypto.cpp @@ -0,0 +1,542 @@ +/* + * Copyright (c) 2000-2006,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@ + */ + + +// +// dbcrypto - cryptographic core for database and key blob cryptography +// +#include "dbcrypto.h" +#include +#include "server.h" // just for Server::csp() +#include +#include +#include +#include +#include +#include + +using namespace CssmClient; +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() +{ + // key objects take care of themselves +} + + +// +// Forget the secrets +// +void DatabaseCryptoCore::invalidate() +{ + mMasterKey.release(); + mHaveMaster = false; + + mEncryptionKey.release(); + mSigningKey.release(); + mIsValid = false; +} + + +// +// Generate new secrets for this crypto core. +// +void DatabaseCryptoCore::generateNewSecrets() +{ + // create a random DES3 key + GenerateKey desGenerator(Server::csp(), CSSM_ALGID_3DES_3KEY_EDE, 24 * 8); + mEncryptionKey = desGenerator(KeySpec(CSSM_KEYUSE_WRAP | CSSM_KEYUSE_UNWRAP, + CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE)); + + // create a random 20 byte HMAC/SHA1 signing "key" + GenerateKey signGenerator(Server::csp(), CSSM_ALGID_SHA1HMAC, + sizeof(DbBlob::PrivateBlob::SigningKey) * 8); + mSigningKey = signGenerator(KeySpec(CSSM_KEYUSE_SIGN | CSSM_KEYUSE_VERIFY, + CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE)); + + // secrets established + mIsValid = true; +} + + +CssmClient::Key DatabaseCryptoCore::masterKey() +{ + assert(mHaveMaster); + return mMasterKey; +} + + +// +// Establish the master secret as derived from a passphrase passed in. +// If a DbBlob is passed, take the salt from it and remember it. +// 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) +{ + if (blob) + memcpy(mSalt, blob->salt, sizeof(mSalt)); + else + Server::active().random(mSalt); + mMasterKey = deriveDbMasterKey(passphrase); + mHaveMaster = true; +} + + +// +// Establish the master secret directly from a master key passed in. +// We will copy the KeyData (caller still owns its copy). +// Blob/salt handling as above. +// +void DatabaseCryptoCore::setup(const DbBlob *blob, CssmClient::Key master) +{ + // pre-screen the key + CssmKey::Header header = master.header(); + if (header.keyClass() != CSSM_KEYCLASS_SESSION_KEY) + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + if (header.algorithm() != CSSM_ALGID_3DES_3KEY_EDE) + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + + // accept it + if (blob) + memcpy(mSalt, blob->salt, sizeof(mSalt)); + else + Server::active().random(mSalt); + mMasterKey = master; + mHaveMaster = true; +} + +bool DatabaseCryptoCore::get_encryption_key(CssmOwnedData &data) +{ + bool result = false; + if (isValid()) { + data = mEncryptionKey->keyData(); + result = true; + } + return result; +} + +// +// Given a putative passphrase, determine whether that passphrase +// properly generates the database's master secret. +// Return a boolean accordingly. Do not change our state. +// The database must have a master secret (to compare with). +// Note that any errors thrown by the cryptography here will actually +// throw out of validatePassphrase, since they "should not happen" and +// thus indicate a problem *beyond* (just) a bad passphrase. +// +bool DatabaseCryptoCore::validatePassphrase(const CssmData &passphrase) +{ + assert(hasMaster()); + CssmClient::Key master = deriveDbMasterKey(passphrase); + + // to compare master with mMaster, see if they encrypt alike + StringData probe + ("Now is the time for all good processes to come to the aid of their kernel."); + CssmData noRemainder((void *)1, 0); // no cipher overflow + Encrypt cryptor(Server::csp(), CSSM_ALGID_3DES_3KEY_EDE); + cryptor.mode(CSSM_ALGMODE_CBCPadIV8); + cryptor.padding(CSSM_PADDING_PKCS1); + uint8 iv[8]; // leave uninitialized; pseudo-random is cool + cryptor.initVector(CssmData::wrap(iv)); + + cryptor.key(master); + CssmAutoData cipher1(Server::csp().allocator()); + cryptor.encrypt(probe, cipher1.get(), noRemainder); + + cryptor.key(mMasterKey); + CssmAutoData cipher2(Server::csp().allocator()); + cryptor.encrypt(probe, cipher2.get(), noRemainder); + + return cipher1 == cipher2; +} + + +// +// Encode a database blob from the core. +// +DbBlob *DatabaseCryptoCore::encodeCore(const DbBlob &blobTemplate, + const CssmData &publicAcl, const CssmData &privateAcl) const +{ + assert(isValid()); // must have secrets to work from + + // make a new IV + uint8 iv[8]; + Server::active().random(iv); + + // build the encrypted section blob + CssmData &encryptionBits = *mEncryptionKey; + CssmData &signingBits = *mSigningKey; + CssmData incrypt[3]; + incrypt[0] = encryptionBits; + incrypt[1] = signingBits; + incrypt[2] = privateAcl; + CssmData cryptoBlob, remData; + Encrypt cryptor(Server::csp(), CSSM_ALGID_3DES_3KEY_EDE); + cryptor.mode(CSSM_ALGMODE_CBCPadIV8); + cryptor.padding(CSSM_PADDING_PKCS1); + cryptor.key(mMasterKey); + CssmData ivd(iv, sizeof(iv)); cryptor.initVector(ivd); + cryptor.encrypt(incrypt, 3, &cryptoBlob, 1, remData); + + // allocate the final DbBlob, uh, blob + size_t length = sizeof(DbBlob) + publicAcl.length() + cryptoBlob.length(); + DbBlob *blob = Allocator::standard().malloc(length); + + // assemble the DbBlob + memset(blob, 0x7d, sizeof(DbBlob)); // deterministically fill any alignment gaps + blob->initialize(); + blob->randomSignature = blobTemplate.randomSignature; + blob->sequence = blobTemplate.sequence; + blob->params = blobTemplate.params; + memcpy(blob->salt, mSalt, sizeof(blob->salt)); + memcpy(blob->iv, iv, sizeof(iv)); + memcpy(blob->publicAclBlob(), publicAcl, publicAcl.length()); + blob->startCryptoBlob = sizeof(DbBlob) + publicAcl.length(); + memcpy(blob->cryptoBlob(), cryptoBlob, cryptoBlob.length()); + blob->totalLength = blob->startCryptoBlob + cryptoBlob.length(); + + // sign the blob + CssmData signChunk[] = { + CssmData(blob->data(), fieldOffsetOf(&DbBlob::blobSignature)), + CssmData(blob->publicAclBlob(), publicAcl.length() + cryptoBlob.length()) + }; + CssmData signature(blob->blobSignature, sizeof(blob->blobSignature)); + GenerateMac signer(Server::csp(), CSSM_ALGID_SHA1HMAC_LEGACY); + signer.key(mSigningKey); + signer.sign(signChunk, 2, signature); + assert(signature.length() == sizeof(blob->blobSignature)); + + // all done. Clean up + Server::csp()->allocator().free(cryptoBlob); + return blob; +} + + +// +// Decode a database blob into the core. +// Throws exceptions if decoding fails. +// Memory returned in privateAclBlob is allocated and becomes owned by caller. +// +void DatabaseCryptoCore::decodeCore(const DbBlob *blob, void **privateAclBlob) +{ + assert(mHaveMaster); // must have master key installed + + // try to decrypt the cryptoblob section + Decrypt decryptor(Server::csp(), CSSM_ALGID_3DES_3KEY_EDE); + decryptor.mode(CSSM_ALGMODE_CBCPadIV8); + decryptor.padding(CSSM_PADDING_PKCS1); + decryptor.key(mMasterKey); + CssmData ivd = CssmData::wrap(blob->iv); decryptor.initVector(ivd); + CssmData cryptoBlob = CssmData::wrap(blob->cryptoBlob(), blob->cryptoBlobLength()); + CssmData decryptedBlob, remData; + decryptor.decrypt(cryptoBlob, decryptedBlob, remData); + DbBlob::PrivateBlob *privateBlob = decryptedBlob.interpretedAs(); + + // tentatively establish keys + mEncryptionKey = makeRawKey(privateBlob->encryptionKey, + sizeof(privateBlob->encryptionKey), CSSM_ALGID_3DES_3KEY_EDE, + CSSM_KEYUSE_WRAP | CSSM_KEYUSE_UNWRAP); + mSigningKey = makeRawKey(privateBlob->signingKey, + sizeof(privateBlob->signingKey), CSSM_ALGID_SHA1HMAC, + CSSM_KEYUSE_SIGN | CSSM_KEYUSE_VERIFY); + + // verify signature on the whole blob + CssmData signChunk[] = { + CssmData::wrap(blob->data(), fieldOffsetOf(&DbBlob::blobSignature)), + CssmData::wrap(blob->publicAclBlob(), blob->publicAclBlobLength() + blob->cryptoBlobLength()) + }; + CSSM_ALGORITHMS verifyAlgorithm = CSSM_ALGID_SHA1HMAC; +#if defined(COMPAT_OSX_10_0) + if (blob->version() == blob->version_MacOS_10_0) + verifyAlgorithm = CSSM_ALGID_SHA1HMAC_LEGACY; // BSafe bug compatibility +#endif + VerifyMac verifier(Server::csp(), verifyAlgorithm); + verifier.key(mSigningKey); + verifier.verify(signChunk, 2, CssmData::wrap(blob->blobSignature)); + + // all checks out; start extracting fields + if (privateAclBlob) { + // extract private ACL blob as a separately allocated area + uint32 blobLength = decryptedBlob.length() - sizeof(DbBlob::PrivateBlob); + *privateAclBlob = Allocator::standard().malloc(blobLength); + memcpy(*privateAclBlob, privateBlob->privateAclBlob(), blobLength); + } + + // secrets have been established + mIsValid = true; + Allocator::standard().free(privateBlob); +} + + +// +// Make another DatabaseCryptoCore's operational secrets our own. +// Intended for keychain synchronization. +// +void DatabaseCryptoCore::importSecrets(const DatabaseCryptoCore &src) +{ + assert(src.isValid()); // must have called src.decodeCore() first + assert(hasMaster()); + mEncryptionKey = src.mEncryptionKey; + mSigningKey = src.mSigningKey; + mIsValid = true; +} + +// +// Encode a key blob +// +KeyBlob *DatabaseCryptoCore::encodeKeyCore(const CssmKey &inKey, + const CssmData &publicAcl, const CssmData &privateAcl, + bool inTheClear) const +{ + CssmKey key = inKey; + uint8 iv[8]; + CssmKey wrappedKey; + + if(inTheClear && (privateAcl.Length != 0)) { + /* can't store private ACL component in the clear */ + CssmError::throwMe(CSSMERR_DL_INVALID_ACCESS_CREDENTIALS); + } + + // extract and hold some header bits the CSP does not want to see + uint32 heldAttributes = key.attributes() & managedAttributes; + key.clearAttribute(managedAttributes); + key.setAttribute(forcedAttributes); + + if(inTheClear) { + /* NULL wrap of public key */ + WrapKey wrap(Server::csp(), CSSM_ALGID_NONE); + wrap(key, wrappedKey, NULL); + } + else { + assert(isValid()); // need our database secrets + + // create new IV + Server::active().random(iv); + + // use a CMS wrap to encrypt the key + WrapKey wrap(Server::csp(), CSSM_ALGID_3DES_3KEY_EDE); + wrap.key(mEncryptionKey); + wrap.mode(CSSM_ALGMODE_CBCPadIV8); + wrap.padding(CSSM_PADDING_PKCS1); + CssmData ivd(iv, sizeof(iv)); wrap.initVector(ivd); + wrap.add(CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT, + uint32(CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM)); + wrap(key, wrappedKey, &privateAcl); + } + + // stick the held attribute bits back in + key.clearAttribute(forcedAttributes); + key.setAttribute(heldAttributes); + + // allocate the final KeyBlob, uh, blob + size_t length = sizeof(KeyBlob) + publicAcl.length() + wrappedKey.length(); + KeyBlob *blob = Allocator::standard().malloc(length); + + // assemble the KeyBlob + memset(blob, 0, sizeof(KeyBlob)); // fill alignment gaps + blob->initialize(); + if(!inTheClear) { + memcpy(blob->iv, iv, sizeof(iv)); + } + blob->header = key.header(); + h2ni(blob->header); // endian-correct the header + blob->wrappedHeader.blobType = wrappedKey.blobType(); + blob->wrappedHeader.blobFormat = wrappedKey.blobFormat(); + blob->wrappedHeader.wrapAlgorithm = wrappedKey.wrapAlgorithm(); + blob->wrappedHeader.wrapMode = wrappedKey.wrapMode(); + memcpy(blob->publicAclBlob(), publicAcl, publicAcl.length()); + blob->startCryptoBlob = sizeof(KeyBlob) + publicAcl.length(); + memcpy(blob->cryptoBlob(), wrappedKey.data(), wrappedKey.length()); + blob->totalLength = blob->startCryptoBlob + wrappedKey.length(); + + if(inTheClear) { + /* indicate that this is cleartext for decoding */ + blob->setClearTextSignature(); + } + else { + // sign the blob + CssmData signChunk[] = { + CssmData(blob->data(), fieldOffsetOf(&KeyBlob::blobSignature)), + CssmData(blob->publicAclBlob(), blob->publicAclBlobLength() + blob->cryptoBlobLength()) + }; + CssmData signature(blob->blobSignature, sizeof(blob->blobSignature)); + GenerateMac signer(Server::csp(), CSSM_ALGID_SHA1HMAC_LEGACY); //@@@!!! CRUD + signer.key(mSigningKey); + signer.sign(signChunk, 2, signature); + assert(signature.length() == sizeof(blob->blobSignature)); + } + + // all done. Clean up + Server::csp()->allocator().free(wrappedKey); + return blob; +} + + +// +// Decode a key blob +// +void DatabaseCryptoCore::decodeKeyCore(KeyBlob *blob, + CssmKey &key, void * &pubAcl, void * &privAcl) const +{ + // Assemble the encrypted blob as a CSSM "wrapped key" + CssmKey wrappedKey; + wrappedKey.KeyHeader = blob->header; + h2ni(wrappedKey.KeyHeader); + wrappedKey.blobType(blob->wrappedHeader.blobType); + wrappedKey.blobFormat(blob->wrappedHeader.blobFormat); + wrappedKey.wrapAlgorithm(blob->wrappedHeader.wrapAlgorithm); + wrappedKey.wrapMode(blob->wrappedHeader.wrapMode); + wrappedKey.KeyData = CssmData(blob->cryptoBlob(), blob->cryptoBlobLength()); + + bool inTheClear = blob->isClearText(); + if(!inTheClear) { + // verify signature (check against corruption) + assert(isValid()); // need our database secrets + CssmData signChunk[] = { + CssmData::wrap(blob, fieldOffsetOf(&KeyBlob::blobSignature)), + CssmData(blob->publicAclBlob(), blob->publicAclBlobLength() + blob->cryptoBlobLength()) + }; + CSSM_ALGORITHMS verifyAlgorithm = CSSM_ALGID_SHA1HMAC; + #if defined(COMPAT_OSX_10_0) + if (blob->version() == blob->version_MacOS_10_0) + verifyAlgorithm = CSSM_ALGID_SHA1HMAC_LEGACY; // BSafe bug compatibility + #endif + VerifyMac verifier(Server::csp(), verifyAlgorithm); + verifier.key(mSigningKey); + CssmData signature(blob->blobSignature, sizeof(blob->blobSignature)); + verifier.verify(signChunk, 2, signature); + } + /* else signature indicates cleartext */ + + // extract and hold some header bits the CSP does not want to see + uint32 heldAttributes = n2h(blob->header.attributes()) & managedAttributes; + + CssmData privAclData; + if(inTheClear) { + /* NULL unwrap */ + UnwrapKey unwrap(Server::csp(), CSSM_ALGID_NONE); + wrappedKey.clearAttribute(managedAttributes); //@@@ shouldn't be needed(?) + unwrap(wrappedKey, + KeySpec(n2h(blob->header.usage()), + (n2h(blob->header.attributes()) & ~managedAttributes) | forcedAttributes), + key, &privAclData); + } + else { + // decrypt the key using an unwrapping operation + UnwrapKey unwrap(Server::csp(), CSSM_ALGID_3DES_3KEY_EDE); + unwrap.key(mEncryptionKey); + unwrap.mode(CSSM_ALGMODE_CBCPadIV8); + unwrap.padding(CSSM_PADDING_PKCS1); + CssmData ivd(blob->iv, sizeof(blob->iv)); unwrap.initVector(ivd); + unwrap.add(CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT, + uint32(CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM)); + wrappedKey.clearAttribute(managedAttributes); //@@@ shouldn't be needed(?) + unwrap(wrappedKey, + KeySpec(n2h(blob->header.usage()), + (n2h(blob->header.attributes()) & ~managedAttributes) | forcedAttributes), + key, &privAclData); + } + + // compare retrieved key headers with blob headers (sanity check) + // @@@ this should probably be checked over carefully + CssmKey::Header &real = key.header(); + CssmKey::Header &incoming = blob->header; + n2hi(incoming); + + if (real.HeaderVersion != incoming.HeaderVersion || + real.cspGuid() != incoming.cspGuid()) + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + if (real.algorithm() != incoming.algorithm()) + CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); + + // re-insert held bits + key.header().KeyAttr |= heldAttributes; + + if(inTheClear && (real.keyClass() != CSSM_KEYCLASS_PUBLIC_KEY)) { + /* Spoof - cleartext KeyBlob passed off as private key */ + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + + // got a valid key: return the pieces + pubAcl = blob->publicAclBlob(); // points into blob (shared) + privAcl = privAclData; // was allocated by CSP decrypt, else NULL for + // cleatext keys + // key was set by unwrap operation +} + + +// +// Derive the blob-specific database blob encryption key from the passphrase and the salt. +// +CssmClient::Key DatabaseCryptoCore::deriveDbMasterKey(const CssmData &passphrase) const +{ + // derive an encryption key and IV from passphrase and salt + CssmClient::DeriveKey makeKey(Server::csp(), + CSSM_ALGID_PKCS5_PBKDF2, CSSM_ALGID_3DES_3KEY_EDE, 24 * 8); + makeKey.iterationCount(1000); + CssmData salt = CssmData::wrap(mSalt); + makeKey.salt(salt); + CSSM_PKCS5_PBKDF2_PARAMS params; + params.Passphrase = passphrase; + params.PseudoRandomFunction = CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1; + CssmData paramData = CssmData::wrap(params); + return makeKey(¶mData, KeySpec(CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE)); +} + + +// +// Turn raw keybits into a symmetric key in the CSP +// +CssmClient::Key DatabaseCryptoCore::makeRawKey(void *data, size_t length, + CSSM_ALGORITHMS algid, CSSM_KEYUSE usage) +{ + // build a fake key + CssmKey key; + key.header().BlobType = CSSM_KEYBLOB_RAW; + key.header().Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; + key.header().AlgorithmId = algid; + key.header().KeyClass = CSSM_KEYCLASS_SESSION_KEY; + key.header().KeyUsage = usage; + key.header().KeyAttr = 0; + key.KeyData = CssmData(data, length); + + // unwrap it into the CSP (but keep it raw) + UnwrapKey unwrap(Server::csp(), CSSM_ALGID_NONE); + CssmKey unwrappedKey; + CssmData descriptiveData; + unwrap(key, + KeySpec(CSSM_KEYUSE_ANY, CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE), + unwrappedKey, &descriptiveData, NULL); + return CssmClient::Key(Server::csp(), unwrappedKey); +} diff --git a/securityd/src/dbcrypto.h b/securityd/src/dbcrypto.h new file mode 100644 index 00000000..fdbc7f4b --- /dev/null +++ b/securityd/src/dbcrypto.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2000-2001,2003-2006,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@ + */ + + +// +// dbcrypto - cryptographic core for database and key blob cryptography +// +#ifndef _H_DBCRYPTO +#define _H_DBCRYPTO + +#include +#include +#include + +using namespace SecurityServer; + + +// +// A DatabaseCryptoCore object encapsulates the secret state of a database. +// It provides for encoding and decoding of database blobs and key blobs, +// and holds all state related to the database secrets. +// +class DatabaseCryptoCore { +public: + DatabaseCryptoCore(); + virtual ~DatabaseCryptoCore(); + + bool isValid() const { return mIsValid; } + bool hasMaster() const { return mHaveMaster; } + void invalidate(); + + void generateNewSecrets(); + CssmClient::Key masterKey(); + + void setup(const DbBlob *blob, const CssmData &passphrase); + void setup(const DbBlob *blob, CssmClient::Key master); + + void decodeCore(const DbBlob *blob, void **privateAclBlob = NULL); + DbBlob *encodeCore(const DbBlob &blobTemplate, + const CssmData &publicAcl, const CssmData &privateAcl) const; + void importSecrets(const DatabaseCryptoCore &src); + + KeyBlob *encodeKeyCore(const CssmKey &key, + const CssmData &publicAcl, const CssmData &privateAcl, + bool inTheClear) const; + void decodeKeyCore(KeyBlob *blob, + CssmKey &key, void * &pubAcl, void * &privAcl) const; + + static const uint32 managedAttributes = KeyBlob::managedAttributes; + static const uint32 forcedAttributes = KeyBlob::forcedAttributes; + + bool get_encryption_key(CssmOwnedData &data); + +public: + bool validatePassphrase(const CssmData &passphrase); + +private: + bool mHaveMaster; // master key has been entered (setup) + bool mIsValid; // master secrets are valid (decode or generateNew) + + CssmClient::Key mMasterKey; // database master key + uint8 mSalt[20]; // salt for master key derivation from passphrase (only) + + CssmClient::Key mEncryptionKey; // master encryption key + CssmClient::Key mSigningKey; // master signing key + + CssmClient::Key deriveDbMasterKey(const CssmData &passphrase) const; + CssmClient::Key makeRawKey(void *data, size_t length, + CSSM_ALGORITHMS algid, CSSM_KEYUSE usage); +}; + + +#endif //_H_DBCRYPTO diff --git a/securityd/src/dtrace.h b/securityd/src/dtrace.h new file mode 100644 index 00000000..6993a13f --- /dev/null +++ b/securityd/src/dtrace.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2007 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@ + */ + + +// +// dtrace - dtrace support in securityd +// +#ifndef _H_DTRACE +#define _H_DTRACE + + +// +// Typedefs used in the DTrace static probe interface +// +typedef const void *DTHandle; +typedef uint32_t DTPort; +typedef uint32_t DTGuest; + + +#define DTHANDLE(it) (dynamic_cast((it))) +#define DTSELF DTHANDLE(this) + + +#include "securityd_dtrace.h" + + + +#endif //_H_DTRACE diff --git a/securityd/src/entropy.cpp b/securityd/src/entropy.cpp new file mode 100644 index 00000000..5839c2a4 --- /dev/null +++ b/securityd/src/entropy.cpp @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2000-2004,2007-2008,2010,2012-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@ + */ + + +// +// EntropyManager - manage entropy on the system. +// +// Here is our mission: +// (1) On startup, read the entropy file and seed it into the RNG for initial use +// (2) Periodically, collect entropy from the system and seed it into the RNG +// (3) Once in a while, take entropy from the RNG and write it to the entropy file +// for use across reboots. +// +// This class will fail to operate if the process has (and retains) root privileges. +// We re-open the entropy file on each use so that we don't work with a "phantom" +// file that some fool administrator removed yesterday. +// +#include "entropy.h" +#include "dtrace.h" +#include +#include +#include +#include +#include +#include +#include +#include + +/* when true, action() called every 15 seconds */ +#define ENTROPY_QUICK_UPDATE 0 +#if ENTROPY_QUICK_UPDATE +#define COLLECT_INTERVAL 15 +#else +#define COLLECT_INTERVAL collectInterval +#endif //ENTROPY_QUICK_UPDATE + +using namespace UnixPlusPlus; + + +// +// During construction, we perform initial entropy file recovery. +// +EntropyManager::EntropyManager(MachPlusPlus::MachServer &srv, const char *entropyFile) + : DevRandomGenerator(true), server(srv), + mEntropyFilePath(entropyFile), mNextUpdate(Time::now()) +{ + // Read the entropy file and seed the RNG. It is not an error if we can't find one. + try { + AutoFileDesc oldEntropyFile(entropyFile, O_RDONLY); + char buffer[entropyFileSize]; + if (size_t size = oldEntropyFile.read(buffer)) + addEntropy(buffer, size); + } catch (...) { } + + // go through a collect/update/reschedule cycle immediately + action(); +} + + +// +// Timer action +// +void EntropyManager::action() +{ + collectEntropy(); + updateEntropyFile(); + + server.setTimer(this, Time::Interval(COLLECT_INTERVAL)); // drifting reschedule (desired) +} + + +static const double kBytesOfEntropyToCollect = 240; +// that gives us a minimum of 2.16 * 10^609 possible combinations. It's a finite number to be sure... + +static const int kExpectedLoops = 10; + +// Calculate the amount of entropy in the buffer (per Shannon's Entropy Calculation) +static double CalculateEntropy(const void* buffer, size_t bufferSize) +{ + double sizef = bufferSize; + const u_int8_t* charBuffer = (const u_int8_t*) buffer; + + // zero the tabulation array + int counts[256]; + memset(counts, 0, sizeof(counts)); + + // tabulate the occurances of each byte in the array + size_t i; + for (i = 0; i < bufferSize; ++i) + { + counts[charBuffer[i]] += 1; + } + + // calculate the number of bits/byte of entropy + double entropy = 0.0; + + for (i = 0; i < 256; ++i) + { + if (counts[i] > 0) + { + double p = ((double) counts[i]) / sizef; + double term = p * -log2(p); + entropy += term; + } + } + + double entropicBytes = bufferSize * entropy / 8.0; + + return entropicBytes; +} + + + +// +// Collect system timings and seed into the RNG. +// Note that the sysctl will block until the buffer is full or the timeout expires. +// We currently use a 1ms timeout, which almost always fills the buffer and +// does not provide enough of a delay to worry about it. If we ever get worried, +// we could call longTermActivity on the server object to get another thread going. +// + +void EntropyManager::collectEntropy() +{ + SECURITYD_ENTROPY_COLLECT(); + + int mib[4]; + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDGETENTROPY; + mib[3] = 1; // milliseconds maximum delay + + mach_timespec_t buffer[timingsToCollect]; + + int result; + + double bytesRemaining = kBytesOfEntropyToCollect; + + int loopCount = 0; + + while (bytesRemaining >= 0) + { + size_t size = sizeof(mach_timespec_t) * timingsToCollect; + + result = sysctl(mib,4, buffer, &size, NULL, 0); + if (result == -1) { + Syslog::alert("entropy measurement returned no entropy (errno=%d)", errno); + sleep(1); + } + else if (size == 0) + { + Syslog::alert("entropy measurement returned no entropy."); + sleep(1); + } + + // remove the non-entropic pieces from the buffer + u_int16_t nonEnt[timingsToCollect]; + + // treat the received buffer as an array of u_int16 and only take the first two bytes of each + u_int16_t *rawEnt = (u_int16_t*) buffer; + + int i; + for (i = 0; i < timingsToCollect; ++i) + { + nonEnt[i] = *rawEnt; + rawEnt += 4; + } + + SECURITYD_ENTROPY_SEED((void *)nonEnt, (unsigned int) sizeof(nonEnt)); + addEntropy(nonEnt, sizeof(nonEnt)); + + double entropyRead = CalculateEntropy(nonEnt, sizeof(nonEnt)); + bytesRemaining -= entropyRead; + + loopCount += 1; + } + + if (loopCount > kExpectedLoops) + { + Syslog::alert("Entropy collection fulfillment took %d loops", loopCount); + } +} + + +// +// (Re)write the entropy file with random data pulled from the RNG +// +void EntropyManager::updateEntropyFile() +{ + if (Time::now() >= mNextUpdate) { + try { + SECURITYD_ENTROPY_SAVE((char *)mEntropyFilePath.c_str()); + mNextUpdate = Time::now() + Time::Interval(updateInterval); + secdebug("entropy", "updating %s", mEntropyFilePath.c_str()); + char buffer[entropyFileSize]; + random(buffer, entropyFileSize); + AutoFileDesc entropyFile(mEntropyFilePath.c_str(), O_WRONLY | O_TRUNC | O_CREAT, 0600); + if (entropyFile.write(buffer) != entropyFileSize) + Syslog::warning("short write on entropy file %s", mEntropyFilePath.c_str()); + } catch (...) { + Syslog::warning("error writing entropy file %s", mEntropyFilePath.c_str()); + } + } +} + diff --git a/securityd/src/entropy.h b/securityd/src/entropy.h new file mode 100644 index 00000000..3f8e0a16 --- /dev/null +++ b/securityd/src/entropy.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2000-2004,2006 Apple Computer, 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@ + */ + + +// +// entropy - periodical to collect and seed entropy into /dev/random +// +#ifndef _H_ENTROPY +#define _H_ENTROPY + +#include +#include +#include + +using namespace Security; +using MachPlusPlus::MachServer; + + +// +// A (one-off) timer object that manages system entropy +// +class EntropyManager : public MachServer::Timer, private DevRandomGenerator { + // all the parameters you ever (should) want to change :-) + static const int collectInterval = 600; // collect every 10 minutes + static const int updateInterval = 3600 * 6; // update file every 6 hours + static const int timingsToCollect = 40; // how many timings? + +public: + EntropyManager(MachPlusPlus::MachServer &srv, const char *entropyFile); + + void action(); + + MachPlusPlus::MachServer &server; // to which we do setTimer() + +private: + string mEntropyFilePath; // absolute path to entropy file + Time::Absolute mNextUpdate; // next time for entropy file update + + void collectEntropy(); // collect system timings and seed RNG + void updateEntropyFile(); // update entropy file from RNG if it's time + + static const size_t entropyFileSize = 20; // bytes (effectively one SHA-1 worth) +}; + +#endif //_H_ENTROPY diff --git a/securityd/src/kcdatabase.cpp b/securityd/src/kcdatabase.cpp new file mode 100644 index 00000000..0fe99c62 --- /dev/null +++ b/securityd/src/kcdatabase.cpp @@ -0,0 +1,1501 @@ +/* + * Copyright (c) 2000-2009,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@ + */ + + +// +// kcdatabase - software database container implementation. +// +// General implementation notes: +// This leverages LocalDatabase/LocalKey for cryptography, and adds the +// storage coder/decoder logic that implements "keychain" databases in their +// intricately choreographed dance between securityd and the AppleCSPDL. +// As always, Database objects are lifetime-bound to their Process referent; +// they can also be destroyed explicitly with a client release call. +// DbCommons are reference-held by their Databases, with one extra special +// reference (from the Session) introduced when the database unlocks, and +// removed when it locks again. That way, an unused DbCommon dies when it +// is locked or when the Session dies, whichever happens earlier. +// There is (as yet) no global-scope Database object for Keychain databases. +// +#include "kcdatabase.h" +#include "agentquery.h" +#include "kckey.h" +#include "server.h" +#include "session.h" +#include "notifications.h" +#include // @@@ 4003540 workaround +#include +#include // for default owner ACLs +#include +#include +#include +#include +#include +#include +#include +#include +#include "securityd_service/securityd_service/securityd_service_client.h" +#include +#include + +void unflattenKey(const CssmData &flatKey, CssmKey &rawKey); //>> make static method on KeychainDatabase + +static int +unlock_keybag(KeychainDbCommon & dbCommon, const void * secret, int secret_len) +{ + int rc = -1; + + if (!dbCommon.isLoginKeychain()) return 0; + + service_context_t context = dbCommon.session().get_current_service_context(); + + // try to unlock first if not found then load/create or unlock + // loading should happen when the kb common object is created + // if it doesn't exist yet then the unlock will fail and we'll create everything + rc = service_client_kb_unlock(&context, secret, secret_len); + if (rc == KB_BagNotLoaded) { + if (service_client_kb_load(&context) == KB_BagNotFound) { + rc = service_client_kb_create(&context, secret, secret_len); + } else { + rc = service_client_kb_unlock(&context, secret, secret_len); + } + } + + if (rc != 0) { // if we just upgraded make sure we swap the encryption key to the password + if (!dbCommon.session().keybagGetState(session_keybag_check_master_key)) { + CssmAutoData encKey(Allocator::standard(Allocator::sensitive)); + dbCommon.get_encryption_key(encKey); + if ((rc = service_client_kb_unlock(&context, encKey.data(), (int)encKey.length())) == 0) { + rc = service_client_kb_change_secret(&context, encKey.data(), (int)encKey.length(), secret, secret_len); + } + + if (rc != 0) { // if a login.keychain password exists but doesnt on the keybag update it + bool no_pin = false; + if ((secret_len > 0) && service_client_kb_is_locked(&context, NULL, &no_pin) == 0) { + if (no_pin) { + syslog(LOG_ERR, "Updating iCloud keychain passphrase for uid %d", dbCommon.session().originatorUid()); + service_client_kb_change_secret(&context, NULL, 0, secret, secret_len); + } + } + } + } // session_keybag_check_master_key + } + + if (rc == 0) { + dbCommon.session().keybagSetState(session_keybag_unlocked|session_keybag_loaded|session_keybag_check_master_key); + } else { + syslog(LOG_ERR, "Failed to unlock iCloud keychain for uid %d", dbCommon.session().originatorUid()); + } + + return rc; +} + +static void +change_secret_on_keybag(KeychainDbCommon & dbCommon, const void * secret, int secret_len, const void * new_secret, int new_secret_len) +{ + if (!dbCommon.isLoginKeychain()) return; + + service_context_t context = dbCommon.session().get_current_service_context(); + + // if a login.keychain doesn't exist yet it comes into securityd as a create then change_secret + // we need to create the keybag in this case if it doesn't exist + if (service_client_kb_change_secret(&context, secret, secret_len, new_secret, new_secret_len) == KB_BagNotLoaded) { + if (service_client_kb_load(&context) == KB_BagNotFound) { + service_client_kb_create(&context, new_secret, new_secret_len); + } + } +} + +// +// Create a Database object from initial parameters (create operation) +// +KeychainDatabase::KeychainDatabase(const DLDbIdentifier &id, const DBParameters ¶ms, Process &proc, + const AccessCredentials *cred, const AclEntryPrototype *owner) + : LocalDatabase(proc), mValidData(false), mSecret(Allocator::standard(Allocator::sensitive)), mSaveSecret(false), version(0), mBlob(NULL) +{ + // save a copy of the credentials for later access control + mCred = DataWalkers::copy(cred, Allocator::standard()); + + // create a new random signature to complete the DLDbIdentifier + DbBlob::Signature newSig; + Server::active().random(newSig.bytes); + DbIdentifier ident(id, newSig); + + // create common block and initialize + RefPointer newCommon = new KeychainDbCommon(proc.session(), ident); + StLock _(*newCommon); + parent(*newCommon); + // new common is now visible (in ident-map) but we hold its lock + + // establish the new master secret + establishNewSecrets(cred, SecurityAgent::newDatabase); + + // set initial database parameters + common().mParams = params; + + // the common is "unlocked" now + common().makeNewSecrets(); + + // establish initial ACL + if (owner) + acl().cssmSetInitial(*owner); + else + acl().cssmSetInitial(new AnyAclSubject()); + mValidData = true; + + // for now, create the blob immediately + encode(); + + proc.addReference(*this); + + // this new keychain is unlocked; make it so + activity(); + + SECURITYD_KEYCHAIN_CREATE(&common(), (char*)this->dbName(), this); +} + + +// +// Create a Database object from a database blob (decoding) +// +KeychainDatabase::KeychainDatabase(const DLDbIdentifier &id, const DbBlob *blob, Process &proc, + const AccessCredentials *cred) + : LocalDatabase(proc), mValidData(false), mSecret(Allocator::standard(Allocator::sensitive)), mSaveSecret(false), version(0), mBlob(NULL) +{ + validateBlob(blob); + + // save a copy of the credentials for later access control + mCred = DataWalkers::copy(cred, Allocator::standard()); + mBlob = blob->copy(); + + // check to see if we already know about this database + DbIdentifier ident(id, blob->randomSignature); + Session &session = process().session(); + if (RefPointer dbcom = + session.findFirst(&KeychainDbCommon::identifier, ident)) { + parent(*dbcom); + //@@@ arbitrate sequence number here, perhaps update common().mParams + SECURITYD_KEYCHAIN_JOIN(&common(), (char*)this->dbName(), this); + } else { + // DbCommon not present; make a new one + parent(*new KeychainDbCommon(proc.session(), ident)); + common().mParams = blob->params; + SECURITYD_KEYCHAIN_MAKE(&common(), (char*)this->dbName(), this); + // this DbCommon is locked; no timer or reference setting + } + proc.addReference(*this); +} + + +// recode/clone: +// +// Special-purpose constructor for keychain synchronization. Copies an +// existing keychain but uses the operational keys from secretsBlob. The +// new KeychainDatabase will silently replace the existing KeychainDatabase +// as soon as the client declares that re-encoding of all keychain items is +// finished. This is a little perilous since it allows a client to dictate +// securityd state, but we try to ensure that only the client that started +// the re-encoding can declare it done. +// +KeychainDatabase::KeychainDatabase(KeychainDatabase &src, Process &proc, DbHandle dbToClone) + : 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 + std::string newDbName = std::string("////") + std::string(src.identifier().dbName()); + DLDbIdentifier newDLDbIdent(src.identifier().dlDbIdentifier().ssuid(), newDbName.c_str(), src.identifier().dlDbIdentifier().dbLocation()); + DbIdentifier ident(newDLDbIdent, src.identifier()); + + // create common block and initialize + RefPointer newCommon = new KeychainDbCommon(proc.session(), ident); + StLock _(*newCommon); + parent(*newCommon); + + // set initial database parameters from the source keychain + common().mParams = src.common().mParams; + + // establish the source keychain's master secret as ours + // @@@ NB: this is a v. 0.1 assumption. We *should* trigger new UI + // that offers the user the option of using the existing password + // or choosing a new one. That would require a new + // SecurityAgentQuery type, new UI, and--possibly--modifications to + // ensure that the new password is available here to generate the + // new master secret. + src.unlockDb(); // precaution for masterKey() + common().setup(src.blob(), src.common().masterKey()); + + // import the operational secrets + RefPointer srcKC = Server::keychain(dbToClone); + common().importSecrets(srcKC->common()); + + // 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 copy, common at %p", + common().dbName(), this, &common()); +} + +// +// Destroy a Database +// +KeychainDatabase::~KeychainDatabase() +{ + secdebug("KCdb", "deleting database %s(%p) common %p", + common().dbName(), this, &common()); + Allocator::standard().free(mCred); + Allocator::standard().free(mBlob); +} + + +// +// Basic Database virtual implementations +// +KeychainDbCommon &KeychainDatabase::common() const +{ + return parent(); +} + +const char *KeychainDatabase::dbName() const +{ + return common().dbName(); +} + +bool KeychainDatabase::transient() const +{ + return false; // has permanent store +} + +AclKind KeychainDatabase::aclKind() const +{ + return dbAcl; +} + +Database *KeychainDatabase::relatedDatabase() +{ + return this; +} + + +static inline KeychainKey &myKey(Key *key) +{ + return *safe_cast(key); +} + + +// +// (Re-)Authenticate the database. This changes the stored credentials. +// +void KeychainDatabase::authenticate(CSSM_DB_ACCESS_TYPE mode, + const AccessCredentials *cred) +{ + StLock _(common()); + + // the (Apple specific) RESET bit means "lock the database now" + switch (mode) { + case CSSM_DB_ACCESS_RESET: + secdebug("KCdb", "%p ACCESS_RESET triggers keychain lock", this); + common().lockDb(); + break; + default: + // store the new credentials for future use + secdebug("KCdb", "%p authenticate stores new database credentials", this); + AccessCredentials *newCred = DataWalkers::copy(cred, Allocator::standard()); + Allocator::standard().free(mCred); + mCred = newCred; + } +} + + +// +// Make a new KeychainKey. +// If PERMANENT is off, make a temporary key instead. +// The db argument allows you to create for another KeychainDatabase (only); +// it defaults to ourselves. +// +RefPointer KeychainDatabase::makeKey(Database &db, const CssmKey &newKey, + uint32 moreAttributes, const AclEntryPrototype *owner) +{ + + if (moreAttributes & CSSM_KEYATTR_PERMANENT) + return new KeychainKey(db, newKey, moreAttributes, owner); + else + return process().makeTemporaryKey(newKey, moreAttributes, owner); +} + +RefPointer KeychainDatabase::makeKey(const CssmKey &newKey, + uint32 moreAttributes, const AclEntryPrototype *owner) +{ + return makeKey(*this, newKey, moreAttributes, owner); +} + + +// +// Return the database blob, recalculating it as needed. +// +DbBlob *KeychainDatabase::blob() +{ + StLock _(common()); + if (!validBlob()) { + makeUnlocked(); // unlock to get master secret + encode(); // (re)encode blob if needed + } + activity(); // reset timeout + assert(validBlob()); // better have a valid blob now... + return mBlob; +} + + +// +// Encode the current database as a blob. +// Note that this returns memory we own and keep. +// Caller must hold common lock. +// +void KeychainDatabase::encode() +{ + DbBlob *blob = common().encode(*this); + Allocator::standard().free(mBlob); + mBlob = blob; + version = common().version; + secdebug("KCdb", "encoded database %p common %p(%s) version %u params=(%u,%u)", + this, &common(), dbName(), version, + common().mParams.idleTimeout, common().mParams.lockOnSleep); +} + + +// +// Change the passphrase on a database +// +void KeychainDatabase::changePassphrase(const AccessCredentials *cred) +{ + // get and hold the common lock (don't let other threads break in here) + StLock _(common()); + + // establish OLD secret - i.e. unlock the database + //@@@ do we want to leave the final lock state alone? + if (common().isLoginKeychain()) mSaveSecret = true; + makeUnlocked(cred); + + // establish NEW secret + establishNewSecrets(cred, SecurityAgent::changePassphrase); + if (mSecret) { mSecret.reset(); } + mSaveSecret = false; + common().invalidateBlob(); // blob state changed + secdebug("KCdb", "Database %s(%p) master secret changed", common().dbName(), this); + encode(); // force rebuild of local blob + + // send out a notification + notify(kNotificationEventPassphraseChanged); + + // I guess this counts as an activity + activity(); +} + +// +// Second stage of keychain synchronization: overwrite the original keychain's +// (this KeychainDatabase's) operational secrets +// +void KeychainDatabase::commitSecretsForSync(KeychainDatabase &cloneDb) +{ + StLock _(common()); + + // try to detect spoofing + if (cloneDb.mRecodingSource != this) + CssmError::throwMe(CSSM_ERRCODE_INVALID_DB_HANDLE); + + // in case we autolocked since starting the sync + makeUnlocked(); // call this because we already own the lock + cloneDb.unlockDb(); // we may not own the lock here, so calling unlockDb will lock the cloneDb's common lock + + // Decode all keys whose handles refer to this on-disk keychain so that + // if the holding client commits the key back to disk, it's encoded with + // the new operational secrets. The recoding client *must* hold a write + // lock for the on-disk keychain from the moment it starts recoding key + // items until after this call. + // + // @@@ This specific implementation is a workaround for 4003540. + std::vector handleList; + U32HandleObject::findAllRefs(handleList); + size_t count = handleList.size(); + if (count > 0) { + for (unsigned int n = 0; n < count; ++n) { + RefPointer kckey = + U32HandleObject::findRefAndLock(handleList[n], CSSMERR_CSP_INVALID_KEY_REFERENCE); + StLock _(*kckey/*, true*/); + if (kckey->database().global().identifier() == identifier()) { + kckey->key(); // force decode + kckey->invalidateBlob(); + secdebug("kcrecode", "changed extant key %p (proc %d)", + &*kckey, kckey->process().pid()); + } + } + } + + // it is now safe to replace the old op secrets + common().importSecrets(cloneDb.common()); + common().invalidateBlob(); +} + + +// +// Extract the database master key as a proper Key object. +// +RefPointer KeychainDatabase::extractMasterKey(Database &db, + const AccessCredentials *cred, const AclEntryPrototype *owner, + uint32 usage, uint32 attrs) +{ + // get and hold common lock + StLock _(common()); + + // force lock to require re-validation of credentials + lockDb(); + + // unlock to establish master secret + makeUnlocked(); + + // extract the raw cryptographic key + CssmClient::WrapKey wrap(Server::csp(), CSSM_ALGID_NONE); + CssmKey key; + wrap(common().masterKey(), key); + + // make the key object and return it + return makeKey(db, key, attrs & LocalKey::managedAttributes, owner); +} + + +// +// Unlock this database (if needed) by obtaining the master secret in some +// suitable way and then proceeding to unlock with it. +// Does absolutely nothing if the database is already unlocked. +// The makeUnlocked forms are identical except the assume the caller already +// holds the common lock. +// +void KeychainDatabase::unlockDb() +{ + StLock _(common()); + makeUnlocked(); +} + +void KeychainDatabase::makeUnlocked() +{ + return makeUnlocked(mCred); +} + +void KeychainDatabase::makeUnlocked(const AccessCredentials *cred) +{ + if (isLocked()) { + secdebug("KCdb", "%p(%p) unlocking for makeUnlocked()", this, &common()); + assert(mBlob || (mValidData && common().hasMaster())); + establishOldSecrets(cred); + common().setUnlocked(); // mark unlocked + if (common().isLoginKeychain()) { + CssmKey master = common().masterKey(); + CssmKey rawMaster; + CssmClient::WrapKey wrap(Server::csp(), CSSM_ALGID_NONE); + wrap(master, rawMaster); + + service_context_t context = common().session().get_current_service_context(); + service_client_stash_load_key(&context, rawMaster.keyData(), (int)rawMaster.length()); + } + } else if (common().isLoginKeychain()) { + bool locked = false; + service_context_t context = common().session().get_current_service_context(); + if ((service_client_kb_is_locked(&context, &locked, NULL) == 0) && locked) { + StSyncLock uisync(common().uiLock(), common()); + QueryKeybagPassphrase keybagQuery(common().session(), 3); + keybagQuery.inferHints(Server::process()); + if (keybagQuery.query() != SecurityAgent::noReason) { + syslog(LOG_NOTICE, "failed to unlock iCloud keychain"); + } + } + } + if (!mValidData) { // need to decode to get our ACLs, master secret available + secdebug("KCdb", "%p(%p) is unlocked; decoding for makeUnlocked()", this, &common()); + if (!decode()) + CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); + } + assert(!isLocked()); + assert(mValidData); +} + +// +// Invoke the securityd_service to retrieve the keychain master +// key from the AppleFDEKeyStore. +// +void KeychainDatabase::stashDbCheck() +{ + CssmAutoData masterKey(Allocator::standard(Allocator::sensitive)); + CssmAutoData encKey(Allocator::standard(Allocator::sensitive)); + + // Fetch the key + int rc = 0; + void * stash_key = NULL; + int stash_key_len = 0; + service_context_t context = common().session().get_current_service_context(); + rc = service_client_stash_get_key(&context, &stash_key, &stash_key_len); + if (rc == 0) { + if (stash_key) { + masterKey.copy(CssmData((void *)stash_key,stash_key_len)); + memset(stash_key, 0, stash_key_len); + free(stash_key); + } + } else { + CssmError::throwMe(rc); + } + + { + StLock _(common()); + + // Now establish it as the keychain master key + CssmClient::Key key(Server::csp(), masterKey.get()); + CssmKey::Header &hdr = key.header(); + hdr.keyClass(CSSM_KEYCLASS_SESSION_KEY); + hdr.algorithm(CSSM_ALGID_3DES_3KEY_EDE); + hdr.usage(CSSM_KEYUSE_ANY); + hdr.blobType(CSSM_KEYBLOB_RAW); + hdr.blobFormat(CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING); + common().setup(mBlob, key); + + if (!decode()) + CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); + + common().get_encryption_key(encKey); + } + + // when upgrading from pre-10.9 create a keybag if it doesn't exist with the encryption key + // only do this after we have verified the master key unlocks the login.keychain + if (service_client_kb_load(&context) == KB_BagNotFound) { + service_client_kb_create(&context, encKey.data(), (int)encKey.length()); + } +} + +// +// Get the keychain master key and invoke the securityd_service +// to stash it in the AppleFDEKeyStore ready for commit to the +// NVRAM blob. +// +void KeychainDatabase::stashDb() +{ + CssmAutoData data(Allocator::standard(Allocator::sensitive)); + + { + StLock _(common()); + + if (!common().isValid()) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + + CssmKey key = common().masterKey(); + data.copy(key.keyData()); + } + + service_context_t context = common().session().get_current_service_context(); + int rc = service_client_stash_set_key(&context, data.data(), (int)data.length()); + if (rc != 0) CssmError::throwMe(rc); +} + +// +// The following unlock given an explicit passphrase, rather than using +// (special cred sample based) default procedures. +// +void KeychainDatabase::unlockDb(const CssmData &passphrase) +{ + StLock _(common()); + makeUnlocked(passphrase); +} + +void KeychainDatabase::makeUnlocked(const CssmData &passphrase) +{ + if (isLocked()) { + if (decode(passphrase)) + return; + else + CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); + } else if (!mValidData) { // need to decode to get our ACLs, passphrase available + if (!decode()) + CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); + } + + if (common().isLoginKeychain()) { + bool locked = false; + service_context_t context = common().session().get_current_service_context(); + if (!common().session().keybagGetState(session_keybag_check_master_key) || ((service_client_kb_is_locked(&context, &locked, NULL) == 0) && locked)) { + unlock_keybag(common(), passphrase.data(), (int)passphrase.length()); + } + } + + assert(!isLocked()); + assert(mValidData); +} + + +// +// Nonthrowing passphrase-based unlock. This returns false if unlock failed. +// Note that this requires an explicitly given passphrase. +// Caller must hold common lock. +// +bool KeychainDatabase::decode(const CssmData &passphrase) +{ + assert(mBlob); + common().setup(mBlob, passphrase); + bool success = decode(); + if (success && common().isLoginKeychain()) { + unlock_keybag(common(), passphrase.data(), (int)passphrase.length()); + } + return success; +} + + +// +// Given the established master secret, decode the working keys and other +// functional secrets for this database. Return false (do NOT throw) if +// the decode fails. Call this in low(er) level code once you established +// the master key. +// +bool KeychainDatabase::decode() +{ + assert(mBlob); + assert(common().hasMaster()); + void *privateAclBlob; + if (common().unlockDb(mBlob, &privateAclBlob)) { + if (!mValidData) { + acl().importBlob(mBlob->publicAclBlob(), privateAclBlob); + mValidData = true; + } + Allocator::standard().free(privateAclBlob); + return true; + } + secdebug("KCdb", "%p decode failed", this); + return false; +} + + +// +// Given an AccessCredentials for this database, wring out the existing primary +// database secret by whatever means necessary. +// On entry, caller must hold the database common lock. It will be held +// throughout except when user interaction is required. User interaction +// requires relinquishing the database common lock and taking the UI lock. On +// return from user interaction, the UI lock is relinquished and the database +// common lock must be reacquired. At no time may the caller hold both locks. +// On exit, the crypto core has its master secret. If things go wrong, +// we will throw a suitable exception. Note that encountering any malformed +// credential sample will throw, but this is not guaranteed -- don't assume +// that NOT throwing means creds is entirely well-formed (it may just be good +// enough to work THIS time). +// +// How this works: +// Walk through the creds. Fish out those credentials (in order) that +// are for unlock processing (they have no ACL subject correspondents), +// and (try to) obey each in turn, until one produces a valid secret +// or you run out. If no special samples are found at all, interpret that as +// "use the system global default," which happens to be hard-coded right here. +// +void KeychainDatabase::establishOldSecrets(const AccessCredentials *creds) +{ + bool forSystem = this->belongsToSystem(); // this keychain belongs to the system security domain + + // attempt system-keychain unlock + if (forSystem) { + SystemKeychainKey systemKeychain(kSystemUnlockFile); + if (systemKeychain.matches(mBlob->randomSignature)) { + secdebug("KCdb", "%p attempting system unlock", this); + common().setup(mBlob, CssmClient::Key(Server::csp(), systemKeychain.key(), true)); + if (decode()) + return; + } + } + + list samples; + if (creds && creds->samples().collect(CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, samples)) { + for (list::iterator it = samples.begin(); it != samples.end(); it++) { + TypedList &sample = *it; + sample.checkProper(); + switch (sample.type()) { + // interactively prompt the user - no additional data + case CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT: + if (!forSystem) { + if (interactiveUnlock()) + return; + } + 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", this); + if (decode(sample[1])) + return; + break; + // 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("KCdb", "%p attempting explicit key unlock", this); + common().setup(mBlob, keyFromCreds(sample, 4)); + if (decode()) { + return; + } + break; + // explicitly defeat the default action but don't try anything in particular + case CSSM_WORDID_CANCELED: + secdebug("KCdb", "%p defeat default action", this); + break; + default: + // Unknown sub-sample for unlocking. + // If we wanted to be fascist, we could now do + // CssmError::throwMe(CSSM_ERRCODE_SAMPLE_VALUE_NOT_SUPPORTED); + // But instead we try to be tolerant and continue on. + // This DOES however count as an explicit attempt at specifying unlock, + // so we will no longer try the default case below... + secdebug("KCdb", "%p unknown sub-sample unlock (%d) ignored", this, sample.type()); + break; + } + } + } else { + // default action + assert(mBlob); + + if (!forSystem) { + if (interactiveUnlock()) + return; + } + } + + // out of options - no secret obtained + CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); +} + +bool KeychainDatabase::interactiveUnlock() +{ + secdebug("KCdb", "%p attempting interactive unlock", this); + SecurityAgent::Reason reason = SecurityAgent::noReason; + QueryUnlock query(*this); + // take UI interlock and release DbCommon lock (to avoid deadlocks) + StSyncLock uisync(common().uiLock(), common()); + + // now that we have the UI lock, interact unless another thread unlocked us first + if (isLocked()) { + query.inferHints(Server::process()); + reason = query(); + if (mSaveSecret && reason == SecurityAgent::noReason) { + query.retrievePassword(mSecret); + } + query.disconnect(); + } else { + secdebug("KCdb", "%p was unlocked during uiLock delay", this); + } + + if (common().isLoginKeychain()) { + bool locked = false; + service_context_t context = common().session().get_current_service_context(); + if ((service_client_kb_is_locked(&context, &locked, NULL) == 0) && locked) { + QueryKeybagNewPassphrase keybagQuery(common().session()); + keybagQuery.inferHints(Server::process()); + CssmAutoData pass(Allocator::standard(Allocator::sensitive)); + CssmAutoData oldPass(Allocator::standard(Allocator::sensitive)); + SecurityAgent::Reason queryReason = keybagQuery.query(oldPass, pass); + if (queryReason == SecurityAgent::noReason) { + service_client_kb_change_secret(&context, oldPass.data(), (int)oldPass.length(), pass.data(), (int)pass.length()); + } else if (queryReason == SecurityAgent::resettingPassword) { + query.retrievePassword(pass); + service_client_kb_reset(&context, pass.data(), (int)pass.length()); + } + + } + } + + return reason == SecurityAgent::noReason; +} + + +// +// Same thing, but obtain a new secret somehow and set it into the common. +// +void KeychainDatabase::establishNewSecrets(const AccessCredentials *creds, SecurityAgent::Reason reason) +{ + list samples; + if (creds && creds->samples().collect(CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK, samples)) { + for (list::iterator it = samples.begin(); it != samples.end(); it++) { + TypedList &sample = *it; + sample.checkProper(); + switch (sample.type()) { + // interactively prompt the user + case CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT: + { + secdebug("KCdb", "%p specified interactive passphrase", this); + QueryNewPassphrase query(*this, reason); + StSyncLock uisync(common().uiLock(), common()); + query.inferHints(Server::process()); + CssmAutoData passphrase(Allocator::standard(Allocator::sensitive)); + CssmAutoData oldPassphrase(Allocator::standard(Allocator::sensitive)); + if (query(oldPassphrase, passphrase) == SecurityAgent::noReason) { + common().setup(NULL, passphrase); + change_secret_on_keybag(common(), oldPassphrase.data(), (int)oldPassphrase.length(), passphrase.data(), (int)passphrase.length()); + return; + } + } + break; + // try to use an explicitly given passphrase + case CSSM_SAMPLE_TYPE_PASSWORD: + { + secdebug("KCdb", "%p specified explicit passphrase", this); + if (sample.length() != 2) + CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE); + common().setup(NULL, sample[1]); + if (common().isLoginKeychain()) { + CssmAutoData oldPassphrase(Allocator::standard(Allocator::sensitive)); + list oldSamples; + creds->samples().collect(CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, oldSamples); + for (list::iterator oit = oldSamples.begin(); oit != oldSamples.end(); oit++) { + TypedList &tmpList = *oit; + tmpList.checkProper(); + if (tmpList.type() == CSSM_SAMPLE_TYPE_PASSWORD) { + if (tmpList.length() == 2) { + oldPassphrase = tmpList[1].data(); + } + } + } + if (!oldPassphrase.length() && mSecret && mSecret.length()) { + oldPassphrase = mSecret; + } + change_secret_on_keybag(common(), oldPassphrase.data(), (int)oldPassphrase.length(), sample[1].data().data(), (int)sample[1].data().length()); + } + return; + } + // try to open with a given master key + case CSSM_WORDID_SYMMETRIC_KEY: + case CSSM_SAMPLE_TYPE_ASYMMETRIC_KEY: + secdebug("KCdb", "%p specified explicit master key", this); + common().setup(NULL, keyFromCreds(sample, 3)); + return; + // explicitly defeat the default action but don't try anything in particular + case CSSM_WORDID_CANCELED: + secdebug("KCdb", "%p defeat default action", this); + break; + default: + // Unknown sub-sample for acquiring new secret. + // If we wanted to be fascist, we could now do + // CssmError::throwMe(CSSM_ERRCODE_SAMPLE_VALUE_NOT_SUPPORTED); + // But instead we try to be tolerant and continue on. + // This DOES however count as an explicit attempt at specifying unlock, + // so we will no longer try the default case below... + secdebug("KCdb", "%p unknown sub-sample acquisition (%d) ignored", + this, sample.type()); + break; + } + } + } else { + // default action -- interactive (only) + QueryNewPassphrase query(*this, reason); + StSyncLock uisync(common().uiLock(), common()); + query.inferHints(Server::process()); + CssmAutoData passphrase(Allocator::standard(Allocator::sensitive)); + CssmAutoData oldPassphrase(Allocator::standard(Allocator::sensitive)); + if (query(oldPassphrase, passphrase) == SecurityAgent::noReason) { + common().setup(NULL, passphrase); + change_secret_on_keybag(common(), oldPassphrase.data(), (int)oldPassphrase.length(), passphrase.data(), (int)passphrase.length()); + return; + } + } + + // out of options - no secret obtained + CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); +} + + +// +// Given a (truncated) Database credentials TypedList specifying a master key, +// locate the key and return a reference to it. +// +CssmClient::Key KeychainDatabase::keyFromCreds(const TypedList &sample, unsigned int requiredLength) +{ + // decode TypedList structure (sample type; Data:CSPHandle; Data:CSSM_KEY) + assert(sample.type() == CSSM_SAMPLE_TYPE_SYMMETRIC_KEY || sample.type() == CSSM_SAMPLE_TYPE_ASYMMETRIC_KEY); + if (sample.length() != requiredLength + || sample[1].type() != CSSM_LIST_ELEMENT_DATUM + || sample[2].type() != CSSM_LIST_ELEMENT_DATUM + || (requiredLength == 4 && sample[3].type() != CSSM_LIST_ELEMENT_DATUM)) + CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE); + KeyHandle &handle = *sample[1].data().interpretedAs(CSSM_ERRCODE_INVALID_SAMPLE_VALUE); + // We used to be able to check the length but supporting multiple client + // architectures dishes that (sizeof(CSSM_KEY) varies due to alignment and + // field-size differences). The decoding in the transition layer should + // serve as a sufficient garbling check anyway. + if (sample[2].data().data() == NULL) + CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE); + CssmKey &key = *sample[2].data().interpretedAs(); + + if (key.header().cspGuid() == gGuidAppleCSPDL) { + // handleOrKey is a SecurityServer KeyHandle; ignore key argument + return safer_cast(*Server::key(handle)); + } else + if (sample.type() == CSSM_SAMPLE_TYPE_ASYMMETRIC_KEY) { + /* + Contents (see DefaultCredentials::unlockKey in libsecurity_keychain/defaultcreds.cpp) + + sample[0] sample type + sample[1] csp handle for master or wrapping key; is really a keyhandle + sample[2] masterKey [not used since securityd cannot interpret; use sample[1] handle instead] + sample[3] UnlockReferralRecord data, in this case the flattened symmetric key + */ + + // RefPointer Server::key(KeyHandle key) + KeyHandle keyhandle = *sample[1].data().interpretedAs(CSSM_ERRCODE_INVALID_SAMPLE_VALUE); + CssmData &flattenedKey = sample[3].data(); + RefPointer unwrappingKey = Server::key(keyhandle); + Database &db=unwrappingKey->database(); + + CssmKey rawWrappedKey; + unflattenKey(flattenedKey, rawWrappedKey); + + RefPointer masterKey; + CssmData emptyDescriptiveData; + const AccessCredentials *cred = NULL; + const AclEntryPrototype *owner = NULL; + CSSM_KEYUSE usage = CSSM_KEYUSE_ANY; + CSSM_KEYATTR_FLAGS attrs = CSSM_KEYATTR_EXTRACTABLE; //CSSM_KEYATTR_RETURN_REF | + + // Get default credentials for unwrappingKey (the one on the token) + // Copied from Statics::Statics() in libsecurity_keychain/aclclient.cpp + // Following KeyItem::getCredentials, one sees that the "operation" parameter + // e.g. "CSSM_ACL_AUTHORIZATION_DECRYPT" is ignored + Allocator &alloc = Allocator::standard(); + AutoCredentials promptCred(alloc, 3);// enable interactive prompting + + // promptCred: a credential permitting user prompt confirmations + // contains: + // a KEYCHAIN_PROMPT sample, both by itself and in a THRESHOLD + // a PROMPTED_PASSWORD sample + promptCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT); + promptCred.sample(1) = TypedList(alloc, CSSM_SAMPLE_TYPE_THRESHOLD, + new(alloc) ListElement(TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT))); + promptCred.sample(2) = TypedList(alloc, CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD, + new(alloc) ListElement(alloc, CssmData())); + + // This unwrap object is here just to provide a context + CssmClient::UnwrapKey unwrap(Server::csp(), CSSM_ALGID_NONE); //ok to lie about csp here + unwrap.mode(CSSM_ALGMODE_NONE); + unwrap.padding(CSSM_PADDING_PKCS1); + unwrap.cred(promptCred); + unwrap.add(CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT, uint32(CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7)); + Security::Context *tmpContext; + CSSM_CC_HANDLE CCHandle = unwrap.handle(); + /*CSSM_RETURN rx = */ CSSM_GetContext (CCHandle, (CSSM_CONTEXT_PTR *)&tmpContext); + + // OK, this is skanky but necessary. We overwrite fields in the context struct + + tmpContext->ContextType = CSSM_ALGCLASS_ASYMMETRIC; + tmpContext->AlgorithmType = CSSM_ALGID_RSA; + + db.unwrapKey(*tmpContext, cred, owner, unwrappingKey, NULL, usage, attrs, + rawWrappedKey, masterKey, emptyDescriptiveData); + + Allocator::standard().free(rawWrappedKey.KeyData.Data); + + return safer_cast(*masterKey).key(); + } + else + { + // not a KeyHandle reference; use key as a raw key + if (key.header().blobType() != CSSM_KEYBLOB_RAW) + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); + if (key.header().keyClass() != CSSM_KEYCLASS_SESSION_KEY) + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); + return CssmClient::Key(Server::csp(), key, true); + } +} + +void unflattenKey(const CssmData &flatKey, CssmKey &rawKey) +{ + // unflatten the raw input key naively: key header then key data + // We also convert it back to host byte order + // A CSSM_KEY is a CSSM_KEYHEADER followed by a CSSM_DATA + + // Now copy: header, then key struct, then key data + memcpy(&rawKey.KeyHeader, flatKey.Data, sizeof(CSSM_KEYHEADER)); + memcpy(&rawKey.KeyData, flatKey.Data + sizeof(CSSM_KEYHEADER), sizeof(CSSM_DATA)); + const uint32 keyDataLength = flatKey.length() - sizeof(CSSM_KEY); + rawKey.KeyData.Data = Allocator::standard().malloc(keyDataLength); + rawKey.KeyData.Length = keyDataLength; + memcpy(rawKey.KeyData.Data, flatKey.Data + sizeof(CSSM_KEY), keyDataLength); + Security::n2hi(rawKey.KeyHeader); // convert it to host byte order +} + + +// +// Verify a putative database passphrase. +// If the database is already unlocked, just check the passphrase. +// Otherwise, unlock with that passphrase and report success. +// Caller must hold the common lock. +// +bool KeychainDatabase::validatePassphrase(const CssmData &passphrase) const +{ + if (common().hasMaster()) { + // verify against known secret + return common().validatePassphrase(passphrase); + } else { + // no master secret - perform "blind" unlock to avoid actual unlock + try { + DatabaseCryptoCore test; + test.setup(mBlob, passphrase); + test.decodeCore(mBlob, NULL); + return true; + } catch (...) { + return false; + } + } +} + + +// +// Lock this database +// +void KeychainDatabase::lockDb() +{ + common().lockDb(); +} + + +// +// Given a Key for this database, encode it into a blob and return it. +// +KeyBlob *KeychainDatabase::encodeKey(const CssmKey &key, const CssmData &pubAcl, const CssmData &privAcl) +{ + bool inTheClear = false; + if((key.keyClass() == CSSM_KEYCLASS_PUBLIC_KEY) && + !(key.attribute(CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT))) { + inTheClear = true; + } + StLock _(common()); + if(!inTheClear) + makeUnlocked(); + + // tell the cryptocore to form the key blob + return common().encodeKeyCore(key, pubAcl, privAcl, inTheClear); +} + + +// +// Given a "blobbed" key for this database, decode it into its real +// key object and (re)populate its ACL. +// +void KeychainDatabase::decodeKey(KeyBlob *blob, CssmKey &key, void * &pubAcl, void * &privAcl) +{ + StLock _(common()); + + if(!blob->isClearText()) + makeUnlocked(); // we need our keys + + common().decodeKeyCore(blob, key, pubAcl, privAcl); + // memory protocol: pubAcl points into blob; privAcl was allocated + + activity(); +} + +// +// Given a KeychainKey (that implicitly belongs to another keychain), +// return it encoded using this keychain's operational secrets. +// +KeyBlob *KeychainDatabase::recodeKey(KeychainKey &oldKey) +{ + if (mRecodingSource != &oldKey.referent()) { + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); + } + oldKey.instantiateAcl(); // make sure key is decoded + CssmData publicAcl, privateAcl; + oldKey.exportBlob(publicAcl, privateAcl); + // NB: blob's memory belongs to caller, not the common + + /* + * Make sure the new key is in the same cleartext/encrypted state. + */ + bool inTheClear = false; + assert(oldKey.blob()); + if(oldKey.blob() && oldKey.blob()->isClearText()) { + /* careful....*/ + inTheClear = true; + } + KeyBlob *blob = common().encodeKeyCore(oldKey.cssmKey(), publicAcl, privateAcl, inTheClear); + oldKey.acl().allocator.free(publicAcl); + oldKey.acl().allocator.free(privateAcl); + return blob; +} + + +// +// Modify database parameters +// +void KeychainDatabase::setParameters(const DBParameters ¶ms) +{ + StLock _(common()); + makeUnlocked(); + common().mParams = params; + common().invalidateBlob(); // invalidate old blobs + activity(); // (also resets the timeout timer) + secdebug("KCdb", "%p common %p(%s) set params=(%u,%u)", + this, &common(), dbName(), params.idleTimeout, params.lockOnSleep); +} + + +// +// Retrieve database parameters +// +void KeychainDatabase::getParameters(DBParameters ¶ms) +{ + StLock _(common()); + makeUnlocked(); + params = common().mParams; + //activity(); // getting parameters does not reset the idle timer +} + + +// +// RIGHT NOW, database ACLs are attached to the database. +// This will soon move upstairs. +// +SecurityServerAcl &KeychainDatabase::acl() +{ + return *this; +} + + +// +// Intercept ACL change requests and reset blob validity +// +void KeychainDatabase::instantiateAcl() +{ + StLock _(common()); + makeUnlocked(); +} + +void KeychainDatabase::changedAcl() +{ + StLock _(common()); + version = 0; +} + + +// +// Check an incoming DbBlob for basic viability +// +void KeychainDatabase::validateBlob(const DbBlob *blob) +{ + // perform basic validation on the blob + assert(blob); + blob->validate(CSSMERR_APPLEDL_INVALID_DATABASE_BLOB); + switch (blob->version()) { +#if defined(COMPAT_OSX_10_0) + case DbBlob::version_MacOS_10_0: + break; +#endif + case DbBlob::version_MacOS_10_1: + break; + default: + CssmError::throwMe(CSSMERR_APPLEDL_INCOMPATIBLE_DATABASE_BLOB); + } +} + + +// +// Debugging support +// +#if defined(DEBUGDUMP) + +void KeychainDbCommon::dumpNode() +{ + PerSession::dumpNode(); + uint32 sig; memcpy(&sig, &mIdentifier.signature(), sizeof(sig)); + Debug::dump(" %s[%8.8x]", mIdentifier.dbName(), sig); + if (isLocked()) { + Debug::dump(" locked"); + } else { + time_t whenTime = time_t(when()); + Debug::dump(" unlocked(%24.24s/%.2g)", ctime(&whenTime), + (when() - Time::now()).seconds()); + } + Debug::dump(" params=(%u,%u)", mParams.idleTimeout, mParams.lockOnSleep); +} + +void KeychainDatabase::dumpNode() +{ + PerProcess::dumpNode(); + Debug::dump(" %s vers=%u", + mValidData ? " data" : " nodata", version); + if (mBlob) { + uint32 sig; memcpy(&sig, &mBlob->randomSignature, sizeof(sig)); + Debug::dump(" blob=%p[%8.8x]", mBlob, sig); + } else { + Debug::dump(" noblob"); + } +} + +#endif //DEBUGDUMP + + +// +// DbCommon basic features +// +KeychainDbCommon::KeychainDbCommon(Session &ssn, const DbIdentifier &id) + : LocalDbCommon(ssn), sequence(0), version(1), mIdentifier(id), + mIsLocked(true), mValidParams(false), mLoginKeychain(false) +{ + // match existing DbGlobal or create a new one + { + Server &server = Server::active(); + StLock _(server); + if (KeychainDbGlobal *dbglobal = + server.findFirst(&KeychainDbGlobal::identifier, identifier())) { + parent(*dbglobal); + secdebug("KCdb", "%p linking to existing DbGlobal %p", this, dbglobal); + } else { + // DbGlobal not present; make a new one + parent(*new KeychainDbGlobal(identifier())); + secdebug("KCdb", "%p linking to new DbGlobal %p", this, &global()); + } + + // link lifetime to the Session + session().addReference(*this); + + if (strcasestr(id.dbName(), "login.keychain") != NULL) { + mLoginKeychain = true; + } + } + + if (mLoginKeychain && !session().keybagGetState(session_keybag_loaded)) { + service_context_t context = session().get_current_service_context(); + if (service_client_kb_load(&context) == 0) { + session().keybagSetState(session_keybag_loaded); + } + } +} + +KeychainDbCommon::~KeychainDbCommon() +{ + SECURITYD_KEYCHAIN_RELEASE(this, (char*)this->dbName()); + + // explicitly unschedule ourselves + Server::active().clearTimer(this); + if (mLoginKeychain) { + session().keybagClearState(session_keybag_unlocked); + } +} + +KeychainDbGlobal &KeychainDbCommon::global() const +{ + return parent(); +} + + +void KeychainDbCommon::select() +{ this->ref(); } + +void KeychainDbCommon::unselect() +{ this->unref(); } + + + +void KeychainDbCommon::makeNewSecrets() +{ + // we already have a master key (right?) + assert(hasMaster()); + + // tell crypto core to generate the use keys + DatabaseCryptoCore::generateNewSecrets(); + + // we're now officially "unlocked"; set the timer + setUnlocked(); +} + + +// +// All unlocking activity ultimately funnels through this method. +// This unlocks a DbCommon using the secrets setup in its crypto core +// component, and performs all the housekeeping needed to represent +// the state change. +// Returns true if unlock was successful, false if it failed due to +// invalid/insufficient secrets. Throws on other errors. +// +bool KeychainDbCommon::unlockDb(DbBlob *blob, void **privateAclBlob) +{ + try { + // Tell the cryptocore to (try to) decode itself. This will fail + // in an astonishing variety of ways if the passphrase is wrong. + assert(hasMaster()); + decodeCore(blob, privateAclBlob); + secdebug("KCdb", "%p unlock successful", this); + } catch (...) { + secdebug("KCdb", "%p unlock failed", this); + return false; + } + + // get the database parameters only if we haven't got them yet + if (!mValidParams) { + mParams = blob->params; + n2hi(mParams.idleTimeout); + mValidParams = true; // sticky + } + + bool isLocked = mIsLocked; + + setUnlocked(); // mark unlocked + + if (isLocked) { + // broadcast unlock notification, but only if we were previously locked + notify(kNotificationEventUnlocked); + SECURITYD_KEYCHAIN_UNLOCK(this, (char*)this->dbName()); + } + return true; +} + +void KeychainDbCommon::setUnlocked() +{ + session().addReference(*this); // active/held + mIsLocked = false; // mark unlocked + activity(); // set timeout timer +} + + +void KeychainDbCommon::lockDb() +{ + bool lock = false; + { + StLock _(*this); + if (!isLocked()) { + DatabaseCryptoCore::invalidate(); + notify(kNotificationEventLocked); + SECURITYD_KEYCHAIN_LOCK(this, (char*)this->dbName()); + Server::active().clearTimer(this); + + mIsLocked = true; // mark locked + lock = true; + + // this call may destroy us if we have no databases anymore + session().removeReference(*this); + } + } + + if (mLoginKeychain && lock) { + service_context_t context = session().get_current_service_context(); + service_client_kb_lock(&context); + session().keybagClearState(session_keybag_unlocked); + } +} + + +DbBlob *KeychainDbCommon::encode(KeychainDatabase &db) +{ + assert(!isLocked()); // must have been unlocked by caller + + // export database ACL to blob form + CssmData pubAcl, privAcl; + db.acl().exportBlob(pubAcl, privAcl); + + // tell the cryptocore to form the blob + DbBlob form; + form.randomSignature = identifier(); + form.sequence = sequence; + form.params = mParams; + h2ni(form.params.idleTimeout); + + assert(hasMaster()); + DbBlob *blob = encodeCore(form, pubAcl, privAcl); + + // clean up and go + db.acl().allocator.free(pubAcl); + db.acl().allocator.free(privAcl); + return blob; +} + + +// +// Perform deferred lock processing for a database. +// +void KeychainDbCommon::action() +{ + secdebug("KCdb", "common %s(%p) locked by timer", dbName(), this); + lockDb(); +} + +void KeychainDbCommon::activity() +{ + if (!isLocked()) { + secdebug("KCdb", "setting DbCommon %p timer to %d", + this, int(mParams.idleTimeout)); + Server::active().setTimer(this, Time::Interval(int(mParams.idleTimeout))); + } +} + +void KeychainDbCommon::sleepProcessing() +{ + secdebug("KCdb", "common %s(%p) sleep-lock processing", dbName(), this); + StLock _(*this); + if (mParams.lockOnSleep) + lockDb(); +} + +void KeychainDbCommon::lockProcessing() +{ + lockDb(); +} + + +// +// We consider a keychain to belong to the system domain if it resides +// in /Library/Keychains. That's not exactly fool-proof, but we don't +// currently have any internal markers to interrogate. +// +bool KeychainDbCommon::belongsToSystem() const +{ + if (const char *name = this->dbName()) + return !strncmp(name, "/Library/Keychains/", 19); + return false; +} + + +// +// Keychain global objects +// +KeychainDbGlobal::KeychainDbGlobal(const DbIdentifier &id) + : mIdentifier(id) +{ +} + +KeychainDbGlobal::~KeychainDbGlobal() +{ + secdebug("KCdb", "DbGlobal %p destroyed", this); +} diff --git a/securityd/src/kcdatabase.h b/securityd/src/kcdatabase.h new file mode 100644 index 00000000..770188e3 --- /dev/null +++ b/securityd/src/kcdatabase.h @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2000-2008,2012-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@ + */ + + +// +// kcdatabase - software database container implementation. +// +// A KeychainDatabase is a software storage container, +// implemented in cooperation by the AppleCSLDP CDSA plugin and this daemon. +// +#ifndef _H_KCDATABASE +#define _H_KCDATABASE + +#include "localdatabase.h" +#include + +class KeychainDatabase; +class KeychainDbCommon; +class KeychainKey; + + +// +// We identify KeychainDatabases uniquely by a combination of +// a DLDbIdentifier and a database (blob) identifier. Equivalence +// by DbIdentifier is the criterion for parent-side merging. +// +class DbIdentifier { +public: + DbIdentifier(const DLDbIdentifier &id, DbBlob::Signature sig) + : mIdent(id), mSig(sig) { } + + const DLDbIdentifier &dlDbIdentifier() const { return mIdent; } + const DbBlob::Signature &signature() const { return mSig; } + operator const DLDbIdentifier &() const { return dlDbIdentifier(); } + operator const DbBlob::Signature &() const { return signature(); } + const char *dbName() const { return mIdent.dbName(); } + + bool operator < (const DbIdentifier &id) const // simple lexicographic + { + if (mIdent < id.mIdent) return true; + if (id.mIdent < mIdent) return false; + return mSig < id.mSig; + } + + bool operator == (const DbIdentifier &id) const + { return mIdent == id.mIdent && mSig == id.mSig; } + +private: + DLDbIdentifier mIdent; + DbBlob::Signature mSig; +}; + + +// +// A vestigal system-global database instance +// We don't (yet) use it for anything. Perhaps it should carry our ACL... +// +class KeychainDbGlobal : public PerGlobal { +public: + KeychainDbGlobal(const DbIdentifier &id); + ~KeychainDbGlobal(); + + const DbIdentifier &identifier() const { return mIdentifier; } + +private: + DbIdentifier mIdentifier; // database external identifier [const] +}; + + +// +// KeychainDatabase DbCommons +// +class KeychainDbCommon : public LocalDbCommon, + public DatabaseCryptoCore, public MachServer::Timer { +public: + KeychainDbCommon(Session &ssn, const DbIdentifier &id); + ~KeychainDbCommon(); + + KeychainDbGlobal &global() const; + + bool unlockDb(DbBlob *blob, void **privateAclBlob = NULL); + void lockDb(); // make locked (if currently unlocked) + bool isLocked() { return mIsLocked; } // lock status + void setUnlocked(); + void invalidateBlob() { version++; } + + void activity(); // reset lock timeout + + void makeNewSecrets(); + + const DbIdentifier &identifier() const {return mIdentifier; } + const DLDbIdentifier &dlDbIdent() const { return identifier(); } + const char *dbName() const { return dlDbIdent().dbName(); } + bool isLoginKeychain() const { return mLoginKeychain; } + + DbBlob *encode(KeychainDatabase &db); + + void notify(NotificationEvent event) { DbCommon::notify(event, identifier()); } + + void sleepProcessing(); + void lockProcessing(); + + bool belongsToSystem() const; + +public: + // debugging + IFDUMP(void dumpNode()); + +protected: + void action(); // timer queue action to lock keychain + + // lifetime management for our Timer personality + void select(); + void unselect(); + +public: + // all following data locked with object lock + uint32 sequence; // change sequence number + DBParameters mParams; // database parameters (arbitrated copy) + + uint32 version; // version stamp for change tracking + +private: + DbIdentifier mIdentifier; // database external identifier [const] + // all following data protected by object lock + bool mIsLocked; // logically locked + bool mValidParams; // mParams has been set + bool mLoginKeychain; +}; + + +// +// A Database object represents an Apple CSP/DL open database (DL/DB) object. +// It maintains its protected semantic state (including keys) and provides controlled +// access. +// +class KeychainDatabase : public LocalDatabase, private virtual SecurityServerAcl { + friend class KeychainDbCommon; +public: + KeychainDatabase(const DLDbIdentifier &id, const DBParameters ¶ms, Process &proc, + const AccessCredentials *cred, const AclEntryPrototype *owner); + KeychainDatabase(const DLDbIdentifier &id, const DbBlob *blob, Process &proc, + const AccessCredentials *cred); + + // keychain synchronization recode to a specfic blob: + KeychainDatabase(KeychainDatabase &src, Process &proc, DbHandle dbToClone); + virtual ~KeychainDatabase(); + + KeychainDbCommon &common() const; + const char *dbName() const; + bool transient() const; + + KeychainDbGlobal &global() const { return common().global(); } + +public: + static const int maxUnlockTryCount = 3; + +public: + const DbIdentifier &identifier() const { return common().identifier(); } + +public: + // encoding/decoding databases + DbBlob *blob(); + + void authenticate(CSSM_DB_ACCESS_TYPE mode, const AccessCredentials *cred); + void changePassphrase(const AccessCredentials *cred); + RefPointer extractMasterKey(Database &db, const AccessCredentials *cred, + const AclEntryPrototype *owner, uint32 usage, uint32 attrs); + void commitSecretsForSync(KeychainDatabase &cloneDb); + + // lock/unlock processing + void lockDb(); // unconditional lock + void unlockDb(); // full-feature unlock + void unlockDb(const CssmData &passphrase); // unlock with passphrase + + void stashDbCheck(); // check AppleKeyStore for master key + void stashDb(); // stash master key in AppleKeyStore + + bool decode(); // unlock given established master key + bool decode(const CssmData &passphrase); // set master key from PP, try unlock + + bool validatePassphrase(const CssmData &passphrase) const; // nonthrowing validation + bool isLocked() { return common().isLocked(); } // lock status + void notify(NotificationEvent event) { return common().notify(event); } + void activity() const { common().activity(); } // reset timeout clock + + // encoding/decoding keys + void decodeKey(KeyBlob *blob, CssmKey &key, void * &pubAcl, void * &privAcl); + KeyBlob *encodeKey(const CssmKey &key, const CssmData &pubAcl, const CssmData &privAcl); + KeyBlob *recodeKey(KeychainKey &oldKey); + bool validBlob() const { return mBlob && version == common().version; } + + // manage database parameters + void setParameters(const DBParameters ¶ms); + void getParameters(DBParameters ¶ms); + + // where's my (database) ACL? + SecurityServerAcl &acl(); + + AclKind aclKind() const; + Database *relatedDatabase(); + + // ACL state management hooks + void instantiateAcl(); + void changedAcl(); + + // miscellaneous utilities + static void validateBlob(const DbBlob *blob); + + // debugging + IFDUMP(void dumpNode()); + +protected: + RefPointer makeKey(const CssmKey &newKey, uint32 moreAttributes, const AclEntryPrototype *owner); + RefPointer makeKey(Database &db, const CssmKey &newKey, uint32 moreAttributes, const AclEntryPrototype *owner); + + void makeUnlocked(); // interior version of unlock() + void makeUnlocked(const AccessCredentials *cred); // like () with explicit cred + void makeUnlocked(const CssmData &passphrase); // interior version of unlock(CssmData) + + void establishOldSecrets(const AccessCredentials *creds); + void establishNewSecrets(const AccessCredentials *creds, SecurityAgent::Reason reason); + + bool interactiveUnlock(); + + CssmClient::Key keyFromCreds(const TypedList &sample, unsigned int requiredLength); + + void encode(); // (re)generate mBlob if needed + +private: + // all following data is locked by the common lock + bool mValidData; // valid ACL and params (blob decoded) + CssmAutoData mSecret; + bool mSaveSecret; + + uint32 version; // version stamp for blob validity + DbBlob *mBlob; // database blob (encoded) + + AccessCredentials *mCred; // local access credentials (always valid) + + RefPointer mRecodingSource; // keychain synchronization ONLY; should not require accessors +}; + +#endif //_H_KCDATABASE diff --git a/securityd/src/kckey.cpp b/securityd/src/kckey.cpp new file mode 100644 index 00000000..cd4cd039 --- /dev/null +++ b/securityd/src/kckey.cpp @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2000-2001,2004-2006,2008-2009 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@ + */ + + +// +// key - representation of securityd key objects +// +#include "kckey.h" +#include "server.h" +#include "database.h" +#include +#include + + +// +// Create a Key object from a database-encoded blob. +// Note that this doesn't decode the blob (yet). +// +KeychainKey::KeychainKey(Database &db, const KeyBlob *blob) + : LocalKey(db, n2h(blob->header.attributes())) +{ + // perform basic validation on the incoming blob + assert(blob); + blob->validate(CSSMERR_APPLEDL_INVALID_KEY_BLOB); + switch (blob->version()) { +#if defined(COMPAT_OSX_10_0) + case KeyBlob::version_MacOS_10_0: + break; +#endif + case KeyBlob::version_MacOS_10_1: + break; + default: + CssmError::throwMe(CSSMERR_APPLEDL_INCOMPATIBLE_KEY_BLOB); + } + + // set it up + mBlob = blob->copy(Allocator::standard()); + mValidBlob = true; + db.addReference(*this); + secdebug("SSkey", "%p (handle %#x) created from blob version %x", + this, handle(), blob->version()); +} + + +// +// Create a Key from an explicit CssmKey. +// +KeychainKey::KeychainKey(Database &db, const CssmKey &newKey, uint32 moreAttributes, + const AclEntryPrototype *owner) + : LocalKey(db, newKey, moreAttributes) +{ + assert(moreAttributes & CSSM_KEYATTR_PERMANENT); + setOwner(owner); + mBlob = NULL; + mValidBlob = false; + db.addReference(*this); +} + + +KeychainKey::~KeychainKey() +{ + Allocator::standard().free(mBlob); + secdebug("SSkey", "%p destroyed", this); +} + + +KeychainDatabase &KeychainKey::database() const +{ + return referent(); +} + + +// +// Retrieve the actual CssmKey value for the key object. +// This will decode its blob if needed (and appropriate). +// +void KeychainKey::getKey() +{ + decode(); +} + +void KeychainKey::getHeader(CssmKey::Header &hdr) +{ + assert(mValidBlob); + hdr = mBlob->header; + n2hi(hdr); // correct for endian-ness +} + + +// +// Ensure that a key is fully decoded. +// This makes the mKey key value available for use, as well as its ACL. +// Caller must hold the key object lock. +// +void KeychainKey::decode() +{ + if (!mValidKey) { + assert(mValidBlob); // must have a blob to decode + + // decode the key + void *publicAcl, *privateAcl; + CssmKey key; + database().decodeKey(mBlob, key, publicAcl, privateAcl); + mKey = CssmClient::Key(Server::csp(), key); + acl().importBlob(publicAcl, privateAcl); + // publicAcl points into the blob; privateAcl was allocated for us + Allocator::standard().free(privateAcl); + + // extract managed attribute bits + mAttributes = mKey.header().attributes() & managedAttributes; + mKey.header().clearAttribute(managedAttributes); + mKey.header().setAttribute(forcedAttributes); + + // key is valid now + mValidKey = true; + } +} + + +// +// Encode a key into a blob. +// We'll have to ask our Database to do this - we don't have its keys. +// Note that this returns memory we own and keep. +// +KeyBlob *KeychainKey::blob() +{ + if (!mValidBlob) { + assert(mValidKey); // must have valid key to encode + + // export Key ACL to blob form + CssmData pubAcl, privAcl; + acl().exportBlob(pubAcl, privAcl); + + // assemble external key form + CssmKey externalKey = mKey; + externalKey.clearAttribute(forcedAttributes); + externalKey.setAttribute(mAttributes); + + // encode the key and replace blob + KeyBlob *newBlob = database().encodeKey(externalKey, pubAcl, privAcl); + Allocator::standard().free(mBlob); + mBlob = newBlob; + mValidBlob = true; + + // clean up and go + acl().allocator.free(pubAcl); + acl().allocator.free(privAcl); + } + return mBlob; +} + +void KeychainKey::invalidateBlob() +{ + mValidBlob = false; +} + + +// +// Override ACL-related methods and events. +// Decode the key before ACL activity; invalidate the stored blob on ACL edits; +// and return the key's database as "related". +// +void KeychainKey::instantiateAcl() +{ + StLock _(*this); + decode(); +} + +void KeychainKey::changedAcl() +{ + invalidateBlob(); +} + + +// +// Intercept Key validation and double-check that the keychain is (still) unlocked +// +void KeychainKey::validate(AclAuthorization auth, const AccessCredentials *cred, + Database *relatedDatabase) +{ + if(!mBlob->isClearText()) { + /* unlock not needed for cleartext keys */ + if (KeychainDatabase *db = dynamic_cast(relatedDatabase)) + db->unlockDb(); + } + SecurityServerAcl::validate(auth, cred, relatedDatabase); + database().activity(); // upon successful validation +} + + +// +// We're a key (duh) +// +AclKind KeychainKey::aclKind() const +{ + return keyAcl; +} + + +Database *KeychainKey::relatedDatabase() +{ + return &database(); +} + +SecurityServerAcl &KeychainKey::acl() +{ + return *this; +} diff --git a/securityd/src/kckey.h b/securityd/src/kckey.h new file mode 100644 index 00000000..7983c620 --- /dev/null +++ b/securityd/src/kckey.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2000-2001,2004-2006 Apple Computer, 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@ + */ + + +// +// key - representation of SecurityServer key objects +// +#ifndef _H_KCKEY +#define _H_KCKEY + +#include "localkey.h" +#include +#include + + +class KeychainDatabase; + + +// +// A KeychainKey object represents a CssmKey that is stored in a KeychainDatabase. +// +// This is a LocalKey with deferred instantiation. A KeychainKey always exists in one of +// two states: +// (*) Decoded: The CssmKey is valid; the blob may or may not be. +// (*) Encoded: The blob is valid, the CssmKey may or may not be. +// One of (blob, CssmKey) is always valid. The process of decoding the CssmKey from the +// blob (and vice versa) requires keychain cryptography, which unlocks the keychain +// (implicitly as needed). +// Other than that, this is just a LocalKey. +// +class KeychainKey : public LocalKey, public SecurityServerAcl { +public: + KeychainKey(Database &db, const KeyBlob *blob); + KeychainKey(Database &db, const CssmKey &newKey, uint32 moreAttributes, + const AclEntryPrototype *owner = NULL); + virtual ~KeychainKey(); + + KeychainDatabase &database() const; + + // we can also yield an encoded KeyBlob + KeyBlob *blob(); + + void invalidateBlob(); + + // ACL state management hooks + void instantiateAcl(); + void changedAcl(); + Database *relatedDatabase(); + void validate(AclAuthorization auth, const AccessCredentials *cred, Database *relatedDatabase); + +public: + // SecurityServerAcl personality + AclKind aclKind() const; + + SecurityServerAcl &acl(); + +private: + void decode(); + void getKey(); + virtual void getHeader(CssmKey::Header &hdr); // get header (only) without mKey + +private: + CssmKey::Header mHeaderCache; // cached, cleaned blob header cache + + KeyBlob *mBlob; // key blob encoded by mDatabase + bool mValidBlob; // mBlob is valid key encoding +}; + + +#endif //_H_KCKEY diff --git a/securityd/src/key.cpp b/securityd/src/key.cpp new file mode 100644 index 00000000..04a92086 --- /dev/null +++ b/securityd/src/key.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2000-2004 Apple Computer, 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@ + */ + + +// +// key - representation of securityd key objects +// +#include "key.h" +#include "server.h" +#include + + +Key::Key(Database &db) + : Database::Subsidiary(db) +{ +} diff --git a/securityd/src/key.h b/securityd/src/key.h new file mode 100644 index 00000000..94c98ccf --- /dev/null +++ b/securityd/src/key.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2000-2004,2008 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@ + */ + + +// +// key - representation of securityd key objects +// +#ifndef _H_KEY +#define _H_KEY + +#include "structure.h" +#include "database.h" +#include "acls.h" +#include +#include + + +class Database; + + +// +// A Key object represents a cryptographic key known to securityd and accessed by clients +// through securityd key references (KeyHandles). A Key may be raw or reference inside securityd, +// but from outside it is always a reference key, and we hide (as best we can) the details of +// its local storage and nature. +// +// Key is a very abstract class; it defines the minimal interface that all actual securityd +// keys must provide. Actual Key subclasses are produced by (subclasses of) Databases, which +// act as Key factories. Most Database subclasses will define Key class hierarchies to track +// their internal structure, but from out here, all we know is that Databases yield Key objects +// when asked nicely, and those subclass objects implement the Key protocol. +// +// A Key can be used by multiple Connections, even at the same time. It is possible for multiple +// Key objects to represent the same underlying cryptographic secret, so don't assume a 1-1 mapping. +// +// Key is completely agnostic as to how the key is stored or maintained. +// For all you know, it might be a virtual artifact of the Key subclass. +// +// All Key subclasses support ACLs. However, different subclasses may host +// their SecurityServerAcls at different levels of the object mesh. Don't assume. +// +// Key::attribute is there for a reason. If you want to check attributes, +// use it rather than returnKey - it may be much, much faster. +// +class Key : public Database::Subsidiary, public AclSource { +public: + Key(Database &db); + + virtual const CssmData &canonicalDigest() = 0; + + Database &database() const { return referent(); } + + virtual CSSM_KEYATTR_FLAGS attributes() = 0; + bool attribute(CSSM_KEYATTR_FLAGS f) { return attributes() & f; } + + virtual void returnKey(U32HandleObject::Handle &h, CssmKey::Header &hdr) = 0; +}; + + +#endif //_H_KEY diff --git a/securityd/src/localdatabase.cpp b/securityd/src/localdatabase.cpp new file mode 100644 index 00000000..418cc311 --- /dev/null +++ b/securityd/src/localdatabase.cpp @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2004,2006,2008 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@ + */ + + +// +// localdatabase - locally implemented database using internal CSP cryptography +// +#include "localdatabase.h" +#include "agentquery.h" +#include "localkey.h" +#include "server.h" +#include "session.h" +#include +#include // for default owner ACLs +#include +#include +#include +#include +#include +#include + + +// +// Create a Database object from initial parameters (create operation) +// +LocalDatabase::LocalDatabase(Process &proc) + : Database(proc) +{ +} + + +static inline LocalKey &myKey(Key &key) +{ + return safer_cast(key); +} + + +// +// Key inquiries +// +void LocalDatabase::queryKeySizeInBits(Key &key, CssmKeySize &result) +{ + CssmClient::Key theKey(Server::csp(), myKey(key)); + result = theKey.sizeInBits(); +} + + +// +// Signatures and MACs +// +void LocalDatabase::generateSignature(const Context &context, Key &key, + CSSM_ALGORITHMS signOnlyAlgorithm, const CssmData &data, CssmData &signature) +{ + context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey()); + key.validate(CSSM_ACL_AUTHORIZATION_SIGN, context); + CssmClient::Sign signer(Server::csp(), context.algorithm(), signOnlyAlgorithm); + signer.override(context); + signer.sign(data, signature); +} + +void LocalDatabase::verifySignature(const Context &context, Key &key, + CSSM_ALGORITHMS verifyOnlyAlgorithm, const CssmData &data, const CssmData &signature) +{ + context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey()); + CssmClient::Verify verifier(Server::csp(), context.algorithm(), verifyOnlyAlgorithm); + verifier.override(context); + verifier.verify(data, signature); +} + +void LocalDatabase::generateMac(const Context &context, Key &key, + const CssmData &data, CssmData &mac) +{ + context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey()); + key.validate(CSSM_ACL_AUTHORIZATION_MAC, context); + CssmClient::GenerateMac signer(Server::csp(), context.algorithm()); + signer.override(context); + signer.sign(data, mac); +} + +void LocalDatabase::verifyMac(const Context &context, Key &key, + const CssmData &data, const CssmData &mac) +{ + context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey()); + key.validate(CSSM_ACL_AUTHORIZATION_MAC, context); + CssmClient::VerifyMac verifier(Server::csp(), context.algorithm()); + verifier.override(context); + verifier.verify(data, mac); +} + + +// +// Encryption/decryption +// +void LocalDatabase::encrypt(const Context &context, Key &key, + const CssmData &clear, CssmData &cipher) +{ + context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey()); + key.validate(CSSM_ACL_AUTHORIZATION_ENCRYPT, context); + CssmClient::Encrypt cryptor(Server::csp(), context.algorithm()); + cryptor.override(context); + CssmData remData; + size_t totalLength = cryptor.encrypt(clear, cipher, remData); + // shouldn't need remData - if an algorithm REQUIRES this, we'd have to ship it + if (remData) + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); + cipher.length(totalLength); +} + +void LocalDatabase::decrypt(const Context &context, Key &key, + const CssmData &cipher, CssmData &clear) +{ + context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey()); + key.validate(CSSM_ACL_AUTHORIZATION_DECRYPT, context); + CssmClient::Decrypt cryptor(Server::csp(), context.algorithm()); + cryptor.override(context); + CssmData remData; + size_t totalLength = cryptor.decrypt(cipher, clear, remData); + // shouldn't need remData - if an algorithm REQUIRES this, we'd have to ship it + if (remData) + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); + clear.length(totalLength); +} + + +// +// Key generation and derivation. +// Currently, we consider symmetric key generation to be fast, but +// asymmetric key generation to be (potentially) slow. +// +void LocalDatabase::generateKey(const Context &context, + const AccessCredentials *cred, const AclEntryPrototype *owner, + uint32 usage, uint32 attrs, RefPointer &newKey) +{ + // prepare a context + CssmClient::GenerateKey generate(Server::csp(), context.algorithm()); + generate.override(context); + + // generate key + // @@@ turn "none" return into reference if permanent (only) + CssmKey key; + generate(key, LocalKey::KeySpec(usage, attrs)); + + // register and return the generated key + newKey = makeKey(key, attrs & LocalKey::managedAttributes, owner); +} + +void LocalDatabase::generateKey(const Context &context, + const AccessCredentials *cred, const AclEntryPrototype *owner, + uint32 pubUsage, uint32 pubAttrs, uint32 privUsage, uint32 privAttrs, + RefPointer &publicKey, RefPointer &privateKey) +{ + // prepare a context + CssmClient::GenerateKey generate(Server::csp(), context.algorithm()); + generate.override(context); + + // this may take a while; let our server object know + Server::active().longTermActivity(); + + // generate keys + // @@@ turn "none" return into reference if permanent (only) + CssmKey pubKey, privKey; + generate(pubKey, LocalKey::KeySpec(pubUsage, pubAttrs), + privKey, LocalKey::KeySpec(privUsage, privAttrs)); + + // register and return the generated keys + publicKey = makeKey(pubKey, pubAttrs & LocalKey::managedAttributes, + (pubAttrs & CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT) ? owner : NULL); + privateKey = makeKey(privKey, privAttrs & LocalKey::managedAttributes, owner); +} + + +// +// Key wrapping and unwrapping. +// Note that the key argument (the key in the context) is optional because of the special +// case of "cleartext" (null algorithm) wrapping for import/export. +// + +void LocalDatabase::wrapKey(const Context &context, const AccessCredentials *cred, + Key *wrappingKey, Key &keyToBeWrapped, + const CssmData &descriptiveData, CssmKey &wrappedKey) +{ + keyToBeWrapped.validate(context.algorithm() == CSSM_ALGID_NONE ? + CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR : CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED, + cred); + if (wrappingKey) { + context.replace(CSSM_ATTRIBUTE_KEY, myKey(*wrappingKey).cssmKey()); + wrappingKey->validate(CSSM_ACL_AUTHORIZATION_ENCRYPT, context); + } + CssmClient::WrapKey wrap(Server::csp(), context.algorithm()); + wrap.override(context); + wrap.cred(cred); + wrap(myKey(keyToBeWrapped), wrappedKey, &descriptiveData); +} + +void LocalDatabase::unwrapKey(const Context &context, + const AccessCredentials *cred, const AclEntryPrototype *owner, + Key *wrappingKey, Key *publicKey, CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, + const CssmKey wrappedKey, RefPointer &unwrappedKey, CssmData &descriptiveData) +{ + if (wrappingKey) { + context.replace(CSSM_ATTRIBUTE_KEY, myKey(*wrappingKey).cssmKey()); + wrappingKey->validate(CSSM_ACL_AUTHORIZATION_DECRYPT, context); + } + // we are not checking access on the public key, if any + + CssmClient::UnwrapKey unwrap(Server::csp(), context.algorithm()); + unwrap.override(context); + unwrap.cred(cred); + + // the AclEntryInput will have to live until unwrap is done + AclEntryInput ownerInput; + if (owner) { + ownerInput.proto() = *owner; + unwrap.owner(ownerInput); + } + + CssmKey result; + unwrap(wrappedKey, LocalKey::KeySpec(usage, attrs), result, &descriptiveData, + publicKey ? &myKey(*publicKey).cssmKey() : NULL); + unwrappedKey = makeKey(result, attrs & LocalKey::managedAttributes, owner); +} + + +// +// Key derivation +// +void LocalDatabase::deriveKey(const Context &context, Key *key, + const AccessCredentials *cred, const AclEntryPrototype *owner, + CssmData *param, uint32 usage, uint32 attrs, RefPointer &derivedKey) +{ + if (key) { + key->validate(CSSM_ACL_AUTHORIZATION_DERIVE, context); + context.replace(CSSM_ATTRIBUTE_KEY, myKey(*key).cssmKey()); + } + CssmClient::DeriveKey derive(Server::csp(), context.algorithm(), CSSM_ALGID_NONE); + derive.override(context); + + // derive key + // @@@ turn "none" return into reference if permanent (only) + CssmKey dKey; + derive(param, LocalKey::KeySpec(usage, attrs), dKey); + + // register and return the generated key + derivedKey = makeKey(dKey, attrs & LocalKey::managedAttributes, owner); +} + + +// +// Miscellaneous CSSM functions +// +void LocalDatabase::getOutputSize(const Context &context, Key &key, uint32 inputSize, + bool encrypt, uint32 &result) +{ + // We're fudging here somewhat, since the context can be any type. + // ctx.override will fix the type, and no-one's the wiser. + context.replace(CSSM_ATTRIBUTE_KEY, myKey(key).cssmKey()); + CssmClient::Digest ctx(Server::csp(), context.algorithm()); + ctx.override(context); + result = ctx.getOutputSize(inputSize, encrypt); +} diff --git a/securityd/src/localdatabase.h b/securityd/src/localdatabase.h new file mode 100644 index 00000000..46466f09 --- /dev/null +++ b/securityd/src/localdatabase.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2004-2005 Apple Computer, 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@ + */ + + +// +// localdatabase - locally implemented database using internal CSP cryptography +// +// A LocalDatabase manages keys with a locally resident AppleCSP. +// This is an abstract class useful for subclassing. +// +#ifndef _H_LOCALDATABASE +#define _H_LOCALDATABASE + +#include "database.h" + +class LocalKey; + +class LocalDbCommon : public DbCommon { +public: + LocalDbCommon(Session &ssn) : DbCommon(ssn) { } + + Mutex &uiLock() { return mUILock; } + +private: + // Contract: callers shall not simultaneously hold mUILock and the + // DbCommon lock. StSyncLock coordinates them to uphold the contract. + Mutex mUILock; // serializes user interaction +}; + +// +// A Database object represents an Apple CSP/DL open database (DL/DB) object. +// It maintains its protected semantic state (including keys) and provides controlled +// access. +// +class LocalDatabase : public Database { +public: + LocalDatabase(Process &proc); + +public: + //void releaseKey(Key &key); + void queryKeySizeInBits(Key &key, CssmKeySize &result); + + // service calls + void generateSignature(const Context &context, Key &key, CSSM_ALGORITHMS signOnlyAlgorithm, + const CssmData &data, CssmData &signature); + void verifySignature(const Context &context, Key &key, CSSM_ALGORITHMS verifyOnlyAlgorithm, + const CssmData &data, const CssmData &signature); + void generateMac(const Context &context, Key &key, + const CssmData &data, CssmData &mac); + void verifyMac(const Context &context, Key &key, + const CssmData &data, const CssmData &mac); + + void encrypt(const Context &context, Key &key, const CssmData &clear, CssmData &cipher); + void decrypt(const Context &context, Key &key, const CssmData &cipher, CssmData &clear); + + void generateKey(const Context &context, + const AccessCredentials *cred, const AclEntryPrototype *owner, + CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, RefPointer &newKey); + void generateKey(const Context &context, + const AccessCredentials *cred, const AclEntryPrototype *owner, + CSSM_KEYUSE pubUsage, CSSM_KEYATTR_FLAGS pubAttrs, + CSSM_KEYUSE privUsage, CSSM_KEYATTR_FLAGS privAttrs, + RefPointer &publicKey, RefPointer &privateKey); + void deriveKey(const Context &context, Key *key, + const AccessCredentials *cred, const AclEntryPrototype *owner, + CssmData *param, uint32 usage, uint32 attrs, RefPointer &derivedKey); + + void wrapKey(const Context &context, const AccessCredentials *cred, + Key *wrappingKey, Key &keyToBeWrapped, + const CssmData &descriptiveData, CssmKey &wrappedKey); + void unwrapKey(const Context &context, + const AccessCredentials *cred, const AclEntryPrototype *owner, + Key *wrappingKey, Key *publicKey, CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, + const CssmKey wrappedKey, RefPointer &unwrappedKey, CssmData &descriptiveData); + + void getOutputSize(const Context &context, Key &key, uint32 inputSize, bool encrypt, uint32 &result); + +protected: + virtual RefPointer makeKey(const CssmKey &newKey, uint32 moreAttributes, + const AclEntryPrototype *owner) = 0; +}; + +#endif //_H_LOCALDATABASE diff --git a/securityd/src/localkey.cpp b/securityd/src/localkey.cpp new file mode 100644 index 00000000..7543ded3 --- /dev/null +++ b/securityd/src/localkey.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2000-2001,2004,2006-2008 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@ + */ + + +// +// localkey - Key objects that store a local CSSM key object +// +#include "localkey.h" +#include "server.h" +#include "database.h" +#include + + +// +// Create a Key from an explicit CssmKey. +// +LocalKey::LocalKey(Database &db, const CssmKey &newKey, CSSM_KEYATTR_FLAGS moreAttributes) + : Key(db), mDigest(Server::csp().allocator()) +{ + mValidKey = true; + setup(newKey, moreAttributes); + secdebug("SSkey", "%p (handle %#x) created from key alg=%u use=0x%x attr=0x%x db=%p", + this, handle(), mKey.header().algorithm(), mKey.header().usage(), mAttributes, &db); +} + + +LocalKey::LocalKey(Database &db, CSSM_KEYATTR_FLAGS attributes) + : Key(db), mValidKey(false), mAttributes(attributes), mDigest(Server::csp().allocator()) +{ +} + + +// +// Set up the CssmKey part of this Key according to instructions. +// +void LocalKey::setup(const CssmKey &newKey, CSSM_KEYATTR_FLAGS moreAttributes) +{ + mKey = CssmClient::Key(Server::csp(), newKey, false); + CssmKey::Header &header = mKey->header(); + + // copy key header + header = newKey.header(); + mAttributes = (header.attributes() & ~forcedAttributes) | moreAttributes; + + // apply initial values of derived attributes (these are all in managedAttributes) + if (!(mAttributes & CSSM_KEYATTR_EXTRACTABLE)) + mAttributes |= CSSM_KEYATTR_NEVER_EXTRACTABLE; + if (mAttributes & CSSM_KEYATTR_SENSITIVE) + mAttributes |= CSSM_KEYATTR_ALWAYS_SENSITIVE; + + // verify internal/external attribute separation + assert((header.attributes() & managedAttributes) == forcedAttributes); +} + + +LocalKey::~LocalKey() +{ + secdebug("SSkey", "%p destroyed", this); +} + + +void LocalKey::setOwner(const AclEntryPrototype *owner) +{ + // establish initial ACL; reinterpret empty (null-list) owner as NULL for resilence's sake + if (owner && !owner->subject().empty()) + acl().cssmSetInitial(*owner); // specified + else + acl().cssmSetInitial(new AnyAclSubject()); // defaulted +} + + +LocalDatabase &LocalKey::database() const +{ + return referent(); +} + + +// +// Retrieve the actual CssmKey value for the key object. +// This will decode its blob if needed (and appropriate). +// +CssmClient::Key LocalKey::keyValue() +{ + StLock _(*this); + if (!mValidKey) { + getKey(); + mValidKey = true; + } + return mKey; +} + + +// +// Return external key attributees +// +CSSM_KEYATTR_FLAGS LocalKey::attributes() +{ + return mAttributes; +} + + +// +// Return a key's handle and header in external form +// +void LocalKey::returnKey(U32HandleObject::Handle &h, CssmKey::Header &hdr) +{ + StLock _(*this); + + // return handle + h = this->handle(); + + // obtain the key header, from the valid key or the blob if no valid key + if (mValidKey) { + hdr = mKey.header(); + } else { + getHeader(hdr); + } + + // adjust for external attributes + hdr.clearAttribute(forcedAttributes); + hdr.setAttribute(mAttributes); +} + + +// +// Generate the canonical key digest. +// This is defined by a CSP feature that we invoke here. +// +const CssmData &LocalKey::canonicalDigest() +{ + StLock _(*this); + if (!mDigest) { + CssmClient::PassThrough ctx(Server::csp()); + ctx.key(keyValue()); + CssmData *digest = NULL; + ctx(CSSM_APPLECSP_KEYDIGEST, (const void *)NULL, &digest); + assert(digest); + mDigest.set(*digest); // takes ownership of digest data + Server::csp().allocator().free(digest); // the CssmData itself + } + return mDigest.get(); +} + + +// +// Default getKey/getHeader calls - should never be called +// +void LocalKey::getKey() +{ + assert(false); +} + +void LocalKey::getHeader(CssmKey::Header &) +{ + assert(false); +} + + +// +// Form a KeySpec with checking and masking +// +LocalKey::KeySpec::KeySpec(CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs) + : CssmClient::KeySpec(usage, (attrs & ~managedAttributes) | forcedAttributes) +{ + if (attrs & generatedAttributes) + CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); +} + +LocalKey::KeySpec::KeySpec(CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, const CssmData &label) + : CssmClient::KeySpec(usage, (attrs & ~managedAttributes) | forcedAttributes, label) +{ + if (attrs & generatedAttributes) + CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); +} diff --git a/securityd/src/localkey.h b/securityd/src/localkey.h new file mode 100644 index 00000000..59003e5b --- /dev/null +++ b/securityd/src/localkey.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2000-2001,2004,2008 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@ + */ + + +// +// localkey - Key objects that store a local CSSM key object +// +#ifndef _H_LOCALKEY +#define _H_LOCALKEY + +#include "key.h" +#include + + +class LocalDatabase; + + +// +// A LocalKey object represents a CssmKey known to securityd. This subclass of Key is the +// parent of all Key objects that rely on local storage of the raw key matter. Cryptographic +// operations are performed by a local CSP within securityd's address space. +// +// LocalKeys are paired with LocalDatabases; LocalKey subclasses must be produced by, and must +// belong to, subclasses of LocalDatabase. +// +// LocalKeys implement their ACLs with a local evaluation machine that does not rely on an outside +// agent for evaluation. It is still possible for different subclasses of LocalDatabase to host +// their ObjectAcl instances at different globality layers. +// +// Since the local CSP refuses to deal with storage-related key attributes, we split the keys's +// CSSM_KEY_ATTRBITS into two parts: +// (*) The KeyHeader.attributes() contain attributes as seen by the local CSP. +// (*) The local mAttributes member contains attributes as seen by the client. +// The two are related by a simple formula: take the external attributes, remove the global-storage +// bits, add the EXTRACTABLE bit (so securityd itself can get at the key matter), and use that in +// the CssmKey. The reverse transition is done on the way out. A local subclass of KeySpec is used +// to make this more consistent. Just follow the pattern. +// +class LocalKey : public Key { +public: + LocalKey(Database &db, const CssmKey &newKey, uint32 moreAttributes); + virtual ~LocalKey(); + + LocalDatabase &database() const; + + // yield the decoded internal key -- internal attributes + CssmClient::Key key() { return keyValue(); } + const CssmKey &cssmKey() { return keyValue(); } + operator CssmClient::Key () { return keyValue(); } + operator const CssmKey &() { return keyValue(); } + operator const CSSM_KEY & () { return keyValue(); } + + // yield the approximate external key header -- external attributes + void returnKey(U32HandleObject::Handle &h, CssmKey::Header &hdr); + + // generate the canonical key digest + const CssmData &canonicalDigest(); + + CSSM_KEYATTR_FLAGS attributes(); + +public: + // key attributes that should not be passed on to the CSP + static const CSSM_KEYATTR_FLAGS managedAttributes = KeyBlob::managedAttributes; + // these attributes are "forced on" in internal keys (but not always in external attributes) + static const CSSM_KEYATTR_FLAGS forcedAttributes = KeyBlob::forcedAttributes; + // these attributes are internally generated, and invalid on input + static const CSSM_KEYATTR_FLAGS generatedAttributes = + CSSM_KEYATTR_ALWAYS_SENSITIVE | CSSM_KEYATTR_NEVER_EXTRACTABLE; + + // a version of KeySpec that self-checks and masks for CSP operation + class KeySpec : public CssmClient::KeySpec { + public: + KeySpec(CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs); + KeySpec(CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, const CssmData &label); + }; + +private: + void setup(const CssmKey &newKey, CSSM_KEYATTR_FLAGS attrs); + CssmClient::Key keyValue(); + +protected: + LocalKey(Database &db, CSSM_KEYATTR_FLAGS attributes); + void setOwner(const AclEntryPrototype *owner); + + virtual void getKey(); // decode into mKey or throw + virtual void getHeader(CssmKey::Header &hdr); // get header (only) without mKey + +protected: + bool mValidKey; // CssmKey form is valid + CssmClient::Key mKey; // clear form CssmKey (attributes modified) + + CSSM_KEYATTR_FLAGS mAttributes; // full attributes (external form) + CssmAutoData mDigest; // computed key digest (cached) +}; + + +#endif //_H_LOCALKEY diff --git a/securityd/src/main.cpp b/securityd/src/main.cpp new file mode 100644 index 00000000..56097886 --- /dev/null +++ b/securityd/src/main.cpp @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2000-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@ + */ + + +// +// securityd - Apple security services daemon. +// +#include + +#include "server.h" +#include "entropy.h" +#include "authority.h" +#include "session.h" +#include "notifications.h" +#include "pcscmonitor.h" +#include "auditevents.h" +#include "self.h" + +#include +#include +#include + +#include + +#include +#include +#include +#include + +// ACL subject types (their makers are instantiated here) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "acl_keychain.h" + + +// +// Local functions of the main program driver +// +static void usage(const char *me) __attribute__((noreturn)); +static void handleSignals(int sig); +static PCSCMonitor::ServiceLevel scOptions(const char *optionString); + + +static Port gMainServerPort; +PCSCMonitor *gPCSC; + + +// +// Main driver +// +int main(int argc, char *argv[]) +{ + // clear the umask - we know what we're doing + secdebug("SS", "starting umask was 0%o", ::umask(0)); + ::umask(0); + + // tell the keychain (client) layer to turn off the server interface + SecKeychainSetServerMode(); + + // program arguments (preset to defaults) + bool debugMode = false; + const char *bootstrapName = NULL; + const char* messagingName = SECURITY_MESSAGES_NAME; + bool doFork = false; + bool reExecute = false; + int workerTimeout = 0; + int maxThreads = 0; + bool waitForClients = true; + bool mdsIsInstalled = false; + const char *authorizationConfig = "/etc/authorization"; + const char *tokenCacheDir = "/var/db/TokenCache"; + const char *entropyFile = "/var/db/SystemEntropyCache"; + const char *equivDbFile = EQUIVALENCEDBPATH; + const char *smartCardOptions = getenv("SMARTCARDS"); + uint32_t keychainAclDefault = CSSM_ACL_KEYCHAIN_PROMPT_INVALID | CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED; + unsigned int verbose = 0; + + // check for the Installation-DVD environment and modify some default arguments if found + if (access("/etc/rc.cdrom", F_OK) == 0) { // /etc/rc.cdrom exists + SECURITYD_INSTALLMODE(); + smartCardOptions = "off"; // needs writable directories that aren't + } + + // parse command line arguments + extern char *optarg; + extern int optind; + int arg; + while ((arg = getopt(argc, argv, "a:c:de:E:imN:s:t:T:uvWX")) != -1) { + switch (arg) { + case 'a': + authorizationConfig = optarg; + break; + case 'c': + tokenCacheDir = optarg; + break; + case 'd': + debugMode = true; + break; + case 'e': + equivDbFile = optarg; + break; + case 'E': + entropyFile = optarg; + break; + case 'i': + keychainAclDefault &= ~CSSM_ACL_KEYCHAIN_PROMPT_INVALID; + break; + case 'm': + mdsIsInstalled = true; + break; + case 'N': + bootstrapName = optarg; + break; + case 's': + smartCardOptions = optarg; + break; + case 't': + if ((maxThreads = atoi(optarg)) < 0) + maxThreads = 0; + break; + case 'T': + if ((workerTimeout = atoi(optarg)) < 0) + workerTimeout = 0; + break; + case 'W': + waitForClients = false; + break; + case 'u': + keychainAclDefault &= ~CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED; + break; + case 'v': + verbose++; + break; + case 'X': + doFork = true; + reExecute = true; + break; + default: + usage(argv[0]); + } + } + + // take no non-option arguments + if (optind < argc) + usage(argv[0]); + + // figure out the bootstrap name + if (!bootstrapName) { + bootstrapName = getenv(SECURITYSERVER_BOOTSTRAP_ENV); + if (!bootstrapName) + { + bootstrapName = SECURITYSERVER_BOOTSTRAP_NAME; + } + else + { + messagingName = bootstrapName; + } + } + else + { + messagingName = bootstrapName; + } + + // configure logging first + if (debugMode) { + Syslog::open(bootstrapName, LOG_AUTHPRIV, LOG_PERROR); + Syslog::notice("%s started in debug mode", argv[0]); + } else { + Syslog::open(bootstrapName, LOG_AUTHPRIV, LOG_CONS); + } + + // if we're not running as root in production mode, fail + // in debug mode, issue a warning + if (uid_t uid = getuid()) { +#if defined(NDEBUG) + Syslog::alert("Tried to run securityd as user %d: aborted", uid); + fprintf(stderr, "You are not allowed to run securityd\n"); + exit(1); +#else + fprintf(stderr, "securityd is unprivileged (uid=%d); some features may not work.\n", uid); +#endif //NDEBUG + } + + // turn into a properly diabolical daemon unless debugMode is on + if (!debugMode && getppid() != 1) { + if (!Daemon::incarnate(doFork)) + exit(1); // can't daemonize + + if (reExecute && !Daemon::executeSelf(argv)) + exit(1); // can't self-execute + } + + // arm signal handlers; code below may generate signals we want to see + if (signal(SIGCHLD, handleSignals) == SIG_ERR + || signal(SIGINT, handleSignals) == SIG_ERR + || signal(SIGTERM, handleSignals) == SIG_ERR + || signal(SIGPIPE, handleSignals) == SIG_ERR +#if !defined(NDEBUG) + || signal(SIGUSR1, handleSignals) == SIG_ERR +#endif //NDEBUG + || signal(SIGUSR2, handleSignals) == SIG_ERR) { + perror("signal"); + exit(1); + } + + // create an Authorization engine + Authority authority(authorizationConfig); + + // introduce all supported ACL subject types + new AnyAclSubject::Maker(); + new PasswordAclSubject::Maker(); + new ProtectedPasswordAclSubject::Maker(); + new PromptedAclSubject::Maker(); + new ThresholdAclSubject::Maker(); + new CommentAclSubject::Maker(); + new ProcessAclSubject::Maker(); + new CodeSignatureAclSubject::Maker(); + new KeychainPromptAclSubject::Maker(keychainAclDefault); + new PreAuthorizationAcls::OriginMaker(); + new PreAuthorizationAcls::SourceMaker(); + + // establish the code equivalents database + CodeSignatures codeSignatures(equivDbFile); + + // create the main server object and register it + Server server(authority, codeSignatures, bootstrapName); + + // Remember the primary service port to send signal events to + gMainServerPort = server.primaryServicePort(); + + // set server configuration from arguments, if specified + if (workerTimeout) + server.timeout(workerTimeout); + if (maxThreads) + server.maxThreads(maxThreads); + server.floatingThread(true); + server.waitForClients(waitForClients); + server.verbosity(verbose); + + // add the RNG seed timer +# if defined(NDEBUG) + EntropyManager entropy(server, entropyFile); +# else + if (getuid() == 0) new EntropyManager(server, entropyFile); +# endif + + // create a smartcard monitor to manage external token devices + gPCSC = new PCSCMonitor(server, tokenCacheDir, scOptions(smartCardOptions)); + + // create the RootSession object (if -d, give it graphics and tty attributes) + RootSession rootSession(debugMode ? (sessionHasGraphicAccess | sessionHasTTY) : 0, server); + + // create a monitor thread to watch for audit session events + AuditMonitor audits(gMainServerPort); + audits.run(); + + // install MDS (if needed) and initialize the local CSSM + server.loadCssm(mdsIsInstalled); + + // create the shared memory notification hub + new SharedMemoryListener(messagingName, kSharedMemoryPoolSize); + + // okay, we're ready to roll + SECURITYD_INITIALIZED((char*)bootstrapName); + Syslog::notice("Entering service"); + + // go + server.run(); + + // fell out of runloop (should not happen) + Syslog::alert("Aborting"); + return 1; +} + + +// +// Issue usage message and die +// +static void usage(const char *me) +{ + fprintf(stderr, "Usage: %s [-dwX]" + "\n\t[-a authConfigFile] Authorization configuration file" + "\n\t[-c tokencache] smartcard token cache directory" + "\n\t[-e equivDatabase] path to code equivalence database" + "\n\t[-N serviceName] MACH service name" + "\n\t[-s off|on|conservative|aggressive] smartcard operation level" + "\n\t[-t maxthreads] [-T threadTimeout] server thread control" + "\n", me); + exit(2); +} + + +// +// Translate strings (e.g. "conservative") into PCSCMonitor service levels +// +static PCSCMonitor::ServiceLevel scOptions(const char *optionString) +{ + if (optionString) + if (!strcmp(optionString, "off")) + return PCSCMonitor::forcedOff; + else if (!strcmp(optionString, "on")) + return PCSCMonitor::externalDaemon; + else if (!strcmp(optionString, "conservative")) + return PCSCMonitor::externalDaemon; + else if (!strcmp(optionString, "aggressive")) + return PCSCMonitor::externalDaemon; + else if (!strcmp(optionString, "external")) + return PCSCMonitor::externalDaemon; + else + usage("securityd"); + else + return PCSCMonitor::externalDaemon; +} + + +// +// Handle signals. +// We send ourselves a message (through the "self" service), so actual +// actions happen on the normal event loop path. Note that another thread +// may be picking up the message immediately. +// +static void handleSignals(int sig) +{ + SECURITYD_SIGNAL_RECEIVED(sig); + if (kern_return_t rc = self_client_handleSignal(gMainServerPort, mach_task_self(), sig)) + Syslog::error("self-send failed (mach error %d)", rc); +} diff --git a/securityd/src/notifications.cpp b/securityd/src/notifications.cpp new file mode 100644 index 00000000..0a82c885 --- /dev/null +++ b/securityd/src/notifications.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2000-2004,2006,2008 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@ + */ + + +// +// notifications - handling of securityd-gated notification messages +// +#include + +#include "notifications.h" +#include "server.h" +#include "connection.h" +#include + + +Listener::ListenerMap& Listener::listeners = *(new Listener::ListenerMap); +Mutex Listener::setLock(Mutex::recursive); + + +// +// Listener basics +// +Listener::Listener(NotificationDomain dom, NotificationMask evs, mach_port_t port) + : domain(dom), events(evs) +{ + assert(events); // what's the point? + + // register in listener set + StLock _(setLock); + listeners.insert(ListenerMap::value_type(port, this)); + + secdebug("notify", "%p created for domain 0x%x events 0x%x port %d", + this, dom, evs, port); +} + +Listener::~Listener() +{ + secdebug("notify", "%p destroyed", this); +} + + +// +// Send a notification to all registered listeners +// +void Listener::notify(NotificationDomain domain, + NotificationEvent event, const CssmData &data) +{ + RefPointer message = new Notification(domain, event, 0, data); + StLock _(setLock); + sendNotification(message); +} + +void Listener::notify(NotificationDomain domain, + NotificationEvent event, uint32 sequence, const CssmData &data) +{ + Connection ¤t = Server::active().connection(); + RefPointer message = new Notification(domain, event, sequence, data); + if (current.inSequence(message)) { + StLock _(setLock); + sendNotification(message); + while (RefPointer next = current.popNotification()) + sendNotification(next); + } +} + +void Listener::sendNotification(Notification *message) +{ + for (ListenerMap::const_iterator it = listeners.begin(); + it != listeners.end(); it++) { + Listener *listener = it->second; + if (listener->domain == kNotificationDomainAll || (message->domain == listener->domain && listener->wants(message->event))) + listener->notifyMe(message); + } +} + + +// +// Handle a port death or deallocation by removing all Listeners using that port. +// Returns true iff we had one. +// +bool Listener::remove(Port port) +{ + typedef ListenerMap::iterator Iterator; + StLock _(setLock); + pair range = listeners.equal_range(port); + if (range.first == range.second) + return false; // not one of ours + + assert(range.first != listeners.end()); + secdebug("notify", "remove port %d", port.port()); +#if !defined(NDEBUG) + for (Iterator it = range.first; it != range.second; it++) { + assert(it->first == port); + secdebug("notify", "%p listener removed", it->second.get()); + } +#endif //NDEBUG + listeners.erase(range.first, range.second); + port.destroy(); + return true; // got it +} + + +// +// Notification message objects +// +Listener::Notification::Notification(NotificationDomain inDomain, + NotificationEvent inEvent, uint32 seq, const CssmData &inData) + : domain(inDomain), event(inEvent), sequence(seq), data(Allocator::standard(), inData) +{ + secdebug("notify", "%p notification created domain 0x%lx event %ld seq %ld", + this, domain, event, sequence); +} + +Listener::Notification::~Notification() +{ + secdebug("notify", "%p notification done domain 0x%lx event %ld seq %ld", + this, domain, event, sequence); +} + + +// +// Jitter buffering +// +bool Listener::JitterBuffer::inSequence(Notification *message) +{ + if (message->sequence == mNotifyLast + 1) { // next in sequence + mNotifyLast++; // record next sequence + return true; // go ahead + } else { + secdebug("notify-jit", "%p out of sequence (last %ld got %ld); buffering", + message, mNotifyLast, message->sequence); + mBuffer[message->sequence] = message; // save for later + return false; // hold your fire + } +} + +RefPointer Listener::JitterBuffer::popNotification() +{ + JBuffer::iterator it = mBuffer.find(mNotifyLast + 1); // have next message? + if (it == mBuffer.end()) + return NULL; // nothing here + else { + RefPointer result = it->second; // save value + mBuffer.erase(it); // remove from buffer + secdebug("notify-jit", "%p retrieved from jitter buffer", result.get()); + return result; // return it + } +} + +/* + * Shared memory listener + */ + + +SharedMemoryListener::SharedMemoryListener(const char* segmentName, SegmentOffsetType segmentSize) : + Listener (kNotificationDomainAll, kNotificationAllEvents), + SharedMemoryServer (segmentName, segmentSize), + mActive (false) +{ + if (segmentName == NULL) + { + secdebug("notify", "Attempted to start securityd with a NULL segmentName"); + exit(1); + } +} + +SharedMemoryListener::~SharedMemoryListener () +{ +} + +const double kServerWait = 0.005; // time in seconds before clients will be notified that data is available + +void SharedMemoryListener::notifyMe(Notification* notification) +{ + const void* data = notification->data.data(); + UInt32 length = notification->data.length(); + WriteMessage (notification->domain, notification->event, data, length); + + if (!mActive) + { + Server::active().setTimer (this, Time::Interval(kServerWait)); + mActive = true; + } +} + +void SharedMemoryListener::action () +{ + secdebug("notify", "Posted notification to clients."); + notify_post (mSegmentName.c_str ()); + mActive = false; +} diff --git a/securityd/src/notifications.h b/securityd/src/notifications.h new file mode 100644 index 00000000..1d13a322 --- /dev/null +++ b/securityd/src/notifications.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2000-2004,2006-2008 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@ + */ + + +// +// notifications - handling of securityd-gated notification messages +// +#ifndef _H_NOTIFICATIONS +#define _H_NOTIFICATIONS + +#include +#include +#include +#include +#include +#include + +#include "SharedMemoryServer.h" + +using MachPlusPlus::Port; +using MachPlusPlus::MachServer; +using SecurityServer::NotificationDomain; +using SecurityServer::NotificationEvent; +using SecurityServer::NotificationMask; + +class SharedMemoryListener; + +// +// A registered receiver of notifications. +// This is an abstract class; you must subclass to define notifyMe(). +// +// All Listeners in existence are collected in an internal map of ports to +// Listener*s, which makes them eligible to have events delivered to them via +// their notifyMe() method. There are (only) two viable lifetime management +// strategies for your Listener subclass: +// (1) Eternal: don't ever destroy your Listener. All is well. By convention, +// such Listeners use the null port. +// (2) Port-based: To get rid of your Listeners, call Listener::remove(port), +// which will delete(!) all Listeners constructed with that port. +// Except for the remove() functionality, Listener does not interpret the port. +// +// If you need another Listener lifetime management strategy, you will probably +// have to change things around here. +// +class Listener: public RefCount { +public: + Listener(NotificationDomain domain, NotificationMask events, + mach_port_t port = MACH_PORT_NULL); + virtual ~Listener(); + + // inject an event into the notification system + static void notify(NotificationDomain domain, + NotificationEvent event, const CssmData &data); + static void notify(NotificationDomain domain, + NotificationEvent event, uint32 sequence, const CssmData &data); + static bool remove(Port port); + + const NotificationDomain domain; + const NotificationMask events; + + bool wants(NotificationEvent event) + { return (1 << event) & events; } + +protected: + class Notification : public RefCount { + public: + Notification(NotificationDomain domain, NotificationEvent event, + uint32 seq, const CssmData &data); + virtual ~Notification(); + + const NotificationDomain domain; + const NotificationEvent event; + const uint32 sequence; + const CssmAutoData data; + + size_t size() const + { return data.length(); } //@@@ add "slop" here for heuristic? + }; + + virtual void notifyMe(Notification *message) = 0; + +public: + class JitterBuffer { + public: + JitterBuffer() : mNotifyLast(0) { } + + bool inSequence(Notification *message); + RefPointer popNotification(); + + private: + uint32 mNotifyLast; // last notification seq processed + typedef std::map > JBuffer; + JBuffer mBuffer; // early messages buffer + }; + +private: + static void sendNotification(Notification *message); + +private: + typedef multimap > ListenerMap; + static ListenerMap& listeners; + static Mutex setLock; +}; + + + +class SharedMemoryListener : public Listener, public SharedMemoryServer, public Security::MachPlusPlus::MachServer::Timer +{ +protected: + virtual void action (); + virtual void notifyMe(Notification *message); + + bool mActive; + +public: + SharedMemoryListener (const char* serverName, u_int32_t serverSize); + virtual ~SharedMemoryListener (); +}; + +#endif diff --git a/securityd/src/pcscmonitor.cpp b/securityd/src/pcscmonitor.cpp new file mode 100644 index 00000000..caeea7c9 --- /dev/null +++ b/securityd/src/pcscmonitor.cpp @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2004-2008,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +// +// pcscmonitor - use PCSC to monitor smartcard reader/card state for securityd +// +// PCSCMonitor is the "glue" between PCSC and the securityd objects representing +// smartcard-related things. Its job is to manage the daemon and translate real-world +// events (such as card and device insertions) into the securityd object web. +// +#include "pcscmonitor.h" +#include + +// +// Construct a PCSCMonitor. +// We strongly assume there's only one of us around here. +// +// Note that this constructor may well run before the server loop has started. +// Don't call anything here that requires an active server loop (like Server::active()). +// In fact, you should push all the hard work into a timer, so as not to hold up the +// general startup process. +// +PCSCMonitor::PCSCMonitor(Server &server, const char* pathToCache, ServiceLevel level) + : Listener(kNotificationDomainPCSC, SecurityServer::kNotificationAllEvents), + server(server), + mServiceLevel(level), + mCachePath(pathToCache), + mTokenCache(NULL) +{ + // do all the smartcard-related work once the event loop has started + server.setTimer(this, Time::now()); // ASAP +} + +PCSCMonitor::Watcher::Watcher(Server &server, TokenCache &tokenCache, ReaderMap& readers) + : mServer(server), mTokenCache(tokenCache), mReaders(readers) +{} + +// +// Poll PCSC for smartcard status. +// We are enumerating all readers on each call. +// +void PCSCMonitor::Watcher::action() +{ + // Associate this watching thread with the server, so that it is possible to call + // Server::active() from inside code called from this thread. + mServer.associateThread(); + + try { + // open PCSC session + mSession.open(); + + // Array of states, userData() points to associated Reader instance, + // name points to string held by Reader::name attribute. + vector states; + + for (;;) { + // enumerate all current readers. + vector names; + mSession.listReaders(names); + secdebug("pcsc", "%ld reader(s) in system", names.size()); + + // Update PCSC states array with new/removed readers. + for (vector::iterator stateIt = states.begin(); stateIt != states.end(); ) { + Reader *reader = stateIt->userData(); + vector::iterator nameIt = find(names.begin(), names.end(), reader->name()); + if (nameIt == names.end()) { + // Reader was removed from the system. + if (Reader *reader = stateIt->userData()) { + secdebug("pcsc", "removing reader %s", stateIt->name()); + Syslog::notice("Token reader %s removed from system", stateIt->name()); + reader->kill(); // prepare to die + mReaders.erase(reader->name()); // remove from reader map + stateIt = states.erase(stateIt); + } + } else { + // This reader is already tracked, copy its signalled state into the last known state. + stateIt->lastKnown(stateIt->state()); + names.erase(nameIt); + stateIt++; + } + } + + // Add states for remaining (newly appeared) reader names. + for (vector::iterator it = names.begin(); it != names.end(); ++it) { + PCSC::ReaderState state; + state.clearPod(); + state.set(it->c_str()); + states.push_back(state); + } + + // Now ask PCSC for status changes, and wait for them. + mSession.statusChange(states, INFINITE); + + // Go through the states and notify changed readers. + for (vector::iterator stateIt = states.begin(); stateIt != states.end(); stateIt++) { + Reader *reader = stateIt->userData(); + if (!reader) { + reader = new Reader(mTokenCache, *stateIt); + stateIt->userData() = reader; + stateIt->name(reader->name().c_str()); + mReaders.insert(make_pair(reader->name(), reader)); + Syslog::notice("Token reader %s inserted into system", stateIt->name()); + } + + // if PCSC flags a change, notify the Reader + if (stateIt->changed()) { + Syslog::notice("reader %s: state changed %lu -> %lu", stateIt->name(), stateIt->lastKnown(), stateIt->state()); + try { + reader->update(*stateIt); + } catch (const exception &e) { + Syslog::notice("Token in reader %s: %s", stateIt->name(), e.what()); + } + } + } + + //wakeup mach server to process notifications + ClientSession session(Allocator::standard(), Allocator::standard()); + session.postNotification(kNotificationDomainPCSC, kNotificationPCSCStateChange, CssmData()); + } + } catch (const exception &e) { + Syslog::error("An error '%s' occured while tracking token readers", e.what()); + } +} + +TokenCache& PCSCMonitor::tokenCache() +{ + if (mTokenCache == NULL) + mTokenCache = new TokenCache(mCachePath.c_str()); + return *mTokenCache; +} + +// +// Event notifier. +// These events are sent by pcscd for our (sole) benefit. +// +void PCSCMonitor::notifyMe(Notification *message) +{ +} + +// +// Timer action. Perform the initial PCSC subsystem initialization. +// This runs (shortly) after securityd is fully functional and the +// server loop has started. +// +void PCSCMonitor::action() +{ + switch (mServiceLevel) { + case forcedOff: + secdebug("pcsc", "smartcard operation is FORCED OFF"); + break; + + case externalDaemon: + secdebug("pcsc", "using PCSC"); + startSoftTokens(); + + // Start PCSC reader watching thread. + (new Watcher(server, tokenCache(), mReaders))->run(); + break; + } +} + + +// +// Software token support +// +void PCSCMonitor::startSoftTokens() +{ + // scan for new ones + CodeRepository candidates("Security/tokend", ".tokend", "TOKENDAEMONPATH", false); + candidates.update(); + for (CodeRepository::iterator it = candidates.begin(); it != candidates.end(); ++it) { + if (CFTypeRef type = (*it)->infoPlistItem("TokendType")) + if (CFEqual(type, CFSTR("software"))) + loadSoftToken(*it); + } +} + +void PCSCMonitor::loadSoftToken(Bundle *tokendBundle) +{ + try { + string bundleName = tokendBundle->identifier(); + + // prepare a virtual reader, removing any existing one (this would kill a previous tokend) + assert(mReaders.find(bundleName) == mReaders.end()); // not already present + RefPointer reader = new Reader(tokenCache(), bundleName); + + // now launch the tokend + RefPointer tokend = new TokenDaemon(tokendBundle, + reader->name(), reader->pcscState(), reader->cache); + + if (tokend->state() == ServerChild::dead) { // ah well, this one's no good + secdebug("pcsc", "softtoken %s tokend launch failed", bundleName.c_str()); + Syslog::notice("Software token %s failed to run", tokendBundle->canonicalPath().c_str()); + return; + } + + // probe the (single) tokend + if (!tokend->probe()) { // non comprende... + secdebug("pcsc", "softtoken %s probe failed", bundleName.c_str()); + Syslog::notice("Software token %s refused operation", tokendBundle->canonicalPath().c_str()); + return; + } + + // okay, this seems to work. Set it up + mReaders.insert(make_pair(reader->name(), reader)); + reader->insertToken(tokend); + Syslog::notice("Software token %s activated", bundleName.c_str()); + } catch (...) { + secdebug("pcsc", "exception loading softtoken %s - continuing", tokendBundle->identifier().c_str()); + } +} diff --git a/securityd/src/pcscmonitor.h b/securityd/src/pcscmonitor.h new file mode 100644 index 00000000..7bc00e2b --- /dev/null +++ b/securityd/src/pcscmonitor.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2004-2008,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +// +// pcscmonitor - use PCSC to monitor smartcard reader/card state for securityd +// +#ifndef _H_PCSCMONITOR +#define _H_PCSCMONITOR + +#include "server.h" +#include "tokencache.h" +#include "reader.h" +#include "token.h" +#include +#include +#include + + +// +// A PCSCMonitor uses PCSC to monitor the state of smartcard readers and +// tokens (cards) in the system, and dispatches messages and events to the +// various related players in securityd. There should be at most one of these +// objects active within securityd. +// +class PCSCMonitor : private Listener, private MachServer::Timer { +public: + enum ServiceLevel { + forcedOff, // no service under any circumstances + externalDaemon // use externally launched daemon if present (do not manage pcscd) + }; + + PCSCMonitor(Server &server, const char* pathToCache, ServiceLevel level = externalDaemon); + +protected: + Server &server; + TokenCache& tokenCache(); + +protected: + // Listener + void notifyMe(Notification *message); + + // MachServer::Timer + void action(); + +public: //@@@@ + void startSoftTokens(); + void loadSoftToken(Bundle *tokendBundle); + +private: + ServiceLevel mServiceLevel; // level of service requested/determined + + std::string mCachePath; // path to cache directory + TokenCache *mTokenCache; // cache object (lazy) + + typedef map > ReaderMap; + typedef set > ReaderSet; + ReaderMap mReaders; // presently known PCSC Readers (aka slots) + + class Watcher : public Thread { + public: + Watcher(Server &server, TokenCache &tokenCache, ReaderMap& readers); + + protected: + void action(); + + private: + Server &mServer; + TokenCache &mTokenCache; + PCSC::Session mSession; // PCSC client session + ReaderMap& mReaders; + }; +}; + + +#endif //_H_PCSCMONITOR diff --git a/securityd/src/process.cpp b/securityd/src/process.cpp new file mode 100644 index 00000000..c756c6b7 --- /dev/null +++ b/securityd/src/process.cpp @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2000-2009,2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + */ + + +// +// process - track a single client process and its belongings +// +#include "process.h" +#include "server.h" +#include "session.h" +#include "tempdatabase.h" +#include "authority.h" +#include "child.h" // ServerChild (really UnixPlusPlus::Child)::find() + +#include //@@@ debug only +#include "agentquery.h" + + +// +// Construct a Process object. +// +Process::Process(TaskPort taskPort, const ClientSetupInfo *info, const CommonCriteria::AuditToken &audit) + : mTaskPort(taskPort), mByteFlipped(false), mPid(audit.pid()), mUid(audit.euid()), mGid(audit.egid()) +{ + StLock _(*this); + + // set parent session + parent(Session::find(audit.sessionId(), true)); + + // let's take a look at our wannabe client... + if (mTaskPort.pid() != mPid) { + secdebug("SS", "Task/pid setup mismatch pid=%d task=%d(%d)", + mPid, mTaskPort.port(), mTaskPort.pid()); + CssmError::throwMe(CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED); // you lied! + } + + setup(info); + ClientIdentification::setup(this->pid()); + + // NB: ServerChild::find() should only be used to determine + // *existence*. Don't use the returned Child object for anything else, + // as it is not protected against its underlying process's destruction. + if (this->pid() == getpid() // called ourselves (through some API). Do NOT record this as a "dirty" transaction + || ServerChild::find(this->pid())) // securityd's child; do not mark this txn dirty + VProc::Transaction::deactivate(); + + if (SECURITYD_CLIENT_NEW_ENABLED()) + SECURITYD_CLIENT_NEW(this, this->pid(), &this->session(), + (char *)codePath(this->processCode()).c_str(), taskPort, mUid, mGid, mByteFlipped); +} + + +// +// Screen a process setup request for an existing process. +// This means the client has requested intialization even though we remember having +// talked to it in the past. This could either be an exec(2), or the client could just +// have forgotten all about its securityd client state. Or it could be an attack... +// +void Process::reset(TaskPort taskPort, const ClientSetupInfo *info, const CommonCriteria::AuditToken &audit) +{ + StLock _(*this); + if (taskPort != mTaskPort) { + secdebug("SS", "Process %p(%d) reset mismatch (tp %d-%d)", + this, pid(), taskPort.port(), mTaskPort.port()); + //@@@ CssmError::throwMe(CSSM_ERRCODE_VERIFICATION_FAILURE); // liar + } + setup(info); + CFCopyRef oldCode = processCode(); + + ClientIdentification::setup(this->pid()); // re-constructs processCode() + if (CFEqual(oldCode, processCode())) { + SECURITYD_CLIENT_RESET_AMNESIA(this); + } else { + SECURITYD_CLIENT_RESET_FULL(this); + CodeSigningHost::reset(); + } +} + + +// +// Common set processing +// +void Process::setup(const ClientSetupInfo *info) +{ + // process setup info + assert(info); + uint32 pversion; + if (info->order == 0x1234) { // right side up + pversion = info->version; + mByteFlipped = false; + } else if (info->order == 0x34120000) { // flip side up + pversion = flip(info->version); + mByteFlipped = true; + } else // non comprende + CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION); + + // check wire protocol version + if (pversion != SSPROTOVERSION) + CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION); +} + + +// +// Clean up a Process object +// +Process::~Process() +{ + SECURITYD_CLIENT_RELEASE(this, this->pid()); + + // tell all our authorizations that we're gone + IFDEBUG(if (!mAuthorizations.empty()) + secdebug("SS", "Process %p(%d) clearing %d authorizations", + this, mPid, int(mAuthorizations.size()))); + for (AuthorizationSet::iterator it = mAuthorizations.begin(); + it != mAuthorizations.end(); ) { + AuthorizationToken *auth = *it; + while (++it != mAuthorizations.end() && *it == auth) ; // Skip duplicates + if (auth->endProcess(*this)) + delete auth; + } + + // release our name for the process's task port + if (mTaskPort) + mTaskPort.destroy(); +} + +void Process::kill() +{ + StLock _(*this); + + // release local temp store + mLocalStore = NULL; + + // standard kill processing + PerProcess::kill(); +} + + +Session& Process::session() const +{ + return parent(); +} + + +void Process::checkSession(const audit_token_t &auditToken) +{ + AuditToken audit(auditToken); + if (audit.sessionId() != this->session().sessionId()) + this->changeSession(audit.sessionId()); +} + + +LocalDatabase &Process::localStore() +{ + StLock _(*this); + if (!mLocalStore) + mLocalStore = new TempDatabase(*this); + return *mLocalStore; +} + +Key *Process::makeTemporaryKey(const CssmKey &key, CSSM_KEYATTR_FLAGS moreAttributes, + const AclEntryPrototype *owner) +{ + return safer_cast(localStore()).makeKey(key, moreAttributes, owner); +} + + +// +// Change the session of a process. +// This is the result of SessionCreate from a known process client. +// +void Process::changeSession(Session::SessionId sessionId) +{ + // re-parent + parent(Session::find(sessionId, true)); + SECURITYD_CLIENT_CHANGE_SESSION(this, &this->session()); +} + + +// +// Authorization set maintainance +// +void Process::addAuthorization(AuthorizationToken *auth) +{ + assert(auth); + StLock _(*this); + mAuthorizations.insert(auth); + auth->addProcess(*this); +} + +void Process::checkAuthorization(AuthorizationToken *auth) +{ + assert(auth); + StLock _(*this); + if (mAuthorizations.find(auth) == mAuthorizations.end()) + MacOSError::throwMe(errAuthorizationInvalidRef); +} + +bool Process::removeAuthorization(AuthorizationToken *auth) +{ + assert(auth); + StLock _(*this); + // we do everything with a single set lookup call... + typedef AuthorizationSet::iterator Iter; + Iter it = mAuthorizations.lower_bound(auth); + bool isLast; + if (it == mAuthorizations.end() || auth != *it) { + isLast = true; + } else { + Iter next = it; ++next; // following element + isLast = (next == mAuthorizations.end()) || auth != *next; + mAuthorizations.erase(it); // remove first match + } + if (isLast) { + if (auth->endProcess(*this)) // ... tell it to remove us, + return true; // ... and tell the caller + } + return false; // keep the auth; it's still in use +} + + +// +// Debug dump support +// +#if defined(DEBUGDUMP) + +void Process::dumpNode() +{ + PerProcess::dumpNode(); + if (mByteFlipped) + Debug::dump(" FLIPPED"); + Debug::dump(" task=%d pid=%d uid/gid=%d/%d", + mTaskPort.port(), mPid, mUid, mGid); + CodeSigningHost::dump(); + ClientIdentification::dump(); +} + +#endif //DEBUGDUMP diff --git a/securityd/src/process.h b/securityd/src/process.h new file mode 100644 index 00000000..935ec465 --- /dev/null +++ b/securityd/src/process.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2000-2009 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@ + */ + + +// +// process - track a single client process and its belongings +// +#ifndef _H_PROCESS +#define _H_PROCESS + +#include "structure.h" +#include "session.h" +#include +#include +#include +#include +#include "clientid.h" +#include "csproxy.h" +#include "localkey.h" +#include "notifications.h" +#include + +using MachPlusPlus::Port; +using MachPlusPlus::TaskPort; + +class Session; +class LocalDatabase; +class AuthorizationToken; + + +// +// A Process object represents a UNIX process (and associated Mach Task) that has +// had contact with us and may have some state associated with it. It primarily tracks +// the process nature of the client. Individual threads in the client are tracked by +// Connection objects. +// +// Code Signing-style Guest identities are managed in two of our mix-ins. The two play +// distinct but related roles: +// * CodeSigningHost manages the public identity of guests within the client. +// In this relationship, securityd provides registry and proxy services to the client. +// * ClientIdentification tracks the identity of guests in the client *as securityd clients*. +// It is concerned with which guest is asking for securityd services, and whether this +// should be granted. +// Often, the two form a loop: ClientIdentification uses CodeSigningHost to determine +// the guest client identity, but it does so through public (Mach IPC) interfaces, because +// clients may implement their own proxy (though currently not registry) services. +// We could short-circuit the IPC leg in those cases where securityd serves itself, +// but there's no evidence (yet) that this is worth the trouble. +// +class Process : public PerProcess, + public CodeSigningHost, + public ClientIdentification, + private VProc::Transaction { +public: + Process(TaskPort tPort, const ClientSetupInfo *info, const CommonCriteria::AuditToken &audit); + virtual ~Process(); + + void reset(TaskPort tPort, const ClientSetupInfo *info, const CommonCriteria::AuditToken &audit); + + uid_t uid() const { return mUid; } + gid_t gid() const { return mGid; } + pid_t pid() const { return mPid; } + TaskPort taskPort() const { return mTaskPort; } + bool byteFlipped() const { return mByteFlipped; } + + void addAuthorization(AuthorizationToken *auth); + void checkAuthorization(AuthorizationToken *auth); + bool removeAuthorization(AuthorizationToken *auth); + + using PerProcess::kill; + void kill(); + + void changeSession(Session::SessionId sessionId); + + Session& session() const; + void checkSession(const audit_token_t &auditToken); + + LocalDatabase &localStore(); + Key *makeTemporaryKey(const CssmKey &key, CSSM_KEYATTR_FLAGS moreAttributes, + const AclEntryPrototype *owner); + + // aclSequence is taken to serialize ACL validations to pick up mutual changes + Mutex aclSequence; + + IFDUMP(void dumpNode()); + +private: + void setup(const ClientSetupInfo *info); + +private: + // peer state: established during connection startup; fixed thereafter + TaskPort mTaskPort; // task port + bool mByteFlipped; // client's byte order is reverse of ours + pid_t mPid; // process id + uid_t mUid; // UNIX uid credential + gid_t mGid; // primary UNIX gid credential + + // authorization dictionary + typedef multiset AuthorizationSet; + AuthorizationSet mAuthorizations; // set of valid authorizations for process + + // canonical local (transient) key store + RefPointer mLocalStore; +}; + + +// +// Convenience comparison +// +inline bool operator == (const Process &p1, const Process &p2) +{ + return &p1 == &p2; +} + + +#endif //_H_PROCESS diff --git a/securityd/src/reader.cpp b/securityd/src/reader.cpp new file mode 100644 index 00000000..a7d219ff --- /dev/null +++ b/securityd/src/reader.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2004,2007-2008 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@ + */ + + +// +// reader - token reader objects +// +#include "reader.h" + + +// +// Construct a Reader +// This does not commence state tracking; call update to start up the reader. +// +Reader::Reader(TokenCache &tc, const PCSC::ReaderState &state) + : cache(tc), mType(pcsc), mToken(NULL) +{ + mName = state.name(); // remember separate copy of name + mPrintName = mName; //@@@ how to make this readable? Use IOKit information? + secdebug("reader", "%p (%s) new PCSC reader", this, name().c_str()); +} + +Reader::Reader(TokenCache &tc, const string &identifier) + : cache(tc), mType(software), mToken(NULL) +{ + mName = identifier; + mPrintName = mName; + secdebug("reader", "%p (%s) new software reader", this, name().c_str()); +} + +Reader::~Reader() +{ + secdebug("reader", "%p (%s) destroyed", this, name().c_str()); +} + + +// +// Type qualification. None matches anything. +// +bool Reader::isType(Type reqType) const +{ + return reqType == this->type(); +} + + +// +// Killing a reader forcibly removes its Token, if any +// +void Reader::kill() +{ + if (mToken) + removeToken(); + NodeCore::kill(); +} + + +// +// State transition matrix for a reader, based on PCSC state changes +// +void Reader::update(const PCSC::ReaderState &state) +{ + // set new state + unsigned long oldState = mState.state(); + mState = state; + mState.name(mName.c_str()); // (fix name pointer, unchanged) + + try { + if (state.state(SCARD_STATE_UNAVAILABLE)) { + // reader is unusable (probably being removed) + secdebug("reader", "%p (%s) unavailable (0x%lx)", + this, name().c_str(), state.state()); + if (mToken) + removeToken(); + } else if (state.state(SCARD_STATE_EMPTY)) { + // reader is empty (no token present) + secdebug("reader", "%p (%s) empty (0x%lx)", + this, name().c_str(), state.state()); + if (mToken) + removeToken(); + } else if (state.state(SCARD_STATE_PRESENT)) { + // reader has a token inserted + secdebug("reader", "%p (%s) card present (0x%lx)", + this, name().c_str(), state.state()); + //@@@ is this hack worth it (with notifications in)?? + if (mToken && CssmData(state) != CssmData(pcscState())) + removeToken(); // incomplete but better than nothing + //@@@ or should we call some verify-still-the-same function of tokend? + //@@@ (I think pcsc will return an error if the card changed?) + if (!mToken) + insertToken(NULL); + } else { + secdebug("reader", "%p (%s) unexpected state change (0x%lx to 0x%lx)", + this, name().c_str(), oldState, state.state()); + } + } catch (...) { + secdebug("reader", "state update exception (ignored)"); + } +} + + +void Reader::insertToken(TokenDaemon *tokend) +{ + RefPointer token = new Token(); + token->insert(*this, tokend); + mToken = token; + addReference(*token); + secdebug("reader", "%p (%s) inserted token %p", + this, name().c_str(), mToken); +} + + +void Reader::removeToken() +{ + secdebug("reader", "%p (%s) removing token %p", + this, name().c_str(), mToken); + assert(mToken); + mToken->remove(); + removeReference(*mToken); + mToken = NULL; +} + + +// +// Debug dump support +// +#if defined(DEBUGDUMP) + +void Reader::dumpNode() +{ + PerGlobal::dumpNode(); + Debug::dump(" [%s] state=0x%lx", name().c_str(), mState.state()); +} + +#endif //DEBUGDUMP diff --git a/securityd/src/reader.h b/securityd/src/reader.h new file mode 100644 index 00000000..341308d6 --- /dev/null +++ b/securityd/src/reader.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2004,2008,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +// +// reader - token reader objects +// +#ifndef _H_READER +#define _H_READER + +#include "structure.h" +#include "token.h" +#include "tokencache.h" +#include + + +// +// A Reader object represents a token (card) reader device attached to the +// system. +// +class Reader : public PerGlobal { +public: + Reader(TokenCache &cache, const PCSC::ReaderState &state); // PCSC managed + Reader(TokenCache &cache, const std::string &name); // software + ~Reader(); + + enum Type { + pcsc, // represents PCSC-managed reader + software // software (virtual) reader, + }; + Type type() const { return mType; } + bool isType(Type type) const; + + TokenCache &cache; + + void kill(); + + const string &name() const { return mName; } + const string &printName() const { return mPrintName; } + const PCSC::ReaderState &pcscState() const { return mState; } + + void insertToken(TokenDaemon *tokend); + void update(const PCSC::ReaderState &state); + void removeToken(); + + IFDUMP(void dumpNode()); + +protected: + +private: + Type mType; + string mName; // PCSC reader name + string mPrintName; // human readable name of reader + PCSC::ReaderState mState; // name field not valid (use mName) + Token *mToken; // token inserted here (also in references) +}; + + +#endif //_H_READER diff --git a/securityd/src/securityd.d b/securityd/src/securityd.d new file mode 100644 index 00000000..32f5d757 --- /dev/null +++ b/securityd/src/securityd.d @@ -0,0 +1,131 @@ +/* + * DTrace provider for securityd + */ + + +/* + * Work around 5194316 + */ +#define uint32_t unsigned + + +/* + * Types + */ +typedef const void *DTHandle; +typedef uint32_t DTPort; +typedef uint32_t DTGuest; +typedef uint8_t bool; + +/* + * The main static provider for securityd + */ +provider securityd { + /* + * Overall operational events + */ + probe installmode(); // configuring for system installation scenario + probe initialized(const char *bootstrapName); + + + /* + * Keychain activity (DbCommon status change) + */ + probe keychain__create(DTHandle common, const char *name, DTHandle db); + probe keychain__make(DTHandle common, const char *name, DTHandle db); + probe keychain__join(DTHandle common, const char *name, DTHandle db); + probe keychain__unlock(DTHandle id, const char *name); + probe keychain__lock(DTHandle id, const char *name); + probe keychain__release(DTHandle id, const char *name); + + /* + * Client management + */ + probe client__new(DTHandle id, int pid, DTHandle session, const char *path, DTPort taskport, int uid, int gid, bool flipped); + probe client__release(DTHandle id, int pid); + probe client__connection__new(DTHandle id, DTPort port, DTHandle client); + probe client__connection__release(DTHandle id); + + probe client__change_session(DTHandle id, DTHandle session); + probe client__reset__amnesia(DTHandle id); + probe client__reset__full(DTHandle id); + + probe request__entry(const char *name, DTHandle connection, DTHandle process); + probe request__return(uint32_t osstatus); + + /* + * Session management + */ + probe session__create(DTHandle id, uint32_t sessionId, const void *auditInfo, uint32_t auditInfoLength); + probe session__kill(DTHandle id, uint32_t sessionId); + probe session__destroy(DTHandle id, uint32_t sessionId); + + probe session__notify(uint64_t id, uint32_t flags, int uid); + + /* + * Port-related events (internal interest only) + */ + probe ports__dead__connection(DTPort port); + probe ports__dead__process(DTPort port); + probe ports__dead__session(DTPort port); + probe ports__dead__orphan(DTPort port); + + /* + * Power management and tracking + */ + probe power__sleep(); + probe power__wake(); + probe power__on(); + + /* + * Code Signing related + */ + probe host__register(DTHandle proc, DTPort port); + probe host__proxy(DTHandle proc, DTPort port); + probe host__unregister(DTHandle proc); + probe guest__create(DTHandle proc, DTGuest host, DTGuest guest, uint32_t status, uint32_t flags, const char *path); + probe guest__cdhash(DTHandle proc, DTGuest guest, const void *hash, uint32_t length); + probe guest__destroy(DTHandle proc, DTGuest guest); + probe guest__change(DTHandle proc, DTGuest guest, uint32_t status); + + /* + * Child management + */ + probe child__dying(int pid); + probe child__checkin(int pid, DTPort servicePort); + probe child__stillborn(int pid); + probe child__ready(int pid); + + /* + * Authorization + */ + /* creation */ + probe auth__create(DTHandle session, void *authref); + /* rule evaluation types */ + probe auth__allow(DTHandle authref, const char *rule); + probe auth__deny(DTHandle authref, const char *rule); + probe auth__user(DTHandle authref, const char *rule); + probe auth__rules(DTHandle authref, const char *rule); + probe auth__kofn(DTHandle authref, const char *rule); + probe auth__mechrule(DTHandle authref, const char *rule); + probe auth__mech(DTHandle authref, const char *mechanism); + /* evaluation intermediate results */ + probe auth__user__allowroot(DTHandle authref); + probe auth__user__allowsessionowner(DTHandle authref); + /* evaluation final result */ + probe auth__evalright(DTHandle authref, const char *right, int32_t status); + + /* + * Miscellaneous activity + */ + probe shutdown__begin(); + probe shutdown__count(int processesLeft, int dirtyCountLeft); + probe shutdown__now(); + + probe entropy__collect(); + probe entropy__seed(const void *data, uint32_t count); + probe entropy__save(const char *path); + + probe signal__received(int signal); + probe signal__handled(int signal); +}; diff --git a/securityd/src/securityd.exp b/securityd/src/securityd.exp new file mode 100644 index 00000000..e69de29b diff --git a/securityd/src/securityd.order b/securityd/src/securityd.order new file mode 100644 index 00000000..38454ed5 --- /dev/null +++ b/securityd/src/securityd.order @@ -0,0 +1,912 @@ +_self_client_handleSession +__ZN8Security12MachPlusPlus10MachServer4busyEv +__ZN8Security5Mutex4lockEv +__ZN8Security12MachPlusPlus10MachServer17ensureReadyThreadEv +__ZN8Security5Mutex6unlockEv +__ZThn144_N6Server6handleEP17mach_msg_header_tS1_ +__ZN6Server6handleEP17mach_msg_header_tS1_ +__Z11ucsp_serverP17mach_msg_header_tS0_ +__Z11self_serverP17mach_msg_header_tS0_ +__ZL15_XhandleSessionP17mach_msg_header_tS0_ +__Z25self_server_handleSessionjjjy +__ZN8Security6StLockINS_12MachPlusPlus10MachServerEXadL_ZNS2_4busyEvEEXadL_ZNS2_4idleEvEEED2Ev +__ZThn144_N6Server9eventDoneEv +__ZN6Server9eventDoneEv +__ZN8Security12MachPlusPlus10MachServer12processTimerEv +__ZN8Security4Time3nowEv +__ZN8Security12MachPlusPlus10MachServer26releaseDeferredAllocationsEv +__ZN8Security11ModuleNexusINS_11ThreadNexusINS_12MachPlusPlus10MachServer9PerThreadEEEEclEv +__ZN8Security11ThreadNexusINS_12MachPlusPlus10MachServer9PerThreadEEclEv +__ZNSt8_Rb_treeIN8Security12MachPlusPlus10MachServer10AllocationES3_St9_IdentityIS3_ESt4lessIS3_ESaIS3_EE5eraseESt23_Rb_tree_co +__ZNSt8_Rb_treeIN8Security12MachPlusPlus10MachServer10AllocationES3_St9_IdentityIS3_ESt4lessIS3_ESaIS3_EE8_M_eraseEPSt13_Rb_tre +_cdsa_notify_server +__Xmach_notify_dead_name +_cdsa_mach_notify_dead_name +__ZThn144_N6Server14notifyDeadNameEN8Security12MachPlusPlus4PortE +__ZN6Server14notifyDeadNameEN8Security12MachPlusPlus4PortE +__ZNSt8_Rb_treeIN8Security12MachPlusPlus4PortESt4pairIKS2_NS0_10RefPointerI10ConnectionEEESt10_Select1stIS8_ESt4lessIS2_ESaIS8_ +__ZNK8Security8RefCount3refEv +__ZN8Security10RefPointerI10ConnectionE7releaseEv +__ZNK8Security8RefCount5unrefEv +__ZN10Connection5abortEb +__ZN8Security12MachPlusPlus5Error5checkEi +__ZN10ConnectionD0Ev +__ZNSt8_Rb_treeIjSt4pairIKjN8Security10RefPointerIN8Listener12NotificationEEEESt10_Select1stIS7_ESt4lessIjESaIS7_EED2Ev +__ZNSt8_Rb_treeIjSt4pairIKjN8Security10RefPointerIN8Listener12NotificationEEEESt10_Select1stIS7_ESt4lessIjESaIS7_EE8_M_eraseEPS +__ZN8NodeCoreD2Ev +__ZNSt8_Rb_treeIN8Security10RefPointerI8NodeCoreEES3_St9_IdentityIS3_ESt4lessIS3_ESaIS3_EED2Ev +__ZNSt8_Rb_treeIN8Security10RefPointerI8NodeCoreEES3_St9_IdentityIS3_ESt4lessIS3_ESaIS3_EE8_M_eraseEPSt13_Rb_tree_nodeIS3_E +__ZN8Security10RefPointerI8NodeCoreE7releaseEv +__ZN8Security5MutexD2Ev +__ZL19_XverifyPrivileged2P17mach_msg_header_tS0_ +__Z29ucsp_server_verifyPrivileged2jj13audit_token_tPiPj +__ZL7_XsetupP17mach_msg_header_tS0_ +__Z17ucsp_server_setupjj13audit_token_tPijN8Security14SecurityServer15ClientSetupInfoEPKc +__ZN6Server6activeEv +__ZN6Server15setupConnectionENS_12ConnectLevelEN8Security12MachPlusPlus4PortES3_RK13audit_token_tPKNS1_14SecurityServer15Client +__ZN8Security14CommonCriteria10AuditTokenC1ERK13audit_token_t +__ZN8Security14CommonCriteria10AuditTokenC2ERK13audit_token_t +__ZN8Security14CommonCriteria10TerminalIdC2Ev +__ZNSt3mapIN8Security12MachPlusPlus4PortENS0_10RefPointerI7ProcessEESt4lessIS2_ESaISt4pairIKS2_S5_EEEixERS9_ +__ZNSt8_Rb_treeIN8Security12MachPlusPlus4PortESt4pairIKS2_NS0_10RefPointerI7ProcessEEESt10_Select1stIS8_ESt4lessIS2_ESaIS8_EE9_ +__ZNSt8_Rb_treeIN8Security12MachPlusPlus4PortESt4pairIKS2_NS0_10RefPointerI7ProcessEEESt10_Select1stIS8_ESt4lessIS2_ESaIS8_EE14 +__ZN9__gnu_cxx13new_allocatorISt4pairIKN8Security12MachPlusPlus4PortENS2_10RefPointerI7ProcessEEEE9constructEPS9_RKS9_ +__ZN8Security10RefPointerI7ProcessE7releaseEv +__ZN7ProcessC1EN8Security12MachPlusPlus8TaskPortEPKNS0_14SecurityServer15ClientSetupInfoERKNS0_14CommonCriteria10AuditTokenE +__ZN7ProcessC2EN8Security12MachPlusPlus8TaskPortEPKNS0_14SecurityServer15ClientSetupInfoERKNS0_14CommonCriteria10AuditTokenE +__ZN10PerProcessC2Ev +__ZN8Security13MappingHandleIjE4makeEv +__ZN8Security11ModuleNexusINS_13MappingHandleIjE5StateEEclEv +__ZN9__gnu_cxx9hashtableISt4pairIKjPN8Security13MappingHandleIjEEEjNS_4hashIjEESt10_Select1stIS7_ESt8equal_toIjESaIS6_EE4findER +__ZN9__gnu_cxx9hashtableISt4pairIKjPN8Security13MappingHandleIjEEEjNS_4hashIjEESt10_Select1stIS7_ESt8equal_toIjESaIS6_EE14find_ +__ZN9__gnu_cxx9hashtableISt4pairIKjPN8Security13MappingHandleIjEEEjNS_4hashIjEESt10_Select1stIS7_ESt8equal_toIjESaIS6_EE6resize +__ZN8NodeCoreC2Ev +__ZN8Security5MutexC2ENS0_4TypeE +__ZN8Security11ModuleNexusI15MutexAttributesEclEv +__ZN15CodeSigningHostC2Ev +__ZN8Security5MutexC1ENS0_4TypeE +__ZN20ClientIdentificationC2Ev +__ZN14CodeSignatures8IdentityC2Ev +__ZN8Security5MutexC1Ev +__ZN8Security5MutexC2Ev +__ZN7Session4findEib +__ZNSt8_Rb_treeIiSt4pairIKiN8Security10RefPointerI7SessionEEESt10_Select1stIS6_ESt4lessIiESaIS6_EE4findERS1_ +__ZN8Security14CommonCriteria9AuditInfo3getEi +__ZN8Security9UnixError5checkEi +__ZN14DynamicSessionC2ERKN8Security14CommonCriteria9AuditInfoE +__ZN7SessionC2ERKN8Security14CommonCriteria9AuditInfoER6Server +__ZN13Authorization10CredentialC1Ev +__ZN13Authorization10CredentialC2Ev +__ZN13Authorization14CredentialImplC2Ev +__ZN8NodeCore6parentERS_ +__ZN8Security10RefPointerI8NodeCoreE10setPointerEPS1_ +__ZNSt3mapIiN8Security10RefPointerI7SessionEESt4lessIiESaISt4pairIKiS3_EEEixERS7_ +__ZNSt8_Rb_treeIiSt4pairIKiN8Security10RefPointerI7SessionEEESt10_Select1stIS6_ESt4lessIiESaIS6_EE16_M_insert_uniqueESt17_Rb_tr +__ZNSt8_Rb_treeIiSt4pairIKiN8Security10RefPointerI7SessionEEESt10_Select1stIS6_ESt4lessIiESaIS6_EE9_M_insertEPSt18_Rb_tree_node +__ZNSt8_Rb_treeIiSt4pairIKiN8Security10RefPointerI7SessionEEESt10_Select1stIS6_ESt4lessIiESaIS6_EE14_M_create_nodeERKS6_ +__ZN9__gnu_cxx13new_allocatorISt4pairIKiN8Security10RefPointerI7SessionEEEE9constructEPS7_RKS7_ +__ZN8Security10RefPointerI7SessionE7releaseEv +__ZN8Security10RefPointerI7SessionE10setPointerEPS1_ +__ZN8Security6Syslog6noticeEPKcz +__ZNSt8_Rb_treeIiSt4pairIKiN8Security10RefPointerI7SessionEEESt10_Select1stIS6_ESt4lessIiESaIS6_EE16_M_insert_uniqueERKS6_ +__ZNK8Security12MachPlusPlus8TaskPort3pidEv +__ZN7Process5setupEPKN8Security14SecurityServer15ClientSetupInfoE +__ZN20ClientIdentification5setupEi +__ZNSt8_Rb_treeIjSt4pairIKjN20ClientIdentification10GuestStateEESt10_Select1stIS4_ESt4lessIjESaIS4_EE5eraseESt17_Rb_tree_iterat +__ZNSt8_Rb_treeIjSt4pairIKjN20ClientIdentification10GuestStateEESt10_Select1stIS4_ESt4lessIjESaIS4_EE8_M_eraseEPSt13_Rb_tree_no +__ZN8Security12UnixPlusPlus5Child4findI11ServerChildEEPT_i +__ZN8Security12UnixPlusPlus5Child11findGenericEi +__ZN8Security11ModuleNexusINS_12UnixPlusPlus5Child8ChildrenEEclEv +__ZNSt8_Rb_treeIiSt4pairIKiPN8Security12UnixPlusPlus5ChildEESt10_Select1stIS6_ESt4lessIiESaIS6_EE4findERS1_ +__ZN8Security10RefPointerI7ProcessE10setPointerEPS1_ +__ZNK8Security12MachPlusPlus10MachServer12notifyIfDeadENS0_4PortEb +__ZN8Security12MachPlusPlus4Port13requestNotifyEjij +__ZNSt3mapIiP7ProcessSt4lessIiESaISt4pairIKiS1_EEEixERS5_ +__ZNSt8_Rb_treeIiSt4pairIKiP7ProcessESt10_Select1stIS4_ESt4lessIiESaIS4_EE16_M_insert_uniqueESt17_Rb_tree_iteratorIS4_ERKS4_ +__ZNSt8_Rb_treeIiSt4pairIKiP7ProcessESt10_Select1stIS4_ESt4lessIiESaIS4_EE9_M_insertEPSt18_Rb_tree_node_baseSC_RKS4_ +__ZN10ConnectionC1ER7ProcessN8Security12MachPlusPlus4PortE +__ZN10ConnectionC2ER7ProcessN8Security12MachPlusPlus4PortE +__ZNKSt8_Rb_treeIN8Security12MachPlusPlus4PortESt4pairIKS2_NS0_10RefPointerI10ConnectionEEESt10_Select1stIS8_ESt4lessIS2_ESaIS8 +__ZNSt3mapIN8Security12MachPlusPlus4PortENS0_10RefPointerI10ConnectionEESt4lessIS2_ESaISt4pairIKS2_S5_EEEixERS9_ +__ZN9__gnu_cxx13new_allocatorISt4pairIKN8Security12MachPlusPlus4PortENS2_10RefPointerI10ConnectionEEEE9constructEPS9_RKS9_ +__ZN8Security10RefPointerI10ConnectionE10setPointerEPS1_ +__ZL21_XauthorizationCreateP17mach_msg_header_tS0_ +__Z31ucsp_server_authorizationCreatejj13audit_token_tPiPvjjS1_jPN8Security14SecurityServer17AuthorizationBlobE +__ZN6Server10connectionEjR13audit_token_t +__ZNK7PortMapI10ConnectionE3getEji +__ZN7Process12checkSessionERK13audit_token_t +__ZN8Security11ThreadNexusINS_10RefPointerI10ConnectionEEEclEv +__ZN10Connection9beginWorkER13audit_token_t +__ZN13Authorization11AuthItemSetC1EPK20AuthorizationItemSet +__ZN13Authorization11AuthItemSetC2EPK20AuthorizationItemSet +__ZNK7Process7sessionEv +__ZN7Session10authCreateERKN13Authorization11AuthItemSetES3_jRN8Security14SecurityServer17AuthorizationBlobERK13audit_token_t +__ZN18AuthorizationTokenC1ER7SessionRKSt3setIN13Authorization10CredentialESt4lessIS4_ESaIS4_EERK13audit_token_tb +__ZN18AuthorizationTokenC2ER7SessionRKSt3setIN13Authorization10CredentialESt4lessIS4_ESaIS4_EERK13audit_token_tb +__ZNSt8_Rb_treeIN13Authorization10CredentialES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EEC2ERKS7_ +__ZN6Server7processEv +__ZN6Server10connectionEb +__ZN10Connection9checkWorkEv +__ZN13Authorization11AuthItemSetC1Ev +__ZNK20ClientIdentification12currentGuestEv +__ZNK20ClientIdentification7currentEv +__ZNSt8_Rb_treeIjSt4pairIKjN20ClientIdentification10GuestStateEESt10_Select1stIS4_ESt4lessIjESaIS4_EE4findERS1_ +__ZN8Security12MachPlusPlus10MachServer16longTermActivityEv +__ZN8Security5CFRefIP9__SecCodeEaSERKS3_ +__ZNSt3mapIjN20ClientIdentification10GuestStateESt4lessIjESaISt4pairIKjS1_EEEixERS5_ +__ZNSt8_Rb_treeIjSt4pairIKjN20ClientIdentification10GuestStateEESt10_Select1stIS4_ESt4lessIjESaIS4_EE16_M_insert_uniqueESt17_Rb +__ZNSt8_Rb_treeIjSt4pairIKjN20ClientIdentification10GuestStateEESt10_Select1stIS4_ESt4lessIjESaIS4_EE16_M_insert_uniqueERKS4_ +__ZNSt8_Rb_treeIjSt4pairIKjN20ClientIdentification10GuestStateEESt10_Select1stIS4_ESt4lessIjESaIS4_EE9_M_insertEPSt18_Rb_tree_n +__ZNSt8_Rb_treeIjSt4pairIKjN20ClientIdentification10GuestStateEESt10_Select1stIS4_ESt4lessIjESaIS4_EE14_M_create_nodeERKS4_ +__ZN8NodeCore8referentERS_ +__ZN8Security18DevRandomGenerator6randomEPvm +__ZN8Security11ModuleNexusINS_18DevRandomGenerator8ReadonlyEEclEv +__ZN8Security12UnixPlusPlus8FileDesc4readEPvm +__ZNSt3mapIN8Security14SecurityServer17AuthorizationBlobENS0_10RefPointerI18AuthorizationTokenEESt4lessIS2_ESaISt4pairIKS2_S5_E +__ZNSt8_Rb_treeIN8Security14SecurityServer17AuthorizationBlobESt4pairIKS2_NS0_10RefPointerI18AuthorizationTokenEEESt10_Select1s +__ZN9__gnu_cxx13new_allocatorISt4pairIKN8Security14SecurityServer17AuthorizationBlobENS2_10RefPointerI18AuthorizationTokenEEEE9 +__ZNSt4pairIKN8Security14SecurityServer17AuthorizationBlobENS0_10RefPointerI18AuthorizationTokenEEEC2ERKS7_ +__ZN8Security10RefPointerI18AuthorizationTokenE7releaseEv +__ZN8Security10RefPointerI18AuthorizationTokenE10setPointerEPS1_ +__ZNSt8_Rb_treeIN13Authorization10CredentialES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EEaSERKS7_ +__ZNSt8_Rb_treeIN13Authorization10CredentialES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE8_M_eraseEPSt13_Rb_tree_nodeIS1_E +__ZN13Authorization6Engine9authorizeERKNS_11AuthItemSetES3_jPKSt3setINS_10CredentialESt4lessIS5_ESaIS5_EEPS9_RS1_R18Authorizati +__ZN13Authorization20AuthorizationDBPlist4syncEd +__ZN13Authorization11AuthItemSetC1ERKS0_ +__ZN13Authorization11AuthItemSetC2ERKS0_ +__ZNSt8_Rb_treeIN13Authorization11AuthItemRefES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EEC2ERKS7_ +__ZN8Security14CommonCriteria9Securityd25RightAuthenticationLoggerC1ERKNS0_10AuditTokenEs +__ZN8Security14CommonCriteria9Securityd25RightAuthenticationLoggerC2ERKNS0_10AuditTokenEs +__ZN8Security14CommonCriteria9Securityd11AuditLoggerC2ERKNS0_10AuditTokenEs +__ZN8Security14CommonCriteria9Securityd11RightLoggerC2Ev +__ZNSt8_Rb_treeIN13Authorization10CredentialES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE4swapERS7_ +__ZNSt6vectorIN13Authorization11AuthItemRefESaIS1_EED2Ev +__ZN8Security14CommonCriteria9Securityd25RightAuthenticationLoggerD2Ev +__ZN8Security14CommonCriteria9Securityd11AuditLoggerD2Ev +__ZN8Security14CommonCriteria9Securityd11AuditLogger5closeEb +__ZN13Authorization11AuthItemSetD1Ev +__ZN13Authorization11AuthItemSetD2Ev +__ZNSt8_Rb_treeIN13Authorization11AuthItemRefES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EED2Ev +__ZNSt8_Rb_treeIN13Authorization11AuthItemRefES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE8_M_eraseEPSt13_Rb_tree_nodeIS1_E +__ZNSt8_Rb_treeIN13Authorization10CredentialES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EED2Ev +__ZN7Process16addAuthorizationEP18AuthorizationToken +__ZNSt8_Rb_treeIP18AuthorizationTokenS1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE15_M_insert_equalERKS1_ +__ZNSt8_Rb_treeIP18AuthorizationTokenS1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE9_M_insertEPSt18_Rb_tree_node_baseS9_RKS1_ +__ZN18AuthorizationToken10addProcessER7Process +__ZNSt8_Rb_treeIP7ProcessS1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE16_M_insert_uniqueERKS1_ +__ZNSt8_Rb_treeIP7ProcessS1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE9_M_insertEPSt18_Rb_tree_node_baseS9_RKS1_ +__ZN6Server15requestCompleteERi +__ZN10Connection7endWorkERi +__ZL25_XauthorizationCopyRightsP17mach_msg_header_tS0_ +__Z35ucsp_server_authorizationCopyRightsjj13audit_token_tPiN8Security14SecurityServer17AuthorizationBlobEPvjjS4_jPS4_Pj +_copyout_AuthorizationItemSet +_copyout +_sec_xdrmem_create +_sec_xdr_sizeof_out +_sec_xdr_arena_init_size_alloc +_xdr_AuthorizationItemSetPtr +_sec_xdr_reference +_sec_xdr_arena_size_allocator +_sec_mem_alloc +_xdr_AuthorizationItemSet +_sec_xdr_array +_sec_xdrmem_getlong_aligned +_xdr_AuthorizationItem +_sec_xdr_charp +_sec_xdr_bytes +_sec_xdrmem_getbytes +_sec_xdr_arena_init +__ZN13Authorization11AuthItemRefC2ERK17AuthorizationItem +__ZN13Authorization8AuthItemC2ERK17AuthorizationItem +__ZNSt8_Rb_treeIN13Authorization11AuthItemRefES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE16_M_insert_uniqueERKS1_ +__ZNSt8_Rb_treeIN13Authorization11AuthItemRefES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE9_M_insertEPSt18_Rb_tree_node_baseS9_RKS1 +__ZNSt8_Rb_treeIN13Authorization11AuthItemRefES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE14_M_create_nodeERKS1_ +__ZN9__gnu_cxx13new_allocatorIN13Authorization11AuthItemRefEE9constructEPS2_RKS2_ +__ZN8Security10RefPointerIN13Authorization8AuthItemEE7releaseEv +__ZN7Session13authGetRightsERKN8Security14SecurityServer17AuthorizationBlobERKN13Authorization11AuthItemSetES8_jRS6_ +__ZN18AuthorizationToken4findERKN8Security14SecurityServer17AuthorizationBlobE +__ZN7Process18checkAuthorizationEP18AuthorizationToken +__ZNSt8_Rb_treeIP18AuthorizationTokenS1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE4findERKS1_ +__ZNK18AuthorizationToken7sessionEv +__ZN7Session13authGetRightsER18AuthorizationTokenRKN13Authorization11AuthItemSetES5_jRS3_ +__ZNK18AuthorizationToken14effectiveCredsEv +__ZNSt8_Rb_treeIN13Authorization11AuthItemRefES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE7_M_copyEPKSt13_Rb_tree_nodeIS1_EPS9_ +__ZNSt6vectorIN13Authorization11AuthItemRefESaIS1_EE6insertEN9__gnu_cxx17__normal_iteratorIPS1_S3_EERKS1_ +__ZNSt6vectorIN13Authorization11AuthItemRefESaIS1_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS1_S3_EERKS1_ +__ZNSt12_Vector_baseIN13Authorization11AuthItemRefESaIS1_EE11_M_allocateEm +__ZSt24__uninitialized_copy_auxIPN13Authorization11AuthItemRefES2_ET0_T_S4_S3_St12__false_type +__ZNK13Authorization20AuthorizationDBPlist7getRuleERKNS_11AuthItemRefE +__ZNKSt8_Rb_treeISsSt4pairIKSsN13Authorization4RuleEESt10_Select1stIS4_ESt4lessISsESaIS4_EE4findERS1_ +__ZN8Security8cfStringEPK7__CFURLb +__ZNK13Authorization8RuleImpl8evaluateERKNS_11AuthItemRefERKNS_4RuleERNS_11AuthItemSetEjdPKSt3setINS_10CredentialESt4lessISA_ES +__ZNK13Authorization8RuleImpl21evaluateMechanismOnlyERKNS_11AuthItemRefERKNS_4RuleERNS_11AuthItemSetER18AuthorizationTokenRSt3s +__ZN13Authorization23AgentMechanismEvaluatorC1EjR7SessionRKSt6vectorISsSaISsEE +__ZN13Authorization23AgentMechanismEvaluatorC2EjR7SessionRKSt6vectorISsSaISsEE +__ZNSt6vectorISsSaISsEEC2ERKS1_ +__ZNSt12_Vector_baseISsSaISsEEC2EmRKS0_ +__ZNSt12_Vector_baseISsSaISsEE11_M_allocateEm +__ZSt24__uninitialized_copy_auxIN9__gnu_cxx17__normal_iteratorIPKSsSt6vectorISsSaISsEEEEPSsET0_T_SA_S9_St12__false_type +__ZN13Authorization12AuthValueRefC1EjPv +__ZN13Authorization12AuthValueRefC2EjPv +__ZN13Authorization9AuthValueC2EjPv +__ZNSt6vectorIN13Authorization12AuthValueRefESaIS1_EE9push_backERKS1_ +__ZNSt6vectorIN13Authorization12AuthValueRefESaIS1_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS1_S3_EERKS1_ +__ZNSt12_Vector_baseIN13Authorization12AuthValueRefESaIS1_EE11_M_allocateEm +__ZSt24__uninitialized_copy_auxIPN13Authorization12AuthValueRefES2_ET0_T_S4_S3_St12__false_type +__ZN9__gnu_cxx13new_allocatorIN13Authorization12AuthValueRefEE9constructEPS2_RKS2_ +__ZNK13Authorization8RuleImpl13setAgentHintsERKNS_11AuthItemRefERKNS_4RuleERNS_11AuthItemSetER18AuthorizationToken +__ZN13Authorization11AuthItemRefC1EPKc +__ZN13Authorization11AuthItemRefC2EPKc +__ZN13Authorization8AuthItemC1EPKc +__ZNSt8_Rb_treeIN13Authorization11AuthItemRefES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE5eraseERKS1_ +__ZNSt8_Rb_treeIN13Authorization11AuthItemRefES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE11upper_boundERKS1_ +__ZNK13Authorization8AuthItemltERKS0_ +__ZNSt8_Rb_treeIN13Authorization11AuthItemRefES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE11lower_boundERKS1_ +__ZNSt8_Rb_treeIN13Authorization11AuthItemRefES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE5eraseESt17_Rb_tree_iteratorIS1_ES9_ +__ZN13Authorization8AuthItemD1Ev +__ZN13Authorization8AuthItemD2Ev +__ZN13Authorization11AuthItemRefC1EPKc18AuthorizationValuej +__ZN13Authorization11AuthItemRefC2EPKc18AuthorizationValuej +__ZN13Authorization8AuthItemC2EPKc18AuthorizationValuej +__Z8codePathPK9__SecCode +__ZN13SecurityAgent6Client11clientHintsENS_13RequestorTypeERSsij +__ZNSt8_Rb_treeIN13Authorization11AuthItemRefES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE16_M_insert_uniqueISt23_Rb_tree_const_ite +__ZNSt8_Rb_treeIN13Authorization11AuthItemRefES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE16_M_insert_uniqueESt17_Rb_tree_iteratorI +__ZNSt8_Rb_treeISsSt4pairIKSsSsESt10_Select1stIS2_ESt4lessISsESaIS2_EEC2ERKS8_ +__ZNSt8_Rb_treeISsSt4pairIKSsSsESt10_Select1stIS2_ESt4lessISsESaIS2_EEaSERKS8_ +__ZNSt8_Rb_treeISsSt4pairIKSsSsESt10_Select1stIS2_ESt4lessISsESaIS2_EE8_M_eraseEPSt13_Rb_tree_nodeIS2_E +__ZNSt8_Rb_treeISsSt4pairIKSsSsESt10_Select1stIS2_ESt4lessISsESaIS2_EED2Ev +__ZNSt8_Rb_treeIN13Authorization11AuthItemRefES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE15_M_destroy_nodeEPSt13_Rb_tree_nodeIS1_E +__ZN13Authorization23AgentMechanismEvaluator3runERKNS_15AuthValueVectorERKNS_11AuthItemSetERK18AuthorizationToken +__ZN8Security14CommonCriteria9Securityd14AuthMechLoggerC1ERKNS0_10AuditTokenEs +__ZN8Security14CommonCriteria9Securityd14AuthMechLoggerC2ERKNS0_10AuditTokenEs +__ZN8Security14CommonCriteria9Securityd11RightLogger8setRightERKSs +__ZN18AuthorizationToken7infoSetEPKc +__ZN13Authorization11AuthItemSetaSERKS0_ +__ZNSt8_Rb_treeIN13Authorization11AuthItemRefES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EEaSERKS7_ +__ZN8Security14CommonCriteria9Securityd14AuthMechLogger19setCurrentMechanismEPKc +__ZNSt8_Rb_treeISsSt4pairIKSsN13Authorization17AgentMechanismRefEESt10_Select1stIS4_ESt4lessISsESaIS4_EE4findERS1_ +__ZN13Authorization17AgentMechanismRefC2E12AuthHostTypeR7Session +__ZN20QueryInvokeMechanismC1E12AuthHostTypeR7Session +__ZN20QueryInvokeMechanismC2E12AuthHostTypeR7Session +__ZN18SecurityAgentQueryC2E12AuthHostTypeR7Session +__ZN23SecurityAgentConnectionC2E12AuthHostTypeR7Session +__ZN13SecurityAgent6ClientC2Ev +__ZN8Security11ThreadNexusIN13SecurityAgent7ClientsEEclEv +__ZN13SecurityAgent7ClientsC2Ev +__ZNK8Security15ThreadStoreSlotaSEPv +__ZN8Security11ModuleNexusINS_5MutexEEclEv +__ZN8Security11ModuleNexusISt3setIPvSt4lessIS2_ESaIS2_EEEclEv +__ZNSt8_Rb_treeIPvS0_St9_IdentityIS0_ESt4lessIS0_ESaIS0_EE16_M_insert_uniqueERKS0_ +__ZNSt8_Rb_treeIPvS0_St9_IdentityIS0_ESt4lessIS0_ESaIS0_EE9_M_insertEPSt18_Rb_tree_node_baseS8_RKS0_ +__ZN13SecurityAgent7Clients6insertEPNS_6ClientE +__ZNSt8_Rb_treeIPN13SecurityAgent6ClientES2_St9_IdentityIS2_ESt4lessIS2_ESaIS2_EE16_M_insert_uniqueERKS2_ +__ZNSt8_Rb_treeIPN13SecurityAgent6ClientES2_St9_IdentityIS2_ESt4lessIS2_ESaIS2_EE9_M_insertEPSt18_Rb_tree_node_baseSA_RKS2_ +__ZN7Session8authhostE12AuthHostTypeb +__ZN16AuthHostInstanceC1ER7Session12AuthHostType +__ZN16AuthHostInstanceC2ER7Session12AuthHostType +__ZN11ServerChildC2Ev +__ZN8Security12UnixPlusPlus5ChildC2Ev +__ZN8Security9ConditionC1ERNS_5MutexE +__ZN8Security9ConditionC2ERNS_5MutexE +__ZN8NodeCore12addReferenceERS_ +__ZNSt8_Rb_treeIN8Security10RefPointerI8NodeCoreEES3_St9_IdentityIS3_ESt4lessIS3_ESaIS3_EE16_M_insert_uniqueERKS3_ +__ZNSt8_Rb_treeIN8Security10RefPointerI8NodeCoreEES3_St9_IdentityIS3_ESt4lessIS3_ESaIS3_EE9_M_insertEPSt18_Rb_tree_node_baseSB_ +__ZNSt8_Rb_treeIN8Security10RefPointerI8NodeCoreEES3_St9_IdentityIS3_ESt4lessIS3_ESaIS3_EE14_M_create_nodeERKS3_ +__ZN9__gnu_cxx13new_allocatorIN8Security10RefPointerI8NodeCoreEEE9constructEPS4_RKS4_ +__Z22initialize_agent_credsv +__ZN20QueryInvokeMechanism10initializeERKSsS1_RKN13Authorization15AuthValueVectorEj +__ZN18SecurityAgentQuery6createEPKcS1_j +__ZN23SecurityAgentConnection8activateEv +__ZNK16AuthHostInstance7sessionEv +__ZN14DynamicSession13copyUserPrefsEv +__ZN16AuthHostInstance6lookupEj +__ZNK7Session11updateAuditEv +__ZN13SecurityAgent6Client8activateEN8Security12MachPlusPlus4PortE +__ZN13SecurityAgent6Client7contactEjN8Security12MachPlusPlus9BootstrapEj +_sa_request_client_contact +__ZN13SecurityAgent6Client6createEPKcS2_j +_sa_request_client_create +__ZN13SecurityAgent6Client7receiveEv +__ZN13SecurityAgent7Clients7receiveEv +__ZN8Security12MachPlusPlus7MessageC1Em +__ZN8Security12MachPlusPlus7Message9setBufferEm +__ZN8Security12MachPlusPlus7Message7receiveEjijj +_secagentreply_server +__ZL11_XdidCreateP17mach_msg_header_tS0_ +__Z25sa_reply_server_didCreatejj +__ZNK13SecurityAgent7Clients4findEj +__ZN13SecurityAgent6Client9didCreateEj +__ZN8Security12MachPlusPlus7MessageD1Ev +__ZN8Security12MachPlusPlus7MessageD2Ev +__ZNSt6vectorIN13Authorization12AuthValueRefESaIS1_EEaSERKS3_ +__ZNSt6vectorIN13Authorization12AuthValueRefESaIS1_EE20_M_allocate_and_copyIN9__gnu_cxx17__normal_iteratorIPKS1_S3_EEEEPS1_mT_S +__ZSt24__uninitialized_copy_auxIN9__gnu_cxx17__normal_iteratorIPKN13Authorization12AuthValueRefESt6vectorIS3_SaIS3_EEEEPS3_ET0_ +__ZNSt4pairIKSsN13Authorization17AgentMechanismRefEEC2ERS0_RKS2_ +__ZNSt8_Rb_treeISsSt4pairIKSsN13Authorization17AgentMechanismRefEESt10_Select1stIS4_ESt4lessISsESaIS4_EE16_M_insert_uniqueERKS4 +__ZNSt8_Rb_treeISsSt4pairIKSsN13Authorization17AgentMechanismRefEESt10_Select1stIS4_ESt4lessISsESaIS4_EE9_M_insertEPSt18_Rb_tre +__ZNSt8_Rb_treeISsSt4pairIKSsN13Authorization17AgentMechanismRefEESt10_Select1stIS4_ESt4lessISsESaIS4_EE14_M_create_nodeERKS4_ +__ZN9__gnu_cxx13new_allocatorISt4pairIKSsN13Authorization17AgentMechanismRefEEE9constructEPS5_RKS5_ +__ZNSt4pairIKSsN13Authorization17AgentMechanismRefEEC2ERKS3_ +__ZNSt4pairIKSsN13Authorization17AgentMechanismRefEED2Ev +__ZN8Security10RefPointerI20QueryInvokeMechanismE7releaseEv +__ZN20QueryInvokeMechanism3runERKN13Authorization15AuthValueVectorERNS0_11AuthItemSetES5_Pj +__ZN13SecurityAgent6Client6invokeEv +__ZN8Security9Allocator8standardEj +__ZN8Security11ModuleNexusI17DefaultAllocatorsEclEv +__ZNK13Authorization11AuthItemSet4copyERP20AuthorizationItemSetRmRN8Security9AllocatorE +__ZN8Security11DataWalkers6CopierI20AuthorizationItemSetEC2EPKS2_RNS_9AllocatorE +__ZN8Security11DataWalkers4walkINS0_10SizeWalkerEEEP20AuthorizationItemSetRT_RS4_ +__ZN8Security11DataWalkers4walkINS0_10SizeWalkerEEEPcRT_RS3_ +__ZN16DefaultAllocator6mallocEm +__ZN8Security11DataWalkers4copyI20AuthorizationItemSetEEPT_PKS3_Pv +__ZN8Security11DataWalkers4walkINS0_10CopyWalkerEEEP20AuthorizationItemSetRT_RS4_ +__ZN8Security11DataWalkers4walkINS0_10CopyWalkerEEEvRT_R17AuthorizationItem +__ZN8Security11DataWalkers4walkINS0_10CopyWalkerEEEPcRT_RS3_ +__ZN16DefaultAllocator4freeEPv +__ZNK13Authorization15AuthValueVector4copyEPP24AuthorizationValueVectorPm +__ZN8Security11DataWalkers6CopierI24AuthorizationValueVectorEC2EPKS2_RNS_9AllocatorE +__ZN8Security11DataWalkers4walkINS0_10SizeWalkerEEEP24AuthorizationValueVectorRT_RS4_ +__ZN8Security11DataWalkers4copyI24AuthorizationValueVectorEEPT_PKS3_Pv +__ZN8Security11DataWalkers4walkINS0_10CopyWalkerEEEP24AuthorizationValueVectorRT_RS4_ +_sa_request_client_invoke +__ZN13SecurityAgent6Client5checkEi +__ZL11_XsetResultP17mach_msg_header_tS0_ +__Z25sa_reply_server_setResultjjP20AuthorizationItemSetjS0_S0_jS0_ +__ZN13SecurityAgent8relocateI20AuthorizationItemSetEEvPT_S3_m +__ZN8Security11DataWalkers4walkIN13SecurityAgent26CheckingReconstituteWalkerEEEP20AuthorizationItemSetRT_RS5_ +__ZN13SecurityAgent26CheckingReconstituteWalker4blobI20AuthorizationItemSetEEvRPT_m +__ZN13SecurityAgent26CheckingReconstituteWalker4blobI17AuthorizationItemEEvRPT_m +__ZN8Security11DataWalkers4walkIN13SecurityAgent26CheckingReconstituteWalkerEEEvRT_R17AuthorizationItem +__ZN13SecurityAgent26CheckingReconstituteWalker4blobIcEEvRPT_m +__ZN13SecurityAgent26CheckingReconstituteWalker4blobIvEEvRPT_m +__ZN13SecurityAgent6Client9setResultEjPK20AuthorizationItemSetS3_ +__ZN13Authorization11AuthItemSetaSERK20AuthorizationItemSet +__ZN8Security14CommonCriteria9Securityd11AuditLogger10logSuccessEv +__ZN8Security14CommonCriteria9Securityd11AuditLogger4openEv +__ZN8Security14CommonCriteria9Securityd14AuthMechLogger11writeCommonEv +__ZN8Security14CommonCriteria9Securityd11AuditLogger12writeSubjectEv +__ZN8Security14CommonCriteria9Securityd11AuditLogger10writeTokenEP8au_tokenPKc +__ZN8NodeCore4killERS_ +__ZN8NodeCore4killEv +__ZN8NodeCore15clearReferencesEv +__ZNSt8_Rb_treeIN8Security10RefPointerI8NodeCoreEES3_St9_IdentityIS3_ESt4lessIS3_ESaIS3_EE5eraseESt23_Rb_tree_const_iteratorIS3 +__ZN8NodeCore15removeReferenceERS_ +__ZNSt8_Rb_treeIN8Security10RefPointerI8NodeCoreEES3_St9_IdentityIS3_ESt4lessIS3_ESaIS3_EE5eraseERKS3_ +__ZNSt8_Rb_treeIN8Security10RefPointerI8NodeCoreEES3_St9_IdentityIS3_ESt4lessIS3_ESaIS3_EE5eraseESt17_Rb_tree_iteratorIS3_ESB_ +__ZNSt8_Rb_treeIN8Security10RefPointerI8NodeCoreEES3_St9_IdentityIS3_ESt4lessIS3_ESaIS3_EE15_M_destroy_nodeEPSt13_Rb_tree_nodeI +__ZN8Security6Thread3runEv +__ZN8Security6Thread6runnerEPv +__ZN8Security12MachPlusPlus10MachServer10LoadThread6actionEv +__ZN8Security12MachPlusPlus10MachServer9addThreadEPNS_6ThreadE +__ZNSt8_Rb_treeIPN8Security6ThreadES2_St9_IdentityIS2_ESt4lessIS2_ESaIS2_EE16_M_insert_uniqueERKS2_ +__ZNSt8_Rb_treeIPN8Security6ThreadES2_St9_IdentityIS2_ESt4lessIS2_ESaIS2_EE9_M_insertEPSt18_Rb_tree_node_baseSA_RKS2_ +__ZN8Security12MachPlusPlus10MachServer15runServerThreadEb +__ZL10_XdecodeDbP17mach_msg_header_tS0_ +__Z20ucsp_server_decodeDbjj13audit_token_tPiPjPvjS2_jS2_j +__ZN7CopyOutC2EPvmPFiP9__rpc_xdrzEbP9cssm_data +__Z25xdr_DLDbFlatIdentifierRefP9__rpc_xdrPPN8Security11DataWalkers18DLDbFlatIdentifierE +__Z22xdr_DLDbFlatIdentifierP9__rpc_xdrPN8Security11DataWalkers18DLDbFlatIdentifierE +_sec_xdr_pointer +_xdr_CSSM_SUBSERVICE_UID +_xdr_CSSM_VERSION +__ZN8Security14DLDbIdentifierC2ERK19cssm_subservice_uidPKcPK16cssm_net_address +__ZN8Security14DLDbIdentifier4ImplC2ERK19cssm_subservice_uidPKcPK16cssm_net_address +__ZN8Security6DbNameC1EPKcPK16cssm_net_address +__ZN8Security6DbNameC2EPKcPK16cssm_net_address +__ZN8Security6DbName16CanonicalizeNameEv +__Z8makeBlobIN8Security14SecurityServer6DbBlobEEPKT_RKNS0_8CssmDataEi +__ZN16KeychainDatabaseC1ERKN8Security14DLDbIdentifierEPKNS0_14SecurityServer6DbBlobER7ProcessPKNS0_17AccessCredentialsE +__ZN17SecurityServerAclC2Ev +__ZN8Security9ObjectAclC2ERNS_9AllocatorE +__ZN13LocalDatabaseC2ER7Process +__ZN8DatabaseC2ER7Process +__ZN16KeychainDatabase12validateBlobEPKN8Security14SecurityServer6DbBlobE +__ZNK8Security14SecurityServer10CommonBlob8validateEi +__ZN8Security11DataWalkers4copyINS_17AccessCredentialsEEEPT_PKS3_RNS_9AllocatorE +__ZN8Security9Allocator6mallocINS_14SecurityServer6DbBlobEEEPT_m +__ZNK8Database7processEv +__ZN8NodeCore9findFirstI16KeychainDbCommonRK12DbIdentifierEEN8Security10RefPointerIT_EEMS7_KFT0_vES9_ +__ZNK16KeychainDbCommon10identifierEv +__ZNK12DbIdentifiereqERKS_ +__ZNK8Security14DLDbIdentifiereqERKS0_ +__ZNK8Security14DLDbIdentifier4ImpleqERKS1_ +__ZNK8Security17CssmSubserviceUideqERK19cssm_subservice_uid +__ZN8Security10RefPointerI16KeychainDbCommonE7releaseEv +__ZN8Security10RefPointerINS_14DLDbIdentifier4ImplEE7releaseEv +__ZN8Security6DbNameD1Ev +__ZN8Security6DbNameD2Ev +__ZN7CopyOutD1Ev +__ZN7CopyOutD2Ev +__ZL16_XauthenticateDbP17mach_msg_header_tS0_ +__Z26ucsp_server_authenticateDbjj13audit_token_tPijjPvj +_xdr_CSSM_ACCESS_CREDENTIALS_PTR +_xdr_CSSM_ACCESS_CREDENTIALS +_xdr_CSSM_BASE_CERTS +_sec_xdr_clip_long +_xdr_CSSM_CERTGROUP +_xdr_CSSM_SAMPLE +_xdr_CSSM_LIST +_xdr_CSSM_LIST_ELEMENT +__ZN6Server8databaseEj +__ZN6Server4findI8DatabaseEEN8Security10RefPointerIT_EEji +__ZN8Security13MappingHandleIjE7findRefI8DatabaseEENS_10RefPointerIT_EEji +__ZN8Security13MappingHandleIjE5State6locateEji +__ZN16KeychainDatabase12authenticateEjPKN8Security17AccessCredentialsE +__ZN8Security11DataWalkers14enumerateArrayINS0_10SizeWalkerENS_11SampleGroupENS_10CssmSampleEEEvRT_RT0_MS7_FRPT1_vE +__ZN8Security11SampleGroup7samplesEv +__ZN8Security11DataWalkers4walkINS0_10SizeWalkerEEEvRT_RNS_10CssmSampleE +__ZN8Security11DataWalkers4walkINS0_10SizeWalkerEEEPNS_11ListElementERT_RS4_ +__ZN8Security11DataWalkers4copyINS_17AccessCredentialsEEEPT_PKS3_RNS_9AllocatorEm +__ZN8Security11DataWalkers4copyINS_17AccessCredentialsEEEPT_PKS3_Pv +__ZN8Security11DataWalkers4walkINS0_10CopyWalkerEEEPNS_17AccessCredentialsERT_RS4_ +__ZN8Security11DataWalkers14enumerateArrayINS0_10CopyWalkerENS_11SampleGroupENS_10CssmSampleEEEvRT_RT0_MS7_FRPT1_vE +__ZN8Security11DataWalkers4walkINS0_10CopyWalkerEEEvRT_RNS_10CssmSampleE +__ZN8Security11DataWalkers9enumerateINS0_10CopyWalkerEEEvRT_RNS_8CssmListE +__ZN8Security11DataWalkers4walkINS0_10CopyWalkerEEEPNS_11ListElementERT_RS4_ +__ZN8Security11ListElement4lastEv +__ZN8Security10RefPointerI8DatabaseE7releaseEv +__ZL11_XreleaseDbP17mach_msg_header_tS0_ +__Z21ucsp_server_releaseDbjj13audit_token_tPij +__ZN16KeychainDatabaseD0Ev +__ZN8Security10RefPointerI16KeychainDatabaseE7releaseEv +__ZN8DatabaseD2Ev +__ZN9AclSourceD2Ev +__ZN10PerProcessD2Ev +__ZN8Security13MappingHandleIjED2Ev +__ZN9__gnu_cxx9hashtableISt4pairIKjPN8Security13MappingHandleIjEEEjNS_4hashIjEESt10_Select1stIS7_ESt8equal_toIjESaIS6_EE5eraseE +__ZN17SecurityServerAclD2Ev +__ZN8Security5MutexD1Ev +__ZN8Security9ObjectAclD2Ev +__ZN8Security10RefPointerINS_10AclSubjectEE7releaseEv +__ZNSt8_Rb_treeISsSt4pairIKSsN8Security9ObjectAcl8AclEntryEESt10_Select1stIS5_ESt4lessISsESaIS5_EED2Ev +__ZNSt8_Rb_treeISsSt4pairIKSsN8Security9ObjectAcl8AclEntryEESt10_Select1stIS5_ESt4lessISsESaIS5_EE8_M_eraseEPSt13_Rb_tree_nodeI +__ZL13_XsetupThreadP17mach_msg_header_tS0_ +__Z23ucsp_server_setupThreadjj13audit_token_tPij +__ZNSt8_Rb_treeIN8Security12MachPlusPlus4PortESt4pairIKS2_NS0_10RefPointerI7ProcessEEESt10_Select1stIS8_ESt4lessIS2_ESaIS8_EE4f +__ZNSt8_Rb_treeIiSt4pairIKiP7ProcessESt10_Select1stIS4_ESt4lessIiESaIS4_EE5eraseERS1_ +__ZNSt8_Rb_treeIiSt4pairIKiP7ProcessESt10_Select1stIS4_ESt4lessIiESaIS4_EE5eraseESt17_Rb_tree_iteratorIS4_ESC_ +__ZNSt8_Rb_treeIN8Security12MachPlusPlus4PortESt4pairIKS2_NS0_10RefPointerI7ProcessEEESt10_Select1stIS8_ESt4lessIS2_ESaIS8_EE15 +__ZN7Process4killEv +__ZN8Security10RefPointerI13LocalDatabaseE10setPointerEPS1_ +__ZN8Security10RefPointerI13LocalDatabaseE7releaseEv +__ZN8Security12MachPlusPlus10MachServer4idleEv +__ZN7ProcessD0Ev +__ZNSt8_Rb_treeIP18AuthorizationTokenS1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE8_M_eraseEPSt13_Rb_tree_nodeIS1_E +__ZN20ClientIdentificationD2Ev +__ZNSt8_Rb_treeIjSt4pairIKjN20ClientIdentification10GuestStateEESt10_Select1stIS4_ESt4lessIjESaIS4_EED2Ev +__ZN14CodeSignatures8IdentityD2Ev +__ZN15CodeSigningHostD2Ev +__ZN15CodeSigningHost5resetEv +__ZNSt8_Rb_treeIjSt4pairIKjN8Security10RefPointerIN15CodeSigningHost5GuestEEEESt10_Select1stIS7_ESt4lessIjESaIS7_EED2Ev +__ZNSt8_Rb_treeIjSt4pairIKjN8Security10RefPointerIN15CodeSigningHost5GuestEEEESt10_Select1stIS7_ESt4lessIjESaIS7_EE8_M_eraseEPS +__ZN8Security12MachPlusPlus10MachServer7HandlerD2Ev +__ZN8Security14CommonCriteria9Securityd14AuthMechLoggerD2Ev +__ZN18AuthorizationToken10setInfoSetERN13Authorization11AuthItemSetEb +__ZN13Authorization11AuthItemSet4findEPKc +__ZN7Session13setAttributesEj +__ZN8Security14CommonCriteria9AuditInfo3setEv +__ZNK13Authorization8RuleImpl15makeCredentialsERK18AuthorizationToken +__ZNK13Authorization8AuthItem11stringValueEv +__ZN13Authorization10CredentialC1EjRKSsS2_S2_b +__ZN13Authorization10CredentialC2EjRKSsS2_S2_b +__ZN13Authorization14CredentialImplC2EjRKSsS2_S2_b +__ZNSt8_Rb_treeIN13Authorization10CredentialES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE16_M_insert_uniqueERKS1_ +__ZNSt8_Rb_treeIN13Authorization10CredentialES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE9_M_insertEPSt18_Rb_tree_node_baseS9_RKS1_ +__ZNSt8_Rb_treeIN13Authorization10CredentialES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE14_M_create_nodeERKS1_ +__ZN9__gnu_cxx13new_allocatorIN13Authorization10CredentialEE9constructEPS2_RKS2_ +__ZN13Authorization10CredentialD1Ev +__ZN8Security10RefPointerIN13Authorization14CredentialImplEE7releaseEv +__ZNSt8_Rb_treeIN13Authorization10CredentialES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE16_M_insert_uniqueISt23_Rb_tree_const_iter +__ZNSt8_Rb_treeIN13Authorization10CredentialES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE16_M_insert_uniqueESt17_Rb_tree_iteratorIS +__ZNSt8_Rb_treeIN13Authorization10CredentialES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE15_M_destroy_nodeEPSt13_Rb_tree_nodeIS1_E +__ZNSt6vectorIN13Authorization12AuthValueRefESaIS1_EED2Ev +__ZN8Security10RefPointerIN13Authorization9AuthValueEE7releaseEv +__ZN13Authorization23AgentMechanismEvaluatorD2Ev +__ZNSt8_Rb_treeISsSt4pairIKSsN13Authorization17AgentMechanismRefEESt10_Select1stIS4_ESt4lessISsESaIS4_EED2Ev +__ZNSt8_Rb_treeISsSt4pairIKSsN13Authorization17AgentMechanismRefEESt10_Select1stIS4_ESt4lessISsESaIS4_EE8_M_eraseEPSt13_Rb_tree +__ZNSt8_Rb_treeISsSt4pairIKSsN13Authorization17AgentMechanismRefEESt10_Select1stIS4_ESt4lessISsESaIS4_EE15_M_destroy_nodeEPSt13 +__ZN20QueryInvokeMechanismD0Ev +__ZN18SecurityAgentQueryD2Ev +__ZN13SecurityAgent6Client7destroyEv +_sa_request_client_destroy +__ZN23SecurityAgentConnectionD2Ev +__ZN8Security10RefPointerI16AuthHostInstanceE7releaseEv +__ZN16AuthHostInstanceD0Ev +__ZN11ServerChildD2Ev +__ZN8Security9ConditionD1Ev +__ZN8Security9ConditionD2Ev +__ZN8Security12UnixPlusPlus5ChildD2Ev +__ZN13SecurityAgent6ClientD2Ev +__ZN13SecurityAgent6Client8teardownEv +__ZN13SecurityAgent7Clients6removeEPNS_6ClientE +__ZNSt8_Rb_treeIPN13SecurityAgent6ClientES2_St9_IdentityIS2_ESt4lessIS2_ESaIS2_EE5eraseERKS2_ +__ZNSt8_Rb_treeIPN13SecurityAgent6ClientES2_St9_IdentityIS2_ESt4lessIS2_ESaIS2_EE5eraseESt17_Rb_tree_iteratorIS2_ESA_ +__ZNSt8_Rb_treeIPN13SecurityAgent6ClientES2_St9_IdentityIS2_ESt4lessIS2_ESaIS2_EE8_M_eraseEPSt13_Rb_tree_nodeIS2_E +__ZN13Authorization9AuthValueD1Ev +__ZN13Authorization9AuthValueD2Ev +__ZNSt6vectorISsSaISsEED2Ev +__ZN8Security14CommonCriteria9Securityd11RightLogger8setRightEPKc +__ZN8Security14CommonCriteria9Securityd25RightAuthenticationLogger22logAuthorizationResultEPKcS4_i +__ZN8Security14CommonCriteria9Securityd25RightAuthenticationLogger11writeCommonEv +__ZN8Security6Syslog4infoEPKcz +__ZN8Security10RefPointerIN13Authorization8RuleImplEE7releaseEv +__ZN7Session16mergeCredentialsERSt3setIN13Authorization10CredentialESt4lessIS2_ESaIS2_EE +__ZNSt8_Rb_treeIN13Authorization10CredentialES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE7_M_copyEPKSt13_Rb_tree_nodeIS1_EPS9_ +__ZNK13Authorization14CredentialImpl8isSharedEv +__ZNK13Authorization14CredentialImpl7isValidEv +__ZNSt8_Rb_treeIN13Authorization10CredentialES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE4findERKS1_ +__ZN18AuthorizationToken16mergeCredentialsERKSt3setIN13Authorization10CredentialESt4lessIS2_ESaIS2_EE +__ZNSt8_Rb_treeIN13Authorization10CredentialES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE5eraseERKS1_ +__ZNSt8_Rb_treeIN13Authorization10CredentialES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE11upper_boundERKS1_ +__ZNSt8_Rb_treeIN13Authorization10CredentialES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE11lower_boundERKS1_ +__ZNSt8_Rb_treeIN13Authorization10CredentialES1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE5eraseESt17_Rb_tree_iteratorIS1_ES9_ +__ZNK13Authorization11AuthItemSet4copyEv +_copyin_AuthorizationItemSet +_copyin +_sec_xdr_sizeof_in +_sec_x_putlong +_sec_x_putbytes +_sec_xdrmem_putlong_aligned +_sec_xdrmem_putbytes +__ZN6Server15releaseWhenDoneEPv +__ZN8Security12MachPlusPlus10MachServer15releaseWhenDoneERNS_9AllocatorEPv +__ZNSt8_Rb_treeIN8Security12MachPlusPlus10MachServer10AllocationES3_St9_IdentityIS3_ESt4lessIS3_ESaIS3_EE16_M_insert_uniqueERKS +__ZNSt8_Rb_treeIN8Security12MachPlusPlus10MachServer10AllocationES3_St9_IdentityIS3_ESt4lessIS3_ESaIS3_EE9_M_insertEPSt18_Rb_tr +__ZL23_XauthorizationCopyInfoP17mach_msg_header_tS0_ +__Z33ucsp_server_authorizationCopyInfojj13audit_token_tPiN8Security14SecurityServer17AuthorizationBlobEPKcPPvPj +__ZN7Session11authGetInfoERKN8Security14SecurityServer17AuthorizationBlobEPKcRN13Authorization11AuthItemSetE +__ZN16KeychainDbCommonC2ER7SessionRK12DbIdentifier +__ZN13LocalDbCommonC2ER7Session +__ZN8DbCommonC2ER7Session +__ZN18DatabaseCryptoCoreC2Ev +__ZN8NodeCore9findFirstI16KeychainDbGlobalRK12DbIdentifierEEN8Security10RefPointerIT_EEMS7_KFT0_vES9_ +__ZN8Security10RefPointerI16KeychainDbGlobalE7releaseEv +__ZN16KeychainDbGlobalC2ERK12DbIdentifier +__ZNK8DbCommon7sessionEv +__ZL24_XunlockDbWithPassphraseP17mach_msg_header_tS0_ +__Z34ucsp_server_unlockDbWithPassphrasejj13audit_token_tPijPvj +__ZN6Server8keychainEj +__ZN6Server4findI16KeychainDatabaseEEN8Security10RefPointerIT_EEji +__ZN8Security13MappingHandleIjE7findRefI16KeychainDatabaseEENS_10RefPointerIT_EEji +__ZN16KeychainDatabase8unlockDbERKN8Security8CssmDataE +__ZN16KeychainDatabase12makeUnlockedERKN8Security8CssmDataE +__ZN16KeychainDatabase8isLockedEv +__ZN18DatabaseCryptoCore5setupEPKN8Security14SecurityServer6DbBlobERKNS0_8CssmDataE +__ZNK18DatabaseCryptoCore17deriveDbMasterKeyERKN8Security8CssmDataE +__ZN8Security10CssmClient9DeriveKeyC1ERKNS0_3CSPEjjj +__ZN8Security10CssmClient5CryptC2ERKNS0_3CSPEj +__ZN8Security10CssmClient7ContextC2ERKNS0_3CSPEj +__ZN8Security10CssmClient10ObjectImplC2ERKNS0_6ObjectE +__ZN8Security10CssmClient9DeriveKeyclEPNS_8CssmDataERKNS0_7KeySpecE +__ZN8Security10CssmClient3Key10makeNewKeyERKNS0_3CSPE +__ZN8Security10CssmClient3KeyC2ERKNS0_3CSPE +__ZN8Security10CssmClient7KeyImplC1ERKNS0_3CSPE +__ZN8Security10RefPointerINS_10CssmClient10ObjectImplEE10setPointerEPS2_ +__ZN8Security10RefPointerINS_10CssmClient10ObjectImplEE7releaseEv +__ZNK8Security10CssmClient6Object4implINS0_7KeyImplEEERT_v +__ZNK8Security10CssmClient9RccBearer12compositeRccEv +__ZN8Security10CssmClient9DeriveKey8activateEv +__ZNK8Security10CssmClient6Object4implINS0_7CSPImplEEERT_v +__ZN8Security10CssmClient14AttachmentImpl8activateEv +__ZN8Security28CssmAllocatorMemoryFunctions11relayMallocEmPv +__ZN8Security28CssmAllocatorMemoryFunctions9relayFreeEPvS1_ +__ZN8Security10CssmClient10ObjectImpl5checkEi +__ZN8Security10CssmClient7KeyImpl8activateEv +__ZN8Security10CssmClient5CryptD2Ev +__ZN8Security10CssmClient7ContextD2Ev +__ZN8Security10CssmClient7Context10deactivateEv +__ZN8Security10CssmClient10ObjectImplD2Ev +__ZN16KeychainDatabase6decodeEv +__ZN16KeychainDbCommon8unlockDbEPN8Security14SecurityServer6DbBlobEPPv +__ZN18DatabaseCryptoCore10decodeCoreEPKN8Security14SecurityServer6DbBlobEPPv +__ZN8Security10CssmClient7DecryptC1ERKNS0_3CSPEj +__ZN8Security10CssmClient7Context3setEjj +__ZN8Security10CssmClient5Crypt3keyERKNS0_3KeyE +__ZN8Security10CssmClient7Context3setINS_7CssmKeyEEEvjRKT_ +__ZN8Security10CssmClient7Context3setINS_8CssmDataEEEvjRKT_ +__ZN8Security10CssmClient7Decrypt7decryptEPKNS_8CssmDataEjPS2_jRS2_ +__ZN8Security10CssmClient7Context8unstagedEv +__ZN8Security10CssmClient5Crypt8activateEv +__ZN18DatabaseCryptoCore10makeRawKeyEPvmjj +__ZN8Security10CssmClient9UnwrapKeyC1ERKNS0_3CSPEj +__ZN8Security10CssmClient9UnwrapKeyclERKNS_7CssmKeyERKNS0_7KeySpecERS2_PNS_8CssmDataEPS3_ +__ZN8Security10CssmClient3KeyC2ERKNS0_3CSPERK8cssm_keyb +__ZN8Security10CssmClient7KeyImplC1ERKNS0_3CSPERK8cssm_keyb +__ZN8Security7CssmKeyC2ERK8cssm_key +__ZN8Security10CssmClient9VerifyMacC1ERKNS0_3CSPEj +__ZN8Security10CssmClient7Context3setINS0_3KeyEEEvjRKT_ +__ZN8Security10CssmClient9VerifyMac6verifyEPKNS_8CssmDataEjRS3_ +__ZN8Security10CssmClient10MacContext8activateEv +__ZN8Security10CssmClient10MacContextD2Ev +__ZN16KeychainDbCommon8activityEv +__ZN8Security12MachPlusPlus10MachServer8setTimerEPNS1_5TimerENS_4Time8AbsoluteE +__ZN8Security13ScheduleQueueINS_4Time8AbsoluteEE8scheduleEPNS3_5EventES2_ +__ZN8DbCommon6notifyEjRKN8Security14DLDbIdentifierE +__ZN8Security19NameValueDictionaryC1Ev +__ZN8Security19NameValueDictionary41MakeNameValueDictionaryFromDLDbIdentifierERKNS_14DLDbIdentifierERS0_ +__ZN8Security13NameValuePair9CloneDataERKNS_8CssmDataE +__ZNSt6vectorIPN8Security13NameValuePairESaIS2_EE9push_backERKS2_ +__ZNSt6vectorIPN8Security13NameValuePairESaIS2_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS2_S4_EERKS2_ +__ZNSt12_Vector_baseIPN8Security13NameValuePairESaIS2_EE11_M_allocateEm +__ZN8Security19NameValueDictionary6ExportERNS_8CssmDataE +__ZNK8Security13NameValuePair6ExportERNS_8CssmDataE +__ZN8Listener6notifyEjjRKN8Security8CssmDataE +__ZN8Listener12NotificationC2EjjjRKN8Security8CssmDataE +__ZN8Security12CssmAutoDataC2INS_8CssmDataEEERNS_9AllocatorERKT_ +__ZN8Security13CssmOwnedData4copyIvEEvPKT_m +__ZN8Security12CssmAutoData5resetEv +__ZN8Security11CssmAutoPtrIvED1Ev +__ZN8Listener16sendNotificationEPNS_12NotificationE +__ZN20SharedMemoryListener8notifyMeEPN8Listener12NotificationE +__ZNK8Security13CssmOwnedData3getEv +__ZN18SharedMemoryServer12WriteMessageEjjPKvj +_CalculateCRC +__ZN18SharedMemoryServer9WriteDataEPKvj +__ZN8Security10RefPointerIN8Listener12NotificationEE7releaseEv +__ZN8Listener12NotificationD0Ev +__ZN8Security12CssmAutoDataD2Ev +__ZN8Security15CssmManagedDataD2Ev +__ZN8Security19NameValueDictionaryD1Ev +__ZN8Security19NameValueDictionaryD2Ev +__ZN16KeychainDatabase3aclEv +__ZN8Security9ObjectAcl10importBlobEPKvS2_ +__ZN8Security9ObjectAcl13importSubjectERNS_23LowLevelMemoryUtilities6ReaderES3_ +__ZN8Security9ObjectAcl8makerForEi +__ZN8Security11ModuleNexusISt3mapIiPNS_10AclSubject5MakerESt4lessIiESaISt4pairIKiS4_EEEEclEv +__ZNSt3mapIiPN8Security10AclSubject5MakerESt4lessIiESaISt4pairIKiS3_EEEixERS7_ +__ZNK8Security13AnyAclSubject5Maker4makeEhRNS_23LowLevelMemoryUtilities6ReaderES4_ +__ZN8Security10AclSubjectC2Ejh +__ZN8Security10RefPointerINS_10AclSubjectEE10setPointerEPS1_ +__ZNSt8_Rb_treeISsSt4pairIKSsN8Security9ObjectAcl8AclEntryEESt10_Select1stIS5_ESt4lessISsESaIS5_EE5eraseESt17_Rb_tree_iteratorI +__ZN8Security9ObjectAcl8AclEntryC2Ev +__ZN8Security9ObjectAcl8AclEntry10importBlobERNS_23LowLevelMemoryUtilities6ReaderES4_ +__ZNSt8_Rb_treeIiiSt9_IdentityIiESt4lessIiESaIiEE5eraseESt23_Rb_tree_const_iteratorIiES7_ +__ZNSt8_Rb_treeIiiSt9_IdentityIiESt4lessIiESaIiEE8_M_eraseEPSt13_Rb_tree_nodeIiE +__ZN8Security9ObjectAcl3addERKSsRKNS0_8AclEntryE +__ZN8Security9ObjectAcl8AclEntryC2ERKS1_ +__ZNSt8_Rb_treeIiiSt9_IdentityIiESt4lessIiESaIiEEC2ERKS5_ +__ZN8Security9ObjectAcl3addERKSsNS0_8AclEntryEl +__ZNSt4pairISsN8Security9ObjectAcl8AclEntryEEC2ERKSsRKS2_ +__ZNSt4pairIKSsN8Security9ObjectAcl8AclEntryEEC2ISsS3_EERKS_IT_T0_E +__ZNSt8_Rb_treeISsSt4pairIKSsN8Security9ObjectAcl8AclEntryEESt10_Select1stIS5_ESt4lessISsESaIS5_EE15_M_insert_equalERKS5_ +__ZNSt8_Rb_treeISsSt4pairIKSsN8Security9ObjectAcl8AclEntryEESt10_Select1stIS5_ESt4lessISsESaIS5_EE9_M_insertEPSt18_Rb_tree_node +__ZNSt8_Rb_treeISsSt4pairIKSsN8Security9ObjectAcl8AclEntryEESt10_Select1stIS5_ESt4lessISsESaIS5_EE14_M_create_nodeERKS5_ +__ZN9__gnu_cxx13new_allocatorISt4pairIKSsN8Security9ObjectAcl8AclEntryEEE9constructEPS6_RKS6_ +__ZNSt4pairIKSsN8Security9ObjectAcl8AclEntryEEC2ERKS4_ +__ZNSt4pairIKSsN8Security9ObjectAcl8AclEntryEED2Ev +__ZN8Security9ObjectAcl8AclEntryD2Ev +__ZNSt4pairISsN8Security9ObjectAcl8AclEntryEED2Ev +__ZN8Security13AnyAclSubjectD0Ev +__ZN8Security10AclSubjectD2Ev +__ZNSt8_Rb_treeISsSt4pairIKSsN8Security9ObjectAcl8AclEntryEESt10_Select1stIS5_ESt4lessISsESaIS5_EE15_M_destroy_nodeEPSt13_Rb_tr +__ZN8Security13ScheduleQueueINS_4Time8AbsoluteEE5Event10unscheduleEv +__ZN8Security12MachPlusPlus10MachServer5Timer6selectEv +__ZThn88_N20SharedMemoryListener6actionEv +__ZN20SharedMemoryListener6actionEv +__ZN8Security12MachPlusPlus10MachServer5Timer8unselectEv +__ZL21_XsetSessionUserPrefsP17mach_msg_header_tS0_ +__Z31ucsp_server_setSessionUserPrefsjj13audit_token_tPijPvj +__ZN7Session4findI14DynamicSessionEERT_j +__ZN6Server7sessionEv +__ZN14DynamicSession12setUserPrefsEPK8__CFData +__ZN8Security5CFRefIPK8__CFDataEaSES3_ +__ZN20QueryInvokeMechanism14terminateAgentEv +__ZN18SecurityAgentQuery9terminateEv +__ZN23SecurityAgentConnection9terminateEv +__ZN13SecurityAgent6Client9terminateEv +_sa_request_client_terminate +__ZN20QueryInvokeMechanismD2Ev +__ZNK13Authorization10CredentialltERKS0_ +__ZNK13Authorization14CredentialImplltERKS0_ +__ZN13Authorization14CredentialImpl5mergeERKS0_ +__ZN13Authorization14CredentialImplD1Ev +__ZN13Authorization14CredentialImplD2Ev +__ZL11_XdecodeKeyP17mach_msg_header_tS0_ +__Z21ucsp_server_decodeKeyjj13audit_token_tPiPjPPvS1_jS2_j +__Z8makeBlobIN8Security14SecurityServer7KeyBlobEEPKT_RKNS0_8CssmDataEi +__ZN11KeychainKeyC1ER8DatabasePKN8Security14SecurityServer7KeyBlobE +__ZN11KeychainKeyC2ER8DatabasePKN8Security14SecurityServer7KeyBlobE +__ZN8LocalKeyC2ER8Databasej +__ZN3KeyC2ER8Database +__ZN8Database10SubsidiaryC2ERS_ +__ZNK8Security10CssmClient10ObjectImpl9allocatorEv +__ZN8Security9Allocator6mallocINS_14SecurityServer7KeyBlobEEEPT_m +__ZN8LocalKey9returnKeyERjRN8Security7CssmKey6HeaderE +__ZN11KeychainKey9getHeaderERN8Security7CssmKey6HeaderE +__ZN8Security4n2hiERNS_7CssmKey6HeaderE +_xdr_CSSM_KEYHEADER +__ZN8Security10RefPointerI3KeyE7releaseEv +__ZL9_XdecryptP17mach_msg_header_tS0_ +__Z19ucsp_server_decryptjj13audit_token_tPiPvjjS1_jPS1_Pj +_xdr_CSSM_CONTEXT_PTR +_xdr_CSSM_CONTEXT +_xdr_CSSM_CONTEXT_ATTRIBUTE +_xdr_CSSM_KEY +_xdr_CSSM_DATA +__ZN6Server3keyEj +__ZN8Security13MappingHandleIjE7findRefI3KeyEENS_10RefPointerIT_EEji +__ZN13LocalDatabase7decryptERKN8Security7ContextER3KeyRKNS0_8CssmDataERS6_ +__ZN8LocalKey7cssmKeyEv +__ZN8LocalKey8keyValueEv +__ZN11KeychainKey6getKeyEv +__ZN11KeychainKey6decodeEv +__ZN16KeychainDatabase9decodeKeyEPN8Security14SecurityServer7KeyBlobERNS0_7CssmKeyERPvS7_ +__ZN8Security14SecurityServer7KeyBlob11isClearTextEv +__ZN16KeychainDatabase8unlockDbEv +__ZN16KeychainDatabase12makeUnlockedEPKN8Security17AccessCredentialsE +__ZN8Security10CssmClient7KeyImplD0Ev +__ZN8Security10CssmClient7KeyImpl10deactivateEv +__ZN8Security10CssmClient9AclBearerD2Ev +__ZNK18DatabaseCryptoCore13decodeKeyCoreEPN8Security14SecurityServer7KeyBlobERNS0_7CssmKeyERPvS7_ +__ZN8Security4h2niERNS_7CssmKey6HeaderE +__ZN8Security10CssmClient9UnwrapKeyclERKNS_7CssmKeyERKNS0_7KeySpecERS2_PNS_8CssmDataE +__ZN11KeychainKey3aclEv +__ZNK8Security19ThresholdAclSubject5Maker4makeEhRNS_23LowLevelMemoryUtilities6ReaderES4_ +__ZNSt6vectorIN8Security10RefPointerINS0_10AclSubjectEEESaIS3_EEC2EmRKS3_RKS4_ +__ZNSt12_Vector_baseIN8Security10RefPointerINS0_10AclSubjectEEESaIS3_EEC2EmRKS4_ +__ZNSt12_Vector_baseIN8Security10RefPointerINS0_10AclSubjectEEESaIS3_EE11_M_allocateEm +__ZSt26__uninitialized_fill_n_auxIPN8Security10RefPointerINS0_10AclSubjectEEEmS3_EvT_T0_RKT1_St12__false_type +__ZNK24KeychainPromptAclSubject5Maker4makeEhRN8Security23LowLevelMemoryUtilities6ReaderES4_ +__ZN24KeychainPromptAclSubjectC2ESsRK33cssm_acl_keychain_prompt_selector +__ZN8Security19ThresholdAclSubjectC2EjjRKSt6vectorINS_10RefPointerINS_10AclSubjectEEESaIS4_EE +__ZNSt6vectorIN8Security10RefPointerINS0_10AclSubjectEEESaIS3_EEC2ERKS5_ +__ZSt24__uninitialized_copy_auxIN9__gnu_cxx17__normal_iteratorIPKN8Security10RefPointerINS2_10AclSubjectEEESt6vectorIS5_SaIS5_E +__ZNSt6vectorIN8Security10RefPointerINS0_10AclSubjectEEESaIS3_EED2Ev +__ZNK8Security23CodeSignatureAclSubject5Maker4makeEhRNS_23LowLevelMemoryUtilities6ReaderES4_ +__ZNK8Security23CodeSignatureAclSubject5Maker4makeEPKhRKNS_8CssmDataE +__ZN8Security23CodeSignatureAclSubjectC2EPKhRKSs +__ZN8Security11OSXVerifierC2EPKhRKSs +__ZN8Security11OSXVerifier3addEPKNS_8BlobCoreE +__ZNSt8_Rb_treeIiiSt9_IdentityIiESt4lessIiESaIiEE16_M_insert_uniqueERKi +__ZNSt8_Rb_treeIiiSt9_IdentityIiESt4lessIiESaIiEE9_M_insertEPSt18_Rb_tree_node_baseS7_RKi +__ZNSt8_Rb_treeIiiSt9_IdentityIiESt4lessIiESaIiEE7_M_copyEPKSt13_Rb_tree_nodeIiEPS7_ +__ZNK8Security7Context7replaceINS_7CssmKeyEEEvjRKT_ +__ZN8Security7Context4findEjPK22cssm_context_attributej +__ZN9AclSource8validateEiRKN8Security7ContextE +__ZThn160_N11KeychainKey15relatedDatabaseEv +__ZThn160_N11KeychainKey3aclEv +__ZN17SecurityServerAcl8validateEiRKN8Security7ContextEP8Database +__ZThn232_N11KeychainKey8validateEiPKN8Security17AccessCredentialsEP8Database +__ZN11KeychainKey8validateEiPKN8Security17AccessCredentialsEP8Database +__ZN17SecurityServerAcl8validateEiPKN8Security17AccessCredentialsEP8Database +__ZN25SecurityServerEnvironmentC1ER17SecurityServerAclP8Database +__ZN8Security9ObjectAcl8validateEiPKNS_17AccessCredentialsEPNS_24AclValidationEnvironmentE +__ZN8Security9ObjectAcl9validatesEiPKNS_17AccessCredentialsEPNS_24AclValidationEnvironmentE +__ZN8Security9ObjectAcl9validatesERNS_20AclValidationContextE +__ZThn232_N11KeychainKey14instantiateAclEv +__ZN11KeychainKey14instantiateAclEv +__ZNK8Security20AclValidationContext9s_credTagEv +__ZNK8Security20AclValidationContext7credTagEv +__ZNK8Security9ObjectAcl8getRangeERKSsRSt4pairISt23_Rb_tree_const_iteratorIS3_IS1_NS0_8AclEntryEEES7_E +__ZNKSt8_Rb_treeIiiSt9_IdentityIiESt4lessIiESaIiEE4findERKi +__ZN8Security20AclValidationContext4initEPNS_9ObjectAclEPNS_10AclSubjectE +__ZN8Security20AclValidationContext8entryTagERKSs +__ZNK8Security16SimpleAclSubject8validateERKNS_20AclValidationContextE +__ZNK21BaseValidationContext5countEv +__ZNK21BaseValidationContext6sampleEj +__ZNK8Security9TypedList8isProperEv +__ZNK8Security11ListElement4wordEv +__ZNK8Security19ThresholdAclSubject8validateERKNS_20AclValidationContextERKNS_9TypedListE +__ZNK8Security23CodeSignatureAclSubject8validateERKNS_20AclValidationContextE +__ZTv0_n48_N25SecurityServerEnvironment19verifyCodeSignatureERKN8Security11OSXVerifierERKNS0_20AclValidationContextE +__ZN14CodeSignatures6verifyER7ProcessRKN8Security11OSXVerifierERKNS2_20AclValidationContextE +__ZN8Security20AclValidationContextD2Ev +__ZNK21BaseValidationContext7matchedEPKN8Security9TypedListE +__ZN25SecurityServerEnvironmentD1Ev +__ZN8Security24AclValidationEnvironmentD2Ev +__ZNK16KeychainDatabase6commonEv +__ZN8Security10CssmClient7Context8overrideERKNS_7ContextE +__ZL12_XreleaseKeyP17mach_msg_header_tS0_ +__Z22ucsp_server_releaseKeyjj13audit_token_tPij +__ZN8Database10releaseKeyER3Key +__ZN11KeychainKeyD0Ev +__ZN8Security19ThresholdAclSubjectD0Ev +__ZN24KeychainPromptAclSubjectD0Ev +__ZN8Security23CodeSignatureAclSubjectD0Ev +__ZN8Security11OSXVerifierD2Ev +__ZN8Security11OSXVerifier6AuxMapD2Ev +__ZNSt8_Rb_treeIjSt4pairIKjPN8Security8BlobCoreEESt10_Select1stIS5_ESt4lessIjESaIS5_EE8_M_eraseEPSt13_Rb_tree_nodeIS5_E +__ZN8LocalKeyD2Ev +__ZN3KeyD2Ev +__ZL18_XpostNotificationP17mach_msg_header_tS0_ +__Z28ucsp_server_postNotificationjj13audit_token_tPijjPvjj +__ZN8Listener6notifyEjjjRKN8Security8CssmDataE +__ZN8Listener12JitterBuffer10inSequenceEPNS_12NotificationE +__ZN8Listener12JitterBuffer15popNotificationEv +__ZNSt8_Rb_treeIjSt4pairIKjN8Security10RefPointerIN8Listener12NotificationEEEESt10_Select1stIS7_ESt4lessIjESaIS7_EE4findERS1_ +__ZL26_XauthorizationExternalizeP17mach_msg_header_tS0_ +__Z36ucsp_server_authorizationExternalizejj13audit_token_tPiN8Security14SecurityServer17AuthorizationBlobEP25AuthorizationExter +__ZN7Session15authExternalizeERKN8Security14SecurityServer17AuthorizationBlobER25AuthorizationExternalForm +__ZNK18AuthorizationToken14mayExternalizeER7Process +__ZL26_XauthorizationInternalizeP17mach_msg_header_tS0_ +__Z36ucsp_server_authorizationInternalizejj13audit_token_tPi25AuthorizationExternalFormPN8Security14SecurityServer17Authorizati +__ZN7Session15authInternalizeERK25AuthorizationExternalFormRN8Security14SecurityServer17AuthorizationBlobE +__ZN18AuthorizationToken14mayInternalizeER7Processb +__ZL10_XisLockedP17mach_msg_header_tS0_ +__Z20ucsp_server_isLockedjj13audit_token_tPijPj +__ZN14CodeSignatures28matchSignedClientToLegacyACLER7ProcessP9__SecCodeRKN8Security11OSXVerifierERKNS4_20AclValidationContextE +__ZN17SecurityServerAcl21looksLikeLegacyDotMacERKN8Security20AclValidationContextE +__ZN8Security8cfStringEPK10__CFStringb +__ZL4trimSsc +__ZL11_XunwrapKeyP17mach_msg_header_tS0_ +__Z21ucsp_server_unwrapKeyjj13audit_token_tPijPvjjS1_jS1_jjS1_jjjPS1_PjS3_S2_S3_ +_xdr_CSSM_KEY_PTR +__ZN6Server16optionalDatabaseEjb +__ZN7Process10localStoreEv +__ZN12TempDatabaseC1ER7Process +__ZN12TempDatabaseC2ER7Process +__Z6pickDbP8DatabaseS0_ +__ZNK12TempDatabase9transientEv +__ZN13LocalDatabase9unwrapKeyERKN8Security7ContextEPKNS0_17AccessCredentialsEPKNS0_17AclEntryPrototypeEP3KeySB_jjNS0_7CssmKeyER +__ZN8Security10CssmClient7Context4credEPK23cssm_access_credentials +__ZN8Security10CssmClient7Context3setINS_17AccessCredentialsEEEvjRKT_ +__ZN8LocalKey7KeySpecC1Ejj +__ZN12TempDatabase7makeKeyERKN8Security7CssmKeyEjPKNS0_17AclEntryPrototypeE +__ZN7TempKeyC2ER8DatabaseRKN8Security7CssmKeyEjPKNS2_17AclEntryPrototypeE +__ZN8LocalKeyC2ER8DatabaseRKN8Security7CssmKeyEj +__ZN8LocalKey5setupERKN8Security7CssmKeyEj +__ZN8LocalKey8setOwnerEPKN8Security17AclEntryPrototypeE +__ZThn160_N7TempKey3aclEv +__ZN8Security9ObjectAcl14cssmSetInitialERKNS_10RefPointerINS_10AclSubjectEEE +__ZN8Security9ObjectAcl5EntryC2ERKNS_10RefPointerINS_10AclSubjectEEE +__ZN8Security9ObjectAcl8AclEntryC2ERKNS_10RefPointerINS_10AclSubjectEEE +__ZN8Security10RefPointerI3KeyE10setPointerEPS1_ +__ZL17_XverifySignatureP17mach_msg_header_tS0_ +__Z27ucsp_server_verifySignaturejj13audit_token_tPiPvjjjS1_jS1_j +__ZN13LocalDatabase15verifySignatureERKN8Security7ContextER3KeyjRKNS0_8CssmDataES8_ +__ZN8Security10CssmClient6VerifyC1ERKNS0_3CSPEjj +__ZN8Security10CssmClient6Verify6verifyEPKNS_8CssmDataEjRS3_ +__ZN8Security10CssmClient14SigningContext8activateEv +__ZN8Security10CssmClient14SigningContextD2Ev +__ZThn16_N7TempKeyD0Ev +__ZN7TempKeyD0Ev +__ZThn16_N16KeychainDatabaseD0Ev +__ZThn16_N12TempDatabaseD0Ev +__ZNSt8_Rb_treeIjSt4pairIKjN20ClientIdentification10GuestStateEESt10_Select1stIS4_ESt4lessIjESaIS4_EE15_M_destroy_nodeEPSt13_Rb +__ZL13_XhostingPortP17mach_msg_header_tS0_ +__Z23ucsp_server_hostingPortjj13audit_token_tPiiPj +__ZNK6Server7findPidEi +__ZNKSt8_Rb_treeIiSt4pairIKiP7ProcessESt10_Select1stIS4_ESt4lessIiESaIS4_EE4findERS1_ +__ZNSt6vectorIN13Authorization11AuthItemRefESaIS1_EE9push_backERKS1_ +__ZNK13Authorization8RuleImpl12evaluateUserERKNS_11AuthItemRefERKNS_4RuleERNS_11AuthItemSetEjdPKSt3setINS_10CredentialESt4lessI +__ZNK13Authorization8RuleImpl26evaluateCredentialForRightERK18AuthorizationTokenRKNS_11AuthItemRefERKNS_4RuleERKNS_11AuthItemSe +__ZNK13Authorization8RuleImpl30evaluateUserCredentialForRightERK18AuthorizationTokenRKNS_11AuthItemRefERKNS_4RuleERKNS_11AuthIt +__ZNK13Authorization14CredentialImpl12creationTimeEv +__ZNSt8_Rb_treeISsSt4pairIKSsSsESt10_Select1stIS2_ESt4lessISsESaIS2_EE7_M_copyEPKSt13_Rb_tree_nodeIS2_EPSA_ +__ZNSt8_Rb_treeISsSt4pairIKSsSsESt10_Select1stIS2_ESt4lessISsESaIS2_EE14_M_create_nodeERKS2_ +__ZN9__gnu_cxx13new_allocatorISt4pairIKSsSsEE9constructEPS3_RKS3_ +__ZNSt4pairIKSsSsEC2ERKS1_ +__ZNSt8_Rb_treeISsSt4pairIKSsSsESt10_Select1stIS2_ESt4lessISsESaIS2_EE15_M_destroy_nodeEPSt13_Rb_tree_nodeIS2_E +__ZNSt4pairIKSsSsED2Ev +__ZNK13Authorization8RuleImpl22evaluateAuthenticationERKNS_11AuthItemRefERKNS_4RuleERNS_11AuthItemSetEjdPKSt3setINS_10Credentia +__ZNK13Authorization8RuleImpl20evaluateSessionOwnerERKNS_11AuthItemRefERKNS_4RuleERKNS_11AuthItemSetEdRK18AuthorizationTokenRNS +__ZNK7Session13originatorUidEv +__ZN8Security10RefPointerIN13Authorization14CredentialImplEE10setPointerEPS2_ +__ZN18AuthorizationToken12scrubInfoSetEb +__ZN8Security14CommonCriteria9Securityd25RightAuthenticationLogger10logSuccessEjjPKc +__ZN18AuthorizationToken17setCredentialInfoERKN13Authorization10CredentialEb +__ZNK13Authorization8RuleImpl13evaluateRulesERKNS_11AuthItemRefERKNS_4RuleERNS_11AuthItemSetEjdPKSt3setINS_10CredentialESt4less +__ZL22_XauthorizationReleaseP17mach_msg_header_tS0_ +__Z32ucsp_server_authorizationReleasejj13audit_token_tPiN8Security14SecurityServer17AuthorizationBlobEj +__ZN7Session8authFreeERKN8Security14SecurityServer17AuthorizationBlobEj +__ZN18AuthorizationToken7DeleterC1ERKN8Security14SecurityServer17AuthorizationBlobE +__ZN18AuthorizationToken7DeleterC2ERKN8Security14SecurityServer17AuthorizationBlobE +__ZN7Process19removeAuthorizationEP18AuthorizationToken +__ZN18AuthorizationToken10endProcessER7Process +__ZNSt8_Rb_treeIP7ProcessS1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE5eraseERKS1_ +__ZNSt8_Rb_treeIP7ProcessS1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE5eraseESt17_Rb_tree_iteratorIS1_ES9_ +__ZNSt8_Rb_treeIP7ProcessS1_St9_IdentityIS1_ESt4lessIS1_ESaIS1_EE8_M_eraseEPSt13_Rb_tree_nodeIS1_E +__ZN18AuthorizationToken7Deleter6removeEv +__ZN18AuthorizationTokenD0Ev +__ZN13Authorization14CredentialImpl10invalidateEv +__ZN7Session7destroyEi +__ZL13handleSignalsi +_self_client_handleSignal +__ZL14_XhandleSignalP17mach_msg_header_tS0_ +__Z24self_server_handleSignaljji +__ZN6Server13beginShutdownEv +__ZN7Session19invalidateAuthHostsEv +__ZN7Session26invalidateSessionAuthHostsEv +__ZN8Security6Syslog7warningEPKcz +__ZN8Security12UnixPlusPlus5Child4killEi diff --git a/securityd/src/server.cpp b/securityd/src/server.cpp new file mode 100644 index 00000000..c7f0e26c --- /dev/null +++ b/securityd/src/server.cpp @@ -0,0 +1,567 @@ +/* + * Copyright (c) 2000-2010,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@ + */ + + +// +// server - securityd main server object +// +#include // MIG ucsp service +#include "self.h" // MIG self service +#include +#include +#include "server.h" +#include "session.h" +#include "acls.h" +#include "notifications.h" +#include "child.h" +#include +#include +#include "pcscmonitor.h" + +#include "agentquery.h" + + +using namespace MachPlusPlus; + +// +// Construct an Authority +// +Authority::Authority(const char *configFile) +: Authorization::Engine(configFile) +{ +} + +Authority::~Authority() +{ +} + + +// +// Construct the server object +// +Server::Server(Authority &authority, CodeSignatures &signatures, const char *bootstrapName) + : MachServer(bootstrapName), + mBootstrapName(bootstrapName), + mCSPModule(gGuidAppleCSP, mCssm), mCSP(mCSPModule), + mAuthority(authority), + mCodeSignatures(signatures), + mVerbosity(0), + mWaitForClients(true), mShuttingDown(false) +{ + // make me eternal (in the object mesh) + ref(); + + // engage the subsidiary port handler for sleep notifications + add(sleepWatcher); +} + + +// +// Clean up the server object +// +Server::~Server() +{ + //@@@ more later +} + + +// +// Locate a connection by reply port and make it the current connection +// of this thread. The connection will be marked busy, and can be accessed +// by calling Server::connection() [no argument] until it is released by +// calling Connection::endWork(). +// +Connection &Server::connection(mach_port_t port, audit_token_t &auditToken) +{ + Server &server = active(); + StLock _(server); + Connection *conn = server.mConnections.get(port, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); + conn->process().checkSession(auditToken); + active().mCurrentConnection() = conn; + conn->beginWork(auditToken); + return *conn; +} + +Connection &Server::connection(bool tolerant) +{ + Connection *conn = active().mCurrentConnection(); + assert(conn); // have to have one + if (!tolerant) + conn->checkWork(); + return *conn; +} + +void Server::requestComplete(CSSM_RETURN &rcode) +{ + // note: there may not be an active connection if connection setup failed + if (RefPointer &conn = active().mCurrentConnection()) { + conn->endWork(rcode); + conn = NULL; + } + IFDUMPING("state", NodeCore::dumpAll()); +} + + +// +// Shorthand for "current" process and session. +// This is the process and session for the current connection. +// +Process &Server::process() +{ + return connection().process(); +} + +Session &Server::session() +{ + return connection().process().session(); +} + +RefPointer Server::key(KeyHandle key) +{ + return U32HandleObject::findRef(key, CSSMERR_CSP_INVALID_KEY_REFERENCE); +} + +RefPointer Server::database(DbHandle db) +{ + return find(db, CSSMERR_DL_INVALID_DB_HANDLE); +} + +RefPointer Server::keychain(DbHandle db) +{ + return find(db, CSSMERR_DL_INVALID_DB_HANDLE); +} + +RefPointer Server::optionalDatabase(DbHandle db, bool persistent) +{ + if (persistent && db != noDb) + return database(db); + else + return &process().localStore(); +} + + +// +// Locate an ACL bearer (database or key) by handle +// The handle might be used across IPC, so we clamp it accordingly +// +AclSource &Server::aclBearer(AclKind kind, U32HandleObject::Handle handle) +{ + AclSource &bearer = U32HandleObject::find(handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE); + if (kind != bearer.acl().aclKind()) + CssmError::throwMe(CSSMERR_CSSM_INVALID_HANDLE_USAGE); + return bearer; +} + + +// +// Run the server. This will not return until the server is forced to exit. +// +void Server::run() +{ + MachServer::run(0x10000, + MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0) | + MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT)); +} + + +// +// Handle thread overflow. MachServer will call this if it has hit its thread +// limit and yet still needs another thread. +// +void Server::threadLimitReached(UInt32 limit) +{ + Syslog::notice("securityd has reached its thread limit (%ld) - service deadlock is possible", + limit); +} + + +// +// The primary server run-loop function. +// Invokes the MIG-generated main dispatch function (ucsp_server), as well +// as the self-send dispatch (self_server). +// For debug builds, look up request names in a MIG-generated table +// for better debug-log messages. +// +boolean_t ucsp_server(mach_msg_header_t *, mach_msg_header_t *); +boolean_t self_server(mach_msg_header_t *, mach_msg_header_t *); + + +boolean_t Server::handle(mach_msg_header_t *in, mach_msg_header_t *out) +{ + return ucsp_server(in, out) || self_server(in, out); +} + + +// +// Set up a new Connection. This establishes the environment (process et al) as needed +// and registers a properly initialized Connection object to run with. +// Type indicates how "deep" we need to initialize (new session, process, or connection). +// Everything at and below that level is constructed. This is straight-forward except +// in the case of session re-initialization (see below). +// +void Server::setupConnection(ConnectLevel type, Port replyPort, Port taskPort, + const audit_token_t &auditToken, const ClientSetupInfo *info) +{ + AuditToken audit(auditToken); + + // first, make or find the process based on task port + StLock _(*this); + RefPointer &proc = mProcesses[taskPort]; + if (proc && proc->session().sessionId() != audit.sessionId()) + proc->changeSession(audit.sessionId()); + if (proc && type == connectNewProcess) { + // the client has amnesia - reset it + assert(info); + proc->reset(taskPort, info, audit); + proc->changeSession(audit.sessionId()); + } + if (!proc) { + if (type == connectNewThread) // client error (or attack) + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); + assert(info); + proc = new Process(taskPort, info, audit); + notifyIfDead(taskPort); + mPids[proc->pid()] = proc; + } + + // now, establish a connection and register it in the server + Connection *connection = new Connection(*proc, replyPort); + if (mConnections.contains(replyPort)) // malicious re-entry attempt? + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); //@@@ error code? (client error) + mConnections[replyPort] = connection; + notifyIfDead(replyPort); +} + + +// +// Synchronously end a Connection. +// This is due to a request from the client, so no thread races are possible. +// In practice, this is optional since the DPN for the client thread reply port +// will destroy the connection anyway when the thread dies. +// +void Server::endConnection(Port replyPort) +{ + StLock _(*this); + PortMap::iterator it = mConnections.find(replyPort); + assert(it != mConnections.end()); + it->second->terminate(); + mConnections.erase(it); +} + + +// +// Handling dead-port notifications. +// This receives DPNs for all kinds of ports we're interested in. +// +void Server::notifyDeadName(Port port) +{ + // We need the lock to get a proper iterator on mConnections or mProcesses, + // but must release it before we call abort or kill, as these might take + // unbounded time, including calls out to token daemons etc. + + StLock serverLock(*this); + secdebug("SSports", "port %d is dead", port.port()); + + // is it a connection? + PortMap::iterator conIt = mConnections.find(port); + if (conIt != mConnections.end()) { + SECURITYD_PORTS_DEAD_CONNECTION(port); + RefPointer con = conIt->second; + mConnections.erase(conIt); + serverLock.unlock(); + con->abort(); + return; + } + + // is it a process? + PortMap::iterator procIt = mProcesses.find(port); + if (procIt != mProcesses.end()) { + SECURITYD_PORTS_DEAD_PROCESS(port); + RefPointer proc = procIt->second; + mPids.erase(proc->pid()); + mProcesses.erase(procIt); + serverLock.unlock(); + // The kill may take some time; make sure there is a spare thread around + // to prevent deadlocks + StLock _(*this); + proc->kill(); + return; + } + + // well, what IS IT?! + SECURITYD_PORTS_DEAD_ORPHAN(port); + secdebug("server", "spurious dead port notification for port %d", port.port()); +} + + +// +// Handling no-senders notifications. +// This is currently only used for (subsidiary) service ports +// +void Server::notifyNoSenders(Port port, mach_port_mscount_t) +{ + SECURITYD_PORTS_DEAD_SESSION(port); +} + + +// +// Handling signals. +// These are sent as Mach messages from ourselves to escape the limitations of +// the signal handler environment. +// +kern_return_t self_server_handleSignal(mach_port_t sport, + mach_port_t taskPort, int sig) +{ + try { + SECURITYD_SIGNAL_HANDLED(sig); + if (taskPort != mach_task_self()) { + Syslog::error("handleSignal: received from someone other than myself"); + return KERN_SUCCESS; + } + switch (sig) { + case SIGCHLD: + ServerChild::checkChildren(); + break; + case SIGINT: + SECURITYD_SHUTDOWN_NOW(); + Syslog::notice("securityd terminated due to SIGINT"); + _exit(0); + case SIGTERM: + Server::active().beginShutdown(); + break; + case SIGPIPE: + fprintf(stderr, "securityd ignoring SIGPIPE received"); + break; + +#if defined(DEBUGDUMP) + case SIGUSR1: + NodeCore::dumpAll(); + break; +#endif //DEBUGDUMP + + case SIGUSR2: + { + extern PCSCMonitor *gPCSC; + gPCSC->startSoftTokens(); + break; + } + + default: + assert(false); + } + } catch(...) { + secdebug("SS", "exception handling a signal (ignored)"); + } + mach_port_deallocate(mach_task_self(), taskPort); + return KERN_SUCCESS; +} + + +kern_return_t self_server_handleSession(mach_port_t sport, + mach_port_t taskPort, uint32_t event, uint64_t ident) +{ + try { + if (taskPort != mach_task_self()) { + Syslog::error("handleSession: received from someone other than myself"); + return KERN_SUCCESS; + } + if (event == AUE_SESSION_CLOSE) + Session::destroy(ident); + } catch(...) { + secdebug("SS", "exception handling a signal (ignored)"); + } + mach_port_deallocate(mach_task_self(), taskPort); + return KERN_SUCCESS; +} + + +// +// Notifier for system sleep events +// +void Server::SleepWatcher::systemWillSleep() +{ + SECURITYD_POWER_SLEEP(); + Session::processSystemSleep(); + for (set::const_iterator it = mPowerClients.begin(); it != mPowerClients.end(); it++) + (*it)->systemWillSleep(); +} + +void Server::SleepWatcher::systemIsWaking() +{ + SECURITYD_POWER_WAKE(); + for (set::const_iterator it = mPowerClients.begin(); it != mPowerClients.end(); it++) + (*it)->systemIsWaking(); +} + +void Server::SleepWatcher::systemWillPowerOn() +{ + SECURITYD_POWER_ON(); + Server::active().longTermActivity(); + for (set::const_iterator it = mPowerClients.begin(); it != mPowerClients.end(); it++) + (*it)->systemWillPowerOn(); +} + +void Server::SleepWatcher::add(PowerWatcher *client) +{ + assert(mPowerClients.find(client) == mPowerClients.end()); + mPowerClients.insert(client); +} + +void Server::SleepWatcher::remove(PowerWatcher *client) +{ + assert(mPowerClients.find(client) != mPowerClients.end()); + mPowerClients.erase(client); +} + + +// +// Expose the process/pid map to the outside +// +Process *Server::findPid(pid_t pid) const +{ + PidMap::const_iterator it = mPids.find(pid); + return (it == mPids.end()) ? NULL : it->second; +} + + +// +// Set delayed shutdown mode +// +void Server::waitForClients(bool waiting) +{ + mWaitForClients = waiting; +} + + +// +// Begin shutdown processing. +// We relinquish our primary state authority. From now on, we'll be +// kept alive (only) by our current clients. +// +static FILE *reportFile; + +void Server::beginShutdown() +{ + StLock _(*this); + if (!mWaitForClients) { + SECURITYD_SHUTDOWN_NOW(); + _exit(0); + } else { + if (!mShuttingDown) { + mShuttingDown = true; + Session::invalidateAuthHosts(); + SECURITYD_SHUTDOWN_BEGIN(); + if (verbosity() >= 2) { + reportFile = fopen("/var/log/securityd-shutdown.log", "w"); + shutdownSnitch(); + } + } + } +} + + +// +// During shutdown, we report residual clients to dtrace, and allow a state dump +// for debugging. +// We don't bother locking for the shuttingDown() check; it's a latching boolean +// and we'll be good enough without a lock. +// +void Server::eventDone() +{ + if (this->shuttingDown()) { + StLock lazy(*this, false); // lazy lock acquisition + if (SECURITYD_SHUTDOWN_COUNT_ENABLED()) { + lazy.lock(); + SECURITYD_SHUTDOWN_COUNT(mProcesses.size(), VProc::Transaction::debugCount()); + } + if (verbosity() >= 2) { + lazy.lock(); + shutdownSnitch(); + } + IFDUMPING("shutdown", NodeCore::dumpAll()); + } +} + + +void Server::shutdownSnitch() +{ + time_t now; + time(&now); + fprintf(reportFile, "%.24s %d residual clients:\n", ctime(&now), int(mPids.size())); + for (PidMap::const_iterator it = mPids.begin(); it != mPids.end(); ++it) + if (SecCodeRef clientCode = it->second->processCode()) { + CFRef path; + OSStatus rc = SecCodeCopyPath(clientCode, kSecCSDefaultFlags, &path.aref()); + if (path) + fprintf(reportFile, " %s (%d)\n", cfString(path).c_str(), it->first); + else + fprintf(reportFile, "pid=%d (error %d)\n", it->first, int32_t(rc)); + } + fprintf(reportFile, "\n"); + fflush(reportFile); +} + +bool Server::inDarkWake() +{ + return IOPMIsADarkWake(IOPMConnectionGetSystemCapabilities()); +} + +// +// Initialize the CSSM/MDS subsystem. +// This was once done lazily on demand. These days, we are setting up the +// system MDS here, and CSSM is pretty much always needed, so this is called +// early during program startup. Do note that the server may not (yet) be running. +// +void Server::loadCssm(bool mdsIsInstalled) +{ + if (!mCssm->isActive()) { + StLock _(*this); + VProc::Transaction xact; + if (!mCssm->isActive()) { + if (!mdsIsInstalled) { // non-system securityd instance should not reinitialize MDS + secdebug("SS", "Installing MDS"); + IFDEBUG(if (geteuid() == 0)) + MDSClient::mds().install(); + } + secdebug("SS", "CSSM initializing"); + mCssm->init(); + mCSP->attach(); + secdebug("SS", "CSSM ready with CSP %s", mCSP->guid().toString().c_str()); + } + } +} + + +// +// LongtermActivity/lock combo +// +LongtermStLock::LongtermStLock(Mutex &lck) + : StLock(lck, false) // don't take the lock yet +{ + if (lck.tryLock()) { // uncontested + this->mActive = true; + } else { // contested - need backup thread + Server::active().longTermActivity(); + this->lock(); + } +} diff --git a/securityd/src/server.h b/securityd/src/server.h new file mode 100644 index 00000000..6a8eae4a --- /dev/null +++ b/securityd/src/server.h @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2000-2009,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@ + */ + + +// +// server - securityd main server object +// +#ifndef _H_SERVER +#define _H_SERVER + +#include "structure.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "codesigdb.h" +#include "connection.h" +#include "key.h" +#include "database.h" +#include "localdatabase.h" +#include "kcdatabase.h" +#include "authority.h" +#include "AuthorizationEngine.h" +#include + +#define EQUIVALENCEDBPATH "/var/db/CodeEquivalenceDatabase" + + +// +// The authority itself. You will usually only have one of these. +// +class Authority : public Authorization::Engine { +public: + Authority(const char *configFile); + ~Authority(); +}; + +// +// The server object itself. This is the "go to" object for anyone who wants +// to access the server's global state. It runs the show. +// There is only one Server, and its name is Server::active(). +// +// Server also acts as the global-scope nexus of securityd's object mesh. +// Sessions have Server as their parent, and global-scope objects have it +// as their referent. The Server is never kill()ed; though kill(globalObject) +// may make sense. Also, we can search for global-scope objects by using the +// findFirst/allReferences feature of Node<>. +// +class Server : public PerGlobal, + public MachPlusPlus::MachServer, + public UniformRandomBlobs { +public: + Server(Authority &myAuthority, CodeSignatures &signatures, const char *bootstrapName); + ~Server(); + + // run the server until it shuts down + void run(); + + // + // Retrieve pieces of the Server's object web. + // These are all static methods that use the active() Server of this thread. + // + static Server &active() { return safer_cast(MachServer::active()); } + static const char *bootstrapName() { return active().mBootstrapName.c_str(); } + static unsigned int verbosity() { return active().mVerbosity; } + + // + // Each thread has at most one "active connection". If the server is currently + // servicing a request received through a Connection, that's it. Otherwise + // there is none. + // + static Connection &connection(mach_port_t replyPort, audit_token_t &auditToken); // find by reply port and make active + static Connection &connection(bool tolerant = false); // return active (or fail unless tolerant) + static void requestComplete(CSSM_RETURN &rcode); // de-activate active connection + + // + // Process and session of the active Connection + // + static Process &process(); + static Session &session(); + + // + // Find objects from their client handles. + // These will all throw on invalid handles, and the RefPointer<> results are always non-NULL. + // + static RefPointer key(KeyHandle key); + static RefPointer optionalKey(KeyHandle k) { return (k == noKey) ? NULL : key(k); } + static RefPointer database(DbHandle db); + static RefPointer keychain(DbHandle db); + static RefPointer optionalDatabase(DbHandle db, bool persistent = true); + static AclSource &aclBearer(AclKind kind, U32HandleObject::Handle handle); + + // Generic version of handle lookup + template + static RefPointer find(uint32_t handle, CSSM_RETURN notFoundError) + { + RefPointer object = + U32HandleObject::findRef(handle, notFoundError); + if (object->process() != Server::process()) + CssmError::throwMe(notFoundError); + return object; + } + + // + // publicly accessible components of the active server + // + static Authority &authority() { return active().mAuthority; } + static CodeSignatures &codeSignatures() { return active().mCodeSignatures; } + static CssmClient::CSP &csp() { return active().mCSP; } + +public: + // + // Initialize CSSM and MDS + // + void loadCssm(bool mdsIsInstalled); + +public: + // set up a new connection + enum ConnectLevel { + connectNewProcess, + connectNewThread + }; + void setupConnection(ConnectLevel type, Port replyPort, Port taskPort, const audit_token_t &auditToken, + const ClientSetupInfo *info = NULL); + + void endConnection(Port replyPort); + + static void releaseWhenDone(Allocator &alloc, void *memory) + { MachServer::active().releaseWhenDone(alloc, memory); } + static void releaseWhenDone(void *memory) + { releaseWhenDone(Allocator::standard(), memory); } + +protected: + // implementation methods of MachServer + boolean_t handle(mach_msg_header_t *in, mach_msg_header_t *out); + void notifyDeadName(Port port); + void notifyNoSenders(Port port, mach_port_mscount_t); + void threadLimitReached(UInt32 count); + void eventDone(); + +private: + class SleepWatcher : public MachPlusPlus::PortPowerWatcher { + public: + void systemWillSleep(); + void systemIsWaking(); + void systemWillPowerOn(); + + void add(PowerWatcher *client); + void remove(PowerWatcher *client); + + private: + set mPowerClients; + }; + + SleepWatcher sleepWatcher; + +public: + using MachServer::add; + using MachServer::remove; + void add(MachPlusPlus::PowerWatcher *client) { StLock _(*this); sleepWatcher.add(client); } + void remove(MachPlusPlus::PowerWatcher *client) { StLock _(*this); sleepWatcher.remove(client); } + +public: + Process *findPid(pid_t pid) const; + + void verbosity(unsigned int v) { mVerbosity = v; } + void waitForClients(bool waiting); // set waiting behavior + void beginShutdown(); // start delayed shutdown if configured + bool shuttingDown() const { return mShuttingDown; } + void shutdownSnitch(); // report lingering clients + bool inDarkWake(); + void associateThread() { perThread().server = this; } + +private: + // mach bootstrap registration name + std::string mBootstrapName; + + // connection map (by client reply port) + PortMap mConnections; + + // process map (by process task port) + typedef std::map PidMap; + PortMap mProcesses; // strong reference + PidMap mPids; // weak reference (subsidiary to mProcesses) + + // Current connection, if any (per thread). + // Set as a side effect of calling connection(mach_port_t) + // and returned by connection(bool). + ThreadNexus > mCurrentConnection; + + // CSSM components + CssmClient::Cssm mCssm; // CSSM instance + CssmClient::Module mCSPModule; // CSP module + CssmClient::CSP mCSP; // CSP attachment + + Authority &mAuthority; + CodeSignatures &mCodeSignatures; + + // busy state for primary state authority + unsigned int mVerbosity; + bool mWaitForClients; + bool mShuttingDown; +}; + + +// +// A StLock that (also) declares a longTermActivity (only) once it's been entered. +// +class LongtermStLock : public StLock { +public: + LongtermStLock(Mutex &lck); + // destructor inherited +}; + +#endif //_H_SERVER diff --git a/securityd/src/session.cpp b/securityd/src/session.cpp new file mode 100644 index 00000000..37472cad --- /dev/null +++ b/securityd/src/session.cpp @@ -0,0 +1,689 @@ +/* + * Copyright (c) 2000-2009,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@ + */ + + +// +// session - authentication session domains +// +// Security sessions are now by definition congruent to audit subsystem sessions. +// We represent these sessions within securityd as subclasses of class Session, +// but we reach for the kernel's data whenever we're not sure if our data is +// up to date. +// +// Modifications to session state are made from client space using system calls. +// We discover them when we see changes in audit records as they come in with +// new requests. We cannot use system notifications for such changes because +// securityd is fully symmetrically multi-threaded, and thus may process new +// requests from clients before it gets those notifications. +// +#include +#include // SIGTERM +#include // kAuthorizationFlagLeastPrivileged +#include "session.h" +#include "connection.h" +#include "database.h" +#include "server.h" +#include +#include + +using namespace CommonCriteria; + + +// +// The static session map +// +Session::SessionMap Session::mSessions; +Mutex Session::mSessionLock(Mutex::recursive); + + +const char Session::kUsername[] = "username"; +const char Session::kRealname[] = "realname"; + + +// +// Create a Session object from initial parameters (create) +// +Session::Session(const AuditInfo &audit, Server &server) + : mAudit(audit), mSecurityAgent(NULL), mAuthHost(NULL), mKeybagState(0) +{ + // link to Server as the global nexus in the object mesh + parent(server); + + // self-register + StLock _(mSessionLock); + assert(!mSessions[audit.sessionId()]); + mSessions[audit.sessionId()] = this; + + // log it + SECURITYD_SESSION_CREATE(this, this->sessionId(), &mAudit, sizeof(mAudit)); + Syslog::notice("Session %d created", this->sessionId()); +} + + +// +// Destroy a Session +// +Session::~Session() +{ + SECURITYD_SESSION_DESTROY(this, this->sessionId()); + Syslog::notice("Session %d destroyed", this->sessionId()); +} + + +Server &Session::server() const +{ + return parent(); +} + + +// +// Locate a session object by session identifier +// +Session &Session::find(pid_t id, bool create) +{ + if (id == callerSecuritySession) + return Server::session(); + StLock _(mSessionLock); + SessionMap::iterator it = mSessions.find(id); + if (it != mSessions.end()) + return *it->second; + + // new session + if (!create) + CssmError::throwMe(errSessionInvalidId); + AuditInfo info; + info.get(id); + assert(info.sessionId() == id); + RefPointer session = new DynamicSession(info); + mSessions.insert(make_pair(id, session)); + return *session; +} + + +// +// Act on a death notification for a session's underlying audit session object. +// We may not destroy the Session outright here (due to processes that use it), +// but we do clear out its accumulated wealth. +// Note that we may get spurious death notifications for audit sessions that we +// never learned about. Ignore those. +// +void Session::destroy(SessionId id) +{ + // remove session from session map + bool unlocked = false; + RefPointer session = NULL; + { + StLock _(mSessionLock); + SessionMap::iterator it = mSessions.find(id); + if (it != mSessions.end()) { + session = it->second; + assert(session->sessionId() == id); + mSessions.erase(it); + + for (SessionMap::iterator kb_it = mSessions.begin(); kb_it != mSessions.end(); kb_it++) { + RefPointer kb_session = kb_it->second; + if (kb_session->originatorUid() == session->originatorUid()) { + if (kb_session->keybagGetState(session_keybag_unlocked)) unlocked = true; + } + } + } + } + + if (session.get()) { + if (!unlocked) { + service_context_t context = session->get_current_service_context(); + service_client_kb_lock(&context); + } + session->kill(); + } +} + + +void Session::kill() +{ + StLock _(*this); // do we need to take this so early? + SECURITYD_SESSION_KILL(this, this->sessionId()); + invalidateSessionAuthHosts(); + + // invalidate shared credentials + { + StLock _(mCredsLock); + + IFDEBUG(if (!mSessionCreds.empty()) + secdebug("SSauth", "session %p clearing %d shared credentials", + this, int(mSessionCreds.size()))); + for (CredentialSet::iterator it = mSessionCreds.begin(); it != mSessionCreds.end(); it++) + (*it)->invalidate(); + } + + // base kill processing + PerSession::kill(); +} + + +// +// Refetch audit session data for the current audit session (to catch outside updates +// to the audit record). This is the price we're paying for not requiring an IPC to +// securityd when audit session data changes (this is desirable for delayering the +// software layer cake). +// If we ever disallow changes to (parts of the) audit session record in the kernel, +// we can loosen up on this continual re-fetching. +// +void Session::updateAudit() const +{ + CommonCriteria::AuditInfo info; + try { + info.get(mAudit.sessionId()); + } catch (...) { + return; + } + mAudit = info; +} + +void Session::verifyKeyStorePassphrase(int32_t retries) +{ + QueryKeybagPassphrase keybagQuery(*this, retries); + keybagQuery.inferHints(Server::process()); + if (keybagQuery.query() != SecurityAgent::noReason) { + CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); + } +} + +void Session::changeKeyStorePassphrase() +{ + service_context_t context = get_current_service_context(); + QueryKeybagNewPassphrase keybagQuery(*this); + keybagQuery.inferHints(Server::process()); + CssmAutoData pass(Allocator::standard(Allocator::sensitive)); + CssmAutoData oldPass(Allocator::standard(Allocator::sensitive)); + SecurityAgent::Reason queryReason = keybagQuery.query(oldPass, pass); + if (queryReason == SecurityAgent::noReason) { + service_client_kb_change_secret(&context, oldPass.data(), (int)oldPass.length(), pass.data(), (int)pass.length()); + } else { + CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); + } +} + +void Session::resetKeyStorePassphrase(const CssmData &passphrase) +{ + service_context_t context = get_current_service_context(); + service_client_kb_reset(&context, passphrase.data(), (int)passphrase.length()); +} + +service_context_t Session::get_current_service_context() +{ + // if this gets called from a timer there is no connection() object. + // need to check for valid connection object and pass the audit token along + service_context_t context = { sessionId(), originatorUid(), {} }; //*Server::connection().auditToken() + return context; +} + +void Session::keybagClearState(int state) +{ + mKeybagState &= ~state; +} + +void Session::keybagSetState(int state) +{ + mKeybagState |= state; +} + +bool Session::keybagGetState(int state) +{ + return mKeybagState & state; +} + + +// +// Manage authorization client processes +// +void Session::invalidateSessionAuthHosts() +{ + StLock _(mAuthHostLock); + + // if you got here, we don't care about pending operations: the auth hosts die + Syslog::warning("Killing auth hosts"); + if (mSecurityAgent) mSecurityAgent->UnixPlusPlus::Child::kill(SIGTERM); + if (mAuthHost) mAuthHost->UnixPlusPlus::Child::kill(SIGTERM); + mSecurityAgent = NULL; + mAuthHost = NULL; +} + +void Session::invalidateAuthHosts() +{ + StLock _(mSessionLock); + for (SessionMap::const_iterator it = mSessions.begin(); it != mSessions.end(); it++) + it->second->invalidateSessionAuthHosts(); +} + +// +// On system sleep, call sleepProcessing on all DbCommons of all Sessions +// +void Session::processSystemSleep() +{ + SecurityAgentXPCQuery::killAllXPCClients(); + + StLock _(mSessionLock); + for (SessionMap::const_iterator it = mSessions.begin(); it != mSessions.end(); it++) + it->second->allReferences(&DbCommon::sleepProcessing); +} + + +// +// On "lockAll", call sleepProcessing on all DbCommons of this session (only) +// +void Session::processLockAll() +{ + allReferences(&DbCommon::lockProcessing); +} + + +// +// The root session corresponds to the audit session that security is running in. +// This is usually the initial system session; but in debug scenarios it may be +// an "ordinary" graphic login session. In such a debug case, we may add attribute +// flags to the session to make our (debugging) life easier. +// +RootSession::RootSession(uint64_t attributes, Server &server) + : Session(AuditInfo::current(), server) +{ + ref(); // eternalize + mAudit.ai_flags |= attributes; // merge imposed attributes +} + + +// +// Dynamic sessions use the audit session context of the first-contact client caller. +// +DynamicSession::DynamicSession(const AuditInfo &audit) + : Session(audit, Server::active()) +{ +} + + +// +// Authorization operations +// +OSStatus Session::authCreate(const AuthItemSet &rights, + const AuthItemSet &environment, + AuthorizationFlags flags, + AuthorizationBlob &newHandle, + const audit_token_t &auditToken) +{ + // invoke the authorization computation engine + CredentialSet resultCreds; + + // this will acquire the object lock, so we delay acquiring it (@@@ no longer needed) + auto_ptr auth(new AuthorizationToken(*this, resultCreds, auditToken, (flags&kAuthorizationFlagLeastPrivileged))); + + SECURITYD_AUTH_CREATE(this, auth.get()); + + // Make a copy of the mSessionCreds + CredentialSet sessionCreds; + { + StLock _(mCredsLock); + sessionCreds = mSessionCreds; + } + + AuthItemSet outRights; + OSStatus result = Server::authority().authorize(rights, environment, flags, + &sessionCreds, &resultCreds, outRights, *auth); + newHandle = auth->handle(); + + // merge resulting creds into shared pool + if ((flags & kAuthorizationFlagExtendRights) && + !(flags & kAuthorizationFlagDestroyRights)) + { + StLock _(mCredsLock); + mergeCredentials(resultCreds); + auth->mergeCredentials(resultCreds); + } + + // Make sure that this isn't done until the auth(AuthorizationToken) is guaranteed to + // not be destroyed anymore since it's destructor asserts it has no processes + Server::process().addAuthorization(auth.get()); + auth.release(); + return result; +} + +void Session::authFree(const AuthorizationBlob &authBlob, AuthorizationFlags flags) +{ + AuthorizationToken::Deleter deleter(authBlob); + AuthorizationToken &auth = deleter; + Process &process = Server::process(); + process.checkAuthorization(&auth); + + if (flags & kAuthorizationFlagDestroyRights) { + // explicitly invalidate all shared credentials and remove them from the session + for (CredentialSet::const_iterator it = auth.begin(); it != auth.end(); it++) + if ((*it)->isShared()) + (*it)->invalidate(); + } + + // now get rid of the authorization itself + if (process.removeAuthorization(&auth)) + deleter.remove(); +} + +OSStatus Session::authGetRights(const AuthorizationBlob &authBlob, + const AuthItemSet &rights, const AuthItemSet &environment, + AuthorizationFlags flags, + AuthItemSet &grantedRights) +{ + AuthorizationToken &auth = authorization(authBlob); + return auth.session().authGetRights(auth, rights, environment, flags, grantedRights); +} + +OSStatus Session::authGetRights(AuthorizationToken &auth, + const AuthItemSet &rights, const AuthItemSet &environment, + AuthorizationFlags flags, + AuthItemSet &grantedRights) +{ + CredentialSet resultCreds; + CredentialSet effective; + { + StLock _(mCredsLock); + effective = auth.effectiveCreds(); + } + OSStatus result = Server::authority().authorize(rights, environment, flags, + &effective, &resultCreds, grantedRights, auth); + + // merge resulting creds into shared pool + if ((flags & kAuthorizationFlagExtendRights) && !(flags & kAuthorizationFlagDestroyRights)) + { + StLock _(mCredsLock); + mergeCredentials(resultCreds); + auth.mergeCredentials(resultCreds); + } + + secdebug("SSauth", "Authorization %p copyRights asked for %d got %d", + &auth, int(rights.size()), int(grantedRights.size())); + return result; +} + +OSStatus Session::authGetInfo(const AuthorizationBlob &authBlob, + const char *tag, + AuthItemSet &contextInfo) +{ + AuthorizationToken &auth = authorization(authBlob); + secdebug("SSauth", "Authorization %p get-info", &auth); + contextInfo = auth.infoSet(tag); + return noErr; +} + +OSStatus Session::authExternalize(const AuthorizationBlob &authBlob, + AuthorizationExternalForm &extForm) +{ + const AuthorizationToken &auth = authorization(authBlob); + StLock _(*this); + if (auth.mayExternalize(Server::process())) { + memset(&extForm, 0, sizeof(extForm)); + AuthorizationExternalBlob &extBlob = + reinterpret_cast(extForm); + extBlob.blob = auth.handle(); + extBlob.session = this->sessionId(); + secdebug("SSauth", "Authorization %p externalized", &auth); + return noErr; + } else + return errAuthorizationExternalizeNotAllowed; +} + +OSStatus Session::authInternalize(const AuthorizationExternalForm &extForm, + AuthorizationBlob &authBlob) +{ + // interpret the external form + const AuthorizationExternalBlob &extBlob = + reinterpret_cast(extForm); + + // locate source authorization + AuthorizationToken &sourceAuth = AuthorizationToken::find(extBlob.blob); + + // check for permission and do it + if (sourceAuth.mayInternalize(Server::process(), true)) { + StLock _(*this); + authBlob = extBlob.blob; + Server::process().addAuthorization(&sourceAuth); + secdebug("SSauth", "Authorization %p internalized", &sourceAuth); + return noErr; + } else + return errAuthorizationInternalizeNotAllowed; +} + + +// +// Accessor method for setting audit session flags. +// +void Session::setAttributes(SessionAttributeBits bits) +{ + StLock _(*this); + updateAudit(); +// assert((bits & ~settableAttributes) == 0); + mAudit.ai_flags = bits; + mAudit.set(); +} + +// +// The default session setup operation always fails. +// Subclasses can override this to support session setup calls. +// +void Session::setupAttributes(SessionCreationFlags flags, SessionAttributeBits attrs) +{ + MacOSError::throwMe(errSessionAuthorizationDenied); +} + +uid_t Session::originatorUid() +{ + if (mAudit.uid() == AU_DEFAUDITID) { + StLock _(*this); + updateAudit(); + } + return mAudit.uid(); +} + +// +// Authorization database I/O +// +OSStatus Session::authorizationdbGet(AuthorizationString inRightName, CFDictionaryRef *rightDict) +{ + string rightName(inRightName); + return Server::authority().getRule(rightName, rightDict); +} + + +OSStatus Session::authorizationdbSet(const AuthorizationBlob &authBlob, AuthorizationString inRightName, CFDictionaryRef rightDict) +{ + CredentialSet resultCreds; + AuthorizationToken &auth = authorization(authBlob); + CredentialSet effective; + + { + StLock _(mCredsLock); + effective = auth.effectiveCreds(); + } + + OSStatus result = Server::authority().setRule(inRightName, rightDict, &effective, &resultCreds, auth); + + { + StLock _(mCredsLock); + mergeCredentials(resultCreds); + auth.mergeCredentials(resultCreds); + } + + secdebug("SSauth", "Authorization %p authorizationdbSet %s (result=%d)", + &authorization(authBlob), inRightName, int32_t(result)); + return result; +} + + +OSStatus Session::authorizationdbRemove(const AuthorizationBlob &authBlob, AuthorizationString inRightName) +{ + CredentialSet resultCreds; + AuthorizationToken &auth = authorization(authBlob); + CredentialSet effective; + + { + StLock _(mCredsLock); + effective = auth.effectiveCreds(); + } + + OSStatus result = Server::authority().removeRule(inRightName, &effective, &resultCreds, auth); + + { + StLock _(mCredsLock); + mergeCredentials(resultCreds); + auth.mergeCredentials(resultCreds); + } + + secdebug("SSauth", "Authorization %p authorizationdbRemove %s (result=%d)", + &authorization(authBlob), inRightName, int32_t(result)); + return result; +} + + +// +// Merge a set of credentials into the shared-session credential pool +// +// must hold mCredsLock +void Session::mergeCredentials(CredentialSet &creds) +{ + secdebug("SSsession", "%p merge creds @%p", this, &creds); + CredentialSet updatedCredentials = creds; + for (CredentialSet::const_iterator it = creds.begin(); it != creds.end(); it++) + if ((*it)->isShared() && (*it)->isValid()) { + CredentialSet::iterator old = mSessionCreds.find(*it); + if (old == mSessionCreds.end()) { + mSessionCreds.insert(*it); + } else { + // replace "new" with "old" in input set to retain synchronization + (*old)->merge(**it); + updatedCredentials.erase(*it); + updatedCredentials.insert(*old); + } + } + creds.swap(updatedCredentials); +} + + +// +// Locate an AuthorizationToken given a blob +// +AuthorizationToken &Session::authorization(const AuthorizationBlob &blob) +{ + AuthorizationToken &auth = AuthorizationToken::find(blob); + Server::process().checkAuthorization(&auth); + return auth; +} + +// +// Run the Authorization engine to check if a given right has been authorized, +// independent of an external client request. +// +OSStatus Session::authCheckRight(string &rightName, Connection &connection, bool allowUI) +{ + // dummy up the arguments for authCreate() + AuthorizationItem rightItem = { rightName.c_str(), 0, NULL, 0 }; + AuthorizationItemSet rightItemSet = { 1, &rightItem }; + AuthItemSet rightAuthItemSet(&rightItemSet); + AuthItemSet envAuthItemSet(kAuthorizationEmptyEnvironment); + AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagExtendRights; + if (true == allowUI) + flags |= kAuthorizationFlagInteractionAllowed; + AuthorizationBlob dummyHandle; + const audit_token_t *at = connection.auditToken(); + + return authCreate(rightAuthItemSet, envAuthItemSet, flags, dummyHandle, *at); +} + +// for places within securityd that don't want to #include +// or to fuss about exceptions +bool Session::isRightAuthorized(string &rightName, Connection &connection, bool allowUI) +{ + bool isAuthorized = false; + + try { + OSStatus status = authCheckRight(rightName, connection, allowUI); + if (errAuthorizationSuccess == status) + isAuthorized = true; + } + catch (...) { + } + return isAuthorized; +} + +RefPointer +Session::authhost(const AuthHostType hostType, const bool restart) +{ + StLock _(mAuthHostLock); + + if (hostType == privilegedAuthHost) + { + if (restart || !mAuthHost || (mAuthHost->state() != Security::UnixPlusPlus::Child::alive)) + { + if (mAuthHost) + PerSession::kill(*mAuthHost); + mAuthHost = new AuthHostInstance(*this, hostType); + } + return mAuthHost; + } + else /* if (hostType == securityAgent) */ + { + if (restart || !mSecurityAgent || (mSecurityAgent->state() != Security::UnixPlusPlus::Child::alive)) + { + if (mSecurityAgent) + PerSession::kill(*mSecurityAgent); + mSecurityAgent = new AuthHostInstance(*this, hostType); + } + return mSecurityAgent; + } +} + +void DynamicSession::setUserPrefs(CFDataRef userPrefsDict) +{ + if (Server::process().uid() != 0) + MacOSError::throwMe(errSessionAuthorizationDenied); + StLock _(*this); + mSessionAgentPrefs = userPrefsDict; +} + +CFDataRef DynamicSession::copyUserPrefs() +{ + StLock _(*this); + if (mSessionAgentPrefs) + CFRetain(mSessionAgentPrefs); + return mSessionAgentPrefs; +} + + +// +// Debug dumping +// +#if defined(DEBUGDUMP) + +void Session::dumpNode() +{ + PerSession::dumpNode(); + Debug::dump(" auid=%d attrs=%#x authhost=%p securityagent=%p", + this->sessionId(), uint32_t(this->attributes()), mAuthHost, mSecurityAgent); +} + +#endif //DEBUGDUMP diff --git a/securityd/src/session.h b/securityd/src/session.h new file mode 100644 index 00000000..3e189ad0 --- /dev/null +++ b/securityd/src/session.h @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2000-2010,2012-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@ + */ + + +// +// session - authentication session domains +// +#ifndef _H_SESSION +#define _H_SESSION + +#include "structure.h" +#include "acls.h" +#include "authority.h" +#include "authhost.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "securityd_service/securityd_service/securityd_service_client.h" + +class Key; +class Connection; +class Server; +class AuthHostInstance; + +enum { + session_keybag_locked = 0, + session_keybag_unlocked = 1 << 0, + session_keybag_check_master_key = 1 << 1, + session_keybag_loaded = 1 << 2, +}; + +// +// A Session object represents one or more Connections that are known to +// belong to the same authentication domain. Informally this means just +// about "the same user", for the right definition of "user." The upshot +// is that global credentials can be shared by Connections of one Session +// with a modicum of security, and so Sessions are the natural nexus of +// single-sign-on functionality. +// +class Session : public PerSession { +public: + typedef au_asid_t SessionId; // internal session identifier (audit session id) + + Session(const CommonCriteria::AuditInfo &audit, Server &server); + virtual ~Session(); + + Server &server() const; + + SessionId sessionId() const { return mAudit.sessionId(); } + CommonCriteria::AuditInfo &auditInfo() { return mAudit; } + + IFDUMP(virtual void dumpNode()); + +public: + static const SessionAttributeBits settableAttributes = + sessionHasGraphicAccess | sessionHasTTY | sessionIsRemote | AU_SESSION_FLAG_HAS_AUTHENTICATED; + + SessionAttributeBits attributes() const { updateAudit(); return mAudit.ai_flags; } + bool attribute(SessionAttributeBits bits) const { return attributes() & bits; } + void setAttributes(SessionAttributeBits bits); + + virtual void setupAttributes(SessionCreationFlags flags, SessionAttributeBits attrs); + + virtual uid_t originatorUid(); + + virtual CFDataRef copyUserPrefs() = 0; + + static const char kUsername[]; + static const char kRealname[]; + +public: + const CredentialSet &authCredentials() const { return mSessionCreds; } + + // + // For external Authorization clients + // + OSStatus authCreate(const AuthItemSet &rights, const AuthItemSet &environment, + AuthorizationFlags flags, AuthorizationBlob &newHandle, const audit_token_t &auditToken); + void authFree(const AuthorizationBlob &auth, AuthorizationFlags flags); + static OSStatus authGetRights(const AuthorizationBlob &auth, + const AuthItemSet &requestedRights, const AuthItemSet &environment, + AuthorizationFlags flags, AuthItemSet &grantedRights); + OSStatus authGetInfo(const AuthorizationBlob &auth, const char *tag, AuthItemSet &contextInfo); + + OSStatus authExternalize(const AuthorizationBlob &auth, AuthorizationExternalForm &extForm); + OSStatus authInternalize(const AuthorizationExternalForm &extForm, AuthorizationBlob &auth); + + OSStatus authorizationdbGet(AuthorizationString inRightName, CFDictionaryRef *rightDict); + OSStatus authorizationdbSet(const AuthorizationBlob &authBlob, AuthorizationString inRightName, CFDictionaryRef rightDict); + OSStatus authorizationdbRemove(const AuthorizationBlob &authBlob, AuthorizationString inRightName); + + // + // Authorization methods for securityd's internal use + // + OSStatus authCheckRight(string &rightName, Connection &connection, bool allowUI); + // authCheckRight() with exception-handling and Boolean return semantics + bool isRightAuthorized(string &rightName, Connection &connection, bool allowUI); + +protected: + void updateAudit() const; + +private: + struct AuthorizationExternalBlob { + AuthorizationBlob blob; + uint32_t session; + }; + +protected: + static AuthorizationToken &authorization(const AuthorizationBlob &blob); + OSStatus authGetRights(AuthorizationToken &auth, + const AuthItemSet &requestedRights, const AuthItemSet &environment, + AuthorizationFlags flags, AuthItemSet &grantedRights); + void mergeCredentials(CredentialSet &creds); + +public: + void invalidateSessionAuthHosts(); // invalidate auth hosts in this session + static void invalidateAuthHosts(); // invalidate auth hosts in all sessions + + static void processSystemSleep(); + void processLockAll(); + + RefPointer authhost(const AuthHostType hostType = securityAgent, const bool restart = false); + +protected: + mutable CommonCriteria::AuditInfo mAudit; + + mutable Mutex mCredsLock; // lock for mSessionCreds + CredentialSet mSessionCreds; // shared session authorization credentials + + mutable Mutex mAuthHostLock; + AuthHostInstance *mSecurityAgent; + AuthHostInstance *mAuthHost; + + CFRef mSessionAgentPrefs; + Credential mOriginatorCredential; + + void kill(); + +public: + void verifyKeyStorePassphrase(int32_t retries); + void changeKeyStorePassphrase(); + void resetKeyStorePassphrase(const CssmData &passphrase); + service_context_t get_current_service_context(); + void keybagClearState(int state); + void keybagSetState(int state); + bool keybagGetState(int state); +private: + int mKeybagState; + +public: + static Session &find(SessionId id, bool create); // find and optionally create + template static SessionType &find(SecuritySessionId id); + static void destroy(SessionId id); + +protected: + typedef std::map > SessionMap; + static SessionMap mSessions; + static Mutex mSessionLock; +}; + + +template +SessionType &Session::find(SecuritySessionId id) +{ + if (SessionType *ssn = dynamic_cast(&find(id, false))) + return *ssn; + else + MacOSError::throwMe(errSessionInvalidId); +} + + +// +// The RootSession is the session of all code that originates from system startup processing +// and does not belong to any particular login origin. (Or, if you prefer, whose login origin +// is the system itself.) +// +class RootSession : public Session { +public: + RootSession(uint64_t attributes, Server &server); + + CFDataRef copyUserPrefs() { return NULL; } +}; + + +// +// A DynamicSession object represents a session that is dynamically constructed +// when we first encounter it. These sessions are actually created in client +// space using the audit session APIs. +// We tear down a DynamicSession when the system reports (via kevents) that the +// kernel audit session object has been destroyed. +// +class DynamicSession : private ReceivePort, public Session { +public: + DynamicSession(const CommonCriteria::AuditInfo &audit); + + void setUserPrefs(CFDataRef userPrefsDict); + CFDataRef copyUserPrefs(); +}; + + +#endif //_H_SESSION diff --git a/securityd/src/structure.cpp b/securityd/src/structure.cpp new file mode 100644 index 00000000..b148a680 --- /dev/null +++ b/securityd/src/structure.cpp @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2000-2001,2004,2009 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@ + */ + + +// +// structure - structural framework for securityd objects +// +#include "structure.h" + + +// +// NodeCore always has a destructor (because it's virtual), +// but its dump support is conditionally included. +// +NodeCore::~NodeCore() +{ +#if defined(DEBUGDUMP) + StLock _(mCoreLock); + mCoreNodes.erase(this); +#endif //DEBUGDUMP +} + + +// +// Basic object mesh maintainance +// +void NodeCore::parent(NodeCore &p) +{ + StLock _(*this); + mParent = &p; +} + +void NodeCore::referent(NodeCore &r) +{ + StLock _(*this); + assert(!mReferent); + mReferent = &r; +} + +void NodeCore::clearReferent() +{ + StLock _(*this); + if (mReferent) + assert(!mReferent->hasReference(*this)); + mReferent = NULL; +} + + +void NodeCore::addReference(NodeCore &p) +{ + StLock _(*this); + assert(p.mReferent == this); + mReferences.insert(&p); +} + +void NodeCore::removeReference(NodeCore &p) +{ + StLock _(*this); + assert(hasReference(p)); + mReferences.erase(&p); +} + +#if !defined(NDEBUG) + +bool NodeCore::hasReference(NodeCore &p) +{ + assert(p.refCountForDebuggingOnly() > 0); + return mReferences.find(&p) != mReferences.end(); +} + +#endif //NDEBUG + + +// +// ClearReferences clears the reference set but does not propagate +// anything; it is NOT recursive. +// +void NodeCore::clearReferences() +{ + StLock _(*this); + secdebug("ssnode", "%p clearing all %d references", + this, int(mReferences.size())); + mReferences.erase(mReferences.begin(), mReferences.end()); +} + + +// +// Kill should be overloaded by Nodes to implement any cleanup and release +// operations that should happen at LOGICAL death of the represented object. +// This is where you should release ports, close files, etc. +// This default behavior, which you MUST include in your override, +// propagates kills to all active references, recursively. +// +void NodeCore::kill() +{ + StLock _(*this); + for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end(); it++) + (*it)->kill(); + clearReferences(); +} + + +void NodeCore::kill(NodeCore &ref) +{ + StLock _(*this); + assert(hasReference(ref)); + ref.kill(); + removeReference(ref); +} + + +// +// NodeCore-level support for state dumping. +// Call NodeCore::dumpAll() to debug-dump all nodes. +// Note that enabling DEBUGDUMP serializes all node creation/destruction +// operations, and thus may cause significant shifts in thread interactions. +// +#if defined(DEBUGDUMP) + +// The (uncounted) set of all known NodeCores in existence, with protective lock +set NodeCore::mCoreNodes; +Mutex NodeCore::mCoreLock; + +// add a new NodeCore to the known set +NodeCore::NodeCore() + : Mutex(Mutex::recursive) +{ + StLock _(mCoreLock); + mCoreNodes.insert(this); +} + +// partial-line common dump text for any NodeCore +// override this to add text to your Node type's state dump output +void NodeCore::dumpNode() +{ + Debug::dump("%s@%p rc=%u", Debug::typeName(*this).c_str(), this, unsigned(refCountForDebuggingOnly())); + if (mParent) + Debug::dump(" parent=%p", mParent.get()); + if (mReferent) + Debug::dump(" referent=%p", mReferent.get()); +} + +// full-line dump of a NodeCore +// override this to completely re-implement the dump format for your Node type +void NodeCore::dump() +{ + dumpNode(); + if (!mReferences.empty()) { + Debug::dump(" {"); + for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end(); it++) { + Debug::dump(" %p", it->get()); + if ((*it)->mReferent != this) + Debug::dump("!*INVALID*"); + } + Debug::dump(" }"); + } + Debug::dump("\n"); +} + +// dump all known nodes +void NodeCore::dumpAll() +{ + StLock _(mCoreLock); + time_t now; time(&now); + Debug::dump("\nNODE DUMP (%24.24s)\n", ctime(&now)); + for (set::const_iterator it = mCoreNodes.begin(); it != mCoreNodes.end(); it++) + (*it)->dump(); + Debug::dump("END NODE DUMP\n\n"); +} + +#endif //DEBUGDUMP diff --git a/securityd/src/structure.h b/securityd/src/structure.h new file mode 100644 index 00000000..d4f1c53f --- /dev/null +++ b/securityd/src/structure.h @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2000-2001,2004-2005,2007-2008 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@ + */ + + +// +// structure - structural framework for securityd objects +// +#ifndef _H_STRUCTURE +#define _H_STRUCTURE + +#include +#include +#include +#include +#include "dtrace.h" + +using MachPlusPlus::Port; + + +// +// Track a per-process real world object +// +template class Node; +class PerConnection; +class PerProcess; +class PerSession; +class PerGlobal; + + +// +// A generic core node of the object mesh. +// Repeat after me: "Everything that matters is a Node." +// +// This contains the mesh links (as smart pointers to NodeCores). +// The 'parent' is the next-more-global related object in the mesh, if any; +// nodes with the same parent "belong together" at the more global layer. +// For example, processes have their sessions as parents. +// The 'referent' is an object at the *same* globality layer that controls +// the lifetime of this node. For example, a Database has its Process as +// its referent. +// Both parent and referent are optional (can be NULL). +// The references set is a partial referent back-link. All NodeCores listed +// in a node's References have this node as a referent, but the set is +// selective (not necessarily complete). The References set propagates the +// 'kill' operation up the referents chain; thus being included in a node's +// References means that a kill() on the referent will (recursively) kill +// all references, too. +// +// Do not inherit directly from NodeCore; use Node<> (below). +// +class NodeCore : public RefCount, public Mutex { + template friend class Node; +public: +#if !defined(DEBUGDUMP) // (see below if DEBUGDUMP) + NodeCore() : Mutex(Mutex::recursive) { } +#endif + virtual ~NodeCore(); + + void addReference(NodeCore &p); + void removeReference(NodeCore &p); + + // reference set operations + template + void allReferences(void (Sub::*func)()); + template + RefPointer findFirst(Value (Sub::*func)() const, Value compare); + void clearReferences(); + + virtual void kill(); // kill all references and self + virtual void kill(NodeCore &ref); // kill ref from my references() + + // for STL ordering (so we can have sets of RefPointers of NodeCores) + bool operator < (const NodeCore &other) const + { return this < &other; } + +protected: + void parent(NodeCore &p); // set parent + void referent(NodeCore &r); // set referent + void clearReferent(); // clear referent + + bool hasParent() const { return mParent; } + bool hasReferent() const { return mReferent; } + +private: + RefPointer mParent; + RefPointer mReferent; + typedef set > ReferenceSet; + ReferenceSet mReferences; + + IFDEBUG(bool hasReference(NodeCore &p)); + +#if defined(DEBUGDUMP) +public: // dump support + NodeCore(); // dump-only constructor (registers node) + + virtual void dumpNode(); // node description (partial line) + virtual void dump(); // dumpNode() + references + NL + static void dumpAll(); // dump all nodes + + static Mutex mCoreLock; // lock for mCoreNodes + static set mCoreNodes; // (debug) set of all known nodes +#endif //DEBUGDUMP +}; + + +// +// Call a member on each reference of a Node<> object. +// The object lock is held throughout, and we keep a RefPointer to each object +// as it's being processed. Thus it's safe for a reference to self-unlink in +// the object mesh; it'll get destroyed after its method returns. +// +template +void NodeCore::allReferences(void (Sub::*func)()) +{ + StLock _(*this); + for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end();) + if (RefPointer sub = dynamic_cast((it++)->get())) + (sub->*func)(); +} + + +// +// Find a reference of a Node<> object that satisfies a simple "method returns value" +// condition. There is no defined order of the scan, so if the condition is not unique, +// any one reference may be returned. If none are found, we return NULL. +// This returns a RefPointer: lifetime of the returned instance (if any) is ensured even +// if it is asynchronously removed from the references set. +// +template +RefPointer NodeCore::findFirst(Value (Sub::*func)() const, Value compare) +{ + StLock _(*this); + for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end(); it++) + if (Sub *sub = dynamic_cast(it->get())) + if ((sub->*func)() == compare) + return sub; + return NULL; +} + + +// +// A typed node of the object mesh. +// This adds type-safe accessors and modifiers to NodeCore. +// +template +class Node : public NodeCore { +protected: + // type-safer versions of node mesh setters + void parent(Glob &p) { NodeCore::parent(p); } + void referent(Base &r) { NodeCore::referent(r); } + +public: + template + T& parent() const + { assert(mParent); return safer_cast(*mParent); } + + template + T& referent() const + { assert(mReferent); return safer_cast(*mReferent); } + +public: + void addReference(Base &p) { NodeCore::addReference(p); } + void removeReference(Base &p) { NodeCore::removeReference(p); } +}; + + +// +// Connection (client thread) layer nodes +// +class PerConnection : public Node { +public: +}; + + +// +// Process (client process) layer nodes +// +class PerProcess : public U32HandleObject, public Node { +public: +}; + + +// +// Session (client-side session) layer nodes +// +class PerSession : public Node { +public: +}; + + +// +// Global (per-system) layer nodes +// +class PerGlobal : public Node { +public: +}; + + +// +// A map from mach port names to (refcounted) pointers-to-somethings +// +template +class PortMap : public Mutex, public std::map > { + typedef std::map > _Map; +public: + bool contains(mach_port_t port) const { return this->find(port) != this->end(); } + Node *getOpt(mach_port_t port) const + { + typename _Map::const_iterator it = this->find(port); + return (it == this->end()) ? NULL : it->second; + } + + Node *get(mach_port_t port) const + { + typename _Map::const_iterator it = this->find(port); + assert(it != this->end()); + return it->second; + } + + Node *get(mach_port_t port, OSStatus error) const + { + typename _Map::const_iterator it = this->find(port); + if (it == this->end()) + MacOSError::throwMe(error); + return it->second; + } + + void dump(); +}; + +template +void PortMap::dump() +{ + for (typename _Map::const_iterator it = this->begin(); it != this->end(); it++) + it->second->dump(); +} + + +#endif //_H_STRUCTURE diff --git a/securityd/src/tempdatabase.cpp b/securityd/src/tempdatabase.cpp new file mode 100644 index 00000000..ed08fd1c --- /dev/null +++ b/securityd/src/tempdatabase.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2004,2008-2009,2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * 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@ + */ + + +// +// tempdatabase - temporary (scratch) storage for keys +// +#include +#include +#include +#include "tempdatabase.h" +#include "localkey.h" +#include "server.h" +#include "session.h" +#include "agentquery.h" + + +// +// Temporary-space Key objects are almost normal LocalKeys, with the key +// matter always preloaded (and thus no deferral of instantiation). +// A TempKey bears its own ACL. +// +class TempKey : public LocalKey, public SecurityServerAcl { +public: + TempKey(Database &db, const CssmKey &newKey, uint32 moreAttributes, + const AclEntryPrototype *owner = NULL); + + Database *relatedDatabase(); + + SecurityServerAcl &acl() { return *this; } + +public: + // SecurityServerAcl personality + AclKind aclKind() const; +}; + + +TempKey::TempKey(Database &db, const CssmKey &newKey, uint32 moreAttributes, + const AclEntryPrototype *owner) + : LocalKey(db, newKey, moreAttributes) +{ + setOwner(owner); + db.addReference(*this); +} + + +AclKind TempKey::aclKind() const +{ + return keyAcl; +} + + +Database *TempKey::relatedDatabase() +{ + return NULL; +} + + +// +// Create a Database object from initial parameters (create operation) +// +TempDatabase::TempDatabase(Process &proc) + : LocalDatabase(proc) +{ + proc.addReference(*this); +} + + +// +// A LocalDatabase itself doesn't really have a database name, +// but here's an innocent placeholder. +// +const char *TempDatabase::dbName() const +{ + return "(transient)"; +} + +bool TempDatabase::transient() const +{ + return true; +} + + +// +// Invoke the Security Agent to get a passphrase (other than for a Keychain) +// +void TempDatabase::getSecurePassphrase(const Context &context, + string &passphrase) +{ + uint32 verify = context.getInt(CSSM_ATTRIBUTE_VERIFY_PASSPHRASE, CSSMERR_CSSM_ATTRIBUTE_NOT_IN_CONTEXT); + + CssmData *promptData = context.get(CSSM_ATTRIBUTE_PROMPT); + + QueryGenericPassphrase agentQuery; + agentQuery.inferHints(Server::process()); + agentQuery(promptData, verify, passphrase); +} + + +void TempDatabase::makeSecurePassphraseKey(const Context &context, + const AccessCredentials *cred, + const AclEntryPrototype *owner, + uint32 usage, uint32 attrs, + RefPointer &newKey) +{ + secdebug("SSdb", "requesting secure passphrase"); + + string passphrase; + getSecurePassphrase(context, passphrase); + + secdebug("SSdb", "wrapping securely-obtained passphrase as key"); + + // CssmKey rawKey(StringData(passphrase)) confuses gcc + StringData passphraseData(passphrase); + CssmKey rawKey(passphraseData); + rawKey.algorithm(context.algorithm()); + rawKey.blobType(CSSM_KEYBLOB_RAW); + rawKey.blobFormat(CSSM_KEYBLOB_WRAPPED_FORMAT_NONE); + rawKey.keyClass(CSSM_KEYCLASS_SESSION_KEY); + + CssmClient::UnwrapKey unwrap(Server::csp(), CSSM_ALGID_NONE); + CssmKey cspKey; + unwrap(rawKey, TempKey::KeySpec(usage, attrs), cspKey); + + newKey = makeKey(cspKey, attrs & TempKey::managedAttributes, owner); +} + + +// +// Obtain "secure passphrases" for the CSP. Useful for PKCS 12. +// +void TempDatabase::generateKey(const Context &context, + const AccessCredentials *cred, + const AclEntryPrototype *owner, + uint32 usage, uint32 attrs, + RefPointer &newKey) +{ + switch (context.algorithm()) + { + case CSSM_ALGID_SECURE_PASSPHRASE: + makeSecurePassphraseKey(context, cred, owner, usage, attrs, newKey); + break; + default: + LocalDatabase::generateKey(context, cred, owner, usage, attrs, newKey); + return; + } +} + + +// +// Make a new TempKey +// +RefPointer TempDatabase::makeKey(const CssmKey &newKey, + uint32 moreAttributes, const AclEntryPrototype *owner) +{ + assert(!newKey.attribute(CSSM_KEYATTR_PERMANENT)); + return new TempKey(*this, newKey, moreAttributes, owner); +} diff --git a/securityd/src/tempdatabase.h b/securityd/src/tempdatabase.h new file mode 100644 index 00000000..10195543 --- /dev/null +++ b/securityd/src/tempdatabase.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2004 Apple Computer, 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@ + */ + + +// +// tempdatabase - temporary (scratch) storage for keys +// +// A TempDatabase locally manages keys using the AppleCSP while providing +// no persistent storage. Keys live until they are no longer referenced in +// client space, at which point they are destroyed. +// +#ifndef _H_TEMPDATABASE +#define _H_TEMPDATABASE + +#include "localdatabase.h" + + +// +// A TempDatabase is simply a container of (a subclass of) LocalKey. +// When it dies, all its contents irretrievably vanish. There is no DbCommon +// or global object; each TempDatabase is completely distinct. +// Database ACLs are not (currently) supported on TempDatabases. +// +class TempDatabase : public LocalDatabase { +public: + TempDatabase(Process &proc); + + const char *dbName() const; + bool transient() const; + + RefPointer makeKey(const CssmKey &newKey, uint32 moreAttributes, + const AclEntryPrototype *owner); + + void generateKey(const Context &context, + const AccessCredentials *cred, + const AclEntryPrototype *owner, uint32 usage, + uint32 attrs, RefPointer &newKey); + +protected: + void getSecurePassphrase(const Context &context, string &passphrase); + void makeSecurePassphraseKey(const Context &context, const AccessCredentials *cred, + const AclEntryPrototype *owner, uint32 usage, + uint32 attrs, RefPointer &newKey); +}; + +#endif //_H_TEMPDATABASE diff --git a/securityd/src/token.cpp b/securityd/src/token.cpp new file mode 100644 index 00000000..4dc47dfa --- /dev/null +++ b/securityd/src/token.cpp @@ -0,0 +1,512 @@ +/* + * Copyright (c) 2004-2008,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@ + */ + + +// +// token - internal representation of a (single distinct) hardware token +// +#include "token.h" +#include "tokendatabase.h" +#include "reader.h" +#include "notifications.h" +#include "child.h" +#include "server.h" +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace MDSClient; + + +// +// SSID -> Token map +// +Token::SSIDMap Token::mSubservices; +// Make sure to always take mSSIDLock after we take the Token lock +// itself or own it's own. +Mutex Token::mSSIDLock; + + +// +// Token construction and destruction is trivial; the good stuff +// happens in insert() and remove() below. +// +Token::Token() + : mFaulted(false), mTokend(NULL), mResetLevel(1) +{ + secdebug("token", "%p created", this); +} + + +Token::~Token() +{ + secdebug("token", "%p (%s:%d) destroyed", + this, mGuid.toString().c_str(), mSubservice); +} + + +Reader &Token::reader() const +{ + return referent< ::Reader>(); +} + +TokenDaemon &Token::tokend() +{ + StLock _(*this); + if (mFaulted) + CssmError::throwMe(CSSM_ERRCODE_DEVICE_FAILED); + if (mTokend) + return *mTokend; + else + CssmError::throwMe(CSSM_ERRCODE_DEVICE_FAILED); +} + + +// +// We don't currently use a database handle to tokend. +// This is just to satisfy the TokenAcl. +// +GenericHandle Token::tokenHandle() const +{ + return noDb; // we don't currently use tokend-side DbHandles +} + + +// +// Token is the SecurityServerAcl for the token +// +AclKind Token::aclKind() const +{ + return dbAcl; +} + +Token &Token::token() +{ + return *this; +} + + +// +// Find Token by subservice id. +// Throws if ssid is invalid (i.e. always returns non-NULL) +// +RefPointer Token::find(uint32 ssid) +{ + StLock _(mSSIDLock); + SSIDMap::const_iterator it = mSubservices.find(ssid); + if (it == mSubservices.end()) + CssmError::throwMe(CSSMERR_CSSM_INVALID_SUBSERVICEID); + else + return it->second; +} + + +// +// We override getAcl to provide PIN state feedback +// +void Token::getAcl(const char *tag, uint32 &count, AclEntryInfo *&acls) +{ + if (pinFromAclTag(tag, "?")) { // read from tokend - do not cache + AclEntryInfo *racls; + token().tokend().getAcl(aclKind(), tokenHandle(), tag, count, racls); + // make a chunk-copy because that's the contract we have with the caller + acls = Allocator::standard().alloc(count * sizeof(AclEntryInfo)); + memcpy(acls, racls, count * sizeof(AclEntryInfo)); + ChunkCopyWalker copy; + for (uint32 n = 0; n < count; n++) + walk(copy, acls[n]); + return; + } + + TokenAcl::cssmGetAcl(tag, count, acls); +} + + +// +// Reset management. +// A Token has a "reset level", a number that is incremented whenever a token +// (hardware) reset is reported (as an error) by tokend. TokenAcls have their +// own matching level, which is that of the Token's when the ACL was last synchronized +// with tokend. Thus, incrementing the reset level invalidates all TokenAcls +// (without the need to enumerate them all). +// Note that a Token starts with a level of 1, while ACLs start at zero. This forces +// them to initially load their state from tokend. +// +Token::ResetGeneration Token::resetGeneration() const +{ + return mResetLevel; +} + +void Token::resetAcls() +{ + CommonSet tmpCommons; + { + StLock _(*this); + mResetLevel++; + secdebug("token", "%p reset (level=%d, propagating to %ld common(s)", + this, mResetLevel, mCommons.size()); + // Make a copy to avoid deadlock with TokenDbCommon lock + tmpCommons = mCommons; + } + for (CommonSet::const_iterator it = tmpCommons.begin(); it != tmpCommons.end();) + RefPointer(*it++)->resetAcls(); +} + +void Token::addCommon(TokenDbCommon &dbc) +{ + secdebug("token", "%p addCommon TokenDbCommon %p", this, &dbc); + mCommons.insert(&dbc); +} + +void Token::removeCommon(TokenDbCommon &dbc) +{ + secdebug("token", "%p removeCommon TokenDbCommon %p", this, &dbc); + if (mCommons.find(&dbc) != mCommons.end()) + mCommons.erase(&dbc); +} + + +// +// Process the logical insertion of a Token into a Reader. +// From the client's point of view, this is where the CSSM subservice is created, +// characterized, and activated. From tokend's point of view, this is where +// we're analyzing the token, determine its characteristics, and get ready to +// use it. +// +void Token::insert(::Reader &slot, RefPointer tokend) +{ + try { + // this might take a while... + Server::active().longTermActivity(); + referent(slot); + mState = slot.pcscState(); + + if (tokend == NULL) { + // no pre-determined Tokend - search for one + if (!(tokend = chooseTokend())) { + secdebug("token", "%p no token daemons available - faulting this card", this); + fault(false); // throws + } + } + + // take Token lock and hold throughout insertion + StLock _(*this); + + Syslog::debug("token inserted into reader %s", slot.name().c_str()); + secdebug("token", "%p begin insertion into slot %p (reader %s)", + this, &slot, slot.name().c_str()); + + // tell the tokend object to relay faults to us + tokend->faultRelay(this); + + // locate or establish cache directories + if (tokend->hasTokenUid()) { + secdebug("token", "%p using %s (score=%d, uid=\"%s\")", + this, tokend->bundlePath().c_str(), tokend->score(), tokend->tokenUid().c_str()); + mCache = new TokenCache::Token(reader().cache, + tokend->bundleIdentifier() + ":" + tokend->tokenUid()); + } else { + secdebug("token", "%p using %s (score=%d, temporary)", + this, tokend->bundlePath().c_str(), tokend->score()); + mCache = new TokenCache::Token(reader().cache); + } + secdebug("token", "%p token cache at %s", this, mCache->root().c_str()); + + // here's the primary parameters of the new subservice + mGuid = gGuidAppleSdCSPDL; + mSubservice = mCache->subservice(); + + // establish work areas with tokend + char mdsDirectory[PATH_MAX]; + char printName[PATH_MAX]; + tokend->establish(mGuid, mSubservice, + (mCache->type() != TokenCache::Token::existing ? kSecTokendEstablishNewCache : 0) | kSecTokendEstablishMakeMDS, + mCache->cachePath().c_str(), mCache->workPath().c_str(), + mdsDirectory, printName); + + // establish print name + if (mCache->type() == TokenCache::Token::existing) { + mPrintName = mCache->printName(); + if (mPrintName.empty()) + mPrintName = printName; + } else + mPrintName = printName; + if (mPrintName.empty()) { + // last resort - new card and tokend didn't give us one + snprintf(printName, sizeof(printName), "smart card #%d", mSubservice); + mPrintName = printName; + } + if (mCache->type() != TokenCache::Token::existing) + mCache->printName(mPrintName); // store in cache + + // install MDS + secdebug("token", "%p installing MDS from %s(%s)", this, + tokend->bundlePath().c_str(), + mdsDirectory[0] ? mdsDirectory : "ALL"); + string holdGuid = mGuid.toString(); // extend lifetime of std::string + string holdTokenUid; + if (tokend->hasTokenUid()) + holdTokenUid = tokend->tokenUid(); + string holdPrintName = this->printName(); + MDS_InstallDefaults mdsDefaults = { + holdGuid.c_str(), + mSubservice, + holdTokenUid.c_str(), + holdPrintName.c_str() + }; + mds().install(&mdsDefaults, + tokend->bundlePath().c_str(), + mdsDirectory[0] ? mdsDirectory : NULL, + NULL); + + { + // commit to insertion + StLock _(mSSIDLock); + assert(mSubservices.find(mSubservice) == mSubservices.end()); + mSubservices.insert(make_pair(mSubservice, this)); + } + + // assign mTokend right before notification - mustn't be set if + // anything goes wrong during insertion + mTokend = tokend; + + notify(kNotificationCDSAInsertion); + + Syslog::notice("reader %s inserted token \"%s\" (%s) subservice %ld using driver %s", + slot.name().c_str(), mPrintName.c_str(), + mTokend->hasTokenUid() ? mTokend->tokenUid().c_str() : "NO UID", + mSubservice, mTokend->bundleIdentifier().c_str()); + secdebug("token", "%p inserted as %s:%d", this, mGuid.toString().c_str(), mSubservice); + } catch (const CommonError &err) { + Syslog::notice("token in reader %s cannot be used (error %ld)", slot.name().c_str(), err.osStatus()); + secdebug("token", "exception during insertion processing"); + fault(false); + } catch (...) { + // exception thrown during insertion processing. Mark faulted + Syslog::notice("token in reader %s cannot be used", slot.name().c_str()); + secdebug("token", "exception during insertion processing"); + fault(false); + } +} + + +// +// Process the logical removal of a Token from a Reader. +// Most of the time, this is asynchronous - someone has yanked the physical +// token out of a physical slot, and we're left with changing our universe +// to conform to the new realities. Reality #1 is that we can't talk to the +// physical token anymore. +// +// Note that if we're in FAULT mode, there really isn't a TokenDaemon around +// to kick. We're just holding on to represent the fact that there *is* a (useless) +// token in the slot, and now it's been finally yanked. Good riddance. +// +void Token::remove() +{ + StLock _(*this); + Syslog::notice("reader %s removed token \"%s\" (%s) subservice %ld", + reader().name().c_str(), mPrintName.c_str(), + mTokend + ? (mTokend->hasTokenUid() ? mTokend->tokenUid().c_str() : "NO UID") + : "NO tokend", + mSubservice); + secdebug("token", "%p begin removal from slot %p (reader %s)", + this, &reader(), reader().name().c_str()); + if (mTokend) + mTokend->faultRelay(NULL); // unregister (no more faults, please) + mds().uninstall(mGuid.toString().c_str(), mSubservice); + secdebug("token", "%p mds uninstall complete", this); + this->kill(); + secdebug("token", "%p kill complete", this); + notify(kNotificationCDSARemoval); + secdebug("token", "%p removal complete", this); +} + + +// +// Set the token to fault state. +// This essentially "cuts off" all operations on an inserted token and makes +// them fail. It also sends a FAULT notification via CSSM to any clients. +// Only one fault is actually processed; multiple calls are ignored. +// +// Note that a faulted token is not REMOVED; it's still physically present. +// No fault is declared when a token is actually removed. +// +void Token::fault(bool async) +{ + StLock _(*this); + if (!mFaulted) { // first one + secdebug("token", "%p %s FAULT", this, async ? "ASYNCHRONOUS" : "SYNCHRONOUS"); + + // mark faulted + mFaulted = true; + + // send CDSA notification + notify(kNotificationCDSAFailure); + + // cast off our TokenDaemon for good +//>>> mTokend = NULL; + } + + // if this is a synchronous fault, abort this operation now + if (!async) + CssmError::throwMe(CSSM_ERRCODE_DEVICE_FAILED); +} + + +void Token::relayFault(bool async) +{ + secdebug("token", "%p fault relayed from tokend", this); + this->fault(async); +} + + +// +// This is the "kill" hook for Token as a Node<> object. +// +void Token::kill() +{ + // Avoid holding the lock across call to resetAcls + // This can cause deadlock on card removal + { + StLock _(*this); + if (mTokend) + { + mTokend = NULL; // cast loose our tokend (if any) + // Take us out of the map + StLock _(mSSIDLock); + SSIDMap::iterator it = mSubservices.find(mSubservice); + assert(it != mSubservices.end() && it->second == this); + if (it != mSubservices.end() && it->second == this) + mSubservices.erase(it); + } + } + + resetAcls(); // release our TokenDbCommons + PerGlobal::kill(); // generic action + +} + + +// +// Send CDSA-layer notifications for this token. +// These events are usually received by CDSA plugins working with securityd. +// +void Token::notify(NotificationEvent event) +{ + NameValueDictionary nvd; + CssmSubserviceUid ssuid(mGuid, NULL, h2n (mSubservice), + h2n(CSSM_SERVICE_DL | CSSM_SERVICE_CSP)); + nvd.Insert(new NameValuePair(SSUID_KEY, CssmData::wrap(ssuid))); + CssmData data; + nvd.Export(data); + + // inject notification into Security event system + Listener::notify(kNotificationDomainCDSA, event, data); + + // clean up + free (data.data()); +} + + +// +// Choose a token daemon for our card. +// +// Right now, we probe tokends sequentially. If there are many tokends, it would be +// faster to launch them in parallel (relying on PCSC transactions to separate them); +// but it's not altogether clear whether this would slow things down on low-memory +// systems by forcing (excessive) swapping. There is room for future experimentation. +// +RefPointer Token::chooseTokend() +{ + //@@@ CodeRepository should learn to update from disk changes to be re-usable + CodeRepository candidates("Security/tokend", ".tokend", "TOKENDAEMONPATH", false); + candidates.update(); + //@@@ we could sort by reverse "maxScore" and avoid launching those who won't cut it anyway... + + RefPointer leader; + for (CodeRepository::const_iterator it = candidates.begin(); + it != candidates.end(); it++) { + RefPointer candidate = *it; + try { + // skip software token daemons - ineligible for automatic choosing + if (CFTypeRef type = (*it)->infoPlistItem("TokendType")) + if (CFEqual(type, CFSTR("software"))) + continue; + + // okay, launch it and let it try + RefPointer tokend = new TokenDaemon(candidate, + reader().name(), reader().pcscState(), reader().cache); + + if (tokend->state() == ServerChild::dead) // ah well, this one's no good + continue; + + // probe the (single) tokend + if (!tokend->probe()) // non comprende... + continue; + + // we got a contender! + if (!leader || tokend->score() > leader->score()) + leader = tokend; // a new front runner, he is... + } catch (...) { + secdebug("token", "exception setting up %s (moving on)", candidate->canonicalPath().c_str()); + } + } + return leader; +} + + +// +// Token::Access mediates calls through TokenDaemon to the actual daemon out there. +// +Token::Access::Access(Token &myToken) + : token(myToken) +{ + mTokend = &token.tokend(); // throws if faulted or otherwise inappropriate +} + +Token::Access::~Access() +{ +} + + +// +// Debug dump support +// +#if defined(DEBUGDUMP) + +void Token::dumpNode() +{ + PerGlobal::dumpNode(); + Debug::dump(" %s[%d] tokend=%p", + mGuid.toString().c_str(), mSubservice, mTokend.get()); +} + +#endif //DEBUGDUMP diff --git a/securityd/src/token.h b/securityd/src/token.h new file mode 100644 index 00000000..dadfc9f1 --- /dev/null +++ b/securityd/src/token.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2004,2007-2008 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@ + */ + + +// +// token - internal representation of a (single distinct) hardware token +// +#ifndef _H_TOKEN +#define _H_TOKEN + +#include "structure.h" +#include "tokencache.h" +#include "tokenacl.h" +#include "tokend.h" +#include +#include + +class Reader; +class TokenDbCommon; + + +// +// Token is the global-scope object representing a smartcard token. +// It also acts as the global-scope database object for the TokenDatabase representing +// its content, and carries the ObjectAcls for objects on the token. +// +class Token : public PerGlobal, public virtual TokenAcl, public FaultRelay { +public: + class Access; friend class Access; + +public: + Token(); + ~Token(); + + ::Reader &reader() const; + TokenDaemon &tokend(); + GenericHandle tokenHandle() const; + uint32 subservice() const { return mSubservice; } + std::string printName() const { return mPrintName; } + TokenCache::Token &cache() const { return *mCache; } + + void insert(::Reader &slot, RefPointer tokend); + void remove(); + + void notify(NotificationEvent event); + void fault(bool async); + + void kill(); + + IFDUMP(void dumpNode()); + + static RefPointer find(uint32 ssid); + + void getAcl(const char *tag, uint32 &count, AclEntryInfo *&acls); + ResetGeneration resetGeneration() const; + bool resetGeneration(ResetGeneration rg) const { return rg == resetGeneration(); } + void resetAcls(); + +public: + // SecurityServerAcl and TokenAcl personalities + AclKind aclKind() const; + Token &token(); // myself + + // FaultRelay personality + void relayFault(bool async); + +public: + class Access { + public: + Access(Token &token); + ~Access(); + + Token &token; + + TokenDaemon &tokend() const { return *mTokend; } + TokenDaemon &operator () () const { return tokend(); } + + private: + RefPointer mTokend; + }; + +public: + // keep track of TokenDbCommons for reset processing + // (this interface is for TokenDbCommon only) + void addCommon(TokenDbCommon &dbc); + void removeCommon(TokenDbCommon &dbc); + +private: + RefPointer chooseTokend(); + +private: + bool mFaulted; // fault state flag + RefPointer mTokend; // the (one) tokend that runs the card + RefPointer mCache; // token cache reference + std::string mPrintName; // print name of token + + Guid mGuid; // our CSP/DL's Guid + uint32 mSubservice; // dynamic subservice of gGuidAppleSdCSPDL + PCSC::ReaderState mState; // reader state as of insertion + + TokenDaemon::Score mScore; // score of winning tokend + +private: + typedef map SSIDMap; + static SSIDMap mSubservices; + static Mutex mSSIDLock; + + typedef set CommonSet; + CommonSet mCommons; + ResetGeneration mResetLevel; +}; + + +#endif //_H_TOKEN diff --git a/securityd/src/tokenaccess.cpp b/securityd/src/tokenaccess.cpp new file mode 100644 index 00000000..4a1aad55 --- /dev/null +++ b/securityd/src/tokenaccess.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2004,2006 Apple Computer, 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@ + */ + + +// +// tokenaccess - access management to a TokenDatabase's Token's TokenDaemon's tokend +// +#include "tokenaccess.h" + + +// +// Process an exception thrown (presumably) by a TokenDaemon interface call. +// +void Access::operator () (const CssmError &err) +{ + if (++mIteration > 2) { + secdebug("tokendb", "retry failed; aborting operation"); + throw; + } + + //@@@ hack until tokend returns RESET + if (err.error == -1) { + secdebug("tokendb", "TEMP HACK (error -1) action - reset and retry"); + token.resetAcls(); + return; + } + + if (CSSM_ERR_IS_CONVERTIBLE(err.error)) + switch (CSSM_ERRCODE(err.error)) { + case CSSM_ERRCODE_OPERATION_AUTH_DENIED: + case CSSM_ERRCODE_OBJECT_USE_AUTH_DENIED: + // @@@ do something more focused here, but for now... + secdebug("tokendb", "tokend denies auth; we're punting for now"); + throw; + case CSSM_ERRCODE_DEVICE_RESET: + secdebug("tokendb", "tokend signals reset; clearing and retrying"); + token.resetAcls(); + return; // induce retry + } + // all others are non-recoverable + secdebug("tokendb", "non-recoverable error in Access(): %d", err.error); + throw; +} diff --git a/securityd/src/tokenaccess.h b/securityd/src/tokenaccess.h new file mode 100644 index 00000000..2ad4211a --- /dev/null +++ b/securityd/src/tokenaccess.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2004 Apple Computer, 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@ + */ + + +// +// tokenaccess - access management to a TokenDatabase's Token's TokenDaemon's tokend +// +#ifndef _H_TOKENACCESS +#define _H_TOKENACCESS + +#include "tokendatabase.h" +#include "tokenkey.h" +#include "server.h" + + +// +// Turn a Key into a TokenKey, when we know that it's that +// +inline TokenKey &myKey(Key &key) +{ + return safer_cast(key); +} + + +// +// The common access/retry/management framework for calls that go to the actual daemon. +// +class Access : public Token::Access { +public: + Access(Token &token) : Token::Access(token), mIteration(0) + { Server::active().longTermActivity(); } + template + Access(Token &token, Whatever &it) : Token::Access(token) + { add(it); Server::active().longTermActivity(); } + + void operator () (const CssmError &err); + using Token::Access::operator (); + + void add(TokenAcl &acl) { mAcls.insert(&acl); } + void add(TokenAcl *acl) { if (acl) mAcls.insert(acl); } + void add(AclSource &src) { add(dynamic_cast(src.acl())); } + void add(AclSource *src) { if (src) add(*src); } + void add(Key &key) { mAcls.insert(&myKey(key)); } + +private: + set mAcls; // TokenAcl subclasses to clear on retry + unsigned int mIteration; // iteration count (try, retry, give up) +}; + + +// +// A nice little macro bracket to apply it. +// You must declare an Access called 'access' before doing +// TRY +// some actions +// GUARD(a call to tokend) +// DONE +// +#define TRY for (;;) { +#define GUARD try { +#define DONE return; \ + } catch (const CssmError &error) { \ + access(error); \ + } } + + +#endif //_H_TOKENACCESS diff --git a/securityd/src/tokenacl.cpp b/securityd/src/tokenacl.cpp new file mode 100644 index 00000000..cdba2afa --- /dev/null +++ b/securityd/src/tokenacl.cpp @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2004-2007,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@ + */ + + +// +// tokenacl - Token-based ACL implementation +// +#include "tokenacl.h" +#include "tokend.h" +#include "token.h" +#include "tokendatabase.h" +#include "agentquery.h" +#include +#include + + +// +// A TokenAcl initializes to "invalid, needs update". +// Note how our Token will start its ResetGeneration at 1, while we start at zero. +// +TokenAcl::TokenAcl() + : mLastReset(0) +{ +} + + +// +// Instantiate is called (by the ACL machinery core) before this ACL object's +// contents are used in any way. Here is where we fetch the ACL data from tokend +// (if we haven't got it yet). +// +void TokenAcl::instantiateAcl() +{ + if (token().resetGeneration(mLastReset)) + return; + + secdebug("tokenacl", "%p loading ACLs from tokend", this); + + // read owner + AclOwnerPrototype *owner = NULL; + token().tokend().getOwner(aclKind(), tokenHandle(), owner); + assert(owner); + + // read entries + uint32 count; + AclEntryInfo *infos; + token().tokend().getAcl(aclKind(), tokenHandle(), NULL, count, infos); + + // commit to setting the ACL data + ObjectAcl::owner(*owner); + ObjectAcl::entries(count, infos); + + // and if we actually made it to here... + mLastReset = token().resetGeneration(); +} + + +// +// The ACL machinery core calls this after successfully making changes to our ACL. +// +void TokenAcl::changedAcl() +{ +} + + +// +// CSSM-layer read gates. This accesses a cached version prepared in our instantiateAcl(). +// +void TokenAcl::getOwner(AclOwnerPrototype &owner) +{ + ObjectAcl::cssmGetOwner(owner); +} + +void TokenAcl::getAcl(const char *tag, uint32 &count, AclEntryInfo *&acls) +{ + ObjectAcl::cssmGetAcl(tag, count, acls); +} + + +// +// CSSM-layer write gates. +// This doesn't directly write to the local ObjectAcl at all. The call is relayed to +// tokend, and the resulting ACL is being re-read when next needed. +// +void TokenAcl::changeAcl(const AclEdit &edit, const AccessCredentials *cred, Database *db) +{ + // changeAcl from/to a PIN (source) ACL has special UI handling here + // @@@ this is an ad-hoc hack; general solution awaits the ACL machinery rebuild later + instantiateAcl(); // (redundant except in error cases) + if (TokenDatabase *tokenDb = dynamic_cast(db)) + if (edit.mode() == CSSM_ACL_EDIT_MODE_REPLACE) + if (const AclEntryInput *input = edit.newEntry()) { + if (unsigned pin = pinFromAclTag(input->proto().tag())) { + // assume this is a PIN change request + pinChange(pin, edit.handle(), *tokenDb); + invalidateAcl(); + return; + } + } + + // hand the request off to tokend to do as it will + token().tokend().changeAcl(aclKind(), tokenHandle(), Required(cred), edit); + invalidateAcl(); +} + +void TokenAcl::changeOwner(const AclOwnerPrototype &newOwner, + const AccessCredentials *cred, Database *db) +{ + token().tokend().changeOwner(aclKind(), tokenHandle(), Required(cred), newOwner); + invalidateAcl(); +} + + +// +// Ad-hoc PIN change processing. +// This cooks a suitable changeAcl call to tokend, ad hoc. +// It does NOT complete the originating request; it replaces it completely. +// (Completion processing requires not-yet-implemented ACL machine UI coalescing features.) +// +class QueryNewPin : public QueryNewPassphrase { +public: + QueryNewPin(unsigned int pinn, CSSM_ACL_HANDLE h, TokenDatabase &db, Reason reason) + : QueryNewPassphrase(db, reason), pin(pinn), handle(h) { } + + const unsigned int pin; + const CSSM_ACL_HANDLE handle; + + Reason accept(CssmManagedData &passphrase, CssmData *oldPassphrase); +}; + +SecurityAgent::Reason QueryNewPin::accept(CssmManagedData &passphrase, CssmData *oldPassphrase) +{ + assert(oldPassphrase); // we don't handle the new-pin case (yet) + + // form a changeAcl query and send it to tokend + try { + TrackingAllocator alloc(Allocator::standard()); + AclEntryPrototype proto(TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD, + new(alloc) ListElement(passphrase) + )); + proto.authorization() = AuthorizationGroup(CSSM_ACL_AUTHORIZATION_PREAUTH(pin), alloc); + char pintag[20]; sprintf(pintag, "PIN%d", pin); + proto.tag(pintag); + AclEntryInput input(proto); + AclEdit edit(CSSM_ACL_EDIT_MODE_REPLACE, handle, &input); + AutoCredentials cred(alloc); + cred += TypedList(alloc, CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD, + new(alloc) ListElement(*oldPassphrase)); + safer_cast(database).token().tokend().changeAcl(dbAcl, noDb, cred, edit); + return SecurityAgent::noReason; + } catch (const CssmError &err) { + switch (err.error) { + default: + return SecurityAgent::unknownReason; + } + } catch (...) { + return SecurityAgent::unknownReason; + } +} + +void TokenAcl::pinChange(unsigned int pin, CSSM_ACL_HANDLE handle, TokenDatabase &database) +{ + QueryNewPin query(pin, handle, database, SecurityAgent::changePassphrase); + query.inferHints(Server::process()); + CssmAutoData newPin(Allocator::standard(Allocator::sensitive)); + CssmAutoData oldPin(Allocator::standard(Allocator::sensitive)); + switch (query(oldPin, newPin)) { + case SecurityAgent::noReason: // worked + return; + default: + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); + } +} diff --git a/securityd/src/tokenacl.h b/securityd/src/tokenacl.h new file mode 100644 index 00000000..5268c959 --- /dev/null +++ b/securityd/src/tokenacl.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2004 Apple Computer, 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_TOKENACL +#define _H_TOKENACL + + +// +// tokenacl - Token-based ACL implementation +// +#include "acls.h" +#include + +class Token; +class TokenDatabase; + + +// +// The Token version of a SecurityServerAcl. +// +class TokenAcl : public virtual SecurityServerAcl { +public: + TokenAcl(); + + typedef unsigned int ResetGeneration; + +public: + // implement SecurityServerAcl + void getOwner(AclOwnerPrototype &owner); + void getAcl(const char *tag, uint32 &count, AclEntryInfo *&acls); + void changeAcl(const AclEdit &edit, const AccessCredentials *cred, + Database *relatedDatabase); + void changeOwner(const AclOwnerPrototype &newOwner, const AccessCredentials *cred, + Database *relatedDatabase); + + void instantiateAcl(); + void changedAcl(); + +public: + // required from our MDC + virtual Token &token() = 0; + virtual GenericHandle tokenHandle() const = 0; + +protected: + void invalidateAcl() { mLastReset = 0; } + void pinChange(unsigned int pin, CSSM_ACL_HANDLE handle, TokenDatabase &database); + +private: + ResetGeneration mLastReset; +}; + + +#endif //_H_TOKENACL diff --git a/securityd/src/tokencache.cpp b/securityd/src/tokencache.cpp new file mode 100644 index 00000000..3f0e6f02 --- /dev/null +++ b/securityd/src/tokencache.cpp @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2004-2006,2008 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@ + */ + + +// +// tokencache - persistent (on-disk) hardware token directory +// +// Here's the basic disk layout, rooted at /var/db/TokenCache (or $TOKENCACHE): +// TBA +// +#include "tokencache.h" +#include +#include +#include + +using namespace UnixPlusPlus; + + +// +// Here are the uid/gid values we assign to token daemons and their cache files +// +#define TOKEND_UID "tokend" +#define TOKEND_GID "tokend" +#define TOKEND_UID_FALLBACK uid_t(-2) +#define TOKEND_GID_FALLBACK gid_t(-2) + + +// +// Fixed relative file paths +// + +// relative to cache root (use cache->path()) +static const char configDir[] = "config"; +static const char lastSSIDFile[] = "config/lastSSID"; +static const char tokensDir[] = "tokens"; + +// relative to token directory (use token->path()) +static const char ssidFile[] = "SSID"; +static const char workDir[] = "work"; +static const char cacheDir[] = "cache"; + + +// +// Internal file I/O helpers. These read/write entire files. +// Note that the defaulted read functions do NOT write the default +// to disk; they work fine in read-only disk areas. +// +static unsigned long getFile(const string &path, unsigned long defaultValue) +{ + try { + AutoFileDesc fd(path, O_RDONLY, FileDesc::modeMissingOk); + if (fd) { + string s; fd.readAll(s); + unsigned long value; sscanf(s.c_str(), "%lu", &value); + return value; + } + } catch (...) { + } + return defaultValue; +} + +static string getFile(const string &path, const string &defaultValue) +{ + try { + AutoFileDesc fd(path, O_RDONLY, FileDesc::modeMissingOk); + if (fd) { + string s; fd.readAll(s); + return s; + } + } catch (...) { + } + return defaultValue; +} + + +static void putFile(const string &path, uint32 value) +{ + char buffer[64]; + snprintf(buffer, sizeof(buffer), "%ld\n", value); + AutoFileDesc(path, O_WRONLY | O_CREAT | O_TRUNC).writeAll(buffer); +} + +static void putFile(const string &path, const string &value) +{ + AutoFileDesc(path, O_WRONLY | O_CREAT | O_TRUNC).writeAll(value); +} + + +// +// The "rooted tree" utility class +// +void Rooted::root(const string &r) +{ + assert(mRoot.empty()); // can't re-set this + mRoot = r; +} + +string Rooted::path(const char *sub) const +{ + if (sub == NULL) + return mRoot; + return mRoot + "/" + sub; +} + + +// +// Open a TokenCache. +// If the cache does not exist at the path given, initialize it. +// If that fails, throw an exception. +// +TokenCache::TokenCache(const char *where) + : Rooted(where), mLastSubservice(0) +{ + makedir(root(), O_CREAT, 0711, securityd); + makedir(path(configDir), O_CREAT, 0700, securityd); + makedir(path(tokensDir), O_CREAT, 0711, securityd); + + mLastSubservice = getFile(path(lastSSIDFile), 1); + + // identify uid/gid for token daemons + struct passwd *pw = getpwnam(TOKEND_UID); + mTokendUid = pw ? pw->pw_uid : TOKEND_UID_FALLBACK; + struct group *gr = getgrnam(TOKEND_GID); + mTokendGid = gr ? gr->gr_gid : TOKEND_GID_FALLBACK; + + secdebug("tokencache", "token cache rooted at %s (last ssid=%ld, uid/gid=%d/%d)", + root().c_str(), mLastSubservice, mTokendUid, mTokendGid); +} + +TokenCache::~TokenCache() +{ +} + + +// +// Get a new, unused subservice id number. +// Update the tracking file so we won't hand it out again (ever) within this cache. +// +uint32 TokenCache::allocateSubservice() +{ + putFile(path(lastSSIDFile), ++mLastSubservice); + return mLastSubservice; +} + + +// +// A slightly souped-up UnixPlusPlus::makedir +// +void TokenCache::makedir(const char *path, int flags, mode_t mode, Owner owner) +{ + UnixPlusPlus::makedir(path, flags, mode); + switch(owner) { + case securityd: + // leave it alone; we own it alrady + break; + case tokend: + ::chown(path, tokendUid(), tokendGid()); + break; + } +} + + +// +// Make a cache entry from a valid tokenUid. +// This will locate an existing entry or make a new one. +// +TokenCache::Token::Token(TokenCache &c, const string &tokenUid) + : Rooted(c.path(string(tokensDir) + "/" + tokenUid)), cache(c) +{ + cache.makedir(root(), O_CREAT, 0711, securityd); + if (mSubservice = getFile(path(ssidFile), 0)) { + secdebug("tokencache", "found token \"%s\" ssid=%ld", tokenUid.c_str(), mSubservice); + init(existing); + } else { + mSubservice = cache.allocateSubservice(); // allocate new, unique ssid... + putFile(path(ssidFile), mSubservice); // ... and save it in cache + secdebug("tokencache", "new token \"%s\" ssid=%ld", tokenUid.c_str(), mSubservice); + init(created); + } +} + + +// +// Make a cache entry that is temporary and will never be reused. +// +TokenCache::Token::Token(TokenCache &c) + : cache(c) +{ + mSubservice = cache.allocateSubservice(); // new, unique id + char rootForm[30]; snprintf(rootForm, sizeof(rootForm), + "%s/temporary:%ld", tokensDir, mSubservice); + root(cache.path(rootForm)); + cache.makedir(root(), O_CREAT | O_EXCL, 0711, securityd); + putFile(path(ssidFile), mSubservice); // ... and save it in cache + secdebug("tokencache", "temporary token \"%s\" ssid=%ld", rootForm, mSubservice); + init(temporary); +} + + +// +// Common constructor setup code +// +void TokenCache::Token::init(Type type) +{ + mType = type; + cache.makedir(workPath(), O_CREAT, 0700, tokend); + cache.makedir(cachePath(), O_CREAT, 0700, tokend); +} + + +// +// The Token destructor might clean or preen a bit, but shouldn't take +// too long (or too much effort). +// +TokenCache::Token::~Token() +{ + if (type() == temporary) + secdebug("tokencache", "@@@ should delete the cache directory here..."); +} + + +// +// Attributes of TokenCache::Tokens +// +string TokenCache::Token::workPath() const +{ + return path("Work"); +} + +string TokenCache::Token::cachePath() const +{ + return path("Cache"); +} + + +string TokenCache::Token::printName() const +{ + return getFile(path("PrintName"), ""); +} + +void TokenCache::Token::printName(const string &name) +{ + putFile(path("PrintName"), name); +} diff --git a/securityd/src/tokencache.h b/securityd/src/tokencache.h new file mode 100644 index 00000000..a6336d41 --- /dev/null +++ b/securityd/src/tokencache.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2004 Apple Computer, 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@ + */ + + +// +// tokencache - persistent (on-disk) hardware token directory +// +#ifndef _H_TOKENCACHE +#define _H_TOKENCACHE + +#include +#include + + +// +// A little helper +// +class Rooted { +public: + Rooted() { } + Rooted(const char *root) : mRoot(root) { } + Rooted(const string &root) : mRoot(root) { } + + string root() const { return mRoot; } + string path(const char *sub) const; + string path(const string &sub) const { return path(sub.c_str()); } + +protected: + void root(const string &s); + +private: + string mRoot; // root of this tree +}; + + +// +// An on-disk cache area. +// You'll only want a single one, though nothing keeps you from +// making multiples if you like. +// +class TokenCache : public Rooted { +public: + TokenCache(const char *root); + ~TokenCache(); + + uid_t tokendUid() const { return mTokendUid; } + gid_t tokendGid() const { return mTokendGid; } + +public: + class Token : public RefCount, public Rooted { + public: + friend class TokenCache; + Token(TokenCache &cache, const std::string &uid); + Token(TokenCache &cache); + ~Token(); + + enum Type { existing, created, temporary }; + Type type() const { return mType; } + + TokenCache &cache; + uint32 subservice() const { return mSubservice; } + string workPath() const; + string cachePath() const; + + string printName() const; + void printName(const string &name); + + uid_t tokendUid() const { return cache.tokendUid(); } + gid_t tokendGid() const { return cache.tokendGid(); } + + protected: + void init(Type type); + + private: + uint32 mSubservice; // subservice id assigned + Type mType; // type of Token cache entry + }; + +public: + uint32 allocateSubservice(); + +private: + enum Owner { securityd, tokend }; + void makedir(const char *path, int flags, mode_t mode, Owner owner); + void makedir(const string &path, int flags, mode_t mode, Owner owner) + { return makedir(path.c_str(), flags, mode, owner); } + +private: + uint32 mLastSubservice; // last subservice id issued + + uid_t mTokendUid; // uid of daemons accessing this token cache + gid_t mTokendGid; // gid of daemons accessing this token cache +}; + + +#endif //_H_TOKENCACHE diff --git a/securityd/src/tokend.cpp b/securityd/src/tokend.cpp new file mode 100644 index 00000000..268e3227 --- /dev/null +++ b/securityd/src/tokend.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2004-2006 Apple Computer, 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@ + */ + + +// +// tokend - internal tracker for a tokend smartcard driver process +// +#include "tokend.h" +#include + + +// +// Construct a TokenDaemon. +// This will (try to) execute the actual tokend at 'path'; it will not communicate +// with it beyond the standard securityd checkin mechanism. +// The constructor will return if the tokend is either checked in and ready, or +// it has died (or been unable to start at all). It's then our owner's responsibility +// to manage us from there, including deleting us eventually. +// +TokenDaemon::TokenDaemon(RefPointer code, + const string &reader, const PCSC::ReaderState &readerState, TokenCache &cache) + : Tokend::ClientSession(Allocator::standard(), Allocator::standard()), + mMe(code), mReaderName(reader), mState(readerState), + mFaultRelay(NULL), mFaulted(false), mProbed(false), + mUid(cache.tokendUid()), mGid(cache.tokendGid()) +{ + this->fork(); + switch (ServerChild::state()) { + case alive: + Tokend::ClientSession::servicePort(ServerChild::servicePort()); + secdebug("tokend", "%p (pid %d) %s has launched", this, pid(), bundlePath().c_str()); + break; + case dead: + // tokend died or quit before becoming ready + secdebug("tokend", "%p (pid %d) %s failed on startup", this, pid(), bundlePath().c_str()); + break; + default: + assert(false); + } +} + + +// +// The destructor for TokenDaemon *may* be called with tokend still alive. +// We rely on ServerChild's destructor to kill it for us. +// If we wanted to do something especally nice just for tokend (such as sending +// a "go die" message), we'd do it here. +// +TokenDaemon::~TokenDaemon() +{ + secdebug("tokend", "%p (pid %d) %s is being destroyed", this, pid(), bundlePath().c_str()); +} + + +// +// Calculate a tokenUid as a concatenation of tokend identifier and uid +// +std::string TokenDaemon::tokenUid() const +{ + assert(hasTokenUid()); + return mTokenUid; +} + + +// +// Access to custom Info.plist fields +// +uint32 TokenDaemon::maxScore() const +{ + return cfNumber(CFNumberRef(mMe->infoPlistItem("TokendBestScore")), INT_MAX); +} + + +// +// Our childAction is to launch tokend after preparing its environment +// +void TokenDaemon::childAction() +{ + + // permanently relinquish high privilege +#if defined(NDEBUG) + UnixError::check(::setgid(mGid)); + UnixError::check(::setuid(mUid)); +#else //NDEBUG + // best effort, okay if not + ::setgid(mGid); + ::setuid(mUid); +#endif //NDEBUG + secdebug("tokend", "uid=%d gid=%d", getuid(), getgid()); + + // go run the tokend + char protocol[20]; snprintf(protocol, sizeof(protocol), "%d", TDPROTOVERSION); + secdebug("tokend", "executing %s(\"%s\",%s)", + mMe->executablePath().c_str(), mReaderName.c_str(), protocol); + execl(mMe->executablePath().c_str(), + mMe->executablePath().c_str(), + protocol, // #1: protocol version + mReaderName.c_str(), // #2: reader name + CssmData::wrap(mState).toHex().c_str(), // #3: PCSC reader state (hex) + NULL); +} + + +// +// This will be called (by the UnixChild layer) when UNIX tells us that our tokend +// has died. That means it's quite dead (a Zombie) already. +// +void TokenDaemon::dying() +{ + ServerChild::dying(); // honor prior engagement + fault(true, "token daemon has died"); // flag asynchronous fault +} + + +// +// Declare a fault. +//@@@ Semantics TBD. +// +void TokenDaemon::fault(bool async, const char *reason) +{ + if (!mFaulted) { + secdebug("tokend", "%p declaring %s FAULT condition: %s", + this, async ? "ASYNCHRONOUS" : "SYNCHRONOUS", reason); + Syslog::notice("card in reader %s has faulted (%s)", + mReaderName.c_str(), reason); + mFaulted = true; + if (mFaultRelay) + mFaultRelay->relayFault(async); + } + if (!async) + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_FAILED); +} + + +// +// A fault signalled from the ClientSession layer is just a (synchronous) fault +// of TokenDaemon itself. +// +void TokenDaemon::fault() +{ + this->fault(false, "tokend service failed"); +} + + +// +// Overridden Tokend::ClientSession methods (to siphon off some return data). +// Note that this does NOT include the Access magic; you still have to use +// TokenDaemon::Access to mediate the call. +// +bool TokenDaemon::probe() +{ + secdebug("tokend", "%p probing", this); + ClientSession::probe(mScore, mTokenUid); + secdebug("tokend", "%p probed score=%d tokenUid=\"%s\"", this, mScore, mTokenUid.c_str()); + mProbed = true; + return mScore > 0; +} + + +// +// FaultRelay +// +FaultRelay::~FaultRelay() +{ /* virtual */ } + + +// +// Debug dump support +// +#if defined(DEBUGDUMP) + +void TokenDaemon::dumpNode() +{ + PerGlobal::dumpNode(); + if (mFaulted) + Debug::dump(" FAULT"); + Debug::dump(" service=%d/%d", + ClientSession::servicePort().port(), ServerChild::servicePort().port()); +} + +#endif //DEBUGDUMP diff --git a/securityd/src/tokend.h b/securityd/src/tokend.h new file mode 100644 index 00000000..f4ecdf83 --- /dev/null +++ b/securityd/src/tokend.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2004-2006 Apple Computer, 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@ + */ + + +// +// tokend - internal tracker for a tokend smartcard driver process +// +#ifndef _H_TOKEND +#define _H_TOKEND + +#include "structure.h" +#include "child.h" +#include "tokencache.h" +#include +#include +#include + + +// +// A Mix-in for classes that can receive (progated) fault nofications +// +class FaultRelay { +public: + virtual ~FaultRelay(); + virtual void relayFault(bool async) = 0; +}; + + +// +// A TokenDaemon object is the ServerChild object representing the real +// tokend process driving a token. It provides the only (official) communications +// and control point between securityd and that tokend. +// +// TokenDaemon is sufficiently aware to track changes in its tokend, particularly +// any sudden, violent, agonizing death it may have suffered. +// If TokenDaemon communications with its tokend break down for any rason, it declares +// a FAULT condition and cuts off any further attempts at communication. There is no way +// to recover from a FAULT condition. (You can create a new TokenDaemon and try again, +// of course.) Fault is propagated to the owner object through a simple callback scheme. +// +// If TokenDaemon is destroyed while its process is still alive, it will (try to) kill +// it right there and then. That's good enough for hard error recovery, though you may +// try to let it down easier to allow it to save its caches and wind down. Caller's choice. +// +// NB: If you ever want to make TokenDaemon BE a Bundle, you must switch NodeCore +// AND OSXCode to virtually derive RefCount. +// +class TokenDaemon : public PerGlobal, public ServerChild, public Tokend::ClientSession { +public: + TokenDaemon(RefPointer code, + const std::string &reader, const PCSC::ReaderState &state, TokenCache &cache); + virtual ~TokenDaemon(); + + bool faulted() const { return mFaulted; } + void fault(bool async, const char *reason); + + void faultRelay(FaultRelay *rcv) { mFaultRelay = rcv; } + + string bundlePath() const { return mMe->canonicalPath(); } + string bundleIdentifier() const { return mMe->identifier(); } + uint32 maxScore() const; + + Score score() const { return mScore; } + bool hasTokenUid() const { return !mTokenUid.empty(); } + std::string tokenUid() const; + + uid_t uid() const { return mUid; } + gid_t gid() const { return mGid; } + + // startup phase calls + using ClientSession::probe; + bool probe(); + + IFDUMP(void dumpNode()); + +protected: + void childAction(); + void dying(); + + void fault(); // relay from Tokend::ClientSession + +private: + RefPointer mMe; // code object for the tokend (it's an Application) + std::string mReaderName; // PCSC name of reader we're working with + PCSC::ReaderState mState; // card state at time of creation (not updated after that) + + // fault processing + FaultRelay *mFaultRelay; // forward initial fault declarations to this object + bool mFaulted; // fault condition + + // returned by tokend scoring system + bool mProbed; // probe() has succeeded; mScore/mTokenUid valid + Score mScore; // token support score as returned by probe() + std::string mTokenUid; // tokenUid as returned by probe(), may be empty + + // credentials of underlying process + uid_t mUid; // uid of tokend process + gid_t mGid; // gid of tokend process +}; + + +#endif //_H_TOKEND diff --git a/securityd/src/tokendatabase.cpp b/securityd/src/tokendatabase.cpp new file mode 100644 index 00000000..cdeee2cb --- /dev/null +++ b/securityd/src/tokendatabase.cpp @@ -0,0 +1,837 @@ +/* + * Copyright (c) 2000-2008,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@ + */ + + +// +// tokendatabase - software database container implementation. +// +#include "tokendatabase.h" +#include "tokenkey.h" +#include "tokenaccess.h" +#include "process.h" +#include "server.h" +#include "localkey.h" // to retrieve local raw keys +#include + + +// +// Construct a TokenDbCommon +// +TokenDbCommon::TokenDbCommon(Session &ssn, Token &tk, const char *name) + : DbCommon(ssn), mDbName(name ? name : ""), mHasAclState(false), mResetLevel(0) +{ + secdebug("tokendb", "creating tokendbcommon %p: with token %p", this, &tk); + parent(tk); +} + +TokenDbCommon::~TokenDbCommon() +{ + secdebug("tokendb", "destroying tokendbcommon %p", this); + token().removeCommon(*this); // unregister from Token +} + +Token &TokenDbCommon::token() const +{ + return parent(); +} + +std::string TokenDbCommon::dbName() const +{ + return token().printName(); +} + + +// +// A TokenDbCommon holds per-session adornments for the ACL machine +// +Adornable &TokenDbCommon::store() +{ + StLock _(*this); + + // if this is the first one, hook for lifetime + if (!mHasAclState) { + session().addReference(*this); // hold and slave to SSN lifetime + token().addCommon(*this); // register with Token + mHasAclState = true; + } + + // return our (now active) adornments + return *this; +} + +void TokenDbCommon::resetAcls() +{ + StLock _(*this); + if (mHasAclState) { + clearAdornments(); // clear ACL state + session().removeReference(*this); // unhook from SSN + mHasAclState = false; + } + token().removeCommon(*this); // unregister from Token +} + + +// +// Send out a "keychain" notification for this database +// +void TokenDbCommon::notify(NotificationEvent event) +{ + DbCommon::notify(event, DLDbIdentifier(dbName().c_str(), gGuidAppleSdCSPDL, + subservice(), CSSM_SERVICE_DL | CSSM_SERVICE_CSP)); +} + + +// +// Process (our part of) a "lock all" request. +// Smartcard tokens interpret a "lock" as a forced card reset, transmitted +// to tokend as an authenticate request. +// @@@ Virtual reset for multi-session tokens. Right now, we're using the sledge hammer. +// +void TokenDbCommon::lockProcessing() +{ + Access access(token()); + access().authenticate(CSSM_DB_ACCESS_RESET, NULL); +} + +// +// Construct a TokenDatabase given subservice information. +// We are currently ignoring the 'name' argument. +// +TokenDatabase::TokenDatabase(uint32 ssid, Process &proc, + const char *name, const AccessCredentials *cred) + : Database(proc) +{ + // locate Token object + RefPointer token = Token::find(ssid); + + Session &session = process().session(); + StLock _(session); + if (TokenDbCommon *dbcom = session.findFirst(&TokenDbCommon::subservice, ssid)) { + parent(*dbcom); + secdebug("tokendb", "open tokendb %p(%d) at known common %p", + this, subservice(), dbcom); + } else { + // DbCommon not present; make a new one + parent(*new TokenDbCommon(proc.session(), *token, name)); + secdebug("tokendb", "open tokendb %p(%d) with new common %p", + this, subservice(), &common()); + } + mOpenCreds = copy(cred, Allocator::standard()); + proc.addReference(*this); +} + +TokenDatabase::~TokenDatabase() +{ + Allocator::standard().free(mOpenCreds); +} + + +// +// Basic Database virtual implementations +// +TokenDbCommon &TokenDatabase::common() const +{ + return parent(); +} + +TokenDaemon &TokenDatabase::tokend() +{ + return common().token().tokend(); +} + +const char *TokenDatabase::dbName() const +{ + //store dbName to ensure that will live outside function scope + mDbName = common().dbName(); + return mDbName.c_str(); +} + +bool TokenDatabase::transient() const +{ + //@@@ let tokend decide? Are there any secure transient keystores? + return false; +} + + +// +// Our ObjectAcl resides in the Token object. +// +SecurityServerAcl &TokenDatabase::acl() +{ + return token(); +} + + +// +// We post-process the status version of getAcl to account for virtual (per-session) +// PIN lock status. +// +void TokenDatabase::getAcl(const char *tag, uint32 &count, AclEntryInfo *&acls) +{ + AclSource::getAcl(tag, count, acls); + + for (unsigned n = 0; n < count; n++) { + AclEntryPrototype &proto = acls[n]; + if (unsigned pin = pinFromAclTag(proto.tag(), "?")) { // pin state response + secdebug("tokendb", "%p updating PIN%d state response", this, pin); + TypedList &subject = proto.subject(); + // subject == { CSSM_WORID_PIN, pin-number, status [, count ] } # all numbers + if (subject.length() > 2 + && subject[0].is(CSSM_LIST_ELEMENT_WORDID) + && subject[0] == CSSM_WORDID_PIN + && subject[1].is(CSSM_LIST_ELEMENT_WORDID) + && subject[2].is(CSSM_LIST_ELEMENT_WORDID)) { + uint32 pin = subject[1]; + if (!common().attachment((void *)pin).accepted) { + // we are not pre-authorized in this session + secdebug("tokendb", "%p session state forces PIN%d reporting unauthorized", this, pin); + uint32 status = subject[2]; + status &= ~CSSM_ACL_PREAUTH_TRACKING_AUTHORIZED; // clear authorized bit + subject[2] = status; +#if !defined(NDEBUG) + if (subject.length() > 3 && subject[3].is(CSSM_LIST_ELEMENT_WORDID)) + secdebug("tokendb", "%p PIN%d count=%d", this, pin, subject[3].word()); +#endif //NDEBUG + } + } + } + } +} + + +bool TokenDatabase::isLocked() +{ + Access access(token()); + + bool lockState = pinState(1); +// bool lockState = access().isLocked(); + + secdebug("tokendb", "returning isLocked=%d", lockState); + return lockState; +} + +bool TokenDatabase::pinState(uint32 pin, int *pinCount /* = NULL */) +{ + uint32 count; + AclEntryInfo *acls; + this->getAcl("PIN1?", count, acls); + bool locked = true; // preset locked + if (pinCount) + *pinCount = -1; // preset unknown + switch (count) { + case 0: + secdebug("tokendb", "PIN%d query returned no entries", pin); + break; + default: + secdebug("tokendb", "PIN%d query returned multiple entries", pin); + break; + case 1: + { + TypedList &subject = acls[0].proto().subject(); + if (subject.length() > 2 + && subject[0].is(CSSM_LIST_ELEMENT_WORDID) + && subject[0] == CSSM_WORDID_PIN + && subject[1].is(CSSM_LIST_ELEMENT_WORDID) + && subject[2].is(CSSM_LIST_ELEMENT_WORDID)) { + uint32 status = subject[2]; + locked = !(status & CSSM_ACL_PREAUTH_TRACKING_AUTHORIZED); + if (pinCount && locked && subject.length() > 3 && subject[3].is(CSSM_LIST_ELEMENT_WORDID)) + *pinCount = subject[3]; + } + } + break; + } + + // release memory allocated by getAcl + ChunkFreeWalker free; + for (uint32 n = 0; n < count; n++) + walk(free, acls[n]); + Allocator::standard().free(acls); + + // return status + return locked; +} + + +// +// TokenDatabases implement the dbName-setting function. +// This sets the print name of the token, which is persistently +// stored in the token cache. So this is a de-facto rename of +// the token, at least on this system. +// +void TokenDatabase::dbName(const char *name) +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + + +// +// Given a key handle and CssmKey returned from tokend, create a Key representing +// it. This takes care of raw returns by turning them into keys of the process's +// local transient store. +// +RefPointer TokenDatabase::makeKey(KeyHandle hKey, const CssmKey *key, + uint32 moreAttributes, const AclEntryPrototype *owner) +{ + switch (key->blobType()) { + case CSSM_KEYBLOB_REFERENCE: + return new TokenKey(*this, hKey, key->header()); + case CSSM_KEYBLOB_RAW: + return process().makeTemporaryKey(*key, moreAttributes, owner); + default: + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); // bad key return from tokend + } + //@@@ Server::releaseWhenDone(key); +} + + +// +// Adjust key attributes for newly created keys +// +static CSSM_KEYATTR_FLAGS modattrs(CSSM_KEYATTR_FLAGS attrs) +{ + static const CSSM_KEYATTR_FLAGS CSSM_KEYATTR_RETURN_FLAGS = 0xff000000; + switch (attrs & CSSM_KEYATTR_RETURN_FLAGS) { + case CSSM_KEYATTR_RETURN_REF: + case CSSM_KEYATTR_RETURN_DATA: + break; // as requested + case CSSM_KEYATTR_RETURN_NONE: + CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK); + case CSSM_KEYATTR_RETURN_DEFAULT: + if (attrs & CSSM_KEYATTR_PERMANENT) + attrs |= CSSM_KEYATTR_RETURN_REF; + else + attrs |= CSSM_KEYATTR_RETURN_DATA; + break; + } + return attrs; +} + + +// +// TokenDatabases support remote secret validation by sending a secret +// (aka passphrase et al) to tokend for processing. +// +bool TokenDatabase::validateSecret(const AclSubject *subject, const AccessCredentials *cred) +{ + secdebug("tokendb", "%p attempting remote validation", this); + try { + Access access(token()); + // @@@ Use cached mode + access().authenticate(CSSM_DB_ACCESS_READ, cred); + secdebug("tokendb", "%p remote validation successful", this); + return true; + } + catch (...) { + secdebug("tokendb", "%p remote validation failed", this); + // return false; + throw; // try not to mask error + } +} + + +// +// Key inquiries +// +void TokenDatabase::queryKeySizeInBits(Key &key, CssmKeySize &result) +{ + Access access(token()); + TRY + GUARD + access().queryKeySizeInBits(myKey(key).tokenHandle(), result); + DONE +} + + +// +// Signatures and MACs +// +void TokenDatabase::generateSignature(const Context &context, Key &key, + CSSM_ALGORITHMS signOnlyAlgorithm, const CssmData &data, CssmData &signature) +{ + Access access(token(), key); + TRY + key.validate(CSSM_ACL_AUTHORIZATION_SIGN, context); + GUARD + access().generateSignature(context, myKey(key).tokenHandle(), data, signature, signOnlyAlgorithm); + DONE +} + + +void TokenDatabase::verifySignature(const Context &context, Key &key, + CSSM_ALGORITHMS verifyOnlyAlgorithm, const CssmData &data, const CssmData &signature) +{ + Access access(token(), key); + TRY + GUARD + access().verifySignature(context, myKey(key).tokenHandle(), data, signature, verifyOnlyAlgorithm); + DONE +} + +void TokenDatabase::generateMac(const Context &context, Key &key, + const CssmData &data, CssmData &mac) +{ + Access access(token()); + TRY + key.validate(CSSM_ACL_AUTHORIZATION_MAC, context); + GUARD + access().generateMac(context, myKey(key).tokenHandle(), data, mac); + DONE +} + +void TokenDatabase::verifyMac(const Context &context, Key &key, + const CssmData &data, const CssmData &mac) +{ + Access access(token()); + TRY + key.validate(CSSM_ACL_AUTHORIZATION_MAC, context); + GUARD + access().verifyMac(context, myKey(key).tokenHandle(), data, mac); + DONE +} + + +// +// Encryption/decryption +// +void TokenDatabase::encrypt(const Context &context, Key &key, + const CssmData &clear, CssmData &cipher) +{ + Access access(token()); + TRY + key.validate(CSSM_ACL_AUTHORIZATION_ENCRYPT, context); + GUARD + access().encrypt(context, myKey(key).tokenHandle(), clear, cipher); + DONE +} + + +void TokenDatabase::decrypt(const Context &context, Key &key, + const CssmData &cipher, CssmData &clear) +{ + Access access(token()); + TRY + key.validate(CSSM_ACL_AUTHORIZATION_DECRYPT, context); + GUARD + access().decrypt(context, myKey(key).tokenHandle(), cipher, clear); + DONE +} + + +// +// Key generation and derivation. +// Currently, we consider symmetric key generation to be fast, but +// asymmetric key generation to be (potentially) slow. +// +void TokenDatabase::generateKey(const Context &context, + const AccessCredentials *cred, const AclEntryPrototype *owner, + CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, RefPointer &newKey) +{ + Access access(token()); + TRY + GUARD + KeyHandle hKey; + CssmKey *result; + access().generateKey(context, cred, owner, usage, modattrs(attrs), hKey, result); + newKey = makeKey(hKey, result, 0, owner); + DONE +} + +void TokenDatabase::generateKey(const Context &context, + const AccessCredentials *cred, const AclEntryPrototype *owner, + CSSM_KEYUSE pubUsage, CSSM_KEYATTR_FLAGS pubAttrs, + CSSM_KEYUSE privUsage, CSSM_KEYATTR_FLAGS privAttrs, + RefPointer &publicKey, RefPointer &privateKey) +{ + Access access(token()); + TRY + GUARD + KeyHandle hPrivate, hPublic; + CssmKey *privKey, *pubKey; + access().generateKey(context, cred, owner, + pubUsage, modattrs(pubAttrs), privUsage, modattrs(privAttrs), + hPublic, pubKey, hPrivate, privKey); + publicKey = makeKey(hPublic, pubKey, 0, owner); + privateKey = makeKey(hPrivate, privKey, 0, owner); + DONE +} + + +// +// Key wrapping and unwrapping. +// Note that the key argument (the key in the context) is optional because of the special +// case of "cleartext" (null algorithm) wrapping for import/export. +// +void TokenDatabase::wrapKey(const Context &context, const AccessCredentials *cred, + Key *wrappingKey, Key &subjectKey, + const CssmData &descriptiveData, CssmKey &wrappedKey) +{ + Access access(token()); + InputKey cWrappingKey(wrappingKey); + InputKey cSubjectKey(subjectKey); + TRY + subjectKey.validate(context.algorithm() == CSSM_ALGID_NONE ? + CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR : CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED, + cred); + if (wrappingKey) + wrappingKey->validate(CSSM_ACL_AUTHORIZATION_ENCRYPT, context); + GUARD + CssmKey *rWrappedKey; + access().wrapKey(context, cred, + cWrappingKey, cWrappingKey, cSubjectKey, cSubjectKey, + descriptiveData, rWrappedKey); + wrappedKey = *rWrappedKey; + //@@@ ownership of wrappedKey.keyData() ?? + DONE +} + +void TokenDatabase::unwrapKey(const Context &context, + const AccessCredentials *cred, const AclEntryPrototype *owner, + Key *wrappingKey, Key *publicKey, CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, + const CssmKey wrappedKey, RefPointer &unwrappedKey, CssmData &descriptiveData) +{ + Access access(token()); + InputKey cWrappingKey(wrappingKey); + InputKey cPublicKey(publicKey); + TRY + if (wrappingKey) + wrappingKey->validate(CSSM_ACL_AUTHORIZATION_DECRYPT, context); + // we are not checking access on the public key, if any + GUARD + KeyHandle hKey; + CssmKey *result; + access().unwrapKey(context, cred, owner, + cWrappingKey, cWrappingKey, cPublicKey, cPublicKey, + wrappedKey, usage, modattrs(attrs), descriptiveData, hKey, result); + unwrappedKey = makeKey(hKey, result, modattrs(attrs) & LocalKey::managedAttributes, owner); + DONE +} + + +// +// Key derivation +// +void TokenDatabase::deriveKey(const Context &context, Key *sourceKey, + const AccessCredentials *cred, const AclEntryPrototype *owner, + CssmData *param, CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, RefPointer &derivedKey) +{ + Access access(token()); + InputKey cSourceKey(sourceKey); + TRY + if (sourceKey) + sourceKey->validate(CSSM_ACL_AUTHORIZATION_DERIVE, cred); + GUARD + KeyHandle hKey; + CssmKey *result; + CssmData params = param ? *param : CssmData(); + access().deriveKey(noDb, context, + cSourceKey, cSourceKey, + usage, modattrs(attrs), params, cred, owner, + hKey, result); + if (param) { + *param = params; + //@@@ leak? what's the rule here? + } + derivedKey = makeKey(hKey, result, 0, owner); + DONE +} + + +// +// Miscellaneous CSSM functions +// +void TokenDatabase::getOutputSize(const Context &context, Key &key, + uint32 inputSize, bool encrypt, uint32 &result) +{ + Access access(token()); + TRY + GUARD + access().getOutputSize(context, myKey(key).tokenHandle(), inputSize, encrypt, result); + DONE +} + + +// +// (Re-)Authenticate the database. +// We use dbAuthenticate as the catch-all "do something about authentication" call. +// +void TokenDatabase::authenticate(CSSM_DB_ACCESS_TYPE mode, const AccessCredentials *cred) +{ + Access access(token()); + TRY + GUARD + if (mode != CSSM_DB_ACCESS_RESET && cred) { + secdebug("tokendb", "%p authenticate calling validate", this); + if (unsigned pin = pinFromAclTag(cred->EntryTag)) { + validate(CSSM_ACL_AUTHORIZATION_PREAUTH(pin), cred); + notify(kNotificationEventUnlocked); + return; + } + } + + access().authenticate(mode, cred); + switch (mode) { + case CSSM_DB_ACCESS_RESET: + // this mode is known to trigger "lockdown" (i.e. reset) + common().resetAcls(); + notify(kNotificationEventLocked); + break; + default: + { + // no idea what that did to the token; + // But let's remember the new creds for our own sake. + AccessCredentials *newCred = copy(cred, Allocator::standard()); + Allocator::standard().free(mOpenCreds); + mOpenCreds = newCred; + } + break; + } + DONE +} + +// +// Data access interface. +// +// Note that the attribute vectors are passed between our two IPC interfaces +// as relocated but contiguous memory blocks (to avoid an extra copy). This means +// you can read them at will, but can't change them in transit unless you're +// willing to repack them right here. +// +void TokenDatabase::findFirst(const CssmQuery &query, + CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength, + CssmData *data, RefPointer &key, + RefPointer &rSearch, RefPointer &rRecord, + CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength) +{ + Access access(token()); + RefPointer search = new Search(*this); + RefPointer record = new Record(*this); + TRY + KeyHandle hKey = noKey; + validate(CSSM_ACL_AUTHORIZATION_DB_READ, openCreds()); + GUARD + record->tokenHandle() = access().Tokend::ClientSession::findFirst(query, + inAttributes, inAttributesLength, search->tokenHandle(), NULL, hKey, + outAttributes, outAttributesLength); + if (!record->tokenHandle()) { // no match (but no other error) + rRecord = NULL; // return null record + return; + } + if (data) { + if (!hKey) + record->validate(CSSM_ACL_AUTHORIZATION_DB_READ, openCreds()); + CssmDbRecordAttributeData *noAttributes; + mach_msg_type_number_t noAttributesLength; + access().Tokend::ClientSession::findRecordHandle(record->tokenHandle(), + NULL, 0, data, hKey, noAttributes, noAttributesLength); + if (hKey) { // tokend returned a key reference & data + CssmKey &keyForm = *data->interpretedAs(CSSMERR_CSP_INVALID_KEY); + key = new TokenKey(*this, hKey, keyForm.header()); + } + } + rSearch = search->commit(); + rRecord = record->commit(); + DONE +} + +void TokenDatabase::findNext(Database::Search *rSearch, + CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength, + CssmData *data, RefPointer &key, RefPointer &rRecord, + CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength) +{ + Access access(token()); + RefPointer record = new Record(*this); + Search *search = safe_cast(rSearch); + TRY + KeyHandle hKey = noKey; + validate(CSSM_ACL_AUTHORIZATION_DB_READ, openCreds()); + GUARD + record->tokenHandle() = access().Tokend::ClientSession::findNext( + search->tokenHandle(), inAttributes, inAttributesLength, + NULL, hKey, outAttributes, outAttributesLength); + if (!record->tokenHandle()) { // no more matches + releaseSearch(*search); // release search handle (consumed by EOD) + rRecord = NULL; // return null record + return; + } + if (data) { + if (!hKey) + record->validate(CSSM_ACL_AUTHORIZATION_DB_READ, openCreds()); + CssmDbRecordAttributeData *noAttributes; + mach_msg_type_number_t noAttributesLength; + access().Tokend::ClientSession::findRecordHandle(record->tokenHandle(), + NULL, 0, data, hKey, noAttributes, noAttributesLength); + if (hKey) { // tokend returned a key reference & data + CssmKey &keyForm = *data->interpretedAs(CSSMERR_CSP_INVALID_KEY); + key = new TokenKey(*this, hKey, keyForm.header()); + } + } + rRecord = record->commit(); + DONE +} + +void TokenDatabase::findRecordHandle(Database::Record *rRecord, + CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength, + CssmData *data, RefPointer &key, + CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength) +{ + Access access(token()); + Record *record = safe_cast(rRecord); + access.add(*record); + TRY + KeyHandle hKey = noKey; + validate(CSSM_ACL_AUTHORIZATION_DB_READ, openCreds()); + if (data) + record->validate(CSSM_ACL_AUTHORIZATION_DB_READ, openCreds()); + GUARD + access().Tokend::ClientSession::findRecordHandle(record->tokenHandle(), + inAttributes, inAttributesLength, data, hKey, outAttributes, outAttributesLength); + rRecord = record; + if (hKey != noKey && data) { // tokend returned a key reference & data + CssmKey &keyForm = *data->interpretedAs(CSSMERR_CSP_INVALID_KEY); + key = new TokenKey(*this, hKey, keyForm.header()); + } + DONE +} + +void TokenDatabase::insertRecord(CSSM_DB_RECORDTYPE recordType, + const CssmDbRecordAttributeData *attributes, mach_msg_type_number_t attributesLength, + const CssmData &data, RefPointer &rRecord) +{ + Access access(token()); + RefPointer record = new Record(*this); + access.add(*record); + TRY + validate(CSSM_ACL_AUTHORIZATION_DB_INSERT, openCreds()); + GUARD + access().Tokend::ClientSession::insertRecord(recordType, + attributes, attributesLength, data, record->tokenHandle()); + rRecord = record; + DONE +} + +void TokenDatabase::modifyRecord(CSSM_DB_RECORDTYPE recordType, Record *rRecord, + const CssmDbRecordAttributeData *attributes, mach_msg_type_number_t attributesLength, + const CssmData *data, CSSM_DB_MODIFY_MODE modifyMode) +{ + Access access(token()); + Record *record = safe_cast(rRecord); + access.add(*record); + TRY + validate(CSSM_ACL_AUTHORIZATION_DB_MODIFY, openCreds()); + record->validate(CSSM_ACL_AUTHORIZATION_DB_MODIFY, openCreds()); + GUARD + access().Tokend::ClientSession::modifyRecord(recordType, + record->tokenHandle(), attributes, attributesLength, data, modifyMode); + DONE +} + +void TokenDatabase::deleteRecord(Database::Record *rRecord) +{ + Access access(token(), *this); + Record *record = safe_cast(rRecord); + access.add(*record); + TRY + validate(CSSM_ACL_AUTHORIZATION_DB_DELETE, openCreds()); + record->validate(CSSM_ACL_AUTHORIZATION_DB_DELETE, openCreds()); + GUARD + access().Tokend::ClientSession::deleteRecord(record->tokenHandle()); + DONE +} + + +// +// Record/Search object handling +// +TokenDatabase::Search::~Search() +{ + if (mHandle) + try { + database().token().tokend().Tokend::ClientSession::releaseSearch(mHandle); + } catch (...) { + secdebug("tokendb", "%p release search handle %u threw (ignored)", + this, mHandle); + } +} + +TokenDatabase::Record::~Record() +{ + if (mHandle) + try { + database().token().tokend().Tokend::ClientSession::releaseRecord(mHandle); + } catch (...) { + secdebug("tokendb", "%p release record handle %u threw (ignored)", + this, mHandle); + } +} + + +// +// TokenAcl personality of Record +// +AclKind TokenDatabase::Record::aclKind() const +{ + return objectAcl; +} + +Token &TokenDatabase::Record::token() +{ + return safer_cast(database()).token(); +} + +GenericHandle TokenDatabase::Record::tokenHandle() const +{ + return Handler::tokenHandle(); +} + + +// +// Local utility classes +// +void TokenDatabase::InputKey::setup(Key *key) +{ + if (TokenKey *myKey = dynamic_cast(key)) { + // one of ours + mKeyHandle = myKey->tokenHandle(); + mKeyPtr = NULL; + } else if (LocalKey *hisKey = dynamic_cast(key)) { + // a local key - turn into raw form + CssmClient::WrapKey wrap(Server::csp(), CSSM_ALGID_NONE); + wrap(hisKey->cssmKey(), mKey); + mKeyHandle = noKey; + mKeyPtr = &mKey; + } else { + // no key at all + mKeyHandle = noKey; + mKeyPtr = NULL; + } +} + + +TokenDatabase::InputKey::~InputKey() +{ + if (mKeyPtr) { + //@@@ Server::csp().freeKey(mKey) ?? + Server::csp()->allocator().free(mKey.keyData()); + } +} diff --git a/securityd/src/tokendatabase.h b/securityd/src/tokendatabase.h new file mode 100644 index 00000000..e48a9a3b --- /dev/null +++ b/securityd/src/tokendatabase.h @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2000-2008,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@ + */ + + +// +// tokendatabase - software database container implementation. +// +// A TokenDatabase represents access to an external (secure) storage container +// of some kind (usually a smartcard token). +// +#ifndef _H_TOKENDATABASE +#define _H_TOKENDATABASE + +#include "database.h" +#include "tokenacl.h" +#include "session.h" +#include "token.h" +#include + +class TokenDatabase; +class TokenDbCommon; +class TokenKey; +class TokenDaemon; + + +// +// The global per-system object for a TokenDatabase (the TokenDbGlobal so to +// speak) is the Token object itself (from token.h). +// + + +// +// TokenDatabase DbCommons +// +class TokenDbCommon : public DbCommon, public Adornable { +public: + TokenDbCommon(Session &ssn, Token &tk, const char *name); + ~TokenDbCommon(); + + Token &token() const; + + uint32 subservice() const { return token().subservice(); } + std::string dbName() const; + + Adornable &store(); + void resetAcls(); + + void notify(NotificationEvent event); + + void lockProcessing(); + + typedef Token::ResetGeneration ResetGeneration; + +private: + std::string mDbName; // name given during open + bool mHasAclState; // Adornment is carrying active ACL state + + ResetGeneration mResetLevel; // validity tag +}; + + +// +// A Database object represents a SC/CSPDL per-process access to a token. +// +class TokenDatabase : public Database { + friend class TokenDbCommon; +public: + TokenDatabase(uint32 ssid, Process &proc, const char *name, const AccessCredentials *cred); + ~TokenDatabase(); + + TokenDbCommon &common() const; + Token &token() const { return common().token(); } + TokenDaemon &tokend(); + uint32 subservice() const { return common().subservice(); } + const char *dbName() const; + void dbName(const char *name); + bool transient() const; + + SecurityServerAcl &acl(); // it's our Token + void getAcl(const char *tag, uint32 &count, AclEntryInfo *&acls); // post-processing + + bool isLocked(); + bool pinState(uint32 pin, int *count = NULL); + + void notify(NotificationEvent event) { return common().notify(event); } + + bool validateSecret(const AclSubject *subject, const AccessCredentials *cred); + + const AccessCredentials *openCreds() const { return mOpenCreds; } + +protected: + // any Process-referent concept handle we hand out to the client + class Handler { + public: + Handler() : mHandle(0) { } + GenericHandle &tokenHandle() { return mHandle; } + GenericHandle tokenHandle() const { return mHandle; } + + protected: + GenericHandle mHandle; + }; + + // CSSM-style search handles (returned by findFirst) + struct Search : public Database::Search, public Handler { + Search(TokenDatabase &db) : Database::Search(db) { } + TokenDatabase &database() const { return referent(); } + ~Search(); + + Search *commit() { database().addReference(*this); return this; } + }; + + // CSSM-style record handles (returned by findFirst/findNext et al) + struct Record : public Database::Record, public Handler, public TokenAcl { + Record(TokenDatabase &db) : Database::Record(db) { } + TokenDatabase &database() const { return referent(); } + ~Record(); + + Record *commit() { database().addReference(*this); return this; } + + void validate(AclAuthorization auth, const AccessCredentials *cred) + { TokenAcl::validate(auth, cred, &database()); } + + // TokenAcl personality + AclKind aclKind() const; + Token &token(); + using Handler::tokenHandle; + GenericHandle tokenHandle() const; + }; + +public: + // + // Cryptographic service calls + // + void queryKeySizeInBits(Key &key, CssmKeySize &result); + void getOutputSize(const Context &context, Key &key, uint32 inputSize, bool encrypt, uint32 &result); + + // service calls + void generateSignature(const Context &context, Key &key, CSSM_ALGORITHMS signOnlyAlgorithm, + const CssmData &data, CssmData &signature); + void verifySignature(const Context &context, Key &key, CSSM_ALGORITHMS verifyOnlyAlgorithm, + const CssmData &data, const CssmData &signature); + void generateMac(const Context &context, Key &key, + const CssmData &data, CssmData &mac); + void verifyMac(const Context &context, Key &key, + const CssmData &data, const CssmData &mac); + + void encrypt(const Context &context, Key &key, const CssmData &clear, CssmData &cipher); + void decrypt(const Context &context, Key &key, const CssmData &cipher, CssmData &clear); + + void generateKey(const Context &context, + const AccessCredentials *cred, const AclEntryPrototype *owner, + uint32 usage, uint32 attrs, RefPointer &newKey); + void generateKey(const Context &context, + const AccessCredentials *cred, const AclEntryPrototype *owner, + uint32 pubUsage, uint32 pubAttrs, uint32 privUsage, uint32 privAttrs, + RefPointer &publicKey, RefPointer &privateKey); + void deriveKey(const Context &context, Key *key, + const AccessCredentials *cred, const AclEntryPrototype *owner, + CssmData *param, uint32 usage, uint32 attrs, RefPointer &derivedKey); + + void wrapKey(const Context &context, const AccessCredentials *cred, + Key *hWrappingKey, Key &keyToBeWrapped, + const CssmData &descriptiveData, CssmKey &wrappedKey); + void unwrapKey(const Context &context, + const AccessCredentials *cred, const AclEntryPrototype *owner, + Key *wrappingKey, Key *publicKey, CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, + const CssmKey wrappedKey, RefPointer &unwrappedKey, CssmData &descriptiveData); + +public: + // + // Data-access calls + // + void findFirst(const CssmQuery &query, + CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength, + CssmData *data, RefPointer &key, + RefPointer &search, RefPointer &record, + CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength); + void findNext(Database::Search *search, + CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength, + CssmData *data, RefPointer &key, RefPointer &record, + CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength); + void findRecordHandle(Database::Record *record, + CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength, + CssmData *data, RefPointer &key, + CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength); + void insertRecord(CSSM_DB_RECORDTYPE recordtype, + const CssmDbRecordAttributeData *attributes, mach_msg_type_number_t inAttributesLength, + const CssmData &data, RefPointer &record); + void modifyRecord(CSSM_DB_RECORDTYPE recordtype, Record *record, + const CssmDbRecordAttributeData *attributes, mach_msg_type_number_t inAttributesLength, + const CssmData *data, CSSM_DB_MODIFY_MODE modifyMode); + void deleteRecord(Database::Record *record); + + // authenticate to database + void authenticate(CSSM_DB_ACCESS_TYPE mode, const AccessCredentials *cred); + +private: + // internal utilities + RefPointer makeKey(KeyHandle hKey, const CssmKey *key, + uint32 moreAttributes, const AclEntryPrototype *owner); + + class InputKey { + public: + InputKey(Key *key) { setup(key); } + InputKey(Key &key) { setup(&key); } + ~InputKey(); + + operator KeyHandle () const { return mKeyHandle; } + operator const CssmKey * () const { return mKeyPtr; } + + private: + KeyHandle mKeyHandle; + CssmKey mKey; + CssmKey *mKeyPtr; + + void setup(Key *key); + }; + +private: + AccessCredentials *mOpenCreds; // credentials passed during open + mutable std::string mDbName; // stored name for method dbName() which need to call c_str on object outside function scope +}; + + +#endif //_H_TOKENDATABASE diff --git a/securityd/src/tokenkey.cpp b/securityd/src/tokenkey.cpp new file mode 100644 index 00000000..b387d7d7 --- /dev/null +++ b/securityd/src/tokenkey.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2004,2008 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@ + */ + + +// +// tokenkey - remote reference key on an attached hardware token +// +#include "tokenkey.h" +#include "tokendatabase.h" + + +// +// Construct a TokenKey from a reference handle and key header +// +TokenKey::TokenKey(TokenDatabase &db, KeyHandle tokenKey, const CssmKey::Header &hdr) + : Key(db), mKey(tokenKey), mHeader(hdr) +{ + db.addReference(*this); +} + + +// +// Destruction of a TokenKey releases the reference from tokend +// +TokenKey::~TokenKey() +{ + try { + database().token().tokend().releaseKey(mKey); + } catch (...) { + secdebug("tokendb", "%p release key handle %u threw (ignored)", + this, mKey); + } +} + + +// +// Links through the object mesh +// +TokenDatabase &TokenKey::database() const +{ + return referent(); +} + +Token &TokenKey::token() +{ + return database().token(); +} + +GenericHandle TokenKey::tokenHandle() const +{ + return mKey; // tokend-side handle +} + + +// +// Canonical external attributes (taken directly from the key header) +// +CSSM_KEYATTR_FLAGS TokenKey::attributes() +{ + return mHeader.attributes(); +} + + +// +// Return-to-caller processing (trivial in this case) +// +void TokenKey::returnKey(Handle &h, CssmKey::Header &hdr) +{ + h = this->handle(); + hdr = mHeader; +} + + +// +// We're a key (duh) +// +AclKind TokenKey::aclKind() const +{ + return keyAcl; +} + + +// +// Right now, key ACLs are at the process level +// +SecurityServerAcl &TokenKey::acl() +{ + return *this; +} + + +// +// The related database is, naturally enough, the TokenDatabase we're in +// +Database *TokenKey::relatedDatabase() +{ + return &database(); +} + + +// +// Generate the canonical key digest. +// This is not currently supported through tokend. If we need it, +// we'll have to force unlock and fake it (in tokend, most likely). +// +const CssmData &TokenKey::canonicalDigest() +{ + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} diff --git a/securityd/src/tokenkey.h b/securityd/src/tokenkey.h new file mode 100644 index 00000000..fac45fbc --- /dev/null +++ b/securityd/src/tokenkey.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2004 Apple Computer, 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_TOKENKEY +#define _H_TOKENKEY + + +// +// tokenkey - remote reference key on an attached hardware token +// +#include "key.h" +#include "tokenacl.h" + +class TokenDatabase; + + +// +// The token-specific instance of a Key +// +class TokenKey : public Key, public TokenAcl { +public: + TokenKey(TokenDatabase &db, KeyHandle hKey, const CssmKey::Header &hdr); + ~TokenKey(); + + TokenDatabase &database() const; + Token &token(); + const CssmKey::Header &header() const { return mHeader; } + KeyHandle tokenHandle() const; + + CSSM_KEYATTR_FLAGS attributes(); + void returnKey(Handle &h, CssmKey::Header &hdr); + const CssmData &canonicalDigest(); + + SecurityServerAcl &acl(); + Database *relatedDatabase(); + +public: + // SecurityServerAcl personality + AclKind aclKind() const; + +private: + KeyHandle mKey; // tokend reference handle + CssmKey::Header mHeader; // key header as maintained by tokend +}; + +#endif //_H_TOKENKEY diff --git a/securityd/src/transition.cpp b/securityd/src/transition.cpp new file mode 100644 index 00000000..bc3fb611 --- /dev/null +++ b/securityd/src/transition.cpp @@ -0,0 +1,1597 @@ +/* + * Copyright (c) 2000-2009,2012-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@ + */ + + +// +// transition - securityd IPC-to-class-methods transition layer +// +// This file contains all server-side MIG implementations for the main +// securityd protocol ("ucsp"). It dispatches them into the vast object +// conspiracy that is securityd, anchored in the Server object. +// +#include +#include +#include "server.h" +#include "session.h" +#include "agentquery.h" +#include "database.h" +#include "kcdatabase.h" +#include "tokendatabase.h" +#include "kckey.h" +#include "child.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// +// Bracket Macros +// +#define UCSP_ARGS mach_port_t servicePort, mach_port_t replyPort, \ + audit_token_t auditToken, CSSM_RETURN *rcode + +#define BEGIN_IPCN *rcode = CSSM_OK; try { +#define BEGIN_IPC(name) BEGIN_IPCN RefPointer connRef(&Server::connection(replyPort, auditToken)); \ + Connection &connection __attribute__((unused)) = *connRef; \ + if (SECURITYD_REQUEST_ENTRY_ENABLED()) { \ + const char * volatile s = #name; volatile char __attribute__((unused)) pagein = s[0]; \ + SECURITYD_REQUEST_ENTRY((char *)s, &connection, &connection.process()); \ + } +#define END_IPC(base) END_IPCN(base) Server::requestComplete(*rcode); return KERN_SUCCESS; +#define END_IPCN(base) SECURITYD_REQUEST_RETURN(*rcode); \ + } \ + catch (const CommonError &err) { *rcode = CssmError::cssmError(err, CSSM_ ## base ## _BASE_ERROR); } \ + catch (const std::bad_alloc &) { *rcode = CssmError::merge(CSSM_ERRCODE_MEMORY_ERROR, CSSM_ ## base ## _BASE_ERROR); } \ + catch (Connection *conn) { *rcode = 0; } \ + catch (...) { *rcode = CssmError::merge(CSSM_ERRCODE_INTERNAL_ERROR, CSSM_ ## base ## _BASE_ERROR); } + +#define BEGIN_IPCS try { +#define END_IPCS(more) } catch (...) { } \ + mach_port_deallocate(mach_task_self(), servicePort); more; return KERN_SUCCESS; + +#define DATA_IN(base) void *base, mach_msg_type_number_t base##Length +#define DATA_OUT(base) void **base, mach_msg_type_number_t *base##Length +#define DATA(base) CssmData(base, base##Length) + +#define SSBLOB(Type, name) makeBlob(DATA(name)) + +using LowLevelMemoryUtilities::increment; +using LowLevelMemoryUtilities::difference; + +class CopyOutAccessCredentials : public CopyOut { +public: + CopyOutAccessCredentials(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_ACCESS_CREDENTIALS), reinterpret_cast(xdr_CSSM_ACCESS_CREDENTIALS_PTR)) { } + operator AccessCredentials *() { return static_cast(reinterpret_cast(data())); } +}; + + +class CopyOutEntryAcl : public CopyOut { +public: + CopyOutEntryAcl(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_ACL_ENTRY_PROTOTYPE), reinterpret_cast(xdr_CSSM_ACL_ENTRY_PROTOTYPE_PTR)) { } + operator AclEntryPrototype *() { return static_cast(reinterpret_cast(data())); } +}; + +class CopyOutOwnerAcl : public CopyOut { +public: + CopyOutOwnerAcl(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_ACL_OWNER_PROTOTYPE), reinterpret_cast(xdr_CSSM_ACL_OWNER_PROTOTYPE_PTR)) { } + operator AclOwnerPrototype *() { return static_cast(reinterpret_cast(data())); } +}; + +class CopyOutAclEntryInput : public CopyOut { +public: + CopyOutAclEntryInput(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_ACL_ENTRY_INPUT), reinterpret_cast(xdr_CSSM_ACL_ENTRY_INPUT_PTR)) { } + operator AclEntryInput *() { return static_cast(reinterpret_cast(data())); } +}; + + +class CopyOutDeriveData : public CopyOut { +public: + CopyOutDeriveData(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_DERIVE_DATA), reinterpret_cast(xdr_CSSM_DERIVE_DATA_PTR)) { } + CSSM_DERIVE_DATA * derive_data() { return reinterpret_cast(data()); } + CSSM_DATA &cssm_data() { return derive_data()->baseData; } + CSSM_ALGORITHMS algorithm() { return derive_data()->algorithm; } +}; + + +class CopyOutContext : public CopyOut { +public: + CopyOutContext(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_CONTEXT), reinterpret_cast(xdr_CSSM_CONTEXT_PTR)) { } + operator Context *() { return static_cast(reinterpret_cast(data())); } + Context &context() { return *static_cast(reinterpret_cast(data())); } +}; + +class CopyOutKey : public CopyOut { +public: + CopyOutKey(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_KEY), reinterpret_cast(xdr_CSSM_KEY_PTR)) { } + operator CssmKey *() { return static_cast(reinterpret_cast(data())); } + CssmKey &key() { return *static_cast(reinterpret_cast(data())); } +}; + +class CopyOutDbRecordAttributes : public CopyOut { +public: + CopyOutDbRecordAttributes(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_DB_RECORD_ATTRIBUTE_DATA), reinterpret_cast(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR)) { } + CssmDbRecordAttributeData *attribute_data() { return static_cast(reinterpret_cast(data())); } +}; + +class CopyOutQuery : public CopyOut { +public: + CopyOutQuery(void *copy, size_t size) : CopyOut(copy, size, reinterpret_cast(xdr_CSSM_QUERY_PTR)) { } + operator CssmQuery *() { return static_cast(reinterpret_cast(data())); } +}; + +// +// Take a DATA type RPC argument purportedly representing a Blob of some kind, +// turn it into a Blob, and fail properly if it's not kosher. +// +template +const BlobType *makeBlob(const CssmData &blobData, CSSM_RETURN error = CSSM_ERRCODE_INVALID_DATA) +{ + if (!blobData.data() || blobData.length() < sizeof(BlobType)) + CssmError::throwMe(error); + const BlobType *blob = static_cast(blobData.data()); + if (blob->totalLength != blobData.length()) + CssmError::throwMe(error); + return blob; +} + +// +// An OutputData object will take memory allocated within securityd, +// hand it to the MIG return-output parameters, and schedule it to be released +// after the MIG reply has been sent. It will also get rid of it in case of +// error. +// +class OutputData : public CssmData { +public: + OutputData(void **outP, mach_msg_type_number_t *outLength) + : mData(*outP), mLength(*outLength) { } + ~OutputData() + { mData = data(); mLength = length(); Server::releaseWhenDone(mData); } + + void operator = (const CssmData &source) + { CssmData::operator = (source); } + +private: + void * &mData; + mach_msg_type_number_t &mLength; +}; + +// +// Choose a Database from a choice of two sources, giving preference +// to persistent stores and to earlier sources. +// +Database *pickDb(Database *db1, Database *db2); + +static inline Database *dbOf(Key *key) { return key ? &key->database() : NULL; } + +inline Database *pickDb(Key *k1, Key *k2) { return pickDb(dbOf(k1), dbOf(k2)); } +inline Database *pickDb(Database *db1, Key *k2) { return pickDb(db1, dbOf(k2)); } +inline Database *pickDb(Key *k1, Database *db2) { return pickDb(dbOf(k1), db2); } + +// +// Choose a Database from a choice of two sources, giving preference +// to persistent stores and to earlier sources. +// +Database *pickDb(Database *db1, Database *db2) +{ + // persistent db1 always wins + if (db1 && !db1->transient()) + return db1; + + // persistent db2 is next choice + if (db2 && !db2->transient()) + return db2; + + // pick any existing transient database + if (db1) + return db1; + if (db2) + return db2; + + // none at all. use the canonical transient store + return Server::optionalDatabase(noDb); +} + +// +// Setup/Teardown functions. +// +kern_return_t ucsp_server_setup(UCSP_ARGS, mach_port_t taskPort, ClientSetupInfo info, const char *identity) +{ + BEGIN_IPCN + SECURITYD_REQUEST_ENTRY((char*)"setup", NULL, NULL); + Server::active().setupConnection(Server::connectNewProcess, replyPort, + taskPort, auditToken, &info); + END_IPCN(CSSM) + if (*rcode) + Syslog::notice("setup(%s) failed rcode=%d", identity ? identity : "", *rcode); + return KERN_SUCCESS; +} + + +kern_return_t ucsp_server_setupThread(UCSP_ARGS, mach_port_t taskPort) +{ + SECURITYD_REQUEST_ENTRY((char*)"setupThread", NULL, NULL); + BEGIN_IPCN + Server::active().setupConnection(Server::connectNewThread, replyPort, taskPort, auditToken); + END_IPCN(CSSM) + if (*rcode) + Syslog::notice("setupThread failed rcode=%d", *rcode); + return KERN_SUCCESS; +} + + +kern_return_t ucsp_server_teardown(UCSP_ARGS) +{ + BEGIN_IPCN + SECURITYD_REQUEST_ENTRY((char*)"teardown", NULL, NULL); + Server::active().endConnection(replyPort); + END_IPCN(CSSM) + return KERN_SUCCESS; +} + +kern_return_t ucsp_server_verifyPrivileged(UCSP_ARGS) +{ + BEGIN_IPCN + SECURITYD_REQUEST_ENTRY((char*)"verifyPrivileged", NULL, NULL); + // doing nothing (we just want securityd's audit credentials returned) + END_IPCN(CSSM) + return KERN_SUCCESS; +} + +kern_return_t ucsp_server_verifyPrivileged2(UCSP_ARGS, mach_port_t *originPort) +{ + BEGIN_IPCN + SECURITYD_REQUEST_ENTRY((char*)"verifyPrivileged2", NULL, NULL); + // send the port back to the sender to check for a MitM (6986198) + *originPort = servicePort; + END_IPCN(CSSM) + return KERN_SUCCESS; +} + +// +// Common database operations +// +kern_return_t ucsp_server_authenticateDb(UCSP_ARGS, DbHandle db, + CSSM_DB_ACCESS_TYPE accessType, DATA_IN(cred)) +{ + BEGIN_IPC(authenticateDb) + secdebug("dl", "authenticateDb"); + CopyOutAccessCredentials creds(cred, credLength); + // ignoring accessType + Server::database(db)->authenticate(accessType, creds); + END_IPC(DL) +} + +kern_return_t ucsp_server_releaseDb(UCSP_ARGS, DbHandle db) +{ + BEGIN_IPC(releaseDb) + connection.process().kill(*Server::database(db)); + END_IPC(DL) +} + + +kern_return_t ucsp_server_getDbName(UCSP_ARGS, DbHandle db, char name[PATH_MAX]) +{ + BEGIN_IPC(getDbName) + string result = Server::database(db)->dbName(); + assert(result.length() < PATH_MAX); + memcpy(name, result.c_str(), result.length() + 1); + END_IPC(DL) +} + +kern_return_t ucsp_server_setDbName(UCSP_ARGS, DbHandle db, const char *name) +{ + BEGIN_IPC(setDbName) + Server::database(db)->dbName(name); + END_IPC(DL) +} + + +// +// External database interface +// +kern_return_t ucsp_server_openToken(UCSP_ARGS, uint32 ssid, FilePath name, + DATA_IN(accessCredentials), DbHandle *db) +{ + BEGIN_IPC(openToken) + CopyOutAccessCredentials creds(accessCredentials, accessCredentialsLength); + *db = (new TokenDatabase(ssid, connection.process(), name, creds))->handle(); + END_IPC(DL) +} + +kern_return_t ucsp_server_findFirst(UCSP_ARGS, DbHandle db, + DATA_IN(inQuery), DATA_IN(inAttributes), DATA_OUT(outAttributes), + boolean_t getData, DATA_OUT(data), + KeyHandle *hKey, SearchHandle *hSearch, IPCRecordHandle *hRecord) +{ + BEGIN_IPC(findFirst) + CopyOutQuery query(inQuery, inQueryLength); + CopyOutDbRecordAttributes attrs(inAttributes, inAttributesLength); + + RefPointer search; + RefPointer record; + RefPointer key; + CssmData outData; + CssmDbRecordAttributeData *outAttrs = NULL; mach_msg_type_number_t outAttrsLength; + Server::database(db)->findFirst(*query, + attrs.attribute_data(), attrs.length(), + getData ? &outData : NULL, key, search, record, outAttrs, outAttrsLength); + + // handle nothing-found case without exceptions + if (!record) { + *hRecord = noRecord; + *hSearch = noSearch; + *hKey = noKey; + } else { + // return handles + *hRecord = record->handle(); + *hSearch = search->handle(); + *hKey = key ? key->handle() : noKey; + + if (outAttrsLength && outAttrs) { + Server::releaseWhenDone(outAttrs); // exception proof it against next line + if (!copyin(outAttrs, reinterpret_cast (xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA), outAttributes, outAttributesLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*outAttributes); + } + + // return data (temporary fix) + if (getData) { + Server::releaseWhenDone(outData.data()); + xdrproc_t encode_proc = reinterpret_cast(xdr_CSSM_NO_KEY_IN_DATA); + if (key) + encode_proc = reinterpret_cast(xdr_CSSM_KEY_IN_DATA); + if (!copyin(&outData, encode_proc, data, dataLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*data); + } + } + END_IPC(DL) +} + + +kern_return_t ucsp_server_findNext(UCSP_ARGS, SearchHandle hSearch, + DATA_IN(inAttributes), + DATA_OUT(outAttributes), + boolean_t getData, DATA_OUT(data), KeyHandle *hKey, + IPCRecordHandle *hRecord) +{ + BEGIN_IPC(findNext) + CopyOutDbRecordAttributes attrs(inAttributes, inAttributesLength); + RefPointer search = + Server::find(hSearch, CSSMERR_DL_INVALID_RESULTS_HANDLE); + RefPointer record; + RefPointer key; + CssmData outData; + CssmDbRecordAttributeData *outAttrs = NULL; mach_msg_type_number_t outAttrsLength; + search->database().findNext(search, attrs.attribute_data(), attrs.length(), + getData ? &outData : NULL, key, record, outAttrs, outAttrsLength); + + // handle nothing-found case without exceptions + if (!record) { + *hRecord = noRecord; + *hKey = noKey; + } else { + // return handles + *hRecord = record->handle(); + *hKey = key ? key->handle() : noKey; + + if (outAttrsLength && outAttrs) { + secdebug("attrmem", "Found attrs: %p of length: %d", outAttrs, outAttrsLength); + Server::releaseWhenDone(outAttrs); // exception proof it against next line + if (!copyin(outAttrs, reinterpret_cast (xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA), outAttributes, outAttributesLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + secdebug("attrmem", "Copied attrs: %p of length: %d", *outAttributes, *outAttributesLength); + Server::releaseWhenDone(*outAttributes); + } + + // return data (temporary fix) + if (getData) { + Server::releaseWhenDone(outData.data()); + xdrproc_t encode_proc = reinterpret_cast(xdr_CSSM_NO_KEY_IN_DATA); + if (key) + encode_proc = reinterpret_cast(xdr_CSSM_KEY_IN_DATA); + if (!copyin(&outData, encode_proc, data, dataLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*data); + } + } + END_IPC(DL) +} + +kern_return_t ucsp_server_findRecordHandle(UCSP_ARGS, IPCRecordHandle hRecord, + DATA_IN(inAttributes), DATA_OUT(outAttributes), + boolean_t getData, DATA_OUT(data), KeyHandle *hKey) +{ + BEGIN_IPC(findRecordHandle) + CopyOutDbRecordAttributes attrs(inAttributes, inAttributesLength); + RefPointer record = + Server::find(hRecord, CSSMERR_DL_INVALID_RECORD_UID); + RefPointer key; + CssmData outData; + CssmDbRecordAttributeData *outAttrs; mach_msg_type_number_t outAttrsLength; + record->database().findRecordHandle(record, attrs.attribute_data(), attrs.length(), + getData ? &outData : NULL, key, outAttrs, outAttrsLength); + + // return handles + *hKey = key ? key->handle() : noKey; + + if (outAttrsLength && outAttrs) { + Server::releaseWhenDone(outAttrs); // exception proof it against next line + if (!copyin(outAttrs, reinterpret_cast (xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA), outAttributes, outAttributesLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*outAttributes); + } + + // return data (temporary fix) + if (getData) { + /* + We can't release this with the usual allocator (which calls free(), since + it was VM allocated. Part of the fix for: + securityd leaks VM memory during certain smartcard operations + will be to call Server::releaseWhenDone below with a new vm allocator param + */ + Server::releaseWhenDone(outData.data()); + xdrproc_t encode_proc = reinterpret_cast(xdr_CSSM_NO_KEY_IN_DATA); + if (key) + encode_proc = reinterpret_cast(xdr_CSSM_KEY_IN_DATA); + if (!copyin(&outData, encode_proc, data, dataLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*data); + } + END_IPC(DL) +} + +kern_return_t ucsp_server_insertRecord(UCSP_ARGS, DbHandle db, CSSM_DB_RECORDTYPE recordType, + DATA_IN(inAttributes), DATA_IN(data), IPCRecordHandle *record) +{ + BEGIN_IPC(insertRecord) + RecordHandle recordHandle; + CopyOutDbRecordAttributes attrs(inAttributes, inAttributesLength); + Server::database(db)->insertRecord(recordType, attrs.attribute_data(), attrs.length(), + DATA(data), recordHandle); + *record = recordHandle; + END_IPC(DL) +} + +kern_return_t ucsp_server_modifyRecord(UCSP_ARGS, DbHandle db, IPCRecordHandle *hRecord, + CSSM_DB_RECORDTYPE recordType, DATA_IN(attributes), + boolean_t setData, DATA_IN(data), CSSM_DB_MODIFY_MODE modifyMode) +{ + BEGIN_IPC(modifyRecord) + CopyOutDbRecordAttributes attrs(attributes, attributesLength); + CssmData newData(DATA(data)); + RefPointer record = + Server::find(*hRecord, CSSMERR_DL_INVALID_RECORD_UID); + Server::database(db)->modifyRecord(recordType, record, attrs.attribute_data(), attrs.length(), + setData ? &newData : NULL, modifyMode); + // note that the record handle presented to the client never changes here + // (we could, but have no reason to - our record handles are just always up to date) + END_IPC(DL) +} + +kern_return_t ucsp_server_deleteRecord(UCSP_ARGS, DbHandle db, IPCRecordHandle hRecord) +{ + BEGIN_IPC(deleteRecord) + Server::database(db)->deleteRecord( + Server::find(hRecord, CSSMERR_DL_INVALID_RECORD_UID)); + END_IPC(DL) +} + +kern_return_t ucsp_server_releaseSearch(UCSP_ARGS, SearchHandle hSearch) +{ + BEGIN_IPC(releaseSearch) + RefPointer search = Server::find(hSearch, 0); + search->database().releaseSearch(*search); + END_IPC(DL) +} + +kern_return_t ucsp_server_releaseRecord(UCSP_ARGS, IPCRecordHandle hRecord) +{ + BEGIN_IPC(releaseRecord) + RefPointer record = Server::find(hRecord, 0); + record->database().releaseRecord(*record); + END_IPC(DL) +} + + +// +// Internal database management +// +kern_return_t ucsp_server_createDb(UCSP_ARGS, DbHandle *db, + DATA_IN(ident), DATA_IN(cred), DATA_IN(owner), + DBParameters params) +{ + BEGIN_IPC(createDb) + CopyOutAccessCredentials creds(cred, credLength); + CopyOutEntryAcl owneracl(owner, ownerLength); + CopyOut flatident(ident, identLength, reinterpret_cast(xdr_DLDbFlatIdentifierRef)); + *db = (new KeychainDatabase(*reinterpret_cast(flatident.data()), params, connection.process(), creds, owneracl))->handle(); + END_IPC(DL) +} + +kern_return_t ucsp_server_recodeDbForSync(UCSP_ARGS, DbHandle dbToClone, + DbHandle srcDb, DbHandle *newDb) +{ + BEGIN_IPC(recodeDbForSync) + RefPointer srcKC = Server::keychain(srcDb); + *newDb = (new KeychainDatabase(*srcKC, connection.process(), dbToClone))->handle(); + END_IPC(DL) +} + +kern_return_t ucsp_server_authenticateDbsForSync(UCSP_ARGS, DATA_IN(dbHandleArray), + DATA_IN(agentData), DbHandle* authenticatedDBHandle) +{ + BEGIN_IPC(authenticateDbsForSync) + QueryDBBlobSecret query; + query.inferHints(connection.process()); + query.addHint(AGENT_HINT_KCSYNC_DICT, agentData, agentDataLength); + CSSM_DATA dbData = DATA(dbHandleArray); + uint8 ipcDbHandleArrayCount = *(dbData.Data); + DbHandle *ipcDbHandleArray = (DbHandle *)Allocator::standard().malloc(ipcDbHandleArrayCount * sizeof(DbHandle)); + if ( ipcDbHandleArray == 0 ) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + DbHandle *currIPCDbHandleArrayPtr = ipcDbHandleArray; + DbHandle *dbHandleArrayPtr = (DbHandle *)(dbData.Data+1); + int index; + for (index=0; index < ipcDbHandleArrayCount; index++) + { + *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++; + } + Server::releaseWhenDone(ipcDbHandleArray); + if (query(ipcDbHandleArray, ipcDbHandleArrayCount, authenticatedDBHandle) != SecurityAgent::noReason) + CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); + END_IPC(DL) +} + +kern_return_t ucsp_server_commitDbForSync(UCSP_ARGS, DbHandle srcDb, + DbHandle cloneDb, DATA_OUT(blob)) +{ + BEGIN_IPC(commitDbForSync) + RefPointer srcKC = Server::keychain(srcDb); + RefPointer cloneKC = Server::keychain(cloneDb); + srcKC->commitSecretsForSync(*cloneKC); + + // re-encode blob for convenience + if (blob && blobLength) { + DbBlob *dbBlob = srcKC->blob(); + *blob = dbBlob; + *blobLength = dbBlob->length(); + } else { + secdebug("kcrecode", "No blob can be returned to client"); + } + END_IPC(DL) +} + +kern_return_t ucsp_server_decodeDb(UCSP_ARGS, DbHandle *db, + DATA_IN(ident), DATA_IN(cred), DATA_IN(blob)) +{ + BEGIN_IPC(decodeDb) + CopyOutAccessCredentials creds(cred, credLength); + CopyOut flatident(ident, identLength, reinterpret_cast(xdr_DLDbFlatIdentifierRef)); + DLDbFlatIdentifier* flatID = (DLDbFlatIdentifier*) flatident.data(); + DLDbIdentifier id = *flatID; // invokes a casting operator + + *db = (new KeychainDatabase(id, SSBLOB(DbBlob, blob), + connection.process(), creds))->handle(); + END_IPC(DL) +} + +kern_return_t ucsp_server_encodeDb(UCSP_ARGS, DbHandle db, DATA_OUT(blob)) +{ + BEGIN_IPC(encodeDb) + DbBlob *dbBlob = Server::keychain(db)->blob(); // memory owned by database + *blob = dbBlob; + *blobLength = dbBlob->length(); + END_IPC(DL) +} + +kern_return_t ucsp_server_setDbParameters(UCSP_ARGS, DbHandle db, DBParameters params) +{ + BEGIN_IPC(setDbParameters) + Server::keychain(db)->setParameters(params); + END_IPC(DL) +} + +kern_return_t ucsp_server_getDbParameters(UCSP_ARGS, DbHandle db, DBParameters *params) +{ + BEGIN_IPC(getDbParameters) + Server::keychain(db)->getParameters(*params); + END_IPC(DL) +} + +kern_return_t ucsp_server_changePassphrase(UCSP_ARGS, DbHandle db, + DATA_IN(cred)) +{ + BEGIN_IPC(changePassphrase) + CopyOutAccessCredentials creds(cred, credLength); + Server::keychain(db)->changePassphrase(creds); + END_IPC(DL) +} + +kern_return_t ucsp_server_lockAll (UCSP_ARGS, boolean_t) +{ + BEGIN_IPC(lockAll) + connection.session().processLockAll(); + END_IPC(DL) +} + +kern_return_t ucsp_server_unlockDb(UCSP_ARGS, DbHandle db) +{ + BEGIN_IPC(unlockDb) + Server::keychain(db)->unlockDb(); + END_IPC(DL) +} + +static void check_stash_entitlement(Process & proc) +{ + OSStatus status = noErr; + CFDictionaryRef code_info = NULL; + CFDictionaryRef entitlements = NULL; + CFTypeRef value = NULL; + bool entitled = false; + + status = SecCodeCopySigningInformation(proc.processCode(), kSecCSRequirementInformation, &code_info); + require_noerr(status, done); + + if (CFDictionaryGetValueIfPresent(code_info, kSecCodeInfoEntitlementsDict, &value)) { + if (CFGetTypeID(value) == CFDictionaryGetTypeID()) { + entitlements = (CFDictionaryRef)value; + } + } + require(entitlements != NULL, done); + + if (CFDictionaryGetValueIfPresent(entitlements, CFSTR("com.apple.private.securityd.stash"), &value)) { + if (CFGetTypeID(value) && CFBooleanGetTypeID()) { + entitled = CFBooleanGetValue((CFBooleanRef)value); + } + } + +done: + if (code_info) { + CFRelease(code_info); + } + + if (!entitled) { + CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED); + } +} + +kern_return_t ucsp_server_unlockDbWithPassphrase(UCSP_ARGS, DbHandle db, DATA_IN(passphrase)) +{ + BEGIN_IPC(unlockDbWithPassphrase) + Server::keychain(db)->unlockDb(DATA(passphrase)); + END_IPC(DL) +} + +kern_return_t ucsp_server_stashDb(UCSP_ARGS, DbHandle db) +{ + BEGIN_IPC(stashDb) + check_stash_entitlement(connection.process()); + Server::keychain(db)->stashDb(); + END_IPC(DL) +} + +kern_return_t ucsp_server_stashDbCheck(UCSP_ARGS, DbHandle db) +{ + BEGIN_IPC(stashDbCheck) + check_stash_entitlement(connection.process()); + Server::keychain(db)->stashDbCheck(); + END_IPC(DL) +} + +kern_return_t ucsp_server_isLocked(UCSP_ARGS, DbHandle db, boolean_t *locked) +{ + BEGIN_IPC(isLocked) + *locked = Server::database(db)->isLocked(); + END_IPC(DL) +} + +kern_return_t ucsp_server_verifyKeyStorePassphrase(UCSP_ARGS, uint32_t retries) +{ + BEGIN_IPC(verifyKeyStorePassphrase) + connection.process().session().verifyKeyStorePassphrase(retries); + END_IPC(DL) +} + +kern_return_t ucsp_server_changeKeyStorePassphrase(UCSP_ARGS) +{ + BEGIN_IPC(verifyKeyStorePassphrase) + connection.process().session().changeKeyStorePassphrase(); + END_IPC(DL) +} + +kern_return_t ucsp_server_resetKeyStorePassphrase(UCSP_ARGS, DATA_IN(passphrase)) +{ + BEGIN_IPC(verifyKeyStorePassphrase) + connection.process().session().resetKeyStorePassphrase(DATA(passphrase)); + END_IPC(DL) +} + +// +// Key management +// +kern_return_t ucsp_server_encodeKey(UCSP_ARGS, KeyHandle keyh, DATA_OUT(blob), + boolean_t wantUid, DATA_OUT(uid)) +{ + BEGIN_IPC(encodeKey) + RefPointer gKey = Server::key(keyh); + if (KeychainKey *key = dynamic_cast(gKey.get())) { + KeyBlob *keyBlob = key->blob(); // still owned by key + *blob = keyBlob; + *blobLength = keyBlob->length(); + if (wantUid) { // uid generation is not implemented + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + } else { + *uidLength = 0; // do not return this + } + } else { // not a KeychainKey + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); + } + END_IPC(CSP) +} + +kern_return_t ucsp_server_decodeKey(UCSP_ARGS, KeyHandle *keyh, DATA_OUT(keyHeader), + DbHandle db, DATA_IN(blob)) +{ + BEGIN_IPC(decodeKey) + RefPointer key = new KeychainKey(*Server::keychain(db), SSBLOB(KeyBlob, blob)); + CssmKey::Header header; + key->returnKey(*keyh, header); + if (!copyin(&header, reinterpret_cast (xdr_CSSM_KEYHEADER), keyHeader, keyHeaderLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*keyHeader); + END_IPC(CSP) +} + +// keychain synchronization +kern_return_t ucsp_server_recodeKey(UCSP_ARGS, DbHandle oldDb, KeyHandle keyh, + DbHandle newDb, DATA_OUT(newBlob)) +{ + BEGIN_IPC(recodeKey) + // If the old key is passed in as DATA_IN(oldBlob): + // RefPointer key = new KeychainKey(*Server::keychain(oldDb), SSBLOB(KeyBlob, oldBlob)); + RefPointer key = Server::key(keyh); + if (KeychainKey *kckey = dynamic_cast(key.get())) { + KeyBlob *blob = Server::keychain(newDb)->recodeKey(*kckey); + *newBlob = blob; + *newBlobLength = blob->length(); + Server::releaseWhenDone(*newBlob); + // @@@ stop leaking blob + } else { // not a KeychainKey + CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); + } + END_IPC(CSP) +} + +kern_return_t ucsp_server_releaseKey(UCSP_ARGS, KeyHandle keyh) +{ + BEGIN_IPC(releaseKey) + RefPointer key = Server::key(keyh); + key->database().releaseKey(*key); + END_IPC(CSP) +} + +kern_return_t ucsp_server_queryKeySizeInBits(UCSP_ARGS, KeyHandle keyh, CSSM_KEY_SIZE *length) +{ + BEGIN_IPC(queryKeySizeInBits) + RefPointer key = Server::key(keyh); + key->database().queryKeySizeInBits(*key, CssmKeySize::overlay(*length)); + END_IPC(CSP) +} + +kern_return_t ucsp_server_getOutputSize(UCSP_ARGS, DATA_IN(context), KeyHandle keyh, + uint32 inputSize, boolean_t encrypt, uint32 *outputSize) +{ + BEGIN_IPC(getOutputSize) + CopyOutContext ctx(context, contextLength); + RefPointer key = Server::key(keyh); + key->database().getOutputSize(*ctx, *key, inputSize, encrypt, *outputSize); + END_IPC(CSP) +} + +kern_return_t ucsp_server_getKeyDigest(UCSP_ARGS, KeyHandle key, DATA_OUT(digest)) +{ + BEGIN_IPC(getKeyDigest) + CssmData digestData = Server::key(key)->canonicalDigest(); + *digest = digestData.data(); + *digestLength = digestData.length(); + END_IPC(CSP) +} + + +// +// Signatures and MACs +// +kern_return_t ucsp_server_generateSignature(UCSP_ARGS, DATA_IN(context), KeyHandle keyh, + CSSM_ALGORITHMS signOnlyAlgorithm, DATA_IN(data), DATA_OUT(signature)) +{ + BEGIN_IPC(generateSignature) + CopyOutContext ctx(context, contextLength); + RefPointer key = Server::key(keyh); + OutputData sigData(signature, signatureLength); + key->database().generateSignature(*ctx, *key, signOnlyAlgorithm, + DATA(data), sigData); + END_IPC(CSP) +} + +kern_return_t ucsp_server_verifySignature(UCSP_ARGS, DATA_IN(context), KeyHandle keyh, + CSSM_ALGORITHMS verifyOnlyAlgorithm, DATA_IN(data), DATA_IN(signature)) +{ + BEGIN_IPC(verifySignature) + CopyOutContext ctx(context, contextLength); + RefPointer key = Server::key(keyh); + key->database().verifySignature(*ctx, *key, verifyOnlyAlgorithm, + DATA(data), DATA(signature)); + END_IPC(CSP) +} + +kern_return_t ucsp_server_generateMac(UCSP_ARGS, DATA_IN(context), KeyHandle keyh, + DATA_IN(data), DATA_OUT(mac)) +{ + BEGIN_IPC(generateMac) + CopyOutContext ctx(context, contextLength); + RefPointer key = Server::key(keyh); + OutputData macData(mac, macLength); + key->database().generateMac(*ctx, *key, DATA(data), macData); + END_IPC(CSP) +} + +kern_return_t ucsp_server_verifyMac(UCSP_ARGS, DATA_IN(context), KeyHandle keyh, + DATA_IN(data), DATA_IN(mac)) +{ + BEGIN_IPC(verifyMac) + CopyOutContext ctx(context, contextLength); + RefPointer key = Server::key(keyh); + key->database().verifyMac(*ctx, *key, DATA(data), DATA(mac)); + END_IPC(CSP) +} + + +// +// Encryption/Decryption +// +kern_return_t ucsp_server_encrypt(UCSP_ARGS, DATA_IN(context), KeyHandle keyh, + DATA_IN(clear), DATA_OUT(cipher)) +{ + BEGIN_IPC(encrypt) + CopyOutContext ctx(context, contextLength); + RefPointer key = Server::key(keyh); + OutputData cipherOut(cipher, cipherLength); + key->database().encrypt(*ctx, *key, DATA(clear), cipherOut); + END_IPC(CSP) +} + +kern_return_t ucsp_server_decrypt(UCSP_ARGS, DATA_IN(context), KeyHandle keyh, + DATA_IN(cipher), DATA_OUT(clear)) +{ + BEGIN_IPC(decrypt) + CopyOutContext ctx(context, contextLength); + RefPointer key = Server::key(keyh); + OutputData clearOut(clear, clearLength); + key->database().decrypt(*ctx, *key, DATA(cipher), clearOut); + END_IPC(CSP) +} + + +// +// Key generation +// +kern_return_t ucsp_server_generateKey(UCSP_ARGS, DbHandle db, DATA_IN(context), + DATA_IN(cred), DATA_IN(owner), + uint32 usage, uint32 attrs, KeyHandle *newKey, DATA_OUT(keyHeader)) +{ + BEGIN_IPC(generateKey) + CopyOutContext ctx(context, contextLength); + CopyOutAccessCredentials creds(cred, credLength); + + CopyOutEntryAcl owneracl(owner, ownerLength); + //@@@ preliminary interpretation - will get "type handle" + RefPointer database = + Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT); + RefPointer key; + database->generateKey(*ctx, creds, owneracl, usage, attrs, key); + CssmKey::Header newHeader; + key->returnKey(*newKey, newHeader); + + if (!copyin(&newHeader, reinterpret_cast (xdr_CSSM_KEYHEADER), keyHeader, keyHeaderLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*keyHeader); + END_IPC(CSP) +} + +kern_return_t ucsp_server_generateKeyPair(UCSP_ARGS, DbHandle db, DATA_IN(context), + DATA_IN(cred), DATA_IN(owner), + uint32 pubUsage, uint32 pubAttrs, uint32 privUsage, uint32 privAttrs, + KeyHandle *pubKey, DATA_OUT(pubHeader), KeyHandle *privKey, DATA_OUT(privHeader)) +{ + BEGIN_IPC(generateKeyPair) + CopyOutContext ctx(context, contextLength); + CopyOutAccessCredentials creds(cred, credLength); + CopyOutEntryAcl owneracl(owner, ownerLength); + RefPointer database = + Server::optionalDatabase(db, (privAttrs | pubAttrs) & CSSM_KEYATTR_PERMANENT); + RefPointer pub, priv; + database->generateKey(*ctx, creds, owneracl, + pubUsage, pubAttrs, privUsage, privAttrs, pub, priv); + CssmKey::Header tmpPubHeader, tmpPrivHeader; + + pub->returnKey(*pubKey, tmpPubHeader); + if (!copyin(&tmpPubHeader, reinterpret_cast (xdr_CSSM_KEYHEADER), pubHeader, pubHeaderLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*pubHeader); + + priv->returnKey(*privKey, tmpPrivHeader); + if (!copyin(&tmpPrivHeader, reinterpret_cast (xdr_CSSM_KEYHEADER), privHeader, privHeaderLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*privHeader); + + END_IPC(CSP) +} + + +// +// Key wrapping and unwrapping +// +kern_return_t ucsp_server_wrapKey(UCSP_ARGS, DATA_IN(context), KeyHandle hWrappingKey, + DATA_IN(cred), KeyHandle hKeyToBeWrapped, + DATA_IN(descriptiveData), DATA_OUT(wrappedKeyData)) +{ + BEGIN_IPC(wrapKey) + CssmKey wrappedKey; + CopyOutContext ctx(context, contextLength); + CopyOutAccessCredentials creds(cred, credLength); + RefPointer subjectKey = Server::key(hKeyToBeWrapped); + RefPointer wrappingKey = Server::optionalKey(hWrappingKey); + if ((ctx.context().algorithm() == CSSM_ALGID_NONE && subjectKey->attribute(CSSM_KEYATTR_SENSITIVE)) + || !subjectKey->attribute(CSSM_KEYATTR_EXTRACTABLE)) + CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); + pickDb(subjectKey, wrappingKey)->wrapKey(*ctx, creds, wrappingKey, *subjectKey, DATA(descriptiveData), wrappedKey); + Server::releaseWhenDone(wrappedKey.keyData().data()); + + if (!copyin(&wrappedKey, reinterpret_cast (xdr_CSSM_KEY), wrappedKeyData, wrappedKeyDataLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + + Server::releaseWhenDone(*wrappedKeyData); + END_IPC(CSP) +} + +kern_return_t ucsp_server_unwrapKey(UCSP_ARGS, DbHandle db, DATA_IN(context), + KeyHandle hWrappingKey, DATA_IN(cred), DATA_IN(owner), + KeyHandle hPublicKey, DATA_IN(wrappedKeyData), + CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, DATA_OUT(descriptiveData), + KeyHandle *newKey, DATA_OUT(keyHeader)/*CssmKey::Header *newHeader*/) +{ + BEGIN_IPC(unwrapKey) + CopyOutContext ctx(context, contextLength); + CopyOutKey wrappedKey(wrappedKeyData, wrappedKeyDataLength); + CopyOutAccessCredentials creds(cred, credLength); + CopyOutEntryAcl owneracl(owner, ownerLength); + OutputData descriptiveDatas(descriptiveData, descriptiveDataLength); + RefPointer wrappingKey = Server::optionalKey(hWrappingKey); + RefPointer unwrappedKey; + pickDb(Server::optionalDatabase(db), wrappingKey)->unwrapKey(*ctx, creds, owneracl, + wrappingKey, Server::optionalKey(hPublicKey), + usage, attrs, wrappedKey.key(), unwrappedKey, descriptiveDatas); + + CssmKey::Header newHeader; + unwrappedKey->returnKey(*newKey, newHeader); + if (!copyin(&newHeader, reinterpret_cast (xdr_CSSM_KEYHEADER), keyHeader, keyHeaderLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*keyHeader); + + END_IPC(CSP) +} + + +// +// Key derivation. +// +// Note that the "param" argument can have structure. The walker for the +// (artificial) POD CssmDeriveData handles those that are known; if you add +// an algorithm with structured param, you need to add a case there. +// +kern_return_t ucsp_server_deriveKey(UCSP_ARGS, DbHandle db, DATA_IN(context), KeyHandle hKey, + DATA_IN(cred), DATA_IN(owner), + DATA_IN(paramInput), DATA_OUT(paramOutput), + uint32 usage, uint32 attrs, KeyHandle *newKey, DATA_OUT(keyHeader)) +{ + BEGIN_IPC(deriveKey) + CopyOutContext ctx(context, contextLength); + CopyOutAccessCredentials creds(cred, credLength); + CopyOutEntryAcl owneracl(owner, ownerLength); + CopyOutDeriveData deriveParam(paramInput, paramInputLength); + if (deriveParam.algorithm() != ctx.context().algorithm()) + CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); // client layer fault + + RefPointer database = + Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT); + RefPointer key = Server::optionalKey(hKey); + CSSM_DATA param = deriveParam.cssm_data(); + RefPointer derivedKey; + pickDb(Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT), + key)->deriveKey(*ctx, key, creds, owneracl, static_cast(¶m), usage, attrs, derivedKey); + + CssmKey::Header newHeader; + derivedKey->returnKey(*newKey, newHeader); + + if (!copyin(&newHeader, reinterpret_cast (xdr_CSSM_KEYHEADER), keyHeader, keyHeaderLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*keyHeader); + + if (param.Length) { + if (!param.Data) // CSP screwed up + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); + OutputData(paramOutput, paramOutputLength) = CssmAutoData(Server::csp().allocator(), param).release(); + } + END_IPC(CSP) +} + + +// +// Random generation +// +kern_return_t ucsp_server_generateRandom(UCSP_ARGS, uint32 ssid, DATA_IN(context), DATA_OUT(data)) +{ + BEGIN_IPC(generateRandom) + CopyOutContext ctx(context, contextLength); + if (ssid) + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + + // default version (use /dev/random) + Allocator &allocator = Allocator::standard(Allocator::sensitive); + if (size_t bytes = ctx.context().getInt(CSSM_ATTRIBUTE_OUTPUT_SIZE)) { + void *buffer = allocator.malloc(bytes); + Server::active().random(buffer, bytes); + *data = buffer; + *dataLength = bytes; + Server::releaseWhenDone(allocator, buffer); + } + END_IPC(CSP) +} + + +// +// ACL management. +// Watch out for the memory-management tap-dance. +// +kern_return_t ucsp_server_getOwner(UCSP_ARGS, AclKind kind, KeyHandle key, + DATA_OUT(ownerOut)) +{ + BEGIN_IPC(getOwner) + AclOwnerPrototype owner; + Server::aclBearer(kind, key).getOwner(owner); // allocates memory in owner + void *owners_data; u_int owners_length; + if (!::copyin(&owner, reinterpret_cast(xdr_CSSM_ACL_OWNER_PROTOTYPE), &owners_data, &owners_length)) + CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR); + + { ChunkFreeWalker free; walk(free, owner); } // release chunked original + Server::releaseWhenDone(owners_data); // throw flat copy out when done + *ownerOut = owners_data; + *ownerOutLength = owners_length; + END_IPC(CSP) +} + +kern_return_t ucsp_server_setOwner(UCSP_ARGS, AclKind kind, KeyHandle key, + DATA_IN(cred), DATA_IN(owner)) +{ + BEGIN_IPC(setOwner) + CopyOutAccessCredentials creds(cred, credLength); + CopyOutOwnerAcl owneracl(owner, ownerLength); + Server::aclBearer(kind, key).changeOwner(*owneracl, creds); + END_IPC(CSP) +} + +kern_return_t ucsp_server_getAcl(UCSP_ARGS, AclKind kind, KeyHandle key, + boolean_t haveTag, const char *tag, + uint32 *countp, DATA_OUT(acls)) +{ + BEGIN_IPC(getAcl) + uint32 count; + AclEntryInfo *aclList; + Server::aclBearer(kind, key).getAcl(haveTag ? tag : NULL, count, aclList); + + CSSM_ACL_ENTRY_INFO_ARRAY aclsArray = { count, aclList }; + void *acls_data; u_int acls_length; + if (!::copyin(&aclsArray, reinterpret_cast(xdr_CSSM_ACL_ENTRY_INFO_ARRAY), &acls_data, &acls_length)) + CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR); + + { // release the chunked memory originals + ChunkFreeWalker free; + for (uint32 n = 0; n < count; n++) + walk(free, aclList[n]); + + // release the memory allocated for the list itself when we are done + Allocator::standard().free (aclList); + } + + + *countp = count; // XXX/cs count becomes part of the blob + *aclsLength = acls_length; + *acls = acls_data; + Server::releaseWhenDone(acls_data); + END_IPC(CSP) +} + +kern_return_t ucsp_server_changeAcl(UCSP_ARGS, AclKind kind, KeyHandle key, + DATA_IN(cred), CSSM_ACL_EDIT_MODE mode, GenericHandle handle, + DATA_IN(acl)) +{ + BEGIN_IPC(changeAcl) + CopyOutAccessCredentials creds(cred, credLength); + CopyOutAclEntryInput entryacl(acl, aclLength); + + Server::aclBearer(kind, key).changeAcl(AclEdit(mode, handle, entryacl), creds); + END_IPC(CSP) +} + + +// +// Login/Logout +// +kern_return_t ucsp_server_login(UCSP_ARGS, DATA_IN(cred), DATA_IN(name)) +{ + BEGIN_IPC(login) + CopyOutAccessCredentials creds(cred, credLength); + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + END_IPC(CSP) +} + +kern_return_t ucsp_server_logout(UCSP_ARGS) +{ + BEGIN_IPC(logout) + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + END_IPC(CSP) +} + + +// +// Miscellaneous CSP-related calls +// +kern_return_t ucsp_server_getStatistics(UCSP_ARGS, uint32 ssid, CSSM_CSP_OPERATIONAL_STATISTICS *statistics) +{ + BEGIN_IPC(getStatistics) + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + END_IPC(CSP) +} + +kern_return_t ucsp_server_getTime(UCSP_ARGS, uint32 ssid, CSSM_ALGORITHMS algorithm, DATA_OUT(data)) +{ + BEGIN_IPC(getTime) + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + END_IPC(CSP) +} + +kern_return_t ucsp_server_getCounter(UCSP_ARGS, uint32 ssid, DATA_OUT(data)) +{ + BEGIN_IPC(getCounter) + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + END_IPC(CSP) +} + +kern_return_t ucsp_server_selfVerify(UCSP_ARGS, uint32 ssid) +{ + BEGIN_IPC(selfVerify) + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + END_IPC(CSP) +} + + +// +// Passthrough calls (separate for CSP and DL passthroughs) +// +kern_return_t ucsp_server_cspPassThrough(UCSP_ARGS, uint32 ssid, uint32 id, DATA_IN(context), + KeyHandle hKey, DATA_IN(inData), DATA_OUT(outData)) +{ + BEGIN_IPC(cspPassThrough) + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + END_IPC(CSP) +} + +kern_return_t ucsp_server_dlPassThrough(UCSP_ARGS, uint32 ssid, uint32 id, + DATA_IN(inData), DATA_OUT(outData)) +{ + BEGIN_IPC(dlPassThrough) + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); + END_IPC(DL) +} + + +// +// Database key management. +// ExtractMasterKey looks vaguely like a key derivation operation, and is in fact +// presented by the CSPDL's CSSM layer as such. +// +kern_return_t ucsp_server_extractMasterKey(UCSP_ARGS, DbHandle db, DATA_IN(context), DbHandle sourceDb, + DATA_IN(cred), DATA_IN(owner), + uint32 usage, uint32 attrs, KeyHandle *newKey, DATA_OUT(keyHeader)) +{ + BEGIN_IPC(extractMasterKey) + CopyOutAccessCredentials creds(cred, credLength); + CopyOutEntryAcl owneracl(owner, ownerLength); + CopyOutContext ctx(context, contextLength); + RefPointer keychain = Server::keychain(sourceDb); + RefPointer masterKey = keychain->extractMasterKey( + *Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT), + creds, owneracl, usage, attrs); + CssmKey::Header header; + masterKey->returnKey(*newKey, header); + if (!copyin(&header, reinterpret_cast (xdr_CSSM_KEYHEADER), keyHeader, keyHeaderLength)) + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + Server::releaseWhenDone(*keyHeader); + END_IPC(CSP) +} + + +// +// Authorization subsystem support +// +kern_return_t ucsp_server_authorizationCreate(UCSP_ARGS, + void *inRights, mach_msg_type_number_t inRightsLength, + uint32 flags, + void *inEnvironment, mach_msg_type_number_t inEnvironmentLength, + AuthorizationBlob *authorization) +{ + BEGIN_IPC(authorizationCreate) + AuthorizationItemSet *authrights = NULL, *authenvironment = NULL; + + if (inRights && !copyout_AuthorizationItemSet(inRights, inRightsLength, &authrights)) + { + Syslog::alert("ucsp_server_authorizationCreate(): error converting 'rights' input"); + CssmError::throwMe(errAuthorizationInternal); // allocation error probably + } + + if (inEnvironment && !copyout_AuthorizationItemSet(inEnvironment, inEnvironmentLength, &authenvironment)) + { + free(authrights); + Syslog::alert("ucsp_server_authorizationCreate(): error converting 'environment' input"); + CssmError::throwMe(errAuthorizationInternal); // allocation error probably + } + + Authorization::AuthItemSet rights(authrights), environment(authenvironment); + + *rcode = connection.process().session().authCreate(rights, environment, + flags, *authorization, auditToken); + + // @@@ safe-guard against code throw()ing in here + + if (authrights) + free(authrights); + + if (authenvironment) + free(authenvironment); + + END_IPC(CSSM) +} + +kern_return_t ucsp_server_authorizationRelease(UCSP_ARGS, + AuthorizationBlob authorization, uint32 flags) +{ + BEGIN_IPC(authorizationRelease) + connection.process().session().authFree(authorization, flags); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_authorizationCopyRights(UCSP_ARGS, + AuthorizationBlob authorization, + void *inRights, mach_msg_type_number_t inRightsLength, + uint32 flags, + void *inEnvironment, mach_msg_type_number_t inEnvironmentLength, + void **result, mach_msg_type_number_t *resultLength) +{ + BEGIN_IPC(authorizationCopyRights) + AuthorizationItemSet *authrights = NULL, *authenvironment = NULL; + + if (inRights && !copyout_AuthorizationItemSet(inRights, inRightsLength, &authrights)) + { + Syslog::alert("ucsp_server_authorizationCopyRights(): error converting 'rights' input"); + CssmError::throwMe(errAuthorizationInternal); // allocation error probably + } + if (inEnvironment && !copyout_AuthorizationItemSet(inEnvironment, inEnvironmentLength, &authenvironment)) + { + free(authrights); + Syslog::alert("ucsp_server_authorizationCopyRights(): error converting 'environment' input"); + CssmError::throwMe(errAuthorizationInternal); // allocation error probably + } + + Authorization::AuthItemSet rights(authrights), environment(authenvironment), grantedRights; + *rcode = Session::authGetRights(authorization, rights, environment, flags, grantedRights); + + // @@@ safe-guard against code throw()ing in here + + if (authrights) + free(authrights); + + if (authenvironment) + free(authenvironment); + + if (result && resultLength) + { + AuthorizationItemSet *copyout = grantedRights.copy(); + if (!copyin_AuthorizationItemSet(copyout, result, resultLength)) + { + free(copyout); + Syslog::alert("ucsp_server_authorizationCopyRights(): error packaging return information"); + CssmError::throwMe(errAuthorizationInternal); + } + free(copyout); + Server::releaseWhenDone(*result); + } + END_IPC(CSSM) +} + +kern_return_t ucsp_server_authorizationCopyInfo(UCSP_ARGS, + AuthorizationBlob authorization, + AuthorizationString tag, + void **info, mach_msg_type_number_t *infoLength) +{ + BEGIN_IPC(authorizationCopyInfo) + Authorization::AuthItemSet infoSet; + *info = NULL; + *infoLength = 0; + *rcode = connection.process().session().authGetInfo(authorization, + tag[0] ? tag : NULL, infoSet); + if (*rcode == noErr) + { + AuthorizationItemSet *copyout = infoSet.copy(); + if (!copyin_AuthorizationItemSet(copyout, info, infoLength)) + { + free(copyout); + Syslog::alert("ucsp_server_authorizationCopyInfo(): error packaging return information"); + CssmError::throwMe(errAuthorizationInternal); + } + free(copyout); + Server::releaseWhenDone(*info); + } + END_IPC(CSSM) +} + +kern_return_t ucsp_server_authorizationExternalize(UCSP_ARGS, + AuthorizationBlob authorization, AuthorizationExternalForm *extForm) +{ + BEGIN_IPC(authorizationExternalize) + *rcode = connection.process().session().authExternalize(authorization, *extForm); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_authorizationInternalize(UCSP_ARGS, + AuthorizationExternalForm extForm, AuthorizationBlob *authorization) +{ + BEGIN_IPC(authorizationInternalize) + *rcode = connection.process().session().authInternalize(extForm, *authorization); + END_IPC(CSSM) +} + + +// +// Session management subsystem +// +kern_return_t ucsp_server_setSessionUserPrefs(UCSP_ARGS, SecuritySessionId sessionId, DATA_IN(userPrefs)) +{ + BEGIN_IPC(setSessionuserPrefs) + CFRef data(CFDataCreate(NULL, (UInt8 *)userPrefs, userPrefsLength)); + + if (!data) + { + *rcode = errSessionValueNotSet; + return 0; + } + + Session::find(sessionId).setUserPrefs(data); + *rcode = 0; + + END_IPC(CSSM) +} + + +// +// Notification core subsystem +// + +kern_return_t ucsp_server_postNotification(UCSP_ARGS, uint32 domain, uint32 event, + DATA_IN(data), uint32 sequence) +{ + BEGIN_IPC(postNotification) + Listener::notify(domain, event, sequence, DATA(data)); + END_IPC(CSSM) +} + + +// +// AuthorizationDB modification +// +kern_return_t ucsp_server_authorizationdbGet(UCSP_ARGS, const char *rightname, DATA_OUT(rightDefinition)) +{ + BEGIN_IPC(authorizationdbGet) + CFDictionaryRef rightDict; + + *rcode = connection.process().session().authorizationdbGet(rightname, &rightDict); + + if (!*rcode && rightDict) + { + CFRef data(CFPropertyListCreateXMLData (NULL, rightDict)); + CFRelease(rightDict); + if (!data) + { + Syslog::alert("ucsp_server_authorizationGet(): unable to make XML version of right definition for '%s'", rightname); + return errAuthorizationInternal; + } + + // @@@ copy data to avoid having to do a delayed cfrelease + mach_msg_type_number_t length = CFDataGetLength(data); + void *xmlData = Allocator::standard().malloc(length); + memcpy(xmlData, CFDataGetBytePtr(data), length); + Server::releaseWhenDone(xmlData); + + *rightDefinition = xmlData; + *rightDefinitionLength = length; + } + END_IPC(CSSM) +} + +kern_return_t ucsp_server_authorizationdbSet(UCSP_ARGS, AuthorizationBlob authorization, const char *rightname, DATA_IN(rightDefinition)) +{ + BEGIN_IPC(authorizationdbSet) + CFRef data(CFDataCreate(NULL, (UInt8 *)rightDefinition, rightDefinitionLength)); + + if (!data) + { + Syslog::alert("ucsp_server_authorizationSet(): CFDataCreate() error"); + return errAuthorizationInternal; + } + + CFRef rightDefinition(static_cast(CFPropertyListCreateFromXMLData(NULL, data, kCFPropertyListImmutable, NULL))); + + if (!rightDefinition || (CFGetTypeID(rightDefinition) != CFDictionaryGetTypeID())) + { + Syslog::alert("ucsp_server_authorizationSet(): error converting XML right definition for '%s' to property list", rightname); + return errAuthorizationInternal; + } + + *rcode = connection.process().session().authorizationdbSet(authorization, rightname, rightDefinition); + + END_IPC(CSSM) +} + +kern_return_t ucsp_server_authorizationdbRemove(UCSP_ARGS, AuthorizationBlob authorization, const char *rightname) +{ + BEGIN_IPC(authorizationdbRemove) + *rcode = connection.process().session().authorizationdbRemove(authorization, rightname); + END_IPC(CSSM) +} + + +// +// Miscellaneous administrative functions +// +kern_return_t ucsp_server_addCodeEquivalence(UCSP_ARGS, DATA_IN(oldHash), DATA_IN(newHash), + const char *name, boolean_t forSystem) +{ + BEGIN_IPC(addCodeEquivalence) + Server::codeSignatures().addLink(DATA(oldHash), DATA(newHash), name, forSystem); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_removeCodeEquivalence(UCSP_ARGS, DATA_IN(hash), + const char *name, boolean_t forSystem) +{ + BEGIN_IPC(removeCodeEquivalence) + Server::codeSignatures().removeLink(DATA(hash), name, forSystem); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_setAlternateSystemRoot(UCSP_ARGS, const char *root) +{ + BEGIN_IPC(setAlternateSystemRoot) +#if defined(NDEBUG) + if (connection.process().uid() != 0) + CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED); +#endif //NDEBUG + Server::codeSignatures().open((string(root) + EQUIVALENCEDBPATH).c_str()); + END_IPC(CSSM) +} + + +// +// Child check-in service. +// Note that this isn't using the standard argument pattern. +// +kern_return_t ucsp_server_childCheckIn(mach_port_t serverPort, + mach_port_t servicePort, mach_port_t taskPort) +{ + BEGIN_IPCS + ServerChild::checkIn(servicePort, TaskPort(taskPort).pid()); + END_IPCS(mach_port_deallocate(mach_task_self(), taskPort)) +} + + +// +// Code Signing Hosting registration. +// Note that the Code Signing Proxy facility (implementing the "cshosting" +// IPC protocol) is elsewhere. +// +kern_return_t ucsp_server_registerHosting(UCSP_ARGS, mach_port_t hostingPort, uint32 flags) +{ + BEGIN_IPC(registerHosting) + connection.process().registerCodeSigning(hostingPort, flags); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_hostingPort(UCSP_ARGS, pid_t hostPid, mach_port_t *hostingPort) +{ + BEGIN_IPC(hostingPort) + if (RefPointer process = Server::active().findPid(hostPid)) + *hostingPort = process->hostingPort(); + else + *hostingPort = MACH_PORT_NULL; + secdebug("hosting", "hosting port for for pid=%d is port %d", hostPid, *hostingPort); + END_IPC(CSSM) +} + + +kern_return_t ucsp_server_setGuest(UCSP_ARGS, SecGuestRef guest, SecCSFlags flags) +{ + BEGIN_IPC(setGuest) + connection.guestRef(guest, flags); + END_IPC(CSSM) +} + + +kern_return_t ucsp_server_createGuest(UCSP_ARGS, SecGuestRef host, + uint32_t status, const char *path, DATA_IN(cdhash), DATA_IN(attributes), + SecCSFlags flags, SecGuestRef *newGuest) +{ + BEGIN_IPC(createGuest) + *newGuest = connection.process().createGuest(host, status, path, DATA(cdhash), DATA(attributes), flags); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_setGuestStatus(UCSP_ARGS, SecGuestRef guest, + uint32_t status, DATA_IN(attributes)) +{ + BEGIN_IPC(setGuestStatus) + connection.process().setGuestStatus(guest, status, DATA(attributes)); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_removeGuest(UCSP_ARGS, SecGuestRef host, SecGuestRef guest) +{ + BEGIN_IPC(removeGuest) + connection.process().removeGuest(host, guest); + END_IPC(CSSM) +} + +kern_return_t ucsp_server_helpCheckLoad(UCSP_ARGS, const char path[PATH_MAX], uint32_t type) +{ + BEGIN_IPC(helpCheckLoad) + END_IPC(CSSM) +} diff --git a/securityd/tests/AZNTest.cpp b/securityd/tests/AZNTest.cpp new file mode 100644 index 00000000..603bb6b3 --- /dev/null +++ b/securityd/tests/AZNTest.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2000-2001,2003-2004 Apple Computer, 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@ + */ + + +/* + * AZNTest.cpp + * SecurityServer + * + * Created by michael on Fri Oct 20 2000. + */ + +#include + +#include + +using namespace Authorization; + +static const AuthorizationItem gItems[] = +{ + {"login", 0, NULL, NULL}, + {"reboot", 0, NULL, NULL}, + {"shutdown", 0, NULL, NULL}, + {"mount", 0, NULL, NULL}, + {"login.reboot", 0, NULL, NULL}, + {"login.shutdown", 0, NULL, NULL}, + {"unmount", 0, NULL, NULL} +}; + +static const AuthorizationRights gRights = +{ + 7, + const_cast(gItems) +}; + +void +printRights(const RightSet &rightSet) +{ + for(RightSet::const_iterator it = rightSet.begin(); it != rightSet.end(); ++it) + { + printf("right: \"%s\"\n", it->rightName()); + } +} + +int +main(int argc, char **argv) +{ + Engine engine("/tmp/config.plist"); + + const RightSet inputRights(&gRights); + MutableRightSet outputRights; + printf("InputRights:\n"); + printRights(inputRights); + printf("Authorizing:\n"); + OSStatus result = engine.authorize(inputRights, NULL, + kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights | kAuthorizationFlagPartialRights, + NULL, NULL, &outputRights); + printf("Result: %ld\n", result); + printf("OutputRights:\n"); + printRights(outputRights); + return 0; +} diff --git a/securityd/tests/auth.plist b/securityd/tests/auth.plist new file mode 100644 index 00000000..b9732dc9 --- /dev/null +++ b/securityd/tests/auth.plist @@ -0,0 +1,19 @@ + + + + + debug. + + group + yes + shared + + timeout + 300 + + debug.allow + allow + debug.deny + deny + + diff --git a/securityd/tests/exectest.cpp b/securityd/tests/exectest.cpp new file mode 100644 index 00000000..b8693bd7 --- /dev/null +++ b/securityd/tests/exectest.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2000-2001,2003-2004 Apple Computer, 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@ + */ + + +// +// Exectest - privileged-execution test driver +// +#include +#include +#include + + +void doLoopback(int argc, char *argv[]); + + +int main(int argc, char **argv) +{ + const char *path = "/usr/bin/id"; + bool writeToPipe = false; + bool loopback = false; + + int arg; + extern char *optarg; + extern int optind; + while ((arg = getopt(argc, argv, "f:lLw")) != -1) { + switch (arg) { + case 'f': + path = optarg; + break; + case 'l': + loopback = true; + break; + case 'L': + doLoopback(argc, argv); + exit(0); + case 'w': + writeToPipe = true; + break; + case '?': + exit(2); + } + } + + AuthorizationItem right = { "system.privilege.admin", 0, NULL, 0 }; + AuthorizationRights rights = { 1, &right }; + + AuthorizationRef auth; + if (OSStatus error = AuthorizationCreate(&rights, NULL /*env*/, + kAuthorizationFlagInteractionAllowed | + kAuthorizationFlagExtendRights | + kAuthorizationFlagPreAuthorize, + &auth)) { + printf("create error %ld\n", error); + exit(1); + } + + if (loopback) { + path = argv[0]; + argv[--optind] = "-L"; // backing over existing array element + } + + FILE *f; + if (OSStatus error = AuthorizationExecuteWithPrivileges(auth, + path, 0, argv + optind, &f)) { + printf("exec error %ld\n", error); + exit(1); + } + printf("--- execute successful ---\n"); + if (writeToPipe) { + char buffer[1024]; + while (fgets(buffer, sizeof(buffer), stdin)) + fprintf(f, "%s", buffer); + } else { + char buffer[1024]; + while (fgets(buffer, sizeof(buffer), f)) + printf("%s", buffer); + } + printf("--- end of output ---\n"); + exit(0); +} + + +void doLoopback(int argc, char *argv[]) +{ + // general status + printf("Authorization Execution Loopback Test\n"); + printf("Invoked as"); + for (int n = 0; argv[n]; n++) + printf(" %s", argv[n]); + printf("\n"); + + // recover the authorization handle + AuthorizationRef auth; + if (OSStatus err = AuthorizationCopyPrivilegedReference(&auth, 0)) { + printf("Cannot recover AuthorizationRef: error=%ld\n", err); + exit(1); + } + + printf("AuthorizationRef recovered.\n"); +} diff --git a/securityd/tests/testacls.cpp b/securityd/tests/testacls.cpp new file mode 100644 index 00000000..3d2986e3 --- /dev/null +++ b/securityd/tests/testacls.cpp @@ -0,0 +1,409 @@ +/* + * Copyright (c) 2000-2001,2003-2004 Apple Computer, 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@ + */ + + +// +// testacls - ACL-related test cases. +// +#include "testclient.h" +#include "testutils.h" +#include + +using namespace CodeSigning; + + +// +// ACL get/set tests +// +void acls() +{ + printf("* Basic ACL tests\n"); + CssmAllocator &alloc = CssmAllocator::standard(); + ClientSession ss(alloc, alloc); + + // create key with initial ACL + StringData initialAclPassphrase("very secret"); + AclEntryPrototype initialAcl; + initialAcl.TypedSubject = TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD, + new(alloc) ListElement(initialAclPassphrase)); + AclEntryInput initialAclInput(initialAcl); + AclTester tester(ss, &initialAclInput); + + // get the owner and verify + AclOwnerPrototype owner; + ss.getKeyOwner(tester.keyRef, owner); + assert(owner.subject().type() == CSSM_ACL_SUBJECT_TYPE_PASSWORD); + assert(owner.subject().length() == 1); + + // get the acl entry and verify + { + uint32 count; + AclEntryInfo *acls; + ss.getKeyAcl(tester.keyRef, NULL/*tag*/, count, acls); + assert(count == 1); + const AclEntryInfo &acl1 = acls[0]; + const TypedList &subject1 = acl1.proto().subject(); + assert(subject1.type() == CSSM_ACL_SUBJECT_TYPE_PASSWORD); + assert(subject1.length() == 1); + } + + // try to use the key and see... + tester.testWrap(&nullCred, "ACCEPTING NULL CREDENTIAL"); + AutoCredentials cred(alloc); + cred += TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD, + new(alloc) ListElement(StringData("wrongo"))); + tester.testWrap(&cred, "ACCEPTING WRONG PASSWORD CREDENTIAL"); + cred += TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD, + new(alloc) ListElement(StringData("very secret"))); + tester.testWrap(&cred); + + // now *replace* the ACL entry with a new one... + { + detail("Changing ACL"); + uint32 count; + AclEntryInfo *infos; + ss.getKeyAcl(tester.keyRef, NULL, count, infos); + assert(count == 1); // one entry + + AclEntryPrototype newAcl; + TypedList subject = TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_THRESHOLD, + new(alloc) ListElement(2), new(alloc) ListElement(3)); + subject += new(alloc) ListElement(TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD, + new(alloc) ListElement(alloc, "check me!"))); + subject += new(alloc) ListElement(TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD, + new(alloc) ListElement(alloc, "once again!"))); + subject += new(alloc) ListElement(TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD, + new(alloc) ListElement(alloc, "hug me!"))); + newAcl.TypedSubject = subject; + AclEntryInput input(newAcl); + AclEdit edit(infos[0].handle(), input); + + try { + AutoCredentials nullCred(alloc); + ss.changeKeyAcl(tester.keyRef, nullCred, edit); + error("ALLOWED ACL EDIT WITHOUT CREDENTIALS"); + } catch (CssmCommonError &err) { + detail(err, "Acl Edit rejected properly"); + } + ss.changeKeyAcl(tester.keyRef, cred, edit); + detail("ACL changed OK"); + } + + // ... and see how the new one reacts + tester.testWrap(&nullCred, "ACCEPTING NULL CREDENTIALS NOW"); + tester.testWrap(&cred, "ACCEPTING OLD CREDENTIALS FOR NEW ACL"); + { + AutoCredentials cred(alloc); + cred += TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD, + new(alloc) ListElement(alloc, "check me!")); + tester.testWrap(&cred, "ACCEPTING LEAF SAMPLE WITHOUT THRESHOLD FRAMEWORK"); + } + + // Threshold subjects + { + detail("Testing threshold ACLs"); + AutoCredentials cred(alloc); + TypedList &threshold = cred += TypedList(alloc, CSSM_SAMPLE_TYPE_THRESHOLD, + new(alloc) ListElement(TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD, + new(alloc) ListElement(alloc, "wrongo!"))) + ); + tester.testWrap(&cred, "ACCEPTING ALL WRONG SAMPLES IN THRESHOLD"); + threshold += new(alloc) ListElement(TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD, + new(alloc) ListElement(alloc, "hug me!"))); + tester.testWrap(&cred, "ACCEPTING TOO FEW THRESHOLD SAMPLES"); + threshold += new(alloc) ListElement(TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD, + new(alloc) ListElement(alloc, "check me!"))); + tester.testWrap(&cred); + // stuff the ballot box + threshold += new(alloc) ListElement(TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD, + new(alloc) ListElement(alloc, "and this!"))); + threshold += new(alloc) ListElement(TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD, + new(alloc) ListElement(alloc, "and that!"))); + threshold += new(alloc) ListElement(TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD, + new(alloc) ListElement(alloc, "and more!"))); +#ifdef STRICT_THRESHOLD_SUBJECTS + tester.testWrap(&cred, "ACCEPTING OVER-STUFFED THRESHOLD"); +#else + tester.testWrap(&cred); +#endif //STRICT_THRESHOLD_SUBJECTS + } + + // comment ACLs and tags + { + detail("Adding Comment entry"); + + AclEntryPrototype newAcl; + TypedList subject = TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_COMMENT, + new(alloc) ListElement(TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_THRESHOLD, + new(alloc) ListElement(alloc, "Robby Ray!"))), + new(alloc) ListElement(666)); + newAcl.TypedSubject = subject; + strcpy(newAcl.EntryTag, "vamos"); + AclEntryInput input(newAcl); + AclEdit edit(input); + ss.changeKeyAcl(tester.keyRef, cred, edit); + detail("Entry added"); + + uint32 count; + AclEntryInfo *infos; + ss.getKeyAcl(tester.keyRef, "vamos", count, infos); + assert(count == 1); // one entry (with this tag) + const AclEntryInfo &acl = infos[0]; + const TypedList &read = acl.proto().subject(); + assert(read.type() == CSSM_ACL_SUBJECT_TYPE_COMMENT); + assert(read.length() == 3); + assert(read[2] == 666); + CssmList &sublist = read[1]; + assert(sublist[0] == CSSM_ACL_SUBJECT_TYPE_THRESHOLD); + assert(string(sublist[1]) == "Robby Ray!"); + + detail("Comment entry retrieved okay"); + } +} + + +// +// ACL authorization tests +// +void authAcls() +{ + printf("* ACL authorizations test\n"); + CssmAllocator &alloc = CssmAllocator::standard(); + ClientSession ss(alloc, alloc); + + // create key with initial ACL + CSSM_ACL_AUTHORIZATION_TAG wrapTag = CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR; + CSSM_ACL_AUTHORIZATION_TAG encryptTag = CSSM_ACL_AUTHORIZATION_ENCRYPT; + StringData initialAclPassphrase("very secret"); + StringData the2ndAclPassword("most secret"); + AclEntryPrototype initialAcl; + initialAcl.TypedSubject = TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD, + new(alloc) ListElement(initialAclPassphrase)); + initialAcl.authorization().NumberOfAuthTags = 1; + initialAcl.authorization().AuthTags = &wrapTag; + AclEntryInput initialAclInput(initialAcl); + AclTester tester(ss, &initialAclInput); + + // get the owner and verify + AclOwnerPrototype owner; + ss.getKeyOwner(tester.keyRef, owner); + assert(owner.subject().type() == CSSM_ACL_SUBJECT_TYPE_PASSWORD); + assert(owner.subject().length() == 1); + + // get the acl entry and verify + { + uint32 count; + AclEntryInfo *acls; + ss.getKeyAcl(tester.keyRef, NULL/*tag*/, count, acls); + assert(count == 1); + const AclEntryInfo &acl1 = acls[0]; + const TypedList &subject1 = acl1.proto().subject(); + assert(subject1.type() == CSSM_ACL_SUBJECT_TYPE_PASSWORD); + assert(subject1.length() == 1); + const AuthorizationGroup &auths = acl1.proto().authorization(); + assert(auths.count() == 1); + assert(auths[0] == CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR); + } + + // try to use the key and see... + tester.testWrap(&nullCred, "ACCEPTING NULL CREDENTIAL"); + AutoCredentials cred(alloc); + cred += TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD, + new(alloc) ListElement(StringData("wrongo"))); + tester.testWrap(&cred, "ACCEPTING WRONG PASSWORD CREDENTIAL"); + cred += TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD, + new(alloc) ListElement(initialAclPassphrase)); + tester.testWrap(&cred); + + tester.testEncrypt(&nullCred, "ACCEPTING NULL CREDENTIAL FOR UNAUTHORIZED OPERATION"); + tester.testEncrypt(&cred, "ACCEPTING GOOD CREDENTIAL FOR UNAUTHORIZED OPERATION"); + + // now *add* a new ACL entry for encryption + { + detail("Adding new ACL entry"); + + AclEntryPrototype newAcl; + newAcl.TypedSubject = TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD, + new(alloc) ListElement(the2ndAclPassword)); + newAcl.authorization().NumberOfAuthTags = 1; + newAcl.authorization().AuthTags = &encryptTag; + AclEntryInput newInput(newAcl); + AclEdit edit(newInput); + + try { + AutoCredentials nullCred(alloc); + ss.changeKeyAcl(tester.keyRef, nullCred, edit); + error("ALLOWED ACL EDIT WITHOUT CREDENTIALS"); + } catch (CssmCommonError &err) { + detail(err, "Acl Edit rejected properly"); + } + ss.changeKeyAcl(tester.keyRef, cred, edit); + detail("ACL changed OK"); + + // read it back and check + { + uint32 count; + AclEntryInfo *acls; + ss.getKeyAcl(tester.keyRef, NULL/*tag*/, count, acls); + assert(count == 2); + const AclEntryInfo &acl1 = acls[0]; + const TypedList &subject1 = acl1.proto().subject(); + assert(subject1.type() == CSSM_ACL_SUBJECT_TYPE_PASSWORD); + assert(subject1.length() == 1); + const AuthorizationGroup &auths1 = acl1.proto().authorization(); + assert(auths1.count() == 1); + assert(auths1[0] == CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR); + const AclEntryInfo &acl2 = acls[1]; + const TypedList &subject2 = acl2.proto().subject(); + assert(subject2.type() == CSSM_ACL_SUBJECT_TYPE_PASSWORD); + assert(subject2.length() == 1); + const AuthorizationGroup &auths2 = acl2.proto().authorization(); + assert(auths2.count() == 1); + assert(auths2[0] == CSSM_ACL_AUTHORIZATION_ENCRYPT); + } + } + + // ... and see how the new composite ACL behaves + AutoCredentials cred2(alloc); + cred2 += TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD, + new(alloc) ListElement(the2ndAclPassword)); + tester.testWrap(&nullCred, "ACCEPTING NULL CREDENTIALS FOR WRAPPING"); + tester.testEncrypt(&nullCred, "ACCEPTING NULL CREDENTIALS FOR ENCRYPTION"); + tester.testWrap(&cred); // "very secret" allows wrapping + tester.testEncrypt(&cred2); // "most secret" allows encrypting + tester.testWrap(&cred2, "ACCEPTING ENCRYPT CRED FOR WRAPPING"); + tester.testEncrypt(&cred, "ACCEPTING WRAP CRED FOR ENCRYPTING"); +} + + +// +// Keychain ACL subjects +// +void keychainAcls() +{ + printf("* Keychain (interactive) ACL test\n"); + CssmAllocator &alloc = CssmAllocator::standard(); + ClientSession ss(alloc, alloc); + + // create key with initial ACL + AclEntryPrototype initialAcl; + initialAcl.TypedSubject = TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT, + new(alloc) ListElement(alloc, "Test Key")); + AclEntryInput initialAclInput(initialAcl); + AclTester tester(ss, &initialAclInput); + + // get the owner and verify + AclOwnerPrototype owner; + ss.getKeyOwner(tester.keyRef, owner); + assert(owner.subject().type() == CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT); + assert(owner.subject().length() == 2); + + // get the acl entry and verify + { + uint32 count; + AclEntryInfo *acls; + ss.getKeyAcl(tester.keyRef, NULL/*tag*/, count, acls); + assert(count == 1); + const AclEntryInfo &acl1 = acls[0]; + const TypedList &subject1 = acl1.proto().subject(); + assert(subject1.type() == CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT); + assert(subject1.length() == 2); + assert(static_cast(subject1[1]) == "Test Key"); + } + + // try to use the key and see... + tester.testWrap(NULL, "ACCEPTING NULL CREDENTIAL"); + AutoCredentials cred(alloc); + cred += TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD, + new(alloc) ListElement(StringData("Test Key"))); + tester.testWrap(&cred, "ACCEPTING PASSWORD CREDENTIAL"); + cred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT); + tester.testWrap(&cred); + // once again, for allow-this-pid feature testing + tester.testWrap(&cred); +} + + +// +// Code-signing ACL subjects +// +void codeSigning() +{ + printf("* Code Signing ACL test\n"); + CssmAllocator &alloc = CssmAllocator::standard(); + ClientSession ss(alloc, alloc); + + // sign ourselves + OSXSigner signer; + OSXCode *main = OSXCode::main(); + Signature *mySignature = signer.sign(*main); + detail("Code signature for testclient obtained"); + + // make a variant signature that isn't right + Signature *badSignature; + { + char buffer[512]; + assert(mySignature->length() <= sizeof(buffer)); + memcpy(buffer, mySignature->data(), mySignature->length()); + memcpy(buffer, "xyz!", 4); // 1 in 2^32 this is right... + badSignature = signer.restore(mySignature->type(), buffer, mySignature->length()); + } + + // create key with good code signature ACL + AclEntryPrototype initialAcl; + initialAcl.subject() = TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE, + new(alloc) ListElement(mySignature->type()), + new(alloc) ListElement(alloc.alloc(*mySignature))); + AclEntryInput initialAclInput(initialAcl); + AclTester tester(ss, &initialAclInput); + + // get the owner and verify + AclOwnerPrototype owner; + ss.getKeyOwner(tester.keyRef, owner); + assert(owner.subject().type() == CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE); + assert(owner.subject().length() == 3); + + // we are us, so the SecurityServer should accept us + tester.testWrap(&nullCred); + + // now try this again with a *bad* signature... + AclEntryPrototype badAcl; + badAcl.TypedSubject = TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE, + new(alloc) ListElement(badSignature->type()), + new(alloc) ListElement(alloc.alloc(*badSignature))); + AclEntryInput badAclInput(badAcl); + AclTester badTester(ss, &badAclInput); + badTester.testWrap(&nullCred, "BAD CODE SIGNATURE ACCEPTED"); + + // make sure the optional comment field makes it back out intact + // (reusing original initialAcl structures) + StringData comment("Walla Walla Washington!\nAbra cadabra.\n\n"); + initialAcl.subject() += new(alloc) ListElement(alloc, comment); + AclEntryInput initialAclInputWithComment(initialAcl); + AclTester commentTester(ss, &initialAclInputWithComment); + ss.getKeyOwner(commentTester.keyRef, owner); + assert(owner.subject().type() == CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE); + assert(owner.subject().length() == 4); + assert(owner.subject()[3] == comment); + detail("Verified comment field intact"); +} diff --git a/securityd/tests/testauth.cpp b/securityd/tests/testauth.cpp new file mode 100644 index 00000000..2e8e893e --- /dev/null +++ b/securityd/tests/testauth.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2000-2001,2003-2004 Apple Computer, 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@ + */ + + +// +// testacls - ACL-related test cases. +// +#include "testclient.h" +#include "testutils.h" +#include + +using namespace CodeSigning; + + +// +// Authorization test. +// This tests the authorization API support. +// @@@ Incomplete and not satisfactory. +// +void authorizations() +{ + printf("* authorization test\n"); + ClientSession ss(CssmAllocator::standard(), CssmAllocator::standard()); + + // make a simple authorization query + AuthorizationBlob auth; + AuthorizationItem testingItem = { "debug.testing", 0, NULL, NULL }; + AuthorizationItem testingMoreItem = { "debug.testing.more", 0, NULL, NULL }; + AuthorizationItem denyItem = { "debug.deny", 0, NULL, NULL }; + AuthorizationItemSet request = { 1, &testingItem }; + ss.authCreate(&request, NULL/*environment*/, + kAuthorizationFlagInteractionAllowed | + kAuthorizationFlagExtendRights | + kAuthorizationFlagPartialRights, + auth); + detail("Initial authorization obtained"); + + // ask for rights from this authorization + { + AuthorizationItem moreItems[3] = { testingItem, denyItem, testingMoreItem }; + AuthorizationItemSet moreRequests = { 3, moreItems }; + AuthorizationItemSet *rightsVector; + ss.authCopyRights(auth, &moreRequests, NULL/*environment*/, + kAuthorizationFlagInteractionAllowed | + kAuthorizationFlagExtendRights | + kAuthorizationFlagPartialRights, + &rightsVector); + if (rightsVector->count != 2) + error("COPYRIGHTS RETURNED %d RIGHTS (EXPECTED 2)", int(rightsVector->count)); + // the output rights could be in either order -- be flexible + set rights; + rights.insert(rightsVector->items[0].name); + rights.insert(rightsVector->items[1].name); + assert(rights.find("debug.testing") != rights.end() && + rights.find("debug.testing.more") != rights.end()); + free(rightsVector); + detail("CopyRights okay"); + } + + // ask for the impossible + try { + AuthorizationBlob badAuth; + AuthorizationItem badItem = { "debug.deny", 0, NULL, NULL }; + AuthorizationItemSet badRequest = { 1, &badItem }; + ss.authCreate(&badRequest, NULL/*environment*/, + kAuthorizationFlagInteractionAllowed | + kAuthorizationFlagExtendRights, + auth); + error("AUTHORIZED debug.deny OPERATION"); + } catch (CssmCommonError &err) { + detail(err, "debug.deny authorization denied properly"); + } + + // externalize + AuthorizationExternalForm extForm; + ss.authExternalize(auth, extForm); + + // re-internalize + AuthorizationBlob auth2; + ss.authInternalize(extForm, auth2); + + // make sure it still works + { + AuthorizationItem moreItems[2] = { testingItem, denyItem }; + AuthorizationItemSet moreRequests = { 2, moreItems }; + AuthorizationItemSet *rightsVector; + ss.authCopyRights(auth2, &moreRequests, NULL/*environment*/, + kAuthorizationFlagInteractionAllowed | + kAuthorizationFlagExtendRights | + kAuthorizationFlagPartialRights, + &rightsVector); + if (rightsVector->count != 1) + error("COPYRIGHTS RETURNED %d RIGHTS (EXPECTED 1)", int(rightsVector->count)); + assert(!strcmp(rightsVector->items[0].name, "debug.testing")); + free(rightsVector); + detail("Re-internalized authorization checks out okay"); + + // try it with no rights output (it's optional) + ss.authCopyRights(auth2, &moreRequests, NULL/*environment*/, + kAuthorizationFlagPartialRights, NULL); + detail("authCopyRights partial success OK (with no output)"); + + // but this will fail if we want ALL rights... + try { + ss.authCopyRights(auth2, &moreRequests, NULL/*environment*/, + kAuthorizationFlagDefaults, NULL); + error("authCopyRights succeeded with (only) partial success"); + } catch (CssmError &err) { + detail("authCopyRight failed for (only) partial success"); + } + } +} diff --git a/securityd/tests/testblobs.cpp b/securityd/tests/testblobs.cpp new file mode 100644 index 00000000..c8c425ee --- /dev/null +++ b/securityd/tests/testblobs.cpp @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2000-2001,2003-2004 Apple Computer, 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@ + */ + + +// +// testacls - ACL-related test cases. +// +#include "testclient.h" +#include "testutils.h" + + +// +// Blob tests. +// Encodes and decodes Db and Key blobs and all that jazz. +// +void blobs() +{ + printf("* Database blob encryption test\n"); + ClientSession ss(CssmAllocator::standard(), CssmAllocator::standard()); + + DbTester db1(ss, "/tmp/one", NULL, 60, true); + DbTester db2(ss, "/tmp/two", NULL, 30, false); + + // encode db1, purge it, decode it again + CssmData dbBlob; + ss.encodeDb(db1, dbBlob); + DbHandle db1a = ss.decodeDb(db1.dbId, &nullCred, dbBlob); + ss.releaseDb(db1); + if (db1 == db1a) + detail("REUSED DB HANDLE ON DECODEDB (probably wrong)"); + DBParameters savedParams; + ss.getDbParameters(db1a, savedParams); + assert(savedParams.idleTimeout == db1.params.idleTimeout); + assert(savedParams.lockOnSleep == db1.params.lockOnSleep); + detail("Database encode/decode passed"); + + // make sure the old handle isn't valid anymore + try { + ss.getDbParameters(db1, savedParams); + printf("OLD DATABASE HANDLE NOT PURGED (possibly wrong)\n"); + } catch (const CssmCommonError &err) { + detail(err, "old DB handle rejected"); + } + + // open db1 a second time (so now there's two db handles for db1) + DbHandle db1b = ss.decodeDb(db1.dbId, &nullCred, dbBlob); + + // release both db1 handles and db2 + ss.releaseDb(db1a); + ss.releaseDb(db1b); + ss.releaseDb(db2); +} + + +// +// Database tests. +// Database locks/unlocks etc. +// +void databases() +{ + printf("* Database manipulation test\n"); + CssmAllocator &alloc = CssmAllocator::standard(); + ClientSession ss(alloc, alloc); + + AutoCredentials pwCred(alloc); + StringData passphrase("two"); + StringData badPassphrase("three"); + pwCred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK, + new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), + new(alloc) ListElement(passphrase)); + pwCred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, + new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), + new(alloc) ListElement(badPassphrase)); + // pwCred = (NEW: two, OLD: three) + + DbTester db1(ss, "/tmp/one", NULL, 30, true); + DbTester db2(ss, "/tmp/two", &pwCred, 60, false); + // db2.passphrase = two + + // encode db1 and re-open it + CssmData dbBlob; + ss.encodeDb(db1, dbBlob); + DbHandle db1b = ss.decodeDb(db1.dbId, &nullCred, dbBlob); + if (db1b == db1.dbRef) + detail("REUSED DB HANDLE ON DECODEDB (probably wrong)"); + + // open db1 a third time (so now there's three db handles for db1) + DbHandle db1c = ss.decodeDb(db1.dbId, &nullCred, dbBlob); + + // lock them to get started + ss.lock(db1); + ss.lock(db2); + + // unlock it through user + prompt("unlock"); + ss.unlock(db1); + prompt(); + ss.unlock(db1b); // 2nd unlock should not prompt + ss.lock(db1c); // lock it again + prompt("unlock"); + ss.unlock(db1); // and that should prompt again + prompt(); + + // db2 has a passphrase lock credentials - it'll work without U/I + db2.unlock("wrong passphrase"); // pw=two, cred=three + AutoCredentials pwCred2(alloc); + pwCred2 += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, + new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), + new(alloc) ListElement(passphrase)); + // pwCred2 = (OLD: two) + ss.authenticateDb(db2, CSSM_DB_ACCESS_WRITE, &pwCred2); // set it + db2.unlock(); + ss.lock(db2); + + // now change db2's passphrase + ss.lock(db2); + pwCred2 += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK, + new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), + new(alloc) ListElement(badPassphrase)); + // pwCred2 = (OLD: two, NEW: three) + db2.changePassphrase(&pwCred2); + // passphrase = three, cred = (OLD: two) + + // encode and re-decode to make sure new data is there + CssmData blob2; + ss.encodeDb(db2, blob2); + DbHandle db2a = ss.decodeDb(db2.dbId, &pwCred, blob2); + // db2a cred = (OLD: two, NEW: three) + + // now, the *old* cred won't work anymore + db2.unlock("old passphrase accepted"); + + // back to the old credentials, which *do* have the (old bad, now good) passphrase + ss.lock(db2a); + ss.unlock(db2a); + detail("New passphrase accepted"); + + // clear the credentials (this will prompt; cancel it) + ss.authenticateDb(db2, CSSM_DB_ACCESS_WRITE, NULL); + prompt("cancel"); + db2.unlock("null credential accepted"); + prompt(); + + // fell-swoop from-to change password operation + StringData newPassphrase("hollerith"); + AutoCredentials pwCred3(alloc); + pwCred3 += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK, + new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), + new(alloc) ListElement(newPassphrase)); + pwCred3 += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, + new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), + new(alloc) ListElement(passphrase)); + db2.changePassphrase(&pwCred3, "accepting original (unchanged) passphrase"); + + AutoCredentials pwCred4(alloc); + pwCred4 += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK, + new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), + new(alloc) ListElement(newPassphrase)); + pwCred4 += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, + new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), + new(alloc) ListElement(badPassphrase)); + db2.changePassphrase(&pwCred4); + + // final status check + AutoCredentials pwCred5(alloc); + pwCred5 += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, + new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), + new(alloc) ListElement(newPassphrase)); + ss.authenticateDb(db2, CSSM_DB_ACCESS_WRITE, &pwCred5); + db2.unlock(); + detail("Final passphrase change verified"); +} + + +// +// Key encryption tests. +// +void keyBlobs() +{ + printf("* Keyblob encryption test\n"); + CssmAllocator &alloc = CssmAllocator::standard(); + ClientSession ss(alloc, alloc); + + DLDbIdentifier dbId1(ssuid, "/tmp/one", NULL); + DBParameters initialParams1 = { 3600, false }; + + // create a new database + DbHandle db = ss.createDb(dbId1, NULL, NULL, initialParams1); + detail("Database created"); + + // establish an ACL for the key + StringData theAclPassword("Strenge Geheimsache"); + AclEntryPrototype initialAcl; + initialAcl.TypedSubject = TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD, + new(alloc) ListElement(theAclPassword)); + AclEntryInput initialAclInput(initialAcl); + + AutoCredentials cred(alloc); + cred += TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD, + new(alloc) ListElement(theAclPassword)); + + // generate a key + const CssmCryptoData seed(StringData("Farmers' day")); + FakeContext genContext(CSSM_ALGCLASS_KEYGEN, CSSM_ALGID_DES, + &::Context::Attr(CSSM_ATTRIBUTE_KEY_LENGTH, 64), + &::Context::Attr(CSSM_ATTRIBUTE_SEED, seed), + NULL); + KeyHandle key; + CssmKey::Header header; + ss.generateKey(db, genContext, CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT, + /*cred*/NULL, &initialAclInput, key, header); + detail("Key generated"); + + // encrypt with the key + StringData clearText("Yet another boring cleartext sample string text sequence."); + StringData iv("Aardvark"); + CssmKey nullKey; memset(&nullKey, 0, sizeof(nullKey)); + FakeContext cryptoContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_DES, + &::Context::Attr(CSSM_ATTRIBUTE_KEY, nullKey), + &::Context::Attr(CSSM_ATTRIBUTE_INIT_VECTOR, iv), + &::Context::Attr(CSSM_ATTRIBUTE_MODE, CSSM_ALGMODE_CBC_IV8), + &::Context::Attr(CSSM_ATTRIBUTE_PADDING, CSSM_PADDING_PKCS1), + &::Context::Attr(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, cred), + NULL); + CssmData cipherText; + ss.encrypt(cryptoContext, key, clearText, cipherText); + detail("Plaintext encrypted with original key"); + + // encode the key and release it + CssmData blob; + ss.encodeKey(key, blob); + ss.releaseKey(key); + detail("Key encoded and released"); + + // decode it again, re-introducing it + CssmKey::Header decodedHeader; + KeyHandle key2 = ss.decodeKey(db, blob, decodedHeader); + detail("Key decoded"); + + // decrypt with decoded key + CssmData recovered; + ss.decrypt(cryptoContext, key2, cipherText, recovered); + assert(recovered == clearText); + detail("Decoded key correctly decrypts ciphertext"); + + // check a few header fields + if (!memcmp(&header, &decodedHeader, sizeof(header))) { + detail("All header fields match"); + } else { + assert(header.algorithm() == decodedHeader.algorithm()); + assert(header.blobType() == decodedHeader.blobType()); + assert(header.blobFormat() == decodedHeader.blobFormat()); + assert(header.keyClass() == decodedHeader.keyClass()); + assert(header.attributes() == decodedHeader.attributes()); + assert(header.usage() == decodedHeader.usage()); + printf("Some header fields differ (probably okay)\n"); + } + + // make sure we need the credentials (destructive) + memset(&cred, 0, sizeof(cred)); + try { + ss.decrypt(cryptoContext, key2, cipherText, recovered); + error("RESTORED ACL FAILS TO RESTRICT"); + } catch (CssmError &err) { + detail(err, "Restored key restricts access properly"); + } +} diff --git a/securityd/tests/testclient.cpp b/securityd/tests/testclient.cpp new file mode 100644 index 00000000..81648543 --- /dev/null +++ b/securityd/tests/testclient.cpp @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2000-2001,2003-2004 Apple Computer, 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@ + */ + + +// +// Tester - test driver for securityserver client side. +// +#include "testclient.h" +#include "testutils.h" +#include // getopt(3) +#include + + +// +// Global constants +// +const CssmData null; // zero pointer, zero length constant data +const AccessCredentials nullCred; // null credentials + +CSSM_GUID ssguid = { 1,2,3 }; +CssmSubserviceUid ssuid(ssguid); + + +// +// Local functions +// +static void usage(); +static void runtest(char type); + + +// +// Default test set +// +static char testCodes[] = ".cesaAbdkKt"; + + +// +// Main program +// +int main(int argc, char *argv[]) +{ + setbuf(stdout, NULL); + + long ranseq = 0; // random stress test count + long ranseed = 1; // random seed for it + + int arg; + while ((arg = getopt(argc, argv, "r:v")) != -1) { + switch (arg) { + case 'r': { + ranseq = atoi(optarg); + if (const char *colon = strchr(optarg, ':')) + ranseed = atoi(colon + 1); + else + ranseed = getpid() ^ time(NULL); + break; + } + case 'v': + verbose = true; + break; + default: + usage(); + } + } + if (optind < argc - 1) + usage(); + const char *sequence = argv[optind]; + if (sequence && !strcmp(sequence, "+")) + sequence = testCodes; + + if (ranseq) { // repeated random (stress test) sequence + if (!sequence) + sequence = testCodes; + printf("*** Random stress test: %ld iterations from <%s> with seed=%ld\n", + ranseq, sequence, ranseed); + srandom(ranseed); + int setSize = strlen(sequence); + for (long n = 0; n < ranseq; n++) { + char type = sequence[random() % setSize]; + printf("\n[%ld:%c]", n, type); + runtest(type); + } + printf("*** Random test sequence complete.\n"); + exit(0); + } else { // single-pass selected tests sequence + if (!sequence) + sequence = "."; // default to ping test + for (const char *s = sequence; *s; s++) + runtest(*s); + printf("*** Test sequence complete.\n"); + exit(0); + } +} + +void usage() +{ + fprintf(stderr, "Usage: SSTester [-r count[:seed]] [-v] [%s|.|+]\n", + testCodes); + exit(2); +} + + +// +// Run a single type test +// +void runtest(char type) +{ + try { + debug("SStest", "Start test <%c>", type); + switch (type) { + case '.': // default + integrity(); + break; + case '-': + adhoc(); + break; + case 'a': + acls(); + break; + case 'A': + authAcls(); + break; + case 'b': + blobs(); + break; + case 'c': + codeSigning(); + break; + case 'd': + databases(); + break; + case 'e': + desEncryption(); + break; + case 'k': + keychainAcls(); + break; + case 'K': + keyBlobs(); + break; + case 's': + signWithRSA(); + break; + case 't': + authorizations(); + break; + case 'T': + timeouts(); + break; + default: + error("Invalid test selection (%c)", type); + } + printf("** Test step complete.\n"); + debug("SStest", "End test <%c>", type); + } catch (CssmCommonError &err) { + error(err, "Unexpected exception"); + } catch (...) { + error("Unexpected system exception"); + } +} + + +// +// Basic integrity test. +// +void integrity() +{ + ClientSession ss(CssmAllocator::standard(), CssmAllocator::standard()); + + printf("* Generating random sample: "); + DataBuffer<11> sample; + ss.generateRandom(sample); + for (uint32 n = 0; n < sample.length(); n++) + printf("%.2x", ((unsigned char *)sample)[n]); + printf("\n"); +} + + +// +// Database timeouts +// @@@ Incomplete and not satisfactory +// +void timeouts() +{ + printf("* Database timeout locks test\n"); + CssmAllocator &alloc = CssmAllocator::standard(); + ClientSession ss(alloc, alloc); + + DLDbIdentifier dbId1(ssuid, "/tmp/one", NULL); + DLDbIdentifier dbId2(ssuid, "/tmp/two", NULL); + DBParameters initialParams1 = { 4, false }; // 4 seconds timeout + DBParameters initialParams2 = { 8, false }; // 8 seconds timeout + + // credential to set keychain passphrase + AutoCredentials pwCred(alloc); + StringData password("mumbojumbo"); + pwCred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK, + new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), + new(alloc) ListElement(password)); + + DbHandle db1 = ss.createDb(dbId1, &pwCred, NULL, initialParams1); + DbHandle db2 = ss.createDb(dbId2, &pwCred, NULL, initialParams2); + detail("Databases created"); + + // generate a key + const CssmCryptoData seed(StringData("rain tonight")); + FakeContext genContext(CSSM_ALGCLASS_KEYGEN, CSSM_ALGID_DES, + &::Context::Attr(CSSM_ATTRIBUTE_KEY_LENGTH, 64), + &::Context::Attr(CSSM_ATTRIBUTE_SEED, seed), + NULL); + KeyHandle key; + CssmKey::Header header; + ss.generateKey(db1, genContext, CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT, + /*cred*/NULL, NULL, key, header); + ss.generateKey(db2, genContext, CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT, + /*cred*/NULL, NULL, key, header); + detail("Keys generated and stored"); + + // credential to provide keychain passphrase + AutoCredentials pwCred2(alloc); + pwCred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, + new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), + new(alloc) ListElement(password)); + + //@@@ incomplete + ss.releaseDb(db1); + ss.releaseDb(db2); +} + + +// +// Ad-hoc test area. +// Used for whatever is needed at the moment... +// +void adhoc() +{ + printf("* Ad-hoc test sequence (now what does it do *this* time?)\n"); + + Cssm cssm1; + Cssm cssm2; + cssm1->init(); + cssm2->init(); + + { + Module m1(gGuidAppleCSP, cssm1); + Module m2(gGuidAppleCSP, cssm2); + CSP r1(m1); + CSP r2(m2); + + Digest d1(r1, CSSM_ALGID_SHA1); + Digest d2(r2, CSSM_ALGID_SHA1); + + StringData foo("foo de doo da blech"); + DataBuffer<30> digest1, digest2; + d1.digest(foo, digest1); + d2.digest(foo, digest2); + if (digest1 == digest2) + detail("Digests verify"); + else + error("Digests mismatch"); + } + + cssm1->terminate(); + cssm2->terminate(); +} diff --git a/securityd/tests/testclient.h b/securityd/tests/testclient.h new file mode 100644 index 00000000..c488cf55 --- /dev/null +++ b/securityd/tests/testclient.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2000-2001,2003-2004 Apple Computer, 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@ + */ + + +// +// Tester - test driver for securityserver client side. +// +#ifndef _H_TESTCLIENT +#define _H_TESTCLIENT + +#include "ssclient.h" +#include +#include +#include +#include +#include +#include + + +// +// Names from the SecurityServerSession class +// +using namespace SecurityServer; +using namespace CssmClient; + + +// +// Test drivers +// +void integrity(); +void signWithRSA(); +void desEncryption(); +void blobs(); +void keyBlobs(); +void databases(); +void timeouts(); +void acls(); +void authAcls(); +void codeSigning(); +void keychainAcls(); +void authorizations(); +void adhoc(); + + +// +// Global constants +// +extern const CssmData null; // zero pointer, zero length constant data +extern const AccessCredentials nullCred; // null credentials + +extern CSSM_GUID ssguid; // a fixed guid +extern CssmSubserviceUid ssuid; // a subservice-uid using this guid + + +#endif //_H_TESTCLIENT diff --git a/securityd/tests/testcrypto.cpp b/securityd/tests/testcrypto.cpp new file mode 100644 index 00000000..f6201106 --- /dev/null +++ b/securityd/tests/testcrypto.cpp @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2000-2001,2003-2004 Apple Computer, 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@ + */ + + +// +// Tester - test driver for securityserver client side. +// +#include "testclient.h" +#include "testutils.h" + + +// +// Simple run-through. +// This generates an RSA key, tests cleartext retrieval, signs a message, +// and veries it both ways. +// This is a basic integrity regression for the SecurityServer. +// +void signWithRSA() +{ + printf("* RSA key signing test\n"); + CSP csp(gGuidAppleCSP); + ClientSession ss(CssmAllocator::standard(), CssmAllocator::standard()); + StringData data("To sign or not to sign, is that the question?"); + + // set up dummy credentials + CssmKey dummyKey; memset(&dummyKey, 0, sizeof(dummyKey)); + CssmData nullData; + + // generate a key + detail("Asking for RSA key generation"); + KeyHandle publicKey, privateKey; + const CssmCryptoData seed(StringData("Seed ye well, my friend, and ye shall reap...")); + FakeContext genContext(CSSM_ALGCLASS_KEYGEN, CSSM_ALGID_RSA, + &::Context::Attr(CSSM_ATTRIBUTE_KEY_LENGTH, 512), + &::Context::Attr(CSSM_ATTRIBUTE_SEED, seed), + NULL); + CssmKey::Header pubHeader, privHeader; + ss.generateKey(noDb, genContext, + CSSM_KEYUSE_VERIFY, CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_DATA, + CSSM_KEYUSE_SIGN, CSSM_KEYATTR_SENSITIVE, + NULL/*cred*/, NULL/*owner*/, publicKey, pubHeader, privateKey, privHeader); + detail("Key pair generated"); + + // retrieve the public key + CssmKey cpk; + FakeContext wrapContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_NONE, 0); + ss.wrapKey(wrapContext, noKey, publicKey, &nullCred, NULL, cpk); + Key clearPublicKey(csp, cpk); + detail("Retrieved public key"); + + // make sure we can't retrieve the private key + CssmKey clearPrivateKey; + try { + ss.wrapKey(wrapContext, noKey, privateKey, NULL/*cred*/, NULL, clearPrivateKey); + error("SecurityServer ACTUALLY gave us the PRIVATE key bits!"); + } catch (CssmError &err) { + detail(err, "Private key retrieval properly rejected"); + } + + // sign a message + CssmData signature; + FakeContext signContext(CSSM_ALGCLASS_SIGNATURE, CSSM_ALGID_SHA1WithRSA, + &::Context::Attr(CSSM_ATTRIBUTE_KEY, dummyKey), + NULL); + ss.generateSignature(signContext, privateKey, data, signature); + detail("Signature generated by SecurityServer"); + + // verify the signature (local) + { + Verify verifier(csp, CSSM_ALGID_SHA1WithRSA); + verifier.key(clearPublicKey); + verifier.verify(data, signature); + detail("Signature verified locally"); + } + + // verify the signature (SS) + ss.verifySignature(signContext, publicKey, data, signature); + detail("Signature verified by SecurityServer"); + + // falsify the signature (SS) + DataBuffer<200> falseData; + memcpy(falseData.data(), data.data(), data.length()); + falseData.length(data.length()); + ((char *)falseData)[3] = '?'; // alter message + try { + ss.verifySignature(signContext, publicKey, falseData, signature); + error("Altered message incorrectly verifies"); + } catch (CssmError &err) { + if (err.cssmError() == CSSMERR_CSP_VERIFY_FAILED) + detail("Verify of altered message successfully failed"); + else + error(err, "Unexpected exception on verify failure test"); + } +} + + +// +// Encrypt with DES +// +void desEncryption() +{ + printf("* DES encryption test\n"); + ClientSession ss(CssmAllocator::standard(), CssmAllocator::standard()); + CSP csp(gGuidAppleCSP); + + StringData clearText("Insert witty quotation here."); + StringData iv("abcdefgh"); + + // make up a DES key + StringData keyBits(strdup("Wallaby!")); + CssmKey keyForm(keyBits); + keyForm.header().KeyClass = CSSM_KEYCLASS_SESSION_KEY; + keyForm.header().BlobType = CSSM_KEYBLOB_RAW; + keyForm.header().AlgorithmId = CSSM_ALGID_DES; + keyForm.header().Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; + Key key(csp, keyForm); + + // encrypt locally + DataBuffer<200> localCipher; + Encrypt localCrypt(csp, CSSM_ALGID_DES); + localCrypt.mode(CSSM_ALGMODE_CBC_IV8); + localCrypt.padding(CSSM_PADDING_PKCS1); + localCrypt.initVector(iv); + localCrypt.key(key); + CssmData remData; + size_t localLen = localCrypt.encrypt(clearText, localCipher, remData); + if (remData) + error("LOCAL ENCRYPTION OVERFLOWED"); + localCipher.length(localLen); + detail("Locally encrypted %ld bytes", localLen); + + // wrap in the key + CssmData unwrappedData; + ResourceControlContext owner; + FakeContext unwrapContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_NONE, 0); + KeyHandle keyRef; + CssmKey::Header keyHeader; + ss.unwrapKey(noDb, unwrapContext, noKey, noKey, + key, + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + CSSM_KEYATTR_RETURN_DEFAULT, + NULL/*cred*/, NULL/*owner*/, unwrappedData, keyRef, keyHeader); + detail("Placed key into SecurityServer; handle=%lx", keyRef); + + // encrypt remotely and compare + const CssmKey &tKey = key; + FakeContext cryptoContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_DES, + &::Context::Attr(CSSM_ATTRIBUTE_KEY, keyForm), + &::Context::Attr(CSSM_ATTRIBUTE_INIT_VECTOR, iv), + &::Context::Attr(CSSM_ATTRIBUTE_MODE, CSSM_ALGMODE_CBC_IV8), + &::Context::Attr(CSSM_ATTRIBUTE_PADDING, CSSM_PADDING_PKCS1), + NULL); + CssmData remoteCipher; + ss.encrypt(cryptoContext, keyRef, clearText, remoteCipher); + detail("Plaintext encrypted on SecurityServer"); + if (remoteCipher == localCipher) + detail("Ciphertexts verified"); + else + error("CIPHERTEXTS DIFFER"); + + // decrypt in SecurityServer + DataBuffer<200> clearRecovered; + ss.decrypt(cryptoContext, keyRef, localCipher, clearRecovered); + detail("Decrypted ciphertext in SecurityServer"); + if (clearRecovered == clearText) + detail("Plaintext recovered"); + else + error("PLAINTEXT MISMATCH"); +} + diff --git a/securityd/tests/testutils.cpp b/securityd/tests/testutils.cpp new file mode 100644 index 00000000..32f172f9 --- /dev/null +++ b/securityd/tests/testutils.cpp @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2000-2001,2003-2004 Apple Computer, 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@ + */ + + +// +// testutils - utilities for unit test drivers +// +#include "testutils.h" + +using namespace CssmClient; + +bool verbose = false; + + +// +// Error and diagnostic drivers +// +void error(const char *msg = NULL, ...) +{ + if (msg) { + va_list args; + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); + putc('\n', stderr); + } + abort(); +} + +void error(const CssmCommonError &err, const char *msg = NULL, ...) +{ + if (msg) { + va_list args; + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); + fprintf(stderr, ": %s", cssmErrorString(err.cssmError()).c_str()); + putc('\n', stderr); + } + abort(); +} + +void detail(const char *msg = NULL, ...) +{ + if (verbose) { + va_list args; + va_start(args, msg); + vfprintf(stdout, msg, args); + va_end(args); + putc('\n', stdout); + } +} + +void detail(const CssmCommonError &err, const char *msg) +{ + if (verbose) + printf("%s (ok): %s\n", msg, cssmErrorString(err).c_str()); +} + +void prompt(const char *msg) +{ + if (isatty(fileno(stdin))) + printf("[%s]", msg); +} + +void prompt() +{ + if (isatty(fileno(stdin))) + printf(" OK\n"); +} + + +// +// FakeContext management +// +FakeContext::FakeContext(CSSM_CONTEXT_TYPE type, CSSM_ALGORITHMS alg, uint32 count) +: Context(type, alg) +{ + NumberOfAttributes = count; + ContextAttributes = new Attr[count]; +} + + +FakeContext::FakeContext(CSSM_CONTEXT_TYPE type, CSSM_ALGORITHMS alg, ...) +: Context(type, alg) +{ + // count arguments + va_list args; + va_start(args, alg); + uint32 count = 0; + while (va_arg(args, Attr *)) + count++; + va_end(args); + + // make vector + NumberOfAttributes = count; + ContextAttributes = new Attr[count]; + + // stuff vector + va_start(args, alg); + for (uint32 n = 0; n < count; n++) + (*this)[n] = *va_arg(args, Attr *); + va_end(args); +} + + +// +// ACL test driver class +// +AclTester::AclTester(ClientSession &ss, const AclEntryInput *acl) : session(ss) +{ + // make up a DES key + StringData keyBits("Tweedle!"); + CssmKey key(keyBits); + key.header().KeyClass = CSSM_KEYCLASS_SESSION_KEY; + + // wrap in the key + CssmData unwrappedData; + FakeContext unwrapContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_NONE, 0); + CssmKey::Header keyHeader; + ss.unwrapKey(noDb, unwrapContext, noKey, noKey, + key, + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + CSSM_KEYATTR_EXTRACTABLE, + NULL /*cred*/, acl, + unwrappedData, keyRef, keyHeader); + detail("Key seeded with ACL"); +} + + +void AclTester::testWrap(const AccessCredentials *cred, const char *howWrong) +{ + FakeContext wrapContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_NONE, 0); + CssmWrappedKey wrappedKey; + try { + session.wrapKey(wrapContext, noKey, keyRef, + cred, NULL /*descriptive*/, wrappedKey); + if (howWrong) { + error("WRAP MISTAKENLY SUCCEEDED: %s", howWrong); + } + detail("extract OK"); + } catch (const CssmCommonError &err) { + if (!howWrong) + error(err, "FAILED TO EXTRACT KEY"); + detail(err, "extract failed OK"); + } +} + +void AclTester::testEncrypt(const AccessCredentials *cred, const char *howWrong) +{ + CssmKey keyForm; memset(&keyForm, 0, sizeof(keyForm)); + StringData iv("Aardvark"); + StringData clearText("blah"); + CssmData remoteCipher; + try { + if (cred) { + FakeContext cryptoContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_DES, + &::Context::Attr(CSSM_ATTRIBUTE_KEY, keyForm), + &::Context::Attr(CSSM_ATTRIBUTE_INIT_VECTOR, iv), + &::Context::Attr(CSSM_ATTRIBUTE_MODE, CSSM_ALGMODE_CBC_IV8), + &::Context::Attr(CSSM_ATTRIBUTE_PADDING, CSSM_PADDING_PKCS1), + &::Context::Attr(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, *cred), + NULL); + session.encrypt(cryptoContext, keyRef, clearText, remoteCipher); + } else { + FakeContext cryptoContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_DES, + &::Context::Attr(CSSM_ATTRIBUTE_KEY, keyForm), + &::Context::Attr(CSSM_ATTRIBUTE_INIT_VECTOR, iv), + &::Context::Attr(CSSM_ATTRIBUTE_MODE, CSSM_ALGMODE_CBC_IV8), + &::Context::Attr(CSSM_ATTRIBUTE_PADDING, CSSM_PADDING_PKCS1), + NULL); + session.encrypt(cryptoContext, keyRef, clearText, remoteCipher); + } + if (howWrong) { + error("ENCRYPT MISTAKENLY SUCCEEDED: %s", howWrong); + } + detail("encrypt OK"); + } catch (CssmCommonError &err) { + if (!howWrong) + error(err, "FAILED TO ENCRYPT"); + detail(err, "encrypt failed"); + } +} + + +// +// Database test driver class +// +DbTester::DbTester(ClientSession &ss, const char *path, + const AccessCredentials *cred, int timeout, bool sleepLock) +: session(ss), dbId(ssuid, path, NULL) +{ + params.idleTimeout = timeout; + params.lockOnSleep = sleepLock; + dbRef = ss.createDb(dbId, cred, NULL, params); + detail("Database %s created", path); +} + + +void DbTester::unlock(const char *howWrong) +{ + session.lock(dbRef); + try { + session.unlock(dbRef); + if (howWrong) + error("DATABASE MISTAKENLY UNLOCKED: %s", howWrong); + } catch (CssmError &err) { + if (!howWrong) + error(err, howWrong); + detail(err, howWrong); + } +} + +void DbTester::changePassphrase(const AccessCredentials *cred, const char *howWrong) +{ + session.lock(dbRef); + try { + session.changePassphrase(dbRef, cred); + if (howWrong) + error("PASSPHRASE CHANGE MISTAKENLY SUCCEEDED: %s", howWrong); + } catch (CssmError &err) { + if (!howWrong) + error(err, howWrong); + detail(err, howWrong); + } +} diff --git a/securityd/tests/testutils.h b/securityd/tests/testutils.h new file mode 100644 index 00000000..adea5aec --- /dev/null +++ b/securityd/tests/testutils.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2000-2001,2003-2004 Apple Computer, 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@ + */ + + +// +// testutils - utilities for unit test drivers +// +#ifndef _H_TESTUTILS +#define _H_TESTUTILS + +#include "testclient.h" + + +// +// Global test state +// +extern bool verbose; + + +// +// Error and diagnostic drivers +// +void error(const char *fmt, ...) __attribute__((format(printf,1,2))); +void error(const CssmCommonError &error, const char *fmt, ...) __attribute__((format(printf,2,3))); +void detail(const char *fmt, ...) __attribute__((format(printf,1,2))); +void detail(const CssmCommonError &error, const char *msg); +void prompt(const char *msg); +void prompt(); + + +// +// A self-building "fake" context. +// (Fake in that it was hand-made without involvement of CSSM.) +// +class FakeContext : public ::Context { +public: + FakeContext(CSSM_CONTEXT_TYPE type, CSSM_ALGORITHMS alg, uint32 count); + FakeContext(CSSM_CONTEXT_TYPE type, CSSM_ALGORITHMS alg, ...); +}; + + +// +// A test driver class for ACL tests +// +class AclTester { +public: + AclTester(ClientSession &ss, const AclEntryInput *acl); + + void testWrap(const AccessCredentials *cred, const char *howWrong = NULL); + void testEncrypt(const AccessCredentials *cred, const char *howWrong = NULL); + + ClientSession &session; + KeyHandle keyRef; +}; + + +// +// A test driver class for database tests +// +class DbTester { +public: + DbTester(ClientSession &ss, const char *path, + const AccessCredentials *cred, int timeout = 30, bool sleepLock = true); + + operator DbHandle () const { return dbRef; } + void unlock(const char *howWrong = NULL); + void changePassphrase(const AccessCredentials *cred, const char *howWrong = NULL); + + ClientSession &session; + DBParameters params; + DLDbIdentifier dbId; + DbHandle dbRef; +}; + + +#endif //_H_TESTUTILS diff --git a/spiralsink114.png b/spiralsink114.png new file mode 100644 index 0000000000000000000000000000000000000000..d69b283a1396dcfb3ea4e04cfe543013db7c12a2 GIT binary patch literal 24752 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 z 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 literal 0 HcmV?d00001 diff --git a/spiralsink57.png b/spiralsink57.png new file mode 100644 index 0000000000000000000000000000000000000000..ada42f210c65f4279fe750643c09d06dc9ee8f51 GIT binary patch literal 7978 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 literal 0 HcmV?d00001 diff --git a/sslViewer/SSLViewer.cpp b/sslViewer/SSLViewer.cpp new file mode 100644 index 00000000..f67d2757 --- /dev/null +++ b/sslViewer/SSLViewer.cpp @@ -0,0 +1,1627 @@ +/* + * Copyright (c) 2006-2013 Apple Inc. All Rights Reserved. + * + * SSL viewer tool, SecureTransport / Aspen version. + */ + +#include +#include // for SSLGetPeerSecTrust +#include +#include "sslAppUtils.h" +#include "ioSock.h" +#include "utilities/fileIo.h" +#include "utilities/SecCFWrappers.h" + +#include + +#include +#include +#include +#include +#include +#include +#include "SecurityTool/print_cert.h" + +#include + +#if NO_SERVER +#include +#endif + +#define DEFAULT_GETMSG "GET" +#define DEFAULT_PATH "/" +#define DEFAULT_GET_SUFFIX "HTTP/1.0\r\n\r\n" + +#define DEFAULT_HOST "www.amazon.com" +#define DEFAULT_PORT 443 + +#include + +static void usageNorm(char **argv) +{ + printf("Usage: %s [hostname|-] [path] [option ...]\n", argv[0]); + printf(" %s hostname [path] [option ...]\n", argv[0]); + printf("Specifying '-' for hostname, or no args, uses default of %s.\n", + DEFAULT_HOST); + printf("Optional path argument must start with leading '/'.\n"); + printf("Options:\n"); + printf(" e Allow Expired Certs\n"); + printf(" E Allow Expired Roots\n"); + printf(" r Allow any root cert\n"); + printf(" c Display peer certs\n"); + printf(" c c Display peer SecTrust\n"); + printf(" d Display received data\n"); + printf(" 2 SSLv2 only (default is TLSv1)\n"); + printf(" 3 SSLv3 only (default is TLSv1)\n"); + printf(" t TLSv1\n"); + printf(" %% TLSv1.1 only\n"); + printf(" ^ TLSv1.2 only\n"); + printf(" L all - TLSv1.2, TLSv1.1, TLSv1.0, SSLv3, SSLv2 (default = TLSv1.2)\n"); + printf(" g={prot...} Specify legal protocols; prot = any combo of" + " [23t]\n"); + printf(" k=keychain Contains cert and keys. Optional.\n"); + printf(" l=loopCount Perform loopCount ops (default = 1)\n"); + printf(" P=port Default = %d\n", DEFAULT_PORT); + printf(" p Pause after each loop\n"); + printf(" q Quiet/diagnostic mode (site names and errors" + " only)\n"); + printf(" a fileName Add fileName to list of trusted roots\n"); + printf(" A fileName fileName is ONLY trusted root\n"); + printf(" x Disable Cert Verification\n"); + printf(" z=password Unlock client keychain with password.\n"); + printf(" 8 Complete cert chains (default is out cert is a root)\n"); + printf(" s Silent\n"); + printf(" V Verbose\n"); + printf(" h Help\n"); + printf(" hv More, verbose help\n"); +} + +static void usageVerbose(char **argv) __attribute__((noreturn)); +static void usageVerbose(char **argv) +{ + usageNorm(argv); + printf("Obscure Usage:\n"); + printf(" u kSSLProtocolUnknown only (TLSv1)\n"); + printf(" M Manual cert verification via " + "SecTrustEvaluate\n"); + printf(" f fileBase Write Peer Certs to fileBase*\n"); + printf(" o TLSv1, SSLv3 use kSSLProtocol__X__Only\n"); + printf(" C=cipherSuite (e=40-bit d=DES D=40-bit DES 3=3DES 4=RC4 " + "$=40-bit RC4\n" + " 2=RC2 a=AES128 A=AES256 h=DH H=Anon DH r=DHE/RSA s=DH/DSS\n"); + printf(" y=keychain Encryption-only cert and keys. Optional.\n"); + printf(" K Keep connected until server disconnects\n"); + printf(" n Require closure notify message in TLSv1, " + "SSLv3 mode (implies K)\n"); + printf(" R Disable resumable session support\n"); + printf(" b Non-blocking I/O\n"); + printf(" v Verify negotiated protocol equals attempted\n"); + printf(" m=[23t] Max protocol supported as specified; implies " + "v\n"); + printf(" T=[nrsj] Verify client cert state = " + "none/requested/sent/rejected\n"); + printf(" H allow hostname spoofing\n"); + printf(" F=vfyHost Verify certs with specified host name\n"); + printf(" G=getMsg Specify entire GET, POST, etc.\n"); + printf(" N Log handshake timing\n"); + printf(" 7 Pause only after first loop\n"); + exit(1); +} + +static void usage(char **argv) __attribute__((noreturn)); +static void usage(char **argv) +{ + usageNorm(argv); + exit(1); +} + +/* + * Arguments to top-level sslPing() + */ +typedef struct { + SSLProtocol tryVersion; // only used if acceptedProts NULL + // uses SSLSetProtocolVersion + char *acceptedProts; // optional, any combo of {2,3,t} + // uses SSLSetProtocolVersionEnabled + const char *hostName; // e.g., "www.amazon.com" + const char *vfyHostName; // use this for cert vfy if non-NULL, + // else use hostName + unsigned short port; + const char *getMsg; // e.g., + // "GET / HTTP/1.0\r\n\r\n" + bool allowExpired; + bool allowAnyRoot; + bool allowExpiredRoot; + bool disableCertVerify; + bool manualCertVerify; + bool dumpRxData; // display server data + char cipherRestrict; // '2', 'd'. etc...; '\0' for + // no restriction + bool keepConnected; + bool requireNotify; // require closure notify + // in V3 mode + bool resumableEnable; + bool allowHostnameSpoof; + bool nonBlocking; + char *anchorFile; + bool replaceAnchors; + CFArrayRef clientCerts; // optional + CFArrayRef encryptClientCerts; // optional + bool quiet; // minimal stdout + bool silent; // no stdout + bool verbose; + SSLProtocol negVersion; // RETURNED + SSLCipherSuite negCipher; // RETURNED + CFArrayRef peerCerts; // mallocd & RETURNED + SecTrustRef peerTrust; // RETURNED + SSLClientCertificateState certState; // RETURNED + char *password; // optional to open clientCerts + char **argv; + Boolean sessionWasResumed; + unsigned char sessionID[MAX_SESSION_ID_LENGTH]; + size_t sessionIDLength; + CFAbsoluteTime handshakeTimeOp; // time for this op + CFAbsoluteTime handshakeTimeFirst; // time for FIRST op, not averaged + CFAbsoluteTime handshakeTimeTotal; // time for all ops except first + unsigned numHandshakes; + +} sslPingArgs; + +#include +static void sigpipe(int sig) +{ + fflush(stdin); + printf("***SIGPIPE***\n"); +} + +/* + * Snag a copy of current connection's peer certs so we can + * examine them later after the connection is closed. + * SecureTransport actually does the create and retain for us. + */ +static OSStatus copyPeerCerts( + SSLContext *ctx, + CFArrayRef *peerCerts) // mallocd & RETURNED +{ + OSStatus ortn = SSLCopyPeerCertificates(ctx, peerCerts); + if(ortn) { + printf("***Error obtaining peer certs: %s\n", + sslGetSSLErrString(ortn)); + } + return ortn; +} + +/* free the cert array obtained via SSLGetPeerCertificates() */ +static void freePeerCerts( + CFArrayRef peerCerts) +{ + if(peerCerts) { + CFRelease(peerCerts); + } +} + +/* + * Manually evaluate session's SecTrustRef. + */ +#define SSL_SEC_TRUST 1 + +static OSStatus sslEvaluateTrust( + SSLContext *ctx, + bool verbose, + bool silent, + CFArrayRef *peerCerts) // fetched and retained +{ + OSStatus ortn = errSecSuccess; +#if USE_CDSA_CRYPTO + SecTrustRef secTrust = NULL; + + #if SSL_SEC_TRUST + ortn = SSLGetPeerSecTrust(ctx, &secTrust); + #else + ortn = errSecUnimplemented; + #endif + if(ortn) { + printf("\n***Error obtaining peer SecTrustRef: %s\n", + sslGetSSLErrString(ortn)); + return ortn; + } + if(secTrust == NULL) { + /* this is the normal case for resumed sessions, in which + * no cert evaluation is performed */ + if(!silent) { + printf("...No SecTrust available - this is a resumed session, right?\n"); + } + return errSecSuccess; + } + SecTrustResultType secTrustResult; + ortn = SecTrustEvaluate(secTrust, &secTrustResult); + if(ortn) { + printf("\n***Error on SecTrustEvaluate: %d\n", (int)ortn); + return ortn; + } + if(verbose) { + char *res = NULL; + switch(secTrustResult) { + case kSecTrustResultInvalid: + res = "kSecTrustResultInvalid"; break; + case kSecTrustResultProceed: + res = "kSecTrustResultProceed"; break; + case kSecTrustResultConfirm: + res = "kSecTrustResultConfirm"; break; + case kSecTrustResultDeny: + res = "kSecTrustResultDeny"; break; + case kSecTrustResultUnspecified: + res = "kSecTrustResultUnspecified"; break; + case kSecTrustResultRecoverableTrustFailure: + res = "kSecTrustResultRecoverableTrustFailure"; break; + case kSecTrustResultFatalTrustFailure: + res = "kSecTrustResultFatalTrustFailure"; break; + case kSecTrustResultOtherError: + res = "kSecTrustResultOtherError"; break; + default: + res = "UNKNOWN"; break; + } + printf("\nSecTrustEvaluate(): secTrustResult %s\n", res); + } + + switch(secTrustResult) { + case kSecTrustResultUnspecified: + /* cert chain valid, no special UserTrust assignments */ + case kSecTrustResultProceed: + /* cert chain valid AND user explicitly trusts this */ + break; + default: + printf("\n***SecTrustEvaluate reported secTrustResult %d\n", + (int)secTrustResult); + ortn = errSSLXCertChainInvalid; + break; + } +#endif + + *peerCerts = NULL; + +#ifdef USE_CDSA_CRYPTO + /* one more thing - get peer certs in the form of an evidence chain */ + CSSM_TP_APPLE_EVIDENCE_INFO *dummyEv; + OSStatus thisRtn = SecTrustGetResult(secTrust, &secTrustResult, + peerCerts, &dummyEv); + if(thisRtn) { + printSslErrStr("SecTrustGetResult", thisRtn); + } + else { + /* workaround for the fact that SSLGetPeerCertificates() + * leaves a retain count on each element in the returned array, + * requiring us to do a release on each cert. + */ + CFIndex numCerts = CFArrayGetCount(*peerCerts); + for(CFIndex dex=0; dex", ((unsigned)c) & 0xff); + } + break; + } + + } + printf("\n"); +} + +/* + * Perform one SSL diagnostic session. Returns nonzero on error. Normally no + * output to stdout except initial "connecting to" message, unless there + * is a really screwed up error (i.e., something not directly related + * to the SSL connection). + */ +#define RCV_BUF_SIZE 256 + +static OSStatus sslPing( + sslPingArgs *pargs) +{ + PeerSpec peerId; + otSocket sock = 0; + OSStatus ortn; + SSLContextRef ctx = NULL; + size_t length; + size_t actLen; + uint8_t rcvBuf[RCV_BUF_SIZE]; + CFAbsoluteTime startHandshake; + CFAbsoluteTime endHandshake; + + pargs->negVersion = kSSLProtocolUnknown; + pargs->negCipher = SSL_NULL_WITH_NULL_NULL; + pargs->peerCerts = NULL; + + /* first make sure requested server is there */ + ortn = MakeServerConnection(pargs->hostName, pargs->port, pargs->nonBlocking, + &sock, &peerId); + if(ortn) { + printf("MakeServerConnection returned %d; aborting\n", (int)ortn); + return ortn; + } + if(pargs->verbose) { + printf("...connected to server; starting SecureTransport\n"); + } + + /* + * Set up a SecureTransport session. + * First the standard calls. + */ + ortn = SSLNewContext(false, &ctx); + if(ortn) { + printSslErrStr("SSLNewContext", ortn); + goto cleanup; + } + ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite); + if(ortn) { + printSslErrStr("SSLSetIOFuncs", ortn); + goto cleanup; + } + ortn = SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)sock); + if(ortn) { + printSslErrStr("SSLSetConnection", ortn); + goto cleanup; + } + SSLConnectionRef getConn; + ortn = SSLGetConnection(ctx, &getConn); + if(ortn) { + printSslErrStr("SSLGetConnection", ortn); + goto cleanup; + } + if(getConn != (SSLConnectionRef)(intptr_t)sock) { + printf("***SSLGetConnection error\n"); + ortn = errSecParam; + goto cleanup; + } + if(!pargs->allowHostnameSpoof) { + /* if this isn't set, it isn't checked by AppleX509TP */ + const char *vfyHost = pargs->hostName; + if(pargs->vfyHostName) { + /* generally means we're expecting an error */ + vfyHost = pargs->vfyHostName; + } + ortn = SSLSetPeerDomainName(ctx, vfyHost, strlen(vfyHost)); + if(ortn) { + printSslErrStr("SSLSetPeerDomainName", ortn); + goto cleanup; + } + } + + /* + * SecureTransport options. + */ + if(pargs->acceptedProts) { + ortn = SSLSetProtocolVersionEnabled(ctx, kSSLProtocolAll, false); + if(ortn) { + printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn); + goto cleanup; + } + for(const char *cp = pargs->acceptedProts; *cp; cp++) { + SSLProtocol prot; + switch(*cp) { + case '2': + prot = kSSLProtocol2; + break; + case '3': + prot = kSSLProtocol3; + break; + case 't': + prot = kTLSProtocol12; + break; + default: + usage(pargs->argv); + } + ortn = SSLSetProtocolVersionEnabled(ctx, prot, true); + if(ortn) { + printSslErrStr("SSLSetProtocolVersionEnabled", ortn); + goto cleanup; + } + } + } + else { + ortn = SSLSetProtocolVersion(ctx, pargs->tryVersion); + if(ortn) { + printSslErrStr("SSLSetProtocolVersion", ortn); + goto cleanup; + } + SSLProtocol getVers; + ortn = SSLGetProtocolVersion(ctx, &getVers); + if(ortn) { + printSslErrStr("SSLGetProtocolVersion", ortn); + goto cleanup; + } + if(getVers != pargs->tryVersion) { + printf("***SSLGetProtocolVersion screwup: try %s get %s\n", + sslGetProtocolVersionString(pargs->tryVersion), + sslGetProtocolVersionString(getVers)); + ortn = errSecParam; + goto cleanup; + } + } + if(pargs->resumableEnable) { + const void *rtnId = NULL; + size_t rtnIdLen = 0; + + ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec)); + if(ortn) { + printSslErrStr("SSLSetPeerID", ortn); + goto cleanup; + } + /* quick test of the get fcn */ + ortn = SSLGetPeerID(ctx, &rtnId, &rtnIdLen); + if(ortn) { + printSslErrStr("SSLGetPeerID", ortn); + goto cleanup; + } + if((rtnId == NULL) || (rtnIdLen != sizeof(PeerSpec))) { + printf("***SSLGetPeerID screwup\n"); + } + else if(memcmp(&peerId, rtnId, rtnIdLen) != 0) { + printf("***SSLGetPeerID data mismatch\n"); + } + } + if(pargs->allowExpired) { + ortn = SSLSetAllowsExpiredCerts(ctx, true); + if(ortn) { + printSslErrStr("SSLSetAllowExpiredCerts", ortn); + goto cleanup; + } + } + if(pargs->allowExpiredRoot) { + ortn = SSLSetAllowsExpiredRoots(ctx, true); + if(ortn) { + printSslErrStr("SSLSetAllowsExpiredRoots", ortn); + goto cleanup; + } + } + if(pargs->disableCertVerify) { + ortn = SSLSetEnableCertVerify(ctx, false); + if(ortn) { + printSslErrStr("SSLSetEnableCertVerify", ortn); + goto cleanup; + } + } + if(pargs->allowAnyRoot) { + ortn = SSLSetAllowsAnyRoot(ctx, true); + if(ortn) { + printSslErrStr("SSLSetAllowAnyRoot", ortn); + goto cleanup; + } + } + if(pargs->cipherRestrict != '\0') { + ortn = sslSetCipherRestrictions(ctx, pargs->cipherRestrict); + if(ortn) { + goto cleanup; + } + } + if(pargs->anchorFile) { + ortn = sslAddTrustedRoot(ctx, pargs->anchorFile, pargs->replaceAnchors); + if(ortn) { + printf("***Error obtaining anchor file %s\n", pargs->anchorFile); + goto cleanup; + } + } + if(pargs->clientCerts) { + CFArrayRef dummy; + if(pargs->anchorFile == NULL) { + /* assume this is a root we want to implicitly trust */ + ortn = addIdentityAsTrustedRoot(ctx, pargs->clientCerts); + if(ortn) { + goto cleanup; + } + } + ortn = SSLSetCertificate(ctx, pargs->clientCerts); + if(ortn) { + printSslErrStr("SSLSetCertificate", ortn); + goto cleanup; + } + /* quickie test for this new function */ + ortn = SSLGetCertificate(ctx, &dummy); + if(ortn) { + printSslErrStr("SSLGetCertificate", ortn); + goto cleanup; + } + if(dummy != pargs->clientCerts) { + printf("***SSLGetCertificate error\n"); + ortn = errSecIO; + goto cleanup; + } + } + if(pargs->encryptClientCerts) { + if(pargs->anchorFile == NULL) { + ortn = addIdentityAsTrustedRoot(ctx, pargs->encryptClientCerts); + if(ortn) { + goto cleanup; + } + } + ortn = SSLSetEncryptionCertificate(ctx, pargs->encryptClientCerts); + if(ortn) { + printSslErrStr("SSLSetEncryptionCertificate", ortn); + goto cleanup; + } + } + + /*** end options ***/ + + if(pargs->verbose) { + printf("...starting SSL handshake\n"); + } + startHandshake = CFAbsoluteTimeGetCurrent(); + + do + { ortn = SSLHandshake(ctx); + if((ortn == errSSLWouldBlock) && !pargs->silent) { + /* keep UI responsive */ + sslOutputDot(); + } + } while (ortn == errSSLWouldBlock); + + endHandshake = CFAbsoluteTimeGetCurrent(); + pargs->handshakeTimeOp = endHandshake - startHandshake; + if(pargs->numHandshakes == 0) { + /* special case, this one is always way longer */ + pargs->handshakeTimeFirst = pargs->handshakeTimeOp; + } + else { + /* normal running total */ + pargs->handshakeTimeTotal += pargs->handshakeTimeOp; + } + pargs->numHandshakes++; + + /* this works even if handshake failed due to cert chain invalid */ + if(!pargs->manualCertVerify) { + copyPeerCerts(ctx, &pargs->peerCerts); + } + else { + /* else fetched via SecTrust later */ + pargs->peerCerts = NULL; + } + + ortn = SSLCopyPeerTrust(ctx, &pargs->peerTrust); + if(ortn) { + printf("***SSLCopyPeerTrust error %" PRIdOSStatus "\n", ortn); + pargs->peerTrust = NULL; + } + + /* ditto */ + SSLGetClientCertificateState(ctx, &pargs->certState); + SSLGetNegotiatedCipher(ctx, &pargs->negCipher); + SSLGetNegotiatedProtocolVersion(ctx, &pargs->negVersion); + pargs->sessionIDLength = MAX_SESSION_ID_LENGTH; + SSLGetResumableSessionInfo(ctx, &pargs->sessionWasResumed, pargs->sessionID, + &pargs->sessionIDLength); + if(pargs->manualCertVerify) { + OSStatus certRtn = sslEvaluateTrust(ctx, pargs->verbose, pargs->silent, + &pargs->peerCerts); + if(certRtn && !ortn ) { + ortn = certRtn; + } + } + + if(ortn) { + if(!pargs->silent) { + printf("\n"); + } + goto cleanup; + } + + if(pargs->verbose) { + printf("...SSL handshake complete\n"); + } + length = strlen(pargs->getMsg); + (void) SSLWrite(ctx, pargs->getMsg, length, &actLen); + + /* + * Try to snag RCV_BUF_SIZE bytes. Exit if (!keepConnected and we get any data + * at all), or (keepConnected and err != (none, wouldBlock)). + */ + while (1) { + actLen = 0; + if(pargs->dumpRxData) { + size_t avail = 0; + + ortn = SSLGetBufferedReadSize(ctx, &avail); + if(ortn) { + printf("***SSLGetBufferedReadSize error\n"); + break; + } + if(avail != 0) { + printf("\n%d bytes available: ", (int)avail); + } + } + ortn = SSLRead(ctx, rcvBuf, RCV_BUF_SIZE, &actLen); + if((actLen == 0) && !pargs->silent) { + sslOutputDot(); + } + if((actLen == 0) && (ortn == errSecSuccess)) { + printf("***Radar 2984932 confirmed***\n"); + } + if (ortn == errSSLWouldBlock) { + /* for this loop, these are identical */ + ortn = errSecSuccess; + } + if((actLen > 0) && pargs->dumpRxData) { + dumpAscii(rcvBuf, actLen); + } + if(ortn != errSecSuccess) { + /* connection closed by server or by error */ + break; + } + if(!pargs->keepConnected && (actLen > 0)) { + /* good enough, we connected */ + break; + } + } + if(!pargs->silent) { + printf("\n"); + } + + /* snag these again in case of renegotiate */ + SSLGetClientCertificateState(ctx, &pargs->certState); + SSLGetNegotiatedCipher(ctx, &pargs->negCipher); + SSLGetNegotiatedProtocolVersion(ctx, &pargs->negVersion); + + /* convert normal "shutdown" into zero err rtn */ + if(ortn == errSSLClosedGraceful) { + ortn = errSecSuccess; + } + if((ortn == errSSLClosedNoNotify) && !pargs->requireNotify) { + /* relaxed disconnect rules */ + ortn = errSecSuccess; + } +cleanup: + /* + * always do close, even on error - to flush outgoing write queue + */ + OSStatus cerr = SSLClose(ctx); + if(ortn == errSecSuccess) { + ortn = cerr; + } + if(sock) { + endpointShutdown(sock); + } + if(ctx) { + SSLDisposeContext(ctx); + } + return ortn; +} + +static void add_key(const void *key, const void *value, void *context) { + CFArrayAppendValue((CFMutableArrayRef)context, key); +} + +static void showInfo(CFDictionaryRef info) { + CFIndex dict_count, key_ix, key_count; + CFMutableArrayRef keys = NULL; + CFIndex maxWidth = 20; /* Maybe precompute this or grab from context? */ + + dict_count = CFDictionaryGetCount(info); + keys = CFArrayCreateMutable(kCFAllocatorDefault, dict_count, + &kCFTypeArrayCallBacks); + CFDictionaryApplyFunction(info, add_key, keys); + key_count = CFArrayGetCount(keys); + CFArraySortValues(keys, CFRangeMake(0, key_count), + (CFComparatorFunction)CFStringCompare, 0); + + for (key_ix = 0; key_ix < key_count; ++key_ix) { + CFStringRef key = (CFStringRef)CFArrayGetValueAtIndex(keys, key_ix); + CFTypeRef value = CFDictionaryGetValue(info, key); + CFMutableStringRef line = CFStringCreateMutable(NULL, 0); + + CFStringAppend(line, key); + CFIndex jx; + for (jx = CFStringGetLength(key); + jx < maxWidth; ++jx) { + CFStringAppend(line, CFSTR(" ")); + } + CFStringAppend(line, CFSTR(" : ")); + if (CFStringGetTypeID() == CFGetTypeID(value)) { + CFStringAppend(line, (CFStringRef)value); + } else if (CFDateGetTypeID() == CFGetTypeID(value)) { + CFLocaleRef lc = CFLocaleCopyCurrent(); + CFDateFormatterRef df = CFDateFormatterCreate(NULL, lc, + kCFDateFormatterFullStyle, kCFDateFormatterFullStyle); + CFDateRef date = (CFDateRef)value; + CFStringRef ds = CFDateFormatterCreateStringWithDate(NULL, df, + date); + CFStringAppend(line, ds); + CFRelease(ds); + CFRelease(df); + CFRelease(lc); + } else if (CFURLGetTypeID() == CFGetTypeID(value)) { + CFURLRef url = (CFURLRef)value; + CFStringAppend(line, CFSTR("<")); + CFStringAppend(line, CFURLGetString(url)); + CFStringAppend(line, CFSTR(">")); + } else if (CFDataGetTypeID() == CFGetTypeID(value)) { + CFDataRef v_d = (CFDataRef)value; + CFStringRef v_s = CFStringCreateFromExternalRepresentation( + kCFAllocatorDefault, v_d, kCFStringEncodingUTF8); + if (v_s) { + CFStringAppend(line, CFSTR("/")); + CFStringAppend(line, v_s); + CFStringAppend(line, CFSTR("/ ")); + CFRelease(v_s); + } + const uint8_t *bytes = CFDataGetBytePtr(v_d); + CFIndex len = CFDataGetLength(v_d); + for (jx = 0; jx < len; ++jx) { + CFStringAppendFormat(line, NULL, CFSTR("%.02X"), bytes[jx]); + } + } else { + CFStringAppendFormat(line, NULL, CFSTR("%@"), value); + } + CFStringWriteToFileWithNewline(line, stdout); + CFRelease(line); + } + CFRelease(keys); +} + +static void showPeerTrust(SecTrustRef peerTrust, bool verbose) { + CFIndex numCerts; + CFIndex i; + + if(peerTrust == NULL) { + return; + } + + printf("\n=============== Peer Trust Properties ===============\n"); + CFArrayRef plist = SecTrustCopyProperties(peerTrust); + if (plist) { + print_plist(plist); + CFRelease(plist); + } + + printf("\n================== Peer Trust Info ==================\n"); + CFDictionaryRef info = SecTrustCopyInfo(peerTrust); + if (info && CFDictionaryGetCount(info)) { + showInfo(info); + } + if (info) + CFRelease(info); + + numCerts = SecTrustGetCertificateCount(peerTrust); + for(i=0; i maxProtocol) { + /* known not to support this attempt, relax */ + reqProtocol = maxProtocol; + } + if(reqProtocol != negProtocol) { + printf("***Expected protocol %s; negotiated %s\n", + sslGetProtocolVersionString(reqProtocol), + sslGetProtocolVersionString(negProtocol)); + return 1; + } + else { + return 0; + } +} + +static int verifyClientCertState( + bool verifyCertState, + SSLClientCertificateState expectState, + SSLClientCertificateState gotState) +{ + if(!verifyCertState) { + return 0; + } + if(expectState == gotState) { + return 0; + } + printf("***Expected clientCertState %s; got %s\n", + sslGetClientCertStateString(expectState), + sslGetClientCertStateString(gotState)); + return 1; +} + +static SSLProtocol charToProt( + char c, // 2, 3, t + char **argv) +{ + switch(c) { + case '2': + return kSSLProtocol2; + case '3': + return kSSLProtocol3; + case 't': + return kTLSProtocol12; + default: + usage(argv); + } + /* NOT REACHED */ + return kSSLProtocolUnknown; +} + +int main(int argc, char **argv) +{ + OSStatus err; + int arg; + char *argp; + char getMsg[300]; + char fullFileBase[100]; + int ourRtn = 0; // exit status - sum of all errors + unsigned loop; + SecKeychainRef serverKc = nil; + SecKeychainRef encryptKc = nil; + sslPingArgs pargs; + + /* user-spec'd parameters */ + const char *getPath = DEFAULT_PATH; + char *fileBase = NULL; + int displayCerts = 0; + bool doSslV2 = false; + bool doSslV3 = false; + bool doTlsV1 = true; + bool doTlsV11 = false; + bool doTlsV12 = false; + bool protXOnly = false; // kSSLProtocol3Only, kTLSProtocol1Only + bool doProtUnknown = false; + unsigned loopCount = 1; + bool doPause = false; + bool pauseFirstLoop = false; + bool verifyProt = false; + SSLProtocol maxProtocol = kTLSProtocol12; // for verifying negotiated + // protocol + char *acceptedProts = NULL; + char *keyChainName = NULL; + char *encryptKeyChainName = NULL; + char *getMsgSpec = NULL; + bool vfyCertState = false; + SSLClientCertificateState expectCertState = kSSLClientCertNone; + bool displayHandshakeTimes = false; + bool completeCertChain = false; + + /* special case - one arg of "h" or "-h" or "hv" */ + if(argc == 2) { + if((strcmp(argv[1], "h") == 0) || (strcmp(argv[1], "-h") == 0)) { + usage(argv); + } + if(strcmp(argv[1], "hv") == 0) { + usageVerbose(argv); + } + } + + /* set up defaults */ + memset(&pargs, 0, sizeof(sslPingArgs)); + pargs.hostName = DEFAULT_HOST; + pargs.port = DEFAULT_PORT; + pargs.resumableEnable = true; + pargs.argv = argv; + + for(arg=1; arg 1) ? "errors" : "error", pargs.hostName); + } + return ourRtn; + +} + + diff --git a/sslViewer/SSL_Sites b/sslViewer/SSL_Sites new file mode 100644 index 00000000..9c297941 --- /dev/null +++ b/sslViewer/SSL_Sites @@ -0,0 +1,306 @@ +www.cduniverse.com + v2 : + export: SSL_RSA_EXPORT_WITH_RC4_40_MD5 + domestic: SSL_RSA_WITH_RC4_128_MD5 + SSL_RSA_WITH_DES_CBC_MD5 + root: RSA Secure Server CA + resumable session via sslViewer? yes + v3: + export: SSL_RSA_EXPORT_WITH_RC4_40_MD5 + domestic: SSL_RSA_WITH_RC4_128_MD5 + SSL_RSA_WITH_RC4_128_SHA + SSL_RSA_WITH_DES_CBC_SHA + root: RSA Secure Server CA + pass root cert? NO + send close alert? NO + resumable session via sslViewer? yes + resumable session via URLAccess? sometimes + + TLSv1? yes + +www.amazon.com 208.216.182.15 + v2 : + export: SSL_RSA_EXPORT_WITH_RC4_40_MD5 + domestic: SSL_RSA_WITH_RC4_128_MD5 + SSL_RSA_WITH_DES_CBC_MD5 + root: RSA Secure Server CA + resumable session via sslViewer? yes + v3: + export: SSL_RSA_EXPORT_WITH_RC4_40_MD5 + SSL_RSA_EXPORT_WITH_DES40_CBC_SHA + domestic: SSL_RSA_WITH_3DES_EDE_CBC_SHA + SSL_RSA_WITH_RC4_128_SHA + SSL_RSA_WITH_DES_CBC_SHA + root: RSA Secure Server CA + pass root cert? NO + send close alert? YES + resumable session via sslViewer? yes + resumable session via URLAccess? unknown + + TLSv1? yes + +store.apple.com 17.254.3.41 + v2 : + export: SSL_RSA_EXPORT_WITH_RC4_40_MD5 + domestic: SSL_RSA_WITH_RC4_128_MD5 + root: RSA Secure Server CA + resumable session via sslViewer? yes + resumable session via URLAccess? unknown + + v3: none - only does V2 + export: n/a + domestic: n/a + root: n/a + pass root cert? n/a + send close alert? n/a + + TLSv1? no + +www.dvdexpress.com 208.228.126.81 + v2 : + export: SSL_RSA_EXPORT_WITH_RC4_40_MD5 + domestic: SSL_RSA_WITH_RC4_128_MD5 + root: RSA Secure Server CA + v3: + export: SSL_RSA_EXPORT_WITH_RC4_40_MD5 + domestic: SSL_RSA_WITH_RC4_128_MD5 + root: RSA Secure Server CA + pass root cert? NO + send close alert? NO + +www.xdss.com 204.33.235.33 + v2 : + export: SSL_RSA_EXPORT_WITH_RC4_40_MD5 + domestic: SSL_RSA_WITH_RC4_128_MD5 + root: RSA Secure Server CA + v3: + export: SSL_RSA_EXPORT_WITH_RC4_40_MD5 + domestic: SSL_RSA_WITH_RC4_128_MD5 + root: old RSA Secure Server CA, expires 12/99 + pass root cert? YES + send close alert? YES + resumable session via sslViewer? NO - MAC errors (Triple DES OK) + + TLSv1? no + +accounts2.keybank.com 156.77.100.194 + v2 : + export: ? + domestic: ? + root: VeriSign International Server CA - Class 3 + (note this isn't a known root!) + Note this server can't be verified in SSL2 mode + v3: + export: SSL_RSA_EXPORT_WITH_RC4_40_MD5 + domestic: SSL_RSA_WITH_RC4_128_MD5 + root: Verisign Class 3 Public Primary CA + pass root cert? NO + send close alert? NO + resumable session via sslViewer? yes + resumable session via URLAccess? no, not attempted + + TLSv1? yes + +cdnow.com 209.83.166.2 + v2 : + export: SSL_RSA_EXPORT_WITH_RC4_40_MD5 + domestic: SSL_RSA_WITH_RC4_128_MD5 + root: RSA Secure Server CA + v3: + export: SSL_RSA_EXPORT_WITH_RC4_40_MD5 + Note: no server key exchange message! + domestic: SSL_RSA_WITH_3DES_EDE_CBC_SHA + root: RSA Secure Server CA + pass root cert? NO + send close alert? + resumable session via URLAccess? TBD + + TLSv1? yes as of 5/1/02 + +www.proteron.com 206.132.170.39 + v2 : + export: SSL_RSA_EXPORT_WITH_RC4_40_MD5 + domestic: SSL_RSA_WITH_RC4_128_MD5 + root: Thawte Server CA + v3: + export: SSL_RSA_EXPORT_WITH_RC4_40_MD5 + domestic: SSL_RSA_WITH_3DES_EDE_CBC_SHA + root: Thawte Server CA + pass root cert? NO + send close alert? YES + resumable session via sslViewer? yes + resumable session via URLAccess? no, not attempted + + TLSv1? yes + +www.starnine.com + v2 : + export: SSL_RSA_EXPORT_WITH_RC4_40_MD5 + domestic: SSL_RSA_WITH_RC4_128_MD5 + root: Equifax Secure E-Business CA-2, UNKNOWN + v3: + export: SSL_RSA_EXPORT_WITH_RC4_40_MD5 + domestic: SSL_RSA_WITH_3DES_EDE_CBC_SHA + root: Thawte Server CA (verifier Equifax Secure E-Business CA-2) + -- end-of-chain expired Jul 10, 2001 + pass root cert? NO + send close alert? NO + +config.puretec.de + v2 : + export: SSL_RSA_EXPORT_WITH_RC4_40_MD5 + domestic: SSL_RSA_WITH_RC4_128_MD5 + root: Thawte Server CA + v3: + export: SSL_RSA_EXPORT_WITH_RC4_40_MD5 + domestic: SSL_RSA_WITH_3DES_EDE_CBC_SHA + root: Thawte Server CA + pass root cert? NO + send close alert? NO + resumable session via sslViewer? no + + TLSv1? yes + +comhome.comdirect.de /de/comhome/login/index_login.html + v2 : + export: ? + domestic: ? + root: VeriSign International Server CA - Class 3 - UNKNOWN + + v3: + export: SSL_RSA_EXPORT_WITH_RC4_40_MD5 + domestic: SSL_RSA_WITH_RC4_128_MD5 + root: Verisign Class 3 Public Primary Certification Authority + pass root cert? NO + send close alert? NO + resumable session via sslViewer? no + +www.yellownet.ch + v2 : + export: ? + domestic: ? + root: VeriSign International Server CA - Class 3 + (note this isn't a known root!) + Note this server can't be verified in SSL2 mode + v3: + domestic: SSL_RSA_WITH_3DES_EDE_CBC_SHA + root: Verisign Class 3 Public Primary CA + pass root cert? NO + send close alert? YES + resumable session? NO + +www.thawte.com + v2 : + export: SSL_RSA_EXPORT_WITH_RC4_40_MD5 + domestic: SSL_RSA_WITH_RC4_128_MD5 + root: Thawte Server CA + v3: + domestic: SSL_RSA_WITH_3DES_EDE_CBC_SHA + root: Thawte Server CA + pass root cert? NO + send close alert? YES + resumable session via sslViewer? yes + resumable session via URLAccess? no, not attempted + + TLSv1? yes + +banking.wellsfargo.com + v2 : + export: ? + domestic: ? + root: VeriSign International Server CA - Class 3 + (note this isn't a known root!) + Note this server can't be verified in SSL2 mode + v3: + domestic: SSL_RSA_WITH_RC4_128_MD5 + root: Verisign Class 3 Public Primary CA + pass root cert? YES + send close alert? YES + resumable session via sslViewer? yes, but >4 loops required + resumable session via URLAccess? YES + +gen2.aeacu.com + v2 : + domestic: SSL_RSA_WITH_RC4_128_MD5 + root: RSA Secure Server CA + + v3: + domestic: SSL_RSA_WITH_RC4_128_MD5 + root: RSA Secure Server CA (expires 10/11/01) + pass root cert? YES + send close alert? NO + resumable session via sslViewer? yes + resumable session via URLAccess? not attempted + + TLSv1? yes + +secure.authorize.net + v2 : + domestic: SSL_RSA_WITH_RC4_128_MD5 + root: RSA Secure Server CA + + v3: + domestic: SSL_RSA_WITH_RC4_128_MD5 + root: RSA Secure Server CA + pass root cert? NO + send close alert? NO + resumable session via sslViewer? sometimes - server rejects some attempts + resumable session via URLAccess? unknown + + TLSv1? yes + +mail.wwc.com + v2 : + domestic: SSL_NULL_WITH_NULL_NULL! + root: None! errSSLClosedGraceful! + + v3: + domestic: SSL_RSA_WITH_RC4_128_SHA + root: Stalker Software, Inc. (Unknown) + pass root cert? NO + send close alert? YES + +www.cynic.org + v2 : + domestic: SSL_RSA_WITH_RC4_128_MD5! + root: Cynics At Large Certificate Authority(Unknown) + + v3: + domestic: SSL_RSA_WITH_3DES_EDE_CBC_SHA + root: Cynics At Large Certificate Authority(Unknown AND expired) + pass root cert? YES + send close alert? NO + resumable session via sslViewer? yes + resumable session via URLAccess? unknown - illegal root cert +.................................................... + +Supported CipherSuites + +SSL_RSA_WITH_3DES_EDE_CBC_SHA + www.amazon.com v3 + www.proteron.com v3 + www.starnine.com v3 + +SSL_RSA_WITH_3DES_EDE_CBC_MD5 (v2 only) + www.proteron.com + +SSL_RSA_WITH_RC4_128_SHA + www.amazon.com v3 + cdu1.cduniverse.com v3 + +SSL_RSA_WITH_RC4_128_MD5 + just about everyone, both v2 and v3 + +SSL_RSA_WITH_DES_CBC_SHA + www.amazon.com v3 + cdu1.cduniverse.com v3 + +SSL_RSA_WITH_DES_CBC_MD5 + www.amazon.com v2 + cdu1.cduniverse.com v2 + +SSL_RSA_EXPORT_WITH_RC4_40_MD5 + just about everyone, both v2 and v3 + +SSL_RSA_EXPORT_WITH_DES40_CBC_SHA + www.amazon.com v3 diff --git a/sslViewer/ecc-secp256r1-client.pfx b/sslViewer/ecc-secp256r1-client.pfx new file mode 100644 index 0000000000000000000000000000000000000000..ec796e987f65ca19a8d0fe58b01518934393f6a4 GIT binary patch literal 1036 zcmXqLV&Pz7WHxAGKE%eU)#lOmotKfFaX}OFW|k)A^+4g(294X1Wg1tqG%hn}Tx`&| zfQ=iffrpEcX+f4jhJg$l7fc9fCLaq&#)=zCpDrxh%*4dOz~b?X-GFIAZb)grrJ}4u zmq%@ykoyjYkgF-r|17cCIiL9{hl$b$wpGms)IH3L<&Ewfj;gY}^vDQYOjB4X7oEuo|tsj+8M_maxn9CzoGDli%}z!kBxEod-k zU}9uI7Gp$lFB{0c{qmjDw#>OI0dntx29_qK8QJkSmaw}2l(L?-W&I)JTfxdojIXV# zOO9JA2c-Wlo_#POZ{xqy{oK2f&VP!YTAKOp?S?h^?rYAMv^`vR_LiB-*JM2}hI`Hx zTyJkpiRn=>deHVIu21T`S~5$Fu}IbdZjM!F#s7)!4PT-YapFbH4gLO~&6Q1Etd5cY zpPk<#=5<^7rB?T8|Btg5vXw=sKYg~yt@C8@oY;wdT)po$q?xLodLpvaxzgQ#J!f5F z-@!xOnI54Z%Iu7`dB5ul{_b;=@BE_nEtCIE4y-O`?wRnI{Yv}U@F_=EEn*UX<7;Vq zS-Eems{3T#$#%>BE(}Opntf_l{e1P$YZiU{x*-4UT5GPe8}IJ1Pdv2zqhn(7|D&=| zg%uMX{jA}Bta`Um=Cf5QOH)?Oj}2XF2?}by9&zWIBoq3)yC44$s@eHH;J~*?*-yLW z3f?4JtaRzEkjc;!O!#cx#@#Lz?sfgnSM5b=-D=$Xk|b@dpH?nkd+o$qvCRTMIaN5h zOQM>^XSQ5&YSCtl-t}JFPiA%X)v_5KyB8?Q{G5F7bnExvlB~@_of>!2SH*i5U&{-; z7*g0^9`L~6{O%-1#;zlMA4S={Y}BXhZC~Q-^!}Y?>XK*7U%F&U98E#%&HuGodT$TMFt`fm^LU;e>Q=7it%=#j? zU21#uroP=5`Fx)(Y&yyEEbfJtH``7f(S)>zi!+y>{CzlzccVyI^nv|%e>nN^Zd{(l z!cn3&qg7a8-dP4XFt9aHG~i@o)#hVnl450G5s^B%fBF^Qt~-wl-n=++-zhI?jf*CW d$iGhy8KyNju2STk%sPSjSZwr%wLG8%4*(T}y(a(w literal 0 HcmV?d00001 diff --git a/sslViewer/ioSock.c b/sslViewer/ioSock.c new file mode 100644 index 00000000..676cf2bc --- /dev/null +++ b/sslViewer/ioSock.c @@ -0,0 +1,481 @@ +/* + * Copyright (c) 2006-2008,2010,2012-2013 Apple Inc. All Rights Reserved. + * + * io_sock.c - SecureTransport sample I/O module, X sockets version + */ + +#include "ioSock.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +/* debugging for this module */ +#define SSL_OT_DEBUG 1 + +/* log errors to stdout */ +#define SSL_OT_ERRLOG 1 + +/* trace all low-level network I/O */ +#define SSL_OT_IO_TRACE 0 + +/* if SSL_OT_IO_TRACE, only log non-zero length transfers */ +#define SSL_OT_IO_TRACE_NZ 1 + +/* pause after each I/O (only meaningful if SSL_OT_IO_TRACE == 1) */ +#define SSL_OT_IO_PAUSE 0 + +/* print a stream of dots while I/O pending */ +#define SSL_OT_DOT 1 + +/* dump some bytes of each I/O (only meaningful if SSL_OT_IO_TRACE == 1) */ +#define SSL_OT_IO_DUMP 0 +#define SSL_OT_IO_DUMP_SIZE 256 + +/* indicate errSSLWouldBlock with a '.' */ +#define SSL_DISPL_WOULD_BLOCK 0 + +/* general, not-too-verbose debugging */ +#if SSL_OT_DEBUG +#define dprintf(s) printf s +#else +#define dprintf(s) +#endif + +/* errors --> stdout */ +#if SSL_OT_ERRLOG +#define eprintf(s) printf s +#else +#define eprintf(s) +#endif + +/* trace completion of every r/w */ +#if SSL_OT_IO_TRACE +static void tprintf( + const char *str, + UInt32 req, + UInt32 act, + const UInt8 *buf) +{ + #if SSL_OT_IO_TRACE_NZ + if(act == 0) { + return; + } + #endif + printf("%s(%u): moved (%u) bytes\n", str, (unsigned)req, (unsigned)act); + #if SSL_OT_IO_DUMP + { + unsigned i; + + for(i=0; i= (SSL_OT_IO_DUMP_SIZE - 1)) { + break; + } + } + printf("\n"); + } + #endif + #if SSL_OT_IO_PAUSE + { + char instr[20]; + printf("CR to continue: "); + gets(instr); + } + #endif +} + +#else +#define tprintf(str, req, act, buf) +#endif /* SSL_OT_IO_TRACE */ + +/* + * If SSL_OT_DOT, output a '.' every so often while waiting for + * connection. This gives user a chance to do something else with the + * UI. + */ + +#if SSL_OT_DOT + +static time_t lastTime = (time_t)0; +#define TIME_INTERVAL 3 + +static void outputDot() +{ + time_t thisTime = time(0); + + if((thisTime - lastTime) >= TIME_INTERVAL) { + printf("."); fflush(stdout); + lastTime = thisTime; + } +} +#else +#define outputDot() +#endif + + +/* + * One-time only init. + */ +void initSslOt(void) +{ + +} + +/* + * Connect to server. + */ +#define GETHOST_RETRIES 3 + +OSStatus MakeServerConnection( + const char *hostName, + int port, + int nonBlocking, // 0 or 1 + otSocket *socketNo, // RETURNED + PeerSpec *peer) // RETURNED +{ + struct sockaddr_in addr; + struct hostent *ent; + struct in_addr host; + int sock = 0; + + *socketNo = 0; + if (hostName[0] >= '0' && hostName[0] <= '9') + { + host.s_addr = inet_addr(hostName); + } + else { + unsigned dex; + /* seeing a lot of soft failures here that I really don't want to track down */ + for(dex=0; dexh_addr, sizeof(struct in_addr)); + } + sock = socket(AF_INET, SOCK_STREAM, 0); + addr.sin_addr = host; + addr.sin_port = htons((u_short)port); + + addr.sin_family = AF_INET; + if (connect(sock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) != 0) + { printf("connect returned error\n"); + return errSecIO; + } + + if(nonBlocking) { + /* OK to do this after connect? */ + int rtn = fcntl(sock, F_SETFL, O_NONBLOCK); + if(rtn == -1) { + perror("fctnl(O_NONBLOCK)"); + return errSecIO; + } + } + + peer->ipAddr = addr.sin_addr.s_addr; + peer->port = htons((u_short)port); + *socketNo = (otSocket)sock; + return errSecSuccess; +} + +/* + * Set up an otSocket to listen for client connections. Call once, then + * use multiple AcceptClientConnection calls. + */ +OSStatus ListenForClients( + int port, + int nonBlocking, // 0 or 1 + otSocket *socketNo) // RETURNED +{ + struct sockaddr_in addr; + struct hostent *ent; + int len; + int sock; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if(sock < 1) { + perror("socket"); + return errSecIO; + } + + int reuse = 1; + int err = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); + if (err != 0) { + perror("setsockopt"); + return err; + } + + ent = gethostbyname("localhost"); + if (!ent) { + perror("gethostbyname"); + return errSecIO; + } + memcpy(&addr.sin_addr, ent->h_addr, sizeof(struct in_addr)); + + addr.sin_port = htons((u_short)port); + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_family = AF_INET; + len = sizeof(struct sockaddr_in); + if (bind(sock, (struct sockaddr *) &addr, len)) { + int theErr = errno; + perror("bind"); + if(theErr == EADDRINUSE) { + return errSecOpWr; + } + else { + return errSecIO; + } + } + if(nonBlocking) { + int rtn = fcntl(sock, F_SETFL, O_NONBLOCK); + if(rtn == -1) { + perror("fctnl(O_NONBLOCK)"); + return errSecIO; + } + } + + for(;;) { + int rtn = listen(sock, 1); + switch(rtn) { + case 0: + *socketNo = (otSocket)sock; + rtn = errSecSuccess; + break; + case EWOULDBLOCK: + continue; + default: + perror("listen"); + rtn = errSecIO; + break; + } + return rtn; + } + /* NOT REACHED */ + return 0; +} + +/* + * Accept a client connection. + */ + +/* + * Currently we always get back a different peer port number on successive + * connections, no matter what the client is doing. To test for resumable + * session support, force peer port = 0. + */ +#define FORCE_ACCEPT_PEER_PORT_ZERO 1 + +OSStatus AcceptClientConnection( + otSocket listenSock, // obtained from ListenForClients + otSocket *acceptSock, // RETURNED + PeerSpec *peer) // RETURNED +{ + struct sockaddr_in addr; + int sock; + socklen_t len; + + len = sizeof(struct sockaddr_in); + do { + sock = accept((int)listenSock, (struct sockaddr *) &addr, &len); + if (sock < 0) { + if(errno == EAGAIN) { + /* nonblocking, no connection yet */ + continue; + } + else { + perror("accept"); + return errSecIO; + } + } + else { + break; + } + } while(1); + *acceptSock = (otSocket)sock; + peer->ipAddr = addr.sin_addr.s_addr; + #if FORCE_ACCEPT_PEER_PORT_ZERO + peer->port = 0; + #else + peer->port = ntohs(addr.sin_port); + #endif + return errSecSuccess; +} + +/* + * Shut down a connection. + */ +void endpointShutdown( + otSocket sock) +{ + close((int)sock); +} + +/* + * R/W. Called out from SSL. + */ +OSStatus SocketRead( + SSLConnectionRef connection, + void *data, /* owned by + * caller, data + * RETURNED */ + size_t *dataLength) /* IN/OUT */ +{ + size_t bytesToGo = *dataLength; + size_t initLen = bytesToGo; + UInt8 *currData = (UInt8 *)data; + int sock = (int)((long)connection); + OSStatus rtn = errSecSuccess; + size_t bytesRead = 0; + ssize_t rrtn; + + *dataLength = 0; + + for(;;) { + /* paranoid check, ensure errno is getting written */ + errno = -555; + rrtn = recv(sock, currData, bytesToGo, 0); + if (rrtn <= 0) { + if(rrtn == 0) { + /* closed, EOF */ + rtn = errSSLClosedGraceful; + break; + } + int theErr = errno; + switch(theErr) { + case ENOENT: + /* + * Undocumented but I definitely see this. + * Non-blocking sockets only. Definitely retriable + * just like an EAGAIN. + */ + dprintf(("SocketRead RETRYING on ENOENT, rrtn %d\n", + (int)rrtn)); + /* normal... */ + //rtn = errSSLWouldBlock; + /* ...for temp testing.... */ + rtn = errSecIO; + break; + case ECONNRESET: + /* explicit peer abort */ + rtn = errSSLClosedAbort; + break; + case EAGAIN: + /* nonblocking, no data */ + rtn = errSSLWouldBlock; + break; + default: + dprintf(("SocketRead: read(%u) error %d, rrtn %d\n", + (unsigned)bytesToGo, theErr, (int)rrtn)); + rtn = errSecIO; + break; + } + /* in any case, we're done with this call if rrtn <= 0 */ + break; + } + bytesRead = rrtn; + bytesToGo -= bytesRead; + currData += bytesRead; + + if(bytesToGo == 0) { + /* filled buffer with incoming data, done */ + break; + } + } + *dataLength = initLen - bytesToGo; + tprintf("SocketRead", initLen, *dataLength, (UInt8 *)data); + + #if SSL_OT_DOT || (SSL_OT_DEBUG && !SSL_OT_IO_TRACE) + if((rtn == 0) && (*dataLength == 0)) { + /* keep UI alive */ + outputDot(); + } + #endif + #if SSL_DISPL_WOULD_BLOCK + if(rtn == errSSLWouldBlock) { + printf("."); fflush(stdout); + } + #endif + return rtn; +} + +int oneAtATime = 0; + +OSStatus SocketWrite( + SSLConnectionRef connection, + const void *data, + size_t *dataLength) /* IN/OUT */ +{ + size_t bytesSent = 0; + int sock = (int)((long)connection); + size_t length; + size_t dataLen = *dataLength; + const UInt8 *dataPtr = (UInt8 *)data; + OSStatus ortn; + + if(oneAtATime && (*dataLength > 1)) { + size_t i; + size_t outLen; + size_t thisMove; + + outLen = 0; + for(i=0; i 0) && + ( (bytesSent += length) < dataLen) ); + + if(length <= 0) { + int theErr = errno; + switch(theErr) { + case EAGAIN: + ortn = errSSLWouldBlock; break; + case EPIPE: + ortn = errSSLClosedAbort; break; + default: + dprintf(("SocketWrite: write(%u) error %d\n", + (unsigned)(dataLen - bytesSent), theErr)); + ortn = errSecIO; + break; + } + } + else { + ortn = errSecSuccess; + } + tprintf("SocketWrite", dataLen, bytesSent, dataPtr); + *dataLength = bytesSent; + return ortn; +} diff --git a/sslViewer/ioSock.h b/sslViewer/ioSock.h new file mode 100644 index 00000000..f816ca94 --- /dev/null +++ b/sslViewer/ioSock.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2006-2007 Apple Inc. All Rights Reserved. + * + * ioSock.h - socket-based I/O routines for SecureTransport tests + */ + +#ifndef _IO_SOCK_H_ +#define _IO_SOCK_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Opaque reference to an Open Transport connection. + */ +typedef int otSocket; + +/* + * info about a peer returned from MakeServerConnection() and + * AcceptClientConnection(). + */ +typedef struct +{ UInt32 ipAddr; + int port; +} PeerSpec; + +/* + * Ont-time only init. + */ +void initSslOt(void); + +/* + * Connect to server. + */ +extern OSStatus MakeServerConnection( + const char *hostName, + int port, + int nonBlocking, // 0 or 1 + otSocket *socketNo, // RETURNED + PeerSpec *peer); // RETURNED + +/* + * Set up an otSocket to listen for client connections. Call once, then + * use multiple AcceptClientConnection calls. + */ +OSStatus ListenForClients( + int port, + int nonBlocking, // 0 or 1 + otSocket *socketNo); // RETURNED + +/* + * Accept a client connection. Call endpointShutdown() for each successful; + * return from this function. + */ +OSStatus AcceptClientConnection( + otSocket listenSock, // obtained from ListenForClients + otSocket *acceptSock, // RETURNED + PeerSpec *peer); // RETURNED + +/* + * Shut down a connection. + */ +void endpointShutdown( + otSocket socket); + +/* + * R/W. Called out from SSL. + */ +OSStatus SocketRead( + SSLConnectionRef connection, + void *data, /* owned by + * caller, data + * RETURNED */ + size_t *dataLength); /* IN/OUT */ + +OSStatus SocketWrite( + SSLConnectionRef connection, + const void *data, + size_t *dataLength); /* IN/OUT */ + +#ifdef __cplusplus +} +#endif + +#endif /* _IO_SOCK_H_ */ diff --git a/sslViewer/pingSslSites b/sslViewer/pingSslSites new file mode 100755 index 00000000..bb818094 --- /dev/null +++ b/sslViewer/pingSslSites @@ -0,0 +1,37 @@ +#! /bin/csh -f +# +# run sslViewer on a list of known sites. Arguments to this script are passed on +# to sslViewer unmodified. +# +set ARG_LIST = +# +while ( $#argv > 0 ) + set thisArg = "$argv[1]" + set ARG_LIST = "$ARG_LIST $thisArg" + shift +end +echo Starting pingSslSites\; args: $ARG_LIST +# +# NOTE: using this list generates two errors when run without the 'e r' options. +# -- www.xdss.com has an unrecognized root cert. +# -- accounts2.keybank.com has an unrecognized cert in SSLv2 mode only +# +# Other anomalies: +# +# -- store.apple.com only supports SSlv2 (!) +# -- www.xdss.com does not support TLSv1 +# +set SSL_SITES = (www.cduniverse.com \ + www.amazon.com \ + store.apple.com \ + www.xdss.com \ + accounts2.keybank.com \ + cdnow.com \ + www.proteron.com \ + config.puretec.de \ + www.thawte.com \ + secure.authorize.net) + +foreach site ($SSL_SITES); + $LOCAL_BUILD_DIR/sslViewer $site $ARG_LIST; +end diff --git a/sslViewer/sslAppUtils.cpp b/sslViewer/sslAppUtils.cpp new file mode 100644 index 00000000..9bdd6329 --- /dev/null +++ b/sslViewer/sslAppUtils.cpp @@ -0,0 +1,1616 @@ +/* + * Copyright (c) 2006-2008,2010-2013 Apple Inc. All Rights Reserved. + */ + +#include "sslAppUtils.h" +//#include "sslThreading.h" +//#include "identPicker.h" +//#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "utilities/SecCFRelease.h" + +/* Set true when PR-3074739 is merged to TOT */ +#define NEW_SSL_ERRS_3074739 1 + + +const char *sslGetCipherSuiteString(SSLCipherSuite cs) +{ + static char noSuite[40]; + + switch(cs) { + case SSL_NULL_WITH_NULL_NULL: + return "SSL_NULL_WITH_NULL_NULL"; + case SSL_RSA_WITH_NULL_MD5: + return "SSL_RSA_WITH_NULL_MD5"; + case SSL_RSA_WITH_NULL_SHA: + return "SSL_RSA_WITH_NULL_SHA"; + case SSL_RSA_EXPORT_WITH_RC4_40_MD5: + return "SSL_RSA_EXPORT_WITH_RC4_40_MD5"; + case SSL_RSA_WITH_RC4_128_MD5: + return "SSL_RSA_WITH_RC4_128_MD5"; + case SSL_RSA_WITH_RC4_128_SHA: + return "SSL_RSA_WITH_RC4_128_SHA"; + case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: + return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5"; + case SSL_RSA_WITH_IDEA_CBC_SHA: + return "SSL_RSA_WITH_IDEA_CBC_SHA"; + case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"; + case SSL_RSA_WITH_DES_CBC_SHA: + return "SSL_RSA_WITH_DES_CBC_SHA"; + case SSL_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_RSA_WITH_3DES_EDE_CBC_SHA"; + case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"; + case SSL_DH_DSS_WITH_DES_CBC_SHA: + return "SSL_DH_DSS_WITH_DES_CBC_SHA"; + case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA"; + case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"; + case SSL_DH_RSA_WITH_DES_CBC_SHA: + return "SSL_DH_RSA_WITH_DES_CBC_SHA"; + case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA"; + case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"; + case SSL_DHE_DSS_WITH_DES_CBC_SHA: + return "SSL_DHE_DSS_WITH_DES_CBC_SHA"; + case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA: + return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; + case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"; + case SSL_DHE_RSA_WITH_DES_CBC_SHA: + return "SSL_DHE_RSA_WITH_DES_CBC_SHA"; + case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; + case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: + return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5"; + case SSL_DH_anon_WITH_RC4_128_MD5: + return "SSL_DH_anon_WITH_RC4_128_MD5"; + case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: + return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA"; + case SSL_DH_anon_WITH_DES_CBC_SHA: + return "SSL_DH_anon_WITH_DES_CBC_SHA"; + case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: + return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA"; + case SSL_FORTEZZA_DMS_WITH_NULL_SHA: + return "SSL_FORTEZZA_DMS_WITH_NULL_SHA"; + case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA: + return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA"; + case SSL_RSA_WITH_RC2_CBC_MD5: + return "SSL_RSA_WITH_RC2_CBC_MD5"; + case SSL_RSA_WITH_IDEA_CBC_MD5: + return "SSL_RSA_WITH_IDEA_CBC_MD5"; + case SSL_RSA_WITH_DES_CBC_MD5: + return "SSL_RSA_WITH_DES_CBC_MD5"; + case SSL_RSA_WITH_3DES_EDE_CBC_MD5: + return "SSL_RSA_WITH_3DES_EDE_CBC_MD5"; + case SSL_NO_SUCH_CIPHERSUITE: + return "SSL_NO_SUCH_CIPHERSUITE"; + case TLS_RSA_WITH_AES_128_CBC_SHA: + return "TLS_RSA_WITH_AES_128_CBC_SHA"; + case TLS_DH_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; + case TLS_DH_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; + case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; + case TLS_RSA_WITH_AES_256_CBC_SHA: + return "TLS_RSA_WITH_AES_256_CBC_SHA"; + case TLS_DH_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; + case TLS_DH_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; + case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: + return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; + case TLS_DH_anon_WITH_AES_256_CBC_SHA: + return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; + + default: + sprintf(noSuite, "Unknown (%d)", (unsigned)cs); + return noSuite; + } +} + +/* + * Given a SSLProtocolVersion - typically from SSLGetProtocolVersion - + * return a string representation. + */ +const char *sslGetProtocolVersionString(SSLProtocol prot) +{ + static char noProt[20]; + + switch(prot) { + case kSSLProtocolUnknown: + return "kSSLProtocolUnknown"; + case kSSLProtocol2: + return "kSSLProtocol2"; + case kSSLProtocol3: + return "kSSLProtocol3"; + case kSSLProtocol3Only: + return "kSSLProtocol3Only"; + case kTLSProtocol1: + return "kTLSProtocol1"; + case kTLSProtocol1Only: + return "kTLSProtocol1Only"; + case kTLSProtocol11: + return "kTLSProtocol11"; + case kTLSProtocol12: + return "kTLSProtocol12"; + default: + sprintf(noProt, "Unknown (%d)", (unsigned)prot); + return noProt; + } +} + +/* + * Return string representation of SecureTransport-related OSStatus. + */ +const char *sslGetSSLErrString(OSStatus err) +{ + static char errSecSuccessStr[20]; + + switch(err) { + case errSecSuccess: + return "errSecSuccess"; + case errSecAllocate: + return "errSecAllocate"; + case errSecParam: + return "errSecParam"; + case errSecUnimplemented: + return "errSecUnimplemented"; + case errSecIO: + return "errSecIO"; + case errSecBadReq: + return "errSecBadReq"; + case errSSLProtocol: + return "errSSLProtocol"; + case errSSLNegotiation: + return "errSSLNegotiation"; + case errSSLFatalAlert: + return "errSSLFatalAlert"; + case errSSLWouldBlock: + return "errSSLWouldBlock"; + case errSSLSessionNotFound: + return "errSSLSessionNotFound"; + case errSSLClosedGraceful: + return "errSSLClosedGraceful"; + case errSSLClosedAbort: + return "errSSLClosedAbort"; + case errSSLXCertChainInvalid: + return "errSSLXCertChainInvalid"; + case errSSLBadCert: + return "errSSLBadCert"; + case errSSLCrypto: + return "errSSLCrypto"; + case errSSLInternal: + return "errSSLInternal"; + case errSSLModuleAttach: + return "errSSLModuleAttach"; + case errSSLUnknownRootCert: + return "errSSLUnknownRootCert"; + case errSSLNoRootCert: + return "errSSLNoRootCert"; + case errSSLCertExpired: + return "errSSLCertExpired"; + case errSSLCertNotYetValid: + return "errSSLCertNotYetValid"; + case errSSLClosedNoNotify: + return "errSSLClosedNoNotify"; + case errSSLBufferOverflow: + return "errSSLBufferOverflow"; + case errSSLBadCipherSuite: + return "errSSLBadCipherSuite"; + /* TLS/Panther addenda */ + case errSSLPeerUnexpectedMsg: + return "errSSLPeerUnexpectedMsg"; + case errSSLPeerBadRecordMac: + return "errSSLPeerBadRecordMac"; + case errSSLPeerDecryptionFail: + return "errSSLPeerDecryptionFail"; + case errSSLPeerRecordOverflow: + return "errSSLPeerRecordOverflow"; + case errSSLPeerDecompressFail: + return "errSSLPeerDecompressFail"; + case errSSLPeerHandshakeFail: + return "errSSLPeerHandshakeFail"; + case errSSLPeerBadCert: + return "errSSLPeerBadCert"; + case errSSLPeerUnsupportedCert: + return "errSSLPeerUnsupportedCert"; + case errSSLPeerCertRevoked: + return "errSSLPeerCertRevoked"; + case errSSLPeerCertExpired: + return "errSSLPeerCertExpired"; + case errSSLPeerCertUnknown: + return "errSSLPeerCertUnknown"; + case errSSLIllegalParam: + return "errSSLIllegalParam"; + case errSSLPeerUnknownCA: + return "errSSLPeerUnknownCA"; + case errSSLPeerAccessDenied: + return "errSSLPeerAccessDenied"; + case errSSLPeerDecodeError: + return "errSSLPeerDecodeError"; + case errSSLPeerDecryptError: + return "errSSLPeerDecryptError"; + case errSSLPeerExportRestriction: + return "errSSLPeerExportRestriction"; + case errSSLPeerProtocolVersion: + return "errSSLPeerProtocolVersion"; + case errSSLPeerInsufficientSecurity: + return "errSSLPeerInsufficientSecurity"; + case errSSLPeerInternalError: + return "errSSLPeerInternalError"; + case errSSLPeerUserCancelled: + return "errSSLPeerUserCancelled"; + case errSSLPeerNoRenegotiation: + return "errSSLPeerNoRenegotiation"; + case errSSLHostNameMismatch: + return "errSSLHostNameMismatch"; + case errSSLConnectionRefused: + return "errSSLConnectionRefused"; + case errSSLDecryptionFail: + return "errSSLDecryptionFail"; + case errSSLBadRecordMac: + return "errSSLBadRecordMac"; + case errSSLRecordOverflow: + return "errSSLRecordOverflow"; + case errSSLBadConfiguration: + return "errSSLBadConfiguration"; + + /* some from the Sec layer */ + case errSecNotAvailable: return "errSecNotAvailable"; + case errSecDuplicateItem: return "errSecDuplicateItem"; + case errSecItemNotFound: return "errSecItemNotFound"; +#if 0 + case errSessionInvalidId: return "errSessionInvalidId"; + case errSessionInvalidAttributes: return "errSessionInvalidAttributes"; + case errSessionAuthorizationDenied: return "errSessionAuthorizationDenied"; + case errSessionInternal: return "errSessionInternal"; + case errSessionInvalidFlags: return "errSessionInvalidFlags"; +#endif + + default: +#if 0 + if (err < (CSSM_BASE_ERROR + + (CSSM_ERRORCODE_MODULE_EXTENT * 8))) + { + /* assume CSSM error */ + return cssmErrToStr(err); + } + else +#endif + { + sprintf(errSecSuccessStr, "Unknown (%d)", (unsigned)err); + return errSecSuccessStr; + } + } +} + +void printSslErrStr( + const char *op, + OSStatus err) +{ + printf("*** %s: %s\n", op, sslGetSSLErrString(err)); +} + +const char *sslGetClientCertStateString(SSLClientCertificateState state) +{ + static char noState[20]; + + switch(state) { + case kSSLClientCertNone: + return "ClientCertNone"; + case kSSLClientCertRequested: + return "CertRequested"; + case kSSLClientCertSent: + return "ClientCertSent"; + case kSSLClientCertRejected: + return "ClientCertRejected"; + default: + sprintf(noState, "Unknown (%d)", (unsigned)state); + return noState; + } + +} + +/* + * Convert a keychain name (which may be NULL) into the CFArrayRef required + * by SSLSetCertificate. This is a bare-bones example of this operation, + * since it requires and assumes that there is exactly one SecIdentity + * in the keychain - i.e., there is exactly one matching cert/private key + * pair. A real world server would probably search a keychain for a SecIdentity + * matching some specific criteria. + */ +CFArrayRef getSslCerts( + const char *kcName, // may be NULL, i.e., use default + bool encryptOnly, + bool completeCertChain, + const char *anchorFile, // optional trusted anchor + SecKeychainRef *pKcRef) // RETURNED +{ +#if 0 + SecKeychainRef kcRef = nil; + OSStatus ortn; + + *pKcRef = nil; + + /* pick a keychain */ + if(kcName) { + ortn = SecKeychainOpen(kcName, &kcRef); + if(ortn) { + printf("SecKeychainOpen returned %d.\n", (int)ortn); + printf("Cannot open keychain at %s. Aborting.\n", kcName); + return NULL; + } + } + else { + /* use default keychain */ + ortn = SecKeychainCopyDefault(&kcRef); + if(ortn) { + printf("SecKeychainCopyDefault returned %d; aborting.\n", (int)ortn); + return nil; + } + } + *pKcRef = kcRef; + return sslKcRefToCertArray(kcRef, encryptOnly, completeCertChain, anchorFile); +#else + SecCertificateRef cert = NULL; + SecIdentityRef identity = NULL; + CFMutableArrayRef certificates = NULL, result = NULL; + CFMutableDictionaryRef certQuery = NULL, keyQuery = NULL, keyResult = NULL; + SecTrustRef trust = NULL; + SecKeyRef key = NULL; + CFTypeRef pkdigest = NULL; + + // Find the first private key in the keychain and return both it's + // attributes and a ref to it. + require(keyQuery = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut); + CFDictionaryAddValue(keyQuery, kSecClass, kSecClassKey); + CFDictionaryAddValue(keyQuery, kSecAttrKeyClass, kSecAttrKeyClassPrivate); + CFDictionaryAddValue(keyQuery, kSecReturnRef, kCFBooleanTrue); + CFDictionaryAddValue(keyQuery, kSecReturnAttributes, kCFBooleanTrue); + require_noerr(SecItemCopyMatching(keyQuery, (CFTypeRef *)&keyResult), + errOut); + require(key = (SecKeyRef)CFDictionaryGetValue(keyResult, kSecValueRef), + errOut); + require(pkdigest = CFDictionaryGetValue(keyResult, kSecAttrApplicationLabel), + errOut); + + // Find the first certificate that has the same public key hash as the + // returned private key and return it as a ref. + require(certQuery = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut); + CFDictionaryAddValue(certQuery, kSecClass, kSecClassCertificate); + CFDictionaryAddValue(certQuery, kSecAttrPublicKeyHash, pkdigest); + CFDictionaryAddValue(certQuery, kSecReturnRef, kCFBooleanTrue); + require_noerr(SecItemCopyMatching(certQuery, (CFTypeRef *)&cert), errOut); + + // Create an identity from the key and certificate. + require(identity = SecIdentityCreate(NULL, cert, key), errOut); + + // Build a (partial) certificate chain from cert + require(certificates = CFArrayCreateMutable(NULL, 0, + &kCFTypeArrayCallBacks), errOut); + CFArrayAppendValue(certificates, cert); + require_noerr(SecTrustCreateWithCertificates(certificates, NULL, &trust), + errOut); + SecTrustResultType tresult; + require_noerr(SecTrustEvaluate(trust, &tresult), errOut); + + CFIndex certCount, ix; + // We need at least 1 certificate + require(certCount = SecTrustGetCertificateCount(trust), errOut); + + // Build a result where element 0 is the identity and the other elements + // are the certs in the chain starting at the first intermediate up to the + // anchor, if we found one, or as far as we were able to build the chain + // if not. + require(result = CFArrayCreateMutable(NULL, certCount, &kCFTypeArrayCallBacks), + errOut); + + // We are commited to returning a result now, so do not use require below + // this line without setting result to NULL again. + CFArrayAppendValue(result, identity); + for (ix = 1; ix < certCount; ++ix) { + CFArrayAppendValue(result, SecTrustGetCertificateAtIndex(trust, ix)); + } + +errOut: + CFReleaseSafe(trust); + CFReleaseSafe(certificates); + CFReleaseSafe(identity); + CFReleaseSafe(cert); + CFReleaseSafe(certQuery); + CFReleaseSafe(keyResult); + CFReleaseSafe(keyQuery); + + return result; +#endif +} + +#if 0 +/* + * Determine if specified SecCertificateRef is a self-signed cert. + * We do this by comparing the subject and issuerr names; no cryptographic + * verification is performed. + * + * Returns true if the cert appears to be a root. + */ +static bool isCertRefRoot( + SecCertificateRef certRef) +{ + bool brtn = false; +#if 0 + /* just search for the two attrs we want */ + UInt32 tags[2] = {kSecSubjectItemAttr, kSecIssuerItemAttr}; + SecKeychainAttributeInfo attrInfo; + attrInfo.count = 2; + attrInfo.tag = tags; + attrInfo.format = NULL; + SecKeychainAttributeList *attrList = NULL; + SecKeychainAttribute *attr1 = NULL; + SecKeychainAttribute *attr2 = NULL; + + OSStatus ortn = SecKeychainItemCopyAttributesAndData( + (SecKeychainItemRef)certRef, + &attrInfo, + NULL, // itemClass + &attrList, + NULL, // length - don't need the data + NULL); // outData + if(ortn) { + cssmPerror("SecKeychainItemCopyAttributesAndData", ortn); + /* may want to be a bit more robust here, but this should + * never happen */ + return false; + } + /* subsequent errors to errOut: */ + + if((attrList == NULL) || (attrList->count != 2)) { + printf("***Unexpected result fetching label attr\n"); + goto errOut; + } + + /* rootness is just byte-for-byte compare of the two names */ + attr1 = &attrList->attr[0]; + attr2 = &attrList->attr[1]; + if(attr1->length == attr2->length) { + if(memcmp(attr1->data, attr2->data, attr1->length) == 0) { + brtn = true; + } + } +errOut: + SecKeychainItemFreeAttributesAndData(attrList, NULL); +#endif + return brtn; +} +#endif + +#if 0 +/* + * Given a SecIdentityRef, do our best to construct a complete, ordered, and + * verified cert chain, returning the result in a CFArrayRef. The result is + * suitable for use when calling SSLSetCertificate(). + */ +OSStatus sslCompleteCertChain( + SecIdentityRef identity, + SecCertificateRef trustedAnchor, // optional additional trusted anchor + bool includeRoot, // include the root in outArray + CFArrayRef *outArray) // created and RETURNED +{ + CFMutableArrayRef certArray; + SecTrustRef secTrust = NULL; + SecPolicyRef policy = NULL; + SecPolicySearchRef policySearch = NULL; + SecTrustResultType secTrustResult; + CSSM_TP_APPLE_EVIDENCE_INFO *dummyEv; // not used + CFArrayRef certChain = NULL; // constructed chain + CFIndex numResCerts; + + certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(certArray, identity); + + /* + * Case 1: identity is a root; we're done. Note that this case + * overrides the includeRoot argument. + */ + SecCertificateRef certRef; + OSStatus ortn = SecIdentityCopyCertificate(identity, &certRef); + if(ortn) { + /* should never happen */ + cssmPerror("SecIdentityCopyCertificate", ortn); + return ortn; + } + bool isRoot = isCertRefRoot(certRef); + if(isRoot) { + *outArray = certArray; + CFRelease(certRef); + return errSecSuccess; + } + + /* + * Now use SecTrust to get a complete cert chain, using all of the + * user's keychains to look for intermediate certs. + * NOTE this does NOT handle root certs which are not in the system + * root cert DB. (The above case, where the identity is a root cert, does.) + */ + CFMutableArrayRef subjCerts = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks); + CFArraySetValueAtIndex(subjCerts, 0, certRef); + + /* the array owns the subject cert ref now */ + CFRelease(certRef); + + /* Get a SecPolicyRef for generic X509 cert chain verification */ + ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3, + &CSSMOID_APPLE_X509_BASIC, + NULL, // value + &policySearch); + if(ortn) { + cssmPerror("SecPolicySearchCreate", ortn); + goto errOut; + } + ortn = SecPolicySearchCopyNext(policySearch, &policy); + if(ortn) { + cssmPerror("SecPolicySearchCopyNext", ortn); + goto errOut; + } + + /* build a SecTrustRef for specified policy and certs */ + ortn = SecTrustCreateWithCertificates(subjCerts, + policy, &secTrust); + if(ortn) { + cssmPerror("SecTrustCreateWithCertificates", ortn); + goto errOut; + } + + if(trustedAnchor) { + /* + * Tell SecTrust to trust this one in addition to the current + * trusted system-wide anchors. + */ + CFMutableArrayRef newAnchors; + CFArrayRef currAnchors; + + ortn = SecTrustCopyAnchorCertificates(&currAnchors); + if(ortn) { + /* should never happen */ + cssmPerror("SecTrustCopyAnchorCertificates", ortn); + goto errOut; + } + newAnchors = CFArrayCreateMutableCopy(NULL, + CFArrayGetCount(currAnchors) + 1, + currAnchors); + CFRelease(currAnchors); + CFArrayAppendValue(newAnchors, trustedAnchor); + ortn = SecTrustSetAnchorCertificates(secTrust, newAnchors); + CFRelease(newAnchors); + if(ortn) { + cssmPerror("SecTrustSetAnchorCertificates", ortn); + goto errOut; + } + } + /* evaluate: GO */ + ortn = SecTrustEvaluate(secTrust, &secTrustResult); + if(ortn) { + cssmPerror("SecTrustEvaluate", ortn); + goto errOut; + } + switch(secTrustResult) { + case kSecTrustResultUnspecified: + /* cert chain valid, no special UserTrust assignments */ + case kSecTrustResultProceed: + /* cert chain valid AND user explicitly trusts this */ + break; + default: + /* + * Cert chain construction failed. + * Just go with the single subject cert we were given. + */ + printf("***Warning: could not construct completed cert chain\n"); + ortn = errSecSuccess; + goto errOut; + } + + /* get resulting constructed cert chain */ + ortn = SecTrustGetResult(secTrust, &secTrustResult, &certChain, &dummyEv); + if(ortn) { + cssmPerror("SecTrustEvaluate", ortn); + goto errOut; + } + + /* + * Copy certs from constructed chain to our result array, skipping + * the leaf (which is already there, as a SecIdentityRef) and possibly + * a root. + */ + numResCerts = CFArrayGetCount(certChain); + if(numResCerts < 2) { + /* + * Can't happen: if subject was a root, we'd already have returned. + * If chain doesn't verify to a root, we'd have bailed after + * SecTrustEvaluate(). + */ + printf("***sslCompleteCertChain screwup: numResCerts %d\n", + (int)numResCerts); + ortn = errSecSuccess; + goto errOut; + } + if(!includeRoot) { + /* skip the last (root) cert) */ + numResCerts--; + } + for(CFIndex dex=1; dexacceptedProts) { + printf(" Allowed SSL versions : %s\n", params->acceptedProts); + } + else { + printf(" Attempted SSL version : %s\n", + sslGetProtocolVersionString(params->tryVersion)); + } + printf(" Result : %s\n", sslGetSSLErrString(params->ortn)); + printf(" Negotiated SSL version : %s\n", + sslGetProtocolVersionString(params->negVersion)); + printf(" Negotiated CipherSuite : %s\n", + sslGetCipherSuiteString(params->negCipher)); + if(params->certState != kSSLClientCertNone) { + printf(" Client Cert State : %s\n", + sslGetClientCertStateString(params->certState)); + } +} +#endif + +/* print a '.' every few seconds to keep UI alive while connecting */ +static time_t lastTime = (time_t)0; +#define TIME_INTERVAL 3 + +void sslOutputDot() +{ + time_t thisTime = time(0); + + if((thisTime - lastTime) >= TIME_INTERVAL) { + printf("."); fflush(stdout); + lastTime = thisTime; + } +} + +#if 0 +/* main server pthread body */ +static void *sslServerThread(void *arg) +{ + SslAppTestParams *testParams = (SslAppTestParams *)arg; + OSStatus status; + + status = sslAppServe(testParams); + pthread_exit((void*)status); + /* NOT REACHED */ + return (void *)status; +} + +/* + * Run one session, with the server in a separate thread. + * On entry, serverParams->port is the port we attempt to run on; + * the server thread may overwrite that with a different port if it's + * unable to open the port we specify. Whatever is left in + * serverParams->port is what's used for the client side. + */ +#define CLIENT_WAIT_SECONDS 1 +int sslRunSession( + SslAppTestParams*serverParams, + SslAppTestParams *clientParams, + const char *testDesc) +{ + pthread_t serverPthread; + OSStatus clientRtn; + void *serverRtn; + + if(testDesc && !clientParams->quiet) { + printf("===== %s =====\n", testDesc); + } + + if(pthread_mutex_init(&serverParams->pthreadMutex, NULL)) { + printf("***Error initializing mutex; aborting.\n"); + return -1; + } + if(pthread_cond_init(&serverParams->pthreadCond, NULL)) { + printf("***Error initializing pthreadCond; aborting.\n"); + return -1; + } + serverParams->serverReady = false; // server sets true + + int result = pthread_create(&serverPthread, NULL, + sslServerThread, serverParams); + if(result) { + printf("***Error starting up server thread; aborting.\n"); + return result; + } + + /* wait for server to set up a socket we can connect to */ + if(pthread_mutex_lock(&serverParams->pthreadMutex)) { + printf("***Error acquiring server lock; aborting.\n"); + return -1; + } + while(!serverParams->serverReady) { + if(pthread_cond_wait(&serverParams->pthreadCond, &serverParams->pthreadMutex)) { + printf("***Error waiting server thread; aborting.\n"); + return -1; + } + } + pthread_mutex_unlock(&serverParams->pthreadMutex); + pthread_cond_destroy(&serverParams->pthreadCond); + pthread_mutex_destroy(&serverParams->pthreadMutex); + + clientParams->port = serverParams->port; + clientRtn = sslAppClient(clientParams); + /* server doesn't shut down its socket until it sees this */ + serverParams->clientDone = 1; + result = pthread_join(serverPthread, &serverRtn); + if(result) { + printf("***pthread_join returned %d, aborting\n", result); + return result; + } + + if(serverParams->verbose) { + sslShowResult("server", serverParams); + } + if(clientParams->verbose) { + sslShowResult("client", clientParams); + } + + /* verify results */ + int ourRtn = 0; + ourRtn += sslVerifyRtn("server", serverParams->expectRtn, serverParams->ortn); + ourRtn += sslVerifyRtn("client", clientParams->expectRtn, clientParams->ortn); + ourRtn += sslVerifyProtVers("server", serverParams->expectVersion, + serverParams->negVersion); + ourRtn += sslVerifyProtVers("client", clientParams->expectVersion, + clientParams->negVersion); + ourRtn += sslVerifyClientCertState("server", serverParams->expectCertState, + serverParams->certState); + ourRtn += sslVerifyClientCertState("client", clientParams->expectCertState, + clientParams->certState); + if(serverParams->ortn == errSecSuccess) { + ourRtn += sslVerifyCipher("server", serverParams->expectCipher, + serverParams->negCipher); + } + if(clientParams->ortn == errSecSuccess) { + ourRtn += sslVerifyCipher("client", clientParams->expectCipher, + clientParams->negCipher); + } + return ourRtn; +} + +static bool isCertRoot( + SecCertificateRef cert) +{ + /* FIXME - per Radar 3247491, the Sec-level functions we'd like to use for this + * haven't been written yet... + CSSM_X509_NAME subject; + CSSM_X509_NAME issuer; + OSStatus ortn; + ... */ + return true; +} + +/* + * Add all of the roots in a given KC to SSL ctx's trusted anchors. + */ +OSStatus sslAddTrustedRoots( + SSLContextRef ctx, + SecKeychainRef keychain, + bool *foundOne) // RETURNED, true if we found + // at least one root cert +{ + OSStatus ortn; + SecCertificateRef secCert; + SecKeychainSearchRef srch; + + *foundOne = false; + ortn = SecKeychainSearchCreateFromAttributes(keychain, + kSecCertificateItemClass, + NULL, // any attrs + &srch); + if(ortn) { + printSslErrStr("SecKeychainSearchCreateFromAttributes", ortn); + return ortn; + } + + /* + * Only use root certs. Not an error if we don't find any. + */ + do { + ortn = SecKeychainSearchCopyNext(srch, + (SecKeychainItemRef *)&secCert); + if(ortn) { + break; + } + + /* see if it's a root */ + if(!isCertRoot(secCert)) { + continue; + } + + /* Tell Secure Transport to trust this one. */ + ortn = addTrustedSecCert(ctx, secCert, false); + if(ortn) { + /* fatal */ + printSslErrStr("addTrustedSecCert", ortn); + return ortn; + } + CFRelease(secCert); + *foundOne = true; + } while(ortn == errSecSuccess); + CFRelease(srch); + return errSecSuccess; +} + +/* + * Wrapper for sslIdentPicker, with optional trusted anchor specified as a filename. + */ +OSStatus sslIdentityPicker( + SecKeychainRef kcRef, // NULL means use default list + const char *trustedAnchor, // optional additional trusted anchor + bool includeRoot, // true --> root is appended to outArray + // false --> root not included + CFArrayRef *outArray) // created and RETURNED +{ + SecCertificateRef trustedCert = NULL; + OSStatus ortn; + + if(trustedAnchor) { + ortn = sslReadAnchor(trustedAnchor, &trustedCert); + if(ortn) { + printf("***Error reading %s. sslIdentityPicker proceeding with no anchor.\n", + trustedAnchor); + trustedCert = NULL; + } + } + ortn = sslIdentPicker(kcRef, trustedCert, includeRoot, outArray); + if(trustedCert) { + CFRelease(trustedCert); + } + return ortn; +} + +/* + * Given a keychain name, convert it into a full path using the "SSL regression + * test suite algorithm". The Sec layer by default locates root root's keychains + * in different places depending on whether we're actually logged in as root + * or running via e.g. cron, so we force the location of root keychains to + * a hard-coded path. User keychain names we leave alone. + */ +void sslKeychainPath( + const char *kcName, + char *kcPath) // allocd by caller, MAXPATHLEN +{ + if(kcName[0] == '\0') { + kcPath[0] = '\0'; + } + else if(geteuid() == 0) { + /* root */ + sprintf(kcPath, "/Library/Keychains/%s", kcName); + } + else { + /* user, leave alone */ + strcpy(kcPath, kcName); + } +} + +/* Verify presence of required file. Returns nonzero if not found. */ +int sslCheckFile(const char *path) +{ + struct stat sb; + + if(stat(path, &sb)) { + printf("***Can't find file %s.\n", path); + printf(" Try running in the build directory, perhaps after running the\n" + " makeLocalCert script.\n"); + return 1; + } + return 0; +} + +#endif + +/* Stringify a SSL_ECDSA_NamedCurve */ +extern const char *sslCurveString( + SSL_ECDSA_NamedCurve namedCurve) +{ + static char unk[100]; + + switch(namedCurve) { + case SSL_Curve_None: return "Curve_None"; + case SSL_Curve_secp256r1: return "secp256r1"; + case SSL_Curve_secp384r1: return "secp384r1"; + case SSL_Curve_secp521r1: return "secp521r1"; + default: + sprintf(unk, "Unknown <%d>", (int)namedCurve); + return unk; + } +} diff --git a/sslViewer/sslAppUtils.h b/sslViewer/sslAppUtils.h new file mode 100644 index 00000000..65361483 --- /dev/null +++ b/sslViewer/sslAppUtils.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2006-2008,2010 Apple Inc. All Rights Reserved. + */ + +#ifndef _SSLS_APP_UTILS_H_ +#define _SSLS_APP_UTILS_H_ 1 + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct OpaqueSecKeychainRef *SecKeychainRef; + +/* disable some Panther-only features */ +#define JAGUAR_BUILD 0 + +const char *sslGetCipherSuiteString(SSLCipherSuite cs); +const char *sslGetProtocolVersionString(SSLProtocol prot); +const char *sslGetSSLErrString(OSStatus err); +void printSslErrStr(const char *op, OSStatus err); +const char *sslGetClientCertStateString(SSLClientCertificateState state); +const char *sslGetClientAuthTypeString(SSLClientAuthenticationType authType); + +CFArrayRef getSslCerts( + const char *kcName, // may be NULL, i.e., use default + bool encryptOnly, + bool completeCertChain, + const char *anchorFile, // optional trusted anchor + SecKeychainRef *pKcRef); // RETURNED +OSStatus sslCompleteCertChain( + SecIdentityRef identity, + SecCertificateRef trustedAnchor, // optional additional trusted anchor + bool includeRoot, // include the root in outArray +// const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL + CFArrayRef *outArray); // created and RETURNED +CFArrayRef sslKcRefToCertArray( + SecKeychainRef kcRef, + bool encryptOnly, + bool completeCertChain, +// const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL policy to complete + const char *trustedAnchorFile); + +OSStatus addTrustedSecCert( + SSLContextRef ctx, + SecCertificateRef secCert, + bool replaceAnchors); +OSStatus sslReadAnchor( + const char *anchorFile, + SecCertificateRef *certRef); +OSStatus sslAddTrustedRoot( + SSLContextRef ctx, + const char *anchorFile, + bool replaceAnchors); + +/* + * Assume incoming identity contains a root (e.g., created by + * certtool) and add that cert to ST's trusted anchors. This + * enables ST's verify of the incoming chain to succeed without + * a kludgy "AllowAnyRoot" specification. + */ +OSStatus addIdentityAsTrustedRoot( + SSLContextRef ctx, + CFArrayRef identArray); + +OSStatus sslAddTrustedRoots( + SSLContextRef ctx, + SecKeychainRef keychain, + bool *foundOne); + +void sslOutputDot(); + +/* + * Lists of SSLCipherSuites used in sslSetCipherRestrictions. + */ +extern const SSLCipherSuite suites40[]; +extern const SSLCipherSuite suitesDES[]; +extern const SSLCipherSuite suitesDES40[]; +extern const SSLCipherSuite suites3DES[]; +extern const SSLCipherSuite suitesRC4[]; +extern const SSLCipherSuite suitesRC4_40[]; +extern const SSLCipherSuite suitesRC2[]; +extern const SSLCipherSuite suitesAES128[]; +extern const SSLCipherSuite suitesAES256[]; +extern const SSLCipherSuite suitesDH[]; +extern const SSLCipherSuite suitesDHAnon[]; +extern const SSLCipherSuite suitesDH_RSA[]; +extern const SSLCipherSuite suitesDH_DSS[]; +extern const SSLCipherSuite suites_SHA1[]; +extern const SSLCipherSuite suites_MD5[]; +extern const SSLCipherSuite suites_ECDHE[]; +extern const SSLCipherSuite suites_ECDH[]; + +/* + * Given an SSLContextRef and an array of SSLCipherSuites, terminated by + * SSL_NO_SUCH_CIPHERSUITE, select those SSLCipherSuites which the library + * supports and do a SSLSetEnabledCiphers() specifying those. + */ +OSStatus sslSetEnabledCiphers( + SSLContextRef ctx, + const SSLCipherSuite *ciphers); + +/* + * Specify restricted sets of cipherspecs and protocols. + */ +OSStatus sslSetCipherRestrictions( + SSLContextRef ctx, + char cipherRestrict); + +#ifndef SPHINX +OSStatus sslSetProtocols( + SSLContextRef ctx, + const char *acceptedProts, + SSLProtocol tryVersion); // only used if acceptedProts NULL +#endif + +int sslVerifyRtn( + const char *whichSide, // "client" or "server" + OSStatus expectRtn, + OSStatus gotRtn); +int sslVerifyProtVers( + const char *whichSide, // "client" or "server" + SSLProtocol expectProt, + SSLProtocol gotProt); +int sslVerifyClientCertState( + const char *whichSide, // "client" or "server" + SSLClientCertificateState expectState, + SSLClientCertificateState gotState); +int sslVerifyCipher( + const char *whichSide, // "client" or "server" + SSLCipherSuite expectCipher, + SSLCipherSuite gotCipher); + + +/* + * Wrapper for sslIdentPicker, with optional trusted anchor specified as a filename. + */ +OSStatus sslIdentityPicker( + SecKeychainRef kcRef, // NULL means use default list + const char *trustedAnchor, // optional additional trusted anchor + bool includeRoot, // true --> root is appended to outArray + // false --> root not included +// const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL + CFArrayRef *outArray); // created and RETURNED + +void sslKeychainPath( + const char *kcName, + char *kcPath); // allocd by caller, MAXPATHLEN + +/* Verify presence of required file. Returns nonzero if not found. */ +int sslCheckFile(const char *path); + +/* Stringify a SSL_ECDSA_NamedCurve */ +extern const char *sslCurveString( + SSL_ECDSA_NamedCurve namedCurve); + +#ifdef __cplusplus +} +#endif + +#endif /* _SSLS_APP_UTILS_H_ */ diff --git a/sslViewer/sslClient.cpp b/sslViewer/sslClient.cpp new file mode 100644 index 00000000..24edd7bf --- /dev/null +++ b/sslViewer/sslClient.cpp @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2006-2008,2010-2011,2013 Apple Inc. All Rights Reserved. + * + * sslClient.cpp : perform one SSL client side sesssion + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +/* when true, keep listening until server disconnects */ +#define KEEP_CONNECTED 1 + +#define CLIENT_GETMSG "GET / HTTP/1.0\r\n\r\n" + +#define READBUF_LEN 256 + +/* relies on SSLSetProtocolVersionEnabled */ +OSStatus sslAppClient( + SslAppTestParams *params) +{ + PeerSpec peerId; + otSocket sock = 0; + OSStatus ortn; + SSLContextRef ctx = NULL; + SecKeychainRef clientKc = nil; + CFArrayRef clientCerts = nil; + + sslThrDebug("Client", "starting"); + params->negVersion = kSSLProtocolUnknown; + params->negCipher = SSL_NULL_WITH_NULL_NULL; + params->ortn = noHardwareErr; + + /* first make sure requested server is there */ + ortn = MakeServerConnection(params->hostName, params->port, + params->nonBlocking, &sock, &peerId); + if(ortn) { + printf("MakeServerConnection returned %d; aborting\n", (int)ortn); + return ortn; + } + + /* + * Set up a SecureTransport session. + */ + ortn = SSLNewContext(false, &ctx); + if(ortn) { + printSslErrStr("SSLNewContext", ortn); + goto cleanup; + } + ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite); + if(ortn) { + printSslErrStr("SSLSetIOFuncs", ortn); + goto cleanup; + } + ortn = SSLSetConnection(ctx, (SSLConnectionRef)sock); + if(ortn) { + printSslErrStr("SSLSetConnection", ortn); + goto cleanup; + } + if(!params->skipHostNameCheck) { + ortn = SSLSetPeerDomainName(ctx, params->hostName, + strlen(params->hostName)); + if(ortn) { + printSslErrStr("SSLSetPeerDomainName", ortn); + goto cleanup; + } + } + + /* remainder of setup is optional */ + if(params->anchorFile) { + ortn = sslAddTrustedRoot(ctx, params->anchorFile, params->replaceAnchors); + if(ortn) { + goto cleanup; + } + } + ortn = sslSetProtocols(ctx, params->acceptedProts, params->tryVersion); + if(ortn) { + goto cleanup; + } + if(params->resumeEnable) { + ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec)); + if(ortn) { + printSslErrStr("SSLSetPeerID", ortn); + goto cleanup; + } + } + if(params->disableCertVerify) { + ortn = SSLSetEnableCertVerify(ctx, false); + if(ortn) { + printSslErrStr("SSLSetEnableCertVerify", ortn); + goto cleanup; + } + } + if(params->ciphers != NULL) { + ortn = sslSetEnabledCiphers(ctx, params->ciphers); + if(ortn) { + goto cleanup; + } + } + if(params->myCertKcName) { + clientCerts = getSslCerts(params->myCertKcName, false, false, NULL, &clientKc); + if(clientCerts == nil) { + exit(1); + } + if(params->password) { + ortn = SecKeychainUnlock(clientKc, strlen(params->password), + (void *)params->password, true); + if(ortn) { + printf("SecKeychainUnlock returned %d\n", (int)ortn); + /* oh well */ + } + } + if(params->idIsTrustedRoot) { + /* assume this is a root we want to implicitly trust */ + ortn = addIdentityAsTrustedRoot(ctx, clientCerts); + if(ortn) { + goto cleanup; + } + } + ortn = SSLSetCertificate(ctx, clientCerts); + if(ortn) { + printSslErrStr("SSLSetCertificate", ortn); + goto cleanup; + } + } + do { + ortn = SSLHandshake(ctx); + if((ortn == errSSLWouldBlock) && !params->silent) { + /* keep UI responsive */ + sslOutputDot(); + } + } while (ortn == errSSLWouldBlock); + + SSLGetClientCertificateState(ctx, ¶ms->certState); + SSLGetNegotiatedCipher(ctx, ¶ms->negCipher); + SSLGetNegotiatedProtocolVersion(ctx, ¶ms->negVersion); + + if(ortn != errSecSuccess) { + goto cleanup; + } + + /* send a GET msg */ + size_t actLen; + ortn = SSLWrite(ctx, CLIENT_GETMSG, strlen(CLIENT_GETMSG), &actLen); + if(ortn) { + printSslErrStr("SSLWrite", ortn); + goto cleanup; + } + + #if KEEP_CONNECTED + + /* + * Consume any server data and wait for server to disconnect + */ + char readBuf[READBUF_LEN]; + do { + ortn = SSLRead(ctx, readBuf, READBUF_LEN, &actLen); + } while (ortn == errSSLWouldBlock); + + /* convert normal "shutdown" into zero err rtn */ + if(ortn == errSSLClosedGraceful) { + ortn = errSecSuccess; + } + #endif /* KEEP_CONNECTED */ + +cleanup: + if(ctx) { + OSStatus cerr = SSLClose(ctx); + if(ortn == errSecSuccess) { + ortn = cerr; + } + } + if(sock) { + endpointShutdown(sock); + } + if(ctx) { + SSLDisposeContext(ctx); + } + params->ortn = ortn; + sslThrDebug("Client", "done"); + return ortn; +} diff --git a/sslViewer/sslEcdsa.cpp b/sslViewer/sslEcdsa.cpp new file mode 100644 index 00000000..1ac49397 --- /dev/null +++ b/sslViewer/sslEcdsa.cpp @@ -0,0 +1,646 @@ +/* + * sslEcdsa.cpp - test SSL connections to a number of known servers. + * + * Note this uses the keychain ecdsa.keychain in cwd; it contains an + * SSL client auth identity. To avoid ACL hassles and to allow this + * program to run hands-off, the identity is imported into this keychain + * with no ACL on the private key. This is done with the kcImport tool + * like so: + * + * % kcImport ecc-secp256r1-client.pfx -k ___path_to_cwd___/ecdsa.keychain -f pkcs12 -z password -n + */ +#include +#include +#include +#include "sslAppUtils.h" +#include "ioSock.h" +//#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#if NO_SERVER +#include +#endif + + +static void usage(char **argv) +{ + printf("Usage: %s [options]\n", argv[0]); + printf("options:\n"); + printf(" -t testNum -- only do test testNum; default is all\n"); + printf(" -q -- quiet\n"); + printf(" -b -- non blocking I/O\n"); + printf(" -p -- pause for malloc debug\n"); + exit(1); +} + +#define IGNORE_SIGPIPE 1 +#if IGNORE_SIGPIPE +#include + +static void sigpipe(int sig) +{ +} +#endif /* IGNORE_SIGPIPE */ + +/* Test params */ +typedef struct { + const char *hostName; + int port; + + /* We enable exacly one CipherSuite and require that to work */ + SSLCipherSuite cipherSuite; + + /* Curve to specify; SSL_Curve_None means use default */ + SSL_ECDSA_NamedCurve specCurve; + + /* Curve to verify; SSL_Curve_None means don't check */ + SSL_ECDSA_NamedCurve expCurve; + + /* + * keychain containing client-side cert, located in LOCAL_BUILD_DIR. + * NULL means no keychain. + */ + const char *keychain; + + /* password for above keychain */ + const char *kcPassword; +} EcdsaTestParams; + +static const EcdsaTestParams ecdsaTestParams[] = +{ + /* client auth */ + { + "tls.secg.org", 8443, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + SSL_Curve_None, SSL_Curve_None, + "ecdsa.keychain", "password" + }, + /* tla.secg.org -- port 40023 - secp256r1 */ + { + "tls.secg.org", 40023, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp256r1 + }, + { + "tls.secg.org", 40023, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + SSL_Curve_secp256r1, SSL_Curve_secp256r1 + }, + { + "tls.secg.org", 40023, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp256r1 + }, + { + "tls.secg.org", 40023, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + SSL_Curve_None, SSL_Curve_secp256r1 + }, + { + "tls.secg.org", 40023, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp256r1 + }, + { + "tls.secg.org", 40023, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp256r1 + }, + { + "tls.secg.org", 40023, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp256r1 + }, + { + "tls.secg.org", 40023, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + SSL_Curve_secp256r1, SSL_Curve_secp256r1 + }, + { + "tls.secg.org", 40023, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, + SSL_Curve_None, SSL_Curve_secp256r1 + }, + { + "tls.secg.org", 40023, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp256r1 + }, + { + "tls.secg.org", 40023, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + SSL_Curve_secp256r1, SSL_Curve_secp256r1 + }, + + /* tla.secg.org -- port 40024 - secp384r1 */ + /* This one doesn't let you specify a curve */ + { + "tls.secg.org", 40024, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp384r1 + }, + { + "tls.secg.org", 40024, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp384r1 + }, + { + "tls.secg.org", 40024, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + SSL_Curve_None, SSL_Curve_secp384r1 + }, + { + "tls.secg.org", 40024, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp384r1 + }, + { + "tls.secg.org", 40024, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp384r1 + }, + { + "tls.secg.org", 40024, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp384r1 + }, + { + "tls.secg.org", 40024, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, + SSL_Curve_None, SSL_Curve_secp384r1 + }, + { + "tls.secg.org", 40024, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp384r1 + }, + + /* tla.secg.org -- port 40025 - secp521r1 */ + { + "tls.secg.org", 40025, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp521r1 + }, + { + "tls.secg.org", 40025, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp521r1 + }, + { + "tls.secg.org", 40025, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + SSL_Curve_None, SSL_Curve_secp521r1 + }, + { + "tls.secg.org", 40025, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp521r1 + }, + { + "tls.secg.org", 40025, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp521r1 + }, + { + "tls.secg.org", 40025, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp521r1 + }, + { + "tls.secg.org", 40025, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, + SSL_Curve_None, SSL_Curve_secp521r1 + }, + { + "tls.secg.org", 40025, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp521r1 + }, + + + /* ecc.fedora.redhat.com - port 8443 - secp256r1 */ + { + "ecc.fedora.redhat.com", 8443, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp256r1 + }, + { + "ecc.fedora.redhat.com", 8443, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + SSL_Curve_secp256r1, SSL_Curve_secp256r1 + }, + { + "ecc.fedora.redhat.com", 8443, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + SSL_Curve_None, SSL_Curve_secp256r1 + }, + { + "ecc.fedora.redhat.com", 8443, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, + SSL_Curve_secp256r1, SSL_Curve_secp256r1 + }, + { + "ecc.fedora.redhat.com", 8443, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + SSL_Curve_secp256r1, SSL_Curve_secp256r1 + }, + { + "ecc.fedora.redhat.com", 8443, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp256r1 + }, + { + "ecc.fedora.redhat.com", 8443, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, + SSL_Curve_secp256r1, SSL_Curve_secp256r1 + }, + { + "ecc.fedora.redhat.com", 8443, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + SSL_Curve_secp256r1, SSL_Curve_secp256r1 + }, + + /* ecc.fedora.redhat.com - port 8444 - SSL_Curve_secp384r1 */ + /* This doesn't work, the server requires a redirect ... + { + "ecc.fedora.redhat.com", 8444, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp384r1 + }, + */ + { + "ecc.fedora.redhat.com", 8445, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp521r1 + }, + { + "ecc.fedora.redhat.com", 8444, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + SSL_Curve_secp384r1, SSL_Curve_secp384r1 + }, + { + "ecc.fedora.redhat.com", 8444, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, + SSL_Curve_secp384r1, SSL_Curve_secp384r1 + }, + { + "ecc.fedora.redhat.com", 8444, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp384r1 + }, + { + "ecc.fedora.redhat.com", 8444, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp384r1 + }, + { + "ecc.fedora.redhat.com", 8444, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, + SSL_Curve_secp384r1, SSL_Curve_secp384r1 + }, + { + "ecc.fedora.redhat.com", 8444, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + SSL_Curve_secp384r1, SSL_Curve_secp384r1 + }, + + /* ecc.fedora.redhat.com - port 8445 - SSL_Curve_secp521r1 */ + /* This one can't do RC4_128 without some HTTP redirection */ + { + "ecc.fedora.redhat.com", 8445, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp521r1 + }, + { + "ecc.fedora.redhat.com", 8445, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + SSL_Curve_secp521r1, SSL_Curve_secp521r1 + }, + { + "ecc.fedora.redhat.com", 8445, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + SSL_Curve_secp521r1, SSL_Curve_secp521r1 + }, + + /* ecc.fedora.redhat.com - port 443 - secp256r1 with RSA authentication */ + { + "ecc.fedora.redhat.com", 443, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + SSL_Curve_secp256r1, SSL_Curve_secp256r1 + }, + { + "ecc.fedora.redhat.com", 443, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + SSL_Curve_secp256r1, SSL_Curve_secp256r1 + }, + { + "ecc.fedora.redhat.com", 443, TLS_ECDHE_RSA_WITH_RC4_128_SHA, + SSL_Curve_secp256r1, SSL_Curve_secp256r1 + }, + { + "ecc.fedora.redhat.com", 443, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + SSL_Curve_secp256r1, SSL_Curve_secp256r1 + }, + { + "ecc.fedora.redhat.com", 443, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp256r1 + }, + { + "ecc.fedora.redhat.com", 443, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, + SSL_Curve_secp256r1, SSL_Curve_secp256r1 + }, + { + "ecc.fedora.redhat.com", 443, TLS_ECDH_RSA_WITH_RC4_128_SHA, + SSL_Curve_None, SSL_Curve_secp256r1 + }, + { + "ecc.fedora.redhat.com", 443, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, + SSL_Curve_None, SSL_Curve_secp256r1 + }, + + /* etc. */ +}; +#define NUM_TEST_PARAMS (sizeof(ecdsaTestParams) / sizeof(ecdsaTestParams[0])) + +static void dumpParams( + const EcdsaTestParams *testParams) +{ + printf("%s:%d %-33s ", + testParams->hostName, testParams->port, + /* skip leading "TLS_" */ + sslGetCipherSuiteString(testParams->cipherSuite)+4); + if(testParams->expCurve != SSL_Curve_None) { + printf("expCurve = %s ", sslCurveString(testParams->expCurve)); + } + if(testParams->specCurve != SSL_Curve_None) { + printf("specCurve = %s ", sslCurveString(testParams->specCurve)); + } + if(testParams->keychain) { + printf("Client Auth Enabled"); + } + putchar('\n'); +} + +static void dumpErrInfo( + const char *op, + const EcdsaTestParams *testParams, + OSStatus ortn) +{ + printf("***%s failed for ", op); + dumpParams(testParams); + printf(" error: %s\n", sslGetSSLErrString(ortn)); +} + +/* + * Custom ping for this test. + */ +#define RCV_BUF_SIZE 256 + +static int doSslPing( + const EcdsaTestParams *testParams, + bool quiet, + int nonBlocking) +{ + PeerSpec peerId; + otSocket sock = 0; + OSStatus ortn; + SSLContextRef ctx = NULL; + SSLCipherSuite negCipher; + + /* first make sure requested server is there */ + ortn = MakeServerConnection(testParams->hostName, testParams->port, + nonBlocking, &sock, &peerId); + if(ortn) { + printf("MakeServerConnection(%s) returned %d\n", + testParams->hostName, (int)ortn); + return -1; + } + + /* + * Set up a SecureTransport session. + * First the standard calls. + */ + ortn = SSLNewContext(false, &ctx); + if(ortn) { + printSslErrStr("SSLNewContext", ortn); + goto cleanup; + } + ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite); + if(ortn) { + printSslErrStr("SSLSetIOFuncs", ortn); + goto cleanup; + } + + /* Restrict to only TLSv1 - we have to do this because of Radar 6133465 */ + ortn = SSLSetProtocolVersionEnabled(ctx, kSSLProtocolAll, false); + if(ortn) { + printSslErrStr("SSLSetProtocolVersionEnabled", ortn); + goto cleanup; + } + ortn = SSLSetProtocolVersionEnabled(ctx, kTLSProtocol1, true); + if(ortn) { + printSslErrStr("SSLSetProtocolVersionEnabled", ortn); + goto cleanup; + } + + /* Restrict to only one CipherSuite */ + ortn = SSLSetEnabledCiphers(ctx, &testParams->cipherSuite, 1); + if(ortn) { + printSslErrStr("SSLSetEnabledCiphers", ortn); + goto cleanup; + } + + ortn = SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)sock); + if(ortn) { + printSslErrStr("SSLSetConnection", ortn); + goto cleanup; + } + + /* These test servers have custom roots, just allow any roots for this test */ + ortn = SSLSetAllowsExpiredCerts(ctx, true); + if(ortn) { + printSslErrStr("SSLSetAllowExpiredCerts", ortn); + goto cleanup; + } + ortn = SSLSetAllowsAnyRoot(ctx, true); + if(ortn) { + printSslErrStr("SSLSetAllowAnyRoot", ortn); + goto cleanup; + } + + if(testParams->specCurve != SSL_Curve_None) { + ortn = SSLSetECDSACurves(ctx, &testParams->specCurve, 1); + if(ortn) { + printSslErrStr("SSLSetAllowAnyRoot", ortn); + goto cleanup; + } + } + +#if 0 + if(testParams->keychain) { + char kcPath[2000]; + const char *lbd = getenv("LOCAL_BUILD_DIR"); + if(lbd == NULL) { + printf("WARNING: no LOCAL_BUILD_DIR env var faound\n"); + lbd = ""; + } + snprintf(kcPath, 2000, "%s/%s", lbd, testParams->keychain); + SecKeychainRef kcRef = NULL; + CFArrayRef certArray = getSslCerts(kcPath, + false, // encryptOnly + false, // completeCertChain + NULL, // anchorFile + &kcRef); + if(kcRef) { + /* Unlock it */ + ortn = SecKeychainUnlock(kcRef, + strlen(testParams->kcPassword), testParams->kcPassword, + true); + if(ortn) { + cssmPerror("SecKeychainUnlock", ortn); + /* oh well */ + } + CFRelease(kcRef); + } + if(certArray == NULL) { + printf("***WARNING no keychain found at %s\n", kcPath); + } + ortn = SSLSetCertificate(ctx, certArray); + if(ortn) { + printSslErrStr("SSLSetAllowAnyRoot", ortn); + goto cleanup; + } + CFRelease(certArray); + } +#endif + do { + ortn = SSLHandshake(ctx); + } while (ortn == errSSLWouldBlock); + + /* convert normal "shutdown" into zero err rtn */ + switch(ortn) { + case errSecSuccess: + break; + case errSSLClosedGraceful: + case errSSLClosedNoNotify: + ortn = errSecSuccess; + goto cleanup; + default: + dumpErrInfo("SSLHandshake", testParams, ortn); + goto cleanup; + } + + + /* + * Unlike other ping tests we don't bother with a GET - just validate + * the handshake + */ + ortn = SSLGetNegotiatedCipher(ctx, &negCipher); + if(ortn) { + dumpErrInfo("SSLHandshake", testParams, ortn); + goto cleanup; + } + + /* here is really what we're testing */ + if(negCipher != testParams->cipherSuite) { + printf("***Cipher mismatch for "); + dumpParams(testParams); + printf("Negotiated cipher: %s\n", sslGetCipherSuiteString(negCipher)); + ortn = errSecIO; + goto cleanup; + } + if(testParams->expCurve != SSL_Curve_None) { + SSL_ECDSA_NamedCurve actNegCurve; + ortn = SSLGetNegotiatedCurve(ctx, &actNegCurve); + if(ortn) { + printSslErrStr("SSLGetNegotiatedCurve", ortn); + goto cleanup; + } + if(actNegCurve != testParams->expCurve) { + printf("***Negotiated curve error\n"); + printf("Specified curve: %s\n", sslCurveString(testParams->specCurve)); + printf("Expected curve: %s\n", sslCurveString(testParams->expCurve)); + printf("Obtained curve: %s\n", sslCurveString(actNegCurve)); + ortn = errSecIO; + goto cleanup; + } + } + if(testParams->keychain) { + /* Verify client auth */ + SSLClientCertificateState authState; + ortn = SSLGetClientCertificateState(ctx, &authState); + if(ortn) { + printSslErrStr("SSLGetClientCertificateState", ortn); + goto cleanup; + } + if(authState != kSSLClientCertSent) { + printf("***Unexpected ClientCertificateState\n"); + printf(" Expected: ClientCertSent\n"); + printf(" Received: %s\n", sslGetClientCertStateString(authState)); + ortn = errSecIO; + goto cleanup; + } + } + + ortn = SSLClose(ctx); + +cleanup: + if(sock) { + endpointShutdown(sock); + } + if(ctx) { + SSLDisposeContext(ctx); + } + return (int)ortn; +} + + +int main(int argc, char **argv) +{ + int ourRtn = 0; + bool quiet = false; + int nonBlocking = false; + unsigned minDex = 0; + unsigned maxDex = NUM_TEST_PARAMS-1; + bool doPause = false; + + extern char *optarg; + int arg; + while ((arg = getopt(argc, argv, "t:bpqh")) != -1) { + switch (arg) { + case 't': + minDex = maxDex = atoi(optarg); + if(minDex > (NUM_TEST_PARAMS - 1)) { + printf("***max test number is %u.\n", (unsigned)NUM_TEST_PARAMS); + exit(1); + } + break; + case 'q': + quiet = true; + break; + case 'b': + nonBlocking = true; + break; + case 'p': + doPause = true; + break; + default: + usage(argv); + } + } + if(optind != argc) { + usage(argv); + } + +#if NO_SERVER +# if DEBUG + securityd_init(NULL); +# endif +#endif + + #if IGNORE_SIGPIPE + signal(SIGPIPE, sigpipe); + #endif + + //testStartBanner("sslEcdsa", argc, argv); + + if(doPause) { + fpurge(stdin); + printf("Pausing at top of loop; CR to continue: "); + fflush(stdout); + getchar(); + } + + for(unsigned dex=minDex; dex<=maxDex; dex++) { + const EcdsaTestParams *testParams = &ecdsaTestParams[dex]; + if(!quiet) { + printf("[%u]: ", dex); + dumpParams(testParams); + } + ourRtn = doSslPing(testParams, quiet, nonBlocking); + if(ourRtn) { + //printf("** Test %u failed **\n", dex); + //if(testError(quiet)) { + // break; + //} + } + } + + if(doPause) { + fpurge(stdin); + printf("Pausing at end of loop; CR to continue: "); + fflush(stdout); + getchar(); + } + + if(!quiet) { + if(ourRtn == 0) { + printf("===== sslEcdsa test PASSED =====\n"); + } + else { + printf("****sslEcdsa test FAILED\n"); + } + } + + return ourRtn; +} diff --git a/sslViewer/sslServe.cpp b/sslViewer/sslServe.cpp new file mode 100644 index 00000000..349d618f --- /dev/null +++ b/sslViewer/sslServe.cpp @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2006-2008,2010,2013 Apple Inc. All Rights Reserved. + * + * sslServe.cpp : perform one server side sesssion + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#define BIND_RETRIES 10 + +#define SERVER_MESSAGE "HTTP/1.0 200 OK\015\012\015\012" \ + "SecureTransport Test Server" \ + "

    Secure connection established.

    " \ + "Message from the 'sslServe' test library.\015\012" \ + "\015\012" + +#define READBUF_LEN 256 + +/* relies on SSLSetProtocolVersionEnabled */ + +/* + * params->lock is held for us by runSession() - we use it as a semapahore by + * unlocking it when we've created a port to listen on. + * This is generally run from a thread via sslRunSession() and + * sslServerThread() in sslAppUtils.cpp. + */ +OSStatus sslAppServe( + SslAppTestParams *params) +{ + otSocket listenSock = 0; + otSocket acceptSock = 0; + PeerSpec peerId; + OSStatus ortn; + SSLContextRef ctx = NULL; + SecKeychainRef serverKc = nil; + CFArrayRef serverCerts = nil; + + sslThrDebug("Server", "starting"); + params->negVersion = kSSLProtocolUnknown; + params->negCipher = SSL_NULL_WITH_NULL_NULL; + params->ortn = noHardwareErr; + + /* set up a socket on which to listen */ + for(unsigned retry=0; retryport, params->nonBlocking, + &listenSock); + switch(ortn) { + case errSecSuccess: + break; + case errSecOpWr: + /* port already in use - try another */ + params->port++; + if(params->verbose || THREADING_DEBUG) { + printf("...retrying ListenForClients at port %d\n", + params->port); + } + break; + default: + break; + } + if(ortn != errSecOpWr) { + break; + } + } + + /* let main thread know a socket is ready */ + if(pthread_mutex_lock(¶ms->pthreadMutex)) { + printf("***Error acquiring server lock; aborting.\n"); + return -1; + } + params->serverReady = true; + if(pthread_cond_broadcast(¶ms->pthreadCond)) { + printf("***Error waking main thread; aborting.\n"); + return -1; + } + if(pthread_mutex_unlock(¶ms->pthreadMutex)) { + printf("***Error acquiring server lock; aborting.\n"); + return -1; + } + + if(ortn) { + printf("ListenForClients returned %d; aborting\n", (int)ortn); + return ortn; + } + + /* wait for a connection */ + if(params->verbose) { + printf("Waiting for client connection..."); + fflush(stdout); + } + ortn = AcceptClientConnection(listenSock, &acceptSock, &peerId); + if(ortn) { + printf("AcceptClientConnection returned %d; aborting\n", (int)ortn); + return ortn; + } + + /* + * Set up a SecureTransport session. + */ + ortn = SSLNewContext(true, &ctx); + if(ortn) { + printSslErrStr("SSLNewContext", ortn); + goto cleanup; + } + ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite); + if(ortn) { + printSslErrStr("SSLSetIOFuncs", ortn); + goto cleanup; + } + ortn = SSLSetConnection(ctx, (SSLConnectionRef)acceptSock); + if(ortn) { + printSslErrStr("SSLSetConnection", ortn); + goto cleanup; + } + + if(params->anchorFile) { + ortn = sslAddTrustedRoot(ctx, params->anchorFile, + params->replaceAnchors); + if(ortn) { + goto cleanup; + } + } + if(params->myCertKcName != NULL) { + /* if not, better be trying anonymous diff-hellman... :-) */ + serverCerts = getSslCerts(params->myCertKcName, false, false, NULL, + &serverKc); + if(serverCerts == nil) { + exit(1); + } + if(params->password) { + ortn = SecKeychainUnlock(serverKc, strlen(params->password), + (void *)params->password, true); + if(ortn) { + printf("SecKeychainUnlock returned %d\n", (int)ortn); + /* oh well */ + } + } + if(params->idIsTrustedRoot) { + /* assume this is a root we want to implicitly trust */ + ortn = addIdentityAsTrustedRoot(ctx, serverCerts); + if(ortn) { + goto cleanup; + } + } + ortn = SSLSetCertificate(ctx, serverCerts); + if(ortn) { + printSslErrStr("SSLSetCertificate", ortn); + goto cleanup; + } + } + + if(params->disableCertVerify) { + ortn = SSLSetEnableCertVerify(ctx, false); + if(ortn) { + printSslErrStr("SSLSetEnableCertVerify", ortn); + goto cleanup; + } + } + ortn = sslSetProtocols(ctx, params->acceptedProts, params->tryVersion); + if(ortn) { + goto cleanup; + } + if(params->resumeEnable) { + ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec)); + if(ortn) { + printSslErrStr("SSLSetPeerID", ortn); + goto cleanup; + } + } + if(params->ciphers != NULL) { + ortn = sslSetEnabledCiphers(ctx, params->ciphers); + if(ortn) { + goto cleanup; + } + } + if(params->authenticate != kNeverAuthenticate) { + ortn = SSLSetClientSideAuthenticate(ctx, params->authenticate); + if(ortn) { + printSslErrStr("SSLSetClientSideAuthenticate", ortn); + goto cleanup; + } + } + if(params->dhParams) { + #if JAGUAR_BUILD + printf("***Diffie-Hellman not supported in this config.\n"); + #else + ortn = SSLSetDiffieHellmanParams(ctx, params->dhParams, + params->dhParamsLen); + if(ortn) { + printSslErrStr("SSLSetDiffieHellmanParams", ortn); + goto cleanup; + } + #endif + } + + /* Perform SSL/TLS handshake */ + do { + ortn = SSLHandshake(ctx); + if((ortn == errSSLWouldBlock) && !params->silent) { + /* keep UI responsive */ + sslOutputDot(); + } + } while (ortn == errSSLWouldBlock); + + SSLGetClientCertificateState(ctx, ¶ms->certState); + SSLGetNegotiatedCipher(ctx, ¶ms->negCipher); + SSLGetNegotiatedProtocolVersion(ctx, ¶ms->negVersion); + + if(params->verbose) { + printf("\n"); + } + if(ortn) { + goto cleanup; + } + + /* wait for one complete line */ + char readBuf[READBUF_LEN]; + size_t length; + while(ortn == errSecSuccess) { + length = READBUF_LEN; + ortn = SSLRead(ctx, readBuf, length, &length); + if (ortn == errSSLWouldBlock) { + /* keep trying */ + ortn = errSecSuccess; + continue; + } + if(length == 0) { + /* keep trying */ + continue; + } + + /* poor person's line completion scan */ + for(unsigned i=0; iclientDone && !params->serverAbort) { + usleep(100); + } + endpointShutdown(acceptSock); + } + if(listenSock) { + endpointShutdown(listenSock); + } + if(ctx) { + SSLDisposeContext(ctx); + } + params->ortn = ortn; + sslThrDebug("Server", "done"); + return ortn; +} diff --git a/sslViewer/sslServer-entitlements.plist b/sslViewer/sslServer-entitlements.plist new file mode 100644 index 00000000..97f6deb2 --- /dev/null +++ b/sslViewer/sslServer-entitlements.plist @@ -0,0 +1,11 @@ + + + + + keychain-access-groups + + apple + test + + + diff --git a/sslViewer/sslServer.cpp b/sslViewer/sslServer.cpp new file mode 100644 index 00000000..fca50f3e --- /dev/null +++ b/sslViewer/sslServer.cpp @@ -0,0 +1,1065 @@ +/* + * Copyright (c) 2008-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@ + */ + +/* + * Trivial SSL server example, using SecureTransport / OS X version. + * + * Written by Doug Mitchell. + */ +#include +#include +#include "sslAppUtils.h" +#include "ioSock.h" +#include "utilities/fileIo.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include "SecurityTool/print_cert.h" + +#if NO_SERVER +#include +#endif + +/* Set true when PR-3074739 is merged to TOT */ +#define SET_DH_PARAMS_ENABLE 1 + +/* true when using SSLCopyPeerCertificates() per Radar 3311892 */ +#define USE_COPY_PEER_CERTS 1 + +/* + * Defaults, overridable by user. + */ +#define SERVER_MESSAGE "HTTP/1.0 200 OK\015\012Content-Type: text/html\015\012\015\012" \ + "SecureTransport Test Server" \ + "

    Secure connection established.

    " \ + "Message from the 'sslServer' sample application.\015\012" \ + "\015\012" + +/* For ease of debugging, pick a non-privileged port */ +#define DEFAULT_PORT 1200 +// #define DEFAULT_PORT 443 + +#define DEFAULT_HOST "localhost" + +#define DEFAULT_KC "certkc" + +static void usage(char **argv) +{ + printf("Usage: %s [option ...]\n", argv[0]); + printf("Options:\n"); + printf(" P=port Port to listen on; default is %d\n", DEFAULT_PORT); + printf(" k=keychain Contains server cert and keys.\n"); + printf(" y=keychain Encryption-only cert and keys.\n"); + printf(" e Allow Expired Certs\n"); + printf(" r Allow any root cert\n"); + printf(" E Allow Expired Roots\n"); + printf(" x Disable Cert Verification\n"); + printf(" f=fileBase Write Peer Certs to fileBase*\n"); + printf(" c Display peer certs\n"); + printf(" d Display received data\n"); + printf(" C=cipherSuite (e=40-bit d=DES D=40-bit DES 3=3DES 4=RC4 $=40-bit RC4\n" + " 2=RC2 a=AES128 A=AES256 h=DH H=Anon DH r=DHE/RSA s=DH/DSS\n" + " n=RSA/NULL\n"); + printf(" 2 SSLv2 only (default is best fit)\n"); + printf(" 3 SSLv3 only (default is best fit)\n"); + printf(" t TLSv1 only (default is best fit)\n"); + printf(" o TLSv1, SSLv3 use kSSLProtocol__X__Only\n"); + printf(" g={prot...} Specify legal protocols; prot = any combo of [23t]\n"); + printf(" T=[nrsj] Verify client cert state = " + "none/requested/sent/rejected\n"); + printf(" R Disable resumable session support\n"); + printf(" i=timeout Session cache timeout\n"); + printf(" u=[nat] Authentication: n=never; a=always; t=try\n"); + printf(" b Non-blocking I/O\n"); + printf(" a fileNmae Add fileName to list of trusted roots\n"); + printf(" A fileName fileName is ONLY trusted root\n"); + printf(" U filename Add filename to acceptable DNList (multiple times OK)\n"); + printf(" D filename Diffie-Hellman parameters from filename\n"); + printf(" z=password Unlock server keychain with password.\n"); + printf(" H Do SecIndentityRef search instead of specific keychain\n"); + printf(" M Complete cert chain (default assumes that our identity is root)\n"); + printf(" 4 Disable anonymous ciphers\n"); + printf(" p Pause after each phase\n"); + printf(" l[=loops] Loop, performing multiple transactions\n"); + printf(" q Quiet/diagnostic mode (site names and errors only)\n"); + printf(" h Help\n"); + exit(1); +} + +/* snag a copy of current connection's peer certs so we can + * examine them later after the connection is closed */ +static OSStatus copyPeerCerts( + SSLContext *ctx, + CFArrayRef *peerCerts) // mallocd & RETURNED +{ + #if USE_COPY_PEER_CERTS + OSStatus ortn = SSLCopyPeerCertificates(ctx, peerCerts); + #else + OSStatus ortn = SSLGetPeerCertificates(ctx, peerCerts); + #endif + if(ortn) { + printf("***Error obtaining peer certs: %s\n", + sslGetSSLErrString(ortn)); + } + return ortn; +} + +/* free the cert array obtained via SSLGetPeerCertificates() */ +static void freePeerCerts( + CFArrayRef peerCerts) +{ + if(peerCerts == NULL) { + return; + } + + #if USE_COPY_PEER_CERTS + + /* Voila! Problem fixed. */ + CFRelease(peerCerts); + return; + + #else + + CFIndex numCerts; + SecCertificateRef certData; + CFIndex i; + + numCerts = CFArrayGetCount(peerCerts); + for(i=0; i", ((unsigned)c) & 0xff); + } + break; + } + + } + printf("\n"); +} + +static void doPause(const char *prompt) { + if(prompt) { + printf("%s. ", prompt); + } + fpurge(stdin); + printf("Continue (n/anything)? "); + char c = getchar(); + if(c == 'n') { + exit(0); + } +} + +/* + * Perform one SSL diagnostic server-side session. Returns nonzero on error. + * Normally no output to stdout except initial "waiting for connection" message, + * unless there is a really screwed up error (i.e., something not directly related + * to the SSL connection). + */ +#define RCV_BUF_SIZE 256 + +static OSStatus sslServe( + otSocket listenSock, + unsigned short portNum, + SSLProtocol tryVersion, // only used if acceptedProts NULL + const char *acceptedProts, + CFArrayRef serverCerts, // required + char *password, // optional + CFArrayRef encryptServerCerts, // optional + bool allowExpired, + bool allowAnyRoot, + bool allowExpiredRoot, + bool disableCertVerify, + char *anchorFile, + bool replaceAnchors, + char cipherRestrict, // '2', 'd'. etc...'\0' for no + // restriction + SSLAuthenticate authenticate, + unsigned char *dhParams, // optional D-H parameters + unsigned dhParamsLen, + CFArrayRef acceptableDNList, // optional + bool resumableEnable, + uint32_t sessionCacheTimeout,// optional + bool disableAnonCiphers, + bool silent, // no stdout + bool pause, + SSLProtocol *negVersion, // RETURNED + SSLCipherSuite *negCipher, // RETURNED + SSLClientCertificateState *certState, // RETURNED + Boolean *sessionWasResumed, // RETURNED + unsigned char *sessionID, // mallocd by caller, RETURNED + size_t *sessionIDLength, // RETURNED + CFArrayRef *peerCerts, // mallocd & RETURNED + char **argv) +{ + otSocket acceptSock; + PeerSpec peerId; + OSStatus ortn; + SSLContextRef ctx = NULL; + size_t length; + uint8_t rcvBuf[RCV_BUF_SIZE]; + const char *outMsg = SERVER_MESSAGE; + + *negVersion = kSSLProtocolUnknown; + *negCipher = SSL_NULL_WITH_NULL_NULL; + *peerCerts = NULL; + + #if IGNORE_SIGPIPE + signal(SIGPIPE, sigpipe); + #endif + + /* first wait for a connection */ + if(!silent) { + printf("Waiting for client connection on port %u...", portNum); + fflush(stdout); + } + ortn = AcceptClientConnection(listenSock, &acceptSock, &peerId); + if(ortn) { + printf("AcceptClientConnection returned %d; aborting\n", (int)ortn); + return ortn; + } + + /* + * Set up a SecureTransport session. + * First the standard calls. + */ + ortn = SSLNewContext(true, &ctx); + if(ortn) { + printSslErrStr("SSLNewContext", ortn); + goto cleanup; + } + ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite); + if(ortn) { + printSslErrStr("SSLSetIOFuncs", ortn); + goto cleanup; + } + ortn = SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)acceptSock); + if(ortn) { + printSslErrStr("SSLSetConnection", ortn); + goto cleanup; + } + + /* have to do these options befor setting server certs */ + if(allowExpired) { + ortn = SSLSetAllowsExpiredCerts(ctx, true); + if(ortn) { + printSslErrStr("SSLSetAllowExpiredCerts", ortn); + goto cleanup; + } + } + if(allowAnyRoot) { + ortn = SSLSetAllowsAnyRoot(ctx, true); + if(ortn) { + printSslErrStr("SSLSetAllowAnyRoot", ortn); + goto cleanup; + } + } + + if(anchorFile) { + ortn = sslAddTrustedRoot(ctx, anchorFile, replaceAnchors); + if(ortn) { + printf("***Error obtaining anchor file %s\n", anchorFile); + goto cleanup; + } + } + if(serverCerts != NULL) { + if(anchorFile == NULL) { + /* no specific anchors, so assume we want to trust this one */ + ortn = addIdentityAsTrustedRoot(ctx, serverCerts); + if(ortn) { + goto cleanup; + } + } + ortn = SSLSetCertificate(ctx, serverCerts); + if(ortn) { + printSslErrStr("SSLSetCertificate", ortn); + goto cleanup; + } + } + if(encryptServerCerts) { + ortn = SSLSetEncryptionCertificate(ctx, encryptServerCerts); + if(ortn) { + printSslErrStr("SSLSetEncryptionCertificate", ortn); + goto cleanup; + } + } + if(allowExpiredRoot) { + ortn = SSLSetAllowsExpiredRoots(ctx, true); + if(ortn) { + printSslErrStr("SSLSetAllowsExpiredRoots", ortn); + goto cleanup; + } + } + if(disableCertVerify) { + ortn = SSLSetEnableCertVerify(ctx, false); + if(ortn) { + printSslErrStr("SSLSetEnableCertVerify", ortn); + goto cleanup; + } + } + + /* + * SecureTransport options. + */ + if(acceptedProts) { + ortn = SSLSetProtocolVersionEnabled(ctx, kSSLProtocolAll, false); + if(ortn) { + printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn); + goto cleanup; + } + for(const char *cp = acceptedProts; *cp; cp++) { + SSLProtocol prot = kSSLProtocolUnknown; + switch(*cp) { + case '2': + prot = kSSLProtocol2; + break; + case '3': + prot = kSSLProtocol3; + break; + case 't': + prot = kTLSProtocol1; + break; + default: + usage(argv); + } + ortn = SSLSetProtocolVersionEnabled(ctx, prot, true); + if(ortn) { + printSslErrStr("SSLSetProtocolVersionEnabled", ortn); + goto cleanup; + } + } + } + else { + ortn = SSLSetProtocolVersion(ctx, tryVersion); + if(ortn) { + printSslErrStr("SSLSetProtocolVersion", ortn); + goto cleanup; + } + } + if(resumableEnable) { + ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec)); + if(ortn) { + printSslErrStr("SSLSetPeerID", ortn); + goto cleanup; + } + } + if(cipherRestrict != '\0') { + ortn = sslSetCipherRestrictions(ctx, cipherRestrict); + if(ortn) { + goto cleanup; + } + } + if(authenticate != kNeverAuthenticate) { + ortn = SSLSetClientSideAuthenticate(ctx, authenticate); + if(ortn) { + printSslErrStr("SSLSetClientSideAuthenticate", ortn); + goto cleanup; + } + } + if(dhParams) { + ortn = SSLSetDiffieHellmanParams(ctx, dhParams, dhParamsLen); + if(ortn) { + printSslErrStr("SSLSetDiffieHellmanParams", ortn); + goto cleanup; + } + } + if(sessionCacheTimeout) { + ortn = SSLSetSessionCacheTimeout(ctx, sessionCacheTimeout); + if(ortn) { + printSslErrStr("SSLSetSessionCacheTimeout", ortn); + goto cleanup; + } + } + if(disableAnonCiphers) { + ortn = SSLSetAllowAnonymousCiphers(ctx, false); + if(ortn) { + printSslErrStr("SSLSetAllowAnonymousCiphers", ortn); + goto cleanup; + } + /* quickie test of the getter */ + Boolean e; + ortn = SSLGetAllowAnonymousCiphers(ctx, &e); + if(ortn) { + printSslErrStr("SSLGetAllowAnonymousCiphers", ortn); + goto cleanup; + } + if(e) { + printf("***SSLGetAllowAnonymousCiphers() returned true; expected false\n"); + ortn = errSecIO; + goto cleanup; + } + } +/* XXX/cs + if(acceptableDNList) { + ortn = SSLSetCertificateAuthorities(ctx, acceptableDNList, TRUE); + if(ortn) { + printSslErrStr("SSLSetCertificateAuthorities", ortn); + goto cleanup; + } + } +*/ + /* end options */ + + if(pause) { + doPause("SSLContext initialized"); + } + + /* Perform SSL/TLS handshake */ + do + { ortn = SSLHandshake(ctx); + if((ortn == errSSLWouldBlock) && !silent) { + /* keep UI responsive */ + sslOutputDot(); + } + } while (ortn == errSSLWouldBlock); + + /* this works even if handshake failed due to cert chain invalid */ + copyPeerCerts(ctx, peerCerts); + + SSLGetClientCertificateState(ctx, certState); + SSLGetNegotiatedCipher(ctx, negCipher); + SSLGetNegotiatedProtocolVersion(ctx, negVersion); + *sessionIDLength = MAX_SESSION_ID_LENGTH; + SSLGetResumableSessionInfo(ctx, sessionWasResumed, sessionID, + sessionIDLength); + + if(!silent) { + printf("\n"); + } + if(ortn) { + goto cleanup; + } + if(pause) { + doPause("SSLContext handshake complete"); + } + + /* wait for one complete line or user says they've had enough */ + while(ortn == errSecSuccess) { + length = sizeof(rcvBuf); + ortn = SSLRead(ctx, rcvBuf, length, &length); + if(length == 0) { + /* keep UI responsive */ + sslOutputDot(); + } + else { + /* print what we have */ + printf("client request: "); + dumpAscii(rcvBuf, length); + } + if(pause) { + /* allow user to bail */ + char resp; + + fpurge(stdin); + printf("\nMore client request (y/anything): "); + resp = getchar(); + if(resp != 'y') { + break; + } + } + + /* poor person's line completion scan */ + for(unsigned i=0; i SSLSetProtocolVersionEnabled + bool quiet = false; + bool resumableEnable = true; + bool pause = false; + char *keyChainName = NULL; + char *encryptKeyChainName = NULL; + int loops = 1; + SSLAuthenticate authenticate = kNeverAuthenticate; + bool nonBlocking = false; + bool allowExpiredRoot = false; + bool disableCertVerify = false; + char *anchorFile = NULL; + bool replaceAnchors = false; + bool vfyCertState = false; + SSLClientCertificateState expectCertState = kSSLClientCertNone; + char *password = NULL; + char *dhParamsFile = NULL; + unsigned char *dhParams = NULL; + unsigned dhParamsLen = 0; + bool doIdSearch = false; + bool completeCertChain = false; + uint32_t sessionCacheTimeout = 0; + bool disableAnonCiphers = false; + CFMutableArrayRef acceptableDNList = NULL; + + for(arg=1; arg loop forever */ + loops = 0; + break; + } + else if(argp[1] != '=') { + usage(argv); + } + loops = atoi(&argp[2]); + break; + default: + usage(argv); + } + } + +#if NO_SERVER +# if DEBUG + securityd_init(NULL); +# endif +#endif + + /* get server cert and optional encryption cert as CFArrayRef */ + if(keyChainName) { + serverCerts = getSslCerts(keyChainName, false, completeCertChain, + anchorFile, &serverKc); + if(serverCerts == nil) { + exit(1); + } + } + else +#if 0 + if(doIdSearch) { + OSStatus ortn = sslIdentityPicker(NULL, anchorFile, true, NULL, &serverCerts); + if(ortn) { + printf("***IdentitySearch failure; aborting.\n"); + exit(1); + } + } + if(password) { + OSStatus ortn = SecKeychainUnlock(serverKc, strlen(password), password, true); + if(ortn) { + printf("SecKeychainUnlock returned %d\n", (int)ortn); + /* oh well */ + } + } + if(encryptKeyChainName) { + encryptCerts = getSslCerts(encryptKeyChainName, true, completeCertChain, + anchorFile, &encryptKc); + if(encryptCerts == nil) { + exit(1); + } + } +#else + (void) doIdSearch; + (void) encryptKeyChainName; +#endif + if(protXOnly) { + switch(attemptProt) { + case kTLSProtocol1: + attemptProt = kTLSProtocol1Only; + break; + case kSSLProtocol3: + attemptProt = kSSLProtocol3Only; + break; + default: + break; + } + } +#if 0 + if(dhParamsFile) { + int r = cspReadFile(dhParamsFile, &dhParams, &dhParamsLen); + if(r) { + printf("***Error reading diffie-hellman params from %s; aborting\n", + dhParamsFile); + } + } +#else + (void) dhParamsFile; +#endif + + /* one-time only server port setup */ + err = ListenForClients(portNum, nonBlocking, &listenSock); + if(err) { + printf("ListenForClients returned %d; aborting\n", (int)err); + exit(1); + } + + for(loopNum=1; ; loopNum++) { + err = sslServe(listenSock, + portNum, + attemptProt, + acceptedProts, + serverCerts, + password, + encryptCerts, + allowExpired, + allowAnyRoot, + allowExpiredRoot, + disableCertVerify, + anchorFile, + replaceAnchors, + cipherRestrict, + authenticate, + dhParams, + dhParamsLen, + acceptableDNList, + resumableEnable, + sessionCacheTimeout, + disableAnonCiphers, + quiet, + pause, + &negVersion, + &negCipher, + &certState, + &sessionWasResumed, + sessionID, + &sessionIDLength, + &peerCerts, + argv); + if(err) { + errCount++; + } + if(!quiet) { + SSLProtocol tryProt = attemptProt; + showSSLResult(tryProt, + acceptedProts, + err, + negVersion, + negCipher, + sessionWasResumed, + sessionID, + sessionIDLength, + peerCerts, + displayCerts, + certState, + fileBase ? fullFileBase : NULL); + } + errCount += verifyClientCertState(vfyCertState, expectCertState, + certState); + freePeerCerts(peerCerts); + if(loops && (loopNum == loops)) { + break; + } + }; + + endpointShutdown(listenSock); + + if(serverKc) { + CFRelease(serverKc); + } + if(encryptKc) { + CFRelease(encryptKc); + } + return errCount; + +} + + diff --git a/sslViewer/sslThreading.h b/sslViewer/sslThreading.h new file mode 100644 index 00000000..8178b1ea --- /dev/null +++ b/sslViewer/sslThreading.h @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2006-2007,2013 Apple Inc. All Rights Reserved. + * + * sslThreading.h - support for two-threaded SSL client/server tests. + */ + +#ifndef _SSL_THREADING_H_ +#define _SSL_THREADING_H_ 1 + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* "Don't bother verifying" values */ +#define SSL_PROTOCOL_IGNORE ((SSLProtocol)0x123456) +#define SSL_CLIENT_CERT_IGNORE ((SSLClientCertificateState)0x234567) +#define SSL_CIPHER_IGNORE ((SSLCipherSuite)0x345678) + +/* + * Test params passed to both sslClient() and sslServer() + */ +typedef struct { + + /* client side only */ + const char *hostName; + bool skipHostNameCheck; + + /* common */ + unsigned short port; + SSLProtocol tryVersion; // only used if acceptedProts + // NULL + const char *acceptedProts; + const char *myCertKcName; // required for server, + // optional for client + const char *password; // optional, to unlock keychain + bool idIsTrustedRoot; // cert in KC is trusted root + bool disableCertVerify; + const char *anchorFile; // to add/replace anchors + bool replaceAnchors; + SSLAuthenticate authenticate; + bool resumeEnable; + const SSLCipherSuite *ciphers; // optional array of allowed ciphers, + // terminated with SSL_NO_SUCH_CIPHERSUITE + bool nonBlocking; + const unsigned char *dhParams; // optional Diffie-Hellman params + unsigned dhParamsLen; + + /* expected results */ + OSStatus expectRtn; + SSLProtocol expectVersion; + SSLClientCertificateState expectCertState; + SSLCipherSuite expectCipher; + + /* UI parameters */ + bool quiet; + bool silent; + bool verbose; + + /* + * Server semaphore: + * + * -- main thread inits and sets serverRady false + * -- main thread starts up server thread + * -- server thread inits and sets of a socket for listening + * -- serrver thread sets serverReady true and does pthread_cond_broadcast + */ + pthread_mutex_t pthreadMutex; + pthread_cond_t pthreadCond; + bool serverReady; + /* + * To ensure error abort is what we expect instead of just " + * peer closed their socket", server avoids closing down the + * socket until client sets this flag. It's just polled, no + * locking. Setting the serverAbort flag skips this + * step to facilitate testing cases where server explicitly + * drops connection (e.g. in response to an unacceptable + * ClientHello). + */ + unsigned clientDone; + bool serverAbort; + + /* + * Returned and also verified by sslRunSession(). + * Conditions in which expected value NOT verified are listed + * in following comments. + * + * NegCipher is only verified if (ortn == errSecSuccess). + */ + SSLProtocol negVersion; // SSL_PROTOCOL_IGNORE + SSLCipherSuite negCipher; // SSL_CIPHER_IGNORE + SSLClientCertificateState certState; // SSL_CLIENT_CERT_IGNORE + OSStatus ortn; // always checked + +} SslAppTestParams; + +/* client and server in sslClient.cpp and sslServe.cpp */ +OSStatus sslAppClient( + SslAppTestParams *params); +OSStatus sslAppServe( + SslAppTestParams *params); + +/* + * Run one session, with the server in a separate thread. + * On entry, serverParams->port is the port we attempt to run on; + * the server thread may overwrite that with a different port if it's + * unable to open the port we specify. Whatever is left in + * serverParams->port is what's used for the client side. + */ +int sslRunSession( + SslAppTestParams *serverParams, + SslAppTestParams *clientParams, + const char *testDesc); + +void sslShowResult( + char *whichSide, // "client" or "server" + SslAppTestParams *params); + + +/* + * Macros which do the repetetive setup/run work + */ +#define SSL_THR_SETUP(serverParams, clientParams, clientDefaults, serverDefault) \ +{ \ + unsigned short serverPort; \ + serverPort = serverParams.port + 1; \ + clientParams = clientDefaults; \ + serverParams = serverDefaults; \ + serverParams.port = serverPort; \ +} + +#define SSL_THR_RUN(serverParams, clientParams, desc, ourRtn) \ +{ \ + thisRtn = sslRunSession(&serverParams, &clientParams, desc); \ + ourRtn += thisRtn; \ + if(thisRtn) { \ + if(testError(clientParams.quiet)) { \ + goto done; \ + } \ + } \ +} + +#define SSL_THR_RUN_NUM(serverParams, clientParams, desc, ourRtn, testNum) \ +{ \ + thisRtn = sslRunSession(&serverParams, &clientParams, desc);\ + ourRtn += thisRtn; \ + if(thisRtn) { \ + printf("***Error on test %u\n", testNum); \ + if(testError(clientParams.quiet)) { \ + goto done; \ + } \ + } \ +} + +#define THREADING_DEBUG 0 +#if THREADING_DEBUG + +#define sslThrDebug(side, end) \ + printf("^^^%s thread %p %s\n", side, pthread_self(), end) +#else /* THREADING_DEBUG */ +#define sslThrDebug(side, end) +#endif /* THREADING_DEBUG */ +#ifdef __cplusplus +} +#endif + +#endif /* _SSL_THREADING_H_ */ diff --git a/sslViewer/sslViewer-entitlements.plist b/sslViewer/sslViewer-entitlements.plist new file mode 100644 index 00000000..97f6deb2 --- /dev/null +++ b/sslViewer/sslViewer-entitlements.plist @@ -0,0 +1,11 @@ + + + + + keychain-access-groups + + apple + test + + + diff --git a/sslViewer/verifyPing b/sslViewer/verifyPing new file mode 100755 index 00000000..667089fe --- /dev/null +++ b/sslViewer/verifyPing @@ -0,0 +1,143 @@ +#! /bin/csh -f +# +# run sslViewer on a list of known sites, using sslViewer's 'verify +# protocol' option. +# Arguments to this script are passed on to sslViewer unmodified. +# +set ARG_LIST = +while ( $#argv > 0 ) + set thisArg = "$argv[1]" + set ARG_LIST = "$ARG_LIST $thisArg" + shift +end +echo Starting verifyPing\; args: $ARG_LIST + +# +# Sites which support all three protocols +# +# this flaked out yet agaqin... www.cduniverse.com +set FULL_TLS_SITES = ( www.amazon.com \ + mypage.apple.com \ + gmail.google.com ) + +# +# Sites which support SSLv2 and SSLv3 only +# None known currently +# +set FULL_SSL_SITES = + +# +# Sites which support SSLv2 only +# +# store.apple.com seems to have been permanently upgraded. +# +#set SSLV2_SITES = ( store.apple.com ) + +# +# Sites which support only TLSv1 and SSLv3 +# remote.harpercollins.com asks for a client cert but works if you don't give it one +# +set TLS_SSL3_SITES = ( www.thawte.com \ + store.apple.com \ + digitalid.verisign.com \ + www.firstamlink.com \ + remote.harpercollins.com \ + mbanxonlinebanking.harrisbank.com \ + www.sun.com \ + directory.umich.edu \ + account.authorize.net ) + +# +# Sites which support all three protocols if 'r' option is specified for SSL2 only +# I.e., these really need to be able to transmit an intermediate cert for us +# to verify them, and SSLv2 doesn't allow that. +# +# 9/24/04 - secure.authorize.net keeps throwing SIGPIPE +# secure.authorize.net +# +# ktt2.keybank.com doesn't seem to be around anymore +set FULL_TLS_ANYROOT_SITES = ( weblogin.umich.edu ) + +# +# Here's one which supports TLSv1 and SSLv2 only (!). It tests the Entrust root cert. +# set TLS_SSL2_SITES = ( directory.umich.edu) +# +set TLS_SSL2_SITES = + +# SSLv3 only - try with TLSv1 +set SSL3_ONLY_SITES = ( www.verisign.com \ + www.cmarket.jp ) + +# +# SSLv3 and TLS with any root set +# office.bis.bonn.org sends a huge pile of certs per radar 3859283 and also asks +# for a client cert +# +# 12/14/05 : office.bis.bonn.org is offline +# +# set TLS_SSL3_ANYROOT_SITES = ( office.bis.bonn.org ) +set TLS_SSL3_ANYROOT_SITES = ( ) + +# +# All three protocols. +# One run with all three protocols using SSLv2-compatible Hello +# One run for each of TLSv1 and SSLv3 ONLY using SLSv3 Hello +# +foreach site ($FULL_TLS_SITES); + $LOCAL_BUILD_DIR/sslViewer $site v L $ARG_LIST || exit(1); + $LOCAL_BUILD_DIR/sslViewer $site v t o $ARG_LIST || exit(1); + $LOCAL_BUILD_DIR/sslViewer $site v 3 o $ARG_LIST || exit(1); +end + +# +# SSLv3 only +# Try with each of +# TLSv1 w/SSLv2 Hello +# SSLv3 w/SSLv3 Hello +# +foreach site ($SSL3_ONLY_SITES); + $LOCAL_BUILD_DIR/sslViewer $site v t m=3 $ARG_LIST || exit(1); + $LOCAL_BUILD_DIR/sslViewer $site v o 3 $ARG_LIST || exit(1); +end + +# +# SSLV2 seems to be obsolete in the real world +# +#foreach site ($SSLV2_SITES); +# $LOCAL_BUILD_DIR/sslViewer $site m=2 $ARG_LIST || exit(1); +# $LOCAL_BUILD_DIR/sslViewer $site 2 v $ARG_LIST || exit(1); +#end + +# +# All three protocols, but SSLv2 needs 'any root' +# Test TLSv1 and SSLv3 with both SSLv3 and SSLv2 Hello +# +foreach site ($FULL_TLS_ANYROOT_SITES); + $LOCAL_BUILD_DIR/sslViewer $site v t $ARG_LIST || exit(1); + $LOCAL_BUILD_DIR/sslViewer $site v t o $ARG_LIST || exit(1); + $LOCAL_BUILD_DIR/sslViewer $site v 3 $ARG_LIST || exit(1); + $LOCAL_BUILD_DIR/sslViewer $site v 3 o $ARG_LIST || exit(1); + $LOCAL_BUILD_DIR/sslViewer $site v 2 r $ARG_LIST || exit(1); +end + +# +# No SSLv2 +# Test TLSv1 and SSLv3 with both SSLv3 and SSLv2 Hello +# +foreach site ($TLS_SSL3_SITES); + $LOCAL_BUILD_DIR/sslViewer $site v t $ARG_LIST || exit(1); + $LOCAL_BUILD_DIR/sslViewer $site v t o $ARG_LIST || exit(1); + $LOCAL_BUILD_DIR/sslViewer $site v 3 $ARG_LIST || exit(1); + $LOCAL_BUILD_DIR/sslViewer $site v 3 o $ARG_LIST || exit(1); +end + +# try SSLv3 and expect SSLV2 +foreach site ($TLS_SSL2_SITES); + $LOCAL_BUILD_DIR/sslViewer $site v t $ARG_LIST || exit(1); + $LOCAL_BUILD_DIR/sslViewer $site v 3 m=2 $ARG_LIST || exit(1); +end +# TLS end SSLv3 with any root +foreach site ($TLS_SSL3_ANYROOT_SITES); + $LOCAL_BUILD_DIR/sslViewer $site v t r $ARG_LIST || exit(1); + $LOCAL_BUILD_DIR/sslViewer $site v 3 r $ARG_LIST || exit(1); +end diff --git a/tlsnke/tlsnke.xcodeproj/project.pbxproj b/tlsnke/tlsnke.xcodeproj/project.pbxproj deleted file mode 100644 index a8225022..00000000 --- a/tlsnke/tlsnke.xcodeproj/project.pbxproj +++ /dev/null @@ -1,593 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXAggregateTarget section */ - 0CE08A7E148FF61C000473EB /* host-loadkext */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 0CE08A7F148FF61C000473EB /* Build configuration list for PBXAggregateTarget "host-loadkext" */; - buildPhases = ( - 0CE08A89148FF86C000473EB /* ShellScript */, - ); - dependencies = ( - 0CE08A83148FF628000473EB /* PBXTargetDependency */, - ); - name = "host-loadkext"; - productName = all; - }; -/* End PBXAggregateTarget section */ - -/* Begin PBXBuildFile section */ - 0C271D7515C8C80300560531 /* libsecurity_ssl_kext.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CBE354615C8C3A5006241C7 /* libsecurity_ssl_kext.a */; }; - 0C38E43D14BF707500DD862C /* tlsnke.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C38E43C14BF707500DD862C /* tlsnke.h */; }; - 0C6C642715D5A9C200BC68CD /* ssl-utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C6C642515D5A9C200BC68CD /* ssl-utils.c */; }; - 0C7CF8D714E18A9F00DF9D95 /* dtls_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C7CF8D614E18A9F00DF9D95 /* dtls_client.c */; }; - 0CBE354515C8C340006241C7 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CBE354415C8C340006241C7 /* Security.framework */; }; - 0CC9A7FA146DF66000C18F89 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0CC9A7F8146DF66000C18F89 /* InfoPlist.strings */; }; - 0CC9A7FC146DF66000C18F89 /* tlsnke.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CC9A7FB146DF66000C18F89 /* tlsnke.c */; }; - 0CDF46A414DC794F00FFE2FD /* tlssocket.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CA31A4214B7DFAB00BD348C /* tlssocket.c */; }; - 0CDF46A514DC795400FFE2FD /* tlssocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CA31A4514B7DFBA00BD348C /* tlssocket.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 0CDF46A614DC79FA00FFE2FD /* libtlssocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CDF46A014DC794300FFE2FD /* libtlssocket.a */; }; - 0CE08A77148FF2C7000473EB /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CE08A76148FF2C7000473EB /* main.c */; }; - 0CEF580014C0E227000A93B0 /* st_test.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CEF57FF14C0E227000A93B0 /* st_test.c */; }; - 0CEF580614C0E566000A93B0 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CEF580514C0E566000A93B0 /* CoreFoundation.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 0CDF46A714DC79FF00FFE2FD /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 0CC9A7E5146DF66000C18F89 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 0CDF469F14DC794300FFE2FD; - remoteInfo = tlssocket; - }; - 0CE08A82148FF628000473EB /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 0CC9A7E5146DF66000C18F89 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 0CC9A7EF146DF66000C18F89; - remoteInfo = tlsnke; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 0CE08A71148FF2C6000473EB /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 0C31453A1492D4B600427C0B /* tlsnke-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "tlsnke-Info.plist"; sourceTree = ""; }; - 0C38E43C14BF707500DD862C /* tlsnke.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tlsnke.h; sourceTree = ""; }; - 0C6C642515D5A9C200BC68CD /* ssl-utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-utils.c"; sourceTree = ""; }; - 0C6C642615D5A9C200BC68CD /* ssl-utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ssl-utils.h"; sourceTree = ""; }; - 0C7CF8D614E18A9F00DF9D95 /* dtls_client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dtls_client.c; sourceTree = ""; }; - 0CA31A4214B7DFAB00BD348C /* tlssocket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tlssocket.c; path = tlsnketest/tlssocket.c; sourceTree = ""; }; - 0CA31A4514B7DFBA00BD348C /* tlssocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tlssocket.h; path = tlsnketest/tlssocket.h; sourceTree = ""; }; - 0CBE354415C8C340006241C7 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Security.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 0CBE354615C8C3A5006241C7 /* libsecurity_ssl_kext.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libsecurity_ssl_kext.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 0CC9A7F0146DF66000C18F89 /* tlsnke.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = tlsnke.kext; sourceTree = BUILT_PRODUCTS_DIR; }; - 0CC9A7F4146DF66000C18F89 /* Kernel.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Kernel.framework; path = System/Library/Frameworks/Kernel.framework; sourceTree = SDKROOT; }; - 0CC9A7F9146DF66000C18F89 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 0CC9A7FB146DF66000C18F89 /* tlsnke.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = tlsnke.c; sourceTree = ""; }; - 0CC9A7FD146DF66000C18F89 /* tlsnke-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "tlsnke-Prefix.pch"; sourceTree = ""; }; - 0CDF468F14DC788000FFE2FD /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 0CDF46A014DC794300FFE2FD /* libtlssocket.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libtlssocket.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 0CE08A73148FF2C6000473EB /* tlsnketest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tlsnketest; sourceTree = BUILT_PRODUCTS_DIR; }; - 0CE08A76148FF2C7000473EB /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; - 0CEF57FF14C0E227000A93B0 /* st_test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = st_test.c; sourceTree = ""; }; - 0CEF580514C0E566000A93B0 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 0CC9A7EB146DF66000C18F89 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 0C271D7515C8C80300560531 /* libsecurity_ssl_kext.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0CDF469D14DC794300FFE2FD /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0CE08A70148FF2C6000473EB /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 0CDF46A614DC79FA00FFE2FD /* libtlssocket.a in Frameworks */, - 0CBE354515C8C340006241C7 /* Security.framework in Frameworks */, - 0CEF580614C0E566000A93B0 /* CoreFoundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 0C953FB814E4621800077526 /* Libraries */ = { - isa = PBXGroup; - children = ( - 0CBE354615C8C3A5006241C7 /* libsecurity_ssl_kext.a */, - ); - name = Libraries; - sourceTree = ""; - }; - 0CC9A7E3146DF66000C18F89 = { - isa = PBXGroup; - children = ( - 0CDF468814DC784200FFE2FD /* tlssocket */, - 0CC9A7F5146DF66000C18F89 /* tlsnke */, - 0CE08A75148FF2C6000473EB /* tlsnketest */, - 0CC9A7F2146DF66000C18F89 /* Frameworks */, - 0C953FB814E4621800077526 /* Libraries */, - 0CC9A7F1146DF66000C18F89 /* Products */, - ); - sourceTree = ""; - }; - 0CC9A7F1146DF66000C18F89 /* Products */ = { - isa = PBXGroup; - children = ( - 0CC9A7F0146DF66000C18F89 /* tlsnke.kext */, - 0CE08A73148FF2C6000473EB /* tlsnketest */, - 0CDF46A014DC794300FFE2FD /* libtlssocket.a */, - ); - name = Products; - sourceTree = ""; - }; - 0CC9A7F2146DF66000C18F89 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 0CBE354415C8C340006241C7 /* Security.framework */, - 0CEF580514C0E566000A93B0 /* CoreFoundation.framework */, - 0CDF468F14DC788000FFE2FD /* Foundation.framework */, - 0CC9A7F3146DF66000C18F89 /* Other Frameworks */, - ); - name = Frameworks; - sourceTree = ""; - }; - 0CC9A7F3146DF66000C18F89 /* Other Frameworks */ = { - isa = PBXGroup; - children = ( - 0CC9A7F4146DF66000C18F89 /* Kernel.framework */, - ); - name = "Other Frameworks"; - sourceTree = ""; - }; - 0CC9A7F5146DF66000C18F89 /* tlsnke */ = { - isa = PBXGroup; - children = ( - 0CC9A7FB146DF66000C18F89 /* tlsnke.c */, - 0C38E43C14BF707500DD862C /* tlsnke.h */, - 0CC9A7F6146DF66000C18F89 /* Supporting Files */, - ); - path = tlsnke; - sourceTree = ""; - }; - 0CC9A7F6146DF66000C18F89 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 0C31453A1492D4B600427C0B /* tlsnke-Info.plist */, - 0CC9A7F8146DF66000C18F89 /* InfoPlist.strings */, - 0CC9A7FD146DF66000C18F89 /* tlsnke-Prefix.pch */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 0CDF468814DC784200FFE2FD /* tlssocket */ = { - isa = PBXGroup; - children = ( - 0CA31A4214B7DFAB00BD348C /* tlssocket.c */, - 0CA31A4514B7DFBA00BD348C /* tlssocket.h */, - ); - name = tlssocket; - sourceTree = ""; - }; - 0CE08A75148FF2C6000473EB /* tlsnketest */ = { - isa = PBXGroup; - children = ( - 0C6C642515D5A9C200BC68CD /* ssl-utils.c */, - 0C6C642615D5A9C200BC68CD /* ssl-utils.h */, - 0CE08A76148FF2C7000473EB /* main.c */, - 0CEF57FF14C0E227000A93B0 /* st_test.c */, - 0C7CF8D614E18A9F00DF9D95 /* dtls_client.c */, - ); - path = tlsnketest; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 0CC9A7EC146DF66000C18F89 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 0C38E43D14BF707500DD862C /* tlsnke.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0CDF469E14DC794300FFE2FD /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 0CDF46A514DC795400FFE2FD /* tlssocket.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 0CC9A7EF146DF66000C18F89 /* tlsnke */ = { - isa = PBXNativeTarget; - buildConfigurationList = 0CC9A800146DF66000C18F89 /* Build configuration list for PBXNativeTarget "tlsnke" */; - buildPhases = ( - 0CC9A7EA146DF66000C18F89 /* Sources */, - 0CC9A7EB146DF66000C18F89 /* Frameworks */, - 0CC9A7EC146DF66000C18F89 /* Headers */, - 0CC9A7ED146DF66000C18F89 /* Resources */, - 0CC9A7EE146DF66000C18F89 /* Rez */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = tlsnke; - productName = tlsnke; - productReference = 0CC9A7F0146DF66000C18F89 /* tlsnke.kext */; - productType = "com.apple.product-type.kernel-extension"; - }; - 0CDF469F14DC794300FFE2FD /* tlssocket */ = { - isa = PBXNativeTarget; - buildConfigurationList = 0CDF46A114DC794300FFE2FD /* Build configuration list for PBXNativeTarget "tlssocket" */; - buildPhases = ( - 0CDF469C14DC794300FFE2FD /* Sources */, - 0CDF469D14DC794300FFE2FD /* Frameworks */, - 0CDF469E14DC794300FFE2FD /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = tlssocket; - productName = tlssocket; - productReference = 0CDF46A014DC794300FFE2FD /* libtlssocket.a */; - productType = "com.apple.product-type.library.static"; - }; - 0CE08A72148FF2C6000473EB /* tlsnketest */ = { - isa = PBXNativeTarget; - buildConfigurationList = 0CE08A7C148FF2C7000473EB /* Build configuration list for PBXNativeTarget "tlsnketest" */; - buildPhases = ( - 0CE08A6F148FF2C6000473EB /* Sources */, - 0CE08A70148FF2C6000473EB /* Frameworks */, - 0CE08A71148FF2C6000473EB /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 0CDF46A814DC79FF00FFE2FD /* PBXTargetDependency */, - ); - name = tlsnketest; - productName = tlsnketest; - productReference = 0CE08A73148FF2C6000473EB /* tlsnketest */; - productType = "com.apple.product-type.tool"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 0CC9A7E5146DF66000C18F89 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0430; - ORGANIZATIONNAME = "Apple, Inc."; - }; - buildConfigurationList = 0CC9A7E8146DF66000C18F89 /* Build configuration list for PBXProject "tlsnke" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 0CC9A7E3146DF66000C18F89; - productRefGroup = 0CC9A7F1146DF66000C18F89 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 0CE08A7E148FF61C000473EB /* host-loadkext */, - 0CC9A7EF146DF66000C18F89 /* tlsnke */, - 0CE08A72148FF2C6000473EB /* tlsnketest */, - 0CDF469F14DC794300FFE2FD /* tlssocket */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 0CC9A7ED146DF66000C18F89 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0CC9A7FA146DF66000C18F89 /* InfoPlist.strings in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXRezBuildPhase section */ - 0CC9A7EE146DF66000C18F89 /* Rez */ = { - isa = PBXRezBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXRezBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 0CE08A89148FF86C000473EB /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "sudo /var/root/loadkext.sh ${BUILT_PRODUCTS_DIR}/tlsnke.kext\n"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 0CC9A7EA146DF66000C18F89 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0CC9A7FC146DF66000C18F89 /* tlsnke.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0CDF469C14DC794300FFE2FD /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0CDF46A414DC794F00FFE2FD /* tlssocket.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0CE08A6F148FF2C6000473EB /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0CE08A77148FF2C7000473EB /* main.c in Sources */, - 0CEF580014C0E227000A93B0 /* st_test.c in Sources */, - 0C7CF8D714E18A9F00DF9D95 /* dtls_client.c in Sources */, - 0C6C642715D5A9C200BC68CD /* ssl-utils.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 0CDF46A814DC79FF00FFE2FD /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 0CDF469F14DC794300FFE2FD /* tlssocket */; - targetProxy = 0CDF46A714DC79FF00FFE2FD /* PBXContainerItemProxy */; - }; - 0CE08A83148FF628000473EB /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 0CC9A7EF146DF66000C18F89 /* tlsnke */; - targetProxy = 0CE08A82148FF628000473EB /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 0CC9A7F8146DF66000C18F89 /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 0CC9A7F9146DF66000C18F89 /* en */, - ); - name = InfoPlist.strings; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 0CC9A7FE146DF66000C18F89 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_TREAT_WARNINGS_AS_ERRORS = YES; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - SUPPORTED_PLATFORMS = "iphoneos macosx"; - }; - name = Debug; - }; - 0CC9A7FF146DF66000C18F89 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_TREAT_WARNINGS_AS_ERRORS = YES; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - SUPPORTED_PLATFORMS = "iphoneos macosx"; - }; - name = Release; - }; - 0CC9A801146DF66000C18F89 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "tlsnke/tlsnke-Prefix.pch"; - HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../libsecurity_ssl/lib"; - INFOPLIST_FILE = "tlsnke/tlsnke-Info.plist"; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Extensions"; - MODULE_NAME = com.apple.nke.tls; - MODULE_START = tlsnke_start; - MODULE_STOP = tlsnke_stop; - MODULE_VERSION = 1.0; - PRODUCT_NAME = "$(TARGET_NAME)"; - WRAPPER_EXTENSION = kext; - }; - name = Debug; - }; - 0CC9A802146DF66000C18F89 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "tlsnke/tlsnke-Prefix.pch"; - HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../libsecurity_ssl/lib"; - INFOPLIST_FILE = "tlsnke/tlsnke-Info.plist"; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Extensions"; - MODULE_NAME = com.apple.nke.tls; - MODULE_START = tlsnke_start; - MODULE_STOP = tlsnke_stop; - MODULE_VERSION = 1.0; - PRODUCT_NAME = "$(TARGET_NAME)"; - WRAPPER_EXTENSION = kext; - }; - name = Release; - }; - 0CDF46A214DC794300FFE2FD /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - EXECUTABLE_PREFIX = lib; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 0CDF46A314DC794300FFE2FD /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - EXECUTABLE_PREFIX = lib; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 0CE08A7A148FF2C7000473EB /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - FRAMEWORK_SEARCH_PATHS = "$(inherited)"; - HEADER_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)/usr/local/include"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(BUILT_PRODUCTS_DIR)", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 0CE08A7B148FF2C7000473EB /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - FRAMEWORK_SEARCH_PATHS = "$(inherited)"; - HEADER_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)/usr/local/include"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(BUILT_PRODUCTS_DIR)", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 0CE08A80148FF61C000473EB /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 0CE08A81148FF61C000473EB /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 0CC9A7E8146DF66000C18F89 /* Build configuration list for PBXProject "tlsnke" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0CC9A7FE146DF66000C18F89 /* Debug */, - 0CC9A7FF146DF66000C18F89 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0CC9A800146DF66000C18F89 /* Build configuration list for PBXNativeTarget "tlsnke" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0CC9A801146DF66000C18F89 /* Debug */, - 0CC9A802146DF66000C18F89 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0CDF46A114DC794300FFE2FD /* Build configuration list for PBXNativeTarget "tlssocket" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0CDF46A214DC794300FFE2FD /* Debug */, - 0CDF46A314DC794300FFE2FD /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0CE08A7C148FF2C7000473EB /* Build configuration list for PBXNativeTarget "tlsnketest" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0CE08A7A148FF2C7000473EB /* Debug */, - 0CE08A7B148FF2C7000473EB /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0CE08A7F148FF61C000473EB /* Build configuration list for PBXAggregateTarget "host-loadkext" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0CE08A80148FF61C000473EB /* Debug */, - 0CE08A81148FF61C000473EB /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 0CC9A7E5146DF66000C18F89 /* Project object */; -} diff --git a/tlsnke/tlsnke.xcodeproj/xcuserdata/fabrice.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist b/tlsnke/tlsnke.xcodeproj/xcuserdata/fabrice.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist deleted file mode 100644 index 05301bc2..00000000 --- a/tlsnke/tlsnke.xcodeproj/xcuserdata/fabrice.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/tlsnke/tlsnke/tlsnke.h b/tlsnke/tlsnke/tlsnke.h deleted file mode 100644 index cd4c063a..00000000 --- a/tlsnke/tlsnke/tlsnke.h +++ /dev/null @@ -1,88 +0,0 @@ -// -// tlsnke.h -// tlsnke -// -// Created by Fabrice Gautier on 1/12/12. -// Copyright (c) 2012 Apple, Inc. All rights reserved. -// - -#ifndef __TLSNKE_H__ -#define __TLSNKE_H__ - -/* Those should be defined in kernel headers eg */ - - -#define TLS_HANDLE_IP4 0xBABABABA /* Temp hack to identify this filter */ -#define TLS_HANDLE_IP6 0xABABABAB /* Temp hack to identify this filter */ - - -/* -SO_TLS_HANDLE: -Get the DTLS handle used to enable utun to dtls bypass. (getsockopt only) -option_value type: int -*/ -#define SO_TLS_HANDLE 0x20000 - -/* -SO_TLS_INIT_CIPHER: -Initialize the new cipher key material. (setsockopt only) -option_value type: -struct { - uint16_t cipherspec; - bool server; - int keylen; - char key[keylen]; -} -*/ -#define SO_TLS_INIT_CIPHER 0x20001 - -/* -SO_TLS_PROTOCOL_VERSION: -Set the protocol version. (setsockopt only) -option_value type: int -*/ -#define SO_TLS_PROTOCOL_VERSION 0x20002 - -/* -SO_TLS_ADVANCE_READ_CIPHER: -Update the read cipher to use the new key. (setsockopt only) -No option value. -*/ -#define SO_TLS_ADVANCE_READ_CIPHER 0x20003 - -/* -SO_TLS_ADVANCE_WRITE_CIPHER: -Update the write cipher to use the new key. (setsockopt only) -No option value. -*/ -#define SO_TLS_ADVANCE_WRITE_CIPHER 0x20004 - -/* -SO_TLS_ROLLBACK_WRITE_CIPHER: -Rollback the write cipher to the previous key. (setsockopt only) -No option value. -*/ -#define SO_TLS_ROLLBACK_WRITE_CIPHER 0x20005 - -/* - SO_TLS_SERVICE_WRITE_QUEUE: - Service the record write queue - No option value. - */ -#define SO_TLS_SERVICE_WRITE_QUEUE 0x20006 - - -/* -SCM_TLS_HEADER: - Type of anciallary data for DTLS record header -*/ - -#define SCM_TLS_HEADER 0x12345 - -typedef struct tls_record_hdr{ - uint8_t content_type; - uint16_t protocol_version; -} *tls_record_hdr_t; - - -#endif /* __TLSNKE_H__ */ diff --git a/tlsnke/tlsnketest/main.c b/tlsnke/tlsnketest/main.c deleted file mode 100644 index a27aa69e..00000000 --- a/tlsnke/tlsnketest/main.c +++ /dev/null @@ -1,279 +0,0 @@ -// -// main.c -// tlsnketest -// -// Created by Fabrice Gautier on 12/7/11. -// Copyright (c) 2011 Apple, Inc. All rights reserved. -// - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include "tlssocket.h" -#include "tlsnke.h" - - -static void print_data(const char *s, size_t l, const unsigned char *p) -{ - printf("%s, %zu:",s, l); - for(int i=0; ih_addr); - bzero(&(server_addr.sin_zero),8); - - err = connect(sock, (struct sockaddr *)&server_addr, - sizeof(struct sockaddr)); - if(err) - { - perror("connect"); - return err; - } - - return sock; -} - -/* simple test */ -static int kext_test(const char *hostname, int bypass) -{ - int sock, i; - char send_data[1024]; - int tlsfd; - pthread_t server_thread; - - if(strcmp(hostname, "localhost")==0) { - pthread_create(&server_thread, NULL, server_thread_func, NULL); - // Just wait for the server to be setup - sleep(1); - } - - - sock = create_client_socket(hostname); - - if(bypass) { - /* Have to open this after we attached the filter to the client socket */ - tlsfd=open("/dev/tlsnke", O_RDWR); - if(tlsfd<0) { - perror("open tlsnke"); - exit(1); - } - } - - - for(i=0; i<20;i++) { - int n; - ssize_t err; - n=sprintf(send_data, "Message #%d\n", i); - if(n<0) { - perror("sprintf"); - exit(1); - } - - printf("Client(1) sending %d bytes (\"%s\")\n", n, send_data); - - if(bypass) { - err = write(tlsfd, send_data, n); - if(err<0) { - perror("write to tlsnke"); - exit(1); - } - } else { - SSLRecord rec; - - rec.contentType = SSL_RecordTypeAppData; - rec.protocolVersion = DTLS_Version_1_0; - rec.contents.data = (uint8_t *)send_data; - rec.contents.length = n; - - err = TLSSocket_Funcs.write((intptr_t)sock, rec); - if(err<0) { - perror("write to socket"); - exit(1); - } - - /* serviceWriteQueue every 2 writes, this will trigger rdar://11348395 */ - if(i&1) { - int err; - err = TLSSocket_Funcs.serviceWriteQueue((intptr_t)sock); - if(err<0) { - perror("service write queue"); - exit(1); - } - } - } - - sleep(1); - } - - return 0; -} - - -/* handshake test */ -int st_test(); - -/* echo test */ -int dtls_client(const char *hostname, int bypass); - -static -int usage(const char *argv0) -{ - printf("Usage: %s \n", argv0); - printf(" : type of test: 's'imple, 'h'andshake or 'e'cho] (see below)\n"); - printf(" : hostname of server\n"); - printf(" : use /dev/tlsnke bypass test\n"); - - printf("\n 'S'imple test:\n" - "\tVery basic test with no handshake. DTLS packets are sent through the socket filter, non encrypted.\n" - "\tIf hostname is 'localhost', a local simple server will be created that will also use the tls filter,\n" - "\tsuch that the input path is tested.\n" - "\tOtherwise, a server on the other side is not required only the output path is tested. If there is no server replying\n" - "\tonly the ouput path will be tested. If a server is replying, input packet will be processed but are never read to userspace\n" - "\tif bypass=1, also send the same packet through the /dev/tlsnke interface, as if they were coming from utun\n"); - - printf("\n 'H'andshake:\n"); - printf("\tTest SSL Handshake with various ciphers, between a local client going through the tlsnke\n" - "\tfilter, and a local server using only the userland SecureTransport.\n" - "\thostname and bypass are ignored.\n"); - - printf("\n 'E'cho:\n"); - printf("\tTest to connect to an udp echo server indicated by hostname, on port 23232.\n" - "\tSet bypass=1 to use the /dev/tlsnke bsd device to send/recv the app data (emulate utun behaviour)\n"); - - printf("\n\tbypass=1 require the tlsnke kext to be compiled with TLS_TEST=1 (not the default in the build)\n"); - - return -1; -} - -int main (int argc, const char * argv[]) -{ - - printf("argv0=%s argc=%d\n", argv[0], argc); - if(argc<2) - return usage(argv[0]); - - switch (argv[1][0]) { - case 's': - case 'S': - if(argc<3) return usage(argv[0]); - return kext_test(argv[2], atoi(argv[3])?1:0); - case 'h': - case 'H': - return st_test(); - case 'e': - case 'E': - if(argc<3) return usage(argv[0]); - return dtls_client(argv[2], atoi(argv[3])?1:0); - default: - return usage(argv[0]); - } -} - diff --git a/tlsnke/tlsnketest/ssl-utils.c b/tlsnke/tlsnketest/ssl-utils.c deleted file mode 100644 index f2bf9c1f..00000000 --- a/tlsnke/tlsnketest/ssl-utils.c +++ /dev/null @@ -1,107 +0,0 @@ -// -// ssl-utils.c -// libsecurity_ssl -// -// Created by Fabrice Gautier on 8/7/12. -// -// - -#include -#include - -#include "ssl-utils.h" - -#if TARGET_OS_IPHONE - - -#include -#include -#include -#include -#include - - -#include "privkey-1.h" -#include "cert-1.h" - -static -CFArrayRef chain_from_der(const unsigned char *cert_der, size_t cert_der_len, const unsigned char *pkey_der, size_t pkey_der_len) -{ - SecKeyRef pkey = NULL; - SecCertificateRef cert = NULL; - SecIdentityRef ident = NULL; - CFArrayRef items = NULL; - - require(pkey = SecKeyCreateRSAPrivateKey(kCFAllocatorDefault, pkey_der, pkey_der_len, kSecKeyEncodingPkcs1), errOut); - require(cert = SecCertificateCreateWithBytes(kCFAllocatorDefault, cert_der, cert_der_len), errOut); - require(ident = SecIdentityCreate(kCFAllocatorDefault, cert, pkey), errOut); - require(items = CFArrayCreate(kCFAllocatorDefault, (const void **)&ident, 1, &kCFTypeArrayCallBacks), errOut); - -errOut: - CFReleaseSafe(pkey); - CFReleaseSafe(cert); - CFReleaseSafe(ident); - return items; -} - -#else - -#include "identity-1.h" -#define P12_PASSWORD "password" - -static -CFArrayRef chain_from_p12(const unsigned char *p12_data, size_t p12_len) -{ - char keychain_path[] = "/tmp/keychain.XXXXXX"; - - SecKeychainRef keychain; - CFArrayRef list; - CFDataRef data; - - require_noerr(SecKeychainCopyDomainSearchList(kSecPreferencesDomainUser, &list), errOut); - require(mktemp(keychain_path), errOut); - require_noerr(SecKeychainCreate (keychain_path, strlen(P12_PASSWORD), P12_PASSWORD, - FALSE, NULL, &keychain), errOut); - require_noerr(SecKeychainSetDomainSearchList(kSecPreferencesDomainUser, list), errOut); // restores the previous search list - require(data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, p12_data, p12_len, kCFAllocatorNull), errOut); - - SecExternalFormat format=kSecFormatPKCS12; - SecExternalItemType type=kSecItemTypeAggregate; - SecItemImportExportFlags flags=0; - SecKeyImportExportParameters params = {0,}; - CFArrayRef out = NULL; - - params.passphrase=CFSTR("password"); - params.keyAttributes = CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_SENSITIVE; - - require_noerr(SecKeychainItemImport(data, CFSTR(".p12"), &format, &type, flags, - ¶ms, keychain, &out), errOut); - -errOut: - CFReleaseSafe(keychain); - CFReleaseSafe(list); - - return out; -} - -#endif - -CFArrayRef server_chain(void) -{ -#if TARGET_OS_IPHONE - return chain_from_der(privkey_1_der, privkey_1_der_len, cert_1_der, cert_1_der_len); -#else - return chain_from_p12(identity_1_p12, identity_1_p12_len); -#endif -} - -CFArrayRef client_chain(void) -{ -#if TARGET_OS_IPHONE - return chain_from_der(privkey_1_der, privkey_1_der_len, cert_1_der, cert_1_der_len); -#else - return chain_from_p12(identity_1_p12, identity_1_p12_len); -#endif -} - - diff --git a/tlsnke/tlsnketest/ssl-utils.h b/tlsnke/tlsnketest/ssl-utils.h deleted file mode 100644 index 5ac94148..00000000 --- a/tlsnke/tlsnketest/ssl-utils.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// ssl-utils.h -// libsecurity_ssl -// -// Created by Fabrice Gautier on 8/7/12. -// -// - -#ifndef __SSL_UTILS_H__ -#define __SSL_UTILS_H__ - -#define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) { CFRelease(_cf); } } -#define CFReleaseNull(CF) { CFTypeRef _cf = (CF); if (_cf) { (CF) = NULL; CFRelease(_cf); } } - -CFArrayRef server_chain(void); -CFArrayRef client_chain(void); - -#endif diff --git a/tlsnke/tlsnketest/tlssocket.h b/tlsnke/tlsnketest/tlssocket.h deleted file mode 100644 index 3d43df16..00000000 --- a/tlsnke/tlsnketest/tlssocket.h +++ /dev/null @@ -1,43 +0,0 @@ -// -// tlssocket.h -// tlsnke -// -// Created by Fabrice Gautier on 1/6/12. -// Copyright (c) 2012 Apple, Inc. All rights reserved. -// - -#ifndef __TLSSOCKET_H__ -#define __TLSSOCKET_H__ - -#include - -/* - Attach the TLS socket filter. - - This makes a socket a TLS socket by attaching the TLS socket filter to that socket. - Return a positive TLS handle or a negative error. - The return TLS handle can be used to route VPN data directly through this TLS - socket - */ -int TLSSocket_Attach(int socket); - -/* - Detach the TLS socket filter. - - Return 0 or negative error. - If the TLS Socket is used with SecureTransport, one should make sure - to tear down the SecureTransport session before calling this. - It is not required to use this, as closing the socket would have the same effect. -*/ -int TLSSocket_Detach(int socket); - -/* - Secure Transport Record Layer functions for TLS Sockets. - - To use SecureTransport with a TLS kernel socket, pass this to SSLSetRecordFuncs and - the socket descriptor to SSLSetRecordContext - */ -const struct SSLRecordFuncs TLSSocket_Funcs; - - -#endif diff --git a/utilities/Regressions/su-10-cfstring-der.c b/utilities/Regressions/su-10-cfstring-der.c deleted file mode 100644 index efcd6fce..00000000 --- a/utilities/Regressions/su-10-cfstring-der.c +++ /dev/null @@ -1,90 +0,0 @@ -// -// su-10-cfstring-der.c -// utilities -// -// Created by Mitch Adler on 6/18/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#include "utilities/der_plist.h" -#include "utilities/der_plist_internal.h" - -#include "utilities/SecCFRelease.h" -#include "utilities/array_size.h" - -#include - -#include "utilities_regressions.h" - - -#define kMaxResultSize 256 - -struct test_case { - CFStringRef str; - size_t size; - uint8_t res[kMaxResultSize]; -}; - -static struct test_case test_cases[] = { - { .str = CFSTR("FOO"), .size = 5, .res = { 0x0C, 0x03, 0x46, 0x4F, 0x4F, } }, - { .str = CFSTR("!ß∂ƒ˙圈ø¥®xzfff"), .size = 29, .res = { 0x0C, 0x1B, 0x21, 0xC3, 0x9F, 0xE2, 0x88, 0x82, 0xC6, 0x92, - 0xCB, 0x99, 0xC3, 0xA5, 0xC5, 0x93, 0xCB, 0x86, 0xC3, 0xB8, - 0xC2, 0xA5, 0xC2, 0xAE, 0x78, 0x7A, 0x66, 0x66, 0x66, } }, -}; - - -#define kTestsPerTestCase 8 -static void one_test(const struct test_case * thisCase) -{ - uint8_t buffer[4 * kMaxResultSize + 1]; - uint8_t* buffer_end = buffer + sizeof(buffer); - - uint8_t* encoded = der_encode_string(thisCase->str, NULL, buffer, buffer_end); - - ok(encoded != NULL && - (thisCase->size == (buffer_end - encoded)) && - (memcmp(encoded, thisCase->res, thisCase->size) == 0)); - - CFStringRef decoded = NULL; - - const uint8_t* decode_end = der_decode_string(NULL, kCFPropertyListMutableContainersAndLeaves, - &decoded, NULL, encoded, buffer_end); - - ok(decode_end == buffer_end); - ok((decoded != NULL) && CFEqual(decoded, thisCase->str)); - - encoded = der_encode_plist(thisCase->str, NULL, buffer, buffer_end); - - ok(encoded != NULL && - (thisCase->size == (buffer_end - encoded)) && - (memcmp(encoded, thisCase->res, thisCase->size) == 0)); - - CFTypeRef decoded_type = NULL; - - decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainersAndLeaves, - &decoded_type, NULL, encoded, buffer_end); - - ok(decode_end == buffer_end); - ok((decoded_type != NULL) && CFEqual(decoded_type, thisCase->str)); - - ok(der_sizeof_string(thisCase->str, NULL) == thisCase->size); - ok(der_sizeof_plist(thisCase->str, NULL) == thisCase->size); - - CFReleaseNull(decoded); - CFReleaseNull(decoded_type); -} - -#define kTestCount (array_size(test_cases) * kTestsPerTestCase) -static void tests(void) -{ - for (int testnumber = 0; testnumber < array_size(test_cases); ++testnumber) - one_test(test_cases + testnumber); -} - -int su_10_cfstring_der(int argc, char *const *argv) -{ - plan_tests(kTestCount); - tests(); - - return 0; -} diff --git a/utilities/Regressions/su-12-cfboolean-der.c b/utilities/Regressions/su-12-cfboolean-der.c deleted file mode 100644 index 45f20282..00000000 --- a/utilities/Regressions/su-12-cfboolean-der.c +++ /dev/null @@ -1,86 +0,0 @@ -// -// su-11-cfdata-der.c -// utilities -// -// Created by Mitch Adler on 6/20/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#include "utilities/der_plist.h" -#include "utilities/der_plist_internal.h" - -#include "utilities/SecCFRelease.h" -#include "utilities/array_size.h" - -#include - -#include "utilities_regressions.h" - -#define kMaxResultSize 16 - -#define kTestsPerTestCase 8 -static void one_test(CFBooleanRef value, size_t der_size, const uint8_t *expected_der) -{ - - uint8_t buffer[kMaxResultSize]; - uint8_t *buffer_end = buffer + sizeof(buffer); - - uint8_t* encoded = der_encode_plist(value, NULL, buffer, buffer_end); - - ok(encoded != NULL && - (der_size == (buffer_end - encoded)) && - (memcmp(encoded, expected_der, der_size) == 0)); - - encoded = der_encode_boolean(value, NULL, buffer, buffer_end); - - ok(encoded != NULL && - (der_size == (buffer_end - encoded)) && - (memcmp(encoded, expected_der, der_size) == 0)); - -#if 0 - printf(".size = %d, .res = { ", (buffer_end - encoded)); - for(int c = 0; c < (buffer_end - encoded); ++c) - printf("0x%02X, ", encoded[c]); - printf("},\n"); -#endif - - CFBooleanRef decoded = NULL; - const uint8_t* decode_end = der_decode_boolean(NULL, kCFPropertyListMutableContainersAndLeaves, - &decoded, NULL, encoded, buffer_end); - - ok(decode_end == buffer_end); - ok((decoded != NULL) && CFEqual(decoded, value)); - - CFPropertyListRef decoded_type = NULL; - decode_end = der_decode_plist(NULL, kCFPropertyListMutableContainersAndLeaves, - &decoded_type, NULL, encoded, buffer_end); - - ok(decode_end == buffer_end); - ok((decoded != NULL) && CFEqual(decoded_type, value)); - - ok(der_sizeof_boolean(value, NULL) == der_size); - ok(der_sizeof_plist(value, NULL) == der_size); - - CFReleaseNull(decoded); - CFReleaseNull(decoded_type); -} - -#define kTestCount (2 * kTestsPerTestCase) -static void tests(void) -{ - const uint8_t der_true[] = { 0x01, 0x01, 0x01 }; - - one_test(kCFBooleanTrue, sizeof(der_true), der_true); - - const uint8_t der_false[] = { 0x01, 0x01, 0x00 }; - - one_test(kCFBooleanFalse, sizeof(der_false), der_false); -} - -int su_12_cfboolean_der(int argc, char *const *argv) -{ - plan_tests(kTestCount); - tests(); - - return 0; -} diff --git a/utilities/SecurityTool/not_on_this_platorm.c b/utilities/SecurityTool/not_on_this_platorm.c deleted file mode 100644 index da4ca131..00000000 --- a/utilities/SecurityTool/not_on_this_platorm.c +++ /dev/null @@ -1,14 +0,0 @@ -// -// File.c -// utilities -// -// Created by J Osborne on 1/11/13. -// Copyright (c) 2013 Apple Inc. All rights reserved. -// - -int command_not_on_this_platform(int argc, char * const *argv); - -int command_not_on_this_platform(int argc, char * const *argv) -{ - return 0; -} \ No newline at end of file diff --git a/utilities/SecurityTool/readline.c b/utilities/SecurityTool/readline.c deleted file mode 100644 index c0132d4a..00000000 --- a/utilities/SecurityTool/readline.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (c) 2003-2004,2006-2010 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@ - * - * readline.c - */ - -#include "readline.h" - -#include -#include -#include -#include -#include -#include - -/* Read a line from stdin into buffer as a null terminated string. If buffer is - non NULL use at most buffer_size bytes and return a pointer to buffer. Otherwise - return a newly malloced buffer. - if EOF is read this function returns NULL. */ -char * -readline(char *buffer, int buffer_size) -{ - int ix = 0, bytes_malloced = 0; - - if (!buffer) - { - bytes_malloced = 64; - buffer = (char *)malloc(bytes_malloced); - buffer_size = bytes_malloced; - } - - for (;;++ix) - { - int ch; - - if (ix == buffer_size - 1) - { - if (!bytes_malloced) - break; - bytes_malloced += bytes_malloced; - buffer = (char *)realloc(buffer, bytes_malloced); - buffer_size = bytes_malloced; - } - - ch = getchar(); - if (ch == EOF) - { - if (bytes_malloced) - free(buffer); - return NULL; - } - if (ch == '\n') - break; - buffer[ix] = ch; - } - - /* 0 terminate buffer. */ - buffer[ix] = '\0'; - - return buffer; -} - -/* Read the file name into buffer. On return buffer contains a newly - malloced buffer or length buffer_size. Return 0 on success and -1 on failure. */ -int -read_file(const char *name, uint8_t **outData, size_t *outLength) -{ - int fd, result; - char *buffer = NULL; - off_t off_end; - ssize_t bytes_read; - size_t length; - - do { - fd = open(name, O_RDONLY, 0); - } while (fd == -1 && errno == EINTR); - - if (fd == -1) - { - fprintf(stderr, "open %s: %s", name, strerror(errno)); - result = -1; - goto loser; - } - - off_end = lseek(fd, 0, SEEK_END); - if (off_end == -1) - { - fprintf(stderr, "lseek %s, SEEK_END: %s", name, strerror(errno)); - result = -1; - goto loser; - } - - if (off_end > (off_t)SIZE_MAX) { - fprintf(stderr, "file %s too large %llu bytes", name, off_end); - result = -1; - goto loser; - } - - length = (size_t)off_end; - buffer = malloc(length); - - do { - bytes_read = pread(fd, buffer, length, 0); - } while (bytes_read == -1 && errno == EINTR); - - if (bytes_read == -1) - { - fprintf(stderr, "pread %s: %s", name, strerror(errno)); - result = -1; - goto loser; - } - if (bytes_read != (ssize_t)length) - { - fprintf(stderr, "read %s: only read %zu of %zu bytes", name, bytes_read, length); - result = -1; - goto loser; - } - - do { - result = close(fd); - } while (result == -1 && errno == EINTR); - - if (result == -1) - { - fprintf(stderr, "close %s: %s", name, strerror(errno)); - goto loser; - } - - *outData = (uint8_t *)buffer; - *outLength = length; - - return result; - -loser: - if (buffer) - free(buffer); - - return result; -} - -CFDataRef copyFileContents(const char *path) { - CFMutableDataRef data = NULL; - int fd = open(path, O_RDONLY, 0666); - if (fd == -1) { - fprintf(stderr, "open %s: %s", path, strerror(errno)); - goto badFile; - } - - off_t fsize = lseek(fd, 0, SEEK_END); - if (fsize == (off_t)-1) { - fprintf(stderr, "lseek %s, 0, SEEK_END: %s", path, strerror(errno)); - goto badFile; - } - - if (fsize > (off_t)INT32_MAX) { - fprintf(stderr, "file %s too large %llu bytes", path, fsize); - goto badFile; - } - - data = CFDataCreateMutable(kCFAllocatorDefault, (CFIndex)fsize); - CFDataSetLength(data, (CFIndex)fsize); - void *buf = CFDataGetMutableBytePtr(data); - off_t total_read = 0; - while (total_read < fsize) { - ssize_t bytes_read; - - bytes_read = pread(fd, buf, (size_t)(fsize - total_read), total_read); - if (bytes_read == -1) { - fprintf(stderr, "read %s: %s", path, strerror(errno)); - goto badFile; - } - if (bytes_read == 0) { - fprintf(stderr, "read %s: unexpected end of file", path); - goto badFile; - } - total_read += bytes_read; - } - - if (close(fd) == -1) { - fprintf(stderr, "close %s: %s", path, strerror(errno)); - /* Failure to close the file isn't fatal. */ - } - - return data; -badFile: - if (fd != -1) { - if (close(fd) == -1) { - fprintf(stderr, "close %s: %s", path, strerror(errno)); - } - } - if (data) - CFRelease(data); - return NULL; -} - - -bool writeFileContents(const char *path, CFDataRef data) { - int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666); - if (fd == -1) { - fprintf(stderr, "open %s: %s", path, strerror(errno)); - goto badFile; - } - - const void *buf = CFDataGetBytePtr(data); - off_t fsize = CFDataGetLength(data); - - off_t total_write = 0; - while (total_write < fsize) { - ssize_t bytes_write; - - bytes_write = pwrite(fd, buf, (size_t)(fsize - total_write), total_write); - if (bytes_write == -1) { - fprintf(stderr, "write %s: %s", path, strerror(errno)); - goto badFile; - } - if (bytes_write == 0) { - fprintf(stderr, "write %s: unexpected end of file", path); - goto badFile; - } - total_write += bytes_write; - } - - if (close(fd) == -1) { - fprintf(stderr, "close %s: %s", path, strerror(errno)); - /* Failure to close the file isn't fatal. */ - } - - return true; -badFile: - if (fd != -1) { - if (close(fd) == -1) { - fprintf(stderr, "close %s: %s", path, strerror(errno)); - } - } - if (data) - CFRelease(data); - return false; -} diff --git a/utilities/SecurityTool/readline.h b/utilities/SecurityTool/readline.h deleted file mode 100644 index a82449aa..00000000 --- a/utilities/SecurityTool/readline.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2003-2004,2006-2010 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@ - * - * readline.h - */ - -#ifndef _READLINE_H_ -#define _READLINE_H_ 1 - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Read a line from stdin into buffer as a null terminated string. If buffer is - non NULL use at most buffer_size bytes and return a pointer to buffer. Otherwise - return a newly malloced buffer. - if EOF is read this function returns NULL. */ -extern char *readline(char *buffer, int buffer_size); - -/* Read the file name into buffer. On return outData.Data contains a newly - malloced buffer of outData.Length bytes. Return 0 on success and -1 on failure. */ -extern int read_file(const char *name, uint8_t **outData, size_t *outLength); - -extern CFDataRef copyFileContents(const char *path); - -extern bool writeFileContents(const char *path, CFDataRef data); - -#ifdef __cplusplus -} -#endif - -#endif /* _READLINE_H_ */ diff --git a/utilities/SecurityTool/security_tool_commands.h b/utilities/SecurityTool/security_tool_commands.h deleted file mode 100644 index 48a50f7a..00000000 --- a/utilities/SecurityTool/security_tool_commands.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// security_tool_commands.h -// Security -// -// Created by Mitch Adler on 1/9/13. -// -// - -// This is included to make SECURITY_COMMAND macros result in declarations of -// commands for use in SecurityTool - -#ifndef SECURITY_COMMAND -#define SECURITY_COMMAND(name, function, parameters, description) int function(int argc, char * const *argv); - -#if TARGET_OS_EMBEDDED -#define SECURITY_COMMAND_IOS(name, function, parameters, description) int function(int argc, char * const *argv); -#else -#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)) -#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); -#endif - - -#endif diff --git a/utilities/SecurityTool/security_tool_commands_table.h b/utilities/SecurityTool/security_tool_commands_table.h deleted file mode 100644 index c44ce69f..00000000 --- a/utilities/SecurityTool/security_tool_commands_table.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// security_tool_commands_table.h -// utilities -// -// Created by J Osborne on 1/11/13. -// Copyright (c) 2013 Apple Inc. All rights reserved. -// - - -// This is included to make SECURITY_COMMAND macros result in table of -// commands for use in SecurityTool - -#undef SECURITY_COMMAND -#undef SECURITY_COMMAND_IOS -#undef SECURITY_COMMAND_MAC -#define SECURITY_COMMAND(name, function, parameters, description) { name, function, parameters, description }, - -#if TARGET_OS_EMBEDDED -#define SECURITY_COMMAND_IOS(name, function, parameters, description) { name, function, parameters, description }, -#else -#define SECURITY_COMMAND_IOS(name, function, parameters, description) { name, command_not_on_this_platform, "", "Not avilable on this platform" }, -#endif - -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) -#define SECURITY_COMMAND_MAC(name, function, parameters, description) { name, function, parameters, description }, -#else -#define SECURITY_COMMAND_MAC(name, function, parameters, description) { name, command_not_on_this_platform, "", "Not avilable on this platform" }, -#endif - diff --git a/utilities/src/SecAKSWrappers.h b/utilities/src/SecAKSWrappers.h deleted file mode 100644 index d9683742..00000000 --- a/utilities/src/SecAKSWrappers.h +++ /dev/null @@ -1,105 +0,0 @@ -// -// SecAKSWrappers.h -// utilities -// -// Created by Mitch Adler on 6/5/13. -// Copyright (c) 2013 Apple Inc. All rights reserved. -// - -#ifndef _SECAKSWRAPPERS_H_ -#define _SECAKSWRAPPERS_H_ - -#include -#include -#include - -#if TARGET_IPHONE_SIMULATOR - -#include - -// Make the compiler happy so this will compile. -#define device_keybag_handle 0 -#define session_keybag_handle 0 - -enum keybag_state { - keybag_state_unlocked = 0, - keybag_state_locked = 1 << 0, - keybag_state_no_pin = 1 << 1, - keybag_state_been_unlocked = 1 << 2, -}; -typedef uint32_t keybag_state_t; -typedef int32_t keybag_handle_t; - -static kern_return_t aks_get_lock_state(keybag_handle_t handle, keybag_state_t *state) { - if (state) *state = keybag_state_no_pin & keybag_state_been_unlocked; - return kIOReturnSuccess; -} - -#else - -#include - -#endif - -// -// MARK: User lock state -// - -enum { - user_keybag_handle = TARGET_OS_EMBEDDED ? device_keybag_handle : session_keybag_handle, -}; - -extern const char * const kUserKeybagStateChangeNotification; - -static inline bool SecAKSGetLockedState(keybag_state_t *state, CFErrorRef* error) -{ - kern_return_t status = aks_get_lock_state(user_keybag_handle, state); - - if (kIOReturnSuccess != status) { - SecCFCreateError(status, CFSTR("com.apple.kern_return_t"), CFSTR("Kern return error"), NULL, error); - return false; - } - - return true; -} - -// returns true if any of the bits in bits is set in the current state of the user bag -static inline bool SecAKSLockedAnyStateBitIsSet(bool* isSet, keybag_state_t bits, CFErrorRef* error) -{ - keybag_state_t state; - bool success = SecAKSGetLockedState(&state, error); - - require_quiet(success, exit); - - if (isSet) - *isSet = (state & bits); - -exit: - return success; - -} - -static inline bool SecAKSGetIsLocked(bool* isLocked, CFErrorRef* error) -{ - return SecAKSLockedAnyStateBitIsSet(isLocked, keybag_state_locked, error); -} - -static inline bool SecAKSGetIsUnlocked(bool* isUnlocked, CFErrorRef* error) -{ - bool isLocked = false; - bool success = SecAKSGetIsLocked(&isLocked, error); - - if (success && isUnlocked) - *isUnlocked = !isLocked; - - return success; -} - -static inline bool SecAKSGetHasBeenUnlocked(bool* hasBeenUnlocked, CFErrorRef* error) -{ - return SecAKSLockedAnyStateBitIsSet(hasBeenUnlocked, keybag_state_been_unlocked, error); -} - -bool SecAKSDoWhileUserBagLocked(CFErrorRef *error, dispatch_block_t action); - -#endif diff --git a/utilities/src/SecCFCanonicalHashes.c b/utilities/src/SecCFCanonicalHashes.c deleted file mode 100644 index 3d5a133d..00000000 --- a/utilities/src/SecCFCanonicalHashes.c +++ /dev/null @@ -1,120 +0,0 @@ -// -// SecCFCanonicalHashes.c -// utilities -// -// Created by Mitch Adler on 2/8/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#include - -#include "utilities/SecCFCanonicalHashes.h" -#include "utilities/comparison.h" - -#include -#include -#include -#include -#include - -struct AddKeyValueHashContext { - CFMutableArrayRef array; - const struct ccdigest_info* di; - bool fail; -}; - -static void AddKeyValueHashData(const void *key, const void *value, void *context) -{ - struct AddKeyValueHashContext* akvContext = (struct AddKeyValueHashContext*) context; - - size_t key_len; - const void* key_data; - if (CFGetTypeID(key) == CFStringGetTypeID()) { - key_len = CFStringGetLength((CFStringRef) key); - key_data = CFStringGetCharactersPtr((CFStringRef) key); - } else { - akvContext->fail = true; - return; - } - - size_t value_len; - const void* value_data; - if (CFGetTypeID(key) == CFStringGetTypeID()) { - value_len = CFStringGetLength((CFStringRef) value); - value_data = CFStringGetCharactersPtr((CFStringRef) value); - } else if (CFGetTypeID(key) == CFDataGetTypeID()) { - value_len = CFDataGetLength((CFDataRef)value); - value_data = CFDataGetBytePtr((CFDataRef)value); - } else { - akvContext->fail = true; - return; - } - - UInt8 hashBuffer[akvContext->di->output_size]; - - ccdigest_di_decl(akvContext->di, finalContext); - - ccdigest(akvContext->di, key_len, key_data, hashBuffer); - - ccdigest_init(akvContext->di, finalContext); - ccdigest_update(akvContext->di, finalContext, sizeof(hashBuffer), hashBuffer); - - ccdigest_update(akvContext->di, finalContext, sizeof(hashBuffer), hashBuffer); - ccdigest(akvContext->di, value_len, value_data, hashBuffer); - - ccdigest_final(akvContext->di, finalContext, (void*)hashBuffer); - - CFDataRef hash = CFDataCreate(kCFAllocatorDefault, hashBuffer, sizeof(hashBuffer)); - CFArrayAppendValue(akvContext->array, hash); - CFReleaseSafe(hash); -} - -static CFComparisonResult CFDataCompare(CFDataRef d1, CFDataRef d2) -{ - CFIndex d1_size = CFDataGetLength(d1); - CFIndex d2_size = CFDataGetLength(d2); - - CFIndex comparison = memcmp(CFDataGetBytePtr(d1), CFDataGetBytePtr(d2), MIN(d1_size, d2_size)); - - if (comparison == 0) - comparison = d1_size - d2_size; - - return (comparison > 0) ? kCFCompareGreaterThan : ((comparison < 0) ? kCFCompareLessThan : kCFCompareEqualTo); -} - -static CFComparisonResult CFEqualComparitor(const void *val1, const void *val2, void * context __unused) -{ - return CFDataCompare((CFDataRef) val1, (CFDataRef) val2); -} - -struct array_hashing_context { - const struct ccdigest_info* di; - struct ccdigest_ctx * ctx; -}; - -static void hash_CFDatas(const void *value, void *context) -{ - struct array_hashing_context* ahc = (struct array_hashing_context*) context; - - ccdigest_update(ahc->di, ahc->ctx, CFDataGetLength((CFDataRef) value), CFDataGetBytePtr((CFDataRef) value)); -} - - -bool SecCFAppendCFDictionaryHash(CFDictionaryRef thisDictionary, const struct ccdigest_info* di, CFMutableDataRef toThis) -{ - CFMutableArrayRef hashArray = CFArrayCreateMutable(kCFAllocatorDefault, CFDictionaryGetCount(thisDictionary), &kCFTypeArrayCallBacks); - - CFDictionaryApplyFunction(thisDictionary, &AddKeyValueHashData, hashArray); - - CFRange wholeArray = CFRangeMake(0, CFArrayGetCount(hashArray)); - - CFArraySortValues(hashArray, wholeArray, &CFEqualComparitor, NULL); - - ccdigest_di_decl(di, finalContext); - - struct array_hashing_context ahc = { .di = di, .ctx = (struct ccdigest_ctx*)&finalContext}; - - CFArrayApplyFunction(hashArray, wholeArray, hash_CFDatas, &ahc); - - return true; -} diff --git a/utilities/src/SecCFCanonicalHashes.h b/utilities/src/SecCFCanonicalHashes.h deleted file mode 100644 index 39f35a4e..00000000 --- a/utilities/src/SecCFCanonicalHashes.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// SecCFCanonicalHashes.h -// Security -// -// Created by Mitch Adler on 2/8/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#ifndef _SECCFCANONICALHASHES_H_ -#define _SECCFCANONICALHASHES_H_ - -#include -#include - -#include - -bool SecCFAppendCFDictionaryHash(CFDictionaryRef thisDictionary, const struct ccdigest_info* di, CFMutableDataRef toThis); - - -#endif diff --git a/utilities/src/SecCFError.c b/utilities/src/SecCFError.c deleted file mode 100644 index cd259433..00000000 --- a/utilities/src/SecCFError.c +++ /dev/null @@ -1,106 +0,0 @@ -// -// SecCFError.c -// utilities -// -// Created by Mitch Adler on 7/18/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#include -#include -#include -#include - -bool SecKernError(kern_return_t result, CFErrorRef *error, CFStringRef format, ...) { - if (!result) return true; - if (error) { - va_list args; - CFIndex code = result; - CFErrorRef previousError = *error; - - *error = NULL; - va_start(args, format); - SecCFCreateErrorWithFormatAndArguments(code, kSecKernDomain, previousError, error, NULL, format, args); - va_end(args); - } - return false; -} - -bool SecCheckErrno(int result, CFErrorRef *error, CFStringRef format, ...) { - if (result == 0) return true; - if (error) { - va_list args; - int errnum = errno; - CFIndex code = errnum; - CFErrorRef previousError = *error; - - *error = NULL; - va_start(args, format); - CFStringRef message = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, format, args); - va_end(args); - SecCFCreateErrorWithFormat(code, kSecErrnoDomain, previousError, error, NULL, CFSTR("%@: [%d] %s"), message, errnum, strerror(errnum)); - CFReleaseSafe(message); - } - return false; -} - -bool SecError(OSStatus status, CFErrorRef *error, CFStringRef format, ...) { - if (status == errSecSuccess) return true; - if (error) { - va_list args; - CFIndex code = status; - CFErrorRef previousError = *error; - - *error = NULL; - va_start(args, format); - SecCFCreateErrorWithFormatAndArguments(code, kSecErrorDomain, previousError, error, NULL, format, args); - va_end(args); - } - return false; -} - - -void SecCFCreateError(CFIndex errorCode, CFStringRef domain, CFStringRef descriptionString, - CFErrorRef previousError, CFErrorRef *newError) -{ -#pragma clang diagnostic push -#pragma GCC diagnostic ignored "-Wformat-security" - SecCFCreateErrorWithFormat(errorCode, domain, previousError, newError, NULL, descriptionString); -#pragma clang diagnostic pop -} - -void SecCFCreateErrorWithFormat(CFIndex errorCode, CFStringRef domain, CFErrorRef previousError, CFErrorRef *newError, - CFDictionaryRef formatoptions, CFStringRef format, ...) -{ - va_list args; - va_start(args, format); - - SecCFCreateErrorWithFormatAndArguments(errorCode, domain, previousError, newError, formatoptions, format, args); - - va_end(args); -} - -void SecCFCreateErrorWithFormatAndArguments(CFIndex errorCode, CFStringRef domain, - CFErrorRef previousError, CFErrorRef *newError, - CFDictionaryRef formatoptions, CFStringRef format, va_list args) -{ - if (newError && !(*newError)) { - CFStringRef formattedString = CFStringCreateWithFormatAndArguments(NULL, formatoptions, format, args); - - const void* keys[2] = { kCFErrorDescriptionKey, kCFErrorUnderlyingErrorKey}; - const void* values[2] = { formattedString, previousError }; - const CFIndex numEntriesToUse = (previousError != NULL) ? 2 : 1; - - *newError = CFErrorCreateWithUserInfoKeysAndValues(kCFAllocatorDefault, domain, errorCode, - keys, values, numEntriesToUse); - - CFReleaseNull(formattedString); - if (previousError) - secnotice("error", "encapsulated %@ with new error: %@", previousError, *newError); - } else { - if (previousError && newError && (previousError != *newError)) { - secnotice("error", "dropping %@", previousError); - CFRelease(previousError); - } - } -} diff --git a/utilities/src/SecCFError.h b/utilities/src/SecCFError.h deleted file mode 100644 index 3bfb6765..00000000 --- a/utilities/src/SecCFError.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// SecCFError.h -// utilities -// -// Created by Mitch Adler on 7/18/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#ifndef _SECCFERROR_H_ -#define _SECCFERROR_H_ - -#include - -// -// Leaf error creation from other systems -// - -// kern_return_t errors -#define kSecKernDomain kCFErrorDomainMach -bool SecKernError(kern_return_t result, CFErrorRef *error, CFStringRef format, ...); - -// Unix errno errors -#define kSecErrnoDomain kCFErrorDomainPOSIX -bool SecCheckErrno(int result, CFErrorRef *error, CFStringRef format, ...); - -// OSStatus errors -#define kSecErrorDomain kCFErrorDomainOSStatus -bool SecError(OSStatus status, CFErrorRef *error, CFStringRef format, ...); - -// -// Create and chain -// -void SecCFCreateError(CFIndex errorCode, CFStringRef domain, CFStringRef descriptionString, - CFErrorRef previousError, CFErrorRef *newError); - -void SecCFCreateErrorWithFormat(CFIndex errorCode, CFStringRef domain, CFErrorRef previousError, CFErrorRef *newError, - CFDictionaryRef formatoptions, CFStringRef descriptionString, ...) - CF_FORMAT_FUNCTION(6,7); - - -void SecCFCreateErrorWithFormatAndArguments(CFIndex errorCode, CFStringRef domain, - CFErrorRef previousError, CFErrorRef *newError, - CFDictionaryRef formatoptions, CFStringRef descriptionString, va_list args) - CF_FORMAT_FUNCTION(6, 0); - -#endif diff --git a/utilities/src/SecCFRelease.h b/utilities/src/SecCFRelease.h deleted file mode 100644 index f63eabf9..00000000 --- a/utilities/src/SecCFRelease.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// SecCFRelease.h -// utilities -// -// Created by Mitch Adler on 2/9/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#ifndef _SECCFRELEASE_H_ -#define _SECCFRELEASE_H_ - -#include - -#define CFRetainSafe(CF) { \ - CFTypeRef _cf = (CF); \ - if (_cf) \ - CFRetain(_cf); \ - } - -#define CFReleaseSafe(CF) { \ - CFTypeRef _cf = (CF); \ - if (_cf) \ - CFRelease(_cf); \ - } - -#define CFReleaseNull(CF) { \ - CFTypeRef _cf = (CF); \ - if (_cf) { \ - (CF) = NULL; \ - CFRelease(_cf); \ - } \ - } - -#endif diff --git a/utilities/src/SecCFWrappers.c b/utilities/src/SecCFWrappers.c deleted file mode 100644 index d16ed676..00000000 --- a/utilities/src/SecCFWrappers.c +++ /dev/null @@ -1,71 +0,0 @@ -// -// SecCFWrappers.c -// utilities -// -// Created by Michael Brouwer on 11/15/12. -// Copyright 2012 Apple Inc. All rights reserved. -// - -#include - -void CFStringPerformWithCStringAndLength(CFStringRef inStr, void(^operation)(const char *utf8String, size_t utf8Length)) { - const char *cstr = CFStringGetCStringPtr(inStr, kCFStringEncodingUTF8); - if (cstr) { - operation(cstr, strlen(cstr)); - } else { - CFIndex neededLen = 0; - CFRange range = { 0, CFStringGetLength(inStr) }; - CFStringGetBytes(inStr, range, kCFStringEncodingUTF8, - 0, FALSE, NULL, 0, &neededLen); - CFIndex usedLen = 0; - if (neededLen < 4096) { - char buf[neededLen + 1]; - CFStringGetBytes(inStr, range, kCFStringEncodingUTF8, - 0, FALSE, (UInt8 *)buf, neededLen, &usedLen); - assert(usedLen == neededLen); - buf[usedLen] = 0; - operation(buf, (size_t)usedLen); - //cc_zero(neededLen, buf); - } else { - char *buf = malloc(neededLen + 1); - CFStringGetBytes(inStr, range, kCFStringEncodingUTF8, - 0, FALSE, (UInt8 *)buf, neededLen, &usedLen); - assert(usedLen == neededLen); - buf[usedLen] = 0; - operation(buf, (size_t)usedLen); - //cc_zero(neededLen, buf); - free(buf); - } - } -} - -void CFStringPerformWithCString(CFStringRef inStr, void(^operation)(const char *utf8String)) { - const char *cstr = CFStringGetCStringPtr(inStr, kCFStringEncodingUTF8); - if (cstr) { - operation(cstr); - } else { - CFIndex neededLen = 0; - CFRange range = { 0, CFStringGetLength(inStr) }; - CFStringGetBytes(inStr, range, kCFStringEncodingUTF8, - 0, FALSE, NULL, 0, &neededLen); - CFIndex usedLen = 0; - if (neededLen < 4096) { - char buf[neededLen + 1]; - CFStringGetBytes(inStr, range, kCFStringEncodingUTF8, - 0, FALSE, (UInt8 *)buf, neededLen, &usedLen); - assert(usedLen == neededLen); - buf[usedLen] = 0; - operation(buf); - //cc_zero(neededLen, buf); - } else { - char *buf = malloc(neededLen + 1); - CFStringGetBytes(inStr, range, kCFStringEncodingUTF8, - 0, FALSE, (UInt8 *)buf, neededLen, &usedLen); - assert(usedLen == neededLen); - buf[usedLen] = 0; - operation(buf); - //cc_zero(neededLen, buf); - free(buf); - } - } -} diff --git a/utilities/src/SecCFWrappers.h b/utilities/src/SecCFWrappers.h deleted file mode 100644 index 93bcc926..00000000 --- a/utilities/src/SecCFWrappers.h +++ /dev/null @@ -1,585 +0,0 @@ -// -// SecCFWrappers.h -// -// Created by Mitch Adler on 1/27/11. -// Copyright 2011 Apple Inc. All rights reserved. -// - -#ifndef _SECCFWRAPPERS_H_ -#define _SECCFWRAPPERS_H_ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - - -// -// Convenience routines. -// - -// -// Macros for the pattern -// -// typedef struct _privateNewClass* NewClassRef; -// -// struct _privateNewClass { -// CFRuntimeBase _base; -// ... class additions -// }; -// -// kClassNameRegisterClass -// kClassNameTypeID -// -// ClassNameGetTypeID() -// -// CFGiblisFor(NewClass); -// -// .. define NewClassDestroy -// .. define NewClassCopyDescription -// -// .. use CFTypeAllocate(NewClass, _privateNewClass, allocator); -// -// - -#define CFGiblisWithFunctions(gibliClassName, describe_func, destroy_func, compare_func, hash_func) \ - CFTypeID gibliClassName##GetTypeID(void); \ - CFTypeID gibliClassName##GetTypeID(void) { \ - static dispatch_once_t k##gibliClassName##RegisterClass; \ - static CFTypeID k##gibliClassName##TypeID = _kCFRuntimeNotATypeID; \ - \ - dispatch_once(&k##gibliClassName##RegisterClass, ^{ \ - static const CFRuntimeClass k##gibliClassName##Class = { \ - .className = #gibliClassName, \ - .finalize = destroy_func, \ - .copyDebugDesc = describe_func, \ - .equal = compare_func, \ - .hash = hash_func, \ - }; \ - \ - k##gibliClassName##TypeID = _CFRuntimeRegisterClass(&k##gibliClassName##Class); \ - }); \ - return k##gibliClassName##TypeID; \ - } - - -#define CFGiblisWithHashFor(gibliClassName) \ - static CFStringRef gibliClassName##CopyDescription(CFTypeRef cf); \ - static void gibliClassName##Destroy(CFTypeRef cf); \ - static Boolean gibliClassName##Compare(CFTypeRef lhs, CFTypeRef rhs); \ - static CFHashCode gibliClassName##Hash(CFTypeRef cf); \ - \ - CFGiblisWithFunctions(gibliClassName, gibliClassName##CopyDescription, gibliClassName##Destroy, gibliClassName##Compare, gibliClassName##Hash) - -#define CFGiblisWithCompareFor(gibliClassName) \ - static CFStringRef gibliClassName##CopyDescription(CFTypeRef cf); \ - static void gibliClassName##Destroy(CFTypeRef cf); \ - static Boolean gibliClassName##Compare(CFTypeRef lhs, CFTypeRef rhs); \ - \ - CFGiblisWithFunctions(gibliClassName, gibliClassName##CopyDescription, gibliClassName##Destroy, gibliClassName##Compare, NULL) - - -#define CFGiblisFor(gibliClassName) \ - static CFStringRef gibliClassName##CopyDescription(CFTypeRef cf); \ - static void gibliClassName##Destroy(CFTypeRef cf); \ - \ - CFGiblisWithFunctions(gibliClassName, gibliClassName##CopyDescription, gibliClassName##Destroy, NULL, NULL) - -#define CFTypeAllocate(classType, internalType, allocator) \ - (classType##Ref) _CFRuntimeCreateInstance(allocator, classType##GetTypeID(), \ - sizeof(internalType) - sizeof(CFRuntimeBase), \ - NULL) - -__BEGIN_DECLS - -// -// Call block function -// - -static void apply_block_1(const void *value, void *context) -{ - return ((void (^)(const void *value))context)(value); -} - -static void apply_block_2(const void *key, const void *value, void *context) -{ - return ((void (^)(const void *key, const void *value))context)(key, value); -} - -// -// CFEqual Helpers -// - -static inline bool CFEqualSafe(CFTypeRef left, CFTypeRef right) -{ - if (left == NULL || right == NULL) - return left == right; - else - return CFEqual(left, right); -} - -// -// CFNumber Helpers -// - -static inline CFNumberRef CFNumberCreateWithCFIndex(CFAllocatorRef allocator, CFIndex value) -{ - return CFNumberCreate(allocator, kCFNumberCFIndexType, &value); -} - -// -// CFData Helpers -// - -static inline CFMutableDataRef CFDataCreateMutableWithScratch(CFAllocatorRef allocator, CFIndex size) { - CFMutableDataRef result = CFDataCreateMutable(allocator, 0); - CFDataSetLength(result, size); - - return result; -} - -static inline void CFDataAppend(CFMutableDataRef appendTo, CFDataRef dataToAppend) -{ - CFDataAppendBytes(appendTo, CFDataGetBytePtr(dataToAppend), CFDataGetLength(dataToAppend)); -} - -static inline CFDataRef CFDataCreateReferenceFromRange(CFAllocatorRef allocator, CFDataRef sourceData, CFRange range) -{ - return CFDataCreateWithBytesNoCopy(allocator, - CFDataGetBytePtr(sourceData) + range.location, range.length, - kCFAllocatorNull); -} - -static inline CFDataRef CFDataCreateCopyFromRange(CFAllocatorRef allocator, CFDataRef sourceData, CFRange range) -{ - return CFDataCreate(allocator, CFDataGetBytePtr(sourceData) + range.location, range.length); -} - -static inline uint8_t* CFDataIncreaseLengthAndGetMutableBytes(CFMutableDataRef data, CFIndex extraLength) -{ - CFIndex startOffset = CFDataGetLength(data); - - CFDataIncreaseLength(data, extraLength); - - return CFDataGetMutableBytePtr(data) + startOffset; -} - -static inline uint8_t* CFDataGetMutablePastEndPtr(CFMutableDataRef theData) -{ - return CFDataGetMutableBytePtr(theData) + CFDataGetLength(theData); -} - -static inline const uint8_t* CFDataGetPastEndPtr(CFDataRef theData) { - return CFDataGetBytePtr(theData) + CFDataGetLength(theData); -} - -static inline CFComparisonResult CFDataCompare(CFDataRef left, CFDataRef right) -{ - const size_t left_size = CFDataGetLength(left); - const size_t right_size = CFDataGetLength(right); - const size_t shortest = (left_size <= right_size) ? left_size : right_size; - - int comparison = memcmp(CFDataGetBytePtr(left), CFDataGetBytePtr(right), shortest); - - if (comparison > 0 || (comparison == 0 && left_size > right_size)) - return kCFCompareGreaterThan; - else if (comparison < 0 || (comparison == 0 && left_size < right_size)) - return kCFCompareLessThan; - else - return kCFCompareEqualTo; -} - - -// -// CFString Helpers -// - -// -// Turn a CFString into an allocated UTF8-encoded C string. -// -static inline char *CFStringToCString(CFStringRef inStr) -{ - if (!inStr) - return (char *)strdup(""); - CFRetain(inStr); // compensate for release on exit - - // need to extract into buffer - CFIndex length = CFStringGetLength(inStr); // in 16-bit character units - size_t len = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8); - char *buffer = (char *)malloc(len); // pessimistic - if (!CFStringGetCString(inStr, buffer, len, kCFStringEncodingUTF8)) - buffer[0] = 0; - - CFRelease(inStr); - return buffer; -} - -// runs operation with inStr as a zero terminated C string -// in utf8 encoding passed to the operation block. -void CFStringPerformWithCString(CFStringRef inStr, void(^operation)(const char *utf8Str)); - -// runs operation with inStr as a zero terminated C string -// in utf8 passed to the operation block, the length of -// the string is also provided to the block. -void CFStringPerformWithCStringAndLength(CFStringRef inStr, void(^operation)(const char *utf8Str, size_t utf8Length)); - -#include - -static inline void CFStringAppendEncryptedData(CFMutableStringRef s, CFDataRef edata) -{ - const uint8_t *bytes = CFDataGetBytePtr(edata); - CFIndex len = CFDataGetLength(edata); - CFStringAppendFormat(s, 0, CFSTR("%04lx:"), len); - if(len<=8) { - for (CFIndex ix = 0; ix < len; ++ix) { - CFStringAppendFormat(s, 0, CFSTR("%02X"), bytes[ix]); - } - } else { - uint64_t crc = 0; - CNCRC(kCN_CRC_64_ECMA_182, bytes+8, len-8, &crc); - for (CFIndex ix = 0; ix < 8; ++ix) { - CFStringAppendFormat(s, 0, CFSTR("%02X"), bytes[ix]); - } - CFStringAppendFormat(s, 0, CFSTR("...|%08llx"), crc); - } -} - -static inline void CFStringAppendHexData(CFMutableStringRef s, CFDataRef data) { - const uint8_t *bytes = CFDataGetBytePtr(data); - CFIndex len = CFDataGetLength(data); - for (CFIndex ix = 0; ix < len; ++ix) { - CFStringAppendFormat(s, 0, CFSTR("%02X"), bytes[ix]); - } -} - -static inline CFStringRef CFDataCopyHexString(CFDataRef data) { - CFMutableStringRef hexString = CFStringCreateMutable(kCFAllocatorDefault, 2 * CFDataGetLength(data)); - CFStringAppendHexData(hexString, data); - return hexString; -} - -static inline void CFDataPerformWithHexString(CFDataRef data, void (^operation)(CFStringRef dataString)) { - CFStringRef hexString = CFDataCopyHexString(data); - operation(hexString); - CFRelease(hexString); -} - -static inline void BufferPerformWithHexString(const UInt8 *bytes, CFIndex length, void (^operation)(CFStringRef dataString)) { - CFDataRef bufferAsData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, bytes, length, kCFAllocatorNull); - - CFDataPerformWithHexString(bufferAsData, operation); - - CFReleaseNull(bufferAsData); -} - - - -static inline void CFStringWriteToFile(CFStringRef inStr, FILE* file) -{ - CFStringPerformWithCStringAndLength(inStr, ^(const char *utf8Str, size_t utf8Length) { - fwrite(utf8Str, 1, utf8Length, file); - }); -} - -static inline void CFStringWriteToFileWithNewline(CFStringRef inStr, FILE* file) -{ - CFStringWriteToFile(inStr, file); - fputc('\n', file); -} - -// -// MARK: CFArray Helpers -// - -static inline CFIndex CFArrayRemoveAllValue(CFMutableArrayRef array, const void* value) -{ - CFIndex position = kCFNotFound; - CFIndex numberRemoved = 0; - - position = CFArrayGetFirstIndexOfValue(array, CFRangeMake(0, CFArrayGetCount(array)), value); - while (position != kCFNotFound) { - CFArrayRemoveValueAtIndex(array, position); - ++numberRemoved; - position = CFArrayGetFirstIndexOfValue(array, CFRangeMake(0, CFArrayGetCount(array)), value); - } - - return numberRemoved; -} - -static inline void CFArrayForEach(CFArrayRef array, void (^operation)(const void *value)) { - CFArrayApplyFunction(array, CFRangeMake(0, CFArrayGetCount(array)), apply_block_1, operation); -} - -static inline void CFArrayForEachReverse(CFArrayRef array, void (^operation)(const void *value)) { - for(CFIndex count = CFArrayGetCount(array); count > 0; --count) { - operation(CFArrayGetValueAtIndex(array, count - 1)); - } -} - -static inline const void *CFArrayGetValueMatching(CFArrayRef array, bool (^match)(const void *value)) { - CFIndex i, n = CFArrayGetCount(array); - for (i = 0; i < n; ++i) { - const void *value = CFArrayGetValueAtIndex(array, i); - if (match(value)) { - return value; - } - } - return NULL; -} - -static inline bool CFArrayHasValueMatching(CFArrayRef array, bool (^match)(const void *value)) { - return CFArrayGetValueMatching(array, match) != NULL; -} - -static inline void CFMutableArrayModifyValues(CFMutableArrayRef array, const void * (^process)(const void *value)) { - CFIndex i, n = CFArrayGetCount(array); - for (i = 0; i < n; ++i) { - const void *value = CFArrayGetValueAtIndex(array, i); - CFArraySetValueAtIndex(array, i, process(value)); - } -} - -// -// MARK: CFArray creatino Var args helper functions. -// -static inline CFArrayRef CFArrayCreateCountedForVC(CFAllocatorRef allocator, const CFArrayCallBacks *cbs, CFIndex entries, va_list args) -{ - const void *values[entries]; - - for(CFIndex currentValue = 0; currentValue < entries; ++currentValue) - { - values[currentValue] = va_arg(args, void*); - - if (values[currentValue] == NULL) - values[currentValue] = kCFNull; - } - - return CFArrayCreate(allocator, values, entries, cbs); -} - -static inline CFArrayRef CFArrayCreateForVC(CFAllocatorRef allocator, const CFArrayCallBacks *cbs, va_list args) -{ - va_list count; - va_copy(count, args); - - CFIndex entries = 0; - while (NULL != va_arg(count, void*)) { - entries += 1; - } - - return CFArrayCreateCountedForVC(allocator, cbs, entries, args); - -} - -// -// MARK: CFArray of CFTypes support -// - -static inline CFMutableArrayRef CFArrayCreateMutableForCFTypes(CFAllocatorRef allocator) -{ - return CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks); -} - -static inline CFArrayRef CFArrayCreateForCFTypes(CFAllocatorRef allocator, ...) -{ - va_list args; - va_start(args, allocator); - - return CFArrayCreateForVC(allocator, &kCFTypeArrayCallBacks, args); - -} - -static inline CFArrayRef CFArrayCreateCountedForCFTypes(CFAllocatorRef allocator, CFIndex entries, ...) -{ - va_list args; - va_start(args, entries); - - return CFArrayCreateCountedForVC(allocator, &kCFTypeArrayCallBacks, entries, args); -} - -static inline CFArrayRef CFArrayCreateCountedForCFTypesV(CFAllocatorRef allocator, CFIndex entries, va_list args) -{ - return CFArrayCreateCountedForVC(allocator, &kCFTypeArrayCallBacks, entries, args); -} - -// -// MARK: CFDictionary of CFTypes helpers -// - -static inline CFDictionaryRef CFDictionaryCreateCountedForCFTypesV(CFAllocatorRef allocator, CFIndex entries, va_list args) -{ - const void *keys[entries]; - const void *values[entries]; - - for(CFIndex currentValue = 0; currentValue < entries; ++currentValue) - { - keys[currentValue] = va_arg(args, void*); - values[currentValue] = va_arg(args, void*); - - if (values[currentValue] == NULL) - values[currentValue] = kCFNull; - } - - return CFDictionaryCreate(allocator, keys, values, entries, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); -} - -static inline CFDictionaryRef CFDictionaryCreateForCFTypes(CFAllocatorRef allocator, ...) -{ - va_list args; - va_start(args, allocator); - - CFIndex entries = 0; - while (NULL != va_arg(args, void*)) { - entries += 2; - (void) va_arg(args, void*); - } - - entries /= 2; - - va_start(args, allocator); - - return CFDictionaryCreateCountedForCFTypesV(allocator, entries, args); - -} - -static inline CFDictionaryRef CFDictionaryCreateCountedForCFTypes(CFAllocatorRef allocator, CFIndex entries, ...) -{ - va_list args; - va_start(args, entries); - - return CFDictionaryCreateCountedForCFTypesV(allocator, entries, args); -} - -static inline CFMutableDictionaryRef CFDictionaryCreateMutableForCFTypes(CFAllocatorRef allocator) -{ - return CFDictionaryCreateMutable(allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); -} - -static inline CFMutableDictionaryRef CFDictionaryCreateMutableForCFTypesWith(CFAllocatorRef allocator, ...) -{ - CFMutableDictionaryRef result = CFDictionaryCreateMutableForCFTypes(allocator); - - va_list args; - va_start(args, allocator); - - void* key = va_arg(args, void*); - - while (key != NULL) { - CFDictionarySetValue(result, key, va_arg(args, void*)); - key = va_arg(args, void*); - }; - - return result; -} - -// -// MARK: CFDictionary Helpers -// - -static inline void CFDictionaryForEach(CFDictionaryRef dictionary, void (^operation)(const void *key, const void *value)) { - CFDictionaryApplyFunction(dictionary, apply_block_2, operation); -} - -// -// Type checking -// - -static inline bool isArray(CFTypeRef cfType) { - return cfType && CFGetTypeID(cfType) == CFArrayGetTypeID(); -} - -static inline bool isData(CFTypeRef cfType) { - return cfType && CFGetTypeID(cfType) == CFDataGetTypeID(); -} - -static inline bool isDate(CFTypeRef cfType) { - return cfType && CFGetTypeID(cfType) == CFDateGetTypeID(); -} - -static inline bool isDictionary(CFTypeRef cfType) { - return cfType && CFGetTypeID(cfType) == CFDictionaryGetTypeID(); -} - -static inline bool isNumber(CFTypeRef cfType) { - return cfType && CFGetTypeID(cfType) == CFNumberGetTypeID(); -} - -static inline bool isNumberOfType(CFTypeRef cfType, CFNumberType number) { - return isNumber(cfType) && CFNumberGetType((CFNumberRef)cfType) == number; -} - -static inline bool isString(CFTypeRef cfType) { - return cfType && CFGetTypeID(cfType) == CFStringGetTypeID(); -} - -static inline bool isBoolean(CFTypeRef cfType) { - return cfType && CFGetTypeID(cfType) == CFBooleanGetTypeID(); -} - -static inline bool isNull(CFTypeRef cfType) { - return cfType && CFGetTypeID(cfType) == CFNullGetTypeID(); -} - - -// -// MARK: PropertyList Helpers -// - -// -// Crazy reading and writing stuff -// - -static inline void CFPropertyListWriteToFile(CFPropertyListRef plist, CFURLRef file) -{ - CFWriteStreamRef writeStream = CFWriteStreamCreateWithFile(kCFAllocatorDefault, file); - CFErrorRef error = NULL; - - CFWriteStreamOpen(writeStream); - CFPropertyListWrite(plist, writeStream, kCFPropertyListBinaryFormat_v1_0, 0, &error); - if (error) - secerror("Can't write plist: %@", error); - - CFReleaseNull(error); - CFReleaseNull(writeStream); -} - -static inline CF_RETURNS_RETAINED CFPropertyListRef CFPropertyListReadFromFile(CFURLRef file) -{ - CFPropertyListRef result = NULL; - CFErrorRef error = NULL; - CFBooleanRef isRegularFile; - if (!CFURLCopyResourcePropertyForKey(file, kCFURLIsRegularFileKey, &isRegularFile, &error)) { - secerror("file %@: %@", file, error); - } else if (CFBooleanGetValue(isRegularFile)) { - CFReadStreamRef readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault, file); - if (readStream) { - if (CFReadStreamOpen(readStream)) { - CFPropertyListFormat format; - result = CFPropertyListCreateWithStream(kCFAllocatorDefault, readStream, 0, kCFPropertyListMutableContainers, &format, &error); - if (!result) { - secerror("read plist from %@: %@", file, error); - } - } - CFRelease(readStream); - } - } - CFReleaseNull(error); - - return result; -} - -__END_DECLS - -#endif diff --git a/utilities/src/SecDb.h b/utilities/src/SecDb.h deleted file mode 100644 index d72504b2..00000000 --- a/utilities/src/SecDb.h +++ /dev/null @@ -1,117 +0,0 @@ -// -// SecDb.h -// utilities -// -// Created by Michael Brouwer on 11/12/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#ifndef _UTILITIES_SECDB_H_ -#define _UTILITIES_SECDB_H_ - -#include -#include - -__BEGIN_DECLS - -// MARK: SecDbRef and SecDbConnectionRef forward declarations -typedef struct __OpaqueSecDb *SecDbRef; -typedef struct __OpaqueSecDbConnection *SecDbConnectionRef; -typedef struct __OpaqueSecDbStatement *SecDbStatementRef; - -// MARK: Configuration values, not used by clients directly. -// TODO: Move this section to a private header -enum { - kSecDbMaxReaders = 4, - kSecDbMaxWriters = 1, - kSecDbMaxIdleHandles = 3, -}; - -// MARK: SecDbTransactionType -enum { - kSecDbNoneTransactionType = 0, - kSecDbImmediateTransactionType, - kSecDbExclusiveTransactionType, - kSecDbNormalTransactionType -}; -typedef uint32_t SecDbTransactionType; - -// MARK: -- -// MARK: Error creation helpers. - -// SQLITE3 errors are in this domain -extern CFStringRef kSecDbErrorDomain; - -bool SecDbError(int sql_code, CFErrorRef *error, CFStringRef format, ...); -bool SecDbErrorWithDb(int sql_code, sqlite3 *db, CFErrorRef *error, CFStringRef format, ...); -bool SecDbErrorWithStmt(int sql_code, sqlite3_stmt *stmt, CFErrorRef *error, CFStringRef format, ...); - -// MARK: mark - -// MARK: mark SecDbRef - -CFTypeID SecDbGetTypeID(void); - -SecDbRef SecDbCreate(CFStringRef dbName, bool (^opened)(SecDbConnectionRef dbconn, bool did_create, CFErrorRef *error)); - -// Read only connections go to the end of the queue, writeable -// connections go to the start of the queue. Use SecDbPerformRead() and SecDbPerformWrite() if you -// can to avoid leaks. -SecDbConnectionRef SecDbConnectionAquire(SecDbRef db, bool readOnly, CFErrorRef *error); -void SecDbConnectionRelease(SecDbConnectionRef dbconn); - -// Perform a database read operation, -bool SecDbPerformRead(SecDbRef db, CFErrorRef *error, void (^perform)(SecDbConnectionRef dbconn)); -bool SecDbPerformWrite(SecDbRef db, CFErrorRef *error, void (^perform)(SecDbConnectionRef dbconn)); - -// TODO: DEBUG only -> Private header -CFIndex SecDbIdleConnectionCount(SecDbRef db); - -// MARK: - -// MARK: SecDbConectionRef - -CFTypeID SecDbConnectionGetTypeID(void); - -bool SecDbPrepare(SecDbConnectionRef dbconn, CFStringRef sql, CFErrorRef *error, void(^exec)(sqlite3_stmt *stmt)); - -bool SecDbStep(SecDbConnectionRef dbconn, sqlite3_stmt *stmt, CFErrorRef *error, void (^row)(bool *stop)); - -bool SecDbExec(SecDbConnectionRef dbconn, CFStringRef sql, CFErrorRef *error); - -bool SecDbCheckpoint(SecDbConnectionRef dbconn, CFErrorRef *error); - -bool SecDbTransaction(SecDbConnectionRef dbconn, SecDbTransactionType ttype, CFErrorRef *error, - void (^transaction)(bool *commit)); - -sqlite3 *SecDbHandle(SecDbConnectionRef dbconn); - -// MARK: - -// MARK: Bind helpers - -#if 0 -bool SecDbBindNull(sqlite3_stmt *stmt, int param, CFErrorRef *error); -#endif -bool SecDbBindBlob(sqlite3_stmt *stmt, int param, const void *zData, size_t n, void(*xDel)(void*), CFErrorRef *error); -bool SecDbBindText(sqlite3_stmt *stmt, int param, const char *zData, size_t n, void(*xDel)(void*), CFErrorRef *error); -bool SecDbBindDouble(sqlite3_stmt *stmt, int param, double value, CFErrorRef *error); -bool SecDbBindInt(sqlite3_stmt *stmt, int param, int value, CFErrorRef *error); -bool SecDbBindInt64(sqlite3_stmt *stmt, int param, sqlite3_int64 value, CFErrorRef *error); -bool SecDbBindObject(sqlite3_stmt *stmt, int param, CFTypeRef value, CFErrorRef *error); - -// MARK: - -// MARK: SecDbStatementRef - -bool SecDbReset(sqlite3_stmt *stmt, CFErrorRef *error); -bool SecDbClearBindings(sqlite3_stmt *stmt, CFErrorRef *error); -bool SecDbFinalize(sqlite3_stmt *stmt, CFErrorRef *error); -sqlite3_stmt *SecDbPrepareV2(SecDbConnectionRef dbconn, const char *sql, size_t sqlLen, const char **sqlTail, CFErrorRef *error); -sqlite3_stmt *SecDbCopyStmt(SecDbConnectionRef dbconn, CFStringRef sql, CFStringRef *tail, CFErrorRef *error); -bool SecDbReleaseCachedStmt(SecDbConnectionRef dbconn, CFStringRef sql, sqlite3_stmt *stmt, CFErrorRef *error); -bool SecDbWithSQL(SecDbConnectionRef dbconn, CFStringRef sql, CFErrorRef *error, bool(^perform)(sqlite3_stmt *stmt)); -bool SecDbForEach(sqlite3_stmt *stmt, CFErrorRef *error, bool(^row)(int row_index)); - -// Mark the database as corrupted. -void SecDbCorrupt(SecDbConnectionRef dbconn); - -__END_DECLS - -#endif /* !_UTILITIES_SECDB_H_ */ diff --git a/utilities/src/SecDispatchRelease.h b/utilities/src/SecDispatchRelease.h deleted file mode 100644 index 81db2f10..00000000 --- a/utilities/src/SecDispatchRelease.h +++ /dev/null @@ -1,58 +0,0 @@ -// -// SecDispatchRelease.h -// utilities -// -// Created by Mitch Adler on 11/26/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - - -#ifndef _SECDISPATCHRELEASE_H_ -#define _SECDISPATCHRELEASE_H_ - -#include -#include - -#define dispatch_retain_safe(DO) { \ - __typeof__(DO) _do = (DO); \ - if (_do) \ - dispatch_retain(_do); \ -} - -#define dispatch_release_safe(DO) { \ - __typeof__(DO) _do = (DO); \ - if (_do) \ - dispatch_release(_do); \ -} - -#define dispatch_release_null(DO) { \ - __typeof__(DO) _do = (DO); \ - if (_do) { \ - (DO) = NULL; \ - dispatch_release(_do); \ - } \ -} - - -#define xpc_retain_safe(XO) { \ - __typeof__(XO) _xo = (XO); \ - if (_xo) \ - xpc_retain(_xo); \ -} - -#define xpc_release_safe(XO) { \ - __typeof__(XO) _xo = (XO); \ - if (_xo) \ - xpc_release(_xo); \ -} - -#define xpc_release_null(XO) { \ - __typeof__(XO) _xo = (XO); \ - if (_xo) { \ - (XO) = NULL; \ - xpc_release(_xo); \ - } \ -} - -#endif - diff --git a/utilities/src/SecIOFormat.h b/utilities/src/SecIOFormat.h deleted file mode 100644 index f5933077..00000000 --- a/utilities/src/SecIOFormat.h +++ /dev/null @@ -1,50 +0,0 @@ -// -// SecIOFormat.h -// utilities -// -// Created by Mitch Adler on 10/1/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#ifndef _SECIOFORMAT_H_ -#define _SECIOFORMAT_H_ - -#include - -// MARK: CFIndex printing support - -#ifdef __LLP64__ -# define PRIdCFIndex "lld" -# define PRIiCFIndex "lli" -# define PRIoCFIndex "llo" -# define PRIuCFIndex "llu" -# define PRIxCFIndex "llx" -# define PRIXCFIndex "llX" -#else -# define PRIdCFIndex "ld" -# define PRIiCFIndex "li" -# define PRIoCFIndex "lo" -# define PRIuCFIndex "lu" -# define PRIxCFIndex "lx" -# define PRIXCFIndex "lX" -#endif - -// MARK: OSStatus printing support - -#ifdef __LP64__ -# define PRIdOSStatus "d" -# define PRIiOSStatus "i" -# define PRIoOSStatus "o" -# define PRIuOSStatus "u" -# define PRIxOSStatus "x" -# define PRIXOSStatus "X" -#else -# define PRIdOSStatus "ld" -# define PRIiOSStatus "li" -# define PRIoOSStatus "lo" -# define PRIuOSStatus "lu" -# define PRIxOSStatus "lx" -# define PRIXOSStatus "lX" -#endif - -#endif diff --git a/utilities/src/SecXPCError.c b/utilities/src/SecXPCError.c deleted file mode 100644 index a4200613..00000000 --- a/utilities/src/SecXPCError.c +++ /dev/null @@ -1,67 +0,0 @@ -// -// SecCFXPCWrappers.c -// utilities -// -// Created by John Hurley on 5/6/13. -// Copyright (c) 2013 Apple Inc. All rights reserved. -// - -#include - -#include -#include -#include - -CFStringRef sSecXPCErrorDomain = CFSTR("com.apple.security.xpc"); - -static const char* kDomainKey = "domain"; -static const char* kDescriptionKey = "description"; -static const char* kCodeKey = "code"; - -CFErrorRef SecCreateCFErrorWithXPCObject(xpc_object_t xpc_error) -{ - CFErrorRef result = NULL; - - if (xpc_get_type(xpc_error) == XPC_TYPE_DICTIONARY) { - CFStringRef domain = NULL; - - const char * domain_string = xpc_dictionary_get_string(xpc_error, kDomainKey); - if (domain_string != NULL) { - domain = CFStringCreateWithCString(kCFAllocatorDefault, domain_string, kCFStringEncodingUTF8); - } else { - domain = sSecXPCErrorDomain; - CFRetain(domain); - } - CFIndex code = (CFIndex) xpc_dictionary_get_int64(xpc_error, kCodeKey); - - const char *description = xpc_dictionary_get_string(xpc_error, kDescriptionKey); - - SecCFCreateErrorWithFormat(code, domain, NULL, &result, NULL, CFSTR("Remote error : %s"), description); - - CFReleaseSafe(domain); - } else { - SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, &result, NULL, CFSTR("Remote error not dictionary!: %@"), xpc_error); - } - return result; -} - -static void SecXPCDictionarySetCFString(xpc_object_t dict, const char *key, CFStringRef string) -{ - CFStringPerformWithCString(string, ^(const char *utf8Str) { - xpc_dictionary_set_string(dict, key, utf8Str); - }); -} - -xpc_object_t SecCreateXPCObjectWithCFError(CFErrorRef error) -{ - xpc_object_t error_xpc = xpc_dictionary_create(NULL, NULL, 0); - - SecXPCDictionarySetCFString(error_xpc, kDomainKey, CFErrorGetDomain(error)); - xpc_dictionary_set_int64(error_xpc, kCodeKey, CFErrorGetCode(error)); - - CFStringRef description = CFErrorCopyDescription(error); - SecXPCDictionarySetCFString(error_xpc, kDescriptionKey, description); - CFReleaseNull(description); - - return error_xpc; -} diff --git a/utilities/src/SecXPCError.h b/utilities/src/SecXPCError.h deleted file mode 100644 index 0a5896b7..00000000 --- a/utilities/src/SecXPCError.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// SecXPCError.h -// utilities -// -// Created by John Hurley on 5/6/13. -// Copyright (c) 2013 Apple Inc. All rights reserved. -// - -#ifndef _UTILITIES_SECXPCERROR_H_ -#define _UTILITIES_SECXPCERROR_H_ - -#include -#include -#include - -__BEGIN_DECLS - -extern CFStringRef sSecXPCErrorDomain; - -enum { - kSecXPCErrorSuccess = 0, - kSecXPCErrorUnexpectedType = 1, - kSecXPCErrorUnexpectedNull = 2, - kSecXPCErrorConnectionFailed = 3, - kSecXPCErrorUnknown = 4, -}; - -CFErrorRef SecCreateCFErrorWithXPCObject(xpc_object_t xpc_error); -xpc_object_t SecCreateXPCObjectWithCFError(CFErrorRef error); - -__END_DECLS - -#endif /* UTILITIES_SECXPCERROR_H */ diff --git a/utilities/src/array_size.h b/utilities/src/array_size.h deleted file mode 100644 index 9d7cb90d..00000000 --- a/utilities/src/array_size.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// array_size.h -// utilities -// -// Created by Mitch Adler on 2/10/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#ifndef utilities_array_size_h -#define utilities_array_size_h - -#define array_size(array) (sizeof(array)/sizeof(*array)) - -#endif diff --git a/utilities/src/comparison.c b/utilities/src/comparison.c deleted file mode 100644 index d0d287df..00000000 --- a/utilities/src/comparison.c +++ /dev/null @@ -1,19 +0,0 @@ -// -// comparison.c -// utilities -// -// Created by Keith Henrickson on 7/1/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#include -#include -#include "comparison.h" - -uint64_t constant_memcmp(const uint8_t *first, const uint8_t *second, size_t count) { - uint64_t error_counter = 0; - for (size_t counter = 0; counter < count; counter++) { - error_counter |= first[counter] ^ second[counter]; - } - return error_counter; -} diff --git a/utilities/src/comparison.h b/utilities/src/comparison.h deleted file mode 100644 index c28e3bf1..00000000 --- a/utilities/src/comparison.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// comparison.h -// utilities -// -// Created by Mitch Adler on 6/14/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#ifndef utilities_comparison_h -#define utilities_comparison_h - -#define MIN(a, b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a <= _b ? _a : _b; }) -#define MAX(a, b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a >= _b ? _a : _b; }) - -uint64_t constant_memcmp(const uint8_t *first, const uint8_t *second, size_t count); - -#endif diff --git a/utilities/src/debugging.c b/utilities/src/debugging.c deleted file mode 100644 index 462de8bb..00000000 --- a/utilities/src/debugging.c +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -/* - * debugging.c - non-trivial debug support - */ -#include "utilities/debugging.h" -#include "utilities/SecCFWrappers.h" -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -/** begin: For SimulateCrash **/ -#include -#include -/// Type to represent a boolean value. -#if TARGET_OS_IPHONE && __LP64__ -typedef bool BOOL; -#else -typedef signed char BOOL; -// BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C" -// even if -funsigned-char is used. -#endif -/** end: For SimulateCrash **/ - -#define MAX_SCOPE_LENGTH 12 - -#if !defined(NDEBUG) -static CFStringRef copyScopeName(const char *scope, CFIndex scopeLen) { - if (scopeLen > MAX_SCOPE_LENGTH) - scopeLen = MAX_SCOPE_LENGTH - 1; - return CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8 *)scope, - scopeLen, kCFStringEncodingUTF8, false); -} - -pthread_once_t __security_debug_once = PTHREAD_ONCE_INIT; -static const char *gDebugScope; -static CFMutableSetRef scopeSet; -static bool negate = false; - -static void __security_debug_init(void) { - const char *cur_scope = gDebugScope = getenv("DEBUGSCOPE"); - if (cur_scope) { - if (!strcmp(cur_scope, "all")) { - scopeSet = NULL; - negate = true; - } else if (!strcmp(cur_scope, "none")) { - scopeSet = NULL; - negate = false; - } else { - scopeSet = CFSetCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeSetCallBacks); - if (cur_scope[0] == '-') { - negate = true; - cur_scope++; - } else { - negate = false; - } - - const char *sep; - while ((sep = strchr(cur_scope, ','))) { - CFStringRef scopeName = copyScopeName(cur_scope, - sep - cur_scope); - CFSetAddValue(scopeSet, scopeName); - CFRelease(scopeName); - cur_scope = sep + 1; - } - - CFStringRef scopeName = copyScopeName(cur_scope, - strlen(cur_scope)); - CFSetAddValue(scopeSet, scopeName); - CFRelease(scopeName); - } - } else { - scopeSet = NULL; - negate = false; - } -} - -#endif - -static CFMutableArrayRef sSecurityLogHandlers; - -static CFMutableArrayRef get_log_handlers() -{ - static dispatch_once_t handlers_once; - - dispatch_once(&handlers_once, ^{ - sSecurityLogHandlers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); - - CFArrayAppendValue(sSecurityLogHandlers, ^(const char *level, CFStringRef scope, const char *function, - const char *file, int line, CFStringRef message){ - CFStringRef logStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %s %@\n"), scope ? scope : CFSTR(""), function, message); - CFStringPerformWithCString(logStr, ^(const char *logMsg) { - aslmsg msg = asl_new(ASL_TYPE_MSG); - if (scope) { - CFStringPerformWithCString(scope, ^(const char *scopeStr) { - asl_set(msg, ASL_KEY_FACILITY, scopeStr); - }); - } - asl_set(msg, ASL_KEY_LEVEL, level); - asl_set(msg, ASL_KEY_MSG, logMsg); - asl_send(NULL, msg); - asl_free(msg); - }); - CFReleaseSafe(logStr); - }); - }); - - return sSecurityLogHandlers; -} - -static void clean_aslclient(void *client) -{ - asl_close(client); -} - -static aslclient get_aslclient() -{ - static dispatch_once_t once; - static pthread_key_t asl_client_key; - dispatch_once(&once, ^{ - pthread_key_create(&asl_client_key, clean_aslclient); - }); - aslclient client = pthread_getspecific(asl_client_key); - if (!client) { - client = asl_open(NULL, "SecAPI", 0); - asl_set_filter(client, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG)); - pthread_setspecific(asl_client_key, client); - } - - return client; -} - -void __security_trace_enter_api(const char *api, CFStringRef format, ...) -{ - aslmsg msg = asl_new(ASL_TYPE_MSG); - asl_set(msg, ASL_KEY_LEVEL, ASL_STRING_DEBUG); - asl_set(msg, "SecAPITrace", api); - asl_set(msg, "ENTER", ""); - va_list args; - va_start(args, format); - if (format) { - CFStringRef message = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, format, args); - va_end(args); - CFStringPerformWithCString(message, ^(const char *utf8Str) { - asl_set(msg, ASL_KEY_MSG, utf8Str); - }); - CFReleaseSafe(message); - } - - { - char stack_info[80]; - - snprintf(stack_info, sizeof(stack_info), "C%p F%p", __builtin_return_address(1), __builtin_frame_address(2)); - asl_set(msg, "CALLER", stack_info); - } - - asl_send(get_aslclient(), msg); - asl_free(msg); -} - -void __security_trace_return_api(const char *api, CFStringRef format, ...) -{ - aslmsg msg = asl_new(ASL_TYPE_MSG); - asl_set(msg, ASL_KEY_LEVEL, ASL_STRING_DEBUG); - asl_set(msg, "SecAPITrace", api); - asl_set(msg, "RETURN", ""); - va_list args; - va_start(args, format); - if (format) { - CFStringRef message = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, format, args); - va_end(args); - CFStringPerformWithCString(message, ^(const char *utf8Str) { - asl_set(msg, ASL_KEY_MSG, utf8Str); - }); - CFReleaseSafe(message); - } - asl_send(get_aslclient(), msg); - asl_free(msg); -} - - -void add_security_log_hanlder(security_log_handler handler) -{ - CFArrayAppendValue(get_log_handlers(), handler); -} - -static void __security_log_msg(const char *level, CFStringRef scope, const char *function, - const char *file, int line, CFStringRef message) -{ - - CFArrayForEach(get_log_handlers(), ^(const void *value) { - security_log_handler handler = (security_log_handler) value; - - handler(level, scope, function, file, line, message); - }); -} - -void __security_debug(CFStringRef scope, const char *function, - const char *file, int line, CFStringRef format, ...) -{ -#if !defined(NDEBUG) - pthread_once(&__security_debug_once, __security_debug_init); - - /* Check if scope is enabled. */ - if (scope && ((scopeSet && negate == CFSetContainsValue(scopeSet, scope)) || - (!scopeSet && !negate))) - return; -#endif - - va_list args; - va_start(args, format); - CFStringRef message = CFStringCreateWithFormatAndArguments( - kCFAllocatorDefault, NULL, format, args); - va_end(args); - - /* DEBUG scopes are logged as notice when enabled. */ - __security_log_msg(ASL_STRING_NOTICE, scope, function, file, line, message); - CFRelease(message); -} - -void __security_log(const char *level, CFStringRef scope, const char *function, - const char *file, int line, CFStringRef format, ...) -{ - va_list args; - va_start(args, format); - CFStringRef message = CFStringCreateWithFormatAndArguments( - kCFAllocatorDefault, NULL, format, args); - va_end(args); - __security_log_msg(level, scope, function, file, line, message); - CFRelease(message); -} - -static void __security_simulatecrash_link(CFStringRef reason, uint32_t code) -{ -#if !TARGET_IPHONE_SIMULATOR - // Prototype defined in , but objC only. - // Soft linking here so we don't link unless we hit this. - static BOOL (*__SimulateCrash)(pid_t pid, mach_exception_data_type_t exceptionCode, CFStringRef description); - - static dispatch_once_t once = 0; - dispatch_once(&once, ^{ - void *image = dlopen("/System/Library/PrivateFrameworks/CrashReporterSupport.framework/CrashReporterSupport", RTLD_NOW); - if (image) - __SimulateCrash = dlsym(image, "SimulateCrash"); - else - __SimulateCrash = NULL; - }); - - if (__SimulateCrash) - __SimulateCrash(getpid(), code, reason); - else - secerror("SimulateCrash not available"); -#else - secerror("SimulateCrash not available in iOS simulator"); -#endif -} - - -void __security_simulatecrash(CFStringRef reason, uint32_t code) -{ - secerror("Simulating crash, reason: %@, code=%08x", reason, code); - __security_simulatecrash_link(reason, code); -} diff --git a/utilities/src/debugging.h b/utilities/src/debugging.h deleted file mode 100644 index c6e0ee41..00000000 --- a/utilities/src/debugging.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2006-2007,2009-2010 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * debugging.h - non-trivial debug support - */ -#ifndef _SECURITY_UTILITIES_DEBUGGING_H_ -#define _SECURITY_UTILITIES_DEBUGGING_H_ - -#ifdef KERNEL - #include - #define secalert(format, ...) printf((format), ## __VA_ARGS__) - #define secemergency(format, ...) printf((format), ## __VA_ARGS__) - #define seccritical(format, ...) printf((format), ## __VA_ARGS__) - #define secerror(format, ...) printf((format), ## __VA_ARGS__) - #define secwarning(format, ...) printf((format), ## __VA_ARGS__) - #define secnotice(scope, format, ...) printf((format), ## __VA_ARGS__) - #define secinfo(scope, format, ...) printf((format), ## __VA_ARGS__) - #if !defined(NDEBUG) - #define secdebug(scope, format, ...) printf((format), ## __VA_ARGS__) - #else // NDEBUG - #define secdebug(scope, format, ...) /* nothing */ - #endif // NDEBUG -#else // !KERNEL - -#include -#include -#include - -__BEGIN_DECLS - -extern void __security_trace_enter_api(const char *api, CFStringRef format, ...) CF_FORMAT_FUNCTION(2, 3); -extern void __security_trace_return_api(const char *api, CFStringRef format, ...) CF_FORMAT_FUNCTION(2, 3); - -extern void __security_debug(CFStringRef scope, - const char *function, const char *file, int line, - CFStringRef format, ...) CF_FORMAT_FUNCTION(5,6); - -extern void __security_log(const char *level, CFStringRef scope, - const char *function, const char *file, int line, - CFStringRef format, ...) CF_FORMAT_FUNCTION(6,7); - -#define sec_trace_enter_api(format...) __security_trace_enter_api(__FUNCTION__, format) -#define sec_trace_return_api(rtype, body, format...) { rtype _r = body(); __security_trace_return_api(__FUNCTION__, format, _r); return _r; } -#define sec_trace_return_bool_api(body, format...) { bool _r = body(); typeof(format) _fmt = format; __security_trace_return_api(__FUNCTION__, _fmt ? _fmt : CFSTR("return=%d"), (int)_r); return _r; } - -#define secemergency(format, ...) __security_log(ASL_STRING_EMERG, NULL, \ - __FUNCTION__, __FILE__, __LINE__, \ - CFSTR(format), ## __VA_ARGS__) - -#define secalert(format, ...) __security_log(ASL_STRING_ALERT, NULL, \ - __FUNCTION__, __FILE__, __LINE__, \ - CFSTR(format), ## __VA_ARGS__) - -#define seccritical(format, ...) __security_log(ASL_STRING_CRIT, NULL, \ - __FUNCTION__, __FILE__, __LINE__, \ - CFSTR(format), ## __VA_ARGS__) - -#define secerror(format, ...) __security_log(ASL_STRING_ERR, NULL, \ - __FUNCTION__, __FILE__, __LINE__, \ - CFSTR(format), ## __VA_ARGS__) - -#define secwarning(format, ...) __security_log(ASL_STRING_WARNING, NULL, \ - __FUNCTION__, __FILE__, __LINE__, \ - CFSTR(format), ## __VA_ARGS__) - -#define secnotice(scope, format, ...) __security_log(ASL_STRING_NOTICE, CFSTR(scope), \ - __FUNCTION__, __FILE__, __LINE__, \ - CFSTR(format), ## __VA_ARGS__) - -#define secinfo(scope, format, ...) __security_log(ASL_STRING_INFO, CFSTR(scope), \ - __FUNCTION__, __FILE__, __LINE__, \ - CFSTR(format), ## __VA_ARGS__) - -#if !defined(NDEBUG) - -# define secdebug(scope,format, ...) __security_debug(CFSTR(scope), \ - __FUNCTION__, __FILE__, __LINE__, \ - CFSTR(format), ## __VA_ARGS__) -#else -# define secdebug(scope,...) /* nothing */ -#endif - -typedef void (^security_log_handler)(const char *level, CFStringRef scope, const char *function, - const char *file, int line, CFStringRef message); - -void add_security_log_hanlder(security_log_handler handler); - -/* To simulate a process crash in some conditions */ -void __security_simulatecrash(CFStringRef reason, uint32_t code); - -/* predefined simulate crash exception codes */ -#define __sec_exception_code(x) (0x53c00000+x) -#define __sec_exception_code_CorruptDb(db,rc) __sec_exception_code(1|((db)<<8)|((rc)<<16)) -#define __sec_exception_code_CorruptItem __sec_exception_code(2) -#define __sec_exception_code_OTRError __sec_exception_code(3) -#define __sec_exception_code_DbItemDescribe __sec_exception_code(4) -#define __sec_exception_code_TwiceCorruptDb(db) __sec_exception_code(5|((db)<<8)) - -__END_DECLS - -#endif // !KERNEL - -#endif /* _SECURITY_UTILITIES_DEBUGGING_H_ */ diff --git a/utilities/src/der_array.c b/utilities/src/der_array.c deleted file mode 100644 index 4ca54f6f..00000000 --- a/utilities/src/der_array.c +++ /dev/null @@ -1,75 +0,0 @@ -// -// der_array.c -// utilities -// -// Created by Mitch Adler on 7/2/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#include - -#include "utilities/SecCFRelease.h" -#include "utilities/der_plist.h" -#include "utilities/der_plist_internal.h" - -#include -#include - - -const uint8_t* der_decode_array(CFAllocatorRef allocator, CFOptionFlags mutability, - CFArrayRef* array, CFErrorRef *error, - const uint8_t* der, const uint8_t *der_end) -{ - if (NULL == der) - return NULL; - - CFMutableArrayRef result = CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks); - - const uint8_t *elements_end; - const uint8_t *current_element = ccder_decode_sequence_tl(&elements_end, der, der_end); - - while (current_element != NULL && current_element < elements_end) { - CFPropertyListRef element = NULL; - current_element = der_decode_plist(allocator, mutability, &element, error, current_element, elements_end); - if (current_element) { - CFArrayAppendValue(result, element); - CFReleaseNull(element); - } - } - - if (current_element) { - *array = result; - result = NULL; - } - - CFReleaseNull(result); - return current_element; -} - - -size_t der_sizeof_array(CFArrayRef data, CFErrorRef *error) -{ - size_t body_size = 0; - for(CFIndex position = CFArrayGetCount(data) - 1; - position >= 0; - --position) - { - body_size += der_sizeof_plist(CFArrayGetValueAtIndex(data, position), error); - } - return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, body_size); -} - - -uint8_t* der_encode_array(CFArrayRef array, CFErrorRef *error, - const uint8_t *der, uint8_t *der_end) -{ - uint8_t* original_der_end = der_end; - for(CFIndex position = CFArrayGetCount(array) - 1; - position >= 0; - --position) - { - der_end = der_encode_plist(CFArrayGetValueAtIndex(array, position), error, der, der_end); - } - - return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, original_der_end, der, der_end); -} diff --git a/utilities/src/der_boolean.c b/utilities/src/der_boolean.c deleted file mode 100644 index 7391bd43..00000000 --- a/utilities/src/der_boolean.c +++ /dev/null @@ -1,54 +0,0 @@ -// -// der_boolean.c -// utilities -// -// Created by Mitch Adler on 6/19/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#include - -#include "utilities/SecCFRelease.h" -#include "utilities/der_plist.h" -#include "utilities/der_plist_internal.h" - -#include -#include - - -const uint8_t* der_decode_boolean(CFAllocatorRef allocator, CFOptionFlags mutability, - CFBooleanRef* boolean, CFErrorRef *error, - const uint8_t* der, const uint8_t *der_end) -{ - if (NULL == der) - return NULL; - - size_t payload_size = 0; - const uint8_t *payload = ccder_decode_tl(CCDER_BOOLEAN, &payload_size, der, der_end); - - if (NULL == payload || (der_end - payload) < payload_size || payload_size != 1) { - SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown boolean encoding"), NULL, error); - return NULL; - } - - *boolean = *payload ? kCFBooleanTrue : kCFBooleanFalse; - - return payload + payload_size; -} - - -size_t der_sizeof_boolean(CFBooleanRef data __unused, CFErrorRef *error) -{ - return ccder_sizeof(CCDER_BOOLEAN, 1); -} - - -uint8_t* der_encode_boolean(CFBooleanRef boolean, CFErrorRef *error, - const uint8_t *der, uint8_t *der_end) -{ - uint8_t value = CFBooleanGetValue(boolean); - - return ccder_encode_tl(CCDER_BOOLEAN, 1, der, - ccder_encode_body(1, &value, der, der_end)); - -} diff --git a/utilities/src/der_data.c b/utilities/src/der_data.c deleted file mode 100644 index 0eb726f4..00000000 --- a/utilities/src/der_data.c +++ /dev/null @@ -1,87 +0,0 @@ -// -// der_data.c -// utilities -// -// Created by Mitch Adler on 6/18/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#include - -#include "utilities/SecCFRelease.h" -#include "utilities/der_plist.h" -#include "utilities/der_plist_internal.h" - -#include -#include - - -const uint8_t* der_decode_data_mutable(CFAllocatorRef allocator, CFOptionFlags mutability, - CFMutableDataRef* data, CFErrorRef *error, - const uint8_t* der, const uint8_t *der_end) -{ - if (NULL == der) - return NULL; - - size_t payload_size = 0; - const uint8_t *payload = ccder_decode_tl(CCDER_OCTET_STRING, &payload_size, der, der_end); - - if (NULL == payload || (der_end - payload) < payload_size) { - SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown data encoding"), NULL, error); - return NULL; - } - - *data = CFDataCreateMutable(allocator, 0); - - if (NULL == *data) { - SecCFDERCreateError(kSecDERErrorUnderlyingError, CFSTR("Failed to create data"), NULL, error); - return NULL; - } - - CFDataAppendBytes(*data, payload, payload_size); - - return payload + payload_size; -} - - -const uint8_t* der_decode_data(CFAllocatorRef allocator, CFOptionFlags mutability, - CFDataRef* data, CFErrorRef *error, - const uint8_t* der, const uint8_t *der_end) -{ - if (NULL == der) - return NULL; - - size_t payload_size = 0; - const uint8_t *payload = ccder_decode_tl(CCDER_OCTET_STRING, &payload_size, der, der_end); - - if (NULL == payload || (der_end - payload) < payload_size) { - SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown data encoding"), NULL, error); - return NULL; - } - - *data = CFDataCreate(allocator, payload, payload_size); - - if (NULL == *data) { - SecCFDERCreateError(kSecDERErrorUnderlyingError, CFSTR("Failed to create data"), NULL, error); - return NULL; - } - - return payload + payload_size; -} - - -size_t der_sizeof_data(CFDataRef data, CFErrorRef *error) -{ - return ccder_sizeof_raw_octet_string(CFDataGetLength(data)); -} - - -uint8_t* der_encode_data(CFDataRef data, CFErrorRef *error, - const uint8_t *der, uint8_t *der_end) -{ - const CFIndex data_length = CFDataGetLength(data); - - return ccder_encode_tl(CCDER_OCTET_STRING, data_length, der, - ccder_encode_body(data_length, CFDataGetBytePtr(data), der, der_end)); - -} diff --git a/utilities/src/der_date.c b/utilities/src/der_date.c deleted file mode 100644 index e8a8e637..00000000 --- a/utilities/src/der_date.c +++ /dev/null @@ -1,406 +0,0 @@ -// -// SecCFDER_CFDate.c -// utilities -// -// Created by Michael Brouwer on 7/7/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#include "utilities/SecCFRelease.h" -#include "utilities/der_date.h" -#include "utilities/der_plist.h" -#include "utilities/der_plist_internal.h" - -#include -#include - -#include - -#define NULL_TIME NAN - -CFAbsoluteTime SecCFGregorianDateGetAbsoluteTime(CFGregorianDate g, CFTimeInterval timeZoneOffset, CFErrorRef *error); -CFGregorianDate SecCFAbsoluteTimeGetGregorianDate(CFAbsoluteTime at, CFTimeInterval timeZoneOffset, CFErrorRef *error); - -/* Cumalitive number of days in the year for months up to month i. */ -static int mdays[13] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; - -CFAbsoluteTime SecCFGregorianDateGetAbsoluteTime(CFGregorianDate g, CFTimeInterval timeZoneOffset, CFErrorRef *error) { - int day = g.day; - int is_leap_year = g.year % 4 == 0 && (g.year % 100 != 0 || g.year % 400 == 0) ? 1 : 0; - if (g.month < 1 || g.month > 12 || day < 1 || day > 31 || g.hour >= 24 || g.minute >= 60 || g.second >= 60.0 - || (g.month == 2 && day > mdays[g.month] - mdays[g.month - 1] + is_leap_year) - || (g.month != 2 && day > mdays[g.month] - mdays[g.month - 1])) { - /* Invalid date. */ - SecCFDERCreateError(-1000, CFSTR("Invalid date."), 0, error); - return NULL_TIME; - } - - int dy = g.year - 2001; - if (dy < 0) { - dy += 1; - day -= 1; - } - - int leap_days = dy / 4 - dy / 100 + dy / 400; - day += ((g.year - 2001) * 365 + leap_days) + mdays[g.month - 1] - 1; - if (g.month > 2) - day += is_leap_year; - -#if 0 - int64_t time = day; - time *= 24; - time += g.hour; - time *= 60; - time += g.minute; - time *= 60; - time += lrint(g.second); - time -= lrint(timeZoneOffset); - return time; -#else - CFAbsoluteTime absTime = (CFAbsoluteTime)((day * 24 + g.hour) * 60 + g.minute) * 60 + g.second; - return absTime - timeZoneOffset; -#endif -} - -CFGregorianDate SecCFAbsoluteTimeGetGregorianDate(CFAbsoluteTime at, CFTimeInterval timeZoneOffset, CFErrorRef *error) { - CFTimeZoneRef tz = CFTimeZoneCreateWithTimeIntervalFromGMT(0, timeZoneOffset); - if (!tz) { - SecCFDERCreateError(-1000, CFSTR("timezone creation failed."), 0, error); - CFGregorianDate g = {}; - return g; - } else { - CFGregorianDate g = CFAbsoluteTimeGetGregorianDate(at, tz); - CFRelease(tz); - return g; - } -} - - -static int der_get_char(const uint8_t **der_p, const uint8_t *der_end, - CFErrorRef *error) { - const uint8_t *der = *der_p; - if (!der) { - /* Don't create a new error in this case. */ - return -1; - } - - if (der >= der_end) { - SecCFDERCreateError(kSecDERErrorUnknownEncoding, - CFSTR("Unexpected end of datetime"), 0, error); - *der_p = NULL; - return -1; - } - - int ch = *der++; - *der_p = der; - return ch; -} - - -static int der_decode_decimal(const uint8_t **der_p, const uint8_t *der_end, - CFErrorRef *error) { - char ch = der_get_char(der_p, der_end, error); - if (ch < '0' || ch > '9') { - SecCFDERCreateError(kSecDERErrorUnknownEncoding, - CFSTR("Not a decimal digit"), 0, error); - *der_p = NULL; - return -1; - } - return ch - '0'; -} - -static int der_decode_decimal_pair(const uint8_t **der_p, const uint8_t *der_end, - CFErrorRef *error) { - return (10 * der_decode_decimal(der_p, der_end, error)) - + der_decode_decimal(der_p, der_end, error); -} - -static int der_peek_byte(const uint8_t *der, const uint8_t *der_end) { - if (!der || der >= der_end) - return -1; - - return *der; -} - -static const uint8_t *der_decode_decimal_fraction(double *fraction, CFErrorRef *error, - const uint8_t* der, const uint8_t *der_end) { - int ch = der_peek_byte(der, der_end); - if (ch == -1) { - der = NULL; - } else if (ch == '.') { - uint64_t divisor = 1; - uint64_t value = 0; - int last = -1; - while (++der < der_end) { - last = ch; - ch = *der; - if (ch < '0' || ch > '9') { - break; - } - if (divisor < UINT64_MAX / 10) { - divisor *= 10; - value *= 10; - value += (ch - '0'); - } - } - if (der >= der_end) - der = NULL; - else if (last == '0') { - SecCFDERCreateError(kSecDERErrorUnknownEncoding, - CFSTR("fraction ends in 0"), 0, error); - der = NULL; - } else if (last == '.') { - SecCFDERCreateError(kSecDERErrorUnknownEncoding, - CFSTR("fraction without digits"), 0, error); - der = NULL; - } else { - *fraction = (double)value / divisor; - } - } else { - *fraction = 0.0; - } - - return der; -} - -static const CFTimeInterval der_decode_timezone_offset(const uint8_t **der_p, - const uint8_t *der_end, - CFErrorRef *error) { - CFTimeInterval timeZoneOffset; - int ch = der_get_char(der_p, der_end, error); - if (ch == 'Z') { - /* Zulu time. */ - timeZoneOffset = 0.0; - } else { - /* ZONE INDICATOR */ - int multiplier; - if (ch == '-') - multiplier = -60; - else if (ch == '+') - multiplier = +60; - else { - SecCFDERCreateError(kSecDERErrorUnknownEncoding, - CFSTR("Invalid datetime character"), 0, error); - timeZoneOffset = NULL_TIME; - } - - timeZoneOffset = multiplier * - (der_decode_decimal_pair(der_p, der_end, error) - * 60 + der_decode_decimal_pair(der_p, der_end, error)); - } - return timeZoneOffset; -} - -static const uint8_t* der_decode_commontime_body(CFAbsoluteTime *at, CFErrorRef *error, SInt32 year, - const uint8_t* der, const uint8_t *der_end) -{ - CFGregorianDate g; - g.year = year; - g.month = der_decode_decimal_pair(&der, der_end, error); - g.day = der_decode_decimal_pair(&der, der_end, error); - g.hour = der_decode_decimal_pair(&der, der_end, error); - g.minute = der_decode_decimal_pair(&der, der_end, error); - g.second = der_decode_decimal_pair(&der, der_end, error); - double fraction; - der = der_decode_decimal_fraction(&fraction, error, der, der_end); - - CFTimeInterval timeZoneOffset = der_decode_timezone_offset(&der, der_end, error); - -#if 0 - secdebug("dateparse", - "date %.*s year: %04d%02d%02d%02d%02d%02d%+05g", - length, bytes, g.year, g.month, - g.day, g.hour, g.minute, g.second, - timeZoneOffset / 60); -#endif - - if (der) { - if (der != der_end) { - SecCFDERCreateError(kSecDERErrorUnknownEncoding, - CFSTR("trailing garbage at end of datetime"), 0, error); - return NULL; - } - - *at = SecCFGregorianDateGetAbsoluteTime(g, timeZoneOffset, error) + fraction; - if (*at == NULL_TIME) - return NULL; - } - - return der; -} - -const uint8_t* der_decode_generalizedtime_body(CFAbsoluteTime *at, CFErrorRef *error, - const uint8_t* der, const uint8_t *der_end) -{ - SInt32 year = 100 * der_decode_decimal_pair(&der, der_end, error) + der_decode_decimal_pair(&der, der_end, error); - return der_decode_commontime_body(at, error, year, der, der_end); -} - -const uint8_t* der_decode_universaltime_body(CFAbsoluteTime *at, CFErrorRef *error, - const uint8_t* der, const uint8_t *der_end) -{ - SInt32 year = der_decode_decimal_pair(&der, der_end, error); - if (year < 50) { - /* 0 <= year < 50 : assume century 21 */ - year += 2000; - } else if (year < 70) { - /* 50 <= year < 70 : illegal per PKIX */ - SecCFDERCreateError(kSecDERErrorUnknownEncoding, - CFSTR("Invalid universal time year between 50 and 70"), 0, error); - der = NULL; - } else { - /* 70 < year <= 99 : assume century 20 */ - year += 1900; - } - - return der_decode_commontime_body(at, error, year, der, der_end); -} - -const uint8_t* der_decode_date(CFAllocatorRef allocator, CFOptionFlags mutability, - CFDateRef* date, CFErrorRef *error, - const uint8_t* der, const uint8_t *der_end) -{ - if (NULL == der) - return NULL; - - der = ccder_decode_constructed_tl(CCDER_GENERALIZED_TIME, &der_end, der, der_end); - CFAbsoluteTime at; - der = der_decode_generalizedtime_body(&at, error, der, der_end); - if (der) { - *date = CFDateCreate(allocator, at); - if (NULL == *date) { - SecCFDERCreateError(kSecDERErrorUnderlyingError, CFSTR("Failed to create date"), NULL, error); - return NULL; - } - } - return der; -} - -extern char *__dtoa(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve); -extern void __freedtoa(char *); - -static size_t ccder_sizeof_nanoseconds(CFAbsoluteTime at) { - int dotoff; - int sign; - char *end; - char *str = __dtoa(at, 0, 0, &dotoff, &sign, &end); - ptrdiff_t len = end - str; - __freedtoa(str); - return len < dotoff ? 0 : len - dotoff; - //return len < dotoff ? 0 : len - dotoff > 9 ? 9 : len - dotoff; -} - -size_t der_sizeof_generalizedtime_body(CFAbsoluteTime at, CFErrorRef *error) -{ - size_t subsec_digits = ccder_sizeof_nanoseconds(at); - - /* Generalized zulu time YYYYMMDDhhmmss[.ssss]Z */ - return subsec_digits ? 16 + subsec_digits : 15; -} - -size_t der_sizeof_generalizedtime(CFAbsoluteTime at, CFErrorRef *error) -{ - return ccder_sizeof(CCDER_GENERALIZED_TIME, - der_sizeof_generalizedtime_body(at, error)); -} - -size_t der_sizeof_date(CFDateRef date, CFErrorRef *error) -{ - return der_sizeof_generalizedtime(CFDateGetAbsoluteTime(date), error); -} - - -static uint8_t *ccder_encode_byte(uint8_t byte, - const uint8_t *der, uint8_t *der_end) { - if (der + 1 > der_end) { - return NULL; - } - *--der_end = byte; - return der_end; -} - -static uint8_t *ccder_encode_decimal_pair(int v, const uint8_t *der, - uint8_t *der_end) { - if (der + 2 > der_end) { - return NULL; - } - assert(v < 100); - *--der_end = '0' + v % 10; - *--der_end = '0' + v / 10; - return der_end; -} - -static uint8_t *ccder_encode_decimal_quad(int v, const uint8_t *der, - uint8_t *der_end) { - return ccder_encode_decimal_pair(v / 100, der, - ccder_encode_decimal_pair(v % 100, der, der_end)); -} - -static uint8_t *ccder_encode_nanoseconds(CFAbsoluteTime at, const uint8_t *der, - uint8_t *der_end) { - int dotoff; - int sign; - char *end; - char *str = __dtoa(at, 0, 0, &dotoff, &sign, &end); - char *begin = str + (dotoff < 0 ? 0 : dotoff); - // Compute 1.0000000 - fraction in ascii space - if (at < 0.0 && begin < end) { - char *p = end - 1; - // Borrow for last digit - *p = ('9' + 1) - (*p - '0'); - while (p-- > begin) { - // Every other digit is a 9 since we borrowed from the last one - *p = '9' - (*p - '0'); - } - } - - ptrdiff_t len = end - str; - if (len > dotoff) { - if (dotoff < 0) { - assert(-1.0 < at && at < 1.0); - der_end = ccder_encode_body(len, (const uint8_t *)str, der, der_end); - der_end = ccder_encode_body_nocopy(-dotoff, der, der_end); - if (der_end) - memset(der_end, at < 0.0 ? '9' : '0', -dotoff); - } else { - der_end = ccder_encode_body(len - dotoff, (const uint8_t *)(str + dotoff), der, der_end); - } - der_end = ccder_encode_byte('.', der, der_end); - } - __freedtoa(str); - - return der_end; -} - -/* Encode generalized zulu time YYYYMMDDhhmmss[.ssss]Z */ -uint8_t* der_encode_generalizedtime_body(CFAbsoluteTime at, CFErrorRef *error, - const uint8_t *der, uint8_t *der_end) -{ - CFGregorianDate g = SecCFAbsoluteTimeGetGregorianDate(floor(at), 0.0, error); - if (g.year == 0) - return NULL; - - return ccder_encode_decimal_quad(g.year, der, - ccder_encode_decimal_pair(g.month, der, - ccder_encode_decimal_pair(g.day, der, - ccder_encode_decimal_pair(g.hour, der, - ccder_encode_decimal_pair(g.minute, der, - ccder_encode_decimal_pair(g.second, der, - ccder_encode_nanoseconds(at, der, - ccder_encode_byte('Z', der, der_end)))))))); -} - -uint8_t* der_encode_generalizedtime(CFAbsoluteTime at, CFErrorRef *error, - const uint8_t *der, uint8_t *der_end) -{ - return ccder_encode_constructed_tl(CCDER_GENERALIZED_TIME, der_end, der, - der_encode_generalizedtime_body(at, error, der, der_end)); -} - - -uint8_t* der_encode_date(CFDateRef date, CFErrorRef *error, - const uint8_t *der, uint8_t *der_end) -{ - return der_encode_generalizedtime(CFDateGetAbsoluteTime(date), error, - der, der_end); -} diff --git a/utilities/src/der_date.h b/utilities/src/der_date.h deleted file mode 100644 index 9fcb5068..00000000 --- a/utilities/src/der_date.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// der_date.h -// utilities -// -// Created by Michael Brouwer on 7/9/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#ifndef _UTILITIES_DER_DATE_H_ -#define _UTILITIES_DER_DATE_H_ - -#include - -const uint8_t* der_decode_generalizedtime_body(CFAbsoluteTime *at, CFErrorRef *error, - const uint8_t* der, const uint8_t *der_end); -const uint8_t* der_decode_universaltime_body(CFAbsoluteTime *at, CFErrorRef *error, - const uint8_t* der, const uint8_t *der_end); - -size_t der_sizeof_generalizedtime(CFAbsoluteTime at, CFErrorRef *error); -uint8_t* der_encode_generalizedtime(CFAbsoluteTime at, CFErrorRef *error, - const uint8_t *der, uint8_t *der_end); - -size_t der_sizeof_generalizedtime_body(CFAbsoluteTime at, CFErrorRef *error); -uint8_t* der_encode_generalizedtime_body(CFAbsoluteTime at, CFErrorRef *error, - const uint8_t *der, uint8_t *der_end); - -#endif /* _UTILITIES_DER_DATE_H_ */ diff --git a/utilities/src/der_null.c b/utilities/src/der_null.c deleted file mode 100644 index 52e39449..00000000 --- a/utilities/src/der_null.c +++ /dev/null @@ -1,50 +0,0 @@ -// -// der_null.c -// utilities -// -// Created by Josh Osborne on 4/30/13. -// Copyright (c) 2013 Apple Inc. All rights reserved. -// - -#include - -#include "utilities/SecCFRelease.h" -#include "utilities/der_plist.h" -#include "utilities/der_plist_internal.h" - -#include -#include - - -const uint8_t* der_decode_null(CFAllocatorRef allocator, CFOptionFlags mutability, - CFNullRef* nul, CFErrorRef *error, - const uint8_t* der, const uint8_t *der_end) -{ - if (NULL == der) - return NULL; - - size_t payload_size = 0; - const uint8_t *payload = ccder_decode_tl(CCDER_NULL, &payload_size, der, der_end); - - if (NULL == payload || payload_size != 0) { - SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown null encoding"), NULL, error); - return NULL; - } - - *nul = kCFNull; - - return payload + payload_size; -} - - -size_t der_sizeof_null(CFNullRef data __unused, CFErrorRef *error) -{ - return ccder_sizeof(CCDER_NULL, 0); -} - - -uint8_t* der_encode_null(CFNullRef boolean __unused, CFErrorRef *error, - const uint8_t *der, uint8_t *der_end) -{ - return ccder_encode_tl(CCDER_NULL, 0, der, der_end); -} diff --git a/utilities/src/der_plist.h b/utilities/src/der_plist.h deleted file mode 100644 index f7e4720c..00000000 --- a/utilities/src/der_plist.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// der_plist.h -// utilities -// -// Created by Mitch Adler on 6/18/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#ifndef _DER_PLIST_H_ -#define _DER_PLIST_H_ - -#include - -// -// Error Codes for PropertyList <-> DER -// - -static const CFIndex kSecDERErrorUnknownEncoding = -1; -static const CFIndex kSecDERErrorUnsupportedCFObject = -2; -static const CFIndex kSecDERErrorUnsupportedDERType = -2; -static const CFIndex kSecDERErrorAllocationFailure = -3; -static const CFIndex kSecDERErrorUnsupportedNumberType = -4; - -static const CFIndex kSecDERErrorUnderlyingError = -100; - -extern CFStringRef sSecDERErrorDomain; - -// PropertyList <-> DER Functions - -size_t der_sizeof_plist(CFPropertyListRef pl, CFErrorRef *error); - -uint8_t* der_encode_plist(CFPropertyListRef pl, CFErrorRef *error, - const uint8_t *der, uint8_t *der_end); - -const uint8_t* der_decode_plist(CFAllocatorRef pl, CFOptionFlags mutability, - CFPropertyListRef* cf, CFErrorRef *error, - const uint8_t* der, const uint8_t *der_end); - -#endif diff --git a/utilities/src/der_plist_internal.c b/utilities/src/der_plist_internal.c deleted file mode 100644 index f99d1235..00000000 --- a/utilities/src/der_plist_internal.c +++ /dev/null @@ -1,18 +0,0 @@ -// -// SecCFToDER.c -// utilities -// -// Created by Mitch Adler on 7/2/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#include "utilities/der_plist_internal.h" -#include "utilities/SecCFError.h" -#include "utilities/SecCFRelease.h" -#include - -CFStringRef sSecDERErrorDomain = CFSTR("com.apple.security.cfder.error"); - -void SecCFDERCreateError(CFIndex errorCode, CFStringRef descriptionString, CFErrorRef previousError, CFErrorRef *newError) { - SecCFCreateError(errorCode, sSecDERErrorDomain, descriptionString, previousError, newError); -} diff --git a/utilities/src/der_string.c b/utilities/src/der_string.c deleted file mode 100644 index 67199f3c..00000000 --- a/utilities/src/der_string.c +++ /dev/null @@ -1,78 +0,0 @@ -// -// der_string.c -// utilities -// -// Created by Mitch Adler on 6/18/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#include - -#include "utilities/SecCFRelease.h" -#include "utilities/der_plist.h" -#include "utilities/der_plist_internal.h" - -#include -#include - - -const uint8_t* der_decode_string(CFAllocatorRef allocator, CFOptionFlags mutability, - CFStringRef* string, CFErrorRef *error, - const uint8_t* der, const uint8_t *der_end) -{ - if (NULL == der) - return NULL; - - size_t payload_size = 0; - const uint8_t *payload = ccder_decode_tl(CCDER_UTF8_STRING, &payload_size, der, der_end); - - if (NULL == payload || (der_end - payload) < payload_size){ - SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown string encoding"), NULL, error); - return NULL; - } - - *string = CFStringCreateWithBytes(allocator, payload, payload_size, kCFStringEncodingUTF8, false); - - if (NULL == *string) { - SecCFDERCreateError(kSecDERErrorAllocationFailure, CFSTR("String allocation failed"), NULL, error); - return NULL; - } - - return payload + payload_size; -} - - -size_t der_sizeof_string(CFStringRef str, CFErrorRef *error) -{ - const CFIndex str_length = CFStringGetLength(str); - const CFIndex maximum = CFStringGetMaximumSizeForEncoding(str_length, kCFStringEncodingUTF8); - - CFIndex encodedLen = 0; - CFIndex converted = CFStringGetBytes(str, CFRangeMake(0, str_length), kCFStringEncodingUTF8, 0, false, NULL, maximum, &encodedLen); - - return ccder_sizeof(CCDER_UTF8_STRING, (converted == str_length) ? encodedLen : 0); -} - - -uint8_t* der_encode_string(CFStringRef string, CFErrorRef *error, - const uint8_t *der, uint8_t *der_end) -{ - // Obey the NULL allowed rules. - if (!der_end) - return NULL; - - const CFIndex str_length = CFStringGetLength(string); - - ptrdiff_t der_space = der_end - der; - CFIndex bytes_used = 0; - uint8_t *buffer = der_end - der_space; - CFIndex converted = CFStringGetBytes(string, CFRangeMake(0, str_length), kCFStringEncodingUTF8, 0, false, buffer, der_space, &bytes_used); - if (converted != str_length){ - SecCFDERCreateError(kSecDERErrorUnderlyingError, CFSTR("String extraction failed"), NULL, error); - return NULL; - } - - return ccder_encode_tl(CCDER_UTF8_STRING, bytes_used, der, - ccder_encode_body(bytes_used, buffer, der, der_end)); - -} diff --git a/utilities/src/fileIo.c b/utilities/src/fileIo.c deleted file mode 100644 index 5c2ff649..00000000 --- a/utilities/src/fileIo.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2005-2007,2010 Apple Inc. All Rights Reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "fileIo.h" - -int writeFile( - const char *fileName, - const unsigned char *bytes, - size_t numBytes) -{ - int rtn; - int fd; - ssize_t wrc; - - if (!fileName) { - fwrite(bytes, 1, numBytes, stdout); - fflush(stdout); - return ferror(stdout); - } - - fd = open(fileName, O_RDWR | O_CREAT | O_TRUNC, 0600); - if(fd <= 0) { - return errno; - } - wrc = write(fd, bytes, (size_t)numBytes); - if(wrc != numBytes) { - if(wrc >= 0) { - fprintf(stderr, "writeFile: short write\n"); - } - rtn = EIO; - } - else { - rtn = 0; - } - close(fd); - return rtn; -} - -/* - * Read entire file. - */ -int readFile( - const char *fileName, - unsigned char **bytes, // mallocd and returned - size_t *numBytes) // returned -{ - int rtn; - int fd; - char *buf; - struct stat sb; - size_t size; - ssize_t rrc; - - *numBytes = 0; - *bytes = NULL; - fd = open(fileName, O_RDONLY); - if(fd <= 0) { - return errno; - } - rtn = fstat(fd, &sb); - if(rtn) { - goto errOut; - } - if (sb.st_size > SIZE_MAX) { - rtn = EFBIG; - goto errOut; - } - size = (size_t)sb.st_size; - buf = (char *)malloc(size); - if(buf == NULL) { - rtn = ENOMEM; - goto errOut; - } - rrc = read(fd, buf, size); - if(rrc != size) { - if(rtn >= 0) { - free(buf); - fprintf(stderr, "readFile: short read\n"); - } - rtn = EIO; - } - else { - rtn = 0; - *bytes = (unsigned char *)buf; - *numBytes = size; - } - -errOut: - close(fd); - return rtn; -} diff --git a/utilities/src/fileIo.h b/utilities/src/fileIo.h deleted file mode 100644 index f23ba03c..00000000 --- a/utilities/src/fileIo.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2005-2007,2010 Apple Inc. All Rights Reserved. - */ - -#include - -/* - * Read entire file. - */ -#ifdef __cplusplus -extern "C" { -#endif - -int readFile( - const char *fileName, - unsigned char **bytes, // mallocd and returned - size_t *numBytes); // returned - -int writeFile( - const char *fileName, - const unsigned char *bytes, - size_t numBytes); - -#ifdef __cplusplus -} -#endif diff --git a/utilities/src/iCloudKeychainTrace.c b/utilities/src/iCloudKeychainTrace.c deleted file mode 100644 index 5b744ae7..00000000 --- a/utilities/src/iCloudKeychainTrace.c +++ /dev/null @@ -1,195 +0,0 @@ -// -// iCloudKeychainTrace.c -// utilities -// -// Created on 7/17/13. -// Copyright (c) 2013 Apple Inc. All rights reserved. -// - -#include "iCloudKeychainTrace.h" -#include -#include -#include "SecCFWrappers.h" - -const CFStringRef kCloudKeychainNumbrerOfSyncingConflicts = CFSTR("com.apple.cloudkeychain.conflictsCount"); -const CFStringRef kCloudKeychainNumberOfTimesSyncFailed = CFSTR("com.apple.cloudkeychain.syncFailureCount"); -const CFStringRef kCloudKeychainNumberOfConflictsResolved = CFSTR("com.apple.cloudkeychain.conflictsResolved"); -const CFStringRef kCloudKeychainNumberOfTimesSyncedWithPeers = CFSTR("com.apple.cloudkeychain.syncedWithPeers"); - -static const CFStringRef gMessageTracerPrefix = CFSTR("com.apple.message."); - -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)) -#include - -static const char* gMessageTracerDomainField = "com.apple.message.domain"; -//static const char* gTopLevelKeyForiCloudKeychainTracing = "com.apple.cloudkeychain"; - -static bool OSX_SetCloudKeychainTraceValueForKey(CFStringRef key, int64_t value) -{ - bool result = false; - - if (NULL == key) - { - return result; - } - - aslmsg mAsl = NULL; - mAsl = asl_new(ASL_TYPE_MSG); - if (NULL == mAsl) - { - return result; - } - - CFIndex key_length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(key), kCFStringEncodingUTF8); - key_length += 1; // For null - char base_key_buffer[key_length]; - memset(base_key_buffer, 0,key_length); - if (!CFStringGetCString(key, base_key_buffer, key_length, kCFStringEncodingUTF8)) - { - asl_free(mAsl); - return result; - } - - - CFStringRef key_str = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@%@"), gMessageTracerPrefix, key); - if (NULL == key_str) - { - asl_free(mAsl); - return result; - } - - CFStringRef value_str = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%lld"), value); - if (NULL == value_str) - { - asl_free(mAsl); - CFRelease(key_str); - return result; - } - - CFIndex key_str_numBytes = CFStringGetMaximumSizeForEncoding(CFStringGetLength(key_str), kCFStringEncodingUTF8); - key_str_numBytes += 1; // For null - char key_buffer[key_str_numBytes]; - memset(key_buffer, 0, key_str_numBytes); - if (!CFStringGetCString(key_str, key_buffer, key_str_numBytes, kCFStringEncodingUTF8)) - { - asl_free(mAsl); - CFRelease(key_str); - CFRelease(value_str); - return result; - } - CFRelease(key_str); - - CFIndex value_str_numBytes = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value_str), kCFStringEncodingUTF8); - value_str_numBytes += 1; // For null - char value_buffer[value_str_numBytes]; - memset(value_buffer, 0, value_str_numBytes); - if (!CFStringGetCString(value_str, value_buffer, value_str_numBytes, kCFStringEncodingUTF8)) - { - asl_free(mAsl); - CFRelease(value_str); - return result; - } - CFRelease(value_str); - - asl_set(mAsl, gMessageTracerDomainField, base_key_buffer); - - asl_set(mAsl, key_buffer, value_buffer); - asl_log(NULL, mAsl, ASL_LEVEL_NOTICE, "%s is %lld", key_buffer, value); - asl_free(mAsl); - return true; -} -#endif - -#if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR) - -typedef void (*type_ADClientClearScalarKey)(CFStringRef key); -typedef void (*type_ADClientAddValueForScalarKey)(CFStringRef key, int64_t value); - -static type_ADClientClearScalarKey gADClientClearScalarKey = NULL; -static type_ADClientAddValueForScalarKey gADClientAddValueForScalarKey = NULL; - -static dispatch_once_t gADFunctionPointersSet = 0; -static CFBundleRef gAggdBundleRef = NULL; -static bool gFunctionPointersAreLoaded = false; - -static bool InitializeADFunctionPointers() -{ - if (gFunctionPointersAreLoaded) - { - return gFunctionPointersAreLoaded; - } - - dispatch_once(&gADFunctionPointersSet, - ^{ - CFStringRef path_to_aggd_framework = CFSTR("/System/Library/PrivateFrameworks/AggregateDictionary.framework"); - - CFURLRef aggd_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path_to_aggd_framework, kCFURLPOSIXPathStyle, true); - - if (NULL != aggd_url) - { - gAggdBundleRef = CFBundleCreate(kCFAllocatorDefault, aggd_url); - if (NULL != gAggdBundleRef) - { - gADClientClearScalarKey = (type_ADClientClearScalarKey) - CFBundleGetFunctionPointerForName(gAggdBundleRef, CFSTR("ADClientClearScalarKey")); - - gADClientAddValueForScalarKey = (type_ADClientAddValueForScalarKey) - CFBundleGetFunctionPointerForName(gAggdBundleRef, CFSTR("ADClientAddValueForScalarKey")); - } - CFRelease(aggd_url); - } - }); - - gFunctionPointersAreLoaded = ((NULL != gADClientClearScalarKey) && (NULL != gADClientAddValueForScalarKey)); - return gFunctionPointersAreLoaded; -} - -static void Internal_ADClientClearScalarKey(CFStringRef key) -{ - if (InitializeADFunctionPointers()) - { - gADClientClearScalarKey(key); - } -} - -static void Internal_ADClientAddValueForScalarKey(CFStringRef key, int64_t value) -{ - if (InitializeADFunctionPointers()) - { - gADClientAddValueForScalarKey(key, value); - } -} - -static bool iOS_SetCloudKeychainTraceValueForKey(CFStringRef key, int64_t value) -{ - if (NULL == key) - { - return false; - } - - if (0LL == value) - { - Internal_ADClientClearScalarKey(key); - } - else - { - Internal_ADClientAddValueForScalarKey(key, value); - } - return true; -} -#endif - -bool SetCloudKeychainTraceValueForKey(CFStringRef key, int64_t value) -{ -#if (TARGET_IPHONE_SIMULATOR) - return false; -#endif - -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) - return OSX_SetCloudKeychainTraceValueForKey(key, value); -#endif - -#if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR) - return iOS_SetCloudKeychainTraceValueForKey(key, value); -#endif -} diff --git a/utilities/src/iCloudKeychainTrace.h b/utilities/src/iCloudKeychainTrace.h deleted file mode 100644 index 4f635f58..00000000 --- a/utilities/src/iCloudKeychainTrace.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2006-2007,2009-2010 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@ - */ - -/* - * iCloudKeychainTrace.h - log statistics for iCloud Keychain usage - */ - -#include - -const CFStringRef kCloudKeychainNumbrerOfSyncingConflicts - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -const CFStringRef kCloudKeychainNumberOfTimesSyncFailed - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -const CFStringRef kCloudKeychainNumberOfConflictsResolved - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); -const CFStringRef kCloudKeychainNumberOfTimesSyncedWithPeers - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - -bool SetCloudKeychainTraceValueForKey(CFStringRef key, int64_t value) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); - - diff --git a/utilities/src/iOSforOSX-SecAttr.c b/utilities/src/iOSforOSX-SecAttr.c deleted file mode 100644 index 9b34f289..00000000 --- a/utilities/src/iOSforOSX-SecAttr.c +++ /dev/null @@ -1,27 +0,0 @@ -// -// iOSforOSX.c -// utilities -// -// Created by J Osborne on 11/13/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#include - -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) -#include - -#include -#include -#include -#include "iOSforOSX.h" -#include -#include - -// Was in SOSAccount.c -#define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); -// We may not have all of these we need -SEC_CONST_DECL (kSecAttrAccessible, "pdmn"); -SEC_CONST_DECL (kSecAttrAccessibleAlwaysThisDeviceOnly, "dku"); - -#endif diff --git a/utilities/src/iOSforOSX-SecRandom.c b/utilities/src/iOSforOSX-SecRandom.c deleted file mode 100644 index 4950cb28..00000000 --- a/utilities/src/iOSforOSX-SecRandom.c +++ /dev/null @@ -1,13 +0,0 @@ -// -// iOSforOSX.c -// utilities -// -// Created by J Osborne on 11/13/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#include - -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) -const void *kSecRandomDefault = (void*)0; -#endif diff --git a/utilities/src/iOSforOSX.c b/utilities/src/iOSforOSX.c deleted file mode 100644 index d17cbef2..00000000 --- a/utilities/src/iOSforOSX.c +++ /dev/null @@ -1,67 +0,0 @@ -// -// iOSforOSX.c -// utilities -// -// Created by J Osborne on 11/13/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#include - -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) - -#include -#include -#include - -#include -#include -#include -#include "iOSforOSX.h" -#include -#include - -#include ".././libsecurity_keychain/lib/SecBase64P.c" - -CFURLRef SecCopyKeychainDirectoryFile(CFStringRef file) -{ - struct passwd *passwd = getpwuid(getuid()); - if (!passwd) - return NULL; - - CFURLRef pathURL = NULL; - CFURLRef fileURL = NULL; - CFStringRef home = NULL; - CFStringRef filePath = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s/%@"), "Library/Keychains", file); - require(filePath, xit); - - if (passwd->pw_dir) - home = CFStringCreateWithCString(NULL, passwd->pw_dir, kCFStringEncodingUTF8); - - pathURL = CFURLCreateWithFileSystemPath(NULL, home?home:CFSTR("/"), kCFURLPOSIXPathStyle, true); - if (pathURL) - fileURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault, pathURL, filePath, false); - -xit: - CFReleaseSafe(filePath); - CFReleaseSafe(pathURL); - CFReleaseSafe(home); - return fileURL; -} - -// XXX: do we still need this? see securityd_files? -CFURLRef PortableCFCopyHomeDirectoryURL(void) -{ - char *path = getenv("HOME"); - if (!path) { - struct passwd *pw = getpwuid(getuid()); - path = pw->pw_dir; - } - CFStringRef path_cf = CFStringCreateWithCStringNoCopy(NULL, path, kCFStringEncodingUTF8, kCFAllocatorNull); - CFURLRef path_url = CFURLCreateWithFileSystemPath(NULL, path_cf, kCFURLPOSIXPathStyle, true); - - CFRelease(path_cf); - return path_url; -} - -#endif diff --git a/utilities/src/iOSforOSX.h b/utilities/src/iOSforOSX.h deleted file mode 100644 index 96cb072f..00000000 --- a/utilities/src/iOSforOSX.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// iOSforOSX.h -// utilities -// -// Created by J Osborne on 11/13/12. -// Copyright (c) 2012 Apple Inc. All rights reserved. -// - -#ifndef utilities_iOSforOSX_h -#define utilities_iOSforOSX_h - -#include -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) - -extern CFURLRef SecCopyKeychainDirectoryFile(CFStringRef file); - -CFURLRef PortableCFCopyHomeDirectoryURL(void); - -#ifndef _SECURITY_SECRANDOM_H_ -extern const void *kSecRandomDefault; -#endif - -#ifndef _SECURITY_SECBASE_H_ -typedef struct OpaqueSecKeyRef *SecKeyRef; -#endif -OSStatus SecKeyCopyPersistentRef(SecKeyRef item, CFDataRef *newPersistantRef); -OSStatus SecKeyFindWithPersistentRef(CFDataRef persistantRef, SecKeyRef *key); - - -#endif - -CFURLRef PortableCFCopyHomeDirectoryURL(void) asm("_CFCopyHomeDirectoryURL"); - -#endif diff --git a/utilities/src/sqlutils.h b/utilities/src/sqlutils.h deleted file mode 100644 index 6837a036..00000000 --- a/utilities/src/sqlutils.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// sqlutils.h -// Security -// -// Created by Fabrice Gautier on 8/26/11. -// Copyright (c) 2011 Apple, Inc. All rights reserved. -// - -/* - * sqlutils.h - some wrapper for sql3lite - */ -#ifndef _SECURITY_UTILITIES_SQLUTILS_H_ -#define _SECURITY_UTILITIES_SQLUTILS_H_ - -#include - -/* Those are just wrapper around the sqlite3 functions, but they have size_t for some len parameters, - and checks for overflow before casting to int */ -static inline int sqlite3_bind_blob_wrapper(sqlite3_stmt* pStmt, int i, const void* zData, size_t n, void(*xDel)(void*)) -{ - if(n>INT_MAX) return SQLITE_TOOBIG; - return sqlite3_bind_blob(pStmt, i, zData, (int)n, xDel); -} - -static inline int sqlite3_bind_text_wrapper(sqlite3_stmt* pStmt, int i, const void* zData, size_t n, void(*xDel)(void*)) -{ - if(n>INT_MAX) return SQLITE_TOOBIG; - return sqlite3_bind_text(pStmt, i, zData, (int)n, xDel); -} - -static inline int sqlite3_prepare_wrapper(sqlite3 *db, const char *zSql, size_t nByte, sqlite3_stmt **ppStmt, const char **pzTail) -{ - if(nByte>INT_MAX) return SQLITE_TOOBIG; - return sqlite3_prepare(db, zSql, (int)nByte, ppStmt, pzTail); -} - -#endif diff --git a/utilities/utilities.xcodeproj/project.pbxproj b/utilities/utilities.xcodeproj/project.pbxproj deleted file mode 100644 index 8998266f..00000000 --- a/utilities/utilities.xcodeproj/project.pbxproj +++ /dev/null @@ -1,546 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 4C068F811653146500E8A1BB /* iOSforOSX.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C068F801653146500E8A1BB /* iOSforOSX.h */; }; - 4C143CF8165172AD003035A3 /* SecDb.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C143CF7165172AD003035A3 /* SecDb.c */; }; - 4C3600451680DEB90049891B /* iOSforOSX-SecAttr.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C3600431680DEB90049891B /* iOSforOSX-SecAttr.c */; }; - 4C3600461680DEB90049891B /* iOSforOSX-SecRandom.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C3600441680DEB90049891B /* iOSforOSX-SecRandom.c */; }; - 4C3963D915ACF2E700762091 /* su-16-cfdate-der.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C3963D815ACF2E700762091 /* su-16-cfdate-der.c */; }; - 4C5BCD8A17304CE600DCEFB4 /* der_null.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C5BCD8917304B8100DCEFB4 /* der_null.c */; }; - 4C6882D415ABADBC00028C8F /* SecCFCanonicalHashes.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882BD15ABADBC00028C8F /* SecCFCanonicalHashes.c */; }; - 4C6882D515ABADBC00028C8F /* SecCFCanonicalHashes.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6882BE15ABADBC00028C8F /* SecCFCanonicalHashes.h */; }; - 4C6882D615ABADBC00028C8F /* SecCFRelease.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6882BF15ABADBC00028C8F /* SecCFRelease.h */; }; - 4C6882D715ABADBC00028C8F /* SecCFWrappers.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6882C015ABADBC00028C8F /* SecCFWrappers.h */; }; - 4C6882D815ABADBC00028C8F /* array_size.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6882C115ABADBC00028C8F /* array_size.h */; }; - 4C6882D915ABADBC00028C8F /* comparison.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882C215ABADBC00028C8F /* comparison.c */; }; - 4C6882DA15ABADBC00028C8F /* comparison.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6882C315ABADBC00028C8F /* comparison.h */; }; - 4C6882DB15ABADBC00028C8F /* debugging.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882C415ABADBC00028C8F /* debugging.c */; }; - 4C6882DC15ABADBC00028C8F /* debugging.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6882C515ABADBC00028C8F /* debugging.h */; }; - 4C6882DD15ABADBC00028C8F /* der_array.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882C615ABADBC00028C8F /* der_array.c */; }; - 4C6882DE15ABADBC00028C8F /* der_boolean.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882C715ABADBC00028C8F /* der_boolean.c */; }; - 4C6882DF15ABADBC00028C8F /* der_data.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882C815ABADBC00028C8F /* der_data.c */; }; - 4C6882E015ABADBC00028C8F /* der_date.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882C915ABADBC00028C8F /* der_date.c */; }; - 4C6882E115ABADBC00028C8F /* der_dictionary.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882CA15ABADBC00028C8F /* der_dictionary.c */; }; - 4C6882E215ABADBC00028C8F /* der_number.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882CB15ABADBC00028C8F /* der_number.c */; }; - 4C6882E315ABADBC00028C8F /* der_plist.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882CC15ABADBC00028C8F /* der_plist.c */; }; - 4C6882E415ABADBC00028C8F /* der_plist.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6882CD15ABADBC00028C8F /* der_plist.h */; }; - 4C6882E515ABADBC00028C8F /* der_plist_internal.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882CE15ABADBC00028C8F /* der_plist_internal.c */; }; - 4C6882E615ABADBC00028C8F /* der_plist_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6882CF15ABADBC00028C8F /* der_plist_internal.h */; }; - 4C6882E715ABADBC00028C8F /* der_string.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882D015ABADBC00028C8F /* der_string.c */; }; - 4C6882E815ABADBC00028C8F /* fileIo.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6882D115ABADBC00028C8F /* fileIo.c */; }; - 4C6882E915ABADBC00028C8F /* fileIo.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6882D215ABADBC00028C8F /* fileIo.h */; }; - 4C6882EA15ABADBC00028C8F /* sqlutils.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6882D315ABADBC00028C8F /* sqlutils.h */; }; - 4CB23B9816A09503003A0131 /* not_on_this_platorm.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CB23B9716A09503003A0131 /* not_on_this_platorm.c */; }; - 4CC0275217A1C796004067B2 /* su-41-secdb-stress.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC0275117A1C796004067B2 /* su-41-secdb-stress.c */; }; - 4CC92B1F15A3C55200C6D578 /* utilities_regressions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92B1E15A3C55200C6D578 /* utilities_regressions.h */; }; - 4CF1FAC21654EAD100261CF4 /* SecCFWrappers.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CF1FAC11654EAD100261CF4 /* SecCFWrappers.c */; }; - 4CF1FAC416550F6900261CF4 /* su-40-secdb.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CF1FAC316550F6900261CF4 /* su-40-secdb.c */; }; - 52743BD616BB278C001A299D /* SecFileLocations.c in Sources */ = {isa = PBXBuildFile; fileRef = 52743BD516BB278C001A299D /* SecFileLocations.c */; }; - 52743BD816BB27A1001A299D /* SecFileLocations.h in Headers */ = {isa = PBXBuildFile; fileRef = 52743BD716BB27A1001A299D /* SecFileLocations.h */; }; - 52E2E4951738371400E78313 /* SecXPCError.h in Headers */ = {isa = PBXBuildFile; fileRef = 52E2E4941738371400E78313 /* SecXPCError.h */; }; - 52E2E4971738394C00E78313 /* SecXPCError.c in Sources */ = {isa = PBXBuildFile; fileRef = 52E2E4961738394C00E78313 /* SecXPCError.c */; }; - 72B918A1179723B500940533 /* iCloudKeychainTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B9189F179723AE00940533 /* iCloudKeychainTrace.c */; }; - 72B918A2179723C100940533 /* iCloudKeychainTrace.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B918A0179723AE00940533 /* iCloudKeychainTrace.h */; }; - BEA22A361811E4C800BE7682 /* SecCertificateTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = BEA22A341811E4A600BE7682 /* SecCertificateTrace.c */; }; - BEA22A371811E4CF00BE7682 /* SecCertificateTrace.h in Headers */ = {isa = PBXBuildFile; fileRef = BEA22A351811E4A600BE7682 /* SecCertificateTrace.h */; }; - E72D461E175FB73100F70B9B /* SecAKSWrappers.h in Headers */ = {isa = PBXBuildFile; fileRef = E72D461D175FAF1E00F70B9B /* SecAKSWrappers.h */; }; - E72D462D175FC35500F70B9B /* SecAKSWrappers.c in Sources */ = {isa = PBXBuildFile; fileRef = E72D462C175FC35500F70B9B /* SecAKSWrappers.c */; }; - E765E23615A79F77006C7347 /* su-15-cfdictionary-der.c in Sources */ = {isa = PBXBuildFile; fileRef = E765E23315A79EA6006C7347 /* su-15-cfdictionary-der.c */; }; - E777C72115B74029004044A8 /* SecCFError.h in Headers */ = {isa = PBXBuildFile; fileRef = E777C71F15B74024004044A8 /* SecCFError.h */; }; - E777C72315B74038004044A8 /* SecCFError.c in Sources */ = {isa = PBXBuildFile; fileRef = E777C72215B74037004044A8 /* SecCFError.c */; }; - E790C14C169E5D9C00E0C0C9 /* readline.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C14A169E5D9C00E0C0C9 /* readline.c */; }; - E790C14D169E5D9C00E0C0C9 /* readline.h in Headers */ = {isa = PBXBuildFile; fileRef = E790C14B169E5D9C00E0C0C9 /* readline.h */; }; - E7934D7115A3A29D007666E0 /* su-14-cfarray-der.c in Sources */ = {isa = PBXBuildFile; fileRef = E7934D6E15A3A298007666E0 /* su-14-cfarray-der.c */; }; - E79D9CE3159D2DB8000834EC /* su-12-cfboolean-der.c in Sources */ = {isa = PBXBuildFile; fileRef = E79D9CE2159D2DB8000834EC /* su-12-cfboolean-der.c */; }; - E79D9CE5159D3138000834EC /* su-13-cfnumber-der.c in Sources */ = {isa = PBXBuildFile; fileRef = E79D9CE4159D3138000834EC /* su-13-cfnumber-der.c */; }; - E7AAB5FA15929D44005C8BCC /* su-11-cfdata-der.c in Sources */ = {isa = PBXBuildFile; fileRef = E7AAB5F815929D3E005C8BCC /* su-11-cfdata-der.c */; }; - E7E0D909158FD9CD002CA176 /* su-10-cfstring-der.c in Sources */ = {isa = PBXBuildFile; fileRef = E7E0D908158FD9CD002CA176 /* su-10-cfstring-der.c */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 4C068F801653146500E8A1BB /* iOSforOSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iOSforOSX.h; sourceTree = ""; }; - 4C068F821653147D00E8A1BB /* iOSforOSX.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iOSforOSX.c; sourceTree = ""; }; - 4C143CF7165172AD003035A3 /* SecDb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecDb.c; sourceTree = ""; }; - 4C143CF9165172C0003035A3 /* SecDb.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecDb.h; sourceTree = ""; }; - 4C3600431680DEB90049891B /* iOSforOSX-SecAttr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "iOSforOSX-SecAttr.c"; sourceTree = ""; }; - 4C3600441680DEB90049891B /* iOSforOSX-SecRandom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "iOSforOSX-SecRandom.c"; sourceTree = ""; }; - 4C3963D815ACF2E700762091 /* su-16-cfdate-der.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-16-cfdate-der.c"; sourceTree = ""; }; - 4C5BCD8917304B8100DCEFB4 /* der_null.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = der_null.c; sourceTree = ""; }; - 4C6882BD15ABADBC00028C8F /* SecCFCanonicalHashes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecCFCanonicalHashes.c; sourceTree = ""; }; - 4C6882BE15ABADBC00028C8F /* SecCFCanonicalHashes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCFCanonicalHashes.h; sourceTree = ""; }; - 4C6882BF15ABADBC00028C8F /* SecCFRelease.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCFRelease.h; sourceTree = ""; }; - 4C6882C015ABADBC00028C8F /* SecCFWrappers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCFWrappers.h; sourceTree = ""; }; - 4C6882C115ABADBC00028C8F /* array_size.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = array_size.h; sourceTree = ""; }; - 4C6882C215ABADBC00028C8F /* comparison.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = comparison.c; sourceTree = ""; }; - 4C6882C315ABADBC00028C8F /* comparison.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = comparison.h; sourceTree = ""; }; - 4C6882C415ABADBC00028C8F /* debugging.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = debugging.c; sourceTree = ""; }; - 4C6882C515ABADBC00028C8F /* debugging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debugging.h; sourceTree = ""; }; - 4C6882C615ABADBC00028C8F /* der_array.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = der_array.c; sourceTree = ""; }; - 4C6882C715ABADBC00028C8F /* der_boolean.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = der_boolean.c; sourceTree = ""; }; - 4C6882C815ABADBC00028C8F /* der_data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = der_data.c; sourceTree = ""; }; - 4C6882C915ABADBC00028C8F /* der_date.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = der_date.c; sourceTree = ""; }; - 4C6882CA15ABADBC00028C8F /* der_dictionary.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = der_dictionary.c; sourceTree = ""; }; - 4C6882CB15ABADBC00028C8F /* der_number.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = der_number.c; sourceTree = ""; }; - 4C6882CC15ABADBC00028C8F /* der_plist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = der_plist.c; sourceTree = ""; }; - 4C6882CD15ABADBC00028C8F /* der_plist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = der_plist.h; sourceTree = ""; }; - 4C6882CE15ABADBC00028C8F /* der_plist_internal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = der_plist_internal.c; sourceTree = ""; }; - 4C6882CF15ABADBC00028C8F /* der_plist_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = der_plist_internal.h; sourceTree = ""; }; - 4C6882D015ABADBC00028C8F /* der_string.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = der_string.c; sourceTree = ""; }; - 4C6882D115ABADBC00028C8F /* fileIo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fileIo.c; sourceTree = ""; }; - 4C6882D215ABADBC00028C8F /* fileIo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fileIo.h; sourceTree = ""; }; - 4C6882D315ABADBC00028C8F /* sqlutils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqlutils.h; sourceTree = ""; }; - 4C6882EB15ABC4B400028C8F /* der_date.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = der_date.h; sourceTree = ""; }; - 4CB23B9616A09318003A0131 /* security_tool_commands_table.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = security_tool_commands_table.h; sourceTree = ""; }; - 4CB23B9716A09503003A0131 /* not_on_this_platorm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = not_on_this_platorm.c; sourceTree = ""; }; - 4CC0275117A1C796004067B2 /* su-41-secdb-stress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-41-secdb-stress.c"; sourceTree = ""; }; - 4CC92B1E15A3C55200C6D578 /* utilities_regressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utilities_regressions.h; sourceTree = ""; }; - 4CF1FAC11654EAD100261CF4 /* SecCFWrappers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecCFWrappers.c; sourceTree = ""; }; - 4CF1FAC316550F6900261CF4 /* su-40-secdb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-40-secdb.c"; sourceTree = ""; }; - 52743BD516BB278C001A299D /* SecFileLocations.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecFileLocations.c; sourceTree = ""; }; - 52743BD716BB27A1001A299D /* SecFileLocations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecFileLocations.h; sourceTree = ""; }; - 52E2E4941738371400E78313 /* SecXPCError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecXPCError.h; sourceTree = ""; }; - 52E2E4961738394C00E78313 /* SecXPCError.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecXPCError.c; sourceTree = ""; }; - 72B9189F179723AE00940533 /* iCloudKeychainTrace.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = iCloudKeychainTrace.c; sourceTree = ""; }; - 72B918A0179723AE00940533 /* iCloudKeychainTrace.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = iCloudKeychainTrace.h; sourceTree = ""; }; - BEA22A341811E4A600BE7682 /* SecCertificateTrace.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecCertificateTrace.c; sourceTree = ""; }; - BEA22A351811E4A600BE7682 /* SecCertificateTrace.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecCertificateTrace.h; sourceTree = ""; }; - E72D461D175FAF1E00F70B9B /* SecAKSWrappers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecAKSWrappers.h; sourceTree = ""; }; - E72D462C175FC35500F70B9B /* SecAKSWrappers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecAKSWrappers.c; sourceTree = ""; }; - E742A09C14E343E70052A486 /* libutilities.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libutilities.a; sourceTree = BUILT_PRODUCTS_DIR; }; - E742A0C014E344940052A486 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; - E765E23315A79EA6006C7347 /* su-15-cfdictionary-der.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-15-cfdictionary-der.c"; sourceTree = ""; }; - E777C71F15B74024004044A8 /* SecCFError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecCFError.h; sourceTree = ""; }; - E777C72215B74037004044A8 /* SecCFError.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecCFError.c; sourceTree = ""; }; - E790C0F6169E4B8500E0C0C9 /* security_tool_commands.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = security_tool_commands.h; sourceTree = ""; }; - E790C14A169E5D9C00E0C0C9 /* readline.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readline.c; sourceTree = ""; }; - E790C14B169E5D9C00E0C0C9 /* readline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = readline.h; sourceTree = ""; }; - E7934D6E15A3A298007666E0 /* su-14-cfarray-der.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-14-cfarray-der.c"; sourceTree = ""; }; - E79D9CE2159D2DB8000834EC /* su-12-cfboolean-der.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-12-cfboolean-der.c"; sourceTree = ""; }; - E79D9CE4159D3138000834EC /* su-13-cfnumber-der.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-13-cfnumber-der.c"; sourceTree = ""; }; - E7AAB5F815929D3E005C8BCC /* su-11-cfdata-der.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-11-cfdata-der.c"; sourceTree = ""; }; - E7B01B961664031B000485F1 /* SecDispatchRelease.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecDispatchRelease.h; sourceTree = ""; }; - E7E0D8F9158FA9A3002CA176 /* libutilitiesRegressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libutilitiesRegressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; - E7E0D908158FD9CD002CA176 /* su-10-cfstring-der.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-10-cfstring-der.c"; sourceTree = ""; }; - E7FC081B161A3038008E0760 /* SecIOFormat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecIOFormat.h; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - E742A09914E343E70052A486 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E7E0D8ED158FA9A3002CA176 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 4C6882BC15ABADBC00028C8F /* src */ = { - isa = PBXGroup; - children = ( - 72B9189F179723AE00940533 /* iCloudKeychainTrace.c */, - 72B918A0179723AE00940533 /* iCloudKeychainTrace.h */, - E72D462C175FC35500F70B9B /* SecAKSWrappers.c */, - E72D461D175FAF1E00F70B9B /* SecAKSWrappers.h */, - BEA22A341811E4A600BE7682 /* SecCertificateTrace.c */, - BEA22A351811E4A600BE7682 /* SecCertificateTrace.h */, - 4C6882BD15ABADBC00028C8F /* SecCFCanonicalHashes.c */, - 4C6882BE15ABADBC00028C8F /* SecCFCanonicalHashes.h */, - 4C6882BF15ABADBC00028C8F /* SecCFRelease.h */, - 4CF1FAC11654EAD100261CF4 /* SecCFWrappers.c */, - 4C6882C015ABADBC00028C8F /* SecCFWrappers.h */, - E777C72215B74037004044A8 /* SecCFError.c */, - E777C71F15B74024004044A8 /* SecCFError.h */, - E7B01B961664031B000485F1 /* SecDispatchRelease.h */, - E7FC081B161A3038008E0760 /* SecIOFormat.h */, - 4C6882C115ABADBC00028C8F /* array_size.h */, - 4C6882C215ABADBC00028C8F /* comparison.c */, - 4C6882C315ABADBC00028C8F /* comparison.h */, - 4C6882C415ABADBC00028C8F /* debugging.c */, - 4C6882C515ABADBC00028C8F /* debugging.h */, - 4C6882C615ABADBC00028C8F /* der_array.c */, - 4C6882C715ABADBC00028C8F /* der_boolean.c */, - 4C5BCD8917304B8100DCEFB4 /* der_null.c */, - 4C6882C815ABADBC00028C8F /* der_data.c */, - 4C6882C915ABADBC00028C8F /* der_date.c */, - 4C6882EB15ABC4B400028C8F /* der_date.h */, - 4C6882CA15ABADBC00028C8F /* der_dictionary.c */, - 4C6882CB15ABADBC00028C8F /* der_number.c */, - 4C6882CC15ABADBC00028C8F /* der_plist.c */, - 4C6882CD15ABADBC00028C8F /* der_plist.h */, - 4C6882CE15ABADBC00028C8F /* der_plist_internal.c */, - 4C6882CF15ABADBC00028C8F /* der_plist_internal.h */, - 4C6882D015ABADBC00028C8F /* der_string.c */, - 4C6882D115ABADBC00028C8F /* fileIo.c */, - 4C6882D215ABADBC00028C8F /* fileIo.h */, - 4C6882D315ABADBC00028C8F /* sqlutils.h */, - 4C068F801653146500E8A1BB /* iOSforOSX.h */, - 4C068F821653147D00E8A1BB /* iOSforOSX.c */, - 4C3600431680DEB90049891B /* iOSforOSX-SecAttr.c */, - 4C3600441680DEB90049891B /* iOSforOSX-SecRandom.c */, - 4C143CF7165172AD003035A3 /* SecDb.c */, - 4C143CF9165172C0003035A3 /* SecDb.h */, - 52743BD516BB278C001A299D /* SecFileLocations.c */, - 52743BD716BB27A1001A299D /* SecFileLocations.h */, - 52E2E4941738371400E78313 /* SecXPCError.h */, - 52E2E4961738394C00E78313 /* SecXPCError.c */, - ); - path = src; - sourceTree = ""; - }; - E742A09114E343E70052A486 = { - isa = PBXGroup; - children = ( - 4C6882BC15ABADBC00028C8F /* src */, - E7E0D8E7158FA984002CA176 /* Regressions */, - E790C0F5169E4B5E00E0C0C9 /* SecurityTool */, - E742A09E14E343E70052A486 /* Frameworks */, - E742A09D14E343E70052A486 /* Products */, - ); - sourceTree = ""; - }; - E742A09D14E343E70052A486 /* Products */ = { - isa = PBXGroup; - children = ( - E742A09C14E343E70052A486 /* libutilities.a */, - E7E0D8F9158FA9A3002CA176 /* libutilitiesRegressions.a */, - ); - name = Products; - sourceTree = ""; - }; - E742A09E14E343E70052A486 /* Frameworks */ = { - isa = PBXGroup; - children = ( - E742A0C014E344940052A486 /* CoreFoundation.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - E790C0F5169E4B5E00E0C0C9 /* SecurityTool */ = { - isa = PBXGroup; - children = ( - E790C14A169E5D9C00E0C0C9 /* readline.c */, - E790C14B169E5D9C00E0C0C9 /* readline.h */, - E790C0F6169E4B8500E0C0C9 /* security_tool_commands.h */, - 4CB23B9616A09318003A0131 /* security_tool_commands_table.h */, - 4CB23B9716A09503003A0131 /* not_on_this_platorm.c */, - ); - path = SecurityTool; - sourceTree = ""; - }; - E7E0D8E7158FA984002CA176 /* Regressions */ = { - isa = PBXGroup; - children = ( - 4CC92B1E15A3C55200C6D578 /* utilities_regressions.h */, - E7E0D908158FD9CD002CA176 /* su-10-cfstring-der.c */, - E7AAB5F815929D3E005C8BCC /* su-11-cfdata-der.c */, - E79D9CE2159D2DB8000834EC /* su-12-cfboolean-der.c */, - E79D9CE4159D3138000834EC /* su-13-cfnumber-der.c */, - E7934D6E15A3A298007666E0 /* su-14-cfarray-der.c */, - E765E23315A79EA6006C7347 /* su-15-cfdictionary-der.c */, - 4C3963D815ACF2E700762091 /* su-16-cfdate-der.c */, - 4CF1FAC316550F6900261CF4 /* su-40-secdb.c */, - 4CC0275117A1C796004067B2 /* su-41-secdb-stress.c */, - ); - path = Regressions; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - E742A09A14E343E70052A486 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 72B918A2179723C100940533 /* iCloudKeychainTrace.h in Headers */, - 4C6882D515ABADBC00028C8F /* SecCFCanonicalHashes.h in Headers */, - 4C6882D615ABADBC00028C8F /* SecCFRelease.h in Headers */, - 52E2E4951738371400E78313 /* SecXPCError.h in Headers */, - 4C6882D715ABADBC00028C8F /* SecCFWrappers.h in Headers */, - E72D461E175FB73100F70B9B /* SecAKSWrappers.h in Headers */, - 4C6882D815ABADBC00028C8F /* array_size.h in Headers */, - 4C6882DA15ABADBC00028C8F /* comparison.h in Headers */, - 4C6882DC15ABADBC00028C8F /* debugging.h in Headers */, - 4C6882E415ABADBC00028C8F /* der_plist.h in Headers */, - BEA22A371811E4CF00BE7682 /* SecCertificateTrace.h in Headers */, - 4C6882E615ABADBC00028C8F /* der_plist_internal.h in Headers */, - 4C6882E915ABADBC00028C8F /* fileIo.h in Headers */, - 4C6882EA15ABADBC00028C8F /* sqlutils.h in Headers */, - E777C72115B74029004044A8 /* SecCFError.h in Headers */, - 4C068F811653146500E8A1BB /* iOSforOSX.h in Headers */, - E790C14D169E5D9C00E0C0C9 /* readline.h in Headers */, - 52743BD816BB27A1001A299D /* SecFileLocations.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E7E0D8EF158FA9A3002CA176 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 4CC92B1F15A3C55200C6D578 /* utilities_regressions.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - E742A09B14E343E70052A486 /* utilities */ = { - isa = PBXNativeTarget; - buildConfigurationList = E742A0A914E343E70052A486 /* Build configuration list for PBXNativeTarget "utilities" */; - buildPhases = ( - E742A09814E343E70052A486 /* Sources */, - E742A09914E343E70052A486 /* Frameworks */, - E742A09A14E343E70052A486 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = utilities; - productName = security_utilities; - productReference = E742A09C14E343E70052A486 /* libutilities.a */; - productType = "com.apple.product-type.library.static"; - }; - E7E0D8E8158FA9A3002CA176 /* utilitiesRegressions */ = { - isa = PBXNativeTarget; - buildConfigurationList = E7E0D8F6158FA9A3002CA176 /* Build configuration list for PBXNativeTarget "utilitiesRegressions" */; - buildPhases = ( - E7E0D8E9158FA9A3002CA176 /* Sources */, - E7E0D8ED158FA9A3002CA176 /* Frameworks */, - E7E0D8EF158FA9A3002CA176 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = utilitiesRegressions; - productName = security_utilities; - productReference = E7E0D8F9158FA9A3002CA176 /* libutilitiesRegressions.a */; - productType = "com.apple.product-type.library.static"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - E742A09314E343E70052A486 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0450; - ORGANIZATIONNAME = "Apple Inc."; - }; - buildConfigurationList = E742A09614E343E70052A486 /* Build configuration list for PBXProject "utilities" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = E742A09114E343E70052A486; - productRefGroup = E742A09D14E343E70052A486 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - E742A09B14E343E70052A486 /* utilities */, - E7E0D8E8158FA9A3002CA176 /* utilitiesRegressions */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - E742A09814E343E70052A486 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 4C6882D415ABADBC00028C8F /* SecCFCanonicalHashes.c in Sources */, - 4C6882D915ABADBC00028C8F /* comparison.c in Sources */, - 4C6882DB15ABADBC00028C8F /* debugging.c in Sources */, - 72B918A1179723B500940533 /* iCloudKeychainTrace.c in Sources */, - 4C6882DD15ABADBC00028C8F /* der_array.c in Sources */, - 4C6882DE15ABADBC00028C8F /* der_boolean.c in Sources */, - 4C6882DF15ABADBC00028C8F /* der_data.c in Sources */, - 4C6882E015ABADBC00028C8F /* der_date.c in Sources */, - E72D462D175FC35500F70B9B /* SecAKSWrappers.c in Sources */, - 4C6882E115ABADBC00028C8F /* der_dictionary.c in Sources */, - 4C6882E215ABADBC00028C8F /* der_number.c in Sources */, - 4C6882E315ABADBC00028C8F /* der_plist.c in Sources */, - 4C6882E515ABADBC00028C8F /* der_plist_internal.c in Sources */, - 4C6882E715ABADBC00028C8F /* der_string.c in Sources */, - 4C6882E815ABADBC00028C8F /* fileIo.c in Sources */, - E777C72315B74038004044A8 /* SecCFError.c in Sources */, - 4C143CF8165172AD003035A3 /* SecDb.c in Sources */, - 4CF1FAC21654EAD100261CF4 /* SecCFWrappers.c in Sources */, - 52E2E4971738394C00E78313 /* SecXPCError.c in Sources */, - 4C3600451680DEB90049891B /* iOSforOSX-SecAttr.c in Sources */, - 4C3600461680DEB90049891B /* iOSforOSX-SecRandom.c in Sources */, - BEA22A361811E4C800BE7682 /* SecCertificateTrace.c in Sources */, - E790C14C169E5D9C00E0C0C9 /* readline.c in Sources */, - 4CB23B9816A09503003A0131 /* not_on_this_platorm.c in Sources */, - 4C5BCD8A17304CE600DCEFB4 /* der_null.c in Sources */, - 52743BD616BB278C001A299D /* SecFileLocations.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E7E0D8E9158FA9A3002CA176 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 4CC0275217A1C796004067B2 /* su-41-secdb-stress.c in Sources */, - E7E0D909158FD9CD002CA176 /* su-10-cfstring-der.c in Sources */, - E7AAB5FA15929D44005C8BCC /* su-11-cfdata-der.c in Sources */, - E79D9CE3159D2DB8000834EC /* su-12-cfboolean-der.c in Sources */, - E79D9CE5159D3138000834EC /* su-13-cfnumber-der.c in Sources */, - E7934D7115A3A29D007666E0 /* su-14-cfarray-der.c in Sources */, - E765E23615A79F77006C7347 /* su-15-cfdictionary-der.c in Sources */, - 4C3963D915ACF2E700762091 /* su-16-cfdate-der.c in Sources */, - 4CF1FAC416550F6900261CF4 /* su-40-secdb.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - E742A0A714E343E70052A486 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CLANG_ENABLE_OBJC_ARC = YES; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "$(inherited)", - "DEBUG=1", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_TREAT_WARNINGS_AS_ERRORS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx"; - }; - name = Debug; - }; - E742A0A814E343E70052A486 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CLANG_ENABLE_OBJC_ARC = YES; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1"; - GCC_TREAT_WARNINGS_AS_ERRORS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - E742A0AA14E343E70052A486 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)", - "$(PROJECT_DIR)/../sec", - "$(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - E742A0AB14E343E70052A486 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)", - "$(PROJECT_DIR)/../sec", - "$(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - }; - name = Release; - }; - E7E0D8F7158FA9A3002CA176 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)", - "$(PROJECT_DIR)/../regressions", - "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - E7E0D8F8158FA9A3002CA176 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)", - "$(PROJECT_DIR)/../regressions", - "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - E742A09614E343E70052A486 /* Build configuration list for PBXProject "utilities" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - E742A0A714E343E70052A486 /* Debug */, - E742A0A814E343E70052A486 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - E742A0A914E343E70052A486 /* Build configuration list for PBXNativeTarget "utilities" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - E742A0AA14E343E70052A486 /* Debug */, - E742A0AB14E343E70052A486 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - E7E0D8F6158FA9A3002CA176 /* Build configuration list for PBXNativeTarget "utilitiesRegressions" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - E7E0D8F7158FA9A3002CA176 /* Debug */, - E7E0D8F8158FA9A3002CA176 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = E742A09314E343E70052A486 /* Project object */; -} -- 2.47.2

    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

  • $LPN#5_v;r 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